From 276f07f40959e965d973a5b6b125df782dc354e0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 10 Jul 2012 10:18:20 +0000 Subject: [PATCH 001/160] dont draw 3d viewport while rendering, mango hack --- source/blender/editors/space_view3d/view3d_draw.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 1ace4688991..fe7e6044456 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -3145,6 +3145,17 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar) const char *grid_unit = NULL; int draw_border = (rv3d->persp == RV3D_CAMOB && (scene->r.mode & R_BORDER)); + /* --- until we get a clue and make viewport threadsafe (temp mango change for stability) */ + if (G.rendering) { + ED_region_pixelspace(ar); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + UI_ThemeClearColor(TH_BACK); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + BLF_draw_default(10,10,0, "do do da da.. da da.. da da.. can't touch this! it's render time", 512); + return; + } + /* --- end temp mango change */ + /* draw viewport using opengl */ if (v3d->drawtype != OB_RENDER || !view3d_main_area_do_render_draw(C) || draw_border) { view3d_main_area_draw_objects(C, ar, &grid_unit); From 350518483dee1504eb03b07f06a00cfa3cbc5cac Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 10 Jul 2012 13:40:09 +0000 Subject: [PATCH 002/160] Code cleanup, typo fixes --- build_files/scons/tools/Blender.py | 2 +- intern/opencolorio/ocio_capi.h | 2 +- source/blender/imbuf/IMB_imbuf.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py index 3566da34570..4bc8a13be9b 100644 --- a/build_files/scons/tools/Blender.py +++ b/build_files/scons/tools/Blender.py @@ -587,7 +587,7 @@ def AppIt(target=None, source=None, env=None): commands.getoutput(cmd) cmd = 'cp -R %s/release/datafiles/fonts %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION) commands.getoutput(cmd) - if env['WITH_BF_OCIO']: + if env['WITH_BF_OCIO']: cmd = 'cp -R %s/release/datafiles/colormanagement %s/%s.app/Contents/MacOS/%s/datafiles/'%(bldroot,installdir,binary,VERSION) commands.getoutput(cmd) cmd = 'cp -R %s/release/scripts %s/%s.app/Contents/MacOS/%s/'%(bldroot,installdir,binary,VERSION) diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index 0f10593ddcc..8b19b1d0868 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -100,7 +100,7 @@ void OCIO_displayTransformSetLinearCC(DisplayTransformRcPtr *dt, ConstTransformR void OCIO_displayTransformRelease(DisplayTransformRcPtr *dt); PackedImageDesc *OCIO_createPackedImageDesc(float *data, long width, long height, long numChannels, - long chanStrideBytes, long xStrideBytes, long yStrideBytes); + long chanStrideBytes, long xStrideBytes, long yStrideBytes); void OCIO_packedImageDescRelease(PackedImageDesc *p); diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 2e02b14723e..50fa8ad1106 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -392,7 +392,7 @@ void IMB_buffer_byte_from_byte(unsigned char *rect_to, const unsigned char *rect int width, int height, int stride_to, int stride_from); void IMB_buffer_float_clamp(float *buf, int width, int height); -/* converting pixel buffers using tobecurve */ +/* converting pixel buffers using tonecurve */ typedef void (*imb_tonecurveCb) (float rgbOut[3], const float rgbIn[3]); From 26f6913516a075ebc6e2a7bc101a026006ed5b81 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 11 Jul 2012 00:08:42 +0000 Subject: [PATCH 003/160] Cycles: blended box mapping support for image texture node. This enabled by selecting Box instead of Flat as projection, and then setting the blend value. Blend 0.0 will not do any blending between box sides, higher values will give a smooth transition between the sides This is useful for mapping image texture without too obvious patterns in a way that looks seamless, without the need for UV mapping. This works basically the same as the mango node setup that was posted, just a bit faster: http://mango.blender.org/production/blended_box/ --- intern/cycles/blender/blender_shader.cpp | 2 + intern/cycles/kernel/svm/svm.h | 3 + intern/cycles/kernel/svm/svm_image.h | 126 +++++++++++++++--- intern/cycles/kernel/svm/svm_types.h | 1 + intern/cycles/render/nodes.cpp | 43 ++++-- intern/cycles/render/nodes.h | 3 + source/blender/editors/space_node/drawnode.c | 4 + source/blender/makesdna/DNA_node_types.h | 12 +- source/blender/makesrna/intern/rna_nodetree.c | 18 +++ 9 files changed, 181 insertions(+), 31 deletions(-) diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 2c15a60dab6..7b1b4d5c6ba 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -404,6 +404,8 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph if(b_image) image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current()); image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()]; + image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()]; + image->projection_blend = b_image_node.projection_blend(); get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping()); node = image; break; diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 8901e5e9628..56a40620765 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -220,6 +220,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT case NODE_TEX_IMAGE: svm_node_tex_image(kg, sd, stack, node); break; + case NODE_TEX_IMAGE_BOX: + svm_node_tex_image_box(kg, sd, stack, node); + break; case NODE_TEX_ENVIRONMENT: svm_node_tex_environment(kg, sd, stack, node); break; diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index 3b2b9204d86..8df1889d270 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -50,7 +50,7 @@ __device_inline float svm_image_texture_frac(float x, int *ix) return x - (float)i; } -__device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y) +__device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, uint srgb) { uint4 info = kernel_tex_fetch(__tex_image_packed_info, id); uint width = info.x; @@ -82,12 +82,18 @@ __device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y) r += ty*(1.0f - tx)*svm_image_texture_read(kg, offset + ix + niy*width); r += ty*tx*svm_image_texture_read(kg, offset + nix + niy*width); + if(srgb) { + r.x = color_srgb_to_scene_linear(r.x); + r.y = color_srgb_to_scene_linear(r.y); + r.z = color_srgb_to_scene_linear(r.z); + } + return r; } #else -__device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y) +__device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, uint srgb) { float4 r; @@ -206,6 +212,12 @@ __device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y) return make_float4(0.0f, 0.0f, 0.0f, 0.0f); } + if(srgb) { + r.x = color_srgb_to_scene_linear(r.x); + r.y = color_srgb_to_scene_linear(r.y); + r.z = color_srgb_to_scene_linear(r.z); + } + return r; } @@ -219,21 +231,102 @@ __device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *stack decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb); float3 co = stack_load_float3(stack, co_offset); - float4 f = svm_image_texture(kg, id, co.x, co.y); - float3 r = make_float3(f.x, f.y, f.z); - - if(srgb) { - r.x = color_srgb_to_scene_linear(r.x); - r.y = color_srgb_to_scene_linear(r.y); - r.z = color_srgb_to_scene_linear(r.z); - } + float4 f = svm_image_texture(kg, id, co.x, co.y, srgb); if(stack_valid(out_offset)) - stack_store_float3(stack, out_offset, r); + stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z)); if(stack_valid(alpha_offset)) stack_store_float(stack, alpha_offset, f.w); } +__device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) +{ + /* get object space normal */ + float3 N = sd->N; + + N = sd->N; + if(sd->object != ~0) + object_inverse_normal_transform(kg, sd, &N); + + /* project from direction vector to barycentric coordinates in triangles */ + N.x = fabsf(N.x); + N.y = fabsf(N.y); + N.z = fabsf(N.z); + + N /= (N.x + N.y + N.z); + + /* basic idea is to think of this as a triangle, each corner representing + * one of the 3 faces of the cube. in the corners we have single textures, + * in between we blend between two textures, and in the middle we a blend + * between three textures. + * + * the Nxyz values are the barycentric coordinates in an equilateral + * triangle, which in case of blending in the middle has a smaller + * equilateral triangle where 3 textures blend. this divides things into + * 7 zones, with an if() test for each zone */ + + float3 weight = make_float3(0.0f, 0.0f, 0.0f); + float blend = __int_as_float(node.w); + float limit = 0.5f*(1.0f + blend); + + /* first test for corners with single texture */ + if(N.x > limit*(N.x + N.y) && N.x > limit*(N.x + N.z)) { + weight.x = 1.0f; + } + else if(N.y > limit*(N.x + N.y) && N.y > limit*(N.y + N.z)) { + weight.y = 1.0f; + } + else if(N.z > limit*(N.x + N.z) && N.z > limit*(N.y + N.z)) { + weight.z = 1.0f; + } + else if(blend > 0.0f) { + /* in case of blending, test for mixes between two textures */ + if(N.z < (1.0f - limit)*(N.y + N.x)) { + weight.x = N.x/(N.x + N.y); + weight.x = clamp((weight.x - 0.5f*(1.0f - blend))/blend, 0.0f, 1.0f); + weight.y = 1.0f - weight.x; + } + else if(N.x < (1.0f - limit)*(N.y + N.z)) { + weight.y = N.y/(N.y + N.z); + weight.y = clamp((weight.y - 0.5f*(1.0f - blend))/blend, 0.0f, 1.0f); + weight.z = 1.0f - weight.y; + } + else if(N.y < (1.0f - limit)*(N.x + N.z)) { + weight.x = N.x/(N.x + N.z); + weight.x = clamp((weight.x - 0.5f*(1.0f - blend))/blend, 0.0f, 1.0f); + weight.z = 1.0f - weight.x; + } + else { + /* last case, we have a mix between three */ + weight.x = ((2.0f - limit)*N.x + (limit - 1.0f))/(2.0f*limit - 1.0f); + weight.y = ((2.0f - limit)*N.y + (limit - 1.0f))/(2.0f*limit - 1.0f); + weight.z = ((2.0f - limit)*N.z + (limit - 1.0f))/(2.0f*limit - 1.0f); + } + } + + /* now fetch textures */ + uint co_offset, out_offset, alpha_offset, srgb; + decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb); + + float3 co = stack_load_float3(stack, co_offset); + uint id = node.y; + + float4 f = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + + if(weight.x > 0.0f) + f += weight.x*svm_image_texture(kg, id, co.y, co.z, srgb); + if(weight.y > 0.0f) + f += weight.y*svm_image_texture(kg, id, co.x, co.z, srgb); + if(weight.z > 0.0f) + f += weight.z*svm_image_texture(kg, id, co.y, co.x, srgb); + + if(stack_valid(out_offset)) + stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z)); + if(stack_valid(alpha_offset)) + stack_store_float(stack, alpha_offset, f.w); +} + + __device void svm_node_tex_environment(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) { uint id = node.y; @@ -252,17 +345,10 @@ __device void svm_node_tex_environment(KernelGlobals *kg, ShaderData *sd, float else uv = direction_to_mirrorball(co); - float4 f = svm_image_texture(kg, id, uv.x, uv.y); - float3 r = make_float3(f.x, f.y, f.z); - - if(srgb) { - r.x = color_srgb_to_scene_linear(r.x); - r.y = color_srgb_to_scene_linear(r.y); - r.z = color_srgb_to_scene_linear(r.z); - } + float4 f = svm_image_texture(kg, id, uv.x, uv.y, srgb); if(stack_valid(out_offset)) - stack_store_float3(stack, out_offset, r); + stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z)); if(stack_valid(alpha_offset)) stack_store_float(stack, alpha_offset, f.w); } diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index c1eeeb55268..14a46079ce7 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -40,6 +40,7 @@ typedef enum NodeType { NODE_MIX_CLOSURE, NODE_JUMP, NODE_TEX_IMAGE, + NODE_TEX_IMAGE_BOX, NODE_TEX_SKY, NODE_GEOMETRY, NODE_LIGHT_PATH, diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index e4a4b874964..c1654589141 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -112,7 +112,18 @@ static ShaderEnum color_space_init() return enm; } +static ShaderEnum image_projection_init() +{ + ShaderEnum enm; + + enm.insert("Flat", 0); + enm.insert("Box", 1); + + return enm; +} + ShaderEnum ImageTextureNode::color_space_enum = color_space_init(); +ShaderEnum ImageTextureNode::projection_enum = image_projection_init(); ImageTextureNode::ImageTextureNode() : TextureNode("image_texture") @@ -122,6 +133,8 @@ ImageTextureNode::ImageTextureNode() is_float = false; filename = ""; color_space = ustring("Color"); + projection = ustring("Flat");; + projection_blend = 0.0f; add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_UV); add_output("Color", SHADER_SOCKET_COLOR); @@ -169,13 +182,25 @@ void ImageTextureNode::compile(SVMCompiler& compiler) tex_mapping.compile(compiler, vector_in->stack_offset, vector_offset); } - compiler.add_node(NODE_TEX_IMAGE, - slot, - compiler.encode_uchar4( - vector_offset, - color_out->stack_offset, - alpha_out->stack_offset, - srgb)); + if(projection == "Flat") { + compiler.add_node(NODE_TEX_IMAGE, + slot, + compiler.encode_uchar4( + vector_offset, + color_out->stack_offset, + alpha_out->stack_offset, + srgb)); + } + else { + compiler.add_node(NODE_TEX_IMAGE_BOX, + slot, + compiler.encode_uchar4( + vector_offset, + color_out->stack_offset, + alpha_out->stack_offset, + srgb), + __float_as_int(projection_blend)); + } if(vector_offset != vector_in->stack_offset) compiler.stack_clear_offset(vector_in->type, vector_offset); @@ -205,7 +230,7 @@ void ImageTextureNode::compile(OSLCompiler& compiler) /* Environment Texture */ -static ShaderEnum projection_init() +static ShaderEnum env_projection_init() { ShaderEnum enm; @@ -216,7 +241,7 @@ static ShaderEnum projection_init() } ShaderEnum EnvironmentTextureNode::color_space_enum = color_space_init(); -ShaderEnum EnvironmentTextureNode::projection_enum = projection_init(); +ShaderEnum EnvironmentTextureNode::projection_enum = env_projection_init(); EnvironmentTextureNode::EnvironmentTextureNode() : TextureNode("environment_texture") diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index efd814e4ae6..ed283492d7b 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -70,8 +70,11 @@ public: bool is_float; string filename; ustring color_space; + ustring projection; + float projection_blend; static ShaderEnum color_space_enum; + static ShaderEnum projection_enum; }; class EnvironmentTextureNode : public TextureNode { diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 0e67f18869e..7bf46a1eeef 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1340,6 +1340,10 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL); uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE); + uiItemR(layout, ptr, "projection", 0, "", ICON_NONE); + + if(RNA_enum_get(ptr, "projection") == SHD_PROJ_BOX) + uiItemR(layout, ptr, "projection_blend", 0, "blend", ICON_NONE); /* note: image user properties used directly here, unlike compositor image node, * which redefines them in the node struct RNA to get proper updates. diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 1e2f6eabce6..4842e33db80 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -589,7 +589,10 @@ typedef struct NodeTexSky { typedef struct NodeTexImage { NodeTexBase base; ImageUser iuser; - int color_space, pad; + int color_space; + int projection; + float projection_blend; + int pad; } NodeTexImage; typedef struct NodeTexChecker { @@ -599,7 +602,8 @@ typedef struct NodeTexChecker { typedef struct NodeTexEnvironment { NodeTexBase base; ImageUser iuser; - int color_space, projection; + int color_space; + int projection; } NodeTexEnvironment; typedef struct NodeTexGradient { @@ -739,6 +743,10 @@ typedef struct NodeTrackPosData { #define SHD_PROJ_EQUIRECTANGULAR 0 #define SHD_PROJ_MIRROR_BALL 1 +/* image texture */ +#define SHD_PROJ_FLAT 0 +#define SHD_PROJ_BOX 1 + /* blur node */ #define CMP_NODE_BLUR_ASPECT_NONE 0 #define CMP_NODE_BLUR_ASPECT_Y 1 diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index a72059063fd..4d8e43a9267 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -1494,6 +1494,15 @@ static void def_sh_tex_image(StructRNA *srna) {0, NULL, 0, NULL, NULL} }; + static const EnumPropertyItem prop_projection_items[] = { + {SHD_PROJ_FLAT, "FLAT", 0, "Flat", + "Image is projected flat using the X and Y coordinates of the texture vector"}, + {SHD_PROJ_BOX, "BOX", 0, "Box", + "Image is projected using different components for each side of the object space bounding box"}, + {0, NULL, 0, NULL, NULL} + }; + + PropertyRNA *prop; prop = RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE); @@ -1511,6 +1520,15 @@ static void def_sh_tex_image(StructRNA *srna) RNA_def_property_ui_text(prop, "Color Space", "Image file color space"); RNA_def_property_update(prop, 0, "rna_Node_update"); + prop = RNA_def_property(srna, "projection", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_projection_items); + RNA_def_property_ui_text(prop, "Projection", "Method to project 2D image on object with a 3D texture vector"); + RNA_def_property_update(prop, 0, "rna_Node_update"); + + prop = RNA_def_property(srna, "projection_blend", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_ui_text(prop, "Projection Blend", "For box projection, amount of blend to use between sides"); + RNA_def_property_update(prop, 0, "rna_Node_update"); + prop = RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "iuser"); From ecfa1965da1320c96fd46ad865c8c62d14911e3a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 11 Jul 2012 12:51:06 +0000 Subject: [PATCH 004/160] Use color management settings form the current window when duplicating area to new window. --- source/blender/editors/screen/screen_ops.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 6be276dea14..d7204bcdc94 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -49,6 +49,7 @@ #include "DNA_mask_types.h" #include "DNA_userdef_types.h" +#include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_global.h" @@ -829,7 +830,11 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, wmEvent *event) rect = sa->totrct; BLI_translate_rcti(&rect, win->posx, win->posy); newwin = WM_window_open(C, &rect); - + + /* copy color management settings from the current window */ + BKE_color_managed_display_settings_copy(&newwin->display_settings, &win->display_settings); + BKE_color_managed_view_settings_copy(&newwin->view_settings, &win->view_settings); + /* allocs new screen and adds to newly created window, using window size */ newsc = ED_screen_add(newwin, CTX_data_scene(C), sc->id.name + 2); newwin->screen = newsc; From ba4a5ff74f37dd010bad5cde8444f4a666149bfc Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 11 Jul 2012 19:39:43 +0000 Subject: [PATCH 005/160] Color management support for sequencer This adds color management controls to the sequencer space, which are applying on the displaying image. Currently used the same UI approach as was used for other areas, but this would probably be cleaned up in the nearest future. This required a bit of hackish stuff to be done, Namely color management for the sequencer requires one extra step in the conversion chain to convert sRGB float buffer to linear space. This was made by setting special flag in ImBuf. Later this could be done using input color space for the ImBuf probably. --- .../scripts/startup/bl_ui/space_sequencer.py | 4 ++ .../editors/space_sequencer/sequencer_draw.c | 29 +++++++-- source/blender/imbuf/IMB_imbuf_types.h | 9 +++ source/blender/imbuf/intern/colormanagement.c | 65 +++++++++++++++---- source/blender/makesdna/DNA_space_types.h | 5 ++ source/blender/makesrna/intern/rna_space.c | 5 ++ 6 files changed, 101 insertions(+), 16 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index a71a2870bee..1c39d91bc1a 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -19,6 +19,7 @@ # import bpy from bpy.types import Header, Menu, Panel +from bl_ui.properties_color_management import ColorManagedViewSettingsPanel def act_strip(context): @@ -860,5 +861,8 @@ class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel): col.prop(st, "show_separate_color") col.prop(st, "proxy_render_size") +class SEQUENCER_PT_display_properties(SequencerButtonsPanel_Output, Panel, ColorManagedViewSettingsPanel): + bl_label = "Display Properties" + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 38f29e8816e..285c51a7d62 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -52,6 +52,7 @@ #include "BKE_sound.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "BIF_gl.h" @@ -68,6 +69,9 @@ #include "UI_resources.h" #include "UI_view2d.h" +#include "WM_api.h" +#include "WM_types.h" + /* own include */ #include "sequencer_intern.h" @@ -812,6 +816,8 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq GLuint texid; GLuint last_texid; SeqRenderData context; + unsigned char *display_buffer; + void *cache_handle = NULL; render_size = sseq->render_size; if (render_size == 0) { @@ -892,12 +898,23 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq if (scope) { IMB_freeImBuf(ibuf); ibuf = scope; + + if (ibuf->rect_float && ibuf->rect == NULL) { + IMB_rect_from_float(ibuf); + } + + display_buffer = (unsigned char *)ibuf->rect; + } + else { + const ColorManagedViewSettings *view_settings; + wmWindow *win = CTX_wm_window(C); + + ibuf->colormanagement_flags |= IMB_COLORMANAGEMENT_SRGB_SOURCE; + + view_settings = IMB_view_settings_get_effective(win, &sseq->view_settings); + display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, &win->display_settings, &cache_handle); } - if (ibuf->rect_float && ibuf->rect == NULL) { - IMB_rect_from_float(ibuf); - } - /* setting up the view - actual drawing starts here */ UI_view2d_view_ortho(v2d); @@ -910,7 +927,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer); glBegin(GL_QUADS); if (frame_ofs) { @@ -1042,6 +1059,8 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq } } + if (cache_handle) + IMB_display_buffer_release(cache_handle); } #if 0 diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 4303b514ea7..45d7b8efde6 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -128,6 +128,7 @@ typedef struct ImBuf { unsigned int encodedbuffersize; /* Size of encodedbuffer */ /* color management */ + unsigned int colormanagement_flags; /* flags filed used by color management rutines */ unsigned int *display_buffer_flags; /* array of per-display display buffers dirty flags */ struct ColormanageCache *colormanage_cache; /* cache used by color management */ @@ -256,4 +257,12 @@ extern const char *imb_ext_image_qt[]; extern const char *imb_ext_movie[]; extern const char *imb_ext_audio[]; +/* imbuf->colormanagement_flags */ + +/* special flag used for color management of compositor results, + * which are in sRGB space and requires extra step in color conversions + * could be replaced with something more general in the future + */ +#define IMB_COLORMANAGEMENT_SRGB_SOURCE (1 << 0) + #endif diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 9e17347bce7..5fb7a1cfab7 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -625,6 +625,8 @@ typedef struct DisplayBufferThread { int channels; int dither; int predivide; + + int buffer_in_srgb; } DisplayBufferThread; static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned char *display_buffer, @@ -637,8 +639,16 @@ static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned c int i, tot_thread = BLI_system_thread_count(); int start_line, tot_line; - if (tot_thread > 1) + if (tot_thread > 1) { + /* XXX: IMB_buffer_byte_from_float_tonecurve isn't thread-safe because of + * possible non-initialized sRGB conversion stuff. Make sure it's properly + * initialized before starting threads, but likely this stuff should be + * initialized somewhere before to avoid possible issues in other issues. + */ + BLI_init_srgb_conversion(); + BLI_init_threads(&threads, do_thread, tot_thread); + } start_line = 0; tot_line = ((float)(ibuf->y / tot_thread)) + 0.5f; @@ -664,6 +674,7 @@ static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned c handles[i].channels = ibuf->channels; handles[i].dither = ibuf->dither; handles[i].predivide = predivide; + handles[i].buffer_in_srgb = ibuf->colormanagement_flags & IMB_COLORMANAGEMENT_SRGB_SOURCE; if (tot_thread > 1) BLI_insert_thread(&threads, &handles[i]); @@ -677,6 +688,30 @@ static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned c do_thread(&handles[0]); } +static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) +{ + float *linear_buffer = handle->buffer; + + if (handle->buffer_in_srgb) { + float *buffer = handle->buffer; + + int channels = handle->channels; + int width = handle->width; + int height = handle->tot_line; + int predivide = handle->predivide; + + int buffer_size = 4 * channels * width * height; + + linear_buffer = MEM_callocN(buffer_size * sizeof(float), "color conversion linear buffer"); + + IMB_buffer_float_from_float(linear_buffer, buffer, channels, + IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, + predivide, width, height, width, width); + } + + return linear_buffer; +} + static void *do_display_buffer_apply_tonemap_thread(void *handle_v) { DisplayBufferThread *handle = (DisplayBufferThread *) handle_v; @@ -691,24 +726,22 @@ static void *do_display_buffer_apply_tonemap_thread(void *handle_v) int dither = handle->dither; int predivide = handle->predivide; - IMB_buffer_byte_from_float_tonecurve(display_buffer, buffer, channels, dither, + float *linear_buffer = display_buffer_apply_get_linear_buffer(handle); + + IMB_buffer_byte_from_float_tonecurve(display_buffer, linear_buffer, channels, dither, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide, width, height, width, width, tonecurve_func); + if (linear_buffer != buffer) + MEM_freeN(linear_buffer); + return NULL; } static void display_buffer_apply_tonemap(ImBuf *ibuf, unsigned char *display_buffer, imb_tonecurveCb tonecurve_func) { - /* XXX: IMB_buffer_byte_from_float_tonecurve isn't thread-safe because of - * possible non-initialized sRGB conversion stuff. Make sure it's properly - * initialized before starting threads, but likely this stuff should be - * initialized somewhere before to avoid possible issues in other issues. - */ - BLI_init_srgb_conversion(); - display_buffer_apply_threaded(ibuf, ibuf->rect_float, display_buffer, tonecurve_func, do_display_buffer_apply_tonemap_thread); } @@ -726,7 +759,9 @@ static void *do_display_buffer_apply_ocio_thread(void *handle_v) int dither = handle->dither; int predivide = handle->predivide; - img = OCIO_createPackedImageDesc(buffer, width, height, channels, sizeof(float), + float *linear_buffer = display_buffer_apply_get_linear_buffer(handle); + + img = OCIO_createPackedImageDesc(linear_buffer, width, height, channels, sizeof(float), channels * sizeof(float), channels * sizeof(float) * width); OCIO_processorApply(processor, img); @@ -734,10 +769,13 @@ static void *do_display_buffer_apply_ocio_thread(void *handle_v) OCIO_packedImageDescRelease(img); /* do conversion */ - IMB_buffer_byte_from_float(display_buffer, buffer, + IMB_buffer_byte_from_float(display_buffer, linear_buffer, channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, predivide, width, height, width, width); + if (linear_buffer != buffer) + MEM_freeN(linear_buffer); + return NULL; } @@ -1103,6 +1141,11 @@ void IMB_colormanagement_check_file_config(Main *bmain) colormanage_check_view_settings(&sclip->view_settings, "clip editor", default_view); } + else if (sl->spacetype == SPACE_SEQ) { + SpaceSeq *sseq = (SpaceSeq *) sl; + + colormanage_check_view_settings(&sseq->view_settings, "sequencer editor", default_view); + } } } } diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index a4cce5dc1aa..03054924cb0 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -473,6 +473,9 @@ typedef struct SpaceSeq { int pad; struct bGPdata *gpd; /* grease-pencil data */ + + /* **** color management **** */ + ColorManagedViewSettings view_settings; } SpaceSeq; @@ -690,6 +693,7 @@ typedef struct SpaceImage { char dt_uvstretch; char around; + /* **** color management **** */ ColorManagedViewSettings view_settings; } SpaceImage; @@ -874,6 +878,7 @@ typedef struct SpaceNode { struct bGPdata *gpd; /* grease-pencil data */ + /* **** color management **** */ ColorManagedViewSettings view_settings; } SpaceNode; diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 51f4cec1540..9c7521c2f3c 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2143,6 +2143,11 @@ static void rna_def_space_sequencer(BlenderRNA *brna) RNA_def_property_struct_type(prop, "GreasePencil"); RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this space"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); + + prop = RNA_def_property(srna, "view_settings", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "view_settings"); + RNA_def_property_struct_type(prop, "ColorManagedViewSettings"); + RNA_def_property_ui_text(prop, "View Settings", "Sampled colors alongColor management settings used for displaying images on the display"); } static void rna_def_space_text(BlenderRNA *brna) From 36f6bf98d59f3954e56a12f4f7893ed44fb8c45c Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Wed, 11 Jul 2012 21:39:04 +0000 Subject: [PATCH 006/160] Node Editor / Cycles: * Typo fix for new Blend mode. --- source/blender/editors/space_node/drawnode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 27cb304ed7b..7bd974c8669 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1341,7 +1341,7 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA uiItemR(layout, ptr, "projection", 0, "", ICON_NONE); if(RNA_enum_get(ptr, "projection") == SHD_PROJ_BOX) - uiItemR(layout, ptr, "projection_blend", 0, "blend", ICON_NONE); + uiItemR(layout, ptr, "projection_blend", 0, "Blend", ICON_NONE); /* note: image user properties used directly here, unlike compositor image node, * which redefines them in the node struct RNA to get proper updates. From f79f3de4d5f1247c1462b50833205072d750315b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 15 Jul 2012 10:43:45 +0000 Subject: [PATCH 007/160] Color management: implemented ability to color manage byte buffers Color management of byte buffers is currently disabled, to enable it COLORMANAGE_BYTE_BUFFER from colormanagement.c should be defined. Currently color management supposes that byte buffer is originally in sRGB space. Ideally it'll be using the same input color space setting as float buffer which is still in a TODO list. It could be nice artistic option to play with. Also in theory it's possible that byte images would store data in non-sRGB space. There's still kind of issue with byte buffers which results in showing linear image when view transform is set to RAW. It'll be resolved as soon as real input color space is added. Other view transformations should work fine. --- .../blender/editors/space_image/image_ops.c | 13 +- source/blender/imbuf/intern/colormanagement.c | 115 ++++++++++++------ 2 files changed, 92 insertions(+), 36 deletions(-) diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index dba943589ba..42af515983a 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1186,8 +1186,17 @@ static ImBuf *save_image_colormanaged_imbuf_acquire(ImBuf *ibuf, SaveImageOption unsigned char *display_buffer = IMB_display_buffer_acquire(ibuf, &imf->view_settings, &imf->display_settings, cache_handle); - colormanaged_ibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, 0); - colormanaged_ibuf->rect = (unsigned int *) display_buffer; + if (*cache_handle) { + colormanaged_ibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, 0); + colormanaged_ibuf->rect = (unsigned int *) display_buffer; + } + else { + /* no cache handle means color management didn't run transformation + * or performed transformation to image's byte buffer which doesn't + * require allocating new image buffer + */ + colormanaged_ibuf = ibuf; + } } else { colormanaged_ibuf = ibuf; diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 5fb7a1cfab7..e2abe50efb7 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -65,11 +65,14 @@ /*********************** Global declarations *************************/ +/* define this to allow byte buffers be color managed */ +#undef COLORMANAGE_BYTE_BUFFER + /* ** list of all supported color spaces, displays and views */ #ifdef WITH_OCIO static ListBase global_colorspaces = {NULL}; -static char global_role_linear[64]; +static char global_role_scene_linear[64]; static char global_role_color_picking[64]; static char global_role_texture_painting[64]; @@ -462,7 +465,7 @@ static void colormanage_load_config(ConstConfigRcPtr *config) const char *name; /* get roles */ - colormanage_role_color_space_name_get(config, global_role_linear, sizeof(global_role_linear), + colormanage_role_color_space_name_get(config, global_role_scene_linear, sizeof(global_role_scene_linear), OCIO_ROLE_SCENE_LINEAR, "scene linear"); colormanage_role_color_space_name_get(config, global_role_color_picking, sizeof(global_role_color_picking), @@ -616,6 +619,7 @@ typedef struct DisplayBufferThread { void *processor; float *buffer; + unsigned char *byte_buffer; unsigned char *display_buffer; int width; @@ -629,7 +633,8 @@ typedef struct DisplayBufferThread { int buffer_in_srgb; } DisplayBufferThread; -static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned char *display_buffer, +static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned char *byte_buffer, + unsigned char *display_buffer, void *processor, void *(do_thread) (void *)) { DisplayBufferThread handles[BLENDER_MAX_THREADS]; @@ -656,9 +661,16 @@ static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned c for (i = 0; i < tot_thread; i++) { int offset = ibuf->channels * start_line * ibuf->x; + memset(&handles[i], 0, sizeof(handles[i])); + handles[i].processor = processor; - handles[i].buffer = buffer + offset; + if (buffer) + handles[i].buffer = buffer + offset; + + if (byte_buffer) + handles[i].byte_buffer = byte_buffer + offset; + handles[i].display_buffer = display_buffer + offset; handles[i].width = ibuf->x; @@ -690,24 +702,53 @@ static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned c static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) { - float *linear_buffer = handle->buffer; + float *linear_buffer = NULL; - if (handle->buffer_in_srgb) { + int channels = handle->channels; + int width = handle->width; + int height = handle->tot_line; + + int buffer_size = channels * width * height; + + /* TODO: do we actually need to handle alpha premultiply in some way here? */ + int predivide = handle->predivide; + + linear_buffer = MEM_callocN(buffer_size * sizeof(float), "color conversion linear buffer"); + + if (!handle->buffer) { + unsigned char *byte_buffer = handle->byte_buffer; + + /* OCIO_TODO: for now assume byte buffers are in sRGB space, + * in the future it shall use color space specified + * by user + */ + IMB_buffer_float_from_byte(linear_buffer, byte_buffer, + IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, + predivide, width, height, width, width); + } + else if (handle->buffer_in_srgb) { + /* sequencer is working with float buffers which are in sRGB space, + * so we need to ensure float buffer is in linear space before + * applying all the view transformations + */ float *buffer = handle->buffer; - int channels = handle->channels; - int width = handle->width; - int height = handle->tot_line; - int predivide = handle->predivide; - - int buffer_size = 4 * channels * width * height; - - linear_buffer = MEM_callocN(buffer_size * sizeof(float), "color conversion linear buffer"); - IMB_buffer_float_from_float(linear_buffer, buffer, channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide, width, height, width, width); } + else { + /* some processors would want to modify float original buffer + * before converting it into display byte buffer, so we need to + * make sure original's ImBuf buffers wouldn't be modified by + * using duplicated buffer here + * + * NOTE: MEM_dupallocN can't be used because buffer could be + * specified as an offset inside allocated buffer + */ + + memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float)); + } return linear_buffer; } @@ -742,7 +783,8 @@ static void *do_display_buffer_apply_tonemap_thread(void *handle_v) static void display_buffer_apply_tonemap(ImBuf *ibuf, unsigned char *display_buffer, imb_tonecurveCb tonecurve_func) { - display_buffer_apply_threaded(ibuf, ibuf->rect_float, display_buffer, tonecurve_func, + display_buffer_apply_threaded(ibuf, ibuf->rect_float, (unsigned char *)ibuf->rect, + display_buffer, tonecurve_func, do_display_buffer_apply_tonemap_thread); } @@ -804,7 +846,7 @@ static ConstProcessorRcPtr *create_display_buffer_processor(const char *view_tra dt = OCIO_createDisplayTransform(); /* OCIO_TODO: get rid of hardcoded input space */ - OCIO_displayTransformSetInputColorSpaceName(dt, global_role_linear); + OCIO_displayTransformSetInputColorSpaceName(dt, global_role_scene_linear); OCIO_displayTransformSetView(dt, view_transform); OCIO_displayTransformSetDisplay(dt, display); @@ -838,20 +880,15 @@ static void display_buffer_apply_ocio(ImBuf *ibuf, unsigned char *display_buffer const float exposure = view_settings->exposure; const char *view_transform = view_settings->view_transform; const char *display = display_settings->display_device; - float *rect_float; - - rect_float = MEM_dupallocN(ibuf->rect_float); processor = create_display_buffer_processor(view_transform, display, exposure, gamma); if (processor) { - display_buffer_apply_threaded(ibuf, rect_float, display_buffer, processor, - do_display_buffer_apply_ocio_thread); + display_buffer_apply_threaded(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect, + display_buffer, processor, do_display_buffer_apply_ocio_thread); } OCIO_processorRelease(processor); - - MEM_freeN(rect_float); } static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *display_buffer, @@ -908,6 +945,12 @@ void IMB_colormanage_cache_free(ImBuf *ibuf) } } +static void imbuf_verify_float(ImBuf *ibuf) +{ + if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID))) + IMB_rect_from_float(ibuf); +} + unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, void **cache_handle) { @@ -920,9 +963,16 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet if (!ibuf->x || !ibuf->y) return NULL; +#if !defined(COLORMANAGE_BYTE_BUFFER) + if (!ibuf->rect_float) { + imbuf_verify_float(ibuf); + + return (unsigned char *) ibuf->rect; + } +#endif + /* OCIO_TODO: support colormanaged byte buffers */ if (!strcmp(view_transform, "NONE") || - !ibuf->rect_float || global_tot_display == 0 || global_tot_view == 0) { @@ -931,8 +981,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet * it's safe to suppose standard byte buffer is used for display */ - if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID))) - IMB_rect_from_float(ibuf); + imbuf_verify_float(ibuf); return (unsigned char *) ibuf->rect; } @@ -980,8 +1029,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet (void) view_transform; (void) display_settings; - if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID))) - IMB_rect_from_float(ibuf); + imbuf_verify_float(ibuf); return (unsigned char*) ibuf->rect; #endif @@ -993,16 +1041,16 @@ void IMB_display_buffer_to_imbuf_rect(ImBuf *ibuf, const ColorManagedViewSetting #ifdef WITH_OCIO const char *view_transform = view_settings->view_transform; +#if !defined(COLORMANAGE_BYTE_BUFFER) if (!ibuf->rect_float) return; +#endif if (!strcmp(view_transform, "NONE") || - !ibuf->rect_float || global_tot_display == 0 || global_tot_view == 0) { - if (!ibuf->rect) - IMB_rect_from_float(ibuf); + imbuf_verify_float(ibuf); } else { if (!ibuf->rect) { @@ -1015,8 +1063,7 @@ void IMB_display_buffer_to_imbuf_rect(ImBuf *ibuf, const ColorManagedViewSetting (void) view_settings; (void) display_settings; - if (!ibuf->rect) - IMB_rect_from_float(ibuf); + imbuf_verify_float(ibuf); #endif } From 50a6cf10b789bc3ead849272bac104e74c0ce534 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 15 Jul 2012 10:43:50 +0000 Subject: [PATCH 008/160] Color management: color management support for saving movie files This enables color management for movie files saving when rendering animation. It uses the same settings as saving byte images. --- .../blender/render/intern/source/pipeline.c | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index a665d1a4bc2..087b3cd889c 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2078,7 +2078,7 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr G.rendering = 0; } -static void colormanage_image_for_write(ImBuf *ibuf, Scene *scene) +static void colormanage_image_for_write(Scene *scene, ImBuf *ibuf) { IMB_display_buffer_to_imbuf_rect(ibuf, &scene->r.im_format.view_settings, &scene->r.im_format.display_settings); @@ -2099,19 +2099,27 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie /* write movie or image */ if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { int do_free = FALSE; - unsigned int *rect32 = (unsigned int *)rres.rect32; + ImBuf *ibuf = render_result_rect_to_ibuf(&rres, &scene->r); + /* note; the way it gets 32 bits rects is weak... */ - if (rres.rect32 == NULL) { - rect32 = MEM_mapallocN(sizeof(int) * rres.rectx * rres.recty, "temp 32 bits rect"); - RE_ResultGet32(re, rect32); + if (ibuf->rect == NULL) { + ibuf->rect = MEM_mapallocN(sizeof(int) * rres.rectx * rres.recty, "temp 32 bits rect"); + RE_ResultGet32(re, ibuf->rect); do_free = TRUE; } - ok = mh->append_movie(&re->r, scene->r.sfra, scene->r.cfra, (int *)rect32, - rres.rectx, rres.recty, re->reports); + colormanage_image_for_write(scene, ibuf); + + ok = mh->append_movie(&re->r, scene->r.sfra, scene->r.cfra, (int *) ibuf->rect, + ibuf->x, ibuf->y, re->reports); if (do_free) { - MEM_freeN(rect32); + MEM_freeN(ibuf->rect); + ibuf->rect = NULL; } + + /* imbuf knows which rects are not part of ibuf */ + IMB_freeImBuf(ibuf); + printf("Append frame %d", scene->r.cfra); } else { @@ -2133,7 +2141,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie do_colormanagement = !BKE_imtype_supports_float(scene->r.im_format.imtype); if (do_colormanagement) - colormanage_image_for_write(ibuf, scene); + colormanage_image_for_write(scene, ibuf); ok = BKE_imbuf_write_stamp(scene, camera, ibuf, name, &scene->r.im_format); @@ -2152,7 +2160,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie BKE_add_image_extension(name, R_IMF_IMTYPE_JPEG90); ibuf->planes = 24; - colormanage_image_for_write(ibuf, scene); + colormanage_image_for_write(scene, ibuf); BKE_imbuf_write_stamp(scene, camera, ibuf, name, &imf); printf("\nSaved: %s", name); From 5a033cae758a6c1bc822547282803b5af221ca21 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 16 Jul 2012 10:50:38 +0000 Subject: [PATCH 009/160] Color management: cleanup of ocio config file - Minor style cleanup - Made scene linear space rec709 instead of aces Reference space is still aces - Get rid of hardcoded rec -. rec709 transformation on view transforms This would make view transform be applied on a reference color space how it's supposed to be. Since scene linear is rec709 such a hardcoded transform isn't needed anymore. This also fixes wrong Log view transform which used to look really weird and now it's nice and smooth. - Also made changes to SPI and Nuke configurations to make them behave properly with reference space of aces. - Renamed Nuke's rec709 space to nuke_rec709. Probably it could be replaced with scene rec709, but that's requires more investigation. --- release/datafiles/colormanagement/config.ocio | 76 +++++++++++-------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio index b17fe3d8468..f21b95cc62c 100644 --- a/release/datafiles/colormanagement/config.ocio +++ b/release/datafiles/colormanagement/config.ocio @@ -14,7 +14,7 @@ roles: default: raw matte_paint: raw reference: aces - scene_linear: aces + scene_linear: rec709 texture_paint: raw displays: @@ -28,7 +28,7 @@ displays: - ! {name: RRT, colorspace: rrt_srgb} - ! {name: SPI Film, colorspace: srgb8} - ! {name: SPI Log, colorspace: lg10} - - ! {name: Nuke rec709, colorspace: rec709} + - ! {name: Nuke rec709, colorspace: nuke_rec709} xyz: - ! {name: Raw, colorspace: raw} - ! {name: Log, colorspace: adx10} @@ -41,7 +41,7 @@ colorspaces: - ! name: aces family: aces - equalitygroup: + equalitygroup: bitdepth: 32f isdata: false allocation: lg2 @@ -50,7 +50,7 @@ colorspaces: - ! name: raw family: raw - equalitygroup: + equalitygroup: bitdepth: 32f isdata: true allocation: uniform @@ -59,11 +59,11 @@ colorspaces: - ! name: adx10 family: adx - equalitygroup: + equalitygroup: bitdepth: 10ui description: | Film Scan, using the 10-bit Academy Density Encoding - + isdata: false allocation: uniform allocationvars: [0, 1] @@ -78,11 +78,11 @@ colorspaces: - ! name: adx16 family: adx - equalitygroup: + equalitygroup: bitdepth: 16ui description: | Film Scan, using the 16-bit Academy Density Encoding - + isdata: false allocation: uniform allocationvars: [0, 1] @@ -97,11 +97,11 @@ colorspaces: - ! name: slogf35 family: sony - equalitygroup: + equalitygroup: bitdepth: 10ui description: | Sony 10-bit S-Log, with f35 color primaries - + isdata: false allocation: uniform allocationvars: [0, 1] @@ -113,11 +113,11 @@ colorspaces: - ! name: slogf65_3200 family: sony - equalitygroup: + equalitygroup: bitdepth: 10ui description: | Sony 10-bit S-Log, with f65 color primaries - + isdata: false allocation: uniform allocationvars: [0, 1] @@ -129,11 +129,11 @@ colorspaces: - ! name: slogf65_5500 family: sony - equalitygroup: + equalitygroup: bitdepth: 10ui description: | Sony 10-bit S-Log, with f65 color primaries - + isdata: false allocation: uniform allocationvars: [0, 1] @@ -145,11 +145,11 @@ colorspaces: - ! name: logc family: arri - equalitygroup: + equalitygroup: bitdepth: 10ui description: | Arri Alexa LogC, V3, Exposure Index 800 - + isdata: false allocation: uniform allocationvars: [0, 1] @@ -161,13 +161,13 @@ colorspaces: - ! name: log family: log - equalitygroup: + equalitygroup: bitdepth: 32f description: | A mathematically idealized log space, which spans the dynamic range currently being utilized by the ACES RRT. Note: this does not correspond to scanned plates, adx10 is preferred for that purpose. - + isdata: false allocation: uniform allocationvars: [0, 1] @@ -175,78 +175,84 @@ colorspaces: children: - ! {allocation: lg2, vars: [-8.5, 5]} + - ! + name: rec709 + family: "" + equalitygroup: "" + bitdepth: 32f + description: | + Rec. 709 (Full Range) Display Space + isdata: false + allocation: uniform + allocationvars: [-0.125, 1.125] + to_reference: ! {src: rec709_to_aces.spimtx, interpolation: nearest} + - ! name: rrt_srgb family: rrt - equalitygroup: + equalitygroup: bitdepth: 32f isdata: false allocation: uniform allocationvars: [0, 1] from_reference: ! children: - - ! {src: rec709_to_aces.spimtx, interpolation: nearest} - ! {allocation: lg2, vars: [-8.5, 5]} - ! {src: rrt_ut33_sRGB.spi3d, interpolation: tetrahedral} - ! name: rrt_rec709 family: rrt - equalitygroup: + equalitygroup: bitdepth: 32f isdata: false allocation: uniform allocationvars: [0, 1] from_reference: ! children: - - ! {src: rec709_to_aces.spimtx, interpolation: nearest} - ! {allocation: lg2, vars: [-8.5, 5]} - ! {src: rrt_ut33_rec709.spi3d, interpolation: tetrahedral} - ! name: rrt_p3dci family: rrt - equalitygroup: + equalitygroup: bitdepth: 32f isdata: false allocation: uniform allocationvars: [0, 1] from_reference: ! children: - - ! {src: rec709_to_aces.spimtx, interpolation: nearest} - ! {allocation: lg2, vars: [-8.5, 5]} - ! {src: rrt_ut33_p3dci.spi3d, interpolation: tetrahedral} - ! name: rrt_p3d60 family: rrt - equalitygroup: + equalitygroup: bitdepth: 32f isdata: false allocation: uniform allocationvars: [0, 1] from_reference: ! children: - - ! {src: rec709_to_aces.spimtx, interpolation: nearest} - ! {allocation: lg2, vars: [-8.5, 5]} - ! {src: rrt_ut33_p3d60.spi3d, interpolation: tetrahedral} - ! name: rrt_xyz family: rrt - equalitygroup: + equalitygroup: bitdepth: 32f isdata: false allocation: uniform allocationvars: [0, 1] from_reference: ! children: - - ! {src: rec709_to_aces.spimtx, interpolation: nearest} - ! {allocation: lg2, vars: [-8.5, 5]} - ! {src: rrt_ut33_dcdm.spi3d, interpolation: tetrahedral} # spi-vfx - - ! name: lg10 family: lg @@ -256,7 +262,10 @@ colorspaces: lg10 : conversion from film log isdata: false allocation: uniform - to_reference: ! {src: lg10.spi1d, interpolation: nearest} + to_reference: ! + children: + - ! {src: lg10.spi1d, interpolation: nearest} + - ! {src: rec709_to_aces.spimtx, interpolation: nearest} - ! name: srgb8 @@ -274,7 +283,7 @@ colorspaces: # nuke-default - ! - name: rec709 + name: nuke_rec709 family: "" equalitygroup: "" bitdepth: 32f @@ -283,4 +292,7 @@ colorspaces: isdata: false allocation: uniform allocationvars: [-0.125, 1.125] - to_reference: ! {src: rec709.spi1d, interpolation: linear} + to_reference: ! + children: + - ! {src: rec709.spi1d, interpolation: linear} + - ! {src: rec709_to_aces.spimtx, interpolation: nearest} From 0d37f82c9ba51889f156eb239cef1edba59e8003 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 16 Jul 2012 10:50:53 +0000 Subject: [PATCH 010/160] Color management: support of configurable input color space This adds a user-defined input color space name for image and movie clip data blocks. Support for this thing for other data blocks is still a TODO. Input color space is being used on loading file to convert loaded image buffer from this space to scene linear space, later this space is never used in a pipeline. Color space name was wrapped into own structure like it's done for display and view settings. This helps keep code de-duplicated in RNA and it'll help when likely more options are added into input color space settings (i.e. flag whether image could be color managed or it's a non-color data). This implied quite of internal refactoring: - Made routines around threaded display buffer calculation more general, so any kind of color transform could be performed using the same technique. - Added function to convert given float buffer from given input color space to output color space. This is a public function which could be used in such a things as compositor node. - Added function to convert ImBuf's content to scene linear space. Currently used only for images and clips. Should be added to any image/movie-related data blocks such as sequencer strips, but that a bit more long-term plan. - If input color space is set to NONE then no buffer transform would be performed on image loading. It'll behave in the same way as using scene linear as input space. --- release/scripts/startup/bl_ui/space_clip.py | 1 + source/blender/blenkernel/intern/image.c | 4 + source/blender/blenkernel/intern/movieclip.c | 6 + .../blender/editors/space_clip/clip_buttons.c | 11 + .../blender/editors/space_clip/clip_editor.c | 13 + .../editors/space_image/image_buttons.c | 13 +- source/blender/imbuf/IMB_colormanagement.h | 13 + .../imbuf/intern/IMB_colormanagement_intern.h | 4 + source/blender/imbuf/intern/colormanagement.c | 463 ++++++++++++++---- source/blender/makesdna/DNA_color_types.h | 4 + source/blender/makesdna/DNA_image_types.h | 4 + source/blender/makesdna/DNA_movieclip_types.h | 4 + source/blender/makesrna/intern/rna_color.c | 72 ++- source/blender/makesrna/intern/rna_image.c | 5 + .../blender/makesrna/intern/rna_movieclip.c | 6 + source/blender/makesrna/intern/rna_space.c | 4 +- 16 files changed, 539 insertions(+), 88 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 43707d29c2a..67a63feb9ea 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -1037,6 +1037,7 @@ class CLIP_PT_footage(CLIP_PT_clip_view_panel, Panel): col = layout.column() col.template_movieclip(sc, "clip", compact=True) + col.separator() col.prop(clip, "start_frame") col.prop(clip, "frame_offset") diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index dfb12503c45..fe364bbf439 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -47,6 +47,7 @@ #include "MEM_guardedalloc.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -2189,6 +2190,9 @@ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr) /* common stuff to do with images after loading */ static void image_initialize_after_load(Image *ima, ImBuf *ibuf) { + /* make float buffer stored in ImBuf scene linear space */ + IMB_colormanagement_imbuf_make_scene_linear(ibuf, &ima->colorspace_settings); + /* preview is NULL when it has never been used as an icon before */ if (G.background == 0 && ima->preview == NULL) BKE_icon_changed(BKE_icon_getid(&ima->id)); diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index de367b6b4d0..a38188e2307 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -74,6 +74,7 @@ #include "BKE_image.h" /* openanim */ #include "BKE_tracking.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" #include "IMB_moviecache.h" @@ -777,6 +778,11 @@ static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *u ibuf = movieclip_load_movie_file(clip, user, framenr, flag); } + if (ibuf) { + /* make float buffer stored in ImBuf scene linear space */ + IMB_colormanagement_imbuf_make_scene_linear(ibuf, &clip->colorspace_settings); + } + if (ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0) put_imbuf_cache(clip, user, ibuf, flag); } diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index e561b2a9e79..7e583078e1f 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -118,6 +118,9 @@ void uiTemplateMovieClip(uiLayout *layout, bContext *C, PointerRNA *ptr, const c uiTemplateID(layout, C, ptr, propname, NULL, "CLIP_OT_open", NULL); if (clip) { + uiLayout *col; + PointerRNA colorspace_settings_ptr; + row = uiLayoutRow(layout, FALSE); block = uiLayoutGetBlock(row); uiDefBut(block, LABEL, 0, "File Path:", 0, 19, 145, 19, NULL, 0, 0, 0, 0, ""); @@ -128,6 +131,14 @@ void uiTemplateMovieClip(uiLayout *layout, bContext *C, PointerRNA *ptr, const c uiItemR(row, &clipptr, "filepath", 0, "", ICON_NONE); uiItemO(row, "", ICON_FILE_REFRESH, "clip.reload"); + + /* OCIO_TODO: de-duplicate this with image space and other areas */ + prop = RNA_struct_find_property(&clipptr, "colorspace_settings"); + colorspace_settings_ptr = RNA_property_pointer_get(&clipptr, prop); + + col = uiLayoutColumn(layout, FALSE); + uiItemL(col, "Color Space:", ICON_NONE); + uiItemR(col, &colorspace_settings_ptr, "name", 0, "", ICON_NONE); } } diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index a441061cb41..1e547c23f57 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -540,6 +540,8 @@ typedef struct SpaceClipDrawContext { /* fields to check if cache is still valid */ int framenr, start_frame, frame_offset; short render_size, render_flag; + + char colorspace[64]; } SpaceClipDrawContext; int ED_space_clip_texture_buffer_supported(SpaceClip *sc) @@ -583,6 +585,15 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf, const unsign need_rebind |= context->start_frame != clip->start_frame; need_rebind |= context->frame_offset != clip->frame_offset; + if (!need_rebind) { + /* OCIO_TODO: not entirely nice, but currently it seems to be easiest way + * to deal with changing input color space settings + * pointer-based check could fail due to new buffers could be + * be allocated on on old memory + */ + need_rebind = strcmp(context->colorspace, clip->colorspace_settings.name) != 0; + } + if (need_rebind) { int width = ibuf->x, height = ibuf->y; int need_recreate = 0; @@ -636,6 +647,8 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf, const unsign context->render_flag = sc->user.render_flag; context->start_frame = clip->start_frame; context->frame_offset = clip->frame_offset; + + strcpy(context->colorspace, clip->colorspace_settings.name); } else { /* displaying exactly the same image which was loaded t oa texture, diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 401b57e61a0..459258c0cae 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -613,6 +613,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char uiLayout *row, *split, *col; uiBlock *block; char str[128]; + void *lock; if (!ptr->data) @@ -728,8 +729,18 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char uiItemL(layout, str, ICON_NONE); } } - + if (ima->source != IMA_SRC_GENERATED) { + PointerRNA colorspace_settings_ptr; + + /* OCIO_TODO: de-duplicate this with clip space and other areas */ + prop = RNA_struct_find_property(&imaptr, "colorspace_settings"); + colorspace_settings_ptr = RNA_property_pointer_get(&imaptr, prop); + + col = uiLayoutColumn(layout, FALSE); + uiItemL(col, "Color Space:", ICON_NONE); + uiItemR(col, &colorspace_settings_ptr, "name", 0, "", ICON_NONE); + if (compact == 0) { /* background image view doesnt need these */ uiItemS(layout); diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 2c31c2c6dcf..0a6fdd8ec47 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -33,6 +33,7 @@ #define BCM_CONFIG_FILE "config.ocio" +struct ColorManagedColorspaceSettings; struct ColorManagedDisplaySettings; struct ColorManagedViewSettings; struct EnumPropertyItem; @@ -47,6 +48,13 @@ struct wmWindow; void IMB_colormanagement_init(void); void IMB_colormanagement_exit(void); +/* ** Color space transformation functions ** */ +void IMB_colormanagement_colorspace_transform(float *buffer, int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace); + +void IMB_colormanagement_imbuf_make_scene_linear(struct ImBuf *ibuf, + struct ColorManagedColorspaceSettings *colorspace_settings); + /* ** Public display buffers interfaces ** */ void IMB_colormanage_cache_free(struct ImBuf *ibuf); @@ -74,9 +82,14 @@ const char *IMB_colormanagement_display_get_default_name(void); int IMB_colormanagement_view_get_named_index(const char *name); const char *IMB_colormanagement_view_get_indexed_name(int index); +/* ** Color space functions ** */ +int IMB_colormanagement_colorspace_get_named_index(const char *name); +const char *IMB_colormanagement_colorspace_get_indexed_name(int index); + /* ** RNA helper functions ** */ void IMB_colormanagement_display_items_add(struct EnumPropertyItem **items, int *totitem); void IMB_colormanagement_view_items_add(struct EnumPropertyItem **items, int *totitem, const char *display_name); +void IMB_colormanagement_colorspace_items_add(struct EnumPropertyItem **items, int *totitem); /* Tile-based buffer management */ struct PartialBufferUpdateContext *IMB_partial_buffer_update_context_new(struct ImBuf *ibuf); diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index 5030aca5822..68a292809de 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -64,4 +64,8 @@ struct ColorManagedView *colormanage_view_add(const char *name); struct ColorManagedView *colormanage_view_get_indexed(int index); struct ColorManagedView *colormanage_view_get_named(const char *name); +struct ColorSpace *colormanage_colorspace_add(const char *name); +struct ColorSpace *colormanage_colorspace_get_named(const char *name); +struct ColorSpace *colormanage_colorspace_get_indexed(int index); + #endif // IMB_COLORMANAGEMENT_INTERN_H diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index e2abe50efb7..6159cfce94f 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -35,6 +35,8 @@ #include #include "DNA_color_types.h" +#include "DNA_image_types.h" +#include "DNA_movieclip_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" @@ -70,17 +72,16 @@ /* ** list of all supported color spaces, displays and views */ #ifdef WITH_OCIO -static ListBase global_colorspaces = {NULL}; - static char global_role_scene_linear[64]; static char global_role_color_picking[64]; static char global_role_texture_painting[64]; - #endif +static ListBase global_colorspaces = {NULL}; static ListBase global_displays = {NULL}; static ListBase global_views = {NULL}; +static int global_tot_colorspace = 0; static int global_tot_display = 0; static int global_tot_view = 0; @@ -229,7 +230,8 @@ static struct MovieCache *colormanage_moviecache_ensure(ImBuf *ibuf) if (!ibuf->colormanage_cache->moviecache) { struct MovieCache *moviecache; - moviecache = IMB_moviecache_create("colormanage cache", sizeof(ColormanageCacheKey), colormanage_hashhash, colormanage_hashcmp); + moviecache = IMB_moviecache_create("colormanage cache", sizeof(ColormanageCacheKey), + colormanage_hashhash, colormanage_hashcmp); ibuf->colormanage_cache->moviecache = moviecache; } @@ -460,7 +462,6 @@ static void colormanage_role_color_space_name_get(ConstConfigRcPtr *config, char static void colormanage_load_config(ConstConfigRcPtr *config) { - ConstColorSpaceRcPtr *ociocs; int tot_colorspace, tot_display, tot_display_view, index, viewindex, viewindex2; const char *name; @@ -477,19 +478,9 @@ static void colormanage_load_config(ConstConfigRcPtr *config) /* load colorspaces */ tot_colorspace = OCIO_configGetNumColorSpaces(config); for (index = 0 ; index < tot_colorspace; index++) { - ColorSpace *colorspace; - name = OCIO_configGetColorSpaceNameByIndex(config, index); - ociocs = OCIO_configGetColorSpace(config, name); - colorspace = MEM_callocN(sizeof(ColorSpace), "ColorSpace"); - colorspace->index = index + 1; - - BLI_strncpy(colorspace->name, name, sizeof(colorspace->name)); - - BLI_addtail(&global_colorspaces, colorspace); - - OCIO_colorSpaceRelease(ociocs); + colormanage_colorspace_add(name); } /* load displays */ @@ -612,9 +603,53 @@ void IMB_colormanagement_exit(void) #endif } -/*********************** Public display buffers interfaces *************************/ +/*********************** Threaded display buffer transform routines *************************/ #ifdef WITH_OCIO +static void colormanage_processor_apply_threaded(int buffer_lines, int handle_size, void *init_customdata, + void (init_handle) (void *handle, int start_line, int tot_line, + void *customdata), + void *(do_thread) (void *)) +{ + void *handles; + ListBase threads; + + int i, tot_thread = BLI_system_thread_count(); + int start_line, tot_line; + + handles = MEM_callocN(handle_size * tot_thread, "processor apply threaded handles"); + + if (tot_thread > 1) + BLI_init_threads(&threads, do_thread, tot_thread); + + start_line = 0; + tot_line = ((float)(buffer_lines / tot_thread)) + 0.5f; + + for (i = 0; i < tot_thread; i++) { + int cur_tot_line; + void *handle = ((char *) handles) + handle_size * i; + + if (i < tot_thread - 1) + cur_tot_line = tot_line; + else + cur_tot_line = buffer_lines - start_line; + + init_handle(handle, start_line, cur_tot_line, init_customdata); + + if (tot_thread > 1) + BLI_insert_thread(&threads, handle); + + start_line += tot_line; + } + + if (tot_thread > 1) + BLI_end_threads(&threads); + else + do_thread(handles); + + MEM_freeN(handles); +} + typedef struct DisplayBufferThread { void *processor; @@ -633,71 +668,72 @@ typedef struct DisplayBufferThread { int buffer_in_srgb; } DisplayBufferThread; +typedef struct DisplayBufferInitData { + ImBuf *ibuf; + void *processor; + float *buffer; + unsigned char *byte_buffer; + unsigned char *display_buffer; + int width; +} DisplayBufferInitData; + +static void display_buffer_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v) +{ + DisplayBufferThread *handle = (DisplayBufferThread *) handle_v; + DisplayBufferInitData *init_data = (DisplayBufferInitData *) init_data_v; + ImBuf *ibuf = init_data->ibuf; + + int predivide = ibuf->flags & IB_cm_predivide; + int channels = ibuf->channels; + int dither = ibuf->dither; + + int offset = channels * start_line * ibuf->x; + + memset(handle, 0, sizeof(DisplayBufferThread)); + + handle->processor = init_data->processor; + + if (init_data->buffer) + handle->buffer = init_data->buffer + offset; + + if (init_data->byte_buffer) + handle->byte_buffer = init_data->byte_buffer + offset; + + handle->display_buffer = init_data->display_buffer + offset; + + handle->width = ibuf->x; + + handle->start_line = start_line; + handle->tot_line = tot_line; + + handle->channels = channels; + handle->dither = dither; + handle->predivide = predivide; + + handle->buffer_in_srgb = ibuf->colormanagement_flags & IMB_COLORMANAGEMENT_SRGB_SOURCE; +} + static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned char *byte_buffer, unsigned char *display_buffer, void *processor, void *(do_thread) (void *)) { - DisplayBufferThread handles[BLENDER_MAX_THREADS]; - ListBase threads; + DisplayBufferInitData init_data; - int predivide = ibuf->flags & IB_cm_predivide; - int i, tot_thread = BLI_system_thread_count(); - int start_line, tot_line; + /* XXX: IMB_buffer_byte_from_float_tonecurve isn't thread-safe because of + * possible non-initialized sRGB conversion stuff. Make sure it's properly + * initialized before starting threads, but likely this stuff should be + * initialized somewhere before to avoid possible issues in other issues. + */ + BLI_init_srgb_conversion(); - if (tot_thread > 1) { - /* XXX: IMB_buffer_byte_from_float_tonecurve isn't thread-safe because of - * possible non-initialized sRGB conversion stuff. Make sure it's properly - * initialized before starting threads, but likely this stuff should be - * initialized somewhere before to avoid possible issues in other issues. - */ - BLI_init_srgb_conversion(); + init_data.ibuf = ibuf; + init_data.processor = processor; + init_data.buffer = buffer; + init_data.byte_buffer = byte_buffer; + init_data.display_buffer = display_buffer; - BLI_init_threads(&threads, do_thread, tot_thread); - } - - start_line = 0; - tot_line = ((float)(ibuf->y / tot_thread)) + 0.5f; - - for (i = 0; i < tot_thread; i++) { - int offset = ibuf->channels * start_line * ibuf->x; - - memset(&handles[i], 0, sizeof(handles[i])); - - handles[i].processor = processor; - - if (buffer) - handles[i].buffer = buffer + offset; - - if (byte_buffer) - handles[i].byte_buffer = byte_buffer + offset; - - handles[i].display_buffer = display_buffer + offset; - handles[i].width = ibuf->x; - - handles[i].start_line = start_line; - - if (i < tot_thread - 1) { - handles[i].tot_line = tot_line; - } - else { - handles[i].tot_line = ibuf->y - start_line; - } - - handles[i].channels = ibuf->channels; - handles[i].dither = ibuf->dither; - handles[i].predivide = predivide; - handles[i].buffer_in_srgb = ibuf->colormanagement_flags & IMB_COLORMANAGEMENT_SRGB_SOURCE; - - if (tot_thread > 1) - BLI_insert_thread(&threads, &handles[i]); - - start_line += tot_line; - } - - if (tot_thread > 1) - BLI_end_threads(&threads); - else - do_thread(&handles[0]); + colormanage_processor_apply_threaded(ibuf->y, sizeof(DisplayBufferThread), &init_data, + display_buffer_init_handle, do_thread); } static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) @@ -845,9 +881,8 @@ static ConstProcessorRcPtr *create_display_buffer_processor(const char *view_tra dt = OCIO_createDisplayTransform(); - /* OCIO_TODO: get rid of hardcoded input space */ + /* assuming handling buffer was already converted to scene linear space */ OCIO_displayTransformSetInputColorSpaceName(dt, global_role_scene_linear); - OCIO_displayTransformSetView(dt, view_transform); OCIO_displayTransformSetDisplay(dt, display); @@ -885,7 +920,7 @@ static void display_buffer_apply_ocio(ImBuf *ibuf, unsigned char *display_buffer if (processor) { display_buffer_apply_threaded(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect, - display_buffer, processor, do_display_buffer_apply_ocio_thread); + display_buffer, processor, do_display_buffer_apply_ocio_thread); } OCIO_processorRelease(processor); @@ -910,6 +945,148 @@ static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *displ } +/*********************** Threaded color space transform routines *************************/ + +typedef struct ColorspaceTransformThread { + void *processor; + float *buffer; + int width; + int start_line; + int tot_line; + int channels; +} ColorspaceTransformThread; + +typedef struct ColorspaceTransformInit { + void *processor; + float *buffer; + int width; + int height; + int channels; +} ColorspaceTransformInitData; + +static void colorspace_transform_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v) +{ + ColorspaceTransformThread *handle = (ColorspaceTransformThread *) handle_v; + ColorspaceTransformInitData *init_data = (ColorspaceTransformInitData *) init_data_v; + + int channels = init_data->channels; + int width = init_data->width; + + int offset = channels * start_line * width; + + memset(handle, 0, sizeof(ColorspaceTransformThread)); + + handle->processor = init_data->processor; + + handle->buffer = init_data->buffer + offset; + + handle->width = width; + + handle->start_line = start_line; + handle->tot_line = tot_line; + + handle->channels = channels; +} + +static void colorspace_transform_apply_threaded(float *buffer, int width, int height, int channels, + void *processor, void *(do_thread) (void *)) +{ + ColorspaceTransformInitData init_data; + + init_data.processor = processor; + init_data.buffer = buffer; + init_data.width = width; + init_data.height = height; + init_data.channels = channels; + + colormanage_processor_apply_threaded(height, sizeof(ColorspaceTransformThread), &init_data, + colorspace_transform_init_handle, do_thread); +} + +static void *do_color_space_transform_thread(void *handle_v) +{ + ColorspaceTransformThread *handle = (ColorspaceTransformThread *) handle_v; + ConstProcessorRcPtr *processor = (ConstProcessorRcPtr *) handle->processor; + PackedImageDesc *img; + float *buffer = handle->buffer; + int channels = handle->channels; + int width = handle->width; + int height = handle->tot_line; + + img = OCIO_createPackedImageDesc(buffer, width, height, channels, sizeof(float), + channels * sizeof(float), channels * sizeof(float) * width); + + OCIO_processorApply(processor, img); + + OCIO_packedImageDescRelease(img); + + return NULL; +} + +static ConstProcessorRcPtr *create_colorspace_transform_processor(const char *from_colorspace, + const char *to_colorspace) +{ + ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + ConstProcessorRcPtr *processor; + + processor = OCIO_configGetProcessorWithNames(config, from_colorspace, to_colorspace); + + return processor; +} +#endif + +void IMB_colormanagement_colorspace_transform(float *buffer, int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace) +{ +#ifdef WITH_OCIO + ConstProcessorRcPtr *processor; + + if (!strcmp(from_colorspace, "NONE")) { + return; + } + + if (!strcmp(from_colorspace, to_colorspace)) { + /* if source and destination color spaces are identical, skip + * threading overhead and simply do nothing + */ + return; + } + + processor = create_colorspace_transform_processor(from_colorspace, to_colorspace); + + if (processor) { + colorspace_transform_apply_threaded(buffer, width, height, channels, + processor, do_color_space_transform_thread); + + OCIO_processorRelease(processor); + } +#else + (void) buffer; + (void) width; + (void) height; + (void) channels; + (void) from_colorspace; + (void) to_colorspace; +#endif +} + +void IMB_colormanagement_imbuf_make_scene_linear(ImBuf *ibuf, ColorManagedColorspaceSettings *colorspace_settings) +{ +#ifdef WITH_OCIO + if (ibuf->rect_float) { + const char *from_colorspace = colorspace_settings->name; + const char *to_colorspace = global_role_scene_linear; + + IMB_colormanagement_colorspace_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, + from_colorspace, to_colorspace); + } +#else + (void) ibuf; + (void) colorspace_settings; +#endif +} + +#ifdef WITH_OCIO static void colormanage_flags_allocate(ImBuf *ibuf) { if (global_tot_display == 0) @@ -919,6 +1096,14 @@ static void colormanage_flags_allocate(ImBuf *ibuf) } #endif +static void imbuf_verify_float(ImBuf *ibuf) +{ + if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID))) + IMB_rect_from_float(ibuf); +} + +/*********************** Public display buffers interfaces *************************/ + void IMB_colormanage_cache_free(ImBuf *ibuf) { if (ibuf->display_buffer_flags) { @@ -945,12 +1130,6 @@ void IMB_colormanage_cache_free(ImBuf *ibuf) } } -static void imbuf_verify_float(ImBuf *ibuf) -{ - if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID))) - IMB_rect_from_float(ibuf); -} - unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, void **cache_handle) { @@ -1131,6 +1310,28 @@ static void colormanage_check_view_settings(ColorManagedViewSettings *view_setti view_settings->gamma = 1.0f; } } + +static void colormanage_check_colorspace_settings(ColorManagedColorspaceSettings *colorspace_settings, const char *what) +{ + if (colorspace_settings->name[0] == '\0') { + BLI_strncpy(colorspace_settings->name, "NONE", sizeof(colorspace_settings->name)); + } + else if (!strcmp(colorspace_settings->name, "NONE")) { + /* pass */ + } + else { + ColorSpace *colorspace = colormanage_colorspace_get_named(colorspace_settings->name); + + if (!colorspace) { + printf("Blender color management: %s colorspace \"%s\" not found, setting NONE instead.\n", + what, colorspace_settings->name); + + BLI_strncpy(colorspace_settings->name, "NONE", sizeof(colorspace_settings->name)); + } + } + + (void) what; +} #endif void IMB_colormanagement_check_file_config(Main *bmain) @@ -1140,6 +1341,8 @@ void IMB_colormanagement_check_file_config(Main *bmain) wmWindow *win; bScreen *sc; Scene *scene; + Image *image; + MovieClip *clip; ColorManagedDisplay *default_display; ColorManagedView *default_view; @@ -1158,6 +1361,8 @@ void IMB_colormanagement_check_file_config(Main *bmain) return; } + /* ** check display device settings ** */ + if (wm) { for (win = wm->windows.first; win; win = win->next) { colormanage_check_display_settings(&win->display_settings, "window", default_display); @@ -1166,6 +1371,7 @@ void IMB_colormanagement_check_file_config(Main *bmain) } } + /* ** check view transform settings ** */ for (sc = bmain->screen.first; sc; sc = sc->id.next) { ScrArea *sa; @@ -1204,6 +1410,16 @@ void IMB_colormanagement_check_file_config(Main *bmain) colormanage_check_view_settings(&imf->view_settings, "scene", default_view); } + + /* ** check input color space settings ** */ + + for (image = bmain->image.first; image; image = image->id.next) { + colormanage_check_colorspace_settings(&image->colorspace_settings, "image"); + } + + for (clip = bmain->movieclip.first; clip; clip = clip->id.next) { + colormanage_check_colorspace_settings(&clip->colorspace_settings, "image"); + } #else (void) bmain; #endif @@ -1402,6 +1618,68 @@ const char *IMB_colormanagement_view_get_indexed_name(int index) return "NONE"; } +/*********************** Color space functions *************************/ + +ColorSpace *colormanage_colorspace_add(const char *name) +{ + ColorSpace *colorspace; + + colorspace = MEM_callocN(sizeof(ColorSpace), "ColorSpace"); + colorspace->index = global_tot_colorspace + 1; + + BLI_strncpy(colorspace->name, name, sizeof(colorspace->name)); + + BLI_addtail(&global_colorspaces, colorspace); + + global_tot_colorspace++; + + return colorspace; +} + +ColorSpace *colormanage_colorspace_get_named(const char *name) +{ + ColorSpace *colorspace; + + for (colorspace = global_colorspaces.first; colorspace; colorspace = colorspace->next) { + if (!strcmp(colorspace->name, name)) + return colorspace; + } + + return NULL; +} + +ColorSpace *colormanage_colorspace_get_indexed(int index) +{ + /* display indices are 1-based */ + return BLI_findlink(&global_colorspaces, index - 1); +} + +int IMB_colormanagement_colorspace_get_named_index(const char *name) +{ + ColorSpace *colorspace; + + colorspace = colormanage_colorspace_get_named(name); + + if (colorspace) { + return colorspace->index; + } + + return 0; +} + +const char *IMB_colormanagement_colorspace_get_indexed_name(int index) +{ + ColorSpace *colorspace; + + colorspace = colormanage_colorspace_get_indexed(index); + + if (colorspace) { + return colorspace->name; + } + + return "NONE"; +} + /*********************** RNA helper functions *************************/ void IMB_colormanagement_display_items_add(EnumPropertyItem **items, int *totitem) @@ -1456,6 +1734,23 @@ void IMB_colormanagement_view_items_add(EnumPropertyItem **items, int *totitem, } } +void IMB_colormanagement_colorspace_items_add(EnumPropertyItem **items, int *totitem) +{ + ColorSpace *colorspace; + + for (colorspace = global_colorspaces.first; colorspace; colorspace = colorspace->next) { + EnumPropertyItem item; + + item.value = colorspace->index; + item.name = colorspace->name; + item.identifier = colorspace->name; + item.icon = 0; + item.description = ""; + + RNA_enum_item_add(items, totitem, &item); + } +} + /*********************** Partial display buffer update *************************/ /* diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h index 0adf22a03ae..c386f912636 100644 --- a/source/blender/makesdna/DNA_color_types.h +++ b/source/blender/makesdna/DNA_color_types.h @@ -174,5 +174,9 @@ typedef struct ColorManagedDisplaySettings { char display_device[64]; } ColorManagedDisplaySettings; +typedef struct ColorManagedColorspaceSettings { + char name[64]; +} ColorManagedColorspaceSettings; + #endif diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index 4a4b21017db..a6f686d9e31 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -33,6 +33,7 @@ #define __DNA_IMAGE_TYPES_H__ #include "DNA_ID.h" +#include "DNA_color_types.h" /* for color management */ struct PackedFile; struct Scene; @@ -107,6 +108,9 @@ typedef struct Image { /* display aspect - for UV editing images resized for faster openGL display */ float aspx, aspy; + + /* color management */ + ColorManagedColorspaceSettings colorspace_settings; } Image; diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h index d8bba4a3bf5..cda51779528 100644 --- a/source/blender/makesdna/DNA_movieclip_types.h +++ b/source/blender/makesdna/DNA_movieclip_types.h @@ -37,6 +37,7 @@ #include "DNA_ID.h" #include "DNA_tracking_types.h" +#include "DNA_color_types.h" /* for color management */ struct anim; struct AnimData; @@ -94,6 +95,9 @@ typedef struct MovieClip { /* from a file. affects only a way how scene frame is mapping */ /* to a file name and not touches other data associated with */ /* a clip */ + + /* color management */ + ColorManagedColorspaceSettings colorspace_settings; } MovieClip; typedef struct MovieClipScopes { diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 32bcbd59b84..1c61053931b 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -42,17 +42,26 @@ static EnumPropertyItem view_transform_items[] = { {0, NULL, 0, NULL, NULL} }; +static EnumPropertyItem color_space_items[] = { + {0, "NONE", 0, "None", ""}, + {0, NULL, 0, NULL, NULL} +}; + #ifdef RNA_RUNTIME #include "RNA_access.h" +#include "DNA_image_types.h" #include "DNA_material_types.h" +#include "DNA_movieclip_types.h" #include "DNA_node_types.h" #include "MEM_guardedalloc.h" #include "BKE_colortools.h" #include "BKE_depsgraph.h" +#include "BKE_image.h" +#include "BKE_movieclip.h" #include "BKE_node.h" #include "BKE_texture.h" @@ -403,10 +412,59 @@ static EnumPropertyItem* rna_ColorManagedViewSettings_view_transform_itemf(bCont IMB_colormanagement_view_items_add(&items, &totitem, display_settings->display_device); RNA_enum_item_end(&items, &totitem); - *free = 1; + *free = TRUE; return items; } +static int rna_ColorManagedColorspaceSettings_colorspace_get(struct PointerRNA *ptr) +{ + ColorManagedColorspaceSettings *colorspace = (ColorManagedColorspaceSettings *) ptr->data; + + return IMB_colormanagement_colorspace_get_named_index(colorspace->name); +} + +static void rna_ColorManagedColorspaceSettings_colorspace_set(struct PointerRNA *ptr, int value) +{ + ColorManagedColorspaceSettings *colorspace = (ColorManagedColorspaceSettings *) ptr->data; + const char *name = IMB_colormanagement_colorspace_get_indexed_name(value); + + if (name) { + BLI_strncpy(colorspace->name, name, sizeof(colorspace->name)); + } +} + +static EnumPropertyItem *rna_ColorManagedColorspaceSettings_colorspace_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free) +{ + EnumPropertyItem *items = NULL; + int totitem = 0; + + RNA_enum_item_add(&items, &totitem, &color_space_items[0]); + IMB_colormanagement_colorspace_items_add(&items, &totitem); + RNA_enum_item_end(&items, &totitem); + + *free = TRUE; + + return items; +} + +static void rna_ColorManagedColorspaceSettings_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + ID *id = ptr->id.data; + + if (GS(id->name) == ID_IM) { + Image *ima = (Image *) id; + + BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); + WM_main_add_notifier(NC_IMAGE | ND_DISPLAY, &ima->id); + } + else if (GS(id->name) == ID_MC) { + MovieClip *clip = (MovieClip *) id; + + BKE_movieclip_reload(clip); + WM_main_add_notifier(NC_MOVIECLIP | ND_DISPLAY, &clip->id); + } +} + #else static void rna_def_curvemappoint(BlenderRNA *brna) @@ -798,6 +856,18 @@ static void rna_def_colormanage(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 5.0f); RNA_def_property_ui_text(prop, "Gamma", "Amount f gamma modification for displaying image buffers"); RNA_def_property_update(prop, NC_WINDOW, NULL); + + /* ** Colorspace ** */ + srna = RNA_def_struct(brna, "ColorManagedColorspaceSettings", NULL); + RNA_def_struct_ui_text(srna, "ColorManagedColorspaceSettings", "Input color space settings"); + + prop= RNA_def_property(srna, "name", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, color_space_items); + RNA_def_property_enum_funcs(prop, "rna_ColorManagedColorspaceSettings_colorspace_get", + "rna_ColorManagedColorspaceSettings_colorspace_set", + "rna_ColorManagedColorspaceSettings_colorspace_itemf"); + RNA_def_property_ui_text(prop, "Color Space", "Input color space name"); + RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedColorspaceSettings_reload_update"); } void RNA_def_color(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index 03e446c9d91..ed933181a7b 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -651,6 +651,11 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_dynamic_array_funcs(prop, "rna_Image_pixels_get_length"); RNA_def_property_float_funcs(prop, "rna_Image_pixels_get", "rna_Image_pixels_set", NULL); + prop = RNA_def_property(srna, "colorspace_settings", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "colorspace_settings"); + RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings"); + RNA_def_property_ui_text(prop, "Colorspace Settings", "Input color space settings"); + RNA_api_image(srna); } diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c index 573e27b52c2..3783bcac748 100644 --- a/source/blender/makesrna/intern/rna_movieclip.c +++ b/source/blender/makesrna/intern/rna_movieclip.c @@ -299,6 +299,12 @@ static void rna_def_movieclip(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Frame Offset", "Offset of footage first frame relative to it's file name " "(affects only how footage is loading, does not change data associated with a clip)"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_MovieClip_reload_update"); + + /* color management */ + prop = RNA_def_property(srna, "colorspace_settings", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "colorspace_settings"); + RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings"); + RNA_def_property_ui_text(prop, "Colorspace Settings", "Input color space settings"); } void RNA_def_movieclip(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index ae00ebd7cd6..f91c65b0601 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2039,7 +2039,7 @@ static void rna_def_space_image(BlenderRNA *brna) prop = RNA_def_property(srna, "view_settings", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "view_settings"); RNA_def_property_struct_type(prop, "ColorManagedViewSettings"); - RNA_def_property_ui_text(prop, "View Settings", "Sampled colors alongColor management settings used for displaying images on the display"); + RNA_def_property_ui_text(prop, "View Settings", "Color management settings used for displaying images on the display"); rna_def_space_image_uv(brna); } @@ -2156,7 +2156,7 @@ static void rna_def_space_sequencer(BlenderRNA *brna) prop = RNA_def_property(srna, "view_settings", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "view_settings"); RNA_def_property_struct_type(prop, "ColorManagedViewSettings"); - RNA_def_property_ui_text(prop, "View Settings", "Sampled colors alongColor management settings used for displaying images on the display"); + RNA_def_property_ui_text(prop, "View Settings", "Color management settings used for displaying images on the display"); } static void rna_def_space_text(BlenderRNA *brna) From 48e23021e1136ab1272c78f00ba13a633631ebfc Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 16 Jul 2012 10:51:02 +0000 Subject: [PATCH 011/160] Color management: display descriptions for color spaces This descriptions are being read from ocio configuration and exposed into UI via standard enum's tooltips. --- intern/opencolorio/ocio_capi.cpp | 5 +++ intern/opencolorio/ocio_capi.h | 2 +- release/datafiles/colormanagement/config.ocio | 2 +- .../imbuf/intern/IMB_colormanagement_intern.h | 3 +- source/blender/imbuf/intern/colormanagement.c | 44 +++++++++++++++++-- source/blender/makesrna/intern/rna_color.c | 4 +- 6 files changed, 52 insertions(+), 8 deletions(-) diff --git a/intern/opencolorio/ocio_capi.cpp b/intern/opencolorio/ocio_capi.cpp index 8a14a7e2240..0eafe12ed5b 100644 --- a/intern/opencolorio/ocio_capi.cpp +++ b/intern/opencolorio/ocio_capi.cpp @@ -305,6 +305,11 @@ const char *OCIO_colorSpaceGetName(ConstColorSpaceRcPtr *cs) return (*cs)->getName(); } +const char *OCIO_colorSpaceGetDescription(ConstColorSpaceRcPtr *cs) +{ + return (*cs)->getDescription(); +} + const char *OCIO_colorSpaceGetFamily(ConstColorSpaceRcPtr *cs) { return (*cs)->getFamily(); diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index 8b19b1d0868..99412916d2b 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -87,8 +87,8 @@ void OCIO_processorApplyRGBA(ConstProcessorRcPtr *processor, float *pixel); void OCIO_processorRelease(ConstProcessorRcPtr *p); - const char *OCIO_colorSpaceGetName(ConstColorSpaceRcPtr *cs); +const char *OCIO_colorSpaceGetDescription(ConstColorSpaceRcPtr *cs); const char *OCIO_colorSpaceGetFamily(ConstColorSpaceRcPtr *cs); DisplayTransformRcPtr *OCIO_createDisplayTransform(void); diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio index f21b95cc62c..8b73303e62a 100644 --- a/release/datafiles/colormanagement/config.ocio +++ b/release/datafiles/colormanagement/config.ocio @@ -181,7 +181,7 @@ colorspaces: equalitygroup: "" bitdepth: 32f description: | - Rec. 709 (Full Range) Display Space + Rec. 709 (Full Range), Blender native internal space isdata: false allocation: uniform allocationvars: [-0.125, 1.125] diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index 68a292809de..628a96d9030 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -39,6 +39,7 @@ typedef struct ColorSpace { struct ColorSpace *next, *prev; int index; char name[64]; + char description[64]; } ColorSpace; typedef struct ColorManagedDisplay { @@ -64,7 +65,7 @@ struct ColorManagedView *colormanage_view_add(const char *name); struct ColorManagedView *colormanage_view_get_indexed(int index); struct ColorManagedView *colormanage_view_get_named(const char *name); -struct ColorSpace *colormanage_colorspace_add(const char *name); +struct ColorSpace *colormanage_colorspace_add(const char *name, const char *description); struct ColorSpace *colormanage_colorspace_get_named(const char *name); struct ColorSpace *colormanage_colorspace_get_indexed(int index); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 6159cfce94f..ba65cd9432a 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -478,9 +478,17 @@ static void colormanage_load_config(ConstConfigRcPtr *config) /* load colorspaces */ tot_colorspace = OCIO_configGetNumColorSpaces(config); for (index = 0 ; index < tot_colorspace; index++) { + ConstColorSpaceRcPtr *ocio_colorspace; + const char *description; + name = OCIO_configGetColorSpaceNameByIndex(config, index); - colormanage_colorspace_add(name); + ocio_colorspace = OCIO_configGetColorSpace(config, name); + description = OCIO_colorSpaceGetDescription(ocio_colorspace); + + colormanage_colorspace_add(name, description); + + OCIO_colorSpaceRelease(ocio_colorspace); } /* load displays */ @@ -1620,7 +1628,27 @@ const char *IMB_colormanagement_view_get_indexed_name(int index) /*********************** Color space functions *************************/ -ColorSpace *colormanage_colorspace_add(const char *name) +static void colormanage_description_strip(char *description) +{ + int i, n; + + for (i = strlen(description) - 1; i >= 0; i--) { + if (ELEM(description[i], '\r', '\n')) { + description[i] = '\0'; + } + else { + break; + } + } + + for (i = 0, n = strlen(description); i < n; i++) { + if (ELEM(description[i], '\r', '\n')) { + description[i] = ' '; + } + } +} + +ColorSpace *colormanage_colorspace_add(const char *name, const char *description) { ColorSpace *colorspace; @@ -1629,6 +1657,12 @@ ColorSpace *colormanage_colorspace_add(const char *name) BLI_strncpy(colorspace->name, name, sizeof(colorspace->name)); + if (description) { + BLI_strncpy(colorspace->description, description, sizeof(colorspace->description)); + + colormanage_description_strip(colorspace->description); + } + BLI_addtail(&global_colorspaces, colorspace); global_tot_colorspace++; @@ -1745,7 +1779,11 @@ void IMB_colormanagement_colorspace_items_add(EnumPropertyItem **items, int *tot item.name = colorspace->name; item.identifier = colorspace->name; item.icon = 0; - item.description = ""; + + if (colorspace->description) + item.description = colorspace->description; + else + item.description = ""; RNA_enum_item_add(items, totitem, &item); } diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 1c61053931b..390c43f175b 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -38,12 +38,12 @@ #include "WM_types.h" static EnumPropertyItem view_transform_items[] = { - {0, "NONE", 0, "None", ""}, + {0, "NONE", 0, "None", "Do not perform any color transform on display, use old non-color managed technique for display"}, {0, NULL, 0, NULL, NULL} }; static EnumPropertyItem color_space_items[] = { - {0, "NONE", 0, "None", ""}, + {0, "NONE", 0, "None", "Do not perform any color transform on load, treat colors as in scene linear space already"}, {0, NULL, 0, NULL, NULL} }; From 9be5c49bbb8ae3f914e028a2bd151310e724f582 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 16 Jul 2012 10:51:14 +0000 Subject: [PATCH 012/160] Color management: resolve some of current TODOs - Some of TODO notes were laying around but they in fact were resolved a while ago, removed this notes form the code. - De-duplicate input color space settings drawing in clip and image spaces. Moved this stuff to a template which could also be used in Python. - Replace py-defined view transform settings panel with a C-defined template as well. Use it in space panels and image format settings. - Remove display settings from color management settings panels used by different spaces. Use window settings instead. --- .../bl_ui/properties_color_management.py | 45 ------------- release/scripts/startup/bl_ui/space_clip.py | 9 ++- release/scripts/startup/bl_ui/space_image.py | 9 ++- release/scripts/startup/bl_ui/space_node.py | 9 ++- .../scripts/startup/bl_ui/space_sequencer.py | 8 ++- source/blender/editors/include/UI_interface.h | 3 + .../editors/interface/interface_templates.c | 63 +++++++++++++++++++ .../blender/editors/space_clip/clip_buttons.c | 8 +-- .../editors/space_image/image_buttons.c | 18 +----- source/blender/imbuf/intern/colormanagement.c | 8 --- source/blender/makesrna/RNA_access.h | 3 + source/blender/makesrna/intern/rna_ui_api.c | 11 ++++ .../bad_level_call_stubs/stubs.c | 2 + 13 files changed, 112 insertions(+), 84 deletions(-) delete mode 100644 release/scripts/startup/bl_ui/properties_color_management.py diff --git a/release/scripts/startup/bl_ui/properties_color_management.py b/release/scripts/startup/bl_ui/properties_color_management.py deleted file mode 100644 index eee8fddbef5..00000000000 --- a/release/scripts/startup/bl_ui/properties_color_management.py +++ /dev/null @@ -1,45 +0,0 @@ -# ##### 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. -# -# ##### END GPL LICENSE BLOCK ##### - -# - -class ColorManagedViewSettingsPanel: - - def draw(self, context): - layout = self.layout - - space = context.space_data - window = context.window - display_settings = context.window.display_settings - space_view_settings = space.view_settings - - if space_view_settings.use_global_settings: - view_settings = window.view_settings - else: - view_settings = space.view_settings - - col = layout.column() - col.prop(space_view_settings, "use_global_settings") - col.prop(display_settings, "display_device", text="Display") - col.prop(view_settings, "view_transform", text="View") - - col = layout.column() - col.active = view_settings.view_transform not in {'ACES ODT Tonecurve', 'NONE'} - col.prop(view_settings, "exposure") - col.prop(view_settings, "gamma") - diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 67a63feb9ea..a14fbcc316e 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -20,7 +20,6 @@ import bpy from bpy.types import Panel, Header, Menu -from bl_ui.properties_color_management import ColorManagedViewSettingsPanel class CLIP_HT_header(Header): @@ -1016,12 +1015,18 @@ class CLIP_PT_proxy(CLIP_PT_clip_view_panel, Panel): col.prop(sc.clip_user, "use_render_undistorted") -class CLIP_PT_display_properties(Panel, ColorManagedViewSettingsPanel): +class CLIP_PT_display_properties(Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' bl_label = "Display Properties" bl_options = {'DEFAULT_CLOSED'} + def draw(self, context): + layout = self.layout + space = context.space_data + + layout.template_colormanaged_view_settings(space, "view_settings", True) + class CLIP_PT_footage(CLIP_PT_clip_view_panel, Panel): bl_space_type = 'CLIP_EDITOR' diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 967027e14fa..92447ba9b05 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -20,7 +20,6 @@ import bpy from bpy.types import Header, Menu, Panel from bl_ui.properties_paint_common import UnifiedPaintPanel -from bl_ui.properties_color_management import ColorManagedViewSettingsPanel class ImagePaintPanel(UnifiedPaintPanel): @@ -428,11 +427,17 @@ class IMAGE_HT_header(Header): layout.prop(sima, "use_realtime_update", text="", icon_only=True, icon='LOCKED') -class IMAGE_PT_display_properties(Panel, ColorManagedViewSettingsPanel): +class IMAGE_PT_display_properties(Panel): bl_space_type = 'IMAGE_EDITOR' bl_region_type = 'UI' bl_label = "Display Properties" + def draw(self, context): + layout = self.layout + space = context.space_data + + layout.template_colormanaged_view_settings(space, "view_settings", True) + class IMAGE_PT_image_properties(Panel): bl_space_type = 'IMAGE_EDITOR' diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index a2f5610ff84..daee7a89e6f 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -19,7 +19,6 @@ # import bpy from bpy.types import Header, Menu, Panel -from bl_ui.properties_color_management import ColorManagedViewSettingsPanel class NODE_HT_header(Header): @@ -185,11 +184,17 @@ class NODE_MT_node(Menu): layout.operator("node.read_fullsamplelayers") -class NODE_PT_display_properties(Panel, ColorManagedViewSettingsPanel): +class NODE_PT_display_properties(Panel): bl_space_type = 'NODE_EDITOR' bl_region_type = 'UI' bl_label = "Display Properties" + def draw(self, context): + layout = self.layout + space = context.space_data + + layout.template_colormanaged_view_settings(space, "view_settings", True) + # Node Backdrop options class NODE_PT_properties(Panel): diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 1c39d91bc1a..81fc8fe974d 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -19,7 +19,6 @@ # import bpy from bpy.types import Header, Menu, Panel -from bl_ui.properties_color_management import ColorManagedViewSettingsPanel def act_strip(context): @@ -861,8 +860,11 @@ class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel): col.prop(st, "show_separate_color") col.prop(st, "proxy_render_size") -class SEQUENCER_PT_display_properties(SequencerButtonsPanel_Output, Panel, ColorManagedViewSettingsPanel): - bl_label = "Display Properties" + col = layout.column() + col.separator() + col.label(text="Color Management:") + col.template_colormanaged_view_settings(st, "view_settings", True) + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 9715fb93c27..7aac2ebb46d 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -822,6 +822,9 @@ void uiTemplateMovieClip(struct uiLayout *layout, struct bContext *C, struct Poi void uiTemplateTrack(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateMarker(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, PointerRNA *userptr, PointerRNA *trackptr, int cmpact); +void uiTemplateColorspaceSettings(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname); +void uiTemplateColormanagedViewSettings(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, int show_global_settings); + /* items */ void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname); void uiItemEnumO_ptr(uiLayout *layout, struct wmOperatorType *ot, const char *name, int icon, const char *propname, int value); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 49e3818fe08..ad07aa51af6 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2768,3 +2768,66 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr) } } +/********************************* Color management *************************************/ + +void uiTemplateColorspaceSettings(uiLayout *layout, PointerRNA *ptr, const char *propname) +{ + PropertyRNA *prop; + PointerRNA colorspace_settings_ptr; + + prop = RNA_struct_find_property(ptr, propname); + + if (!prop) { + printf("%s: property not found: %s.%s\n", + __func__, RNA_struct_identifier(ptr->type), propname); + return; + } + + colorspace_settings_ptr = RNA_property_pointer_get(ptr, prop); + + uiItemL(layout, "Color Space:", ICON_NONE); + uiItemR(layout, &colorspace_settings_ptr, "name", 0, "", ICON_NONE); +} + +void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, int show_global_settings) +{ + PropertyRNA *prop; + PointerRNA view_transform_ptr; + uiLayout *col; + ColorManagedViewSettings *view_settings; + + prop = RNA_struct_find_property(ptr, propname); + + if (!prop) { + printf("%s: property not found: %s.%s\n", + __func__, RNA_struct_identifier(ptr->type), propname); + return; + } + + view_transform_ptr = RNA_property_pointer_get(ptr, prop); + view_settings = view_transform_ptr.data; + + col = uiLayoutColumn(layout, FALSE); + + if (show_global_settings) { + wmWindow *win = CTX_wm_window(C); + bScreen *screen = CTX_wm_screen(C); + + uiItemR(col, &view_transform_ptr, "use_global_settings", 0, NULL, ICON_NONE); + + if (view_settings->flag & COLORMANAGE_VIEW_USE_GLOBAL) { + PointerRNA window_ptr; + + RNA_pointer_create(&screen->id, &RNA_Window, win, &window_ptr); + + prop = RNA_struct_find_property(&window_ptr, "view_settings"); + view_transform_ptr = RNA_property_pointer_get(&window_ptr, prop); + } + } + + uiItemR(col, &view_transform_ptr, "view_transform", 0, "View", ICON_NONE); + + col = uiLayoutColumn(layout, FALSE); + uiItemR(col, &view_transform_ptr, "exposure", 0, NULL, ICON_NONE); + uiItemR(col, &view_transform_ptr, "gamma", 0, NULL, ICON_NONE); +} diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index 7e583078e1f..5bf6bcc047f 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -119,7 +119,6 @@ void uiTemplateMovieClip(uiLayout *layout, bContext *C, PointerRNA *ptr, const c if (clip) { uiLayout *col; - PointerRNA colorspace_settings_ptr; row = uiLayoutRow(layout, FALSE); block = uiLayoutGetBlock(row); @@ -132,13 +131,8 @@ void uiTemplateMovieClip(uiLayout *layout, bContext *C, PointerRNA *ptr, const c uiItemR(row, &clipptr, "filepath", 0, "", ICON_NONE); uiItemO(row, "", ICON_FILE_REFRESH, "clip.reload"); - /* OCIO_TODO: de-duplicate this with image space and other areas */ - prop = RNA_struct_find_property(&clipptr, "colorspace_settings"); - colorspace_settings_ptr = RNA_property_pointer_get(&clipptr, prop); - col = uiLayoutColumn(layout, FALSE); - uiItemL(col, "Color Space:", ICON_NONE); - uiItemR(col, &colorspace_settings_ptr, "name", 0, "", ICON_NONE); + uiTemplateColorspaceSettings(col, &clipptr, "colorspace_settings"); } } diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 459258c0cae..18a571c1bc6 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -731,15 +731,8 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char } if (ima->source != IMA_SRC_GENERATED) { - PointerRNA colorspace_settings_ptr; - - /* OCIO_TODO: de-duplicate this with clip space and other areas */ - prop = RNA_struct_find_property(&imaptr, "colorspace_settings"); - colorspace_settings_ptr = RNA_property_pointer_get(&imaptr, prop); - col = uiLayoutColumn(layout, FALSE); - uiItemL(col, "Color Space:", ICON_NONE); - uiItemR(col, &colorspace_settings_ptr, "name", 0, "", ICON_NONE); + uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings"); if (compact == 0) { /* background image view doesnt need these */ uiItemS(layout); @@ -809,7 +802,7 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr) { ImageFormatData *imf = imfptr->data; ID *id = imfptr->id.data; - PointerRNA display_settings_ptr, view_settings_ptr; + PointerRNA display_settings_ptr; PropertyRNA *prop; const int depth_ok = BKE_imtype_valid_depths(imf->imtype); /* some settings depend on this being a scene thats rendered */ @@ -887,17 +880,12 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr) prop = RNA_struct_find_property(imfptr, "display_settings"); display_settings_ptr = RNA_property_pointer_get(imfptr, prop); - prop = RNA_struct_find_property(imfptr, "view_settings"); - view_settings_ptr = RNA_property_pointer_get(imfptr, prop); - col = uiLayoutColumn(layout, FALSE); uiItemL(col, IFACE_("Color Management"), ICON_NONE); uiItemR(col, &display_settings_ptr, "display_device", 0, NULL, ICON_NONE); - uiItemR(col, &view_settings_ptr, "view_transform", 0, NULL, ICON_NONE); - uiItemR(col, &view_settings_ptr, "exposure", 0, NULL, ICON_NONE); - uiItemR(col, &view_settings_ptr, "gamma", 0, NULL, ICON_NONE); + uiTemplateColormanagedViewSettings(col, NULL, imfptr, "view_settings", FALSE); } } diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index ba65cd9432a..d800db76a44 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1158,7 +1158,6 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet } #endif - /* OCIO_TODO: support colormanaged byte buffers */ if (!strcmp(view_transform, "NONE") || global_tot_display == 0 || global_tot_view == 0) @@ -1191,13 +1190,6 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet return display_buffer; } - /* OCIO_TODO: in case when image is being resized it is possible - * to save buffer allocation here - * - * actually not because there might be other users of - * that buffer which better not to change - */ - buffer_size = ibuf->channels * ibuf->x * ibuf->y * sizeof(float); display_buffer = MEM_callocN(buffer_size, "imbuf display buffer"); diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 31612f556e4..74adb25d994 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -104,6 +104,9 @@ extern StructRNA RNA_CollectionProperty; extern StructRNA RNA_CollisionModifier; extern StructRNA RNA_CollisionSensor; extern StructRNA RNA_CollisionSettings; +extern StructRNA RNA_ColorManagedColorspaceSettings; +extern StructRNA RNA_ColorManagedDisplaySettings; +extern StructRNA RNA_ColorManagedViewSettings; extern StructRNA RNA_ColorRamp; extern StructRNA RNA_ColorRampElement; extern StructRNA RNA_ColorSequence; diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 96ddcce6004..0375b1811c5 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -496,6 +496,17 @@ void RNA_api_ui_layout(StructRNA *srna) func = RNA_def_function(srna, "introspect", "uiLayoutIntrospect"); parm = RNA_def_string(func, "string", "", 1024 * 1024, "Descr", "DESCR"); RNA_def_function_return(func, parm); + + /* color management templates */ + func = RNA_def_function(srna, "template_colorspace_settings", "uiTemplateColorspaceSettings"); + RNA_def_function_ui_description(func, "Item. A widget to control input color space settings."); + api_ui_item_rna_common(func); + + func = RNA_def_function(srna, "template_colormanaged_view_settings", "uiTemplateColormanagedViewSettings"); + RNA_def_function_ui_description(func, "Item. A widget to control color managed view settings settings."); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + api_ui_item_rna_common(func); + RNA_def_boolean(func, "show_global_settings", 0, "", "Show widgets to control global color management settings"); } #endif diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 53f3dacbffa..964fea8fb1e 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -421,6 +421,8 @@ void uiTemplateMovieClip(struct uiLayout *layout, struct bContext *C, struct Poi void uiTemplateTrack(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname) {} void uiTemplateMarker(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, PointerRNA *userptr, PointerRNA *trackptr, int compact) {} void uiTemplateImageSettings(struct uiLayout *layout, struct PointerRNA *imfptr) {} +void uiTemplateColorspaceSettings(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname) {} +void uiTemplateColormanagedViewSettings(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, int show_global_settings) {} /* rna render */ struct RenderResult *RE_engine_begin_result(struct RenderEngine *engine, int x, int y, int w, int h) {return (struct RenderResult *) NULL;} From 8f85e93ea69a313fa77ad551a7a4c39797f1c0e1 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 17 Jul 2012 11:10:40 +0000 Subject: [PATCH 013/160] Color management: fix missed color management settings for new created scenes - Initialize color management settings if creating new scene - Copy settings from active scene if creating with copying settings or if using other copy/link object settings This also should fix issue with Export UV Layout operator --- source/blender/blenkernel/intern/scene.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index d9afd1eefb4..960713fd5d1 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -57,6 +57,7 @@ #include "BKE_anim.h" #include "BKE_animsys.h" +#include "BKE_colortools.h" #include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_group.h" @@ -132,6 +133,8 @@ Scene *BKE_scene_copy(Scene *sce, int type) MEM_freeN(scen->toolsettings); } else { + ImageFormatData *im_format, *im_formatn; + scen = BKE_libblock_copy(&sce->id); BLI_duplicatelist(&(scen->base), &(sce->base)); @@ -166,6 +169,13 @@ Scene *BKE_scene_copy(Scene *sce, int type) obase = obase->next; base = base->next; } + + /* copy color management settings */ + im_format = &sce->r.im_format; + im_formatn = &scen->r.im_format; + + BKE_color_managed_display_settings_copy(&im_formatn->display_settings, &im_format->display_settings); + BKE_color_managed_view_settings_copy(&im_formatn->view_settings, &im_format->view_settings); } /* tool settings */ @@ -545,6 +555,9 @@ Scene *BKE_scene_add(const char *name) sound_create_scene(sce); + BKE_color_managed_display_settings_init(&sce->r.im_format.display_settings); + BKE_color_managed_view_settings_init(&sce->r.im_format.view_settings); + return sce; } From 8568ce6fc8b907ad9fa664703f808064c7b0c264 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 20 Jul 2012 10:35:46 +0000 Subject: [PATCH 014/160] Mask rasteriyer: fixed wrong bounding box calculation for non-cyclic splines --- source/blender/blenkernel/intern/mask.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 8facc2c1672..a8c95a4fc71 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -556,6 +556,8 @@ static void spline_feather_collapse_inner_loops(MaskSpline *spline, float (*feat int next = i + 1; float delta; + DO_MINMAX2(feather_points[i], min, max); + if (next == tot_feather_point) { if (spline->flag & MASK_SPLINE_CYCLIC) next = 0; @@ -570,8 +572,6 @@ static void spline_feather_collapse_inner_loops(MaskSpline *spline, float (*feat delta = fabsf(feather_points[i][1] - feather_points[next][1]); if (delta > max_delta_y) max_delta_y = delta; - - DO_MINMAX2(feather_points[i], min, max); } /* use dynamically calculated buckets per side, so we likely wouldn't From 7271f8e38f2ae89be0a0e68af6d724aae0424788 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 20 Jul 2012 14:16:25 +0000 Subject: [PATCH 015/160] Color management: threading fixes and partial buffer update refactor There used to be an issue in colormanage_cache_get which lead to wrong reference number counter in cases when exposure / gamma does not match values stored in cache. In this case cache handle should be set to NULL, no callee function could always call buffer release function (as it was intended to). Made display buffer acquire / release functions thread safe. This applies to "external" API only, internal helpers are non-thread safe for performance issues, so if one uses them he need to be careful. Converted partial display buffer update into a single function which still updates all display buffer ever created for given image buffer. This means that it's not needed to create any kind of context first and if there're display buffers created in-between of partial updates they would also be updated with next calls of partial updates. This allowed to make render result nicely color managed during rendering, meaning that render progress is visualisable with color management for image editor set up. --- source/blender/blenlib/BLI_threads.h | 1 + source/blender/blenlib/intern/threads.c | 5 + .../operations/COM_ViewerBaseOperation.cpp | 28 +- .../operations/COM_ViewerBaseOperation.h | 2 +- .../blender/editors/render/render_internal.c | 4 + source/blender/imbuf/IMB_colormanagement.h | 6 +- source/blender/imbuf/intern/colormanagement.c | 294 +++++++----------- 7 files changed, 141 insertions(+), 199 deletions(-) diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index 902373bcd6b..9cd801f819d 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -77,6 +77,7 @@ int BLI_system_thread_count(void); /* gets the number of threads the system #define LOCK_OPENGL 5 #define LOCK_NODES 6 #define LOCK_MOVIECLIP 7 +#define LOCK_COLORMANAGE 8 void BLI_lock_thread(int type); void BLI_unlock_thread(int type); diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index 9994f89acd5..66527b9b92a 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -113,6 +113,7 @@ static pthread_mutex_t _rcache_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _opengl_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _nodes_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _movieclip_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t _colormanage_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_t mainid; static int thread_levels = 0; /* threads can be invoked inside threads */ @@ -351,6 +352,8 @@ void BLI_lock_thread(int type) pthread_mutex_lock(&_nodes_lock); else if (type == LOCK_MOVIECLIP) pthread_mutex_lock(&_movieclip_lock); + else if (type == LOCK_COLORMANAGE) + pthread_mutex_lock(&_colormanage_lock); } void BLI_unlock_thread(int type) @@ -371,6 +374,8 @@ void BLI_unlock_thread(int type) pthread_mutex_unlock(&_nodes_lock); else if (type == LOCK_MOVIECLIP) pthread_mutex_unlock(&_movieclip_lock); + else if (type == LOCK_COLORMANAGE) + pthread_mutex_unlock(&_colormanage_lock); } /* Mutex Locks */ diff --git a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp index 5b2b6370953..5434d06eb22 100644 --- a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp @@ -47,13 +47,10 @@ ViewerBaseOperation::ViewerBaseOperation() : NodeOperation() this->m_outputBufferDisplay = NULL; this->m_active = false; this->m_doColorManagement = true; - this->m_partialBufferUpdate = NULL; } void ViewerBaseOperation::initExecution() { - this->m_partialBufferUpdate = NULL; - if (isActiveViewerOutput()) { initImage(); } @@ -77,36 +74,35 @@ void ViewerBaseOperation::initImage() imb_addrectfloatImBuf(ibuf); anImage->ok = IMA_OK_LOADED; + IMB_display_buffer_invalidate(ibuf); + BLI_unlock_thread(LOCK_DRAW_IMAGE); } - this->m_partialBufferUpdate = IMB_partial_buffer_update_context_new(ibuf); - /* now we combine the input with ibuf */ this->m_outputBuffer = ibuf->rect_float; this->m_outputBufferDisplay = (unsigned char *)ibuf->rect; + /* needed for display buffer update + * + * no need to lock / reference the image buffer because it's seems + * to be the single place which changes buffers of viewer image + * which is this node + */ + this->m_ibuf = ibuf; + BKE_image_release_ibuf(this->m_image, this->m_lock); } void ViewerBaseOperation:: updateImage(rcti *rect) { - IMB_partial_buffer_update_rect(this->m_partialBufferUpdate, this->m_outputBuffer, rect); + IMB_partial_display_buffer_update(this->m_ibuf, this->m_outputBuffer, getWidth(), 0, 0, + rect->xmin, rect->ymin, rect->xmax, rect->ymax); WM_main_add_notifier(NC_WINDOW | ND_DRAW, NULL); } void ViewerBaseOperation::deinitExecution() { - if (this->m_partialBufferUpdate) { - /* partial buffer context could be NULL if it's not active viewer node */ - - ImBuf *ibuf = BKE_image_acquire_ibuf(this->m_image, this->m_imageUser, &this->m_lock); - - IMB_partial_buffer_update_free(this->m_partialBufferUpdate, ibuf); - - BKE_image_release_ibuf(this->m_image, this->m_lock); - } - this->m_outputBuffer = NULL; } diff --git a/source/blender/compositor/operations/COM_ViewerBaseOperation.h b/source/blender/compositor/operations/COM_ViewerBaseOperation.h index 4052c49ebbc..e21bd8c3566 100644 --- a/source/blender/compositor/operations/COM_ViewerBaseOperation.h +++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.h @@ -39,8 +39,8 @@ protected: OrderOfChunks m_chunkOrder; bool m_doColorManagement; bool m_doColorPredivide; + ImBuf *m_ibuf; - struct PartialBufferUpdateContext *m_partialBufferUpdate; public: bool isOutputOperation(bool rendering) const { return isActiveViewerOutput(); } void initExecution(); diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 8fa3c6f992f..3d867bd85a5 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -61,6 +61,7 @@ #include "ED_object.h" #include "RE_pipeline.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -150,6 +151,9 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat IMB_buffer_byte_from_float(rectc, rectf, 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide, xmax, ymax, ibuf->x, rr->rectx); + + IMB_partial_display_buffer_update(ibuf, rectf, rr->rectx, rxmin, rymin, + rxmin, rymin, rxmin + xmax - 1, rymin + ymax - 1); } /* ****************************** render invoking ***************** */ diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 0a6fdd8ec47..08c9fd7d19a 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -92,8 +92,8 @@ void IMB_colormanagement_view_items_add(struct EnumPropertyItem **items, int *to void IMB_colormanagement_colorspace_items_add(struct EnumPropertyItem **items, int *totitem); /* Tile-based buffer management */ -struct PartialBufferUpdateContext *IMB_partial_buffer_update_context_new(struct ImBuf *ibuf); -void IMB_partial_buffer_update_rect(struct PartialBufferUpdateContext *context, const float *linear_buffer, struct rcti *rect); -void IMB_partial_buffer_update_free(struct PartialBufferUpdateContext *context, struct ImBuf *ibuf); +void IMB_partial_display_buffer_update(struct ImBuf *ibuf, const float *linear_buffer, + int stride, int offset_x, int offset_y, + int xmin, int ymin, int xmax, int ymax); #endif // IMB_COLORMANAGEMENT_H diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index d800db76a44..091bde6ec70 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -70,6 +70,8 @@ /* define this to allow byte buffers be color managed */ #undef COLORMANAGE_BYTE_BUFFER +#define ACES_ODT_TONECORVE "ACES ODT Tonecurve" + /* ** list of all supported color spaces, displays and views */ #ifdef WITH_OCIO static char global_role_scene_linear[64]; @@ -224,7 +226,7 @@ static int colormanage_hashcmp(const void *av, const void *bv) static struct MovieCache *colormanage_moviecache_ensure(ImBuf *ibuf) { if (!ibuf->colormanage_cache) { - ibuf->colormanage_cache = MEM_callocN(sizeof(ColormanageCache), "imbuf colormanage ca cache"); + ibuf->colormanage_cache = MEM_callocN(sizeof(ColormanageCache), "imbuf colormanage cache"); } if (!ibuf->colormanage_cache->moviecache) { @@ -242,7 +244,7 @@ static struct MovieCache *colormanage_moviecache_ensure(ImBuf *ibuf) static void colormanage_cachedata_set(ImBuf *ibuf, ColormnaageCacheData *data) { if (!ibuf->colormanage_cache) { - ibuf->colormanage_cache = MEM_callocN(sizeof(ColormanageCache), "imbuf colormanage ca cache"); + ibuf->colormanage_cache = MEM_callocN(sizeof(ColormanageCache), "imbuf colormanage cache"); } ibuf->colormanage_cache->data = data; @@ -324,8 +326,10 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV cache_data = colormanage_cachedata_get(cache_ibuf); if (cache_data->exposure != view_settings->exposure || - cache_data->gamma != view_settings->gamma) + cache_data->gamma != view_settings->gamma) { + *cache_handle = NULL; + IMB_freeImBuf(cache_ibuf); return NULL; @@ -371,20 +375,12 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting IMB_moviecache_put(moviecache, &key, cache_ibuf); } -/* validation function checks whether there's buffer with given display transform - * in the cache and if so, check whether it matches resolution of source buffer. - * if resolution is different new buffer would be put into the cache and it'll - * be returned as a result - * - * this function does not check exposure / gamma because currently it's only - * used by partial buffer update functions which uses the same exposure / gamma - * settings as cached buffer had - */ -static unsigned char *colormanage_cache_get_validated(ImBuf *ibuf, const ColormanageCacheViewSettings *view_settings, - const ColormanageCacheDisplaySettings *display_settings, - void **cache_handle) +static unsigned char *colormanage_cache_get_cache_data(ImBuf *ibuf, const ColormanageCacheViewSettings *view_settings, + const ColormanageCacheDisplaySettings *display_settings, + void **cache_handle, float *exposure, float *gamma) { ColormanageCacheKey key; + ColormnaageCacheData *cache_data; ImBuf *cache_ibuf; colormanage_settings_to_key(&key, view_settings, display_settings); @@ -392,44 +388,16 @@ static unsigned char *colormanage_cache_get_validated(ImBuf *ibuf, const Colorma cache_ibuf = colormanage_cache_get_ibuf(ibuf, &key, cache_handle); if (cache_ibuf) { - if (cache_ibuf->x != ibuf->x || cache_ibuf->y != ibuf->y) { - ColormanageCacheViewSettings new_view_settings = *view_settings; - ColormnaageCacheData *cache_data; - unsigned char *display_buffer; - int buffer_size; + cache_data = colormanage_cachedata_get(cache_ibuf); - /* use the same settings as original cached buffer */ - cache_data = colormanage_cachedata_get(cache_ibuf); - new_view_settings.exposure = cache_data->exposure; - new_view_settings.gamma = cache_data->gamma; - - buffer_size = ibuf->channels * ibuf->x * ibuf->y * sizeof(float); - display_buffer = MEM_callocN(buffer_size, "imbuf validated display buffer"); - - colormanage_cache_put(ibuf, &new_view_settings, display_settings, display_buffer, cache_handle); - - IMB_freeImBuf(cache_ibuf); - - return display_buffer; - } + *exposure = cache_data->exposure; + *gamma = cache_data->gamma; return (unsigned char *) cache_ibuf->rect; } return NULL; } - -/* return view settings which are stored in cached buffer, not in key itself */ -static void colormanage_cache_get_cache_data(void *cache_handle, float *exposure, float *gamma) -{ - ImBuf *cache_ibuf = (ImBuf *) cache_handle; - ColormnaageCacheData *cache_data; - - cache_data = colormanage_cachedata_get(cache_ibuf); - - *exposure = cache_data->exposure; - *gamma = cache_data->gamma; -} #endif static void colormanage_cache_handle_release(void *cache_handle) @@ -600,7 +568,7 @@ void IMB_colormanagement_init(void) OCIO_configRelease(config); /* special views, which does not depend on OCIO */ - colormanage_view_add("ACES ODT Tonecurve"); + colormanage_view_add(ACES_ODT_TONECORVE); #endif } @@ -940,7 +908,7 @@ static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *displ { const char *view_transform = view_settings->view_transform; - if (!strcmp(view_transform, "ACES ODT Tonecurve")) { + if (!strcmp(view_transform, ACES_ODT_TONECORVE)) { /* special case for Mango team, this does not actually apply * any input space -> display space conversion and just applies * a tonecurve for better linear float -> sRGB byte conversion @@ -1106,8 +1074,18 @@ static void colormanage_flags_allocate(ImBuf *ibuf) static void imbuf_verify_float(ImBuf *ibuf) { + /* multiple threads could request for display buffer at once and in case + * view transform is not used it'll lead to display buffer calculated + * several times + * it is harmless, but would take much more time (assuming thread lock + * happens faster than running float->byte conversion for average image) + */ + BLI_lock_thread(LOCK_COLORMANAGE); + if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID))) IMB_rect_from_float(ibuf); + + BLI_unlock_thread(LOCK_COLORMANAGE); } /*********************** Public display buffers interfaces *************************/ @@ -1180,6 +1158,8 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet colormanage_view_settings_to_cache(&cache_view_settings, view_settings); colormanage_display_settings_to_cache(&cache_display_settings, display_settings); + BLI_lock_thread(LOCK_COLORMANAGE); + /* ensure color management bit fields exists */ if (!ibuf->display_buffer_flags) colormanage_flags_allocate(ibuf); @@ -1187,6 +1167,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet display_buffer = colormanage_cache_get(ibuf, &cache_view_settings, &cache_display_settings, cache_handle); if (display_buffer) { + BLI_unlock_thread(LOCK_COLORMANAGE); return display_buffer; } @@ -1197,6 +1178,8 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet colormanage_cache_put(ibuf, &cache_view_settings, &cache_display_settings, display_buffer, cache_handle); + BLI_unlock_thread(LOCK_COLORMANAGE); + return display_buffer; } #else @@ -1249,7 +1232,11 @@ void IMB_display_buffer_to_imbuf_rect(ImBuf *ibuf, const ColorManagedViewSetting void IMB_display_buffer_release(void *cache_handle) { if (cache_handle) { + BLI_lock_thread(LOCK_COLORMANAGE); + colormanage_cache_handle_release(cache_handle); + + BLI_unlock_thread(LOCK_COLORMANAGE); } } @@ -1744,7 +1731,7 @@ void IMB_colormanagement_view_items_add(EnumPropertyItem **items, int *totitem, ColorManagedView *view; /* OCIO_TODO: try to get rid of such a hackish stuff */ - view = colormanage_view_get_named("ACES ODT Tonecurve"); + view = colormanage_view_get_named(ACES_ODT_TONECORVE); if (view) { colormanagement_view_item_add(items, totitem, view); } @@ -1784,68 +1771,83 @@ void IMB_colormanagement_colorspace_items_add(EnumPropertyItem **items, int *tot /*********************** Partial display buffer update *************************/ /* - * Partial display update is supposed to be used by such areas as compositor, - * which re-calculates parts of the images and requires updating only - * specified areas of buffers to provide better visual feedback. + * Partial display update is supposed to be used by such areas as + * compositor and renderer, This areas are calculating tiles of the + * images and because of performance reasons only this tiles should + * be color managed when they finished to be calculated. This gives + * nice visual feedback without slowing things down. * - * To achieve this special context is being constructed. This context is - * holding all buffers which were color managed and transformations which - * need to be applied on this buffers to make them valid. - * - * Updating happens for all buffers from this context using given linear - * float buffer and rectangle area which shall be updated. - * - * Updating every rectangle is thread-save operation due to buffers are - * referenced by the context, so they shouldn't have been deleted - * during execution. + * Updating happens for all display buffers generated for given + * ImBuf at the time function is being called. */ -typedef struct PartialBufferUpdateItem { - struct PartialBufferUpdateItem *next, *prev; - - unsigned char *display_buffer; - void *cache_handle; - - int display, view; - #ifdef WITH_OCIO - ConstProcessorRcPtr *processor; +static void partial_buffer_update_rect(unsigned char *display_buffer, const float *linear_buffer, int display_stride, + int linear_stride, int linear_offset_x, int linear_offset_y, + int channels, int dither, int predivide, + ConstProcessorRcPtr *processor, imb_tonecurveCb tonecurve_func, + int xmin, int ymin, int xmax, int ymax) +{ + int x, y; + + for (y = ymin; y <= ymax; y++) { + for (x = xmin; x <= xmax; x++) { + int display_index = (y * display_stride + x) * channels; + int linear_index = ((y - linear_offset_y) * linear_stride + (x - linear_offset_x)) * channels; + float pixel[4]; + + if (processor) { + copy_v4_v4(pixel, (float *) linear_buffer + linear_index); + + OCIO_processorApplyRGBA(processor, pixel); + + rgba_float_to_uchar(display_buffer + display_index, pixel); + } + else { + IMB_buffer_byte_from_float_tonecurve(display_buffer + display_index, linear_buffer + linear_index, + channels, dither, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, + predivide, 1, 1, 1, 1, tonecurve_func); + } + } + } +} #endif - imb_tonecurveCb tonecurve_func; -} PartialBufferUpdateItem; - -typedef struct PartialBufferUpdateContext { - int buffer_width; - int dither, predivide; - - ListBase items; -} PartialBufferUpdateContext; - -PartialBufferUpdateContext *IMB_partial_buffer_update_context_new(ImBuf *ibuf) +void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, + int stride, int offset_x, int offset_y, + int xmin, int ymin, int xmax, int ymax) { - PartialBufferUpdateContext *context = NULL; - #ifdef WITH_OCIO int display; - context = MEM_callocN(sizeof(PartialBufferUpdateContext), "partial buffer update context"); + int *display_buffer_flags; - context->buffer_width = ibuf->x; + int buffer_width = ibuf->x; + int channels = ibuf->channels; + int predivide = ibuf->flags & IB_cm_predivide; + int dither = ibuf->dither; - context->predivide = ibuf->flags & IB_cm_predivide; - context->dither = ibuf->dither; + BLI_lock_thread(LOCK_COLORMANAGE); if (!ibuf->display_buffer_flags) { /* there's no cached display buffers, so no need to iterate though bit fields */ - return context; + BLI_unlock_thread(LOCK_COLORMANAGE); + + return; } + /* make a copy of flags, so other areas could calculate new display buffers + * and they'll be properly handled later + */ + display_buffer_flags = MEM_dupallocN(ibuf->display_buffer_flags); + + BLI_unlock_thread(LOCK_COLORMANAGE); + for (display = 0; display < global_tot_display; display++) { ColormanageCacheDisplaySettings display_settings = {0}; int display_index = display + 1; /* displays in configuration are 1-based */ const char *display_name = IMB_colormanagement_display_get_indexed_name(display_index); - int view_flags = ibuf->display_buffer_flags[display]; + int view_flags = display_buffer_flags[display]; int view = 0; display_settings.display = display_index; @@ -1856,116 +1858,50 @@ PartialBufferUpdateContext *IMB_partial_buffer_update_context_new(ImBuf *ibuf) unsigned char *display_buffer; void *cache_handle; int view_index = view + 1; /* views in configuration are 1-based */ + float exposure, gamma; view_settings.view = view_index; - display_buffer = - colormanage_cache_get_validated(ibuf, &view_settings, &display_settings, &cache_handle); + BLI_lock_thread(LOCK_COLORMANAGE); + display_buffer = colormanage_cache_get_cache_data(ibuf, &view_settings, &display_settings, + &cache_handle, &exposure, &gamma); + BLI_unlock_thread(LOCK_COLORMANAGE); if (display_buffer) { - PartialBufferUpdateItem *item; const char *view_name = IMB_colormanagement_view_get_indexed_name(view_index); - float exposure, gamma; + ConstProcessorRcPtr *processor = NULL; + imb_tonecurveCb tonecurve_func = NULL; - colormanage_cache_get_cache_data(cache_handle, &exposure, &gamma); - - item = MEM_callocN(sizeof(PartialBufferUpdateItem), "partial buffer update item"); - - item->display_buffer = display_buffer; - item->cache_handle = cache_handle; - item->display = display_index; - item->view = view_index; - - if (!strcmp(view_name, "ACES ODT Tonecurve")) { - item->tonecurve_func = IMB_ratio_preserving_odt_tonecurve; + if (!strcmp(view_name, ACES_ODT_TONECORVE)) { + tonecurve_func = IMB_ratio_preserving_odt_tonecurve; } else { - ConstProcessorRcPtr *processor; - processor = create_display_buffer_processor(view_name, display_name, exposure, gamma); - - item->processor = processor; } - BLI_addtail(&context->items, item); + partial_buffer_update_rect(display_buffer, linear_buffer, buffer_width, stride, + offset_x, offset_y, channels, dither, predivide, + processor, tonecurve_func, xmin, ymin, xmax, ymax); + + if (processor) + OCIO_processorRelease(processor); } + + IMB_display_buffer_release(cache_handle); } view_flags /= 2; view++; } } + + MEM_freeN(display_buffer_flags); #else (void) ibuf; -#endif - - return context; -} - -void IMB_partial_buffer_update_rect(PartialBufferUpdateContext *context, const float *linear_buffer, struct rcti *rect) -{ -#ifdef WITH_OCIO - PartialBufferUpdateItem *item; - - for (item = context->items.first; item; item = item->next) { - if (item->processor || item->tonecurve_func) { - unsigned char *display_buffer = item->display_buffer; - int x, y; - - for (y = rect->ymin; y < rect->ymax; y++) { - for (x = rect->xmin; x < rect->xmax; x++) { - int index = (y * context->buffer_width + x) * 4; - float pixel[4]; - - if (item->processor) { - copy_v4_v4(pixel, (float *)linear_buffer + index); - - OCIO_processorApplyRGBA(item->processor, pixel); - - rgba_float_to_uchar(display_buffer + index, pixel); - } - else { - IMB_buffer_byte_from_float_tonecurve(display_buffer + index, linear_buffer + index, - 4, context->dither, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, - context->predivide, 1, 1, 1, 1, item->tonecurve_func); - } - } - } - } - } -#else - (void) context; (void) linear_buffer; - (void) rect; -#endif -} - -void IMB_partial_buffer_update_free(PartialBufferUpdateContext *context, ImBuf *ibuf) -{ -#ifdef WITH_OCIO - PartialBufferUpdateItem *item; - - IMB_display_buffer_invalidate(ibuf); - - item = context->items.first; - while (item) { - PartialBufferUpdateItem *item_next = item->next; - - /* displays are 1-based, need to go to 0-based arrays indices */ - ibuf->display_buffer_flags[item->display - 1] |= (1 << (item->view - 1)); - - colormanage_cache_handle_release(item->cache_handle); - - OCIO_processorRelease(item->processor); - - MEM_freeN(item); - - item = item_next; - } - - MEM_freeN(context); -#else - (void) context; - (void) ibuf; + (void) xmin; + (void) ymin; + (void) xmax; + (void) ymax; #endif } From 44800e884c9d638fb668089d8569888d8ef0502f Mon Sep 17 00:00:00 2001 From: Lukas Toenne Date: Fri, 20 Jul 2012 17:28:42 +0000 Subject: [PATCH 016/160] Masking: prevent crashes in cases when mask spline is axis aligned --- source/blender/blenkernel/intern/mask.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index a8c95a4fc71..e63dfdf4445 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -574,12 +574,25 @@ static void spline_feather_collapse_inner_loops(MaskSpline *spline, float (*feat max_delta_y = delta; } + /* prevent divisionsby zero by ensuring bounding box is not collapsed */ + if (max[0] - min[0] < FLT_EPSILON) { + max[0] += 0.01f; + min[0] -= 0.01f; + } + + if (max[1] - min[1] < FLT_EPSILON) { + max[1] += 0.01f; + min[1] -= 0.01f; + } + /* use dynamically calculated buckets per side, so we likely wouldn't * run into a situation when segment doesn't fit two buckets which is * pain collecting candidates for intersection */ + max_delta_x /= max[0] - min[0]; max_delta_y /= max[1] - min[1]; + max_delta = MAX2(max_delta_x, max_delta_y); buckets_per_side = MIN2(512, 0.9f / max_delta); From a3989d79df72b4bf735bd1bacd3f9753da60277d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 23 Jul 2012 09:20:11 +0000 Subject: [PATCH 017/160] ACES ODT tonecurve style cleanup and small tweaks Convert color into ACES color space from rec709 (which is quite the same as blender internal) before running tonecurve and convert color space back after tonecurve. This makes tonecurve be applying in actual space it was intended to and it makes color range smoother a bit. Would be nice to convert this into OCIO view tho. --- source/blender/imbuf/intern/filter.c | 321 +++++++++++++++------------ 1 file changed, 175 insertions(+), 146 deletions(-) diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c index 60a94044f39..6f7fd81f890 100644 --- a/source/blender/imbuf/intern/filter.c +++ b/source/blender/imbuf/intern/filter.c @@ -31,7 +31,6 @@ * \ingroup imbuf */ -#define _GNU_SOURCE /* See feature_test_macros(7) */ #include #include "MEM_guardedalloc.h" @@ -601,185 +600,215 @@ void IMB_premultiply_alpha(ImBuf *ibuf) /* Tonecurve corrections */ -// code of rdt_shaper_fwd and ratio_preserving_odt_tonecurve belongs to -// ACES project (https://github.com/ampas/aces-dev) +/* code of rdt_shaper_fwd and ratio_preserving_odt_tonecurve belongs to + * ACES project (https://github.com/ampas/aces-dev) + */ -// === ODT SPLINE === // -// -// Algorithm for applying ODT tone curve in forward direction. -// -// vers 1.0 Doug Walker 2012-01-23 -// modified by Scott Dyer 2012-02-28 +/* === ODT SPLINE === */ +/* + * Algorithm for applying ODT tone curve in forward direction. + * + * vers 1.0 Doug Walker 2012-01-23 + * modified by Scott Dyer 2012-02-28 + */ -// Input and output are in linear (not log) units. -static float rdt_shaper_fwd( float x) +/* Input and output are in linear (not log) units. */ +static float rdt_shaper_fwd(float x) { - // B-spline coefficients. - // The units are density of the output. - const float COEFS0 = -0.008; - const float COEFS1 = -0.00616; - const float COEFS2 = 0.026; - const float COEFS3 = 0.185; - const float COEFS4 = 0.521; - const float COEFS5 = 0.993; - const float COEFS6 = 1.563; - const float COEFS7 = 2.218; - const float COEFS8 = 2.795; - const float COEFS9 = 3.36; - const float COEFS10 = 4.0; // NB: keep this less than or equal to -log10( FLARE) - // The locations of these control points in OCES density space are: - // -1., -0.79, -0.44, -0.01, 0.48, 1.01, 1.58, 2.18, 2.82, 3.47, 4.15, 4.85 + /* B-spline coefficients. + * The units are density of the output. + */ + const float COEFS0 = -0.008f; + const float COEFS1 = -0.00616f; + const float COEFS2 = 0.026f; + const float COEFS3 = 0.185f; + const float COEFS4 = 0.521f; + const float COEFS5 = 0.993f; + const float COEFS6 = 1.563f; + const float COEFS7 = 2.218f; + const float COEFS8 = 2.795f; + const float COEFS9 = 3.36f; + const float COEFS10 = 4.0f; /* NB: keep this less than or equal to -log10(FLARE) */ + /* The locations of these control points in OCES density space are: + * -1., -0.79, -0.44, -0.01, 0.48, 1.01, 1.58, 2.18, 2.82, 3.47, 4.15, 4.85 + */ - // The flare term allows the spline to more rapidly approach zero - // while keeping the shape of the curve well-behaved in density space. - const float FLARE = 1e-4; + /* The flare term allows the spline to more rapidly approach zero + * while keeping the shape of the curve well-behaved in density space. + */ + const float FLARE = 1e-4f; - // The last control point is fixed to yield a specific density at the - // end of the knot domain. - //const float COEFS11 = 2. * ( -log10( FLARE) - 0.001) - COEFS10; - // Note: Apparently a CTL bug prevents calling log10() here, so - // you'll need to update this manually if you change FLARE. - const float COEFS11 = COEFS10 + 2. * ( 4. - COEFS10); + /* The last control point is fixed to yield a specific density at the + * end of the knot domain. + */ + /* const float COEFS11 = 2. * (-log10(FLARE) - 0.001) - COEFS10; */ - // The knots are in units of OCES density. + /* Note: Apparently a CTL bug prevents calling log10() here, so + * you'll need to update this manually if you change FLARE. + */ + const float COEFS11 = COEFS10 + 2.0f * (4.0f - COEFS10); + + /* The knots are in units of OCES density. */ const unsigned int KNOT_LEN = 11; - const float KNOT_START = -0.9; - const float KNOT_END = 4.484256; + const float KNOT_START = -0.9f; + const float KNOT_END = 4.484256f; - // The KNOT_POW adjusts the spacing to put more knots near the toe (highlights). - const float KNOT_POW = 1. / 1.3; + /* The KNOT_POW adjusts the spacing to put more knots near the toe (highlights). */ + const float KNOT_POW = 1.0f / 1.3f; const float OFFS = KNOT_START; const float SC = KNOT_END - KNOT_START; - // KNOT_DENS is density of the spline at the knots. - const float KNOT_DENS[ 11] = { - ( COEFS0 + COEFS1) / 2., - ( COEFS1 + COEFS2) / 2., - ( COEFS2 + COEFS3) / 2., - ( COEFS3 + COEFS4) / 2., - ( COEFS4 + COEFS5) / 2., - ( COEFS5 + COEFS6) / 2., - ( COEFS6 + COEFS7) / 2., - ( COEFS7 + COEFS8) / 2., - ( COEFS8 + COEFS9) / 2., - ( COEFS9 + COEFS10) / 2., - ( COEFS10 + COEFS11) / 2. + /* KNOT_DENS is density of the spline at the knots. */ + const float KNOT_DENS[11] = { + (COEFS0 + COEFS1) / 2.0f, + (COEFS1 + COEFS2) / 2.0f, + (COEFS2 + COEFS3) / 2.0f, + (COEFS3 + COEFS4) / 2.0f, + (COEFS4 + COEFS5) / 2.0f, + (COEFS5 + COEFS6) / 2.0f, + (COEFS6 + COEFS7) / 2.0f, + (COEFS7 + COEFS8) / 2.0f, + (COEFS8 + COEFS9) / 2.0f, + (COEFS9 + COEFS10) / 2.0f, + (COEFS10 + COEFS11) / 2.0f }; - // Parameters controlling linear extrapolation. + /* Parameters controlling linear extrapolation. */ const float LIGHT_SLOPE = 0.023; const float CROSSOVER = pow(10,-KNOT_END); const float REV_CROSSOVER = pow(10.0f, -KNOT_DENS[ KNOT_LEN - 1]) - FLARE; const float DARK_SLOPE = REV_CROSSOVER / CROSSOVER; - // Textbook monomial to basis-function conversion matrix. - /*const*/ float M[ 3][ 3] = { - { 0.5, -1.0, 0.5 }, - { -1.0, 1.0, 0.5 }, - { 0.5, 0.0, 0.0 } + /* Textbook monomial to basis-function conversion matrix. */ + /*const*/ float M[3][3] = { + { 0.5f, -1.0f, 0.5f}, + {-1.0f, 1.0f, 0.5f}, + { 0.5f, 0.0f, 0.0f} }; - float y; - // Linear extrapolation in linear space for negative & very dark values. - if ( x <= CROSSOVER) - y = x * DARK_SLOPE; - else { - float in_dens = -log10( x); - float out_dens; - float knot_coord = ( in_dens - OFFS) / SC; + float y; - // Linear extrapolation in log space for very light values. - if ( knot_coord <= 0.) - out_dens = KNOT_DENS[ 0] - ( KNOT_START - in_dens) * LIGHT_SLOPE; + /* Linear extrapolation in linear space for negative & very dark values. */ + if (x <= CROSSOVER) { + y = x * DARK_SLOPE; + } + else { + float in_dens = -log10(x); + float out_dens; + float knot_coord = (in_dens - OFFS) / SC; - // For typical OCES values, apply a B-spline curve. - else { - knot_coord = ( KNOT_LEN - 1) * pow( knot_coord, KNOT_POW); - { - int j = knot_coord; - float t = knot_coord - j; + if (knot_coord <= 0.0f) { + /* Linear extrapolation in log space for very light values. */ - // Would like to do this: - //float cf[ 3] = { COEFS[ j], COEFS[ j + 1], COEFS[ j + 2]}; - // or at least: - //cf[ 0] = COEFS[ j]; - //cf[ 1] = COEFS[ j + 1]; - //cf[ 2] = COEFS[ j + 2]; - // But apparently CTL bugs prevent it, so we do the following: - float cf[ 3]; - if ( j <= 0) { - cf[ 0] = COEFS0; cf[ 1] = COEFS1; cf[ 2] = COEFS2; - } - else if ( j == 1) { - cf[ 0] = COEFS1; cf[ 1] = COEFS2; cf[ 2] = COEFS3; - } - else if ( j == 2) { - cf[ 0] = COEFS2; cf[ 1] = COEFS3; cf[ 2] = COEFS4; - } - else if ( j == 3) { - cf[ 0] = COEFS3; cf[ 1] = COEFS4; cf[ 2] = COEFS5; - } - else if ( j == 4) { - cf[ 0] = COEFS4; cf[ 1] = COEFS5; cf[ 2] = COEFS6; - } - else if ( j == 5) { - cf[ 0] = COEFS5; cf[ 1] = COEFS6; cf[ 2] = COEFS7; - } - else if ( j == 6) { - cf[ 0] = COEFS6; cf[ 1] = COEFS7; cf[ 2] = COEFS8; - } - else if ( j == 7) { - cf[ 0] = COEFS7; cf[ 1] = COEFS8; cf[ 2] = COEFS9; - } - else if ( j == 8) { - cf[ 0] = COEFS8; cf[ 1] = COEFS9; cf[ 2] = COEFS10; - } - else { - cf[ 0] = COEFS9; cf[ 1] = COEFS10; cf[ 2] = COEFS11; - } + out_dens = KNOT_DENS[0] - (KNOT_START - in_dens) * LIGHT_SLOPE; + } + else { + /* For typical OCES values, apply a B-spline curve. */ - { - float monomials[ 3] = { t * t, t, 1. }; - float v[3]; + int j; + float t; + float cf[3], monomials[3], v[3]; - // XXX: check on this! maths could be different here (like row-major vs. column major or so) - //out_dens = dot_f3_f3( monomials, mult_f3_f33( cf, M)); + knot_coord = ( KNOT_LEN - 1) * pow( knot_coord, KNOT_POW); - mul_v3_m3v3(v, M, cf); - out_dens = dot_v3v3( monomials, v); - } + j = knot_coord; + t = knot_coord - j; + + /* Would like to do this: */ + /* float cf[ 3] = { COEFS[ j], COEFS[ j + 1], COEFS[ j + 2]}; */ + /* or at least: */ + /* cf[0] = COEFS[j]; */ + /* cf[1] = COEFS[j + 1]; */ + /* cf[2] = COEFS[j + 2]; */ + /* But apparently CTL bugs prevent it, so we do the following: */ + if (j <= 0) { + cf[0] = COEFS0; cf[1] = COEFS1; cf[2] = COEFS2; } - } - y = pow(10.0f, -out_dens) - FLARE; - } - return y; + else if (j == 1) { + cf[0] = COEFS1; cf[1] = COEFS2; cf[2] = COEFS3; + } + else if (j == 2) { + cf[0] = COEFS2; cf[1] = COEFS3; cf[2] = COEFS4; + } + else if (j == 3) { + cf[0] = COEFS3; cf[1] = COEFS4; cf[2] = COEFS5; + } + else if (j == 4) { + cf[0] = COEFS4; cf[1] = COEFS5; cf[2] = COEFS6; + } + else if (j == 5) { + cf[0] = COEFS5; cf[1] = COEFS6; cf[2] = COEFS7; + } + else if (j == 6) { + cf[0] = COEFS6; cf[1] = COEFS7; cf[2] = COEFS8; + } + else if (j == 7) { + cf[0] = COEFS7; cf[1] = COEFS8; cf[2] = COEFS9; + } + else if (j == 8) { + cf[0] = COEFS8; cf[1] = COEFS9; cf[2] = COEFS10; + } + else { + cf[0] = COEFS9; cf[1] = COEFS10; cf[2] = COEFS11; + } + + monomials[0] = t * t; + monomials[1] = t; + monomials[2] = 1.0f; + + mul_v3_m3v3(v, M, cf); + out_dens = dot_v3v3( monomials, v); + } + + y = pow(10.0f, -out_dens) - FLARE; + } + + return y; } void IMB_ratio_preserving_odt_tonecurve(float rgbOut[3], const float rgbIn[3]) { - // - // The "ratio preserving tonecurve" is used to avoid hue/chroma shifts. - // It sends a norm through the tonecurve and scales the RGB values based on the output. - // + float acesIn[3], acesOut[3]; - const float NTH_POWER = 2.0; - const float TINY = 1e-12; + float rec709_to_aces[3][3] = {{0.4395770431f, 0.0895979404f, 0.0174174830f}, + {0.3839148879f, 0.8147120476f, 0.1087378338f}, + {0.1765103489f, 0.0956883803f, 0.8738504052f}}; - float numerator = ( pow(rgbIn[0],NTH_POWER) + pow(rgbIn[1],NTH_POWER) + pow(rgbIn[2],NTH_POWER) ); - float denominator = MAX2( TINY, - ( pow(rgbIn[0],NTH_POWER-1) + - pow(rgbIn[1],NTH_POWER-1) + - pow(rgbIn[2],NTH_POWER-1) - ) - ); // use of max function to avoid divide by zero - float normRGB = numerator / denominator; - if (normRGB <= 0.0) normRGB = TINY; + float aces_to_rec709[3][3] = {{ 2.5219228268f, -0.2754705548f, -0.0159884077f}, + {-1.1370280981f, 1.3698303699f, -0.1477921605f}, + {-0.3849000633f, -0.0943564922f, 1.1637737751f}}; - { - float normRGBo = rdt_shaper_fwd( normRGB ); + /* The "ratio preserving tonecurve" is used to avoid hue/chroma shifts. + * It sends a norm through the tonecurve and scales the RGB values based on the output. + */ - rgbOut[0] = rgbIn[0] * normRGBo / normRGB; - rgbOut[1] = rgbIn[1] * normRGBo / normRGB; - rgbOut[2] = rgbIn[2] * normRGBo / normRGB; + const float NTH_POWER = 2.0f; + const float TINY = 1e-12f; + float numerator, denominator; + float normRGB, normRGBo; + + mul_v3_m3v3(acesIn, rec709_to_aces, (float *) rgbIn); + + numerator = pow(acesIn[0], NTH_POWER) + pow(acesIn[1], NTH_POWER) + pow(acesIn[2], NTH_POWER); + + denominator = pow(acesIn[0], NTH_POWER - 1) + + pow(acesIn[1], NTH_POWER - 1) + + pow(acesIn[2], NTH_POWER - 1); + + /* use of max function to avoid divide by zero */ + denominator = MAX2(TINY, denominator); + + normRGB = numerator / denominator; + + if (normRGB <= 0.0f) { + normRGB = TINY; } + + normRGBo = rdt_shaper_fwd(normRGB); + + acesOut[0] = acesIn[0] * normRGBo / normRGB; + acesOut[1] = acesIn[1] * normRGBo / normRGB; + acesOut[2] = acesIn[2] * normRGBo / normRGB; + + mul_v3_m3v3(rgbOut, aces_to_rec709, (float *) acesOut); } From 5652c9e107e79887c227a725e4f15ff50d4eee7a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 23 Jul 2012 13:01:30 +0000 Subject: [PATCH 018/160] Tomato Cycles: rendering can be cencelled before tile is fully rendered Probably there;s a proper way to check whether rendering was requested to cancel, but couldn't see any clearer ways to do that. --- intern/cycles/device/device_cpu.cpp | 15 +++++++++++++-- intern/cycles/device/device_task.h | 1 + intern/cycles/render/session.cpp | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index ebd486b0e0a..3ba49f17c9c 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -155,9 +155,14 @@ public: if(system_cpu_support_optimized()) { for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) - for(int sample = start_sample; sample < end_sample; sample++) + for(int sample = start_sample; sample < end_sample; sample++) { + if (task.get_cancel()) { + break; + } + kernel_cpu_optimized_path_trace(kg, render_buffer, rng_state, sample, x, y, tile.offset, tile.stride); + } if(task_pool.cancelled()) break; @@ -168,10 +173,16 @@ public: { for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) - for(int sample = start_sample; sample < end_sample; sample++) + for(int sample = start_sample; sample < end_sample; sample++) { + if (task.get_cancel()) { + break; + } + kernel_cpu_path_trace(kg, render_buffer, rng_state, sample, x, y, tile.offset, tile.stride); + } + if(task_pool.cancelled()) break; } diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h index e0433e56c64..b6236cab58d 100644 --- a/intern/cycles/device/device_task.h +++ b/intern/cycles/device/device_task.h @@ -59,6 +59,7 @@ public: boost::function acquire_tile; boost::function release_tile; + boost::function get_cancel; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index eddb288a600..ef387c54725 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -678,6 +678,7 @@ void Session::path_trace() task.acquire_tile = function_bind(&Session::acquire_tile, this, _1, _2); task.release_tile = function_bind(&Session::release_tile, this, _1); + task.get_cancel = function_bind(&Progress::get_cancel, &this->progress); device->task_add(task); } From b25d28df18059b3494a3ab2569ef5444eca1135d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 23 Jul 2012 13:51:29 +0000 Subject: [PATCH 019/160] Tomato Cycles: ability to cancel rendering before tile was fully rendered Seems this requred cuda context synchronization after every finished sample, which could give few percent of slowdown. In test made here it was only minor slowdown, so think it's pretty much acceptable for now. --- intern/cycles/device/device_cuda.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index c297d120b69..05d19ec106e 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -531,6 +531,8 @@ public: cuda_assert(cuFuncSetBlockShape(cuPathTrace, xthreads, ythreads, 1)) cuda_assert(cuLaunchGrid(cuPathTrace, xblocks, yblocks)) + cuda_assert(cuCtxSynchronize()) + cuda_pop_context(); } @@ -834,12 +836,13 @@ public: int start_sample = tile.start_sample; int end_sample = tile.start_sample + tile.num_samples; - for(int sample = start_sample; sample < end_sample; sample++) - path_trace(tile, sample); + for(int sample = start_sample; sample < end_sample; sample++) { + if (task->get_cancel()) { + break; + } - cuda_push_context(); - cuda_assert(cuCtxSynchronize()) - cuda_pop_context(); + path_trace(tile, sample); + } task->release_tile(tile); } From 9cdf5a855313d77d898191de16d0823807b66526 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 23 Jul 2012 18:45:29 +0000 Subject: [PATCH 020/160] Tomato Cycles: update buffers on every sample finished Was requested by Mango team to improve feedback during rendering. Known issues: - Updating of samples are accumulative, meaning that visually samples would be dark in the beginning becoming brighter during progress. - Could give some % of slowdown, so probably should be disabled in background mode. Still to come: update of samples when using CUDA and OpenCL. --- intern/cycles/device/device_cpu.cpp | 29 +++++++++++++++++------------ intern/cycles/device/device_task.h | 1 + intern/cycles/render/session.cpp | 16 ++++++++++++++++ intern/cycles/render/session.h | 1 + 4 files changed, 35 insertions(+), 12 deletions(-) diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 3ba49f17c9c..97e8b263159 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -153,38 +153,43 @@ public: #ifdef WITH_OPTIMIZED_KERNEL if(system_cpu_support_optimized()) { - for(int y = tile.y; y < tile.y + tile.h; y++) { - for(int x = tile.x; x < tile.x + tile.w; x++) - for(int sample = start_sample; sample < end_sample; sample++) { - if (task.get_cancel()) { + for(int sample = start_sample; sample < end_sample; sample++) { + for(int y = tile.y; y < tile.y + tile.h; y++) { + for(int x = tile.x; x < tile.x + tile.w; x++) { + if (task.get_cancel()) + break; + + if(task_pool.cancelled()) break; - } kernel_cpu_optimized_path_trace(kg, render_buffer, rng_state, sample, x, y, tile.offset, tile.stride); } + } - if(task_pool.cancelled()) - break; + task.update_tile_sample(tile); } } else #endif { - for(int y = tile.y; y < tile.y + tile.h; y++) { - for(int x = tile.x; x < tile.x + tile.w; x++) - for(int sample = start_sample; sample < end_sample; sample++) { + for(int sample = start_sample; sample < end_sample; sample++) { + for(int y = tile.y; y < tile.y + tile.h; y++) { + for(int x = tile.x; x < tile.x + tile.w; x++) { if (task.get_cancel()) { break; } + if(task_pool.cancelled()) + break; + kernel_cpu_path_trace(kg, render_buffer, rng_state, sample, x, y, tile.offset, tile.stride); } + } - if(task_pool.cancelled()) - break; + task.update_tile_sample(tile); } } diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h index b6236cab58d..34e1d9a6954 100644 --- a/intern/cycles/device/device_task.h +++ b/intern/cycles/device/device_task.h @@ -58,6 +58,7 @@ public: void split_max_size(list& tasks, int max_size); boost::function acquire_tile; + boost::function update_tile_sample; boost::function release_tile; boost::function get_cancel; }; diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index ef387c54725..9e565d2909a 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -373,12 +373,27 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile) return true; } +void Session::update_tile_sample(RenderTile& rtile) +{ + thread_scoped_lock tile_lock(tile_mutex); + + if(write_render_buffers_cb) { + /* todo: optimize this by making it thread safe and removing lock */ + + if(!progress.get_cancel()) + write_render_buffers_cb(rtile.buffers); + } + + update_status_time(); +} + void Session::release_tile(RenderTile& rtile) { thread_scoped_lock tile_lock(tile_mutex); if(write_render_buffers_cb) { /* todo: optimize this by making it thread safe and removing lock */ + /* todo: this could be removed as soon as all devices would use update_tile_sample */ if(!progress.get_cancel()) write_render_buffers_cb(rtile.buffers); delete rtile.buffers; @@ -679,6 +694,7 @@ void Session::path_trace() task.acquire_tile = function_bind(&Session::acquire_tile, this, _1, _2); task.release_tile = function_bind(&Session::release_tile, this, _1); task.get_cancel = function_bind(&Progress::get_cancel, &this->progress); + task.update_tile_sample = function_bind(&Session::update_tile_sample, this, _1); device->task_add(task); } diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index d06f5b823fb..5ad9b50fbda 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -145,6 +145,7 @@ protected: void reset_gpu(BufferParams& params, int samples); bool acquire_tile(Device *tile_device, RenderTile& tile); + void update_tile_sample(RenderTile& tile); void release_tile(RenderTile& tile); bool device_use_gl; From 10118cc8259115153afbfdbec29c1e0baecdc443 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 23 Jul 2012 19:06:04 +0000 Subject: [PATCH 021/160] Tomato Cycles: update buffers after sample wasfinished for CUDA devices --- intern/cycles/device/device_cuda.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 05d19ec106e..bbbb577b693 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -842,6 +842,7 @@ public: } path_trace(tile, sample); + task->update_tile_sample(tile); } task->release_tile(tile); From e0eed025c95eb1a9c1991705f96d171d68743727 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 23 Jul 2012 20:46:27 +0000 Subject: [PATCH 022/160] Tomato Cycles: deadlock with save buffers enabled should be resolved now --- intern/cycles/blender/blender_session.cpp | 8 +++++--- intern/cycles/blender/blender_session.h | 2 +- intern/cycles/render/session.cpp | 5 ++--- intern/cycles/render/session.h | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 3cc07a186cb..0fb84638d03 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -189,7 +189,7 @@ static void end_render_result(BL::RenderEngine b_engine, BL::RenderResult b_rr, RE_engine_end_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data, (int)cancel); } -void BlenderSession::write_render_buffers(RenderBuffers *buffers) +void BlenderSession::write_render_buffers(RenderBuffers *buffers, bool final_sample) { BufferParams& params = buffers->params; int x = params.full_x - session->tile_manager.params.full_x; @@ -211,13 +211,15 @@ void BlenderSession::write_render_buffers(RenderBuffers *buffers) /* write result */ write_render_result(b_rr, b_rlay, buffers); - end_render_result(b_engine, b_rr); + + if (final_sample) + end_render_result(b_engine, b_rr); } void BlenderSession::render() { /* set callback to write out render results */ - session->write_render_buffers_cb = function_bind(&BlenderSession::write_render_buffers, this, _1); + session->write_render_buffers_cb = function_bind(&BlenderSession::write_render_buffers, this, _1, _2); /* get buffer parameters */ SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index 0eda2a1944e..00b22404159 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -48,7 +48,7 @@ public: /* offline render */ void render(); void write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers); - void write_render_buffers(RenderBuffers *buffers); + void write_render_buffers(RenderBuffers *buffers, bool final_sample); /* interactive updates */ void synchronize(); diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 9e565d2909a..50ad8cc1da2 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -381,7 +381,7 @@ void Session::update_tile_sample(RenderTile& rtile) /* todo: optimize this by making it thread safe and removing lock */ if(!progress.get_cancel()) - write_render_buffers_cb(rtile.buffers); + write_render_buffers_cb(rtile.buffers, false); } update_status_time(); @@ -393,9 +393,8 @@ void Session::release_tile(RenderTile& rtile) if(write_render_buffers_cb) { /* todo: optimize this by making it thread safe and removing lock */ - /* todo: this could be removed as soon as all devices would use update_tile_sample */ if(!progress.get_cancel()) - write_render_buffers_cb(rtile.buffers); + write_render_buffers_cb(rtile.buffers, true); delete rtile.buffers; } diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 5ad9b50fbda..131e9f74591 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -105,7 +105,7 @@ public: TileManager tile_manager; int sample; - boost::function write_render_buffers_cb; + boost::function write_render_buffers_cb; Session(const SessionParams& params); ~Session(); From d9d4430a56bc11889b0508914133d301383e9a88 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 23 Jul 2012 22:06:43 +0000 Subject: [PATCH 023/160] Tomato Cycles: code reshuffle to make data flow more obvious Should be no functional changes --- intern/cycles/blender/blender_session.cpp | 21 +++++++++++++++++---- intern/cycles/blender/blender_session.h | 4 +++- intern/cycles/render/session.cpp | 6 +++--- intern/cycles/render/session.h | 3 ++- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 0fb84638d03..b67bd876ea6 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -189,7 +189,7 @@ static void end_render_result(BL::RenderEngine b_engine, BL::RenderResult b_rr, RE_engine_end_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data, (int)cancel); } -void BlenderSession::write_render_buffers(RenderBuffers *buffers, bool final_sample) +void BlenderSession::do_write_update_render_buffers(RenderBuffers *buffers, bool do_update, bool do_write) { BufferParams& params = buffers->params; int x = params.full_x - session->tile_manager.params.full_x; @@ -210,16 +210,28 @@ void BlenderSession::write_render_buffers(RenderBuffers *buffers, bool final_sam BL::RenderLayer b_rlay = *b_single_rlay; /* write result */ - write_render_result(b_rr, b_rlay, buffers); + if (do_update) + write_render_result(b_rr, b_rlay, buffers); - if (final_sample) + if (do_write) end_render_result(b_engine, b_rr); } +void BlenderSession::write_render_buffers(RenderBuffers *buffers) +{ + do_write_update_render_buffers(buffers, true, true); +} + +void BlenderSession::update_render_buffers(RenderBuffers *buffers) +{ + do_write_update_render_buffers(buffers, true, false); +} + void BlenderSession::render() { /* set callback to write out render results */ - session->write_render_buffers_cb = function_bind(&BlenderSession::write_render_buffers, this, _1, _2); + session->write_render_buffers_cb = function_bind(&BlenderSession::write_render_buffers, this, _1); + session->update_render_buffers_cb = function_bind(&BlenderSession::update_render_buffers, this, _1); /* get buffer parameters */ SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); @@ -290,6 +302,7 @@ void BlenderSession::render() /* clear callback */ session->write_render_buffers_cb = NULL; + session->update_render_buffers_cb = NULL; } void BlenderSession::write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers) diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index 00b22404159..dfc40a14414 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -47,8 +47,10 @@ public: /* offline render */ void render(); + void do_write_update_render_buffers(RenderBuffers *buffers, bool do_update, bool do_write); void write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers); - void write_render_buffers(RenderBuffers *buffers, bool final_sample); + void write_render_buffers(RenderBuffers *buffers); + void update_render_buffers(RenderBuffers *buffers); /* interactive updates */ void synchronize(); diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 50ad8cc1da2..9926e906ddf 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -377,11 +377,11 @@ void Session::update_tile_sample(RenderTile& rtile) { thread_scoped_lock tile_lock(tile_mutex); - if(write_render_buffers_cb) { + if(update_render_buffers_cb) { /* todo: optimize this by making it thread safe and removing lock */ if(!progress.get_cancel()) - write_render_buffers_cb(rtile.buffers, false); + update_render_buffers_cb(rtile.buffers); } update_status_time(); @@ -394,7 +394,7 @@ void Session::release_tile(RenderTile& rtile) if(write_render_buffers_cb) { /* todo: optimize this by making it thread safe and removing lock */ if(!progress.get_cancel()) - write_render_buffers_cb(rtile.buffers, true); + write_render_buffers_cb(rtile.buffers); delete rtile.buffers; } diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 131e9f74591..be834409756 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -105,7 +105,8 @@ public: TileManager tile_manager; int sample; - boost::function write_render_buffers_cb; + boost::function write_render_buffers_cb; + boost::function update_render_buffers_cb; Session(const SessionParams& params); ~Session(); From a0bdc54572c55158a39b40dabf7eb67698f5450c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 24 Jul 2012 11:49:21 +0000 Subject: [PATCH 024/160] Color management: fix memory corruption when using border rendering Image's get render result function used to modify ImBuf directly, without making needed invalidates to color management cache when it's needed. --- source/blender/blenkernel/intern/image.c | 7 +++++++ source/blender/imbuf/intern/colormanagement.c | 12 +++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index fe364bbf439..20ad570a882 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2560,6 +2560,13 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); } + /* invalidate color managed buffers if render result changed */ + BLI_lock_thread(LOCK_COLORMANAGE); + if (ibuf->x != rres.rectx || ibuf->y != rres.recty || ibuf->rect_float != rectf) { + IMB_display_buffer_invalidate(ibuf); + } + BLI_unlock_thread(LOCK_COLORMANAGE); + ibuf->x = rres.rectx; ibuf->y = rres.recty; diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 091bde6ec70..a5546aa3890 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -316,6 +316,10 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV if (cache_ibuf) { ColormnaageCacheData *cache_data; + BLI_assert(cache_ibuf->x == ibuf->x && + cache_ibuf->y == ibuf->y && + cache_ibuf->channels == ibuf->channels); + /* only buffers with different color space conversions are being stored * in cache separately. buffer which were used only different exposure/gamma * are re-suing the same cached buffer @@ -1822,7 +1826,6 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, int *display_buffer_flags; - int buffer_width = ibuf->x; int channels = ibuf->channels; int predivide = ibuf->flags & IB_cm_predivide; int dither = ibuf->dither; @@ -1859,12 +1862,19 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, void *cache_handle; int view_index = view + 1; /* views in configuration are 1-based */ float exposure, gamma; + int buffer_width; view_settings.view = view_index; BLI_lock_thread(LOCK_COLORMANAGE); display_buffer = colormanage_cache_get_cache_data(ibuf, &view_settings, &display_settings, &cache_handle, &exposure, &gamma); + + /* in some rare cases buffer's dimension could be changing directly from + * different thread + * this i.e. happens when image editor acquires render result + */ + buffer_width = ibuf->x; BLI_unlock_thread(LOCK_COLORMANAGE); if (display_buffer) { From a6d62e9e87d460473f16ddd1fccc319ffd9b9246 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 24 Jul 2012 12:18:40 +0000 Subject: [PATCH 025/160] Correction to previous commit -- make sure float buffer is not being changed while color management transformations are running. --- source/blender/blenkernel/intern/image.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 20ad570a882..fa0070de76b 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2565,7 +2565,6 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ if (ibuf->x != rres.rectx || ibuf->y != rres.recty || ibuf->rect_float != rectf) { IMB_display_buffer_invalidate(ibuf); } - BLI_unlock_thread(LOCK_COLORMANAGE); ibuf->x = rres.rectx; ibuf->y = rres.recty; @@ -2602,6 +2601,8 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ ibuf->flags &= ~IB_zbuffloat; } + BLI_unlock_thread(LOCK_COLORMANAGE); + /* since its possible to access the buffer from the image directly, set the profile [#25073] */ ibuf->profile = (iuser->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_NONE; ibuf->dither = dither; From de6d480f715a41464d405d2840d05e2d5006b2bf Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 24 Jul 2012 20:05:00 +0000 Subject: [PATCH 026/160] Tomato Cycles: fix for memory overflow issue This fixes memory overflow caused by creating render result every time RenderResult is creating when updating sample and not being freed until tile is fully rendered. Solved in probably not best way -- RenderResult is being stored in RenderBuffers, so it's creating only once. This solves memory issues, but while was looking into this issue discovered dramatic slowdown caused by samples update in some files from mango svn. Solving this slowdown is becoming first priority from now on. --- intern/cycles/blender/blender_session.cpp | 30 ++++++++++++++----- intern/cycles/render/buffers.cpp | 2 ++ intern/cycles/render/buffers.h | 2 ++ .../render/intern/source/external_engine.c | 3 +- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index b67bd876ea6..1a0a9327528 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -176,17 +176,31 @@ static PassType get_pass_type(BL::RenderPass b_pass) return PASS_NONE; } -static BL::RenderResult begin_render_result(BL::RenderEngine b_engine, int x, int y, int w, int h, const char *layername) +static BL::RenderResult begin_render_result(BL::RenderEngine b_engine, int x, int y, int w, int h, const char *layername, BufferParams *params) { - RenderResult *rrp = RE_engine_begin_result((RenderEngine*)b_engine.ptr.data, x, y, w, h, layername); + RenderResult *rrp = NULL; + + if (params) + rrp = (RenderResult *) params->render_result; + + if (!rrp) { + rrp = RE_engine_begin_result((RenderEngine*)b_engine.ptr.data, x, y, w, h, layername); + + if (params) + params->render_result = rrp; + } + PointerRNA rrptr; RNA_pointer_create(NULL, &RNA_RenderResult, rrp, &rrptr); return BL::RenderResult(rrptr); } -static void end_render_result(BL::RenderEngine b_engine, BL::RenderResult b_rr, bool cancel = false) +static void end_render_result(BL::RenderEngine b_engine, BL::RenderResult b_rr, BufferParams *params, bool cancel = false) { RE_engine_end_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data, (int)cancel); + + if (params) + params->render_result = NULL; } void BlenderSession::do_write_update_render_buffers(RenderBuffers *buffers, bool do_update, bool do_write) @@ -198,7 +212,7 @@ void BlenderSession::do_write_update_render_buffers(RenderBuffers *buffers, bool int h = params.height; /* get render result */ - BL::RenderResult b_rr = begin_render_result(b_engine, x, y, w, h, b_rlay_name.c_str()); + BL::RenderResult b_rr = begin_render_result(b_engine, x, y, w, h, b_rlay_name.c_str(), ¶ms); /* can happen if the intersected rectangle gives 0 width or height */ if (b_rr.ptr.data == NULL) { @@ -214,7 +228,7 @@ void BlenderSession::do_write_update_render_buffers(RenderBuffers *buffers, bool write_render_result(b_rr, b_rlay, buffers); if (do_write) - end_render_result(b_engine, b_rr); + end_render_result(b_engine, b_rr, ¶ms); } void BlenderSession::write_render_buffers(RenderBuffers *buffers) @@ -245,13 +259,13 @@ void BlenderSession::render() b_rlay_name = b_iter->name(); /* temporary render result to find needed passes */ - BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_rlay_name.c_str()); + BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_rlay_name.c_str(), NULL); BL::RenderResult::layers_iterator b_single_rlay; b_rr.layers.begin(b_single_rlay); /* layer will be missing if it was disabled in the UI */ if(b_single_rlay == b_rr.layers.end()) { - end_render_result(b_engine, b_rr, true); + end_render_result(b_engine, b_rr, NULL, true); continue; } @@ -278,7 +292,7 @@ void BlenderSession::render() } /* free result without merging */ - end_render_result(b_engine, b_rr, true); + end_render_result(b_engine, b_rr, NULL, true); buffer_params.passes = passes; scene->film->tag_passes_update(scene, passes); diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index bd8c6cd22dd..30cd7049983 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -44,6 +44,8 @@ BufferParams::BufferParams() full_width = 0; full_height = 0; + render_result = NULL; + Pass::add(PASS_COMBINED, passes); } diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h index f8df2b3587e..c2bb977a537 100644 --- a/intern/cycles/render/buffers.h +++ b/intern/cycles/render/buffers.h @@ -52,6 +52,8 @@ public: /* passes */ vector passes; + void *render_result; + /* functions */ BufferParams(); diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index ab66a3c770f..a4fa2bb34e7 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -233,7 +233,8 @@ void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel } /* free */ - render_result_free_list(&engine->fullresult, result); + BLI_remlink(&engine->fullresult, result); + render_result_free(result); } /* Cancel */ From 375882f396920777eed6532c22b9914e74ee2563 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 24 Jul 2012 20:54:06 +0000 Subject: [PATCH 027/160] Tomato Cycles: speedup realtime samples update Copy pixels for combined pass only when updating tile after each sample skipping all other passes. Behaves noticeable faster on scenes with lots passes used. Would check further tomorrow from studio whether stuff could be speed up further. --- intern/cycles/blender/blender_session.cpp | 53 +++++++++++++++-------- intern/cycles/blender/blender_session.h | 11 ++++- 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 1a0a9327528..dbffb2f6eac 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -203,7 +203,7 @@ static void end_render_result(BL::RenderEngine b_engine, BL::RenderResult b_rr, params->render_result = NULL; } -void BlenderSession::do_write_update_render_buffers(RenderBuffers *buffers, bool do_update, bool do_write) +void BlenderSession::do_write_update_render_buffers(RenderBuffers *buffers, bool do_update_only) { BufferParams& params = buffers->params; int x = params.full_x - session->tile_manager.params.full_x; @@ -223,22 +223,25 @@ void BlenderSession::do_write_update_render_buffers(RenderBuffers *buffers, bool b_rr.layers.begin(b_single_rlay); BL::RenderLayer b_rlay = *b_single_rlay; - /* write result */ - if (do_update) + if (do_update_only) { + /* update only needed */ + update_render_result(b_rr, b_rlay, buffers); + } + else { + /* write result */ write_render_result(b_rr, b_rlay, buffers); - - if (do_write) end_render_result(b_engine, b_rr, ¶ms); + } } void BlenderSession::write_render_buffers(RenderBuffers *buffers) { - do_write_update_render_buffers(buffers, true, true); + do_write_update_render_buffers(buffers, false); } void BlenderSession::update_render_buffers(RenderBuffers *buffers) { - do_write_update_render_buffers(buffers, true, false); + do_write_update_render_buffers(buffers, true); } void BlenderSession::render() @@ -319,7 +322,7 @@ void BlenderSession::render() session->update_render_buffers_cb = NULL; } -void BlenderSession::write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers) +void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers, bool do_update_only) { /* copy data from device */ if(!buffers->copy_from_device()) @@ -334,19 +337,21 @@ void BlenderSession::write_render_result(BL::RenderResult b_rr, BL::RenderLayer vector pixels(params.width*params.height*4); - /* copy each pass */ - BL::RenderLayer::passes_iterator b_iter; - - for(b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) { - BL::RenderPass b_pass(*b_iter); + if (!do_update_only) { + /* copy each pass */ + BL::RenderLayer::passes_iterator b_iter; - /* find matching pass type */ - PassType pass_type = get_pass_type(b_pass); - int components = b_pass.channels(); + for(b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) { + BL::RenderPass b_pass(*b_iter); - /* copy pixels */ - if(buffers->get_pass(pass_type, exposure, sample, components, &pixels[0])) - rna_RenderPass_rect_set(&b_pass.ptr, &pixels[0]); + /* find matching pass type */ + PassType pass_type = get_pass_type(b_pass); + int components = b_pass.channels(); + + /* copy pixels */ + if(buffers->get_pass(pass_type, exposure, sample, components, &pixels[0])) + rna_RenderPass_rect_set(&b_pass.ptr, &pixels[0]); + } } /* copy combined pass */ @@ -357,6 +362,16 @@ void BlenderSession::write_render_result(BL::RenderResult b_rr, BL::RenderLayer RE_engine_update_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data); } +void BlenderSession::write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers) +{ + do_write_update_render_result(b_rr, b_rlay, buffers, false); +} + +void BlenderSession::update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers) +{ + do_write_update_render_result(b_rr, b_rlay, buffers, true); +} + void BlenderSession::synchronize() { /* on session/scene parameter changes, we recreate session entirely */ diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index dfc40a14414..5f458aa888b 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -47,9 +47,14 @@ public: /* offline render */ void render(); - void do_write_update_render_buffers(RenderBuffers *buffers, bool do_update, bool do_write); + void write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers); void write_render_buffers(RenderBuffers *buffers); + + /* update functions are used to update display buffer only after sample was rendered + * only needed for better visual feedback + */ + void update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers); void update_render_buffers(RenderBuffers *buffers); /* interactive updates */ @@ -82,6 +87,10 @@ public: float last_progress; int width, height; + +protected: + void do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers, bool do_update_only); + void do_write_update_render_buffers(RenderBuffers *buffers, bool do_update_only); }; CCL_NAMESPACE_END From 62df895415912b646d7773ebd8cbc46f6318ab3d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 25 Jul 2012 14:29:14 +0000 Subject: [PATCH 028/160] Tomato Cycles: resolve slowdown introduced by interactive samples view commit Update samples displayign in the interface once in a whiel only (currently once in 1 sec). This still keeps rendering interactive enough for artists and it eliminates slowdown caused by constant uploading sampels from GPU to host. This also allowed to get rid of hack with storing render result in render buffers, due to it's not so big overhead ow to create render result when sample needs to be updated. Tests made with different files shows that now render speed is really close to oroginal speed from before we started hackign into this stuff. There still some issues with interactive update when rendering several render layers, but that seems to be irrelivant to all this sampels commtis, so woudl look into this as a separate patch. --- intern/cycles/blender/blender_session.cpp | 31 +++++++---------------- intern/cycles/device/device_cpu.cpp | 4 +-- intern/cycles/device/device_cuda.cpp | 2 +- intern/cycles/device/device_task.cpp | 18 +++++++++++++ intern/cycles/device/device_task.h | 5 ++++ intern/cycles/render/buffers.cpp | 2 -- intern/cycles/render/buffers.h | 2 -- 7 files changed, 35 insertions(+), 29 deletions(-) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index dbffb2f6eac..4e7ab217dc0 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -176,31 +176,17 @@ static PassType get_pass_type(BL::RenderPass b_pass) return PASS_NONE; } -static BL::RenderResult begin_render_result(BL::RenderEngine b_engine, int x, int y, int w, int h, const char *layername, BufferParams *params) +static BL::RenderResult begin_render_result(BL::RenderEngine b_engine, int x, int y, int w, int h, const char *layername) { - RenderResult *rrp = NULL; - - if (params) - rrp = (RenderResult *) params->render_result; - - if (!rrp) { - rrp = RE_engine_begin_result((RenderEngine*)b_engine.ptr.data, x, y, w, h, layername); - - if (params) - params->render_result = rrp; - } - + RenderResult *rrp = RE_engine_begin_result((RenderEngine*)b_engine.ptr.data, x, y, w, h, layername); PointerRNA rrptr; RNA_pointer_create(NULL, &RNA_RenderResult, rrp, &rrptr); return BL::RenderResult(rrptr); } -static void end_render_result(BL::RenderEngine b_engine, BL::RenderResult b_rr, BufferParams *params, bool cancel = false) +static void end_render_result(BL::RenderEngine b_engine, BL::RenderResult b_rr, bool cancel = false) { RE_engine_end_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data, (int)cancel); - - if (params) - params->render_result = NULL; } void BlenderSession::do_write_update_render_buffers(RenderBuffers *buffers, bool do_update_only) @@ -212,7 +198,7 @@ void BlenderSession::do_write_update_render_buffers(RenderBuffers *buffers, bool int h = params.height; /* get render result */ - BL::RenderResult b_rr = begin_render_result(b_engine, x, y, w, h, b_rlay_name.c_str(), ¶ms); + BL::RenderResult b_rr = begin_render_result(b_engine, x, y, w, h, b_rlay_name.c_str()); /* can happen if the intersected rectangle gives 0 width or height */ if (b_rr.ptr.data == NULL) { @@ -226,11 +212,12 @@ void BlenderSession::do_write_update_render_buffers(RenderBuffers *buffers, bool if (do_update_only) { /* update only needed */ update_render_result(b_rr, b_rlay, buffers); + end_render_result(b_engine, b_rr, true); } else { /* write result */ write_render_result(b_rr, b_rlay, buffers); - end_render_result(b_engine, b_rr, ¶ms); + end_render_result(b_engine, b_rr); } } @@ -262,13 +249,13 @@ void BlenderSession::render() b_rlay_name = b_iter->name(); /* temporary render result to find needed passes */ - BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_rlay_name.c_str(), NULL); + BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_rlay_name.c_str()); BL::RenderResult::layers_iterator b_single_rlay; b_rr.layers.begin(b_single_rlay); /* layer will be missing if it was disabled in the UI */ if(b_single_rlay == b_rr.layers.end()) { - end_render_result(b_engine, b_rr, NULL, true); + end_render_result(b_engine, b_rr, true); continue; } @@ -295,7 +282,7 @@ void BlenderSession::render() } /* free result without merging */ - end_render_result(b_engine, b_rr, NULL, true); + end_render_result(b_engine, b_rr, true); buffer_params.passes = passes; scene->film->tag_passes_update(scene, passes); diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 97e8b263159..9febd7ae27c 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -167,7 +167,7 @@ public: } } - task.update_tile_sample(tile); + task.update_progress(tile); } } else @@ -189,7 +189,7 @@ public: } } - task.update_tile_sample(tile); + task.update_progress(tile); } } diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index bbbb577b693..35f541d0c9c 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -842,7 +842,7 @@ public: } path_trace(tile, sample); - task->update_tile_sample(tile); + task->update_progress(tile); } task->release_tile(tile); diff --git a/intern/cycles/device/device_task.cpp b/intern/cycles/device/device_task.cpp index fe872bc6f19..479dbc76f1c 100644 --- a/intern/cycles/device/device_task.cpp +++ b/intern/cycles/device/device_task.cpp @@ -22,6 +22,7 @@ #include "device_task.h" #include "util_algorithm.h" +#include "util_time.h" CCL_NAMESPACE_BEGIN @@ -33,6 +34,7 @@ DeviceTask::DeviceTask(Type type_) shader_input(0), shader_output(0), shader_eval_type(0), shader_x(0), shader_w(0) { + last_update_time = time_dt(); } void DeviceTask::split_max_size(list& tasks, int max_size) @@ -88,5 +90,21 @@ void DeviceTask::split(list& tasks, int num) } } +void DeviceTask::update_progress(RenderTile &rtile) +{ + if (type != PATH_TRACE) + return; + + if (update_tile_sample) { + double current_time = time_dt(); + + if (current_time - last_update_time >= 1.0f) { + update_tile_sample(rtile); + + last_update_time = current_time; + } + } +} + CCL_NAMESPACE_END diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h index 34e1d9a6954..9c8eced15bf 100644 --- a/intern/cycles/device/device_task.h +++ b/intern/cycles/device/device_task.h @@ -57,10 +57,15 @@ public: void split(list& tasks, int num); void split_max_size(list& tasks, int max_size); + void update_progress(RenderTile &rtile); + boost::function acquire_tile; boost::function update_tile_sample; boost::function release_tile; boost::function get_cancel; + +protected: + double last_update_time; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index 30cd7049983..bd8c6cd22dd 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -44,8 +44,6 @@ BufferParams::BufferParams() full_width = 0; full_height = 0; - render_result = NULL; - Pass::add(PASS_COMBINED, passes); } diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h index c2bb977a537..f8df2b3587e 100644 --- a/intern/cycles/render/buffers.h +++ b/intern/cycles/render/buffers.h @@ -52,8 +52,6 @@ public: /* passes */ vector passes; - void *render_result; - /* functions */ BufferParams(); From 5e90606b174a43f1521414722fe6bb5a9f40d128 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Jul 2012 12:16:23 +0000 Subject: [PATCH 029/160] Tomato Cycles: fix for wrong resolution used for rendering Render Layer node Issue was caused by Cycles using render options from rendering scene, not from active scene. For now solved by passing render resolution inside RenderEngine structure. This probably could be solved in more general way, like adding bindings for RenderEngine->Render, which would avoid passing options like is_animation, came_override and so via RenderEngine. Would think about this a bit more and probably would do that. The same issue happens in trunk as well, but not consider such a change trunk-ready, would want to make more tests and probably clean the code a little bit before commiting this into trunk. --- intern/cycles/blender/blender_session.cpp | 6 +++--- source/blender/makesrna/intern/rna_render.c | 8 ++++++++ source/blender/render/extern/include/RE_engine.h | 2 ++ source/blender/render/intern/source/external_engine.c | 3 +++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 4e7ab217dc0..5b4260de9e5 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -45,10 +45,10 @@ BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::UserPreferences b b_v3d(PointerRNA_NULL), b_rv3d(PointerRNA_NULL) { /* offline render */ - BL::RenderSettings r = b_scene.render(); - width = (int)(r.resolution_x()*r.resolution_percentage()/100); - height = (int)(r.resolution_y()*r.resolution_percentage()/100); + width = b_engine.resolution_x(); + height = b_engine.resolution_y(); + background = true; last_redraw_time = 0.0f; diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 38b001c7a29..c21d029a6b7 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -367,6 +367,14 @@ static void rna_def_render_engine(BlenderRNA *brna) prop = RNA_def_property(srna, "tile_y", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "tile_y"); + prop = RNA_def_property(srna, "resolution_x", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "resolution_x"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop = RNA_def_property(srna, "resolution_y", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "resolution_y"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + /* registration */ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index bfd55dfd23a..2376aeca55e 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -92,6 +92,8 @@ typedef struct RenderEngine { struct Render *re; ListBase fullresult; char *text; + + int resolution_x, resolution_y; } RenderEngine; RenderEngine *RE_engine_create(RenderEngineType *type); diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index a4fa2bb34e7..81b42f1cb42 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -341,6 +341,9 @@ int RE_engine_render(Render *re, int do_all) engine->flag |= RE_ENGINE_PREVIEW; engine->camera_override = re->camera_override; + engine->resolution_x = re->winx; + engine->resolution_y = re->winy; + if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_PREVIEWBUTS)) == 0) BKE_scene_update_for_newframe(re->main, re->scene, re->lay); From 19bf60c54a0143596b7ee01a4de1cf70f4a6304e Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Jul 2012 13:16:04 +0000 Subject: [PATCH 030/160] Fix crash in drawing socket names when zooming out a lot --- source/blender/editors/space_node/drawnode.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index d84893e703f..e83185591fa 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -218,16 +218,20 @@ static void node_draw_output_default(const bContext *C, uiBlock *block, float slen; int ofs = 0; const char *ui_name = IFACE_(name); + int len = strlen(ui_name); UI_ThemeColor(TH_TEXT); slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect_sqrt; - while (slen > node->width) { + while (slen > node->width && ofs < len) { ofs++; slen = (UI_GetStringWidth(ui_name + ofs) + NODE_MARGIN_X) * snode->aspect_sqrt; } - uiDefBut(block, LABEL, 0, ui_name + ofs, - (int)(sock->locx - slen), (int)(sock->locy - 9.0f), - (short)(node->width - NODE_DY), (short)NODE_DY, - NULL, 0, 0, 0, 0, ""); + + if (ofs < len) { + uiDefBut(block, LABEL, 0, ui_name + ofs, + (int)(sock->locx - slen), (int)(sock->locy - 9.0f), + (short)(node->width - NODE_DY), (short)NODE_DY, + NULL, 0, 0, 0, 0, ""); + } (void)snode; } From 0471ffe9a4739b67c72ceb155ecbcd9c6111d188 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 27 Jul 2012 13:48:23 +0000 Subject: [PATCH 031/160] Display solver keyframes in cache line --- source/blender/editors/space_clip/clip_draw.c | 30 +++++++++++++++---- .../blender/editors/space_clip/tracking_ops.c | 2 ++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index d0629b354db..5adbcfe0391 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -94,13 +94,30 @@ void clip_draw_curfra_label(SpaceClip *sc, float x, float y) BLF_draw(fontid, numstr, sizeof(numstr)); } +static void draw_keyframe(int frame, int cfra, int sfra, float framelen, int width) +{ + int height = (frame == cfra) ? 22 : 10; + int x = (frame - sfra) * framelen; + + if (width == 1) { + glBegin(GL_LINES); + glVertex2i(x, 0); + glVertex2i(x, height); + glEnd(); + } + else { + glRecti(x, 0, x + width, height); + } +} + static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Scene *scene) { float x; int *points, totseg, i, a; float sfra = SFRA, efra = EFRA, framelen = ar->winx / (efra - sfra + 1); + MovieTracking *tracking = &clip->tracking; MovieTrackingTrack *act_track = BKE_tracking_track_get_active(&clip->tracking); - MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(&clip->tracking); + MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking); glEnable(GL_BLEND); @@ -198,6 +215,11 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc clip_draw_curfra_label(sc, x, 8.0f); + /* solver keyframes */ + glColor4ub(175, 255, 0, 255); + draw_keyframe(tracking->settings.keyframe1 + clip->start_frame - 1, CFRA, sfra, framelen, 2); + draw_keyframe(tracking->settings.keyframe2 + clip->start_frame - 1, CFRA, sfra, framelen, 2); + /* movie clip animation */ if ((sc->mode == SC_MODE_MASKEDIT) && sc->mask_info.mask) { MaskLayer *masklay = BKE_mask_layer_active(sc->mask_info.mask); @@ -213,11 +235,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc { i = masklay_shape->frame; - /* glRecti((i - sfra) * framelen, 0, (i - sfra + 1) * framelen, 4); */ - - /* use a line so we always see the keyframes */ - glVertex2i((i - sfra) * framelen, 0); - glVertex2i((i - sfra) * framelen, (i == CFRA) ? 22 : 10); + draw_keyframe(i, CFRA, sfra, framelen, 1); } glEnd(); diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 28bb0f70611..6821acc5f5a 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -2867,6 +2867,8 @@ static int set_solver_keyframe_exec(bContext *C, wmOperator *op) else settings->keyframe2 = framenr; + WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); + return OPERATOR_FINISHED; } From b6288e94ebb9da8cf6377ede4d0748e861c4d3a1 Mon Sep 17 00:00:00 2001 From: Peter Schlaile Date: Sun, 29 Jul 2012 15:48:38 +0000 Subject: [PATCH 032/160] == compositor == This adds an inpaint node to blender. In case, you don't know, inpainting does this: http://en.wikipedia.org/wiki/Inpainting It's use cases in blender are * wire removal * green screen background reconstruction The node isn't tile based (for fundamental reasons), but very fast, since it first builds a manhatten distance map and after that performs color convolution only on the edges. That's something, one should probably add also to the dilate node (in step mode) to make it perform a lot better for dilate iterations greater than 3. It will bring it's computing time from O(n^3) down to O(n^2). Take a look here for the details: http://ostermiller.org/dilate_and_erode.html ) --- source/blender/blenkernel/BKE_node.h | 1 + source/blender/blenkernel/SConscript | 7 + source/blender/blenkernel/intern/node.c | 1 + source/blender/compositor/CMakeLists.txt | 4 + .../compositor/intern/COM_Converter.cpp | 4 + .../compositor/nodes/COM_InpaintNode.cpp | 48 +++ .../compositor/nodes/COM_InpaintNode.h | 38 +++ .../operations/COM_InpaintOperation.cpp | 278 ++++++++++++++++++ .../operations/COM_InpaintOperation.h | 76 +++++ source/blender/editors/space_node/drawnode.c | 8 + source/blender/makesdna/DNA_node_types.h | 4 + source/blender/makesrna/RNA_access.h | 1 + source/blender/makesrna/intern/rna_nodetree.c | 20 ++ .../makesrna/intern/rna_nodetree_types.h | 1 + source/blender/nodes/CMakeLists.txt | 1 + source/blender/nodes/NOD_composite.h | 1 + .../composite/nodes/node_composite_inpaint.c | 61 ++++ 17 files changed, 554 insertions(+) create mode 100644 source/blender/compositor/nodes/COM_InpaintNode.cpp create mode 100644 source/blender/compositor/nodes/COM_InpaintNode.h create mode 100644 source/blender/compositor/operations/COM_InpaintOperation.cpp create mode 100644 source/blender/compositor/operations/COM_InpaintOperation.h create mode 100644 source/blender/nodes/composite/nodes/node_composite_inpaint.c diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 7bd9f75b2dd..4d6e0cbc900 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -661,6 +661,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat); #define CMP_NODE_KEYINGSCREEN 269 #define CMP_NODE_KEYING 270 #define CMP_NODE_TRACKPOS 271 +#define CMP_NODE_INPAINT 272 #define CMP_NODE_GLARE 301 #define CMP_NODE_TONEMAP 302 diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 86124ed932e..555d95acf88 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -3,6 +3,10 @@ Import ('env') import os sources = env.Glob('intern/*.c') +sources.remove('intern' + os.sep + 'mask_rasterize.c') +sources.remove('intern' + os.sep + 'mask.c') + +sources_mask = env.Glob('intern/mask*.c') incs = '. #/intern/guardedalloc #/intern/memutil' incs += ' ../blenlib ../blenfont ../makesdna ../windowmanager' @@ -117,7 +121,10 @@ if env['WITH_BF_INTERNATIONAL']: if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): incs += ' ' + env['BF_PTHREADS_INC'] + if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): env.BlenderLib ( libname = 'bf_blenkernel', sources = sources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [166,25]) #, cc_compileflags = env['CCFLAGS'].append('/WX') ) else: env.BlenderLib ( libname = 'bf_blenkernel', sources = sources, includes = Split(incs), defines = defs, libtype=['core','player', 'player2'], priority = [166,25,0] ) + +env.BlenderLib ( libname = 'bf_blenkernel_mask', sources = sources_mask, includes = Split(incs), defines = defs, libtype=['core','player', 'player2'], priority = [200,25,0] ) diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 56b1c0a17e8..937015c0cac 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1892,6 +1892,7 @@ static void registerCompositNodes(bNodeTreeType *ttype) register_node_type_cmp_bilateralblur(ttype); register_node_type_cmp_vecblur(ttype); register_node_type_cmp_dilateerode(ttype); + register_node_type_cmp_inpaint(ttype); register_node_type_cmp_defocus(ttype); register_node_type_cmp_valtorgb(ttype); diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 870e379b343..4dc111cebd2 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -286,6 +286,8 @@ set(SRC nodes/COM_FilterNode.h nodes/COM_DilateErodeNode.cpp nodes/COM_DilateErodeNode.h + nodes/COM_InpaintNode.cpp + nodes/COM_InpaintNode.h nodes/COM_BlurNode.cpp nodes/COM_BlurNode.h nodes/COM_BokehBlurNode.cpp @@ -590,6 +592,8 @@ set(SRC operations/COM_ConvolutionEdgeFilterOperation.cpp operations/COM_DilateErodeOperation.cpp operations/COM_DilateErodeOperation.h + operations/COM_InpaintOperation.cpp + operations/COM_InpaintOperation.h operations/COM_GlareThresholdOperation.cpp operations/COM_GlareThresholdOperation.h operations/COM_GlareBaseOperation.cpp diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index 37d38261ea5..24c3c36b79e 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -74,6 +74,7 @@ #include "COM_HueSaturationValueNode.h" #include "COM_IDMaskNode.h" #include "COM_ImageNode.h" +#include "COM_InpaintNode.h" #include "COM_InvertNode.h" #include "COM_KeyingNode.h" #include "COM_KeyingScreenNode.h" @@ -303,6 +304,9 @@ Node *Converter::convert(bNode *b_node, bool fast) case CMP_NODE_DILATEERODE: node = new DilateErodeNode(b_node); break; + case CMP_NODE_INPAINT: + node = new InpaintNode(b_node); + break; case CMP_NODE_LENSDIST: node = new LensDistortionNode(b_node); break; diff --git a/source/blender/compositor/nodes/COM_InpaintNode.cpp b/source/blender/compositor/nodes/COM_InpaintNode.cpp new file mode 100644 index 00000000000..e90a3921edc --- /dev/null +++ b/source/blender/compositor/nodes/COM_InpaintNode.cpp @@ -0,0 +1,48 @@ +/* + * 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. + * + * Contributor: Peter Schlaile + * Jeroen Bakker + * Monique Dewanchand + */ + +#include "COM_InpaintNode.h" +#include "DNA_scene_types.h" +#include "COM_ExecutionSystem.h" +#include "COM_InpaintOperation.h" +#include "BLI_math.h" + +InpaintNode::InpaintNode(bNode *editorNode) : Node(editorNode) +{ + /* pass */ +} + +void InpaintNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) +{ + + bNode *editorNode = this->getbNode(); + + /* if (editorNode->custom1 == CMP_NODE_INPAINT_SIMPLE) { */ + if (true) { + InpaintSimpleOperation *operation = new InpaintSimpleOperation(); + operation->setbNode(editorNode); + operation->setIterations(editorNode->custom2); + this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); + this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0)); + graph->addOperation(operation); + } +} diff --git a/source/blender/compositor/nodes/COM_InpaintNode.h b/source/blender/compositor/nodes/COM_InpaintNode.h new file mode 100644 index 00000000000..5837b979958 --- /dev/null +++ b/source/blender/compositor/nodes/COM_InpaintNode.h @@ -0,0 +1,38 @@ +/* + * 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. + * + * Contributor: Peter Schlaile + * Jeroen Bakker + * Monique Dewanchand + */ + +#ifndef _COM_InpaintNode_h_ +#define _COM_InpaintNode_h_ + +#include "COM_Node.h" + +/** + * @brief InpaintNode + * @ingroup Node + */ +class InpaintNode : public Node { +public: + InpaintNode(bNode *editorNode); + void convertToOperations(ExecutionSystem *graph, CompositorContext *context); +}; + +#endif diff --git a/source/blender/compositor/operations/COM_InpaintOperation.cpp b/source/blender/compositor/operations/COM_InpaintOperation.cpp new file mode 100644 index 00000000000..2d7bb8a7794 --- /dev/null +++ b/source/blender/compositor/operations/COM_InpaintOperation.cpp @@ -0,0 +1,278 @@ +/* + * 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. + * + * Contributor: Peter Schlaile + * Jeroen Bakker + * Monique Dewanchand + */ + +#include "COM_InpaintOperation.h" +#include "BLI_math.h" +#include "COM_OpenCLDevice.h" + +// Inpaint (simple convolve using average of known pixels) +InpaintSimpleOperation::InpaintSimpleOperation() : NodeOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->setComplex(true); + this->m_inputImageProgram = NULL; + this->pixelorder = NULL; + this->manhatten_distance = NULL; + this->m_cached_buffer = NULL; + this->cached_buffer_ready = false; +} +void InpaintSimpleOperation::initExecution() +{ + this->m_inputImageProgram = this->getInputSocketReader(0); + + this->m_cached_buffer = NULL; + this->pixelorder = NULL; + this->manhatten_distance = NULL; + this->m_cached_buffer = NULL; + this->cached_buffer_ready = false; + + this->initMutex(); +} + +void InpaintSimpleOperation::clamp_xy(int & x, int & y) +{ + int width = this->getWidth(); + int height = this->getHeight(); + + if (x < 0) { + x = 0; + } + if (x >= width) { + x = width-1; + } + if (y < 0) { + y = 0; + } + if (y >= height) { + y = height -1; + } +} + +float InpaintSimpleOperation::get(int x, int y, int component) +{ + int width = this->getWidth(); + + clamp_xy(x, y); + return this->m_cached_buffer[ + y * width * COM_NUMBER_OF_CHANNELS + + x * COM_NUMBER_OF_CHANNELS + component]; +} + +void InpaintSimpleOperation::set(int x, int y, int component, float v) +{ + int width = this->getWidth(); + + this->m_cached_buffer[ + y * width * COM_NUMBER_OF_CHANNELS + + x * COM_NUMBER_OF_CHANNELS + component] = v; +} + +int InpaintSimpleOperation::mdist(int x, int y) +{ + int width = this->getWidth(); + clamp_xy(x, y); + return this->manhatten_distance[y * width + x]; +} + +bool InpaintSimpleOperation::next_pixel(int & x,int & y, int & curr, int iters) +{ + int width = this->getWidth(); + + if (curr >= area_size) { + return false; + } + + int r = this->pixelorder[curr++]; + + x = r % width; + y = r / width; + + if (mdist(x, y) > iters) { + return false; + } + + return true; +} + +void InpaintSimpleOperation::calc_manhatten_distance() +{ + int width = this->getWidth(); + int height = this->getHeight(); + short * m = this->manhatten_distance = new short[width*height]; + int offsets[width+height+1]; + + memset(offsets, 0, sizeof(offsets)); + + for (int j = 0; j < height; j++) { + for (int i = 0; i < width; i++) { + int r = 0; + if (get(i, j, 3) < 1.0) { + r = width + height; + if (i > 0) + r = MIN2(r, m[j*width+i-1]+1); + if (j > 0) + r = MIN2(r, m[(j-1)*width+i]+1); + } + m[j*width+i] = r; + } + } + + for (int j = height-1; j >= 0; j--) { + for (int i = width; i >= 0; i--) { + int r = m[j*width+i]; + + if (i + 1 < width) + r = MIN2(r, m[j*width+i+1]+1); + if (j + 1 < height) + r = MIN2(r, m[(j+1)*width+i]+1); + + m[j*width+i] = r; + + offsets[r]++; + } + } + + offsets[0] = 0; + + for (int i = 1; i < width + height + 1; i++) { + offsets[i] += offsets[i-1]; + } + + area_size = offsets[width+height]; + pixelorder = new int[area_size]; + + for (int i = 0; i < width * height; i++) { + if (m[i] > 0) { + pixelorder[offsets[m[i]-1]++] = i; + } + } +} + +void InpaintSimpleOperation::pix_step(int x, int y) +{ + int d = this->mdist(x, y); + + float n = 0; + + float pix[3]; + + memset(pix, 0, sizeof(pix)); + + for (int dx = -1; dx <= 1; dx++) { + for (int dy = -1; dy <= 1; dy++) { + if (dx != 0 && dy != 0 && + this->mdist(x + dx, y + dy) < d) { + float weight = 1.0f / sqrt(2); + + if (dx == 0 || dy == 0) { + weight = 1; + } + + for (int c = 0; c < 3; c++) { + float fk = this->get(x + dx, y + dy, c); + + pix[c] += fk * weight; + } + n += weight; + } + } + } + + for (int c = 0; c < 3; c++) { + this->set(x, y, c, pix[c] / n); + } +} + +void *InpaintSimpleOperation::initializeTileData(rcti *rect) +{ + if (this->cached_buffer_ready) { + return this->m_cached_buffer; + } + lockMutex(); + if (!this->cached_buffer_ready) { + MemoryBuffer * buf = (MemoryBuffer *)this->m_inputImageProgram->initializeTileData(rect); + + this->m_cached_buffer = new float[this->getWidth() * this->getHeight() * COM_NUMBER_OF_CHANNELS]; + memcpy(this->m_cached_buffer, buf->getBuffer(), this->getWidth() * this->getHeight() * COM_NUMBER_OF_CHANNELS * sizeof(float)); + + calc_manhatten_distance(); + + int curr = 0; + int x,y; + + + while (next_pixel(x, y, curr, this->m_iterations)) { + pix_step(x, y); + } + this->cached_buffer_ready = true; + } + + unlockMutex(); + return this->m_cached_buffer; +} + +void InpaintSimpleOperation::executePixel(float *color, int x, int y, void *data) +{ + for (int c = 0; c < 3; c++) { + color[c] = get(x,y,c); + } + color[3] = 1.0f; +} + +void InpaintSimpleOperation::deinitExecution() +{ + this->m_inputImageProgram = NULL; + this->deinitMutex(); + if (this->m_cached_buffer) { + delete this->m_cached_buffer; + this->m_cached_buffer = NULL; + } + + if (this->pixelorder) { + delete this->pixelorder; + this->pixelorder = NULL; + } + + if (this->manhatten_distance) { + delete this->manhatten_distance; + this->manhatten_distance = NULL; + } + this->cached_buffer_ready = false; +} + +bool InpaintSimpleOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +{ + if (this->cached_buffer_ready) { + return false; + } else { + rcti newInput; + + newInput.xmax = getWidth(); + newInput.xmin = 0; + newInput.ymax = getHeight(); + newInput.ymin = 0; + + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + } +} + diff --git a/source/blender/compositor/operations/COM_InpaintOperation.h b/source/blender/compositor/operations/COM_InpaintOperation.h new file mode 100644 index 00000000000..8ba41a3062d --- /dev/null +++ b/source/blender/compositor/operations/COM_InpaintOperation.h @@ -0,0 +1,76 @@ +/* + * 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. + * + * Contributor: Peter Schlaile + * Jeroen Bakker + * Monique Dewanchand + */ + +#ifndef _COM_InpaintOperation_h +#define _COM_InpaintOperation_h +#include "COM_NodeOperation.h" + +class InpaintSimpleOperation : public NodeOperation { +protected: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputImageProgram; + + int m_iterations; + + float *m_cached_buffer; + bool cached_buffer_ready; + + int * pixelorder; + int area_size; + short * manhatten_distance; +public: + InpaintSimpleOperation(); + + /** + * the inner loop of this program + */ + void executePixel(float *color, int x, int y, void *data); + + /** + * Initialize the execution + */ + void initExecution(); + + void *initializeTileData(rcti *rect); + /** + * Deinitialize the execution + */ + void deinitExecution(); + + void setIterations(int iterations) { this->m_iterations = iterations; } + + bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + +private: + void calc_manhatten_distance(); + void clamp_xy(int & x, int & y); + float get(int x, int y, int component); + void set(int x, int y, int component, float v); + int mdist(int x, int y); + bool next_pixel(int & x,int & y, int & curr, int iters); + void pix_step(int x, int y); +}; + + +#endif diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index e83185591fa..ebaccdc7fb5 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1829,6 +1829,11 @@ static void node_composit_buts_dilateerode(uiLayout *layout, bContext *UNUSED(C) } } +static void node_composit_buts_inpaint(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE); +} + static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *col; @@ -2681,6 +2686,9 @@ static void node_composit_set_butfunc(bNodeType *ntype) case CMP_NODE_DILATEERODE: ntype->uifunc = node_composit_buts_dilateerode; break; + case CMP_NODE_INPAINT: + ntype->uifunc = node_composit_buts_inpaint; + break; case CMP_NODE_OUTPUT_FILE: ntype->uifunc = node_composit_buts_file_output; ntype->uifuncbut = node_composit_buts_file_output_details; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index c935382bff6..e7954c083fe 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -374,6 +374,10 @@ enum { CMP_NODE_DILATEERODE_DISTANCE_FEATHER = 3 }; +enum { + CMP_NODE_INPAINT_SIMPLE = 0 +}; + enum { CMP_NODEFLAG_MASK_AA = (1 << 0), CMP_NODEFLAG_MASK_NO_FEATHER = (1 << 1), diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 74adb25d994..8e387dd4eba 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -141,6 +141,7 @@ extern StructRNA RNA_CompositorNodeHueSat; extern StructRNA RNA_CompositorNodeIDMask; extern StructRNA RNA_CompositorNodeDoubleEdgeMask; extern StructRNA RNA_CompositorNodeImage; +extern StructRNA RNA_CompositorNodeInpaint; extern StructRNA RNA_CompositorNodeInvert; extern StructRNA RNA_CompositorNodeLensdist; extern StructRNA RNA_CompositorNodeLevels; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index ae376bad720..2220aee3f3e 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -2145,6 +2145,26 @@ static void def_cmp_dilate_erode(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_cmp_inpaint(StructRNA *srna) +{ + PropertyRNA *prop; + +/* + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, type_items); + RNA_def_property_ui_text(prop, "Type", "Type of inpaint algorithm"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +*/ + + prop = RNA_def_property(srna, "distance", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "custom2"); + RNA_def_property_range(prop, 1, 100000); + RNA_def_property_ui_text(prop, "Distance", "Distance to inpaint (number of iterations)"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + static void def_cmp_scale(StructRNA *srna) { PropertyRNA *prop; diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index a4837a88b17..494f147f6d9 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -121,6 +121,7 @@ DefNode( CompositorNode, CMP_NODE_TRANSLATE, 0, "TRANS DefNode( CompositorNode, CMP_NODE_ZCOMBINE, def_cmp_zcombine, "ZCOMBINE", Zcombine, "Z Combine", "" ) DefNode( CompositorNode, CMP_NODE_COMBRGBA, 0, "COMBRGBA", CombRGBA, "Combine RGBA", "" ) DefNode( CompositorNode, CMP_NODE_DILATEERODE, def_cmp_dilate_erode, "DILATEERODE", DilateErode, "Dilate/Erode", "" ) +DefNode( CompositorNode, CMP_NODE_INPAINT, def_cmp_inpaint, "INPAINT", Inpaint, "Inpaint", "" ) DefNode( CompositorNode, CMP_NODE_ROTATE, def_cmp_rotate, "ROTATE", Rotate, "Rotate", "" ) DefNode( CompositorNode, CMP_NODE_SCALE, def_cmp_scale, "SCALE", Scale, "Scale", "" ) DefNode( CompositorNode, CMP_NODE_SEPYCCA, def_cmp_ycc, "SEPYCCA", SepYCCA, "Separate YCCA", "" ) diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index e8dd4acb63b..d95751af82f 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -74,6 +74,7 @@ set(SRC composite/nodes/node_composite_huecorrect.c composite/nodes/node_composite_idMask.c composite/nodes/node_composite_image.c + composite/nodes/node_composite_inpaint.c composite/nodes/node_composite_invert.c composite/nodes/node_composite_keyingscreen.c composite/nodes/node_composite_keying.c diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index 3b4fa49ea05..92e547288c9 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -80,6 +80,7 @@ void register_node_type_cmp_dblur(struct bNodeTreeType *ttype); void register_node_type_cmp_bilateralblur(struct bNodeTreeType *ttype); void register_node_type_cmp_vecblur(struct bNodeTreeType *ttype); void register_node_type_cmp_dilateerode(struct bNodeTreeType *ttype); +void register_node_type_cmp_inpaint(struct bNodeTreeType *ttype); void register_node_type_cmp_defocus(struct bNodeTreeType *ttype); void register_node_type_cmp_valtorgb(struct bNodeTreeType *ttype); diff --git a/source/blender/nodes/composite/nodes/node_composite_inpaint.c b/source/blender/nodes/composite/nodes/node_composite_inpaint.c new file mode 100644 index 00000000000..e792ef0a95f --- /dev/null +++ b/source/blender/nodes/composite/nodes/node_composite_inpaint.c @@ -0,0 +1,61 @@ +/* + * ***** 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) 2006 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/composite/nodes/node_composite_inpaint.c + * \ingroup cmpnodes + */ + + +#include "node_composite_util.h" + + +/* **************** Inpaint/ ******************** */ + +static bNodeSocketTemplate cmp_node_inpaint_in[] = { + {SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, + { -1, 0, "" } +}; +static bNodeSocketTemplate cmp_node_inpaint_out[] = { + {SOCK_RGBA, 0, N_("Image")}, + { -1, 0, "" } +}; + +static void node_composit_exec_inpaint(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) +{ +} + +void register_node_type_cmp_inpaint(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, CMP_NODE_INPAINT, "Inpaint", NODE_CLASS_OP_FILTER, NODE_OPTIONS); + node_type_socket_templates(&ntype, cmp_node_inpaint_in, cmp_node_inpaint_out); + node_type_size(&ntype, 130, 100, 320); + node_type_exec(&ntype, node_composit_exec_inpaint); + + nodeRegisterType(ttype, &ntype); +} From b9fb8eddddfbc0a77510473c04ba42968d271808 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 29 Jul 2012 18:53:47 +0000 Subject: [PATCH 033/160] style cleanup --- .../operations/COM_InpaintOperation.cpp | 49 ++++++++++--------- .../operations/COM_InpaintOperation.h | 6 +-- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/source/blender/compositor/operations/COM_InpaintOperation.cpp b/source/blender/compositor/operations/COM_InpaintOperation.cpp index 2d7bb8a7794..bd0ae584f15 100644 --- a/source/blender/compositor/operations/COM_InpaintOperation.cpp +++ b/source/blender/compositor/operations/COM_InpaintOperation.cpp @@ -58,13 +58,13 @@ void InpaintSimpleOperation::clamp_xy(int & x, int & y) x = 0; } if (x >= width) { - x = width-1; + x = width - 1; } if (y < 0) { y = 0; } if (y >= height) { - y = height -1; + y = height - 1; } } @@ -74,8 +74,8 @@ float InpaintSimpleOperation::get(int x, int y, int component) clamp_xy(x, y); return this->m_cached_buffer[ - y * width * COM_NUMBER_OF_CHANNELS - + x * COM_NUMBER_OF_CHANNELS + component]; + y * width * COM_NUMBER_OF_CHANNELS + + x * COM_NUMBER_OF_CHANNELS + component]; } void InpaintSimpleOperation::set(int x, int y, int component, float v) @@ -83,8 +83,8 @@ void InpaintSimpleOperation::set(int x, int y, int component, float v) int width = this->getWidth(); this->m_cached_buffer[ - y * width * COM_NUMBER_OF_CHANNELS - + x * COM_NUMBER_OF_CHANNELS + component] = v; + y * width * COM_NUMBER_OF_CHANNELS + + x * COM_NUMBER_OF_CHANNELS + component] = v; } int InpaintSimpleOperation::mdist(int x, int y) @@ -94,7 +94,7 @@ int InpaintSimpleOperation::mdist(int x, int y) return this->manhatten_distance[y * width + x]; } -bool InpaintSimpleOperation::next_pixel(int & x,int & y, int & curr, int iters) +bool InpaintSimpleOperation::next_pixel(int & x, int & y, int & curr, int iters) { int width = this->getWidth(); @@ -118,8 +118,8 @@ void InpaintSimpleOperation::calc_manhatten_distance() { int width = this->getWidth(); int height = this->getHeight(); - short * m = this->manhatten_distance = new short[width*height]; - int offsets[width+height+1]; + short *m = this->manhatten_distance = new short[width * height]; + int offsets[width + height + 1]; memset(offsets, 0, sizeof(offsets)); @@ -129,24 +129,24 @@ void InpaintSimpleOperation::calc_manhatten_distance() if (get(i, j, 3) < 1.0) { r = width + height; if (i > 0) - r = MIN2(r, m[j*width+i-1]+1); + r = MIN2(r, m[j * width + i - 1] + 1); if (j > 0) - r = MIN2(r, m[(j-1)*width+i]+1); + r = MIN2(r, m[(j - 1) * width + i] + 1); } - m[j*width+i] = r; + m[j * width + i] = r; } } - for (int j = height-1; j >= 0; j--) { + for (int j = height - 1; j >= 0; j--) { for (int i = width; i >= 0; i--) { - int r = m[j*width+i]; + int r = m[j * width + i]; if (i + 1 < width) - r = MIN2(r, m[j*width+i+1]+1); + r = MIN2(r, m[j * width + i + 1] + 1); if (j + 1 < height) - r = MIN2(r, m[(j+1)*width+i]+1); + r = MIN2(r, m[(j + 1) * width + i] + 1); - m[j*width+i] = r; + m[j * width + i] = r; offsets[r]++; } @@ -155,15 +155,15 @@ void InpaintSimpleOperation::calc_manhatten_distance() offsets[0] = 0; for (int i = 1; i < width + height + 1; i++) { - offsets[i] += offsets[i-1]; + offsets[i] += offsets[i - 1]; } - area_size = offsets[width+height]; + area_size = offsets[width + height]; pixelorder = new int[area_size]; for (int i = 0; i < width * height; i++) { if (m[i] > 0) { - pixelorder[offsets[m[i]-1]++] = i; + pixelorder[offsets[m[i] - 1]++] = i; } } } @@ -210,7 +210,7 @@ void *InpaintSimpleOperation::initializeTileData(rcti *rect) } lockMutex(); if (!this->cached_buffer_ready) { - MemoryBuffer * buf = (MemoryBuffer *)this->m_inputImageProgram->initializeTileData(rect); + MemoryBuffer *buf = (MemoryBuffer *)this->m_inputImageProgram->initializeTileData(rect); this->m_cached_buffer = new float[this->getWidth() * this->getHeight() * COM_NUMBER_OF_CHANNELS]; memcpy(this->m_cached_buffer, buf->getBuffer(), this->getWidth() * this->getHeight() * COM_NUMBER_OF_CHANNELS * sizeof(float)); @@ -218,7 +218,7 @@ void *InpaintSimpleOperation::initializeTileData(rcti *rect) calc_manhatten_distance(); int curr = 0; - int x,y; + int x, y; while (next_pixel(x, y, curr, this->m_iterations)) { @@ -234,7 +234,7 @@ void *InpaintSimpleOperation::initializeTileData(rcti *rect) void InpaintSimpleOperation::executePixel(float *color, int x, int y, void *data) { for (int c = 0; c < 3; c++) { - color[c] = get(x,y,c); + color[c] = get(x, y, c); } color[3] = 1.0f; } @@ -264,7 +264,8 @@ bool InpaintSimpleOperation::determineDependingAreaOfInterest(rcti *input, ReadB { if (this->cached_buffer_ready) { return false; - } else { + } + else { rcti newInput; newInput.xmax = getWidth(); diff --git a/source/blender/compositor/operations/COM_InpaintOperation.h b/source/blender/compositor/operations/COM_InpaintOperation.h index 8ba41a3062d..53cc571a7bd 100644 --- a/source/blender/compositor/operations/COM_InpaintOperation.h +++ b/source/blender/compositor/operations/COM_InpaintOperation.h @@ -36,9 +36,9 @@ protected: float *m_cached_buffer; bool cached_buffer_ready; - int * pixelorder; + int *pixelorder; int area_size; - short * manhatten_distance; + short *manhatten_distance; public: InpaintSimpleOperation(); @@ -68,7 +68,7 @@ private: float get(int x, int y, int component); void set(int x, int y, int component, float v); int mdist(int x, int y); - bool next_pixel(int & x,int & y, int & curr, int iters); + bool next_pixel(int & x, int & y, int & curr, int iters); void pix_step(int x, int y); }; From 595156fd736376d0d8f6def464e531b7e542c349 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 29 Jul 2012 19:02:23 +0000 Subject: [PATCH 034/160] style cleanup: use this->m_* for private members. --- .../operations/COM_InpaintOperation.cpp | 48 +++++++++---------- .../operations/COM_InpaintOperation.h | 8 ++-- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/source/blender/compositor/operations/COM_InpaintOperation.cpp b/source/blender/compositor/operations/COM_InpaintOperation.cpp index bd0ae584f15..94b80f7dbd2 100644 --- a/source/blender/compositor/operations/COM_InpaintOperation.cpp +++ b/source/blender/compositor/operations/COM_InpaintOperation.cpp @@ -31,20 +31,20 @@ InpaintSimpleOperation::InpaintSimpleOperation() : NodeOperation() this->addOutputSocket(COM_DT_COLOR); this->setComplex(true); this->m_inputImageProgram = NULL; - this->pixelorder = NULL; - this->manhatten_distance = NULL; + this->m_pixelorder = NULL; + this->m_manhatten_distance = NULL; this->m_cached_buffer = NULL; - this->cached_buffer_ready = false; + this->m_cached_buffer_ready = false; } void InpaintSimpleOperation::initExecution() { this->m_inputImageProgram = this->getInputSocketReader(0); this->m_cached_buffer = NULL; - this->pixelorder = NULL; - this->manhatten_distance = NULL; + this->m_pixelorder = NULL; + this->m_manhatten_distance = NULL; this->m_cached_buffer = NULL; - this->cached_buffer_ready = false; + this->m_cached_buffer_ready = false; this->initMutex(); } @@ -91,18 +91,18 @@ int InpaintSimpleOperation::mdist(int x, int y) { int width = this->getWidth(); clamp_xy(x, y); - return this->manhatten_distance[y * width + x]; + return this->m_manhatten_distance[y * width + x]; } bool InpaintSimpleOperation::next_pixel(int & x, int & y, int & curr, int iters) { int width = this->getWidth(); - if (curr >= area_size) { + if (curr >= this->m_area_size) { return false; } - int r = this->pixelorder[curr++]; + int r = this->m_pixelorder[curr++]; x = r % width; y = r / width; @@ -118,7 +118,7 @@ void InpaintSimpleOperation::calc_manhatten_distance() { int width = this->getWidth(); int height = this->getHeight(); - short *m = this->manhatten_distance = new short[width * height]; + short *m = this->m_manhatten_distance = new short[width * height]; int offsets[width + height + 1]; memset(offsets, 0, sizeof(offsets)); @@ -158,12 +158,12 @@ void InpaintSimpleOperation::calc_manhatten_distance() offsets[i] += offsets[i - 1]; } - area_size = offsets[width + height]; - pixelorder = new int[area_size]; + this->m_area_size = offsets[width + height]; + this->m_pixelorder = new int[this->m_area_size]; for (int i = 0; i < width * height; i++) { if (m[i] > 0) { - pixelorder[offsets[m[i] - 1]++] = i; + this->m_pixelorder[offsets[m[i] - 1]++] = i; } } } @@ -205,11 +205,11 @@ void InpaintSimpleOperation::pix_step(int x, int y) void *InpaintSimpleOperation::initializeTileData(rcti *rect) { - if (this->cached_buffer_ready) { + if (this->m_cached_buffer_ready) { return this->m_cached_buffer; } lockMutex(); - if (!this->cached_buffer_ready) { + if (!this->m_cached_buffer_ready) { MemoryBuffer *buf = (MemoryBuffer *)this->m_inputImageProgram->initializeTileData(rect); this->m_cached_buffer = new float[this->getWidth() * this->getHeight() * COM_NUMBER_OF_CHANNELS]; @@ -224,7 +224,7 @@ void *InpaintSimpleOperation::initializeTileData(rcti *rect) while (next_pixel(x, y, curr, this->m_iterations)) { pix_step(x, y); } - this->cached_buffer_ready = true; + this->m_cached_buffer_ready = true; } unlockMutex(); @@ -248,21 +248,21 @@ void InpaintSimpleOperation::deinitExecution() this->m_cached_buffer = NULL; } - if (this->pixelorder) { - delete this->pixelorder; - this->pixelorder = NULL; + if (this->m_pixelorder) { + delete this->m_pixelorder; + this->m_pixelorder = NULL; } - if (this->manhatten_distance) { - delete this->manhatten_distance; - this->manhatten_distance = NULL; + if (this->m_manhatten_distance) { + delete this->m_manhatten_distance; + this->m_manhatten_distance = NULL; } - this->cached_buffer_ready = false; + this->m_cached_buffer_ready = false; } bool InpaintSimpleOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) { - if (this->cached_buffer_ready) { + if (this->m_cached_buffer_ready) { return false; } else { diff --git a/source/blender/compositor/operations/COM_InpaintOperation.h b/source/blender/compositor/operations/COM_InpaintOperation.h index 53cc571a7bd..0ff65174161 100644 --- a/source/blender/compositor/operations/COM_InpaintOperation.h +++ b/source/blender/compositor/operations/COM_InpaintOperation.h @@ -34,11 +34,11 @@ protected: int m_iterations; float *m_cached_buffer; - bool cached_buffer_ready; + bool m_cached_buffer_ready; - int *pixelorder; - int area_size; - short *manhatten_distance; + int *m_pixelorder; + int m_area_size; + short *m_manhatten_distance; public: InpaintSimpleOperation(); From 953423e1eddd8cf41457549ce865651c2ddb94ca Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 29 Jul 2012 19:11:00 +0000 Subject: [PATCH 035/160] - fix incorrect array delete use. - replace 1.0f / sqrt(2) with M_SQRT1_2 define. - use mini rather then MIN2. --- .../operations/COM_InpaintOperation.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/source/blender/compositor/operations/COM_InpaintOperation.cpp b/source/blender/compositor/operations/COM_InpaintOperation.cpp index 94b80f7dbd2..2ca2e36bbdc 100644 --- a/source/blender/compositor/operations/COM_InpaintOperation.cpp +++ b/source/blender/compositor/operations/COM_InpaintOperation.cpp @@ -126,12 +126,12 @@ void InpaintSimpleOperation::calc_manhatten_distance() for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { int r = 0; - if (get(i, j, 3) < 1.0) { + if (get(i, j, 3) < 1.0f) { r = width + height; if (i > 0) - r = MIN2(r, m[j * width + i - 1] + 1); + r = mini(r, m[j * width + i - 1] + 1); if (j > 0) - r = MIN2(r, m[(j - 1) * width + i] + 1); + r = mini(r, m[(j - 1) * width + i] + 1); } m[j * width + i] = r; } @@ -142,9 +142,9 @@ void InpaintSimpleOperation::calc_manhatten_distance() int r = m[j * width + i]; if (i + 1 < width) - r = MIN2(r, m[j * width + i + 1] + 1); + r = mini(r, m[j * width + i + 1] + 1); if (j + 1 < height) - r = MIN2(r, m[(j + 1) * width + i] + 1); + r = mini(r, m[(j + 1) * width + i] + 1); m[j * width + i] = r; @@ -182,10 +182,10 @@ void InpaintSimpleOperation::pix_step(int x, int y) for (int dy = -1; dy <= 1; dy++) { if (dx != 0 && dy != 0 && this->mdist(x + dx, y + dy) < d) { - float weight = 1.0f / sqrt(2); + float weight = M_SQRT1_2; /* 1.0f / sqrt(2) */ if (dx == 0 || dy == 0) { - weight = 1; + weight = 1.0f; } for (int c = 0; c < 3; c++) { @@ -244,17 +244,17 @@ void InpaintSimpleOperation::deinitExecution() this->m_inputImageProgram = NULL; this->deinitMutex(); if (this->m_cached_buffer) { - delete this->m_cached_buffer; + delete [] this->m_cached_buffer; this->m_cached_buffer = NULL; } if (this->m_pixelorder) { - delete this->m_pixelorder; + delete [] this->m_pixelorder; this->m_pixelorder = NULL; } if (this->m_manhatten_distance) { - delete this->m_manhatten_distance; + delete [] this->m_manhatten_distance; this->m_manhatten_distance = NULL; } this->m_cached_buffer_ready = false; From 4b4395213eebc7ebc298b17575b6c3f7abd0c0db Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 29 Jul 2012 19:36:09 +0000 Subject: [PATCH 036/160] inpaint - gain some speed by not doing X/Y clamping in inner loops. add assert() so we can ensure its not happening still. --- .../operations/COM_InpaintOperation.cpp | 58 +++++++++++++------ 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/source/blender/compositor/operations/COM_InpaintOperation.cpp b/source/blender/compositor/operations/COM_InpaintOperation.cpp index 2ca2e36bbdc..c727510305e 100644 --- a/source/blender/compositor/operations/COM_InpaintOperation.cpp +++ b/source/blender/compositor/operations/COM_InpaintOperation.cpp @@ -24,6 +24,12 @@ #include "BLI_math.h" #include "COM_OpenCLDevice.h" + +#define ASSERT_XY_RANGE(x, y) \ + BLI_assert(x >= 0 && x < this->getWidth() && \ + y >= 0 && y < this->getHeight()) + + // Inpaint (simple convolve using average of known pixels) InpaintSimpleOperation::InpaintSimpleOperation() : NodeOperation() { @@ -57,13 +63,14 @@ void InpaintSimpleOperation::clamp_xy(int & x, int & y) if (x < 0) { x = 0; } - if (x >= width) { + else if (x >= width) { x = width - 1; } + if (y < 0) { y = 0; } - if (y >= height) { + else if (y >= height) { y = height - 1; } } @@ -72,7 +79,8 @@ float InpaintSimpleOperation::get(int x, int y, int component) { int width = this->getWidth(); - clamp_xy(x, y); + ASSERT_XY_RANGE(x, y); + return this->m_cached_buffer[ y * width * COM_NUMBER_OF_CHANNELS + x * COM_NUMBER_OF_CHANNELS + component]; @@ -82,6 +90,8 @@ void InpaintSimpleOperation::set(int x, int y, int component, float v) { int width = this->getWidth(); + ASSERT_XY_RANGE(x, y); + this->m_cached_buffer[ y * width * COM_NUMBER_OF_CHANNELS + x * COM_NUMBER_OF_CHANNELS + component] = v; @@ -90,7 +100,9 @@ void InpaintSimpleOperation::set(int x, int y, int component, float v) int InpaintSimpleOperation::mdist(int x, int y) { int width = this->getWidth(); - clamp_xy(x, y); + + ASSERT_XY_RANGE(x, y); + return this->m_manhatten_distance[y * width + x]; } @@ -126,6 +138,7 @@ void InpaintSimpleOperation::calc_manhatten_distance() for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { int r = 0; + /* no need to clamp here */ if (get(i, j, 3) < 1.0f) { r = width + height; if (i > 0) @@ -174,26 +187,34 @@ void InpaintSimpleOperation::pix_step(int x, int y) float n = 0; - float pix[3]; - - memset(pix, 0, sizeof(pix)); + float pix[3] = {0.0f, 0.0f, 0.0f}; for (int dx = -1; dx <= 1; dx++) { for (int dy = -1; dy <= 1; dy++) { - if (dx != 0 && dy != 0 && - this->mdist(x + dx, y + dy) < d) { - float weight = M_SQRT1_2; /* 1.0f / sqrt(2) */ + if (dx != 0 && dy != 0) { - if (dx == 0 || dy == 0) { - weight = 1.0f; - } - - for (int c = 0; c < 3; c++) { - float fk = this->get(x + dx, y + dy, c); + int x_ofs = x + dx; + int y_ofs = y + dy; + clamp_xy(x_ofs, y_ofs); - pix[c] += fk * weight; + if (this->mdist(x_ofs, y_ofs) < d) { + + float weight; + + if (dx == 0 || dy == 0) { + weight = 1.0f; + } + else { + weight = M_SQRT1_2; /* 1.0f / sqrt(2) */ + } + + for (int c = 0; c < 3; c++) { + float fk = this->get(x_ofs, y_ofs, c); + + pix[c] += fk * weight; + } + n += weight; } - n += weight; } } } @@ -233,6 +254,7 @@ void *InpaintSimpleOperation::initializeTileData(rcti *rect) void InpaintSimpleOperation::executePixel(float *color, int x, int y, void *data) { + clamp_xy(x, y); for (int c = 0; c < 3; c++) { color[c] = get(x, y, c); } From 24dae0f0e83fe9743c6cfaf2d394cd72a893f722 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 29 Jul 2012 20:00:16 +0000 Subject: [PATCH 037/160] max value for distance was larger then a short. --- source/blender/makesrna/intern/rna_nodetree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 30b7a439025..4eb6bb8ab6e 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -2135,7 +2135,7 @@ static void def_cmp_inpaint(StructRNA *srna) prop = RNA_def_property(srna, "distance", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom2"); - RNA_def_property_range(prop, 1, 100000); + RNA_def_property_range(prop, 1, 10000); RNA_def_property_ui_text(prop, "Distance", "Distance to inpaint (number of iterations)"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } From 0c6c907cf73d5b90ecc5a5f1dad1693560f22c30 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 30 Jul 2012 08:08:04 +0000 Subject: [PATCH 038/160] Tag unused variables --- source/blender/nodes/composite/nodes/node_composite_inpaint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/nodes/composite/nodes/node_composite_inpaint.c b/source/blender/nodes/composite/nodes/node_composite_inpaint.c index e792ef0a95f..dc4177bd2a4 100644 --- a/source/blender/nodes/composite/nodes/node_composite_inpaint.c +++ b/source/blender/nodes/composite/nodes/node_composite_inpaint.c @@ -44,7 +44,7 @@ static bNodeSocketTemplate cmp_node_inpaint_out[] = { { -1, 0, "" } }; -static void node_composit_exec_inpaint(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) +static void node_composit_exec_inpaint(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **UNUSED(in), bNodeStack **UNUSED(out)) { } From 1a062e28af9521d1bfa40f94a693f2a544068631 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 30 Jul 2012 10:35:34 +0000 Subject: [PATCH 039/160] Color management: fix crash in partial display buffer update Crash was caused by the difference in how compositor walks tile rectangles and how they were walked in partial update function: compositor excludes right / top bound and partial update handled it which lead to reading / writing to wrong memory. Switch partial update routines to the same logic as it's used in tile compositor, which made it kind of unified with render rectangle update. --- source/blender/editors/render/render_internal.c | 2 +- source/blender/imbuf/intern/colormanagement.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 3d867bd85a5..9309e3e5ac5 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -153,7 +153,7 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat xmax, ymax, ibuf->x, rr->rectx); IMB_partial_display_buffer_update(ibuf, rectf, rr->rectx, rxmin, rymin, - rxmin, rymin, rxmin + xmax - 1, rymin + ymax - 1); + rxmin, rymin, rxmin + xmax, rymin + ymax); } /* ****************************** render invoking ***************** */ diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 7e48cc36656..055eb6abc81 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1789,8 +1789,8 @@ static void partial_buffer_update_rect(unsigned char *display_buffer, const floa { int x, y; - for (y = ymin; y <= ymax; y++) { - for (x = xmin; x <= xmax; x++) { + for (y = ymin; y < ymax; y++) { + for (x = xmin; x < xmax; x++) { int display_index = (y * display_stride + x) * channels; int linear_index = ((y - linear_offset_y) * linear_stride + (x - linear_offset_x)) * channels; float pixel[4]; From b8c3f59e92f906de3f4f90cbca50f41dd0599a8c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 30 Jul 2012 15:26:06 +0000 Subject: [PATCH 040/160] Tomato Cycles: resolve textures limit when using CPU render Remove limit for number of textures when using CPU rendering, so huge scenes from Mango could be rendered properly. Re-arranged float and bytes textures for this, so now float textures goes before byte. This is needed to make alignment stuff easier for variable number of textures. Also replace code-generated CPU kernel structure's members with an array, which makes it easier to access textures without adding bunch of cases in switch. Should be no functional changes when rendering with GPU or OpenCL devices. --- intern/cycles/blender/blender_session.cpp | 2 +- intern/cycles/kernel/kernel.cpp | 110 ++-------------------- intern/cycles/kernel/kernel_compat_cpu.h | 2 +- intern/cycles/kernel/kernel_globals.h | 7 +- intern/cycles/kernel/kernel_textures.h | 24 ++--- intern/cycles/kernel/svm/svm_image.h | 24 +++-- intern/cycles/render/image.cpp | 79 +++++++++------- intern/cycles/render/image.h | 13 ++- intern/cycles/render/scene.cpp | 5 +- intern/cycles/render/scene.h | 7 +- 10 files changed, 102 insertions(+), 171 deletions(-) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 5b4260de9e5..e187fe8740c 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -86,7 +86,7 @@ void BlenderSession::create_session() last_progress = -1.0f; /* create scene */ - scene = new Scene(scene_params); + scene = new Scene(scene_params, session_params.device); /* create sync */ sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background); diff --git a/intern/cycles/kernel/kernel.cpp b/intern/cycles/kernel/kernel.cpp index 667db1e5f03..62d79bdd946 100644 --- a/intern/cycles/kernel/kernel.cpp +++ b/intern/cycles/kernel/kernel.cpp @@ -87,14 +87,10 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t else if(strstr(name, "__tex_image_float")) { texture_image_float4 *tex = NULL; int id = atoi(name + strlen("__tex_image_float_")); + int array_index = id; - switch(id) { - case 95: tex = &kg->__tex_image_float_095; break; - case 96: tex = &kg->__tex_image_float_096; break; - case 97: tex = &kg->__tex_image_float_097; break; - case 98: tex = &kg->__tex_image_float_098; break; - case 99: tex = &kg->__tex_image_float_099; break; - default: break; + if (array_index >= 0 && array_index < MAX_FLOAT_IMAGES) { + tex = &kg->texture_float_images[array_index]; } if(tex) { @@ -106,104 +102,10 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t else if(strstr(name, "__tex_image")) { texture_image_uchar4 *tex = NULL; int id = atoi(name + strlen("__tex_image_")); + int array_index = id - MAX_FLOAT_IMAGES; - switch(id) { - case 0: tex = &kg->__tex_image_000; break; - case 1: tex = &kg->__tex_image_001; break; - case 2: tex = &kg->__tex_image_002; break; - case 3: tex = &kg->__tex_image_003; break; - case 4: tex = &kg->__tex_image_004; break; - case 5: tex = &kg->__tex_image_005; break; - case 6: tex = &kg->__tex_image_006; break; - case 7: tex = &kg->__tex_image_007; break; - case 8: tex = &kg->__tex_image_008; break; - case 9: tex = &kg->__tex_image_009; break; - case 10: tex = &kg->__tex_image_010; break; - case 11: tex = &kg->__tex_image_011; break; - case 12: tex = &kg->__tex_image_012; break; - case 13: tex = &kg->__tex_image_013; break; - case 14: tex = &kg->__tex_image_014; break; - case 15: tex = &kg->__tex_image_015; break; - case 16: tex = &kg->__tex_image_016; break; - case 17: tex = &kg->__tex_image_017; break; - case 18: tex = &kg->__tex_image_018; break; - case 19: tex = &kg->__tex_image_019; break; - case 20: tex = &kg->__tex_image_020; break; - case 21: tex = &kg->__tex_image_021; break; - case 22: tex = &kg->__tex_image_022; break; - case 23: tex = &kg->__tex_image_023; break; - case 24: tex = &kg->__tex_image_024; break; - case 25: tex = &kg->__tex_image_025; break; - case 26: tex = &kg->__tex_image_026; break; - case 27: tex = &kg->__tex_image_027; break; - case 28: tex = &kg->__tex_image_028; break; - case 29: tex = &kg->__tex_image_029; break; - case 30: tex = &kg->__tex_image_030; break; - case 31: tex = &kg->__tex_image_031; break; - case 32: tex = &kg->__tex_image_032; break; - case 33: tex = &kg->__tex_image_033; break; - case 34: tex = &kg->__tex_image_034; break; - case 35: tex = &kg->__tex_image_035; break; - case 36: tex = &kg->__tex_image_036; break; - case 37: tex = &kg->__tex_image_037; break; - case 38: tex = &kg->__tex_image_038; break; - case 39: tex = &kg->__tex_image_039; break; - case 40: tex = &kg->__tex_image_040; break; - case 41: tex = &kg->__tex_image_041; break; - case 42: tex = &kg->__tex_image_042; break; - case 43: tex = &kg->__tex_image_043; break; - case 44: tex = &kg->__tex_image_044; break; - case 45: tex = &kg->__tex_image_045; break; - case 46: tex = &kg->__tex_image_046; break; - case 47: tex = &kg->__tex_image_047; break; - case 48: tex = &kg->__tex_image_048; break; - case 49: tex = &kg->__tex_image_049; break; - case 50: tex = &kg->__tex_image_050; break; - case 51: tex = &kg->__tex_image_051; break; - case 52: tex = &kg->__tex_image_052; break; - case 53: tex = &kg->__tex_image_053; break; - case 54: tex = &kg->__tex_image_054; break; - case 55: tex = &kg->__tex_image_055; break; - case 56: tex = &kg->__tex_image_056; break; - case 57: tex = &kg->__tex_image_057; break; - case 58: tex = &kg->__tex_image_058; break; - case 59: tex = &kg->__tex_image_059; break; - case 60: tex = &kg->__tex_image_060; break; - case 61: tex = &kg->__tex_image_061; break; - case 62: tex = &kg->__tex_image_062; break; - case 63: tex = &kg->__tex_image_063; break; - case 64: tex = &kg->__tex_image_064; break; - case 65: tex = &kg->__tex_image_065; break; - case 66: tex = &kg->__tex_image_066; break; - case 67: tex = &kg->__tex_image_067; break; - case 68: tex = &kg->__tex_image_068; break; - case 69: tex = &kg->__tex_image_069; break; - case 70: tex = &kg->__tex_image_070; break; - case 71: tex = &kg->__tex_image_071; break; - case 72: tex = &kg->__tex_image_072; break; - case 73: tex = &kg->__tex_image_073; break; - case 74: tex = &kg->__tex_image_074; break; - case 75: tex = &kg->__tex_image_075; break; - case 76: tex = &kg->__tex_image_076; break; - case 77: tex = &kg->__tex_image_077; break; - case 78: tex = &kg->__tex_image_078; break; - case 79: tex = &kg->__tex_image_079; break; - case 80: tex = &kg->__tex_image_080; break; - case 81: tex = &kg->__tex_image_081; break; - case 82: tex = &kg->__tex_image_082; break; - case 83: tex = &kg->__tex_image_083; break; - case 84: tex = &kg->__tex_image_084; break; - case 85: tex = &kg->__tex_image_085; break; - case 86: tex = &kg->__tex_image_086; break; - case 87: tex = &kg->__tex_image_087; break; - case 88: tex = &kg->__tex_image_088; break; - case 89: tex = &kg->__tex_image_089; break; - case 90: tex = &kg->__tex_image_090; break; - case 91: tex = &kg->__tex_image_091; break; - case 92: tex = &kg->__tex_image_092; break; - case 93: tex = &kg->__tex_image_093; break; - case 94: tex = &kg->__tex_image_094; break; - default: break; + if (array_index >= 0 && array_index < MAX_BYTE_IMAGES) { + tex = &kg->texture_byte_images[array_index]; } if(tex) { diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h index cc8f1f3323b..45f653a686c 100644 --- a/intern/cycles/kernel/kernel_compat_cpu.h +++ b/intern/cycles/kernel/kernel_compat_cpu.h @@ -158,7 +158,7 @@ typedef texture_image texture_image_uchar4; #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_image_interp(tex, x, y) (kg->tex.interp(x, y)) +#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_globals.h b/intern/cycles/kernel/kernel_globals.h index a99fffbc519..1e56c11ab90 100644 --- a/intern/cycles/kernel/kernel_globals.h +++ b/intern/cycles/kernel/kernel_globals.h @@ -35,10 +35,15 @@ CCL_NAMESPACE_BEGIN #ifdef __KERNEL_CPU__ +#define MAX_BYTE_IMAGES 512 +#define MAX_FLOAT_IMAGES 5 + typedef struct KernelGlobals { + texture_image_uchar4 texture_byte_images[MAX_BYTE_IMAGES]; + texture_image_float4 texture_float_images[MAX_FLOAT_IMAGES]; #define KERNEL_TEX(type, ttype, name) ttype name; -#define KERNEL_IMAGE_TEX(type, ttype, name) ttype name; +#define KERNEL_IMAGE_TEX(type, ttype, name) #include "kernel_textures.h" KernelData __data; diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index c1b8eed3dff..4855a948c6e 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -66,12 +66,14 @@ KERNEL_TEX(float, texture_float, __filter_table) /* sobol */ KERNEL_TEX(uint, texture_uint, __sobol_directions) +/* full-float image */ +KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_000) +KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_001) +KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_002) +KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_003) +KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_004) + /* image */ -KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_000) -KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_001) -KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_002) -KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_003) -KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_004) KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_005) KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_006) KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_007) @@ -162,13 +164,11 @@ KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_091) KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_092) KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_093) KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_094) - -/* full-float image */ -KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_095) -KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_096) -KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_097) -KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_098) -KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_099) +KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_095) +KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_096) +KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_097) +KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_098) +KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_099) /* packed image (opencl) */ KERNEL_TEX(uchar4, texture_uchar4, __tex_image_packed) diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index 8df1889d270..662419418e3 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -97,6 +97,9 @@ __device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, u { float4 r; +#ifdef __KERNEL_CPU__ + r = kernel_tex_image_interp(id, x, y); +#else /* not particularly proud of this massive switch, what are the * alternatives? * - use a single big 1D texture, and do our own lookup/filtering @@ -107,11 +110,11 @@ __device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, u * we still need some for other storage */ switch(id) { - case 0: r = kernel_tex_image_interp(__tex_image_000, x, y); break; - case 1: r = kernel_tex_image_interp(__tex_image_001, x, y); break; - case 2: r = kernel_tex_image_interp(__tex_image_002, x, y); break; - case 3: r = kernel_tex_image_interp(__tex_image_003, x, y); break; - case 4: r = kernel_tex_image_interp(__tex_image_004, x, y); break; + case 0: r = kernel_tex_image_interp(__tex_image_float_000, x, y); break; + case 1: r = kernel_tex_image_interp(__tex_image_float_001, x, y); break; + case 2: r = kernel_tex_image_interp(__tex_image_float_002, x, y); break; + case 3: r = kernel_tex_image_interp(__tex_image_float_003, x, y); break; + case 4: r = kernel_tex_image_interp(__tex_image_float_004, x, y); break; case 5: r = kernel_tex_image_interp(__tex_image_005, x, y); break; case 6: r = kernel_tex_image_interp(__tex_image_006, x, y); break; case 7: r = kernel_tex_image_interp(__tex_image_007, x, y); break; @@ -202,15 +205,16 @@ __device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, u case 92: r = kernel_tex_image_interp(__tex_image_092, x, y); break; case 93: r = kernel_tex_image_interp(__tex_image_093, x, y); break; case 94: r = kernel_tex_image_interp(__tex_image_094, x, y); break; - case 95: r = kernel_tex_image_interp(__tex_image_float_095, x, y); break; - case 96: r = kernel_tex_image_interp(__tex_image_float_096, x, y); break; - case 97: r = kernel_tex_image_interp(__tex_image_float_097, x, y); break; - case 98: r = kernel_tex_image_interp(__tex_image_float_098, x, y); break; - case 99: r = kernel_tex_image_interp(__tex_image_float_099, x, y); break; + case 95: r = kernel_tex_image_interp(__tex_image_095, x, y); break; + case 96: r = kernel_tex_image_interp(__tex_image_096, x, y); break; + case 97: r = kernel_tex_image_interp(__tex_image_097, x, y); break; + case 98: r = kernel_tex_image_interp(__tex_image_098, x, y); break; + case 99: r = kernel_tex_image_interp(__tex_image_099, x, y); break; default: kernel_assert(0); return make_float4(0.0f, 0.0f, 0.0f, 0.0f); } +#endif if(srgb) { r.x = color_srgb_to_scene_linear(r.x); diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index e2c760f0114..4ee024dd52a 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -36,6 +36,10 @@ ImageManager::ImageManager() need_update = true; pack_images = false; osl_texture_system = NULL; + + tex_num_images = TEX_NUM_IMAGES; + tex_num_float_images = TEX_NUM_FLOAT_IMAGES; + tex_image_byte_start = TEX_IMAGE_BYTE_START; } ImageManager::~ImageManager() @@ -56,6 +60,13 @@ void ImageManager::set_osl_texture_system(void *texture_system) osl_texture_system = texture_system; } +void ImageManager::set_extended_image_limits(void) +{ + tex_num_images = TEX_EXTENDED_NUM_IMAGES; + tex_num_float_images = TEX_EXTENDED_NUM_FLOAT_IMAGES; + tex_image_byte_start = TEX_EXTENDED_IMAGE_BYTE_START; +} + static bool is_float_image(const string& filename) { ImageInput *in = ImageInput::create(filename); @@ -97,7 +108,7 @@ int ImageManager::add_image(const string& filename, bool& is_float) for(slot = 0; slot < float_images.size(); slot++) { if(float_images[slot] && float_images[slot]->filename == filename) { float_images[slot]->users++; - return slot+TEX_IMAGE_FLOAT_START; + return slot; } } @@ -110,8 +121,8 @@ int ImageManager::add_image(const string& filename, bool& is_float) if(slot == float_images.size()) { /* max images limit reached */ if(float_images.size() == TEX_NUM_FLOAT_IMAGES) { - printf("ImageManager::add_image: byte image limit reached %d, skipping '%s'\n", - TEX_NUM_IMAGES, filename.c_str()); + printf("ImageManager::add_image: float image limit reached %d, skipping '%s'\n", + tex_num_float_images, filename.c_str()); return -1; } @@ -125,14 +136,12 @@ int ImageManager::add_image(const string& filename, bool& is_float) img->users = 1; float_images[slot] = img; - /* report slot out of total set of textures */ - slot += TEX_IMAGE_FLOAT_START; } else { for(slot = 0; slot < images.size(); slot++) { if(images[slot] && images[slot]->filename == filename) { images[slot]->users++; - return slot; + return slot+tex_image_byte_start; } } @@ -144,9 +153,9 @@ int ImageManager::add_image(const string& filename, bool& is_float) if(slot == images.size()) { /* max images limit reached */ - if(images.size() == TEX_NUM_IMAGES) { + if(images.size() == tex_num_images) { printf("ImageManager::add_image: byte image limit reached %d, skipping '%s'\n", - TEX_NUM_IMAGES, filename.c_str()); + tex_num_images, filename.c_str()); return -1; } @@ -160,6 +169,8 @@ int ImageManager::add_image(const string& filename, bool& is_float) img->users = 1; images[slot] = img; + + slot += tex_image_byte_start; } need_update = true; @@ -235,8 +246,6 @@ bool ImageManager::file_load_image(Image *img, device_vector& tex_img) return false; } - printf("loading byte image: '%s' %dx%d\n", img->filename.c_str(), width, height); - /* read RGBA pixels */ uchar *pixels = (uchar*)tex_img.resize(width, height); int scanlinesize = width*components*sizeof(uchar); @@ -299,8 +308,6 @@ bool ImageManager::file_load_float_image(Image *img, device_vector& tex_ return false; } - printf("loading float image: '%s' %dx%d\n", img->filename.c_str(), width, height); - /* read RGBA pixels */ float *pixels = (float*)tex_img.resize(width, height); int scanlinesize = width*components*sizeof(float); @@ -344,20 +351,20 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl Image *img; bool is_float; - if(slot < TEX_IMAGE_FLOAT_START) { - img = images[slot]; + if(slot >= tex_image_byte_start) { + img = images[slot - tex_image_byte_start]; is_float = false; } else { - img = float_images[slot - TEX_IMAGE_FLOAT_START]; + img = float_images[slot]; is_float = true; } if(is_float) { - string filename = path_filename(float_images[slot - TEX_IMAGE_FLOAT_START]->filename); + string filename = path_filename(float_images[slot]->filename); progress->set_status("Updating Images", "Loading " + filename); - device_vector& tex_img = dscene->tex_float_image[slot - TEX_IMAGE_FLOAT_START]; + device_vector& tex_img = dscene->tex_float_image[slot]; if(tex_img.device_pointer) device->tex_free(tex_img); @@ -381,10 +388,10 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl device->tex_alloc(name.c_str(), tex_img, true, true); } else { - string filename = path_filename(images[slot]->filename); + string filename = path_filename(images[slot - tex_image_byte_start]->filename); progress->set_status("Updating Images", "Loading " + filename); - device_vector& tex_img = dscene->tex_image[slot]; + device_vector& tex_img = dscene->tex_image[slot - tex_image_byte_start]; if(tex_img.device_pointer) device->tex_free(tex_img); @@ -416,12 +423,12 @@ void ImageManager::device_free_image(Device *device, DeviceScene *dscene, int sl Image *img; bool is_float; - if(slot < TEX_IMAGE_FLOAT_START) { - img = images[slot]; + if(slot >= tex_image_byte_start) { + img = images[slot - tex_image_byte_start]; is_float = false; } else { - img = float_images[slot - TEX_IMAGE_FLOAT_START]; + img = float_images[slot]; is_float = true; } @@ -433,18 +440,18 @@ void ImageManager::device_free_image(Device *device, DeviceScene *dscene, int sl #endif } else if(is_float) { - device->tex_free(dscene->tex_float_image[slot - TEX_IMAGE_FLOAT_START]); - dscene->tex_float_image[slot - TEX_IMAGE_FLOAT_START].clear(); + device->tex_free(dscene->tex_float_image[slot]); + dscene->tex_float_image[slot].clear(); - delete float_images[slot - TEX_IMAGE_FLOAT_START]; - float_images[slot - TEX_IMAGE_FLOAT_START] = NULL; + delete float_images[slot]; + float_images[slot] = NULL; } else { - device->tex_free(dscene->tex_image[slot]); - dscene->tex_image[slot].clear(); + device->tex_free(dscene->tex_image[slot - tex_image_byte_start]); + dscene->tex_image[slot - tex_image_byte_start].clear(); - delete images[slot]; - images[slot] = NULL; + delete images[slot - tex_image_byte_start]; + images[slot - tex_image_byte_start] = NULL; } } } @@ -461,11 +468,11 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress& continue; if(images[slot]->users == 0) { - device_free_image(device, dscene, slot); + device_free_image(device, dscene, slot + tex_image_byte_start); } else if(images[slot]->need_load) { if(!osl_texture_system) - pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, slot, &progress)); + pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, slot + tex_image_byte_start, &progress)); } } @@ -474,11 +481,11 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress& continue; if(float_images[slot]->users == 0) { - device_free_image(device, dscene, slot + TEX_IMAGE_FLOAT_START); + device_free_image(device, dscene, slot); } else if(float_images[slot]->need_load) { if(!osl_texture_system) - pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, slot + TEX_IMAGE_FLOAT_START, &progress)); + pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, slot, &progress)); } } @@ -530,9 +537,9 @@ void ImageManager::device_pack_images(Device *device, DeviceScene *dscene, Progr void ImageManager::device_free(Device *device, DeviceScene *dscene) { for(size_t slot = 0; slot < images.size(); slot++) - device_free_image(device, dscene, slot); + device_free_image(device, dscene, slot + tex_image_byte_start); for(size_t slot = 0; slot < float_images.size(); slot++) - device_free_image(device, dscene, slot + TEX_IMAGE_FLOAT_START); + device_free_image(device, dscene, slot); device->tex_free(dscene->tex_image_packed); dscene->tex_image_packed.clear(); diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index ef046cfcafb..04a705c27bf 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -28,8 +28,11 @@ CCL_NAMESPACE_BEGIN #define TEX_NUM_FLOAT_IMAGES 5 #define TEX_NUM_IMAGES 95 -#define TEX_IMAGE_MAX (TEX_NUM_IMAGES + TEX_NUM_FLOAT_IMAGES) -#define TEX_IMAGE_FLOAT_START TEX_NUM_IMAGES +#define TEX_IMAGE_BYTE_START TEX_NUM_FLOAT_IMAGES + +#define TEX_EXTENDED_NUM_FLOAT_IMAGES 5 +#define TEX_EXTENDED_NUM_IMAGES 512 +#define TEX_EXTENDED_IMAGE_BYTE_START TEX_EXTENDED_NUM_FLOAT_IMAGES /* color to use when textures are not found */ #define TEX_IMAGE_MISSING_R 1 @@ -55,9 +58,15 @@ public: void set_osl_texture_system(void *texture_system); void set_pack_images(bool pack_images_); + void set_extended_image_limits(void); + bool need_update; private: + int tex_num_images; + int tex_num_float_images; + int tex_image_byte_start; + struct Image { string filename; diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 45c8a05c27d..33ebd7a59ef 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -37,7 +37,7 @@ CCL_NAMESPACE_BEGIN -Scene::Scene(const SceneParams& params_) +Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_) : params(params_) { device = NULL; @@ -53,6 +53,9 @@ Scene::Scene(const SceneParams& params_) integrator = new Integrator(); image_manager = new ImageManager(); shader_manager = ShaderManager::create(this); + + if (device_info_.type == DEVICE_CPU) + image_manager->set_extended_image_limits(); } Scene::~Scene() diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 8b9944cb76e..1a9540b319d 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -37,6 +37,7 @@ class AttributeRequestSet; class Background; class Camera; class Device; +class DeviceInfo; class Film; class Filter; class Integrator; @@ -97,8 +98,8 @@ public: device_vector sobol_directions; /* images */ - device_vector tex_image[TEX_NUM_IMAGES]; - device_vector tex_float_image[TEX_NUM_FLOAT_IMAGES]; + device_vector tex_image[TEX_EXTENDED_NUM_IMAGES]; + device_vector tex_float_image[TEX_EXTENDED_NUM_FLOAT_IMAGES]; /* opencl images */ device_vector tex_image_packed; @@ -179,7 +180,7 @@ public: /* mutex must be locked manually by callers */ thread_mutex mutex; - Scene(const SceneParams& params); + Scene(const SceneParams& params, const DeviceInfo& device_info); ~Scene(); void device_update(Device *device, Progress& progress); From 3ea4c49ef70fbd47b991cf93d8fc9797d8548e28 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 30 Jul 2012 16:07:30 +0000 Subject: [PATCH 041/160] Color management: abort execution when error happens in debug mode --- intern/opencolorio/ocio_capi.cpp | 59 +++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/intern/opencolorio/ocio_capi.cpp b/intern/opencolorio/ocio_capi.cpp index 0eafe12ed5b..15ef0dd25e9 100644 --- a/intern/opencolorio/ocio_capi.cpp +++ b/intern/opencolorio/ocio_capi.cpp @@ -32,6 +32,25 @@ #define OCIO_CAPI_IMPLEMENTATION #include "ocio_capi.h" +#ifdef NDEBUG +# define OCIO_abort() +#else +# include +# define OCIO_abort() abort() +#endif + +static void OCIO_reportError(const char *err) +{ + std::cerr << "OpenColorIO Error: " << err << std::endl; + + OCIO_abort(); +} + +static void OCIO_reportException(Exception &exception) +{ + OCIO_reportError(exception.what()); +} + ConstConfigRcPtr *OCIO_getCurrentConfig(void) { ConstConfigRcPtr *config = new ConstConfigRcPtr(); @@ -42,7 +61,7 @@ ConstConfigRcPtr *OCIO_getCurrentConfig(void) return config; } catch (Exception &exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + OCIO_reportException(exception); } return NULL; @@ -53,8 +72,8 @@ void OCIO_setCurrentConfig(const ConstConfigRcPtr *config) try { SetCurrentConfig(*config); } - catch (Exception & exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + catch (Exception &exception) { + OCIO_reportException(exception); } } @@ -69,7 +88,7 @@ ConstConfigRcPtr *OCIO_configCreateFromEnv(void) return config; } catch (Exception &exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + OCIO_reportException(exception); } return NULL; @@ -87,7 +106,7 @@ ConstConfigRcPtr *OCIO_configCreateFromFile(const char *filename) return config; } catch (Exception &exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + OCIO_reportException(exception); } return NULL; @@ -104,7 +123,7 @@ int OCIO_configGetNumColorSpaces(ConstConfigRcPtr *config) return (*config)->getNumColorSpaces(); } catch (Exception &exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + OCIO_reportException(exception); } return 0; @@ -116,7 +135,7 @@ const char *OCIO_configGetColorSpaceNameByIndex(ConstConfigRcPtr *config, int in return (*config)->getColorSpaceNameByIndex(index); } catch (Exception &exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + OCIO_reportException(exception); } return NULL; @@ -133,7 +152,7 @@ ConstColorSpaceRcPtr *OCIO_configGetColorSpace(ConstConfigRcPtr *config, const c return cs; } catch (Exception &exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + OCIO_reportException(exception); delete cs; } @@ -146,7 +165,7 @@ int OCIO_configGetIndexForColorSpace(ConstConfigRcPtr *config, const char *name) return (*config)->getIndexForColorSpace(name); } catch (Exception &exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + OCIO_reportException(exception); } return -1; @@ -158,7 +177,7 @@ const char *OCIO_configGetDefaultDisplay(ConstConfigRcPtr *config) return (*config)->getDefaultDisplay(); } catch (Exception &exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + OCIO_reportException(exception); } return NULL; @@ -170,7 +189,7 @@ int OCIO_configGetNumDisplays(ConstConfigRcPtr* config) return (*config)->getNumDisplays(); } catch (Exception &exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + OCIO_reportException(exception); } return 0; @@ -182,7 +201,7 @@ const char *OCIO_configGetDisplay(ConstConfigRcPtr *config, int index) return (*config)->getDisplay(index); } catch (Exception &exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + OCIO_reportException(exception); } return NULL; @@ -194,7 +213,7 @@ const char *OCIO_configGetDefaultView(ConstConfigRcPtr *config, const char *disp return (*config)->getDefaultView(display); } catch (Exception &exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + OCIO_reportException(exception); } return NULL; @@ -206,7 +225,7 @@ int OCIO_configGetNumViews(ConstConfigRcPtr *config, const char *display) return (*config)->getNumViews(display); } catch (Exception &exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + OCIO_reportException(exception); } return 0; @@ -218,7 +237,7 @@ const char *OCIO_configGetView(ConstConfigRcPtr *config, const char *display, in return (*config)->getView(display, index); } catch (Exception &exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + OCIO_reportException(exception); } return NULL; @@ -230,7 +249,7 @@ const char *OCIO_configGetDisplayColorSpaceName(ConstConfigRcPtr *config, const return (*config)->getDisplayColorSpaceName(display, view); } catch (Exception &exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + OCIO_reportException(exception); } return NULL; @@ -252,7 +271,7 @@ ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(ConstConfigRcPtr *config, return p; } catch (Exception &exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + OCIO_reportException(exception); } return 0; @@ -269,7 +288,7 @@ ConstProcessorRcPtr *OCIO_configGetProcessor(ConstConfigRcPtr *config, ConstTran return p; } catch (Exception &exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + OCIO_reportException(exception); } return NULL; @@ -281,7 +300,7 @@ void OCIO_processorApply(ConstProcessorRcPtr *processor, PackedImageDesc *img) (*processor)->apply(*img); } catch (Exception &exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + OCIO_reportException(exception); } } @@ -364,7 +383,7 @@ PackedImageDesc *OCIO_createPackedImageDesc(float *data, long width, long height return id; } catch (Exception &exception) { - std::cerr << "OpenColorIO Error: " << exception.what() << std::endl; + OCIO_reportException(exception); } return NULL; From 2feac552ebbe22d6ddbb4be0d830238459dc678d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 30 Jul 2012 16:07:37 +0000 Subject: [PATCH 042/160] Color management: initialize input color space for newly opening images --- source/blender/blenkernel/BKE_colortools.h | 5 +++++ source/blender/blenkernel/intern/colortools.c | 11 +++++++++++ source/blender/blenkernel/intern/image.c | 5 +++++ 3 files changed, 21 insertions(+) diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index 345ec68f457..d9b6e874c25 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -31,6 +31,7 @@ * \ingroup bke */ +struct ColorManagedColorspaceSettings; struct ColorManagedDisplaySettings; struct ColorManagedViewSettings; struct CurveMapping; @@ -90,4 +91,8 @@ void BKE_color_managed_view_settings_init(struct ColorManagedViewSettings *setti void BKE_color_managed_view_settings_copy(struct ColorManagedViewSettings *new_settings, const struct ColorManagedViewSettings *settings); +void BKE_color_managed_colorspace_settings_init(struct ColorManagedColorspaceSettings *colorspace_settings); +void BKE_color_managed_colorspace_settings_copy(struct ColorManagedColorspaceSettings *colorspace_settings, + const struct ColorManagedColorspaceSettings *settings); + #endif diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index c489c08f4df..ec9198590ed 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -1244,3 +1244,14 @@ void BKE_color_managed_view_settings_copy(ColorManagedViewSettings *new_settings new_settings->exposure = settings->exposure; new_settings->gamma = settings->gamma; } + +void BKE_color_managed_colorspace_settings_init(ColorManagedColorspaceSettings *colorspace_settings) +{ + BLI_strncpy(colorspace_settings->name, "NONE", sizeof(colorspace_settings->name)); +} + +void BKE_color_managed_colorspace_settings_copy(ColorManagedColorspaceSettings *colorspace_settings, + const ColorManagedColorspaceSettings *settings) +{ + BLI_strncpy(colorspace_settings->name, settings->name, sizeof(colorspace_settings->name)); +} diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index fa0070de76b..e65099cc621 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -71,6 +71,7 @@ #include "BLI_bpath.h" #include "BKE_bmfont.h" +#include "BKE_colortools.h" #include "BKE_global.h" #include "BKE_icons.h" #include "BKE_image.h" @@ -245,6 +246,8 @@ static Image *image_alloc(const char *name, short source, short type) ima->source = source; ima->type = type; + + BKE_color_managed_colorspace_settings_init(&ima->colorspace_settings); } return ima; } @@ -327,6 +330,8 @@ Image *BKE_image_copy(Image *ima) nima->aspx = ima->aspx; nima->aspy = ima->aspy; + BKE_color_managed_colorspace_settings_copy(&nima->colorspace_settings, &ima->colorspace_settings); + return nima; } From 60044b12da8e6605211fa1921ac2e323c36121be Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 31 Jul 2012 13:15:53 +0000 Subject: [PATCH 043/160] Tomato Cycles: use the same order of parts as Blender Internal --- intern/cycles/render/tile.cpp | 50 +++++++++++++++++++++++++++++++---- intern/cycles/render/tile.h | 3 ++- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index 0898edf18dd..170c22bea77 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -113,16 +113,56 @@ void TileManager::set_tiles() bool TileManager::next_tile(Tile& tile, int device) { - list::iterator iter; + list::iterator iter, best = state.tiles.end(); + int resolution = state.resolution; + int image_w = max(1, params.width/resolution); + int image_h = max(1, params.height/resolution); + + int num = min(image_h, num_devices); + + int device_y = (image_h / num) * device; + int device_h = (device == num - 1) ? image_h - device * (image_h / num) : image_h / num; + + long long int centx = image_w / 2, centy = device_h / 2, tot = 1; + long long int mindist = (long long int) image_w * (long long int) device_h; + + /* find center of rendering tiles, image center counts for 1 too */ for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) { - if(iter->device == device) { - tile = *iter; - state.tiles.erase(iter); - return true; + if(iter->device == device && iter->rendering) { + Tile &cur_tile = *iter; + centx += cur_tile.x + cur_tile.w / 2; + centy += cur_tile.y + cur_tile.h / 2; + tot++; } } + centx /= tot; + centy /= tot; + + /* closest of the non-rendering tiles */ + for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) { + if(iter->device == device && iter->rendering == false) { + Tile &cur_tile = *iter; + + long long int distx = centx - (cur_tile.x + cur_tile.w / 2); + long long int disty = centy - (cur_tile.y + cur_tile.h / 2); + distx = (long long int) sqrt(distx * distx + disty * disty); + + if (distx < mindist) { + best = iter; + mindist = distx; + } + } + } + + if (best != state.tiles.end()) { + best->rendering = true; + tile = *best; + + return true; + } + return false; } diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h index b9d1fb26c00..6786620ceab 100644 --- a/intern/cycles/render/tile.h +++ b/intern/cycles/render/tile.h @@ -32,12 +32,13 @@ class Tile { public: int x, y, w, h; int device; + bool rendering; Tile() {} Tile(int x_, int y_, int w_, int h_, int device_) - : x(x_), y(y_), w(w_), h(h_), device(device_) {} + : x(x_), y(y_), w(w_), h(h_), device(device_), rendering(false) {} }; /* Tile Manager */ From aec620cc28d2f0901a49af2b7a6081cef5765443 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 31 Jul 2012 14:27:14 +0000 Subject: [PATCH 044/160] Resolve compilation error with MSVC --- intern/cycles/render/tile.cpp | 11 ++++++----- .../compositor/operations/COM_InpaintOperation.cpp | 10 +++++++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index 170c22bea77..1b2c6a0b11f 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -19,6 +19,7 @@ #include "tile.h" #include "util_algorithm.h" +#include "util_types.h" CCL_NAMESPACE_BEGIN @@ -124,8 +125,8 @@ bool TileManager::next_tile(Tile& tile, int device) int device_y = (image_h / num) * device; int device_h = (device == num - 1) ? image_h - device * (image_h / num) : image_h / num; - long long int centx = image_w / 2, centy = device_h / 2, tot = 1; - long long int mindist = (long long int) image_w * (long long int) device_h; + int64_t centx = image_w / 2, centy = device_h / 2, tot = 1; + int64_t mindist = (int64_t) image_w * (int64_t) device_h; /* find center of rendering tiles, image center counts for 1 too */ for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) { @@ -145,9 +146,9 @@ bool TileManager::next_tile(Tile& tile, int device) if(iter->device == device && iter->rendering == false) { Tile &cur_tile = *iter; - long long int distx = centx - (cur_tile.x + cur_tile.w / 2); - long long int disty = centy - (cur_tile.y + cur_tile.h / 2); - distx = (long long int) sqrt(distx * distx + disty * disty); + int64_t distx = centx - (cur_tile.x + cur_tile.w / 2); + int64_t disty = centy - (cur_tile.y + cur_tile.h / 2); + distx = (int64_t) sqrt((double)distx * distx + disty * disty); if (distx < mindist) { best = iter; diff --git a/source/blender/compositor/operations/COM_InpaintOperation.cpp b/source/blender/compositor/operations/COM_InpaintOperation.cpp index c727510305e..5b21273e4ab 100644 --- a/source/blender/compositor/operations/COM_InpaintOperation.cpp +++ b/source/blender/compositor/operations/COM_InpaintOperation.cpp @@ -20,10 +20,12 @@ * Monique Dewanchand */ +#include "MEM_guardedalloc.h" + #include "COM_InpaintOperation.h" -#include "BLI_math.h" #include "COM_OpenCLDevice.h" +#include "BLI_math.h" #define ASSERT_XY_RANGE(x, y) \ BLI_assert(x >= 0 && x < this->getWidth() && \ @@ -131,9 +133,9 @@ void InpaintSimpleOperation::calc_manhatten_distance() int width = this->getWidth(); int height = this->getHeight(); short *m = this->m_manhatten_distance = new short[width * height]; - int offsets[width + height + 1]; + int *offsets; - memset(offsets, 0, sizeof(offsets)); + offsets = (int *)MEM_callocN(sizeof(int) * (width + height + 1), "InpaintSimpleOperation offsets"); for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { @@ -179,6 +181,8 @@ void InpaintSimpleOperation::calc_manhatten_distance() this->m_pixelorder[offsets[m[i] - 1]++] = i; } } + + MEM_freeN(offsets); } void InpaintSimpleOperation::pix_step(int x, int y) From de4e940885f20b17a2e527599626105d50cae71d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 1 Aug 2012 14:19:42 +0000 Subject: [PATCH 045/160] Remove mask cache hack added for mango project a while ago We've got new rasterizer which doesn't require cacheing anymore. --- source/blender/blenkernel/intern/mask.c | 47 ----------------- .../blender/blenloader/intern/readblenentry.c | 6 --- source/blender/blenloader/intern/readfile.c | 52 ------------------- source/blender/blenloader/intern/readfile.h | 3 -- source/blender/makesdna/DNA_mask_types.h | 2 - 5 files changed, 110 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index ddba9a7a65b..81800016cbd 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -56,21 +56,6 @@ #include "BKE_movieclip.h" #include "BKE_utildefines.h" -#ifdef USE_MANGO_MASK_CACHE_HACK - -#include "BLI_threads.h" - -typedef struct MaskRasterCache { - float *buffer; - int width, height; - short do_aspect_correct; - short do_mask_aa; - short do_feather; - - ListBase layers; -} MaskRasterCache; -#endif - static MaskSplinePoint *mask_spline_point_next(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point) { if (point == &points_array[spline->tot_point - 1]) { @@ -1560,41 +1545,9 @@ void BKE_mask_layer_free_list(ListBase *masklayers) } -#ifdef USE_MANGO_MASK_CACHE_HACK -void BKE_mask_raster_cache_free(Mask *mask) -{ - MaskRasterCache *cache = mask->raster_cache; - - if (cache) { - MaskLayer *layer; - - layer = cache->layers.first; - while (layer) { - MaskLayer *layer_next = layer->next; - - BKE_mask_layer_free(layer); - layer = layer_next; - } - - MEM_freeN(cache->buffer); - MEM_freeN(cache); - - mask->raster_cache = NULL; - } -} -#endif - void BKE_mask_free(Mask *mask) { BKE_mask_layer_free_list(&mask->masklayers); - -#ifdef USE_MANGO_MASK_CACHE_HACK - if (mask->raster_cache) { - BKE_mask_raster_cache_free(mask); - - mask->raster_cache = NULL; - } -#endif } void BKE_mask_unlink(Main *bmain, Mask *mask) diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c index 04994b5b0de..eb12a7bd837 100644 --- a/source/blender/blenloader/intern/readblenentry.c +++ b/source/blender/blenloader/intern/readblenentry.c @@ -310,9 +310,6 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil /* makes lookup of existing video clips in old main */ blo_make_movieclip_pointer_map(fd, oldmain); - /* makes lookup of existing masks in old main */ - blo_make_mask_pointer_map(fd, oldmain); - bfd = blo_read_file_internal(fd, filename); /* ensures relinked images are not freed */ @@ -321,9 +318,6 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil /* ensures relinked movie clips are not freed */ blo_end_movieclip_pointer_map(fd, oldmain); - /* ensures relinked masks are not freed */ - blo_end_mask_pointer_map(fd, oldmain); - /* move libraries from old main to new main */ if (bfd && mainlist.first != mainlist.last) { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index dd9fcbb9f1a..a9f3f4c36b9 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1090,10 +1090,6 @@ void blo_freefiledata(FileData *fd) oldnewmap_free(fd->imamap); if (fd->movieclipmap) oldnewmap_free(fd->movieclipmap); -#ifdef USE_MANGO_MASK_CACHE_HACK - if (fd->maskmap) - oldnewmap_free(fd->maskmap); -#endif if (fd->libmap && !(fd->flags & FD_FLAGS_NOT_MY_LIBMAP)) oldnewmap_free(fd->libmap); if (fd->bheadmap) @@ -1178,16 +1174,6 @@ static void *newmclipadr(FileData *fd, void *adr) /* used to restor return NULL; } -#ifdef USE_MANGO_MASK_CACHE_HACK -static void *newmaskadr(FileData *fd, void *adr) /* used to restore mask data after undo */ -{ - if (fd->maskmap && adr) - return oldnewmap_lookup_and_inc(fd->maskmap, adr); - return NULL; -} -#endif - - static void *newlibadr(FileData *fd, void *lib, void *adr) /* only lib data */ { return oldnewmap_liblookup(fd->libmap, adr, lib); @@ -1382,39 +1368,6 @@ void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain) } } -#ifdef USE_MANGO_MASK_CACHE_HACK -void blo_make_mask_pointer_map(FileData *fd, Main *oldmain) -{ - Mask *mask; - - fd->maskmap = oldnewmap_new(); - - for (mask = oldmain->mask.first; mask; mask = mask->id.next) { - if (mask->raster_cache) - oldnewmap_insert(fd->maskmap, mask->raster_cache, mask->raster_cache, 0); - } -} - -/* set old main mask caches to zero if it has been restored */ -/* this works because freeing old main only happens after this call */ -void blo_end_mask_pointer_map(FileData *fd, Main *oldmain) -{ - OldNew *entry = fd->maskmap->entries; - Mask *mask; - int i; - - /* used entries were restored, so we put them to zero */ - for (i = 0; i < fd->maskmap->nentries; i++, entry++) { - if (entry->nr > 0) - entry->newp = NULL; - } - - for (mask = oldmain->mask.first; mask; mask = mask->id.next) { - mask->raster_cache = newmclipadr(fd, mask->raster_cache); - } -} -#endif - /* undo file support: add all library pointers in lookup */ void blo_add_library_pointer_map(ListBase *mainlist, FileData *fd) { @@ -6314,11 +6267,6 @@ static void direct_link_mask(FileData *fd, Mask *mask) { MaskLayer *masklay; -#ifdef USE_MANGO_MASK_CACHE_HACK - if (fd->maskmap) mask->raster_cache = newmaskadr(fd, mask->raster_cache); - else mask->raster_cache = NULL; -#endif - mask->adt = newdataadr(fd, mask->adt); link_list(fd, &mask->masklayers); diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index 32792dd7b9d..a3aa8e783a0 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -83,7 +83,6 @@ typedef struct FileData { struct OldNewMap *libmap; struct OldNewMap *imamap; struct OldNewMap *movieclipmap; - struct OldNewMap *maskmap; struct bheadsort *bheadmap; int tot_bheadmap; @@ -128,8 +127,6 @@ void blo_make_image_pointer_map(FileData *fd, Main *oldmain); void blo_end_image_pointer_map(FileData *fd, Main *oldmain); void blo_make_movieclip_pointer_map(FileData *fd, Main *oldmain); void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain); -void blo_make_mask_pointer_map(FileData *fd, Main *oldmain); -void blo_end_mask_pointer_map(FileData *fd, Main *oldmain); void blo_add_library_pointer_map(ListBase *mainlist, FileData *fd); void blo_freefiledata(FileData *fd); diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index a789f570c36..63015bd56af 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -40,8 +40,6 @@ #include "DNA_listBase.h" #include "DNA_curve_types.h" -#define USE_MANGO_MASK_CACHE_HACK - typedef struct Mask { ID id; struct AnimData *adt; From 0f6eb8c2cd0750f7a8af290ea574ce7306356228 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 1 Aug 2012 16:16:10 +0000 Subject: [PATCH 046/160] Fix own regression in cycles material group cased by recent changes in nodes rna --- source/blender/makesrna/intern/rna_nodetree.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index ef58b82a3bd..f505bc0baa4 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -217,12 +217,15 @@ static StructRNA *rna_Node_refine(struct PointerRNA *ptr) #include "rna_nodetree_types.h" case NODE_GROUP: + return &RNA_NodeGroup; case NODE_FORLOOP: + return &RNA_NodeForLoop; case NODE_WHILELOOP: + return &RNA_NodeWhileLoop; case NODE_FRAME: + return &RNA_NodeFrame; case NODE_REROUTE: - return &RNA_SpecialNode; - + return &RNA_NodeReroute; default: return &RNA_Node; } @@ -1051,11 +1054,11 @@ static void init(void) #include "rna_nodetree_types.h" - reg_node(NODE_GROUP, Category_GroupNode, "GROUP", "NodeGroup", "Node", "Group", ""); - reg_node(NODE_FORLOOP, Category_LoopNode, "FORLOOP", "NodeForLoop", "Node", "ForLoop", ""); - reg_node(NODE_WHILELOOP, Category_LoopNode, "WHILELOOP", "NodeWhileLoop", "Node", "WhileLoop", ""); - reg_node(NODE_FRAME, Category_LayoutNode, "FRAME", "NodeFrame", "Node", "Frame", ""); - reg_node(NODE_REROUTE, Category_LayoutNode, "REROUTE", "NodeReroute", "Node", "Reroute", ""); + reg_node(NODE_GROUP, Category_GroupNode, "GROUP", "NodeGroup", "SpecialNode", "Group", ""); + reg_node(NODE_FORLOOP, Category_LoopNode, "FORLOOP", "NodeForLoop", "SpecialNode", "ForLoop", ""); + reg_node(NODE_WHILELOOP, Category_LoopNode, "WHILELOOP", "NodeWhileLoop", "SpecialNode", "WhileLoop", ""); + reg_node(NODE_FRAME, Category_LayoutNode, "FRAME", "NodeFrame", "SpecialNode", "Frame", ""); + reg_node(NODE_REROUTE, Category_LayoutNode, "REROUTE", "NodeReroute", "SpecialNode", "Reroute", ""); } static StructRNA *def_node(BlenderRNA *brna, int node_id) From 3c2fffd1a913e061d9f16810a191276da1474495 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 2 Aug 2012 14:16:37 +0000 Subject: [PATCH 047/160] Tomato Cycles: experimental option to cancel rendering when doing initial synchronization This required wrapping create and update pytohn callbacks as into begin/end allow threading macroses. From quick tests this seems to be stable enough, but more tests would be needed before considering this stable. --- intern/cycles/blender/blender_object.cpp | 11 ++++++++--- intern/cycles/blender/blender_python.cpp | 10 +++++++++- intern/cycles/blender/blender_session.cpp | 18 +++++++++--------- intern/cycles/blender/blender_sync.cpp | 5 +++-- intern/cycles/blender/blender_sync.h | 4 +++- 5 files changed, 32 insertions(+), 16 deletions(-) diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 242f7c8ecef..6575cc84814 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -302,14 +302,17 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) BL::Scene b_sce = b_scene; int particle_offset = 0; - for(; b_sce; b_sce = b_sce.background_set()) { - for(b_sce.objects.begin(b_ob); b_ob != b_sce.objects.end(); ++b_ob) { + bool cancel = false; + + for(; b_sce && !cancel; b_sce = b_sce.background_set()) { + for(b_sce.objects.begin(b_ob); b_ob != b_sce.objects.end() && !cancel; ++b_ob) { bool hide = (render_layer.use_viewport_visibility)? b_ob->hide(): b_ob->hide_render(); uint ob_layer = get_layer(b_ob->layers(), b_ob->layers_local_view(), object_is_light(*b_ob)); CYCLES_LOCAL_LAYER_HACK(render_layer.use_localview, ob_layer); hide = hide || !(ob_layer & scene_layer); if(!hide) { + progress.set_status("Synchronizing object", (*b_ob).name()); int num_particles = object_count_particles(*b_ob); @@ -351,10 +354,12 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) particle_offset += num_particles; } + + cancel = progress.get_cancel(); } } - if(!motion) { + if(!cancel && !motion) { sync_background_light(); /* handle removed data and modified pointers */ diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index 4560c2f8543..96d5bb61ff8 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -80,6 +80,8 @@ static PyObject *create_func(PyObject *self, PyObject *args) /* create session */ BlenderSession *session; + Py_BEGIN_ALLOW_THREADS + if(rv3d) { /* interactive session */ int width = region.width(); @@ -91,7 +93,9 @@ static PyObject *create_func(PyObject *self, PyObject *args) /* offline session */ session = new BlenderSession(engine, userpref, data, scene); } - + + Py_END_ALLOW_THREADS + return PyLong_FromVoidPtr(session); } @@ -136,9 +140,13 @@ static PyObject *draw_func(PyObject *self, PyObject *args) static PyObject *sync_func(PyObject *self, PyObject *value) { + Py_BEGIN_ALLOW_THREADS + BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(value); session->synchronize(); + Py_END_ALLOW_THREADS + Py_RETURN_NONE; } diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index e187fe8740c..540f6294820 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -88,15 +88,6 @@ void BlenderSession::create_session() /* create scene */ scene = new Scene(scene_params, session_params.device); - /* create sync */ - sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background); - sync->sync_data(b_v3d, b_engine.camera_override()); - - if(b_rv3d) - sync->sync_view(b_v3d, b_rv3d, width, height); - else - sync->sync_camera(b_engine.camera_override(), width, height); - /* create session */ session = new Session(session_params); session->scene = scene; @@ -104,6 +95,15 @@ void BlenderSession::create_session() session->progress.set_cancel_callback(function_bind(&BlenderSession::test_cancel, this)); session->set_pause(BlenderSync::get_session_pause(b_scene, background)); + /* create sync */ + sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress); + sync->sync_data(b_v3d, b_engine.camera_override()); + + if(b_rv3d) + sync->sync_view(b_v3d, b_rv3d, width, height); + else + sync->sync_camera(b_engine.camera_override(), width, height); + /* set buffer parameters */ BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height); session->reset(buffer_params, session_params.samples); diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index bab467746c7..0cb59f76156 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -40,7 +40,7 @@ CCL_NAMESPACE_BEGIN /* Constructor */ -BlenderSync::BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_, Scene *scene_, bool preview_) +BlenderSync::BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_, Scene *scene_, bool preview_, Progress &progress_) : b_engine(b_engine_), b_data(b_data_), b_scene(b_scene_), shader_map(&scene_->shaders), @@ -49,7 +49,8 @@ BlenderSync::BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL:: light_map(&scene_->lights), world_map(NULL), world_recalc(false), - experimental(false) + experimental(false), + progress(progress_) { scene = scene_; preview = preview_; diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 8a8452b75d9..c7cc3fe42b1 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -49,7 +49,7 @@ class ShaderNode; class BlenderSync { public: - BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data, BL::Scene b_scene, Scene *scene_, bool preview_); + BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data, BL::Scene b_scene, Scene *scene_, bool preview_, Progress &progress_); ~BlenderSync(); /* sync */ @@ -131,6 +131,8 @@ private: bool use_localview; int samples; } render_layer; + + Progress &progress; }; /* we don't have spare bits for localview (normally 20-28) From ecab45a018c8f4b5ec4cfdaa43aa2311a3eb3cba Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 3 Aug 2012 10:42:21 +0000 Subject: [PATCH 048/160] Tomato Cycles: fix wrong center coordinate when using multi-device configurations --- intern/cycles/render/tile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index 1b2c6a0b11f..990211e1f4f 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -125,7 +125,7 @@ bool TileManager::next_tile(Tile& tile, int device) int device_y = (image_h / num) * device; int device_h = (device == num - 1) ? image_h - device * (image_h / num) : image_h / num; - int64_t centx = image_w / 2, centy = device_h / 2, tot = 1; + int64_t centx = image_w / 2, centy = device_y + device_h / 2, tot = 1; int64_t mindist = (int64_t) image_w * (int64_t) device_h; /* find center of rendering tiles, image center counts for 1 too */ From 535a17dd189dc8b565047718a6bb8fb522a37e83 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 3 Aug 2012 10:55:33 +0000 Subject: [PATCH 049/160] Tomato Cycles: fix own regression in currently rendering tile status --- intern/cycles/render/session.cpp | 3 ++- intern/cycles/render/tile.cpp | 2 ++ intern/cycles/render/tile.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 9926e906ddf..01aff644c37 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -652,7 +652,8 @@ void Session::update_status_time(bool show_pause, bool show_done) int num_samples = tile_manager.state.num_samples; int resolution = tile_manager.state.resolution; int num_tiles = tile_manager.state.num_tiles; - int tile = num_tiles - tile_manager.state.tiles.size(); + int num_rendered_tiles = tile_manager.state.num_rendered_tiles; + int tile = num_tiles - num_rendered_tiles; /* update status */ string status, substatus; diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index 990211e1f4f..6e034fe9041 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -60,6 +60,7 @@ void TileManager::reset(BufferParams& params_, int num_samples_) state.buffer = BufferParams(); state.sample = -1; state.num_tiles = 0; + state.num_rendered_tiles = 0; state.num_samples = 0; state.resolution = start_resolution; state.tiles.clear(); @@ -160,6 +161,7 @@ bool TileManager::next_tile(Tile& tile, int device) if (best != state.tiles.end()) { best->rendering = true; tile = *best; + state.num_rendered_tiles++; return true; } diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h index 6786620ceab..8bde6e153dc 100644 --- a/intern/cycles/render/tile.h +++ b/intern/cycles/render/tile.h @@ -53,6 +53,7 @@ public: int num_samples; int resolution; int num_tiles; + int num_rendered_tiles; list tiles; } state; From e135bfe41bebfdd7f9518c8700758dbc54de3c1b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 3 Aug 2012 11:13:38 +0000 Subject: [PATCH 050/160] Correction top previous commit: tiles were counted in opposite way --- intern/cycles/render/session.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 01aff644c37..addd97ca840 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -652,8 +652,7 @@ void Session::update_status_time(bool show_pause, bool show_done) int num_samples = tile_manager.state.num_samples; int resolution = tile_manager.state.resolution; int num_tiles = tile_manager.state.num_tiles; - int num_rendered_tiles = tile_manager.state.num_rendered_tiles; - int tile = num_tiles - num_rendered_tiles; + int tile = tile_manager.state.num_rendered_tiles; /* update status */ string status, substatus; From b5e1419e5be6cf2dbbb5fd8868dadea17dc23fbf Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 3 Aug 2012 15:18:42 +0000 Subject: [PATCH 051/160] Tomato Cycles: internal cleanup of tile-based integrator This commit solves couple of issues appeared with new integrator: - Render job progress bar is now shows progress based on number of rendered tiles. This is the same as Blender Internal does. This still requires some further thoughts because for GPU it's better to use single tile and in this case progress bar should be based on number of rendered samples. - Removes "global" sample counter from progress descriptor. There's no more global-being sample which makes sense. This counter was replaced with tile counter. - Use proper sample number when copying render buffer to blender. It used to be final sample number used which lead to tiles appearing from complete dark to normal brightness as they're being rendered. Now tile would be displayed with proper brightness starting from the very first sample. Use sample counter stored in render tile descriptor and pass it to update / write callbacks. This was tested on CPU and GPU CUDA rendering. Additional change: OpenCL rendering now should be cancellable before it finished rendering all the samples (the same change as for CPU/CUDA from a while ago). This part of commit wasn't actually tested, would do it later. --- intern/cycles/blender/blender_session.cpp | 53 +++++++++++------------ intern/cycles/blender/blender_session.h | 13 +++--- intern/cycles/blender/blender_util.h | 1 - intern/cycles/device/device_cpu.cpp | 2 + intern/cycles/device/device_cuda.cpp | 6 ++- intern/cycles/device/device_opencl.cpp | 10 ++++- intern/cycles/render/buffers.cpp | 2 +- intern/cycles/render/buffers.h | 3 +- intern/cycles/render/session.cpp | 17 ++++---- intern/cycles/render/session.h | 4 +- intern/cycles/util/util_progress.h | 24 +++++----- 11 files changed, 73 insertions(+), 62 deletions(-) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 540f6294820..2ebeedc8218 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -189,9 +189,9 @@ static void end_render_result(BL::RenderEngine b_engine, BL::RenderResult b_rr, RE_engine_end_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data, (int)cancel); } -void BlenderSession::do_write_update_render_buffers(RenderBuffers *buffers, bool do_update_only) +void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_update_only) { - BufferParams& params = buffers->params; + BufferParams& params = rtile.buffers->params; int x = params.full_x - session->tile_manager.params.full_x; int y = params.full_y - session->tile_manager.params.full_y; int w = params.width; @@ -211,31 +211,31 @@ void BlenderSession::do_write_update_render_buffers(RenderBuffers *buffers, bool if (do_update_only) { /* update only needed */ - update_render_result(b_rr, b_rlay, buffers); + update_render_result(b_rr, b_rlay, rtile); end_render_result(b_engine, b_rr, true); } else { /* write result */ - write_render_result(b_rr, b_rlay, buffers); + write_render_result(b_rr, b_rlay, rtile); end_render_result(b_engine, b_rr); } } -void BlenderSession::write_render_buffers(RenderBuffers *buffers) +void BlenderSession::write_render_tile(RenderTile& rtile) { - do_write_update_render_buffers(buffers, false); + do_write_update_render_tile(rtile, false); } -void BlenderSession::update_render_buffers(RenderBuffers *buffers) +void BlenderSession::update_render_tile(RenderTile& rtile) { - do_write_update_render_buffers(buffers, true); + do_write_update_render_tile(rtile, true); } void BlenderSession::render() { /* set callback to write out render results */ - session->write_render_buffers_cb = function_bind(&BlenderSession::write_render_buffers, this, _1); - session->update_render_buffers_cb = function_bind(&BlenderSession::update_render_buffers, this, _1); + session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1); + session->update_render_tile_cb = function_bind(&BlenderSession::update_render_tile, this, _1); /* get buffer parameters */ SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); @@ -305,22 +305,20 @@ void BlenderSession::render() } /* clear callback */ - session->write_render_buffers_cb = NULL; - session->update_render_buffers_cb = NULL; + session->write_render_tile_cb = NULL; + session->update_render_tile_cb = NULL; } -void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers, bool do_update_only) +void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile, bool do_update_only) { + RenderBuffers *buffers = rtile.buffers; + /* copy data from device */ if(!buffers->copy_from_device()) return; BufferParams& params = buffers->params; float exposure = scene->film->exposure; - double total_time, sample_time; - int sample; - - session->progress.get_sample(sample, total_time, sample_time); vector pixels(params.width*params.height*4); @@ -336,27 +334,27 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::Re int components = b_pass.channels(); /* copy pixels */ - if(buffers->get_pass(pass_type, exposure, sample, components, &pixels[0])) + if(buffers->get_pass_rect(pass_type, exposure, rtile.sample, components, &pixels[0])) rna_RenderPass_rect_set(&b_pass.ptr, &pixels[0]); } } /* copy combined pass */ - if(buffers->get_pass(PASS_COMBINED, exposure, sample, 4, &pixels[0])) + if(buffers->get_pass_rect(PASS_COMBINED, exposure, rtile.sample, 4, &pixels[0])) rna_RenderLayer_rect_set(&b_rlay.ptr, &pixels[0]); /* tag result as updated */ RE_engine_update_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data); } -void BlenderSession::write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers) +void BlenderSession::write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile) { - do_write_update_render_result(b_rr, b_rlay, buffers, false); + do_write_update_render_result(b_rr, b_rlay, rtile, false); } -void BlenderSession::update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers) +void BlenderSession::update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile) { - do_write_update_render_result(b_rr, b_rlay, buffers, true); + do_write_update_render_result(b_rr, b_rlay, rtile, true); } void BlenderSession::synchronize() @@ -461,11 +459,12 @@ void BlenderSession::get_status(string& status, string& substatus) void BlenderSession::get_progress(float& progress, double& total_time) { - double sample_time; - int sample; + double tile_time; + int tile; + int tile_total = session->tile_manager.state.num_tiles; - session->progress.get_sample(sample, total_time, sample_time); - progress = ((float)sample/(float)session->params.samples); + session->progress.get_tile(tile, total_time, tile_time); + progress = ((float)tile/(float)tile_total); } void BlenderSession::update_status_progress() diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index 5f458aa888b..4666b5982e1 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -30,6 +30,7 @@ CCL_NAMESPACE_BEGIN class Scene; class Session; class RenderBuffers; +class RenderTile; class BlenderSession { public: @@ -48,14 +49,14 @@ public: /* offline render */ void render(); - void write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers); - void write_render_buffers(RenderBuffers *buffers); + void write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile); + void write_render_tile(RenderTile& rtile); /* update functions are used to update display buffer only after sample was rendered * only needed for better visual feedback */ - void update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers); - void update_render_buffers(RenderBuffers *buffers); + void update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile); + void update_render_tile(RenderTile& rtile); /* interactive updates */ void synchronize(); @@ -89,8 +90,8 @@ public: int width, height; protected: - void do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderBuffers *buffers, bool do_update_only); - void do_write_update_render_buffers(RenderBuffers *buffers, bool do_update_only); + void do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile, bool do_update_only); + void do_write_update_render_tile(RenderTile& rtile, bool do_update_only); }; CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index ab1f7cf7907..b08c1e7e765 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -55,7 +55,6 @@ void rna_ColorRamp_eval(void *coba, float position, float color[4]); void rna_Scene_frame_set(void *scene, int frame, float subframe); void BKE_image_user_frame_calc(void *iuser, int cfra, int fieldnr); void BKE_image_user_file_path(void *iuser, void *ima, char *path); - } CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 9febd7ae27c..fe32e9a2760 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -167,6 +167,7 @@ public: } } + tile.sample = sample + 1; task.update_progress(tile); } } @@ -189,6 +190,7 @@ public: } } + tile.sample = sample + 1; task.update_progress(tile); } } diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 35f541d0c9c..c8dcfdc2f3d 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -837,11 +837,13 @@ public: int end_sample = tile.start_sample + tile.num_samples; for(int sample = start_sample; sample < end_sample; sample++) { - if (task->get_cancel()) { + if (task->get_cancel()) break; - } path_trace(tile, sample); + + tile.sample = sample + 1; + task->update_progress(tile); } diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 471ada60eea..3c78b4895ae 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -685,9 +685,17 @@ public: int start_sample = tile.start_sample; int end_sample = tile.start_sample + tile.num_samples; - for(int sample = start_sample; sample < end_sample; sample++) + for(int sample = start_sample; sample < end_sample; sample++) { + if (task->get_cancel()) + break; + path_trace(tile, sample); + tile.sample = sample + 1; + + task->update_progress(tile); + } + task->release_tile(tile); } } diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index bd8c6cd22dd..51568f65323 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -158,7 +158,7 @@ bool RenderBuffers::copy_from_device() return true; } -bool RenderBuffers::get_pass(PassType type, float exposure, int sample, int components, float *pixels) +bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels) { int pass_offset = 0; diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h index f8df2b3587e..ee0d78a1cd8 100644 --- a/intern/cycles/render/buffers.h +++ b/intern/cycles/render/buffers.h @@ -79,7 +79,7 @@ public: void reset(Device *device, BufferParams& params); bool copy_from_device(); - bool get_pass(PassType type, float exposure, int sample, int components, float *pixels); + bool get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels); protected: void device_free(); @@ -129,6 +129,7 @@ public: int x, y, w, h; int start_sample; int num_samples; + int sample; int resolution; int offset; int stride; diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index addd97ca840..3bd2c6af6d8 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -339,7 +339,7 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile) /* in case of a permant buffer, return it, otherwise we will allocate * a new temporary buffer */ - if(!write_render_buffers_cb) { + if(!write_render_tile_cb) { tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride); rtile.buffer = buffers->buffer.device_pointer; @@ -377,11 +377,11 @@ void Session::update_tile_sample(RenderTile& rtile) { thread_scoped_lock tile_lock(tile_mutex); - if(update_render_buffers_cb) { + if(update_render_tile_cb) { /* todo: optimize this by making it thread safe and removing lock */ if(!progress.get_cancel()) - update_render_buffers_cb(rtile.buffers); + update_render_tile_cb(rtile); } update_status_time(); @@ -391,10 +391,10 @@ void Session::release_tile(RenderTile& rtile) { thread_scoped_lock tile_lock(tile_mutex); - if(write_render_buffers_cb) { + if(write_render_tile_cb) { /* todo: optimize this by making it thread safe and removing lock */ if(!progress.get_cancel()) - write_render_buffers_cb(rtile.buffers); + write_render_tile_cb(rtile); delete rtile.buffers; } @@ -648,8 +648,6 @@ void Session::update_scene() void Session::update_status_time(bool show_pause, bool show_done) { - int sample = tile_manager.state.sample; - int num_samples = tile_manager.state.num_samples; int resolution = tile_manager.state.resolution; int num_tiles = tile_manager.state.num_tiles; int tile = tile_manager.state.num_rendered_tiles; @@ -677,14 +675,15 @@ void Session::update_status_time(bool show_pause, bool show_done) if(preview_time == 0.0 && resolution == 1) preview_time = time_dt(); - double sample_time = (sample == 0)? 0.0: (time_dt() - preview_time - paused_time)/(sample); + double tile_time = (tile == 0)? 0.0: (time_dt() - preview_time - paused_time)/(sample); /* negative can happen when we pause a bit before rendering, can discard that */ if(preview_time < 0.0) preview_time = 0.0; - progress.set_sample(sample + num_samples, sample_time); + progress.set_tile(tile, tile_time); } + void Session::path_trace() { /* add path trace task */ diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index be834409756..6c5e40bca63 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -105,8 +105,8 @@ public: TileManager tile_manager; int sample; - boost::function write_render_buffers_cb; - boost::function update_render_buffers_cb; + boost::function write_render_tile_cb; + boost::function update_render_tile_cb; Session(const SessionParams& params); ~Session(); diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h index c63aa841c52..e21f1b90166 100644 --- a/intern/cycles/util/util_progress.h +++ b/intern/cycles/util/util_progress.h @@ -36,10 +36,10 @@ class Progress { public: Progress() { - sample = 0; + tile = 0; start_time = time_dt(); total_time = 0.0f; - sample_time = 0.0f; + tile_time = 0.0f; status = "Initializing"; substatus = ""; update_cb = NULL; @@ -57,8 +57,8 @@ public: { thread_scoped_lock lock(progress.progress_mutex); - progress.get_sample(sample, total_time, sample_time); progress.get_status(status, substatus); + progress.get_tile(tile, total_time, tile_time); return *this; } @@ -90,7 +90,7 @@ public: cancel_cb = function; } - /* sample and timing information */ + /* tile and timing information */ void set_start_time(double start_time_) { @@ -99,22 +99,22 @@ public: start_time = start_time_; } - void set_sample(int sample_, double sample_time_) + void set_tile(int tile_, double tile_time_) { thread_scoped_lock lock(progress_mutex); - sample = sample_; + tile = tile_; total_time = time_dt() - start_time; - sample_time = sample_time_; + tile_time = tile_time_; } - void get_sample(int& sample_, double& total_time_, double& sample_time_) + void get_tile(int& tile_, double& total_time_, double& tile_time_) { thread_scoped_lock lock(progress_mutex); - sample_ = sample; + tile_ = tile; total_time_ = (total_time > 0.0)? total_time: 0.0; - sample_time_ = sample_time; + tile_time_ = tile_time; } /* status messages */ @@ -170,11 +170,11 @@ protected: boost::function update_cb; boost::function cancel_cb; - int sample; + int tile; double start_time; double total_time; - double sample_time; + double tile_time; string status; string substatus; From e7f8b52aee26c05b4497850b4085cea91eac5e8a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 4 Aug 2012 09:13:52 +0000 Subject: [PATCH 052/160] Tomato Cycles: minor code cleanup Move center tile acquiring code into own function. Should be easier for time being when we'll want to support other tile render orders. Also now there should be a single bucket growing from center when multi-GPU is used. Can't test this here tho. --- intern/cycles/render/tile.cpp | 21 +++++++++++++++------ intern/cycles/render/tile.h | 2 ++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index 6e034fe9041..877e26bf79e 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -113,7 +113,7 @@ void TileManager::set_tiles() state.buffer.full_height = max(1, params.full_height/resolution); } -bool TileManager::next_tile(Tile& tile, int device) +list::iterator TileManager::next_center_tile(int device) { list::iterator iter, best = state.tiles.end(); @@ -131,7 +131,7 @@ bool TileManager::next_tile(Tile& tile, int device) /* find center of rendering tiles, image center counts for 1 too */ for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) { - if(iter->device == device && iter->rendering) { + if(iter->rendering) { Tile &cur_tile = *iter; centx += cur_tile.x + cur_tile.w / 2; centy += cur_tile.y + cur_tile.h / 2; @@ -151,16 +151,25 @@ bool TileManager::next_tile(Tile& tile, int device) int64_t disty = centy - (cur_tile.y + cur_tile.h / 2); distx = (int64_t) sqrt((double)distx * distx + disty * disty); - if (distx < mindist) { + if(distx < mindist) { best = iter; mindist = distx; } } } - if (best != state.tiles.end()) { - best->rendering = true; - tile = *best; + return best; +} + +bool TileManager::next_tile(Tile& tile, int device) +{ + list::iterator tile_it; + + tile_it = next_center_tile(device); + + if(tile_it != state.tiles.end()) { + tile_it->rendering = true; + tile = *tile_it; state.num_rendered_tiles++; return true; diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h index 8bde6e153dc..a4a518b1eb4 100644 --- a/intern/cycles/render/tile.h +++ b/intern/cycles/render/tile.h @@ -76,6 +76,8 @@ protected: int num_devices; int start_resolution; + + list::iterator next_center_tile(int device = 0); }; CCL_NAMESPACE_END From 7b644b819627ded84fb59e99f1b8754a19ecd6a6 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 5 Aug 2012 17:24:10 +0000 Subject: [PATCH 053/160] Tomato Cycles: fix for vector pass gives wrong result in some circumstances Issue was caused by wrong camera motion stored in device in cases when first render layer does not have vector pass enabled. Solved by forcing device camera update in cases when scene's motion changed since previous device camera update. --- intern/cycles/render/camera.cpp | 14 +++++++++++++- intern/cycles/render/camera.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 55a0f23f8d0..272ddb89b0c 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -75,6 +75,7 @@ Camera::Camera() need_update = true; need_device_update = true; + previous_motion = -1; } Camera::~Camera() @@ -140,8 +141,19 @@ void Camera::update() void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) { + Scene::MotionType need_motion = scene->need_motion(); + update(); + if (previous_motion != need_motion) { + /* scene's motion model could have been changed since + * previous device camera update + * this could happen for example in case when one render + * layer has got motion pass and another not + */ + need_device_update = true; + } + if(!need_device_update) return; @@ -159,7 +171,6 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) kcam->worldtocamera = transform_inverse(cameratoworld); /* camera motion */ - Scene::MotionType need_motion = scene->need_motion(); kcam->have_motion = 0; if(need_motion == Scene::MOTION_PASS) { @@ -226,6 +237,7 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) kcam->cliplength = (farclip == FLT_MAX)? FLT_MAX: farclip - nearclip; need_device_update = false; + previous_motion = need_motion; } void Camera::device_free(Device *device, DeviceScene *dscene) diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index d2a3cce1817..a539510029f 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -91,6 +91,7 @@ public: /* update */ bool need_update; bool need_device_update; + int previous_motion; /* functions */ Camera(); From 1ba78bca9487c7f9fe5404d782a34c5abd118db0 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 5 Aug 2012 17:38:44 +0000 Subject: [PATCH 054/160] Tomato Cycles: fix regression since rev49535 Wrong sample number was reporting in viewport rendering. --- intern/cycles/render/session.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 3bd2c6af6d8..7c4ac4e2277 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -648,6 +648,7 @@ void Session::update_scene() void Session::update_status_time(bool show_pause, bool show_done) { + int sample = tile_manager.state.sample; int resolution = tile_manager.state.resolution; int num_tiles = tile_manager.state.num_tiles; int tile = tile_manager.state.num_rendered_tiles; From c93be80be9f27edffaa848eb147e5b09dceec1c3 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 6 Aug 2012 10:10:35 +0000 Subject: [PATCH 055/160] Tomato Cycles: report current scene and render layer being rendering Helps figuring out what exactly takes time when rendering in render farm. --- intern/cycles/blender/blender_session.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 2ebeedc8218..9f76d30c77d 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -477,8 +477,13 @@ void BlenderSession::update_status_progress() get_status(status, substatus); get_progress(progress, total_time); + timestatus = b_scene.name(); + if(b_rlay_name != "") + timestatus += ", " + b_rlay_name; + timestatus += " | "; + BLI_timestr(total_time, time_str); - timestatus = "Elapsed: " + string(time_str) + " | "; + timestatus += "Elapsed: " + string(time_str) + " | "; if(substatus.size() > 0) status += " | " + substatus; From 385c38f6ed13b3d9502644f6912517ea4314630e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 6 Aug 2012 13:59:11 +0000 Subject: [PATCH 056/160] misc small edits syncing with trunk --- source/blender/blenkernel/intern/mask.c | 2 -- source/blender/blenkernel/intern/node.c | 4 ++-- source/blender/blenloader/intern/readfile.c | 4 +++- source/blender/imbuf/IMB_imbuf.h | 1 + source/blender/makesrna/intern/rna_nodetree_types.h | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 01aa9fa9fa9..f41d8feef0b 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1528,7 +1528,6 @@ void BKE_mask_layer_free(MaskLayer *masklay) MEM_freeN(masklay); } - void BKE_mask_layer_free_list(ListBase *masklayers) { MaskLayer *masklay = masklayers->first; @@ -1541,7 +1540,6 @@ void BKE_mask_layer_free_list(ListBase *masklayers) masklay = masklay_next; } - } void BKE_mask_free(Mask *mask) diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 8f3c76c3357..8670f86cd67 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1443,13 +1443,13 @@ void BKE_node_clipboard_clear(void) bNode *node, *node_next; bNodeLink *link, *link_next; - for (link = node_clipboard.links.first; link; link=link_next) { + for (link = node_clipboard.links.first; link; link = link_next) { link_next = link->next; nodeRemLink(NULL, link); } node_clipboard.links.first = node_clipboard.links.last = NULL; - for (node = node_clipboard.nodes.first; node; node=node_next) { + for (node = node_clipboard.nodes.first; node; node = node_next) { node_next = node->next; nodeFreeNode(NULL, node); } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 890cb0e1ed0..e1095d25b1d 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1174,6 +1174,7 @@ static void *newmclipadr(FileData *fd, void *adr) /* used to restor return NULL; } + static void *newlibadr(FileData *fd, void *lib, void *adr) /* only lib data */ { return oldnewmap_liblookup(fd->libmap, adr, lib); @@ -1368,6 +1369,7 @@ void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain) } } + /* undo file support: add all library pointers in lookup */ void blo_add_library_pointer_map(ListBase *mainlist, FileData *fd) { @@ -8083,7 +8085,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) fix_relpaths_library(fd->relabase, bfd->main); /* make all relative paths, relative to the open blend file */ link_global(fd, bfd); /* as last */ - + return bfd; } diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 50fa8ad1106..99db8bbfa0a 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -508,3 +508,4 @@ short imb_addtilesImBuf(struct ImBuf *ibuf); void imb_freetilesImBuf(struct ImBuf *ibuf); #endif + diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index 494f147f6d9..c70dd01cd57 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -121,7 +121,7 @@ DefNode( CompositorNode, CMP_NODE_TRANSLATE, 0, "TRANS DefNode( CompositorNode, CMP_NODE_ZCOMBINE, def_cmp_zcombine, "ZCOMBINE", Zcombine, "Z Combine", "" ) DefNode( CompositorNode, CMP_NODE_COMBRGBA, 0, "COMBRGBA", CombRGBA, "Combine RGBA", "" ) DefNode( CompositorNode, CMP_NODE_DILATEERODE, def_cmp_dilate_erode, "DILATEERODE", DilateErode, "Dilate/Erode", "" ) -DefNode( CompositorNode, CMP_NODE_INPAINT, def_cmp_inpaint, "INPAINT", Inpaint, "Inpaint", "" ) +DefNode( CompositorNode, CMP_NODE_INPAINT, def_cmp_inpaint, "INPAINT", Inpaint, "Inpaint", "" ) DefNode( CompositorNode, CMP_NODE_ROTATE, def_cmp_rotate, "ROTATE", Rotate, "Rotate", "" ) DefNode( CompositorNode, CMP_NODE_SCALE, def_cmp_scale, "SCALE", Scale, "Scale", "" ) DefNode( CompositorNode, CMP_NODE_SEPYCCA, def_cmp_ycc, "SEPYCCA", SepYCCA, "Separate YCCA", "" ) From cc1af6bb3669fdaeb665a4cfbfedfc53edfd21a2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 6 Aug 2012 15:54:52 +0000 Subject: [PATCH 057/160] fix for memory leak playing animations. --- .../blender/windowmanager/intern/wm_playanim.c | 17 ++++++++++++++++- source/creator/creator.c | 14 +++++++++----- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index 3c7ae3ef584..3c791cb6e5d 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -941,6 +941,9 @@ void playanim(int argc, const char **argv) pupdate_time(); ptottime = 0; + /* newly added in 2.6x, without this images never get freed */ +#define USE_IMB_CACHE + while (ps.go) { if (ps.pingpong) ps.direction = -ps.direction; @@ -967,8 +970,9 @@ void playanim(int argc, const char **argv) if (ptottime > 0.0) ptottime = 0.0; while (ps.picture) { +#ifndef USE_IMB_CACHE if (ibuf != NULL && ibuf->ftype == 0) IMB_freeImBuf(ibuf); - +#endif if (ps.picture->ibuf) { ibuf = ps.picture->ibuf; } @@ -984,6 +988,11 @@ void playanim(int argc, const char **argv) } if (ibuf) { + +#ifdef USE_IMB_CACHE + ps.picture->ibuf = ibuf; +#endif + BLI_strncpy(ibuf->name, ps.picture->name, sizeof(ibuf->name)); /* why only windows? (from 2.4x) - campbell */ @@ -1101,7 +1110,10 @@ void playanim(int argc, const char **argv) #endif /* WITH_QUICKTIME */ /* cleanup */ +#ifndef USE_IMB_CACHE if (ibuf) IMB_freeImBuf(ibuf); +#endif + BLI_freelistN(&picsbase); #if 0 // XXX25 free_blender(); @@ -1115,7 +1127,10 @@ void playanim(int argc, const char **argv) totblock = MEM_get_memory_blocks_in_use(); if (totblock != 0) { + /* prints many bAKey, bArgument's which are tricky to fix */ +#if 0 printf("Error Totblock: %d\n", totblock); MEM_printmemlist(); +#endif } } diff --git a/source/creator/creator.c b/source/creator/creator.c index c9f2892bcce..7479935c179 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -1270,11 +1270,6 @@ int main(int argc, const char **argv) BLI_threadapi_init(); - RNA_init(); - RE_engines_init(); - - init_nodesystem(); - initglobals(); /* blender.c */ IMB_init(); @@ -1295,6 +1290,15 @@ int main(int argc, const char **argv) BLI_argsParse(ba, 1, NULL, NULL); #endif + + /* after level 1 args, this is so playanim skips RNA init */ + RNA_init(); + + RE_engines_init(); + init_nodesystem(); + /* end second init */ + + #if defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS) G.background = 1; /* python module mode ALWAYS runs in background mode (for now) */ #else From 6498c054e0a41f9e9e07eb014e18e025ec12a573 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 6 Aug 2012 19:31:34 +0000 Subject: [PATCH 058/160] remove unused mask pointer --- source/blender/makesdna/DNA_mask_types.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index 475c4168fcb..b34a6c9b12f 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -51,9 +51,6 @@ typedef struct Mask { int flag; /* for anim info */ int pad; - - /* XXX: cache data, remove as soon as rasterizer is multithreaded */ - void *raster_cache; } Mask; typedef struct MaskParent { From 946061919971ff5b6307c04a00fbea162f8b9d32 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 7 Aug 2012 09:22:26 +0000 Subject: [PATCH 059/160] Tomato Cycles: do not discard unfinished tiles on cancel Do not discard (fill with black) tiles which are not fully rendered (not all the samples are calculated for tile) when canceling render. This could be helpful to tweak some settings when render glitch is discovered. Also it could be used in such scenarios as setting samples number to something really high and render still image until result is reasonable, controlling this manually. This could make cancel not so responsible on CPU, but it wouldn't be less responsible than GPU, also could potentially give some %% of speedup by avoiding checking cancel state after every pixel sampled. --- intern/cycles/device/device_cpu.cpp | 22 ++++++++-------------- intern/cycles/render/session.cpp | 7 +++---- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index fe32e9a2760..4c54671b0d0 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -154,20 +154,18 @@ public: #ifdef WITH_OPTIMIZED_KERNEL if(system_cpu_support_optimized()) { for(int sample = start_sample; sample < end_sample; sample++) { + if (task.get_cancel() || task_pool.cancelled()) + break; + for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) { - if (task.get_cancel()) - break; - - if(task_pool.cancelled()) - break; - kernel_cpu_optimized_path_trace(kg, render_buffer, rng_state, sample, x, y, tile.offset, tile.stride); } } tile.sample = sample + 1; + task.update_progress(tile); } } @@ -175,22 +173,18 @@ public: #endif { for(int sample = start_sample; sample < end_sample; sample++) { + if (task.get_cancel() || task_pool.cancelled()) + break; + for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) { - if (task.get_cancel()) { - break; - } - - if(task_pool.cancelled()) - break; - kernel_cpu_path_trace(kg, render_buffer, rng_state, sample, x, y, tile.offset, tile.stride); - } } tile.sample = sample + 1; + task.update_progress(tile); } } diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 7c4ac4e2277..5b32d23ceac 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -380,8 +380,7 @@ void Session::update_tile_sample(RenderTile& rtile) if(update_render_tile_cb) { /* todo: optimize this by making it thread safe and removing lock */ - if(!progress.get_cancel()) - update_render_tile_cb(rtile); + update_render_tile_cb(rtile); } update_status_time(); @@ -393,8 +392,8 @@ void Session::release_tile(RenderTile& rtile) if(write_render_tile_cb) { /* todo: optimize this by making it thread safe and removing lock */ - if(!progress.get_cancel()) - write_render_tile_cb(rtile); + write_render_tile_cb(rtile); + delete rtile.buffers; } From 0d8a2456235e1233aa21bb4bfbe921345167501a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 7 Aug 2012 09:54:55 +0000 Subject: [PATCH 060/160] Code cleanup: remove unused sample counter from render session It's not used since new tile-based rendering and it was confusing to have it in both session and tile manager. Should be no functional changes. --- intern/cycles/render/session.cpp | 2 -- intern/cycles/render/session.h | 1 - 2 files changed, 3 deletions(-) diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 5b32d23ceac..e5c42f8a40e 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -61,7 +61,6 @@ Session::Session(const SessionParams& params_) reset_time = 0.0; preview_time = 0.0; paused_time = 0.0; - sample = 0; delayed_reset.do_reset = false; delayed_reset.samples = 0; @@ -569,7 +568,6 @@ void Session::reset_(BufferParams& buffer_params, int samples) start_time = time_dt(); preview_time = 0.0; paused_time = 0.0; - sample = 0; if(!params.background) progress.set_start_time(start_time + paused_time); diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 6c5e40bca63..2e00ac3d602 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -103,7 +103,6 @@ public: Progress progress; SessionParams params; TileManager tile_manager; - int sample; boost::function write_render_tile_cb; boost::function update_render_tile_cb; From b364f6e6929febb94e7de4891293a4042f7ac62f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 7 Aug 2012 13:27:19 +0000 Subject: [PATCH 061/160] Tomato Cycles: report currently rendering sample when using GPU Currently it makes more sense to use single tile for GPU rendering and in this case tile-based progress report doesn't work well. Since threading happens within single tile, it's possible to detect currently computing sample and report it to the interface, This also allows to display smoother progress when using CPU with small amount of tiles. --- intern/cycles/blender/blender_session.cpp | 8 +++++-- intern/cycles/device/device_task.cpp | 5 +++- intern/cycles/device/device_task.h | 1 + intern/cycles/render/session.cpp | 28 ++++++++++++++++++++++- intern/cycles/render/session.h | 2 ++ intern/cycles/util/util_progress.h | 18 ++++++++++++++- 6 files changed, 57 insertions(+), 5 deletions(-) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 9f76d30c77d..7b80c520e72 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -460,11 +460,15 @@ void BlenderSession::get_status(string& status, string& substatus) void BlenderSession::get_progress(float& progress, double& total_time) { double tile_time; - int tile; + int tile, sample, samples_per_tile; int tile_total = session->tile_manager.state.num_tiles; session->progress.get_tile(tile, total_time, tile_time); - progress = ((float)tile/(float)tile_total); + + sample = session->progress.get_sample(); + samples_per_tile = session->tile_manager.state.num_samples; + + progress = ((float)sample/(float)(tile_total * samples_per_tile)); } void BlenderSession::update_status_progress() diff --git a/intern/cycles/device/device_task.cpp b/intern/cycles/device/device_task.cpp index 479dbc76f1c..c85e182d629 100644 --- a/intern/cycles/device/device_task.cpp +++ b/intern/cycles/device/device_task.cpp @@ -95,7 +95,10 @@ void DeviceTask::update_progress(RenderTile &rtile) if (type != PATH_TRACE) return; - if (update_tile_sample) { + if(update_progress_sample) + update_progress_sample(); + + if(update_tile_sample) { double current_time = time_dt(); if (current_time - last_update_time >= 1.0f) { diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h index 9c8eced15bf..cfb3d8d988e 100644 --- a/intern/cycles/device/device_task.h +++ b/intern/cycles/device/device_task.h @@ -60,6 +60,7 @@ public: void update_progress(RenderTile &rtile); boost::function acquire_tile; + boost::function update_progress_sample; boost::function update_tile_sample; boost::function release_tile; boost::function get_cancel; diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index e5c42f8a40e..142fe52a9d5 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -653,8 +653,29 @@ void Session::update_status_time(bool show_pause, bool show_done) /* update status */ string status, substatus; - if(!params.progressive) + if(!params.progressive) { substatus = string_printf("Path Tracing Tile %d/%d", tile, num_tiles); + + if(params.device.type == DEVICE_CUDA || params.device.type == DEVICE_OPENCL) { + /* when rendering on GPU multithreading happens within single tile, as in + * tiles are handling sequentially and in this case we could display + * currently rendering sample number + * this helps a lot from feedback point of view + */ + + int sample = progress.get_sample(), num_samples = tile_manager.state.num_samples; + + if(tile > 1) { + /* sample counter is global for all tiles, subtract samples + * from already finished tiles to get sample counter for + * current tile only + */ + sample -= (tile - 1) * num_samples; + } + + substatus += string_printf(", Sample %d/%d", sample, num_samples); + } + } else if(params.samples == INT_MAX) substatus = string_printf("Path Tracing Sample %d", sample+1); else @@ -681,6 +702,10 @@ void Session::update_status_time(bool show_pause, bool show_done) progress.set_tile(tile, tile_time); } +void Session::update_progress_sample() +{ + progress.increment_sample(); +} void Session::path_trace() { @@ -691,6 +716,7 @@ void Session::path_trace() task.release_tile = function_bind(&Session::release_tile, this, _1); task.get_cancel = function_bind(&Progress::get_cancel, &this->progress); task.update_tile_sample = function_bind(&Session::update_tile_sample, this, _1); + task.update_progress_sample = function_bind(&Session::update_progress_sample, this); device->task_add(task); } diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 2e00ac3d602..3867799b559 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -148,6 +148,8 @@ protected: void update_tile_sample(RenderTile& tile); void release_tile(RenderTile& tile); + void update_progress_sample(); + bool device_use_gl; thread *session_thread; diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h index e21f1b90166..6e2c0c68427 100644 --- a/intern/cycles/util/util_progress.h +++ b/intern/cycles/util/util_progress.h @@ -37,6 +37,7 @@ public: Progress() { tile = 0; + sample = 0; start_time = time_dt(); total_time = 0.0f; tile_time = 0.0f; @@ -60,6 +61,8 @@ public: progress.get_status(status, substatus); progress.get_tile(tile, total_time, tile_time); + sample = progress.get_sample(); + return *this; } @@ -117,6 +120,18 @@ public: tile_time_ = tile_time; } + void increment_sample() + { + thread_scoped_lock lock(progress_mutex); + + sample++; + } + + int get_sample() + { + return sample; + } + /* status messages */ void set_status(const string& status_, const string& substatus_ = "") @@ -170,7 +185,8 @@ protected: boost::function update_cb; boost::function cancel_cb; - int tile; + int tile; /* counter for rendered tiles */ + int sample; /* counter of rendered samples, global for all tiles */ double start_time; double total_time; From c8934b44f9f958a8d270a9f18a2fe24b033236ed Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Tue, 7 Aug 2012 14:02:53 +0000 Subject: [PATCH 062/160] Tomato Cycles: * Improvement for reporting current sample. Also show the current amount of rendered samples, when using the CPU, and 1x1 tiles. --- intern/cycles/render/session.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 142fe52a9d5..36bdbd006c9 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -656,11 +656,13 @@ void Session::update_status_time(bool show_pause, bool show_done) if(!params.progressive) { substatus = string_printf("Path Tracing Tile %d/%d", tile, num_tiles); - if(params.device.type == DEVICE_CUDA || params.device.type == DEVICE_OPENCL) { + if(params.device.type == DEVICE_CUDA || params.device.type == DEVICE_OPENCL || + (params.device.type == DEVICE_CPU && num_tiles == 1)) { /* when rendering on GPU multithreading happens within single tile, as in * tiles are handling sequentially and in this case we could display * currently rendering sample number - * this helps a lot from feedback point of view + * this helps a lot from feedback point of view. + * also display the info on CPU, when using 1 tile only */ int sample = progress.get_sample(), num_samples = tile_manager.state.num_samples; From 6bcec045debbcfb7e8e5b13a10e8ae878718dccd Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 7 Aug 2012 16:55:15 +0000 Subject: [PATCH 063/160] Code cleanup: use generic threaded image buffer processor for color management --- source/blender/imbuf/intern/colormanagement.c | 52 ++----------------- 1 file changed, 4 insertions(+), 48 deletions(-) diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 055eb6abc81..76f1128b8fc 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -588,50 +588,6 @@ void IMB_colormanagement_exit(void) /*********************** Threaded display buffer transform routines *************************/ #ifdef WITH_OCIO -static void colormanage_processor_apply_threaded(int buffer_lines, int handle_size, void *init_customdata, - void (init_handle) (void *handle, int start_line, int tot_line, - void *customdata), - void *(do_thread) (void *)) -{ - void *handles; - ListBase threads; - - int i, tot_thread = BLI_system_thread_count(); - int start_line, tot_line; - - handles = MEM_callocN(handle_size * tot_thread, "processor apply threaded handles"); - - if (tot_thread > 1) - BLI_init_threads(&threads, do_thread, tot_thread); - - start_line = 0; - tot_line = ((float)(buffer_lines / tot_thread)) + 0.5f; - - for (i = 0; i < tot_thread; i++) { - int cur_tot_line; - void *handle = ((char *) handles) + handle_size * i; - - if (i < tot_thread - 1) - cur_tot_line = tot_line; - else - cur_tot_line = buffer_lines - start_line; - - init_handle(handle, start_line, cur_tot_line, init_customdata); - - if (tot_thread > 1) - BLI_insert_thread(&threads, handle); - - start_line += tot_line; - } - - if (tot_thread > 1) - BLI_end_threads(&threads); - else - do_thread(handles); - - MEM_freeN(handles); -} - typedef struct DisplayBufferThread { void *processor; @@ -707,8 +663,8 @@ static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned c init_data.byte_buffer = byte_buffer; init_data.display_buffer = display_buffer; - colormanage_processor_apply_threaded(ibuf->y, sizeof(DisplayBufferThread), &init_data, - display_buffer_init_handle, do_thread); + IMB_processor_apply_threaded(ibuf->y, sizeof(DisplayBufferThread), &init_data, + display_buffer_init_handle, do_thread); } static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) @@ -974,8 +930,8 @@ static void colorspace_transform_apply_threaded(float *buffer, int width, int he init_data.height = height; init_data.channels = channels; - colormanage_processor_apply_threaded(height, sizeof(ColorspaceTransformThread), &init_data, - colorspace_transform_init_handle, do_thread); + IMB_processor_apply_threaded(height, sizeof(ColorspaceTransformThread), &init_data, + colorspace_transform_init_handle, do_thread); } static void *do_color_space_transform_thread(void *handle_v) From ed098158decb86d16bf697baf5ade2bba2632eb3 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 9 Aug 2012 18:12:58 +0000 Subject: [PATCH 064/160] Compilation error fix: G.rendering was renamed to G.is_rendering --- source/blender/editors/space_view3d/view3d_draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 54d26e2ec5f..b8d5f52b9fd 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -3150,7 +3150,7 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar) int draw_border = (rv3d->persp == RV3D_CAMOB && (scene->r.mode & R_BORDER)); /* --- until we get a clue and make viewport threadsafe (temp mango change for stability) */ - if (G.rendering) { + if (G.is_rendering) { ED_region_pixelspace(ar); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); UI_ThemeClearColor(TH_BACK); From 711b97c2acbdda30e325df561907bf86bd8c7e6b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 12 Aug 2012 11:58:34 +0000 Subject: [PATCH 065/160] Tomato Cycles: use actual number of tiles for viewport rendering Before this debug_tile_size was used as a size of tile, which became hidden property since tile-based rendering implementation and couldn't have been controlled. This resolves the issue with single thread used for viewport rendering in some cases. Also it makes possible to control tiles for CUDA viewport rendering, which still behaves much faster when using the single tile. Also fixed issue with minimal tile size which was used to calculate divider of final resolution to be used for initial rendering. Now it's a Resolution Divider property in Performance tab. This option could be used to tweak initial resolution of viewport for faster navigation or faster refresh when changing some properties. --- intern/cycles/blender/addon/properties.py | 17 ++++++----------- intern/cycles/blender/addon/ui.py | 5 ++--- intern/cycles/blender/blender_sync.cpp | 15 +++------------ intern/cycles/render/session.cpp | 2 +- intern/cycles/render/session.h | 6 +++--- intern/cycles/render/tile.cpp | 19 +++---------------- intern/cycles/render/tile.h | 4 ++-- .../editors/space_view3d/view3d_draw.c | 12 ++++++++++-- 8 files changed, 30 insertions(+), 50 deletions(-) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 7a22cba316e..4abdfb0d737 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -235,18 +235,13 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): default=0.0, ) - cls.debug_tile_size = IntProperty( - name="Tile Size", - description="", - min=1, max=4096, - default=1024, - ) - cls.debug_min_size = IntProperty( - name="Min Size", - description="", - min=1, max=4096, - default=64, + cls.resolution_divider = IntProperty( + name="Resolution Divider", + description="Start viewport rendering with lower resolutionm which would be real resolution divided by two in power of this value", + min=1, max=512, + default=4, ) + cls.debug_reset_timeout = FloatProperty( name="Reset timeout", description="", diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 1191d1b8c25..561ccbbe3d1 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -205,9 +205,6 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel): subsub.enabled = not rd.use_border subsub.prop(rd, "use_save_buffers") - #sub.prop(cscene, "debug_tile_size") - #sub.prop(cscene, "debug_min_size") - col = split.column() sub = col.column(align=True) @@ -216,6 +213,8 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel): sub.prop(cscene, "debug_use_spatial_splits") sub.prop(cscene, "use_cache") + sub.prop(cscene, "resolution_divider") + class CyclesRender_PT_layers(CyclesButtonsPanel, Panel): bl_label = "Layers" diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 0cb59f76156..c44a3902f73 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -347,17 +347,8 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use int tile_x = b_engine.tile_x(); int tile_y = b_engine.tile_y(); - if(tile_x == 0 || tile_y == 0) { - tile_x = get_int(cscene, "debug_tile_size"); - tile_y = tile_x; - - params.tile_size = make_int2(tile_x, tile_y); - params.min_size = get_int(cscene, "debug_min_size"); - } - else { - params.tile_size = make_int2(tile_x, tile_y); - params.min_size = min(tile_x, tile_y); - } + params.tile_size = make_int2(tile_x, tile_y); + params.resolution = 1 << get_int(cscene, "resolution_divider"); /* other parameters */ params.threads = b_scene.render().threads(); @@ -368,7 +359,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use if(background) { params.progressive = false; - params.min_size = INT_MAX; + params.resolution = 1; } else params.progressive = true; diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 36bdbd006c9..15f24320ee8 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -36,7 +36,7 @@ CCL_NAMESPACE_BEGIN Session::Session(const SessionParams& params_) : params(params_), - tile_manager(params.progressive, params.samples, params.tile_size, params.min_size, + tile_manager(params.progressive, params.samples, params.tile_size, params.resolution, (params.background)? 1: max(params.device.multi_devices.size(), 1)) { device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background); diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 3867799b559..7b01357a2b7 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -48,7 +48,7 @@ public: bool experimental; int samples; int2 tile_size; - int min_size; + int resolution; int threads; double cancel_timeout; @@ -64,7 +64,7 @@ public: experimental = false; samples = INT_MAX; tile_size = make_int2(64, 64); - min_size = 64; + resolution = 4; threads = 0; cancel_timeout = 0.1; @@ -81,7 +81,7 @@ public: && progressive == params.progressive && experimental == params.experimental && tile_size == params.tile_size - && min_size == params.min_size + && resolution == params.resolution && threads == params.threads && cancel_timeout == params.cancel_timeout && reset_timeout == params.reset_timeout diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index 877e26bf79e..b4156fd9471 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -23,11 +23,11 @@ CCL_NAMESPACE_BEGIN -TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int min_size_, int num_devices_) +TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int resolution_, int num_devices_) { progressive = progressive_; tile_size = tile_size_; - min_size = min_size_; + resolution = resolution_; num_devices = num_devices_; BufferParams buffer_params; @@ -42,19 +42,6 @@ void TileManager::reset(BufferParams& params_, int num_samples_) { params = params_; - start_resolution = 1; - - int w = params.width, h = params.height; - - if(min_size != INT_MAX) { - while(w*h > min_size*min_size) { - w = max(1, w/2); - h = max(1, h/2); - - start_resolution *= 2; - } - } - num_samples = num_samples_; state.buffer = BufferParams(); @@ -62,7 +49,7 @@ void TileManager::reset(BufferParams& params_, int num_samples_) state.num_tiles = 0; state.num_rendered_tiles = 0; state.num_samples = 0; - state.resolution = start_resolution; + state.resolution = resolution; state.tiles.clear(); } diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h index a4a518b1eb4..29f2b1ef9f9 100644 --- a/intern/cycles/render/tile.h +++ b/intern/cycles/render/tile.h @@ -57,7 +57,7 @@ public: list tiles; } state; - TileManager(bool progressive, int num_samples, int2 tile_size, int min_size, int num_devices = 1); + TileManager(bool progressive, int num_samples, int2 tile_size, int resolution, int num_devices = 1); ~TileManager(); void reset(BufferParams& params, int num_samples); @@ -72,7 +72,7 @@ protected: bool progressive; int num_samples; int2 tile_size; - int min_size; + int resolution; int num_devices; int start_resolution; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index b8d5f52b9fd..9d988fbef4a 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -2824,13 +2824,21 @@ static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar, int draw /* create render engine */ if (!rv3d->render_engine) { + RenderEngine *engine; + type = RE_engines_find(scene->r.engine); if (!(type->view_update && type->view_draw)) return 0; - rv3d->render_engine = RE_engine_create(type); - type->view_update(rv3d->render_engine, C); + engine = RE_engine_create(type); + + engine->tile_x = scene->r.xparts; + engine->tile_y = scene->r.yparts; + + type->view_update(engine, C); + + rv3d->render_engine = engine; } /* setup view matrices */ From b37fae861175f2fcdae8c57abfc417801b803b69 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Sun, 12 Aug 2012 12:47:32 +0000 Subject: [PATCH 066/160] Tomato Cycles: *Typo fix. --- intern/cycles/blender/addon/properties.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 4abdfb0d737..3007c44a20c 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -237,7 +237,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): cls.resolution_divider = IntProperty( name="Resolution Divider", - description="Start viewport rendering with lower resolutionm which would be real resolution divided by two in power of this value", + description="Start viewport rendering with lower resolution which would be real resolution divided by two in power of this value", min=1, max=512, default=4, ) From bd71fb6d1dde254fd77e9c3e9201d182c629cf80 Mon Sep 17 00:00:00 2001 From: Peter Schlaile Date: Sun, 12 Aug 2012 15:59:40 +0000 Subject: [PATCH 067/160] == Inpaint Node == Fixed several small (stupid) issues with the inpaint node: * on pixel order building, some ranges got wrong and origin was considered several times. * the convolution kernel didn't consider all pixels (+1,0),(-1,0),(0,1) and (0-1) were omited, leading to suboptimal results (sometimes even black areas) * alpha channel is now only affected an areas considered by inpaint. That's only important, if you choose low iteration counts. --- .../compositor/operations/COM_InpaintOperation.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/blender/compositor/operations/COM_InpaintOperation.cpp b/source/blender/compositor/operations/COM_InpaintOperation.cpp index e586dded8db..eb732cc2b80 100644 --- a/source/blender/compositor/operations/COM_InpaintOperation.cpp +++ b/source/blender/compositor/operations/COM_InpaintOperation.cpp @@ -142,7 +142,7 @@ void InpaintSimpleOperation::calc_manhatten_distance() } for (int j = height - 1; j >= 0; j--) { - for (int i = width; i >= 0; i--) { + for (int i = width - 1; i >= 0; i--) { int r = m[j * width + i]; if (i + 1 < width) @@ -184,8 +184,7 @@ void InpaintSimpleOperation::pix_step(int x, int y) for (int dx = -1; dx <= 1; dx++) { for (int dy = -1; dy <= 1; dy++) { - if (dx != 0 && dy != 0) { - + if (dx != 0 || dy != 0) { int x_ofs = x + dx; int y_ofs = y + dy; @@ -210,6 +209,8 @@ void InpaintSimpleOperation::pix_step(int x, int y) } mul_v3_v3fl(this->get_pixel(x, y), pix, 1.0f / n); + + this->get_pixel(x, y)[3] = 1.0f; } void *InpaintSimpleOperation::initializeTileData(rcti *rect) @@ -243,8 +244,7 @@ void *InpaintSimpleOperation::initializeTileData(rcti *rect) void InpaintSimpleOperation::executePixel(float output[4], int x, int y, void *data) { this->clamp_xy(x, y); - copy_v3_v3(output, this->get_pixel(x, y)); - output[3] = 1.0f; + copy_v4_v4(output, this->get_pixel(x, y)); } void InpaintSimpleOperation::deinitExecution() From 5c29f5bfcf57a8b48905fa46bbb68b41778b169b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 13 Aug 2012 14:51:39 +0000 Subject: [PATCH 068/160] Tomato Cycles: revert some changes of r49835 Apparently for viewport rendering on GPU tile size of 1024 gives much better performance than using single tile. Not sure why it doesn't work for background rendering, need to be investigated further. Meanwhile use old debug value of 1024 for tile size. --- intern/cycles/blender/addon/properties.py | 7 +++++++ intern/cycles/blender/blender_sync.cpp | 20 +++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 3007c44a20c..c23f0196c2d 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -235,6 +235,13 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): default=0.0, ) + cls.debug_tile_size = IntProperty( + name="Tile Size", + description="", + min=1, max=4096, + default=1024, + ) + cls.resolution_divider = IntProperty( name="Resolution Divider", description="Start viewport rendering with lower resolution which would be real resolution divided by two in power of this value", diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index c44a3902f73..d35c93ccbd2 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -344,10 +344,24 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use } /* tiles */ - int tile_x = b_engine.tile_x(); - int tile_y = b_engine.tile_y(); + if(params.device.type != DEVICE_CPU && !background) { + printf("%d\n", get_int(cscene, "debug_tile_size")); + + /* currently GPU could be much slower than CPU when using tiles, + * still need to be investigated, but meanwhile make it possible + * to work in viewport smoothly + */ + int debug_tile_size = get_int(cscene, "debug_tile_size"); + + params.tile_size = make_int2(debug_tile_size, debug_tile_size); + } + else { + int tile_x = b_engine.tile_x(); + int tile_y = b_engine.tile_y(); + + params.tile_size = make_int2(tile_x, tile_y); + } - params.tile_size = make_int2(tile_x, tile_y); params.resolution = 1 << get_int(cscene, "resolution_divider"); /* other parameters */ From 555b6afe2079c111389fd1bb9232b2e22faef416 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 14 Aug 2012 11:12:31 +0000 Subject: [PATCH 069/160] Color Management: convert strips to float if Make Float is enabled but no other filters used Makes it possible to have color corrections in preview for strips which are originally bytes. --- source/blender/blenkernel/intern/sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index cec868cfc10..f342ea088f7 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1678,7 +1678,7 @@ int BKE_sequencer_input_have_to_preprocess(SeqRenderData UNUSED(context), Sequen float mul; if (seq->flag & (SEQ_FILTERY | SEQ_USE_CROP | SEQ_USE_TRANSFORM | SEQ_FLIPX | - SEQ_FLIPY | SEQ_USE_COLOR_BALANCE | SEQ_MAKE_PREMUL)) + SEQ_FLIPY | SEQ_USE_COLOR_BALANCE | SEQ_MAKE_PREMUL | SEQ_MAKE_FLOAT)) { return TRUE; } From 8270293e6a64c5e42d6d08aa5f89d6d2a07d74a0 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 14 Aug 2012 14:45:27 +0000 Subject: [PATCH 070/160] Mango request: display sliders for current point in curve mapping --- .../editors/interface/interface_templates.c | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 37372505e97..5997bd77699 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1743,6 +1743,13 @@ static void curvemap_buttons_redraw(bContext *C, void *UNUSED(arg1), void *UNUSE ED_region_tag_redraw(CTX_wm_region(C)); } +static void curvemap_buttons_update(bContext *UNUSED(C), void *UNUSED(arg1), void *cumap_v) +{ + CurveMapping *cumap = cumap_v; + + curvemapping_changed(cumap, TRUE); +} + static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v) { CurveMapping *cumap = cumap_v; @@ -1765,12 +1772,14 @@ static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v) static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, int brush, RNAUpdateCb *cb) { CurveMapping *cumap = ptr->data; + CurveMap *cm = &cumap->cm[cumap->cur]; + CurveMapPoint *cmp = NULL; uiLayout *row, *sub, *split; uiBlock *block; uiBut *bt; float dx = UI_UNIT_X; int icon, size; - int bg = -1; + int bg = -1, i; block = uiLayoutGetBlock(layout); @@ -1875,6 +1884,21 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe row = uiLayoutRow(layout, FALSE); uiDefBut(block, BUT_CURVE, 0, "", 0, 0, size, MIN2(size, 200), cumap, 0.0f, 1.0f, bg, 0, ""); + /* sliders for selected point */ + for (i = 0; i < cm->totpoint; i++) { + if (cm->curve[i].flag & CUMA_SELECT) { + cmp = &cm->curve[i]; + break; + } + } + + if (cmp) { + uiLayoutColumn(layout, TRUE); + uiBlockSetNFunc(block, curvemap_buttons_update, NULL, cumap); + uiDefButF(block, NUM, 0, "X", 0, 2 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, &cmp->x, 0.0f, 1.0f, 1, 5, ""); + uiDefButF(block, NUM, 0, "Y", 0, 1 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, &cmp->y, 0.0f, 1.0f, 1, 5, ""); + } + /* black/white levels */ if (levels) { split = uiLayoutSplit(layout, 0.0f, FALSE); From 63b5338dbd8706764d12d3890559a71bb0fb2099 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 16 Aug 2012 08:49:43 +0000 Subject: [PATCH 071/160] Fixed incorrect sample counter reported when rendering several render layers --- intern/cycles/render/session.cpp | 3 +++ intern/cycles/util/util_progress.h | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 15f24320ee8..2fb1f49e563 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -532,6 +532,9 @@ void Session::run() /* run */ if(!progress.get_cancel()) { + /* reset number of rendered samples */ + progress.reset_sample(); + if(device_use_gl) run_gpu(); else diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h index 6e2c0c68427..ab9ab7243e9 100644 --- a/intern/cycles/util/util_progress.h +++ b/intern/cycles/util/util_progress.h @@ -120,6 +120,13 @@ public: tile_time_ = tile_time; } + void reset_sample() + { + thread_scoped_lock lock(progress_mutex); + + sample = 0; + } + void increment_sample() { thread_scoped_lock lock(progress_mutex); From bcbd8c00c77694f47a40add5eda45ddc0abea585 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 17 Aug 2012 12:58:31 +0000 Subject: [PATCH 072/160] Tomato Cycles: fix incorrect memory read when synchronizing mesh motion --- intern/cycles/blender/blender_mesh.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 16e4ceded89..9764f24a893 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -317,11 +317,11 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion) BL::Mesh::vertices_iterator v; AttributeStandard std = (motion == -1)? ATTR_STD_MOTION_PRE: ATTR_STD_MOTION_POST; Attribute *attr_M = mesh->attributes.add(std); - float3 *M = attr_M->data_float3(); + float3 *M = attr_M->data_float3(), *cur_M; size_t i = 0; - for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end() && i < size; ++v, M++, i++) - *M = get_float3(v->co()); + for(b_mesh.vertices.begin(v), cur_M = M; v != b_mesh.vertices.end() && i < size; ++v, cur_M++, i++) + *cur_M = get_float3(v->co()); /* if number of vertices changed, or if coordinates stayed the same, drop it */ if(i != size || memcmp(M, &mesh->verts[0], sizeof(float3)*size) == 0) From 900d7d9e35fb2314595f03f6b9f0ae8506577cbf Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 18 Aug 2012 15:46:32 +0000 Subject: [PATCH 073/160] Tomato Cycles: fix crash appearing when direct light usage is different on different layers Seems some variables used for light sampling should be reset when integrator's use_direct_light flag is setting to false, otherwise this values could be used from previously rendered layer resulting in using freed memory of __light_distribution texture. --- intern/cycles/render/light.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index d00b242d153..9d221d56efb 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -289,8 +289,14 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen /* CDF */ device->tex_alloc("__light_distribution", dscene->light_distribution); } - else + else { + kintegrator->num_distribution = 0; + kintegrator->pdf_triangles = 0.0f; + kintegrator->pdf_lights = 0.0f; + kintegrator->num_all_lights = 0; + dscene->light_distribution.clear(); + } } void LightManager::device_update_background(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) From c37a863ff4949ecb474e4f1e396cb52195515d7f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 19 Aug 2012 12:07:28 +0000 Subject: [PATCH 074/160] Tomato Cycles: fix for reading freed memory Incorrect read was happening after nodes which are not affect on output were removed from the graph. Other nodes could have been connected to this nodes which lead to accessing freed memory in some other places. Solved by removing links from unused nodes before removing them from the graph. --- intern/cycles/render/graph.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index 18e802b610d..ce715ad3893 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -402,6 +402,20 @@ void ShaderGraph::clean() /* break cycles */ break_cycles(output(), visited, on_stack); + /* disconnect unused nodes */ + foreach(ShaderNode *node, nodes) { + if(!visited[node->id]) { + foreach(ShaderInput *to, node->inputs) { + ShaderOutput *from = to->link; + + if (from) { + to->link = NULL; + from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end()); + } + } + } + } + /* remove unused nodes */ foreach(ShaderNode *node, nodes) { if(visited[node->id]) From 6f518e0ee9802042459098c4d7ef23aa4a47100a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 20 Aug 2012 16:15:09 +0000 Subject: [PATCH 075/160] Sequencer: clear cache and animation buffers for strips outside of cursor when rendering This avoids having bunch of cached images when doing animation rendering, keeping all the memory available for rendered itself. This keeps memory usage low when rendering huge edits with mixed scenes and movie strips. This should not affect on sped of video encoding, which was confirmed by some own tests. Currently commiting to tomato due to not sure if there's something i can not foresee here. --- source/blender/blenkernel/BKE_sequencer.h | 2 +- source/blender/blenkernel/intern/sequencer.c | 37 +++++-------------- .../editors/space_sequencer/sequencer_edit.c | 10 ++--- .../blender/makesrna/intern/rna_sequencer.c | 2 +- .../blender/render/intern/source/pipeline.c | 2 +- 5 files changed, 17 insertions(+), 36 deletions(-) diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 7a5c45e4800..e79644da967 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -290,7 +290,7 @@ void BKE_sequencer_dupe_animdata(struct Scene *scene, const char *name_src, cons int BKE_sequence_base_shuffle(struct ListBase *seqbasep, struct Sequence *test, struct Scene *evil_scene); int BKE_sequence_base_shuffle_time(ListBase *seqbasep, struct Scene *evil_scene); int BKE_sequence_base_isolated_sel_check(struct ListBase *seqbase); -void BKE_sequencer_free_imbuf(struct Scene *scene, struct ListBase *seqbasep, int check_mem_usage, int keep_file_handles); +void BKE_sequencer_free_imbuf(struct Scene *scene, struct ListBase *seqbasep, int for_render); struct Sequence *BKE_sequence_dupli_recursive(struct Scene *scene, struct Scene *scene_to, struct Sequence *seq, int dupe_flag); int BKE_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char **error_str); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index edbbbe10300..14dd4f6d053 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -2991,46 +2991,27 @@ void BKE_sequence_invalidate_cache_for_modifier(Scene *scene, Sequence *seq) sequence_invalidate_cache(scene, seq, FALSE); } -void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, int check_mem_usage, int keep_file_handles) +void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, int for_render) { Sequence *seq; - if (check_mem_usage) { - /* Let the cache limitor take care of this (schlaile) */ - /* While render let's keep all memory available for render - * (ton) - * At least if free memory is tight... - * This can make a big difference in encoding speed - * (it is around 4 times(!) faster, if we do not waste time - * on freeing _all_ buffers every time on long timelines...) - * (schlaile) - */ - - uintptr_t mem_in_use; - uintptr_t mmap_in_use; - uintptr_t max; - - mem_in_use = MEM_get_memory_in_use(); - mmap_in_use = MEM_get_mapped_memory_in_use(); - max = MEM_CacheLimiter_get_maximum(); - - if (max == 0 || mem_in_use + mmap_in_use <= max) { - return; - } - } - BKE_sequencer_cache_cleanup(); - + for (seq = seqbase->first; seq; seq = seq->next) { + if (for_render && CFRA >= seq->startdisp && CFRA <= seq->enddisp) { + continue; + } + if (seq->strip) { - if (seq->type == SEQ_TYPE_MOVIE && !keep_file_handles) + if (seq->type == SEQ_TYPE_MOVIE) { free_anim_seq(seq); + } if (seq->type == SEQ_TYPE_SPEED) { BKE_sequence_effect_speed_rebuild_map(scene, seq, 1); } } if (seq->type == SEQ_TYPE_META) { - BKE_sequencer_free_imbuf(scene, &seq->seqbase, FALSE, keep_file_handles); + BKE_sequencer_free_imbuf(scene, &seq->seqbase, for_render); } if (seq->type == SEQ_TYPE_SCENE) { /* FIXME: recurs downwards, diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 5bb3f710133..64fd2cbf3bf 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -170,7 +170,7 @@ static void proxy_endjob(void *pjv) BKE_sequencer_proxy_rebuild_finish(link->data, pj->stop); } - BKE_sequencer_free_imbuf(pj->scene, &ed->seqbase, FALSE, FALSE); + BKE_sequencer_free_imbuf(pj->scene, &ed->seqbase, FALSE); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, pj->scene); } @@ -1340,7 +1340,7 @@ static int sequencer_refresh_all_exec(bContext *C, wmOperator *UNUSED(op)) Scene *scene = CTX_data_scene(C); Editing *ed = BKE_sequencer_editing_get(scene, FALSE); - BKE_sequencer_free_imbuf(scene, &ed->seqbase, FALSE, FALSE); + BKE_sequencer_free_imbuf(scene, &ed->seqbase, FALSE); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -2880,7 +2880,7 @@ static int sequencer_change_effect_input_exec(bContext *C, wmOperator *op) BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1); /* important else we don't get the imbuf cache flushed */ - BKE_sequencer_free_imbuf(scene, &ed->seqbase, FALSE, FALSE); + BKE_sequencer_free_imbuf(scene, &ed->seqbase, FALSE); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -2940,7 +2940,7 @@ static int sequencer_change_effect_type_exec(bContext *C, wmOperator *op) BKE_sequencer_update_changed_seq_and_deps(scene, seq, 0, 1); /* important else we don't get the imbuf cache flushed */ - BKE_sequencer_free_imbuf(scene, &ed->seqbase, FALSE, FALSE); + BKE_sequencer_free_imbuf(scene, &ed->seqbase, FALSE); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -3013,7 +3013,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op) BKE_sequence_calc(scene, seq); /* important else we don't get the imbuf cache flushed */ - BKE_sequencer_free_imbuf(scene, &ed->seqbase, FALSE, FALSE); + BKE_sequencer_free_imbuf(scene, &ed->seqbase, FALSE); } else { /* lame, set rna filepath */ diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index e14c1db8a76..5717fe697b1 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -659,7 +659,7 @@ static void rna_Sequence_update_reopen_files(Main *UNUSED(bmain), Scene *UNUSED( Scene *scene = (Scene *) ptr->id.data; Editing *ed = BKE_sequencer_editing_get(scene, FALSE); - BKE_sequencer_free_imbuf(scene, &ed->seqbase, FALSE, FALSE); + BKE_sequencer_free_imbuf(scene, &ed->seqbase, FALSE); if (RNA_struct_is_a(ptr->type, &RNA_SoundSequence)) BKE_sequencer_update_sound_bounds(scene, ptr->data); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index d5851bad406..abb52efe2da 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1689,7 +1689,7 @@ static void do_render_seq(Render *re) if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */ Editing *ed = re->scene->ed; if (ed) - BKE_sequencer_free_imbuf(re->scene, &ed->seqbase, TRUE, TRUE); + BKE_sequencer_free_imbuf(re->scene, &ed->seqbase, TRUE); } IMB_freeImBuf(ibuf); } From abda89bf4d6e145164c0767989ae3f32a77cc9b5 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 21 Aug 2012 08:57:24 +0000 Subject: [PATCH 076/160] Fix cycles continuously updating when creating a driver for a scene property, like driving integrator seed with #frame. The scene drivers are evaluated continuously, which would be nice to fix but complicated, now it compares the RNA value to see if it actually changed, and avoids the update in that case, which is a useful optimization by itself. --- source/blender/blenkernel/intern/anim_sys.c | 58 +++++++++++++++------ 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 8e8c98a38e4..a4bf7bd9720 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1145,6 +1145,7 @@ static short animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_in /* set value - only for animatable numerical values */ if (RNA_property_animateable(&new_ptr, prop)) { int array_len = RNA_property_array_length(&new_ptr, prop); + int written = FALSE; if (array_len && array_index >= array_len) { if (G.debug & G_DEBUG) { @@ -1158,25 +1159,52 @@ static short animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_in switch (RNA_property_type(prop)) { case PROP_BOOLEAN: - if (array_len) - RNA_property_boolean_set_index(&new_ptr, prop, array_index, ANIMSYS_FLOAT_AS_BOOL(value)); - else - RNA_property_boolean_set(&new_ptr, prop, ANIMSYS_FLOAT_AS_BOOL(value)); + if (array_len) { + if (RNA_property_boolean_get_index(&new_ptr, prop, array_index) != ANIMSYS_FLOAT_AS_BOOL(value)) { + RNA_property_boolean_set_index(&new_ptr, prop, array_index, ANIMSYS_FLOAT_AS_BOOL(value)); + written = TRUE; + } + } + else { + if (RNA_property_boolean_get(&new_ptr, prop) != ANIMSYS_FLOAT_AS_BOOL(value)) { + RNA_property_boolean_set(&new_ptr, prop, ANIMSYS_FLOAT_AS_BOOL(value)); + written = TRUE; + } + } break; case PROP_INT: - if (array_len) - RNA_property_int_set_index(&new_ptr, prop, array_index, (int)value); - else - RNA_property_int_set(&new_ptr, prop, (int)value); + if (array_len) { + if (RNA_property_int_get_index(&new_ptr, prop, array_index) != (int)value) { + RNA_property_int_set_index(&new_ptr, prop, array_index, (int)value); + written = TRUE; + } + } + else { + if (RNA_property_int_get(&new_ptr, prop) != (int)value) { + RNA_property_int_set(&new_ptr, prop, (int)value); + written = TRUE; + } + } break; case PROP_FLOAT: - if (array_len) - RNA_property_float_set_index(&new_ptr, prop, array_index, value); - else - RNA_property_float_set(&new_ptr, prop, value); + if (array_len) { + if (RNA_property_float_get_index(&new_ptr, prop, array_index) != value) { + RNA_property_float_set_index(&new_ptr, prop, array_index, value); + written = TRUE; + } + } + else { + if (RNA_property_float_get(&new_ptr, prop) != value) { + RNA_property_float_set(&new_ptr, prop, value); + written = TRUE; + } + } break; case PROP_ENUM: - RNA_property_enum_set(&new_ptr, prop, (int)value); + if (RNA_property_enum_get(&new_ptr, prop) != (int)value) { + RNA_property_enum_set(&new_ptr, prop, (int)value); + written = TRUE; + } break; default: /* nothing can be done here... so it is unsuccessful? */ @@ -1186,7 +1214,7 @@ static short animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_in /* RNA property update disabled for now - [#28525] [#28690] [#28774] [#28777] */ #if 0 /* buffer property update for later flushing */ - if (RNA_property_update_check(prop)) { + if (written && RNA_property_update_check(prop)) { short skip_updates_hack = 0; /* optimization hacks: skip property updates for those properties @@ -1206,7 +1234,7 @@ static short animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_in /* as long as we don't do property update, we still tag datablock * as having been updated. this flag does not cause any updates to * be run, it's for e.g. render engines to synchronize data */ - if (new_ptr.id.data) { + if (written && new_ptr.id.data) { ID *id = new_ptr.id.data; id->flag |= LIB_ID_RECALC; DAG_id_type_tag(G.main, GS(id->name)); From 66f694fca39cafdb88a9fd9d0e8d731f1f369961 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 21 Aug 2012 09:01:50 +0000 Subject: [PATCH 077/160] Fix cycles issue with non-progressive integrator and AO, setting AO samples > 1 did not give properly normalized values. --- intern/cycles/kernel/kernel_path.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index f5188345948..8d983a4ec75 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -693,7 +693,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam if(kernel_data.integrator.use_ambient_occlusion) { int num_samples = kernel_data.integrator.ao_samples; float num_samples_inv = 1.0f/num_samples; - float ao_factor = kernel_data.background.ao_factor/num_samples; + float ao_factor = kernel_data.background.ao_factor; for(int j = 0; j < num_samples; j++) { /* todo: solve correlation */ From dd65a6b67d9bbc01e82e94c399e4721538c714be Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 22 Aug 2012 14:23:08 +0000 Subject: [PATCH 078/160] Color Management: pipeline cleanup - Move color management settings to scene, so it's now clear for all areas (such as compositor, sequencer) which settings to use for display buffers - Currently removed per-editor color management settings. It could be nice to have them, but they don't fit nicely into overall pipeline and could be added as a override settings for display only later. - Make sequencer working in space defined by sequencer_workspace role in OCIO configuration file. If this role is not set, sequencer will fallback to legacy sRGB Gamma 2.2 space. Currently use vd16 color space for sequencer. Not sure what exactly this color space is, but it's pretty close to SPI Film view and it's still invertable. - Sequencer will now output linear float buffers, not color managed float buffers. Before this sequencer used to output float buffers in sRGB space, which was sequencer's working space. Now it can not output buffers in this space since other areas are not aware of this space. This also makes it's consistent that all float buffers in Blender are in linear space. - When saving render result into byte file format scene's display transform would be applied on this buffer. When saving files from image editor, there'll be a display transform settings which are default set to scene's settings but could also be overwritten. Additional details are there (would be extended soon): http://wiki.blender.org/index.php/User:Nazg-gul/ColorManagement --- intern/opencolorio/ocio_capi.h | 1 + release/datafiles/colormanagement/config.ocio | 61 +- .../datafiles/colormanagement/luts/srgb.spi1d | 4107 + .../datafiles/colormanagement/luts/vd16.spi1d | 131079 +++++++++++++++ .../startup/bl_ui/properties_render.py | 2 +- .../scripts/startup/bl_ui/properties_scene.py | 15 + release/scripts/startup/bl_ui/space_clip.py | 13 - release/scripts/startup/bl_ui/space_image.py | 12 - release/scripts/startup/bl_ui/space_info.py | 4 - release/scripts/startup/bl_ui/space_node.py | 12 - .../scripts/startup/bl_ui/space_sequencer.py | 8 +- source/blender/blenkernel/intern/colortools.c | 2 - source/blender/blenkernel/intern/scene.c | 8 +- source/blender/blenkernel/intern/sequencer.c | 27 +- source/blender/editors/include/UI_interface.h | 4 +- .../editors/interface/interface_templates.c | 23 +- source/blender/editors/screen/screen_ops.c | 4 - source/blender/editors/screen/screendump.c | 2 +- source/blender/editors/space_clip/clip_draw.c | 9 +- .../blender/editors/space_clip/space_clip.c | 5 - .../editors/space_image/image_buttons.c | 9 +- .../blender/editors/space_image/image_draw.c | 15 +- .../blender/editors/space_image/image_ops.c | 18 +- .../blender/editors/space_image/space_image.c | 5 - source/blender/editors/space_node/drawnode.c | 9 +- .../blender/editors/space_node/space_node.c | 5 - .../editors/space_sequencer/sequencer_draw.c | 8 +- source/blender/imbuf/IMB_colormanagement.h | 21 +- source/blender/imbuf/IMB_imbuf.h | 5 + source/blender/imbuf/IMB_imbuf_types.h | 7 +- source/blender/imbuf/intern/colormanagement.c | 285 +- source/blender/makesdna/DNA_color_types.h | 6 - source/blender/makesdna/DNA_scene_types.h | 6 +- source/blender/makesdna/DNA_space_types.h | 14 +- .../makesdna/DNA_windowmanager_types.h | 6 - source/blender/makesrna/intern/rna_color.c | 35 +- source/blender/makesrna/intern/rna_scene.c | 11 + source/blender/makesrna/intern/rna_space.c | 21 - source/blender/makesrna/intern/rna_ui_api.c | 3 +- source/blender/makesrna/intern/rna_wm.c | 11 - .../blender/render/intern/source/pipeline.c | 3 +- .../blender/windowmanager/intern/wm_window.c | 2 - 42 files changed, 135571 insertions(+), 332 deletions(-) create mode 100644 release/datafiles/colormanagement/luts/srgb.spi1d create mode 100644 release/datafiles/colormanagement/luts/vd16.spi1d diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index 99412916d2b..1af77ad41ea 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -42,6 +42,7 @@ extern "C" { #define OCIO_ROLE_SCENE_LINEAR "scene_linear" #define OCIO_ROLE_COLOR_PICKING "color_picking" #define OCIO_ROLE_TEXTURE_PAINT "texture_paint" + #define OCIO_ROLE_SEQUENCER "sequencer" OCIO_DECLARE_HANDLE(ConstConfigRcPtr); OCIO_DECLARE_HANDLE(ConstColorSpaceRcPtr); diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio index 8b73303e62a..571c0f8f339 100644 --- a/release/datafiles/colormanagement/config.ocio +++ b/release/datafiles/colormanagement/config.ocio @@ -8,14 +8,10 @@ description: RRT version ut33 roles: color_picking: raw - color_timing: adx10 - compositing_log: adx10 - data: raw - default: raw - matte_paint: raw reference: aces scene_linear: rec709 texture_paint: raw + sequencer: vd16 displays: p3dci: @@ -23,19 +19,19 @@ displays: - ! {name: Log, colorspace: adx10} - ! {name: RRT, colorspace: rrt_p3dci} sRGB: + - ! {name: Gamma2.2, colorspace: sRGB} - ! {name: Raw, colorspace: raw} - - ! {name: Log, colorspace: adx10} - ! {name: RRT, colorspace: rrt_srgb} - - ! {name: SPI Film, colorspace: srgb8} - - ! {name: SPI Log, colorspace: lg10} - - ! {name: Nuke rec709, colorspace: nuke_rec709} + - ! {name: Film, colorspace: srgb8} + - ! {name: Log, colorspace: lg10} + - ! {name: rec709, colorspace: nuke_rec709} xyz: - ! {name: Raw, colorspace: raw} - ! {name: Log, colorspace: adx10} - ! {name: RRT, colorspace: rrt_xyz} active_displays: [sRGB, p3dci, xyz] -active_views: [RRT, Log, SPI Film, SPI Log, Raw] +active_views: [Gamma2.2, RRT, Log, Film, Log, Raw, rec709] colorspaces: - ! @@ -296,3 +292,48 @@ colorspaces: children: - ! {src: rec709.spi1d, interpolation: linear} - ! {src: rec709_to_aces.spimtx, interpolation: nearest} + + - ! + name: sRGB + family: "" + equalitygroup: "" + bitdepth: 32f + description: | + Standard RGB Display Space + isdata: false + allocation: uniform + allocationvars: [-0.125, 1.125] + to_reference: ! + children: + - ! {src: srgb.spi1d, interpolation: linear} + - ! {src: rec709_to_aces.spimtx, interpolation: nearest} + + - ! + name: vd16 + family: vd + equalitygroup: + bitdepth: 16ui + description: | + vd16 : The simple video conversion from a gamma 2.2 srgb space + isdata: false + allocation: uniform + to_reference: ! + children: + - ! {src: vd16.spi1d, interpolation: nearest} + - ! {src: rec709_to_aces.spimtx, interpolation: linear} + + - ! + name: Gamma2.2 + family: "" + equalitygroup: "" + bitdepth: 32f + description: | + Emulates a idealized Gamma 2.2 display device. + isdata: false + allocation: uniform + allocationvars: [0, 1] + to_reference: ! + children: + #- ! {src: rec709.spi1d, interpolation: linear} + - ! {value: [2.2, 2.2, 2.2, 1]} + - ! {src: rec709_to_aces.spimtx, interpolation: linear} diff --git a/release/datafiles/colormanagement/luts/srgb.spi1d b/release/datafiles/colormanagement/luts/srgb.spi1d new file mode 100644 index 00000000000..f1fb422a763 --- /dev/null +++ b/release/datafiles/colormanagement/luts/srgb.spi1d @@ -0,0 +1,4107 @@ +Version 1 +From -0.125 1.125 +Length 4101 +Components 1 +{ + -0.00967492260062 + -0.00965132522842 + -0.00962772785623 + -0.00960413048403 + -0.00958053311183 + -0.00955693573964 + -0.00953333836744 + -0.00950974099524 + -0.00948614362305 + -0.00946254625085 + -0.00943894887865 + -0.00941535150646 + -0.00939175413426 + -0.00936815676206 + -0.00934455938987 + -0.00932096201767 + -0.00929736464547 + -0.00927376727328 + -0.00925016990108 + -0.00922657252888 + -0.00920297515669 + -0.00917937778449 + -0.00915578041229 + -0.0091321830401 + -0.0091085856679 + -0.0090849882957 + -0.00906139092351 + -0.00903779355131 + -0.00901419617911 + -0.00899059880692 + -0.00896700143472 + -0.00894340406252 + -0.00891980669033 + -0.00889620931813 + -0.00887261194593 + -0.00884901457374 + -0.00882541720154 + -0.00880181982934 + -0.00877822245715 + -0.00875462508495 + -0.00873102771275 + -0.00870743034056 + -0.00868383296836 + -0.00866023559616 + -0.00863663822397 + -0.00861304085177 + -0.00858944347957 + -0.00856584610738 + -0.00854224873518 + -0.00851865136298 + -0.00849505399079 + -0.00847145661859 + -0.00844785924639 + -0.0084242618742 + -0.008400664502 + -0.0083770671298 + -0.00835346975761 + -0.00832987238541 + -0.00830627501321 + -0.00828267764102 + -0.00825908026882 + -0.00823548289662 + -0.00821188552443 + -0.00818828815223 + -0.00816469078003 + -0.00814109340784 + -0.00811749603564 + -0.00809389866344 + -0.00807030129125 + -0.00804670391905 + -0.00802310654685 + -0.00799950917466 + -0.00797591180246 + -0.00795231443027 + -0.00792871705807 + -0.00790511968587 + -0.00788152231368 + -0.00785792494148 + -0.00783432756928 + -0.00781073019709 + -0.00778713282489 + -0.00776353545269 + -0.0077399380805 + -0.0077163407083 + -0.0076927433361 + -0.00766914596391 + -0.00764554859171 + -0.00762195121951 + -0.00759835384732 + -0.00757475647512 + -0.00755115910292 + -0.00752756173073 + -0.00750396435853 + -0.00748036698633 + -0.00745676961414 + -0.00743317224194 + -0.00740957486974 + -0.00738597749755 + -0.00736238012535 + -0.00733878275315 + -0.00731518538096 + -0.00729158800876 + -0.00726799063656 + -0.00724439326437 + -0.00722079589217 + -0.00719719851997 + -0.00717360114778 + -0.00715000377558 + -0.00712640640338 + -0.00710280903119 + -0.00707921165899 + -0.00705561428679 + -0.0070320169146 + -0.0070084195424 + -0.0069848221702 + -0.00696122479801 + -0.00693762742581 + -0.00691403005361 + -0.00689043268142 + -0.00686683530922 + -0.00684323793702 + -0.00681964056483 + -0.00679604319263 + -0.00677244582043 + -0.00674884844824 + -0.00672525107604 + -0.00670165370384 + -0.00667805633165 + -0.00665445895945 + -0.00663086158725 + -0.00660726421506 + -0.00658366684286 + -0.00656006947066 + -0.00653647209847 + -0.00651287472627 + -0.00648927735407 + -0.00646567998188 + -0.00644208260968 + -0.00641848523748 + -0.00639488786529 + -0.00637129049309 + -0.00634769312089 + -0.0063240957487 + -0.0063004983765 + -0.0062769010043 + -0.00625330363211 + -0.00622970625991 + -0.00620610888771 + -0.00618251151552 + -0.00615891414332 + -0.00613531677112 + -0.00611171939893 + -0.00608812202673 + -0.00606452465453 + -0.00604092728234 + -0.00601732991014 + -0.00599373253794 + -0.00597013516575 + -0.00594653779355 + -0.00592294042135 + -0.00589934304916 + -0.00587574567696 + -0.00585214830476 + -0.00582855093257 + -0.00580495356037 + -0.00578135618817 + -0.00575775881598 + -0.00573416144378 + -0.00571056407158 + -0.00568696669939 + -0.00566336932719 + -0.005639771955 + -0.0056161745828 + -0.0055925772106 + -0.00556897983841 + -0.00554538246621 + -0.00552178509401 + -0.00549818772182 + -0.00547459034962 + -0.00545099297742 + -0.00542739560523 + -0.00540379823303 + -0.00538020086083 + -0.00535660348864 + -0.00533300611644 + -0.00530940874424 + -0.00528581137205 + -0.00526221399985 + -0.00523861662765 + -0.00521501925546 + -0.00519142188326 + -0.00516782451106 + -0.00514422713887 + -0.00512062976667 + -0.00509703239447 + -0.00507343502228 + -0.00504983765008 + -0.00502624027788 + -0.00500264290569 + -0.00497904553349 + -0.00495544816129 + -0.0049318507891 + -0.0049082534169 + -0.0048846560447 + -0.00486105867251 + -0.00483746130031 + -0.00481386392811 + -0.00479026655592 + -0.00476666918372 + -0.00474307181152 + -0.00471947443933 + -0.00469587706713 + -0.00467227969493 + -0.00464868232274 + -0.00462508495054 + -0.00460148757834 + -0.00457789020615 + -0.00455429283395 + -0.00453069546175 + -0.00450709808956 + -0.00448350071736 + -0.00445990334516 + -0.00443630597297 + -0.00441270860077 + -0.00438911122857 + -0.00436551385638 + -0.00434191648418 + -0.00431831911198 + -0.00429472173979 + -0.00427112436759 + -0.00424752699539 + -0.0042239296232 + -0.004200332251 + -0.0041767348788 + -0.00415313750661 + -0.00412954013441 + -0.00410594276221 + -0.00408234539002 + -0.00405874801782 + -0.00403515064562 + -0.00401155327343 + -0.00398795590123 + -0.00396435852903 + -0.00394076115684 + -0.00391716378464 + -0.00389356641244 + -0.00386996904025 + -0.00384637166805 + -0.00382277429585 + -0.00379917692366 + -0.00377557955146 + -0.00375198217926 + -0.00372838480707 + -0.00370478743487 + -0.00368119006267 + -0.00365759269048 + -0.00363399531828 + -0.00361039794608 + -0.00358680057389 + -0.00356320320169 + -0.00353960582949 + -0.0035160084573 + -0.0034924110851 + -0.0034688137129 + -0.00344521634071 + -0.00342161896851 + -0.00339802159632 + -0.00337442422412 + -0.00335082685192 + -0.00332722947973 + -0.00330363210753 + -0.00328003473533 + -0.00325643736314 + -0.00323283999094 + -0.00320924261874 + -0.00318564524655 + -0.00316204787435 + -0.00313845050215 + -0.00311485312996 + -0.00309125575776 + -0.00306765838556 + -0.00304406101337 + -0.00302046364117 + -0.00299686626897 + -0.00297326889678 + -0.00294967152458 + -0.00292607415238 + -0.00290247678019 + -0.00287887940799 + -0.00285528203579 + -0.0028316846636 + -0.0028080872914 + -0.0027844899192 + -0.00276089254701 + -0.00273729517481 + -0.00271369780261 + -0.00269010043042 + -0.00266650305822 + -0.00264290568602 + -0.00261930831383 + -0.00259571094163 + -0.00257211356943 + -0.00254851619724 + -0.00252491882504 + -0.00250132145284 + -0.00247772408065 + -0.00245412670845 + -0.00243052933625 + -0.00240693196406 + -0.00238333459186 + -0.00235973721966 + -0.00233613984747 + -0.00231254247527 + -0.00228894510307 + -0.00226534773088 + -0.00224175035868 + -0.00221815298648 + -0.00219455561429 + -0.00217095824209 + -0.00214736086989 + -0.0021237634977 + -0.0021001661255 + -0.0020765687533 + -0.00205297138111 + -0.00202937400891 + -0.00200577663671 + -0.00198217926452 + -0.00195858189232 + -0.00193498452012 + -0.00191138714793 + -0.00188778977573 + -0.00186419240353 + -0.00184059503134 + -0.00181699765914 + -0.00179340028694 + -0.00176980291475 + -0.00174620554255 + -0.00172260817035 + -0.00169901079816 + -0.00167541342596 + -0.00165181605376 + -0.00162821868157 + -0.00160462130937 + -0.00158102393717 + -0.00155742656498 + -0.00153382919278 + -0.00151023182058 + -0.00148663444839 + -0.00146303707619 + -0.00143943970399 + -0.0014158423318 + -0.0013922449596 + -0.0013686475874 + -0.00134505021521 + -0.00132145284301 + -0.00129785547081 + -0.00127425809862 + -0.00125066072642 + -0.00122706335422 + -0.00120346598203 + -0.00117986860983 + -0.00115627123763 + -0.00113267386544 + -0.00110907649324 + -0.00108547912105 + -0.00106188174885 + -0.00103828437665 + -0.00101468700446 + -0.000991089632259 + -0.000967492260062 + -0.000943894887865 + -0.000920297515669 + -0.000896700143472 + -0.000873102771275 + -0.000849505399079 + -0.000825908026882 + -0.000802310654685 + -0.000778713282489 + -0.000755115910292 + -0.000731518538096 + -0.000707921165899 + -0.000684323793702 + -0.000660726421506 + -0.000637129049309 + -0.000613531677112 + -0.000589934304916 + -0.000566336932719 + -0.000542739560523 + -0.000519142188326 + -0.000495544816129 + -0.000471947443933 + -0.000448350071736 + -0.000424752699539 + -0.000401155327343 + -0.000377557955146 + -0.000353960582949 + -0.000330363210753 + -0.000306765838556 + -0.00028316846636 + -0.000259571094163 + -0.000235973721966 + -0.00021237634977 + -0.000188778977573 + -0.000165181605376 + -0.00014158423318 + -0.000117986860983 + -9.43894887865e-05 + -7.07921165899e-05 + -4.71947443933e-05 + -2.35973721966e-05 + 0.0 + 2.35973721966e-05 + 4.71947443933e-05 + 7.07921165899e-05 + 9.43894887865e-05 + 0.000117986860983 + 0.00014158423318 + 0.000165181605376 + 0.000188778977573 + 0.00021237634977 + 0.000235973721966 + 0.000259571094163 + 0.00028316846636 + 0.000306765838556 + 0.000330363210753 + 0.000353960582949 + 0.000377557955146 + 0.000401155327343 + 0.000424752699539 + 0.000448350071736 + 0.000471947443933 + 0.000495544816129 + 0.000519142188326 + 0.000542739560523 + 0.000566336932719 + 0.000589934304916 + 0.000613531677112 + 0.000637129049309 + 0.000660726421506 + 0.000684323793702 + 0.000707921165899 + 0.000731518538096 + 0.000755115910292 + 0.000778713282489 + 0.000802310654685 + 0.000825908026882 + 0.000849505399079 + 0.000873102771275 + 0.000896700143472 + 0.000920297515669 + 0.000943894887865 + 0.000967492260062 + 0.000991089632259 + 0.00101468700446 + 0.00103828437665 + 0.00106188174885 + 0.00108547912105 + 0.00110907649324 + 0.00113267386544 + 0.00115627123763 + 0.00117986860983 + 0.00120346598203 + 0.00122706335422 + 0.00125066072642 + 0.00127425809862 + 0.00129785547081 + 0.00132145284301 + 0.00134505021521 + 0.0013686475874 + 0.0013922449596 + 0.0014158423318 + 0.00143943970399 + 0.00146303707619 + 0.00148663444839 + 0.00151023182058 + 0.00153382919278 + 0.00155742656498 + 0.00158102393717 + 0.00160462130937 + 0.00162821868157 + 0.00165181605376 + 0.00167541342596 + 0.00169901079816 + 0.00172260817035 + 0.00174620554255 + 0.00176980291475 + 0.00179340028694 + 0.00181699765914 + 0.00184059503134 + 0.00186419240353 + 0.00188778977573 + 0.00191138714793 + 0.00193498452012 + 0.00195858189232 + 0.00198217926452 + 0.00200577663671 + 0.00202937400891 + 0.00205297138111 + 0.0020765687533 + 0.0021001661255 + 0.0021237634977 + 0.00214736086989 + 0.00217095824209 + 0.00219455561429 + 0.00221815298648 + 0.00224175035868 + 0.00226534773088 + 0.00228894510307 + 0.00231254247527 + 0.00233613984747 + 0.00235973721966 + 0.00238333459186 + 0.00240693196406 + 0.00243052933625 + 0.00245412670845 + 0.00247772408065 + 0.00250132145284 + 0.00252491882504 + 0.00254851619724 + 0.00257211356943 + 0.00259571094163 + 0.00261930831383 + 0.00264290568602 + 0.00266650305822 + 0.00269010043042 + 0.00271369780261 + 0.00273729517481 + 0.00276089254701 + 0.0027844899192 + 0.0028080872914 + 0.0028316846636 + 0.00285528203579 + 0.00287887940799 + 0.00290247678019 + 0.00292607415238 + 0.00294967152458 + 0.00297326889678 + 0.00299686626897 + 0.00302046364117 + 0.00304406101337 + 0.00306765838556 + 0.00309125575776 + 0.00311485312996 + 0.0031385890345 + 0.00316267788401 + 0.00318687423862 + 0.00321117823498 + 0.00323559000948 + 0.00326010969823 + 0.00328473743711 + 0.00330947336173 + 0.00333431760746 + 0.00335927030939 + 0.00338433160238 + 0.00340950162104 + 0.00343478049972 + 0.00346016837252 + 0.0034856653733 + 0.00351127163568 + 0.00353698729303 + 0.00356281247846 + 0.00358874732486 + 0.00361479196487 + 0.0036409465309 + 0.00366721115511 + 0.00369358596941 + 0.0037200711055 + 0.00374666669484 + 0.00377337286863 + 0.00380018975787 + 0.00382711749331 + 0.00385415620548 + 0.00388130602466 + 0.00390856708091 + 0.00393593950409 + 0.00396342342379 + 0.0039910189694 + 0.00401872627008 + 0.00404654545476 + 0.00407447665216 + 0.00410251999077 + 0.00413067559886 + 0.00415894360449 + 0.00418732413548 + 0.00421581731946 + 0.00424442328382 + 0.00427314215575 + 0.00430197406221 + 0.00433091912997 + 0.00435997748556 + 0.00438914925532 + 0.00441843456538 + 0.00444783354163 + 0.00447734630978 + 0.00450697299533 + 0.00453671372356 + 0.00456656861956 + 0.00459653780821 + 0.00462662141416 + 0.0046568195619 + 0.00468713237568 + 0.00471755997958 + 0.00474810249745 + 0.00477876005296 + 0.00480953276957 + 0.00484042077055 + 0.00487142417896 + 0.00490254311768 + 0.00493377770939 + 0.00496512807657 + 0.0049965943415 + 0.00502817662628 + 0.0050598750528 + 0.00509168974279 + 0.00512362081776 + 0.00515566839903 + 0.00518783260776 + 0.00522011356488 + 0.00525251139117 + 0.0052850262072 + 0.00531765813336 + 0.00535040728986 + 0.00538327379672 + 0.00541625777377 + 0.00544935934067 + 0.0054825786169 + 0.00551591572174 + 0.00554937077429 + 0.0055829438935 + 0.00561663519811 + 0.00565044480668 + 0.00568437283762 + 0.00571841940914 + 0.00575258463927 + 0.00578686864589 + 0.00582127154667 + 0.00585579345914 + 0.00589043450063 + 0.00592519478831 + 0.00596007443917 + 0.00599507357003 + 0.00603019229756 + 0.00606543073822 + 0.00610078900832 + 0.00613626722402 + 0.00617186550129 + 0.00620758395592 + 0.00624342270356 + 0.00627938185968 + 0.00631546153959 + 0.00635166185843 + 0.00638798293118 + 0.00642442487264 + 0.00646098779746 + 0.00649767182014 + 0.006534477055 + 0.0065714036162 + 0.00660845161773 + 0.00664562117345 + 0.00668291239704 + 0.00672032540201 + 0.00675786030174 + 0.00679551720942 + 0.00683329623811 + 0.0068711975007 + 0.00690922110993 + 0.00694736717837 + 0.00698563581845 + 0.00702402714244 + 0.00706254126247 + 0.00710117829048 + 0.0071399383383 + 0.00717882151758 + 0.00721782793983 + 0.0072569577164 + 0.00729621095851 + 0.0073355877772 + 0.00737508828338 + 0.00741471258781 + 0.00745446080109 + 0.00749433303369 + 0.00753432939592 + 0.00757444999795 + 0.00761469494979 + 0.00765506436132 + 0.00769555834227 + 0.00773617700222 + 0.00777692045062 + 0.00781778879675 + 0.00785878214977 + 0.00789990061869 + 0.00794114431238 + 0.00798251333957 + 0.00802400780883 + 0.00806562782861 + 0.00810737350722 + 0.00814924495281 + 0.00819124227342 + 0.00823336557692 + 0.00827561497107 + 0.00831799056348 + 0.0083604924616 + 0.00840312077279 + 0.00844587560423 + 0.008488757063 + 0.00853176525601 + 0.00857490029005 + 0.00861816227179 + 0.00866155130774 + 0.0087050675043 + 0.00874871096771 + 0.0087924818041 + 0.00883638011947 + 0.00888040601966 + 0.00892455961041 + 0.0089688409973 + 0.00901325028581 + 0.00905778758127 + 0.00910245298887 + 0.0091472466137 + 0.00919216856071 + 0.0092372189347 + 0.00928239784036 + 0.00932770538227 + 0.00937314166485 + 0.0094187067924 + 0.00946440086912 + 0.00951022399905 + 0.00955617628612 + 0.00960225783414 + 0.00964846874678 + 0.0096948091276 + 0.00974127908002 + 0.00978787870736 + 0.0098346081128 + 0.00988146739939 + 0.00992845667008 + 0.00997557602767 + 0.0100228255749 + 0.0100702054142 + 0.0101177156482 + 0.0101653563792 + 0.0102131277093 + 0.0102610297407 + 0.0103090625753 + 0.010357226315 + 0.0104055210615 + 0.0104539469164 + 0.0105025039813 + 0.0105511923574 + 0.0106000121461 + 0.0106489634486 + 0.0106980463657 + 0.0107472609986 + 0.0107966074478 + 0.0108460858142 + 0.0108956961983 + 0.0109454387006 + 0.0109953134213 + 0.0110453204607 + 0.011095459919 + 0.011145731896 + 0.0111961364918 + 0.011246673806 + 0.0112973439383 + 0.0113481469883 + 0.0113990830554 + 0.0114501522389 + 0.011501354638 + 0.0115526903519 + 0.0116041594794 + 0.0116557621196 + 0.0117074983712 + 0.0117593683328 + 0.0118113721029 + 0.0118635097801 + 0.0119157814627 + 0.0119681872489 + 0.0120207272367 + 0.0120734015243 + 0.0121262102095 + 0.0121791533901 + 0.0122322311638 + 0.0122854436282 + 0.0123387908808 + 0.0123922730189 + 0.0124458901399 + 0.0124996423408 + 0.0125535297187 + 0.0126075523707 + 0.0126617103934 + 0.0127160038838 + 0.0127704329384 + 0.0128249976537 + 0.0128796981262 + 0.0129345344523 + 0.0129895067281 + 0.0130446150498 + 0.0130998595134 + 0.0131552402149 + 0.01321075725 + 0.0132664107145 + 0.013322200704 + 0.0133781273141 + 0.0134341906401 + 0.0134903907774 + 0.0135467278211 + 0.0136032018666 + 0.0136598130086 + 0.0137165613422 + 0.0137734469623 + 0.0138304699634 + 0.0138876304403 + 0.0139449284876 + 0.0140023641995 + 0.0140599376705 + 0.0141176489949 + 0.0141754982666 + 0.0142334855799 + 0.0142916110287 + 0.0143498747068 + 0.014408276708 + 0.0144668171259 + 0.0145254960541 + 0.0145843135862 + 0.0146432698154 + 0.0147023648351 + 0.0147615987385 + 0.0148209716187 + 0.0148804835686 + 0.0149401346812 + 0.0149999250493 + 0.0150598547657 + 0.0151199239229 + 0.0151801326136 + 0.0152404809302 + 0.0153009689649 + 0.0153615968102 + 0.0154223645582 + 0.0154832723009 + 0.0155443201304 + 0.0156055081386 + 0.0156668364173 + 0.0157283050581 + 0.0157899141528 + 0.015851663793 + 0.0159135540699 + 0.0159755850751 + 0.0160377568997 + 0.0161000696351 + 0.0161625233722 + 0.0162251182021 + 0.0162878542158 + 0.016350731504 + 0.0164137501575 + 0.016476910267 + 0.016540211923 + 0.0166036552161 + 0.0166672402366 + 0.0167309670748 + 0.0167948358211 + 0.0168588465654 + 0.016922999398 + 0.0169872944087 + 0.0170517316874 + 0.017116311324 + 0.0171810334081 + 0.0172458980295 + 0.0173109052775 + 0.0173760552418 + 0.0174413480117 + 0.0175067836764 + 0.0175723623252 + 0.0176380840473 + 0.0177039489316 + 0.0177699570671 + 0.0178361085427 + 0.0179024034472 + 0.0179688418694 + 0.0180354238978 + 0.0181021496209 + 0.0181690191274 + 0.0182360325055 + 0.0183031898435 + 0.0183704912298 + 0.0184379367523 + 0.0185055264993 + 0.0185732605586 + 0.0186411390182 + 0.0187091619659 + 0.0187773294894 + 0.0188456416764 + 0.0189140986145 + 0.0189827003912 + 0.0190514470939 + 0.0191203388099 + 0.0191893756265 + 0.019258557631 + 0.0193278849103 + 0.0193973575516 + 0.0194669756418 + 0.0195367392677 + 0.0196066485162 + 0.019676703474 + 0.0197469042277 + 0.0198172508639 + 0.0198877434691 + 0.0199583821296 + 0.0200291669319 + 0.0201000979621 + 0.0201711753065 + 0.0202423990512 + 0.0203137692821 + 0.0203852860853 + 0.0204569495466 + 0.0205287597519 + 0.0206007167868 + 0.020672820737 + 0.020745071688 + 0.0208174697255 + 0.0208900149348 + 0.0209627074012 + 0.0210355472101 + 0.0211085344467 + 0.021181669196 + 0.0212549515432 + 0.0213283815732 + 0.021401959371 + 0.0214756850213 + 0.021549558609 + 0.0216235802187 + 0.0216977499351 + 0.0217720678426 + 0.0218465340259 + 0.0219211485693 + 0.021995911557 + 0.0220708230735 + 0.0221458832028 + 0.0222210920291 + 0.0222964496364 + 0.0223719561088 + 0.02244761153 + 0.0225234159839 + 0.0225993695544 + 0.0226754723251 + 0.0227517243795 + 0.0228281258014 + 0.022904676674 + 0.0229813770809 + 0.0230582271055 + 0.0231352268308 + 0.0232123763403 + 0.0232896757169 + 0.0233671250438 + 0.023444724404 + 0.0235224738803 + 0.0236003735557 + 0.0236784235129 + 0.0237566238346 + 0.0238349746036 + 0.0239134759023 + 0.0239921278133 + 0.0240709304191 + 0.024149883802 + 0.0242289880444 + 0.0243082432284 + 0.0243876494363 + 0.0244672067502 + 0.0245469152521 + 0.024626775024 + 0.0247067861478 + 0.0247869487054 + 0.0248672627785 + 0.0249477284489 + 0.0250283457981 + 0.0251091149078 + 0.0251900358596 + 0.0252711087347 + 0.0253523336147 + 0.0254337105808 + 0.0255152397143 + 0.0255969210965 + 0.0256787548083 + 0.0257607409309 + 0.0258428795452 + 0.0259251707322 + 0.0260076145728 + 0.0260902111478 + 0.0261729605378 + 0.0262558628236 + 0.0263389180858 + 0.0264221264049 + 0.0265054878614 + 0.0265890025358 + 0.0266726705083 + 0.0267564918593 + 0.026840466669 + 0.0269245950175 + 0.0270088769851 + 0.0270933126516 + 0.0271779020971 + 0.0272626454016 + 0.0273475426448 + 0.0274325939065 + 0.0275177992666 + 0.0276031588046 + 0.0276886726001 + 0.0277743407328 + 0.027860163282 + 0.0279461403273 + 0.0280322719479 + 0.0281185582232 + 0.0282049992324 + 0.0282915950547 + 0.0283783457692 + 0.0284652514549 + 0.0285523121909 + 0.0286395280562 + 0.0287268991294 + 0.0288144254896 + 0.0289021072154 + 0.0289899443855 + 0.0290779370787 + 0.0291660853733 + 0.0292543893481 + 0.0293428490813 + 0.0294314646515 + 0.029520236137 + 0.029609163616 + 0.0296982471668 + 0.0297874868674 + 0.0298768827962 + 0.029966435031 + 0.0300561436499 + 0.0301460087307 + 0.0302360303515 + 0.0303262085899 + 0.0304165435238 + 0.0305070352307 + 0.0305976837885 + 0.0306884892746 + 0.0307794517666 + 0.0308705713419 + 0.030961848078 + 0.0310532820522 + 0.0311448733418 + 0.031236622024 + 0.0313285281761 + 0.0314205918751 + 0.0315128131981 + 0.0316051922222 + 0.0316977290242 + 0.0317904236811 + 0.0318832762697 + 0.0319762868669 + 0.0320694555492 + 0.0321627823935 + 0.0322562674764 + 0.0323499108743 + 0.0324437126639 + 0.0325376729215 + 0.0326317917235 + 0.0327260691464 + 0.0328205052664 + 0.0329151001597 + 0.0330098539025 + 0.0331047665709 + 0.033199838241 + 0.0332950689888 + 0.0333904588903 + 0.0334860080213 + 0.0335817164578 + 0.0336775842755 + 0.0337736115501 + 0.0338697983574 + 0.033966144773 + 0.0340626508725 + 0.0341593167313 + 0.034256142425 + 0.034353128029 + 0.0344502736186 + 0.0345475792692 + 0.0346450450561 + 0.0347426710544 + 0.0348404573392 + 0.0349384039858 + 0.0350365110691 + 0.0351347786641 + 0.0352332068458 + 0.0353317956891 + 0.0354305452689 + 0.0355294556598 + 0.0356285269366 + 0.0357277591741 + 0.0358271524468 + 0.0359267068294 + 0.0360264223963 + 0.0361262992221 + 0.0362263373811 + 0.0363265369477 + 0.0364268979963 + 0.0365274206011 + 0.0366281048364 + 0.0367289507762 + 0.0368299584948 + 0.0369311280662 + 0.0370324595644 + 0.0371339530634 + 0.037235608637 + 0.0373374263592 + 0.0374394063038 + 0.0375415485445 + 0.037643853155 + 0.037746320209 + 0.0378489497802 + 0.037951741942 + 0.038054696768 + 0.0381578143316 + 0.0382610947063 + 0.0383645379655 + 0.0384681441823 + 0.0385719134302 + 0.0386758457823 + 0.0387799413118 + 0.0388842000918 + 0.0389886221953 + 0.0390932076954 + 0.0391979566651 + 0.0393028691773 + 0.0394079453048 + 0.0395131851204 + 0.039618588697 + 0.0397241561073 + 0.039829887424 + 0.0399357827196 + 0.0400418420667 + 0.040148065538 + 0.0402544532058 + 0.0403610051427 + 0.0404677214209 + 0.0405746021129 + 0.040681647291 + 0.0407888570273 + 0.0408962313941 + 0.0410037704635 + 0.0411114743077 + 0.0412193429986 + 0.0413273766084 + 0.0414355752089 + 0.0415439388721 + 0.0416524676699 + 0.041761161674 + 0.0418700209563 + 0.0419790455884 + 0.0420882356421 + 0.0421975911889 + 0.0423071123006 + 0.0424167990485 + 0.0425266515043 + 0.0426366697393 + 0.042746853825 + 0.0428572038327 + 0.0429677198337 + 0.0430784018994 + 0.0431892501008 + 0.0433002645092 + 0.0434114451957 + 0.0435227922315 + 0.0436343056874 + 0.0437459856346 + 0.0438578321439 + 0.0439698452863 + 0.0440820251327 + 0.0441943717537 + 0.0443068852203 + 0.0444195656031 + 0.0445324129727 + 0.0446454273999 + 0.0447586089552 + 0.0448719577092 + 0.0449854737323 + 0.0450991570949 + 0.0452130078676 + 0.0453270261206 + 0.0454412119244 + 0.0455555653491 + 0.0456700864649 + 0.0457847753421 + 0.0458996320509 + 0.0460146566613 + 0.0461298492433 + 0.046245209867 + 0.0463607386023 + 0.0464764355192 + 0.0465923006876 + 0.0467083341772 + 0.0468245360579 + 0.0469409063994 + 0.0470574452714 + 0.0471741527436 + 0.0472910288857 + 0.0474080737671 + 0.0475252874574 + 0.0476426700262 + 0.0477602215427 + 0.0478779420766 + 0.0479958316971 + 0.0481138904735 + 0.0482321184751 + 0.0483505157711 + 0.0484690824308 + 0.0485878185233 + 0.0487067241177 + 0.0488257992831 + 0.0489450440884 + 0.0490644586027 + 0.0491840428949 + 0.0493037970339 + 0.0494237210886 + 0.0495438151277 + 0.0496640792201 + 0.0497845134344 + 0.0499051178394 + 0.0500258925036 + 0.0501468374958 + 0.0502679528845 + 0.0503892387381 + 0.0505106951252 + 0.0506323221142 + 0.0507541197736 + 0.0508760881716 + 0.0509982273765 + 0.0511205374567 + 0.0512430184805 + 0.0513656705159 + 0.0514884936311 + 0.0516114878943 + 0.0517346533735 + 0.0518579901367 + 0.051981498252 + 0.0521051777872 + 0.0522290288104 + 0.0523530513893 + 0.0524772455919 + 0.0526016114858 + 0.0527261491388 + 0.0528508586187 + 0.0529757399931 + 0.0531007933296 + 0.0532260186959 + 0.0533514161594 + 0.0534769857877 + 0.0536027276483 + 0.0537286418086 + 0.0538547283359 + 0.0539809872976 + 0.0541074187611 + 0.0542340227936 + 0.0543607994623 + 0.0544877488345 + 0.0546148709772 + 0.0547421659577 + 0.0548696338429 + 0.0549972746999 + 0.0551250885958 + 0.0552530755974 + 0.0553812357717 + 0.0555095691856 + 0.0556380759059 + 0.0557667559994 + 0.0558956095329 + 0.0560246365731 + 0.0561538371867 + 0.0562832114404 + 0.0564127594007 + 0.0565424811343 + 0.0566723767076 + 0.0568024461872 + 0.0569326896395 + 0.057063107131 + 0.057193698728 + 0.0573244644969 + 0.0574554045039 + 0.0575865188155 + 0.0577178074976 + 0.0578492706167 + 0.0579809082388 + 0.0581127204301 + 0.0582447072565 + 0.0583768687843 + 0.0585092050793 + 0.0586417162076 + 0.0587744022351 + 0.0589072632276 + 0.0590402992511 + 0.0591735103713 + 0.0593068966541 + 0.0594404581651 + 0.0595741949702 + 0.0597081071348 + 0.0598421947248 + 0.0599764578057 + 0.060110896443 + 0.0602455107023 + 0.0603803006491 + 0.0605152663488 + 0.0606504078668 + 0.0607857252685 + 0.0609212186193 + 0.0610568879844 + 0.0611927334292 + 0.0613287550188 + 0.0614649528185 + 0.0616013268934 + 0.0617378773086 + 0.0618746041293 + 0.0620115074204 + 0.062148587247 + 0.0622858436742 + 0.0624232767667 + 0.0625608865896 + 0.0626986732076 + 0.0628366366858 + 0.0629747770887 + 0.0631130944813 + 0.0632515889282 + 0.0633902604941 + 0.0635291092438 + 0.0636681352417 + 0.0638073385526 + 0.0639467192409 + 0.0640862773712 + 0.064226013008 + 0.0643659262156 + 0.0645060170586 + 0.0646462856013 + 0.0647867319081 + 0.0649273560432 + 0.0650681580709 + 0.0652091380555 + 0.0653502960612 + 0.0654916321521 + 0.0656331463924 + 0.0657748388461 + 0.0659167095774 + 0.0660587586503 + 0.0662009861287 + 0.0663433920767 + 0.0664859765581 + 0.0666287396369 + 0.0667716813768 + 0.0669148018418 + 0.0670581010956 + 0.067201579202 + 0.0673452362247 + 0.0674890722274 + 0.0676330872737 + 0.0677772814273 + 0.0679216547518 + 0.0680662073106 + 0.0682109391674 + 0.0683558503856 + 0.0685009410286 + 0.0686462111599 + 0.0687916608429 + 0.0689372901409 + 0.0690830991172 + 0.0692290878351 + 0.0693752563579 + 0.0695216047488 + 0.0696681330709 + 0.0698148413874 + 0.0699617297615 + 0.0701087982562 + 0.0702560469345 + 0.0704034758596 + 0.0705510850943 + 0.0706988747016 + 0.0708468447445 + 0.0709949952858 + 0.0711433263883 + 0.071291838115 + 0.0714405305285 + 0.0715894036917 + 0.0717384576673 + 0.0718876925179 + 0.0720371083062 + 0.0721867050949 + 0.0723364829464 + 0.0724864419235 + 0.0726365820886 + 0.0727869035042 + 0.0729374062327 + 0.0730880903367 + 0.0732389558784 + 0.0733900029203 + 0.0735412315247 + 0.0736926417539 + 0.0738442336702 + 0.0739960073358 + 0.0741479628129 + 0.0743001001637 + 0.0744524194503 + 0.0746049207348 + 0.0747576040794 + 0.074910469546 + 0.0750635171967 + 0.0752167470935 + 0.0753701592983 + 0.075523753873 + 0.0756775308795 + 0.0758314903797 + 0.0759856324354 + 0.0761399571085 + 0.0762944644605 + 0.0764491545534 + 0.0766040274487 + 0.0767590832083 + 0.0769143218936 + 0.0770697435663 + 0.077225348288 + 0.0773811361202 + 0.0775371071245 + 0.0776932613623 + 0.077849598895 + 0.0780061197842 + 0.0781628240911 + 0.0783197118772 + 0.0784767832038 + 0.0786340381321 + 0.0787914767235 + 0.0789490990391 + 0.0791069051402 + 0.079264895088 + 0.0794230689436 + 0.0795814267681 + 0.0797399686225 + 0.0798986945681 + 0.0800576046657 + 0.0802166989763 + 0.080375977561 + 0.0805354404807 + 0.0806950877962 + 0.0808549195685 + 0.0810149358583 + 0.0811751367265 + 0.0813355222339 + 0.0814960924412 + 0.0816568474092 + 0.0818177871984 + 0.0819789118697 + 0.0821402214836 + 0.0823017161008 + 0.0824633957817 + 0.082625260587 + 0.0827873105771 + 0.0829495458126 + 0.0831119663539 + 0.0832745722613 + 0.0834373635955 + 0.0836003404165 + 0.0837635027849 + 0.083926850761 + 0.0840903844049 + 0.0842541037769 + 0.0844180089374 + 0.0845820999463 + 0.084746376864 + 0.0849108397506 + 0.085075488666 + 0.0852403236705 + 0.0854053448241 + 0.0855705521867 + 0.0857359458184 + 0.0859015257791 + 0.0860672921287 + 0.0862332449272 + 0.0863993842344 + 0.0865657101102 + 0.0867322226143 + 0.0868989218065 + 0.0870658077467 + 0.0872328804945 + 0.0874001401096 + 0.0875675866517 + 0.0877352201804 + 0.0879030407554 + 0.0880710484362 + 0.0882392432824 + 0.0884076253535 + 0.088576194709 + 0.0887449514084 + 0.0889138955111 + 0.0890830270765 + 0.0892523461641 + 0.0894218528331 + 0.0895915471429 + 0.0897614291528 + 0.0899314989221 + 0.09010175651 + 0.0902722019757 + 0.0904428353785 + 0.0906136567774 + 0.0907846662317 + 0.0909558638004 + 0.0911272495425 + 0.0912988235173 + 0.0914705857835 + 0.0916425364004 + 0.0918146754267 + 0.0919870029215 + 0.0921595189437 + 0.0923322235521 + 0.0925051168057 + 0.0926781987632 + 0.0928514694834 + 0.0930249290251 + 0.0931985774471 + 0.093372414808 + 0.0935464411666 + 0.0937206565816 + 0.0938950611115 + 0.0940696548149 + 0.0942444377505 + 0.0944194099769 + 0.0945945715524 + 0.0947699225357 + 0.0949454629852 + 0.0951211929593 + 0.0952971125165 + 0.0954732217152 + 0.0956495206136 + 0.0958260092703 + 0.0960026877434 + 0.0961795560913 + 0.0963566143722 + 0.0965338626443 + 0.0967113009659 + 0.0968889293951 + 0.0970667479901 + 0.097244756809 + 0.0974229559098 + 0.0976013453508 + 0.0977799251898 + 0.097958695485 + 0.0981376562943 + 0.0983168076757 + 0.0984961496871 + 0.0986756823864 + 0.0988554058316 + 0.0990353200804 + 0.0992154251908 + 0.0993957212204 + 0.0995762082271 + 0.0997568862687 + 0.0999377554029 + 0.100118815687 + 0.10030006718 + 0.100481509938 + 0.100663144019 + 0.100844969481 + 0.101026986381 + 0.101209194778 + 0.101391594728 + 0.101574186288 + 0.101756969518 + 0.101939944473 + 0.102123111211 + 0.10230646979 + 0.102490020267 + 0.102673762699 + 0.102857697144 + 0.10304182366 + 0.103226142302 + 0.103410653129 + 0.103595356197 + 0.103780251564 + 0.103965339288 + 0.104150619424 + 0.104336092031 + 0.104521757165 + 0.104707614883 + 0.104893665243 + 0.105079908301 + 0.105266344115 + 0.105452972741 + 0.105639794237 + 0.105826808659 + 0.106014016063 + 0.106201416508 + 0.10638901005 + 0.106576796745 + 0.10676477665 + 0.106952949823 + 0.10714131632 + 0.107329876197 + 0.107518629511 + 0.107707576319 + 0.107896716678 + 0.108086050644 + 0.108275578273 + 0.108465299623 + 0.10865521475 + 0.10884532371 + 0.10903562656 + 0.109226123356 + 0.109416814155 + 0.109607699013 + 0.109798777986 + 0.109990051131 + 0.110181518505 + 0.110373180162 + 0.110565036161 + 0.110757086557 + 0.110949331406 + 0.111141770764 + 0.111334404688 + 0.111527233234 + 0.111720256458 + 0.111913474416 + 0.112106887164 + 0.112300494759 + 0.112494297255 + 0.11268829471 + 0.11288248718 + 0.113076874719 + 0.113271457385 + 0.113466235233 + 0.113661208319 + 0.113856376699 + 0.114051740429 + 0.114247299564 + 0.114443054161 + 0.114639004275 + 0.114835149961 + 0.115031491277 + 0.115228028277 + 0.115424761016 + 0.115621689552 + 0.115818813939 + 0.116016134233 + 0.116213650489 + 0.116411362764 + 0.116609271112 + 0.116807375589 + 0.117005676251 + 0.117204173153 + 0.117402866351 + 0.117601755899 + 0.117800841855 + 0.118000124271 + 0.118199603205 + 0.118399278712 + 0.118599150846 + 0.118799219663 + 0.118999485219 + 0.119199947568 + 0.119400606766 + 0.119601462868 + 0.119802515928 + 0.120003766004 + 0.120205213148 + 0.120406857417 + 0.120608698866 + 0.120810737549 + 0.121012973522 + 0.121215406839 + 0.121418037556 + 0.121620865728 + 0.121823891409 + 0.122027114655 + 0.12223053552 + 0.122434154059 + 0.122637970327 + 0.122841984379 + 0.123046196269 + 0.123250606053 + 0.123455213785 + 0.123660019521 + 0.123865023313 + 0.124070225218 + 0.12427562529 + 0.124481223584 + 0.124687020154 + 0.124893015054 + 0.12509920834 + 0.125305600066 + 0.125512190287 + 0.125718979056 + 0.125925966429 + 0.12613315246 + 0.126340537203 + 0.126548120713 + 0.126755903044 + 0.126963884251 + 0.127172064387 + 0.127380443508 + 0.127589021667 + 0.127797798919 + 0.128006775318 + 0.128215950919 + 0.128425325775 + 0.12863489994 + 0.12884467347 + 0.129054646417 + 0.129264818837 + 0.129475190783 + 0.129685762309 + 0.12989653347 + 0.130107504319 + 0.130318674911 + 0.130530045299 + 0.130741615537 + 0.13095338568 + 0.131165355781 + 0.131377525894 + 0.131589896074 + 0.131802466373 + 0.132015236847 + 0.132228207548 + 0.13244137853 + 0.132654749847 + 0.132868321554 + 0.133082093703 + 0.133296066349 + 0.133510239544 + 0.133724613344 + 0.133939187801 + 0.134153962969 + 0.134368938901 + 0.134584115652 + 0.134799493275 + 0.135015071823 + 0.135230851349 + 0.135446831909 + 0.135663013554 + 0.135879396338 + 0.136095980315 + 0.136312765538 + 0.136529752061 + 0.136746939936 + 0.136964329218 + 0.13718191996 + 0.137399712214 + 0.137617706034 + 0.137835901474 + 0.138054298587 + 0.138272897425 + 0.138491698043 + 0.138710700493 + 0.138929904828 + 0.139149311102 + 0.139368919367 + 0.139588729678 + 0.139808742086 + 0.140028956645 + 0.140249373408 + 0.140469992428 + 0.140690813758 + 0.140911837451 + 0.14113306356 + 0.141354492137 + 0.141576123237 + 0.141797956911 + 0.142019993212 + 0.142242232194 + 0.142464673909 + 0.142687318409 + 0.142910165749 + 0.14313321598 + 0.143356469155 + 0.143579925328 + 0.143803584549 + 0.144027446874 + 0.144251512353 + 0.14447578104 + 0.144700252987 + 0.144924928247 + 0.145149806873 + 0.145374888917 + 0.145600174431 + 0.145825663468 + 0.146051356081 + 0.146277252321 + 0.146503352243 + 0.146729655897 + 0.146956163337 + 0.147182874614 + 0.147409789782 + 0.147636908892 + 0.147864231997 + 0.148091759149 + 0.1483194904 + 0.148547425803 + 0.14877556541 + 0.149003909274 + 0.149232457445 + 0.149461209978 + 0.149690166923 + 0.149919328333 + 0.15014869426 + 0.150378264757 + 0.150608039875 + 0.150838019666 + 0.151068204182 + 0.151298593476 + 0.1515291876 + 0.151759986605 + 0.151990990543 + 0.152222199467 + 0.152453613428 + 0.152685232479 + 0.152917056671 + 0.153149086055 + 0.153381320685 + 0.153613760611 + 0.153846405886 + 0.154079256562 + 0.154312312689 + 0.154545574321 + 0.154779041508 + 0.155012714302 + 0.155246592756 + 0.15548067692 + 0.155714966847 + 0.155949462588 + 0.156184164194 + 0.156419071718 + 0.156654185211 + 0.156889504724 + 0.157125030309 + 0.157360762017 + 0.157596699901 + 0.157832844011 + 0.1580691944 + 0.158305751117 + 0.158542514216 + 0.158779483747 + 0.159016659761 + 0.159254042311 + 0.159491631447 + 0.15972942722 + 0.159967429683 + 0.160205638886 + 0.160444054881 + 0.160682677718 + 0.16092150745 + 0.161160544127 + 0.161399787801 + 0.161639238523 + 0.161878896343 + 0.162118761313 + 0.162358833485 + 0.162599112909 + 0.162839599636 + 0.163080293717 + 0.163321195205 + 0.163562304148 + 0.163803620599 + 0.164045144609 + 0.164286876228 + 0.164528815508 + 0.164770962499 + 0.165013317253 + 0.165255879819 + 0.16549865025 + 0.165741628596 + 0.165984814907 + 0.166228209235 + 0.166471811631 + 0.166715622145 + 0.166959640827 + 0.16720386773 + 0.167448302903 + 0.167692946397 + 0.167937798263 + 0.168182858552 + 0.168428127314 + 0.168673604599 + 0.16891929046 + 0.169165184945 + 0.169411288106 + 0.169657599993 + 0.169904120657 + 0.170150850149 + 0.170397788518 + 0.170644935816 + 0.170892292092 + 0.171139857397 + 0.171387631783 + 0.171635615298 + 0.171883807994 + 0.172132209921 + 0.172380821129 + 0.172629641669 + 0.17287867159 + 0.173127910944 + 0.173377359781 + 0.17362701815 + 0.173876886103 + 0.174126963688 + 0.174377250957 + 0.17462774796 + 0.174878454747 + 0.175129371368 + 0.175380497874 + 0.175631834313 + 0.175883380737 + 0.176135137196 + 0.176387103739 + 0.176639280417 + 0.17689166728 + 0.177144264378 + 0.17739707176 + 0.177650089477 + 0.177903317579 + 0.178156756116 + 0.178410405137 + 0.178664264693 + 0.178918334833 + 0.179172615607 + 0.179427107066 + 0.179681809259 + 0.179936722235 + 0.180191846045 + 0.180447180739 + 0.180702726366 + 0.180958482976 + 0.181214450619 + 0.181470629344 + 0.181727019201 + 0.18198362024 + 0.182240432511 + 0.182497456063 + 0.182754690946 + 0.183012137209 + 0.183269794902 + 0.183527664074 + 0.183785744776 + 0.184044037057 + 0.184302540966 + 0.184561256552 + 0.184820183866 + 0.185079322956 + 0.185338673873 + 0.185598236666 + 0.185858011383 + 0.186117998075 + 0.186378196791 + 0.18663860758 + 0.186899230491 + 0.187160065575 + 0.187421112879 + 0.187682372455 + 0.18794384435 + 0.188205528614 + 0.188467425296 + 0.188729534447 + 0.188991856114 + 0.189254390347 + 0.189517137195 + 0.189780096708 + 0.190043268934 + 0.190306653923 + 0.190570251723 + 0.190834062385 + 0.191098085956 + 0.191362322487 + 0.191626772025 + 0.191891434621 + 0.192156310323 + 0.19242139918 + 0.192686701241 + 0.192952216555 + 0.193217945171 + 0.193483887138 + 0.193750042505 + 0.19401641132 + 0.194282993634 + 0.194549789494 + 0.194816798949 + 0.195084022048 + 0.19535145884 + 0.195619109375 + 0.195886973699 + 0.196155051863 + 0.196423343915 + 0.196691849904 + 0.196960569879 + 0.197229503888 + 0.197498651979 + 0.197768014202 + 0.198037590606 + 0.198307381238 + 0.198577386148 + 0.198847605383 + 0.199118038994 + 0.199388687027 + 0.199659549532 + 0.199930626558 + 0.200201918152 + 0.200473424364 + 0.200745145241 + 0.201017080833 + 0.201289231187 + 0.201561596353 + 0.201834176378 + 0.202106971311 + 0.2023799812 + 0.202653206094 + 0.202926646041 + 0.203200301089 + 0.203474171287 + 0.203748256683 + 0.204022557326 + 0.204297073263 + 0.204571804542 + 0.204846751213 + 0.205121913323 + 0.20539729092 + 0.205672884053 + 0.20594869277 + 0.206224717119 + 0.206500957148 + 0.206777412905 + 0.207054084439 + 0.207330971797 + 0.207608075028 + 0.207885394179 + 0.208162929299 + 0.208440680435 + 0.208718647636 + 0.20899683095 + 0.209275230424 + 0.209553846107 + 0.209832678047 + 0.210111726291 + 0.210390990887 + 0.210670471884 + 0.210950169329 + 0.21123008327 + 0.211510213755 + 0.211790560831 + 0.212071124548 + 0.212351904951 + 0.21263290209 + 0.212914116012 + 0.213195546764 + 0.213477194395 + 0.213759058951 + 0.214041140482 + 0.214323439035 + 0.214605954656 + 0.214888687395 + 0.215171637298 + 0.215454804413 + 0.215738188788 + 0.21602179047 + 0.216305609507 + 0.216589645947 + 0.216873899837 + 0.217158371225 + 0.217443060158 + 0.217727966683 + 0.218013090849 + 0.218298432702 + 0.218583992291 + 0.218869769662 + 0.219155764862 + 0.219441977941 + 0.219728408944 + 0.220015057919 + 0.220301924914 + 0.220589009975 + 0.220876313151 + 0.221163834489 + 0.221451574035 + 0.221739531837 + 0.222027707943 + 0.222316102399 + 0.222604715254 + 0.222893546553 + 0.223182596345 + 0.223471864677 + 0.223761351595 + 0.224051057147 + 0.22434098138 + 0.224631124341 + 0.224921486078 + 0.225212066637 + 0.225502866066 + 0.225793884411 + 0.22608512172 + 0.226376578039 + 0.226668253416 + 0.226960147898 + 0.227252261532 + 0.227544594365 + 0.227837146443 + 0.228129917814 + 0.228422908524 + 0.228716118621 + 0.229009548151 + 0.229303197162 + 0.2295970657 + 0.229891153812 + 0.230185461545 + 0.230479988946 + 0.230774736061 + 0.231069702938 + 0.231364889622 + 0.231660296162 + 0.231955922604 + 0.232251768994 + 0.232547835379 + 0.232844121806 + 0.233140628321 + 0.233437354972 + 0.233734301805 + 0.234031468867 + 0.234328856203 + 0.234626463862 + 0.234924291889 + 0.235222340331 + 0.235520609235 + 0.235819098647 + 0.236117808614 + 0.236416739182 + 0.236715890398 + 0.237015262309 + 0.23731485496 + 0.237614668399 + 0.237914702671 + 0.238214957824 + 0.238515433903 + 0.238816130955 + 0.239117049027 + 0.239418188165 + 0.239719548415 + 0.240021129824 + 0.240322932438 + 0.240624956303 + 0.240927201466 + 0.241229667972 + 0.241532355869 + 0.241835265203 + 0.242138396019 + 0.242441748364 + 0.242745322285 + 0.243049117826 + 0.243353135036 + 0.243657373959 + 0.243961834643 + 0.244266517132 + 0.244571421474 + 0.244876547715 + 0.2451818959 + 0.245487466075 + 0.245793258288 + 0.246099272583 + 0.246405509007 + 0.246711967606 + 0.247018648426 + 0.247325551513 + 0.247632676913 + 0.247940024672 + 0.248247594836 + 0.248555387451 + 0.248863402563 + 0.249171640217 + 0.249480100461 + 0.249788783338 + 0.250097688897 + 0.250406817181 + 0.250716168238 + 0.251025742113 + 0.251335538852 + 0.2516455585 + 0.251955801104 + 0.25226626671 + 0.252576955362 + 0.252887867107 + 0.253199001991 + 0.253510360059 + 0.253821941357 + 0.254133745931 + 0.254445773826 + 0.254758025089 + 0.255070499764 + 0.255383197898 + 0.255696119535 + 0.256009264722 + 0.256322633505 + 0.256636225928 + 0.256950042038 + 0.25726408188 + 0.2575783455 + 0.257892832942 + 0.258207544253 + 0.258522479479 + 0.258837638663 + 0.259153021853 + 0.259468629094 + 0.259784460431 + 0.260100515909 + 0.260416795574 + 0.260733299471 + 0.261050027646 + 0.261366980144 + 0.26168415701 + 0.26200155829 + 0.26231918403 + 0.262637034274 + 0.262955109067 + 0.263273408456 + 0.263591932485 + 0.2639106812 + 0.264229654646 + 0.264548852868 + 0.264868275911 + 0.265187923821 + 0.265507796643 + 0.265827894421 + 0.266148217202 + 0.266468765031 + 0.266789537952 + 0.26711053601 + 0.267431759251 + 0.267753207721 + 0.268074881463 + 0.268396780523 + 0.268718904946 + 0.269041254778 + 0.269363830063 + 0.269686630846 + 0.270009657172 + 0.270332909087 + 0.270656386635 + 0.270980089861 + 0.27130401881 + 0.271628173528 + 0.271952554058 + 0.272277160447 + 0.272601992739 + 0.272927050978 + 0.27325233521 + 0.27357784548 + 0.273903581832 + 0.274229544312 + 0.274555732963 + 0.274882147832 + 0.275208788962 + 0.275535656399 + 0.275862750187 + 0.276190070371 + 0.276517616996 + 0.276845390106 + 0.277173389747 + 0.277501615962 + 0.277830068798 + 0.278158748297 + 0.278487654506 + 0.278816787468 + 0.279146147229 + 0.279475733832 + 0.279805547324 + 0.280135587747 + 0.280465855147 + 0.280796349568 + 0.281127071056 + 0.281458019653 + 0.281789195406 + 0.282120598358 + 0.282452228554 + 0.282784086039 + 0.283116170857 + 0.283448483052 + 0.283781022669 + 0.284113789753 + 0.284446784347 + 0.284780006497 + 0.285113456246 + 0.28544713364 + 0.285781038721 + 0.286115171536 + 0.286449532128 + 0.286784120541 + 0.28711893682 + 0.287453981009 + 0.287789253152 + 0.288124753295 + 0.28846048148 + 0.288796437753 + 0.289132622157 + 0.289469034737 + 0.289805675536 + 0.290142544601 + 0.290479641973 + 0.290816967698 + 0.29115452182 + 0.291492304383 + 0.291830315431 + 0.292168555008 + 0.292507023158 + 0.292845719926 + 0.293184645356 + 0.293523799491 + 0.293863182375 + 0.294202794054 + 0.29454263457 + 0.294882703969 + 0.295223002293 + 0.295563529587 + 0.295904285895 + 0.29624527126 + 0.296586485728 + 0.296927929341 + 0.297269602144 + 0.297611504181 + 0.297953635496 + 0.298295996131 + 0.298638586133 + 0.298981405543 + 0.299324454407 + 0.299667732768 + 0.300011240669 + 0.300354978156 + 0.300698945271 + 0.301043142058 + 0.301387568561 + 0.301732224824 + 0.302077110891 + 0.302422226805 + 0.30276757261 + 0.303113148351 + 0.30345895407 + 0.303804989811 + 0.304151255618 + 0.304497751535 + 0.304844477606 + 0.305191433873 + 0.305538620381 + 0.305886037173 + 0.306233684294 + 0.306581561785 + 0.306929669692 + 0.307278008058 + 0.307626576926 + 0.30797537634 + 0.308324406343 + 0.308673666979 + 0.309023158292 + 0.309372880325 + 0.309722833121 + 0.310073016724 + 0.310423431177 + 0.310774076524 + 0.311124952809 + 0.311476060074 + 0.311827398364 + 0.312178967721 + 0.312530768189 + 0.312882799812 + 0.313235062632 + 0.313587556694 + 0.31394028204 + 0.314293238713 + 0.314646426758 + 0.314999846217 + 0.315353497134 + 0.315707379552 + 0.316061493515 + 0.316415839065 + 0.316770416246 + 0.3171252251 + 0.317480265673 + 0.317835538005 + 0.318191042142 + 0.318546778125 + 0.318902745999 + 0.319258945805 + 0.319615377588 + 0.319972041391 + 0.320328937256 + 0.320686065228 + 0.321043425348 + 0.32140101766 + 0.321758842207 + 0.322116899033 + 0.322475188179 + 0.32283370969 + 0.323192463609 + 0.323551449977 + 0.32391066884 + 0.324270120238 + 0.324629804216 + 0.324989720816 + 0.325349870081 + 0.325710252055 + 0.32607086678 + 0.326431714298 + 0.326792794654 + 0.32715410789 + 0.327515654049 + 0.327877433174 + 0.328239445307 + 0.328601690491 + 0.32896416877 + 0.329326880186 + 0.329689824782 + 0.3300530026 + 0.330416413684 + 0.330780058077 + 0.33114393582 + 0.331508046958 + 0.331872391532 + 0.332236969586 + 0.332601781161 + 0.332966826302 + 0.33333210505 + 0.333697617448 + 0.334063363539 + 0.334429343366 + 0.334795556971 + 0.335162004396 + 0.335528685686 + 0.335895600881 + 0.336262750025 + 0.336630133161 + 0.33699775033 + 0.337365601576 + 0.337733686941 + 0.338102006468 + 0.338470560199 + 0.338839348176 + 0.339208370443 + 0.339577627041 + 0.339947118014 + 0.340316843403 + 0.340686803252 + 0.341056997602 + 0.341427426497 + 0.341798089977 + 0.342168988087 + 0.342540120868 + 0.342911488363 + 0.343283090614 + 0.343654927664 + 0.344026999555 + 0.344399306329 + 0.344771848028 + 0.345144624695 + 0.345517636373 + 0.345890883103 + 0.346264364929 + 0.346638081891 + 0.347012034033 + 0.347386221396 + 0.347760644024 + 0.348135301958 + 0.34851019524 + 0.348885323913 + 0.349260688018 + 0.349636287599 + 0.350012122697 + 0.350388193355 + 0.350764499614 + 0.351141041517 + 0.351517819106 + 0.351894832422 + 0.352272081509 + 0.352649566409 + 0.353027287162 + 0.353405243812 + 0.353783436401 + 0.35416186497 + 0.354540529562 + 0.354919430218 + 0.355298566981 + 0.355677939893 + 0.356057548995 + 0.356437394331 + 0.356817475941 + 0.357197793867 + 0.357578348152 + 0.357959138838 + 0.358340165966 + 0.358721429579 + 0.359102929718 + 0.359484666426 + 0.359866639743 + 0.360248849713 + 0.360631296376 + 0.361013979776 + 0.361396899953 + 0.361780056949 + 0.362163450807 + 0.362547081568 + 0.362930949273 + 0.363315053966 + 0.363699395687 + 0.364083974478 + 0.364468790381 + 0.364853843438 + 0.365239133691 + 0.365624661181 + 0.36601042595 + 0.366396428039 + 0.366782667491 + 0.367169144347 + 0.367555858648 + 0.367942810438 + 0.368329999756 + 0.368717426644 + 0.369105091145 + 0.3694929933 + 0.369881133151 + 0.370269510739 + 0.370658126105 + 0.371046979292 + 0.37143607034 + 0.371825399292 + 0.372214966189 + 0.372604771073 + 0.372994813984 + 0.373385094965 + 0.373775614057 + 0.374166371302 + 0.37455736674 + 0.374948600414 + 0.375340072365 + 0.375731782634 + 0.376123731263 + 0.376515918294 + 0.376908343767 + 0.377301007723 + 0.377693910206 + 0.378087051255 + 0.378480430912 + 0.378874049219 + 0.379267906217 + 0.379662001946 + 0.38005633645 + 0.380450909768 + 0.380845721942 + 0.381240773014 + 0.381636063025 + 0.382031592016 + 0.382427360027 + 0.382823367102 + 0.38321961328 + 0.383616098603 + 0.384012823112 + 0.384409786849 + 0.384806989855 + 0.38520443217 + 0.385602113836 + 0.386000034894 + 0.386398195386 + 0.386796595352 + 0.387195234834 + 0.387594113872 + 0.387993232508 + 0.388392590783 + 0.388792188739 + 0.389192026415 + 0.389592103853 + 0.389992421095 + 0.390392978181 + 0.390793775152 + 0.39119481205 + 0.391596088915 + 0.391997605788 + 0.392399362711 + 0.392801359724 + 0.393203596868 + 0.393606074185 + 0.394008791715 + 0.394411749499 + 0.394814947578 + 0.395218385993 + 0.395622064786 + 0.396025983996 + 0.396430143665 + 0.396834543833 + 0.397239184543 + 0.397644065833 + 0.398049187746 + 0.398454550322 + 0.398860153601 + 0.399265997626 + 0.399672082436 + 0.400078408072 + 0.400484974575 + 0.400891781987 + 0.401298830347 + 0.401706119696 + 0.402113650076 + 0.402521421526 + 0.402929434088 + 0.403337687803 + 0.40374618271 + 0.404154918852 + 0.404563896267 + 0.404973114998 + 0.405382575085 + 0.405792276568 + 0.406202219488 + 0.406612403886 + 0.407022829802 + 0.407433497277 + 0.407844406352 + 0.408255557067 + 0.408666949462 + 0.409078583579 + 0.409490459458 + 0.409902577139 + 0.410314936663 + 0.410727538071 + 0.411140381402 + 0.411553466698 + 0.411966793999 + 0.412380363346 + 0.412794174779 + 0.413208228338 + 0.413622524064 + 0.414037061997 + 0.414451842178 + 0.414866864648 + 0.415282129446 + 0.415697636613 + 0.41611338619 + 0.416529378216 + 0.416945612733 + 0.417362089781 + 0.417778809399 + 0.418195771629 + 0.41861297651 + 0.419030424084 + 0.419448114389 + 0.419866047468 + 0.420284223359 + 0.420702642103 + 0.421121303741 + 0.421540208313 + 0.421959355859 + 0.422378746419 + 0.422798380033 + 0.423218256742 + 0.423638376586 + 0.424058739606 + 0.424479345841 + 0.424900195331 + 0.425321288117 + 0.425742624239 + 0.426164203737 + 0.426586026651 + 0.427008093021 + 0.427430402888 + 0.427852956292 + 0.428275753272 + 0.428698793869 + 0.429122078123 + 0.429545606074 + 0.429969377762 + 0.430393393228 + 0.43081765251 + 0.431242155649 + 0.431666902686 + 0.43209189366 + 0.432517128611 + 0.43294260758 + 0.433368330606 + 0.433794297729 + 0.434220508989 + 0.434646964426 + 0.435073664081 + 0.435500607993 + 0.435927796201 + 0.436355228747 + 0.436782905669 + 0.437210827008 + 0.437638992804 + 0.438067403096 + 0.438496057925 + 0.43892495733 + 0.43935410135 + 0.439783490027 + 0.4402131234 + 0.440643001508 + 0.441073124392 + 0.441503492091 + 0.441934104645 + 0.442364962094 + 0.442796064477 + 0.443227411835 + 0.443659004207 + 0.444090841633 + 0.444522924152 + 0.444955251805 + 0.445387824631 + 0.445820642669 + 0.44625370596 + 0.446687014543 + 0.447120568458 + 0.447554367744 + 0.447988412442 + 0.44842270259 + 0.448857238229 + 0.449292019398 + 0.449727046137 + 0.450162318484 + 0.450597836481 + 0.451033600167 + 0.45146960958 + 0.451905864761 + 0.45234236575 + 0.452779112585 + 0.453216105306 + 0.453653343954 + 0.454090828566 + 0.454528559184 + 0.454966535846 + 0.455404758592 + 0.455843227462 + 0.456281942494 + 0.456720903729 + 0.457160111205 + 0.457599564963 + 0.458039265042 + 0.45847921148 + 0.458919404318 + 0.459359843596 + 0.459800529351 + 0.460241461625 + 0.460682640455 + 0.461124065882 + 0.461565737945 + 0.462007656684 + 0.462449822136 + 0.462892234343 + 0.463334893343 + 0.463777799176 + 0.464220951881 + 0.464664351496 + 0.465107998063 + 0.465551891619 + 0.465996032204 + 0.466440419857 + 0.466885054618 + 0.467329936526 + 0.46777506562 + 0.468220441939 + 0.468666065522 + 0.469111936409 + 0.469558054639 + 0.470004420252 + 0.470451033285 + 0.470897893779 + 0.471345001772 + 0.471792357304 + 0.472239960414 + 0.472687811141 + 0.473135909525 + 0.473584255603 + 0.474032849416 + 0.474481691002 + 0.4749307804 + 0.475380117651 + 0.475829702792 + 0.476279535862 + 0.476729616902 + 0.477179945949 + 0.477630523043 + 0.478081348223 + 0.478532421528 + 0.478983742996 + 0.479435312668 + 0.479887130581 + 0.480339196776 + 0.48079151129 + 0.481244074162 + 0.481696885433 + 0.48214994514 + 0.482603253323 + 0.48305681002 + 0.48351061527 + 0.483964669113 + 0.484418971587 + 0.484873522731 + 0.485328322584 + 0.485783371185 + 0.486238668573 + 0.486694214786 + 0.487150009863 + 0.487606053844 + 0.488062346767 + 0.48851888867 + 0.488975679593 + 0.489432719575 + 0.489890008653 + 0.490347546868 + 0.490805334257 + 0.49126337086 + 0.491721656715 + 0.492180191862 + 0.492638976337 + 0.493098010182 + 0.493557293433 + 0.49401682613 + 0.494476608312 + 0.494936640017 + 0.495396921284 + 0.495857452151 + 0.496318232658 + 0.496779262842 + 0.497240542743 + 0.497702072399 + 0.498163851849 + 0.498625881131 + 0.499088160284 + 0.499550689347 + 0.500013468358 + 0.500476497356 + 0.500939776379 + 0.501403305466 + 0.501867084655 + 0.502331113985 + 0.502795393495 + 0.503259923222 + 0.503724703206 + 0.504189733486 + 0.504655014098 + 0.505120545083 + 0.505586326478 + 0.506052358322 + 0.506518640654 + 0.506985173511 + 0.507451956933 + 0.507918990957 + 0.508386275623 + 0.508853810968 + 0.509321597032 + 0.509789633851 + 0.510257921466 + 0.510726459913 + 0.511195249232 + 0.511664289461 + 0.512133580639 + 0.512603122803 + 0.513072915991 + 0.513542960243 + 0.514013255597 + 0.514483802091 + 0.514954599763 + 0.515425648651 + 0.515896948794 + 0.51636850023 + 0.516840302998 + 0.517312357135 + 0.51778466268 + 0.518257219671 + 0.518730028146 + 0.519203088144 + 0.519676399702 + 0.52014996286 + 0.520623777654 + 0.521097844124 + 0.521572162308 + 0.522046732243 + 0.522521553968 + 0.522996627522 + 0.523471952941 + 0.523947530264 + 0.52442335953 + 0.524899440777 + 0.525375774042 + 0.525852359364 + 0.526329196781 + 0.526806286331 + 0.527283628051 + 0.527761221981 + 0.528239068158 + 0.52871716662 + 0.529195517406 + 0.529674120552 + 0.530152976098 + 0.530632084081 + 0.53111144454 + 0.531591057512 + 0.532070923035 + 0.532551041148 + 0.533031411887 + 0.533512035292 + 0.5339929114 + 0.53447404025 + 0.534955421878 + 0.535437056323 + 0.535918943623 + 0.536401083817 + 0.53688347694 + 0.537366123033 + 0.537849022132 + 0.538332174275 + 0.538815579501 + 0.539299237846 + 0.53978314935 + 0.54026731405 + 0.540751731983 + 0.541236403188 + 0.541721327702 + 0.542206505563 + 0.542691936809 + 0.543177621478 + 0.543663559608 + 0.544149751235 + 0.544636196399 + 0.545122895137 + 0.545609847486 + 0.546097053484 + 0.54658451317 + 0.54707222658 + 0.547560193753 + 0.548048414726 + 0.548536889537 + 0.549025618223 + 0.549514600823 + 0.550003837374 + 0.550493327913 + 0.550983072479 + 0.551473071109 + 0.55196332384 + 0.552453830711 + 0.552944591758 + 0.55343560702 + 0.553926876534 + 0.554418400337 + 0.554910178468 + 0.555402210964 + 0.555894497862 + 0.5563870392 + 0.556879835016 + 0.557372885347 + 0.557866190231 + 0.558359749704 + 0.558853563806 + 0.559347632573 + 0.559841956042 + 0.560336534252 + 0.560831367239 + 0.561326455042 + 0.561821797697 + 0.562317395243 + 0.562813247716 + 0.563309355154 + 0.563805717595 + 0.564302335076 + 0.564799207634 + 0.565296335307 + 0.565793718133 + 0.566291356147 + 0.566789249389 + 0.567287397896 + 0.567785801704 + 0.568284460851 + 0.568783375375 + 0.569282545312 + 0.569781970701 + 0.570281651579 + 0.570781587982 + 0.571281779949 + 0.571782227516 + 0.572282930721 + 0.572783889601 + 0.573285104193 + 0.573786574535 + 0.574288300664 + 0.574790282617 + 0.575292520432 + 0.575795014146 + 0.576297763795 + 0.576800769418 + 0.577304031051 + 0.577807548731 + 0.578311322497 + 0.578815352385 + 0.579319638431 + 0.579824180675 + 0.580328979151 + 0.580834033899 + 0.581339344954 + 0.581844912355 + 0.582350736138 + 0.58285681634 + 0.583363152998 + 0.58386974615 + 0.584376595833 + 0.584883702084 + 0.585391064939 + 0.585898684437 + 0.586406560613 + 0.586914693506 + 0.587423083152 + 0.587931729588 + 0.588440632851 + 0.588949792979 + 0.589459210008 + 0.589968883975 + 0.590478814918 + 0.590989002873 + 0.591499447878 + 0.592010149968 + 0.592521109183 + 0.593032325557 + 0.593543799129 + 0.594055529935 + 0.594567518013 + 0.595079763398 + 0.595592266129 + 0.596105026241 + 0.596618043773 + 0.59713131876 + 0.59764485124 + 0.59815864125 + 0.598672688826 + 0.599186994006 + 0.599701556825 + 0.600216377322 + 0.600731455533 + 0.601246791495 + 0.601762385244 + 0.602278236818 + 0.602794346254 + 0.603310713587 + 0.603827338855 + 0.604344222095 + 0.604861363344 + 0.605378762638 + 0.605896420014 + 0.606414335509 + 0.606932509159 + 0.607450941002 + 0.607969631074 + 0.608488579412 + 0.609007786052 + 0.609527251032 + 0.610046974388 + 0.610566956156 + 0.611087196374 + 0.611607695078 + 0.612128452304 + 0.612649468091 + 0.613170742473 + 0.613692275488 + 0.614214067172 + 0.614736117563 + 0.615258426696 + 0.615780994609 + 0.616303821338 + 0.616826906919 + 0.617350251389 + 0.617873854785 + 0.618397717144 + 0.618921838501 + 0.619446218894 + 0.619970858359 + 0.620495756933 + 0.621020914651 + 0.621546331552 + 0.622072007671 + 0.622597943044 + 0.623124137709 + 0.623650591702 + 0.624177305059 + 0.624704277817 + 0.625231510012 + 0.625759001681 + 0.62628675286 + 0.626814763586 + 0.627343033895 + 0.627871563823 + 0.628400353408 + 0.628929402685 + 0.629458711692 + 0.629988280463 + 0.630518109036 + 0.631048197448 + 0.631578545734 + 0.632109153931 + 0.632640022075 + 0.633171150203 + 0.633702538351 + 0.634234186555 + 0.634766094852 + 0.635298263279 + 0.63583069187 + 0.636363380664 + 0.636896329695 + 0.637429539001 + 0.637963008618 + 0.638496738582 + 0.639030728929 + 0.639564979695 + 0.640099490918 + 0.640634262632 + 0.641169294875 + 0.641704587683 + 0.642240141091 + 0.642775955137 + 0.643312029856 + 0.643848365284 + 0.644384961458 + 0.644921818414 + 0.645458936189 + 0.645996314818 + 0.646533954337 + 0.647071854783 + 0.647610016192 + 0.648148438599 + 0.648687122043 + 0.649226066557 + 0.649765272179 + 0.650304738945 + 0.65084446689 + 0.651384456051 + 0.651924706464 + 0.652465218165 + 0.653005991191 + 0.653547025576 + 0.654088321358 + 0.654629878573 + 0.655171697255 + 0.655713777443 + 0.656256119171 + 0.656798722475 + 0.657341587392 + 0.657884713958 + 0.658428102208 + 0.65897175218 + 0.659515663907 + 0.660059837428 + 0.660604272777 + 0.661148969991 + 0.661693929106 + 0.662239150157 + 0.66278463318 + 0.663330378213 + 0.663876385289 + 0.664422654446 + 0.66496918572 + 0.665515979145 + 0.666063034759 + 0.666610352597 + 0.667157932695 + 0.667705775089 + 0.668253879814 + 0.668802246907 + 0.669350876404 + 0.66989976834 + 0.670448922751 + 0.670998339673 + 0.671548019143 + 0.672097961194 + 0.672648165865 + 0.67319863319 + 0.673749363205 + 0.674300355946 + 0.674851611449 + 0.675403129749 + 0.675954910883 + 0.676506954886 + 0.677059261794 + 0.677611831643 + 0.678164664468 + 0.678717760305 + 0.67927111919 + 0.679824741159 + 0.680378626247 + 0.68093277449 + 0.681487185924 + 0.682041860585 + 0.682596798508 + 0.683151999728 + 0.683707464283 + 0.684263192206 + 0.684819183534 + 0.685375438303 + 0.685931956549 + 0.686488738306 + 0.68704578361 + 0.687603092498 + 0.688160665004 + 0.688718501165 + 0.689276601016 + 0.689834964592 + 0.69039359193 + 0.690952483064 + 0.691511638031 + 0.692071056865 + 0.692630739603 + 0.693190686281 + 0.693750896932 + 0.694311371594 + 0.694872110301 + 0.69543311309 + 0.695994379996 + 0.696555911053 + 0.697117706299 + 0.697679765767 + 0.698242089495 + 0.698804677516 + 0.699367529867 + 0.699930646584 + 0.700494027701 + 0.701057673254 + 0.701621583279 + 0.702185757811 + 0.702750196885 + 0.703314900537 + 0.703879868802 + 0.704445101716 + 0.705010599314 + 0.705576361632 + 0.706142388705 + 0.706708680567 + 0.707275237256 + 0.707842058805 + 0.708409145251 + 0.708976496629 + 0.709544112974 + 0.710111994321 + 0.710680140706 + 0.711248552164 + 0.711817228731 + 0.712386170441 + 0.712955377331 + 0.713524849435 + 0.714094586788 + 0.714664589427 + 0.715234857385 + 0.7158053907 + 0.716376189405 + 0.716947253536 + 0.717518583128 + 0.718090178217 + 0.718662038838 + 0.719234165025 + 0.719806556815 + 0.720379214243 + 0.720952137343 + 0.72152532615 + 0.722098780701 + 0.722672501031 + 0.723246487173 + 0.723820739164 + 0.724395257039 + 0.724970040833 + 0.725545090581 + 0.726120406319 + 0.72669598808 + 0.727271835902 + 0.727847949817 + 0.728424329863 + 0.729000976073 + 0.729577888484 + 0.730155067129 + 0.730732512045 + 0.731310223266 + 0.731888200827 + 0.732466444764 + 0.733044955111 + 0.733623731904 + 0.734202775177 + 0.734782084966 + 0.735361661306 + 0.735941504231 + 0.736521613777 + 0.737101989979 + 0.737682632871 + 0.738263542489 + 0.738844718868 + 0.739426162043 + 0.740007872048 + 0.740589848919 + 0.741172092691 + 0.741754603398 + 0.742337381076 + 0.742920425759 + 0.743503737483 + 0.744087316282 + 0.744671162192 + 0.745255275246 + 0.745839655481 + 0.746424302931 + 0.747009217631 + 0.747594399616 + 0.74817984892 + 0.748765565579 + 0.749351549628 + 0.749937801101 + 0.750524320033 + 0.751111106459 + 0.751698160414 + 0.752285481933 + 0.75287307105 + 0.753460927801 + 0.75404905222 + 0.754637444342 + 0.755226104201 + 0.755815031834 + 0.756404227274 + 0.756993690556 + 0.757583421715 + 0.758173420785 + 0.758763687802 + 0.759354222801 + 0.759945025815 + 0.760536096881 + 0.761127436031 + 0.761719043302 + 0.762310918728 + 0.762903062344 + 0.763495474184 + 0.764088154283 + 0.764681102675 + 0.765274319397 + 0.765867804481 + 0.766461557963 + 0.767055579878 + 0.76764987026 + 0.768244429143 + 0.768839256563 + 0.769434352554 + 0.770029717151 + 0.770625350388 + 0.7712212523 + 0.771817422922 + 0.772413862288 + 0.773010570433 + 0.773607547391 + 0.774204793197 + 0.774802307886 + 0.775400091492 + 0.775998144049 + 0.776596465593 + 0.777195056158 + 0.777793915778 + 0.778393044488 + 0.778992442322 + 0.779592109316 + 0.780192045503 + 0.780792250918 + 0.781392725595 + 0.781993469569 + 0.782594482875 + 0.783195765547 + 0.78379731762 + 0.784399139127 + 0.785001230104 + 0.785603590585 + 0.786206220604 + 0.786809120196 + 0.787412289396 + 0.788015728237 + 0.788619436754 + 0.789223414981 + 0.789827662954 + 0.790432180706 + 0.791036968271 + 0.791642025685 + 0.792247352982 + 0.792852950195 + 0.793458817359 + 0.79406495451 + 0.79467136168 + 0.795278038905 + 0.795884986218 + 0.796492203655 + 0.797099691249 + 0.797707449035 + 0.798315477047 + 0.798923775319 + 0.799532343886 + 0.800141182782 + 0.800750292042 + 0.801359671699 + 0.801969321788 + 0.802579242343 + 0.803189433398 + 0.803799894988 + 0.804410627148 + 0.80502162991 + 0.80563290331 + 0.806244447382 + 0.806856262159 + 0.807468347677 + 0.808080703969 + 0.80869333107 + 0.809306229013 + 0.809919397834 + 0.810532837566 + 0.811146548243 + 0.8117605299 + 0.81237478257 + 0.812989306288 + 0.813604101089 + 0.814219167006 + 0.814834504073 + 0.815450112324 + 0.816065991795 + 0.816682142518 + 0.817298564528 + 0.817915257859 + 0.818532222545 + 0.81914945862 + 0.819766966119 + 0.820384745075 + 0.821002795523 + 0.821621117496 + 0.822239711029 + 0.822858576156 + 0.82347771291 + 0.824097121327 + 0.824716801439 + 0.825336753281 + 0.825956976887 + 0.826577472291 + 0.827198239527 + 0.82781927863 + 0.828440589632 + 0.829062172568 + 0.829684027472 + 0.830306154379 + 0.830928553321 + 0.831551224333 + 0.832174167449 + 0.832797382703 + 0.833420870129 + 0.834044629761 + 0.834668661633 + 0.835292965778 + 0.835917542231 + 0.836542391025 + 0.837167512195 + 0.837792905774 + 0.838418571797 + 0.839044510296 + 0.839670721307 + 0.840297204863 + 0.840923960998 + 0.841550989745 + 0.842178291139 + 0.842805865213 + 0.843433712002 + 0.844061831539 + 0.844690223858 + 0.845318888993 + 0.845947826977 + 0.846577037845 + 0.84720652163 + 0.847836278366 + 0.848466308088 + 0.849096610828 + 0.84972718662 + 0.850358035499 + 0.850989157498 + 0.851620552651 + 0.852252220991 + 0.852884162553 + 0.85351637737 + 0.854148865475 + 0.854781626904 + 0.855414661689 + 0.856047969864 + 0.856681551462 + 0.857315406519 + 0.857949535066 + 0.858583937139 + 0.85921861277 + 0.859853561993 + 0.860488784843 + 0.861124281352 + 0.861760051555 + 0.862396095484 + 0.863032413175 + 0.86366900466 + 0.864305869972 + 0.864943009147 + 0.865580422217 + 0.866218109215 + 0.866856070177 + 0.867494305134 + 0.868132814121 + 0.868771597172 + 0.869410654319 + 0.870049985598 + 0.87068959104 + 0.87132947068 + 0.871969624552 + 0.872610052688 + 0.873250755123 + 0.87389173189 + 0.874532983022 + 0.875174508554 + 0.875816308518 + 0.876458382948 + 0.877100731878 + 0.877743355342 + 0.878386253372 + 0.879029426002 + 0.879672873266 + 0.880316595197 + 0.880960591829 + 0.881604863195 + 0.882249409329 + 0.882894230264 + 0.883539326034 + 0.884184696672 + 0.884830342211 + 0.885476262686 + 0.886122458128 + 0.886768928573 + 0.887415674053 + 0.888062694601 + 0.888709990252 + 0.889357561038 + 0.890005406994 + 0.890653528151 + 0.891301924544 + 0.891950596207 + 0.892599543171 + 0.893248765472 + 0.893898263142 + 0.894548036215 + 0.895198084723 + 0.895848408701 + 0.896499008181 + 0.897149883198 + 0.897801033783 + 0.898452459971 + 0.899104161796 + 0.899756139289 + 0.900408392485 + 0.901060921417 + 0.901713726118 + 0.902366806622 + 0.903020162961 + 0.903673795169 + 0.90432770328 + 0.904981887326 + 0.905636347341 + 0.906291083358 + 0.90694609541 + 0.907601383531 + 0.908256947753 + 0.908912788111 + 0.909568904637 + 0.910225297364 + 0.910881966326 + 0.911538911555 + 0.912196133086 + 0.912853630951 + 0.913511405184 + 0.914169455817 + 0.914827782883 + 0.915486386417 + 0.916145266451 + 0.916804423018 + 0.917463856152 + 0.918123565885 + 0.918783552251 + 0.919443815283 + 0.920104355013 + 0.920765171476 + 0.921426264704 + 0.92208763473 + 0.922749281588 + 0.92341120531 + 0.92407340593 + 0.92473588348 + 0.925398637995 + 0.926061669506 + 0.926724978047 + 0.927388563651 + 0.928052426351 + 0.92871656618 + 0.929380983171 + 0.930045677357 + 0.930710648772 + 0.931375897448 + 0.932041423418 + 0.932707226715 + 0.933373307372 + 0.934039665423 + 0.9347063009 + 0.935373213836 + 0.936040404265 + 0.936707872218 + 0.93737561773 + 0.938043640833 + 0.93871194156 + 0.939380519944 + 0.940049376018 + 0.940718509816 + 0.941387921369 + 0.94205761071 + 0.942727577874 + 0.943397822892 + 0.944068345798 + 0.944739146624 + 0.945410225404 + 0.94608158217 + 0.946753216955 + 0.947425129793 + 0.948097320715 + 0.948769789755 + 0.949442536946 + 0.95011556232 + 0.950788865911 + 0.951462447751 + 0.952136307873 + 0.95281044631 + 0.953484863095 + 0.95415955826 + 0.954834531839 + 0.955509783864 + 0.956185314368 + 0.956861123384 + 0.957537210945 + 0.958213577083 + 0.958890221831 + 0.959567145223 + 0.96024434729 + 0.960921828065 + 0.961599587582 + 0.962277625873 + 0.962955942971 + 0.963634538909 + 0.964313413718 + 0.964992567433 + 0.965672000086 + 0.966351711709 + 0.967031702335 + 0.967711971997 + 0.968392520728 + 0.96907334856 + 0.969754455527 + 0.970435841659 + 0.971117506992 + 0.971799451556 + 0.972481675385 + 0.973164178512 + 0.973846960968 + 0.974530022788 + 0.975213364002 + 0.975896984645 + 0.976580884748 + 0.977265064345 + 0.977949523468 + 0.978634262149 + 0.979319280421 + 0.980004578317 + 0.980690155869 + 0.98137601311 + 0.982062150073 + 0.98274856679 + 0.983435263294 + 0.984122239617 + 0.984809495791 + 0.985497031851 + 0.986184847827 + 0.986872943752 + 0.98756131966 + 0.988249975582 + 0.988938911552 + 0.989628127601 + 0.990317623762 + 0.991007400068 + 0.991697456552 + 0.992387793245 + 0.99307841018 + 0.99376930739 + 0.994460484907 + 0.995151942764 + 0.995843680993 + 0.996535699626 + 0.997227998697 + 0.997920578237 + 0.998613438279 + 0.999306578856 + 1.0 + 1.00069370174 + 1.00138768412 + 1.00208194716 + 1.00277649089 + 1.00347131536 + 1.00416642058 + 1.0048618066 + 1.00555747345 + 1.00625342116 + 1.00694964975 + 1.00764615927 + 1.00834294975 + 1.00904002121 + 1.00973737369 + 1.01043500723 + 1.01113292185 + 1.01183111759 + 1.01252959448 + 1.01322835255 + 1.01392739184 + 1.01462671237 + 1.01532631419 + 1.01602619731 + 1.01672636178 + 1.01742680762 + 1.01812753488 + 1.01882854357 + 1.01952983374 + 1.02023140541 + 1.02093325862 + 1.0216353934 + 1.02233780978 + 1.0230405078 + 1.02374348748 + 1.02444674886 + 1.02515029198 + 1.02585411685 + 1.02655822353 + 1.02726261203 + 1.02796728239 + 1.02867223464 + 1.02937746881 + 1.03008298495 + 1.03078878307 + 1.03149486321 + 1.03220122541 + 1.03290786969 + 1.03361479609 + 1.03432200464 + 1.03502949538 + 1.03573726832 + 1.03644532351 + 1.03715366099 + 1.03786228077 + 1.03857118289 + 1.03928036739 + 1.0399898343 + 1.04069958364 + 1.04140961546 + 1.04211992978 + 1.04283052663 + 1.04354140606 + 1.04425256808 + 1.04496401273 + 1.04567574005 + 1.04638775006 + 1.04710004281 + 1.04781261831 + 1.0485254766 + 1.04923861772 + 1.04995204169 + 1.05066574856 + 1.05137973834 + 1.05209401108 + 1.0528085668 + 1.05352340553 + 1.05423852732 + 1.05495393218 + 1.05566962016 + 1.05638559128 + 1.05710184558 + 1.05781838308 + 1.05853520383 + 1.05925230785 + 1.05996969517 + 1.06068736583 + 1.06140531986 + 1.06212355729 + 1.06284207815 + 1.06356088248 + 1.0642799703 + 1.06499934165 + 1.06571899655 + 1.06643893505 + 1.06715915718 + 1.06787966296 + 1.06860045243 + 1.06932152561 + 1.07004288255 + 1.07076452328 + 1.07148644781 + 1.0722086562 + 1.07293114846 + 1.07365392463 + 1.07437698475 + 1.07510032884 + 1.07582395694 + 1.07654786908 + 1.07727206528 + 1.07799654559 + 1.07872131003 + 1.07944635864 + 1.08017169145 + 1.08089730848 + 1.08162320978 + 1.08234939536 + 1.08307586528 + 1.08380261955 + 1.08452965821 + 1.08525698128 + 1.08598458881 + 1.08671248083 + 1.08744065736 + 1.08816911843 + 1.08889786409 + 1.08962689435 + 1.09035620926 + 1.09108580884 + 1.09181569313 + 1.09254586216 + 1.09327631595 + 1.09400705455 + 1.09473807798 + 1.09546938627 + 1.09620097946 + 1.09693285758 + 1.09766502066 + 1.09839746872 + 1.09913020182 + 1.09986321996 + 1.1005965232 + 1.10133011155 + 1.10206398505 + 1.10279814373 + 1.10353258762 + 1.10426731676 + 1.10500233118 + 1.1057376309 + 1.10647321597 + 1.1072090864 + 1.10794524224 + 1.10868168351 + 1.10941841025 + 1.11015542248 + 1.11089272025 + 1.11163030357 + 1.11236817249 + 1.11310632704 + 1.11384476723 + 1.11458349312 + 1.11532250472 + 1.11606180208 + 1.11680138521 + 1.11754125416 + 1.11828140896 + 1.11902184963 + 1.11976257621 + 1.12050358873 + 1.12124488722 + 1.12198647171 + 1.12272834223 + 1.12347049883 + 1.12421294152 + 1.12495567034 + 1.12569868531 + 1.12644198648 + 1.12718557388 + 1.12792944753 + 1.12867360746 + 1.12941805371 + 1.13016278631 + 1.13090780529 + 1.13165311069 + 1.13239870252 + 1.13314458084 + 1.13389074565 + 1.13463719701 + 1.13538393494 + 1.13613095946 + 1.13687827062 + 1.13762586844 + 1.13837375296 + 1.1391219242 + 1.1398703822 + 1.14061912699 + 1.1413681586 + 1.14211747706 + 1.1428670824 + 1.14361697466 + 1.14436715387 + 1.14511762005 + 1.14586837324 + 1.14661941347 + 1.14737074078 + 1.14812235518 + 1.14887425672 + 1.14962644542 + 1.15037892133 + 1.15113168446 + 1.15188473484 + 1.15263807252 + 1.15339169753 + 1.15414560988 + 1.15489980962 + 1.15565429677 + 1.15640907138 + 1.15716413346 + 1.15791948305 + 1.15867512018 + 1.15943104488 + 1.16018725719 + 1.16094375713 + 1.16170054474 + 1.16245762004 + 1.16321498308 + 1.16397263387 + 1.16473057246 + 1.16548879886 + 1.16624731312 + 1.16700611527 + 1.16776520533 + 1.16852458333 + 1.16928424932 + 1.17004420331 + 1.17080444535 + 1.17156497546 + 1.17232579367 + 1.17308690001 + 1.17384829452 + 1.17460997723 + 1.17537194816 + 1.17613420735 + 1.17689675484 + 1.17765959064 + 1.17842271479 + 1.17918612733 + 1.17994982829 + 1.18071381769 + 1.18147809556 + 1.18224266195 + 1.18300751687 + 1.18377266036 + 1.18453809246 + 1.18530381318 + 1.18606982257 + 1.18683612066 + 1.18760270746 + 1.18836958303 + 1.18913674738 + 1.18990420056 + 1.19067194258 + 1.19143997348 + 1.1922082933 + 1.19297690205 + 1.19374579979 + 1.19451498652 + 1.19528446229 + 1.19605422713 + 1.19682428107 + 1.19759462414 + 1.19836525637 + 1.19913617778 + 1.19990738842 + 1.20067888832 + 1.20145067749 + 1.20222275598 + 1.20299512382 + 1.20376778104 + 1.20454072766 + 1.20531396372 + 1.20608748925 + 1.20686130429 + 1.20763540885 + 1.20840980298 + 1.2091844867 + 1.20995946004 + 1.21073472304 + 1.21151027573 + 1.21228611814 + 1.21306225029 + 1.21383867222 + 1.21461538396 + 1.21539238555 + 1.216169677 + 1.21694725836 + 1.21772512965 + 1.21850329091 + 1.21928174216 + 1.22006048344 + 1.22083951477 + 1.22161883619 + 1.22239844774 + 1.22317834943 + 1.2239585413 + 1.22473902338 + 1.22551979571 + 1.22630085831 + 1.22708221121 + 1.22786385445 + 1.22864578805 + 1.22942801205 + 1.23021052647 + 1.23099333136 + 1.23177642673 + 1.23255981262 + 1.23334348906 + 1.23412745609 + 1.23491171372 + 1.235696262 + 1.23648110095 + 1.23726623061 + 1.238051651 + 1.23883736216 + 1.23962336411 + 1.24040965689 + 1.24119624053 + 1.24198311505 + 1.2427702805 + 1.2435577369 + 1.24434548427 + 1.24513352266 + 1.24592185209 + 1.24671047259 + 1.2474993842 + 1.24828858694 + 1.24907808085 + 1.24986786595 + 1.25065794228 + 1.25144830986 + 1.25223896874 + 1.25302991893 + 1.25382116047 + 1.25461269339 + 1.25540451772 + 1.25619663349 + 1.25698904073 + 1.25778173948 + 1.25857472976 + 1.2593680116 + 1.26016158504 + 1.2609554501 + 1.26174960681 + 1.26254405521 + 1.26333879533 + 1.2641338272 + 1.26492915084 + 1.26572476629 + 1.26652067358 + 1.26731687274 + 1.26811336381 + 1.2689101468 + 1.26970722175 + 1.27050458869 + 1.27130224766 + 1.27210019868 + 1.27289844178 + 1.273696977 + 1.27449580436 + 1.27529492389 + 1.27609433563 + 1.27689403961 + 1.27769403586 + 1.2784943244 + 1.27929490527 + 1.28009577849 + 1.28089694411 + 1.28169840214 + 1.28250015263 + 1.28330219559 + 1.28410453107 + 1.28490715908 + 1.28571007967 + 1.28651329286 + 1.28731679868 + 1.28812059716 + 1.28892468834 + 1.28972907224 + 1.2905337489 + 1.29133871834 + 1.29214398059 + 1.29294953569 + 1.29375538367 + 1.29456152455 + 1.29536795837 + 1.29617468516 + 1.29698170494 + 1.29778901775 + 1.29859662362 + 1.29940452258 + 1.30021271466 + 1.30102119989 + 1.3018299783 + 1.30263904991 + 1.30344841477 + 1.3042580729 + 1.30506802433 + 1.30587826909 + 1.30668880721 + 1.30749963873 + 1.30831076367 +} diff --git a/release/datafiles/colormanagement/luts/vd16.spi1d b/release/datafiles/colormanagement/luts/vd16.spi1d new file mode 100644 index 00000000000..50ea9e964c0 --- /dev/null +++ b/release/datafiles/colormanagement/luts/vd16.spi1d @@ -0,0 +1,131079 @@ +Version 1 +From 0.0 1.0 +Length 131073 +Components 1 +{ + 0.0000000000000000000 + 0.0037965930661236582 + 0.0038008543326060414 + 0.0038051021418722768 + 0.0038093365935017651 + 0.0038135577855092292 + 0.0038177658143781611 + 0.0038219607750932479 + 0.0038261427611719274 + 0.0038303118646951582 + 0.003834468176337303 + 0.0038386117853952315 + 0.0038427427798166758 + 0.0038468612462278224 + 0.0038509672699601864 + 0.0038550609350767608 + 0.0038591423243975616 + 0.003863211519524427 + 0.0038672686008652366 + 0.0038713136476575183 + 0.0038753467379914457 + 0.0038793679488322206 + 0.0038833773560419979 + 0.0038873750344011137 + 0.003891361057628951 + 0.0038953354984041831 + 0.0038992984283845516 + 0.0039032499182261957 + 0.0039071900376024512 + 0.0039111188552222592 + 0.0039150364388480735 + 0.0039189428553134346 + 0.0039228381705400219 + 0.0039267224495543561 + 0.003930595756504114 + 0.0039344581546740731 + 0.0039383097065016368 + 0.003942150473592059 + 0.0039459805167332621 + 0.0039497998959103905 + 0.0039536086703199531 + 0.0039574068983837044 + 0.0039611946377622106 + 0.0039649719453680298 + 0.0039687388773787585 + 0.0039724954892496013 + 0.0039762418357258264 + 0.0039799779708548401 + 0.003983703947998048 + 0.003987419819842449 + 0.0039911256384119473 + 0.0039948214550785104 + 0.0039985083419848471 + 0.0040021887876768424 + 0.0040058629345717418 + 0.0040095308257328934 + 0.0040131925037228443 + 0.0040168480106115359 + 0.0040204973879842815 + 0.0040241406769495752 + 0.0040277779181467962 + 0.0040314091517537169 + 0.0040350344174938189 + 0.00403865375464356 + 0.0040422672020393631 + 0.0040458747980846137 + 0.0040494765807563664 + 0.004053072587612022 + 0.0040566628557958525 + 0.00406024742204534 + 0.004063826322697469 + 0.0040673995936948235 + 0.0040709672705916515 + 0.0040745293885596839 + 0.0040780859823939903 + 0.0040816370865186021 + 0.0040851827349920634 + 0.0040887229615129304 + 0.0040922577994250723 + 0.0040957872817229376 + 0.0040993114410567003 + 0.0041028303097373113 + 0.0041063439197414507 + 0.0041098523027163856 + 0.0041133554899847446 + 0.0041168535125492116 + 0.0041203464010971073 + 0.0041238341860049032 + 0.0041273168973426757 + 0.0041307945648784159 + 0.0041342672180823235 + 0.0041377348861309947 + 0.0041411975979115372 + 0.0041446553820256226 + 0.0041481082667934399 + 0.0041515562802576077 + 0.0041549994501869966 + 0.0041584378040805036 + 0.0041618713691707427 + 0.0041653001724276696 + 0.00416872424056216 + 0.004172143600029511 + 0.0041755582770328873 + 0.0041789682975267107 + 0.0041823736872199898 + 0.0041857744715795737 + 0.0041891706758333891 + 0.0041925623249735701 + 0.0041959494437596246 + 0.0041993320567214115 + 0.0042027101881621969 + 0.0042060838621615854 + 0.0042094531025784337 + 0.0042128179330536922 + 0.0042161783770132324 + 0.004219534457670579 + 0.0042228861980296547 + 0.0042262336208874346 + 0.0042295767488365853 + 0.0042329156042680361 + 0.0042362502093735224 + 0.0042395805861481072 + 0.0042429067563926207 + 0.0042462287417160943 + 0.0042495465635381448 + 0.0042528602430912986 + 0.0042561698014233268 + 0.0042594752593995222 + 0.0042627766377048943 + 0.0042660739568463986 + 0.0042693672371551207 + 0.0042726564987883584 + 0.0042759417617317767 + 0.0042792230458014169 + 0.0042825003706457943 + 0.004285773755747852 + 0.0042890432204269529 + 0.0042923087838408151 + 0.0042955704649874438 + 0.004298828282706996 + 0.0043020822556836431 + 0.004305332402447389 + 0.0043085787413758882 + 0.0043118212906961993 + 0.0043150600684865592 + 0.0043182950926780629 + 0.0043215263810564035 + 0.0043247539512635018 + 0.0043279778207991719 + 0.0043311980070227657 + 0.0043344145271547131 + 0.0043376273982781389 + 0.0043408366373404155 + 0.0043440422611546649 + 0.0043472442864012908 + 0.0043504427296294475 + 0.0043536376072585052 + 0.0043568289355795098 + 0.0043600167307565781 + 0.0043632010088283267 + 0.0043663817857092363 + 0.004369559077191003 + 0.0043727328989439252 + 0.0043759032665181786 + 0.0043790701953451607 + 0.004382233700738738 + 0.0043853937978965652 + 0.0043885505019013006 + 0.0043917038277218445 + 0.004394853790214568 + 0.0043980004041245134 + 0.004401143684086577 + 0.0044042836446266777 + 0.0044074203001628915 + 0.004410553665006616 + 0.0044136837533636829 + 0.0044168105793354661 + 0.0044199341569199514 + 0.0044230545000128315 + 0.0044261716224085852 + 0.0044292855378014907 + 0.0044323962597866912 + 0.0044355038018611794 + 0.0044386081774248458 + 0.0044417093997814287 + 0.0044448074821395542 + 0.004447902437613639 + 0.0044509942792248756 + 0.0044540830199021886 + 0.0044571686724831387 + 0.0044602512497148583 + 0.0044633307642549481 + 0.0044664072286723835 + 0.0044694806554483827 + 0.0044725510569772848 + 0.0044756184455674291 + 0.0044786828334419659 + 0.00448174423273974 + 0.0044848026555160733 + 0.0044878581137436195 + 0.0044909106193131649 + 0.004493960184034417 + 0.0044970068196367799 + 0.0045000505377701715 + 0.0045030913500057387 + 0.0045061292678366749 + 0.0045091643026789136 + 0.0045121964658719049 + 0.0045152257686793384 + 0.0045182522222898414 + 0.0045212758378177283 + 0.0045242966263036944 + 0.0045273145987154793 + 0.0045303297659486028 + 0.0045333421388270108 + 0.0045363517281037519 + 0.0045393585444616549 + 0.0045423625985139523 + 0.0045453639008049673 + 0.0045483624618107288 + 0.0045513582919395881 + 0.0045543514015328789 + 0.0045573418008655123 + 0.0045603295001465753 + 0.0045633145095199685 + 0.0045662968390649521 + 0.0045692764987967944 + 0.004572253498667289 + 0.0045752278485653632 + 0.0045781995583176584 + 0.0045811686376890509 + 0.004584135096383243 + 0.0045870989440432936 + 0.0045900601902521673 + 0.0045930188445332558 + 0.0045959749163509188 + 0.0045989284151110163 + 0.0046018793501613952 + 0.0046048277307924506 + 0.0046077735662375637 + 0.0046107168656736612 + 0.0046136576382216936 + 0.0046165958929471002 + 0.0046195316388603158 + 0.0046224648849172425 + 0.0046253956400197135 + 0.0046283239130159894 + 0.004631249712701172 + 0.00463417304781771 + 0.0046370939270558176 + 0.0046400123590539218 + 0.0046429283523991361 + 0.0046458419156276669 + 0.0046487530572252413 + 0.0046516617856275661 + 0.0046545681092207145 + 0.0046574720363415792 + 0.004660373575278258 + 0.0046632727342704643 + 0.0046661695215099623 + 0.0046690639451409249 + 0.0046719560132603647 + 0.0046748457339184984 + 0.0046777331151191598 + 0.0046806181648201611 + 0.0046835008909336794 + 0.0046863813013266467 + 0.0046892594038210932 + 0.0046921352061945424 + 0.0046950087161803603 + 0.0046978799414681026 + 0.0047007488897038976 + 0.0047036155684907878 + 0.0047064799853890754 + 0.0047093421479166616 + 0.0047122020635493866 + 0.0047150597397213907 + 0.0047179151838254293 + 0.0047207684032131887 + 0.0047236194051956662 + 0.0047264681970434147 + 0.0047293147859869449 + 0.0047321591792169951 + 0.004735001383884844 + 0.0047378414071026376 + 0.0047406792559437057 + 0.004743514937442829 + 0.0047463484585965965 + 0.0047491798263636373 + 0.0047520090476649837 + 0.0047548361293843072 + 0.0047576610783682258 + 0.0047604839014266341 + 0.0047633046053329117 + 0.004766123196824258 + 0.0047689396826019487 + 0.0047717540693316268 + 0.0047745663636435511 + 0.0047773765721328869 + 0.0047801847013599665 + 0.0047829907578505549 + 0.0047857947480961088 + 0.0047885966785540333 + 0.0047913965556479546 + 0.0047941943857679548 + 0.0047969901752708353 + 0.0047997839304803587 + 0.0048025756576875033 + 0.0048053653631507202 + 0.0048081530530961281 + 0.0048109387337178129 + 0.0048137224111780277 + 0.0048165040916074413 + 0.0048192837811053746 + 0.0048220614857400028 + 0.0048248372115486313 + 0.0048276109645378944 + 0.0048303827506839675 + 0.0048331525759328269 + 0.0048359204462004339 + 0.0048386863673729654 + 0.0048414503453070344 + 0.0048442123858299171 + 0.0048469724947397255 + 0.0048497306778056545 + 0.0048524869407681739 + 0.0048552412893392311 + 0.0048579937292024785 + 0.0048607442660134389 + 0.0048634929053997392 + 0.0048662396529612862 + 0.0048689845142704784 + 0.0048717274948723976 + 0.0048744686002849934 + 0.0048772078359992851 + 0.0048799452074795449 + 0.0048826807201634969 + 0.0048854143794624773 + 0.0048881461907616499 + 0.0048908761594201773 + 0.0048936042907713872 + 0.0048963305901229756 + 0.0048990550627571712 + 0.0049017777139309139 + 0.004904498548876029 + 0.0049072175727993992 + 0.0049099347908831475 + 0.0049126502082847915 + 0.004915363830137417 + 0.0049180756615498531 + 0.0049207857076068347 + 0.0049234939733691519 + 0.0049262004638738269 + 0.0049289051841342833 + 0.0049316081391404861 + 0.0049343093338591135 + 0.0049370087732337068 + 0.0049397064621848358 + 0.0049424024056102332 + 0.0049450966083849739 + 0.0049477890753616173 + 0.004950479811370331 + 0.0049531688212190901 + 0.0049558561096937764 + 0.0049585416815583682 + 0.0049612255415550409 + 0.00496390769440435 + 0.004966588144805344 + 0.0049692668974357221 + 0.004971943956951985 + 0.0049746193279895544 + 0.004977293015162902 + 0.0049799650230657223 + 0.0049826353562710275 + 0.0049853040193313276 + 0.0049879710167787085 + 0.004990636353125022 + 0.0049933000328619623 + 0.0049959620604612337 + 0.0049986224403746685 + 0.0050012811770343618 + 0.0050039382748527728 + 0.0050065937382228771 + 0.0050092475715182837 + 0.005011899779093356 + 0.0050145503652833422 + 0.0050171993344044737 + 0.005019846690754109 + 0.0050224924386108602 + 0.0050251365822346784 + 0.0050277791258670004 + 0.0050304200737308598 + 0.0050330594300309868 + 0.0050356971989539475 + 0.0050383333846682216 + 0.0050409679913243667 + 0.0050436010230550951 + 0.0050462324839753809 + 0.0050488623781825793 + 0.00505149070975655 + 0.0050541174827597509 + 0.0050567427012373376 + 0.0050593663692172957 + 0.0050619884907105121 + 0.005064609069710917 + 0.0050672281101955706 + 0.0050698456161247353 + 0.0050724615914420476 + 0.0050750760400745613 + 0.0050776889659328549 + 0.0050803003729111744 + 0.0050829102648874917 + 0.0050855186457235994 + 0.0050881255192652278 + 0.005090730889342158 + 0.0050933347597682688 + 0.0050959371343416741 + 0.0050985380168448021 + 0.0051011374110444983 + 0.0051037353206920856 + 0.0051063317495235183 + 0.0051089267012594175 + 0.005111520179605175 + 0.0051141121882510637 + 0.0051167027308723157 + 0.0051192918111292018 + 0.0051218794326671306 + 0.0051244655991167405 + 0.0051270503140939715 + 0.0051296335812001572 + 0.0051322154040221247 + 0.0051347957861322575 + 0.0051373747310885865 + 0.0051399522424348939 + 0.0051425283237007575 + 0.0051451029784016682 + 0.0051476762100390967 + 0.0051502480221005753 + 0.0051528184180597734 + 0.0051553874013765865 + 0.0051579549754972188 + 0.005160521143854257 + 0.005163085909866731 + 0.0051656492769402134 + 0.0051682112484669048 + 0.0051707718278256659 + 0.0051733310183821549 + 0.0051758888234888561 + 0.005178445246485165 + 0.0051810002906974781 + 0.0051835539594392369 + 0.005186106256011039 + 0.0051886571837006885 + 0.0051912067457832627 + 0.005193754945521184 + 0.005196301786164312 + 0.0051988472709499946 + 0.0052013914031031495 + 0.0052039341858363094 + 0.0052064756223497276 + 0.0052090157158314193 + 0.0052115544694572346 + 0.0052140918863909378 + 0.0052166279697842544 + 0.0052191627227769627 + 0.0052216961484969375 + 0.0052242282500602 + 0.0052267590305710666 + 0.005229288493122086 + 0.0052318166407942174 + 0.0052343434766568258 + 0.0052368690037677681 + 0.0052393932251734608 + 0.0052419161439089257 + 0.0052444377629978804 + 0.0052469580854527633 + 0.0052494771142748099 + 0.0052519948524541284 + 0.0052545113029697421 + 0.0052570264687896526 + 0.005259540352870914 + 0.0052620529581596399 + 0.0052645642875911456 + 0.0052670743440899354 + 0.0052695831305697889 + 0.0052720906499338039 + 0.0052745969050744974 + 0.0052771018988737994 + 0.0052796056342031437 + 0.005282108113923518 + 0.0052846093408855229 + 0.0052871093179294127 + 0.0052896080478851771 + 0.0052921055335725638 + 0.0052946017778011606 + 0.0052970967833704131 + 0.005299590553069714 + 0.0053020830896784469 + 0.0053045743959660189 + 0.0053070644746919336 + 0.0053095533286058264 + 0.0053120409604475363 + 0.0053145273729471466 + 0.0053170125688250169 + 0.0053194965507918747 + 0.0053219793215488172 + 0.0053244608837873988 + 0.0053269412401896667 + 0.0053294203934281942 + 0.0053318983461661633 + 0.0053343751010573757 + 0.0053368506607463359 + 0.0053393250278682561 + 0.0053417982050491634 + 0.0053442701949058874 + 0.005346741000046131 + 0.0053492106230685265 + 0.005351679066562671 + 0.0053541463331091702 + 0.0053566124252796875 + 0.0053590773456369794 + 0.0053615410967349682 + 0.0053640036811187491 + 0.00536646510132467 + 0.0053689253598803435 + 0.0053713844593047105 + 0.0053738424021080745 + 0.0053762991907921453 + 0.0053787548278501039 + 0.0053812093157666009 + 0.0053836626570178455 + 0.0053861148540716068 + 0.0053885659093872804 + 0.0053910158254159343 + 0.0053934646046003209 + 0.0053959122493749479 + 0.0053983587621661104 + 0.0054008041453919133 + 0.0054032484014623419 + 0.0054056915327792684 + 0.0054081335417365305 + 0.0054105744307199324 + 0.0054130142021073012 + 0.0054154528582685312 + 0.005417890401565627 + 0.005420326834352702 + 0.0054227621589760661 + 0.005425196377774234 + 0.0054276294930779897 + 0.0054300615072103804 + 0.0054324924224868013 + 0.0054349222412149872 + 0.0054373509656950947 + 0.0054397785982197048 + 0.0054422051410738604 + 0.0054446305965351414 + 0.0054470549668736434 + 0.0054494782543520548 + 0.0054519004612256592 + 0.0054543215897424249 + 0.0054567416421429683 + 0.0054591606206606568 + 0.0054615785275215758 + 0.0054639953649446293 + 0.0054664111351415256 + 0.005468825840316837 + 0.0054712394826680159 + 0.0054736520643854465 + 0.0054760635876524542 + 0.0054784740546453626 + 0.0054808834675335255 + 0.0054832918284793307 + 0.0054856991396382577 + 0.0054881054031589169 + 0.0054905106211830534 + 0.0054929147958455984 + 0.0054953179292747028 + 0.0054977200235917442 + 0.0055001210809113984 + 0.0055025211033416415 + 0.0055049200929837777 + 0.0055073180519324824 + 0.0055097149822758394 + 0.0055121108860953522 + 0.0055145057654659877 + 0.0055168996224561982 + 0.0055192924591279556 + 0.005521684277536785 + 0.0055240750797317783 + 0.0055264648677556408 + 0.0055288536436447202 + 0.0055312414094290134 + 0.0055336281671322287 + 0.0055360139187717681 + 0.0055383986663588196 + 0.0055407824118983203 + 0.0055431651573890359 + 0.0055455469048235392 + 0.0055479276561882949 + 0.005550307413463621 + 0.0055526861786238009 + 0.0055550639536370034 + 0.0055574407404654184 + 0.0055598165410652078 + 0.0055621913573865546 + 0.005564565191373709 + 0.0055669380449649896 + 0.0055693099200928142 + 0.0055716808186837344 + 0.0055740507426584552 + 0.0055764196939318668 + 0.0055787876744130705 + 0.0055811546860053771 + 0.0055835207306063799 + 0.0055858858101079404 + 0.0055882499263962453 + 0.0055906130813517842 + 0.0055929752768494375 + 0.0055953365147584384 + 0.005597696796942454 + 0.0056000561252595501 + 0.0056024145015622752 + 0.0056047719276976519 + 0.0056071284055071949 + 0.0056094839368269452 + 0.0056118385234875138 + 0.0056141921673140598 + 0.0056165448701263583 + 0.0056188966337388027 + 0.0056212474599604137 + 0.0056235973505949031 + 0.0056259463074406499 + 0.0056282943322907572 + 0.0056306414269330692 + 0.0056329875931501608 + 0.0056353328327194219 + 0.0056376771474130165 + 0.0056400205389979478 + 0.0056423630092360573 + 0.0056447045598840527 + 0.0056470451926935381 + 0.0056493849094110312 + 0.0056517237117779699 + 0.005654061601530749 + 0.0056563985804007431 + 0.0056587346501143186 + 0.0056610698123928721 + 0.0056634040689528212 + 0.0056657374215056495 + 0.0056680698717579171 + 0.0056704014214112889 + 0.0056727320721625491 + 0.0056750618257036256 + 0.0056773906837215959 + 0.005679718647898728 + 0.0056820457199124978 + 0.0056843719014355787 + 0.0056866971941359071 + 0.0056890215996766797 + 0.0056913451197163553 + 0.0056936677559087032 + 0.0056959895099028173 + 0.0056983103833431192 + 0.0057006303778693954 + 0.0057029494951168066 + 0.005705267736715894 + 0.005707585104292639 + 0.00570990159946844 + 0.0057122172238601452 + 0.0057145319790800802 + 0.0057168458667360535 + 0.0057191588884313799 + 0.005721471045764902 + 0.0057237823403310127 + 0.0057260927737196468 + 0.0057284023475163261 + 0.0057307110633021841 + 0.0057330189226539475 + 0.0057353259271439904 + 0.0057376320783403345 + 0.0057399373778066459 + 0.005742241827102308 + 0.0057445454277823844 + 0.0057468481813976839 + 0.0057491500894947083 + 0.005751451153615755 + 0.0057537513752988663 + 0.0057560507560778709 + 0.0057583492974824305 + 0.0057606470010379829 + 0.0057629438682658459 + 0.0057652399006831436 + 0.0057675350998029279 + 0.0057698294671340829 + 0.0057721230041814292 + 0.0057744157124456829 + 0.0057767075934235185 + 0.0057789986486075388 + 0.0057812888794863283 + 0.0057835782875444476 + 0.0057858668742624495 + 0.0057881546411169106 + 0.005790441589580436 + 0.0057927277211216625 + 0.0057950130372053038 + 0.0057972975392921386 + 0.0057995812288390344 + 0.0058018641072989756 + 0.0058041461761210679 + 0.0058064274367505232 + 0.0058087078906287459 + 0.0058109875391932691 + 0.0058132663838778489 + 0.0058155444261123969 + 0.0058178216673230448 + 0.0058200981089321585 + 0.0058223737523583454 + 0.0058246485990164389 + 0.0058269226503175784 + 0.0058291959076691565 + 0.0058314683724748732 + 0.0058337400461347371 + 0.0058360109300450817 + 0.0058382810255985735 + 0.0058405503341842383 + 0.0058428188571874691 + 0.005845086595990031 + 0.0058473535519700864 + 0.005849619726502199 + 0.0058518851209573702 + 0.0058541497367030149 + 0.0058564135751030082 + 0.005858676637517682 + 0.0058609389253038453 + 0.0058632004398147973 + 0.0058654611824003229 + 0.0058677211544067333 + 0.0058699803571768726 + 0.0058722387920501044 + 0.005874496460362374 + 0.0058767533634461631 + 0.0058790095026305389 + 0.0058812648792411753 + 0.0058835194946003392 + 0.0058857733500269089 + 0.0058880264468364005 + 0.0058902787863409686 + 0.0058925303698494158 + 0.0058947811986672146 + 0.005897031274096529 + 0.0058992805974361958 + 0.0059015291699817509 + 0.0059037769930254625 + 0.005906024067856324 + 0.0059082703957600482 + 0.00591051597801913 + 0.00591276081591279 + 0.0059150049107170562 + 0.0059172482637047247 + 0.0059194908761453884 + 0.0059217327493054769 + 0.0059239738844481986 + 0.0059262142828336297 + 0.0059284539457186702 + 0.0059306928743570828 + 0.0059329310699995069 + 0.0059351685338934436 + 0.0059374052672832916 + 0.0059396412714103558 + 0.0059418765475128489 + 0.0059441110968258982 + 0.005946344920581585 + 0.0059485780200089168 + 0.0059508103963338511 + 0.0059530420507793516 + 0.0059552729845653192 + 0.0059575031989086719 + 0.0059597326950232973 + 0.0059619614741201173 + 0.005964189537407071 + 0.0059664168860891252 + 0.0059686435213682906 + 0.0059708694444436166 + 0.0059730946565112446 + 0.0059753191587643617 + 0.0059775429523932578 + 0.0059797660385853026 + 0.0059819884185249748 + 0.0059842100933938779 + 0.0059864310643707262 + 0.0059886513326313732 + 0.0059908708993488191 + 0.0059930897656932129 + 0.0059953079328318778 + 0.0059975254019293076 + 0.0059997421741471791 + 0.0060019582506443602 + 0.0060041736325769333 + 0.0060063883210981824 + 0.0060086023173586281 + 0.0060108156225060147 + 0.0060130282376853394 + 0.0060152401640388275 + 0.0060174514027059945 + 0.0060196619548236185 + 0.0060218718215257552 + 0.0060240810039437539 + 0.006026289503206249 + 0.0060284973204392089 + 0.0060307044567659077 + 0.0060329109133069386 + 0.0060351166911802442 + 0.0060373217915011016 + 0.0060395262153821669 + 0.0060417299639334244 + 0.0060439330382622541 + 0.0060461354394734206 + 0.0060483371686690579 + 0.0060505382269487214 + 0.0060527386154093738 + 0.0060549383351453795 + 0.0060571373872485394 + 0.0060593357728080917 + 0.0060615334929107105 + 0.0060637305486405235 + 0.0060659269410791245 + 0.0060681226713055767 + 0.0060703177403964035 + 0.0060725121494256589 + 0.0060747058994648304 + 0.0060768989915829675 + 0.0060790914268465798 + 0.006081283206319745 + 0.0060834743310640279 + 0.0060856648021385554 + 0.0060878546205999926 + 0.0060900437875025621 + 0.0060922323038980252 + 0.0060944201708357506 + 0.0060966073893626441 + 0.0060987939605232295 + 0.006100979885359608 + 0.0061031651649114827 + 0.006105349800216181 + 0.0061075337923086155 + 0.0061097171422213664 + 0.0061118998509846062 + 0.0061140819196261837 + 0.0061162633491715626 + 0.006118444140643893 + 0.006120624295063974 + 0.0061228038134502833 + 0.0061249826968189629 + 0.0061271609461838574 + 0.0061293385625565099 + 0.0061315155469461469 + 0.0061336919003597183 + 0.0061358676238018961 + 0.0061380427182750564 + 0.0061402171847793289 + 0.0061423910243125733 + 0.0061445642378703969 + 0.0061467368264461648 + 0.0061489087910309888 + 0.0061510801326137687 + 0.0061532508521811727 + 0.0061554209507176504 + 0.0061575904292054482 + 0.0061597592886246007 + 0.0061619275299529428 + 0.0061640951541661422 + 0.0061662621622376708 + 0.0061684285551388256 + 0.0061705943338387368 + 0.0061727594993043712 + 0.0061749240525005604 + 0.0061770879943899753 + 0.0061792513259331392 + 0.0061814140480884582 + 0.0061835761618122004 + 0.0061857376680585193 + 0.0061878985677794665 + 0.0061900588619249698 + 0.0061922185514428647 + 0.0061943776372789033 + 0.0061965361203767336 + 0.0061986940016779497 + 0.0062008512821220456 + 0.0062030079626464712 + 0.0062051640441866032 + 0.0062073195276757739 + 0.0062094744140452586 + 0.0062116287042243076 + 0.0062137823991401308 + 0.0062159354997178961 + 0.0062180880068807764 + 0.00622023992154991 + 0.0062223912446444417 + 0.0062245419770815052 + 0.0062266921197762391 + 0.0062288416736417948 + 0.0062309906395893325 + 0.0062331390185280623 + 0.0062352868113651899 + 0.0062374340190059687 + 0.006239580642353703 + 0.0062417266823097247 + 0.0062438721397734395 + 0.0062460170156423073 + 0.0062481613108118523 + 0.0062503050261756496 + 0.0062524481626253974 + 0.0062545907210508275 + 0.0062567327023397993 + 0.0062588741073782445 + 0.0062610149370502096 + 0.0062631551922378388 + 0.0062652948738213957 + 0.0062674339826792472 + 0.006269572519687917 + 0.0062717104857220214 + 0.006273847881654338 + 0.0062759847083557795 + 0.0062781209666953998 + 0.0062802566575404055 + 0.0062823917817561728 + 0.0062845263402062307 + 0.0062866603337522848 + 0.0062887937632542185 + 0.0062909266295700728 + 0.0062930589335561159 + 0.006295190676066772 + 0.0062973218579546672 + 0.0062994524800706582 + 0.0063015825432637751 + 0.0063037120483812863 + 0.0063058409962686648 + 0.0063079693877696064 + 0.0063100972237260522 + 0.0063122245049781617 + 0.0063143512323643475 + 0.0063164774067212531 + 0.0063186030288837937 + 0.006320728099685125 + 0.0063228526199566541 + 0.0063249765905280825 + 0.0063271000122273654 + 0.006329222885880734 + 0.0063313452123127095 + 0.0063334669923460936 + 0.0063355882268019874 + 0.0063377089164997702 + 0.0063398290622571551 + 0.0063419486648901378 + 0.0063440677252130286 + 0.006346186244038478 + 0.0063483042221774187 + 0.0063504216604391428 + 0.0063525385596312619 + 0.0063546549205597373 + 0.0063567707440288553 + 0.0063588860308412543 + 0.0063610007817979201 + 0.0063631149976982266 + 0.0063652286793398566 + 0.0063673418275189035 + 0.0063694544430298048 + 0.0063715665266653879 + 0.0063736780792168568 + 0.0063757891014738039 + 0.0063778995942242005 + 0.0063800095582544269 + 0.0063821189943492453 + 0.0063842279032918477 + 0.0063863362858638181 + 0.0063884441428451464 + 0.0063905514750142558 + 0.0063926582831479763 + 0.0063947645680215845 + 0.0063968703304087817 + 0.0063989755710816953 + 0.0064010802908108936 + 0.0064031844903654055 + 0.006405288170512698 + 0.0064073913320186965 + 0.0064094939756477818 + 0.0064115961021627985 + 0.0064136977123250595 + 0.0064157988068943494 + 0.0064178993866289289 + 0.0064199994522855363 + 0.0064220990046194035 + 0.006424198044384241 + 0.0064262965723322577 + 0.0064283945892141536 + 0.0064304920957791575 + 0.0064325890927749681 + 0.0064346855809478062 + 0.0064367815610424364 + 0.0064388770338020887 + 0.0064409719999685639 + 0.0064430664602821699 + 0.0064451604154817498 + 0.006447253866304673 + 0.0064493468134868698 + 0.0064514392577627883 + 0.0064535311998654542 + 0.0064556226405264212 + 0.0064577135804758075 + 0.0064598040204422958 + 0.0064618939611531282 + 0.0064639834033341139 + 0.0064660723477096517 + 0.0064681607950026797 + 0.0064702487459347632 + 0.0064723362012260102 + 0.0064744231615951487 + 0.0064765096277594782 + 0.0064785956004349042 + 0.0064806810803359283 + 0.0064827660681756726 + 0.0064848505646658353 + 0.0064869345705167551 + 0.0064890180864373712 + 0.0064911011131352486 + 0.0064931836513165819 + 0.0064952657016861754 + 0.0064973472649474708 + 0.0064994283418025609 + 0.0065015089329521544 + 0.0065035890390956223 + 0.0065056686609309671 + 0.0065077477991548494 + 0.0065098264544625733 + 0.006511904627548107 + 0.0065139823191040927 + 0.0065160595298218108 + 0.006518136260391231 + 0.0065202125115009814 + 0.0065222882838383836 + 0.0065243635780894123 + 0.0065264383949387491 + 0.0065285127350697631 + 0.0065305865991644755 + 0.006532659987903657 + 0.0065347329019667336 + 0.0065368053420318505 + 0.0065388773087758523 + 0.0065409488028742814 + 0.0065430198250014098 + 0.0065450903758302254 + 0.0065471604560324165 + 0.0065492300662784043 + 0.006551299207237328 + 0.0065533678795770692 + 0.0065554360839642231 + 0.0065575038210641395 + 0.0065595710915409009 + 0.0065616378960573259 + 0.0065637042352749714 + 0.0065657701098541747 + 0.0065678355204539848 + 0.0065699004677322462 + 0.0065719649523455371 + 0.0065740289749491952 + 0.0065760925361973465 + 0.0065781556367428707 + 0.0065802182772374202 + 0.0065822804583314286 + 0.0065843421806741007 + 0.0065864034449134336 + 0.0065884642516962069 + 0.0065905246016679745 + 0.0065925844954731047 + 0.0065946439337547487 + 0.0065967029171548567 + 0.0065987614463141903 + 0.0066008195218722971 + 0.0066028771444675474 + 0.0066049343147371233 + 0.0066069910333170032 + 0.0066090473008420091 + 0.0066111031179457644 + 0.0066131584852607214 + 0.0066152134034181617 + 0.0066172678730481889 + 0.0066193218947797599 + 0.0066213754692406365 + 0.0066234285970574406 + 0.0066254812788556381 + 0.0066275335152595222 + 0.0066295853068922576 + 0.0066316366543758432 + 0.006633687558331134 + 0.0066357380193778452 + 0.006637788038134554 + 0.0066398376152186989 + 0.0066418867512465819 + 0.0066439354468333751 + 0.0066459837025931298 + 0.0066480315191387584 + 0.0066500788970820651 + 0.0066521258370337236 + 0.0066541723396033019 + 0.0066562184053992448 + 0.0066582640350288909 + 0.006660309229098476 + 0.0066623539882131148 + 0.0066643983129768417 + 0.0066664422039925848 + 0.0066684856618621554 + 0.0066705286871863046 + 0.0066725712805646657 + 0.0066746134425958092 + 0.0066766551738771896 + 0.0066786964750052066 + 0.0066807373465751661 + 0.0066827777891813088 + 0.0066848178034167888 + 0.0066868573898736872 + 0.0066888965491430329 + 0.0066909352818147741 + 0.0066929735884778095 + 0.0066950114697199616 + 0.0066970489261280013 + 0.0066990859582876545 + 0.0067011225667835874 + 0.0067031587521994155 + 0.0067051945151176936 + 0.0067072298561199721 + 0.0067092647757867156 + 0.0067112992746973781 + 0.0067133333534303719 + 0.0067153670125630598 + 0.0067174002526717951 + 0.0067194330743318917 + 0.0067214654781176377 + 0.006723497464602303 + 0.0067255290343581301 + 0.0067275601879563498 + 0.0067295909259671707 + 0.0067316212489597922 + 0.0067336511575024193 + 0.006735680652162207 + 0.0067377097335053525 + 0.0067397384020970201 + 0.0067417666585013834 + 0.006743794503281623 + 0.0067458219369999082 + 0.0067478489602174349 + 0.0067498755734944011 + 0.0067519017773900007 + 0.0067539275724624722 + 0.0067559529592690574 + 0.0067579779383660056 + 0.0067600025103086089 + 0.0067620266756511704 + 0.0067640504349470148 + 0.0067660737887485214 + 0.0067680967376070687 + 0.0067701192820730895 + 0.0067721414226960585 + 0.0067741631600244604 + 0.0067761844946058625 + 0.0067782054269868355 + 0.0067802259577130243 + 0.0067822460873291062 + 0.0067842658163788146 + 0.0067862851454049307 + 0.0067883040749493065 + 0.0067903226055528428 + 0.0067923407377554765 + 0.0067943584720962531 + 0.006796375809113249 + 0.0067983927493436135 + 0.0068004092933235732 + 0.0068024254415884272 + 0.0068044411946725329 + 0.0068064565531093307 + 0.0068084715174313521 + 0.0068104860881701857 + 0.0068125002658565347 + 0.0068145140510201497 + 0.0068165274441898977 + 0.0068185404458937183 + 0.0068205530566586578 + 0.0068225652770108431 + 0.0068245771074754887 + 0.0068265885485769328 + 0.0068285996008386127 + 0.0068306102647830332 + 0.0068326205409318342 + 0.00683463042980576 + 0.0068366399319246644 + 0.0068386490478074954 + 0.0068406577779723315 + 0.0068426661229363675 + 0.0068446740832159023 + 0.0068466816593263707 + 0.0068486888517823143 + 0.0068506956610974038 + 0.0068527020877844382 + 0.0068547081323553551 + 0.0068567137953212025 + 0.0068587190771921616 + 0.0068607239784775689 + 0.0068627284996858832 + 0.0068647326413246931 + 0.0068667364039007462 + 0.0068687397879199251 + 0.0068707427938872476 + 0.0068727454223069017 + 0.0068747476736821991 + 0.0068767495485156154 + 0.0068787510473087765 + 0.0068807521705624647 + 0.0068827529187766162 + 0.0068847532924503187 + 0.0068867532920818446 + 0.0068887529181686068 + 0.0068907521712071968 + 0.0068927510516933604 + 0.0068947495601220125 + 0.0068967476969872456 + 0.0068987454627823363 + 0.0069007428579997169 + 0.0069027398831310021 + 0.0069047365386669789 + 0.0069067328250976261 + 0.0069087287429121088 + 0.0069107242925987517 + 0.0069127194746451005 + 0.0069147142895378613 + 0.0069167087377629338 + 0.0069187028198054177 + 0.0069206965361496148 + 0.0069226898872789943 + 0.0069246828736762639 + 0.0069266754958232793 + 0.006928667754201148 + 0.0069306596492901551 + 0.0069326511815697876 + 0.0069346423515187503 + 0.0069366331596149447 + 0.0069386236063355058 + 0.0069406136921567512 + 0.006942603417554232 + 0.0069445927830027124 + 0.0069465817889761737 + 0.0069485704359478172 + 0.0069505587243900548 + 0.0069525466547745475 + 0.0069545342275721556 + 0.0069565214432529762 + 0.0069585083022863379 + 0.0069604948051407971 + 0.0069624809522841344 + 0.0069644667441833901 + 0.0069664521813048016 + 0.0069684372641138793 + 0.0069704219930753633 + 0.0069724063686532126 + 0.0069743903913106605 + 0.006976374061510162 + 0.0069783573797134318 + 0.0069803403463814286 + 0.0069823229619743543 + 0.0069843052269516707 + 0.0069862871417720939 + 0.0069882687068935903 + 0.0069902499227733764 + 0.0069922307898679509 + 0.006994211308633029 + 0.0069961914795236366 + 0.0069981713029940319 + 0.0070001507794977477 + 0.0070021299094875878 + 0.0070041086934156133 + 0.0070060871317331542 + 0.0070080652248908316 + 0.0070100429733385228 + 0.0070120203775253746 + 0.0070139974378998372 + 0.0070159741549096124 + 0.0070179505290016977 + 0.0070199265606223481 + 0.0070219022502171326 + 0.0070238775982309019 + 0.0070258526051077685 + 0.0070278272712911514 + 0.0070298015972237457 + 0.0070317755833475626 + 0.0070337492301038888 + 0.0070357225379332903 + 0.0070376955072756599 + 0.0070396681385701603 + 0.0070416404322552889 + 0.0070436123887688022 + 0.0070455840085477837 + 0.0070475552920286188 + 0.0070495262396469815 + 0.0070514968518378763 + 0.0070534671290356085 + 0.0070554370716737775 + 0.0070574066801853156 + 0.0070593759550024509 + 0.0070613448965567462 + 0.0070633135052790685 + 0.0070652817815995937 + 0.0070672497259478178 + 0.0070692173387525876 + 0.0070711846204420392 + 0.0070731515714436309 + 0.0070751181921841723 + 0.0070770844830897904 + 0.0070790504445859158 + 0.0070810160770973457 + 0.0070829813810481769 + 0.0070849463568618647 + 0.0070869110049611786 + 0.0070888753257682307 + 0.0070908393197044745 + 0.0070928029871907012 + 0.0070947663286470347 + 0.0070967293444929476 + 0.0070986920351472412 + 0.0071006544010280845 + 0.0071026164425529691 + 0.0071045781601387506 + 0.0071065395542016336 + 0.0071085006251571468 + 0.0071104613734202082 + 0.0071124217994050576 + 0.0071143819035253087 + 0.0071163416861939133 + 0.007118301147823196 + 0.0071202602888248328 + 0.0071222191096098628 + 0.0071241776105886835 + 0.0071261357921710514 + 0.0071280936547660914 + 0.0071300511987823049 + 0.0071320084246275341 + 0.0071339653327090018 + 0.0071359219234333228 + 0.0071378781972064407 + 0.0071398341544337074 + 0.007141789795519827 + 0.0071437451208688817 + 0.0071457001308843464 + 0.007147654825969049 + 0.0071496092065252131 + 0.00715156327295444 + 0.0071535170256577007 + 0.0071554704650353676 + 0.0071574235914871965 + 0.0071593764054123099 + 0.0071613289072092268 + 0.0071632810972758658 + 0.0071652329760095177 + 0.0071671845438068789 + 0.0071691358010640234 + 0.0071710867481764289 + 0.0071730373855389707 + 0.0071749877135459158 + 0.0071769377325909232 + 0.007178887443067051 + 0.0071808368453667648 + 0.0071827859398819281 + 0.0071847347270038112 + 0.0071866832071230879 + 0.0071886313806298228 + 0.0071905792479135004 + 0.0071925268093630127 + 0.0071944740653666558 + 0.0071964210163121354 + 0.0071983676625865748 + 0.0072003140045765017 + 0.0072022600426678652 + 0.0072042057772460288 + 0.0072061512086957673 + 0.0072080963374012742 + 0.007210041163746162 + 0.0072119856881134627 + 0.0072139299108856404 + 0.0072158738324445675 + 0.0072178174531715485 + 0.0072197607734473005 + 0.0072217037936519839 + 0.007223646514165182 + 0.007225588935365893 + 0.0072275310576325582 + 0.0072294728813430487 + 0.0072314144068746661 + 0.0072333556346041439 + 0.0072352965649076558 + 0.007237237198160793 + 0.0072391775347386148 + 0.0072411175750155821 + 0.0072430573193656284 + 0.0072449967681621113 + 0.0072469359217778367 + 0.0072488747805850269 + 0.0072508133449553881 + 0.0072527516152600504 + 0.0072546895918695915 + 0.0072566272751540426 + 0.0072585646654828671 + 0.0072605017632249953 + 0.0072624385687488054 + 0.007264375082422129 + 0.0072663113046122349 + 0.007268247235685866 + 0.0072701828760092079 + 0.0072721182259479159 + 0.0072740532858670852 + 0.0072759880561312825 + 0.0072779225371045319 + 0.0072798567291503229 + 0.0072817906326315884 + 0.0072837242479107493 + 0.0072856575753496647 + 0.0072875906153096991 + 0.0072895233681516299 + 0.0072914558342357496 + 0.0072933880139217939 + 0.0072953199075689694 + 0.0072972515155359709 + 0.0072991828381809461 + 0.0073011138758615228 + 0.0073030446289348077 + 0.0073049750977573682 + 0.00730690528268527 + 0.0073088351840740352 + 0.0073107648022786706 + 0.0073126941376536816 + 0.0073146231905530145 + 0.0073165519613301441 + 0.0073184804503379861 + 0.0073204086579289687 + 0.0073223365844549875 + 0.0073242642302674462 + 0.0073261915957171962 + 0.0073281186811546169 + 0.007330045486929556 + 0.0073319720133913557 + 0.0073338982608888515 + 0.0073358242297703654 + 0.0073377499203837147 + 0.0073396753330762215 + 0.0073416004681946855 + 0.0073435253260854165 + 0.0073454499070942075 + 0.0073473742115663723 + 0.0073492982398466848 + 0.0073512219922794702 + 0.0073531454692085203 + 0.0073550686709771334 + 0.0073569915979281213 + 0.007358914250403783 + 0.0073608366287459519 + 0.007362758733295941 + 0.0073646805643945669 + 0.0073666021223821911 + 0.0073685234075986511 + 0.0073704444203832944 + 0.0073723651610750011 + 0.0073742856300121418 + 0.0073762058275326217 + 0.007378125753973834 + 0.007380045409672709 + 0.0073819647949657013 + 0.0073838839101887377 + 0.0073858027556773127 + 0.0073877213317664111 + 0.0073896396387905482 + 0.0073915576770837623 + 0.0073934754469796036 + 0.0073953929488111466 + 0.0073973101829110021 + 0.0073992271496112968 + 0.0074011438492436769 + 0.0074030602821393279 + 0.0074049764486289549 + 0.0074068923490427938 + 0.0074088079837106137 + 0.0074107233529616999 + 0.007412638457124884 + 0.0074145532965285248 + 0.0074164678715005197 + 0.0074183821823682831 + 0.0074202962294587895 + 0.0074222100130985173 + 0.0074241235336135209 + 0.007426036791329354 + 0.0074279497865711343 + 0.0074298625196635194 + 0.0074317749909306877 + 0.0074336872006963758 + 0.0074355991492838502 + 0.0074375108370159388 + 0.0074394222642149939 + 0.0074413334312029246 + 0.0074432443383011864 + 0.0074451549858307728 + 0.0074470653741122231 + 0.0074489755034656399 + 0.0074508853742106728 + 0.0074527949866665119 + 0.0074547043411518936 + 0.0074566134379851247 + 0.0074585222774840544 + 0.0074604308599660859 + 0.0074623391857481774 + 0.0074642472551468397 + 0.0074661550684781454 + 0.0074680626260577266 + 0.0074699699282007722 + 0.0074718769752220209 + 0.0074737837674357672 + 0.0074756903051559024 + 0.0074775965886958321 + 0.0074795026183685533 + 0.0074814083944866189 + 0.007483313917362149 + 0.0074852191873068137 + 0.0074871242046318709 + 0.00748902896964813 + 0.0074909334826659809 + 0.007492837743995364 + 0.0074947417539458026 + 0.0074966455128263818 + 0.0074985490209457592 + 0.0075004522786121805 + 0.0075023552861334343 + 0.0075042580438169073 + 0.0075061605519695426 + 0.0075080628108978673 + 0.0075099648209079927 + 0.0075118665823055908 + 0.0075137680953959096 + 0.0075156693604837991 + 0.0075175703778736528 + 0.0075194711478694795 + 0.0075213716707748504 + 0.0075232719468929067 + 0.0075251719765263968 + 0.0075270717599776309 + 0.0075289712975485281 + 0.0075308705895405668 + 0.0075327696362548196 + 0.0075346684379919409 + 0.0075365669950521862 + 0.007538465307735393 + 0.0075403633763409693 + 0.0075422612011679432 + 0.0075441587825149032 + 0.0075460561206800534 + 0.0075479532159611704 + 0.0075498500686556327 + 0.0075517466790604171 + 0.0075536430474720806 + 0.0075555391741867744 + 0.0075574350595002783 + 0.0075593307037079109 + 0.0075612261071046471 + 0.0075631212699850221 + 0.0075650161926431748 + 0.0075669108753728554 + 0.0075688053184674066 + 0.0075706995222197667 + 0.0075725934869224935 + 0.0075744872128677195 + 0.0075763807003472123 + 0.0075782739496523151 + 0.007580166961073994 + 0.0075820597349028126 + 0.0075839522714289389 + 0.0075858445709421473 + 0.0075877366337318312 + 0.0075896284600869895 + 0.0075915200502962134 + 0.0075934114046477064 + 0.0075953025234293181 + 0.0075971934069284687 + 0.0075990840554321978 + 0.0076009744692271735 + 0.007602864648599667 + 0.0076047545938355597 + 0.0076066443052203491 + 0.007608533783039168 + 0.0076104230275767298 + 0.0076123120391174024 + 0.007614200817945142 + 0.007616089364343534 + 0.0076179776785957913 + 0.007619865760984724 + 0.0076217536117927911 + 0.0076236412313020613 + 0.0076255286197942137 + 0.0076274157775505572 + 0.0076293027048520441 + 0.0076311894019792182 + 0.0076330758692122599 + 0.0076349621068309828 + 0.0076368481151148282 + 0.0076387338943428472 + 0.0076406194447937387 + 0.0076425047667458123 + 0.0076443898604770183 + 0.0076462747262649264 + 0.0076481593643867489 + 0.0076500437751193251 + 0.0076519279587391196 + 0.0076538119155222361 + 0.0076556956457444003 + 0.0076575791496809849 + 0.0076594624276070042 + 0.0076613454797970727 + 0.0076632283065254728 + 0.0076651109080661129 + 0.0076669932846925503 + 0.0076688754366779441 + 0.0076707573642951429 + 0.0076726390678165937 + 0.0076745205475143947 + 0.0076764018036602861 + 0.0076782828365256567 + 0.0076801636463815215 + 0.0076820442334985589 + 0.0076839245981470674 + 0.007685804740596997 + 0.0076876846611179574 + 0.0076895643599791692 + 0.0076914438374495455 + 0.0076933230937975905 + 0.0076952021292915045 + 0.0076970809441991106 + 0.0076989595387878772 + 0.0077008379133249307 + 0.0077027160680770597 + 0.0077045940033106655 + 0.007706471719291833 + 0.0077083492162862855 + 0.0077102264945594062 + 0.0077121035543762156 + 0.0077139803960014058 + 0.0077158570196993069 + 0.0077177334257339117 + 0.0077196096143688671 + 0.0077214855858674727 + 0.0077233613404926972 + 0.0077252368785071437 + 0.0077271122001730955 + 0.0077289873057524655 + 0.0077308621955068683 + 0.0077327368696975323 + 0.0077346113285853757 + 0.0077364855724309702 + 0.0077383596014945358 + 0.0077402334160359843 + 0.007742107016314859 + 0.007743980402590377 + 0.0077458535751214214 + 0.0077477265341665399 + 0.0077495992799839434 + 0.0077514718128315055 + 0.0077533441329667675 + 0.0077552162406469569 + 0.0077570881361289255 + 0.007758959819669225 + 0.0077608312915240819 + 0.0077627025519493645 + 0.0077645736012006234 + 0.00776644443953308 + 0.0077683150672016336 + 0.0077701854844608505 + 0.0077720556915649485 + 0.007773925688767858 + 0.0077757954763231453 + 0.0077776650544840731 + 0.0077795344235035693 + 0.0077814035836342417 + 0.0077832725351283591 + 0.0077851412782378795 + 0.0077870098132144482 + 0.0077888781403093674 + 0.0077907462597736213 + 0.0077926141718578723 + 0.0077944818768124844 + 0.0077963493748874528 + 0.0077982166663324998 + 0.007800083751397009 + 0.0078019506303300427 + 0.0078038173033803506 + 0.0078056837707963581 + 0.0078075500328261818 + 0.0078094160897176166 + 0.0078112819417181433 + 0.0078131475890749272 + 0.0078150130320348166 + 0.0078168782708443463 + 0.0078187433057497393 + 0.0078206081369968893 + 0.0078224727648314139 + 0.0078243371894985893 + 0.0078262014112433845 + 0.0078280654303104526 + 0.0078299292469441572 + 0.0078317928613885323 + 0.0078336562738873013 + 0.0078355194846838946 + 0.0078373824940214214 + 0.0078392453021426962 + 0.0078411079092901952 + 0.0078429703157061378 + 0.0078448325216323878 + 0.0078466945273105385 + 0.0078485563329818465 + 0.0078504179388873014 + 0.0078522793452675543 + 0.0078541405523629704 + 0.0078560015604136127 + 0.0078578623696592409 + 0.0078597229803393006 + 0.0078615833926929442 + 0.0078634436069590363 + 0.0078653036233761117 + 0.0078671634421824364 + 0.0078690230636159555 + 0.0078708824879143175 + 0.0078727417153148915 + 0.007874600746054736 + 0.0078764595803705872 + 0.0078783182184989243 + 0.0078801766606759194 + 0.0078820349071374377 + 0.0078838929581190528 + 0.0078857508138560541 + 0.0078876084745834168 + 0.0078894659405358367 + 0.0078913232119477324 + 0.007893180289053189 + 0.0078950371720860248 + 0.0078968938612797787 + 0.0078987503568676599 + 0.0079006066590826315 + 0.0079024627681573267 + 0.0079043186843241291 + 0.007906174407815084 + 0.0079080299388619973 + 0.0079098852776963591 + 0.0079117404245493735 + 0.0079135953796519547 + 0.0079154501432347479 + 0.0079173047155280934 + 0.0079191590967620622 + 0.0079210132871664271 + 0.007922867286970673 + 0.0079247210964040107 + 0.0079265747156953593 + 0.0079284281450733747 + 0.0079302813847664036 + 0.0079321344350025223 + 0.0079339872960095207 + 0.0079358399680149131 + 0.0079376924512459344 + 0.0079395447459295332 + 0.0079413968522923754 + 0.0079432487705608547 + 0.00794510050096108 + 0.0079469520437188933 + 0.0079488033990598467 + 0.0079506545672092133 + 0.0079525055483920058 + 0.0079543563428329262 + 0.0079562069507564392 + 0.0079580573723867162 + 0.007959907607947651 + 0.0079617576576628667 + 0.0079636075217557074 + 0.0079654572004492479 + 0.0079673066939662928 + 0.0079691560025293619 + 0.007971005126360722 + 0.0079728540656823447 + 0.0079747028207159554 + 0.0079765513916829761 + 0.0079783997788045926 + 0.0079802479823016925 + 0.0079820960023949117 + 0.0079839438393046053 + 0.0079857914932508767 + 0.0079876389644535414 + 0.0079894862531321616 + 0.0079913333595060046 + 0.007993180283794114 + 0.0079950270262152331 + 0.0079968735869878523 + 0.0079987199663302064 + 0.0080005661644602273 + 0.0080024121815956192 + 0.0080042580179538279 + 0.0080061036737519818 + 0.0080079491492070203 + 0.0080097944445355531 + 0.0080116395599539644 + 0.0080134844956783642 + 0.008015329251924613 + 0.0080171738289082951 + 0.0080190182268447281 + 0.0080208624459489966 + 0.008022706486435903 + 0.0080245503485200029 + 0.008026394032415585 + 0.0080282375383366675 + 0.0080300808664970271 + 0.0080319240171101893 + 0.0080337669903894123 + 0.0080356097865476924 + 0.0080374524057977587 + 0.0080392948483521288 + 0.0080411371144230165 + 0.0080429792042223999 + 0.0080448211179620054 + 0.0080466628558533045 + 0.0080485044181074928 + 0.0080503458049355509 + 0.0080521870165481853 + 0.0080540280531558352 + 0.0080558689149687144 + 0.0080577096021967748 + 0.0080595501150497011 + 0.0080613904537369576 + 0.0080632306184677278 + 0.0080650706094509694 + 0.008066910426895375 + 0.0080687500710093923 + 0.0080705895420012125 + 0.0080724288400787925 + 0.0080742679654498377 + 0.0080761069183217897 + 0.008077945698901863 + 0.0080797843073970223 + 0.0080816227440139617 + 0.0080834610089591617 + 0.0080852991024388428 + 0.008087137024658974 + 0.0080889747758252899 + 0.0080908123561432878 + 0.008092649765818187 + 0.0080944870050549903 + 0.0080963240740584697 + 0.0080981609730331212 + 0.0080999977021832051 + 0.0081018342617127752 + 0.0081036706518255956 + 0.0081055068727252134 + 0.008107342924614928 + 0.008109178807697813 + 0.0081110145221766766 + 0.0081128500682541155 + 0.0081146854461324556 + 0.0081165206560138078 + 0.0081183556981000316 + 0.0081201905725927729 + 0.0081220252796933897 + 0.0081238598196030631 + 0.0081256941925226898 + 0.0081275283986529407 + 0.0081293624381942719 + 0.0081311963113468791 + 0.0081330300183107291 + 0.0081348635592855649 + 0.0081366969344708832 + 0.0081385301440659412 + 0.0081403631882697829 + 0.0081421960672811901 + 0.0081440287812987351 + 0.00814586133052074 + 0.0081476937151453172 + 0.0081495259353703241 + 0.0081513579913933924 + 0.0081531898834119217 + 0.0081550216116230909 + 0.0081568531762238432 + 0.0081586845774108841 + 0.0081605158153806954 + 0.0081623468903295263 + 0.0081641778024534005 + 0.0081660085519481042 + 0.0081678391390092118 + 0.0081696695638320497 + 0.0081714998266117396 + 0.008173329927543143 + 0.0081751598668209375 + 0.0081769896446395318 + 0.0081788192611931317 + 0.0081806487166757175 + 0.0081824780112810368 + 0.0081843071452026035 + 0.0081861361186337314 + 0.0081879649317674885 + 0.0081897935847967274 + 0.0081916220779140736 + 0.0081934504113119356 + 0.0081952785851824878 + 0.0081971065997176878 + 0.0081989344551092747 + 0.0082007621515487617 + 0.008202589689227437 + 0.0082044170683363768 + 0.0082062442890664198 + 0.0082080713516082034 + 0.0082098982561521431 + 0.008211725002888413 + 0.0082135515920069933 + 0.0082153780236976226 + 0.0082172042981498421 + 0.0082190304155529605 + 0.0082208563760960748 + 0.0082226821799680581 + 0.008224507827357572 + 0.008226333318453051 + 0.0082281586534427333 + 0.0082299838325146212 + 0.0082318088558565074 + 0.0082336337236559726 + 0.0082354584361003687 + 0.0082372829933768463 + 0.0082391073956723411 + 0.008240931643173563 + 0.0082427557360670207 + 0.0082445796745390029 + 0.0082464034587755898 + 0.0082482270889626397 + 0.0082500505652857974 + 0.0082518738879304998 + 0.0082536970570819927 + 0.0082555200729252671 + 0.0082573429356451421 + 0.008259165645426194 + 0.0082609882024528136 + 0.0082628106069091746 + 0.0082646328589792203 + 0.0082664549588467237 + 0.0082682769066952152 + 0.0082700987027080203 + 0.0082719203470682703 + 0.0082737418399588814 + 0.0082755631815625546 + 0.0082773843720617916 + 0.0082792054116388875 + 0.0082810263004759171 + 0.0082828470387547714 + 0.0082846676266571037 + 0.0082864880643643991 + 0.0082883083520579031 + 0.0082901284899186741 + 0.0082919484781275588 + 0.0082937683168651955 + 0.0082955880063120373 + 0.008297407546648301 + 0.0082992269380540284 + 0.0083010461807090461 + 0.0083028652747929761 + 0.0083046842204852322 + 0.0083065030179650425 + 0.0083083216674114217 + 0.0083101401690031801 + 0.0083119585229189247 + 0.008313776729337077 + 0.0083155947884358365 + 0.0083174127003932119 + 0.0083192304653870244 + 0.0083210480835948664 + 0.0083228655551941498 + 0.0083246828803620835 + 0.0083265000592756908 + 0.0083283170921117627 + 0.0083301339790469147 + 0.0083319507202575544 + 0.0083337673159199158 + 0.0083355837662100005 + 0.0083374000713036349 + 0.0083392162313764406 + 0.0083410322466038397 + 0.0083428481171610672 + 0.0083446638432231549 + 0.0083464794249649352 + 0.0083482948625610599 + 0.0083501101561859747 + 0.0083519253060139048 + 0.0083537403122189522 + 0.0083555551749749379 + 0.0083573698944555633 + 0.0083591844708342765 + 0.0083609989042843745 + 0.008362813194978929 + 0.008364627343090859 + 0.0083664413487928475 + 0.0083682552122574007 + 0.0083700689336568476 + 0.0083718825131633198 + 0.0083736959509487265 + 0.0083755092471848366 + 0.0083773224020431952 + 0.0083791354156951652 + 0.0083809482883118961 + 0.0083827610200644023 + 0.0083845736111234654 + 0.00838638606165968 + 0.0083881983718434566 + 0.008390010541845027 + 0.0083918225718344324 + 0.0083936344619815022 + 0.0083954462124559079 + 0.0083972578234271303 + 0.008399069295064435 + 0.0084008806275369299 + 0.0084026918210135266 + 0.0084045028756629409 + 0.0084063137916537117 + 0.008408124569154192 + 0.0084099352083325547 + 0.008411745709356773 + 0.0084135560723946363 + 0.0084153662976137571 + 0.0084171763851815708 + 0.0084189863352653067 + 0.0084207961480320392 + 0.0084226058236486177 + 0.0084244153622817439 + 0.0084262247640979285 + 0.0084280340292634901 + 0.0084298431579445735 + 0.0084316521503071205 + 0.0084334610065169326 + 0.0084352697267395839 + 0.0084370783111405046 + 0.0084388867598849185 + 0.0084406950731378636 + 0.0084425032510642307 + 0.0084443112938286952 + 0.0084461192015957681 + 0.008447926974529783 + 0.008449734612794883 + 0.0084515421165550549 + 0.0084533494859740689 + 0.0084551567212155388 + 0.0084569638224429068 + 0.0084587707898194347 + 0.0084605776235081795 + 0.0084623843236720526 + 0.008464190890473778 + 0.0084659973240758871 + 0.0084678036246407587 + 0.0084696097923305843 + 0.0084714158273073697 + 0.0084732217297329594 + 0.0084750274997690139 + 0.0084768331375770136 + 0.0084786386433182721 + 0.0084804440171539312 + 0.008482249259244944 + 0.0084840543697520948 + 0.0084858593488360123 + 0.0084876641966571045 + 0.0084894689133756581 + 0.008491273499151757 + 0.0084930779541453234 + 0.0084948822785160787 + 0.0084966864724236226 + 0.0084984905360273276 + 0.0085002944694864396 + 0.008502098272959998 + 0.0085039019466068878 + 0.0085057054905858243 + 0.0085075089050553453 + 0.0085093121901738053 + 0.0085111153460994196 + 0.0085129183729902042 + 0.0085147212710040155 + 0.0085165240402985433 + 0.0085183266810312987 + 0.0085201291933596369 + 0.008521931577440715 + 0.0085237338334315706 + 0.0085255359614890211 + 0.0085273379617697449 + 0.0085291398344302469 + 0.0085309415796268519 + 0.0085327431975157301 + 0.0085345446882528851 + 0.0085363460519941436 + 0.0085381472888951763 + 0.0085399483991114682 + 0.0085417493827983637 + 0.0085435502401110235 + 0.0085453509712044382 + 0.0085471515762334544 + 0.0085489520553527348 + 0.0085507524087167705 + 0.0085525526364799119 + 0.0085543527387963204 + 0.0085561527158200118 + 0.0085579525677048247 + 0.008559752294604428 + 0.0085615518966723515 + 0.0085633513740619362 + 0.0085651507269263755 + 0.0085669499554186877 + 0.008568749059691733 + 0.0085705480398982192 + 0.0085723468961906718 + 0.0085741456287214777 + 0.0085759442376428293 + 0.0085777427231067908 + 0.0085795410852652441 + 0.0085813393242699185 + 0.0085831374402723769 + 0.008584935433424026 + 0.0085867333038761144 + 0.0085885310517797141 + 0.0085903286772857652 + 0.0085921261805450202 + 0.0085939235617080809 + 0.0085957208209254 + 0.0085975179583472547 + 0.0085993149741237784 + 0.0086011118684049381 + 0.0086029086413405339 + 0.0086047052930802222 + 0.0086065018237735016 + 0.0086082982335697038 + 0.0086100945226179927 + 0.0086118906910674052 + 0.0086136867390667927 + 0.008615482666764868 + 0.0086172784743101718 + 0.008619074161851115 + 0.0086208697295359071 + 0.0086226651775126451 + 0.0086244605059292555 + 0.0086262557149334937 + 0.0086280508046729723 + 0.0086298457752951654 + 0.0086316406269473633 + 0.0086334353597767206 + 0.0086352299739302259 + 0.0086370244695547216 + 0.0086388188467968925 + 0.0086406131058032725 + 0.0086424072467202375 + 0.0086442012696940108 + 0.0086459951748706632 + 0.0086477889623961194 + 0.0086495826324161414 + 0.0086513761850763402 + 0.0086531696205221845 + 0.0086549629388989798 + 0.008656756140351874 + 0.0086585492250258779 + 0.0086603421930658529 + 0.0086621350446164942 + 0.0086639277798223596 + 0.0086657203988278492 + 0.008667512901777202 + 0.0086693052888145335 + 0.0086710975600837927 + 0.0086728897157287658 + 0.0086746817558931207 + 0.0086764736807203504 + 0.0086782654903537985 + 0.0086800571849366733 + 0.008681848764612041 + 0.0086836402295227839 + 0.0086854315798116748 + 0.0086872228156213201 + 0.0086890139370941859 + 0.0086908049443725696 + 0.0086925958375986441 + 0.0086943866169144207 + 0.0086961772824617877 + 0.0086979678343824494 + 0.0086997582728179975 + 0.0087015485979098483 + 0.0087033388097992985 + 0.0087051289086274748 + 0.0087069188945353721 + 0.0087087087676638499 + 0.0087104985281535822 + 0.0087122881761451526 + 0.0087140777117789472 + 0.0087158671351952495 + 0.0087176564465341697 + 0.008719445645935681 + 0.0087212347335396279 + 0.0087230237094856923 + 0.00872481257391341 + 0.0087266013269621957 + 0.0087283899687712971 + 0.0087301784994798255 + 0.0087319669192267562 + 0.0087337552281509055 + 0.0087355434263909782 + 0.008737331514085506 + 0.0087391194913728817 + 0.0087409073583913782 + 0.0087426951152790987 + 0.0087444827621740249 + 0.0087462702992139804 + 0.008748057726536666 + 0.0087498450442796364 + 0.0087516322525802853 + 0.0087534193515759039 + 0.0087552063414035944 + 0.0087569932222003599 + 0.0087587799941030442 + 0.0087605666572483695 + 0.0087623532117728845 + 0.0087641396578130252 + 0.0087659259955050819 + 0.0087677122249852062 + 0.008769498346389409 + 0.0087712843598535574 + 0.0087730702655134038 + 0.0087748560635045238 + 0.0087766417539623751 + 0.0087784273370222956 + 0.0087802128128194393 + 0.0087819981814888891 + 0.008783783443165525 + 0.0087855685979841159 + 0.0087873536460793076 + 0.0087891385875855897 + 0.0087909234226373235 + 0.0087927081513687194 + 0.0087944927739138871 + 0.0087962772904067576 + 0.0087980617009811406 + 0.0087998460057707485 + 0.0088016302049090875 + 0.0088034142985295889 + 0.008805198286765516 + 0.0088069821697500193 + 0.008808765947616079 + 0.0088105496204965855 + 0.008812333188524259 + 0.0088141166518317122 + 0.0088159000105513981 + 0.008817683264815664 + 0.0088194664147566871 + 0.0088212494605065563 + 0.0088230324021971937 + 0.0088248152399603985 + 0.0088265979739278327 + 0.008828380604231037 + 0.0088301631310014044 + 0.0088319455543702085 + 0.0088337278744685839 + 0.0088355100914275352 + 0.0088372922053779387 + 0.0088390742164505213 + 0.0088408561247759147 + 0.008842637930484577 + 0.008844419633706857 + 0.0088462012345729823 + 0.0088479827332130397 + 0.0088497641297569738 + 0.0088515454243346114 + 0.0088533266170756492 + 0.0088551077081096396 + 0.0088568886975660382 + 0.0088586695855741339 + 0.0088604503722631098 + 0.0088622310577620017 + 0.0088640116421997393 + 0.0088657921257051069 + 0.0088675725084067583 + 0.008869352790433228 + 0.0088711329719129064 + 0.0088729130529740866 + 0.0088746930337449143 + 0.0088764729143533758 + 0.008878252694927407 + 0.0088800323755947284 + 0.0088818119564829951 + 0.00888359143771973 + 0.0088853708194322825 + 0.0088871501017479225 + 0.0088889292847937878 + 0.0088907083686968567 + 0.0088924873535840224 + 0.0088942662395820205 + 0.0088960450268174805 + 0.0088978237154169002 + 0.0088996023055066351 + 0.0089013807972129523 + 0.0089031591906619644 + 0.008904937485979654 + 0.0089067156832919134 + 0.0089084937827244633 + 0.0089102717844029393 + 0.0089120496884528347 + 0.008913827494999518 + 0.0089156052041682397 + 0.0089173828160841184 + 0.0089191603308721636 + 0.0089209377486572407 + 0.0089227150695641057 + 0.0089244922937173898 + 0.0089262694212416047 + 0.0089280464522611108 + 0.0089298233869001958 + 0.0089316002252829898 + 0.0089333769675334993 + 0.0089351536137756253 + 0.0089369301641331281 + 0.0089387066187296693 + 0.008940482977688775 + 0.0089422592411338344 + 0.0089440354091881447 + 0.0089458114819748781 + 0.0089475874596170544 + 0.0089493633422375995 + 0.0089511391299593266 + 0.0089529148229048963 + 0.0089546904211968859 + 0.0089564659249577131 + 0.0089582413343097106 + 0.0089600166493750653 + 0.0089617918702758672 + 0.0089635669971340603 + 0.0089653420300714881 + 0.0089671169692098797 + 0.0089688918146708235 + 0.0089706665665757971 + 0.0089724412250461807 + 0.0089742157902032004 + 0.0089759902621679866 + 0.0089777646410615485 + 0.0089795389270047668 + 0.0089813131201184199 + 0.0089830872205231352 + 0.0089848612283394795 + 0.00898663514368786 + 0.0089884089666885693 + 0.0089901826974617856 + 0.0089919563361275778 + 0.0089937298828058915 + 0.0089955033376165634 + 0.0089972767006792995 + 0.0089990499721136971 + 0.0090008231520392404 + 0.0090025962405752887 + 0.0090043692378410992 + 0.0090061421439558004 + 0.0090079149590384013 + 0.0090096876832078208 + 0.0090114603165828266 + 0.009013232859282079 + 0.0090150053114241707 + 0.0090167776731275122 + 0.0090185499445104289 + 0.0090203221256911388 + 0.0090220942167877401 + 0.0090238662179182062 + 0.009025638129200415 + 0.0090274099507521091 + 0.0090291816826909305 + 0.0090309533251344016 + 0.0090327248781999336 + 0.0090344963420048354 + 0.0090362677166662807 + 0.0090380390023013374 + 0.0090398101990269795 + 0.0090415813069600389 + 0.009043352326217247 + 0.0090451232569152291 + 0.0090468940991705014 + 0.0090486648530994449 + 0.0090504355188183363 + 0.0090522060964433691 + 0.0090539765860905841 + 0.0090557469878759407 + 0.0090575173019152647 + 0.0090592875283242863 + 0.0090610576672186111 + 0.009062827718713749 + 0.0090645976829250921 + 0.009066367559967918 + 0.0090681373499573829 + 0.0090699070530085631 + 0.0090716766692363945 + 0.0090734461987557243 + 0.009075215641681263 + 0.0090769849981276532 + 0.0090787542682093936 + 0.0090805234520408753 + 0.0090822925497363784 + 0.0090840615614101103 + 0.009085830487176122 + 0.0090875993271483761 + 0.0090893680814407209 + 0.009091136750166904 + 0.0090929053334405686 + 0.0090946738313752232 + 0.0090964422440842924 + 0.009098210571681092 + 0.0090999788142788057 + 0.0091017469719905375 + 0.0091035150449292803 + 0.0091052830332078987 + 0.0091070509369391602 + 0.0091088187562357349 + 0.0091105864912101719 + 0.009112354141974921 + 0.0091141217086423316 + 0.0091158891913246214 + 0.0091176565901339244 + 0.0091194239051822622 + 0.0091211911365815489 + 0.0091229582844435907 + 0.0091247253488800865 + 0.0091264923300026363 + 0.009128259227922722 + 0.0091300260427517321 + 0.009131792774600949 + 0.0091335594235815408 + 0.0091353259898045713 + 0.0091370924733810057 + 0.0091388588744216962 + 0.0091406251930373893 + 0.0091423914293387483 + 0.0091441575834363114 + 0.0091459236554405042 + 0.0091476896454616707 + 0.0091494555536100371 + 0.0091512213799957252 + 0.0091529871247287547 + 0.0091547527879190446 + 0.0091565183696764117 + 0.0091582838701105614 + 0.0091600492893310903 + 0.0091618146274475218 + 0.0091635798845692302 + 0.009165345060805536 + 0.0091671101562656107 + 0.00916887517105857 + 0.0091706401052933668 + 0.0091724049590789138 + 0.0091741697325239853 + 0.0091759344257372703 + 0.0091776990388273225 + 0.00917946357190263 + 0.0091812280250715885 + 0.0091829923984424345 + 0.0091847566921233643 + 0.0091865209062224323 + 0.0091882850408476161 + 0.0091900490961067845 + 0.0091918130721076914 + 0.0091935769689580043 + 0.0091953407867652881 + 0.0091971045256370072 + 0.0091988681856805185 + 0.009200631767003092 + 0.0092023952697118851 + 0.0092041586939139598 + 0.0092059220397162755 + 0.009207685307225686 + 0.0092094484965489568 + 0.0092112116077927696 + 0.0092129746410636523 + 0.0092147375964680752 + 0.0092165004741124271 + 0.0092182632741029443 + 0.0092200259965457936 + 0.0092217886415470515 + 0.0092235512092126871 + 0.0092253136996485602 + 0.0092270761129604403 + 0.009228838449253993 + 0.0092306007086347917 + 0.009232362891208332 + 0.009234124997079967 + 0.0092358870263549841 + 0.009237648979138563 + 0.0092394108555357846 + 0.0092411726556516291 + 0.0092429343795909953 + 0.0092446960274586709 + 0.0092464575993593378 + 0.0092482190953976119 + 0.0092499805156779687 + 0.0092517418603048334 + 0.0092535031293824819 + 0.0092552643230151537 + 0.0092570254413069462 + 0.0092587864843618733 + 0.0092605474522838675 + 0.00926230834517674 + 0.0092640691631442167 + 0.0092658299062899317 + 0.0092675905747174291 + 0.0092693511685301416 + 0.0092711116878314223 + 0.009272872132724503 + 0.0092746325033125493 + 0.0092763927996986177 + 0.0092781530219856762 + 0.0092799131702765835 + 0.0092816732446741271 + 0.0092834332452809681 + 0.0092851931721997221 + 0.0092869530255328455 + 0.0092887128053827442 + 0.0092904725118517252 + 0.0092922321450419985 + 0.0092939917050556698 + 0.0092957511919947722 + 0.0092975106059612154 + 0.0092992699470568277 + 0.0093010292153833662 + 0.0093027884110424754 + 0.0093045475341356973 + 0.0093063065847644837 + 0.00930806556303021 + 0.00930982446903416 + 0.0093115833028775009 + 0.0093133420646613237 + 0.0093151007544866188 + 0.0093168593724542899 + 0.0093186179186651522 + 0.0093203763932199254 + 0.00932213479621922 + 0.0093238931277635877 + 0.0093256513879534531 + 0.0093274095768891892 + 0.0093291676946710336 + 0.0093309257413991611 + 0.0093326837171736343 + 0.0093344416220944564 + 0.0093361994562615146 + 0.0093379572197746005 + 0.0093397149127334381 + 0.0093414725352376424 + 0.009343230087386729 + 0.0093449875692801655 + 0.009346744981017268 + 0.0093485023226973305 + 0.0093502595944194786 + 0.0093520167962828134 + 0.009353773928386315 + 0.0093555309908288919 + 0.0093572879837093264 + 0.0093590449071263553 + 0.009360801761178603 + 0.0093625585459646068 + 0.009364315261582809 + 0.0093660719081315909 + 0.0093678284857091811 + 0.0093695849944138033 + 0.0093713414343435317 + 0.0093730978055963574 + 0.0093748541082702037 + 0.0093766103424629092 + 0.0093783665082721977 + 0.0093801226057957203 + 0.0093818786351310361 + 0.0093836345963756312 + 0.0093853904896268638 + 0.0093871463149820377 + 0.0093889020725383774 + 0.0093906577623929996 + 0.0093924133846429083 + 0.0093941689393850815 + 0.0093959244267163757 + 0.0093976798467335417 + 0.0093994351995332695 + 0.0094011904852121537 + 0.0094029457038667195 + 0.0094047008555933672 + 0.0094064559404884347 + 0.0094082109586481853 + 0.009409965910168766 + 0.009411720795146265 + 0.0094134756136766608 + 0.0094152303658558596 + 0.0094169850517796666 + 0.0094187396715438333 + 0.0094204942252439864 + 0.009422248712975697 + 0.0094240031348344234 + 0.0094257574909155633 + 0.0094275117813144172 + 0.0094292660061261937 + 0.0094310201654460371 + 0.0094327742593689791 + 0.0094345282879899871 + 0.0094362822514039383 + 0.0094380361497056215 + 0.0094397899829897318 + 0.0094415437513508896 + 0.0094432974548836496 + 0.0094450510936824553 + 0.0094468046678416653 + 0.0094485581774555738 + 0.0094503116226183643 + 0.0094520650034241697 + 0.0094538183199670087 + 0.0094555715723408304 + 0.0094573247606395006 + 0.0094590778849567951 + 0.009460830945386401 + 0.0094625839420219449 + 0.0094643368749569474 + 0.0094660897442848616 + 0.0094678425500990381 + 0.0094695952924927634 + 0.0094713479715592252 + 0.0094731005873915485 + 0.009474853140082751 + 0.0094766056297257862 + 0.0094783580564135293 + 0.0094801104202387413 + 0.0094818627212941379 + 0.0094836149596723273 + 0.009485367135465864 + 0.009487119248767174 + 0.0094888712996686504 + 0.009490623288262565 + 0.009492375214641139 + 0.0094941270788964829 + 0.009495878881120667 + 0.00949763062140563 + 0.0094993822998432672 + 0.0095011339165253783 + 0.0095028854715436782 + 0.0095046369649897915 + 0.0095063883969553047 + 0.0095081397675316672 + 0.0095098910768102746 + 0.009511642324882455 + 0.0095133935118394426 + 0.0095151446377723849 + 0.0095168957027723551 + 0.0095186467069303341 + 0.0095203976503372579 + 0.0095221485330839444 + 0.0095238993552611371 + 0.0095256501169595238 + 0.0095274008182696882 + 0.009529151459282138 + 0.0095309020400873249 + 0.0095326525607755709 + 0.0095344030214371805 + 0.009536153422162328 + 0.0095379037630411393 + 0.0095396540441636396 + 0.0095414042656197968 + 0.0095431544274994871 + 0.009544904529892503 + 0.0095466545728885594 + 0.0095484045565773033 + 0.0095501544810483157 + 0.0095519043463910443 + 0.0095536541526949192 + 0.0095554039000492579 + 0.0095571535885433257 + 0.009558903218266265 + 0.0095606527893071849 + 0.0095624023017550994 + 0.0095641517556989443 + 0.0095659011512275877 + 0.0095676504884298023 + 0.0095693997673942759 + 0.009571148988209658 + 0.0095728981509644925 + 0.0095746472557472415 + 0.0095763963026463117 + 0.009578145291750011 + 0.0095798942231465831 + 0.0095816430969241865 + 0.0095833919131709019 + 0.0095851406719747526 + 0.0095868893734236786 + 0.0095886380176055004 + 0.0095903866046080331 + 0.0095921351345189601 + 0.0095938836074259144 + 0.0095956320234164474 + 0.0095973803825780291 + 0.0095991286849980671 + 0.0096008769307638648 + 0.0096026251199626978 + 0.0096043732526816996 + 0.0096061213290080001 + 0.0096078693490285888 + 0.0096096173128304326 + 0.0096113652205004028 + 0.0096131130721252601 + 0.0096148608677917528 + 0.0096166086075865111 + 0.0096183562915961012 + 0.0096201039199070235 + 0.0096218514926056896 + 0.0096235990097784403 + 0.009625346471511545 + 0.0096270938778912005 + 0.009628841229003527 + 0.0096305885249345653 + 0.0096323357657702759 + 0.0096340829515965693 + 0.0096358300824992693 + 0.0096375771585641024 + 0.009639324179876764 + 0.0096410711465228296 + 0.0096428180585878473 + 0.0096445649161572607 + 0.0096463117193164531 + 0.0096480584681507206 + 0.0096498051627452921 + 0.009651551803185332 + 0.0096532983895559147 + 0.0096550449219420659 + 0.0096567914004287141 + 0.0096585378251007239 + 0.0096602841960428971 + 0.0096620305133399403 + 0.0096637767770764871 + 0.0096655229873371436 + 0.0096672691442063856 + 0.0096690152477686454 + 0.0096707612981082915 + 0.0096725072953095913 + 0.0096742532394567468 + 0.0096759991306339214 + 0.0096777449689251782 + 0.0096794907544144916 + 0.0096812364871857945 + 0.0096829821673229434 + 0.0096847277949097064 + 0.0096864733700298012 + 0.0096882188927668571 + 0.0096899643632044306 + 0.0096917097814260243 + 0.0096934551475150559 + 0.0096952004615548735 + 0.0096969457236287544 + 0.0096986909338199079 + 0.0097004360922114587 + 0.0097021811988864896 + 0.0097039262539279879 + 0.0097056712574188717 + 0.0097074162094420036 + 0.009709161110080149 + 0.0097109059594160298 + 0.0097126507575323005 + 0.009714395504511501 + 0.0097161402004361519 + 0.0097178848453886666 + 0.0097196294394514271 + 0.0097213739827067096 + 0.0097231184752367261 + 0.0097248629171236452 + 0.0097266073084495263 + 0.0097283516492963993 + 0.0097300959397461882 + 0.0097318401798807651 + 0.0097335843697819464 + 0.0097353285095314393 + 0.0097370725992109199 + 0.0097388166389019929 + 0.009740560628686161 + 0.0097423045686448849 + 0.0097440484588595545 + 0.0097457922994114866 + 0.0097475360903819218 + 0.0097492798318520469 + 0.009751023523902962 + 0.0097527671666157254 + 0.0097545107600712899 + 0.009756254304350568 + 0.0097579977995344066 + 0.0097597412457035536 + 0.0097614846429387274 + 0.0097632279913205389 + 0.0097649712909295729 + 0.0097667145418463153 + 0.0097684577441511846 + 0.0097702008979245521 + 0.0097719440032466975 + 0.009773687060197862 + 0.0097754300688581829 + 0.0097771730293077629 + 0.0097789159416266074 + 0.0097806588058946941 + 0.0097824016221918862 + 0.0097841443905980086 + 0.0097858871111928189 + 0.009787629784055998 + 0.0097893724092671715 + 0.0097911149869058748 + 0.0097928575170516032 + 0.0097945999997837742 + 0.0097963424351817322 + 0.0097980848233247594 + 0.0097998271642920805 + 0.0098015694581628406 + 0.0098033117050161378 + 0.0098050539049309732 + 0.0098067960579862976 + 0.0098085381642610044 + 0.009810280223833916 + 0.0098120222367837785 + 0.0098137642031892822 + 0.0098155061231290572 + 0.0098172479966816429 + 0.0098189898239255287 + 0.0098207316049391553 + 0.0098224733398008697 + 0.0098242150285889722 + 0.0098259566713816866 + 0.0098276982682571866 + 0.0098294398192935364 + 0.009831181324568802 + 0.0098329227841609402 + 0.0098346641981478435 + 0.0098364055666073577 + 0.0098381468896172625 + 0.0098398881672552441 + 0.0098416293995989505 + 0.0098433705867259792 + 0.0098451117287138221 + 0.0098468528256399294 + 0.0098485938775816767 + 0.0098503348846164067 + 0.0098520758468213718 + 0.009853816764273729 + 0.0098555576370506544 + 0.0098572984652291716 + 0.0098590392488862953 + 0.0098607799880989586 + 0.0098625206829440256 + 0.0098642613334983201 + 0.0098660019398385639 + 0.0098677425020414471 + 0.0098694830201835858 + 0.0098712234943415158 + 0.0098729639245917575 + 0.0098747043110107048 + 0.0098764446536747392 + 0.0098781849526601451 + 0.0098799252080431776 + 0.0098816654198999807 + 0.0098834055883066912 + 0.0098851457133393422 + 0.0098868857950739162 + 0.0098886258335863335 + 0.0098903658289524621 + 0.0098921057812480818 + 0.0098938456905489358 + 0.0098955855569306823 + 0.00989732538046895 + 0.0098990651612392531 + 0.0099008048993171095 + 0.0099025445947779067 + 0.0099042842476970254 + 0.0099060238581497474 + 0.0099077634262113214 + 0.0099095029519569063 + 0.0099112424354616188 + 0.0099129818768005033 + 0.0099147212760485395 + 0.009916460633280659 + 0.0099181999485717341 + 0.0099199392219965609 + 0.0099216784536298626 + 0.0099234176435463381 + 0.0099251567918205927 + 0.009926895898527183 + 0.0099286349637406277 + 0.0099303739875353219 + 0.0099321129699856524 + 0.0099338519111659383 + 0.009935590811150424 + 0.0099373296700132913 + 0.0099390684878286808 + 0.0099408072646706529 + 0.0099425460006132178 + 0.0099442846957303235 + 0.0099460233500958482 + 0.0099477619637836252 + 0.0099495005368674221 + 0.009951239069420921 + 0.0099529775615177906 + 0.0099547160132316126 + 0.0099564544246358942 + 0.0099581927958041112 + 0.0099599311268096652 + 0.0099616694177259053 + 0.0099634076686261012 + 0.0099651458795834945 + 0.0099668840506712368 + 0.0099686221819624329 + 0.0099703602735301197 + 0.009972098325447298 + 0.0099738363377869007 + 0.0099755743106217827 + 0.0099773122440247348 + 0.0099790501380685181 + 0.0099807879928258316 + 0.0099825258083692959 + 0.0099842635847714831 + 0.0099860013221048892 + 0.009987739020441996 + 0.0099894766798551676 + 0.009991214300416747 + 0.0099929518821990256 + 0.0099946894252741936 + 0.0099964269297144262 + 0.0099981643955918183 + 0.0099999018229784149 + 0.010001639211946189 + 0.010003376562567076 + 0.010005113874912944 + 0.010006851149055576 + 0.010008588385066748 + 0.010010325583018146 + 0.010012062742981396 + 0.010013799865028072 + 0.010015536949229692 + 0.010017273995657733 + 0.010019011004383564 + 0.010020747975478547 + 0.01002248490901397 + 0.010024221805061059 + 0.010025958663690984 + 0.010027695484974869 + 0.010029432268983748 + 0.010031169015788616 + 0.010032905725460447 + 0.010034642398070098 + 0.010036379033688409 + 0.010038115632386138 + 0.010039852194234013 + 0.01004158871930266 + 0.010043325207662712 + 0.010045061659384694 + 0.010046798074539091 + 0.010048534453196327 + 0.01005027079542678 + 0.010052007101300766 + 0.010053743370888541 + 0.010055479604260311 + 0.010057215801486205 + 0.010058951962636321 + 0.010060688087780701 + 0.010062424176989314 + 0.010064160230332068 + 0.010065896247878845 + 0.010067632229699437 + 0.010069368175863614 + 0.01007110408644105 + 0.010072839961501403 + 0.010074575801114247 + 0.01007631160534911 + 0.010078047374275468 + 0.010079783107962738 + 0.010081518806480288 + 0.010083254469897397 + 0.01008499009828335 + 0.010086725691707319 + 0.01008846125023845 + 0.01009019677394583 + 0.010091932262898479 + 0.010093667717165378 + 0.01009540313681544 + 0.010097138521917541 + 0.010098873872540465 + 0.010100609188752992 + 0.010102344470623812 + 0.010104079718221555 + 0.010105814931614826 + 0.010107550110872164 + 0.010109285256062028 + 0.01011102036725286 + 0.010112755444513019 + 0.010114490487910821 + 0.010116225497514546 + 0.010117960473392385 + 0.01011969541561249 + 0.010121430324242968 + 0.010123165199351856 + 0.010124900041007152 + 0.010126634849276782 + 0.010128369624228637 + 0.010130104365930544 + 0.010131839074450276 + 0.010133573749855563 + 0.010135308392214057 + 0.01013704300159338 + 0.010138777578061085 + 0.010140512121684682 + 0.010142246632531627 + 0.010143981110669303 + 0.010145715556165086 + 0.010147449969086243 + 0.010149184349500021 + 0.01015091869747361 + 0.010152653013074126 + 0.01015438729636866 + 0.010156121547424244 + 0.010157855766307844 + 0.010159589953086374 + 0.010161324107826714 + 0.010163058230595674 + 0.010164792321460007 + 0.010166526380486434 + 0.010168260407741601 + 0.010169994403292117 + 0.010171728367204536 + 0.010173462299545348 + 0.010175196200381006 + 0.010176930069777901 + 0.010178663907802374 + 0.010180397714520716 + 0.010182131489999167 + 0.010183865234303894 + 0.01018559894750104 + 0.010187332629656697 + 0.010189066280836883 + 0.010190799901107569 + 0.010192533490534691 + 0.01019426704918411 + 0.010196000577121653 + 0.01019773407441308 + 0.010199467541124121 + 0.010201200977320435 + 0.010202934383067646 + 0.010204667758431308 + 0.01020640110347692 + 0.010208134418269964 + 0.010209867702875831 + 0.010211600957359892 + 0.010213334181787449 + 0.010215067376223743 + 0.010216800540733997 + 0.010218533675383347 + 0.010220266780236903 + 0.010221999855359711 + 0.010223732900816785 + 0.010225465916673037 + 0.010227198902993409 + 0.010228931859842723 + 0.010230664787285784 + 0.010232397685387324 + 0.010234130554212059 + 0.010235863393824618 + 0.010237596204289602 + 0.01023932898567155 + 0.010241061738034936 + 0.010242794461444254 + 0.010244527155963842 + 0.010246259821658077 + 0.010247992458591241 + 0.010249725066827566 + 0.010251457646431249 + 0.010253190197466447 + 0.010254922719997232 + 0.01025665521408765 + 0.0102583876798017 + 0.01026012011720333 + 0.010261852526356422 + 0.010263584907324805 + 0.010265317260172284 + 0.010267049584962619 + 0.010268781881759495 + 0.010270514150626539 + 0.010272246391627361 + 0.010273978604825512 + 0.010275710790284467 + 0.010277442948067698 + 0.010279175078238584 + 0.010280907180860487 + 0.010282639255996697 + 0.010284371303710462 + 0.010286103324065 + 0.010287835317123444 + 0.01028956728294891 + 0.010291299221604442 + 0.010293031133153045 + 0.010294763017657691 + 0.010296494875181276 + 0.010298226705786661 + 0.010299958509536664 + 0.010301690286494041 + 0.010303422036721499 + 0.01030515376028171 + 0.010306885457237305 + 0.010308617127650825 + 0.010310348771584812 + 0.010312080389101735 + 0.010313811980264006 + 0.010315543545134004 + 0.01031727508377406 + 0.010319006596246448 + 0.01032073808261341 + 0.010322469542937127 + 0.010324200977279719 + 0.010325932385703295 + 0.010327663768269879 + 0.010329395125041472 + 0.010331126456080014 + 0.010332857761447396 + 0.010334589041205471 + 0.010336320295416054 + 0.010338051524140883 + 0.010339782727441659 + 0.010341513905380061 + 0.010343245058017685 + 0.010344976185416103 + 0.010346707287636826 + 0.010348438364741324 + 0.010350169416791028 + 0.010351900443847303 + 0.010353631445971489 + 0.010355362423224842 + 0.010357093375668633 + 0.010358824303364017 + 0.010360555206372144 + 0.010362286084754127 + 0.010364016938570982 + 0.010365747767883729 + 0.010367478572753322 + 0.010369209353240655 + 0.010370940109406599 + 0.010372670841311956 + 0.010374401549017503 + 0.010376132232583969 + 0.010377862892072006 + 0.010379593527542251 + 0.010381324139055296 + 0.010383054726671666 + 0.010384785290451844 + 0.010386515830456286 + 0.010388246346745391 + 0.010389976839379488 + 0.010391707308418903 + 0.010393437753923887 + 0.01039516817595466 + 0.010396898574571366 + 0.010398628949834154 + 0.010400359301803079 + 0.010402089630538179 + 0.010403819936099444 + 0.0104055502185468 + 0.010407280477940135 + 0.010409010714339318 + 0.010410740927804139 + 0.010412471118394349 + 0.010414201286169669 + 0.010415931431189749 + 0.010417661553514215 + 0.010419391653202648 + 0.010421121730314575 + 0.010422851784909488 + 0.010424581817046804 + 0.010426311826785935 + 0.010428041814186228 + 0.010429771779306969 + 0.010431501722207439 + 0.010433231642946848 + 0.01043496154158435 + 0.0104366914181791 + 0.010438421272790138 + 0.01044015110547653 + 0.010441880916297247 + 0.01044361070531126 + 0.01044534047257744 + 0.010447070218154667 + 0.010448799942101728 + 0.010450529644477412 + 0.010452259325340437 + 0.010453988984749467 + 0.010455718622763156 + 0.010457448239440085 + 0.010459177834838816 + 0.01046090740901782 + 0.010462636962035574 + 0.010464366493950487 + 0.010466096004820929 + 0.01046782549470523 + 0.010469554963661672 + 0.010471284411748471 + 0.010473013839023852 + 0.010474743245545953 + 0.010476472631372863 + 0.010478201996562663 + 0.010479931341173376 + 0.01048166066526296 + 0.010483389968889366 + 0.010485119252110457 + 0.010486848514984099 + 0.01048857775756808 + 0.010490306979920158 + 0.010492036182098064 + 0.010493765364159441 + 0.010495494526161945 + 0.010497223668163127 + 0.01049895279022057 + 0.01050068189239173 + 0.010502410974734087 + 0.010504140037305052 + 0.010505869080161987 + 0.010507598103362206 + 0.010509327106963021 + 0.010511056091021646 + 0.010512785055595277 + 0.010514514000741083 + 0.010516242926516175 + 0.010517971832977608 + 0.010519700720182424 + 0.010521429588187593 + 0.010523158437050061 + 0.010524887266826721 + 0.010526616077574439 + 0.010528344869350019 + 0.010530073642210234 + 0.010531802396211811 + 0.010533531131411441 + 0.010535259847865757 + 0.010536988545631377 + 0.010538717224764847 + 0.010540445885322686 + 0.010542174527361369 + 0.010543903150937331 + 0.010545631756106962 + 0.010547360342926606 + 0.010549088911452575 + 0.01055081746174113 + 0.010552545993848503 + 0.010554274507830858 + 0.010556003003744359 + 0.010557731481645074 + 0.010559459941589073 + 0.010561188383632382 + 0.010562916807830952 + 0.010564645214240723 + 0.010566373602917596 + 0.010568101973917398 + 0.010569830327295944 + 0.010571558663109 + 0.010573286981412295 + 0.010575015282261497 + 0.010576743565712261 + 0.010578471831820186 + 0.010580200080640815 + 0.010581928312229675 + 0.01058365652664226 + 0.010585384723933966 + 0.01058711290416022 + 0.010588841067376361 + 0.010590569213637708 + 0.010592297342999523 + 0.010594025455517032 + 0.010595753551245446 + 0.010597481630239892 + 0.010599209692555487 + 0.010600937738247296 + 0.010602665767370355 + 0.010604393779979644 + 0.010606121776130083 + 0.010607849755876609 + 0.01060957771927408 + 0.010611305666377312 + 0.010613033597241093 + 0.010614761511920149 + 0.010616489410469212 + 0.010618217292942924 + 0.010619945159395914 + 0.010621673009882759 + 0.010623400844457996 + 0.010625128663176138 + 0.010626856466091638 + 0.010628584253258924 + 0.010630312024732361 + 0.010632039780566304 + 0.010633767520815043 + 0.010635495245532856 + 0.01063722295477394 + 0.010638950648592506 + 0.010640678327042668 + 0.010642405990178547 + 0.010644133638054184 + 0.010645861270723617 + 0.010647588888240821 + 0.01064931649065976 + 0.010651044078034301 + 0.010652771650418323 + 0.01065449920786567 + 0.0106562267504301 + 0.010657954278165366 + 0.010659681791125194 + 0.010661409289363223 + 0.010663136772933086 + 0.010664864241888375 + 0.010666591696282647 + 0.010668319136169394 + 0.010670046561602106 + 0.010671773972634207 + 0.010673501369319077 + 0.010675228751710081 + 0.010676956119860541 + 0.010678683473823712 + 0.010680410813652841 + 0.010682138139401135 + 0.010683865451121745 + 0.010685592748867783 + 0.010687320032692326 + 0.01068904730264845 + 0.010690774558789123 + 0.010692501801167315 + 0.010694229029835974 + 0.010695956244847963 + 0.010697683446256155 + 0.010699410634113338 + 0.010701137808472296 + 0.010702864969385769 + 0.010704592116906437 + 0.010706319251086959 + 0.010708046371979975 + 0.010709773479638033 + 0.0107115005741137 + 0.010713227655459475 + 0.010714954723727813 + 0.010716681778971166 + 0.010718408821241898 + 0.010720135850592364 + 0.010721862867074898 + 0.010723589870741757 + 0.010725316861645179 + 0.010727043839837381 + 0.010728770805370503 + 0.010730497758296672 + 0.01073222469866799 + 0.010733951626536509 + 0.010735678541954204 + 0.01073740544497309 + 0.010739132335645071 + 0.010740859214022076 + 0.010742586080155931 + 0.010744312934098476 + 0.010746039775901498 + 0.010747766605616743 + 0.010749493423295927 + 0.010751220228990711 + 0.010752947022752731 + 0.010754673804633607 + 0.010756400574684875 + 0.010758127332958061 + 0.010759854079504668 + 0.010761580814376136 + 0.010763307537623864 + 0.010765034249299248 + 0.01076676094945362 + 0.010768487638138268 + 0.010770214315404484 + 0.010771940981303473 + 0.010773667635886428 + 0.010775394279204499 + 0.010777120911308813 + 0.010778847532250457 + 0.010780574142080446 + 0.01078230074084981 + 0.010784027328609497 + 0.010785753905410469 + 0.010787480471303589 + 0.010789207026339748 + 0.010790933570569752 + 0.01079266010404438 + 0.010794386626814392 + 0.010796113138930511 + 0.010797839640443407 + 0.010799566131403704 + 0.010801292611862016 + 0.010803019081868927 + 0.010804745541474944 + 0.010806471990730582 + 0.010808198429686286 + 0.010809924858392484 + 0.010811651276899576 + 0.010813377685257893 + 0.010815104083517746 + 0.01081683047172944 + 0.01081855684994319 + 0.010820283218209222 + 0.010822009576577699 + 0.01082373592509875 + 0.01082546226382248 + 0.01082718859279895 + 0.010828914912078184 + 0.010830641221710192 + 0.010832367521744915 + 0.01083409381223226 + 0.010835820093222117 + 0.010837546364764359 + 0.010839272626908781 + 0.010840998879705155 + 0.010842725123203225 + 0.010844451357452713 + 0.01084617758250327 + 0.010847903798404543 + 0.010849630005206133 + 0.010851356202957596 + 0.010853082391708471 + 0.010854808571508235 + 0.010856534742406382 + 0.010858260904452294 + 0.010859987057695385 + 0.010861713202184984 + 0.010863439337970451 + 0.010865165465101027 + 0.010866891583626 + 0.010868617693594537 + 0.010870343795055861 + 0.010872069888059083 + 0.010873795972653307 + 0.010875522048887643 + 0.010877248116811096 + 0.01087897417647268 + 0.010880700227921362 + 0.010882426271206089 + 0.010884152306375742 + 0.010885878333479194 + 0.010887604352565278 + 0.010889330363682777 + 0.010891056366880463 + 0.010892782362207058 + 0.01089450834971125 + 0.010896234329441708 + 0.010897960301447048 + 0.010899686265775841 + 0.010901412222476668 + 0.010903138171598039 + 0.010904864113188435 + 0.010906590047296298 + 0.010908315973970064 + 0.010910041893258096 + 0.010911767805208769 + 0.010913493709870362 + 0.01091521960729119 + 0.010916945497519455 + 0.010918671380603416 + 0.010920397256591219 + 0.010922123125531022 + 0.010923848987470916 + 0.010925574842459011 + 0.010927300690543311 + 0.010929026531771847 + 0.010930752366192578 + 0.010932478193853451 + 0.010934204014802383 + 0.01093592982908723 + 0.010937655636755835 + 0.010939381437856017 + 0.010941107232435522 + 0.010942833020542095 + 0.010944558802223461 + 0.010946284577527264 + 0.010948010346501167 + 0.010949736109192754 + 0.010951461865649582 + 0.010953187615919223 + 0.010954913360049161 + 0.01095663909808686 + 0.01095836483007977 + 0.010960090556075292 + 0.01096181627612078 + 0.010963541990263583 + 0.010965267698551015 + 0.010966993401030335 + 0.010968719097748771 + 0.010970444788753539 + 0.0109721704740918 + 0.010973896153810713 + 0.010975621827957343 + 0.010977347496578803 + 0.01097907315972212 + 0.010980798817434285 + 0.010982524469762282 + 0.010984250116753053 + 0.010985975758453493 + 0.010987701394910492 + 0.010989427026170884 + 0.010991152652281486 + 0.01099287827328905 + 0.010994603889240347 + 0.01099632950018207 + 0.010998055106160897 + 0.010999780707223485 + 0.011001506303416444 + 0.011003231894786351 + 0.011004957481379741 + 0.011006683063243154 + 0.011008408640423066 + 0.011010134212965912 + 0.011011859780918112 + 0.011013585344326081 + 0.011015310903236132 + 0.011017036457694607 + 0.011018762007747797 + 0.011020487553441963 + 0.0110222130948233 + 0.011023938631938028 + 0.011025664164832307 + 0.011027389693552254 + 0.01102911521814396 + 0.0110308407386535 + 0.011032566255126899 + 0.011034291767610156 + 0.011036017276149236 + 0.011037742780790089 + 0.011039468281578611 + 0.01104119377856067 + 0.011042919271782106 + 0.011044644761288724 + 0.011046370247126312 + 0.011048095729340606 + 0.011049821207977321 + 0.011051546683082142 + 0.011053272154700705 + 0.011054997622878638 + 0.011056723087661525 + 0.011058448549094924 + 0.011060174007224368 + 0.011061899462095315 + 0.011063624913753253 + 0.011065350362243594 + 0.011067075807611758 + 0.011068801249903089 + 0.011070526689162932 + 0.011072252125436581 + 0.011073977558769316 + 0.011075702989206375 + 0.011077428416792968 + 0.011079153841574263 + 0.011080879263595415 + 0.011082604682901537 + 0.011084330099537716 + 0.011086055513549008 + 0.011087780924980414 + 0.011089506333876951 + 0.011091231740283572 + 0.011092957144245189 + 0.011094682545806714 + 0.011096407945013018 + 0.011098133341908937 + 0.011099858736539256 + 0.011101584128948757 + 0.01110330951918221 + 0.011105034907284293 + 0.011106760293299696 + 0.011108485677273079 + 0.011110211059249068 + 0.01111193643927222 + 0.011113661817387125 + 0.011115387193638306 + 0.011117112568070249 + 0.011118837940727428 + 0.01112056331165428 + 0.011122288680895192 + 0.011124014048494576 + 0.011125739414496761 + 0.011127464778946041 + 0.011129190141886718 + 0.011130915503363049 + 0.011132640863419252 + 0.011134366222099514 + 0.011136091579448001 + 0.011137816935508849 + 0.011139542290326144 + 0.011141267643943992 + 0.011142992996406394 + 0.01114471834775739 + 0.011146443698040954 + 0.01114816904730102 + 0.011149894395581526 + 0.011151619742926366 + 0.011153345089379388 + 0.01115507043498443 + 0.011156795779785294 + 0.011158521123825749 + 0.011160246467149526 + 0.01116197180980035 + 0.011163697151821892 + 0.011165422493257821 + 0.011167147834151733 + 0.011168873174547235 + 0.011170598514487883 + 0.011172323854017216 + 0.011174049193178725 + 0.011175774532015894 + 0.011177499870572151 + 0.011179225208890923 + 0.011180950547015589 + 0.011182675884989515 + 0.011184401222856013 + 0.011186126560658373 + 0.011187851898439865 + 0.011189577236243725 + 0.011191302574113172 + 0.011193027912091367 + 0.011194753250221465 + 0.011196478588546586 + 0.011198203927109808 + 0.011199929265954202 + 0.011201654605122794 + 0.011203379944658596 + 0.011205105284604564 + 0.011206830625003647 + 0.011208555965898754 + 0.011210281307332773 + 0.011212006649348575 + 0.011213731991988963 + 0.011215457335296743 + 0.01121718267931468 + 0.01121890802408552 + 0.011220633369651968 + 0.0112223587160567 + 0.011224084063342384 + 0.011225809411551633 + 0.011227534760727034 + 0.011229260110911165 + 0.011230985462146553 + 0.011232710814475711 + 0.011234436167941125 + 0.011236161522585228 + 0.011237886878450449 + 0.011239612235579188 + 0.011241337594013809 + 0.011243062953796634 + 0.011244788314969979 + 0.011246513677576116 + 0.011248239041657311 + 0.011249964407255755 + 0.011251689774413674 + 0.011253415143173214 + 0.011255140513576511 + 0.011256865885665671 + 0.011258591259482788 + 0.011260316635069892 + 0.011262042012469015 + 0.011263767391722145 + 0.011265492772871241 + 0.011267218155958261 + 0.0112689435410251 + 0.011270668928113636 + 0.011272394317265726 + 0.011274119708523191 + 0.011275845101927836 + 0.01127757049752141 + 0.011279295895345669 + 0.011281021295442319 + 0.011282746697853042 + 0.011284472102619493 + 0.011286197509783297 + 0.011287922919386052 + 0.011289648331469332 + 0.011291373746074694 + 0.011293099163243626 + 0.01129482458301764 + 0.011296550005438178 + 0.011298275430546673 + 0.011300000858384542 + 0.011301726288993152 + 0.01130345172241386 + 0.011305177158687962 + 0.011306902597856766 + 0.011308628039961554 + 0.011310353485043542 + 0.011312078933143935 + 0.011313804384303943 + 0.011315529838564696 + 0.011317255295967318 + 0.011318980756552922 + 0.011320706220362577 + 0.011322431687437316 + 0.01132415715781818 + 0.011325882631546127 + 0.011327608108662139 + 0.011329333589207157 + 0.011331059073222067 + 0.011332784560747759 + 0.011334510051825088 + 0.011336235546494874 + 0.011337961044797928 + 0.011339686546774986 + 0.011341412052466833 + 0.011343137561914168 + 0.011344863075157672 + 0.011346588592238006 + 0.011348314113195817 + 0.011350039638071704 + 0.011351765166906259 + 0.011353490699740008 + 0.011355216236613506 + 0.011356941777567237 + 0.011358667322641684 + 0.011360392871877276 + 0.011362118425314443 + 0.011363843982993565 + 0.011365569544955025 + 0.011367295111239148 + 0.011369020681886244 + 0.011370746256936603 + 0.01137247183643047 + 0.011374197420408091 + 0.011375923008909656 + 0.01137764860197534 + 0.01137937419964531 + 0.011381099801959673 + 0.011382825408958533 + 0.011384551020681951 + 0.011386276637169981 + 0.011388002258462636 + 0.011389727884599906 + 0.011391453515621755 + 0.011393179151568117 + 0.011394904792478892 + 0.011396630438393984 + 0.011398356089353254 + 0.011400081745396508 + 0.011401807406563571 + 0.01140353307289421 + 0.011405258744428182 + 0.011406984421205215 + 0.011408710103264995 + 0.011410435790647211 + 0.011412161483391491 + 0.011413887181537481 + 0.011415612885124755 + 0.011417338594192894 + 0.011419064308781418 + 0.011420790028929864 + 0.011422515754677707 + 0.011424241486064435 + 0.011425967223129453 + 0.01142769296591219 + 0.011429418714452032 + 0.01143114446878833 + 0.011432870228960407 + 0.011434595995007612 + 0.011436321766969173 + 0.011438047544884382 + 0.01143977332879245 + 0.011441499118732585 + 0.011443224914743973 + 0.011444950716865746 + 0.011446676525137051 + 0.011448402339596974 + 0.011450128160284592 + 0.011451853987238957 + 0.011453579820499092 + 0.011455305660103976 + 0.011457031506092622 + 0.011458757358503935 + 0.011460483217376848 + 0.011462209082750254 + 0.011463934954663028 + 0.011465660833154014 + 0.01146738671826201 + 0.011469112610025834 + 0.011470838508484231 + 0.011472564413675968 + 0.011474290325639742 + 0.011476016244414239 + 0.011477742170038129 + 0.011479468102550048 + 0.011481194041988626 + 0.011482919988392428 + 0.011484645941800041 + 0.011486371902249985 + 0.011488097869780774 + 0.011489823844430919 + 0.011491549826238838 + 0.011493275815243011 + 0.011495001811481822 + 0.01149672781499367 + 0.011498453825816915 + 0.011500179843989876 + 0.011501905869550902 + 0.011503631902538241 + 0.011505357942990178 + 0.011507083990944935 + 0.011508810046440712 + 0.011510536109515725 + 0.011512262180208128 + 0.011513988258556034 + 0.011515714344597571 + 0.011517440438370814 + 0.011519166539913851 + 0.011520892649264687 + 0.011522618766461349 + 0.011524344891541815 + 0.011526071024544051 + 0.011527797165506006 + 0.011529523314465558 + 0.011531249471460633 + 0.011532975636529077 + 0.011534701809708722 + 0.011536427991037383 + 0.011538154180552856 + 0.011539880378292899 + 0.011541606584295259 + 0.011543332798597634 + 0.011545059021237725 + 0.011546785252253212 + 0.011548511491681705 + 0.011550237739560848 + 0.011551963995928203 + 0.011553690260821372 + 0.011555416534277867 + 0.011557142816335226 + 0.011558869107030943 + 0.011560595406402471 + 0.011562321714487281 + 0.011564048031322766 + 0.011565774356946338 + 0.011567500691395371 + 0.011569227034707199 + 0.011570953386919164 + 0.01157267974806855 + 0.011574406118192646 + 0.011576132497328686 + 0.011577858885513921 + 0.011579585282785533 + 0.011581311689180696 + 0.01158303810473659 + 0.011584764529490321 + 0.011586490963478996 + 0.011588217406739728 + 0.011589943859309533 + 0.011591670321225479 + 0.01159339679252455 + 0.011595123273243741 + 0.011596849763420028 + 0.011598576263090325 + 0.011600302772291564 + 0.011602029291060634 + 0.011603755819434385 + 0.01160548235744968 + 0.011607208905143326 + 0.011608935462552126 + 0.011610662029712848 + 0.011612388606662232 + 0.011614115193436993 + 0.011615841790073864 + 0.011617568396609499 + 0.011619295013080551 + 0.011621021639523638 + 0.011622748275975408 + 0.011624474922472374 + 0.011626201579051157 + 0.011627928245748259 + 0.011629654922600201 + 0.011631381609643457 + 0.011633108306914513 + 0.011634835014449771 + 0.011636561732285684 + 0.011638288460458633 + 0.011640015199004998 + 0.011641741947961104 + 0.011643468707363281 + 0.011645195477247841 + 0.011646922257651033 + 0.011648649048609136 + 0.011650375850158375 + 0.011652102662334941 + 0.01165382948517503 + 0.011655556318714783 + 0.011657283162990365 + 0.011659010018037874 + 0.011660736883893384 + 0.011662463760592982 + 0.011664190648172704 + 0.011665917546668571 + 0.011667644456116582 + 0.011669371376552705 + 0.011671098308012882 + 0.011672825250533068 + 0.011674552204149142 + 0.011676279168897 + 0.011678006144812486 + 0.011679733131931457 + 0.011681460130289702 + 0.01168318713992301 + 0.011684914160867175 + 0.011686641193157913 + 0.011688368236830955 + 0.011690095291921993 + 0.011691822358466704 + 0.011693549436500751 + 0.011695276526059751 + 0.011697003627179309 + 0.011698730739895023 + 0.01170045786424243 + 0.011702185000257086 + 0.011703912147974492 + 0.011705639307430149 + 0.011707366478659532 + 0.011709093661698082 + 0.01171082085658123 + 0.011712548063344352 + 0.011714275282022854 + 0.011716002512652091 + 0.011717729755267381 + 0.011719457009904058 + 0.011721184276597383 + 0.011722911555382637 + 0.011724638846295059 + 0.011726366149369885 + 0.011728093464642294 + 0.011729820792147468 + 0.011731548131920564 + 0.011733275483996714 + 0.01173500284841103 + 0.011736730225198581 + 0.011738457614394442 + 0.011740185016033664 + 0.011741912430151257 + 0.011743639856782217 + 0.011745367295961521 + 0.011747094747724111 + 0.011748822212104937 + 0.011750549689138901 + 0.011752277178860878 + 0.011754004681305755 + 0.011755732196508337 + 0.011757459724503474 + 0.011759187265325937 + 0.011760914819010534 + 0.011762642385591991 + 0.01176436996510505 + 0.011766097557584426 + 0.011767825163064786 + 0.011769552781580806 + 0.011771280413167134 + 0.011773008057858383 + 0.011774735715689159 + 0.01177646338669402 + 0.011778191070907542 + 0.011779918768364246 + 0.011781646479098644 + 0.011783374203145238 + 0.011785101940538462 + 0.011786829691312801 + 0.011788557455502656 + 0.011790285233142439 + 0.011792013024266513 + 0.011793740828909254 + 0.011795468647104975 + 0.011797196478888026 + 0.011798924324292671 + 0.011800652183353194 + 0.011802380056103842 + 0.011804107942578834 + 0.011805835842812386 + 0.011807563756838672 + 0.011809291684691872 + 0.011811019626406108 + 0.011812747582015504 + 0.01181447555155417 + 0.011816203535056176 + 0.011817931532555569 + 0.011819659544086395 + 0.011821387569682658 + 0.011823115609378343 + 0.011824843663207433 + 0.011826571731203852 + 0.011828299813401548 + 0.011830027909834428 + 0.011831756020536368 + 0.011833484145541218 + 0.011835212284882836 + 0.011836940438595024 + 0.011838668606711596 + 0.01184039678926632 + 0.011842124986292951 + 0.011843853197825237 + 0.011845581423896866 + 0.011847309664541538 + 0.011849037919792931 + 0.011850766189684692 + 0.011852494474250441 + 0.011854222773523796 + 0.011855951087538338 + 0.011857679416327623 + 0.011859407759925196 + 0.011861136118364615 + 0.011862864491679323 + 0.01186459287990283 + 0.011866321283068595 + 0.011868049701210056 + 0.011869778134360629 + 0.011871506582553698 + 0.011873235045822649 + 0.011874963524200838 + 0.011876692017721594 + 0.011878420526418234 + 0.011880149050324041 + 0.011881877589472281 + 0.011883606143896226 + 0.01188533471362907 + 0.011887063298704058 + 0.011888791899154347 + 0.011890520515013124 + 0.011892249146313526 + 0.011893977793088678 + 0.011895706455371679 + 0.011897435133195612 + 0.011899163826593546 + 0.011900892535598531 + 0.011902621260243558 + 0.011904350000561652 + 0.011906078756585779 + 0.011907807528348925 + 0.011909536315883981 + 0.011911265119223911 + 0.011912993938401591 + 0.011914722773449887 + 0.011916451624401666 + 0.011918180491289775 + 0.011919909374147017 + 0.011921638273006192 + 0.011923367187900063 + 0.011925096118861386 + 0.011926825065922899 + 0.011928554029117319 + 0.01193028300847733 + 0.0119320120040356 + 0.01193374101582478 + 0.011935470043877525 + 0.011937199088226408 + 0.011938928148904054 + 0.011940657225943009 + 0.011942386319375834 + 0.011944115429235045 + 0.011945844555553172 + 0.011947573698362685 + 0.011949302857696065 + 0.011951032033585753 + 0.011952761226064168 + 0.011954490435163745 + 0.011956219660916851 + 0.011957948903355851 + 0.011959678162513107 + 0.011961407438420935 + 0.011963136731111646 + 0.011964866040617517 + 0.011966595366970836 + 0.011968324710203836 + 0.01197005407034874 + 0.011971783447437757 + 0.011973512841503078 + 0.011975242252576884 + 0.0119769716806913 + 0.011978701125878446 + 0.01198043058817045 + 0.011982160067599383 + 0.011983889564197324 + 0.011985619077996322 + 0.011987348609028396 + 0.011989078157325549 + 0.011990807722919774 + 0.011992537305843043 + 0.011994266906127295 + 0.011995996523804469 + 0.011997726158906452 + 0.011999455811465165 + 0.01200118548151244 + 0.01200291516908015 + 0.012004644874200124 + 0.012006374596904158 + 0.012008104337224048 + 0.012009834095191577 + 0.012011563870838465 + 0.012013293664196472 + 0.012015023475297296 + 0.012016753304172626 + 0.012018483150854145 + 0.012020213015373491 + 0.012021942897762311 + 0.012023672798052202 + 0.012025402716274771 + 0.012027132652461586 + 0.012028862606644198 + 0.012030592578854152 + 0.012032322569122948 + 0.012034052577482102 + 0.012035782603963067 + 0.012037512648597341 + 0.012039242711416317 + 0.012040972792451423 + 0.012042702891734078 + 0.012044433009295648 + 0.01204616314516747 + 0.012047893299380935 + 0.012049623471967336 + 0.012051353662957962 + 0.012053083872384114 + 0.012054814100277061 + 0.012056544346668035 + 0.012058274611588262 + 0.012060004895068969 + 0.012061735197141302 + 0.012063465517836465 + 0.012065195857185572 + 0.012066926215219782 + 0.012068656591970201 + 0.012070386987467903 + 0.012072117401743972 + 0.012073847834829475 + 0.012075578286755408 + 0.012077308757552811 + 0.012079039247252683 + 0.012080769755885991 + 0.012082500283483677 + 0.012084230830076705 + 0.012085961395695977 + 0.012087691980372411 + 0.012089422584136865 + 0.012091153207020212 + 0.012092883849053302 + 0.012094614510266952 + 0.012096345190691965 + 0.01209807589035913 + 0.012099806609299216 + 0.012101537347542969 + 0.012103268105121133 + 0.012104998882064396 + 0.012106729678403464 + 0.012108460494168997 + 0.012110191329391664 + 0.012111922184102101 + 0.012113653058330917 + 0.012115383952108701 + 0.012117114865466062 + 0.012118845798433538 + 0.012120576751041667 + 0.012122307723320987 + 0.012124038715302 + 0.012125769727015186 + 0.012127500758491011 + 0.012129231809759932 + 0.012130962880852367 + 0.012132693971798742 + 0.012134425082629432 + 0.012136156213374829 + 0.01213788736406528 + 0.012139618534731122 + 0.012141349725402682 + 0.01214308093611024 + 0.0121448121668841 + 0.012146543417754511 + 0.012148274688751718 + 0.01215000597990594 + 0.012151737291247416 + 0.0121534686228063 + 0.012155199974612781 + 0.012156931346697007 + 0.012158662739089105 + 0.01216039415181921 + 0.012162125584917402 + 0.012163857038413762 + 0.012165588512338357 + 0.012167320006721209 + 0.012169051521592368 + 0.012170783056981825 + 0.012172514612919577 + 0.012174246189435588 + 0.012175977786559794 + 0.012177709404322152 + 0.012179441042752572 + 0.012181172701880932 + 0.012182904381737126 + 0.012184636082351012 + 0.012186367803752419 + 0.012188099545971181 + 0.012189831309037114 + 0.012191563092979982 + 0.012193294897829558 + 0.01219502672361561 + 0.012196758570367856 + 0.012198490438116018 + 0.012200222326889798 + 0.01220195423671885 + 0.012203686167632869 + 0.012205418119661467 + 0.012207150092834277 + 0.012208882087180909 + 0.012210614102730957 + 0.012212346139513988 + 0.012214078197559548 + 0.012215810276897191 + 0.012217542377556408 + 0.012219274499566708 + 0.012221006642957584 + 0.01222273880775847 + 0.012224470993998841 + 0.012226203201708124 + 0.012227935430915698 + 0.012229667681650987 + 0.012231399953943354 + 0.012233132247822158 + 0.012234864563316726 + 0.012236596900456384 + 0.012238329259270436 + 0.01224006163978817 + 0.012241794042038857 + 0.012243526466051731 + 0.012245258911856044 + 0.012246991379481003 + 0.012248723868955787 + 0.012250456380309603 + 0.012252188913571594 + 0.012253921468770907 + 0.012255654045936671 + 0.012257386645098003 + 0.012259119266283976 + 0.012260851909523668 + 0.012262584574846152 + 0.012264317262280448 + 0.012266049971855573 + 0.012267782703600542 + 0.012269515457544348 + 0.012271248233715932 + 0.012272981032144269 + 0.012274713852858294 + 0.012276446695886904 + 0.012278179561259005 + 0.01227991244900347 + 0.012281645359149192 + 0.012283378291724985 + 0.012285111246759694 + 0.012286844224282115 + 0.012288577224321069 + 0.012290310246905302 + 0.0122920432920636 + 0.01229377635982468 + 0.012295509450217278 + 0.012297242563270109 + 0.012298975699011859 + 0.012300708857471193 + 0.012302442038676774 + 0.012304175242657246 + 0.012305908469441207 + 0.012307641719057278 + 0.012309374991534047 + 0.012311108286900081 + 0.012312841605183929 + 0.012314574946414131 + 0.012316308310619193 + 0.012318041697827626 + 0.012319775108067919 + 0.012321508541368535 + 0.012323241997757904 + 0.012324975477264482 + 0.012326708979916683 + 0.012328442505742884 + 0.012330176054771503 + 0.012331909627030872 + 0.012333643222549347 + 0.012335376841355246 + 0.012337110483476908 + 0.01233884414894262 + 0.012340577837780656 + 0.012342311550019275 + 0.012344045285686724 + 0.012345779044811244 + 0.012347512827421029 + 0.012349246633544284 + 0.012350980463209177 + 0.012352714316443884 + 0.012354448193276545 + 0.012356182093735268 + 0.01235791601784819 + 0.01235964996564339 + 0.012361383937148938 + 0.012363117932392902 + 0.012364851951403334 + 0.012366585994208239 + 0.012368320060835649 + 0.012370054151313536 + 0.01237178826566989 + 0.012373522403932672 + 0.012375256566129809 + 0.012376990752289227 + 0.012378724962438853 + 0.012380459196606569 + 0.012382193454820254 + 0.012383927737107756 + 0.012385662043496939 + 0.012387396374015602 + 0.012389130728691572 + 0.012390865107552655 + 0.01239259951062658 + 0.012394333937941145 + 0.012396068389524088 + 0.012397802865403127 + 0.012399537365605982 + 0.012401271890160326 + 0.012403006439093851 + 0.012404741012434219 + 0.012406475610209073 + 0.012408210232446027 + 0.012409944879172709 + 0.012411679550416705 + 0.012413414246205587 + 0.012415148966566919 + 0.012416883711528265 + 0.012418618481117116 + 0.012420353275361031 + 0.012422088094287454 + 0.012423822937923911 + 0.012425557806297845 + 0.012427292699436694 + 0.0124290276173679 + 0.012430762560118875 + 0.012432497527717017 + 0.012434232520189692 + 0.012435967537564294 + 0.012437702579868148 + 0.012439437647128607 + 0.012441172739372957 + 0.012442907856628544 + 0.012444642998922607 + 0.012446378166282428 + 0.012448113358735276 + 0.012449848576308349 + 0.012451583819028922 + 0.01245331908692413 + 0.012455054380021223 + 0.012456789698347336 + 0.012458525041929623 + 0.012460260410795227 + 0.012461995804971294 + 0.012463731224484893 + 0.012465466669363146 + 0.012467202139633099 + 0.012468937635321828 + 0.012470673156456363 + 0.012472408703063742 + 0.012474144275170974 + 0.012475879872805046 + 0.012477615495992942 + 0.012479351144761621 + 0.012481086819138029 + 0.012482822519149093 + 0.012484558244821732 + 0.012486293996182833 + 0.012488029773259295 + 0.01248976557607798 + 0.012491501404665725 + 0.012493237259049378 + 0.012494973139255754 + 0.012496709045311652 + 0.012498444977243879 + 0.012500180935079173 + 0.012501916918844301 + 0.012503652928566025 + 0.012505388964271036 + 0.01250712502598606 + 0.012508861113737781 + 0.012510597227552883 + 0.012512333367458018 + 0.012514069533479845 + 0.012515805725644974 + 0.012517541943980037 + 0.012519278188511609 + 0.012521014459266304 + 0.012522750756270658 + 0.012524487079551229 + 0.012526223429134557 + 0.012527959805047161 + 0.012529696207315547 + 0.012531432635966195 + 0.012533169091025578 + 0.012534905572520164 + 0.012536642080476368 + 0.012538378614920654 + 0.012540115175879401 + 0.012541851763379014 + 0.012543588377445862 + 0.012545325018106337 + 0.012547061685386739 + 0.012548798379313443 + 0.012550535099912758 + 0.012552271847210963 + 0.01255400862123437 + 0.012555745422009228 + 0.012557482249561805 + 0.012559219103918332 + 0.012560955985105034 + 0.012562692893148125 + 0.012564429828073797 + 0.012566166789908228 + 0.012567903778677563 + 0.012569640794407979 + 0.012571377837125582 + 0.012573114906856512 + 0.012574852003626848 + 0.012576589127462675 + 0.012578326278390077 + 0.012580063456435095 + 0.012581800661623784 + 0.012583537893982168 + 0.01258527515353622 + 0.012587012440311992 + 0.012588749754335417 + 0.012590487095632472 + 0.012592224464229099 + 0.012593961860151253 + 0.012595699283424817 + 0.012597436734075717 + 0.012599174212129843 + 0.012600911717613045 + 0.012602649250551198 + 0.012604386810970133 + 0.012606124398895696 + 0.012607862014353658 + 0.012609599657369864 + 0.012611337327970061 + 0.012613075026180018 + 0.012614812752025497 + 0.01261655050553223 + 0.012618288286725942 + 0.012620026095632324 + 0.012621763932277074 + 0.012623501796685865 + 0.012625239688884368 + 0.012626977608898221 + 0.01262871555675305 + 0.012630453532474481 + 0.012632191536088098 + 0.012633929567619507 + 0.012635667627094258 + 0.012637405714537918 + 0.012639143829976026 + 0.012640881973434106 + 0.012642620144937658 + 0.012644358344512207 + 0.012646096572183208 + 0.012647834827976137 + 0.012649573111916432 + 0.012651311424029549 + 0.012653049764340901 + 0.012654788132875879 + 0.012656526529659902 + 0.012658264954718328 + 0.012660003408076532 + 0.012661741889759855 + 0.012663480399793614 + 0.012665218938203151 + 0.012666957505013753 + 0.012668696100250716 + 0.012670434723939316 + 0.012672173376104795 + 0.012673912056772414 + 0.012675650765967378 + 0.012677389503714949 + 0.012679128270040287 + 0.012680867064968579 + 0.012682605888525001 + 0.012684344740734722 + 0.012686083621622869 + 0.012687822531214563 + 0.012689561469534939 + 0.012691300436609054 + 0.012693039432462031 + 0.012694778457118928 + 0.012696517510604778 + 0.012698256592944646 + 0.012699995704163542 + 0.012701734844286479 + 0.012703474013338432 + 0.012705213211344425 + 0.012706952438329389 + 0.012708691694318283 + 0.012710430979336045 + 0.012712170293407599 + 0.012713909636557851 + 0.012715649008811713 + 0.012717388410194035 + 0.012719127840729677 + 0.012720867300443523 + 0.01272260678936039 + 0.012724346307505092 + 0.012726085854902456 + 0.012727825431577258 + 0.01272956503755427 + 0.012731304672858275 + 0.012733044337513998 + 0.012734784031546207 + 0.012736523754979599 + 0.012738263507838885 + 0.012740003290148757 + 0.012741743101933885 + 0.012743482943218943 + 0.012745222814028571 + 0.012746962714387428 + 0.012748702644320088 + 0.012750442603851201 + 0.012752182593005333 + 0.012753922611807078 + 0.012755662660280978 + 0.012757402738451613 + 0.012759142846343486 + 0.012760882983981134 + 0.012762623151389065 + 0.012764363348591764 + 0.0127661035756137 + 0.012767843832479364 + 0.012769584119213185 + 0.012771324435839594 + 0.012773064782383037 + 0.0127748051588679 + 0.012776545565318589 + 0.01277828600175946 + 0.012780026468214911 + 0.012781766964709253 + 0.012783507491266855 + 0.012785248047912031 + 0.012786988634669084 + 0.012788729251562315 + 0.012790469898616007 + 0.012792210575854418 + 0.01279395128330179 + 0.012795692020982396 + 0.012797432788920426 + 0.012799173587140106 + 0.012800914415665623 + 0.012802655274521168 + 0.01280439616373092 + 0.01280613708331901 + 0.012807878033309591 + 0.012809619013726792 + 0.012811360024594707 + 0.012813101065937464 + 0.012814842137779123 + 0.012816583240143769 + 0.012818324373055457 + 0.012820065536538224 + 0.01282180673061609 + 0.012823547955313111 + 0.012825289210653238 + 0.012827030496660482 + 0.012828771813358833 + 0.012830513160772224 + 0.01283225453892462 + 0.012833995947839938 + 0.012835737387542097 + 0.01283747885805501 + 0.012839220359402579 + 0.012840961891608658 + 0.012842703454697126 + 0.012844445048691819 + 0.012846186673616601 + 0.012847928329495266 + 0.012849670016351631 + 0.012851411734209495 + 0.012853153483092634 + 0.012854895263024824 + 0.012856637074029804 + 0.012858378916131329 + 0.012860120789353129 + 0.012861862693718897 + 0.012863604629252342 + 0.012865346595977155 + 0.012867088593916999 + 0.012868830623095547 + 0.012870572683536419 + 0.012872314775263271 + 0.012874056898299721 + 0.012875799052669352 + 0.012877541238395764 + 0.012879283455502537 + 0.012881025704013237 + 0.012882767983951413 + 0.01288451029534058 + 0.012886252638204292 + 0.012887995012566046 + 0.012889737418449338 + 0.012891479855877654 + 0.01289322232487445 + 0.012894964825463193 + 0.012896707357667316 + 0.012898449921510268 + 0.012900192517015451 + 0.012901935144206253 + 0.012903677803106086 + 0.012905420493738299 + 0.012907163216126265 + 0.012908905970293349 + 0.012910648756262858 + 0.01291239157405814 + 0.01291413442370248 + 0.012915877305219184 + 0.012917620218631531 + 0.012919363163962787 + 0.012921106141236201 + 0.012922849150475037 + 0.012924592191702501 + 0.012926335264941824 + 0.012928078370216188 + 0.01292982150754878 + 0.012931564676962794 + 0.012933307878481385 + 0.012935051112127685 + 0.012936794377924858 + 0.012938537675896006 + 0.012940281006064241 + 0.012942024368452664 + 0.012943767763084337 + 0.012945511189982356 + 0.012947254649169761 + 0.012948998140669609 + 0.012950741664504911 + 0.012952485220698681 + 0.012954228809273927 + 0.012955972430253662 + 0.012957716083660831 + 0.012959459769518421 + 0.012961203487849354 + 0.0129629472386766 + 0.012964691022023057 + 0.012966434837911659 + 0.01296817868636529 + 0.01296992256740683 + 0.012971666481059161 + 0.012973410427345141 + 0.012975154406287616 + 0.012976898417909414 + 0.012978642462233344 + 0.012980386539282256 + 0.012982130649078896 + 0.012983874791646059 + 0.012985618967006505 + 0.012987363175183026 + 0.012989107416198324 + 0.012990851690075139 + 0.012992595996836186 + 0.012994340336504179 + 0.0129960847091018 + 0.012997829114651719 + 0.012999573553176616 + 0.013001318024699119 + 0.013003062529241893 + 0.013004807066827535 + 0.013006551637478674 + 0.013008296241217927 + 0.01301004087806785 + 0.01301178554805103 + 0.013013530251190022 + 0.013015274987507385 + 0.01301701975702564 + 0.013018764559767311 + 0.013020509395754935 + 0.013022254265010972 + 0.013023999167557926 + 0.013025744103418257 + 0.013027489072614451 + 0.013029234075168917 + 0.013030979111104098 + 0.013032724180442422 + 0.013034469283206302 + 0.013036214419418126 + 0.013037959589100272 + 0.013039704792275104 + 0.013041450028964997 + 0.013043195299192281 + 0.013044940602979284 + 0.013046685940348328 + 0.013048431311321733 + 0.01305017671592177 + 0.013051922154170732 + 0.013053667626090877 + 0.013055413131704477 + 0.013057158671033761 + 0.013058904244100973 + 0.013060649850928314 + 0.013062395491537987 + 0.013064141165952189 + 0.013065886874193104 + 0.01306763261628289 + 0.013069378392243714 + 0.013071124202097705 + 0.013072870045867003 + 0.013074615923573722 + 0.013076361835239957 + 0.013078107780887803 + 0.013079853760539342 + 0.013081599774216645 + 0.013083345821941752 + 0.013085091903736712 + 0.013086838019623565 + 0.013088584169624303 + 0.01309033035376095 + 0.013092076572055484 + 0.013093822824529902 + 0.013095569111206143 + 0.013097315432106191 + 0.013099061787251972 + 0.013100808176665407 + 0.013102554600368424 + 0.01310430105838294 + 0.013106047550730811 + 0.013107794077433958 + 0.013109540638514215 + 0.013111287233993464 + 0.013113033863893519 + 0.01311478052823623 + 0.013116527227043399 + 0.013118273960336851 + 0.013120020728138376 + 0.013121767530469728 + 0.013123514367352714 + 0.01312526123880906 + 0.013127008144860524 + 0.013128755085528836 + 0.013130502060835714 + 0.01313224907080285 + 0.013133996115451973 + 0.013135743194804733 + 0.013137490308882813 + 0.013139237457707877 + 0.013140984641301555 + 0.013142731859685499 + 0.013144479112881302 + 0.013146226400910606 + 0.013147973723794991 + 0.013149721081556036 + 0.013151468474215312 + 0.013153215901794409 + 0.013154963364314843 + 0.013156710861798163 + 0.013158458394265871 + 0.013160205961739526 + 0.013161953564240582 + 0.013163701201790532 + 0.013165448874410882 + 0.013167196582123068 + 0.013168944324948539 + 0.013170692102908743 + 0.013172439916025106 + 0.013174187764319048 + 0.013175935647811955 + 0.013177683566525236 + 0.013179431520480261 + 0.013181179509698396 + 0.013182927534200995 + 0.013184675594009394 + 0.013186423689144947 + 0.013188171819628941 + 0.0131899199854827 + 0.013191668186727502 + 0.013193416423384662 + 0.013195164695475416 + 0.013196913003021041 + 0.013198661346042776 + 0.013200409724561853 + 0.013202158138599511 + 0.013203906588176936 + 0.013205655073315333 + 0.013207403594035912 + 0.013209152150359813 + 0.013210900742308223 + 0.013212649369902263 + 0.013214398033163112 + 0.013216146732111876 + 0.013217895466769668 + 0.013219644237157593 + 0.013221393043296748 + 0.013223141885208196 + 0.013224890762913031 + 0.013226639676432289 + 0.013228388625787013 + 0.013230137610998241 + 0.013231886632086996 + 0.013233635689074281 + 0.013235384781981101 + 0.01323713391082843 + 0.013238883075637243 + 0.013240632276428497 + 0.013242381513223161 + 0.013244130786042148 + 0.0132458800949064 + 0.013247629439836824 + 0.013249378820854328 + 0.0132511282379798 + 0.013252877691234113 + 0.01325462718063814 + 0.013256376706212721 + 0.013258126267978723 + 0.013259875865956979 + 0.013261625500168291 + 0.013263375170633473 + 0.013265124877373309 + 0.013266874620408627 + 0.013268624399760153 + 0.013270374215448681 + 0.013272124067494935 + 0.013273873955919674 + 0.013275623880743621 + 0.013277373841987484 + 0.013279123839671966 + 0.013280873873817768 + 0.013282623944445576 + 0.013284374051576044 + 0.013286124195229822 + 0.013287874375427592 + 0.013289624592189943 + 0.013291374845537527 + 0.013293125135490951 + 0.013294875462070806 + 0.01329662582529768 + 0.013298376225192162 + 0.013300126661774804 + 0.01330187713506617 + 0.013303627645086778 + 0.013305378191857186 + 0.013307128775397909 + 0.01330887939572944 + 0.013310630052872282 + 0.013312380746846927 + 0.01331413147767384 + 0.013315882245373476 + 0.013317633049966303 + 0.013319383891472737 + 0.013321134769913208 + 0.013322885685308166 + 0.013324636637677972 + 0.013326387627043038 + 0.013328138653423745 + 0.013329889716840466 + 0.013331640817313547 + 0.013333391954863343 + 0.0133351431295102 + 0.013336894341274422 + 0.013338645590176333 + 0.013340396876236234 + 0.013342148199474423 + 0.013343899559911165 + 0.013345650957566735 + 0.013347402392461372 + 0.013349153864615364 + 0.013350905374048897 + 0.013352656920782214 + 0.013354408504835529 + 0.013356160126229059 + 0.01335791178498294 + 0.0133596634811174 + 0.013361415214652582 + 0.013363166985608641 + 0.013364918794005734 + 0.013366670639863973 + 0.013368422523203494 + 0.013370174444044402 + 0.013371926402406789 + 0.013373678398310752 + 0.013375430431776357 + 0.01337718250282369 + 0.013378934611472782 + 0.01338068675774368 + 0.013382438941656418 + 0.013384191163231024 + 0.013385943422487487 + 0.013387695719445812 + 0.013389448054126001 + 0.013391200426548022 + 0.013392952836731822 + 0.013394705284697375 + 0.013396457770464614 + 0.013398210294053473 + 0.013399962855483867 + 0.013401715454775717 + 0.013403468091948896 + 0.013405220767023308 + 0.013406973480018838 + 0.013408726230955317 + 0.013410479019852633 + 0.013412231846730606 + 0.013413984711609084 + 0.013415737614507874 + 0.013417490555446786 + 0.013419243534445622 + 0.013420996551524175 + 0.013422749606702191 + 0.013424502699999471 + 0.013426255831435752 + 0.013428009001030781 + 0.013429762208804293 + 0.013431515454775994 + 0.013433268738965618 + 0.013435022061392831 + 0.01343677542207735 + 0.013438528821038848 + 0.013440282258296968 + 0.013442035733871385 + 0.013443789247781739 + 0.013445542800047672 + 0.013447296390688784 + 0.013449050019724716 + 0.013450803687175042 + 0.013452557393059363 + 0.01345431113739725 + 0.013456064920208281 + 0.013457818741512004 + 0.013459572601327992 + 0.013461326499675734 + 0.013463080436574765 + 0.013464834412044645 + 0.013466588426104818 + 0.013468342478774804 + 0.013470096570074076 + 0.013471850700022114 + 0.013473604868638364 + 0.013475359075942281 + 0.013477113321953303 + 0.013478867606690856 + 0.013480621930174354 + 0.013482376292423206 + 0.013484130693456801 + 0.013485885133294521 + 0.013487639611955758 + 0.013489394129459849 + 0.013491148685826142 + 0.013492903281074003 + 0.01349465791522275 + 0.013496412588291703 + 0.013498167300300153 + 0.013499922051267413 + 0.013501676841212779 + 0.013503431670155523 + 0.013505186538114897 + 0.01350694144511016 + 0.013508696391160559 + 0.013510451376285326 + 0.013512206400503693 + 0.01351396146383487 + 0.013515716566298039 + 0.0135174717079124 + 0.013519226888697149 + 0.013520982108671437 + 0.013522737367854433 + 0.013524492666265263 + 0.013526248003923106 + 0.013528003380847059 + 0.013529758797056242 + 0.013531514252569756 + 0.013533269747406701 + 0.013535025281586182 + 0.013536780855127236 + 0.013538536468048954 + 0.013540292120370364 + 0.013542047812110533 + 0.013543803543288482 + 0.013545559313923233 + 0.013547315124033798 + 0.013549070973639178 + 0.013550826862758349 + 0.013552582791410302 + 0.013554338759614001 + 0.013556094767388406 + 0.013557850814752479 + 0.01355960690172512 + 0.013561363028325297 + 0.01356311919457189 + 0.013564875400483824 + 0.013566631646079998 + 0.013568387931379277 + 0.01357014425640056 + 0.013571900621162689 + 0.013573657025684518 + 0.013575413469984896 + 0.013577169954082665 + 0.01357892647799664 + 0.013580683041745624 + 0.013582439645348427 + 0.013584196288823827 + 0.013585952972190613 + 0.013587709695467567 + 0.013589466458673444 + 0.013591223261826955 + 0.013592980104946889 + 0.013594736988051942 + 0.013596493911160851 + 0.01359825087429231 + 0.013600007877465022 + 0.013601764920697689 + 0.013603522004008948 + 0.0136052791274175 + 0.013607036290941994 + 0.013608793494601068 + 0.013610550738413359 + 0.013612308022397485 + 0.01361406534657207 + 0.013615822710955712 + 0.013617580115567018 + 0.01361933756042456 + 0.013621095045546917 + 0.013622852570952642 + 0.013624610136660307 + 0.013626367742688432 + 0.013628125389055558 + 0.013629883075780221 + 0.013631640802880896 + 0.013633398570376118 + 0.013635156378284377 + 0.013636914226624143 + 0.013638672115413891 + 0.013640430044672086 + 0.013642188014417161 + 0.013643946024667572 + 0.013645704075441746 + 0.013647462166758108 + 0.013649220298635051 + 0.01365097847109099 + 0.013652736684144315 + 0.0136544949378134 + 0.013656253232116606 + 0.013658011567072303 + 0.013659769942698846 + 0.013661528359014553 + 0.013663286816037772 + 0.013665045313786811 + 0.013666803852279977 + 0.01366856243153557 + 0.013670321051571881 + 0.013672079712407199 + 0.013673838414059758 + 0.013675597156547859 + 0.013677355939889719 + 0.013679114764103594 + 0.013680873629207679 + 0.013682632535220238 + 0.013684391482159447 + 0.013686150470043509 + 0.013687909498890614 + 0.013689668568718952 + 0.013691427679546673 + 0.013693186831391927 + 0.013694946024272885 + 0.013696705258207665 + 0.013698464533214398 + 0.013700223849311211 + 0.013701983206516215 + 0.013703742604847488 + 0.013705502044323132 + 0.013707261524961207 + 0.013709021046779801 + 0.013710780609796957 + 0.013712540214030742 + 0.013714299859499167 + 0.013716059546220277 + 0.013717819274212084 + 0.013719579043492589 + 0.01372133885407981 + 0.013723098705991716 + 0.013724858599246284 + 0.013726618533861487 + 0.013728378509855296 + 0.013730138527245651 + 0.013731898586050466 + 0.013733658686287703 + 0.013735418827975257 + 0.013737179011131069 + 0.013738939235772997 + 0.01374069950191897 + 0.013742459809586825 + 0.01374422015879446 + 0.013745980549559722 + 0.013747740981900475 + 0.013749501455834548 + 0.013751261971379752 + 0.01375302252855394 + 0.013754783127374909 + 0.013756543767860462 + 0.013758304450028383 + 0.013760065173896441 + 0.013761825939482438 + 0.013763586746804116 + 0.013765347595879237 + 0.013767108486725525 + 0.013768869419360726 + 0.013770630393802559 + 0.013772391410068736 + 0.013774152468176953 + 0.01377591356814491 + 0.013777674709990298 + 0.01377943589373077 + 0.013781197119384003 + 0.013782958386967657 + 0.013784719696499362 + 0.013786481047996764 + 0.013788242441477461 + 0.013790003876959113 + 0.013791765354459291 + 0.013793526873995597 + 0.013795288435585629 + 0.013797050039246963 + 0.013798811684997149 + 0.013800573372853746 + 0.013802335102834311 + 0.013804096874956392 + 0.013805858689237494 + 0.013807620545695145 + 0.013809382444346848 + 0.01381114438521013 + 0.01381290636830244 + 0.013814668393641285 + 0.013816430461244122 + 0.013818192571128412 + 0.013819954723311618 + 0.013821716917811184 + 0.01382347915464451 + 0.013825241433829042 + 0.013827003755382202 + 0.013828766119321373 + 0.013830528525663958 + 0.013832290974427354 + 0.013834053465628909 + 0.013835815999286004 + 0.013837578575415984 + 0.013839341194036205 + 0.013841103855163992 + 0.013842866558816695 + 0.013844629305011605 + 0.013846392093766043 + 0.013848154925097304 + 0.013849917799022667 + 0.01385168071555944 + 0.013853443674724854 + 0.013855206676536209 + 0.013856969721010715 + 0.013858732808165649 + 0.013860495938018223 + 0.013862259110585657 + 0.013864022325885177 + 0.013865785583933974 + 0.013867548884749246 + 0.013869312228348191 + 0.013871075614747942 + 0.013872839043965718 + 0.013874602516018649 + 0.013876366030923888 + 0.013878129588698556 + 0.013879893189359794 + 0.013881656832924734 + 0.013883420519410454 + 0.013885184248834068 + 0.013886948021212672 + 0.01388871183656335 + 0.013890475694903147 + 0.01389223959624917 + 0.013894003540618424 + 0.013895767528027977 + 0.013897531558494873 + 0.013899295632036115 + 0.013901059748668726 + 0.013902823908409726 + 0.013904588111276076 + 0.013906352357284808 + 0.013908116646452851 + 0.013909880978797222 + 0.013911645354334859 + 0.013913409773082709 + 0.013915174235057701 + 0.013916938740276798 + 0.013918703288756896 + 0.01392046788051491 + 0.01392223251556776 + 0.013923997193932322 + 0.013925761915625499 + 0.013927526680664144 + 0.013929291489065155 + 0.013931056340845356 + 0.013932821236021613 + 0.013934586174610755 + 0.013936351156629612 + 0.013938116182095032 + 0.013939881251023788 + 0.013941646363432692 + 0.013943411519338552 + 0.013945176718758135 + 0.013946941961708212 + 0.013948707248205574 + 0.013950472578266947 + 0.013952237951909103 + 0.013954003369148751 + 0.01395576883000265 + 0.013957534334487485 + 0.013959299882619994 + 0.013961065474416863 + 0.013962831109894791 + 0.013964596789070449 + 0.013966362511960524 + 0.01396812827858168 + 0.013969894088950557 + 0.013971659943083815 + 0.01397342584099808 + 0.013975191782709985 + 0.01397695776823615 + 0.013978723797593191 + 0.013980489870797684 + 0.013982255987866241 + 0.013984022148815433 + 0.013985788353661847 + 0.013987554602422026 + 0.013989320895112553 + 0.013991087231749936 + 0.013992853612350736 + 0.013994620036931492 + 0.013996386505508688 + 0.01399815301809886 + 0.013999919574718505 + 0.014001686175384097 + 0.014003452820112137 + 0.014005219508919097 + 0.014006986241821428 + 0.014008753018835585 + 0.014010519839978034 + 0.014012286705265187 + 0.014014053614713496 + 0.014015820568339369 + 0.014017587566159208 + 0.014019354608189413 + 0.014021121694446402 + 0.014022888824946534 + 0.014024655999706188 + 0.014026423218741724 + 0.014028190482069514 + 0.014029957789705874 + 0.014031725141667183 + 0.014033492537969742 + 0.014035259978629894 + 0.014037027463663927 + 0.014038794993088147 + 0.014040562566918845 + 0.014042330185172328 + 0.014044097847864844 + 0.01404586555501269 + 0.014047633306632088 + 0.014049401102739308 + 0.01405116894335059 + 0.014052936828482165 + 0.014054704758150243 + 0.014056472732371051 + 0.014058240751160781 + 0.014060008814535641 + 0.014061776922511815 + 0.014063545075105469 + 0.014065313272332774 + 0.014067081514209911 + 0.014068849800753019 + 0.01407061813197822 + 0.01407238650790168 + 0.014074154928539495 + 0.014075923393907808 + 0.014077691904022695 + 0.014079460458900286 + 0.014081229058556652 + 0.014082997703007858 + 0.014084766392270026 + 0.014086535126359169 + 0.014088303905291345 + 0.01409007272908264 + 0.014091841597749052 + 0.014093610511306608 + 0.01409537946977135 + 0.014097148473159272 + 0.014098917521486395 + 0.014100686614768682 + 0.014102455753022134 + 0.014104224936262724 + 0.014105994164506423 + 0.014107763437769177 + 0.014109532756066939 + 0.014111302119415647 + 0.014113071527831237 + 0.014114840981329648 + 0.014116610479926758 + 0.014118380023638508 + 0.014120149612480756 + 0.014121919246469416 + 0.014123688925620357 + 0.014125458649949463 + 0.014127228419472589 + 0.014128998234205575 + 0.014130768094164277 + 0.01413253799936454 + 0.014134307949822171 + 0.014136077945553001 + 0.014137847986572822 + 0.014139618072897464 + 0.014141388204542686 + 0.01414315838152431 + 0.014144928603858077 + 0.014146698871559765 + 0.014148469184645129 + 0.014150239543129935 + 0.014152009947029896 + 0.014153780396360772 + 0.014155550891138262 + 0.014157321431378093 + 0.014159092017095965 + 0.014160862648307579 + 0.014162633325028616 + 0.014164404047274778 + 0.014166174815061711 + 0.014167945628405086 + 0.014169716487320579 + 0.014171487391823794 + 0.014173258341930391 + 0.014175029337656006 + 0.014176800379016259 + 0.014178571466026741 + 0.014180342598703079 + 0.014182113777060849 + 0.014183885001115634 + 0.014185656270883034 + 0.01418742758637861 + 0.014189198947617906 + 0.014190970354616483 + 0.014192741807389889 + 0.014194513305953655 + 0.014196284850323312 + 0.014198056440514372 + 0.01419982807654235 + 0.01420159975842273 + 0.01420337148617103 + 0.014205143259802707 + 0.014206915079333266 + 0.014208686944778141 + 0.014210458856152826 + 0.014212230813472728 + 0.014214002816753326 + 0.014215774866010033 + 0.014217546961258282 + 0.014219319102513492 + 0.014221091289791054 + 0.014222863523106376 + 0.014224635802474867 + 0.014226408127911866 + 0.014228180499432787 + 0.014229952917052984 + 0.014231725380787808 + 0.014233497890652607 + 0.014235270446662727 + 0.014237043048833498 + 0.014238815697180251 + 0.014240588391718286 + 0.014242361132462918 + 0.014244133919429436 + 0.014245906752633144 + 0.014247679632089314 + 0.014249452557813231 + 0.014251225529820132 + 0.014252998548125298 + 0.014254771612743985 + 0.014256544723691405 + 0.01425831788098279 + 0.014260091084633397 + 0.014261864334658406 + 0.014263637631073042 + 0.014265410973892497 + 0.014267184363131959 + 0.014268957798806606 + 0.014270731280931622 + 0.014272504809522154 + 0.014274278384593372 + 0.014276052006160431 + 0.014277825674238447 + 0.014279599388842573 + 0.014281373149987925 + 0.014283146957689601 + 0.014284920811962734 + 0.014286694712822418 + 0.014288468660283734 + 0.014290242654361756 + 0.014292016695071569 + 0.014293790782428253 + 0.014295564916446823 + 0.014297339097142375 + 0.014299113324529919 + 0.01430088759862449 + 0.014302661919441132 + 0.014304436286994831 + 0.014306210701300618 + 0.014307985162373481 + 0.014309759670228411 + 0.014311534224880391 + 0.014313308826344408 + 0.014315083474635407 + 0.014316858169768357 + 0.014318632911758217 + 0.014320407700619918 + 0.014322182536368393 + 0.014323957419018579 + 0.014325732348585377 + 0.014327507325083699 + 0.014329282348528451 + 0.014331057418934534 + 0.014332832536316812 + 0.014334607700690187 + 0.014336382912069501 + 0.014338158170469625 + 0.014339933475905413 + 0.014341708828391723 + 0.014343484227943359 + 0.014345259674575162 + 0.014347035168301953 + 0.014348810709138555 + 0.01435058629709975 + 0.014352361932200354 + 0.014354137614455134 + 0.014355913343878889 + 0.014357689120486353 + 0.014359464944292334 + 0.014361240815311562 + 0.014363016733558782 + 0.014364792699048747 + 0.014366568711796179 + 0.014368344771815806 + 0.014370120879122317 + 0.014371897033730437 + 0.014373673235654881 + 0.01437544948491031 + 0.014377225781511415 + 0.014379002125472875 + 0.01438077851680936 + 0.014382554955535495 + 0.014384331441665982 + 0.014386107975215423 + 0.014387884556198459 + 0.014389661184629723 + 0.014391437860523831 + 0.014393214583895394 + 0.01439499135475901 + 0.014396768173129267 + 0.014398545039020759 + 0.014400321952448055 + 0.014402098913425747 + 0.014403875921968351 + 0.014405652978090478 + 0.014407430081806625 + 0.014409207233131363 + 0.014410984432079194 + 0.014412761678664661 + 0.01441453897290227 + 0.014416316314806527 + 0.01441809370439192 + 0.014419871141672957 + 0.014421648626664105 + 0.014423426159379835 + 0.014425203739834627 + 0.014426981368042928 + 0.014428759044019203 + 0.01443053676777787 + 0.01443231453933339 + 0.014434092358700161 + 0.014435870225892631 + 0.014437648140925184 + 0.014439426103812245 + 0.014441204114568189 + 0.014442982173207402 + 0.014444760279744282 + 0.014446538434193185 + 0.014448316636568478 + 0.014450094886884523 + 0.014451873185155653 + 0.014453651531396218 + 0.014455429925620534 + 0.01445720836784295 + 0.014458986858077762 + 0.014460765396339288 + 0.01446254398264182 + 0.014464322616999642 + 0.014466101299427067 + 0.014467880029938353 + 0.014469658808547767 + 0.014471437635269563 + 0.014473216510118016 + 0.01447499543310735 + 0.014476774404251812 + 0.014478553423565636 + 0.014480332491063027 + 0.01448211160675821 + 0.014483890770665411 + 0.014485669982798785 + 0.014487449243172541 + 0.014489228551800881 + 0.014491007908697959 + 0.014492787313877943 + 0.014494566767354999 + 0.01449634626914327 + 0.014498125819256908 + 0.014499905417710049 + 0.014501685064516814 + 0.014503464759691326 + 0.014505244503247704 + 0.014507024295200038 + 0.014508804135562454 + 0.014510584024348998 + 0.014512363961573784 + 0.014514143947250877 + 0.014515923981394341 + 0.014517704064018245 + 0.014519484195136621 + 0.014521264374763527 + 0.014523044602912986 + 0.014524824879599031 + 0.014526605204835705 + 0.014528385578636971 + 0.01453016600101688 + 0.014531946471989386 + 0.014533726991568515 + 0.01453550755976824 + 0.014537288176602515 + 0.014539068842085313 + 0.01454084955623061 + 0.014542630319052343 + 0.014544411130564457 + 0.014546191990780893 + 0.014547972899715562 + 0.014549753857382395 + 0.014551534863795302 + 0.014553315918968189 + 0.014555097022914942 + 0.014556878175649464 + 0.014558659377185642 + 0.014560440627537327 + 0.014562221926718414 + 0.014564003274742745 + 0.014565784671624154 + 0.014567566117376517 + 0.014569347612013651 + 0.014571129155549391 + 0.014572910747997532 + 0.014574692389371936 + 0.014576474079686375 + 0.014578255818954644 + 0.014580037607190552 + 0.014581819444407861 + 0.014583601330620376 + 0.014585383265841835 + 0.014587165250085998 + 0.014588947283366637 + 0.014590729365697478 + 0.014592511497092264 + 0.01459429367756473 + 0.014596075907128594 + 0.014597858185797574 + 0.014599640513585373 + 0.014601422890505686 + 0.014603205316572207 + 0.01460498779179863 + 0.014606770316198621 + 0.014608552889785856 + 0.014610335512573977 + 0.014612118184576662 + 0.014613900905807548 + 0.014615683676280277 + 0.014617466496008475 + 0.014619249365005757 + 0.014621032283285759 + 0.014622815250862084 + 0.01462459826774833 + 0.014626381333958088 + 0.014628164449504941 + 0.01462994761440249 + 0.014631730828664282 + 0.014633514092303887 + 0.014635297405334874 + 0.014637080767770766 + 0.014638864179625137 + 0.014640647640911495 + 0.014642431151643378 + 0.014644214711834306 + 0.014645998321497784 + 0.014647781980647314 + 0.014649565689296406 + 0.014651349447458537 + 0.014653133255147187 + 0.01465491711237585 + 0.014656701019157971 + 0.014658484975507015 + 0.014660268981436434 + 0.014662053036959685 + 0.014663837142090181 + 0.014665621296841378 + 0.01466740550122668 + 0.014669189755259512 + 0.014670974058953283 + 0.014672758412321376 + 0.014674542815377186 + 0.014676327268134122 + 0.014678111770605556 + 0.014679896322804829 + 0.014681680924745342 + 0.014683465576440433 + 0.014685250277903433 + 0.014687035029147722 + 0.014688819830186599 + 0.01469060468103341 + 0.014692389581701472 + 0.014694174532204089 + 0.014695959532554552 + 0.014697744582766192 + 0.014699529682852286 + 0.014701314832826103 + 0.01470310003270091 + 0.014704885282490006 + 0.014706670582206642 + 0.014708455931864053 + 0.014710241331475485 + 0.0147120267810542 + 0.014713812280613425 + 0.014715597830166356 + 0.014717383429726227 + 0.014719169079306262 + 0.014720954778919635 + 0.01472274052857956 + 0.014724526328299193 + 0.014726312178091753 + 0.014728098077970405 + 0.014729884027948285 + 0.014731670028038589 + 0.014733456078254437 + 0.014735242178608993 + 0.014737028329115364 + 0.014738814529786719 + 0.014740600780636158 + 0.0147423870816768 + 0.014744173432921738 + 0.01474595983438408 + 0.014747746286076927 + 0.014749532788013362 + 0.014751319340206457 + 0.01475310594266927 + 0.014754892595414886 + 0.014756679298456352 + 0.014758466051806723 + 0.014760252855479019 + 0.014762039709486309 + 0.0147638266138416 + 0.014765613568557906 + 0.014767400573648249 + 0.014769187629125649 + 0.014770974735003073 + 0.014772761891293538 + 0.014774549098010008 + 0.014776336355165471 + 0.014778123662772896 + 0.014779911020845232 + 0.014781698429395465 + 0.014783485888436523 + 0.014785273397981354 + 0.014787060958042872 + 0.014788848568634022 + 0.014790636229767718 + 0.014792423941456873 + 0.014794211703714399 + 0.014795999516553178 + 0.014797787379986093 + 0.014799575294026078 + 0.014801363258685958 + 0.014803151273978609 + 0.014804939339916917 + 0.014806727456513711 + 0.014808515623781864 + 0.014810303841734202 + 0.014812092110383547 + 0.014813880429742743 + 0.014815668799824601 + 0.01481745722064195 + 0.014819245692207574 + 0.014821034214534278 + 0.014822822787634842 + 0.014824611411522071 + 0.014826400086208729 + 0.014828188811707584 + 0.014829977588031416 + 0.014831766415192953 + 0.014833555293204959 + 0.014835344222080167 + 0.014837133201831327 + 0.014838922232471156 + 0.014840711314012361 + 0.014842500446467668 + 0.014844289629849799 + 0.01484607886417141 + 0.014847868149445231 + 0.014849657485683933 + 0.014851446872900194 + 0.014853236311106676 + 0.014855025800316063 + 0.014856815340541009 + 0.014858604931794124 + 0.014860394574088097 + 0.014862184267435539 + 0.014863974011849093 + 0.014865763807341366 + 0.014867553653924977 + 0.014869343551612523 + 0.014871133500416626 + 0.014872923500349862 + 0.014874713551424841 + 0.014876503653654099 + 0.014878293807050249 + 0.014880084011625841 + 0.014881874267393413 + 0.014883664574365556 + 0.01488545493255479 + 0.014887245341973649 + 0.01488903580263466 + 0.014890826314550369 + 0.014892616877733283 + 0.014894407492195897 + 0.01489619815795072 + 0.014897988875010247 + 0.014899779643386967 + 0.014901570463093374 + 0.014903361334141918 + 0.014905152256545103 + 0.014906943230315347 + 0.014908734255465121 + 0.014910525332006876 + 0.014912316459953043 + 0.014914107639316066 + 0.014915898870108366 + 0.014917690152342355 + 0.014919481486030447 + 0.014921272871185059 + 0.014923064307818566 + 0.014924855795943392 + 0.014926647335571874 + 0.014928438926716423 + 0.014930230569389424 + 0.014932022263603196 + 0.014933814009370128 + 0.014935605806702565 + 0.014937397655612833 + 0.014939189556113295 + 0.014940981508216242 + 0.014942773511934031 + 0.014944565567278962 + 0.014946357674263338 + 0.014948149832899481 + 0.014949942043199656 + 0.014951734305176181 + 0.014953526618841301 + 0.014955318984207334 + 0.014957111401286503 + 0.014958903870091097 + 0.014960696390633358 + 0.014962488962925551 + 0.014964281586979874 + 0.014966074262808608 + 0.014967866990423953 + 0.014969659769838111 + 0.014971452601063319 + 0.014973245484111788 + 0.014975038418995702 + 0.014976831405727255 + 0.01497862444431864 + 0.014980417534782008 + 0.01498221067712956 + 0.014984003871373457 + 0.014985797117525833 + 0.01498759041559887 + 0.014989383765604688 + 0.014991177167555454 + 0.014992970621463245 + 0.014994764127340236 + 0.014996557685198524 + 0.014998351295050222 + 0.015000144956907423 + 0.015001938670782224 + 0.015003732436686734 + 0.015005526254633026 + 0.015007320124633156 + 0.015009114046699227 + 0.015010908020843271 + 0.015012702047077364 + 0.015014496125413546 + 0.015016290255863859 + 0.015018084438440339 + 0.015019878673155022 + 0.015021672960019912 + 0.01502346729904705 + 0.015025261690248421 + 0.015027056133636033 + 0.015028850629221907 + 0.015030645177017977 + 0.015032439777036269 + 0.015034234429288746 + 0.015036029133787364 + 0.015037823890544094 + 0.015039618699570901 + 0.015041413560879712 + 0.015043208474482478 + 0.01504500344039115 + 0.015046798458617616 + 0.01504859352917382 + 0.015050388652071693 + 0.015052183827323116 + 0.015053979054939987 + 0.015055774334934236 + 0.015057569667317708 + 0.01505936505210231 + 0.015061160489299907 + 0.015062955978922364 + 0.015064751520981553 + 0.015066547115489307 + 0.015068342762457495 + 0.015070138461897956 + 0.015071934213822502 + 0.015073730018242989 + 0.0150755258751712 + 0.015077321784618987 + 0.015079117746598156 + 0.015080913761120477 + 0.015082709828197765 + 0.015084505947841815 + 0.015086302120064392 + 0.015088098344877262 + 0.015089894622292212 + 0.015091690952321001 + 0.015093487334975375 + 0.015095283770267084 + 0.015097080258207871 + 0.015098876798809467 + 0.0151006733920836 + 0.015102470038041996 + 0.015104266736696357 + 0.0151060634880584 + 0.015107860292139823 + 0.01510965714895234 + 0.015111454058507607 + 0.015113251020817344 + 0.015115048035893175 + 0.01511684510374681 + 0.015118642224389894 + 0.015120439397834067 + 0.015122236624091024 + 0.015124033903172362 + 0.015125831235089716 + 0.015127628619854755 + 0.015129426057479065 + 0.015131223547974262 + 0.015133021091351987 + 0.015134818687623803 + 0.015136616336801332 + 0.015138414038896158 + 0.015140211793919851 + 0.015142009601883999 + 0.015143807462800181 + 0.01514560537667994 + 0.01514740334353484 + 0.015149201363376436 + 0.015150999436216256 + 0.01515279756206586 + 0.015154595740936765 + 0.015156393972840489 + 0.015158192257788569 + 0.015159990595792488 + 0.015161788986863768 + 0.01516358743101391 + 0.015165385928254393 + 0.015167184478596711 + 0.015168983082052343 + 0.01517078173863276 + 0.015172580448349416 + 0.015174379211213779 + 0.015176178027237289 + 0.015177976896431418 + 0.015179775818807577 + 0.015181574794377213 + 0.015183373823151748 + 0.015185172905142612 + 0.015186972040361202 + 0.015188771228818933 + 0.015190570470527217 + 0.015192369765497427 + 0.01519416911374096 + 0.015195968515269186 + 0.015197767970093491 + 0.015199567478225253 + 0.015201367039675812 + 0.015203166654456531 + 0.015204966322578761 + 0.015206766044053835 + 0.01520856581889311 + 0.015210365647107885 + 0.01521216552870951 + 0.015213965463709284 + 0.015215765452118529 + 0.015217565493948532 + 0.015219365589210604 + 0.015221165737916039 + 0.015222965940076104 + 0.015224766195702085 + 0.015226566504805259 + 0.015228366867396894 + 0.015230167283488224 + 0.015231967753090518 + 0.015233768276215037 + 0.015235568852872989 + 0.015237369483075634 + 0.015239170166834183 + 0.015240970904159849 + 0.015242771695063873 + 0.015244572539557423 + 0.01524637343765174 + 0.015248174389357976 + 0.015249975394687362 + 0.015251776453651061 + 0.015253577566260251 + 0.015255378732526085 + 0.01525717995245974 + 0.015258981226072365 + 0.015260782553375119 + 0.015262583934379148 + 0.015264385369095568 + 0.015266186857535537 + 0.01526798839971015 + 0.015269789995630547 + 0.015271591645307836 + 0.015273393348753111 + 0.015275195105977498 + 0.015276996916992053 + 0.015278798781807879 + 0.015280600700436058 + 0.015282402672887664 + 0.015284204699173758 + 0.01528600677930542 + 0.015287808913293665 + 0.015289611101149573 + 0.015291413342884178 + 0.015293215638508516 + 0.015295017988033613 + 0.015296820391470504 + 0.015298622848830188 + 0.015300425360123672 + 0.015302227925361992 + 0.015304030544556093 + 0.015305833217717028 + 0.015307635944855744 + 0.015309438725983211 + 0.015311241561110429 + 0.01531304445024835 + 0.015314847393407934 + 0.015316650390600147 + 0.01531845344183592 + 0.015320256547126192 + 0.015322059706481917 + 0.015323862919913996 + 0.015325666187433371 + 0.015327469509050954 + 0.015329272884777667 + 0.015331076314624388 + 0.015332879798602018 + 0.015334683336721475 + 0.015336486928993615 + 0.015338290575429321 + 0.01534009427603948 + 0.015341898030834942 + 0.015343701839826574 + 0.015345505703025224 + 0.015347309620441729 + 0.015349113592086969 + 0.015350917617971735 + 0.015352721698106876 + 0.015354525832503203 + 0.015356330021171538 + 0.015358134264122709 + 0.015359938561367491 + 0.015361742912916683 + 0.01536354731878109 + 0.015365351778971513 + 0.015367156293498678 + 0.015368960862373398 + 0.015370765485606435 + 0.015372570163208532 + 0.015374374895190468 + 0.015376179681562964 + 0.015377984522336777 + 0.015379789417522641 + 0.015381594367131286 + 0.015383399371173421 + 0.015385204429659769 + 0.015387009542601051 + 0.015388814710007958 + 0.015390619931891203 + 0.015392425208261456 + 0.015394230539129422 + 0.015396035924505754 + 0.015397841364401161 + 0.015399646858826287 + 0.0154014524077918 + 0.015403258011308355 + 0.015405063669386602 + 0.015406869382037161 + 0.015408675149270697 + 0.01541048097109785 + 0.015412286847529192 + 0.015414092778575387 + 0.015415898764247028 + 0.015417704804554721 + 0.015419510899509076 + 0.015421317049120671 + 0.015423123253400117 + 0.015424929512357953 + 0.015426735826004805 + 0.015428542194351198 + 0.015430348617407715 + 0.01543215509518491 + 0.015433961627693329 + 0.015435768214943522 + 0.015437574856946027 + 0.015439381553711376 + 0.015441188305250082 + 0.015442995111572681 + 0.015444801972689685 + 0.015446608888611598 + 0.015448415859348906 + 0.015450222884912129 + 0.015452029965311732 + 0.015453837100558216 + 0.015455644290662065 + 0.015457451535633732 + 0.015459258835483682 + 0.015461066190222373 + 0.015462873599860271 + 0.015464681064407826 + 0.015466488583875469 + 0.015468296158273604 + 0.015470103787612701 + 0.015471911471903181 + 0.015473719211155444 + 0.015475527005379894 + 0.015477334854586957 + 0.015479142758787015 + 0.015480950717990459 + 0.015482758732207686 + 0.015484566801449049 + 0.015486374925724971 + 0.015488183105045766 + 0.015489991339421846 + 0.015491799628863526 + 0.015493607973381169 + 0.015495416372985123 + 0.015497224827685714 + 0.01549903333749328 + 0.015500841902418164 + 0.015502650522470655 + 0.015504459197661084 + 0.015506267927999749 + 0.015508076713496981 + 0.015509885554163017 + 0.015511694450008199 + 0.015513503401042787 + 0.015515312407277068 + 0.015517121468721291 + 0.015518930585385756 + 0.015520739757280686 + 0.015522548984416362 + 0.015524358266803021 + 0.015526167604450893 + 0.015527976997370229 + 0.015529786445571261 + 0.015531595949064203 + 0.015533405507859269 + 0.015535215121966666 + 0.015537024791396617 + 0.015538834516159311 + 0.015540644296264939 + 0.015542454131723699 + 0.015544264022545759 + 0.015546073968741286 + 0.015547883970320477 + 0.015549694027293488 + 0.015551504139670448 + 0.015553314307461544 + 0.0155551245306769 + 0.01555693480932667 + 0.015558745143420974 + 0.015560555532969948 + 0.015562365977983708 + 0.015564176478472381 + 0.015565987034446059 + 0.015567797645914858 + 0.01556960831288887 + 0.015571419035378189 + 0.015573229813392904 + 0.015575040646943089 + 0.01557685153603882 + 0.01557866248069018 + 0.015580473480907204 + 0.015582284536699962 + 0.015584095648078507 + 0.015585906815052879 + 0.015587718037633119 + 0.015589529315829263 + 0.015591340649651333 + 0.015593152039109343 + 0.01559496348421332 + 0.01559677498497326 + 0.015598586541399178 + 0.015600398153501066 + 0.015602209821288925 + 0.015604021544772719 + 0.015605833323962438 + 0.015607645158868051 + 0.015609457049499537 + 0.015611268995866869 + 0.015613080997979962 + 0.015614893055848806 + 0.015616705169483316 + 0.015618517338893436 + 0.01562032956408912 + 0.015622141845080274 + 0.015623954181876835 + 0.015625766574488689 + 0.015627579022925771 + 0.015629391527197972 + 0.015631204087315189 + 0.01563301670328732 + 0.015634829375124237 + 0.015636642102835847 + 0.015638454886431983 + 0.015640267725922554 + 0.015642080621317393 + 0.015643893572626362 + 0.015645706579859323 + 0.015647519643026107 + 0.015649332762136554 + 0.01565114593720051 + 0.01565295916822779 + 0.015654772455228214 + 0.015656585798211595 + 0.015658399197187745 + 0.015660212652166477 + 0.015662026163157584 + 0.015663839730170839 + 0.015665653353216066 + 0.015667467032303005 + 0.015669280767441462 + 0.015671094558641178 + 0.015672908405911939 + 0.015674722309263485 + 0.015676536268705566 + 0.015678350284247952 + 0.015680164355900354 + 0.015681978483672532 + 0.015683792667574175 + 0.015685606907615036 + 0.015687421203804841 + 0.015689235556153262 + 0.01569104996467004 + 0.01569286442936486 + 0.015694678950247405 + 0.015696493527327368 + 0.015698308160614436 + 0.015700122850118289 + 0.015701937595848588 + 0.015703752397814984 + 0.015705567256027168 + 0.01570738217049476 + 0.015709197141227448 + 0.015711012168234818 + 0.015712827251526545 + 0.015714642391112237 + 0.015716457587001544 + 0.015718272839204062 + 0.015720088147729405 + 0.01572190351258717 + 0.015723718933786997 + 0.015725534411338435 + 0.015727349945251105 + 0.015729165535534578 + 0.015730981182198421 + 0.015732796885252229 + 0.015734612644705537 + 0.015736428460567945 + 0.015738244332848983 + 0.015740060261558185 + 0.015741876246705141 + 0.015743692288299343 + 0.015745508386350335 + 0.015747324540867656 + 0.015749140751860825 + 0.015750957019339339 + 0.015752773343312734 + 0.015754589723790471 + 0.015756406160782086 + 0.015758222654297056 + 0.015760039204344874 + 0.015761855810935012 + 0.015763672474076937 + 0.015765489193780149 + 0.015767305970054074 + 0.015769122802908184 + 0.015770939692351937 + 0.015772756638394784 + 0.015774573641046136 + 0.015776390700315467 + 0.015778207816212159 + 0.015780024988745683 + 0.015781842217925428 + 0.015783659503760823 + 0.015785476846261252 + 0.01578729424543614 + 0.015789111701294874 + 0.015790929213846817 + 0.015792746783101386 + 0.015794564409067947 + 0.015796382091755871 + 0.015798199831174524 + 0.015800017627333282 + 0.015801835480241468 + 0.015803653389908443 + 0.015805471356343581 + 0.015807289379556184 + 0.015809107459555598 + 0.015810925596351152 + 0.015812743789952156 + 0.015814562040367935 + 0.015816380347607795 + 0.015818198711681046 + 0.015820017132596988 + 0.0158218356103649 + 0.015823654144994079 + 0.015825472736493817 + 0.015827291384873359 + 0.015829110090142009 + 0.015830928852309002 + 0.015832747671383606 + 0.015834566547375094 + 0.015836385480292706 + 0.01583820447014567 + 0.015840023516943229 + 0.015841842620694619 + 0.015843661781409071 + 0.015845480999095777 + 0.015847300273763975 + 0.015849119605422873 + 0.015850938994081659 + 0.015852758439749554 + 0.015854577942435728 + 0.015856397502149365 + 0.015858217118899662 + 0.015860036792695792 + 0.015861856523546908 + 0.015863676311462183 + 0.015865496156450776 + 0.01586731605852186 + 0.015869136017684537 + 0.015870956033947982 + 0.01587277610732131 + 0.01587459623781368 + 0.015876416425434182 + 0.015878236670191958 + 0.015880056972096119 + 0.015881877331155755 + 0.015883697747379993 + 0.015885518220777908 + 0.015887338751358601 + 0.015889159339131164 + 0.015890979984104669 + 0.015892800686288188 + 0.015894621445690787 + 0.015896442262321533 + 0.015898263136189496 + 0.015900084067303699 + 0.015901905055673234 + 0.015903726101307084 + 0.015905547204214346 + 0.015907368364403995 + 0.015909189581885082 + 0.015911010856666619 + 0.015912832188757633 + 0.015914653578167109 + 0.015916475024904061 + 0.015918296528977499 + 0.015920118090396385 + 0.015921939709169722 + 0.01592376138530649 + 0.015925583118815659 + 0.015927404909706198 + 0.015929226757987077 + 0.015931048663667229 + 0.015932870626755649 + 0.015934692647261252 + 0.015936514725192991 + 0.015938336860559805 + 0.015940159053370588 + 0.015941981303634313 + 0.015943803611359882 + 0.015945625976556198 + 0.015947448399232168 + 0.015949270879396724 + 0.015951093417058738 + 0.015952916012227102 + 0.015954738664910709 + 0.015956561375118437 + 0.015958384142859161 + 0.015960206968141745 + 0.015962029850975064 + 0.015963852791367975 + 0.015965675789329312 + 0.015967498844867943 + 0.015969321957992708 + 0.015971145128712439 + 0.015972968357035974 + 0.015974791642972119 + 0.015976614986529726 + 0.015978438387717578 + 0.015980261846544497 + 0.015982085363019299 + 0.015983908937150768 + 0.0159857325689477 + 0.01598755625841887 + 0.015989380005573088 + 0.015991203810419102 + 0.015993027672965697 + 0.015994851593221636 + 0.01599667557119569 + 0.015998499606896584 + 0.016000323700333104 + 0.016002147851513961 + 0.016003972060447919 + 0.016005796327143679 + 0.016007620651610009 + 0.016009445033855603 + 0.016011269473889179 + 0.016013093971719461 + 0.016014918527355163 + 0.016016743140804941 + 0.016018567812077524 + 0.016020392541181601 + 0.016022217328125841 + 0.016024042172918942 + 0.01602586707556955 + 0.016027692036086363 + 0.016029517054478019 + 0.016031342130753187 + 0.016033167264920514 + 0.016034992456988643 + 0.01603681770696623 + 0.016038643014861874 + 0.01604046838068425 + 0.016042293804441939 + 0.016044119286143591 + 0.016045944825797798 + 0.016047770423413196 + 0.016049596078998363 + 0.016051421792561905 + 0.016053247564112416 + 0.016055073393658453 + 0.016056899281208646 + 0.016058725226771538 + 0.016060551230355699 + 0.016062377291969701 + 0.016064203411622117 + 0.016066029589321483 + 0.016067855825076336 + 0.016069682118895257 + 0.016071508470786745 + 0.016073334880759356 + 0.016075161348821598 + 0.016076987874982025 + 0.016078814459249118 + 0.016080641101631384 + 0.016082467802137373 + 0.016084294560775543 + 0.016086121377554413 + 0.016087948252482446 + 0.016089775185568159 + 0.016091602176820007 + 0.016093429226246469 + 0.016095256333856028 + 0.016097083499657105 + 0.0160989107236582 + 0.016100738005867744 + 0.016102565346294194 + 0.016104392744945979 + 0.016106220201831539 + 0.016108047716959312 + 0.016109875290337704 + 0.016111702921975151 + 0.016113530611880075 + 0.016115358360060866 + 0.016117186166525931 + 0.016119014031283681 + 0.016120841954342491 + 0.016122669935710768 + 0.016124497975396876 + 0.016126326073409199 + 0.016128154229756095 + 0.01612998244444596 + 0.016131810717487139 + 0.016133639048887968 + 0.016135467438656837 + 0.016137295886802065 + 0.016139124393331997 + 0.016140952958254955 + 0.016142781581579287 + 0.016144610263313312 + 0.016146439003465352 + 0.016148267802043696 + 0.01615009665905668 + 0.016151925574512584 + 0.016153754548419729 + 0.016155583580786372 + 0.016157412671620845 + 0.016159241820931404 + 0.016161071028726322 + 0.016162900295013865 + 0.016164729619802313 + 0.016166559003099903 + 0.016168388444914923 + 0.016170217945255593 + 0.016172047504130177 + 0.016173877121546915 + 0.016175706797514022 + 0.016177536532039731 + 0.016179366325132276 + 0.016181196176799865 + 0.016183026087050717 + 0.016184856055893027 + 0.016186686083334997 + 0.016188516169384857 + 0.016190346314050752 + 0.016192176517340881 + 0.016194006779263456 + 0.01619583709982661 + 0.016197667479038523 + 0.01619949791690739 + 0.016201328413441331 + 0.016203158968648525 + 0.016204989582537105 + 0.016206820255115238 + 0.016208650986391033 + 0.016210481776372646 + 0.016212312625068188 + 0.016214143532485799 + 0.016215974498633587 + 0.01621780552351967 + 0.016219636607152133 + 0.016221467749539101 + 0.016223298950688664 + 0.016225130210608923 + 0.016226961529307943 + 0.01622879290679383 + 0.016230624343074613 + 0.016232455838158428 + 0.016234287392053275 + 0.016236119004767277 + 0.016237950676308437 + 0.016239782406684833 + 0.016241614195904495 + 0.016243446043975471 + 0.016245277950905773 + 0.016247109916703476 + 0.016248941941376549 + 0.016250774024933048 + 0.016252606167380959 + 0.016254438368728325 + 0.016256270628983108 + 0.01625810294815332 + 0.016259935326246956 + 0.016261767763272025 + 0.016263600259236458 + 0.016265432814148276 + 0.016267265428015432 + 0.0162690981008459 + 0.016270930832647607 + 0.016272763623428558 + 0.016274596473196668 + 0.01627642938195991 + 0.016278262349726198 + 0.016280095376503462 + 0.016281928462299651 + 0.0162837616071227 + 0.016285594810980502 + 0.016287428073880981 + 0.016289261395832044 + 0.016291094776841594 + 0.016292928216917531 + 0.016294761716067745 + 0.016296595274300132 + 0.016298428891622571 + 0.016300262568042932 + 0.016302096303569096 + 0.016303930098208928 + 0.016305763951970288 + 0.01630759786486102 + 0.016309431836888995 + 0.016311265868062082 + 0.016313099958388064 + 0.016314934107874816 + 0.016316768316530155 + 0.016318602584361918 + 0.016320436911377922 + 0.016322271297585976 + 0.016324105742993894 + 0.016325940247609475 + 0.016327774811440529 + 0.016329609434494859 + 0.016331444116780235 + 0.016333278858304445 + 0.016335113659075255 + 0.016336948519100485 + 0.01633878343838787 + 0.016340618416945171 + 0.016342453454780158 + 0.016344288551900597 + 0.016346123708314196 + 0.016347958924028742 + 0.016349794199051946 + 0.016351629533391553 + 0.016353464927055281 + 0.016355300380050862 + 0.016357135892386025 + 0.016358971464068443 + 0.016360807095105869 + 0.016362642785505987 + 0.016364478535276467 + 0.016366314344425051 + 0.016368150212959402 + 0.016369986140887187 + 0.016371822128216102 + 0.016373658174953815 + 0.016375494281107988 + 0.016377330446686284 + 0.016379166671696362 + 0.016381002956145863 + 0.016382839300042452 + 0.016384675703393758 + 0.016386512166207418 + 0.016388348688491056 + 0.016390185270252301 + 0.016392021911498772 + 0.016393858612238108 + 0.016395695372477877 + 0.01639753219222571 + 0.016399369071489218 + 0.016401206010275966 + 0.016403043008593559 + 0.016404880066449586 + 0.01640671718385163 + 0.016408554360807247 + 0.01641039159732402 + 0.01641222889340951 + 0.016414066249071269 + 0.016415903664316868 + 0.016417741139153841 + 0.016419578673589747 + 0.016421416267632102 + 0.016423253921288457 + 0.016425091634566343 + 0.016426929407473274 + 0.016428767240016771 + 0.016430605132204342 + 0.016432443084043513 + 0.016434281095541781 + 0.016436119166706623 + 0.016437957297545557 + 0.016439795488066067 + 0.016441633738275629 + 0.016443472048181737 + 0.016445310417791827 + 0.016447148847113412 + 0.016448987336153909 + 0.016450825884920819 + 0.016452664493421573 + 0.016454503161663619 + 0.016456341889654405 + 0.016458180677401367 + 0.016460019524911929 + 0.016461858432193534 + 0.016463697399253598 + 0.016465536426099527 + 0.016467375512738754 + 0.016469214659178673 + 0.016471053865426678 + 0.016472893131490179 + 0.016474732457376576 + 0.016476571843093236 + 0.016478411288647559 + 0.016480250794046903 + 0.016482090359298651 + 0.016483929984410176 + 0.016485769669388837 + 0.016487609414241985 + 0.016489449218976961 + 0.01649128908360115 + 0.016493129008121835 + 0.016494968992546419 + 0.016496809036882176 + 0.016498649141136482 + 0.016500489305316623 + 0.016502329529429916 + 0.016504169813483703 + 0.016506010157485266 + 0.016507850561441901 + 0.016509691025360932 + 0.016511531549249628 + 0.016513372133115281 + 0.016515212776965164 + 0.016517053480806579 + 0.016518894244646781 + 0.016520735068493015 + 0.016522575952352594 + 0.016524416896232727 + 0.016526257900140687 + 0.016528098964083717 + 0.016529940088069059 + 0.016531781272103956 + 0.016533622516195622 + 0.016535463820351311 + 0.016537305184578216 + 0.016539146608883563 + 0.016540988093274579 + 0.016542829637758438 + 0.016544671242342369 + 0.016546512907033559 + 0.016548354631839214 + 0.016550196416766499 + 0.016552038261822607 + 0.016553880167014697 + 0.016555722132349966 + 0.016557564157835589 + 0.016559406243478684 + 0.016561248389286444 + 0.016563090595266002 + 0.016564932861424523 + 0.016566775187769139 + 0.016568617574306978 + 0.016570460021045192 + 0.016572302527990884 + 0.016574145095151191 + 0.016575987722533221 + 0.016577830410144104 + 0.016579673157990922 + 0.016581515966080793 + 0.016583358834420824 + 0.016585201763018094 + 0.016587044751879689 + 0.016588887801012666 + 0.016590730910424161 + 0.016592574080121186 + 0.016594417310110857 + 0.016596260600400221 + 0.016598103950996319 + 0.016599947361906193 + 0.016601790833136964 + 0.016603634364695585 + 0.016605477956589138 + 0.016607321608824655 + 0.016609165321409162 + 0.01661100909434968 + 0.016612852927653222 + 0.016614696821326793 + 0.016616540775377421 + 0.016618384789812094 + 0.016620228864637817 + 0.016622072999861588 + 0.0166239171954904 + 0.016625761451531208 + 0.016627605767991008 + 0.016629450144876785 + 0.016631294582195495 + 0.016633139079954107 + 0.016634983638159566 + 0.016636828256818847 + 0.016638672935938882 + 0.016640517675526607 + 0.016642362475589003 + 0.016644207336132952 + 0.016646052257165422 + 0.016647897238693317 + 0.016649742280723561 + 0.016651587383263073 + 0.016653432546318767 + 0.016655277769897513 + 0.016657123054006264 + 0.016658968398651858 + 0.01666081380384124 + 0.01666265926958127 + 0.016664504795878818 + 0.016666350382740776 + 0.016668196030174002 + 0.016670041738185364 + 0.016671887506781721 + 0.016673733335969942 + 0.016675579225756871 + 0.016677425176149341 + 0.016679271187154211 + 0.016681117258778314 + 0.016682963391028465 + 0.016684809583911487 + 0.016686655837434249 + 0.016688502151603529 + 0.016690348526426133 + 0.016692194961908869 + 0.016694041458058563 + 0.016695888014882001 + 0.016697734632385955 + 0.016699581310577232 + 0.016701428049462629 + 0.016703274849048873 + 0.0167051217093428 + 0.016706968630351118 + 0.016708815612080631 + 0.016710662654538081 + 0.016712509757730233 + 0.016714356921663818 + 0.016716204146345587 + 0.016718051431782281 + 0.016719898777980635 + 0.016721746184947359 + 0.016723593652689196 + 0.016725441181212868 + 0.016727288770525078 + 0.016729136420632524 + 0.016730984131541948 + 0.016732831903260019 + 0.016734679735793432 + 0.016736527629148876 + 0.016738375583333052 + 0.01674022359835264 + 0.0167420716742143 + 0.016743919810924712 + 0.016745768008490536 + 0.016747616266918425 + 0.016749464586215054 + 0.016751312966387061 + 0.016753161407441104 + 0.016755009909383809 + 0.01675685847222182 + 0.016758707095961764 + 0.016760555780610288 + 0.016762404526173971 + 0.01676425333265948 + 0.01676610220007339 + 0.016767951128422321 + 0.016769800117712882 + 0.016771649167951687 + 0.016773498279145281 + 0.016775347451300278 + 0.016777196684423269 + 0.016779045978520816 + 0.016780895333599506 + 0.016782744749665904 + 0.016784594226726571 + 0.016786443764788075 + 0.016788293363856944 + 0.01679014302393976 + 0.01679199274504305 + 0.016793842527173367 + 0.016795692370337231 + 0.01679754227454117 + 0.016799392239791721 + 0.016801242266095417 + 0.01680309235345873 + 0.016804942501888215 + 0.016806792711390357 + 0.016808642981971666 + 0.016810493313638618 + 0.016812343706397732 + 0.016814194160255487 + 0.016816044675218345 + 0.016817895251292809 + 0.016819745888485352 + 0.016821596586802413 + 0.016823447346250492 + 0.016825298166836009 + 0.016827149048565443 + 0.016828999991445239 + 0.016830850995481823 + 0.016832702060681663 + 0.016834553187051161 + 0.016836404374596773 + 0.016838255623324916 + 0.016840106933241995 + 0.016841958304354455 + 0.016843809736668672 + 0.016845661230191069 + 0.016847512784928048 + 0.016849364400886 + 0.016851216078071315 + 0.016853067816490385 + 0.016854919616149572 + 0.016856771477055284 + 0.016858623399213856 + 0.016860475382631707 + 0.016862327427315145 + 0.016864179533270553 + 0.01686603170050428 + 0.016867883929022678 + 0.01686973621883207 + 0.016871588569938822 + 0.016873440982349251 + 0.016875293456069702 + 0.016877145991106474 + 0.016878998587465905 + 0.016880851245154305 + 0.016882703964177997 + 0.016884556744543242 + 0.016886409586256385 + 0.016888262489323704 + 0.016890115453751502 + 0.016891968479546035 + 0.016893821566713606 + 0.016895674715260506 + 0.016897527925192977 + 0.01689938119651729 + 0.01690123452923973 + 0.016903087923366526 + 0.016904941378903953 + 0.016906794895858245 + 0.016908648474235653 + 0.016910502114042405 + 0.01691235581528475 + 0.016914209577968894 + 0.016916063402101087 + 0.016917917287687521 + 0.016919771234734447 + 0.016921625243248049 + 0.016923479313234516 + 0.01692533344470009 + 0.016927187637650942 + 0.016929041892093266 + 0.016930896208033262 + 0.016932750585477069 + 0.016934605024430907 + 0.016936459524900933 + 0.016938314086893305 + 0.016940168710414198 + 0.016942023395469765 + 0.016943878142066174 + 0.016945732950209545 + 0.016947587819906032 + 0.016949442751161791 + 0.016951297743982924 + 0.016953152798375608 + 0.01695500791434592 + 0.01695686309189998 + 0.016958718331043936 + 0.016960573631783882 + 0.016962428994125929 + 0.016964284418076184 + 0.016966139903640712 + 0.01696799545082563 + 0.016969851059637029 + 0.016971706730080978 + 0.016973562462163558 + 0.016975418255890846 + 0.016977274111268884 + 0.016979130028303781 + 0.016980986007001573 + 0.016982842047368309 + 0.016984698149410039 + 0.016986554313132795 + 0.016988410538542647 + 0.016990266825645611 + 0.016992123174447718 + 0.016993979584954994 + 0.016995836057173471 + 0.016997692591109146 + 0.016999549186768052 + 0.01700140584415618 + 0.017003262563279518 + 0.017005119344144101 + 0.017006976186755892 + 0.017008833091120897 + 0.017010690057245082 + 0.017012547085134444 + 0.017014404174794936 + 0.017016261326232542 + 0.017018118539453227 + 0.017019975814462931 + 0.017021833151267648 + 0.017023690549873301 + 0.017025548010285826 + 0.017027405532511183 + 0.017029263116555296 + 0.017031120762424117 + 0.017032978470123552 + 0.01703483623965954 + 0.017036694071037979 + 0.017038551964264789 + 0.017040409919345887 + 0.017042267936287162 + 0.017044126015094523 + 0.01704598415577388 + 0.017047842358331081 + 0.01704970062277205 + 0.017051558949102649 + 0.017053417337328767 + 0.017055275787456237 + 0.017057134299490968 + 0.017058992873438813 + 0.017060851509305603 + 0.017062710207097237 + 0.017064568966819516 + 0.017066427788478288 + 0.017068286672079418 + 0.017070145617628731 + 0.017072004625132038 + 0.017073863694595192 + 0.017075722826023976 + 0.017077582019424227 + 0.017079441274801769 + 0.017081300592162368 + 0.017083159971511868 + 0.017085019412856037 + 0.017086878916200678 + 0.017088738481551565 + 0.017090598108914501 + 0.017092457798295244 + 0.017094317549699586 + 0.017096177363133271 + 0.017098037238602069 + 0.017099897176111767 + 0.017101757175668073 + 0.017103617237276776 + 0.017105477360943616 + 0.01710733754667431 + 0.017109197794474618 + 0.017111058104350256 + 0.017112918476306953 + 0.017114778910350414 + 0.0171166394064864 + 0.017118499964720587 + 0.017120360585058707 + 0.017122221267506444 + 0.017124082012069497 + 0.017125942818753574 + 0.017127803687564346 + 0.017129664618507515 + 0.017131525611588753 + 0.01713338666681373 + 0.017135247784188127 + 0.0171371089637176 + 0.017138970205407823 + 0.017140831509264445 + 0.01714269287529312 + 0.017144554303499492 + 0.01714641579388921 + 0.017148277346467893 + 0.017150138961241207 + 0.017152000638214766 + 0.017153862377394191 + 0.017155724178785102 + 0.017157586042393119 + 0.017159447968223853 + 0.017161309956282903 + 0.017163172006575876 + 0.017165034119108372 + 0.017166896293885969 + 0.017168758530914263 + 0.017170620830198845 + 0.017172483191745289 + 0.017174345615559153 + 0.017176208101646027 + 0.017178070650011468 + 0.017179933260661029 + 0.017181795933600284 + 0.017183658668834759 + 0.017185521466370007 + 0.017187384326211579 + 0.017189247248365017 + 0.017191110232835836 + 0.01719297327962957 + 0.017194836388751741 + 0.017196699560207872 + 0.017198562794003471 + 0.017200426090144043 + 0.017202289448635114 + 0.017204152869482167 + 0.017206016352690697 + 0.017207879898266207 + 0.017209743506214153 + 0.01721160717654004 + 0.017213470909249348 + 0.017215334704347555 + 0.017217198561840109 + 0.01721906248173247 + 0.017220926464030124 + 0.017222790508738504 + 0.017224654615863064 + 0.017226518785409262 + 0.017228383017382519 + 0.017230247311788266 + 0.017232111668631946 + 0.017233976087919003 + 0.017235840569654815 + 0.017237705113844846 + 0.01723956972049448 + 0.017241434389609126 + 0.017243299121194211 + 0.017245163915255112 + 0.017247028771797221 + 0.017248893690825943 + 0.017250758672346655 + 0.01725262371636474 + 0.017254488822885571 + 0.017256353991914501 + 0.017258219223456956 + 0.017260084517518235 + 0.017261949874103719 + 0.017263815293218757 + 0.017265680774868734 + 0.017267546319058934 + 0.017269411925794738 + 0.017271277595081468 + 0.017273143326924447 + 0.017275009121329017 + 0.017276874978300487 + 0.017278740897844175 + 0.0172806068799654 + 0.017282472924669473 + 0.017284339031961683 + 0.017286205201847326 + 0.017288071434331708 + 0.01728993772942013 + 0.017291804087117842 + 0.017293670507430161 + 0.017295536990362324 + 0.017297403535919634 + 0.017299270144107343 + 0.017301136814930725 + 0.017303003548395028 + 0.017304870344505494 + 0.017306737203267399 + 0.017308604124685972 + 0.017310471108766434 + 0.017312338155514043 + 0.017314205264934022 + 0.017316072437031604 + 0.017317939671811999 + 0.01731980696928043 + 0.017321674329442104 + 0.017323541752302222 + 0.017325409237866001 + 0.017327276786138639 + 0.017329144397125334 + 0.017331012070831237 + 0.017332879807261566 + 0.017334747606421522 + 0.017336615468316229 + 0.017338483392950899 + 0.017340351380330681 + 0.017342219430460715 + 0.017344087543346213 + 0.017345955718992286 + 0.017347823957404088 + 0.017349692258586773 + 0.017351560622545479 + 0.017353429049285319 + 0.017355297538811463 + 0.017357166091129011 + 0.017359034706243084 + 0.017360903384158775 + 0.017362772124881257 + 0.017364640928415595 + 0.017366509794766897 + 0.017368378723940269 + 0.017370247715940798 + 0.01737211677077357 + 0.017373985888443688 + 0.017375855068956208 + 0.017377724312316222 + 0.017379593618528803 + 0.017381462987599003 + 0.017383332419531893 + 0.017385201914332543 + 0.017387071472005994 + 0.017388941092557269 + 0.017390810775991476 + 0.017392680522313578 + 0.017394550331528657 + 0.017396420203641759 + 0.017398290138657867 + 0.017400160136582032 + 0.017402030197419257 + 0.017403900321174545 + 0.017405770507852917 + 0.017407640757459392 + 0.01740951106999895 + 0.017411381445476576 + 0.017413251883897286 + 0.01741512238526605 + 0.017416992949587852 + 0.017418863576867675 + 0.017420734267110469 + 0.017422605020321225 + 0.017424475836504888 + 0.017426346715666438 + 0.017428217657810795 + 0.017430088662942947 + 0.017431959731067804 + 0.017433830862190344 + 0.017435702056315477 + 0.017437573313448147 + 0.017439444633593267 + 0.017441316016755748 + 0.017443187462940553 + 0.017445058972152559 + 0.01744693054439668 + 0.017448802179677821 + 0.017450673878000891 + 0.017452545639370785 + 0.017454417463792379 + 0.017456289351270585 + 0.01745816130181025 + 0.017460033315416276 + 0.017461905392093541 + 0.017463777531846893 + 0.017465649734681211 + 0.017467522000601338 + 0.01746939432961216 + 0.017471266721718493 + 0.017473139176925192 + 0.017475011695237127 + 0.01747688427665909 + 0.017478756921195954 + 0.017480629628852516 + 0.017482502399633608 + 0.017484375233544056 + 0.017486248130588685 + 0.017488121090772274 + 0.017489994114099659 + 0.017491867200575616 + 0.01749374035020497 + 0.017495613562992493 + 0.017497486838942963 + 0.017499360178061193 + 0.017501233580351942 + 0.017503107045819997 + 0.017504980574470096 + 0.01750685416630705 + 0.017508727821335595 + 0.01751060153956048 + 0.017512475320986477 + 0.01751434916561832 + 0.017516223073460731 + 0.017518097044518503 + 0.017519971078796326 + 0.017521845176298949 + 0.017523719337031098 + 0.01752559356099747 + 0.017527467848202805 + 0.017529342198651814 + 0.017531216612349198 + 0.017533091089299648 + 0.017534965629507886 + 0.017536840232978575 + 0.017538714899716441 + 0.017540589629726135 + 0.017542464423012352 + 0.017544339279579782 + 0.017546214199433093 + 0.017548089182576911 + 0.017549964229015953 + 0.017551839338754857 + 0.017553714511798268 + 0.017555589748150822 + 0.017557465047817199 + 0.017559340410802031 + 0.017561215837109935 + 0.017563091326745554 + 0.017564966879713508 + 0.017566842496018441 + 0.017568718175664952 + 0.017570593918657642 + 0.017572469725001146 + 0.017574345594700062 + 0.017576221527758992 + 0.017578097524182511 + 0.017579973583975228 + 0.017581849707141738 + 0.017583725893686595 + 0.017585602143614414 + 0.017587478456929737 + 0.01758935483363715 + 0.017591231273741216 + 0.017593107777246497 + 0.017594984344157533 + 0.017596860974478889 + 0.017598737668215104 + 0.017600614425370729 + 0.017602491245950296 + 0.017604368129958355 + 0.017606245077399406 + 0.017608122088277993 + 0.017609999162598627 + 0.017611876300365828 + 0.017613753501584117 + 0.017615630766257988 + 0.017617508094391936 + 0.017619385485990478 + 0.017621262941058081 + 0.017623140459599292 + 0.017625018041618531 + 0.017626895687120298 + 0.01762877339610909 + 0.017630651168589338 + 0.01763252900456555 + 0.01763440690404218 + 0.01763628486702367 + 0.01763816289351447 + 0.01764004098351905 + 0.017641919137041842 + 0.017643797354087304 + 0.017645675634659835 + 0.017647553978763896 + 0.017649432386403908 + 0.017651310857584302 + 0.017653189392309476 + 0.017655067990583861 + 0.017656946652411847 + 0.017658825377797869 + 0.017660704166746293 + 0.017662583019261553 + 0.017664461935348014 + 0.017666340915010056 + 0.017668219958252088 + 0.017670099065078472 + 0.017671978235493602 + 0.017673857469501796 + 0.017675736767107476 + 0.01767761612831497 + 0.017679495553128654 + 0.017681375041552875 + 0.017683254593591973 + 0.017685134209250285 + 0.017687013888532166 + 0.017688893631441948 + 0.017690773437983944 + 0.017692653308162502 + 0.017694533241981926 + 0.017696413239446557 + 0.017698293300560667 + 0.017700173425328584 + 0.017702053613754622 + 0.017703933865843079 + 0.017705814181598237 + 0.017707694561024372 + 0.017709575004125809 + 0.017711455510906807 + 0.017713336081371645 + 0.017715216715524573 + 0.017717097413369916 + 0.01771897817491188 + 0.017720859000154743 + 0.017722739889102772 + 0.017724620841760221 + 0.017726501858131301 + 0.017728382938220273 + 0.017730264082031402 + 0.017732145289568891 + 0.017734026560836967 + 0.017735907895839859 + 0.017737789294581797 + 0.017739670757066981 + 0.017741552283299621 + 0.017743433873283962 + 0.017745315527024144 + 0.017747197244524403 + 0.017749079025788934 + 0.017750960870821911 + 0.017752842779627524 + 0.017754724752209947 + 0.017756606788573371 + 0.017758488888721953 + 0.017760371052659867 + 0.017762253280391268 + 0.01776413557192031 + 0.017766017927251167 + 0.017767900346387984 + 0.01776978282933489 + 0.017771665376096028 + 0.017773547986675558 + 0.017775430661077573 + 0.017777313399306251 + 0.017779196201365668 + 0.017781079067259953 + 0.017782961996993231 + 0.017784844990569613 + 0.017786728048279792 + 0.017788611179684111 + 0.017790494389337486 + 0.017792377677237802 + 0.017794261043383008 + 0.017796144487771004 + 0.017798028010399689 + 0.017799911611267004 + 0.017801795290370816 + 0.017803679047709058 + 0.017805562883279627 + 0.017807446797080385 + 0.017809330789109259 + 0.017811214859364103 + 0.017813099007842816 + 0.017814983234543297 + 0.017816867539463394 + 0.017818751922601007 + 0.017820636383953956 + 0.017822520923520178 + 0.01782440554129747 + 0.017826290237283739 + 0.017828175011476832 + 0.017830059863874571 + 0.017831944794474856 + 0.017833829803275497 + 0.017835714890274353 + 0.017837600055469225 + 0.017839485298858013 + 0.017841370620438498 + 0.017843256020208545 + 0.017845141498165941 + 0.017847027054308542 + 0.017848912688634141 + 0.017850798401140597 + 0.017852684191825677 + 0.017854570060687188 + 0.017856456007722957 + 0.017858342032930772 + 0.017860228136308463 + 0.01786211431785379 + 0.017864000577564539 + 0.017865886915438521 + 0.017867773331473498 + 0.017869659825667294 + 0.017871546398017649 + 0.01787343304852235 + 0.017875319777179145 + 0.017877206583985856 + 0.017879093468940181 + 0.017880980432039922 + 0.017882867473282812 + 0.01788475459266663 + 0.017886641790189117 + 0.017888529065848018 + 0.017890416419641061 + 0.017892303851566004 + 0.017894191361620577 + 0.017896078949802545 + 0.017897966616109592 + 0.017899854360539459 + 0.017901742183089851 + 0.017903630083758518 + 0.017905518062543167 + 0.01790740611944153 + 0.017909294254451272 + 0.017911182467570126 + 0.017913070758795786 + 0.017914959128125955 + 0.017916847575558333 + 0.01791873610109062 + 0.017920624704720479 + 0.017922513386445595 + 0.017924402146263674 + 0.017926290984172387 + 0.017928179900169417 + 0.017930068894252409 + 0.017931957966419033 + 0.017933847116666995 + 0.017935736344993902 + 0.017937625651397438 + 0.017939515035875285 + 0.017941404498425028 + 0.017943294039044381 + 0.017945183657730946 + 0.017947073354482375 + 0.017948963129296312 + 0.017950852982170386 + 0.017952742913102209 + 0.017954632922089448 + 0.017956523009129706 + 0.017958413174220592 + 0.017960303417359737 + 0.01796219373854473 + 0.017964084137773225 + 0.017965974615042804 + 0.017967865170351056 + 0.017969755803695593 + 0.017971646515074012 + 0.017973537304483918 + 0.017975428171922884 + 0.017977319117388504 + 0.017979210140878353 + 0.01798110124239001 + 0.01798299242192106 + 0.017984883679469061 + 0.017986775015031591 + 0.01798866642860621 + 0.017990557920190494 + 0.017992449489781997 + 0.017994341137378241 + 0.01799623286297683 + 0.017998124666575285 + 0.018000016548171151 + 0.018001908507761961 + 0.018003800545345266 + 0.018005692660918615 + 0.018007584854479505 + 0.018009477126025481 + 0.018011369475554078 + 0.018013261903062776 + 0.018015154408549144 + 0.018017046992010677 + 0.01801893965344489 + 0.018020832392849257 + 0.018022725210221309 + 0.018024618105558551 + 0.018026511078858474 + 0.01802840413011856 + 0.0180302972593363 + 0.018032190466509206 + 0.01803408375163474 + 0.018035977114710382 + 0.018037870555733616 + 0.018039764074701901 + 0.01804165767161273 + 0.018043551346463543 + 0.018045445099251805 + 0.018047338929974996 + 0.018049232838630566 + 0.018051126825215931 + 0.018053020889728603 + 0.018054915032165973 + 0.018056809252525508 + 0.018058703550804644 + 0.018060597927000818 + 0.018062492381111437 + 0.018064386913133966 + 0.018066281523065806 + 0.018068176210904386 + 0.018070070976647132 + 0.018071965820291434 + 0.01807386074183474 + 0.018075755741274426 + 0.018077650818607901 + 0.018079545973832566 + 0.018081441206945832 + 0.018083336517945081 + 0.018085231906827707 + 0.018087127373591097 + 0.018089022918232636 + 0.018090918540749675 + 0.018092814241139669 + 0.018094710019399905 + 0.01809660587552778 + 0.018098501809520683 + 0.018100397821375958 + 0.018102293911090972 + 0.018104190078663082 + 0.018106086324089634 + 0.018107982647367966 + 0.018109879048495446 + 0.018111775527469405 + 0.018113672084287193 + 0.01811556871894613 + 0.018117465431443547 + 0.018119362221776781 + 0.018121259089943179 + 0.018123156035940023 + 0.01812505305976465 + 0.018126950161414385 + 0.018128847340886503 + 0.018130744598178334 + 0.018132641933287216 + 0.018134539346210423 + 0.018136436836945213 + 0.018138334405488944 + 0.018140232051838866 + 0.018142129775992291 + 0.018144027577946479 + 0.018145925457698716 + 0.018147823415246303 + 0.01814972145058651 + 0.018151619563716578 + 0.018153517754633784 + 0.018155416023335411 + 0.01815731436981869 + 0.018159212794080899 + 0.018161111296119289 + 0.018163009875931106 + 0.018164908533513605 + 0.018166807268864014 + 0.018168706081979551 + 0.018170604972857506 + 0.018172503941495079 + 0.018174402987889512 + 0.018176302112038016 + 0.018178201313937808 + 0.018180100593586115 + 0.01818199995098017 + 0.018183899386117183 + 0.018185798898994326 + 0.018187698489608838 + 0.018189598157957915 + 0.018191497904038741 + 0.018193397727848507 + 0.01819529762938445 + 0.018197197608643707 + 0.018199097665623481 + 0.018200997800320959 + 0.018202898012733289 + 0.018204798302857702 + 0.018206698670691308 + 0.018208599116231322 + 0.018210499639474863 + 0.018212400240419119 + 0.018214300919061253 + 0.018216201675398402 + 0.018218102509427708 + 0.018220003421146345 + 0.018221904410551444 + 0.018223805477640128 + 0.018225706622409559 + 0.018227607844856848 + 0.018229509144979145 + 0.018231410522773557 + 0.018233311978237219 + 0.018235213511367247 + 0.018237115122160755 + 0.018239016810614832 + 0.018240918576726634 + 0.018242820420493241 + 0.018244722341911754 + 0.018246624340979272 + 0.018248526417692895 + 0.018250428572049702 + 0.018252330804046795 + 0.018254233113681247 + 0.018256135500950156 + 0.018258037965850571 + 0.018259940508379601 + 0.018261843128534273 + 0.018263745826311708 + 0.018265648601708939 + 0.018267551454723023 + 0.018269454385351019 + 0.018271357393589989 + 0.018273260479436986 + 0.018275163642889045 + 0.018277066883943215 + 0.018278970202596521 + 0.018280873598846038 + 0.018282777072688754 + 0.018284680624121752 + 0.018286584253141985 + 0.018288487959746531 + 0.018290391743932391 + 0.018292295605696594 + 0.018294199545036121 + 0.018296103561948013 + 0.018298007656429263 + 0.018299911828476866 + 0.01830181607808784 + 0.018303720405259159 + 0.018305624809987812 + 0.018307529292270808 + 0.01830943385210515 + 0.018311338489487742 + 0.018313243204415627 + 0.018315147996885776 + 0.018317052866895153 + 0.018318957814440682 + 0.018320862839519392 + 0.018322767942128223 + 0.018324673122264105 + 0.018326578379924012 + 0.018328483715104885 + 0.018330389127803701 + 0.018332294618017386 + 0.018334200185742854 + 0.018336105830977063 + 0.018338011553716942 + 0.018339917353959425 + 0.01834182323170146 + 0.018343729186939928 + 0.018345635219671759 + 0.018347541329893878 + 0.018349447517603212 + 0.018351353782796637 + 0.018353260125471078 + 0.018355166545623421 + 0.018357073043250589 + 0.018358979618349466 + 0.018360886270916924 + 0.018362793000949888 + 0.018364699808445222 + 0.018366606693399783 + 0.018368513655810489 + 0.018370420695674208 + 0.018372327812987796 + 0.018374235007748128 + 0.018376142279952073 + 0.018378049629596476 + 0.018379957056678192 + 0.018381864561194079 + 0.01838377214314103 + 0.018385679802515827 + 0.018387587539315329 + 0.018389495353536404 + 0.01839140324517587 + 0.018393311214230563 + 0.018395219260697322 + 0.018397127384572942 + 0.018399035585854252 + 0.018400943864538097 + 0.018402852220621293 + 0.018404760654100606 + 0.0184066691649729 + 0.01840857775323497 + 0.018410486418883574 + 0.018412395161915573 + 0.018414303982327684 + 0.01841621288011679 + 0.018418121855279603 + 0.018420030907812936 + 0.018421940037713577 + 0.01842384924497829 + 0.018425758529603872 + 0.018427667891587077 + 0.018429577330924648 + 0.018431486847613403 + 0.018433396441650037 + 0.018435306113031368 + 0.018437215861754119 + 0.018439125687815042 + 0.018441035591210891 + 0.018442945571938405 + 0.018444855629994289 + 0.018446765765375343 + 0.018448675978078265 + 0.01845058626809977 + 0.018452496635436605 + 0.018454407080085482 + 0.018456317602043158 + 0.01845822820130627 + 0.018460138877871624 + 0.018462049631735832 + 0.018463960462895675 + 0.018465871371347805 + 0.018467782357088947 + 0.018469693420115788 + 0.018471604560425015 + 0.018473515778013344 + 0.018475427072877398 + 0.018477338445013904 + 0.018479249894419528 + 0.01848116142109096 + 0.018483073025024853 + 0.018484984706217868 + 0.018486896464666669 + 0.018488808300367931 + 0.018490720213318292 + 0.018492632203514416 + 0.018494544270952956 + 0.018496456415630556 + 0.018498368637543845 + 0.01850028093668947 + 0.018502193313064061 + 0.018504105766664277 + 0.018506018297486708 + 0.018507930905527999 + 0.018509843590784787 + 0.018511756353253663 + 0.018513669192931247 + 0.018515582109814153 + 0.01851749510389902 + 0.018519408175182397 + 0.0185213213236609 + 0.018523234549331156 + 0.018525147852189717 + 0.018527061232233206 + 0.018528974689458216 + 0.018530888223861303 + 0.01853280183543906 + 0.018534715524188054 + 0.018536629290104877 + 0.018538543133186057 + 0.018540457053428216 + 0.018542371050827892 + 0.018544285125381626 + 0.01854619927708601 + 0.018548113505937564 + 0.018550027811932861 + 0.018551942195068408 + 0.0185538566553408 + 0.018555771192746536 + 0.018557685807282166 + 0.018559600498944215 + 0.018561515267729204 + 0.018563430113633685 + 0.018565345036654163 + 0.018567260036787134 + 0.018569175114029158 + 0.018571090268376687 + 0.018573005499826281 + 0.018574920808374425 + 0.018576836194017603 + 0.018578751656752331 + 0.018580667196575116 + 0.018582582813482393 + 0.018584498507470692 + 0.018586414278536492 + 0.01858833012667627 + 0.018590246051886489 + 0.018592162054163641 + 0.018594078133504176 + 0.01859599428990456 + 0.018597910523361266 + 0.018599826833870757 + 0.01860174322142949 + 0.018603659686033881 + 0.018605576227680401 + 0.018607492846365519 + 0.018609409542085627 + 0.018611326314837199 + 0.018613243164616673 + 0.018615160091420446 + 0.018617077095244964 + 0.018618994176086638 + 0.018620911333941913 + 0.0186228285688072 + 0.018624745880678896 + 0.018626663269553402 + 0.018628580735427166 + 0.018630498278296551 + 0.018632415898157961 + 0.01863433359500782 + 0.018636251368842501 + 0.018638169219658371 + 0.018640087147451856 + 0.018642005152219296 + 0.018643923233957114 + 0.018645841392661656 + 0.018647759628329291 + 0.0186496779409564 + 0.018651596330539321 + 0.018653514797074465 + 0.018655433340558147 + 0.018657351960986727 + 0.018659270658356569 + 0.018661189432664021 + 0.018663108283905414 + 0.018665027212077072 + 0.018666946217175382 + 0.018668865299196612 + 0.018670784458137153 + 0.018672703693993292 + 0.018674623006761357 + 0.018676542396437679 + 0.018678461863018567 + 0.018680381406500319 + 0.018682301026879265 + 0.018684220724151695 + 0.018686140498313936 + 0.018688060349362236 + 0.018689980277292947 + 0.018691900282102322 + 0.018693820363786657 + 0.018695740522342224 + 0.018697660757765338 + 0.018699581070052249 + 0.01870150145919924 + 0.018703421925202579 + 0.018705342468058533 + 0.018707263087763343 + 0.018709183784313299 + 0.018711104557704659 + 0.018713025407933633 + 0.018714946334996527 + 0.018716867338889557 + 0.018718788419608955 + 0.018720709577150978 + 0.018722630811511862 + 0.018724552122687824 + 0.018726473510675089 + 0.018728394975469916 + 0.018730316517068482 + 0.018732238135467028 + 0.018734159830661751 + 0.018736081602648894 + 0.018738003451424644 + 0.01873992537698518 + 0.018741847379326756 + 0.018743769458445518 + 0.018745691614337697 + 0.018747613846999456 + 0.018749536156427 + 0.018751458542616471 + 0.018753381005564125 + 0.018755303545266052 + 0.018757226161718481 + 0.01875914885491756 + 0.018761071624859463 + 0.018762994471540343 + 0.018764917394956348 + 0.018766840395103668 + 0.018768763471978381 + 0.018770686625576724 + 0.018772609855894806 + 0.01877453316292875 + 0.018776456546674709 + 0.018778380007128802 + 0.018780303544287166 + 0.01878222715814595 + 0.018784150848701241 + 0.018786074615949191 + 0.018787998459885887 + 0.018789922380507442 + 0.018791846377809996 + 0.018793770451789617 + 0.018795694602442427 + 0.01879761882976454 + 0.018799543133752032 + 0.018801467514400982 + 0.018803391971707491 + 0.018805316505667663 + 0.018807241116277535 + 0.018809165803533204 + 0.018811090567430754 + 0.01881301540796626 + 0.018814940325135771 + 0.018816865318935356 + 0.018818790389361083 + 0.018820715536409002 + 0.018822640760075157 + 0.018824566060355607 + 0.018826491437246386 + 0.018828416890743556 + 0.018830342420843138 + 0.018832268027541177 + 0.018834193710833707 + 0.018836119470716728 + 0.018838045307186295 + 0.018839971220238436 + 0.018841897209869153 + 0.018843823276074447 + 0.018845749418850363 + 0.018847675638192861 + 0.018849601934097963 + 0.018851528306561692 + 0.018853454755580038 + 0.018855381281148956 + 0.01885730788326449 + 0.01885923456192258 + 0.018861161317119245 + 0.018863088148850436 + 0.01886501505711214 + 0.018866942041900318 + 0.018868869103210961 + 0.01887079624104003 + 0.018872723455383437 + 0.018874650746237221 + 0.018876578113597269 + 0.018878505557459558 + 0.018880433077820027 + 0.018882360674674643 + 0.018884288348019321 + 0.018886216097850021 + 0.018888143924162631 + 0.018890071826953129 + 0.018891999806217405 + 0.018893927861951407 + 0.018895855994151053 + 0.01889778420281225 + 0.018899712487930903 + 0.018901640849502917 + 0.018903569287524232 + 0.018905497801990696 + 0.018907426392898247 + 0.018909355060242761 + 0.01891128380402016 + 0.018913212624226274 + 0.018915141520857031 + 0.018917070493908301 + 0.018918999543375951 + 0.018920928669255873 + 0.018922857871543904 + 0.018924787150235933 + 0.018926716505327821 + 0.018928645936815421 + 0.01893057544469462 + 0.018932505028961207 + 0.018934434689611087 + 0.018936364426640078 + 0.018938294240044031 + 0.018940224129818755 + 0.018942154095960114 + 0.018944084138463966 + 0.018946014257326067 + 0.018947944452542283 + 0.018949874724108435 + 0.01895180507202035 + 0.018953735496273806 + 0.018955665996864633 + 0.018957596573788631 + 0.018959527227041612 + 0.018961457956619347 + 0.018963388762517682 + 0.018965319644732363 + 0.018967250603259184 + 0.01896918163809394 + 0.018971112749232421 + 0.018973043936670396 + 0.018974975200403643 + 0.018976906540427919 + 0.018978837956738992 + 0.018980769449332659 + 0.018982701018204623 + 0.018984632663350678 + 0.01898656438476657 + 0.01898849618244804 + 0.018990428056390837 + 0.018992360006590714 + 0.018994292033043408 + 0.018996224135744647 + 0.018998156314690158 + 0.01900008856987568 + 0.019002020901296914 + 0.019003953308949616 + 0.019005885792829483 + 0.019007818352932224 + 0.01900975098925356 + 0.01901168370178918 + 0.019013616490534811 + 0.019015549355486144 + 0.019017482296638872 + 0.019019415313988684 + 0.019021348407531277 + 0.019023281577262321 + 0.019025214823177514 + 0.019027148145272538 + 0.019029081543543058 + 0.019031015017984737 + 0.01903294856859325 + 0.019034882195364269 + 0.019036815898293435 + 0.019038749677376409 + 0.019040683532608883 + 0.019042617463986455 + 0.019044551471504807 + 0.019046485555159549 + 0.019048419714946349 + 0.01905035395086082 + 0.019052288262898617 + 0.019054222651055337 + 0.019056157115326627 + 0.019058091655708122 + 0.019060026272195427 + 0.019061960964784137 + 0.019063895733469866 + 0.019065830578248257 + 0.019067765499114892 + 0.01906970049606534 + 0.019071635569095257 + 0.019073570718200174 + 0.019075505943375731 + 0.019077441244617469 + 0.01907937662192102 + 0.019081312075281923 + 0.01908324760469577 + 0.01908518321015814 + 0.019087118891664558 + 0.019089054649210641 + 0.019090990482791916 + 0.019092926392403974 + 0.019094862378042341 + 0.019096798439702554 + 0.019098734577380202 + 0.019100670791070785 + 0.019102607080769857 + 0.019104543446472989 + 0.019106479888175657 + 0.019108416405873421 + 0.019110352999561799 + 0.019112289669236317 + 0.019114226414892483 + 0.019116163236525811 + 0.019118100134131844 + 0.019120037107706048 + 0.019121974157243916 + 0.019123911282741001 + 0.01912584848419278 + 0.019127785761594719 + 0.019129723114942342 + 0.019131660544231113 + 0.019133598049456507 + 0.019135535630614018 + 0.019137473287699144 + 0.01913941102070733 + 0.019141348829633999 + 0.019143286714474697 + 0.019145224675224844 + 0.019147162711879901 + 0.01914910082443531 + 0.019151039012886537 + 0.019152977277229036 + 0.019154915617458256 + 0.019156854033569579 + 0.01915879252555849 + 0.019160731093420421 + 0.019162669737150799 + 0.01916460845674502 + 0.019166547252198535 + 0.019168486123506748 + 0.019170425070665093 + 0.019172364093668952 + 0.019174303192513724 + 0.019176242367194875 + 0.019178181617707745 + 0.019180120944047752 + 0.019182060346210263 + 0.019183999824190712 + 0.019185939377984459 + 0.019187879007586877 + 0.019189818712993356 + 0.019191758494199289 + 0.019193698351199995 + 0.019195638283990905 + 0.019197578292567352 + 0.019199518376924688 + 0.019201458537058281 + 0.019203398772963468 + 0.019205339084635627 + 0.019207279472070075 + 0.019209219935262187 + 0.019211160474207269 + 0.019213101088900678 + 0.019215041779337742 + 0.01921698254551378 + 0.01921892338742413 + 0.019220864305064086 + 0.019222805298429003 + 0.019224746367514173 + 0.019226687512314888 + 0.019228628732826498 + 0.019230570029044276 + 0.01923251140096351 + 0.019234452848579539 + 0.019236394371887615 + 0.019238335970883026 + 0.019240277645561101 + 0.019242219395917089 + 0.019244161221946242 + 0.019246103123643891 + 0.019248045101005268 + 0.019249987154025656 + 0.019251929282700288 + 0.019253871487024492 + 0.019255813766993434 + 0.019257756122602429 + 0.019259698553846717 + 0.019261641060721535 + 0.019263583643222119 + 0.019265526301343715 + 0.019267469035081537 + 0.019269411844430855 + 0.019271354729386875 + 0.019273297689944797 + 0.019275240726099901 + 0.019277183837847343 + 0.019279127025182353 + 0.01928107028810017 + 0.019283013626595957 + 0.019284957040664963 + 0.019286900530302332 + 0.019288844095503289 + 0.019290787736263033 + 0.01929273145257673 + 0.01929467524443956 + 0.019296619111846745 + 0.019298563054793418 + 0.019300507073274766 + 0.019302451167285972 + 0.019304395336822166 + 0.019306339581878548 + 0.019308283902450266 + 0.019310228298532479 + 0.019312172770120331 + 0.019314117317208963 + 0.019316061939793513 + 0.019318006637869142 + 0.019319951411430988 + 0.019321896260474168 + 0.019323841184993831 + 0.019325786184985077 + 0.019327731260443032 + 0.019329676411362844 + 0.019331621637739608 + 0.019333566939568437 + 0.019335512316844428 + 0.01933745776956269 + 0.019339403297718345 + 0.019341348901306482 + 0.019343294580322187 + 0.019345240334760545 + 0.019347186164616618 + 0.019349132069885533 + 0.019351078050562368 + 0.019353024106642188 + 0.019354970238120044 + 0.019356916444991025 + 0.019358862727250185 + 0.019360809084892596 + 0.019362755517913326 + 0.019364702026307388 + 0.019366648610069877 + 0.0193685952691958 + 0.019370542003680231 + 0.019372488813518187 + 0.019374435698704708 + 0.019376382659234841 + 0.019378329695103606 + 0.019380276806305993 + 0.01938222399283708 + 0.019384171254691877 + 0.019386118591865346 + 0.019388066004352545 + 0.019390013492148479 + 0.019391961055248118 + 0.019393908693646478 + 0.019395856407338562 + 0.019397804196319344 + 0.019399752060583846 + 0.019401700000127028 + 0.019403648014943861 + 0.01940559610502934 + 0.01940754427037843 + 0.019409492510986125 + 0.019411440826847339 + 0.019413389217957069 + 0.019415337684310304 + 0.019417286225901925 + 0.019419234842726962 + 0.019421183534780305 + 0.01942313230205692 + 0.019425081144551739 + 0.019427030062259727 + 0.019428979055175797 + 0.019430928123294857 + 0.019432877266611866 + 0.01943482648512174 + 0.019436775778819408 + 0.019438725147699724 + 0.019440674591757693 + 0.019442624110988165 + 0.019444573705386044 + 0.019446523374946258 + 0.019448473119663676 + 0.019450422939533214 + 0.019452372834549748 + 0.019454322804708161 + 0.019456272850003339 + 0.019458222970430164 + 0.01946017316598353 + 0.01946212343665828 + 0.019464073782449277 + 0.019466024203351411 + 0.019467974699359528 + 0.019469925270468487 + 0.019471875916673147 + 0.019473826637968334 + 0.019475777434348918 + 0.019477728305809731 + 0.019479679252345641 + 0.019481630273951427 + 0.019483581370621963 + 0.019485532542352066 + 0.019487483789136548 + 0.01948943511097025 + 0.019491386507847958 + 0.019493337979764505 + 0.019495289526714709 + 0.019497241148693386 + 0.019499192845695276 + 0.019501144617715259 + 0.01950309646474805 + 0.019505048386788491 + 0.019507000383831356 + 0.019508952455871455 + 0.019510904602903504 + 0.019512856824922337 + 0.019514809121922706 + 0.01951676149389938 + 0.019518713940847116 + 0.019520666462760673 + 0.019522619059634847 + 0.019524571731464359 + 0.019526524478243962 + 0.019528477299968396 + 0.01953043019663242 + 0.019532383168230784 + 0.019534336214758204 + 0.019536289336209395 + 0.019538242532579127 + 0.019540195803862098 + 0.019542149150053024 + 0.019544102571146641 + 0.019546056067137652 + 0.019548009638020784 + 0.019549963283790713 + 0.019551917004442171 + 0.019553870799969824 + 0.019555824670368406 + 0.019557778615632581 + 0.019559732635757058 + 0.019561686730736501 + 0.019563640900565598 + 0.019565595145239031 + 0.019567549464751463 + 0.019569503859097569 + 0.019571458328272031 + 0.019573412872269449 + 0.019575367491084586 + 0.019577322184712014 + 0.019579276953146388 + 0.019581231796382402 + 0.019583186714414686 + 0.019585141707237835 + 0.019587096774846546 + 0.019589051917235395 + 0.019591007134399058 + 0.019592962426332145 + 0.01959491779302925 + 0.019596873234485054 + 0.019598828750694099 + 0.019600784341651033 + 0.019602740007350478 + 0.019604695747787011 + 0.019606651562955241 + 0.019608607452849744 + 0.019610563417465143 + 0.019612519456795999 + 0.019614475570836939 + 0.019616431759582505 + 0.019618388023027268 + 0.019620344361165821 + 0.019622300773992733 + 0.019624257261502565 + 0.019626213823689891 + 0.019628170460549252 + 0.019630127172075226 + 0.019632083958262339 + 0.019634040819105154 + 0.019635997754598199 + 0.019637954764736024 + 0.019639911849513192 + 0.019641869008924184 + 0.019643826242963579 + 0.019645783551625853 + 0.01964774093490557 + 0.019649698392797219 + 0.019651655925295341 + 0.019653613532394431 + 0.019655571214089007 + 0.019657528970373535 + 0.019659486801242576 + 0.019661444706690557 + 0.019663402686712024 + 0.019665360741301444 + 0.01966731887045331 + 0.019669277074162078 + 0.019671235352422246 + 0.019673193705228298 + 0.019675152132574699 + 0.019677110634455885 + 0.019679069210866346 + 0.019681027861800537 + 0.019682986587252892 + 0.019684945387217889 + 0.019686904261689973 + 0.019688863210663585 + 0.019690822234133171 + 0.019692781332093116 + 0.019694740504537941 + 0.019696699751461995 + 0.019698659072859753 + 0.019700618468725624 + 0.019702577939054 + 0.0197045374838393 + 0.019706497103075996 + 0.019708456796758405 + 0.019710416564881001 + 0.019712376407438139 + 0.019714336324424236 + 0.019716296315833673 + 0.019718256381660845 + 0.019720216521900136 + 0.019722176736545912 + 0.019724137025592565 + 0.019726097389034476 + 0.019728057826865986 + 0.01973001833908147 + 0.019731978925675325 + 0.019733939586641845 + 0.01973590032197545 + 0.019737861131670441 + 0.019739822015721189 + 0.019741782974122022 + 0.019743744006867299 + 0.019745705113951344 + 0.019747666295368466 + 0.019749627551113043 + 0.019751588881179376 + 0.019753550285561753 + 0.019755511764254535 + 0.019757473317252031 + 0.019759434944548522 + 0.019761396646138331 + 0.019763358422015778 + 0.019765320272175129 + 0.01976728219661068 + 0.01976924419531674 + 0.019771206268287614 + 0.019773168415517545 + 0.019775130637000815 + 0.019777092932731721 + 0.019779055302704518 + 0.019781017746913508 + 0.019782980265352905 + 0.019784942858017004 + 0.019786905524900048 + 0.019788868265996306 + 0.019790831081300003 + 0.01979279397080539 + 0.019794756934506743 + 0.019796719972398253 + 0.019798683084474179 + 0.019800646270728743 + 0.019802609531156177 + 0.019804572865750703 + 0.019806536274506528 + 0.019808499757417896 + 0.019810463314478988 + 0.019812426945684049 + 0.01981439065102723 + 0.019816354430502784 + 0.01981831828410488 + 0.019820282211827731 + 0.01982224621366549 + 0.019824210289612374 + 0.019826174439662562 + 0.019828138663810196 + 0.019830102962049515 + 0.019832067334374627 + 0.019834031780779752 + 0.019835996301259005 + 0.019837960895806563 + 0.019839925564416581 + 0.019841890307083217 + 0.019843855123800647 + 0.019845820014562952 + 0.019847784979364326 + 0.019849750018198851 + 0.019851715131060703 + 0.019853680317944006 + 0.019855645578842875 + 0.019857610913751447 + 0.01985957632266383 + 0.019861541805574111 + 0.019863507362476451 + 0.019865472993364917 + 0.019867438698233635 + 0.019869404477076684 + 0.019871370329888158 + 0.019873336256662166 + 0.019875302257392809 + 0.019877268332074118 + 0.019879234480700218 + 0.01988120070326517 + 0.019883166999763044 + 0.019885133370187932 + 0.019887099814533845 + 0.019889066332794896 + 0.019891032924965121 + 0.019892999591038584 + 0.01989496633100931 + 0.019896933144871374 + 0.019898900032618797 + 0.019900866994245626 + 0.019902834029745894 + 0.019904801139113637 + 0.01990676832234289 + 0.019908735579427635 + 0.019910702910361941 + 0.019912670315139783 + 0.019914637793755199 + 0.019916605346202196 + 0.019918572972474756 + 0.019920540672566895 + 0.019922508446472621 + 0.019924476294185922 + 0.019926444215700757 + 0.019928412211011149 + 0.019930380280111053 + 0.019932348422994454 + 0.019934316639655336 + 0.019936284930087658 + 0.019938253294285384 + 0.019940221732242493 + 0.019942190243952929 + 0.019944158829410641 + 0.019946127488609602 + 0.019948096221543737 + 0.019950065028206999 + 0.019952033908593337 + 0.019954002862696645 + 0.019955971890510911 + 0.019957940992030031 + 0.019959910167247928 + 0.019961879416158543 + 0.019963848738755775 + 0.019965818135033536 + 0.019967787604985746 + 0.019969757148606302 + 0.019971726765889097 + 0.019973696456828064 + 0.019975666221417047 + 0.019977636059649962 + 0.019979605971520712 + 0.01998157595702315 + 0.019983546016151158 + 0.019985516148898621 + 0.019987486355259425 + 0.019989456635227384 + 0.019991426988796426 + 0.019993397415960363 + 0.01999536791671308 + 0.019997338491048403 + 0.019999309138960201 + 0.020001279860442311 + 0.020003250655488563 + 0.020005221524092807 + 0.020007192466248869 + 0.02000916348195058 + 0.020011134571191774 + 0.020013105733966249 + 0.020015076970267845 + 0.020017048280090356 + 0.020019019663427607 + 0.020020991120273394 + 0.020022962650621534 + 0.020024934254465811 + 0.020026905931800006 + 0.020028877682617945 + 0.020030849506913397 + 0.020032821404680129 + 0.020034793375911953 + 0.020036765420602606 + 0.020038737538745882 + 0.020040709730335539 + 0.02004268199536537 + 0.020044654333829098 + 0.02004662674572048 + 0.020048599231033283 + 0.020050571789761263 + 0.020052544421898161 + 0.020054517127437683 + 0.020056489906373612 + 0.020058462758699658 + 0.020060435684409537 + 0.020062408683497009 + 0.020064381755955776 + 0.020066354901779552 + 0.02006832812096206 + 0.020070301413497006 + 0.02007227477937808 + 0.020074248218599013 + 0.020076221731153487 + 0.020078195317035172 + 0.020080168976237808 + 0.020082142708755042 + 0.020084116514580599 + 0.020086090393708102 + 0.020088064346131276 + 0.020090038371843765 + 0.020092012470839232 + 0.02009398664311135 + 0.02009596088865381 + 0.02009793520746021 + 0.020099909599524242 + 0.020101884064839523 + 0.020103858603399735 + 0.020105833215198494 + 0.020107807900229448 + 0.020109782658486203 + 0.020111757489962419 + 0.02011373239465172 + 0.020115707372547705 + 0.020117682423643996 + 0.020119657547934228 + 0.020121632745411983 + 0.020123608016070882 + 0.020125583359904515 + 0.020127558776906512 + 0.020129534267070429 + 0.020131509830389867 + 0.020133485466858406 + 0.020135461176469655 + 0.020137436959217166 + 0.020139412815094539 + 0.020141388744095306 + 0.020143364746213064 + 0.020145340821441361 + 0.020147316969773781 + 0.020149293191203847 + 0.020151269485725119 + 0.020153245853331156 + 0.020155222294015486 + 0.020157198807771674 + 0.020159175394593241 + 0.020161152054473698 + 0.020163128787406604 + 0.020165105593385465 + 0.020167082472403817 + 0.020169059424455165 + 0.020171036449533011 + 0.020173013547630889 + 0.020174990718742264 + 0.020176967962860694 + 0.020178945279979637 + 0.020180922670092603 + 0.02018290013319304 + 0.020184877669274497 + 0.020186855278330394 + 0.020188832960354262 + 0.020190810715339541 + 0.020192788543279716 + 0.020194766444168233 + 0.020196744417998583 + 0.020198722464764198 + 0.020200700584458543 + 0.020202678777075069 + 0.020204657042607228 + 0.020206635381048436 + 0.020208613792392166 + 0.020210592276631838 + 0.020212570833760882 + 0.02021454946377272 + 0.020216528166660773 + 0.020218506942418463 + 0.02022048579103922 + 0.020222464712516427 + 0.020224443706843526 + 0.020226422774013889 + 0.020228401914020935 + 0.020230381126858047 + 0.020232360412518628 + 0.020234339770996042 + 0.02023631920228371 + 0.020238298706374992 + 0.02024027828326324 + 0.020242257932941866 + 0.020244237655404229 + 0.020246217450643676 + 0.020248197318653571 + 0.02025017725942729 + 0.020252157272958152 + 0.020254137359239543 + 0.020256117518264775 + 0.020258097750027227 + 0.020260078054520188 + 0.020262058431737031 + 0.020264038881671057 + 0.020266019404315598 + 0.020267999999663985 + 0.020269980667709527 + 0.020271961408445539 + 0.020273942221865342 + 0.020275923107962238 + 0.020277904066729496 + 0.020279885098160449 + 0.020281866202248373 + 0.020283847378986575 + 0.020285828628368318 + 0.020287809950386898 + 0.020289791345035588 + 0.020291772812307672 + 0.020293754352196405 + 0.020295735964695062 + 0.0202977176497969 + 0.020299699407495167 + 0.020301681237783156 + 0.020303663140654071 + 0.020305645116101199 + 0.020307627164117728 + 0.020309609284696963 + 0.020311591477832094 + 0.020313573743516351 + 0.020315556081742979 + 0.020317538492505196 + 0.020319520975796222 + 0.020321503531609261 + 0.020323486159937544 + 0.02032546886077426 + 0.020327451634112599 + 0.020329434479945785 + 0.020331417398267007 + 0.020333400389069473 + 0.020335383452346329 + 0.020337366588090787 + 0.020339349796296018 + 0.020341333076955192 + 0.020343316430061514 + 0.020345299855608092 + 0.020347283353588128 + 0.020349266923994788 + 0.020351250566821209 + 0.02035323428206055 + 0.020355218069705947 + 0.02035720192975056 + 0.020359185862187528 + 0.020361169867009962 + 0.02036315394421102 + 0.020365138093783819 + 0.020367122315721499 + 0.020369106610017139 + 0.02037109097666389 + 0.020373075415654869 + 0.020375059926983158 + 0.020377044510641873 + 0.020379029166624117 + 0.020381013894922976 + 0.020382998695531559 + 0.02038498356844293 + 0.020386968513650197 + 0.020388953531146427 + 0.020390938620924701 + 0.020392923782978065 + 0.02039490901729963 + 0.020396894323882451 + 0.020398879702719554 + 0.020400865153804026 + 0.020402850677128912 + 0.020404836272687268 + 0.020406821940472129 + 0.020408807680476534 + 0.020410793492693511 + 0.020412779377116105 + 0.020414765333737352 + 0.020416751362550271 + 0.020418737463547856 + 0.020420723636723141 + 0.020422709882069165 + 0.020424696199578905 + 0.020426682589245369 + 0.020428669051061565 + 0.020430655585020475 + 0.020432642191115118 + 0.020434628869338462 + 0.020436615619683501 + 0.020438602442143194 + 0.020440589336710547 + 0.020442576303378507 + 0.020444563342140083 + 0.020446550452988176 + 0.020448537635915792 + 0.020450524890915873 + 0.020452512217981379 + 0.020454499617105253 + 0.020456487088280441 + 0.020458474631499888 + 0.02046046224675652 + 0.020462449934043277 + 0.020464437693353078 + 0.020466425524678859 + 0.020468413428013529 + 0.020470401403350016 + 0.020472389450681219 + 0.020474377570000056 + 0.020476365761299433 + 0.020478354024572234 + 0.020480342359811381 + 0.020482330767009751 + 0.020484319246160228 + 0.020486307797255708 + 0.020488296420289043 + 0.020490285115253158 + 0.020492273882140876 + 0.020494262720945101 + 0.020496251631658698 + 0.020498240614274486 + 0.020500229668785359 + 0.020502218795184161 + 0.020504207993463721 + 0.020506197263616899 + 0.020508186605636528 + 0.020510176019515471 + 0.020512165505246531 + 0.020514155062822535 + 0.020516144692236331 + 0.02051813439348071 + 0.020520124166548501 + 0.020522114011432516 + 0.020524103928125557 + 0.020526093916620448 + 0.020528083976909951 + 0.020530074108986884 + 0.020532064312844062 + 0.020534054588474231 + 0.020536044935870187 + 0.020538035355024725 + 0.020540025845930603 + 0.020542016408580603 + 0.020544007042967494 + 0.020545997749084013 + 0.020547988526922956 + 0.020549979376477057 + 0.020551970297739069 + 0.02055396129070175 + 0.020555952355357825 + 0.020557943491700047 + 0.020559934699721144 + 0.020561925979413836 + 0.020563917330770884 + 0.020565908753784983 + 0.020567900248448845 + 0.020569891814755218 + 0.020571883452696789 + 0.020573875162266254 + 0.020575866943456332 + 0.020577858796259719 + 0.020579850720669108 + 0.020581842716677196 + 0.020583834784276653 + 0.020585826923460185 + 0.020587819134220451 + 0.020589811416550134 + 0.020591803770441879 + 0.020593796195888404 + 0.020595788692882314 + 0.020597781261416308 + 0.020599773901483015 + 0.020601766613075105 + 0.020603759396185202 + 0.020605752250805954 + 0.020607745176930006 + 0.020609738174549985 + 0.020611731243658539 + 0.020613724384248269 + 0.020615717596311783 + 0.020617710879841752 + 0.02061970423483072 + 0.020621697661271358 + 0.020623691159156243 + 0.02062568472847796 + 0.020627678369229133 + 0.020629672081402348 + 0.020631665864990177 + 0.020633659719985212 + 0.020635653646380075 + 0.020637647644167267 + 0.020639641713339412 + 0.020641635853889069 + 0.020643630065808806 + 0.020645624349091157 + 0.020647618703728686 + 0.020649613129713952 + 0.020651607627039527 + 0.020653602195697923 + 0.020655596835681678 + 0.020657591546983343 + 0.020659586329595445 + 0.020661581183510507 + 0.020663576108721046 + 0.020665571105219601 + 0.020667566172998662 + 0.020669561312050763 + 0.020671556522368399 + 0.020673551803944069 + 0.02067554715677028 + 0.020677542580839519 + 0.020679538076144272 + 0.020681533642677042 + 0.020683529280430293 + 0.020685524989396527 + 0.020687520769568181 + 0.020689516620937765 + 0.0206915125434977 + 0.020693508537240481 + 0.020695504602158563 + 0.020697500738244376 + 0.020699496945490396 + 0.020701493223889061 + 0.0207034895734328 + 0.020705485994114068 + 0.020707482485925275 + 0.020709479048858871 + 0.020711475682907269 + 0.020713472388062884 + 0.02071546916431815 + 0.02071746601166545 + 0.020719462930097209 + 0.02072145991960584 + 0.020723456980183727 + 0.020725454111823301 + 0.020727451314516889 + 0.02072944858825693 + 0.020731445933035803 + 0.020733443348845849 + 0.020735440835679485 + 0.020737438393529067 + 0.020739436022386943 + 0.020741433722245496 + 0.020743431493097073 + 0.020745429334934042 + 0.020747427247748758 + 0.020749425231533537 + 0.020751423286280737 + 0.020753421411982716 + 0.020755419608631795 + 0.02075741787622026 + 0.020759416214740496 + 0.0207614146241848 + 0.020763413104545492 + 0.020765411655814858 + 0.020767410277985253 + 0.020769408971048946 + 0.020771407734998266 + 0.020773406569825483 + 0.02077540547552291 + 0.020777404452082798 + 0.02077940349949747 + 0.020781402617759202 + 0.020783401806860238 + 0.020785401066792889 + 0.020787400397549394 + 0.020789399799122019 + 0.02079139927150303 + 0.020793398814684692 + 0.020795398428659222 + 0.020797398113418915 + 0.02079939786895596 + 0.020801397695262638 + 0.020803397592331158 + 0.020805397560153732 + 0.020807397598722636 + 0.020809397708030048 + 0.020811397888068218 + 0.020813398138829351 + 0.020815398460305615 + 0.020817398852489274 + 0.020819399315372498 + 0.020821399848947469 + 0.020823400453206391 + 0.020825401128141467 + 0.020827401873744877 + 0.020829402690008776 + 0.02083140357692537 + 0.020833404534486816 + 0.020835405562685282 + 0.020837406661512924 + 0.020839407830961897 + 0.020841409071024365 + 0.020843410381692493 + 0.020845411762958406 + 0.020847413214814248 + 0.020849414737252166 + 0.020851416330264282 + 0.020853417993842719 + 0.020855419727979621 + 0.020857421532667106 + 0.02085942340789728 + 0.020861425353662269 + 0.020863427369954158 + 0.020865429456765085 + 0.020867431614087117 + 0.020869433841912359 + 0.020871436140232919 + 0.02087343850904087 + 0.020875440948328279 + 0.020877443458087255 + 0.020879446038309855 + 0.020881448688988169 + 0.020883451410114235 + 0.020885454201680122 + 0.020887457063677905 + 0.020889459996099619 + 0.020891462998937328 + 0.020893466072183061 + 0.020895469215828872 + 0.020897472429866799 + 0.020899475714288875 + 0.020901479069087101 + 0.020903482494253521 + 0.020905485989780176 + 0.020907489555659041 + 0.020909493191882154 + 0.020911496898441531 + 0.020913500675329138 + 0.020915504522537008 + 0.020917508440057103 + 0.020919512427881457 + 0.020921516486002014 + 0.020923520614410791 + 0.020925524813099741 + 0.020927529082060827 + 0.020929533421286048 + 0.020931537830767368 + 0.020933542310496722 + 0.020935546860466069 + 0.0209375514806674 + 0.020939556171092614 + 0.020941560931733685 + 0.02094356576258254 + 0.020945570663631115 + 0.020947575634871343 + 0.020949580676295158 + 0.020951585787894463 + 0.02095359096966121 + 0.020955596221587276 + 0.020957601543664578 + 0.020959606935885031 + 0.020961612398240553 + 0.020963617930723006 + 0.020965623533324321 + 0.020967629206036353 + 0.020969634948850992 + 0.02097164076176012 + 0.020973646644755629 + 0.020975652597829363 + 0.020977658620973227 + 0.020979664714179041 + 0.020981670877438695 + 0.020983677110744038 + 0.020985683414086895 + 0.020987689787459154 + 0.02098969623085261 + 0.020991702744259141 + 0.02099370932767056 + 0.020995715981078696 + 0.020997722704475374 + 0.020999729497852421 + 0.021001736361201655 + 0.02100374329451488 + 0.021005750297783891 + 0.021007757371000527 + 0.021009764514156558 + 0.021011771727243771 + 0.021013779010253988 + 0.021015786363178971 + 0.021017793786010514 + 0.021019801278740396 + 0.021021808841360377 + 0.021023816473862228 + 0.021025824176237728 + 0.021027831948478622 + 0.021029839790576675 + 0.021031847702523625 + 0.021033855684311247 + 0.021035863735931266 + 0.021037871857375424 + 0.02103988004863545 + 0.021041888309703081 + 0.021043896640570037 + 0.021045905041228045 + 0.021047913511668809 + 0.021049922051884069 + 0.021051930661865524 + 0.021053939341604856 + 0.02105594809109379 + 0.021057956910324041 + 0.021059965799287251 + 0.021061974757975135 + 0.021063983786379369 + 0.021065992884491624 + 0.021068002052303619 + 0.021070011289806973 + 0.021072020596993361 + 0.02107402997385447 + 0.021076039420381922 + 0.021078048936567419 + 0.021080058522402551 + 0.021082068177879006 + 0.021084077902988392 + 0.021086087697722387 + 0.02108809756207258 + 0.021090107496030609 + 0.021092117499588104 + 0.021094127572736685 + 0.021096137715467967 + 0.021098147927773554 + 0.021100158209645063 + 0.021102168561074063 + 0.021104178982052191 + 0.021106189472571014 + 0.021108200032622128 + 0.021110210662197128 + 0.02111222136128757 + 0.021114232129885037 + 0.021116242967981112 + 0.021118253875567358 + 0.02112026485263533 + 0.021122275899176573 + 0.021124287015182673 + 0.021126298200645148 + 0.02112830945555556 + 0.021130320779905443 + 0.021132332173686357 + 0.021134343636889794 + 0.02113635516950731 + 0.021138366771530418 + 0.021140378442950632 + 0.021142390183759477 + 0.021144401993948445 + 0.021146413873509063 + 0.021148425822432825 + 0.02115043784071122 + 0.021152449928335759 + 0.021154462085297889 + 0.021156474311589159 + 0.021158486607201002 + 0.021160498972124891 + 0.021162511406352304 + 0.021164523909874739 + 0.021166536482683618 + 0.021168549124770432 + 0.021170561836126599 + 0.021172574616743583 + 0.021174587466612833 + 0.021176600385725788 + 0.021178613374073882 + 0.021180626431648541 + 0.021182639558441203 + 0.02118465275444328 + 0.021186666019646208 + 0.021188679354041378 + 0.021190692757620234 + 0.021192706230374132 + 0.021194719772294507 + 0.021196733383372735 + 0.021198747063600254 + 0.021200760812968376 + 0.021202774631468566 + 0.021204788519092146 + 0.021206802475830521 + 0.021208816501675026 + 0.021210830596617065 + 0.02121284476064797 + 0.021214858993759137 + 0.02121687329594189 + 0.021218887667187568 + 0.021220902107487529 + 0.021222916616833121 + 0.021224931195215676 + 0.02122694584262648 + 0.021228960559056931 + 0.021230975344498328 + 0.021232990198941953 + 0.021235005122379153 + 0.02123702011480124 + 0.021239035176199485 + 0.021241050306565239 + 0.021243065505889742 + 0.021245080774164312 + 0.021247096111380242 + 0.021249111517528816 + 0.021251126992601291 + 0.021253142536588953 + 0.021255158149483078 + 0.021257173831274907 + 0.021259189581955742 + 0.021261205401516787 + 0.021263221289949327 + 0.02126523724724462 + 0.021267253273393863 + 0.021269269368388334 + 0.021271285532219249 + 0.021273301764877857 + 0.021275318066355353 + 0.021277334436642984 + 0.02127935087573193 + 0.021281367383613442 + 0.021283383960278724 + 0.02128540060571895 + 0.02128741731992535 + 0.021289434102889089 + 0.021291450954601377 + 0.021293467875053384 + 0.021295484864236307 + 0.02129750192214129 + 0.021299519048759558 + 0.021301536244082254 + 0.021303553508100512 + 0.021305570840805525 + 0.021307588242188431 + 0.021309605712240387 + 0.021311623250952524 + 0.021313640858316014 + 0.021315658534321966 + 0.021317676278961511 + 0.021319694092225786 + 0.021321711974105921 + 0.021323729924592999 + 0.02132574794367819 + 0.021327766031352547 + 0.021329784187607202 + 0.021331802412433275 + 0.021333820705821831 + 0.02133583906776397 + 0.021337857498250776 + 0.021339875997273348 + 0.021341894564822755 + 0.021343913200890047 + 0.021345931905466332 + 0.021347950678542647 + 0.021349969520110066 + 0.021351988430159639 + 0.021354007408682422 + 0.021356026455669464 + 0.021358045571111775 + 0.021360064755000449 + 0.021362084007326487 + 0.021364103328080933 + 0.021366122717254771 + 0.02136814217483907 + 0.02137016170082482 + 0.021372181295203036 + 0.021374200957964731 + 0.021376220689100892 + 0.021378240488602533 + 0.02138026035646064 + 0.021382280292666214 + 0.021384300297210203 + 0.021386320370083634 + 0.021388340511277446 + 0.021390360720782636 + 0.02139238099859014 + 0.021394401344690964 + 0.021396421759076002 + 0.021398442241736253 + 0.02140046279266267 + 0.021402483411846175 + 0.021404504099277692 + 0.021406524854948209 + 0.0214085456788486 + 0.021410566570969826 + 0.021412587531302794 + 0.021414608559838434 + 0.021416629656567626 + 0.021418650821481314 + 0.02142067205457036 + 0.021422693355825723 + 0.021424714725238245 + 0.021426736162798825 + 0.021428757668498374 + 0.021430779242327738 + 0.021432800884277802 + 0.021434822594339455 + 0.021436844372503566 + 0.021438866218760969 + 0.021440888133102548 + 0.021442910115519128 + 0.021444932166001591 + 0.021446954284540756 + 0.021448976471127475 + 0.021450998725752578 + 0.021453021048406903 + 0.021455043439081264 + 0.021457065897766511 + 0.021459088424453415 + 0.021461111019132832 + 0.021463133681795536 + 0.021465156412432355 + 0.021467179211034061 + 0.021469202077591475 + 0.021471225012095377 + 0.021473248014536563 + 0.021475271084905791 + 0.021477294223193867 + 0.02147931742939152 + 0.02148134070348956 + 0.021483364045478716 + 0.02148538745534977 + 0.021487410933093466 + 0.021489434478700557 + 0.021491458092161776 + 0.021493481773467878 + 0.021495505522609579 + 0.021497529339577652 + 0.021499553224362755 + 0.021501577176955659 + 0.021503601197347073 + 0.021505625285527696 + 0.021507649441488245 + 0.021509673665219442 + 0.021511697956711942 + 0.021513722315956486 + 0.021515746742943702 + 0.021517771237664341 + 0.021519795800109053 + 0.021521820430268512 + 0.0215238451281334 + 0.021525869893694365 + 0.021527894726942085 + 0.021529919627867215 + 0.021531944596460413 + 0.021533969632712313 + 0.021535994736613571 + 0.021538019908154807 + 0.021540045147326679 + 0.021542070454119818 + 0.021544095828524817 + 0.021546121270532331 + 0.021548146780132955 + 0.021550172357317307 + 0.021552198002075997 + 0.021554223714399634 + 0.021556249494278805 + 0.021558275341704087 + 0.021560301256666112 + 0.021562327239155427 + 0.021564353289162622 + 0.021566379406678268 + 0.021568405591692947 + 0.02157043184419722 + 0.02157245816418165 + 0.021574484551636765 + 0.02157651100655314 + 0.021578537528921332 + 0.021580564118731875 + 0.021582590775975304 + 0.021584617500642164 + 0.021586644292722945 + 0.021588671152208222 + 0.02159069807908847 + 0.021592725073354233 + 0.02159475213499602 + 0.021596779264004311 + 0.021598806460369633 + 0.021600833724082471 + 0.021602861055133312 + 0.021604888453512657 + 0.021606915919210986 + 0.021608943452218764 + 0.021610971052526476 + 0.021612998720124559 + 0.021615026455003527 + 0.021617054257153816 + 0.021619082126565874 + 0.021621110063230167 + 0.021623138067137119 + 0.021625166138277162 + 0.021627194276640772 + 0.021629222482218349 + 0.021631250755000331 + 0.021633279094977132 + 0.021635307502139194 + 0.021637335976476876 + 0.021639364517980667 + 0.021641393126640891 + 0.021643421802447996 + 0.021645450545392343 + 0.021647479355464336 + 0.021649508232654369 + 0.021651537176952802 + 0.021653566188350036 + 0.021655595266836431 + 0.021657624412402328 + 0.021659653625038133 + 0.021661682904734147 + 0.021663712251480782 + 0.021665741665268346 + 0.0216677711460872 + 0.021669800693927672 + 0.021671830308780081 + 0.0216738599906348 + 0.021675889739482083 + 0.021677919555312317 + 0.021679949438115801 + 0.021681979387882831 + 0.021684009404603712 + 0.021686039488268735 + 0.02168806963886822 + 0.02169009985639243 + 0.021692130140831701 + 0.021694160492176234 + 0.021696190910416399 + 0.021698221395542387 + 0.021700251947544522 + 0.021702282566413048 + 0.021704313252138219 + 0.021706344004710276 + 0.02170837482411949 + 0.021710405710356092 + 0.021712436663410332 + 0.021714467683272443 + 0.021716498769932636 + 0.021718529923381167 + 0.021720561143608243 + 0.021722592430604044 + 0.021724623784358854 + 0.021726655204862812 + 0.021728686692106172 + 0.021730718246079084 + 0.021732749866771775 + 0.021734781554174416 + 0.021736813308277203 + 0.021738845129070292 + 0.021740877016543862 + 0.021742908970688087 + 0.021744940991493163 + 0.021746973078949187 + 0.021749005233046358 + 0.021751037453774807 + 0.021753069741124686 + 0.021755102095086142 + 0.021757134515649295 + 0.021759167002804267 + 0.021761199556541225 + 0.02176323217685024 + 0.021765264863721469 + 0.021767297617145 + 0.021769330437110948 + 0.021771363323609426 + 0.021773396276630497 + 0.021775429296164311 + 0.02177746238220089 + 0.021779495534730364 + 0.021781528753742802 + 0.021783562039228266 + 0.021785595391176828 + 0.02178762880957855 + 0.021789662294423487 + 0.021791695845701731 + 0.0217937294634033 + 0.021795763147518219 + 0.02179779689803657 + 0.021799830714948377 + 0.021801864598243667 + 0.021803898547912464 + 0.021805932563944776 + 0.021807966646330636 + 0.021810000795060056 + 0.021812035010123049 + 0.021814069291509596 + 0.021816103639209709 + 0.021818138053213375 + 0.021820172533510589 + 0.021822207080091319 + 0.021824241692945574 + 0.021826276372063289 + 0.021828311117434464 + 0.021830345929049044 + 0.021832380806896992 + 0.02183441575096827 + 0.021836450761252828 + 0.021838485837740611 + 0.021840520980421524 + 0.021842556189285538 + 0.021844591464322577 + 0.021846626805522594 + 0.021848662212875462 + 0.021850697686371101 + 0.021852733225999465 + 0.021854768831750419 + 0.02185680450361388 + 0.021858840241579743 + 0.021860876045637898 + 0.021862911915778244 + 0.021864947851990627 + 0.021866983854264981 + 0.021869019922591135 + 0.021871056056958976 + 0.021873092257358343 + 0.021875128523779118 + 0.021877164856211172 + 0.02187920125464431 + 0.021881237719068403 + 0.021883274249473266 + 0.021885310845848785 + 0.021887347508184732 + 0.021889384236470945 + 0.021891421030697269 + 0.02189345789085349 + 0.021895494816929442 + 0.021897531808914877 + 0.021899568866799678 + 0.021901605990573596 + 0.021903643180226411 + 0.021905680435747917 + 0.021907717757127909 + 0.021909755144356152 + 0.021911792597422416 + 0.021913830116316469 + 0.021915867701028071 + 0.02191790535154698 + 0.021919943067862931 + 0.02192198084996571 + 0.021924018697845032 + 0.021926056611490642 + 0.021928094590892264 + 0.021930132636039618 + 0.021932170746922462 + 0.021934208923530474 + 0.021936247165853406 + 0.021938285473880912 + 0.021940323847602732 + 0.021942362287008577 + 0.02194440079208811 + 0.021946439362831027 + 0.021948477999227028 + 0.021950516701265778 + 0.021952555468936943 + 0.021954594302230197 + 0.021956633201135226 + 0.021958672165641645 + 0.021960711195739151 + 0.021962750291417383 + 0.021964789452665976 + 0.021966828679474561 + 0.021968867971832812 + 0.02197090732973029 + 0.021972946753156686 + 0.021974986242101598 + 0.021977025796554646 + 0.021979065416505419 + 0.021981105101943527 + 0.021983144852858603 + 0.021985184669240203 + 0.02198722455107794 + 0.021989264498361392 + 0.021991304511080126 + 0.021993344589223755 + 0.021995384732781832 + 0.021997424941743882 + 0.02199946521609954 + 0.022001505555838321 + 0.022003545960949764 + 0.022005586431423446 + 0.022007626967248877 + 0.022009667568415631 + 0.022011708234913212 + 0.02201374896673116 + 0.022015789763858987 + 0.022017830626286202 + 0.02201987155400234 + 0.022021912546996904 + 0.022023953605259369 + 0.022025994728779277 + 0.022028035917546079 + 0.022030077171549284 + 0.022032118490778359 + 0.022034159875222802 + 0.022036201324872065 + 0.022038242839715626 + 0.022040284419742956 + 0.022042326064943489 + 0.022044367775306706 + 0.022046409550822051 + 0.02204845139147894 + 0.022050493297266813 + 0.022052535268175123 + 0.022054577304193308 + 0.022056619405310764 + 0.022058661571516924 + 0.022060703802801174 + 0.022062746099152972 + 0.022064788460561664 + 0.022066830887016699 + 0.02206887337850744 + 0.022070915935023295 + 0.022072958556553633 + 0.022075001243087821 + 0.022077043994615245 + 0.022079086811125279 + 0.022081129692607285 + 0.022083172639050623 + 0.022085215650444637 + 0.022087258726778677 + 0.022089301868042088 + 0.022091345074224208 + 0.02209338834531438 + 0.022095431681301916 + 0.022097475082176143 + 0.02209951854792638 + 0.022101562078541949 + 0.022103605674012157 + 0.022105649334326311 + 0.022107693059473677 + 0.022109736849443576 + 0.022111780704225308 + 0.022113824623808141 + 0.022115868608181353 + 0.022117912657334208 + 0.022119956771255996 + 0.022122000949935966 + 0.022124045193363365 + 0.022126089501527502 + 0.02212813387441754 + 0.022130178312022793 + 0.022132222814332456 + 0.022134267381335778 + 0.022136312013022002 + 0.022138356709380337 + 0.022140401470399987 + 0.022142446296070185 + 0.022144491186380136 + 0.022146536141319041 + 0.022148581160876091 + 0.022150626245040505 + 0.022152671393801417 + 0.022154716607148083 + 0.022156761885069626 + 0.022158807227555231 + 0.022160852634594077 + 0.022162898106175305 + 0.022164943642288115 + 0.022166989242921604 + 0.022169034908064957 + 0.022171080637707331 + 0.022173126431837813 + 0.022175172290445567 + 0.022177218213519732 + 0.022179264201049396 + 0.022181310253023695 + 0.022183356369431754 + 0.022185402550262644 + 0.022187448795505511 + 0.022189495105149427 + 0.02219154147918349 + 0.022193587917596777 + 0.02219563442037838 + 0.022197680987517392 + 0.022199727619002851 + 0.022201774314823834 + 0.022203821074969429 + 0.022205867899428661 + 0.022207914788190578 + 0.022209961741244254 + 0.022212008758578716 + 0.022214055840182989 + 0.022216102986046142 + 0.022218150196157131 + 0.022220197470505056 + 0.022222244809078893 + 0.022224292211867648 + 0.022226339678860337 + 0.022228387210045965 + 0.022230434805413514 + 0.022232482464951974 + 0.022234530188650358 + 0.022236577976497605 + 0.022238625828482725 + 0.02224067374459467 + 0.022242721724822407 + 0.022244769769154904 + 0.022246817877581093 + 0.022248866050089959 + 0.02225091428667042 + 0.022252962587311433 + 0.022255010952001889 + 0.022257059380730766 + 0.022259107873486984 + 0.02226115643025944 + 0.022263205051037068 + 0.022265253735808718 + 0.022267302484563378 + 0.022269351297289904 + 0.022271400173977194 + 0.022273449114614142 + 0.022275498119189614 + 0.022277547187692485 + 0.022279596320111672 + 0.02228164551643598 + 0.022283694776654327 + 0.022285744100755518 + 0.022287793488728457 + 0.022289842940561948 + 0.022291892456244876 + 0.022293942035766019 + 0.022295991679114252 + 0.022298041386278399 + 0.022300091157247258 + 0.022302140992009677 + 0.022304190890554451 + 0.022306240852870366 + 0.022308290878946247 + 0.022310340968770895 + 0.022312391122333072 + 0.022314441339621575 + 0.022316491620625187 + 0.02231854196533271 + 0.022320592373732871 + 0.022322642845814443 + 0.022324693381566191 + 0.022326743980976858 + 0.022328794644035227 + 0.022330845370730008 + 0.022332896161049932 + 0.022334947014983775 + 0.022336997932520253 + 0.022339048913648046 + 0.022341099958355905 + 0.022343151066632542 + 0.022345202238466654 + 0.022347253473846959 + 0.022349304772762139 + 0.022351356135200891 + 0.022353407561151908 + 0.022355459050603866 + 0.022357510603545433 + 0.022359562219965285 + 0.022361613899852101 + 0.022363665643194502 + 0.022365717449981195 + 0.022367769320200785 + 0.022369821253841949 + 0.022371873250893307 + 0.022373925311343502 + 0.022375977435181185 + 0.022378029622394918 + 0.022380081872973384 + 0.022382134186905153 + 0.022384186564178864 + 0.022386239004783093 + 0.022388291508706467 + 0.022390344075937551 + 0.022392396706464944 + 0.022394449400277228 + 0.022396502157362982 + 0.022398554977710775 + 0.022400607861309176 + 0.022402660808146731 + 0.022404713818212008 + 0.022406766891493565 + 0.022408820027979941 + 0.022410873227659663 + 0.022412926490521286 + 0.02241497981655332 + 0.02241703320574432 + 0.02241908665808277 + 0.022421140173557196 + 0.022423193752156113 + 0.022425247393868024 + 0.022427301098681421 + 0.022429354866584785 + 0.022431408697566626 + 0.022433462591615421 + 0.022435516548719645 + 0.022437570568867755 + 0.022439624652048226 + 0.022441678798249536 + 0.02244373300746013 + 0.02244578727966845 + 0.022447841614862948 + 0.022449896013032065 + 0.022451950474164244 + 0.022454004998247873 + 0.022456059585271432 + 0.022458114235223304 + 0.02246016894809191 + 0.022462223723865651 + 0.022464278562532965 + 0.022466333464082205 + 0.022468388428501782 + 0.022470443455780108 + 0.02247249854590553 + 0.022474553698866414 + 0.022476608914651176 + 0.022478664193248142 + 0.022480719534645685 + 0.022482774938832155 + 0.022484830405795922 + 0.022486885935525322 + 0.02248894152800867 + 0.022490997183234347 + 0.022493052901190632 + 0.02249510868186588 + 0.022497164525248393 + 0.022499220431326485 + 0.02250127640008846 + 0.022503332431522641 + 0.022505388525617322 + 0.022507444682360763 + 0.022509500901741274 + 0.022511557183747127 + 0.022513613528366613 + 0.022515669935587981 + 0.022517726405399504 + 0.022519782937789432 + 0.022521839532746037 + 0.022523896190257561 + 0.022525952910312223 + 0.022528009692898299 + 0.022530066538004 + 0.022532123445617554 + 0.02253418041572719 + 0.022536237448321124 + 0.022538294543387554 + 0.022540351700914691 + 0.022542408920890732 + 0.022544466203303894 + 0.022546523548142336 + 0.022548580955394262 + 0.022550638425047852 + 0.022552695957091258 + 0.022554753551512673 + 0.022556811208300234 + 0.022558868927442122 + 0.022560926708926472 + 0.02256298455274142 + 0.022565042458875157 + 0.02256710042731579 + 0.022569158458051412 + 0.022571216551070195 + 0.022573274706360232 + 0.022575332923909668 + 0.022577391203706575 + 0.022579449545739077 + 0.022581507949995267 + 0.022583566416463256 + 0.022585624945131066 + 0.022587683535986874 + 0.022589742189018689 + 0.022591800904214601 + 0.022593859681562665 + 0.022595918521050948 + 0.022597977422667521 + 0.022600036386400409 + 0.022602095412237667 + 0.022604154500167346 + 0.022606213650177443 + 0.022608272862256008 + 0.022610332136391065 + 0.022612391472570624 + 0.02261445087078269 + 0.022616510331015298 + 0.022618569853256401 + 0.022620629437494044 + 0.022622689083716188 + 0.022624748791910811 + 0.022626808562065889 + 0.022628868394169426 + 0.022630928288209364 + 0.022632988244173667 + 0.022635048262050289 + 0.022637108341827205 + 0.022639168483492345 + 0.02264122868703362 + 0.022643288952439007 + 0.022645349279696411 + 0.022647409668793774 + 0.02264947011971901 + 0.022651530632460032 + 0.02265359120700472 + 0.022655651843341014 + 0.022657712541456775 + 0.02265977330133993 + 0.022661834122978345 + 0.022663895006359895 + 0.022665955951472465 + 0.022668016958303911 + 0.022670078026842129 + 0.022672139157074948 + 0.022674200348990203 + 0.022676261602575774 + 0.022678322917819498 + 0.022680384294709227 + 0.022682445733232748 + 0.0226845072333779 + 0.02268656879513253 + 0.022688630418484425 + 0.022690692103421395 + 0.022692753849931257 + 0.022694815658001802 + 0.022696877527620819 + 0.022698939458776091 + 0.022701001451455396 + 0.022703063505646544 + 0.022705125621337259 + 0.022707187798515324 + 0.022709250037168494 + 0.022711312337284531 + 0.02271337469885119 + 0.022715437121856183 + 0.022717499606287279 + 0.022719562152132187 + 0.022721624759378656 + 0.022723687428014384 + 0.022725750158027073 + 0.022727812949404472 + 0.022729875802134262 + 0.022731938716204134 + 0.0227340016916018 + 0.022736064728314916 + 0.022738127826331195 + 0.022740190985638304 + 0.022742254206223913 + 0.022744317488075674 + 0.022746380831181256 + 0.022748444235528308 + 0.022750507701104483 + 0.022752571227897433 + 0.022754634815894778 + 0.022756698465084154 + 0.022758762175453189 + 0.022760825946989496 + 0.022762889779680703 + 0.022764953673514398 + 0.022767017628478218 + 0.022769081644559715 + 0.022771145721746527 + 0.022773209860026202 + 0.022775274059386334 + 0.02277733831981452 + 0.02277940264129831 + 0.022781467023825254 + 0.022783531467382941 + 0.022785595971958898 + 0.022787660537540694 + 0.022789725164115864 + 0.022791789851671934 + 0.022793854600196436 + 0.022795919409676908 + 0.02279798428010087 + 0.022800049211455811 + 0.022802114203729254 + 0.022804179256908714 + 0.022806244370981679 + 0.022808309545935625 + 0.022810374781758055 + 0.022812440078436438 + 0.022814505435958261 + 0.022816570854310998 + 0.022818636333482085 + 0.022820701873458995 + 0.022822767474229178 + 0.022824833135780077 + 0.022826898858099146 + 0.022828964641173819 + 0.022831030484991504 + 0.022833096389539641 + 0.022835162354805635 + 0.022837228380776932 + 0.022839294467440884 + 0.022841360614784936 + 0.02284342682279648 + 0.022845493091462887 + 0.022847559420771546 + 0.022849625810709831 + 0.022851692261265138 + 0.022853758772424789 + 0.022855825344176201 + 0.022857891976506697 + 0.02285995866940364 + 0.022862025422854353 + 0.022864092236846181 + 0.022866159111366486 + 0.022868226046402564 + 0.022870293041941749 + 0.022872360097971348 + 0.02287442721447867 + 0.022876494391451046 + 0.022878561628875752 + 0.022880628926740063 + 0.022882696285031298 + 0.022884763703736741 + 0.022886831182843639 + 0.02288889872233928 + 0.022890966322210927 + 0.022893033982445857 + 0.02289510170303128 + 0.022897169483954493 + 0.022899237325202704 + 0.022901305226763157 + 0.02290337318862307 + 0.022905441210769695 + 0.022907509293190239 + 0.022909577435871895 + 0.022911645638801912 + 0.022913713901967461 + 0.022915782225355737 + 0.022917850608953939 + 0.022919919052749271 + 0.022921987556728862 + 0.022924056120879926 + 0.022926124745189621 + 0.022928193429645104 + 0.022930262174233527 + 0.022932330978942043 + 0.022934399843757822 + 0.022936468768667943 + 0.022938537753659619 + 0.022940606798719895 + 0.022942675903835936 + 0.022944745068994864 + 0.022946814294183784 + 0.022948883579389769 + 0.022950952924599952 + 0.022953022329801408 + 0.022955091794981241 + 0.022957161320126502 + 0.022959230905224309 + 0.022961300550261691 + 0.022963370255225712 + 0.022965440020103475 + 0.022967509844881988 + 0.022969579729548304 + 0.022971649674089472 + 0.02297371967849253 + 0.022975789742744484 + 0.022977859866832401 + 0.022979930050743252 + 0.022982000294464074 + 0.022984070597981854 + 0.022986140961283635 + 0.022988211384356364 + 0.022990281867187028 + 0.022992352409762655 + 0.022994423012070168 + 0.02299649367409657 + 0.02299856439582881 + 0.023000635177253873 + 0.023002706018358684 + 0.023004776919130204 + 0.023006847879555373 + 0.023008918899621124 + 0.023010989979314375 + 0.023013061118622075 + 0.023015132317531144 + 0.023017203576028468 + 0.023019274894100963 + 0.023021346271735542 + 0.02302341770891907 + 0.023025489205638464 + 0.023027560761880617 + 0.023029632377632375 + 0.023031704052880627 + 0.023033775787612235 + 0.023035847581814064 + 0.023037919435472967 + 0.023039991348575779 + 0.023042063321109345 + 0.023044135353060515 + 0.023046207444416107 + 0.023048279595162955 + 0.023050351805287896 + 0.023052424074777696 + 0.023054496403619177 + 0.023056568791799154 + 0.023058641239304425 + 0.023060713746121776 + 0.02306278631223798 + 0.02306485893763981 + 0.023066931622314046 + 0.023069004366247477 + 0.023071077169426826 + 0.023073150031838879 + 0.023075222953470347 + 0.023077295934308004 + 0.023079368974338575 + 0.023081442073548779 + 0.023083515231925374 + 0.023085588449455026 + 0.02308766172612451 + 0.023089735061920465 + 0.023091808456829656 + 0.023093881910838724 + 0.023095955423934403 + 0.023098028996103345 + 0.023100102627332243 + 0.023102176317607741 + 0.023104250066916545 + 0.023106323875245291 + 0.023108397742580646 + 0.023110471668909231 + 0.023112545654217716 + 0.023114619698492728 + 0.023116693801720892 + 0.023118767963888821 + 0.023120842184983156 + 0.023122916464990477 + 0.023124990803897419 + 0.023127065201690587 + 0.023129139658356536 + 0.023131214173881882 + 0.023133288748253211 + 0.023135363381457091 + 0.02313743807348009 + 0.023139512824308782 + 0.023141587633929695 + 0.02314366250232943 + 0.023145737429494495 + 0.023147812415411431 + 0.023149887460066795 + 0.023151962563447075 + 0.023154037725538854 + 0.023156112946328591 + 0.023158188225802828 + 0.023160263563948038 + 0.023162338960750779 + 0.023164414416197467 + 0.023166489930274665 + 0.023168565502968801 + 0.023170641134266354 + 0.0231727168241538 + 0.02317479257261762 + 0.023176868379644236 + 0.023178944245220105 + 0.023181020169331688 + 0.023183096151965434 + 0.023185172193107735 + 0.023187248292745044 + 0.023189324450863757 + 0.023191400667450339 + 0.023193476942491145 + 0.023195553275972603 + 0.023197629667881102 + 0.023199706118203042 + 0.02320178262692477 + 0.02320385919403271 + 0.023205935819513208 + 0.023208012503352637 + 0.023210089245537347 + 0.023212166046053719 + 0.023214242904888067 + 0.023216319822026755 + 0.02321839679745611 + 0.023220473831162464 + 0.023222550923132104 + 0.023224628073351426 + 0.023226705281806675 + 0.023228782548484171 + 0.02323085987337024 + 0.023232937256451133 + 0.02323501469771316 + 0.023237092197142609 + 0.023239169754725734 + 0.023241247370448803 + 0.023243325044298123 + 0.023245402776259895 + 0.023247480566320391 + 0.023249558414465854 + 0.023251636320682525 + 0.02325371428495664 + 0.023255792307274415 + 0.02325787038762207 + 0.023259948525985827 + 0.023262026722351881 + 0.023264104976706449 + 0.023266183289035722 + 0.023268261659325874 + 0.023270340087563107 + 0.023272418573733595 + 0.023274497117823478 + 0.023276575719818973 + 0.0232786543797062 + 0.023280733097471331 + 0.023282811873100502 + 0.023284890706579877 + 0.023286969597895536 + 0.02328904854703364 + 0.023291127553980339 + 0.023293206618721692 + 0.023295285741243857 + 0.02329736492153292 + 0.023299444159574967 + 0.023301523455356084 + 0.023303602808862383 + 0.02330568222007991 + 0.023307761688994785 + 0.023309841215593034 + 0.02331192079986073 + 0.023314000441783913 + 0.023316080141348661 + 0.023318159898540983 + 0.02332023971334693 + 0.023322319585752534 + 0.023324399515743808 + 0.023326479503306779 + 0.023328559548427472 + 0.023330639651091858 + 0.023332719811285936 + 0.023334800028995739 + 0.023336880304207223 + 0.023338960636906367 + 0.023341041027079144 + 0.023343121474711546 + 0.023345201979789482 + 0.023347282542298974 + 0.023349363162225915 + 0.023351443839556275 + 0.023353524574275981 + 0.023355605366370952 + 0.023357686215827143 + 0.023359767122630461 + 0.023361848086766807 + 0.023363929108222076 + 0.023366010186982211 + 0.023368091323033052 + 0.023370172516360508 + 0.023372253766950443 + 0.023374335074788772 + 0.023376416439861335 + 0.023378497862153982 + 0.023380579341652608 + 0.023382660878343006 + 0.023384742472211065 + 0.023386824123242608 + 0.023388905831423463 + 0.023390987596739445 + 0.023393069419176387 + 0.023395151298720086 + 0.02339723323535637 + 0.023399315229071006 + 0.023401397279849804 + 0.023403479387678571 + 0.023405561552543044 + 0.023407643774429013 + 0.023409726053322265 + 0.023411808389208554 + 0.023413890782073607 + 0.023415973231903205 + 0.023418055738683084 + 0.02342013830239896 + 0.023422220923036568 + 0.023424303600581672 + 0.023426386335019932 + 0.023428469126337104 + 0.023430551974518862 + 0.023432634879550922 + 0.023434717841418949 + 0.023436800860108683 + 0.023438883935605743 + 0.023440967067895824 + 0.023443050256964595 + 0.023445133502797737 + 0.023447216805380863 + 0.023449300164699663 + 0.023451383580739744 + 0.023453467053486769 + 0.023455550582926327 + 0.023457634169044075 + 0.023459717811825605 + 0.023461801511256566 + 0.023463885267322522 + 0.023465969080009075 + 0.023468052949301828 + 0.023470136875186374 + 0.023472220857648243 + 0.023474304896673077 + 0.023476388992246387 + 0.023478473144353754 + 0.023480557352980717 + 0.023482641618112823 + 0.023484725939735652 + 0.023486810317834679 + 0.023488894752395434 + 0.023490979243403494 + 0.023493063790844343 + 0.023495148394703447 + 0.023497233054966388 + 0.023499317771618573 + 0.023501402544645555 + 0.023503487374032787 + 0.023505572259765756 + 0.023507657201829919 + 0.023509742200210754 + 0.023511827254893713 + 0.02351391236586425 + 0.023515997533107784 + 0.023518082756609774 + 0.023520168036355659 + 0.023522253372330833 + 0.023524338764520748 + 0.023526424212910797 + 0.023528509717486365 + 0.023530595278232907 + 0.023532680895135771 + 0.023534766568180328 + 0.023536852297352008 + 0.023538938082636136 + 0.023541023924018124 + 0.023543109821483305 + 0.023545195775017007 + 0.023547281784604635 + 0.023549367850231477 + 0.023551453971882894 + 0.023553540149544222 + 0.023555626383200752 + 0.023557712672837836 + 0.023559799018440748 + 0.023561885419994825 + 0.023563971877485303 + 0.023566058390897548 + 0.02356814496021677 + 0.023570231585428293 + 0.023572318266517372 + 0.023574405003469273 + 0.02357649179626925 + 0.023578578644902544 + 0.023580665549354396 + 0.023582752509610044 + 0.023584839525654756 + 0.023586926597473721 + 0.023589013725052146 + 0.023591100908375268 + 0.023593188147428269 + 0.023595275442196386 + 0.023597362792664753 + 0.023599450198818608 + 0.023601537660643105 + 0.023603625178123394 + 0.023605712751244661 + 0.023607800379992092 + 0.023609888064350798 + 0.023611975804305935 + 0.023614063599842663 + 0.023616151450946081 + 0.023618239357601351 + 0.023620327319793563 + 0.023622415337507821 + 0.023624503410729268 + 0.023626591539442989 + 0.023628679723634072 + 0.02363076796328761 + 0.02363285625838869 + 0.023634944608922355 + 0.023637033014873691 + 0.023639121476227754 + 0.023641209992969609 + 0.023643298565084313 + 0.02364538719255687 + 0.023647475875372345 + 0.023649564613515743 + 0.02365165340697211 + 0.023653742255726428 + 0.023655831159763722 + 0.023657920119069021 + 0.023660009133627247 + 0.023662098203423475 + 0.023664187328442634 + 0.02366627650866969 + 0.023668365744089658 + 0.023670455034687451 + 0.023672544380448048 + 0.0236746337813564 + 0.023676723237397439 + 0.023678812748556103 + 0.023680902314817301 + 0.023682991936165982 + 0.023685081612587075 + 0.02368717134406545 + 0.023689261130586014 + 0.023691350972133679 + 0.023693440868693336 + 0.023695530820249864 + 0.023697620826788099 + 0.023699710888292966 + 0.023701801004749296 + 0.023703891176141967 + 0.023705981402455785 + 0.023708071683675631 + 0.023710162019786332 + 0.023712252410772711 + 0.023714342856619584 + 0.023716433357311769 + 0.023718523912834105 + 0.023720614523171341 + 0.023722705188308296 + 0.023724795908229783 + 0.023726886682920521 + 0.023728977512365353 + 0.023731068396549027 + 0.023733159335456291 + 0.023735250329071908 + 0.023737341377380622 + 0.023739432480367164 + 0.023741523638016286 + 0.023743614850312737 + 0.023745706117241201 + 0.02374779743878638 + 0.023749888814933038 + 0.023751980245665834 + 0.023754071730969478 + 0.023756163270828634 + 0.023758254865228007 + 0.023760346514152285 + 0.023762438217586116 + 0.023764529975514155 + 0.023766621787921053 + 0.023768713654791489 + 0.023770805576110065 + 0.023772897551861429 + 0.023774989582030226 + 0.023777081666601054 + 0.023779173805558537 + 0.02378126599888726 + 0.023783358246571865 + 0.023785450548596907 + 0.023787542904946998 + 0.023789635315606697 + 0.02379172778056059 + 0.023793820299793243 + 0.023795912873289228 + 0.023798005501033052 + 0.023800098183009308 + 0.023802190919202517 + 0.023804283709597199 + 0.023806376554177902 + 0.023808469452929148 + 0.023810562405835418 + 0.023812655412881242 + 0.023814748474051118 + 0.023816841589329514 + 0.023818934758700939 + 0.02382102798214987 + 0.023823121259660757 + 0.023825214591218089 + 0.023827307976806295 + 0.023829401416409865 + 0.023831494910013205 + 0.023833588457600773 + 0.023835682059156992 + 0.023837775714666287 + 0.023839869424113057 + 0.023841963187481743 + 0.023844057004756725 + 0.023846150875922408 + 0.023848244800963193 + 0.023850338779863429 + 0.023852432812607512 + 0.023854526899179811 + 0.02385662103956469 + 0.02385871523374649 + 0.023860809481709547 + 0.023862903783438263 + 0.023864998138916894 + 0.023867092548129815 + 0.02386918701106135 + 0.023871281527695794 + 0.023873376098017436 + 0.0238754707220106 + 0.023877565399659566 + 0.023879660130948648 + 0.023881754915862086 + 0.023883849754384182 + 0.023885944646499187 + 0.023888039592191365 + 0.023890134591444939 + 0.023892229644244197 + 0.023894324750573345 + 0.023896419910416623 + 0.02389851512375828 + 0.023900610390582493 + 0.023902705710873488 + 0.02390480108461546 + 0.023906896511792602 + 0.023908991992389134 + 0.023911087526389211 + 0.023913183113777013 + 0.023915278754536702 + 0.02391737444865244 + 0.023919470196108406 + 0.023921565996888706 + 0.023923661850977489 + 0.023925757758358923 + 0.023927853719017105 + 0.023929949732936152 + 0.02393204580010019 + 0.02393414192049332 + 0.023936238094099636 + 0.02393833432090323 + 0.023940430600888192 + 0.023942526934038588 + 0.023944623320338504 + 0.023946719759771983 + 0.023948816252323112 + 0.023950912797975885 + 0.023953009396714412 + 0.02395510604852269 + 0.023957202753384744 + 0.023959299511284615 + 0.023961396322206303 + 0.023963493186133823 + 0.023965590103051167 + 0.023967687072942338 + 0.023969784095791286 + 0.023971881171582061 + 0.023973978300298581 + 0.023976075481924826 + 0.023978172716444746 + 0.023980270003842299 + 0.023982367344101432 + 0.023984464737206068 + 0.023986562183140166 + 0.023988659681887622 + 0.023990757233432341 + 0.023992854837758266 + 0.0239949524948493 + 0.023997050204689285 + 0.023999147967262158 + 0.024001245782551785 + 0.024003343650542051 + 0.024005441571216795 + 0.024007539544559885 + 0.02400963757055519 + 0.024011735649186527 + 0.024013833780437761 + 0.024015931964292723 + 0.02401803020073523 + 0.024020128489749073 + 0.024022226831318091 + 0.024024325225426069 + 0.024026423672056808 + 0.024028522171194121 + 0.02403062072282176 + 0.024032719326923493 + 0.024034817983483101 + 0.024036916692484343 + 0.024039015453910965 + 0.024041114267746726 + 0.024043213133975359 + 0.024045312052580599 + 0.024047411023546138 + 0.024049510046855724 + 0.024051609122493066 + 0.024053708250441848 + 0.024055807430685795 + 0.024057906663208551 + 0.024060005947993846 + 0.024062105285025316 + 0.024064204674286657 + 0.024066304115761501 + 0.024068403609433513 + 0.024070503155286353 + 0.024072602753303637 + 0.024074702403468987 + 0.024076802105766047 + 0.024078901860178439 + 0.024081001666689757 + 0.024083101525283607 + 0.024085201435943573 + 0.024087301398653276 + 0.024089401413396255 + 0.024091501480156111 + 0.024093601598916405 + 0.024095701769660676 + 0.024097801992372502 + 0.024099902267035397 + 0.024102002593632956 + 0.024104102972148628 + 0.024106203402565998 + 0.024108303884868565 + 0.024110404419039801 + 0.024112505005063279 + 0.024114605642922424 + 0.024116706332600754 + 0.024118807074081757 + 0.024120907867348884 + 0.024123008712385621 + 0.024125109609175382 + 0.024127210557701669 + 0.024129311557947893 + 0.024131412609897519 + 0.024133513713533925 + 0.024135614868840589 + 0.024137716075800869 + 0.024139817334398239 + 0.024141918644616015 + 0.024144020006437658 + 0.024146121419846525 + 0.024148222884825994 + 0.024150324401359443 + 0.024152425969430215 + 0.024154527589021684 + 0.024156629260117187 + 0.024158730982700074 + 0.024160832756753674 + 0.02416293458226134 + 0.02416503645920633 + 0.024167138387572 + 0.024169240367341638 + 0.024171342398498566 + 0.024173444481026034 + 0.024175546614907336 + 0.024177648800125767 + 0.024179751036664591 + 0.024181853324507046 + 0.024183955663636396 + 0.024186058054035894 + 0.024188160495688768 + 0.024190262988578261 + 0.024192365532687565 + 0.024194468127999941 + 0.02419657077449856 + 0.024198673472166643 + 0.024200776220987368 + 0.024202879020943948 + 0.024204981872019547 + 0.024207084774197328 + 0.024209187727460467 + 0.024211290731792096 + 0.024213393787175398 + 0.024215496893593515 + 0.024217600051029541 + 0.024219703259466645 + 0.024221806518887942 + 0.024223909829276524 + 0.024226013190615486 + 0.024228116602887966 + 0.024230220066077026 + 0.024232323580165752 + 0.024234427145137242 + 0.02423653076097454 + 0.024238634427660694 + 0.02424073814517879 + 0.024242841913511844 + 0.024244945732642915 + 0.024247049602555037 + 0.024249153523231204 + 0.024251257494654462 + 0.024253361516807802 + 0.024255465589674233 + 0.024257569713236744 + 0.024259673887478309 + 0.024261778112381931 + 0.024263882387930563 + 0.024265986714107176 + 0.024268091090894731 + 0.024270195518276149 + 0.024272299996234408 + 0.024274404524752425 + 0.024276509103813109 + 0.024278613733399405 + 0.024280718413494221 + 0.024282823144080434 + 0.024284927925140979 + 0.024287032756658705 + 0.02428913763861652 + 0.024291242570997289 + 0.024293347553783869 + 0.024295452586959136 + 0.024297557670505919 + 0.024299662804407093 + 0.024301767988645466 + 0.024303873223203858 + 0.024305978508065113 + 0.024308083843212057 + 0.024310189228627436 + 0.024312294664294101 + 0.024314400150194839 + 0.024316505686312426 + 0.024318611272629624 + 0.024320716909129209 + 0.024322822595793939 + 0.024324928332606566 + 0.024327034119549826 + 0.024329139956606488 + 0.024331245843759265 + 0.024333351780990858 + 0.024335457768284 + 0.024337563805621399 + 0.024339669892985749 + 0.024341776030359762 + 0.024343882217726084 + 0.024345988455067424 + 0.02434809474236644 + 0.024350201079605761 + 0.0243523074667681 + 0.024354413903836067 + 0.024356520390792311 + 0.024358626927619462 + 0.024360733514300136 + 0.02436284015081696 + 0.024364946837152512 + 0.02436705357328944 + 0.024369160359210312 + 0.024371267194897687 + 0.02437337408033418 + 0.024375481015502354 + 0.024377588000384753 + 0.024379695034963962 + 0.024381802119222477 + 0.024383909253142887 + 0.024386016436707719 + 0.024388123669899446 + 0.024390230952700639 + 0.024392338285093788 + 0.024394445667061383 + 0.024396553098585932 + 0.024398660579649911 + 0.024400768110235796 + 0.024402875690326068 + 0.024404983319903165 + 0.024407090998949568 + 0.024409198727447727 + 0.024411306505380051 + 0.024413414332728964 + 0.024415522209476952 + 0.024417630135606366 + 0.02441973811109965 + 0.024421846135939167 + 0.024423954210107377 + 0.024426062333586577 + 0.0244281705063592 + 0.024430278728407612 + 0.024432386999714159 + 0.024434495320261228 + 0.024436603690031086 + 0.024438712109006163 + 0.024440820577168738 + 0.024442929094501142 + 0.024445037660985693 + 0.024447146276604697 + 0.02444925494134045 + 0.024451363655175244 + 0.024453472418091385 + 0.024455581230071109 + 0.024457690091096711 + 0.024459799001150438 + 0.024461907960214569 + 0.024464016968271291 + 0.02446612602530291 + 0.024468235131291587 + 0.024470344286219619 + 0.02447245349006914 + 0.024474562742822413 + 0.02447667204446162 + 0.024478781394968938 + 0.024480890794326575 + 0.024483000242516657 + 0.024485109739521411 + 0.024487219285322957 + 0.024489328879903446 + 0.024491438523245021 + 0.024493548215329841 + 0.024495657956139998 + 0.024497767745657647 + 0.024499877583864873 + 0.024501987470743801 + 0.024504097406276484 + 0.024506207390445067 + 0.024508317423231583 + 0.024510427504618133 + 0.024512537634586759 + 0.024514647813119513 + 0.024516758040198473 + 0.024518868315805672 + 0.024520978639923131 + 0.024523089012532862 + 0.024525199433616921 + 0.024527309903157272 + 0.024529420421135942 + 0.024531530987534914 + 0.024533641602336169 + 0.024535752265521703 + 0.024537862977073468 + 0.024539973736973437 + 0.024542084545203541 + 0.024544195401745746 + 0.024546306306581972 + 0.024548417259694172 + 0.024550528261064238 + 0.024552639310674106 + 0.024554750408505674 + 0.024556861554540853 + 0.024558972748761475 + 0.024561083991149511 + 0.024563195281686757 + 0.02456530662035512 + 0.024567418007136448 + 0.024569529442012562 + 0.02457164092496536 + 0.024573752455976639 + 0.024575864035028237 + 0.024577975662101934 + 0.02458008733717958 + 0.024582199060242973 + 0.024584310831273899 + 0.024586422650254111 + 0.024588534517165455 + 0.02459064643198967 + 0.02459275839470848 + 0.024594870405303688 + 0.024596982463756998 + 0.024599094570050172 + 0.024601206724164944 + 0.024603318926083018 + 0.024605431175786129 + 0.024607543473255947 + 0.024609655818474199 + 0.024611768211422566 + 0.024613880652082708 + 0.024615993140436322 + 0.024618105676465076 + 0.024620218260150602 + 0.024622330891474569 + 0.024624443570418608 + 0.024626556296964343 + 0.024628669071093422 + 0.024630781892787432 + 0.024632894762027995 + 0.02463500767879671 + 0.024637120643075168 + 0.024639233654844963 + 0.024641346714087655 + 0.024643459820784825 + 0.024645572974918015 + 0.024647686176468765 + 0.024649799425418648 + 0.024651912721749183 + 0.024654026065441918 + 0.024656139456478331 + 0.024658252894839951 + 0.024660366380508315 + 0.02466247991346485 + 0.024664593493691093 + 0.024666707121168484 + 0.024668820795878538 + 0.024670934517802688 + 0.024673048286922367 + 0.024675162103219055 + 0.024677275966674166 + 0.024679389877269153 + 0.024681503834985415 + 0.02468361783980437 + 0.024685731891707426 + 0.024687845990675951 + 0.024689960136691381 + 0.024692074329735053 + 0.024694188569788354 + 0.024696302856832643 + 0.024698417190849288 + 0.024700531571819621 + 0.024702645999724979 + 0.024704760474546707 + 0.024706874996266087 + 0.024708989564864493 + 0.024711104180323171 + 0.024713218842623456 + 0.024715333551746599 + 0.024717448307673941 + 0.024719563110386693 + 0.024721677959866149 + 0.024723792856093579 + 0.024725907799050179 + 0.024728022788717229 + 0.024730137825075951 + 0.024732252908107565 + 0.024734368037793279 + 0.024736483214114292 + 0.024738598437051833 + 0.024740713706587064 + 0.024742829022701158 + 0.02474494438537532 + 0.024747059794590687 + 0.024749175250328433 + 0.024751290752569686 + 0.024753406301295588 + 0.024755521896487293 + 0.0247576375381259 + 0.024759753226192522 + 0.024761868960668267 + 0.024763984741534243 + 0.024766100568771533 + 0.024768216442361199 + 0.024770332362284347 + 0.024772448328522038 + 0.024774564341055301 + 0.024776680399865195 + 0.024778796504932768 + 0.024780912656239031 + 0.024783028853765019 + 0.024785145097491759 + 0.024787261387400204 + 0.02478937772347142 + 0.02479149410568636 + 0.024793610534025987 + 0.024795727008471317 + 0.024797843529003275 + 0.02479996009560281 + 0.024802076708250909 + 0.02480419336692849 + 0.02480631007161645 + 0.024808426822295768 + 0.024810543618947328 + 0.02481266046155203 + 0.024814777350090744 + 0.024816894284544422 + 0.024819011264893893 + 0.02482112829112005 + 0.024823245363203718 + 0.024825362481125796 + 0.024827479644867121 + 0.024829596854408498 + 0.024831714109730802 + 0.024833831410814803 + 0.024835948757641346 + 0.024838066150191219 + 0.024840183588445218 + 0.024842301072384127 + 0.024844418601988723 + 0.024846536177239788 + 0.02484865379811806 + 0.024850771464604283 + 0.02485288917667924 + 0.024855006934323638 + 0.024857124737518208 + 0.024859242586243672 + 0.024861360480480706 + 0.024863478420210059 + 0.024865596405412388 + 0.024867714436068406 + 0.02486983251215873 + 0.024871950633664104 + 0.024874068800565127 + 0.024876187012842471 + 0.02487830527047678 + 0.024880423573448655 + 0.02488254192173877 + 0.02488466031532769 + 0.024886778754196055 + 0.024888897238324437 + 0.024891015767693439 + 0.024893134342283633 + 0.024895252962075617 + 0.024897371627049907 + 0.024899490337187098 + 0.024901609092467691 + 0.02490372789287227 + 0.024905846738381348 + 0.024907965628975445 + 0.024910084564635067 + 0.024912203545340707 + 0.024914322571072879 + 0.024916441641812052 + 0.024918560757538712 + 0.024920679918233317 + 0.024922799123876342 + 0.024924918374448241 + 0.024927037669929392 + 0.024929157010300323 + 0.024931276395541411 + 0.024933395825633045 + 0.024935515300555697 + 0.024937634820289718 + 0.0249397543848155 + 0.024941873994113448 + 0.024943993648163902 + 0.024946113346947251 + 0.024948233090443844 + 0.024950352878634032 + 0.024952472711498128 + 0.024954592589016496 + 0.024956712511169429 + 0.024958832477937239 + 0.024960952489300237 + 0.024963072545238729 + 0.024965192645732982 + 0.024967312790763262 + 0.024969432980309857 + 0.024971553214353039 + 0.024973673492873022 + 0.02497579381585005 + 0.02497791418326438 + 0.024980034595096227 + 0.024982155051325821 + 0.024984275551933322 + 0.024986396096898986 + 0.024988516686202934 + 0.024990637319825402 + 0.024992757997746546 + 0.02499487871994651 + 0.02499699948640546 + 0.024999120297103557 + 0.025001241152020893 + 0.02500336205113763 + 0.025005482994433888 + 0.025007603981889767 + 0.025009725013485359 + 0.025011846089200759 + 0.025013967209016066 + 0.02501608837291134 + 0.025018209580866629 + 0.025020330832862019 + 0.025022452128877534 + 0.025024573468893214 + 0.025026694852889109 + 0.025028816280845221 + 0.025030937752741577 + 0.025033059268558172 + 0.025035180828274974 + 0.025037302431872001 + 0.025039424079329228 + 0.025041545770626606 + 0.025043667505744108 + 0.025045789284661665 + 0.025047911107359225 + 0.025050032973816735 + 0.025052154884014102 + 0.025054276837931239 + 0.025056398835548062 + 0.025058520876844435 + 0.025060642961800283 + 0.025062765090395473 + 0.025064887262609876 + 0.02506700947842332 + 0.025069131737815695 + 0.025071254040766829 + 0.025073376387256555 + 0.025075498777264699 + 0.025077621210771062 + 0.025079743687755476 + 0.025081866208197721 + 0.025083988772077577 + 0.02508611137937487 + 0.025088234030069292 + 0.025090356724140644 + 0.025092479461568704 + 0.025094602242333182 + 0.025096725066413816 + 0.025098847933790337 + 0.025100970844442468 + 0.025103093798349886 + 0.025105216795492335 + 0.025107339835849469 + 0.025109462919400975 + 0.025111586046126518 + 0.025113709216005781 + 0.025115832429018378 + 0.025117955685144001 + 0.025120078984362259 + 0.025122202326652764 + 0.025124325711995164 + 0.025126449140369048 + 0.025128572611754 + 0.025130696126129632 + 0.025132819683475523 + 0.025134943283771236 + 0.025137066926996309 + 0.025139190613130337 + 0.025141314342152849 + 0.025143438114043373 + 0.025145561928781431 + 0.025147685786346543 + 0.025149809686718236 + 0.025151933629875955 + 0.025154057615799256 + 0.025156181644467573 + 0.02515830571586038 + 0.025160429829957143 + 0.025162553986737328 + 0.025164678186180379 + 0.025166802428265692 + 0.025168926712972741 + 0.0251710510402809 + 0.025173175410169588 + 0.025175299822618222 + 0.025177424277606171 + 0.025179548775112817 + 0.025181673315117517 + 0.025183797897599666 + 0.025185922522538557 + 0.025188047189913593 + 0.025190171899704059 + 0.025192296651889323 + 0.02519442144644865 + 0.025196546283361401 + 0.025198671162606805 + 0.025200796084164201 + 0.025202921048012833 + 0.025205046054132003 + 0.025207171102500956 + 0.025209296193098904 + 0.02521142132590513 + 0.025213546500898871 + 0.025215671718059298 + 0.025217796977365672 + 0.025219922278797192 + 0.025222047622333016 + 0.025224173007952353 + 0.025226298435634377 + 0.025228423905358271 + 0.025230549417103142 + 0.025232674970848187 + 0.025234800566572516 + 0.025236926204255262 + 0.025239051883875561 + 0.025241177605412495 + 0.025243303368845157 + 0.025245429174152678 + 0.025247555021314129 + 0.025249680910308565 + 0.025251806841115061 + 0.025253932813712646 + 0.025256058828080408 + 0.025258184884197336 + 0.025260310982042497 + 0.025262437121594879 + 0.025264563302833488 + 0.025266689525737331 + 0.025268815790285424 + 0.025270942096456667 + 0.025273068444230121 + 0.025275194833584664 + 0.02527732126449931 + 0.025279447736952974 + 0.025281574250924567 + 0.025283700806393052 + 0.025285827403337315 + 0.025287954041736255 + 0.02529008072156878 + 0.025292207442813779 + 0.0252943342054501 + 0.025296461009456653 + 0.025298587854812222 + 0.025300714741495724 + 0.025302841669485952 + 0.025304968638761756 + 0.025307095649301954 + 0.025309222701085335 + 0.025311349794090714 + 0.025313476928296899 + 0.02531560410368262 + 0.025317731320226688 + 0.02531985857790784 + 0.025321985876704829 + 0.02532411321659641 + 0.025326240597561306 + 0.025328368019578253 + 0.025330495482625948 + 0.025332622986683106 + 0.025334750531728407 + 0.025336878117740557 + 0.0253390057446982 + 0.025341133412580021 + 0.025343261121364685 + 0.02534538887103081 + 0.025347516661557074 + 0.025349644492922062 + 0.02535177236510441 + 0.025353900278082726 + 0.025356028231835612 + 0.025358156226341622 + 0.025360284261579401 + 0.025362412337527469 + 0.025364540454164381 + 0.025366668611468728 + 0.025368796809419003 + 0.025370925047993754 + 0.025373053327171539 + 0.025375181646930832 + 0.025377310007250138 + 0.025379438408107927 + 0.025381566849482739 + 0.025383695331353002 + 0.025385823853697198 + 0.025387952416493779 + 0.025390081019721161 + 0.025392209663357819 + 0.025394338347382164 + 0.025396467071772601 + 0.02539859583650754 + 0.025400724641565377 + 0.0254028534869245 + 0.025404982372563289 + 0.025407111298460086 + 0.025409240264593288 + 0.02541136927094121 + 0.025413498317482196 + 0.025415627404194577 + 0.025417756531056671 + 0.025419885698046773 + 0.025422014905143214 + 0.025424144152324243 + 0.025426273439568159 + 0.025428402766853226 + 0.025430532134157725 + 0.025432661541459862 + 0.025434790988737913 + 0.025436920475970085 + 0.025439050003134615 + 0.0254411795702097 + 0.025443309177173554 + 0.025445438824004341 + 0.025447568510680262 + 0.025449698237179477 + 0.02545182800348016 + 0.02545395780956048 + 0.025456087655398533 + 0.02545821754097248 + 0.02546034746626042 + 0.025462477431240513 + 0.02546460743589081 + 0.025466737480189395 + 0.025468867564114407 + 0.025470997687643882 + 0.025473127850755874 + 0.025475258053428453 + 0.025477388295639659 + 0.025479518577367542 + 0.025481648898590076 + 0.025483779259285303 + 0.025485909659431236 + 0.025488040099005869 + 0.025490170577987158 + 0.025492301096353105 + 0.025494431654081655 + 0.025496562251150774 + 0.025498692887538383 + 0.025500823563222436 + 0.025502954278180872 + 0.025505085032391572 + 0.025507215825832444 + 0.025509346658481397 + 0.025511477530316296 + 0.025513608441315026 + 0.025515739391455468 + 0.02551787038071545 + 0.025520001409072818 + 0.025522132476505408 + 0.025524263582991057 + 0.025526394728507568 + 0.02552852591303274 + 0.025530657136544368 + 0.025532788399020245 + 0.025534919700438148 + 0.025537051040775825 + 0.025539182420011037 + 0.025541313838121527 + 0.025543445295085013 + 0.025545576790879269 + 0.025547708325481935 + 0.025549839898870757 + 0.025551971511023445 + 0.025554103161917658 + 0.025556234851531055 + 0.025558366579841313 + 0.025560498346826097 + 0.025562630152463042 + 0.02556476199672977 + 0.025566893879603928 + 0.025569025801063086 + 0.025571157761084887 + 0.025573289759646907 + 0.02557542179672672 + 0.025577553872301911 + 0.025579685986350052 + 0.025581818138848671 + 0.025583950329775305 + 0.025586082559107503 + 0.025588214826822796 + 0.025590347132898671 + 0.025592479477312659 + 0.0255946118600422 + 0.025596744281064818 + 0.025598876740357972 + 0.025601009237899111 + 0.025603141773665697 + 0.025605274347635171 + 0.025607406959784949 + 0.02560953961009246 + 0.025611672298535129 + 0.025613805025090319 + 0.025615937789735414 + 0.025618070592447837 + 0.025620203433204949 + 0.025622336311984066 + 0.025624469228762586 + 0.025626602183517797 + 0.025628735176227071 + 0.025630868206867694 + 0.025633001275416966 + 0.02563513438185222 + 0.025637267526150743 + 0.025639400708289753 + 0.025641533928246564 + 0.025643667185998403 + 0.025645800481522544 + 0.025647933814796194 + 0.025650067185796602 + 0.025652200594500955 + 0.025654334040886503 + 0.025656467524930383 + 0.025658601046609792 + 0.025660734605901913 + 0.025662868202783923 + 0.025665001837232949 + 0.025667135509226127 + 0.02566926921874061 + 0.025671402965753497 + 0.025673536750241921 + 0.02567567057218299 + 0.025677804431553732 + 0.025679938328331282 + 0.025682072262492708 + 0.025684206234015048 + 0.025686340242875361 + 0.025688474289050644 + 0.025690608372517982 + 0.025692742493254372 + 0.025694876651236809 + 0.025697010846442297 + 0.025699145078847813 + 0.025701279348430351 + 0.025703413655166835 + 0.025705547999034285 + 0.025707682380009554 + 0.025709816798069659 + 0.025711951253191461 + 0.025714085745351917 + 0.025716220274527905 + 0.02571835484069631 + 0.025720489443834035 + 0.025722624083917928 + 0.025724758760924865 + 0.025726893474831671 + 0.025729028225615208 + 0.025731163013252293 + 0.025733297837719743 + 0.025735432698994372 + 0.025737567597052931 + 0.025739702531872299 + 0.025741837503429173 + 0.025743972511700325 + 0.025746107556662533 + 0.025748242638292548 + 0.025750377756567043 + 0.025752512911462831 + 0.025754648102956544 + 0.025756783331024925 + 0.025758918595644647 + 0.025761053896792382 + 0.02576318923444482 + 0.025765324608578614 + 0.025767460019170407 + 0.02576959546619683 + 0.025771730949634503 + 0.025773866469460078 + 0.02577600202565011 + 0.025778137618181228 + 0.025780273247030007 + 0.025782408912173014 + 0.025784544613586827 + 0.025786680351247974 + 0.025788816125133032 + 0.025790951935218485 + 0.025793087781480876 + 0.025795223663896728 + 0.025797359582442513 + 0.025799495537094718 + 0.025801631527829851 + 0.025803767554624338 + 0.025805903617454669 + 0.025808039716297269 + 0.025810175851128579 + 0.025812312021925007 + 0.025814448228662995 + 0.025816584471318908 + 0.025818720749869149 + 0.025820857064290114 + 0.025822993414558161 + 0.025825129800649653 + 0.025827266222540925 + 0.025829402680208325 + 0.025831539173628171 + 0.025833675702776792 + 0.025835812267630466 + 0.025837948868165511 + 0.0258400855043582 + 0.025842222176184797 + 0.025844358883621583 + 0.025846495626644789 + 0.025848632405230651 + 0.025850769219355425 + 0.025852906068995301 + 0.025855042954126502 + 0.025857179874725196 + 0.025859316830767622 + 0.025861453822229909 + 0.025863590849088201 + 0.025865727911318723 + 0.025867865008897564 + 0.025870002141800841 + 0.025872139310004694 + 0.025874276513485259 + 0.025876413752218587 + 0.025878551026180807 + 0.025880688335347953 + 0.025882825679696114 + 0.025884963059201346 + 0.025887100473839672 + 0.025889237923587136 + 0.025891375408419768 + 0.025893512928313565 + 0.02589565048324452 + 0.025897788073188644 + 0.025899925698121912 + 0.025902063358020234 + 0.025904201052859625 + 0.025906338782616008 + 0.025908476547265354 + 0.025910614346783517 + 0.025912752181146446 + 0.025914890050330049 + 0.025917027954310189 + 0.025919165893062757 + 0.025921303866563602 + 0.025923441874788608 + 0.025925579917713593 + 0.02592771799531441 + 0.025929856107566887 + 0.025931994254446828 + 0.025934132435930003 + 0.025936270651992239 + 0.025938408902609296 + 0.025940547187756936 + 0.025942685507410929 + 0.025944823861547027 + 0.025946962250140929 + 0.025949100673168381 + 0.025951239130605094 + 0.025953377622426766 + 0.025955516148609078 + 0.025957654709127718 + 0.025959793303958322 + 0.025961931933076617 + 0.025964070596458156 + 0.025966209294078627 + 0.025968348025913666 + 0.025970486791938835 + 0.025972625592129747 + 0.025974764426461988 + 0.025976903294911168 + 0.025979042197452829 + 0.025981181134062514 + 0.025983320104715775 + 0.025985459109388175 + 0.025987598148055183 + 0.025989737220692335 + 0.025991876327275114 + 0.025994015467779026 + 0.025996154642179539 + 0.025998293850452103 + 0.026000433092572203 + 0.026002572368515237 + 0.026004711678256673 + 0.026006851021771932 + 0.026008990399036373 + 0.02601112981002543 + 0.026013269254714502 + 0.026015408733078938 + 0.026017548245094096 + 0.026019687790735345 + 0.026021827369978011 + 0.026023966982797426 + 0.026026106629168901 + 0.026028246309067748 + 0.026030386022469272 + 0.026032525769348745 + 0.026034665549681434 + 0.026036805363442619 + 0.026038945210607491 + 0.026041085091151359 + 0.026043225005049395 + 0.026045364952276866 + 0.026047504932808933 + 0.026049644946620789 + 0.02605178499368763 + 0.02605392507398464 + 0.026056065187486939 + 0.026058205334169686 + 0.026060345514007995 + 0.026062485726977041 + 0.026064625973051894 + 0.02606676625220767 + 0.026068906564419451 + 0.026071046909662315 + 0.026073187287911317 + 0.026075327699141532 + 0.026077468143327957 + 0.026079608620445692 + 0.026081749130469699 + 0.026083889673375032 + 0.026086030249136645 + 0.026088170857729541 + 0.026090311499128688 + 0.026092452173309057 + 0.026094592880245574 + 0.026096733619913208 + 0.026098874392286864 + 0.026101015197341457 + 0.026103156035051908 + 0.026105296905393094 + 0.026107437808339889 + 0.026109578743867191 + 0.026111719711949827 + 0.026113860712562647 + 0.026116001745680503 + 0.026118142811278201 + 0.026120283909330543 + 0.026122425039812342 + 0.026124566202698374 + 0.026126707397963456 + 0.026128848625582287 + 0.026130989885529646 + 0.026133131177780291 + 0.026135272502308921 + 0.026137413859090308 + 0.026139555248099085 + 0.026141696669309988 + 0.026143838122697684 + 0.026145979608236843 + 0.026148121125902118 + 0.026150262675668189 + 0.026152404257509664 + 0.026154545871401157 + 0.026156687517317295 + 0.026158829195232682 + 0.026160970905121872 + 0.026163112646959495 + 0.026165254420720079 + 0.026167396226378169 + 0.026169538063908336 + 0.026171679933285095 + 0.026173821834482948 + 0.026175963767476419 + 0.026178105732240001 + 0.026180247728748149 + 0.026182389756975365 + 0.026184531816896093 + 0.026186673908484781 + 0.026188816031715884 + 0.026190958186563768 + 0.026193100373002876 + 0.026195242591007646 + 0.026197384840552392 + 0.026199527121611534 + 0.026201669434159414 + 0.026203811778170407 + 0.026205954153618833 + 0.026208096560479028 + 0.026210238998725269 + 0.026212381468331922 + 0.026214523969273235 + 0.026216666501523503 + 0.026218809065057001 + 0.026220951659847967 + 0.026223094285870639 + 0.026225236943099261 + 0.026227379631508074 + 0.02622952235107124 + 0.02623166510176296 + 0.026233807883557468 + 0.026235950696428881 + 0.026238093540351382 + 0.026240236415299122 + 0.02624237932124621 + 0.026244522258166817 + 0.026246665226034988 + 0.026248808224824879 + 0.02625095125451055 + 0.026253094315066079 + 0.026255237406465536 + 0.026257380528682962 + 0.026259523681692414 + 0.026261666865467898 + 0.026263810079983428 + 0.026265953325213018 + 0.026268096601130646 + 0.026270239907710335 + 0.026272383244925965 + 0.026274526612751557 + 0.026276670011161039 + 0.026278813440128335 + 0.026280956899627363 + 0.026283100389632032 + 0.026285243910116211 + 0.026287387461053805 + 0.026289531042418698 + 0.026291674654184728 + 0.026293818296325714 + 0.026295961968815527 + 0.026298105671627985 + 0.026300249404736856 + 0.026302393168115973 + 0.026304536961739122 + 0.026306680785580044 + 0.0263088246396125 + 0.026310968523810253 + 0.02631311243814706 + 0.026315256382596599 + 0.026317400357132613 + 0.026319544361728755 + 0.026321688396358733 + 0.026323832460996253 + 0.026325976555614937 + 0.026328120680188433 + 0.026330264834690399 + 0.026332409019094456 + 0.026334553233374178 + 0.026336697477503196 + 0.026338841751455094 + 0.026340986055203464 + 0.026343130388721797 + 0.026345274751983727 + 0.026347419144962761 + 0.026349563567632402 + 0.026351708019966169 + 0.026353852501937572 + 0.026355997013520135 + 0.026358141554687242 + 0.026360286125412448 + 0.026362430725669145 + 0.026364575355430773 + 0.026366720014670792 + 0.026368864703362586 + 0.026371009421479557 + 0.026373154168995137 + 0.026375298945882631 + 0.026377443752115447 + 0.026379588587666904 + 0.026381733452510381 + 0.026383878346619156 + 0.026386023269966592 + 0.026388168222525935 + 0.02639031320427054 + 0.026392458215173619 + 0.026394603255208458 + 0.02639674832434832 + 0.026398893422566402 + 0.026401038549835987 + 0.026403183706130266 + 0.026405328891422414 + 0.026407474105685634 + 0.026409619348893108 + 0.026411764621017981 + 0.026413909922033428 + 0.026416055251912554 + 0.026418200610628523 + 0.026420345998154401 + 0.026422491414463331 + 0.026424636859528366 + 0.026426782333322581 + 0.026428927835819051 + 0.026431073366990836 + 0.026433218926810935 + 0.026435364515252423 + 0.026437510132288275 + 0.026439655777891466 + 0.026441801452035035 + 0.026443947154691911 + 0.026446092885835087 + 0.02644823864543748 + 0.026450384433472033 + 0.026452530249911684 + 0.026454676094729318 + 0.026456821967897837 + 0.026458967869390143 + 0.026461113799179085 + 0.026463259757237532 + 0.026465405743538326 + 0.026467551758054288 + 0.026469697800758252 + 0.026471843871623008 + 0.026473989970621361 + 0.026476136097726099 + 0.026478282252909973 + 0.026480428436145762 + 0.026482574647406162 + 0.026484720886663961 + 0.026486867153891841 + 0.026489013449062491 + 0.026491159772148644 + 0.026493306123122951 + 0.026495452501958054 + 0.026497598908626664 + 0.026499745343101382 + 0.026501891805354841 + 0.026504038295359654 + 0.026506184813088411 + 0.026508331358513736 + 0.02651047793160816 + 0.026512624532344261 + 0.026514771160694586 + 0.026516917816631669 + 0.026519064500128049 + 0.026521211211156203 + 0.026523357949688676 + 0.026525504715697906 + 0.02652765150915638 + 0.026529798330036561 + 0.026531945178310892 + 0.0265340920539518 + 0.026536238956931718 + 0.026538385887223011 + 0.026540532844798112 + 0.026542679829629389 + 0.026544826841689198 + 0.026546973880949905 + 0.026549120947383872 + 0.026551268040963361 + 0.026553415161660751 + 0.026555562309448312 + 0.026557709484298326 + 0.026559856686183086 + 0.026562003915074843 + 0.026564151170945845 + 0.026566298453768362 + 0.02656844576351455 + 0.026570593100156664 + 0.026572740463666904 + 0.026574887854017404 + 0.026577035271180389 + 0.026579182715127977 + 0.026581330185832343 + 0.026583477683265581 + 0.026585625207399832 + 0.026587772758207208 + 0.02658992033565977 + 0.026592067939729624 + 0.02659421557038881 + 0.026596363227609398 + 0.026598510911363397 + 0.026600658621622853 + 0.026602806358359789 + 0.026604954121546169 + 0.026607101911154004 + 0.026609249727155233 + 0.026611397569521866 + 0.026613545438225805 + 0.026615693333238977 + 0.026617841254533325 + 0.026619989202080748 + 0.026622137175853131 + 0.026624285175822333 + 0.026626433201960249 + 0.026628581254238726 + 0.026630729332629555 + 0.026632877437104636 + 0.026635025567635723 + 0.026637173724194638 + 0.026639321906753149 + 0.02664147011528303 + 0.026643618349756041 + 0.026645766610143933 + 0.026647914896418424 + 0.026650063208551247 + 0.026652211546514083 + 0.026654359910278626 + 0.02665650829981657 + 0.026658656715099552 + 0.026660805156099251 + 0.026662953622787266 + 0.026665102115135252 + 0.026667250633114783 + 0.0266693991766975 + 0.026671547745854954 + 0.02667369634055872 + 0.026675844960780331 + 0.026677993606491372 + 0.026680142277663316 + 0.02668229097426773 + 0.02668443969627609 + 0.026686588443659884 + 0.026688737216390555 + 0.026690886014439631 + 0.02669303483777849 + 0.026695183686378601 + 0.026697332560211361 + 0.026699481459248189 + 0.026701630383460493 + 0.026703779332819613 + 0.026705928307296917 + 0.026708077306863795 + 0.026710226331491543 + 0.026712375381151513 + 0.026714524455814966 + 0.026716673555453256 + 0.026718822680037637 + 0.026720971829539371 + 0.02672312100392972 + 0.02672527020317992 + 0.026727419427261208 + 0.026729568676144781 + 0.026731717949801847 + 0.026733867248203626 + 0.026736016571321207 + 0.026738165919125801 + 0.02674031529158857 + 0.026742464688680613 + 0.026744614110373047 + 0.02674676355663699 + 0.026748913027443512 + 0.02675106252276372 + 0.026753212042568631 + 0.026755361586829302 + 0.026757511155516812 + 0.026759660748602112 + 0.026761810366056269 + 0.026763960007850227 + 0.026766109673954996 + 0.026768259364341525 + 0.026770409078980761 + 0.026772558817843666 + 0.026774708580901131 + 0.026776858368124056 + 0.026779008179483376 + 0.026781158014949961 + 0.026783307874494639 + 0.026785457758088271 + 0.026787607665701759 + 0.026789757597305862 + 0.026791907552871384 + 0.026794057532369173 + 0.026796207535769972 + 0.026798357563044564 + 0.026800507614163714 + 0.026802657689098123 + 0.026804807787818564 + 0.026806957910295717 + 0.026809108056500285 + 0.026811258226402977 + 0.026813408419974424 + 0.026815558637185297 + 0.02681770887800625 + 0.026819859142407913 + 0.02682200943036088 + 0.026824159741835732 + 0.026826310076803112 + 0.026828460435233542 + 0.026830610817097603 + 0.026832761222365827 + 0.026834911651008733 + 0.026837062102996866 + 0.026839212578300697 + 0.026841363076890716 + 0.026843513598737403 + 0.026845664143811218 + 0.026847814712082595 + 0.026849965303521978 + 0.026852115918099741 + 0.026854266555786349 + 0.026856417216552131 + 0.026858567900367492 + 0.02686071860720278 + 0.026862869337028313 + 0.026865020089814434 + 0.026867170865531489 + 0.026869321664149771 + 0.026871472485639519 + 0.026873623329971057 + 0.026875774197114607 + 0.026877925087040455 + 0.02688007599971878 + 0.026882226935119821 + 0.026884377893213771 + 0.02688652887397084 + 0.026888679877361151 + 0.026890830903354895 + 0.026892981951922204 + 0.026895133023033219 + 0.026897284116658038 + 0.026899435232766764 + 0.026901586371329483 + 0.026903737532316285 + 0.026905888715697192 + 0.02690803992144224 + 0.026910191149521496 + 0.026912342399904941 + 0.026914493672562576 + 0.026916644967464411 + 0.026918796284580385 + 0.026920947623880465 + 0.026923098985334584 + 0.026925250368912662 + 0.026927401774584626 + 0.026929553202320336 + 0.026931704652089727 + 0.026933856123862652 + 0.026936007617608931 + 0.02693815913329841 + 0.026940310670900934 + 0.026942462230386308 + 0.026944613811724312 + 0.026946765414884732 + 0.026948917039837324 + 0.026951068686551852 + 0.026953220354998038 + 0.026955372045145604 + 0.02695752375696428 + 0.026959675490423725 + 0.026961827245493623 + 0.026963979022143633 + 0.026966130820343423 + 0.026968282640062596 + 0.026970434481270809 + 0.026972586343937621 + 0.02697473822803265 + 0.026976890133525444 + 0.026979042060385573 + 0.026981194008582617 + 0.026983345978086035 + 0.026985497968865391 + 0.02698764998089016 + 0.026989802014129843 + 0.026991954068553918 + 0.026994106144131797 + 0.026996258240832984 + 0.02699841035862683 + 0.027000562497482793 + 0.027002714657370253 + 0.027004866838258607 + 0.027007019040117219 + 0.027009171262915403 + 0.027011323506622525 + 0.027013475771207919 + 0.027015628056640869 + 0.02701778036289066 + 0.027019932689926578 + 0.027022085037717889 + 0.027024237406233834 + 0.027026389795443632 + 0.027028542205316523 + 0.027030694635821698 + 0.027032847086928331 + 0.027034999558605603 + 0.027037152050822685 + 0.027039304563548666 + 0.02704145709675275 + 0.027043609650403987 + 0.027045762224471488 + 0.027047914818924358 + 0.027050067433731603 + 0.027052220068862348 + 0.02705437272428559 + 0.027056525399970329 + 0.027058678095885601 + 0.027060830812000395 + 0.027062983548283688 + 0.027065136304704411 + 0.027067289081231547 + 0.027069441877834 + 0.027071594694480696 + 0.027073747531140526 + 0.027075900387782372 + 0.027078053264375103 + 0.027080206160887587 + 0.027082359077288638 + 0.027084512013547113 + 0.027086664969631791 + 0.027088817945511462 + 0.027090970941154931 + 0.027093123956530935 + 0.027095276991608241 + 0.027097430046355543 + 0.027099583120741597 + 0.027101736214735071 + 0.027103889328304712 + 0.027106042461419098 + 0.027108195614046957 + 0.027110348786156896 + 0.027112501977717553 + 0.027114655188697521 + 0.027116808419065427 + 0.027118961668789788 + 0.027121114937839228 + 0.027123268226182246 + 0.027125421533787403 + 0.02712757486062323 + 0.027129728206658179 + 0.027131881571860764 + 0.027134034956199479 + 0.027136188359642731 + 0.027138341782158983 + 0.027140495223716653 + 0.027142648684284145 + 0.027144802163829879 + 0.027146955662322197 + 0.027149109179729482 + 0.027151262716020048 + 0.027153416271162283 + 0.02715556984512444 + 0.027157723437874867 + 0.027159877049381807 + 0.027162030679613557 + 0.027164184328538357 + 0.027166337996124463 + 0.027168491682340066 + 0.027170645387153376 + 0.027172799110532598 + 0.027174952852445915 + 0.027177106612861452 + 0.027179260391747364 + 0.027181414189071815 + 0.027183568004802854 + 0.027185721838908654 + 0.027187875691357211 + 0.027190029562116642 + 0.027192183451154973 + 0.027194337358440235 + 0.027196491283940482 + 0.027198645227623667 + 0.02720079918945785 + 0.02720295316941089 + 0.02720510716745082 + 0.027207261183545561 + 0.027209415217663045 + 0.027211569269771148 + 0.027213723339837782 + 0.027215877427830847 + 0.027218031533718139 + 0.02722018565746755 + 0.027222339799046914 + 0.027224493958423981 + 0.027226648135566609 + 0.027228802330442555 + 0.027230956543019595 + 0.027233110773265481 + 0.027235265021147894 + 0.027237419286634607 + 0.027239573569693309 + 0.027241727870291679 + 0.027243882188397347 + 0.027246036523978029 + 0.027248190877001328 + 0.027250345247434853 + 0.027252499635246244 + 0.027254654040403066 + 0.027256808462872883 + 0.027258962902623265 + 0.027261117359621754 + 0.027263271833835871 + 0.027265426325233114 + 0.027267580833780974 + 0.027269735359446948 + 0.027271889902198476 + 0.027274044462003013 + 0.027276199038827977 + 0.027278353632640799 + 0.027280508243408833 + 0.027282662871099497 + 0.027284817515680144 + 0.027286972177118105 + 0.027289126855380739 + 0.027291281550435347 + 0.027293436262249195 + 0.027295590990789608 + 0.027297745736023841 + 0.027299900497919121 + 0.027302055276442729 + 0.027304210071561839 + 0.027306364883243658 + 0.027308519711455388 + 0.027310674556164146 + 0.027312829417337169 + 0.027314984294941547 + 0.027317139188944357 + 0.027319294099312767 + 0.027321449026013852 + 0.027323603969014655 + 0.027325758928282241 + 0.027327913903783658 + 0.027330068895485914 + 0.027332223903356007 + 0.027334378927360937 + 0.027336533967467682 + 0.027338689023643187 + 0.027340844095854404 + 0.027342999184068226 + 0.0273451542882516 + 0.027347309408371365 + 0.02734946454439444 + 0.02735161969628765 + 0.027353774864017855 + 0.027355930047551869 + 0.02735808524685648 + 0.027360240461898531 + 0.027362395692644738 + 0.027364550939061903 + 0.027366706201116725 + 0.027368861478775965 + 0.027371016772006328 + 0.027373172080774465 + 0.027375327405047081 + 0.027377482744790821 + 0.027379638099972334 + 0.027381793470558261 + 0.027383948856515194 + 0.027386104257809716 + 0.027388259674408388 + 0.027390415106277797 + 0.027392570553384499 + 0.027394726015694967 + 0.027396881493175727 + 0.027399036985793296 + 0.02740119249351412 + 0.02740334801630467 + 0.027405503554131381 + 0.027407659106960663 + 0.027409814674758944 + 0.027411970257492625 + 0.027414125855128046 + 0.027416281467631566 + 0.027418437094969557 + 0.027420592737108309 + 0.027422748394014131 + 0.027424904065653326 + 0.027427059751992174 + 0.027429215452996911 + 0.02743137116863379 + 0.027433526898868989 + 0.027435682643668788 + 0.027437838402999296 + 0.027439994176826746 + 0.027442149965117263 + 0.027444305767836984 + 0.027446461584952047 + 0.027448617416428515 + 0.027450773262232518 + 0.027452929122330074 + 0.027455084996687286 + 0.027457240885270191 + 0.027459396788044765 + 0.027461552704977014 + 0.027463708636032945 + 0.027465864581178511 + 0.027468020540379678 + 0.027470176513602357 + 0.02747233250081246 + 0.027474488501975897 + 0.027476644517058533 + 0.027478800546026264 + 0.027480956588844925 + 0.02748311264548034 + 0.027485268715898299 + 0.027487424800064626 + 0.027489580897945086 + 0.027491737009505461 + 0.027493893134711466 + 0.027496049273528823 + 0.027498205425923291 + 0.027500361591860492 + 0.027502517771306158 + 0.027504673964225897 + 0.027506830170585403 + 0.027508986390350237 + 0.02751114262348606 + 0.027513298869958423 + 0.027515455129732913 + 0.027517611402775088 + 0.027519767689050484 + 0.027521923988524578 + 0.027524080301162938 + 0.027526236626930975 + 0.027528392965794211 + 0.027530549317718079 + 0.027532705682668007 + 0.027534862060609417 + 0.027537018451507706 + 0.027539174855328207 + 0.027541331272036351 + 0.027543487701597438 + 0.027545644143976814 + 0.027547800599139766 + 0.027549957067051621 + 0.027552113547677611 + 0.027554270040983014 + 0.02755642654693307 + 0.027558583065493011 + 0.027560739596628001 + 0.02756289614030329 + 0.027565052696483964 + 0.027567209265135232 + 0.027569365846222233 + 0.027571522439710044 + 0.027573679045563796 + 0.027575835663748521 + 0.027577992294229355 + 0.027580148936971284 + 0.027582305591939346 + 0.027584462259098573 + 0.027586618938413937 + 0.027588775629850404 + 0.027590932333372939 + 0.027593089048946501 + 0.027595245776535986 + 0.027597402516106304 + 0.027599559267622347 + 0.027601716031048967 + 0.027603872806351036 + 0.027606029593493342 + 0.027608186392440736 + 0.027610343203158007 + 0.027612500025609932 + 0.027614656859761284 + 0.027616813705576775 + 0.027618970563021157 + 0.027621127432059106 + 0.027623284312655351 + 0.027625441204774542 + 0.027627598108381304 + 0.027629755023440311 + 0.027631911949916162 + 0.027634068887773471 + 0.027636225836976804 + 0.027638382797490715 + 0.027640539769279777 + 0.027642696752308495 + 0.027644853746541399 + 0.027647010751942928 + 0.027649167768477617 + 0.027651324796109867 + 0.027653481834804147 + 0.027655638884524877 + 0.027657795945236451 + 0.027659953016903237 + 0.027662110099489604 + 0.027664267192959915 + 0.027666424297278485 + 0.027668581412409618 + 0.027670738538317613 + 0.027672895674966731 + 0.027675052822321217 + 0.027677209980345358 + 0.027679367149003306 + 0.027681524328259308 + 0.027683681518077551 + 0.027685838718422152 + 0.027687995929257286 + 0.027690153150547091 + 0.027692310382255631 + 0.027694467624347033 + 0.027696624876785363 + 0.027698782139534701 + 0.027700939412559005 + 0.027703096695822358 + 0.027705253989288758 + 0.027707411292922136 + 0.027709568606686479 + 0.02771172593054573 + 0.027713883264463841 + 0.027716040608404678 + 0.027718197962332145 + 0.027720355326210113 + 0.027722512700002443 + 0.027724670083672923 + 0.027726827477185405 + 0.027728984880503665 + 0.027731142293591523 + 0.027733299716412679 + 0.027735457148930887 + 0.027737614591109867 + 0.02773977204291337 + 0.02774192950430503 + 0.027744086975248498 + 0.027746244455707454 + 0.027748401945645519 + 0.027750559445026305 + 0.027752716953813369 + 0.027754874471970337 + 0.027757031999460717 + 0.02775918953624807 + 0.027761347082295888 + 0.027763504637567691 + 0.027765662202026944 + 0.027767819775637116 + 0.027769977358361595 + 0.027772134950163903 + 0.027774292551007353 + 0.0277764501608554 + 0.027778607779671328 + 0.027780765407418549 + 0.02778292304406035 + 0.027785080689560079 + 0.027787238343880992 + 0.027789396006986378 + 0.027791553678839481 + 0.027793711359403526 + 0.027795869048641744 + 0.027798026746517331 + 0.027800184452993433 + 0.027802342168033241 + 0.027804499891599894 + 0.02780665762365649 + 0.027808815364166125 + 0.027810973113091903 + 0.027813130870396881 + 0.027815288636044076 + 0.027817446409996543 + 0.027819604192217285 + 0.027821761982669283 + 0.027823919781315477 + 0.027826077588118843 + 0.027828235403042322 + 0.027830393226048789 + 0.027832551057101158 + 0.027834708896162293 + 0.027836866743195042 + 0.027839024598162225 + 0.027841182461026681 + 0.027843340331751214 + 0.027845498210298563 + 0.027847656096631503 + 0.027849813990712749 + 0.027851971892505063 + 0.027854129801971106 + 0.027856287719073568 + 0.027858445643775112 + 0.027860603576038361 + 0.027862761515825951 + 0.027864919463100494 + 0.027867077417824564 + 0.027869235379960691 + 0.02787139334947145 + 0.027873551326319374 + 0.027875709310466949 + 0.027877867301876677 + 0.02788002530051099 + 0.027882183306332353 + 0.027884341319303212 + 0.027886499339385935 + 0.027888657366542943 + 0.027890815400736589 + 0.027892973441929231 + 0.027895131490083172 + 0.027897289545160762 + 0.027899447607124258 + 0.027901605675935942 + 0.027903763751558078 + 0.027905921833952865 + 0.02790807992308254 + 0.027910238018909274 + 0.027912396121395271 + 0.027914554230502656 + 0.027916712346193587 + 0.02791887046843014 + 0.027921028597174428 + 0.027923186732388538 + 0.027925344874034506 + 0.027927503022074397 + 0.02792966117647017 + 0.02793181933718385 + 0.027933977504177424 + 0.027936135677412821 + 0.027938293856852012 + 0.027940452042456893 + 0.027942610234189327 + 0.027944768432011245 + 0.027946926635884481 + 0.027949084845770866 + 0.027951243061632203 + 0.027953401283430317 + 0.027955559511126972 + 0.027957717744683905 + 0.027959875984062878 + 0.027962034229225632 + 0.0279641924801338 + 0.027966350736749104 + 0.027968508999033175 + 0.027970667266947646 + 0.027972825540454167 + 0.02797498381951433 + 0.027977142104089667 + 0.027979300394141794 + 0.027981458689632192 + 0.0279836169905224 + 0.027985775296773933 + 0.02798793360834825 + 0.027990091925206805 + 0.027992250247311026 + 0.027994408574622334 + 0.027996566907102127 + 0.027998725244711802 + 0.028000883587412685 + 0.028003041935166097 + 0.028005200287933383 + 0.028007358645675835 + 0.0280095170083547 + 0.028011675375931255 + 0.028013833748366718 + 0.028015992125622335 + 0.02801815050765925 + 0.02802030889443867 + 0.028022467285921723 + 0.028024625682069561 + 0.02802678408284328 + 0.028028942488203996 + 0.028031100898112747 + 0.028033259312530586 + 0.028035417731418547 + 0.028037576154737693 + 0.028039734582448923 + 0.028041893014513233 + 0.028044051450891602 + 0.028046209891544941 + 0.028048368336434124 + 0.028050526785520093 + 0.028052685238763673 + 0.028054843696125716 + 0.02805700215756704 + 0.02805916062304847 + 0.028061319092530786 + 0.028063477565974722 + 0.028065636043341058 + 0.028067794524590475 + 0.028069953009683696 + 0.028072111498581392 + 0.028074269991244231 + 0.028076428487632855 + 0.028078586987707873 + 0.028080745491429887 + 0.028082903998759429 + 0.028085062509657126 + 0.028087221024083439 + 0.02808937954199895 + 0.028091538063364129 + 0.028093696588139417 + 0.028095855116285325 + 0.028098013647762193 + 0.028100172182530504 + 0.028102330720550624 + 0.028104489261782908 + 0.028106647806187716 + 0.028108806353725393 + 0.02811096490435621 + 0.02811312345804045 + 0.028115282014738386 + 0.028117440574410291 + 0.028119599137016338 + 0.028121757702516716 + 0.028123916270871657 + 0.028126074842041281 + 0.028128233415985738 + 0.028130391992665139 + 0.028132550572039599 + 0.028134709154069147 + 0.028136867738713836 + 0.02813902632593375 + 0.02814118491568884 + 0.028143343507939143 + 0.0281455021026446 + 0.028147660699765147 + 0.028149819299260723 + 0.028151977901091235 + 0.028154136505216532 + 0.028156295111596535 + 0.028158453720191025 + 0.028160612330959862 + 0.028162770943862814 + 0.028164929558859672 + 0.028167088175910179 + 0.028169246794974075 + 0.028171405416011083 + 0.028173564038980855 + 0.028175722663843099 + 0.028177881290557445 + 0.028180039919083539 + 0.028182198549380946 + 0.02818435718140927 + 0.028186515815128071 + 0.028188674450496876 + 0.028190833087475234 + 0.028192991726022628 + 0.028195150366098501 + 0.028197309007662361 + 0.028199467650673611 + 0.028201626295091656 + 0.02820378494087588 + 0.02820594358798565 + 0.028208102236380355 + 0.02821026088601928 + 0.02821241953686171 + 0.028214578188866975 + 0.028216736841994307 + 0.028218895496202916 + 0.028221054151452062 + 0.028223212807700924 + 0.028225371464908638 + 0.028227530123034424 + 0.028229688782037372 + 0.028231847441876564 + 0.028234006102511113 + 0.028236164763900087 + 0.0282383234260025 + 0.028240482088777403 + 0.028242640752183763 + 0.028244799416180567 + 0.028246958080726765 + 0.028249116745781299 + 0.028251275411303053 + 0.02825343407725097 + 0.028255592743583857 + 0.028257751410260584 + 0.02825991007723996 + 0.028262068744480763 + 0.028264227411941838 + 0.028266386079581859 + 0.028268544747359622 + 0.02827070341523381 + 0.028272862083163115 + 0.028275020751106203 + 0.028277179419021723 + 0.028279338086868291 + 0.02828149675460449 + 0.028283655422188941 + 0.028285814089580152 + 0.028287972756736706 + 0.028290131423617061 + 0.028292290090179747 + 0.028294448756383195 + 0.028296607422185881 + 0.02829876608754623 + 0.028300924752422595 + 0.0283030834167734 + 0.02830524208055701 + 0.028307400743731691 + 0.028309559406255812 + 0.028311718068087629 + 0.028313876729185443 + 0.028316035389507457 + 0.028318194049011907 + 0.028320352707656989 + 0.028322511365400902 + 0.028324670022201754 + 0.028326828678017703 + 0.028328987332806876 + 0.028331145986527292 + 0.028333304639137104 + 0.028335463290594262 + 0.028337621940856834 + 0.028339780589882811 + 0.028341939237630173 + 0.028344097884056847 + 0.028346256529120768 + 0.028348415172779844 + 0.028350573814991963 + 0.028352732455714964 + 0.028354891094906687 + 0.028357049732524946 + 0.028359208368527542 + 0.028361367002872243 + 0.028363525635516782 + 0.028365684266418893 + 0.02836784289553625 + 0.028370001522826569 + 0.028372160148247474 + 0.028374318771756599 + 0.028376477393311568 + 0.028378636012869933 + 0.028380794630389269 + 0.028382953245827153 + 0.028385111859141034 + 0.028387270470288474 + 0.028389429079226897 + 0.028391587685913745 + 0.028393746290306478 + 0.028395904892362468 + 0.028398063492039098 + 0.028400222089293724 + 0.028402380684083676 + 0.028404539276366259 + 0.028406697866098778 + 0.028408856453238471 + 0.028411015037742592 + 0.028413173619568344 + 0.028415332198672913 + 0.028417490775013481 + 0.02841964934854721 + 0.028421807919231178 + 0.028423966487022525 + 0.028426125051878331 + 0.028428283613755607 + 0.028430442172611408 + 0.028432600728402754 + 0.028434759281086582 + 0.028436917830619909 + 0.028439076376959627 + 0.02844123492006264 + 0.028443393459885898 + 0.028445551996386209 + 0.028447710529520435 + 0.028449869059245386 + 0.028452027585517861 + 0.02845418610829465 + 0.028456344627532468 + 0.028458503143188079 + 0.028460661655218128 + 0.028462820163579344 + 0.02846497866822836 + 0.028467137169121821 + 0.028469295666216293 + 0.028471454159468387 + 0.028473612648834669 + 0.028475771134271657 + 0.028477929615735881 + 0.028480088093183788 + 0.028482246566571879 + 0.028484405035856603 + 0.028486563500994343 + 0.028488721961941514 + 0.028490880418654486 + 0.028493038871089588 + 0.028495197319203157 + 0.028497355762951475 + 0.028499514202290813 + 0.028501672637177435 + 0.028503831067567559 + 0.028505989493417403 + 0.028508147914683101 + 0.028510306331320841 + 0.028512464743286777 + 0.02851462315053695 + 0.028516781553027473 + 0.028518939950714427 + 0.028521098343553819 + 0.028523256731501641 + 0.028525415114513925 + 0.028527573492546577 + 0.028529731865555578 + 0.028531890233496841 + 0.028534048596326224 + 0.028536206953999606 + 0.028538365306472829 + 0.028540523653701678 + 0.028542681995641989 + 0.028544840332249535 + 0.028546998663480018 + 0.028549156989289167 + 0.028551315309632699 + 0.028553473624466277 + 0.028555631933745537 + 0.028557790237426078 + 0.028559948535463515 + 0.02856210682781346 + 0.028564265114431404 + 0.028566423395272895 + 0.028568581670293428 + 0.028570739939448482 + 0.028572898202693497 + 0.02857505645998391 + 0.028577214711275122 + 0.028579372956522488 + 0.028581531195681398 + 0.028583689428707152 + 0.028585847655555035 + 0.028588005876180364 + 0.02859016409053837 + 0.028592322298584293 + 0.028594480500273325 + 0.028596638695560634 + 0.028598796884401412 + 0.028600955066750769 + 0.028603113242563812 + 0.028605271411795575 + 0.028607429574401193 + 0.028609587730335638 + 0.028611745879553958 + 0.028613904022011073 + 0.02861606215766202 + 0.028618220286461642 + 0.028620378408364917 + 0.028622536523326688 + 0.028624694631301829 + 0.028626852732245151 + 0.028629010826111474 + 0.028631168912855585 + 0.028633326992432227 + 0.028635485064796119 + 0.028637643129901996 + 0.028639801187704539 + 0.028641959238158345 + 0.028644117281218132 + 0.02864627531683845 + 0.028648433344973873 + 0.028650591365578994 + 0.028652749378608334 + 0.028654907384016361 + 0.028657065381757604 + 0.028659223371786478 + 0.028661381354057408 + 0.028663539328524834 + 0.028665697295143126 + 0.028667855253866618 + 0.028670013204649632 + 0.028672171147446503 + 0.028674329082211472 + 0.028676487008898837 + 0.028678644927462749 + 0.02868080283785748 + 0.028682960740037164 + 0.028685118633955967 + 0.028687276519568008 + 0.028689434396827369 + 0.028691592265688171 + 0.028693750126104405 + 0.028695907978030111 + 0.028698065821419299 + 0.028700223656225956 + 0.028702381482403956 + 0.028704539299907288 + 0.028706697108689828 + 0.028708854908705436 + 0.028711012699907928 + 0.028713170482251131 + 0.028715328255688892 + 0.028717486020174904 + 0.028719643775662947 + 0.02872180152210671 + 0.028723959259459888 + 0.028726116987676159 + 0.028728274706709144 + 0.028730432416512422 + 0.028732590117039651 + 0.028734747808244317 + 0.028736905490079959 + 0.028739063162500123 + 0.028741220825458276 + 0.028743378478907858 + 0.028745536122802288 + 0.028747693757094971 + 0.028749851381739293 + 0.028752008996688592 + 0.028754166601896232 + 0.028756324197315435 + 0.028758481782899532 + 0.028760639358601743 + 0.028762796924375313 + 0.028764954480173379 + 0.02876711202594915 + 0.028769269561655743 + 0.02877142708724631 + 0.028773584602673905 + 0.028775742107891578 + 0.028777899602852371 + 0.028780057087509317 + 0.028782214561815352 + 0.028784372025723492 + 0.028786529479186626 + 0.028788686922157639 + 0.028790844354589434 + 0.028793001776434877 + 0.028795159187646756 + 0.02879731658817786 + 0.02879947397798098 + 0.028801631357008882 + 0.028803788725214257 + 0.028805946082549765 + 0.028808103428968099 + 0.028810260764421905 + 0.028812418088863801 + 0.028814575402246318 + 0.028816732704522053 + 0.028818889995643537 + 0.028821047275563252 + 0.028823204544233687 + 0.028825361801607281 + 0.028827519047636484 + 0.028829676282273644 + 0.028831833505471166 + 0.028833990717181377 + 0.0288361479173566 + 0.02883830510594913 + 0.028840462282911192 + 0.028842619448195071 + 0.028844776601752928 + 0.028846933743536956 + 0.028849090873499329 + 0.028851247991592163 + 0.028853405097767525 + 0.028855562191977505 + 0.028857719274174184 + 0.028859876344309546 + 0.028862033402335577 + 0.028864190448204263 + 0.028866347481867494 + 0.028868504503277215 + 0.028870661512385317 + 0.028872818509143625 + 0.028874975493503992 + 0.028877132465418197 + 0.028879289424838004 + 0.028881446371715171 + 0.02888360330600143 + 0.028885760227648456 + 0.028887917136607905 + 0.028890074032831441 + 0.02889223091627063 + 0.028894387786877078 + 0.028896544644602312 + 0.028898701489397896 + 0.028900858321215302 + 0.028903015140006014 + 0.028905171945721467 + 0.02890732873831307 + 0.028909485517732193 + 0.028911642283930228 + 0.028913799036858513 + 0.028915955776468313 + 0.028918112502710949 + 0.028920269215537621 + 0.028922425914899592 + 0.028924582600748011 + 0.028926739273034095 + 0.028928895931708953 + 0.028931052576723695 + 0.028933209208029421 + 0.028935365825577125 + 0.028937522429317911 + 0.028939679019202733 + 0.028941835595182572 + 0.028943992157208373 + 0.028946148705231035 + 0.028948305239201454 + 0.028950461759070505 + 0.028952618264788982 + 0.0289547747563077 + 0.028956931233577451 + 0.028959087696548952 + 0.028961244145172944 + 0.028963400579400101 + 0.028965556999181095 + 0.028967713404466557 + 0.028969869795207062 + 0.028972026171353246 + 0.028974182532855594 + 0.028976338879664668 + 0.028978495211730928 + 0.028980651529004874 + 0.028982807831436905 + 0.028984964118977427 + 0.02898712039157687 + 0.028989276649185509 + 0.028991432891753717 + 0.028993589119231767 + 0.028995745331569914 + 0.028997901528718412 + 0.029000057710627459 + 0.029002213877247229 + 0.029004370028527876 + 0.029006526164419528 + 0.029008682284872248 + 0.029010838389836143 + 0.029012994479261197 + 0.02901515055309746 + 0.029017306611294879 + 0.029019462653803417 + 0.029021618680573021 + 0.029023774691553511 + 0.029025930686694804 + 0.029028086665946719 + 0.029030242629259045 + 0.029032398576581585 + 0.029034554507864095 + 0.029036710423056236 + 0.029038866322107729 + 0.029041022204968236 + 0.029043178071587405 + 0.029045333921914791 + 0.029047489755900012 + 0.029049645573492582 + 0.029051801374642014 + 0.029053957159297809 + 0.029056112927409426 + 0.029058268678926254 + 0.029060424413797734 + 0.029062580131973229 + 0.029064735833402053 + 0.029066891518033527 + 0.029069047185816953 + 0.029071202836701546 + 0.029073358470636534 + 0.029075514087571114 + 0.029077669687454465 + 0.029079825270235695 + 0.029081980835863927 + 0.029084136384288233 + 0.029086291915457651 + 0.029088447429321197 + 0.029090602925827855 + 0.029092758404926575 + 0.029094913866566315 + 0.029097069310695944 + 0.029099224737264329 + 0.029101380146220317 + 0.029103535537512694 + 0.029105690911090262 + 0.029107846266901778 + 0.02911000160489596 + 0.029112156925021462 + 0.029114312227226977 + 0.029116467511461103 + 0.029118622777672479 + 0.029120778025809649 + 0.029122933255821142 + 0.029125088467655515 + 0.029127243661261196 + 0.029129398836586669 + 0.029131553993580316 + 0.029133709132190568 + 0.029135864252365765 + 0.029138019354054252 + 0.029140174437204298 + 0.029142329501764208 + 0.02914448454768219 + 0.029146639574906468 + 0.029148794583385235 + 0.029150949573066628 + 0.029153104543898745 + 0.029155259495829693 + 0.029157414428807531 + 0.029159569342780297 + 0.029161724237695957 + 0.029163879113502517 + 0.029166033970147887 + 0.029168188807580001 + 0.029170343625746664 + 0.029172498424595808 + 0.029174653204075203 + 0.029176807964132637 + 0.029178962704715882 + 0.029181117425772635 + 0.029183272127250613 + 0.029185426809097442 + 0.029187581471260805 + 0.029189736113688251 + 0.0291918907363274 + 0.02919404533912574 + 0.029196199922030801 + 0.029198354484990079 + 0.029200509027951002 + 0.029202663550860986 + 0.029204818053667439 + 0.029206972536317703 + 0.02920912699875906 + 0.029211281440938854 + 0.029213435862804348 + 0.029215590264302756 + 0.029217744645381242 + 0.029219899005987052 + 0.029222053346067256 + 0.029224207665568998 + 0.029226361964439326 + 0.029228516242625326 + 0.029230670500073965 + 0.029232824736732273 + 0.029234978952547157 + 0.029237133147465563 + 0.029239287321434378 + 0.029241441474400436 + 0.029243595606310572 + 0.029245749717111625 + 0.029247903806750301 + 0.029250057875173343 + 0.029252211922327447 + 0.029254365948159351 + 0.029256519952615589 + 0.029258673935642826 + 0.029260827897187636 + 0.029262981837196556 + 0.029265135755616067 + 0.029267289652392708 + 0.029269443527472901 + 0.029271597380803031 + 0.029273751212329519 + 0.02927590502199872 + 0.029278058809756938 + 0.029280212575550479 + 0.029282366319325577 + 0.029284520041028477 + 0.029286673740605378 + 0.029288827418002424 + 0.029290981073165752 + 0.029293134706041501 + 0.029295288316575678 + 0.029297441904714356 + 0.029299595470403523 + 0.029301749013589139 + 0.029303902534217174 + 0.029306056032233518 + 0.029308209507584049 + 0.029310362960214602 + 0.029312516390071004 + 0.029314669797099013 + 0.0293168231812444 + 0.029318976542452836 + 0.029321129880670076 + 0.029323283195841696 + 0.029325436487913355 + 0.029327589756830637 + 0.029329743002539058 + 0.029331896224984194 + 0.029334049424111486 + 0.029336202599866426 + 0.029338355752194401 + 0.029340508881040846 + 0.02934266198635109 + 0.029344815068070459 + 0.029346968126144249 + 0.029349121160517716 + 0.029351274171136112 + 0.029353427157944586 + 0.029355580120888337 + 0.029357733059912509 + 0.029359885974962162 + 0.02936203886598238 + 0.029364191732918189 + 0.0293663445757146 + 0.029368497394316562 + 0.029370650188669002 + 0.029372802958716845 + 0.029374955704404959 + 0.029377108425678169 + 0.029379261122481262 + 0.029381413794759011 + 0.029383566442456172 + 0.02938571906551745 + 0.029387871663887465 + 0.029390024237510921 + 0.029392176786332377 + 0.029394329310296417 + 0.029396481809347591 + 0.029398634283430359 + 0.029400786732489217 + 0.029402939156468643 + 0.029405091555312967 + 0.029407243928966608 + 0.029409396277373885 + 0.029411548600479124 + 0.029413700898226564 + 0.02941585317056046 + 0.029418005417425019 + 0.029420157638764401 + 0.02942230983452274 + 0.029424462004644155 + 0.029426614149072713 + 0.029428766267752437 + 0.029430918360627317 + 0.029433070427641345 + 0.029435222468738458 + 0.029437374483862532 + 0.029439526472957465 + 0.029441678435967084 + 0.029443830372835173 + 0.029445982283505506 + 0.029448134167921806 + 0.029450286026027797 + 0.029452437857767112 + 0.029454589663083414 + 0.029456741441920262 + 0.029458893194221247 + 0.029461044919929895 + 0.029463196618989679 + 0.029465348291344073 + 0.029467499936936516 + 0.029469651555710383 + 0.029471803147609044 + 0.02947395471257578 + 0.029476106250553944 + 0.02947825776148676 + 0.029480409245317467 + 0.029482560701989201 + 0.029484712131445164 + 0.029486863533628435 + 0.029489014908482158 + 0.029491166255949303 + 0.029493317575972976 + 0.029495468868496078 + 0.029497620133461563 + 0.029499771370812382 + 0.029501922580491384 + 0.029504073762441428 + 0.029506224916605307 + 0.029508376042925766 + 0.029510527141345597 + 0.029512678211807492 + 0.029514829254254075 + 0.029516980268628038 + 0.029519131254871933 + 0.029521282212928358 + 0.029523433142739787 + 0.029525584044248779 + 0.029527734917397779 + 0.029529885762129178 + 0.029532036578385396 + 0.029534187366108772 + 0.029536338125241649 + 0.029538488855726255 + 0.0295406395575049 + 0.029542790230519752 + 0.029544940874713013 + 0.029547091490026826 + 0.029549242076403318 + 0.02955139263378451 + 0.029553543162112471 + 0.029555693661329218 + 0.029557844131376687 + 0.029559994572196806 + 0.029562144983731532 + 0.029564295365922623 + 0.029566445718711996 + 0.029568596042041394 + 0.029570746335852598 + 0.02957289660008728 + 0.029575046834687185 + 0.029577197039593925 + 0.029579347214749099 + 0.029581497360094321 + 0.029583647475571091 + 0.029585797561120945 + 0.029587947616685335 + 0.029590097642205684 + 0.029592247637623387 + 0.029594397602879841 + 0.029596547537916355 + 0.029598697442674213 + 0.029600847317094649 + 0.029602997161118926 + 0.029605146974688166 + 0.029607296757743561 + 0.029609446510226203 + 0.029611596232077163 + 0.029613745923237497 + 0.029615895583648178 + 0.02961804521325017 + 0.029620194811984437 + 0.029622344379791839 + 0.029624493916613232 + 0.029626643422389447 + 0.029628792897061249 + 0.029630942340569413 + 0.029633091752854633 + 0.029635241133857588 + 0.029637390483518891 + 0.029639539801779167 + 0.029641689088579014 + 0.029643838343858871 + 0.029645987567559273 + 0.029648136759620716 + 0.02965028591998357 + 0.029652435048588194 + 0.029654584145374981 + 0.029656733210284249 + 0.029658882243256222 + 0.029661031244231126 + 0.029663180213149204 + 0.029665329149950587 + 0.029667478054575421 + 0.029669626926963743 + 0.029671775767055663 + 0.029673924574791163 + 0.029676073350110202 + 0.02967822209295274 + 0.029680370803258679 + 0.029682519480967871 + 0.029684668126020133 + 0.029686816738355267 + 0.029688965317913055 + 0.029691113864633141 + 0.029693262378455269 + 0.029695410859319035 + 0.029697559307164046 + 0.029699707721929907 + 0.029701856103556089 + 0.029704004451982114 + 0.029706152767147432 + 0.02970830104899146 + 0.029710449297453562 + 0.029712597512473099 + 0.029714745693989346 + 0.02971689384194157 + 0.029719041956269003 + 0.029721190036910875 + 0.029723338083806287 + 0.029725486096894335 + 0.029727634076114159 + 0.029729782021404718 + 0.029731929932705084 + 0.029734077809954192 + 0.029736225653090958 + 0.029738373462054268 + 0.029740521236782995 + 0.029742668977215898 + 0.029744816683291767 + 0.02974696435494938 + 0.029749111992127378 + 0.029751259594764441 + 0.029753407162799162 + 0.029755554696170174 + 0.029757702194815955 + 0.029759849658675064 + 0.029761997087685961 + 0.029764144481786999 + 0.029766291840916653 + 0.029768439165013233 + 0.02977058645401507 + 0.029772733707860415 + 0.029774880926487515 + 0.029777028109834559 + 0.029779175257839689 + 0.029781322370441069 + 0.029783469447576722 + 0.029785616489184746 + 0.029787763495203106 + 0.029789910465569756 + 0.02979205740022265 + 0.029794204299099649 + 0.029796351162138617 + 0.029798497989277355 + 0.02980064478045363 + 0.029802791535605166 + 0.029804938254669674 + 0.029807084937584764 + 0.029809231584288089 + 0.029811378194717218 + 0.029813524768809635 + 0.029815671306502908 + 0.029817817807734449 + 0.029819964272441667 + 0.029822110700561951 + 0.029824257092032663 + 0.029826403446791053 + 0.029828549764774424 + 0.029830696045919966 + 0.029832842290164873 + 0.029834988497446261 + 0.029837134667701257 + 0.029839280800866924 + 0.029841426896880255 + 0.029843572955678254 + 0.029845718977197819 + 0.029847864961375935 + 0.029850010908149389 + 0.029852156817455042 + 0.029854302689229648 + 0.02985644852340999 + 0.029858594319932725 + 0.029860740078734543 + 0.029862885799752055 + 0.029865031482921849 + 0.029867177128180468 + 0.029869322735464401 + 0.029871468304710106 + 0.029873613835854042 + 0.029875759328832557 + 0.029877904783581998 + 0.029880050200038668 + 0.029882195578138839 + 0.029884340917818716 + 0.029886486219014477 + 0.029888631481662268 + 0.029890776705698192 + 0.029892921891058296 + 0.029895067037678625 + 0.029897212145495115 + 0.029899357214443728 + 0.029901502244460344 + 0.029903647235480849 + 0.029905792187441025 + 0.029907937100276664 + 0.029910081973923468 + 0.02991222680831717 + 0.029914371603393417 + 0.029916516359087809 + 0.029918661075335889 + 0.029920805752073221 + 0.029922950389235276 + 0.029925094986757519 + 0.029927239544575317 + 0.029929384062624066 + 0.029931528540839091 + 0.02993367297915565 + 0.029935817377508982 + 0.02993796173583433 + 0.029940106054066825 + 0.029942250332141519 + 0.029944394569993597 + 0.02994653876755805 + 0.029948682924769855 + 0.029950827041563946 + 0.02995297111787527 + 0.029955115153638693 + 0.029957259148789009 + 0.029959403103261041 + 0.029961547016989484 + 0.029963690889909085 + 0.029965834721954483 + 0.029967978513060302 + 0.029970122263161092 + 0.029972265972191398 + 0.029974409640085759 + 0.029976553266778561 + 0.029978696852204223 + 0.029980840396297139 + 0.029982983898991601 + 0.029985127360221908 + 0.029987270779922307 + 0.029989414158026962 + 0.029991557494470081 + 0.029993700789185718 + 0.029995844042107978 + 0.029997987253170873 + 0.030000130422308396 + 0.030002273549454495 + 0.030004416634543056 + 0.030006559677507958 + 0.030008702678282994 + 0.030010845636801935 + 0.03001298855299854 + 0.030015131426806466 + 0.030017274258159397 + 0.03001941704699089 + 0.030021559793234519 + 0.030023702496823804 + 0.030025845157692244 + 0.030027987775773226 + 0.030030130351000148 + 0.030032272883306368 + 0.0300344153726252 + 0.030036557818889888 + 0.030038700222033636 + 0.030040842581989625 + 0.030042984898690991 + 0.03004512717207081 + 0.030047269402062156 + 0.030049411588597988 + 0.030051553731611263 + 0.030053695831034913 + 0.030055837886801825 + 0.030057979898844813 + 0.030060121867096622 + 0.030062263791490032 + 0.030064405671957728 + 0.030066547508432368 + 0.030068689300846548 + 0.030070831049132839 + 0.030072972753223761 + 0.030075114413051791 + 0.030077256028549361 + 0.03007939759964888 + 0.030081539126282662 + 0.030083680608383047 + 0.030085822045882258 + 0.03008796343871252 + 0.030090104786805991 + 0.03009224609009482 + 0.030094387348511085 + 0.030096528561986819 + 0.030098669730454025 + 0.030100810853844612 + 0.030102951932090522 + 0.030105092965123613 + 0.030107233952875703 + 0.030109374895278537 + 0.030111515792263871 + 0.030113656643763385 + 0.030115797449708707 + 0.030117938210031416 + 0.030120078924663118 + 0.030122219593535258 + 0.030124360216579302 + 0.03012650079372671 + 0.030128641324908792 + 0.030130781810056916 + 0.030132922249102353 + 0.030135062641976344 + 0.030137202988610064 + 0.030139343288934677 + 0.030141483542881244 + 0.030143623750380866 + 0.030145763911364538 + 0.030147904025763232 + 0.030150044093507841 + 0.03015218411452928 + 0.030154324088758341 + 0.030156464016125838 + 0.03015860389656249 + 0.030160743729999006 + 0.030162883516366031 + 0.030165023255594156 + 0.03016716294761394 + 0.030169302592355899 + 0.030171442189750514 + 0.030173581739728179 + 0.030175721242219282 + 0.030177860697154155 + 0.030180000104463086 + 0.030182139464076285 + 0.030184278775923983 + 0.030186418039936276 + 0.03018855725604333 + 0.030190696424175129 + 0.03019283554426171 + 0.030194974616233057 + 0.030197113640019042 + 0.030199252615549583 + 0.030201391542754464 + 0.030203530421563492 + 0.030205669251906334 + 0.030207808033712754 + 0.030209946766912358 + 0.030212085451434712 + 0.030214224087209408 + 0.030216362674165904 + 0.03021850121223366 + 0.03022063970134211 + 0.030222778141420593 + 0.030224916532398394 + 0.030227054874204805 + 0.030229193166769065 + 0.030231331410020299 + 0.030233469603887682 + 0.030235607748300235 + 0.03023774584318702 + 0.030239883888477034 + 0.030242021884099201 + 0.030244159829982402 + 0.030246297726055478 + 0.030248435572247229 + 0.030250573368486418 + 0.030252711114701725 + 0.030254848810821817 + 0.030256986456775291 + 0.030259124052490732 + 0.030261261597896581 + 0.030263399092921382 + 0.030265536537493518 + 0.030267673931541349 + 0.030269811274993223 + 0.030271948567777381 + 0.030274085809822066 + 0.030276223001055445 + 0.030278360141405655 + 0.030280497230800785 + 0.030282634269168877 + 0.030284771256437897 + 0.030286908192535801 + 0.030289045077390466 + 0.030291181910929724 + 0.030293318693081391 + 0.030295455423773199 + 0.030297592102932858 + 0.030299728730488029 + 0.030301865306366284 + 0.03030400183049518 + 0.030306138302802245 + 0.030308274723214897 + 0.03031041109166057 + 0.030312547408066638 + 0.030314683672360374 + 0.030316819884469073 + 0.030318956044319945 + 0.030321092151840132 + 0.030323228206956741 + 0.030325364209596906 + 0.030327500159687562 + 0.030329636057155725 + 0.030331771901928321 + 0.030333907693932193 + 0.030336043433094168 + 0.03033817911934102 + 0.0303403147525995 + 0.030342450332796266 + 0.030344585859857925 + 0.03034672133371109 + 0.030348856754282252 + 0.030350992121497909 + 0.030353127435284486 + 0.030355262695568361 + 0.030357397902275856 + 0.030359533055333253 + 0.030361668154666795 + 0.030363803200202655 + 0.030365938191866941 + 0.030368073129585785 + 0.030370208013285178 + 0.03037234284289109 + 0.030374477618329503 + 0.030376612339526272 + 0.030378747006407227 + 0.030380881618898133 + 0.030383016176924738 + 0.03038515068041275 + 0.030387285129287737 + 0.030389419523475326 + 0.030391553862901041 + 0.030393688147490369 + 0.030395822377168737 + 0.030397956551861473 + 0.030400090671493993 + 0.03040222473599153 + 0.030404358745279303 + 0.0304064926992825 + 0.030408626597926241 + 0.03041076044113563 + 0.030412894228835686 + 0.03041502796095134 + 0.030417161637407559 + 0.030419295258129198 + 0.030421428823041091 + 0.030423562332067978 + 0.030425695785134634 + 0.030427829182165668 + 0.030429962523085729 + 0.030432095807819401 + 0.030434229036291158 + 0.030436362208425459 + 0.030438495324146775 + 0.030440628383379447 + 0.030442761386047727 + 0.030444894332075933 + 0.030447027221388236 + 0.030449160053908828 + 0.030451292829561778 + 0.030453425548271171 + 0.030455558209960983 + 0.030457690814555155 + 0.030459823361977573 + 0.030461955852152143 + 0.030464088285002602 + 0.030466220660452691 + 0.030468352978426136 + 0.030470485238846552 + 0.030472617441637494 + 0.030474749586722538 + 0.030476881674025121 + 0.030479013703468706 + 0.030481145674976659 + 0.030483277588472323 + 0.030485409443878914 + 0.03048754124111968 + 0.030489672980117795 + 0.030491804660796359 + 0.030493936283078449 + 0.030496067846887027 + 0.030498199352145105 + 0.030500330798775524 + 0.030502462186701187 + 0.03050459351584486 + 0.03050672478612931 + 0.030508855997477193 + 0.030510987149811156 + 0.030513118243053812 + 0.030515249277127628 + 0.030517380251955138 + 0.030519511167458761 + 0.030521642023560853 + 0.030523772820183714 + 0.030525903557249628 + 0.030528034234680822 + 0.0305301648523994 + 0.030532295410327519 + 0.030534425908387206 + 0.030536556346500453 + 0.030538686724589186 + 0.03054081704257532 + 0.03054294730038069 + 0.030545077497927075 + 0.030547207635136187 + 0.030549337711929681 + 0.030551467728229215 + 0.030553597683956348 + 0.030555727579032559 + 0.030557857413379338 + 0.030559987186918068 + 0.030562116899570099 + 0.030564246551256721 + 0.030566376141899169 + 0.030568505671418618 + 0.030570635139736221 + 0.030572764546773046 + 0.030574893892450109 + 0.030577023176688353 + 0.030579152399408747 + 0.030581281560532077 + 0.030583410659979195 + 0.030585539697670815 + 0.030587668673527649 + 0.030589797587470314 + 0.030591926439419409 + 0.030594055229295435 + 0.030596183957018873 + 0.03059831262251015 + 0.030600441225689633 + 0.030602569766477589 + 0.030604698244794275 + 0.030606826660559912 + 0.030608955013694643 + 0.030611083304118488 + 0.030613211531751557 + 0.030615339696513758 + 0.030617467798325033 + 0.030619595837105225 + 0.030621723812774154 + 0.030623851725251564 + 0.030625979574457132 + 0.030628107360310498 + 0.030630235082731272 + 0.030632362741638951 + 0.030634490336952976 + 0.030636617868592789 + 0.030638745336477761 + 0.030640872740527181 + 0.030643000080660242 + 0.030645127356796184 + 0.030647254568854133 + 0.030649381716753125 + 0.030651508800412196 + 0.030653635819750329 + 0.030655762774686374 + 0.030657889665139219 + 0.030660016491027627 + 0.030662143252270343 + 0.030664269948786044 + 0.030666396580493336 + 0.030668523147310792 + 0.030670649649156875 + 0.03067277608595011 + 0.030674902457608802 + 0.030677028764051314 + 0.030679155005195961 + 0.030681281180960886 + 0.030683407291264283 + 0.030685533336024251 + 0.030687659315158839 + 0.03068978522858606 + 0.03069191107622378 + 0.030694036857989916 + 0.030696162573802265 + 0.030698288223578556 + 0.03070041380723653 + 0.030702539324693811 + 0.030704664775867991 + 0.030706790160676557 + 0.030708915479036997 + 0.030711040730866709 + 0.03071316591608304 + 0.030715291034603288 + 0.030717416086344672 + 0.030719541071224384 + 0.030721665989159503 + 0.030723790840067135 + 0.030725915623864241 + 0.030728040340467739 + 0.030730164989794563 + 0.030732289571761492 + 0.030734414086285296 + 0.030736538533282686 + 0.03073866291267029 + 0.030740787224364682 + 0.030742911468282431 + 0.030745035644339978 + 0.03074715975245371 + 0.030749283792540012 + 0.030751407764515137 + 0.030753531668295329 + 0.030755655503796768 + 0.030757779270935533 + 0.030759902969627707 + 0.03076202659978924 + 0.030764150161336098 + 0.030766273654184138 + 0.030768397078249164 + 0.03077052043344693 + 0.030772643719693137 + 0.030774766936903414 + 0.030776890084993312 + 0.030779013163878363 + 0.030781136173473996 + 0.03078325911369563 + 0.03078538198445855 + 0.030787504785678058 + 0.030789627517269352 + 0.030791750179147585 + 0.030793872771227852 + 0.030795995293425128 + 0.030798117745654455 + 0.030800240127830687 + 0.030802362439868683 + 0.030804484681683227 + 0.03080660685318902 + 0.030808728954300757 + 0.030810850984933014 + 0.03081297294500035 + 0.030815094834417203 + 0.030817216653098053 + 0.030819338400957175 + 0.030821460077908924 + 0.030823581683867528 + 0.030825703218747117 + 0.03082782468246182 + 0.030829946074925712 + 0.030832067396052727 + 0.030834188645756849 + 0.030836309823951885 + 0.030838430930551643 + 0.030840551965469896 + 0.030842672928620269 + 0.030844793819916418 + 0.030846914639271892 + 0.030849035386600127 + 0.030851156061814631 + 0.030853276664828705 + 0.030855397195555676 + 0.030857517653908782 + 0.030859638039801185 + 0.030861758353146015 + 0.030863878593856333 + 0.0308659987618451 + 0.03086811885702527 + 0.030870238879309685 + 0.030872358828611127 + 0.030874478704842393 + 0.030876598507916107 + 0.030878718237744896 + 0.030880837894241318 + 0.030882957477317813 + 0.030885076986886851 + 0.030887196422860776 + 0.030889315785151871 + 0.030891435073672365 + 0.030893554288334461 + 0.030895673429050204 + 0.03089779249573165 + 0.030899911488290802 + 0.030902030406639584 + 0.030904149250689773 + 0.03090626802035323 + 0.030908386715541612 + 0.030910505336166624 + 0.030912623882139823 + 0.03091474235337275 + 0.030916860749776866 + 0.03091897907126356 + 0.030921097317744201 + 0.030923215489130011 + 0.030925333585332213 + 0.030927451606261959 + 0.030929569551830311 + 0.03093168742194826 + 0.030933805216526798 + 0.030935922935476787 + 0.030938040578709011 + 0.03094015814613427 + 0.030942275637663205 + 0.030944393053206447 + 0.030946510392674566 + 0.03094862765597807 + 0.030950744843027327 + 0.030952861953732733 + 0.030954978988004572 + 0.030957095945753077 + 0.030959212826888401 + 0.03096132963132063 + 0.030963446358959836 + 0.030965563009715934 + 0.030967679583498813 + 0.030969796080218378 + 0.030971912499784329 + 0.030974028842106371 + 0.030976145107094177 + 0.030978261294657267 + 0.030980377404705179 + 0.030982493437147329 + 0.030984609391893077 + 0.030986725268851743 + 0.030988841067932541 + 0.030990956789044653 + 0.030993072432097157 + 0.03099518799699913 + 0.030997303483659505 + 0.030999418891987193 + 0.03100153422189102 + 0.031003649473279764 + 0.031005764646062115 + 0.031007879740146679 + 0.031009994755442055 + 0.031012109691856745 + 0.031014224549299162 + 0.031016339327677642 + 0.031018454026900531 + 0.031020568646875996 + 0.031022683187512216 + 0.03102479764871733 + 0.031026912030399274 + 0.031029026332466056 + 0.031031140554825584 + 0.031033254697385607 + 0.031035368760053916 + 0.031037482742738192 + 0.031039596645346067 + 0.031041710467785016 + 0.03104382420996259 + 0.031045937871786149 + 0.031048051453163035 + 0.031050164954000554 + 0.03105227837420587 + 0.031054391713686135 + 0.031056504972348385 + 0.031058618150099648 + 0.031060731246846815 + 0.031062844262496777 + 0.031064957196956282 + 0.031067070050132099 + 0.031069182821930823 + 0.031071295512259057 + 0.031073408121023306 + 0.031075520648129986 + 0.031077633093485497 + 0.031079745456996127 + 0.031081857738568124 + 0.031083969938107629 + 0.031086082055520724 + 0.031088194090713409 + 0.031090306043591687 + 0.031092417914061411 + 0.031094529702028365 + 0.031096641407398342 + 0.031098753030076969 + 0.031100864569969848 + 0.031102976026982494 + 0.031105087401020404 + 0.031107198691988924 + 0.031109309899793405 + 0.031111421024339038 + 0.031113532065531035 + 0.031115643023274474 + 0.031117753897474419 + 0.031119864688035782 + 0.031121975394863492 + 0.031124086017862363 + 0.031126196556937089 + 0.031128307011992398 + 0.031130417382932873 + 0.031132527669663051 + 0.031134637872087395 + 0.03113674799011025 + 0.03113885802363597 + 0.031140967972568791 + 0.031143077836812878 + 0.031145187616272337 + 0.031147297310851169 + 0.031149406920453371 + 0.03115151644498277 + 0.031153625884343217 + 0.031155735238438433 + 0.031157844507172079 + 0.031159953690447745 + 0.031162062788168965 + 0.031164171800239178 + 0.031166280726561735 + 0.031168389567039961 + 0.031170498321577075 + 0.031172606990076238 + 0.031174715572440503 + 0.031176824068572882 + 0.031178932478376328 + 0.031181040801753691 + 0.031183149038607763 + 0.031185257188841253 + 0.031187365252356783 + 0.031189473229056922 + 0.03119158111884418 + 0.031193688921620995 + 0.031195796637289632 + 0.031197904265752412 + 0.031200011806911534 + 0.031202119260669112 + 0.031204226626927192 + 0.031206333905587705 + 0.03120844109655262 + 0.031210548199723704 + 0.031212655215002716 + 0.031214762142291328 + 0.031216868981491175 + 0.03121897573250372 + 0.031221082395230446 + 0.031223188969572727 + 0.031225295455431856 + 0.031227401852709034 + 0.03122950816130543 + 0.031231614381122118 + 0.031233720512060088 + 0.031235826554020248 + 0.031237932506903463 + 0.031240038370610467 + 0.031242144145042013 + 0.031244249830098665 + 0.031246355425680973 + 0.031248460931689426 + 0.031250566348024381 + 0.031252671674586167 + 0.031254776911275019 + 0.031256882057991105 + 0.031258987114634491 + 0.031261092081105182 + 0.03126319695730314 + 0.031265301743128165 + 0.031267406438480076 + 0.03126951104325857 + 0.031271615557363248 + 0.031273719980693657 + 0.031275824313149271 + 0.031277928554629492 + 0.031280032705033621 + 0.0312821367642609 + 0.031284240732210471 + 0.031286344608781436 + 0.031288448393872764 + 0.031290552087383412 + 0.031292655689212225 + 0.031294759199257956 + 0.031296862617419312 + 0.031298965943594881 + 0.031301069177683223 + 0.031303172319582781 + 0.031305275369191934 + 0.031307378326409001 + 0.031309481191132173 + 0.031311583963259615 + 0.031313686642689353 + 0.031315789229319421 + 0.031317891723047712 + 0.031319994123772024 + 0.031322096431390126 + 0.031324198645799661 + 0.031326300766898268 + 0.031328402794583411 + 0.031330504728752533 + 0.031332606569302986 + 0.031334708316132068 + 0.031336809969136917 + 0.031338911528214684 + 0.03134101299326239 + 0.031343114364176972 + 0.0313452267312649 + 0.031347458588596715 + 0.031349690507343576 + 0.031351922487500773 + 0.031354154529063621 + 0.031356386632027416 + 0.031358618796387433 + 0.031360851022139057 + 0.031363083309277506 + 0.031365315657798189 + 0.031367548067696323 + 0.03136978053896726 + 0.031372013071606274 + 0.031374245665608744 + 0.031376478320969903 + 0.031378711037685116 + 0.031380943815749629 + 0.031383176655158808 + 0.031385409555907962 + 0.031387642517992378 + 0.031389875541407382 + 0.031392108626148281 + 0.03139434177221033 + 0.031396574979588976 + 0.031398808248279411 + 0.031401041578276993 + 0.031403274969577025 + 0.031405508422174835 + 0.031407741936065707 + 0.031409975511245004 + 0.031412209147707981 + 0.031414442845450002 + 0.031416676604466315 + 0.031418910424752311 + 0.031421144306303259 + 0.031423378249114509 + 0.031425612253181349 + 0.03142784631849907 + 0.031430080445063076 + 0.031432314632868601 + 0.031434548881910968 + 0.03143678319218552 + 0.031439017563687589 + 0.031441251996412449 + 0.031443486490355464 + 0.031445721045511882 + 0.031447955661877122 + 0.031450190339446446 + 0.031452425078215135 + 0.031454659878178609 + 0.031456894739332081 + 0.031459129661670908 + 0.031461364645190455 + 0.031463599689886018 + 0.031465834795752885 + 0.031468069962786401 + 0.031470305190981894 + 0.031472540480334661 + 0.03147477583084006 + 0.0314770112424934 + 0.031479246715290003 + 0.03148148224922518 + 0.031483717844294247 + 0.031485953500492561 + 0.031488189217815446 + 0.031490424996258162 + 0.031492660835816116 + 0.031494896736484569 + 0.031497132698258899 + 0.031499368721134395 + 0.031501604805106394 + 0.031503840950170212 + 0.031506077156321179 + 0.031508313423554646 + 0.031510549751865902 + 0.031512786141250339 + 0.031515022591703162 + 0.031517259103219848 + 0.031519495675795609 + 0.031521732309425815 + 0.031523969004105812 + 0.031526205759830915 + 0.031528442576596441 + 0.031530679454397734 + 0.031532916393230088 + 0.031535153393088919 + 0.031537390453969465 + 0.031539627575867105 + 0.031541864758777162 + 0.031544102002694967 + 0.031546339307615842 + 0.031548576673535098 + 0.03155081410044816 + 0.031553051588350242 + 0.03155528913723675 + 0.031557526747102979 + 0.031559764417944322 + 0.031562002149756033 + 0.031564239942533504 + 0.031566477796272009 + 0.031568715710966984 + 0.031570953686613654 + 0.031573191723207453 + 0.031575429820743614 + 0.031577667979217523 + 0.031579906198624531 + 0.031582144478959982 + 0.031584382820219192 + 0.031586621222397492 + 0.03158885968549021 + 0.031591098209492699 + 0.031593336794400309 + 0.031595575440208364 + 0.031597814146912193 + 0.031600052914507182 + 0.031602291742988606 + 0.031604530632351815 + 0.031606769582592176 + 0.031609008593705024 + 0.031611247665685696 + 0.031613486798529516 + 0.031615725992231843 + 0.03161796524678806 + 0.031620204562193402 + 0.031622443938443288 + 0.031624683375533091 + 0.031626922873458037 + 0.031629162432213559 + 0.031631402051794988 + 0.03163364173219764 + 0.031635881473416914 + 0.031638121275448072 + 0.031640361138286541 + 0.031642601061927594 + 0.03164484104636664 + 0.031647081091598937 + 0.031649321197619956 + 0.03165156136442495 + 0.031653801592009242 + 0.031656041880368274 + 0.03165828222949732 + 0.031660522639391744 + 0.031662763110046885 + 0.031665003641458161 + 0.031667244233620793 + 0.031669484886530264 + 0.031671725600181805 + 0.031673966374570851 + 0.031676207209692671 + 0.031678448105542704 + 0.031680689062116262 + 0.031682930079408658 + 0.031685171157415273 + 0.031687412296131451 + 0.031689653495552562 + 0.031691894755673924 + 0.031694136076490957 + 0.031696377457998921 + 0.031698618900193216 + 0.031700860403069187 + 0.031703101966622203 + 0.031705343590847583 + 0.031707585275740725 + 0.031709827021296925 + 0.031712068827511569 + 0.031714310694380028 + 0.031716552621897653 + 0.031718794610059754 + 0.031721036658861737 + 0.031723278768298918 + 0.031725520938366683 + 0.031727763169060383 + 0.031730005460375375 + 0.031732247812306956 + 0.031734490224850607 + 0.031736732698001584 + 0.031738975231755291 + 0.031741217826107032 + 0.03174346048105222 + 0.031745703196586185 + 0.031747945972704306 + 0.031750188809401919 + 0.031752431706674411 + 0.031754674664517119 + 0.031756917682925434 + 0.031759160761894667 + 0.03176140390142021 + 0.031763647101497386 + 0.03176589036212165 + 0.031768133683288242 + 0.031770377064992632 + 0.031772620507230127 + 0.031774864009996073 + 0.031777107573285855 + 0.031779351197094845 + 0.031781594881418372 + 0.031783838626251865 + 0.031786082431590638 + 0.031788326297430065 + 0.031790570223765517 + 0.031792814210592338 + 0.031795058257905927 + 0.031797302365701573 + 0.031799546533974744 + 0.031801790762720765 + 0.031804035051934958 + 0.031806279401612791 + 0.031808523811749527 + 0.031810768282340599 + 0.031813012813381343 + 0.031815257404867119 + 0.031817502056793331 + 0.031819746769155298 + 0.031821991541948438 + 0.03182423637516809 + 0.031826481268809645 + 0.031828726222868461 + 0.031830971237339925 + 0.031833216312219366 + 0.031835461447502197 + 0.031837706643183757 + 0.031839951899259436 + 0.031842197215724607 + 0.031844442592574615 + 0.031846688029804886 + 0.031848933527410736 + 0.031851179085387565 + 0.031853424703730732 + 0.031855670382435641 + 0.031857916121497618 + 0.031860161920912108 + 0.031862407780674423 + 0.031864653700779948 + 0.03186689968122406 + 0.03186914572200214 + 0.031871391823109607 + 0.03187363798454175 + 0.031875884206293996 + 0.031878130488361717 + 0.031880376830740291 + 0.031882623233425111 + 0.031884869696411501 + 0.031887116219694873 + 0.031889362803270621 + 0.031891609447134123 + 0.031893856151280729 + 0.031896102915705812 + 0.031898349740404779 + 0.031900596625373014 + 0.031902843570605896 + 0.031905090576098749 + 0.031907337641847028 + 0.031909584767846069 + 0.031911831954091294 + 0.031914079200578011 + 0.031916326507301682 + 0.031918573874257644 + 0.031920821301441291 + 0.031923068788848014 + 0.03192531633647315 + 0.031927563944312183 + 0.031929811612360401 + 0.031932059340613217 + 0.031934307129066059 + 0.031936554977714193 + 0.031938802886553125 + 0.031941050855578218 + 0.031943298884784838 + 0.031945546974168335 + 0.031947795123724122 + 0.031950043333447628 + 0.031952291603334175 + 0.031954539933379218 + 0.031956788323578067 + 0.031959036773926162 + 0.031961285284418897 + 0.031963533855051622 + 0.03196578248581973 + 0.031968031176718675 + 0.031970279927743754 + 0.031972528738890393 + 0.031974777610154 + 0.031977026541529972 + 0.031979275533013662 + 0.031981524584600456 + 0.031983773696285828 + 0.031986022868065053 + 0.031988272099933629 + 0.031990521391886829 + 0.031992770743920151 + 0.031995020156028973 + 0.031997269628208647 + 0.031999519160454605 + 0.032001768752762193 + 0.032004018405126823 + 0.032006268117543937 + 0.032008517890008858 + 0.032010767722517042 + 0.032013017615063824 + 0.032015267567644681 + 0.032017517580254923 + 0.03201976765288999 + 0.032022017785545275 + 0.032024267978216177 + 0.032026518230898054 + 0.032028768543586349 + 0.0320310189162765 + 0.032033269348963798 + 0.032035519841643732 + 0.032037770394311618 + 0.032040021006962953 + 0.032042271679593053 + 0.032044522412197386 + 0.03204677320477127 + 0.032049024057310159 + 0.032051274969809432 + 0.032053525942264557 + 0.032055776974670838 + 0.032058028067023743 + 0.032060279219318644 + 0.032062530431550933 + 0.032064781703716051 + 0.032067033035809371 + 0.032069284427826285 + 0.032071535879762234 + 0.032073787391612582 + 0.032076038963372772 + 0.032078290595038188 + 0.032080542286604244 + 0.032082794038066333 + 0.032085045849419874 + 0.032087297720660268 + 0.03208954965178288 + 0.032091801642783184 + 0.032094053693656539 + 0.03209630580439838 + 0.032098557975004077 + 0.032100810205469121 + 0.032103062495788807 + 0.032105314845958639 + 0.03210756725597394 + 0.032109819725830172 + 0.032112072255522775 + 0.032114324845047067 + 0.032116577494398543 + 0.032118830203572576 + 0.03212108297256458 + 0.032123335801369952 + 0.032125588689984115 + 0.032127841638402474 + 0.032130094646620477 + 0.032132347714633483 + 0.032134600842436967 + 0.032136854030026259 + 0.032139107277396835 + 0.032141360584544081 + 0.032143613951463416 + 0.032145867378150263 + 0.032148120864600047 + 0.032150374410808119 + 0.032152628016769984 + 0.032154881682480992 + 0.03215713540793657 + 0.032159389193132167 + 0.032161643038063174 + 0.032163896942724993 + 0.032166150907113063 + 0.032168404931222812 + 0.032170659015049619 + 0.032172913158588903 + 0.032175167361836135 + 0.032177421624786699 + 0.032179675947435989 + 0.032181930329779451 + 0.032184184771812521 + 0.032186439273530605 + 0.032188693834929116 + 0.032190948456003447 + 0.032193203136749067 + 0.03219545787716141 + 0.032197712677235805 + 0.032199967536967765 + 0.032202222456352687 + 0.032204477435385993 + 0.032206732474063055 + 0.032208987572379361 + 0.032211242730330346 + 0.032213497947911354 + 0.032215753225117855 + 0.032218008561945316 + 0.032220263958389082 + 0.032222519414444623 + 0.032224774930107385 + 0.032227030505372713 + 0.032229286140236096 + 0.03223154183469297 + 0.03223379758873874 + 0.032236053402368819 + 0.032238309275578629 + 0.032240565208363603 + 0.032242821200719231 + 0.03224507725264087 + 0.032247333364123928 + 0.032249589535163922 + 0.032251845765756224 + 0.032254102055896287 + 0.032256358405579492 + 0.032258614814801294 + 0.032260871283557167 + 0.032263127811842492 + 0.032265384399652708 + 0.032267641046983271 + 0.032269897753829574 + 0.032272154520187044 + 0.032274411346051191 + 0.032276668231417331 + 0.032278925176281031 + 0.032281182180637601 + 0.032283439244482549 + 0.032285696367811291 + 0.032287953550619239 + 0.032290210792901841 + 0.032292468094654546 + 0.032294725455872746 + 0.032296982876551958 + 0.032299240356687554 + 0.032301497896274949 + 0.032303755495309644 + 0.03230601315378704 + 0.032308270871702578 + 0.032310528649051713 + 0.032312786485829866 + 0.032315044382032428 + 0.032317302337654931 + 0.032319560352692754 + 0.032321818427141352 + 0.032324076560996159 + 0.032326334754252652 + 0.032328593006906207 + 0.032330851318952282 + 0.032333109690386323 + 0.032335368121203786 + 0.032337626611400105 + 0.032339885160970708 + 0.032342143769911062 + 0.032344402438216603 + 0.032346661165882744 + 0.032348919952904967 + 0.032351178799278665 + 0.032353437704999342 + 0.032355696670062425 + 0.032357955694463314 + 0.032360214778197505 + 0.032362473921260425 + 0.032364733123647502 + 0.032366992385354239 + 0.032369251706375987 + 0.032371511086708285 + 0.032373770526346546 + 0.032376030025286148 + 0.032378289583522651 + 0.032380549201051434 + 0.032382808877867986 + 0.032385068613967727 + 0.032387328409346099 + 0.032389588263998556 + 0.03239184817792054 + 0.032394108151107527 + 0.032396368183554965 + 0.032398628275258273 + 0.032400888426212957 + 0.0324031486364144 + 0.032405408905858052 + 0.03240766923453943 + 0.032409929622453974 + 0.032412190069597058 + 0.032414450575964218 + 0.032416711141550876 + 0.032418971766352486 + 0.032421232450364497 + 0.032423493193582384 + 0.032425753996001588 + 0.032428014857617538 + 0.032430275778425721 + 0.032432536758421553 + 0.032434797797600549 + 0.032437058895958132 + 0.032439320053489748 + 0.032441581270190867 + 0.032443842546056943 + 0.032446103881083418 + 0.032448365275265775 + 0.03245062672859949 + 0.03245288824107994 + 0.032455149812702637 + 0.032457411443463084 + 0.032459673133356653 + 0.032461934882378848 + 0.032464196690525124 + 0.032466458557790963 + 0.032468720484171744 + 0.03247098246966304 + 0.032473244514260209 + 0.032475506617958803 + 0.032477768780754229 + 0.032480031002641963 + 0.032482293283617444 + 0.032484555623676171 + 0.032486818022813592 + 0.032489080481025147 + 0.032491342998306354 + 0.032493605574652605 + 0.032495868210059432 + 0.032498130904522256 + 0.032500393658036544 + 0.032502656470597809 + 0.032504919342201434 + 0.03250718227284298 + 0.032509445262517832 + 0.0325117083112215 + 0.032513971418949447 + 0.0325162345856971 + 0.032518497811459983 + 0.032520761096233537 + 0.032523024440013204 + 0.032525287842794494 + 0.032527551304572903 + 0.032529814825343839 + 0.032532078405102749 + 0.032534342043845171 + 0.032536605741566589 + 0.032538869498262395 + 0.032541133313928106 + 0.03254339718855917 + 0.032545661122151077 + 0.032547925114699339 + 0.032550189166199332 + 0.03255245327664661 + 0.0325547174460366 + 0.032556981674364778 + 0.032559245961626661 + 0.032561510307817676 + 0.032563774712933313 + 0.032566039176969042 + 0.032568303699920371 + 0.032570568281782702 + 0.032572832922551594 + 0.032575097622222472 + 0.032577362380790793 + 0.032579627198252088 + 0.032581892074601826 + 0.03258415700983544 + 0.032586422003948436 + 0.03258868705693628 + 0.032590952168794506 + 0.032593217339518525 + 0.032595482569103836 + 0.032597747857545871 + 0.032600013204840191 + 0.03260227861098227 + 0.032604544075967537 + 0.032606809599791467 + 0.032609075182449619 + 0.032611340823937421 + 0.032613606524250313 + 0.032615872283383834 + 0.032618138101333502 + 0.032620403978094695 + 0.032622669913662937 + 0.032624935908033781 + 0.032627201961202633 + 0.032629468073164983 + 0.032631734243916341 + 0.032634000473452184 + 0.032636266761767951 + 0.032638533108859197 + 0.032640799514721416 + 0.032643065979349975 + 0.032645332502740515 + 0.032647599084888394 + 0.032649865725789207 + 0.032652132425438352 + 0.03265439918383134 + 0.032656666000963723 + 0.032658932876830887 + 0.032661199811428364 + 0.032663466804751684 + 0.032665733856796282 + 0.032668000967557655 + 0.032670268137031326 + 0.032672535365212758 + 0.032674802652097414 + 0.032677069997680844 + 0.032679337401958518 + 0.032681604864925863 + 0.032683872386578501 + 0.032686139966911831 + 0.032688407605921337 + 0.032690675303602541 + 0.032692943059950949 + 0.03269521087496207 + 0.032697478748631326 + 0.032699746680954253 + 0.032702014671926363 + 0.032704282721543097 + 0.032706550829800014 + 0.032708818996692604 + 0.032711087222216335 + 0.032713355506366677 + 0.032715623849139168 + 0.03271789225052929 + 0.032720160710532561 + 0.032722429229144444 + 0.032724697806360427 + 0.03272696644217607 + 0.032729235136586848 + 0.032731503889588259 + 0.032733772701175765 + 0.032736041571344847 + 0.032738310500091114 + 0.032740579487409951 + 0.032742848533296967 + 0.032745117637747574 + 0.03274738680075729 + 0.032749656022321674 + 0.032751925302436147 + 0.032754194641096232 + 0.032756464038297448 + 0.032758733494035346 + 0.032761003008305346 + 0.032763272581102981 + 0.032765542212423768 + 0.032767811902263223 + 0.032770081650616789 + 0.032772351457480052 + 0.032774621322848432 + 0.032776891246717517 + 0.032779161229082726 + 0.032781431269939647 + 0.032783701369283755 + 0.032785971527110574 + 0.032788241743415568 + 0.032790512018194252 + 0.032792782351442222 + 0.032795052743154807 + 0.032797323193327725 + 0.032799593701956287 + 0.032801864269036148 + 0.032804134894562735 + 0.032806405578531692 + 0.032808676320938326 + 0.032810947121778268 + 0.032813217981047041 + 0.0328154888987401 + 0.032817759874853011 + 0.03282003090938123 + 0.03282230200232026 + 0.032824573153665736 + 0.032826844363412981 + 0.032829115631557715 + 0.032831386958095295 + 0.032833658343021294 + 0.032835929786331181 + 0.032838201288020577 + 0.032840472848084938 + 0.03284274446651974 + 0.032845016143320499 + 0.032847287878482803 + 0.0328495596720021 + 0.03285183152387397 + 0.032854103434093875 + 0.032856375402657331 + 0.032858647429559858 + 0.032860919514797013 + 0.032863191658364384 + 0.032865463860257314 + 0.032867736120471398 + 0.032870008439002153 + 0.03287228081584511 + 0.032874553250995829 + 0.032876825744449813 + 0.032879098296202468 + 0.032881370906249457 + 0.032883643574586306 + 0.032885916301208427 + 0.032888189086111394 + 0.032890461929290737 + 0.032892734830741961 + 0.032895007790460624 + 0.032897280808442252 + 0.032899553884682305 + 0.032901827019176343 + 0.032904100211919918 + 0.032906373462908513 + 0.032908646772137687 + 0.032910920139602971 + 0.032913193565299842 + 0.032915467049223851 + 0.032917740591370516 + 0.032920014191735354 + 0.03292228785031398 + 0.032924561567101829 + 0.032926835342094479 + 0.032929109175287415 + 0.032931383066676166 + 0.032933657016256293 + 0.032935931024023271 + 0.032938205089972743 + 0.032940479214100114 + 0.03294275339640098 + 0.032945027636870863 + 0.032947301935505324 + 0.032949576292299811 + 0.032951850707249909 + 0.032954125180351145 + 0.032956399711599041 + 0.032958674300989171 + 0.032960948948517033 + 0.032963223654178198 + 0.032965498417968128 + 0.032967773239882397 + 0.032970048119916544 + 0.032972323058066071 + 0.032974598054326544 + 0.032976873108693523 + 0.032979148221162484 + 0.032981423391729027 + 0.032983698620388614 + 0.032985973907136874 + 0.03298824925196929 + 0.032990524654881372 + 0.03299280011586872 + 0.032995075634926804 + 0.032997351212051218 + 0.032999626847237479 + 0.033001902540481139 + 0.033004178291777722 + 0.033006454101122761 + 0.033008729968511841 + 0.033011005893940473 + 0.033013281877404141 + 0.033015557918898493 + 0.033017834018418984 + 0.033020110175961202 + 0.033022386391520692 + 0.033024662665093026 + 0.033026938996673659 + 0.033029215386258193 + 0.033031491833842075 + 0.03303376833942101 + 0.033036044902990461 + 0.033038321524545944 + 0.033040598204083081 + 0.03304287494159739 + 0.033045151737084368 + 0.033047428590539572 + 0.033049705501958626 + 0.033051982471336921 + 0.033054259498670191 + 0.033056536583953848 + 0.033058813727183507 + 0.033061090928354693 + 0.033063368187462992 + 0.033065645504503867 + 0.033067922879472939 + 0.033070200312365725 + 0.033072477803177833 + 0.033074755351904704 + 0.033077032958541995 + 0.033079310623085209 + 0.033081588345529933 + 0.033083866125871601 + 0.033086143964105932 + 0.033088421860228381 + 0.033090699814234459 + 0.03309297782611987 + 0.033095255895880006 + 0.033097534023510546 + 0.033099812209006957 + 0.033102090452364862 + 0.033104368753579728 + 0.033106647112647179 + 0.033108925529562738 + 0.033111204004322041 + 0.033113482536920522 + 0.033115761127353788 + 0.033118039775617419 + 0.033120318481706962 + 0.033122597245617981 + 0.033124876067345974 + 0.03312715494688661 + 0.033129433884235317 + 0.033131712879387751 + 0.033133991932339443 + 0.033136271043085953 + 0.033138550211622854 + 0.033140829437945662 + 0.033143108722049945 + 0.033145388063931358 + 0.033147667463585322 + 0.033149946921007513 + 0.033152226436193408 + 0.033154506009138621 + 0.033156785639838697 + 0.033159065328289203 + 0.033161345074485746 + 0.033163624878423802 + 0.033165904740099006 + 0.033168184659506862 + 0.03317046463664302 + 0.033172744671502927 + 0.033175024764082288 + 0.033177304914376593 + 0.033179585122381339 + 0.033181865388092265 + 0.033184145711504749 + 0.033186426092614477 + 0.033188706531417006 + 0.033190987027907855 + 0.033193267582082679 + 0.033195548193936962 + 0.033197828863466339 + 0.033200109590666285 + 0.033202390375532451 + 0.033204671218060366 + 0.033206952118245647 + 0.033209233076083804 + 0.03321151409157045 + 0.033213795164701181 + 0.033216076295471512 + 0.033218357483877026 + 0.033220638729913349 + 0.033222920033575951 + 0.033225201394860508 + 0.033227482813762532 + 0.033229764290277596 + 0.033232045824401348 + 0.033234327416129285 + 0.033236609065457022 + 0.033238890772380104 + 0.033241172536894133 + 0.033243454358994638 + 0.033245736238677236 + 0.033248018175937581 + 0.033250300170771081 + 0.033252582223173441 + 0.03325486433314017 + 0.033257146500666912 + 0.033259428725749191 + 0.033261711008382606 + 0.033263993348562691 + 0.033266275746285136 + 0.033268558201545423 + 0.033270840714339153 + 0.033273123284661928 + 0.033275405912509298 + 0.033277688597876907 + 0.033279971340760252 + 0.033282254141154967 + 0.033284536999056612 + 0.033286819914460808 + 0.033289102887363121 + 0.033291385917759035 + 0.033293669005644316 + 0.033295952151014448 + 0.033298235353865009 + 0.03330051861419156 + 0.033302801931989756 + 0.033305085307255164 + 0.033307368739983342 + 0.033309652230169878 + 0.0333119357778104 + 0.033314219382900467 + 0.033316503045435646 + 0.033318786765411508 + 0.033321070542823739 + 0.033323354377667869 + 0.033325638269939471 + 0.033327922219634105 + 0.033330206226747421 + 0.033332490291275017 + 0.033334774413212462 + 0.033337058592555334 + 0.033339342829299158 + 0.033341627123439667 + 0.033343911474972364 + 0.033346195883892905 + 0.033348480350196767 + 0.033350764873879633 + 0.033353049454937091 + 0.033355334093364726 + 0.033357618789158119 + 0.033359903542312851 + 0.033362188352824576 + 0.033364473220688792 + 0.033366758145901156 + 0.033369043128457287 + 0.033371328168352726 + 0.033373613265583128 + 0.033375898420144059 + 0.033378183632031086 + 0.033380468901239871 + 0.033382754227765925 + 0.03338503961160489 + 0.03338732505275243 + 0.033389610551204048 + 0.033391896106955317 + 0.033394181720001963 + 0.033396467390339517 + 0.03339875311796358 + 0.033401038902869731 + 0.033403324745053621 + 0.033405610644510829 + 0.033407896601236893 + 0.033410182615227546 + 0.033412468686478243 + 0.033414754814984689 + 0.033417041000742512 + 0.033419327243747174 + 0.033421613543994463 + 0.033423899901479828 + 0.033426186316198918 + 0.033428472788147381 + 0.033430759317320771 + 0.033433045903714743 + 0.033435332547324843 + 0.033437619248146755 + 0.033439906006176023 + 0.033442192821408222 + 0.033444479693839069 + 0.033446766623464061 + 0.033449053610278862 + 0.033451340654279099 + 0.03345362775546034 + 0.033455914913818191 + 0.03345820212934833 + 0.03346048940204624 + 0.033462776731907687 + 0.033465064118928127 + 0.033467351563103286 + 0.033469639064428743 + 0.033471926622900071 + 0.033474214238512934 + 0.033476501911262904 + 0.033478789641145604 + 0.033481077428156633 + 0.033483365272291656 + 0.03348565317354623 + 0.033487941131916055 + 0.033490229147396626 + 0.033492517219983628 + 0.033494805349672668 + 0.033497093536459369 + 0.033499381780339337 + 0.033501670081308166 + 0.033503958439361513 + 0.03350624685449495 + 0.033508535326704114 + 0.033510823855984646 + 0.033513112442332127 + 0.033515401085742205 + 0.033517689786210468 + 0.033519978543732606 + 0.033522267358304096 + 0.033524556229920732 + 0.033526845158577998 + 0.033529134144271604 + 0.033531423186997075 + 0.033533712286750179 + 0.033536001443526385 + 0.033538290657321383 + 0.033540579928130802 + 0.03354286925595025 + 0.033545158640775355 + 0.033547448082601683 + 0.033549737581424974 + 0.033552027137240752 + 0.033554316750044701 + 0.033556606419832408 + 0.033558896146599571 + 0.033561185930341686 + 0.033563475771054459 + 0.033565765668733531 + 0.033568055623374553 + 0.033570345634973027 + 0.0335726357035247 + 0.033574925829025132 + 0.033577216011470006 + 0.033579506250854874 + 0.033581796547175441 + 0.033584086900427315 + 0.033586377310606118 + 0.033588667777707429 + 0.033590958301726967 + 0.033593248882660319 + 0.033595539520503113 + 0.033597830215250993 + 0.033600120966899578 + 0.033602411775444506 + 0.033604702640881376 + 0.0336069935632059 + 0.033609284542413659 + 0.033611575578500245 + 0.033613866671461379 + 0.033616157821292646 + 0.033618449027989716 + 0.033620740291548171 + 0.033623031611963686 + 0.033625322989231841 + 0.033627614423348343 + 0.033629905914308783 + 0.033632197462108805 + 0.033634489066744114 + 0.033636780728210261 + 0.033639072446502848 + 0.033641364221617641 + 0.0336436560535502 + 0.033645947942296146 + 0.033648239887851164 + 0.033650531890210889 + 0.033652823949370914 + 0.033655116065326909 + 0.033657408238074553 + 0.03365970046760948 + 0.033661992753927249 + 0.033664285097023551 + 0.033666577496894057 + 0.033668869953534394 + 0.033671162466940227 + 0.033673455037107079 + 0.033675747664030739 + 0.033678040347706814 + 0.033680333088130898 + 0.033682625885298682 + 0.03368491873920576 + 0.033687211649847892 + 0.033689504617220555 + 0.033691797641319549 + 0.033694090722140385 + 0.033696383859678838 + 0.033698677053930447 + 0.033700970304890963 + 0.033703263612555968 + 0.03370555697692109 + 0.033707850397982013 + 0.033710143875734407 + 0.033712437410173948 + 0.033714731001296142 + 0.03371702464909674 + 0.033719318353571434 + 0.03372161211471579 + 0.033723905932525493 + 0.033726199806996177 + 0.033728493738123526 + 0.033730787725903232 + 0.033733081770330804 + 0.03373537587140206 + 0.033737670029112501 + 0.033739964243457939 + 0.033742258514433854 + 0.033744552842036063 + 0.033746847226260146 + 0.03374914166710169 + 0.03375143616455651 + 0.03375373071862009 + 0.033756025329288238 + 0.033758319996556478 + 0.033760614720420551 + 0.033762909500876154 + 0.033765204337918783 + 0.033767499231544269 + 0.033769794181748233 + 0.033772089188526255 + 0.033774384251874026 + 0.033776679371787161 + 0.033778974548261481 + 0.033781269781292443 + 0.033783565070875841 + 0.033785860417007346 + 0.033788155819682551 + 0.033790451278897134 + 0.033792746794646777 + 0.033795042366927076 + 0.033797337995733763 + 0.033799633681062514 + 0.033801929422908945 + 0.033804225221268705 + 0.033806521076137533 + 0.033808816987511058 + 0.033811112955384907 + 0.03381340897975478 + 0.033815705060616374 + 0.033818001197965263 + 0.033820297391797163 + 0.033822593642107802 + 0.033824889948892767 + 0.033827186312147761 + 0.033829482731868393 + 0.033831779208050444 + 0.033834075740689487 + 0.033836372329781234 + 0.033838668975321312 + 0.033840965677305442 + 0.033843262435729236 + 0.033845559250588464 + 0.033847856121878725 + 0.033850153049595613 + 0.033852450033734993 + 0.033854747074292355 + 0.033857044171263485 + 0.033859341324643993 + 0.033861638534429549 + 0.033863935800615905 + 0.033866233123198607 + 0.03386853050217345 + 0.033870827937536055 + 0.0338731254292821 + 0.033875422977407282 + 0.033877720581907238 + 0.033880018242777671 + 0.033882315960014245 + 0.033884613733612637 + 0.033886911563568496 + 0.033889209449877583 + 0.033891507392535478 + 0.033893805391537926 + 0.033896103446880599 + 0.033898401558559145 + 0.033900699726569283 + 0.033902997950906587 + 0.033905296231566913 + 0.033907594568545772 + 0.033909892961838987 + 0.033912191411442104 + 0.033914489917350882 + 0.033916788479561005 + 0.033919087098068186 + 0.033921385772867976 + 0.033923684503956199 + 0.033925983291328447 + 0.033928282134980489 + 0.033930581034907932 + 0.033932879991106481 + 0.033935179003571805 + 0.033937478072299659 + 0.033939777197285671 + 0.033942076378525525 + 0.033944375616014918 + 0.033946674909749529 + 0.033948974259725088 + 0.033951273665937184 + 0.033953573128381612 + 0.033955872647053999 + 0.033958172221950057 + 0.033960471853065444 + 0.033962771540395946 + 0.033965071283937102 + 0.033967371083684722 + 0.033969670939634419 + 0.033971970851781941 + 0.03397427082012297 + 0.033976570844653116 + 0.033978870925368145 + 0.033981171062263775 + 0.033983471255335691 + 0.033985771504579508 + 0.03398807180999102 + 0.033990372171565822 + 0.03399267258929968 + 0.03399497306318823 + 0.03399727359322724 + 0.033999574179412316 + 0.034001874821739275 + 0.034004175520203683 + 0.034006476274801335 + 0.034008777085527832 + 0.034011077952378989 + 0.034013378875350365 + 0.034015679854437784 + 0.03401798088963686 + 0.034020281980943361 + 0.034022583128352879 + 0.034024884331861266 + 0.034027185591464094 + 0.034029486907157076 + 0.034031788278935958 + 0.034034089706796444 + 0.034036391190734198 + 0.034038692730744946 + 0.03404099432682442 + 0.034043295978968199 + 0.034045597687172087 + 0.034047899451431801 + 0.034050201271743012 + 0.034052503148101397 + 0.034054805080502723 + 0.034057107068942653 + 0.034059409113416858 + 0.034061711213921118 + 0.034064013370451049 + 0.034066315583002438 + 0.034068617851571018 + 0.034070920176152326 + 0.034073222556742257 + 0.034075524993336416 + 0.03407782748593053 + 0.034080130034520359 + 0.034082432639101552 + 0.034084735299669815 + 0.034087038016220837 + 0.034089340788750436 + 0.034091643617254155 + 0.034093946501727881 + 0.034096249442167235 + 0.034098552438567915 + 0.034100855490925647 + 0.034103158599236169 + 0.034105461763495118 + 0.034107764983698309 + 0.034110068259841413 + 0.034112371591920092 + 0.034114674979930162 + 0.034116978423867211 + 0.034119281923727068 + 0.034121585479505362 + 0.034123889091197852 + 0.034126192758800279 + 0.03412849648230832 + 0.034130800261717692 + 0.034133104097024095 + 0.034135407988223287 + 0.034137711935310969 + 0.034140015938282864 + 0.034142319997134622 + 0.034144624111862115 + 0.03414692828246086 + 0.03414923250892677 + 0.034151536791255432 + 0.034153841129442641 + 0.034156145523484033 + 0.03415844997337545 + 0.034160754479112473 + 0.034163059040690953 + 0.034165363658106587 + 0.034167668331354949 + 0.034169973060431943 + 0.034172277845333242 + 0.034174582686054528 + 0.034176887582591561 + 0.034179192534940062 + 0.034181497543095733 + 0.034183802607054281 + 0.034186107726811507 + 0.034188412902363095 + 0.034190718133704695 + 0.034193023420832178 + 0.034195328763741137 + 0.034197634162427402 + 0.034199939616886645 + 0.034202245127114637 + 0.03420455069310703 + 0.034206856314859611 + 0.034209161992368106 + 0.03421146772562824 + 0.034213773514635698 + 0.034216079359386267 + 0.034218385259875639 + 0.034220691216099622 + 0.034222997228053859 + 0.034225303295734054 + 0.034227609419136065 + 0.034229915598255535 + 0.03423222183308814 + 0.03423452812362978 + 0.034236834469876097 + 0.034239140871822768 + 0.034241447329465616 + 0.034243753842800338 + 0.034246060411822654 + 0.034248367036528338 + 0.034250673716913121 + 0.034252980452972683 + 0.03425528724470283 + 0.034257594092099226 + 0.034259900995157681 + 0.034262207953873927 + 0.034264514968243648 + 0.034266822038262611 + 0.034269129163926527 + 0.034271436345231214 + 0.034273743582172354 + 0.034276050874745632 + 0.034278358222946906 + 0.034280665626771858 + 0.034282973086216161 + 0.034285280601275649 + 0.034287588171946125 + 0.034289895798223127 + 0.034292203480102604 + 0.034294511217580162 + 0.034296819010651604 + 0.034299126859312655 + 0.034301434763559027 + 0.034303742723386536 + 0.034306050738790908 + 0.034308358809767847 + 0.034310666936313093 + 0.034312975118422469 + 0.034315283356091603 + 0.034317591649316401 + 0.034319899998092436 + 0.034322208402415594 + 0.034324516862281607 + 0.034326825377686068 + 0.034329133948624899 + 0.034331442575093789 + 0.034333751257088513 + 0.03433605999460472 + 0.034338368787638303 + 0.034340677636184889 + 0.034342986540240317 + 0.034345295499800303 + 0.034347604514860595 + 0.034349913585416954 + 0.034352222711465159 + 0.034354531893000875 + 0.03435684113001989 + 0.034359150422518019 + 0.03436145977049098 + 0.034363769173934487 + 0.034366078632844334 + 0.034368388147216253 + 0.034370697717046032 + 0.03437300734232946 + 0.03437531702306218 + 0.034377626759240006 + 0.034379936550858733 + 0.034382246397914026 + 0.034384556300401735 + 0.034386866258317557 + 0.034389176271657336 + 0.034391486340416728 + 0.034393796464591488 + 0.034396106644177478 + 0.034398416879170404 + 0.034400727169565985 + 0.03440303751536003 + 0.034405347916548298 + 0.034407658373126496 + 0.034409968885090528 + 0.034412279452435912 + 0.034414590075158694 + 0.034416900753254369 + 0.034419211486718899 + 0.034421522275547976 + 0.03442383311973736 + 0.034426144019282796 + 0.034428454974180067 + 0.034430765984424995 + 0.034433077050013278 + 0.034435388170940683 + 0.034437699347202914 + 0.034440010578795865 + 0.034442321865715296 + 0.034444633207956883 + 0.034446944605516457 + 0.034449256058389728 + 0.034451567566572493 + 0.034453879130060573 + 0.034456190748849688 + 0.034458502422935591 + 0.034460814152314126 + 0.034463125936980941 + 0.034465437776931944 + 0.034467749672162797 + 0.034470061622669267 + 0.034472373628447267 + 0.034474685689492413 + 0.034476997805800567 + 0.034479309977367478 + 0.034481622204188871 + 0.034483934486260526 + 0.034486246823578377 + 0.034488559216137984 + 0.034490871663935205 + 0.034493184166965826 + 0.034495496725225637 + 0.034497809338710377 + 0.034500122007415909 + 0.034502434731337857 + 0.034504747510472153 + 0.034507060344814419 + 0.034509373234360534 + 0.034511686179106278 + 0.034513999179047405 + 0.034516312234179759 + 0.03451862534449894 + 0.034520938510000938 + 0.034523251730681402 + 0.034525565006536141 + 0.034527878337560942 + 0.03453019172375163 + 0.034532505165103929 + 0.034534818661613648 + 0.03453713221327652 + 0.034539445820088388 + 0.034541759482045034 + 0.034544073199142204 + 0.034546386971375721 + 0.034548700798741262 + 0.034551014681234768 + 0.034553328618851929 + 0.034555642611588562 + 0.034557956659440482 + 0.034560270762403388 + 0.034562584920473115 + 0.034564899133645452 + 0.034567213401916194 + 0.034569527725281123 + 0.034571842103736004 + 0.034574156537276718 + 0.034576471025898899 + 0.034578785569598439 + 0.034581100168371091 + 0.034583414822212687 + 0.03458572953111895 + 0.034588044295085739 + 0.034590359114108842 + 0.034592673988183963 + 0.034594988917306994 + 0.034597303901473656 + 0.034599618940679817 + 0.034601934034921213 + 0.03460424918419365 + 0.034606564388492876 + 0.034608879647814783 + 0.03461119496215511 + 0.034613510331509653 + 0.034615825755874213 + 0.034618141235244579 + 0.034620456769616503 + 0.034622772358985872 + 0.034625088003348452 + 0.034627403702700024 + 0.034629719457036322 + 0.034632035266353327 + 0.034634351130646654 + 0.034636667049912133 + 0.034638983024145628 + 0.034641299053342928 + 0.03464361513749982 + 0.034645931276612037 + 0.034648247470675513 + 0.034650563719685896 + 0.034652880023639109 + 0.034655196382530964 + 0.034657512796357169 + 0.034659829265113566 + 0.034662145788795916 + 0.034664462367400103 + 0.034666779000921917 + 0.034669095689357082 + 0.034671412432701519 + 0.034673729230950925 + 0.034676046084101179 + 0.03467836299214809 + 0.034680679955087376 + 0.03468299697291493 + 0.034685314045626532 + 0.034687631173217992 + 0.034689948355685084 + 0.034692265593023693 + 0.034694582885229523 + 0.034696900232298454 + 0.034699217634226273 + 0.034701535091008824 + 0.034703852602641833 + 0.034706170169121191 + 0.034708487790442749 + 0.03471080546660215 + 0.034713123197595411 + 0.034715440983418111 + 0.034717758824066261 + 0.034720076719535649 + 0.034722394669821979 + 0.034724712674921117 + 0.03472703073482894 + 0.034729348849541181 + 0.034731667019053669 + 0.034733985243362221 + 0.034736303522462708 + 0.034738621856350863 + 0.034740940245022514 + 0.034743258688473527 + 0.034745577186699725 + 0.034747895739696874 + 0.034750214347460742 + 0.034752533009987263 + 0.034754851727272218 + 0.034757170499311409 + 0.034759489326100713 + 0.034761808207635816 + 0.034764127143912665 + 0.034766446134926993 + 0.034768765180674704 + 0.034771084281151568 + 0.034773403436353406 + 0.034775722646276021 + 0.034778041910915304 + 0.034780361230267016 + 0.034782680604327001 + 0.034785000033091075 + 0.034787319516555081 + 0.034789639054714813 + 0.034791958647566124 + 0.034794278295104827 + 0.034796597997326706 + 0.034798917754227637 + 0.034801237565803458 + 0.034803557432049978 + 0.034805877352963005 + 0.034808197328538383 + 0.034810517358771907 + 0.034812837443659456 + 0.034815157583196865 + 0.034817477777379903 + 0.034819798026204392 + 0.034822118329666238 + 0.034824438687761208 + 0.034826759100485195 + 0.034829079567833959 + 0.034831400089803316 + 0.03483372066638922 + 0.034836041297587397 + 0.034838361983393719 + 0.034840682723803959 + 0.034843003518814045 + 0.034845324368419729 + 0.034847645272616912 + 0.034849966231401353 + 0.034852287244768958 + 0.034854608312715495 + 0.034856929435236855 + 0.034859250612328897 + 0.034861571843987305 + 0.034863893130208101 + 0.034866214470987027 + 0.034868535866319959 + 0.034870857316202666 + 0.034873178820631068 + 0.034875500379600938 + 0.034877821993108155 + 0.034880143661148562 + 0.034882465383717982 + 0.034884787160812225 + 0.034887108992427189 + 0.034889430878558669 + 0.03489175281920253 + 0.034894074814354616 + 0.034896396864010734 + 0.034898718968166792 + 0.034901041126818536 + 0.034903363339961906 + 0.034905685607592711 + 0.034908007929706775 + 0.034910330306299933 + 0.034912652737368051 + 0.034914975222907013 + 0.034917297762912629 + 0.034919620357380679 + 0.034921943006307118 + 0.034924265709687777 + 0.034926588467518394 + 0.034928911279794916 + 0.034931234146513182 + 0.034933557067669006 + 0.034935880043258302 + 0.034938203073276816 + 0.034940526157720489 + 0.034942849296585088 + 0.034945172489866581 + 0.03494749573756066 + 0.034949819039663307 + 0.034952142396170338 + 0.034954465807077603 + 0.034956789272380891 + 0.034959112792076183 + 0.034961436366159164 + 0.034963759994625823 + 0.034966083677471976 + 0.034968407414693509 + 0.034970731206286167 + 0.03497305505224594 + 0.034975378952568532 + 0.034977702907249941 + 0.034980026916285954 + 0.034982350979672422 + 0.034984675097405299 + 0.034986999269480262 + 0.034989323495893301 + 0.034991647776640239 + 0.034993972111716912 + 0.034996296501119205 + 0.034998620944843004 + 0.035000945442884082 + 0.035003269995238437 + 0.035005594601901793 + 0.035007919262870058 + 0.035010243978139136 + 0.035012568747704788 + 0.03501489357156299 + 0.035017218449709481 + 0.035019543382140271 + 0.035021868368851086 + 0.035024193409837867 + 0.03502651850509645 + 0.035028843654622721 + 0.035031168858412502 + 0.035033494116461686 + 0.035035819428766171 + 0.035038144795321767 + 0.035040470216124338 + 0.035042795691169852 + 0.035045121220454015 + 0.035047446803972822 + 0.035049772441722041 + 0.03505209813369764 + 0.035054423879895401 + 0.035056749680311264 + 0.035059075534941038 + 0.035061401443780636 + 0.035063727406825888 + 0.035066053424072721 + 0.03506837949551693 + 0.035070705621154441 + 0.035073031800981126 + 0.035075358034992801 + 0.0350776843231854 + 0.035080010665554787 + 0.035082337062096826 + 0.035084663512807361 + 0.035086990017682257 + 0.035089316576717496 + 0.03509164318990881 + 0.035093969857252202 + 0.035096296578743448 + 0.035098623354378453 + 0.035100950184153164 + 0.035103277068063272 + 0.035105604006104865 + 0.035107930998273716 + 0.035110258044565731 + 0.035112585144976727 + 0.035114912299502664 + 0.0351172395081394 + 0.035119566770882814 + 0.0351218940877287 + 0.035124221458673013 + 0.035126548883711653 + 0.03512887636284049 + 0.035131203896055396 + 0.035133531483352201 + 0.035135859124726894 + 0.035138186820175235 + 0.035140514569693249 + 0.035142842373276667 + 0.035145170230921424 + 0.035147498142623509 + 0.035149826108378669 + 0.035152154128182816 + 0.03515448220203192 + 0.035156810329921746 + 0.035159138511848265 + 0.035161466747807332 + 0.035163795037794821 + 0.035166123381806656 + 0.035168451779838676 + 0.035170780231886807 + 0.035173108737946941 + 0.035175437298014922 + 0.035177765912086739 + 0.035180094580158125 + 0.035182423302225062 + 0.035184752078283477 + 0.035187080908329241 + 0.035189409792358156 + 0.035191738730366205 + 0.035194067722349238 + 0.035196396768303169 + 0.035198725868223861 + 0.035201055022107242 + 0.035203384229949196 + 0.035205713491745561 + 0.035208042807492353 + 0.035210372177185374 + 0.035212701600820517 + 0.035215031078393702 + 0.035217360609900841 + 0.035219690195337786 + 0.035222019834700455 + 0.03522434952798472 + 0.035226679275186523 + 0.035229009076301762 + 0.035231338931326329 + 0.035233668840256055 + 0.035235998803086935 + 0.035238328819814833 + 0.035240658890435608 + 0.03524298901494527 + 0.035245319193339522 + 0.035247649425614452 + 0.035249979711765883 + 0.035252310051789734 + 0.035254640445681849 + 0.035256970893438218 + 0.035259301395054732 + 0.035261631950527166 + 0.035263962559851647 + 0.035266293223023867 + 0.035268623940039892 + 0.035270954710895523 + 0.035273285535586688 + 0.035275616414109284 + 0.035277947346459233 + 0.035280278332632475 + 0.03528260937262484 + 0.035284940466432317 + 0.035287271614050701 + 0.03528960281547603 + 0.035291934070704127 + 0.035294265379730932 + 0.035296596742552366 + 0.035298928159164335 + 0.035301259629562688 + 0.035303591153743437 + 0.035305922731702355 + 0.035308254363435494 + 0.035310586048938719 + 0.03531291778820788 + 0.035315249581238911 + 0.035317581428027774 + 0.035319913328570401 + 0.035322245282862673 + 0.035324577290900425 + 0.035326909352679667 + 0.035329241468196299 + 0.035331573637446212 + 0.035333905860425313 + 0.035336238137129543 + 0.035338570467554814 + 0.035340902851697067 + 0.035343235289552119 + 0.035345567781116013 + 0.035347900326384581 + 0.035350232925353761 + 0.035352565578019489 + 0.035354898284377684 + 0.035357231044424266 + 0.035359563858155169 + 0.035361896725566229 + 0.035364229646653443 + 0.035366562621412717 + 0.035368895649839964 + 0.035371228731931138 + 0.035373561867682118 + 0.035375895057088859 + 0.035378228300147238 + 0.035380561596853231 + 0.035382894947202641 + 0.035385228351191629 + 0.035387561808815887 + 0.03538989532007146 + 0.035392228884954267 + 0.035394562503460181 + 0.035396896175585134 + 0.035399229901325074 + 0.03540156368067595 + 0.035403897513633674 + 0.035406231400194173 + 0.035408565340353304 + 0.03541089933410714 + 0.035413233381451491 + 0.035415567482382275 + 0.035417901636895524 + 0.035420235844987109 + 0.03542257010665293 + 0.035424904421888982 + 0.035427238790691172 + 0.03542957321305544 + 0.035431907688977693 + 0.035434242218453864 + 0.035436576801479887 + 0.035438911438051675 + 0.03544124612816521 + 0.035443580871816399 + 0.035445915669001203 + 0.035448250519715493 + 0.035450585423955294 + 0.035452920381716449 + 0.035455255392994933 + 0.035457590457786743 + 0.035459925576087695 + 0.035462260747893805 + 0.03546459597320098 + 0.035466931252005215 + 0.035469266584302384 + 0.035471601970088459 + 0.0354739374093593 + 0.035476272902110993 + 0.03547860844833934 + 0.03548094404804035 + 0.035483279701209999 + 0.035485615407844139 + 0.035487951167938764 + 0.035490286981489753 + 0.035492622848493117 + 0.035494958768944825 + 0.035497294742840725 + 0.035499630770176864 + 0.035501966850949078 + 0.035504302985153377 + 0.035506639172785716 + 0.03550897541384198 + 0.035511311708318172 + 0.03551364805621017 + 0.035515984457514034 + 0.035518320912225572 + 0.035520657420340877 + 0.035522993981855745 + 0.035525330596766255 + 0.035527667265068279 + 0.035530003986757798 + 0.035532340761830733 + 0.03553467759028299 + 0.035537014472110627 + 0.035539351407309558 + 0.03554168839587573 + 0.035544025437804994 + 0.035546362533093512 + 0.035548699681736996 + 0.035551036883731596 + 0.035553374139073148 + 0.035555711447757647 + 0.035558048809781008 + 0.035560386225139275 + 0.035562723693828263 + 0.035565061215844067 + 0.035567398791182529 + 0.035569736419839716 + 0.03557207410181145 + 0.03557441183709377 + 0.035576749625682719 + 0.03557908746757403 + 0.035581425362763826 + 0.03558376331124808 + 0.035586101313022582 + 0.035588439368083508 + 0.035590777476426617 + 0.035593115638048019 + 0.035595453852943645 + 0.035597792121109341 + 0.035600130442541171 + 0.035602468817235139 + 0.035604807245187095 + 0.035607145726393112 + 0.035609484260848964 + 0.035611822848550856 + 0.035614161489494582 + 0.035616500183676153 + 0.035618838931091537 + 0.035621177731736675 + 0.035623516585607577 + 0.03562585549270017 + 0.035628194453010471 + 0.035630533466534331 + 0.035632872533267884 + 0.035635211653206954 + 0.035637550826347508 + 0.035639890052685627 + 0.035642229332217244 + 0.035644568664938203 + 0.035646908050844639 + 0.035649247489932409 + 0.035651586982197482 + 0.03565392652763593 + 0.035656266126243633 + 0.035658605778016592 + 0.035660945482950783 + 0.035663285241042147 + 0.035665625052286654 + 0.035667964916680353 + 0.035670304834219083 + 0.035672644804898908 + 0.03567498482871586 + 0.035677324905665754 + 0.035679665035744719 + 0.035682005218948612 + 0.035684345455273457 + 0.03568668574471516 + 0.035689026087269857 + 0.035691366482933425 + 0.035693706931701812 + 0.035696047433571007 + 0.035698387988537084 + 0.035700728596595857 + 0.035703069257743414 + 0.03570540997197573 + 0.035707750739288738 + 0.035710091559678407 + 0.03571243243314081 + 0.035714773359671867 + 0.035717114339267553 + 0.035719455371923822 + 0.03572179645763672 + 0.03572413759640216 + 0.035726478788216193 + 0.035728820033074739 + 0.035731161330973815 + 0.035733502681909383 + 0.035735844085877468 + 0.035738185542874078 + 0.035740527052895044 + 0.035742868615936479 + 0.035745210231994361 + 0.035747551901064663 + 0.03574989362314332 + 0.03575223539822641 + 0.035754577226309828 + 0.035756919107389665 + 0.035759261041461841 + 0.035761603028522264 + 0.035763945068567074 + 0.035766287161592192 + 0.035768629307593593 + 0.035770971506567301 + 0.035773313758509277 + 0.035775656063415547 + 0.035777998421282042 + 0.035780340832104809 + 0.035782683295879775 + 0.035785025812602997 + 0.035787368382270486 + 0.035789711004878134 + 0.035792053680422035 + 0.035794396408898081 + 0.0357967391903024 + 0.035799082024630904 + 0.035801424911879529 + 0.035803767852044352 + 0.035806110845121385 + 0.03580845389110654 + 0.035810796989995966 + 0.035813140141785507 + 0.035815483346471166 + 0.035817826604048961 + 0.035820169914515018 + 0.035822513277865196 + 0.035824856694095498 + 0.035827200163201969 + 0.035829543685180563 + 0.035831887260027367 + 0.035834230887738266 + 0.035836574568309354 + 0.035838918301736619 + 0.035841262088015996 + 0.035843605927143557 + 0.035845949819115278 + 0.035848293763927105 + 0.035850637761575169 + 0.035852981812055373 + 0.035855325915363792 + 0.035857670071496303 + 0.035860014280449021 + 0.03586235854221799 + 0.035864702856799074 + 0.035867047224188403 + 0.035869391644381944 + 0.035871736117375638 + 0.035874080643165593 + 0.035876425221747756 + 0.03587876985311815 + 0.035881114537272815 + 0.035883459274207739 + 0.035885804063918843 + 0.035888148906402219 + 0.035890493801653982 + 0.035892838749669954 + 0.035895183750446223 + 0.035897528803978854 + 0.035899873910263745 + 0.035902219069296963 + 0.035904564281074622 + 0.035906909545592544 + 0.035909254862846851 + 0.03591160023283356 + 0.035913945655548701 + 0.035916291130988237 + 0.035918636659148177 + 0.035920982240024546 + 0.035923327873613409 + 0.035925673559910692 + 0.035928019298912511 + 0.035930365090614869 + 0.03593271093501367 + 0.035935056832105079 + 0.035937402781885029 + 0.035939748784349509 + 0.035942094839494669 + 0.035944440947316358 + 0.035946787107810768 + 0.035949133320973749 + 0.035951479586801512 + 0.035953825905289873 + 0.035956172276435015 + 0.035958518700232825 + 0.035960865176679443 + 0.035963211705770839 + 0.035965558287503009 + 0.035967904921872053 + 0.035970251608873939 + 0.035972598348504664 + 0.035974945140760321 + 0.035977291985636872 + 0.035979638883130445 + 0.035981985833236932 + 0.035984332835952454 + 0.035986679891272966 + 0.035989026999194547 + 0.035991374159713214 + 0.03599372137282502 + 0.035996068638525947 + 0.035998415956812031 + 0.036000763327679271 + 0.036003110751123828 + 0.036005458227141532 + 0.036007805755728574 + 0.036010153336880943 + 0.036012500970594642 + 0.036014848656865675 + 0.036017196395690149 + 0.036019544187064129 + 0.036021892030983445 + 0.036024239927444357 + 0.036026587876442813 + 0.036028935877974802 + 0.036031283932036431 + 0.036033632038623642 + 0.036035980197732562 + 0.036038328409359235 + 0.036040676673499562 + 0.036043024990149712 + 0.03604537335930573 + 0.036047721780963514 + 0.036050070255119263 + 0.036052418781768909 + 0.036054767360908513 + 0.036057115992534201 + 0.036059464676641818 + 0.036061813413227568 + 0.036064162202287496 + 0.036066511043817515 + 0.036068859937813759 + 0.036071208884272232 + 0.03607355788318907 + 0.036075906934560122 + 0.036078256038381641 + 0.036080605194649548 + 0.036082954403359867 + 0.036085303664508711 + 0.036087652978092119 + 0.036090002344106101 + 0.03609235176254668 + 0.03609470123341 + 0.036097050756691958 + 0.036099400332388752 + 0.036101749960496331 + 0.036104099641010801 + 0.036106449373928172 + 0.036108799159244497 + 0.036111148996955798 + 0.036113498887058129 + 0.036115848829547589 + 0.036118198824420224 + 0.036120548871672008 + 0.03612289897129909 + 0.036125249123297426 + 0.036127599327663143 + 0.036129949584392224 + 0.036132299893480775 + 0.036134650254924842 + 0.03613700066872047 + 0.036139351134863697 + 0.036141701653350532 + 0.036144052224177124 + 0.036146402847339484 + 0.036148753522833671 + 0.036151104250655736 + 0.036153455030801723 + 0.036155805863267713 + 0.036158156748049737 + 0.036160507685143874 + 0.036162858674546092 + 0.036165209716252623 + 0.036167560810259403 + 0.03616991195656246 + 0.036172263155157959 + 0.036174614406041881 + 0.036176965709210293 + 0.036179317064659273 + 0.036181668472384881 + 0.036184019932383175 + 0.036186371444650214 + 0.03618872300918205 + 0.036191074625974769 + 0.036193426295024443 + 0.036195778016327049 + 0.036198129789878741 + 0.036200481615675559 + 0.036202833493713553 + 0.036205185423988748 + 0.036207537406497313 + 0.036209889441235245 + 0.036212241528198616 + 0.036214593667383436 + 0.03621694585878589 + 0.036219298102402028 + 0.036221650398227757 + 0.03622400274625933 + 0.03622635514649275 + 0.036228707598924048 + 0.03623106010354929 + 0.036233412660364665 + 0.036235765269366046 + 0.036238117930549686 + 0.036240470643911588 + 0.036242823409447802 + 0.036245176227154369 + 0.036247529097027442 + 0.036249882019063082 + 0.036252234993257249 + 0.036254588019606154 + 0.036256941098105837 + 0.036259294228752251 + 0.03626164741154167 + 0.036264000646470063 + 0.036266353933533432 + 0.036268707272728004 + 0.03627106066404974 + 0.036273414107494746 + 0.036275767603059117 + 0.036278121150738953 + 0.036280474750530284 + 0.036282828402429176 + 0.036285182106431731 + 0.036287535862534005 + 0.036289889670732163 + 0.036292243531022159 + 0.036294597443400203 + 0.036296951407862231 + 0.036299305424404432 + 0.036301659493022859 + 0.036304013613713604 + 0.036306367786472699 + 0.036308722011296264 + 0.036311076288180352 + 0.036313430617121084 + 0.036315784998114546 + 0.036318139431156825 + 0.03632049391624393 + 0.036322848453371998 + 0.036325203042537155 + 0.036327557683735454 + 0.036329912376962918 + 0.036332267122215725 + 0.036334621919489898 + 0.036336976768781573 + 0.036339331670086829 + 0.036341686623401655 + 0.03634404162872229 + 0.036346396686044773 + 0.03634875179536514 + 0.036351106956679501 + 0.036353462169984002 + 0.036355817435274614 + 0.036358172752547609 + 0.0363605281217989 + 0.036362883543024679 + 0.036365239016221004 + 0.036367594541383927 + 0.036369950118509645 + 0.036372305747594182 + 0.03637466142863361 + 0.036377017161624059 + 0.036379372946561628 + 0.036381728783442417 + 0.036384084672262521 + 0.036386440613017955 + 0.036388796605704953 + 0.036391152650319461 + 0.03639350874685772 + 0.03639586489531571 + 0.03639822109568959 + 0.036400577347975437 + 0.036402933652169393 + 0.036405290008267512 + 0.036407646416265899 + 0.036410002876160634 + 0.036412359387947853 + 0.036414715951623655 + 0.036417072567184128 + 0.036419429234625308 + 0.036421785953943443 + 0.036424142725134522 + 0.036426499548194706 + 0.036428856423120042 + 0.036431213349906663 + 0.036433570328550685 + 0.036435927359048159 + 0.036438284441395276 + 0.036440641575588045 + 0.036442998761622679 + 0.036445355999495138 + 0.036447713289201739 + 0.036450070630738372 + 0.036452428024101272 + 0.036454785469286433 + 0.036457142966290143 + 0.036459500515108337 + 0.036461858115737211 + 0.036464215768172874 + 0.036466573472411425 + 0.036468931228448902 + 0.03647128903628153 + 0.03647364689590539 + 0.036476004807316491 + 0.036478362770511058 + 0.03648072078548522 + 0.036483078852234993 + 0.036485436970756513 + 0.036487795141045928 + 0.036490153363099347 + 0.036492511636912861 + 0.036494869962482614 + 0.036497228339804712 + 0.036499586768875228 + 0.036501945249690346 + 0.036504303782246131 + 0.036506662366538697 + 0.036509021002564201 + 0.036511379690318757 + 0.036513738429798409 + 0.036516097220999313 + 0.036518456063917702 + 0.03652081495854953 + 0.036523173904890981 + 0.036525532902938189 + 0.036527891952687255 + 0.036530251054134329 + 0.036532610207275454 + 0.036534969412106842 + 0.036537328668624552 + 0.036539687976824727 + 0.036542047336703506 + 0.036544406748257034 + 0.036546766211481403 + 0.036549125726372637 + 0.036551485292927031 + 0.036553844911140623 + 0.036556204581009541 + 0.036558564302529878 + 0.036560924075697859 + 0.036563283900509572 + 0.036565643776961081 + 0.036568003705048528 + 0.036570363684768077 + 0.036572723716115911 + 0.036575083799088026 + 0.036577443933680606 + 0.036579804119889835 + 0.036582164357711729 + 0.036584524647142576 + 0.036586884988178366 + 0.036589245380815295 + 0.036591605825049438 + 0.036593966320877004 + 0.036596326868294116 + 0.036598687467296782 + 0.036601048117881306 + 0.036603408820043738 + 0.036605769573780235 + 0.036608130379086889 + 0.036610491235959844 + 0.036612852144395303 + 0.03661521310438931 + 0.036617574115938023 + 0.03661993517903761 + 0.036622296293684173 + 0.036624657459873929 + 0.036627018677602902 + 0.036629379946867317 + 0.036631741267663213 + 0.03663410263998685 + 0.036636464063834293 + 0.036638825539201697 + 0.036641187066085157 + 0.036643548644480925 + 0.036645910274385025 + 0.03664827195579367 + 0.036650633688702965 + 0.036652995473109032 + 0.036655357309008076 + 0.036657719196396245 + 0.036660081135269605 + 0.036662443125624368 + 0.036664805167456606 + 0.036667167260762489 + 0.036669529405538227 + 0.036671891601779957 + 0.036674253849483647 + 0.036676616148645709 + 0.036678978499262112 + 0.036681340901329039 + 0.036683703354842612 + 0.036686065859799083 + 0.036688428416194484 + 0.036690791024025095 + 0.036693153683286898 + 0.036695516393976155 + 0.036697879156088985 + 0.036700241969621537 + 0.036702604834569927 + 0.036704967750930365 + 0.036707330718698972 + 0.036709693737871911 + 0.036712056808445297 + 0.036714419930415382 + 0.036716783103778176 + 0.036719146328529947 + 0.036721509604666795 + 0.03672387293218491 + 0.036726236311080393 + 0.036728599741349441 + 0.036730963222988189 + 0.036733326755992862 + 0.036735690340359471 + 0.036738053976084289 + 0.036740417663163411 + 0.036742781401593101 + 0.036745145191369379 + 0.036747509032488447 + 0.036749872924946511 + 0.036752236868739664 + 0.036754600863864152 + 0.036756964910316048 + 0.036759329008091556 + 0.036761693157186824 + 0.03676405735759803 + 0.036766421609321261 + 0.036768785912352817 + 0.036771150266688715 + 0.036773514672325265 + 0.036775879129258532 + 0.036778243637484664 + 0.036780608196999881 + 0.036782972807800268 + 0.036785337469882121 + 0.03678770218324149 + 0.036790066947874546 + 0.036792431763777542 + 0.036794796630946557 + 0.036797161549377851 + 0.036799526519067489 + 0.036801891540011698 + 0.036804256612206619 + 0.036806621735648491 + 0.036808986910333359 + 0.036811352136257455 + 0.036813717413416935 + 0.036816082741808025 + 0.036818448121426865 + 0.036820813552269613 + 0.036823179034332416 + 0.036825544567611487 + 0.036827910152102961 + 0.036830275787803117 + 0.036832641474707974 + 0.036835007212813797 + 0.036837373002116695 + 0.036839738842612907 + 0.036842104734298588 + 0.036844470677169922 + 0.036846836671223071 + 0.036849202716454248 + 0.036851568812859552 + 0.036853934960435215 + 0.036856301159177388 + 0.0368586674090823 + 0.036861033710146034 + 0.036863400062364861 + 0.036865766465734945 + 0.036868132920252344 + 0.036870499425913431 + 0.03687286598271429 + 0.036875232590651105 + 0.036877599249719992 + 0.036879965959917271 + 0.036882332721239058 + 0.036884699533681481 + 0.036887066397240764 + 0.036889433311913127 + 0.03689180027769464 + 0.036894167294581677 + 0.036896534362570219 + 0.036898901481656608 + 0.036901268651836898 + 0.036903635873107389 + 0.036906003145464203 + 0.036908370468903551 + 0.036910737843421637 + 0.036913105269014576 + 0.036915472745678586 + 0.036917840273409892 + 0.036920207852204616 + 0.036922575482059079 + 0.036924943162969313 + 0.036927310894931634 + 0.036929678677942092 + 0.036932046511997024 + 0.036934414397092517 + 0.036936782333224775 + 0.036939150320390066 + 0.03694151835858453 + 0.036943886447804324 + 0.036946254588045735 + 0.036948622779304885 + 0.036950991021577971 + 0.036953359314861149 + 0.036955727659150714 + 0.036958096054442759 + 0.036960464500733564 + 0.036962832998019272 + 0.036965201546296095 + 0.036967570145560284 + 0.0369699387958079 + 0.03697230749703527 + 0.036974676249238524 + 0.0369770450524139 + 0.036979413906557609 + 0.036981782811665746 + 0.036984151767734584 + 0.036986520774760397 + 0.036988889832739243 + 0.036991258941667431 + 0.036993628101541089 + 0.03699599731235647 + 0.036998366574109737 + 0.037000735886797143 + 0.037003105250414781 + 0.037005474664958987 + 0.037007844130425953 + 0.037010213646811778 + 0.037012583214112736 + 0.037014952832325032 + 0.037017322501444856 + 0.037019692221468392 + 0.037022061992391955 + 0.037024431814211604 + 0.037026801686923606 + 0.037029171610524214 + 0.037031541585009577 + 0.037033911610375926 + 0.037036281686619502 + 0.037038651813736417 + 0.037041021991722947 + 0.037043392220575372 + 0.037045762500289764 + 0.037048132830862383 + 0.037050503212289497 + 0.037052873644567191 + 0.03705524412769183 + 0.037057614661659528 + 0.037059985246466538 + 0.037062355882109072 + 0.037064726568583312 + 0.037067097305885546 + 0.037069468094011848 + 0.03707183893295854 + 0.037074209822721874 + 0.037076580763297999 + 0.037078951754683113 + 0.037081322796873435 + 0.037083693889865182 + 0.037086065033654698 + 0.037088436228238 + 0.037090807473611445 + 0.037093178769771168 + 0.037095550116713498 + 0.03709792151443457 + 0.037100292962930582 + 0.037102664462197878 + 0.037105036012232473 + 0.037107407613030767 + 0.037109779264588957 + 0.0371121509669032 + 0.037114522719969761 + 0.037116894523784784 + 0.037119266378344652 + 0.037121638283645404 + 0.037124010239683362 + 0.037126382246454828 + 0.037128754303955853 + 0.037131126412182851 + 0.037133498571131851 + 0.037135870780799191 + 0.037138243041181115 + 0.037140615352273788 + 0.037142987714073511 + 0.037145360126576425 + 0.037147732589778791 + 0.037150105103676827 + 0.037152477668266855 + 0.037154850283544975 + 0.037157222949507469 + 0.037159595666150562 + 0.037161968433470506 + 0.037164341251463541 + 0.037166714120125892 + 0.037169087039453694 + 0.037171460009443352 + 0.037173833030090954 + 0.037176206101392759 + 0.037178579223345096 + 0.037180952395944059 + 0.037183325619186039 + 0.037185698893067075 + 0.037188072217583558 + 0.037190445592731672 + 0.037192819018507677 + 0.037195192494907783 + 0.037197566021928238 + 0.037199939599565246 + 0.037202313227815101 + 0.037204686906674021 + 0.037207060636138253 + 0.03720943441620396 + 0.037211808246867505 + 0.037214182128125009 + 0.037216556059972788 + 0.037218930042407075 + 0.037221304075424039 + 0.037223678159020057 + 0.037226052293191238 + 0.037228426477933931 + 0.037230800713244278 + 0.037233174999118601 + 0.037235549335553092 + 0.037237923722544024 + 0.037240298160087663 + 0.037242672648180208 + 0.037245047186817863 + 0.037247421775997026 + 0.037249796415713785 + 0.037252171105964446 + 0.037254545846745292 + 0.037256920638052526 + 0.037259295479882465 + 0.037261670372231166 + 0.037264045315095112 + 0.037266420308470438 + 0.037268795352353362 + 0.037271170446740193 + 0.037273545591627183 + 0.037275920787010551 + 0.037278296032886606 + 0.037280671329251495 + 0.037283046676101592 + 0.037285422073432987 + 0.037287797521242096 + 0.037290173019525114 + 0.037292548568278308 + 0.03729492416749787 + 0.037297299817180121 + 0.037299675517321253 + 0.037302051267917621 + 0.037304427068965355 + 0.037306802920460798 + 0.037309178822400209 + 0.03731155477477982 + 0.037313930777595893 + 0.03731630683084463 + 0.037318682934522375 + 0.03732105908862534 + 0.037323435293149791 + 0.037325811548091982 + 0.037328187853448193 + 0.037330564209214691 + 0.037332940615387715 + 0.037335317071963525 + 0.037337693578938382 + 0.037340070136308551 + 0.037342446744070244 + 0.037344823402219826 + 0.037347200110753521 + 0.037349576869667597 + 0.037351953678958251 + 0.037354330538621826 + 0.03735670744865454 + 0.037359084409052667 + 0.037361461419812572 + 0.037363838480930292 + 0.037366215592402351 + 0.037368592754224779 + 0.037370969966394066 + 0.037373347228906298 + 0.037375724541757908 + 0.037378101904944991 + 0.037380479318463937 + 0.037382856782311034 + 0.037385234296482384 + 0.037387611860974453 + 0.037389989475783425 + 0.037392367140905533 + 0.037394744856337092 + 0.03739712262207439 + 0.0373995004381137 + 0.037401878304451235 + 0.037404256221083371 + 0.037406634188006216 + 0.037409012205216287 + 0.037411390272709635 + 0.037413768390482584 + 0.037416146558531489 + 0.03741852477685257 + 0.037420903045442114 + 0.037423281364296415 + 0.037425659733411699 + 0.037428038152784324 + 0.037430416622410437 + 0.037432795142286465 + 0.037435173712408634 + 0.037437552332773162 + 0.037439931003376406 + 0.037442309724214612 + 0.037444688495284012 + 0.03744706731658097 + 0.037449446188101754 + 0.037451825109842574 + 0.037454204081799822 + 0.037456583103969675 + 0.037458962176348476 + 0.037461341298932534 + 0.037463720471718066 + 0.037466099694701403 + 0.037468478967878756 + 0.037470858291246481 + 0.037473237664800853 + 0.037475617088538159 + 0.03747799656245468 + 0.037480376086546675 + 0.037482755660810455 + 0.037485135285242333 + 0.037487514959838528 + 0.037489894684595432 + 0.037492274459509194 + 0.037494654284576212 + 0.037497034159792796 + 0.037499414085155079 + 0.037501794060659517 + 0.037504174086302321 + 0.037506554162079889 + 0.037508934287988301 + 0.037511314464024031 + 0.037513694690183272 + 0.037516074966462427 + 0.03751845529285764 + 0.037520835669365364 + 0.037523216095981769 + 0.037525596572703171 + 0.037527977099525926 + 0.037530357676446302 + 0.037532738303460475 + 0.037535118980564962 + 0.037537499707755877 + 0.037539880485029625 + 0.037542261312382488 + 0.037544642189810684 + 0.037547023117310584 + 0.037549404094878447 + 0.037551785122510624 + 0.037554166200203423 + 0.037556547327953035 + 0.03755892850575588 + 0.037561309733608182 + 0.037563691011506264 + 0.037566072339446414 + 0.037568453717425003 + 0.03757083514543829 + 0.037573216623482515 + 0.037575598151554084 + 0.037577979729649214 + 0.037580361357764283 + 0.037582743035895545 + 0.037585124764039315 + 0.037587506542191958 + 0.03758988837034969 + 0.037592270248508822 + 0.037594652176665723 + 0.037597034154816647 + 0.037599416182957958 + 0.037601798261085874 + 0.037604180389196787 + 0.037606562567286964 + 0.03760894479535274 + 0.037611327073390419 + 0.037613709401396293 + 0.037616091779366707 + 0.037618474207297907 + 0.037620856685186284 + 0.037623239213028042 + 0.037625621790819623 + 0.037628004418557293 + 0.037630387096237311 + 0.037632769823855994 + 0.037635152601409719 + 0.037637535428894808 + 0.037639918306307509 + 0.037642301233644128 + 0.037644684210901086 + 0.037647067238074601 + 0.037649450315161023 + 0.037651833442156675 + 0.037654216619057837 + 0.037656599845860846 + 0.037658983122562086 + 0.037661366449157754 + 0.037663749825644244 + 0.037666133252017849 + 0.037668516728274953 + 0.037670900254411811 + 0.037673283830424717 + 0.037675667456310055 + 0.037678051132064148 + 0.037680434857683277 + 0.037682818633163757 + 0.037685202458501911 + 0.03768758633369413 + 0.037689970258736667 + 0.037692354233625915 + 0.037694738258358125 + 0.037697122332929635 + 0.037699506457336801 + 0.037701890631575904 + 0.037704274855643323 + 0.0377066591295354 + 0.037709043453248374 + 0.037711427826778568 + 0.037713812250122408 + 0.037716196723276224 + 0.037718581246236289 + 0.037720965818998864 + 0.037723350441560374 + 0.037725735113917129 + 0.037728119836065485 + 0.037730504608001716 + 0.037732889429722229 + 0.037735274301223219 + 0.037737659222501184 + 0.037740044193552306 + 0.03774242921437309 + 0.037744814284959662 + 0.03774719940530858 + 0.037749584575415933 + 0.03775196979527827 + 0.037754355064891769 + 0.037756740384252904 + 0.037759125753357881 + 0.03776151117220311 + 0.03776389664078493 + 0.037766282159099621 + 0.037768667727143594 + 0.037771053344913159 + 0.037773439012404604 + 0.037775824729614368 + 0.037778210496538685 + 0.037780596313173959 + 0.037782982179516499 + 0.037785368095562669 + 0.037787754061308798 + 0.037790140076751223 + 0.037792526141886267 + 0.03779491225671032 + 0.037797298421219705 + 0.037799684635410745 + 0.03780207089927981 + 0.037804457212823245 + 0.037806843576037322 + 0.037809229988918489 + 0.037811616451463047 + 0.037814002963667319 + 0.037816389525527676 + 0.037818776137040426 + 0.037821162798201982 + 0.037823549509008653 + 0.037825936269456767 + 0.037828323079542717 + 0.037830709939262817 + 0.037833096848613433 + 0.037835483807590879 + 0.037837870816191554 + 0.037840257874411809 + 0.037842644982247979 + 0.037845032139696373 + 0.037847419346753342 + 0.037849806603415331 + 0.037852193909678616 + 0.037854581265539568 + 0.037856968670994529 + 0.037859356126039849 + 0.037861743630671914 + 0.037864131184887059 + 0.037866518788681643 + 0.037868906442051958 + 0.037871294144994475 + 0.037873681897505451 + 0.037876069699581329 + 0.03787845755121836 + 0.037880845452412999 + 0.037883233403161583 + 0.037885621403460384 + 0.037888009453305838 + 0.037890397552694334 + 0.037892785701622161 + 0.037895173900085739 + 0.037897562148081383 + 0.037899950445605464 + 0.037902338792654311 + 0.037904727189224337 + 0.037907115635311919 + 0.037909504130913353 + 0.037911892676025044 + 0.037914281270643307 + 0.037916669914764556 + 0.037919058608385195 + 0.037921447351501492 + 0.037923836144109851 + 0.037926224986206659 + 0.037928613877788217 + 0.037931002818850937 + 0.037933391809391245 + 0.037935780849405409 + 0.037938169938889869 + 0.037940559077840878 + 0.037942948266254967 + 0.037945337504128408 + 0.037947726791457539 + 0.037950116128238814 + 0.037952505514468562 + 0.03795489495014312 + 0.037957284435258858 + 0.037959673969812237 + 0.037962063553799545 + 0.037964453187217168 + 0.037966842870061558 + 0.03796923260232897 + 0.037971622384015837 + 0.037974012215118501 + 0.037976402095633376 + 0.037978792025556818 + 0.03798118200488515 + 0.037983572033614806 + 0.037985962111742218 + 0.037988352239263661 + 0.037990742416175532 + 0.037993132642474232 + 0.037995522918156083 + 0.037997913243217628 + 0.038000303617655017 + 0.038002694041464793 + 0.038005084514643218 + 0.038007475037186766 + 0.038009865609091767 + 0.038012256230354667 + 0.038014646900971748 + 0.038017037620939421 + 0.038019428390254129 + 0.038021819208912219 + 0.038024210076910057 + 0.038026600994244007 + 0.038028991960910453 + 0.03803138297690585 + 0.038033774042226479 + 0.038036165156868855 + 0.038038556320829253 + 0.038040947534104093 + 0.038043338796689793 + 0.038045730108582636 + 0.038048121469779123 + 0.038050512880275562 + 0.038052904340068493 + 0.038055295849154062 + 0.038057687407528837 + 0.038060079015189131 + 0.038062470672131345 + 0.038064862378351924 + 0.03806725413384715 + 0.038069645938613478 + 0.038072037792647326 + 0.038074429695945038 + 0.038076821648503019 + 0.038079213650317661 + 0.038081605701385357 + 0.038083997801702553 + 0.038086389951265495 + 0.038088782150070749 + 0.038091174398114568 + 0.03809356669539344 + 0.038095959041903736 + 0.038098351437641863 + 0.038100743882604177 + 0.038103136376787097 + 0.03810552892018701 + 0.038107921512800361 + 0.03811031415462348 + 0.03811270684565278 + 0.038115099585884681 + 0.038117492375315545 + 0.038119885213941884 + 0.038122278101759895 + 0.03812467103876617 + 0.038127064024957052 + 0.038129457060328914 + 0.038131850144878077 + 0.038134243278601147 + 0.038136636461494372 + 0.038139029693554191 + 0.038141422974777031 + 0.038143816305159214 + 0.038146209684697271 + 0.038148603113387504 + 0.038150996591226387 + 0.038153390118210243 + 0.038155783694335539 + 0.038158177319598724 + 0.038160570993996092 + 0.038162964717524124 + 0.038165358490179192 + 0.038167752311957792 + 0.038170146182856177 + 0.038172540102870869 + 0.038174934071998207 + 0.038177328090234698 + 0.038179722157576708 + 0.038182116274020614 + 0.038184510439562794 + 0.038186904654199764 + 0.038189298917927848 + 0.038191693230743534 + 0.038194087592643089 + 0.038196482003623161 + 0.038198876463679941 + 0.038201270972810043 + 0.038203665531009644 + 0.038206060138275343 + 0.038208454794603476 + 0.038210849499990499 + 0.038213244254432774 + 0.038215639057926784 + 0.038218033910468886 + 0.038220428812055528 + 0.038222823762683183 + 0.038225218762348148 + 0.038227613811046883 + 0.038230008908775842 + 0.03823240405553141 + 0.038234799251310049 + 0.038237194496108122 + 0.038239589789922132 + 0.038241985132748423 + 0.038244380524583434 + 0.038246775965423557 + 0.038249171455265268 + 0.038251566994105021 + 0.038253962581939194 + 0.038256358218764101 + 0.038258753904576344 + 0.038261149639372258 + 0.038263545423148269 + 0.038265941255900847 + 0.038268337137626361 + 0.03827073306832126 + 0.038273129047981996 + 0.038275525076604935 + 0.0382779211541866 + 0.038280317280723279 + 0.03828271345621153 + 0.03828510968064773 + 0.038287505954028245 + 0.038289902276349659 + 0.038292298647608233 + 0.038294695067800512 + 0.03829709153692288 + 0.038299488054971811 + 0.038301884621943595 + 0.038304281237834914 + 0.038306677902641952 + 0.038309074616361287 + 0.038311471378989291 + 0.038313868190522418 + 0.038316265050957123 + 0.038318661960289761 + 0.038321058918516893 + 0.03832345592563486 + 0.038325852981640131 + 0.038328250086529077 + 0.038330647240298277 + 0.038333044442944039 + 0.038335441694462791 + 0.038337838994851076 + 0.038340236344105286 + 0.038342633742221813 + 0.038345031189197167 + 0.038347428685027767 + 0.038349826229709991 + 0.03835222382324039 + 0.038354621465615253 + 0.038357019156831165 + 0.038359416896884525 + 0.038361814685771767 + 0.038364212523489288 + 0.038366610410033607 + 0.038369008345401141 + 0.038371406329588284 + 0.038373804362591531 + 0.038376202444407301 + 0.038378600575032111 + 0.038380998754462291 + 0.038383396982694336 + 0.038385795259724756 + 0.038388193585549873 + 0.038390591960166309 + 0.038392990383570302 + 0.038395388855758474 + 0.038397787376727152 + 0.038400185946472855 + 0.038402584564992036 + 0.038404983232281011 + 0.038407381948336455 + 0.038409780713154693 + 0.038412179526732142 + 0.038414578389065313 + 0.038416977300150673 + 0.038419376259984588 + 0.038421775268563586 + 0.038424174325884124 + 0.038426573431942626 + 0.038428972586735458 + 0.038431371790259239 + 0.038433771042510369 + 0.038436170343485287 + 0.038438569693180422 + 0.038440969091592246 + 0.038443368538717194 + 0.038445768034551811 + 0.038448167579092467 + 0.038450567172335637 + 0.03845296681427781 + 0.038455366504915406 + 0.038457766244244906 + 0.038460166032262724 + 0.038462565868965383 + 0.038464965754349358 + 0.03846736568841104 + 0.038469765671146919 + 0.038472165702553476 + 0.038474565782627125 + 0.038476965911364389 + 0.038479366088761714 + 0.038481766314815501 + 0.038484166589522265 + 0.038486566912878453 + 0.038488967284880674 + 0.038491367705525137 + 0.038493768174808457 + 0.038496168692727033 + 0.038498569259277408 + 0.038500969874456059 + 0.038503370538259356 + 0.038505771250683801 + 0.038508172011725864 + 0.038510572821382094 + 0.038512973679648829 + 0.038515374586522676 + 0.038517775541999949 + 0.03852017654607727 + 0.038522577598750996 + 0.038524978700017601 + 0.038527379849873637 + 0.038529781048315538 + 0.038532182295339779 + 0.03853458359094275 + 0.038536984935121088 + 0.038539386327871142 + 0.038541787769189435 + 0.038544189259072374 + 0.038546590797516544 + 0.038548992384518331 + 0.038551394020074216 + 0.038553795704180778 + 0.03855619743683434 + 0.038558599218031474 + 0.038561001047768627 + 0.038563402926042302 + 0.038565804852848988 + 0.038568206828185077 + 0.038570608852047154 + 0.038573010924431606 + 0.038575413045334975 + 0.038577815214753723 + 0.038580217432684319 + 0.038582619699123293 + 0.038585022014067057 + 0.038587424377512135 + 0.038589826789454974 + 0.038592229249892071 + 0.038594631758819969 + 0.038597034316235103 + 0.038599436922133905 + 0.038601839576512961 + 0.038604242279368671 + 0.038606645030697551 + 0.03860904783049611 + 0.038611450678760782 + 0.038613853575488119 + 0.03861625652067454 + 0.038618659514316582 + 0.038621062556410735 + 0.038623465646953424 + 0.038625868785941195 + 0.038628271973370515 + 0.038630675209237915 + 0.038633078493539856 + 0.038635481826272799 + 0.038637885207433262 + 0.038640288637017725 + 0.038642692115022671 + 0.038645095641444652 + 0.038647499216280072 + 0.038649902839525491 + 0.038652306511177355 + 0.038654710231232257 + 0.038657113999686556 + 0.038659517816536801 + 0.038661921681779503 + 0.038664325595411123 + 0.038666729557428267 + 0.03866913356782728 + 0.038671537626604684 + 0.038673941733757121 + 0.038676345889280914 + 0.038678750093172606 + 0.038681154345428743 + 0.038683558646045814 + 0.038685962995020313 + 0.038688367392348696 + 0.03869077183802748 + 0.038693176332053186 + 0.038695580874422396 + 0.038697985465131458 + 0.03870039010417696 + 0.038702794791555396 + 0.038705199527263236 + 0.038707604311297002 + 0.038710009143653176 + 0.038712414024328318 + 0.038714818953318964 + 0.038717223930621505 + 0.038719628956232453 + 0.038722034030148421 + 0.038724439152365828 + 0.038726844322881177 + 0.03872924954169104 + 0.038731654808791822 + 0.038734060124180139 + 0.038736465487852464 + 0.038738870899805281 + 0.03874127636003509 + 0.038743681868538493 + 0.03874608742531193 + 0.038748493030351848 + 0.038750898683654847 + 0.038753304385217395 + 0.038755710135036051 + 0.038758115933107296 + 0.038760521779427612 + 0.03876292767399353 + 0.03876533361680163 + 0.038767739607848371 + 0.038770145647130182 + 0.038772551734643751 + 0.038774957870385464 + 0.038777364054351941 + 0.038779770286539512 + 0.038782176566944875 + 0.038784582895564496 + 0.038786989272394906 + 0.038789395697432567 + 0.038791802170674072 + 0.038794208692115861 + 0.038796615261754437 + 0.038799021879586455 + 0.038801428545608314 + 0.038803835259816587 + 0.03880624202220772 + 0.03880864883277832 + 0.038811055691524904 + 0.038813462598443968 + 0.038815869553531987 + 0.038818276556785568 + 0.038820683608201206 + 0.038823090707775385 + 0.038825497855504681 + 0.038827905051385551 + 0.038830312295414643 + 0.03883271958758832 + 0.038835126927903238 + 0.038837534316355907 + 0.038839941752942718 + 0.03884234923766039 + 0.038844756770505334 + 0.038847164351474117 + 0.038849571980563255 + 0.038851979657769257 + 0.03885438738308869 + 0.038856795156518111 + 0.038859202978053953 + 0.038861610847692789 + 0.038864018765431121 + 0.038866426731265606 + 0.038868834745192669 + 0.038871242807208807 + 0.038873650917310654 + 0.038876059075494657 + 0.038878467281757423 + 0.038880875536095399 + 0.03888328383850518 + 0.038885692188983335 + 0.038888100587526293 + 0.038890509034130695 + 0.038892917528793043 + 0.038895326071509785 + 0.03889773466227759 + 0.03890014330109292 + 0.03890255198795238 + 0.038904960722852419 + 0.038907369505789567 + 0.038909778336760473 + 0.03891218721576159 + 0.038914596142789512 + 0.038917005117840735 + 0.038919414140911796 + 0.038921823211999218 + 0.038924232331099637 + 0.038926641498209472 + 0.038929050713325371 + 0.038931459976443844 + 0.038933869287561422 + 0.038936278646674621 + 0.038938688053780007 + 0.038941097508874159 + 0.038943507011953572 + 0.038945916563014785 + 0.038948326162054459 + 0.038950735809068986 + 0.038953145504054987 + 0.038955555247008972 + 0.038957965037927554 + 0.038960374876807286 + 0.038962784763644558 + 0.038965194698436102 + 0.03896760468117836 + 0.038970014711867951 + 0.038972424790501413 + 0.038974834917075193 + 0.038977245091586024 + 0.038979655314030304 + 0.038982065584404625 + 0.038984475902705581 + 0.038986886268929717 + 0.038989296683073479 + 0.038991707145133607 + 0.038994117655106457 + 0.038996528212988761 + 0.038998938818776911 + 0.039001349472467604 + 0.039003760174057316 + 0.039006170923542596 + 0.03900858172092006 + 0.039010992566186196 + 0.039013403459337639 + 0.039015814400370864 + 0.039018225389282492 + 0.039020636426069004 + 0.039023047510727049 + 0.03902545864325313 + 0.039027869823643861 + 0.039030281051895703 + 0.039032692328005353 + 0.03903510365196923 + 0.039037515023783977 + 0.03903992644344613 + 0.039042337910952296 + 0.039044749426299034 + 0.039047160989482771 + 0.039049572600500279 + 0.039051984259347951 + 0.039054395966022407 + 0.039056807720520302 + 0.039059219522838057 + 0.03906163137297234 + 0.039064043270919675 + 0.039066455216676579 + 0.039068867210239729 + 0.039071279251605619 + 0.039073691340770815 + 0.039076103477731952 + 0.039078515662485498 + 0.039080927895028067 + 0.039083340175356279 + 0.039085752503466645 + 0.039088164879355743 + 0.039090577303020228 + 0.039092989774456528 + 0.039095402293661229 + 0.039097814860631012 + 0.03910022747536241 + 0.039102640137851925 + 0.039105052848096226 + 0.039107465606091844 + 0.03910987841183531 + 0.039112291265323285 + 0.039114704166552286 + 0.039117117115518893 + 0.039119530112219691 + 0.039121943156651254 + 0.039124356248810166 + 0.039126769388693007 + 0.039129182576296329 + 0.03913159581161671 + 0.039134009094650798 + 0.039136422425395077 + 0.03913883580384625 + 0.039141249230000702 + 0.039143662703855227 + 0.039146076225406216 + 0.03914848979465041 + 0.039150903411584288 + 0.039153317076204439 + 0.039155730788507433 + 0.039158144548490016 + 0.039160558356148512 + 0.039162972211479692 + 0.039165386114480082 + 0.039167800065146245 + 0.039170214063474859 + 0.039172628109462385 + 0.039175042203105477 + 0.039177456344400681 + 0.03917987053334461 + 0.039182284769933941 + 0.039184699054165058 + 0.039187113386034665 + 0.039189527765539404 + 0.039191942192675785 + 0.039194356667440387 + 0.039196771189829817 + 0.03919918575984075 + 0.039201600377469628 + 0.039204015042713189 + 0.039206429755567936 + 0.03920884451603044 + 0.039211259324097358 + 0.039213674179765179 + 0.039216089083030634 + 0.039218504033890308 + 0.039220919032340658 + 0.039223334078378358 + 0.03922574917200003 + 0.039228164313202273 + 0.039230579501981611 + 0.03923299473833472 + 0.03923541002225811 + 0.039237825353748437 + 0.039240240732802328 + 0.039242656159416293 + 0.039245071633586974 + 0.039247487155311005 + 0.039249902724584916 + 0.039252318341405343 + 0.039254734005768954 + 0.039257149717672191 + 0.039259565477111756 + 0.039261981284084264 + 0.039264397138586281 + 0.039266813040614433 + 0.039269228990165286 + 0.039271644987235427 + 0.039274061031821537 + 0.039276477123920149 + 0.039278893263527959 + 0.039281309450641413 + 0.039283725685257266 + 0.03928614196737204 + 0.039288558296982412 + 0.039290974674084933 + 0.03929339109867621 + 0.039295807570752843 + 0.039298224090311501 + 0.039300640657348652 + 0.039303057271861092 + 0.039305473933845307 + 0.039307890643297969 + 0.039310307400215592 + 0.039312724204594883 + 0.039315141056432419 + 0.039317557955724752 + 0.039319974902468628 + 0.039322391896660557 + 0.039324808938297158 + 0.039327226027375053 + 0.039329643163890898 + 0.039332060347841258 + 0.039334477579222767 + 0.039336894858032011 + 0.039339312184265632 + 0.039341729557920237 + 0.039344146978992418 + 0.039346564447478846 + 0.039348981963376078 + 0.039351399526680826 + 0.03935381713738962 + 0.039356234795499039 + 0.039358652501005779 + 0.039361070253906484 + 0.039363488054197697 + 0.039365905901876067 + 0.0393683237969382 + 0.039370741739380759 + 0.039373159729200323 + 0.039375577766393548 + 0.039377995850957005 + 0.039380413982887358 + 0.039382832162181219 + 0.039385250388835197 + 0.039387668662845904 + 0.039390086984210079 + 0.039392505352924177 + 0.039394923768984846 + 0.039397342232388895 + 0.039399760743132742 + 0.039402179301213071 + 0.039404597906626572 + 0.039407016559369748 + 0.039409435259439372 + 0.039411854006832003 + 0.039414272801544227 + 0.039416691643572754 + 0.039419110532914171 + 0.039421529469565078 + 0.039423948453522158 + 0.039426367484782003 + 0.039428786563341207 + 0.039431205689196544 + 0.039433624862344509 + 0.03943604408278175 + 0.039438463350504951 + 0.039440882665510761 + 0.03944330202779571 + 0.03944572143735655 + 0.039448140894189819 + 0.0394505603982922 + 0.039452979949660273 + 0.039455399548290769 + 0.039457819194180253 + 0.039460238887325416 + 0.039462658627722844 + 0.03946507841536917 + 0.039467498250261045 + 0.039469918132395122 + 0.03947233806176801 + 0.039474758038376391 + 0.039477178062216851 + 0.039479598133286088 + 0.039482018251580743 + 0.039484438417097353 + 0.039486858629832693 + 0.039489278889783257 + 0.039491699196945805 + 0.039494119551316986 + 0.0394965399528934 + 0.039498960401671682 + 0.039501380897648423 + 0.039503801440820351 + 0.039506222031184091 + 0.03950864266873632 + 0.039511063353473597 + 0.039513484085392667 + 0.039515904864490088 + 0.039518325690762517 + 0.039520746564206698 + 0.039523167484819127 + 0.039525588452596599 + 0.039528009467535659 + 0.039530430529632996 + 0.039532851638885279 + 0.039535272795289088 + 0.039537693998841134 + 0.039540115249538023 + 0.039542536547376446 + 0.03954495789235301 + 0.039547379284464494 + 0.039549800723707375 + 0.039552222210078432 + 0.039554643743574203 + 0.039557065324191384 + 0.039559486951926744 + 0.039561908626776748 + 0.039564330348738214 + 0.039566752117807726 + 0.039569173933981912 + 0.039571595797257469 + 0.039574017707631019 + 0.039576439665099224 + 0.039578861669658807 + 0.039581283721306378 + 0.039583705820038492 + 0.039586127965852036 + 0.039588550158743421 + 0.039590972398709526 + 0.039593394685746852 + 0.039595817019852125 + 0.039598239401022021 + 0.039600661829253134 + 0.039603084304542194 + 0.039605506826885864 + 0.039607929396280682 + 0.03961035201272347 + 0.039612774676210848 + 0.039615197386739451 + 0.039617620144305879 + 0.039620042948906913 + 0.0396224658005392 + 0.039624888699199327 + 0.03962731164488404 + 0.039629734637589911 + 0.039632157677313727 + 0.039634580764052081 + 0.039637003897801629 + 0.039639427078559122 + 0.039641850306321155 + 0.039644273581084404 + 0.03964669690284555 + 0.039649120271601265 + 0.039651543687348197 + 0.039653967150083021 + 0.039656390659802455 + 0.039658814216503052 + 0.039661237820181647 + 0.039663661470834777 + 0.039666085168459209 + 0.039668508913051521 + 0.039670932704608516 + 0.03967335654312671 + 0.039675780428602855 + 0.039678204361033684 + 0.039680628340415788 + 0.039683052366745873 + 0.039685476440020566 + 0.039687900560236689 + 0.039690324727390751 + 0.039692748941479464 + 0.039695173202499559 + 0.039697597510447713 + 0.039700021865320623 + 0.03970244626711484 + 0.039704870715827151 + 0.039707295211454247 + 0.039709719753992762 + 0.039712144343439379 + 0.039714568979790768 + 0.039716993663043688 + 0.039719418393194761 + 0.039721843170240641 + 0.039724267994178046 + 0.039726692865003646 + 0.039729117782714138 + 0.039731542747306191 + 0.039733967758776571 + 0.039736392817121789 + 0.039738817922338687 + 0.039741243074423907 + 0.039743668273374055 + 0.039746093519185982 + 0.039748518811856232 + 0.039750944151381556 + 0.039753369537758619 + 0.039755794970984096 + 0.03975822045105469 + 0.039760645977967142 + 0.039763071551718036 + 0.039765497172304168 + 0.039767922839722129 + 0.039770348553968667 + 0.039772774315040484 + 0.03977520012293425 + 0.039777625977646704 + 0.039780051879174445 + 0.039782477827514227 + 0.039784903822662726 + 0.039787329864616632 + 0.039789755953372682 + 0.039792182088927486 + 0.03979460827127785 + 0.039797034500420395 + 0.039799460776351818 + 0.039801887099068817 + 0.039804313468568109 + 0.039806739884846398 + 0.039809166347900361 + 0.039811592857726702 + 0.039814019414322069 + 0.039816446017683291 + 0.039818872667806933 + 0.039821299364689734 + 0.039823726108328426 + 0.039826152898719692 + 0.039828579735860271 + 0.039831006619746756 + 0.039833433550375989 + 0.039835860527744529 + 0.039838287551849177 + 0.039840714622686645 + 0.039843141740253531 + 0.039845568904546651 + 0.039847996115562723 + 0.039850423373298346 + 0.039852850677750219 + 0.039855278028915149 + 0.039857705426789854 + 0.039860132871370933 + 0.039862560362655106 + 0.039864987900639151 + 0.03986741548531976 + 0.039869843116693594 + 0.039872270794757442 + 0.039874698519507944 + 0.039877126290941756 + 0.039879554109055748 + 0.039881981973846486 + 0.039884409885310737 + 0.039886837843445287 + 0.039889265848246681 + 0.039891693899711783 + 0.03989412199783722 + 0.039896550142619697 + 0.039898978334056048 + 0.039901406572142806 + 0.039903834856876798 + 0.039906263188254743 + 0.03990869156627333 + 0.039911119990929271 + 0.039913548462219277 + 0.039915976980140079 + 0.039918405544688444 + 0.039920834155860944 + 0.039923262813654443 + 0.039925691518065624 + 0.03992812026909115 + 0.039930549066727744 + 0.039932977910972209 + 0.039935406801821123 + 0.039937835739271392 + 0.03994026472331956 + 0.039942693753962491 + 0.039945122831196833 + 0.039947551955019277 + 0.039949981125426616 + 0.03995241034241552 + 0.039954839605982763 + 0.039957268916125034 + 0.039959698272839059 + 0.039962127676121575 + 0.039964557125969274 + 0.039966986622378957 + 0.039969416165347188 + 0.039971845754870929 + 0.039974275390946667 + 0.039976705073571359 + 0.039979134802741532 + 0.039981564578454011 + 0.03998399440070554 + 0.039986424269492789 + 0.039988854184812496 + 0.039991284146661442 + 0.039993714155036338 + 0.039996144209933956 + 0.039998574311350898 + 0.040001004459283937 + 0.040003434653729936 + 0.040005864894685494 + 0.040008295182147331 + 0.04001072551611231 + 0.040013155896577009 + 0.040015586323538244 + 0.040018016796992746 + 0.040020447316937283 + 0.040022877883368557 + 0.040025308496283239 + 0.040027739155678151 + 0.040030169861550051 + 0.04003260061389554 + 0.04003503141271151 + 0.040037462257994594 + 0.040039893149741594 + 0.040042324087949215 + 0.040044755072614159 + 0.040047186103733284 + 0.040049617181303218 + 0.040052048305320734 + 0.040054479475782577 + 0.040056910692685493 + 0.040059341956026243 + 0.040061773265801515 + 0.040064204622008104 + 0.040066636024642707 + 0.040069067473702133 + 0.040071498969183036 + 0.040073930511082177 + 0.040076362099396426 + 0.040078793734122362 + 0.04008122541525682 + 0.040083657142796526 + 0.040086088916738226 + 0.04008852073707863 + 0.040090952603814581 + 0.040093384516942762 + 0.040095816476459906 + 0.040098248482362805 + 0.040100680534648152 + 0.040103112633312815 + 0.040105544778353396 + 0.040107976969766673 + 0.04011040920754947 + 0.040112841491698518 + 0.040115273822210501 + 0.040117706199082247 + 0.040120138622310501 + 0.040122571091891955 + 0.040125003607823416 + 0.04012743617010163 + 0.040129868778723314 + 0.040132301433685305 + 0.040134734134984293 + 0.040137166882617065 + 0.040139599676580283 + 0.040142032516870839 + 0.040144465403485451 + 0.040146898336420773 + 0.040149331315673713 + 0.040151764341240924 + 0.04015419741311918 + 0.040156630531305276 + 0.040159063695796055 + 0.040161496906588053 + 0.040163930163678203 + 0.040166363467063135 + 0.040168796816739787 + 0.040171230212704773 + 0.040173663654954915 + 0.04017609714348698 + 0.040178530678297679 + 0.040180964259383826 + 0.040183397886742155 + 0.040185831560369478 + 0.040188265280262508 + 0.04019069904641806 + 0.040193132858832796 + 0.040195566717503586 + 0.040198000622427198 + 0.040200434573600334 + 0.040202868571019755 + 0.040205302614682234 + 0.040207736704584683 + 0.040210170840723682 + 0.040212605023096121 + 0.040215039251698663 + 0.040217473526528165 + 0.040219907847581324 + 0.040222342214854968 + 0.040224776628345886 + 0.040227211088050753 + 0.040229645593966447 + 0.040232080146089685 + 0.040234514744417242 + 0.040236949388945877 + 0.040239384079672404 + 0.040241818816593604 + 0.04024425359970616 + 0.040246688429006985 + 0.04024912330449272 + 0.040251558226160264 + 0.040253993194006264 + 0.040256428208027543 + 0.040258863268220958 + 0.040261298374583185 + 0.040263733527111066 + 0.04026616872580132 + 0.040268603970650768 + 0.040271039261656198 + 0.040273474598814349 + 0.040275909982122028 + 0.040278345411576037 + 0.040280780887173046 + 0.040283216408910034 + 0.04028565197678359 + 0.040288087590790583 + 0.040290523250927766 + 0.040292958957191934 + 0.040295394709579921 + 0.040297830508088446 + 0.040300266352714276 + 0.040302702243454266 + 0.040305138180305171 + 0.040307574163263749 + 0.040310010192326849 + 0.040312446267491205 + 0.040314882388753574 + 0.040317318556110836 + 0.040319754769559672 + 0.040322191029096947 + 0.040324627334719435 + 0.0403270636864239 + 0.040329500084207152 + 0.040331936528065979 + 0.040334373017997159 + 0.040336809553997488 + 0.040339246136063774 + 0.040341682764192754 + 0.040344119438381287 + 0.040346556158626146 + 0.040348992924924089 + 0.04035142973727196 + 0.040353866595666546 + 0.040356303500104593 + 0.04035874045058286 + 0.04036117744709828 + 0.040363614489647551 + 0.04036605157822748 + 0.040368488712834903 + 0.040370925893466574 + 0.040373363120119306 + 0.040375800392789873 + 0.040378237711475091 + 0.040380675076171796 + 0.040383112486876697 + 0.040385549943586681 + 0.040387987446298526 + 0.040390424995008979 + 0.040392862589714897 + 0.040395300230413045 + 0.04039773791710026 + 0.040400175649773308 + 0.040402613428429004 + 0.040405051253064164 + 0.040407489123675609 + 0.040409927040260044 + 0.0404123650028144 + 0.040414803011335404 + 0.040417241065819891 + 0.040419679166264669 + 0.040422117312666532 + 0.040424555505022206 + 0.040426993743328588 + 0.040429432027582597 + 0.040431870357780751 + 0.040434308733920135 + 0.040436747155997377 + 0.040439185624009368 + 0.040441624137952881 + 0.04044406269782478 + 0.040446501303621804 + 0.040448939955340796 + 0.040451378652978577 + 0.040453817396532012 + 0.040456256185997776 + 0.040458695021372768 + 0.040461133902653774 + 0.040463572829837591 + 0.040466011802921149 + 0.040468450821901064 + 0.04047088988677431 + 0.040473328997537639 + 0.040475768154187922 + 0.040478207356721883 + 0.040480646605136408 + 0.040483085899428228 + 0.040485525239594242 + 0.040487964625631243 + 0.040490404057536095 + 0.040492843535305474 + 0.040495283058936356 + 0.040497722628425478 + 0.040500162243769705 + 0.040502601904965831 + 0.040505041612010642 + 0.040507481364900975 + 0.040509921163633736 + 0.04051236100820562 + 0.040514800898613458 + 0.040517240834854189 + 0.040519680816924558 + 0.040522120844821465 + 0.040524560918541563 + 0.04052700103808176 + 0.040529441203438925 + 0.040531881414609852 + 0.040534321671591413 + 0.040536761974380352 + 0.040539202322973499 + 0.04054164271736773 + 0.040544083157559932 + 0.040546523643546745 + 0.040548964175325157 + 0.040551404752891929 + 0.040553845376243902 + 0.040556286045377934 + 0.040558726760290757 + 0.040561167520979345 + 0.040563608327440423 + 0.040566049179670854 + 0.04056849007766751 + 0.040570931021427101 + 0.040573372010946615 + 0.040575813046222799 + 0.04057825412725246 + 0.040580695254032489 + 0.040583136426559641 + 0.040585577644830881 + 0.040588018908842935 + 0.040590460218592639 + 0.040592901574076933 + 0.040595342975292506 + 0.040597784422236265 + 0.0406002259149051 + 0.040602667453295778 + 0.040605109037405114 + 0.040607550667230041 + 0.040609992342767326 + 0.04061243406401386 + 0.04061487583096636 + 0.040617317643621823 + 0.040619759501976965 + 0.040622201406028721 + 0.040624643355773898 + 0.040627085351209284 + 0.040629527392331791 + 0.040631969479138254 + 0.040634411611625509 + 0.040636853789790338 + 0.040639296013629651 + 0.040641738283140334 + 0.040644180598319098 + 0.040646622959162902 + 0.040649065365668514 + 0.040651507817832819 + 0.040653950315652707 + 0.040656392859124937 + 0.04065883544824643 + 0.040661278083013945 + 0.040663720763424435 + 0.040666163489474653 + 0.040668606261161526 + 0.040671049078481861 + 0.040673491941432466 + 0.040675934850010351 + 0.040678377804212185 + 0.040680820804034935 + 0.040683263849475355 + 0.040685706940530385 + 0.040688150077196832 + 0.040690593259471504 + 0.040693036487351342 + 0.040695479760833174 + 0.040697923079913836 + 0.0407003664445902 + 0.0407028098548591 + 0.040705253310717351 + 0.040707696812161936 + 0.040710140359189601 + 0.040712583951797235 + 0.040715027589981696 + 0.040717471273739841 + 0.040719915003068506 + 0.040722358777964575 + 0.040724802598424925 + 0.040727246464446351 + 0.0407296903760258 + 0.040732134333160051 + 0.04073457833584597 + 0.040737022384080439 + 0.040739466477860364 + 0.040741910617182568 + 0.040744354802043865 + 0.04074679903244121 + 0.040749243308371423 + 0.040751687629831286 + 0.040754131996817773 + 0.040756576409327755 + 0.040759020867358012 + 0.040761465370905449 + 0.040763909919966992 + 0.040766354514539346 + 0.040768799154619582 + 0.04077124384020437 + 0.040773688571290746 + 0.040776133347875457 + 0.040778578169955407 + 0.040781023037527522 + 0.040783467950588591 + 0.040785912909135517 + 0.040788357913165131 + 0.040790802962674379 + 0.040793248057660117 + 0.040795693198119175 + 0.040798138384048423 + 0.040800583615444717 + 0.040803028892304971 + 0.040805474214626068 + 0.040807919582404831 + 0.040810364995638219 + 0.04081281045432298 + 0.040815255958456094 + 0.040817701508034349 + 0.040820147103054705 + 0.040822592743514061 + 0.040825038429409141 + 0.04082748416073697 + 0.04082992993749434 + 0.040832375759678109 + 0.040834821627285287 + 0.040837267540312666 + 0.040839713498757112 + 0.04084215950261548 + 0.040844605551884683 + 0.040847051646561605 + 0.040849497786643159 + 0.040851943972126208 + 0.040854390203007594 + 0.040856836479284217 + 0.040859282800952954 + 0.040861729168010688 + 0.04086417558045434 + 0.040866622038280738 + 0.040869068541486836 + 0.04087151509006947 + 0.040873961684025462 + 0.040876408323351772 + 0.040878855008045382 + 0.040881301738102997 + 0.040883748513521521 + 0.040886195334297944 + 0.040888642200429121 + 0.040891089111911957 + 0.040893536068743221 + 0.040895983070919989 + 0.040898430118439008 + 0.040900877211297156 + 0.040903324349491468 + 0.040905771533018637 + 0.040908218761875705 + 0.040910666036059556 + 0.040913113355567 + 0.040915560720394914 + 0.040918008130540383 + 0.040920455586000042 + 0.04092290308677092 + 0.040925350632849924 + 0.040927798224233904 + 0.040930245860919777 + 0.040932693542904436 + 0.04093514127018473 + 0.040937589042757648 + 0.040940036860620019 + 0.040942484723768734 + 0.040944932632200691 + 0.040947380585912845 + 0.040949828584901989 + 0.040952276629165119 + 0.040954724718699084 + 0.040957172853500846 + 0.040959621033567227 + 0.040962069258895173 + 0.040964517529481589 + 0.040966965845323326 + 0.040969414206417344 + 0.040971862612760389 + 0.040974311064349594 + 0.040976759561181714 + 0.040979208103253735 + 0.040981656690562508 + 0.040984105323104938 + 0.040986554000878014 + 0.040989002723878447 + 0.040991451492103335 + 0.040993900305549467 + 0.040996349164213831 + 0.040998798068093235 + 0.041001247017184668 + 0.041003696011485041 + 0.041006145050991184 + 0.041008594135700099 + 0.041011043265608615 + 0.041013492440713707 + 0.041015941661012252 + 0.041018390926501093 + 0.041020840237177301 + 0.041023289593037617 + 0.041025738994079054 + 0.041028188440298513 + 0.041030637931692857 + 0.04103308746825908 + 0.041035537049993999 + 0.041037986676894594 + 0.041040436348957758 + 0.041042886066180409 + 0.041045335828559439 + 0.04104778563609178 + 0.041050235488774407 + 0.041052685386604088 + 0.041055135329577899 + 0.041057585317692664 + 0.041060035350945316 + 0.041062485429332746 + 0.041064935552851942 + 0.041067385721499775 + 0.04106983593527317 + 0.041072286194169062 + 0.041074736498184355 + 0.041077186847315976 + 0.041079637241560836 + 0.041082087680915889 + 0.041084538165377965 + 0.041086988694944093 + 0.041089439269611144 + 0.041091889889376065 + 0.041094340554235664 + 0.041096791264187089 + 0.04109924201922701 + 0.041101692819352553 + 0.041104143664560618 + 0.041106594554847997 + 0.041109045490211701 + 0.041111496470648649 + 0.041113947496155809 + 0.04111639856673005 + 0.041118849682368334 + 0.041121300843067518 + 0.041123752048824645 + 0.041126203299636586 + 0.041128654595500247 + 0.041131105936412587 + 0.041133557322370513 + 0.041136008753370951 + 0.041138460229410874 + 0.041140911750487195 + 0.041143363316596814 + 0.041145814927736724 + 0.041148266583903803 + 0.041150718285095006 + 0.041153170031307189 + 0.041155621822537493 + 0.041158073658782636 + 0.041160525540039648 + 0.041162977466305421 + 0.041165429437576943 + 0.041167881453851134 + 0.041170333515124932 + 0.041172785621395251 + 0.041175237772659058 + 0.041177689968913224 + 0.041180142210154785 + 0.041182594496380599 + 0.04118504682758764 + 0.041187499203772848 + 0.041189951624933177 + 0.041192404091065567 + 0.041194856602166867 + 0.041197309158234122 + 0.041199761759264236 + 0.041202214405254171 + 0.041204667096200846 + 0.041207119832101263 + 0.041209572612952237 + 0.041212025438750834 + 0.041214478309493922 + 0.041216931225178506 + 0.041219384185801462 + 0.0412218371913598 + 0.041224290241850439 + 0.041226743337270291 + 0.041229196477616456 + 0.041231649662885644 + 0.041234102893074956 + 0.041236556168181261 + 0.041239009488201604 + 0.041241462853132828 + 0.041243916262971983 + 0.041246369717715996 + 0.041248823217361723 + 0.041251276761906201 + 0.041253730351346322 + 0.041256183985679123 + 0.04125863766490151 + 0.041261091389010428 + 0.04126354515800279 + 0.041265998971875648 + 0.041268452830625892 + 0.041270906734250483 + 0.041273360682746341 + 0.041275814676110509 + 0.041278268714339851 + 0.041280722797431363 + 0.041283176925382005 + 0.04128563109818871 + 0.041288085315848468 + 0.041290539578358196 + 0.041292993885714918 + 0.041295448237915477 + 0.041297902634956973 + 0.041300357076836262 + 0.041302811563550382 + 0.041305266095096209 + 0.041307720671470746 + 0.041310175292670941 + 0.041312629958693746 + 0.041315084669536137 + 0.041317539425195116 + 0.041319994225667615 + 0.041322449070950507 + 0.041324903961040875 + 0.04132735889593564 + 0.041329813875631803 + 0.041332268900126291 + 0.041334723969416017 + 0.041337179083498057 + 0.041339634242369298 + 0.04134208944602677 + 0.041344544694467335 + 0.041346999987688031 + 0.041349455325685881 + 0.041351910708457708 + 0.041354366136000666 + 0.0413568216083115 + 0.041359277125387388 + 0.041361732687225157 + 0.04136418829382188 + 0.041366643945174482 + 0.041369099641279869 + 0.041371555382135092 + 0.041374011167737063 + 0.041376466998082902 + 0.041378922873169417 + 0.041381378792993584 + 0.041383834757552522 + 0.041386290766843074 + 0.041388746820862236 + 0.041391202919606976 + 0.041393659063074371 + 0.041396115251261259 + 0.041398571484164697 + 0.041401027761781603 + 0.041403484084109043 + 0.041405940451143937 + 0.041408396862883265 + 0.041410853319323933 + 0.041413309820463047 + 0.041415766366297534 + 0.04141822295682434 + 0.04142067959204055 + 0.041423136271943002 + 0.041425592996528829 + 0.04142804976579486 + 0.041430506579738138 + 0.041432963438355661 + 0.041435420341644373 + 0.041437877289601313 + 0.041440334282223434 + 0.041442791319507725 + 0.041445248401451168 + 0.04144770552805075 + 0.041450162699303447 + 0.04145261991520624 + 0.041455077175756111 + 0.041457534480950131 + 0.041459991830785158 + 0.04146244922525822 + 0.041464906664366329 + 0.041467364148106534 + 0.041469821676475629 + 0.041472279249470827 + 0.041474736867088947 + 0.041477194529327105 + 0.041479652236182253 + 0.04148210998765129 + 0.041484567783731274 + 0.041487025624419277 + 0.041489483509712162 + 0.041491941439607001 + 0.041494399414100713 + 0.041496857433190405 + 0.041499315496872961 + 0.041501773605145412 + 0.041504231758004766 + 0.041506689955448026 + 0.041509148197472187 + 0.041511606484074183 + 0.041514064815251085 + 0.041516523190999827 + 0.041518981611317472 + 0.041521440076200913 + 0.041523898585647319 + 0.041526357139653525 + 0.041528815738216582 + 0.041531274381333527 + 0.041533733069001287 + 0.041536191801216996 + 0.041538650577977454 + 0.041541109399279887 + 0.041543568265121074 + 0.041546027175498185 + 0.041548486130408145 + 0.041550945129847972 + 0.041553404173814652 + 0.041555863262305259 + 0.041558322395316649 + 0.041560781572845977 + 0.041563240794890155 + 0.041565700061446248 + 0.041568159372511224 + 0.041570618728082112 + 0.041573078128155951 + 0.04157553757272963 + 0.041577997061800244 + 0.041580456595364787 + 0.041582916173420241 + 0.041585375795963719 + 0.041587835462992051 + 0.041590295174502391 + 0.041592754930491707 + 0.041595214730957022 + 0.041597674575895277 + 0.041600134465303557 + 0.04160259439917887 + 0.041605054377518207 + 0.041607514400318554 + 0.041609974467576971 + 0.041612434579290453 + 0.041614894735455973 + 0.041617354936070591 + 0.041619815181131364 + 0.041622275470635232 + 0.041624735804579212 + 0.041627196182960319 + 0.041629656605775653 + 0.041632117073022147 + 0.04163457758469688 + 0.041637038140796764 + 0.041639498741318927 + 0.041641959386260287 + 0.041644420075617986 + 0.041646880809388949 + 0.041649341587570145 + 0.041651802410158735 + 0.041654263277151708 + 0.041656724188546039 + 0.041659185144338723 + 0.041661646144526852 + 0.041664107189107388 + 0.041666568278077389 + 0.041669029411433856 + 0.041671490589173812 + 0.041673951811294324 + 0.041676413077792414 + 0.041678874388665084 + 0.041681335743909295 + 0.041683797143522133 + 0.04168625858750067 + 0.041688720075841866 + 0.041691181608542724 + 0.041693643185600343 + 0.041696104807011726 + 0.041698566472773875 + 0.041701028182883862 + 0.041703489937338668 + 0.041705951736135401 + 0.041708413579271034 + 0.041710875466742542 + 0.041713337398547053 + 0.041715799374681548 + 0.041718261395143015 + 0.041720723459928603 + 0.041723185569035245 + 0.041725647722459992 + 0.04172810992019995 + 0.041730572162252073 + 0.041733034448613447 + 0.041735496779281046 + 0.041737959154251943 + 0.041740421573523173 + 0.041742884037091713 + 0.041745346544954716 + 0.041747809097109123 + 0.041750271693551978 + 0.041752734334280339 + 0.041755197019291354 + 0.041757659748581838 + 0.041760122522149001 + 0.041762585339989798 + 0.041765048202101293 + 0.041767511108480551 + 0.041769974059124568 + 0.041772437054030422 + 0.041774900093195094 + 0.04177736317661572 + 0.041779826304289266 + 0.041782289476212861 + 0.041784752692383464 + 0.041787215952798065 + 0.041789679257453881 + 0.041792142606347754 + 0.041794605999476958 + 0.041797069436838349 + 0.041799532918429062 + 0.041801996444246106 + 0.04180446001428649 + 0.041806923628547384 + 0.041809387287025747 + 0.041811850989718589 + 0.041814314736623087 + 0.041816778527736118 + 0.041819242363054877 + 0.041821706242576404 + 0.041824170166297615 + 0.041826634134215737 + 0.041829098146327751 + 0.041831562202630602 + 0.041834026303121462 + 0.04183649044779738 + 0.041838954636655365 + 0.0418414188696924 + 0.04184388314690575 + 0.041846347468292272 + 0.041848811833849101 + 0.041851276243573314 + 0.041853740697461887 + 0.041856205195511975 + 0.041858669737720518 + 0.041861134324084628 + 0.041863598954601393 + 0.041866063629267855 + 0.041868528348081011 + 0.041870993111038014 + 0.041873457918135869 + 0.041875922769371625 + 0.041878387664742348 + 0.041880852604245081 + 0.041883317587876945 + 0.041885782615635012 + 0.041888247687516221 + 0.0418907128035177 + 0.041893177963636563 + 0.041895643167869798 + 0.041898108416214504 + 0.041900573708667746 + 0.041903039045226569 + 0.041905504425888002 + 0.041907969850649186 + 0.041910435319507208 + 0.041912900832459028 + 0.041915366389501746 + 0.041917831990632398 + 0.041920297635848147 + 0.041922763325146009 + 0.041925229058523056 + 0.041927694835976331 + 0.041930160657502949 + 0.041932626523099877 + 0.041935092432764318 + 0.041937558386493261 + 0.041940024384283799 + 0.04194249042613294 + 0.041944956512037841 + 0.041947422641995594 + 0.041949888816003152 + 0.041952355034057677 + 0.041954821296156242 + 0.041957287602295841 + 0.041959753952473637 + 0.041962220346686674 + 0.041964686784932002 + 0.041967153267206701 + 0.041969619793507947 + 0.041972086363832602 + 0.04197455297817794 + 0.041977019636540942 + 0.041979486338918688 + 0.041981953085308256 + 0.041984419875706794 + 0.041986886710111262 + 0.041989353588518893 + 0.041991820510926599 + 0.041994287477331527 + 0.041996754487730804 + 0.041999221542121483 + 0.042001688640500578 + 0.042004155782865267 + 0.042006622969212558 + 0.042009090199539564 + 0.042011557473843344 + 0.042014024792121053 + 0.042016492154369693 + 0.042018959560586329 + 0.042021427010768164 + 0.042023894504912125 + 0.042026362043015471 + 0.042028829625075162 + 0.042031297251088263 + 0.042033764921052 + 0.042036232634963366 + 0.042038700392819386 + 0.042041168194617277 + 0.042043636040354035 + 0.042046103930026786 + 0.042048571863632603 + 0.042051039841168612 + 0.042053507862631859 + 0.042055975928019469 + 0.042058444037328446 + 0.042060912190555994 + 0.042063380387699155 + 0.042065848628755044 + 0.042068316913720684 + 0.042070785242593195 + 0.042073253615369725 + 0.042075722032047368 + 0.042078190492623131 + 0.042080658997094171 + 0.042083127545457545 + 0.042085596137710367 + 0.042088064773849784 + 0.042090533453872765 + 0.042093002177776513 + 0.042095470945558169 + 0.042097939757214639 + 0.042100408612743181 + 0.042102877512140924 + 0.042105346455404785 + 0.042107815442532018 + 0.042110284473519659 + 0.042112753548364863 + 0.042115222667064633 + 0.04211769182961618 + 0.042120161036016492 + 0.042122630286262765 + 0.042125099580352064 + 0.042127568918281434 + 0.042130038300048071 + 0.042132507725649047 + 0.042134977195081427 + 0.042137446708342352 + 0.042139916265428984 + 0.042142385866338283 + 0.042144855511067503 + 0.042147325199613665 + 0.042149794931973836 + 0.042152264708145204 + 0.042154734528124863 + 0.042157204391909911 + 0.042159674299497428 + 0.042162144250884569 + 0.042164614246068384 + 0.042167084285046001 + 0.042169554367814624 + 0.042172024494371178 + 0.042174494664712958 + 0.04217696487883698 + 0.042179435136740363 + 0.042181905438420202 + 0.042184375783873657 + 0.042186846173097745 + 0.042189316606089773 + 0.042191787082846668 + 0.042194257603365544 + 0.042196728167643617 + 0.042199198775677994 + 0.042201669427465692 + 0.042204140123003941 + 0.042206610862289759 + 0.042209081645320314 + 0.04221155247209276 + 0.042214023342604073 + 0.042216494256851589 + 0.042218965214832253 + 0.042221436216543208 + 0.042223907261981664 + 0.042226378351144594 + 0.042228849484029246 + 0.042231320660632662 + 0.04223379188095204 + 0.042236263144984368 + 0.042238734452726898 + 0.042241205804176736 + 0.042243677199330962 + 0.04224614863818666 + 0.042248620120741057 + 0.042251091646991173 + 0.042253563216934235 + 0.042256034830567266 + 0.042258506487887419 + 0.042260978188891934 + 0.042263449933577717 + 0.042265921721942108 + 0.042268393553982091 + 0.042270865429694861 + 0.042273337349077525 + 0.042275809312127176 + 0.042278281318841031 + 0.042280753369216155 + 0.042283225463249655 + 0.042285697600938685 + 0.042288169782280408 + 0.042290642007271888 + 0.042293114275910357 + 0.042295586588192852 + 0.042298058944116528 + 0.042300531343678532 + 0.042303003786876001 + 0.04230547627370599 + 0.042307948804165794 + 0.04231042137825243 + 0.042312893995963038 + 0.042315366657294712 + 0.042317839362244654 + 0.042320312110810054 + 0.042322784902987937 + 0.042325257738775476 + 0.042327730618169822 + 0.042330203541168086 + 0.042332676507767474 + 0.042335149517964972 + 0.042337622571757903 + 0.042340095669143277 + 0.042342568810118275 + 0.042345041994680081 + 0.042347515222825767 + 0.04234998849455248 + 0.042352461809857377 + 0.042354935168737604 + 0.042357408571190316 + 0.042359882017212587 + 0.042362355506801626 + 0.042364829039954609 + 0.04236730261666858 + 0.042369776236940736 + 0.042372249900768252 + 0.042374723608148208 + 0.042377197359077759 + 0.042379671153554087 + 0.042382144991574333 + 0.042384618873135646 + 0.042387092798235139 + 0.042389566766869925 + 0.042392040779037292 + 0.042394514834734214 + 0.042396988933957991 + 0.042399463076705626 + 0.042401937262974421 + 0.042404411492761425 + 0.042406885766063808 + 0.042409360082878704 + 0.042411834443203372 + 0.042414308847034787 + 0.04241678329437025 + 0.042419257785206818 + 0.042421732319541668 + 0.042424206897372016 + 0.042426681518694907 + 0.042429156183507566 + 0.042431630891807154 + 0.042434105643590798 + 0.04243658043885562 + 0.042439055277598871 + 0.042441530159817595 + 0.042444005085509044 + 0.04244648005467036 + 0.042448955067298677 + 0.042451430123391039 + 0.042453905222944836 + 0.042456380365957051 + 0.042458855552424929 + 0.042461330782345534 + 0.042463806055716175 + 0.042466281372533915 + 0.042468756732795876 + 0.042471232136499261 + 0.04247370758364126 + 0.042476183074219048 + 0.04247865860822974 + 0.04248113418567049 + 0.042483609806538508 + 0.042486085470830874 + 0.042488561178544888 + 0.042491036929677616 + 0.042493512724226232 + 0.042495988562187927 + 0.042498464443559848 + 0.042500940368339124 + 0.042503416336523013 + 0.042505892348108601 + 0.042508368403093112 + 0.042510844501473757 + 0.042513320643247476 + 0.042515796828411695 + 0.042518273056963519 + 0.042520749328900001 + 0.042523225644218406 + 0.04252570200291593 + 0.042528178404989722 + 0.042530654850436868 + 0.042533131339254703 + 0.042535607871440187 + 0.042538084446990705 + 0.042540561065903273 + 0.042543037728175165 + 0.042545514433803486 + 0.042547991182785433 + 0.042550467975118231 + 0.042552944810798979 + 0.042555421689824888 + 0.042557898612193161 + 0.042560375577900947 + 0.042562852586945345 + 0.042565329639323669 + 0.042567806735032972 + 0.042570283874070587 + 0.042572761056433539 + 0.042575238282119066 + 0.042577715551124405 + 0.042580192863446609 + 0.042582670219082956 + 0.042585147618030596 + 0.042587625060286731 + 0.042590102545848475 + 0.042592580074713088 + 0.042595057646877731 + 0.042597535262339517 + 0.04260001292109572 + 0.042602490623143592 + 0.042604968368480101 + 0.042607446157102567 + 0.04260992398900821 + 0.042612401864194106 + 0.042614879782657489 + 0.042617357744395595 + 0.042619835749405567 + 0.042622313797684552 + 0.042624791889229796 + 0.042627270024038467 + 0.042629748202107763 + 0.042632226423434831 + 0.042634704688016896 + 0.042637182995851203 + 0.042639661346934823 + 0.042642139741264989 + 0.042644618178838974 + 0.042647096659653848 + 0.04264957518370692 + 0.042652053750995261 + 0.042654532361516152 + 0.042657011015266748 + 0.042659489712244245 + 0.04266196845244586 + 0.042664447235868715 + 0.042666926062510144 + 0.042669404932367178 + 0.042671883845437124 + 0.042674362801717165 + 0.042676841801204374 + 0.042679320843896161 + 0.042681799929789564 + 0.042684279058881849 + 0.042686758231170178 + 0.042689237446651762 + 0.042691716705323811 + 0.042694196007183521 + 0.042696675352228021 + 0.042699154740454631 + 0.042701634171860493 + 0.042704113646442769 + 0.042706593164198746 + 0.042709072725125627 + 0.042711552329220491 + 0.042714031976480583 + 0.042716511666903233 + 0.042718991400485531 + 0.042721471177224635 + 0.042723950997117857 + 0.042726430860162382 + 0.042728910766355391 + 0.042731390715694074 + 0.042733870708175657 + 0.042736350743797363 + 0.042738830822556292 + 0.04274131094444987 + 0.042743791109475071 + 0.042746271317629272 + 0.042748751568909574 + 0.042751231863313255 + 0.042753712200837443 + 0.042756192581479419 + 0.042758673005236385 + 0.042761153472105545 + 0.04276363398208409 + 0.042766114535169236 + 0.04276859513135825 + 0.042771075770648231 + 0.042773556453036557 + 0.042776037178520313 + 0.042778517947096695 + 0.042780998758763011 + 0.042783479613516404 + 0.042785960511354096 + 0.042788441452273368 + 0.042790922436271389 + 0.042793403463345363 + 0.042795884533492493 + 0.042798365646710017 + 0.042800846802995132 + 0.04280332800234516 + 0.04280580924475718 + 0.04280829053022852 + 0.042810771858756286 + 0.042813253230337807 + 0.042815734644970252 + 0.042818216102650776 + 0.042820697603376742 + 0.04282317914714532 + 0.042825660733953642 + 0.042828142363799018 + 0.042830624036678637 + 0.042833105752589758 + 0.042835587511529605 + 0.042838069313495312 + 0.042840551158484175 + 0.042843033046493458 + 0.042845514977520309 + 0.042847996951561995 + 0.042850478968615678 + 0.042852961028678728 + 0.042855443131748237 + 0.042857925277821445 + 0.042860407466895588 + 0.042862889698967975 + 0.042865371974035817 + 0.042867854292096233 + 0.04287033665314649 + 0.042872819057183896 + 0.042875301504205612 + 0.042877783994208836 + 0.04288026652719093 + 0.042882749103149029 + 0.042885231722080391 + 0.042887714383982228 + 0.042890197088851757 + 0.042892679836686293 + 0.042895162627482941 + 0.042897645461239052 + 0.042900128337951815 + 0.04290261125761842 + 0.042905094220236202 + 0.042907577225802289 + 0.042910060274314002 + 0.0429125433657686 + 0.042915026500163149 + 0.042917509677495032 + 0.042919992897761494 + 0.042922476160959747 + 0.042924959467086965 + 0.042927442816140429 + 0.042929926208117461 + 0.042932409643015153 + 0.04293489312083091 + 0.042937376641561775 + 0.042939860205205162 + 0.042942343811758238 + 0.042944827461218256 + 0.04294731115358242 + 0.042949794888847988 + 0.042952278667012282 + 0.042954762488072465 + 0.042957246352025788 + 0.042959730258869552 + 0.042962214208600927 + 0.042964698201217177 + 0.042967182236715577 + 0.042969666315093351 + 0.042972150436347792 + 0.042974634600476076 + 0.042977118807475463 + 0.042979603057343198 + 0.042982087350076616 + 0.0429845716856729 + 0.042987056064129232 + 0.04298954048544297 + 0.042992024949611282 + 0.042994509456631476 + 0.042996994006500783 + 0.042999478599216441 + 0.043001963234775779 + 0.043004447913175932 + 0.043006932634414165 + 0.043009417398487827 + 0.043011902205394144 + 0.04301438705513027 + 0.043016871947693588 + 0.043019356883081269 + 0.043021841861290606 + 0.043024326882318824 + 0.043026811946163167 + 0.043029297052820936 + 0.04303178220228944 + 0.043034267394565798 + 0.043036752629647325 + 0.043039237907531336 + 0.043041723228215006 + 0.043044208591695637 + 0.04304669399797053 + 0.043049179447036838 + 0.043051664938891926 + 0.04305415047353299 + 0.043056636050957255 + 0.043059121671162069 + 0.043061607334144734 + 0.043064093039902322 + 0.043066578788432258 + 0.043069064579731788 + 0.043071550413798107 + 0.043074036290628566 + 0.043076522210220333 + 0.043079008172570772 + 0.043081494177677065 + 0.043083980225536472 + 0.043086466316146363 + 0.043088952449503899 + 0.043091438625606375 + 0.043093924844451077 + 0.043096411106035279 + 0.043098897410356204 + 0.043101383757411196 + 0.043103870147197423 + 0.043106356579712221 + 0.043108843054952883 + 0.043111329572916565 + 0.043113816133600734 + 0.04311630273700242 + 0.043118789383119076 + 0.043121276071947927 + 0.043123762803486218 + 0.043126249577731222 + 0.043128736394680213 + 0.043131223254330553 + 0.043133710156679377 + 0.043136197101724019 + 0.043138684089461754 + 0.043141171119889889 + 0.043143658193005668 + 0.043146145308806359 + 0.043148632467289234 + 0.043151119668451601 + 0.043153606912290685 + 0.043156094198803827 + 0.043158581527988273 + 0.043161068899841316 + 0.043163556314360238 + 0.043166043771542296 + 0.043168531271384744 + 0.043171018813884902 + 0.043173506399040086 + 0.043175994026847492 + 0.043178481697304469 + 0.043180969410408269 + 0.043183457166156146 + 0.043185944964545531 + 0.043188432805573489 + 0.043190920689237466 + 0.043193408615534591 + 0.043195896584462289 + 0.043198384596017832 + 0.04320087265019848 + 0.043203360747001512 + 0.043205848886424182 + 0.043208337068463804 + 0.043210825293117684 + 0.043213313560383097 + 0.043215801870257371 + 0.043218290222737696 + 0.043220778617821455 + 0.043223267055505804 + 0.043225755535788217 + 0.043228244058665877 + 0.043230732624136146 + 0.043233221232196188 + 0.043235709882843365 + 0.043238198576074943 + 0.043240687311888272 + 0.043243176090280611 + 0.043245664911249274 + 0.043248153774791492 + 0.0432506426809047 + 0.04325313162958596 + 0.043255620620832776 + 0.043258109654642399 + 0.043260598731011984 + 0.043263087849939021 + 0.04326557701142069 + 0.043268066215454301 + 0.043270555462037202 + 0.043273044751166612 + 0.043275534082839878 + 0.043278023457054317 + 0.043280512873807214 + 0.043283002333095809 + 0.043285491834917464 + 0.043287981379269522 + 0.043290470966149151 + 0.043292960595553764 + 0.043295450267480606 + 0.043297939981927047 + 0.043300429738890249 + 0.043302919538367644 + 0.04330540938035652 + 0.043307899264854094 + 0.043310389191857791 + 0.043312879161364864 + 0.043315369173372607 + 0.043317859227878258 + 0.043320349324879256 + 0.04332283946437282 + 0.043325329646356277 + 0.0433278198708269 + 0.043330310137782116 + 0.043332800447219058 + 0.043335290799135173 + 0.043337781193527714 + 0.043340271630393987 + 0.043342762109731349 + 0.043345252631537004 + 0.043347743195808384 + 0.043350233802542694 + 0.043352724451737344 + 0.043355215143389567 + 0.043357705877496662 + 0.043360196654056056 + 0.043362687473064945 + 0.043365178334520728 + 0.043367669238420545 + 0.043370160184761981 + 0.043372651173542186 + 0.043375142204758445 + 0.043377633278408163 + 0.043380124394488614 + 0.043382615552997064 + 0.043385106753930994 + 0.04338759799728753 + 0.043390089283064065 + 0.043392580611257982 + 0.04339507198186645 + 0.043397563394886936 + 0.043400054850316672 + 0.043402546348153034 + 0.043405037888393311 + 0.043407529471034809 + 0.043410021096074815 + 0.043412512763510734 + 0.043415004473339867 + 0.043417496225559508 + 0.043419988020166986 + 0.043422479857159621 + 0.043424971736534763 + 0.043427463658289756 + 0.043429955622421829 + 0.043432447628928318 + 0.043434939677806601 + 0.043437431769054104 + 0.043439923902667918 + 0.043442416078645532 + 0.043444908296984261 + 0.043447400557681391 + 0.043449892860734203 + 0.043452385206140157 + 0.043454877593896511 + 0.043457370024000498 + 0.043459862496449612 + 0.043462355011241127 + 0.043464847568372336 + 0.043467340167840547 + 0.04346983280964313 + 0.043472325493777469 + 0.043474818220240879 + 0.043477310989030564 + 0.043479803800143955 + 0.043482296653578438 + 0.043484789549331201 + 0.043487282487399775 + 0.04348977546778128 + 0.043492268490473197 + 0.043494761555472848 + 0.043497254662777478 + 0.043499747812384498 + 0.043502241004291238 + 0.043504734238494991 + 0.043507227514993238 + 0.043509720833783058 + 0.043512214194862051 + 0.043514707598227335 + 0.043517201043876415 + 0.04351969453180652 + 0.043522188062015119 + 0.043524681634499428 + 0.043527175249256797 + 0.043529668906284638 + 0.043532162605580217 + 0.043534656347140988 + 0.043537150130964153 + 0.043539643957047139 + 0.043542137825387239 + 0.043544631735981866 + 0.043547125688828223 + 0.043549619683923853 + 0.043552113721265981 + 0.043554607800851949 + 0.043557101922679135 + 0.043559596086744881 + 0.04356209029304655 + 0.043564584541581471 + 0.043567078832346909 + 0.043569573165340367 + 0.043572067540559062 + 0.043574561958000392 + 0.043577056417661734 + 0.043579550919540418 + 0.043582045463633791 + 0.043584540049939134 + 0.043587034678453901 + 0.043589529349175385 + 0.043592024062101005 + 0.043594518817228034 + 0.043597013614553808 + 0.043599508454075779 + 0.043602003335791249 + 0.043604498259697505 + 0.043606993225792028 + 0.043609488234072062 + 0.043611983284535014 + 0.043614478377178259 + 0.043616973511999065 + 0.043619468688994883 + 0.043621963908163051 + 0.043624459169500862 + 0.043626954473005776 + 0.043629449818675066 + 0.043631945206506116 + 0.043634440636496227 + 0.04363693610864286 + 0.043639431622943321 + 0.043641927179395024 + 0.043644422777995288 + 0.04364691841874143 + 0.043649414101630826 + 0.043651909826660902 + 0.043654405593828952 + 0.043656901403132345 + 0.043659397254568494 + 0.043661893148134762 + 0.043664389083828428 + 0.043666885061646919 + 0.043669381081587619 + 0.043671877143647841 + 0.043674373247824951 + 0.043676869394116365 + 0.04367936558251935 + 0.043681861813031436 + 0.04368435808564982 + 0.04368685440037199 + 0.043689350757195253 + 0.043691847156116959 + 0.043694343597134526 + 0.043696840080245283 + 0.043699336605446698 + 0.043701833172736022 + 0.04370432978211064 + 0.04370682643356797 + 0.043709323127105348 + 0.043711819862720158 + 0.043714316640409777 + 0.043716813460171568 + 0.043719310322002901 + 0.043721807225901223 + 0.043724304171863723 + 0.043726801159888008 + 0.043729298189971233 + 0.043731795262110976 + 0.043734292376304419 + 0.043736789532549086 + 0.043739286730842285 + 0.043741783971181385 + 0.043744281253563784 + 0.043746778577986839 + 0.043749275944448031 + 0.043751773352944549 + 0.043754270803473924 + 0.043756768296033421 + 0.043759265830620592 + 0.043761763407232653 + 0.043764261025867057 + 0.043766758686521141 + 0.043769256389192289 + 0.043771754133877974 + 0.043774251920575435 + 0.04377674974928214 + 0.043779247619995541 + 0.043781745532712864 + 0.043784243487431568 + 0.043786741484149037 + 0.043789239522862705 + 0.043791737603569851 + 0.043794235726267963 + 0.043796733890954322 + 0.043799232097626394 + 0.043801730346281514 + 0.043804228636917145 + 0.043806726969530571 + 0.04380922534411931 + 0.043811723760680592 + 0.04381422221921194 + 0.043816720719710697 + 0.043819219262174247 + 0.043821717846599904 + 0.043824216472985192 + 0.043826715141327459 + 0.043829213851624055 + 0.043831712603872336 + 0.043834211398069853 + 0.043836710234213816 + 0.043839209112301741 + 0.043841708032331027 + 0.043844206994298911 + 0.043846705998202937 + 0.043849205044040503 + 0.043851704131808902 + 0.043854203261505659 + 0.043856702433128031 + 0.043859201646673458 + 0.043861700902139381 + 0.043864200199523168 + 0.043866699538822281 + 0.043869198920033985 + 0.043871698343155768 + 0.043874197808185036 + 0.043876697315119124 + 0.043879196863955472 + 0.043881696454691539 + 0.043884196087324599 + 0.043886695761852113 + 0.043889195478271553 + 0.043891695236580215 + 0.043894195036775538 + 0.043896694878854899 + 0.043899194762815778 + 0.043901694688655526 + 0.043904194656371513 + 0.043906694665961185 + 0.043909194717421926 + 0.043911694810751169 + 0.043914194945946276 + 0.043916695123004744 + 0.043919195341923865 + 0.043921695602701122 + 0.043924195905333842 + 0.043926696249819541 + 0.043929196636155514 + 0.043931697064339283 + 0.043934197534368197 + 0.043936698046239668 + 0.043939198599951074 + 0.043941699195499853 + 0.043944199832883453 + 0.043946700512099215 + 0.043949201233144566 + 0.043951701996017015 + 0.043954202800713792 + 0.043956703647232427 + 0.043959204535570402 + 0.043961705465724983 + 0.043964206437693658 + 0.043966707451473817 + 0.043969208507062908 + 0.043971709604458273 + 0.043974210743657434 + 0.043976711924657727 + 0.043979213147456633 + 0.043981714412051481 + 0.043984215718439704 + 0.043986717066618802 + 0.043989218456586092 + 0.04399171988833904 + 0.043994221361875113 + 0.043996722877191675 + 0.043999224434286117 + 0.044001726033155879 + 0.044004227673798441 + 0.044006729356211111 + 0.044009231080391453 + 0.044011732846336721 + 0.044014234654044471 + 0.044016736503512156 + 0.044019238394737002 + 0.044021740327716649 + 0.044024242302448363 + 0.044026744318929695 + 0.044029246377157889 + 0.044031748477130615 + 0.044034250618845097 + 0.044036752802298851 + 0.044039255027489281 + 0.044041757294413807 + 0.04404425960306986 + 0.044046761953454881 + 0.044049264345566309 + 0.044051766779401529 + 0.044054269254957923 + 0.044056771772233098 + 0.044059274331224363 + 0.044061776931929079 + 0.04406427957434482 + 0.044066782258468953 + 0.04406928498429892 + 0.044071787751832112 + 0.044074290561065946 + 0.04407679341199798 + 0.04407929630462553 + 0.044081799238946062 + 0.044084302214957051 + 0.044086805232655818 + 0.044089308292039921 + 0.044091811393106695 + 0.044094314535853676 + 0.044096817720278236 + 0.0440993209463778 + 0.044101824214149876 + 0.04410432752359178 + 0.044106830874701082 + 0.044109334267475139 + 0.044111837701911398 + 0.04411434117800736 + 0.044116844695760347 + 0.044119348255167855 + 0.044121851856227377 + 0.044124355498936306 + 0.044126859183292018 + 0.044129362909292133 + 0.044131866676933897 + 0.04413437048621488 + 0.044136874337132495 + 0.044139378229684119 + 0.044141882163867212 + 0.044144386139679269 + 0.044146890157117841 + 0.044149394216180096 + 0.044151898316863655 + 0.044154402459165965 + 0.044156906643084491 + 0.044159410868616536 + 0.044161915135759684 + 0.044164419444511327 + 0.04416692379486898 + 0.044169428186830041 + 0.044171932620391888 + 0.044174437095552063 + 0.044176941612307979 + 0.044179446170657111 + 0.044181950770596848 + 0.044184455412124748 + 0.044186960095238134 + 0.044189464819934549 + 0.044191969586211403 + 0.044194474394066131 + 0.044196979243496283 + 0.044199484134499194 + 0.044201989067072373 + 0.044204494041213266 + 0.044206999056919313 + 0.044209504114188017 + 0.044212009213016754 + 0.044214514353403025 + 0.044217019535344307 + 0.044219524758838037 + 0.044222030023881656 + 0.044224535330472624 + 0.044227040678608401 + 0.044229546068286468 + 0.044232051499504266 + 0.044234556972259191 + 0.04423706248654883 + 0.044239568042370531 + 0.044242073639721893 + 0.044244579278600128 + 0.044247084959003015 + 0.044249590680927736 + 0.044252096444371898 + 0.044254602249332885 + 0.044257108095808274 + 0.044259613983795403 + 0.044262119913291841 + 0.044264625884294924 + 0.044267131896802266 + 0.044269637950811194 + 0.04427214404631926 + 0.044274650183323917 + 0.044277156361822605 + 0.044279662581812831 + 0.044282168843292009 + 0.044284675146257668 + 0.044287181490707178 + 0.044289687876638152 + 0.044292194304047877 + 0.044294700772933966 + 0.044297207283293817 + 0.044299713835124967 + 0.044302220428424799 + 0.044304727063190788 + 0.044307233739420505 + 0.04430974045711128 + 0.044312247216260758 + 0.044314754016866229 + 0.044317260858925338 + 0.044319767742435415 + 0.044322274667393934 + 0.044324781633798493 + 0.044327288641646478 + 0.044329795690935397 + 0.044332302781662683 + 0.044334809913825803 + 0.044337317087422293 + 0.044339824302449649 + 0.044342331558905247 + 0.044344838856786611 + 0.044347346196091257 + 0.044349853576816596 + 0.044352360998960123 + 0.04435486846251939 + 0.044357375967491779 + 0.044359883513874786 + 0.044362391101665989 + 0.044364898730862717 + 0.044367406401462528 + 0.044369914113462916 + 0.044372421866861356 + 0.044374929661655321 + 0.044377437497842336 + 0.044379945375419706 + 0.044382453294385164 + 0.044384961254736059 + 0.044387469256469851 + 0.044389977299584098 + 0.044392485384076245 + 0.044394993509943775 + 0.044397501677184162 + 0.044400009885794935 + 0.044402518135773582 + 0.044405026427117557 + 0.044407534759824306 + 0.044410043133891429 + 0.044412551549316344 + 0.044415060006096539 + 0.04441756850422944 + 0.044420077043712675 + 0.044422585624543647 + 0.044425094246719858 + 0.04442760291023886 + 0.044430111615097995 + 0.044432620361294951 + 0.044435129148827017 + 0.044437637977691825 + 0.044440146847886809 + 0.044442655759409568 + 0.044445164712257401 + 0.044447673706427965 + 0.044450182741918663 + 0.044452691818727054 + 0.044455200936850577 + 0.044457710096286747 + 0.04446021929703306 + 0.044462728539087067 + 0.044465237822446185 + 0.044467747147107918 + 0.044470256513069857 + 0.04447276592032938 + 0.04447527536888405 + 0.044477784858731308 + 0.044480294389868717 + 0.044482803962293815 + 0.044485313576003993 + 0.044487823230996752 + 0.044490332927269734 + 0.044492842664820308 + 0.044495352443646004 + 0.044497862263744387 + 0.04450037212511284 + 0.044502882027748936 + 0.04450539197165021 + 0.04450790195681411 + 0.044510411983238171 + 0.044512922050919938 + 0.044515432159856802 + 0.044517942310046341 + 0.044520452501486112 + 0.044522962734173457 + 0.044525473008106047 + 0.044527983323281319 + 0.044530493679696768 + 0.044533004077350016 + 0.04453551451623837 + 0.044538024996359525 + 0.044540535517710922 + 0.044543046080289965 + 0.044545556684094337 + 0.044548067329121484 + 0.044550578015368887 + 0.044553088742834049 + 0.044555599511514478 + 0.044558110321407794 + 0.044560621172511368 + 0.044563132064822812 + 0.044565642998339622 + 0.044568153973059292 + 0.04457066498897929 + 0.044573176046097236 + 0.044575687144410479 + 0.044578198283916751 + 0.044580709464613455 + 0.044583220686498046 + 0.044585731949568108 + 0.044588243253821228 + 0.044590754599254795 + 0.044593265985866389 + 0.044595777413653524 + 0.044598288882613711 + 0.044600800392744465 + 0.044603311944043302 + 0.044605823536507792 + 0.044608335170135453 + 0.044610846844923675 + 0.044613358560870169 + 0.044615870317972296 + 0.044618382116227637 + 0.044620893955633761 + 0.044623405836188158 + 0.044625917757888309 + 0.044628429720731784 + 0.044630941724716114 + 0.04463345376983878 + 0.044635965856097332 + 0.044638477983489321 + 0.044640990152012158 + 0.044643502361663548 + 0.044646014612440901 + 0.044648526904341811 + 0.044651039237363702 + 0.044653551611504159 + 0.044656064026760797 + 0.044658576483130999 + 0.044661088980612343 + 0.044663601519202456 + 0.044666114098898674 + 0.044668626719698706 + 0.044671139381599972 + 0.044673652084600113 + 0.044676164828696539 + 0.044678677613886837 + 0.04468119044016855 + 0.044683703307539166 + 0.044686216215996256 + 0.044688729165537414 + 0.044691242156160056 + 0.044693755187861825 + 0.044696268260640167 + 0.044698781374492617 + 0.044701294529416735 + 0.04470380772541014 + 0.044706320962470222 + 0.044708834240594603 + 0.044711347559780817 + 0.044713860920026376 + 0.044716374321328842 + 0.044718887763685725 + 0.044721401247094589 + 0.044723914771553033 + 0.044726428337058463 + 0.044728941943608519 + 0.044731455591200689 + 0.044733969279832572 + 0.044736483009501636 + 0.044738996780205466 + 0.044741510591941612 + 0.044744024444707535 + 0.044746538338500896 + 0.044749052273319233 + 0.044751566249159956 + 0.044754080266020776 + 0.04475659432389914 + 0.044759108422792536 + 0.044761622562698625 + 0.04476413674361495 + 0.044766650965538987 + 0.044769165228468341 + 0.044771679532400535 + 0.044774193877333092 + 0.044776708263263625 + 0.044779222690189573 + 0.044781737158108605 + 0.044784251667018195 + 0.044786766216915901 + 0.044789280807799349 + 0.044791795439666 + 0.044794310112513384 + 0.044796824826339135 + 0.044799339581140789 + 0.044801854376915883 + 0.044804369213661939 + 0.044806884091376585 + 0.044809399010057246 + 0.04481191396970164 + 0.044814428970307171 + 0.044816944011871487 + 0.044819459094392097 + 0.044821974217866593 + 0.044824489382292512 + 0.044827004587667404 + 0.044829519833988848 + 0.044832035121254402 + 0.044834550449461594 + 0.044837065818607975 + 0.044839581228691139 + 0.0448420966797086 + 0.04484461217165802 + 0.044847127704536825 + 0.04484964327834267 + 0.044852158893073008 + 0.044854674548725583 + 0.044857190245297766 + 0.044859705982787212 + 0.044862221761191493 + 0.044864737580508081 + 0.044867253440734639 + 0.044869769341868794 + 0.044872285283907902 + 0.044874801266849611 + 0.044877317290691547 + 0.044879833355431324 + 0.044882349461066305 + 0.044884865607594228 + 0.044887381795012574 + 0.044889898023318983 + 0.044892414292510979 + 0.044894930602586071 + 0.044897446953541927 + 0.044899963345376132 + 0.044902479778086084 + 0.0449049962516695 + 0.044907512766123918 + 0.044910029321446908 + 0.044912545917636056 + 0.044915062554688918 + 0.044917579232602978 + 0.04492009595137595 + 0.044922612711005304 + 0.044925129511488693 + 0.044927646352823654 + 0.04493016323500771 + 0.04493268015803855 + 0.044935197121913621 + 0.044937714126630619 + 0.044940231172186977 + 0.044942748258580335 + 0.044945265385808328 + 0.044947782553868512 + 0.044950299762758349 + 0.044952817012475575 + 0.044955334303017687 + 0.0449578516343822 + 0.044960369006566879 + 0.044962886419569116 + 0.044965403873386565 + 0.044967921368016778 + 0.044970438903457394 + 0.04497295647970595 + 0.044975474096760018 + 0.044977991754617218 + 0.044980509453275107 + 0.044983027192731243 + 0.044985544972983231 + 0.044988062794028637 + 0.044990580655865087 + 0.044993098558490145 + 0.044995616501901398 + 0.044998134486096394 + 0.045000652511072763 + 0.045003170576828053 + 0.045005688683359885 + 0.045008206830665844 + 0.045010725018743467 + 0.045013243247590401 + 0.045015761517204177 + 0.045018279827582358 + 0.045020798178722676 + 0.045023316570622647 + 0.045025835003279772 + 0.045028353476691707 + 0.045030871990856099 + 0.045033390545770491 + 0.04503590914143242 + 0.045038427777839493 + 0.045040946454989315 + 0.045043465172879646 + 0.045045983931507765 + 0.045048502730871499 + 0.045051021570968332 + 0.04505354045179593 + 0.045056059373351803 + 0.045058578335633641 + 0.045061097338638993 + 0.045063616382365404 + 0.045066135466810563 + 0.045068654591971936 + 0.045071173757847298 + 0.04507369296443408 + 0.045076212211729957 + 0.04507873149973253 + 0.045081250828439411 + 0.045083770197848087 + 0.04508628960795627 + 0.045088809058761614 + 0.045091328550261538 + 0.045093848082453765 + 0.045096367655335909 + 0.045098887268905451 + 0.045101406923160156 + 0.045103926618097485 + 0.0451064463537151 + 0.045108966130010572 + 0.045111485946981542 + 0.045114005804625622 + 0.045116525702940405 + 0.045119045641923428 + 0.045121565621572449 + 0.045124085641884901 + 0.045126605702858473 + 0.045129125804490772 + 0.045131645946779417 + 0.045134166129721966 + 0.045136686353316059 + 0.045139206617559283 + 0.045141726922449207 + 0.045144247267983571 + 0.045146767654159918 + 0.045149288080975736 + 0.04515180854842879 + 0.045154329056516687 + 0.045156849605236908 + 0.045159370194587253 + 0.045161890824565135 + 0.045164411495168262 + 0.045166932206394242 + 0.045169452958240729 + 0.045171973750705204 + 0.045174494583785481 + 0.045177015457478979 + 0.045179536371783416 + 0.045182057326696376 + 0.045184578322215431 + 0.045187099358338367 + 0.045189620435062569 + 0.045192141552385781 + 0.045194662710305651 + 0.045197183908819674 + 0.045199705147925526 + 0.04520222642762093 + 0.045204747747903382 + 0.045207269108770501 + 0.04520979051021988 + 0.045212311952249271 + 0.045214833434856175 + 0.045217354958038275 + 0.045219876521793184 + 0.045222398126118439 + 0.045224919771011798 + 0.045227441456470743 + 0.045229963182493012 + 0.045232484949076189 + 0.045235006756217874 + 0.045237528603915667 + 0.045240050492167241 + 0.045242572420970309 + 0.045245094390322219 + 0.045247616400220896 + 0.045250138450663835 + 0.045252660541648629 + 0.045255182673172939 + 0.045257704845234455 + 0.04526022705783074 + 0.045262749310959347 + 0.045265271604618011 + 0.045267793938804347 + 0.045270316313516037 + 0.045272838728750549 + 0.045275361184505626 + 0.045277883680778876 + 0.045280406217567938 + 0.04528292879487044 + 0.045285451412683989 + 0.04528797407100621 + 0.045290496769834807 + 0.045293019509167344 + 0.045295542289001456 + 0.045298065109334845 + 0.045300587970165118 + 0.045303110871489777 + 0.045305633813306663 + 0.045308156795613251 + 0.045310679818407265 + 0.045313202881686318 + 0.045315725985448065 + 0.045318249129690034 + 0.045320772314410014 + 0.045323295539605561 + 0.04532581880527433 + 0.045328342111413907 + 0.045330865458022056 + 0.045333388845096287 + 0.04533591227263431 + 0.045338435740633766 + 0.045340959249092205 + 0.045343482798007387 + 0.04534600638737691 + 0.045348530017198428 + 0.045351053687469479 + 0.045353577398187864 + 0.045356101149351152 + 0.045358624940956889 + 0.045361148773002902 + 0.045363672645486734 + 0.045366196558406041 + 0.045368720511758401 + 0.045371244505541621 + 0.045373768539753181 + 0.045376292614390891 + 0.045378816729452216 + 0.04538134088493493 + 0.045383865080836666 + 0.04538638931715492 + 0.04538891359388756 + 0.045391437911032159 + 0.045393962268586302 + 0.045396486666547664 + 0.045399011104913956 + 0.045401535583682769 + 0.045404060102851772 + 0.045406584662418627 + 0.045409109262380933 + 0.045411633902736406 + 0.045414158583482675 + 0.045416683304617345 + 0.045419208066138174 + 0.045421732868042693 + 0.045424257710328646 + 0.045426782592993695 + 0.045429307516035383 + 0.045431832479451498 + 0.045434357483239603 + 0.045436882527397401 + 0.045439407611922521 + 0.045441932736812615 + 0.045444457902065409 + 0.045446983107678453 + 0.045449508353649429 + 0.045452033639976124 + 0.045454558966656032 + 0.045457084333686913 + 0.045459609741066324 + 0.045462135188792045 + 0.045464660676861689 + 0.045467186205272889 + 0.045469711774023321 + 0.045472237383110646 + 0.045474763032532617 + 0.045477288722286721 + 0.045479814452370738 + 0.045482340222782261 + 0.045484866033519027 + 0.045487391884578683 + 0.04548991777595885 + 0.045492443707657239 + 0.045494969679671496 + 0.045497495691999283 + 0.045500021744638276 + 0.045502547837586185 + 0.045505073970840519 + 0.045507600144399085 + 0.04551012635825958 + 0.045512652612419595 + 0.045515178906876799 + 0.045517705241628868 + 0.045520231616673464 + 0.045522758032008302 + 0.045525284487631046 + 0.045527810983539294 + 0.045530337519730742 + 0.045532864096203128 + 0.045535390712954094 + 0.045537917369981244 + 0.045540444067282304 + 0.045542970804855018 + 0.045545497582696916 + 0.045548024400805742 + 0.045550551259179194 + 0.045553078157814966 + 0.045555605096710625 + 0.045558132075863962 + 0.045560659095272557 + 0.04556318615493414 + 0.045565713254846402 + 0.045568240395006974 + 0.045570767575413541 + 0.045573294796063819 + 0.045575822056955435 + 0.045578349358086176 + 0.045580876699453571 + 0.045583404081055358 + 0.045585931502889268 + 0.045588458964952887 + 0.045590986467243994 + 0.045593514009760222 + 0.045596041592499262 + 0.04559856921545876 + 0.04560109687863638 + 0.045603624582029899 + 0.045606152325636952 + 0.045608680109455277 + 0.045611207933482424 + 0.045613735797716153 + 0.045616263702154235 + 0.045618791646794186 + 0.045621319631633787 + 0.045623847656670768 + 0.04562637572190277 + 0.045628903827327413 + 0.045631431972942435 + 0.045633960158745532 + 0.045636488384734435 + 0.04563901665090675 + 0.045641544957260222 + 0.045644073303792491 + 0.045646601690501304 + 0.045649130117384355 + 0.045651658584439203 + 0.045654187091663703 + 0.04565671563905551 + 0.045659244226612272 + 0.04566177285433165 + 0.045664301522211466 + 0.045666830230249242 + 0.045669358978442799 + 0.045671887766789793 + 0.045674416595287884 + 0.045676945463934825 + 0.045679474372728318 + 0.045682003321665922 + 0.04568453231074552 + 0.045687061339964662 + 0.045689590409321149 + 0.045692119518812656 + 0.045694648668436776 + 0.04569717785819135 + 0.045699707088074012 + 0.045702236358082467 + 0.045704765668214395 + 0.045707295018467479 + 0.045709824408839458 + 0.045712353839328042 + 0.045714883309930919 + 0.045717412820645738 + 0.045719942371470257 + 0.045722471962402249 + 0.045725001593439257 + 0.045727531264579034 + 0.045730060975819421 + 0.045732590727157872 + 0.045735120518592319 + 0.045737650350120375 + 0.045740180221739687 + 0.045742710133448113 + 0.045745240085243118 + 0.045747770077122676 + 0.045750300109084319 + 0.045752830181125873 + 0.045755360293244902 + 0.045757890445439174 + 0.045760420637706453 + 0.045762950870044346 + 0.045765481142450694 + 0.04576801145492311 + 0.04577054180745932 + 0.045773072200057052 + 0.045775602632714019 + 0.045778133105427839 + 0.04578066361819641 + 0.045783194171017276 + 0.045785724763888216 + 0.045788255396806914 + 0.045790786069771085 + 0.045793316782778481 + 0.045795847535826856 + 0.045798378328913786 + 0.0458009091620371 + 0.045803440035194445 + 0.045805970948383595 + 0.04580850190160219 + 0.045811032894848044 + 0.045813563928118757 + 0.045816095001412149 + 0.045818626114725952 + 0.045821157268057737 + 0.045823688461405353 + 0.045826219694766503 + 0.045828750968138862 + 0.045831282281520176 + 0.045833813634908099 + 0.045836345028300481 + 0.045838876461694961 + 0.045841407935089271 + 0.045843939448481121 + 0.045846471001868193 + 0.045849002595248323 + 0.045851534228619137 + 0.045854065901978408 + 0.045856597615323867 + 0.045859129368653169 + 0.0458616611619641 + 0.045864192995254356 + 0.045866724868521669 + 0.045869256781763755 + 0.045871788734978436 + 0.0458743207281632 + 0.045876852761316075 + 0.045879384834434579 + 0.045881916947516511 + 0.045884449100559555 + 0.045886981293561523 + 0.045889513526520063 + 0.045892045799432929 + 0.045894578112297871 + 0.045897110465112634 + 0.04589964285787488 + 0.045902175290582332 + 0.045904707763232855 + 0.045907240275824032 + 0.045909772828353637 + 0.045912305420819512 + 0.045914838053219213 + 0.045917370725550626 + 0.04591990343781132 + 0.045922436189999208 + 0.045924968982111888 + 0.045927501814147162 + 0.045930034686102739 + 0.04593256759797635 + 0.045935100549765767 + 0.045937633541468736 + 0.045940166573082961 + 0.045942699644606136 + 0.045945232756036028 + 0.04594776590737043 + 0.045950299098607095 + 0.045952832329743627 + 0.045955365600777877 + 0.04595789891170754 + 0.045960432262530396 + 0.045962965653244141 + 0.045965499083846499 + 0.045968032554335285 + 0.045970566064708215 + 0.045973099614962938 + 0.045975633205097351 + 0.045978166835109122 + 0.045980700504995926 + 0.045983234214755579 + 0.045985767964385887 + 0.045988301753884485 + 0.045990835583249172 + 0.045993369452477631 + 0.045995903361567704 + 0.045998437310517108 + 0.046000971299323533 + 0.046003505327984785 + 0.046006039396498555 + 0.046008573504862711 + 0.046011107653074833 + 0.046013641841132762 + 0.04601617606903427 + 0.046018710336777027 + 0.046021244644358882 + 0.046023778991777495 + 0.046026313379030681 + 0.046028847806116109 + 0.046031382273031655 + 0.046033916779774954 + 0.046036451326343805 + 0.046038985912735954 + 0.046041520538949172 + 0.046044055204981178 + 0.046046589910829834 + 0.04604912465649269 + 0.046051659441967742 + 0.046054194267252525 + 0.046056729132344883 + 0.046059264037242587 + 0.04606179898194343 + 0.046064333966445117 + 0.046066868990745365 + 0.046069404054842021 + 0.046071939158732818 + 0.046074474302415458 + 0.046077009485887721 + 0.046079544709147414 + 0.046082079972192248 + 0.046084615275019995 + 0.046087150617628435 + 0.046089686000015298 + 0.046092221422178371 + 0.046094756884115365 + 0.046097292385824142 + 0.046099827927302356 + 0.046102363508547878 + 0.04610489912955832 + 0.046107434790331588 + 0.046109970490865383 + 0.046112506231157452 + 0.046115042011205636 + 0.046117577831007658 + 0.046120113690561237 + 0.046122649589864138 + 0.046125185528914245 + 0.046127721507709232 + 0.046130257526246832 + 0.046132793584524906 + 0.046135329682541165 + 0.046137865820293354 + 0.046140401997779294 + 0.046142938214996779 + 0.046145474471943469 + 0.046148010768617284 + 0.046150547105015829 + 0.046153083481137024 + 0.046155619896978556 + 0.046158156352538199 + 0.046160692847813739 + 0.046163229382802921 + 0.046165765957503567 + 0.046168302571913462 + 0.046170839226030325 + 0.046173375919851913 + 0.046175912653376068 + 0.046178449426600543 + 0.046180986239523089 + 0.0461835230921415 + 0.046186059984453583 + 0.046188596916457041 + 0.046191133888149709 + 0.046193670899529332 + 0.046196207950593683 + 0.046198745041340541 + 0.046201282171767756 + 0.046203819341873058 + 0.046206356551654164 + 0.046208893801108993 + 0.046211431090235178 + 0.046213968419030527 + 0.046216505787492937 + 0.046219043195620077 + 0.046221580643409768 + 0.046224118130859783 + 0.046226655657967838 + 0.046229193224731888 + 0.046231730831149544 + 0.046234268477218676 + 0.046236806162937016 + 0.046239343888302489 + 0.046241881653312708 + 0.046244419457965501 + 0.046246957302258668 + 0.046249495186190058 + 0.046252033109757271 + 0.046254571072958377 + 0.046257109075790934 + 0.046259647118252846 + 0.046262185200341831 + 0.04626472332205573 + 0.046267261483392282 + 0.046269799684349334 + 0.046272337924924599 + 0.046274876205115958 + 0.046277414524921151 + 0.046279952884337977 + 0.04628249128336423 + 0.046285029721997648 + 0.046287568200236093 + 0.046290106718077366 + 0.04629264527551917 + 0.046295183872559466 + 0.046297722509195845 + 0.046300261185426198 + 0.046302799901248359 + 0.04630533865666004 + 0.04630787745165911 + 0.046310416286243335 + 0.046312955160410507 + 0.046315494074158456 + 0.04631803302748487 + 0.046320572020387675 + 0.046323111052864595 + 0.046325650124913471 + 0.046328189236532022 + 0.046330728387718144 + 0.046333267578469624 + 0.046335806808784248 + 0.046338346078659734 + 0.046340885388094021 + 0.046343424737084749 + 0.046345964125629927 + 0.046348503553727147 + 0.046351043021374369 + 0.046353582528569297 + 0.046356122075309779 + 0.046358661661593623 + 0.046361201287418607 + 0.046363740952782562 + 0.046366280657683182 + 0.046368820402118455 + 0.04637136018608614 + 0.046373900009583892 + 0.046376439872609684 + 0.046378979775161248 + 0.046381519717236377 + 0.04638405969883299 + 0.046386599719948796 + 0.046389139780581561 + 0.04639167988072921 + 0.046394220020389447 + 0.046396760199560128 + 0.046399300418239121 + 0.046401840676424139 + 0.04640438097411307 + 0.046406921311303653 + 0.046409461687993731 + 0.046412002104181158 + 0.04641454255986361 + 0.046417083055039075 + 0.046419623589705312 + 0.046422164163860108 + 0.046424704777501227 + 0.046427245430626547 + 0.046429786123233875 + 0.046432326855321046 + 0.046434867626885874 + 0.046437408437926118 + 0.046439949288439607 + 0.046442490178424195 + 0.04644503110787767 + 0.046447572076797887 + 0.046450113085182564 + 0.046452654133029674 + 0.046455195220336962 + 0.046457736347102242 + 0.046460277513323295 + 0.046462818718997975 + 0.046465359964124132 + 0.046467901248699581 + 0.046470442572722093 + 0.046472983936189538 + 0.046475525339099745 + 0.046478066781450424 + 0.046480608263239589 + 0.046483149784464904 + 0.046485691345124189 + 0.046488232945215445 + 0.046490774584736265 + 0.04649331626368465 + 0.046495857982058339 + 0.046498399739855173 + 0.046500941537073022 + 0.04650348337370961 + 0.046506025249762828 + 0.046508567165230622 + 0.046511109120110583 + 0.046513651114400673 + 0.046516193148098718 + 0.046518735221202555 + 0.04652127733370999 + 0.046523819485618803 + 0.046526361676926878 + 0.046528903907632126 + 0.046531446177732201 + 0.046533988487225057 + 0.046536530836108488 + 0.046539073224380376 + 0.046541615652038446 + 0.046544158119080643 + 0.046546700625504679 + 0.046549243171308513 + 0.046551785756489938 + 0.04655432838104677 + 0.046556871044976876 + 0.046559413748277982 + 0.046561956490948096 + 0.046564499272984936 + 0.046567042094386293 + 0.046569584955150158 + 0.046572127855274217 + 0.046574670794756461 + 0.046577213773594646 + 0.046579756791786511 + 0.046582299849330031 + 0.046584842946223115 + 0.046587386082463371 + 0.046589929258048814 + 0.046592472472977237 + 0.046595015727246468 + 0.046597559020854294 + 0.046600102353798675 + 0.046602645726077453 + 0.046605189137688352 + 0.046607732588629235 + 0.046610276078898068 + 0.046612819608492596 + 0.046615363177410656 + 0.046617906785650136 + 0.046620450433208845 + 0.046622994120084672 + 0.046625537846275426 + 0.046628081611778963 + 0.046630625416593102 + 0.046633169260715708 + 0.046635713144144664 + 0.046638257066877853 + 0.046640801028912958 + 0.046643345030247946 + 0.046645889070880707 + 0.046648433150809028 + 0.046650977270030744 + 0.046653521428543711 + 0.046656065626345798 + 0.046658609863434813 + 0.046661154139808661 + 0.046663698455465197 + 0.046666242810402311 + 0.04666878720461775 + 0.046671331638109374 + 0.046673876110875076 + 0.046676420622912752 + 0.046678965174220224 + 0.046681509764795293 + 0.046684054394635917 + 0.046686599063739842 + 0.046689143772104938 + 0.046691688519729158 + 0.046694233306610315 + 0.046696778132746156 + 0.046699322998134708 + 0.046701867902773739 + 0.046704412846661082 + 0.046706957829794678 + 0.046709502852172298 + 0.046712047913791854 + 0.046714593014651216 + 0.046717138154748185 + 0.046719683334080671 + 0.046722228552646523 + 0.046724773810443612 + 0.046727319107469766 + 0.04672986444372286 + 0.046732409819200793 + 0.046734955233901379 + 0.046737500687822557 + 0.046740046180962093 + 0.046742591713317912 + 0.046745137284887779 + 0.046747682895669732 + 0.046750228545661528 + 0.046752774234861058 + 0.046755319963266151 + 0.046757865730874745 + 0.046760411537684572 + 0.046762957383693661 + 0.046765503268899819 + 0.046768049193300902 + 0.046770595156894745 + 0.046773141159679274 + 0.04677568720165233 + 0.046778233282811804 + 0.04678077940315551 + 0.046783325562681354 + 0.046785871761387279 + 0.046788417999271012 + 0.046790964276330588 + 0.046793510592563765 + 0.046796056947968373 + 0.046798603342542378 + 0.04680114977628367 + 0.046803696249190098 + 0.046806242761259491 + 0.046808789312489739 + 0.046811335902878788 + 0.04681388253242437 + 0.046816429201124499 + 0.046818975908977024 + 0.046821522655979733 + 0.046824069442130592 + 0.046826616267427443 + 0.046829163131868169 + 0.046831710035450724 + 0.046834256978172832 + 0.046836803960032466 + 0.046839350981027518 + 0.046841898041155836 + 0.046844445140415254 + 0.046846992278803783 + 0.0468495394563192 + 0.046852086672959384 + 0.046854633928722279 + 0.046857181223605653 + 0.046859728557607574 + 0.046862275930725769 + 0.046864823342958169 + 0.046867370794302698 + 0.046869918284757124 + 0.046872465814319468 + 0.046875013382987538 + 0.046877560990759244 + 0.046880108637632492 + 0.046882656323605047 + 0.046885204048674925 + 0.046887751812840037 + 0.046890299616098148 + 0.046892847458447226 + 0.046895395339885147 + 0.046897943260409775 + 0.046900491220019033 + 0.046903039218710758 + 0.046905587256482896 + 0.046908135333333323 + 0.046910683449259923 + 0.046913231604260613 + 0.04691577979833314 + 0.046918328031475595 + 0.046920876303685854 + 0.046923424614961677 + 0.046925972965300995 + 0.046928521354701769 + 0.046931069783161861 + 0.046933618250679036 + 0.046936166757251457 + 0.046938715302876806 + 0.046941263887553049 + 0.046943812511278063 + 0.046946361174049808 + 0.046948909875866016 + 0.046951458616724832 + 0.046954007396623948 + 0.046956556215561308 + 0.046959105073534853 + 0.046961653970542458 + 0.046964202906582021 + 0.046966751881651475 + 0.046969300895748668 + 0.046971849948871526 + 0.046974399041017918 + 0.046976948172185812 + 0.046979497342372972 + 0.046982046551577526 + 0.046984595799797149 + 0.04698714508702987 + 0.046989694413273567 + 0.046992243778526135 + 0.046994793182785502 + 0.046997342626049529 + 0.046999892108316142 + 0.047002441629583239 + 0.047004991189848716 + 0.047007540789110555 + 0.047010090427366542 + 0.047012640104614666 + 0.047015189820852787 + 0.047017739576078854 + 0.047020289370290798 + 0.047022839203486343 + 0.047025389075663636 + 0.047027938986820485 + 0.047030488936954856 + 0.047033038926064495 + 0.047035588954147507 + 0.047038139021201658 + 0.047040689127224929 + 0.047043239272215265 + 0.047045789456170488 + 0.047048339679088599 + 0.047050889940967379 + 0.047053440241804835 + 0.047055990581598935 + 0.047058540960347499 + 0.047061091378048502 + 0.047063641834699771 + 0.047066192330299302 + 0.047068742864845012 + 0.04707129343833473 + 0.047073844050766464 + 0.047076394702138182 + 0.047078945392447571 + 0.047081496121692774 + 0.047084046889871646 + 0.047086597696982049 + 0.047089148543021923 + 0.047091699427989207 + 0.047094250351881833 + 0.047096801314697713 + 0.047099352316434695 + 0.047101903357090837 + 0.047104454436663896 + 0.047107005555151994 + 0.047109556712552889 + 0.04711210790886456 + 0.047114659144084858 + 0.047117210418211784 + 0.047119761731243284 + 0.047122313083177297 + 0.047124864474011596 + 0.047127415903744238 + 0.047129967372373148 + 0.047132518879896189 + 0.047135070426311293 + 0.04713762201161642 + 0.047140173635809524 + 0.04714272529888839 + 0.047145277000851103 + 0.047147828741695583 + 0.047150380521419601 + 0.047152932340021221 + 0.047155484197498383 + 0.047158036093848943 + 0.04716058802907086 + 0.047163140003162143 + 0.047165692016120489 + 0.047168244067944114 + 0.047170796158630811 + 0.047173348288178499 + 0.047175900456585075 + 0.047178452663848632 + 0.047181004909966913 + 0.047183557194937942 + 0.047186109518759678 + 0.047188661881429998 + 0.047191214282946835 + 0.047193766723308155 + 0.047196319202511924 + 0.047198871720556014 + 0.047201424277438404 + 0.047203976873156986 + 0.047206529507709767 + 0.047209082181094597 + 0.047211634893309498 + 0.047214187644352305 + 0.047216740434221062 + 0.047219293262913693 + 0.04722184613042802 + 0.047224399036762163 + 0.047226951981913859 + 0.0472295049658812 + 0.047232057988662104 + 0.047234611050254512 + 0.047237164150656381 + 0.0472397172898655 + 0.047242270467879946 + 0.047244823684697748 + 0.047247376940316652 + 0.047249930234734699 + 0.047252483567949866 + 0.04725503693996002 + 0.047257590350763143 + 0.047260143800357222 + 0.047262697288740142 + 0.047265250815909807 + 0.04726780438186428 + 0.047270357986601418 + 0.047272911630119221 + 0.047275465312415652 + 0.04727801903348855 + 0.047280572793335994 + 0.047283126591955799 + 0.047285680429346097 + 0.047288234305504669 + 0.047290788220429487 + 0.047293342174118604 + 0.047295896166569852 + 0.047298450197781262 + 0.047301004267750739 + 0.047303558376476249 + 0.047306112523955821 + 0.047308666710187235 + 0.047311220935168589 + 0.047313775198897783 + 0.047316329501372725 + 0.047318883842591489 + 0.04732143822255197 + 0.047323992641252081 + 0.04732654709868981 + 0.047329101594863088 + 0.047331656129769945 + 0.047334210703408326 + 0.047336765315776068 + 0.047339319966871261 + 0.047341874656691756 + 0.047344429385235622 + 0.047346984152500722 + 0.047349538958485121 + 0.047352093803186592 + 0.047354648686603322 + 0.047357203608733113 + 0.047359758569574001 + 0.04736231356912389 + 0.047364868607380844 + 0.047367423684342699 + 0.04736997880000747 + 0.047372533954373082 + 0.047375089147437641 + 0.047377644379198926 + 0.047380199649655008 + 0.047382754958803792 + 0.047385310306643259 + 0.047387865693171438 + 0.047390421118386192 + 0.047392976582285605 + 0.047395532084867492 + 0.047398087626129987 + 0.047400643206070944 + 0.047403198824688283 + 0.047405754481980165 + 0.047408310177944363 + 0.04741086591257896 + 0.047413421685881849 + 0.047415977497851043 + 0.047418533348484511 + 0.04742108923778026 + 0.047423645165736134 + 0.047426201132350257 + 0.047428757137620535 + 0.047431313181544886 + 0.047433869264121332 + 0.04743642538534789 + 0.047438981545222435 + 0.047441537743743004 + 0.04744409398090757 + 0.047446650256714108 + 0.047449206571160543 + 0.047451762924244877 + 0.047454319315965089 + 0.047456875746319183 + 0.047459432215305117 + 0.047461988722920866 + 0.04746454526916432 + 0.047467101854033619 + 0.047469658477526613 + 0.047472215139641331 + 0.047474771840375775 + 0.047477328579727897 + 0.047479885357695574 + 0.047482442174277023 + 0.047484999029470003 + 0.047487555923272542 + 0.047490112855682706 + 0.047492669826698385 + 0.047495226836317662 + 0.047497783884538403 + 0.047500340971358634 + 0.047502898096776346 + 0.047505455260789531 + 0.047508012463396185 + 0.047510569704594205 + 0.047513126984381746 + 0.047515684302756579 + 0.047518241659716839 + 0.047520799055260472 + 0.047523356489385438 + 0.047525913962089772 + 0.047528471473371435 + 0.047531029023228352 + 0.047533586611658588 + 0.047536144238660143 + 0.047538701904230964 + 0.04754125960836899 + 0.04754381735107234 + 0.047546375132338961 + 0.047548932952166716 + 0.047551490810553751 + 0.047554048707497985 + 0.0475566066429974 + 0.047559164617050051 + 0.047561722629653837 + 0.047564280680806856 + 0.047566838770506999 + 0.047569396898752302 + 0.047571955065540773 + 0.047574513270870374 + 0.047577071514739173 + 0.047579629797145091 + 0.047582188118086087 + 0.047584746477560266 + 0.047587304875565548 + 0.047589863312099925 + 0.047592421787161408 + 0.047594980300748026 + 0.047597538852857751 + 0.04760009744348858 + 0.047602656072638513 + 0.047605214740305525 + 0.047607773446487679 + 0.047610332191182901 + 0.047612890974389151 + 0.04761544979610461 + 0.047618008656327149 + 0.047620567555054699 + 0.047623126492285443 + 0.047625685468017286 + 0.047628244482248158 + 0.047630803534976215 + 0.047633362626199272 + 0.047635921755915599 + 0.047638480924122893 + 0.047641040130819372 + 0.047643599376002939 + 0.047646158659671659 + 0.047648717981823539 + 0.04765127734245652 + 0.047653836741568603 + 0.047656396179157887 + 0.047658955655222261 + 0.047661515169759847 + 0.047664074722768672 + 0.047666634314246552 + 0.04766919394419164 + 0.047671753612601939 + 0.047674313319475435 + 0.047676873064810138 + 0.047679432848604118 + 0.047681992670855239 + 0.047684552531561633 + 0.047687112430721282 + 0.047689672368332173 + 0.047692232344392384 + 0.047694792358899861 + 0.047697352411852689 + 0.047699912503248704 + 0.047702472633086128 + 0.047705032801362866 + 0.047707593008076969 + 0.047710153253226396 + 0.047712713536809281 + 0.047715273858823529 + 0.047717834219267195 + 0.04772039461813822 + 0.047722955055434731 + 0.047725515531154727 + 0.047728076045296212 + 0.047730636597857173 + 0.047733197188835612 + 0.04773575781822964 + 0.047738318486037171 + 0.047740879192256239 + 0.047743439936884978 + 0.047746000719921342 + 0.047748561541363262 + 0.047751122401208837 + 0.047753683299456097 + 0.047756244236103043 + 0.047758805211147712 + 0.047761366224588077 + 0.04776392727642223 + 0.047766488366648215 + 0.047769049495263942 + 0.047771610662267511 + 0.047774171867656964 + 0.047776733111430242 + 0.047779294393585504 + 0.047781855714120587 + 0.047784417073033679 + 0.047786978470322768 + 0.047789539905985855 + 0.047792101380020956 + 0.047794662892426065 + 0.047797224443199338 + 0.047799786032338726 + 0.047802347659842225 + 0.047804909325707967 + 0.047807471029933789 + 0.047810032772517948 + 0.047812594553458349 + 0.047815156372753007 + 0.047817718230400028 + 0.047820280126397385 + 0.047822842060743123 + 0.047825404033435256 + 0.047827966044471884 + 0.047830528093851021 + 0.047833090181570628 + 0.047835652307628776 + 0.047838214472023501 + 0.047840776674752845 + 0.047843338915814916 + 0.047845901195207603 + 0.047848463512929075 + 0.047851025868977243 + 0.047853588263350288 + 0.047856150696046068 + 0.047858713167062764 + 0.047861275676398363 + 0.04786383822405095 + 0.047866400810018452 + 0.047868963434299035 + 0.047871526096890632 + 0.047874088797791384 + 0.047876651536999201 + 0.047879214314512301 + 0.047881777130328596 + 0.047884339984446078 + 0.047886902876862869 + 0.047889465807577122 + 0.047892028776586687 + 0.04789459178388971 + 0.04789715482948418 + 0.047899717913368139 + 0.047902281035539757 + 0.047904844195996887 + 0.047907407394737735 + 0.047909970631760251 + 0.047912533907062516 + 0.047915097220642598 + 0.047917660572498418 + 0.047920223962628211 + 0.047922787391029828 + 0.047925350857701526 + 0.047927914362641183 + 0.047930477905846931 + 0.047933041487316773 + 0.047935605107048813 + 0.047938168765041082 + 0.047940732461291637 + 0.047943296195798436 + 0.047945859968559629 + 0.047948423779573236 + 0.04795098762883733 + 0.047953551516349925 + 0.047956115442109121 + 0.047958679406112967 + 0.047961243408359416 + 0.047963807448846582 + 0.047966371527572556 + 0.047968935644535464 + 0.047971499799733155 + 0.047974063993163819 + 0.047976628224825464 + 0.047979192494716202 + 0.047981756802834057 + 0.047984321149177112 + 0.047986885533743313 + 0.047989449956530865 + 0.047992014417537733 + 0.047994578916761968 + 0.047997143454201745 + 0.047999708029854968 + 0.048002272643719771 + 0.048004837295794245 + 0.048007401986076385 + 0.048009966714564256 + 0.04801253148125597 + 0.048015096286149542 + 0.04801766112924314 + 0.048020226010534621 + 0.048022790930022229 + 0.048025355887703937 + 0.048027920883577865 + 0.048030485917641995 + 0.0480330509898945 + 0.048035616100333384 + 0.048038181248956646 + 0.048040746435762484 + 0.048043311660748843 + 0.04804587692391387 + 0.048048442225255603 + 0.048051007564772111 + 0.048053572942461431 + 0.048056138358321648 + 0.048058703812350848 + 0.048061269304547093 + 0.048063834834908475 + 0.048066400403433011 + 0.048068966010118806 + 0.048071531654963917 + 0.048074097337966429 + 0.048076663059124447 + 0.048079228818435883 + 0.048081794615898975 + 0.048084360451511758 + 0.04808692632527227 + 0.048089492237178552 + 0.048092058187228788 + 0.048094624175420951 + 0.048097190201753182 + 0.048099756266223481 + 0.048102322368829949 + 0.048104888509570717 + 0.048107454688443831 + 0.048110020905447325 + 0.048112587160579347 + 0.048115153453837864 + 0.048117719785221079 + 0.048120286154727007 + 0.048122852562353664 + 0.048125419008099246 + 0.048127985491961733 + 0.048130552013939308 + 0.048133118574029923 + 0.048135685172231775 + 0.048138251808542885 + 0.048140818482961277 + 0.048143385195485146 + 0.048145951946112521 + 0.048148518734841543 + 0.048151085561670151 + 0.048153652426596541 + 0.048156219329618777 + 0.048158786270734902 + 0.048161353249943077 + 0.048163920267241263 + 0.048166487322627669 + 0.048169054416100317 + 0.048171621547657278 + 0.048174188717296673 + 0.048176755925016579 + 0.048179323170815073 + 0.048181890454690297 + 0.048184457776640259 + 0.048187025136663085 + 0.04818959253475686 + 0.048192159970919635 + 0.048194727445149556 + 0.048197294957444688 + 0.048199862507803067 + 0.048202430096222867 + 0.048204997722702141 + 0.048207565387238929 + 0.048210133089831464 + 0.048212700830477712 + 0.048215268609175792 + 0.048217836425923817 + 0.048220404280719872 + 0.048222972173562001 + 0.048225540104448343 + 0.048228108073376991 + 0.048230676080346056 + 0.04823324412535368 + 0.048235812208397753 + 0.048238380329476575 + 0.048240948488588183 + 0.04824351668573066 + 0.04824608492090212 + 0.048248653194100606 + 0.048251221505324272 + 0.048253789854571197 + 0.048256358241839457 + 0.048258926667127201 + 0.048261495130432486 + 0.048264063631753423 + 0.048266632171088043 + 0.048269200748434611 + 0.048271769363791149 + 0.04827433801715561 + 0.048276906708526371 + 0.04827947543790128 + 0.048282044205278554 + 0.048284613010656313 + 0.048287181854032565 + 0.048289750735405597 + 0.048292319654773305 + 0.048294888612133872 + 0.048297457607485481 + 0.048300026640826194 + 0.048302595712153992 + 0.048305164821467121 + 0.048307733968763623 + 0.048310303154041619 + 0.048312872377299268 + 0.048315441638534587 + 0.048318010937745702 + 0.048320580274930774 + 0.048323149650087847 + 0.048325719063215145 + 0.048328288514310619 + 0.048330858003372459 + 0.048333427530398779 + 0.048335997095387648 + 0.048338566698337242 + 0.04834113633924559 + 0.048343706018110881 + 0.048346275734931207 + 0.048348845489704653 + 0.048351415282429304 + 0.048353985113103383 + 0.04835655498172492 + 0.048359124888291985 + 0.048361694832802733 + 0.048364264815255388 + 0.048366834835647896 + 0.048369404893978479 + 0.048371974990245196 + 0.048374545124446174 + 0.048377115296579572 + 0.048379685506643406 + 0.048382255754635936 + 0.04838482604055519 + 0.04838739636439926 + 0.048389966726166321 + 0.048392537125854479 + 0.048395107563461874 + 0.048397678038986543 + 0.048400248552426701 + 0.04840281910378038 + 0.048405389693045787 + 0.048407960320220947 + 0.048410530985304123 + 0.04841310168829329 + 0.048415672429186651 + 0.048418243207982256 + 0.048420814024678335 + 0.048423384879272988 + 0.048425955771764194 + 0.048428526702150268 + 0.048431097670429274 + 0.048433668676599234 + 0.048436239720658456 + 0.048438810802604898 + 0.048441381922436806 + 0.048443953080152154 + 0.048446524275749268 + 0.048449095509226117 + 0.048451666780580931 + 0.048454238089811669 + 0.048456809436916756 + 0.048459380821893987 + 0.048461952244741709 + 0.048464523705458035 + 0.048467095204041015 + 0.048469666740488825 + 0.048472238314799597 + 0.048474809926971375 + 0.048477381577002411 + 0.048479953264890817 + 0.048482524990634726 + 0.048485096754232182 + 0.048487668555681367 + 0.04849024039498049 + 0.048492812272127525 + 0.048495384187120794 + 0.048497956139958304 + 0.048500528130638258 + 0.048503100159158673 + 0.048505672225517812 + 0.048508244329713769 + 0.048510816471744669 + 0.048513388651608674 + 0.048515960869303869 + 0.048518533124828449 + 0.048521105418180541 + 0.048523677749358271 + 0.048526250118359794 + 0.048528822525183216 + 0.048531394969826697 + 0.048533967452288274 + 0.048536539972566323 + 0.04853911253065879 + 0.048541685126563906 + 0.04854425776027968 + 0.048546830431804487 + 0.048549403141136226 + 0.048551975888273237 + 0.048554548673213516 + 0.048557121495955251 + 0.048559694356496617 + 0.048562267254835832 + 0.048564840190970814 + 0.048567413164899834 + 0.048569986176621109 + 0.048572559226132711 + 0.048575132313432787 + 0.048577705438519476 + 0.048580278601390983 + 0.048582851802045343 + 0.048585425040480808 + 0.048587998316695497 + 0.048590571630687564 + 0.048593144982455143 + 0.04859571837199634 + 0.048598291799309377 + 0.048600865264392355 + 0.048603438767243483 + 0.048606012307860824 + 0.04860858588624261 + 0.048611159502386911 + 0.048613733156291965 + 0.048616306847955933 + 0.048618880577376816 + 0.048621454344552922 + 0.048624028149482378 + 0.048626601992163281 + 0.048629175872593869 + 0.048631749790772158 + 0.048634323746696427 + 0.048636897740364775 + 0.048639471771775397 + 0.048642045840926448 + 0.04864461994781609 + 0.048647194092442371 + 0.048649768274803509 + 0.048652342494897763 + 0.048654916752723203 + 0.048657491048277969 + 0.048660065381560223 + 0.048662639752568133 + 0.048665214161299923 + 0.048667788607753747 + 0.048670363091927668 + 0.048672937613819856 + 0.048675512173428526 + 0.048678086770751923 + 0.048680661405787959 + 0.048683236078535072 + 0.048685810788991257 + 0.048688385537154689 + 0.048690960323023606 + 0.048693535146596113 + 0.048696110007870427 + 0.048698684906844661 + 0.048701259843516934 + 0.048703834817885545 + 0.048706409829948547 + 0.048708984879704126 + 0.048711559967150528 + 0.048714135092285796 + 0.04871671025510816 + 0.048719285455615831 + 0.048721860693806983 + 0.04872443596967968 + 0.048727011283232091 + 0.048729586634462509 + 0.048732162023368976 + 0.0487347374499498 + 0.048737312914203038 + 0.048739888416126864 + 0.048742463955719455 + 0.048745039532979012 + 0.048747615147903718 + 0.048750190800491797 + 0.048752766490741284 + 0.048755342218650473 + 0.0487579179842174 + 0.048760493787440386 + 0.048763069628317501 + 0.048765645506846943 + 0.048768221423026933 + 0.048770797376855649 + 0.048773373368331215 + 0.048775949397451814 + 0.048778525464215662 + 0.048781101568620852 + 0.048783677710665663 + 0.048786253890348186 + 0.048788830107666672 + 0.048791406362619243 + 0.048793982655204071 + 0.048796558985419486 + 0.04879913535326344 + 0.048801711758734267 + 0.048804288201830109 + 0.048806864682549064 + 0.048809441200889418 + 0.048812017756849353 + 0.048814594350427079 + 0.048817170981620597 + 0.04881974765042827 + 0.048822324356848128 + 0.048824901100878559 + 0.048827477882517602 + 0.04883005470176343 + 0.048832631558614392 + 0.048835208453068456 + 0.048837785385123865 + 0.048840362354778961 + 0.048842939362031719 + 0.048845516406880417 + 0.048848093489323306 + 0.048850670609358451 + 0.048853247766984104 + 0.048855824962198487 + 0.048858402194999762 + 0.048860979465385999 + 0.048863556773355576 + 0.048866134118906647 + 0.048868711502037206 + 0.048871288922745712 + 0.048873866381030188 + 0.048876443876888852 + 0.048879021410319939 + 0.04888159898132164 + 0.048884176589892074 + 0.04888675423602952 + 0.048889331919732146 + 0.048891909640998078 + 0.048894487399825624 + 0.048897065196212876 + 0.048899643030158091 + 0.04890222090165941 + 0.048904798810715133 + 0.048907376757323283 + 0.048909954741482221 + 0.048912532763190027 + 0.048915110822445061 + 0.048917688919245264 + 0.048920267053589109 + 0.048922845225474569 + 0.048925423434900001 + 0.048928001681863502 + 0.048930579966363373 + 0.048933158288397664 + 0.048935736647964669 + 0.048938315045062644 + 0.048940893479689634 + 0.048943471951844002 + 0.048946050461523873 + 0.048948629008727429 + 0.048951207593452895 + 0.048953786215698514 + 0.048956364875462392 + 0.048958943572742795 + 0.048961522307537989 + 0.048964101079846042 + 0.048966679889665285 + 0.048969258736993801 + 0.048971837621829897 + 0.048974416544171742 + 0.048976995504017497 + 0.048979574501365475 + 0.048982153536213761 + 0.048984732608560691 + 0.048987311718404355 + 0.048989890865742999 + 0.04899247005057486 + 0.048995049272898099 + 0.04899762853271096 + 0.049000207830011661 + 0.04900278716479841 + 0.049005366537069439 + 0.049007945946822833 + 0.049010525394056911 + 0.049013104878769857 + 0.049015684400959922 + 0.049018263960625322 + 0.049020843557764239 + 0.049023423192374807 + 0.049026002864455361 + 0.049028582574004047 + 0.049031162321019145 + 0.049033742105498761 + 0.049036321927441208 + 0.049038901786844662 + 0.049041481683707304 + 0.049044061618027414 + 0.049046641589803229 + 0.049049221599032848 + 0.049051801645714668 + 0.049054381729846656 + 0.049056961851427251 + 0.049059542010454545 + 0.049062122206926871 + 0.049064702440842337 + 0.049067282712199248 + 0.049069863020995738 + 0.049072443367230087 + 0.049075023750900448 + 0.04907760417200515 + 0.049080184630542346 + 0.049082765126510261 + 0.04908534565990718 + 0.049087926230731202 + 0.049090506838980662 + 0.049093087484653651 + 0.049095668167748609 + 0.049098248888263529 + 0.049100829646196782 + 0.049103410441546549 + 0.049105991274311089 + 0.049108572144488528 + 0.049111153052077181 + 0.04911373399707529 + 0.049116314979480984 + 0.049118895999292575 + 0.049121477056508274 + 0.049124058151126256 + 0.049126639283144848 + 0.049129220452562163 + 0.049131801659376508 + 0.049134382903586168 + 0.049136964185189189 + 0.049139545504184 + 0.04914212686056868 + 0.049144708254341522 + 0.049147289685500799 + 0.049149871154044664 + 0.049152452659971389 + 0.049155034203279255 + 0.049157615783966407 + 0.049160197402031092 + 0.049162779057471566 + 0.049165360750286068 + 0.049167942480472841 + 0.04917052424803009 + 0.049173106052956078 + 0.049175687895249003 + 0.049178269774907135 + 0.049180851691928713 + 0.049183433646312009 + 0.049186015638055129 + 0.04918859766715647 + 0.049191179733614109 + 0.049193761837426395 + 0.049196343978591579 + 0.049198926157107803 + 0.049201508372973379 + 0.049204090626186539 + 0.049206672916745534 + 0.0492092552446486 + 0.049211837609893908 + 0.049214420012479804 + 0.049217002452404464 + 0.049219584929666139 + 0.04922216744426311 + 0.049224749996193501 + 0.049227332585455745 + 0.049229915212047948 + 0.04923249787596834 + 0.049235080577215318 + 0.049237663315786925 + 0.049240246091681539 + 0.049242828904897319 + 0.049245411755432643 + 0.049247994643285643 + 0.0492505775684546 + 0.049253160530937729 + 0.049255743530733379 + 0.049258326567839655 + 0.049260909642254942 + 0.049263492753977366 + 0.049266075903005239 + 0.049268659089336801 + 0.049271242312970302 + 0.049273825573904015 + 0.04927640887213619 + 0.049278992207665011 + 0.049281575580488735 + 0.049284158990605731 + 0.049286742438014154 + 0.049289325922712256 + 0.049291909444698329 + 0.049294493003970645 + 0.049297076600527401 + 0.049299660234366792 + 0.049302243905487257 + 0.049304827613886867 + 0.049307411359563937 + 0.049309995142516785 + 0.049312578962743644 + 0.04931516282024271 + 0.049317746715012267 + 0.049320330647050555 + 0.049322914616355858 + 0.049325498622926435 + 0.049328082666760614 + 0.049330666747856543 + 0.049333250866212437 + 0.049335835021826702 + 0.049338419214697532 + 0.049341003444823159 + 0.049343587712201951 + 0.049346172016831988 + 0.049348756358711721 + 0.0493513407378392 + 0.04935392515421292 + 0.049356509607830952 + 0.049359094098691644 + 0.049361678626793325 + 0.049364263192134078 + 0.049366847794712329 + 0.049369432434526357 + 0.049372017111574254 + 0.04937460182585441 + 0.049377186577365111 + 0.049379771366104531 + 0.049382356192070959 + 0.049384941055262761 + 0.049387525955678087 + 0.049390110893315291 + 0.049392695868172513 + 0.049395280880248207 + 0.049397865929540458 + 0.04940045101604764 + 0.049403036139767986 + 0.049405621300699767 + 0.049408206498841249 + 0.049410791734190801 + 0.049413377006746473 + 0.049415962316506815 + 0.049418547663469814 + 0.049421133047634007 + 0.049423718468997437 + 0.049426303927558542 + 0.049428889423315497 + 0.049431474956266624 + 0.049434060526410174 + 0.049436646133744454 + 0.049439231778267652 + 0.049441817459978193 + 0.049444403178874219 + 0.049446988934954049 + 0.049449574728215991 + 0.049452160558658267 + 0.049454746426279159 + 0.049457332331076985 + 0.049459918273049984 + 0.049462504252196463 + 0.049465090268514658 + 0.049467676322002899 + 0.049470262412659456 + 0.049472848540482575 + 0.049475434705470563 + 0.049478020907621684 + 0.049480607146934218 + 0.049483193423406499 + 0.04948577973703671 + 0.049488366087823164 + 0.049490952475764197 + 0.049493538900858086 + 0.049496125363103084 + 0.049498711862497428 + 0.049501298399039446 + 0.049503884972727494 + 0.049506471583559711 + 0.049509058231534495 + 0.049511644916650131 + 0.049514231638904845 + 0.04951681839829692 + 0.04951940519482468 + 0.049521992028486422 + 0.049524578899280386 + 0.049527165807204857 + 0.04952975275225819 + 0.049532339734438595 + 0.049534926753744477 + 0.049537513810173954 + 0.049540100903725418 + 0.049542688034397153 + 0.049545275202187496 + 0.049547862407094634 + 0.049550449649116993 + 0.04955303692825265 + 0.049555624244500121 + 0.049558211597857477 + 0.04956079898832326 + 0.04956338641589559 + 0.049565973880572801 + 0.049568561382353271 + 0.049571148921235091 + 0.049573736497216719 + 0.049576324110296451 + 0.049578911760472473 + 0.04958149944774326 + 0.049584087172106911 + 0.049586674933561815 + 0.04958926273210628 + 0.049591850567738585 + 0.049594438440456995 + 0.049597026350259858 + 0.04959961429714542 + 0.049602202281112048 + 0.049604790302157982 + 0.049607378360281576 + 0.04960996645548104 + 0.049612554587754779 + 0.049615142757101015 + 0.04961773096351809 + 0.049620319207004257 + 0.049622907487557898 + 0.04962549580517725 + 0.049628084159860614 + 0.049630672551606358 + 0.049633260980412743 + 0.049635849446278024 + 0.049638437949200517 + 0.04964102648917864 + 0.049643615066210581 + 0.049646203680294668 + 0.049648792331429249 + 0.049651381019612563 + 0.04965396974484295 + 0.049656558507118684 + 0.049659147306438174 + 0.049661736142799597 + 0.049664325016201334 + 0.049666913926641687 + 0.049669502874118948 + 0.04967209185863148 + 0.049674680880177485 + 0.049677269938755354 + 0.049679859034363387 + 0.04968244816699989 + 0.049685037336663157 + 0.04968762654335146 + 0.04969021578706323 + 0.049692805067796636 + 0.049695394385550117 + 0.049697983740321874 + 0.049700573132110279 + 0.049703162560913706 + 0.049705752026730325 + 0.049708341529558581 + 0.049710931069396676 + 0.049713520646243022 + 0.049716110260095925 + 0.049718699910953637 + 0.049721289598814458 + 0.049723879323676869 + 0.049726469085538981 + 0.049729058884399185 + 0.049731648720255844 + 0.049734238593107251 + 0.049736828502951684 + 0.049739418449787492 + 0.049742008433613025 + 0.049744598454426601 + 0.049747188512226474 + 0.049749778607010992 + 0.049752368738778509 + 0.049754958907527284 + 0.049757549113255702 + 0.049760139355962046 + 0.049762729635644702 + 0.049765319952301879 + 0.049767910305931987 + 0.049770500696533285 + 0.049773091124104142 + 0.0497756815886429 + 0.049778272090147839 + 0.049780862628617271 + 0.049783453204049602 + 0.049786043816443054 + 0.049788634465796067 + 0.049791225152106891 + 0.049793815875373744 + 0.049796406635595203 + 0.04979899743276945 + 0.049801588266894785 + 0.049804179137969598 + 0.049806770045992203 + 0.049809360990960873 + 0.049811951972874087 + 0.049814542991729979 + 0.049817134047527037 + 0.049819725140263449 + 0.04982231626993764 + 0.049824907436548015 + 0.049827498640092727 + 0.049830089880570215 + 0.049832681157978787 + 0.049835272472316783 + 0.049837863823582559 + 0.049840455211774382 + 0.049843046636890605 + 0.049845638098929668 + 0.049848229597889759 + 0.049850821133769263 + 0.04985341270656652 + 0.049856004316279914 + 0.049858595962907697 + 0.049861187646448257 + 0.04986377936689991 + 0.049866371124261011 + 0.049868962918529845 + 0.049871554749704894 + 0.04987414661778429 + 0.049876738522766459 + 0.049879330464649867 + 0.049881922443432633 + 0.049884514459113238 + 0.049887106511690003 + 0.049889698601161249 + 0.049892290727525317 + 0.049894882890780534 + 0.049897475090925257 + 0.049900067327957875 + 0.049902659601876655 + 0.049905251912679943 + 0.049907844260366152 + 0.049910436644933526 + 0.049913029066380545 + 0.049915621524705404 + 0.049918214019906523 + 0.049920806551982271 + 0.049923399120930953 + 0.049925991726750871 + 0.04992858436944049 + 0.049931177048998 + 0.049933769765421916 + 0.049936362518710531 + 0.049938955308862103 + 0.049941548135875057 + 0.04994414099974772 + 0.049946733900478414 + 0.049949326838065605 + 0.04995191981250751 + 0.04995451282380254 + 0.049957105871949008 + 0.049959698956945325 + 0.049962292078789772 + 0.049964885237480765 + 0.049967478433016556 + 0.049970071665395681 + 0.04997266493461628 + 0.04997525824067682 + 0.049977851583575594 + 0.04998044496331111 + 0.049983038379881536 + 0.049985631833285291 + 0.049988225323520749 + 0.049990818850586247 + 0.049993412414480201 + 0.049996006015200843 + 0.049998599652746646 + 0.050001193327115889 + 0.05000378703830699 + 0.050006380786318215 + 0.050008974571148009 + 0.050011568392794713 + 0.05001416225125669 + 0.050016756146532296 + 0.05001935007861983 + 0.050021944047517697 + 0.050024538053224321 + 0.050027132095737913 + 0.050029726175056896 + 0.050032320291179766 + 0.050034914444104704 + 0.05003750863383017 + 0.050040102860354471 + 0.050042697123676046 + 0.050045291423793138 + 0.050047885760704236 + 0.05005048013440757 + 0.050053074544901627 + 0.050055668992184721 + 0.050058263476255228 + 0.050060857997111519 + 0.050063452554751885 + 0.050066047149174848 + 0.050068641780378606 + 0.050071236448361596 + 0.050073831153122174 + 0.050076425894658765 + 0.050079020672969703 + 0.050081615488053302 + 0.050084210339908002 + 0.050086805228532122 + 0.050089400153924053 + 0.050091995116082151 + 0.05009459011500482 + 0.050097185150690386 + 0.050099780223137297 + 0.050102375332343851 + 0.050104970478308378 + 0.050107565661029377 + 0.050110160880505149 + 0.050112756136734 + 0.050115351429714433 + 0.050117946759444781 + 0.050120542125923345 + 0.050123137529148577 + 0.05012573296911884 + 0.050128328445832433 + 0.050130923959287817 + 0.050133519509483387 + 0.050136115096417501 + 0.050138710720088443 + 0.05014130638049466 + 0.05014390207763457 + 0.050146497811506423 + 0.050149093582108735 + 0.050151689389439889 + 0.050154285233498144 + 0.05015688111428189 + 0.050159477031789607 + 0.050162072986019622 + 0.05016466897697034 + 0.050167265004640055 + 0.050169861069027259 + 0.050172457170130261 + 0.050175053307947443 + 0.050177649482477264 + 0.050180245693718054 + 0.050182841941668187 + 0.050185438226325943 + 0.050188034547689955 + 0.050190630905758413 + 0.050193227300529705 + 0.050195823732002362 + 0.050198420200174586 + 0.050201016705044885 + 0.050203613246611628 + 0.05020620982487313 + 0.050208806439827912 + 0.050211403091474184 + 0.050213999779810489 + 0.050216596504835113 + 0.050219193266546489 + 0.050221790064942991 + 0.050224386900023017 + 0.050226983771785021 + 0.050229580680227238 + 0.050232177625348214 + 0.050234774607146218 + 0.050237371625619712 + 0.050239968680767078 + 0.050242565772586685 + 0.050245162901076924 + 0.050247760066236269 + 0.050250357268062949 + 0.050252954506555488 + 0.050255551781712288 + 0.05025814909353165 + 0.050260746442011978 + 0.050263343827151766 + 0.050265941248949321 + 0.05026853870740304 + 0.05027113620251137 + 0.050273733734272734 + 0.050276331302685391 + 0.050278928907747829 + 0.050281526549458458 + 0.050284124227815627 + 0.050286721942817705 + 0.050289319694463229 + 0.050291917482750512 + 0.050294515307677937 + 0.050297113169243936 + 0.050299711067446864 + 0.050302309002285106 + 0.050304906973757162 + 0.050307504981861317 + 0.050310103026596123 + 0.050312701107959851 + 0.050315299225950905 + 0.050317897380567717 + 0.050320495571808711 + 0.050323093799672335 + 0.050325692064156845 + 0.050328290365260792 + 0.050330888702982413 + 0.050333487077320299 + 0.050336085488272793 + 0.050338683935838256 + 0.050341282420015093 + 0.050343880940801743 + 0.050346479498196629 + 0.050349078092198109 + 0.050351676722804606 + 0.050354275390014518 + 0.050356874093826304 + 0.050359472834238334 + 0.050362071611249025 + 0.050364670424856817 + 0.050367269275059946 + 0.050369868161857123 + 0.050372467085246446 + 0.050375066045226548 + 0.050377665041795784 + 0.050380264074952462 + 0.050382863144695193 + 0.05038546225102223 + 0.050388061393931982 + 0.05039066057342291 + 0.050393259789493487 + 0.05039585904214202 + 0.05039845833136699 + 0.050401057657166792 + 0.050403657019539784 + 0.050406256418484396 + 0.050408855853999165 + 0.050411455326082419 + 0.050414054834732561 + 0.050416654379948037 + 0.050419253961727223 + 0.050421853580068517 + 0.050424453234970412 + 0.050427052926431355 + 0.050429652654449646 + 0.050432252419023799 + 0.050434852220152183 + 0.050437452057833197 + 0.050440051932065293 + 0.050442651842846888 + 0.050445251790176462 + 0.050447851774052317 + 0.050450451794473022 + 0.050453051851436823 + 0.050455651944942288 + 0.050458252074987726 + 0.050460852241571659 + 0.050463452444692525 + 0.050466052684348554 + 0.050468652960538408 + 0.050471253273260332 + 0.050473853622512881 + 0.050476454008294418 + 0.050479054430603375 + 0.050481654889438246 + 0.050484255384797276 + 0.050486855916679049 + 0.05048945648508197 + 0.050492057090004379 + 0.050494657731444861 + 0.050497258409401675 + 0.050499859123873309 + 0.050502459874858324 + 0.050505060662354981 + 0.050507661486361703 + 0.050510262346877034 + 0.050512863243899316 + 0.050515464177427048 + 0.050518065147458581 + 0.050520666153992422 + 0.050523267197026947 + 0.050525868276560623 + 0.05052846939259191 + 0.050531070545119176 + 0.050533671734140868 + 0.050536272959655348 + 0.05053887422166127 + 0.050541475520156837 + 0.050544076855140625 + 0.050546678226611047 + 0.050549279634566423 + 0.050551881079005337 + 0.050554482559926145 + 0.050557084077327355 + 0.050559685631207274 + 0.050562287221564466 + 0.050564888848397271 + 0.050567490511704234 + 0.050570092211483751 + 0.050572693947734178 + 0.050575295720454036 + 0.050577897529641785 + 0.050580499375295823 + 0.050583101257414567 + 0.050585703175996491 + 0.050588305131040047 + 0.050590907122543639 + 0.050593509150505811 + 0.050596111214924855 + 0.050598713315799279 + 0.050601315453127564 + 0.050603917626908065 + 0.050606519837139326 + 0.050609122083819708 + 0.05061172436694765 + 0.050614326686521778 + 0.050616929042540275 + 0.050619531435001711 + 0.050622133863904552 + 0.050624736329247265 + 0.050627338831028164 + 0.050629941369245916 + 0.050632543943898711 + 0.050635146554985209 + 0.050637749202503697 + 0.05064035188645271 + 0.050642954606830722 + 0.050645557363636122 + 0.050648160156867322 + 0.050650762986522893 + 0.050653365852601218 + 0.050655968755100714 + 0.050658571694019904 + 0.050661174669357281 + 0.050663777681111057 + 0.05066638072927996 + 0.050668983813862291 + 0.050671586934856523 + 0.050674190092261213 + 0.050676793286074662 + 0.050679396516295376 + 0.050681999782921844 + 0.050684603085952525 + 0.050687206425385815 + 0.050689809801220197 + 0.050692413213454197 + 0.050695016662086083 + 0.050697620147114535 + 0.050700223668537922 + 0.05070282722635467 + 0.05070543082056321 + 0.0507080344511621 + 0.050710638118149708 + 0.050713241821524563 + 0.050715845561285063 + 0.050718449337429708 + 0.050721053149956938 + 0.050723656998865212 + 0.050726260884153031 + 0.050728864805818737 + 0.050731468763860955 + 0.05073407275827807 + 0.050736676789068479 + 0.050739280856230778 + 0.050741884959763325 + 0.050744489099664586 + 0.050747093275933158 + 0.050749697488567301 + 0.050752301737565612 + 0.050754906022926601 + 0.050757510344648545 + 0.050760114702730064 + 0.050762719097169527 + 0.050765323527965547 + 0.05076792799511648 + 0.050770532498620791 + 0.050773137038476947 + 0.050775741614683449 + 0.050778346227238751 + 0.050780950876141283 + 0.050783555561389603 + 0.050786160282982155 + 0.050788765040917248 + 0.050791369835193598 + 0.050793974665809566 + 0.050796579532763605 + 0.050799184436054134 + 0.050801789375679786 + 0.050804394351638874 + 0.050806999363929899 + 0.050809604412551473 + 0.050812209497501905 + 0.050814814618779708 + 0.050817419776383418 + 0.050820024970311461 + 0.050822630200562269 + 0.050825235467134404 + 0.050827840770026257 + 0.050830446109236399 + 0.050833051484763164 + 0.050835656896605186 + 0.050838262344760854 + 0.050840867829228711 + 0.050843473350007093 + 0.050846078907094666 + 0.050848684500489731 + 0.050851290130190872 + 0.050853895796196542 + 0.050856501498505256 + 0.050859107237115425 + 0.05086171301202555 + 0.050864318823234139 + 0.050866924670739638 + 0.050869530554540549 + 0.050872136474635385 + 0.050874742431022531 + 0.050877348423700584 + 0.050879954452667971 + 0.050882560517923128 + 0.050885166619464607 + 0.050887772757290894 + 0.050890378931400457 + 0.050892985141791788 + 0.050895591388463245 + 0.050898197671413528 + 0.050900803990641001 + 0.050903410346144179 + 0.050906016737921451 + 0.050908623165971494 + 0.050911229630292647 + 0.050913836130883391 + 0.050916442667742277 + 0.050919049240867861 + 0.050921655850258443 + 0.050924262495912705 + 0.050926869177828953 + 0.050929475896005869 + 0.05093208265044178 + 0.050934689441135279 + 0.050937296268084777 + 0.050939903131288884 + 0.050942510030745909 + 0.050945116966454519 + 0.05094772393841307 + 0.050950330946620159 + 0.050952937991074226 + 0.050955545071773842 + 0.050958152188717333 + 0.050960759341903368 + 0.05096336653133033 + 0.050965973756996769 + 0.050968581018901143 + 0.050971188317041942 + 0.050973795651417776 + 0.050976403022026995 + 0.050979010428868154 + 0.050981617871939743 + 0.050984225351240239 + 0.050986832866768174 + 0.050989440418521999 + 0.050992048006500285 + 0.050994655630701519 + 0.050997263291124202 + 0.050999870987766732 + 0.051002478720627707 + 0.051005086489705649 + 0.051007694294998976 + 0.051010302136506168 + 0.051012910014225837 + 0.051015517928156409 + 0.051018125878296433 + 0.051020733864644389 + 0.05102334188719871 + 0.051025949945958042 + 0.051028558040920775 + 0.051031166172085432 + 0.051033774339450527 + 0.051036382543014604 + 0.051038990782776163 + 0.05104159905873365 + 0.05104420737088558 + 0.051046815719230518 + 0.051049424103766852 + 0.051052032524493286 + 0.051054640981408141 + 0.051057249474509986 + 0.051059858003797351 + 0.05106246656926873 + 0.051065075170922659 + 0.051067683808757633 + 0.051070292482772062 + 0.0510729011929646 + 0.051075509939333658 + 0.051078118721877834 + 0.05108072754059554 + 0.051083336395485401 + 0.051085945286545795 + 0.051088554213775325 + 0.051091163177172473 + 0.051093772176735795 + 0.051096381212463751 + 0.05109899028435487 + 0.051101599392407666 + 0.051104208536620649 + 0.051106817716992332 + 0.051109426933521281 + 0.051112036186205891 + 0.05111464547504483 + 0.051117254800036489 + 0.051119864161179439 + 0.051122473558472235 + 0.051125082991913352 + 0.051127692461501222 + 0.051130301967234476 + 0.051132911509111617 + 0.051135521087131153 + 0.051138130701291598 + 0.051140740351591454 + 0.051143350038029271 + 0.051145959760603536 + 0.051148569519312799 + 0.051151179314155588 + 0.051153789145130371 + 0.051156399012235752 + 0.051159008915470108 + 0.051161618854832128 + 0.051164228830320298 + 0.05116683884193305 + 0.051169448889669011 + 0.051172058973526592 + 0.051174669093504398 + 0.051177279249600978 + 0.051179889441814765 + 0.051182499670144342 + 0.051185109934588226 + 0.051187720235145034 + 0.051190330571813117 + 0.051192940944591064 + 0.051195551353477455 + 0.051198161798470823 + 0.051200772279569602 + 0.051203382796772431 + 0.051205993350077722 + 0.051208603939484079 + 0.051211214564990101 + 0.051213825226594137 + 0.051216435924294867 + 0.05121904665809069 + 0.051221657427980294 + 0.05122426823396211 + 0.051226879076034723 + 0.051229489954196586 + 0.051232100868446269 + 0.051234711818782357 + 0.05123732280520326 + 0.051239933827707668 + 0.051242544886294018 + 0.051245155980960813 + 0.051247767111706685 + 0.051250378278530129 + 0.051252989481429631 + 0.051255600720403749 + 0.051258211995451088 + 0.051260823306570079 + 0.051263434653759342 + 0.051266046037017371 + 0.051268657456342723 + 0.051271268911733885 + 0.051273880403189476 + 0.051276491930708032 + 0.051279103494287985 + 0.05128171509392792 + 0.051284326729626524 + 0.051286938401382105 + 0.051289550109193324 + 0.051292161853058682 + 0.051294773632976798 + 0.05129738544894611 + 0.051299997300965253 + 0.051302609189032691 + 0.051305221113147025 + 0.051307833073306761 + 0.051310445069510463 + 0.051313057101756668 + 0.051315669170043876 + 0.051318281274370735 + 0.051320893414735703 + 0.051323505591137304 + 0.051326117803574198 + 0.051328730052044795 + 0.051331342336547708 + 0.051333954657081536 + 0.051336567013644668 + 0.051339179406235842 + 0.051341791834853497 + 0.05134440429949625 + 0.051347016800162515 + 0.051349629336850937 + 0.051352241909560128 + 0.05135485451828848 + 0.051357467163034631 + 0.051360079843797105 + 0.051362692560574512 + 0.051365305313365341 + 0.051367918102168168 + 0.051370530926981565 + 0.051373143787804068 + 0.05137575668463417 + 0.051378369617470498 + 0.051380982586311567 + 0.051383595591155969 + 0.051386208632002196 + 0.051388821708848877 + 0.051391434821694525 + 0.051394047970537676 + 0.05139666115537686 + 0.051399274376210731 + 0.051401887633037782 + 0.051404500925856578 + 0.051407114254665716 + 0.051409727619463663 + 0.051412341020249053 + 0.051414954457020406 + 0.051417567929776233 + 0.051420181438515261 + 0.051422794983235827 + 0.051425408563936667 + 0.051428022180616241 + 0.051430635833273203 + 0.051433249521906005 + 0.051435863246513232 + 0.051438477007093489 + 0.051441090803645305 + 0.051443704636167265 + 0.051446318504657931 + 0.051448932409115793 + 0.051451546349539516 + 0.051454160325927652 + 0.051456774338278666 + 0.051459388386591275 + 0.051462002470863896 + 0.051464616591095178 + 0.051467230747283592 + 0.051469844939427849 + 0.051472459167526442 + 0.051475073431577853 + 0.05147768773158079 + 0.051480302067533776 + 0.05148291643943536 + 0.051485530847284064 + 0.051488145291078508 + 0.05149075977081724 + 0.051493374286498889 + 0.051495988838121905 + 0.051498603425684977 + 0.051501218049186663 + 0.051503832708625394 + 0.051506447403999914 + 0.051509062135308724 + 0.05151167690255045 + 0.051514291705723483 + 0.051516906544826623 + 0.05151952141985823 + 0.05152213633081703 + 0.051524751277701585 + 0.051527366260510458 + 0.051529981279242125 + 0.051532596333895307 + 0.051535211424468347 + 0.051537826550960106 + 0.051540441713368981 + 0.051543056911693648 + 0.051545672145932669 + 0.051548287416084526 + 0.051550902722147809 + 0.051553518064121166 + 0.051556133442003167 + 0.05155874885579232 + 0.051561364305487328 + 0.051563979791086637 + 0.051566595312588941 + 0.051569210869992707 + 0.051571826463296562 + 0.051574442092499055 + 0.051577057757598861 + 0.05157967345859453 + 0.051582289195484542 + 0.051584904968267641 + 0.051587520776942238 + 0.051590136621506966 + 0.051592752501960548 + 0.051595368418301382 + 0.051597984370528156 + 0.051600600358639385 + 0.051603216382633682 + 0.051605832442509679 + 0.051608448538265884 + 0.051611064669900952 + 0.051613680837413412 + 0.05161629704080186 + 0.05161891328006487 + 0.051621529555201134 + 0.051624145866209094 + 0.051626762213087457 + 0.051629378595834732 + 0.051631995014449497 + 0.051634611468930426 + 0.051637227959275979 + 0.051639844485484782 + 0.051642461047555564 + 0.051645077645486821 + 0.051647694279277061 + 0.051650310948925006 + 0.051652927654429096 + 0.051655544395788067 + 0.051658161173000476 + 0.051660777986064901 + 0.051663394834979871 + 0.05166601171974404 + 0.051668628640356054 + 0.051671245596814401 + 0.051673862589117846 + 0.051676479617264709 + 0.051679096681253783 + 0.051681713781083584 + 0.051684330916752813 + 0.051686948088259882 + 0.051689565295603639 + 0.051692182538782397 + 0.051694799817794956 + 0.051697417132639874 + 0.051700034483315657 + 0.051702651869820988 + 0.051705269292154452 + 0.051707886750314659 + 0.051710504244300189 + 0.051713121774109541 + 0.051715739339741579 + 0.051718356941194601 + 0.051720974578467457 + 0.051723592251558599 + 0.051726209960466583 + 0.051728827705190196 + 0.051731445485727862 + 0.051734063302078269 + 0.051736681154240065 + 0.051739299042211723 + 0.051741916965991924 + 0.05174453492557924 + 0.051747152920972352 + 0.051749770952169788 + 0.051752389019170147 + 0.051755007121972126 + 0.051757625260574244 + 0.051760243434975109 + 0.051762861645173387 + 0.051765479891167601 + 0.051768098172956425 + 0.051770716490538354 + 0.051773334843912222 + 0.051775953233076426 + 0.051778571658029647 + 0.051781190118770484 + 0.051783808615297536 + 0.051786427147609504 + 0.051789045715704869 + 0.051791664319582299 + 0.051794282959240399 + 0.051796901634677789 + 0.051799520345893087 + 0.051802139092884829 + 0.051804757875651739 + 0.051807376694192366 + 0.051809995548505378 + 0.051812614438589241 + 0.051815233364442721 + 0.051817852326064402 + 0.051820471323452862 + 0.051823090356606719 + 0.05182570942552462 + 0.051828328530205144 + 0.051830947670646943 + 0.051833566846848575 + 0.051836186058808721 + 0.051838805306525931 + 0.051841424589998929 + 0.051844043909226166 + 0.051846663264206436 + 0.051849282654938281 + 0.051851902081420272 + 0.051854521543651062 + 0.051857141041629272 + 0.051859760575353533 + 0.051862380144822556 + 0.051864999750034758 + 0.051867619390988849 + 0.051870239067683531 + 0.051872858780117333 + 0.051875478528288908 + 0.05187809831219687 + 0.051880718131839837 + 0.051883337987216477 + 0.051885957878325326 + 0.051888577805165113 + 0.051891197767734341 + 0.051893817766031781 + 0.051896437800055865 + 0.051899057869805462 + 0.051901677975278948 + 0.051904298116475095 + 0.051906918293392494 + 0.0519095385060298 + 0.051912158754385547 + 0.051914779038458474 + 0.05191739935824722 + 0.051920019713750307 + 0.051922640104966368 + 0.051925260531894141 + 0.051927880994532119 + 0.051930501492879068 + 0.051933122026933509 + 0.051935742596694118 + 0.051938363202159506 + 0.051940983843328362 + 0.051943604520199228 + 0.051946225232770829 + 0.051948845981041637 + 0.051951466765010515 + 0.051954087584675943 + 0.051956708440036505 + 0.051959329331091049 + 0.051961950257838015 + 0.051964571220276104 + 0.051967192218403888 + 0.051969813252220075 + 0.051972434321723271 + 0.051975055426912185 + 0.051977676567785354 + 0.051980297744341396 + 0.051982918956579076 + 0.051985540204496861 + 0.051988161488093564 + 0.05199078280736763 + 0.051993404162317874 + 0.051996025552942866 + 0.051998646979241274 + 0.052001268441211661 + 0.052003889938852722 + 0.052006511472163099 + 0.052009133041141381 + 0.052011754645786348 + 0.052014376286096432 + 0.052016997962070398 + 0.052019619673706892 + 0.052022241421004513 + 0.052024863203961928 + 0.05202748502257782 + 0.052030106876850751 + 0.052032728766779376 + 0.052035350692362363 + 0.052037972653598413 + 0.052040594650486084 + 0.052043216683024009 + 0.052045838751210868 + 0.052048460855045373 + 0.052051082994526106 + 0.052053705169651618 + 0.052056327380420778 + 0.052058949626832038 + 0.052061571908884122 + 0.052064194226575669 + 0.052066816579905341 + 0.052069438968871742 + 0.052072061393473534 + 0.052074683853709468 + 0.052077306349578065 + 0.052079928881078007 + 0.05208255144820792 + 0.052085174050966555 + 0.052087796689352442 + 0.052090419363364372 + 0.052093042073000827 + 0.052095664818260543 + 0.052098287599142173 + 0.052100910415644408 + 0.052103533267765817 + 0.052106156155505123 + 0.052108779078860988 + 0.052111402037831912 + 0.052114025032416786 + 0.052116648062614082 + 0.052119271128422594 + 0.052121894229840822 + 0.052124517366867601 + 0.052127140539501363 + 0.052129763747740941 + 0.052132386991585039 + 0.052135010271032074 + 0.052137633586080992 + 0.052140256936730182 + 0.05214288032297841 + 0.052145503744824413 + 0.052148127202266796 + 0.052150750695304143 + 0.052153374223935255 + 0.052155997788158708 + 0.052158621387973121 + 0.052161245023377253 + 0.052163868694369633 + 0.05216649240094913 + 0.052169116143114258 + 0.05217173992086363 + 0.052174363734196032 + 0.052176987583110006 + 0.0521796114676044 + 0.05218223538767771 + 0.052184859343328699 + 0.052187483334555869 + 0.052190107361358103 + 0.052192731423733908 + 0.052195355521682051 + 0.052197979655201177 + 0.05220060382428985 + 0.052203228028946821 + 0.052205852269170745 + 0.052208476544960344 + 0.052211100856314314 + 0.052213725203231143 + 0.052216349585709601 + 0.052218974003748329 + 0.052221598457346037 + 0.052224222946501447 + 0.052226847471213089 + 0.052229472031479762 + 0.052232096627300023 + 0.052234721258672644 + 0.052237345925596285 + 0.052239970628069482 + 0.052242595366091132 + 0.052245220139659737 + 0.052247844948773971 + 0.052250469793432626 + 0.052253094673634211 + 0.052255719589377567 + 0.05225834454066132 + 0.052260969527484082 + 0.052263594549844535 + 0.052266219607741436 + 0.052268844701173336 + 0.05227146983013907 + 0.052274094994637185 + 0.052276720194666428 + 0.052279345430225402 + 0.05228197070131279 + 0.05228459600792737 + 0.052287221350067713 + 0.052289846727732611 + 0.052292472140920636 + 0.052295097589630475 + 0.052297723073860873 + 0.052300348593610511 + 0.052302974148877919 + 0.052305599739662 + 0.052308225365961282 + 0.05231085102777451 + 0.052313476725100311 + 0.052316102457937497 + 0.052318728226284535 + 0.052321354030140307 + 0.052323979869503365 + 0.052326605744372416 + 0.052329231654746226 + 0.052331857600623442 + 0.052334483582002614 + 0.052337109598882672 + 0.05233973565126214 + 0.052342361739139739 + 0.052344987862514118 + 0.052347614021384055 + 0.052350240215748155 + 0.052352866445605085 + 0.052355492710953605 + 0.052358119011792381 + 0.052360745348120082 + 0.052363371719935471 + 0.052365998127237093 + 0.052368624570023739 + 0.052371251048294085 + 0.052373877562046832 + 0.052376504111280552 + 0.052379130695994119 + 0.052381757316186099 + 0.052384383971855242 + 0.05238701066300025 + 0.052389637389619791 + 0.052392264151712518 + 0.052394890949277143 + 0.052397517782312365 + 0.052400144650816931 + 0.052402771554789493 + 0.052405398494228685 + 0.052408025469133333 + 0.052410652479501947 + 0.052413279525333444 + 0.052415906606626331 + 0.052418533723379464 + 0.052421160875591392 + 0.052423788063260868 + 0.052426415286386641 + 0.052429042544967296 + 0.05243166983900166 + 0.052434297168488374 + 0.052436924533426077 + 0.052439551933813514 + 0.052442179369649435 + 0.052444806840932508 + 0.052447434347661449 + 0.05245006188983483 + 0.052452689467451498 + 0.052455317080510079 + 0.052457944729009373 + 0.052460572412947978 + 0.052463200132324611 + 0.052465827887138008 + 0.052468455677386838 + 0.052471083503069824 + 0.052473711364185667 + 0.052476339260733133 + 0.052478967192710786 + 0.052481595160117432 + 0.052484223162951704 + 0.052486851201212464 + 0.052489479274898262 + 0.052492107384007759 + 0.052494735528539858 + 0.052497363708493165 + 0.052499991923866292 + 0.052502620174658135 + 0.052505248460867245 + 0.052507876782492427 + 0.052510505139532322 + 0.052513133531985667 + 0.052515761959851151 + 0.052518390423127538 + 0.052521018921813489 + 0.052523647455907735 + 0.052526276025408963 + 0.052528904630315919 + 0.05253153327062729 + 0.052534161946341779 + 0.052536790657458109 + 0.052539419403975003 + 0.052542048185891234 + 0.05254467700320533 + 0.052547305855916229 + 0.05254993474402244 + 0.052552563667522832 + 0.0525551926264161 + 0.052557821620700794 + 0.052560450650375817 + 0.052563079715439845 + 0.052565708815891503 + 0.052568337951729688 + 0.052570967122952929 + 0.052573596329560046 + 0.052576225571549701 + 0.052578854848920588 + 0.05258148416167157 + 0.052584113509801279 + 0.05258674289330844 + 0.052589372312191622 + 0.05259200176644982 + 0.052594631256081499 + 0.052597260781085564 + 0.052599890341460578 + 0.052602519937205536 + 0.052605149568318792 + 0.052607779234799333 + 0.052610408936645765 + 0.052613038673856923 + 0.052615668446431292 + 0.052618298254367826 + 0.052620928097665179 + 0.052623557976322052 + 0.052626187890337184 + 0.052628817839709324 + 0.052631447824437176 + 0.052634077844519483 + 0.052636707899954831 + 0.052639337990742184 + 0.052641968116880128 + 0.052644598278367351 + 0.052647228475202687 + 0.052649858707384756 + 0.05265248897491244 + 0.052655119277784324 + 0.052657749615999151 + 0.052660379989555778 + 0.052663010398452753 + 0.052665640842688898 + 0.052668271322262934 + 0.052670901837173642 + 0.052673532387419647 + 0.0526761629729997 + 0.052678793593912664 + 0.052681424250157094 + 0.052684054941731881 + 0.052686685668635609 + 0.052689316430867113 + 0.052691947228425011 + 0.052694578061308235 + 0.052697208929515314 + 0.05269983983304511 + 0.052702470771896347 + 0.052705101746067691 + 0.052707732755557915 + 0.0527103638003657 + 0.052712994880489923 + 0.052715625995929181 + 0.052718257146682268 + 0.052720888332747996 + 0.052723519554124895 + 0.052726150810811903 + 0.052728782102807618 + 0.052731413430110917 + 0.052734044792720432 + 0.052736676190634976 + 0.052739307623853149 + 0.052741939092373888 + 0.052744570596195778 + 0.05274720213531759 + 0.052749833709738195 + 0.052752465319456134 + 0.052755096964470262 + 0.052757728644779386 + 0.05276036036038205 + 0.0527629921112771 + 0.052765623897463414 + 0.052768255718939443 + 0.052770887575704237 + 0.052773519467756373 + 0.052776151395094541 + 0.05277878335771765 + 0.052781415355624327 + 0.052784047388813385 + 0.052786679457283506 + 0.052789311561033454 + 0.052791943700061982 + 0.052794575874367901 + 0.052797208083949908 + 0.052799840328806691 + 0.052802472608937105 + 0.052805104924339714 + 0.052807737275013512 + 0.052810369660957077 + 0.052813002082169283 + 0.052815634538648723 + 0.052818267030394314 + 0.052820899557404634 + 0.0528235321196786 + 0.052826164717214817 + 0.052828797350012141 + 0.052831430018069316 + 0.052834062721385029 + 0.052836695459958095 + 0.052839328233787203 + 0.052841961042871151 + 0.052844593887208753 + 0.052847226766798573 + 0.052849859681639612 + 0.052852492631730481 + 0.052855125617069947 + 0.052857758637656689 + 0.052860391693489606 + 0.05286302478456744 + 0.052865657910888805 + 0.052868291072452667 + 0.052870924269257581 + 0.052873557501302411 + 0.052876190768585879 + 0.05287882407110682 + 0.052881457408863922 + 0.052884090781855998 + 0.052886724190081655 + 0.052889357633539816 + 0.052891991112229225 + 0.052894624626148495 + 0.05289725817529662 + 0.052899891759672107 + 0.052902525379273917 + 0.052905159034100764 + 0.052907792724151331 + 0.05291042644942448 + 0.052913060209918927 + 0.05291569400563343 + 0.052918327836566706 + 0.052920961702717685 + 0.052923595604084932 + 0.052926229540667287 + 0.052928863512463557 + 0.052931497519472459 + 0.052934131561692861 + 0.05293676563912339 + 0.052939399751762803 + 0.052942033899609935 + 0.052944668082663612 + 0.052947302300922469 + 0.052949936554385402 + 0.05295257084305114 + 0.052955205166918352 + 0.052957839525985942 + 0.052960473920252549 + 0.052963108349717056 + 0.052965742814378151 + 0.052968377314234733 + 0.052971011849285439 + 0.052973646419529036 + 0.052976281024964399 + 0.052978915665590168 + 0.052981550341405254 + 0.052984185052408386 + 0.052986819798598324 + 0.052989454579973762 + 0.05299208939653359 + 0.052994724248276504 + 0.052997359135201295 + 0.052999994057306765 + 0.053002629014591671 + 0.053005264007054818 + 0.053007899034694897 + 0.05301053409751081 + 0.053013169195501211 + 0.053015804328664991 + 0.053018439497000788 + 0.053021074700507501 + 0.0530237099391839 + 0.053026345213028618 + 0.053028980522040643 + 0.053031615866218615 + 0.053034251245561298 + 0.053036886660067617 + 0.053039522109736226 + 0.053042157594565917 + 0.053044793114555476 + 0.053047428669703703 + 0.053050064260009383 + 0.053052699885471281 + 0.053055335546088191 + 0.053057971241858876 + 0.053060606972782191 + 0.053063242738856813 + 0.053065878540081525 + 0.053068514376455204 + 0.053071150247976574 + 0.053073786154644434 + 0.05307642209645759 + 0.053079058073414738 + 0.053081694085514781 + 0.053084330132756388 + 0.053086966215138462 + 0.053089602332659774 + 0.053092238485319035 + 0.053094874673115043 + 0.053097510896046633 + 0.053100147154112522 + 0.053102783447311612 + 0.053105419775642614 + 0.053108056139104333 + 0.053110692537695542 + 0.053113328971415033 + 0.053115965440261537 + 0.053118601944234005 + 0.053121238483331119 + 0.053123875057551687 + 0.053126511666894423 + 0.053129148311358239 + 0.053131784990941962 + 0.053134421705644266 + 0.053137058455463931 + 0.053139695240399826 + 0.053142332060450714 + 0.053144968915615397 + 0.053147605805892652 + 0.053150242731281341 + 0.053152879691780147 + 0.053155516687387924 + 0.0531581537181035 + 0.053160790783925563 + 0.053163427884853065 + 0.053166065020884647 + 0.053168702192019253 + 0.053171339398255545 + 0.053173976639592391 + 0.053176613916028577 + 0.053179251227563007 + 0.053181888574194203 + 0.053184525955921269 + 0.053187163372742832 + 0.053189800824657719 + 0.053192438311664772 + 0.053195075833762685 + 0.053197713390950363 + 0.053200350983226632 + 0.053202988610590203 + 0.053205626273039909 + 0.053208263970574585 + 0.053210901703193036 + 0.053213539470893939 + 0.053216177273676224 + 0.053218815111538739 + 0.053221452984480083 + 0.053224090892499243 + 0.053226728835595011 + 0.053229366813766145 + 0.053232004827011445 + 0.053234642875329759 + 0.053237280958719865 + 0.053239919077180474 + 0.053242557230710537 + 0.053245195419308826 + 0.053247833642974127 + 0.053250471901705197 + 0.053253110195500934 + 0.053255748524360103 + 0.05325838688828162 + 0.053261025287264091 + 0.053263663721306448 + 0.053266302190407441 + 0.053268940694565954 + 0.053271579233780807 + 0.053274217808050722 + 0.053276856417374563 + 0.053279495061751177 + 0.053282133741179259 + 0.053284772455657763 + 0.053287411205185452 + 0.053290049989761022 + 0.053292688809383426 + 0.053295327664051435 + 0.053297966553763898 + 0.053300605478519579 + 0.053303244438317354 + 0.053305883433155905 + 0.053308522463034178 + 0.053311161527951026 + 0.053313800627905049 + 0.053316439762895261 + 0.053319078932920448 + 0.053321718137979347 + 0.053324357378070869 + 0.053326996653193771 + 0.053329635963346875 + 0.053332275308529034 + 0.053334914688739056 + 0.053337554103975726 + 0.053340193554237907 + 0.053342833039524376 + 0.053345472559833948 + 0.053348112115165547 + 0.053350751705517931 + 0.053353391330889843 + 0.053356030991280223 + 0.053358670686687822 + 0.053361310417111479 + 0.053363950182550003 + 0.053366589983002255 + 0.053369229818467048 + 0.053371869688943155 + 0.053374509594429492 + 0.053377149534924853 + 0.053379789510427919 + 0.053382429520937698 + 0.053385069566452989 + 0.053387709646972578 + 0.053390349762495272 + 0.053392989913019946 + 0.0533956300985454 + 0.053398270319070511 + 0.053400910574593986 + 0.053403550865114793 + 0.053406191190631586 + 0.053408831551143426 + 0.05341147194664897 + 0.053414112377147077 + 0.053416752842636583 + 0.053419393343116378 + 0.053422033878585226 + 0.053424674449041989 + 0.053427315054485496 + 0.053429955694914516 + 0.053432596370327982 + 0.053435237080724597 + 0.053437877826103382 + 0.05344051860646308 + 0.053443159421802458 + 0.053445800272120349 + 0.053448441157415601 + 0.053451082077687243 + 0.05345372303293381 + 0.053456364023154346 + 0.053459005048347587 + 0.053461646108512409 + 0.053464287203647626 + 0.053466928333752099 + 0.05346956949882465 + 0.053472210698864119 + 0.053474851933869312 + 0.053477493203839176 + 0.053480134508772426 + 0.053482775848667903 + 0.05348541722352456 + 0.053488058633341114 + 0.053490700078116432 + 0.05349334155784944 + 0.053495983072538889 + 0.053498624622183633 + 0.053501266206782506 + 0.053503907826334345 + 0.053506549480838099 + 0.053509191170292514 + 0.053511832894696382 + 0.053514474654048662 + 0.053517116448348098 + 0.053519758277593595 + 0.053522400141783964 + 0.053525042040918042 + 0.053527683974994772 + 0.053530325944012865 + 0.053532967947971265 + 0.053535609986868737 + 0.053538252060704179 + 0.053540894169476418 + 0.053543536313184287 + 0.053546178491826711 + 0.053548820705402393 + 0.053551462953910361 + 0.053554105237349249 + 0.053556747555718126 + 0.053559389909015653 + 0.053562032297240839 + 0.053564674720392481 + 0.053567317178469312 + 0.053569959671470345 + 0.053572602199394345 + 0.053575244762240154 + 0.05357788736000664 + 0.053580529992692708 + 0.053583172660297107 + 0.053585815362818805 + 0.053588458100256572 + 0.053591100872609231 + 0.053593743679875724 + 0.053596386522054881 + 0.053599029399145529 + 0.053601672311146507 + 0.053604315258056721 + 0.053606958239875102 + 0.053609601256600317 + 0.053612244308231319 + 0.053614887394766893 + 0.053617530516206019 + 0.053620173672547476 + 0.053622816863790133 + 0.053625460089932922 + 0.05362810335097451 + 0.053630746646913946 + 0.053633389977749982 + 0.053636033343481569 + 0.053638676744107508 + 0.053641320179626556 + 0.053643963650037818 + 0.053646607155339879 + 0.053649250695531843 + 0.053651894270612406 + 0.053654537880580472 + 0.05365718152543493 + 0.05365982520517467 + 0.05366246891979843 + 0.05366511266930523 + 0.053667756453693739 + 0.053670400272962993 + 0.053673044127111887 + 0.053675688016139082 + 0.053678331940043615 + 0.053680975898824222 + 0.053683619892479904 + 0.053686263921009392 + 0.053688907984411699 + 0.053691552082685584 + 0.053694196215829888 + 0.053696840383843591 + 0.053699484586725493 + 0.053702128824474463 + 0.053704773097089417 + 0.053707417404569094 + 0.053710061746912494 + 0.053712706124118402 + 0.053715350536185764 + 0.053717994983113318 + 0.053720639464900209 + 0.053723283981544988 + 0.053725928533046738 + 0.053728573119404162 + 0.053731217740616274 + 0.053733862396681868 + 0.053736507087599888 + 0.053739151813369045 + 0.053741796573988469 + 0.05374444136945683 + 0.053747086199773059 + 0.05374973106493601 + 0.053752375964944622 + 0.05375502089979773 + 0.053757665869494188 + 0.053760310874032845 + 0.053762955913412666 + 0.053765600987632473 + 0.053768246096691147 + 0.05377089124058753 + 0.05377353641932054 + 0.053776181632889067 + 0.053778826881292041 + 0.053781472164528166 + 0.053784117482596497 + 0.05378676283549573 + 0.053789408223224998 + 0.053792053645782927 + 0.053794699103168524 + 0.053797344595380617 + 0.053799990122418241 + 0.05380263568428003 + 0.053805281280964991 + 0.053807926912472014 + 0.053810572578800009 + 0.053813218279947783 + 0.053815864015914275 + 0.053818509786698283 + 0.053821155592298879 + 0.05382380143271475 + 0.053826447307944884 + 0.053829093217988039 + 0.053831739162843215 + 0.053834385142509329 + 0.05383703115698512 + 0.053839677206269629 + 0.053842323290361635 + 0.053844969409260091 + 0.053847615562963906 + 0.053850261751471833 + 0.053852907974782878 + 0.05385555423289589 + 0.053858200525809828 + 0.053860846853523367 + 0.053863493216035625 + 0.053866139613345396 + 0.053868786045451554 + 0.05387143251235306 + 0.053874079014048733 + 0.053876725550537519 + 0.053879372121818259 + 0.053882018727889891 + 0.053884665368751181 + 0.053887312044401149 + 0.053889958754838721 + 0.053892605500062661 + 0.053895252280071956 + 0.053897899094865434 + 0.053900545944442095 + 0.053903192828800697 + 0.053905839747940228 + 0.053908486701859465 + 0.0539111336905575 + 0.053913780714033091 + 0.053916427772285079 + 0.0539190748653125 + 0.053921721993114208 + 0.053924369155689079 + 0.053927016353035949 + 0.053929663585153789 + 0.053932310852041525 + 0.053934958153697976 + 0.053937605490122165 + 0.053940252861312807 + 0.053942900267268938 + 0.053945547707989427 + 0.053948195183473095 + 0.053950842693719039 + 0.053953490238725935 + 0.053956137818492768 + 0.053958785433018505 + 0.053961433082301967 + 0.053964080766342022 + 0.053966728485137755 + 0.053969376238687847 + 0.05397202402699134 + 0.05397467185004709 + 0.05397731970785398 + 0.053979967600410982 + 0.053982615527716923 + 0.053985263489770778 + 0.053987911486571311 + 0.053990559518117633 + 0.05399320758440853 + 0.053995855685442927 + 0.053998503821219679 + 0.0540011519917378 + 0.05400380019699616 + 0.054006448436993537 + 0.054009096711729057 + 0.05401174502120145 + 0.054014393365409669 + 0.054017041744352713 + 0.054019690158029376 + 0.054022338606438645 + 0.054024987089579361 + 0.054027635607450407 + 0.054030284160050922 + 0.05403293274737956 + 0.054035581369435301 + 0.054038230026217125 + 0.05404087871772395 + 0.054043527443954506 + 0.054046176204907911 + 0.054048825000582987 + 0.054051473830978629 + 0.054054122696093804 + 0.054056771595927422 + 0.054059420530478346 + 0.054062069499745555 + 0.054064718503727953 + 0.054067367542424409 + 0.054070016615833813 + 0.054072665723955152 + 0.05407531486678735 + 0.054077964044329276 + 0.054080613256579847 + 0.054083262503538031 + 0.05408591178520275 + 0.054088561101572813 + 0.054091210452647233 + 0.054093859838424921 + 0.054096509258904697 + 0.054099158714085611 + 0.054101808203966539 + 0.054104457728546468 + 0.054107107287824148 + 0.054109756881798671 + 0.054112406510468884 + 0.054115056173833637 + 0.054117705871891922 + 0.054120355604642727 + 0.054123005372084899 + 0.054125655174217309 + 0.054128305011039005 + 0.054130954882548883 + 0.054133604788745793 + 0.054136254729628665 + 0.054138904705196389 + 0.054141554715448098 + 0.054144204760382515 + 0.054146854839998614 + 0.054149504954295373 + 0.054152155103271628 + 0.054154805286926379 + 0.05415745550525853 + 0.054160105758267005 + 0.054162756045950736 + 0.054165406368308661 + 0.054168056725339642 + 0.054170707117042659 + 0.054173357543416706 + 0.054176008004460582 + 0.0541786585001734 + 0.054181309030553827 + 0.054183959595601038 + 0.054186610195313796 + 0.054189260829691124 + 0.054191911498731919 + 0.054194562202435091 + 0.054197212940799711 + 0.054199863713824528 + 0.054202514521508489 + 0.054205165363850734 + 0.054207816240849971 + 0.054210467152505187 + 0.05421311809881546 + 0.054215769079779499 + 0.054218420095396354 + 0.054221071145664913 + 0.054223722230584248 + 0.054226373350153088 + 0.054229024504370615 + 0.054231675693235504 + 0.054234326916746886 + 0.054236978174903576 + 0.054239629467704588 + 0.054242280795148888 + 0.054244932157235297 + 0.054247583553962829 + 0.054250234985330381 + 0.05425288645133694 + 0.0542555379519815 + 0.054258189487262853 + 0.054260841057180022 + 0.054263492661732006 + 0.054266144300917571 + 0.054268795974735794 + 0.054271447683185627 + 0.054274099426265911 + 0.054276751203975696 + 0.054279403016313933 + 0.054282054863279493 + 0.054284706744871306 + 0.05428735866108831 + 0.054290010611929541 + 0.054292662597393862 + 0.05429531461748021 + 0.054297966672187586 + 0.054300618761514929 + 0.054303270885461219 + 0.054305923044025282 + 0.054308575237206162 + 0.054311227465002762 + 0.054313879727413999 + 0.054316532024438972 + 0.054319184356076425 + 0.054321836722325469 + 0.054324489123184987 + 0.054327141558653917 + 0.054329794028731164 + 0.05433244653341579 + 0.054335099072706658 + 0.054337751646602768 + 0.054340404255103045 + 0.054343056898206357 + 0.054345709575911845 + 0.054348362288218356 + 0.054351015035124815 + 0.054353667816630175 + 0.054356320632733511 + 0.054358973483433583 + 0.054361626368729446 + 0.054364279288620115 + 0.054366932243104453 + 0.054369585232181376 + 0.054372238255849983 + 0.054374891314109088 + 0.054377544406957717 + 0.054380197534394874 + 0.05438285069641937 + 0.054385503893030269 + 0.054388157124226476 + 0.054390810390007038 + 0.054393463690370826 + 0.054396117025316798 + 0.05439877039484399 + 0.054401423798951236 + 0.054404077237637627 + 0.05440673071090206 + 0.054409384218743445 + 0.054412037761160874 + 0.054414691338153055 + 0.054417344949719261 + 0.054419998595858311 + 0.054422652276569131 + 0.054425305991850671 + 0.054427959741701948 + 0.054430613526121933 + 0.054433267345109601 + 0.054435921198663889 + 0.054438575086783708 + 0.054441229009468059 + 0.054443882966715866 + 0.054446536958526227 + 0.054449190984897991 + 0.054451845045830165 + 0.054454499141321701 + 0.05445715327137151 + 0.054459807435978634 + 0.054462461635142033 + 0.054465115868860672 + 0.054467770137133449 + 0.054470424439959413 + 0.054473078777337501 + 0.054475733149266813 + 0.054478387555745959 + 0.054481041996774227 + 0.054483696472350539 + 0.054486350982473779 + 0.054489005527142968 + 0.054491660106357039 + 0.054494314720115039 + 0.05449696936841586 + 0.054499624051258501 + 0.054502278768641936 + 0.05450493352056511 + 0.054507588307027004 + 0.054510243128026686 + 0.054512897983562986 + 0.054515552873634951 + 0.054518207798241465 + 0.054520862757381675 + 0.05452351775105449 + 0.054526172779258766 + 0.054528827841993581 + 0.054531482939257886 + 0.054534138071050627 + 0.054536793237370866 + 0.054539448438217578 + 0.054542103673589658 + 0.054544758943486045 + 0.054547414247905844 + 0.054550069586847966 + 0.054552724960311404 + 0.05455538036829511 + 0.054558035810798086 + 0.054560691287819305 + 0.054563346799357745 + 0.054566002345412347 + 0.054568657925982186 + 0.054571313541066181 + 0.054573969190663332 + 0.054576624874772557 + 0.054579280593392905 + 0.054581936346523349 + 0.054584592134162876 + 0.05458724795631046 + 0.054589903812965031 + 0.054592559704125659 + 0.054595215629791298 + 0.054597871589960871 + 0.054600527584633352 + 0.054603183613807907 + 0.05460583967748335 + 0.054608495775658662 + 0.054611151908332912 + 0.05461380807550504 + 0.054616464277174016 + 0.054619120513338927 + 0.054621776783998689 + 0.0546244330891522 + 0.054627089428798618 + 0.054629745802936808 + 0.054632402211565824 + 0.054635058654684529 + 0.054637715132292049 + 0.054640371644387425 + 0.054643028190969473 + 0.05464568477203726 + 0.054648341387589859 + 0.054650998037626061 + 0.054653654722145069 + 0.054656311441145751 + 0.054658968194627143 + 0.054661624982588135 + 0.054664281805027845 + 0.054666938661945337 + 0.05466959555333941 + 0.054672252479209073 + 0.054674909439553471 + 0.054677566434371459 + 0.054680223463662164 + 0.054682880527424454 + 0.054685537625657366 + 0.05468819475835987 + 0.05469085192553106 + 0.054693509127169866 + 0.054696166363275206 + 0.054698823633846184 + 0.054701480938881754 + 0.054704138278380929 + 0.054706795652342752 + 0.054709453060766175 + 0.054712110503650137 + 0.054714767980993638 + 0.054717425492795846 + 0.054720083039055553 + 0.054722740619771879 + 0.054725398234943802 + 0.054728055884570352 + 0.05473071356865037 + 0.054733371287183058 + 0.054736029040167326 + 0.054738686827602176 + 0.054741344649486684 + 0.054744002505819685 + 0.05474666039660029 + 0.054749318321827577 + 0.054751976281500428 + 0.054754634275617935 + 0.054757292304178924 + 0.054759950367182703 + 0.054762608464627986 + 0.054765266596513915 + 0.054767924762839516 + 0.054770582963603716 + 0.054773241198805514 + 0.054775899468444016 + 0.054778557772518152 + 0.054781216111026987 + 0.05478387448396943 + 0.054786532891344573 + 0.054789191333151424 + 0.05479184980938899 + 0.054794508320056237 + 0.054797166865152111 + 0.054799825444675807 + 0.054802484058626234 + 0.054805142707002402 + 0.054807801389803221 + 0.054810460107027899 + 0.054813118858675312 + 0.054815777644744469 + 0.054818436465234439 + 0.054821095320144286 + 0.054823754209472872 + 0.05482641313321935 + 0.054829072091382672 + 0.05483173108396177 + 0.054834390110955776 + 0.054837049172363699 + 0.054839708268184489 + 0.054842367398417198 + 0.054845026563060839 + 0.054847685762114476 + 0.054850344995576984 + 0.054853004263447552 + 0.054855663565725063 + 0.054858322902408552 + 0.054860982273497096 + 0.054863641678989758 + 0.054866301118885429 + 0.054868960593183122 + 0.054871620101881978 + 0.054874279644980942 + 0.054876939222479056 + 0.0548795988343753 + 0.054882258480668709 + 0.054884918161358341 + 0.054887577876443203 + 0.054890237625922211 + 0.054892897409794604 + 0.054895557228059173 + 0.054898217080715024 + 0.054900876967761296 + 0.054903536889196906 + 0.054906196845020801 + 0.054908856835232181 + 0.054911516859829916 + 0.054914176918813139 + 0.054916837012180718 + 0.054919497139931862 + 0.054922157302065552 + 0.054924817498580712 + 0.054927477729476488 + 0.05493013799475182 + 0.054932798294405789 + 0.054935458628437399 + 0.054938118996845663 + 0.054940779399629651 + 0.054943439836788281 + 0.054946100308320735 + 0.054948760814225943 + 0.054951421354503004 + 0.054954081929150821 + 0.054956742538168575 + 0.054959403181555191 + 0.05496206385930974 + 0.054964724571431207 + 0.054967385317918754 + 0.054970046098771264 + 0.054972706913987743 + 0.054975367763567415 + 0.054978028647509176 + 0.054980689565812042 + 0.054983350518475103 + 0.054986011505497381 + 0.054988672526877898 + 0.054991333582615681 + 0.054993994672709851 + 0.054996655797159233 + 0.054999316955963086 + 0.055001978149120313 + 0.055004639376629999 + 0.055007300638491206 + 0.055009961934702874 + 0.055012623265264182 + 0.055015284630174008 + 0.055017946029431504 + 0.055020607463035651 + 0.055023268930985539 + 0.055025930433280162 + 0.055028591969918467 + 0.055031253540899716 + 0.055033915146222814 + 0.055036576785886686 + 0.055039238459890616 + 0.055041900168233508 + 0.055044561910914419 + 0.055047223687932405 + 0.055049885499286431 + 0.055052547344975673 + 0.055055209224999006 + 0.055057871139355632 + 0.055060533088044504 + 0.055063195071064726 + 0.055065857088415306 + 0.05506851914009523 + 0.055071181226103702 + 0.055073843346439506 + 0.055076505501101963 + 0.055079167690089907 + 0.055081829913402491 + 0.0550844921710388 + 0.055087154462997751 + 0.05508981678927849 + 0.055092479149880073 + 0.05509514154480142 + 0.055097803974041674 + 0.055100466437599895 + 0.055103128935475178 + 0.055105791467666428 + 0.055108454034172812 + 0.055111116634993282 + 0.055113779270126936 + 0.055116441939572852 + 0.055119104643330065 + 0.055121767381397596 + 0.055124430153774509 + 0.05512709296045986 + 0.055129755801452712 + 0.055132418676752129 + 0.055135081586357097 + 0.055137744530266694 + 0.05514040750848001 + 0.055143070520996117 + 0.055145733567813965 + 0.055148396648932736 + 0.055151059764351321 + 0.055153722914068989 + 0.055156386098084577 + 0.05515904931639725 + 0.055161712569006018 + 0.055164375855910087 + 0.05516703917710828 + 0.055169702532599854 + 0.055172365922383698 + 0.055175029346459036 + 0.055177692804824791 + 0.055180356297480117 + 0.055183019824423953 + 0.055185683385655437 + 0.055188346981173683 + 0.055191010610977642 + 0.055193674275066447 + 0.055196337973439119 + 0.055199001706094701 + 0.055201665473032242 + 0.055204329274250917 + 0.055206993109749719 + 0.055209656979527622 + 0.055212320883583813 + 0.055214984821917272 + 0.05521764879452716 + 0.055220312801412416 + 0.0552229768425722 + 0.055225640918005532 + 0.055228305027711436 + 0.055230969171689029 + 0.055233633349937472 + 0.055236297562455579 + 0.055238961809242614 + 0.055241626090297598 + 0.055244290405619588 + 0.055246954755207585 + 0.055249619139060811 + 0.055252283557178199 + 0.055254948009558866 + 0.055257612496201876 + 0.055260277017106264 + 0.055262941572271164 + 0.055265606161695562 + 0.055268270785378562 + 0.055270935443319298 + 0.055273600135516771 + 0.055276264861969973 + 0.05527892962267815 + 0.055281594417640259 + 0.055284259246855413 + 0.055286924110322641 + 0.055289589008041019 + 0.05529225394000975 + 0.055294918906227709 + 0.055297583906693995 + 0.055300248941407816 + 0.055302914010368187 + 0.055305579113574144 + 0.055308244251024694 + 0.055310909422719122 + 0.055313574628656326 + 0.05531623986883543 + 0.055318905143255534 + 0.055321570451915665 + 0.055324235794814887 + 0.055326901171952422 + 0.055329566583327154 + 0.055332232028938194 + 0.055334897508784689 + 0.055337563022865799 + 0.0553402285711804 + 0.055342894153727749 + 0.055345559770506689 + 0.055348225421516614 + 0.055350891106756374 + 0.055353556826225093 + 0.055356222579921899 + 0.055358888367845797 + 0.055361554189996033 + 0.055364220046371475 + 0.055366885936971297 + 0.055369551861794652 + 0.055372217820840501 + 0.055374883814107892 + 0.05537754984159618 + 0.055380215903304129 + 0.055382881999230922 + 0.055385548129375746 + 0.055388214293737636 + 0.055390880492315622 + 0.055393546725108836 + 0.055396212992116306 + 0.055398879293337137 + 0.055401545628770463 + 0.055404211998415387 + 0.055406878402270869 + 0.055409544840336153 + 0.05541221131261017 + 0.055414877819092163 + 0.0554175443597811 + 0.055420210934676056 + 0.0554228775437762 + 0.055425544187080643 + 0.055428210864588427 + 0.055430877576298554 + 0.055433544322210274 + 0.055436211102322518 + 0.055438877916634544 + 0.055441544765145262 + 0.055444211647853903 + 0.055446878564759529 + 0.055449545515861183 + 0.055452212501158039 + 0.055454879520649085 + 0.055457546574333466 + 0.055460213662210336 + 0.055462880784278572 + 0.055465547940537603 + 0.055468215130986265 + 0.055470882355623689 + 0.055473549614449023 + 0.055476216907461323 + 0.055478884234659777 + 0.055481551596043441 + 0.055484218991611267 + 0.055486886421362479 + 0.055489553885296201 + 0.055492221383411533 + 0.055494888915707453 + 0.055497556482183172 + 0.055500224082837765 + 0.055502891717670262 + 0.055505559386679802 + 0.055508227089865442 + 0.055510894827226445 + 0.055513562598761779 + 0.055516230404470533 + 0.055518898244351841 + 0.055521566118404773 + 0.055524234026628497 + 0.055526901969022081 + 0.055529569945584618 + 0.055532237956315178 + 0.055534906001212865 + 0.055537574080276826 + 0.055540242193506222 + 0.055542910340899955 + 0.055545578522457305 + 0.055548246738177341 + 0.055550914988059107 + 0.055553583272101872 + 0.055556251590304515 + 0.055558919942666242 + 0.055561588329186201 + 0.055564256749863504 + 0.055566925204697186 + 0.055569593693686366 + 0.055572262216830155 + 0.055574930774127701 + 0.055577599365578018 + 0.055580267991180314 + 0.055582936650933654 + 0.055585605344837169 + 0.055588274072889923 + 0.055590942835091056 + 0.055593611631439666 + 0.055596280461934891 + 0.055598949326575796 + 0.055601618225361492 + 0.055604287158291146 + 0.055606956125363802 + 0.055609625126578688 + 0.055612294161934757 + 0.055614963231431266 + 0.055617632335067183 + 0.055620301472841721 + 0.055622970644753911 + 0.055625639850803051 + 0.055628309090988023 + 0.055630978365308108 + 0.055633647673762249 + 0.055636317016349787 + 0.055638986393069682 + 0.055641655803921067 + 0.055644325248903032 + 0.055646994728014862 + 0.055649664241255434 + 0.055652333788624032 + 0.055655003370119721 + 0.055657672985741598 + 0.055660342635488767 + 0.055663012319360404 + 0.055665682037355606 + 0.055668351789473512 + 0.0556710215757132 + 0.055673691396073768 + 0.055676361250554397 + 0.055679031139154227 + 0.055681701061872264 + 0.055684371018707712 + 0.055687041009659759 + 0.055689711034727307 + 0.05569238109390974 + 0.055695051187206003 + 0.05569772131461527 + 0.055700391476136653 + 0.055703061671769312 + 0.05570573190151238 + 0.055708402165364913 + 0.055711072463326024 + 0.055713742795394941 + 0.055716413161570701 + 0.055719083561852463 + 0.055721753996239375 + 0.055724424464730499 + 0.055727094967324975 + 0.055729765504022005 + 0.055732436074820667 + 0.055735106679719953 + 0.055737777318719262 + 0.055740447991817502 + 0.055743118699013945 + 0.055745789440307607 + 0.055748460215697654 + 0.055751131025183212 + 0.055753801868763435 + 0.055756472746437497 + 0.055759143658204377 + 0.05576181460406332 + 0.055764485584013451 + 0.055767156598053862 + 0.055769827646183691 + 0.055772498728402176 + 0.055775169844708233 + 0.055777840995101219 + 0.055780512179580112 + 0.055783183398144129 + 0.055785854650792305 + 0.055788525937523939 + 0.055791197258337998 + 0.055793868613233696 + 0.055796540002210203 + 0.055799211425266552 + 0.055801882882401961 + 0.055804554373615492 + 0.055807225898906361 + 0.05580989745827368 + 0.055812569051716547 + 0.055815240679234185 + 0.055817912340825636 + 0.055820584036490033 + 0.05582325576622657 + 0.055825927530034458 + 0.055828599327912738 + 0.055831271159860495 + 0.055833943025876881 + 0.055836614925961169 + 0.055839286860112386 + 0.055841958828329818 + 0.055844630830612335 + 0.055847302866959304 + 0.055849974937369769 + 0.055852647041842923 + 0.055855319180377852 + 0.055857991352973743 + 0.055860663559629757 + 0.055863335800344943 + 0.055866008075118559 + 0.055868680383949633 + 0.055871352726837457 + 0.055874025103781026 + 0.055876697514779597 + 0.055879369959832295 + 0.055882042438938115 + 0.055884714952096362 + 0.055887387499306218 + 0.055890060080566656 + 0.055892732695876975 + 0.055895405345236265 + 0.055898078028643626 + 0.0559007507460983 + 0.055903423497599351 + 0.055906096283145974 + 0.055908769102737378 + 0.055911441956372591 + 0.05591411484405083 + 0.055916787765771178 + 0.055919460721532893 + 0.055922133711335073 + 0.055924806735176857 + 0.055927479793057316 + 0.055930152884975694 + 0.055932826010931233 + 0.055935499170922935 + 0.055938172364949953 + 0.055940845593011664 + 0.055943518855106837 + 0.055946192151234954 + 0.055948865481394966 + 0.05595153884558618 + 0.055954212243807679 + 0.05595688567605861 + 0.055959559142338119 + 0.055962232642645361 + 0.055964906176979516 + 0.0559675797453398 + 0.055970253347725242 + 0.055972926984134974 + 0.055975600654568365 + 0.055978274359024395 + 0.055980948097502224 + 0.055983621870001138 + 0.055986295676520186 + 0.0559889695170585 + 0.055991643391615296 + 0.055994317300189771 + 0.055996991242781048 + 0.055999665219388255 + 0.056002339230010585 + 0.056005013274647193 + 0.056007687353297177 + 0.056010361465959835 + 0.056013035612634231 + 0.056015709793319518 + 0.056018384008014906 + 0.056021058256719554 + 0.056023732539432589 + 0.056026406856153121 + 0.056029081206880514 + 0.056031755591613691 + 0.056034430010352042 + 0.056037104463094518 + 0.056039778949840427 + 0.056042453470588803 + 0.05604512802533896 + 0.056047802614090071 + 0.056050477236841159 + 0.056053151893591474 + 0.056055826584340163 + 0.056058501309086455 + 0.056061176067829399 + 0.056063850860568303 + 0.05606652568730211 + 0.056069200548030232 + 0.056071875442751745 + 0.056074550371465866 + 0.056077225334171636 + 0.056079900330868307 + 0.056082575361555052 + 0.056085250426231095 + 0.056087925524895478 + 0.056090600657547493 + 0.056093275824186252 + 0.056095951024810867 + 0.05609862625942056 + 0.056101301528014527 + 0.056103976830592046 + 0.056106652167152028 + 0.056109327537693918 + 0.056112002942216715 + 0.056114678380719658 + 0.056117353853201796 + 0.056120029359662524 + 0.056122704900100892 + 0.056125380474516033 + 0.056128056082907204 + 0.056130731725273601 + 0.056133407401614287 + 0.056136083111928588 + 0.056138758856215491 + 0.056141434634474373 + 0.056144110446704254 + 0.056146786292904406 + 0.056149462173073997 + 0.056152138087212145 + 0.056154814035318135 + 0.056157490017390947 + 0.056160166033430041 + 0.056162842083434396 + 0.056165518167403228 + 0.056168194285335732 + 0.056170870437231089 + 0.056173546623088495 + 0.056176222842907096 + 0.056178899096686094 + 0.056181575384424733 + 0.056184251706122117 + 0.056186928061777455 + 0.056189604451389853 + 0.056192280874958596 + 0.056194957332482816 + 0.056197633823961743 + 0.056200310349394537 + 0.056202986908780415 + 0.056205663502118502 + 0.056208340129407931 + 0.056211016790648057 + 0.056213693485837997 + 0.056216370214976823 + 0.056219046978063902 + 0.056221723775098306 + 0.056224400606079188 + 0.056227077471005804 + 0.056229754369877372 + 0.056232431302693016 + 0.056235108269451946 + 0.056237785270153398 + 0.056240462304796519 + 0.056243139373380435 + 0.056245816475904473 + 0.056248493612367716 + 0.056251170782769401 + 0.05625384798710871 + 0.056256525225384733 + 0.056259202497596916 + 0.056261879803744169 + 0.056264557143825861 + 0.056267234517841054 + 0.056269911925789118 + 0.056272589367669067 + 0.056275266843480221 + 0.056277944353221768 + 0.056280621896892806 + 0.056283299474492669 + 0.056285977086020331 + 0.056288654731475186 + 0.056291332410856376 + 0.056294010124163033 + 0.056296687871394496 + 0.056299365652549872 + 0.056302043467628293 + 0.056304721316629003 + 0.056307399199551279 + 0.056310077116394193 + 0.05631275506715705 + 0.056315433051839024 + 0.056318111070439263 + 0.056320789122957043 + 0.056323467209391506 + 0.056326145329741825 + 0.056328823484007293 + 0.056331501672186979 + 0.056334179894280197 + 0.056336858150286169 + 0.056339536440204008 + 0.056342214764032957 + 0.056344893121772169 + 0.056347571513420923 + 0.056350249938978345 + 0.056352928398443726 + 0.0563556068918162 + 0.056358285419094968 + 0.056360963980279316 + 0.056363642575368356 + 0.056366321204361323 + 0.056368999867257394 + 0.056371678564055838 + 0.056374357294755907 + 0.056377036059356588 + 0.05637971485785731 + 0.056382393690257174 + 0.056385072556555428 + 0.056387751456751206 + 0.056390430390843842 + 0.056393109358832384 + 0.056395788360716237 + 0.05639846739649447 + 0.056401146466166237 + 0.056403825569730948 + 0.056406504707187624 + 0.056409183878535642 + 0.056411863083774029 + 0.056414542322902085 + 0.056417221595919019 + 0.056419900902824095 + 0.056422580243616495 + 0.056425259618295372 + 0.056427939026859941 + 0.056430618469309433 + 0.056433297945643134 + 0.056435977455860174 + 0.056438656999959806 + 0.056441336577941259 + 0.056444016189803714 + 0.056446695835546339 + 0.05644937551516839 + 0.056452055228669112 + 0.056454734976047742 + 0.056457414757303426 + 0.056460094572435351 + 0.056462774421442895 + 0.05646545430432507 + 0.056468134221081226 + 0.056470814171710612 + 0.056473494156212348 + 0.056476174174585614 + 0.056478854226829765 + 0.056481534312943955 + 0.056484214432927331 + 0.056486894586779246 + 0.056489574774498862 + 0.056492254996085359 + 0.056494935251538002 + 0.056497615540856007 + 0.056500295864038604 + 0.056502976221084973 + 0.05650565661199438 + 0.05650833703676602 + 0.056511017495399087 + 0.056513697987892901 + 0.056516378514246624 + 0.056519059074459456 + 0.056521739668530697 + 0.056524420296459398 + 0.056527100958245001 + 0.056529781653886529 + 0.056532462383383393 + 0.056535143146734711 + 0.056537823943939795 + 0.056540504774997773 + 0.056543185639907914 + 0.056545866538669387 + 0.05654854747128147 + 0.056551228437743455 + 0.056553909438054446 + 0.056556590472213723 + 0.056559271540220592 + 0.056561952642074156 + 0.056564633777773689 + 0.056567314947318426 + 0.05656999615070759 + 0.056572677387940445 + 0.056575358659016209 + 0.056578039963934054 + 0.056580721302693295 + 0.056583402675293069 + 0.056586084081732768 + 0.056588765522011468 + 0.056591446996128343 + 0.056594128504082852 + 0.056596810045874066 + 0.056599491621501241 + 0.056602173230963698 + 0.056604854874260549 + 0.056607536551391079 + 0.056610218262354545 + 0.056612900007150128 + 0.056615581785777115 + 0.056618263598234735 + 0.056620945444522203 + 0.056623627324638742 + 0.056626309238583646 + 0.056628991186356066 + 0.056631673167955303 + 0.056634355183380572 + 0.056637037232631138 + 0.056639719315706223 + 0.056642401432605065 + 0.056645083583326816 + 0.056647765767870943 + 0.05665044798623637 + 0.056653130238422666 + 0.056655812524428757 + 0.056658494844254149 + 0.056661177197897872 + 0.056663859585359355 + 0.056666542006637663 + 0.056669224461732171 + 0.056671906950642045 + 0.056674589473366559 + 0.056677272029905003 + 0.056679954620256601 + 0.056682637244420395 + 0.056685319902395954 + 0.056688002594182232 + 0.056690685319778715 + 0.056693368079184424 + 0.05669605087239879 + 0.056698733699421015 + 0.056701416560250226 + 0.05670409945488579 + 0.056706782383326867 + 0.056709465345572883 + 0.056712148341622873 + 0.056714831371476183 + 0.056717514435132101 + 0.056720197532589701 + 0.056722880663848403 + 0.056725563828907387 + 0.056728247027765973 + 0.056730930260423335 + 0.056733613526878633 + 0.056736296827131355 + 0.056738980161180542 + 0.056741663529025523 + 0.056744346930665553 + 0.056747030366099883 + 0.056749713835327731 + 0.056752397338348463 + 0.05675508087516113 + 0.056757764445765121 + 0.056760448050159729 + 0.056763131688344085 + 0.056765815360317509 + 0.056768499066079225 + 0.056771182805628539 + 0.056773866578964702 + 0.056776550386086845 + 0.056779234226994366 + 0.056781918101686535 + 0.056784602010162367 + 0.056787285952421405 + 0.056789969928462788 + 0.056792653938285802 + 0.056795337981889654 + 0.056798022059273583 + 0.056800706170436949 + 0.056803390315378892 + 0.056806074494098815 + 0.05680875870659579 + 0.056811442952869183 + 0.056814127232918274 + 0.056816811546742368 + 0.056819495894340565 + 0.056822180275712182 + 0.056824864690856583 + 0.05682754913977292 + 0.056830233622460362 + 0.056832918138918491 + 0.056835602689146288 + 0.056838287273143086 + 0.056840971890908178 + 0.056843656542440758 + 0.056846341227740162 + 0.05684902594680559 + 0.056851710699636501 + 0.056854395486231869 + 0.056857080306591111 + 0.056859765160713512 + 0.056862450048598259 + 0.056865134970244639 + 0.05686781992565193 + 0.056870504914819389 + 0.056873189937746309 + 0.056875874994432009 + 0.056878560084875608 + 0.056881245209076531 + 0.056883930367033861 + 0.056886615558747071 + 0.056889300784215238 + 0.056891986043437794 + 0.056894671336413898 + 0.056897356663142842 + 0.05690004202362392 + 0.056902727417856395 + 0.056905412845839574 + 0.056908098307572666 + 0.056910783803054879 + 0.056913469332285645 + 0.056916154895264165 + 0.056918840491989697 + 0.056921526122461479 + 0.056924211786678877 + 0.056926897484641054 + 0.05692958321634739 + 0.056932268981797013 + 0.056934954780989394 + 0.056937640613923639 + 0.056940326480599088 + 0.05694301238101504 + 0.05694569831517074 + 0.056948384283065458 + 0.056951070284698438 + 0.056953756320069056 + 0.056956442389176479 + 0.056959128492019992 + 0.056961814628599006 + 0.056964500798912659 + 0.056967187002960266 + 0.05696987324074114 + 0.056972559512254425 + 0.056975245817499603 + 0.056977932156475897 + 0.056980618529182472 + 0.056983304935618692 + 0.056985991375783723 + 0.056988677849677032 + 0.056991364357297798 + 0.056994050898645385 + 0.056996737473718917 + 0.056999424082517701 + 0.05700211072504123 + 0.057004797401288547 + 0.057007484111259041 + 0.057010170854951969 + 0.057012857632366624 + 0.057015544443502264 + 0.05701823128835825 + 0.057020918166933832 + 0.057023605079228136 + 0.057026292025240705 + 0.057028979004970649 + 0.057031666018417269 + 0.057034353065579926 + 0.057037040146457788 + 0.057039727261050319 + 0.05704241440935668 + 0.057045101591376164 + 0.057047788807108084 + 0.057050476056551724 + 0.057053163339706364 + 0.057055850656571372 + 0.057058538007145804 + 0.057061225391429209 + 0.057063912809420712 + 0.057066600261119732 + 0.057069287746525463 + 0.057071975265637211 + 0.057074662818454282 + 0.05707735040497592 + 0.057080038025201431 + 0.05708272567913026 + 0.057085413366761477 + 0.057088101088094458 + 0.05709078884312855 + 0.057093476631862962 + 0.057096164454296966 + 0.057098852310429951 + 0.057101540200261237 + 0.057104228123789985 + 0.057106916081015591 + 0.057109604071937291 + 0.057112292096554412 + 0.057114980154866234 + 0.057117668246872109 + 0.057120356372571179 + 0.057123044531962944 + 0.057125732725046542 + 0.057128420951821302 + 0.057131109212286577 + 0.057133797506441653 + 0.057136485834285856 + 0.057139174195818335 + 0.057141862591038484 + 0.057144551019945658 + 0.057147239482539053 + 0.057149927978818099 + 0.057152616508782013 + 0.057155305072430052 + 0.057157993669761556 + 0.057160682300775839 + 0.057163370965472179 + 0.05716605966384989 + 0.057168748395908318 + 0.057171437161646715 + 0.057174125961064318 + 0.057176814794160633 + 0.057179503660934709 + 0.057182192561386028 + 0.057184881495513817 + 0.057187570463317412 + 0.057190259464796084 + 0.057192948499949207 + 0.057195637568775978 + 0.057198326671275813 + 0.057201015807447894 + 0.057203704977291686 + 0.057206394180806384 + 0.057209083417991261 + 0.057211772688845731 + 0.057214461993368992 + 0.057217151331560426 + 0.057219840703419386 + 0.057222530108945034 + 0.057225219548136863 + 0.057227909020993936 + 0.057230598527515809 + 0.057233288067701595 + 0.057235977641550813 + 0.057238667249062597 + 0.057241356890236343 + 0.057244046565071295 + 0.057246736273566801 + 0.057249426015722187 + 0.057252115791536731 + 0.057254805601009859 + 0.057257495444140646 + 0.057260185320928587 + 0.057262875231373002 + 0.057265565175473147 + 0.057268255153228351 + 0.05727094516463789 + 0.057273635209701093 + 0.057276325288417397 + 0.057279015400785838 + 0.057281705546806061 + 0.057284395726477082 + 0.057287085939798504 + 0.05728977618676942 + 0.057292466467389183 + 0.057295156781657232 + 0.05729784712957272 + 0.057300537511135057 + 0.057303227926343604 + 0.057305918375197593 + 0.057308608857696355 + 0.057311299373839261 + 0.057313989923625575 + 0.057316680507054664 + 0.057319371124125766 + 0.057322061774838319 + 0.057324752459191483 + 0.057327443177184786 + 0.057330133928817306 + 0.057332824714088598 + 0.057335515532997802 + 0.057338206385544419 + 0.057340897271727594 + 0.057343588191546765 + 0.057346279145001143 + 0.057348970132090143 + 0.057351661152813073 + 0.057354352207169342 + 0.057357043295158061 + 0.057359734416778746 + 0.057362425572030577 + 0.057365116760913 + 0.057367807983425327 + 0.057370499239566781 + 0.057373190529336773 + 0.057375881852734685 + 0.057378573209759635 + 0.057381264600411187 + 0.057383956024688543 + 0.057386647482591063 + 0.057389338974117958 + 0.057392030499268769 + 0.057394722058042739 + 0.057397413650439086 + 0.057400105276457281 + 0.05740279693609663 + 0.057405488629356405 + 0.057408180356235884 + 0.05741087211673454 + 0.057413563910851693 + 0.057416255738586573 + 0.057418947599938611 + 0.057421639494906987 + 0.05742433142349114 + 0.057427023385690508 + 0.057429715381504209 + 0.057432407410931717 + 0.057435099473972358 + 0.057437791570625361 + 0.057440483700890138 + 0.05744317586476605 + 0.057445868062252395 + 0.05744856029334855 + 0.057451252558053778 + 0.057453944856367414 + 0.057456637188288799 + 0.057459329553817454 + 0.057462021952952344 + 0.057464714385693186 + 0.057467406852039132 + 0.057470099351989483 + 0.057472791885543592 + 0.057475484452700905 + 0.057478177053460651 + 0.057480869687822289 + 0.057483562355785021 + 0.057486255057348265 + 0.057488947792511291 + 0.057491640561273517 + 0.057494333363634256 + 0.057497026199592821 + 0.057499719069148671 + 0.05750241197230091 + 0.057505104909049129 + 0.057507797879392468 + 0.057510490883330455 + 0.057513183920862271 + 0.057515876991987368 + 0.057518570096705003 + 0.057521263235014629 + 0.057523956406915572 + 0.057526649612406972 + 0.057529342851488439 + 0.057532036124159178 + 0.057534729430418624 + 0.057537422770266002 + 0.057540116143700734 + 0.057542809550722142 + 0.057545502991329593 + 0.057548196465522485 + 0.057550889973299997 + 0.05755358351466168 + 0.057556277089606679 + 0.05755897069813453 + 0.057561664340244435 + 0.057564358015935818 + 0.057567051725208089 + 0.057569745468060436 + 0.057572439244492297 + 0.057575133054503042 + 0.057577826898091967 + 0.057580520775258485 + 0.057583214686001929 + 0.057585908630321668 + 0.057588602608216896 + 0.057591296619687204 + 0.057593990664731781 + 0.057596684743350043 + 0.057599378855541332 + 0.057602073001304953 + 0.057604767180640309 + 0.057607461393546722 + 0.057610155640023628 + 0.057612849920070333 + 0.057615544233686158 + 0.057618238580870437 + 0.057620932961622705 + 0.057623627375942045 + 0.057626321823827993 + 0.057629016305279862 + 0.057631710820296986 + 0.057634405368878802 + 0.057637099951024506 + 0.057639794566733675 + 0.057642489216005503 + 0.057645183898839381 + 0.057647878615234634 + 0.057650573365190784 + 0.057653268148707019 + 0.057655962965782681 + 0.057658657816417311 + 0.057661352700610083 + 0.057664047618360463 + 0.057666742569667771 + 0.057669437554531404 + 0.057672132572950618 + 0.057674827624924908 + 0.057677522710453635 + 0.057680217829536015 + 0.057682912982171528 + 0.057685608168359569 + 0.057688303388099382 + 0.057690998641390344 + 0.057693693928231961 + 0.057696389248623484 + 0.057699084602564288 + 0.0577017799900537 + 0.057704475411091118 + 0.057707170865675991 + 0.057709866353807614 + 0.057712561875485326 + 0.057715257430708482 + 0.057717953019476534 + 0.057720648641788788 + 0.057723344297644606 + 0.057726039987043336 + 0.057728735709984449 + 0.05773143146646726 + 0.057734127256491026 + 0.057736823080055302 + 0.057739518937159333 + 0.057742214827802556 + 0.057744910751984291 + 0.0577476067097039 + 0.057750302700960744 + 0.057752998725754331 + 0.057755694784083836 + 0.05775839087594882 + 0.057761087001348486 + 0.057763783160282259 + 0.057766479352749547 + 0.057769175578749735 + 0.057771871838282182 + 0.057774568131346196 + 0.057777264457941242 + 0.057779960818066557 + 0.057782657211721641 + 0.057785353638905919 + 0.057788050099618633 + 0.057790746593859181 + 0.057793443121627014 + 0.057796139682921396 + 0.05779883627774185 + 0.057801532906087555 + 0.057804229567958131 + 0.057806926263352709 + 0.057809622992270875 + 0.057812319754711905 + 0.057815016550675134 + 0.057817713380160035 + 0.057820410243165921 + 0.057823107139692166 + 0.057825804069738196 + 0.057828501033303385 + 0.057831198030387131 + 0.057833895060988724 + 0.057836592125107542 + 0.057839289222743152 + 0.057841986353894717 + 0.057844683518561785 + 0.057847380716743647 + 0.057850077948439681 + 0.057852775213649295 + 0.057855472512371921 + 0.057858169844606767 + 0.057860867210353405 + 0.057863564609611083 + 0.057866262042379338 + 0.057868959508657412 + 0.057871657008444786 + 0.057874354541740836 + 0.057877052108544803 + 0.057879749708856232 + 0.057882447342674545 + 0.057885145009998938 + 0.057887842710828905 + 0.057890540445163861 + 0.057893238213003184 + 0.057895936014346221 + 0.05789863384919236 + 0.057901331717541048 + 0.05790402961939161 + 0.057906727554743423 + 0.057909425523595938 + 0.057912123525948558 + 0.057914821561800625 + 0.057917519631151486 + 0.057920217734000579 + 0.057922915870347348 + 0.057925614040191128 + 0.057928312243531302 + 0.057931010480367265 + 0.057933708750698407 + 0.057936407054524117 + 0.057939105391843798 + 0.057941803762656868 + 0.057944502166962737 + 0.057947200604760683 + 0.057949899076050283 + 0.057952597580830684 + 0.057955296119101572 + 0.057957994690862054 + 0.057960693296111719 + 0.057963391934849923 + 0.057966090607075998 + 0.057968789312789384 + 0.057971488051989477 + 0.057974186824675686 + 0.057976885630847373 + 0.057979584470504011 + 0.057982283343644914 + 0.057984982250269546 + 0.057987681190377206 + 0.05799038016396741 + 0.057993079171039429 + 0.057995778211592811 + 0.057998477285626814 + 0.058001176393140973 + 0.058003875534134539 + 0.058006574708607074 + 0.058009273916557878 + 0.058011973157986299 + 0.058014672432891858 + 0.058017371741273964 + 0.058020071083131855 + 0.058022770458465163 + 0.058025469867272979 + 0.05802816930955508 + 0.058030868785310601 + 0.058033568294538991 + 0.058036267837239711 + 0.058038967413412169 + 0.058041667023055764 + 0.058044366666169911 + 0.058047066342753854 + 0.058049766052807227 + 0.058052465796329389 + 0.058055165573319578 + 0.058057865383777399 + 0.058060565227702143 + 0.058063265105093256 + 0.058065965015950113 + 0.058068664960272132 + 0.058071364938058839 + 0.058074064949309508 + 0.058076764994023505 + 0.058079465072200395 + 0.058082165183839483 + 0.058084865328940166 + 0.058087565507501854 + 0.058090265719524151 + 0.058092965965006169 + 0.05809566624394745 + 0.058098366556347501 + 0.058101066902205581 + 0.058103767281521203 + 0.058106467694293826 + 0.058109168140522652 + 0.058111868620207223 + 0.058114569133346908 + 0.05811726967994129 + 0.058119970259989592 + 0.058122670873491294 + 0.058125371520445737 + 0.058128072200852504 + 0.058130772914710784 + 0.058133473662020235 + 0.058136174442780096 + 0.058138875256989957 + 0.058141576104648963 + 0.058144276985756693 + 0.058146977900312646 + 0.058149678848316143 + 0.058152379829766544 + 0.058155080844663323 + 0.05815778189300598 + 0.058160482974793808 + 0.058163184090026243 + 0.05816588523870278 + 0.058168586420822836 + 0.058171287636385696 + 0.058173988885390944 + 0.058176690167837906 + 0.058179391483726028 + 0.058182092833054776 + 0.058184794215823392 + 0.058187495632031468 + 0.058190197081678476 + 0.058192898564763694 + 0.05819560008128654 + 0.058198301631246563 + 0.058201003214643138 + 0.058203704831475592 + 0.058206406481743495 + 0.058209108165446166 + 0.058211809882583045 + 0.058214511633153547 + 0.058217213417157222 + 0.058219915234593286 + 0.058222617085461378 + 0.058225318969760721 + 0.058228020887490857 + 0.058230722838651328 + 0.058233424823241238 + 0.058236126841260324 + 0.058238828892707838 + 0.058241530977583285 + 0.058244233095886104 + 0.058246935247615671 + 0.058249637432771409 + 0.058252339651352805 + 0.058255041903359228 + 0.058257744188790116 + 0.058260446507644947 + 0.058263148859923133 + 0.058265851245624042 + 0.058268553664747189 + 0.058271256117291982 + 0.05827395860325784 + 0.058276661122644159 + 0.058279363675450474 + 0.058282066261676112 + 0.058284768881320531 + 0.058287471534383212 + 0.05829017422086346 + 0.058292876940760976 + 0.058295579694074895 + 0.058298282480804806 + 0.058300985300950098 + 0.058303688154510251 + 0.058306391041484683 + 0.05830909396187272 + 0.058311796915673945 + 0.058314499902887784 + 0.058317202923513625 + 0.05831990597755092 + 0.058322609064999024 + 0.058325312185857542 + 0.058328015340125786 + 0.058330718527803221 + 0.058333421748889301 + 0.058336125003383463 + 0.058338828291285012 + 0.058341531612593679 + 0.058344234967308665 + 0.058346938355429472 + 0.058349641776955528 + 0.058352345231886385 + 0.058355048720221347 + 0.05835775224195993 + 0.05836045579710146 + 0.058363159385645541 + 0.058365863007591536 + 0.058368566662938888 + 0.05837127035168703 + 0.058373974073835384 + 0.05837667782938348 + 0.058379381618330638 + 0.058382085440676433 + 0.058384789296420277 + 0.058387493185561461 + 0.05839019710809968 + 0.058392901064034233 + 0.058395605053364559 + 0.058398309076090095 + 0.058401013132210362 + 0.058403717221724771 + 0.058406421344632795 + 0.058409125500933773 + 0.058411829690627297 + 0.058414533913712673 + 0.058417238170189484 + 0.058419942460057078 + 0.05842264678331497 + 0.05842535113996257 + 0.058428055529999377 + 0.058430759953424762 + 0.058433464410238244 + 0.058436168900439213 + 0.058438873424027184 + 0.058441577981001476 + 0.058444282571361757 + 0.058446987195107297 + 0.058449691852237626 + 0.058452396542752236 + 0.058455101266650378 + 0.058457806023931816 + 0.058460510814595731 + 0.058463215638641694 + 0.058465920496069163 + 0.058468625386877554 + 0.058471330311066411 + 0.058474035268634969 + 0.058476740259582993 + 0.058479445283909755 + 0.058482150341614657 + 0.058484855432697262 + 0.058487560557157037 + 0.058490265714993314 + 0.058492970906205657 + 0.058495676130793539 + 0.058498381388756356 + 0.058501086680093614 + 0.05850379200480478 + 0.058506497362889112 + 0.058509202754346325 + 0.058511908179175835 + 0.058514613637376957 + 0.058517319128949315 + 0.058520024653892271 + 0.058522730212205269 + 0.058525435803887846 + 0.058528141428939494 + 0.058530847087359499 + 0.05853355277914752 + 0.058536258504302857 + 0.058538964262825025 + 0.058541670054713647 + 0.058544375879967914 + 0.058547081738587456 + 0.058549787630571712 + 0.058552493555920099 + 0.058555199514632138 + 0.058557905506707267 + 0.058560611532145049 + 0.058563317590944755 + 0.058566023683105907 + 0.058568729808628019 + 0.058571435967510667 + 0.058574142159753033 + 0.058576848385354874 + 0.058579554644315482 + 0.058582260936634364 + 0.058584967262311043 + 0.058587673621344899 + 0.05859038001373542 + 0.058593086439482148 + 0.058595792898584458 + 0.058598499391041919 + 0.058601205916853853 + 0.05860391247601985 + 0.058606619068539423 + 0.058609325694411844 + 0.058612032353636753 + 0.058614739046213622 + 0.058617445772141834 + 0.058620152531420854 + 0.058622859324050189 + 0.05862556615002941 + 0.05862827300935787 + 0.058630979902035037 + 0.058633686828060388 + 0.058636393787433495 + 0.058639100780153747 + 0.058641807806220622 + 0.058644514865633587 + 0.058647221958392122 + 0.058649929084495719 + 0.058652636243943901 + 0.058655343436736063 + 0.058658050662871608 + 0.05866075792235026 + 0.058663465215171247 + 0.058666172541334223 + 0.058668879900838487 + 0.058671587293683658 + 0.058674294719869215 + 0.058677002179394568 + 0.058679709672259189 + 0.058682417198462594 + 0.058685124758004241 + 0.058687832350883602 + 0.058690539977100269 + 0.058693247636653546 + 0.058695955329542991 + 0.058698663055768194 + 0.058701370815328384 + 0.05870407860822327 + 0.058706786434452228 + 0.058709494294014709 + 0.058712202186910346 + 0.05871491011313848 + 0.058717618072698645 + 0.058720326065590286 + 0.05872303409181294 + 0.058725742151366049 + 0.058728450244249115 + 0.058731158370461632 + 0.058733866530003023 + 0.058736574722872845 + 0.058739282949070562 + 0.058741991208595669 + 0.058744699501447707 + 0.058747407827625976 + 0.058750116187130212 + 0.058752824579959569 + 0.058755533006113844 + 0.058758241465592394 + 0.058760949958394787 + 0.058763658484520385 + 0.058766367043968766 + 0.058769075636739457 + 0.058771784262831792 + 0.058774492922245375 + 0.058777201614979679 + 0.058779910341034178 + 0.058782619100408336 + 0.058785327893101702 + 0.058788036719113666 + 0.058790745578443999 + 0.058793454471091772 + 0.058796163397056782 + 0.05879887235633844 + 0.058801581348936177 + 0.058804290374849542 + 0.058806999434078015 + 0.05880970852662111 + 0.058812417652478334 + 0.058815126811649139 + 0.058817836004133033 + 0.058820545229929432 + 0.058823254489037989 + 0.058825963781458115 + 0.058828673107189228 + 0.058831382466231014 + 0.058834091858582786 + 0.058836801284244136 + 0.058839510743214508 + 0.058842220235493396 + 0.058844929761080349 + 0.058847639319974901 + 0.058850348912176456 + 0.05885305853768448 + 0.058855768196498626 + 0.05885847788861822 + 0.058861187614042916 + 0.058863897372772082 + 0.058866607164805337 + 0.058869316990142112 + 0.058872026848781858 + 0.058874736740724173 + 0.058877446665968496 + 0.058880156624514422 + 0.05888286661636126 + 0.058885576641508695 + 0.058888286699956188 + 0.058890996791703135 + 0.058893706916749201 + 0.058896417075093715 + 0.058899127266736358 + 0.058901837491676594 + 0.058904547749913778 + 0.058907258041447495 + 0.058909968366277411 + 0.058912678724402791 + 0.058915389115823211 + 0.058918099540538275 + 0.058920809998547395 + 0.058923520489850105 + 0.058926231014445878 + 0.058928941572334324 + 0.058931652163514821 + 0.058934362787986944 + 0.058937073445750165 + 0.058939784136804001 + 0.058942494861148026 + 0.058945205618781658 + 0.058947916409704398 + 0.058950627233915913 + 0.058953338091415487 + 0.058956048982202761 + 0.058958759906277247 + 0.058961470863638489 + 0.058964181854285896 + 0.058966892878218997 + 0.058969603935437348 + 0.058972315025940449 + 0.058975026149727806 + 0.058977737306798929 + 0.058980448497153302 + 0.058983159720790518 + 0.058985870977710041 + 0.058988582267911309 + 0.058991293591393927 + 0.058994004948157409 + 0.058996716338201222 + 0.058999427761524996 + 0.059002139218128073 + 0.059004850708010051 + 0.059007562231170506 + 0.059010273787608925 + 0.059012985377324731 + 0.059015697000317523 + 0.059018408656586731 + 0.059021120346132099 + 0.059023832068952793 + 0.059026543825048648 + 0.059029255614419046 + 0.059031967437063446 + 0.0590346792929815 + 0.059037391182172674 + 0.059040103104636386 + 0.059042815060372324 + 0.059045527049379917 + 0.059048239071658709 + 0.059050951127208193 + 0.059053663216027924 + 0.059056375338117355 + 0.059059087493476041 + 0.059061799682103629 + 0.059064511903999438 + 0.059067224159163129 + 0.059069936447594139 + 0.059072648769292045 + 0.05907536112425639 + 0.059078073512486624 + 0.059080785933982319 + 0.059083498388742918 + 0.059086210876768124 + 0.05908892339805729 + 0.05909163595261005 + 0.059094348540425841 + 0.059097061161504212 + 0.059099773815844761 + 0.05910248650344696 + 0.059105199224310338 + 0.05910791197843436 + 0.059110624765818708 + 0.059113337586462748 + 0.059116050440366032 + 0.059118763327528162 + 0.059121476247948689 + 0.05912418920162707 + 0.059126902188562855 + 0.059129615208755544 + 0.059132328262204728 + 0.059135041348909824 + 0.059137754468870422 + 0.059140467622086246 + 0.059143180808556524 + 0.059145894028280896 + 0.059148607281258994 + 0.059151320567490208 + 0.059154033886974107 + 0.059156747239710213 + 0.05915946062569824 + 0.059162174044937441 + 0.059164887497427522 + 0.059167600983167944 + 0.059170314502158351 + 0.059173028054398176 + 0.0591757416398868 + 0.05917845525862412 + 0.059181168910609434 + 0.059183882595842341 + 0.059186596314322382 + 0.059189310066049022 + 0.059192023851021847 + 0.059194737669240348 + 0.059197451520704186 + 0.05920016540541282 + 0.059202879323365765 + 0.059205593274562561 + 0.059208307259002717 + 0.059211021276686038 + 0.059213735327611622 + 0.059216449411779351 + 0.059219163529188622 + 0.059221877679838872 + 0.059224591863729914 + 0.059227306080861103 + 0.059230020331232071 + 0.059232734614842214 + 0.059235448931691206 + 0.059238163281778479 + 0.059240877665103768 + 0.059243592081666414 + 0.059246306531466036 + 0.059249021014502155 + 0.059251735530774369 + 0.059254450080282156 + 0.059257164663025108 + 0.059259879279002746 + 0.059262593928214674 + 0.059265308610660331 + 0.059268023326339347 + 0.059270738075251149 + 0.059273452857395437 + 0.059276167672771704 + 0.059278882521379396 + 0.059281597403218221 + 0.05928431231828768 + 0.059287027266587147 + 0.059289742248116409 + 0.059292457262874854 + 0.059295172310862149 + 0.05929788739207776 + 0.059300602506521173 + 0.059303317654192153 + 0.059306032835090075 + 0.059308748049214516 + 0.059311463296565038 + 0.059314178577141149 + 0.059316893890942565 + 0.059319609237968605 + 0.059322324618219055 + 0.059325040031693171 + 0.059327755478390774 + 0.05933047095831126 + 0.059333186471454316 + 0.059335902017819381 + 0.059338617597406058 + 0.059341333210213856 + 0.059344048856242386 + 0.059346764535491134 + 0.059349480247959663 + 0.059352195993647675 + 0.059354911772554531 + 0.059357627584679884 + 0.059360343430023207 + 0.059363059308584237 + 0.0593657752203623 + 0.059368491165357126 + 0.059371207143568153 + 0.059373923154995012 + 0.059376639199637253 + 0.059379355277494418 + 0.059382071388566035 + 0.059384787532851757 + 0.059387503710351036 + 0.059390219921063386 + 0.059392936164988593 + 0.05939565244212601 + 0.059398368752475318 + 0.059401085096035963 + 0.059403801472807535 + 0.059406517882789667 + 0.059409234325981886 + 0.059411950802383678 + 0.059414667311994712 + 0.059417383854814557 + 0.05942010043084265 + 0.059422817040078603 + 0.05942553368252209 + 0.059428250358172598 + 0.059430967067029619 + 0.059433683809092794 + 0.05943640058436158 + 0.059439117392835757 + 0.059441834234514684 + 0.059444551109398107 + 0.059447268017485379 + 0.05944998495877625 + 0.059452701933270187 + 0.059455418940966752 + 0.05945813598186548 + 0.059460853055966108 + 0.059463570163267969 + 0.059466287303770828 + 0.059469004477474156 + 0.059471721684377594 + 0.05947443892448058 + 0.059477156197782752 + 0.059479873504283777 + 0.059482590843983073 + 0.059485308216880299 + 0.059488025622974963 + 0.059490743062266607 + 0.059493460534754919 + 0.059496178040439524 + 0.059498895579319741 + 0.059501613151395273 + 0.059504330756665696 + 0.059507048395130602 + 0.059509766066789531 + 0.059512483771642075 + 0.059515201509687886 + 0.059517919280926382 + 0.059520637085357181 + 0.059523354922979874 + 0.059526072793794078 + 0.059528790697799323 + 0.059531508634995199 + 0.05953422660538122 + 0.059536944608957046 + 0.059539662645722281 + 0.05954238071567633 + 0.059545098818818899 + 0.059547816955149546 + 0.059550535124667868 + 0.059553253327373462 + 0.059555971563265746 + 0.059558689832344532 + 0.059561408134609271 + 0.059564126470059452 + 0.059566844838694795 + 0.059569563240514857 + 0.059572281675519166 + 0.059575000143707327 + 0.059577718645078978 + 0.059580437179633537 + 0.059583155747370685 + 0.059585874348290144 + 0.059588592982391247 + 0.059591311649673726 + 0.059594030350137141 + 0.059596749083780994 + 0.05959946785060493 + 0.059602186650608527 + 0.059604905483791458 + 0.059607624350153196 + 0.059610343249693235 + 0.059613062182411303 + 0.059615781148307012 + 0.059618500147379863 + 0.059621219179629432 + 0.059623938245055415 + 0.059626657343657241 + 0.059629376475434592 + 0.059632095640386948 + 0.059634814838513996 + 0.059637534069815389 + 0.059640253334290606 + 0.059642972631939226 + 0.05964569196276083 + 0.059648411326755156 + 0.0596511307239216 + 0.059653850154259828 + 0.059656569617769419 + 0.059659289114450037 + 0.059662008644301122 + 0.059664728207322333 + 0.059667447803513345 + 0.059670167432873698 + 0.059672887095402846 + 0.059675606791100524 + 0.059678326519966317 + 0.059681046281999793 + 0.059683766077200578 + 0.059686485905568187 + 0.059689205767102183 + 0.059691925661802307 + 0.059694645589668013 + 0.059697365550699044 + 0.059700085544894844 + 0.059702805572255026 + 0.059705525632779317 + 0.059708245726467185 + 0.059710965853318219 + 0.059713686013332032 + 0.059716406206508262 + 0.059719126432846534 + 0.059721846692346287 + 0.059724566985007256 + 0.059727287310828978 + 0.059730007669811132 + 0.059732728061953184 + 0.059735448487254879 + 0.059738168945715681 + 0.059740889437335271 + 0.059743609962113149 + 0.059746330520049074 + 0.059749051111142502 + 0.059751771735393124 + 0.059754492392800472 + 0.05975721308336409 + 0.059759933807083852 + 0.059762654563959038 + 0.059765375353989326 + 0.059768096177174497 + 0.059770817033514001 + 0.05977353792300736 + 0.059776258845654365 + 0.059778979801454489 + 0.059781700790407358 + 0.059784421812512659 + 0.059787142867769823 + 0.05978986395617867 + 0.059792585077738658 + 0.059795306232449344 + 0.059798027420310568 + 0.059800748641321663 + 0.059803469895482325 + 0.059806191182792255 + 0.059808912503250967 + 0.059811633856858087 + 0.059814355243613206 + 0.059817076663515913 + 0.05981979811656591 + 0.059822519602762685 + 0.059825241122105972 + 0.059827962674595218 + 0.059830684260230138 + 0.059833405879010308 + 0.059836127530935417 + 0.059838849216004936 + 0.059841570934218623 + 0.059844292685575916 + 0.059847014470076537 + 0.059849736287720112 + 0.059852458138506204 + 0.059855180022434423 + 0.059857901939504327 + 0.059860623889715629 + 0.059863345873067936 + 0.059866067889560809 + 0.059868789939193819 + 0.05987151202196675 + 0.059874234137878998 + 0.059876956286930308 + 0.059879678469120248 + 0.059882400684448472 + 0.059885122932914502 + 0.059887845214518107 + 0.059890567529258781 + 0.059893289877136179 + 0.059896012258149861 + 0.059898734672299517 + 0.059901457119584729 + 0.059904179600005145 + 0.059906902113560305 + 0.059909624660249933 + 0.059912347240073535 + 0.059915069853030724 + 0.05991779249912127 + 0.059920515178344638 + 0.059923237890700518 + 0.059925960636188505 + 0.059928683414808205 + 0.059931406226559278 + 0.059934129071441349 + 0.059936851949454001 + 0.059939574860596784 + 0.059942297804869427 + 0.059945020782271527 + 0.059947743792802731 + 0.059950466836462636 + 0.059953189913250833 + 0.059955913023166912 + 0.059958636166210638 + 0.059961359342381428 + 0.059964082551679052 + 0.059966805794103177 + 0.059969529069653256 + 0.059972252378329059 + 0.059974975720130184 + 0.059977699095056111 + 0.059980422503106631 + 0.059983145944281363 + 0.059985869418579849 + 0.059988592926001706 + 0.059991316466546686 + 0.059994040040214289 + 0.059996763647004174 + 0.059999487286915981 + 0.060002210959949322 + 0.060004934666103862 + 0.060007658405379243 + 0.060010382177775039 + 0.060013105983290807 + 0.06001582982192627 + 0.060018553693681101 + 0.060021277598554808 + 0.060024001536547134 + 0.06002672550765769 + 0.060029449511886011 + 0.060032173549231821 + 0.060034897619694681 + 0.060037621723274329 + 0.06004034585997025 + 0.060043070029782181 + 0.060045794232709726 + 0.060048518468752567 + 0.060051242737910147 + 0.06005396704018244 + 0.060056691375568697 + 0.060059415744068832 + 0.060062140145682265 + 0.060064864580408883 + 0.060067589048248049 + 0.060070313549199589 + 0.060073038083263024 + 0.060075762650438042 + 0.060078487250724309 + 0.060081211884121438 + 0.060083936550629019 + 0.060086661250246746 + 0.060089385982974246 + 0.060092110748811066 + 0.060094835547756902 + 0.060097560379811579 + 0.060100285244974454 + 0.060103010143245227 + 0.060105735074623606 + 0.060108460039109211 + 0.060111185036701646 + 0.060113910067400605 + 0.060116635131205721 + 0.060119360228116557 + 0.060122085358132855 + 0.0601248105212542 + 0.060127535717480245 + 0.0601302609468106 + 0.060132986209244961 + 0.060135711504782981 + 0.060138436833424083 + 0.060141162195168317 + 0.06014388759001494 + 0.060146613017963854 + 0.060149338479014477 + 0.060152063973166629 + 0.060154789500419956 + 0.060157515060773992 + 0.060160240654228404 + 0.060162966280782874 + 0.06016569194043702 + 0.060168417633190585 + 0.060171143359043146 + 0.060173869117994272 + 0.060176594910043645 + 0.060179320735190986 + 0.060182046593435873 + 0.060184772484778055 + 0.060187498409216972 + 0.060190224366752483 + 0.060192950357384097 + 0.060195676381111542 + 0.060198402437934465 + 0.060201128527852435 + 0.060203854650865161 + 0.060206580806972325 + 0.060209306996173544 + 0.060212033218468394 + 0.060214759473856683 + 0.060217485762337965 + 0.060220212083911845 + 0.060222938438578066 + 0.060225664826336206 + 0.060228391247185889 + 0.060231117701126859 + 0.060233844188158872 + 0.060236570708281222 + 0.060239297261493949 + 0.060242023847796457 + 0.060244750467188586 + 0.06024747711966974 + 0.060250203805239891 + 0.060252930523898331 + 0.060255657275645011 + 0.060258384060479467 + 0.060261110878401428 + 0.060263837729410422 + 0.06026656461350615 + 0.060269291530688315 + 0.060272018480956639 + 0.060274745464310588 + 0.060277472480749925 + 0.060280199530274275 + 0.060282926612883356 + 0.060285653728576839 + 0.060288380877354317 + 0.060291108059215365 + 0.060293835274159872 + 0.060296562522187264 + 0.060299289803297358 + 0.060302017117489691 + 0.060304744464764123 + 0.060307471845120114 + 0.060310199258557413 + 0.060312926705075598 + 0.060315654184674418 + 0.060318381697353519 + 0.060321109243112549 + 0.060323836821951221 + 0.06032656443386912 + 0.06032929207886592 + 0.060332019756941281 + 0.060334747468094953 + 0.060337475212326443 + 0.060340202989635591 + 0.060342930800021927 + 0.060345658643485178 + 0.060348386520025013 + 0.060351114429641098 + 0.060353842372332996 + 0.060356570348100505 + 0.060359298356943272 + 0.060362026398860923 + 0.060364754473853081 + 0.060367482581919471 + 0.060370210723059793 + 0.060372938897273701 + 0.060375667104560785 + 0.060378395344920816 + 0.060381123618353308 + 0.060383851924858102 + 0.06038658026443483 + 0.060389308637083118 + 0.060392037042802625 + 0.060394765481593095 + 0.060397493953454083 + 0.060400222458385319 + 0.060402950996386477 + 0.060405679567457259 + 0.060408408171597303 + 0.060411136808806304 + 0.060413865479083784 + 0.060416594182429721 + 0.06041932291884352 + 0.060422051688324957 + 0.060424780490873679 + 0.060427509326489312 + 0.060430238195171723 + 0.060432967096920351 + 0.06043569603173507 + 0.060438424999615367 + 0.060441154000561027 + 0.060443883034571724 + 0.060446612101647069 + 0.060449341201786848 + 0.060452070334990546 + 0.06045479950125808 + 0.060457528700588979 + 0.060460257932982951 + 0.060462987198439691 + 0.060465716496958873 + 0.060468445828540149 + 0.060471175193183159 + 0.060473904590887702 + 0.060476634021653312 + 0.060479363485479873 + 0.060482092982366793 + 0.060484822512313921 + 0.060487552075320909 + 0.060490281671387473 + 0.060493011300513239 + 0.060495740962697886 + 0.060498470657941117 + 0.060501200386242612 + 0.060503930147602109 + 0.060506659942019189 + 0.060509389769493535 + 0.06051211963002489 + 0.060514849523612982 + 0.060517579450257437 + 0.060520309409957798 + 0.060523039402714092 + 0.060525769428525618 + 0.060528499487392293 + 0.060531229579313742 + 0.060533959704289625 + 0.060536689862319755 + 0.060539420053403577 + 0.060542150277540979 + 0.060544880534731581 + 0.060547610824975132 + 0.060550341148271188 + 0.060553071504619554 + 0.060555801894019802 + 0.060558532316471736 + 0.060561262771974926 + 0.060563993260529296 + 0.060566723782134291 + 0.06056945433678966 + 0.060572184924495044 + 0.060574915545250296 + 0.060577646199055056 + 0.060580376885908803 + 0.060583107605811447 + 0.060585838358762661 + 0.060588569144762114 + 0.060591299963809457 + 0.060594030815904434 + 0.060596761701046692 + 0.060599492619235834 + 0.060602223570471798 + 0.060604954554754044 + 0.060607685572082404 + 0.060610416622456482 + 0.060613147705876107 + 0.060615878822340749 + 0.060618609971850347 + 0.060621341154404318 + 0.060624072370002696 + 0.060626803618644899 + 0.060629534900330795 + 0.060632266215060009 + 0.060634997562832117 + 0.060637728943647017 + 0.060640460357504304 + 0.060643191804403654 + 0.060645923284344844 + 0.060648654797327596 + 0.060651386343351418 + 0.060654117922416192 + 0.060656849534521537 + 0.060659581179667216 + 0.060662312857852813 + 0.060665044569078147 + 0.060667776313342865 + 0.060670508090646599 + 0.06067323990098919 + 0.06067597174437022 + 0.060678703620789441 + 0.060681435530246609 + 0.060684167472741295 + 0.060686899448273296 + 0.060689631456842287 + 0.060692363498447963 + 0.060695095573090031 + 0.060697827680768236 + 0.06070055982148221 + 0.060703291995231681 + 0.060706024202016332 + 0.06070875644183598 + 0.060711488714690183 + 0.060714221020578718 + 0.060716953359501342 + 0.060719685731457529 + 0.060722418136447333 + 0.060725150574470199 + 0.060727883045525843 + 0.060730615549614085 + 0.060733348086734688 + 0.060736080656887126 + 0.060738813260071266 + 0.06074154589628683 + 0.060744278565533459 + 0.060747011267810902 + 0.060749744003118875 + 0.060752476771456988 + 0.060755209572825035 + 0.060757942407222772 + 0.06076067527464981 + 0.0607634081751059 + 0.060766141108590764 + 0.06076887407510409 + 0.060771607074645607 + 0.060774340107214955 + 0.060777073172811898 + 0.060779806271436268 + 0.060782539403087657 + 0.060785272567765732 + 0.060788005765470242 + 0.060790738996200931 + 0.060793472259957473 + 0.060796205556739695 + 0.06079893888654718 + 0.060801672249379664 + 0.060804405645236835 + 0.060807139074118499 + 0.060809872536024392 + 0.060812606030954064 + 0.060815339558907319 + 0.060818073119883999 + 0.060820806713883624 + 0.060823540340906 + 0.060826274000950788 + 0.060829007694017799 + 0.060831741420106632 + 0.060834475179217237 + 0.060837208971348991 + 0.060839942796501845 + 0.060842676654675555 + 0.060845410545869553 + 0.060848144470083916 + 0.060850878427318136 + 0.060853612417571951 + 0.060856346440845248 + 0.060859080497137522 + 0.060861814586448619 + 0.060864548708778263 + 0.060867282864126113 + 0.060870017052491961 + 0.060872751273875404 + 0.060875485528276339 + 0.060878219815694364 + 0.060880954136129241 + 0.060883688489580708 + 0.060886422876048486 + 0.060889157295532181 + 0.0608918917480318 + 0.060894626233546689 + 0.060897360752076905 + 0.060900095303621976 + 0.060902829888181693 + 0.06090556450575578 + 0.060908299156343958 + 0.060911033839945943 + 0.060913768556561575 + 0.060916503306190299 + 0.060919238088832123 + 0.060921972904486636 + 0.060924707753153617 + 0.060927442634832775 + 0.06093017754952381 + 0.060932912497226488 + 0.060935647477940523 + 0.06093838249166561 + 0.060941117538401521 + 0.060943852618148019 + 0.060946587730904833 + 0.060949322876671583 + 0.060952058055448101 + 0.060954793267234061 + 0.060957528512029263 + 0.060960263789833366 + 0.060962999100646169 + 0.060965734444467311 + 0.060968469821296556 + 0.060971205231133675 + 0.06097394067397837 + 0.060976676149830412 + 0.060979411658689545 + 0.060982147200555357 + 0.060984882775427809 + 0.06098761838330638 + 0.060990354024191042 + 0.060993089698081412 + 0.060995825404977236 + 0.060998561144878297 + 0.061001296917784192 + 0.061004032723694847 + 0.061006768562609816 + 0.061009504434528967 + 0.061012240339452004 + 0.061014976277378556 + 0.061017712248308528 + 0.061020448252241587 + 0.06102318428917753 + 0.061025920359115908 + 0.061028656462056664 + 0.061031392597999438 + 0.061034128766944015 + 0.061036864968890041 + 0.061039601203837376 + 0.061042337471785585 + 0.061045073772734652 + 0.061047810106684218 + 0.061050546473633928 + 0.061053282873583539 + 0.061056019306532955 + 0.061058755772481821 + 0.06106149227142979 + 0.061064228803376801 + 0.061066965368322353 + 0.061069701966266286 + 0.06107243859720847 + 0.061075175261148446 + 0.061077911958086158 + 0.061080648688021225 + 0.06108338545095341 + 0.061086122246882438 + 0.061088859075808112 + 0.061091595937730239 + 0.06109433283264832 + 0.061097069760562277 + 0.061099806721471916 + 0.061102543715376809 + 0.061105280742276891 + 0.061108017802171725 + 0.06111075489506114 + 0.06111349202094489 + 0.061116229179822727 + 0.061118966371694484 + 0.061121703596559683 + 0.061124440854418281 + 0.061127178145269863 + 0.061129915469114324 + 0.0611326528259514 + 0.061135390215780794 + 0.061138127638602241 + 0.061140865094415457 + 0.061143602583220318 + 0.061146340105016468 + 0.061149077659803638 + 0.061151815247581696 + 0.061154552868350268 + 0.061157290522109282 + 0.061160028208858346 + 0.061162765928597228 + 0.061165503681325693 + 0.061168241467043444 + 0.061170979285750333 + 0.061173717137446085 + 0.061176455022130413 + 0.061179192939803131 + 0.06118193089046392 + 0.061184668874112613 + 0.061187406890748919 + 0.061190144940372601 + 0.061192883022983473 + 0.061195621138581111 + 0.061198359287165383 + 0.061201097468736199 + 0.061203835683293156 + 0.061206573930835909 + 0.061209312211364435 + 0.061212050524878381 + 0.061214788871377435 + 0.061217527250861506 + 0.061220265663330317 + 0.061223004108783591 + 0.061225742587221015 + 0.061228481098642547 + 0.061231219643047681 + 0.061233958220436403 + 0.061236696830808374 + 0.061239435474163398 + 0.061242174150501233 + 0.061244912859821539 + 0.061247651602124198 + 0.061250390377408932 + 0.061253129185675527 + 0.061255868026923663 + 0.061258606901153152 + 0.061261345808363843 + 0.06126408474855536 + 0.061266823721727579 + 0.061269562727880172 + 0.061272301767013017 + 0.061275040839125744 + 0.061277779944218201 + 0.061280519082290132 + 0.061283258253341265 + 0.061285997457371462 + 0.06128873669438039 + 0.061291475964367889 + 0.06129421526733364 + 0.06129695460327754 + 0.06129969397219924 + 0.06130243337409861 + 0.061305172808975274 + 0.061307912276829017 + 0.061310651777659819 + 0.06131339131146727 + 0.061316130878251156 + 0.061318870478011295 + 0.061321610110747327 + 0.061324349776459154 + 0.061327089475146562 + 0.06132982920680919 + 0.061332568971446982 + 0.061335308769059571 + 0.061338048599646748 + 0.061340788463208382 + 0.061343528359744111 + 0.061346268289253769 + 0.061349008251737142 + 0.061351748247193964 + 0.061354488275624092 + 0.061357228337027177 + 0.061359968431403081 + 0.061362708558751582 + 0.061365448719072381 + 0.061368188912365326 + 0.06137092913863014 + 0.061373669397866731 + 0.061376409690074636 + 0.061379150015253736 + 0.061381890373403906 + 0.0613846307645248 + 0.061387371188616285 + 0.061390111645678071 + 0.061392852135709983 + 0.061395592658711792 + 0.061398333214683153 + 0.061401073803624036 + 0.061403814425534116 + 0.061406555080413171 + 0.061409295768261089 + 0.06141203648907749 + 0.061414777242862102 + 0.061417518029614933 + 0.061420258849335711 + 0.061422999702024056 + 0.061425740587679904 + 0.061428481506302958 + 0.061431222457893057 + 0.06143396344244987 + 0.061436704459973325 + 0.061439445510463132 + 0.061442186593919097 + 0.06144492771034097 + 0.061447668859728563 + 0.061450410042081627 + 0.061453151257399932 + 0.061455892505683347 + 0.061458633786931616 + 0.061461375101144411 + 0.061464116448321691 + 0.061466857828463187 + 0.061469599241568591 + 0.06147234068763785 + 0.061475082166670601 + 0.061477823678666665 + 0.06148056522362591 + 0.06148330680154801 + 0.061486048412432867 + 0.061488790056280163 + 0.061491531733089799 + 0.061494273442861375 + 0.061497015185594958 + 0.061499756961290071 + 0.061502498769946692 + 0.061505240611564399 + 0.06150798248614317 + 0.06151072439368277 + 0.061513466334182948 + 0.061516208307643511 + 0.061518950314064215 + 0.06152169235344486 + 0.06152443442578532 + 0.061527176531085241 + 0.061529918669344548 + 0.061532660840562914 + 0.061535403044740269 + 0.061538145281876303 + 0.061540887551970805 + 0.061543629855023589 + 0.061546372191034537 + 0.061549114560003303 + 0.061551856961929802 + 0.061554599396813729 + 0.061557341864654863 + 0.06156008436545319 + 0.061562826899208264 + 0.061565569465919998 + 0.061568312065588209 + 0.06157105469821271 + 0.061573797363793127 + 0.061576540062329446 + 0.061579282793821383 + 0.061582025558268784 + 0.061584768355671428 + 0.061587511186029009 + 0.061590254049341389 + 0.06159299694560854 + 0.061595739874829962 + 0.061598482837005676 + 0.061601225832135419 + 0.06160396886021894 + 0.061606711921256087 + 0.061609455015246652 + 0.061612198142190419 + 0.061614941302087244 + 0.061617684494936834 + 0.061620427720739057 + 0.061623170979493769 + 0.061625914271200538 + 0.061628657595859525 + 0.06163140095347025 + 0.061634144344032624 + 0.061636887767546396 + 0.061639631224011428 + 0.061642374713427518 + 0.061645118235794452 + 0.061647861791112028 + 0.061650605379379955 + 0.061653349000598302 + 0.061656092654766598 + 0.061658836341884862 + 0.061661580061952694 + 0.061664323814970057 + 0.061667067600936695 + 0.061669811419852422 + 0.061672555271717062 + 0.061675299156530382 + 0.06167804307429222 + 0.061680787025002376 + 0.061683531008660766 + 0.061686275025266926 + 0.061689019074820925 + 0.061691763157322485 + 0.061694507272771384 + 0.061697251421167457 + 0.061699995602510514 + 0.06170273981680028 + 0.061705484064036753 + 0.061708228344219629 + 0.061710972657348713 + 0.06171371700342386 + 0.061716461382444757 + 0.061719205794411376 + 0.061721950239323517 + 0.061724694717180804 + 0.061727439227983322 + 0.061730183771730694 + 0.061732928348422839 + 0.061735672958059387 + 0.061738417600640347 + 0.06174116227616553 + 0.061743906984634674 + 0.061746651726047493 + 0.061749396500404022 + 0.061752141307703928 + 0.06175488614794708 + 0.061757631021133283 + 0.06176037592726237 + 0.061763120866334155 + 0.061765865838348463 + 0.06176861084330508 + 0.061771355881203749 + 0.061774100952044372 + 0.061776846055826812 + 0.061779591192550894 + 0.061782336362216299 + 0.061785081564822958 + 0.061787826800370628 + 0.061790572068859212 + 0.061793317370288384 + 0.061796062704658171 + 0.061798808071968206 + 0.06180155347221844 + 0.061804298905408658 + 0.06180704437153859 + 0.061809789870608096 + 0.061812535402617094 + 0.061815280967565299 + 0.061818026565452627 + 0.061820772196278795 + 0.061823517860043753 + 0.061826263556747155 + 0.061829009286388945 + 0.061831755048969005 + 0.061834500844486898 + 0.061837246672942825 + 0.061839992534336308 + 0.061842738428667228 + 0.061845484355935502 + 0.061848230316140944 + 0.061850976309283275 + 0.061853722335362418 + 0.06185646839437825 + 0.061859214486330395 + 0.061861960611218805 + 0.061864706769043376 + 0.061867452959803802 + 0.061870199183500035 + 0.061872945440131742 + 0.061875691729698958 + 0.061878438052201383 + 0.061881184407638831 + 0.061883930796011191 + 0.061886677217318206 + 0.061889423671559869 + 0.061892170158735778 + 0.061894916678846008 + 0.061897663231890263 + 0.06190040981786829 + 0.061903156436780023 + 0.061905903088625383 + 0.061908649773404011 + 0.061911396491115878 + 0.061914143241760797 + 0.061916890025338525 + 0.06191963684184891 + 0.06192238369129182 + 0.061925130573667157 + 0.061927877488974624 + 0.06193062443721413 + 0.061933371418385501 + 0.061936118432488557 + 0.061938865479523167 + 0.061941612559489038 + 0.0619443596723862 + 0.061947106818214401 + 0.061949853996973434 + 0.061952601208663166 + 0.061955348453283467 + 0.061958095730834127 + 0.061960843041314946 + 0.061963590384725827 + 0.06196633776106665 + 0.06196908517033721 + 0.061971832612537338 + 0.061974580087666757 + 0.061977327595725495 + 0.061980075136713358 + 0.061982822710630096 + 0.061985570317475591 + 0.06198831795724976 + 0.061991065629952213 + 0.061993813335583098 + 0.061996561074142024 + 0.061999308845628917 + 0.062002056650043609 + 0.062004804487385989 + 0.06200755235765578 + 0.062010300260852989 + 0.062013048196977269 + 0.062015796166028613 + 0.062018544168006833 + 0.062021292202911735 + 0.062024040270743208 + 0.062026788371500996 + 0.062029536505185084 + 0.062032284671795182 + 0.06203503287133133 + 0.062037781103793141 + 0.062040529369180558 + 0.062043277667493506 + 0.06204602599873172 + 0.062048774362895021 + 0.062051522759983373 + 0.06205427118999652 + 0.062057019652934441 + 0.062059768148796865 + 0.062062516677583654 + 0.062065265239294752 + 0.062068013833929819 + 0.062070762461488869 + 0.062073511121971646 + 0.062076259815378128 + 0.062079008541708107 + 0.06208175730096132 + 0.062084506093137752 + 0.062087254918237189 + 0.062090003776259527 + 0.06209275266720457 + 0.062095501591072244 + 0.062098250547862242 + 0.062100999537574607 + 0.06210374856020906 + 0.062106497615765553 + 0.062109246704243795 + 0.062111995825643883 + 0.06211474497996531 + 0.062117494167208333 + 0.062120243387372473 + 0.0621229926404578 + 0.062125741926463994 + 0.062128491245391118 + 0.062131240597238784 + 0.062133989982007053 + 0.062136739399695662 + 0.062139488850304549 + 0.062142238333833519 + 0.062144987850282378 + 0.062147737399651112 + 0.062150486981939458 + 0.062153236597147374 + 0.062155986245274616 + 0.062158735926321068 + 0.062161485640286618 + 0.062164235387171224 + 0.062166985166974574 + 0.062169734979696516 + 0.062172484825337021 + 0.062175234703895882 + 0.062177984615373043 + 0.06218073455976833 + 0.062183484537081536 + 0.062186234547312542 + 0.062188984590461314 + 0.062191734666527478 + 0.062194484775511226 + 0.062197234917412136 + 0.062199985092230271 + 0.062202735299965284 + 0.062205485540617139 + 0.062208235814185858 + 0.062210986120671025 + 0.062213736460072715 + 0.062216486832390692 + 0.062219237237624757 + 0.062221987675774977 + 0.062224738146841083 + 0.062227488650822907 + 0.062230239187720457 + 0.062232989757533372 + 0.062235740360261659 + 0.062238490995905303 + 0.062241241664463896 + 0.062243992365937501 + 0.062246743100325935 + 0.062249493867629076 + 0.062252244667846776 + 0.062254995500978877 + 0.062257746367025323 + 0.062260497265985933 + 0.062263248197860513 + 0.062265999162649036 + 0.062268750160351348 + 0.06227150119096727 + 0.062274252254496752 + 0.062277003350939525 + 0.062279754480295643 + 0.062282505642564753 + 0.06228525683774689 + 0.062288008065842032 + 0.062290759326849833 + 0.062293510620770175 + 0.062296261947603036 + 0.062299013307348348 + 0.062301764700005709 + 0.062304516125575277 + 0.062307267584056733 + 0.062310019075450078 + 0.062312770599755159 + 0.062315522156971809 + 0.062318273747099841 + 0.062321025370139331 + 0.062323777026090009 + 0.062326528714951722 + 0.062329280436724435 + 0.062332032191407989 + 0.06233478397900228 + 0.062337535799507113 + 0.062340287652922488 + 0.062343039539248114 + 0.06234579145848395 + 0.062348543410629967 + 0.062351295395685936 + 0.062354047413651748 + 0.062356799464527192 + 0.062359551548312415 + 0.062362303665007057 + 0.062365055814611041 + 0.062367807997124304 + 0.062370560212546701 + 0.062373312460878058 + 0.062376064742118376 + 0.062378817056267417 + 0.062381569403325142 + 0.062384321783291258 + 0.062387074196165945 + 0.062389826641948871 + 0.062392579120639925 + 0.062395331632239107 + 0.062398084176746145 + 0.062400836754161103 + 0.062403589364483744 + 0.062406342007713916 + 0.062409094683851578 + 0.062411847392896624 + 0.062414600134848855 + 0.062417352909708214 + 0.062420105717474646 + 0.062422858558147942 + 0.062425611431727979 + 0.062428364338214706 + 0.062431117277608035 + 0.062433870249907757 + 0.062436623255113781 + 0.062439376293226032 + 0.062442129364244342 + 0.062444882468168698 + 0.062447635604998823 + 0.062450388774734876 + 0.062453141977376489 + 0.062455895212923621 + 0.062458648481376118 + 0.062461401782733975 + 0.062464155116997107 + 0.062466908484165244 + 0.062469661884238387 + 0.062472415317216409 + 0.062475168783099201 + 0.06247792228188661 + 0.062480675813578669 + 0.06248342937817504 + 0.062486182975675757 + 0.062488936606080667 + 0.062491690269389853 + 0.062494443965602858 + 0.062497197694719842 + 0.062499951456740574 + 0.062502705251665014 + 0.062505459079492995 + 0.062508212940224475 + 0.06251096683385933 + 0.062513720760397434 + 0.062516474719838691 + 0.062519228712183017 + 0.06252198273743019 + 0.062524736795580196 + 0.06252749088663305 + 0.062530245010588514 + 0.062532999167446465 + 0.062535753357206847 + 0.062538507579869534 + 0.062541261835434486 + 0.06254401612390148 + 0.062546770445270572 + 0.062549524799541498 + 0.062552279186714285 + 0.062555033606788685 + 0.062557788059764863 + 0.062560542545642417 + 0.062563297064421403 + 0.062566051616101667 + 0.062568806200683155 + 0.0625715608181657 + 0.062574315468549316 + 0.062577070151833836 + 0.062579824868019149 + 0.062582579617105144 + 0.062585334399091752 + 0.062588089213978931 + 0.062590844061766529 + 0.062593598942454351 + 0.062596353856042425 + 0.062599108802530598 + 0.062601863781918815 + 0.062604618794206993 + 0.062607373839395034 + 0.062610128917482813 + 0.062612884028470095 + 0.062615639172357088 + 0.062618394349143403 + 0.06262114955882922 + 0.062623904801414193 + 0.062626660076898419 + 0.062629415385281592 + 0.06263217072656381 + 0.062634926100744934 + 0.062637681507824866 + 0.06264043694780351 + 0.062643192420680699 + 0.062645947926456461 + 0.062648703465130642 + 0.062651459036703189 + 0.062654214641173878 + 0.062656970278542806 + 0.062659725948809822 + 0.062662481651974716 + 0.062665237388037531 + 0.062667993156998225 + 0.062670748958856534 + 0.062673504793612458 + 0.062676260661265901 + 0.062679016561816819 + 0.06268177249526509 + 0.062684528461610531 + 0.062687284460853268 + 0.06269004049299301 + 0.062692796558029812 + 0.062695552655963452 + 0.062698308786793999 + 0.062701064950521163 + 0.062703821147145039 + 0.062706577376665518 + 0.062709333639082487 + 0.062712089934395795 + 0.062714846262605387 + 0.062717602623711302 + 0.062720359017713292 + 0.062723115444611371 + 0.0627258719044054 + 0.062728628397095296 + 0.062731384922681016 + 0.06273414148116245 + 0.062736898072539571 + 0.062739654696812225 + 0.062742411353980315 + 0.062745168044043786 + 0.062747924767002666 + 0.062750681522856705 + 0.062753438311605944 + 0.06275619513325012 + 0.062758951987789427 + 0.062761708875223601 + 0.062764465795552615 + 0.062767222748776344 + 0.062769979734894774 + 0.062772736753907779 + 0.062775493805815263 + 0.06277825089061724 + 0.062781008008313474 + 0.062783765158904145 + 0.062786522342388809 + 0.062789279558767772 + 0.062792036808040672 + 0.06279479409020762 + 0.062797551405268409 + 0.062800308753223039 + 0.062803066134071384 + 0.062805823547813402 + 0.062808580994448998 + 0.06281133847397817 + 0.062814095986400628 + 0.062816853531716593 + 0.06281961110992583 + 0.062822368721028199 + 0.062825126365023756 + 0.062827884041912363 + 0.062830641751694005 + 0.062833399494368558 + 0.062836157269935966 + 0.062838915078396076 + 0.062841672919748931 + 0.062844430793994516 + 0.062847188701132511 + 0.062849946641163085 + 0.062852704614086111 + 0.062855462619901367 + 0.062858220658608951 + 0.06286097873020878 + 0.062863736834700715 + 0.062866494972084755 + 0.062869253142360734 + 0.062872011345528694 + 0.062874769581588524 + 0.062877527850540113 + 0.062880286152383502 + 0.062883044487118456 + 0.062885802854744974 + 0.06288856125526314 + 0.062891319688672634 + 0.062894078154973623 + 0.062896836654165858 + 0.06289959518624938 + 0.062902353751224091 + 0.062905112349089951 + 0.062907870979846806 + 0.062910629643494767 + 0.062913388340033599 + 0.06291614706946326 + 0.062918905831783778 + 0.062921664626994889 + 0.062924423455096926 + 0.062927182316089333 + 0.062929941209972473 + 0.062932700136745956 + 0.062935459096409949 + 0.062938218088964257 + 0.062940977114408866 + 0.062943736172743764 + 0.062946495263968755 + 0.062949254388083922 + 0.062952013545089211 + 0.062954772734984288 + 0.062957531957769403 + 0.062960291213444514 + 0.062963050502009288 + 0.062965809823463836 + 0.06296856917780809 + 0.062971328565042006 + 0.062974087985165489 + 0.062976847438178468 + 0.062979606924080958 + 0.062982366442872778 + 0.06298512599455397 + 0.062987885579124492 + 0.062990645196584288 + 0.062993404846933124 + 0.062996164530171164 + 0.06299892424629823 + 0.063001683995314334 + 0.063004443777219338 + 0.063007203592013325 + 0.063009963439696115 + 0.063012723320267625 + 0.063015483233727965 + 0.063018243180076913 + 0.06302100315931447 + 0.063023763171440705 + 0.06302652321645541 + 0.063029283294358529 + 0.063032043405150034 + 0.06303480354883001 + 0.06303756372539826 + 0.063040323934854758 + 0.063043084177199449 + 0.063045844452432276 + 0.063048604760553253 + 0.063051365101562229 + 0.063054125475459244 + 0.063056885882244229 + 0.063059646321917046 + 0.063062406794477777 + 0.063065167299926256 + 0.063067927838262497 + 0.063070688409486514 + 0.063073449013598112 + 0.063076209650597362 + 0.063078970320484151 + 0.063081731023258383 + 0.063084491758920211 + 0.063087252527469342 + 0.063090013328905889 + 0.06309277416322974 + 0.063095535030440922 + 0.063098295930539325 + 0.063101056863524949 + 0.063103817829397585 + 0.063106578828157373 + 0.063109339859804256 + 0.06311210092433811 + 0.063114862021758977 + 0.063117623152066732 + 0.063120384315261374 + 0.063123145511342807 + 0.063125906740311086 + 0.063128668002165989 + 0.063131429296907737 + 0.063134190624536027 + 0.063136951985051051 + 0.063139713378452589 + 0.063142474804740598 + 0.063145236263915175 + 0.063147997755976237 + 0.063150759280923674 + 0.06315352083875754 + 0.063156282429477614 + 0.063159044053084035 + 0.063161805709576732 + 0.063164567398955665 + 0.063167329121220681 + 0.063170090876371876 + 0.063172852664409238 + 0.06317561448533264 + 0.063178376339142014 + 0.063181138225837347 + 0.063183900145418678 + 0.063186662097885871 + 0.063189424083239007 + 0.063192186101477962 + 0.063194948152602654 + 0.063197710236613178 + 0.063200472353509354 + 0.063203234503291295 + 0.06320599668595886 + 0.063208758901512049 + 0.063211521149950822 + 0.063214283431275151 + 0.063217045745485076 + 0.063219808092580376 + 0.06322257047256119 + 0.063225332885427449 + 0.063228095331179068 + 0.063230857809816021 + 0.063233620321338294 + 0.063236382865745844 + 0.063239145443038755 + 0.063241908053216736 + 0.063244670696280036 + 0.063247433372228434 + 0.063250196081062013 + 0.063252958822780703 + 0.063255721597384421 + 0.06325848440487318 + 0.063261247245246982 + 0.063264010118505798 + 0.063266773024649531 + 0.063269535963678208 + 0.063272298935591817 + 0.063275061940390204 + 0.063277824978073466 + 0.063280588048641645 + 0.063283351152094464 + 0.063286114288432158 + 0.063288877457654505 + 0.063291640659761672 + 0.063294403894753437 + 0.063297167162629883 + 0.063299930463390941 + 0.063302693797036569 + 0.06330545716356685 + 0.06330822056298166 + 0.063310983995280998 + 0.063313747460464906 + 0.063316510958533287 + 0.063319274489486085 + 0.063322038053323274 + 0.063324801650044907 + 0.06332756527965093 + 0.063330328942141342 + 0.063333092637516131 + 0.063335856365775212 + 0.063338620126918571 + 0.063341383920946279 + 0.063344147747858168 + 0.063346911607654335 + 0.063349675500334698 + 0.06335243942589934 + 0.063355203384348094 + 0.06335796737568096 + 0.063360731399898007 + 0.063363495456999222 + 0.063366259546984535 + 0.063369023669853849 + 0.063371787825607304 + 0.063374552014244745 + 0.063377316235766271 + 0.063380080490171825 + 0.063382844777461284 + 0.063385609097634771 + 0.06338837345069219 + 0.063391137836633554 + 0.063393902255458892 + 0.063396666707168037 + 0.063399431191761196 + 0.063402195709238246 + 0.063404960259599102 + 0.063407724842843849 + 0.063410489458972305 + 0.063413254107984707 + 0.063416018789880887 + 0.063418783504660889 + 0.063421548252324614 + 0.063424313032872146 + 0.063427077846303442 + 0.063429842692618421 + 0.063432607571817207 + 0.06343537248389966 + 0.063438137428865823 + 0.063440902406715752 + 0.063443667417449279 + 0.063446432461066529 + 0.063449197537567434 + 0.063451962646951951 + 0.063454727789220108 + 0.063457492964371948 + 0.063460258172407386 + 0.063463023413326394 + 0.063465788687129099 + 0.06346855399381536 + 0.06347131933338529 + 0.063474084705838665 + 0.063476850111175653 + 0.063479615549396198 + 0.063482381020500356 + 0.063485146524488029 + 0.063487912061359245 + 0.063490677631114018 + 0.063493443233752278 + 0.063496208869274068 + 0.063498974537679428 + 0.063501740238968249 + 0.063504505973140626 + 0.063507271740196519 + 0.063510037540135802 + 0.063512803372958643 + 0.063515569238665012 + 0.063518335137254842 + 0.063521101068728159 + 0.063523867033084963 + 0.063526633030325269 + 0.063529399060448979 + 0.063532165123456205 + 0.063534931219346974 + 0.063537697348121119 + 0.063540463509778808 + 0.063543229704319845 + 0.063545995931744439 + 0.06354876219205248 + 0.06355152848524398 + 0.06355429481131894 + 0.063557061170277387 + 0.063559827562119323 + 0.063562593986844648 + 0.063565360444453559 + 0.063568126934945846 + 0.063570893458321676 + 0.063573660014580854 + 0.063576426603723674 + 0.063579193225749814 + 0.063581959880659483 + 0.06358472656845271 + 0.063587493289129396 + 0.063590260042689528 + 0.063593026829133162 + 0.063595793648460283 + 0.063598560500670961 + 0.063601327385765127 + 0.063604094303742767 + 0.063606861254604033 + 0.06360962823834862 + 0.063612395254976875 + 0.063615162304488632 + 0.063617929386883973 + 0.063620696502162857 + 0.063623463650325257 + 0.063626230831371255 + 0.063628998045300783 + 0.063631765292113854 + 0.063634532571810565 + 0.063637299884390874 + 0.06364006722985481 + 0.063642834608202359 + 0.063645602019433464 + 0.063648369463548224 + 0.06365113694054661 + 0.063653904450428622 + 0.063656671993194303 + 0.063659439568843734 + 0.063662207177376751 + 0.063664974818793532 + 0.063667742493093982 + 0.063670510200278099 + 0.063673277940345996 + 0.063676045713297644 + 0.063678813519132932 + 0.06368158135785211 + 0.063684349229454998 + 0.063687117133941734 + 0.063689885071312208 + 0.063692653041566558 + 0.063695421044704645 + 0.063698189080726664 + 0.063700957149632517 + 0.063703725251422219 + 0.063706493386095783 + 0.063709261553653307 + 0.063712029754094693 + 0.06371479798742008 + 0.063717566253629343 + 0.063720334552722704 + 0.063723102884699984 + 0.063725871249561195 + 0.063728639647306476 + 0.063731408077935758 + 0.063734176541449236 + 0.063736945037846687 + 0.063739713567128195 + 0.063742482129293843 + 0.063745250724343616 + 0.063748019352277571 + 0.06375078801309568 + 0.06375355670679797 + 0.063756325433384525 + 0.06375909419285522 + 0.06376186298521018 + 0.06376463181044946 + 0.063767400668572963 + 0.063770169559580772 + 0.063772938483472999 + 0.063775707440249532 + 0.063778476429910469 + 0.063781245452455768 + 0.063784014507885484 + 0.063786783596199714 + 0.063789552717398307 + 0.063792321871481497 + 0.063795091058449133 + 0.063797860278301394 + 0.063800629531038128 + 0.063803398816659515 + 0.063806168135165542 + 0.063808937486556153 + 0.063811706870831472 + 0.063814476287991431 + 0.06381724573803621 + 0.063820015220965615 + 0.063822784736779839 + 0.063825554285478897 + 0.06382832386706272 + 0.063831093481531445 + 0.063833863128885004 + 0.063836632809123564 + 0.06383940252224693 + 0.063842172268255379 + 0.063844942047148773 + 0.063847711858927236 + 0.063850481703590742 + 0.063853251581139317 + 0.063856021491573045 + 0.063858791434891843 + 0.063861561411095849 + 0.063864331420185008 + 0.063867101462159445 + 0.063869871537019202 + 0.063872641644764208 + 0.063875411785394548 + 0.063878181958910346 + 0.063880952165311436 + 0.063883722404597956 + 0.063886492676769976 + 0.063889262981827483 + 0.063892033319770516 + 0.06389480369059912 + 0.06389757409431332 + 0.063900344530913131 + 0.063903115000398608 + 0.063905885502769808 + 0.063908656038026729 + 0.063911426606169414 + 0.063914197207197931 + 0.063916967841112282 + 0.063919738507912591 + 0.063922509207598704 + 0.063925279940170804 + 0.063928050705628903 + 0.063930821503972987 + 0.063933592335203238 + 0.063936363199319515 + 0.063939134096321945 + 0.063941905026210555 + 0.063944675988985372 + 0.063947446984646508 + 0.063950218013193866 + 0.063952989074627625 + 0.063955760168947731 + 0.063958531296154211 + 0.063961302456247204 + 0.063964073649226696 + 0.063966844875092702 + 0.063969616133845317 + 0.0639723874254845 + 0.063975158750010433 + 0.063977930107422976 + 0.063980701497722392 + 0.063983472920908516 + 0.063986244376981485 + 0.063989015865941301 + 0.063991787387788102 + 0.063994558942521818 + 0.063997330530142504 + 0.064000102150650315 + 0.064002873804045166 + 0.064005645490327195 + 0.064008417209496474 + 0.064011188961552917 + 0.064013960746496651 + 0.064016732564327661 + 0.064019504415046058 + 0.064022276298651926 + 0.064025048215145236 + 0.064027820164525989 + 0.064030592146794421 + 0.064033364161950379 + 0.06403613620999403 + 0.064038908290925331 + 0.064041680404744394 + 0.064044452551451289 + 0.064047224731046015 + 0.0640499969435286 + 0.064052769188899156 + 0.064055541467157695 + 0.064058313778304329 + 0.064061086122339017 + 0.064063858499261842 + 0.0640666309090729 + 0.064069403351772233 + 0.064072175827359745 + 0.064074948335835755 + 0.064077720877200067 + 0.064080493451452808 + 0.064083266058594185 + 0.064086038698624018 + 0.064088811371542501 + 0.064091584077349661 + 0.0640943568160455 + 0.0640971295876301 + 0.064099902392103586 + 0.064102675229465986 + 0.064105448099717244 + 0.064108221002857582 + 0.064110993938886848 + 0.064113766907805292 + 0.064116539909612899 + 0.064119312944309698 + 0.064122086011895743 + 0.064124859112371119 + 0.064127632245735963 + 0.06413040541199011 + 0.064133178611133906 + 0.064135951843167213 + 0.064138725108090072 + 0.064141498405902567 + 0.064144271736604933 + 0.064147045100196989 + 0.064149818496678959 + 0.064152591926050759 + 0.064155365388312596 + 0.064158138883464472 + 0.064160912411506371 + 0.064163685972438461 + 0.064166459566260714 + 0.064169233192973241 + 0.064172006852576152 + 0.064174780545069379 + 0.064177554270453158 + 0.064180328028727349 + 0.064183101819892202 + 0.064185875643947649 + 0.064188649500893827 + 0.064191423390730792 + 0.064194197313458559 + 0.064196971269077141 + 0.064199745257586788 + 0.064202519278987388 + 0.064205293333279137 + 0.064208067420462006 + 0.06421084154053612 + 0.06421361569350155 + 0.064216389879358224 + 0.064219164098106393 + 0.064221938349745988 + 0.064224712634277092 + 0.064227486951699886 + 0.064230261302014327 + 0.064233035685220513 + 0.064235810101318513 + 0.064238584550308397 + 0.06424135903219029 + 0.064244133546964136 + 0.064246908094630073 + 0.06424968267518813 + 0.064252457288638487 + 0.064255231934981075 + 0.064258006614216087 + 0.064260781326343427 + 0.064263556071363373 + 0.064266330849275841 + 0.064269105660081038 + 0.064271880503778814 + 0.064274655380369472 + 0.064277430289852971 + 0.064280205232229382 + 0.064282980207498758 + 0.064285755215661322 + 0.06428853025671695 + 0.064291305330665807 + 0.064294080437507992 + 0.064296855577243475 + 0.064299630749872425 + 0.064302405955394951 + 0.064305181193811026 + 0.064307956465120733 + 0.064310731769324211 + 0.064313507106421516 + 0.064316282476412676 + 0.064319057879297814 + 0.064321833315076987 + 0.064324608783750306 + 0.064327384285317743 + 0.064330159819779548 + 0.064332935387135623 + 0.064335710987386191 + 0.064338486620531155 + 0.064341262286570805 + 0.064344037985505032 + 0.064346813717334042 + 0.064349589482057809 + 0.064352365279676541 + 0.064355141110190264 + 0.064357916973598925 + 0.064360692869902814 + 0.064363468799101833 + 0.064366244761196262 + 0.064369020756185946 + 0.06437179678407115 + 0.064374572844851916 + 0.064377348938528187 + 0.064380125065100269 + 0.064382901224568065 + 0.0643856774169317 + 0.064388453642191326 + 0.064391229900347 + 0.064394006191398748 + 0.064396782515346654 + 0.064399558872190871 + 0.064402335261931468 + 0.064405111684568458 + 0.064407888140102051 + 0.064410664628532191 + 0.064413441149859044 + 0.064416217704082721 + 0.064418994291203235 + 0.064421770911220658 + 0.064424547564135196 + 0.064427324249946807 + 0.064430100968655687 + 0.064432877720261766 + 0.06443565450476535 + 0.064438431322166312 + 0.064441208172464834 + 0.064443985055661054 + 0.06444676197175507 + 0.064449538920746813 + 0.064452315902636476 + 0.06445509291742417 + 0.06445786996510991 + 0.064460647045693903 + 0.064463424159176122 + 0.064466201305556692 + 0.064468978484835779 + 0.064471755697013369 + 0.064474532942089588 + 0.06447731022006449 + 0.064480087530938229 + 0.064482864874710957 + 0.064485642251382605 + 0.064488419660953325 + 0.064491197103423312 + 0.064493974578792482 + 0.064496752087061085 + 0.06449952962822908 + 0.06450230720229673 + 0.064505084809263979 + 0.064507862449130954 + 0.064510640121897805 + 0.064513417827564562 + 0.064516195566131321 + 0.06451897333759829 + 0.064521751141965372 + 0.064524528979232873 + 0.064527306849400695 + 0.064530084752469088 + 0.064532862688438025 + 0.064535640657307727 + 0.064538418659078139 + 0.064541196693749567 + 0.064543974761321857 + 0.064546752861795356 + 0.064549530995169982 + 0.064552309161445887 + 0.06455508736062314 + 0.064557865592701963 + 0.064560643857682357 + 0.064563422155564376 + 0.064566200486348119 + 0.064568978850033876 + 0.064571757246621606 + 0.064574535676111364 + 0.064577314138503317 + 0.06458009263379752 + 0.064582871161994182 + 0.064585649723093247 + 0.064588428317094992 + 0.064591206943999349 + 0.064593985603806539 + 0.064596764296516729 + 0.064599543022129738 + 0.064602321780645955 + 0.06460510057206531 + 0.064607879396388082 + 0.064610658253614159 + 0.064613437143743777 + 0.064616216066777088 + 0.064618995022714038 + 0.064621774011554944 + 0.064624553033299684 + 0.06462733208794845 + 0.06463011117550152 + 0.064632890295958673 + 0.06463566944932024 + 0.064638448635586362 + 0.064641227854756927 + 0.064644007106832269 + 0.064646786391812344 + 0.064649565709697362 + 0.064652345060487448 + 0.064655124444182518 + 0.064657903860782878 + 0.064660683310288555 + 0.064663462792699689 + 0.064666242308016403 + 0.064669021856238754 + 0.06467180143736688 + 0.064674581051400851 + 0.064677360698340874 + 0.064680140378186923 + 0.064682920090939233 + 0.064685699836597901 + 0.064688479615162983 + 0.064691259426634631 + 0.064694039271012929 + 0.064696819148298057 + 0.064699599058489918 + 0.064702379001588928 + 0.064705158977595045 + 0.064707938986508326 + 0.064710719028328922 + 0.064713499103057057 + 0.064716279210692715 + 0.064719059351236008 + 0.064721839524687214 + 0.064724619731046262 + 0.064727399970313362 + 0.064730180242488583 + 0.064732960547572091 + 0.064735740885563955 + 0.06473852125646426 + 0.064741301660273282 + 0.064744082096991021 + 0.064746862566617533 + 0.064749643069153026 + 0.064752423604597653 + 0.064755204172951414 + 0.064757984774214489 + 0.064760765408387072 + 0.06476354607546915 + 0.064766326775461 + 0.064769107508362525 + 0.064771888274173961 + 0.064774669072895502 + 0.064777449904527148 + 0.064780230769069122 + 0.064783011666521409 + 0.064785792596884259 + 0.064788573560157714 + 0.064791354556341954 + 0.064794135585437063 + 0.064796916647443248 + 0.064799697742360454 + 0.064802478870188918 + 0.064805260030928805 + 0.064808041224580185 + 0.064810822451143085 + 0.064813603710617812 + 0.064816385003004393 + 0.064819166328302924 + 0.064821947686513628 + 0.064824729077636506 + 0.064827510501671723 + 0.064830291958619529 + 0.064833073448479883 + 0.064835854971253007 + 0.064838636526938984 + 0.06484141811553798 + 0.064844199737050037 + 0.064846981391475433 + 0.064849763078814085 + 0.064852544799066283 + 0.06485532655223214 + 0.06485810833831171 + 0.064860890157305215 + 0.064863672009212711 + 0.064866453894034309 + 0.064869235811770259 + 0.064872017762420547 + 0.064874799745985368 + 0.064877581762464845 + 0.064880363811859146 + 0.064883145894168368 + 0.064885928009392677 + 0.064888710157532045 + 0.064891492338586806 + 0.06489427455255703 + 0.064897056799442798 + 0.064899839079244251 + 0.064902621391961623 + 0.064905403737594888 + 0.064908186116144295 + 0.064910968527609914 + 0.064913750971992007 + 0.064916533449290478 + 0.064919315959505688 + 0.064922098502637568 + 0.064924881078686436 + 0.064927663687652307 + 0.064930446329535402 + 0.064933229004335846 + 0.064936011712053668 + 0.064938794452689033 + 0.064941577226242261 + 0.064944360032713172 + 0.064947142872102223 + 0.064949925744409331 + 0.064952708649634761 + 0.064955491587778524 + 0.064958274558840984 + 0.064961057562822 + 0.064963840599721837 + 0.064966623669540646 + 0.064969406772278526 + 0.064972189907935643 + 0.06497497307651226 + 0.064977756278008295 + 0.064980539512423954 + 0.064983322779759448 + 0.064986106080014844 + 0.064988889413190365 + 0.064991672779286094 + 0.064994456178302198 + 0.064997239610238733 + 0.065000023075096017 + 0.065002806572873911 + 0.065005590103572874 + 0.065008373667192906 + 0.065011157263734104 + 0.065013940893196648 + 0.065016724555580746 + 0.06501950825088644 + 0.065022291979113869 + 0.065025075740263283 + 0.065027859534334806 + 0.065030643361328508 + 0.065033427221244583 + 0.065036211114083087 + 0.065038995039844352 + 0.06504177899852838 + 0.065044562990135377 + 0.065047347014665413 + 0.065050131072118711 + 0.065052915162495423 + 0.065055699285795604 + 0.065058483442019505 + 0.065061267631167263 + 0.065064051853238936 + 0.065066836108234757 + 0.06506962039615484 + 0.06507240471699928 + 0.065075189070768438 + 0.065077973457462218 + 0.065080757877080841 + 0.06508354232962453 + 0.065086326815093382 + 0.065089111333487562 + 0.065091895884807224 + 0.065094680469052466 + 0.065097465086223397 + 0.06510024973632042 + 0.06510303441934337 + 0.065105819135292634 + 0.065108603884168212 + 0.065111388665970368 + 0.0651141734806992 + 0.065116958328354818 + 0.065119743208937472 + 0.065122528122447274 + 0.065125313068884361 + 0.065128098048248845 + 0.065130883060541031 + 0.065133668105760864 + 0.065136453183908621 + 0.065139238294984511 + 0.06514202343898863 + 0.065144808615921049 + 0.065147593825782085 + 0.065150379068571768 + 0.065153164344290276 + 0.065155949652937778 + 0.065158734994514494 + 0.065161520369020495 + 0.065164305776456044 + 0.065167091216821141 + 0.065169876690116008 + 0.065172662196340866 + 0.065175447735495926 + 0.065178233307581074 + 0.065181018912596742 + 0.065183804550543026 + 0.065186590221419941 + 0.065189375925227805 + 0.06519216166196673 + 0.065194947431637021 + 0.065197733234238497 + 0.065200519069771659 + 0.065203304938236437 + 0.065206090839633093 + 0.065208876773961838 + 0.06521166274122274 + 0.065214448741415965 + 0.065217234774541721 + 0.065220020840600218 + 0.06522280693959151 + 0.065225593071515833 + 0.065228379236373285 + 0.065231165434164101 + 0.06523395166488842 + 0.065236737928546312 + 0.065239524225138165 + 0.065242310554663896 + 0.065245096917123852 + 0.065247883312518129 + 0.065250669740846784 + 0.065253456202110219 + 0.065256242696308434 + 0.065259029223441692 + 0.065261815783510049 + 0.065264602376513686 + 0.065267389002452839 + 0.065270175661327645 + 0.065272962353138342 + 0.065275749077884998 + 0.065278535835567753 + 0.065281322626186869 + 0.065284109449742542 + 0.065286896306234743 + 0.065289683195663875 + 0.065292470118030035 + 0.065295257073333293 + 0.065298044061573995 + 0.065300831082752142 + 0.065303618136867969 + 0.065306405223921685 + 0.0653091923439134 + 0.065311979496843295 + 0.06531476668271162 + 0.065317553901518458 + 0.065320341153264086 + 0.065323128437948491 + 0.065325915755572048 + 0.065328703106134783 + 0.065331490489636948 + 0.065334277906078653 + 0.065337065355460119 + 0.065339852837781626 + 0.065342640353043158 + 0.065345427901244951 + 0.065348215482387215 + 0.065351003096470073 + 0.065353790743493831 + 0.065356578423458545 + 0.065359366136364366 + 0.065362153882211504 + 0.065364941661000223 + 0.065367729472730521 + 0.065370517317402746 + 0.065373305195017134 + 0.065376093105573602 + 0.065378881049072496 + 0.065381669025513969 + 0.065384457034898175 + 0.065387245077225389 + 0.065390033152495614 + 0.065392821260709152 + 0.065395609401866187 + 0.065398397575966827 + 0.065401185783011365 + 0.065403974022999856 + 0.065406762295932563 + 0.065409550601809724 + 0.065412338940631337 + 0.065415127312397695 + 0.065417915717108976 + 0.065420704154765363 + 0.065423492625367022 + 0.065426281128914146 + 0.065429069665406903 + 0.065431858234845527 + 0.065434646837230132 + 0.065437435472560965 + 0.06544022414083811 + 0.06544301284206186 + 0.065445801576232365 + 0.065448590343349766 + 0.065451379143414368 + 0.065454167976426184 + 0.065456956842385491 + 0.065459745741292485 + 0.065462534673147402 + 0.065465323637950268 + 0.065468112635701389 + 0.065470901666400946 + 0.065473690730049092 + 0.065476479826645992 + 0.06547926895619198 + 0.065482058118687056 + 0.06548484731413147 + 0.065487636542525443 + 0.065490425803869198 + 0.065493215098162819 + 0.065496004425406554 + 0.065498793785600667 + 0.065501583178745146 + 0.065504372604840322 + 0.065507162063886432 + 0.065509951555883586 + 0.065512741080831979 + 0.065515530638731806 + 0.06551832022958326 + 0.065521109853386536 + 0.0655238995101418 + 0.065526689199849344 + 0.065529478922509182 + 0.065532268678121702 + 0.06553505846668696 + 0.065537848288205303 + 0.065540638142676702 + 0.065543428030101464 + 0.065546217950479727 + 0.065549007903811851 + 0.065551797890097907 + 0.065554587909338075 + 0.065557377961532562 + 0.065560168046681619 + 0.065562958164785301 + 0.065565748315844066 + 0.065568538499857901 + 0.065571328716826957 + 0.065574118966751527 + 0.065576909249631915 + 0.065579699565468177 + 0.065582489914260522 + 0.065585280296009088 + 0.065588070710714319 + 0.065590861158376063 + 0.065593651638994777 + 0.06559644215257053 + 0.065599232699103657 + 0.065602023278594254 + 0.065604813891042529 + 0.065607604536448719 + 0.065610395214812892 + 0.065613185926135423 + 0.065615976670416437 + 0.065618767447656198 + 0.065621558257854776 + 0.065624349101012502 + 0.065627139977129448 + 0.065629930886205945 + 0.065632721828242077 + 0.06563551280323815 + 0.065638303811194287 + 0.065641094852110796 + 0.065643885925987758 + 0.065646677032825451 + 0.065649468172624056 + 0.065652259345383768 + 0.065655050551104821 + 0.065657841789787355 + 0.065660633061431689 + 0.065663424366037948 + 0.065666215703606284 + 0.06566900707413699 + 0.065671798477630244 + 0.065674589914086298 + 0.065677381383505248 + 0.065680172885887483 + 0.065682964421232878 + 0.065685755989542058 + 0.065688547590814939 + 0.065691339225051909 + 0.065694130892252997 + 0.065696922592418522 + 0.065699714325548608 + 0.065702506091643603 + 0.065705297890703604 + 0.06570808972272886 + 0.065710881587719594 + 0.065713673485676027 + 0.065716465416598313 + 0.065719257380486618 + 0.065722049377341232 + 0.06572484140716249 + 0.065727633469950336 + 0.065730425565705117 + 0.065733217694427054 + 0.06573600985611644 + 0.065738802050773301 + 0.065741594278397888 + 0.065744386538990549 + 0.06574717883255142 + 0.065749971159080656 + 0.065752763518578561 + 0.065755555911045288 + 0.065758348336481115 + 0.065761140794886208 + 0.065763933286260706 + 0.06576672581060497 + 0.065769518367919139 + 0.065772310958203489 + 0.065775103581458091 + 0.065777896237683334 + 0.065780688926879299 + 0.065783481649046252 + 0.065786274404184455 + 0.065789067192294076 + 0.065791860013375308 + 0.065794652867428416 + 0.065797445754453621 + 0.065800238674451117 + 0.065803031627421182 + 0.065805824613363845 + 0.065808617632279576 + 0.065811410684168417 + 0.065814203769030688 + 0.065816996886866541 + 0.065819790037676254 + 0.065822583221459924 + 0.065825376438217939 + 0.065828169687950466 + 0.06583096297065763 + 0.065833756286339792 + 0.065836549634997091 + 0.065839343016629706 + 0.065842136431237971 + 0.065844929878822026 + 0.065847723359382146 + 0.065850516872918471 + 0.065853310419431377 + 0.065856103998920945 + 0.065858897611387371 + 0.065861691256831001 + 0.06586448493525203 + 0.065867278646650637 + 0.065870072391027046 + 0.065872866168381547 + 0.065875659978714307 + 0.065878453822025548 + 0.065881247698315659 + 0.06588404160758457 + 0.065886835549832684 + 0.065889629525060195 + 0.065892423533267311 + 0.065895217574454337 + 0.065898011648621455 + 0.065900805755768829 + 0.065903599895896753 + 0.065906394069005503 + 0.06590918827509519 + 0.06591198251416612 + 0.065914776786218487 + 0.065917571091252555 + 0.065920365429268574 + 0.06592315980026657 + 0.065925954204247073 + 0.065928748641210094 + 0.065931543111156038 + 0.065934337614084973 + 0.065937132149997163 + 0.065939926718892941 + 0.065942721320772502 + 0.065945515955635997 + 0.065948310623483664 + 0.065951105324315792 + 0.065953900058132592 + 0.065956694824934381 + 0.065959489624721215 + 0.065962284457493442 + 0.065965079323251324 + 0.065967874221995029 + 0.065970669153724792 + 0.065973464118440892 + 0.065976259116143479 + 0.065979054146832861 + 0.065981849210509314 + 0.06598464430717299 + 0.065987439436824141 + 0.065990234599463043 + 0.065993029795089891 + 0.065995825023704907 + 0.06599862028530834 + 0.066001415579900385 + 0.066004210907481403 + 0.06600700626805163 + 0.066009801661611078 + 0.066012597088160277 + 0.066015392547699323 + 0.066018188040228395 + 0.066020983565747732 + 0.06602377912425772 + 0.066026574715758499 + 0.06602937034025029 + 0.066032165997733441 + 0.066034961688208091 + 0.066037757411674503 + 0.066040553168132898 + 0.066043348957583556 + 0.066046144780026683 + 0.06604894063546253 + 0.066051736523891347 + 0.066054532445313396 + 0.066057328399728873 + 0.066060124387138069 + 0.066062920407541165 + 0.066065716460938437 + 0.066068512547330219 + 0.066071308666716649 + 0.066074104819097895 + 0.066076901004474331 + 0.066079697222846207 + 0.066082493474213633 + 0.066085289758577054 + 0.066088086075936567 + 0.066090882426292394 + 0.066093678809644951 + 0.066096475225994225 + 0.06609927167534066 + 0.06610206815768456 + 0.066104864673025968 + 0.066107661221365285 + 0.066110457802702596 + 0.066113254417038358 + 0.066116051064372683 + 0.066118847744705847 + 0.066121644458038045 + 0.066124441204369597 + 0.06612723798370071 + 0.066130034796031675 + 0.066132831641362758 + 0.066135628519694192 + 0.06613842543102616 + 0.066141222375358966 + 0.06614401935269279 + 0.066146816363028049 + 0.066149613406364827 + 0.066152410482703428 + 0.066155207592044157 + 0.066158004734387141 + 0.066160801909732739 + 0.066163599118081159 + 0.066166396359432736 + 0.066169193633787649 + 0.066171990941146092 + 0.066174788281508301 + 0.066177585654874777 + 0.06618038306124556 + 0.066183180500620928 + 0.066185977973001145 + 0.066188775478386488 + 0.066191573016777111 + 0.066194370588173471 + 0.066197168192575706 + 0.066199965829984053 + 0.06620276350039872 + 0.066205561203820096 + 0.066208358940248388 + 0.066211156709683805 + 0.06621395451212661 + 0.06621675234757711 + 0.066219550216035525 + 0.066222348117502161 + 0.066225146051977157 + 0.066227944019460847 + 0.066230742019953631 + 0.066233540053455497 + 0.066236338119966931 + 0.066239136219488071 + 0.066241934352019097 + 0.066244732517560495 + 0.066247530716112349 + 0.066250328947675005 + 0.066253127212248672 + 0.06625592550983353 + 0.066258723840430037 + 0.066261522204038456 + 0.06626432060065876 + 0.066267119030291449 + 0.0662699174929368 + 0.066272715988594938 + 0.066275514517266265 + 0.066278313078950921 + 0.066281111673649237 + 0.066283910301361423 + 0.066286708962087854 + 0.066289507655828597 + 0.066292306382584182 + 0.066295105142354663 + 0.066297903935140373 + 0.066300702760941521 + 0.066303501619758509 + 0.06630630051159149 + 0.066309099436440699 + 0.066311898394306526 + 0.066314697385189109 + 0.066317496409088822 + 0.066320295466005902 + 0.066323094555940543 + 0.066325893678893105 + 0.066328692834863826 + 0.066331492023853036 + 0.06633429124586071 + 0.066337090500887527 + 0.066339889788933459 + 0.066342689109998965 + 0.066345488464084154 + 0.066348287851189403 + 0.066351087271314946 + 0.066353886724461048 + 0.06635668621062793 + 0.066359485729816023 + 0.066362285282025466 + 0.066365084867256549 + 0.066367884485509482 + 0.066370684136784638 + 0.066373483821082255 + 0.066376283538402664 + 0.066379083288746032 + 0.066381883072112555 + 0.066384682888502813 + 0.066387482737916809 + 0.066390282620354915 + 0.066393082535817313 + 0.066395882484304364 + 0.066398682465816372 + 0.066401482480353574 + 0.06640428252791622 + 0.066407082608504545 + 0.066409882722118951 + 0.066412682868759537 + 0.066415483048426815 + 0.06641828326112087 + 0.066421083506842019 + 0.066423883785590582 + 0.066426684097366767 + 0.066429484442170908 + 0.066432284820003282 + 0.066435085230864124 + 0.066437885674753672 + 0.06644068615167234 + 0.066443486661620338 + 0.066446287204597929 + 0.066449087780605362 + 0.066451888389643041 + 0.066454689031711089 + 0.066457489706809897 + 0.06646029041493963 + 0.066463091156100662 + 0.0664658919302933 + 0.066468692737517723 + 0.066471493577774141 + 0.066474294451063121 + 0.066477095357384774 + 0.066479896296739352 + 0.066482697269127145 + 0.066485498274548457 + 0.066488299313003582 + 0.066491100384492768 + 0.066493901489016419 + 0.066496702626574589 + 0.066499503797167792 + 0.066502305000796152 + 0.066505106237460046 + 0.066507907507159611 + 0.066510708809895347 + 0.066513510145667448 + 0.066516311514476179 + 0.066519112916321788 + 0.066521914351204608 + 0.066524715819124933 + 0.066527517320083052 + 0.066530318854079173 + 0.066533120421113673 + 0.066535922021186772 + 0.066538723654298859 + 0.066541525320450143 + 0.066544327019640817 + 0.066547128751871312 + 0.066549930517141948 + 0.066552732315452903 + 0.066555534146804471 + 0.066558336011197053 + 0.06656113790863076 + 0.066563939839106009 + 0.066566741802623106 + 0.066569543799182201 + 0.066572345828783686 + 0.066575147891427933 + 0.06657794998711504 + 0.066580752115845437 + 0.066583554277619361 + 0.066586356472437047 + 0.066589158700298981 + 0.06659196096120526 + 0.066594763255156314 + 0.066597565582152254 + 0.066600367942193484 + 0.066603170335280348 + 0.066605972761413099 + 0.066608775220591929 + 0.066611577712817296 + 0.066614380238089368 + 0.066617182796408519 + 0.066619985387774999 + 0.066622788012189113 + 0.066625590669651222 + 0.066628393360161436 + 0.066631196083720229 + 0.066633998840327793 + 0.066636801629984574 + 0.066639604452690626 + 0.06664240730844645 + 0.066645210197252253 + 0.066648013119108396 + 0.06665081607401506 + 0.066653619061972591 + 0.066656422082981392 + 0.066659225137041658 + 0.066662028224153694 + 0.066664831344317735 + 0.066667634497534295 + 0.066670437683803402 + 0.066673240903125486 + 0.066676044155500935 + 0.066678847440929917 + 0.066681650759412792 + 0.066684454110949851 + 0.066687257495541261 + 0.066690060913187563 + 0.066692864363888854 + 0.066695667847645537 + 0.066698471364457959 + 0.066701274914326286 + 0.066704078497250963 + 0.066706882113232183 + 0.066709685762270307 + 0.066712489444365655 + 0.066715293159518352 + 0.066718096907728994 + 0.066720900688997636 + 0.066723704503324627 + 0.066726508350710451 + 0.06672931223115515 + 0.066732116144659223 + 0.066734920091223005 + 0.066737724070846549 + 0.06674052808353044 + 0.066743332129274746 + 0.066746136208079995 + 0.066748940319946326 + 0.066751744464874155 + 0.06675454864286362 + 0.066757352853915222 + 0.066760157098029155 + 0.066762961375205807 + 0.066765765685445413 + 0.066768570028748336 + 0.066771374405114867 + 0.066774178814545268 + 0.066776983257039846 + 0.066779787732598975 + 0.066782592241222974 + 0.066785396782912093 + 0.066788201357666652 + 0.066791005965486983 + 0.066793810606373349 + 0.066796615280326085 + 0.066799419987345565 + 0.066802224727431997 + 0.066805029500585783 + 0.06680783430680716 + 0.066810639146096459 + 0.066813444018454002 + 0.066816248923880134 + 0.066819053862375077 + 0.066821858833939277 + 0.066824663838572967 + 0.066827468876276414 + 0.066830273947050031 + 0.066833079050894098 + 0.066835884187808864 + 0.066838689357794648 + 0.066841494560851866 + 0.066844299796980797 + 0.066847105066181592 + 0.066849910368454946 + 0.066852715703800761 + 0.066855521072219606 + 0.066858326473711635 + 0.066861131908277319 + 0.066863937375916865 + 0.066866742876630636 + 0.066869548410418964 + 0.06687235397728214 + 0.066875159577220483 + 0.066877965210234258 + 0.066880770876323908 + 0.066883576575489656 + 0.066886382307731876 + 0.066889188073050762 + 0.066891993871446717 + 0.066894799702920144 + 0.066897605567471277 + 0.066900411465100437 + 0.066903217395807957 + 0.066906023359594155 + 0.066908829356459337 + 0.066911635386403864 + 0.066914441449427944 + 0.066917247545532077 + 0.066920053674716429 + 0.066922859836981458 + 0.066925666032327372 + 0.066928472260754462 + 0.066931278522263216 + 0.066934084816853812 + 0.06693689114452657 + 0.066939697505281948 + 0.066942503899120223 + 0.066945310326041563 + 0.066948116786046508 + 0.066950923279135294 + 0.066953729805308171 + 0.066956536364565541 + 0.066959342956907725 + 0.066962149582335054 + 0.06696495624084782 + 0.066967762932446356 + 0.066970569657131024 + 0.066973376414902169 + 0.066976183205759973 + 0.066978990029704935 + 0.06698179688673736 + 0.066984603776857429 + 0.066987410700065642 + 0.066990217656362233 + 0.066993024645747537 + 0.066995831668221928 + 0.066998638723785614 + 0.06700144581243915 + 0.067004252934182648 + 0.067007060089016496 + 0.067009867276941179 + 0.067012674497956753 + 0.067015481752063705 + 0.067018289039262394 + 0.067021096359553042 + 0.067023903712936053 + 0.067026711099411759 + 0.067029518518980494 + 0.067032325971642576 + 0.067035133457398421 + 0.067037940976248114 + 0.067040748528192237 + 0.067043556113231026 + 0.067046363731364869 + 0.067049171382593975 + 0.067051979066918843 + 0.067054786784339626 + 0.067057594534856782 + 0.067060402318470644 + 0.067063210135181531 + 0.06706601798498979 + 0.067068825867895671 + 0.06707163378389959 + 0.067074441733001783 + 0.067077249715202764 + 0.06708005773050274 + 0.067082865778902032 + 0.067085673860401054 + 0.067088481975000142 + 0.067091290122699598 + 0.067094098303499744 + 0.067096906517400939 + 0.067099714764403504 + 0.067102523044507811 + 0.067105331357714126 + 0.067108139704022921 + 0.067110948083434457 + 0.067113756495949015 + 0.067116564941566953 + 0.067119373420288689 + 0.067122181932114555 + 0.067124990477044788 + 0.067127799055079804 + 0.067130607666220005 + 0.067133416310465571 + 0.067136224987816989 + 0.067139033698274536 + 0.067141842441838614 + 0.067144651218509446 + 0.067147460028287434 + 0.067150268871172994 + 0.06715307774716639 + 0.067155886656267996 + 0.067158695598478022 + 0.067161504573797076 + 0.067164313582225285 + 0.067167122623763051 + 0.06716993169841072 + 0.067172740806168654 + 0.067175549947037214 + 0.067178359121016648 + 0.06718116832810743 + 0.067183977568309905 + 0.067186786841624296 + 0.067189596148051006 + 0.067192405487590381 + 0.067195214860242811 + 0.067198024266008571 + 0.067200833704887997 + 0.067203643176881614 + 0.067206452681989493 + 0.067209262220212257 + 0.06721207179155006 + 0.067214881396003318 + 0.067217691033572405 + 0.067220500704257655 + 0.067223310408059359 + 0.067226120144977877 + 0.067228929915013697 + 0.067231739718166969 + 0.067234549554438194 + 0.067237359423827636 + 0.067240169326335669 + 0.067242979261962668 + 0.06724578923070898 + 0.067248599232574854 + 0.067251409267560902 + 0.067254219335667081 + 0.067257029436894114 + 0.06725983957124218 + 0.067262649738711683 + 0.067265459939302955 + 0.067268270173016259 + 0.067271080439852124 + 0.067273890739810743 + 0.067276701072892547 + 0.067279511439097855 + 0.06728232183842707 + 0.067285132270880538 + 0.067287942736458606 + 0.067290753235161579 + 0.06729356376699 + 0.067296374331943964 + 0.067299184930023986 + 0.067301995561230302 + 0.067304806225563382 + 0.067307616923023589 + 0.067310427653611171 + 0.067313238417326629 + 0.067316049214170295 + 0.067318860044142323 + 0.067321670907243308 + 0.067324481803473418 + 0.067327292732833291 + 0.067330103695323024 + 0.06733291469094306 + 0.06733572571969379 + 0.067338536781575517 + 0.067341347876588561 + 0.067344159004733423 + 0.067346970166010378 + 0.067349781360419844 + 0.067352592587962057 + 0.067355403848637529 + 0.067358215142446498 + 0.067361026469389421 + 0.067363837829466519 + 0.067366649222678349 + 0.067369460649025131 + 0.067372272108507256 + 0.067375083601125138 + 0.067377895126879139 + 0.067380706685769481 + 0.06738351827779665 + 0.067386329902961034 + 0.06738914156126298 + 0.067391953252702697 + 0.067394764977280835 + 0.06739757673499755 + 0.067400388525853228 + 0.0674032003498483 + 0.06740601220698314 + 0.06740882409725793 + 0.067411636020673238 + 0.067414447977229452 + 0.067417259966926754 + 0.06742007198976567 + 0.067422884045746534 + 0.067425696134869623 + 0.067428508257135422 + 0.06743132041254421 + 0.067434132601096389 + 0.067436944822792333 + 0.067439757077632417 + 0.067442569365617017 + 0.067445381686746478 + 0.067448194041021106 + 0.067451006428441443 + 0.067453818849007738 + 0.067456631302720324 + 0.067459443789579659 + 0.067462256309586105 + 0.06746506886273998 + 0.0674678814490417 + 0.067470694068491682 + 0.067473506721090135 + 0.067476319406837543 + 0.067479132125734309 + 0.067481944877780697 + 0.067484757662977235 + 0.067487570481324186 + 0.06749038333282191 + 0.067493196217470769 + 0.06749600913527129 + 0.067498822086223598 + 0.067501635070328317 + 0.067504448087585725 + 0.067507261137996155 + 0.06751007422156001 + 0.067512887338277677 + 0.067515700488149491 + 0.067518513671175784 + 0.067521326887357097 + 0.067524140136693736 + 0.067526953419185992 + 0.067529766734834351 + 0.067532580083639104 + 0.067535393465600654 + 0.067538206880719445 + 0.067541020328995824 + 0.067543833810430026 + 0.067546647325022705 + 0.067549460872773942 + 0.06755227445368428 + 0.067555088067754121 + 0.067557901714983784 + 0.067560715395373699 + 0.067563529108924172 + 0.06756634285563555 + 0.067569156635508332 + 0.067571970448542906 + 0.067574784294739496 + 0.067577598174098696 + 0.067580412086620703 + 0.067583226032305946 + 0.067586040011154896 + 0.067588854023167833 + 0.067591668068345198 + 0.067594482146687243 + 0.067597296258194564 + 0.067600110402867425 + 0.067602924580706256 + 0.067605738791711306 + 0.067608553035883104 + 0.06761136731322194 + 0.067614181623728356 + 0.067616995967402574 + 0.067619810344244982 + 0.067622624754256039 + 0.067625439197436188 + 0.067628253673785596 + 0.06763106818330486 + 0.06763388272599434 + 0.067636697301854287 + 0.067639511910885214 + 0.06764232655308744 + 0.067645141228461381 + 0.067647955937007453 + 0.067650770678725949 + 0.067653585453617354 + 0.067656400261682015 + 0.067659215102920334 + 0.06766202997733263 + 0.067664844884919514 + 0.067667659825681098 + 0.067670474799617839 + 0.067673289806730277 + 0.067676104847018692 + 0.067678919920483416 + 0.067681735027124934 + 0.067684550166943636 + 0.067687365339939853 + 0.067690180546114045 + 0.067692995785466489 + 0.06769581105799774 + 0.067698626363707978 + 0.0677014417025978 + 0.067704257074667526 + 0.067707072479917488 + 0.067709887918348116 + 0.06771270338995998 + 0.067715518894753135 + 0.067718334432728275 + 0.067721150003885552 + 0.06772396560822555 + 0.067726781245748532 + 0.067729596916454984 + 0.067732412620345267 + 0.067735228357419769 + 0.067738044127678892 + 0.067740859931123068 + 0.067743675767752601 + 0.067746491637568004 + 0.067749307540569528 + 0.067752123476757659 + 0.067754939446132811 + 0.067757755448695486 + 0.067760571484445767 + 0.067763387553384333 + 0.06776620365551142 + 0.06776901979082757 + 0.067771835959333046 + 0.067774652161028293 + 0.067777468395913726 + 0.067780284663989818 + 0.067783100965256762 + 0.06778591729971517 + 0.067788733667365292 + 0.067791550068207654 + 0.067794366502242562 + 0.06779718296947046 + 0.067799999469891695 + 0.06780281600350678 + 0.067805632570315966 + 0.067808449170319793 + 0.067811265803518497 + 0.067814082469912745 + 0.067816899169502662 + 0.067819715902288816 + 0.06782253266827154 + 0.067825349467451279 + 0.067828166299828407 + 0.067830983165403397 + 0.067833800064176469 + 0.067836616996148263 + 0.067839433961319084 + 0.067842250959689224 + 0.067845067991259209 + 0.067847885056029428 + 0.067850702154000367 + 0.067853519285172234 + 0.067856336449545626 + 0.067859153647120876 + 0.067861970877898276 + 0.067864788141878435 + 0.067867605439061673 + 0.067870422769448269 + 0.06787324013303879 + 0.067876057529833708 + 0.067878874959833232 + 0.067881692423037876 + 0.067884509919448111 + 0.067887327449064158 + 0.067890145011886532 + 0.067892962607915761 + 0.067895780237152092 + 0.067898597899595903 + 0.067901415595247816 + 0.067904233324108054 + 0.067907051086177034 + 0.067909868881455296 + 0.067912686709943104 + 0.067915504571641014 + 0.067918322466549261 + 0.067921140394668372 + 0.067923958355998737 + 0.067926776350540841 + 0.067929594378294988 + 0.067932412439261555 + 0.06793523053344111 + 0.067938048660833986 + 0.067940866821440613 + 0.067943685015261338 + 0.06794650324229666 + 0.067949321502546914 + 0.06795213979601257 + 0.067954958122694017 + 0.0679577764825917 + 0.067960594875706021 + 0.067963413302037354 + 0.067966231761586185 + 0.067969050254352861 + 0.067971868780337827 + 0.067974687339541637 + 0.067977505931964444 + 0.067980324557606747 + 0.067983143216469116 + 0.06798596190855187 + 0.067988780633855384 + 0.067991599392380059 + 0.067994418184126437 + 0.067997237009094838 + 0.068000055867285636 + 0.068002874758699428 + 0.068005693683336546 + 0.068008512641197338 + 0.068011331632282263 + 0.068014150656591679 + 0.068016969714126199 + 0.068019788804886086 + 0.06802260792887177 + 0.068025427086083737 + 0.068028246276522292 + 0.068031065500187962 + 0.068033884757081303 + 0.068036704047202384 + 0.068039523370551816 + 0.06804234272713014 + 0.068045162116937619 + 0.068047981539974628 + 0.068050800996241834 + 0.06805362048573943 + 0.068056440008467875 + 0.068059259564427696 + 0.068062079153619226 + 0.068064898776042868 + 0.068067718431699176 + 0.068070538120588456 + 0.068073357842711166 + 0.068076177598067764 + 0.068078997386658666 + 0.068081817208484219 + 0.068084637063544923 + 0.068087456951841305 + 0.068090276873373531 + 0.068093096828142158 + 0.068095916816147753 + 0.068098736837390525 + 0.068101556891871057 + 0.068104376979589654 + 0.068107197100546843 + 0.068110017254742986 + 0.068112837442178636 + 0.068115657662854004 + 0.068118477916769671 + 0.06812129820392604 + 0.06812411852432354 + 0.068126938877962645 + 0.068129759264843631 + 0.068132579684967123 + 0.068135400138333441 + 0.068138220624943027 + 0.068141041144796369 + 0.068143861697893812 + 0.068146682284235829 + 0.06814950290382274 + 0.068152323556655223 + 0.068155144242733529 + 0.068157964962058157 + 0.068160785714629524 + 0.068163606500448018 + 0.068166427319514125 + 0.068169248171828289 + 0.068172069057390844 + 0.068174889976202385 + 0.068177710928263205 + 0.068180531913573747 + 0.068183352932134608 + 0.068186173983946066 + 0.068188995069008537 + 0.068191816187322618 + 0.068194637338888545 + 0.068197458523706872 + 0.068200279741778003 + 0.068203100993102478 + 0.06820592227768052 + 0.068208743595512808 + 0.068211564946599551 + 0.068214386330941332 + 0.068217207748538594 + 0.068220029199391616 + 0.068222850683501118 + 0.068225672200867199 + 0.068228493751490607 + 0.068231315335371565 + 0.068234136952510627 + 0.068236958602908085 + 0.068239780286564675 + 0.068242602003480521 + 0.068245423753656262 + 0.068248245537092245 + 0.068251067353788913 + 0.06825388920374674 + 0.068256711086966182 + 0.068259533003447739 + 0.068262354953191606 + 0.068265176936198463 + 0.068267998952468614 + 0.068270821002002643 + 0.068273643084800925 + 0.068276465200863834 + 0.068279287350191911 + 0.068282109532785532 + 0.068284931748645153 + 0.068287753997771261 + 0.0682905762801643 + 0.068293398595824575 + 0.068296220944752697 + 0.06829904332694911 + 0.068301865742414147 + 0.068304688191148405 + 0.068307510673152161 + 0.068310333188425915 + 0.068313155736970207 + 0.068315978318785317 + 0.068318800933871784 + 0.068321623582230165 + 0.068324446263860708 + 0.068327268978763928 + 0.068330091726940378 + 0.068332914508390338 + 0.068335737323114404 + 0.068338560171112936 + 0.068341383052386365 + 0.068344205966935204 + 0.068347028914759966 + 0.068349851895860902 + 0.068352674910238637 + 0.06835549795789353 + 0.068358321038826025 + 0.068361144153036624 + 0.068363967300525796 + 0.068366790481293904 + 0.068369613695341544 + 0.068372436942668965 + 0.068375260223276779 + 0.068378083537165346 + 0.068380906884335194 + 0.068383730264786696 + 0.06838655367852034 + 0.068389377125536707 + 0.068392200605835993 + 0.068395024119418793 + 0.068397847666285636 + 0.068400671246436839 + 0.068403494859872974 + 0.068406318506594371 + 0.068409142186601574 + 0.068411965899894997 + 0.068414789646475113 + 0.068417613426342352 + 0.068420437239497173 + 0.068423261085940074 + 0.068426084965671416 + 0.068428908878691769 + 0.068431732825001576 + 0.068434556804601254 + 0.068437380817491275 + 0.068440204863672041 + 0.068443028943144135 + 0.068445853055907904 + 0.068448677201963765 + 0.068451501381312313 + 0.068454325593953938 + 0.068457149839889153 + 0.068459974119118347 + 0.068462798431641936 + 0.068465622777460489 + 0.068468447156574394 + 0.068471271568984082 + 0.068474096014690178 + 0.068476920493692986 + 0.068479745005993076 + 0.068482569551590752 + 0.06848539413048664 + 0.068488218742681045 + 0.068491043388174577 + 0.068493868066967625 + 0.068496692779060703 + 0.068499517524454157 + 0.068502342303148625 + 0.068505167115144372 + 0.068507991960441939 + 0.068510816839041797 + 0.06851364175094446 + 0.068516466696150413 + 0.068519291674660018 + 0.068522116686473789 + 0.068524941731592223 + 0.068527766810015669 + 0.068530591921744724 + 0.068533417066779762 + 0.068536242245121282 + 0.068539067456769756 + 0.068541892701725601 + 0.0685447179799894 + 0.068547543291561527 + 0.068550368636442469 + 0.068553194014632682 + 0.068556019426132625 + 0.068558844870942798 + 0.0685616703490637 + 0.068564495860495733 + 0.068567321405239398 + 0.06857014698329511 + 0.06857297259466337 + 0.068575798239344732 + 0.068578623917339529 + 0.068581449628648344 + 0.068584275373271608 + 0.068587101151209695 + 0.068589926962463202 + 0.068592752807032531 + 0.068595578684918224 + 0.068598404596120627 + 0.068601230540640337 + 0.068604056518477799 + 0.068606882529633428 + 0.068609708574107808 + 0.068612534651901244 + 0.068615360763014346 + 0.068618186907447504 + 0.068621013085201257 + 0.068623839296276037 + 0.068626665540672302 + 0.068629491818390606 + 0.068632318129431394 + 0.068635144473795068 + 0.068637970851482169 + 0.0686407972624931 + 0.068643623706828499 + 0.068646450184488603 + 0.068649276695474049 + 0.068652103239785309 + 0.0686549298174228 + 0.068657756428387048 + 0.068660583072678499 + 0.068663409750297624 + 0.068666236461245006 + 0.068669063205520936 + 0.068671889983125983 + 0.068674716794060717 + 0.068677543638325497 + 0.068680370515920769 + 0.068683197426847031 + 0.068686024371104937 + 0.068688851348694777 + 0.06869167835961705 + 0.068694505403872327 + 0.068697332481460996 + 0.068700159592383597 + 0.06870298673664052 + 0.068705813914232403 + 0.068708641125159606 + 0.068711468369422643 + 0.068714295647021972 + 0.068717122957958107 + 0.068719950302231506 + 0.068722777679842639 + 0.068725605090792036 + 0.068728432535080153 + 0.068731260012707546 + 0.068734087523674547 + 0.068736915067981685 + 0.068739742645629556 + 0.068742570256618438 + 0.06874539790094901 + 0.068748225578621716 + 0.068751053289636904 + 0.068753881033995309 + 0.068756708811697223 + 0.068759536622743075 + 0.068762364467133547 + 0.068765192344869025 + 0.068768020255950038 + 0.068770848200376988 + 0.068773676178150306 + 0.068776504189270754 + 0.068779332233738569 + 0.068782160311554305 + 0.06878498842271849 + 0.068787816567231583 + 0.068790644745094026 + 0.068793472956306431 + 0.068796301200869145 + 0.068799129478782597 + 0.068801957790047538 + 0.0688047861346643 + 0.068807614512633342 + 0.068810442923955217 + 0.068813271368630427 + 0.068816099846659456 + 0.068818928358042639 + 0.068821756902780667 + 0.068824585480873987 + 0.068827414092323083 + 0.068830242737128317 + 0.068833071415290367 + 0.068835900126809596 + 0.068838728871686655 + 0.068841557649921808 + 0.068844386461515666 + 0.068847215306468826 + 0.06885004418478155 + 0.068852873096454589 + 0.068855702041488206 + 0.06885853101988304 + 0.068861360031639535 + 0.06886418907675812 + 0.068867018155239462 + 0.068869847267083881 + 0.068872676412291903 + 0.068875505590864125 + 0.068878334802800964 + 0.068881164048102933 + 0.068883993326770546 + 0.068886822638804288 + 0.068889651984204575 + 0.068892481362972088 + 0.068895310775107063 + 0.068898140220610249 + 0.068900969699481951 + 0.06890379921172278 + 0.068906628757333305 + 0.068909458336313886 + 0.068912287948665024 + 0.068915117594387176 + 0.068917947273480995 + 0.068920776985946897 + 0.06892360673178545 + 0.068926436510997016 + 0.06892926632358222 + 0.06893209616954149 + 0.068934926048875356 + 0.068937755961584302 + 0.068940585907668897 + 0.068943415887129517 + 0.068946245899966729 + 0.068949075946181021 + 0.068951906025772919 + 0.068954736138742923 + 0.068957566285091518 + 0.068960396464819274 + 0.068963226677926467 + 0.068966056924413946 + 0.068968887204281945 + 0.068971717517531089 + 0.068974547864161767 + 0.0689773782441747 + 0.06898020865757018 + 0.068983039104348789 + 0.06898586958451107 + 0.068988700098057534 + 0.068991530644988516 + 0.068994361225304696 + 0.068997191839006503 + 0.069000022486094534 + 0.069002853166569234 + 0.069005683880431032 + 0.069008514627680567 + 0.069011345408318159 + 0.069014176222344611 + 0.069017007069760217 + 0.069019837950565502 + 0.069022668864761036 + 0.069025499812347207 + 0.069028330793324641 + 0.069031161807693905 + 0.069033992855455292 + 0.069036823936609593 + 0.069039655051157042 + 0.069042486199098266 + 0.069045317380433763 + 0.069048148595164116 + 0.069050979843289728 + 0.069053811124811196 + 0.069056642439728935 + 0.069059473788043571 + 0.06906230516975552 + 0.06906513658486535 + 0.069067968033373506 + 0.069070799515280543 + 0.069073631030587029 + 0.069076462579293368 + 0.069079294161400157 + 0.069082125776907893 + 0.069084957425817092 + 0.069087789108128142 + 0.069090620823841764 + 0.069093452572958361 + 0.069096284355478432 + 0.069099116171402561 + 0.069101948020731177 + 0.069104779903464905 + 0.069107611819604065 + 0.069110443769149335 + 0.069113275752101272 + 0.069116107768460319 + 0.069118939818226907 + 0.069121771901401674 + 0.069124604017985064 + 0.069127436167977618 + 0.069130268351379878 + 0.069133100568192413 + 0.069135932818415596 + 0.069138765102050012 + 0.06914159741909616 + 0.069144429769554719 + 0.069147262153425954 + 0.06915009457071053 + 0.069152927021408961 + 0.069155759505521705 + 0.069158592023049387 + 0.069161424573992339 + 0.069164257158351283 + 0.069167089776126719 + 0.069169922427318994 + 0.069172755111928733 + 0.069175587829956572 + 0.069178420581402778 + 0.069181253366268167 + 0.069184086184553073 + 0.069186919036258052 + 0.069189751921383616 + 0.069192584839930238 + 0.069195417791898597 + 0.069198250777289125 + 0.069201083796102292 + 0.069203916848338737 + 0.069206749933998862 + 0.06920958305308321 + 0.069212416205592431 + 0.069215249391526901 + 0.069218082610887244 + 0.069220915863673918 + 0.06922374914988752 + 0.06922658246952848 + 0.069229415822597409 + 0.069232249209094793 + 0.06923508262902113 + 0.069237916082377018 + 0.069240749569162985 + 0.069243583089379432 + 0.069246416643027012 + 0.069249250230106196 + 0.069252083850617541 + 0.069254917504561572 + 0.069257751191938818 + 0.069260584912749737 + 0.069263418666994939 + 0.069266252454674923 + 0.069269086275790259 + 0.069271920130341419 + 0.069274754018328957 + 0.069277587939753374 + 0.069280421894615252 + 0.069283255882915118 + 0.069286089904653458 + 0.069288923959830717 + 0.069291758048447588 + 0.069294592170504682 + 0.069297426326002304 + 0.069300260514941092 + 0.069303094737321477 + 0.069305928993144181 + 0.069308763282409563 + 0.069311597605118277 + 0.069314431961270739 + 0.069317266350867601 + 0.069320100773909307 + 0.069322935230396454 + 0.069325769720329472 + 0.069328604243709083 + 0.069331438800535619 + 0.069334273390809706 + 0.069337108014531926 + 0.069339942671702751 + 0.06934277736232268 + 0.069345612086392353 + 0.06934844684391217 + 0.069351281634882841 + 0.069354116459304727 + 0.069356951317178464 + 0.069359786208504581 + 0.069362621133283647 + 0.069365456091516162 + 0.069368291083202527 + 0.069371126108343478 + 0.069373961166939557 + 0.069376796258991152 + 0.069379631384498819 + 0.069382466543463236 + 0.069385301735884919 + 0.069388136961764255 + 0.06939097222110191 + 0.069393807513898453 + 0.069396642840154218 + 0.069399478199869954 + 0.069402313593046161 + 0.069405149019683365 + 0.069407984479782053 + 0.069410819973342808 + 0.069413655500366211 + 0.06941649106085275 + 0.06941932665480291 + 0.069422162282217398 + 0.069424997943096631 + 0.069427833637441164 + 0.069430669365251649 + 0.069433505126528419 + 0.06943634092127221 + 0.069439176749483425 + 0.069442012611162715 + 0.069444848506310566 + 0.06944768443492752 + 0.069450520397014215 + 0.069453356392571053 + 0.06945619242159877 + 0.069459028484097615 + 0.06946186458006845 + 0.069464700709511523 + 0.069467536872427599 + 0.069470373068817259 + 0.069473209298680824 + 0.069476045562019001 + 0.069478881858832345 + 0.069481718189121272 + 0.069484554552886463 + 0.069487390950128444 + 0.069490227380847758 + 0.069493063845044792 + 0.069495900342720338 + 0.069498736873874881 + 0.069501573438508879 + 0.069504410036622943 + 0.069507246668217615 + 0.069510083333293435 + 0.069512920031850944 + 0.069515756763890657 + 0.069518593529413253 + 0.069521430328419162 + 0.069524267160908967 + 0.069527104026883266 + 0.069529940926342501 + 0.069532777859287381 + 0.069535614825718392 + 0.069538451825635991 + 0.06954128885904079 + 0.06954412592593337 + 0.069546963026314287 + 0.069549800160184028 + 0.069552637327543215 + 0.069555474528392447 + 0.069558311762732083 + 0.069561149030562847 + 0.06956398633188525 + 0.069566823666699876 + 0.069569661035007266 + 0.069572498436807906 + 0.069575335872102378 + 0.069578173340891378 + 0.069581010843175223 + 0.069583848378954608 + 0.069586685948230143 + 0.069589523551002216 + 0.069592361187271523 + 0.069595198857038604 + 0.069598036560303916 + 0.069600874297068183 + 0.069603712067331791 + 0.069606549871095436 + 0.069609387708359588 + 0.069612225579124859 + 0.069615063483391665 + 0.069617901421160824 + 0.069620739392432643 + 0.0696235773972078 + 0.06962641543548688 + 0.069629253507270408 + 0.0696320916125589 + 0.069634929751353006 + 0.069637767923653227 + 0.069640606129460103 + 0.06964344436877426 + 0.069646282641596211 + 0.06964912094792651 + 0.069651959287765769 + 0.069654797661114501 + 0.069657636067973247 + 0.069660474508342674 + 0.069663312982223294 + 0.069666151489615566 + 0.069668990030520211 + 0.069671828604937688 + 0.069674667212868607 + 0.069677505854313565 + 0.069680344529272978 + 0.069683183237747554 + 0.069686021979737903 + 0.069688860755244303 + 0.069691699564267656 + 0.069694538406808365 + 0.06969737728286704 + 0.069700216192444209 + 0.069703055135540412 + 0.069705894112156344 + 0.069708733122292463 + 0.069711572165949365 + 0.069714411243127425 + 0.069717250353827628 + 0.069720089498050183 + 0.069722928675795867 + 0.069725767887065096 + 0.06972860713185855 + 0.069731446410176659 + 0.069734285722020145 + 0.069737125067389438 + 0.069739964446285246 + 0.069742803858708138 + 0.069745643304658544 + 0.069748482784137103 + 0.069751322297144425 + 0.069754161843681051 + 0.069757001423747592 + 0.06975984103734445 + 0.069762680684472445 + 0.069765520365131922 + 0.069768360079323646 + 0.069771199827048005 + 0.069774039608305749 + 0.069776879423097363 + 0.069779719271423277 + 0.069782559153284268 + 0.069785399068680878 + 0.069788239017613662 + 0.069791079000083217 + 0.069793919016089945 + 0.069796759065634636 + 0.06979959914871782 + 0.069802439265339994 + 0.069805279415501659 + 0.069808119599203688 + 0.069810959816446416 + 0.069813800067230342 + 0.069816640351556297 + 0.069819480669424713 + 0.069822321020836187 + 0.069825161405791217 + 0.06982800182429047 + 0.069830842276334515 + 0.069833682761923949 + 0.069836523281059396 + 0.069839363833741161 + 0.069842204419970161 + 0.069845045039746825 + 0.069847885693071682 + 0.069850726379945396 + 0.069853567100368455 + 0.069856407854341551 + 0.069859248641865213 + 0.06986208946293998 + 0.06986493031756652 + 0.069867771205745222 + 0.069870612127476958 + 0.069873453082762077 + 0.069876294071601286 + 0.069879135093995084 + 0.069881976149944056 + 0.06988481723944881 + 0.069887658362509944 + 0.069890499519127985 + 0.0698933407093036 + 0.069896181933037344 + 0.069899023190329715 + 0.069901864481181408 + 0.069904705805592965 + 0.069907547163564884 + 0.069910388555097874 + 0.069913229980192448 + 0.069916071438849273 + 0.069918912931068763 + 0.069921754456851726 + 0.069924596016198548 + 0.06992743760910991 + 0.069930279235586368 + 0.0699331208956286 + 0.069935962589237038 + 0.069938804316412376 + 0.069941646077155098 + 0.069944487871465955 + 0.069947329699345334 + 0.069950171560794083 + 0.069953013455812452 + 0.069955855384401341 + 0.069958697346561113 + 0.069961539342292461 + 0.069964381371595913 + 0.069967223434472245 + 0.069970065530921818 + 0.069972907660945313 + 0.069975749824543299 + 0.069978592021716329 + 0.069981434252465058 + 0.069984276516790095 + 0.069987118814691968 + 0.069989961146171259 + 0.069992803511228607 + 0.069995645909864637 + 0.06999848834207982 + 0.070001330807874823 + 0.070004173307250311 + 0.070007015840206688 + 0.070009858406744618 + 0.070012701006864811 + 0.070015543640567723 + 0.07001838630785405 + 0.070021229008724359 + 0.070024071743179025 + 0.070026914511219049 + 0.070029757312844679 + 0.070032600148056678 + 0.070035443016855561 + 0.070038285919241966 + 0.070041128855216489 + 0.070043971824779672 + 0.070046814827932249 + 0.07004965786467468 + 0.07005250093500752 + 0.070055344038931461 + 0.070058187176447129 + 0.070061030347555051 + 0.070063873552255851 + 0.070066716790550043 + 0.070069560062438391 + 0.07007240336792131 + 0.07007524670699955 + 0.070078090079673652 + 0.070080933485944172 + 0.070083776925811761 + 0.070086620399276947 + 0.070089463906340396 + 0.070092307447002677 + 0.070095151021264512 + 0.070097994629126248 + 0.070100838270588647 + 0.070103681945652335 + 0.070106525654317756 + 0.070109369396585797 + 0.07011221317245668 + 0.070115056981931295 + 0.07011790082501014 + 0.070120744701693785 + 0.070123588611982896 + 0.070126432555878068 + 0.070129276533379942 + 0.070132120544488974 + 0.0701349645892059 + 0.070137808667531193 + 0.070140652779465629 + 0.070143496925009638 + 0.070146341104163984 + 0.070149185316929152 + 0.070152029563305823 + 0.070154873843294524 + 0.07015771815689581 + 0.070160562504110541 + 0.070163406884939064 + 0.070166251299382087 + 0.070169095747440194 + 0.070171940229113994 + 0.070174784744404112 + 0.070177629293311117 + 0.070180473875835564 + 0.070183318491978314 + 0.070186163141739658 + 0.070189007825120289 + 0.070191852542120917 + 0.070194697292742109 + 0.070197542076984434 + 0.07020038689484849 + 0.070203231746334929 + 0.07020607663144432 + 0.070208921550177369 + 0.070211766502534551 + 0.070214611488516557 + 0.070217456508124013 + 0.070220301561357376 + 0.070223146648217452 + 0.070225991768704699 + 0.070228836922819823 + 0.070231682110563437 + 0.070234527331936109 + 0.070237372586938365 + 0.070240217875571054 + 0.070243063197834521 + 0.070245908553729544 + 0.070248753943256761 + 0.070251599366416617 + 0.070254444823209819 + 0.070257290313636991 + 0.070260135837698759 + 0.07026298139539576 + 0.070265826986728425 + 0.070268672611697586 + 0.070271518270303743 + 0.070274363962547576 + 0.070277209688429584 + 0.070280055447950546 + 0.070282901241110862 + 0.070285747067911408 + 0.070288592928352642 + 0.070291438822435062 + 0.070294284750159572 + 0.070297130711526615 + 0.07029997670653676 + 0.070302822735190756 + 0.070305668797489118 + 0.070308514893432469 + 0.070311361023021463 + 0.070314207186256708 + 0.070317053383138886 + 0.070319899613668566 + 0.070322745877846232 + 0.070325592175672663 + 0.070328438507148483 + 0.070331284872274233 + 0.070334131271050537 + 0.070336977703478049 + 0.070339824169557391 + 0.070342670669289134 + 0.070345517202673971 + 0.070348363769712541 + 0.070351210370405301 + 0.070354057004752973 + 0.07035690367275621 + 0.070359750374415581 + 0.070362597109731778 + 0.07036544387870533 + 0.070368290681336917 + 0.070371137517627191 + 0.070373984387576638 + 0.070376831291185965 + 0.070379678228455908 + 0.070382525199386856 + 0.070385372203979613 + 0.070388219242234706 + 0.070391066314152942 + 0.070393913419734638 + 0.070396760558980628 + 0.070399607731891536 + 0.070402454938467918 + 0.070405302178710411 + 0.070408149452619556 + 0.070410996760196146 + 0.07041384410144072 + 0.070416691476353932 + 0.070419538884936378 + 0.070422386327188669 + 0.070425233803111484 + 0.070428081312705421 + 0.070430928855971103 + 0.070433776432909156 + 0.070436624043520302 + 0.070439471687804942 + 0.070442319365763867 + 0.070445167077397702 + 0.070448014822707128 + 0.070450862601692574 + 0.070453710414354873 + 0.07045655826069451 + 0.070459406140712208 + 0.070462254054408521 + 0.070465102001784241 + 0.070467949982839756 + 0.070470797997575829 + 0.070473646045993113 + 0.070476494128092287 + 0.070479342243873769 + 0.070482190393338376 + 0.070485038576486692 + 0.070487886793319257 + 0.070490735043836905 + 0.07049358332804008 + 0.070496431645929572 + 0.070499279997505798 + 0.070502128382769577 + 0.07050497680172145 + 0.070507825254362083 + 0.070510673740692101 + 0.070513522260712211 + 0.070516370814422941 + 0.070519219401824956 + 0.070522068022918855 + 0.070524916677705357 + 0.070527765366184977 + 0.070530614088358631 + 0.07053346284422661 + 0.070536311633789622 + 0.070539160457048458 + 0.070542009314003673 + 0.070544858204655864 + 0.070547707129005724 + 0.070550556087053795 + 0.070553405078800868 + 0.070556254104247429 + 0.070559103163394296 + 0.070561952256241914 + 0.070564801382790948 + 0.070567650543042162 + 0.070570499736996001 + 0.070573348964653365 + 0.070576198226014741 + 0.070579047521080657 + 0.070581896849852027 + 0.070584746212329227 + 0.070587595608513021 + 0.070590445038404045 + 0.070593294502002982 + 0.070596143999310315 + 0.070598993530326754 + 0.070601843095053046 + 0.070604692693489832 + 0.070607542325637554 + 0.070610391991497032 + 0.070613241691068793 + 0.0706160914243536 + 0.070618941191352064 + 0.070621790992064754 + 0.070624640826492308 + 0.070627490694635545 + 0.070630340596494853 + 0.070633190532070997 + 0.070636040501364697 + 0.070638890504376564 + 0.070641740541107209 + 0.070644590611557173 + 0.070647440715727164 + 0.070650290853617986 + 0.070653141025230182 + 0.07065599123056425 + 0.070658841469620967 + 0.070661691742401 + 0.07066454204890496 + 0.070667392389133624 + 0.070670242763087338 + 0.070673093170767004 + 0.070675943612173248 + 0.070678794087306554 + 0.070681644596167714 + 0.070684495138757353 + 0.070687345715076122 + 0.070690196325124563 + 0.070693046968903467 + 0.070695897646413361 + 0.070698748357655064 + 0.070701599102629104 + 0.070704449881336076 + 0.070707300693776759 + 0.070710151539951652 + 0.070713002419861601 + 0.070715853333507106 + 0.070718704280888847 + 0.070721555262007546 + 0.070724406276863744 + 0.070727257325458134 + 0.070730108407791453 + 0.0707329595238642 + 0.070735810673677096 + 0.070738661857230822 + 0.070741513074526127 + 0.070744364325563372 + 0.070747215610343445 + 0.070750066928866942 + 0.070752918281134558 + 0.070755769667146834 + 0.070758621086904519 + 0.070761472540408238 + 0.070764324027658698 + 0.070767175548656358 + 0.070770027103402147 + 0.070772878691896496 + 0.070775730314140278 + 0.070778581970133897 + 0.070781433659878171 + 0.070784285383373738 + 0.070787137140621195 + 0.07078998893162132 + 0.070792840756374639 + 0.070795692614881764 + 0.070798544507143568 + 0.070801396433160607 + 0.07080424839293345 + 0.070807100386462762 + 0.070809952413749377 + 0.070812804474793767 + 0.070815656569596763 + 0.070818508698158797 + 0.070821360860480687 + 0.070824213056563085 + 0.070827065286406546 + 0.070829917550011931 + 0.07083276984737967 + 0.070835622178510513 + 0.070838474543405194 + 0.07084132694206427 + 0.070844179374488489 + 0.070847031840678365 + 0.070849884340634772 + 0.070852736874358266 + 0.070855589441849456 + 0.070858442043108968 + 0.070861294678137732 + 0.070864147346936163 + 0.070867000049504886 + 0.070869852785844775 + 0.070872705555956317 + 0.07087555835984026 + 0.070878411197497271 + 0.070881264068927988 + 0.070884116974133077 + 0.070886969913113176 + 0.070889822885868869 + 0.070892675892401072 + 0.070895528932710297 + 0.070898382006797198 + 0.070901235114662495 + 0.070904088256306785 + 0.070906941431730736 + 0.070909794640935053 + 0.070912647883920432 + 0.070915501160687414 + 0.07091835447123683 + 0.070921207815569251 + 0.070924061193685356 + 0.070926914605585867 + 0.070929768051271408 + 0.070932621530742576 + 0.070935475044000162 + 0.070938328591044708 + 0.07094118217187699 + 0.070944035786497633 + 0.070946889434907318 + 0.070949743117106764 + 0.070952596833096571 + 0.070955450582877347 + 0.070958304366449884 + 0.070961158183814849 + 0.070964012034972768 + 0.070966865919924599 + 0.070969719838670647 + 0.070972573791211843 + 0.070975427777548741 + 0.070978281797682036 + 0.070981135851612517 + 0.070983989939340644 + 0.070986844060867305 + 0.070989698216192984 + 0.070992552405318418 + 0.070995406628244329 + 0.070998260884971395 + 0.071001115175500243 + 0.071003969499831551 + 0.071006823857965987 + 0.071009678249904271 + 0.071012532675646972 + 0.071015387135194952 + 0.071018241628548667 + 0.071021096155708952 + 0.071023950716676498 + 0.071026805311451779 + 0.071029659940035642 + 0.071032514602428765 + 0.071035369298631662 + 0.071038224028645236 + 0.071041078792470014 + 0.071043933590106786 + 0.071046788421556067 + 0.071049643286818634 + 0.071052498185895277 + 0.071055353118786399 + 0.071058208085492847 + 0.071061063086015383 + 0.071063918120354536 + 0.071066773188511068 + 0.07106962829048559 + 0.071072483426278851 + 0.071075338595891505 + 0.071078193799324146 + 0.071081049036577609 + 0.071083904307652476 + 0.071086759612549497 + 0.071089614951269253 + 0.071092470323812523 + 0.071095325730179862 + 0.071098181170372074 + 0.071101036644389701 + 0.071103892152233714 + 0.071106747693904515 + 0.071109603269402868 + 0.071112458878729384 + 0.071115314521884909 + 0.071118170198870012 + 0.071121025909685442 + 0.071123881654331839 + 0.071126737432809881 + 0.071129593245120304 + 0.071132449091263691 + 0.071135304971240765 + 0.071138160885052273 + 0.071141016832698911 + 0.071143872814181233 + 0.071146728829500017 + 0.071149584878655942 + 0.071152440961649771 + 0.071155297078482033 + 0.071158153229153462 + 0.071161009413664822 + 0.071163865632016654 + 0.07116672188420986 + 0.071169578170244968 + 0.071172434490122685 + 0.071175290843843775 + 0.071178147231408806 + 0.071181003652818556 + 0.071183860108073649 + 0.071186716597174862 + 0.071189573120122848 + 0.071192429676918162 + 0.071195286267561761 + 0.071198142892054103 + 0.071200999550395924 + 0.071203856242588057 + 0.071206712968631014 + 0.071209569728525532 + 0.071212426522272387 + 0.071215283349872177 + 0.071218140211325637 + 0.071220997106633432 + 0.071223854035796272 + 0.071226710998814877 + 0.071229567995689913 + 0.071232425026422019 + 0.071235282091011903 + 0.071238139189460384 + 0.07124099632176803 + 0.071243853487935521 + 0.071246710687963552 + 0.071249567921852955 + 0.071252425189604382 + 0.071255282491218375 + 0.071258139826695779 + 0.071260997196037193 + 0.071263854599243406 + 0.071266712036315016 + 0.071269569507252703 + 0.071272427012057368 + 0.071275284550729456 + 0.0712781421232698 + 0.071280999729679106 + 0.071283857369957918 + 0.071286715044107107 + 0.071289572752127356 + 0.071292430494019218 + 0.071295288269783541 + 0.071298146079420976 + 0.071301003922932274 + 0.071303861800317947 + 0.071306719711578939 + 0.071309577656715722 + 0.071312435635729129 + 0.07131529364861984 + 0.071318151695388618 + 0.071321009776036032 + 0.071323867890562734 + 0.071326726038969682 + 0.071329584221257389 + 0.071332442437426535 + 0.071335300687477884 + 0.071338158971412172 + 0.071341017289230091 + 0.071343875640932197 + 0.071346734026519323 + 0.071349592445992163 + 0.071352450899351466 + 0.071355309386597801 + 0.071358167907731959 + 0.071361026462754718 + 0.07136388505166659 + 0.07136674367446838 + 0.071369602331160797 + 0.071372461021744549 + 0.071375319746220314 + 0.071378178504588788 + 0.071381037296850747 + 0.071383896123006843 + 0.071386754983057743 + 0.071389613877004321 + 0.071392472804846993 + 0.071395331766586717 + 0.071398190762224006 + 0.071401049791759819 + 0.071403908855194556 + 0.071406767952529204 + 0.071409627083764235 + 0.07141248624890055 + 0.071415345447938636 + 0.07141820468087956 + 0.071421063947723726 + 0.071423923248471757 + 0.071426782583124626 + 0.071429641951682984 + 0.071432501354147429 + 0.071435360790518793 + 0.071438220260797713 + 0.071441079764984913 + 0.071443939303081141 + 0.071446798875086912 + 0.071449658481003209 + 0.07145251812083056 + 0.071455377794569883 + 0.071458237502221605 + 0.071461097243786603 + 0.071463957019265598 + 0.071466816828659227 + 0.071469676671968296 + 0.071472536549193347 + 0.071475396460335294 + 0.071478256405394763 + 0.071481116384372378 + 0.071483976397269111 + 0.071486836444085308 + 0.071489696524821997 + 0.071492556639479732 + 0.071495416788059221 + 0.071498276970561228 + 0.071501137186986488 + 0.071503997437335737 + 0.071506857721609571 + 0.071509718039808767 + 0.071512578391934103 + 0.071515438777986162 + 0.071518299197965818 + 0.071521159651873625 + 0.071524020139710431 + 0.071526880661476847 + 0.071529741217173745 + 0.071532601806801627 + 0.071535462430361282 + 0.071538323087853573 + 0.071541183779279108 + 0.07154404450463861 + 0.071546905263932675 + 0.07154976605716222 + 0.071552626884327869 + 0.071555487745430343 + 0.071558348640470393 + 0.071561209569448669 + 0.071564070532365937 + 0.071566931529222999 + 0.071569792560020412 + 0.071572653624758967 + 0.071575514723439454 + 0.07157837585606254 + 0.071581237022628835 + 0.071584098223139256 + 0.071586959457594371 + 0.071589820725994943 + 0.07159268202834175 + 0.071595543364635486 + 0.071598404734876803 + 0.07160126613906645 + 0.071604127577205259 + 0.071606989049293898 + 0.071609850555332991 + 0.071612712095323314 + 0.071615573669265686 + 0.071618435277160761 + 0.07162129691900912 + 0.07162415859481179 + 0.071627020304569175 + 0.071629882048282245 + 0.071632743825951611 + 0.071635605637578037 + 0.071638467483162258 + 0.071641329362704884 + 0.071644191276206762 + 0.071647053223668558 + 0.071649915205091064 + 0.071652777220474972 + 0.071655639269820895 + 0.071658501353129761 + 0.071661363470402209 + 0.071664225621638974 + 0.071667087806840668 + 0.071669950026008233 + 0.071672812279142212 + 0.071675674566243408 + 0.071678536887312599 + 0.071681399242350397 + 0.071684261631357563 + 0.07168712405433493 + 0.071689986511283083 + 0.071692849002202866 + 0.07169571152709496 + 0.07169857408596006 + 0.071701436678798997 + 0.071704299305612423 + 0.071707161966401103 + 0.071710024661165689 + 0.071712887389907068 + 0.071715750152625823 + 0.071718612949322663 + 0.071721475779998475 + 0.071724338644653857 + 0.071727201543289654 + 0.071730064475906477 + 0.071732927442505104 + 0.071735790443086395 + 0.071738653477650932 + 0.071741516546199383 + 0.071744379648732676 + 0.071747242785251464 + 0.071750105955756441 + 0.071752969160248356 + 0.071755832398728014 + 0.071758695671196096 + 0.071761558977653295 + 0.071764422318100374 + 0.071767285692538083 + 0.071770149100967184 + 0.071773012543388373 + 0.071775876019802481 + 0.071778739530210037 + 0.071781603074611941 + 0.071784466653008888 + 0.0717873302654016 + 0.071790193911790964 + 0.071793057592177467 + 0.071795921306561941 + 0.071798785054945177 + 0.071801648837327897 + 0.071804512653710767 + 0.071807376504094717 + 0.071810240388480162 + 0.071813104306868158 + 0.071815968259259358 + 0.071818832245654468 + 0.071821696266054044 + 0.071824560320459155 + 0.071827424408870313 + 0.071830288531288408 + 0.071833152687714064 + 0.071836016878148085 + 0.071838881102591109 + 0.07184174536104404 + 0.071844609653507585 + 0.071847473979982299 + 0.071850338340469194 + 0.071853202734968841 + 0.071856067163481988 + 0.071858931626009523 + 0.071861796122551988 + 0.071864660653110202 + 0.071867525217684969 + 0.071870389816276956 + 0.071873254448886897 + 0.071876119115515738 + 0.071878983816163936 + 0.071881848550832322 + 0.071884713319521829 + 0.071887578122232912 + 0.071890442958966572 + 0.071893307829723391 + 0.071896172734504132 + 0.071899037673309629 + 0.071901902646140561 + 0.071904767652997637 + 0.071907632693881757 + 0.071910497768793422 + 0.071913362877733603 + 0.071916228020702952 + 0.071919093197702164 + 0.07192195840873214 + 0.071924823653793546 + 0.071927688932887035 + 0.071930554246013606 + 0.071933419593173634 + 0.071936284974368256 + 0.071939150389597931 + 0.071942015838863588 + 0.07194488132216588 + 0.071947746839505486 + 0.071950612390883406 + 0.071953477976300168 + 0.071956343595756686 + 0.071959209249253503 + 0.071962074936791562 + 0.071964940658371501 + 0.071967806413994098 + 0.071970672203660116 + 0.071973538027370373 + 0.071976403885125467 + 0.0719792697769263 + 0.071982135702773453 + 0.071985001662667886 + 0.071987867656610263 + 0.071990733684601252 + 0.071993599746641712 + 0.071996465842732421 + 0.071999331972874003 + 0.072002198137067319 + 0.072005064335313049 + 0.072007930567612038 + 0.072010796833965066 + 0.072013663134372727 + 0.072016529468835841 + 0.072019395837355227 + 0.072022262239931564 + 0.0720251286765657 + 0.072027995147258259 + 0.072030861652010059 + 0.072033728190821961 + 0.072036594763694645 + 0.072039461370628749 + 0.072042328011625148 + 0.072045194686684674 + 0.072048061395807911 + 0.072050928138995732 + 0.072053794916248956 + 0.072056661727568097 + 0.072059528572954126 + 0.072062395452407751 + 0.072065262365929722 + 0.072068129313520843 + 0.072070996295181752 + 0.072073863310913339 + 0.072076730360716323 + 0.072079597444591401 + 0.072082464562539431 + 0.072085331714561066 + 0.072088198900657138 + 0.072091066120828523 + 0.072093933375075761 + 0.072096800663399685 + 0.072099667985801141 + 0.072102535342280838 + 0.072105402732839469 + 0.072108270157477838 + 0.072111137616196808 + 0.072114005108997015 + 0.072116872635879306 + 0.072119740196844404 + 0.072122607791893112 + 0.072125475421026056 + 0.072128343084244151 + 0.072131210781548202 + 0.072134078512938821 + 0.072136946278416797 + 0.072139814077982992 + 0.072142681911638085 + 0.072145549779382784 + 0.072148417681218061 + 0.072151285617144567 + 0.072154153587162942 + 0.072157021591274212 + 0.072159889629478974 + 0.072162757701777908 + 0.072165625808172096 + 0.072168493948661969 + 0.072171362123248442 + 0.072174230331932307 + 0.072177098574714285 + 0.072179966851595181 + 0.072182835162575704 + 0.072185703507656712 + 0.072188571886838873 + 0.072191440300123005 + 0.072194308747509886 + 0.072197177229000237 + 0.072200045744594932 + 0.072202914294294679 + 0.072205782878100103 + 0.072208651496012299 + 0.072211520148031769 + 0.072214388834159357 + 0.072217257554395828 + 0.072220126308742014 + 0.07222299509719865 + 0.072225863919766473 + 0.072228732776446383 + 0.072231601667238909 + 0.072234470592145023 + 0.072237339551165458 + 0.07224020854430091 + 0.072243077571552294 + 0.072245946632920208 + 0.072248815728405566 + 0.072251684858009077 + 0.072254554021731546 + 0.072257423219573763 + 0.072260292451536465 + 0.072263161717620358 + 0.072266031017826415 + 0.072268900352155163 + 0.072271769720607601 + 0.072274639123184409 + 0.072277508559886308 + 0.072280378030714229 + 0.072283247535668713 + 0.07228611707475073 + 0.072288986647961018 + 0.072291856255300241 + 0.07229472589676933 + 0.072297595572369019 + 0.072300465282100115 + 0.072303335025963297 + 0.072306204803959315 + 0.072309074616089167 + 0.072311944462353395 + 0.072314814342752831 + 0.07231768425728842 + 0.072320554205960674 + 0.072323424188770621 + 0.0723262942057189 + 0.072329164256806328 + 0.072332034342033724 + 0.072334904461401811 + 0.072337774614911338 + 0.072340644802563206 + 0.072343515024358096 + 0.072346385280296854 + 0.072349255570380105 + 0.072352125894608807 + 0.072354996252983764 + 0.0723578666455056 + 0.072360737072175205 + 0.072363607532993243 + 0.072366478027960771 + 0.072369348557078286 + 0.072372219120346679 + 0.072375089717766697 + 0.072377960349339146 + 0.072380831015064873 + 0.072383701714944598 + 0.072386572448979072 + 0.072389443217169169 + 0.072392314019515555 + 0.072395184856019104 + 0.072398055726680732 + 0.072400926631500939 + 0.072403797570480669 + 0.072406668543620642 + 0.072409539550921762 + 0.072412410592384707 + 0.072415281668010423 + 0.07241815277779938 + 0.072421023921752661 + 0.072423895099870989 + 0.072426766312155097 + 0.072429637558605625 + 0.072432508839223669 + 0.072435380154009882 + 0.072438251502965068 + 0.072441122886089893 + 0.072443994303385273 + 0.072446865754852069 + 0.072449737240490863 + 0.0724526087603026 + 0.072455480314288029 + 0.072458351902447843 + 0.072461223524782986 + 0.07246409518129425 + 0.072466966871982327 + 0.072469838596847913 + 0.072472710355892048 + 0.072475582149115328 + 0.072478453976518697 + 0.072481325838102822 + 0.072484197733868577 + 0.072487069663816683 + 0.072489941627948015 + 0.072492813626263225 + 0.072495685658763256 + 0.072498557725448901 + 0.072501429826320865 + 0.072504301961379941 + 0.072507174130627031 + 0.072510046334062786 + 0.072512918571688012 + 0.072515790843503611 + 0.072518663149510443 + 0.072521535489708994 + 0.072524407864100374 + 0.072527280272685235 + 0.072530152715464355 + 0.072533025192438594 + 0.072535897703608715 + 0.072538770248975509 + 0.072541642828539796 + 0.072544515442302393 + 0.072547388090264023 + 0.072550260772425545 + 0.072553133488787794 + 0.07255600623935142 + 0.072558879024117368 + 0.072561751843086386 + 0.072564624696259225 + 0.072567497583636675 + 0.07257037050521975 + 0.072573243461008963 + 0.072576116451005215 + 0.072578989475209424 + 0.072581862533622157 + 0.07258473562624447 + 0.072587608753077029 + 0.072590481914120569 + 0.072593355109376007 + 0.07259622833884416 + 0.072599101602525695 + 0.072601974900421487 + 0.072604848232532354 + 0.072607721598859074 + 0.072610594999402506 + 0.072613468434163442 + 0.072616341903142506 + 0.072619215406340781 + 0.072622088943758822 + 0.072624962515397642 + 0.072627836121257908 + 0.072630709761340437 + 0.072633583435646062 + 0.072636457144175548 + 0.072639330886929906 + 0.072642204663909554 + 0.072645078475115601 + 0.072647952320548798 + 0.07265082620020985 + 0.072653700114099523 + 0.072656574062218898 + 0.072659448044568517 + 0.072662322061149295 + 0.072665196111962108 + 0.072668070197007578 + 0.072670944316286554 + 0.072673818469799992 + 0.072676692657548558 + 0.072679566879533086 + 0.072682441135754464 + 0.072685315426213398 + 0.072688189750910764 + 0.072691064109847256 + 0.072693938503023817 + 0.07269681293044121 + 0.072699687392100351 + 0.072702561888001768 + 0.072705436418146516 + 0.072708310982535329 + 0.072711185581168944 + 0.07271406021404829 + 0.0727169348811742 + 0.072719809582547354 + 0.07272268431816864 + 0.072725559088038849 + 0.072728433892158745 + 0.072731308730529215 + 0.072734183603151106 + 0.072737058510025057 + 0.072739933451152095 + 0.072742808426532968 + 0.072745683436168371 + 0.072748558480059136 + 0.072751433558206152 + 0.072754308670610363 + 0.072757183817272322 + 0.072760058998192961 + 0.072762934213373043 + 0.072765809462813566 + 0.07276868474651503 + 0.072771560064478574 + 0.072774435416704794 + 0.072777310803194564 + 0.07278018622394869 + 0.072783061678968086 + 0.072785937168253517 + 0.072788812691805621 + 0.072791688249625508 + 0.072794563841713747 + 0.072797439468071268 + 0.072800315128698903 + 0.072803190823597458 + 0.072806066552767765 + 0.072808942316210545 + 0.07281181811392666 + 0.072814693945917025 + 0.072817569812182403 + 0.072820445712723503 + 0.072823321647541295 + 0.072826197616636446 + 0.072829073620009954 + 0.072831949657662529 + 0.07283482572959496 + 0.072837701835808247 + 0.072840577976302917 + 0.072843454151080039 + 0.07284633036014028 + 0.072849206603484637 + 0.072852082881113681 + 0.072854959193028521 + 0.072857835539229809 + 0.072860711919718241 + 0.072863588334494883 + 0.072866464783560458 + 0.072869341266915813 + 0.072872217784561766 + 0.072875094336498955 + 0.072877970922728491 + 0.072880847543251095 + 0.072883724198067532 + 0.072886600887178715 + 0.072889477610585313 + 0.072892354368288309 + 0.07289523116028844 + 0.072898107986586608 + 0.07290098484718352 + 0.072903861742080106 + 0.072906738671277158 + 0.072909615634775549 + 0.072912492632575918 + 0.072915369664679347 + 0.072918246731086503 + 0.072921123831798232 + 0.07292400096681545 + 0.072926878136138767 + 0.072929755339769226 + 0.072932632577707657 + 0.072935509849954686 + 0.072938387156511339 + 0.07294126449737838 + 0.072944141872556531 + 0.072947019282046832 + 0.072949896725849991 + 0.072952774203966786 + 0.072955651716398076 + 0.072958529263144792 + 0.072961406844207682 + 0.072964284459587539 + 0.072967162109285222 + 0.072970039793301578 + 0.072972917511637467 + 0.072975795264293708 + 0.072978673051271092 + 0.072981550872570286 + 0.072984428728192524 + 0.072987306618138278 + 0.072990184542408604 + 0.072993062501004263 + 0.072995940493925965 + 0.072998818521174763 + 0.073001696582751255 + 0.073004574678656384 + 0.073007452808891121 + 0.07301033097345612 + 0.073013209172352142 + 0.073016087405580216 + 0.073018965673141131 + 0.073021843975035694 + 0.073024722311264695 + 0.073027600681828966 + 0.073030479086729411 + 0.073033357525966847 + 0.07303623599954219 + 0.073039114507456079 + 0.073041993049709361 + 0.073044871626303146 + 0.073047750237238016 + 0.073050628882514859 + 0.073053507562134537 + 0.073056386276097909 + 0.073059265024405795 + 0.073062143807058971 + 0.073065022624058354 + 0.073067901475404734 + 0.073070780361098972 + 0.073073659281141956 + 0.073076538235534352 + 0.073079417224277132 + 0.073082296247371156 + 0.073085175304817271 + 0.073088054396616198 + 0.073090933522768839 + 0.073093812683276124 + 0.073096691878138761 + 0.073099571107357625 + 0.073102450370933547 + 0.07310532966886743 + 0.07310820900116001 + 0.073111088367812285 + 0.073113967768824978 + 0.073116847204198851 + 0.073119726673934973 + 0.073122606178034039 + 0.07312548571649688 + 0.073128365289324315 + 0.073131244896517372 + 0.073134124538076745 + 0.073137004214003265 + 0.07313988392429778 + 0.073142763668961164 + 0.073145643447994249 + 0.073148523261397883 + 0.073151403109172924 + 0.073154282991320221 + 0.073157162907840564 + 0.073160042858734869 + 0.073162922844004011 + 0.073165802863648655 + 0.0731686829176698 + 0.07317156300606828 + 0.073174443128844885 + 0.073177323286000406 + 0.073180203477535927 + 0.073183083703452084 + 0.073185963963749795 + 0.073188844258429794 + 0.073191724587493165 + 0.073194604950940489 + 0.073197485348772767 + 0.073200365780990831 + 0.073203246247595583 + 0.073206126748587647 + 0.073209007283968203 + 0.07321188785373782 + 0.073214768457897497 + 0.073217649096448054 + 0.073220529769390266 + 0.073223410476725065 + 0.073226291218453268 + 0.073229171994575723 + 0.073232052805093303 + 0.073234933650006925 + 0.073237814529317269 + 0.073240695443025292 + 0.073243576391131812 + 0.073246457373637747 + 0.073249338390543858 + 0.073252219441851049 + 0.073255100527560194 + 0.073257981647672055 + 0.073260862802187521 + 0.073263743991107536 + 0.073266625214432779 + 0.073269506472164264 + 0.073272387764302838 + 0.073275269090849263 + 0.073278150451804372 + 0.073281031847169137 + 0.073283913276944349 + 0.073286794741130812 + 0.073289676239729484 + 0.073292557772741213 + 0.073295439340166746 + 0.073298320942007042 + 0.073301202578262864 + 0.073304084248935156 + 0.073306965954024625 + 0.073309847693532465 + 0.073312729467459162 + 0.073315611275805742 + 0.073318493118573011 + 0.073321374995761884 + 0.073324256907373195 + 0.073327138853407706 + 0.073330020833866472 + 0.0733329028487502 + 0.073335784898059822 + 0.073338666981796086 + 0.073341549099959921 + 0.073344431252552286 + 0.073347313439573944 + 0.073350195661025588 + 0.073353077916908441 + 0.073355960207223112 + 0.07335884253197042 + 0.073361724891151364 + 0.073364607284766847 + 0.073367489712817535 + 0.073370372175304469 + 0.073373254672228369 + 0.07337613720359025 + 0.073379019769390805 + 0.073381902369631061 + 0.073384785004311739 + 0.073387667673433757 + 0.073390550376997973 + 0.073393433115005333 + 0.073396315887456459 + 0.073399198694352547 + 0.073402081535694191 + 0.073404964411482365 + 0.073407847321717873 + 0.073410730266401727 + 0.073413613245534595 + 0.073416496259117558 + 0.073419379307151214 + 0.073422262389636658 + 0.073425145506574627 + 0.073428028657966077 + 0.073430911843811772 + 0.073433795064112739 + 0.073436678318869589 + 0.073439561608083362 + 0.073442444931755016 + 0.073445328289885162 + 0.073448211682474798 + 0.073451095109524842 + 0.07345397857103611 + 0.073456862067009479 + 0.07345974559744585 + 0.073462629162345972 + 0.073465512761710844 + 0.073468396395541244 + 0.073471280063838143 + 0.073474163766602235 + 0.073477047503834519 + 0.07347993127553594 + 0.073482815081707245 + 0.073485698922349255 + 0.073488582797462926 + 0.073491466707049133 + 0.073494350651108667 + 0.07349723462964261 + 0.073500118642651588 + 0.073503002690136543 + 0.073505886772098392 + 0.073508770888538036 + 0.073511655039456211 + 0.073514539224853889 + 0.073517423444731944 + 0.073520307699091209 + 0.073523191987932612 + 0.073526076311256947 + 0.073528960669065196 + 0.07353184506135807 + 0.073534729488136552 + 0.073537613949401587 + 0.073540498445153799 + 0.073543382975394408 + 0.073546267540123986 + 0.073549152139343585 + 0.073552036773053928 + 0.073554921441256152 + 0.073557806143950799 + 0.073560690881138951 + 0.073563575652821483 + 0.073566460458999242 + 0.073569345299672934 + 0.073572230174843753 + 0.07357511508451238 + 0.07357800002867966 + 0.073580885007346608 + 0.073583770020514 + 0.073586655068182738 + 0.073589540150353586 + 0.073592425267027681 + 0.073595310418205676 + 0.073598195603888625 + 0.07360108082407725 + 0.073603966078772468 + 0.073606851367975179 + 0.073609736691686342 + 0.073612622049906665 + 0.073615507442637132 + 0.073618392869878646 + 0.073621278331631998 + 0.073624163827898145 + 0.073627049358677948 + 0.073629934923972198 + 0.073632820523781992 + 0.07363570615810805 + 0.073638591826951205 + 0.073641477530312513 + 0.073644363268192625 + 0.073647249040592624 + 0.073650134847513357 + 0.07365302068895567 + 0.073655906564920423 + 0.073658792475408505 + 0.073661678420420817 + 0.073664564399958277 + 0.073667450414021715 + 0.073670336462612021 + 0.073673222545730124 + 0.073676108663376774 + 0.073678994815553026 + 0.073681881002259711 + 0.073684767223497677 + 0.073687653479267826 + 0.073690539769571003 + 0.073693426094408196 + 0.073696312453780208 + 0.073699198847687927 + 0.073702085276132298 + 0.073704971739114084 + 0.073707858236634297 + 0.07371074476869377 + 0.073713631335293447 + 0.073716517936434162 + 0.073719404572116745 + 0.073722291242342183 + 0.073725177947111337 + 0.073728064686425107 + 0.073730951460284314 + 0.073733838268689955 + 0.073736725111642781 + 0.07373961198914375 + 0.073742498901193776 + 0.073745385847793762 + 0.073748272828944486 + 0.073751159844647002 + 0.073754046894902045 + 0.073756933979710559 + 0.073759821099073503 + 0.073762708252991693 + 0.073765595441466145 + 0.073768482664497495 + 0.073771369922086771 + 0.073774257214235028 + 0.073777144540942835 + 0.073780031902211413 + 0.073782919298041427 + 0.073785806728433781 + 0.073788694193389501 + 0.073791581692909294 + 0.073794469226994314 + 0.073797356795645128 + 0.07380024439886293 + 0.0738031320366484 + 0.073806019709002621 + 0.073808907415926356 + 0.073811795157420507 + 0.073814682933485989 + 0.07381757074412372 + 0.073820458589334545 + 0.07382334646911938 + 0.073826234383479156 + 0.073829122332414759 + 0.073832010315927038 + 0.073834898334016907 + 0.073837786386685172 + 0.073840674473932957 + 0.073843562595760998 + 0.073846450752170195 + 0.073849338943161494 + 0.073852227168735796 + 0.073855115428893919 + 0.073858003723636836 + 0.073860892052965449 + 0.07386378041688052 + 0.07386666881538323 + 0.073869557248474216 + 0.073872445716154492 + 0.07387533421842489 + 0.073878222755286355 + 0.073881111326739829 + 0.073883999932786187 + 0.073886888573426276 + 0.073889777248660984 + 0.073892665958491255 + 0.073895554702918032 + 0.073898443481942216 + 0.073901332295564615 + 0.073904221143786114 + 0.073907110026607714 + 0.073909998944030372 + 0.073912887896054755 + 0.073915776882681999 + 0.073918665903912967 + 0.073921554959748392 + 0.073924444050189331 + 0.073927333175236615 + 0.073930222334891257 + 0.073933111529154175 + 0.073936000758026033 + 0.073938890021507969 + 0.073941779319600803 + 0.073944668652305409 + 0.073947558019622717 + 0.073950447421553656 + 0.073953336858099072 + 0.073956226329260022 + 0.073959115835037198 + 0.073962005375431614 + 0.073964894950444199 + 0.073967784560075939 + 0.073970674204327444 + 0.073973563883199853 + 0.073976453596694053 + 0.073979343344810961 + 0.073982233127551408 + 0.073985122944916368 + 0.073988012796906727 + 0.073990902683523291 + 0.073993792604767211 + 0.07399668256063914 + 0.073999572551140175 + 0.074002462576271091 + 0.074005352636032792 + 0.074008242730426346 + 0.074011132859452503 + 0.07401402302311226 + 0.074016913221406494 + 0.074019803454336175 + 0.074022693721902094 + 0.074025584024105237 + 0.074028474360946436 + 0.074031364732426816 + 0.074034255138547014 + 0.074037145579308142 + 0.074040036054710892 + 0.074042926564756459 + 0.074045817109445508 + 0.07404870768877915 + 0.074051598302758176 + 0.074054488951383557 + 0.07405737963465614 + 0.074060270352576937 + 0.074063161105146713 + 0.074066051892366522 + 0.074068942714237182 + 0.074071833570759665 + 0.074074724461934902 + 0.074077615387763696 + 0.074080506348247047 + 0.07408339734338594 + 0.074086288373181208 + 0.074089179437633684 + 0.074092070536744339 + 0.074094961670514256 + 0.074097852838944128 + 0.074100744042034983 + 0.07410363527978775 + 0.074106526552203261 + 0.074109417859282364 + 0.074112309201026197 + 0.074115200577435536 + 0.074118091988511409 + 0.074120983434254592 + 0.07412387491466603 + 0.074126766429746777 + 0.074129657979497568 + 0.074132549563919403 + 0.074135441183013212 + 0.074138332836779994 + 0.074141224525220428 + 0.074144116248335695 + 0.074147008006126475 + 0.074149899798593891 + 0.074152791625738831 + 0.074155683487562116 + 0.074158575384064743 + 0.074161467315247545 + 0.074164359281111619 + 0.074167251281657728 + 0.07417014331688683 + 0.074173035386799854 + 0.074175927491397703 + 0.074178819630681306 + 0.074181711804651634 + 0.074184604013309507 + 0.074187496256656035 + 0.074190388534691995 + 0.074193280847418289 + 0.074196173194835874 + 0.074199065576945708 + 0.074201957993748652 + 0.074204850445245718 + 0.074207742931437753 + 0.074210635452325688 + 0.074213528007910576 + 0.074216420598193167 + 0.074219313223174446 + 0.074222205882855302 + 0.074225098577236789 + 0.074227991306319699 + 0.074230884070105016 + 0.074233776868593601 + 0.074236669701786384 + 0.074239562569684531 + 0.074242455472288693 + 0.074245348409599857 + 0.074248241381619035 + 0.074251134388347059 + 0.074254027429784861 + 0.074256920505933438 + 0.07425981361679368 + 0.074262706762366515 + 0.074265599942652874 + 0.074268493157653631 + 0.074271386407369841 + 0.074274279691802267 + 0.074277173010951963 + 0.074280066364819888 + 0.074282959753406833 + 0.074285853176713823 + 0.074288746634741831 + 0.074291640127491704 + 0.074294533654964301 + 0.074297427217160761 + 0.074300320814081791 + 0.07430321444572853 + 0.074306108112101754 + 0.074309001813202477 + 0.074311895549031545 + 0.074314789319589986 + 0.074317683124878742 + 0.074320576964898549 + 0.074323470839650671 + 0.074326364749135759 + 0.074329258693354855 + 0.074332152672308915 + 0.074335046685998801 + 0.074337940734425456 + 0.074340834817589893 + 0.074343728935492931 + 0.07434662308813568 + 0.074349517275518945 + 0.074352411497643614 + 0.0743553057545107 + 0.07435820004612112 + 0.074361094372475914 + 0.074363988733575803 + 0.074366883129421898 + 0.07436977756001506 + 0.074372672025356162 + 0.074375566525446385 + 0.07437846106028638 + 0.074381355629877244 + 0.074384250234219892 + 0.074387144873315159 + 0.074390039547164166 + 0.074392934255767693 + 0.074395828999126709 + 0.074398723777242257 + 0.074401618590115182 + 0.074404513437746414 + 0.074407408320136897 + 0.074410303237287645 + 0.074413198189199586 + 0.074416093175873457 + 0.074418988197310465 + 0.074421883253511456 + 0.074424778344477319 + 0.074427673470209052 + 0.074430568630707516 + 0.074433463825973781 + 0.07443635905600865 + 0.074439254320813206 + 0.074442149620388295 + 0.074445044954734835 + 0.074447940323853837 + 0.074450835727746204 + 0.074453731166412948 + 0.074456626639854889 + 0.074459522148073082 + 0.074462417691068358 + 0.074465313268841787 + 0.074468208881394313 + 0.074471104528726739 + 0.074474000210840038 + 0.074476895927735348 + 0.074479791679413404 + 0.07448268746587508 + 0.074485583287121584 + 0.074488479143153832 + 0.074491375033972518 + 0.074494270959578821 + 0.074497166919973518 + 0.074500062915157775 + 0.074502958945132286 + 0.07450585500989812 + 0.074508751109456262 + 0.074511647243807641 + 0.074514543412953105 + 0.074517439616893763 + 0.074520335855630504 + 0.074523232129164063 + 0.074526128437495731 + 0.074529024780626299 + 0.074531921158556669 + 0.074534817571287756 + 0.074537714018820714 + 0.07454061050115629 + 0.074543507018295457 + 0.074546403570239353 + 0.074549300156988699 + 0.074552196778544563 + 0.074555093434907779 + 0.074557990126079471 + 0.074560886852060429 + 0.074563783612851778 + 0.074566680408454239 + 0.07456957723886902 + 0.07457247410409687 + 0.074575371004138843 + 0.074578267938995815 + 0.074581164908668771 + 0.074584061913158681 + 0.074586958952466573 + 0.074589856026593224 + 0.07459275313553973 + 0.074595650279307021 + 0.074598547457895958 + 0.074601444671307554 + 0.07460434191954278 + 0.074607239202602593 + 0.074610136520487896 + 0.074613033873199758 + 0.074615931260739024 + 0.07461882868310668 + 0.07462172614030356 + 0.074624623632330869 + 0.074627521159189428 + 0.074630418720880096 + 0.074633316317404025 + 0.074636213948762006 + 0.07463911161495515 + 0.07464200931598422 + 0.074644907051850354 + 0.074647804822554328 + 0.074650702628097323 + 0.074653600468480144 + 0.074656498343703789 + 0.074659396253769203 + 0.074662294198677329 + 0.07466519217842911 + 0.074668090193025574 + 0.074670988242467581 + 0.074673886326756284 + 0.074676784445892375 + 0.074679682599877048 + 0.074682580788711136 + 0.074685479012395639 + 0.074688377270931416 + 0.074691275564319579 + 0.074694173892561 + 0.074697072255656694 + 0.07469997065360752 + 0.074702869086414617 + 0.074705767554078789 + 0.074708666056601009 + 0.074711564593982344 + 0.074714463166223585 + 0.074717361773325927 + 0.074720260415290035 + 0.074723159092117089 + 0.074726057803808171 + 0.074728956550363865 + 0.074731855331785405 + 0.074734754148073748 + 0.074737652999229728 + 0.074740551885254372 + 0.074743450806148665 + 0.074746349761913564 + 0.074749248752549999 + 0.074752147778058942 + 0.074755046838441447 + 0.074757945933698347 + 0.07476084506383078 + 0.074763744228839427 + 0.074766643428725535 + 0.074769542663489966 + 0.074772441933133676 + 0.074775341237657611 + 0.074778240577062727 + 0.074781139951350051 + 0.074784039360520568 + 0.074786938804575209 + 0.074789838283514862 + 0.074792737797340622 + 0.074795637346053309 + 0.074798536929654103 + 0.074801436548143738 + 0.074804336201523366 + 0.074807235889793947 + 0.074810135612956227 + 0.074813035371011458 + 0.074815935163960456 + 0.074818834991804251 + 0.074821734854543687 + 0.074824634752179875 + 0.074827534684713787 + 0.074830434652146283 + 0.074833334654478362 + 0.074836234691711107 + 0.074839134763845405 + 0.07484203487088216 + 0.074844935012822439 + 0.074847835189667283 + 0.074850735401417498 + 0.074853635648074096 + 0.074856535929638132 + 0.074859436246110495 + 0.07486233659749221 + 0.074865236983784222 + 0.07486813740498742 + 0.074871037861103024 + 0.074873938352131825 + 0.074876838878074725 + 0.074879739438932849 + 0.074882640034707154 + 0.074885540665398459 + 0.074888441331008013 + 0.074891342031536551 + 0.074894242766985114 + 0.074897143537354688 + 0.074900044342646313 + 0.074902945182860906 + 0.074905846057999381 + 0.074908746968062823 + 0.07491164791305209 + 0.074914548892968252 + 0.074917449907812309 + 0.074920350957585216 + 0.074923252042287919 + 0.074926153161921333 + 0.074929054316486512 + 0.074931955505984485 + 0.074934856730416138 + 0.074937757989782444 + 0.074940659284084429 + 0.074943560613323121 + 0.074946461977499365 + 0.074949363376614286 + 0.074952264810668759 + 0.074955166279663782 + 0.07495806778360041 + 0.074960969322479476 + 0.074963870896301993 + 0.074966772505069126 + 0.074969674148781654 + 0.074972575827440574 + 0.074975477541047039 + 0.074978379289601813 + 0.07498128107310606 + 0.0749841828915606 + 0.074987084744966542 + 0.074989986633324734 + 0.074992888556636383 + 0.074995790514902141 + 0.074998692508123285 + 0.075001594536300661 + 0.075004496599435311 + 0.075007398697528191 + 0.075010300830580176 + 0.075013202998592474 + 0.075016105201565944 + 0.075019007439501476 + 0.075021909712400206 + 0.075024812020263149 + 0.07502771436309108 + 0.075030616740885153 + 0.075033519153646297 + 0.075036421601375622 + 0.07503932408407378 + 0.075042226601742201 + 0.075045129154381496 + 0.075048031741992857 + 0.075050934364577312 + 0.075053837022135556 + 0.075056739714668946 + 0.075059642442178207 + 0.075062545204664335 + 0.075065448002128596 + 0.075068350834571626 + 0.07507125370199462 + 0.075074156604398479 + 0.075077059541784216 + 0.075079962514152887 + 0.075082865521505393 + 0.075085768563842692 + 0.075088671641165852 + 0.075091574753475984 + 0.07509447790077374 + 0.075097381083060355 + 0.075100284300336842 + 0.075103187552604117 + 0.075106090839863082 + 0.075108994162114806 + 0.075111897519360343 + 0.075114800911600652 + 0.075117704338836633 + 0.075120607801069467 + 0.075123511298299875 + 0.075126414830529092 + 0.075129318397758008 + 0.075132221999987647 + 0.075135125637218927 + 0.075138029309452931 + 0.075140933016690656 + 0.07514383675893295 + 0.075146740536180909 + 0.075149644348435657 + 0.075152548195697916 + 0.075155452077968837 + 0.07515835599524949 + 0.075161259947540707 + 0.075164163934843556 + 0.075167067957159051 + 0.07516997201448819 + 0.075172876106831904 + 0.075175780234191192 + 0.075178684396567164 + 0.075181588593960708 + 0.075184492826372809 + 0.075187397093804495 + 0.075190301396256876 + 0.07519320573373077 + 0.075196110106227218 + 0.075199014513747331 + 0.075201918956291941 + 0.075204823433862131 + 0.075207727946458983 + 0.075210632494083329 + 0.075213537076736212 + 0.075216441694418698 + 0.075219346347131774 + 0.075222251034876411 + 0.075225155757653608 + 0.075228060515464323 + 0.075230965308309694 + 0.07523387013619065 + 0.075236774999107997 + 0.075239679897063053 + 0.07524258483005665 + 0.075245489798089718 + 0.075248394801163423 + 0.075251299839278668 + 0.075254204912436506 + 0.075257110020637855 + 0.075260015163883878 + 0.075262920342175382 + 0.075265825555513505 + 0.075268730803899106 + 0.075271636087333449 + 0.075274541405817227 + 0.075277446759351635 + 0.075280352147937685 + 0.075283257571576237 + 0.075286163030268388 + 0.075289068524015179 + 0.075291974052817609 + 0.075294879616676552 + 0.075297785215593133 + 0.075300690849568308 + 0.075303596518603119 + 0.075306502222698593 + 0.075309407961855618 + 0.075312313736075276 + 0.075315219545358664 + 0.075318125389706628 + 0.075321031269120292 + 0.075323937183600531 + 0.075326843133148413 + 0.075329749117765132 + 0.075332655137451354 + 0.075335561192208397 + 0.075338467282036956 + 0.075341373406938444 + 0.075344279566913377 + 0.075347185761963212 + 0.075350091992088725 + 0.075352998257290929 + 0.075355904557570921 + 0.075358810892929631 + 0.075361717263368072 + 0.075364623668887271 + 0.075367530109488282 + 0.075370436585172049 + 0.075373343095939696 + 0.075376249641792056 + 0.075379156222730268 + 0.075382062838755273 + 0.075384969489868156 + 0.075387876176069832 + 0.075390782897361328 + 0.075393689653743795 + 0.075396596445218025 + 0.075399503271785268 + 0.075402410133446424 + 0.075405317030202423 + 0.075408223962054363 + 0.075411130929003201 + 0.075414037931050032 + 0.07541694496819587 + 0.07541985204044159 + 0.075422759147788371 + 0.075425666290237114 + 0.075428573467788862 + 0.07543148068044471 + 0.075434387928205615 + 0.075437295211072508 + 0.075440202529046541 + 0.075443109882128614 + 0.075446017270319743 + 0.075448924693621106 + 0.075451832152033521 + 0.075454739645558169 + 0.075457647174195924 + 0.075460554737947869 + 0.075463462336815085 + 0.075466369970798503 + 0.075469277639899093 + 0.075472185344117884 + 0.075475093083455985 + 0.075478000857914493 + 0.075480908667494184 + 0.075483816512196197 + 0.075486724392021587 + 0.07548963230697131 + 0.075492540257046381 + 0.075495448242247909 + 0.075498356262576824 + 0.075501264318034153 + 0.075504172408621034 + 0.075507080534338245 + 0.075509988695186908 + 0.075512896891168219 + 0.075515805122283008 + 0.075518713388532346 + 0.075521621689917245 + 0.075524530026438802 + 0.07552743839809796 + 0.075530346804895593 + 0.075533255246833034 + 0.075536163723911157 + 0.075539072236130905 + 0.075541980783493431 + 0.075544889365999596 + 0.075547797983650605 + 0.075550706636447376 + 0.075553615324390991 + 0.075556524047482476 + 0.075559432805722734 + 0.075562341599112876 + 0.075565250427653941 + 0.075568159291346984 + 0.075571068190192853 + 0.075573977124192782 + 0.075576886093347714 + 0.075579795097658678 + 0.075582704137126672 + 0.075585613211752709 + 0.075588522321537913 + 0.075591431466483172 + 0.075594340646589611 + 0.075597249861858229 + 0.07560015911229008 + 0.075603068397886108 + 0.07560597771864741 + 0.075608887074575068 + 0.0756117964656699 + 0.07561470589193317 + 0.075617615353365739 + 0.075620524849968784 + 0.075623434381743154 + 0.075626343948690014 + 0.075629253550810405 + 0.075632163188105242 + 0.075635072860575636 + 0.075637982568222462 + 0.075640892311047092 + 0.07564380208905018 + 0.075646711902232933 + 0.075649621750596516 + 0.075652531634141665 + 0.075655441552869629 + 0.075658351506781255 + 0.075661261495877749 + 0.075664171520160112 + 0.0756670815796293 + 0.075669991674286396 + 0.075672901804132373 + 0.075675811969168394 + 0.075678722169395266 + 0.075681632404814278 + 0.075684542675426292 + 0.075687452981232403 + 0.075690363322233695 + 0.075693273698431054 + 0.075696184109825662 + 0.075699094556418364 + 0.075702005038210382 + 0.075704915555202798 + 0.075707826107396445 + 0.075710736694792363 + 0.075713647317391733 + 0.075716557975195539 + 0.075719468668204823 + 0.075722379396420472 + 0.07572529015984375 + 0.075728200958475642 + 0.075731111792317021 + 0.075734022661369124 + 0.075736933565632727 + 0.075739844505109233 + 0.075742755479799403 + 0.07574566648970435 + 0.07574857753482514 + 0.075751488615162704 + 0.075754399730718236 + 0.075757310881492679 + 0.075760222067487032 + 0.075763133288702433 + 0.075766044545139882 + 0.075768955836800378 + 0.075771867163685058 + 0.075774778525794867 + 0.075777689923130775 + 0.075780601355693991 + 0.075783512823485472 + 0.075786424326506355 + 0.075789335864757459 + 0.075792247438240062 + 0.07579515904695501 + 0.075798070690903441 + 0.075800982370086409 + 0.075803894084504927 + 0.075806805834159982 + 0.075809717619052766 + 0.075812629439184182 + 0.075815541294555394 + 0.075818453185167195 + 0.075821365111020972 + 0.075824277072117488 + 0.075827189068457937 + 0.075830101100043304 + 0.075833013166874727 + 0.075835925268952969 + 0.075838837406279447 + 0.075841749578854978 + 0.075844661786680659 + 0.075847574029757558 + 0.075850486308086607 + 0.075853398621669024 + 0.075856310970505644 + 0.075859223354597771 + 0.075862135773946321 + 0.075865048228552195 + 0.07586796071841663 + 0.075870873243540707 + 0.075873785803925287 + 0.075876698399571493 + 0.075879611030480382 + 0.075882523696653076 + 0.075885436398090561 + 0.075888349134793767 + 0.07589126190676386 + 0.075894174714001922 + 0.075897087556509008 + 0.07590000043428613 + 0.075902913347334094 + 0.075905826295654358 + 0.075908739279247864 + 0.075911652298115348 + 0.075914565352258281 + 0.075917478441677386 + 0.075920391566373938 + 0.075923304726348881 + 0.075926217921603242 + 0.075929131152138188 + 0.07593204441795455 + 0.075934957719053578 + 0.075937871055436354 + 0.075940784427103822 + 0.075943697834056911 + 0.075946611276296913 + 0.075949524753824757 + 0.075952438266641484 + 0.075955351814748176 + 0.075958265398145985 + 0.075961179016835731 + 0.075964092670818634 + 0.075967006360095804 + 0.075969920084668033 + 0.075972833844536625 + 0.075975747639702496 + 0.075978661470166797 + 0.075981575335930571 + 0.075984489236994787 + 0.075987403173360585 + 0.075990317145028893 + 0.075993231152000934 + 0.075996145194277651 + 0.075999059271860153 + 0.076001973384749441 + 0.076004887532946638 + 0.076007801716452758 + 0.076010715935268883 + 0.07601363018939597 + 0.076016544478835144 + 0.076019458803587583 + 0.076022373163654122 + 0.076025287559035953 + 0.076028201989734132 + 0.076031116455749698 + 0.076034030957083665 + 0.076036945493737143 + 0.076039860065711132 + 0.076042774673006699 + 0.076045689315625054 + 0.07604860399356711 + 0.076051518706833923 + 0.076054433455426493 + 0.076057348239346095 + 0.076060263058593522 + 0.076063177913170077 + 0.076066092803076718 + 0.076069007728314403 + 0.076071922688884325 + 0.076074837684787636 + 0.076077752716025057 + 0.076080667782597949 + 0.076083582884507242 + 0.076086498021754101 + 0.076089413194339539 + 0.076092328402264472 + 0.076095243645530261 + 0.076098158924137682 + 0.076101074238087887 + 0.07610398958738207 + 0.076106904972021147 + 0.076109820392006228 + 0.076112735847338311 + 0.07611565133801855 + 0.076118566864047929 + 0.076121482425427628 + 0.076124398022158521 + 0.076127313654241913 + 0.076130229321678733 + 0.076133145024470023 + 0.076136060762616933 + 0.076138976536120423 + 0.076141892344981588 + 0.076144808189201621 + 0.076147724068781342 + 0.076150639983722054 + 0.076153555934024758 + 0.076156471919690369 + 0.076159387940720191 + 0.076162303997115099 + 0.076165220088876287 + 0.076168136216004767 + 0.076171052378501497 + 0.076173968576367823 + 0.076176884809604481 + 0.076179801078212803 + 0.076182717382193663 + 0.076185633721548213 + 0.07618855009627766 + 0.076191466506382935 + 0.076194382951864925 + 0.076197299432725102 + 0.076200215948964173 + 0.07620313250058347 + 0.076206049087583896 + 0.07620896570996652 + 0.076211882367732534 + 0.076214799060882799 + 0.076217715789418675 + 0.07622063255334105 + 0.076223549352651007 + 0.076226466187349642 + 0.076229383057438024 + 0.07623229996291718 + 0.076235216903788178 + 0.076238133880052281 + 0.076241050891710307 + 0.076243967938763507 + 0.076246885021212768 + 0.076249802139059394 + 0.076252719292304288 + 0.076255636480948477 + 0.076258553704993223 + 0.07626147096443954 + 0.076264388259288468 + 0.076267305589541048 + 0.076270222955198308 + 0.076273140356261551 + 0.076276057792731569 + 0.076278975264609652 + 0.076281892771896856 + 0.076284810314594054 + 0.076287727892702509 + 0.076290645506223248 + 0.07629356315515734 + 0.076296480839505895 + 0.076299398559269926 + 0.076302316314450558 + 0.076305234105048844 + 0.076308151931065923 + 0.076311069792502725 + 0.076313987689360471 + 0.076316905621640216 + 0.076319823589342931 + 0.076322741592469809 + 0.076325659631021905 + 0.076328577705000303 + 0.076331495814406056 + 0.076334413959240233 + 0.076337332139503972 + 0.076340250355198272 + 0.076343168606324174 + 0.076346086892882942 + 0.07634900521487549 + 0.076351923572302915 + 0.07635484196516644 + 0.076357760393466964 + 0.076360678857205697 + 0.076363597356383678 + 0.076366515891001879 + 0.076369434461061536 + 0.076372353066563647 + 0.076375271707509323 + 0.076378190383899675 + 0.076381109095735783 + 0.076384027843018606 + 0.076386946625749338 + 0.076389865443929172 + 0.076392784297558899 + 0.07639570318663981 + 0.076398622111172945 + 0.076401541071159346 + 0.076404460066600233 + 0.076407379097496453 + 0.076410298163849283 + 0.076413217265659791 + 0.076416136402928991 + 0.076419055575658049 + 0.076421974783847935 + 0.076424894027499829 + 0.076427813306614745 + 0.076430732621193889 + 0.076433651971238165 + 0.076436571356748848 + 0.076439490777726854 + 0.076442410234173419 + 0.076445329726089487 + 0.076448249253476264 + 0.076451168816334791 + 0.076454088414666152 + 0.076457008048471428 + 0.076459927717751772 + 0.076462847422508098 + 0.076465767162741755 + 0.076468686938453559 + 0.076471606749644774 + 0.076474526596316469 + 0.076477446478469671 + 0.076480366396105559 + 0.076483286349225119 + 0.076486206337829474 + 0.076489126361919763 + 0.076492046421497012 + 0.076494966516562277 + 0.076497886647116875 + 0.076500806813161626 + 0.076503727014697667 + 0.07650664725172622 + 0.076509567524248256 + 0.076512487832264969 + 0.0765154081757774 + 0.076518328554786547 + 0.076521248969293659 + 0.076524169419299654 + 0.076527089904805917 + 0.0765300104258132 + 0.076532930982322833 + 0.076535851574335706 + 0.076538772201853164 + 0.076541692864876054 + 0.076544613563405584 + 0.076547534297442932 + 0.076550455066989029 + 0.07655337587204511 + 0.07655629671261216 + 0.076559217588691317 + 0.076562138500283664 + 0.07656505944739031 + 0.07656798043001245 + 0.076570901448150874 + 0.076573822501806985 + 0.076576743590981836 + 0.076579664715676371 + 0.076582585875891826 + 0.0765855070716292 + 0.076588428302889602 + 0.076591349569674214 + 0.076594270871984074 + 0.076597192209820253 + 0.076600113583183943 + 0.076603034992076172 + 0.076605956436497924 + 0.076608877916450574 + 0.07661179943193494 + 0.0766147209829523 + 0.076617642569503722 + 0.076620564191590218 + 0.076623485849212997 + 0.076626407542373084 + 0.076629329271071564 + 0.076632251035309754 + 0.076635172835088389 + 0.07663809467040883 + 0.076641016541272089 + 0.07664393844767925 + 0.076646860389631449 + 0.076649782367129785 + 0.076652704380175393 + 0.07665562642876933 + 0.076658548512912678 + 0.076661470632606574 + 0.076664392787852101 + 0.076667314978650328 + 0.076670237205002462 + 0.076673159466909488 + 0.076676081764372628 + 0.076679004097392908 + 0.076681926465971356 + 0.076684848870109207 + 0.076687771309807556 + 0.076690693785067474 + 0.076693616295890041 + 0.076696538842276396 + 0.076699461424227622 + 0.076702384041744814 + 0.076705306694829001 + 0.076708229383481499 + 0.076711152107703268 + 0.076714074867495471 + 0.07671699766285911 + 0.076719920493795404 + 0.076722843360305382 + 0.076725766262390249 + 0.076728689200051048 + 0.076731612173288791 + 0.076734535182104643 + 0.076737458226499869 + 0.076740381306475397 + 0.076743304422032449 + 0.076746227573171968 + 0.076749150759895121 + 0.076752073982203226 + 0.07675499724009717 + 0.076757920533578064 + 0.076760843862647171 + 0.076763767227305435 + 0.076766690627554035 + 0.076769614063394012 + 0.076772537534826615 + 0.076775461041852872 + 0.076778384584473836 + 0.076781308162690742 + 0.076784231776504688 + 0.076787155425916534 + 0.076790079110927792 + 0.076793002831539212 + 0.076795926587752167 + 0.076798850379567643 + 0.076801774206986723 + 0.076804698070010599 + 0.076807621968640341 + 0.076810545902877073 + 0.076813469872721973 + 0.076816393878176015 + 0.076819317919240404 + 0.076822241995916168 + 0.076825166108204612 + 0.07682809025610661 + 0.076831014439623396 + 0.076833938658756137 + 0.076836862913505777 + 0.076839787203873605 + 0.076842711529860691 + 0.076845635891468062 + 0.076848560288696965 + 0.076851484721548402 + 0.076854409190023509 + 0.076857333694123481 + 0.07686025823384933 + 0.076863182809202207 + 0.076866107420183238 + 0.076869032066793616 + 0.076871956749034243 + 0.076874881466906533 + 0.076877806220411307 + 0.07688073100954991 + 0.076883655834323258 + 0.07688658069473267 + 0.076889505590779186 + 0.076892430522463862 + 0.076895355489787848 + 0.076898280492752297 + 0.07690120553135836 + 0.076904130605606941 + 0.076907055715499439 + 0.0769099808610368 + 0.076912906042220244 + 0.076915831259050868 + 0.076918756511529698 + 0.076921681799657957 + 0.076924607123436725 + 0.076927532482867114 + 0.076930457877950262 + 0.076933383308687264 + 0.076936308775079301 + 0.076939234277127386 + 0.07694215981483285 + 0.076945085388196596 + 0.076948010997219762 + 0.076950936641903583 + 0.076953862322249031 + 0.076956788038257506 + 0.076959713789929801 + 0.076962639577267219 + 0.076965565400270899 + 0.076968491258941868 + 0.076971417153281332 + 0.076974343083290375 + 0.076977269048970107 + 0.076980195050321637 + 0.076983121087346187 + 0.076986047160044785 + 0.076988973268418581 + 0.076991899412468742 + 0.076994825592196281 + 0.076997751807602446 + 0.077000678058688279 + 0.07700360434545496 + 0.077006530667903597 + 0.077009457026035413 + 0.077012383419851255 + 0.077015309849352578 + 0.077018236314540314 + 0.077021162815415573 + 0.077024089351979574 + 0.077027015924233347 + 0.077029942532178222 + 0.07703286917581513 + 0.077035795855145278 + 0.077038722570169721 + 0.077041649320889666 + 0.077044576107306195 + 0.077047502929420461 + 0.077050429787233685 + 0.077053356680746823 + 0.077056283609961043 + 0.077059210574877565 + 0.077062137575497416 + 0.077065064611821846 + 0.077067991683851825 + 0.077070918791588672 + 0.077073845935033386 + 0.077076773114187078 + 0.077079700329050996 + 0.077082627579626167 + 0.07708555486591373 + 0.077088482187914892 + 0.077091409545630721 + 0.077094336939062369 + 0.077097264368210947 + 0.077100191833077689 + 0.077103119333663553 + 0.077106046869969844 + 0.077108974441997546 + 0.077111902049747882 + 0.07711482969322192 + 0.077117757372420839 + 0.077120685087345833 + 0.077123612837997846 + 0.077126540624378251 + 0.077129468446488117 + 0.077132396304328402 + 0.077135324197900465 + 0.077138252127205251 + 0.077141180092244035 + 0.077144108093017874 + 0.077147036129527946 + 0.077149964201775389 + 0.077152892309761342 + 0.077155820453486859 + 0.077158748632953245 + 0.077161676848161456 + 0.07716460509911266 + 0.077167533385808104 + 0.077170461708248858 + 0.077173390066436143 + 0.077176318460370805 + 0.077179246890054343 + 0.07718217535548777 + 0.077185103856672099 + 0.077188032393608635 + 0.077190960966298378 + 0.077193889574742588 + 0.077196818218942295 + 0.077199746898898705 + 0.077202675614612984 + 0.077205604366086228 + 0.077208533153319561 + 0.077211461976314164 + 0.077214390835071117 + 0.077217319729591616 + 0.077220248659876783 + 0.077223177625927814 + 0.077226106627745691 + 0.077229035665331805 + 0.07723196473868707 + 0.077234893847812763 + 0.077237822992709884 + 0.077240752173379737 + 0.077243681389823307 + 0.077246610642041871 + 0.077249539930036554 + 0.077252469253808381 + 0.077255398613358672 + 0.077258328008688398 + 0.077261257439798781 + 0.077264186906690971 + 0.077267116409366177 + 0.077270045947825466 + 0.077272975522069978 + 0.077275905132100739 + 0.077278834777919109 + 0.07728176445952617 + 0.077284694176923088 + 0.077287623930110849 + 0.077290553719090757 + 0.077293483543863964 + 0.077296413404431413 + 0.077299343300794535 + 0.077302273232954244 + 0.077305203200911929 + 0.077308133204668436 + 0.077311063244225098 + 0.077313993319583107 + 0.077316923430743423 + 0.077319853577707362 + 0.077322783760476077 + 0.077325713979050553 + 0.077328644233432137 + 0.077331574523621743 + 0.077334504849620719 + 0.077337435211430133 + 0.077340365609051179 + 0.077343296042484924 + 0.077346226511732646 + 0.077349157016795331 + 0.077352087557674226 + 0.077355018134370554 + 0.077357948746885244 + 0.077360879395219684 + 0.077363810079374803 + 0.077366740799352032 + 0.077369671555152258 + 0.077372602346776745 + 0.077375533174226671 + 0.077378464037503106 + 0.077381394936607242 + 0.077384325871540247 + 0.077387256842303229 + 0.077390187848897438 + 0.077393118891323873 + 0.077396049969583755 + 0.07739898108367832 + 0.077401912233608691 + 0.077404843419375896 + 0.077407774640981281 + 0.077410705898425788 + 0.07741363719171071 + 0.077416568520837198 + 0.077419499885806306 + 0.077422431286619339 + 0.077425362723277283 + 0.077428294195781511 + 0.07743122570413298 + 0.077434157248332885 + 0.077437088828382489 + 0.077440020444282748 + 0.077442952096034953 + 0.07744588378364034 + 0.077448815507099922 + 0.077451747266414891 + 0.077454679061586443 + 0.07745761089261563 + 0.0774605427595038 + 0.077463474662251994 + 0.077466406600861251 + 0.077469338575332961 + 0.077472270585668149 + 0.077475202631867898 + 0.077478134713933541 + 0.077481066831866161 + 0.077483998985666894 + 0.077486931175336934 + 0.077489863400877407 + 0.077492795662289476 + 0.077495727959574365 + 0.077498660292733154 + 0.077501592661766969 + 0.077504525066677127 + 0.077507457507464669 + 0.077510389984130651 + 0.077513322496676543 + 0.077516255045103288 + 0.077519187629411998 + 0.077522120249603976 + 0.077525052905680347 + 0.077527985597642179 + 0.07753091832549068 + 0.077533851089227182 + 0.077536783888852587 + 0.077539716724368143 + 0.077542649595775198 + 0.077545582503074723 + 0.077548515446267771 + 0.077551448425355773 + 0.077554381440339826 + 0.077557314491220899 + 0.07756024757800041 + 0.077563180700679343 + 0.077566113859258892 + 0.077569047053740278 + 0.077571980284124709 + 0.077574913550413238 + 0.077577846852607144 + 0.07758078019070748 + 0.077583713564715398 + 0.077586646974632217 + 0.077589580420458909 + 0.077592513902196847 + 0.077595447419847058 + 0.077598380973410652 + 0.07760131456288899 + 0.077604248188283056 + 0.077607181849594184 + 0.077610115546823275 + 0.077613049279971896 + 0.077615983049040868 + 0.077618916854031494 + 0.077621850694944969 + 0.077624784571782318 + 0.07762771848454493 + 0.077630652433233777 + 0.077633586417850189 + 0.077636520438395168 + 0.077639454494869989 + 0.077642388587275762 + 0.077645322715613752 + 0.077648256879885108 + 0.077651191080090928 + 0.077654125316232364 + 0.07765705958831072 + 0.077659993896327092 + 0.077662928240282592 + 0.077665862620178411 + 0.077668797036015799 + 0.07767173148779595 + 0.077674665975519822 + 0.077677600499188884 + 0.077680535058804012 + 0.077683469654366635 + 0.077686404285877711 + 0.077689338953338599 + 0.077692273656750396 + 0.077695208396114268 + 0.077698143171431353 + 0.07770107798270276 + 0.077704012829929864 + 0.077706947713113775 + 0.077709882632255603 + 0.077712817587356459 + 0.077715752578417688 + 0.077718687605440318 + 0.077721622668425611 + 0.077724557767374844 + 0.077727492902288906 + 0.077730428073169142 + 0.077733363280016787 + 0.077736298522832939 + 0.077739233801618748 + 0.077742169116375437 + 0.077745104467104115 + 0.077748039853806086 + 0.077750975276482392 + 0.077753910735134379 + 0.077756846229762991 + 0.077759781760369698 + 0.077762717326955375 + 0.077765652929521381 + 0.077768588568068814 + 0.077771524242598991 + 0.077774459953112843 + 0.077777395699611784 + 0.077780331482096787 + 0.077783267300569267 + 0.077786203155030278 + 0.077789139045480946 + 0.077792074971922559 + 0.077795010934356201 + 0.077797946932783149 + 0.077800882967204499 + 0.077803819037621402 + 0.077806755144035109 + 0.077809691286446825 + 0.077812627464857745 + 0.077815563679268979 + 0.077818499929681637 + 0.077821436216097092 + 0.077824372538516387 + 0.077827308896940839 + 0.077830245291371447 + 0.077833181721809433 + 0.07783611818825617 + 0.077839054690712534 + 0.077841991229180008 + 0.077844927803659592 + 0.07784786441415259 + 0.077850801060660002 + 0.077853737743183132 + 0.077856674461723202 + 0.077859611216281377 + 0.077862548006858823 + 0.07786548483345665 + 0.077868421696076079 + 0.077871358594718401 + 0.077874295529384657 + 0.077877232500076124 + 0.077880169506793939 + 0.077883106549539435 + 0.07788604362831357 + 0.077888980743117661 + 0.077891917893952861 + 0.077894855080820405 + 0.077897792303721403 + 0.077900729562657048 + 0.077903666857628576 + 0.07790660418863711 + 0.077909541555684012 + 0.077912478958770182 + 0.077915416397897147 + 0.077918353873065782 + 0.077921291384277447 + 0.077924228931533279 + 0.077927166514834431 + 0.077930104134182235 + 0.077933041789577703 + 0.077935979481022197 + 0.077938917208516784 + 0.077941854972062657 + 0.077944792771661053 + 0.077947730607313179 + 0.077950668479020088 + 0.077953606386783156 + 0.07795654433060345 + 0.077959482310482137 + 0.077962420326420631 + 0.077965358378419877 + 0.077968296466481096 + 0.077971234590605648 + 0.07797417275079456 + 0.077977110947049122 + 0.077980049179370459 + 0.077982987447759819 + 0.077985925752218285 + 0.077988864092747134 + 0.077991802469347615 + 0.077994740882020783 + 0.077997679330768024 + 0.078000617815590367 + 0.078003556336488977 + 0.078006494893465159 + 0.078009433486520216 + 0.07801237211565501 + 0.078015310780871053 + 0.078018249482169358 + 0.078021188219551174 + 0.078024126993017695 + 0.078027065802570086 + 0.078030004648209611 + 0.078032943529937407 + 0.078035882447754765 + 0.078038821401662795 + 0.078041760391662676 + 0.078044699417755617 + 0.07804763847994281 + 0.078050577578225575 + 0.078053516712604951 + 0.078056455883082201 + 0.078059395089658548 + 0.078062334332335129 + 0.07806527361111322 + 0.078068212925993877 + 0.078071152276978417 + 0.078074091664068021 + 0.078077031087264007 + 0.078079970546567221 + 0.078082910041979287 + 0.078085849573501134 + 0.078088789141134055 + 0.078091728744879157 + 0.078094668384737748 + 0.078097608060711102 + 0.078100547772800163 + 0.07810348752100639 + 0.078106427305330794 + 0.078109367125774654 + 0.078112306982339147 + 0.078115246875025593 + 0.078118186803835088 + 0.078121126768768756 + 0.078124066769827999 + 0.07812700680701383 + 0.078129946880327608 + 0.078132886989770348 + 0.078135827135343366 + 0.078138767317047983 + 0.078141707534885252 + 0.078144647788856325 + 0.078147588078962535 + 0.078150528405205061 + 0.078153468767585027 + 0.078156409166103738 + 0.078159349600762359 + 0.078162290071562071 + 0.078165230578504108 + 0.07816817112158965 + 0.07817111170081989 + 0.078174052316196063 + 0.078176992967719461 + 0.078179933655391068 + 0.078182874379212272 + 0.078185815139184309 + 0.07818875593530826 + 0.078191696767585292 + 0.078194637636016792 + 0.078197578540603913 + 0.078200519481347722 + 0.07820346045824951 + 0.078206401471310555 + 0.078209342520531994 + 0.078212283605915048 + 0.078215224727460925 + 0.078218165885170859 + 0.078221107079046073 + 0.078224048309087635 + 0.078226989575296974 + 0.078229930877675144 + 0.078232872216223381 + 0.078235813590942879 + 0.078238755001834831 + 0.078241696448900611 + 0.078244637932141273 + 0.078247579451558039 + 0.078250521007152199 + 0.07825346259892485 + 0.078256404226877227 + 0.078259345891010648 + 0.078262287591326168 + 0.07826522932782512 + 0.078268171100508724 + 0.078271112909378146 + 0.078274054754434566 + 0.078276996635679302 + 0.078279938553113423 + 0.078282880506738234 + 0.078285822496554941 + 0.078288764522564572 + 0.078291706584768736 + 0.07829464868316828 + 0.078297590817764634 + 0.078300532988558949 + 0.078303475195552419 + 0.078306417438746195 + 0.078309359718141708 + 0.078312302033739858 + 0.078315244385542063 + 0.078318186773549625 + 0.078321129197763559 + 0.078324071658185099 + 0.078327014154815591 + 0.078329956687656133 + 0.078332899256708055 + 0.078335841861972524 + 0.078338784503450651 + 0.078341727181143864 + 0.078344669895053093 + 0.078347612645179865 + 0.078350555431525096 + 0.078353498254090367 + 0.078356441112876471 + 0.07835938400788503 + 0.078362326939116933 + 0.07836526990657372 + 0.078368212910256307 + 0.078371155950165985 + 0.078374099026304114 + 0.078377042138671763 + 0.078379985287270179 + 0.078382928472100696 + 0.078385871693164397 + 0.07838881495046264 + 0.078391758243996412 + 0.078394701573767184 + 0.078397644939776093 + 0.078400588342024319 + 0.078403531780513055 + 0.078406475255243607 + 0.078409418766217112 + 0.078412362313435 + 0.078415305896898171 + 0.07841824951660803 + 0.078421193172565837 + 0.078424136864772689 + 0.078427080593229864 + 0.078430024357938652 + 0.078432968158900149 + 0.078435911996115798 + 0.078438855869586502 + 0.078441799779313787 + 0.078444743725298624 + 0.078447687707542416 + 0.078450631726046285 + 0.078453575780811594 + 0.078456519871839353 + 0.078459463999130938 + 0.078462408162687652 + 0.078465352362510399 + 0.078468296598600773 + 0.078471240870959719 + 0.078474185179588665 + 0.078477129524488834 + 0.078480073905661293 + 0.078483018323107306 + 0.07848596277682815 + 0.078488907266824975 + 0.078491851793099157 + 0.078494796355651916 + 0.078497740954484321 + 0.078500685589597635 + 0.078503630260993204 + 0.078506574968672208 + 0.07850951971263577 + 0.078512464492885209 + 0.078515409309421802 + 0.078518354162246645 + 0.078521299051361113 + 0.0785242439767663 + 0.078527188938463513 + 0.078530133936453958 + 0.078533078970738968 + 0.078536024041319541 + 0.078538969148197108 + 0.078541914291372764 + 0.078544859470847925 + 0.07854780468662359 + 0.078550749938701175 + 0.078553695227081805 + 0.078556640551766768 + 0.078559585912757218 + 0.078562531310054501 + 0.078565476743659809 + 0.078568422213574268 + 0.078571367719799293 + 0.078574313262335993 + 0.078577258841185646 + 0.078580204456349376 + 0.078583150107828612 + 0.07858609579562445 + 0.078589041519738084 + 0.07859198728017093 + 0.078594933076923987 + 0.078597878909998656 + 0.078600824779396103 + 0.078603770685117647 + 0.078606716627164411 + 0.078609662605537672 + 0.078612608620238666 + 0.078615554671268739 + 0.078618500758628876 + 0.07862144688232052 + 0.078624393042344781 + 0.07862733923870302 + 0.078630285471396402 + 0.078633231740426177 + 0.078636178045793523 + 0.07863912438749987 + 0.078642070765546232 + 0.078645017179933885 + 0.078647963630664106 + 0.078650910117738129 + 0.07865385664115726 + 0.078656803200922637 + 0.078659749797035494 + 0.078662696429497136 + 0.078665643098308868 + 0.078668589803471717 + 0.078671536544987083 + 0.078674483322856079 + 0.078677430137080104 + 0.078680376987660353 + 0.078683323874598005 + 0.078686270797894281 + 0.078689217757550473 + 0.078692164753567814 + 0.078695111785947569 + 0.078698058854691 + 0.078701005959799245 + 0.078703953101273608 + 0.078706900279115366 + 0.078709847493325658 + 0.078712794743905815 + 0.078715742030857044 + 0.078718689354180568 + 0.078721636713877649 + 0.078724584109949605 + 0.078727531542397547 + 0.078730479011222806 + 0.078733426516426522 + 0.078736374058010053 + 0.078739321635974566 + 0.078742269250321406 + 0.07874521690105174 + 0.078748164588166747 + 0.078751112311667856 + 0.078754060071556123 + 0.078757007867832893 + 0.078759955700499332 + 0.078762903569556827 + 0.078765851475006504 + 0.078768799416849597 + 0.07877174739508748 + 0.078774695409721235 + 0.078777643460752209 + 0.078780591548181608 + 0.078783539672010655 + 0.078786487832240779 + 0.078789436028872964 + 0.078792384261908627 + 0.078795332531348877 + 0.078798280837195173 + 0.078801229179448581 + 0.078804177558110422 + 0.078807125973181846 + 0.078810074424664256 + 0.078813022912558831 + 0.078815971436866722 + 0.07881891999758936 + 0.078821868594727812 + 0.078824817228283509 + 0.078827765898257601 + 0.078830714604651325 + 0.078833663347465957 + 0.078836612126702676 + 0.078839560942362899 + 0.078842509794447693 + 0.07884545868295835 + 0.078848407607896187 + 0.078851356569262496 + 0.0788543055670584 + 0.078857254601285218 + 0.078860203671944157 + 0.078863152779036508 + 0.078866101922563603 + 0.078869051102526552 + 0.078872000318926674 + 0.078874949571765121 + 0.078877898861043322 + 0.078880848186762345 + 0.07888379754892362 + 0.078886746947528341 + 0.078889696382577632 + 0.078892645854072949 + 0.078895595362015444 + 0.078898544906406284 + 0.078901494487246926 + 0.078904444104538424 + 0.078907393758282166 + 0.078910343448479386 + 0.078913293175131322 + 0.078916242938239151 + 0.078919192737804192 + 0.07892214257382775 + 0.07892509244631106 + 0.07892804235525526 + 0.078930992300661806 + 0.078933942282531755 + 0.078936892300866424 + 0.078939842355667214 + 0.078942792446935292 + 0.07894574257467174 + 0.078948692738878154 + 0.078951642939555464 + 0.078954593176705098 + 0.078957543450328238 + 0.078960493760426284 + 0.078963444107000319 + 0.078966394490051661 + 0.078969344909581698 + 0.078972295365591527 + 0.078975245858082396 + 0.078978196387055652 + 0.07898114695251264 + 0.078984097554454374 + 0.078987048192882284 + 0.078989998867797562 + 0.078992949579201485 + 0.0789959003270954 + 0.078998851111480542 + 0.079001801932357882 + 0.079004752789729113 + 0.079007703683595304 + 0.079010654613957565 + 0.079013605580817534 + 0.079016556584176098 + 0.079019507624034688 + 0.079022458700394538 + 0.079025409813256897 + 0.079028360962623043 + 0.079031312148494265 + 0.079034263370871868 + 0.079037214629757033 + 0.079040165925151021 + 0.07904311725705504 + 0.079046068625470478 + 0.079049020030398556 + 0.079051971471840524 + 0.079054922949797574 + 0.079057874464271163 + 0.079060826015262375 + 0.079063777602772597 + 0.07906672922680294 + 0.079069680887354929 + 0.079072632584429467 + 0.079075584318028178 + 0.079078536088152088 + 0.079081487894802627 + 0.079084439737980794 + 0.079087391617688185 + 0.079090343533925897 + 0.079093295486695192 + 0.07909624747599743 + 0.079099199501833695 + 0.079102151564205414 + 0.079105103663113893 + 0.079108055798560242 + 0.079111007970545669 + 0.079113960179071838 + 0.079116912424139624 + 0.07911986470575047 + 0.079122817023905542 + 0.079125769378606242 + 0.07912872176985368 + 0.079131674197649243 + 0.07913462666199407 + 0.07913757916288966 + 0.079140531700337108 + 0.079143484274337747 + 0.07914643688489284 + 0.079149389532003595 + 0.07915234221567137 + 0.079155294935897388 + 0.079158247692682843 + 0.079161200486029204 + 0.079164153315937555 + 0.079167106182409283 + 0.079170059085445554 + 0.079173012025047812 + 0.079175965001217111 + 0.07917891801395488 + 0.079181871063262355 + 0.079184824149140728 + 0.079187777271591417 + 0.079190730430615627 + 0.079193683626214553 + 0.079196636858389624 + 0.079199590127141964 + 0.079202543432472933 + 0.079205496774383807 + 0.079208450152875726 + 0.079211403567950214 + 0.079214357019608356 + 0.079217310507851399 + 0.079220264032680773 + 0.079223217594097672 + 0.07922617119210329 + 0.07922912482669911 + 0.07923207849788623 + 0.079235032205665898 + 0.079237985950039572 + 0.079240939731008403 + 0.07924389354857371 + 0.079246847402736714 + 0.079249801293498789 + 0.079252755220861115 + 0.07925570918482501 + 0.079258663185391751 + 0.079261617222562558 + 0.079264571296338751 + 0.079267525406721676 + 0.079270479553712636 + 0.079273433737312743 + 0.079276387957523342 + 0.079279342214345724 + 0.079282296507781222 + 0.079285250837831028 + 0.079288205204496476 + 0.079291159607778786 + 0.079294114047679373 + 0.079297068524199377 + 0.079300023037340156 + 0.079302977587102905 + 0.079305932173488983 + 0.079308886796499653 + 0.07931184145613622 + 0.079314796152399947 + 0.079317750885291985 + 0.07932070565481382 + 0.079323660460966658 + 0.079326615303751694 + 0.079329570183170439 + 0.079332525099223922 + 0.079335480051913529 + 0.079338435041240551 + 0.079341390067206252 + 0.079344345129811866 + 0.079347300229058781 + 0.079350255364948302 + 0.079353210537481608 + 0.07935616574665999 + 0.079359120992484711 + 0.079362076274957172 + 0.079365031594078594 + 0.079367986949850186 + 0.079370942342273376 + 0.079373897771349414 + 0.079376853237079423 + 0.07937980873946486 + 0.07938276427850692 + 0.079385719854206963 + 0.079388675466566333 + 0.079391631115586142 + 0.079394586801267777 + 0.079397542523612488 + 0.079400498282621593 + 0.079403454078296326 + 0.079406409910638076 + 0.079409365779648119 + 0.079412321685327622 + 0.07941527762767793 + 0.079418233606700347 + 0.079421189622396207 + 0.079424145674766577 + 0.079427101763813179 + 0.079430057889536915 + 0.079433014051939199 + 0.079435970251021323 + 0.079438926486784578 + 0.07944188275923017 + 0.079444839068359585 + 0.079447795414173975 + 0.079450751796674518 + 0.079453708215862784 + 0.079456664671739868 + 0.079459621164307132 + 0.079462577693565836 + 0.07946553425951719 + 0.079468490862162566 + 0.079471447501503367 + 0.079474404177540786 + 0.079477360890276016 + 0.079480317639710515 + 0.079483274425845449 + 0.079486231248682204 + 0.079489188108222045 + 0.079492145004466178 + 0.079495101937415977 + 0.079498058907072761 + 0.079501015913437695 + 0.07950397295651232 + 0.079506930036297593 + 0.079509887152795111 + 0.079512844306005984 + 0.079515801495931668 + 0.079518758722573288 + 0.079521715985932176 + 0.079524673286009706 + 0.079527630622807113 + 0.07953058799632573 + 0.07953354540656675 + 0.079536502853531588 + 0.079539460337221479 + 0.079542417857637826 + 0.07954537541478171 + 0.079548333008654631 + 0.079551290639257741 + 0.079554248306592398 + 0.079557206010659964 + 0.079560163751461688 + 0.079563121528998804 + 0.079566079343272686 + 0.0795690371942845 + 0.079571995082035829 + 0.079574953006527657 + 0.079577910967761484 + 0.07958086896573853 + 0.0795838270004601 + 0.079586785071927457 + 0.07958974318014192 + 0.079592701325104848 + 0.079595659506817587 + 0.079598617725281234 + 0.079601575980497219 + 0.079604534272466887 + 0.079607492601191404 + 0.079610450966672242 + 0.079613409368910426 + 0.079616367807907609 + 0.079619326283664887 + 0.079622284796183482 + 0.079625243345464947 + 0.079628201931510337 + 0.079631160554321109 + 0.079634119213898458 + 0.07963707791024377 + 0.07964003664335835 + 0.07964299541324342 + 0.079645954219900367 + 0.079648913063330426 + 0.079651871943534999 + 0.079654830860515266 + 0.079657789814272559 + 0.079660748804808224 + 0.079663707832123634 + 0.079666666896219901 + 0.079669625997098509 + 0.079672585134760582 + 0.079675544309207591 + 0.079678503520440799 + 0.079681462768461497 + 0.079684422053271017 + 0.079687381374870594 + 0.079690340733261644 + 0.079693300128445291 + 0.079696259560422963 + 0.079699219029196036 + 0.079702178534765633 + 0.079705138077133267 + 0.079708097656300048 + 0.079711057272267391 + 0.079714016925036671 + 0.079716976614608984 + 0.07971993634098587 + 0.079722896104168439 + 0.079725855904158122 + 0.07972881574095618 + 0.079731775614564029 + 0.079734735524982767 + 0.079737695472213946 + 0.079740655456258636 + 0.079743615477118376 + 0.079746575534794209 + 0.079749535629287702 + 0.079752495760599978 + 0.079755455928732483 + 0.079758416133686394 + 0.079761376375463197 + 0.079764336654063975 + 0.079767296969490267 + 0.079770257321743351 + 0.079773217710824323 + 0.079776178136734738 + 0.079779138599475663 + 0.079782099099048709 + 0.079785059635454902 + 0.07978802020869577 + 0.079790980818772547 + 0.079793941465686441 + 0.079796902149438992 + 0.079799862870031255 + 0.0798028236274647 + 0.079805784421740633 + 0.079808745252860372 + 0.079811706120825096 + 0.079814667025636304 + 0.079817627967295274 + 0.079820588945803184 + 0.079823549961161464 + 0.07982651101337139 + 0.079829472102434393 + 0.079832433228351526 + 0.079835394391124317 + 0.07983835559075407 + 0.079841316827242048 + 0.079844278100589514 + 0.079847239410797841 + 0.079850200757868389 + 0.079853162141802422 + 0.079856123562601328 + 0.079859085020266271 + 0.079862046514798724 + 0.079865008046199906 + 0.079867969614471096 + 0.079870931219613805 + 0.0798738928616292 + 0.07987685454051853 + 0.079879816256283334 + 0.07988277800892464 + 0.079885739798444114 + 0.079888701624842753 + 0.079891663488122128 + 0.079894625388283333 + 0.079897587325327785 + 0.079900549299256884 + 0.079903511310071798 + 0.079906473357774066 + 0.079909435442364757 + 0.079912397563845383 + 0.079915359722217041 + 0.0799183219174813 + 0.079921284149639393 + 0.079924246418692571 + 0.079927208724642193 + 0.079930171067489647 + 0.079933133447236182 + 0.079936095863883061 + 0.079939058317431755 + 0.079942020807883526 + 0.079944983335239556 + 0.079947945899501369 + 0.079950908500670229 + 0.079953871138747412 + 0.079956833813734376 + 0.079959796525632218 + 0.07996275927444231 + 0.079965722060166181 + 0.07996868488280498 + 0.079971647742360041 + 0.079974610638832794 + 0.079977573572224375 + 0.079980536542536215 + 0.079983499549769743 + 0.079986462593926069 + 0.079989425675006692 + 0.079992388793012834 + 0.079995351947945922 + 0.07999831513980718 + 0.080001278368597994 + 0.080004241634319614 + 0.080007204936973442 + 0.080010168276560836 + 0.080013131653083006 + 0.080016095066541365 + 0.080019058516937192 + 0.0800220220042719 + 0.080024985528546741 + 0.080027949089762906 + 0.08003091268792209 + 0.080033876323025305 + 0.080036839995073952 + 0.080039803704069351 + 0.080042767450012861 + 0.080045731232905912 + 0.080048695052749669 + 0.080051658909545548 + 0.080054622803294756 + 0.080057586733998848 + 0.080060550701658975 + 0.080063514706276456 + 0.080066478747852748 + 0.080069442826389142 + 0.080072406941886873 + 0.080075371094347356 + 0.080078335283771854 + 0.080081299510161866 + 0.080084263773518433 + 0.080087228073843206 + 0.08009019241113724 + 0.080093156785402089 + 0.080096121196638947 + 0.080099085644849188 + 0.0801020501300342 + 0.080105014652195189 + 0.080107979211333558 + 0.08011094380745061 + 0.080113908440547804 + 0.080116873110626236 + 0.080119837817687542 + 0.080122802561732737 + 0.080125767342763318 + 0.080128732160780716 + 0.080131697015786124 + 0.08013466190778093 + 0.080137626836766326 + 0.080140591802743771 + 0.080143556805714694 + 0.08014652184568026 + 0.080149486922642052 + 0.080152452036601082 + 0.080155417187558753 + 0.080158382375516604 + 0.080161347600475857 + 0.080164312862437789 + 0.080167278161403691 + 0.080170243497375102 + 0.080173208870353285 + 0.080176174280339477 + 0.080179139727335022 + 0.080182105211341365 + 0.080185070732359864 + 0.080188036290391715 + 0.080191001885438332 + 0.080193967517501047 + 0.080196933186581137 + 0.080199898892680074 + 0.080202864635799079 + 0.080205830415939552 + 0.0802087962331028 + 0.08021176208729025 + 0.080214727978503028 + 0.080217693906742646 + 0.080220659872010505 + 0.080223625874307772 + 0.080226591913635889 + 0.080229557989996203 + 0.080232524103389935 + 0.080235490253818598 + 0.080238456441283385 + 0.080241422665785725 + 0.080244388927326882 + 0.080247355225908298 + 0.080250321561531279 + 0.080253287934197157 + 0.080256254343907235 + 0.080259220790662875 + 0.080262187274465449 + 0.080265153795316332 + 0.080268120353216732 + 0.080271086948168091 + 0.080274053580171797 + 0.080277020249229086 + 0.080279986955341373 + 0.080282953698509962 + 0.080285920478736159 + 0.080288887296021363 + 0.080291854150367076 + 0.080294821041774309 + 0.080297787970244699 + 0.080300754935779345 + 0.080303721938379868 + 0.080306688978047408 + 0.080309656054783324 + 0.080312623168588962 + 0.080315590319465807 + 0.080318557507414998 + 0.080321524732438088 + 0.080324491994536257 + 0.080327459293710879 + 0.080330426629963508 + 0.0803333940032952 + 0.080336361413707452 + 0.080339328861201501 + 0.080342296345778871 + 0.080345263867440786 + 0.080348231426188688 + 0.080351199022023798 + 0.08035416665494749 + 0.080357134324961291 + 0.080360102032066213 + 0.080363069776263896 + 0.080366037557555517 + 0.080369005375942673 + 0.080371973231426391 + 0.08037494112400817 + 0.080377909053689398 + 0.080380877020471364 + 0.080383845024355388 + 0.080386813065342996 + 0.080389781143435299 + 0.080392749258633781 + 0.080395717410939774 + 0.080398685600354694 + 0.080401653826879707 + 0.080404622090516395 + 0.080407590391265923 + 0.080410558729129777 + 0.080413527104109178 + 0.080416495516205638 + 0.080419463965420296 + 0.080422432451754677 + 0.080425400975210143 + 0.080428369535787941 + 0.080431338133489433 + 0.080434306768316047 + 0.080437275440269101 + 0.080440244149349957 + 0.080443212895559946 + 0.080446181678900427 + 0.080449150499372749 + 0.080452119356978283 + 0.080455088251718321 + 0.080458057183594348 + 0.080461026152607668 + 0.080463995158759655 + 0.080466964202051502 + 0.080469933282484682 + 0.080472902400060581 + 0.080475871554780531 + 0.080478840746645922 + 0.080481809975658083 + 0.080484779241818294 + 0.080487748545127996 + 0.080490717885588522 + 0.08049368726320133 + 0.080496656677967515 + 0.080499626129888688 + 0.08050259561896618 + 0.080505565145201186 + 0.080508534708595106 + 0.080511504309149468 + 0.080514473946865492 + 0.080517443621744553 + 0.080520413333788024 + 0.080523383082997224 + 0.080526352869373666 + 0.080529322692918487 + 0.080532292553633145 + 0.080535262451518999 + 0.080538232386577535 + 0.080541202358809835 + 0.080544172368217481 + 0.080547142414801765 + 0.080550112498564003 + 0.080553082619505667 + 0.080556052777628076 + 0.080559022972932548 + 0.08056199320542036 + 0.080564963475093121 + 0.080567933781951956 + 0.080570904125998294 + 0.080573874507233592 + 0.080576844925659127 + 0.080579815381276343 + 0.080582785874086432 + 0.08058575640409088 + 0.08058872697129113 + 0.080591697575688306 + 0.080594668217283991 + 0.080597638896079474 + 0.080600609612076018 + 0.080603580365275235 + 0.080606551155678205 + 0.080609521983286511 + 0.080612492848101305 + 0.080615463750124142 + 0.080618434689356394 + 0.080621405665799339 + 0.080624376679454324 + 0.080627347730322721 + 0.080630318818405919 + 0.080633289943705305 + 0.080636261106222226 + 0.080639232305958042 + 0.080642203542914154 + 0.080645174817091825 + 0.080648146128492582 + 0.080651117477117645 + 0.080654088862968515 + 0.080657060286046411 + 0.080660031746352806 + 0.080663003243889017 + 0.08066597477865646 + 0.080668946350656426 + 0.080671917959890302 + 0.080674889606359559 + 0.080677861290065503 + 0.080680833011009451 + 0.080683804769192777 + 0.080686776564617049 + 0.080689748397283365 + 0.080692720267193124 + 0.080695692174347883 + 0.080698664118748806 + 0.080701636100397434 + 0.080704608119295113 + 0.080707580175443022 + 0.0807105522688428 + 0.080713524399495556 + 0.080716496567402971 + 0.080719468772566041 + 0.080722441014986449 + 0.080725413294665413 + 0.080728385611604406 + 0.080731357965804731 + 0.080734330357267681 + 0.080737302785994863 + 0.080740275251987376 + 0.0807432477552468 + 0.080746220295774385 + 0.080749192873571532 + 0.080752165488639671 + 0.080755138140980065 + 0.080758110830594185 + 0.080761083557483418 + 0.080764056321649041 + 0.080767029123092526 + 0.080770001961815149 + 0.080772974837818326 + 0.080775947751103541 + 0.080778920701671975 + 0.08078189368952518 + 0.080784866714664436 + 0.080787839777091072 + 0.080790812876806617 + 0.080793786013812263 + 0.080796759188109482 + 0.080799732399699661 + 0.080802705648584217 + 0.080805678934764424 + 0.080808652258241714 + 0.080811625619017377 + 0.080814599017092995 + 0.080817572452469746 + 0.080820545925149145 + 0.080823519435132399 + 0.080826492982421005 + 0.080829466567016423 + 0.080832440188919913 + 0.080835413848132753 + 0.080838387544656609 + 0.080841361278492563 + 0.080844335049642169 + 0.080847308858106801 + 0.080850282703887777 + 0.080853256586986527 + 0.080856230507404342 + 0.080859204465142692 + 0.080862178460203007 + 0.080865152492586523 + 0.080868126562294682 + 0.080871100669328844 + 0.080874074813690508 + 0.080877048995380882 + 0.080880023214401367 + 0.08088299747075349 + 0.080885971764438569 + 0.080888946095457909 + 0.080891920463812952 + 0.08089489486950513 + 0.080897869312535689 + 0.08090084379290613 + 0.080903818310617812 + 0.08090679286567215 + 0.080909767458070395 + 0.080912742087814085 + 0.080915716754904485 + 0.080918691459342981 + 0.080921666201131087 + 0.080924640980270066 + 0.080927615796761276 + 0.080930590650606329 + 0.080933565541806377 + 0.080936540470362861 + 0.080939515436277212 + 0.080942490439550721 + 0.080945465480184817 + 0.080948440558180984 + 0.080951415673540431 + 0.080954390826264724 + 0.080957366016355184 + 0.080960341243813086 + 0.080963316508640013 + 0.080966291810837157 + 0.080969267150405991 + 0.080972242527347998 + 0.08097521794166429 + 0.080978193393356615 + 0.08098116888242618 + 0.080984144408874373 + 0.08098711997270247 + 0.080990095573911985 + 0.080993071212504444 + 0.080996046888480971 + 0.080999022601843051 + 0.081001998352592142 + 0.081004974140729602 + 0.081007949966256695 + 0.081010925829175004 + 0.08101390172948586 + 0.081016877667190582 + 0.081019853642290598 + 0.081022829654787229 + 0.081025805704682041 + 0.081028781791976326 + 0.081031757916671374 + 0.081034734078768697 + 0.081037710278269795 + 0.081040686515175819 + 0.081043662789488269 + 0.081046639101208504 + 0.081049615450337981 + 0.081052591836878088 + 0.081055568260830047 + 0.081058544722195508 + 0.081061521220975805 + 0.081064497757172116 + 0.081067474330786107 + 0.081070450941819 + 0.081073427590272307 + 0.08107640427614736 + 0.081079380999445436 + 0.081082357760168006 + 0.081085334558316596 + 0.081088311393892512 + 0.081091288266897155 + 0.081094265177331842 + 0.081097242125198074 + 0.081100219110497182 + 0.081103196133230582 + 0.081106173193399661 + 0.081109150291005891 + 0.081112127426050576 + 0.081115104598535062 + 0.081118081808460862 + 0.081121059055829267 + 0.081124036340641872 + 0.081127013662899761 + 0.081129991022604667 + 0.081132968419757687 + 0.081135945854360417 + 0.081138923326414286 + 0.081141900835920447 + 0.08114487838288055 + 0.081147855967295845 + 0.081150833589167817 + 0.081153811248497798 + 0.081156788945287273 + 0.081159766679537476 + 0.081162744451250005 + 0.081165722260426079 + 0.08116870010706724 + 0.08117167799117482 + 0.081174655912750304 + 0.081177633871794899 + 0.081180611868310146 + 0.081183589902297459 + 0.0811865679737582 + 0.081189546082693714 + 0.08119252422910557 + 0.081195502412995002 + 0.081198480634363385 + 0.081201458893212314 + 0.081204437189543149 + 0.081207415523357071 + 0.08121039389465573 + 0.081213372303440348 + 0.081216350749712354 + 0.081219329233473317 + 0.081222307754724513 + 0.081225286313467357 + 0.081228264909703279 + 0.081231243543433626 + 0.081234222214659854 + 0.081237200923383338 + 0.081240179669605464 + 0.081243158453327732 + 0.081246137274551378 + 0.08124911613327794 + 0.081252095029508836 + 0.081255073963245383 + 0.081258052934488997 + 0.081261031943241163 + 0.081264010989503227 + 0.081266990073276577 + 0.081269969194562683 + 0.081272948353362878 + 0.081275927549678537 + 0.08127890678351124 + 0.081281886054862182 + 0.081284865363732944 + 0.081287844710124832 + 0.08129082409403926 + 0.081293803515477686 + 0.081296782974441428 + 0.081299762470932069 + 0.081302742004950815 + 0.081305721576499082 + 0.081308701185578466 + 0.081311680832190245 + 0.08131466051633586 + 0.081317640238016645 + 0.081320619997234042 + 0.081323599793989537 + 0.081326579628284518 + 0.081329559500120288 + 0.081332539409498361 + 0.08133551935642018 + 0.081338499340887077 + 0.08134147936290044 + 0.08134445942246174 + 0.081347439519572254 + 0.081350419654233674 + 0.081353399826447126 + 0.081356380036214107 + 0.081359360283536145 + 0.081362340568414557 + 0.081365320890850773 + 0.081368301250846112 + 0.081371281648402044 + 0.081374262083520055 + 0.081377242556201546 + 0.081380223066447765 + 0.081383203614260366 + 0.081386184199640596 + 0.081389164822589843 + 0.081392145483109649 + 0.081395126181201455 + 0.081398106916866483 + 0.081401087690106302 + 0.081404068500922272 + 0.081407049349315821 + 0.081410030235288255 + 0.081413011158841198 + 0.081415992119975814 + 0.081418973118693755 + 0.081421954154996409 + 0.081424935228885026 + 0.081427916340361145 + 0.081430897489426099 + 0.081433878676081387 + 0.081436859900328423 + 0.081439841162168666 + 0.081442822461603268 + 0.081445803798634003 + 0.081448785173262123 + 0.081451766585488888 + 0.081454748035315966 + 0.081457729522744632 + 0.081460711047776468 + 0.081463692610412683 + 0.081466674210654733 + 0.081469655848504269 + 0.081472637523962332 + 0.08147561923703063 + 0.081478600987710467 + 0.081481582776003328 + 0.081484564601910531 + 0.081487546465433616 + 0.081490528366573819 + 0.081493510305332806 + 0.08149649228171188 + 0.081499474295712276 + 0.081502456347335703 + 0.081505438436583547 + 0.081508420563456974 + 0.081511402727957705 + 0.081514384930087003 + 0.081517367169846242 + 0.081520349447237017 + 0.081523331762260579 + 0.081526314114918522 + 0.081529296505212109 + 0.081532278933142771 + 0.081535261398711978 + 0.081538243901921187 + 0.081541226442771841 + 0.081544209021265246 + 0.08154719163740283 + 0.081550174291186217 + 0.081553156982616504 + 0.081556139711695411 + 0.081559122478424298 + 0.081562105282804401 + 0.081565088124837412 + 0.081568071004524526 + 0.081571053921867337 + 0.081574036876867137 + 0.081577019869525355 + 0.081580002899843573 + 0.081582985967823027 + 0.081585969073465298 + 0.081588952216771732 + 0.081591935397743717 + 0.081594918616382836 + 0.081597901872690309 + 0.081600885166667594 + 0.081603868498316232 + 0.081606851867637692 + 0.081609835274633252 + 0.081612818719304425 + 0.081615802201652501 + 0.081618785721679077 + 0.081621769279385567 + 0.081624752874773193 + 0.081627736507843676 + 0.081630720178598293 + 0.081633703887038347 + 0.081636687633165589 + 0.081639671416981169 + 0.081642655238486572 + 0.081645639097683326 + 0.081648622994572803 + 0.081651606929156267 + 0.081654590901435467 + 0.081657574911411623 + 0.081660558959086207 + 0.081663543044460704 + 0.08166652716753646 + 0.081669511328314917 + 0.081672495526797534 + 0.081675479762985781 + 0.081678464036880949 + 0.081681448348484648 + 0.081684432697798265 + 0.081687417084823022 + 0.08169040150956064 + 0.081693385972012408 + 0.081696370472179772 + 0.081699355010064201 + 0.081702339585667111 + 0.081705324198989904 + 0.081708308850033926 + 0.081711293538800814 + 0.081714278265291873 + 0.081717263029508574 + 0.08172024783145232 + 0.081723232671124579 + 0.081726217548526714 + 0.08172920246366025 + 0.081732187416526672 + 0.081735172407127285 + 0.081738157435463449 + 0.081741142501536815 + 0.081744127605348701 + 0.081747112746900608 + 0.081750097926193852 + 0.081753083143229918 + 0.08175606839801032 + 0.08175905369053639 + 0.081762039020809793 + 0.081765024388831584 + 0.081768009794603427 + 0.081770995238126754 + 0.081773980719402978 + 0.081776966238433502 + 0.081779951795219838 + 0.081782937389763347 + 0.081785923022065568 + 0.081788908692127724 + 0.08179189439995159 + 0.081794880145538235 + 0.081797865928889324 + 0.081800851750006356 + 0.081803837608890595 + 0.081806823505543497 + 0.081809809439966574 + 0.081812795412161243 + 0.081815781422128905 + 0.081818767469871129 + 0.081821753555389121 + 0.08182473967868456 + 0.081827725839758739 + 0.081830712038613154 + 0.081833698275249264 + 0.081836684549668443 + 0.08183967086187216 + 0.081842657211861999 + 0.081845643599639084 + 0.081848630025205121 + 0.081851616488561527 + 0.081854602989709563 + 0.08185758952865084 + 0.081860576105386745 + 0.081863562719918737 + 0.081866549372248257 + 0.081869536062376791 + 0.081872522790305644 + 0.081875509556036383 + 0.081878496359570438 + 0.081881483200909169 + 0.081884470080054131 + 0.081887456997006697 + 0.081890443951768324 + 0.081893430944340428 + 0.081896417974724536 + 0.081899405042922091 + 0.081902392148934341 + 0.081905379292763023 + 0.081908366474409341 + 0.081911353693874867 + 0.081914340951161027 + 0.081917328246269253 + 0.081920315579200931 + 0.081923302949957644 + 0.08192629035854071 + 0.081929277804951683 + 0.081932265289191897 + 0.081935252811262918 + 0.081938240371166038 + 0.081941227968902852 + 0.081944215604474735 + 0.081947203277883268 + 0.081950190989129618 + 0.081953178738215504 + 0.081956166525142163 + 0.081959154349911106 + 0.081962142212523945 + 0.081965130112981968 + 0.081968118051286704 + 0.081971106027439483 + 0.08197409404144175 + 0.08197708209329517 + 0.081980070183001061 + 0.081983058310560811 + 0.081986046475975877 + 0.081989034679247827 + 0.081992022920377994 + 0.081995011199367848 + 0.081997999516218945 + 0.082000987870932532 + 0.082003976263510331 + 0.082006964693953549 + 0.082009953162263741 + 0.082012941668442293 + 0.082015930212490915 + 0.082018918794410672 + 0.082021907414203246 + 0.082024896071870093 + 0.08202788476741249 + 0.082030873500832158 + 0.082033862272130276 + 0.082036851081308523 + 0.082039839928368219 + 0.082042828813310847 + 0.082045817736137838 + 0.082048806696850732 + 0.082051795695450916 + 0.082054784731939834 + 0.082057773806318887 + 0.082060762918589769 + 0.082063752068753618 + 0.08206674125681207 + 0.082069730482766556 + 0.082072719746618478 + 0.0820757090483695 + 0.082078698388020704 + 0.082081687765573924 + 0.082084677181030324 + 0.082087666634391529 + 0.082090656125658898 + 0.082093645654833888 + 0.082096635221918152 + 0.082099624826912812 + 0.082102614469819715 + 0.082105604150640013 + 0.082108593869375246 + 0.082111583626026899 + 0.082114573420596332 + 0.082117563253085182 + 0.082120553123494838 + 0.082123543031826687 + 0.082126532978082242 + 0.082129522962262974 + 0.082132512984370312 + 0.082135503044405728 + 0.08213849314237065 + 0.082141483278266536 + 0.08214447345209501 + 0.082147463663857154 + 0.082150453913554869 + 0.082153444201189321 + 0.082156434526762051 + 0.082159424890274557 + 0.082162415291728269 + 0.082165405731124658 + 0.082168396208465166 + 0.08217138672375128 + 0.08217437727698447 + 0.082177367868166054 + 0.082180358497297712 + 0.082183349164380873 + 0.082186339869416744 + 0.082189330612407074 + 0.082192321393353238 + 0.082195312212256733 + 0.08219830306911885 + 0.082201293963941269 + 0.082204284896725224 + 0.082207275867472382 + 0.082210266876184268 + 0.082213257922862132 + 0.082216249007507444 + 0.082219240130121829 + 0.08222223129070666 + 0.08222522248926338 + 0.082228213725793503 + 0.082231205000298416 + 0.082234196312779742 + 0.082237187663238717 + 0.082240179051676993 + 0.082243170478096012 + 0.082246161942497106 + 0.082249153444881956 + 0.082252144985251838 + 0.082255136563608278 + 0.082258128179952802 + 0.082261119834286772 + 0.082264111526611741 + 0.082267103256929042 + 0.082270095025240325 + 0.082273086831547063 + 0.082276078675850503 + 0.082279070558152284 + 0.082282062478453863 + 0.082285054436756599 + 0.082288046433062159 + 0.082291038467371819 + 0.082294030539687188 + 0.082297022650009488 + 0.082300014798340523 + 0.082303006984681515 + 0.082305999209034128 + 0.082308991471399667 + 0.082311983771779604 + 0.082314976110175547 + 0.082317968486588955 + 0.082320960901020951 + 0.082323953353473561 + 0.082326945843947841 + 0.082329938372445427 + 0.082332930938967763 + 0.082335923543516307 + 0.08233891618609257 + 0.082341908866697913 + 0.082344901585333988 + 0.082347894342002043 + 0.082350887136703799 + 0.082353879969440463 + 0.082356872840213757 + 0.082359865749024916 + 0.082362858695875674 + 0.082365851680767252 + 0.082368844703701344 + 0.082371837764679226 + 0.082374830863702536 + 0.082377824000772579 + 0.082380817175891061 + 0.082383810389059148 + 0.082386803640278561 + 0.082389796929550715 + 0.082392790256877055 + 0.082395783622258995 + 0.082398777025698158 + 0.082401770467195934 + 0.082404763946753681 + 0.082407757464373205 + 0.08241075102005567 + 0.082413744613802617 + 0.082416738245615559 + 0.082419731915496036 + 0.082422725623445395 + 0.082425719369465245 + 0.082428713153556973 + 0.082431706975722066 + 0.082434700835962021 + 0.082437694734278255 + 0.082440688670672418 + 0.082443682645145788 + 0.082446676657699919 + 0.082449670708336184 + 0.082452664797056305 + 0.082455658923861627 + 0.082458653088753567 + 0.082461647291733664 + 0.082464641532803334 + 0.082467635811964313 + 0.082470630129217681 + 0.082473624484565217 + 0.082476618878008306 + 0.082479613309548283 + 0.082482607779186909 + 0.082485602286925488 + 0.082488596832765493 + 0.082491591416708532 + 0.082494586038755896 + 0.082497580698909195 + 0.082500575397169956 + 0.082503570133539442 + 0.0825065649080194 + 0.08250955972061115 + 0.082512554571316232 + 0.082515549460136006 + 0.082518544387072221 + 0.082521539352126083 + 0.082524534355299189 + 0.082527529396593011 + 0.082530524476009032 + 0.082533519593548821 + 0.082536514749213738 + 0.082539509943005324 + 0.082542505174925021 + 0.082545500444974412 + 0.082548495753154719 + 0.082551491099467814 + 0.082554486483914863 + 0.082557481906497476 + 0.08256047736721718 + 0.082563472866075363 + 0.082566468403073578 + 0.08256946397821327 + 0.082572459591495923 + 0.082575455242923132 + 0.082578450932496272 + 0.082581446660216759 + 0.08258444242608616 + 0.082587438230106086 + 0.082590434072277785 + 0.082593429952602965 + 0.082596425871082943 + 0.082599421827719288 + 0.082602417822513471 + 0.082605413855467047 + 0.082608409926581278 + 0.082611406035857982 + 0.082614402183298366 + 0.082617398368903985 + 0.08262039459267656 + 0.082623390854617257 + 0.082626387154727698 + 0.082629383493009426 + 0.08263237986946384 + 0.082635376284092357 + 0.082638372736896726 + 0.082641369227878181 + 0.08264436575703836 + 0.082647362324378651 + 0.082650358929900691 + 0.082653355573605716 + 0.082656352255495502 + 0.08265934897557134 + 0.082662345733834838 + 0.082665342530287483 + 0.082668339364930676 + 0.082671336237765874 + 0.082674333148794826 + 0.082677330098018684 + 0.082680327085439195 + 0.082683324111057679 + 0.082686321174875843 + 0.082689318276894935 + 0.082692315417116552 + 0.082695312595542192 + 0.082698309812173368 + 0.082701307067011579 + 0.082704304360058253 + 0.082707301691314891 + 0.08271029906078306 + 0.082713296468464259 + 0.08271629391435982 + 0.082719291398471409 + 0.082722288920800482 + 0.082725286481348387 + 0.082728284080116871 + 0.082731281717107322 + 0.082734279392321114 + 0.082737277105759829 + 0.082740274857425022 + 0.082743272647318178 + 0.082746270475440642 + 0.082749268341794149 + 0.082752266246379977 + 0.082755264189199748 + 0.082758262170254948 + 0.082761260189546951 + 0.082764258247077491 + 0.082767256342847748 + 0.082770254476859512 + 0.082773252649114115 + 0.082776250859613182 + 0.08277924910835803 + 0.082782247395350242 + 0.082785245720591483 + 0.082788244084082932 + 0.08279124248582638 + 0.082794240925823145 + 0.082797239404074782 + 0.082800237920582789 + 0.082803236475348568 + 0.082806235068373882 + 0.082809233699659923 + 0.082812232369208386 + 0.082815231077020685 + 0.082818229823098485 + 0.082821228607442954 + 0.082824227430055908 + 0.082827226290938735 + 0.082830225190092796 + 0.082833224127519881 + 0.082836223103221224 + 0.082839222117198449 + 0.082842221169453084 + 0.082845220259986557 + 0.082848219388800437 + 0.082851218555896153 + 0.082854217761275314 + 0.082857217004939226 + 0.082860216286889651 + 0.08286321560712781 + 0.082866214965655549 + 0.082869214362474006 + 0.082872213797584901 + 0.082875213270989706 + 0.082878212782689906 + 0.082881212332687013 + 0.082884211920982484 + 0.082887211547577846 + 0.082890211212474751 + 0.082893210915674351 + 0.082896210657178587 + 0.082899210436988682 + 0.082902210255106135 + 0.082905210111532665 + 0.082908210006269495 + 0.082911209939318345 + 0.0829142099106807 + 0.082917209920357907 + 0.08292020996835156 + 0.082923210054663202 + 0.082926210179294413 + 0.082929210342246457 + 0.082932210543521179 + 0.082935210783119717 + 0.082938211061043862 + 0.082941211377294932 + 0.082944211731874593 + 0.082947212124784189 + 0.082950212556025402 + 0.082953213025599618 + 0.082956213533508391 + 0.082959214079753277 + 0.082962214664335565 + 0.08296521528725706 + 0.082968215948519136 + 0.082971216648123181 + 0.0829742173860709 + 0.082977218162363711 + 0.082980218977003278 + 0.082983219829990768 + 0.082986220721327997 + 0.082989221651016354 + 0.082992222619057338 + 0.082995223625452516 + 0.082998224670203388 + 0.083001225753311439 + 0.083004226874778139 + 0.083007228034605099 + 0.083010229232793761 + 0.083013230469345681 + 0.083016231744262287 + 0.083019233057545258 + 0.083022234409195844 + 0.083025235799215835 + 0.083028237227606536 + 0.083031238694369625 + 0.083034240199506421 + 0.083037241743018686 + 0.083040243324907628 + 0.083043244945175038 + 0.083046246603822274 + 0.083049248300850989 + 0.083052250036262515 + 0.083055251810058364 + 0.083058253622240216 + 0.08306125547280957 + 0.083064257361767813 + 0.083067259289116527 + 0.083070261254857156 + 0.083073263258991392 + 0.083076265301520624 + 0.083079267382446378 + 0.083082269501770112 + 0.083085271659493518 + 0.083088273855617845 + 0.083091276090144911 + 0.083094278363075952 + 0.083097280674412632 + 0.083100283024156535 + 0.083103285412309089 + 0.083106287838871834 + 0.083109290303846159 + 0.083112292807233729 + 0.08311529534903607 + 0.083118297929254611 + 0.08312130054789095 + 0.08312430320494657 + 0.083127305900422957 + 0.083130308634321637 + 0.083133311406644164 + 0.083136314217392024 + 0.083139317066566826 + 0.083142319954170013 + 0.083145322880203085 + 0.083148325844667498 + 0.083151328847564904 + 0.083154331888896871 + 0.083157334968664703 + 0.083160338086870109 + 0.083163341243514474 + 0.08316634443859941 + 0.083169347672126553 + 0.083172350944097098 + 0.083175354254512848 + 0.083178357603375205 + 0.083181360990685696 + 0.083184364416445986 + 0.083187367880657226 + 0.083190371383321415 + 0.083193374924439775 + 0.083196378504013777 + 0.083199382122045196 + 0.083202385778535434 + 0.083205389473485922 + 0.083208393206898365 + 0.083211396978774124 + 0.083214400789114698 + 0.083217404637921821 + 0.083220408525196854 + 0.083223412450941309 + 0.083226416415156795 + 0.083229420417844799 + 0.083232424459006915 + 0.08323542853864449 + 0.083238432656759259 + 0.083241436813352485 + 0.083244441008425943 + 0.083247445241981077 + 0.083250449514019401 + 0.083253453824542439 + 0.083256458173551803 + 0.083259462561048755 + 0.083262466987035086 + 0.083265471451512293 + 0.083268475954481794 + 0.08327148049594521 + 0.083274485075903973 + 0.083277489694359733 + 0.083280494351313836 + 0.083283499046768045 + 0.083286503780723678 + 0.083289508553182331 + 0.083292513364145712 + 0.083295518213615055 + 0.083298523101592081 + 0.083301528028078178 + 0.083304532993075039 + 0.083307537996584011 + 0.083310543038606855 + 0.08331354811914489 + 0.083316553238199725 + 0.083319558395772875 + 0.083322563591865906 + 0.083325568826480303 + 0.08332857409961765 + 0.083331579411279347 + 0.083334584761467087 + 0.083337590150182328 + 0.083340595577426624 + 0.083343601043201446 + 0.083346606547508417 + 0.083349612090348954 + 0.083352617671724707 + 0.083355623291637107 + 0.08335862895008779 + 0.083361634647078187 + 0.083364640382609878 + 0.083367646156684419 + 0.08337065196930328 + 0.083373657820468072 + 0.083376663710180279 + 0.083379669638441387 + 0.083382675605253045 + 0.083385681610616727 + 0.083388687654533819 + 0.083391693737006167 + 0.083394699858035007 + 0.083397706017622114 + 0.083400712215768849 + 0.083403718452476766 + 0.08340672472774753 + 0.083409731041582599 + 0.083412737393983416 + 0.08341574378495159 + 0.08341875021448876 + 0.083421756682596271 + 0.083424763189275761 + 0.083427769734528728 + 0.083430776318356797 + 0.083433782940761439 + 0.083436789601744249 + 0.083439796301306546 + 0.083442803039450161 + 0.083445809816176456 + 0.083448816631486997 + 0.083451823485383353 + 0.083454830377867134 + 0.083457837308939603 + 0.083460844278602647 + 0.083463851286857627 + 0.08346685833370604 + 0.083469865419149455 + 0.083472872543189372 + 0.083475879705827621 + 0.083478886907065286 + 0.083481894146904295 + 0.083484901425345939 + 0.083487908742391773 + 0.083490916098043516 + 0.083493923492302613 + 0.083496930925170534 + 0.083499938396648876 + 0.083502945906739109 + 0.083505953455442927 + 0.083508961042761856 + 0.083511968668697284 + 0.083514976333250876 + 0.083517984036423992 + 0.083520991778218451 + 0.083523999558635625 + 0.083527007377677015 + 0.08353001523534434 + 0.083533023131639017 + 0.083536031066562558 + 0.0835390390401166 + 0.083542047052302629 + 0.083545055103122115 + 0.083548063192576821 + 0.083551071320668011 + 0.083554079487397528 + 0.083557087692766679 + 0.083560095936777046 + 0.083563104219430251 + 0.083566112540727794 + 0.083569120900671243 + 0.08357212929926211 + 0.083575137736501992 + 0.083578146212392429 + 0.083581154726934753 + 0.083584163280130908 + 0.083587171871982141 + 0.083590180502490077 + 0.083593189171656229 + 0.083596197879482192 + 0.083599206625969535 + 0.083602215411119674 + 0.0836052242349343 + 0.0836082330974149 + 0.083611241998563027 + 0.083614250938380263 + 0.083617259916868053 + 0.083620268934028116 + 0.08362327798986173 + 0.083626287084370768 + 0.083629296217556492 + 0.083632305389420639 + 0.08363531459996465 + 0.083638323849190149 + 0.08364133313709865 + 0.083644342463691665 + 0.083647351828970803 + 0.083650361232937592 + 0.083653370675593586 + 0.083656380156940269 + 0.083659389676979376 + 0.083662399235712268 + 0.08366540883314047 + 0.083668418469265676 + 0.083671428144089469 + 0.083674437857613249 + 0.083677447609838543 + 0.083680457400767017 + 0.083683467230400196 + 0.083686477098739678 + 0.083689487005786961 + 0.083692496951543516 + 0.08369550693601098 + 0.083698516959190908 + 0.083701527021084951 + 0.083704537121694469 + 0.083707547261021142 + 0.083710557439066371 + 0.083713567655831836 + 0.083716577911319118 + 0.083719588205529674 + 0.083722598538465198 + 0.083725608910127092 + 0.08372861932051702 + 0.083731629769636315 + 0.08373464025748685 + 0.083737650784069986 + 0.083740661349387263 + 0.083743671953440388 + 0.083746682596230762 + 0.083749693277760093 + 0.083752703998029671 + 0.083755714757041314 + 0.08375872555479652 + 0.083761736391296832 + 0.083764747266543677 + 0.08376775818053879 + 0.083770769133283532 + 0.083773780124779706 + 0.083776791155028646 + 0.083779802224032057 + 0.083782813331791439 + 0.083785824478308318 + 0.083788835663584374 + 0.083791846887621035 + 0.083794858150419815 + 0.08379786945198249 + 0.083800880792310281 + 0.083803892171405103 + 0.083806903589268331 + 0.083809915045901601 + 0.083812926541306329 + 0.083815938075484209 + 0.083818949648436752 + 0.083821961260165528 + 0.083824972910672091 + 0.083827984599957897 + 0.083830996328024793 + 0.083834008094873985 + 0.083837019900507292 + 0.083840031744926116 + 0.083843043628132136 + 0.08384605555012685 + 0.083849067510911784 + 0.083852079510488689 + 0.083855091548858895 + 0.083858103626023903 + 0.083861115741985529 + 0.083864127896745244 + 0.08386714009030459 + 0.083870152322665134 + 0.083873164593828375 + 0.083876176903796035 + 0.083879189252569514 + 0.083882201640150353 + 0.083885214066540398 + 0.083888226531740842 + 0.083891239035753407 + 0.083894251578579701 + 0.083897264160221252 + 0.083900276780679656 + 0.083903289439956397 + 0.083906302138053154 + 0.08390931487497133 + 0.083912327650712618 + 0.083915340465278529 + 0.083918353318670744 + 0.083921366210890622 + 0.083924379141939787 + 0.083927392111819987 + 0.08393040512053257 + 0.083933418168079171 + 0.083936431254461333 + 0.083939444379680719 + 0.083942457543738774 + 0.083945470746637177 + 0.083948483988377495 + 0.083951497268961131 + 0.083954510588389777 + 0.0839575239466651 + 0.083960537343788361 + 0.08396355077976142 + 0.083966564254585707 + 0.083969577768262874 + 0.083972591320794321 + 0.083975604912181839 + 0.083978618542426775 + 0.08398163221153096 + 0.083984645919495726 + 0.083987659666322698 + 0.083990673452013553 + 0.083993687276569681 + 0.083996701139992802 + 0.083999715042284456 + 0.084002728983446212 + 0.084005742963479554 + 0.084008756982386149 + 0.084011771040167535 + 0.084014785136825171 + 0.084017799272360846 + 0.084020813446776033 + 0.084023827660072201 + 0.084026841912251141 + 0.084029856203314171 + 0.08403287053326304 + 0.084035884902099303 + 0.084038899309824472 + 0.084041913756440115 + 0.084044928241947855 + 0.084047942766349221 + 0.084050957329645723 + 0.08405397193183918 + 0.084056986572930856 + 0.084060001252922525 + 0.084063015971815661 + 0.084066030729611912 + 0.084069045526312836 + 0.084072060361919929 + 0.084075075236434857 + 0.084078090149859119 + 0.08408110510219427 + 0.084084120093442072 + 0.084087135123603968 + 0.084090150192681457 + 0.084093165300676259 + 0.084096180447589763 + 0.084099195633423746 + 0.084102210858179718 + 0.084105226121859195 + 0.084108241424463825 + 0.084111256765995054 + 0.084114272146454616 + 0.084117287565843996 + 0.084120303024164914 + 0.084123318521418688 + 0.084126334057607069 + 0.084129349632731582 + 0.084132365246793919 + 0.084135380899795498 + 0.084138396591738066 + 0.084141412322622941 + 0.084144428092451984 + 0.084147443901226499 + 0.084150459748948289 + 0.084153475635618938 + 0.084156491561239805 + 0.08415950752581261 + 0.084162523529339006 + 0.084165539571820394 + 0.084168555653258537 + 0.084171571773654877 + 0.084174587933011052 + 0.084177604131328618 + 0.084180620368609196 + 0.084183636644854301 + 0.084186652960065556 + 0.084189669314244583 + 0.08419268570739287 + 0.084195702139512052 + 0.084198718610603643 + 0.084201735120669349 + 0.08420475166971067 + 0.084207768257729174 + 0.084210784884726483 + 0.084213801550704195 + 0.08421681825566385 + 0.084219834999607016 + 0.084222851782535177 + 0.08422586860445018 + 0.084228885465353578 + 0.084231902365246566 + 0.084234919304131226 + 0.084237936282008846 + 0.084240953298881108 + 0.084243970354749467 + 0.084246987449615701 + 0.084250004583481267 + 0.084253021756347746 + 0.084256038968216818 + 0.084259056219090009 + 0.084262073508968846 + 0.084265090837854911 + 0.084268108205750036 + 0.084271125612655498 + 0.08427414305857292 + 0.08427716054350412 + 0.084280178067450418 + 0.084283195630413615 + 0.084286213232395157 + 0.084289230873396626 + 0.084292248553419699 + 0.084295266272465877 + 0.084298284030536755 + 0.084301301827634012 + 0.08430431966375912 + 0.084307337538913771 + 0.084310355453099395 + 0.084313373406317796 + 0.084316391398570376 + 0.084319409429858772 + 0.084322427500184538 + 0.084325445609549493 + 0.084328463757955011 + 0.084331481945402589 + 0.084334500171894089 + 0.084337518437430883 + 0.084340536742014652 + 0.084343555085646921 + 0.084346573468329272 + 0.084349591890063538 + 0.084352610350850912 + 0.084355628850693351 + 0.084358647389592242 + 0.084361665967549071 + 0.084364684584565725 + 0.084367703240643632 + 0.084370721935784335 + 0.084373740669989511 + 0.084376759443260771 + 0.084379778255599613 + 0.084382797107007593 + 0.084385815997486527 + 0.084388834927037762 + 0.084391853895663102 + 0.084394872903363949 + 0.08439789195014194 + 0.084400911035998685 + 0.084403930160935808 + 0.084406949324954988 + 0.084409968528057641 + 0.08441298777024539 + 0.084416007051519901 + 0.084419026371882727 + 0.084422045731335535 + 0.084425065129879795 + 0.084428084567517173 + 0.084431104044249292 + 0.084434123560077637 + 0.084437143115003971 + 0.084440162709029695 + 0.084443182342156656 + 0.084446202014386115 + 0.084449221725719906 + 0.084452241476159609 + 0.084455261265706683 + 0.084458281094362889 + 0.084461300962129782 + 0.084464320869008791 + 0.084467340815001679 + 0.084470360800110084 + 0.084473380824335406 + 0.084476400887679576 + 0.084479420990143717 + 0.084482441131729841 + 0.084485461312439378 + 0.084488481532273882 + 0.084491501791235046 + 0.084494522089324411 + 0.08449754242654367 + 0.084500562802894225 + 0.084503583218377948 + 0.084506603672996047 + 0.084509624166750522 + 0.084512644699642731 + 0.084515665271674464 + 0.084518685882847097 + 0.084521706533162336 + 0.08452472722262179 + 0.084527747951227153 + 0.084530768718979701 + 0.084533789525881392 + 0.084536810371933696 + 0.084539831257138168 + 0.084542852181496556 + 0.084545873145010192 + 0.084548894147680825 + 0.084551915189510163 + 0.084554936270499689 + 0.084557957390651001 + 0.084560978549965776 + 0.084563999748445501 + 0.084567020986091881 + 0.084570042262906486 + 0.084573063578890786 + 0.084576084934046683 + 0.084579106328375481 + 0.084582127761878984 + 0.084585149234558704 + 0.084588170746416239 + 0.084591192297453169 + 0.084594213887671188 + 0.084597235517071795 + 0.084600257185656738 + 0.084603278893427447 + 0.084606300640385684 + 0.084609322426532893 + 0.084612344251870794 + 0.084615366116401011 + 0.084618388020125085 + 0.084621409963044625 + 0.084624431945161199 + 0.084627453966476543 + 0.084630476026992099 + 0.084633498126709616 + 0.084636520265630691 + 0.084639542443756655 + 0.084642564661089603 + 0.084645586917630716 + 0.08464860921338177 + 0.084651631548344444 + 0.084654653922520251 + 0.084657676335910689 + 0.084660698788517633 + 0.084663721280342497 + 0.084666743811386766 + 0.084669766381652467 + 0.084672788991140793 + 0.084675811639853604 + 0.084678834327792413 + 0.084681857054958731 + 0.084684879821354295 + 0.08468790262698081 + 0.084690925471839679 + 0.084693948355932649 + 0.084696971279261263 + 0.084699994241827017 + 0.084703017243631801 + 0.084706040284676973 + 0.084709063364964324 + 0.084712086484495297 + 0.084715109643271627 + 0.084718132841294924 + 0.084721156078566645 + 0.084724179355088636 + 0.084727202670862312 + 0.084730226025889435 + 0.08473324942017145 + 0.084736272853710118 + 0.084739296326506994 + 0.084742319838563659 + 0.084745343389881753 + 0.084748366980462883 + 0.084751390610308702 + 0.084754414279420834 + 0.08475743798780068 + 0.084760461735450154 + 0.08476348552237073 + 0.084766509348563904 + 0.084769533214031523 + 0.084772557118775085 + 0.084775581062796201 + 0.08477860504609637 + 0.084781629068677436 + 0.084784653130540899 + 0.084787677231688369 + 0.084790701372121455 + 0.084793725551841767 + 0.084796749770850985 + 0.084799774029150649 + 0.084802798326742382 + 0.08480582266362785 + 0.084808847039808705 + 0.084811871455286361 + 0.084814895910062679 + 0.084817920404139116 + 0.084820944937517406 + 0.084823969510198993 + 0.084826994122185612 + 0.084830018773478927 + 0.084833043464080424 + 0.084836068193991879 + 0.084839092963214763 + 0.084842117771750755 + 0.08484514261960148 + 0.084848167506768504 + 0.08485119243325355 + 0.084854217399058157 + 0.084857242404184019 + 0.084860267448632523 + 0.084863292532405599 + 0.084866317655504675 + 0.084869342817931404 + 0.084872368019687422 + 0.084875393260774437 + 0.084878418541193879 + 0.084881443860947509 + 0.084884469220036896 + 0.084887494618463705 + 0.084890520056229407 + 0.084893545533335862 + 0.084896571049784542 + 0.084899596605577027 + 0.084902622200715067 + 0.084905647835200229 + 0.084908673509034013 + 0.084911699222218265 + 0.084914724974754538 + 0.084917750766644276 + 0.084920776597889269 + 0.084923802468491183 + 0.084926828378451502 + 0.084929854327771864 + 0.084932880316453949 + 0.084935906344499365 + 0.084938932411909876 + 0.084941958518686841 + 0.084944984664831968 + 0.084948010850347005 + 0.084951037075233396 + 0.084954063339493013 + 0.084957089643127121 + 0.084960115986137813 + 0.084963142368526298 + 0.084966168790294283 + 0.08496919525144353 + 0.084972221751975566 + 0.084975248291892139 + 0.084978274871194678 + 0.084981301489884989 + 0.084984328147964541 + 0.084987354845435084 + 0.084990381582298241 + 0.084993408358555567 + 0.084996435174208698 + 0.08499946202925926 + 0.085002488923708902 + 0.085005515857559388 + 0.085008542830811981 + 0.085011569843468707 + 0.085014596895531008 + 0.085017623987000357 + 0.085020651117878696 + 0.085023678288167454 + 0.085026705497868366 + 0.085029732746982958 + 0.085032760035512883 + 0.08503578736345975 + 0.085038814730825363 + 0.085041842137611026 + 0.085044869583818766 + 0.085047897069449888 + 0.085050924594506111 + 0.085053952158989185 + 0.085056979762900581 + 0.08506000740624195 + 0.085063035089015082 + 0.085066062811221421 + 0.085069090572862618 + 0.085072118373940353 + 0.085075146214456429 + 0.085078174094412082 + 0.08508120201380924 + 0.085084229972649431 + 0.085087257970934443 + 0.085090286008665639 + 0.085093314085844876 + 0.085096342202473571 + 0.085099370358553666 + 0.085102398554086453 + 0.085105426789073818 + 0.085108455063517288 + 0.085111483377418501 + 0.085114511730779094 + 0.085117540123600705 + 0.085120568555884957 + 0.085123597027633474 + 0.085126625538847825 + 0.085129654089529869 + 0.085132682679681104 + 0.085135711309303003 + 0.085138739978397535 + 0.085141768686965935 + 0.085144797435010258 + 0.085147826222531822 + 0.085150855049532501 + 0.08515388391601364 + 0.085156912821977113 + 0.085159941767424557 + 0.085162970752357389 + 0.085165999776777482 + 0.085169028840686431 + 0.085172057944085625 + 0.085175087086977033 + 0.085178116269362128 + 0.085181145491242657 + 0.085184174752620023 + 0.085187204053496016 + 0.085190233393872355 + 0.085193262773750528 + 0.085196292193132309 + 0.085199321652019183 + 0.085202351150412886 + 0.085205380688315097 + 0.085208410265727383 + 0.085211439882651369 + 0.085214469539088705 + 0.085217499235040961 + 0.085220528970510009 + 0.085223558745497252 + 0.085226588560004549 + 0.085229618414033259 + 0.085232648307585146 + 0.085235678240661986 + 0.085238708213265152 + 0.085241738225396518 + 0.08524476827705775 + 0.085247798368250319 + 0.08525082849897582 + 0.085253858669235974 + 0.085256888879032613 + 0.085259919128367126 + 0.085262949417241232 + 0.08526597974565657 + 0.085269010113614846 + 0.085272040521117726 + 0.085275070968166597 + 0.085278101454763361 + 0.085281131980909614 + 0.085284162546606965 + 0.085287193151856955 + 0.085290223796661402 + 0.08529325448102186 + 0.085296285204939981 + 0.085299315968417444 + 0.085302346771455859 + 0.085305377614056765 + 0.085308408496221996 + 0.08531143941795323 + 0.085314470379251814 + 0.085317501380119717 + 0.085320532420558287 + 0.085323563500569383 + 0.085326594620154628 + 0.08532962577931559 + 0.085332656978053992 + 0.085335688216371344 + 0.085338719494269411 + 0.085341750811749925 + 0.08534478216881429 + 0.08534781356546435 + 0.085350845001701675 + 0.085353876477527901 + 0.085356907992944681 + 0.08535993954795365 + 0.085362971142556629 + 0.085366002776754893 + 0.085369034450550441 + 0.085372066163944799 + 0.085375097916939549 + 0.085378129709536441 + 0.085381161541737083 + 0.085384193413543003 + 0.085387225324956129 + 0.085390257275977918 + 0.085393289266609954 + 0.085396321296854011 + 0.085399353366711811 + 0.0854023854761847 + 0.085405417625274677 + 0.085408449813983184 + 0.085411482042311845 + 0.085414514310262521 + 0.085417546617836626 + 0.085420578965035923 + 0.085423611351862078 + 0.085426643778316672 + 0.085429676244401537 + 0.085432708750118061 + 0.085435741295468076 + 0.08543877388045315 + 0.085441806505075032 + 0.085444839169335221 + 0.085447871873235395 + 0.085450904616777401 + 0.085453937399962682 + 0.085456970222793013 + 0.085460003085269853 + 0.085463035987395103 + 0.085466068929170275 + 0.085469101910597076 + 0.085472134931677199 + 0.085475167992412143 + 0.085478201092803657 + 0.085481234232853281 + 0.085484267412562903 + 0.085487300631934104 + 0.085490333890968398 + 0.085493367189667602 + 0.085496400528033215 + 0.085499433906067082 + 0.085502467323770634 + 0.085505500781145716 + 0.085508534278193826 + 0.08551156781491677 + 0.085514601391316086 + 0.085517635007393483 + 0.085520668663150654 + 0.085523702358589138 + 0.085526736093710809 + 0.085529769868517 + 0.085532803683009639 + 0.08553583753719024 + 0.085538871431060565 + 0.085541905364622126 + 0.085544939337876796 + 0.085547973350826007 + 0.085551007403471546 + 0.085554041495815053 + 0.085557075627858206 + 0.085560109799602477 + 0.085563144011049835 + 0.085566178262201753 + 0.085569212553059798 + 0.085572246883625899 + 0.085575281253901472 + 0.085578315663888252 + 0.085581350113587959 + 0.085584384603002217 + 0.085587419132132594 + 0.085590453700980923 + 0.085593488309548715 + 0.085596522957837679 + 0.085599557645849519 + 0.085602592373585806 + 0.085605627141048343 + 0.085608661948238546 + 0.085611696795158329 + 0.08561473168180922 + 0.085617766608192938 + 0.085620801574311123 + 0.085623836580165397 + 0.085626871625757536 + 0.085629906711089027 + 0.085632941836161672 + 0.085635977000976998 + 0.085639012205536824 + 0.085642047449842773 + 0.08564508273389651 + 0.085648118057699618 + 0.085651153421253831 + 0.085654188824560731 + 0.085657224267622067 + 0.085660259750439505 + 0.085663295273014695 + 0.085666330835349178 + 0.085669366437444827 + 0.085672402079303211 + 0.085675437760925954 + 0.085678473482314721 + 0.085681509243471232 + 0.085684545044397181 + 0.085687580885094206 + 0.085690616765563929 + 0.085693652685807947 + 0.085696688645828092 + 0.085699724645625877 + 0.085702760685203105 + 0.085705796764561332 + 0.085708832883702346 + 0.085711869042627717 + 0.085714905241339123 + 0.085717941479838189 + 0.085720977758126676 + 0.08572401407620614 + 0.085727050434078425 + 0.085730086831745031 + 0.08573312326920772 + 0.085736159746468144 + 0.085739196263527842 + 0.085742232820388689 + 0.085745269417052267 + 0.085748306053520171 + 0.085751342729794053 + 0.085754379445875856 + 0.085757416201766926 + 0.085760452997469039 + 0.085763489832983958 + 0.085766526708313279 + 0.085769563623458583 + 0.08577260057842169 + 0.085775637573204153 + 0.08577867460780772 + 0.085781711682234058 + 0.085784748796484844 + 0.085787785950561676 + 0.085790823144466316 + 0.085793860378200318 + 0.085796897651765458 + 0.085799934965163346 + 0.085802972318395745 + 0.085806009711464223 + 0.085809047144370487 + 0.085812084617116313 + 0.085815122129703159 + 0.085818159682132786 + 0.085821197274406888 + 0.085824234906527241 + 0.085827272578495345 + 0.085830310290312961 + 0.085833348041981741 + 0.085836385833503365 + 0.085839423664879566 + 0.0858424615361119 + 0.085845499447201989 + 0.085848537398151792 + 0.085851575388962695 + 0.085854613419636558 + 0.085857651490174935 + 0.085860689600579576 + 0.085863727750852048 + 0.085866765940994211 + 0.085869804171007577 + 0.085872842440893812 + 0.085875880750654776 + 0.085878919100291926 + 0.085881957489807093 + 0.085884995919201956 + 0.085888034388478002 + 0.085891072897637061 + 0.08589411144668091 + 0.085897150035610964 + 0.085900188664429139 + 0.085903227333136975 + 0.085906266041736082 + 0.085909304790228361 + 0.085912343578615297 + 0.085915382406898694 + 0.085918421275080079 + 0.085921460183161366 + 0.085924499131143986 + 0.08592753811902977 + 0.085930577146820286 + 0.085933616214517269 + 0.085936655322122538 + 0.085939694469637604 + 0.085942733657064119 + 0.085945772884403748 + 0.085948812151658394 + 0.085951851458829484 + 0.085954890805918893 + 0.085957930192928175 + 0.085960969619859023 + 0.085964009086713145 + 0.085967048593492218 + 0.085970088140197992 + 0.085973127726831994 + 0.085976167353395944 + 0.085979207019891618 + 0.085982246726320682 + 0.08598528647268476 + 0.085988326258985476 + 0.085991366085224771 + 0.085994405951403979 + 0.085997445857525015 + 0.086000485803589502 + 0.086003525789599147 + 0.086006565815555505 + 0.086009605881460463 + 0.086012645987315534 + 0.086015686133122424 + 0.086018726318882993 + 0.086021766544598685 + 0.086024806810271248 + 0.086027847115902528 + 0.086030887461493968 + 0.086033927847047414 + 0.086036968272564546 + 0.08604000873804693 + 0.086043049243496372 + 0.086046089788914579 + 0.08604913037430309 + 0.086052170999663752 + 0.086055211664997938 + 0.086058252370307842 + 0.086061293115594698 + 0.086064333900860449 + 0.086067374726106663 + 0.086070415591335034 + 0.086073456496547393 + 0.086076497441745156 + 0.086079538426930252 + 0.086082579452104208 + 0.086085620517268938 + 0.08608866162242583 + 0.086091702767576717 + 0.086094743952723346 + 0.086097785177867356 + 0.086100826443010245 + 0.086103867748154109 + 0.086106909093300377 + 0.086109950478450603 + 0.086112991903606689 + 0.086116033368770328 + 0.086119074873943102 + 0.086122116419126746 + 0.086125158004323007 + 0.086128199629533497 + 0.08613124129475995 + 0.086134283000004086 + 0.086137324745267391 + 0.086140366530551821 + 0.08614340835585893 + 0.086146450221190385 + 0.086149492126547947 + 0.086152534071933212 + 0.08615557605734811 + 0.086158618082793986 + 0.086161660148272867 + 0.086164702253786155 + 0.086167744399335722 + 0.08617078658492322 + 0.086173828810550301 + 0.086176871076218742 + 0.086179913381930123 + 0.086182955727686195 + 0.086185998113488677 + 0.086189040539339221 + 0.086192083005239506 + 0.086195125511191309 + 0.086198168057196184 + 0.086201210643255893 + 0.086204253269372241 + 0.086207295935546824 + 0.086210338641781292 + 0.08621338138807734 + 0.086216424174436646 + 0.086219467000861097 + 0.086222509867352234 + 0.086225552773911709 + 0.086228595720541326 + 0.086231638707242708 + 0.086234681734017576 + 0.086237724800867721 + 0.086240767907794585 + 0.086243811054800085 + 0.08624685424188587 + 0.08624989746905358 + 0.086252940736304934 + 0.086255984043641667 + 0.08625902739106539 + 0.086262070778577934 + 0.086265114206180882 + 0.086268157673876009 + 0.086271201181664939 + 0.086274244729549504 + 0.086277288317531189 + 0.086280331945611757 + 0.086283375613793067 + 0.086286419322076674 + 0.086289463070464353 + 0.086292506858957674 + 0.086295550687558398 + 0.086298594556268329 + 0.086301638465089023 + 0.086304682414022268 + 0.086307726403069732 + 0.086310770432233078 + 0.086313814501514027 + 0.086316858610914371 + 0.086319902760435552 + 0.086322946950079707 + 0.086325991179848155 + 0.086329035449742658 + 0.086332079759764951 + 0.086335124109916811 + 0.086338168500200041 + 0.086341212930616043 + 0.086344257401166635 + 0.086347301911853566 + 0.086350346462678543 + 0.086353391053643258 + 0.086356435684749419 + 0.086359480355998622 + 0.08636252506739274 + 0.086365569818933383 + 0.086368614610622244 + 0.086371659442460946 + 0.086374704314451406 + 0.086377749226595205 + 0.086380794178894035 + 0.086383839171349619 + 0.086386884203963663 + 0.086389929276737845 + 0.086392974389673818 + 0.086396019542773497 + 0.08639906473603827 + 0.086402109969470189 + 0.086405155243070686 + 0.086408200556841591 + 0.086411245910784612 + 0.086414291304901386 + 0.086417336739193606 + 0.086420382213663147 + 0.086423427728311533 + 0.086426473283140542 + 0.086429518878151812 + 0.086432564513347215 + 0.086435610188728279 + 0.086438655904296807 + 0.086441701660054507 + 0.086444747456002974 + 0.086447793292143957 + 0.086450839168479413 + 0.086453885085010701 + 0.086456931041739599 + 0.086459977038668034 + 0.086463023075797521 + 0.086466069153129807 + 0.08646911527066653 + 0.086472161428409577 + 0.086475207626360462 + 0.086478253864521043 + 0.086481300142892847 + 0.08648434646147786 + 0.086487392820277537 + 0.086490439219293752 + 0.086493485658528171 + 0.086496532137982349 + 0.086499578657658283 + 0.086502625217557291 + 0.086505671817681595 + 0.086508718458032527 + 0.086511765138611835 + 0.086514811859421364 + 0.086517858620462712 + 0.086520905421737654 + 0.086523952263247814 + 0.086526999144995023 + 0.086530046066980837 + 0.086533093029207156 + 0.086536140031675715 + 0.08653918707438793 + 0.086542234157345757 + 0.086545281280550834 + 0.086548328444004868 + 0.086551375647709705 + 0.086554422891666843 + 0.086557470175878073 + 0.086560517500345213 + 0.086563564865069872 + 0.086566612270053758 + 0.086569659715298536 + 0.086572707200806148 + 0.086575754726578039 + 0.086578802292616025 + 0.086581849898921953 + 0.086584897545497336 + 0.086587945232343907 + 0.086590992959463514 + 0.086594040726857835 + 0.086597088534528577 + 0.086600136382477322 + 0.086603184270705916 + 0.086606232199216093 + 0.086609280168009464 + 0.086612328177087874 + 0.086615376226452906 + 0.086618424316106363 + 0.086621472446049938 + 0.086624520616285394 + 0.086627568826814313 + 0.086630617077638666 + 0.086633665368759757 + 0.086636713700179821 + 0.086639762071900106 + 0.086642810483922625 + 0.086645858936249015 + 0.086648907428880817 + 0.086651955961820029 + 0.08665500453506822 + 0.086658053148627207 + 0.086661101802498655 + 0.086664150496684147 + 0.086667199231185585 + 0.086670248006004674 + 0.086673296821143039 + 0.086676345676602359 + 0.086679394572384549 + 0.086682443508491205 + 0.086685492484924007 + 0.086688541501684757 + 0.086691590558775233 + 0.086694639656196976 + 0.086697688793951802 + 0.086700737972041461 + 0.08670378719046766 + 0.086706836449231939 + 0.086709885748336296 + 0.086712935087782425 + 0.08671598446757188 + 0.086719033887706409 + 0.086722083348187803 + 0.086725132849017825 + 0.086728182390198152 + 0.086731231971730369 + 0.086734281593616486 + 0.086737331255857975 + 0.086740380958456584 + 0.086743430701414215 + 0.086746480484732436 + 0.086749530308412967 + 0.086752580172457669 + 0.08675563007686804 + 0.086758680021646023 + 0.086761730006793214 + 0.086764780032311445 + 0.086767830098202228 + 0.086770880204467521 + 0.086773930351109044 + 0.086776980538128309 + 0.086780030765527136 + 0.08678308103330741 + 0.086786131341470618 + 0.086789181690018632 + 0.08679223207895316 + 0.086795282508275881 + 0.086798332977988571 + 0.086801383488092854 + 0.08680443403859063 + 0.086807484629483414 + 0.086810535260773231 + 0.086813585932461509 + 0.086816636644550055 + 0.086819687397040712 + 0.086822738189935078 + 0.086825789023234928 + 0.086828839896942026 + 0.086831890811058049 + 0.086834941765584664 + 0.086837992760523744 + 0.08684104379587694 + 0.086844094871646002 + 0.086847145987832663 + 0.086850197144438646 + 0.086853248341465628 + 0.086856299578915303 + 0.086859350856789572 + 0.086862402175090017 + 0.086865453533818429 + 0.08686850493297657 + 0.08687155637256605 + 0.086874607852588853 + 0.086877659373046326 + 0.086880710933940467 + 0.086883762535272996 + 0.086886814177045552 + 0.086889865859259854 + 0.086892917581917681 + 0.086895969345020904 + 0.086899021148570982 + 0.086902072992569857 + 0.086905124877018999 + 0.086908176801920534 + 0.086911228767275958 + 0.086914280773087035 + 0.086917332819355445 + 0.08692038490608299 + 0.086923437033271378 + 0.086926489200922302 + 0.086929541409037581 + 0.086932593657618892 + 0.086935645946667958 + 0.086938698276186582 + 0.086941750646176388 + 0.086944803056639264 + 0.086947855507576763 + 0.086950907998990773 + 0.086953960530882946 + 0.086957013103255015 + 0.086960065716108786 + 0.086963118369445855 + 0.08696617106326808 + 0.086969223797577155 + 0.086972276572374857 + 0.086975329387662892 + 0.086978382243442912 + 0.086981435139716776 + 0.086984488076486205 + 0.086987541053752865 + 0.08699059407151849 + 0.08699364712978494 + 0.086996700228553811 + 0.086999753367826865 + 0.087002806547605893 + 0.087005859767892588 + 0.087008913028688795 + 0.087011966329996165 + 0.087015019671816365 + 0.087018073054151171 + 0.087021126477002414 + 0.087024179940371732 + 0.087027233444260985 + 0.08703028698867174 + 0.087033340573605872 + 0.087036394199065045 + 0.087039447865051037 + 0.087042501571565581 + 0.087045555318610385 + 0.087048609106187225 + 0.087051662934297794 + 0.087054716802943966 + 0.087057770712127266 + 0.087060824661849584 + 0.087063878652112639 + 0.087066932682918222 + 0.087069986754267845 + 0.08707304086616359 + 0.0870760950186069 + 0.087079149211599607 + 0.08708220344514353 + 0.087085257719240389 + 0.087088312033891946 + 0.087091366389099756 + 0.087094420784865789 + 0.08709747522119167 + 0.087100529698079202 + 0.087103584215529994 + 0.087106638773546019 + 0.087109693372128816 + 0.087112748011280217 + 0.08711580269100197 + 0.087118857411295769 + 0.087121912172163404 + 0.087124966973606527 + 0.087128021815627066 + 0.087131076698226576 + 0.087134131621406846 + 0.087137186585169696 + 0.087140241589516804 + 0.087143296634449988 + 0.087146351719970885 + 0.087149406846081315 + 0.087152462012783094 + 0.087155517220077708 + 0.087158572467967182 + 0.087161627756453114 + 0.087164683085537417 + 0.087167738455221438 + 0.087170793865507343 + 0.087173849316396754 + 0.087176904807891323 + 0.087179960339992868 + 0.08718301591270311 + 0.087186071526023867 + 0.087189127179956805 + 0.08719218287450374 + 0.087195238609666395 + 0.08719829438544642 + 0.087201350201845634 + 0.087204406058865841 + 0.087207461956508761 + 0.087210517894776074 + 0.087213573873669598 + 0.087216629893191039 + 0.087219685953342244 + 0.087222742054124835 + 0.087225798195540619 + 0.087228854377591342 + 0.087231910600278684 + 0.087234966863604435 + 0.087238023167570428 + 0.087241079512178341 + 0.087244135897430006 + 0.087247192323327019 + 0.087250248789871282 + 0.087253305297064418 + 0.087256361844908245 + 0.087259418433404526 + 0.087262475062554967 + 0.087265531732361346 + 0.087268588442825382 + 0.087271645193948921 + 0.087274701985733658 + 0.08727775881818127 + 0.087280815691293576 + 0.087283872605072296 + 0.087286929559519263 + 0.087289986554636129 + 0.087293043590424738 + 0.087296100666886811 + 0.08729915778402414 + 0.087302214941838319 + 0.087305272140331278 + 0.087308329379504612 + 0.087311386659360279 + 0.087314443979899833 + 0.087317501341125092 + 0.087320558743037874 + 0.087323616185639927 + 0.087326673668932986 + 0.08732973119291873 + 0.087332788757598936 + 0.087335846362975394 + 0.087338904009049922 + 0.087341961695824144 + 0.087345019423299988 + 0.087348077191478996 + 0.087351135000363123 + 0.087354192849953868 + 0.087357250740253384 + 0.08736030867126296 + 0.087363366642984802 + 0.087366424655420341 + 0.087369482708571394 + 0.087372540802439766 + 0.087375598937027329 + 0.087378657112335653 + 0.087381715328366541 + 0.087384773585121867 + 0.087387831882603212 + 0.087390890220812423 + 0.087393948599751331 + 0.087397007019421644 + 0.087400065479824957 + 0.087403123980963254 + 0.087406182522838161 + 0.087409241105451507 + 0.087412299728805001 + 0.087415358392900475 + 0.087418417097739606 + 0.087421475843324173 + 0.087424534629655937 + 0.087427593456736688 + 0.087430652324568231 + 0.087433711233152134 + 0.087436770182490395 + 0.087439829172584596 + 0.087442888203436597 + 0.087445947275048078 + 0.087449006387420869 + 0.087452065540556817 + 0.087455124734457393 + 0.087458183969124734 + 0.087461243244560227 + 0.087464302560765914 + 0.087467361917743472 + 0.087470421315494651 + 0.08747348075402113 + 0.087476540233324823 + 0.087479599753407425 + 0.087482659314270669 + 0.087485718915916277 + 0.087488778558346178 + 0.087491838241562009 + 0.087494897965565629 + 0.087497957730358594 + 0.08750101753594286 + 0.087504077382320092 + 0.087507137269492163 + 0.087510197197460712 + 0.087513257166227612 + 0.087516317175794708 + 0.087519377226163472 + 0.087522437317335777 + 0.087525497449313622 + 0.087528557622098407 + 0.087531617835692188 + 0.087534678090096615 + 0.08753773838531341 + 0.087540798721344473 + 0.087543859098191484 + 0.087546919515856192 + 0.087549979974340386 + 0.087553040473645732 + 0.087556101013774215 + 0.08755916159472743 + 0.087562222216507238 + 0.087565282879115344 + 0.087568343582553582 + 0.087571404326823574 + 0.087574465111927235 + 0.087577525937866205 + 0.087580586804642535 + 0.087583647712257656 + 0.0875867086607134 + 0.087589769650011751 + 0.087592830680154235 + 0.087595891751142657 + 0.087598952862978946 + 0.087602014015664698 + 0.087605075209201799 + 0.087608136443591972 + 0.087611197718837019 + 0.087614259034938524 + 0.087617320391898595 + 0.087620381789718774 + 0.087623443228400696 + 0.087626504707946529 + 0.087629566228357783 + 0.087632627789636236 + 0.087635689391783581 + 0.087638751034801857 + 0.087641812718692549 + 0.087644874443457671 + 0.087647936209098873 + 0.087650998015617806 + 0.087654059863016456 + 0.087657121751296502 + 0.087660183680459691 + 0.087663245650507898 + 0.087666307661442761 + 0.087669369713266138 + 0.087672431805979723 + 0.087675493939585347 + 0.087678556114084844 + 0.087681618329479932 + 0.087684680585772265 + 0.08768774288296384 + 0.087690805221056295 + 0.087693867600051392 + 0.087696930019950922 + 0.087699992480756744 + 0.087703054982470552 + 0.087706117525094038 + 0.087709180108629076 + 0.087712242733077483 + 0.08771530539844101 + 0.087718368104721361 + 0.087721430851920495 + 0.087724493640039827 + 0.087727556469081425 + 0.087730619339047106 + 0.087733682249938369 + 0.087736745201757199 + 0.087739808194505442 + 0.08774287122818468 + 0.087745934302796785 + 0.08774899741834348 + 0.087752060574826651 + 0.087755123772247895 + 0.087758187010609223 + 0.087761250289912246 + 0.087764313610158712 + 0.087767376971350605 + 0.087770440373489453 + 0.087773503816577184 + 0.087776567300615546 + 0.087779630825606372 + 0.087782694391551272 + 0.087785757998452202 + 0.087788821646310813 + 0.08779188533512905 + 0.087794949064908548 + 0.08779801283565114 + 0.08780107664735845 + 0.087804140500032449 + 0.087807204393674856 + 0.087810268328287547 + 0.087813332303872213 + 0.087816396320430604 + 0.087819460377964481 + 0.087822524476475691 + 0.087825588615966052 + 0.087828652796437257 + 0.087831717017891123 + 0.087834781280329371 + 0.087837845583753932 + 0.087840909928166469 + 0.087843974313568815 + 0.087847038739962677 + 0.087850103207349858 + 0.08785316771573233 + 0.087856232265111495 + 0.08785929685548953 + 0.087862361486867921 + 0.087865426159248652 + 0.087868490872633459 + 0.087871555627024006 + 0.087874620422422237 + 0.087877685258829774 + 0.087880750136248575 + 0.087883815054680306 + 0.087886880014126742 + 0.087889945014589702 + 0.087893010056071058 + 0.087896075138572491 + 0.087899140262095707 + 0.087902205426642718 + 0.087905270632215149 + 0.087908335878814747 + 0.087911401166443415 + 0.087914466495102886 + 0.087917531864794965 + 0.087920597275521331 + 0.087923662727284024 + 0.087926728220084613 + 0.087929793753924873 + 0.087932859328806651 + 0.087935924944731833 + 0.08793899060170203 + 0.087942056299719143 + 0.087945122038784906 + 0.087948187818901125 + 0.087951253640069629 + 0.087954319502292114 + 0.087957385405570354 + 0.087960451349906349 + 0.087963517335301694 + 0.087966583361758277 + 0.087969649429277735 + 0.087972715537861998 + 0.087975781687512786 + 0.087978847878231875 + 0.087981914110021139 + 0.087984980382882327 + 0.08798804669681716 + 0.08799111305182758 + 0.087994179447915197 + 0.087997245885081982 + 0.0880003123633296 + 0.088003378882659716 + 0.088006445443074427 + 0.088009512044575397 + 0.08801257868716432 + 0.08801564537084311 + 0.088018712095613419 + 0.088021778861477218 + 0.088024845668436144 + 0.088027912516492043 + 0.08803097940564672 + 0.088034046335902005 + 0.088037113307259662 + 0.088040180319721412 + 0.088043247373289071 + 0.088046314467964473 + 0.088049381603749505 + 0.088052448780645803 + 0.088055515998655132 + 0.088058583257779363 + 0.088061650558020413 + 0.088064717899379849 + 0.088067785281859587 + 0.088070852705461347 + 0.088073920170187003 + 0.088076987676038443 + 0.088080055223017206 + 0.088083122811125333 + 0.088086190440364351 + 0.088089258110736271 + 0.088092325822242828 + 0.088095393574885855 + 0.088098461368667114 + 0.088101529203588352 + 0.088104597079651389 + 0.088107664996857946 + 0.088110732955210144 + 0.088113800954709401 + 0.088116868995357603 + 0.088119937077156679 + 0.088123005200108351 + 0.08812607336421438 + 0.088129141569476599 + 0.088132209815896756 + 0.088135278103476683 + 0.088138346432218323 + 0.088141414802123244 + 0.08814448321319332 + 0.088147551665430313 + 0.088150620158836263 + 0.088153688693412557 + 0.088156757269161279 + 0.0881598258860843 + 0.088162894544183079 + 0.088165963243459655 + 0.088169031983915847 + 0.088172100765553318 + 0.088175169588373986 + 0.088178238452379695 + 0.088181307357572042 + 0.088184376303952941 + 0.088187445291524238 + 0.088190514320287641 + 0.088193583390245023 + 0.088196652501398118 + 0.0881997216537488 + 0.088202790847298845 + 0.088205860082049989 + 0.088208929358004132 + 0.088211998675163023 + 0.08821506803352841 + 0.088218137433102098 + 0.088221206873886168 + 0.088224276355881981 + 0.088227345879091645 + 0.088230415443516896 + 0.088233485049159427 + 0.088236554696021166 + 0.088239624384103904 + 0.088242694113409459 + 0.08824576388393944 + 0.088248833695695902 + 0.088251903548680524 + 0.08825497344289511 + 0.08825804337834145 + 0.088261113355021431 + 0.088264183372936886 + 0.088267253432089451 + 0.088270323532480988 + 0.088273393674113368 + 0.088276463856988369 + 0.088279534081107808 + 0.088282604346473392 + 0.088285674653087023 + 0.08828874500095045 + 0.088291815390065601 + 0.088294885820434141 + 0.088297956292057916 + 0.088301026804938745 + 0.088304097359078501 + 0.088307167954478877 + 0.088310238591141704 + 0.088313309269068718 + 0.088316379988261931 + 0.08831945074872305 + 0.088322521550453795 + 0.088325592393456026 + 0.088328663277731548 + 0.088331734203282289 + 0.088334805170109901 + 0.088337876178216257 + 0.088340947227603134 + 0.088344018318272294 + 0.088347089450225708 + 0.088350160623465068 + 0.088353231837992152 + 0.088356303093808902 + 0.08835937439091697 + 0.088362445729318215 + 0.08836551710901451 + 0.088368588530007577 + 0.088371659992299276 + 0.088374731495891423 + 0.088377803040785796 + 0.088380874626984282 + 0.088383946254488574 + 0.088387017923300587 + 0.088390089633422014 + 0.088393161384854813 + 0.088396233177600619 + 0.088399305011661433 + 0.088402376887038864 + 0.088405448803734937 + 0.088408520761751277 + 0.088411592761089869 + 0.088414664801752335 + 0.088417736883740577 + 0.088420809007056525 + 0.088423881171701829 + 0.088426953377678322 + 0.088430025624987862 + 0.088433097913632297 + 0.088436170243613305 + 0.088439242614932814 + 0.088442315027592588 + 0.088445387481594417 + 0.088448459976940258 + 0.088451532513631775 + 0.08845460509167076 + 0.088457677711059224 + 0.088460750371798735 + 0.088463823073891334 + 0.088466895817338645 + 0.088469968602142485 + 0.088473041428304838 + 0.088476114295827496 + 0.088479187204712068 + 0.088482260154960579 + 0.088485333146574793 + 0.088488406179556459 + 0.088491479253907393 + 0.088494552369629609 + 0.088497625526724549 + 0.088500698725194379 + 0.088503771965040806 + 0.088506845246265606 + 0.088509918568870541 + 0.088512991932857554 + 0.088516065338228311 + 0.088519138784984838 + 0.088522212273128814 + 0.088525285802662113 + 0.088528359373586551 + 0.088531432985903824 + 0.088534506639615831 + 0.088537580334724475 + 0.088540654071231378 + 0.088543727849138595 + 0.088546801668447903 + 0.088549875529160924 + 0.08855294943127956 + 0.088556023374805767 + 0.088559097359741226 + 0.088562171386087823 + 0.088565245453847377 + 0.088568319563021553 + 0.088571393713612362 + 0.088574467905621651 + 0.088577542139051071 + 0.088580616413902566 + 0.088583690730177786 + 0.088586765087878744 + 0.088589839487007271 + 0.088592913927565006 + 0.088595988409553933 + 0.088599062932975856 + 0.088602137497832453 + 0.088605212104125711 + 0.088608286751857293 + 0.088611361441029282 + 0.088614436171643204 + 0.088617510943700975 + 0.088620585757204551 + 0.088623660612155652 + 0.08862673550855607 + 0.088629810446407664 + 0.088632885425712252 + 0.088635960446471679 + 0.088639035508687777 + 0.088642110612362338 + 0.08864518575749708 + 0.088648260944094018 + 0.088651336172154857 + 0.088654411441681499 + 0.088657486752675693 + 0.088660562105139354 + 0.088663637499074216 + 0.088666712934482167 + 0.088669788411364941 + 0.088672863929724427 + 0.088675939489562455 + 0.088679015090880928 + 0.088682090733681426 + 0.088685166417965991 + 0.088688242143736482 + 0.088691317910994549 + 0.088694393719742068 + 0.088697469569980994 + 0.088700545461712924 + 0.088703621394939994 + 0.088706697369663717 + 0.088709773385886231 + 0.08871284944360909 + 0.088715925542834223 + 0.088719001683563434 + 0.088722077865798568 + 0.088725154089541472 + 0.088728230354793922 + 0.088731306661557804 + 0.088734383009834952 + 0.088737459399627169 + 0.088740535830936329 + 0.088743612303764222 + 0.088746688818112526 + 0.088749765373983311 + 0.08875284197137831 + 0.088755918610299384 + 0.088758995290748266 + 0.088762072012726845 + 0.088765148776236924 + 0.088768225581280405 + 0.088771302427859147 + 0.088774379315974816 + 0.088777456245629258 + 0.088780533216824484 + 0.088783610229562271 + 0.088786687283844312 + 0.088789764379672606 + 0.088792841517048846 + 0.088795918695974876 + 0.088798995916452642 + 0.088802073178483959 + 0.088805150482070452 + 0.088808227827214176 + 0.088811305213916975 + 0.0888143826421805 + 0.088817460112006696 + 0.088820537623397408 + 0.088823615176354453 + 0.088826692770879692 + 0.088829770406974873 + 0.088832848084641772 + 0.08883592580388254 + 0.088839003564698538 + 0.088842081367092055 + 0.088845159211064742 + 0.088848237096618266 + 0.088851315023754776 + 0.088854392992475828 + 0.088857471002783323 + 0.088860549054679314 + 0.088863627148165439 + 0.088866705283243488 + 0.088869783459915364 + 0.088872861678183021 + 0.088875939938048057 + 0.088879018239512539 + 0.088882096582578132 + 0.088885174967246697 + 0.088888253393520161 + 0.088891331861400233 + 0.088894410370888938 + 0.088897488921987927 + 0.088900567514699186 + 0.088903646149024407 + 0.088906724824965436 + 0.088909803542524243 + 0.08891288230170262 + 0.088915961102502356 + 0.088919039944925296 + 0.088922118828973176 + 0.088925197754648036 + 0.088928276721951721 + 0.088931355730885869 + 0.088934434781452493 + 0.088937513873653257 + 0.088940593007490201 + 0.088943672182965075 + 0.088946751400079654 + 0.088949830658835841 + 0.088952909959235438 + 0.088955989301280403 + 0.088959068684972373 + 0.088962148110313388 + 0.08896522757730517 + 0.088968307085949605 + 0.088971386636248539 + 0.088974466228203722 + 0.088977545861817123 + 0.088980625537090477 + 0.088983705254025658 + 0.088986785012624525 + 0.08898986481288905 + 0.088992944654820799 + 0.0889960245384218 + 0.088999104463693843 + 0.089002184430638787 + 0.089005264439258477 + 0.089008344489554678 + 0.08901142458152933 + 0.089014504715184198 + 0.089017584890521265 + 0.089020665107542252 + 0.089023745366248977 + 0.089026825666643369 + 0.089029906008727261 + 0.089032986392502372 + 0.089036066817970771 + 0.089039147285134138 + 0.089042227793994316 + 0.089045308344553181 + 0.089048388936812606 + 0.089051469570774422 + 0.089054550246440489 + 0.08905763096381257 + 0.089060711722892566 + 0.08906379252368235 + 0.089066873366183741 + 0.089069954250398584 + 0.089073035176328766 + 0.089076116143976078 + 0.089079197153342296 + 0.08908227820442928 + 0.089085359297239194 + 0.089088440431773455 + 0.08909152160803413 + 0.089094602826022995 + 0.089097684085742007 + 0.089100765387192846 + 0.089103846730377509 + 0.089106928115297773 + 0.089110009541955498 + 0.089113091010352474 + 0.089116172520490589 + 0.089119254072371798 + 0.089122335665997796 + 0.089125417301370455 + 0.089128498978491733 + 0.089131580697363405 + 0.089134662457987165 + 0.089137744260365123 + 0.089140826104499138 + 0.089143907990390708 + 0.089146989918042027 + 0.089150071887454899 + 0.089153153898631043 + 0.089156235951572321 + 0.089159318046280772 + 0.089162400182757881 + 0.089165482361005868 + 0.089168564581026497 + 0.0891716468428215 + 0.089174729146392726 + 0.089177811491742198 + 0.089180893878871639 + 0.089183976307782839 + 0.08918705877847781 + 0.089190141290958216 + 0.08919322384522621 + 0.089196306441283249 + 0.089199389079131525 + 0.089202471758772717 + 0.089205554480208643 + 0.089208637243441205 + 0.089211720048472415 + 0.08921480289530391 + 0.089217885783937606 + 0.089220968714375459 + 0.089224051686619038 + 0.089227134700670632 + 0.089230217756531699 + 0.089233300854204306 + 0.08923638399369016 + 0.08923946717499126 + 0.08924255039810941 + 0.0892456336630464 + 0.089248716969804201 + 0.089251800318384616 + 0.089254883708789381 + 0.089257967141020647 + 0.089261050615079968 + 0.089264134130969341 + 0.089267217688690462 + 0.089270301288245549 + 0.089273384929636088 + 0.089276468612864188 + 0.089279552337931473 + 0.089282636104840024 + 0.089285719913591383 + 0.089288803764187782 + 0.089291887656630958 + 0.089294971590922589 + 0.089298055567064674 + 0.089301139585059142 + 0.08930422364490774 + 0.08930730774661233 + 0.089310391890174839 + 0.089313476075597087 + 0.089316560302880876 + 0.089319644572028054 + 0.089322728883040645 + 0.08932581323592037 + 0.089328897630669105 + 0.089331982067288776 + 0.08933506654578105 + 0.089338151066147981 + 0.089341235628391524 + 0.089344320232513194 + 0.089347404878515099 + 0.089350489566399086 + 0.089353574296166902 + 0.089356659067820504 + 0.089359743881361697 + 0.089362828736792438 + 0.089365913634114377 + 0.08936899857332968 + 0.089372083554440027 + 0.089375168577447095 + 0.089378253642353148 + 0.08938133874915978 + 0.089384423897868909 + 0.089387509088482392 + 0.089390594321002145 + 0.089393679595429945 + 0.089396764911767609 + 0.089399850270017206 + 0.089402935670180497 + 0.089406021112259218 + 0.089409106596255408 + 0.089412192122170803 + 0.089415277690007428 + 0.089418363299766976 + 0.089421448951451377 + 0.089424534645062517 + 0.08942762038060223 + 0.089430706158072415 + 0.08943379197747485 + 0.089436877838811449 + 0.089439963742084169 + 0.089443049687294648 + 0.089446135674444996 + 0.08944922170353696 + 0.089452307774572373 + 0.089455393887553192 + 0.08945848004248122 + 0.089461566239358359 + 0.089464652478186427 + 0.089467738758967241 + 0.089470825081702829 + 0.08947391144639498 + 0.089476997853045498 + 0.08948008430165641 + 0.089483170792229269 + 0.089486257324766311 + 0.089489343899269158 + 0.089492430515739879 + 0.089495517174180014 + 0.089498603874591728 + 0.089501690616976881 + 0.089504777401337068 + 0.089507864227674525 + 0.089510951095990846 + 0.089514038006288016 + 0.089517124958567798 + 0.08952021195283226 + 0.089523298989083136 + 0.089526386067322258 + 0.089529473187551556 + 0.089532560349772791 + 0.089535647553988046 + 0.089538734800199138 + 0.089541822088407733 + 0.08954490941861587 + 0.08954799679082541 + 0.089551084205038184 + 0.089554171661256107 + 0.089557259159481012 + 0.089560346699714771 + 0.089563434281959273 + 0.08956652190621639 + 0.08956960957248794 + 0.08957269728077577 + 0.089575785031081906 + 0.089578872823408193 + 0.089581960657756268 + 0.08958504853412827 + 0.089588136452526057 + 0.089591224412951309 + 0.089594312415405997 + 0.089597400459892007 + 0.089600488546411297 + 0.089603576674965491 + 0.089606664845556697 + 0.08960975305818672 + 0.089612841312857447 + 0.089615929609570738 + 0.089619017948328356 + 0.089622106329132339 + 0.08962519475198448 + 0.089628283216886651 + 0.089631371723840766 + 0.089634460272848715 + 0.0896375488639123 + 0.089640637497033382 + 0.089643726172213944 + 0.08964681488945582 + 0.089649903648760826 + 0.089652992450130906 + 0.089656081293567849 + 0.089659170179073558 + 0.089662259106649989 + 0.089665348076298945 + 0.089668437088022357 + 0.089671526141822014 + 0.089674615237699914 + 0.089677704375657794 + 0.089680793555697663 + 0.089683882777821203 + 0.089686972042030536 + 0.089690061348327438 + 0.089693150696713658 + 0.089696240087191334 + 0.089699329519762089 + 0.089702418994427893 + 0.08970550851119076 + 0.089708598070052284 + 0.089711687671014603 + 0.08971477731407955 + 0.089717866999248871 + 0.089720956726524512 + 0.089724046495908372 + 0.089727136307402366 + 0.089730226161008245 + 0.089733316056728074 + 0.089736405994563631 + 0.089739495974516706 + 0.089742585996589214 + 0.089745676060783333 + 0.089748766167100522 + 0.089751856315542722 + 0.089754946506112168 + 0.089758036738810318 + 0.089761127013639308 + 0.089764217330600943 + 0.089767307689697193 + 0.08977039809092964 + 0.089773488534300588 + 0.08977657901981155 + 0.089779669547464622 + 0.089782760117261676 + 0.089785850729204433 + 0.089788941383295004 + 0.089792032079535108 + 0.089795122817926579 + 0.089798213598471621 + 0.089801304421171652 + 0.089804395286028918 + 0.089807486193045183 + 0.089810577142222209 + 0.089813668133562091 + 0.089816759167066496 + 0.089819850242737642 + 0.089822941360577044 + 0.089826032520586754 + 0.089829123722768606 + 0.089832214967124513 + 0.089835306253656447 + 0.08983839758236617 + 0.089841488953255638 + 0.089844580366326587 + 0.08984767182158114 + 0.089850763319021004 + 0.089853854858648052 + 0.089856946440464339 + 0.089860038064471598 + 0.089863129730671829 + 0.089866221439066904 + 0.089869313189658476 + 0.089872404982448723 + 0.089875496817439393 + 0.089878588694632389 + 0.089881680614029638 + 0.089884772575633071 + 0.089887864579444393 + 0.089890956625465548 + 0.089894048713698521 + 0.089897140844145171 + 0.089900233016807468 + 0.089903325231687023 + 0.089906417488786083 + 0.089909509788106287 + 0.089912602129649494 + 0.089915694513417702 + 0.089918786939412743 + 0.089921879407636712 + 0.08992497191809129 + 0.08992806447077839 + 0.089931157065699832 + 0.089934249702857724 + 0.089937342382253704 + 0.089940435103889868 + 0.08994352786776795 + 0.08994662067388999 + 0.089949713522257779 + 0.089952806412873162 + 0.089955899345738097 + 0.089958992320854539 + 0.089962085338224321 + 0.089965178397849205 + 0.089968271499731287 + 0.089971364643872412 + 0.089974457830274343 + 0.089977551058939037 + 0.08998064432986852 + 0.089983737643064429 + 0.089986830998528833 + 0.089989924396263632 + 0.089993017836270672 + 0.089996111318551772 + 0.089999204843109012 + 0.09000229840994399 + 0.090005392019058994 + 0.090008485670455537 + 0.090011579364135799 + 0.090014673100101444 + 0.090017766878354555 + 0.090020860698896962 + 0.090023954561730526 + 0.090027048466857051 + 0.090030142414278674 + 0.090033236403997061 + 0.090036330436014209 + 0.090039424510332089 + 0.090042518626952381 + 0.090045612785877194 + 0.090048706987108262 + 0.090051801230647599 + 0.09005489551649698 + 0.090057989844658473 + 0.090061084215133841 + 0.090064178627924943 + 0.090067273083033791 + 0.090070367580462246 + 0.090073462120212208 + 0.09007655670228551 + 0.090079651326684135 + 0.090082745993409888 + 0.09008584070246474 + 0.090088935453850563 + 0.090092030247569316 + 0.090095125083622801 + 0.090098219962012852 + 0.090101314882741659 + 0.090104409845810751 + 0.090107504851222292 + 0.090110599898978044 + 0.090113694989079993 + 0.090116790121529969 + 0.09011988529632993 + 0.090122980513481762 + 0.090126075772987202 + 0.090129171074848358 + 0.090132266419067103 + 0.090135361805645312 + 0.090138457234584857 + 0.090141552705887487 + 0.090144648219555465 + 0.090147743775590441 + 0.090150839373994221 + 0.090153935014768982 + 0.090157030697916529 + 0.090160126423438625 + 0.090163222191337267 + 0.090166318001614357 + 0.090169413854271852 + 0.090172509749311597 + 0.09017560568673548 + 0.090178701666545388 + 0.090181797688743251 + 0.090184893753330886 + 0.090187989860310416 + 0.090191086009683522 + 0.090194182201452214 + 0.09019727843561838 + 0.090200374712183867 + 0.090203471031150603 + 0.090206567392520587 + 0.090209663796295608 + 0.090212760242477597 + 0.090215856731068481 + 0.090218953262070217 + 0.090222049835484514 + 0.090225146451313423 + 0.090228243109558862 + 0.09023133981022273 + 0.090234436553306818 + 0.090237533338813236 + 0.090240630166743691 + 0.090243727037100097 + 0.090246823949884453 + 0.090249920905098729 + 0.090253017902744662 + 0.090256114942824164 + 0.090259212025339361 + 0.090262309150291931 + 0.090265406317683761 + 0.090268503527516961 + 0.090271600779793279 + 0.0902746980745147 + 0.090277795411683112 + 0.09028089279130036 + 0.090283990213368429 + 0.090287087677889163 + 0.090290185184864424 + 0.090293282734296348 + 0.090296380326186559 + 0.090299477960537194 + 0.090302575637350072 + 0.09030567335662705 + 0.090308771118370018 + 0.090311868922581043 + 0.090314966769261859 + 0.090318064658414562 + 0.090321162590040791 + 0.090324260564142667 + 0.090327358580722078 + 0.090330456639780884 + 0.090333554741320932 + 0.090336652885344301 + 0.090339751071852797 + 0.090342849300848266 + 0.090345947572332733 + 0.090349045886308141 + 0.090352144242776225 + 0.090355242641739025 + 0.090358341083198387 + 0.09036143956715624 + 0.09036453809361461 + 0.09036763666257526 + 0.090370735274040048 + 0.090373833928011099 + 0.090376932624490175 + 0.090380031363479205 + 0.090383130144980173 + 0.090386228968994883 + 0.090389327835525307 + 0.090392426744573262 + 0.090395525696140885 + 0.09039862469022994 + 0.090401723726842409 + 0.090404822805979945 + 0.090407921927644797 + 0.090411021091838781 + 0.090414120298563647 + 0.090417219547821545 + 0.090420318839614183 + 0.090423418173943615 + 0.09042651755081163 + 0.090429616970220325 + 0.090432716432171489 + 0.090435815936667094 + 0.090438915483708984 + 0.09044201507329902 + 0.09044511470543927 + 0.090448214380131606 + 0.090451314097377861 + 0.090454413857180005 + 0.090457513659540023 + 0.090460613504459761 + 0.090463713391941092 + 0.090466813321985889 + 0.090469913294596374 + 0.090473013309774059 + 0.090476113367521108 + 0.090479213467839353 + 0.090482313610730808 + 0.090485413796197178 + 0.090488514024240713 + 0.090491614294862924 + 0.090494714608066074 + 0.090497814963851883 + 0.090500915362222351 + 0.090504015803179322 + 0.090507116286724837 + 0.0905102168128607 + 0.090513317381588895 + 0.090516417992911269 + 0.090519518646829819 + 0.090522619343346489 + 0.090525720082462985 + 0.0905288208641815 + 0.090531921688503755 + 0.090535022555431804 + 0.090538123464967535 + 0.090541224417112792 + 0.090544325411869617 + 0.090547426449239729 + 0.090550527529225294 + 0.090553628651828061 + 0.090556729817050027 + 0.090559831024893053 + 0.090562932275359123 + 0.090566033568450097 + 0.090569134904168028 + 0.090572236282514609 + 0.090575337703491937 + 0.090578439167101954 + 0.090581540673346339 + 0.090584642222227341 + 0.090587743813746735 + 0.090590845447906271 + 0.090593947124708224 + 0.090597048844154218 + 0.090600150606246363 + 0.090603252410986435 + 0.090606354258376487 + 0.090609456148418227 + 0.090612558081113931 + 0.090615660056465208 + 0.090618762074474057 + 0.09062186413514256 + 0.090624966238472437 + 0.090628068384465757 + 0.090631170573124378 + 0.090634272804450217 + 0.090637375078445173 + 0.09064047739511126 + 0.090643579754450199 + 0.090646682156464237 + 0.090649784601155026 + 0.090652887088524758 + 0.090655989618575003 + 0.090659092191307925 + 0.090662194806725466 + 0.090665297464829459 + 0.090668400165621818 + 0.090671502909104515 + 0.090674605695279478 + 0.090677708524148609 + 0.090680811395713809 + 0.090683914309977021 + 0.09068701726694027 + 0.090690120266605431 + 0.090693223308974336 + 0.09069632639404912 + 0.090699429521831396 + 0.090702532692323312 + 0.090705635905526785 + 0.090708739161443744 + 0.090711842460075923 + 0.09071494580142557 + 0.090718049185494448 + 0.090721152612284431 + 0.090724256081797516 + 0.090727359594035648 + 0.090730463149000642 + 0.090733566746694569 + 0.0907366703871193 + 0.090739774070276835 + 0.090742877796168908 + 0.090745981564797698 + 0.090749085376165023 + 0.090752189230272701 + 0.090755293127122771 + 0.090758397066717164 + 0.090761501049057849 + 0.090764605074146659 + 0.090767709141985509 + 0.090770813252576493 + 0.090773917405921403 + 0.090777021602022306 + 0.090780125840880993 + 0.090783230122499309 + 0.090786334446879391 + 0.090789438814023155 + 0.090792543223932473 + 0.090795647676609262 + 0.090798752172055519 + 0.090801856710273077 + 0.090804961291263961 + 0.090808065915029906 + 0.090811170581573078 + 0.09081427529089546 + 0.090817380042998691 + 0.090820484837884977 + 0.090823589675556052 + 0.090826694556013957 + 0.090829799479260703 + 0.090832904445297999 + 0.09083600945412805 + 0.090839114505752605 + 0.090842219600173607 + 0.090845324737393054 + 0.090848429917412848 + 0.090851535140235001 + 0.090854640405861262 + 0.090857745714293781 + 0.090860851065534307 + 0.090863956459584852 + 0.090867061896447429 + 0.090870167376123925 + 0.0908732728986162 + 0.090876378463926155 + 0.090879484072056024 + 0.090882589723007334 + 0.090885695416782306 + 0.090888801153382812 + 0.090891906932810795 + 0.090895012755068158 + 0.09089811862015687 + 0.090901224528078722 + 0.090904330478835893 + 0.0909074364724302 + 0.090910542508863559 + 0.090913648588137899 + 0.09091675471025526 + 0.090919860875217404 + 0.090922967083026482 + 0.090926073333684368 + 0.090929179627192866 + 0.090932285963554002 + 0.090935392342769747 + 0.090938498764841946 + 0.090941605229772723 + 0.090944711737563785 + 0.090947818288217283 + 0.090950924881734993 + 0.090954031518118983 + 0.090957138197371085 + 0.090960244919493283 + 0.090963351684487589 + 0.090966458492355767 + 0.090969565343099898 + 0.090972672236721897 + 0.090975779173223692 + 0.090978886152607227 + 0.090981993174874487 + 0.090985100240027275 + 0.090988207348067729 + 0.090991314498997708 + 0.090994421692819072 + 0.090997528929533791 + 0.091000636209143976 + 0.091003743531651304 + 0.091006850897057914 + 0.091009958305365721 + 0.0910130657565765 + 0.091016173250692389 + 0.091019280787715304 + 0.091022388367647131 + 0.091025495990489869 + 0.091028603656245377 + 0.091031711364915641 + 0.09103481911650263 + 0.09103792691100826 + 0.091041034748434405 + 0.091044142628783173 + 0.09104725055205648 + 0.091050358518256116 + 0.091053466527384108 + 0.091056574579442384 + 0.091059682674433068 + 0.091062790812357824 + 0.091065898993218847 + 0.091069007217017869 + 0.091072115483756946 + 0.091075223793438034 + 0.091078332146063076 + 0.091081440541633876 + 0.091084548980152641 + 0.091087657461621244 + 0.09109076598604135 + 0.091093874553415249 + 0.091096983163744663 + 0.0911000918170317 + 0.091103200513278332 + 0.091106309252486223 + 0.091109418034657649 + 0.091112526859794332 + 0.091115635727898395 + 0.091118744638971585 + 0.091121853593016125 + 0.091124962590033706 + 0.091128071630026425 + 0.091131180712996085 + 0.091134289838944754 + 0.09113739900787439 + 0.091140508219786961 + 0.091143617474684219 + 0.091146726772568354 + 0.091149836113441185 + 0.091152945497304683 + 0.091156054924160818 + 0.091159164394011574 + 0.091162273906858896 + 0.091165383462704558 + 0.091168493061550726 + 0.091171602703399163 + 0.091174712388252005 + 0.091177822116111223 + 0.091180931886978581 + 0.091184041700856103 + 0.091187151557745691 + 0.091190261457649538 + 0.09119337140056924 + 0.091196481386507031 + 0.091199591415464729 + 0.091202701487444346 + 0.091205811602447742 + 0.091208921760476999 + 0.091212031961533963 + 0.091215142205620645 + 0.091218252492739044 + 0.091221362822890908 + 0.091224473196078362 + 0.091227583612303334 + 0.091230694071567767 + 0.091233804573873659 + 0.09123691511922298 + 0.091240025707617523 + 0.091243136339059353 + 0.091246247013550372 + 0.091249357731092634 + 0.091252468491688041 + 0.091255579295338562 + 0.091258690142046003 + 0.091261801031812487 + 0.09126491196464008 + 0.091268022940530436 + 0.091271133959485759 + 0.091274245021507855 + 0.091277356126598722 + 0.091280467274760232 + 0.091283578465994691 + 0.091286689700303625 + 0.091289800977689101 + 0.0912929122981532 + 0.091296023661697853 + 0.091299135068324919 + 0.091302246518036478 + 0.091305358010834337 + 0.091308469546720658 + 0.091311581125697192 + 0.091314692747766005 + 0.091317804412929041 + 0.091320916121188242 + 0.09132402787254558 + 0.091327139667002968 + 0.091330251504562435 + 0.091333363385225949 + 0.09133647530899533 + 0.091339587275872686 + 0.091342699285859918 + 0.091345811338958957 + 0.091348923435171842 + 0.09135203557450039 + 0.091355147756946767 + 0.091358259982512804 + 0.091361372251200459 + 0.091364484563011647 + 0.091367596917948476 + 0.091370709316012683 + 0.091373821757206514 + 0.091376934241531815 + 0.091380046768990336 + 0.091383159339584324 + 0.091386271953315557 + 0.091389384610186183 + 0.091392497310198051 + 0.091395610053352908 + 0.091398722839653196 + 0.091401835669100318 + 0.091404948541696798 + 0.09140806145744422 + 0.091411174416344623 + 0.091414287418400034 + 0.091417400463612464 + 0.09142051355198362 + 0.091423626683515738 + 0.091426739858210621 + 0.091429853076070322 + 0.09143296633709673 + 0.09143607964129187 + 0.091439192988657755 + 0.091442306379196162 + 0.091445419812909198 + 0.091448533289798892 + 0.091451646809867018 + 0.091454760373115743 + 0.091457873979546758 + 0.091460987629162285 + 0.091464101321964239 + 0.091467215057954521 + 0.091470328837135059 + 0.091473442659508006 + 0.091476556525075026 + 0.091479670433838339 + 0.091482784385799834 + 0.091485898380961481 + 0.091489012419325264 + 0.09149212650089307 + 0.091495240625666982 + 0.091498354793648706 + 0.091501469004840644 + 0.091504583259244446 + 0.091507697556862083 + 0.091510811897695638 + 0.091513926281747066 + 0.091517040709018255 + 0.091520155179511287 + 0.091523269693227965 + 0.091526384250170401 + 0.091529498850340452 + 0.091532613493740311 + 0.091535728180371589 + 0.091538842910236534 + 0.091541957683337102 + 0.091545072499675015 + 0.091548187359252645 + 0.091551302262071504 + 0.09155441720813387 + 0.091557532197441643 + 0.091560647229996781 + 0.091563762305801336 + 0.091566877424857099 + 0.091569992587166027 + 0.091573107792730341 + 0.091576223041551774 + 0.091579338333632507 + 0.091582453668974356 + 0.09158556904757921 + 0.091588684469449344 + 0.091591799934586354 + 0.091594915442992572 + 0.091598030994669732 + 0.091601146589619917 + 0.091604262227844929 + 0.091607377909346963 + 0.091610493634127738 + 0.091613609402189516 + 0.091616725213534048 + 0.091619841068163468 + 0.091622956966079624 + 0.091626072907284528 + 0.091629188891780136 + 0.091632304919568489 + 0.091635420990651542 + 0.091638537105031156 + 0.091641653262709455 + 0.091644769463688269 + 0.091647885707969681 + 0.091651001995555675 + 0.091654118326448042 + 0.091657234700649112 + 0.091660351118160427 + 0.09166346757898429 + 0.091666584083122546 + 0.091669700630577167 + 0.091672817221350122 + 0.091675933855443481 + 0.091679050532859074 + 0.091682167253598998 + 0.09168528401766507 + 0.091688400825059468 + 0.091691517675784054 + 0.091694634569840838 + 0.091697751507231834 + 0.091700868487958859 + 0.091703985512024105 + 0.091707102579429225 + 0.091710219690176592 + 0.091713336844267926 + 0.091716454041705336 + 0.091719571282490739 + 0.091722688566626048 + 0.091725805894113291 + 0.091728923264954604 + 0.091732040679151666 + 0.091735158136706685 + 0.09173827563762163 + 0.091741393181898293 + 0.091744510769538795 + 0.091747628400545095 + 0.091750746074919162 + 0.09175386379266301 + 0.091756981553778538 + 0.091760099358267774 + 0.091763217206132716 + 0.091766335097375348 + 0.091769453031997683 + 0.091772571010001497 + 0.091775689031388955 + 0.091778807096162027 + 0.091781925204322712 + 0.091785043355872856 + 0.091788161550814526 + 0.091791279789149763 + 0.091794398070880509 + 0.091797516396008583 + 0.09180063476453619 + 0.091803753176465261 + 0.091806871631797654 + 0.091809990130535465 + 0.091813108672680777 + 0.091816227258235239 + 0.091819345887201184 + 0.091822464559580402 + 0.091825583275374809 + 0.091828702034586679 + 0.091831820837217581 + 0.091834939683269889 + 0.091838058572745421 + 0.091841177505646243 + 0.091844296481974133 + 0.091847415501731144 + 0.091850534564919539 + 0.0918536536715409 + 0.091856772821597321 + 0.091859892015090969 + 0.09186301125202366 + 0.091866130532397491 + 0.091869249856214391 + 0.091872369223476386 + 0.091875488634185265 + 0.091878608088343208 + 0.091881727585952186 + 0.09188484712701403 + 0.09188796671153103 + 0.091891086339504865 + 0.091894206010937687 + 0.091897325725831425 + 0.091900445484188076 + 0.091903565286009584 + 0.09190668513129796 + 0.091909805020055343 + 0.091912924952283453 + 0.091916044927984469 + 0.091919164947160265 + 0.091922285009812948 + 0.091925405115944353 + 0.091928525265556643 + 0.091931645458651609 + 0.091934765695231319 + 0.091937885975297826 + 0.091941006298853101 + 0.091944126665899087 + 0.091947247076437796 + 0.091950367530471172 + 0.091953488028001296 + 0.091956608569029999 + 0.091959729153559405 + 0.091962849781591555 + 0.091965970453128196 + 0.091969091168171549 + 0.091972211926723613 + 0.091975332728786163 + 0.09197845357436131 + 0.091981574463451093 + 0.091984695396057511 + 0.091987816372182465 + 0.091990937391827829 + 0.091994058454995906 + 0.091997179561688486 + 0.092000300711907582 + 0.092003421905655289 + 0.09200654314293337 + 0.092009664423743934 + 0.092012785748089146 + 0.092015907115970783 + 0.092019028527390842 + 0.092022149982351406 + 0.092025271480854445 + 0.092028393022901875 + 0.09203151460849586 + 0.092034636237638121 + 0.092037757910330892 + 0.092040879626576089 + 0.092044001386375612 + 0.092047123189731767 + 0.092050245036646022 + 0.092053366927120878 + 0.092056488861158026 + 0.092059610838759562 + 0.092062732859927568 + 0.09206585492466382 + 0.092068977032970428 + 0.09207209918484939 + 0.092075221380302746 + 0.092078343619332356 + 0.092081465901940371 + 0.092084588228128761 + 0.092087710597899358 + 0.092090833011254328 + 0.092093955468195599 + 0.092097077968725141 + 0.092100200512845037 + 0.092103323100557286 + 0.092106445731863773 + 0.092109568406766443 + 0.092112691125267557 + 0.092115813887368878 + 0.092118936693072376 + 0.092122059542380272 + 0.092125182435294412 + 0.092128305371816793 + 0.092131428351949499 + 0.092134551375694443 + 0.092137674443053541 + 0.092140797554029014 + 0.092143920708622623 + 0.092147043906836618 + 0.092150167148672774 + 0.0921532904341332 + 0.092156413763219813 + 0.092159537135934763 + 0.092162660552279826 + 0.09216578401225714 + 0.092168907515868773 + 0.092172031063116569 + 0.092175154654002653 + 0.092178278288528884 + 0.092181401966697427 + 0.092184525688510058 + 0.092187649453969137 + 0.092190773263076231 + 0.092193897115833742 + 0.092197021012243363 + 0.092200144952307217 + 0.092203268936027247 + 0.092206392963405645 + 0.092209517034444174 + 0.092212641149144889 + 0.092215765307509925 + 0.092218889509541185 + 0.09222201375524057 + 0.092225138044610258 + 0.092228262377652165 + 0.092231386754368219 + 0.092234511174760725 + 0.092237635638831306 + 0.09224076014658214 + 0.092243884698015199 + 0.092247009293132565 + 0.092250133931936137 + 0.092253258614427958 + 0.092256383340610038 + 0.092259508110484362 + 0.092262632924052998 + 0.092265757781317848 + 0.09226888268228102 + 0.092272007626944361 + 0.092275132615309993 + 0.092278257647379847 + 0.092281382723156072 + 0.09228450784264057 + 0.092287633005835243 + 0.092290758212742366 + 0.092293883463363674 + 0.092297008757701277 + 0.092300134095757172 + 0.092303259477533456 + 0.092306384903031974 + 0.092309510372254877 + 0.092312635885204039 + 0.092315761441881652 + 0.092318887042289438 + 0.092322012686429589 + 0.0923251383743042 + 0.092328264105915034 + 0.092331389881264339 + 0.09233451570035392 + 0.092337641563185913 + 0.092340767469762206 + 0.092343893420084922 + 0.092347019414156045 + 0.092350145451977603 + 0.092353271533551454 + 0.092356397658879832 + 0.092359523827964612 + 0.09236265004080782 + 0.092365776297411425 + 0.092368902597777552 + 0.092372028941908005 + 0.092375155329804989 + 0.092378281761470449 + 0.092381408236906284 + 0.092384534756114703 + 0.092387661319097619 + 0.092390787925857101 + 0.092393914576394967 + 0.092397041270713368 + 0.092400168008814385 + 0.092403294790699794 + 0.092406421616371887 + 0.092409548485832438 + 0.09241267539908371 + 0.092415802356127452 + 0.092418929356965732 + 0.092422056401600811 + 0.092425183490034341 + 0.0924283106222685 + 0.092431437798305344 + 0.092434565018146786 + 0.092437692281794895 + 0.09244081958925171 + 0.092443946940519175 + 0.0924470743355994 + 0.092450201774494173 + 0.092453329257205771 + 0.092456456783736027 + 0.09245958435408709 + 0.092462711968260947 + 0.092465839626259469 + 0.092468967328084822 + 0.092472095073738908 + 0.092475222863223808 + 0.092478350696541603 + 0.092481478573694098 + 0.09248460649468343 + 0.092487734459511736 + 0.092490862468180834 + 0.092493990520692973 + 0.092497118617049789 + 0.092500246757253615 + 0.092503374941306296 + 0.092506503169210039 + 0.092509631440966619 + 0.092512759756578272 + 0.09251588811604694 + 0.09251901651937447 + 0.092522144966563136 + 0.092525273457614785 + 0.092528401992531401 + 0.092531530571315204 + 0.092534659193968014 + 0.092537787860491952 + 0.09254091657088899 + 0.092544045325161139 + 0.092547174123310302 + 0.092550302965338768 + 0.092553431851248397 + 0.092556560781041353 + 0.092559689754719357 + 0.092562818772284464 + 0.092565947833739018 + 0.092569076939084755 + 0.092572206088323811 + 0.092575335281458213 + 0.092578464518489792 + 0.092581593799420811 + 0.092584723124253046 + 0.092587852492988801 + 0.092590981905629893 + 0.092594111362178405 + 0.092597240862636293 + 0.092600370407005528 + 0.092603499995288385 + 0.092606629627486711 + 0.092609759303602546 + 0.092612889023637845 + 0.092616018787594734 + 0.092619148595475209 + 0.092622278447281173 + 0.09262540834301472 + 0.092628538282677975 + 0.092631668266272796 + 0.092634798293801321 + 0.09263792836526559 + 0.09264105848066749 + 0.092644188640009117 + 0.092647318843292498 + 0.092650449090519671 + 0.092653579381692608 + 0.092656709716813307 + 0.092659840095883919 + 0.092662970518906318 + 0.092666100985882641 + 0.092669231496814802 + 0.092672362051704968 + 0.092675492650555011 + 0.092678623293367013 + 0.092681753980143042 + 0.092684884710885096 + 0.092688015485595091 + 0.092691146304275121 + 0.09269427716692745 + 0.0926974080735537 + 0.092700539024156176 + 0.092703670018736764 + 0.092706801057297394 + 0.092709932139840384 + 0.092713063266367537 + 0.092716194436881075 + 0.092719325651382647 + 0.092722456909874601 + 0.092725588212358975 + 0.092728719558837602 + 0.092731850949312619 + 0.092734982383786038 + 0.092738113862259927 + 0.09274124538473616 + 0.092744376951216984 + 0.092747508561704245 + 0.092750640216200053 + 0.092753771914706323 + 0.092756903657225234 + 0.092760035443758826 + 0.092763167274308972 + 0.092766299148877768 + 0.09276943106746724 + 0.0927725630300794 + 0.092775695036716441 + 0.09277882708738007 + 0.092781959182072604 + 0.092785091320795932 + 0.092788223503552134 + 0.092791355730343222 + 0.092794488001171127 + 0.092797620316038026 + 0.09280075267494596 + 0.092803885077896775 + 0.092807017524892566 + 0.092810150015935511 + 0.092813282551027526 + 0.092816415130170554 + 0.09281954775336683 + 0.092822680420618225 + 0.092825813131926768 + 0.092828945887294581 + 0.09283207868672369 + 0.092835211530215997 + 0.092838344417773694 + 0.092841477349398668 + 0.092844610325093085 + 0.09284774334485886 + 0.092850876408698116 + 0.09285400951661274 + 0.092857142668604981 + 0.092860275864676614 + 0.092863409104829958 + 0.092866542389066761 + 0.092869675717389272 + 0.092872809089799377 + 0.092875942506299214 + 0.092879075966890753 + 0.092882209471576049 + 0.0928853430203571 + 0.092888476613236029 + 0.092891610250214793 + 0.092894743931295376 + 0.092897877656479957 + 0.092901011425770397 + 0.092904145239168817 + 0.092907279096677425 + 0.092910412998297887 + 0.092913546944032546 + 0.092916680933883264 + 0.09291981496785208 + 0.092922949045941144 + 0.092926083168152346 + 0.092929217334487904 + 0.092932351544949693 + 0.092935485799539891 + 0.09293862009826033 + 0.092941754441113217 + 0.092944888828100453 + 0.092948023259224258 + 0.092951157734486506 + 0.092954292253889292 + 0.092957426817434671 + 0.092960561425124613 + 0.092963696076961255 + 0.092966830772946457 + 0.092969965513082453 + 0.092973100297371228 + 0.092976235125814682 + 0.092979369998415079 + 0.092982504915174208 + 0.092985639876094303 + 0.092988774881177391 + 0.092991909930425318 + 0.092995045023840359 + 0.092998180161424332 + 0.093001315343179514 + 0.093004450569107708 + 0.093007585839211177 + 0.093010721153491752 + 0.093013856511951667 + 0.093016991914592784 + 0.09302012736141721 + 0.093023262852427027 + 0.093026398387624123 + 0.093029533967010775 + 0.093032669590588868 + 0.093035805258360457 + 0.093038940970327555 + 0.093042076726492298 + 0.093045212526856644 + 0.093048348371422604 + 0.093051484260192358 + 0.093054620193167806 + 0.093057756170350989 + 0.093060892191744141 + 0.093064028257349149 + 0.09306716436716797 + 0.093070300521202812 + 0.093073436719455588 + 0.093076572961928422 + 0.093079709248623244 + 0.093082845579542342 + 0.093085981954687452 + 0.093089118374060947 + 0.093092254837664506 + 0.093095391345500378 + 0.093098527897570643 + 0.093101664493877259 + 0.093104801134422377 + 0.093107937819207731 + 0.093111074548235723 + 0.093114211321508281 + 0.093117348139027431 + 0.093120485000795117 + 0.093123621906813586 + 0.093126758857084629 + 0.093129895851610467 + 0.093133032890393153 + 0.093136169973434685 + 0.093139307100737076 + 0.093142444272302394 + 0.09314558148813272 + 0.093148718748230136 + 0.093151856052596516 + 0.093154993401234051 + 0.093158130794144756 + 0.093161268231330599 + 0.09316440571279376 + 0.09316754323853621 + 0.093170680808559961 + 0.093173818422867052 + 0.093176956081459719 + 0.093180093784339724 + 0.09318323153150937 + 0.093186369322970516 + 0.093189507158725343 + 0.09319264503877582 + 0.093195782963123905 + 0.093198920931771859 + 0.093202058944721597 + 0.093205197001975104 + 0.093208335103534656 + 0.093211473249402044 + 0.093214611439579542 + 0.093217749674068887 + 0.093220887952872533 + 0.093224026275992133 + 0.093227164643430047 + 0.093230303055188229 + 0.093233441511268708 + 0.093236580011673315 + 0.093239718556404463 + 0.093242857145463973 + 0.093245995778854091 + 0.093249134456576621 + 0.093252273178633771 + 0.093255411945027608 + 0.093258550755760034 + 0.093261689610833157 + 0.093264828510249156 + 0.093267967454009962 + 0.093271106442117724 + 0.093274245474574205 + 0.093277384551381806 + 0.093280523672542442 + 0.093283662838058043 + 0.093286802047930897 + 0.093289941302162907 + 0.093293080600756209 + 0.093296219943712705 + 0.093299359331034601 + 0.093302498762723937 + 0.093305638238782559 + 0.093308777759212799 + 0.093311917324016572 + 0.093315056933195903 + 0.093318196586752916 + 0.093321336284689624 + 0.093324476027008177 + 0.093327615813710366 + 0.093330755644798605 + 0.093333895520274657 + 0.093337035440140673 + 0.093340175404398748 + 0.093343315413050895 + 0.09334645546609914 + 0.093349595563545579 + 0.093352735705392348 + 0.093355875891641307 + 0.09335901612229465 + 0.093362156397354387 + 0.093365296716822685 + 0.093368437080701361 + 0.093371577488992608 + 0.093374717941698521 + 0.093377858438821196 + 0.093380998980362465 + 0.093384139566324534 + 0.093387280196709554 + 0.0933904208715194 + 0.093393561590756236 + 0.093396702354422101 + 0.09339984316251905 + 0.093402984015049081 + 0.093406124912014318 + 0.093409265853416662 + 0.093412406839258527 + 0.093415547869541538 + 0.093418688944268136 + 0.093421830063440112 + 0.093424971227059686 + 0.093428112435128802 + 0.093431253687649499 + 0.093434394984623942 + 0.093437536326054199 + 0.093440677711942241 + 0.093443819142290094 + 0.09344696061709995 + 0.093450102136373711 + 0.093453243700113611 + 0.093456385308321566 + 0.093459526960999739 + 0.093462668658150089 + 0.093465810399774779 + 0.093468952185875781 + 0.093472094016455148 + 0.093475235891515088 + 0.0934783778110575 + 0.093481519775084496 + 0.093484661783598155 + 0.093487803836600492 + 0.093490945934093614 + 0.093494088076079535 + 0.093497230262560377 + 0.093500372493538111 + 0.093503514769015014 + 0.093506657088992903 + 0.093509799453473888 + 0.093512941862459995 + 0.09351608431595354 + 0.093519226813956316 + 0.093522369356470444 + 0.093525511943498035 + 0.09352865457504117 + 0.093531797251101848 + 0.093534939971682204 + 0.093538082736784198 + 0.093541225546409992 + 0.093544368400561559 + 0.093547511299241007 + 0.093550654242450487 + 0.093553797230191971 + 0.093556940262467386 + 0.093560083339278982 + 0.09356322646062884 + 0.093566369626518889 + 0.093569512836951418 + 0.093572656091928233 + 0.093575799391451511 + 0.093578942735523293 + 0.093582086124145689 + 0.093585229557320695 + 0.093588373035050507 + 0.09359151655733712 + 0.093594660124182466 + 0.093597803735588764 + 0.093600947391558012 + 0.093604091092092431 + 0.093607234837193895 + 0.093610378626864388 + 0.093613522461106366 + 0.093616666339921481 + 0.093619810263312064 + 0.093622954231280045 + 0.093626098243827519 + 0.093629242300956622 + 0.093632386402669326 + 0.09363553054896781 + 0.093638674739854072 + 0.093641818975330138 + 0.093644963255398062 + 0.093648107580060064 + 0.093651251949318073 + 0.093654396363174075 + 0.093657540821630511 + 0.093660685324689075 + 0.093663829872351959 + 0.093666974464621272 + 0.093670119101499069 + 0.093673263782987279 + 0.093676408509088135 + 0.093679553279803637 + 0.093682698095136005 + 0.093685842955087098 + 0.09368898785965897 + 0.093692132808853884 + 0.093695277802673893 + 0.093698422841120857 + 0.093701567924197024 + 0.093704713051904434 + 0.093707858224245169 + 0.093711003441221144 + 0.093714148702834732 + 0.093717294009087806 + 0.093720439359982366 + 0.093723584755520617 + 0.093726730195704613 + 0.093729875680536354 + 0.093733021210018003 + 0.093736166784151656 + 0.093739312402939215 + 0.093742458066382872 + 0.093745603774484737 + 0.093748749527246739 + 0.093751895324671208 + 0.093755041166759895 + 0.093758187053515143 + 0.093761332984938786 + 0.093764478961033168 + 0.093767624981800107 + 0.093770771047241797 + 0.093773917157360373 + 0.093777063312157793 + 0.093780209511636167 + 0.093783355755797534 + 0.093786502044644088 + 0.093789648378177853 + 0.093792794756400788 + 0.09379594117931507 + 0.093799087646922796 + 0.093802234159225978 + 0.09380538071622678 + 0.093808527317927159 + 0.09381167396432924 + 0.093814820655435088 + 0.093817967391246884 + 0.093821114171766598 + 0.093824260996996173 + 0.093827407866937954 + 0.093830554781593939 + 0.093833701740966169 + 0.093836848745056614 + 0.093839995793867509 + 0.093843142887400935 + 0.093846290025658793 + 0.093849437208643346 + 0.093852584436356593 + 0.093855731708800683 + 0.093858879025977476 + 0.093862026387889305 + 0.093865173794538195 + 0.093868321245926103 + 0.093871468742055195 + 0.093874616282927467 + 0.093877763868545142 + 0.093880911498910119 + 0.093884059174024703 + 0.093887206893890865 + 0.093890354658510616 + 0.093893502467886053 + 0.093896650322019243 + 0.093899798220912489 + 0.093902946164567555 + 0.093906094152986702 + 0.093909242186171971 + 0.093912390264125387 + 0.093915538386849129 + 0.093918686554345251 + 0.093921834766615794 + 0.093924983023662784 + 0.093928131325488454 + 0.093931279672094817 + 0.093934428063483844 + 0.093937576499657824 + 0.093940724980618673 + 0.093943873506368583 + 0.093947022076909512 + 0.093950170692243637 + 0.093953319352372985 + 0.093956468057299625 + 0.093959616807025775 + 0.093962765601553408 + 0.093965914440884604 + 0.093969063325021487 + 0.093972212253966 + 0.093975361227720461 + 0.093978510246286756 + 0.093981659309667204 + 0.093984808417863622 + 0.093987957570878092 + 0.093991106768712959 + 0.093994256011370111 + 0.093997405298851616 + 0.09400055463115968 + 0.094003704008296274 + 0.094006853430263604 + 0.094010002897063655 + 0.094013152408698578 + 0.094016301965170343 + 0.09401945156648113 + 0.094022601212633033 + 0.094025750903628108 + 0.094028900639468449 + 0.094032050420156069 + 0.094035200245693229 + 0.094038350116081706 + 0.094041500031323957 + 0.094044649991421841 + 0.094047799996377565 + 0.094050950046193085 + 0.094054100140870595 + 0.094057250280412105 + 0.094060400464819727 + 0.094063550694095555 + 0.094066700968241684 + 0.094069851287260281 + 0.09407300165115326 + 0.094076152059922771 + 0.094079302513570953 + 0.094082453012099859 + 0.094085603555511599 + 0.094088754143808268 + 0.094091904776991864 + 0.094095055455064636 + 0.094098206178028623 + 0.094101356945885686 + 0.094104507758638239 + 0.094107658616288198 + 0.094110809518837601 + 0.094113960466288726 + 0.094117111458643557 + 0.094120262495904203 + 0.094123413578072565 + 0.094126564705151045 + 0.094129715877141612 + 0.094132867094046266 + 0.094136018355867268 + 0.094139169662606534 + 0.094142321014266242 + 0.094145472410848405 + 0.094148623852355298 + 0.094151775338788782 + 0.094154926870151118 + 0.094158078446444304 + 0.094161230067670465 + 0.094164381733831709 + 0.094167533444930077 + 0.094170685200967677 + 0.094173837001946717 + 0.094176988847869139 + 0.094180140738736984 + 0.094183292674552499 + 0.094186444655317836 + 0.094189596681034965 + 0.094192748751705843 + 0.09419590086733283 + 0.094199053027917853 + 0.094202205233463093 + 0.094205357483970534 + 0.094208509779442326 + 0.094211662119880607 + 0.094214814505287472 + 0.094217966935664851 + 0.094221119411015186 + 0.094224271931340087 + 0.09422742449664212 + 0.094230577106923202 + 0.094233729762185262 + 0.09423688246243056 + 0.094240035207661207 + 0.09424318799787923 + 0.094246340833086639 + 0.094249493713285823 + 0.094252646638478668 + 0.09425579960866716 + 0.094258952623853698 + 0.09426210568404006 + 0.094265258789228576 + 0.094268411939421259 + 0.094271565134620164 + 0.094274718374827482 + 0.094277871660045143 + 0.094281024990275422 + 0.09428417836552036 + 0.094287331785782094 + 0.094290485251062553 + 0.094293638761364013 + 0.094296792316688471 + 0.094299945917038247 + 0.094303099562415074 + 0.094306253252821229 + 0.094309406988258904 + 0.094312560768730083 + 0.094315714594236932 + 0.094318868464781491 + 0.094322022380365772 + 0.094325176340992051 + 0.094328330346662284 + 0.094331484397378748 + 0.094334638493143455 + 0.09433779263395832 + 0.094340946819825813 + 0.09434410105074767 + 0.094347255326726165 + 0.094350409647763395 + 0.094353564013861552 + 0.094356718425022468 + 0.094359872881248488 + 0.094363027382541584 + 0.09436618192890385 + 0.094369336520337591 + 0.094372491156844651 + 0.094375645838427225 + 0.094378800565087462 + 0.094381955336827458 + 0.094385110153649268 + 0.094388265015555001 + 0.09439141992254671 + 0.094394574874626561 + 0.094397729871796718 + 0.094400884914059194 + 0.094404040001416098 + 0.09440719513386954 + 0.094410350311421573 + 0.09441350553407446 + 0.094416660801830199 + 0.094419816114690802 + 0.094422971472658518 + 0.094426126875735483 + 0.094429282323923613 + 0.094432437817225073 + 0.094435593355642139 + 0.094438748939176656 + 0.094441904567830873 + 0.094445060241606898 + 0.094448215960506829 + 0.094451371724532759 + 0.094454527533686897 + 0.094457683387971017 + 0.094460839287387591 + 0.094463995231938533 + 0.094467151221625953 + 0.094470307256452071 + 0.094473463336418845 + 0.094476619461528549 + 0.094479775631783197 + 0.094482931847184759 + 0.094486088107735594 + 0.09448924441343759 + 0.094492400764293161 + 0.094495557160303945 + 0.094498713601472425 + 0.094501870087800699 + 0.094505026619290597 + 0.094508183195944478 + 0.094511339817764398 + 0.094514496484752436 + 0.094517653196910648 + 0.094520809954241211 + 0.094523966756746153 + 0.09452712360442779 + 0.094530280497288038 + 0.094533437435328965 + 0.094536594418552763 + 0.094539751446961653 + 0.094542908520557564 + 0.094546065639342688 + 0.094549222803319163 + 0.094552380012488918 + 0.094555537266854353 + 0.094558694566417259 + 0.09456185191118005 + 0.09456500930114467 + 0.094568166736313283 + 0.09457132421668793 + 0.094574481742270775 + 0.094577639313063844 + 0.0945807969290694 + 0.094583954590289482 + 0.094587112296726159 + 0.094590270048381525 + 0.094593427845257774 + 0.094596585687357085 + 0.094599743574681344 + 0.094602901507232773 + 0.094606059485013577 + 0.094609217508025784 + 0.094612375576271487 + 0.094615533689752784 + 0.094618691848471936 + 0.094621850052430873 + 0.094625008301631675 + 0.094628166596076674 + 0.094631324935767994 + 0.094634483320707397 + 0.094637641750897311 + 0.094640800226339777 + 0.094643958747036863 + 0.094647117312990664 + 0.0946502759242034 + 0.094653434580677112 + 0.094656593282413826 + 0.094659752029415956 + 0.094662910821685292 + 0.094666069659224084 + 0.09466922854203437 + 0.09467238747011833 + 0.094675546443478129 + 0.09467870546211575 + 0.094681864526033568 + 0.094685023635233415 + 0.094688182789717537 + 0.094691341989487948 + 0.094694501234546938 + 0.094697660524896463 + 0.094700819860538674 + 0.094703979241475736 + 0.094707138667709703 + 0.094710298139242782 + 0.094713457656077013 + 0.09471661721821456 + 0.094719776825657478 + 0.09472293647840789 + 0.094726096176467947 + 0.094729255919839883 + 0.094732415708525641 + 0.094735575542527373 + 0.094738735421847228 + 0.094741895346487262 + 0.094745055316449653 + 0.09474821533173651 + 0.094751375392350012 + 0.0947545354982922 + 0.094757695649565224 + 0.094760855846171027 + 0.094764016088112038 + 0.094767176375390227 + 0.094770336708007649 + 0.094773497085966524 + 0.094776657509268919 + 0.094779817977916986 + 0.094782978491912848 + 0.094786139051258503 + 0.094789299655956075 + 0.094792460306007992 + 0.094795621001416142 + 0.09479878174218262 + 0.094801942528309563 + 0.094805103359799067 + 0.094808264236653519 + 0.094811425158874571 + 0.094814586126464789 + 0.094817747139426062 + 0.094820908197760442 + 0.094824069301470221 + 0.09482723045055752 + 0.094830391645024395 + 0.094833552884872899 + 0.094836714170105335 + 0.094839875500723564 + 0.094843036876730041 + 0.094846198298126627 + 0.0948493597649155 + 0.094852521277098811 + 0.094855682834678712 + 0.094858844437657366 + 0.094862006086036663 + 0.094865167779819098 + 0.094868329519006395 + 0.094871491303600938 + 0.094874653133604797 + 0.094877815009020178 + 0.094880976929848967 + 0.094884138896093498 + 0.094887300907755823 + 0.094890462964838065 + 0.094893625067342266 + 0.094896787215270728 + 0.094899949408625381 + 0.094903111647408625 + 0.094906273931622362 + 0.094909436261268673 + 0.094912598636349821 + 0.094915761056868025 + 0.094918923522825133 + 0.094922086034223488 + 0.094925248591064965 + 0.094928411193352089 + 0.094931573841086719 + 0.09493473653427098 + 0.094937899272907064 + 0.094941062056997164 + 0.094944224886543208 + 0.094947387761547444 + 0.094950550682011983 + 0.094953713647939003 + 0.0949568766593306 + 0.094960039716188854 + 0.094963202818515988 + 0.09496636596631404 + 0.094969529159585175 + 0.094972692398331518 + 0.094975855682555219 + 0.094979019012258456 + 0.094982182387442993 + 0.094985345808111549 + 0.094988509274265831 + 0.094991672785908102 + 0.094994836343040373 + 0.094997999945665074 + 0.095001163593784063 + 0.095004327287399534 + 0.095007491026513707 + 0.095010654811128498 + 0.09501381864124632 + 0.095016982516869061 + 0.095020146437998887 + 0.095023310404638142 + 0.095026474416788714 + 0.095029638474452782 + 0.095032802577632622 + 0.095035966726330176 + 0.095039130920547679 + 0.095042295160287296 + 0.095045459445551136 + 0.09504862377634124 + 0.095051788152659716 + 0.095054952574508911 + 0.095058117041890738 + 0.095061281554807475 + 0.095064446113261175 + 0.095067610717253961 + 0.095070775366788027 + 0.095073940061865425 + 0.095077104802488377 + 0.095080269588658978 + 0.095083434420379337 + 0.095086599297651606 + 0.095089764220478018 + 0.095092929188860503 + 0.09509609420280131 + 0.095099259262302602 + 0.09510242436736642 + 0.09510558951799504 + 0.095108754714190447 + 0.095111919955954832 + 0.095115085243290404 + 0.095118250576199145 + 0.095121415954683361 + 0.09512458137874498 + 0.095127746848386346 + 0.095130912363609488 + 0.095134077924416582 + 0.09513724353080974 + 0.095140409182790986 + 0.095143574880362625 + 0.095146740623526821 + 0.095149906412285531 + 0.095153072246641004 + 0.095156238126595363 + 0.095159404052150828 + 0.095162570023309301 + 0.09516573604007314 + 0.09516890210244433 + 0.095172068210425217 + 0.095175234364017619 + 0.095178400563224005 + 0.09518156680804632 + 0.095184733098486796 + 0.095187899434547488 + 0.095191065816230616 + 0.095194232243538068 + 0.09519739871647237 + 0.09520056523503552 + 0.09520373179922946 + 0.095206898409056523 + 0.095210065064518748 + 0.095213231765618453 + 0.095216398512357678 + 0.095219565304738463 + 0.095222732142763014 + 0.095225899026433372 + 0.095229065955752021 + 0.095232232930720709 + 0.095235399951341837 + 0.095238567017617279 + 0.095241734129549477 + 0.095244901287140277 + 0.095248068490392065 + 0.095251235739307008 + 0.095254403033886936 + 0.095257570374134362 + 0.095260737760051117 + 0.095263905191639409 + 0.095267072668901498 + 0.09527024019183955 + 0.09527340776045555 + 0.095276575374751704 + 0.095279743034730122 + 0.09528291074039312 + 0.095286078491742587 + 0.095289246288780882 + 0.095292414131510045 + 0.095295582019932171 + 0.095298749954049453 + 0.095301917933864069 + 0.095305085959378089 + 0.0953082540305938 + 0.095311422147513133 + 0.095314590310138392 + 0.095317758518471699 + 0.095320926772515149 + 0.095324095072270812 + 0.095327263417741004 + 0.095330431808927793 + 0.095333600245833275 + 0.09533676872845967 + 0.095339937256809143 + 0.095343105830883748 + 0.095346274450685636 + 0.095349443116217028 + 0.09535261182748006 + 0.095355780584476815 + 0.095358949387209346 + 0.095362118235680055 + 0.095365287129890911 + 0.095368456069844149 + 0.095371625055541892 + 0.095374794086986181 + 0.095377963164179236 + 0.095381132287123221 + 0.095384301455820275 + 0.095387470670272617 + 0.095390639930482177 + 0.09539380923645141 + 0.095396978588182219 + 0.095400147985676795 + 0.095403317428937304 + 0.095406486917965966 + 0.095409656452764793 + 0.09541282603333609 + 0.095415995659681854 + 0.09541916533180439 + 0.095422335049705709 + 0.095425504813387962 + 0.095428674622853482 + 0.095431844478104239 + 0.09543501437914241 + 0.09543818432597001 + 0.09544135431858948 + 0.095444524357002916 + 0.095447694441212261 + 0.095450864571219762 + 0.095454034747027544 + 0.095457204968637993 + 0.095460375236052941 + 0.095463545549274664 + 0.095466715908305244 + 0.09546988631314697 + 0.095473056763801856 + 0.095476227260272231 + 0.09547939780256004 + 0.095482568390667627 + 0.095485739024596908 + 0.095488909704350283 + 0.095492080429929724 + 0.095495251201337436 + 0.095498422018575585 + 0.095501592881646405 + 0.095504763790551866 + 0.095507934745294232 + 0.095511105745875638 + 0.09551427679229825 + 0.095517447884564247 + 0.09552061902267571 + 0.095523790206634748 + 0.095526961436443639 + 0.09553013271210456 + 0.095533304033619565 + 0.095536475400990736 + 0.095539646814220336 + 0.095542818273310529 + 0.095545989778263507 + 0.095549161329081395 + 0.095552332925766176 + 0.095555504568320251 + 0.095558676256745537 + 0.095561847991044488 + 0.095565019771219006 + 0.095568191597271313 + 0.095571363469203627 + 0.095574535387017989 + 0.095577707350716593 + 0.095580879360301615 + 0.095584051415775251 + 0.095587223517139677 + 0.095590395664396921 + 0.0955935678575493 + 0.095596740096598798 + 0.095599912381547789 + 0.09560308471239802 + 0.095606257089152144 + 0.095609429511812047 + 0.095612601980379824 + 0.095615774494857822 + 0.095618947055248149 + 0.095622119661552887 + 0.095625292313774299 + 0.095628465011914396 + 0.095631637755975482 + 0.095634810545959542 + 0.095637983381869004 + 0.095641156263705729 + 0.095644329191472144 + 0.095647502165170192 + 0.095650675184802025 + 0.09565384825037003 + 0.095657021361876177 + 0.095660194519322714 + 0.09566336772271164 + 0.095666540972045272 + 0.095669714267325678 + 0.095672887608555204 + 0.095676060995735807 + 0.095679234428869817 + 0.095682407907959149 + 0.09568558143300615 + 0.095688755004012874 + 0.095691928620981651 + 0.095695102283914424 + 0.095698275992813595 + 0.095701449747681078 + 0.095704623548519274 + 0.095707797395330058 + 0.095710971288115704 + 0.095714145226878669 + 0.095717319211620674 + 0.095720493242344079 + 0.095723667319051103 + 0.095726841441743843 + 0.095730015610424324 + 0.09573318982509503 + 0.09573636408575785 + 0.095739538392414975 + 0.095742712745068723 + 0.09574588714372112 + 0.095749061588374415 + 0.095752236079030606 + 0.095755410615692108 + 0.095758585198360766 + 0.095761759827039133 + 0.095764934501729113 + 0.095768109222432785 + 0.09577128398915255 + 0.095774458801890505 + 0.095777633660648717 + 0.095780808565429462 + 0.095783983516234822 + 0.09578715851306692 + 0.095790333555928073 + 0.095793508644820391 + 0.095796683779746053 + 0.095799858960707043 + 0.095803034187705707 + 0.095806209460744196 + 0.095809384779824688 + 0.095812560144949308 + 0.095815735556120121 + 0.095818911013339628 + 0.095822086516609534 + 0.095825262065932365 + 0.095828437661310092 + 0.095831613302744881 + 0.095834788990239048 + 0.095837964723794702 + 0.095841140503413955 + 0.095844316329098997 + 0.095847492200852008 + 0.095850668118675111 + 0.095853844082570569 + 0.095857020092540504 + 0.095860196148586901 + 0.095863372250712342 + 0.095866548398918561 + 0.095869724593207958 + 0.095872900833582769 + 0.095876077120044909 + 0.09587925345259668 + 0.095882429831240387 + 0.095885606255978056 + 0.0958887827268117 + 0.09589195924374383 + 0.095895135806776319 + 0.095898312415911499 + 0.095901489071151508 + 0.095904665772498565 + 0.095907842519954684 + 0.095911019313522194 + 0.095914196153203193 + 0.095917373038999845 + 0.095920549970914412 + 0.095923726948948934 + 0.095926903973105576 + 0.095930081043386628 + 0.095933258159794144 + 0.095936435322330496 + 0.095939612530997545 + 0.095942789785797747 + 0.095945967086733114 + 0.095949144433805963 + 0.095952321827018197 + 0.095955499266372132 + 0.095958676751870142 + 0.0959618542835141 + 0.095965031861306255 + 0.095968209485248854 + 0.095971387155344104 + 0.095974564871594045 + 0.095977742634000995 + 0.095980920442566883 + 0.095984098297294138 + 0.095987276198184826 + 0.095990454145241252 + 0.09599363213846529 + 0.09599681017785941 + 0.095999988263425595 + 0.096003166395166165 + 0.096006344573083185 + 0.096009522797178892 + 0.096012701067455311 + 0.09601587938391494 + 0.096019057746559666 + 0.096022236155391669 + 0.096025414610413348 + 0.09602859311162662 + 0.096031771659033885 + 0.096034950252637113 + 0.09603812889243861 + 0.09604130757844058 + 0.096044486310645036 + 0.096047665089054296 + 0.096050843913670539 + 0.096054022784495804 + 0.096057201701532355 + 0.096060380664782424 + 0.096063559674248122 + 0.096066738729931683 + 0.096069917831835244 + 0.096073096979960956 + 0.096076276174310998 + 0.096079455414887577 + 0.096082634701692871 + 0.096085814034729017 + 0.096088993413998278 + 0.096092172839502707 + 0.096095352311244553 + 0.09609853182922605 + 0.096101711393449279 + 0.096104891003916462 + 0.096108070660629777 + 0.096111250363591458 + 0.0961144301128036 + 0.096117609908268342 + 0.096120789749987931 + 0.096123969637964574 + 0.096127149572200449 + 0.096130329552697624 + 0.096133509579458445 + 0.096136689652485036 + 0.096139869771779407 + 0.096143049937344016 + 0.096146230149180861 + 0.096149410407292163 + 0.096152590711680058 + 0.096155771062346782 + 0.096158951459294525 + 0.096162131902525538 + 0.096165312392041791 + 0.096168492927845572 + 0.096171673509939201 + 0.096174854138324689 + 0.096178034813004215 + 0.096181215533980083 + 0.096184396301254374 + 0.096187577114829281 + 0.096190757974707039 + 0.096193938880889743 + 0.096197119833379668 + 0.096200300832178925 + 0.096203481877289845 + 0.09620666296871444 + 0.09620984410645475 + 0.09621302529051344 + 0.096216206520892272 + 0.096219387797593633 + 0.096222569120619508 + 0.096225750489972284 + 0.096228931905654055 + 0.096232113367667071 + 0.096235294876013372 + 0.096238476430695261 + 0.096241658031715041 + 0.096244839679074559 + 0.096248021372776327 + 0.09625120311282237 + 0.09625438489921484 + 0.096257566731956012 + 0.096260748611048039 + 0.096263930536493167 + 0.096267112508293465 + 0.096270294526451181 + 0.096273476590968535 + 0.096276658701847637 + 0.096279840859090762 + 0.096283023062699952 + 0.096286205312677536 + 0.09628938760902557 + 0.096292569951746398 + 0.096295752340842089 + 0.096298934776314946 + 0.096302117258167064 + 0.096305299786400608 + 0.09630848236101773 + 0.096311664982020817 + 0.096314847649411783 + 0.09631803036319303 + 0.096321213123366764 + 0.096324395929934997 + 0.096327578782900047 + 0.096330761682263982 + 0.096333944628029133 + 0.09633712762019768 + 0.096340310658771702 + 0.096343493743753394 + 0.096346676875145074 + 0.09634986005294878 + 0.096353043277166817 + 0.096356226547801224 + 0.096359409864854445 + 0.096362593228328436 + 0.0963657766382255 + 0.096368960094547762 + 0.096372143597297483 + 0.09637532714647673 + 0.096378510742087906 + 0.096381694384132965 + 0.096384878072614352 + 0.096388061807533995 + 0.096391245588894253 + 0.096394429416697236 + 0.096397613290945164 + 0.09640079721164023 + 0.096403981178784653 + 0.09640716519238067 + 0.096410349252430305 + 0.096413533358935821 + 0.096416717511899411 + 0.096419901711323405 + 0.096423085957209775 + 0.096426270249560894 + 0.09642945458837883 + 0.096432638973665774 + 0.096435823405424156 + 0.096439007883655864 + 0.096442192408363214 + 0.096445376979548303 + 0.096448561597213489 + 0.096451746261360938 + 0.096454930971992828 + 0.096458115729111171 + 0.096461300532718425 + 0.096464485382816559 + 0.096467670279408058 + 0.096470855222494836 + 0.096474040212079226 + 0.096477225248163309 + 0.096480410330749458 + 0.096483595459839602 + 0.09648678063543624 + 0.096489965857541368 + 0.096493151126157223 + 0.096496336441286079 + 0.096499521802930102 + 0.096502707211091304 + 0.096505892665772183 + 0.096509078166974821 + 0.096512263714701202 + 0.096515449308953782 + 0.096518634949734589 + 0.096521820637045994 + 0.096525006370890079 + 0.096528192151269121 + 0.09653137797818527 + 0.096534563851640567 + 0.096537749771637441 + 0.096540935738178055 + 0.096544121751264464 + 0.096547307810899 + 0.096550493917083799 + 0.09655368006982111 + 0.096556866269113112 + 0.096560052514962011 + 0.096563238807369875 + 0.096566425146339022 + 0.096569611531871824 + 0.096572797963970156 + 0.096575984442636334 + 0.096579170967872607 + 0.096582357539681099 + 0.096585544158064141 + 0.096588730823023813 + 0.096591917534562269 + 0.096595104292681852 + 0.09659829109738477 + 0.096601477948673076 + 0.096604664846549129 + 0.096607851791014887 + 0.096611038782072889 + 0.096614225819725091 + 0.096617412903973646 + 0.09662060003482098 + 0.096623787212269246 + 0.096626974436320429 + 0.096630161706976941 + 0.096633349024240867 + 0.096636536388114549 + 0.096639723798600113 + 0.096642911255699696 + 0.096646098759415683 + 0.096649286309749879 + 0.096652473906705047 + 0.096655661550282906 + 0.096658849240485942 + 0.096662036977316179 + 0.096665224760776061 + 0.096668412590867531 + 0.096671600467592989 + 0.096674788390954419 + 0.096677976360954251 + 0.096681164377594539 + 0.096684352440877502 + 0.096687540550805376 + 0.096690728707380533 + 0.096693916910604777 + 0.096697105160480731 + 0.096700293457010325 + 0.096703481800195917 + 0.096706670190039534 + 0.09670985862654366 + 0.096713047109710237 + 0.096716235639541542 + 0.096719424216039837 + 0.096722612839207175 + 0.096725801509046069 + 0.096728990225558475 + 0.096732178988746656 + 0.096735367798612776 + 0.096738556655159222 + 0.096741745558387882 + 0.096744934508301308 + 0.096748123504901459 + 0.09675131254819061 + 0.096754501638170926 + 0.096757690774844807 + 0.096760879958214363 + 0.096764069188281579 + 0.09676725846504898 + 0.096770447788518524 + 0.096773637158692666 + 0.096776826575573405 + 0.096780016039163058 + 0.096783205549463763 + 0.096786395106477713 + 0.096789584710207363 + 0.09679277436065456 + 0.096795964057821662 + 0.096799153801711002 + 0.09680234359232455 + 0.096805533429664734 + 0.096808723313733691 + 0.096811913244533615 + 0.096815103222066642 + 0.096818293246335105 + 0.09682148331734107 + 0.096824673435086966 + 0.096827863599574751 + 0.096831053810806783 + 0.09683424406878538 + 0.096837434373512415 + 0.096840624724990415 + 0.096843815123221447 + 0.096847005568207745 + 0.096850196059951613 + 0.096853386598455216 + 0.096856577183720455 + 0.096859767815750078 + 0.096862958494545931 + 0.096866149220110276 + 0.096869339992445375 + 0.096872530811553489 + 0.096875721677436785 + 0.096878912590097482 + 0.09688210354953769 + 0.096885294555759852 + 0.096888485608765867 + 0.096891676708558291 + 0.096894867855138955 + 0.096898059048510329 + 0.09690125028867462 + 0.096904441575634104 + 0.096907632909390723 + 0.096910824289946962 + 0.096914015717304861 + 0.09691720719146675 + 0.096920398712434852 + 0.096923590280211164 + 0.0969267818947981 + 0.09692997355619791 + 0.09693316526441266 + 0.096936357019444641 + 0.096939548821296018 + 0.096942740669969121 + 0.096945932565466172 + 0.096949124507789197 + 0.096952316496940485 + 0.096955508532922355 + 0.096958700615736887 + 0.096961892745386358 + 0.096965084921873113 + 0.096968277145199067 + 0.096971469415366759 + 0.096974661732378162 + 0.096977854096235716 + 0.096981046506941407 + 0.096984238964497593 + 0.096987431468906399 + 0.096990624020170169 + 0.096993816618290915 + 0.096997009263271108 + 0.097000201955112858 + 0.097003394693818357 + 0.097006587479389714 + 0.097009780311829344 + 0.097012973191139426 + 0.097016166117322056 + 0.097019359090379537 + 0.097022552110314145 + 0.097025745177127962 + 0.097028938290823333 + 0.097032131451402465 + 0.097035324658867439 + 0.097038517913220518 + 0.097041711214464116 + 0.097044904562600301 + 0.097048097957631224 + 0.097051291399559161 + 0.097054484888386486 + 0.097057678424115237 + 0.097060872006747567 + 0.097064065636285946 + 0.09706725931273244 + 0.09707045303608916 + 0.097073646806358563 + 0.09707684062354266 + 0.097080034487643865 + 0.097083228398664317 + 0.097086422356606181 + 0.097089616361471787 + 0.097092810413263189 + 0.097096004511982803 + 0.097099198657632613 + 0.097102392850215172 + 0.097105587089732437 + 0.097108781376186559 + 0.097111975709580106 + 0.097115170089915021 + 0.097118364517193648 + 0.097121558991418167 + 0.097124753512590756 + 0.097127948080713719 + 0.097131142695789249 + 0.097134337357819442 + 0.097137532066806809 + 0.097140726822753293 + 0.097143921625661253 + 0.097147116475533007 + 0.097150311372370471 + 0.097153506316176266 + 0.097156701306952281 + 0.097159896344700861 + 0.097163091429424267 + 0.097166286561124721 + 0.097169481739804428 + 0.097172676965465568 + 0.097175872238110389 + 0.097179067557741139 + 0.097182262924359969 + 0.097185458337969252 + 0.097188653798571153 + 0.097191849306167852 + 0.097195044860761623 + 0.097198240462354604 + 0.097201436110949169 + 0.097204631806547259 + 0.097207827549151471 + 0.097211023338763872 + 0.097214219175386599 + 0.097217415059021983 + 0.097220610989672274 + 0.09722380696733951 + 0.097227002992026176 + 0.097230199063734257 + 0.097233395182466237 + 0.097236591348224127 + 0.097239787561010205 + 0.097242983820826759 + 0.09724618012767601 + 0.097249376481560235 + 0.097252572882481472 + 0.097255769330442152 + 0.097258965825444271 + 0.097262162367490287 + 0.097265358956582421 + 0.097268555592722739 + 0.097271752275913545 + 0.097274949006157199 + 0.0972781457834557 + 0.09728134260781128 + 0.097284539479226495 + 0.097287736397703273 + 0.097290933363243931 + 0.097294130375850552 + 0.097297327435525702 + 0.097300524542271435 + 0.097303721696089793 + 0.097306918896983272 + 0.097310116144953995 + 0.097313313440004184 + 0.097316510782136073 + 0.097319708171351979 + 0.097322905607653998 + 0.097326103091044447 + 0.097329300621525533 + 0.097332498199099574 + 0.097335695823768567 + 0.097338893495534956 + 0.097342091214400989 + 0.097345288980368677 + 0.097348486793440506 + 0.097351684653618556 + 0.097354882560905187 + 0.097358080515302453 + 0.097361278516812658 + 0.097364476565438174 + 0.097367674661181014 + 0.097370872804043496 + 0.09737407099402795 + 0.09737726923113646 + 0.097380467515371327 + 0.097383665846734913 + 0.097386864225229186 + 0.097390062650856479 + 0.097393261123619207 + 0.097396459643519409 + 0.097399658210559306 + 0.097402856824741327 + 0.097406055486067483 + 0.097409254194540204 + 0.097412452950161557 + 0.097415651752933985 + 0.097418850602859347 + 0.097422049499940155 + 0.097425248444178728 + 0.097428447435577062 + 0.097431646474137643 + 0.097434845559862454 + 0.097438044692753953 + 0.097441243872814151 + 0.097444443100045436 + 0.097447642374450111 + 0.097450841696030271 + 0.097454041064788152 + 0.097457240480726071 + 0.097460439943846219 + 0.097463639454150777 + 0.097466839011642159 + 0.097470038616322446 + 0.097473238268193887 + 0.097476437967258772 + 0.097479637713519307 + 0.097482837506977768 + 0.097486037347636459 + 0.097489237235497364 + 0.097492437170562926 + 0.097495637152835393 + 0.097498837182316916 + 0.097502037259009772 + 0.097505237382916346 + 0.097508437554038499 + 0.09751163777237884 + 0.097514838037939339 + 0.097518038350722494 + 0.097521238710730401 + 0.097524439117965267 + 0.097527639572429381 + 0.097530840074124922 + 0.097534040623054277 + 0.097537241219219514 + 0.097540441862623034 + 0.097543642553267043 + 0.097546843291153609 + 0.097550044076285203 + 0.097553244908663919 + 0.097556445788292007 + 0.097559646715171741 + 0.097562847689305482 + 0.097566048710695227 + 0.097569249779343475 + 0.097572450895252225 + 0.097575652058423945 + 0.097578853268860677 + 0.097582054526564765 + 0.097585255831538417 + 0.097588457183783839 + 0.097591658583303334 + 0.097594860030099262 + 0.097598061524173677 + 0.097601263065528909 + 0.097604464654167195 + 0.097607666290090711 + 0.097610867973301832 + 0.097614069703802639 + 0.097617271481595436 + 0.09762047330668254 + 0.09762367517906613 + 0.097626877098748496 + 0.097630079065731873 + 0.097633281080018355 + 0.097636483141610414 + 0.09763968525051013 + 0.097642887406719808 + 0.097646089610241779 + 0.097649291861078027 + 0.097652494159231162 + 0.09765569650470321 + 0.097658898897496418 + 0.097662101337613036 + 0.097665303825055408 + 0.097668506359825658 + 0.097671708941926061 + 0.097674911571358894 + 0.097678114248126433 + 0.097681316972230828 + 0.097684519743674342 + 0.097687722562459375 + 0.097690925428588038 + 0.09769412834206255 + 0.097697331302885285 + 0.097700534311058296 + 0.097703737366584012 + 0.097706940469464515 + 0.097710143619702317 + 0.097713346817299457 + 0.09771655006225817 + 0.097719753354580705 + 0.097722956694269406 + 0.097726160081326549 + 0.097729363515754272 + 0.097732566997554768 + 0.097735770526730548 + 0.097738974103283596 + 0.097742177727216245 + 0.097745381398530826 + 0.097748585117229406 + 0.097751788883314469 + 0.097754992696788223 + 0.097758196557652652 + 0.097761400465910239 + 0.09776460442156315 + 0.097767808424613731 + 0.097771012475064256 + 0.097774216572916753 + 0.097777420718173705 + 0.09778062491083718 + 0.097783829150909538 + 0.097787033438392956 + 0.097790237773289851 + 0.097793442155602303 + 0.097796646585332631 + 0.097799851062483067 + 0.097803055587055959 + 0.097806260159053388 + 0.097809464778477684 + 0.097812669445331096 + 0.097815874159615887 + 0.097819078921334374 + 0.097822283730488638 + 0.097825488587081066 + 0.097828693491113908 + 0.097831898442589368 + 0.097835103441509641 + 0.097838308487877279 + 0.097841513581694184 + 0.097844718722962576 + 0.09784792391168512 + 0.097851129147863716 + 0.097854334431500725 + 0.097857539762598325 + 0.097860745141158959 + 0.097863950567184735 + 0.097867156040677875 + 0.097870361561640667 + 0.097873567130075514 + 0.097876772745984553 + 0.097879978409369947 + 0.097883184120234112 + 0.097886389878579116 + 0.097889595684407374 + 0.097892801537721189 + 0.097896007438522614 + 0.097899213386814024 + 0.097902419382597708 + 0.097905625425875858 + 0.097908831516650752 + 0.09791203765492458 + 0.097915243840699717 + 0.097918450073978328 + 0.097921656354762715 + 0.097924862683055142 + 0.097928069058857842 + 0.097931275482173064 + 0.097934481953003125 + 0.09793768847135019 + 0.097940895037216605 + 0.097944101650604479 + 0.097947308311516296 + 0.097950515019954179 + 0.097953721775920349 + 0.097956928579417069 + 0.097960135430446779 + 0.097963342329011466 + 0.097966549275113571 + 0.097969756268755329 + 0.097972963309938946 + 0.097976170398666684 + 0.097979377534940806 + 0.097982584718763699 + 0.097985791950137444 + 0.097988999229064386 + 0.097992206555546732 + 0.097995413929586772 + 0.097998621351186796 + 0.098001828820349093 + 0.098005036337075843 + 0.09800824390136928 + 0.098011451513231762 + 0.098014659172665566 + 0.098017866879672788 + 0.098021074634255786 + 0.098024282436416879 + 0.098027490286158245 + 0.098030698183482187 + 0.098033906128390941 + 0.098037114120886726 + 0.098040322160971985 + 0.0980435302486488 + 0.098046738383919474 + 0.098049946566786284 + 0.09805315479725138 + 0.098056363075317329 + 0.098059571400986104 + 0.098062779774260048 + 0.09806598819514134 + 0.098069196663632535 + 0.098072405179735547 + 0.098075613743452833 + 0.098078822354786599 + 0.098082031013739177 + 0.0980852397203128 + 0.098088448474509746 + 0.098091657276332012 + 0.098094866125782276 + 0.098098075022862441 + 0.098101283967575198 + 0.098104492959922421 + 0.098107701999906524 + 0.098110911087529729 + 0.098114120222794407 + 0.098117329405702586 + 0.098120538636256902 + 0.098123747914459297 + 0.098126957240312146 + 0.098130166613817696 + 0.09813337603497832 + 0.09813658550379617 + 0.098139795020273521 + 0.098143004584412621 + 0.098146214196215845 + 0.098149423855685244 + 0.09815263356282336 + 0.098155843317632288 + 0.098159053120114317 + 0.098162262970271766 + 0.098165472868106812 + 0.098168682813621816 + 0.098171892806818928 + 0.098175102847700535 + 0.098178312936268844 + 0.098181523072526145 + 0.09818473325647474 + 0.098187943488116797 + 0.098191153767454631 + 0.098194364094490616 + 0.098197574469226903 + 0.098200784891665616 + 0.098203995361809265 + 0.098207205879660156 + 0.098210416445220355 + 0.09821362705849225 + 0.098216837719478048 + 0.098220048428180023 + 0.098223259184600467 + 0.098226469988741669 + 0.098229680840605932 + 0.098232891740195477 + 0.098236102687512483 + 0.098239313682559323 + 0.098242524725338218 + 0.098245735815851623 + 0.098248946954101524 + 0.098252158140090348 + 0.0982553693738204 + 0.098258580655293887 + 0.098261791984512986 + 0.098265003361480086 + 0.098268214786197433 + 0.098271426258667374 + 0.098274637778892018 + 0.09827784934687385 + 0.098281060962614894 + 0.098284272626117691 + 0.098287484337384282 + 0.098290696096417093 + 0.098293907903218181 + 0.098297119757790041 + 0.098300331660134951 + 0.09830354361025509 + 0.098306755608152552 + 0.09830996765383003 + 0.098313179747289425 + 0.098316391888533181 + 0.098319604077563627 + 0.098322816314382888 + 0.098326028598993323 + 0.098329240931397208 + 0.098332453311596651 + 0.09833566573959418 + 0.098338878215391931 + 0.098342090738992319 + 0.098345303310397356 + 0.09834851592960947 + 0.09835172859663098 + 0.098354941311464023 + 0.098358154074111165 + 0.098361366884574419 + 0.098364579742855965 + 0.098367792648958327 + 0.098371005602883643 + 0.098374218604634217 + 0.098377431654212394 + 0.098380644751620408 + 0.098383857896860466 + 0.098387071089934913 + 0.09839028433084604 + 0.098393497619596038 + 0.098396710956187294 + 0.098399924340621947 + 0.098403137772902452 + 0.098406351253030946 + 0.09840956478100972 + 0.098412778356841063 + 0.098415991980527348 + 0.098419205652070768 + 0.09842241937147353 + 0.09842563313873802 + 0.098428846953866542 + 0.098432060816861233 + 0.098435274727724481 + 0.09843848868645852 + 0.098441702693065708 + 0.098444916747548183 + 0.098448130849908291 + 0.098451345000148377 + 0.09845455919827073 + 0.098457773444277377 + 0.098460987738170955 + 0.098464202079953517 + 0.098467416469627353 + 0.098470630907194878 + 0.098473845392658202 + 0.098477059926019642 + 0.098480274507281571 + 0.098483489136446167 + 0.098486703813515875 + 0.098489918538492691 + 0.098493133311379225 + 0.098496348132177475 + 0.098499563000889828 + 0.098502777917518783 + 0.098505992882066254 + 0.098509207894534601 + 0.098512422954926362 + 0.09851563806324358 + 0.098518853219488542 + 0.098522068423663609 + 0.098525283675771153 + 0.098528498975813228 + 0.098531714323792347 + 0.098534929719710604 + 0.098538145163570345 + 0.098541360655373847 + 0.098544576195123343 + 0.098547791782821359 + 0.098551007418469963 + 0.098554223102071389 + 0.098557438833628025 + 0.098560654613142201 + 0.098563870440616014 + 0.098567086316051961 + 0.098570302239452234 + 0.098573518210819097 + 0.098576734230154839 + 0.098579950297461791 + 0.098583166412742174 + 0.098586382575998346 + 0.098589598787232502 + 0.098592815046447013 + 0.09859603135364417 + 0.098599247708826027 + 0.098602464111995178 + 0.098605680563153789 + 0.098608897062304135 + 0.098612113609448548 + 0.09861533020458918 + 0.098618546847728403 + 0.098621763538868493 + 0.098624980278011823 + 0.098628197065160614 + 0.098631413900317169 + 0.098634630783483626 + 0.098637847714662455 + 0.098641064693855973 + 0.098644281721066193 + 0.098647498796295668 + 0.09865071591954673 + 0.098653933090821377 + 0.098657150310122163 + 0.098660367577451197 + 0.098663584892810866 + 0.098666802256203445 + 0.098670019667631087 + 0.09867323712709633 + 0.098676454634601313 + 0.098679672190148282 + 0.098682889793739625 + 0.098686107445377591 + 0.09868932514506451 + 0.098692542892802618 + 0.098695760688594147 + 0.098698978532441639 + 0.098702196424347077 + 0.098705414364312793 + 0.098708632352341216 + 0.098711850388434705 + 0.098715068472595272 + 0.098718286604825345 + 0.098721504785127201 + 0.098724723013503379 + 0.098727941289955698 + 0.098731159614486835 + 0.098734377987098873 + 0.098737596407794156 + 0.098740814876575086 + 0.098744033393443745 + 0.09874725195840256 + 0.098750470571453849 + 0.09875368923259982 + 0.098756907941842748 + 0.098760126699184977 + 0.098763345504628813 + 0.098766564358176587 + 0.098769783259830421 + 0.098773002209592869 + 0.098776221207465903 + 0.098779440253452186 + 0.098782659347553509 + 0.098785878489772688 + 0.098789097680111765 + 0.098792316918573056 + 0.098795536205158851 + 0.098798755539871469 + 0.098801974922713171 + 0.098805194353686135 + 0.098808413832792999 + 0.098811633360035636 + 0.098814852935416808 + 0.098818072558938291 + 0.098821292230602806 + 0.098824511950412322 + 0.098827731718369421 + 0.098830951534476227 + 0.098834171398735085 + 0.098837391311148146 + 0.098840611271718004 + 0.098843831280446715 + 0.098847051337336567 + 0.098850271442389961 + 0.098853491595609175 + 0.098856711796996635 + 0.098859932046554355 + 0.098863152344284763 + 0.098866372690190163 + 0.098869593084273011 + 0.09887281352653518 + 0.098876034016979308 + 0.098879254555607698 + 0.09888247514242253 + 0.09888569577742605 + 0.098888916460620813 + 0.098892137192008747 + 0.098895357971592393 + 0.098898578799374068 + 0.09890179967535602 + 0.098905020599540455 + 0.098908241571929734 + 0.098911462592526159 + 0.098914683661332048 + 0.098917904778349608 + 0.098921125943581281 + 0.098924347157029427 + 0.09892756841869603 + 0.098930789728583504 + 0.098934011086694432 + 0.098937232493030755 + 0.098940453947594945 + 0.098943675450389221 + 0.098946897001415943 + 0.098950118600677442 + 0.098953340248175981 + 0.098956561943913737 + 0.098959783687893252 + 0.098963005480116661 + 0.098966227320586297 + 0.09896944920930438 + 0.098972671146273422 + 0.098975893131495588 + 0.09897911516497318 + 0.098982337246708393 + 0.098985559376703683 + 0.09898878155496138 + 0.098992003781483609 + 0.098995226056272881 + 0.098998448379331264 + 0.09900167075066138 + 0.099004893170265174 + 0.099008115638145155 + 0.09901133815430363 + 0.099014560718742733 + 0.09901778333146502 + 0.099021005992472516 + 0.099024228701767789 + 0.099027451459352961 + 0.099030674265230462 + 0.0990338971194024 + 0.0990371200218714 + 0.099040342972639361 + 0.099043565971708825 + 0.099046789019082149 + 0.099050012114761457 + 0.099053235258749317 + 0.099056458451047782 + 0.099059681691659157 + 0.099062904980585939 + 0.099066128317830099 + 0.099069351703394426 + 0.099072575137280822 + 0.099075798619491728 + 0.099079022150029519 + 0.099082245728896304 + 0.099085469356094663 + 0.099088693031626637 + 0.099091916755494669 + 0.099095140527701159 + 0.099098364348248286 + 0.099101588217138187 + 0.099104812134373471 + 0.099108036099956262 + 0.099111260113888974 + 0.099114484176173842 + 0.0991177082868131 + 0.099120932445809398 + 0.099124156653164569 + 0.099127380908881207 + 0.099130605212961534 + 0.099133829565407922 + 0.099137053966222632 + 0.099140278415407956 + 0.099143502912966308 + 0.099146727458899728 + 0.099149952053210741 + 0.099153176695901679 + 0.099156401386974791 + 0.099159626126432351 + 0.099162850914276679 + 0.099166075750510133 + 0.099169300635135002 + 0.099172525568153536 + 0.099175750549568092 + 0.09917897557938106 + 0.099182200657594657 + 0.099185425784210995 + 0.09918865095923271 + 0.099191876182662092 + 0.099195101454501222 + 0.099198326774752613 + 0.099201552143418498 + 0.099204777560501153 + 0.099208003026002967 + 0.099211228539926144 + 0.099214454102273031 + 0.099217679713046014 + 0.099220905372247314 + 0.099224131079879305 + 0.099227356835944344 + 0.099230582640444626 + 0.099233808493382425 + 0.099237034394760254 + 0.099240260344580195 + 0.099243486342844703 + 0.099246712389556124 + 0.09924993848471661 + 0.099253164628328547 + 0.09925639082039435 + 0.099259617060916197 + 0.099262843349896449 + 0.099266069687337435 + 0.099269296073241531 + 0.099272522507610816 + 0.09927574899044786 + 0.099278975521754853 + 0.099282202101534003 + 0.099285428729787892 + 0.099288655406518586 + 0.09929188213172857 + 0.099295108905420135 + 0.099298335727595458 + 0.099301562598257009 + 0.099304789517407024 + 0.099308016485047793 + 0.099311243501181687 + 0.099314470565811039 + 0.09931769767893793 + 0.099320924840565109 + 0.0993241520506946 + 0.099327379309328709 + 0.099330606616469835 + 0.099333833972120242 + 0.099337061376282357 + 0.099340288828958401 + 0.099343516330150622 + 0.099346743879861393 + 0.09934997147809313 + 0.099353199124847982 + 0.099356426820128504 + 0.099359654563936695 + 0.099362882356275148 + 0.099366110197146015 + 0.099369338086551642 + 0.099372566024494485 + 0.099375794010976598 + 0.099379022046000576 + 0.099382250129568417 + 0.099385478261682883 + 0.099388706442345751 + 0.099391934671559948 + 0.099395162949327279 + 0.099398391275650186 + 0.099401619650531195 + 0.09940484807397236 + 0.099408076545976276 + 0.0994113050665449 + 0.099414533635680868 + 0.099417762253386485 + 0.099420990919663832 + 0.099424219634515379 + 0.099427448397943513 + 0.099430677209950372 + 0.099433906070538342 + 0.099437134979709976 + 0.099440363937467247 + 0.099443592943812692 + 0.099446821998748478 + 0.099450051102277018 + 0.099453280254400631 + 0.099456509455121689 + 0.099459738704442344 + 0.09946296800236519 + 0.09946619734889231 + 0.099469426744025924 + 0.099472656187768752 + 0.099475885680122778 + 0.099479115221090444 + 0.099482344810674112 + 0.099485574448876055 + 0.099488804135698508 + 0.099492033871143928 + 0.099495263655214536 + 0.099498493487912842 + 0.099501723369240833 + 0.099504953299201185 + 0.099508183277796022 + 0.099511413305027677 + 0.099514643380898479 + 0.099517873505410789 + 0.099521103678566966 + 0.099524333900369286 + 0.09952756417082001 + 0.099530794489921567 + 0.099534024857676179 + 0.099537255274086259 + 0.099540485739154014 + 0.099543716252881928 + 0.099546946815272278 + 0.099550177426327352 + 0.099553408086049483 + 0.099556638794440891 + 0.099559869551504185 + 0.099563100357241308 + 0.099566331211654924 + 0.099569562114747087 + 0.099572793066520351 + 0.099576024066976923 + 0.099579255116119078 + 0.099582486213949259 + 0.099585717360469769 + 0.099588948555682941 + 0.09959217979959098 + 0.099595411092196329 + 0.099598642433501236 + 0.099601873823508144 + 0.09960510526221926 + 0.099608336749637053 + 0.099611568285763716 + 0.099614799870601553 + 0.099618031504152965 + 0.099621263186420381 + 0.099624494917405895 + 0.09962772669711184 + 0.099630958525540977 + 0.099634190402695083 + 0.099637422328576752 + 0.099640654303188372 + 0.099643886326532038 + 0.09964711839861029 + 0.099650350519425362 + 0.099653582688979656 + 0.099656814907275459 + 0.099660047174314953 + 0.099663279490100731 + 0.099666511854634959 + 0.099669744267919955 + 0.09967297672995816 + 0.099676209240751754 + 0.099679441800303165 + 0.099682674408614724 + 0.099685907065688778 + 0.099689139771527588 + 0.099692372526133569 + 0.099695605329508927 + 0.099698838181656119 + 0.099702071082577282 + 0.099705304032275024 + 0.099708537030751568 + 0.099711770078009146 + 0.099715003174050007 + 0.099718236318876829 + 0.099721469512491681 + 0.099724702754896977 + 0.09972793604609502 + 0.0997311693860881 + 0.099734402774878675 + 0.099737636212468922 + 0.099740869698861381 + 0.099744103234058148 + 0.099747336818061749 + 0.099750570450874335 + 0.099753804132498375 + 0.099757037862936132 + 0.099760271642189979 + 0.099763505470262262 + 0.099766739347155159 + 0.099769973272871293 + 0.099773207247412746 + 0.099776441270782057 + 0.099779675342981239 + 0.09978290946401297 + 0.099786143633879498 + 0.099789377852583003 + 0.099792612120125981 + 0.099795846436510571 + 0.099799080801739368 + 0.099802315215814522 + 0.09980554967873842 + 0.099808784190513367 + 0.099812018751141804 + 0.099815253360625994 + 0.099818488018968241 + 0.099821722726170889 + 0.099824957482236285 + 0.09982819228716687 + 0.099831427140964851 + 0.099834662043632505 + 0.099837896995172343 + 0.099841131995586502 + 0.099844367044877563 + 0.099847602143047706 + 0.099850837290099262 + 0.099854072486034631 + 0.099857307730856076 + 0.099860543024565943 + 0.099863778367166617 + 0.099867013758660597 + 0.099870249199049715 + 0.0998734846883369 + 0.099876720226524093 + 0.099879955813613822 + 0.099883191449608388 + 0.099886427134510056 + 0.09988966286832128 + 0.099892898651044351 + 0.099896134482681462 + 0.099899370363235124 + 0.099902606292707613 + 0.099905842271101261 + 0.099909078298418413 + 0.099912314374661609 + 0.09991555049983282 + 0.099918786673934737 + 0.099922022896969262 + 0.099925259168939226 + 0.099928495489846628 + 0.099931731859693937 + 0.099934968278483638 + 0.099938204746217757 + 0.099941441262898806 + 0.09994467782852913 + 0.099947914443111074 + 0.099951151106646915 + 0.099954387819139082 + 0.099957624580589891 + 0.099960861391001493 + 0.099964098250376554 + 0.099967335158717086 + 0.099970572116025863 + 0.099973809122304733 + 0.099977046177556331 + 0.099980283281782989 + 0.099983520434986914 + 0.099986757637170548 + 0.099989994888336292 + 0.099993232188486256 + 0.09999646953762302 + 0.099999706935748889 + 0.10000294438286607 + 0.10000618187897703 + 0.10000941942408417 + 0.10001265701818958 + 0.1000158946612958 + 0.10001913235340512 + 0.10002237009451993 + 0.10002560788464261 + 0.10002884572377535 + 0.10003208361192067 + 0.10003532154908064 + 0.10003855953525792 + 0.10004179757045464 + 0.10004503565467336 + 0.1000482737879162 + 0.10005151197018555 + 0.10005475020148388 + 0.10005798848181342 + 0.10006122681117655 + 0.10006446518957561 + 0.10006770361701296 + 0.10007094209349097 + 0.10007418061901194 + 0.10007741919357808 + 0.10008065781719196 + 0.10008389648985579 + 0.10008713521157216 + 0.10009037398234309 + 0.10009361280217104 + 0.10009685167105847 + 0.1001000905890076 + 0.1001033295560208 + 0.10010656857210051 + 0.10010980763724887 + 0.1001130467514683 + 0.10011628591476136 + 0.10011952512713024 + 0.10012276438857709 + 0.1001260036991047 + 0.10012924305871496 + 0.10013248246741056 + 0.10013572192519374 + 0.10013896143206667 + 0.10014220098803199 + 0.1001454405930918 + 0.10014868024724864 + 0.10015191995050474 + 0.10015515970286257 + 0.10015839950432423 + 0.10016163935489243 + 0.10016487925456914 + 0.10016811920335697 + 0.10017135920125826 + 0.1001745992482752 + 0.1001778393444102 + 0.10018107948966569 + 0.10018431968404401 + 0.10018755992754746 + 0.10019080022017832 + 0.1001940405619391 + 0.10019728095283202 + 0.10020052139285948 + 0.10020376188202389 + 0.1002070024203275 + 0.1002102430077727 + 0.10021348364436188 + 0.10021672433009732 + 0.10021996506498129 + 0.10022320584901644 + 0.1002264466822049 + 0.100229687564549 + 0.10023292849605119 + 0.10023616947671384 + 0.10023941050653913 + 0.1002426515855296 + 0.10024589271368751 + 0.1002491338910152 + 0.10025237511751525 + 0.10025561639318958 + 0.10025885771804093 + 0.10026209909207144 + 0.10026534051528346 + 0.10026858198767946 + 0.10027182350926191 + 0.10027506508003284 + 0.10027830669999471 + 0.10028154836915003 + 0.10028479008750089 + 0.10028803185504997 + 0.10029127367179937 + 0.10029451553775172 + 0.10029775745290896 + 0.1003009994172739 + 0.10030424143084836 + 0.10030748349363511 + 0.10031072560563654 + 0.10031396776685471 + 0.10031720997729229 + 0.1003204522369513 + 0.10032369454583441 + 0.10032693690394368 + 0.10033017931128171 + 0.10033342176785071 + 0.10033666427365309 + 0.10033990682869132 + 0.10034314943296754 + 0.1003463920864842 + 0.10034963478924375 + 0.1003528775412484 + 0.10035612034250056 + 0.10035936319300259 + 0.10036260609275686 + 0.10036584904176581 + 0.10036909204003154 + 0.10037233508755672 + 0.10037557818434359 + 0.1003788213303943 + 0.10038206452571155 + 0.10038530777029737 + 0.1003885510641544 + 0.10039179440728489 + 0.10039503779969122 + 0.10039828124137566 + 0.10040152473234054 + 0.10040476827258843 + 0.10040801186212153 + 0.10041125550094228 + 0.10041449918905287 + 0.10041774292645597 + 0.10042098671315362 + 0.10042423054914829 + 0.10042747443444239 + 0.10043071836903823 + 0.10043396235293821 + 0.10043720638614471 + 0.10044045046866001 + 0.10044369460048647 + 0.1004469387816266 + 0.10045018301208263 + 0.1004534272918569 + 0.10045667162095182 + 0.10045991599936979 + 0.10046316042711299 + 0.10046640490418407 + 0.10046964943058513 + 0.10047289400631869 + 0.1004761386313871 + 0.10047938330579267 + 0.10048262802953777 + 0.1004858728026248 + 0.10048911762505595 + 0.10049236249683383 + 0.10049560741796064 + 0.10049885238843879 + 0.10050209740827079 + 0.10050534247745867 + 0.1005085875960051 + 0.10051183276391226 + 0.10051507798118257 + 0.10051832324781851 + 0.10052156856382231 + 0.10052481392919638 + 0.10052805934394292 + 0.10053130480806458 + 0.1005345503215635 + 0.10053779588444214 + 0.1005410414967029 + 0.10054428715834811 + 0.10054753286938015 + 0.10055077862980118 + 0.1005540244396138 + 0.10055727029882047 + 0.10056051620742318 + 0.10056376216542461 + 0.10056700817282706 + 0.10057025422963273 + 0.10057350033584435 + 0.10057674649146386 + 0.10057999269649388 + 0.10058323895093675 + 0.10058648525479484 + 0.10058973160807055 + 0.10059297801076594 + 0.10059622446288373 + 0.10059947096442617 + 0.10060271751539558 + 0.10060596411579444 + 0.100609210765625 + 0.10061245746488974 + 0.10061570421359099 + 0.10061895101173099 + 0.1006221978593122 + 0.10062544475633706 + 0.10062869170280789 + 0.10063193869872704 + 0.10063518574409673 + 0.10063843283891956 + 0.10064167998319788 + 0.10064492717693393 + 0.1006481744201301 + 0.10065142171278896 + 0.10065466905491265 + 0.10065791644650363 + 0.10066116388756421 + 0.10066441137809679 + 0.10066765891810371 + 0.10067090650758748 + 0.10067415414655022 + 0.10067740183499466 + 0.10068064957292272 + 0.10068389736033725 + 0.10068714519724016 + 0.10069039308363414 + 0.10069364101952134 + 0.10069688900490438 + 0.10070013703978549 + 0.10070338512416692 + 0.10070663325805138 + 0.10070988144144084 + 0.100713129674338 + 0.100716377956745 + 0.10071962628866434 + 0.10072287467009837 + 0.10072612310104934 + 0.10072937158151986 + 0.10073262011151203 + 0.10073586869102852 + 0.10073911732007147 + 0.10074236599864332 + 0.10074561472674645 + 0.10074886350438315 + 0.10075211233155605 + 0.10075536120826728 + 0.10075861013451912 + 0.10076185911031429 + 0.10076510813565488 + 0.10076835721054339 + 0.10077160633498221 + 0.10077485550897369 + 0.10077810473252015 + 0.10078135400562394 + 0.10078460332828754 + 0.10078785270051317 + 0.1007911021223034 + 0.10079435159366049 + 0.10079760111458691 + 0.10080085068508486 + 0.10080410030515677 + 0.10080734997480513 + 0.10081059969403236 + 0.10081384946284053 + 0.10081709928123235 + 0.10082034914920991 + 0.10082359906677577 + 0.10082684903393233 + 0.1008300990506818 + 0.10083334911702684 + 0.10083659923296935 + 0.10083984939851225 + 0.10084309961365753 + 0.10084634987840771 + 0.10084960019276522 + 0.10085285055673232 + 0.10085610097031143 + 0.10085935143350501 + 0.10086260194631522 + 0.10086585250874462 + 0.10086910312079564 + 0.10087235378247052 + 0.10087560449377168 + 0.1008788552547015 + 0.10088210606526234 + 0.1008853569254566 + 0.10088860783528668 + 0.10089185879475482 + 0.10089510980386369 + 0.10089836086261543 + 0.10090161197101229 + 0.10090486312905711 + 0.10090811433675194 + 0.10091136559409906 + 0.10091461690110108 + 0.10091786825776036 + 0.10092111966407916 + 0.10092437112006003 + 0.10092762262570501 + 0.10093087418101687 + 0.10093412578599784 + 0.10093737744065032 + 0.10094062914497655 + 0.10094388089897913 + 0.10094713270266018 + 0.10095038455602234 + 0.10095363645906788 + 0.10095688841179919 + 0.10096014041421866 + 0.1009633924663286 + 0.10096664456813151 + 0.10096989671962969 + 0.1009731489208255 + 0.10097640117172133 + 0.1009796534723197 + 0.10098290582262277 + 0.1009861582226332 + 0.10098941067235304 + 0.1009926631717849 + 0.10099591572093115 + 0.10099916831979408 + 0.10100242096837617 + 0.10100567366667965 + 0.10100892641470713 + 0.10101217921246083 + 0.10101543205994318 + 0.10101868495715646 + 0.1010219379041032 + 0.10102519090078572 + 0.10102844394720646 + 0.10103169704336772 + 0.101034950189272 + 0.1010382033849215 + 0.10104145663031878 + 0.10104470992546613 + 0.10104796327036603 + 0.10105121666502066 + 0.10105447010943261 + 0.10105772360360429 + 0.10106097714753778 + 0.10106423074123587 + 0.10106748438470059 + 0.1010707380779346 + 0.10107399182094012 + 0.10107724561371968 + 0.10108049945627542 + 0.10108375334860988 + 0.10108700729072553 + 0.10109026128262473 + 0.10109351532430974 + 0.10109676941578295 + 0.10110002355704689 + 0.10110327774810376 + 0.10110653198895618 + 0.10110978627960646 + 0.10111304062005681 + 0.10111629501030973 + 0.10111954945036761 + 0.10112280394023292 + 0.10112605847990797 + 0.10112931306939509 + 0.10113256770869684 + 0.10113582239781535 + 0.10113907713675335 + 0.10114233192551292 + 0.10114558676409666 + 0.10114884165250669 + 0.10115209659074564 + 0.10115535157881593 + 0.10115860661671976 + 0.10116186170445958 + 0.10116511684203792 + 0.10116837202945693 + 0.1011716272667192 + 0.10117488255382701 + 0.10117813789078277 + 0.10118139327758892 + 0.1011846487142478 + 0.10118790420076186 + 0.10119115973713343 + 0.1011944153233649 + 0.10119767095945863 + 0.10120092664541708 + 0.10120418238124264 + 0.10120743816693771 + 0.10121069400250457 + 0.10121394988794573 + 0.10121720582326361 + 0.10122046180846045 + 0.10122371784353867 + 0.10122697392850084 + 0.10123023006334912 + 0.10123348624808609 + 0.10123674248271398 + 0.10123999876723543 + 0.10124325510165248 + 0.10124651148596789 + 0.10124976792018364 + 0.10125302440430246 + 0.10125628093832661 + 0.10125953752225852 + 0.10126279415610064 + 0.1012660508398552 + 0.10126930757352474 + 0.10127256435711166 + 0.10127582119061818 + 0.10127907807404682 + 0.10128233500739998 + 0.10128559199068009 + 0.10128884902388949 + 0.1012921061070305 + 0.10129536324010556 + 0.10129862042311714 + 0.10130187765606768 + 0.10130513493895935 + 0.10130839227179476 + 0.10131164965457606 + 0.10131490708730601 + 0.10131816456998673 + 0.10132142210262074 + 0.10132467968521028 + 0.10132793731775788 + 0.10133119500026601 + 0.10133445273273689 + 0.10133771051517293 + 0.10134096834757651 + 0.10134422622995023 + 0.10134748416229632 + 0.10135074214461727 + 0.10135400017691541 + 0.10135725825919306 + 0.10136051639145272 + 0.10136377457369668 + 0.10136703280592761 + 0.1013702910881477 + 0.10137354942035932 + 0.10137680780256486 + 0.10138006623476679 + 0.10138332471696755 + 0.10138658324916945 + 0.10138984183137491 + 0.10139310046358642 + 0.10139635914580614 + 0.10139961787803678 + 0.10140287666028051 + 0.10140613549253974 + 0.10140939437481709 + 0.10141265330711459 + 0.10141591228943504 + 0.10141917132178056 + 0.10142243040415365 + 0.1014256895365566 + 0.101428948718992 + 0.10143220795146214 + 0.10143546723396946 + 0.10143872656651623 + 0.10144198594910511 + 0.10144524538173817 + 0.10144850486441818 + 0.10145176439714723 + 0.10145502397992792 + 0.10145828361276242 + 0.10146154329565341 + 0.10146480302860307 + 0.10146806281161388 + 0.1014713226446884 + 0.10147458252782872 + 0.10147784246103744 + 0.10148110244431689 + 0.10148436247766962 + 0.10148762256109779 + 0.10149088269460414 + 0.10149414287819059 + 0.10149740311186002 + 0.10150066339561448 + 0.10150392372945663 + 0.10150718411338867 + 0.10151044454741323 + 0.10151370503153248 + 0.101516965565749 + 0.1015202261500651 + 0.10152348678448311 + 0.10152674746900558 + 0.10153000820363481 + 0.10153326898837337 + 0.10153652982322345 + 0.10153979070818749 + 0.10154305164326805 + 0.10154631262846736 + 0.10154957366378793 + 0.10155283474923217 + 0.10155609588480238 + 0.10155935707050109 + 0.10156261830633063 + 0.10156587959229342 + 0.10156914092839189 + 0.10157240231462843 + 0.10157566375100537 + 0.10157892523752515 + 0.10158218677419036 + 0.10158544836100306 + 0.10158870999796606 + 0.10159197168508148 + 0.1015952334223518 + 0.10159849520977939 + 0.10160175704736671 + 0.10160501893511609 + 0.10160828087303014 + 0.10161154286111113 + 0.10161480489936132 + 0.10161806698778338 + 0.10162132912637954 + 0.10162459131515224 + 0.10162785355410399 + 0.10163111584323703 + 0.1016343781825539 + 0.10163764057205704 + 0.10164090301174868 + 0.10164416550163137 + 0.10164742804170743 + 0.10165069063197942 + 0.10165395327244951 + 0.10165721596312029 + 0.10166047870399421 + 0.10166374149507344 + 0.10166700433636072 + 0.10167026722785824 + 0.10167353016956839 + 0.10167679316149354 + 0.10168005620363628 + 0.10168331929599898 + 0.10168658243858399 + 0.10168984563139379 + 0.10169310887443066 + 0.10169637216769704 + 0.10169963551119549 + 0.10170289890492823 + 0.10170616234889775 + 0.10170942584310652 + 0.10171268938755694 + 0.10171595298225135 + 0.1017192166271922 + 0.10172248032238176 + 0.10172574406782281 + 0.10172900786351737 + 0.101732271709468 + 0.10173553560567722 + 0.10173879955214725 + 0.10174206354888056 + 0.10174532759587959 + 0.10174859169314696 + 0.10175185584068469 + 0.10175512003849538 + 0.10175838428658157 + 0.10176164858494545 + 0.10176491293358952 + 0.10176817733251615 + 0.10177144178172799 + 0.10177470628122712 + 0.10177797083101614 + 0.10178123543109731 + 0.10178450008147334 + 0.10178776478214641 + 0.10179102953311894 + 0.10179429433439346 + 0.10179755918597214 + 0.10180082408785769 + 0.10180408904005248 + 0.10180735404255867 + 0.10181061909537896 + 0.10181388419851571 + 0.10181714935197117 + 0.10182041455574789 + 0.1018236798098484 + 0.10182694511427481 + 0.10183021046902975 + 0.10183347587411556 + 0.10183674132953467 + 0.10184000683528961 + 0.10184327239138262 + 0.10184653799781619 + 0.10184980365459281 + 0.10185306936171469 + 0.10185633511918443 + 0.10185960092700447 + 0.10186286678517706 + 0.10186613269370474 + 0.10186939865258988 + 0.10187266466183494 + 0.10187593072144231 + 0.1018791968314144 + 0.1018824629917536 + 0.1018857292024624 + 0.10188899546354316 + 0.10189226177499826 + 0.1018955281368303 + 0.10189879454904148 + 0.10190206101163439 + 0.1019053275246113 + 0.10190859408797469 + 0.10191186070172711 + 0.10191512736587069 + 0.10191839408040808 + 0.10192166084534174 + 0.10192492766067378 + 0.101928194526407 + 0.1019314614425435 + 0.10193472840908598 + 0.10193799542603664 + 0.10194126249339801 + 0.10194452961117242 + 0.10194779677936246 + 0.10195106399797033 + 0.1019543312669985 + 0.10195759858644954 + 0.10196086595632575 + 0.10196413337662966 + 0.10196740084736353 + 0.10197066836852997 + 0.10197393594013128 + 0.10197720356216981 + 0.10198047123464797 + 0.10198373895756846 + 0.1019870067309335 + 0.10199027455474541 + 0.10199354242900675 + 0.10199681035372006 + 0.10200007832888762 + 0.10200334635451172 + 0.10200661443059497 + 0.10200988255713966 + 0.10201315073414839 + 0.10201641896162368 + 0.10201968723956747 + 0.1020229555679826 + 0.10202622394687137 + 0.10202949237623618 + 0.10203276085607937 + 0.10203602938640358 + 0.10203929796721108 + 0.10204256659850441 + 0.10204583528028589 + 0.1020491040125579 + 0.10205237279532299 + 0.10205564162858352 + 0.10205891051234195 + 0.10206217944660066 + 0.10206544843136209 + 0.10206871746662864 + 0.10207198655240274 + 0.10207525568868688 + 0.10207852487548337 + 0.10208179411279476 + 0.10208506340062362 + 0.10208833273897193 + 0.10209160212784242 + 0.1020948715672374 + 0.10209814105715946 + 0.10210141059761088 + 0.1021046801885942 + 0.10210794983011165 + 0.10211121952216587 + 0.10211448926475912 + 0.10211775905789394 + 0.10212102890157279 + 0.10212429879579793 + 0.10212756874057197 + 0.10213083873589718 + 0.10213410878177602 + 0.102137378878211 + 0.10214064902520456 + 0.10214391922275905 + 0.10214718947087693 + 0.10215045976956057 + 0.10215373011881239 + 0.10215700051863502 + 0.10216027096903064 + 0.10216354147000173 + 0.10216681202155083 + 0.10217008262368028 + 0.10217335327639261 + 0.10217662397969024 + 0.10217989473357528 + 0.10218316553805061 + 0.10218643639311828 + 0.10218970729878113 + 0.10219297825504123 + 0.10219624926190113 + 0.10219952031936334 + 0.10220279142743025 + 0.10220606258610407 + 0.10220933379538748 + 0.10221260505528305 + 0.10221587636579287 + 0.10221914772691945 + 0.10222241913866528 + 0.10222569060103291 + 0.10222896211402463 + 0.10223223367764295 + 0.10223550529189004 + 0.10223877695676867 + 0.10224204867228119 + 0.10224532043842979 + 0.10224859225521729 + 0.10225186412264586 + 0.10225513604071798 + 0.10225840800943616 + 0.10226168002880266 + 0.10226495209882006 + 0.10226822421949074 + 0.10227149639081712 + 0.10227476861280184 + 0.10227804088544694 + 0.10228131320875519 + 0.10228458558272883 + 0.10228785800737038 + 0.10229113048268221 + 0.10229440300866696 + 0.10229767558532676 + 0.10230094821266429 + 0.10230422089068175 + 0.1023074936193818 + 0.10231076639876674 + 0.10231403922883901 + 0.10231731210960117 + 0.1023205850410554 + 0.10232385802320443 + 0.10232713105605058 + 0.10233040413959622 + 0.10233367727384389 + 0.10233695045879582 + 0.1023402236944547 + 0.10234349698082283 + 0.10234677031790265 + 0.10235004370569663 + 0.10235331714420726 + 0.1023565906334368 + 0.10235986417338776 + 0.10236313776406282 + 0.10236641140546401 + 0.10236968509759409 + 0.10237295884045529 + 0.1023762326340502 + 0.10237950647838108 + 0.1023827803734506 + 0.10238605431926093 + 0.10238932831581472 + 0.10239260236311432 + 0.10239587646116217 + 0.1023991506099608 + 0.10240242480951245 + 0.10240569905981978 + 0.10240897336088503 + 0.10241224771271067 + 0.10241552211529935 + 0.10241879656865316 + 0.10242207107277493 + 0.10242534562766688 + 0.10242862023333142 + 0.10243189488977107 + 0.10243516959698812 + 0.10243844435498531 + 0.10244171916376471 + 0.10244499402332913 + 0.10244826893368079 + 0.10245154389482196 + 0.10245481890675544 + 0.10245809396948359 + 0.10246136908300865 + 0.1024646442473333 + 0.1024679194624598 + 0.10247119472839064 + 0.10247447004512819 + 0.10247774541267508 + 0.10248102083103368 + 0.10248429630020633 + 0.10248757182019561 + 0.10249084739100385 + 0.10249412301263355 + 0.10249739868508705 + 0.10250067440836702 + 0.10250395018247568 + 0.10250722600741548 + 0.10251050188318905 + 0.10251377780979856 + 0.10251705378724661 + 0.10252032981553584 + 0.10252360589466838 + 0.10252688202464678 + 0.10253015820547348 + 0.10253343443715091 + 0.10253671071968153 + 0.10253998705306776 + 0.10254326343731207 + 0.10254653987241691 + 0.10254981635838473 + 0.10255309289521795 + 0.10255636948291907 + 0.10255964612149039 + 0.10256292281093458 + 0.10256619955125373 + 0.10256947634245062 + 0.10257275318452769 + 0.10257603007748717 + 0.10257930702133157 + 0.10258258401606345 + 0.10258586106168514 + 0.10258913815819906 + 0.10259241530560778 + 0.1025956925039137 + 0.10259896975311918 + 0.10260224705322686 + 0.10260552440423897 + 0.102608801806158 + 0.10261207925898649 + 0.10261535676272687 + 0.10261863431738157 + 0.10262191192295293 + 0.1026251895794435 + 0.10262846728685571 + 0.10263174504519208 + 0.10263502285445487 + 0.10263830071464675 + 0.10264157862576997 + 0.10264485658782718 + 0.10264813460082063 + 0.10265141266475285 + 0.10265469077962623 + 0.10265796894544342 + 0.10266124716220666 + 0.10266452542991844 + 0.10266780374858125 + 0.10267108211819738 + 0.10267436053876958 + 0.10267763901030016 + 0.10268091753279149 + 0.10268419610624599 + 0.10268747473066622 + 0.10269075340605457 + 0.10269403213241365 + 0.10269731090974564 + 0.10270058973805328 + 0.10270386861733877 + 0.10270714754760457 + 0.10271042652885333 + 0.10271370556108733 + 0.10271698464430916 + 0.10272026377852109 + 0.10272354296372561 + 0.10272682219992522 + 0.10273010148712246 + 0.10273338082531971 + 0.1027366602145194 + 0.10273993965472392 + 0.10274321914593583 + 0.10274649868815747 + 0.10274977828139145 + 0.10275305792564011 + 0.10275633762090591 + 0.10275961736719126 + 0.10276289716449871 + 0.10276617701283061 + 0.10276945691218967 + 0.102772736862578 + 0.10277601686399809 + 0.10277929691645259 + 0.1027825770199438 + 0.10278585717447425 + 0.1027891373800465 + 0.1027924176366628 + 0.10279569794432558 + 0.10279897830303747 + 0.10280225871280085 + 0.10280553917361822 + 0.10280881968549185 + 0.1028121002484244 + 0.10281538086241826 + 0.10281866152747585 + 0.10282194224359958 + 0.10282522301079196 + 0.10282850382905556 + 0.10283178469839263 + 0.10283506561880583 + 0.10283834659029742 + 0.10284162761286995 + 0.10284490868652592 + 0.10284818981126774 + 0.10285147098709779 + 0.10285475221401857 + 0.10285803349203254 + 0.10286131482114225 + 0.10286459620135013 + 0.10286787763265839 + 0.10287115911506978 + 0.1028744406485867 + 0.10287772223321158 + 0.10288100386894686 + 0.10288428555579489 + 0.10288756729375827 + 0.10289084908283939 + 0.10289413092304074 + 0.10289741281436486 + 0.10290069475681403 + 0.10290397675039079 + 0.10290725879509763 + 0.10291054089093694 + 0.10291382303791122 + 0.10291710523602293 + 0.10292038748527443 + 0.10292366978566851 + 0.10292695213720719 + 0.10293023453989317 + 0.10293351699372884 + 0.10293679949871667 + 0.10294008205485919 + 0.10294336466215882 + 0.10294664732061791 + 0.10294993003023906 + 0.10295321279102471 + 0.10295649560297711 + 0.10295977846609909 + 0.10296306138039282 + 0.10296634434586092 + 0.10296962736250571 + 0.10297291043032976 + 0.10297619354933542 + 0.10297947671952527 + 0.1029827599409017 + 0.10298604321346716 + 0.10298932653722422 + 0.10299260991217525 + 0.10299589333832271 + 0.102999176815669 + 0.10300246034421678 + 0.10300574392396832 + 0.10300902755492615 + 0.10301231123709265 + 0.1030155949704704 + 0.10301887875506184 + 0.10302216259086946 + 0.10302544647789569 + 0.10302873041614281 + 0.10303201440561358 + 0.10303529844631029 + 0.10303858253823549 + 0.10304186668139154 + 0.10304515087578098 + 0.10304843512140612 + 0.10305171941826963 + 0.10305500376637396 + 0.10305828816572148 + 0.10306157261631474 + 0.10306485711815597 + 0.10306814167124806 + 0.10307142627559303 + 0.10307471093119357 + 0.10307799563805212 + 0.10308128039617104 + 0.10308456520555292 + 0.10308785006620033 + 0.10309113497811545 + 0.10309441994130103 + 0.10309770495575919 + 0.10310099002149273 + 0.10310427513850402 + 0.10310756030679544 + 0.10311084552636944 + 0.10311413079722855 + 0.10311741611937528 + 0.10312070149281209 + 0.10312398691754139 + 0.10312727239356556 + 0.10313055792088718 + 0.10313384349950878 + 0.10313712912943272 + 0.10314041481066155 + 0.10314370054319746 + 0.10314698632704342 + 0.10315027216220143 + 0.10315355804867413 + 0.10315684398646414 + 0.10316012997557363 + 0.10316341601600527 + 0.10316670210776138 + 0.10316998825084481 + 0.10317327444525751 + 0.10317656069100208 + 0.10317984698808129 + 0.10318313333649742 + 0.10318641973625284 + 0.1031897061873501 + 0.10319299268979169 + 0.10319627924358006 + 0.10319956584871749 + 0.10320285250520682 + 0.10320613921305037 + 0.10320942597225038 + 0.10321271278280968 + 0.10321599964473063 + 0.10321928655801538 + 0.10322257352266684 + 0.10322586053868719 + 0.10322914760607917 + 0.10323243472484496 + 0.10323572189498718 + 0.10323900911650831 + 0.10324229638941072 + 0.10324558371369698 + 0.10324887108936943 + 0.1032521585164308 + 0.10325544599488332 + 0.10325873352472946 + 0.10326202110597184 + 0.10326530873861296 + 0.10326859642265503 + 0.10327188415810068 + 0.10327517194495248 + 0.1032784597832128 + 0.10328174767288407 + 0.10328503561396882 + 0.10328832360646954 + 0.10329161165038854 + 0.10329489974572863 + 0.1032981878924918 + 0.10330147609068102 + 0.10330476434029845 + 0.10330805264134675 + 0.10331134099382817 + 0.10331462939774542 + 0.1033179178531007 + 0.10332120635989674 + 0.10332449491813599 + 0.10332778352782079 + 0.10333107218895356 + 0.10333436090153703 + 0.10333764966557345 + 0.1033409384810655 + 0.10334422734801532 + 0.1033475162664258 + 0.10335080523629903 + 0.10335409425763777 + 0.10335738333044438 + 0.10336067245472129 + 0.10336396163047103 + 0.10336725085769606 + 0.10337054013639894 + 0.10337382946658195 + 0.10337711884824777 + 0.10338040828139881 + 0.10338369776603744 + 0.10338698730216617 + 0.10339027688978773 + 0.10339356652890432 + 0.10339685621951845 + 0.10340014596163254 + 0.10340343575524921 + 0.10340672560037097 + 0.10341001549700024 + 0.10341330544513934 + 0.10341659544479098 + 0.10341988549595749 + 0.10342317559864139 + 0.10342646575284517 + 0.10342975595857121 + 0.10343304621582215 + 0.10343633652460039 + 0.10343962688490839 + 0.10344291729674865 + 0.10344620776012357 + 0.10344949827503577 + 0.10345278884148768 + 0.10345607945948174 + 0.10345937012902044 + 0.10346266085010619 + 0.10346595162274162 + 0.10346924244692914 + 0.10347253332267126 + 0.10347582424997021 + 0.10347911522882884 + 0.10348240625924941 + 0.10348569734123461 + 0.1034889884747867 + 0.10349227965990815 + 0.10349557089660144 + 0.10349886218486928 + 0.10350215352471397 + 0.10350544491613788 + 0.10350873635914382 + 0.10351202785373391 + 0.10351531939991074 + 0.10351861099767705 + 0.10352190264703501 + 0.1035251943479872 + 0.10352848610053617 + 0.10353177790468428 + 0.103535069760434 + 0.10353836166778801 + 0.10354165362674875 + 0.10354494563731836 + 0.10354823769949975 + 0.1035515298132951 + 0.10355482197870715 + 0.1035581141957382 + 0.10356140646439077 + 0.10356469878466742 + 0.10356799115657046 + 0.10357128358010248 + 0.10357457605526606 + 0.10357786858206354 + 0.10358116116049741 + 0.10358445379057037 + 0.10358774647228455 + 0.10359103920564271 + 0.10359433199064715 + 0.10359762482730038 + 0.10360091771560505 + 0.10360421065556355 + 0.10360750364717831 + 0.1036107966904519 + 0.10361408978538665 + 0.10361738293198519 + 0.10362067613025 + 0.10362396938018351 + 0.10362726268178826 + 0.10363055603506661 + 0.10363384944002114 + 0.10363714289665432 + 0.10364043640496884 + 0.10364372996496686 + 0.10364702357665094 + 0.10365031724002362 + 0.1036536109550875 + 0.10365690472184479 + 0.10366019854029823 + 0.10366349241045023 + 0.10366678633230327 + 0.10367008030585971 + 0.10367337433112228 + 0.10367666840809342 + 0.10367996253677535 + 0.10368325671717088 + 0.10368655094928222 + 0.10368984523311203 + 0.10369313956866286 + 0.10369643395593703 + 0.1036997283949371 + 0.10370302288566553 + 0.103706317428125 + 0.10370961202231767 + 0.10371290666824616 + 0.10371620136591315 + 0.10371949611532089 + 0.10372279091647188 + 0.10372608576936874 + 0.10372938067401383 + 0.10373267563040976 + 0.10373597063855894 + 0.10373926569846381 + 0.10374256081012707 + 0.103745855973551 + 0.10374915118873819 + 0.10375244645569109 + 0.10375574177441203 + 0.10375903714490378 + 0.10376233256716887 + 0.10376562804120942 + 0.10376892356702813 + 0.10377221914462768 + 0.10377551477401034 + 0.10377881045517839 + 0.10378210618813483 + 0.10378540197288179 + 0.10378869780942185 + 0.10379199369775753 + 0.10379528963789127 + 0.10379858562982568 + 0.10380188167356301 + 0.10380517776910603 + 0.10380847391645713 + 0.10381177011561855 + 0.10381506636659328 + 0.10381836266938346 + 0.10382165902399156 + 0.10382495543042036 + 0.10382825188867204 + 0.10383154839874915 + 0.10383484496065441 + 0.10383814157439007 + 0.10384143823995873 + 0.10384473495736285 + 0.10384803172660508 + 0.10385132854768753 + 0.10385462542061305 + 0.10385792234538389 + 0.10386121932200276 + 0.10386451635047204 + 0.10386781343079432 + 0.10387111056297202 + 0.10387440774700754 + 0.10387770498290361 + 0.10388100227066233 + 0.10388429961028661 + 0.10388759700177884 + 0.10389089444514141 + 0.10389419194037676 + 0.10389748948748762 + 0.10390078708647629 + 0.10390408473734525 + 0.10390738244009722 + 0.10391068019473444 + 0.1039139780012595 + 0.10391727585967504 + 0.10392057376998333 + 0.10392387173218694 + 0.10392716974628841 + 0.10393046781229021 + 0.10393376593019486 + 0.10393706410000478 + 0.10394036232172259 + 0.10394366059535065 + 0.10394695892089152 + 0.10395025729834777 + 0.10395355572772169 + 0.10395685420901611 + 0.10396015274223322 + 0.10396345132737561 + 0.10396674996444585 + 0.10397004865344638 + 0.10397334739437972 + 0.10397664618724826 + 0.10397994503205474 + 0.10398324392880148 + 0.10398654287749091 + 0.10398984187812566 + 0.10399314093070816 + 0.10399644003524097 + 0.10399973919172648 + 0.10400303840016743 + 0.10400633766056605 + 0.10400963697292497 + 0.10401293633724663 + 0.10401623575353375 + 0.10401953522178846 + 0.10402283474201353 + 0.10402613431421123 + 0.10402943393838444 + 0.10403273361453522 + 0.10403603334266633 + 0.1040393331227803 + 0.10404263295487946 + 0.10404593283896639 + 0.1040492327750436 + 0.10405253276311369 + 0.10405583280317902 + 0.10405913289524205 + 0.10406243303930542 + 0.10406573323537149 + 0.10406903348344296 + 0.10407233378352214 + 0.10407563413561161 + 0.10407893453971387 + 0.10408223499583154 + 0.10408553550396678 + 0.1040888360641225 + 0.10409213667630103 + 0.10409543734050465 + 0.10409873805673625 + 0.10410203882499813 + 0.10410533964529281 + 0.10410864051762278 + 0.10411194144199061 + 0.10411524241839867 + 0.10411854344684961 + 0.10412184452734589 + 0.1041251456598899 + 0.10412844684448429 + 0.10413174808113163 + 0.10413504936983428 + 0.10413835071059471 + 0.10414165210341535 + 0.10414495354829902 + 0.10414825504524804 + 0.10415155659426491 + 0.10415485819535214 + 0.10415815984851216 + 0.10416146155374759 + 0.10416476331106095 + 0.10416806512045464 + 0.1041713669819313 + 0.10417466889549322 + 0.10417797086114317 + 0.10418127287888349 + 0.10418457494871665 + 0.10418787707064531 + 0.10419117924467186 + 0.10419448147079882 + 0.10419778374902872 + 0.1042010860793641 + 0.10420438846180737 + 0.10420769089636124 + 0.10421099338302788 + 0.10421429592181007 + 0.1042175985127103 + 0.10422090115573092 + 0.10422420385087461 + 0.10422750659814367 + 0.1042308093975409 + 0.10423411224906855 + 0.10423741515272934 + 0.10424071810852549 + 0.10424402111645986 + 0.10424732417653448 + 0.10425062728875245 + 0.10425393045311573 + 0.1042572336696274 + 0.10426053693828945 + 0.10426384025910446 + 0.10426714363207522 + 0.10427044705720422 + 0.10427375053449361 + 0.10427705406394613 + 0.10428035764556441 + 0.10428366127935082 + 0.10428696496530783 + 0.10429026870343805 + 0.10429357249374396 + 0.10429687633622793 + 0.10430018023089262 + 0.10430348417774052 + 0.1043067881767742 + 0.10431009222799609 + 0.10431339633140878 + 0.10431670048701444 + 0.10432000469481621 + 0.10432330895481604 + 0.10432661326701663 + 0.10432991763142063 + 0.10433322204803039 + 0.10433652651684838 + 0.10433983103787738 + 0.10434313561111946 + 0.10434644023657752 + 0.10434974491425406 + 0.10435304964415126 + 0.10435635442627199 + 0.10435965926061856 + 0.10436296414719347 + 0.10436626908599939 + 0.10436957407703867 + 0.10437287912031398 + 0.10437618421582764 + 0.10437948936358243 + 0.1043827945635806 + 0.10438609981582476 + 0.1043894051203175 + 0.10439271047706133 + 0.10439601588605857 + 0.10439932134731179 + 0.1044026268608237 + 0.10440593242659664 + 0.10440923804463319 + 0.10441254371493595 + 0.10441584943750723 + 0.10441915521234967 + 0.10442246103946577 + 0.10442576691885795 + 0.10442907285052892 + 0.10443237883448114 + 0.10443568487071694 + 0.10443899095923911 + 0.10444229710004999 + 0.104445603293152 + 0.10444890953854791 + 0.10445221583624001 + 0.10445552218623097 + 0.10445882858852328 + 0.10446213504311942 + 0.1044654415500219 + 0.1044687481092333 + 0.10447205472075602 + 0.10447536138459269 + 0.10447866810074584 + 0.1044819748692179 + 0.10448528169001128 + 0.10448858856312879 + 0.10449189548857277 + 0.10449520246634562 + 0.10449850949645013 + 0.10450181657888861 + 0.10450512371366373 + 0.1045084309007779 + 0.10451173814023369 + 0.10451504543203352 + 0.10451835277618002 + 0.10452166017267567 + 0.10452496762152312 + 0.10452827512272463 + 0.10453158267628294 + 0.1045348902822003 + 0.1045381979404796 + 0.10454150565112305 + 0.10454481341413321 + 0.10454812122951283 + 0.10455142909726427 + 0.10455473701738989 + 0.10455804498989256 + 0.10456135301477454 + 0.10456466109203845 + 0.10456796922168672 + 0.10457127740372189 + 0.1045745856381467 + 0.10457789392496335 + 0.10458120226417467 + 0.10458451065578285 + 0.10458781909979069 + 0.10459112759620051 + 0.10459443614501489 + 0.10459774474623638 + 0.10460105339986761 + 0.10460436210591098 + 0.10460767086436898 + 0.10461097967524427 + 0.10461428853853907 + 0.10461759745425635 + 0.10462090642239819 + 0.10462421544296747 + 0.10462752451596648 + 0.10463083364139786 + 0.104634142819264 + 0.10463745204956763 + 0.10464076133231111 + 0.10464407066749698 + 0.10464738005512791 + 0.10465068949520617 + 0.10465399898773455 + 0.10465730853271538 + 0.10466061813015118 + 0.10466392778004459 + 0.10466723748239817 + 0.10467054723721425 + 0.10467385704449551 + 0.10467716690424443 + 0.10468047681646352 + 0.10468378678115529 + 0.10468709679832235 + 0.10469040686796716 + 0.10469371699009226 + 0.10469702716470013 + 0.10470033739179328 + 0.10470364767137437 + 0.10470695800344573 + 0.10471026838801017 + 0.10471357882506997 + 0.10471688931462766 + 0.10472019985668594 + 0.10472351045124714 + 0.10472682109831388 + 0.10473013179788872 + 0.10473344254997413 + 0.10473675335457276 + 0.104740064211687 + 0.10474337512131916 + 0.10474668608347239 + 0.1047499970981486 + 0.10475330816535063 + 0.10475661928508098 + 0.10475993045734204 + 0.10476324168213642 + 0.10476655295946678 + 0.10476986428933546 + 0.10477317567174509 + 0.10477648710669814 + 0.10477979859419716 + 0.10478311013424471 + 0.10478642172684322 + 0.10478973337199525 + 0.10479304506970341 + 0.10479635681997028 + 0.10479966862279826 + 0.1048029804781898 + 0.10480629238614765 + 0.10480960434667411 + 0.10481291635977188 + 0.10481622842544344 + 0.10481954054369154 + 0.10482285271451817 + 0.10482616493792633 + 0.10482947721391836 + 0.10483278954249677 + 0.10483610192366424 + 0.10483941435742311 + 0.10484272684377617 + 0.10484603938272566 + 0.10484935197427425 + 0.10485266461842445 + 0.10485597731517882 + 0.10485929006453995 + 0.10486260286651017 + 0.10486591572109207 + 0.10486922862828836 + 0.10487254158810157 + 0.10487585460053395 + 0.10487916766558829 + 0.10488248078326692 + 0.10488579395357259 + 0.10488910717650772 + 0.10489242045207484 + 0.10489573378027647 + 0.10489904716111516 + 0.10490236059459349 + 0.10490567408071398 + 0.10490898761947895 + 0.10491230121089128 + 0.10491561485495322 + 0.10491892855166751 + 0.10492224230103651 + 0.10492555610306291 + 0.10492886995774924 + 0.10493218386509788 + 0.1049354978251115 + 0.10493881183779249 + 0.10494212590314357 + 0.10494544002116712 + 0.10494875419186579 + 0.10495206841524186 + 0.10495538269129834 + 0.10495869702003732 + 0.10496201140146152 + 0.10496532583557357 + 0.10496864032237584 + 0.10497195486187083 + 0.10497526945406122 + 0.10497858409894958 + 0.10498189879653838 + 0.10498521354682994 + 0.10498852834982708 + 0.1049918432055323 + 0.10499515811394795 + 0.10499847307507675 + 0.10500178808892127 + 0.10500510315548386 + 0.10500841827476716 + 0.10501173344677385 + 0.10501504867150611 + 0.10501836394896687 + 0.10502167927915827 + 0.10502499466208326 + 0.10502831009774412 + 0.10503162558614337 + 0.10503494112728365 + 0.10503825672116744 + 0.10504157236779749 + 0.105044888067176 + 0.10504820381930566 + 0.10505151962418897 + 0.1050548354818287 + 0.10505815139222696 + 0.10506146735538675 + 0.10506478337131021 + 0.10506809944000019 + 0.10507141556145891 + 0.10507473173568936 + 0.10507804796269368 + 0.10508136424247441 + 0.10508468057503439 + 0.10508799696037584 + 0.10509131339850158 + 0.10509462988941394 + 0.10509794643311564 + 0.10510126302960905 + 0.10510457967889678 + 0.10510789638098145 + 0.1051112131358654 + 0.10511452994355136 + 0.10511784680404176 + 0.10512116371733916 + 0.10512448068344617 + 0.10512779770236517 + 0.10513111477409896 + 0.10513443189864985 + 0.1051377490760206 + 0.10514106630621359 + 0.10514438358923124 + 0.10514770092507639 + 0.10515101831375134 + 0.1051543357552587 + 0.10515765324960115 + 0.10516097079678113 + 0.10516428839680113 + 0.10516760604966367 + 0.10517092375537142 + 0.10517424151392672 + 0.10517755932533247 + 0.10518087718959095 + 0.10518419510670463 + 0.10518751307667636 + 0.10519083109950829 + 0.10519414917520327 + 0.10519746730376379 + 0.10520078548519234 + 0.10520410371949124 + 0.10520742200666361 + 0.10521074034671132 + 0.10521405873963745 + 0.10521737718544436 + 0.10522069568413453 + 0.10522401423571044 + 0.10522733284017488 + 0.10523065149753019 + 0.10523397020777901 + 0.10523728897092381 + 0.10524060778696724 + 0.10524392665591163 + 0.10524724557775977 + 0.10525056455251419 + 0.10525388358017733 + 0.10525720266075178 + 0.10526052179424009 + 0.10526384098064473 + 0.10526716021996829 + 0.10527047951221336 + 0.1052737988573824 + 0.10527711825547809 + 0.10528043770650296 + 0.10528375721045942 + 0.10528707676735014 + 0.10529039637717753 + 0.10529371603994436 + 0.10529703575565298 + 0.10530035552430593 + 0.10530367534590598 + 0.1053069952204555 + 0.10531031514795688 + 0.10531363512841306 + 0.10531695516182633 + 0.10532027524819923 + 0.1053235953875345 + 0.10532691557983437 + 0.10533023582510177 + 0.1053335561233389 + 0.10533687647454858 + 0.10534019687873322 + 0.10534351733589539 + 0.10534683784603752 + 0.10535015840916245 + 0.10535347902527255 + 0.10535679969437035 + 0.10536012041645831 + 0.10536344119153911 + 0.10536676201961538 + 0.10537008290068955 + 0.10537340383476423 + 0.10537672482184192 + 0.10538004586192509 + 0.10538336695501652 + 0.10538668810111862 + 0.10539000930023389 + 0.10539333055236494 + 0.10539665185751437 + 0.10539997321568478 + 0.10540329462687847 + 0.10540661609109811 + 0.10540993760834651 + 0.10541325917862569 + 0.10541658080193865 + 0.10541990247828788 + 0.10542322420767587 + 0.10542654599010501 + 0.10542986782557807 + 0.1054331897140975 + 0.10543651165566598 + 0.10543983365028589 + 0.1054431556979598 + 0.10544647779869046 + 0.10544979995248024 + 0.10545312215933163 + 0.1054564444192474 + 0.10545976673223 + 0.10546308909828195 + 0.10546641151740573 + 0.10546973398960409 + 0.10547305651487944 + 0.10547637909323444 + 0.10547970172467157 + 0.10548302440919335 + 0.1054863471468024 + 0.10548966993750129 + 0.10549299278129257 + 0.1054963156781787 + 0.10549963862816236 + 0.10550296163124601 + 0.10550628468743221 + 0.10550960779672358 + 0.10551293095912277 + 0.10551625417463188 + 0.10551957744325417 + 0.10552290076499166 + 0.10552622413984691 + 0.1055295475678228 + 0.10553287104892173 + 0.10553619458314616 + 0.10553951817049874 + 0.10554284181098218 + 0.10554616550459868 + 0.10554948925135101 + 0.10555281305124176 + 0.10555613690427337 + 0.10555946081044845 + 0.10556278476976959 + 0.10556610878223929 + 0.1055694328478602 + 0.10557275696663482 + 0.10557608113856572 + 0.10557940536365536 + 0.10558272964190638 + 0.10558605397332138 + 0.10558937835790293 + 0.10559270279565344 + 0.10559602728657561 + 0.10559935183067203 + 0.10560267642794506 + 0.1056060010783974 + 0.10560932578203151 + 0.10561265053885024 + 0.10561597534885581 + 0.10561930021205082 + 0.10562262512843808 + 0.10562595009801985 + 0.10562927512079885 + 0.1056326001967776 + 0.10563592532595872 + 0.10563925050834477 + 0.10564257574393815 + 0.10564590103274162 + 0.10564922637475753 + 0.10565255176998863 + 0.10565587721843744 + 0.10565920272010647 + 0.10566252827499828 + 0.10566585388311546 + 0.10566917954446053 + 0.10567250525903621 + 0.10567583102684484 + 0.10567915684788913 + 0.10568248272217146 + 0.10568580864969471 + 0.10568913463046112 + 0.10569246066447335 + 0.10569578675173415 + 0.10569911289224586 + 0.10570243908601117 + 0.10570576533303246 + 0.10570909163331245 + 0.1057124179868538 + 0.10571574439365884 + 0.10571907085373008 + 0.10572239736707049 + 0.10572572393368219 + 0.10572905055356814 + 0.10573237722673054 + 0.10573570395317219 + 0.10573903073289555 + 0.10574235756590313 + 0.1057456844521977 + 0.10574901139178154 + 0.1057523383846575 + 0.10575566543082797 + 0.10575899253029553 + 0.10576231968306288 + 0.10576564688913227 + 0.10576897414850654 + 0.10577230146118832 + 0.10577562882717995 + 0.10577895624648409 + 0.10578228371910341 + 0.10578561124504021 + 0.10578893882429719 + 0.10579226645687705 + 0.10579559414278206 + 0.10579892188201533 + 0.10580224967457875 + 0.10580557752047534 + 0.10580890541970747 + 0.10581223337227774 + 0.1058155613781888 + 0.10581888943744307 + 0.10582221755004328 + 0.10582554571599193 + 0.10582887393529151 + 0.10583220220794468 + 0.10583553053395393 + 0.10583885891332193 + 0.1058421873460513 + 0.10584551583214433 + 0.10584884437160387 + 0.10585217296443231 + 0.10585550161063226 + 0.10585883031020628 + 0.10586215906315713 + 0.10586548786948721 + 0.10586881672919896 + 0.10587214564229513 + 0.10587547460877821 + 0.10587880362865076 + 0.10588213270191557 + 0.10588546182857494 + 0.10588879100863149 + 0.10589212024208788 + 0.10589544952894667 + 0.10589877886921023 + 0.10590210826288141 + 0.10590543770996258 + 0.10590876721045651 + 0.10591209676436554 + 0.10591542637169242 + 0.10591875603243953 + 0.10592208574660968 + 0.10592541551420524 + 0.10592874533522884 + 0.10593207520968313 + 0.10593540513757063 + 0.10593873511889379 + 0.10594206515365548 + 0.10594539524185788 + 0.10594872538350382 + 0.10595205557859588 + 0.10595538582713653 + 0.10595871612912834 + 0.10596204648457397 + 0.10596537689347592 + 0.10596870735583683 + 0.10597203787165915 + 0.10597536844094543 + 0.1059786990636985 + 0.10598202973992082 + 0.10598536046961467 + 0.10598869125278312 + 0.10599202208942828 + 0.10599535297955298 + 0.10599868392315991 + 0.10600201492025137 + 0.10600534597083003 + 0.10600867707489851 + 0.10601200823245931 + 0.10601533944351499 + 0.10601867070806822 + 0.10602200202612162 + 0.10602533339767754 + 0.10602866482273884 + 0.10603199630130776 + 0.10603532783338715 + 0.10603865941897954 + 0.10604199105808743 + 0.10604532275071331 + 0.10604865449685991 + 0.10605198629652983 + 0.10605531814972553 + 0.10605865005644956 + 0.10606198201670476 + 0.10606531403049338 + 0.10606864609781817 + 0.10607197821868165 + 0.10607531039308647 + 0.10607864262103497 + 0.10608197490252998 + 0.10608530723757406 + 0.10608863962616974 + 0.10609197206831947 + 0.10609530456402598 + 0.10609863711329183 + 0.1061019697161195 + 0.10610530237251174 + 0.1061086350824709 + 0.10611196784599974 + 0.10611530066310078 + 0.10611863353377657 + 0.10612196645802974 + 0.10612529943586288 + 0.1061286324672784 + 0.10613196555227913 + 0.10613529869086751 + 0.10613863188304615 + 0.10614196512881754 + 0.10614529842818432 + 0.1061486317811491 + 0.10615196518771443 + 0.10615529864788299 + 0.10615863216165708 + 0.10616196572903963 + 0.10616529935003313 + 0.1061686330246399 + 0.10617196675286263 + 0.1061753005347042 + 0.10617863437016681 + 0.10618196825925318 + 0.10618530220196601 + 0.10618863619830771 + 0.10619197024828086 + 0.10619530435188815 + 0.10619863850913219 + 0.10620197272001534 + 0.10620530698454031 + 0.10620864130270982 + 0.10621197567452627 + 0.10621531009999229 + 0.1062186445791104 + 0.10622197911188333 + 0.10622531369831351 + 0.10622864833840362 + 0.10623198303215634 + 0.10623531777957394 + 0.10623865258065916 + 0.10624198743541474 + 0.106245322343843 + 0.10624865730594665 + 0.10625199232172851 + 0.10625532739119066 + 0.10625866251433615 + 0.10626199769116726 + 0.10626533292168668 + 0.10626866820589687 + 0.10627200354380073 + 0.10627533893540052 + 0.10627867438069891 + 0.10628200987969859 + 0.10628534543240209 + 0.10628868103881187 + 0.10629201669893061 + 0.10629535241276106 + 0.10629868818030545 + 0.10630202400156677 + 0.10630535987654725 + 0.10630869580524965 + 0.10631203178767655 + 0.1063153678238305 + 0.10631870391371423 + 0.10632204005732993 + 0.10632537625468047 + 0.10632871250576857 + 0.10633204881059663 + 0.10633538516916716 + 0.10633872158148289 + 0.10634205804754632 + 0.10634539456736025 + 0.10634873114092684 + 0.10635206776824904 + 0.10635540444932923 + 0.10635874118417021 + 0.10636207797277443 + 0.10636541481514446 + 0.10636875171128288 + 0.1063720886611923 + 0.10637542566487551 + 0.10637876272233475 + 0.10638209983357279 + 0.10638543699859218 + 0.10638877421739565 + 0.10639211148998541 + 0.10639544881636442 + 0.10639878619653521 + 0.10640212363050018 + 0.10640546111826209 + 0.10640879865982358 + 0.10641213625518695 + 0.10641547390435513 + 0.10641881160733041 + 0.10642214936411556 + 0.10642548717471315 + 0.10642882503912572 + 0.10643216295735596 + 0.10643550092940623 + 0.10643883895527946 + 0.10644217703497795 + 0.10644551516850446 + 0.10644885335586131 + 0.10645219159705156 + 0.10645552989207734 + 0.10645886824094158 + 0.10646220664364651 + 0.10646554510019512 + 0.10646888361058973 + 0.106472222174833 + 0.10647556079292753 + 0.10647889946487599 + 0.10648223819068078 + 0.10648557697034468 + 0.10648891580387025 + 0.10649225469125999 + 0.10649559363251643 + 0.10649893262764233 + 0.10650227167664017 + 0.10650561077951277 + 0.10650894993626236 + 0.10651228914689179 + 0.10651562841140357 + 0.10651896772980027 + 0.10652230710208452 + 0.10652564652825888 + 0.106528986008326 + 0.10653232554228841 + 0.10653566513014867 + 0.10653900477190946 + 0.10654234446757344 + 0.10654568421714307 + 0.106549024020621 + 0.10655236387800968 + 0.10655570378931198 + 0.10655904375453026 + 0.10656238377366721 + 0.10656572384672532 + 0.1065690639737073 + 0.10657240415461573 + 0.1065757443894533 + 0.1065790846782223 + 0.10658242502092564 + 0.10658576541756581 + 0.10658910586814542 + 0.10659244637266689 + 0.10659578693113307 + 0.10659912754354649 + 0.10660246820990948 + 0.10660580893022498 + 0.10660914970449548 + 0.10661249053272343 + 0.1066158314149117 + 0.10661917235106266 + 0.10662251334117898 + 0.10662585438526322 + 0.10662919548331801 + 0.10663253663534597 + 0.10663587784134976 + 0.10663921910133178 + 0.10664256041529473 + 0.10664590178324122 + 0.10664924320517394 + 0.10665258468109523 + 0.10665592621100792 + 0.10665926779491453 + 0.10666260943281761 + 0.10666595112471981 + 0.1066692928706237 + 0.10667263467053212 + 0.10667597652444727 + 0.10667931843237181 + 0.10668266039430864 + 0.10668600241026008 + 0.10668934448022878 + 0.10669268660421748 + 0.10669602878222861 + 0.1066993710142649 + 0.10670271330032874 + 0.10670605564042297 + 0.10670939803455014 + 0.10671274048271272 + 0.10671608298491338 + 0.10671942554115481 + 0.10672276815143945 + 0.10672611081576991 + 0.10672945353414888 + 0.10673279630657906 + 0.1067361391330628 + 0.10673948201360289 + 0.10674282494820188 + 0.10674616793686224 + 0.10674951097958674 + 0.10675285407637798 + 0.1067561972272385 + 0.10675954043217079 + 0.10676288369117766 + 0.10676622700426165 + 0.10676957037142532 + 0.10677291379267115 + 0.10677625726800195 + 0.10677960079742023 + 0.10678294438092867 + 0.1067862880185298 + 0.10678963171022628 + 0.10679297545602057 + 0.10679631925591535 + 0.10679966310991319 + 0.10680300701801684 + 0.10680635098022873 + 0.10680969499655148 + 0.10681303906698786 + 0.10681638319154027 + 0.10681972737021146 + 0.10682307160300397 + 0.10682641588992035 + 0.1068297602309633 + 0.10683310462613545 + 0.10683644907543924 + 0.10683979357887741 + 0.10684313813645246 + 0.10684648274816717 + 0.10684982741402391 + 0.10685317213402547 + 0.10685651690817434 + 0.10685986173647317 + 0.10686320661892458 + 0.10686655155553121 + 0.10686989654629554 + 0.10687324159122027 + 0.10687658669030803 + 0.10687993184356132 + 0.1068832770509829 + 0.10688662231257524 + 0.10688996762834101 + 0.1068933129982827 + 0.10689665842240312 + 0.10690000390070462 + 0.10690334943319006 + 0.10690669501986184 + 0.10691004066072275 + 0.10691338635577537 + 0.10691673210502209 + 0.10692007790846578 + 0.10692342376610879 + 0.10692676967795402 + 0.106930115644004 + 0.10693346166426108 + 0.1069368077387281 + 0.10694015386740763 + 0.1069435000503024 + 0.10694684628741474 + 0.10695019257874742 + 0.10695353892430313 + 0.10695688532408422 + 0.10696023177809347 + 0.10696357828633364 + 0.10696692484880711 + 0.10697027146551649 + 0.10697361813646435 + 0.10697696486165348 + 0.10698031164108661 + 0.10698365847476601 + 0.10698700536269429 + 0.10699035230487432 + 0.1069936993013086 + 0.10699704635199968 + 0.10700039345695016 + 0.10700374061616275 + 0.10700708782964 + 0.10701043509738462 + 0.10701378241939903 + 0.10701712979568596 + 0.10702047722624811 + 0.10702382471108782 + 0.10702717225020798 + 0.10703051984361094 + 0.1070338674912996 + 0.1070372151932764 + 0.10704056294954384 + 0.10704391076010475 + 0.10704725862496171 + 0.10705060654411717 + 0.10705395451757389 + 0.10705730254533447 + 0.10706065062740147 + 0.10706399876377751 + 0.10706734695446521 + 0.10707069519946721 + 0.10707404349878605 + 0.10707739185242449 + 0.107080740260385 + 0.10708408872267013 + 0.10708743723928271 + 0.10709078581022519 + 0.10709413443550027 + 0.10709748311511044 + 0.10710083184905853 + 0.10710418063734692 + 0.1071075294799784 + 0.10711087837695543 + 0.10711422732828083 + 0.10711757633395688 + 0.10712092539398657 + 0.10712427450837218 + 0.10712762367711659 + 0.1071309729002224 + 0.10713432217769202 + 0.10713767150952823 + 0.10714102089573348 + 0.10714437033631063 + 0.10714771983126202 + 0.10715106938059057 + 0.10715441898429874 + 0.107157768642389 + 0.10716111835486415 + 0.10716446812172674 + 0.10716781794297942 + 0.10717116781862483 + 0.10717451774866549 + 0.1071778677331041 + 0.10718121777194324 + 0.10718456786518545 + 0.10718791801283362 + 0.10719126821488992 + 0.10719461847135743 + 0.10719796878223842 + 0.10720131914753572 + 0.10720466956725189 + 0.10720802004138943 + 0.1072113705699512 + 0.10721472115293956 + 0.10721807179035721 + 0.10722142248220688 + 0.10722477322849112 + 0.10722812402921233 + 0.10723147488437357 + 0.10723482579397711 + 0.10723817675802565 + 0.10724152777652191 + 0.10724487884946834 + 0.1072482299768677 + 0.10725158115872246 + 0.10725493239503542 + 0.10725828368580904 + 0.10726163503104613 + 0.10726498643074919 + 0.10726833788492081 + 0.10727168939356353 + 0.1072750409566802 + 0.10727839257427323 + 0.10728174424634536 + 0.10728509597289917 + 0.10728844775393739 + 0.10729179958946247 + 0.10729515147947707 + 0.10729850342398389 + 0.10730185542298538 + 0.10730520747648435 + 0.10730855958448333 + 0.10731191174698497 + 0.10731526396399189 + 0.10731861623550656 + 0.10732196856153192 + 0.10732532094207037 + 0.10732867337712458 + 0.10733202586669714 + 0.10733537841079065 + 0.10733873100940784 + 0.10734208366255128 + 0.10734543637022351 + 0.10734878913242724 + 0.10735214194916511 + 0.10735549482043959 + 0.10735884774625359 + 0.10736220072660947 + 0.10736555376150993 + 0.10736890685095764 + 0.10737225999495516 + 0.10737561319350512 + 0.10737896644661016 + 0.10738231975427301 + 0.10738567311649609 + 0.10738902653328211 + 0.10739238000463376 + 0.10739573353055365 + 0.10739908711104436 + 0.10740244074610837 + 0.10740579443574849 + 0.10740914817996737 + 0.10741250197876762 + 0.10741585583215167 + 0.10741920974012237 + 0.1074225637026823 + 0.1074259177198339 + 0.1074292717915801 + 0.10743262591792335 + 0.10743598009886621 + 0.1074393343344115 + 0.10744268862456155 + 0.10744604296931924 + 0.10744939736868712 + 0.10745275182266789 + 0.10745610633126405 + 0.1074594608944784 + 0.10746281551231324 + 0.1074661701847715 + 0.10746952491185577 + 0.10747287969356857 + 0.10747623452991262 + 0.10747958942089039 + 0.10748294436650463 + 0.10748629936675795 + 0.10748965442165295 + 0.10749300953119234 + 0.10749636469537871 + 0.10749971991421463 + 0.10750307518770275 + 0.10750643051584582 + 0.10750978589864614 + 0.10751314133610683 + 0.10751649682822999 + 0.1075198523750187 + 0.10752320797647527 + 0.10752656363260248 + 0.10752991934340297 + 0.10753327510887938 + 0.10753663092903411 + 0.1075399868038702 + 0.10754334273338985 + 0.10754669871759591 + 0.10755005475649097 + 0.10755341085007768 + 0.10755676699835878 + 0.10756012320133668 + 0.10756347945901409 + 0.1075668357713937 + 0.10757019213847811 + 0.10757354856026988 + 0.10757690503677166 + 0.10758026156798627 + 0.10758361815391616 + 0.10758697479456393 + 0.10759033148993216 + 0.10759368824002377 + 0.10759704504484119 + 0.10760040190438704 + 0.10760375881866387 + 0.10760711578767461 + 0.10761047281142151 + 0.10761382988990753 + 0.10761718702313508 + 0.10762054421110695 + 0.10762390145382582 + 0.10762725875129399 + 0.1076306161035144 + 0.10763397351048958 + 0.10763733097222204 + 0.10764068848871473 + 0.10764404605997011 + 0.10764740368599056 + 0.10765076136677905 + 0.10765411910233826 + 0.10765747689267058 + 0.10766083473777874 + 0.10766419263766533 + 0.107667550592333 + 0.10767090860178452 + 0.10767426666602227 + 0.10767762478504916 + 0.10768098295886765 + 0.10768434118748037 + 0.10768769947088994 + 0.10769105780909914 + 0.10769441620211051 + 0.10769777464992658 + 0.10770113315255023 + 0.10770449170998396 + 0.10770785032223032 + 0.10771120898929208 + 0.10771456771117172 + 0.1077179264878721 + 0.1077212853193957 + 0.10772464420574514 + 0.10772800314692312 + 0.10773136214293232 + 0.10773472119377522 + 0.10773808029945459 + 0.10774143945997311 + 0.10774479867533324 + 0.10774815794553756 + 0.10775151727058911 + 0.10775487665049015 + 0.10775823608524347 + 0.10776159557485163 + 0.10776495511931725 + 0.10776831471864316 + 0.10777167437283183 + 0.10777503408188593 + 0.10777839384580806 + 0.10778175366460083 + 0.107785113538267 + 0.10778847346680932 + 0.10779183345023002 + 0.10779519348853199 + 0.10779855358171801 + 0.10780191372979049 + 0.10780527393275206 + 0.10780863419060545 + 0.10781199450335349 + 0.10781535487099835 + 0.10781871529354305 + 0.10782207577099008 + 0.1078254363033422 + 0.10782879689060186 + 0.10783215753277174 + 0.10783551822985461 + 0.1078388789818531 + 0.10784223978876969 + 0.10784560065060715 + 0.10784896156736815 + 0.10785232253905525 + 0.10785568356567106 + 0.10785904464721832 + 0.10786240578369946 + 0.10786576697511736 + 0.10786912822147461 + 0.10787248952277383 + 0.10787585087901766 + 0.10787921229020861 + 0.10788257375634952 + 0.10788593527744289 + 0.10788929685349154 + 0.1078926584844979 + 0.10789602017046473 + 0.10789938191139471 + 0.10790274370729022 + 0.10790610555815426 + 0.1079094674639894 + 0.10791282942479802 + 0.107916191440583 + 0.1079195535113469 + 0.10792291563709235 + 0.10792627781782214 + 0.10792964005353854 + 0.10793300234424463 + 0.10793636468994286 + 0.10793972709063589 + 0.10794308954632634 + 0.10794645205701674 + 0.10794981462271007 + 0.10795317724340875 + 0.10795653991911525 + 0.10795990264983264 + 0.1079632654355631 + 0.10796662827630953 + 0.10796999117207469 + 0.10797335412286103 + 0.10797671712867121 + 0.10798008018950785 + 0.10798344330537371 + 0.10798680647627133 + 0.10799016970220356 + 0.10799353298317278 + 0.10799689631918163 + 0.108000259710233 + 0.1080036231563293 + 0.10800698665747337 + 0.10801035021366766 + 0.10801371382491505 + 0.10801707749121793 + 0.1080204412125791 + 0.1080238049890013 + 0.10802716882048689 + 0.10803053270703879 + 0.10803389664865939 + 0.10803726064535153 + 0.10804062469711791 + 0.10804398880396093 + 0.10804735296588347 + 0.108050717182888 + 0.10805408145497733 + 0.10805744578215401 + 0.1080608101644206 + 0.10806417460177997 + 0.10806753909423471 + 0.10807090364178729 + 0.10807426824444057 + 0.108077632902197 + 0.10808099761505925 + 0.10808436238303031 + 0.10808772720611247 + 0.10809109208430839 + 0.1080944570176208 + 0.1080978220060524 + 0.10810118704960583 + 0.10810455214828374 + 0.10810791730208859 + 0.10811128251102323 + 0.10811464777509033 + 0.10811801309429235 + 0.10812137846863214 + 0.10812474389811236 + 0.10812810938273545 + 0.10813147492250409 + 0.10813484051742106 + 0.10813820616748905 + 0.10814157187271062 + 0.10814493763308837 + 0.10814830344862499 + 0.10815166931932307 + 0.10815503524518548 + 0.10815840122621477 + 0.10816176726241335 + 0.10816513335378422 + 0.10816849950032986 + 0.10817186570205296 + 0.10817523195895604 + 0.10817859827104197 + 0.10818196463831328 + 0.10818533106077251 + 0.10818869753842257 + 0.10819206407126597 + 0.10819543065930527 + 0.10819879730254338 + 0.10820216400098273 + 0.10820553075462598 + 0.10820889756347582 + 0.10821226442753501 + 0.10821563134680606 + 0.10821899832129175 + 0.10822236535099457 + 0.10822573243591735 + 0.10822909957606269 + 0.10823246677143315 + 0.10823583402203144 + 0.10823920132786016 + 0.108242568688922 + 0.10824593610521971 + 0.10824930357675595 + 0.10825267110353311 + 0.1082560386855542 + 0.10825940632282161 + 0.10826277401533818 + 0.10826614176310627 + 0.10826950956612888 + 0.10827287742440843 + 0.1082762453379478 + 0.10827961330674944 + 0.10828298133081604 + 0.10828634941015038 + 0.10828971754475487 + 0.10829308573463248 + 0.10829645397978566 + 0.10829982228021699 + 0.10830319063592936 + 0.10830655904692532 + 0.10830992751320753 + 0.10831329603477848 + 0.10831666461164113 + 0.10832003324379802 + 0.10832340193125164 + 0.10832677067400498 + 0.10833013947206034 + 0.10833350832542053 + 0.10833687723408815 + 0.10834024619806602 + 0.10834361521735678 + 0.10834698429196292 + 0.10835035342188706 + 0.10835372260713222 + 0.10835709184770054 + 0.10836046114359514 + 0.10836383049481844 + 0.10836719990137304 + 0.10837056936326184 + 0.10837393888048738 + 0.10837730845305231 + 0.10838067808095929 + 0.10838404776421086 + 0.10838741750280974 + 0.10839078729675881 + 0.1083941571460605 + 0.10839752705071756 + 0.10840089701073261 + 0.10840426702610816 + 0.10840763709684723 + 0.10841100722295215 + 0.10841437740442578 + 0.10841774764127063 + 0.10842111793348945 + 0.10842448828108495 + 0.10842785868405959 + 0.10843122914241615 + 0.10843459965615761 + 0.10843797022528606 + 0.10844134084980443 + 0.10844471152971534 + 0.10844808226502166 + 0.10845145305572579 + 0.10845482390183044 + 0.10845819480333836 + 0.10846156576025215 + 0.10846493677257443 + 0.10846830784030798 + 0.10847167896345539 + 0.10847505014201929 + 0.10847842137600236 + 0.10848179266540736 + 0.10848516401023683 + 0.10848853541049346 + 0.10849190686618 + 0.10849527837729903 + 0.10849864994385323 + 0.10850202156584517 + 0.10850539324327757 + 0.10850876497615335 + 0.10851213676447473 + 0.10851550860824462 + 0.10851888050746572 + 0.10852225246214059 + 0.10852562447227186 + 0.10852899653786234 + 0.10853236865891469 + 0.10853574083543142 + 0.10853911306741526 + 0.10854248535486878 + 0.10854585769779496 + 0.1085492300961963 + 0.10855260255007521 + 0.10855597505943464 + 0.10855934762427716 + 0.10856272024460559 + 0.10856609292042234 + 0.10856946565173022 + 0.1085728384385319 + 0.10857621128082984 + 0.10857958417862706 + 0.10858295713192596 + 0.10858633014072956 + 0.10858970320503995 + 0.10859307632486029 + 0.10859644950019295 + 0.1085998227310407 + 0.10860319601740639 + 0.10860656935929233 + 0.10860994275670141 + 0.10861331620963627 + 0.10861668971809947 + 0.10862006328209388 + 0.10862343690162203 + 0.1086268105766867 + 0.1086301843072903 + 0.10863355809343575 + 0.10863693193512568 + 0.10864030583236255 + 0.10864367978514941 + 0.10864705379348853 + 0.10865042785738285 + 0.10865380197683498 + 0.10865717615184742 + 0.10866055038242314 + 0.10866392466856443 + 0.10866729901027422 + 0.10867067340755523 + 0.10867404786041004 + 0.10867742236884129 + 0.1086807969328516 + 0.10868417155244371 + 0.10868754622762021 + 0.10869092095838394 + 0.10869429574473752 + 0.10869767058668341 + 0.10870104548422457 + 0.10870442043736347 + 0.1087077954461029 + 0.10871117051044545 + 0.10871454563039386 + 0.10871792080595069 + 0.10872129603711868 + 0.1087246713239006 + 0.10872804666629898 + 0.10873142206431655 + 0.10873479751795585 + 0.10873817302721975 + 0.10874154859211088 + 0.10874492421263181 + 0.10874829988878522 + 0.10875167562057388 + 0.10875505140800049 + 0.10875842725106762 + 0.10876180314977787 + 0.10876517910413402 + 0.10876855511413873 + 0.10877193117979476 + 0.1087753073011046 + 0.1087786834780711 + 0.10878205971069677 + 0.10878543599898439 + 0.10878881234293664 + 0.10879218874255613 + 0.1087955651978455 + 0.10879894170880762 + 0.10880231827544498 + 0.10880569489776025 + 0.10880907157575605 + 0.10881244830943533 + 0.10881582509880058 + 0.10881920194385454 + 0.10882257884459967 + 0.10882595580103893 + 0.10882933281317476 + 0.10883270988100997 + 0.10883608700454726 + 0.1088394641837892 + 0.10884284141873858 + 0.10884621870939798 + 0.10884959605577009 + 0.10885297345785759 + 0.10885635091566323 + 0.10885972842918949 + 0.10886310599843932 + 0.10886648362341519 + 0.10886986130411985 + 0.10887323904055603 + 0.10887661683272633 + 0.10887999468063322 + 0.10888337258427976 + 0.10888675054366852 + 0.10889012855880198 + 0.10889350662968308 + 0.10889688475631426 + 0.10890026293869834 + 0.10890364117683794 + 0.10890701947073585 + 0.10891039782039459 + 0.1089137762258169 + 0.10891715468700552 + 0.10892053320396303 + 0.10892391177669204 + 0.10892729040519536 + 0.10893066908947573 + 0.10893404782953571 + 0.10893742662537796 + 0.10894080547700526 + 0.10894418438442026 + 0.10894756334762563 + 0.10895094236662403 + 0.10895432144141799 + 0.10895770057201036 + 0.10896107975840393 + 0.10896445900060117 + 0.10896783829860489 + 0.10897121765241763 + 0.10897459706204227 + 0.10897797652748123 + 0.10898135604873743 + 0.10898473562581343 + 0.1089881152587119 + 0.10899149494743555 + 0.10899487469198713 + 0.10899825449236918 + 0.10900163434858444 + 0.10900501426063561 + 0.10900839422852542 + 0.10901177425225643 + 0.10901515433183145 + 0.10901853446725308 + 0.10902191465852401 + 0.10902529490564693 + 0.1090286752086245 + 0.10903205556745936 + 0.10903543598215432 + 0.10903881645271199 + 0.10904219697913506 + 0.10904557756142616 + 0.10904895819958813 + 0.10905233889362348 + 0.1090557196435349 + 0.10905910044932521 + 0.10906248131099687 + 0.10906586222855283 + 0.10906924320199567 + 0.10907262423132801 + 0.1090760053165524 + 0.10907938645767191 + 0.10908276765468886 + 0.10908614890760618 + 0.10908953021642641 + 0.10909291158115228 + 0.10909629300178642 + 0.10909967447833163 + 0.10910305601079039 + 0.10910643759916573 + 0.10910981924346004 + 0.10911320094367599 + 0.10911658269981643 + 0.10911996451188398 + 0.10912334637988129 + 0.10912672830381119 + 0.1091301102836761 + 0.10913349231947901 + 0.10913687441122231 + 0.10914025655890884 + 0.10914363876254136 + 0.10914702102212237 + 0.10915040333765466 + 0.10915378570914093 + 0.10915716813658383 + 0.10916055061998609 + 0.10916393315935034 + 0.10916731575467924 + 0.10917069840597568 + 0.1091740811132421 + 0.10917746387648124 + 0.10918084669569587 + 0.10918422957088869 + 0.10918761250206221 + 0.10919099548921936 + 0.10919437853236255 + 0.10919776163149472 + 0.10920114478661853 + 0.10920452799773644 + 0.10920791126485127 + 0.10921129458796584 + 0.10921467796708263 + 0.10921806140220459 + 0.10922144489333412 + 0.109224828440474 + 0.10922821204362701 + 0.10923159570279574 + 0.10923497941798295 + 0.10923836318919139 + 0.10924174701642352 + 0.10924513089968224 + 0.10924851483897008 + 0.10925189883428985 + 0.10925528288564418 + 0.10925866699303577 + 0.10926205115646748 + 0.10926543537594166 + 0.10926881965146119 + 0.10927220398302877 + 0.10927558837064716 + 0.10927897281431877 + 0.10928235731404665 + 0.10928574186983316 + 0.10928912648168121 + 0.10929251114959336 + 0.10929589587357254 + 0.10929928065362111 + 0.10930266548974205 + 0.10930605038193779 + 0.10930943533021123 + 0.10931282033456501 + 0.10931620539500174 + 0.10931959051152415 + 0.10932297568413502 + 0.10932636091283687 + 0.10932974619763258 + 0.10933313153852464 + 0.10933651693551585 + 0.10933990238860913 + 0.10934328789780676 + 0.1093466734631116 + 0.10935005908452644 + 0.10935344476205397 + 0.10935683049569656 + 0.10936021628545731 + 0.10936360213133882 + 0.1093669880333436 + 0.10937037399147446 + 0.10937376000573418 + 0.10937714607612534 + 0.10938053220265058 + 0.10938391838531267 + 0.10938730462411438 + 0.10939069091905843 + 0.10939407727014727 + 0.10939746367738376 + 0.10940085014077051 + 0.10940423666031032 + 0.10940762323600584 + 0.10941100986785982 + 0.10941439655587491 + 0.10941778330005367 + 0.10942117010039897 + 0.1094245569569135 + 0.10942794386960004 + 0.10943133083846093 + 0.10943471786349919 + 0.1094381049447174 + 0.10944149208211822 + 0.10944487927570448 + 0.10944826652547873 + 0.10945165383144374 + 0.10945504119360228 + 0.10945842861195684 + 0.10946181608651027 + 0.10946520361726525 + 0.1094685912042245 + 0.10947197884739071 + 0.10947536654676637 + 0.10947875430235446 + 0.10948214211415756 + 0.10948552998217843 + 0.10948891790641974 + 0.10949230588688405 + 0.10949569392357421 + 0.10949908201649294 + 0.10950247016564273 + 0.1095058583710265 + 0.10950924663264683 + 0.10951263495050649 + 0.10951602332460815 + 0.10951941175495455 + 0.10952280024154823 + 0.10952618878439208 + 0.10952957738348872 + 0.10953296603884081 + 0.10953635475045101 + 0.10953974351832224 + 0.10954313234245704 + 0.10954652122285807 + 0.10954991015952806 + 0.10955329915246971 + 0.10955668820168582 + 0.10956007730717898 + 0.109563466468952 + 0.10956685568700728 + 0.10957024496134797 + 0.10957363429197652 + 0.10957702367889562 + 0.10958041312210788 + 0.10958380262161616 + 0.10958719217742331 + 0.10959058178953171 + 0.10959397145794415 + 0.10959736118266344 + 0.10960075096369219 + 0.10960414080103308 + 0.109607530694689 + 0.10961092064466253 + 0.1096143106509562 + 0.10961770071357295 + 0.10962109083251527 + 0.10962448100778609 + 0.10962787123938803 + 0.10963126152732366 + 0.10963465187159603 + 0.1096380422722074 + 0.10964143272916081 + 0.10964482324245869 + 0.10964821381210393 + 0.10965160443809926 + 0.10965499512044724 + 0.10965838585915069 + 0.10966177665421221 + 0.10966516750563453 + 0.10966855841342046 + 0.10967194937757266 + 0.10967534039809379 + 0.10967873147498657 + 0.10968212260825359 + 0.10968551379789777 + 0.1096889050439217 + 0.10969229634632809 + 0.10969568770511956 + 0.10969907912029898 + 0.10970247059186906 + 0.10970586211983226 + 0.10970925370419161 + 0.10971264534494936 + 0.10971603704210876 + 0.10971942879567223 + 0.1097228206056424 + 0.10972621247202209 + 0.10972960439481402 + 0.10973299637402101 + 0.10973638840964543 + 0.10973978050169034 + 0.10974317265015809 + 0.10974656485505185 + 0.10974995711637396 + 0.10975334943412712 + 0.10975674180831432 + 0.10976013423893792 + 0.10976352672600088 + 0.10976691926950587 + 0.10977031186945543 + 0.10977370452585246 + 0.10977709723869961 + 0.10978049000799958 + 0.10978388283375511 + 0.1097872757159687 + 0.1097906686546435 + 0.10979406164978175 + 0.10979745470138638 + 0.10980084780946009 + 0.10980424097400551 + 0.10980763419502547 + 0.10981102747252257 + 0.1098144208064997 + 0.10981781419695937 + 0.10982120764390416 + 0.10982460114733715 + 0.10982799470726089 + 0.10983138832367799 + 0.10983478199659132 + 0.10983817572600341 + 0.10984156951191711 + 0.10984496335433505 + 0.10984835725325999 + 0.10985175120869467 + 0.10985514522064181 + 0.10985853928910388 + 0.10986193341408385 + 0.10986532759558448 + 0.10986872183360825 + 0.10987211612815798 + 0.10987551047923635 + 0.10987890488684615 + 0.10988229935099007 + 0.1098856938716707 + 0.10988908844889081 + 0.1098924830826533 + 0.10989587777296073 + 0.10989927251981557 + 0.10990266732322089 + 0.10990606218317937 + 0.10990945709969348 + 0.10991285207276619 + 0.10991624710240012 + 0.1099196421885979 + 0.10992303733136224 + 0.10992643253069606 + 0.10992982778660187 + 0.10993322309908243 + 0.10993661846814048 + 0.10994001389377875 + 0.10994340937599989 + 0.10994680491480664 + 0.10995020051020177 + 0.10995359616218799 + 0.10995699187076775 + 0.10996038763594414 + 0.10996378345771973 + 0.10996717933609718 + 0.10997057527107927 + 0.10997397126266877 + 0.10997736731086803 + 0.1099807634156803 + 0.10998415957710787 + 0.10998755579515369 + 0.1099909520698204 + 0.10999434840111079 + 0.10999774478902749 + 0.11000114123357316 + 0.11000453773475061 + 0.11000793429256263 + 0.11001133090701172 + 0.11001472757810069 + 0.11001812430583234 + 0.1100215210902093 + 0.1100249179312344 + 0.11002831482891018 + 0.11003171178323957 + 0.11003510879422497 + 0.11003850586186936 + 0.11004190298617536 + 0.11004530016714577 + 0.11004869740478318 + 0.11005209469909041 + 0.11005549205007012 + 0.11005888945772493 + 0.11006228692205791 + 0.11006568444307135 + 0.11006908202076822 + 0.11007247965515128 + 0.110075877346223 + 0.11007927509398628 + 0.11008267289844371 + 0.11008607075959811 + 0.11008946867745238 + 0.11009286665200889 + 0.11009626468327043 + 0.11009966277123986 + 0.11010306091591993 + 0.11010645911731309 + 0.11010985737542245 + 0.11011325569025042 + 0.11011665406179975 + 0.11012005249007331 + 0.1101234509750736 + 0.11012684951680361 + 0.11013024811526585 + 0.11013364677046307 + 0.11013704548239803 + 0.1101404442510735 + 0.1101438430764921 + 0.11014724195865666 + 0.11015064089756971 + 0.11015403989323419 + 0.11015743894565282 + 0.110160838054828 + 0.11016423722076282 + 0.11016763644345984 + 0.11017103572292179 + 0.11017443505915137 + 0.11017783445215135 + 0.11018123390192451 + 0.11018463340847338 + 0.11018803297180078 + 0.11019143259190951 + 0.11019483226880231 + 0.11019823200248167 + 0.11020163179295041 + 0.1102050316402115 + 0.11020843154426742 + 0.11021183150512086 + 0.11021523152277461 + 0.11021863159723141 + 0.11022203172849405 + 0.11022543191656506 + 0.11022883216144738 + 0.11023223246314356 + 0.11023563282165653 + 0.11023903323698868 + 0.11024243370914305 + 0.1102458342381222 + 0.11024923482392902 + 0.110252635466566 + 0.11025603616603598 + 0.11025943692234169 + 0.11026283773548592 + 0.11026623860547122 + 0.11026963953230033 + 0.11027304051597629 + 0.1102764415565015 + 0.11027984265387868 + 0.11028324380811071 + 0.11028664501920023 + 0.11029004628715008 + 0.11029344761196284 + 0.11029684899364131 + 0.11030025043218809 + 0.11030365192760604 + 0.11030705347989803 + 0.11031045508906641 + 0.1103138567551141 + 0.11031725847804397 + 0.11032066025785854 + 0.1103240620945606 + 0.11032746398815292 + 0.1103308659386382 + 0.1103342679460191 + 0.11033767001029843 + 0.11034107213147885 + 0.11034447430956316 + 0.11034787654455394 + 0.11035127883645425 + 0.11035468118526635 + 0.11035808359099333 + 0.11036148605363774 + 0.11036488857320256 + 0.1103682911496902 + 0.11037169378310349 + 0.11037509647344509 + 0.11037849922071792 + 0.11038190202492472 + 0.11038530488606781 + 0.11038870780415042 + 0.11039211077917514 + 0.11039551381114432 + 0.11039891690006129 + 0.11040232004592844 + 0.11040572324874846 + 0.11040912650852421 + 0.1104125298252583 + 0.11041593319895367 + 0.11041933662961279 + 0.1104227401172386 + 0.11042614366183363 + 0.11042954726340075 + 0.11043295092194268 + 0.11043635463746218 + 0.11043975840996199 + 0.11044316223944459 + 0.11044656612591301 + 0.11044997006936978 + 0.11045337406981783 + 0.11045677812725976 + 0.11046018224169825 + 0.11046358641313624 + 0.11046699064157621 + 0.11047039492702108 + 0.11047379926947329 + 0.1104772036689361 + 0.11048060812541181 + 0.11048401263890321 + 0.11048741720941309 + 0.11049082183694431 + 0.11049422652149934 + 0.1104976312630811 + 0.11050103606169225 + 0.11050444091733549 + 0.11050784583001377 + 0.1105112507997295 + 0.11051465582648563 + 0.11051806091028482 + 0.11052146605112978 + 0.11052487124902337 + 0.11052827650396818 + 0.11053168181596698 + 0.11053508718502253 + 0.11053849261113745 + 0.11054189809431469 + 0.11054530363455685 + 0.11054870923186672 + 0.11055211488624693 + 0.11055552059770038 + 0.11055892636622956 + 0.11056233219183745 + 0.11056573807452652 + 0.11056914401429989 + 0.11057255001115998 + 0.11057595606510949 + 0.11057936217615147 + 0.11058276834428839 + 0.11058617456952304 + 0.11058958085185809 + 0.11059298719129662 + 0.11059639358784089 + 0.11059980004149401 + 0.11060320655225833 + 0.11060661312013695 + 0.1106100197451325 + 0.11061342642724768 + 0.11061683316648513 + 0.11062023996284767 + 0.11062364681633814 + 0.11062705372695919 + 0.11063046069471361 + 0.110633867719604 + 0.11063727480163309 + 0.11064068194080388 + 0.11064408913711886 + 0.11064749639058073 + 0.11065090370119254 + 0.11065431106895667 + 0.11065771849387622 + 0.1106611259759535 + 0.11066453351519154 + 0.11066794111159295 + 0.11067134876516052 + 0.11067475647589707 + 0.11067816424380533 + 0.11068157206888786 + 0.11068497995114743 + 0.11068838789058694 + 0.11069179588720905 + 0.11069520394101655 + 0.11069861205201198 + 0.11070202022019844 + 0.11070542844557826 + 0.11070883672815439 + 0.11071224506792955 + 0.11071565346490646 + 0.11071906191908801 + 0.11072247043047663 + 0.11072587899907528 + 0.11072928762488672 + 0.1107326963079137 + 0.11073610504815878 + 0.11073951384562462 + 0.11074292270031438 + 0.11074633161223055 + 0.11074974058137581 + 0.11075314960775309 + 0.11075655869136497 + 0.11075996783221412 + 0.11076337703030359 + 0.11076678628563573 + 0.11077019559821366 + 0.1107736049680399 + 0.11077701439511717 + 0.11078042387944838 + 0.11078383342103604 + 0.11078724301988324 + 0.11079065267599227 + 0.11079406238936616 + 0.11079747216000774 + 0.11080088198791947 + 0.11080429187310427 + 0.11080770181556471 + 0.11081111181530381 + 0.11081452187232421 + 0.11081793198662857 + 0.11082134215821966 + 0.11082475238710011 + 0.11082816267327299 + 0.11083157301674076 + 0.11083498341750639 + 0.11083839387557239 + 0.1108418043909415 + 0.11084521496361668 + 0.11084862559360051 + 0.11085203628089579 + 0.11085544702550516 + 0.11085885782743152 + 0.11086226868667766 + 0.1108656796032461 + 0.11086909057713967 + 0.11087250160836126 + 0.1108759126969134 + 0.110879323842799 + 0.11088273504602073 + 0.11088614630658135 + 0.11088955762448365 + 0.11089296899973022 + 0.11089638043232389 + 0.11089979192226757 + 0.11090320346956377 + 0.11090661507421538 + 0.11091002673622501 + 0.11091343845559555 + 0.11091685023232974 + 0.11092026206643014 + 0.11092367395789973 + 0.11092708590674115 + 0.11093049791295724 + 0.11093390997655064 + 0.11093732209752387 + 0.11094073427588012 + 0.11094414651162206 + 0.11094755880475209 + 0.11095097115527328 + 0.11095438356318832 + 0.11095779602849985 + 0.11096120855121067 + 0.11096462113132358 + 0.11096803376884135 + 0.11097144646376668 + 0.11097485921610241 + 0.110978272025851 + 0.11098168489301544 + 0.11098509781759838 + 0.11098851079960266 + 0.11099192383903103 + 0.11099533693588631 + 0.11099875009017099 + 0.11100216330188793 + 0.11100557657104004 + 0.11100898989762978 + 0.11101240328166022 + 0.11101581672313379 + 0.11101923022205347 + 0.11102264377842191 + 0.11102605739224204 + 0.11102947106351635 + 0.11103288479224774 + 0.11103629857843889 + 0.1110397124220925 + 0.11104312632321153 + 0.11104654028179856 + 0.11104995429785644 + 0.11105336837138777 + 0.11105678250239538 + 0.11106019669088218 + 0.1110636109368506 + 0.11106702524030365 + 0.11107043960124399 + 0.1110738540196744 + 0.11107726849559757 + 0.11108068302901644 + 0.11108409761993349 + 0.11108751226835167 + 0.11109092697427356 + 0.11109434173770212 + 0.11109775655863997 + 0.1111011714370899 + 0.11110458637305458 + 0.11110800136653691 + 0.11111141641753959 + 0.11111483152606531 + 0.11111824669211687 + 0.11112166191569707 + 0.11112507719680845 + 0.11112849253545407 + 0.11113190793163646 + 0.11113532338535845 + 0.11113873889662296 + 0.11114215446543241 + 0.11114557009178971 + 0.11114898577569779 + 0.11115240151715905 + 0.11115581731617656 + 0.11115923317275296 + 0.11116264908689097 + 0.11116606505859331 + 0.11116948108786284 + 0.11117289717470231 + 0.11117631331911443 + 0.11117972952110189 + 0.1111831457806674 + 0.11118656209781415 + 0.11118997847254444 + 0.11119339490486113 + 0.11119681139476696 + 0.11120022794226482 + 0.11120364454735726 + 0.11120706121004721 + 0.11121047793033748 + 0.11121389470823061 + 0.11121731154372962 + 0.11122072843683696 + 0.11122414538755557 + 0.11122756239588827 + 0.11123097946183758 + 0.11123439658540639 + 0.11123781376659761 + 0.11124123100541378 + 0.11124464830185771 + 0.1112480656559322 + 0.11125148306764003 + 0.11125490053698379 + 0.11125831806396642 + 0.11126173564859071 + 0.1112651532908593 + 0.11126857099077495 + 0.11127198874834048 + 0.11127540656355858 + 0.111278824436432 + 0.11128224236696352 + 0.111285660355156 + 0.1112890784010121 + 0.1112924965045346 + 0.11129591466572633 + 0.11129933288458983 + 0.11130275116112805 + 0.11130616949534367 + 0.11130958788723957 + 0.11131300633681838 + 0.11131642484408301 + 0.11131984340903597 + 0.11132326203168022 + 0.11132668071201847 + 0.11133009945005334 + 0.11133351824578799 + 0.11133693709922479 + 0.11134035601036657 + 0.11134377497921626 + 0.1113471940057764 + 0.11135061309004987 + 0.11135403223203957 + 0.11135745143174797 + 0.11136087068917801 + 0.11136429000433239 + 0.11136770937721388 + 0.11137112880782532 + 0.1113745482961693 + 0.11137796784224875 + 0.11138138744606649 + 0.11138480710762509 + 0.11138822682692728 + 0.11139164660397601 + 0.11139506643877405 + 0.11139848633132383 + 0.11140190628162859 + 0.1114053262896908 + 0.11140874635551332 + 0.11141216647909885 + 0.11141558666045005 + 0.11141900689956999 + 0.11142242719646123 + 0.11142584755112644 + 0.11142926796356868 + 0.11143268843379044 + 0.11143610896179457 + 0.11143952954758385 + 0.11144295019116107 + 0.11144637089252886 + 0.11144979165169029 + 0.11145321246864778 + 0.1114566333434043 + 0.11146005427596246 + 0.11146347526632518 + 0.11146689631449522 + 0.11147031742047527 + 0.11147373858426805 + 0.11147715980587634 + 0.111480581085303 + 0.11148400242255077 + 0.11148742381762246 + 0.11149084527052062 + 0.11149426678124834 + 0.11149768834980811 + 0.11150110997620277 + 0.11150453166043522 + 0.11150795340250796 + 0.11151137520242405 + 0.11151479706018605 + 0.11151821897579675 + 0.11152164094925919 + 0.11152506298057585 + 0.11152848506974931 + 0.11153190721678277 + 0.11153532942167883 + 0.11153875168444027 + 0.11154217400506977 + 0.11154559638357003 + 0.11154901881994428 + 0.11155244131419473 + 0.11155586386632436 + 0.11155928647633599 + 0.11156270914423233 + 0.11156613187001625 + 0.1115695546536903 + 0.11157297749525749 + 0.11157640039472036 + 0.11157982335208194 + 0.11158324636734478 + 0.11158666944051171 + 0.11159009257158554 + 0.11159351576056906 + 0.11159693900746488 + 0.11160036231227598 + 0.11160378567500498 + 0.11160720909565479 + 0.11161063257422806 + 0.1116140561107276 + 0.11161747970515613 + 0.11162090335751645 + 0.11162432706781131 + 0.11162775083604359 + 0.11163117466221599 + 0.11163459854633126 + 0.11163802248839216 + 0.11164144648840155 + 0.11164487054636203 + 0.11164829466227659 + 0.1116517188361479 + 0.11165514306797872 + 0.11165856735777173 + 0.11166199170552982 + 0.11166541611125577 + 0.1116688405749523 + 0.11167226509662218 + 0.11167568967626824 + 0.11167911431389323 + 0.11168253900949988 + 0.11168596376309085 + 0.11168938857466935 + 0.11169281344423766 + 0.11169623837179879 + 0.1116996633573554 + 0.11170308840091039 + 0.11170651350246642 + 0.11170993866202637 + 0.11171336387959291 + 0.11171678915516893 + 0.11172021448875703 + 0.11172363988036028 + 0.1117270653299811 + 0.11173049083762247 + 0.11173391640328713 + 0.11173734202697787 + 0.11174076770869752 + 0.11174419344844862 + 0.11174761924623412 + 0.11175104510205688 + 0.11175447101591958 + 0.11175789698782473 + 0.11176132301777555 + 0.11176474910577473 + 0.11176817525182474 + 0.11177160145592864 + 0.11177502771808913 + 0.11177845403830894 + 0.1117818804165909 + 0.11178530685293774 + 0.1117887333473523 + 0.11179215989983729 + 0.11179558651039555 + 0.11179901317902981 + 0.11180243990574282 + 0.11180586669053734 + 0.1118092935334163 + 0.1118127204343824 + 0.1118161473934383 + 0.11181957441058692 + 0.11182300148583098 + 0.11182642861917316 + 0.11182985581061643 + 0.11183328306016356 + 0.11183671036781705 + 0.11184013773357991 + 0.11184356515745499 + 0.11184699263944491 + 0.11185042017955252 + 0.11185384777778068 + 0.11185727543413189 + 0.11186070314860917 + 0.11186413092121511 + 0.11186755875195267 + 0.11187098664082466 + 0.11187441458783372 + 0.11187784259298263 + 0.11188127065627414 + 0.1118846987777113 + 0.11188812695729655 + 0.11189155519503277 + 0.11189498349092299 + 0.11189841184496951 + 0.1119018402571756 + 0.11190526872754361 + 0.11190869725607665 + 0.11191212584277735 + 0.11191555448764849 + 0.11191898319069292 + 0.11192241195191346 + 0.11192584077131264 + 0.11192926964889345 + 0.11193269858465868 + 0.11193612757861102 + 0.11193955663075329 + 0.11194298574108826 + 0.11194641490961887 + 0.11194984413634747 + 0.11195327342127738 + 0.11195670276441103 + 0.11196013216575124 + 0.11196356162530098 + 0.11196699114306272 + 0.11197042071903968 + 0.11197385035323412 + 0.11197728004564933 + 0.11198070979628749 + 0.11198413960515208 + 0.11198756947224535 + 0.11199099939757039 + 0.11199442938112991 + 0.1119978594229265 + 0.1120012895229632 + 0.11200471968124272 + 0.11200814989776768 + 0.11201158017254111 + 0.11201501050556562 + 0.11201844089684404 + 0.11202187134637921 + 0.11202530185417382 + 0.11202873242023068 + 0.11203216304455267 + 0.11203559372714252 + 0.11203902446800292 + 0.1120424552671367 + 0.1120458861245468 + 0.11204931704023574 + 0.11205274801420663 + 0.11205617904646184 + 0.11205961013700445 + 0.1120630412858373 + 0.11206647249296291 + 0.11206990375838424 + 0.11207333508210408 + 0.1120767664641252 + 0.11208019790445033 + 0.11208362940308225 + 0.11208706096002384 + 0.11209049257527783 + 0.11209392424884698 + 0.11209735598073413 + 0.11210078777094193 + 0.11210421961947351 + 0.11210765152633126 + 0.11211108349151812 + 0.1121145155150369 + 0.1121179475968903 + 0.11212137973708132 + 0.11212481193561266 + 0.11212824419248693 + 0.112131676507707 + 0.11213510888127572 + 0.11213854131319589 + 0.11214197380347024 + 0.11214540635210166 + 0.11214883895909275 + 0.11215227162444648 + 0.11215570434816551 + 0.11215913713025273 + 0.1121625699707109 + 0.11216600286954279 + 0.11216943582675107 + 0.11217286884233872 + 0.11217630191630845 + 0.11217973504866308 + 0.11218316823940543 + 0.11218660148853817 + 0.11219003479606413 + 0.11219346816198614 + 0.11219690158630699 + 0.11220033506902957 + 0.11220376861015635 + 0.11220720220969035 + 0.11221063586763437 + 0.11221406958399116 + 0.11221750335876353 + 0.11222093719195424 + 0.11222437108356596 + 0.11222780503360177 + 0.11223123904206431 + 0.11223467310895632 + 0.11223810723428061 + 0.11224154141803994 + 0.11224497566023722 + 0.1122484099608753 + 0.11225184431995669 + 0.11225527873748437 + 0.11225871321346124 + 0.11226214774788978 + 0.11226558234077291 + 0.11226901699211356 + 0.11227245170191445 + 0.1122758864701783 + 0.11227932129690797 + 0.1122827561821063 + 0.11228619112577601 + 0.11228962612791984 + 0.11229306118854046 + 0.11229649630764117 + 0.11229993148522432 + 0.11230336672129282 + 0.11230680201584946 + 0.11231023736889705 + 0.11231367278043837 + 0.11231710825047619 + 0.11232054377901335 + 0.1123239793660526 + 0.11232741501159685 + 0.11233085071564858 + 0.11233428647821099 + 0.11233772229928661 + 0.11234115817887842 + 0.11234459411698899 + 0.11234803011362134 + 0.11235146616877804 + 0.11235490228246213 + 0.1123583384546761 + 0.11236177468542313 + 0.11236521097470557 + 0.11236864732252656 + 0.11237208372888896 + 0.11237552019379508 + 0.11237895671724828 + 0.1123823932992509 + 0.1123858299398061 + 0.11238926663891655 + 0.11239270339658475 + 0.11239614021281392 + 0.11239957708760673 + 0.11240301402096591 + 0.11240645101289433 + 0.11240988806339475 + 0.11241332517246981 + 0.11241676234012254 + 0.11242019956635571 + 0.11242363685117206 + 0.1124270741945743 + 0.11243051159656538 + 0.11243394905714799 + 0.11243738657632497 + 0.1124408241540992 + 0.11244426179047329 + 0.11244769948545028 + 0.11245113723903279 + 0.11245457505122351 + 0.11245801292202552 + 0.11246145085144135 + 0.11246488883947407 + 0.11246832688612633 + 0.11247176499140087 + 0.11247520315530059 + 0.11247864137782826 + 0.11248207965898679 + 0.11248551799877869 + 0.11248895639720712 + 0.11249239485427454 + 0.11249583336998387 + 0.11249927194433808 + 0.11250271057733983 + 0.1125061492689918 + 0.11250958801929703 + 0.11251302682825813 + 0.112516465695878 + 0.11251990462215944 + 0.1125233436071052 + 0.11252678265071803 + 0.11253022175300093 + 0.11253366091395647 + 0.11253710013358766 + 0.11254053941189709 + 0.11254397874888784 + 0.11254741814456237 + 0.11255085759892382 + 0.11255429711197458 + 0.11255773668371792 + 0.11256117631415634 + 0.11256461600329276 + 0.11256805575112994 + 0.11257149555767051 + 0.11257493542291766 + 0.11257837534687382 + 0.11258181532954194 + 0.11258525537092499 + 0.1125886954710255 + 0.11259213562984641 + 0.11259557584739054 + 0.11259901612366069 + 0.11260245645865943 + 0.11260589685238989 + 0.11260933730485463 + 0.11261277781605668 + 0.11261621838599876 + 0.11261965901468356 + 0.112623099702114 + 0.11262654044829296 + 0.11262998125322288 + 0.11263342211690702 + 0.11263686303934797 + 0.11264030402054839 + 0.11264374506051139 + 0.1126471861592396 + 0.11265062731673581 + 0.1126540685330029 + 0.11265750980804358 + 0.11266095114186075 + 0.11266439253445708 + 0.11266783398583571 + 0.11267127549599902 + 0.11267471706495001 + 0.1126781586926915 + 0.11268160037922637 + 0.11268504212455728 + 0.11268848392868702 + 0.11269192579161867 + 0.11269536771335456 + 0.11269880969389792 + 0.1127022517332513 + 0.11270569383141765 + 0.11270913598839979 + 0.11271257820420047 + 0.1127160204788224 + 0.11271946281226851 + 0.1127229052045416 + 0.1127263476556445 + 0.11272979016558002 + 0.11273323273435076 + 0.11273667536195989 + 0.1127401180484099 + 0.11274356079370366 + 0.11274700359784415 + 0.11275044646083408 + 0.11275388938267618 + 0.11275733236337325 + 0.11276077540292828 + 0.1127642185013439 + 0.11276766165862299 + 0.11277110487476844 + 0.1127745481497829 + 0.11277799148366931 + 0.11278143487643033 + 0.11278487832806887 + 0.11278832183858772 + 0.11279176540798981 + 0.11279520903627781 + 0.11279865272345442 + 0.11280209646952266 + 0.11280554027448524 + 0.11280898413834502 + 0.11281242806110488 + 0.11281587204276738 + 0.11281931608333558 + 0.11282276018281208 + 0.11282620434119996 + 0.11282964855850179 + 0.11283309283472054 + 0.11283653716985889 + 0.11283998156391969 + 0.11284342601690579 + 0.11284687052882002 + 0.11285031509966503 + 0.11285375972944378 + 0.11285720441815922 + 0.11286064916581377 + 0.11286409397241066 + 0.11286753883795252 + 0.11287098376244206 + 0.11287442874588209 + 0.11287787378827566 + 0.11288131888962551 + 0.11288476404993421 + 0.11288820926920468 + 0.11289165454744003 + 0.11289509988464264 + 0.11289854528081565 + 0.11290199073596185 + 0.11290543625008372 + 0.11290888182318441 + 0.11291232745526662 + 0.11291577314633305 + 0.11291921889638681 + 0.11292266470543043 + 0.1129261105734668 + 0.11292955650049895 + 0.11293300248652927 + 0.11293644853156093 + 0.11293989463559663 + 0.11294334079863913 + 0.11294678702069127 + 0.11295023330175605 + 0.112953679641836 + 0.11295712604093404 + 0.11296057249905313 + 0.11296401901619581 + 0.11296746559236505 + 0.11297091222756375 + 0.11297435892179467 + 0.11297780567506042 + 0.11298125248736401 + 0.11298469935870835 + 0.11298814628909609 + 0.11299159327853002 + 0.11299504032701316 + 0.11299848743454802 + 0.11300193460113779 + 0.11300538182678493 + 0.11300882911149249 + 0.11301227645526321 + 0.11301572385809995 + 0.11301917132000529 + 0.11302261884098236 + 0.11302606642103399 + 0.11302951406016275 + 0.1130329617583716 + 0.11303640951566321 + 0.11303985733204068 + 0.11304330520750648 + 0.11304675314206378 + 0.11305020113571515 + 0.11305364918846353 + 0.1130570973003117 + 0.11306054547126236 + 0.11306399370131856 + 0.11306744199048305 + 0.1130708903387586 + 0.11307433874614779 + 0.11307778721265396 + 0.11308123573827952 + 0.11308468432302744 + 0.11308813296690037 + 0.11309158166990149 + 0.11309503043203341 + 0.11309847925329881 + 0.11310192813370064 + 0.11310537707324179 + 0.11310882607192492 + 0.11311227512975301 + 0.11311572424672885 + 0.1131191734228552 + 0.11312262265813489 + 0.11312607195257067 + 0.11312952130616562 + 0.11313297071892216 + 0.11313642019084351 + 0.11313986972193231 + 0.11314331931219136 + 0.11314676896162347 + 0.11315021867023152 + 0.11315366843801837 + 0.11315711826498678 + 0.11316056815113938 + 0.11316401809647926 + 0.11316746810100914 + 0.11317091816473202 + 0.11317436828765043 + 0.11317781846976754 + 0.11318126871108578 + 0.11318471901160826 + 0.11318816937133759 + 0.1131916197902767 + 0.11319507026842858 + 0.11319852080579577 + 0.1132019714023812 + 0.11320542205818764 + 0.11320887277321816 + 0.11321232354747524 + 0.11321577438096195 + 0.11321922527368099 + 0.11322267622563519 + 0.11322612723682746 + 0.11322957830726048 + 0.11323302943693736 + 0.11323648062586054 + 0.11323993187403313 + 0.11324338318145774 + 0.11324683454813747 + 0.11325028597407472 + 0.11325373745927277 + 0.11325718900373431 + 0.11326064060746201 + 0.1132640922704588 + 0.1132675439927274 + 0.11327099577427091 + 0.11327444761509188 + 0.11327789951519321 + 0.11328135147457777 + 0.1132848034932484 + 0.11328825557120786 + 0.11329170770845903 + 0.11329515990500473 + 0.11329861216084766 + 0.11330206447599094 + 0.11330551685043701 + 0.11330896928418904 + 0.11331242177724958 + 0.11331587432962176 + 0.11331932694130803 + 0.11332277961231156 + 0.11332623234263507 + 0.11332968513228132 + 0.11333313798125316 + 0.1133365908895534 + 0.11334004385718494 + 0.11334349688415059 + 0.11334694997045311 + 0.11335040311609536 + 0.11335385632108022 + 0.1133573095854105 + 0.11336076290908896 + 0.11336421629211849 + 0.11336766973450185 + 0.11337112323624209 + 0.11337457679734154 + 0.1133780304178037 + 0.11338148409763089 + 0.11338493783682614 + 0.11338839163539233 + 0.11339184549333198 + 0.11339529941064842 + 0.11339875338734408 + 0.11340220742342183 + 0.11340566151888463 + 0.11340911567373528 + 0.1134125698879767 + 0.11341602416161144 + 0.11341947849464253 + 0.11342293288707292 + 0.11342638733890512 + 0.11342984185014229 + 0.11343329642078702 + 0.11343675105084222 + 0.11344020574031072 + 0.11344366048919531 + 0.113447115297499 + 0.11345057016522442 + 0.11345402509237446 + 0.11345748007895194 + 0.11346093512495971 + 0.1134643902304006 + 0.11346784539527754 + 0.11347130061959312 + 0.1134747559033505 + 0.11347821124655229 + 0.1134816666492013 + 0.11348512211130035 + 0.11348857763285256 + 0.11349203321386023 + 0.11349548885432682 + 0.11349894455425467 + 0.11350240031364688 + 0.11350585613250626 + 0.11350931201083542 + 0.11351276794863749 + 0.11351622394591504 + 0.11351968000267119 + 0.11352313611890862 + 0.11352659229463002 + 0.11353004852983849 + 0.1135335048245367 + 0.11353696117872739 + 0.11354041759241369 + 0.1135438740655984 + 0.1135473305982839 + 0.11355078719047347 + 0.11355424384216987 + 0.1135577005533759 + 0.11356115732409433 + 0.11356461415432817 + 0.11356807104407994 + 0.11357152799335284 + 0.11357498500214949 + 0.11357844207047267 + 0.1135818991983254 + 0.11358535638571049 + 0.11358881363263064 + 0.11359227093908872 + 0.11359572830508763 + 0.11359918573063019 + 0.11360264321571931 + 0.11360610076035765 + 0.11360955836454817 + 0.11361301602829381 + 0.11361647375159706 + 0.11361993153446093 + 0.11362338937688851 + 0.11362684727888235 + 0.11363030524044537 + 0.11363376326158034 + 0.11363722134229029 + 0.11364067948257783 + 0.1136441376824458 + 0.11364759594189736 + 0.11365105426093482 + 0.1136545126395616 + 0.11365797107778014 + 0.11366142957559333 + 0.11366488813300413 + 0.11366834675001539 + 0.11367180542662969 + 0.11367526416285026 + 0.11367872295867956 + 0.1136821818141206 + 0.11368564072917632 + 0.11368909970384948 + 0.11369255873814275 + 0.1136960178320594 + 0.11369947698560172 + 0.11370293619877289 + 0.11370639547157561 + 0.11370985480401292 + 0.11371331419608743 + 0.11371677364780217 + 0.11372023315915981 + 0.11372369273016332 + 0.11372715236081533 + 0.11373061205111905 + 0.113734071801077 + 0.11373753161069199 + 0.11374099147996722 + 0.11374445140890521 + 0.11374791139750896 + 0.11375137144578128 + 0.11375483155372489 + 0.11375829172134258 + 0.11376175194863751 + 0.11376521223561235 + 0.11376867258226987 + 0.11377213298861311 + 0.11377559345464465 + 0.1137790539803675 + 0.11378251456578445 + 0.11378597521089835 + 0.11378943591571213 + 0.11379289668022843 + 0.11379635750445037 + 0.11379981838838049 + 0.11380327933202185 + 0.11380674033537722 + 0.11381020139844943 + 0.11381366252124125 + 0.11381712370375577 + 0.11382058494599553 + 0.11382404624796359 + 0.1138275076096627 + 0.1138309690310957 + 0.11383443051226563 + 0.113837892053175 + 0.11384135365382672 + 0.11384481531422386 + 0.11384827703436906 + 0.11385173881426541 + 0.11385520065391552 + 0.11385866255332215 + 0.11386212451248849 + 0.11386558653141707 + 0.11386904861011087 + 0.11387251074857267 + 0.11387597294680545 + 0.11387943520481197 + 0.11388289752259496 + 0.11388635990015746 + 0.11388982233750221 + 0.11389328483463199 + 0.11389674739154984 + 0.11390021000825856 + 0.1139036726847608 + 0.11390713542105965 + 0.11391059821715788 + 0.11391406107305815 + 0.11391752398876351 + 0.11392098696427684 + 0.11392444999960082 + 0.11392791309473844 + 0.11393137624969242 + 0.11393483946446584 + 0.11393830273906112 + 0.11394176607348157 + 0.11394522946772982 + 0.11394869292180865 + 0.11395215643572099 + 0.11395562000946965 + 0.11395908364305775 + 0.11396254733648768 + 0.11396601108976263 + 0.1139694749028853 + 0.11397293877585851 + 0.11397640270868527 + 0.1139798667013683 + 0.11398333075391034 + 0.11398679486631448 + 0.11399025903858349 + 0.11399372327072026 + 0.11399718756272741 + 0.11400065191460797 + 0.11400411632636487 + 0.11400758079800075 + 0.11401104532951875 + 0.11401450992092141 + 0.11401797457221166 + 0.11402143928339248 + 0.11402490405446647 + 0.11402836888543684 + 0.11403183377630621 + 0.11403529872707741 + 0.11403876373775342 + 0.11404222880833696 + 0.11404569393883099 + 0.11404915912923823 + 0.11405262437956173 + 0.11405608968980416 + 0.11405955505996841 + 0.11406302049005741 + 0.11406648598007385 + 0.11406995153002079 + 0.11407341713990091 + 0.11407688280971726 + 0.1140803485394724 + 0.11408381432916938 + 0.11408728017881106 + 0.11409074608840018 + 0.1140942120579397 + 0.11409767808743258 + 0.11410114417688147 + 0.11410461032628907 + 0.11410807653565866 + 0.11411154280499272 + 0.11411500913429436 + 0.1141184755235663 + 0.11412194197281141 + 0.11412540848203252 + 0.11412887505123261 + 0.11413234168041435 + 0.11413580836958076 + 0.11413927511873449 + 0.11414274192787871 + 0.11414620879701604 + 0.11414967572614929 + 0.1141531427152815 + 0.1141566097644153 + 0.11416007687355381 + 0.11416354404269968 + 0.11416701127185587 + 0.11417047856102516 + 0.11417394591021043 + 0.11417741331941457 + 0.11418088078864051 + 0.11418434831789084 + 0.11418781590716874 + 0.1141912835564768 + 0.11419475126581813 + 0.11419821903519525 + 0.1142016868646113 + 0.11420515475406909 + 0.11420862270357135 + 0.114212090713121 + 0.11421555878272086 + 0.11421902691237391 + 0.11422249510208295 + 0.1142259633518508 + 0.11422943166168045 + 0.11423290003157453 + 0.11423636846153594 + 0.11423983695156785 + 0.11424330550167258 + 0.11424677411185342 + 0.11425024278211306 + 0.11425371151245445 + 0.11425718030288037 + 0.11426064915339353 + 0.11426411806399718 + 0.11426758703469375 + 0.11427105606548643 + 0.11427452515637786 + 0.11427799430737112 + 0.11428146351846877 + 0.1142849327896739 + 0.1142884021209893 + 0.11429187151241782 + 0.11429534096396216 + 0.11429881047562554 + 0.11430228004741065 + 0.11430574967932022 + 0.11430921937135723 + 0.11431268912352459 + 0.11431615893582507 + 0.11431962880826153 + 0.11432309874083682 + 0.11432656873355371 + 0.11433003878641536 + 0.11433350889942442 + 0.11433697907258371 + 0.11434044930589622 + 0.11434391959936467 + 0.11434738995299212 + 0.1143508603667812 + 0.11435433084073489 + 0.11435780137485607 + 0.11436127196914761 + 0.11436474262361231 + 0.11436821333825306 + 0.11437168411307272 + 0.11437515494807414 + 0.11437862584326017 + 0.11438209679863363 + 0.11438556781419755 + 0.11438903888995469 + 0.11439251002590782 + 0.11439598122205991 + 0.11439945247841395 + 0.1144029237949723 + 0.11440639517173849 + 0.11440986660871504 + 0.11441333810590482 + 0.11441680966331061 + 0.11442028128093544 + 0.11442375295878218 + 0.11442722469685342 + 0.11443069649515243 + 0.11443416835368173 + 0.11443764027244448 + 0.11444111225144325 + 0.11444458429068108 + 0.11444805639016073 + 0.11445152854988529 + 0.11445500076985725 + 0.11445847305007995 + 0.11446194539055581 + 0.11446541779128791 + 0.11446889025227905 + 0.11447236277353211 + 0.11447583535505006 + 0.11447930799683555 + 0.11448278069889156 + 0.11448625346122114 + 0.11448972628382695 + 0.11449319916671169 + 0.11449667210987859 + 0.11450014511333027 + 0.11450361817706965 + 0.11450709130109964 + 0.11451056448542314 + 0.11451403773004287 + 0.11451751103496177 + 0.11452098440018288 + 0.11452445782570871 + 0.11452793131154237 + 0.11453140485768679 + 0.11453487846414459 + 0.11453835213091887 + 0.11454182585801234 + 0.11454529964542796 + 0.11454877349316862 + 0.11455224740123704 + 0.11455572136963614 + 0.11455919539836885 + 0.11456266948743801 + 0.11456614363684658 + 0.11456961784659722 + 0.11457309211669305 + 0.11457656644713672 + 0.11458004083793107 + 0.11458351528907922 + 0.11458698980058388 + 0.11459046437244796 + 0.11459393900467421 + 0.11459741369726574 + 0.11460088845022506 + 0.1146043632635554 + 0.11460783813725943 + 0.11461131307134001 + 0.11461478806580032 + 0.11461826312064274 + 0.11462173823587042 + 0.1146252134114862 + 0.11462868864749297 + 0.11463216394389356 + 0.11463563930069084 + 0.11463911471788767 + 0.11464259019548699 + 0.1146460657334915 + 0.11464954133190422 + 0.11465301699072802 + 0.1146564927099657 + 0.11465996848962033 + 0.11466344432969433 + 0.11466692023019107 + 0.11467039619111315 + 0.11467387221246356 + 0.11467734829424489 + 0.11468082443646049 + 0.11468430063911286 + 0.11468777690220512 + 0.11469125322573991 + 0.11469472960972008 + 0.11469820605414878 + 0.11470168255902866 + 0.11470515912436272 + 0.11470863575015376 + 0.11471211243640456 + 0.11471558918311821 + 0.11471906599029741 + 0.11472254285794511 + 0.11472601978606409 + 0.11472949677465739 + 0.11473297382372771 + 0.11473645093327819 + 0.11473992810331131 + 0.11474340533383019 + 0.11474688262483769 + 0.1147503599763367 + 0.11475383738832998 + 0.11475731486082053 + 0.11476079239381111 + 0.1147642699873046 + 0.11476774764130407 + 0.11477122535581206 + 0.11477470313083186 + 0.11477818096636588 + 0.11478165886241734 + 0.11478513681898905 + 0.1147886148360838 + 0.11479209291370454 + 0.11479557105185405 + 0.11479904925053526 + 0.11480252750975119 + 0.11480600582950447 + 0.11480948420979811 + 0.11481296265063508 + 0.11481644115201796 + 0.11481991971394985 + 0.11482339833643349 + 0.1148268770194719 + 0.11483035576306791 + 0.11483383456722447 + 0.11483731343194434 + 0.11484079235723035 + 0.11484427134308546 + 0.1148477503895126 + 0.11485122949651468 + 0.11485470866409431 + 0.11485818789225452 + 0.11486166718099843 + 0.11486514653032844 + 0.11486862594024794 + 0.11487210541075933 + 0.11487558494186581 + 0.11487906453357023 + 0.11488254418587528 + 0.11488602389878404 + 0.11488950367229919 + 0.11489298350642374 + 0.11489646340116058 + 0.11489994335651262 + 0.11490342337248259 + 0.11490690344907356 + 0.11491038358628818 + 0.11491386378412957 + 0.11491734404260029 + 0.1149208243617036 + 0.11492430474144211 + 0.11492778518181891 + 0.11493126568283681 + 0.11493474624449843 + 0.11493822686680698 + 0.11494170754976513 + 0.11494518829337594 + 0.11494866909764212 + 0.11495214996256657 + 0.1149556308881523 + 0.11495911187440216 + 0.114962592921319 + 0.1149660740289056 + 0.11496955519716499 + 0.11497303642610011 + 0.11497651771571349 + 0.11497999906600835 + 0.11498348047698748 + 0.11498696194865375 + 0.11499044348100994 + 0.11499392507405924 + 0.11499740672780406 + 0.11500088844224772 + 0.11500437021739283 + 0.11500785205324249 + 0.11501133394979929 + 0.11501481590706639 + 0.11501829792504648 + 0.11502178000374266 + 0.11502526214315752 + 0.1150287443432942 + 0.11503222660415542 + 0.11503570892574422 + 0.11503919130806331 + 0.11504267375111565 + 0.11504615625490421 + 0.11504963881943156 + 0.11505312144470113 + 0.11505660413071531 + 0.11506008687747718 + 0.11506356968498954 + 0.1150670525532554 + 0.11507053548227753 + 0.11507401847205893 + 0.11507750152260252 + 0.11508098463391088 + 0.11508446780598718 + 0.11508795103883424 + 0.11509143433245488 + 0.11509491768685201 + 0.11509840110202872 + 0.11510188457798751 + 0.11510536811473154 + 0.11510885171226365 + 0.11511233537058656 + 0.11511581908970332 + 0.11511930286961694 + 0.11512278671033016 + 0.11512627061184577 + 0.11512975457416678 + 0.11513323859729586 + 0.11513672268123624 + 0.1151402068259906 + 0.1151436910315619 + 0.115147175297953 + 0.11515065962516687 + 0.1151541440132062 + 0.11515762846207386 + 0.11516111297177307 + 0.1151645975423064 + 0.11516808217367681 + 0.11517156686588745 + 0.11517505161894075 + 0.1151785364328399 + 0.11518202130758788 + 0.11518550624318719 + 0.11518899123964102 + 0.11519247629695216 + 0.11519596141512359 + 0.11519944659415807 + 0.11520293183405854 + 0.11520641713482792 + 0.11520990249646894 + 0.11521338791898486 + 0.11521687340237816 + 0.11522035894665199 + 0.11522384455180915 + 0.11522733021785243 + 0.11523081594478479 + 0.11523430173260929 + 0.11523778758132855 + 0.11524127349094562 + 0.11524475946146351 + 0.11524824549288466 + 0.11525173158521242 + 0.11525521773844948 + 0.11525870395259886 + 0.11526219022766329 + 0.11526567656364567 + 0.11526916296054894 + 0.1152726494183761 + 0.11527613593712972 + 0.11527962251681313 + 0.11528310915742881 + 0.11528659585898 + 0.1152900826214695 + 0.11529356944489993 + 0.11529705632927437 + 0.11530054327459592 + 0.11530403028086715 + 0.11530751734809107 + 0.11531100447627055 + 0.11531449166540861 + 0.11531797891550798 + 0.11532146622657155 + 0.11532495359860237 + 0.11532844103160324 + 0.11533192852557703 + 0.11533541608052662 + 0.11533890369645494 + 0.11534239137336488 + 0.11534587911125929 + 0.11534936691014119 + 0.11535285477001338 + 0.11535634269087876 + 0.11535983067274025 + 0.11536331871560049 + 0.11536680681946285 + 0.11537029498432991 + 0.11537378321020471 + 0.11537727149708998 + 0.11538075984498852 + 0.11538424825390352 + 0.11538773672383784 + 0.11539122525479424 + 0.11539471384677574 + 0.115398202499785 + 0.11540169121382517 + 0.11540517998889914 + 0.11540866882500955 + 0.11541215772215953 + 0.11541564668035184 + 0.11541913569958959 + 0.11542262477987535 + 0.1154261139212123 + 0.11542960312360308 + 0.11543309238705092 + 0.11543658171155834 + 0.11544007109712862 + 0.11544356054376424 + 0.11544705005146844 + 0.11545053962024403 + 0.11545402925009385 + 0.1154575189410208 + 0.11546100869302767 + 0.11546449850611766 + 0.11546798838029332 + 0.11547147831555785 + 0.11547496831191378 + 0.11547845836936449 + 0.11548194848791248 + 0.11548543866756077 + 0.11548892890831235 + 0.11549241921017006 + 0.11549590957313675 + 0.11549939999721538 + 0.11550289048240873 + 0.11550638102871996 + 0.11550987163615158 + 0.1155133623047068 + 0.11551685303438844 + 0.11552034382519932 + 0.11552383467714246 + 0.11552732559022066 + 0.11553081656443687 + 0.11553430759979393 + 0.11553779869629476 + 0.11554128985394248 + 0.11554478107273961 + 0.11554827235268919 + 0.11555176369379432 + 0.11555525509605762 + 0.11555874655948221 + 0.11556223808407078 + 0.11556572966982634 + 0.11556922131675187 + 0.1155727130248501 + 0.11557620479412399 + 0.11557969662457672 + 0.11558318851621067 + 0.11558668046902906 + 0.11559017248303495 + 0.11559366455823081 + 0.1155971566946198 + 0.11560064889220485 + 0.11560414115098873 + 0.11560763347097441 + 0.1156111258521649 + 0.11561461829456281 + 0.11561811079817136 + 0.11562160336299333 + 0.11562509598903149 + 0.11562858867628902 + 0.11563208142476847 + 0.11563557423447304 + 0.11563906710540557 + 0.11564256003756873 + 0.11564605303096571 + 0.11564954608559939 + 0.11565303920147257 + 0.115656532378588 + 0.11566002561694902 + 0.11566351891655803 + 0.11566701227741838 + 0.1156705056995327 + 0.11567399918290394 + 0.11567749272753514 + 0.11568098633342895 + 0.11568448000058838 + 0.11568797372901653 + 0.11569146751871602 + 0.11569496136969001 + 0.11569845528194107 + 0.11570194925547242 + 0.11570544329028684 + 0.11570893738638735 + 0.11571243154377661 + 0.11571592576245765 + 0.11571942004243334 + 0.11572291438370684 + 0.11572640878628072 + 0.11572990325015804 + 0.11573339777534158 + 0.11573689236183456 + 0.11574038700963953 + 0.11574388171875957 + 0.11574737648919754 + 0.11575087132095628 + 0.11575436621403891 + 0.11575786116844805 + 0.1157613561841869 + 0.11576485126125813 + 0.11576834639966475 + 0.11577184159940976 + 0.11577533686049586 + 0.11577883218292612 + 0.11578232756670326 + 0.11578582301183037 + 0.11578931851831036 + 0.115792814086146 + 0.11579630971534033 + 0.11579980540589623 + 0.11580330115781658 + 0.11580679697110417 + 0.11581029284576216 + 0.11581378878179328 + 0.11581728477920043 + 0.11582078083798662 + 0.11582427695815477 + 0.11582777313970764 + 0.11583126938264816 + 0.11583476568697954 + 0.11583826205270407 + 0.11584175847982527 + 0.11584525496834593 + 0.11584875151826868 + 0.11585224812959662 + 0.11585574480233275 + 0.11585924153647978 + 0.11586273833204055 + 0.11586623518901841 + 0.11586973210741588 + 0.11587322908723591 + 0.11587672612848153 + 0.11588022323115565 + 0.115883720395261 + 0.11588721762080065 + 0.1158907149077775 + 0.11589421225619449 + 0.11589770966605446 + 0.11590120713736034 + 0.11590470467011492 + 0.1159082022643214 + 0.11591169991998244 + 0.11591519763710104 + 0.11591869541568006 + 0.11592219325572246 + 0.11592569115723107 + 0.11592918912020911 + 0.11593268714465917 + 0.11593618523058422 + 0.11593968337798714 + 0.11594318158687084 + 0.11594667985723847 + 0.11595017818909271 + 0.11595367658243655 + 0.11595717503727281 + 0.11596067355360463 + 0.1159641721314347 + 0.11596767077076592 + 0.11597116947160145 + 0.11597466823394385 + 0.11597816705779633 + 0.11598166594316174 + 0.11598516489004294 + 0.11598866389844274 + 0.1159921629683643 + 0.1159956620998103 + 0.11599916129278373 + 0.11600266054728767 + 0.11600615986332476 + 0.11600965924089812 + 0.1160131586800105 + 0.11601665818066501 + 0.11602015774286445 + 0.11602365736661162 + 0.11602715705190973 + 0.11603065679876134 + 0.11603415660716983 + 0.11603765647713754 + 0.11604115640866786 + 0.11604465640176349 + 0.11604815645642731 + 0.11605165657266227 + 0.11605515675047144 + 0.11605865698985751 + 0.11606215729082364 + 0.11606565765337251 + 0.1160691580775072 + 0.11607265856323044 + 0.11607615911054543 + 0.11607965971945487 + 0.11608316038996161 + 0.11608666112206892 + 0.11609016191577924 + 0.11609366277109587 + 0.11609716368802149 + 0.11610066466655937 + 0.11610416570671196 + 0.11610766680848236 + 0.11611116797187361 + 0.1161146691968884 + 0.11611817048352997 + 0.116121671831801 + 0.11612517324170418 + 0.1161286747132432 + 0.11613217624642011 + 0.11613567784123838 + 0.11613917949770061 + 0.11614268121581002 + 0.11614618299556921 + 0.11614968483698133 + 0.11615318674004931 + 0.11615668870477595 + 0.1161601907311641 + 0.11616369281921687 + 0.11616719496893706 + 0.11617069718032759 + 0.11617419945339152 + 0.11617770178813164 + 0.1161812041845508 + 0.11618470664265194 + 0.11618820916243823 + 0.11619171174391237 + 0.11619521438707739 + 0.11619871709193585 + 0.11620221985849113 + 0.11620572268674607 + 0.11620922557670348 + 0.11621272852836617 + 0.11621623154173732 + 0.11621973461681967 + 0.11622323775361623 + 0.1162267409521298 + 0.11623024421236351 + 0.11623374753432004 + 0.11623725091800252 + 0.11624075436341376 + 0.11624425787055664 + 0.11624776143943419 + 0.11625126507004944 + 0.11625476876240495 + 0.11625827251650393 + 0.11626177633234923 + 0.11626528020994377 + 0.11626878414929044 + 0.11627228815039223 + 0.11627579221325196 + 0.11627929633787262 + 0.1162828005242572 + 0.11628630477240846 + 0.11628980908232953 + 0.11629331345402312 + 0.1162968178874923 + 0.11630032238273985 + 0.11630382693976883 + 0.11630733155858224 + 0.11631083623918277 + 0.11631434098157355 + 0.11631784578575734 + 0.11632135065173718 + 0.11632485557951606 + 0.11632836056909662 + 0.11633186562048208 + 0.11633537073367525 + 0.11633887590867892 + 0.11634238114549628 + 0.11634588644413006 + 0.11634939180458326 + 0.11635289722685867 + 0.11635640271095959 + 0.11635990825688856 + 0.11636341386464864 + 0.11636691953424279 + 0.11637042526567387 + 0.11637393105894475 + 0.11637743691405854 + 0.11638094283101795 + 0.11638444880982611 + 0.11638795485048588 + 0.11639146095300028 + 0.11639496711737186 + 0.11639847334360401 + 0.11640197963169946 + 0.11640548598166112 + 0.11640899239349181 + 0.11641249886719476 + 0.11641600540277248 + 0.11641951200022826 + 0.11642301865956491 + 0.11642652538078523 + 0.11643003216389247 + 0.11643353900888924 + 0.11643704591577866 + 0.11644055288456341 + 0.11644405991524677 + 0.11644756700783129 + 0.11645107416232024 + 0.11645458137871631 + 0.1164580886570226 + 0.11646159599724203 + 0.1164651033993773 + 0.11646861086343152 + 0.11647211838940769 + 0.11647562597730851 + 0.11647913362713716 + 0.11648264133889642 + 0.11648614911258921 + 0.11648965694821856 + 0.11649316484578719 + 0.11649667280529845 + 0.11650018082675469 + 0.11650368891015944 + 0.11650719705551521 + 0.11651070526282506 + 0.11651421353209189 + 0.11651772186331873 + 0.11652123025650844 + 0.11652473871166384 + 0.11652824722878806 + 0.11653175580788397 + 0.11653526444895443 + 0.11653877315200249 + 0.11654228191703088 + 0.11654579074404271 + 0.11654929963304092 + 0.11655280858402833 + 0.11655631759700801 + 0.11655982667198277 + 0.11656333580895556 + 0.11656684500792922 + 0.11657035426890684 + 0.11657386359189155 + 0.11657737297688579 + 0.11658088242389265 + 0.11658439193291541 + 0.11658790150395654 + 0.11659141113701925 + 0.11659492083210644 + 0.11659843058922087 + 0.11660194040836593 + 0.11660545028954389 + 0.11660896023275814 + 0.11661247023801147 + 0.11661598030530695 + 0.11661949043464719 + 0.11662300062603549 + 0.11662651087947462 + 0.11663002119496758 + 0.11663353157251707 + 0.11663704201212635 + 0.11664055251379819 + 0.11664406307753551 + 0.11664757370334128 + 0.11665108439121843 + 0.11665459514117001 + 0.11665810595319859 + 0.11666161682730752 + 0.11666512776349958 + 0.11666863876177767 + 0.11667214982214481 + 0.11667566094460384 + 0.1166791721291576 + 0.11668268337580924 + 0.11668619468456168 + 0.11668970605541773 + 0.11669321748838053 + 0.11669672898345267 + 0.11670024054063742 + 0.11670375215993763 + 0.11670726384135587 + 0.11671077558489575 + 0.1167142873905597 + 0.11671779925835087 + 0.11672131118827207 + 0.11672482318032633 + 0.11672833523451664 + 0.11673184735084575 + 0.1167353595293168 + 0.11673887176993253 + 0.11674238407269591 + 0.11674589643761021 + 0.11674940886467797 + 0.11675292135390228 + 0.11675643390528608 + 0.11675994651883218 + 0.11676345919454378 + 0.11676697193242355 + 0.11677048473247459 + 0.11677399759469985 + 0.11677751051910223 + 0.11678102350568448 + 0.11678453655444986 + 0.11678804966540121 + 0.11679156283854129 + 0.11679507607387321 + 0.11679858937139981 + 0.11680210273112421 + 0.11680561615304917 + 0.11680912963717767 + 0.1168126431835127 + 0.11681615679205722 + 0.11681967046281393 + 0.11682318419578612 + 0.11682669799097656 + 0.11683021184838813 + 0.11683372576802394 + 0.11683723974988658 + 0.11684075379397948 + 0.11684426790030533 + 0.11684778206886696 + 0.11685129629966751 + 0.11685481059270984 + 0.11685832494799697 + 0.11686183936553153 + 0.11686535384531692 + 0.11686886838735584 + 0.1168723829916512 + 0.11687589765820597 + 0.11687941238702317 + 0.11688292717810558 + 0.11688644203145637 + 0.11688995694707839 + 0.11689347192497442 + 0.11689698696514765 + 0.11690050206760083 + 0.11690401723233695 + 0.11690753245935911 + 0.11691104774867006 + 0.11691456310027283 + 0.11691807851417028 + 0.1169215939903655 + 0.11692510952886125 + 0.11692862512966075 + 0.11693214079276651 + 0.11693565651818191 + 0.11693917230590979 + 0.11694268815595282 + 0.11694620406831416 + 0.11694972004299679 + 0.11695323608000363 + 0.1169567521793376 + 0.11696026834100152 + 0.11696378456499869 + 0.11696730085133168 + 0.11697081720000355 + 0.11697433361101731 + 0.11697785008437589 + 0.11698136662008222 + 0.11698488321813917 + 0.11698839987854978 + 0.11699191660131682 + 0.11699543338644362 + 0.11699895023393271 + 0.11700246714378744 + 0.11700598411601029 + 0.11700950115060456 + 0.11701301824757299 + 0.11701653540691867 + 0.1170200526286444 + 0.11702356991275335 + 0.11702708725924842 + 0.11703060466813231 + 0.11703412213940824 + 0.11703763967307906 + 0.11704115726914739 + 0.11704467492761692 + 0.1170481926484899 + 0.11705171043176971 + 0.11705522827745897 + 0.11705874618556086 + 0.11706226415607827 + 0.11706578218901417 + 0.11706930028437149 + 0.11707281844215306 + 0.11707633666236193 + 0.11707985494500109 + 0.11708337329007354 + 0.11708689169758207 + 0.11709041016752963 + 0.11709392869991937 + 0.1170974472947539 + 0.11710096595203662 + 0.11710448467176994 + 0.11710800345395736 + 0.1171115222986015 + 0.11711504120570525 + 0.11711856017527192 + 0.11712207920730408 + 0.11712559830180481 + 0.11712911745877717 + 0.11713263667822381 + 0.11713615596014806 + 0.11713967530455266 + 0.11714319471144068 + 0.1171467141808149 + 0.11715023371267842 + 0.11715375330703401 + 0.11715727296388484 + 0.11716079268323371 + 0.11716431246508366 + 0.11716783230943752 + 0.11717135221629844 + 0.11717487218566906 + 0.11717839221755276 + 0.11718191231195221 + 0.11718543246887043 + 0.11718895268831028 + 0.11719247297027477 + 0.11719599331476691 + 0.11719951372178951 + 0.11720303419134583 + 0.11720655472343836 + 0.11721007531807046 + 0.11721359597524493 + 0.11721711669496473 + 0.11722063747723259 + 0.11722415832205194 + 0.11722767922942524 + 0.1172312001993559 + 0.11723472123184647 + 0.11723824232690019 + 0.1172417634845199 + 0.11724528470470853 + 0.11724880598746887 + 0.11725232733280436 + 0.11725584874071759 + 0.11725937021121145 + 0.117262891744289 + 0.11726641333995334 + 0.1172699349982073 + 0.11727345671905391 + 0.11727697850249588 + 0.11728050034853633 + 0.11728402225717842 + 0.11728754422842469 + 0.11729106626227837 + 0.11729458835874247 + 0.11729811051781969 + 0.1173016327395132 + 0.11730515502382595 + 0.1173086773707607 + 0.11731219978032058 + 0.11731572225250844 + 0.1173192447873274 + 0.11732276738478023 + 0.11732629004486986 + 0.11732981276759974 + 0.11733333555297205 + 0.11733685840099026 + 0.11734038131165719 + 0.11734390428497589 + 0.1173474273209491 + 0.11735095041958009 + 0.11735447358087159 + 0.11735799680482632 + 0.1173615200914478 + 0.11736504344073866 + 0.11736856685270192 + 0.11737209032734054 + 0.11737561386465743 + 0.11737913746465564 + 0.11738266112733797 + 0.11738618485270758 + 0.1173897086407672 + 0.11739323249152005 + 0.1173967564049689 + 0.11740028038111675 + 0.11740380441996644 + 0.11740732852152132 + 0.11741085268578381 + 0.11741437691275729 + 0.11741790120244457 + 0.11742142555484857 + 0.11742494996997231 + 0.11742847444781887 + 0.11743199898839086 + 0.11743552359169154 + 0.11743904825772383 + 0.11744257298649061 + 0.11744609777799485 + 0.11744962263223947 + 0.11745314754922755 + 0.11745667252896197 + 0.11746019757144575 + 0.1174637226766817 + 0.11746724784467297 + 0.11747077307542252 + 0.11747429836893319 + 0.11747782372520793 + 0.11748134914424979 + 0.11748487462606153 + 0.11748840017064648 + 0.11749192577800729 + 0.11749545144814721 + 0.11749897718106889 + 0.11750250297677539 + 0.11750602883526974 + 0.11750955475655478 + 0.11751308074063373 + 0.11751660678750921 + 0.11752013289718446 + 0.11752365906966229 + 0.11752718530494585 + 0.11753071160303773 + 0.11753423796394132 + 0.11753776438765921 + 0.1175412908741946 + 0.11754481742355039 + 0.11754834403572968 + 0.1175518707107351 + 0.11755539744856991 + 0.11755892424923682 + 0.11756245111273914 + 0.11756597803907952 + 0.11756950502826118 + 0.1175730320802869 + 0.11757655919515957 + 0.11758008637288234 + 0.11758361361345832 + 0.11758714091688995 + 0.11759066828318061 + 0.11759419571233326 + 0.11759772320435065 + 0.11760125075923589 + 0.11760477837699213 + 0.11760830605762199 + 0.11761183380112834 + 0.11761536160751455 + 0.11761888947678342 + 0.11762241740893796 + 0.117625945403981 + 0.11762947346191552 + 0.1176330015827447 + 0.11763652976647132 + 0.11764005801309836 + 0.11764358632262868 + 0.1176471146950656 + 0.1176506431304116 + 0.11765417162867015 + 0.11765770018984383 + 0.11766122881393591 + 0.11766475750094903 + 0.11766828625088641 + 0.11767181506375096 + 0.11767534393954565 + 0.11767887287827319 + 0.11768240187993698 + 0.11768593094453964 + 0.11768946007208435 + 0.11769298926257413 + 0.11769651851601165 + 0.11770004783240012 + 0.11770357721174245 + 0.11770710665404163 + 0.11771063615930051 + 0.11771416572752208 + 0.11771769535870956 + 0.11772122505286561 + 0.11772475480999331 + 0.11772828463009576 + 0.11773181451317577 + 0.1177353444592362 + 0.11773887446828024 + 0.11774240454031086 + 0.11774593467533091 + 0.1177494648733433 + 0.11775299513435127 + 0.11775652545835744 + 0.11776005584536524 + 0.11776358629537717 + 0.11776711680839649 + 0.11777064738442597 + 0.11777417802346865 + 0.11777770872552761 + 0.11778123949060586 + 0.11778477031870582 + 0.11778830120983129 + 0.11779183216398489 + 0.11779536318116947 + 0.11779889426138795 + 0.11780242540464338 + 0.11780595661093894 + 0.11780948788027742 + 0.11781301921266184 + 0.11781655060809508 + 0.1178200820665801 + 0.11782361358812007 + 0.11782714517271776 + 0.11783067682037628 + 0.11783420853109845 + 0.11783774030488749 + 0.11784127214174617 + 0.11784480404167742 + 0.11784833600468449 + 0.11785186803077 + 0.11785540011993705 + 0.11785893227218873 + 0.11786246448752791 + 0.11786599676595755 + 0.11786952910748071 + 0.11787306151210043 + 0.11787659397981935 + 0.11788012651064075 + 0.11788365910456756 + 0.11788719176160259 + 0.11789072448174898 + 0.1178942572650097 + 0.1178977901113878 + 0.11790132302088596 + 0.11790485599350733 + 0.11790838902925489 + 0.11791192212813179 + 0.11791545529014059 + 0.1179189885152845 + 0.11792252180356655 + 0.11792605515498965 + 0.11792958856955692 + 0.11793312204727098 + 0.11793665558813517 + 0.1179401891921522 + 0.11794372285932526 + 0.11794725658965721 + 0.11795079038315109 + 0.1179543242398097 + 0.11795785815963618 + 0.11796139214263353 + 0.11796492618880459 + 0.11796846029815254 + 0.11797199447068007 + 0.11797552870639048 + 0.11797906300528659 + 0.1179825973673712 + 0.11798613179264753 + 0.11798966628111859 + 0.1179932008327871 + 0.1179967354476564 + 0.11800027012572901 + 0.11800380486700823 + 0.11800733967149707 + 0.11801087453919835 + 0.11801440947011492 + 0.11801794446425004 + 0.11802147952160656 + 0.11802501464218759 + 0.11802854982599599 + 0.1180320850730347 + 0.11803562038330664 + 0.11803915575681513 + 0.11804269119356277 + 0.11804622669355275 + 0.11804976225678776 + 0.11805329788327115 + 0.11805683357300582 + 0.11806036932599465 + 0.11806390514224055 + 0.11806744102174677 + 0.11807097696451595 + 0.11807451297055133 + 0.1180780490398556 + 0.11808158517243221 + 0.11808512136828368 + 0.11808865762741319 + 0.11809219394982387 + 0.11809573033551829 + 0.11809926678449982 + 0.11810280329677136 + 0.11810633987233575 + 0.11810987651119602 + 0.11811341321335518 + 0.11811694997881619 + 0.11812048680758215 + 0.11812402369965587 + 0.11812756065504038 + 0.11813109767373867 + 0.11813463475575385 + 0.11813817190108857 + 0.11814170910974628 + 0.11814524638172968 + 0.11814878371704166 + 0.11815232111568534 + 0.11815585857766378 + 0.11815939610297987 + 0.11816293369163643 + 0.11816647134363679 + 0.11817000905898363 + 0.1181735468376801 + 0.11817708467972918 + 0.11818062258513354 + 0.11818416055389667 + 0.11818769858602135 + 0.11819123668151038 + 0.11819477484036688 + 0.11819831306259407 + 0.11820185134819443 + 0.11820538969717138 + 0.11820892810952779 + 0.1182124665852666 + 0.11821600512439061 + 0.11821954372690298 + 0.11822308239280692 + 0.11822662112210498 + 0.11823015991480043 + 0.11823369877089621 + 0.11823723769039531 + 0.11824077667330067 + 0.1182443157196152 + 0.11824785482934207 + 0.11825139400248416 + 0.11825493323904446 + 0.11825847253902588 + 0.11826201190243148 + 0.11826555132926445 + 0.11826909081952736 + 0.11827263037322344 + 0.11827616999035574 + 0.11827970967092701 + 0.11828324941494066 + 0.11828678922239912 + 0.1182903290933057 + 0.11829386902766341 + 0.11829740902547517 + 0.11830094908674386 + 0.11830448921147264 + 0.11830802939966448 + 0.11831156965132217 + 0.11831510996644894 + 0.1183186503450476 + 0.11832219078712128 + 0.11832573129267296 + 0.11832927186170557 + 0.11833281249422201 + 0.11833635319022535 + 0.11833989394971857 + 0.11834343477270479 + 0.11834697565918674 + 0.11835051660916764 + 0.11835405762265029 + 0.11835759869963798 + 0.11836113984013337 + 0.11836468104413947 + 0.11836822231165946 + 0.11837176364269623 + 0.11837530503725284 + 0.11837884649533217 + 0.11838238801693723 + 0.11838592960207101 + 0.11838947125073662 + 0.11839301296293689 + 0.11839655473867487 + 0.11840009657795354 + 0.11840363848077597 + 0.11840718044714506 + 0.11841072247706386 + 0.11841426457053532 + 0.11841780672756237 + 0.11842134894814811 + 0.11842489123229541 + 0.11842843358000744 + 0.11843197599128708 + 0.11843551846613727 + 0.11843906100456124 + 0.11844260360656161 + 0.11844614627214156 + 0.11844968900130416 + 0.11845323179405227 + 0.11845677465038887 + 0.11846031757031722 + 0.11846386055383998 + 0.11846740360096025 + 0.11847094671168111 + 0.11847448988600551 + 0.11847803312393627 + 0.11848157642547674 + 0.11848511979062971 + 0.11848866321939801 + 0.11849220671178486 + 0.11849575026779313 + 0.11849929388742587 + 0.11850283757068619 + 0.11850638131757676 + 0.11850992512810093 + 0.11851346900226156 + 0.11851701294006145 + 0.11852055694150397 + 0.11852410100659164 + 0.11852764513532803 + 0.11853118932771557 + 0.11853473358375768 + 0.1185382779034571 + 0.11854182228681692 + 0.11854536673384021 + 0.11854891124452974 + 0.11855245581888876 + 0.11855600045692023 + 0.11855954515862678 + 0.11856308992401186 + 0.11856663475307823 + 0.11857017964582908 + 0.11857372460226707 + 0.11857726962239568 + 0.1185808147062174 + 0.11858435985373547 + 0.11858790506495291 + 0.11859145033987263 + 0.11859499567849774 + 0.11859854108083115 + 0.11860208654687583 + 0.1186056320766348 + 0.11860917767011098 + 0.1186127233273076 + 0.11861626904822743 + 0.11861981483287354 + 0.11862336068124918 + 0.11862690659335681 + 0.11863045256919989 + 0.11863399860878114 + 0.11863754471210375 + 0.11864109087917056 + 0.1186446371099848 + 0.11864818340454913 + 0.11865172976286682 + 0.11865527618494061 + 0.11865882267077399 + 0.11866236922036921 + 0.11866591583372994 + 0.11866946251085893 + 0.11867300925175904 + 0.11867655605643357 + 0.11868010292488523 + 0.11868364985711725 + 0.11868719685313232 + 0.11869074391293384 + 0.11869429103652454 + 0.11869783822390755 + 0.11870138547508578 + 0.1187049327900622 + 0.11870848016883984 + 0.11871202761142162 + 0.1187155751178109 + 0.11871912268801024 + 0.11872267032202295 + 0.11872621801985184 + 0.11872976578150005 + 0.11873331360697034 + 0.11873686149626597 + 0.11874040944938986 + 0.11874395746634492 + 0.11874750554713433 + 0.11875105369176084 + 0.11875460190022774 + 0.11875815017253777 + 0.11876169850869413 + 0.11876524690869975 + 0.11876879537255759 + 0.11877234390027075 + 0.11877589249184209 + 0.11877944114727469 + 0.11878298986657143 + 0.11878653864973557 + 0.1187900874967701 + 0.11879363640767768 + 0.1187971853824616 + 0.11880073442112475 + 0.11880428352367019 + 0.11880783269010096 + 0.11881138192041991 + 0.11881493121463024 + 0.11881848057273472 + 0.11882202999473666 + 0.11882557948063875 + 0.11882912903044424 + 0.11883267864415588 + 0.11883622832177686 + 0.1188397780633102 + 0.11884332786875888 + 0.1188468777381257 + 0.11885042767141413 + 0.11885397766862664 + 0.11885752772976653 + 0.11886107785483668 + 0.11886462804384014 + 0.11886817829678008 + 0.11887172861365924 + 0.11887527899448078 + 0.1188788294392477 + 0.1188823799479629 + 0.11888593052062947 + 0.11888948115725056 + 0.11889303185782893 + 0.11889658262236757 + 0.11890013345086961 + 0.11890368434333809 + 0.11890723529977588 + 0.11891078632018616 + 0.11891433740457191 + 0.11891788855293596 + 0.11892143976528152 + 0.1189249910416114 + 0.11892854238192858 + 0.11893209378623637 + 0.11893564525453755 + 0.11893919678683514 + 0.11894274838313219 + 0.11894630004343176 + 0.11894985176773683 + 0.11895340355605029 + 0.11895695540837528 + 0.11896050732471472 + 0.1189640593050717 + 0.11896761134944914 + 0.11897116345785015 + 0.11897471563027753 + 0.11897826786673453 + 0.1189818201672241 + 0.11898537253174916 + 0.11898892496031274 + 0.11899247745291798 + 0.11899603000956761 + 0.11899958263026497 + 0.11900313531501291 + 0.1190066880638144 + 0.11901024087667249 + 0.11901379375359032 + 0.11901734669457065 + 0.11902089969961652 + 0.11902445276873122 + 0.11902800590191739 + 0.11903155909917836 + 0.1190351123605167 + 0.1190386656859361 + 0.11904221907543894 + 0.1190457725290287 + 0.11904932604670786 + 0.11905287962848003 + 0.11905643327434778 + 0.11905998698431426 + 0.11906354075838255 + 0.11906709459655558 + 0.11907064849883638 + 0.11907420246522789 + 0.11907775649573325 + 0.11908131059035536 + 0.11908486474909742 + 0.11908841897196225 + 0.11909197325895284 + 0.11909552761007215 + 0.11909908202532354 + 0.11910263650470984 + 0.11910619104823389 + 0.11910974565589873 + 0.11911330032770774 + 0.11911685506366351 + 0.11912040986376914 + 0.11912396472802787 + 0.11912751965644255 + 0.11913107464901608 + 0.11913462970575167 + 0.1191381848266521 + 0.11914174001172068 + 0.11914529526096036 + 0.11914885057437413 + 0.11915240595196473 + 0.11915596139373529 + 0.11915951689968919 + 0.11916307246982909 + 0.11916662810415808 + 0.11917018380267909 + 0.11917373956539541 + 0.11917729539230976 + 0.11918085128342527 + 0.11918440723874496 + 0.11918796325827186 + 0.11919151934200885 + 0.11919507548995925 + 0.11919863170212565 + 0.11920218797851148 + 0.1192057443191195 + 0.11920930072395269 + 0.11921285719301429 + 0.1192164137263072 + 0.1192199703238345 + 0.11922352698559903 + 0.11922708371160383 + 0.11923064050185204 + 0.11923419735634667 + 0.1192377542750907 + 0.11924131125808711 + 0.11924486830533899 + 0.11924842541684935 + 0.11925198259262107 + 0.11925553983265742 + 0.11925909713696102 + 0.1192626545055354 + 0.11926621193838313 + 0.11926976943550753 + 0.1192733269969114 + 0.11927688462259783 + 0.11928044231256996 + 0.11928400006683065 + 0.11928755788538289 + 0.11929111576822993 + 0.11929467371537447 + 0.11929823172681979 + 0.11930178980256892 + 0.11930534794262448 + 0.11930890614699004 + 0.11931246441566826 + 0.11931602274866231 + 0.11931958114597516 + 0.11932313960760975 + 0.11932669813356907 + 0.11933025672385647 + 0.11933381537847458 + 0.1193373740974266 + 0.11934093288071553 + 0.11934449172834445 + 0.1193480506403162 + 0.11935160961663403 + 0.11935516865730074 + 0.11935872776231952 + 0.1193622869316934 + 0.1193658461654252 + 0.11936940546351812 + 0.11937296482597516 + 0.11937652425279928 + 0.11938008374399342 + 0.1193836432995608 + 0.11938720291950436 + 0.11939076260382692 + 0.11939432235253197 + 0.11939788216562201 + 0.11940144204310049 + 0.11940500198497012 + 0.11940856199123406 + 0.11941212206189535 + 0.11941568219695688 + 0.11941924239642182 + 0.11942280266029322 + 0.11942636298857395 + 0.11942992338126709 + 0.11943348383837568 + 0.11943704435990272 + 0.11944060494585131 + 0.1194441655962243 + 0.11944772631102488 + 0.11945128709025597 + 0.11945484793392069 + 0.11945840884202201 + 0.11946196981456306 + 0.11946553085154663 + 0.11946909195297582 + 0.11947265311885365 + 0.1194762143491834 + 0.11947977564396772 + 0.11948333700320983 + 0.11948689842691285 + 0.11949045991507949 + 0.11949402146771314 + 0.11949758308481655 + 0.1195011447663929 + 0.11950470651244501 + 0.11950826832297617 + 0.11951183019798928 + 0.11951539213748741 + 0.1195189541414734 + 0.1195225162099505 + 0.11952607834292174 + 0.11952964054038999 + 0.11953320280235828 + 0.11953676512882981 + 0.11954032751980731 + 0.11954388997529421 + 0.11954745249529315 + 0.11955101507980749 + 0.11955457772883979 + 0.1195581404423936 + 0.11956170322047156 + 0.11956526606307705 + 0.11956882897021266 + 0.11957239194188181 + 0.11957595497808747 + 0.11957951807883248 + 0.11958308124411998 + 0.11958664447395288 + 0.11959020776833426 + 0.1195937711272675 + 0.11959733455075491 + 0.11960089803880014 + 0.11960446159140588 + 0.11960802520857541 + 0.11961158889031151 + 0.11961515263661741 + 0.11961871644749592 + 0.11962228032295037 + 0.11962584426298349 + 0.11962940826759855 + 0.1196329723367983 + 0.11963653647058591 + 0.11964010066896456 + 0.11964366493193705 + 0.11964722925950658 + 0.11965079365167612 + 0.11965435810844866 + 0.11965792262982715 + 0.1196614872158147 + 0.1196650518664145 + 0.11966861658162924 + 0.11967218136146236 + 0.11967574620591666 + 0.11967931111499512 + 0.11968287608870083 + 0.1196864411270368 + 0.11969000623000606 + 0.11969357139761173 + 0.1196971366298567 + 0.11970070192674422 + 0.11970426728827709 + 0.11970783271445838 + 0.11971139820529129 + 0.11971496376077863 + 0.11971852938092359 + 0.11972209506572916 + 0.11972566081519813 + 0.11972922662933394 + 0.11973279250813934 + 0.11973635845161751 + 0.11973992445977147 + 0.11974349053260418 + 0.11974705667011869 + 0.11975062287231793 + 0.11975418913920517 + 0.11975775547078328 + 0.1197613218670554 + 0.11976488832802447 + 0.11976845485369333 + 0.11977202144406533 + 0.11977558809914364 + 0.11977915481893069 + 0.11978272160343004 + 0.11978628845264458 + 0.11978985536657728 + 0.11979342234523116 + 0.11979698938860939 + 0.11980055649671476 + 0.11980412366955069 + 0.11980769090711978 + 0.11981125820942543 + 0.11981482557647039 + 0.11981839300825782 + 0.11982196050479098 + 0.11982552806607243 + 0.11982909569210538 + 0.1198326633828931 + 0.1198362311384384 + 0.1198397989587444 + 0.11984336684381419 + 0.11984693479365056 + 0.11985050280825674 + 0.11985407088763568 + 0.11985763903179047 + 0.11986120724072426 + 0.11986477551443994 + 0.11986834385294051 + 0.11987191225622905 + 0.11987548072430859 + 0.11987904925718229 + 0.11988261785485319 + 0.11988618651732394 + 0.11988975524459788 + 0.1198933240366781 + 0.11989689289356766 + 0.11990046181526946 + 0.11990403080178644 + 0.11990759985312194 + 0.1199111689692787 + 0.11991473815025991 + 0.11991830739606858 + 0.11992187670670781 + 0.11992544608218045 + 0.11992901552248972 + 0.11993258502763864 + 0.11993615459763017 + 0.11993972423246736 + 0.11994329393215321 + 0.11994686369669097 + 0.11995043352608327 + 0.11995400342033365 + 0.11995757337944486 + 0.11996114340341996 + 0.11996471349226205 + 0.11996828364597406 + 0.11997185386455914 + 0.11997542414802025 + 0.11997899449636035 + 0.11998256490958274 + 0.11998613538769021 + 0.11998970593068597 + 0.11999327653857307 + 0.11999684721135438 + 0.12000041794903291 + 0.120003988751612 + 0.12000755961909457 + 0.12001113055148332 + 0.12001470154878172 + 0.12001827261099259 + 0.12002184373811919 + 0.12002541493016439 + 0.12002898618713113 + 0.1200325575090227 + 0.12003612889584184 + 0.12003970034759186 + 0.12004327186427566 + 0.12004684344589638 + 0.12005041509245701 + 0.12005398680396047 + 0.12005755858041005 + 0.12006113042180853 + 0.12006470232815913 + 0.12006827429946483 + 0.12007184633572882 + 0.12007541843695387 + 0.12007899060314312 + 0.12008256283429972 + 0.12008613513042658 + 0.12008970749152686 + 0.12009327991760349 + 0.12009685240865962 + 0.1201004249646983 + 0.12010399758572236 + 0.12010757027173505 + 0.1201111430227394 + 0.12011471583873835 + 0.12011828871973508 + 0.12012186166573255 + 0.12012543467673363 + 0.1201290077527417 + 0.12013258089375969 + 0.12013615409979045 + 0.12013972737083736 + 0.12014330070690306 + 0.12014687410799099 + 0.12015044757410399 + 0.12015402110524508 + 0.12015759470141731 + 0.12016116836262387 + 0.1201647420888677 + 0.12016831588015182 + 0.1201718897364794 + 0.12017546365785312 + 0.12017903764427643 + 0.1201826116957523 + 0.12018618581228359 + 0.12018975999387362 + 0.12019333424052538 + 0.12019690855224162 + 0.12020048292902548 + 0.12020405737088036 + 0.12020763187780888 + 0.12021120644981441 + 0.1202147810868998 + 0.12021835578906795 + 0.1202219305563224 + 0.12022550538866564 + 0.12022908028610126 + 0.12023265524863175 + 0.12023623027626065 + 0.12023980536899062 + 0.12024338052682497 + 0.12024695574976656 + 0.12025053103781858 + 0.12025410639098402 + 0.12025768180926588 + 0.12026125729266735 + 0.12026483284119123 + 0.12026840845484082 + 0.12027198413361904 + 0.1202755598775291 + 0.12027913568657383 + 0.12028271156075634 + 0.12028628750007972 + 0.120289863504547 + 0.12029343957416132 + 0.12029701570892561 + 0.12030059190884278 + 0.12030416817391626 + 0.12030774450414872 + 0.12031132089954354 + 0.12031489736010349 + 0.12031847388583167 + 0.12032205047673146 + 0.1203256271328053 + 0.12032920385405679 + 0.12033278064048879 + 0.12033635749210422 + 0.12033993440890621 + 0.12034351139089798 + 0.12034708843808231 + 0.12035066555046255 + 0.12035424272804132 + 0.12035781997082218 + 0.12036139727880789 + 0.12036497465200145 + 0.12036855209040605 + 0.12037212959402477 + 0.12037570716286049 + 0.12037928479691641 + 0.12038286249619543 + 0.12038644026070078 + 0.12039001809043541 + 0.12039359598540249 + 0.12039717394560487 + 0.12040075197104566 + 0.12040433006172806 + 0.12040790821765501 + 0.12041148643882955 + 0.12041506472525476 + 0.12041864307693369 + 0.12042222149386943 + 0.12042579997606495 + 0.12042937852352327 + 0.12043295713624759 + 0.12043653581424094 + 0.12044011455750626 + 0.12044369336604667 + 0.1204472722398654 + 0.12045085117896513 + 0.120454430183349 + 0.12045800925302035 + 0.12046158838798213 + 0.12046516758823714 + 0.12046874685378851 + 0.1204723261846397 + 0.12047590558079332 + 0.12047948504225259 + 0.12048306456902044 + 0.12048664416110005 + 0.12049022381849446 + 0.1204938035412069 + 0.12049738332924004 + 0.12050096318259719 + 0.12050454310128138 + 0.12050812308529557 + 0.12051170313464289 + 0.12051528324932641 + 0.12051886342934913 + 0.12052244367471412 + 0.12052602398542449 + 0.12052960436148329 + 0.12053318480289345 + 0.12053676530965818 + 0.12054034588178027 + 0.1205439265192632 + 0.1205475072221099 + 0.12055108799032309 + 0.12055466882390625 + 0.12055824972286219 + 0.12056183068719403 + 0.12056541171690478 + 0.12056899281199761 + 0.12057257397247545 + 0.12057615519834135 + 0.12057973648959872 + 0.12058331784625005 + 0.12058689926829885 + 0.12059048075574803 + 0.12059406230860044 + 0.12059764392685952 + 0.12060122561052809 + 0.1206048073596091 + 0.12060838917410591 + 0.12061197105402123 + 0.12061555299935857 + 0.12061913501012068 + 0.12062271708631062 + 0.12062629922793149 + 0.1206298814349864 + 0.12063346370747845 + 0.12063704604541046 + 0.1206406284487858 + 0.12064421091760719 + 0.12064779345187801 + 0.12065137605160108 + 0.12065495871677978 + 0.12065854144741672 + 0.12066212424351538 + 0.12066570710507846 + 0.12066929003210937 + 0.1206728730246108 + 0.12067645608258605 + 0.12068003920603837 + 0.12068362239497038 + 0.12068720564938545 + 0.12069078896928638 + 0.12069437235467649 + 0.12069795580555867 + 0.12070153932193621 + 0.12070512290381186 + 0.12070870655118891 + 0.12071229026407031 + 0.12071587404245915 + 0.12071945788635849 + 0.12072304179577156 + 0.12072662577070095 + 0.1207302098111504 + 0.12073379391712231 + 0.12073737808862015 + 0.12074096232564691 + 0.12074454662820547 + 0.12074813099629926 + 0.12075171542993104 + 0.12075529992910375 + 0.12075888449382083 + 0.12076246912408514 + 0.12076605381989981 + 0.1207696385812678 + 0.12077322340819224 + 0.12077680830067616 + 0.12078039325872267 + 0.12078397828233486 + 0.12078756337151578 + 0.12079114852626835 + 0.12079473374659583 + 0.12079831903250118 + 0.12080190438398739 + 0.12080548980105771 + 0.12080907528371516 + 0.12081266083196267 + 0.1208162464458034 + 0.1208198321252404 + 0.12082341787027688 + 0.12082700368091565 + 0.12083058955715988 + 0.12083417549901268 + 0.12083776150647697 + 0.12084134757955618 + 0.1208449337182529 + 0.12084851992257054 + 0.1208521061925119 + 0.12085569252808036 + 0.12085927892927857 + 0.12086286539611008 + 0.12086645192857763 + 0.12087003852668446 + 0.12087362519043342 + 0.12087721191982781 + 0.12088079871487051 + 0.12088438557556465 + 0.12088797250191352 + 0.12089155949391976 + 0.12089514655158672 + 0.12089873367491744 + 0.12090232086391495 + 0.12090590811858226 + 0.12090949543892253 + 0.12091308282493875 + 0.12091667027663415 + 0.12092025779401155 + 0.12092384537707426 + 0.12092743302582515 + 0.1209310207402674 + 0.12093460852040409 + 0.12093819636623832 + 0.12094178427777294 + 0.12094537225501126 + 0.12094896029795618 + 0.12095254840661089 + 0.12095613658097844 + 0.12095972482106195 + 0.12096331312686427 + 0.12096690149838869 + 0.12097048993563821 + 0.1209740784386158 + 0.12097766700732465 + 0.12098125564176784 + 0.12098484434194845 + 0.12098843310786932 + 0.12099202193953389 + 0.12099561083694486 + 0.12099919980010558 + 0.12100278882901916 + 0.12100637792368828 + 0.12100996708411632 + 0.12101355631030637 + 0.12101714560226143 + 0.12102073495998455 + 0.12102432438347868 + 0.12102791387274715 + 0.12103150342779287 + 0.12103509304861899 + 0.12103868273522847 + 0.12104227248762452 + 0.12104586230581012 + 0.12104945218978837 + 0.12105304213956221 + 0.12105663215513501 + 0.12106022223650967 + 0.12106381238368909 + 0.12106740259667667 + 0.12107099287547524 + 0.12107458322008806 + 0.12107817363051791 + 0.12108176410676819 + 0.12108535464884188 + 0.1210889452567419 + 0.12109253593047145 + 0.12109612667003361 + 0.12109971747543145 + 0.12110330834666794 + 0.12110689928374628 + 0.12111049028666951 + 0.12111408135544072 + 0.1211176724900629 + 0.12112126369053929 + 0.12112485495687278 + 0.12112844628906634 + 0.12113203768712354 + 0.12113562915104688 + 0.12113922068083977 + 0.12114281227650528 + 0.12114640393804632 + 0.12114999566546605 + 0.12115358745876757 + 0.12115717931795394 + 0.12116077124302829 + 0.12116436323399361 + 0.12116795529085284 + 0.12117154741360936 + 0.12117513960226617 + 0.12117873185682616 + 0.12118232417729258 + 0.12118591656366839 + 0.12118950901595667 + 0.12119310153416069 + 0.12119669411828334 + 0.12120028676832777 + 0.12120387948429698 + 0.12120747226619415 + 0.12121106511402226 + 0.12121465802778437 + 0.12121825100748368 + 0.12122184405312325 + 0.12122543716470588 + 0.12122903034223503 + 0.12123262358571377 + 0.1212362168951448 + 0.12123981027053155 + 0.12124340371187702 + 0.12124699721918404 + 0.12125059079245601 + 0.12125418443169597 + 0.12125777813690686 + 0.12126137190809176 + 0.12126496574525387 + 0.12126855964839631 + 0.12127215361752178 + 0.12127574765263377 + 0.12127934175373525 + 0.1212829359208293 + 0.12128653015391883 + 0.1212901244530071 + 0.1212937188180972 + 0.12129731324919217 + 0.1213009077462949 + 0.1213045023094089 + 0.12130809693853682 + 0.12131169163368195 + 0.12131528639484726 + 0.12131888122203603 + 0.12132247611525117 + 0.12132607107449579 + 0.12132966609977285 + 0.12133326119108578 + 0.1213368563484373 + 0.12134045157183071 + 0.12134404686126901 + 0.12134764221675517 + 0.12135123763829248 + 0.12135483312588392 + 0.12135842867953248 + 0.12136202429924142 + 0.12136561998501387 + 0.12136921573685262 + 0.12137281155476096 + 0.12137640743874187 + 0.12138000338879852 + 0.12138359940493396 + 0.12138719548715138 + 0.12139079163545349 + 0.12139438784984381 + 0.12139798413032525 + 0.12140158047690085 + 0.12140517688957371 + 0.12140877336834695 + 0.12141236991322377 + 0.12141596652420691 + 0.12141956320129971 + 0.12142315994450546 + 0.12142675675382662 + 0.12143035362926681 + 0.12143395057082904 + 0.12143754757851602 + 0.12144114465233133 + 0.12144474179227768 + 0.12144833899835855 + 0.12145193627057667 + 0.12145553360893509 + 0.12145913101343719 + 0.12146272848408592 + 0.12146632602088438 + 0.12146992362383559 + 0.12147352129294262 + 0.1214771190282086 + 0.12148071682963667 + 0.12148431469722984 + 0.12148791263099107 + 0.12149151063092385 + 0.12149510869703097 + 0.12149870682931539 + 0.12150230502778049 + 0.12150590329242902 + 0.12150950162326449 + 0.12151310002028981 + 0.12151669848350789 + 0.12152029701292198 + 0.12152389560853526 + 0.12152749427035045 + 0.12153109299837116 + 0.1215346917926 + 0.12153829065304031 + 0.12154188957969518 + 0.12154548857256738 + 0.12154908763166045 + 0.12155268675697728 + 0.1215562859485209 + 0.12155988520629453 + 0.12156348453030105 + 0.12156708392054384 + 0.12157068337702578 + 0.12157428289975002 + 0.12157788248871945 + 0.12158148214393751 + 0.12158508186540712 + 0.12158868165313126 + 0.12159228150711313 + 0.12159588142735599 + 0.12159948141386255 + 0.12160308146663625 + 0.12160668158567994 + 0.12161028177099682 + 0.12161388202258995 + 0.12161748234046241 + 0.12162108272461727 + 0.1216246831750576 + 0.12162828369178666 + 0.12163188427480749 + 0.12163548492412286 + 0.12163908563973631 + 0.12164268642165074 + 0.12164628726986908 + 0.12164988818439475 + 0.12165348916523056 + 0.1216570902123796 + 0.12166069132584524 + 0.12166429250563031 + 0.12166789375173803 + 0.12167149506417141 + 0.12167509644293358 + 0.12167869788802743 + 0.12168229939945648 + 0.12168590097722357 + 0.12168950262133157 + 0.12169310433178408 + 0.12169670610858394 + 0.12170030795173413 + 0.12170390986123775 + 0.1217075118370981 + 0.12171111387931803 + 0.12171471598790083 + 0.12171831816284957 + 0.1217219204041671 + 0.12172552271185684 + 0.12172912508592165 + 0.1217327275263647 + 0.12173633003318908 + 0.12173993260639805 + 0.12174353524599439 + 0.12174713795198144 + 0.12175074072436214 + 0.12175434356313962 + 0.12175794646831722 + 0.12176154943989757 + 0.12176515247788414 + 0.12176875558227983 + 0.12177235875308762 + 0.12177596199031104 + 0.12177956529395285 + 0.12178316866401616 + 0.12178677210050422 + 0.12179037560341989 + 0.12179397917276652 + 0.12179758280854701 + 0.12180118651076459 + 0.12180479027942219 + 0.12180839411452316 + 0.12181199801607029 + 0.12181560198406681 + 0.12181920601851602 + 0.12182281011942066 + 0.12182641428678402 + 0.12183001852060911 + 0.12183362282089923 + 0.1218372271876572 + 0.12184083162088627 + 0.12184443612058973 + 0.12184804068677012 + 0.12185164531943107 + 0.1218552500185755 + 0.1218588547842064 + 0.1218624596163268 + 0.12186606451494017 + 0.1218696694800494 + 0.12187327451165751 + 0.12187687960976755 + 0.12188048477438289 + 0.12188409000550646 + 0.12188769530314121 + 0.12189130066729043 + 0.1218949060979572 + 0.12189851159514478 + 0.12190211715885574 + 0.12190572278909383 + 0.12190932848586154 + 0.12191293424916248 + 0.12191654007899945 + 0.12192014597537569 + 0.12192375193829412 + 0.12192735796775804 + 0.12193096406377039 + 0.12193457022633436 + 0.1219381764554531 + 0.1219417827511295 + 0.12194538911336707 + 0.12194899554216845 + 0.12195260203753702 + 0.12195620859947565 + 0.12195981522798771 + 0.12196342192307591 + 0.12196702868474385 + 0.12197063551299445 + 0.12197424240783056 + 0.12197784936925561 + 0.12198145639727238 + 0.12198506349188426 + 0.12198867065309411 + 0.1219922778809053 + 0.12199588517532078 + 0.1219994925363436 + 0.12200309996397694 + 0.12200670745822387 + 0.12201031501908749 + 0.12201392264657099 + 0.12201753034067728 + 0.12202113810140958 + 0.12202474592877104 + 0.1220283538227647 + 0.12203196178339368 + 0.12203556981066101 + 0.12203917790456989 + 0.12204278606512335 + 0.12204639429232453 + 0.12205000258617667 + 0.12205361094668248 + 0.12205721937384537 + 0.12206082786766845 + 0.12206443642815476 + 0.12206804505530737 + 0.12207165374912943 + 0.1220752625096241 + 0.12207887133679425 + 0.12208248023064319 + 0.12208608919117396 + 0.12208969821838975 + 0.12209330731229354 + 0.12209691647288852 + 0.12210052570017771 + 0.12210413499416439 + 0.12210774435485142 + 0.12211135378224199 + 0.12211496327633931 + 0.12211857283714635 + 0.12212218246466629 + 0.1221257921589023 + 0.1221294019198573 + 0.12213301174753451 + 0.122136621641937 + 0.12214023160306785 + 0.12214384163093024 + 0.12214745172552724 + 0.12215106188686205 + 0.12215467211493765 + 0.12215828240975729 + 0.12216189277132378 + 0.12216550319964044 + 0.12216911369471037 + 0.12217272425653661 + 0.12217633488512235 + 0.12217994558047064 + 0.12218355634258467 + 0.12218716717146741 + 0.12219077806712206 + 0.12219438902955165 + 0.12219800005875946 + 0.1222016111547484 + 0.12220522231752158 + 0.12220883354708227 + 0.12221244484343349 + 0.1222160562065783 + 0.12221966763651981 + 0.12222327913326116 + 0.12222689069680555 + 0.12223050232715589 + 0.1222341140243155 + 0.12223772578828741 + 0.12224133761907474 + 0.1222449495166803 + 0.12224856148110785 + 0.12225217351235983 + 0.1222557856104398 + 0.12225939777535047 + 0.12226301000709537 + 0.12226662230567725 + 0.1222702346710994 + 0.12227384710336506 + 0.12227745960247711 + 0.12228107216843874 + 0.12228468480125304 + 0.12228829750092313 + 0.12229191026745222 + 0.12229552310084316 + 0.1222991360010994 + 0.12230274896822374 + 0.12230636200221943 + 0.12230997510308973 + 0.1223135882708374 + 0.12231720150546577 + 0.12232081480697803 + 0.1223244281753771 + 0.12232804161066624 + 0.12233165511284853 + 0.12233526868192697 + 0.12233888231790474 + 0.12234249602078505 + 0.12234610979057091 + 0.12234972362726541 + 0.12235333753087166 + 0.12235695150139286 + 0.12236056553883198 + 0.12236417964319227 + 0.12236779381447679 + 0.12237140805268867 + 0.12237502235783097 + 0.12237863672990695 + 0.12238225116891935 + 0.12238586567487175 + 0.12238948024776702 + 0.12239309488760833 + 0.12239670959439873 + 0.12240032436814136 + 0.12240393920883944 + 0.12240755411649575 + 0.12241116909111385 + 0.12241478413269659 + 0.12241839924124716 + 0.12242201441676852 + 0.12242562965926417 + 0.12242924496873664 + 0.12243286034518952 + 0.12243647578862575 + 0.12244009129904847 + 0.12244370687646096 + 0.12244732252086593 + 0.12245093823226698 + 0.12245455401066677 + 0.12245816985606862 + 0.12246178576847577 + 0.12246540174789107 + 0.12246901779431781 + 0.1224726339077591 + 0.12247625008821808 + 0.12247986633569767 + 0.1224834826502013 + 0.12248709903173173 + 0.12249071548029242 + 0.12249433199588601 + 0.12249794857851633 + 0.12250156522818581 + 0.12250518194489791 + 0.12250879872865568 + 0.12251241557946234 + 0.12251603249732085 + 0.1225196494822345 + 0.12252326653420605 + 0.12252688365323897 + 0.12253050083933616 + 0.12253411809250091 + 0.12253773541273641 + 0.12254135280004551 + 0.12254497025443142 + 0.12254858777589721 + 0.12255220536444623 + 0.12255582302008136 + 0.12255944074280595 + 0.12256305853262281 + 0.12256667638953508 + 0.1225702943135462 + 0.12257391230465911 + 0.12257753036287687 + 0.12258114848820273 + 0.12258476668063953 + 0.12258838494019075 + 0.12259200326685933 + 0.12259562166064825 + 0.12259924012156083 + 0.12260285864960027 + 0.12260647724476954 + 0.1226100959070717 + 0.12261371463650987 + 0.12261733343308728 + 0.12262095229680715 + 0.12262457122767229 + 0.12262819022568611 + 0.12263180929085145 + 0.12263542842317174 + 0.12263904762265009 + 0.1226426668892892 + 0.12264628622309265 + 0.12264990562406319 + 0.12265352509220431 + 0.12265714462751894 + 0.12266076423001018 + 0.12266438389968125 + 0.122668003636535 + 0.12267162344057493 + 0.12267524331180406 + 0.12267886325022527 + 0.12268248325584194 + 0.12268610332865708 + 0.12268972346867371 + 0.12269334367589511 + 0.12269696395032438 + 0.1227005842919648 + 0.12270420470081912 + 0.1227078251768908 + 0.12271144572018275 + 0.12271506633069816 + 0.12271868700844017 + 0.12272230775341195 + 0.12272592856561643 + 0.12272954944505683 + 0.12273317039173649 + 0.12273679140565823 + 0.12274041248682541 + 0.12274403363524099 + 0.12274765485090801 + 0.12275127613382975 + 0.12275489748400949 + 0.12275851890145 + 0.12276214038615464 + 0.12276576193812654 + 0.12276938355736867 + 0.12277300524388417 + 0.1227766269976763 + 0.12278024881874809 + 0.1227838707071027 + 0.12278749266274314 + 0.12279111468567283 + 0.12279473677589459 + 0.12279835893341168 + 0.12280198115822716 + 0.12280560345034428 + 0.12280922580976607 + 0.1228128482364956 + 0.12281647073053607 + 0.12282009329189067 + 0.1228237159205624 + 0.12282733861655437 + 0.1228309613798698 + 0.1228345842105118 + 0.12283820710848355 + 0.12284183007378807 + 0.12284545310642858 + 0.12284907620640804 + 0.1228526993737297 + 0.12285632260839675 + 0.12285994591041226 + 0.12286356927977928 + 0.12286719271650107 + 0.12287081622058063 + 0.12287443979202116 + 0.12287806343082566 + 0.12288168713699754 + 0.12288531091053952 + 0.12288893475145504 + 0.12289255865974735 + 0.12289618263541915 + 0.12289980667847376 + 0.12290343078891458 + 0.12290705496674434 + 0.12291067921196641 + 0.1229143035245838 + 0.12291792790459954 + 0.12292155235201707 + 0.12292517686683932 + 0.12292880144906936 + 0.12293242609871041 + 0.12293605081576554 + 0.12293967560023812 + 0.12294330045213087 + 0.12294692537144726 + 0.1229505503581903 + 0.12295417541236307 + 0.12295780053396868 + 0.12296142572301046 + 0.12296505097949127 + 0.12296867630341425 + 0.12297230169478283 + 0.12297592715359999 + 0.12297955267986888 + 0.12298317827359245 + 0.12298680393477394 + 0.12299042966341651 + 0.12299405545952345 + 0.12299768132309757 + 0.12300130725414221 + 0.12300493325266036 + 0.1230085593186554 + 0.12301218545213015 + 0.12301581165308788 + 0.12301943792153189 + 0.123023064257465 + 0.12302669066089045 + 0.12303031713181163 + 0.12303394367023132 + 0.12303757027615282 + 0.12304119694957917 + 0.12304482369051359 + 0.12304845049895918 + 0.1230520773749192 + 0.12305570431839653 + 0.12305933132939453 + 0.12306295840791623 + 0.12306658555396453 + 0.1230702127675431 + 0.12307384004865463 + 0.12307746739730238 + 0.12308109481348958 + 0.12308472229721923 + 0.12308834984849448 + 0.12309197746731863 + 0.12309560515369455 + 0.12309923290762562 + 0.12310286072911472 + 0.12310648861816516 + 0.12311011657478013 + 0.12311374459896259 + 0.12311737269071585 + 0.12312100085004288 + 0.123124629076947 + 0.12312825737143117 + 0.12313188573349855 + 0.12313551416315224 + 0.12313914266039558 + 0.12314277122523153 + 0.12314639985766326 + 0.12315002855769398 + 0.12315365732532657 + 0.12315728616056458 + 0.12316091506341073 + 0.12316454403386849 + 0.12316817307194076 + 0.12317180217763087 + 0.12317543135094164 + 0.12317906059187658 + 0.12318268990043868 + 0.12318631927663101 + 0.12318994872045683 + 0.12319357823191916 + 0.12319720781102113 + 0.12320083745776592 + 0.12320446717215676 + 0.1232080969541967 + 0.12321172680388888 + 0.12321535672123644 + 0.12321898670624248 + 0.12322261675891015 + 0.12322624687924248 + 0.12322987706724287 + 0.12323350732291452 + 0.12323713764626003 + 0.12324076803728318 + 0.12324439849598652 + 0.12324802902237365 + 0.12325165961644757 + 0.12325529027821124 + 0.12325892100766804 + 0.12326255180482107 + 0.12326618266967321 + 0.12326981360222811 + 0.12327344460248831 + 0.12327707567045744 + 0.12328070680613831 + 0.12328433800953413 + 0.12328796928064829 + 0.12329160061948365 + 0.12329523202604331 + 0.12329886350033055 + 0.12330249504234865 + 0.12330612665210058 + 0.1233097583295894 + 0.12331339007481833 + 0.12331702188779065 + 0.12332065376850927 + 0.12332428571697748 + 0.12332791773319826 + 0.12333154981717502 + 0.12333518196891058 + 0.12333881418840856 + 0.12334244647567143 + 0.12334607883070292 + 0.1233497112535059 + 0.12335334374408355 + 0.12335697630243889 + 0.12336060892857535 + 0.1233642416224959 + 0.12336787438420363 + 0.12337150721370167 + 0.12337514011099339 + 0.12337877307608164 + 0.12338240610896986 + 0.1233860392096609 + 0.12338967237815808 + 0.12339330561446431 + 0.12339693891858328 + 0.12340057229051746 + 0.12340420573027049 + 0.12340783923784528 + 0.12341147281324508 + 0.12341510645647283 + 0.12341874016753186 + 0.1234223739464253 + 0.12342600779315634 + 0.12342964170772795 + 0.12343327569014338 + 0.12343690974040586 + 0.12344054385851833 + 0.12344417804448402 + 0.12344781229830623 + 0.12345144661998794 + 0.1234550810095323 + 0.12345871546694237 + 0.12346234999222154 + 0.12346598458537272 + 0.12346961924639936 + 0.12347325397530433 + 0.1234768887720907 + 0.12348052363676178 + 0.12348415856932077 + 0.12348779356977078 + 0.12349142863811494 + 0.12349506377435623 + 0.12349869897849805 + 0.12350233425054329 + 0.1235059695904954 + 0.12350960499835739 + 0.12351324047413224 + 0.12351687601782324 + 0.12352051162943367 + 0.12352414730896646 + 0.12352778305642509 + 0.12353141887181211 + 0.12353505475513116 + 0.12353869070638525 + 0.12354232672557741 + 0.12354596281271098 + 0.12354959896778893 + 0.12355323519081464 + 0.12355687148179118 + 0.12356050784072145 + 0.12356414426760881 + 0.12356778076245653 + 0.12357141732526734 + 0.12357505395604491 + 0.12357869065479189 + 0.12358232742151198 + 0.12358596425620771 + 0.12358960115888271 + 0.12359323812953998 + 0.12359687516818262 + 0.12360051227481382 + 0.12360414944943668 + 0.12360778669205436 + 0.12361142400266993 + 0.12361506138128686 + 0.12361869882790801 + 0.1236223363425366 + 0.12362597392517571 + 0.12362961157582864 + 0.12363324929449845 + 0.12363688708118825 + 0.12364052493590118 + 0.12364416285864062 + 0.12364780084940952 + 0.12365143890821104 + 0.12365507703504831 + 0.12365871522992451 + 0.12366235349284273 + 0.12366599182380633 + 0.12366963022281836 + 0.12367326868988188 + 0.12367690722500008 + 0.12368054582817603 + 0.12368418449941312 + 0.12368782323871436 + 0.12369146204608274 + 0.12369510092152176 + 0.12369873986503432 + 0.12370237887662359 + 0.12370601795629287 + 0.12370965710404516 + 0.12371329631988363 + 0.12371693560381139 + 0.12372057495583175 + 0.1237242143759478 + 0.12372785386416271 + 0.12373149342047951 + 0.12373513304490147 + 0.12373877273743178 + 0.12374241249807359 + 0.12374605232682971 + 0.12374969222370372 + 0.12375333218869869 + 0.1237569722218177 + 0.12376061232306393 + 0.12376425249244033 + 0.12376789272995042 + 0.12377153303559714 + 0.12377517340938358 + 0.12377881385131304 + 0.12378245436138859 + 0.1237860949396135 + 0.12378973558599092 + 0.12379337630052391 + 0.12379701708321542 + 0.12380065793406905 + 0.12380429885308751 + 0.12380793984027436 + 0.12381158089563254 + 0.12381522201916535 + 0.12381886321087572 + 0.1238225044707668 + 0.12382614579884192 + 0.12382978719510433 + 0.1238334286595569 + 0.12383707019220314 + 0.12384071179304572 + 0.12384435346208826 + 0.12384799519933358 + 0.12385163700478503 + 0.12385527887844575 + 0.12385892082031881 + 0.12386256283040741 + 0.12386620490871474 + 0.12386984705524394 + 0.12387348926999804 + 0.12387713155298052 + 0.12388077390419427 + 0.12388441632364242 + 0.12388805881132824 + 0.1238917013672549 + 0.12389534399142557 + 0.12389898668384328 + 0.12390262944451134 + 0.12390627227343283 + 0.1239099151706108 + 0.12391355813604864 + 0.12391720116974934 + 0.12392084427171618 + 0.12392448744195204 + 0.12392813068046052 + 0.12393177398724445 + 0.12393541736230709 + 0.12393906080565151 + 0.12394270431728106 + 0.12394634789719879 + 0.1239499915454078 + 0.12395363526191137 + 0.12395727904671257 + 0.12396092289981461 + 0.12396456682122071 + 0.1239682108109337 + 0.12397185486895722 + 0.12397549899529396 + 0.12397914318994754 + 0.12398278745292082 + 0.12398643178421709 + 0.12399007618383941 + 0.123993720651791 + 0.1239973651880749 + 0.1240010097926947 + 0.12400465446565287 + 0.12400829920695318 + 0.1240119440165984 + 0.12401558889459197 + 0.12401923384093684 + 0.12402287885563637 + 0.12402652393869348 + 0.12403016909011159 + 0.12403381430989374 + 0.12403745959804287 + 0.12404110495456255 + 0.1240447503794557 + 0.12404839587272555 + 0.12405204143437522 + 0.12405568706440792 + 0.12405933276282673 + 0.12406297852963487 + 0.12406662436483561 + 0.1240702702684318 + 0.12407391624042705 + 0.12407756228082423 + 0.1240812083896265 + 0.12408485456683717 + 0.1240885008124591 + 0.12409214712649587 + 0.12409579350895045 + 0.12409943995982581 + 0.12410308647912546 + 0.12410673306685237 + 0.12411037972300978 + 0.12411402644760063 + 0.12411767324062843 + 0.1241213201020961 + 0.12412496703200675 + 0.12412861403036399 + 0.12413226109717058 + 0.12413590823242966 + 0.12413955543614461 + 0.12414320270831843 + 0.12414685004895434 + 0.12415049745805551 + 0.12415414493562522 + 0.12415779248166654 + 0.12416144009618259 + 0.12416508777917643 + 0.1241687355306515 + 0.12417238335061082 + 0.12417603123905757 + 0.12417967919599499 + 0.1241833272214259 + 0.124186975315354 + 0.12419062347778212 + 0.1241942717087135 + 0.1241979200081513 + 0.12420156837609866 + 0.12420521681255894 + 0.12420886531753497 + 0.12421251389103018 + 0.12421616253304764 + 0.12421981124359041 + 0.12422346002266188 + 0.12422710887026515 + 0.12423075778640341 + 0.12423440677107961 + 0.12423805582429705 + 0.12424170494605903 + 0.12424535413636863 + 0.1242490033952289 + 0.12425265272264327 + 0.12425630211861456 + 0.12425995158314634 + 0.12426360111624134 + 0.12426725071790311 + 0.12427090038813464 + 0.12427455012693905 + 0.1242781999343197 + 0.12428184981027951 + 0.12428549975482189 + 0.12428914976794976 + 0.12429279984966644 + 0.12429644999997519 + 0.12430010021887915 + 0.12430375050638123 + 0.12430740086248503 + 0.12431105128719326 + 0.12431470178050935 + 0.12431835234243641 + 0.12432200297297775 + 0.12432565367213627 + 0.12432930443991538 + 0.1243329552763182 + 0.12433660618134773 + 0.12434025715500743 + 0.1243439081973001 + 0.1243475593082293 + 0.12435121048779806 + 0.12435486173600933 + 0.12435851305286653 + 0.12436216443837293 + 0.12436581589253141 + 0.12436946741534521 + 0.12437311900681768 + 0.12437677066695182 + 0.12438042239575096 + 0.12438407419321817 + 0.12438772605935634 + 0.12439137799416933 + 0.12439502999765972 + 0.12439868206983079 + 0.12440233421068589 + 0.12440598642022799 + 0.1244096386984606 + 0.12441329104538645 + 0.12441694346100907 + 0.12442059594533127 + 0.12442424849835661 + 0.12442790112008825 + 0.12443155381052892 + 0.1244352065696822 + 0.12443885939755112 + 0.12444251229413897 + 0.12444616525944878 + 0.12444981829348377 + 0.12445347139624707 + 0.12445712456774211 + 0.12446077780797164 + 0.12446443111693924 + 0.1244680844946478 + 0.12447173794110064 + 0.12447539145630089 + 0.12447904504025167 + 0.12448269869295621 + 0.12448635241441773 + 0.12449000620463932 + 0.12449366006362418 + 0.12449731399137576 + 0.12450096798789669 + 0.12450462205319057 + 0.12450827618726049 + 0.12451193039010942 + 0.12451558466174073 + 0.12451923900215764 + 0.12452289341136318 + 0.12452654788936054 + 0.12453020243615313 + 0.12453385705174375 + 0.12453751173613598 + 0.12454116648933267 + 0.12454482131133711 + 0.12454847620215255 + 0.12455213116178204 + 0.12455578619022878 + 0.12455944128749623 + 0.12456309645358707 + 0.12456675168850478 + 0.1245704069922524 + 0.1245740623648334 + 0.12457771780625065 + 0.12458137331650745 + 0.12458502889560699 + 0.12458868454355239 + 0.12459234026034686 + 0.12459599604599357 + 0.12459965190049586 + 0.12460330782385652 + 0.12460696381607909 + 0.12461061987716657 + 0.12461427600712224 + 0.12461793220594923 + 0.12462158847365067 + 0.12462524481022969 + 0.12462890121568976 + 0.12463255769003379 + 0.12463621423326507 + 0.12463987084538668 + 0.12464352752640194 + 0.12464718427631397 + 0.12465084109512591 + 0.12465449798284103 + 0.12465815493946231 + 0.12466181196499329 + 0.12466546905943669 + 0.12466912622279605 + 0.12467278345507432 + 0.12467644075627499 + 0.12468009812640091 + 0.12468375556545559 + 0.12468741307344171 + 0.12469107065036297 + 0.12469472829622219 + 0.12469838601102291 + 0.12470204379476792 + 0.1247057016474606 + 0.12470935956910426 + 0.12471301755970171 + 0.12471667561925648 + 0.12472033374777164 + 0.12472399194525044 + 0.12472765021169592 + 0.12473130854711138 + 0.12473496695149978 + 0.12473862542486465 + 0.12474228396720893 + 0.12474594257853582 + 0.12474960125884874 + 0.1247532600081504 + 0.1247569188264445 + 0.12476057771373403 + 0.12476423667002204 + 0.12476789569531165 + 0.12477155478960646 + 0.1247752139529093 + 0.12477887318522339 + 0.12478253248655218 + 0.12478619185689849 + 0.12478985129626576 + 0.124793510804657 + 0.12479717038207563 + 0.12480083002852439 + 0.12480448974400687 + 0.12480814952852622 + 0.12481180938208553 + 0.12481546930468787 + 0.12481912929633664 + 0.12482278935703504 + 0.12482644948678598 + 0.12483010968559305 + 0.12483376995345905 + 0.12483743029038744 + 0.12484109069638115 + 0.12484475117144352 + 0.12484841171557765 + 0.12485207232878705 + 0.12485573301107436 + 0.12485939376244327 + 0.12486305458289673 + 0.12486671547243788 + 0.12487037643106996 + 0.1248740374587963 + 0.12487769855561975 + 0.12488135972154391 + 0.12488502095657165 + 0.12488868226070637 + 0.12489234363395102 + 0.12489600507630912 + 0.12489966658778361 + 0.12490332816837758 + 0.1249069898180945 + 0.12491065153693748 + 0.1249143133249096 + 0.124917975182014 + 0.12492163710825413 + 0.12492529910363299 + 0.12492896116815373 + 0.12493262330181966 + 0.12493628550463388 + 0.12493994777659968 + 0.12494361011772015 + 0.12494727252799855 + 0.12495093500743799 + 0.12495459755604178 + 0.12495826017381281 + 0.12496192286075471 + 0.12496558561687042 + 0.12496924844216313 + 0.12497291133663602 + 0.12497657430029233 + 0.1249802373331354 + 0.12498390043516805 + 0.12498756360639378 + 0.12499122684681556 + 0.12499489015643687 + 0.12499855353526068 + 0.12500221698329023 + 0.12500588050052869 + 0.1250095440869792 + 0.12501320774264524 + 0.12501687146752963 + 0.1250205352616357 + 0.12502419912496676 + 0.12502786305752589 + 0.12503152705931608 + 0.12503519113034103 + 0.12503885527060352 + 0.12504251948010681 + 0.1250461837588541 + 0.1250498481068488 + 0.12505351252409372 + 0.12505717701059238 + 0.12506084156634772 + 0.12506450619136322 + 0.1250681708856419 + 0.12507183564918689 + 0.12507550048200144 + 0.12507916538408884 + 0.1250828303554522 + 0.12508649539609468 + 0.12509016050601937 + 0.12509382568522981 + 0.12509749093372882 + 0.12510115625151996 + 0.12510482163860601 + 0.12510848709499067 + 0.12511215262067657 + 0.12511581821566731 + 0.12511948387996591 + 0.12512314961357562 + 0.12512681541649945 + 0.12513048128874102 + 0.12513414723030311 + 0.12513781324118919 + 0.12514147932140224 + 0.12514514547094555 + 0.12514881168982245 + 0.12515247797803583 + 0.12515614433558911 + 0.12515981076248545 + 0.12516347725872801 + 0.12516714382432004 + 0.12517081045926462 + 0.1251744771635652 + 0.12517814393722457 + 0.12518181078024626 + 0.12518547769263347 + 0.1251891446743891 + 0.12519281172551655 + 0.12519647884601906 + 0.12520014603589985 + 0.12520381329516189 + 0.12520748062380868 + 0.1252111480218431 + 0.12521481548926863 + 0.12521848302608823 + 0.12522215063230535 + 0.12522581830792293 + 0.12522948605294432 + 0.12523315386737263 + 0.12523682175121109 + 0.12524048970446311 + 0.12524415772713157 + 0.12524782581921967 + 0.12525149398073088 + 0.1252551622116683 + 0.12525883051203493 + 0.12526249888183413 + 0.12526616732106918 + 0.12526983582974299 + 0.12527350440785928 + 0.12527717305542058 + 0.12528084177243062 + 0.12528451055889234 + 0.12528817941480905 + 0.12529184834018398 + 0.12529551733502006 + 0.12529918639932078 + 0.12530285553308915 + 0.1253065247363285 + 0.12531019400904211 + 0.12531386335123298 + 0.12531753276290447 + 0.12532120224405968 + 0.12532487179470178 + 0.12532854141483399 + 0.12533221110445972 + 0.12533588086358166 + 0.12533955069220368 + 0.12534322059032846 + 0.12534689055795936 + 0.12535056059509977 + 0.12535423070175261 + 0.12535790087792112 + 0.12536157112360891 + 0.12536524143881847 + 0.12536891182355361 + 0.1253725822778172 + 0.1253762528016126 + 0.12537992339494294 + 0.12538359405781155 + 0.12538726479022133 + 0.12539093559217579 + 0.125394606463678 + 0.1253982774047312 + 0.12540194841533847 + 0.12540561949550325 + 0.12540929064522857 + 0.12541296186451756 + 0.12541663315337365 + 0.12542030451179995 + 0.12542397593979956 + 0.12542764743737572 + 0.12543131900453167 + 0.12543499064127067 + 0.1254386623475959 + 0.12544233412351055 + 0.12544600596901784 + 0.12544967788412095 + 0.12545334986882295 + 0.12545702192312719 + 0.12546069404703697 + 0.1254643662405554 + 0.12546803850368551 + 0.12547171083643069 + 0.12547538323879417 + 0.12547905571077902 + 0.12548272825238863 + 0.12548640086362617 + 0.12549007354449451 + 0.12549374629499727 + 0.12549741911513757 + 0.12550109200491832 + 0.1255047649643431 + 0.12550843799341491 + 0.12551211109213725 + 0.12551578426051282 + 0.12551945749854532 + 0.12552313080623759 + 0.12552680418359297 + 0.12553047763061478 + 0.12553415114730604 + 0.12553782473367012 + 0.12554149838971013 + 0.12554517211542909 + 0.12554884591083063 + 0.12555251977591755 + 0.12555619371069346 + 0.12555986771516128 + 0.12556354178932413 + 0.12556721593318559 + 0.1255708901467486 + 0.12557456443001633 + 0.12557823878299215 + 0.12558191320567916 + 0.12558558769808065 + 0.12558926226019976 + 0.12559293689203976 + 0.1255966115936038 + 0.12560028636489504 + 0.12560396120591671 + 0.12560763611667222 + 0.12561131109716445 + 0.12561498614739705 + 0.12561866126737273 + 0.12562233645709503 + 0.12562601171656698 + 0.12562968704579189 + 0.12563336244477288 + 0.12563703791351341 + 0.12564071345201633 + 0.12564438906028516 + 0.12564806473832291 + 0.12565174048613284 + 0.12565541630371824 + 0.12565909219108209 + 0.12566276814822785 + 0.12566644417515879 + 0.12567012027187774 + 0.12567379643838836 + 0.12567747267469354 + 0.12568114898079652 + 0.12568482535670064 + 0.12568850180240915 + 0.12569217831792509 + 0.12569585490325183 + 0.12569953155839239 + 0.12570320828335005 + 0.12570688507812822 + 0.12571056194272995 + 0.12571423887715838 + 0.1257179158814169 + 0.12572159295550847 + 0.12572527009943654 + 0.12572894731320425 + 0.12573262459681478 + 0.12573630195027141 + 0.12573997937357728 + 0.12574365686673553 + 0.12574733442974947 + 0.12575101206262249 + 0.12575468976535742 + 0.12575836753795774 + 0.12576204538042671 + 0.12576572329276733 + 0.12576940127498298 + 0.12577307932707668 + 0.12577675744905198 + 0.12578043564091165 + 0.12578411390265931 + 0.12578779223429809 + 0.12579147063583088 + 0.12579514910726125 + 0.12579882764859229 + 0.12580250625982714 + 0.12580618494096923 + 0.12580986369202149 + 0.12581354251298751 + 0.12581722140387006 + 0.12582090036467267 + 0.12582457939539846 + 0.12582825849605084 + 0.12583193766663245 + 0.12583561690714712 + 0.12583929621759771 + 0.12584297559798768 + 0.12584665504832002 + 0.1258503345685982 + 0.12585401415882505 + 0.12585769381900413 + 0.12586137354913857 + 0.12586505334923162 + 0.12586873321928635 + 0.12587241315930614 + 0.1258760931692941 + 0.1258797732492534 + 0.12588345339918752 + 0.12588713361909926 + 0.12589081390899209 + 0.12589449426886934 + 0.12589817469873396 + 0.12590185519858949 + 0.12590553576843877 + 0.12590921640828534 + 0.12591289711813217 + 0.12591657789798255 + 0.12592025874783988 + 0.12592393966770718 + 0.1259276206575877 + 0.12593130171748468 + 0.1259349828474014 + 0.12593866404734103 + 0.12594234531730669 + 0.1259460266573017 + 0.12594970806732927 + 0.12595338954739266 + 0.12595707109749496 + 0.12596075271763946 + 0.12596443440782956 + 0.12596811616806816 + 0.1259717979983587 + 0.12597547989870422 + 0.12597916186910812 + 0.12598284390957351 + 0.12598652602010371 + 0.12599020820070178 + 0.1259938904513711 + 0.12599757277211474 + 0.1260012551629362 + 0.12600493762383838 + 0.1260086201548247 + 0.12601230275589814 + 0.12601598542706222 + 0.12601966816832005 + 0.12602335097967476 + 0.12602703386112959 + 0.12603071681268796 + 0.1260343998343528 + 0.12603808292612756 + 0.12604176608801534 + 0.12604544932001935 + 0.12604913262214298 + 0.12605281599438931 + 0.1260564994367615 + 0.12606018294926288 + 0.12606386653189658 + 0.12606755018466606 + 0.12607123390757424 + 0.12607491770062454 + 0.12607860156382003 + 0.1260822854971641 + 0.12608596950065981 + 0.12608965357431048 + 0.12609333771811945 + 0.12609702193208971 + 0.12610070621622449 + 0.12610439057052719 + 0.12610807499500096 + 0.12611175948964903 + 0.12611544405447458 + 0.12611912868948078 + 0.12612281339467105 + 0.12612649817004845 + 0.12613018301561629 + 0.12613386793137765 + 0.126137552917336 + 0.12614123797349427 + 0.12614492309985595 + 0.12614860829642408 + 0.12615229356320204 + 0.12615597890019292 + 0.12615966430739997 + 0.12616334978482649 + 0.12616703533247556 + 0.12617072095035067 + 0.12617440663845475 + 0.12617809239679104 + 0.12618177822536317 + 0.12618546412417392 + 0.1261891500932267 + 0.12619283613252474 + 0.12619652224207104 + 0.1262002084218693 + 0.12620389467192225 + 0.1262075809922332 + 0.1262112673828058 + 0.12621495384364287 + 0.12621864037474773 + 0.12622232697612365 + 0.1262260136477738 + 0.12622970038970147 + 0.12623338720190996 + 0.12623707408440227 + 0.12624076103718171 + 0.12624444806025156 + 0.12624813515361519 + 0.12625182231727544 + 0.12625550955123588 + 0.12625919685549974 + 0.12626288423007004 + 0.12626657167495003 + 0.12627025919014301 + 0.1262739467756524 + 0.12627763443148113 + 0.12628132215763255 + 0.12628500995410971 + 0.1262886978209162 + 0.1262923857580549 + 0.12629607376552943 + 0.12629976184334257 + 0.12630344999149778 + 0.1263071382099985 + 0.12631082649884748 + 0.12631451485804823 + 0.1263182032876041 + 0.12632189178751799 + 0.1263255803577932 + 0.12632926899843322 + 0.1263329577094412 + 0.12633664649082024 + 0.12634033534257361 + 0.12634402426470451 + 0.12634771325721639 + 0.12635140232011219 + 0.12635509145339519 + 0.12635878065706879 + 0.12636246993113606 + 0.12636615927560035 + 0.12636984869046491 + 0.12637353817573263 + 0.12637722773140711 + 0.12638091735749152 + 0.12638460705398907 + 0.12638829682090302 + 0.12639198665823642 + 0.12639567656599277 + 0.12639936654417497 + 0.12640305659278658 + 0.12640674671183064 + 0.12641043690131054 + 0.12641412716122935 + 0.12641781749159042 + 0.12642150789239684 + 0.12642519836365188 + 0.12642888890535889 + 0.1264325795175211 + 0.12643627020014164 + 0.12643996095322377 + 0.12644365177677072 + 0.1264473426707857 + 0.12645103363527202 + 0.12645472467023294 + 0.12645841577567152 + 0.12646210695159135 + 0.12646579819799511 + 0.1264694895148864 + 0.12647318090226847 + 0.12647687236014454 + 0.12648056388851764 + 0.12648425548739115 + 0.12648794715676848 + 0.12649163889665263 + 0.12649533070704672 + 0.12649902258795429 + 0.12650271453937845 + 0.12650640656132228 + 0.12651009865378934 + 0.12651379081678263 + 0.12651748305030536 + 0.12652117535436097 + 0.12652486772895258 + 0.12652856017408334 + 0.12653225268975657 + 0.12653594527597556 + 0.12653963793274342 + 0.12654333066006349 + 0.12654702345793892 + 0.12655071632637313 + 0.12655440926536896 + 0.12655810227493014 + 0.1265617953550596 + 0.12656548850576077 + 0.12656918172703652 + 0.12657287501889058 + 0.12657656838132589 + 0.12658026181434556 + 0.12658395531795313 + 0.12658764889215177 + 0.12659134253694468 + 0.12659503625233495 + 0.12659873003832603 + 0.12660242389492091 + 0.12660611782212325 + 0.12660981181993586 + 0.12661350588836223 + 0.12661720002740542 + 0.12662089423706893 + 0.12662458851735578 + 0.1266282828682693 + 0.12663197728981246 + 0.12663567178198901 + 0.12663936634480177 + 0.12664306097825412 + 0.12664675568234926 + 0.12665045045709056 + 0.12665414530248115 + 0.12665784021852428 + 0.12666153520522322 + 0.12666523026258117 + 0.12666892539060129 + 0.12667262058928708 + 0.12667631585864148 + 0.12668001119866798 + 0.12668370660936976 + 0.12668740209074977 + 0.1266910976428117 + 0.12669479326555844 + 0.12669848895899344 + 0.12670218472311981 + 0.12670588055794091 + 0.1267095764634599 + 0.12671327243968014 + 0.12671696848660455 + 0.12672066460423684 + 0.12672436079257984 + 0.12672805705163695 + 0.12673175338141152 + 0.12673544978190668 + 0.1267391462531256 + 0.12674284279507159 + 0.12674653940774799 + 0.12675023609115801 + 0.12675393284530476 + 0.12675762967019161 + 0.12676132656582167 + 0.12676502353219843 + 0.12676872056932473 + 0.12677241767720421 + 0.12677611485583992 + 0.12677981210523506 + 0.12678350942539324 + 0.12678720681631722 + 0.12679090427801035 + 0.12679460181047625 + 0.12679829941371748 + 0.12680199708773798 + 0.12680569483254064 + 0.12680939264812865 + 0.12681309053450548 + 0.12681678849167427 + 0.12682048651963823 + 0.12682418461840056 + 0.12682788278796459 + 0.1268315810283337 + 0.12683527933951078 + 0.12683897772149938 + 0.12684267617430256 + 0.12684637469792373 + 0.126850073292366 + 0.12685377195763273 + 0.12685747069372699 + 0.12686116950065213 + 0.12686486837841157 + 0.12686856732700838 + 0.12687226634644549 + 0.1268759654367268 + 0.12687966459785502 + 0.12688336382983376 + 0.12688706313266609 + 0.12689076250635531 + 0.12689446195090448 + 0.12689816146631713 + 0.12690186105259624 + 0.12690556070974537 + 0.1269092604377674 + 0.12691296023666604 + 0.12691666010644398 + 0.12692036004710483 + 0.12692406005865173 + 0.12692776014108792 + 0.12693146029441696 + 0.12693516051864154 + 0.12693886081376524 + 0.12694256117979127 + 0.12694626161672287 + 0.12694996212456328 + 0.12695366270331576 + 0.12695736335298358 + 0.12696106407356988 + 0.12696476486507802 + 0.12696846572751119 + 0.1269721666608726 + 0.12697586766516564 + 0.12697956874039365 + 0.12698326988655934 + 0.12698697110366655 + 0.12699067239171835 + 0.12699437375071781 + 0.12699807518066844 + 0.1270017766815732 + 0.12700547825343561 + 0.12700917989625882 + 0.12701288161004609 + 0.12701658339480068 + 0.12702028525052575 + 0.12702398717722474 + 0.12702768917490054 + 0.1270313912435567 + 0.12703509338319655 + 0.12703879559382319 + 0.1270424978754397 + 0.12704620022804963 + 0.12704990265165603 + 0.12705360514626224 + 0.12705730771187174 + 0.12706101034848721 + 0.1270647130561125 + 0.12706841583475043 + 0.12707211868440446 + 0.12707582160507785 + 0.1270795245967738 + 0.12708322765949548 + 0.12708693079324621 + 0.12709063399802925 + 0.12709433727384803 + 0.12709804062070548 + 0.12710174403860511 + 0.12710544752754993 + 0.1271091510875435 + 0.12711285471858869 + 0.12711655842068917 + 0.12712026219384792 + 0.12712396603806825 + 0.12712766995335339 + 0.12713137393970672 + 0.12713507799713139 + 0.12713878212563048 + 0.12714248632520761 + 0.12714619059586585 + 0.12714989493760839 + 0.1271535993504386 + 0.12715730383435966 + 0.12716100838937497 + 0.1271647130154876 + 0.12716841771270063 + 0.12717212248101781 + 0.12717582732044211 + 0.12717953223097686 + 0.12718323721262509 + 0.12718694226539029 + 0.12719064738927571 + 0.12719435258428458 + 0.12719805785042015 + 0.12720176318768556 + 0.12720546859608417 + 0.12720917407561927 + 0.12721287962629402 + 0.12721658524811177 + 0.12722029094107584 + 0.12722399670518916 + 0.12722770254045532 + 0.12723140844687739 + 0.12723511442445887 + 0.12723882047320265 + 0.1272425265931123 + 0.12724623278419092 + 0.12724993904644186 + 0.12725364537986822 + 0.12725735178447359 + 0.12726105826026074 + 0.12726476480723325 + 0.12726847142539433 + 0.1272721781147472 + 0.12727588487529523 + 0.12727959170704134 + 0.12728329860998916 + 0.12728700558414208 + 0.12729071262950273 + 0.12729441974607486 + 0.12729812693386164 + 0.12730183419286625 + 0.12730554152309209 + 0.12730924892454223 + 0.12731295639722001 + 0.12731666394112878 + 0.12732037155627157 + 0.12732407924265191 + 0.12732778700027289 + 0.12733149482913786 + 0.12733520272924995 + 0.12733891070061248 + 0.12734261874322891 + 0.12734632685710218 + 0.12735003504223572 + 0.1273537432986328 + 0.12735745162629661 + 0.12736116002523046 + 0.12736486849543754 + 0.12736857703692117 + 0.12737228564968456 + 0.12737599433373112 + 0.12737970308906391 + 0.12738341191568642 + 0.12738712081360171 + 0.12739082978281308 + 0.1273945388233238 + 0.12739824793513721 + 0.12740195711825644 + 0.12740566637268494 + 0.12740937569842575 + 0.12741308509548219 + 0.12741679456385771 + 0.12742050410355535 + 0.12742421371457854 + 0.12742792339693021 + 0.12743163315061401 + 0.12743534297563311 + 0.12743905287199067 + 0.12744276283969003 + 0.12744647287873434 + 0.12745018298912708 + 0.12745389317087136 + 0.12745760342397033 + 0.12746131374842748 + 0.12746502414424588 + 0.12746873461142913 + 0.12747244514998007 + 0.12747615575990215 + 0.1274798664411988 + 0.12748357719387293 + 0.127487288017928 + 0.12749099891336726 + 0.12749470988019401 + 0.12749842091841157 + 0.12750213202802307 + 0.12750584320903161 + 0.12750955446144097 + 0.1275132657852541 + 0.12751697718047419 + 0.12752068864710453 + 0.12752440018514849 + 0.12752811179460921 + 0.12753182347549014 + 0.12753553522779434 + 0.12753924705152533 + 0.12754295894668621 + 0.12754667091328006 + 0.12755038295131049 + 0.12755409506078055 + 0.1275578072416936 + 0.12756151949405295 + 0.12756523181786178 + 0.12756894421312323 + 0.12757265667984088 + 0.12757636921801765 + 0.12758008182765726 + 0.12758379450876234 + 0.12758750726133686 + 0.12759122008538362 + 0.12759493298090591 + 0.12759864594790715 + 0.12760235898639058 + 0.12760607209635935 + 0.12760978527781694 + 0.12761349853076639 + 0.12761721185521108 + 0.12762092525115437 + 0.1276246387185993 + 0.12762835225754943 + 0.12763206586800779 + 0.12763577954997771 + 0.12763949330346253 + 0.12764320712846533 + 0.12764692102498951 + 0.12765063499303833 + 0.12765434903261519 + 0.12765806314372322 + 0.12766177732636569 + 0.12766549158054585 + 0.1276692059062669 + 0.12767292030353228 + 0.12767663477234525 + 0.127680349312709 + 0.12768406392462672 + 0.12768777860810188 + 0.12769149336313765 + 0.12769520818973734 + 0.12769892308790418 + 0.1277026380576412 + 0.12770635309895212 + 0.12771006821183989 + 0.12771378339630801 + 0.12771749865235951 + 0.12772121397999792 + 0.12772492937922622 + 0.12772864485004798 + 0.12773236039246608 + 0.12773607600648432 + 0.12773979169210556 + 0.12774350744933327 + 0.1277472232781704 + 0.12775093917862071 + 0.12775465515068718 + 0.12775837119437319 + 0.1277620873096818 + 0.12776580349661659 + 0.12776951975518064 + 0.12777323608537719 + 0.12777695248720961 + 0.12778066896068113 + 0.12778438550579507 + 0.12778810212255468 + 0.12779181881096305 + 0.12779553557102388 + 0.12779925240274018 + 0.12780296930611507 + 0.12780668628115194 + 0.12781040332785432 + 0.12781412044622517 + 0.12781783763626789 + 0.12782155489798569 + 0.12782527223138168 + 0.12782898963645981 + 0.1278327071132225 + 0.1278364246616735 + 0.12784014228181609 + 0.12784385997365333 + 0.12784757773718872 + 0.12785129557242522 + 0.12785501347936648 + 0.12785873145801557 + 0.12786244950837569 + 0.12786616763045033 + 0.12786988582424275 + 0.1278736040897559 + 0.12787732242699346 + 0.1278810408359583 + 0.12788475931665413 + 0.12788847786908397 + 0.1278921964932512 + 0.12789591518915913 + 0.12789963395681081 + 0.12790335279620954 + 0.12790707170735888 + 0.1279107906902619 + 0.12791450974492186 + 0.12791822887134213 + 0.12792194806952603 + 0.12792566733947663 + 0.12792938668119735 + 0.12793310609469152 + 0.12793682557996222 + 0.12794054513701278 + 0.12794426476584669 + 0.12794798446646716 + 0.12795170423887739 + 0.12795542408308042 + 0.12795914399908004 + 0.12796286398687898 + 0.12796658404648109 + 0.12797030417788918 + 0.12797402438110675 + 0.12797774465613707 + 0.12798146500298332 + 0.12798518542164875 + 0.12798890591213688 + 0.12799262647445075 + 0.1279963471085937 + 0.12800006781456899 + 0.12800378859238004 + 0.12800750944203004 + 0.12801123036352219 + 0.1280149513568597 + 0.12801867242204615 + 0.12802239355908457 + 0.12802611476797837 + 0.12802983604873086 + 0.12803355740134512 + 0.12803727882582472 + 0.12804100032217255 + 0.12804472189039234 + 0.12804844353048703 + 0.12805216524245996 + 0.1280558870263144 + 0.12805960888205378 + 0.12806333080968149 + 0.12806705280920036 + 0.12807077488061405 + 0.12807449702392565 + 0.12807821923913854 + 0.12808194152625585 + 0.12808566388528111 + 0.1280893863162173 + 0.1280931088190681 + 0.12809683139383657 + 0.12810055404052575 + 0.12810427675913943 + 0.12810799954968044 + 0.1281117224121523 + 0.1281154453465583 + 0.12811916835290152 + 0.12812289143118541 + 0.12812661458141333 + 0.1281303378035884 + 0.12813406109771383 + 0.12813778446379315 + 0.12814150790182963 + 0.12814523141182624 + 0.12814895499378653 + 0.12815267864771379 + 0.1281564023736112 + 0.12816012617148212 + 0.12816385004132969 + 0.12816757398315726 + 0.12817129799696833 + 0.12817502208276588 + 0.12817874624055342 + 0.12818247047033401 + 0.12818619477211105 + 0.12818991914588782 + 0.12819364359166777 + 0.12819736810945384 + 0.12820109269924959 + 0.12820481736105824 + 0.12820854209488297 + 0.12821226690072726 + 0.12821599177859433 + 0.12821971672848739 + 0.12822344175040959 + 0.12822716684436444 + 0.12823089201035529 + 0.12823461724838509 + 0.12823834255845756 + 0.12824206794057572 + 0.12824579339474287 + 0.12824951892096215 + 0.12825324451923717 + 0.12825697018957102 + 0.12826069593196721 + 0.12826442174642871 + 0.12826814763295902 + 0.1282718735915612 + 0.1282755996222387 + 0.12827932572499498 + 0.12828305189983305 + 0.12828677814675618 + 0.12829050446576787 + 0.12829423085687128 + 0.12829795732006977 + 0.12830168385536656 + 0.12830541046276486 + 0.12830913714226813 + 0.12831286389387975 + 0.1283165907176026 + 0.12832031761344023 + 0.12832404458139601 + 0.12832777162147316 + 0.12833149873367486 + 0.12833522591800445 + 0.12833895317446523 + 0.1283426805030605 + 0.12834640790379379 + 0.12835013537666787 + 0.12835386292168641 + 0.1283575905388524 + 0.12836131822816971 + 0.12836504598964102 + 0.12836877382326986 + 0.12837250172905948 + 0.12837622970701321 + 0.12837995775713423 + 0.12838368587942614 + 0.12838741407389193 + 0.12839114234053492 + 0.12839487067935837 + 0.12839859909036583 + 0.12840232757356035 + 0.12840605612894521 + 0.12840978475652393 + 0.12841351345629962 + 0.12841724222827547 + 0.12842097107245498 + 0.12842469998884137 + 0.12842842897743792 + 0.12843215803824787 + 0.12843588717127474 + 0.12843961637652146 + 0.1284433456539916 + 0.12844707500368829 + 0.12845080442561499 + 0.12845453391977488 + 0.1284582634861712 + 0.12846199312480733 + 0.12846572283568644 + 0.12846945261881204 + 0.1284731824741874 + 0.12847691240181561 + 0.12848064240169996 + 0.12848437247384409 + 0.12848810261825086 + 0.12849183283492385 + 0.12849556312386629 + 0.12849929348508149 + 0.12850302391857257 + 0.12850675442434303 + 0.1285104850023959 + 0.12851421565273491 + 0.1285179463753631 + 0.12852167717028365 + 0.12852540803750007 + 0.12852913897701554 + 0.12853286998883323 + 0.12853660107295672 + 0.12854033222938913 + 0.12854406345813377 + 0.1285477947591939 + 0.12855152613257301 + 0.12855525757827405 + 0.12855898909630062 + 0.12856272068665586 + 0.12856645234934325 + 0.12857018408436596 + 0.12857391589172718 + 0.12857764777143027 + 0.12858137972347863 + 0.12858511174787543 + 0.12858884384462418 + 0.1285925760137277 + 0.12859630825518989 + 0.12860004056901364 + 0.12860377295520231 + 0.12860750541375923 + 0.12861123794468785 + 0.12861497054799137 + 0.128618703223673 + 0.128622435971736 + 0.12862616879218372 + 0.12862990168501964 + 0.12863363465024691 + 0.12863736768786876 + 0.12864110079788849 + 0.12864483398030954 + 0.12864856723513521 + 0.12865230056236857 + 0.12865603396201317 + 0.12865976743407212 + 0.12866350097854881 + 0.12866723459544654 + 0.12867096828476857 + 0.12867470204651837 + 0.12867843588069905 + 0.12868216978731395 + 0.12868590376636621 + 0.12868963781785939 + 0.12869337194179675 + 0.12869710613818147 + 0.12870084040701699 + 0.12870457474830632 + 0.12870830916205314 + 0.12871204364826055 + 0.12871577820693189 + 0.12871951283807043 + 0.12872324754167958 + 0.12872698231776233 + 0.12873071716632237 + 0.12873445208736267 + 0.1287381870808868 + 0.12874192214689789 + 0.12874565728539947 + 0.12874939249639442 + 0.12875312777988651 + 0.1287568631358787 + 0.12876059856437433 + 0.12876433406537702 + 0.1287680696388897 + 0.12877180528491569 + 0.12877554100345853 + 0.12877927679452153 + 0.12878301265810749 + 0.12878674859422037 + 0.12879048460286316 + 0.12879422068403901 + 0.12879795683775153 + 0.12880169306400385 + 0.12880542936279935 + 0.12880916573414125 + 0.12881290217803293 + 0.12881663869447765 + 0.12882037528347867 + 0.12882411194503943 + 0.12882784867916305 + 0.12883158548585288 + 0.12883532236511247 + 0.12883905931694487 + 0.12884279634135337 + 0.12884653343834129 + 0.12885027060791213 + 0.12885400785006901 + 0.12885774516481521 + 0.12886148255215404 + 0.128865220012089 + 0.12886895754462321 + 0.12887269514976005 + 0.12887643282750277 + 0.12888017057785467 + 0.12888390840081909 + 0.12888764629639937 + 0.12889138426459859 + 0.12889512230542036 + 0.12889886041886778 + 0.12890259860494438 + 0.12890633686365324 + 0.12891007519499786 + 0.12891381359898135 + 0.12891755207560704 + 0.12892129062487839 + 0.12892502924679852 + 0.12892876794137087 + 0.12893250670859879 + 0.12893624554848526 + 0.128939984461034 + 0.12894372344624816 + 0.12894746250413103 + 0.12895120163468576 + 0.12895494083791589 + 0.12895868011382466 + 0.1289624194624153 + 0.12896615888369131 + 0.12896989837765568 + 0.12897363794431213 + 0.12897737758366348 + 0.12898111729571357 + 0.12898485708046534 + 0.12898859693792195 + 0.1289923368680872 + 0.12899607687096423 + 0.12899981694655613 + 0.12900355709486619 + 0.12900729731589822 + 0.12901103760965485 + 0.12901477797613994 + 0.12901851841535639 + 0.12902225892730776 + 0.12902599951199742 + 0.12902974016942853 + 0.12903348089960437 + 0.12903722170252815 + 0.12904096257820349 + 0.12904470352663355 + 0.12904844454782155 + 0.12905218564177087 + 0.12905592680848499 + 0.12905966804796687 + 0.12906340936022009 + 0.12906715074524783 + 0.12907089220305343 + 0.12907463373364045 + 0.12907837533701166 + 0.12908211701317085 + 0.129085858762121 + 0.1290896005838657 + 0.12909334247840809 + 0.12909708444575163 + 0.12910082648589943 + 0.12910456859885497 + 0.12910831078462132 + 0.12911205304320211 + 0.12911579537460049 + 0.12911953777881977 + 0.12912328025586314 + 0.12912702280573432 + 0.12913076542843621 + 0.12913450812397209 + 0.12913825089234574 + 0.12914199373356006 + 0.12914573664761836 + 0.12914947963452419 + 0.12915322269428076 + 0.12915696582689132 + 0.12916070903235929 + 0.12916445231068788 + 0.12916819566188037 + 0.12917193908594016 + 0.12917568258287063 + 0.12917942615267508 + 0.1291831697953566 + 0.1291869135109186 + 0.1291906572993646 + 0.12919440116069764 + 0.12919814509492122 + 0.12920188910203861 + 0.12920563318205314 + 0.12920937733496818 + 0.12921312156078674 + 0.12921686585951253 + 0.12922061023114853 + 0.12922435467569812 + 0.12922809919316491 + 0.12923184378355199 + 0.12923558844686253 + 0.12923933318310016 + 0.12924307799226797 + 0.12924682287436937 + 0.12925056782940769 + 0.12925431285738612 + 0.12925805795830808 + 0.12926180313217689 + 0.12926554837899593 + 0.12926929369876838 + 0.12927303909149745 + 0.1292767845571868 + 0.12928053009583942 + 0.12928427570745879 + 0.12928802139204834 + 0.12929176714961108 + 0.12929551298015052 + 0.12929925888367 + 0.12930300486017263 + 0.12930675090966207 + 0.12931049703214131 + 0.12931424322761392 + 0.12931798949608297 + 0.12932173583755208 + 0.12932548225202425 + 0.12932922873950306 + 0.12933297529999163 + 0.1293367219334933 + 0.12934046864001164 + 0.12934421541954969 + 0.12934796227211076 + 0.12935170919769831 + 0.12935545619631555 + 0.12935920326796604 + 0.12936295041265278 + 0.1293666976303792 + 0.12937044492114871 + 0.1293741922849643 + 0.12937793972182995 + 0.12938168723174842 + 0.1293854348147232 + 0.12938918247075748 + 0.12939293019985484 + 0.1293966780020184 + 0.12940042587725153 + 0.12940417382555755 + 0.12940792184693981 + 0.12941166994140144 + 0.12941541810894622 + 0.12941916634957706 + 0.12942291466329731 + 0.12942666305011052 + 0.12943041151001963 + 0.12943416004302843 + 0.1294379086491399 + 0.12944165732835747 + 0.12944540608068439 + 0.12944915490612419 + 0.12945290380468003 + 0.12945665277635524 + 0.12946040182115304 + 0.1294641509390769 + 0.12946790013013024 + 0.1294716493943161 + 0.12947539873163799 + 0.12947914814209929 + 0.12948289762570309 + 0.1294866471824529 + 0.12949039681235192 + 0.12949414651540361 + 0.12949789629161121 + 0.12950164614097792 + 0.12950539606350742 + 0.12950914605920266 + 0.12951289612806702 + 0.12951664627010412 + 0.12952039648531696 + 0.12952414677370908 + 0.12952789713528365 + 0.12953164757004404 + 0.12953539807799352 + 0.12953914865913552 + 0.12954289931347335 + 0.12954665004101018 + 0.1295504008417496 + 0.1295541517156947 + 0.12955790266284892 + 0.12956165368321565 + 0.1295654047767979 + 0.12956915594359938 + 0.1295729071836233 + 0.12957665849687275 + 0.12958040988335129 + 0.12958416134306233 + 0.1295879128760089 + 0.12959166448219464 + 0.12959541616162251 + 0.12959916791429615 + 0.12960291974021881 + 0.12960667163939363 + 0.12961042361182445 + 0.12961417565751379 + 0.12961792777646575 + 0.12962167996868321 + 0.12962543223416956 + 0.12962918457292816 + 0.12963293698496248 + 0.12963668947027571 + 0.12964044202887104 + 0.12964419466075205 + 0.12964794736592206 + 0.12965170014438418 + 0.1296554529961417 + 0.12965920592119834 + 0.12966295891955729 + 0.12966671199122146 + 0.12967046513619468 + 0.12967421835448015 + 0.12967797164608103 + 0.12968172501100075 + 0.1296854784492425 + 0.12968923196080995 + 0.12969298554570621 + 0.12969673920393465 + 0.12970049293549851 + 0.12970424674040115 + 0.12970800061864596 + 0.1297117545702364 + 0.12971550859517542 + 0.12971926269346684 + 0.12972301686511331 + 0.12972677111011893 + 0.12973052542848651 + 0.12973427982021948 + 0.12973803428532135 + 0.12974178882379533 + 0.12974554343564448 + 0.12974929812087271 + 0.12975305287948299 + 0.12975680771147854 + 0.12976056261686283 + 0.12976431759563936 + 0.12976807264781123 + 0.12977182777338184 + 0.12977558297235453 + 0.1297793382447327 + 0.12978309359051929 + 0.1297868490097184 + 0.12979060450233249 + 0.12979436006836551 + 0.12979811570782063 + 0.12980187142070104 + 0.12980562720701019 + 0.12980938306675138 + 0.12981313899992797 + 0.1298168950065432 + 0.12982065108660065 + 0.1298244072401033 + 0.12982816346705475 + 0.12983191976745828 + 0.12983567614131705 + 0.12983943258863465 + 0.12984318910941417 + 0.12984694570365912 + 0.12985070237137292 + 0.12985445911255836 + 0.12985821592721961 + 0.12986197281535936 + 0.12986572977698108 + 0.12986948681208818 + 0.12987324392068411 + 0.12987700110277181 + 0.12988075835835527 + 0.12988451568743711 + 0.1298882730900211 + 0.12989203056611059 + 0.12989578811570857 + 0.12989954573881868 + 0.12990330343544412 + 0.12990706120558826 + 0.12991081904925433 + 0.12991457696644601 + 0.1299183349571662 + 0.12992209302141863 + 0.12992585115920613 + 0.12992960937053269 + 0.12993336765540109 + 0.12993712601381482 + 0.12994088444577739 + 0.12994464295129196 + 0.12994840153036197 + 0.12995216018299066 + 0.12995591890918146 + 0.12995967770893754 + 0.12996343658226234 + 0.12996719552915939 + 0.12997095454963162 + 0.12997471364368274 + 0.12997847281131591 + 0.12998223205253434 + 0.12998599136734168 + 0.12998975075574087 + 0.12999351021773581 + 0.12999726975332937 + 0.13000102936252497 + 0.13000478904532595 + 0.13000854880173582 + 0.13001230863175778 + 0.13001606853539513 + 0.13001982851265134 + 0.13002358856352952 + 0.13002734868803315 + 0.13003110888616573 + 0.13003486915793036 + 0.13003862950333053 + 0.13004238992236927 + 0.13004615041505024 + 0.13004991098137683 + 0.13005367162135223 + 0.13005743233497968 + 0.13006119312226264 + 0.13006495398320447 + 0.13006871491780861 + 0.1300724759260779 + 0.13007623700801632 + 0.13007999816362703 + 0.13008375939291306 + 0.13008752069587798 + 0.1300912820725251 + 0.13009504352285781 + 0.13009880504687937 + 0.1301025666445931 + 0.13010632831600255 + 0.13011009006111088 + 0.13011385187992133 + 0.13011761377243744 + 0.13012137573866264 + 0.13012513777859985 + 0.13012889989225279 + 0.13013266207962473 + 0.13013642434071893 + 0.13014018667553862 + 0.13014394908408747 + 0.13014771156636848 + 0.1301514741223852 + 0.13015523675214108 + 0.13015899945563911 + 0.13016276223288284 + 0.13016652508387569 + 0.1301702880086209 + 0.13017405100712173 + 0.13017781407938164 + 0.13018157722540386 + 0.13018534044519187 + 0.13018910373874898 + 0.13019286710607847 + 0.13019663054718364 + 0.13020039406206799 + 0.13020415765073476 + 0.13020792131318756 + 0.13021168504942918 + 0.13021544885946337 + 0.13021921274329326 + 0.13022297670092245 + 0.13022674073235416 + 0.13023050483759172 + 0.13023426901663832 + 0.13023803326949751 + 0.13024179759617266 + 0.13024556199666698 + 0.13024932647098383 + 0.13025309101912669 + 0.13025685564109871 + 0.13026062033690342 + 0.13026438510654401 + 0.13026814995002378 + 0.13027191486734632 + 0.13027567985851476 + 0.13027944492353269 + 0.13028321006240301 + 0.1302869752751295 + 0.13029074056171541 + 0.13029450592216385 + 0.1302982713564784 + 0.13030203686466255 + 0.13030580244671905 + 0.13030956810265176 + 0.1303133338324641 + 0.13031709963615909 + 0.13032086551374022 + 0.13032463146521089 + 0.13032839749057426 + 0.13033216358983366 + 0.13033592976299269 + 0.13033969601005474 + 0.13034346233102284 + 0.13034722872590049 + 0.13035099519469107 + 0.13035476173739777 + 0.13035852835402417 + 0.13036229504457358 + 0.13036606180904911 + 0.13036982864745436 + 0.13037359555979258 + 0.13037736254606716 + 0.13038112960628132 + 0.13038489674043865 + 0.1303886639485422 + 0.13039243123059552 + 0.13039619858660187 + 0.13039996601656462 + 0.1304037335204872 + 0.13040750109837279 + 0.13041126875022491 + 0.13041503647604694 + 0.13041880427584213 + 0.13042257214961378 + 0.13042634009736512 + 0.13043010811909983 + 0.13043387621482097 + 0.13043764438453218 + 0.13044141262823655 + 0.13044518094593746 + 0.13044894933763851 + 0.13045271780334272 + 0.13045648634305354 + 0.13046025495677449 + 0.13046402364450879 + 0.13046779240625964 + 0.13047156124203069 + 0.13047533015182514 + 0.13047909913564623 + 0.13048286819349747 + 0.13048663732538221 + 0.13049040653130381 + 0.13049417581126543 + 0.13049794516527063 + 0.13050171459332283 + 0.13050548409542495 + 0.13050925367158081 + 0.13051302332179365 + 0.13051679304606661 + 0.1305205628444033 + 0.13052433271680686 + 0.13052810266328088 + 0.13053187268382846 + 0.13053564277845306 + 0.13053941294715801 + 0.13054318318994687 + 0.13054695350682274 + 0.13055072389778899 + 0.13055449436284911 + 0.13055826490200625 + 0.13056203551526402 + 0.13056580620262562 + 0.13056957696409432 + 0.13057334779967353 + 0.13057711870936678 + 0.13058088969317724 + 0.13058466075110839 + 0.1305884318831636 + 0.13059220308934588 + 0.130595974369659 + 0.13059974572410621 + 0.13060351715269064 + 0.13060728865541588 + 0.13061106023228536 + 0.130614831883302 + 0.13061860360846964 + 0.13062237540779134 + 0.13062614728127073 + 0.13062991922891082 + 0.13063369125071522 + 0.13063746334668727 + 0.13064123551683007 + 0.13064500776114724 + 0.13064878007964206 + 0.13065255247231802 + 0.13065632493917814 + 0.13066009748022606 + 0.13066387009546504 + 0.13066764278489831 + 0.13067141554852968 + 0.13067518838636202 + 0.13067896129839865 + 0.13068273428464347 + 0.13068650734509926 + 0.13069028047976977 + 0.13069405368865819 + 0.13069782697176777 + 0.13070160032910202 + 0.13070537376066435 + 0.13070914726645788 + 0.13071292084648634 + 0.13071669450075277 + 0.13072046822926056 + 0.13072424203201302 + 0.13072801590901387 + 0.13073178986026607 + 0.13073556388577315 + 0.13073933798553858 + 0.13074311215956544 + 0.13074688640785714 + 0.1307506607304173 + 0.13075443512724902 + 0.13075820959835577 + 0.13076198414374085 + 0.13076575876340774 + 0.13076953345735959 + 0.13077330822560004 + 0.13077708306813215 + 0.13078085798495936 + 0.13078463297608534 + 0.13078840804151295 + 0.13079218318124589 + 0.13079595839528743 + 0.13079973368364095 + 0.1308035090463098 + 0.13080728448329731 + 0.13081105999460671 + 0.13081483558024173 + 0.13081861124020533 + 0.13082238697450121 + 0.13082616278313253 + 0.13082993866610271 + 0.13083371462341498 + 0.130837490655073 + 0.13084126676107977 + 0.13084504294143876 + 0.13084881919615346 + 0.13085259552522732 + 0.13085637192866353 + 0.1308601484064652 + 0.13086392495863627 + 0.13086770158517966 + 0.13087147828609896 + 0.13087525506139738 + 0.1308790319110783 + 0.13088280883514514 + 0.13088658583360122 + 0.13089036290644993 + 0.13089414005369476 + 0.13089791727533881 + 0.13090169457138548 + 0.13090547194183844 + 0.13090924938670082 + 0.13091302690597592 + 0.13091680449966711 + 0.13092058216777799 + 0.13092435991031176 + 0.13092813772727163 + 0.13093191561866122 + 0.13093569358448387 + 0.13093947162474281 + 0.13094324973944155 + 0.13094702792858329 + 0.13095080619217131 + 0.13095458453020931 + 0.13095836294270041 + 0.13096214142964813 + 0.13096591999105567 + 0.13096969862692653 + 0.13097347733726403 + 0.13097725612207153 + 0.13098103498135241 + 0.13098481391510985 + 0.13098859292334758 + 0.1309923720060687 + 0.1309961511632767 + 0.13099993039497479 + 0.13100370970116643 + 0.13100748908185503 + 0.13101126853704392 + 0.13101504806673633 + 0.13101882767093595 + 0.13102260734964594 + 0.13102638710286951 + 0.13103016693061034 + 0.13103394683287162 + 0.13103772680965675 + 0.13104150686096908 + 0.13104528698681214 + 0.13104906718718892 + 0.13105284746210313 + 0.131056627811558 + 0.13106040823555692 + 0.13106418873410328 + 0.13106796930720035 + 0.1310717499548518 + 0.13107553067706046 + 0.1310793114738302 + 0.13108309234516424 + 0.13108687329106583 + 0.13109065431153824 + 0.13109443540658539 + 0.13109821657620996 + 0.13110199782041573 + 0.13110577913920604 + 0.13110956053258413 + 0.13111334200055336 + 0.13111712354311733 + 0.13112090516027916 + 0.13112468685204234 + 0.13112846861841004 + 0.13113225045938598 + 0.13113603237497334 + 0.13113981436517549 + 0.13114359642999579 + 0.13114737856943745 + 0.13115116078350411 + 0.13115494307219916 + 0.13115872543552567 + 0.13116250787348741 + 0.13116629038608735 + 0.13117007297332908 + 0.13117385563521605 + 0.13117763837175139 + 0.13118142118293857 + 0.13118520406878112 + 0.13118898702928225 + 0.13119277006444535 + 0.13119655317427378 + 0.13120033635877087 + 0.13120411961794015 + 0.13120790295178469 + 0.13121168636030825 + 0.1312154698435142 + 0.13121925340140553 + 0.13122303703398563 + 0.13122682074125844 + 0.13123060452322646 + 0.1312343883798939 + 0.13123817231126389 + 0.13124195631733934 + 0.13124574039812437 + 0.13124952455362174 + 0.13125330878383493 + 0.13125709308876762 + 0.13126087746842294 + 0.13126466192280423 + 0.13126844645191516 + 0.13127223105575853 + 0.13127601573433836 + 0.13127980048765764 + 0.13128358531571985 + 0.13128737021852843 + 0.13129115519608653 + 0.13129494024839775 + 0.13129872537546555 + 0.13130251057729289 + 0.13130629585388345 + 0.13131008120524065 + 0.13131386663136776 + 0.1313176521322679 + 0.13132143770794513 + 0.13132522335840213 + 0.13132900908364253 + 0.13133279488366989 + 0.13133658075848723 + 0.13134036670809832 + 0.13134415273250605 + 0.13134793883171431 + 0.13135172500572612 + 0.13135551125454489 + 0.13135929757817424 + 0.1313630839766175 + 0.13136687044987774 + 0.13137065699795855 + 0.13137444362086337 + 0.13137823031859533 + 0.13138201709115813 + 0.13138580393855484 + 0.13138959086078902 + 0.13139337785786412 + 0.13139716492978318 + 0.13140095207655 + 0.13140473929816776 + 0.13140852659463972 + 0.1314123139659695 + 0.13141610141216031 + 0.13141988893321557 + 0.13142367652913867 + 0.13142746419993284 + 0.13143125194560173 + 0.13143503976614854 + 0.13143882766157672 + 0.13144261563188969 + 0.13144640367709057 + 0.13145019179718304 + 0.13145397999217032 + 0.13145776826205599 + 0.13146155660684303 + 0.13146534502653529 + 0.13146913352113576 + 0.13147292209064809 + 0.1314767107350753 + 0.13148049945442136 + 0.1314842882486891 + 0.13148807711788216 + 0.13149186606200394 + 0.13149565508105768 + 0.13149944417504669 + 0.13150323334397462 + 0.13150702258784483 + 0.13151081190666042 + 0.13151460130042503 + 0.13151839076914193 + 0.13152218031281446 + 0.13152596993144611 + 0.13152975962504004 + 0.13153354939360015 + 0.13153733923712929 + 0.1315411291556311 + 0.13154491914910874 + 0.13154870921756587 + 0.13155249936100549 + 0.13155628957943155 + 0.1315600798728469 + 0.13156387024125513 + 0.13156766068465989 + 0.13157145120306413 + 0.13157524179647132 + 0.13157903246488492 + 0.1315828232083085 + 0.13158661402674507 + 0.13159040492019825 + 0.13159419588867147 + 0.13159798693216787 + 0.13160177805069098 + 0.13160556924424435 + 0.13160936051283101 + 0.13161315185645467 + 0.13161694327511855 + 0.13162073476882591 + 0.13162452633758051 + 0.13162831798138536 + 0.131632109700244 + 0.13163590149415971 + 0.13163969336313616 + 0.13164348530717643 + 0.13164727732628395 + 0.13165106942046226 + 0.13165486158971462 + 0.1316586538340444 + 0.13166244615345518 + 0.13166623854795009 + 0.13167003101753266 + 0.13167382356220614 + 0.13167761618197418 + 0.13168140887683977 + 0.13168520164680667 + 0.13168899449187815 + 0.13169278741205739 + 0.13169658040734819 + 0.13170037347775354 + 0.13170416662327697 + 0.13170795984392178 + 0.13171175313969172 + 0.13171554651058973 + 0.13171933995661936 + 0.13172313347778397 + 0.13172692707408717 + 0.13173072074553205 + 0.13173451449212215 + 0.13173830831386085 + 0.13174210221075133 + 0.13174589618279739 + 0.13174969023000191 + 0.13175348435236878 + 0.13175727854990102 + 0.13176107282260224 + 0.13176486717047556 + 0.13176866159352482 + 0.13177245609175292 + 0.13177625066516352 + 0.13178004531375984 + 0.13178384003754554 + 0.13178763483652381 + 0.13179142971069802 + 0.13179522466007165 + 0.13179901968464808 + 0.13180281478443065 + 0.13180660995942275 + 0.13181040520962778 + 0.13181420053504916 + 0.13181799593569027 + 0.13182179141155442 + 0.13182558696264518 + 0.1318293825889657 + 0.13183317829051946 + 0.13183697406731013 + 0.13184076991934068 + 0.13184456584661464 + 0.13184836184913551 + 0.13185215792690655 + 0.13185595407993131 + 0.13185975030821301 + 0.13186354661175506 + 0.13186734299056097 + 0.13187113944463386 + 0.13187493597397751 + 0.13187873257859509 + 0.13188252925849001 + 0.13188632601366546 + 0.13189012284412543 + 0.13189391974987263 + 0.13189771673091086 + 0.13190151378724335 + 0.13190531091887356 + 0.13190910812580478 + 0.13191290540804065 + 0.13191670276558434 + 0.13192050019843923 + 0.1319242977066088 + 0.1319280952900965 + 0.13193189294890545 + 0.13193569068303934 + 0.13193948849250148 + 0.13194328637729516 + 0.13194708433742391 + 0.13195088237289093 + 0.13195468048370002 + 0.13195847866985416 + 0.13196227693135687 + 0.1319660752682115 + 0.13196987368042168 + 0.13197367216799047 + 0.1319774707309215 + 0.13198126936921806 + 0.13198506808288341 + 0.13198886687192121 + 0.13199266573633478 + 0.13199646467612744 + 0.13200026369130272 + 0.13200406278186383 + 0.13200786194781422 + 0.13201166118915741 + 0.13201546050589669 + 0.13201925989803542 + 0.13202305936557701 + 0.13202685890852492 + 0.13203065852688245 + 0.13203445822065302 + 0.13203825798984023 + 0.13204205783444734 + 0.13204585775447752 + 0.13204965774993449 + 0.13205345782082148 + 0.13205725796714188 + 0.13206105818889929 + 0.13206485848609673 + 0.13206865885873792 + 0.13207245930682615 + 0.1320762598303647 + 0.13208006042935722 + 0.1320838611038069 + 0.13208766185371712 + 0.1320914626790915 + 0.13209526357993337 + 0.13209906455624579 + 0.13210286560803269 + 0.13210666673529697 + 0.1321104679380424 + 0.13211426921627226 + 0.13211807056998986 + 0.13212187199919864 + 0.13212567350390186 + 0.13212947508410336 + 0.13213327673980602 + 0.13213707847101375 + 0.13214088027772949 + 0.13214468215995684 + 0.13214848411769906 + 0.13215228615095986 + 0.1321560882597424 + 0.13215989044405002 + 0.13216369270388642 + 0.13216749503925457 + 0.13217129745015824 + 0.13217509993660065 + 0.13217890249858527 + 0.13218270513611549 + 0.13218650784919456 + 0.1321903106378261 + 0.13219411350201338 + 0.13219791644175996 + 0.13220171945706902 + 0.13220552254794404 + 0.13220932571438854 + 0.13221312895640575 + 0.13221693227399905 + 0.13222073566717205 + 0.13222453913592805 + 0.13222834268027031 + 0.13223214630020247 + 0.13223594999572777 + 0.13223975376684979 + 0.13224355761357159 + 0.13224736153589681 + 0.13225116553382887 + 0.13225496960737118 + 0.13225877375652706 + 0.13226257798129998 + 0.13226638228169316 + 0.1322701866577102 + 0.13227399110935437 + 0.1322777956366292 + 0.132281600239538 + 0.13228540491808424 + 0.13228920967227142 + 0.13229301450210268 + 0.1322968194075817 + 0.13230062438871151 + 0.13230442944549595 + 0.13230823457793811 + 0.13231203978604164 + 0.13231584506980951 + 0.13231965042924573 + 0.13232345586435335 + 0.13232726137513565 + 0.13233106696159611 + 0.13233487262373847 + 0.13233867836156568 + 0.13234248417508165 + 0.13234629006428927 + 0.1323500960291922 + 0.13235390206979364 + 0.13235770818609749 + 0.13236151437810667 + 0.13236532064582462 + 0.13236912698925501 + 0.13237293340840112 + 0.13237673990326623 + 0.13238054647385381 + 0.13238435312016736 + 0.13238815984221031 + 0.13239196663998576 + 0.13239577351349752 + 0.13239958046274891 + 0.13240338748774302 + 0.1324071945884836 + 0.13241100176497397 + 0.13241480901721742 + 0.1324186163452174 + 0.1324224237489775 + 0.13242623122850092 + 0.13243003878379114 + 0.13243384641485142 + 0.13243765412168537 + 0.1324414619042964 + 0.13244526976268786 + 0.13244907769686304 + 0.13245288570682551 + 0.13245669379257846 + 0.13246050195412559 + 0.13246431019147015 + 0.13246811850461568 + 0.13247192689356532 + 0.13247573535832269 + 0.13247954389889116 + 0.13248335251527418 + 0.13248716120747492 + 0.13249096997549709 + 0.13249477881934399 + 0.13249858773901896 + 0.13250239673452549 + 0.13250620580586703 + 0.13251001495304682 + 0.1325138241760683 + 0.13251763347493503 + 0.13252144284965042 + 0.13252525230021783 + 0.13252906182664059 + 0.13253287142892203 + 0.13253668110706562 + 0.13254049086107511 + 0.13254430069095349 + 0.13254811059670435 + 0.13255192057833107 + 0.13255573063583709 + 0.13255954076922563 + 0.13256335097850047 + 0.13256716126366463 + 0.13257097162472176 + 0.13257478206167531 + 0.13257859257452853 + 0.13258240316328479 + 0.13258621382794775 + 0.1325900245685207 + 0.13259383538500683 + 0.1325976462774098 + 0.13260145724573305 + 0.13260526828997993 + 0.13260907941015376 + 0.13261289060625805 + 0.13261670187829619 + 0.1326205132262715 + 0.13262432465018764 + 0.13262813615004779 + 0.13263194772585549 + 0.1326357593776139 + 0.13263957110532679 + 0.13264338290899746 + 0.13264719478862921 + 0.13265100674422545 + 0.13265481877578986 + 0.13265863088332558 + 0.13266244306683594 + 0.13266625532632464 + 0.13267006766179501 + 0.13267388007325026 + 0.13267769256069409 + 0.13268150512412966 + 0.13268531776356066 + 0.1326891304789902 + 0.13269294327042211 + 0.13269675613785947 + 0.13270056908130565 + 0.13270438210076413 + 0.13270819519623842 + 0.13271200836773195 + 0.13271582161524789 + 0.13271963493879013 + 0.13272344833836167 + 0.13272726181396596 + 0.13273107536560672 + 0.13273488899328714 + 0.13273870269701035 + 0.13274251647678029 + 0.13274633033260017 + 0.13275014426447332 + 0.13275395827240327 + 0.1327577723563933 + 0.13276158651644682 + 0.13276540075256768 + 0.13276921506475847 + 0.13277302945302349 + 0.13277684391736577 + 0.13278065845778847 + 0.13278447307429533 + 0.13278828776688975 + 0.13279210253557513 + 0.13279591738035473 + 0.13279973230123224 + 0.13280354729821076 + 0.13280736237129387 + 0.13281117752048507 + 0.13281499274578765 + 0.132818808047205 + 0.13282262342474063 + 0.13282643887839801 + 0.1328302544081803 + 0.13283407001409148 + 0.13283788569613422 + 0.13284170145431246 + 0.13284551728862937 + 0.13284933319908862 + 0.13285314918569338 + 0.13285696524844726 + 0.13286078138735347 + 0.13286459760241556 + 0.13286841389363691 + 0.13287223026102102 + 0.13287604670457123 + 0.13287986322429102 + 0.13288367982018354 + 0.13288749649225259 + 0.13289131324050146 + 0.13289513006493356 + 0.13289894696555221 + 0.132902763942361 + 0.13290658099536332 + 0.13291039812456243 + 0.13291421532996184 + 0.13291803261156507 + 0.13292184996937537 + 0.13292566740339648 + 0.13292948491363132 + 0.13293330250008376 + 0.13293712016275686 + 0.13294093790165434 + 0.13294475571677949 + 0.13294857360813561 + 0.13295239157572664 + 0.13295620961955526 + 0.13296002773962534 + 0.13296384593594021 + 0.13296766420850345 + 0.13297148255731808 + 0.132975300982388 + 0.13297911948371632 + 0.13298293806130651 + 0.13298675671516202 + 0.13299057544528628 + 0.13299439425168269 + 0.13299821313435484 + 0.13300203209330586 + 0.13300585112853941 + 0.1330096702400588 + 0.13301348942786753 + 0.13301730869196887 + 0.13302112803236635 + 0.13302494744906346 + 0.13302876694206348 + 0.13303258651136998 + 0.13303640615698625 + 0.13304022587891581 + 0.13304404567716202 + 0.1330478655517284 + 0.13305168550261834 + 0.13305550552983508 + 0.13305932563338244 + 0.13306314581326339 + 0.13306696606948154 + 0.1330707864020404 + 0.13307460681094346 + 0.13307842729619379 + 0.13308224785779535 + 0.13308606849575105 + 0.13308988921006462 + 0.13309371000073922 + 0.13309753086777865 + 0.13310135181118612 + 0.13310517283096499 + 0.13310899392711872 + 0.13311281509965078 + 0.1331166363485648 + 0.1331204576738638 + 0.13312427907555155 + 0.13312810055363139 + 0.13313192210810643 + 0.13313574373898063 + 0.13313956544625713 + 0.13314338722993921 + 0.13314720909003053 + 0.13315103102653447 + 0.13315485303945454 + 0.13315867512879395 + 0.13316249729455626 + 0.13316631953674476 + 0.13317014185536319 + 0.13317396425041472 + 0.1331777867219027 + 0.13318160926983111 + 0.13318543189420257 + 0.13318925459502098 + 0.13319307737228986 + 0.13319690022601233 + 0.13320072315619205 + 0.13320454616283223 + 0.13320836924593663 + 0.13321219240550841 + 0.13321601564155097 + 0.133219838954068 + 0.13322366234306279 + 0.13322748580853858 + 0.13323130935049898 + 0.13323513296894748 + 0.13323895666388741 + 0.13324278043532239 + 0.13324660428325541 + 0.13325042820769029 + 0.13325425220863038 + 0.13325807628607905 + 0.13326190044003983 + 0.13326572467051609 + 0.1332695489775112 + 0.1332733733610286 + 0.13327719782107175 + 0.13328102235764416 + 0.13328484697074927 + 0.1332886716603903 + 0.13329249642657084 + 0.13329632126929439 + 0.13330014618856423 + 0.13330397118438381 + 0.13330779625675659 + 0.13331162140568603 + 0.13331544663117548 + 0.13331927193322871 + 0.1333230973118486 + 0.13332692276703911 + 0.13333074829880312 + 0.13333457390714459 + 0.13333839959206659 + 0.1333422253535729 + 0.13334605119166651 + 0.13334987710635129 + 0.13335370309763037 + 0.13335752916550728 + 0.13336135530998561 + 0.13336518153106852 + 0.13336900782875946 + 0.13337283420306209 + 0.13337666065397968 + 0.13338048718151577 + 0.13338431378567375 + 0.13338814046645689 + 0.13339196722386887 + 0.13339579405791299 + 0.13339962096859281 + 0.1334034479559115 + 0.13340727501987285 + 0.13341110216047988 + 0.13341492937773644 + 0.13341875667164577 + 0.13342258404221133 + 0.13342641148943643 + 0.13343023901332474 + 0.13343406661387947 + 0.1334378942911042 + 0.13344172204500224 + 0.13344554987557727 + 0.13344937778283239 + 0.13345320576677142 + 0.13345703382739746 + 0.13346086196471413 + 0.13346469017872459 + 0.1334685184694327 + 0.13347234683684184 + 0.13347617528095493 + 0.13348000380177608 + 0.13348383239930819 + 0.13348766107355506 + 0.13349148982452003 + 0.13349531865220635 + 0.1334991475566176 + 0.13350297653775745 + 0.133506805595629 + 0.13351063473023575 + 0.13351446394158115 + 0.13351829322966866 + 0.13352212259450191 + 0.13352595203608417 + 0.13352978155441877 + 0.13353361114950929 + 0.13353744082135893 + 0.13354127056997162 + 0.13354510039535028 + 0.13354893029749865 + 0.1335527602764201 + 0.13355659033211817 + 0.13356042046459604 + 0.1335642506738573 + 0.13356808095990552 + 0.13357191132274376 + 0.13357574176237588 + 0.13357957227880518 + 0.13358340287203493 + 0.13358723354206894 + 0.13359106428891016 + 0.1335948951125624 + 0.13359872601302902 + 0.13360255699031323 + 0.13360638804441879 + 0.13361021917534902 + 0.13361405038310747 + 0.13361788166769734 + 0.13362171302912215 + 0.13362554446738542 + 0.13362937598249069 + 0.13363320757444114 + 0.13363703924324036 + 0.13364087098889174 + 0.13364470281139887 + 0.13364853471076488 + 0.13365236668699357 + 0.13365619874008816 + 0.13366003087005218 + 0.13366386307688902 + 0.13366769536060213 + 0.13367152772119498 + 0.13367536015867101 + 0.13367919267303355 + 0.13368302526428616 + 0.13368685793243243 + 0.13369069067747544 + 0.13369452349941885 + 0.13369835639826627 + 0.13370218937402087 + 0.13370602242668611 + 0.13370985555626555 + 0.13371368876276257 + 0.13371752204618065 + 0.13372135540652325 + 0.13372518884379364 + 0.13372902235799547 + 0.1337328559491322 + 0.13373668961720692 + 0.13374052336222358 + 0.1337443571841854 + 0.13374819108309569 + 0.13375202505895803 + 0.13375585911177593 + 0.13375969324155274 + 0.1337635274482919 + 0.13376736173199688 + 0.1337711960926711 + 0.13377503053031797 + 0.13377886504494102 + 0.13378269963654366 + 0.13378653430512938 + 0.13379036905070171 + 0.13379420387326371 + 0.13379803877281912 + 0.13380187374937164 + 0.13380570880292419 + 0.13380954393348041 + 0.13381337914104396 + 0.13381721442561789 + 0.13382104978720596 + 0.13382488522581165 + 0.13382872074143823 + 0.13383255633408914 + 0.13383639200376807 + 0.13384022775047788 + 0.13384406357422271 + 0.13384789947500583 + 0.13385173545283033 + 0.1338555715077 + 0.13385940763961823 + 0.1338632438485885 + 0.13386708013461401 + 0.13387091649769853 + 0.13387475293784512 + 0.13387858945505779 + 0.1338824260493395 + 0.13388626272069373 + 0.13389009946912434 + 0.13389393629463436 + 0.13389777319722745 + 0.13390161017690697 + 0.13390544723367626 + 0.13390928436753902 + 0.13391312157849861 + 0.13391695886655838 + 0.13392079623172187 + 0.13392463367399257 + 0.13392847119337364 + 0.13393230878986903 + 0.13393614646348179 + 0.13393998421421546 + 0.13394382204207347 + 0.13394765994705943 + 0.13395149792917665 + 0.13395533598842868 + 0.13395917412481881 + 0.13396301233835062 + 0.13396685062902758 + 0.13397068899685302 + 0.13397452744183044 + 0.13397836596396326 + 0.13398220456325508 + 0.13398604323970911 + 0.13398988199332904 + 0.13399372082411831 + 0.13399755973208011 + 0.13400139871721817 + 0.13400523777953582 + 0.13400907691903663 + 0.13401291613572372 + 0.13401675542960079 + 0.13402059480067136 + 0.13402443424893887 + 0.1340282737744066 + 0.13403211337707815 + 0.13403595305695695 + 0.13403979281404635 + 0.13404363264834995 + 0.13404747255987096 + 0.13405131254861319 + 0.1340551526145799 + 0.1340589927577745 + 0.13406283297820054 + 0.13406667327586136 + 0.13407051365076042 + 0.13407435410290133 + 0.13407819463228729 + 0.13408203523892209 + 0.13408587592280899 + 0.13408971668395139 + 0.13409355752235286 + 0.1340973984380168 + 0.13410123943094668 + 0.13410508050114583 + 0.13410892164861793 + 0.13411276287336624 + 0.13411660417539431 + 0.13412044555470568 + 0.13412428701130363 + 0.13412812854519182 + 0.13413197015637338 + 0.13413581184485221 + 0.13413965361063129 + 0.1341434954537144 + 0.13414733737410481 + 0.13415117937180623 + 0.13415502144682201 + 0.13415886359915533 + 0.13416270582880985 + 0.1341665481357891 + 0.13417039052009663 + 0.13417423298173559 + 0.13417807552070962 + 0.13418191813702218 + 0.13418576083067657 + 0.13418960360167659 + 0.13419344645002532 + 0.13419728937572639 + 0.13420113237878317 + 0.13420497545919932 + 0.13420881861697803 + 0.13421266185212308 + 0.13421650516463765 + 0.13422034855452528 + 0.13422419202178951 + 0.13422803556643356 + 0.13423187918846111 + 0.13423572288787566 + 0.13423956666468043 + 0.13424341051887911 + 0.13424725445047508 + 0.13425109845947175 + 0.1342549425458725 + 0.13425878670968119 + 0.1342626309509008 + 0.13426647526953489 + 0.13427031966558714 + 0.1342741641390609 + 0.13427800868995951 + 0.13428185331828657 + 0.13428569802404555 + 0.13428954280723984 + 0.13429338766787283 + 0.13429723260594822 + 0.1343010776214692 + 0.13430492271443936 + 0.13430876788486215 + 0.13431261313274095 + 0.1343164584580793 + 0.13432030386088087 + 0.13432414934114864 + 0.13432799489888655 + 0.13433184053409777 + 0.13433568624678585 + 0.13433953203695428 + 0.13434337790460635 + 0.13434722384974576 + 0.13435106987237583 + 0.13435491597250007 + 0.1343587621501218 + 0.13436260840524486 + 0.13436645473787237 + 0.1343703011480078 + 0.13437414763565478 + 0.13437799420081661 + 0.13438184084349697 + 0.13438568756369912 + 0.13438953436142648 + 0.1343933812366829 + 0.13439722818947128 + 0.13440107521979541 + 0.13440492232765877 + 0.13440876951306471 + 0.13441261677601676 + 0.13441646411651834 + 0.13442031153457309 + 0.1344241590301842 + 0.13442800660335505 + 0.13443185425408966 + 0.13443570198239099 + 0.13443954978826275 + 0.13444339767170815 + 0.13444724563273094 + 0.13445109367133437 + 0.13445494178752215 + 0.13445878998129759 + 0.13446263825266397 + 0.134466486601625 + 0.13447033502818412 + 0.13447418353234478 + 0.13447803211411027 + 0.13448188077348441 + 0.13448572951047039 + 0.13448957832507188 + 0.13449342721729202 + 0.13449727618713447 + 0.13450112523460278 + 0.13450497435970027 + 0.13450882356243055 + 0.134512672842797 + 0.13451652220080301 + 0.13452037163645225 + 0.13452422114974796 + 0.13452807074069378 + 0.13453192040929296 + 0.13453577015554921 + 0.13453961997946601 + 0.13454346988104648 + 0.13454731986029447 + 0.13455116991721339 + 0.13455502005180647 + 0.13455887026407751 + 0.13456272055402951 + 0.13456657092166655 + 0.13457042136699154 + 0.13457427189000815 + 0.1345781224907199 + 0.13458197316913029 + 0.13458582392524274 + 0.13458967475906072 + 0.13459352567058766 + 0.13459737665982685 + 0.13460122772678229 + 0.13460507887145695 + 0.13460893009385447 + 0.13461278139397834 + 0.13461663277183214 + 0.13462048422741901 + 0.13462433576074276 + 0.1346281873718066 + 0.13463203906061419 + 0.13463589082716892 + 0.13463974267147427 + 0.13464359459353364 + 0.13464744659335062 + 0.13465129867092848 + 0.13465515082627103 + 0.13465900305938155 + 0.13466285537026343 + 0.13466670775892023 + 0.13467056022535537 + 0.13467441276957237 + 0.13467826539157468 + 0.1346821180913659 + 0.13468597086894915 + 0.13468982372432825 + 0.13469367665750664 + 0.13469752966848758 + 0.13470138275727475 + 0.13470523592387143 + 0.13470908916828114 + 0.13471294249050761 + 0.13471679589055396 + 0.13472064936842393 + 0.13472450292412066 + 0.13472835655764814 + 0.13473221026900933 + 0.13473606405820795 + 0.13473991792524753 + 0.13474377187013131 + 0.13474762589286285 + 0.13475147999344583 + 0.13475533417188354 + 0.13475918842817941 + 0.13476304276233708 + 0.13476689717435975 + 0.1347707516642512 + 0.13477460623201479 + 0.13477846087765394 + 0.13478231560117218 + 0.13478617040257285 + 0.13479002528185968 + 0.13479388023903599 + 0.13479773527410516 + 0.13480159038707079 + 0.13480544557793631 + 0.13480930084670528 + 0.13481315619338116 + 0.13481701161796725 + 0.13482086712046717 + 0.13482472270088455 + 0.13482857835922246 + 0.13483243409548459 + 0.13483628990967453 + 0.13484014580179579 + 0.13484400177185152 + 0.13484785781984551 + 0.13485171394578102 + 0.13485557014966168 + 0.13485942643149085 + 0.13486328279127222 + 0.13486713922900898 + 0.13487099574470462 + 0.13487485233836283 + 0.13487870900998694 + 0.13488256575958063 + 0.13488642258714706 + 0.13489027949268989 + 0.13489413647621248 + 0.13489799353771861 + 0.13490185067721144 + 0.1349057078946945 + 0.13490956519017147 + 0.13491342256364558 + 0.13491728001512041 + 0.13492113754459942 + 0.13492499515208617 + 0.13492885283758402 + 0.13493271060109635 + 0.134936568442627 + 0.13494042636217923 + 0.13494428435975642 + 0.13494814243536221 + 0.13495200058899995 + 0.13495585882067321 + 0.13495971713038543 + 0.13496357551814023 + 0.13496743398394068 + 0.13497129252779083 + 0.13497515114969375 + 0.13497900984965305 + 0.13498286862767209 + 0.13498672748375468 + 0.1349905864179039 + 0.13499444543012343 + 0.13499830452041686 + 0.13500216368878737 + 0.13500602293523875 + 0.13500988225977426 + 0.1350137416623976 + 0.13501760114311187 + 0.135021460701921 + 0.13502532033882814 + 0.13502918005383688 + 0.13503303984695086 + 0.13503689971817312 + 0.13504075966750778 + 0.13504461969495771 + 0.13504847980052681 + 0.13505233998421837 + 0.13505620024603576 + 0.13506006058598277 + 0.13506392100406278 + 0.13506778150027901 + 0.13507164207463529 + 0.13507550272713498 + 0.1350793634577814 + 0.13508322426657821 + 0.13508708515352894 + 0.13509094611863698 + 0.13509480716190572 + 0.13509866828333877 + 0.13510252948293977 + 0.13510639076071196 + 0.1351102521166585 + 0.13511411355078362 + 0.1351179750630904 + 0.13512183665358224 + 0.13512569832226276 + 0.13512956006913557 + 0.13513342189420388 + 0.13513728379747145 + 0.13514114577894137 + 0.13514500783861749 + 0.13514886997650327 + 0.13515273219260202 + 0.13515659448691725 + 0.13516045685945258 + 0.13516431931021156 + 0.13516818183919724 + 0.13517204444641359 + 0.1351759071318637 + 0.13517976989555139 + 0.13518363273748002 + 0.13518749565765306 + 0.13519135865607398 + 0.13519522173274631 + 0.13519908488767329 + 0.13520294812085898 + 0.13520681143230626 + 0.13521067482201904 + 0.13521453829000032 + 0.13521840183625414 + 0.13522226546078372 + 0.13522612916359253 + 0.1352299929446841 + 0.13523385680406202 + 0.1352377207417296 + 0.13524158475769033 + 0.13524544885194781 + 0.13524931302450555 + 0.13525317727536698 + 0.13525704160453542 + 0.1352609060120146 + 0.13526477049780788 + 0.13526863506191891 + 0.13527249970435087 + 0.13527636442510765 + 0.13528022922419225 + 0.13528409410160858 + 0.13528795905735996 + 0.13529182409144985 + 0.13529568920388185 + 0.13529955439465935 + 0.13530341966378603 + 0.13530728501126499 + 0.1353111504371001 + 0.1353150159412945 + 0.13531888152385205 + 0.13532274718477602 + 0.13532661292406992 + 0.13533047874173723 + 0.13533434463778155 + 0.13533821061220624 + 0.13534207666501474 + 0.13534594279621084 + 0.13534980900579774 + 0.13535367529377901 + 0.13535754166015804 + 0.13536140810493869 + 0.13536527462812384 + 0.13536914122971769 + 0.13537300790972309 + 0.13537687466814408 + 0.13538074150498369 + 0.13538460842024563 + 0.13538847541393331 + 0.13539234248605031 + 0.13539620963660012 + 0.13540007686558611 + 0.13540394417301202 + 0.13540781155888104 + 0.13541167902319678 + 0.13541554656596297 + 0.13541941418718267 + 0.13542328188685956 + 0.13542714966499733 + 0.13543101752159908 + 0.13543488545666876 + 0.13543875347020942 + 0.13544262156222489 + 0.13544648973271847 + 0.13545035798169366 + 0.13545422630915407 + 0.1354580947151032 + 0.13546196319954434 + 0.13546583176248109 + 0.13546970040391706 + 0.13547356912385572 + 0.13547743792230038 + 0.13548130679925457 + 0.13548517575472208 + 0.13548904478870605 + 0.13549291390121015 + 0.13549678309223773 + 0.13550065236179243 + 0.13550452170987773 + 0.1355083911364971 + 0.13551226064165406 + 0.13551613022535194 + 0.1355199998875945 + 0.13552386962838511 + 0.1355277394477272 + 0.13553160934562425 + 0.1355354793220799 + 0.13553934937709758 + 0.13554321951068077 + 0.13554708972283305 + 0.13555096001355757 + 0.13555483038285834 + 0.13555870083073848 + 0.13556257135720165 + 0.13556644196225143 + 0.13557031264589109 + 0.13557418340812424 + 0.13557805424895442 + 0.13558192516838505 + 0.13558579616641953 + 0.13558966724306151 + 0.13559353839831473 + 0.13559740963218228 + 0.13560128094466761 + 0.13560515233577453 + 0.13560902380550643 + 0.13561289535386664 + 0.13561676698085889 + 0.13562063868648658 + 0.13562451047075325 + 0.13562838233366217 + 0.13563225427521725 + 0.13563612629542174 + 0.13563999839427901 + 0.13564387057179278 + 0.13564774282796666 + 0.1356516151628038 + 0.13565548757630794 + 0.13565936006848237 + 0.13566323263933081 + 0.13566710528885667 + 0.13567097801706346 + 0.13567485082395467 + 0.13567872370953371 + 0.13568259667380433 + 0.13568646971676987 + 0.1356903428384337 + 0.13569421603879944 + 0.1356980893178707 + 0.13570196267565074 + 0.13570583611214324 + 0.13570970962735177 + 0.13571358322127952 + 0.13571745689393039 + 0.1357213306453075 + 0.1357252044754147 + 0.13572907838425521 + 0.13573295237183269 + 0.1357368264381506 + 0.13574070058321236 + 0.13574457480702162 + 0.1357484491095817 + 0.13575232349089628 + 0.13575619795096869 + 0.1357600724898026 + 0.1357639471074015 + 0.1357678218037687 + 0.135771696578908 + 0.13577557143282254 + 0.13577944636551606 + 0.13578332137699212 + 0.13578719646725407 + 0.13579107163630541 + 0.1357949468841497 + 0.13579882221079051 + 0.13580269761623129 + 0.13580657310047536 + 0.13581044866352648 + 0.13581432430538809 + 0.13581820002606368 + 0.13582207582555658 + 0.13582595170387066 + 0.13582982766100907 + 0.13583370369697537 + 0.13583757981177333 + 0.1358414560054062 + 0.13584533227787748 + 0.1358492086291907 + 0.13585308505934965 + 0.13585696156835736 + 0.13586083815621774 + 0.13586471482293414 + 0.13586859156850992 + 0.1358724683929487 + 0.13587634529625411 + 0.13588022227842955 + 0.1358840993394784 + 0.13588797647940434 + 0.13589185369821077 + 0.13589573099590135 + 0.1358996083724793 + 0.13590348582794851 + 0.13590736336231224 + 0.13591124097557411 + 0.13591511866773739 + 0.13591899643880567 + 0.13592287428878272 + 0.13592675221767178 + 0.13593063022547647 + 0.13593450831220022 + 0.13593838647784665 + 0.13594226472241905 + 0.13594614304592131 + 0.13595002144835647 + 0.13595389992972837 + 0.13595777849004032 + 0.13596165712929598 + 0.13596553584749871 + 0.13596941464465234 + 0.13597329352076001 + 0.13597717247582525 + 0.13598105150985174 + 0.13598493062284298 + 0.13598880981480252 + 0.13599268908573361 + 0.1359965684356399 + 0.13600044786452492 + 0.13600432737239224 + 0.13600820695924531 + 0.13601208662508765 + 0.13601596636992261 + 0.13601984619375385 + 0.1360237260965852 + 0.13602760607841957 + 0.13603148613926058 + 0.13603536627911211 + 0.13603924649797736 + 0.13604312679586006 + 0.13604700717276344 + 0.13605088762869127 + 0.13605476816364689 + 0.1360586487776341 + 0.13606252947065589 + 0.13606641024271604 + 0.13607029109381824 + 0.13607417202396585 + 0.13607805303316242 + 0.13608193412141117 + 0.13608581528871611 + 0.1360896965350803 + 0.13609357786050752 + 0.13609745926500122 + 0.13610134074856492 + 0.13610522231120212 + 0.1361091039529162 + 0.13611298567371088 + 0.13611686747358959 + 0.13612074935255583 + 0.13612463131061317 + 0.13612851334776493 + 0.13613239546401493 + 0.13613627765936642 + 0.13614015993382289 + 0.13614404228738816 + 0.1361479247200654 + 0.13615180723185838 + 0.13615568982277043 + 0.13615957249280525 + 0.13616345524196613 + 0.13616733807025666 + 0.13617122097768047 + 0.13617510396424101 + 0.13617898702994155 + 0.13618287017478609 + 0.13618675339877781 + 0.13619063670192028 + 0.1361945200842169 + 0.13619840354567142 + 0.1362022870862872 + 0.13620617070606783 + 0.13621005440501682 + 0.13621393818313765 + 0.13621782204043384 + 0.1362217059769088 + 0.13622558999256618 + 0.13622947408740968 + 0.13623335826144242 + 0.13623724251466801 + 0.13624112684709019 + 0.13624501125871233 + 0.13624889574953805 + 0.13625278031957064 + 0.13625666496881361 + 0.13626054969727067 + 0.13626443450494527 + 0.13626831939184109 + 0.1362722043579612 + 0.13627608940330965 + 0.13627997452788962 + 0.1362838597317047 + 0.13628774501475838 + 0.13629163037705433 + 0.13629551581859586 + 0.13629940133938667 + 0.13630328693943003 + 0.13630717261872968 + 0.13631105837728916 + 0.1363149442151117 + 0.13631883013220122 + 0.13632271612856087 + 0.13632660220419437 + 0.13633048835910525 + 0.13633437459329681 + 0.13633826090677292 + 0.13634214729953689 + 0.13634603377159218 + 0.13634992032294235 + 0.13635380695359101 + 0.13635769366354161 + 0.13636158045279775 + 0.13636546732136259 + 0.13636935426924021 + 0.13637324129643383 + 0.13637712840294702 + 0.13638101558878316 + 0.13638490285394589 + 0.13638879019843883 + 0.13639267762226531 + 0.13639656512542883 + 0.13640045270793319 + 0.13640434036978163 + 0.13640822811097778 + 0.13641211593152505 + 0.1364160038314273 + 0.13641989181068762 + 0.13642377986930973 + 0.13642766800729716 + 0.13643155622465342 + 0.13643544452138198 + 0.1364393328974865 + 0.1364432213529703 + 0.13644710988783687 + 0.13645099850209019 + 0.13645488719573326 + 0.1364587759687696 + 0.13646266482120326 + 0.13646655375303737 + 0.1364704427642755 + 0.13647433185492105 + 0.1364782210249777 + 0.13648211027444898 + 0.13648599960333835 + 0.13648988901164938 + 0.13649377849938571 + 0.1364976680665505 + 0.13650155771314745 + 0.13650544743918042 + 0.13650933724465247 + 0.13651322712956721 + 0.13651711709392841 + 0.13652100713773929 + 0.13652489726100361 + 0.13652878746372468 + 0.13653267774590624 + 0.13653656810755174 + 0.13654045854866451 + 0.13654434906924831 + 0.13654823966930665 + 0.13655213034884289 + 0.13655602110786072 + 0.13655991194636355 + 0.13656380286435515 + 0.13656769386183862 + 0.13657158493881777 + 0.13657547609529619 + 0.13657936733127712 + 0.13658325864676429 + 0.13658715004176128 + 0.13659104151627144 + 0.13659493307029827 + 0.13659882470384568 + 0.13660271641691671 + 0.13660660820951517 + 0.13661050008164433 + 0.13661439203330822 + 0.13661828406450982 + 0.13662217617525288 + 0.13662606836554084 + 0.13662996063537736 + 0.13663385298476585 + 0.13663774541371013 + 0.13664163792221318 + 0.13664553051027906 + 0.13664942317791107 + 0.13665331592511276 + 0.13665720875188747 + 0.13666110165823894 + 0.13666499464417067 + 0.13666888770968627 + 0.13667278085478904 + 0.13667667407948278 + 0.13668056738377068 + 0.13668446076765658 + 0.13668835423114387 + 0.13669224777423608 + 0.13669614139693667 + 0.13670003509924933 + 0.13670392888117749 + 0.13670782274272464 + 0.13671171668389456 + 0.13671561070469035 + 0.13671950480511599 + 0.13672339898517458 + 0.13672729324487001 + 0.13673118758420566 + 0.13673508200318488 + 0.13673897650181152 + 0.13674287108008895 + 0.13674676573802069 + 0.13675066047561041 + 0.13675455529286126 + 0.13675845018977714 + 0.1367623451663616 + 0.13676624022261813 + 0.13677013535854993 + 0.13677403057416088 + 0.13677792586945431 + 0.13678182124443378 + 0.13678571669910308 + 0.13678961223346556 + 0.13679350784752453 + 0.13679740354128386 + 0.13680129931474697 + 0.13680519516791728 + 0.13680909110079839 + 0.13681298711339382 + 0.13681688320570731 + 0.13682077937774209 + 0.13682467562950182 + 0.13682857196098996 + 0.13683246837221036 + 0.13683636486316614 + 0.1368402614338608 + 0.13684415808429823 + 0.1368480548144817 + 0.13685195162441502 + 0.1368558485141016 + 0.13685974548354468 + 0.1368636425327481 + 0.13686753966171536 + 0.13687143687044975 + 0.1368753341589552 + 0.13687923152723497 + 0.13688312897529276 + 0.13688702650313195 + 0.13689092411075607 + 0.13689482179816884 + 0.13689871956537347 + 0.136902617412374 + 0.13690651533917345 + 0.13691041334577553 + 0.13691431143218377 + 0.13691820959840192 + 0.13692210784443332 + 0.13692600617028158 + 0.13692990457595006 + 0.13693380306144243 + 0.136937701626762 + 0.13694160027191263 + 0.13694549899689792 + 0.13694939780172102 + 0.13695329668638578 + 0.13695719565089545 + 0.13696109469525383 + 0.13696499381946456 + 0.1369688930235308 + 0.13697279230745615 + 0.13697669167124435 + 0.13698059111489891 + 0.13698449063842319 + 0.13698839024182094 + 0.13699228992509546 + 0.13699618968825056 + 0.13700008953128956 + 0.13700398945421607 + 0.1370078894570336 + 0.13701178953974566 + 0.13701568970235603 + 0.13701958994486788 + 0.13702349026728514 + 0.13702739066961089 + 0.13703129115184909 + 0.13703519171400289 + 0.13703909235607617 + 0.13704299307807236 + 0.13704689387999489 + 0.13705079476184734 + 0.13705469572363341 + 0.13705859676535656 + 0.1370624978870201 + 0.13706639908862786 + 0.13707030037018331 + 0.13707420173168974 + 0.137078103173151 + 0.13708200469457055 + 0.13708590629595208 + 0.13708980797729861 + 0.13709370973861429 + 0.13709761157990222 + 0.13710151350116612 + 0.13710541550240954 + 0.13710931758363606 + 0.13711321974484919 + 0.13711712198605241 + 0.13712102430724921 + 0.13712492670844326 + 0.13712882918963801 + 0.13713273175083698 + 0.1371366343920439 + 0.13714053711326207 + 0.13714443991449515 + 0.13714834279574684 + 0.13715224575702034 + 0.13715614879831944 + 0.13716005191964747 + 0.13716395512100826 + 0.13716785840240506 + 0.13717176176384174 + 0.1371756652053214 + 0.13717956872684797 + 0.1371834723284249 + 0.13718737601005554 + 0.13719127977174375 + 0.13719518361349267 + 0.13719908753530627 + 0.13720299153718779 + 0.13720689561914082 + 0.13721079978116896 + 0.13721470402327582 + 0.13721860834546482 + 0.13722251274773969 + 0.13722641723010384 + 0.13723032179256062 + 0.13723422643511377 + 0.13723813115776698 + 0.13724203596052342 + 0.13724594084338712 + 0.13724984580636107 + 0.13725375084944935 + 0.13725765597265521 + 0.13726156117598209 + 0.13726546645943385 + 0.13726937182301377 + 0.13727327726672531 + 0.13727718279057252 + 0.13728108839455855 + 0.13728499407868675 + 0.13728889984296114 + 0.13729280568738492 + 0.13729671161196177 + 0.13730061761669535 + 0.13730452370158908 + 0.13730842986664665 + 0.13731233611187124 + 0.13731624243726673 + 0.13732014884283628 + 0.13732405532858402 + 0.13732796189451316 + 0.13733186854062707 + 0.13733577526692975 + 0.13733968207342434 + 0.13734358896011459 + 0.1373474959270039 + 0.13735140297409601 + 0.13735531010139435 + 0.1373592173089026 + 0.13736312459662403 + 0.13736703196456237 + 0.13737093941272124 + 0.13737484694110402 + 0.13737875454971438 + 0.13738266223855575 + 0.13738657000763177 + 0.13739047785694605 + 0.13739438578650182 + 0.13739829379630308 + 0.13740220188635308 + 0.1374061100566554 + 0.13741001830721364 + 0.13741392663803145 + 0.13741783504911217 + 0.13742174354045958 + 0.13742565211207694 + 0.13742956076396795 + 0.13743346949613638 + 0.13743737830858524 + 0.13744128720131865 + 0.1374451961743397 + 0.13744910522765233 + 0.1374530143612599 + 0.13745692357516573 + 0.1374608328693738 + 0.13746474224388747 + 0.13746865169871025 + 0.13747256123384571 + 0.1374764708492974 + 0.137480380545069 + 0.1374842903211638 + 0.13748820017758556 + 0.13749211011433785 + 0.13749602013142401 + 0.13749993022884771 + 0.13750384040661254 + 0.13750775066472212 + 0.13751166100317969 + 0.13751557142198922 + 0.13751948192115385 + 0.13752339250067749 + 0.13752730316056339 + 0.13753121390081557 + 0.13753512472143689 + 0.1375390356224315 + 0.13754294660380267 + 0.13754685766555391 + 0.13755076880768882 + 0.13755468003021107 + 0.13755859133312406 + 0.13756250271643161 + 0.13756641418013693 + 0.13757032572424377 + 0.13757423734875576 + 0.1375781490536761 + 0.1375820608390087 + 0.13758597270475692 + 0.13758988465092448 + 0.13759379667751467 + 0.13759770878453134 + 0.13760162097197787 + 0.13760553323985797 + 0.13760944558817492 + 0.13761335801693256 + 0.13761727052613421 + 0.13762118311578347 + 0.13762509578588403 + 0.13762900853643939 + 0.13763292136745306 + 0.13763683427892853 + 0.13764074727086958 + 0.13764466034327957 + 0.13764857349616202 + 0.13765248672952071 + 0.13765640004335908 + 0.1376603134376804 + 0.13766422691248881 + 0.13766814046778736 + 0.13767205410357983 + 0.13767596781986985 + 0.13767988161666064 + 0.1376837954939561 + 0.13768770945175954 + 0.13769162349007483 + 0.13769553760890521 + 0.13769945180825427 + 0.13770336608812594 + 0.13770728044852323 + 0.13771119488945002 + 0.13771510941090984 + 0.13771902401290623 + 0.13772293869544272 + 0.13772685345852295 + 0.13773076830215017 + 0.1377346832263284 + 0.13773859823106088 + 0.13774251331635132 + 0.13774642848220306 + 0.13775034372861991 + 0.13775425905560523 + 0.13775817446316296 + 0.1377620899512961 + 0.13776600552000862 + 0.13776992116930389 + 0.13777383689918543 + 0.13777775270965714 + 0.13778166860072197 + 0.13778558457238399 + 0.1377895006246467 + 0.13779341675751353 + 0.1377973329709879 + 0.13780124926507367 + 0.13780516563977432 + 0.13780908209509324 + 0.13781299863103424 + 0.13781691524760067 + 0.13782083194479608 + 0.13782474872262415 + 0.13782866558108853 + 0.13783258252019256 + 0.13783649953994009 + 0.13784041664033406 + 0.13784433382137887 + 0.13784825108307749 + 0.13785216842543366 + 0.13785608584845074 + 0.13786000335213289 + 0.13786392093648295 + 0.13786783860150498 + 0.13787175634720236 + 0.13787567417357852 + 0.13787959208063719 + 0.13788351006838204 + 0.1378874281368162 + 0.13789134628594385 + 0.13789526451576795 + 0.13789918282629232 + 0.13790310121752078 + 0.1379070196894564 + 0.13791093824210315 + 0.13791485687546423 + 0.13791877558954363 + 0.13792269438434457 + 0.13792661325987077 + 0.13793053221612583 + 0.13793445125311296 + 0.13793837037083623 + 0.13794228956929883 + 0.13794620884850456 + 0.13795012820845692 + 0.13795404764915942 + 0.13795796717061537 + 0.13796188677282889 + 0.13796580645580314 + 0.1379697262195419 + 0.13797364606404849 + 0.1379775659893267 + 0.13798148599538007 + 0.13798540608221208 + 0.13798932624982629 + 0.13799324649822622 + 0.13799716682741556 + 0.13800108723739804 + 0.1380050077281767 + 0.13800892829975564 + 0.13801284895213808 + 0.13801676968532764 + 0.13802069049932802 + 0.13802461139414282 + 0.13802853236977541 + 0.13803245342622958 + 0.13803637456350859 + 0.13804029578161617 + 0.13804421708055609 + 0.13804813846033143 + 0.13805205992094624 + 0.1380559814624038 + 0.13805990308470772 + 0.13806382478786175 + 0.13806774657186924 + 0.13807166843673399 + 0.13807559038245934 + 0.13807951240904889 + 0.13808343451650618 + 0.13808735670483488 + 0.1380912789740385 + 0.13809520132412073 + 0.1380991237550851 + 0.13810304626693506 + 0.13810696885967411 + 0.13811089153330597 + 0.13811481428783434 + 0.13811873712326231 + 0.138122660039594 + 0.13812658303683278 + 0.13813050611498204 + 0.13813442927404559 + 0.13813835251402687 + 0.13814227583492952 + 0.13814619923675692 + 0.13815012271951302 + 0.13815404628320088 + 0.13815796992782453 + 0.13816189365338738 + 0.13816581745989279 + 0.13816974134734469 + 0.13817366531574621 + 0.13817758936510147 + 0.13818151349541366 + 0.13818543770668631 + 0.1381893619989234 + 0.13819328637212785 + 0.13819721082630393 + 0.13820113536145462 + 0.13820505997758392 + 0.13820898467469514 + 0.13821290945279197 + 0.1382168343118779 + 0.13822075925195659 + 0.13822468427303164 + 0.13822860937510648 + 0.13823253455818482 + 0.13823645982227006 + 0.138240385167366 + 0.13824431059347603 + 0.13824823610060386 + 0.13825216168875284 + 0.1382560873579268 + 0.1382600131081291 + 0.13826393893936348 + 0.13826786485163342 + 0.13827179084494245 + 0.13827571691929422 + 0.13827964307469237 + 0.13828356931114036 + 0.13828749562864184 + 0.13829142202720027 + 0.13829534850681929 + 0.13829927506750253 + 0.13830320170925348 + 0.13830712843207568 + 0.13831105523597284 + 0.13831498212094845 + 0.13831890908700603 + 0.13832283613414917 + 0.13832676326238155 + 0.13833069047170679 + 0.13833461776212827 + 0.13833854513364954 + 0.13834247258627441 + 0.13834640012000632 + 0.13835032773484887 + 0.13835425543080551 + 0.13835818320787999 + 0.13836211106607596 + 0.1383660390053966 + 0.13836996702584586 + 0.13837389512742704 + 0.13837782331014398 + 0.13838175157400029 + 0.13838567991899925 + 0.13838960834514455 + 0.1383935368524398 + 0.13839746544088866 + 0.13840139411049454 + 0.13840532286126106 + 0.13840925169319199 + 0.13841318060629079 + 0.13841710960056075 + 0.13842103867600583 + 0.13842496783262939 + 0.1384288970704351 + 0.13843282638942664 + 0.13843675578960749 + 0.13844068527098097 + 0.13844461483355106 + 0.13844854447732119 + 0.13845247420229492 + 0.13845640400847584 + 0.1384603338958672 + 0.13846426386447336 + 0.1384681939142971 + 0.13847212404534243 + 0.13847605425761284 + 0.13847998455111199 + 0.13848391492584317 + 0.13848784538181039 + 0.13849177591901665 + 0.13849570653746593 + 0.13849963723716197 + 0.13850356801810801 + 0.13850749888030781 + 0.1385114298237648 + 0.13851536084848259 + 0.13851929195446494 + 0.13852322314171531 + 0.13852715441023705 + 0.13853108576003412 + 0.13853501719110986 + 0.13853894870346811 + 0.13854288029711206 + 0.13854681197204563 + 0.13855074372827225 + 0.13855467556579534 + 0.1385586074846189 + 0.13856253948474628 + 0.13856647156618074 + 0.13857040372892654 + 0.13857433597298663 + 0.138578268298365 + 0.13858220070506505 + 0.13858613319309038 + 0.13859006576244451 + 0.13859399841313125 + 0.13859793114515387 + 0.13860186395851623 + 0.13860579685322161 + 0.13860972982927397 + 0.13861366288667665 + 0.13861759602543333 + 0.1386215292455473 + 0.13862546254702252 + 0.13862939592986265 + 0.13863332939407086 + 0.13863726293965081 + 0.1386411965666064 + 0.13864513027494088 + 0.1386490640646581 + 0.13865299793576125 + 0.13865693188825454 + 0.13866086592214102 + 0.13866480003742432 + 0.13866873423410822 + 0.13867266851219637 + 0.13867660287169209 + 0.13868053731259905 + 0.13868447183492102 + 0.13868840643866132 + 0.13869234112382353 + 0.13869627589041153 + 0.13870021073842864 + 0.13870414566787839 + 0.13870808067876467 + 0.13871201577109096 + 0.13871595094486064 + 0.13871988620007752 + 0.13872382153674506 + 0.13872775695486703 + 0.13873169245444672 + 0.13873562803548789 + 0.13873956369799414 + 0.13874349944196895 + 0.13874743526741604 + 0.13875137117433897 + 0.13875530716274109 + 0.13875924323262648 + 0.13876317938399835 + 0.13876711561686025 + 0.13877105193121592 + 0.13877498832706875 + 0.13877892480442278 + 0.13878286136328108 + 0.1387867980036476 + 0.13879073472552569 + 0.13879467152891908 + 0.13879860841383143 + 0.13880254538026607 + 0.13880648242822671 + 0.13881041955771689 + 0.13881435676874027 + 0.13881829406130056 + 0.13882223143540123 + 0.13882616889104568 + 0.13883010642823768 + 0.13883404404698102 + 0.13883798174727896 + 0.13884191952913508 + 0.13884585739255323 + 0.13884979533753694 + 0.13885373336408954 + 0.13885767147221492 + 0.13886160966191638 + 0.13886554793319791 + 0.13886948628606263 + 0.13887342472051445 + 0.13887736323655694 + 0.13888130183419362 + 0.1388852405134281 + 0.13888917927426392 + 0.1388931181167046 + 0.13889705704075403 + 0.13890099604641548 + 0.13890493513369254 + 0.13890887430258925 + 0.13891281355310864 + 0.13891675288525454 + 0.13892069229903051 + 0.13892463179444031 + 0.13892857137148731 + 0.13893251103017504 + 0.13893645077050751 + 0.13894039059248772 + 0.13894433049611968 + 0.13894827048140695 + 0.13895221054835305 + 0.13895615069696149 + 0.13896009092723588 + 0.13896403123918 + 0.13896797163279717 + 0.13897191210809118 + 0.13897585266506574 + 0.13897979330372412 + 0.13898373402406994 + 0.13898767482610708 + 0.13899161570983889 + 0.13899555667526914 + 0.13899949772240117 + 0.13900343885123875 + 0.13900738006178556 + 0.13901132135404498 + 0.13901526272802045 + 0.13901920418371638 + 0.13902314572113542 + 0.13902708734028163 + 0.13903102903656733 + 0.13903497081828933 + 0.13903891269170685 + 0.13904285465682406 + 0.13904679671364439 + 0.1390507388621712 + 0.13905468110240832 + 0.1390586234343596 + 0.13906256585802837 + 0.139066508373418 + 0.13907045098053272 + 0.13907439367937557 + 0.13907833646995044 + 0.13908227935226097 + 0.1390862223263106 + 0.13909016539210309 + 0.13909410854964202 + 0.13909805179893095 + 0.13910199513997354 + 0.13910593857277345 + 0.13910988209733416 + 0.13911382571365941 + 0.13911776942175266 + 0.13912171322161762 + 0.13912565711325789 + 0.13912960109667716 + 0.13913354517187904 + 0.13913748933886699 + 0.13914143359764486 + 0.13914537794821585 + 0.139149322390584 + 0.13915326692475277 + 0.13915721155072577 + 0.13916115626850648 + 0.13916510107809885 + 0.13916904597950616 + 0.13917299097273222 + 0.13917693605778048 + 0.13918088123465477 + 0.13918482650335845 + 0.13918877186389542 + 0.13919271731626892 + 0.13919666286048307 + 0.13920060849654101 + 0.13920455422444664 + 0.13920850004420343 + 0.13921244595581514 + 0.13921639195928517 + 0.13922033805461728 + 0.13922428424181513 + 0.13922823052088221 + 0.13923217689182218 + 0.13923612335463867 + 0.13924006990933532 + 0.13924401655591584 + 0.13924796329438352 + 0.13925191012474233 + 0.13925585704699561 + 0.13925980406114727 + 0.13926375116720063 + 0.1392676983651594 + 0.13927164565502737 + 0.13927559303680795 + 0.13927954051050476 + 0.13928348807612156 + 0.13928743573366195 + 0.1392913834831295 + 0.13929533132452757 + 0.13929927925786018 + 0.13930322728313085 + 0.13930717540034296 + 0.13931112360950049 + 0.1393150719106068 + 0.13931902030366561 + 0.13932296878868025 + 0.13932691736565481 + 0.1393308660345926 + 0.13933481479549753 + 0.13933876364837286 + 0.13934271259322226 + 0.13934666163004966 + 0.13935061075885838 + 0.13935455997965204 + 0.13935850929243448 + 0.13936245869720904 + 0.13936640819397958 + 0.13937035778274956 + 0.13937430746352264 + 0.13937825723630248 + 0.1393822071010927 + 0.13938615705789709 + 0.13939010710671873 + 0.13939405724756165 + 0.1393980074804296 + 0.13940195780532585 + 0.13940590822225432 + 0.13940985873121831 + 0.13941380933222175 + 0.13941776002526787 + 0.13942171081036078 + 0.13942566168750387 + 0.13942961265670045 + 0.13943356371795479 + 0.1394375148712699 + 0.1394414661166499 + 0.13944541745409803 + 0.13944936888361806 + 0.13945332040521358 + 0.13945727201888836 + 0.13946122372464573 + 0.13946517552248952 + 0.1394691274124232 + 0.13947307939445067 + 0.13947703146857518 + 0.13948098363480088 + 0.13948493589313074 + 0.13948888824356889 + 0.13949284068611861 + 0.1394967932207837 + 0.13950074584756786 + 0.13950469856647466 + 0.1395086513775074 + 0.13951260428067022 + 0.1395165572759664 + 0.13952051036339963 + 0.1395244635429736 + 0.13952841681469191 + 0.13953237017855816 + 0.13953632363457588 + 0.13954027718274878 + 0.13954423082308051 + 0.13954818455557469 + 0.13955213838023495 + 0.13955609229706503 + 0.13956004630606814 + 0.13956400040724842 + 0.13956795460060903 + 0.13957190888615403 + 0.13957586326388657 + 0.13957981773381062 + 0.13958377229592969 + 0.1395877269502476 + 0.13959168169676772 + 0.13959563653549359 + 0.13959959146642917 + 0.13960354648957782 + 0.13960750160494323 + 0.13961145681252912 + 0.13961541211233891 + 0.13961936750437659 + 0.13962332298864538 + 0.13962727856514914 + 0.13963123423389143 + 0.1396351899948759 + 0.13963914584810599 + 0.13964310179358577 + 0.13964705783131831 + 0.13965101396130769 + 0.13965497018355716 + 0.13965892649807077 + 0.13966288290485179 + 0.1396668394039039 + 0.13967079599523088 + 0.13967475267883633 + 0.13967870945472366 + 0.1396826663228968 + 0.13968662328335915 + 0.13969058033611439 + 0.13969453748116625 + 0.13969849471851817 + 0.13970245204817403 + 0.13970640947013716 + 0.1397103669844115 + 0.13971432459100017 + 0.13971828228990765 + 0.13972224008113657 + 0.13972619796469141 + 0.13973015594057514 + 0.13973411400879179 + 0.13973807216934497 + 0.13974203042223812 + 0.13974598876747493 + 0.13974994720505915 + 0.13975390573499427 + 0.13975786435728402 + 0.1397618230719318 + 0.13976578187894151 + 0.13976974077831683 + 0.13977369977006088 + 0.13977765885417795 + 0.1397816180306711 + 0.13978557729954441 + 0.13978953666080129 + 0.13979349611444544 + 0.13979745566048046 + 0.1398014152989098 + 0.13980537502973728 + 0.13980933485296659 + 0.13981329476860133 + 0.13981725477664494 + 0.13982121487710131 + 0.13982517506997369 + 0.13982913535526625 + 0.13983309573298205 + 0.13983705620312512 + 0.13984101676569913 + 0.13984497742070748 + 0.13984893816815364 + 0.13985289900804163 + 0.13985685994037492 + 0.13986082096515712 + 0.13986478208239186 + 0.13986874329208276 + 0.13987270459423345 + 0.13987666598884771 + 0.13988062747592897 + 0.13988458905548093 + 0.13988855072750725 + 0.13989251249201154 + 0.13989647434899741 + 0.13990043629846863 + 0.13990439834042859 + 0.13990836047488114 + 0.13991232270182966 + 0.13991628502127801 + 0.13992024743322976 + 0.13992420993768856 + 0.13992817253465809 + 0.13993213522414166 + 0.13993609800614334 + 0.13994006088066654 + 0.1399440238477149 + 0.13994798690729213 + 0.1399519500594017 + 0.13995591330404744 + 0.13995987664123283 + 0.13996384007096163 + 0.13996780359323732 + 0.1399717672080637 + 0.13997573091544438 + 0.13997969471538288 + 0.13998365860788281 + 0.13998762259294795 + 0.13999158667058184 + 0.13999555084078802 + 0.13999951510357031 + 0.14000347945893241 + 0.14000744390687772 + 0.14001140844740997 + 0.14001537308053269 + 0.14001933780624978 + 0.14002330262456456 + 0.14002726753548111 + 0.14003123253900243 + 0.14003519763513281 + 0.14003916282387532 + 0.14004312810523406 + 0.14004709347921235 + 0.14005105894581385 + 0.1400550245050424 + 0.14005899015690143 + 0.14006295590139456 + 0.14006692173852578 + 0.14007088766829814 + 0.14007485369071571 + 0.14007881980578202 + 0.14008278601350077 + 0.14008675231387546 + 0.14009071870690978 + 0.14009468519260748 + 0.14009865177097189 + 0.14010261844200708 + 0.14010658520571628 + 0.14011055206210329 + 0.14011451901117181 + 0.14011848605292543 + 0.14012245318736791 + 0.14012642041450254 + 0.14013038773433317 + 0.14013435514686365 + 0.14013832265209725 + 0.1401422902500376 + 0.14014625794068877 + 0.14015022572405395 + 0.14015419360013701 + 0.14015816156894154 + 0.14016212963047128 + 0.1401660977847296 + 0.14017006603172036 + 0.14017403437144707 + 0.14017800280391349 + 0.14018197132912322 + 0.1401859399470797 + 0.14018990865778674 + 0.1401938774612482 + 0.14019784635746743 + 0.14020181534644807 + 0.1402057844281939 + 0.14020975360270835 + 0.14021372286999523 + 0.14021769223005817 + 0.14022166168290087 + 0.14022563122852671 + 0.14022960086693961 + 0.14023357059814312 + 0.14023754042214073 + 0.14024151033893623 + 0.14024548034853326 + 0.14024945045093537 + 0.14025342064614635 + 0.14025739093416975 + 0.14026136131500919 + 0.14026533178866835 + 0.14026930235515081 + 0.14027327301446038 + 0.14027724376660036 + 0.14028121461157486 + 0.14028518554938707 + 0.14028915658004082 + 0.14029312770353983 + 0.14029709891988759 + 0.14030107022908783 + 0.14030504163114418 + 0.14030901312606026 + 0.14031298471383979 + 0.14031695639448641 + 0.14032092816800359 + 0.14032490003439507 + 0.14032887199366453 + 0.14033284404581564 + 0.14033681619085189 + 0.14034078842877692 + 0.14034476075959471 + 0.14034873318330868 + 0.14035270569992223 + 0.14035667830943932 + 0.14036065101186349 + 0.14036462380719841 + 0.14036859669544766 + 0.14037256967661485 + 0.14037654275070374 + 0.14038051591771822 + 0.14038448917766119 + 0.14038846253053702 + 0.14039243597634904 + 0.14039640951510096 + 0.14040038314679634 + 0.14040435687143871 + 0.14040833068903211 + 0.14041230459957979 + 0.14041627860308575 + 0.14042025269955324 + 0.14042422688898626 + 0.14042820117138832 + 0.14043217554676285 + 0.14043615001511389 + 0.14044012457644481 + 0.14044409923075923 + 0.140448073978061 + 0.14045204881835349 + 0.14045602375164074 + 0.14045999877792606 + 0.14046397389721316 + 0.14046794910950572 + 0.14047192441480744 + 0.14047589981312189 + 0.14047987530445274 + 0.14048385088880347 + 0.14048782656617803 + 0.1404918023365799 + 0.14049577820001286 + 0.14049975415648036 + 0.140503730205986 + 0.14050770634853371 + 0.14051168258412705 + 0.14051565891276951 + 0.14051963533446465 + 0.1405236118492165 + 0.14052758845702831 + 0.14053156515790419 + 0.14053554195184734 + 0.14053951883886148 + 0.1405434958189504 + 0.14054747289211783 + 0.14055145005836708 + 0.14055542731770201 + 0.14055940467012659 + 0.14056338211564381 + 0.14056735965425782 + 0.14057133728597188 + 0.14057531501079004 + 0.14057929282871559 + 0.14058327073975241 + 0.14058724874390419 + 0.14059122684117417 + 0.14059520503156658 + 0.14059918331508481 + 0.14060316169173229 + 0.14060714016151293 + 0.14061111872443025 + 0.14061509738048791 + 0.14061907612968974 + 0.14062305497203925 + 0.14062703390754 + 0.14063101293619581 + 0.14063499205801022 + 0.14063897127298688 + 0.14064295058112949 + 0.14064692998244149 + 0.14065090947692699 + 0.14065488906458931 + 0.14065886874543204 + 0.14066284851945904 + 0.14066682838667377 + 0.1406708083470801 + 0.14067478840068146 + 0.14067876854748165 + 0.14068274878748419 + 0.14068672912069283 + 0.14069070954711099 + 0.14069469006674279 + 0.14069867067959158 + 0.1407026513856609 + 0.14070663218495472 + 0.14071061307747634 + 0.14071459406322981 + 0.14071857514221833 + 0.1407225563144458 + 0.14072653757991596 + 0.14073051893863223 + 0.14073450039059854 + 0.14073848193581817 + 0.14074246357429507 + 0.14074644530603267 + 0.14075042713103503 + 0.14075440904930533 + 0.14075839106084764 + 0.14076237316566512 + 0.14076635536376175 + 0.14077033765514119 + 0.14077432003980703 + 0.14077830251776302 + 0.14078228508901253 + 0.14078626775355943 + 0.14079025051140739 + 0.14079423336255995 + 0.14079821630702077 + 0.14080219934479363 + 0.14080618247588211 + 0.14081016570029001 + 0.1408141490180205 + 0.14081813242907779 + 0.1408221159334653 + 0.14082609953118658 + 0.14083008322224547 + 0.14083406700664547 + 0.1408380508843905 + 0.14084203485548377 + 0.14084601891992946 + 0.14085000307773085 + 0.14085398732889157 + 0.14085797167341568 + 0.14086195611130634 + 0.14086594064256738 + 0.14086992526720266 + 0.14087390998521568 + 0.14087789479660989 + 0.14088187970138935 + 0.14088586469955741 + 0.1408898497911179 + 0.14089383497607413 + 0.14089782025443026 + 0.14090180562618965 + 0.14090579109135598 + 0.14090977664993304 + 0.14091376230192437 + 0.14091774804733348 + 0.14092173388616441 + 0.14092571981842048 + 0.14092970584410544 + 0.14093369196322303 + 0.14093767817577676 + 0.14094166448177031 + 0.1409456508812075 + 0.14094963737409177 + 0.1409536239604271 + 0.14095761064021672 + 0.14096159741346459 + 0.14096558428017422 + 0.1409695712403494 + 0.14097355829399366 + 0.14097754544111063 + 0.14098153268170427 + 0.14098552001577766 + 0.14098950744333502 + 0.14099349496437988 + 0.14099748257891562 + 0.14100147028694629 + 0.14100545808847514 + 0.14100944598350623 + 0.14101343397204288 + 0.14101742205408901 + 0.14102141022964804 + 0.14102539849872386 + 0.14102938686131999 + 0.14103337531744009 + 0.14103736386708782 + 0.14104135251026703 + 0.14104534124698104 + 0.14104933007723358 + 0.14105331900102852 + 0.14105730801836949 + 0.14106129712925999 + 0.14106528633370385 + 0.14106927563170454 + 0.14107326502326584 + 0.1410772545083914 + 0.14108124408708478 + 0.14108523375934989 + 0.14108922352519002 + 0.14109321338460923 + 0.14109720333761089 + 0.14110119338419871 + 0.14110518352437643 + 0.14110917375814785 + 0.14111316408551641 + 0.14111715450648554 + 0.14112114502105932 + 0.14112513562924134 + 0.14112912633103517 + 0.14113311712644439 + 0.14113710801547288 + 0.1411410989981241 + 0.14114509007440199 + 0.14114908124430978 + 0.14115307250785142 + 0.14115706386503052 + 0.14116105531585083 + 0.14116504686031597 + 0.14116903849842929 + 0.14117303023019498 + 0.14117702205561639 + 0.14118101397469723 + 0.14118500598744102 + 0.14118899809385166 + 0.14119299029393273 + 0.14119698258768792 + 0.14120097497512077 + 0.14120496745623501 + 0.14120896003103431 + 0.14121295269952236 + 0.14121694546170299 + 0.14122093831757951 + 0.14122493126715577 + 0.14122892431043535 + 0.14123291744742203 + 0.14123691067811942 + 0.14124090400253106 + 0.14124489742066096 + 0.14124889093251233 + 0.14125288453808921 + 0.14125687823739524 + 0.14126087203043386 + 0.14126486591720869 + 0.14126885989772367 + 0.1412728539719825 + 0.14127684813998848 + 0.14128084240174543 + 0.14128483675725714 + 0.14128883120652716 + 0.14129282574955929 + 0.14129682038635707 + 0.14130081511692402 + 0.14130480994126418 + 0.14130880485938088 + 0.14131279987127801 + 0.14131679497695912 + 0.14132079017642782 + 0.14132478546968807 + 0.14132878085674302 + 0.14133277633759678 + 0.14133677191225297 + 0.14134076758071507 + 0.14134476334298676 + 0.14134875919907178 + 0.14135275514897389 + 0.14135675119269667 + 0.1413607473302437 + 0.14136474356161888 + 0.14136873988682541 + 0.14137273630586747 + 0.14137673281874866 + 0.14138072942547231 + 0.1413847261260423 + 0.14138872292046237 + 0.14139271980873605 + 0.14139671679086716 + 0.1414007138668591 + 0.14140471103671587 + 0.14140870830044092 + 0.1414127056580379 + 0.14141670310951077 + 0.14142070065486267 + 0.14142469829409779 + 0.14142869602721961 + 0.14143269385423163 + 0.14143669177513768 + 0.14144068978994159 + 0.14144468789864664 + 0.1414486861012568 + 0.1414526843977757 + 0.14145668278820683 + 0.14146068127255401 + 0.14146467985082081 + 0.14146867852301123 + 0.14147267728912863 + 0.14147667614917653 + 0.14148067510315898 + 0.14148467415107943 + 0.14148867329294146 + 0.141492672528749 + 0.14149667185850581 + 0.141500671282215 + 0.14150467079988072 + 0.14150867041150642 + 0.14151267011709584 + 0.14151666991665282 + 0.14152066981018072 + 0.1415246697976833 + 0.14152866987916449 + 0.14153267005462772 + 0.14153667032407666 + 0.14154067068751505 + 0.14154467114494645 + 0.14154867169637481 + 0.14155267234180352 + 0.14155667308123634 + 0.14156067391467686 + 0.14156467484212909 + 0.14156867586359617 + 0.1415726769790821 + 0.1415766781885906 + 0.14158067949212527 + 0.1415846808896897 + 0.14158868238128741 + 0.14159268396692259 + 0.14159668564659861 + 0.14160068742031887 + 0.14160468928808756 + 0.14160869124990805 + 0.14161269330578402 + 0.141616695455719 + 0.14162069769971711 + 0.14162470003778174 + 0.14162870246991649 + 0.14163270499612515 + 0.14163670761641145 + 0.14164071033077871 + 0.14164471313923133 + 0.14164871604177215 + 0.14165271903840537 + 0.14165672212913466 + 0.14166072531396334 + 0.14166472859289542 + 0.14166873196593432 + 0.14167273543308415 + 0.1416767389943481 + 0.14168074264972988 + 0.14168474639923348 + 0.1416887502428622 + 0.14169275418062027 + 0.14169675821251057 + 0.14170076233853762 + 0.14170476655870451 + 0.14170877087301531 + 0.14171277528147333 + 0.14171677978408229 + 0.14172078438084623 + 0.14172478907176839 + 0.14172879385685261 + 0.14173279873610273 + 0.14173680370952227 + 0.14174080877711484 + 0.14174481393888413 + 0.14174881919483395 + 0.14175282454496788 + 0.14175682998928976 + 0.14176083552780303 + 0.14176484116051136 + 0.14176884688741864 + 0.14177285270852857 + 0.14177685862384448 + 0.14178086463337033 + 0.14178487073710974 + 0.14178887693506631 + 0.14179288322724398 + 0.141796889613646 + 0.14180089609427646 + 0.14180490266913867 + 0.14180890933823678 + 0.14181291610157398 + 0.14181692295915427 + 0.14182092991098103 + 0.14182493695705822 + 0.14182894409738947 + 0.14183295133197846 + 0.14183695866082854 + 0.14184096608394381 + 0.14184497360132794 + 0.14184898121298428 + 0.1418529889189169 + 0.14185699671912896 + 0.14186100461362466 + 0.14186501260240728 + 0.14186902068548105 + 0.14187302886284903 + 0.14187703713451524 + 0.1418810455004833 + 0.14188505396075693 + 0.14188906251533948 + 0.14189307116423519 + 0.1418970799074474 + 0.14190108874497995 + 0.14190509767683612 + 0.14190910670302001 + 0.14191311582353514 + 0.14191712503838524 + 0.14192113434757403 + 0.14192514375110521 + 0.14192915324898217 + 0.1419331628412088 + 0.14193717252778898 + 0.14194118230872613 + 0.14194519218402396 + 0.14194920215368631 + 0.14195321221771659 + 0.14195722237611869 + 0.14196123262889632 + 0.14196524297605287 + 0.14196925341759237 + 0.14197326395351839 + 0.14197727458383444 + 0.14198128530854465 + 0.14198529612765201 + 0.1419893070411607 + 0.14199331804907453 + 0.1419973291513966 + 0.14200134034813122 + 0.14200535163928166 + 0.1420093630248517 + 0.14201337450484519 + 0.14201738607926542 + 0.14202139774811651 + 0.14202540951140191 + 0.14202942136912539 + 0.14203343332129054 + 0.14203744536790122 + 0.14204145750896108 + 0.14204546974447341 + 0.1420494820744424 + 0.14205349449887153 + 0.14205750701776448 + 0.14206151963112493 + 0.14206553233895663 + 0.14206954514126313 + 0.14207355803804822 + 0.14207757102931559 + 0.14208158411506888 + 0.14208559729531187 + 0.14208961057004815 + 0.14209362393928135 + 0.14209763740301526 + 0.14210165096125357 + 0.14210566461399982 + 0.14210967836125785 + 0.14211369220303124 + 0.14211770613932392 + 0.14212172017013919 + 0.14212573429548109 + 0.14212974851535309 + 0.14213376282975906 + 0.14213777723870233 + 0.14214179174218694 + 0.14214580634021648 + 0.1421498210327945 + 0.14215383581992497 + 0.14215785070161133 + 0.14216186567785724 + 0.14216588074866648 + 0.14216989591404292 + 0.14217391117398992 + 0.14217792652851141 + 0.14218194197761103 + 0.14218595752129229 + 0.14218997315955911 + 0.142193988892415 + 0.14219800471986382 + 0.14220202064190923 + 0.14220603665855461 + 0.14221005276980409 + 0.14221406897566108 + 0.14221808527612931 + 0.14222210167121244 + 0.14222611816091435 + 0.14223013474523855 + 0.14223415142418877 + 0.14223816819776886 + 0.14224218506598224 + 0.14224620202883259 + 0.14225021908632379 + 0.14225423623845954 + 0.14225825348524349 + 0.14226227082667917 + 0.14226628826277044 + 0.14227030579352096 + 0.14227432341893426 + 0.1422783411390143 + 0.14228235895376462 + 0.1422863768631889 + 0.14229039486729098 + 0.14229441296607429 + 0.14229843115954269 + 0.14230244944769985 + 0.14230646783054937 + 0.14231048630809509 + 0.14231450488034061 + 0.14231852354728966 + 0.14232254230894598 + 0.14232656116531309 + 0.14233058011639482 + 0.14233459916219471 + 0.14233861830271671 + 0.14234263753796428 + 0.14234665686794118 + 0.14235067629265125 + 0.14235469581209795 + 0.14235871542628498 + 0.14236273513521625 + 0.1423667549388952 + 0.14237077483732583 + 0.1423747948305116 + 0.14237881491845622 + 0.14238283510116337 + 0.14238685537863693 + 0.14239087575088014 + 0.14239489621789736 + 0.1423989167796916 + 0.14240293743626697 + 0.14240695818762727 + 0.1424109790337757 + 0.14241499997471643 + 0.14241902101045284 + 0.14242304214098891 + 0.14242706336632802 + 0.14243108468647422 + 0.14243510610143079 + 0.14243912761120167 + 0.14244314921579071 + 0.14244717091520112 + 0.1424511927094371 + 0.14245521459850208 + 0.14245923658239976 + 0.14246325866113391 + 0.14246728083470828 + 0.14247130310312625 + 0.14247532546639194 + 0.14247934792450873 + 0.14248337047748039 + 0.14248739312531078 + 0.14249141586800346 + 0.14249543870556211 + 0.14249946163799046 + 0.1425034846652922 + 0.14250750778747101 + 0.14251153100453046 + 0.14251555431647464 + 0.14251957772330695 + 0.14252360122503088 + 0.14252762482165043 + 0.14253164851316927 + 0.14253567229959122 + 0.14253969618091969 + 0.14254372015715849 + 0.1425477442283114 + 0.14255176839438202 + 0.14255579265537405 + 0.14255981701129125 + 0.14256384146213721 + 0.14256786600791574 + 0.14257189064863057 + 0.14257591538428516 + 0.1425799402148834 + 0.14258396514042898 + 0.14258799016092577 + 0.14259201527637691 + 0.1425960404867867 + 0.14260006579215848 + 0.14260409119249623 + 0.14260811668780318 + 0.14261214227808353 + 0.1426161679633409 + 0.14262019374357846 + 0.14262421961880073 + 0.14262824558901074 + 0.14263227165421266 + 0.14263629781440981 + 0.142640324069606 + 0.14264435041980505 + 0.14264837686501053 + 0.14265240340522634 + 0.14265643004045581 + 0.14266045677070296 + 0.14266448359597128 + 0.14266851051626489 + 0.14267253753158685 + 0.14267656464194145 + 0.14268059184733209 + 0.14268461914776226 + 0.14268864654323607 + 0.14269267403375721 + 0.14269670161932899 + 0.14270072929995542 + 0.14270475707564023 + 0.14270878494638703 + 0.14271281291219937 + 0.14271684097308124 + 0.14272086912903606 + 0.14272489738006772 + 0.14272892572617996 + 0.14273295416737622 + 0.1427369827036605 + 0.14274101133503625 + 0.14274504006150737 + 0.1427490688830774 + 0.14275309779975015 + 0.1427571268115293 + 0.14276115591841862 + 0.14276518512042169 + 0.14276921441754223 + 0.14277324380978404 + 0.14277727329715076 + 0.14278130287964585 + 0.14278533255727358 + 0.1427893623300372 + 0.14279339219794052 + 0.1427974221609872 + 0.14280145221918103 + 0.14280548237252585 + 0.14280951262102504 + 0.14281354296468243 + 0.14281757340350179 + 0.14282160393748686 + 0.14282563456664119 + 0.14282966529096869 + 0.14283369611047272 + 0.14283772702515743 + 0.14284175803502613 + 0.14284578914008267 + 0.14284982034033092 + 0.14285385163577433 + 0.14285788302641678 + 0.14286191451226188 + 0.14286594609331341 + 0.14286997776957505 + 0.14287400954105028 + 0.14287804140774304 + 0.14288207336965716 + 0.14288610542679614 + 0.14289013757916375 + 0.14289416982676365 + 0.14289820216959948 + 0.14290223460767512 + 0.1429062671409943 + 0.14291029976956043 + 0.14291433249337751 + 0.14291836531244906 + 0.14292239822677896 + 0.14292643123637078 + 0.14293046434122825 + 0.14293449754135507 + 0.14293853083675495 + 0.14294256422743176 + 0.14294659771338891 + 0.14295063129463051 + 0.14295466497115969 + 0.14295869874298073 + 0.14296273261009695 + 0.14296676657251223 + 0.14297080063023035 + 0.14297483478325476 + 0.14297886903158932 + 0.14298290337523781 + 0.14298693781420391 + 0.14299097234849117 + 0.14299500697810358 + 0.1429990417030445 + 0.1430030765233179 + 0.14300711143892744 + 0.14301114644987684 + 0.14301518155616966 + 0.14301921675780965 + 0.1430232520548006 + 0.14302728744714635 + 0.14303132293485041 + 0.14303535851791641 + 0.14303939419634829 + 0.14304342997014968 + 0.14304746583932401 + 0.14305150180387555 + 0.14305553786380765 + 0.14305957401912398 + 0.14306361026982845 + 0.14306764661592453 + 0.14307168305741619 + 0.14307571959430676 + 0.14307975622660046 + 0.14308379295430065 + 0.14308782977741114 + 0.14309186669593571 + 0.14309590370987785 + 0.14309994081924146 + 0.14310397802403022 + 0.14310801532424783 + 0.14311205271989819 + 0.14311609021098448 + 0.14312012779751088 + 0.14312416547948104 + 0.14312820325689848 + 0.14313224112976713 + 0.14313627909809043 + 0.14314031716187256 + 0.14314435532111658 + 0.14314839357582684 + 0.14315243192600671 + 0.14315647037165988 + 0.1431605089127902 + 0.14316454754940139 + 0.14316858628149687 + 0.14317262510908074 + 0.14317666403215665 + 0.14318070305072811 + 0.14318474216479887 + 0.14318878137437277 + 0.14319282067945352 + 0.14319686008004473 + 0.14320089957615006 + 0.14320493916777338 + 0.14320897885491846 + 0.1432130186375889 + 0.14321705851578831 + 0.14322109848952067 + 0.14322513855878941 + 0.14322917872359828 + 0.14323321898395119 + 0.14323725933985174 + 0.14324129979130354 + 0.14324534033831049 + 0.14324938098087633 + 0.14325342171900463 + 0.14325746255269903 + 0.14326150348196343 + 0.14326554450680143 + 0.14326958562721681 + 0.1432736268432134 + 0.14327766815479462 + 0.14328170956196443 + 0.14328575106472624 + 0.14328979266308434 + 0.14329383435704179 + 0.14329787614660294 + 0.143301918031771 + 0.14330596001254967 + 0.14331000208894307 + 0.14331404426095465 + 0.14331808652858827 + 0.14332212889184739 + 0.14332617135073586 + 0.14333021390525766 + 0.14333425655541612 + 0.14333829930121508 + 0.14334234214265848 + 0.14334638507974959 + 0.14335042811249252 + 0.14335447124089087 + 0.14335851446494832 + 0.14336255778466855 + 0.1433666012000554 + 0.14337064471111252 + 0.1433746883178435 + 0.14337873202025228 + 0.14338277581834255 + 0.14338681971211786 + 0.14339086370158211 + 0.1433949077867388 + 0.143398951967592 + 0.1434029962441449 + 0.1434070406164018 + 0.1434110850843662 + 0.14341512964804154 + 0.14341917430743173 + 0.14342321906254066 + 0.14342726391337204 + 0.1434313088599293 + 0.14343535390221629 + 0.14343939904023684 + 0.14344344427399472 + 0.14344748960349324 + 0.14345153502873667 + 0.14345558054972837 + 0.14345962616647198 + 0.14346367187897169 + 0.14346771768723082 + 0.14347176359125291 + 0.14347580959104236 + 0.14347985568660207 + 0.14348390187793661 + 0.14348794816504906 + 0.14349199454794348 + 0.14349604102662344 + 0.14350008760109248 + 0.14350413427135469 + 0.14350818103741372 + 0.14351222789927306 + 0.14351627485693666 + 0.14352032191040817 + 0.1435243690596911 + 0.14352841630478946 + 0.14353246364570688 + 0.14353651108244717 + 0.14354055861501383 + 0.14354460624341089 + 0.1435486539676418 + 0.14355270178771037 + 0.14355674970362037 + 0.14356079771537542 + 0.14356484582297938 + 0.14356889402643586 + 0.14357294232574855 + 0.14357699072092131 + 0.14358103921195775 + 0.14358508779886162 + 0.14358913648163671 + 0.14359318526028678 + 0.14359723413481559 + 0.14360128310522638 + 0.14360533217152355 + 0.14360938133371035 + 0.14361343059179074 + 0.14361747994576821 + 0.14362152939564679 + 0.14362557894143008 + 0.14362962858312164 + 0.14363367832072546 + 0.14363772815424508 + 0.14364177808368436 + 0.14364582810904691 + 0.14364987823033645 + 0.14365392844755681 + 0.14365797876071165 + 0.14366202916980478 + 0.1436660796748396 + 0.14367013027582043 + 0.14367418097275036 + 0.14367823176563355 + 0.14368228265447358 + 0.14368633363927411 + 0.14369038472003889 + 0.1436944358967718 + 0.14369848716947628 + 0.14370253853815637 + 0.14370659000281566 + 0.14371064156345786 + 0.14371469322008665 + 0.14371874497270587 + 0.14372279682131919 + 0.14372684876593034 + 0.14373090080654291 + 0.14373495294316094 + 0.143739005175788 + 0.14374305750442767 + 0.14374710992908371 + 0.1437511624497603 + 0.14375521506646055 + 0.14375926777918852 + 0.14376332058794775 + 0.14376737349274216 + 0.14377142649357547 + 0.14377547959045128 + 0.14377953278337333 + 0.1437835860723454 + 0.14378763945737122 + 0.14379169293845467 + 0.1437957465155992 + 0.14379980018880861 + 0.14380385395808684 + 0.14380790782343728 + 0.14381196178486372 + 0.14381601584237014 + 0.14382006999596034 + 0.14382412424563759 + 0.14382817859140606 + 0.14383223303326909 + 0.14383628757123085 + 0.1438403422052946 + 0.1438443969354645 + 0.14384845176174402 + 0.14385250668413688 + 0.14385656170264693 + 0.14386061681727783 + 0.14386467202803338 + 0.14386872733491726 + 0.14387278273793316 + 0.14387683823708494 + 0.14388089383237618 + 0.1438849495238107 + 0.14388900531139212 + 0.14389306119512438 + 0.14389711717501116 + 0.14390117325105611 + 0.14390522942326273 + 0.14390928569163522 + 0.14391334205617706 + 0.143917398516892 + 0.14392145507378382 + 0.14392551172685597 + 0.14392956847611274 + 0.1439336253215574 + 0.14393768226319387 + 0.1439417393010258 + 0.14394579643505709 + 0.14394985366529128 + 0.14395391099173194 + 0.14395796841438344 + 0.14396202593324872 + 0.14396608354833226 + 0.14397014125963717 + 0.14397419906716755 + 0.14397825697092712 + 0.14398231497091946 + 0.1439863730671482 + 0.14399043125961744 + 0.14399448954833063 + 0.1439985479332917 + 0.14400260641450413 + 0.1440066649919719 + 0.14401072366569859 + 0.14401478243568802 + 0.14401884130194392 + 0.14402290026446996 + 0.14402695932326995 + 0.14403101847834762 + 0.14403507772970653 + 0.14403913707735061 + 0.14404319652128364 + 0.14404725606150906 + 0.14405131569803098 + 0.14405537543085289 + 0.1440594352599785 + 0.14406349518541176 + 0.14406755520715636 + 0.14407161532521578 + 0.14407567553959408 + 0.14407973585029468 + 0.14408379625732162 + 0.14408785676067845 + 0.14409191736036908 + 0.14409597805639715 + 0.1441000388487661 + 0.14410409973748023 + 0.14410816072254282 + 0.14411222180395786 + 0.14411628298172888 + 0.14412034425585996 + 0.14412440562635451 + 0.14412846709321633 + 0.14413252865644918 + 0.14413659031605711 + 0.14414065207204324 + 0.14414471392441167 + 0.14414877587316619 + 0.14415283791831041 + 0.14415690005984816 + 0.14416096229778311 + 0.14416502463211892 + 0.14416908706285955 + 0.14417314959000857 + 0.14417721221356966 + 0.14418127493354682 + 0.14418533774994358 + 0.14418940066276364 + 0.14419346367201094 + 0.14419752677768924 + 0.14420158997980187 + 0.14420565327835302 + 0.14420971667334623 + 0.14421378016478512 + 0.14421784375267366 + 0.14422190743701571 + 0.14422597121781447 + 0.14423003509507432 + 0.14423409906879853 + 0.14423816313899104 + 0.1442422273056555 + 0.14424629156879593 + 0.14425035592841565 + 0.14425442038451852 + 0.14425848493710861 + 0.14426254958618925 + 0.14426661433176424 + 0.14427067917383757 + 0.14427474411241287 + 0.14427880914749383 + 0.14428287427908409 + 0.14428693950718749 + 0.14429100483180796 + 0.14429507025294899 + 0.14429913577061454 + 0.14430320138480793 + 0.14430726709553324 + 0.14431133290279435 + 0.14431539880659483 + 0.14431946480693827 + 0.14432353090382849 + 0.14432759709726942 + 0.14433166338726475 + 0.14433572977381795 + 0.14433979625693308 + 0.14434386283661363 + 0.14434792951286371 + 0.1443519962856866 + 0.14435606315508639 + 0.14436013012106666 + 0.14436419718363125 + 0.14436826434278394 + 0.14437233159852808 + 0.14437639895086807 + 0.14438046639980728 + 0.14438453394534928 + 0.14438860158749803 + 0.1443926693262573 + 0.14439673716163073 + 0.14440080509362216 + 0.14440487312223554 + 0.144408941247474 + 0.14441300946934207 + 0.14441707778784282 + 0.14442114620298022 + 0.14442521471475819 + 0.14442928332318017 + 0.14443335202825039 + 0.14443742082997207 + 0.1444414897283493 + 0.14444555872338552 + 0.14444962781508477 + 0.1444536970034507 + 0.14445776628848703 + 0.14446183567019744 + 0.14446590514858582 + 0.14446997472365566 + 0.14447404439541103 + 0.14447811416385559 + 0.14448218402899304 + 0.14448625399082682 + 0.14449032404936143 + 0.14449439420459986 + 0.14449846445654629 + 0.14450253480520442 + 0.14450660525057771 + 0.1445106757926703 + 0.14451474643148557 + 0.14451881716702761 + 0.14452288799929996 + 0.14452695892830641 + 0.14453102995405065 + 0.14453510107653647 + 0.14453917229576779 + 0.14454324361174828 + 0.1445473150244814 + 0.14455138653397109 + 0.14455545814022122 + 0.14455952984323561 + 0.1445636016430176 + 0.14456767353957123 + 0.14457174553290017 + 0.14457581762300831 + 0.1445798898098993 + 0.14458396209357668 + 0.14458803447404459 + 0.14459210695130659 + 0.14459617952536641 + 0.14460025219622782 + 0.14460432496389442 + 0.14460839782837034 + 0.14461247078965894 + 0.14461654384776423 + 0.14462061700268972 + 0.14462469025443939 + 0.14462876360301682 + 0.14463283704842611 + 0.14463691059067041 + 0.14464098422975405 + 0.14464505796568042 + 0.14464913179845335 + 0.1446532057280768 + 0.1446572797545542 + 0.1446613538778895 + 0.14466542809808636 + 0.1446695024151485 + 0.14467357682907994 + 0.14467765133988422 + 0.14468172594756495 + 0.14468580065212611 + 0.14468987545357151 + 0.14469395035190463 + 0.14469802534712931 + 0.14470210043924944 + 0.14470617562826868 + 0.14471025091419104 + 0.14471432629701969 + 0.14471840177675901 + 0.1447224773534124 + 0.14472655302698359 + 0.14473062879747647 + 0.14473470466489455 + 0.14473878062924198 + 0.14474285669052234 + 0.14474693284873924 + 0.14475100910389668 + 0.1447550854559983 + 0.14475916190504773 + 0.14476323845104885 + 0.14476731509400537 + 0.14477139183392135 + 0.14477546867079988 + 0.14477954560464532 + 0.14478362263546127 + 0.14478769976325123 + 0.14479177698801921 + 0.14479585430976913 + 0.14479993172850422 + 0.14480400924422854 + 0.1448080868569461 + 0.14481216456666021 + 0.14481624237337479 + 0.14482032027709368 + 0.14482439827782059 + 0.14482847637555921 + 0.14483255457031358 + 0.14483663286208692 + 0.1448407112508833 + 0.14484478973670667 + 0.14484886831956037 + 0.14485294699944859 + 0.14485702577637458 + 0.1448611046503426 + 0.14486518362135609 + 0.14486926268941916 + 0.14487334185453504 + 0.14487742111670776 + 0.14488150047594114 + 0.14488557993223894 + 0.14488965948560489 + 0.14489373913604262 + 0.14489781888355602 + 0.14490189872814874 + 0.1449059786698246 + 0.14491005870858742 + 0.14491413884444088 + 0.1449182190773888 + 0.14492229940743495 + 0.14492637983458281 + 0.14493046035883669 + 0.14493454098019981 + 0.14493862169867608 + 0.14494270251426961 + 0.14494678342698361 + 0.14495086443682212 + 0.14495494554378921 + 0.14495902674788783 + 0.14496310804912249 + 0.14496718944749665 + 0.14497127094301404 + 0.14497535253567873 + 0.14497943422549386 + 0.1449835160124639 + 0.14498759789659202 + 0.14499167987788231 + 0.14499576195633854 + 0.14499984413196432 + 0.14500392640476339 + 0.14500800877473974 + 0.14501209124189698 + 0.14501617380623882 + 0.14502025646776906 + 0.14502433922649161 + 0.14502842208240996 + 0.145032505035528 + 0.1450365880858496 + 0.14504067123337827 + 0.14504475447811802 + 0.14504883782007261 + 0.14505292125924563 + 0.14505700479564096 + 0.14506108842926241 + 0.14506517216011341 + 0.14506925598819834 + 0.14507333991352028 + 0.14507742393608342 + 0.14508150805589137 + 0.14508559227294798 + 0.14508967658725688 + 0.14509376099882215 + 0.14509784550764707 + 0.14510193011373571 + 0.14510601481709187 + 0.14511009961771923 + 0.14511418451562144 + 0.14511826951080239 + 0.14512235460326589 + 0.14512643979301557 + 0.14513052508005536 + 0.14513461046438886 + 0.14513869594601997 + 0.14514278152495216 + 0.14514686720118958 + 0.14515095297473593 + 0.14515503884559494 + 0.14515912481376997 + 0.14516321087926545 + 0.14516729704208484 + 0.14517138330223164 + 0.14517546965971009 + 0.14517955611452363 + 0.14518364266667616 + 0.14518772931617141 + 0.14519181606301315 + 0.14519590290720499 + 0.14519998984875104 + 0.14520407688765488 + 0.14520816402392026 + 0.14521225125755083 + 0.14521633858855076 + 0.14522042601692323 + 0.14522451354267246 + 0.14522860116580211 + 0.14523268888631594 + 0.14523677670421761 + 0.14524086461951108 + 0.14524495263219997 + 0.14524904074228795 + 0.14525312894977899 + 0.14525721725467672 + 0.14526130565698517 + 0.14526539415670781 + 0.14526948275384835 + 0.14527357144841091 + 0.14527766024039912 + 0.14528174912981665 + 0.14528583811666732 + 0.14528992720095479 + 0.14529401638268316 + 0.14529810566185572 + 0.14530219503847649 + 0.14530628451254932 + 0.14531037408407793 + 0.14531446375306598 + 0.14531855351951747 + 0.14532264338343587 + 0.14532673334482527 + 0.14533082340368911 + 0.14533491356003123 + 0.1453390038138557 + 0.145343094165166 + 0.14534718461396587 + 0.14535127516025931 + 0.1453553658040499 + 0.14535945654534152 + 0.14536354738413793 + 0.14536763832044278 + 0.14537172935425993 + 0.14537582048559308 + 0.1453799117144462 + 0.14538400304082288 + 0.14538809446472689 + 0.14539218598616227 + 0.14539627760513243 + 0.14540036932164127 + 0.14540446113569253 + 0.14540855304729011 + 0.14541264505643772 + 0.1454167371631391 + 0.14542082936739797 + 0.14542492166921808 + 0.14542901406860342 + 0.14543310656555766 + 0.14543719916008452 + 0.14544129185218782 + 0.14544538464187132 + 0.14544947752913859 + 0.14545357051399371 + 0.14545766359644044 + 0.1454617567764824 + 0.14546585005412327 + 0.14546994342936728 + 0.14547403690221775 + 0.14547813047267849 + 0.14548222414075329 + 0.14548631790644626 + 0.14549041176976088 + 0.14549450573070094 + 0.14549859978927024 + 0.14550269394547252 + 0.14550678819931162 + 0.14551088255079109 + 0.14551497699991511 + 0.14551907154668739 + 0.1455231661911113 + 0.14552726093319093 + 0.14553135577293017 + 0.14553545071033239 + 0.14553954574540184 + 0.14554364087814209 + 0.14554773610855659 + 0.1455518314366496 + 0.14555592686242472 + 0.14556002238588547 + 0.14556411800703606 + 0.14556821372588019 + 0.14557230954242137 + 0.14557640545666353 + 0.14558050146861043 + 0.14558459757826592 + 0.14558869378563372 + 0.1455927900907176 + 0.14559688649352132 + 0.14560098299404858 + 0.14560507959230337 + 0.1456091762882892 + 0.14561327308201011 + 0.14561736997346975 + 0.14562146696267209 + 0.14562556404962046 + 0.14562966123431911 + 0.14563375851677149 + 0.14563785589698147 + 0.14564195337495303 + 0.14564605095068978 + 0.14565014862419515 + 0.14565424639547353 + 0.14565834426452842 + 0.14566244223136365 + 0.14566654029598294 + 0.14567063845839004 + 0.14567473671858883 + 0.14567883507658308 + 0.14568293353237635 + 0.14568703208597283 + 0.14569113073737594 + 0.14569522948658967 + 0.14569932833361759 + 0.14570342727846369 + 0.14570752632113163 + 0.14571162546162514 + 0.14571572469994823 + 0.14571982403610445 + 0.14572392347009774 + 0.14572802300193183 + 0.14573212263161048 + 0.14573622235913719 + 0.14574032218451646 + 0.14574442210775135 + 0.1457485221288459 + 0.14575262224780403 + 0.14575672246462931 + 0.1457608227793257 + 0.14576492319189691 + 0.14576902370234668 + 0.14577312431067874 + 0.14577722501689702 + 0.14578132582100523 + 0.14578542672300709 + 0.14578952772290649 + 0.14579362882070709 + 0.14579773001641286 + 0.14580183131002747 + 0.14580593270155479 + 0.14581003419099842 + 0.14581413577836225 + 0.14581823746365014 + 0.14582233924686555 + 0.14582644112801271 + 0.14583054310709506 + 0.14583464518411668 + 0.14583874735908106 + 0.14584284963199209 + 0.14584695200285375 + 0.14585105447166954 + 0.14585515703844329 + 0.14585925970317887 + 0.14586336246588022 + 0.14586746532655082 + 0.14587156828519468 + 0.14587567134181534 + 0.14587977449641676 + 0.14588387774900263 + 0.14588798109957704 + 0.14589208454814334 + 0.14589618809470559 + 0.14590029173926747 + 0.14590439548183276 + 0.14590849932240524 + 0.14591260326098879 + 0.14591670729758727 + 0.14592081143220423 + 0.14592491566484353 + 0.14592901999550897 + 0.14593312442420422 + 0.14593722895093336 + 0.14594133357570008 + 0.14594543829850801 + 0.14594954311936109 + 0.145953648038263 + 0.14595775305521752 + 0.14596185817022866 + 0.14596596338329984 + 0.1459700686944351 + 0.14597417410363833 + 0.14597827961091284 + 0.14598238521626292 + 0.14598649091969218 + 0.14599059672120454 + 0.14599470262080333 + 0.14599880861849282 + 0.14600291471427651 + 0.14600702090815856 + 0.14601112720014231 + 0.1460152335902318 + 0.1460193400784307 + 0.14602344666474298 + 0.14602755334917217 + 0.14603166013172236 + 0.14603576701239707 + 0.14603987399120033 + 0.14604398106813568 + 0.146048088243207 + 0.14605219551641824 + 0.1460563028877728 + 0.14606041035727482 + 0.14606451792492822 + 0.1460686255907363 + 0.14607273335470339 + 0.14607684121683276 + 0.14608094917712855 + 0.14608505723559445 + 0.14608916539223415 + 0.14609327364705171 + 0.14609738200005054 + 0.14610149045123477 + 0.14610559900060802 + 0.14610970764817408 + 0.1461138163939367 + 0.14611792523790004 + 0.1461220341800675 + 0.14612614322044284 + 0.14613025235902991 + 0.14613436159583282 + 0.146138470930855 + 0.14614258036410049 + 0.14614668989557275 + 0.14615079952527588 + 0.14615490925321345 + 0.14615901907938963 + 0.14616312900380776 + 0.14616723902647188 + 0.14617134914738578 + 0.14617545936655302 + 0.14617956968397769 + 0.1461836800996632 + 0.14618779061361398 + 0.14619190122583339 + 0.14619601193632509 + 0.14620012274509314 + 0.14620423365214144 + 0.14620834465747348 + 0.14621245576109315 + 0.14621656696300428 + 0.1462206782632107 + 0.14622478966171604 + 0.14622890115852447 + 0.14623301275363915 + 0.14623712444706458 + 0.14624123623880411 + 0.14624534812886161 + 0.14624946011724105 + 0.14625357220394597 + 0.14625768438898032 + 0.14626179667234784 + 0.1462659090540524 + 0.14627002153409757 + 0.14627413411248746 + 0.14627824678922574 + 0.14628235956431621 + 0.14628647243776266 + 0.14629058540956866 + 0.1462946984797385 + 0.14629881164827557 + 0.14630292491518371 + 0.14630703828046687 + 0.14631115174412881 + 0.14631526530617334 + 0.14631937896660402 + 0.14632349272542489 + 0.14632760658263982 + 0.14633172053825227 + 0.14633583459226648 + 0.14633994874468575 + 0.14634406299551428 + 0.1463481773447558 + 0.14635229179241385 + 0.14635640633849259 + 0.14636052098299543 + 0.14636463572592651 + 0.14636875056728951 + 0.1463728655070882 + 0.14637698054532641 + 0.14638109568200797 + 0.14638521091713635 + 0.14638932625071605 + 0.14639344168274998 + 0.14639755721324293 + 0.14640167284219774 + 0.14640578856961886 + 0.14640990439550977 + 0.14641402031987449 + 0.14641813634271647 + 0.14642225246403992 + 0.14642636868384834 + 0.14643048500214578 + 0.1464346014189358 + 0.14643871793422231 + 0.14644283454800935 + 0.14644695126030011 + 0.14645106807109895 + 0.14645518498040946 + 0.14645930198823554 + 0.14646341909458091 + 0.1464675362994492 + 0.14647165360284453 + 0.14647577100477049 + 0.146479888505231 + 0.14648400610422976 + 0.14648812380177059 + 0.14649224159785748 + 0.1464963594924939 + 0.1465004774856839 + 0.14650459557743115 + 0.14650871376773955 + 0.14651283205661275 + 0.14651695044405463 + 0.14652106893006922 + 0.14652518751466018 + 0.14652930619783106 + 0.14653342497958607 + 0.14653754385992851 + 0.14654166283886252 + 0.146545781916392 + 0.14654990109252078 + 0.14655402036725212 + 0.14655813974059051 + 0.14656225921253929 + 0.14656637878310241 + 0.1465704984522837 + 0.1465746182200868 + 0.14657873808651578 + 0.14658285805157442 + 0.14658697811526633 + 0.14659109827759534 + 0.14659521853856558 + 0.14659933889818028 + 0.14660345935644378 + 0.14660757991335963 + 0.1466117005689315 + 0.1466158213231635 + 0.14661994217605936 + 0.14662406312762261 + 0.14662818417785761 + 0.14663230532676766 + 0.14663642657435677 + 0.14664054792062861 + 0.14664466936558709 + 0.14664879090923608 + 0.14665291255157928 + 0.14665703429262061 + 0.14666115613236375 + 0.1466652780708125 + 0.14666940010797075 + 0.1466735222438422 + 0.14667764447843101 + 0.14668176681174039 + 0.14668588924377465 + 0.14669001177453739 + 0.14669413440403234 + 0.14669825713226356 + 0.14670237995923463 + 0.14670650288494955 + 0.14671062590941172 + 0.14671474903262549 + 0.14671887225459415 + 0.14672299557532209 + 0.14672711899481278 + 0.1467312425130701 + 0.14673536613009744 + 0.14673948984589924 + 0.146743613660479 + 0.14674773757384066 + 0.14675186158598785 + 0.14675598569692455 + 0.14676010990665433 + 0.14676423421518128 + 0.146768358622509 + 0.1467724831286415 + 0.14677660773358242 + 0.14678073243733578 + 0.14678485723990514 + 0.14678898214129429 + 0.14679310714150728 + 0.14679723224054772 + 0.14680135743841957 + 0.14680548273512634 + 0.14680960813067226 + 0.14681373362506106 + 0.14681785921829635 + 0.14682198491038187 + 0.14682611070132184 + 0.14683023659111971 + 0.14683436257977933 + 0.1468384886673047 + 0.14684261485369945 + 0.14684674113896745 + 0.14685086752311269 + 0.14685499400613855 + 0.1468591205880492 + 0.14686324726884839 + 0.14686737404853983 + 0.14687150092712747 + 0.14687562790461509 + 0.14687975498100633 + 0.14688388215630513 + 0.14688800943051539 + 0.14689213680364072 + 0.1468962642756852 + 0.14690039184665243 + 0.14690451951654629 + 0.14690864728537059 + 0.14691277515312903 + 0.14691690311982589 + 0.14692103118546432 + 0.14692515935004849 + 0.14692928761358229 + 0.14693341597606915 + 0.14693754443751342 + 0.14694167299791849 + 0.14694580165728827 + 0.14694993041562679 + 0.14695405927293781 + 0.14695818822922477 + 0.14696231728449177 + 0.1469664464387426 + 0.14697057569198121 + 0.14697470504421131 + 0.14697883449543656 + 0.14698296404566097 + 0.14698709369488822 + 0.14699122344312232 + 0.14699535329036695 + 0.14699948323662576 + 0.14700361328190281 + 0.14700774342620201 + 0.14701187366952687 + 0.14701600401188139 + 0.14702013445326936 + 0.14702426499369461 + 0.14702839563316075 + 0.14703252637167211 + 0.14703665720923176 + 0.14704078814584429 + 0.14704491918151305 + 0.14704905031624196 + 0.14705318155003483 + 0.14705731288289556 + 0.14706144431482771 + 0.14706557584583543 + 0.14706970747592218 + 0.14707383920509215 + 0.14707797103334913 + 0.14708210296069657 + 0.14708623498713869 + 0.14709036711267906 + 0.14709449933732155 + 0.14709863166107012 + 0.14710276408392831 + 0.14710689660590015 + 0.14711102922698943 + 0.14711516194720006 + 0.14711929476653574 + 0.14712342768500031 + 0.14712756070259739 + 0.14713169381933111 + 0.14713582703520522 + 0.14713996035022339 + 0.14714409376438964 + 0.14714822727770768 + 0.14715236089018127 + 0.14715649460181432 + 0.14716062841261057 + 0.14716476232257392 + 0.14716889633170829 + 0.14717303044001728 + 0.14717716464750485 + 0.14718129895417473 + 0.14718543336003084 + 0.14718956786507675 + 0.14719370246931673 + 0.14719783717275428 + 0.14720197197539325 + 0.14720610687723765 + 0.14721024187829104 + 0.14721437697855735 + 0.14721851217804052 + 0.14722264747674413 + 0.14722678287467222 + 0.14723091837182842 + 0.14723505396821687 + 0.14723918966384103 + 0.14724332545870492 + 0.14724746135281228 + 0.14725159734616697 + 0.14725573343877291 + 0.14725986963063378 + 0.14726400592175334 + 0.14726814231213561 + 0.14727227880178417 + 0.14727641539070321 + 0.14728055207889643 + 0.14728468886636731 + 0.14728882575312011 + 0.14729296273915829 + 0.14729709982448599 + 0.14730123700910699 + 0.1473053742930249 + 0.14730951167624373 + 0.14731364915876721 + 0.14731778674059923 + 0.14732192442174344 + 0.14732606220220398 + 0.14733020008198433 + 0.14733433806108867 + 0.14733847613952053 + 0.14734261431728393 + 0.14734675259438271 + 0.14735089097082041 + 0.14735502944660106 + 0.14735916802172866 + 0.14736330669620668 + 0.14736744547003905 + 0.14737158434322978 + 0.14737572331578261 + 0.14737986238770129 + 0.14738400155898984 + 0.14738814082965168 + 0.14739228019969089 + 0.14739641966911138 + 0.14740055923791712 + 0.14740469890611149 + 0.14740883867369858 + 0.14741297854068208 + 0.1474171185070661 + 0.14742125857285407 + 0.14742539873805019 + 0.14742953900265796 + 0.14743367936668172 + 0.14743781983012463 + 0.1474419603929909 + 0.14744610105528438 + 0.14745024181700883 + 0.14745438267816793 + 0.14745852363876574 + 0.1474626646988059 + 0.14746680585829247 + 0.1474709471172293 + 0.14747508847561963 + 0.14747922993346804 + 0.14748337149077781 + 0.14748751314755332 + 0.1474916549037977 + 0.14749579675951538 + 0.14749993871471015 + 0.14750408076938532 + 0.14750822292354515 + 0.14751236517719352 + 0.14751650753033405 + 0.14752064998297043 + 0.147524792535107 + 0.14752893518674706 + 0.14753307793789486 + 0.14753722078855405 + 0.14754136373872823 + 0.14754550678842168 + 0.14754964993763781 + 0.14755379318638082 + 0.14755793653465418 + 0.1475620799824621 + 0.14756622352980814 + 0.14757036717669608 + 0.14757451092313009 + 0.14757865476911372 + 0.14758279871465083 + 0.14758694275974538 + 0.14759108690440106 + 0.1475952311486218 + 0.14759937549241151 + 0.14760351993577367 + 0.14760766447871235 + 0.14761180912123159 + 0.14761595386333504 + 0.1476200987050264 + 0.14762424364630963 + 0.14762838868718842 + 0.14763253382766686 + 0.14763667906774858 + 0.1476408244074377 + 0.14764496984673764 + 0.14764911538565231 + 0.14765326102418594 + 0.14765740676234188 + 0.14766155260012445 + 0.14766569853753708 + 0.14766984457458374 + 0.14767399071126827 + 0.14767813694759449 + 0.14768228328356631 + 0.14768642971918716 + 0.14769057625446153 + 0.14769472288939295 + 0.14769886962398529 + 0.14770301645824221 + 0.14770716339216763 + 0.14771131042576546 + 0.14771545755903942 + 0.14771960479199378 + 0.14772375212463165 + 0.14772789955695742 + 0.1477320470889748 + 0.14773619472068747 + 0.14774034245209935 + 0.14774449028321446 + 0.14774863821403619 + 0.14775278624456911 + 0.14775693437481621 + 0.14776108260478185 + 0.1477652309344698 + 0.14776937936388368 + 0.14777352789302783 + 0.14777767652190554 + 0.14778182525052075 + 0.1477859740788775 + 0.14779012300697952 + 0.1477942720348307 + 0.14779842116243494 + 0.14780257038979566 + 0.14780671971691722 + 0.14781086914380337 + 0.14781501867045752 + 0.14781916829688416 + 0.14782331802308665 + 0.14782746784906889 + 0.14783161777483483 + 0.14783576780038832 + 0.14783991792573317 + 0.14784406815087311 + 0.14784821847581214 + 0.14785236890055406 + 0.14785651942510269 + 0.14786067004946199 + 0.14786482077363547 + 0.14786897159762724 + 0.14787312252144119 + 0.1478772735450809 + 0.14788142466855025 + 0.14788557589185347 + 0.14788972721499399 + 0.1478938786379756 + 0.14789803016080255 + 0.14790218178347839 + 0.14790633350600704 + 0.14791048532839227 + 0.147914637250638 + 0.14791878927274818 + 0.14792294139472628 + 0.1479270936165766 + 0.14793124593830262 + 0.14793539835990829 + 0.1479395508813976 + 0.14794370350277439 + 0.14794785622404216 + 0.14795200904520511 + 0.14795616196626687 + 0.14796031498723147 + 0.14796446810810268 + 0.14796862132888419 + 0.14797277464958011 + 0.14797692807019397 + 0.14798108159072998 + 0.14798523521119167 + 0.14798938893158306 + 0.14799354275190787 + 0.14799769667216997 + 0.14800185069237326 + 0.14800600481252166 + 0.14801015903261883 + 0.14801431335266887 + 0.14801846777267544 + 0.14802262229264235 + 0.1480267769125734 + 0.14803093163247283 + 0.1480350864523437 + 0.14803924137219077 + 0.14804339639201736 + 0.14804755151182725 + 0.14805170673162477 + 0.14805586205141322 + 0.14806001747119663 + 0.14806417299097899 + 0.14806832861076405 + 0.14807248433055575 + 0.1480766401503576 + 0.14808079607017383 + 0.14808495209000816 + 0.14808910820986435 + 0.1480932644297463 + 0.14809742074965798 + 0.14810157716960318 + 0.1481057336895856 + 0.148109890309609 + 0.1481140470296777 + 0.1481182038497949 + 0.14812236076996521 + 0.14812651779019187 + 0.14813067491047893 + 0.14813483213083034 + 0.1481389894512497 + 0.14814314687174107 + 0.1481473043923083 + 0.14815146201295512 + 0.14815561973368538 + 0.14815977755450288 + 0.14816393547541171 + 0.14816809349641566 + 0.14817225161751829 + 0.14817640983872368 + 0.14818056816003583 + 0.14818472658145823 + 0.1481888851029951 + 0.14819304372464986 + 0.14819720244642684 + 0.14820136126832945 + 0.14820552019036187 + 0.14820967921252773 + 0.14821383833483098 + 0.14821799755727563 + 0.14822215687986512 + 0.14822631630260355 + 0.14823047582549492 + 0.14823463544854282 + 0.14823879517175131 + 0.1482429549951241 + 0.14824711491866488 + 0.1482512749423778 + 0.14825543506626671 + 0.14825959529033542 + 0.14826375561458746 + 0.14826791603902711 + 0.14827207656365807 + 0.14827623718848393 + 0.14828039791350911 + 0.14828455873873694 + 0.14828871966417176 + 0.14829288068981678 + 0.14829704181567635 + 0.14830120304175412 + 0.14830536436805403 + 0.14830952579457982 + 0.14831368732133565 + 0.14831784894832492 + 0.14832201067555173 + 0.1483261725030201 + 0.14833033443073368 + 0.14833449645869606 + 0.1483386585869117 + 0.14834282081538394 + 0.14834698314411687 + 0.14835114557311446 + 0.14835530810238018 + 0.14835947073191827 + 0.14836363346173234 + 0.14836779629182628 + 0.14837195922220398 + 0.14837612225286942 + 0.14838028538382617 + 0.14838444861507846 + 0.14838861194662989 + 0.14839277537848433 + 0.14839693891064554 + 0.1484011025431177 + 0.14840526627590442 + 0.14840943010900967 + 0.14841359404243709 + 0.14841775807619073 + 0.1484219222102745 + 0.14842608644469205 + 0.14843025077944744 + 0.14843441521454429 + 0.1484385797499867 + 0.14844274438577842 + 0.1484469091219234 + 0.1484510739584253 + 0.14845523889528831 + 0.14845940393251578 + 0.14846356907011199 + 0.14846773430808066 + 0.14847189964642557 + 0.14847606508515065 + 0.14848023062425977 + 0.14848439626375701 + 0.14848856200364571 + 0.14849272784393011 + 0.148496893784614 + 0.14850105982570111 + 0.14850522596719562 + 0.14850939220910081 + 0.14851355855142115 + 0.14851772499416044 + 0.14852189153732204 + 0.14852605818091016 + 0.14853022492492873 + 0.14853439176938146 + 0.14853855871427224 + 0.14854272575960473 + 0.14854689290538331 + 0.14855106015161149 + 0.14855522749829297 + 0.14855939494543191 + 0.14856356249303201 + 0.1485677301410972 + 0.1485718978896314 + 0.1485760657386383 + 0.14858023368812184 + 0.14858440173808607 + 0.1485885698885345 + 0.14859273813947124 + 0.1485969064909001 + 0.14860107494282496 + 0.14860524349524953 + 0.14860941214817772 + 0.14861358090161367 + 0.14861774975556086 + 0.14862191871002337 + 0.14862608776500499 + 0.1486302569205096 + 0.14863442617654118 + 0.14863859553310341 + 0.14864276499020015 + 0.14864693454783545 + 0.14865110420601296 + 0.14865527396473652 + 0.14865944382401047 + 0.14866361378383802 + 0.14866778384422333 + 0.1486719540051703 + 0.14867612426668267 + 0.14868029462876461 + 0.14868446509141964 + 0.14868863565465174 + 0.14869280631846482 + 0.1486969770828627 + 0.14870114794784911 + 0.14870531891342825 + 0.14870948997960373 + 0.14871366114637946 + 0.14871783241375935 + 0.1487220037817471 + 0.14872617525034681 + 0.14873034681956213 + 0.14873451848939712 + 0.14873869025985545 + 0.14874286213094132 + 0.1487470341026583 + 0.14875120617501028 + 0.14875537834800109 + 0.14875955062163462 + 0.148763722995915 + 0.14876789547084576 + 0.14877206804643101 + 0.14877624072267448 + 0.14878041349957979 + 0.14878458637715139 + 0.14878875935539293 + 0.1487929324343078 + 0.14879710561390039 + 0.14880127889417455 + 0.14880545227513395 + 0.14880962575678255 + 0.14881379933912417 + 0.14881797302216271 + 0.14882214680590178 + 0.14882632069034593 + 0.14883049467549825 + 0.14883466876136317 + 0.14883884294794422 + 0.14884301723524537 + 0.14884719162327056 + 0.14885136611202363 + 0.14885554070150842 + 0.1488597153917289 + 0.14886389018268864 + 0.14886806507439171 + 0.14887224006684222 + 0.14887641516004363 + 0.14888059035399992 + 0.14888476564871511 + 0.14888894104419287 + 0.14889311654043733 + 0.14889729213745226 + 0.14890146783524127 + 0.14890564363380865 + 0.14890981953315791 + 0.14891399553329299 + 0.14891817163421803 + 0.14892234783593655 + 0.14892652413845281 + 0.14893070054177018 + 0.14893487704589306 + 0.14893905365082477 + 0.14894323035656973 + 0.14894740716313154 + 0.1489515840705137 + 0.1489557610787208 + 0.14895993818775649 + 0.14896411539762419 + 0.14896829270832834 + 0.14897247011987264 + 0.14897664763226073 + 0.14898082524549677 + 0.14898500295958453 + 0.14898918077452775 + 0.14899335869033059 + 0.14899753670699681 + 0.14900171482453001 + 0.14900589304293455 + 0.14901007136221359 + 0.14901424978237168 + 0.14901842830341272 + 0.14902260692534014 + 0.14902678564815811 + 0.14903096447187014 + 0.14903514339648039 + 0.14903932242199286 + 0.14904350154841126 + 0.14904768077573954 + 0.14905186010398133 + 0.1490560395331407 + 0.14906021906322162 + 0.14906439869422783 + 0.14906857842616317 + 0.1490727582590316 + 0.14907693819283679 + 0.14908111822758308 + 0.14908529836327389 + 0.14908947859991342 + 0.14909365893750523 + 0.14909783937605325 + 0.14910201991556152 + 0.14910620055603407 + 0.14911038129747428 + 0.1491145621398865 + 0.14911874308327441 + 0.1491229241276418 + 0.14912710527299264 + 0.14913128651933069 + 0.14913546786666029 + 0.14913964931498461 + 0.14914383086430802 + 0.14914801251463436 + 0.14915219426596729 + 0.14915637611831079 + 0.14916055807166875 + 0.14916474012604522 + 0.14916892228144363 + 0.14917310453786831 + 0.14917728689532297 + 0.14918146935381149 + 0.14918565191333769 + 0.1491898345739055 + 0.14919401733551876 + 0.14919820019818125 + 0.1492023831618973 + 0.14920656622667028 + 0.14921074939250431 + 0.14921493265940308 + 0.1492191160273709 + 0.14922329949641117 + 0.14922748306652797 + 0.14923166673772523 + 0.1492358505100066 + 0.14924003438337632 + 0.1492442183578381 + 0.1492484024333956 + 0.14925258661005303 + 0.14925677088781425 + 0.14926095526668279 + 0.14926513974666297 + 0.14926932432775822 + 0.14927350900997291 + 0.14927769379331049 + 0.14928187867777526 + 0.14928606366337074 + 0.14929024875010097 + 0.14929443393796971 + 0.14929861922698101 + 0.14930280461713863 + 0.14930699010844659 + 0.14931117570090854 + 0.14931536139452889 + 0.14931954718931073 + 0.14932373308525856 + 0.14932791908237589 + 0.14933210518066678 + 0.14933629138013521 + 0.14934047768078504 + 0.1493446640826199 + 0.14934885058564384 + 0.14935303718986082 + 0.1493572238952745 + 0.14936141070188907 + 0.14936559760970791 + 0.14936978461873562 + 0.14937397172897568 + 0.14937815894043185 + 0.1493823462531082 + 0.14938653366700866 + 0.14939072118213698 + 0.14939490879849696 + 0.14939909651609279 + 0.14940328433492805 + 0.14940747225500697 + 0.14941166027633329 + 0.14941584839891053 + 0.14942003662274303 + 0.14942422494783444 + 0.14942841337418875 + 0.14943260190180988 + 0.14943679053070158 + 0.1494409792608678 + 0.14944516809231245 + 0.14944935702503964 + 0.14945354605905264 + 0.14945773519435607 + 0.14946192443095316 + 0.14946611376884819 + 0.14947030320804514 + 0.14947449274854749 + 0.14947868239035958 + 0.14948287213348482 + 0.14948706197792752 + 0.14949125192369131 + 0.14949544197078016 + 0.14949963211919792 + 0.14950382236894844 + 0.14950801272003594 + 0.14951220317246383 + 0.14951639372623643 + 0.14952058438135721 + 0.14952477513783027 + 0.14952896599565951 + 0.14953315695484876 + 0.14953734801540206 + 0.14954153917732324 + 0.149545730440616 + 0.14954992180528445 + 0.14955411327133247 + 0.14955830483876364 + 0.14956249650758219 + 0.14956668827779177 + 0.14957088014939685 + 0.14957507212240043 + 0.14957926419680692 + 0.14958345637262019 + 0.14958764864984408 + 0.1495918410284825 + 0.14959603350853923 + 0.14960022609001819 + 0.14960441877292344 + 0.14960861155725874 + 0.14961280444302794 + 0.1496169974302351 + 0.14962119051888395 + 0.14962538370897832 + 0.14962957700052221 + 0.14963377039351958 + 0.14963796388797435 + 0.14964215748389015 + 0.14964635118127098 + 0.14965054498012087 + 0.1496547388804437 + 0.14965893288224327 + 0.1496631269855235 + 0.14966732119028811 + 0.14967151549654134 + 0.14967570990428683 + 0.14967990441352869 + 0.14968409902427035 + 0.14968829373651626 + 0.14969248855026995 + 0.14969668346553566 + 0.14970087848231683 + 0.14970507360061755 + 0.14970926882044186 + 0.14971346414179351 + 0.14971765956467636 + 0.14972185508909439 + 0.14972605071505146 + 0.1497302464425517 + 0.14973444227159849 + 0.14973863820219616 + 0.14974283423434839 + 0.14974703036805917 + 0.14975122660333237 + 0.14975542294017183 + 0.14975961937858157 + 0.14976381591856536 + 0.14976801256012717 + 0.14977220930327087 + 0.14977640614800042 + 0.14978060309431956 + 0.14978480014223233 + 0.1497889972917425 + 0.1497931945428542 + 0.14979739189557101 + 0.14980158934989707 + 0.14980578690583612 + 0.1498099845633922 + 0.14981418232256907 + 0.14981838018337071 + 0.14982257814580111 + 0.14982677620986409 + 0.14983097437556328 + 0.1498351726429028 + 0.14983937101188682 + 0.14984356948251873 + 0.14984776805480279 + 0.14985196672874276 + 0.14985616550434258 + 0.14986036438160596 + 0.14986456336053719 + 0.14986876244113992 + 0.1498729616234179 + 0.14987716090737546 + 0.14988136029301602 + 0.1498855597803439 + 0.14988975936936258 + 0.14989395906007624 + 0.14989815885248875 + 0.14990235874660393 + 0.1499065587424257 + 0.14991075883995822 + 0.14991495903920476 + 0.14991915934016986 + 0.14992335974285728 + 0.14992756024727052 + 0.14993176085341392 + 0.14993596156129135 + 0.14994016237090646 + 0.14994436328226315 + 0.14994856429536557 + 0.14995276541021765 + 0.14995696662682301 + 0.14996116794518566 + 0.14996536936530958 + 0.14996957088719864 + 0.1499737725108567 + 0.14997797423628759 + 0.14998217606349545 + 0.14998637799248393 + 0.14999058002325727 + 0.14999478215581885 + 0.14999898439017301 + 0.15000318672632346 + 0.15000738916427411 + 0.150011591704029 + 0.15001579434559176 + 0.15001999708896654 + 0.15002419993415717 + 0.15002840288116762 + 0.15003260593000156 + 0.15003680908066336 + 0.15004101233315625 + 0.1500452156874848 + 0.1500494191436525 + 0.15005362270166347 + 0.15005782636152143 + 0.15006203012323019 + 0.15006623398679422 + 0.15007043795221661 + 0.15007464201950202 + 0.15007884618865394 + 0.15008305045967621 + 0.15008725483257321 + 0.1500914593073481 + 0.15009566388400561 + 0.150099868562549 + 0.15010407334298245 + 0.15010827822530989 + 0.15011248320953521 + 0.15011668829566208 + 0.15012089348369467 + 0.15012509877363692 + 0.15012930416549269 + 0.15013350965926542 + 0.15013771525495981 + 0.15014192095257928 + 0.15014612675212791 + 0.15015033265360947 + 0.15015453865702794 + 0.15015874476238714 + 0.15016295096969096 + 0.1501671572789437 + 0.15017136369014886 + 0.1501755702033104 + 0.15017977681843217 + 0.15018398353551843 + 0.15018819035457281 + 0.15019239727559902 + 0.1501966042986014 + 0.15020081142358366 + 0.15020501865054964 + 0.15020922597950326 + 0.15021343341044879 + 0.15021764094338944 + 0.15022184857832979 + 0.15022605631527339 + 0.15023026415422422 + 0.15023447209518631 + 0.1502386801381633 + 0.15024288828315932 + 0.15024709653017818 + 0.15025130487922389 + 0.15025551333030041 + 0.15025972188341133 + 0.15026393053856085 + 0.15026813929575283 + 0.15027234815499108 + 0.15027655711627974 + 0.15028076617962235 + 0.15028497534502316 + 0.15028918461248586 + 0.15029339398201452 + 0.15029760345361301 + 0.15030181302728504 + 0.15030602270303484 + 0.15031023248086622 + 0.15031444236078303 + 0.15031865234278921 + 0.15032286242688855 + 0.15032707261308531 + 0.15033128290138303 + 0.15033549329178567 + 0.1503397037842972 + 0.15034391437892167 + 0.15034812507566306 + 0.15035233587452485 + 0.15035654677551127 + 0.15036075777862612 + 0.15036496888387349 + 0.15036918009125713 + 0.1503733914007811 + 0.15037760281244894 + 0.15038181432626518 + 0.15038602594223305 + 0.15039023766035692 + 0.15039444948064071 + 0.15039866140308805 + 0.15040287342770314 + 0.15040708555448951 + 0.15041129778345155 + 0.15041551011459303 + 0.15041972254791777 + 0.15042393508342961 + 0.15042814772113236 + 0.15043236046103042 + 0.15043657330312743 + 0.15044078624742704 + 0.15044499929393351 + 0.15044921244265089 + 0.15045342569358275 + 0.15045763904673284 + 0.15046185250210578 + 0.15046606605970489 + 0.15047027971953414 + 0.1504744934815978 + 0.15047870734589941 + 0.15048292131244315 + 0.15048713538123265 + 0.15049134955227214 + 0.15049556382556545 + 0.15049977820111618 + 0.15050399267892867 + 0.15050820725900682 + 0.15051242194135436 + 0.15051663672597498 + 0.15052085161287307 + 0.15052506660205234 + 0.15052928169351668 + 0.15053349688727016 + 0.15053771218331655 + 0.1505419275816596 + 0.15054614308230355 + 0.15055035868525235 + 0.15055457439050943 + 0.15055879019807938 + 0.15056300610796558 + 0.15056722212017226 + 0.15057143823470312 + 0.15057565445156226 + 0.15057987077075358 + 0.1505840871922807 + 0.15058830371614818 + 0.15059252034235923 + 0.15059673707091828 + 0.1506009539018289 + 0.15060517083509528 + 0.1506093878707212 + 0.15061360500871057 + 0.15061782224906745 + 0.15062203959179565 + 0.15062625703689908 + 0.15063047458438172 + 0.1506346922342473 + 0.15063890998650006 + 0.15064312784114361 + 0.15064734579818218 + 0.15065156385761949 + 0.15065578201945939 + 0.15066000028370607 + 0.15066421865036317 + 0.15066843711943467 + 0.15067265569092461 + 0.15067687436483707 + 0.1506810931411755 + 0.15068531201994423 + 0.15068953100114713 + 0.15069375008478797 + 0.15069796927087048 + 0.15070218855939899 + 0.15070640795037737 + 0.15071062744380939 + 0.15071484703969923 + 0.15071906673805024 + 0.15072328653886694 + 0.15072750644215302 + 0.15073172644791236 + 0.15073594655614889 + 0.15074016676686677 + 0.15074438708006946 + 0.15074860749576147 + 0.15075282801394616 + 0.15075704863462791 + 0.15076126935781051 + 0.1507654901834975 + 0.15076971111169329 + 0.15077393214240162 + 0.15077815327562655 + 0.15078237451137178 + 0.15078659584964149 + 0.15079081729043908 + 0.15079503883376921 + 0.15079926047963538 + 0.15080348222804166 + 0.1508077040789918 + 0.15081192603248988 + 0.15081614808853985 + 0.15082037024714531 + 0.15082459250831065 + 0.15082881487203964 + 0.15083303733833614 + 0.15083725990720409 + 0.1508414825786473 + 0.15084570535266983 + 0.15084992822927579 + 0.15085415120846876 + 0.15085837429025273 + 0.15086259747463202 + 0.15086682076161009 + 0.1508710441511911 + 0.15087526764337872 + 0.1508794912381772 + 0.15088371493559036 + 0.15088793873562206 + 0.15089216263827657 + 0.1508963866435572 + 0.15090061075146827 + 0.15090483496201368 + 0.1509090592751974 + 0.150913283691023 + 0.15091750820949507 + 0.15092173283061691 + 0.15092595755439289 + 0.15093018238082673 + 0.15093440730992222 + 0.15093863234168373 + 0.15094285747611469 + 0.1509470827132193 + 0.1509513080530013 + 0.15095553349546501 + 0.15095975904061415 + 0.1509639846884524 + 0.15096821043898404 + 0.15097243629221285 + 0.15097666224814274 + 0.15098088830677769 + 0.15098511446812182 + 0.15098934073217857 + 0.15099356709895245 + 0.15099779356844692 + 0.15100202014066619 + 0.15100624681561423 + 0.15101047359329467 + 0.15101470047371165 + 0.1510189274568691 + 0.15102315454277085 + 0.15102738173142105 + 0.15103160902282339 + 0.15103583641698182 + 0.15104006391390049 + 0.15104429151358337 + 0.15104851921603404 + 0.15105274702125659 + 0.15105697492925499 + 0.15106120294003331 + 0.15106543105359538 + 0.15106965926994489 + 0.15107388758908591 + 0.15107811601102258 + 0.15108234453575875 + 0.15108657316329835 + 0.15109080189364515 + 0.15109503072680319 + 0.1510992596627766 + 0.15110348870156887 + 0.15110771784318433 + 0.1511119470876269 + 0.15111617643490005 + 0.1511204058850083 + 0.15112463543795548 + 0.15112886509374535 + 0.15113309485238172 + 0.15113732471386881 + 0.15114155467821044 + 0.15114578474541063 + 0.15115001491547314 + 0.15115424518840206 + 0.15115847556420134 + 0.15116270604287466 + 0.15116693662442629 + 0.15117116730886002 + 0.1511753980961798 + 0.15117962898638945 + 0.15118385997949313 + 0.15118809107549455 + 0.15119232227439786 + 0.15119655357620687 + 0.15120078498092562 + 0.15120501648855797 + 0.15120924809910777 + 0.15121347981257918 + 0.15121771162897585 + 0.15122194354830201 + 0.15122617557056151 + 0.15123040769575816 + 0.15123463992389596 + 0.15123887225497895 + 0.15124310468901098 + 0.15124733722599593 + 0.15125156986593796 + 0.15125580260884069 + 0.15126003545470834 + 0.15126426840354493 + 0.15126850145535389 + 0.15127273461013965 + 0.15127696786790595 + 0.15128120122865688 + 0.15128543469239622 + 0.15128966825912793 + 0.15129390192885597 + 0.15129813570158435 + 0.15130236957731685 + 0.15130660355605755 + 0.15131083763781045 + 0.15131507182257931 + 0.1513193061103682 + 0.15132354050118099 + 0.1513277749950217 + 0.15133200959189427 + 0.15133624429180245 + 0.15134047909475037 + 0.15134471400074193 + 0.1513489490097811 + 0.15135318412187188 + 0.15135741933701816 + 0.15136165465522355 + 0.15136589007649262 + 0.15137012560082885 + 0.15137436122823641 + 0.15137859695871905 + 0.1513828327922809 + 0.15138706872892591 + 0.15139130476865756 + 0.15139554091148047 + 0.15139977715739841 + 0.15140401350641508 + 0.15140824995853447 + 0.1514124865137608 + 0.15141672317209742 + 0.15142095993354907 + 0.15142519679811905 + 0.15142943376581172 + 0.15143367083663084 + 0.1514379080105803 + 0.15144214528766417 + 0.15144638266788618 + 0.15145062015125058 + 0.15145485773776118 + 0.15145909542742186 + 0.15146333322023664 + 0.15146757111620951 + 0.15147180911534427 + 0.15147604721764499 + 0.15148028542311559 + 0.15148452373175988 + 0.15148876214358223 + 0.15149300065858612 + 0.15149723927677558 + 0.15150147799815486 + 0.15150571682272748 + 0.15150995575049783 + 0.15151419478146946 + 0.15151843391564648 + 0.151522673153033 + 0.15152691249363251 + 0.15153115193744945 + 0.15153539148448761 + 0.15153963113475083 + 0.15154387088824325 + 0.15154811074496866 + 0.15155235070493098 + 0.15155659076813441 + 0.15156083093458259 + 0.1515650712042797 + 0.15156931157722942 + 0.15157355205343589 + 0.15157779263290322 + 0.15158203331563494 + 0.15158627410163547 + 0.15159051499090836 + 0.15159475598345784 + 0.15159899707928759 + 0.15160323827840191 + 0.15160747958080442 + 0.15161172098649917 + 0.15161596249549025 + 0.15162020410778165 + 0.15162444582337714 + 0.15162868764228055 + 0.15163292956449595 + 0.1516371715900274 + 0.15164141371887904 + 0.15164565595105428 + 0.15164989828655745 + 0.15165414072539246 + 0.15165838326756315 + 0.15166262591307353 + 0.15166686866192763 + 0.15167111151412932 + 0.1516753544696825 + 0.15167959752859114 + 0.15168384069085941 + 0.15168808395649097 + 0.1516923273254901 + 0.15169657079786025 + 0.15170081437360586 + 0.15170505805273063 + 0.15170930183523867 + 0.15171354572113377 + 0.15171778971041983 + 0.15172203380310115 + 0.15172627799918151 + 0.15173052229866454 + 0.15173476670155481 + 0.1517390112078556 + 0.15174325581757148 + 0.15174750053070604 + 0.15175174534726324 + 0.15175599026724718 + 0.15176023529066171 + 0.15176448041751098 + 0.15176872564779864 + 0.15177297098152881 + 0.15177721641870545 + 0.15178146195933256 + 0.15178570760341403 + 0.15178995335095383 + 0.15179419920195567 + 0.15179844515642407 + 0.15180269121436249 + 0.15180693737577511 + 0.1518111836406659 + 0.15181543000903863 + 0.15181967648089739 + 0.15182392305624612 + 0.15182816973508895 + 0.15183241651742965 + 0.15183666340327209 + 0.15184091039262027 + 0.15184515748547825 + 0.15184940468185015 + 0.15185365198173953 + 0.15185789938515057 + 0.1518621468920871 + 0.15186639450255346 + 0.15187064221655319 + 0.15187489003409038 + 0.15187913795516908 + 0.15188338597979309 + 0.15188763410796643 + 0.15189188233969314 + 0.15189613067497704 + 0.15190037911382223 + 0.15190462765623258 + 0.15190887630221214 + 0.15191312505176477 + 0.15191737390489438 + 0.15192162286160504 + 0.15192587192190091 + 0.15193012108578538 + 0.1519343703532629 + 0.15193861972433748 + 0.15194286919901265 + 0.15194711877729269 + 0.15195136845918136 + 0.15195561824468284 + 0.151959868133801 + 0.15196411812653998 + 0.15196836822290319 + 0.15197261842289531 + 0.15197686872651972 + 0.15198111913378073 + 0.15198536964468209 + 0.15198962025922774 + 0.15199387097742204 + 0.15199812179926844 + 0.15200237272477127 + 0.15200662375393431 + 0.15201087488676149 + 0.15201512612325699 + 0.15201937746342456 + 0.15202362890726831 + 0.15202788045479196 + 0.15203213210599981 + 0.15203638386089563 + 0.15204063571948331 + 0.15204488768176708 + 0.15204913974775053 + 0.152053391917438 + 0.15205764419083329 + 0.15206189656794017 + 0.15206614904876292 + 0.15207040163330554 + 0.15207465432157163 + 0.15207890711356545 + 0.15208316000929079 + 0.15208741300875175 + 0.15209166611195218 + 0.15209591931889613 + 0.15210017262958772 + 0.15210442604403057 + 0.15210867956222882 + 0.15211293318418642 + 0.15211718690990753 + 0.15212144073939565 + 0.15212569467265538 + 0.15212994870969004 + 0.152134202850504 + 0.15213845709510118 + 0.1521427114434854 + 0.15214696589566085 + 0.15215122045163135 + 0.15215547511140065 + 0.1521597298749732 + 0.15216398474235257 + 0.1521682397135429 + 0.15217249478854822 + 0.15217674996737232 + 0.15218100525001926 + 0.15218526063649315 + 0.1521895161267976 + 0.15219377172093684 + 0.15219802741891483 + 0.15220228322073545 + 0.15220653912640289 + 0.15221079513592078 + 0.15221505124929327 + 0.15221930746652435 + 0.15222356378761798 + 0.15222782021257814 + 0.15223207674140871 + 0.15223633337411369 + 0.15224059011069707 + 0.15224484695116275 + 0.15224910389551488 + 0.15225336094375735 + 0.152257618095894 + 0.15226187535192909 + 0.15226613271186612 + 0.15227039017570962 + 0.15227464774346322 + 0.15227890541513087 + 0.15228316319071672 + 0.15228742107022458 + 0.15229167905365851 + 0.15229593714102255 + 0.15230019533232028 + 0.15230445362755637 + 0.15230871202673424 + 0.15231297052985798 + 0.15231722913693155 + 0.15232148784795912 + 0.15232574666294443 + 0.15233000558189155 + 0.1523342646048044 + 0.15233852373168708 + 0.15234278296254361 + 0.15234704229737764 + 0.15235130173619346 + 0.15235556127899474 + 0.15235982092578568 + 0.15236408067657031 + 0.15236834053135251 + 0.1523726004901361 + 0.15237686055292529 + 0.15238112071972393 + 0.15238538099053622 + 0.15238964136536573 + 0.15239390184421658 + 0.152398162427093 + 0.15240242311399865 + 0.15240668390493761 + 0.15241094479991407 + 0.15241520579893153 + 0.15241946690199451 + 0.15242372810910673 + 0.15242798942027186 + 0.15243225083549444 + 0.15243651235477806 + 0.15244077397812686 + 0.15244503570554482 + 0.15244929753703576 + 0.15245355947260389 + 0.1524578215122529 + 0.15246208365598707 + 0.15246634590381017 + 0.15247060825572611 + 0.15247487071173912 + 0.15247913327185314 + 0.15248339593607199 + 0.15248765870439965 + 0.1524919215768403 + 0.15249618455339781 + 0.15250044763407597 + 0.15250471081887915 + 0.15250897410781086 + 0.15251323750087545 + 0.15251750099807668 + 0.15252176459941877 + 0.15252602830490528 + 0.15253029211454056 + 0.15253455602832872 + 0.1525388200462732 + 0.15254308416837847 + 0.15254734839464823 + 0.15255161272508647 + 0.15255587715969746 + 0.15256014169848478 + 0.15256440634145271 + 0.15256867108860492 + 0.15257293593994573 + 0.15257720089547913 + 0.15258146595520872 + 0.15258573111913898 + 0.15258999638727325 + 0.1525942617596161 + 0.15259852723617121 + 0.15260279281694278 + 0.15260705850193451 + 0.15261132429115062 + 0.15261559018459483 + 0.15261985618227147 + 0.15262412228418418 + 0.15262838849033733 + 0.15263265480073446 + 0.15263692121537997 + 0.15264118773427743 + 0.15264545435743104 + 0.15264972108484479 + 0.15265398791652274 + 0.15265825485246901 + 0.15266252189268692 + 0.15266678903718114 + 0.15267105628595529 + 0.15267532363901337 + 0.15267959109635951 + 0.15268385865799777 + 0.15268812632393197 + 0.15269239409416618 + 0.15269666196870418 + 0.15270092994754994 + 0.15270519803070789 + 0.15270946621818174 + 0.15271373450997544 + 0.15271800290609294 + 0.1527222714065381 + 0.15272654001131544 + 0.15273080872042849 + 0.15273507753388135 + 0.15273934645167772 + 0.15274361547382201 + 0.15274788460031818 + 0.15275215383117008 + 0.15275642316638166 + 0.15276069260595698 + 0.15276496214989993 + 0.15276923179821461 + 0.15277350155090491 + 0.15277777140797497 + 0.15278204136942874 + 0.15278631143526988 + 0.15279058160550288 + 0.15279485188013134 + 0.15279912225915959 + 0.15280339274259114 + 0.1528076633304305 + 0.1528119340226812 + 0.1528162048193476 + 0.15282047572043342 + 0.15282474672594287 + 0.15282901783587974 + 0.15283328905024823 + 0.15283756036905216 + 0.15284183179229552 + 0.1528461033199823 + 0.15285037495211665 + 0.15285464668870227 + 0.15285891852974348 + 0.15286319047524405 + 0.15286746252520816 + 0.15287173467963941 + 0.15287600693854203 + 0.15288027930192027 + 0.15288455176977758 + 0.15288882434211851 + 0.15289309701894674 + 0.15289736980026628 + 0.15290164268608111 + 0.1529059156763953 + 0.15291018877121274 + 0.15291446197053735 + 0.15291873527437352 + 0.1529230086827249 + 0.1529272821955954 + 0.15293155581298923 + 0.15293582953491042 + 0.15294010336136274 + 0.15294437729235036 + 0.15294865132787705 + 0.15295292546794706 + 0.15295719971256438 + 0.15296147406173285 + 0.15296574851545644 + 0.15297002307373941 + 0.15297429773658525 + 0.15297857250399857 + 0.15298284737598286 + 0.15298712235254242 + 0.15299139743368101 + 0.15299567261940294 + 0.15299994790971175 + 0.15300422330461197 + 0.15300849880410722 + 0.15301277440820146 + 0.15301705011689878 + 0.15302132593020323 + 0.15302560184811892 + 0.1530298778706497 + 0.15303415399779963 + 0.1530384302295725 + 0.15304270656597241 + 0.15304698300700348 + 0.1530512595526696 + 0.15305553620297488 + 0.15305981295792312 + 0.1530640898175184 + 0.15306836678176478 + 0.1530726438506663 + 0.15307692102422676 + 0.15308119830245018 + 0.15308547568534081 + 0.15308975317290241 + 0.15309403076513883 + 0.15309830846205458 + 0.15310258626365322 + 0.15310686416993874 + 0.15311114218091548 + 0.15311542029658706 + 0.15311969851695784 + 0.15312397684203152 + 0.1531282552718122 + 0.15313253380630387 + 0.15313681244551056 + 0.15314109118943628 + 0.15314537003808493 + 0.1531496489914605 + 0.15315392804956715 + 0.15315820721240883 + 0.1531624864799894 + 0.15316676585231301 + 0.15317104532938358 + 0.15317532491120517 + 0.15317960459778179 + 0.15318388438911734 + 0.15318816428521589 + 0.1531924442860812 + 0.1531967243917178 + 0.15320100460212929 + 0.15320528491731972 + 0.15320956533729291 + 0.15321384586205336 + 0.15321812649160485 + 0.15322240722595118 + 0.15322668806509659 + 0.15323096900904487 + 0.15323525005780017 + 0.15323953121136627 + 0.1532438124697475 + 0.15324809383294777 + 0.15325237530097099 + 0.15325665687382117 + 0.15326093855150238 + 0.15326522033401865 + 0.15326950222137381 + 0.15327378421357185 + 0.15327806631061694 + 0.1532823485125131 + 0.1532866308192643 + 0.15329091323087443 + 0.15329519574734748 + 0.15329947836868763 + 0.15330376109489885 + 0.15330804392598499 + 0.15331232686195007 + 0.15331660990279858 + 0.15332089304853355 + 0.15332517629915984 + 0.1533294596546812 + 0.15333374311510159 + 0.1533380266804249 + 0.15334231035065526 + 0.15334659412579674 + 0.15335087800585323 + 0.15335516199082883 + 0.15335944608072738 + 0.15336373027555306 + 0.1533680145753098 + 0.1533722989800016 + 0.15337658348963246 + 0.15338086810420656 + 0.15338515282372756 + 0.15338943764819968 + 0.15339372257762707 + 0.15339800761201339 + 0.15340229275136286 + 0.15340657799567944 + 0.15341086334496723 + 0.15341514879923013 + 0.15341943435847208 + 0.15342372002269716 + 0.15342800579190952 + 0.15343229166611294 + 0.15343657764531157 + 0.15344086372950941 + 0.15344514991871025 + 0.15344943621291848 + 0.15345372261213772 + 0.15345800911637225 + 0.153462295725626 + 0.15346658243990302 + 0.15347086925920733 + 0.15347515618354279 + 0.15347944321291343 + 0.15348373034732335 + 0.1534880175867766 + 0.15349230493127711 + 0.15349659238082891 + 0.15350087993543585 + 0.15350516759510213 + 0.15350945535983163 + 0.15351374322962869 + 0.15351803120449697 + 0.15352231928444049 + 0.15352660746946362 + 0.15353089575956974 + 0.15353518415476344 + 0.15353947265504847 + 0.15354376126042885 + 0.15354804997090873 + 0.15355233878649197 + 0.15355662770718248 + 0.15356091673298447 + 0.15356520586390215 + 0.15356949509993897 + 0.15357378444109959 + 0.15357807388738742 + 0.15358236343880666 + 0.15358665309536162 + 0.15359094285705593 + 0.1535952327238938 + 0.15359952269587923 + 0.15360381277301619 + 0.15360810295530872 + 0.15361239324276085 + 0.15361668363537653 + 0.15362097413315984 + 0.15362526473611474 + 0.15362955544424522 + 0.15363384625755533 + 0.1536381371760491 + 0.15364242819973059 + 0.15364671932860363 + 0.15365101056267255 + 0.15365530190194096 + 0.15365959334641313 + 0.15366388489609303 + 0.15366817655098472 + 0.15367246831109224 + 0.15367676017641932 + 0.15368105214697034 + 0.15368534422274935 + 0.15368963640375988 + 0.15369392869000634 + 0.15369822108149253 + 0.15370251357822268 + 0.15370680618020086 + 0.15371109888743084 + 0.15371539169991671 + 0.15371968461766247 + 0.15372397764067219 + 0.15372827076894993 + 0.15373256400249954 + 0.15373685734132519 + 0.1537411507854306 + 0.15374544433482051 + 0.15374973798949831 + 0.15375403174946806 + 0.15375832561473388 + 0.15376261958529977 + 0.1537669136611699 + 0.15377120784234807 + 0.15377550212883853 + 0.15377979652064508 + 0.15378409101777177 + 0.15378838562022262 + 0.15379268032800164 + 0.15379697514111296 + 0.1538012700595604 + 0.15380556508334858 + 0.15380986021248053 + 0.15381415544696098 + 0.1538184507867939 + 0.15382274623198297 + 0.15382704178253262 + 0.15383133743844654 + 0.15383563319972871 + 0.15383992906638341 + 0.15384422503841461 + 0.15384852111582636 + 0.15385281729862241 + 0.15385711358680709 + 0.15386140998038444 + 0.15386570647935796 + 0.1538700030837323 + 0.15387429979351108 + 0.15387859660869846 + 0.15388289352929885 + 0.15388719055531558 + 0.15389148768675298 + 0.15389578492361516 + 0.15390008226590596 + 0.15390437971362955 + 0.15390867726679006 + 0.15391297492539102 + 0.15391727268943708 + 0.15392157055893196 + 0.15392586853387957 + 0.15393016661428402 + 0.15393446480014944 + 0.15393876309147969 + 0.15394306148827896 + 0.15394735999055117 + 0.1539516585983004 + 0.15395595731153067 + 0.15396025613024586 + 0.15396455505445031 + 0.15396885408414765 + 0.15397315321934202 + 0.15397745246003763 + 0.15398175180623852 + 0.15398605125794843 + 0.15399035081517162 + 0.15399465047791194 + 0.1539989502461736 + 0.15400325011996052 + 0.15400755009927672 + 0.15401185018412633 + 0.15401615037451324 + 0.15402045067044165 + 0.15402475107191516 + 0.15402905157893834 + 0.15403335219151493 + 0.15403765290964899 + 0.15404195373334442 + 0.15404625466260549 + 0.15405055569743625 + 0.15405485683784031 + 0.15405915808382217 + 0.15406345943538577 + 0.15406776089253482 + 0.15407206245527372 + 0.15407636412360634 + 0.15408066589753658 + 0.15408496777706868 + 0.15408926976220663 + 0.15409357185295439 + 0.15409787404931585 + 0.15410217635129539 + 0.15410647875889674 + 0.15411078127212408 + 0.15411508389098127 + 0.15411938661547256 + 0.15412368944560204 + 0.15412799238137337 + 0.1541322954227908 + 0.15413659856985837 + 0.15414090182258014 + 0.15414520518096003 + 0.15414950864500213 + 0.15415381221471053 + 0.15415811589008899 + 0.15416241967114191 + 0.15416672355787311 + 0.15417102755028664 + 0.15417533164838662 + 0.15417963585217709 + 0.15418394016166187 + 0.15418824457684516 + 0.15419254909773097 + 0.15419685372432321 + 0.15420115845662621 + 0.15420546329464366 + 0.1542097682383797 + 0.15421407328783854 + 0.15421837844302408 + 0.15422268370394027 + 0.15422698907059132 + 0.15423129454298101 + 0.15423560012111362 + 0.15423990580499292 + 0.1542442115946234 + 0.15424851749000848 + 0.15425282349115274 + 0.15425712959805976 + 0.15426143581073409 + 0.15426574212917935 + 0.15427004855339968 + 0.15427435508339907 + 0.1542786617191817 + 0.15428296846075154 + 0.1542872753081124 + 0.15429158226126882 + 0.15429588932022445 + 0.15430019648498319 + 0.15430450375554944 + 0.15430881113192718 + 0.15431311861412025 + 0.15431742620213262 + 0.15432173389596862 + 0.15432604169563216 + 0.15433034960112738 + 0.1543346576124579 + 0.1543389657296283 + 0.15434327395264241 + 0.15434758228150397 + 0.1543518907162176 + 0.15435619925678665 + 0.15436050790321584 + 0.15436481665550883 + 0.15436912551366963 + 0.15437343447770235 + 0.15437774354761108 + 0.15438205272339969 + 0.1543863620050725 + 0.15439067139263313 + 0.15439498088608611 + 0.1543992904854351 + 0.1544036001906843 + 0.15440791000183798 + 0.15441221991889967 + 0.15441652994187369 + 0.1544208400707642 + 0.15442515030557485 + 0.15442946064630986 + 0.15443377109297354 + 0.15443808164556963 + 0.15444239230410228 + 0.15444670306857552 + 0.15445101393899319 + 0.15445532491535977 + 0.15445963599767903 + 0.15446394718595477 + 0.15446825848019149 + 0.15447256988039304 + 0.15447688138656324 + 0.15448119299870647 + 0.15448550471682648 + 0.15448981654092764 + 0.15449412847101368 + 0.15449844050708889 + 0.15450275264915694 + 0.15450706489722246 + 0.15451137725128886 + 0.15451568971136059 + 0.15452000227744164 + 0.15452431494953581 + 0.15452862772764747 + 0.15453294061178063 + 0.15453725360193898 + 0.15454156669812666 + 0.15454587990034813 + 0.15455019320860719 + 0.15455450662290762 + 0.15455882014325364 + 0.15456313376964956 + 0.15456744750209908 + 0.15457176134060624 + 0.15457607528517542 + 0.15458038933581025 + 0.15458470349251505 + 0.15458901775529396 + 0.15459333212415066 + 0.15459764659908937 + 0.15460196118011421 + 0.15460627586722905 + 0.15461059066043811 + 0.1546149055597455 + 0.15461922056515504 + 0.15462353567667064 + 0.15462785089429687 + 0.15463216621803746 + 0.15463648164789642 + 0.15464079718387766 + 0.15464511282598553 + 0.15464942857422403 + 0.15465374442859714 + 0.15465806038910868 + 0.15466237645576311 + 0.15466669262856417 + 0.15467100890751612 + 0.15467532529262287 + 0.1546796417838886 + 0.15468395838131696 + 0.15468827508491262 + 0.15469259189467904 + 0.15469690881062073 + 0.15470122583274137 + 0.15470554296104519 + 0.15470986019553629 + 0.15471417753621863 + 0.15471849498309628 + 0.15472281253617307 + 0.15472713019545348 + 0.15473144796094118 + 0.15473576583264065 + 0.1547400838105554 + 0.15474440189468994 + 0.15474872008504784 + 0.15475303838163373 + 0.15475735678445118 + 0.15476167529350432 + 0.15476599390879758 + 0.15477031263033439 + 0.15477463145811937 + 0.15477895039215633 + 0.15478326943244924 + 0.15478758857900216 + 0.15479190783181937 + 0.15479622719090469 + 0.15480054665626231 + 0.15480486622789619 + 0.15480918590581025 + 0.15481350569000876 + 0.15481782558049595 + 0.15482214557727522 + 0.15482646568035133 + 0.1548307858897279 + 0.15483510620540919 + 0.15483942662739905 + 0.15484374715570179 + 0.15484806779032118 + 0.15485238853126138 + 0.15485670937852669 + 0.15486103033212081 + 0.15486535139204793 + 0.15486967255831227 + 0.15487399383091752 + 0.15487831520986794 + 0.15488263669516777 + 0.15488695828682073 + 0.15489127998483099 + 0.15489560178920259 + 0.15489992369993966 + 0.15490424571704633 + 0.15490856784052628 + 0.15491289007038417 + 0.15491721240662318 + 0.15492153484924823 + 0.15492585739826301 + 0.15493018005367162 + 0.15493450281547816 + 0.15493882568368636 + 0.15494314865830067 + 0.15494747173932494 + 0.15495179492676334 + 0.15495611822061983 + 0.15496044162089859 + 0.15496476512760349 + 0.15496908874073878 + 0.15497341246030838 + 0.15497773628631642 + 0.15498206021876693 + 0.15498638425766395 + 0.15499070840301155 + 0.15499503265481376 + 0.15499935701307466 + 0.15500368147779833 + 0.15500800604898871 + 0.1550123307266501 + 0.15501665551078644 + 0.15502098040140172 + 0.1550253053984999 + 0.15502963050208532 + 0.15503395571216197 + 0.1550382810287336 + 0.15504260645180451 + 0.15504693198137898 + 0.15505125761746058 + 0.15505558336005376 + 0.15505990920916246 + 0.15506423516479054 + 0.1550685612269424 + 0.15507288739562197 + 0.15507721367083324 + 0.1550815400525801 + 0.15508586654086698 + 0.15509019313569777 + 0.15509451983707664 + 0.15509884664500734 + 0.15510317355949427 + 0.15510750058054126 + 0.15511182770815252 + 0.15511615494233214 + 0.15512048228308409 + 0.15512480973041243 + 0.15512913728432101 + 0.15513346494481425 + 0.15513779271189615 + 0.15514212058557059 + 0.15514644856584164 + 0.15515077665271346 + 0.15515510484619044 + 0.15515943314627589 + 0.15516376155297459 + 0.1551680900662902 + 0.15517241868622686 + 0.15517674741278861 + 0.15518107624597963 + 0.15518540518580384 + 0.15518973423226531 + 0.15519406338536837 + 0.15519839264511665 + 0.15520272201151475 + 0.15520705148456618 + 0.15521138106427532 + 0.15521571075064614 + 0.15522004054368263 + 0.15522437044338902 + 0.15522870044976933 + 0.15523303056282778 + 0.15523736078256803 + 0.15524169110899427 + 0.1552460215421107 + 0.15525035208192151 + 0.15525468272843057 + 0.15525901348164198 + 0.15526334434155969 + 0.15526767530818808 + 0.15527200638153069 + 0.15527633756159229 + 0.15528066884837624 + 0.15528500024188713 + 0.15528933174212861 + 0.15529366334910516 + 0.15529799506282055 + 0.15530232688327905 + 0.15530665881048444 + 0.15531099084444114 + 0.15531532298515296 + 0.15531965523262409 + 0.15532398758685845 + 0.15532832004786026 + 0.15533265261563353 + 0.15533698529018233 + 0.15534131807151072 + 0.15534565095962291 + 0.15534998395452276 + 0.15535431705621441 + 0.15535865026470194 + 0.15536298357998946 + 0.15536731700208101 + 0.15537165053098062 + 0.15537598416669227 + 0.15538031790922022 + 0.15538465175856861 + 0.15538898571474097 + 0.15539331977774218 + 0.15539765394757574 + 0.15540198822424581 + 0.1554063226077565 + 0.155410657098112 + 0.15541499169531631 + 0.15541932639937336 + 0.15542366121028728 + 0.15542799612806221 + 0.15543233115270219 + 0.15543666628421127 + 0.15544100152259374 + 0.15544533686785339 + 0.1554496723199944 + 0.15545400787902081 + 0.15545834354493676 + 0.15546267931774613 + 0.1554670151974531 + 0.15547135118406186 + 0.15547568727757646 + 0.15548002347800072 + 0.15548435978533917 + 0.15548869619959543 + 0.15549303272077358 + 0.15549736934887806 + 0.15550170608391276 + 0.15550604292588174 + 0.15551037987478927 + 0.15551471693063865 + 0.155519054093435 + 0.15552339136318197 + 0.1555277287398833 + 0.15553206622354349 + 0.15553640381416636 + 0.15554074151175631 + 0.15554507931631711 + 0.15554941722785284 + 0.15555375524636778 + 0.15555809337186574 + 0.15556243160435115 + 0.1555667699438277 + 0.15557110839029961 + 0.15557544694377107 + 0.15557978560424618 + 0.15558412437172878 + 0.15558846324622314 + 0.15559280222773339 + 0.15559714131626298 + 0.15560148051181705 + 0.15560581981439889 + 0.15561015922401283 + 0.15561449874066272 + 0.15561883836435297 + 0.15562317809508769 + 0.15562751793287069 + 0.15563185787770617 + 0.15563619792959793 + 0.15564053808855075 + 0.15564487835456775 + 0.15564921872765386 + 0.15565355920781274 + 0.15565789979504854 + 0.15566224048936531 + 0.15566658129076724 + 0.15567092219925824 + 0.15567526321484243 + 0.15567960433752401 + 0.15568394556730705 + 0.15568828690419539 + 0.15569262834819353 + 0.15569696989930495 + 0.15570131155753433 + 0.1557056533228853 + 0.15570999519536241 + 0.1557143371749693 + 0.15571867926171026 + 0.15572302145558939 + 0.1557273637566105 + 0.15573170616477813 + 0.15573604868009594 + 0.1557403913025682 + 0.15574473403219885 + 0.15574907686899234 + 0.15575341981295238 + 0.15575776286408299 + 0.1557621060223888 + 0.15576644928787342 + 0.15577079266054084 + 0.15577513614039556 + 0.15577947972744116 + 0.1557838234216822 + 0.1557881672231225 + 0.15579251113176634 + 0.15579685514761768 + 0.15580119927068031 + 0.15580554350095877 + 0.15580988783845692 + 0.15581423228317889 + 0.15581857683512901 + 0.15582292149431087 + 0.15582726626072879 + 0.15583161113438676 + 0.15583595611528919 + 0.15584030120343989 + 0.15584464639884299 + 0.15584899170150252 + 0.15585333711142266 + 0.15585768262860736 + 0.15586202825306097 + 0.15586637398478725 + 0.1558707198237905 + 0.15587506577007479 + 0.15587941182364409 + 0.15588375798450274 + 0.15588810425265445 + 0.15589245062810356 + 0.15589679711085408 + 0.15590114370090999 + 0.15590549039827567 + 0.15590983720295482 + 0.15591418411495189 + 0.15591853113427082 + 0.15592287826091561 + 0.15592722549489055 + 0.15593157283619941 + 0.15593592028484665 + 0.15594026784083614 + 0.15594461550417202 + 0.15594896327485827 + 0.15595331115289915 + 0.15595765913829876 + 0.15596200723106091 + 0.15596635543118981 + 0.15597070373868974 + 0.15597505215356464 + 0.15597940067581847 + 0.15598374930545578 + 0.15598809804248021 + 0.15599244688689587 + 0.15599679583870701 + 0.15600114489791755 + 0.1560054940645321 + 0.15600984333855397 + 0.15601419271998762 + 0.15601854220883737 + 0.15602289180510706 + 0.15602724150880051 + 0.15603159131992253 + 0.15603594123847658 + 0.15604029126446692 + 0.1560446413978977 + 0.15604899163877289 + 0.15605334198709683 + 0.15605769244287346 + 0.15606204300610677 + 0.15606639367680111 + 0.1560707444549603 + 0.1560750953405885 + 0.15607944633368989 + 0.15608379743426867 + 0.1560881486423287 + 0.156092499957874 + 0.15609685138090879 + 0.15610120291143739 + 0.15610555454946365 + 0.15610990629499147 + 0.15611425814802551 + 0.15611861010856942 + 0.15612296217662716 + 0.15612731435220345 + 0.15613166663530176 + 0.15613601902592647 + 0.15614037152408161 + 0.15614472412977135 + 0.15614907684299947 + 0.15615342966377066 + 0.15615778259208846 + 0.15616213562795719 + 0.15616648877138101 + 0.15617084202236381 + 0.1561751953809099 + 0.15617954884702318 + 0.15618390242070795 + 0.15618825610196835 + 0.15619260989080797 + 0.15619696378723166 + 0.15620131779124277 + 0.15620567190284584 + 0.15621002612204501 + 0.15621438044884411 + 0.15621873488324728 + 0.15622308942525898 + 0.1562274440748829 + 0.15623179883212299 + 0.1562361536969839 + 0.15624050866946954 + 0.15624486374958357 + 0.15624921893733063 + 0.15625357423271466 + 0.15625792963573959 + 0.15626228514640961 + 0.15626664076472913 + 0.15627099649070178 + 0.15627535232433173 + 0.15627970826562324 + 0.15628406431458042 + 0.15628842047120733 + 0.15629277673550812 + 0.15629713310748666 + 0.15630148958714721 + 0.156305846174494 + 0.15631020286953087 + 0.15631455967226218 + 0.15631891658269187 + 0.15632327360082388 + 0.15632763072666253 + 0.15633198796021197 + 0.15633634530147622 + 0.15634070275045939 + 0.15634506030716544 + 0.1563494179715986 + 0.15635377574376311 + 0.15635813362366283 + 0.15636249161130206 + 0.15636684970668452 + 0.15637120790981485 + 0.1563755662206969 + 0.15637992463933456 + 0.1563842831657323 + 0.15638864179989401 + 0.15639300054182373 + 0.15639735939152574 + 0.15640171834900407 + 0.1564060774142628 + 0.15641043658730608 + 0.15641479586813803 + 0.1564191552567627 + 0.1564235147531842 + 0.15642787435740649 + 0.15643223406943382 + 0.15643659388927045 + 0.15644095381692025 + 0.15644531385238744 + 0.15644967399567605 + 0.15645403424679022 + 0.15645839460573407 + 0.15646275507251164 + 0.15646711564712709 + 0.1564714763295845 + 0.15647583711988794 + 0.15648019801804161 + 0.1564845590240497 + 0.15648892013791593 + 0.15649328135964471 + 0.15649764268924021 + 0.15650200412670648 + 0.15650636567204732 + 0.15651072732526727 + 0.15651508908637013 + 0.15651945095536021 + 0.1565238129322413 + 0.1565281750170181 + 0.15653253720969415 + 0.15653689951027358 + 0.15654126191876094 + 0.15654562443516015 + 0.15654998705947495 + 0.15655434979170985 + 0.15655871263186885 + 0.15656307557995594 + 0.15656743863597544 + 0.15657180179993135 + 0.15657616507182781 + 0.15658052845166878 + 0.15658489193945868 + 0.15658925553520125 + 0.15659361923890081 + 0.1565979830505615 + 0.15660234697018732 + 0.15660671099778231 + 0.15661107513335079 + 0.15661543937689679 + 0.15661980372842438 + 0.15662416818793776 + 0.15662853275544072 + 0.15663289743093775 + 0.15663726221443294 + 0.15664162710593019 + 0.15664599210543373 + 0.15665035721294759 + 0.15665472242847595 + 0.15665908775202286 + 0.15666345318359268 + 0.15666781872318924 + 0.15667218437081654 + 0.15667655012647896 + 0.15668091599018072 + 0.15668528196192552 + 0.15668964804171778 + 0.15669401422956145 + 0.15669838052546106 + 0.15670274692941993 + 0.15670711344144284 + 0.1567114800615336 + 0.15671584678969647 + 0.15672021362593547 + 0.15672458057025476 + 0.15672894762265846 + 0.15673331478315072 + 0.15673768205173527 + 0.15674204942841696 + 0.15674641691319935 + 0.15675078450608637 + 0.15675515220708278 + 0.15675952001619251 + 0.15676388793341928 + 0.15676825595876748 + 0.1567726240922411 + 0.15677699233384457 + 0.15678136068358167 + 0.1567857291414568 + 0.15679009770747368 + 0.15679446638163683 + 0.1567988351639501 + 0.15680320405441764 + 0.15680757305304369 + 0.15681194215983235 + 0.1568163113747876 + 0.15682068069791372 + 0.15682505012921469 + 0.15682941966869474 + 0.15683378931635783 + 0.1568381590722083 + 0.15684252893624989 + 0.1568468989084873 + 0.15685126898892421 + 0.15685563917756468 + 0.15686000947441306 + 0.15686437987947338 + 0.15686875039274994 + 0.1568731210142465 + 0.15687749174396737 + 0.1568818625819168 + 0.15688623352809886 + 0.15689060458251722 + 0.15689497574517663 + 0.15689934701608083 + 0.15690371839523409 + 0.15690808988264043 + 0.15691246147830409 + 0.15691683318222924 + 0.15692120499441969 + 0.15692557691487999 + 0.15692994894361373 + 0.15693432108062552 + 0.15693869332591923 + 0.15694306567949898 + 0.15694743814136891 + 0.15695181071153314 + 0.15695618338999626 + 0.15696055617676141 + 0.1569649290718336 + 0.15696930207521634 + 0.15697367518691405 + 0.15697804840693108 + 0.15698242173527083 + 0.15698679517193836 + 0.15699116871693711 + 0.15699554237027141 + 0.15699991613194531 + 0.15700429000196309 + 0.15700866398032873 + 0.1570130380670465 + 0.15701741226212015 + 0.15702178656555443 + 0.15702616097735295 + 0.15703053549752002 + 0.15703491012605958 + 0.15703928486297603 + 0.15704365970827339 + 0.15704803466195572 + 0.15705240972402718 + 0.15705678489449193 + 0.15706116017335389 + 0.15706553556061761 + 0.15706991105628706 + 0.15707428666036602 + 0.15707866237285892 + 0.15708303819376984 + 0.15708741412310279 + 0.15709179016086203 + 0.15709616630705187 + 0.15710054256167599 + 0.15710491892473871 + 0.15710929539624444 + 0.15711367197619691 + 0.15711804866460025 + 0.15712242546145902 + 0.15712680236677673 + 0.15713117938055801 + 0.15713555650280667 + 0.15713993373352722 + 0.15714431107272334 + 0.15714868852039929 + 0.15715306607655952 + 0.15715744374120766 + 0.15716182151434813 + 0.15716619939598503 + 0.15717057738612242 + 0.15717495548476451 + 0.15717933369191525 + 0.15718371200757897 + 0.1571880904317598 + 0.15719246896446185 + 0.15719684760568908 + 0.15720122635544589 + 0.15720560521373611 + 0.15720998418056395 + 0.1572143632559336 + 0.15721874243984937 + 0.15722312173231512 + 0.15722750113333514 + 0.1572318806429133 + 0.15723626026105395 + 0.15724063998776136 + 0.15724501982303932 + 0.15724939976689228 + 0.15725377981932392 + 0.15725815998033912 + 0.15726254024994119 + 0.15726692062813483 + 0.15727130111492391 + 0.15727568171031236 + 0.15728006241430487 + 0.1572844432269053 + 0.15728882414811762 + 0.15729320517794626 + 0.15729758631639498 + 0.15730196756346829 + 0.15730634891916992 + 0.1573107303835044 + 0.15731511195647568 + 0.15731949363808784 + 0.15732387542834531 + 0.15732825732725161 + 0.15733263933481154 + 0.15733702145102887 + 0.15734140367590799 + 0.15734578600945257 + 0.15735016845166719 + 0.15735455100255574 + 0.15735893366212239 + 0.15736331643037149 + 0.15736769930730693 + 0.1573720822929329 + 0.15737646538725361 + 0.1573808485902731 + 0.15738523190199544 + 0.15738961532242499 + 0.15739399885156563 + 0.15739838248942159 + 0.15740276623599733 + 0.15740715009129644 + 0.15741153405532357 + 0.15741591812808234 + 0.15742030230957729 + 0.15742468659981226 + 0.15742907099879169 + 0.15743345550651944 + 0.15743784012299977 + 0.15744222484823706 + 0.15744660968223484 + 0.15745099462499773 + 0.15745537967652981 + 0.1574597648368351 + 0.15746415010591799 + 0.15746853548378217 + 0.15747292097043203 + 0.15747730656587181 + 0.15748169227010553 + 0.15748607808313714 + 0.15749046400497141 + 0.15749485003561181 + 0.15749923617506253 + 0.15750362242332799 + 0.15750800878041238 + 0.15751239524631955 + 0.15751678182105389 + 0.15752116850461909 + 0.15752555529701989 + 0.15752994219826022 + 0.15753432920834412 + 0.15753871632727562 + 0.15754310355505921 + 0.15754749089169878 + 0.15755187833719858 + 0.15755626589156255 + 0.15756065355479504 + 0.15756504132690005 + 0.15756942920788192 + 0.15757381719774458 + 0.15757820529649222 + 0.15758259350412915 + 0.15758698182065936 + 0.15759137024608702 + 0.15759575878041604 + 0.15760014742365117 + 0.15760453617579581 + 0.15760892503685453 + 0.15761331400683171 + 0.15761770308573084 + 0.15762209227355636 + 0.1576264815703127 + 0.15763087097600376 + 0.15763526049063353 + 0.1576396501142063 + 0.15764403984672634 + 0.15764842968819759 + 0.15765281963862429 + 0.15765720969801061 + 0.15766159986636058 + 0.15766599014367846 + 0.15767038052996843 + 0.15767477102523456 + 0.15767916162948087 + 0.15768355234271159 + 0.15768794316493087 + 0.15769233409614308 + 0.15769672513635208 + 0.15770111628556205 + 0.15770550754377721 + 0.15770989891100179 + 0.15771429038723972 + 0.15771868197249533 + 0.15772307366677271 + 0.15772746547007593 + 0.15773185738240905 + 0.15773624940377656 + 0.15774064153418244 + 0.15774503377363067 + 0.15774942612212547 + 0.15775381857967141 + 0.15775821114627178 + 0.15776260382193158 + 0.15776699660665441 + 0.15777138950044464 + 0.15777578250330648 + 0.15778017561524402 + 0.15778456883626127 + 0.15778896216636246 + 0.15779335560555163 + 0.15779774915383324 + 0.15780214281121127 + 0.15780653657768967 + 0.15781093045327305 + 0.15781532443796498 + 0.15781971853177007 + 0.15782411273469221 + 0.15782850704673573 + 0.15783290146790474 + 0.15783729599820331 + 0.15784169063763551 + 0.15784608538620581 + 0.15785048024391793 + 0.15785487521077649 + 0.15785927028678531 + 0.15786366547194847 + 0.15786806076627036 + 0.15787245616975501 + 0.15787685168240667 + 0.15788124730422951 + 0.15788564303522751 + 0.15789003887540498 + 0.15789443482476595 + 0.15789883088331458 + 0.15790322705105519 + 0.15790762332799158 + 0.1579120197141283 + 0.15791641620946936 + 0.1579208128140189 + 0.15792520952778091 + 0.15792960635075981 + 0.15793400328295962 + 0.1579384003243845 + 0.15794279747503853 + 0.15794719473492599 + 0.15795159210405105 + 0.15795598958241786 + 0.15796038717003036 + 0.15796478486689292 + 0.15796918267300972 + 0.15797358058838476 + 0.15797797861302221 + 0.15798237674692633 + 0.15798677499010103 + 0.15799117334255094 + 0.15799557180427981 + 0.15799997037529201 + 0.15800436905559151 + 0.1580087678451825 + 0.15801316674406934 + 0.15801756575225584 + 0.1580219648697464 + 0.15802636409654519 + 0.15803076343265632 + 0.15803516287808408 + 0.15803956243283226 + 0.15804396209690535 + 0.15804836187030721 + 0.15805276175304228 + 0.15805716174511475 + 0.15806156184652845 + 0.15806596205728787 + 0.15807036237739691 + 0.15807476280685984 + 0.15807916334568106 + 0.15808356399386431 + 0.15808796475141382 + 0.15809236561833415 + 0.15809676659462896 + 0.15810116768030255 + 0.15810556887535918 + 0.15810997017980299 + 0.15811437159363817 + 0.15811877311686881 + 0.15812317474949911 + 0.15812757649153342 + 0.15813197834297518 + 0.15813638030382937 + 0.15814078237409993 + 0.15814518455379076 + 0.15814958684290617 + 0.15815398924145019 + 0.1581583917494275 + 0.15816279436684161 + 0.15816719709369709 + 0.15817159992999802 + 0.15817600287574851 + 0.15818040593095273 + 0.15818480909561455 + 0.15818921236973874 + 0.15819361575332902 + 0.15819801924638957 + 0.15820242284892483 + 0.15820682656093862 + 0.15821123038243534 + 0.15821563431341909 + 0.15822003835389389 + 0.15822444250386408 + 0.15822884676333399 + 0.15823325113230741 + 0.15823765561078865 + 0.1582420601987819 + 0.15824646489629129 + 0.15825086970332095 + 0.15825527461987518 + 0.15825967964595794 + 0.15826408478157364 + 0.1582684900267263 + 0.15827289538142009 + 0.15827730084565925 + 0.1582817064194478 + 0.15828611210279003 + 0.15829051789568999 + 0.15829492379815174 + 0.15829932981017986 + 0.15830373593177827 + 0.15830814216295105 + 0.15831254850370247 + 0.15831695495403683 + 0.15832136151395809 + 0.15832576818347033 + 0.1583301749625779 + 0.15833458185128502 + 0.15833898884959574 + 0.1583433959575142 + 0.1583478031750446 + 0.15835221050219123 + 0.15835661793895814 + 0.15836102548534939 + 0.15836543314136922 + 0.15836984090702183 + 0.15837424878231154 + 0.15837865676724233 + 0.15838306486181841 + 0.1583874730660442 + 0.15839188137992327 + 0.15839628980346038 + 0.15840069833665921 + 0.15840510697952428 + 0.15840951573205972 + 0.15841392459426956 + 0.15841833356615823 + 0.1584227426477294 + 0.15842715183898781 + 0.15843156113993714 + 0.15843597055058203 + 0.15844038007092645 + 0.15844478970097423 + 0.15844919944073005 + 0.15845360929019772 + 0.15845801924938183 + 0.15846242931828611 + 0.15846683949691487 + 0.15847124978527238 + 0.15847566018336287 + 0.15848007069119011 + 0.15848448130875853 + 0.15848889203607255 + 0.15849330287313601 + 0.15849771381995331 + 0.15850212487652826 + 0.15850653604286544 + 0.15851094731896898 + 0.15851535870484279 + 0.15851977020049102 + 0.15852418180591832 + 0.1585285935211283 + 0.15853300534612541 + 0.15853741728091356 + 0.15854182932549754 + 0.15854624147988103 + 0.15855065374406835 + 0.15855506611806347 + 0.15855947860187086 + 0.15856389119549438 + 0.15856830389893856 + 0.1585727167122073 + 0.15857712963530488 + 0.15858154266823557 + 0.15858595581100327 + 0.15859036906361229 + 0.15859478242606706 + 0.15859919589837157 + 0.15860360948052979 + 0.15860802317254616 + 0.1586124369744247 + 0.15861685088616984 + 0.15862126490778539 + 0.15862567903927574 + 0.15863009328064495 + 0.15863450763189729 + 0.15863892209303701 + 0.15864333666406816 + 0.15864775134499484 + 0.15865216613582153 + 0.15865658103655214 + 0.15866099604719097 + 0.15866541116774197 + 0.15866982639820973 + 0.15867424173859801 + 0.1586786571889113 + 0.15868307274915369 + 0.15868748841932928 + 0.15869190419944235 + 0.15869632008949691 + 0.15870073608949734 + 0.15870515219944753 + 0.15870956841935208 + 0.15871398474921497 + 0.15871840118904007 + 0.15872281773883212 + 0.1587272343985949 + 0.15873165116833285 + 0.15873606804804991 + 0.15874048503775021 + 0.15874490213743825 + 0.15874931934711825 + 0.15875373666679385 + 0.15875815409646976 + 0.15876257163614974 + 0.15876698928583846 + 0.15877140704553977 + 0.15877582491525796 + 0.15878024289499701 + 0.15878466098476124 + 0.15878907918455512 + 0.15879349749438237 + 0.15879791591424733 + 0.15880233444415456 + 0.15880675308410747 + 0.15881117183411098 + 0.15881559069416876 + 0.15882000966428528 + 0.15882442874446467 + 0.15882884793471108 + 0.15883326723502875 + 0.15883768664542175 + 0.15884210616589431 + 0.15884652579645059 + 0.15885094553709489 + 0.1588553653878314 + 0.15885978534866402 + 0.15886420541959725 + 0.15886862560063506 + 0.15887304589178189 + 0.15887746629304175 + 0.15888188680441881 + 0.15888630742591717 + 0.15889072815754113 + 0.15889514899929513 + 0.15889956995118293 + 0.15890399101320893 + 0.15890841218537732 + 0.15891283346769217 + 0.1589172548601579 + 0.15892167636277824 + 0.15892609797555776 + 0.15893051969850072 + 0.15893494153161114 + 0.15893936347489315 + 0.15894378552835087 + 0.1589482076919887 + 0.15895262996581086 + 0.15895705234982127 + 0.15896147484402437 + 0.15896589744842418 + 0.15897032016302493 + 0.15897474298783082 + 0.15897916592284614 + 0.15898358896807493 + 0.15898801212352162 + 0.15899243538918986 + 0.15899685876508457 + 0.15900128225120935 + 0.15900570584756846 + 0.15901012955416644 + 0.15901455337100737 + 0.15901897729809505 + 0.15902340133543413 + 0.15902782548302863 + 0.1590322497408827 + 0.15903667410900058 + 0.15904109858738644 + 0.15904552317604437 + 0.15904994787497892 + 0.15905437268419376 + 0.15905879760369368 + 0.15906322263348222 + 0.15906764777356414 + 0.15907207302394316 + 0.15907649838462382 + 0.15908092385561001 + 0.1590853494369063 + 0.1590897751285168 + 0.1590942009304453 + 0.15909862684269657 + 0.15910305286527435 + 0.15910747899818273 + 0.15911190524142657 + 0.15911633159500949 + 0.15912075805893602 + 0.15912518463320974 + 0.15912961131783582 + 0.15913403811281757 + 0.15913846501815967 + 0.15914289203386617 + 0.15914731915994107 + 0.15915174639638902 + 0.15915617374321381 + 0.15916060120041969 + 0.15916502876801117 + 0.1591694564459922 + 0.15917388423436687 + 0.15917831213313952 + 0.15918274014231446 + 0.15918716826189563 + 0.15919159649188747 + 0.15919602483229395 + 0.15920045328311927 + 0.15920488184436793 + 0.15920931051604378 + 0.15921373929815122 + 0.1592181681906942 + 0.15922259719367743 + 0.15922702630710456 + 0.15923145553097998 + 0.15923588486530804 + 0.15924031431009275 + 0.15924474386533824 + 0.15924917353104914 + 0.15925360330722907 + 0.15925803319388246 + 0.15926246319101373 + 0.15926689329862678 + 0.15927132351672588 + 0.15927575384531545 + 0.15928018428439938 + 0.15928461483398176 + 0.15928904549406739 + 0.15929347626466009 + 0.15929790714576392 + 0.15930233813738326 + 0.15930676923952217 + 0.15931120045218508 + 0.15931563177537622 + 0.15932006320909933 + 0.15932449475335916 + 0.1593289264081594 + 0.15933335817350466 + 0.15933779004939921 + 0.15934222203584683 + 0.15934665413285182 + 0.15935108634041864 + 0.15935551865855152 + 0.15935995108725415 + 0.15936438362653113 + 0.15936881627638663 + 0.15937324903682487 + 0.15937768190785007 + 0.15938211488946616 + 0.15938654798167773 + 0.15939098118448863 + 0.15939541449790329 + 0.15939984792192616 + 0.15940428145656063 + 0.15940871510181159 + 0.1594131488576831 + 0.15941758272417927 + 0.15942201670130432 + 0.1594264507890627 + 0.15943088498745819 + 0.15943531929649526 + 0.15943975371617802 + 0.15944418824651085 + 0.15944862288749756 + 0.15945305763914283 + 0.1594574925014505 + 0.159461927474425 + 0.1594663625580704 + 0.15947079775239115 + 0.15947523305739106 + 0.15947966847307452 + 0.15948410399944607 + 0.15948853963650925 + 0.15949297538426871 + 0.15949741124272848 + 0.15950184721189309 + 0.15950628329176622 + 0.15951071948235265 + 0.15951515578365599 + 0.15951959219568101 + 0.15952402871843152 + 0.15952846535191187 + 0.15953290209612644 + 0.15953733895107899 + 0.15954177591677418 + 0.15954621299321595 + 0.15955065018040868 + 0.15955508747835626 + 0.15955952488706354 + 0.15956396240653384 + 0.15956840003677228 + 0.15957283777778231 + 0.15957727562956853 + 0.15958171359213519 + 0.15958615166548631 + 0.15959058984962612 + 0.15959502814455898 + 0.15959946655028909 + 0.15960390506682035 + 0.15960834369415733 + 0.1596127824323042 + 0.15961722128126493 + 0.15962166024104396 + 0.15962609931164534 + 0.15963053849307335 + 0.15963497778533237 + 0.15963941718842636 + 0.15964385670235945 + 0.15964829632713615 + 0.15965273606276048 + 0.15965717590923689 + 0.15966161586656927 + 0.15966605593476194 + 0.15967049611381912 + 0.15967493640374514 + 0.15967937680454417 + 0.15968381731622033 + 0.15968825793877786 + 0.15969269867222094 + 0.15969713951655401 + 0.15970158047178085 + 0.15970602153790608 + 0.15971046271493364 + 0.15971490400286786 + 0.15971934540171304 + 0.15972378691147338 + 0.15972822853215293 + 0.1597326702637559 + 0.15973711210628672 + 0.15974155405974935 + 0.15974599612414833 + 0.1597504382994876 + 0.1597548805857715 + 0.15975932298300427 + 0.15976376549118987 + 0.15976820811033277 + 0.15977265084043707 + 0.15977709368150717 + 0.15978153663354708 + 0.15978597969656089 + 0.15979042287055342 + 0.15979486615552821 + 0.15979930955148963 + 0.15980375305844219 + 0.15980819667638999 + 0.15981264040533708 + 0.15981708424528754 + 0.15982152819624623 + 0.15982597225821668 + 0.15983041643120355 + 0.15983486071521091 + 0.15983930511024283 + 0.15984374961630379 + 0.15984819423339777 + 0.15985263896152926 + 0.15985708380070227 + 0.15986152875092077 + 0.15986597381218953 + 0.15987041898451251 + 0.15987486426789374 + 0.1598793096623379 + 0.15988375516784886 + 0.15988820078443089 + 0.1598926465120882 + 0.15989709235082497 + 0.1599015383006456 + 0.15990598436155423 + 0.15991043053355508 + 0.15991487681665228 + 0.15991932321085031 + 0.15992376971615277 + 0.15992821633256471 + 0.15993266306008977 + 0.15993710989873222 + 0.15994155684849667 + 0.15994600390938696 + 0.1599504510814074 + 0.15995489836456225 + 0.15995934575885573 + 0.15996379326429208 + 0.15996824088087544 + 0.15997268860861025 + 0.15997713644750042 + 0.15998158439755025 + 0.15998603245876447 + 0.15999048063114635 + 0.15999492891470077 + 0.15999937730943178 + 0.16000382581534392 + 0.16000827443244095 + 0.16001272316072726 + 0.16001717200020707 + 0.16002162095088462 + 0.16002607001276412 + 0.16003051918585001 + 0.16003496847014598 + 0.16003941786565698 + 0.16004386737238674 + 0.16004831699033939 + 0.16005276671951948 + 0.16005721655993108 + 0.16006166651157852 + 0.1600661165744659 + 0.16007056674859738 + 0.16007501703397745 + 0.16007946743061013 + 0.16008391793849974 + 0.16008836855765043 + 0.16009281928806623 + 0.16009727012975211 + 0.16010172108271137 + 0.16010617214694878 + 0.16011062332246856 + 0.16011507460927482 + 0.16011952600737153 + 0.16012397751676336 + 0.16012842913745431 + 0.16013288086944877 + 0.16013733271275074 + 0.16014178466736437 + 0.16014623673329426 + 0.16015068891054454 + 0.16015514119911928 + 0.16015959359902274 + 0.16016404611025925 + 0.16016849873283284 + 0.16017295146674806 + 0.16017740431200864 + 0.16018185726861925 + 0.16018631033658431 + 0.16019076351590747 + 0.16019521680659321 + 0.16019967020864576 + 0.16020412372206946 + 0.16020857734686828 + 0.1602130310830466 + 0.16021748493060881 + 0.16022193888955902 + 0.16022639295990132 + 0.16023084714164001 + 0.16023530143477963 + 0.16023975583932379 + 0.16024421035527728 + 0.1602486649826442 + 0.16025311972142867 + 0.16025757457163481 + 0.16026202953326707 + 0.16026648460632967 + 0.16027093979082674 + 0.16027539508676253 + 0.16027985049414134 + 0.16028430601296745 + 0.16028876164324496 + 0.16029321738497823 + 0.16029767323817132 + 0.16030212920282855 + 0.16030658527895414 + 0.16031104146655253 + 0.16031549776562765 + 0.16031995417618397 + 0.16032441069822548 + 0.16032886733175644 + 0.16033332407678122 + 0.16033778093330411 + 0.16034223790132915 + 0.1603466949808609 + 0.16035115217190338 + 0.1603556094744607 + 0.16036006688853721 + 0.16036452441413721 + 0.16036898205126485 + 0.1603734397999243 + 0.16037789766012009 + 0.16038235563185613 + 0.16038681371513686 + 0.16039127190996624 + 0.16039573021634906 + 0.16040018863428895 + 0.1604046471637903 + 0.16040910580485773 + 0.16041356455749514 + 0.16041802342170683 + 0.16042248239749687 + 0.16042694148486975 + 0.16043140068382955 + 0.16043585999438062 + 0.16044031941652726 + 0.16044477895027362 + 0.16044923859562382 + 0.16045369835258222 + 0.16045815822115286 + 0.16046261820134039 + 0.16046707829314877 + 0.16047153849658219 + 0.16047599881164523 + 0.1604804592383417 + 0.16048491977667606 + 0.16048938042665256 + 0.1604938411882752 + 0.16049830206154869 + 0.1605027630464769 + 0.16050722414306406 + 0.16051168535131444 + 0.16051614667123265 + 0.16052060810282259 + 0.16052506964608831 + 0.16052953130103451 + 0.16053399306766522 + 0.16053845494598445 + 0.16054291693599684 + 0.16054737903770633 + 0.16055184125111749 + 0.16055630357623421 + 0.16056076601306105 + 0.16056522856160188 + 0.16056969122186129 + 0.16057415399384337 + 0.16057861687755215 + 0.16058307987299242 + 0.16058754298016803 + 0.1605920061990832 + 0.16059646952974238 + 0.16060093297214958 + 0.16060539652630912 + 0.16060986019222556 + 0.16061432396990263 + 0.16061878785934497 + 0.1606232518605567 + 0.16062771597354186 + 0.16063218019830494 + 0.1606366445348501 + 0.16064110898318165 + 0.16064557354330378 + 0.16065003821522086 + 0.16065450299893705 + 0.16065896789445622 + 0.16066343290178323 + 0.16066789802092199 + 0.16067236325187698 + 0.16067682859465207 + 0.1606812940492518 + 0.16068575961568032 + 0.16069022529394195 + 0.1606946910840408 + 0.16069915698598111 + 0.16070362299976748 + 0.16070808912540363 + 0.16071255536289411 + 0.16071702171224322 + 0.16072148817345511 + 0.16072595474653414 + 0.16073042143148419 + 0.16073488822830997 + 0.16073935513701551 + 0.16074382215760494 + 0.16074828929008272 + 0.16075275653445301 + 0.16075722389072011 + 0.16076169135888824 + 0.16076615893896171 + 0.16077062663094474 + 0.16077509443484134 + 0.16077956235065607 + 0.16078403037839303 + 0.16078849851805654 + 0.16079296676965082 + 0.16079743513317998 + 0.16080190360864868 + 0.16080637219606075 + 0.16081084089542069 + 0.16081530970673272 + 0.16081977863000088 + 0.16082424766522965 + 0.16082871681242311 + 0.16083318607158556 + 0.16083765544272149 + 0.1608421249258348 + 0.16084659452093014 + 0.16085106422801113 + 0.16085553404708261 + 0.16086000397814884 + 0.16086447402121368 + 0.16086894417628161 + 0.16087341444335673 + 0.16087788482244361 + 0.16088235531354617 + 0.16088682591666881 + 0.16089129663181581 + 0.16089576745899151 + 0.16090023839819995 + 0.16090470944944538 + 0.16090918061273218 + 0.16091365188806467 + 0.16091812327544705 + 0.16092259477488338 + 0.16092706638637819 + 0.16093153810993555 + 0.16093600994555987 + 0.16094048189325516 + 0.16094495395302588 + 0.16094942612487625 + 0.16095389840881044 + 0.16095837080483308 + 0.16096284331294783 + 0.16096731593315938 + 0.16097178866547174 + 0.16097626150988928 + 0.16098073446641642 + 0.16098520753505716 + 0.16098968071581579 + 0.16099415400869665 + 0.16099862741370383 + 0.16100310093084211 + 0.16100757456011516 + 0.16101204830152735 + 0.16101652215508311 + 0.1610209961207868 + 0.1610254701986423 + 0.16102994438865426 + 0.16103441869082644 + 0.16103889310516356 + 0.16104336763166988 + 0.16104784227034938 + 0.16105231702120645 + 0.16105679188424527 + 0.16106126685947045 + 0.16106574194688567 + 0.16107021714649561 + 0.16107469245830458 + 0.16107916788231635 + 0.16108364341853576 + 0.16108811906696657 + 0.16109259482761348 + 0.16109707070048068 + 0.16110154668557208 + 0.16110602278289224 + 0.16111049899244537 + 0.16111497531423594 + 0.16111945174826761 + 0.16112392829454517 + 0.16112840495307293 + 0.16113288172385462 + 0.16113735860689513 + 0.16114183560219819 + 0.16114631270976842 + 0.16115078992961002 + 0.16115526726172713 + 0.16115974470612396 + 0.16116422226280511 + 0.16116869993177455 + 0.16117317771303674 + 0.16117765560659555 + 0.16118213361245576 + 0.16118661173062138 + 0.1611910899610966 + 0.16119556830388573 + 0.16120004675899324 + 0.1612045253264231 + 0.16120900400617982 + 0.16121348279826742 + 0.1612179617026904 + 0.16122244071945285 + 0.16122691984855908 + 0.16123139909001358 + 0.16123587844382034 + 0.16124035790998367 + 0.16124483748850779 + 0.16124931717939728 + 0.16125379698265602 + 0.16125827689828845 + 0.16126275692629879 + 0.16126723706669127 + 0.16127171731947035 + 0.16127619768464013 + 0.16128067816220484 + 0.16128515875216903 + 0.1612896394545367 + 0.16129412026931211 + 0.16129860119649952 + 0.16130308223610346 + 0.16130756338812791 + 0.16131204465257742 + 0.16131652602945593 + 0.16132100751876788 + 0.16132548912051767 + 0.16132997083470915 + 0.16133445266134702 + 0.16133893460043547 + 0.16134341665197854 + 0.16134789881598077 + 0.16135238109244607 + 0.16135686348137937 + 0.16136134598278415 + 0.16136582859666496 + 0.16137031132302654 + 0.1613747941618727 + 0.16137927711320768 + 0.1613837601770359 + 0.16138824335336174 + 0.16139272664218907 + 0.16139721004352259 + 0.16140169355736619 + 0.16140617718372463 + 0.16141066092260195 + 0.16141514477400215 + 0.16141962873792975 + 0.16142411281438906 + 0.16142859700338436 + 0.16143308130491979 + 0.16143756571899964 + 0.16144205024562822 + 0.16144653488481003 + 0.16145101963654887 + 0.16145550450084936 + 0.16145998947771578 + 0.16146447456715227 + 0.16146895976916292 + 0.16147344508375253 + 0.1614779305109251 + 0.16148241605068459 + 0.1614869017030359 + 0.16149138746798261 + 0.16149587334552964 + 0.16150035933568083 + 0.16150484543844074 + 0.16150933165381343 + 0.16151381798180334 + 0.16151830442241441 + 0.16152279097565148 + 0.16152727764151842 + 0.16153176442001943 + 0.16153625131115915 + 0.16154073831494148 + 0.16154522543137109 + 0.16154971266045198 + 0.16155420000218848 + 0.16155868745658483 + 0.16156317502364537 + 0.16156766270337436 + 0.161572150495776 + 0.16157663840085484 + 0.16158112641861488 + 0.16158561454906059 + 0.16159010279219607 + 0.16159459114802566 + 0.16159907961655365 + 0.16160356819778424 + 0.16160805689172178 + 0.16161254569837066 + 0.1616170346177353 + 0.16162152364981938 + 0.1616260127946276 + 0.16163050205216434 + 0.16163499142243351 + 0.16163948090543978 + 0.16164397050118728 + 0.1616484602096801 + 0.16165295003092262 + 0.16165743996491935 + 0.16166193001167439 + 0.16166642017119207 + 0.16167091044347637 + 0.16167540082853199 + 0.16167989132636315 + 0.16168438193697385 + 0.16168887266036869 + 0.16169336349655192 + 0.16169785444552762 + 0.1617023455073 + 0.16170683668187374 + 0.16171132796925283 + 0.16171581936944154 + 0.16172031088244446 + 0.1617248025082654 + 0.16172929424690918 + 0.1617337860983796 + 0.16173827806268118 + 0.16174277013981822 + 0.16174726232979478 + 0.16175175463261546 + 0.1617562470482842 + 0.16176073957680565 + 0.16176523221818406 + 0.1617697249724234 + 0.16177421783952822 + 0.16177871081950249 + 0.16178320391235093 + 0.1617876971180775 + 0.1617921904366868 + 0.16179668386818266 + 0.16180117741256986 + 0.16180567106985233 + 0.16181016484003466 + 0.16181465872312065 + 0.16181915271911509 + 0.161823646828022 + 0.16182814104984572 + 0.16183263538459075 + 0.16183712983226103 + 0.1618416243928609 + 0.16184611906639482 + 0.161850613852867 + 0.16185510875228171 + 0.16185960376464309 + 0.16186409888995598 + 0.16186859412822402 + 0.16187308947945198 + 0.16187758494364371 + 0.16188208052080358 + 0.16188657621093633 + 0.16189107201404584 + 0.16189556793013635 + 0.16190006395921244 + 0.16190456010127829 + 0.16190905635633818 + 0.16191355272439625 + 0.16191804920545691 + 0.16192254579952434 + 0.16192704250660325 + 0.16193153932669724 + 0.16193603625981129 + 0.1619405333059494 + 0.1619450304651156 + 0.16194952773731466 + 0.16195402512255058 + 0.16195852262082769 + 0.16196302023215026 + 0.16196751795652251 + 0.16197201579394907 + 0.16197651374443375 + 0.16198101180798138 + 0.16198550998459582 + 0.16199000827428137 + 0.16199450667704285 + 0.16199900519288365 + 0.16200350382180906 + 0.16200800256382264 + 0.16201250141892889 + 0.16201700038713232 + 0.16202149946843708 + 0.16202599866284725 + 0.16203049797036737 + 0.16203499739100183 + 0.16203949692475456 + 0.16204399657163016 + 0.16204849633163271 + 0.1620529962047669 + 0.16205749619103646 + 0.16206199629044613 + 0.16206649650300006 + 0.16207099682870241 + 0.16207549726755774 + 0.16207999781957 + 0.16208449848474385 + 0.16208899926308337 + 0.16209350015459292 + 0.16209800115927675 + 0.16210250227713935 + 0.16210700350818477 + 0.16211150485241738 + 0.1621160063098413 + 0.1621205078804614 + 0.16212500956428116 + 0.16212951136130585 + 0.16213401327153878 + 0.16213851529498485 + 0.16214301743164813 + 0.16214751968153315 + 0.16215202204464413 + 0.16215652452098503 + 0.16216102711056049 + 0.16216552981337479 + 0.16217003262943222 + 0.1621745355587369 + 0.16217903860129326 + 0.16218354175710567 + 0.16218804502617842 + 0.16219254840851574 + 0.16219705190412173 + 0.16220155551300092 + 0.16220605923515791 + 0.16221056307059634 + 0.16221506701932092 + 0.16221957108133614 + 0.16222407525664562 + 0.16222857954525427 + 0.16223308394716615 + 0.16223758846238556 + 0.16224209309091711 + 0.16224659783276449 + 0.16225110268793275 + 0.16225560765642558 + 0.16226011273824742 + 0.16226461793340285 + 0.1622691232418958 + 0.1622736286637308 + 0.16227813419891213 + 0.16228263984744393 + 0.16228714560933058 + 0.16229165148457661 + 0.16229615747318615 + 0.16230066357516368 + 0.16230516979051293 + 0.1623096761192388 + 0.16231418256134542 + 0.162318689116837 + 0.16232319578571794 + 0.1623277025679925 + 0.16233220946366486 + 0.16233671647273978 + 0.1623412235952211 + 0.16234573083111317 + 0.16235023818042063 + 0.16235474564314736 + 0.16235925321929795 + 0.16236376090887655 + 0.16236826871188764 + 0.16237277662833532 + 0.16237728465822404 + 0.16238179280155812 + 0.1623863010583417 + 0.16239080942857909 + 0.16239531791227507 + 0.16239982650943319 + 0.16240433522005834 + 0.16240884404415459 + 0.16241335298172641 + 0.16241786203277764 + 0.16242237119731331 + 0.16242688047533715 + 0.16243138986685379 + 0.16243589937186725 + 0.16244040899038209 + 0.16244491872240258 + 0.16244942856793301 + 0.16245393852697765 + 0.16245844859954073 + 0.16246295878562694 + 0.16246746908523987 + 0.16247197949838471 + 0.16247649002506484 + 0.16248100066528531 + 0.16248551141905024 + 0.16249002228636383 + 0.16249453326723018 + 0.16249904436165422 + 0.16250355556963966 + 0.16250806689119121 + 0.16251257832631286 + 0.16251708987500901 + 0.16252160153728426 + 0.16252611331314265 + 0.16253062520258826 + 0.16253513720562596 + 0.16253964932225984 + 0.16254416155249404 + 0.16254867389633285 + 0.16255318635378097 + 0.16255769892484218 + 0.16256221160952117 + 0.16256672440782238 + 0.16257123731974968 + 0.16257575034530752 + 0.16258026348450047 + 0.16258477673733263 + 0.16258929010380835 + 0.16259380358393197 + 0.16259831717770784 + 0.16260283088514013 + 0.16260734470623325 + 0.16261185864099154 + 0.16261637268941923 + 0.16262088685152057 + 0.16262540112730026 + 0.16262991551676206 + 0.16263443001991074 + 0.16263894463675044 + 0.16264345936728561 + 0.16264797421152014 + 0.16265248916945885 + 0.16265700424110577 + 0.16266151942646509 + 0.16266603472554156 + 0.16267055013833939 + 0.16267506566486253 + 0.16267958130511576 + 0.162684097059103 + 0.16268861292682898 + 0.16269312890829737 + 0.16269764500351333 + 0.1627021612124803 + 0.16270667753520349 + 0.16271119397168651 + 0.16271571052193393 + 0.16272022718595033 + 0.16272474396373954 + 0.16272926085530603 + 0.16273377786065449 + 0.16273829497978889 + 0.16274281221271336 + 0.16274732955943272 + 0.16275184701995102 + 0.16275636459427256 + 0.16276088228240176 + 0.1627654000843427 + 0.16276991800009999 + 0.16277443602967784 + 0.16277895417308072 + 0.16278347243031271 + 0.1627879908013781 + 0.16279250928628153 + 0.1627970278850269 + 0.16280154659761889 + 0.16280606542406179 + 0.16281058436435966 + 0.16281510341851688 + 0.16281962258653807 + 0.16282414186842728 + 0.16282866126418896 + 0.16283318077382739 + 0.16283770039734688 + 0.16284222013475158 + 0.16284673998604629 + 0.16285125995123489 + 0.16285578003032172 + 0.16286030022331136 + 0.16286482053020798 + 0.16286934095101593 + 0.16287386148573935 + 0.16287838213438308 + 0.16288290289695082 + 0.1628874237734472 + 0.16289194476387664 + 0.16289646586824336 + 0.16290098708655176 + 0.16290550841880572 + 0.16291002986501016 + 0.16291455142516931 + 0.16291907309928713 + 0.16292359488736843 + 0.16292811678941688 + 0.1629326388054374 + 0.16293716093543428 + 0.16294168317941163 + 0.16294620553737357 + 0.16295072800932506 + 0.16295525059526966 + 0.16295977329521241 + 0.16296429610915719 + 0.1629688190371083 + 0.16297334207907041 + 0.16297786523504768 + 0.16298238850504443 + 0.16298691188906494 + 0.16299143538711355 + 0.16299595899919472 + 0.16300048272531242 + 0.1630050065654714 + 0.16300953051967568 + 0.16301405458792995 + 0.16301857877023807 + 0.16302310306660489 + 0.16302762747703423 + 0.16303215200153071 + 0.16303667664009869 + 0.16304120139274239 + 0.16304572625946595 + 0.16305025124027431 + 0.16305477633517096 + 0.16305930154416098 + 0.16306382686724827 + 0.16306835230443734 + 0.16307287785573246 + 0.16307740352113798 + 0.16308192930065821 + 0.16308645519429749 + 0.16309098120206 + 0.16309550732395031 + 0.16310003355997288 + 0.16310455991013154 + 0.16310908637443094 + 0.16311361295287555 + 0.16311813964546948 + 0.1631226664522171 + 0.16312719337312259 + 0.16313172040819077 + 0.16313624755742534 + 0.16314077482083117 + 0.16314530219841233 + 0.16314982969017308 + 0.16315435729611794 + 0.16315888501625117 + 0.16316341285057712 + 0.16316794079910013 + 0.16317246886182446 + 0.16317699703875457 + 0.16318152532989474 + 0.16318605373524911 + 0.1631905822548223 + 0.1631951108886186 + 0.1631996396366423 + 0.16320416849889763 + 0.16320869747538905 + 0.16321322656612089 + 0.16321775577109765 + 0.16322228509032305 + 0.16322681452380211 + 0.16323134407153878 + 0.16323587373353779 + 0.16324040350980298 + 0.16324493340033913 + 0.16324946340515012 + 0.16325399352424053 + 0.16325852375761493 + 0.16326305410527728 + 0.16326758456723206 + 0.16327211514348353 + 0.16327664583403628 + 0.16328117663889452 + 0.16328570755806238 + 0.16329023859154437 + 0.16329476973934509 + 0.16329930100146833 + 0.16330383237791907 + 0.16330836386870104 + 0.16331289547381875 + 0.16331742719327666 + 0.16332195902707897 + 0.16332649097523053 + 0.16333102303773486 + 0.16333555521459686 + 0.16334008750582094 + 0.16334461991141097 + 0.16334915243137163 + 0.16335368506570716 + 0.16335821781442192 + 0.16336275067752021 + 0.16336728365500652 + 0.16337181674688511 + 0.16337634995316005 + 0.16338088327383612 + 0.16338541670891743 + 0.16338995025840836 + 0.16339448392231334 + 0.16339901770063664 + 0.16340355159338243 + 0.16340808560055539 + 0.16341261972215951 + 0.16341715395819945 + 0.1634216883086792 + 0.16342622277360358 + 0.16343075735297644 + 0.16343529204680254 + 0.16343982685508587 + 0.16344436177783112 + 0.16344889681504218 + 0.16345343196672391 + 0.16345796723288039 + 0.163462502613516 + 0.16346703810863511 + 0.16347157371824184 + 0.16347610944234084 + 0.16348064528093645 + 0.16348518123403272 + 0.16348971730163425 + 0.16349425348374549 + 0.16349878978037027 + 0.16350332619151359 + 0.16350786271717943 + 0.16351239935737205 + 0.16351693611209606 + 0.16352147298135575 + 0.16352600996515521 + 0.16353054706349907 + 0.1635350842763918 + 0.16353962160383714 + 0.16354415904584016 + 0.16354869660240487 + 0.16355323427353541 + 0.16355777205923641 + 0.16356230995951232 + 0.16356684797436721 + 0.16357138610380551 + 0.16357592434783153 + 0.16358046270644996 + 0.16358500117966474 + 0.16358953976748042 + 0.16359407846990118 + 0.16359861728693159 + 0.16360315621857582 + 0.16360769526483826 + 0.16361223442572334 + 0.16361677370123551 + 0.16362131309137895 + 0.16362585259615792 + 0.16363039221557685 + 0.16363493194964007 + 0.16363947179835225 + 0.16364401176171717 + 0.16364855183973981 + 0.16365309203242395 + 0.16365763233977429 + 0.16366217276179512 + 0.1636667132984907 + 0.16367125394986531 + 0.16367579471592356 + 0.16368033559666983 + 0.16368487659210806 + 0.16368941770224305 + 0.163693958927079 + 0.16369850026661997 + 0.16370304172087088 + 0.16370758328983562 + 0.16371212497351872 + 0.16371666677192451 + 0.16372120868505735 + 0.16372575071292148 + 0.16373029285552143 + 0.16373483511286169 + 0.16373937748494624 + 0.1637439199717797 + 0.16374846257336631 + 0.16375300528971046 + 0.16375754812081644 + 0.1637620910666886 + 0.16376663412733147 + 0.1637711773027494 + 0.16377572059294643 + 0.16378026399792725 + 0.163784807517696 + 0.16378935115225723 + 0.163793894901615 + 0.16379843876577405 + 0.16380298274473865 + 0.16380752683851282 + 0.16381207104710147 + 0.16381661537050823 + 0.16382115980873824 + 0.16382570436179519 + 0.16383024902968399 + 0.16383479381240856 + 0.16383933870997358 + 0.16384388372238332 + 0.16384842884964185 + 0.16385297409175387 + 0.16385751944872382 + 0.16386206492055572 + 0.16386661050725418 + 0.16387115620882328 + 0.16387570202526783 + 0.16388024795659178 + 0.16388479400279971 + 0.16388934016389578 + 0.16389388643988451 + 0.16389843283077021 + 0.1639029793365574 + 0.16390752595725031 + 0.16391207269285316 + 0.16391661954337058 + 0.16392116650880661 + 0.16392571358916594 + 0.16393026078445283 + 0.16393480809467126 + 0.16393935551982625 + 0.1639439030599219 + 0.16394845071496256 + 0.16395299848495229 + 0.16395754636989582 + 0.16396209436979742 + 0.16396664248466153 + 0.1639711907144922 + 0.16397573905929413 + 0.16398028751907173 + 0.16398483609382894 + 0.16398938478357056 + 0.16399393358830058 + 0.16399848250802374 + 0.16400303154274415 + 0.16400758069246626 + 0.16401212995719466 + 0.1640166793369332 + 0.16402122883168643 + 0.16402577844145907 + 0.1640303281662551 + 0.16403487800607908 + 0.16403942796093554 + 0.16404397803082821 + 0.1640485282157621 + 0.16405307851574122 + 0.16405762893077022 + 0.16406217946085316 + 0.16406673010599451 + 0.16407128086619871 + 0.16407583174147003 + 0.16408038273181319 + 0.16408493383723186 + 0.16408948505773113 + 0.16409403639331502 + 0.16409858784398776 + 0.1641031394097541 + 0.16410769109061812 + 0.1641122428865841 + 0.16411679479765667 + 0.16412134682384014 + 0.16412589896513874 + 0.16413045122155717 + 0.16413500359309946 + 0.16413955607977002 + 0.16414410868157323 + 0.1641486613985137 + 0.16415321423059545 + 0.16415776717782304 + 0.16416232024020083 + 0.16416687341773342 + 0.16417142671042459 + 0.16417598011827914 + 0.16418053364130153 + 0.16418508727949593 + 0.16418964103286654 + 0.16419419490141793 + 0.16419874888515468 + 0.16420330298408084 + 0.1642078571982008 + 0.16421241152751936 + 0.16421696597204027 + 0.16422152053176839 + 0.16422607520670765 + 0.16423062999686275 + 0.16423518490223815 + 0.16423973992283789 + 0.16424429505866664 + 0.16424885030972852 + 0.16425340567602811 + 0.1642579611575696 + 0.16426251675435741 + 0.16426707246639624 + 0.16427162829369002 + 0.16427618423624321 + 0.16428074029406028 + 0.16428529646714585 + 0.16428985275550373 + 0.16429440915913862 + 0.16429896567805505 + 0.1643035223122572 + 0.16430807906174938 + 0.16431263592653622 + 0.1643171929066217 + 0.16432175000201046 + 0.16432630721270688 + 0.16433086453871523 + 0.16433542198004028 + 0.16433997953668578 + 0.16434453720865652 + 0.16434909499595668 + 0.16435365289859077 + 0.16435821091656325 + 0.16436276904987823 + 0.16436732729854026 + 0.16437188566255365 + 0.16437644414192279 + 0.16438100273665213 + 0.16438556144674579 + 0.16439012027220873 + 0.16439467921304474 + 0.16439923826925837 + 0.16440379744085412 + 0.16440835672783627 + 0.16441291613020897 + 0.1644174756479774 + 0.16442203528114491 + 0.1644265950297166 + 0.16443115489369656 + 0.16443571487308911 + 0.16444027496789893 + 0.16444483517813011 + 0.16444939550378712 + 0.16445395594487433 + 0.16445851650139631 + 0.16446307717335695 + 0.16446763796076119 + 0.164472198863613 + 0.16447675988191723 + 0.16448132101567783 + 0.16448588226489905 + 0.16449044362958584 + 0.16449500510974227 + 0.16449956670537266 + 0.16450412841648149 + 0.16450869024307324 + 0.164513252185152 + 0.16451781424272238 + 0.16452237641578879 + 0.16452693870435531 + 0.16453150110842676 + 0.1645360636280073 + 0.16454062626310129 + 0.16454518901371312 + 0.16454975187984722 + 0.16455431486150801 + 0.16455887795869967 + 0.16456344117142682 + 0.16456800449969397 + 0.16457256794350508 + 0.16457713150286474 + 0.16458169517777749 + 0.1645862589682473 + 0.16459082287427895 + 0.16459538689587677 + 0.16459995103304506 + 0.16460451528578823 + 0.16460907965411073 + 0.16461364413801677 + 0.16461820873751104 + 0.16462277345259754 + 0.16462733828328086 + 0.16463190322956553 + 0.16463646829145553 + 0.1646410334689557 + 0.16464559876207008 + 0.16465016417080333 + 0.16465472969515996 + 0.16465929533514367 + 0.16466386109075953 + 0.16466842696201164 + 0.16467299294890433 + 0.16467755905144249 + 0.16468212526962972 + 0.16468669160347096 + 0.1646912580529703 + 0.1646958246181324 + 0.16470039129896152 + 0.16470495809546204 + 0.16470952500763855 + 0.16471409203549497 + 0.16471865917903605 + 0.1647232264382662 + 0.16472779381318964 + 0.16473236130381097 + 0.16473692891013422 + 0.16474149663216422 + 0.16474606446990514 + 0.1647506324233613 + 0.16475520049253725 + 0.16475976867743714 + 0.16476433697806558 + 0.16476890539442698 + 0.1647734739265258 + 0.16477804257436598 + 0.16478261133795252 + 0.16478718021728944 + 0.16479174921238107 + 0.16479631832323208 + 0.16480088754984676 + 0.1648054568922295 + 0.16481002635038461 + 0.16481459592431655 + 0.16481916561402976 + 0.16482373541952841 + 0.16482830534081727 + 0.16483287537790048 + 0.16483744553078239 + 0.16484201579946747 + 0.16484658618396039 + 0.16485115668426487 + 0.16485572730038611 + 0.16486029803232796 + 0.16486486888009491 + 0.16486943984369154 + 0.16487401092312221 + 0.16487858211839101 + 0.16488315342950263 + 0.16488772485646147 + 0.16489229639927183 + 0.16489686805793816 + 0.16490143983246489 + 0.16490601172285613 + 0.16491058372911677 + 0.16491515585125072 + 0.16491972808926272 + 0.16492430044315701 + 0.16492887291293812 + 0.16493344549861033 + 0.16493801820017798 + 0.16494259101764569 + 0.16494716395101749 + 0.16495173700029805 + 0.16495631016549189 + 0.16496088344660309 + 0.16496545684363634 + 0.16497003035659591 + 0.16497460398548602 + 0.1649791777303114 + 0.16498375159107609 + 0.164988325567785 + 0.16499289966044209 + 0.16499747386905192 + 0.16500204819361877 + 0.16500662263414714 + 0.16501119719064153 + 0.16501577186310626 + 0.16502034665154544 + 0.1650249215559641 + 0.16502949657636615 + 0.16503407171275605 + 0.16503864696513834 + 0.16504322233351729 + 0.1650477978178975 + 0.16505237341828308 + 0.16505694913467889 + 0.1650615249670887 + 0.16506610091551752 + 0.16507067697996933 + 0.16507525316044885 + 0.16507982945696015 + 0.16508440586950787 + 0.16508898239809647 + 0.16509355904272999 + 0.16509813580341329 + 0.1651027126801505 + 0.16510728967294605 + 0.16511186678180434 + 0.1651164440067299 + 0.16512102134772713 + 0.16512559880480046 + 0.16513017637795396 + 0.16513475406719233 + 0.16513933187251986 + 0.16514390979394108 + 0.1651484878314603 + 0.16515306598508206 + 0.16515764425481061 + 0.16516222264065031 + 0.16516680114260587 + 0.16517137976068119 + 0.16517595849488129 + 0.16518053734521013 + 0.16518511631167215 + 0.165189695394272 + 0.16519427459301395 + 0.16519885390790226 + 0.16520343333894177 + 0.16520801288613626 + 0.16521259254949067 + 0.16521717232900934 + 0.16522175222469629 + 0.16522633223655642 + 0.16523091236459375 + 0.1652354926088129 + 0.16524007296921842 + 0.16524465344581427 + 0.16524923403860534 + 0.16525381474759562 + 0.16525839557278998 + 0.16526297651419228 + 0.16526755757180739 + 0.16527213874563967 + 0.16527672003569335 + 0.16528130144197273 + 0.16528588296448266 + 0.16529046460322702 + 0.16529504635821077 + 0.16529962822943783 + 0.16530421021691308 + 0.1653087923206405 + 0.1653133745406247 + 0.16531795687687006 + 0.16532253932938101 + 0.16532712189816173 + 0.16533170458321733 + 0.16533628738455133 + 0.16534087030216879 + 0.16534545333607376 + 0.165350036486271 + 0.16535461975276458 + 0.16535920313555905 + 0.16536378663465898 + 0.16536837025006851 + 0.16537295398179219 + 0.16537753782983444 + 0.16538212179419962 + 0.16538670587489213 + 0.16539129007191639 + 0.16539587438527703 + 0.16540045881497822 + 0.16540504336102446 + 0.16540962802342007 + 0.16541421280216972 + 0.16541879769727744 + 0.16542338270874804 + 0.16542796783658564 + 0.16543255308079491 + 0.16543713844138025 + 0.16544172391834572 + 0.16544630951169589 + 0.16545089522143561 + 0.16545548104756866 + 0.16546006699009974 + 0.16546465304903349 + 0.16546923922437384 + 0.16547382551612566 + 0.16547841192429327 + 0.1654829984488809 + 0.16548758508989317 + 0.16549217184733428 + 0.16549675872120881 + 0.16550134571152117 + 0.16550593281827572 + 0.16551052004147693 + 0.16551510738112934 + 0.16551969483723708 + 0.16552428240980463 + 0.16552887009883654 + 0.16553345790433754 + 0.16553804582631124 + 0.16554263386476287 + 0.16554722201969627 + 0.1655518102911161 + 0.16555639867902697 + 0.16556098718343301 + 0.16556557580433864 + 0.1655701645417485 + 0.16557475339566696 + 0.16557934236609814 + 0.1655839314530469 + 0.16558852065651741 + 0.16559310997651414 + 0.16559769941304156 + 0.16560228896610388 + 0.16560687863570592 + 0.16561146842185179 + 0.16561605832454601 + 0.16562064834379278 + 0.1656252384795969 + 0.16562982873196269 + 0.16563441910089435 + 0.16563900958639663 + 0.16564360018847374 + 0.1656481909071302 + 0.16565278174237014 + 0.16565737269419856 + 0.16566196376261949 + 0.16566655494763724 + 0.16567114624925658 + 0.16567573766748167 + 0.16568032920231715 + 0.16568492085376726 + 0.1656895126218364 + 0.16569410450652933 + 0.16569869650785019 + 0.16570328862580341 + 0.1657078808603934 + 0.16571247321162491 + 0.1657170656795019 + 0.16572165826402904 + 0.1657262509652106 + 0.16573084378305133 + 0.16573543671755533 + 0.16574002976872737 + 0.16574462293657136 + 0.1657492162210924 + 0.16575380962229438 + 0.16575840314018181 + 0.16576299677475922 + 0.1657675905260311 + 0.16577218439400185 + 0.1657767783786758 + 0.1657813724800575 + 0.16578596669815121 + 0.16579056103296164 + 0.16579515548449275 + 0.16579975005274966 + 0.16580434473773603 + 0.16580893953945691 + 0.16581353445791644 + 0.16581812949311911 + 0.1658227246450692 + 0.16582731991377153 + 0.16583191529923014 + 0.16583651080144957 + 0.1658411064204344 + 0.16584570215618882 + 0.16585029800871742 + 0.16585489397802466 + 0.16585949006411488 + 0.16586408626699256 + 0.1658686825866621 + 0.16587327902312787 + 0.16587787557639452 + 0.16588247224646638 + 0.16588706903334774 + 0.16589166593704324 + 0.16589626295755727 + 0.16590086009489402 + 0.16590545734905812 + 0.16591005472005413 + 0.16591465220788632 + 0.16591924981255918 + 0.16592384753407702 + 0.16592844537244444 + 0.1659330433276659 + 0.16593764139974565 + 0.16594223958868823 + 0.16594683789449818 + 0.16595143631717973 + 0.16595603485673741 + 0.16596063351317569 + 0.16596523228649893 + 0.16596983117671174 + 0.16597443018381819 + 0.1659790293078231 + 0.16598362854873086 + 0.16598822790654569 + 0.165992827381272 + 0.16599742697291461 + 0.16600202668147762 + 0.16600662650696557 + 0.1660112264493829 + 0.16601582650873406 + 0.16602042668502351 + 0.16602502697825566 + 0.16602962738843488 + 0.16603422791556574 + 0.16603882855965252 + 0.16604342932069971 + 0.16604803019871178 + 0.16605263119369332 + 0.16605723230564839 + 0.16606183353458201 + 0.16606643488049788 + 0.16607103634340128 + 0.16607563792329583 + 0.16608023962018637 + 0.16608484143407762 + 0.16608944336497347 + 0.1660940454128785 + 0.16609864757779741 + 0.16610324985973457 + 0.16610785225869429 + 0.16611245477468098 + 0.16611705740769925 + 0.16612166015775334 + 0.16612626302484801 + 0.16613086600898738 + 0.16613546911017604 + 0.16614007232841849 + 0.1661446756637189 + 0.16614927911608185 + 0.16615388268551212 + 0.1661584863720138 + 0.16616309017559108 + 0.16616769409624921 + 0.16617229813399173 + 0.16617690228882387 + 0.16618150656074945 + 0.16618611094977323 + 0.16619071545589978 + 0.16619532007913299 + 0.16619992481947807 + 0.16620452967693869 + 0.16620913465152004 + 0.1662137397432259 + 0.16621834495206134 + 0.16622295027803013 + 0.16622755572113723 + 0.16623216128138699 + 0.16623676695878398 + 0.1662413727533319 + 0.16624597866503621 + 0.16625058469390078 + 0.16625519083993012 + 0.16625979710312888 + 0.16626440348350122 + 0.16626900998105168 + 0.16627361659578493 + 0.16627822332770523 + 0.1662828301768168 + 0.16628743714312466 + 0.16629204422663274 + 0.1662966514273457 + 0.16630125874526816 + 0.1663058661804041 + 0.16631047373275862 + 0.16631508140233545 + 0.16631968918913947 + 0.16632429709317484 + 0.16632890511444653 + 0.16633351325295875 + 0.16633812150871552 + 0.16634272988172172 + 0.16634733837198182 + 0.16635194697950026 + 0.16635655570428132 + 0.16636116454632952 + 0.16636577350564954 + 0.16637038258224521 + 0.16637499177612156 + 0.16637960108728309 + 0.16638421051573382 + 0.16638882006147851 + 0.16639342972452134 + 0.16639803950486709 + 0.16640264940252017 + 0.16640725941748483 + 0.16641186954976545 + 0.16641647979936669 + 0.16642109016629314 + 0.16642570065054904 + 0.16643031125213881 + 0.16643492197106707 + 0.16643953280733792 + 0.16644414376095643 + 0.1664487548319265 + 0.16645336602025285 + 0.16645797732593981 + 0.166462588748992 + 0.16646720028941345 + 0.16647181194720931 + 0.16647642372238339 + 0.16648103561494068 + 0.16648564762488505 + 0.16649025975222131 + 0.16649487199695426 + 0.16649948435908765 + 0.16650409683862621 + 0.16650870943557453 + 0.166513322149937 + 0.16651793498171805 + 0.16652254793092217 + 0.16652716099755374 + 0.16653177418161738 + 0.16653638748311733 + 0.16654100090205814 + 0.16654561443844448 + 0.1665502280922804 + 0.1665548418635707 + 0.16655945575231967 + 0.16656406975853166 + 0.16656868388221152 + 0.16657329812336316 + 0.16657791248199166 + 0.16658252695810102 + 0.16658714155169588 + 0.16659175626278061 + 0.16659637109135977 + 0.16660098603743781 + 0.16660560110101899 + 0.16661021628210795 + 0.1666148315807093 + 0.16661944699682726 + 0.16662406253046635 + 0.16662867818163088 + 0.16663329395032578 + 0.16663790983655499 + 0.16664252584032321 + 0.16664714196163491 + 0.16665175820049449 + 0.16665637455690657 + 0.16666099103087539 + 0.16666560762240526 + 0.1666702243315013 + 0.16667484115816736 + 0.16667945810240822 + 0.16668407516422798 + 0.16668869234363165 + 0.16669330964062329 + 0.16669792705520739 + 0.16670254458738856 + 0.16670716223717127 + 0.16671178000455972 + 0.16671639788955861 + 0.16672101589217231 + 0.16672563401240542 + 0.16673025225026242 + 0.16673487060574749 + 0.1667394890788654 + 0.16674410766962042 + 0.16674872637801696 + 0.16675334520405996 + 0.16675796414775321 + 0.16676258320910162 + 0.16676720238810958 + 0.16677182168478152 + 0.16677644109912179 + 0.16678106063113501 + 0.16678568028082555 + 0.16679030004819817 + 0.16679491993325687 + 0.16679953993600646 + 0.16680416005645129 + 0.16680878029459562 + 0.16681340065044437 + 0.16681802112400176 + 0.16682264171527225 + 0.16682726242426013 + 0.16683188325097031 + 0.16683650419540685 + 0.16684112525757444 + 0.16684574643747754 + 0.16685036773512038 + 0.16685498915050784 + 0.16685961068364413 + 0.16686423233453371 + 0.16686885410318111 + 0.16687347598959076 + 0.16687809799376704 + 0.16688272011571481 + 0.16688734235543803 + 0.16689196471294146 + 0.16689658718822947 + 0.16690120978130657 + 0.16690583249217747 + 0.16691045532084625 + 0.16691507826731755 + 0.16691970133159578 + 0.16692432451368558 + 0.16692894781359138 + 0.16693357123131738 + 0.16693819476686833 + 0.1669428184202488 + 0.1669474421914629 + 0.16695206608051513 + 0.16695669008741032 + 0.16696131421215271 + 0.16696593845474697 + 0.16697056281519723 + 0.1669751872935081 + 0.16697981188968425 + 0.16698443660373 + 0.16698906143564973 + 0.16699368638544826 + 0.1669983114531296 + 0.16700293663869845 + 0.16700756194215929 + 0.16701218736351672 + 0.16701681290277501 + 0.16702143855993865 + 0.16702606433501224 + 0.1670306902280001 + 0.1670353162389068 + 0.16703994236773681 + 0.16704456861449463 + 0.1670491949791848 + 0.16705382146181169 + 0.16705844806237974 + 0.16706307478089344 + 0.16706770161735757 + 0.16707232857177598 + 0.16707695564415373 + 0.16708158283449509 + 0.1670862101428045 + 0.16709083756908646 + 0.16709546511334528 + 0.16710009277558605 + 0.16710472055581252 + 0.16710934845402953 + 0.16711397647024143 + 0.16711860460445271 + 0.16712323285666811 + 0.16712786122689166 + 0.16713248971512826 + 0.16713711832138217 + 0.16714174704565807 + 0.16714637588796016 + 0.16715100484829298 + 0.16715563392666116 + 0.16716026312306898 + 0.16716489243752111 + 0.16716952187002193 + 0.1671741514205759 + 0.16717878108918768 + 0.16718341087586139 + 0.16718804078060198 + 0.16719267080341368 + 0.16719730094430088 + 0.16720193120326812 + 0.16720656158032005 + 0.16721119207546092 + 0.16721582268869561 + 0.16722045342002809 + 0.16722508426946303 + 0.16722971523700517 + 0.1672343463226586 + 0.167238977526428 + 0.16724360884831782 + 0.16724824028833263 + 0.16725287184647683 + 0.16725750352275495 + 0.16726213531717141 + 0.16726676722973083 + 0.16727139926043746 + 0.16727603140929592 + 0.16728066367631078 + 0.16728529606148629 + 0.16728992856482713 + 0.16729456118633795 + 0.1672991939260231 + 0.16730382678388642 + 0.16730845975993344 + 0.16731309285416812 + 0.16731772606659492 + 0.16732235939721848 + 0.16732699284604308 + 0.16733162641307336 + 0.16733626009831409 + 0.16734089390176929 + 0.16734552782344336 + 0.16735016186334153 + 0.16735479602146752 + 0.1673594302978261 + 0.16736406469242171 + 0.16736869920525899 + 0.16737333383634229 + 0.16737796858567608 + 0.16738260345326492 + 0.16738723843911321 + 0.16739187354322568 + 0.16739650876560666 + 0.16740114410626059 + 0.16740577956519195 + 0.16741041514240532 + 0.16741505083790514 + 0.16741968665169588 + 0.16742432258378229 + 0.16742895863416835 + 0.16743359480285894 + 0.16743823108985842 + 0.16744286749517154 + 0.16744750401880229 + 0.16745214066075556 + 0.1674567774210356 + 0.16746141429964714 + 0.16746605129659461 + 0.16747068841188217 + 0.16747532564551482 + 0.1674799629974966 + 0.16748460046783253 + 0.16748923805652655 + 0.1674938757635836 + 0.16749851358900766 + 0.16750315153280385 + 0.16750778959497623 + 0.16751242777552947 + 0.16751706607446801 + 0.16752170449179601 + 0.16752634302751848 + 0.16753098168164005 + 0.16753562045416445 + 0.16754025934509695 + 0.16754489835444153 + 0.16754953748220297 + 0.16755417672838549 + 0.16755881609299375 + 0.16756345557603244 + 0.16756809517750604 + 0.16757273489741858 + 0.16757737473577486 + 0.16758201469257958 + 0.16758665476783685 + 0.16759129496155145 + 0.16759593527372763 + 0.16760057570437026 + 0.16760521625348332 + 0.16760985692107166 + 0.16761449770713999 + 0.16761913861169234 + 0.16762377963473341 + 0.16762842077626772 + 0.16763306203629966 + 0.16763770341483392 + 0.16764234491187488 + 0.16764698652742682 + 0.1676516282614948 + 0.1676562701140826 + 0.16766091208519537 + 0.16766555417483708 + 0.16767019638301278 + 0.16767483870972649 + 0.16767948115498321 + 0.16768412371878694 + 0.16768876640114233 + 0.16769340920205375 + 0.16769805212152616 + 0.16770269515956379 + 0.16770733831617093 + 0.16771198159135237 + 0.16771662498511258 + 0.16772126849745594 + 0.16772591212838708 + 0.16773055587791033 + 0.16773519974603043 + 0.16773984373275166 + 0.16774448783807858 + 0.16774913206201586 + 0.16775377640456762 + 0.16775842086573886 + 0.16776306544553385 + 0.16776771014395692 + 0.16777235496101284 + 0.16777699989670586 + 0.16778164495104084 + 0.16778629012402188 + 0.16779093541565396 + 0.16779558082594095 + 0.16780022635488795 + 0.16780487200249922 + 0.16780951776877912 + 0.1678141636537327 + 0.16781880965736365 + 0.16782345577967714 + 0.16782810202067736 + 0.16783274838036877 + 0.16783739485875618 + 0.16784204145584369 + 0.16784668817163617 + 0.16785133500613819 + 0.16785598195935361 + 0.16786062903128762 + 0.16786527622194455 + 0.16786992353132893 + 0.1678745709594448 + 0.16787921850629739 + 0.16788386617189072 + 0.16788851395622958 + 0.1678931618593183 + 0.16789780988116132 + 0.16790245802176329 + 0.1679071062811287 + 0.16791175465926217 + 0.16791640315616796 + 0.1679210517718509 + 0.1679257005063152 + 0.16793034935956547 + 0.16793499833160605 + 0.1679396474224418 + 0.16794429663207716 + 0.16794894596051643 + 0.16795359540776408 + 0.16795824497382494 + 0.1679628946587034 + 0.16796754446240375 + 0.16797219438493102 + 0.16797684442628896 + 0.16798149458648282 + 0.16798614486551655 + 0.16799079526339503 + 0.16799544578012254 + 0.16800009641570393 + 0.16800474717014333 + 0.16800939804344528 + 0.16801404903561448 + 0.1680187001466556 + 0.16802335137657273 + 0.16802800272537061 + 0.16803265419305366 + 0.16803730577962664 + 0.16804195748509376 + 0.16804660930945961 + 0.16805126125272885 + 0.16805591331490602 + 0.16806056549599527 + 0.16806521779600142 + 0.16806987021492906 + 0.16807452275278253 + 0.16807917540956635 + 0.16808382818528494 + 0.16808848107994304 + 0.16809313409354529 + 0.16809778722609575 + 0.16810244047759923 + 0.16810709384806011 + 0.1681117473374831 + 0.16811640094587271 + 0.16812105467323302 + 0.16812570851956923 + 0.16813036248488528 + 0.16813501656918603 + 0.1681396707724758 + 0.16814432509475927 + 0.16814897953604083 + 0.16815363409632517 + 0.16815828877561645 + 0.1681629435739195 + 0.16816759849123877 + 0.16817225352757897 + 0.16817690868294402 + 0.16818156395733927 + 0.16818621935076866 + 0.16819087486323661 + 0.16819553049474839 + 0.16820018624530744 + 0.16820484211491946 + 0.16820949810358787 + 0.1682141542113178 + 0.16821881043811393 + 0.16822346678398026 + 0.16822812324892158 + 0.16823277983294241 + 0.16823743653604722 + 0.1682420933582407 + 0.16824675029952707 + 0.16825140735991118 + 0.16825606453939745 + 0.16826072183799023 + 0.16826537925569407 + 0.16827003679251346 + 0.1682746944484533 + 0.16827935222351789 + 0.16828401011771163 + 0.16828866813103915 + 0.16829332626350507 + 0.16829798451511341 + 0.16830264288586938 + 0.16830730137577718 + 0.16831195998484125 + 0.16831661871306658 + 0.16832127756045703 + 0.16832593652701736 + 0.16833059561275227 + 0.1683352548176662 + 0.16833991414176377 + 0.16834457358504945 + 0.16834923314752734 + 0.16835389282920266 + 0.16835855263007954 + 0.16836321255016265 + 0.16836787258945635 + 0.16837253274796529 + 0.16837719302569393 + 0.16838185342264697 + 0.16838651393882853 + 0.16839117457424366 + 0.16839583532889654 + 0.16840049620279177 + 0.16840515719593396 + 0.16840981830832757 + 0.16841447953997732 + 0.16841914089088728 + 0.16842380236106241 + 0.16842846395050701 + 0.16843312565922577 + 0.16843778748722299 + 0.16844244943450346 + 0.1684471115010715 + 0.16845177368693179 + 0.16845643599208884 + 0.16846109841654711 + 0.1684657609603111 + 0.16847042362338552 + 0.1684750864057748 + 0.16847974930748347 + 0.16848441232851577 + 0.16848907546887684 + 0.1684937387285706 + 0.16849840210760203 + 0.16850306560597544 + 0.1685077292236955 + 0.16851239296076656 + 0.16851705681719317 + 0.16852172079298008 + 0.16852638488813165 + 0.16853104910265246 + 0.16853571343654714 + 0.16854037788981993 + 0.16854504246247531 + 0.16854970715451839 + 0.16855437196595321 + 0.16855903689678473 + 0.16856370194701684 + 0.16856836711665477 + 0.16857303240570243 + 0.16857769781416485 + 0.16858236334204624 + 0.16858702898935118 + 0.16859169475608432 + 0.16859636064225042 + 0.16860102664785356 + 0.16860569277289839 + 0.16861035901738963 + 0.16861502538133186 + 0.16861969186472917 + 0.16862435846758642 + 0.16862902518990822 + 0.16863369203169906 + 0.16863835899296337 + 0.16864302607370565 + 0.16864769327393064 + 0.16865236059364283 + 0.16865702803284657 + 0.16866169559154673 + 0.16866636326974738 + 0.16867103106745318 + 0.16867569898466922 + 0.16868036702139924 + 0.16868503517764849 + 0.16868970345342099 + 0.16869437184872152 + 0.16869904036355449 + 0.16870370899792442 + 0.16870837775183617 + 0.16871304662529396 + 0.1687177156183024 + 0.16872238473086607 + 0.16872705396298948 + 0.16873172331467728 + 0.16873639278593386 + 0.16874106237676376 + 0.16874573208717161 + 0.16875040191716192 + 0.1687550718667391 + 0.16875974193590812 + 0.16876441212467305 + 0.16876908243303859 + 0.16877375286100926 + 0.16877842340858965 + 0.16878309407578421 + 0.16878776486259772 + 0.16879243576903444 + 0.16879710679509913 + 0.16880177794079629 + 0.16880644920613033 + 0.16881112059110581 + 0.16881579209572747 + 0.16882046371999962 + 0.16882513546392691 + 0.1688298073275139 + 0.16883447931076506 + 0.16883915141368505 + 0.16884382363627842 + 0.16884849597854959 + 0.16885316844050305 + 0.1688578410221436 + 0.16886251372347569 + 0.16886718654450361 + 0.16887185948523231 + 0.16887653254566612 + 0.16888120572580964 + 0.16888587902566718 + 0.16889055244524365 + 0.16889522598454351 + 0.16889989964357097 + 0.16890457342233092 + 0.16890924732082796 + 0.16891392133906644 + 0.16891859547705101 + 0.16892326973478611 + 0.16892794411227649 + 0.16893261860952635 + 0.16893729322654041 + 0.16894196796332347 + 0.16894664281987967 + 0.16895131779621389 + 0.16895599289233076 + 0.16896066810823426 + 0.16896534344392938 + 0.16897001889942073 + 0.16897469447471272 + 0.16897937016980974 + 0.16898404598471642 + 0.16898872191943762 + 0.16899339797397753 + 0.16899807414834081 + 0.1690027504425318 + 0.16900742685655551 + 0.16901210339041642 + 0.16901678004411888 + 0.16902145681766723 + 0.16902613371106651 + 0.16903081072432091 + 0.16903548785743494 + 0.16904016511041364 + 0.16904484248326099 + 0.16904951997598192 + 0.16905419758858084 + 0.16905887532106212 + 0.16906355317343075 + 0.169068231145691 + 0.16907290923784737 + 0.16907758744990473 + 0.16908226578186716 + 0.16908694423373963 + 0.16909162280552653 + 0.1690963014972322 + 0.16910098030886173 + 0.16910565924041907 + 0.16911033829190911 + 0.16911501746333646 + 0.16911969675470548 + 0.169124376166021 + 0.16912905569728709 + 0.1691337353485087 + 0.16913841511969055 + 0.1691430950108366 + 0.16914777502195197 + 0.16915245515304095 + 0.16915713540410801 + 0.16916181577515793 + 0.16916649626619498 + 0.16917117687722411 + 0.16917585760824974 + 0.16918053845927622 + 0.16918521943030831 + 0.16918990052135047 + 0.16919458173240709 + 0.16919926306348332 + 0.16920394451458307 + 0.1692086260857113 + 0.16921330777687241 + 0.16921798958807097 + 0.16922267151931153 + 0.16922735357059851 + 0.16923203574193674 + 0.16923671803333071 + 0.16924140044478511 + 0.16924608297630395 + 0.1692507656278924 + 0.16925544839955484 + 0.16926013129129552 + 0.16926481430311946 + 0.16926949743503109 + 0.16927418068703445 + 0.16927886405913489 + 0.16928354755133682 + 0.16928823116364436 + 0.1692929148960621 + 0.16929759874859535 + 0.16930228272124767 + 0.16930696681402435 + 0.16931165102692969 + 0.16931633535996829 + 0.1693210198131446 + 0.16932570438646338 + 0.16933038907992892 + 0.16933507389354599 + 0.16933975882731922 + 0.16934444388125303 + 0.16934912905535185 + 0.16935381434962049 + 0.16935849976406359 + 0.16936318529868544 + 0.16936787095349071 + 0.16937255672848406 + 0.16937724262366999 + 0.16938192863905294 + 0.16938661477463771 + 0.16939130103042865 + 0.16939598740643041 + 0.16940067390264762 + 0.16940536051908481 + 0.16941004725574665 + 0.16941473411263727 + 0.16941942108976166 + 0.16942410818712428 + 0.16942879540472983 + 0.16943348274258255 + 0.16943817020068747 + 0.16944285777904852 + 0.16944754547767094 + 0.1694522332965589 + 0.16945692123571707 + 0.16946160929514983 + 0.16946629747486208 + 0.16947098577485822 + 0.16947567419514267 + 0.16948036273572042 + 0.16948505139659559 + 0.16948974017777313 + 0.16949442907925732 + 0.16949911810105281 + 0.16950380724316422 + 0.16950849650559607 + 0.16951318588835282 + 0.1695178753914395 + 0.16952256501485996 + 0.16952725475861941 + 0.16953194462272217 + 0.1695366346071728 + 0.16954132471197594 + 0.16954601493713581 + 0.16955070528265762 + 0.16955539574854531 + 0.16956008633480404 + 0.1695647770414378 + 0.16956946786845173 + 0.16957415881584989 + 0.16957884988363725 + 0.16958354107181797 + 0.16958823238039714 + 0.16959292380937893 + 0.16959761535876797 + 0.16960230702856915 + 0.16960699881878671 + 0.16961169072942511 + 0.16961638276048929 + 0.16962107491198369 + 0.1696257671839129 + 0.16963045957628139 + 0.16963515208909369 + 0.16963984472235472 + 0.16964453747606847 + 0.16964923035024013 + 0.169653923344874 + 0.16965861645997452 + 0.16966330969554649 + 0.1696680030515946 + 0.16967269652812289 + 0.16967739012513644 + 0.16968208384263977 + 0.1696867776806375 + 0.16969147163913384 + 0.16969616571813345 + 0.16970085991764119 + 0.16970555423766148 + 0.16971024867819884 + 0.16971494323925818 + 0.16971963792084366 + 0.16972433272295989 + 0.16972902764561157 + 0.16973372268880357 + 0.16973841785253996 + 0.16974311313682547 + 0.16974780854166491 + 0.16975250406706285 + 0.16975719971302342 + 0.16976189547955178 + 0.16976659136665206 + 0.16977128737432903 + 0.16977598350258716 + 0.16978067975143127 + 0.16978537612086564 + 0.16979007261089515 + 0.1697947692215242 + 0.16979946595275736 + 0.16980416280459931 + 0.16980885977705432 + 0.16981355687012772 + 0.16981825408382348 + 0.16982295141814596 + 0.1698276488731002 + 0.16983234644869097 + 0.16983704414492218 + 0.16984174196179905 + 0.16984643989932588 + 0.16985113795750711 + 0.16985583613634764 + 0.16986053443585181 + 0.1698652328560244 + 0.1698699313968699 + 0.1698746300583926 + 0.16987932884059767 + 0.16988402774348935 + 0.16988872676707198 + 0.16989342591135073 + 0.16989812517632988 + 0.16990282456201392 + 0.16990752406840751 + 0.16991222369551526 + 0.16991692344334183 + 0.16992162331189165 + 0.16992632330116955 + 0.16993102341117985 + 0.16993572364192711 + 0.16994042399341616 + 0.16994512446565155 + 0.16994982505863776 + 0.16995452577237943 + 0.16995922660688109 + 0.16996392756214757 + 0.16996862863818296 + 0.16997332983499217 + 0.16997803115257978 + 0.16998273259095045 + 0.16998743415010861 + 0.1699921358300589 + 0.16999683763080592 + 0.17000153955235434 + 0.17000624159470862 + 0.1700109437578734 + 0.17001564604185326 + 0.17002034844665295 + 0.17002505097227674 + 0.17002975361872935 + 0.17003445638601536 + 0.17003915927413971 + 0.17004386228310636 + 0.17004856541292068 + 0.17005326866358647 + 0.17005797203510881 + 0.17006267552749196 + 0.17006737914074102 + 0.17007208287485975 + 0.1700767867298536 + 0.17008149070572703 + 0.17008619480248402 + 0.17009089902012983 + 0.17009560335866858 + 0.17010030781810512 + 0.17010501239844406 + 0.17010971709968992 + 0.17011442192184723 + 0.17011912686492059 + 0.17012383192891464 + 0.17012853711383422 + 0.1701332424196835 + 0.17013794784646744 + 0.17014265339419024 + 0.17014735906285688 + 0.17015206485247178 + 0.17015677076303937 + 0.17016147679456456 + 0.17016618294705199 + 0.1701708892205058 + 0.17017559561493081 + 0.17018030213033178 + 0.17018500876671325 + 0.1701897155240798 + 0.17019442240243607 + 0.17019912940178636 + 0.17020383652213533 + 0.17020854376348787 + 0.17021325112584848 + 0.17021795860922173 + 0.17022266621361226 + 0.17022737393902437 + 0.17023208178546312 + 0.17023678975293285 + 0.17024149784143813 + 0.17024620605098342 + 0.17025091438157375 + 0.17025562283321363 + 0.17026033140590699 + 0.17026504009965945 + 0.17026974891447497 + 0.17027445785035825 + 0.17027916690731398 + 0.17028387608534676 + 0.17028858538446101 + 0.17029329480466157 + 0.17029800434595294 + 0.17030271400833971 + 0.17030742379182637 + 0.17031213369641782 + 0.17031684372211828 + 0.17032155386893261 + 0.17032626413686541 + 0.17033097452592108 + 0.17033568503610472 + 0.17034039566742026 + 0.17034510641987272 + 0.17034981729346646 + 0.17035452828820649 + 0.170359239404097 + 0.17036395064114271 + 0.17036866199934828 + 0.17037337347871834 + 0.17037808507925736 + 0.17038279680096999 + 0.17038750864386104 + 0.17039222060793488 + 0.17039693269319622 + 0.17040164489964946 + 0.17040635722729952 + 0.17041106967615083 + 0.17041578224620801 + 0.17042049493747558 + 0.17042520774995831 + 0.17042992068366072 + 0.17043463373858739 + 0.17043934691474302 + 0.17044406021213215 + 0.17044877363075955 + 0.17045348717062955 + 0.17045820083174676 + 0.1704629146141162 + 0.17046762851774191 + 0.170472342542629 + 0.17047705668878166 + 0.1704817709562047 + 0.17048648534490285 + 0.17049119985488057 + 0.17049591448614226 + 0.17050062923869283 + 0.17050534411253712 + 0.17051005910767919 + 0.17051477422412395 + 0.17051948946187592 + 0.17052420482093972 + 0.17052892030132008 + 0.1705336359030214 + 0.17053835162604847 + 0.17054306747040576 + 0.17054778343609789 + 0.17055249952312965 + 0.17055721573150537 + 0.17056193206123016 + 0.17056664851230799 + 0.17057136508474383 + 0.17057608177854214 + 0.1705807985937077 + 0.17058551553024523 + 0.170590232588159 + 0.17059494976745379 + 0.17059966706813409 + 0.17060438449020474 + 0.17060910203367052 + 0.17061381969853531 + 0.17061853748480441 + 0.17062325539248216 + 0.17062797342157299 + 0.17063269157208219 + 0.17063740984401357 + 0.17064212823737221 + 0.17064684675216243 + 0.17065156538838924 + 0.17065628414605702 + 0.17066100302517026 + 0.17066572202573399 + 0.17067044114775234 + 0.17067516039123007 + 0.17067987975617196 + 0.17068459924258259 + 0.17068931885046643 + 0.17069403857982818 + 0.17069875843067245 + 0.17070347840300396 + 0.17070819849682697 + 0.17071291871214653 + 0.17071763904896714 + 0.17072235950729331 + 0.17072708008712975 + 0.17073180078848085 + 0.17073652161135169 + 0.17074124255574635 + 0.17074596362166983 + 0.17075068480912683 + 0.17075540611812121 + 0.17076012754865869 + 0.1707648491007431 + 0.17076957077437935 + 0.17077429256957202 + 0.17077901448632585 + 0.17078373652464504 + 0.17078845868453466 + 0.17079318096599913 + 0.17079790336904319 + 0.17080262589367118 + 0.17080734853988808 + 0.17081207130769827 + 0.17081679419710641 + 0.17082151720811722 + 0.17082624034073543 + 0.17083096359496522 + 0.1708356869708117 + 0.17084041046827922 + 0.17084513408737248 + 0.17084985782809603 + 0.17085458169045439 + 0.17085930567445259 + 0.17086402978009488 + 0.17086875400738599 + 0.17087347835633052 + 0.17087820282693328 + 0.1708829274191988 + 0.17088765213313148 + 0.17089237696873602 + 0.17089710192601704 + 0.17090182700497974 + 0.17090655220562775 + 0.1709112775279665 + 0.17091600297200021 + 0.17092072853773357 + 0.17092545422517144 + 0.17093018003431817 + 0.17093490596517852 + 0.17093963201775683 + 0.17094435819205805 + 0.17094908448808699 + 0.17095381090584774 + 0.17095853744534523 + 0.17096326410658411 + 0.17096799088956888 + 0.17097271779430429 + 0.1709774448207948 + 0.17098217196904525 + 0.17098689923906008 + 0.17099162663084402 + 0.17099635414440173 + 0.17100108177973766 + 0.17100580953685685 + 0.17101053741576344 + 0.17101526541646223 + 0.17101999353895789 + 0.17102472178325503 + 0.1710294501493583 + 0.17103417863727233 + 0.1710389072470018 + 0.17104363597855138 + 0.17104836483192537 + 0.17105309380712869 + 0.17105782290416588 + 0.17106255212304156 + 0.17106728146376057 + 0.17107201092632723 + 0.17107674051074634 + 0.1710814702170225 + 0.17108620004516045 + 0.17109092999516468 + 0.17109566006703966 + 0.17110039026079035 + 0.17110512057642113 + 0.17110985101393714 + 0.17111458157334219 + 0.17111931225464158 + 0.17112404305783963 + 0.17112877398294105 + 0.17113350502995056 + 0.17113823619887247 + 0.17114296748971192 + 0.17114769890247311 + 0.17115243043716083 + 0.17115716209377996 + 0.17116189387233449 + 0.17116662577282976 + 0.17117135779526998 + 0.17117608993966005 + 0.17118082220600447 + 0.17118555459430773 + 0.17119028710457462 + 0.17119501973680987 + 0.17119975249101818 + 0.17120448536720362 + 0.1712092183653714 + 0.17121395148552593 + 0.17121868472767196 + 0.17122341809181407 + 0.1712281515779569 + 0.17123288518610494 + 0.17123761891626307 + 0.1712423527684358 + 0.17124708674262787 + 0.17125182083884358 + 0.17125655505708801 + 0.17126128939736568 + 0.17126602385968118 + 0.17127075844403908 + 0.17127549315044369 + 0.17128022797890058 + 0.17128496292941361 + 0.17128969800198773 + 0.17129443319662724 + 0.17129916851333749 + 0.17130390395212225 + 0.17130863951298672 + 0.1713133751959354 + 0.17131811100097283 + 0.17132284692810384 + 0.17132758297733283 + 0.17133231914866479 + 0.17133705544210412 + 0.17134179185765536 + 0.17134652839532341 + 0.17135126505511269 + 0.1713560018370282 + 0.17136073874107399 + 0.17136547576725528 + 0.17137021291557655 + 0.17137495018604218 + 0.17137968757865696 + 0.17138442509342561 + 0.17138916273035279 + 0.17139390048944306 + 0.17139863837070116 + 0.17140337637413147 + 0.17140811449973892 + 0.17141285274752813 + 0.17141759111750376 + 0.1714223296096701 + 0.17142706822403231 + 0.1714318069605946 + 0.17143654581936207 + 0.17144128480033904 + 0.17144602390353009 + 0.17145076312893995 + 0.17145550247657321 + 0.17146024194643486 + 0.17146498153852904 + 0.17146972125286097 + 0.17147446108943501 + 0.17147920104825543 + 0.17148394112932761 + 0.1714886813326556 + 0.17149342165824427 + 0.17149816210609822 + 0.1715029026762222 + 0.1715076433686209 + 0.17151238418329864 + 0.17151712512026035 + 0.17152186617951054 + 0.17152660736105416 + 0.17153134866489558 + 0.17153609009103959 + 0.1715408316394906 + 0.17154557331025344 + 0.17155031510333263 + 0.17155505701873305 + 0.17155979905645927 + 0.17156454121651601 + 0.17156928349890752 + 0.1715740259036389 + 0.1715787684307146 + 0.17158351108013914 + 0.17158825385191748 + 0.17159299674605433 + 0.1715977397625538 + 0.17160248290142111 + 0.17160722616266053 + 0.17161196954627694 + 0.17161671305227488 + 0.17162145668065909 + 0.17162620043143426 + 0.17163094430460479 + 0.17163568830017564 + 0.17164043241815111 + 0.17164517665853626 + 0.17164992102133558 + 0.17165466550655348 + 0.17165941011419508 + 0.1716641548442647 + 0.17166889969676694 + 0.1716736446717067 + 0.17167838976908847 + 0.17168313498891705 + 0.17168788033119689 + 0.17169262579593275 + 0.17169737138312943 + 0.17170211709279132 + 0.17170686292492315 + 0.17171160887952985 + 0.1717163549566158 + 0.17172110115618561 + 0.17172584747824421 + 0.17173059392279574 + 0.17173534048984546 + 0.17174008717939787 + 0.17174483399145732 + 0.17174958092602888 + 0.17175432798311674 + 0.17175907516272595 + 0.17176382246486119 + 0.17176856988952682 + 0.17177331743672752 + 0.17177806510646831 + 0.17178281289875338 + 0.17178756081358784 + 0.17179230885097604 + 0.17179705701092263 + 0.17180180529343264 + 0.17180655369851006 + 0.17181130222616028 + 0.17181605087638757 + 0.17182079964919658 + 0.17182554854459214 + 0.17183029756257864 + 0.17183504670316097 + 0.17183979596634391 + 0.1718445453521317 + 0.17184929486052927 + 0.1718540444915414 + 0.17185879424517267 + 0.17186354412142735 + 0.17186829412031066 + 0.17187304424182698 + 0.17187779448598101 + 0.17188254485277746 + 0.17188729534222111 + 0.17189204595431623 + 0.17189679668906799 + 0.17190154754648057 + 0.17190629852655892 + 0.17191104962930756 + 0.17191580085473129 + 0.17192055220283486 + 0.17192530367362252 + 0.17193005526709934 + 0.17193480698327007 + 0.17193955882213866 + 0.17194431078371084 + 0.17194906286799014 + 0.17195381507498236 + 0.17195856740469134 + 0.17196331985712182 + 0.17196807243227885 + 0.17197282513016687 + 0.17197757795079044 + 0.17198233089415471 + 0.17198708396026358 + 0.17199183714912236 + 0.17199659046073554 + 0.17200134389510743 + 0.17200609745224343 + 0.17201085113214737 + 0.1720156049348246 + 0.17202035886027958 + 0.1720251129085166 + 0.17202986707954096 + 0.17203462137335684 + 0.172039375789969 + 0.17204413032938243 + 0.17204888499160159 + 0.17205363977663082 + 0.17205839468447531 + 0.17206314971513934 + 0.17206790486862797 + 0.17207266014494557 + 0.17207741554409664 + 0.17208217106608667 + 0.1720869267109193 + 0.17209168247859977 + 0.17209643836913252 + 0.17210119438252253 + 0.17210595051877423 + 0.17211070677789239 + 0.1721154631598816 + 0.17212021966474653 + 0.17212497629249196 + 0.17212973304312243 + 0.17213448991664287 + 0.17213924691305749 + 0.17214400403237154 + 0.17214876127458917 + 0.17215351863971531 + 0.17215827612775464 + 0.17216303373871167 + 0.17216779147259134 + 0.17217254932939796 + 0.17217730730913669 + 0.17218206541181175 + 0.17218682363742813 + 0.17219158198599016 + 0.17219634045750301 + 0.17220109905197087 + 0.17220585776939895 + 0.17221061660979131 + 0.17221537557315283 + 0.17222013465948827 + 0.17222489386880258 + 0.17222965320110001 + 0.17223441265638548 + 0.17223917223466334 + 0.17224393193593873 + 0.17224869176021604 + 0.17225345170750014 + 0.1722582117777951 + 0.17226297197110657 + 0.1722677322874385 + 0.17227249272679593 + 0.17227725328918328 + 0.17228201397460538 + 0.17228677478306692 + 0.17229153571457267 + 0.17229629676912697 + 0.17230105794673478 + 0.1723058192474006 + 0.1723105806711295 + 0.17231534221792574 + 0.17232010388779403 + 0.17232486568073913 + 0.17232962759676615 + 0.17233438963587883 + 0.17233915179808279 + 0.17234391408338198 + 0.17234867649178173 + 0.17235343902328626 + 0.17235820167790053 + 0.17236296445562893 + 0.17236772735647635 + 0.17237249038044739 + 0.17237725352754685 + 0.17238201679777934 + 0.17238678019114931 + 0.17239154370766191 + 0.17239630734732128 + 0.17240107111013273 + 0.17240583499610052 + 0.1724105990052292 + 0.17241536313752401 + 0.17242012739298909 + 0.17242489177162931 + 0.17242965627344972 + 0.17243442089845434 + 0.17243918564664831 + 0.17244395051803604 + 0.17244871551262245 + 0.17245348063041216 + 0.17245824587140998 + 0.17246301123562027 + 0.17246777672304767 + 0.17247254233369749 + 0.17247730806757383 + 0.17248207392468159 + 0.17248683990502536 + 0.17249160600861005 + 0.17249637223543993 + 0.17250113858552019 + 0.17250590505885532 + 0.17251067165544989 + 0.17251543837530853 + 0.17252020521843636 + 0.17252497218483745 + 0.17252973927451692 + 0.17253450648747934 + 0.17253927382372949 + 0.17254404128327183 + 0.17254880886611126 + 0.17255357657225226 + 0.17255834440169993 + 0.17256311235445854 + 0.17256788043053287 + 0.17257264862992777 + 0.17257741695264792 + 0.1725821853986978 + 0.17258695396808216 + 0.17259172266080591 + 0.17259649147687367 + 0.17260126041628987 + 0.17260602947905929 + 0.1726107986651868 + 0.17261556797467686 + 0.17262033740753449 + 0.17262510696376426 + 0.17262987664337071 + 0.17263464644635834 + 0.1726394163727327 + 0.17264418642249749 + 0.17264895659565796 + 0.17265372689221864 + 0.17265849731218397 + 0.17266326785555935 + 0.17266803852234885 + 0.17267280931255719 + 0.1726775802261894 + 0.1726823512632501 + 0.17268712242374387 + 0.17269189370767515 + 0.17269666511504911 + 0.17270143664587029 + 0.17270620830014327 + 0.17271098007787278 + 0.1727157519790635 + 0.1727205240037204 + 0.17272529615184781 + 0.17273006842345057 + 0.17273484081853352 + 0.17273961333710097 + 0.17274438597915781 + 0.17274915874470897 + 0.17275393163375896 + 0.17275870464631252 + 0.17276347778237416 + 0.17276825104194871 + 0.17277302442504108 + 0.17277779793165571 + 0.17278257156179738 + 0.17278734531547063 + 0.17279211919268031 + 0.17279689319343111 + 0.17280166731772784 + 0.17280644156557495 + 0.17281121593697735 + 0.17281599043193976 + 0.17282076505046659 + 0.17282553979256299 + 0.17283031465823315 + 0.17283508964748204 + 0.17283986476031457 + 0.17284463999673491 + 0.17284941535674828 + 0.17285419084035916 + 0.17285896644757215 + 0.17286374217839226 + 0.17286851803282374 + 0.17287329401087195 + 0.17287807011254069 + 0.17288284633783532 + 0.17288762268676064 + 0.17289239915932073 + 0.17289717575552088 + 0.17290195247536558 + 0.17290672931885959 + 0.17291150628600718 + 0.17291628337681375 + 0.17292106059128348 + 0.17292583792942159 + 0.1729306153912322 + 0.17293539297672017 + 0.17294017068589054 + 0.17294494851874784 + 0.17294972647529641 + 0.17295450455554154 + 0.17295928275948766 + 0.17296406108713946 + 0.17296883953850153 + 0.17297361811357886 + 0.17297839681237603 + 0.17298317563489743 + 0.17298795458114843 + 0.17299273365113321 + 0.17299751284485659 + 0.17300229216232341 + 0.17300707160353815 + 0.17301185116850573 + 0.1730166308572309 + 0.17302141066971816 + 0.17302619060597219 + 0.17303097066599799 + 0.17303575084980027 + 0.17304053115738333 + 0.17304531158875197 + 0.17305009214391129 + 0.17305487282286569 + 0.1730596536256199 + 0.17306443455217874 + 0.1730692156025469 + 0.17307399677672883 + 0.17307877807472952 + 0.1730835594965536 + 0.17308834104220602 + 0.17309312271169103 + 0.17309790450501356 + 0.17310268642217863 + 0.17310746846319039 + 0.17311225062805374 + 0.17311703291677374 + 0.17312181532935464 + 0.17312659786580151 + 0.17313138052611868 + 0.17313616331031126 + 0.17314094621838391 + 0.1731457292503408 + 0.17315051240618745 + 0.173155295685928 + 0.17316007908956729 + 0.17316486261711023 + 0.17316964626856143 + 0.17317443004392541 + 0.17317921394320721 + 0.17318399796641112 + 0.17318878211354219 + 0.17319356638460529 + 0.1731983507796048 + 0.17320313529854528 + 0.17320791994143189 + 0.17321270470826927 + 0.17321748959906175 + 0.17322227461381462 + 0.17322705975253208 + 0.17323184501521929 + 0.1732366304018805 + 0.17324141591252065 + 0.1732462015471446 + 0.17325098730575683 + 0.17325577318836233 + 0.17326055919496558 + 0.17326534532557131 + 0.17327013158018437 + 0.1732749179588095 + 0.17327970446145111 + 0.17328449108811411 + 0.17328927783880343 + 0.17329406471352357 + 0.17329885171227913 + 0.17330363883507521 + 0.17330842608191621 + 0.1733132134528069 + 0.17331800094775213 + 0.17332278856675626 + 0.17332757630982437 + 0.17333236417696127 + 0.17333715216817161 + 0.17334194028345962 + 0.17334672852283073 + 0.17335151688628908 + 0.17335630537383975 + 0.17336109398548744 + 0.17336588272123665 + 0.17337067158109221 + 0.17337546056505901 + 0.17338024967314158 + 0.17338503890534468 + 0.17338982826167315 + 0.17339461774213139 + 0.17339940734672443 + 0.17340419707545701 + 0.17340898692833362 + 0.17341377690535917 + 0.17341856700653846 + 0.17342335723187599 + 0.17342814758137656 + 0.17343293805504473 + 0.17343772865288573 + 0.17344251937490379 + 0.1734473102211038 + 0.17345210119149049 + 0.17345689228606856 + 0.1734616835048429 + 0.17346647484781788 + 0.17347126631499871 + 0.17347605790638965 + 0.17348084962199567 + 0.17348564146182155 + 0.17349043342587173 + 0.1734952255141512 + 0.17350001772666465 + 0.17350481006341661 + 0.17350960252441242 + 0.17351439510965597 + 0.17351918781915257 + 0.17352398065290661 + 0.17352877361092278 + 0.17353356669320627 + 0.17353835989976146 + 0.17354315323059324 + 0.17354794668570594 + 0.17355274026510492 + 0.17355753396879453 + 0.17356232779677941 + 0.17356712174906452 + 0.17357191582565448 + 0.17357671002655412 + 0.17358150435176811 + 0.17358629880130086 + 0.17359109337515788 + 0.17359588807334286 + 0.17360068289586159 + 0.17360547784271813 + 0.1736102729139174 + 0.173615068109464 + 0.17361986342936278 + 0.1736246588736188 + 0.17362945444223613 + 0.17363425013522002 + 0.17363904595257496 + 0.17364384189430573 + 0.17364863796041693 + 0.17365343415091397 + 0.17365823046580053 + 0.17366302690508201 + 0.17366782346876303 + 0.1736726201568484 + 0.17367741696934241 + 0.17368221390625047 + 0.17368701096757694 + 0.1736918081533266 + 0.17369660546350391 + 0.1737014028981142 + 0.17370620045716184 + 0.17371099814065147 + 0.17371579594858808 + 0.17372059388097624 + 0.17372539193782072 + 0.17373019011912627 + 0.17373498842489754 + 0.17373978685513963 + 0.17374458540985649 + 0.17374938408905385 + 0.17375418289273581 + 0.17375898182090738 + 0.17376378087357292 + 0.17376858005073767 + 0.1737733793524058 + 0.17377817877858273 + 0.17378297832927278 + 0.1737877780044807 + 0.1737925778042112 + 0.17379737772846909 + 0.1738021777772592 + 0.17380697795058642 + 0.17381177824845495 + 0.17381657867086975 + 0.17382137921783594 + 0.17382617988935781 + 0.17383098068544028 + 0.17383578160608815 + 0.17384058265130595 + 0.17384538382109865 + 0.17385018511547082 + 0.17385498653442727 + 0.17385978807797281 + 0.1738645897461121 + 0.17386939153884987 + 0.17387419345619096 + 0.17387899549814004 + 0.17388379766470174 + 0.17388859995588091 + 0.17389340237168241 + 0.17389820491211094 + 0.17390300757717106 + 0.17390781036686756 + 0.1739126132812055 + 0.17391741632018903 + 0.17392221948382358 + 0.17392702277211339 + 0.17393182618506348 + 0.17393662972267837 + 0.17394143338496307 + 0.17394623717192198 + 0.1739510410835601 + 0.1739558451198823 + 0.17396064928089303 + 0.17396545356659709 + 0.17397025797699925 + 0.17397506251210443 + 0.17397986717191705 + 0.17398467195644221 + 0.17398947686568447 + 0.17399428189964861 + 0.17399908705833908 + 0.17400389234176128 + 0.17400869774991962 + 0.17401350328281859 + 0.17401830894046313 + 0.17402311472285822 + 0.17402792063000838 + 0.17403272666191841 + 0.17403753281859291 + 0.17404233910003691 + 0.17404714550625472 + 0.17405195203725154 + 0.17405675869303211 + 0.17406156547360097 + 0.17406637237896283 + 0.17407117940912262 + 0.17407598656408488 + 0.1740807938438545 + 0.17408560124843642 + 0.17409040877783508 + 0.17409521643205542 + 0.17410002421110193 + 0.17410483211497943 + 0.17410964014369312 + 0.17411444829724723 + 0.17411925657564681 + 0.1741240649788964 + 0.17412887350700096 + 0.17413368215996516 + 0.17413849093779357 + 0.17414329984049121 + 0.17414810886806248 + 0.17415291802051264 + 0.17415772729784612 + 0.1741625367000679 + 0.17416734622718236 + 0.17417215587919452 + 0.17417696565610905 + 0.17418177555793085 + 0.17418658558466435 + 0.17419139573631479 + 0.17419620601288621 + 0.17420101641438415 + 0.17420582694081302 + 0.1742106375921775 + 0.17421544836848255 + 0.17422025926973234 + 0.17422507029593284 + 0.17422988144708743 + 0.17423469272320183 + 0.17423950412428019 + 0.17424431565032769 + 0.17424912730134887 + 0.17425393907734857 + 0.17425875097833138 + 0.17426356300430235 + 0.17426837515526616 + 0.17427318743122741 + 0.17427799983219092 + 0.17428281235816168 + 0.17428762500914383 + 0.17429243778514295 + 0.17429725068616314 + 0.17430206371220958 + 0.17430687686328672 + 0.17431169013939957 + 0.17431650354055259 + 0.17432131706675111 + 0.17432613071799916 + 0.17433094449430189 + 0.17433575839566418 + 0.17434057242209053 + 0.17434538657358586 + 0.17435020085015471 + 0.17435501525180233 + 0.17435982977853279 + 0.17436464443035155 + 0.17436945920726271 + 0.17437427410927173 + 0.1743790891363827 + 0.17438390428860079 + 0.1743887195659308 + 0.17439353496837712 + 0.17439835049594507 + 0.17440316614863899 + 0.17440798192646345 + 0.17441279782942384 + 0.17441761385752447 + 0.17442243001077018 + 0.17442724628916584 + 0.17443206269271624 + 0.17443687922142609 + 0.17444169587529992 + 0.17444651265434291 + 0.17445132955855969 + 0.17445614658795455 + 0.174460963742533 + 0.17446578102229943 + 0.17447059842725859 + 0.17447541595741523 + 0.17448023361277434 + 0.17448505139334058 + 0.17448986929911842 + 0.17449468733011314 + 0.17449950548632909 + 0.17450432376777109 + 0.17450914217444441 + 0.174513960706353 + 0.17451877936350216 + 0.17452359814589674 + 0.17452841705354119 + 0.17453323608644047 + 0.17453805524459901 + 0.17454287452802211 + 0.17454769393671424 + 0.17455251347068007 + 0.17455733312992475 + 0.17456215291445276 + 0.17456697282426881 + 0.17457179285937777 + 0.17457661301978455 + 0.17458143330549367 + 0.17458625371651029 + 0.17459107425283865 + 0.17459589491448374 + 0.17460071570145047 + 0.17460553661374356 + 0.17461035765136776 + 0.17461517881432781 + 0.1746200001026286 + 0.1746248215162744 + 0.17462964305527065 + 0.17463446471962188 + 0.17463928650933294 + 0.17464410842440842 + 0.17464893046485294 + 0.17465375263067173 + 0.1746585749218694 + 0.1746633973384506 + 0.17466821988042003 + 0.1746730425477829 + 0.17467786534054333 + 0.17468268825870664 + 0.1746875113022775 + 0.17469233447126056 + 0.17469715776566055 + 0.17470198118548241 + 0.17470680473073097 + 0.17471162840141063 + 0.17471645219752657 + 0.17472127611908339 + 0.17472610016608589 + 0.1747309243385386 + 0.17473574863644684 + 0.17474057305981505 + 0.17474539760864799 + 0.17475022228295062 + 0.17475504708272752 + 0.1747598720079834 + 0.17476469705872336 + 0.17476952223495185 + 0.17477434753667381 + 0.1747791729638942 + 0.17478399851661763 + 0.17478882419484848 + 0.17479364999859223 + 0.17479847592785316 + 0.17480330198263633 + 0.17480812816294619 + 0.174812954468788 + 0.17481778090016623 + 0.17482260745708569 + 0.1748274341395511 + 0.1748322609475674 + 0.17483708788113908 + 0.17484191494027149 + 0.17484674212496892 + 0.17485156943523644 + 0.17485639687107848 + 0.17486122443249999 + 0.17486605211950587 + 0.17487087993210088 + 0.17487570787028972 + 0.17488053593407704 + 0.17488536412346806 + 0.17489019243846687 + 0.17489502087907899 + 0.17489984944530884 + 0.17490467813716115 + 0.17490950695464086 + 0.17491433589775271 + 0.17491916496650148 + 0.17492399416089174 + 0.17492882348092872 + 0.174933652926617 + 0.17493848249796107 + 0.17494331219496612 + 0.17494814201763689 + 0.17495297196597775 + 0.17495780203999411 + 0.1749626322396903 + 0.17496746256507126 + 0.17497229301614181 + 0.17497712359290657 + 0.17498195429537061 + 0.1749867851235386 + 0.17499161607741517 + 0.17499644715700535 + 0.17500127836231347 + 0.17500610969334496 + 0.17501094115010438 + 0.17501577273259625 + 0.17502060444082534 + 0.17502543627479705 + 0.17503026823451545 + 0.17503510031998595 + 0.17503993253121286 + 0.17504476486820103 + 0.17504959733095549 + 0.17505442991948089 + 0.17505926263378216 + 0.17506409547386387 + 0.17506892843973076 + 0.17507376153138782 + 0.17507859474884002 + 0.17508342809209179 + 0.17508826156114801 + 0.17509309515601357 + 0.17509792887669298 + 0.17510276272319161 + 0.17510759669551337 + 0.17511243079366401 + 0.17511726501764788 + 0.17512209936746959 + 0.1751269338431343 + 0.17513176844464651 + 0.17513660317201107 + 0.17514143802523308 + 0.17514627300431693 + 0.17515110810926762 + 0.17515594334008977 + 0.17516077869678853 + 0.17516561417936838 + 0.17517044978783397 + 0.17517528552219078 + 0.17518012138244285 + 0.17518495736859518 + 0.17518979348065297 + 0.17519462971862046 + 0.17519946608250275 + 0.17520430257230468 + 0.17520913918803091 + 0.17521397592968618 + 0.1752188127972755 + 0.17522364979080368 + 0.17522848691027507 + 0.17523332415569493 + 0.17523816152706806 + 0.17524299902439885 + 0.17524783664769239 + 0.17525267439695347 + 0.17525751227218689 + 0.17526235027339745 + 0.17526718840058977 + 0.17527202665376898 + 0.17527686503293965 + 0.17528170353810676 + 0.17528654216927481 + 0.17529138092644853 + 0.17529621980963336 + 0.17530105881883362 + 0.17530589795405407 + 0.17531073721529977 + 0.17531557660257521 + 0.17532041611588556 + 0.17532525575523528 + 0.17533009552062934 + 0.17533493541207254 + 0.17533977542956944 + 0.17534461557312533 + 0.17534945584274472 + 0.17535429623843241 + 0.17535913676019302 + 0.17536397740803186 + 0.17536881818195321 + 0.17537365908196209 + 0.1753785001080633 + 0.17538334126026181 + 0.17538818253856198 + 0.17539302394296932 + 0.17539786547348776 + 0.17540270713012293 + 0.17540754891287919 + 0.1754123908217613 + 0.17541723285677413 + 0.17542207501792254 + 0.17542691730521143 + 0.17543175971864536 + 0.17543660225822955 + 0.17544144492396838 + 0.17544628771586662 + 0.17545113063392961 + 0.17545597367816149 + 0.17546081684856762 + 0.17546566014515258 + 0.17547050356792099 + 0.17547534711687804 + 0.1754801907920282 + 0.17548503459337653 + 0.17548987852092768 + 0.17549472257468654 + 0.17549956675465775 + 0.17550441106084644 + 0.1755092554932571 + 0.17551410005189469 + 0.17551894473676394 + 0.1755237895478699 + 0.17552863448521702 + 0.17553347954881021 + 0.17553832473865472 + 0.17554317005475475 + 0.1755480154971153 + 0.17555286106574108 + 0.17555770676063737 + 0.17556255258180872 + 0.17556739852925962 + 0.17557224460299531 + 0.17557709080302025 + 0.17558193712933967 + 0.17558678358195792 + 0.17559163016088034 + 0.17559647686611135 + 0.17560132369765591 + 0.17560617065551859 + 0.1756110177397045 + 0.17561586495021833 + 0.17562071228706488 + 0.17562555975024902 + 0.17563040733977567 + 0.17563525505564936 + 0.17564010289787504 + 0.17564495086645759 + 0.17564979896140179 + 0.17565464718271256 + 0.17565949553039423 + 0.1756643440044523 + 0.17566919260489119 + 0.17567404133171602 + 0.1756788901849311 + 0.1756837391645415 + 0.1756885882705522 + 0.17569343750296765 + 0.17569828686179312 + 0.17570313634703308 + 0.17570798595869239 + 0.17571283569677612 + 0.17571768556128872 + 0.17572253555223544 + 0.17572738566962073 + 0.17573223591344947 + 0.17573708628372656 + 0.17574193678045677 + 0.17574678740364508 + 0.17575163815329603 + 0.17575648902941465 + 0.17576134003200578 + 0.17576619116107417 + 0.17577104241662447 + 0.17577589379866165 + 0.17578074530719054 + 0.17578559694221593 + 0.17579044870374286 + 0.17579530059177562 + 0.17580015260631979 + 0.17580500474737948 + 0.17580985701495977 + 0.17581470940906546 + 0.17581956192970155 + 0.17582441457687289 + 0.17582926735058382 + 0.17583412025083967 + 0.17583897327764492 + 0.17584382643100477 + 0.17584867971092349 + 0.17585353311740667 + 0.17585838665045825 + 0.17586324031008363 + 0.17586809409628767 + 0.17587294800907491 + 0.1758778020484503 + 0.17588265621441865 + 0.17588751050698473 + 0.17589236492615354 + 0.1758972194719296 + 0.17590207414431799 + 0.17590692894332371 + 0.17591178386895101 + 0.17591663892120521 + 0.17592149410009092 + 0.175926349405613 + 0.17593120483777633 + 0.17593606039658563 + 0.17594091608204601 + 0.17594577189416175 + 0.17595062783293836 + 0.17595548389838009 + 0.17596034009049188 + 0.1759651964092788 + 0.17597005285474573 + 0.17597490942689706 + 0.17597976612573801 + 0.17598462295127315 + 0.17598947990350755 + 0.17599433698244582 + 0.17599919418809301 + 0.17600405152045362 + 0.17600890897953297 + 0.17601376656533538 + 0.17601862427786605 + 0.1760234821171297 + 0.17602834008313084 + 0.17603319817587482 + 0.17603805639536615 + 0.17604291474160971 + 0.17604777321461049 + 0.17605263181437322 + 0.17605749054090264 + 0.17606234939420337 + 0.17606720837428086 + 0.17607206748113952 + 0.17607692671478414 + 0.17608178607522001 + 0.17608664556245127 + 0.17609150517648331 + 0.17609636491732056 + 0.17610122478496823 + 0.17610608477943107 + 0.17611094490071372 + 0.17611580514882114 + 0.17612066552375799 + 0.17612552602552942 + 0.17613038665414002 + 0.17613524740959474 + 0.17614010829189838 + 0.17614496930105569 + 0.17614983043707164 + 0.17615469169995113 + 0.17615955308969863 + 0.1761644146063196 + 0.17616927624981824 + 0.17617413802019952 + 0.17617899991746885 + 0.17618386194163002 + 0.17618872409268893 + 0.17619358637064986 + 0.17619844877551769 + 0.17620331130729727 + 0.17620817396599339 + 0.17621303675161107 + 0.17621789966415513 + 0.17622276270363027 + 0.17622762587004132 + 0.17623248916339343 + 0.17623735258369075 + 0.17624221613093879 + 0.17624707980514207 + 0.17625194360630564 + 0.17625680753443426 + 0.17626167158953271 + 0.17626653577160578 + 0.17627140008065839 + 0.17627626451669537 + 0.17628112907972149 + 0.17628599376974174 + 0.17629085858676086 + 0.17629572353078368 + 0.17630058860181513 + 0.17630545379986012 + 0.17631031912492298 + 0.17631518457700934 + 0.17632005015612337 + 0.17632491586227025 + 0.17632978169545488 + 0.17633464765568177 + 0.17633951374295612 + 0.17634437995728278 + 0.17634924629866613 + 0.17635411276711138 + 0.17635897936262321 + 0.17636384608520692 + 0.17636871293486672 + 0.17637357991160776 + 0.17637844701543487 + 0.17638331424635306 + 0.17638818160436687 + 0.17639304908948106 + 0.17639791670170094 + 0.17640278444103105 + 0.17640765230747638 + 0.17641252030104143 + 0.17641738842173141 + 0.17642225666955125 + 0.17642712504450539 + 0.17643199354659897 + 0.17643686217583676 + 0.17644173093222348 + 0.17644659981576427 + 0.17645146882646381 + 0.17645633796432672 + 0.17646120722935837 + 0.17646607662156305 + 0.17647094614094591 + 0.17647581578751195 + 0.17648068556126587 + 0.17648555546221217 + 0.17649042549035612 + 0.1764952956457026 + 0.17650016592825615 + 0.17650503633802186 + 0.17650990687500462 + 0.17651477753920886 + 0.17651964833063999 + 0.17652451924930243 + 0.1765293902952014 + 0.17653426146834134 + 0.17653913276872743 + 0.17654400419636437 + 0.17654887575125711 + 0.17655374743341037 + 0.17655861924282906 + 0.17656349117951825 + 0.17656836324348235 + 0.17657323543472658 + 0.1765781077532555 + 0.17658298019907434 + 0.17658785277218772 + 0.17659272547260046 + 0.17659759830031749 + 0.17660247125534351 + 0.17660734433768363 + 0.17661221754734249 + 0.17661709088432506 + 0.17662196434863614 + 0.17662683794028061 + 0.17663171165926334 + 0.17663658550558931 + 0.17664145947926307 + 0.17664633358028964 + 0.1766512078086741 + 0.17665608216442083 + 0.17666095664753489 + 0.17666583125802132 + 0.17667070599588486 + 0.17667558086113039 + 0.17668045585376269 + 0.17668533097378669 + 0.1766902062212071 + 0.17669508159602895 + 0.17669995709825695 + 0.17670483272789614 + 0.17670970848495121 + 0.17671458436942714 + 0.17671946038132863 + 0.17672433652066083 + 0.17672921278742834 + 0.17673408918163599 + 0.17673896570328898 + 0.17674384235239168 + 0.17674871912894949 + 0.17675359603296681 + 0.1767584730644485 + 0.17676335022339995 + 0.17676822750982529 + 0.17677310492373002 + 0.17677798246511853 + 0.17678286013399624 + 0.17678773793036734 + 0.17679261585423714 + 0.17679749390561023 + 0.17680237208449195 + 0.17680725039088663 + 0.17681212882479916 + 0.17681700738623471 + 0.17682188607519805 + 0.17682676489169399 + 0.17683164383572716 + 0.17683652290730295 + 0.17684140210642593 + 0.17684628143310077 + 0.17685116088733283 + 0.17685604046912626 + 0.17686092017848692 + 0.17686580001541868 + 0.17687067997992709 + 0.17687556007201644 + 0.17688044029169195 + 0.17688532063895859 + 0.17689020111382084 + 0.17689508171628412 + 0.17689996244635284 + 0.176904843304032 + 0.17690972428932636 + 0.1769146054022411 + 0.17691948664278084 + 0.17692436801095038 + 0.17692924950675476 + 0.1769341311301986 + 0.17693901288128724 + 0.17694389476002514 + 0.17694877676641729 + 0.17695365890046855 + 0.17695854116218382 + 0.17696342355156799 + 0.17696830606862571 + 0.17697318871336212 + 0.17697807148578201 + 0.17698295438589029 + 0.1769878374136917 + 0.17699272056919105 + 0.17699760385239335 + 0.17700248726330375 + 0.17700737080192663 + 0.17701225446826713 + 0.17701713826232984 + 0.17702202218412005 + 0.17702690623364253 + 0.17703179041090183 + 0.17703667471590304 + 0.1770415591486513 + 0.17704644370915093 + 0.17705132839740712 + 0.1770562132134248 + 0.17706109815720883 + 0.17706598322876366 + 0.17707086842809489 + 0.17707575375520673 + 0.17708063921010461 + 0.17708552479279299 + 0.17709041050327667 + 0.1770952963415609 + 0.17710018230765037 + 0.17710506840155008 + 0.17710995462326462 + 0.17711484097279925 + 0.17711972745015847 + 0.17712461405534738 + 0.17712950078837086 + 0.17713438764923364 + 0.17713927463794082 + 0.17714416175449715 + 0.17714904899890724 + 0.17715393637117618 + 0.17715882387130918 + 0.17716371149931054 + 0.17716859925518569 + 0.17717348713893921 + 0.17717837515057588 + 0.17718326329010076 + 0.17718815155751844 + 0.17719303995283436 + 0.17719792847605292 + 0.17720281712717928 + 0.17720770590621798 + 0.17721259481317433 + 0.177217483848053 + 0.17722237301085872 + 0.1772272623015963 + 0.17723215172027132 + 0.17723704126688763 + 0.17724193094145099 + 0.17724682074396581 + 0.17725171067443707 + 0.17725660073286978 + 0.17726149091926863 + 0.17726638123363866 + 0.17727127167598461 + 0.1772761622463114 + 0.17728105294462398 + 0.17728594377092738 + 0.17729083472522594 + 0.17729572580752515 + 0.17730061701782959 + 0.17730550835614428 + 0.17731039982247393 + 0.17731529141682353 + 0.17732018313919803 + 0.17732507498960207 + 0.1773299669680406 + 0.17733485907451874 + 0.17733975130904134 + 0.17734464367161301 + 0.17734953616223878 + 0.17735442878092364 + 0.1773593215276725 + 0.1773642144024902 + 0.17736910740538148 + 0.17737400053635111 + 0.17737889379540414 + 0.17738378718254566 + 0.17738868069778047 + 0.17739357434111322 + 0.17739846811254897 + 0.17740336201209261 + 0.1774082560397488 + 0.17741315019552301 + 0.17741804447941956 + 0.17742293889144348 + 0.17742783343159985 + 0.17743272809989333 + 0.177437622896329 + 0.17744251782091153 + 0.1774474128736459 + 0.17745230805453699 + 0.17745720336358983 + 0.17746209880080907 + 0.17746699436619973 + 0.17747189005976685 + 0.17747678588151505 + 0.17748168183144949 + 0.17748657790957464 + 0.17749147411589578 + 0.17749637045041769 + 0.17750126691314541 + 0.1775061635040833 + 0.17751106022323682 + 0.17751595707061096 + 0.1775208540462099 + 0.17752575115003888 + 0.17753064838210342 + 0.17753554574240732 + 0.17754044323095616 + 0.17754534084775472 + 0.17755023859280791 + 0.17755513646612056 + 0.1775600344676975 + 0.17756493259754352 + 0.17756983085566383 + 0.17757472924206338 + 0.17757962775674657 + 0.17758452639971889 + 0.17758942517098464 + 0.1775943240705492 + 0.17759922309841714 + 0.17760412225459352 + 0.17760902153908334 + 0.17761392095189119 + 0.17761882049302222 + 0.17762372016248129 + 0.17762861996027324 + 0.1776335198864028 + 0.17763841994087515 + 0.17764332012369513 + 0.17764822043486758 + 0.17765312087439755 + 0.17765802144228945 + 0.17766292213854887 + 0.17766782296317998 + 0.17767272391618832 + 0.17767762499757853 + 0.17768252620735542 + 0.17768742754552405 + 0.17769232901208912 + 0.17769723060705581 + 0.1777021323304287 + 0.1777070341822129 + 0.17771193616241324 + 0.1777168382710346 + 0.1777217405080822 + 0.17772664287356055 + 0.17773154536747443 + 0.17773644798982918 + 0.17774135074062961 + 0.17774625361988006 + 0.17775115662758612 + 0.17775605976375264 + 0.17776096302838423 + 0.17776586642148576 + 0.17777076994306246 + 0.17777567359311885 + 0.17778057737166011 + 0.17778548127869098 + 0.1777903853142164 + 0.17779528947824158 + 0.17780019377077078 + 0.17780509819180954 + 0.17781000274136258 + 0.17781490741943431 + 0.17781981222603033 + 0.17782471716115555 + 0.17782962222481413 + 0.17783452741701167 + 0.17783943273775263 + 0.17784433818704254 + 0.17784924376488553 + 0.17785414947128692 + 0.1778590553062516 + 0.17786396126978446 + 0.17786886736189031 + 0.17787377358257417 + 0.17787867993184087 + 0.17788358640969537 + 0.17788849301614268 + 0.1778933997511877 + 0.17789830661483488 + 0.17790321360708961 + 0.17790812072795675 + 0.17791302797744094 + 0.1779179353555477 + 0.17792284286228105 + 0.17792775049764656 + 0.17793265826164878 + 0.1779375661542931 + 0.17794247417558387 + 0.17794738232552629 + 0.17795229060412512 + 0.17795719901138557 + 0.17796210754731229 + 0.17796701621191016 + 0.17797192500518416 + 0.17797683392713926 + 0.17798174297778038 + 0.17798665215711235 + 0.17799156146514011 + 0.17799647090186863 + 0.17800138046730277 + 0.17800629016144737 + 0.17801119998430734 + 0.17801610993588776 + 0.17802102001619363 + 0.17802593022522939 + 0.17803084056300034 + 0.17803575102951133 + 0.1780406616247672 + 0.17804557234877302 + 0.17805048320153352 + 0.17805539418305363 + 0.17806030529333847 + 0.17806521653239271 + 0.17807012790022111 + 0.17807503939682912 + 0.17807995102222149 + 0.17808486277640273 + 0.17808977465937809 + 0.1780946866711525 + 0.17809959881173087 + 0.17810451108111813 + 0.17810942347931905 + 0.17811433600633844 + 0.17811924866218157 + 0.17812416144685328 + 0.17812907436035827 + 0.1781339874027015 + 0.17813890057388809 + 0.17814381387392272 + 0.17814872730281039 + 0.17815364086055635 + 0.17815855454716509 + 0.1781634683626416 + 0.17816838230699075 + 0.17817329638021789 + 0.1781782105823275 + 0.17818312491332441 + 0.17818803937321387 + 0.17819295396200063 + 0.17819786867968976 + 0.17820278352628613 + 0.17820769850179455 + 0.1782126136062199 + 0.17821752883956735 + 0.17822244420184136 + 0.17822735969304754 + 0.17823227531319033 + 0.17823719106227487 + 0.17824210694030582 + 0.17824702294728834 + 0.17825193908322709 + 0.17825685534812727 + 0.17826177174199384 + 0.17826668826483147 + 0.17827160491664518 + 0.17827652169743985 + 0.17828143860722059 + 0.17828635564599207 + 0.17829127281375939 + 0.17829619011052766 + 0.17830110753630116 + 0.17830602509108562 + 0.17831094277488546 + 0.17831586058770563 + 0.17832077852955122 + 0.17832569660042694 + 0.17833061480033807 + 0.17833553312928904 + 0.17834045158728551 + 0.17834537017433161 + 0.17835028889043275 + 0.17835520773559355 + 0.17836012670981924 + 0.17836504581311449 + 0.1783699650454845 + 0.17837488440693405 + 0.1783798038974681 + 0.17838472351709142 + 0.17838964326580894 + 0.17839456314362589 + 0.1783994831505471 + 0.17840440328657717 + 0.17840932355172148 + 0.17841424394598471 + 0.17841916446937195 + 0.17842408512188776 + 0.17842900590353775 + 0.17843392681432593 + 0.1784388478542579 + 0.17844376902333842 + 0.17844869032157262 + 0.17845361174896501 + 0.17845853330552075 + 0.17846345499124502 + 0.17846837680614205 + 0.17847329875021758 + 0.17847822082347614 + 0.17848314302592247 + 0.17848806535756212 + 0.17849298781839948 + 0.17849791040843954 + 0.17850283312768728 + 0.17850775597614785 + 0.178512678953826 + 0.17851760206072653 + 0.17852252529685464 + 0.17852744866221515 + 0.17853237215681306 + 0.17853729578065317 + 0.17854221953374047 + 0.17854714341607983 + 0.17855206742767643 + 0.17855699156853508 + 0.17856191583866035 + 0.17856684023805772 + 0.17857176476673195 + 0.17857668942468774 + 0.17858161421193061 + 0.17858653912846495 + 0.17859146417429572 + 0.17859638934942818 + 0.17860131465386694 + 0.17860624008761694 + 0.17861116565068361 + 0.17861609134307119 + 0.17862101716478523 + 0.17862594311583024 + 0.17863086919621135 + 0.17863579540593358 + 0.17864072174500165 + 0.17864564821342055 + 0.17865057481119528 + 0.17865550153833071 + 0.17866042839483212 + 0.17866535538070386 + 0.17867028249595157 + 0.17867520974057952 + 0.1786801371145931 + 0.17868506461799674 + 0.17868999225079618 + 0.17869492001299558 + 0.17869984790460047 + 0.17870477592561526 + 0.17870970407604525 + 0.17871463235589555 + 0.17871956076517043 + 0.17872448930387533 + 0.17872941797201533 + 0.17873434676959526 + 0.17873927569661979 + 0.1787442047530938 + 0.17874913393902289 + 0.17875406325441137 + 0.17875899269926432 + 0.17876392227358676 + 0.17876885197738382 + 0.17877378181065992 + 0.17877871177342083 + 0.17878364186567067 + 0.17878857208741483 + 0.17879350243865794 + 0.17879843291940545 + 0.17880336352966189 + 0.17880829426943215 + 0.17881322513872175 + 0.17881815613753479 + 0.17882308726587712 + 0.17882801852375282 + 0.17883294991116763 + 0.17883788142812587 + 0.17884281307463257 + 0.17884774485069327 + 0.17885267675631208 + 0.17885760879149476 + 0.1788625409562454 + 0.17886747325056984 + 0.17887240567447227 + 0.17887733822795826 + 0.17888227091103223 + 0.17888720372369943 + 0.17889213666596479 + 0.17889706973783312 + 0.17890200293930947 + 0.17890693627039875 + 0.17891186973110601 + 0.17891680332143625 + 0.17892173704139414 + 0.17892667089098488 + 0.17893160487021328 + 0.17893653897908443 + 0.17894147321760295 + 0.17894640758577418 + 0.17895134208360314 + 0.17895627671109424 + 0.17896121146825295 + 0.17896614635508393 + 0.17897108137159259 + 0.17897601651778317 + 0.17898095179366097 + 0.17898588719923125 + 0.17899082273449848 + 0.17899575839946794 + 0.17900069419414447 + 0.17900563011853277 + 0.17901056617263811 + 0.17901550235646546 + 0.17902043867001971 + 0.17902537511330571 + 0.17903031168632838 + 0.17903524838909293 + 0.17904018522160423 + 0.17904512218386709 + 0.17905005927588644 + 0.17905499649766779 + 0.17905993384921517 + 0.17906487133053428 + 0.1790698089416298 + 0.17907474668250678 + 0.17907968455316997 + 0.17908462255362453 + 0.17908956068387544 + 0.17909449894392748 + 0.1790994373337858 + 0.17910437585345501 + 0.17910931450294063 + 0.17911425328224698 + 0.17911919219137964 + 0.17912413123034329 + 0.17912907039914258 + 0.17913400969778293 + 0.17913894912626929 + 0.17914388868460621 + 0.17914882837279916 + 0.17915376819085274 + 0.17915870813877191 + 0.17916364821656192 + 0.1791685884242275 + 0.17917352876177356 + 0.17917846922920524 + 0.17918340982652761 + 0.17918835055374516 + 0.17919329141086332 + 0.17919823239788671 + 0.17920317351482043 + 0.17920811476166965 + 0.17921305613843913 + 0.17921799764513388 + 0.17922293928175886 + 0.17922788104831894 + 0.17923282294481901 + 0.17923776497126451 + 0.17924270712766002 + 0.17924764941401039 + 0.17925259183032083 + 0.17925753437659608 + 0.17926247705284157 + 0.17926741985906186 + 0.17927236279526196 + 0.17927730586144686 + 0.17928224905762136 + 0.17928719238379098 + 0.17929213583996001 + 0.17929707942613404 + 0.17930202314231755 + 0.17930696698851559 + 0.17931191096473345 + 0.17931685507097569 + 0.17932179930724759 + 0.17932674367355397 + 0.17933168816989975 + 0.17933663279628992 + 0.17934157755272959 + 0.17934652243922364 + 0.17935146745577704 + 0.17935641260239474 + 0.17936135787908147 + 0.17936630328584288 + 0.17937124882268313 + 0.17937619448960784 + 0.17938114028662136 + 0.17938608621372959 + 0.17939103227093642 + 0.17939597845824748 + 0.17940092477566752 + 0.17940587122320165 + 0.17941081780085477 + 0.17941576450863184 + 0.17942071134653789 + 0.17942565831457774 + 0.17943060541275652 + 0.1794355526410791 + 0.17944049999955061 + 0.17944544748817587 + 0.17945039510695987 + 0.1794553428559077 + 0.17946029073502404 + 0.17946523874431433 + 0.17947018688378311 + 0.17947513515343552 + 0.17948008355327671 + 0.17948503208331121 + 0.17948998074354458 + 0.17949492953398111 + 0.17949987845462656 + 0.1795048275054853 + 0.17950977668656237 + 0.17951472599786303 + 0.17951967543939212 + 0.1795246250111546 + 0.17952957471315528 + 0.17953452454539945 + 0.17953947450789207 + 0.17954442460063796 + 0.17954937482364197 + 0.17955432517690931 + 0.17955927566044472 + 0.17956422627425359 + 0.17956917701834046 + 0.17957412789271074 + 0.17957907889736882 + 0.17958403003232035 + 0.17958898129756989 + 0.17959393269312246 + 0.17959888421898298 + 0.17960383587515683 + 0.17960878766164845 + 0.17961373957846324 + 0.17961869162560617 + 0.17962364380308163 + 0.17962859611089535 + 0.17963354854905189 + 0.17963850111755636 + 0.1796434538164137 + 0.17964840664562892 + 0.17965335960520709 + 0.17965831269515301 + 0.17966326591547163 + 0.17966821926616827 + 0.17967317274724764 + 0.17967812635871477 + 0.17968308010057465 + 0.17968803397283223 + 0.17969298797549246 + 0.17969794210856038 + 0.17970289637204115 + 0.17970785076593934 + 0.17971280529026062 + 0.17971775994500924 + 0.17972271473019061 + 0.17972766964580947 + 0.17973262469187082 + 0.1797375798683799 + 0.17974253517534169 + 0.17974749061276074 + 0.17975244618064251 + 0.17975740187899183 + 0.17976235770781346 + 0.17976731366711274 + 0.17977226975689448 + 0.17977722597716386 + 0.17978218232792545 + 0.17978713880918462 + 0.17979209542094618 + 0.17979705216321526 + 0.17980200903599655 + 0.17980696603929536 + 0.17981192317311659 + 0.17981688043746524 + 0.17982183783234626 + 0.17982679535776439 + 0.17983175301372503 + 0.179836710800233 + 0.17984166871729329 + 0.1798466267649112 + 0.17985158494309092 + 0.17985654325183828 + 0.17986150169115783 + 0.1798664602610546 + 0.17987141896153364 + 0.17987637779259993 + 0.17988133675425852 + 0.17988629584651444 + 0.17989125506937254 + 0.17989621442283776 + 0.17990117390691537 + 0.17990613352161025 + 0.17991109326692703 + 0.17991605314287115 + 0.17992101314944753 + 0.17992597328666118 + 0.17993093355451692 + 0.1799358939530199 + 0.17994085448217481 + 0.17994581514198715 + 0.17995077593246148 + 0.17995573685360305 + 0.17996069790541697 + 0.17996565908790779 + 0.17997062040108067 + 0.17997558184494108 + 0.17998054341949321 + 0.1799855051247426 + 0.17999046696069415 + 0.17999542892735279 + 0.18000039102601667 + 0.18000535327542444 + 0.18001031564580988 + 0.18001527813717749 + 0.18002024074953188 + 0.18002520348287648 + 0.18003016633721586 + 0.18003512931255453 + 0.18004009240889654 + 0.18004505562624631 + 0.18005001896460798 + 0.18005498242398602 + 0.18005994600438446 + 0.18006490970580735 + 0.18006987352825968 + 0.18007483747174544 + 0.18007980153626865 + 0.18008476572183349 + 0.18008973002844472 + 0.1800946944561061 + 0.18009965900482255 + 0.18010462367459759 + 0.18010958846543579 + 0.18011455337734208 + 0.18011951841031962 + 0.18012448356437338 + 0.18012944883950732 + 0.18013441423572604 + 0.18013937975303357 + 0.18014434539143431 + 0.18014931115093247 + 0.18015427703153247 + 0.18015924303323838 + 0.18016420915605419 + 0.18016917539998498 + 0.18017414176503418 + 0.18017910825120692 + 0.18018407485850671 + 0.18018904158693802 + 0.18019400843650546 + 0.180198975407213 + 0.18020394249906516 + 0.18020890971206602 + 0.18021387704622002 + 0.18021884450153086 + 0.18022381207800389 + 0.18022877977564219 + 0.1802337475944509 + 0.18023871553443438 + 0.18024368359559584 + 0.18024865177794069 + 0.18025362008147292 + 0.18025858850619622 + 0.180263557052116 + 0.18026852571923488 + 0.18027349450755878 + 0.18027846341709128 + 0.18028343244783698 + 0.18028840159979936 + 0.18029337087298342 + 0.18029834026739325 + 0.18030330978303333 + 0.18030827941990776 + 0.18031324917802052 + 0.18031821905737619 + 0.18032318905797923 + 0.18032815917983333 + 0.18033312942294336 + 0.18033809978731347 + 0.18034307027294808 + 0.18034804087985082 + 0.18035301160802672 + 0.18035798245747972 + 0.18036295342821401 + 0.18036792452023448 + 0.18037289573354437 + 0.18037786706814898 + 0.18038283852405151 + 0.1803878101012574 + 0.1803927817997707 + 0.18039775361959459 + 0.18040272556073486 + 0.18040769762319483 + 0.18041266980697887 + 0.18041764211209199 + 0.18042261453853733 + 0.18042758708632037 + 0.18043255975544417 + 0.1804375325459143 + 0.18044250545773421 + 0.18044747849090809 + 0.18045245164544085 + 0.1804574249213361 + 0.18046239831859887 + 0.18046737183723266 + 0.18047234547724253 + 0.18047731923863208 + 0.18048229312140585 + 0.18048726712556828 + 0.18049224125112351 + 0.18049721549807607 + 0.18050218986642996 + 0.1805071643561893 + 0.18051213896735857 + 0.18051711369994231 + 0.18052208855394458 + 0.18052706352936992 + 0.18053203862622239 + 0.18053701384450607 + 0.18054198918422543 + 0.18054696464538464 + 0.18055194022798857 + 0.1805569159320409 + 0.18056189175754617 + 0.18056686770450836 + 0.18057184377293209 + 0.18057681996282135 + 0.18058179627418119 + 0.18058677270701518 + 0.18059174926132743 + 0.18059672593712281 + 0.18060170273440557 + 0.18060667965317961 + 0.18061165669344917 + 0.18061663385521909 + 0.18062161113849351 + 0.18062658854327646 + 0.18063156606957204 + 0.1806365437173853 + 0.18064152148671972 + 0.18064649937758034 + 0.18065147738997084 + 0.18065645552389561 + 0.18066143377935936 + 0.18066641215636603 + 0.18067139065491974 + 0.18067636927502503 + 0.18068134801668639 + 0.18068632687990796 + 0.18069130586469373 + 0.18069628497104831 + 0.18070126419897617 + 0.180706243548481 + 0.18071122301956768 + 0.18071620261224039 + 0.18072118232650319 + 0.18072616216236057 + 0.18073114211981661 + 0.18073612219887586 + 0.18074110239954244 + 0.1807460827218208 + 0.18075106316571504 + 0.18075604373122978 + 0.18076102441836897 + 0.18076600522713721 + 0.18077098615753862 + 0.18077596720957717 + 0.18078094838325795 + 0.18078592967858412 + 0.18079091109556106 + 0.18079589263419288 + 0.18080087429448322 + 0.18080585607643754 + 0.18081083798005854 + 0.1808158200053521 + 0.18082080215232138 + 0.180825784420971 + 0.18083076681130589 + 0.18083574932332921 + 0.18084073195704642 + 0.18084571471246072 + 0.18085069758957756 + 0.18085568058840049 + 0.18086066370893369 + 0.18086564695118168 + 0.18087063031514941 + 0.18087561380084008 + 0.18088059740825865 + 0.18088558113740927 + 0.180890564988296 + 0.18089554896092386 + 0.18090053305529638 + 0.18090551727141818 + 0.18091050160929337 + 0.18091548606892646 + 0.18092047065032199 + 0.18092545535348353 + 0.1809304401784162 + 0.18093542512512398 + 0.1809404101936106 + 0.18094539538388141 + 0.18095038069593966 + 0.18095536612979074 + 0.18096035168543795 + 0.18096533736288661 + 0.18097032316213993 + 0.18097530908320297 + 0.18098029512607974 + 0.18098528129077443 + 0.1809902675772915 + 0.18099525398563551 + 0.18100024051581054 + 0.18100522716782078 + 0.18101021394167061 + 0.18101520083736419 + 0.18102018785490614 + 0.18102517499430096 + 0.1810301622555523 + 0.1810351496386646 + 0.18104013714364253 + 0.18104512477049015 + 0.18105011251921202 + 0.18105510038981174 + 0.18106008838229479 + 0.18106507649666437 + 0.18107006473292545 + 0.1810750530910821 + 0.18108004157113849 + 0.18108503017309915 + 0.1810900188969686 + 0.18109500774275047 + 0.18109999671044982 + 0.18110498580007028 + 0.18110997501161633 + 0.18111496434509261 + 0.18111995380050358 + 0.18112494337785295 + 0.18112993307714528 + 0.18113492289838509 + 0.18113991284157607 + 0.18114490290672358 + 0.18114989309383087 + 0.18115488340290251 + 0.18115987383394347 + 0.181164864386957 + 0.18116985506194849 + 0.18117484585892163 + 0.18117983677788049 + 0.18118482781883008 + 0.18118981898177458 + 0.18119481026671752 + 0.1811998016736644 + 0.18120479320261845 + 0.18120978485358469 + 0.18121477662656713 + 0.18121976852156996 + 0.18122476053859762 + 0.18122975267765484 + 0.18123474493874514 + 0.1812397373218736 + 0.18124472982704382 + 0.1812497224542608 + 0.18125471520352823 + 0.18125970807485114 + 0.18126470106823314 + 0.18126969418367872 + 0.18127468742119263 + 0.18127968078077877 + 0.18128467426244135 + 0.18128966786618497 + 0.18129466159201404 + 0.18129965543993284 + 0.18130464940994487 + 0.18130964350205572 + 0.18131463771626896 + 0.18131963205258872 + 0.18132462651102002 + 0.18132962109156656 + 0.18133461579423277 + 0.18133961061902337 + 0.18134460556594231 + 0.18134960063499383 + 0.18135459582618246 + 0.18135959113951269 + 0.18136458657498827 + 0.18136958213261414 + 0.18137457781239405 + 0.18137957361433291 + 0.18138456953843446 + 0.18138956558470321 + 0.18139456175314414 + 0.18139955804376057 + 0.18140455445655698 + 0.18140955099153844 + 0.18141454764870854 + 0.18141954442807146 + 0.18142454132963215 + 0.18142953835339479 + 0.18143453549936345 + 0.18143953276754271 + 0.18144453015793621 + 0.18144952767054948 + 0.18145452530538608 + 0.18145952306245022 + 0.18146452094174645 + 0.18146951894327881 + 0.18147451706705242 + 0.18147951531307044 + 0.18148451368133831 + 0.18148951217185977 + 0.18149451078463885 + 0.18149950951968064 + 0.18150450837698878 + 0.18150950735656787 + 0.1815145064584224 + 0.18151950568255659 + 0.18152450502897444 + 0.18152950449768057 + 0.18153450408867916 + 0.1815395038019752 + 0.18154450363757182 + 0.18154950359547412 + 0.18155450367568624 + 0.1815595038782131 + 0.18156450420305759 + 0.18156950465022553 + 0.18157450521972024 + 0.18157950591154667 + 0.18158450672570894 + 0.18158950766221124 + 0.18159450872105806 + 0.18159950990225354 + 0.18160451120580182 + 0.18160951263170788 + 0.18161451417997551 + 0.18161951585060959 + 0.18162451764361384 + 0.1816295195589929 + 0.18163452159675081 + 0.18163952375689218 + 0.18164452603942161 + 0.18164952844434226 + 0.18165453097165965 + 0.18165953362137788 + 0.18166453639350155 + 0.18166953928803389 + 0.18167454230497987 + 0.18167954544434411 + 0.18168454870613074 + 0.1816895520903439 + 0.18169455559698808 + 0.18169955922606751 + 0.18170456297758672 + 0.18170956685154988 + 0.18171457084796103 + 0.18171957496682478 + 0.18172457920814578 + 0.18172958357192806 + 0.1817345880581758 + 0.18173959266689357 + 0.18174459739808554 + 0.18174960225175618 + 0.18175460722790976 + 0.18175961232655075 + 0.18176461754768281 + 0.1817696228913111 + 0.1817746283574401 + 0.18177963394607308 + 0.18178463965721503 + 0.18178964549087059 + 0.1817946514470434 + 0.18179965752573804 + 0.18180466372695958 + 0.18180967005071075 + 0.18181467649699753 + 0.18181968306582311 + 0.18182468975719251 + 0.18182969657110998 + 0.18183470350757949 + 0.18183971056660575 + 0.1818447177481928 + 0.18184972505234484 + 0.18185473247906689 + 0.18185974002836261 + 0.18186474770023661 + 0.18186975549469306 + 0.18187476341173639 + 0.18187977145137094 + 0.18188477961360164 + 0.18188978789843177 + 0.18189479630586583 + 0.18189980483590934 + 0.18190481348856516 + 0.18190982226383823 + 0.18191483116173324 + 0.18191984018225379 + 0.18192484932540492 + 0.1819298585911904 + 0.18193486797961514 + 0.18193987749068291 + 0.18194488712439835 + 0.18194989688076593 + 0.18195490675978943 + 0.18195991676147383 + 0.18196492688582286 + 0.18196993713284151 + 0.18197494750253357 + 0.18197995799490396 + 0.18198496860995647 + 0.18198997934769559 + 0.18199499020812557 + 0.18200000119125134 + 0.18200501229707625 + 0.18201002352560569 + 0.18201503487684301 + 0.18202004635079314 + 0.18202505794746029 + 0.18203006966684909 + 0.18203508150896314 + 0.18204009347380753 + 0.18204510556138642 + 0.18205011777170385 + 0.1820551301047641 + 0.18206014256057221 + 0.18206515513913177 + 0.18207016784044741 + 0.18207518066452374 + 0.18208019361136454 + 0.18208520668097514 + 0.18209021987335849 + 0.18209523318851997 + 0.18210024662646329 + 0.18210526018719309 + 0.18211027387071399 + 0.18211528767703006 + 0.18212030160614551 + 0.18212531565806495 + 0.18213032983279245 + 0.18213534413033264 + 0.18214035855068925 + 0.18214537309386772 + 0.18215038775987138 + 0.18215540254870524 + 0.18216041746037295 + 0.1821654324948796 + 0.18217044765222939 + 0.1821754629324259 + 0.18218047833547427 + 0.18218549386137914 + 0.18219050951014362 + 0.18219552528177332 + 0.18220054117627194 + 0.18220555719364356 + 0.18221057333389332 + 0.18221558959702483 + 0.18222060598304271 + 0.18222562249195165 + 0.1822306391237557 + 0.18223565587845911 + 0.18224067275606634 + 0.18224568975658167 + 0.18225070688000924 + 0.18225572412635405 + 0.18226074149561983 + 0.18226575898781119 + 0.18227077660293228 + 0.18227579434098773 + 0.18228081220198208 + 0.18228583018591907 + 0.18229084829280331 + 0.1822958665226394 + 0.18230088487543106 + 0.18230590335118335 + 0.1823109219498999 + 0.18231594067158588 + 0.18232095951624538 + 0.18232597848388213 + 0.18233099757450164 + 0.18233601678810668 + 0.18234103612470323 + 0.18234605558429451 + 0.1823510751668857 + 0.18235609487248039 + 0.18236111470108321 + 0.1823661346526988 + 0.18237115472733084 + 0.18237617492498445 + 0.18238119524566371 + 0.18238621568937277 + 0.18239123625611636 + 0.18239625694589806 + 0.18240127775872297 + 0.18240629869459571 + 0.18241131975351957 + 0.18241634093550008 + 0.18242136224054042 + 0.18242638366864569 + 0.18243140521982004 + 0.18243642689406805 + 0.182441448691394 + 0.18244647061180191 + 0.18245149265529609 + 0.18245651482188149 + 0.18246153711156229 + 0.18246655952434226 + 0.18247158206022637 + 0.18247660471921884 + 0.18248162750132435 + 0.18248665040654649 + 0.18249167343488995 + 0.18249669658635892 + 0.18250171986095834 + 0.18250674325869207 + 0.18251176677956513 + 0.18251679042358074 + 0.18252181419074398 + 0.18252683808105905 + 0.18253186209453054 + 0.18253688623116265 + 0.18254191049095955 + 0.18254693487392576 + 0.18255195938006558 + 0.18255698400938353 + 0.18256200876188386 + 0.18256703363757065 + 0.18257205863644904 + 0.18257708375852275 + 0.1825821090037959 + 0.18258713437227353 + 0.18259215986395946 + 0.18259718547885828 + 0.18260221121697504 + 0.18260723707831253 + 0.18261226306287631 + 0.18261728917067058 + 0.1826223154016994 + 0.18262734175596754 + 0.18263236823347864 + 0.18263739483423772 + 0.18264242155824906 + 0.18264744840551678 + 0.18265247537604504 + 0.18265750246983942 + 0.18266252968690222 + 0.18266755702723994 + 0.18267258449085533 + 0.18267761207775393 + 0.18268263978793947 + 0.18268766762141572 + 0.18269269557818812 + 0.18269772365826092 + 0.18270275186163829 + 0.1827077801883239 + 0.18271280863832332 + 0.18271783721163984 + 0.18272286590827849 + 0.18272789472824347 + 0.18273292367153893 + 0.18273795273816953 + 0.18274298192813992 + 0.18274801124145376 + 0.18275304067811571 + 0.18275807023812995 + 0.18276309992150114 + 0.18276812972823384 + 0.18277315965833182 + 0.18277818971179971 + 0.1827832198886421 + 0.18278825018886322 + 0.18279328061246769 + 0.1827983111594588 + 0.18280334182984251 + 0.18280837262362162 + 0.18281340354080169 + 0.18281843458138644 + 0.18282346574538058 + 0.18282849703278858 + 0.18283352844361431 + 0.18283855997786236 + 0.1828435916355369 + 0.18284862341664301 + 0.18285365532118444 + 0.18285868734916538 + 0.18286371950059091 + 0.18286875177546472 + 0.18287378417379146 + 0.18287881669557582 + 0.18288384934082191 + 0.1828888821095335 + 0.18289391500171615 + 0.18289894801737314 + 0.18290398115650947 + 0.18290901441912938 + 0.18291404780523707 + 0.18291908131483672 + 0.18292411494793342 + 0.18292914870453086 + 0.1829341825846342 + 0.18293921658824669 + 0.18294425071537385 + 0.182949284966019 + 0.18295431934018722 + 0.18295935383788262 + 0.18296438845910998 + 0.18296942320387297 + 0.1829744580721766 + 0.18297949306402475 + 0.18298452817942193 + 0.18298956341837291 + 0.18299459878088128 + 0.18299963426695226 + 0.1830046698765895 + 0.18300970560979815 + 0.18301474146658192 + 0.18301977744694548 + 0.18302481355089292 + 0.18302984977842859 + 0.18303488612955746 + 0.18303992260428373 + 0.18304495920261121 + 0.18304999592454496 + 0.18305503277008917 + 0.18306006973924804 + 0.18306510683202573 + 0.18307014404842689 + 0.18307518138845619 + 0.18308021885211734 + 0.18308525643941545 + 0.18309029415035477 + 0.18309533198493896 + 0.18310036994317266 + 0.18310540802506109 + 0.18311044623060782 + 0.18311548455981716 + 0.18312052301269369 + 0.18312556158924259 + 0.18313060028946665 + 0.18313563911337141 + 0.18314067806096107 + 0.18314571713223982 + 0.18315075632721192 + 0.18315579564588191 + 0.18316083508825409 + 0.18316587465433307 + 0.183170914344123 + 0.18317595415762861 + 0.183180994094854 + 0.18318603415580348 + 0.18319107434048115 + 0.18319611464889218 + 0.18320115508104032 + 0.18320619563693011 + 0.18321123631656586 + 0.1832162771199527 + 0.1832213180470938 + 0.18322635909799434 + 0.18323140027265855 + 0.18323644157109059 + 0.18324148299329457 + 0.18324652453927581 + 0.18325156620903829 + 0.18325660800258595 + 0.18326164991992372 + 0.18326669196105588 + 0.18327173412598669 + 0.18327677641472029 + 0.18328181882726133 + 0.18328686136361402 + 0.18329190402378345 + 0.18329694680777295 + 0.18330198971558759 + 0.18330703274723165 + 0.18331207590270923 + 0.18331711918202509 + 0.1833221625851838 + 0.18332720611218872 + 0.18333224976304535 + 0.18333729353775749 + 0.1833423374363298 + 0.18334738145876647 + 0.18335242560507173 + 0.18335746987525059 + 0.1833625142693065 + 0.18336755878724495 + 0.18337260342906969 + 0.18337764819478489 + 0.18338269308439528 + 0.18338773809790548 + 0.18339278323531927 + 0.1833978284966413 + 0.1834028738818762 + 0.18340791939102821 + 0.18341296502410157 + 0.18341801078110084 + 0.18342305666203035 + 0.18342810266689469 + 0.18343314879569764 + 0.18343819504844425 + 0.18344324142513835 + 0.1834482879257851 + 0.18345333455038818 + 0.18345838129895223 + 0.18346342817148151 + 0.18346847516798065 + 0.18347352228845393 + 0.18347856953290592 + 0.18348361690134046 + 0.18348866439376216 + 0.18349371201017617 + 0.18349875975058583 + 0.18350380761499613 + 0.18350885560341099 + 0.1835139037158354 + 0.18351895195227369 + 0.18352400031272947 + 0.18352904879720802 + 0.18353409740571344 + 0.18353914613825001 + 0.18354419499482236 + 0.18354924397543429 + 0.18355429308009083 + 0.18355934230879634 + 0.18356439166155486 + 0.18356944113837079 + 0.18357449073924911 + 0.18357954046419364 + 0.18358459031320865 + 0.18358964028629915 + 0.18359469038346896 + 0.18359974060472276 + 0.18360479095006521 + 0.18360984141950007 + 0.18361489201303202 + 0.18361994273066573 + 0.18362499357240497 + 0.18363004453825485 + 0.18363509562821959 + 0.18364014684230343 + 0.18364519818051009 + 0.1836502496428456 + 0.18365530122931251 + 0.18366035293991667 + 0.18366540477466187 + 0.18367045673355248 + 0.18367550881659303 + 0.1836805610237878 + 0.18368561335514097 + 0.18369066581065774 + 0.18369571839034177 + 0.1837007710941978 + 0.18370582392222964 + 0.18371087687444279 + 0.18371592995084066 + 0.18372098315142782 + 0.18372603647620905 + 0.18373108992518847 + 0.18373614349837081 + 0.18374119719575985 + 0.18374625101736072 + 0.18375130496317713 + 0.18375635903321388 + 0.18376141322747555 + 0.18376646754596593 + 0.18377152198869015 + 0.18377657655565197 + 0.18378163124685615 + 0.18378668606230683 + 0.18379174100200918 + 0.18379679606596647 + 0.18380185125418344 + 0.18380690656666521 + 0.1838119620034151 + 0.18381701756443869 + 0.18382207324973932 + 0.18382712905932205 + 0.18383218499319076 + 0.18383724105135049 + 0.18384229723380513 + 0.18384735354055928 + 0.18385240997161761 + 0.1838574665269839 + 0.18386252320666291 + 0.18386758001065925 + 0.18387263693897718 + 0.18387769399162088 + 0.18388275116859515 + 0.1838878084699036 + 0.18389286589555151 + 0.18389792344554309 + 0.18390298111988249 + 0.18390803891857399 + 0.1839130968416228 + 0.18391815488903257 + 0.18392321306080761 + 0.18392827135695305 + 0.18393332977747223 + 0.18393838832237067 + 0.18394344699165227 + 0.18394850578532163 + 0.18395356470338253 + 0.18395862374584016 + 0.18396368291269868 + 0.18396874220396245 + 0.18397380161963606 + 0.18397886115972328 + 0.18398392082422885 + 0.18398898061315785 + 0.18399404052651328 + 0.18399910056430105 + 0.18400416072652503 + 0.18400922101318898 + 0.18401428142429804 + 0.18401934195985689 + 0.18402440261986885 + 0.18402946340433912 + 0.18403452431327233 + 0.18403958534667189 + 0.18404464650454286 + 0.18404970778688998 + 0.18405476919371747 + 0.1840598307250291 + 0.18406489238082963 + 0.18406995416112412 + 0.18407501606591639 + 0.18408007809521026 + 0.18408514024901129 + 0.18409020252732328 + 0.18409526493015094 + 0.18410032745749805 + 0.18410539010936977 + 0.18411045288577024 + 0.18411551578670388 + 0.18412057881217478 + 0.18412564196218814 + 0.18413070523674732 + 0.18413576863585746 + 0.18414083215952323 + 0.18414589580774807 + 0.18415095958053693 + 0.18415602347789467 + 0.18416108749982502 + 0.18416615164633227 + 0.18417121591742194 + 0.18417628031309702 + 0.18418134483336304 + 0.18418640947822379 + 0.18419147424768406 + 0.18419653914174797 + 0.18420160416042028 + 0.1842066693037048 + 0.18421173457160664 + 0.18421679996412965 + 0.18422186548127892 + 0.18422693112305785 + 0.18423199688947203 + 0.18423706278052474 + 0.18424212879622168 + 0.18424719493656613 + 0.18425226120156285 + 0.18425732759121644 + 0.18426239410553125 + 0.18426746074451147 + 0.18427252750816184 + 0.18427759439648658 + 0.18428266140949048 + 0.18428772854717718 + 0.18429279580955196 + 0.18429786319661853 + 0.18430293070838172 + 0.1843079983448461 + 0.18431306610601558 + 0.18431813399189523 + 0.18432320200248886 + 0.18432827013780076 + 0.18433333839783606 + 0.18433840678259911 + 0.18434347529209352 + 0.1843485439263246 + 0.18435361268529613 + 0.18435868156901319 + 0.1843637505774797 + 0.18436881971070029 + 0.18437388896867873 + 0.18437895835142068 + 0.18438402785892954 + 0.18438909749121038 + 0.18439416724826707 + 0.18439923713010431 + 0.18440430713672673 + 0.18440937726813822 + 0.18441444752434391 + 0.18441951790534764 + 0.18442458841115406 + 0.18442965904176742 + 0.18443472979719203 + 0.18443980067743307 + 0.18444487168249429 + 0.18444994281238 + 0.18445501406709527 + 0.1844600854466445 + 0.18446515695103094 + 0.18447022858026021 + 0.18447530033433662 + 0.18448037221326435 + 0.18448544421704735 + 0.18449051634569111 + 0.18449558859919896 + 0.1845006609775762 + 0.18450573348082702 + 0.18451080610895521 + 0.18451587886196594 + 0.18452095173986349 + 0.18452602474265214 + 0.18453109787033656 + 0.18453617112292059 + 0.1845412445004094 + 0.18454631800280724 + 0.18455139163011794 + 0.18455646538234663 + 0.18456153925949761 + 0.18456661326157514 + 0.18457168738858346 + 0.1845767616405273 + 0.18458183601741096 + 0.18458691051923909 + 0.18459198514601596 + 0.18459705989774591 + 0.18460213477443319 + 0.18460720977608286 + 0.18461228490269932 + 0.18461736015428587 + 0.18462243553084812 + 0.18462751103239036 + 0.18463258665891644 + 0.18463766241043147 + 0.18464273828693931 + 0.18464781428844468 + 0.18465289041495181 + 0.18465796666646542 + 0.18466304304298983 + 0.18466811954452925 + 0.18467319617108843 + 0.18467827292267169 + 0.18468334979928319 + 0.1846884268009282 + 0.18469350392761 + 0.1846985811793343 + 0.18470365855610446 + 0.18470873605792515 + 0.18471381368480111 + 0.18471889143673617 + 0.18472396931373594 + 0.18472904731580339 + 0.1847341254429441 + 0.18473920369516231 + 0.18474428207246194 + 0.18474936057484759 + 0.18475443920232412 + 0.18475951795489526 + 0.18476459683256616 + 0.18476967583534076 + 0.18477475496322415 + 0.18477983421621971 + 0.18478491359433313 + 0.18478999309756769 + 0.18479507272592816 + 0.18480015247941975 + 0.18480523235804577 + 0.18481031236181142 + 0.18481539249072104 + 0.18482047274477842 + 0.1848255531239891 + 0.18483063362835656 + 0.1848357142578855 + 0.18484079501258058 + 0.18484587589244625 + 0.1848509568974866 + 0.1848560380277065 + 0.18486111928310967 + 0.1848662006637018 + 0.18487128216948578 + 0.18487636380046732 + 0.18488144555665068 + 0.18488652743803957 + 0.18489160944463884 + 0.18489669157645322 + 0.18490177383348649 + 0.18490685621574382 + 0.18491193872322953 + 0.18491702135594745 + 0.18492210411390284 + 0.18492718699709931 + 0.1849322700055418 + 0.18493735313923451 + 0.18494243639818223 + 0.18494751978238963 + 0.18495260329186008 + 0.18495768692659878 + 0.18496277068661054 + 0.1849678545718991 + 0.18497293858246877 + 0.18497802271832478 + 0.18498310697947132 + 0.18498819136591232 + 0.18499327587765246 + 0.18499836051469656 + 0.18500344527704876 + 0.1850085301647135 + 0.18501361517769535 + 0.18501870031599876 + 0.18502378557962793 + 0.18502887096858761 + 0.18503395648288165 + 0.18503904212251562 + 0.18504412788749253 + 0.18504921377781808 + 0.18505429979349641 + 0.18505938593453145 + 0.18506447220092792 + 0.18506955859269053 + 0.18507464510982366 + 0.18507973175233147 + 0.18508481852021841 + 0.18508990541348905 + 0.18509499243214819 + 0.18510007957619973 + 0.18510516684564834 + 0.18511025424049835 + 0.18511534176075448 + 0.18512042940642104 + 0.18512551717750234 + 0.18513060507400306 + 0.18513569309592753 + 0.18514078124328004 + 0.18514586951606579 + 0.18515095791428815 + 0.18515604643795189 + 0.18516113508706172 + 0.18516622386162243 + 0.18517131276163787 + 0.18517640178711225 + 0.18518149093805084 + 0.18518658021445789 + 0.18519166961633726 + 0.18519675914369371 + 0.18520184879653204 + 0.18520693857485643 + 0.18521202847867166 + 0.1852171185079812 + 0.18522220866279013 + 0.18522729894310327 + 0.18523238934892491 + 0.18523747988025938 + 0.18524257053711046 + 0.18524766131948384 + 0.18525275222738333 + 0.18525784326081282 + 0.18526293441977795 + 0.18526802570428208 + 0.18527311711433045 + 0.18527820864992731 + 0.18528330031107706 + 0.18528839209778389 + 0.18529348401005261 + 0.18529857604788755 + 0.18530366821129288 + 0.18530876050027395 + 0.18531385291483404 + 0.18531894545497848 + 0.18532403812071147 + 0.18532913091203729 + 0.18533422382896081 + 0.1853393168714858 + 0.18534441003961702 + 0.18534950333335964 + 0.18535459675271673 + 0.18535969029769428 + 0.18536478396829523 + 0.18536987776452529 + 0.18537497168638833 + 0.18538006573388865 + 0.18538515990703139 + 0.1853902542058205 + 0.18539534863026019 + 0.18540044318035573 + 0.18540553785611047 + 0.18541063265752969 + 0.18541572758461805 + 0.18542082263737905 + 0.1854259178158183 + 0.18543101311993918 + 0.18543610854974654 + 0.18544120410524548 + 0.18544629978643939 + 0.18545139559333362 + 0.18545649152593194 + 0.18546158758423953 + 0.18546668376826031 + 0.18547178007799858 + 0.18547687651345945 + 0.18548197307464692 + 0.1854870697615657 + 0.18549216657422007 + 0.18549726351261434 + 0.18550236057675332 + 0.18550745776664124 + 0.1855125550822829 + 0.18551765252368269 + 0.18552275009084432 + 0.1855278477837731 + 0.1855329456024733 + 0.18553804354694931 + 0.18554314161720531 + 0.1855482398132462 + 0.18555333813507663 + 0.18555843658270052 + 0.1855635351561222 + 0.18556863385534683 + 0.1855737326803783 + 0.1855788316312218 + 0.18558393070788082 + 0.18558902991036003 + 0.1855941292386647 + 0.18559922869279863 + 0.18560432827276621 + 0.18560942797857222 + 0.18561452781022131 + 0.18561962776771701 + 0.1856247278510649 + 0.18562982806026898 + 0.18563492839533341 + 0.18564002885626349 + 0.18564512944306255 + 0.18565023015573598 + 0.18565533099428791 + 0.18566043195872281 + 0.18566553304904487 + 0.18567063426525943 + 0.18567573560737022 + 0.18568083707538119 + 0.18568593866929803 + 0.18569104038912457 + 0.18569614223486561 + 0.1857012442065254 + 0.18570634630410834 + 0.18571144852761867 + 0.18571655087706129 + 0.18572165335244037 + 0.18572675595376076 + 0.18573185868102676 + 0.18573696153424271 + 0.18574206451341296 + 0.18574716761854268 + 0.18575227084963525 + 0.18575737420669597 + 0.18576247768972914 + 0.1857675812987391 + 0.18577268503373059 + 0.18577778889470747 + 0.18578289288167502 + 0.18578799699463705 + 0.18579310123359841 + 0.18579820559856339 + 0.18580331008953624 + 0.18580841470652226 + 0.18581351944952537 + 0.18581862431854931 + 0.18582372931359992 + 0.18582883443468093 + 0.18583393968179721 + 0.18583904505495255 + 0.18584415055415229 + 0.18584925617940024 + 0.18585436193070068 + 0.1858594678080594 + 0.18586457381147928 + 0.18586967994096554 + 0.18587478619652259 + 0.18587989257815521 + 0.18588499908586717 + 0.18589010571966375 + 0.1858952124795489 + 0.18590031936552687 + 0.18590542637760291 + 0.18591053351578088 + 0.18591564078006556 + 0.18592074817046184 + 0.18592585568697295 + 0.18593096332960435 + 0.18593607109836016 + 0.18594117899324525 + 0.18594628701426349 + 0.18595139516141976 + 0.1859565034347187 + 0.18596161183416424 + 0.18596672035976117 + 0.18597182901151427 + 0.18597693778942739 + 0.18598204669350588 + 0.18598715572375307 + 0.18599226488017462 + 0.18599737416277404 + 0.18600248357155599 + 0.18600759310652545 + 0.18601270276768658 + 0.18601781255504385 + 0.18602292246860241 + 0.18602803250836525 + 0.18603314267433801 + 0.18603825296652515 + 0.18604336338493049 + 0.18604847392955925 + 0.18605358460041532 + 0.1860586953975035 + 0.18606380632082814 + 0.18606891737039399 + 0.18607402854620539 + 0.18607913984826627 + 0.18608425127658187 + 0.18608936283115646 + 0.18609447451199446 + 0.18609958631910056 + 0.18610469825247877 + 0.18610981031213378 + 0.18611492249807041 + 0.18612003481029302 + 0.18612514724880544 + 0.186130259813613 + 0.18613537250471998 + 0.18614048532213032 + 0.18614559826584914 + 0.18615071133588093 + 0.18615582453222945 + 0.18616093785490009 + 0.18616605130389707 + 0.18617116487922433 + 0.18617627858088709 + 0.18618139240888926 + 0.18618650636323564 + 0.18619162044393101 + 0.18619673465097925 + 0.18620184898438472 + 0.18620696344415311 + 0.18621207803028744 + 0.18621719274279286 + 0.1862223075816743 + 0.18622742254693558 + 0.18623253763858147 + 0.18623765285661589 + 0.1862427682010446 + 0.18624788367187051 + 0.18625299926909974 + 0.18625811499273545 + 0.18626323084278268 + 0.18626834681924592 + 0.18627346292212943 + 0.18627857915143856 + 0.18628369550717666 + 0.18628881198934849 + 0.18629392859795899 + 0.18629904533301198 + 0.18630416219451321 + 0.18630927918246556 + 0.1863143962968748 + 0.18631951353774442 + 0.18632463090507964 + 0.18632974839888478 + 0.18633486601916419 + 0.18633998376592267 + 0.18634510163916418 + 0.18635021963889398 + 0.18635533776511581 + 0.18636045601783424 + 0.18636557439705431 + 0.18637069290278013 + 0.18637581153501587 + 0.18638093029376684 + 0.18638604917903701 + 0.18639116819083065 + 0.18639628732915306 + 0.18640140659400772 + 0.18640652598539975 + 0.18641164550333367 + 0.18641676514781372 + 0.18642188491884476 + 0.18642700481643115 + 0.1864321248405767 + 0.18643724499128678 + 0.18644236526856567 + 0.18644748567241778 + 0.18645260620284743 + 0.18645772685985945 + 0.18646284764345816 + 0.18646796855364794 + 0.18647308959043357 + 0.18647821075381948 + 0.18648333204380999 + 0.18648845346040938 + 0.18649357500362299 + 0.18649869667345428 + 0.18650381846990891 + 0.18650894039299037 + 0.18651406244270349 + 0.18651918461905304 + 0.18652430692204294 + 0.18652942935167799 + 0.186534551907963 + 0.18653967459090187 + 0.18654479740049995 + 0.18654992033676099 + 0.18655504339968945 + 0.18656016658929017 + 0.18656528990556795 + 0.18657041334852659 + 0.186575536918171 + 0.18658066061450557 + 0.18658578443753457 + 0.18659090838726333 + 0.18659603246369527 + 0.18660115666683569 + 0.18660628099668847 + 0.18661140545325886 + 0.18661653003655079 + 0.18662165474656917 + 0.18662677958331775 + 0.1866319045468019 + 0.1866370296370255 + 0.18664215485399333 + 0.18664728019770987 + 0.18665240566818025 + 0.18665753126540757 + 0.18666265698939752 + 0.18666778284015398 + 0.18667290881768184 + 0.18667803492198543 + 0.1866831611530691 + 0.18668828751093766 + 0.1866934139955955 + 0.18669854060704702 + 0.18670366734529698 + 0.18670879421034928 + 0.18671392120220928 + 0.18671904832088126 + 0.18672417556636922 + 0.18672930293867787 + 0.18673443043781165 + 0.18673955806377587 + 0.18674468581657397 + 0.18674981369621113 + 0.18675494170269133 + 0.18676006983601945 + 0.18676519809619976 + 0.18677032648323716 + 0.18677545499713599 + 0.18678058363790059 + 0.18678571240553585 + 0.18679084130004514 + 0.18679597032143477 + 0.18680109946970766 + 0.18680622874486955 + 0.18681135814692393 + 0.18681648767587561 + 0.18682161733172986 + 0.18682674711449021 + 0.1868318770241614 + 0.18683700706074827 + 0.18684213722425475 + 0.18684726751468617 + 0.18685239793204642 + 0.1868575284763398 + 0.18686265914757169 + 0.18686778994574596 + 0.18687292087086751 + 0.1868780519229401 + 0.18688318310196922 + 0.18688831440795911 + 0.18689344584091369 + 0.18689857740083785 + 0.18690370908773637 + 0.18690884090161319 + 0.18691397284247366 + 0.18691910491032113 + 0.18692423710516143 + 0.18692936942699795 + 0.18693450187583605 + 0.18693963445167958 + 0.18694476715453343 + 0.18694989998440201 + 0.18695503294129007 + 0.18696016602520152 + 0.1869652992361413 + 0.18697043257411416 + 0.18697556603912407 + 0.18698069963117636 + 0.18698583335027433 + 0.18699096719642339 + 0.18699610116962792 + 0.18700123526989235 + 0.18700636949722091 + 0.18701150385161902 + 0.1870166383330901 + 0.18702177294163899 + 0.18702690767727057 + 0.18703204253998909 + 0.18703717752979909 + 0.18704231264670579 + 0.1870474478907122 + 0.18705258326182414 + 0.1870577187600454 + 0.18706285438538092 + 0.18706799013783512 + 0.18707312601741222 + 0.18707826202411726 + 0.18708339815795449 + 0.18708853441892828 + 0.18709367080704312 + 0.18709880732230377 + 0.18710394396471514 + 0.18710908073428062 + 0.187114217631006 + 0.18711935465489479 + 0.18712449180595223 + 0.18712962908418224 + 0.18713476648958977 + 0.18713990402217906 + 0.18714504168195506 + 0.18715017946892218 + 0.18715531738308422 + 0.18716045542444656 + 0.1871655935930131 + 0.18717073188878924 + 0.18717587031177829 + 0.18718100886198569 + 0.18718614753941576 + 0.18719128634407342 + 0.18719642527596203 + 0.187201564335087 + 0.18720670352145263 + 0.18721184283506384 + 0.18721698227592448 + 0.1872221218440395 + 0.18722726153941327 + 0.1872324013620501 + 0.18723754131195533 + 0.1872426813891325 + 0.18724782159358686 + 0.18725296192532229 + 0.18725810238434373 + 0.18726324297065605 + 0.1872683836842631 + 0.18727352452516979 + 0.18727866549337999 + 0.18728380658889951 + 0.18728894781173183 + 0.18729408916188137 + 0.18729923063935386 + 0.18730437224415231 + 0.18730951397628245 + 0.18731465583574833 + 0.18731979782255423 + 0.18732493993670463 + 0.18733008217820529 + 0.18733522454705875 + 0.1873403670432712 + 0.18734550966684665 + 0.18735065241778942 + 0.18735579529610399 + 0.18736093830179512 + 0.18736608143486735 + 0.18737122469532488 + 0.18737636808317273 + 0.18738151159841526 + 0.1873866552410568 + 0.18739179901110223 + 0.18739694290855557 + 0.18740208693342159 + 0.18740723108570517 + 0.18741237536541075 + 0.1874175197725422 + 0.18742266430710444 + 0.18742780896910227 + 0.18743295375854013 + 0.18743809867542241 + 0.18744324371975354 + 0.18744838889153834 + 0.1874535341907812 + 0.18745867961748658 + 0.18746382517165927 + 0.18746897085330322 + 0.18747411666242383 + 0.1874792625990245 + 0.18748440866311103 + 0.18748955485468732 + 0.18749470117375747 + 0.18749984762032712 + 0.18750499419439975 + 0.18751014089598073 + 0.18751528772507356 + 0.18752043468168356 + 0.18752558176581555 + 0.187530728977473 + 0.18753587631666127 + 0.1875410237833848 + 0.18754617137764798 + 0.18755131909945519 + 0.18755646694881126 + 0.18756161492572063 + 0.18756676303018777 + 0.18757191126221742 + 0.18757705962181409 + 0.18758220810898169 + 0.18758735672372553 + 0.18759250546605008 + 0.18759765433595921 + 0.18760280333345827 + 0.18760795245855122 + 0.18761310171124343 + 0.18761825109153829 + 0.18762340059944121 + 0.18762855023495606 + 0.18763369999808782 + 0.1876388498888408 + 0.18764399990721994 + 0.1876491500532296 + 0.18765430032687372 + 0.18765945072815818 + 0.18766460125708595 + 0.18766975191366275 + 0.18767490269789264 + 0.18768005360977999 + 0.18768520464932967 + 0.18769035581654608 + 0.18769550711143368 + 0.18770065853399781 + 0.18770581008424134 + 0.18771096176217075 + 0.18771611356778892 + 0.18772126550110127 + 0.18772641756211214 + 0.18773156975082642 + 0.18773672206724815 + 0.18774187451138205 + 0.18774702708323268 + 0.18775217978280437 + 0.18775733261010202 + 0.18776248556513006 + 0.18776763864789339 + 0.18777279185839538 + 0.18777794519664198 + 0.18778309866263704 + 0.18778825225638504 + 0.18779340597789079 + 0.18779855982715835 + 0.18780371380419295 + 0.18780886790899909 + 0.18781402214158019 + 0.1878191765019426 + 0.1878243309900893 + 0.18782948560602561 + 0.18783464034975597 + 0.18783979522128483 + 0.18784495022061654 + 0.18785010534775654 + 0.18785526060270821 + 0.18786041598547654 + 0.18786557149606636 + 0.18787072713448205 + 0.18787588290072815 + 0.18788103879480894 + 0.18788619481672938 + 0.18789135096649387 + 0.18789650724410684 + 0.18790166364957273 + 0.18790682018289634 + 0.1879119768440827 + 0.1879171336331352 + 0.18792229055005916 + 0.18792744759485916 + 0.1879326047675399 + 0.18793776206810495 + 0.1879429194965597 + 0.1879480770529085 + 0.18795323473715631 + 0.18795839254930657 + 0.18796355048936514 + 0.18796870855733597 + 0.18797386675322342 + 0.18797902507703246 + 0.187984183528767 + 0.18798934210843246 + 0.18799450081603269 + 0.18799965965157225 + 0.18800481861505638 + 0.18800997770648908 + 0.18801513692587526 + 0.18802029627321892 + 0.18802545574852528 + 0.18803061535179802 + 0.18803577508304273 + 0.18804093494226318 + 0.1880460949294645 + 0.18805125504465078 + 0.18805641528782635 + 0.18806157565899623 + 0.18806673615816519 + 0.18807189678533778 + 0.18807705754051787 + 0.1880822184237104 + 0.18808737943491974 + 0.18809254057415081 + 0.18809770184140812 + 0.18810286323669601 + 0.18810802476001939 + 0.18811318641138222 + 0.18811834819078946 + 0.18812351009824596 + 0.1881286721337557 + 0.18813383429732353 + 0.18813899658895389 + 0.18814415900865128 + 0.18814932155642008 + 0.18815448423226569 + 0.18815964703619195 + 0.18816480996820348 + 0.18816997302830513 + 0.18817513621650078 + 0.18818029953279583 + 0.18818546297719424 + 0.18819062654970145 + 0.1881957902503209 + 0.18820095407905751 + 0.18820611803591619 + 0.18821128212090132 + 0.18821644633401741 + 0.1882216106752688 + 0.18822677514466052 + 0.1882319397421969 + 0.18823710446788242 + 0.18824226932172156 + 0.1882474343037196 + 0.18825259941388006 + 0.18825776465220792 + 0.18826293001870797 + 0.18826809551338428 + 0.18827326113624218 + 0.18827842688728569 + 0.18828359276651913 + 0.18828875877394755 + 0.18829392490957572 + 0.18829909117340771 + 0.18830425756544797 + 0.18830942408570178 + 0.18831459073417267 + 0.18831975751086613 + 0.18832492441578644 + 0.1883300914489377 + 0.18833525861032518 + 0.1883404258999534 + 0.1883455933178263 + 0.18835076086394878 + 0.18835592853832528 + 0.18836109634096079 + 0.18836626427185965 + 0.1883714323310263 + 0.1883766005184653 + 0.18838176883418192 + 0.18838693727817923 + 0.18839210585046309 + 0.18839727455103741 + 0.18840244337990725 + 0.1884076123370769 + 0.18841278142255088 + 0.18841795063633404 + 0.18842311997843048 + 0.18842828944884549 + 0.18843345904758302 + 0.18843862877464757 + 0.18844379863004404 + 0.18844896861377691 + 0.18845413872585057 + 0.18845930896626997 + 0.18846447933503951 + 0.18846964983216324 + 0.18847482045764696 + 0.18847999121149378 + 0.18848516209370941 + 0.18849033310429755 + 0.18849550424326386 + 0.18850067551061206 + 0.18850584690634642 + 0.18851101843047283 + 0.18851619008299444 + 0.18852136186391649 + 0.18852653377324355 + 0.18853170581098044 + 0.18853687797713126 + 0.18854205027170035 + 0.18854722269469315 + 0.18855239524611361 + 0.18855756792596667 + 0.18856274073425633 + 0.18856791367098755 + 0.18857308673616513 + 0.1885782599297931 + 0.18858343325187646 + 0.18858860670241956 + 0.18859378028142737 + 0.18859895398890392 + 0.18860412782485403 + 0.18860930178928217 + 0.18861447588219338 + 0.18861965010359152 + 0.18862482445348155 + 0.18862999893186841 + 0.18863517353875561 + 0.18864034827414902 + 0.18864552313805211 + 0.18865069813047031 + 0.18865587325140762 + 0.18866104850086848 + 0.18866622387885831 + 0.18867139938538102 + 0.18867657502044116 + 0.18868175078404406 + 0.18868692667619333 + 0.18869210269689379 + 0.18869727884615034 + 0.18870245512396761 + 0.18870763153034989 + 0.18871280806530175 + 0.18871798472882806 + 0.1887231615209328 + 0.18872833844162093 + 0.18873351549089734 + 0.18873869266876653 + 0.18874386997523249 + 0.18874904741030016 + 0.18875422497397445 + 0.18875940266625926 + 0.18876458048715972 + 0.18876975843668015 + 0.18877493651482546 + 0.18878011472159972 + 0.18878529305700786 + 0.1887904715210543 + 0.18879565011374355 + 0.18880082883508092 + 0.18880600768507003 + 0.1888111866637158 + 0.18881636577102265 + 0.18882154500699597 + 0.18882672437163939 + 0.18883190386495768 + 0.18883708348695594 + 0.18884226323763809 + 0.18884744311700902 + 0.18885262312507375 + 0.18885780326183577 + 0.18886298352730094 + 0.18886816392147279 + 0.18887334444435674 + 0.18887852509595679 + 0.18888370587627781 + 0.18888888678532395 + 0.18889406782310042 + 0.18889924898961141 + 0.18890443028486173 + 0.18890961170885587 + 0.1889147932615983 + 0.18891997494309401 + 0.18892515675334692 + 0.18893033869236203 + 0.18893552076014425 + 0.1889407029566971 + 0.18894588528202649 + 0.18895106773613643 + 0.18895625031903088 + 0.18896143303071572 + 0.18896661587119445 + 0.18897179884047163 + 0.18897698193855314 + 0.18898216516544195 + 0.18898734852114357 + 0.18899253200566235 + 0.18899771561900286 + 0.18900289936117048 + 0.18900808323216833 + 0.18901326723200171 + 0.18901845136067563 + 0.18902363561819413 + 0.18902882000456209 + 0.18903400451978403 + 0.18903918916386436 + 0.18904437393680756 + 0.18904955883861915 + 0.18905474386930213 + 0.18905992902886279 + 0.18906511431730427 + 0.18907029973463246 + 0.18907548528085083 + 0.1890806709559649 + 0.1890858567599781 + 0.18909104269289642 + 0.18909622875472376 + 0.18910141494546465 + 0.18910660126512313 + 0.18911178771370502 + 0.18911697429121435 + 0.18912216099765564 + 0.18912734783303334 + 0.1891325347973524 + 0.18913772189061726 + 0.18914290911283241 + 0.18914809646400238 + 0.18915328394413211 + 0.18915847155322604 + 0.18916365929128873 + 0.18916884715832499 + 0.18917403515433895 + 0.18917922327933503 + 0.18918441153331872 + 0.18918959991629439 + 0.18919478842826615 + 0.1891999770692385 + 0.1892051658392167 + 0.18921035473820497 + 0.18921554376620814 + 0.18922073292323072 + 0.18922592220927673 + 0.18923111162435152 + 0.18923630116845969 + 0.18924149084160521 + 0.18924668064379349 + 0.1892518705750281 + 0.18925706063531486 + 0.18926225082465742 + 0.18926744114306066 + 0.18927263159052912 + 0.18927782216706768 + 0.18928301287268043 + 0.18928820370737276 + 0.1892933946711487 + 0.18929858576401268 + 0.18930377698596929 + 0.1893089683370239 + 0.18931415981718053 + 0.18931935142644415 + 0.18932454316481878 + 0.18932973503230932 + 0.18933492702892032 + 0.18934011915465671 + 0.18934531140952299 + 0.18935050379352319 + 0.18935569630666227 + 0.18936088894894518 + 0.18936608172037592 + 0.18937127462095993 + 0.18937646765070085 + 0.18938166080960392 + 0.18938685409767336 + 0.18939204751491398 + 0.18939724106133035 + 0.18940243473692694 + 0.1894076285417087 + 0.1894128224756802 + 0.1894180165388458 + 0.1894232107312101 + 0.18942840505277753 + 0.18943359950355312 + 0.18943879408354175 + 0.18944398879274707 + 0.18944918363117441 + 0.18945437859882786 + 0.18945957369571287 + 0.18946476892183337 + 0.18946996427719395 + 0.18947515976179949 + 0.18948035537565414 + 0.18948555111876325 + 0.18949074699113086 + 0.1894959429927619 + 0.18950113912366046 + 0.18950633538383196 + 0.18951153177327992 + 0.18951672829201024 + 0.18952192494002654 + 0.18952712171733421 + 0.18953231862393688 + 0.18953751565983992 + 0.18954271282504778 + 0.18954791011956512 + 0.18955310754339577 + 0.18955830509654575 + 0.18956350277901865 + 0.1895687005908194 + 0.18957389853195245 + 0.18957909660242289 + 0.18958429480223413 + 0.18958949313139264 + 0.18959469158990153 + 0.18959989017776568 + 0.18960508889499017 + 0.18961028774157948 + 0.18961548671753803 + 0.18962068582287037 + 0.18962588505758107 + 0.18963108442167501 + 0.18963628391515713 + 0.18964148353803112 + 0.18964668329030235 + 0.18965188317197534 + 0.18965708318305458 + 0.18966228332354415 + 0.18966748359344937 + 0.18967268399277487 + 0.18967788452152465 + 0.1896830851797042 + 0.18968828596731746 + 0.18969348688436943 + 0.18969868793086422 + 0.18970388910680672 + 0.18970909041220146 + 0.18971429184705338 + 0.18971949341136712 + 0.18972469510514661 + 0.18972989692839778 + 0.18973509888112375 + 0.18974030096332944 + 0.18974550317502037 + 0.18975070551620055 + 0.18975590798687444 + 0.18976111058704714 + 0.18976631331672256 + 0.18977151617590621 + 0.18977671916460215 + 0.1897819222828149 + 0.1897871255305493 + 0.18979232890781003 + 0.18979753241460154 + 0.18980273605092882 + 0.18980793981679589 + 0.1898131437122077 + 0.18981834773716882 + 0.18982355189168421 + 0.18982875617575798 + 0.18983396058939495 + 0.1898391651325998 + 0.18984436980537692 + 0.18984957460773091 + 0.18985477953966717 + 0.1898599846011893 + 0.18986518979230271 + 0.18987039511301154 + 0.1898756005633202 + 0.18988080614323424 + 0.18988601185275714 + 0.1898912176918944 + 0.18989642366065007 + 0.18990162975902913 + 0.18990683598703656 + 0.18991204234467599 + 0.18991724883195274 + 0.18992245544887101 + 0.18992766219543619 + 0.18993286907165188 + 0.18993807607752344 + 0.18994328321305551 + 0.1899484904782521 + 0.18995369787311864 + 0.18995890539765875 + 0.18996411305187835 + 0.18996932083578047 + 0.18997452874937118 + 0.18997973679265442 + 0.18998494496563523 + 0.18999015326831761 + 0.18999536170070658 + 0.1900005702628067 + 0.19000577895462295 + 0.1900109877761593 + 0.19001619672742034 + 0.19002140580841151 + 0.1900266150191369 + 0.19003182435960142 + 0.19003703382980924 + 0.19004224342976528 + 0.19004745315947402 + 0.19005266301894005 + 0.19005787300816837 + 0.19006308312716347 + 0.1900682933759299 + 0.19007350375447213 + 0.19007871426279468 + 0.1900839249009027 + 0.19008913566880054 + 0.19009434656649321 + 0.19009955759398439 + 0.19010476875127993 + 0.1901099800383835 + 0.19011519145530004 + 0.19012040300203409 + 0.19012561467859057 + 0.19013082648497415 + 0.19013603842118876 + 0.19014125048723995 + 0.19014646268313176 + 0.19015167500886868 + 0.19015688746445619 + 0.19016210004989789 + 0.19016731276519933 + 0.19017252561036438 + 0.19017773858539821 + 0.19018295169030527 + 0.19018816492509011 + 0.19019337828975724 + 0.19019859178431167 + 0.19020380540875798 + 0.1902090191631006 + 0.19021423304734414 + 0.19021944706149307 + 0.19022466120555298 + 0.19022987547952733 + 0.19023508988342117 + 0.19024030441723955 + 0.19024551908098641 + 0.19025073387466684 + 0.19025594879828545 + 0.19026116385184658 + 0.1902663790353554 + 0.19027159434881638 + 0.19027680979223352 + 0.19028202536561242 + 0.19028724106895659 + 0.19029245690227198 + 0.19029767286556223 + 0.19030288895883227 + 0.19030810518208721 + 0.19031332153533057 + 0.19031853801856832 + 0.19032375463180404 + 0.19032897137504318 + 0.19033418824828988 + 0.1903394052515486 + 0.19034462238482441 + 0.19034983964812185 + 0.19035505704144542 + 0.19036027456480009 + 0.19036549221818999 + 0.19037071000162062 + 0.19037592791509553 + 0.19038114595861974 + 0.19038636413219823 + 0.19039158243583565 + 0.19039680086953589 + 0.19040201943330456 + 0.19040723812714569 + 0.19041245695106387 + 0.1904176759050645 + 0.19042289498915124 + 0.19042811420332956 + 0.19043333354760347 + 0.19043855302197807 + 0.1904437726264574 + 0.19044899236104693 + 0.19045421222575071 + 0.19045943222057379 + 0.19046465234552026 + 0.19046987260059509 + 0.19047509298580334 + 0.19048031350114855 + 0.19048553414663624 + 0.19049075492227147 + 0.19049597582805775 + 0.19050119686400063 + 0.19050641803010368 + 0.19051163932637286 + 0.19051686075281177 + 0.19052208230942597 + 0.19052730399621945 + 0.19053252581319671 + 0.19053774776036292 + 0.19054296983772304 + 0.19054819204528056 + 0.19055341438304066 + 0.19055863685100874 + 0.19056385944918799 + 0.19056908217758475 + 0.19057430503620221 + 0.19057952802504585 + 0.19058475114411977 + 0.19058997439342901 + 0.19059519777297854 + 0.19060042128277194 + 0.19060564492281523 + 0.19061086869311156 + 0.19061609259366685 + 0.1906213166244852 + 0.19062654078557159 + 0.19063176507693019 + 0.19063698949856545 + 0.19064221405048293 + 0.19064743873268666 + 0.19065266354518123 + 0.19065788848797166 + 0.190663113561062 + 0.19066833876445785 + 0.19067356409816316 + 0.19067878956218295 + 0.19068401515652142 + 0.1906892408811835 + 0.1906944667361738 + 0.19069969272149728 + 0.19070491883715809 + 0.19071014508316117 + 0.19071537145951073 + 0.19072059796621216 + 0.19072582460326959 + 0.19073105137068805 + 0.19073627826847209 + 0.19074150529662579 + 0.19074673245515461 + 0.1907519597440627 + 0.19075718716335455 + 0.19076241471303576 + 0.19076764239311034 + 0.1907728702035828 + 0.19077809814445779 + 0.19078332621574029 + 0.19078855441743492 + 0.19079378274954573 + 0.19079901121207862 + 0.1908042398050368 + 0.19080946852842628 + 0.19081469738225065 + 0.19081992636651493 + 0.19082515548122414 + 0.19083038472638233 + 0.19083561410199462 + 0.19084084360806558 + 0.19084607324459968 + 0.1908513030116015 + 0.19085653290907659 + 0.19086176293702806 + 0.19086699309546193 + 0.19087222338438228 + 0.19087745380379362 + 0.19088268435370098 + 0.19088791503410854 + 0.19089314584502173 + 0.19089837678644472 + 0.19090360785838195 + 0.19090883906083855 + 0.19091407039381908 + 0.19091930185732758 + 0.19092453345137014 + 0.19092976517594976 + 0.190934997031072 + 0.19094022901674151 + 0.19094546113296276 + 0.19095069337974038 + 0.19095592575707934 + 0.19096115826498375 + 0.19096639090345871 + 0.19097162367250919 + 0.19097685657213889 + 0.19098208960235366 + 0.19098732276315675 + 0.19099255605455423 + 0.19099778947655 + 0.19100302302914871 + 0.191008256712355 + 0.19101349052617381 + 0.19101872447061025 + 0.19102395854566787 + 0.19102919275135227 + 0.19103442708766752 + 0.19103966155461863 + 0.19104489615221015 + 0.19105013088044631 + 0.19105536573933246 + 0.19106060072887326 + 0.19106583584907333 + 0.19107107109993662 + 0.19107630648146881 + 0.19108154199367386 + 0.19108677763655643 + 0.1910920134101215 + 0.19109724931437372 + 0.19110248534931809 + 0.19110772151495825 + 0.19111295781129972 + 0.19111819423834708 + 0.19112343079610483 + 0.19112866748457769 + 0.19113390430377006 + 0.19113914125368714 + 0.19114437833433343 + 0.19114961554571303 + 0.19115485288783152 + 0.1911600903606929 + 0.1911653279643023 + 0.19117056569866378 + 0.19117580356378244 + 0.19118104155966328 + 0.1911862796863105 + 0.19119151794372852 + 0.19119675633192248 + 0.19120199485089692 + 0.19120723350065646 + 0.19121247228120619 + 0.1912177111925501 + 0.19122295023469288 + 0.19122818940763997 + 0.19123342871139554 + 0.19123866814596413 + 0.1912439077113508 + 0.19124914740755966 + 0.19125438723459623 + 0.19125962719246417 + 0.19126486728116898 + 0.19127010750071477 + 0.19127534785110661 + 0.19128058833234909 + 0.19128582894444721 + 0.19129106968740467 + 0.19129631056122651 + 0.19130155156591819 + 0.19130679270148349 + 0.19131203396792779 + 0.19131727536525522 + 0.19132251689347049 + 0.19132775855257853 + 0.19133300034258396 + 0.19133824226349136 + 0.1913434843153054 + 0.19134872649803097 + 0.19135396881167283 + 0.19135921125623498 + 0.19136445383172246 + 0.19136969653814045 + 0.19137493937549291 + 0.19138018234378454 + 0.19138542544302087 + 0.19139066867320548 + 0.19139591203434392 + 0.19140115552644035 + 0.19140639914949981 + 0.1914116429035263 + 0.19141688678852559 + 0.1914221308045016 + 0.19142737495145892 + 0.19143261922940227 + 0.19143786363833712 + 0.19144310817826707 + 0.19144835284919767 + 0.19145359765113312 + 0.19145884258407792 + 0.19146408764803713 + 0.19146933284301587 + 0.19147457816901778 + 0.1914798236260484 + 0.19148506921411176 + 0.191490314933213 + 0.19149556078335678 + 0.191500806764547 + 0.19150605287678996 + 0.1915112991200886 + 0.19151654549444855 + 0.1915217919998749 + 0.19152703863637124 + 0.19153228540394265 + 0.19153753230259421 + 0.1915427793323306 + 0.19154802649315575 + 0.19155327378507489 + 0.191558521208093 + 0.19156376876221426 + 0.1915690164474432 + 0.19157426426378543 + 0.19157951221124458 + 0.19158476028982568 + 0.19159000849953386 + 0.19159525684037371 + 0.19160050531234926 + 0.19160575391546569 + 0.19161100264972752 + 0.19161625151513942 + 0.19162150051170643 + 0.19162674963943269 + 0.19163199889832364 + 0.19163724828838311 + 0.19164249780961645 + 0.19164774746202798 + 0.19165299724562265 + 0.19165824716040461 + 0.19166349720637937 + 0.19166874738355114 + 0.19167399769192453 + 0.1916792481315045 + 0.19168449870229526 + 0.19168974940430183 + 0.19169500023752939 + 0.19170025120198192 + 0.19170550229766417 + 0.19171075352458111 + 0.19171600488273735 + 0.19172125637213758 + 0.19172650799278634 + 0.19173175974468867 + 0.19173701162784923 + 0.19174226364227168 + 0.19174751578796245 + 0.19175276806492481 + 0.19175802047316429 + 0.19176327301268498 + 0.19176852568349195 + 0.19177377848558988 + 0.19177903141898378 + 0.19178428448367735 + 0.19178953767967608 + 0.19179479100698468 + 0.19180004446560725 + 0.19180529805554927 + 0.19181055177681444 + 0.19181580562940836 + 0.19182105961333601 + 0.19182631372860073 + 0.19183156797520837 + 0.19183682235316327 + 0.19184207686246985 + 0.1918473315031328 + 0.19185258627515761 + 0.19185784117854807 + 0.19186309621330969 + 0.19186835137944605 + 0.19187360667696279 + 0.19187886210586447 + 0.19188411766615576 + 0.19188937335784123 + 0.19189462918092504 + 0.19189988513541315 + 0.19190514122130886 + 0.19191039743861812 + 0.19191565378734465 + 0.19192091026749392 + 0.19192616687907021 + 0.19193142362207799 + 0.19193668049652246 + 0.19194193750240815 + 0.19194719463973969 + 0.19195245190852225 + 0.19195770930875941 + 0.19196296684045674 + 0.19196822450361886 + 0.19197348229825043 + 0.19197874022435599 + 0.19198399828194021 + 0.19198925647100812 + 0.19199451479156399 + 0.1919997732436127 + 0.19200503182715956 + 0.19201029054220808 + 0.19201554938876395 + 0.19202080836683166 + 0.19202606747641546 + 0.19203132671752041 + 0.19203658609015109 + 0.19204184559431259 + 0.19204710523000909 + 0.19205236499724568 + 0.19205762489602654 + 0.19206288492635715 + 0.19206814508824174 + 0.19207340538168485 + 0.19207866580669158 + 0.19208392636326668 + 0.19208918705141415 + 0.19209444787113908 + 0.19209970882244667 + 0.19210496990534151 + 0.19211023111982722 + 0.19211549246590992 + 0.19212075394359368 + 0.19212601555288317 + 0.19213127729378296 + 0.19213653916629822 + 0.192141801170433 + 0.19214706330619302 + 0.19215232557358183 + 0.19215758797260504 + 0.19216285050326684 + 0.19216811316557225 + 0.19217337595952544 + 0.19217863888513206 + 0.19218390194239568 + 0.19218916513132242 + 0.19219442845191542 + 0.19219969190418032 + 0.19220495548812169 + 0.19221021920374426 + 0.19221548305105249 + 0.19222074703005163 + 0.19222601114074572 + 0.19223127538313997 + 0.19223653975723889 + 0.19224180426304674 + 0.1922470689005695 + 0.19225233366981045 + 0.1922575985707751 + 0.19226286360346806 + 0.19226812876789401 + 0.19227339406405755 + 0.19227865949196335 + 0.19228392505161651 + 0.19228919074302159 + 0.19229445656618277 + 0.19229972252110525 + 0.19230498860779399 + 0.19231025482625325 + 0.19231552117648809 + 0.19232078765850272 + 0.19232605427230212 + 0.19233132101789105 + 0.19233658789527414 + 0.19234185490445641 + 0.1923471220454426 + 0.19235238931823676 + 0.19235765672284405 + 0.1923629242592691 + 0.19236819192751703 + 0.19237345972759193 + 0.19237872765949857 + 0.19238399572324238 + 0.19238926391882713 + 0.19239453224625844 + 0.19239980070554036 + 0.19240506929667767 + 0.19241033801967533 + 0.19241560687453807 + 0.19242087586127046 + 0.1924261449798772 + 0.19243141423036292 + 0.1924366836127327 + 0.19244195312699122 + 0.19244722277314261 + 0.19245249255119243 + 0.19245776246114488 + 0.19246303250300456 + 0.19246830267677667 + 0.19247357298246576 + 0.19247884342007607 + 0.19248411398961313 + 0.19248938469108062 + 0.19249465552448464 + 0.19249992648982839 + 0.19250519758711798 + 0.19251046881635747 + 0.1925157401775511 + 0.19252101167070451 + 0.19252628329582175 + 0.19253155505290803 + 0.19253682694196791 + 0.19254209896300614 + 0.19254737111602724 + 0.19255264340103601 + 0.19255791581803686 + 0.19256318836703565 + 0.19256846104803585 + 0.19257373386104268 + 0.1925790068060608 + 0.19258427988309482 + 0.19258955309214981 + 0.19259482643323053 + 0.19260009990634105 + 0.19260537351148704 + 0.19261064724867219 + 0.19261592111790199 + 0.19262119511918072 + 0.19262646925251345 + 0.19263174351790485 + 0.19263701791535956 + 0.19264229244488226 + 0.19264756710647798 + 0.1926528419001505 + 0.19265811682590592 + 0.19266339188374826 + 0.19266866707368183 + 0.19267394239571223 + 0.19267921784984304 + 0.19268449343608049 + 0.19268976915442818 + 0.19269504500489124 + 0.19270032098747436 + 0.1927055971021821 + 0.19271087334901923 + 0.19271614972799084 + 0.19272142623910155 + 0.19272670288235552 + 0.1927319796577584 + 0.19273725656531429 + 0.19274253360502797 + 0.192747810776904 + 0.19275308808094799 + 0.1927583655171631 + 0.19276364308555605 + 0.19276892078612995 + 0.19277419861888997 + 0.19277947658384118 + 0.19278475468098832 + 0.19279003291033597 + 0.19279531127188834 + 0.19280058976565106 + 0.1928058683916283 + 0.19281114714982464 + 0.19281642604024576 + 0.19282170506289489 + 0.19282698421777811 + 0.19283226350489954 + 0.19283754292426436 + 0.19284282247587625 + 0.19284810215974138 + 0.19285338197586335 + 0.1928586619242473 + 0.19286394200489845 + 0.19286922221782044 + 0.19287450256301891 + 0.19287978304049846 + 0.19288506365026381 + 0.19289034439231911 + 0.19289562526666951 + 0.19290090627332007 + 0.19290618741227561 + 0.19291146868353967 + 0.19291675008711848 + 0.19292203162301566 + 0.1929273132912368 + 0.19293259509178567 + 0.19293787702466841 + 0.19294315908988857 + 0.19294844128745092 + 0.1929537236173606 + 0.19295900607962274 + 0.19296428867424104 + 0.19296957140122106 + 0.19297485426056751 + 0.19298013725228463 + 0.19298542037637745 + 0.19299070363285076 + 0.19299598702170911 + 0.19300127054295765 + 0.19300655419660068 + 0.19301183798264324 + 0.19301712190108952 + 0.1930224059519447 + 0.1930276901352139 + 0.19303297445090128 + 0.19303825889901205 + 0.19304354347954991 + 0.19304882819252084 + 0.19305411303792921 + 0.19305939801577957 + 0.19306468312607661 + 0.19306996836882503 + 0.19307525374402992 + 0.19308053925169597 + 0.19308582489182735 + 0.19309111066442977 + 0.19309639656950733 + 0.19310168260706476 + 0.19310696877710712 + 0.19311225507963917 + 0.19311754151466504 + 0.19312282808218989 + 0.19312811478221842 + 0.19313340161475573 + 0.19313868857980607 + 0.19314397567737454 + 0.19314926290746581 + 0.19315455027008413 + 0.19315983776523507 + 0.19316512539292285 + 0.19317041315315214 + 0.19317570104592807 + 0.19318098907125533 + 0.19318627722913811 + 0.193191565519582 + 0.19319685394259081 + 0.19320214249817055 + 0.19320743118632458 + 0.1932127200070588 + 0.19321800896037714 + 0.19322329804628466 + 0.19322858726478603 + 0.19323387661588598 + 0.19323916609958958 + 0.19324445571590157 + 0.19324974546482609 + 0.1932550353463684 + 0.19326032536053306 + 0.19326561550732521 + 0.19327090578674919 + 0.19327619619880951 + 0.1932814867435115 + 0.1932867774208597 + 0.19329206823085884 + 0.19329735917351357 + 0.19330265024882862 + 0.1933079414568091 + 0.19331323279745971 + 0.19331852427078461 + 0.19332381587678904 + 0.19332910761547761 + 0.19333439948685499 + 0.19333969149092639 + 0.19334498362769603 + 0.19335027589716947 + 0.19335556829935002 + 0.19336086083424373 + 0.19336615350185485 + 0.19337144630218805 + 0.19337673923524848 + 0.19338203230104084 + 0.19338732549956936 + 0.19339261883083911 + 0.19339791229485487 + 0.19340320589162124 + 0.19340849962114348 + 0.19341379348342574 + 0.19341908747847311 + 0.19342438160628991 + 0.19342967586688178 + 0.19343497026025286 + 0.1934402647864078 + 0.19344555944535141 + 0.19345085423708874 + 0.19345614916162457 + 0.1934614442189635 + 0.19346673940910977 + 0.19347203473206909 + 0.19347733018784549 + 0.19348262577644434 + 0.19348792149786975 + 0.19349321735212735 + 0.19349851333922086 + 0.19350380945915552 + 0.193509105711936 + 0.19351440209756743 + 0.193519698616054 + 0.19352499526740097 + 0.19353029205161293 + 0.19353558896869461 + 0.19354088601865072 + 0.19354618320148589 + 0.19355148051720536 + 0.19355677796581325 + 0.19356207554731483 + 0.19356737326171478 + 0.19357267110901769 + 0.19357796908922839 + 0.19358326720235147 + 0.19358856544839209 + 0.19359386382735505 + 0.19359916233924446 + 0.19360446098406556 + 0.19360975976182296 + 0.19361505867252193 + 0.19362035771616659 + 0.1936256568927617 + 0.19363095620231241 + 0.19363625564482348 + 0.19364155522029947 + 0.19364685492874514 + 0.19365215477016523 + 0.19365745474456439 + 0.19366275485194778 + 0.19366805509232013 + 0.19367335546568612 + 0.19367865597204995 + 0.1936839566114178 + 0.19368925738379233 + 0.19369455828918034 + 0.19369985932758543 + 0.19370516049901285 + 0.19371046180346682 + 0.19371576324095241 + 0.19372106481147489 + 0.19372636651503894 + 0.19373166835164835 + 0.19373697032130863 + 0.19374227242402464 + 0.19374757465980103 + 0.193752877028642 + 0.19375817953055319 + 0.19376348216553882 + 0.19376878493360417 + 0.19377408783475331 + 0.19377939086899154 + 0.19378469403632353 + 0.19378999733675395 + 0.19379530077028798 + 0.19380060433692933 + 0.19380590803668382 + 0.19381121186955599 + 0.19381651583555015 + 0.1938218199346714 + 0.19382712416692452 + 0.19383242853231467 + 0.19383773303084609 + 0.19384303766252345 + 0.19384834242735194 + 0.19385364732533628 + 0.19385895235648065 + 0.19386425752079078 + 0.19386956281827089 + 0.19387486824892564 + 0.19388017381276021 + 0.19388547950977889 + 0.19389078533998683 + 0.19389609130338875 + 0.19390139739998932 + 0.1939067036297932 + 0.19391200999280575 + 0.19391731648903107 + 0.19392262311847386 + 0.19392792988113985 + 0.19393323677703322 + 0.19393854380615821 + 0.19394385096851999 + 0.19394915826412382 + 0.19395446569297389 + 0.19395977325507535 + 0.19396508095043299 + 0.19397038877905143 + 0.19397569674093493 + 0.19398100483608915 + 0.19398631306451841 + 0.19399162142622781 + 0.19399692992122108 + 0.19400223854950446 + 0.19400754731108213 + 0.19401285620595882 + 0.19401816523413917 + 0.19402347439562806 + 0.19402878369043047 + 0.19403409311855083 + 0.19403940267999417 + 0.19404471237476481 + 0.19405002220286846 + 0.19405533216430926 + 0.19406064225909198 + 0.19406595248722178 + 0.19407126284870296 + 0.19407657334354064 + 0.19408188397173912 + 0.19408719473330402 + 0.19409250562823915 + 0.1940978166565501 + 0.19410312781824166 + 0.19410843911331763 + 0.19411375054178401 + 0.19411906210364474 + 0.19412437379890488 + 0.19412968562756922 + 0.19413499758964289 + 0.19414030968512971 + 0.19414562191403587 + 0.19415093427636504 + 0.19415624677212195 + 0.19416155940131233 + 0.19416687216393999 + 0.19417218506001047 + 0.19417749808952808 + 0.19418281125249751 + 0.19418812454892403 + 0.19419343797881231 + 0.19419875154216706 + 0.19420406523899256 + 0.1942093790692945 + 0.19421469303307706 + 0.19422000713034498 + 0.19422532136110349 + 0.19423063572535684 + 0.19423595022311016 + 0.19424126485436874 + 0.1942465796191363 + 0.19425189451741806 + 0.19425720954921921 + 0.19426252471454403 + 0.19426784001339814 + 0.19427315544578491 + 0.19427847101171042 + 0.19428378671117844 + 0.19428910254419471 + 0.19429441851076343 + 0.1942997346108894 + 0.19430505084457775 + 0.19431036721183317 + 0.19431568371266006 + 0.19432100034706343 + 0.19432631711504864 + 0.19433163401661988 + 0.19433695105178186 + 0.1943422682205394 + 0.19434758552289805 + 0.19435290295886118 + 0.19435822052843496 + 0.19436353823162367 + 0.19436885606843193 + 0.19437417403886456 + 0.19437949214292674 + 0.19438481038062269 + 0.19439012875195766 + 0.19439544725693642 + 0.1944007658955631 + 0.19440608466784354 + 0.19441140357378189 + 0.19441672261338289 + 0.19442204178665182 + 0.19442736109359329 + 0.19443268053421114 + 0.19443800010851209 + 0.19444331981649934 + 0.19444863965817816 + 0.19445395963355322 + 0.1944592797426298 + 0.19446459998541205 + 0.1944699203619053 + 0.19447524087211426 + 0.19448056151604362 + 0.19448588229369768 + 0.19449120320508209 + 0.19449652425020164 + 0.19450184542906004 + 0.19450716674166355 + 0.19451248818801586 + 0.19451780976812175 + 0.19452313148198688 + 0.1945284533296156 + 0.19453377531101257 + 0.19453909742618297 + 0.19454441967513114 + 0.1945497420578618 + 0.19455506457438015 + 0.19456038722469091 + 0.19456571000879885 + 0.19457103292670921 + 0.19457635597842618 + 0.19458167916395411 + 0.19458700248329908 + 0.19459232593646494 + 0.19459764952345687 + 0.19460297324427914 + 0.19460829709893754 + 0.19461362108743618 + 0.1946189452097799 + 0.19462426946597386 + 0.19462959385602235 + 0.19463491837993066 + 0.19464024303770344 + 0.19464556782934497 + 0.19465089275486094 + 0.19465621781425521 + 0.19466154300753344 + 0.19466686833470032 + 0.19467219379576015 + 0.1946775193907182 + 0.19468284511957917 + 0.19468817098234731 + 0.19469349697902835 + 0.19469882310962611 + 0.19470414937414621 + 0.19470947577259343 + 0.19471480230497207 + 0.19472012897128738 + 0.19472545577154399 + 0.19473078270574626 + 0.19473610977389985 + 0.1947414369760091 + 0.19474676431207866 + 0.19475209178211386 + 0.1947574193861189 + 0.19476274712409899 + 0.19476807499605889 + 0.19477340300200294 + 0.19477873114193675 + 0.19478405941586469 + 0.19478938782379146 + 0.19479471636572226 + 0.1948000450416614 + 0.19480537385161451 + 0.19481070279558552 + 0.1948160318735791 + 0.19482136108560091 + 0.19482669043165529 + 0.19483201991174753 + 0.1948373495258818 + 0.19484267927406285 + 0.19484800915629596 + 0.19485333917258588 + 0.19485866932293736 + 0.19486399960735512 + 0.194869330025844 + 0.19487466057840908 + 0.19487999126505481 + 0.19488532208578582 + 0.19489065304060738 + 0.19489598412952422 + 0.19490131535254113 + 0.19490664670966287 + 0.19491197820089423 + 0.19491730982624034 + 0.19492264158570508 + 0.19492797347929461 + 0.19493330550701274 + 0.19493863766886471 + 0.1949439699648548 + 0.19494930239498867 + 0.19495463495927073 + 0.1949599676577056 + 0.19496530049029812 + 0.19497063345705343 + 0.19497596655797642 + 0.19498129979307127 + 0.19498663316234374 + 0.19499196666579766 + 0.19499730030343868 + 0.1950026340752706 + 0.19500796798129921 + 0.19501330202152878 + 0.19501863619596496 + 0.19502397050461115 + 0.1950293049474735 + 0.19503463952455632 + 0.19503997423586383 + 0.19504530908140189 + 0.19505064406117456 + 0.19505597917518733 + 0.19506131442344429 + 0.19506664980595079 + 0.19507198532271111 + 0.1950773209737309 + 0.19508265675901404 + 0.19508799267856619 + 0.19509332873239169 + 0.19509866492049532 + 0.19510400124288224 + 0.19510933769955729 + 0.19511467429052465 + 0.19512001101578974 + 0.19512534787535765 + 0.19513068486923224 + 0.19513602199741881 + 0.19514135925992251 + 0.19514669665674766 + 0.19515203418789956 + 0.19515737185338244 + 0.19516270965320201 + 0.19516804758736211 + 0.19517338565586803 + 0.19517872385872498 + 0.19518406219593673 + 0.19518940066750959 + 0.19519473927344674 + 0.19520007801375408 + 0.19520541688843623 + 0.19521075589749801 + 0.19521609504094423 + 0.19522143431877961 + 0.19522677373100897 + 0.19523211327763754 + 0.19523745295866909 + 0.19524279277410991 + 0.19524813272396374 + 0.19525347280823585 + 0.19525881302693099 + 0.19526415338005404 + 0.19526949386760967 + 0.19527483448960267 + 0.1952801752460383 + 0.19528551613692083 + 0.19529085716225558 + 0.19529619832204678 + 0.19530153961629967 + 0.19530688104501912 + 0.19531222260821032 + 0.19531756430587704 + 0.19532290613802511 + 0.19532824810465879 + 0.19533359020578328 + 0.19533893244140296 + 0.19534427481152303 + 0.19534961731614833 + 0.19535495995528351 + 0.19536030272893348 + 0.19536564563710296 + 0.19537098867979721 + 0.19537633185702058 + 0.19538167516877772 + 0.19538701861507399 + 0.19539236219591416 + 0.19539770591130301 + 0.19540304976124526 + 0.19540839374574526 + 0.19541373786480928 + 0.19541908211844056 + 0.19542442650664485 + 0.19542977102942652 + 0.19543511568679078 + 0.19544046047874242 + 0.19544580540528625 + 0.19545115046642703 + 0.19545649566216952 + 0.19546184099251851 + 0.19546718645747876 + 0.19547253205705609 + 0.19547787779125383 + 0.19548322366007764 + 0.19548856966353237 + 0.19549391580162273 + 0.19549926207435361 + 0.19550460848172976 + 0.1955099550237564 + 0.1955153017004374 + 0.19552064851177847 + 0.19552599545778446 + 0.19553134253845958 + 0.19553668975380914 + 0.19554203710383791 + 0.19554738458855073 + 0.19555273220795283 + 0.19555807996204802 + 0.19556342785084205 + 0.19556877587433924 + 0.19557412403254493 + 0.19557947232546324 + 0.19558482075309963 + 0.19559016931545881 + 0.19559551801254604 + 0.19560086684436517 + 0.19560621581092139 + 0.19561156491222007 + 0.19561691414826551 + 0.19562226351906295 + 0.1956276130246167 + 0.19563296266493202 + 0.1956383124400137 + 0.19564366234986658 + 0.19564901239449545 + 0.19565436257390548 + 0.19565971288810055 + 0.19566506333708653 + 0.19567041392086801 + 0.19567576463944944 + 0.19568111549283612 + 0.19568646648103269 + 0.19569181760404358 + 0.19569716886187452 + 0.19570252025452986 + 0.19570787178201429 + 0.19571322344433317 + 0.19571857524149081 + 0.19572392717349194 + 0.19572927924034239 + 0.195734631442046 + 0.19573998377860793 + 0.19574533625003313 + 0.19575068885632627 + 0.19575604159749269 + 0.19576139447353622 + 0.1957667474844631 + 0.19577210063027717 + 0.1957774539109832 + 0.19578280732658643 + 0.19578816087709228 + 0.19579351456250441 + 0.19579886838282823 + 0.19580422233806849 + 0.19580957642823049 + 0.19581493065331851 + 0.19582028501333787 + 0.19582563950829282 + 0.19583099413818825 + 0.19583634890302984 + 0.19584170380282201 + 0.19584705883756895 + 0.19585241400727654 + 0.19585776931194951 + 0.19586312475159173 + 0.19586848032620849 + 0.19587383603580549 + 0.19587919188038666 + 0.19588454785995721 + 0.19588990397452202 + 0.19589526022408532 + 0.19590061660865293 + 0.19590597312822919 + 0.19591132978281883 + 0.1959166865724267 + 0.19592204349705858 + 0.19592740055671778 + 0.19593275775141017 + 0.19593811508114092 + 0.19594347254591396 + 0.19594883014573447 + 0.19595418788060737 + 0.19595954575053739 + 0.19596490375552986 + 0.19597026189558908 + 0.1959756201707199 + 0.19598097858092806 + 0.19598633712621735 + 0.19599169580659265 + 0.19599705462205971 + 0.19600241357262238 + 0.19600777265828642 + 0.19601313187905614 + 0.19601849123493689 + 0.19602385072593242 + 0.19602921035204909 + 0.19603457011329067 + 0.19603993000966247 + 0.19604529004116883 + 0.19605065020781501 + 0.19605601050960639 + 0.19606137094654719 + 0.19606673151864229 + 0.1960720922258965 + 0.19607745306831456 + 0.19608281404590233 + 0.19608817515866364 + 0.19609353640660321 + 0.19609889778972694 + 0.19610425930803865 + 0.19610962096154413 + 0.19611498275024714 + 0.19612034467415351 + 0.19612570673326762 + 0.19613106892759466 + 0.19613643125713909 + 0.19614179372190563 + 0.19614715632190005 + 0.19615251905712627 + 0.19615788192759004 + 0.19616324493329523 + 0.19616860807424705 + 0.19617397135045098 + 0.19617933476191113 + 0.19618469830863247 + 0.19619006199062072 + 0.1961954258078793 + 0.19620078976041391 + 0.19620615384822995 + 0.19621151807133069 + 0.19621688242972299 + 0.19622224692341009 + 0.19622761155239787 + 0.19623297631669018 + 0.19623834121629272 + 0.19624370625121038 + 0.19624907142144754 + 0.19625443672700937 + 0.19625980216790087 + 0.19626516774412667 + 0.19627053345569123 + 0.19627589930260034 + 0.19628126528485823 + 0.19628663140246982 + 0.19629199765544039 + 0.19629736404377426 + 0.1963027305674768 + 0.19630809722655221 + 0.19631346402100597 + 0.19631883095084277 + 0.19632419801606749 + 0.19632956521668493 + 0.19633493255269996 + 0.1963403000241174 + 0.19634566763094244 + 0.19635103537317961 + 0.19635640325083403 + 0.19636177126391022 + 0.19636713941241332 + 0.19637250769634826 + 0.19637787611571983 + 0.19638324467053239 + 0.19638861336079172 + 0.19639398218650223 + 0.19639935114766913 + 0.19640472024429625 + 0.19641008947638999 + 0.19641545884395367 + 0.19642082834699315 + 0.19642619798551358 + 0.19643156775951898 + 0.19643693766901457 + 0.19644230771400523 + 0.19644767789449577 + 0.1964530482104915 + 0.19645841866199629 + 0.19646378924901645 + 0.19646915997155528 + 0.19647453082961908 + 0.19647990182321134 + 0.1964852729523382 + 0.1964906442170041 + 0.19649601561721378 + 0.19650138715297166 + 0.19650675882428356 + 0.19651213063115383 + 0.19651750257358766 + 0.19652287465158955 + 0.19652824686516424 + 0.19653361921431706 + 0.1965389916990529 + 0.19654436431937655 + 0.19654973707529233 + 0.19655510996680617 + 0.19656048299392176 + 0.19656585615664496 + 0.19657122945498023 + 0.19657660288893275 + 0.19658197645850647 + 0.1965873501637076 + 0.19659272400454014 + 0.1965980979810093 + 0.19660347209311943 + 0.19660884634087591 + 0.19661422072428406 + 0.19661959524334766 + 0.19662496989807265 + 0.19663034468846327 + 0.19663571961452486 + 0.1966410946762614 + 0.19664646987367901 + 0.19665184520678122 + 0.19665722067557423 + 0.19666259628006241 + 0.19666797202025063 + 0.19667334789614282 + 0.19667872390774566 + 0.19668410005506254 + 0.19668947633809925 + 0.19669485275686072 + 0.19670022931135081 + 0.19670560600157525 + 0.19671098282753893 + 0.19671635978924676 + 0.19672173688670294 + 0.19672711411991289 + 0.19673249148888153 + 0.19673786899361403 + 0.19674324663411441 + 0.19674862441038787 + 0.19675400232243986 + 0.1967593803702751 + 0.19676475855389802 + 0.19677013687331343 + 0.19677551532852672 + 0.1967808939195427 + 0.19678627264636619 + 0.19679165150900163 + 0.19679703050745476 + 0.19680240964172996 + 0.19680778891183154 + 0.19681316831776594 + 0.1968185478595364 + 0.19682392753714881 + 0.19682930735060802 + 0.19683468729991846 + 0.19684006738508533 + 0.1968454476061135 + 0.19685082796300737 + 0.19685620845577279 + 0.19686158908441406 + 0.19686696984893615 + 0.1968723507493432 + 0.19687773178564175 + 0.19688311295783553 + 0.19688849426592947 + 0.19689387570992883 + 0.19689925728983854 + 0.19690463900566293 + 0.19691002085740733 + 0.19691540284507661 + 0.19692078496867563 + 0.19692616722820919 + 0.19693154962368264 + 0.19693693215509994 + 0.19694231482246677 + 0.19694769762578818 + 0.19695308056506836 + 0.19695846364031219 + 0.19696384685152515 + 0.1969692301987119 + 0.19697461368187749 + 0.19697999730102658 + 0.19698538105616417 + 0.19699076494729501 + 0.19699614897442408 + 0.19700153313755611 + 0.19700691743669649 + 0.19701230187184962 + 0.19701768644302084 + 0.19702307115021447 + 0.19702845599343585 + 0.19703384097268992 + 0.197039226087981 + 0.19704461133931483 + 0.19704999672669596 + 0.19705538225012867 + 0.19706076790961877 + 0.19706615370517067 + 0.19707153963678972 + 0.19707692570448021 + 0.19708231190824713 + 0.19708769824809619 + 0.19709308472403086 + 0.19709847133605748 + 0.19710385808418038 + 0.19710924496840398 + 0.19711463198873355 + 0.19712001914517446 + 0.19712540643773066 + 0.19713079386640792 + 0.19713618143121064 + 0.19714156913214415 + 0.19714695696921286 + 0.19715234494242215 + 0.19715773305177628 + 0.19716312129728072 + 0.19716850967894026 + 0.19717389819675976 + 0.19717928685074415 + 0.19718467564089823 + 0.19719006456722693 + 0.19719545362973553 + 0.19720084282842795 + 0.19720623216331007 + 0.19721162163438669 + 0.19721701124166224 + 0.19722240098514152 + 0.19722779086483047 + 0.19723318088073286 + 0.19723857103285417 + 0.19724396132119915 + 0.19724935174577279 + 0.19725474230657988 + 0.19726013300362524 + 0.19726552383691437 + 0.19727091480645154 + 0.1972763059122416 + 0.19728169715429 + 0.19728708853260102 + 0.19729248004718064 + 0.19729787169803209 + 0.19730326348516189 + 0.19730865540857381 + 0.19731404746827372 + 0.19731943966426604 + 0.19732483199655509 + 0.19733022446514681 + 0.19733561707004543 + 0.19734100981125652 + 0.19734640268878428 + 0.19735179570263367 + 0.19735718885281003 + 0.19736258213931823 + 0.19736797556216321 + 0.19737336912134923 + 0.19737876281688171 + 0.19738415664876602 + 0.19738955061700608 + 0.19739494472160771 + 0.19740033896257483 + 0.19740573333991326 + 0.19741112785362744 + 0.19741652250372266 + 0.19742191729020339 + 0.19742731221307541 + 0.19743270727234211 + 0.19743810246800944 + 0.19744349780008222 + 0.19744889326856535 + 0.19745428887346417 + 0.19745968461478214 + 0.19746508049252551 + 0.19747047650669922 + 0.19747587265730768 + 0.19748126894435578 + 0.19748666536784831 + 0.1974920619277907 + 0.19749745862418736 + 0.19750285545704407 + 0.19750825242636477 + 0.19751364953215439 + 0.19751904677441878 + 0.19752444415316223 + 0.19752984166838927 + 0.19753523932010561 + 0.19754063710831576 + 0.19754603503302462 + 0.19755143309423698 + 0.1975568312919587 + 0.19756222962619327 + 0.1975676280969465 + 0.19757302670422283 + 0.19757842544802756 + 0.1975838243283656 + 0.1975892233452419 + 0.19759462249866128 + 0.19760002178862859 + 0.19760542121514829 + 0.19761082077822625 + 0.19761622047786684 + 0.1976216203140754 + 0.19762702028685594 + 0.1976324203962147 + 0.1976378206421551 + 0.19764322102468312 + 0.197648621543804 + 0.19765402219952127 + 0.19765942299184125 + 0.19766482392076778 + 0.19767022498630638 + 0.19767562618846174 + 0.19768102752723946 + 0.19768642900264327 + 0.1976918306146791 + 0.19769723236335088 + 0.19770263424866497 + 0.1977080362706253 + 0.19771343842923664 + 0.19771884072450452 + 0.19772424315643325 + 0.19772964572502824 + 0.19773504843029485 + 0.19774045127223652 + 0.19774585425085967 + 0.19775125736616855 + 0.19775666061816821 + 0.19776206400686341 + 0.19776746753225913 + 0.19777287119436077 + 0.19777827499317216 + 0.19778367892869969 + 0.1977890830009473 + 0.19779448720991988 + 0.19779989155562283 + 0.19780529603806096 + 0.1978107006572388 + 0.19781610541316214 + 0.19782151030583489 + 0.19782691533526248 + 0.19783232050144975 + 0.19783772580440212 + 0.19784313124412356 + 0.19784853682062037 + 0.19785394253389593 + 0.19785934838395575 + 0.19786475437080508 + 0.19787016049444894 + 0.19787556675489174 + 0.19788097315213871 + 0.19788637968619494 + 0.19789178635706467 + 0.19789719316475346 + 0.19790260010926602 + 0.19790800719060792 + 0.19791341440878293 + 0.19791882176379705 + 0.19792422925565412 + 0.19792963688436058 + 0.19793504464991973 + 0.19794045255233764 + 0.19794586059161853 + 0.19795126876776795 + 0.19795667708079015 + 0.19796208553069072 + 0.19796749411747491 + 0.19797290284114613 + 0.1979783117017109 + 0.19798372069917294 + 0.19798912983353834 + 0.19799453910481143 + 0.19799994851299704 + 0.19800535805810018 + 0.19801076774012566 + 0.19801617755907902 + 0.19802158751496451 + 0.19802699760778755 + 0.19803240783755269 + 0.19803781820426519 + 0.19804322870792951 + 0.19804863934855158 + 0.19805405012613472 + 0.19805946104068539 + 0.19806487209220805 + 0.19807028328070755 + 0.19807569460618873 + 0.19808110606865661 + 0.19808651766811608 + 0.19809192940457249 + 0.1980973412780303 + 0.19810275328849439 + 0.19810816543597015 + 0.19811357772046254 + 0.1981189901419754 + 0.19812440270051523 + 0.19812981539608587 + 0.19813522822869326 + 0.19814064119834077 + 0.1981460543050349 + 0.19815146754877991 + 0.19815688092958089 + 0.1981622944474426 + 0.19816770810237 + 0.19817312189436859 + 0.19817853582344264 + 0.19818394988959709 + 0.19818936409283699 + 0.1981947784331676 + 0.19820019291059388 + 0.19820560752512023 + 0.19821102227675214 + 0.19821643716549389 + 0.19822185219135102 + 0.19822726735432886 + 0.19823268265443136 + 0.19823809809166396 + 0.19824351366603152 + 0.19824892937753949 + 0.19825434522619176 + 0.19825976121199421 + 0.19826517733495139 + 0.1982705935950681 + 0.19827600999234976 + 0.19828142652680136 + 0.19828684319842724 + 0.19829226000723238 + 0.19829767695322215 + 0.19830309403640142 + 0.19830851125677523 + 0.19831392861434802 + 0.19831934610912549 + 0.19832476374111177 + 0.19833018151031268 + 0.19833559941673221 + 0.19834101746037613 + 0.1983464356412491 + 0.19835185395935581 + 0.1983572724147018 + 0.19836269100729095 + 0.19836810973712973 + 0.19837352860422203 + 0.19837894760857272 + 0.19838436675018728 + 0.19838978602907115 + 0.19839520544522771 + 0.19840062499866337 + 0.19840604468938211 + 0.19841146451738934 + 0.19841688448268993 + 0.19842230458528934 + 0.19842772482519147 + 0.19843314520240182 + 0.19843856571692575 + 0.19844398636876767 + 0.19844940715793299 + 0.19845482808442624 + 0.19846024914825225 + 0.19846567034941645 + 0.19847109168792385 + 0.19847651316377879 + 0.19848193477698675 + 0.19848735652755209 + 0.19849277841548074 + 0.19849820044077676 + 0.1985036226034454 + 0.19850904490349175 + 0.19851446734092107 + 0.19851988991573744 + 0.19852531262794615 + 0.19853073547755279 + 0.19853615846456213 + 0.19854158158897817 + 0.19854700485080687 + 0.19855242825005259 + 0.19855785178672083 + 0.19856327546081601 + 0.19856869927234352 + 0.1985741232213083 + 0.19857954730771485 + 0.19858497153156848 + 0.19859039589287417 + 0.1985958203916369 + 0.19860124502786158 + 0.19860666980155312 + 0.19861209471271643 + 0.1986175197613565 + 0.19862294494747876 + 0.19862837027108712 + 0.19863379573218745 + 0.19863922133078435 + 0.19864464706688312 + 0.19865007294048823 + 0.19865549895160506 + 0.19866092510023814 + 0.19866635138639235 + 0.19867177781007367 + 0.19867720437128647 + 0.19868263107003525 + 0.19868805790632493 + 0.19869348488016142 + 0.1986989119915491 + 0.19870433924049308 + 0.19870976662699816 + 0.19871519415106934 + 0.19872062181271144 + 0.19872604961192955 + 0.19873147754872908 + 0.19873690562311441 + 0.19874233383509099 + 0.19874776218466331 + 0.19875319067183625 + 0.19875861929661526 + 0.1987640480590048 + 0.19876947695901087 + 0.19877490599663725 + 0.19878033517188953 + 0.19878576448477206 + 0.19879119393529035 + 0.19879662352344982 + 0.19880205324925437 + 0.19880748311270946 + 0.19881291311382063 + 0.19881834325259215 + 0.19882377352902858 + 0.19882920394313636 + 0.19883463449491889 + 0.19884006518438213 + 0.19884549601153051 + 0.19885092697636952 + 0.19885635807890353 + 0.19886178931913762 + 0.19886722069707755 + 0.1988726522127269 + 0.19887808386609207 + 0.19888351565717755 + 0.19888894758598766 + 0.19889437965252801 + 0.19889981185680344 + 0.19890524419881894 + 0.19891067667857945 + 0.19891610929608985 + 0.1989215420513557 + 0.19892697494438089 + 0.19893240797517142 + 0.19893784114373164 + 0.19894327445006654 + 0.19894870789418162 + 0.19895414147608129 + 0.19895957519577051 + 0.19896500905325518 + 0.19897044304853884 + 0.19897587718162785 + 0.19898131145252618 + 0.19898674586123891 + 0.19899218040777175 + 0.19899761509212888 + 0.19900304991431611 + 0.19900848487433745 + 0.19901391997219836 + 0.19901935520790373 + 0.19902479058145908 + 0.19903022609286833 + 0.19903566174213694 + 0.19904109752927041 + 0.19904653345427309 + 0.19905196951715051 + 0.19905740571790709 + 0.19906284205654784 + 0.19906827853307815 + 0.19907371514750255 + 0.19907915189982592 + 0.19908458879005422 + 0.19909002581819141 + 0.19909546298424299 + 0.19910090028821342 + 0.19910633773010858 + 0.19911177530993251 + 0.19911721302769061 + 0.19912265088338787 + 0.19912808887702924 + 0.19913352700862016 + 0.1991389652781646 + 0.19914440368566802 + 0.19914984223113594 + 0.19915528091457271 + 0.19916071973598332 + 0.19916615869537277 + 0.19917159779274651 + 0.19917703702810896 + 0.19918247640146564 + 0.19918791591282095 + 0.19919335556218037 + 0.19919879534954893 + 0.19920423527493095 + 0.19920967533833156 + 0.19921511553975657 + 0.19922055587921003 + 0.19922599635669738 + 0.19923143697222356 + 0.19923687772579407 + 0.19924231861741293 + 0.19924775964708544 + 0.19925320081481668 + 0.19925864212061165 + 0.1992640835644752 + 0.19926952514641283 + 0.19927496686642907 + 0.19928040872452882 + 0.19928585072071706 + 0.19929129285499927 + 0.19929673512738041 + 0.19930217753786442 + 0.1993076200864578 + 0.19931306277316402 + 0.1993185055979895 + 0.1993239485609383 + 0.1993293916620158 + 0.19933483490122697 + 0.19934027827857631 + 0.19934572179406981 + 0.19935116544771089 + 0.19935660923950654 + 0.19936205316946023 + 0.19936749723757696 + 0.19937294144386308 + 0.19937838578832223 + 0.19938383027095977 + 0.19938927489178115 + 0.19939471965079092 + 0.19940016454799409 + 0.19940560958339545 + 0.19941105475700066 + 0.19941650006881412 + 0.19942194551884077 + 0.19942739110708607 + 0.19943283683355506 + 0.1994382826982522 + 0.1994437287011829 + 0.19944917484235172 + 0.19945462112176404 + 0.19946006753942497 + 0.19946551409533933 + 0.19947096078951168 + 0.19947640762194749 + 0.19948185459265225 + 0.19948730170162987 + 0.19949274894888588 + 0.19949819633442528 + 0.19950364385825342 + 0.19950909152037441 + 0.19951453932079419 + 0.19951998725951672 + 0.19952543533654798 + 0.19953088355189297 + 0.19953633190555564 + 0.19954178039754192 + 0.1995472290278569 + 0.19955267779650498 + 0.19955812670349121 + 0.199563575748821 + 0.19956902493249876 + 0.19957447425453012 + 0.19957992371492003 + 0.19958537331367343 + 0.19959082305079431 + 0.19959627292628909 + 0.19960172294016237 + 0.19960717309241902 + 0.19961262338306363 + 0.19961807381210206 + 0.1996235243795384 + 0.19962897508537811 + 0.1996344259296266 + 0.19963987691228793 + 0.19964532803336804 + 0.19965077929287137 + 0.19965623069080304 + 0.19966168222716793 + 0.19966713390197108 + 0.19967258571521787 + 0.19967803766691292 + 0.19968348975706163 + 0.19968894198566853 + 0.19969439435273903 + 0.19969984685827769 + 0.19970529950228949 + 0.19971075228477991 + 0.19971620520575437 + 0.19972165826521648 + 0.19972711146317212 + 0.19973256479962628 + 0.19973801827458407 + 0.19974347188805031 + 0.19974892564002963 + 0.19975437953052744 + 0.19975983355954871 + 0.19976528772709898 + 0.19977074203318224 + 0.19977619647780395 + 0.19978165106096962 + 0.19978710578268322 + 0.19979256064295078 + 0.19979801564177671 + 0.19980347077916558 + 0.19980892605512388 + 0.19981438146965502 + 0.19981983702276507 + 0.19982529271445904 + 0.19983074854474134 + 0.19983620451361694 + 0.19984166062109149 + 0.19984711686716936 + 0.19985257325185604 + 0.19985802977515604 + 0.19986348643707488 + 0.19986894323761759 + 0.19987440017678854 + 0.19987985725459334 + 0.19988531447103694 + 0.19989077182612433 + 0.19989622931985998 + 0.19990168695224994 + 0.19990714472329818 + 0.19991260263301072 + 0.19991806068139151 + 0.19992351886844612 + 0.19992897719417946 + 0.199934435658597 + 0.19993989426170289 + 0.19994535300350302 + 0.19995081188400191 + 0.19995627090320447 + 0.19996173006111642 + 0.19996718935774155 + 0.19997264879308593 + 0.19997810836715454 + 0.19998356807995143 + 0.19998902793148254 + 0.19999448792175292 + 0.19999994805076754 + 0.20000540831853039 + 0.20001086872504803 + 0.20001632927032389 + 0.20002178995436448 + 0.20002725077717387 + 0.20003271173875745 + 0.20003817283912032 + 0.20004363407826695 + 0.20004909545620284 + 0.20005455697293301 + 0.20006001862846245 + 0.20006548042279615 + 0.20007094235593909 + 0.20007640442789584 + 0.20008186663867233 + 0.20008732898827267 + 0.20009279147670272 + 0.20009825410396712 + 0.20010371687007075 + 0.20010917977501877 + 0.20011464281881608 + 0.20012010600146818 + 0.20012556932297912 + 0.20013103278335534 + 0.20013649638260045 + 0.20014196012071991 + 0.2001474239977197 + 0.20015288801360334 + 0.20015835216837685 + 0.20016381646204523 + 0.20016928089461247 + 0.2001747454660851 + 0.2001802101764672 + 0.20018567502576365 + 0.20019114001398053 + 0.20019660514112178 + 0.20020207040719254 + 0.20020753581219819 + 0.20021300135614384 + 0.20021846703903448 + 0.20022393286087503 + 0.20022939882167015 + 0.2002348649214257 + 0.20024033116014581 + 0.20024579753783595 + 0.20025126405450105 + 0.20025673071014627 + 0.20026219750477653 + 0.20026766443839686 + 0.20027313151101278 + 0.20027859872262832 + 0.20028406607324895 + 0.20028953356288023 + 0.20029500119152666 + 0.20030046895919326 + 0.20030593686588499 + 0.20031140491160743 + 0.20031687309636459 + 0.20032234142016297 + 0.20032780988300608 + 0.20033327848489993 + 0.20033874722584957 + 0.20034421610585945 + 0.20034968512493473 + 0.20035515428308026 + 0.20036062358030216 + 0.20036609301660438 + 0.20037156259199249 + 0.20037703230647103 + 0.20038250216004491 + 0.20038797215272028 + 0.20039344228450107 + 0.2003989125553928 + 0.20040438296540056 + 0.20040985351452886 + 0.20041532420278313 + 0.20042079503016902 + 0.20042626599668992 + 0.20043173710235243 + 0.20043720834716103 + 0.20044267973112079 + 0.20044815125423621 + 0.20045362291651328 + 0.20045909471795656 + 0.20046456665857057 + 0.20047003873836136 + 0.20047551095733337 + 0.20048098331549166 + 0.20048645581284183 + 0.20049192844938782 + 0.20049740122513512 + 0.20050287414008938 + 0.20050834719425503 + 0.20051382038763763 + 0.20051929372024119 + 0.20052476719207221 + 0.20053024080313425 + 0.20053571455343333 + 0.200541188442974 + 0.20054666247176178 + 0.20055213663980115 + 0.2005576109470977 + 0.20056308539365589 + 0.20056855997948081 + 0.20057403470457849 + 0.20057950956895287 + 0.20058498457260907 + 0.20059045971555253 + 0.20059593499778841 + 0.20060141041932164 + 0.20060688598015627 + 0.20061236168029886 + 0.20061783751975393 + 0.20062331349852644 + 0.20062878961662101 + 0.20063426587404312 + 0.20063974227079789 + 0.20064521880689018 + 0.20065069548232467 + 0.20065617229710733 + 0.20066164925124275 + 0.20066712634473535 + 0.20067260357759126 + 0.20067808094981451 + 0.20068355846141103 + 0.20068903611238553 + 0.2006945139027424 + 0.20069999183248771 + 0.20070546990162599 + 0.2007109481101623 + 0.20071642645810217 + 0.20072190494545014 + 0.2007273835722107 + 0.20073286233838997 + 0.20073834124399292 + 0.20074382028902357 + 0.20074929947348802 + 0.20075477879739076 + 0.20076025826073735 + 0.20076573786353233 + 0.20077121760578068 + 0.200776697487488 + 0.20078217750865884 + 0.20078765766929871 + 0.20079313796941212 + 0.20079861840900465 + 0.20080409898808085 + 0.20080957970664617 + 0.20081506056470524 + 0.20082054156226362 + 0.20082602269932628 + 0.20083150397589827 + 0.20083698539198375 + 0.20084246694758906 + 0.20084794864271829 + 0.20085343047737717 + 0.20085891245157053 + 0.20086439456530297 + 0.20086987681858007 + 0.20087535921140737 + 0.20088084174378837 + 0.20088632441572962 + 0.20089180722723568 + 0.20089729017831109 + 0.20090277326896197 + 0.20090825649919222 + 0.20091373986900743 + 0.20091922337841275 + 0.20092470702741361 + 0.20093019081601413 + 0.20093567474421975 + 0.20094115881203564 + 0.20094664301946674 + 0.20095212736651868 + 0.20095761185319549 + 0.20096309647950314 + 0.20096858124544575 + 0.20097406615102936 + 0.20097955119625852 + 0.20098503638113829 + 0.20099052170567416 + 0.20099600716987023 + 0.20100149277373258 + 0.20100697851726565 + 0.20101246440047507 + 0.20101795042336487 + 0.2010234365859411 + 0.20102892288820828 + 0.20103440933017203 + 0.20103989591183735 + 0.20104538263320834 + 0.20105086949429099 + 0.20105635649508985 + 0.20106184363561055 + 0.20106733091585757 + 0.20107281833583646 + 0.20107830589555184 + 0.20108379359500869 + 0.20108928143421304 + 0.20109476941316856 + 0.20110025753188121 + 0.20110574579035609 + 0.20111123418859828 + 0.20111672272661224 + 0.20112221140440303 + 0.20112770022197629 + 0.20113318917933756 + 0.20113867827649029 + 0.20114416751344119 + 0.20114965689019423 + 0.20115514640675444 + 0.20116063606312795 + 0.20116612585931878 + 0.20117161579533246 + 0.2011771058711741 + 0.20118259608684874 + 0.20118808644236091 + 0.20119357693771617 + 0.20119906757291964 + 0.20120455834797635 + 0.20121004926289132 + 0.20121554031766911 + 0.20122103151231582 + 0.20122652284683598 + 0.20123201432123416 + 0.20123750593551645 + 0.20124299768968684 + 0.20124848958375099 + 0.20125398161771438 + 0.2012594737915811 + 0.20126496610535724 + 0.20127045855904679 + 0.20127595115265531 + 0.20128144388618849 + 0.20128693675965029 + 0.20129242977304676 + 0.20129792292638246 + 0.20130341621966252 + 0.20130890965289203 + 0.20131440322607588 + 0.20131989693921984 + 0.20132539079232833 + 0.20133088478540598 + 0.20133637891845887 + 0.20134187319149149 + 0.2013473676045095 + 0.20135286215751688 + 0.20135835685052028 + 0.20136385168352322 + 0.20136934665653122 + 0.20137484176954992 + 0.20138033702258384 + 0.20138583241563812 + 0.20139132794871825 + 0.20139682362182881 + 0.20140231943497491 + 0.2014078153881621 + 0.20141331148139541 + 0.20141880771467896 + 0.20142430408801881 + 0.20142980060141949 + 0.2014352972548866 + 0.20144079404842524 + 0.20144629098203942 + 0.20145178805573521 + 0.20145728526951778 + 0.2014627826233916 + 0.20146828011736229 + 0.20147377775143438 + 0.20147927552561301 + 0.20148477343990417 + 0.20149027149431145 + 0.2014957696888415 + 0.20150126802349777 + 0.201506766498287 + 0.20151226511321307 + 0.20151776386828171 + 0.20152326276349738 + 0.20152876179886575 + 0.20153426097439137 + 0.20153976029007969 + 0.20154525974593598 + 0.20155075934196473 + 0.20155625907817198 + 0.20156175895456138 + 0.20156725897113942 + 0.20157275912791023 + 0.20157825942487942 + 0.20158375986205149 + 0.20158926043943254 + 0.20159476115702668 + 0.20160026201483899 + 0.20160576301287544 + 0.20161126415114028 + 0.20161676542963902 + 0.20162226684837667 + 0.20162776840735835 + 0.20163327010658871 + 0.20163877194607321 + 0.20164427392581752 + 0.20164977604582521 + 0.2016552783061028 + 0.20166078070665497 + 0.2016662832474862 + 0.20167178592860213 + 0.20167728875000776 + 0.2016827917117083 + 0.20168829481370881 + 0.20169379805601426 + 0.20169930143862985 + 0.20170480496156062 + 0.20171030862481112 + 0.20171581242838749 + 0.20172131637229379 + 0.20172682045653562 + 0.20173232468111849 + 0.20173782904604656 + 0.20174333355132545 + 0.20174883819696016 + 0.2017543429829558 + 0.20175984790931745 + 0.20176535297605072 + 0.20177085818315968 + 0.2017763635306499 + 0.20178186901852649 + 0.20178737464679461 + 0.20179288041545923 + 0.20179838632452546 + 0.2018038923739989 + 0.20180939856388366 + 0.20181490489418583 + 0.2018204113649095 + 0.2018259179760602 + 0.20183142472764354 + 0.20183693161966415 + 0.20184243865212664 + 0.20184794582503707 + 0.20185345313839995 + 0.20185896059222047 + 0.20186446818650366 + 0.20186997592125469 + 0.2018754837964786 + 0.201880991812181 + 0.20188649996836588 + 0.20189200826503947 + 0.20189751670220638 + 0.20190302527987156 + 0.20190853399803968 + 0.20191404285671732 + 0.20191955185590807 + 0.20192506099561758 + 0.20193057027585143 + 0.20193607969661409 + 0.20194158925791084 + 0.20194709895974658 + 0.20195260880212712 + 0.2019581187850564 + 0.2019636289085405 + 0.20196913917258413 + 0.20197464957719233 + 0.20198016012237022 + 0.20198567080812332 + 0.20199118163445631 + 0.20199669260137426 + 0.20200220370888231 + 0.20200771495698547 + 0.20201322634568936 + 0.20201873787499858 + 0.20202424954491832 + 0.20202976135545356 + 0.20203527330660992 + 0.2020407853983916 + 0.20204629763080506 + 0.202051810003854 + 0.20205732251754399 + 0.20206283517188062 + 0.20206834796686848 + 0.2020738609025127 + 0.20207937397881889 + 0.2020848871957916 + 0.20209040055343591 + 0.20209591405175703 + 0.2021014276907605 + 0.20210694147045044 + 0.20211245539083292 + 0.2021179694519131 + 0.20212348365369501 + 0.20212899799618481 + 0.20213451247938755 + 0.20214002710330736 + 0.20214554186795042 + 0.20215105677332121 + 0.2021565718194249 + 0.20216208700626709 + 0.20216760233385245 + 0.20217311780218594 + 0.20217863341127276 + 0.20218414916111849 + 0.20218966505172775 + 0.20219518108310613 + 0.2022006972552578 + 0.20220621356818883 + 0.20221173002190379 + 0.20221724661640827 + 0.2022227633517065 + 0.20222828022780492 + 0.2022337972447073 + 0.20223931440241963 + 0.20224483170094659 + 0.2022503491402933 + 0.20225586672046481 + 0.20226138444146674 + 0.20226690230330377 + 0.20227242030598139 + 0.20227793844950384 + 0.20228345673387713 + 0.20228897515910638 + 0.20229449372519576 + 0.2023000124321514 + 0.20230553127997786 + 0.20231105026868074 + 0.20231656939826412 + 0.20232208866873425 + 0.20232760808009609 + 0.20233312763235387 + 0.20233864732551363 + 0.20234416715957998 + 0.20234968713455861 + 0.20235520725045356 + 0.20236072750727099 + 0.20236624790501601 + 0.2023717684436927 + 0.20237728912330721 + 0.20238280994386415 + 0.20238833090536865 + 0.20239385200782628 + 0.20239937325124169 + 0.20240489463561995 + 0.20241041616096631 + 0.20241593782728623 + 0.20242145963458438 + 0.20242698158286596 + 0.20243250367213594 + 0.20243802590240007 + 0.20244354827366293 + 0.20244907078592958 + 0.20245459343920522 + 0.20246011623349544 + 0.20246563916880486 + 0.20247116224513859 + 0.20247668546250172 + 0.20248220882089998 + 0.2024877323203374 + 0.20249325596082005 + 0.2024987797423527 + 0.20250430366494082 + 0.20250982772858866 + 0.20251535193330233 + 0.20252087627908635 + 0.20252640076594589 + 0.20253192539388612 + 0.20253745016291266 + 0.20254297507302957 + 0.20254850012424297 + 0.20255402531655756 + 0.20255955064997844 + 0.20256507612451122 + 0.20257060174015998 + 0.20257612749693096 + 0.2025816533948287 + 0.20258717943385829 + 0.20259270561402495 + 0.20259823193533377 + 0.20260375839779038 + 0.20260928500139888 + 0.20261481174616489 + 0.20262033863209414 + 0.20262586565919113 + 0.20263139282746104 + 0.20263692013690904 + 0.20264244758754019 + 0.20264797517935959 + 0.2026535029123725 + 0.20265903078658451 + 0.20266455880199966 + 0.2026700869586241 + 0.20267561525646202 + 0.20268114369551954 + 0.20268667227580131 + 0.20269220099731186 + 0.20269772986005744 + 0.20270325886404256 + 0.202708788009272 + 0.20271431729575179 + 0.20271984672348656 + 0.20272537629248147 + 0.20273090600274166 + 0.20273643585427173 + 0.20274196584707788 + 0.2027474959811647 + 0.20275302625653679 + 0.20275855667320039 + 0.20276408723115952 + 0.20276961793042036 + 0.20277514877098704 + 0.20278067975286565 + 0.20278621087606044 + 0.20279174214057696 + 0.20279727354642038 + 0.2028028050935958 + 0.20280833678210838 + 0.20281386861196332 + 0.20281940058316511 + 0.20282493269571999 + 0.20283046494963211 + 0.20283599734490759 + 0.20284152988155055 + 0.20284706255956658 + 0.20285259537896039 + 0.20285812833973815 + 0.2028636614419039 + 0.20286919468546333 + 0.20287472807042162 + 0.20288026159678382 + 0.20288579526455466 + 0.20289132907374022 + 0.20289686302434418 + 0.2029023971163732 + 0.20290793134983182 + 0.2029134657247248 + 0.20291900024105766 + 0.20292453489883513 + 0.20293006969806335 + 0.20293560463874649 + 0.20294113972088962 + 0.20294667494449836 + 0.2029522103095785 + 0.20295774581613352 + 0.20296328146416967 + 0.20296881725369204 + 0.2029743531847058 + 0.20297988925721561 + 0.20298542547122658 + 0.20299096182674489 + 0.20299649832377459 + 0.203002034962321 + 0.20300757174238962 + 0.20301310866398564 + 0.20301864572711373 + 0.20302418293177896 + 0.2030297202779871 + 0.20303525776574324 + 0.20304079539505202 + 0.20304633316591905 + 0.20305187107834857 + 0.20305740913234713 + 0.20306294732791894 + 0.20306848566506916 + 0.20307402414380335 + 0.20307956276412631 + 0.20308510152604356 + 0.20309064042955982 + 0.20309617947468017 + 0.20310171866141036 + 0.20310725798975499 + 0.20311279745971916 + 0.20311833707130861 + 0.20312387682452795 + 0.20312941671938237 + 0.20313495675587742 + 0.20314049693401737 + 0.20314603725380881 + 0.20315157771525538 + 0.20315711831836325 + 0.20316265906313669 + 0.20316819994958166 + 0.20317374097770344 + 0.20317928214750611 + 0.20318482345899588 + 0.2031903649121769 + 0.20319590650705585 + 0.20320144824363578 + 0.20320699012192397 + 0.203212532141924 + 0.20321807430364155 + 0.20322361660708227 + 0.20322915905225034 + 0.20323470163915189 + 0.20324024436779106 + 0.2032457872381741 + 0.20325133025030556 + 0.20325687340419016 + 0.20326241669983405 + 0.20326796013724135 + 0.20327350371641831 + 0.20327904743736899 + 0.20328459130009957 + 0.20329013530461426 + 0.20329567945091917 + 0.20330122373901799 + 0.20330676816891735 + 0.20331231274062198 + 0.20331785745413694 + 0.20332340230946699 + 0.20332894730661819 + 0.20333449244559432 + 0.20334003772640249 + 0.20334558314904583 + 0.20335112871353053 + 0.20335667441986172 + 0.20336222026804465 + 0.20336776625808389 + 0.20337331238998566 + 0.20337885866375366 + 0.20338440507939445 + 0.2033899516369122 + 0.20339549833631274 + 0.20340104517760055 + 0.20340659216078136 + 0.2034121392858598 + 0.20341768655284218 + 0.20342323396173195 + 0.20342878151253543 + 0.20343432920525784 + 0.20343987703990363 + 0.20344542501647864 + 0.20345097313498703 + 0.20345652139543535 + 0.20346206979782791 + 0.20346761834216981 + 0.20347316702846671 + 0.20347871585672328 + 0.20348426482694473 + 0.20348981393913668 + 0.20349536319330386 + 0.20350091258945133 + 0.20350646212758489 + 0.20351201180770914 + 0.20351756162982929 + 0.20352311159395045 + 0.20352866170007836 + 0.20353421194821769 + 0.20353976233837351 + 0.20354531287055111 + 0.2035508635447556 + 0.2035564143609922 + 0.20356196531926654 + 0.20356751641958334 + 0.20357306766194722 + 0.20357861904636435 + 0.20358417057283948 + 0.2035897222413772 + 0.20359527405198374 + 0.20360082600466375 + 0.20360637809942192 + 0.20361193033626437 + 0.20361748271519589 + 0.20362303523622108 + 0.20362858789934557 + 0.20363414070457514 + 0.20363969365191392 + 0.20364524674136708 + 0.20365079997294083 + 0.20365635334663984 + 0.20366190686246874 + 0.20366746052043322 + 0.20367301432053803 + 0.20367856826278927 + 0.20368412234719063 + 0.20368967657374884 + 0.20369523094246855 + 0.20370078545335438 + 0.20370634010641162 + 0.20371189490164585 + 0.20371744983906234 + 0.20372300491866624 + 0.20372856014046223 + 0.20373411550445544 + 0.20373967101065166 + 0.20374522665905542 + 0.20375078244967204 + 0.20375633838250765 + 0.20376189445756596 + 0.20376745067485311 + 0.20377300703437379 + 0.20377856353613372 + 0.2037841201801375 + 0.20378967696639047 + 0.20379523389489818 + 0.20380079096566533 + 0.20380634817869667 + 0.20381190553399883 + 0.20381746303157552 + 0.20382302067143235 + 0.20382857845357516 + 0.20383413637800857 + 0.20383969444473771 + 0.20384525265376777 + 0.20385081100510402 + 0.20385636949875161 + 0.20386192813471563 + 0.20386748691300141 + 0.2038730458336141 + 0.2038786048965589 + 0.20388416410184096 + 0.20388972344946543 + 0.20389528293943709 + 0.20390084257176208 + 0.20390640234644461 + 0.20391196226349037 + 0.20391752232290453 + 0.20392308252469227 + 0.20392864286885831 + 0.20393420335540891 + 0.20393976398434813 + 0.20394532475568122 + 0.20395088566941386 + 0.20395644672555127 + 0.20396200792409813 + 0.20396756926506016 + 0.20397313074844253 + 0.20397869237424984 + 0.203984254142488 + 0.20398981605316147 + 0.20399537810627558 + 0.20400094030183602 + 0.20400650263984793 + 0.20401206512031556 + 0.20401762774324508 + 0.20402319050864168 + 0.2040287534165095 + 0.20403431646685488 + 0.20403987965968243 + 0.20404544299499786 + 0.2040510064728058 + 0.20405657009311159 + 0.20406213385591979 + 0.20406769776123715 + 0.20407326180906737 + 0.20407882599941624 + 0.20408439033228926 + 0.20408995480769077 + 0.20409551942562693 + 0.20410108418610245 + 0.20410664908912207 + 0.20411221413469141 + 0.20411777932281569 + 0.20412334465350015 + 0.2041289101267505 + 0.20413447574257088 + 0.20414004150096654 + 0.2041456074019436 + 0.20415117344550643 + 0.20415673963166051 + 0.20416230596041127 + 0.20416787243176324 + 0.20417343904572222 + 0.20417900580229281 + 0.20418457270148085 + 0.2041901397432915 + 0.2041957069277299 + 0.20420127425480028 + 0.20420684172450937 + 0.20421240933686091 + 0.20421797709186151 + 0.20422354498951498 + 0.20422911302982741 + 0.20423468121280414 + 0.20424024953844924 + 0.20424581800676905 + 0.20425138661776815 + 0.2042569553714523 + 0.20426252426782626 + 0.20426809330689519 + 0.20427366248866424 + 0.20427923181313876 + 0.20428480128032381 + 0.2042903708902247 + 0.20429594064284712 + 0.2043015105381952 + 0.20430708057627525 + 0.20431265075709146 + 0.20431822108065001 + 0.20432379154695512 + 0.20432936215601252 + 0.20433493290782739 + 0.20434050380240498 + 0.20434607483974995 + 0.20435164601986858 + 0.20435721734276499 + 0.204362788808445 + 0.20436836041691325 + 0.20437393216817595 + 0.20437950406223684 + 0.20438507609910261 + 0.20439064827877754 + 0.20439622060126675 + 0.20440179306657605 + 0.20440736567471005 + 0.20441293842567451 + 0.20441851131947475 + 0.20442408435611478 + 0.20442965753560149 + 0.20443523085793852 + 0.20444080432313208 + 0.20444637793118689 + 0.20445195168210825 + 0.20445752557590122 + 0.20446309961257164 + 0.20446867379212419 + 0.20447424811456361 + 0.20447982257989608 + 0.20448539718812683 + 0.20449097193926011 + 0.20449654683330162 + 0.20450212187025657 + 0.20450769705013011 + 0.20451327237292757 + 0.20451884783865365 + 0.20452442344731459 + 0.20452999919891451 + 0.20453557509345921 + 0.20454115113095389 + 0.20454672731140383 + 0.20455230363481364 + 0.20455788010118911 + 0.20456345671053547 + 0.2045690334628574 + 0.20457461035816069 + 0.20458018739644998 + 0.20458576457773101 + 0.20459134190200853 + 0.20459691936928828 + 0.20460249697957497 + 0.20460807473287385 + 0.20461365262919057 + 0.20461923066852991 + 0.20462480885089759 + 0.20463038717629781 + 0.20463596564473685 + 0.20464154425621936 + 0.20464712301075066 + 0.2046527019083364 + 0.20465828094898075 + 0.20466386013268958 + 0.20466943945946858 + 0.20467501892932197 + 0.2046805985422559 + 0.20468617829827468 + 0.20469175819738403 + 0.20469733823958911 + 0.2047029184248953 + 0.20470849875330716 + 0.20471407922483101 + 0.20471965983947107 + 0.20472524059723252 + 0.20473082149812166 + 0.20473640254214273 + 0.20474198372930141 + 0.2047475650596019 + 0.20475314653305102 + 0.20475872814965299 + 0.20476430990941347 + 0.20476989181233723 + 0.20477547385842951 + 0.204781056047696 + 0.20478663838014152 + 0.20479222085577126 + 0.20479780347459089 + 0.20480338623660474 + 0.20480896914181898 + 0.20481455219023895 + 0.20482013538186825 + 0.20482571871671418 + 0.20483130219478041 + 0.20483688581607332 + 0.20484246958059699 + 0.20484805348835727 + 0.20485363753935931 + 0.20485922173360843 + 0.2048648060711098 + 0.20487039055186818 + 0.20487597517588926 + 0.20488155994317839 + 0.20488714485374074 + 0.20489272990758103 + 0.20489831510470499 + 0.20490390044511742 + 0.20490948592882449 + 0.20491507155583005 + 0.2049206573261402 + 0.20492624323976028 + 0.20493182929669448 + 0.20493741549694908 + 0.20494300184052927 + 0.20494858832743984 + 0.204954174957686 + 0.20495976173127298 + 0.20496534864820609 + 0.20497093570849098 + 0.20497652291213245 + 0.20498211025913526 + 0.20498769774950557 + 0.20499328538324821 + 0.20499887316036841 + 0.20500446108087084 + 0.20501004914476181 + 0.20501563735204553 + 0.20502122570272782 + 0.20502681419681382 + 0.20503240283430885 + 0.20503799161521766 + 0.20504358053954594 + 0.20504916960729894 + 0.20505475881848145 + 0.20506034817309918 + 0.20506593767115691 + 0.20507152731266035 + 0.20507711709761425 + 0.20508270702602394 + 0.20508829709789503 + 0.20509388731323283 + 0.20509947767204165 + 0.20510506817432766 + 0.20511065882009566 + 0.20511624960935079 + 0.20512184054209848 + 0.20512743161834382 + 0.20513302283809268 + 0.20513861420134918 + 0.20514420570811917 + 0.20514979735840791 + 0.20515538915222109 + 0.20516098108956302 + 0.20516657317043885 + 0.20517216539485492 + 0.20517775776281547 + 0.20518335027432624 + 0.20518894292939252 + 0.20519453572801899 + 0.20520012867021145 + 0.20520572175597465 + 0.20521131498531484 + 0.20521690835823581 + 0.20522250187474378 + 0.20522809553484339 + 0.20523368933854064 + 0.2052392832858396 + 0.20524487737674657 + 0.20525047161126683 + 0.2052560659894046 + 0.20526166051116612 + 0.20526725517655575 + 0.20527284998557965 + 0.20527844493824265 + 0.20528404003454942 + 0.20528963527450625 + 0.20529523065811797 + 0.2053008261853892 + 0.20530642185632636 + 0.20531201767093354 + 0.20531761362921613 + 0.20532320973118032 + 0.2053288059768304 + 0.20533440236617162 + 0.20533999889921029 + 0.20534559557595003 + 0.20535119239639776 + 0.20535678936055765 + 0.20536238646843499 + 0.20536798372003504 + 0.20537358111536355 + 0.20537917865442532 + 0.20538477633722604 + 0.20539037416377004 + 0.20539597213406352 + 0.20540157024811137 + 0.20540716850591814 + 0.2054127669074903 + 0.20541836545283251 + 0.20542396414195008 + 0.20542956297484821 + 0.20543516195153169 + 0.20544076107200637 + 0.20544636033627739 + 0.20545195974435013 + 0.20545755929622975 + 0.20546315899192108 + 0.20546875883142982 + 0.20547435881476084 + 0.20547995894191981 + 0.20548555921291156 + 0.20549115962774181 + 0.20549676018641541 + 0.20550236088893803 + 0.20550796173531449 + 0.20551356272555002 + 0.20551916385964997 + 0.20552476513761955 + 0.20553036655946455 + 0.20553596812518965 + 0.20554156983479974 + 0.20554717168830106 + 0.20555277368569788 + 0.2055583758269964 + 0.20556397811220098 + 0.20556958054131785 + 0.2055751831143508 + 0.2055807858313066 + 0.20558638869218951 + 0.20559199169700529 + 0.20559759484575924 + 0.20560319813845615 + 0.2056088015751017 + 0.20561440515570079 + 0.20562000888025864 + 0.20562561274878149 + 0.20563121676127311 + 0.20563682091773933 + 0.2056424252181859 + 0.20564802966261761 + 0.20565363425103975 + 0.2056592389834575 + 0.20566484385987674 + 0.2056704488803017 + 0.20567605404473813 + 0.20568165935319141 + 0.20568726480566668 + 0.20569287040216935 + 0.20569847614270459 + 0.20570408202727772 + 0.20570968805589304 + 0.2057152942285573 + 0.20572090054527475 + 0.20572650700605127 + 0.20573211361089205 + 0.2057377203598019 + 0.2057433272527861 + 0.20574893428985036 + 0.20575454147099964 + 0.20576014879623902 + 0.20576575626557439 + 0.20577136387900993 + 0.20577697163655209 + 0.20578257953820553 + 0.20578818758397557 + 0.2057937957738675 + 0.20579940410788661 + 0.20580501258603809 + 0.20581062120832683 + 0.20581622997475907 + 0.20582183888533903 + 0.20582744794007266 + 0.20583305713896463 + 0.20583866648202068 + 0.2058442759692467 + 0.20584988560064643 + 0.20585549537622616 + 0.20586110529599069 + 0.20586671535994527 + 0.20587232556809568 + 0.20587793592044723 + 0.20588354641700421 + 0.20588915705777297 + 0.20589476784275815 + 0.20590037877196515 + 0.20590598984539921 + 0.20591160106306514 + 0.20591721242496971 + 0.20592282393111624 + 0.20592843558151147 + 0.20593404737616025 + 0.20593965931506736 + 0.20594527139823848 + 0.20595088362567904 + 0.2059564959973938 + 0.20596210851338798 + 0.20596772117366799 + 0.20597333397823794 + 0.20597894692710331 + 0.2059845600202693 + 0.20599017325774172 + 0.20599578663952536 + 0.20600140016562546 + 0.20600701383604791 + 0.20601262765079742 + 0.20601824160987928 + 0.20602385571329837 + 0.20602946996106095 + 0.20603508435317178 + 0.20604069888963569 + 0.20604631357045891 + 0.20605192839564584 + 0.20605754336520166 + 0.20606315847913273 + 0.20606877373744339 + 0.20607438914013937 + 0.2060800046872254 + 0.20608562037870692 + 0.20609123621459019 + 0.20609685219487892 + 0.20610246831957948 + 0.2061080845886967 + 0.20611370100223575 + 0.2061193175602021 + 0.20612493426260139 + 0.20613055110943854 + 0.20613616810071825 + 0.20614178523644686 + 0.20614740251662869 + 0.20615301994127005 + 0.20615863751037519 + 0.20616425522394999 + 0.20616987308199966 + 0.20617549108452901 + 0.2061811092315439 + 0.20618672752304906 + 0.20619234595905037 + 0.20619796453955253 + 0.20620358326456151 + 0.20620920213408189 + 0.20621482114811965 + 0.20622044030667908 + 0.20622605960976634 + 0.20623167905738693 + 0.20623729864954451 + 0.20624291838624639 + 0.20624853826749645 + 0.20625415829330046 + 0.20625977846366372 + 0.20626539877859099 + 0.20627101923808866 + 0.20627663984216102 + 0.20628226059081384 + 0.20628788148405192 + 0.20629350252188111 + 0.20629912370430667 + 0.2063047450313335 + 0.20631036650296727 + 0.20631598811921237 + 0.20632160988007509 + 0.20632723178556081 + 0.20633285383567368 + 0.20633847603042013 + 0.2063440983698045 + 0.20634972085383294 + 0.20635534348251044 + 0.20636096625584219 + 0.20636658917383302 + 0.20637221223648933 + 0.20637783544381474 + 0.20638345879581679 + 0.20638908229249867 + 0.20639470593386666 + 0.20640032971992611 + 0.20640595365068187 + 0.20641157772613922 + 0.20641720194630397 + 0.20642282631118095 + 0.20642845082077596 + 0.20643407547509326 + 0.20643970027413977 + 0.20644532521791867 + 0.20645095030643695 + 0.20645657553969982 + 0.20646220091771153 + 0.20646782644047751 + 0.20647345210800405 + 0.20647907792029599 + 0.20648470387735804 + 0.20649032997919609 + 0.20649595622581493 + 0.20650158261722046 + 0.20650720915341786 + 0.20651283583441207 + 0.20651846266020835 + 0.20652408963081254 + 0.20652971674622939 + 0.20653534400646434 + 0.20654097141152306 + 0.20654659896141003 + 0.20655222665613146 + 0.20655785449569167 + 0.20656348248009709 + 0.20656911060935185 + 0.20657473888346245 + 0.20658036730243315 + 0.20658599586626922 + 0.20659162457497704 + 0.20659725342856086 + 0.20660288242702665 + 0.20660851157037907 + 0.20661414085862351 + 0.20661977029176581 + 0.20662539986981127 + 0.20663102959276428 + 0.20663665946063101 + 0.2066422894734164 + 0.20664791963112575 + 0.20665354993376439 + 0.20665918038133763 + 0.20666481097385028 + 0.2066704417113093 + 0.20667607259371776 + 0.20668170362108221 + 0.20668733479340787 + 0.20669296611070012 + 0.20669859757296419 + 0.20670422918020451 + 0.20670986093242788 + 0.20671549282963814 + 0.20672112487184158 + 0.2067267570590435 + 0.2067323893912483 + 0.20673802186846224 + 0.20674365449069029 + 0.20674928725793759 + 0.20675492017020961 + 0.20676055322751155 + 0.20676618642984887 + 0.20677181977722636 + 0.20677745326965027 + 0.20678308690712505 + 0.20678872068965645 + 0.20679435461724935 + 0.20679998868990956 + 0.20680562290764193 + 0.20681125727045221 + 0.20681689177834536 + 0.20682252643132659 + 0.20682816122940181 + 0.20683379617257586 + 0.20683943126085405 + 0.20684506649424164 + 0.2068507018727441 + 0.20685633739636666 + 0.2068619730651147 + 0.20686760887899358 + 0.20687324483800809 + 0.20687888094216406 + 0.20688451719146686 + 0.20689015358592133 + 0.20689579012553322 + 0.20690142681030799 + 0.20690706364024988 + 0.20691270061536526 + 0.20691833773565954 + 0.20692397500113743 + 0.20692961241180383 + 0.2069352499676651 + 0.20694088766872604 + 0.20694652551499196 + 0.20695216350646831 + 0.20695780164316036 + 0.20696343992507291 + 0.20696907835221237 + 0.206974716924583 + 0.20698035564219017 + 0.20698599450504029 + 0.20699163351313715 + 0.2069972726664871 + 0.20700291196509546 + 0.2070085514089666 + 0.20701419099810736 + 0.20701983073252153 + 0.20702547061221493 + 0.20703111063719357 + 0.20703675080746167 + 0.20704239112302503 + 0.20704803158388962 + 0.20705367219005968 + 0.20705931294154056 + 0.20706495383833867 + 0.20707059488045834 + 0.20707623606790537 + 0.20708187740068465 + 0.207087518878802 + 0.20709316050226226 + 0.20709880227107128 + 0.20710444418523341 + 0.20711008624475502 + 0.20711572844964093 + 0.20712137079989654 + 0.2071270132955276 + 0.20713265593653848 + 0.2071382987229351 + 0.20714394165472275 + 0.20714958473190628 + 0.20715522795449157 + 0.20716087132248395 + 0.2071665148358888 + 0.20717215849471093 + 0.20717780229895569 + 0.20718344624862889 + 0.20718909034373548 + 0.20719473458428123 + 0.2072003789702711 + 0.20720602350170977 + 0.20721166817860373 + 0.20721731300095778 + 0.20722295796877729 + 0.20722860308206706 + 0.20723424834083351 + 0.20723989374508101 + 0.20724553929481529 + 0.20725118499004186 + 0.20725683083076546 + 0.20726247681699142 + 0.20726812294872576 + 0.20727376922597374 + 0.20727941564873956 + 0.20728506221703036 + 0.2072907089308498 + 0.20729635579020378 + 0.20730200279509772 + 0.20730764994553685 + 0.20731329724152717 + 0.20731894468307238 + 0.20732459227017946 + 0.20733024000285327 + 0.20733588788109863 + 0.20734153590492138 + 0.20734718407432637 + 0.20735283238931948 + 0.2073584808499056 + 0.20736412945609059 + 0.20736977820787919 + 0.20737542710527693 + 0.20738107614828905 + 0.2073867253369209 + 0.20739237467117802 + 0.20739802415106551 + 0.20740367377658894 + 0.20740932354775357 + 0.20741497346456425 + 0.20742062352702742 + 0.20742627373514688 + 0.20743192408892955 + 0.20743757458837969 + 0.20744322523350278 + 0.20744887602430459 + 0.20745452696078948 + 0.20746017804296393 + 0.20746582927083321 + 0.20747148064440171 + 0.20747713216367528 + 0.20748278382865978 + 0.20748843563935956 + 0.20749408759578059 + 0.20749973969792809 + 0.20750539194580706 + 0.20751104433942327 + 0.20751669687878213 + 0.20752234956388846 + 0.2075280023947477 + 0.20753365537136559 + 0.20753930849374719 + 0.20754496176189824 + 0.20755061517582313 + 0.20755626873552821 + 0.20756192244101787 + 0.20756757629229794 + 0.20757323028937441 + 0.2075788844322515 + 0.20758453872093521 + 0.20759019315543081 + 0.20759584773574322 + 0.20760150246187775 + 0.20760715733384036 + 0.20761281235163637 + 0.20761846751527063 + 0.20762412282474862 + 0.20762977828007614 + 0.20763543388125746 + 0.20764108962829911 + 0.20764674552120538 + 0.20765240155998271 + 0.20765805774463539 + 0.20766371407516929 + 0.2076693705515899 + 0.20767502717390199 + 0.20768068394211142 + 0.20768634085622367 + 0.20769199791624357 + 0.20769765512217647 + 0.20770331247402823 + 0.20770896997180371 + 0.20771462761550838 + 0.20772028540514759 + 0.20772594334072661 + 0.20773160142225097 + 0.20773725964972597 + 0.207742918023157 + 0.20774857654254938 + 0.20775423520790806 + 0.20775989401923892 + 0.20776555297654678 + 0.20777121207983759 + 0.20777687132911668 + 0.20778253072438843 + 0.20778819026565923 + 0.20779384995293398 + 0.20779950978621803 + 0.20780516976551675 + 0.20781082989083613 + 0.20781649016218035 + 0.2078221505795555 + 0.20782781114296681 + 0.20783347185241927 + 0.20783913270791868 + 0.20784479370947048 + 0.20785045485707951 + 0.20785611615075164 + 0.20786177759049135 + 0.20786743917630537 + 0.20787310090819777 + 0.20787876278617431 + 0.20788442481024089 + 0.2078900869804024 + 0.20789574929666371 + 0.20790141175903074 + 0.20790707436750885 + 0.20791273712210348 + 0.20791840002281992 + 0.20792406306966313 + 0.20792972626263853 + 0.20793538960175187 + 0.20794105308700814 + 0.2079467167184133 + 0.20795238049597156 + 0.2079580444196894 + 0.20796370848957166 + 0.20796937270562385 + 0.20797503706785125 + 0.20798070157625931 + 0.20798636623085284 + 0.20799203103163777 + 0.2079976959786195 + 0.20800336107180298 + 0.20800902631119397 + 0.20801469169679751 + 0.20802035722861936 + 0.20802602290666442 + 0.20803168873093819 + 0.20803735470144599 + 0.2080430208181932 + 0.20804868708118521 + 0.20805435349042745 + 0.20806002004592533 + 0.20806568674768416 + 0.20807135359570894 + 0.20807702059000549 + 0.20808268773057917 + 0.20808835501743495 + 0.20809402245057826 + 0.20809969003001483 + 0.2081053577557492 + 0.20811102562778833 + 0.20811669364613591 + 0.20812236181079791 + 0.20812803012177983 + 0.20813369857908701 + 0.20813936718272472 + 0.20814503593269856 + 0.20815070482901332 + 0.20815637387167438 + 0.20816204306068817 + 0.20816771239605858 + 0.20817338187779255 + 0.20817905150589397 + 0.20818472128036913 + 0.2081903912012226 + 0.20819606126846066 + 0.2082017314820882 + 0.20820740184211073 + 0.20821307234853306 + 0.20821874300136112 + 0.20822441380060028 + 0.20823008474625598 + 0.20823575583833315 + 0.20824142707683707 + 0.20824709846177375 + 0.20825276999314862 + 0.20825844167096599 + 0.2082641134952323 + 0.20826978546595251 + 0.20827545758313137 + 0.20828112984677546 + 0.20828680225688956 + 0.20829247481347862 + 0.2082981475165486 + 0.20830382036610479 + 0.20830949336215218 + 0.20831516650469672 + 0.20832083979374316 + 0.20832651322929754 + 0.20833218681136415 + 0.20833786053994954 + 0.20834353441505848 + 0.20834920843669655 + 0.20835488260486898 + 0.20836055691958122 + 0.20836623138083876 + 0.20837190598864641 + 0.2083775807430101 + 0.20838325564393534 + 0.20838893069142689 + 0.2083946058854908 + 0.20840028122613186 + 0.20840595671335554 + 0.20841163234716725 + 0.20841730812757236 + 0.20842298405457682 + 0.20842866012818556 + 0.20843433634840342 + 0.20844001271523638 + 0.20844568922868983 + 0.20845136588876867 + 0.20845704269547882 + 0.20846271964882568 + 0.20846839674881421 + 0.20847407399544973 + 0.20847975138873828 + 0.20848542892868469 + 0.20849110661529444 + 0.20849678444857231 + 0.20850246242852483 + 0.2085081405551569 + 0.20851381882847392 + 0.20851949724848085 + 0.20852517581518351 + 0.20853085452858691 + 0.2085365333886969 + 0.20854221239551893 + 0.20854789154905737 + 0.20855357084931875 + 0.20855925029630784 + 0.20856492989003017 + 0.20857060963049162 + 0.20857628951769658 + 0.20858196955165101 + 0.20858764973236038 + 0.2085933300598295 + 0.20859901053406432 + 0.2086046911550703 + 0.20861037192285231 + 0.2086160528374158 + 0.2086217338987667 + 0.20862741510691046 + 0.20863309646185088 + 0.20863877796359551 + 0.2086444596121482 + 0.20865014140751484 + 0.20865582334970098 + 0.20866150543871193 + 0.20866718767455317 + 0.20867287005722912 + 0.20867855258674664 + 0.20868423526311022 + 0.20868991808632531 + 0.20869560105639776 + 0.20870128417333203 + 0.20870696743713452 + 0.20871265084781018 + 0.20871833440536444 + 0.20872401810980268 + 0.20872970196113041 + 0.20873538595935248 + 0.20874107010447482 + 0.20874675439650239 + 0.20875243883544117 + 0.20875812342129599 + 0.20876380815407278 + 0.20876949303377651 + 0.20877517806041263 + 0.20878086323398651 + 0.20878654855450357 + 0.20879223402196931 + 0.20879791963638916 + 0.20880360539776846 + 0.20880929130611223 + 0.20881497736142635 + 0.20882066356371573 + 0.20882634991298635 + 0.20883203640924317 + 0.20883772305249149 + 0.20884340984273744 + 0.20884909677998525 + 0.20885478386424144 + 0.20886047109551101 + 0.20886615847379875 + 0.20887184599911068 + 0.20887753367145223 + 0.20888322149082891 + 0.20888890945724545 + 0.2088945975707075 + 0.20890028583122083 + 0.20890597423879045 + 0.2089116627934223 + 0.20891735149512078 + 0.20892304034389239 + 0.20892872933974149 + 0.20893441848267405 + 0.20894010777269603 + 0.2089457972098113 + 0.20895148679402692 + 0.20895717652534718 + 0.20896286640377754 + 0.20896855642932408 + 0.20897424660199157 + 0.20897993692178604 + 0.2089856273887119 + 0.20899131800277509 + 0.20899700876398156 + 0.20900269967233573 + 0.20900839072784358 + 0.20901408193051044 + 0.20901977328034194 + 0.20902546477734285 + 0.2090311564215187 + 0.20903684821287538 + 0.20904254015141835 + 0.2090482322371521 + 0.20905392447008297 + 0.20905961685021549 + 0.2090653093775561 + 0.20907100205210916 + 0.20907669487388067 + 0.20908238784287611 + 0.20908808095910034 + 0.20909377422255992 + 0.20909946763325868 + 0.20910516119120309 + 0.20911085489639816 + 0.20911654874884975 + 0.20912224274856231 + 0.20912793689554235 + 0.20913363118979431 + 0.20913932563132462 + 0.20914502022013767 + 0.20915071495623946 + 0.20915640983963546 + 0.20916210487033049 + 0.20916780004833016 + 0.20917349537364036 + 0.20917919084626602 + 0.20918488646621261 + 0.20919058223348602 + 0.2091962781480913 + 0.20920197421003334 + 0.20920767041931806 + 0.20921336677595095 + 0.20921906327993747 + 0.20922475993128251 + 0.20923045672999213 + 0.20923615367607165 + 0.20924185076952564 + 0.20924754801036047 + 0.20925324539858106 + 0.20925894293419295 + 0.20926464061720162 + 0.20927033844761242 + 0.20927603642543086 + 0.20928173455066237 + 0.20928743282331189 + 0.20929313124338547 + 0.20929882981088796 + 0.20930452852582529 + 0.20931022738820249 + 0.20931592639802502 + 0.20932162555529879 + 0.20932732486002831 + 0.20933302431221998 + 0.20933872391187827 + 0.2093444236590091 + 0.20935012355361801 + 0.20935582359571045 + 0.20936152378529074 + 0.20936722412236602 + 0.20937292460694068 + 0.20937862523902012 + 0.20938432601860985 + 0.20939002694571529 + 0.20939572802034248 + 0.20940142924249577 + 0.20940713061218122 + 0.20941283212940423 + 0.20941853379417028 + 0.20942423560648435 + 0.20942993756635184 + 0.20943563967377876 + 0.20944134192877056 + 0.20944704433133168 + 0.20945274688146867 + 0.20945844957918633 + 0.20946415242448974 + 0.20946985541738533 + 0.20947555855787811 + 0.20948126184597246 + 0.2094869652816754 + 0.20949266886499193 + 0.20949837259592635 + 0.20950407647448527 + 0.2095097805006742 + 0.20951548467449743 + 0.20952118899596156 + 0.209526893465071 + 0.20953259808183225 + 0.20953830284624969 + 0.2095440077583294 + 0.20954971281807686 + 0.2095554180254969 + 0.20956112338059557 + 0.2095668288833778 + 0.20957253453384908 + 0.20957824033201547 + 0.20958394627788127 + 0.20958965237145299 + 0.20959535861273573 + 0.20960106500173431 + 0.20960677153845481 + 0.20961247822290252 + 0.2096181850550832 + 0.20962389203500101 + 0.20962959916266311 + 0.20963530643807346 + 0.20964101386123843 + 0.20964672143216309 + 0.20965242915085289 + 0.20965813701731326 + 0.20966384503154972 + 0.2096695531935677 + 0.20967526150337215 + 0.20968096996096916 + 0.20968667856636414 + 0.20969238731956144 + 0.20969809622056776 + 0.20970380526938839 + 0.2097095144660279 + 0.20971522381049276 + 0.20972093330278738 + 0.20972664294291832 + 0.20973235273089 + 0.20973806266670839 + 0.20974377275037848 + 0.20974948298190624 + 0.20975519336129717 + 0.20976090388855573 + 0.20976661456368834 + 0.20977232538670015 + 0.2097780363575964 + 0.20978374747638281 + 0.20978945874306465 + 0.20979517015764756 + 0.20980088172013639 + 0.20980659343053715 + 0.20981230528885539 + 0.20981801729509605 + 0.20982372944926456 + 0.20982944175136697 + 0.20983515420140778 + 0.20984086679939329 + 0.20984657954532876 + 0.20985229243921891 + 0.20985800548107039 + 0.20986371867088766 + 0.20986943200867605 + 0.20987514549444231 + 0.20988085912819016 + 0.20988657290992624 + 0.20989228683965552 + 0.20989800091738342 + 0.20990371514311543 + 0.20990942951685704 + 0.20991514403861433 + 0.20992085870839117 + 0.20992657352619462 + 0.20993228849202911 + 0.20993800360590009 + 0.20994371886781363 + 0.20994943427777471 + 0.20995514983578925 + 0.20996086554186183 + 0.20996658139599886 + 0.20997229739820536 + 0.20997801354848625 + 0.2099837298468476 + 0.20998944629329491 + 0.2099951628878331 + 0.21000087963046823 + 0.21000659652120521 + 0.21001231356004957 + 0.21001803074700731 + 0.21002374808208343 + 0.21002946556528332 + 0.21003518319661207 + 0.21004090097607619 + 0.21004661890368012 + 0.21005233697942985 + 0.21005805520333035 + 0.21006377357538764 + 0.21006949209560674 + 0.2100752107639931 + 0.21008092958055272 + 0.21008664854529011 + 0.21009236765821171 + 0.21009808691932208 + 0.21010380632862771 + 0.21010952588613308 + 0.21011524559184361 + 0.21012096544576539 + 0.21012668544790342 + 0.21013240559826363 + 0.21013812589685107 + 0.21014384634367114 + 0.21014956693872944 + 0.21015528768203151 + 0.21016100857358269 + 0.21016672961338856 + 0.21017245080145411 + 0.21017817213778531 + 0.21018389362238721 + 0.2101896152552658 + 0.21019533703642554 + 0.21020105896587343 + 0.21020678104361354 + 0.21021250326965174 + 0.21021822564399367 + 0.21022394816664478 + 0.21022967083760996 + 0.21023539365689592 + 0.21024111662450648 + 0.21024683974044819 + 0.21025256300472658 + 0.21025828641734612 + 0.21026400997831332 + 0.21026973368763324 + 0.2102754575453108 + 0.21028118155135259 + 0.21028690570576294 + 0.210292630008548 + 0.21029835445971276 + 0.21030407905926324 + 0.21030980380720488 + 0.21031552870354225 + 0.21032125374828173 + 0.21032697894142846 + 0.21033270428298736 + 0.21033842977296499 + 0.21034415541136636 + 0.21034988119819592 + 0.21035560713346074 + 0.21036133321716527 + 0.2103670594493155 + 0.21037278582991656 + 0.21037851235897378 + 0.21038423903649284 + 0.21038996586247907 + 0.21039569283693813 + 0.21040141995987549 + 0.21040714723129664 + 0.21041287465120656 + 0.21041860221961128 + 0.21042432993651586 + 0.21043005780192625 + 0.2104357858158469 + 0.21044151397828451 + 0.21044724228924391 + 0.21045297074873071 + 0.21045869935675038 + 0.21046442811330793 + 0.2104701570184094 + 0.21047588607206025 + 0.21048161527426554 + 0.2104873446250313 + 0.21049307412436188 + 0.21049880377226407 + 0.21050453356874266 + 0.21051026351380328 + 0.21051599360745135 + 0.21052172384969198 + 0.2105274542405311 + 0.21053318477997435 + 0.21053891546802653 + 0.21054464630469391 + 0.21055037728998133 + 0.21055610842389433 + 0.21056183970643844 + 0.21056757113761923 + 0.21057330271744218 + 0.21057903444591275 + 0.21058476632303605 + 0.21059049834881802 + 0.21059623052326432 + 0.21060196284637972 + 0.21060769531816995 + 0.21061342793864096 + 0.21061916070779726 + 0.21062489362564485 + 0.21063062669218979 + 0.21063635990743662 + 0.21064209327139075 + 0.21064782678405883 + 0.21065356044544531 + 0.21065929425555568 + 0.21066502821439609 + 0.21067076232197146 + 0.2106764965782868 + 0.21068223098334865 + 0.21068796553716207 + 0.21069370023973252 + 0.21069943509106512 + 0.21070517009116579 + 0.2107109052400401 + 0.2107166405376926 + 0.21072237598412971 + 0.21072811157935709 + 0.21073384732337916 + 0.21073958321620204 + 0.21074531925783169 + 0.21075105544827261 + 0.21075679178753037 + 0.21076252827561143 + 0.21076826491252046 + 0.21077400169826288 + 0.21077973863284474 + 0.21078547571627054 + 0.21079121294854683 + 0.21079695032967863 + 0.21080268785967149 + 0.21080842553853044 + 0.21081416336626146 + 0.21081990134287013 + 0.21082563946836144 + 0.21083137774274149 + 0.21083711616601525 + 0.21084285473818823 + 0.21084859345926599 + 0.21085433232925407 + 0.21086007134815793 + 0.21086581051598324 + 0.21087154983273537 + 0.21087728929841951 + 0.21088302891304161 + 0.21088876867660669 + 0.21089450858912026 + 0.21090024865058793 + 0.21090598886101519 + 0.21091172922040807 + 0.21091746972877107 + 0.21092321038611034 + 0.2109289511924313 + 0.21093469214773902 + 0.21094043325203954 + 0.2109461745053379 + 0.21095191590763962 + 0.21095765745895079 + 0.21096339915927584 + 0.21096914100862141 + 0.21097488300699194 + 0.21098062515439356 + 0.21098636745083171 + 0.21099210989631151 + 0.21099785249083897 + 0.21100359523441914 + 0.21100933812705752 + 0.21101508116875972 + 0.21102082435953168 + 0.211026567699378 + 0.21103231118830471 + 0.21103805482631735 + 0.21104379861342093 + 0.2110495425496216 + 0.21105528663492476 + 0.21106103086933503 + 0.21106677525285888 + 0.21107251978550148 + 0.21107826446726824 + 0.21108400929816473 + 0.2110897542781961 + 0.21109549940736877 + 0.21110124468568731 + 0.21110699011315723 + 0.21111273568978417 + 0.21111848141557404 + 0.21112422729053257 + 0.21112997331466418 + 0.21113571948797488 + 0.21114146581047027 + 0.21114721228215594 + 0.21115295890303684 + 0.21115870567311909 + 0.21116445259240768 + 0.21117019966090869 + 0.2111759468786272 + 0.21118169424556812 + 0.2111874417617382 + 0.2111931894271423 + 0.21119893724178607 + 0.21120468520567454 + 0.21121043331881378 + 0.21121618158120931 + 0.21122192999286613 + 0.21122767855378988 + 0.21123342726398656 + 0.21123917612346069 + 0.21124492513221887 + 0.21125067429026564 + 0.21125642359760699 + 0.2112621730542486 + 0.2112679226601954 + 0.21127367241545353 + 0.21127942232002797 + 0.21128517237392433 + 0.2112909225771481 + 0.21129667292970536 + 0.21130242343160066 + 0.21130817408284014 + 0.21131392488342918 + 0.21131967583337347 + 0.2113254269326775 + 0.21133117818134833 + 0.21133692957939004 + 0.21134268112680915 + 0.21134843282361079 + 0.21135418466980044 + 0.21135993666538366 + 0.21136568881036552 + 0.21137144110475212 + 0.21137719354854895 + 0.21138294614176109 + 0.21138869888439454 + 0.21139445177645394 + 0.21140020481794586 + 0.21140595800887529 + 0.21141171134924736 + 0.21141746483906856 + 0.21142321847834342 + 0.21142897226707807 + 0.21143472620527759 + 0.21144048029294749 + 0.21144623453009387 + 0.21145198891672168 + 0.21145774345283713 + 0.21146349813844467 + 0.21146925297355043 + 0.21147500795815941 + 0.21148076309227767 + 0.21148651837591084 + 0.21149227380906396 + 0.21149802939174306 + 0.21150378512395271 + 0.21150954100569949 + 0.21151529703698851 + 0.21152105321782469 + 0.21152680954821423 + 0.21153256602816317 + 0.21153832265767547 + 0.21154407943675779 + 0.21154983636541574 + 0.21155559344365382 + 0.21156135067147852 + 0.21156710804889456 + 0.2115728655759084 + 0.21157862325252466 + 0.21158438107874933 + 0.21159013905458809 + 0.2115958971800459 + 0.21160165545512888 + 0.21160741387984161 + 0.21161317245419065 + 0.21161893117818098 + 0.21162469005181833 + 0.21163044907510811 + 0.21163620824805551 + 0.21164196757066656 + 0.21164772704294685 + 0.2116534866649008 + 0.21165924643653569 + 0.21166500635785551 + 0.21167076642886626 + 0.21167652664957362 + 0.21168228701998359 + 0.21168804754010082 + 0.21169380820993075 + 0.21169956902947953 + 0.2117053299987523 + 0.21171109111775555 + 0.21171685238649277 + 0.2117226138049712 + 0.21172837537319583 + 0.21173413709117231 + 0.21173989895890608 + 0.21174566097640227 + 0.21175142314366699 + 0.21175718546070532 + 0.21176294792752332 + 0.21176871054412549 + 0.21177447331051852 + 0.21178023622670741 + 0.21178599929269784 + 0.21179176250849469 + 0.21179752587410419 + 0.21180328938953191 + 0.21180905305478293 + 0.21181481686986275 + 0.21182058083477748 + 0.21182634494953231 + 0.21183210921413206 + 0.21183787362858364 + 0.21184363819289131 + 0.21184940290706139 + 0.21185516777109942 + 0.21186093278501034 + 0.21186669794879981 + 0.211872463262474 + 0.21187822872603787 + 0.21188399433949703 + 0.21188976010285659 + 0.2118955260161226 + 0.2119012920793007 + 0.21190705829239639 + 0.21191282465541475 + 0.21191859116836148 + 0.21192435783124258 + 0.21193012464406308 + 0.21193589160682819 + 0.21194165871954443 + 0.21194742598221686 + 0.21195319339485058 + 0.2119589609574512 + 0.21196472867002478 + 0.21197049653257638 + 0.21197626454511218 + 0.21198203270763716 + 0.21198780102015696 + 0.21199356948267667 + 0.21199933809520285 + 0.21200510685774013 + 0.21201087577029407 + 0.21201664483287069 + 0.21202241404547573 + 0.21202818340811366 + 0.21203395292079108 + 0.21203972258351311 + 0.21204549239628487 + 0.21205126235911234 + 0.21205703247200119 + 0.21206280273495706 + 0.21206857314798494 + 0.21207434371109044 + 0.21208011442427965 + 0.2120858852875572 + 0.21209165630092972 + 0.21209742746440169 + 0.21210319877797976 + 0.21210897024166805 + 0.21211474185547355 + 0.21212051361940049 + 0.21212628553345539 + 0.21213205759764384 + 0.21213782981197041 + 0.21214360217644176 + 0.21214937469106243 + 0.21215514735583857 + 0.21216092017077517 + 0.21216669313587849 + 0.21217246625115402 + 0.21217823951660625 + 0.21218401293224251 + 0.21218978649806625 + 0.21219556021408462 + 0.21220133408030264 + 0.21220710809672547 + 0.21221288226335974 + 0.21221865658020947 + 0.21222443104728125 + 0.21223020566458028 + 0.21223598043211259 + 0.21224175534988277 + 0.21224753041789746 + 0.21225330563616121 + 0.21225908100468016 + 0.21226485652345933 + 0.21227063219250494 + 0.21227640801182204 + 0.21228218398141674 + 0.21228796010129414 + 0.21229373637145929 + 0.21229951279191883 + 0.21230528936267737 + 0.21231106608374106 + 0.21231684295511538 + 0.21232261997680552 + 0.21232839714881707 + 0.21233417447115616 + 0.21233995194382729 + 0.21234572956683714 + 0.21235150734019032 + 0.21235728526389291 + 0.2123630633379506 + 0.21236884156236885 + 0.21237461993715237 + 0.21238039846230822 + 0.21238617713784055 + 0.21239195596375537 + 0.21239773494005842 + 0.21240351406675517 + 0.21240929334385136 + 0.21241507277135249 + 0.21242085234926378 + 0.21242663207759072 + 0.21243241195633894 + 0.21243819198551461 + 0.21244397216512276 + 0.21244975249516856 + 0.21245553297565867 + 0.21246131360659759 + 0.21246709438799147 + 0.21247287531984541 + 0.21247865640216504 + 0.21248443763495595 + 0.21249021901822426 + 0.21249600055197509 + 0.21250178223621413 + 0.21250756407094629 + 0.21251334605617786 + 0.21251912819191388 + 0.21252491047816049 + 0.21253069291492277 + 0.21253647550220689 + 0.21254225824001738 + 0.21254804112836037 + 0.21255382416724158 + 0.21255960735666654 + 0.21256539069664088 + 0.21257117418716917 + 0.21257695782825811 + 0.21258274161991322 + 0.21258852556213967 + 0.21259430965494261 + 0.21260009389832865 + 0.21260587829230226 + 0.2126116628368698 + 0.21261744753203618 + 0.21262323237780759 + 0.21262901737418918 + 0.21263480252118658 + 0.21264058781880582 + 0.21264637326705157 + 0.21265215886592997 + 0.21265794461544665 + 0.21266373051560716 + 0.21266951656641664 + 0.21267530276788077 + 0.21268108912000566 + 0.21268687562279584 + 0.21269266227625797 + 0.21269844908039676 + 0.21270423603521874 + 0.21271002314072854 + 0.2127158103969318 + 0.21272159780383462 + 0.21272738536144217 + 0.21273317306976061 + 0.21273896092879435 + 0.21274474893855028 + 0.21275053709903291 + 0.21275632541024833 + 0.21276211387220165 + 0.21276790248489913 + 0.21277369124834628 + 0.21277948016254766 + 0.21278526922751012 + 0.21279105844323859 + 0.21279684780973823 + 0.21280263732701574 + 0.21280842699507568 + 0.21281421681392376 + 0.21282000678356597 + 0.2128257969040081 + 0.21283158717525461 + 0.21283737759731228 + 0.21284316817018561 + 0.21284895889388075 + 0.21285474976840343 + 0.21286054079375871 + 0.21286633196995272 + 0.21287212329699062 + 0.21287791477487847 + 0.2128837064036215 + 0.21288949818322478 + 0.21289529011369443 + 0.21290108219503603 + 0.21290687442725542 + 0.2129126668103575 + 0.21291845934434855 + 0.21292425202923362 + 0.2129300448650184 + 0.21293583785170839 + 0.21294163098930946 + 0.21294742427782704 + 0.21295321771726633 + 0.21295901130763353 + 0.21296480504893364 + 0.2129705989411729 + 0.21297639298435644 + 0.21298218717848932 + 0.21298798152357826 + 0.21299377601962832 + 0.21299957066664474 + 0.21300536546463356 + 0.21301116041360046 + 0.21301695551355004 + 0.21302275076448896 + 0.21302854616642239 + 0.21303434171935595 + 0.21304013742329528 + 0.21304593327824597 + 0.21305172928421323 + 0.21305752544120313 + 0.21306332174922088 + 0.21306911820827207 + 0.21307491481836285 + 0.21308071157949784 + 0.21308650849168373 + 0.21309230555492512 + 0.21309810276922767 + 0.21310390013459804 + 0.2131096976510409 + 0.21311549531856119 + 0.21312129313716635 + 0.21312709110686032 + 0.21313288922764928 + 0.2131386874995389 + 0.21314448592253488 + 0.2131502844966422 + 0.21315608322186669 + 0.21316188209821435 + 0.2131676811256904 + 0.213173480304301 + 0.21317927963405076 + 0.21318507911494522 + 0.21319087874699127 + 0.21319667853019392 + 0.21320247846455767 + 0.21320827855008948 + 0.21321407878679477 + 0.21321987917467822 + 0.21322567971374601 + 0.21323148040400378 + 0.21323728124545716 + 0.21324308223811134 + 0.21324888338197245 + 0.21325468467704617 + 0.21326048612333709 + 0.2132662877208519 + 0.21327208946959572 + 0.2132778913695737 + 0.21328369342079251 + 0.2132894956232568 + 0.21329529797697222 + 0.21330110048194487 + 0.21330690313817999 + 0.21331270594568319 + 0.21331850890446008 + 0.21332431201451643 + 0.2133301152758578 + 0.21333591868848983 + 0.21334172225241768 + 0.21334752596764711 + 0.21335332983418412 + 0.21335913385203395 + 0.21336493802120227 + 0.21337074234169418 + 0.21337654681351634 + 0.21338235143667345 + 0.21338815621117163 + 0.213393961137016 + 0.21339976621421233 + 0.2134055714427667 + 0.21341137682268427 + 0.21341718235397017 + 0.21342298803663107 + 0.21342879387067171 + 0.21343459985609758 + 0.21344040599291503 + 0.21344621228112967 + 0.21345201872074604 + 0.21345782531177038 + 0.2134636320542089 + 0.21346943894806611 + 0.21347524599334833 + 0.21348105319006064 + 0.21348686053820926 + 0.21349266803779926 + 0.21349847568883687 + 0.21350428349132669 + 0.21351009144527497 + 0.21351589955068728 + 0.21352170780756932 + 0.21352751621592628 + 0.21353332477576484 + 0.21353913348708853 + 0.21354494234990523 + 0.21355075136421886 + 0.21355656053003574 + 0.21356236984736204 + 0.21356817931620181 + 0.21357398893656179 + 0.2135797987084477 + 0.2135856086318646 + 0.21359141870681878 + 0.21359722893331479 + 0.21360303931135874 + 0.21360884984095646 + 0.21361466052211356 + 0.2136204713548352 + 0.21362628233912753 + 0.2136320934749957 + 0.21363790476244549 + 0.21364371620148237 + 0.21364952779211269 + 0.21365533953434054 + 0.21366115142817313 + 0.21366696347361505 + 0.21367277567067255 + 0.21367858801935075 + 0.21368440051965534 + 0.21369021317159198 + 0.2136960259751664 + 0.21370183893038416 + 0.21370765203725051 + 0.21371346529577218 + 0.2137192787059532 + 0.21372509226780029 + 0.21373090598131864 + 0.21373671984651396 + 0.2137425338633919 + 0.21374834803195758 + 0.2137541623522177 + 0.2137599768241765 + 0.21376579144784108 + 0.21377160622321617 + 0.21377742115030682 + 0.21378323622911988 + 0.2137890514596604 + 0.21379486684193363 + 0.21380068237594566 + 0.21380649806170227 + 0.21381231389920857 + 0.21381812988847027 + 0.21382394602949295 + 0.21382976232228298 + 0.21383557876684489 + 0.21384139536318489 + 0.21384721211130864 + 0.2138530290112213 + 0.21385884606292915 + 0.21386466326643677 + 0.21387048062175096 + 0.21387629812887671 + 0.21388211578781985 + 0.21388793359858607 + 0.21389375156118043 + 0.21389956967560869 + 0.213905387941877 + 0.21391120635999111 + 0.2139170249299556 + 0.21392284365177672 + 0.21392866252546014 + 0.21393448155101152 + 0.21394030072843664 + 0.21394612005774055 + 0.21395193953892902 + 0.21395775917200816 + 0.2139635789569827 + 0.21396939889385877 + 0.21397521898264274 + 0.21398103922333903 + 0.21398685961595348 + 0.21399268016049283 + 0.21399850085696115 + 0.21400432170536457 + 0.21401014270570945 + 0.2140159638580004 + 0.2140217851622441 + 0.21402760661844525 + 0.21403342822660948 + 0.21403924998674304 + 0.21404507189885114 + 0.21405089396293991 + 0.21405671617901403 + 0.21406253854707974 + 0.21406836106714272 + 0.21407418373920864 + 0.21408000656328263 + 0.2140858295393705 + 0.2140916526674784 + 0.21409747594761153 + 0.21410329937977551 + 0.21410912296397611 + 0.21411494670021844 + 0.21412077058850931 + 0.21412659462885281 + 0.21413241882125572 + 0.21413824316572308 + 0.21414406766226129 + 0.21414989231087483 + 0.21415571711157008 + 0.21416154206435262 + 0.21416736716922768 + 0.21417319242620148 + 0.21417901783527915 + 0.21418484339646643 + 0.214190669109769 + 0.21419649497519255 + 0.21420232099274283 + 0.21420814716242551 + 0.21421397348424573 + 0.21421979995820972 + 0.21422562658432273 + 0.21423145336258981 + 0.21423728029301783 + 0.21424310737561195 + 0.21424893461037781 + 0.21425476199732063 + 0.21426058953644661 + 0.21426641722776094 + 0.21427224507126938 + 0.21427807306697749 + 0.21428390121489166 + 0.2142897295150164 + 0.21429555796735805 + 0.21430138657192174 + 0.21430721532871425 + 0.21431304423773967 + 0.21431887329900426 + 0.21432470251251423 + 0.21433053187827431 + 0.21433636139629056 + 0.21434219106656888 + 0.21434802088911434 + 0.21435385086393319 + 0.21435968099103056 + 0.21436551127041231 + 0.21437134170208455 + 0.21437717228605196 + 0.21438300302232022 + 0.21438883391089616 + 0.21439466495178394 + 0.21440049614499068 + 0.21440632749052066 + 0.21441215898838059 + 0.21441799063857508 + 0.21442382244111099 + 0.21442965439599299 + 0.21443548650322664 + 0.2144413187628183 + 0.21444715117477317 + 0.21445298373909741 + 0.21445881645579568 + 0.21446464932487427 + 0.2144704823463395 + 0.2144763155201953 + 0.21448214884644906 + 0.21448798232510502 + 0.21449381595616976 + 0.21449964973964858 + 0.21450548367554717 + 0.21451131776387122 + 0.21451715200462598 + 0.21452298639781769 + 0.21452882094345146 + 0.21453465564153357 + 0.2145404904920698 + 0.21454632549506417 + 0.21455216065052407 + 0.21455799595845459 + 0.2145638314188611 + 0.21456966703174965 + 0.21457550279712606 + 0.21458133871499502 + 0.21458717478536321 + 0.2145930110082353 + 0.21459884738361817 + 0.21460468391151646 + 0.2146105205919363 + 0.21461635742488294 + 0.2146221944103622 + 0.21462803154838017 + 0.21463386883894223 + 0.21463970628205392 + 0.21464554387772047 + 0.21465138162594824 + 0.21465721952674288 + 0.21466305758010953 + 0.21466889578605394 + 0.21467473414458246 + 0.21468057265569965 + 0.2146864113194118 + 0.21469225013572463 + 0.21469808910464389 + 0.21470392822617473 + 0.21470976750032295 + 0.21471560692709465 + 0.21472144650649466 + 0.21472728623852969 + 0.21473312612320436 + 0.21473896616052504 + 0.21474480635049692 + 0.21475064669312613 + 0.21475648718841797 + 0.21476232783637811 + 0.2147681686370124 + 0.21477400959032641 + 0.21477985069632594 + 0.21478569195501623 + 0.21479153336640347 + 0.21479737493049286 + 0.21480321664729013 + 0.21480905851680107 + 0.21481490053903146 + 0.21482074271398685 + 0.21482658504167307 + 0.21483242752209478 + 0.21483827015525941 + 0.21484411294117139 + 0.21484995587983616 + 0.21485579897126039 + 0.21486164221544879 + 0.21486748561240759 + 0.21487332916214252 + 0.21487917286465885 + 0.2148850167199628 + 0.21489086072805905 + 0.21489670488895438 + 0.21490254920265348 + 0.21490839366916312 + 0.21491423828848746 + 0.21492008306063329 + 0.21492592798560642 + 0.21493177306341193 + 0.21493761829405567 + 0.2149434636775433 + 0.21494930921388003 + 0.21495515490307224 + 0.21496100074512547 + 0.21496684674004557 + 0.2149726928878373 + 0.21497853918850679 + 0.21498438564206038 + 0.21499023224850267 + 0.21499607900784004 + 0.21500192592007819 + 0.21500777298522231 + 0.21501362020327813 + 0.21501946757425192 + 0.21502531509814896 + 0.21503116277497442 + 0.21503701060473449 + 0.21504285858743508 + 0.21504870672308121 + 0.2150545550116793 + 0.21506040345323454 + 0.21506625204775259 + 0.21507210079523922 + 0.21507794969570027 + 0.21508379874914091 + 0.21508964795556731 + 0.21509549731498481 + 0.21510134682739959 + 0.21510719649281645 + 0.21511304631124206 + 0.21511889628268119 + 0.21512474640714066 + 0.21513059668462514 + 0.2151364471151398 + 0.21514229769869198 + 0.21514814843528643 + 0.21515399932492832 + 0.21515985036762444 + 0.21516570156337958 + 0.21517155291219989 + 0.21517740441409117 + 0.21518325606905814 + 0.2151891078771081 + 0.21519495983824471 + 0.21520081195247526 + 0.21520666421980506 + 0.21521251664023974 + 0.21521836921378404 + 0.21522422194044535 + 0.21523007482022774 + 0.21523592785313811 + 0.21524178103918112 + 0.21524763437836358 + 0.21525348787069021 + 0.21525934151616666 + 0.21526519531479987 + 0.21527104926659393 + 0.21527690337155514 + 0.21528275762968976 + 0.21528861204100255 + 0.21529446660549972 + 0.21530032132318713 + 0.21530617619406986 + 0.21531203121815376 + 0.21531788639544508 + 0.21532374172594854 + 0.21532959720967096 + 0.21533545284661698 + 0.21534130863679296 + 0.21534716458020411 + 0.21535302067685663 + 0.2153588769267554 + 0.21536473332990758 + 0.21537058988631738 + 0.2153764465959907 + 0.21538230345893364 + 0.21538816047515211 + 0.21539401764465119 + 0.21539987496743676 + 0.21540573244351505 + 0.21541159007289079 + 0.21541744785557082 + 0.21542330579155927 + 0.21542916388086347 + 0.21543502212348814 + 0.21544088051943913 + 0.21544673906872203 + 0.21545259777134279 + 0.21545845662730756 + 0.21546431563662055 + 0.21547017479928862 + 0.21547603411531754 + 0.21548189358471251 + 0.21548775320747923 + 0.21549361298362357 + 0.21549947291315125 + 0.21550533299606811 + 0.21551119323237922 + 0.21551705362209106 + 0.21552291416520869 + 0.21552877486173797 + 0.2155346357116853 + 0.21554049671505512 + 0.215546357871854 + 0.21555221918208703 + 0.21555808064576051 + 0.21556394226288028 + 0.21556980403345097 + 0.2155756659574789 + 0.21558152803497038 + 0.2155873902659301 + 0.21559325265036447 + 0.2155991151882786 + 0.21560497787967872 + 0.21561084072457032 + 0.21561670372295896 + 0.21562256687484999 + 0.21562843018025016 + 0.2156342936391642 + 0.21564015725159849 + 0.2156460210175582 + 0.21565188493704962 + 0.2156577490100775 + 0.21566361323664815 + 0.21566947761676725 + 0.21567534215044074 + 0.21568120683767425 + 0.21568707167847256 + 0.21569293667284248 + 0.21569880182078929 + 0.21570466712231925 + 0.21571053257743655 + 0.21571639818614863 + 0.21572226394846006 + 0.21572812986437676 + 0.21573399593390491 + 0.21573986215704991 + 0.21574572853381688 + 0.21575159506421271 + 0.21575746174824206 + 0.21576332858591132 + 0.21576919557722568 + 0.21577506272219096 + 0.21578093002081347 + 0.2157867974730984 + 0.21579266507905101 + 0.21579853283867767 + 0.21580440075198412 + 0.21581026881897508 + 0.21581613703965788 + 0.21582200541403679 + 0.21582787394211864 + 0.21583374262390814 + 0.21583961145941152 + 0.21584548044863466 + 0.21585134959158231 + 0.21585721888826118 + 0.21586308833867721 + 0.21586895794283495 + 0.21587482770074087 + 0.21588069761240064 + 0.21588656767782011 + 0.21589243789700455 + 0.21589830826995912 + 0.2159041787966913 + 0.21591004947720521 + 0.21591592031150716 + 0.21592179129960304 + 0.21592766244149855 + 0.21593353373719842 + 0.21593940518670954 + 0.21594527679003764 + 0.2159511485471875 + 0.21595702045816537 + 0.21596289252297707 + 0.21596876474162791 + 0.21597463711412415 + 0.21598050964047102 + 0.21598638232067438 + 0.21599225515473999 + 0.21599812814267424 + 0.21600400128448119 + 0.21600987458016774 + 0.21601574802973972 + 0.21602162163320238 + 0.21602749539056207 + 0.21603336930182293 + 0.2160392433669929 + 0.21604511758607559 + 0.21605099195907851 + 0.21605686648600628 + 0.21606274116686422 + 0.21606861600165914 + 0.21607449099039691 + 0.21608036613308221 + 0.21608624142972077 + 0.21609211688031907 + 0.21609799248488276 + 0.21610386824341712 + 0.21610974415592807 + 0.21611562022242131 + 0.2161214964429026 + 0.21612737281737723 + 0.21613324934585215 + 0.21613912602833149 + 0.21614500286482208 + 0.21615087985532924 + 0.21615675699985876 + 0.21616263429841587 + 0.21616851175100743 + 0.21617438935763822 + 0.21618026711831406 + 0.2161861450330412 + 0.21619202310182492 + 0.21619790132467054 + 0.21620377970158491 + 0.21620965823257279 + 0.21621553691764042 + 0.21622141575679313 + 0.21622729475003671 + 0.21623317389737759 + 0.21623905319882028 + 0.21624493265437136 + 0.2162508122640365 + 0.2162566920278215 + 0.21626257194573167 + 0.21626845201777228 + 0.21627433224395076 + 0.21628021262427119 + 0.21628609315873953 + 0.21629197384736257 + 0.21629785469014501 + 0.21630373568709274 + 0.21630961683821212 + 0.21631549814350826 + 0.21632137960298664 + 0.21632726121665399 + 0.21633314298451509 + 0.21633902490657572 + 0.21634490698284228 + 0.21635078921332002 + 0.21635667159801475 + 0.21636255413693226 + 0.21636843683007836 + 0.21637431967745838 + 0.21638020267907854 + 0.21638608583494429 + 0.21639196914506179 + 0.21639785260943586 + 0.21640373622807293 + 0.21640962000097869 + 0.216415503928159 + 0.21642138800961919 + 0.2164272722453649 + 0.21643315663540263 + 0.21643904117973767 + 0.21644492587837522 + 0.21645081073132164 + 0.2164566957385827 + 0.21646258090016385 + 0.21646846621607069 + 0.21647435168630971 + 0.21648023731088617 + 0.21648612308980528 + 0.21649200902307345 + 0.2164978951106965 + 0.21650378135267967 + 0.21650966774902883 + 0.2165155542997497 + 0.21652144100484877 + 0.21652732786433065 + 0.21653321487820182 + 0.21653910204646798 + 0.21654498936913388 + 0.21655087684620652 + 0.21655676447769112 + 0.21656265226359406 + 0.21656854020391947 + 0.21657442829867482 + 0.21658031654786494 + 0.21658620495149555 + 0.21659209350957304 + 0.21659798222210216 + 0.21660387108908977 + 0.21660976011054059 + 0.21661564928646115 + 0.21662153861685654 + 0.21662742810173322 + 0.21663331774109645 + 0.21663920753495206 + 0.21664509748330588 + 0.21665098758616316 + 0.21665687784353024 + 0.21666276825541306 + 0.21666865882181627 + 0.21667454954274681 + 0.21668044041820991 + 0.21668633144821151 + 0.21669222263275731 + 0.21669811397185271 + 0.21670400546550339 + 0.21670989711371588 + 0.21671578891649537 + 0.21672168087384766 + 0.21672757298577816 + 0.21673346525229367 + 0.21673935767339844 + 0.21674525024909938 + 0.21675114297940229 + 0.21675703586431189 + 0.21676292890383464 + 0.21676882209797685 + 0.21677471544674282 + 0.21678060895013984 + 0.21678650260817228 + 0.21679239642084688 + 0.21679829038816906 + 0.2168041845101441 + 0.21681007878677891 + 0.21681597321807825 + 0.2168218678040478 + 0.21682776254469419 + 0.21683365744002253 + 0.2168395524900387 + 0.21684544769474853 + 0.21685134305415729 + 0.21685723856827147 + 0.21686313423709622 + 0.21686903006063796 + 0.21687492603890202 + 0.21688082217189369 + 0.21688671845961982 + 0.21689261490208528 + 0.21689851149929631 + 0.21690440825125834 + 0.2169103051579771 + 0.21691620221945848 + 0.21692209943570889 + 0.21692799680673247 + 0.21693389433253668 + 0.21693979201312641 + 0.21694568984850732 + 0.21695158783868582 + 0.21695748598366682 + 0.2169633842834571 + 0.21696928273806143 + 0.21697518134748625 + 0.21698108011173681 + 0.21698697903081895 + 0.21699287810473913 + 0.21699877733350198 + 0.21700467671711401 + 0.21701057625558093 + 0.21701647594890874 + 0.21702237579710262 + 0.2170282758001684 + 0.217034175958112 + 0.21704007627093927 + 0.217045976738656 + 0.21705187736126746 + 0.21705777813878019 + 0.21706367907119933 + 0.21706958015853134 + 0.2170754814007809 + 0.21708138279795455 + 0.21708728435005803 + 0.21709318605709718 + 0.21709908791907737 + 0.21710498993600436 + 0.21711089210788406 + 0.2171167944347229 + 0.21712269691652555 + 0.21712859955329844 + 0.21713450234504686 + 0.21714040529177719 + 0.2171463083934948 + 0.21715221165020554 + 0.21715811506191518 + 0.21716401862862902 + 0.21716992235035412 + 0.21717582622709461 + 0.21718173025885737 + 0.21718763444564784 + 0.21719353878747238 + 0.21719944328433566 + 0.21720534793624421 + 0.21721125274320324 + 0.21721715770521921 + 0.21722306282229736 + 0.21722896809444356 + 0.21723487352166376 + 0.21724077910396369 + 0.21724668484134868 + 0.21725259073382525 + 0.21725849678139852 + 0.21726440298407504 + 0.21727030934186009 + 0.2172762158547589 + 0.21728212252277854 + 0.21728802934592317 + 0.21729393632419966 + 0.21729984345761399 + 0.21730575074617087 + 0.21731165818987724 + 0.21731756578873843 + 0.2173234735427598 + 0.21732938145194763 + 0.21733528951630737 + 0.21734119773584479 + 0.21734710611056635 + 0.21735301464047674 + 0.21735892332558246 + 0.21736483216588934 + 0.21737074116140265 + 0.21737665031212827 + 0.21738255961807262 + 0.21738846907924053 + 0.21739437869563885 + 0.21740028846727241 + 0.2174061983941476 + 0.21741210847626971 + 0.21741801871364469 + 0.21742392910627881 + 0.21742983965417698 + 0.21743575035734611 + 0.21744166121579095 + 0.21744757222951736 + 0.21745348339853174 + 0.21745939472283948 + 0.21746530620244583 + 0.21747121783735779 + 0.2174771296275807 + 0.21748304157311979 + 0.21748895367398099 + 0.21749486593017073 + 0.21750077834169426 + 0.21750669090855759 + 0.21751260363076641 + 0.21751851650832607 + 0.2175244295412426 + 0.21753034272952224 + 0.21753625607317092 + 0.21754216957219349 + 0.21754808322659622 + 0.21755399703638567 + 0.21755991100156596 + 0.21756582512214415 + 0.21757173939812541 + 0.21757765382951633 + 0.21758356841632165 + 0.21758948315854768 + 0.2175953980562004 + 0.21760131310928565 + 0.21760722831780879 + 0.21761314368177509 + 0.21761905920119151 + 0.21762497487606344 + 0.21763089070639671 + 0.21763680669219673 + 0.21764272283346975 + 0.21764863913022073 + 0.21765455558245703 + 0.21766047219018306 + 0.21766638895340507 + 0.21767230587212844 + 0.21767822294635969 + 0.21768414017610405 + 0.21769005756136792 + 0.21769597510215671 + 0.21770189279847574 + 0.21770781065033146 + 0.21771372865772962 + 0.21771964682067624 + 0.21772556513917601 + 0.21773148361323599 + 0.21773740224286087 + 0.21774332102805768 + 0.21774923996883117 + 0.21775515906518778 + 0.21776107831713293 + 0.2177669977246724 + 0.21777291728781206 + 0.21777883700655787 + 0.21778475688091561 + 0.2177906769108913 + 0.21779659709649016 + 0.21780251743771814 + 0.21780843793458105 + 0.21781435858708481 + 0.21782027939523535 + 0.21782620035903852 + 0.21783212147849965 + 0.21783804275362512 + 0.21784396418441981 + 0.21784988577089121 + 0.21785580751304301 + 0.21786172941088217 + 0.21786765146441467 + 0.21787357367364626 + 0.21787949603858184 + 0.21788541855922836 + 0.21789134123559109 + 0.21789726406767546 + 0.21790318705548792 + 0.21790911019903372 + 0.21791503349831939 + 0.21792095695335068 + 0.21792688056413254 + 0.21793280433067133 + 0.21793872825297242 + 0.21794465233104224 + 0.21795057656488664 + 0.21795650095451102 + 0.2179624254999212 + 0.21796835020112315 + 0.21797427505812222 + 0.21798020007092478 + 0.2179861252395367 + 0.21799205056396345 + 0.21799797604421081 + 0.21800390168028472 + 0.21800982747219105 + 0.2180157534199357 + 0.21802167952352405 + 0.21802760578296251 + 0.21803353219825639 + 0.21803945876941164 + 0.21804538549643365 + 0.21805131237932932 + 0.21805723941810351 + 0.21806316661276207 + 0.21806909396331145 + 0.21807502146975699 + 0.21808094913210468 + 0.2180868769503603 + 0.21809280492452923 + 0.21809873305461794 + 0.21810466134063181 + 0.21811058978257672 + 0.21811651838045903 + 0.21812244713428361 + 0.21812837604405699 + 0.21813430510978435 + 0.21814023433147228 + 0.21814616370912601 + 0.21815209324275209 + 0.21815802293235531 + 0.21816395277794209 + 0.21816988277951782 + 0.21817581293708888 + 0.21818174325066073 + 0.21818767372023973 + 0.21819360434583066 + 0.21819953512744061 + 0.21820546606507379 + 0.21821139715873775 + 0.21821732840843733 + 0.21822325981417842 + 0.21822919137596691 + 0.21823512309380866 + 0.21824105496770912 + 0.21824698699767528 + 0.21825291918371187 + 0.21825885152582425 + 0.21826478402402008 + 0.21827071667830303 + 0.21827664948868056 + 0.21828258245515808 + 0.21828851557774104 + 0.21829444885643526 + 0.21830038229124665 + 0.21830631588218113 + 0.21831224962924464 + 0.21831818353244306 + 0.21832411759178222 + 0.21833005180726706 + 0.21833598617890457 + 0.21834192070670003 + 0.21834785539065943 + 0.21835379023078863 + 0.21835972522709302 + 0.218365660379579 + 0.21837159568825198 + 0.21837753115311798 + 0.21838346677418272 + 0.21838940255145167 + 0.21839533848493184 + 0.21840127457462802 + 0.21840721082054612 + 0.21841314722269209 + 0.21841908378107233 + 0.21842502049569176 + 0.21843095736655674 + 0.21843689439367267 + 0.218442831577046 + 0.21844876891668211 + 0.21845470641258691 + 0.21846064406476581 + 0.21846658187322582 + 0.21847251983797172 + 0.21847845795900994 + 0.21848439623634594 + 0.21849033466998555 + 0.21849627325993415 + 0.21850221200619885 + 0.21850815090878492 + 0.21851408996769731 + 0.21852002918294283 + 0.21852596855452755 + 0.21853190808245623 + 0.2185378477667354 + 0.21854378760737042 + 0.21854972760436822 + 0.21855566775773316 + 0.2185616080674723 + 0.21856754853359089 + 0.21857348915609437 + 0.21857942993498916 + 0.21858537087028129 + 0.21859131196197656 + 0.21859725321007992 + 0.21860319461459832 + 0.21860913617553654 + 0.21861507789290111 + 0.21862101976669795 + 0.21862696179693303 + 0.2186329039836111 + 0.21863884632673916 + 0.21864478882632271 + 0.21865073148236702 + 0.21865667429487859 + 0.21866261726386288 + 0.21866856038932619 + 0.21867450367127403 + 0.21868044710971238 + 0.21868639070464702 + 0.21869233445608388 + 0.2186982783640285 + 0.21870422242848669 + 0.21871016664946491 + 0.21871611102696861 + 0.21872205556100313 + 0.21872800025157496 + 0.21873394509868999 + 0.21873989010235426 + 0.21874583526257244 + 0.21875178057935174 + 0.21875772605269686 + 0.21876367168261432 + 0.21876961746911003 + 0.2187755634121894 + 0.21878150951185896 + 0.218787455768124 + 0.21879340218098994 + 0.21879934875046386 + 0.21880529547655048 + 0.21881124235925639 + 0.21881718939858641 + 0.21882313659454755 + 0.21882908394714523 + 0.21883503145638528 + 0.21884097912227374 + 0.21884692694481597 + 0.21885287492401789 + 0.21885882305988597 + 0.21886477135242566 + 0.21887071980164235 + 0.21887666840754244 + 0.21888261717013194 + 0.21888856608941618 + 0.21889451516540118 + 0.2189004643980933 + 0.21890641378749751 + 0.21891236333362024 + 0.21891831303646747 + 0.21892426289604455 + 0.2189302129123579 + 0.2189361630854125 + 0.21894211341521477 + 0.21894806390177124 + 0.21895401454508612 + 0.2189599653451671 + 0.21896591630201842 + 0.21897186741564706 + 0.21897781868605801 + 0.21898377011325817 + 0.2189897216972525 + 0.21899567343804738 + 0.21900162533564829 + 0.2190075773900611 + 0.21901352960129181 + 0.21901948196934637 + 0.21902543449423018 + 0.21903138717594969 + 0.21903734001451086 + 0.21904329300991857 + 0.21904924616217983 + 0.21905519947129953 + 0.21906115293728462 + 0.21906710656013947 + 0.21907306033987173 + 0.21907901427648552 + 0.21908496836998811 + 0.21909092262038415 + 0.2190968770276803 + 0.21910283159188243 + 0.21910878631299593 + 0.2191147411910267 + 0.21912069622598138 + 0.21912665141786478 + 0.21913260676668328 + 0.21913856227244297 + 0.21914451793514914 + 0.21915047375480839 + 0.21915642973142552 + 0.21916238586500761 + 0.21916834215555947 + 0.21917429860308765 + 0.21918025520759751 + 0.21918621196909555 + 0.21919216888758722 + 0.21919812596307783 + 0.21920408319557461 + 0.21921004058508223 + 0.2192159981316073 + 0.21922195583515516 + 0.2192279136957318 + 0.21923387171334319 + 0.21923982988799531 + 0.21924578821969404 + 0.21925174670844486 + 0.21925770535425415 + 0.21926366415712747 + 0.21926962311707016 + 0.21927558223408924 + 0.21928154150818965 + 0.21928750093937782 + 0.21929346052765977 + 0.21929942027304036 + 0.21930538017552653 + 0.2193113402351233 + 0.21931730045183709 + 0.21932326082567391 + 0.2193292213566391 + 0.21933518204473873 + 0.21934114288997916 + 0.21934710389236536 + 0.21935306505190383 + 0.21935902636859991 + 0.21936498784246022 + 0.21937094947349015 + 0.21937691126169614 + 0.21938287320708308 + 0.21938883530965747 + 0.21939479756942484 + 0.21940075998639152 + 0.21940672256056309 + 0.21941268529194599 + 0.21941864818054505 + 0.21942461122636683 + 0.21943057442941732 + 0.21943653778970185 + 0.21944250130722648 + 0.21944846498199772 + 0.21945442881402033 + 0.21946039280330093 + 0.21946635694984545 + 0.2194723212536599 + 0.21947828571474909 + 0.21948425033312008 + 0.21949021510877834 + 0.21949618004172927 + 0.21950214513197941 + 0.21950811037953466 + 0.21951407578440052 + 0.21952004134658287 + 0.2195260070660878 + 0.21953197294292112 + 0.21953793897708901 + 0.21954390516859618 + 0.21954987151745026 + 0.21955583802365561 + 0.21956180468721931 + 0.21956777150814624 + 0.21957373848644293 + 0.21957970562211535 + 0.21958567291516887 + 0.21959164036560944 + 0.21959760797344313 + 0.21960357573867587 + 0.21960954366131305 + 0.21961551174136132 + 0.21962147997882653 + 0.21962744837371406 + 0.21963341692602953 + 0.21963938563577981 + 0.2196453545029699 + 0.21965132352760577 + 0.21965729270969447 + 0.21966326204924033 + 0.21966923154624984 + 0.21967520120072906 + 0.21968117101268389 + 0.21968714098211978 + 0.21969311110904333 + 0.21969908139345984 + 0.21970505183537542 + 0.21971102243479593 + 0.21971699319172688 + 0.21972296410617534 + 0.2197289351781456 + 0.21973490640764476 + 0.2197408777946783 + 0.21974684933925162 + 0.21975282104137173 + 0.21975879290104303 + 0.21976476491827265 + 0.21977073709306644 + 0.21977670942542996 + 0.21978268191536857 + 0.21978865456288887 + 0.21979462736799676 + 0.21980060033069776 + 0.21980657345099774 + 0.21981254672890335 + 0.21981852016441941 + 0.21982449375755245 + 0.21983046750830795 + 0.21983644141669245 + 0.21984241548271133 + 0.21984838970637122 + 0.21985436408767689 + 0.21986033862663493 + 0.21986631332325074 + 0.21987228817753099 + 0.21987826318948098 + 0.2198842383591067 + 0.2198902136864142 + 0.21989618917140952 + 0.21990216481409791 + 0.2199081406144861 + 0.21991411657257945 + 0.21992009268838394 + 0.21992606896190567 + 0.21993204539314987 + 0.21993802198212326 + 0.21994399872883177 + 0.21994997563328084 + 0.21995595269547646 + 0.2199619299154246 + 0.2199679072931307 + 0.21997388482860139 + 0.2199798625218426 + 0.21998584037285981 + 0.21999181838165838 + 0.21999779654824544 + 0.22000377487262651 + 0.22000975335480694 + 0.22001573199479277 + 0.2200217107925905 + 0.22002768974820514 + 0.22003366886164361 + 0.22003964813291094 + 0.22004562756201368 + 0.22005160714895777 + 0.2200575868937481 + 0.2200635667963918 + 0.22006954685689373 + 0.22007552707526049 + 0.22008150745149807 + 0.2200874879856119 + 0.22009346867760846 + 0.22009944952749333 + 0.2201054305352719 + 0.22011141170095072 + 0.2201173930245352 + 0.22012337450603253 + 0.22012935614544699 + 0.22013533794278514 + 0.22014131989805305 + 0.22014730201125662 + 0.22015328428240188 + 0.2201592667114943 + 0.22016524929853992 + 0.22017123204354466 + 0.2201772149465146 + 0.22018319800745564 + 0.22018918122637338 + 0.22019516460327426 + 0.22020114813816383 + 0.22020713183104793 + 0.22021311568193275 + 0.22021909969082368 + 0.22022508385772718 + 0.22023106818264943 + 0.22023705266559518 + 0.2202430373065716 + 0.22024902210558367 + 0.22025500706263834 + 0.22026099217774067 + 0.22026697745089602 + 0.22027296288211204 + 0.22027894847139315 + 0.22028493421874645 + 0.22029092012417631 + 0.22029690618769027 + 0.2203028924092934 + 0.22030887878899161 + 0.22031486532679095 + 0.22032085202269747 + 0.2203268388767165 + 0.22033282588885475 + 0.22033881305911812 + 0.22034480038751156 + 0.22035078787404222 + 0.22035677551871499 + 0.2203627633215364 + 0.22036875128251249 + 0.22037473940164864 + 0.22038072767895103 + 0.22038671611442562 + 0.22039270470807834 + 0.22039869345991464 + 0.22040468236994182 + 0.22041067143816401 + 0.22041666066458848 + 0.22042265004922018 + 0.22042863959206604 + 0.22043462929313062 + 0.22044061915242141 + 0.22044660916994349 + 0.22045259934570277 + 0.22045858967970536 + 0.22046458017195664 + 0.22047057082246316 + 0.22047656163123103 + 0.22048255259826569 + 0.22048854372357313 + 0.2204945350071599 + 0.22050052644903048 + 0.22050651804919236 + 0.22051250980765064 + 0.22051850172441126 + 0.2205244937994808 + 0.22053048603286413 + 0.22053647842456789 + 0.22054247097459809 + 0.22054846368296013 + 0.22055445654966016 + 0.22056044957470469 + 0.22056644275809859 + 0.2205724360998485 + 0.22057842959996041 + 0.22058442325843983 + 0.22059041707529281 + 0.22059641105052527 + 0.22060240518414381 + 0.22060839947615346 + 0.22061439392656063 + 0.22062038853537094 + 0.22062638330259038 + 0.22063237822822493 + 0.22063837331228064 + 0.22064436855476358 + 0.22065036395567969 + 0.22065635951503398 + 0.22066235523283406 + 0.22066835110908437 + 0.22067434714379092 + 0.22068034333696082 + 0.22068633968859896 + 0.22069233619871201 + 0.22069833286730489 + 0.22070432969438464 + 0.22071032667995685 + 0.22071632382402692 + 0.22072232112660142 + 0.22072831858768535 + 0.22073431620728634 + 0.22074031398540886 + 0.22074631192205935 + 0.22075231001724394 + 0.2207583082709681 + 0.22076430668323779 + 0.22077030525405977 + 0.22077630398343875 + 0.22078230287138201 + 0.22078830191789448 + 0.2207943011229821 + 0.22080030048665153 + 0.22080630000890825 + 0.22081229968975774 + 0.22081829952920715 + 0.22082429952726138 + 0.22083029968392703 + 0.22083629999920903 + 0.22084230047311454 + 0.22084830110564907 + 0.22085430189681857 + 0.22086030284662855 + 0.22086630395508514 + 0.22087230522219478 + 0.22087830664796318 + 0.22088430823239616 + 0.22089030997549927 + 0.22089631187727915 + 0.22090231393774176 + 0.22090831615689219 + 0.22091431853473739 + 0.22092032107128301 + 0.22092632376653443 + 0.22093232662049833 + 0.22093832963318014 + 0.22094433280458586 + 0.22095033613472162 + 0.22095633962359348 + 0.22096234327120745 + 0.22096834707756893 + 0.22097435104268462 + 0.22098035516655998 + 0.22098635944920056 + 0.22099236389061347 + 0.22099836849080354 + 0.22100437324977756 + 0.22101037816754035 + 0.22101638324409908 + 0.22102238847945926 + 0.22102839387362688 + 0.22103439942660813 + 0.22104040513840778 + 0.22104641100903308 + 0.22105241703849005 + 0.22105842322678368 + 0.22106442957391995 + 0.22107043607990606 + 0.22107644274474697 + 0.22108244956844861 + 0.22108845655101722 + 0.22109446369245869 + 0.22110047099277916 + 0.22110647845198403 + 0.22111248607007949 + 0.22111849384707202 + 0.22112450178296716 + 0.22113050987777108 + 0.22113651813148905 + 0.22114252654412789 + 0.22114853511569346 + 0.22115454384619093 + 0.22116055273562668 + 0.2211665617840069 + 0.22117257099133764 + 0.22117858035762433 + 0.22118458988287371 + 0.22119059956709111 + 0.22119660941028213 + 0.22120261941245392 + 0.2212086295736114 + 0.22121463989376122 + 0.22122065037290839 + 0.22122666101105992 + 0.22123267180822145 + 0.2212386827643989 + 0.22124469387959789 + 0.22125070515382453 + 0.22125671658708526 + 0.22126272817938566 + 0.22126873993073184 + 0.22127475184112927 + 0.22128076391058449 + 0.22128677613910372 + 0.22129278852669174 + 0.22129880107335589 + 0.22130481377910102 + 0.22131082664393373 + 0.22131683966786009 + 0.22132285285088563 + 0.22132886619301645 + 0.22133487969425858 + 0.22134089335461804 + 0.22134690717410035 + 0.22135292115271221 + 0.22135893529045905 + 0.22136494958734695 + 0.22137096404338255 + 0.22137697865857084 + 0.22138299343291776 + 0.22138900836643058 + 0.22139502345911374 + 0.22140103871097375 + 0.22140705412201728 + 0.22141306969224928 + 0.22141908542167585 + 0.2214251013103036 + 0.22143111735813806 + 0.22143713356518577 + 0.22144314993145178 + 0.22144916645694265 + 0.22145518314166399 + 0.22146119998562175 + 0.2214672169888226 + 0.22147323415127212 + 0.22147925147297623 + 0.22148526895394063 + 0.22149128659417122 + 0.22149730439367529 + 0.2215033223524572 + 0.22150934047052359 + 0.22151535874788053 + 0.22152137718453357 + 0.2215273957804893 + 0.2215334145357532 + 0.22153943345033147 + 0.22154545252423061 + 0.22155147175745565 + 0.22155749115001258 + 0.22156351070190813 + 0.22156953041314728 + 0.22157555028373771 + 0.22158157031368325 + 0.22158759050299165 + 0.22159361085166795 + 0.22159963135971866 + 0.22160565202714888 + 0.22161167285396577 + 0.22161769384017424 + 0.22162371498578087 + 0.22162973629079188 + 0.22163575775521274 + 0.22164177937904889 + 0.22164780116230767 + 0.22165382310499446 + 0.22165984520711482 + 0.2216658674686755 + 0.22167188988968189 + 0.22167791247013957 + 0.22168393521005567 + 0.22168995810943581 + 0.22169598116828548 + 0.22170200438661131 + 0.22170802776441825 + 0.22171405130171354 + 0.22172007499850208 + 0.22172609885479061 + 0.22173212287058511 + 0.22173814704589112 + 0.22174417138071487 + 0.22175019587506223 + 0.22175622052893942 + 0.22176224534235248 + 0.22176827031530699 + 0.22177429544780894 + 0.22178032073986509 + 0.22178634619148027 + 0.22179237180266131 + 0.2217983975734141 + 0.2218044235037443 + 0.22181044959365792 + 0.22181647584316111 + 0.22182250225225991 + 0.22182852882096046 + 0.22183455554926879 + 0.2218405824371899 + 0.22184660948473106 + 0.22185263669189767 + 0.22185866405869595 + 0.22186469158513131 + 0.22187071927121046 + 0.221876747116939 + 0.22188277512232288 + 0.22188880328736829 + 0.22189483161208132 + 0.22190086009646748 + 0.22190688874053338 + 0.2219129175442846 + 0.22191894650772784 + 0.22192497563086747 + 0.22193100491371115 + 0.22193703435626461 + 0.22194306395853269 + 0.22194909372052266 + 0.22195512364224007 + 0.22196115372369102 + 0.22196718396488097 + 0.2219732143658166 + 0.22197924492650353 + 0.22198527564694831 + 0.22199130652715596 + 0.22199733756713314 + 0.22200336876688548 + 0.22200940012641945 + 0.22201543164574125 + 0.22202146332485587 + 0.22202749516376991 + 0.22203352716248961 + 0.22203955932102032 + 0.22204559163936879 + 0.22205162411754062 + 0.22205765675554184 + 0.22206368955337855 + 0.22206972251105681 + 0.22207575562858226 + 0.222081788905961 + 0.2220878223431996 + 0.22209385594030309 + 0.22209988969727809 + 0.22210592361413076 + 0.22211195769086667 + 0.22211799192749249 + 0.22212402632401357 + 0.22213006088043569 + 0.22213609559676548 + 0.22214213047300888 + 0.22214816550917163 + 0.22215420070525968 + 0.22216023606127927 + 0.22216627157723692 + 0.22217230725313719 + 0.22217834308898776 + 0.22218437908479319 + 0.22219041524056055 + 0.22219645155629555 + 0.22220248803200357 + 0.22220852466769142 + 0.22221456146336513 + 0.22222059841903025 + 0.22222663553469235 + 0.22223267281035866 + 0.2222387102460342 + 0.2222447478417256 + 0.22225078559743836 + 0.22225682351317924 + 0.22226286158895378 + 0.2222688998247675 + 0.22227493822062705 + 0.22228097677653805 + 0.22228701549250712 + 0.22229305436853983 + 0.22229909340464227 + 0.22230513260082005 + 0.22231117195707978 + 0.22231721147342753 + 0.22232325114986903 + 0.22232929098641027 + 0.22233533098305677 + 0.22234137113981584 + 0.22234741145669248 + 0.22235345193369277 + 0.22235949257082338 + 0.22236553336808931 + 0.22237157432549726 + 0.22237761544305332 + 0.22238365672076368 + 0.22238969815863324 + 0.22239573975666921 + 0.2224017815148773 + 0.22240782343326296 + 0.22241386551183284 + 0.22241990775059314 + 0.22242595014954883 + 0.2224319927087072 + 0.22243803542807372 + 0.22244407830765392 + 0.22245012134745407 + 0.22245616454748129 + 0.22246220790774004 + 0.22246825142823712 + 0.22247429510897848 + 0.2224803389499698 + 0.22248638295121764 + 0.22249242711272821 + 0.22249847143450652 + 0.22250451591655929 + 0.22251056055889251 + 0.22251660536151191 + 0.22252265032442453 + 0.22252869544763448 + 0.22253474073114937 + 0.22254078617497494 + 0.22254683177911719 + 0.22255287754358166 + 0.22255892346837458 + 0.22256496955350263 + 0.22257101579897076 + 0.22257706220478565 + 0.22258310877095352 + 0.22258915549747985 + 0.22259520238437128 + 0.22260124943163298 + 0.22260729663927209 + 0.22261334400729302 + 0.22261939153570373 + 0.22262543922450909 + 0.22263148707371522 + 0.22263753508332837 + 0.22264358325335454 + 0.22264963158379944 + 0.22265568007466965 + 0.22266172872597079 + 0.22266777753770894 + 0.22267382650989029 + 0.22267987564252098 + 0.22268592493560707 + 0.2226919743891537 + 0.22269802400316796 + 0.22270407377765553 + 0.22271012371262255 + 0.2227161738080751 + 0.2227222240640182 + 0.22272827448045973 + 0.22273432505740406 + 0.22274037579485789 + 0.22274642669282743 + 0.22275247775131876 + 0.22275852897033749 + 0.22276458034988969 + 0.22277063188998156 + 0.22277668359061981 + 0.22278273545180891 + 0.22278878747355596 + 0.22279483965586733 + 0.22280089199874836 + 0.2228069445022054 + 0.22281299716624448 + 0.22281904999087113 + 0.22282510297609162 + 0.22283115612191262 + 0.22283720942833968 + 0.22284326289537887 + 0.22284931652303588 + 0.22285537031131789 + 0.22286142426022942 + 0.22286747836977772 + 0.22287353263996784 + 0.22287958707080699 + 0.22288564166230018 + 0.22289169641445361 + 0.22289775132727396 + 0.22290380640076679 + 0.22290986163493773 + 0.22291591702979405 + 0.22292197258534069 + 0.22292802830158442 + 0.22293408417853025 + 0.22294014021618538 + 0.2229461964145556 + 0.22295225277364628 + 0.22295830929346364 + 0.22296436597401445 + 0.22297042281530424 + 0.22297647981733909 + 0.22298253698012524 + 0.22298859430366888 + 0.22299465178797487 + 0.22300070943305067 + 0.22300676723890173 + 0.22301282520553425 + 0.22301888333295439 + 0.22302494162116773 + 0.2230310000701804 + 0.22303705867999912 + 0.22304311745062902 + 0.22304917638207719 + 0.22305523547434819 + 0.2230612947274499 + 0.22306735414138673 + 0.22307341371616596 + 0.22307947345179263 + 0.223085533348274 + 0.22309159340561455 + 0.22309765362382164 + 0.22310371400290072 + 0.22310977454285799 + 0.22311583524369963 + 0.22312189610543179 + 0.22312795712806013 + 0.22313401831159069 + 0.22314007965602961 + 0.22314614116138323 + 0.22315220282765746 + 0.22315826465485869 + 0.22316432664299182 + 0.22317038879206469 + 0.22317645110208123 + 0.2231825135730493 + 0.22318857620497454 + 0.2231946389978624 + 0.22320070195171926 + 0.2232067650665511 + 0.22321282834236411 + 0.22321889177916454 + 0.22322495537695788 + 0.22323101913575086 + 0.22323708305554921 + 0.22324314713635893 + 0.22324921137818626 + 0.22325527578103682 + 0.22326134034491729 + 0.2232674050698332 + 0.22327346995579089 + 0.22327953500279643 + 0.223285600210856 + 0.22329166557997515 + 0.22329773111016113 + 0.22330379680141807 + 0.22330986265375355 + 0.22331592866717337 + 0.22332199484168366 + 0.22332806117728995 + 0.22333412767399849 + 0.22334019433181534 + 0.22334626115074679 + 0.22335232813079889 + 0.2233583952719779 + 0.22336446257428941 + 0.22337053003773957 + 0.22337659766233453 + 0.22338266544808044 + 0.22338873339498355 + 0.22339480150304941 + 0.22340086977228418 + 0.22340693820269469 + 0.22341300679428638 + 0.22341907554706494 + 0.22342514446103667 + 0.2234312135362081 + 0.22343728277258551 + 0.22344335217017389 + 0.22344942172898002 + 0.22345549144901003 + 0.22346156133027015 + 0.2234676313727654 + 0.22347370157650312 + 0.2234797719414888 + 0.22348584246772812 + 0.22349191315522793 + 0.22349798400399365 + 0.22350405501403212 + 0.22351012618534838 + 0.22351619751794977 + 0.22352226901184125 + 0.22352834066702956 + 0.22353441248351988 + 0.22354048446131999 + 0.22354655660043377 + 0.22355262890086916 + 0.22355870136263112 + 0.22356477398572652 + 0.22357084677016092 + 0.2235769197159399 + 0.22358299282307076 + 0.22358906609155865 + 0.22359513952141025 + 0.22360121311263109 + 0.22360728686522752 + 0.22361336077920557 + 0.2236194348545715 + 0.2236255090913315 + 0.22363158348949058 + 0.22363765804905608 + 0.2236437327700336 + 0.22364980765242937 + 0.2236558826962495 + 0.22366195790149909 + 0.22366803326818599 + 0.22367410879631469 + 0.223680184485892 + 0.22368626033692401 + 0.22369233634941701 + 0.22369841252337649 + 0.22370448885880878 + 0.22371056535572001 + 0.22371664201411626 + 0.22372271883400333 + 0.22372879581538838 + 0.22373487295827602 + 0.22374095026267291 + 0.22374702772858532 + 0.22375310535601997 + 0.22375918314498133 + 0.22376526109547673 + 0.2237713392075118 + 0.22377741748109325 + 0.22378349591622573 + 0.22378957451291695 + 0.22379565327117201 + 0.22380173219099717 + 0.22380781127239913 + 0.22381389051538295 + 0.2238199699199554 + 0.22382604948612264 + 0.22383212921388984 + 0.22383820910326477 + 0.22384428915425195 + 0.22385036936685815 + 0.22385644974108901 + 0.22386253027695133 + 0.22386861097445065 + 0.22387469183359315 + 0.22388077285438573 + 0.22388685403683276 + 0.22389293538094221 + 0.22389901688671851 + 0.22390509855416907 + 0.22391118038329944 + 0.22391726237411583 + 0.22392334452662391 + 0.22392942684082984 + 0.22393550931674047 + 0.22394159195436128 + 0.22394767475369859 + 0.22395375771475848 + 0.22395984083754616 + 0.22396592412206948 + 0.22397200756833294 + 0.22397809117634376 + 0.22398417494610717 + 0.22399025887762986 + 0.22399634297091753 + 0.22400242722597624 + 0.22400851164281285 + 0.22401459622143252 + 0.22402068096184183 + 0.22402676586404649 + 0.22403285092805336 + 0.22403893615386794 + 0.2240450215414965 + 0.2240511070909447 + 0.22405719280221928 + 0.22406327867532647 + 0.22406936471027181 + 0.22407545090706107 + 0.22408153726570157 + 0.22408762378619826 + 0.224093710468558 + 0.2240997973127859 + 0.22410588431888925 + 0.22411197148687423 + 0.22411805881674543 + 0.22412414630851013 + 0.22413023396217457 + 0.22413632177774429 + 0.22414240975522509 + 0.22414849789462421 + 0.22415458619594678 + 0.22416067465919953 + 0.22416676328438812 + 0.22417285207151871 + 0.22417894102059704 + 0.22418503013163044 + 0.22419111940462391 + 0.22419720883958422 + 0.22420329843651657 + 0.22420938819542766 + 0.22421547811632431 + 0.22422156819921149 + 0.22422765844409551 + 0.22423374885098318 + 0.22423983941987952 + 0.22424593015079186 + 0.22425202104372527 + 0.22425811209868657 + 0.22426420331568148 + 0.22427029469471607 + 0.22427638623579663 + 0.22428247793892886 + 0.22428856980412001 + 0.22429466183137514 + 0.22430075402070007 + 0.22430684637210202 + 0.22431293888558668 + 0.22431903156116018 + 0.22432512439882774 + 0.22433121739859666 + 0.22433731056047307 + 0.22434340388446214 + 0.22434949737057069 + 0.22435559101880434 + 0.22436168482916988 + 0.22436777880167288 + 0.22437387293631963 + 0.22437996723311646 + 0.22438606169206882 + 0.2243921563131836 + 0.22439825109646641 + 0.22440434604192364 + 0.22441044114956124 + 0.22441653641938561 + 0.22442263185140243 + 0.22442872744561784 + 0.22443482320203861 + 0.22444091912067046 + 0.22444701520151902 + 0.2244531114445911 + 0.22445920784989229 + 0.22446530441742948 + 0.22447140114720771 + 0.22447749803923436 + 0.22448359509351454 + 0.22448969231005436 + 0.22449578968886075 + 0.22450188722993936 + 0.22450798493329627 + 0.22451408279893789 + 0.22452018082686981 + 0.22452627901709818 + 0.22453237736962994 + 0.22453847588447062 + 0.22454457456162599 + 0.22455067340110274 + 0.2245567724029072 + 0.22456287156704446 + 0.22456897089352179 + 0.22457507038234492 + 0.22458117003351949 + 0.22458726984705285 + 0.22459336982294967 + 0.22459946996121655 + 0.22460557026185982 + 0.22461167072488572 + 0.22461777135030048 + 0.22462387213810972 + 0.22462997308831975 + 0.22463607420093726 + 0.22464217547596743 + 0.22464827691341707 + 0.22465437851329181 + 0.22466048027559793 + 0.22466658220034216 + 0.22467268428753023 + 0.2246787865371678 + 0.22468488894926161 + 0.22469099152381747 + 0.2246970942608415 + 0.22470319716033993 + 0.22470930022231961 + 0.22471540344678509 + 0.22472150683374373 + 0.22472761038320169 + 0.22473371409516421 + 0.22473981796963857 + 0.22474592200662938 + 0.22475202620614443 + 0.22475813056818897 + 0.22476423509276922 + 0.22477033977989086 + 0.2247764446295612 + 0.22478254964178546 + 0.22478865481656968 + 0.22479476015392091 + 0.22480086565384463 + 0.22480697131634661 + 0.22481307714143428 + 0.22481918312911206 + 0.22482528927938736 + 0.22483139559226592 + 0.22483750206775341 + 0.22484360870585712 + 0.22484971550658225 + 0.22485582246993499 + 0.22486192959592219 + 0.22486803688454951 + 0.22487414433582265 + 0.22488025194974781 + 0.22488635972633236 + 0.22489246766558094 + 0.22489857576750086 + 0.22490468403209726 + 0.22491079245937692 + 0.22491690104934556 + 0.22492300980200994 + 0.22492911871737584 + 0.22493522779544939 + 0.22494133703623642 + 0.22494744643974363 + 0.22495355600597666 + 0.22495966573494247 + 0.22496577562664613 + 0.22497188568109436 + 0.22497799589829351 + 0.22498410627824925 + 0.22499021682096843 + 0.22499632752645607 + 0.22500243839471967 + 0.22500854942576365 + 0.22501466061959607 + 0.22502077197622208 + 0.22502688349564778 + 0.225032995177879 + 0.22503910702292304 + 0.22504521903078517 + 0.22505133120147194 + 0.22505744353498877 + 0.22506355603134284 + 0.2250696686905394 + 0.22507578151258575 + 0.22508189449748645 + 0.22508800764524897 + 0.22509412095587888 + 0.22510023442938204 + 0.22510634806576513 + 0.22511246186503447 + 0.22511857582719569 + 0.22512468995225518 + 0.22513080424021964 + 0.22513691869109362 + 0.22514303330488517 + 0.22514914808159942 + 0.22515526302124256 + 0.22516137812382087 + 0.22516749338934006 + 0.22517360881780746 + 0.22517972440922773 + 0.22518584016360885 + 0.22519195608095527 + 0.22519807216127383 + 0.22520418840457035 + 0.22521030481085211 + 0.22521642138012368 + 0.22522253811239251 + 0.2252286550076637 + 0.22523477206594469 + 0.22524088928723995 + 0.22524700667155756 + 0.22525312421890195 + 0.22525924192928068 + 0.22526535980269877 + 0.22527147783916307 + 0.22527759603867933 + 0.22528371440125375 + 0.22528983292689322 + 0.22529595161560281 + 0.22530207046738948 + 0.22530818948225928 + 0.22531430866021812 + 0.22532042800127219 + 0.22532654750542777 + 0.22533266717269113 + 0.22533878700306792 + 0.22534490699656509 + 0.22535102715318817 + 0.22535714747294361 + 0.22536326795583703 + 0.2253693886018758 + 0.22537550941106463 + 0.22538163038341069 + 0.22538775151891999 + 0.22539387281759848 + 0.22539999427945276 + 0.22540611590448822 + 0.22541223769271138 + 0.2254183596441289 + 0.22542448175874608 + 0.22543060403656967 + 0.22543672647760596 + 0.22544284908186063 + 0.22544897184934001 + 0.22545509478005091 + 0.22546121787399848 + 0.22546734113118899 + 0.22547346455162923 + 0.22547958813532562 + 0.22548571188228322 + 0.22549183579250884 + 0.22549795986600879 + 0.22550408410278941 + 0.22551020850285625 + 0.22551633306621524 + 0.22552245779287358 + 0.22552858268283713 + 0.22553470773611156 + 0.22554083295270314 + 0.22554695833261865 + 0.2255530838758634 + 0.22555920958244463 + 0.22556533545236707 + 0.22557146148563861 + 0.22557758768226388 + 0.22558371404225028 + 0.22558984056560294 + 0.22559596725232869 + 0.22560209410243384 + 0.22560822111592418 + 0.22561434829280594 + 0.22562047563308477 + 0.22562660313676811 + 0.22563273080386118 + 0.22563885863437083 + 0.22564498662830212 + 0.22565111478566258 + 0.22565724310645729 + 0.22566337159069316 + 0.2256695002383764 + 0.22567562904951216 + 0.22568175802410795 + 0.22568788716216889 + 0.22569401646370238 + 0.22570014592871304 + 0.22570627555720829 + 0.22571240534919379 + 0.22571853530467528 + 0.22572466542366024 + 0.22573079570615381 + 0.22573692615216229 + 0.22574305676169246 + 0.22574918753474954 + 0.22575531847134045 + 0.22576144957147132 + 0.225767580835148 + 0.22577371226237675 + 0.22577984385316444 + 0.22578597560751618 + 0.22579210752543891 + 0.22579823960693826 + 0.22580437185202062 + 0.2258105042606928 + 0.22581663683295997 + 0.22582276956882902 + 0.22582890246830614 + 0.22583503553139725 + 0.22584116875810786 + 0.22584730214844609 + 0.22585343570241592 + 0.22585956942002491 + 0.2258657033012792 + 0.22587183734618455 + 0.22587797155474676 + 0.22588410592697319 + 0.22589024046286904 + 0.2258963751624406 + 0.2259025100256947 + 0.22590864505263722 + 0.22591478024327372 + 0.22592091559761104 + 0.2259270511156557 + 0.22593318679741325 + 0.22593932264289007 + 0.22594545865209242 + 0.22595159482502658 + 0.22595773116169837 + 0.2259638676621146 + 0.22597000432628045 + 0.22597614115420336 + 0.22598227814588842 + 0.22598841530134267 + 0.2259945526205723 + 0.22600069010358251 + 0.22600682775038064 + 0.226012965560972 + 0.22601910353536345 + 0.22602524167356067 + 0.22603137997557052 + 0.22603751844139877 + 0.2260436570710517 + 0.22604979586453516 + 0.22605593482185588 + 0.22606207394301966 + 0.22606821322803278 + 0.22607435267690165 + 0.22608049228963248 + 0.22608663206623097 + 0.22609277200670413 + 0.22609891211105759 + 0.22610505237929771 + 0.22611119281143019 + 0.22611733340746201 + 0.22612347416739936 + 0.22612961509124804 + 0.22613575617901435 + 0.22614189743070465 + 0.22614803884632459 + 0.22615418042588112 + 0.22616032216938001 + 0.22616646407682744 + 0.22617260614822987 + 0.2261787483835935 + 0.22618489078292423 + 0.22619103334622875 + 0.22619717607351236 + 0.22620331896478246 + 0.2262094620200443 + 0.22621560523930465 + 0.22622174862256936 + 0.22622789216984526 + 0.22623403588113758 + 0.22624017975645366 + 0.22624632379579876 + 0.22625246799917925 + 0.22625861236660141 + 0.22626475689807202 + 0.22627090159359642 + 0.22627704645318145 + 0.22628319147683335 + 0.22628933666455739 + 0.22629548201636096 + 0.22630162753224986 + 0.22630777321223039 + 0.22631391905630777 + 0.2263200650644899 + 0.22632621123678159 + 0.22633235757318962 + 0.22633850407372086 + 0.22634465073837998 + 0.22635079756717444 + 0.22635694456010994 + 0.22636309171719338 + 0.22636923903842995 + 0.22637538652382605 + 0.22638153417338905 + 0.22638768198712364 + 0.22639382996503668 + 0.22639997810713441 + 0.22640612641342328 + 0.22641227488390905 + 0.22641842351859848 + 0.22642457231749749 + 0.22643072128061173 + 0.22643687040794808 + 0.22644301969951303 + 0.2264491691553121 + 0.22645531877535238 + 0.22646146855963897 + 0.22646761850817876 + 0.22647376862097762 + 0.22647991889804228 + 0.22648606933937862 + 0.22649221994499294 + 0.22649837071489157 + 0.22650452164908078 + 0.22651067274756587 + 0.22651682401035486 + 0.22652297543745226 + 0.22652912702886513 + 0.22653527878459967 + 0.22654143070466168 + 0.22654758278905759 + 0.22655373503779414 + 0.22655988745087668 + 0.22656604002831202 + 0.22657219277010643 + 0.22657834567626584 + 0.22658449874679651 + 0.22659065198170469 + 0.22659680538099689 + 0.22660295894467872 + 0.22660911267275716 + 0.22661526656523792 + 0.22662142062212684 + 0.22662757484343143 + 0.22663372922915676 + 0.22663988377930974 + 0.22664603849389631 + 0.22665219337292208 + 0.22665834841639509 + 0.2266645036243195 + 0.22667065899670275 + 0.22667681453355062 + 0.22668297023486936 + 0.22668912610066547 + 0.22669528213094511 + 0.22670143832571424 + 0.22670759468497959 + 0.22671375120874704 + 0.22671990789702237 + 0.22672606474981299 + 0.2267322217671241 + 0.22673837894896215 + 0.22674453629533348 + 0.2267506938062448 + 0.22675685148170149 + 0.22676300932171048 + 0.22676916732627744 + 0.22677532549540882 + 0.22678148382911145 + 0.2267876423273906 + 0.22679380099025309 + 0.22679995981770479 + 0.22680611880975257 + 0.22681227796640224 + 0.22681843728765957 + 0.22682459677353145 + 0.22683075642402423 + 0.2268369162391437 + 0.22684307621889621 + 0.22684923636328805 + 0.22685539667232571 + 0.22686155714601486 + 0.22686771778436246 + 0.22687387858737368 + 0.22688003955505601 + 0.22688620068741527 + 0.22689236198445667 + 0.22689852344618824 + 0.22690468507261519 + 0.22691084686374335 + 0.2269170088195796 + 0.22692317094013031 + 0.22692933322540179 + 0.22693549567539986 + 0.22694165829013038 + 0.22694782106960062 + 0.22695398401381608 + 0.22696014712278345 + 0.22696631039650866 + 0.22697247383499802 + 0.2269786374382578 + 0.22698480120629394 + 0.22699096513911321 + 0.22699712923672208 + 0.22700329349912576 + 0.22700945792633165 + 0.22701562251834509 + 0.227021787275173 + 0.22702795219682101 + 0.22703411728329567 + 0.2270402825346037 + 0.22704644795075055 + 0.22705261353174247 + 0.22705877927758641 + 0.22706494518828862 + 0.22707111126385446 + 0.22707727750429085 + 0.2270834439096035 + 0.22708961047979989 + 0.2270957772148848 + 0.22710194411486517 + 0.22710811117974775 + 0.22711427840953785 + 0.22712044580424195 + 0.2271266133638668 + 0.22713278108841831 + 0.22713894897790227 + 0.22714511703232609 + 0.22715128525169509 + 0.22715745363601564 + 0.22716362218529404 + 0.22716979089953723 + 0.22717595977875044 + 0.22718212882294014 + 0.22718829803211307 + 0.22719446740627525 + 0.22720063694543341 + 0.22720680664959289 + 0.22721297651876007 + 0.22721914655294181 + 0.227225316752144 + 0.22723148711637289 + 0.227237657645635 + 0.2272438283399365 + 0.2272499991992834 + 0.22725617022368197 + 0.22726234141313911 + 0.22726851276766014 + 0.22727468428725198 + 0.22728085597192033 + 0.22728702782167226 + 0.22729319983651353 + 0.2272993720164499 + 0.22730554436148889 + 0.22731171687163582 + 0.22731788954689697 + 0.22732406238727873 + 0.22733023539278804 + 0.22733640856343018 + 0.2273425818992115 + 0.22734875540013888 + 0.22735492906621829 + 0.22736110289745642 + 0.22736727689385877 + 0.2273734510554315 + 0.2273796253821817 + 0.22738579987411511 + 0.22739197453123819 + 0.22739814935355718 + 0.2274043243410786 + 0.22741049949380812 + 0.22741667481175221 + 0.22742285029491724 + 0.22742902594330952 + 0.22743520175693552 + 0.22744137773580095 + 0.22744755387991289 + 0.22745373018927706 + 0.22745990666389984 + 0.22746608330378704 + 0.22747226010894572 + 0.22747843707938151 + 0.22748461421510091 + 0.22749079151611024 + 0.22749696898241598 + 0.2275031466140244 + 0.22750932441094135 + 0.2275155023731727 + 0.22752168050072644 + 0.22752785879360674 + 0.22753403725182117 + 0.22754021587537598 + 0.22754639466427709 + 0.2275525736185309 + 0.22755875273814372 + 0.22756493202312136 + 0.22757111147347089 + 0.22757729108919794 + 0.22758347087030914 + 0.22758965081681062 + 0.22759583092870839 + 0.22760201120600931 + 0.22760819164871926 + 0.22761437225684511 + 0.22762055303039222 + 0.22762673396936747 + 0.22763291507377667 + 0.22763909634362681 + 0.22764527777892374 + 0.22765145937967379 + 0.2276576411458828 + 0.22766382307755778 + 0.22767000517470506 + 0.22767618743732984 + 0.22768236986543922 + 0.2276885524590401 + 0.22769473521813718 + 0.22770091814273846 + 0.22770710123284874 + 0.22771328448847497 + 0.22771946790962408 + 0.22772565149630078 + 0.22773183524851257 + 0.22773801916626585 + 0.22774420324956587 + 0.22775038749841961 + 0.22775657191283347 + 0.22776275649281327 + 0.22776894123836544 + 0.22777512614949685 + 0.22778131122621295 + 0.22778749646852101 + 0.2277936818764259 + 0.22779986744993519 + 0.2278060531890545 + 0.22781223909379045 + 0.22781842516414877 + 0.22782461140013638 + 0.22783079780175977 + 0.22783698436902422 + 0.22784317110193658 + 0.22784935800050329 + 0.22785554506473085 + 0.227861732294625 + 0.22786791969019213 + 0.22787410725143867 + 0.22788029497837106 + 0.22788648287099558 + 0.22789267092931823 + 0.22789885915334535 + 0.22790504754308324 + 0.22791123609853783 + 0.22791742481971669 + 0.22792361370662445 + 0.22792980275926925 + 0.22793599197765577 + 0.22794218136179106 + 0.2279483709116808 + 0.22795456062733213 + 0.22796075050875136 + 0.2279669405559438 + 0.22797313076891643 + 0.22797932114767558 + 0.22798551169222714 + 0.22799170240257757 + 0.22799789327873377 + 0.22800408432070154 + 0.22801027552848688 + 0.22801646690209665 + 0.22802265844153669 + 0.22802885014681348 + 0.22803504201793334 + 0.22804123405490273 + 0.2280474262577275 + 0.22805361862641457 + 0.22805981116096991 + 0.22806600386139919 + 0.22807219672771006 + 0.22807838975990841 + 0.22808458295799944 + 0.22809077632199062 + 0.22809696985188796 + 0.22810316354769725 + 0.22810935740942545 + 0.22811555143707843 + 0.22812174563066312 + 0.22812793999018538 + 0.22813413451565165 + 0.22814032920706778 + 0.22814652406444016 + 0.22815271908777587 + 0.22815891427708063 + 0.22816510963236092 + 0.22817130515362305 + 0.22817750084087249 + 0.22818369669411667 + 0.22818989271336201 + 0.22819608889861384 + 0.22820228524987907 + 0.22820848176716366 + 0.22821467845047455 + 0.22822087529981694 + 0.22822707231519851 + 0.22823326949662506 + 0.22823946684410185 + 0.22824566435763705 + 0.2282518620372353 + 0.22825805988290426 + 0.22826425789464858 + 0.22827045607247637 + 0.22827665441639305 + 0.22828285292640482 + 0.22828905160251831 + 0.22829525044473983 + 0.22830144945307582 + 0.22830764862753158 + 0.22831384796811524 + 0.22832004747483151 + 0.22832624714768743 + 0.22833244698668884 + 0.22833864699184264 + 0.22834484716315476 + 0.22835104750063165 + 0.22835724800427967 + 0.22836344867410535 + 0.2283696495101144 + 0.22837585051231343 + 0.22838205168070932 + 0.22838825301530732 + 0.22839445451611448 + 0.22840065618313674 + 0.228406858016381 + 0.22841306001585313 + 0.22841926218155897 + 0.22842546451350618 + 0.22843166701169998 + 0.22843786967614679 + 0.22844407250685306 + 0.22845027550382532 + 0.22845647866706983 + 0.22846268199659311 + 0.22846888549240099 + 0.22847508915449946 + 0.22848129298289643 + 0.22848749697759624 + 0.22849370113860645 + 0.22849990546593341 + 0.22850610995958298 + 0.22851231461956112 + 0.22851851944587534 + 0.22852472443853097 + 0.22853092959753446 + 0.22853713492289271 + 0.22854334041461169 + 0.22854954607269728 + 0.22855575189715699 + 0.22856195788799552 + 0.22856816404522057 + 0.22857437036883727 + 0.22858057685885336 + 0.22858678351527406 + 0.22859299033810634 + 0.2285991973273562 + 0.22860540448302996 + 0.22861161180513412 + 0.2286178192936745 + 0.22862402694865816 + 0.22863023477009151 + 0.2286364427579799 + 0.22864265091233024 + 0.22864885923314909 + 0.22865506772044283 + 0.22866127637421679 + 0.22866748519447846 + 0.22867369418123382 + 0.22867990333448873 + 0.22868611265425071 + 0.2286923221405246 + 0.22869853179331728 + 0.22870474161263593 + 0.22871095159848565 + 0.22871716175087364 + 0.22872337206980572 + 0.2287295825552883 + 0.22873579320732779 + 0.22874200402593073 + 0.22874821501110354 + 0.22875442616285205 + 0.22876063748118278 + 0.22876684896610211 + 0.22877306061761657 + 0.22877927243573198 + 0.22878548442045529 + 0.22879169657179252 + 0.22879790888975007 + 0.22880412137433431 + 0.22881033402555184 + 0.22881654684340844 + 0.2288227598279105 + 0.2288289729790646 + 0.22883518629687713 + 0.22884139978135459 + 0.22884761343250273 + 0.22885382725032874 + 0.22886004123483844 + 0.22886625538603769 + 0.22887246970393355 + 0.22887868418853238 + 0.22888489883984017 + 0.22889111365786338 + 0.22889732864260837 + 0.22890354379408107 + 0.22890975911228856 + 0.22891597459723714 + 0.22892219024893234 + 0.22892840606738163 + 0.22893462205259035 + 0.22894083820456554 + 0.22894705452331246 + 0.22895327100883933 + 0.22895948766115093 + 0.22896570448025419 + 0.22897192146615514 + 0.2289781386188606 + 0.22898435593837665 + 0.22899057342470969 + 0.22899679107786558 + 0.22900300889785147 + 0.22900922688467359 + 0.22901544503833804 + 0.22902166335885116 + 0.2290278818462195 + 0.22903410050044887 + 0.22904031932154575 + 0.22904653830951727 + 0.22905275746436918 + 0.22905897678610812 + 0.22906519627473979 + 0.22907141593027128 + 0.22907763575270856 + 0.22908385574205797 + 0.22909007589832611 + 0.22909629622151881 + 0.22910251671164311 + 0.22910873736870493 + 0.22911495819271072 + 0.2291211791836669 + 0.22912740034157997 + 0.22913362166645584 + 0.22913984315830155 + 0.22914606481712299 + 0.22915228664292667 + 0.22915850863571779 + 0.22916473079550467 + 0.22917095312229258 + 0.22917717561608791 + 0.22918339827689729 + 0.2291896211047271 + 0.22919584409958332 + 0.22920206726147285 + 0.22920829059040165 + 0.22921451408637561 + 0.22922073774940244 + 0.22922696157948733 + 0.22923318557663688 + 0.22923940974085805 + 0.22924563407215615 + 0.22925185857053834 + 0.22925808323601099 + 0.22926430806858003 + 0.22927053306825196 + 0.22927675823503324 + 0.22928298356893034 + 0.22928920906994968 + 0.22929543473809727 + 0.2293016605733795 + 0.22930788657580348 + 0.229314112745374 + 0.22932033908209909 + 0.22932656558598427 + 0.22933279225703593 + 0.22933901909526105 + 0.22934524610066515 + 0.22935147327325509 + 0.22935770061303698 + 0.22936392812001705 + 0.22937015579420253 + 0.22937638363559876 + 0.2293826116442127 + 0.22938883982005029 + 0.22939506816311864 + 0.22940129667342357 + 0.22940752535097109 + 0.2294137541957687 + 0.22941998320782125 + 0.22942621238713631 + 0.22943244173372052 + 0.22943867124757905 + 0.22944490092871897 + 0.22945113077714624 + 0.22945736079286738 + 0.22946359097588939 + 0.22946982132621763 + 0.22947605184385972 + 0.22948228252882044 + 0.22948851338110737 + 0.22949474440072706 + 0.22950097558768487 + 0.22950720694198776 + 0.22951343846364178 + 0.22951967015265387 + 0.22952590200903 + 0.22953213403277661 + 0.2295383662238997 + 0.22954459858240625 + 0.22955083110830291 + 0.22955706380159532 + 0.22956329666228964 + 0.2295695296903934 + 0.22957576288591192 + 0.22958199624885178 + 0.22958822977921997 + 0.22959446347702187 + 0.22960069734226515 + 0.22960693137495505 + 0.22961316557509823 + 0.22961939994270159 + 0.22962563447777054 + 0.2296318691803127 + 0.22963810405033347 + 0.22964433908783935 + 0.22965057429283736 + 0.22965680966533342 + 0.22966304520533401 + 0.22966928091284508 + 0.22967551678787376 + 0.22968175283042533 + 0.22968798904050741 + 0.22969422541812656 + 0.2297004619632875 + 0.22970669867599794 + 0.22971293555626374 + 0.22971917260409147 + 0.22972540981948755 + 0.22973164720245851 + 0.2297378847530103 + 0.22974412247114995 + 0.22975036035688343 + 0.22975659841021664 + 0.22976283663115721 + 0.22976907501971053 + 0.22977531357588316 + 0.22978155229968147 + 0.22978779119111201 + 0.22979403025018127 + 0.22980026947689527 + 0.229806508871261 + 0.22981274843328436 + 0.22981898816297192 + 0.22982522806032968 + 0.22983146812536451 + 0.22983770835808315 + 0.22984394875849079 + 0.22985018932659512 + 0.2298564300624015 + 0.22986267096591706 + 0.22986891203714771 + 0.22987515327609992 + 0.22988139468278027 + 0.2298876362571951 + 0.2298938779993511 + 0.22990011990925413 + 0.22990636198691075 + 0.22991260423232796 + 0.22991884664551057 + 0.2299250892264669 + 0.22993133197520213 + 0.22993757489172295 + 0.2299438179760358 + 0.22995006122814712 + 0.22995630464806358 + 0.22996254823579096 + 0.22996879199133588 + 0.22997503591470478 + 0.22998128000590423 + 0.22998752426494071 + 0.22999376869182014 + 0.23000001328654959 + 0.23000625804913458 + 0.23001250297958198 + 0.23001874807789902 + 0.23002499334409046 + 0.23003123877816395 + 0.23003748438012486 + 0.23004373014998089 + 0.23004997608773733 + 0.23005622219340138 + 0.23006246846697881 + 0.23006871490847633 + 0.23007496151790036 + 0.2300812082952568 + 0.23008745524055288 + 0.23009370235379495 + 0.2300999496349885 + 0.23010619708414115 + 0.2301124447012583 + 0.23011869248634706 + 0.23012494043941326 + 0.230131188560463 + 0.2301374368495038 + 0.23014368530654172 + 0.23014993393158326 + 0.23015618272463373 + 0.2301624316857003 + 0.23016868081479006 + 0.2301749301119089 + 0.23018117957706227 + 0.23018742921025775 + 0.23019367901150192 + 0.23019992898080016 + 0.23020617911815952 + 0.23021242942358666 + 0.23021867989708736 + 0.23022493053866824 + 0.23023118134833576 + 0.2302374323260965 + 0.23024368347195645 + 0.23024993478592262 + 0.23025618626800098 + 0.23026243791819817 + 0.23026868973652051 + 0.23027494172297416 + 0.23028119387756604 + 0.23028744620030231 + 0.23029369869118932 + 0.23029995135023362 + 0.23030620417744124 + 0.23031245717281928 + 0.23031871033637366 + 0.23032496366811089 + 0.23033121716803759 + 0.23033747083615957 + 0.23034372467248404 + 0.23034997867701701 + 0.23035623284976489 + 0.23036248719073418 + 0.23036874169993163 + 0.23037499637736294 + 0.23038125122303488 + 0.23038750623695378 + 0.23039376141912629 + 0.23040001676955887 + 0.23040627228825816 + 0.23041252797522949 + 0.23041878383048053 + 0.23042503985401666 + 0.23043129604584559 + 0.23043755240597263 + 0.23044380893440392 + 0.23045006563114695 + 0.23045632249620784 + 0.23046257952959304 + 0.23046883673130852 + 0.23047509410136077 + 0.23048135163975703 + 0.23048760934650259 + 0.23049386722160459 + 0.23050012526506961 + 0.23050638347690353 + 0.23051264185711298 + 0.23051890040570444 + 0.23052515912268387 + 0.23053141800805899 + 0.23053767706183462 + 0.23054393628401848 + 0.2305501956746159 + 0.23055645523363405 + 0.23056271496107936 + 0.23056897485695796 + 0.23057523492127682 + 0.23058149515404147 + 0.23058775555525893 + 0.23059401612493585 + 0.23060027686307749 + 0.23060653776969217 + 0.23061279884478472 + 0.2306190600883623 + 0.23062532150043086 + 0.2306315830809969 + 0.23063784483006816 + 0.23064410674764887 + 0.23065036883374729 + 0.23065663108836887 + 0.23066289351152069 + 0.23066915610320873 + 0.23067541886343948 + 0.23068168179221907 + 0.23068794488955505 + 0.2306942081554523 + 0.23070047158991858 + 0.23070673519295976 + 0.23071299896458183 + 0.2307192629047925 + 0.23072552701359667 + 0.23073179129100199 + 0.23073805573701445 + 0.2307443203516405 + 0.2307505851348863 + 0.23075685008675884 + 0.23076311520726417 + 0.23076938049640877 + 0.23077564595419922 + 0.23078191158064157 + 0.23078817737574345 + 0.23079444333950977 + 0.23080070947194756 + 0.23080697577306339 + 0.23081324224286387 + 0.23081950888135497 + 0.23082577568854376 + 0.23083204266443574 + 0.23083830980903852 + 0.23084457712235762 + 0.23085084460440006 + 0.23085711225517189 + 0.23086338007467908 + 0.23086964806292934 + 0.23087591621992865 + 0.23088218454568299 + 0.23088845304019892 + 0.23089472170348357 + 0.23090099053554242 + 0.23090725953638253 + 0.23091352870601042 + 0.23091979804443158 + 0.23092606755165368 + 0.23093233722768278 + 0.23093860707252534 + 0.23094487708618741 + 0.23095114726867558 + 0.23095741761999689 + 0.23096368814015686 + 0.23096995882916319 + 0.23097622968702064 + 0.23098250071373691 + 0.2309887719093181 + 0.23099504327377082 + 0.23100131480710145 + 0.23100758650931666 + 0.23101385838042238 + 0.23102013042042527 + 0.2310264026293313 + 0.23103267500714819 + 0.23103894755388124 + 0.23104522026953775 + 0.23105149315412307 + 0.2310577662076449 + 0.23106403943010934 + 0.23107031282152224 + 0.23107658638189019 + 0.23108286011121987 + 0.23108913400951833 + 0.23109540807679163 + 0.23110168231304568 + 0.2311079567182871 + 0.23111423129252245 + 0.23112050603575895 + 0.23112678094800196 + 0.23113305602925854 + 0.2311393312795354 + 0.23114560669883791 + 0.23115188228717326 + 0.23115815804454853 + 0.23116443397096922 + 0.23117071006644183 + 0.23117698633097294 + 0.23118326276456974 + 0.23118953936723763 + 0.23119581613898443 + 0.23120209307981485 + 0.23120837018973667 + 0.23121464746875531 + 0.23122092491687851 + 0.23122720253411175 + 0.23123348032046212 + 0.2312397582759356 + 0.23124603640053878 + 0.23125231469427834 + 0.23125859315716016 + 0.23126487178919142 + 0.23127115059037825 + 0.23127742956072755 + 0.23128370870024503 + 0.23128998800893705 + 0.23129626748681095 + 0.23130254713387313 + 0.23130882695012975 + 0.23131510693558666 + 0.23132138709025177 + 0.23132766741412986 + 0.23133394790722861 + 0.23134022856955408 + 0.2313465094011129 + 0.23135279040191162 + 0.23135907157195557 + 0.23136535291125318 + 0.23137163441980993 + 0.23137791609763167 + 0.23138419794472562 + 0.23139047996109849 + 0.23139676214675611 + 0.23140304450170521 + 0.23140932702595224 + 0.23141560971950334 + 0.23142189258236623 + 0.23142817561454571 + 0.23143445881604952 + 0.23144074218688312 + 0.2314470257270537 + 0.23145330943656792 + 0.23145959331543162 + 0.23146587736365204 + 0.23147216158123463 + 0.23147844596818656 + 0.23148473052451449 + 0.23149101525022373 + 0.23149730014532208 + 0.23150358520981554 + 0.2315098704437108 + 0.23151615584701427 + 0.23152244141973211 + 0.23152872716187031 + 0.23153501307343663 + 0.23154129915443644 + 0.23154758540487758 + 0.23155387182476483 + 0.23156015841410604 + 0.23156644517290709 + 0.23157273210117413 + 0.2315790191989143 + 0.23158530646613359 + 0.23159159390283912 + 0.23159788150903701 + 0.23160416928473326 + 0.23161045722993504 + 0.23161674534464835 + 0.2316230336288804 + 0.23162932208263715 + 0.23163561070592464 + 0.23164189949875011 + 0.23164818846112015 + 0.23165447759304009 + 0.23166076689451784 + 0.23166705636555882 + 0.23167334600617062 + 0.23167963581635834 + 0.23168592579612957 + 0.23169221594549042 + 0.23169850626444688 + 0.23170479675300673 + 0.23171108741117485 + 0.23171737823895897 + 0.23172366923636509 + 0.23172996040339985 + 0.2317362517400699 + 0.23174254324638063 + 0.23174883492234036 + 0.23175512676795404 + 0.23176141878322881 + 0.23176771096817128 + 0.23177400332278739 + 0.23178029584708393 + 0.23178658854106793 + 0.23179288140474494 + 0.23179917443812215 + 0.23180546764120605 + 0.23181176101400275 + 0.23181805455651891 + 0.2318243482687605 + 0.23183064215073518 + 0.23183693620244863 + 0.23184323042390736 + 0.23184952481511789 + 0.23185581937608754 + 0.23186211410682114 + 0.23186840900732703 + 0.23187470407761004 + 0.23188099931767805 + 0.23188729472753702 + 0.231893590307193 + 0.2318998860566531 + 0.23190618197592408 + 0.23191247806501139 + 0.23191877432392208 + 0.23192507075266292 + 0.23193136735124037 + 0.23193766411965999 + 0.23194396105792958 + 0.23195025816605511 + 0.23195655544404323 + 0.23196285289189997 + 0.23196915050963252 + 0.23197544829724637 + 0.23198174625474866 + 0.23198804438214662 + 0.23199434267944577 + 0.23200064114665256 + 0.23200693978377385 + 0.2320132385908166 + 0.2320195375677864 + 0.23202583671468993 + 0.23203213603153425 + 0.23203843551832545 + 0.23204473517507013 + 0.23205103500177504 + 0.23205733499844602 + 0.2320636351650911 + 0.2320699355017149 + 0.23207623600832417 + 0.23208253668492676 + 0.23208883753152806 + 0.23209513854813521 + 0.23210143973475433 + 0.23210774109139207 + 0.23211404261805504 + 0.23212034431474871 + 0.23212664618148132 + 0.23213294821825853 + 0.23213925042508687 + 0.23214555280197238 + 0.23215185534892285 + 0.2321581580659432 + 0.23216446095304122 + 0.23217076401022285 + 0.23217706723749487 + 0.23218337063486322 + 0.23218967420233516 + 0.23219597793991675 + 0.23220228184761402 + 0.23220858592543478 + 0.23221489017338501 + 0.23222119459147084 + 0.23222749917969887 + 0.23223380393807574 + 0.23224010886660806 + 0.23224641396530196 + 0.23225271923416452 + 0.23225902467320186 + 0.23226533028242127 + 0.23227163606182805 + 0.23227794201142959 + 0.23228424813123191 + 0.23229055442124152 + 0.23229686088146576 + 0.23230316751191007 + 0.23230947431258164 + 0.23231578128348709 + 0.23232208842463256 + 0.23232839573602407 + 0.23233470321766936 + 0.23234101086957457 + 0.23234731869174563 + 0.2323536266841888 + 0.23235993484691228 + 0.23236624317992105 + 0.23237255168322238 + 0.23237886035682215 + 0.23238516920072716 + 0.23239147821494457 + 0.23239778739947997 + 0.23240409675434096 + 0.23241040627953313 + 0.23241671597506314 + 0.23242302584093755 + 0.23242933587716311 + 0.23243564608374642 + 0.23244195646069352 + 0.23244826700801163 + 0.2324545777257063 + 0.23246088861378522 + 0.2324671996722539 + 0.23247351090111973 + 0.23247982230038858 + 0.23248613387006767 + 0.23249244561016266 + 0.23249875752068058 + 0.23250506960162762 + 0.23251138185301104 + 0.23251769427483673 + 0.23252400686711153 + 0.23253031962984194 + 0.23253663256303417 + 0.23254294566669473 + 0.23254925894083084 + 0.23255557238544877 + 0.23256188600055433 + 0.23256819978615501 + 0.23257451374225663 + 0.23258082786886652 + 0.23258714216599027 + 0.23259345663363495 + 0.23259977127180737 + 0.23260608608051345 + 0.23261240105975986 + 0.23261871620955399 + 0.23262503152990113 + 0.23263134702080862 + 0.23263766268228253 + 0.23264397851432952 + 0.23265029451695618 + 0.2326566106901693 + 0.23266292703397476 + 0.23266924354838051 + 0.23267556023339139 + 0.23268187708901472 + 0.23268819411525712 + 0.2326945113121246 + 0.23270082867962447 + 0.23270714621776281 + 0.23271346392654624 + 0.23271978180598143 + 0.23272609985607506 + 0.23273241807683323 + 0.23273873646826249 + 0.23274505503036963 + 0.23275137376316118 + 0.23275769266664384 + 0.23276401174082373 + 0.2327703309857081 + 0.23277665040130244 + 0.23278296998761391 + 0.23278928974464932 + 0.23279560967241464 + 0.23280192977091704 + 0.2328082500401622 + 0.23281457048015788 + 0.23282089109090892 + 0.23282721187242381 + 0.23283353282470803 + 0.23283985394776768 + 0.23284617524161058 + 0.23285249670624222 + 0.2328588183416698 + 0.2328651401478995 + 0.23287146212493787 + 0.23287778427279171 + 0.23288410659146758 + 0.2328904290809716 + 0.23289675174131044 + 0.23290307457249132 + 0.23290939757451981 + 0.23291572074740316 + 0.23292204409114733 + 0.23292836760575972 + 0.23293469129124689 + 0.23294101514761387 + 0.2329473391748684 + 0.23295366337301776 + 0.23295998774206689 + 0.23296631228202302 + 0.23297263699289286 + 0.232978961874683 + 0.2329852869274002 + 0.23299161215104996 + 0.23299793754564066 + 0.2330042631111767 + 0.23301058884766634 + 0.2330169147551153 + 0.23302324083353015 + 0.23302956708291753 + 0.2330358935032848 + 0.23304222009463735 + 0.2330485468569819 + 0.23305487379032638 + 0.23306120089467555 + 0.23306752817003684 + 0.23307385561641683 + 0.2330801832338216 + 0.23308651102225847 + 0.23309283898173294 + 0.23309916711225281 + 0.23310549541382419 + 0.23311182388645321 + 0.23311815253014659 + 0.2331244813449114 + 0.23313081033075342 + 0.23313713948768025 + 0.23314346881569753 + 0.23314979831481195 + 0.23315612798503016 + 0.23316245782635941 + 0.23316878783880524 + 0.23317511802237434 + 0.2331814483770745 + 0.23318777890291076 + 0.23319410959989031 + 0.23320044046801983 + 0.23320677150730601 + 0.23321310271775497 + 0.2332194340993734 + 0.23322576565216793 + 0.23323209737614531 + 0.23323842927131222 + 0.23324476133767472 + 0.23325109357523949 + 0.23325742598401325 + 0.23326375856400272 + 0.23327009131521451 + 0.23327642423765474 + 0.23328275733133022 + 0.23328909059624797 + 0.2332954240324138 + 0.23330175763983424 + 0.23330809141851711 + 0.23331442536846739 + 0.23332075948969244 + 0.23332709378219937 + 0.23333342824599387 + 0.23333976288108252 + 0.23334609768747261 + 0.23335243266516975 + 0.23335876781418174 + 0.233365103134514 + 0.23337143862617338 + 0.23337777428916706 + 0.23338411012350127 + 0.23339044612918253 + 0.23339678230621708 + 0.23340311865461219 + 0.23340945517437386 + 0.23341579186550895 + 0.23342212872802395 + 0.2334284657619258 + 0.23343480296722038 + 0.23344114034391514 + 0.23344747789201548 + 0.23345381561152936 + 0.23346015350246174 + 0.23346649156482097 + 0.23347282979861264 + 0.2334791682038434 + 0.23348550678052005 + 0.23349184552864866 + 0.23349818444823642 + 0.23350452353929016 + 0.23351086280181538 + 0.23351720223581984 + 0.23352354184130925 + 0.23352988161829016 + 0.23353622156676995 + 0.23354256168675466 + 0.23354890197825101 + 0.23355524244126519 + 0.23356158307580507 + 0.23356792388187547 + 0.23357426485948438 + 0.23358060600863728 + 0.23358694732934152 + 0.23359328882160368 + 0.23359963048543 + 0.23360597232082719 + 0.23361231432780247 + 0.23361865650636138 + 0.23362499885651067 + 0.23363134137825764 + 0.23363768407160834 + 0.23364402693656952 + 0.23365036997314789 + 0.23365671318134956 + 0.23366305656118128 + 0.23366940011265025 + 0.2336757438357627 + 0.23368208773052532 + 0.23368843179694415 + 0.233694776035026 + 0.23370112044477803 + 0.23370746502620598 + 0.23371380977931758 + 0.23372015470411844 + 0.23372649980061522 + 0.23373284506881525 + 0.23373919050872408 + 0.23374553612034957 + 0.23375188190369667 + 0.23375822785877387 + 0.23376457398558612 + 0.23377092028414126 + 0.23377726675444493 + 0.23378361339650439 + 0.23378996021032575 + 0.23379630719591635 + 0.23380265435328218 + 0.23380900168242957 + 0.23381534918336566 + 0.23382169685609674 + 0.23382804470062996 + 0.23383439271697154 + 0.23384074090512763 + 0.23384708926510545 + 0.23385343779691173 + 0.2338597865005527 + 0.23386613537603498 + 0.2338724844233647 + 0.23387883364254983 + 0.23388518303359587 + 0.23389153259650952 + 0.23389788233129757 + 0.23390423223796664 + 0.23391058231652298 + 0.2339169325669738 + 0.23392328298932585 + 0.23392963358358476 + 0.23393598434975829 + 0.23394233528785208 + 0.23394868639787283 + 0.23395503767982789 + 0.23396138913372275 + 0.23396774075956533 + 0.23397409255736176 + 0.23398044452711758 + 0.2339867966688407 + 0.23399314898253792 + 0.23399950146821469 + 0.23400585412587835 + 0.2340122069555351 + 0.23401855995719156 + 0.23402491313085513 + 0.23403126647653189 + 0.23403761999422809 + 0.23404397368395088 + 0.23405032754570657 + 0.2340566815795018 + 0.2340630357853439 + 0.23406939016323838 + 0.23407574471319206 + 0.23408209943521216 + 0.23408845432930492 + 0.23409480939547705 + 0.2341011646337352 + 0.234107520044085 + 0.23411387562653499 + 0.23412023138109067 + 0.23412658730775812 + 0.23413294340654534 + 0.23413929967745784 + 0.23414565612050239 + 0.23415201273568578 + 0.23415836952301516 + 0.23416472648249628 + 0.23417108361413577 + 0.2341774409179409 + 0.23418379839391856 + 0.23419015604207419 + 0.23419651386241519 + 0.2342028718549482 + 0.23420923001967892 + 0.23421558835661574 + 0.23422194686576372 + 0.23422830554713006 + 0.23423466440072099 + 0.23424102342654385 + 0.23424738262460482 + 0.23425374199491059 + 0.23426010153746787 + 0.23426646125228348 + 0.23427282113936343 + 0.23427918119871463 + 0.2342855414303438 + 0.23429190183425758 + 0.23429826241046275 + 0.23430462315896552 + 0.23431098407977255 + 0.23431734517289074 + 0.23432370643832659 + 0.23433006787608704 + 0.23433642948617817 + 0.23434279126860735 + 0.2343491532233801 + 0.23435551535050381 + 0.23436187764998517 + 0.23436824012183094 + 0.23437460276604724 + 0.23438096558264035 + 0.23438732857161815 + 0.23439369173298608 + 0.23440005506675163 + 0.23440641857292091 + 0.23441278225150067 + 0.23441914610249767 + 0.23442551012591858 + 0.23443187432176971 + 0.23443823869005764 + 0.23444460323078983 + 0.23445096794397186 + 0.23445733282961093 + 0.23446369788771396 + 0.23447006311828647 + 0.23447642852133635 + 0.23448279409686973 + 0.23448915984489346 + 0.23449552576541369 + 0.23450189185843709 + 0.23450825812397105 + 0.23451462456202121 + 0.23452099117259542 + 0.23452735795569865 + 0.23453372491133892 + 0.23454009203952239 + 0.23454645934025573 + 0.23455282681354575 + 0.2345591944593986 + 0.23456556227782169 + 0.23457193026882109 + 0.2345782984324036 + 0.2345846667685754 + 0.23459103527734382 + 0.23459740395871564 + 0.2346037728126964 + 0.23461014183929413 + 0.23461651103851427 + 0.23462288041036428 + 0.23462924995485032 + 0.23463561967197907 + 0.234641989561758 + 0.23464835962419262 + 0.23465472985929026 + 0.23466110026705711 + 0.23466747084749998 + 0.23467384160062621 + 0.23468021252644128 + 0.23468658362495265 + 0.23469295489616654 + 0.23469932634008958 + 0.23470569795672924 + 0.23471206974609099 + 0.23471844170818226 + 0.23472481384300917 + 0.23473118615057861 + 0.23473755863089779 + 0.23474393128397239 + 0.23475030410980977 + 0.23475667710841602 + 0.23476305027979855 + 0.23476942362396294 + 0.23477579714091718 + 0.23478217083066683 + 0.23478854469321864 + 0.23479491872857999 + 0.23480129293675706 + 0.23480766731775657 + 0.23481404187158481 + 0.23482041659824898 + 0.2348267914977554 + 0.23483316657011086 + 0.23483954181532196 + 0.23484591723339565 + 0.23485229282433803 + 0.23485866858815585 + 0.23486504452485649 + 0.23487142063444563 + 0.23487779691693053 + 0.23488417337231796 + 0.23489055000061421 + 0.23489692680182594 + 0.23490330377596 + 0.2349096809230225 + 0.2349160582430215 + 0.23492243573596186 + 0.23492881340185165 + 0.23493519124069648 + 0.23494156925250365 + 0.23494794743727998 + 0.23495432579503167 + 0.23496070432576541 + 0.23496708302948868 + 0.23497346190620641 + 0.23497984095592714 + 0.2349862201786565 + 0.23499259957440133 + 0.23499897914316836 + 0.23500535888496374 + 0.23501173879979487 + 0.23501811888766858 + 0.23502449914859097 + 0.23503087958256824 + 0.23503726018960847 + 0.23504364096971714 + 0.23505002192290117 + 0.23505640304916775 + 0.2350627843485226 + 0.23506916582097356 + 0.23507554746652648 + 0.23508192928518792 + 0.23508831127696533 + 0.23509469344186429 + 0.23510107577989284 + 0.2351074582910565 + 0.23511384097536214 + 0.235120223832817 + 0.2351266068634269 + 0.23513299006719959 + 0.23513937344414076 + 0.23514575699425724 + 0.23515214071755636 + 0.23515852461404438 + 0.23516490868372797 + 0.23517129292661348 + 0.23517767734270814 + 0.23518406193201827 + 0.23519044669455061 + 0.23519683163031133 + 0.23520321673930847 + 0.23520960202154759 + 0.23521598747703545 + 0.23522237310577956 + 0.23522875890778541 + 0.23523514488306041 + 0.2352415310316108 + 0.23524791735344386 + 0.23525430384856535 + 0.2352606905169832 + 0.235267077358703 + 0.23527346437373209 + 0.23527985156207673 + 0.23528623892374428 + 0.23529262645874041 + 0.23529901416707247 + 0.23530540204874661 + 0.23531179010377032 + 0.23531817833214969 + 0.23532456673389107 + 0.23533095530900228 + 0.23533734405748907 + 0.23534373297935821 + 0.23535012207461706 + 0.23535651134327118 + 0.23536290078532807 + 0.23536929040079452 + 0.23537568018967667 + 0.23538207015198132 + 0.23538846028771596 + 0.23539485059688606 + 0.23540124107949861 + 0.23540763173556081 + 0.23541402256507907 + 0.23542041356806004 + 0.2354268047445105 + 0.23543319609443739 + 0.23543958761784681 + 0.23544597931474562 + 0.23545237118514059 + 0.23545876322903861 + 0.23546515544644578 + 0.23547154783736957 + 0.23547794040181622 + 0.23548433313979242 + 0.235490726051305 + 0.23549711913636087 + 0.2355035123949662 + 0.23550990582712775 + 0.23551629943285238 + 0.23552269321214747 + 0.23552908716501803 + 0.23553548129147267 + 0.23554187559151646 + 0.23554827006515733 + 0.235554664712401 + 0.23556105953325468 + 0.2355674545277254 + 0.23557384969581871 + 0.23558024503754249 + 0.2355866405529031 + 0.23559303624190675 + 0.23559943210456077 + 0.23560582814087147 + 0.23561222435084617 + 0.23561862073449055 + 0.23562501729181198 + 0.2356314140228167 + 0.23563781092751215 + 0.23564420800590455 + 0.23565060525800005 + 0.23565700268380674 + 0.23566340028333016 + 0.23566979805657717 + 0.23567619600355524 + 0.23568259412426995 + 0.23568899241872862 + 0.23569539088693817 + 0.23570178952890483 + 0.23570818834463544 + 0.23571458733413675 + 0.23572098649741555 + 0.23572738583447878 + 0.23573378534533199 + 0.2357401850299832 + 0.23574658488843866 + 0.23575298492070509 + 0.23575938512678887 + 0.23576578550669733 + 0.23577218606043676 + 0.23577858678801383 + 0.23578498768943554 + 0.23579138876470804 + 0.23579779001383874 + 0.2358041914368339 + 0.23581059303370033 + 0.23581699480444482 + 0.23582339674907365 + 0.23582979886759423 + 0.23583620116001278 + 0.23584260362633672 + 0.2358490062665711 + 0.23585540908072453 + 0.23586181206880258 + 0.23586821523081222 + 0.23587461856676073 + 0.23588102207665387 + 0.23588742576049898 + 0.23589382961830235 + 0.23590023365007132 + 0.2359066378558122 + 0.23591304223553122 + 0.2359194467892364 + 0.23592585151693329 + 0.23593225641862883 + 0.23593866149432979 + 0.23594506674404306 + 0.23595147216777543 + 0.23595787776553317 + 0.23596428353732363 + 0.23597068948315253 + 0.23597709560302785 + 0.23598350189695527 + 0.23598990836494282 + 0.2359963150069955 + 0.23600272182312074 + 0.23600912881332603 + 0.2360155359776169 + 0.23602194331600093 + 0.23602835082848431 + 0.23603475851507377 + 0.2360411663757763 + 0.23604757441059868 + 0.2360539826195471 + 0.23606039100262907 + 0.2360667995598508 + 0.23607320829121961 + 0.23607961719674136 + 0.23608602627642281 + 0.23609243553027134 + 0.23609884495829322 + 0.23610525456049533 + 0.23611166433688444 + 0.23611807428746678 + 0.23612448441224992 + 0.23613089471124002 + 0.23613730518444445 + 0.23614371583186902 + 0.23615012665352109 + 0.23615653764940678 + 0.23616294881953317 + 0.23616936016390755 + 0.23617577168253559 + 0.23618218337542471 + 0.23618859524258187 + 0.23619500728401316 + 0.23620141949972492 + 0.23620783188972519 + 0.23621424445402026 + 0.23622065719261626 + 0.23622707010552008 + 0.23623348319273865 + 0.23623989645427868 + 0.23624630989014775 + 0.23625272350035087 + 0.236259137284896 + 0.23626555124378956 + 0.23627196537703821 + 0.23627837968464832 + 0.23628479416662734 + 0.2362912088229821 + 0.23629762365371818 + 0.23630403865884372 + 0.23631045383836441 + 0.23631686919228756 + 0.23632328472061953 + 0.23632970042336776 + 0.23633611630053789 + 0.23634253235213734 + 0.23634894857817298 + 0.23635536497865117 + 0.23636178155357918 + 0.23636819830296288 + 0.23637461522680953 + 0.236381032325126 + 0.23638744959791869 + 0.23639386704519438 + 0.23640028466696045 + 0.23640670246322268 + 0.23641312043398846 + 0.23641953857926468 + 0.23642595689905696 + 0.23643237539337283 + 0.23643879406221968 + 0.23644521290560316 + 0.23645163192353072 + 0.23645805111600871 + 0.23646447048304392 + 0.23647089002464267 + 0.23647730974081296 + 0.23648372963156042 + 0.23649014969689197 + 0.23649656993681512 + 0.23650299035133546 + 0.23650941094046041 + 0.23651583170419696 + 0.23652225264255064 + 0.23652867375553016 + 0.23653509504314013 + 0.23654151650538902 + 0.2365479381422825 + 0.23655435995382812 + 0.23656078194003161 + 0.23656720410090082 + 0.23657362643644161 + 0.2365800489466614 + 0.23658647163156701 + 0.23659289449116411 + 0.23659931752546021 + 0.23660574073446278 + 0.23661216411817684 + 0.23661858767661106 + 0.23662501140977052 + 0.23663143531766334 + 0.23663785940029519 + 0.23664428365767343 + 0.23665070808980443 + 0.23665713269669564 + 0.23666355747835272 + 0.23666998243478315 + 0.23667640756599373 + 0.23668283287199143 + 0.23668925835278193 + 0.23669568400837324 + 0.23670210983877168 + 0.23670853584398344 + 0.2367149620240161 + 0.23672138837887591 + 0.23672781490856962 + 0.23673424161310427 + 0.23674066849248607 + 0.23674709554672307 + 0.2367535227758204 + 0.23675995017978604 + 0.2367663777586258 + 0.23677280551234708 + 0.23677923344095675 + 0.2367856615444611 + 0.23679208982286765 + 0.23679851827618198 + 0.23680494690441112 + 0.23681137570756294 + 0.23681780468564273 + 0.23682423383865897 + 0.23683066316661691 + 0.23683709266952338 + 0.23684352234738645 + 0.23684995220021113 + 0.23685638222800559 + 0.23686281243077614 + 0.23686924280852897 + 0.23687567336127158 + 0.23688210408901095 + 0.23688853499175319 + 0.23689496606950536 + 0.23690139732227422 + 0.23690782875006611 + 0.23691426035288851 + 0.23692069213074771 + 0.23692712408365055 + 0.23693355621160395 + 0.2369399885146142 + 0.23694642099268878 + 0.2369528536458346 + 0.23695928647405728 + 0.23696571947736497 + 0.23697215265576335 + 0.23697858600925925 + 0.23698501953786022 + 0.23699145324157198 + 0.23699788712040251 + 0.23700432117435821 + 0.23701075540344527 + 0.23701718980767061 + 0.2370236243870418 + 0.23703005914156444 + 0.23703649407124608 + 0.23704292917609351 + 0.23704936445611313 + 0.23705579991131179 + 0.23706223554169636 + 0.23706867134727383 + 0.23707510732805095 + 0.23708154348403415 + 0.23708797981523017 + 0.23709441632164607 + 0.23710085300328865 + 0.23710728986016474 + 0.23711372689228083 + 0.23712016409964368 + 0.2371266014822602 + 0.23713303904013722 + 0.23713947677328179 + 0.23714591468170007 + 0.237152352765399 + 0.23715879102438611 + 0.23716522945866716 + 0.23717166806824946 + 0.23717810685313948 + 0.23718454581334458 + 0.23719098494887123 + 0.23719742425972559 + 0.23720386374591573 + 0.23721030340744748 + 0.23721674324432773 + 0.23722318325656322 + 0.23722962344416107 + 0.23723606380712803 + 0.23724250434547101 + 0.23724894505919641 + 0.23725538594831105 + 0.23726182701282125 + 0.23726826825273512 + 0.23727470966805836 + 0.23728115125879845 + 0.23728759302496177 + 0.23729403496655455 + 0.23730047708358493 + 0.23730691937605861 + 0.23731336184398305 + 0.23731980448736403 + 0.23732624730620963 + 0.23733269030052609 + 0.23733913347031982 + 0.23734557681559826 + 0.23735202033636715 + 0.23735846403263461 + 0.2373649079044069 + 0.23737135195169098 + 0.23737779617449253 + 0.23738424057282029 + 0.23739068514667927 + 0.23739712989607714 + 0.23740357482102067 + 0.23741001992151622 + 0.23741646519757134 + 0.23742291064919169 + 0.23742935627638542 + 0.23743580207915824 + 0.2374422480575176 + 0.23744869421146989 + 0.23745514054102254 + 0.23746158704618139 + 0.23746803372695388 + 0.23747448058334628 + 0.23748092761536613 + 0.23748737482302038 + 0.23749382220631474 + 0.23750026976525679 + 0.23750671749985269 + 0.23751316541010997 + 0.23751961349603512 + 0.23752606175763491 + 0.23753251019491631 + 0.23753895880788564 + 0.23754540759655038 + 0.23755185656091685 + 0.23755830570099265 + 0.2375647550167834 + 0.23757120450829666 + 0.23757765417553872 + 0.23758410401851657 + 0.23759055403723772 + 0.23759700423170788 + 0.23760345460193444 + 0.23760990514792449 + 0.23761635586968433 + 0.23762280676722086 + 0.23762925784054034 + 0.2376357090896509 + 0.23764216051455844 + 0.23764861211527022 + 0.23765506389179278 + 0.23766151584413228 + 0.23766796797229642 + 0.23767442027629196 + 0.23768087275612532 + 0.23768732541180401 + 0.23769377824333374 + 0.23770023125072207 + 0.23770668443397583 + 0.23771313779310208 + 0.23771959132810647 + 0.23772604503899708 + 0.23773249892577974 + 0.23773895298846198 + 0.23774540722705004 + 0.23775186164155154 + 0.23775831623197216 + 0.23776477099832 + 0.23777122594060085 + 0.23777768105882222 + 0.23778413635299039 + 0.23779059182311177 + 0.2377970474691945 + 0.23780350329124483 + 0.23780995928926912 + 0.237816415463275 + 0.23782287181326803 + 0.23782932833925594 + 0.23783578504124606 + 0.23784224191924369 + 0.23784869897325742 + 0.23785515620329253 + 0.23786161360935645 + 0.23786807119145617 + 0.23787452894959799 + 0.23788098688379006 + 0.23788744499403694 + 0.23789390328034798 + 0.23790036174272822 + 0.23790682038118466 + 0.23791327919572489 + 0.23791973818635517 + 0.23792619735308307 + 0.23793265669591432 + 0.2379391162148565 + 0.23794557590991594 + 0.2379520357810995 + 0.23795849582841475 + 0.23796495605186749 + 0.23797141645146522 + 0.23797787702721487 + 0.23798433777912281 + 0.237990798707196 + 0.23799725981144079 + 0.23800372109186521 + 0.23801018254847514 + 0.23801664418127802 + 0.23802310599028023 + 0.23802956797548813 + 0.2380360301369093 + 0.23804249247455062 + 0.23804895498841902 + 0.23805541767852029 + 0.23806188054486258 + 0.2380683435874516 + 0.238074806806295 + 0.23808127020139902 + 0.23808773377277115 + 0.23809419752041733 + 0.23810066144434494 + 0.23810712554456101 + 0.2381135898210725 + 0.23812005427388563 + 0.23812651890300693 + 0.23813298370844441 + 0.23813944869020398 + 0.23814591384829301 + 0.23815237918271787 + 0.23815884469348625 + 0.23816531038060382 + 0.23817177624407809 + 0.23817824228391551 + 0.23818470850012347 + 0.23819117489270852 + 0.23819764146167693 + 0.2382041082070368 + 0.23821057512879393 + 0.23821704222695592 + 0.23822350950152846 + 0.23822997695251968 + 0.23823644457993598 + 0.23824291238378381 + 0.23824938036406995 + 0.23825584852080203 + 0.23826231685398647 + 0.2382687853636295 + 0.23827525404973882 + 0.23828172291232128 + 0.23828819195138326 + 0.23829466116693174 + 0.23830113055897367 + 0.23830760012751603 + 0.23831406987256509 + 0.23832053979412796 + 0.23832700989221153 + 0.23833348016682332 + 0.23833995061796914 + 0.23834642124565592 + 0.23835289204989116 + 0.23835936303068139 + 0.238365834188034 + 0.2383723055219549 + 0.238378777032451 + 0.23838524871952976 + 0.23839172058319771 + 0.23839819262346171 + 0.23840466484032868 + 0.23841113723380516 + 0.23841760980389856 + 0.23842408255061531 + 0.23843055547396236 + 0.23843702857394661 + 0.23844350185057459 + 0.23844997530385434 + 0.238456448933791 + 0.23846292274039288 + 0.23846939672366563 + 0.2384758708836168 + 0.23848234522025283 + 0.23848881973358135 + 0.23849529442360853 + 0.23850176929034153 + 0.23850824433378662 + 0.23851471955395137 + 0.23852119495084281 + 0.23852767052446672 + 0.23853414627483119 + 0.23854062220194203 + 0.23854709830580678 + 0.2385535745864325 + 0.23856005104382488 + 0.23856652767799211 + 0.23857300448894 + 0.23857948147667607 + 0.23858595864120735 + 0.2385924359825396 + 0.23859891350068094 + 0.23860539119563787 + 0.2386118690674166 + 0.23861834711602481 + 0.23862482534146881 + 0.23863130374375574 + 0.23863778232289234 + 0.23864426107888578 + 0.23865074001174291 + 0.23865721912146962 + 0.23866369840807397 + 0.23867017787156244 + 0.23867665751194134 + 0.23868313732921889 + 0.2386896173234003 + 0.23869609749449364 + 0.23870257784250479 + 0.23870905836744191 + 0.23871553906931076 + 0.23872201994811829 + 0.23872850100387222 + 0.23873498223657871 + 0.23874146364624432 + 0.23874794523287665 + 0.2387544269964825 + 0.23876090893706844 + 0.23876739105464134 + 0.23877387334920891 + 0.23878035582077611 + 0.23878683846935139 + 0.23879332129494149 + 0.2387998042975524 + 0.23880628747719226 + 0.23881277083386676 + 0.23881925436758356 + 0.23882573807834903 + 0.23883222196617074 + 0.2388387060310545 + 0.23884519027300788 + 0.23885167469203794 + 0.23885815928815093 + 0.23886464406135402 + 0.23887112901165469 + 0.2388776141390587 + 0.23888409944357369 + 0.23889058492520659 + 0.23889707058396334 + 0.23890355641985198 + 0.23891004243287836 + 0.23891652862305066 + 0.23892301499037411 + 0.23892950153485748 + 0.23893598825650592 + 0.2389424751553271 + 0.23894896223132794 + 0.23895544948451486 + 0.23896193691489545 + 0.23896842452247619 + 0.23897491230726395 + 0.23898140026926518 + 0.23898788840848803 + 0.23899437672493781 + 0.2390008652186226 + 0.23900735388954891 + 0.23901384273772358 + 0.23902033176315318 + 0.23902682096584518 + 0.23903331034580602 + 0.23903979990304275 + 0.2390462896375628 + 0.23905277954937165 + 0.23905926963847784 + 0.23906575990488674 + 0.23907225034860641 + 0.23907874096964274 + 0.23908523176800392 + 0.23909172274369572 + 0.2390982138967252 + 0.23910470522709934 + 0.23911119673482575 + 0.23911768841991016 + 0.23912418028236024 + 0.23913067232218238 + 0.23913716453938363 + 0.23914365693397091 + 0.23915014950595181 + 0.23915664225533168 + 0.23916313518211918 + 0.2391696282863196 + 0.23917612156794105 + 0.23918261502699006 + 0.23918910866347298 + 0.23919560247739743 + 0.23920209646876978 + 0.23920859063759703 + 0.23921508498388622 + 0.23922157950764436 + 0.2392280742088779 + 0.23923456908759438 + 0.23924106414380028 + 0.23924755937750253 + 0.23925405478870815 + 0.23926055037742358 + 0.23926704614365646 + 0.23927354208741314 + 0.23928003820870064 + 0.23928653450752602 + 0.2392930309838957 + 0.23929952763781723 + 0.23930602446929702 + 0.23931252147834212 + 0.23931901866495958 + 0.2393255160291563 + 0.23933201357093939 + 0.23933851129031528 + 0.23934500918729029 + 0.23935150726187276 + 0.23935800551406899 + 0.23936450394388545 + 0.23937100255132912 + 0.23937750133640767 + 0.23938400029912693 + 0.23939049943949509 + 0.23939699875751794 + 0.23940349825320306 + 0.23940999792655634 + 0.23941649777758603 + 0.23942299780629786 + 0.23942949801270016 + 0.23943599839679863 + 0.23944249895860037 + 0.23944899969811234 + 0.2394555006153416 + 0.23946200171029519 + 0.23946850298297953 + 0.23947500443340214 + 0.23948150606156962 + 0.23948800786748828 + 0.23949450985116635 + 0.23950101201260965 + 0.23950751435182577 + 0.23951401686882068 + 0.23952051956360243 + 0.23952702243617757 + 0.23953352548655246 + 0.23954002871473473 + 0.23954653212073088 + 0.23955303570454778 + 0.23955953946619202 + 0.23956604340567181 + 0.23957254752299284 + 0.23957905181816225 + 0.23958555629118758 + 0.23959206094207483 + 0.2395985657708315 + 0.2396050707774646 + 0.23961157596198057 + 0.23961808132438658 + 0.23962458686469004 + 0.23963109258289692 + 0.23963759847901425 + 0.2396441045530496 + 0.23965061080501004 + 0.23965711723490141 + 0.23966362384273138 + 0.23967013062850687 + 0.23967663759223495 + 0.23968314473392152 + 0.23968965205357479 + 0.23969615955120055 + 0.23970266722680703 + 0.23970917508040013 + 0.23971568311198685 + 0.23972219132157424 + 0.23972869970916927 + 0.23973520827477909 + 0.23974171701841065 + 0.23974822594007039 + 0.23975473503976599 + 0.23976124431750329 + 0.23976775377328988 + 0.23977426340713284 + 0.2397807732190386 + 0.23978728320901413 + 0.23979379337706719 + 0.23980030372320357 + 0.23980681424743083 + 0.23981332494975616 + 0.2398198358301859 + 0.23982634688872712 + 0.23983285812538679 + 0.23983936954017207 + 0.23984588113308938 + 0.23985239290414631 + 0.23985890485334929 + 0.2398654169807054 + 0.23987192928622111 + 0.23987844176990469 + 0.23988495443176183 + 0.23989146727179916 + 0.23989798029002535 + 0.2399044934864458 + 0.23991100686106753 + 0.23991752041389808 + 0.23992403414494456 + 0.23993054805421285 + 0.23993706214171112 + 0.23994357640744537 + 0.23995009085142305 + 0.23995660547365075 + 0.23996312027413538 + 0.23996963525288478 + 0.23997615040990469 + 0.23998266574520213 + 0.23998918125878482 + 0.23999569695065975 + 0.24000221282083284 + 0.24000872886931168 + 0.24001524509610336 + 0.2400217615012149 + 0.24002827808465221 + 0.24003479484642343 + 0.24004131178653512 + 0.24004782890499368 + 0.24005434620180674 + 0.24006086367698146 + 0.24006738133052363 + 0.24007389916244087 + 0.24008041717274084 + 0.24008693536142947 + 0.24009345372851376 + 0.24009997227400079 + 0.24010649099789821 + 0.24011300990021184 + 0.24011952898094932 + 0.24012604824011721 + 0.24013256767772309 + 0.24013908729377345 + 0.24014560708827534 + 0.24015212706123584 + 0.24015864721266131 + 0.24016516754255895 + 0.24017168805093572 + 0.2401782087377993 + 0.24018472960315562 + 0.24019125064701224 + 0.24019777186937571 + 0.24020429327025358 + 0.24021081484965184 + 0.2402173366075781 + 0.24022385854404002 + 0.24023038065904284 + 0.24023690295259478 + 0.24024342542470248 + 0.24024994807537281 + 0.24025647090461233 + 0.24026299391242875 + 0.24026951709882841 + 0.24027604046381904 + 0.24028256400740716 + 0.24028908772959914 + 0.24029561163040217 + 0.24030213570982431 + 0.24030865996787104 + 0.24031518440455055 + 0.24032170901986866 + 0.24032823381383309 + 0.24033475878645094 + 0.240341283937728 + 0.24034780926767257 + 0.24035433477629117 + 0.24036086046359076 + 0.24036738632957791 + 0.24037391237425967 + 0.24038043859764371 + 0.24038696499973589 + 0.24039349158054385 + 0.24040001834007529 + 0.24040654527833555 + 0.24041307239533219 + 0.24041959969107299 + 0.24042612716556369 + 0.24043265481881212 + 0.2404391826508252 + 0.24044571066160894 + 0.24045223885117153 + 0.24045876721951956 + 0.2404652957666599 + 0.24047182449259921 + 0.2404783533973445 + 0.24048488248090347 + 0.24049141174328253 + 0.24049794118448822 + 0.24050447080452819 + 0.24051100060340888 + 0.24051753058113812 + 0.24052406073772162 + 0.24053059107316779 + 0.24053712158748239 + 0.24054365228067323 + 0.24055018315274665 + 0.2405567142037098 + 0.24056324543356986 + 0.24056977684233366 + 0.24057630843000796 + 0.2405828401966002 + 0.24058937214211704 + 0.24059590426656499 + 0.24060243656995214 + 0.24060896905228452 + 0.24061550171356977 + 0.24062203455381434 + 0.24062856757302539 + 0.24063510077120995 + 0.2406416341483745 + 0.24064816770452677 + 0.24065470143967388 + 0.24066123535382161 + 0.24066776944697826 + 0.2406743037191498 + 0.2406808381703433 + 0.24068737280056643 + 0.24069390760982623 + 0.24070044259812859 + 0.24070697776548131 + 0.24071351311189138 + 0.24072004863736532 + 0.2407265843419108 + 0.24073312022553378 + 0.24073965628824248 + 0.24074619253004273 + 0.24075272895094241 + 0.24075926555094782 + 0.24076580233006617 + 0.24077233928830449 + 0.24077887642566997 + 0.240785413742169 + 0.24079195123780933 + 0.24079848891259742 + 0.24080502676654031 + 0.24081156479964527 + 0.24081810301191917 + 0.24082464140336868 + 0.24083117997400089 + 0.24083771872382334 + 0.24084425765284215 + 0.2408507967610648 + 0.24085733604849852 + 0.24086387551514973 + 0.24087041516102564 + 0.24087695498613323 + 0.24088349499047965 + 0.24089003517407204 + 0.24089657553691682 + 0.24090311607902115 + 0.24090965680039206 + 0.24091619770103673 + 0.24092273878096218 + 0.24092928004017505 + 0.24093582147868287 + 0.2409423630964922 + 0.24094890489360968 + 0.24095544687004336 + 0.24096198902579932 + 0.2409685313608847 + 0.24097507387530709 + 0.24098161656907299 + 0.24098815944218893 + 0.24099470249466268 + 0.24100124572650067 + 0.24100778913771065 + 0.24101433272829909 + 0.24102087649827314 + 0.2410274204476392 + 0.24103396457640575 + 0.24104050888457793 + 0.24104705337216353 + 0.24105359803917029 + 0.24106014288560404 + 0.24106668791147251 + 0.24107323311678228 + 0.24107977850154094 + 0.24108632406575514 + 0.24109286980943126 + 0.24109941573257701 + 0.241105961835199 + 0.24111250811730553 + 0.24111905457890129 + 0.24112560121999507 + 0.2411321480405936 + 0.24113869504070379 + 0.24114524222033171 + 0.24115178957948563 + 0.24115833711817203 + 0.241164884836398 + 0.2411714327341701 + 0.24117798081149602 + 0.24118452906838234 + 0.24119107750483607 + 0.2411976261208644 + 0.24120417491647447 + 0.24121072389167275 + 0.24121727304646687 + 0.24122382238086351 + 0.24123037189486976 + 0.24123692158849203 + 0.24124347146173811 + 0.24125002151461511 + 0.24125657174712958 + 0.24126312215928855 + 0.24126967275109926 + 0.24127622352256811 + 0.24128277447370297 + 0.24128932560451016 + 0.24129587691499696 + 0.24130242840517108 + 0.2413089800750384 + 0.24131553192460597 + 0.24132208395388227 + 0.24132863616287251 + 0.24133518855158445 + 0.24134174112002518 + 0.24134829386820189 + 0.2413548467961211 + 0.24136139990379046 + 0.24136795319121654 + 0.24137450665840582 + 0.24138106030536619 + 0.24138761413210452 + 0.24139416813862752 + 0.24140072232494292 + 0.24140727669105655 + 0.24141383123697616 + 0.24142038596270893 + 0.24142694086826136 + 0.24143349595364058 + 0.24144005121885434 + 0.24144660666390846 + 0.24145316228881142 + 0.24145971809356909 + 0.24146627407818802 + 0.24147283024267704 + 0.24147938658704163 + 0.2414859431112894 + 0.24149249981542692 + 0.24149905669946201 + 0.24150561376340104 + 0.24151217100725192 + 0.24151872843102046 + 0.24152528603471377 + 0.24153184381834028 + 0.24153840178190536 + 0.24154495992541716 + 0.24155151824888232 + 0.24155807675230742 + 0.24156463543570017 + 0.24157119429906712 + 0.24157775334241596 + 0.24158431256575261 + 0.24159087196908544 + 0.24159743155242039 + 0.24160399131576521 + 0.24161055125912584 + 0.24161711138251063 + 0.24162367168592602 + 0.24163023216937932 + 0.2416367928328769 + 0.24164335367642656 + 0.24164991470003488 + 0.24165647590370898 + 0.24166303728745545 + 0.24166959885128192 + 0.24167616059519559 + 0.24168272251920297 + 0.24168928462331132 + 0.24169584690752763 + 0.24170240937185911 + 0.24170897201631236 + 0.24171553484089442 + 0.24172209784561305 + 0.24172866103047491 + 0.24173522439548706 + 0.24174178794065596 + 0.24174835166598888 + 0.24175491557149356 + 0.24176147965717648 + 0.24176804392304485 + 0.2417746083691058 + 0.24178117299536528 + 0.24178773780183221 + 0.24179430278851191 + 0.24180086795541281 + 0.24180743330254084 + 0.24181399882990373 + 0.24182056453750858 + 0.24182713042536141 + 0.24183369649347058 + 0.241840262741842 + 0.24184682917048408 + 0.2418533957794021 + 0.2418599625686044 + 0.24186652953809756 + 0.24187309668788881 + 0.24187966401798516 + 0.24188623152839395 + 0.24189279921912149 + 0.24189936709017518 + 0.24190593514156197 + 0.24191250337328915 + 0.24191907178536384 + 0.24192564037779318 + 0.24193220915058317 + 0.24193877810374206 + 0.24194534723727587 + 0.24195191655119305 + 0.24195848604549941 + 0.24196505572020216 + 0.24197162557530907 + 0.2419781956108267 + 0.24198476582676165 + 0.24199133622312219 + 0.24199790679991368 + 0.24200447755714519 + 0.24201104849482202 + 0.24201761961295185 + 0.2420241909115414 + 0.2420307623905989 + 0.24203733405013031 + 0.24204390589014288 + 0.24205047791064374 + 0.24205705011164003 + 0.24206362249313892 + 0.24207019505514701 + 0.2420767677976714 + 0.24208334072071991 + 0.24208991382429845 + 0.24209648710841483 + 0.24210306057307626 + 0.24210963421828918 + 0.24211620804406142 + 0.242122782050399 + 0.24212935623731022 + 0.24213593060480049 + 0.24214250515287866 + 0.24214907988155085 + 0.24215565479082352 + 0.24216222988070518 + 0.24216880515120226 + 0.24217538060232133 + 0.24218195623406966 + 0.24218853204645494 + 0.24219510803948377 + 0.24220168421316332 + 0.24220826056750017 + 0.24221483710250202 + 0.24222141381817547 + 0.2422279907145278 + 0.24223456779156605 + 0.24224114504929753 + 0.24224772248772869 + 0.24225430010686727 + 0.24226087790672002 + 0.24226745588729395 + 0.24227403404859629 + 0.24228061239063423 + 0.24228719091341372 + 0.24229376961694374 + 0.24230034850123039 + 0.24230692756628003 + 0.24231350681210057 + 0.24232008623869913 + 0.24232666584608228 + 0.24233324563425734 + 0.24233982560323192 + 0.24234640575301206 + 0.2423529860836055 + 0.2423595665950195 + 0.24236614728726058 + 0.24237272816033534 + 0.24237930921425221 + 0.24238589044901768 + 0.24239247186463839 + 0.24239905346112203 + 0.2424056352384753 + 0.24241221719670475 + 0.24241879933581872 + 0.24242538165582381 + 0.24243196415672605 + 0.24243854683853439 + 0.24244512970125418 + 0.24245171274489319 + 0.24245829596945873 + 0.24246487937495789 + 0.24247146296139727 + 0.24247804672878459 + 0.24248463067712592 + 0.24249121480642907 + 0.24249779911670119 + 0.24250438360794888 + 0.24251096828017984 + 0.24251755313340076 + 0.24252413816761886 + 0.24253072338284054 + 0.24253730877907445 + 0.24254389435632631 + 0.24255048011460353 + 0.2425570660539132 + 0.24256365217426254 + 0.24257023847565806 + 0.24257682495810765 + 0.24258341162161848 + 0.24258999846619653 + 0.24259658549185018 + 0.24260317269858542 + 0.24260976008641008 + 0.24261634765533133 + 0.24262293540535515 + 0.24262952333648996 + 0.24263611144874234 + 0.24264269974211886 + 0.24264928821662735 + 0.24265587687227441 + 0.24266246570906783 + 0.24266905472701367 + 0.24267564392612012 + 0.24268223330639338 + 0.24268882286784063 + 0.24269541261046956 + 0.24270200253428623 + 0.242708592639299 + 0.24271518292551392 + 0.24272177339293885 + 0.24272836404158085 + 0.242734954871446 + 0.24274154588254263 + 0.24274813707487686 + 0.24275472844845639 + 0.24276132000328846 + 0.24276791173937967 + 0.24277450365673728 + 0.24278109575536774 + 0.24278768803527956 + 0.24279428049647872 + 0.24280087313897308 + 0.24280746596276917 + 0.24281405896787425 + 0.2428206521542948 + 0.24282724552203941 + 0.242833839071114 + 0.2428404328015257 + 0.24284702671328184 + 0.24285362080639011 + 0.24286021508085665 + 0.2428668095366886 + 0.24287340417389433 + 0.24287999899247922 + 0.24288659399245119 + 0.242893189173818 + 0.24289978453658573 + 0.2429063800807614 + 0.24291297580635302 + 0.24291957171336703 + 0.24292616780181081 + 0.24293276407169145 + 0.24293936052301554 + 0.24294595715579162 + 0.24295255397002499 + 0.2429591509657236 + 0.24296574814289448 + 0.24297234550154495 + 0.24297894304168216 + 0.24298554076331219 + 0.24299213866644342 + 0.24299873675108313 + 0.24300533501723659 + 0.24301193346491301 + 0.24301853209411822 + 0.24302513090485955 + 0.24303172989714475 + 0.24303832907097986 + 0.24304492842637276 + 0.24305152796333054 + 0.24305812768185997 + 0.24306472758196815 + 0.24307132766366288 + 0.24307792792695027 + 0.24308452837183817 + 0.24309112899833366 + 0.24309772980644342 + 0.24310433079617469 + 0.24311093196753414 + 0.24311753332053007 + 0.24312413485516862 + 0.24313073657145748 + 0.24313733846940341 + 0.24314394054901417 + 0.24315054281029574 + 0.24315714525325541 + 0.24316374787790163 + 0.24317035068423967 + 0.24317695367227812 + 0.24318355684202356 + 0.24319016019348319 + 0.24319676372666366 + 0.24320336744157273 + 0.24320997133821706 + 0.24321657541660455 + 0.24322317967674106 + 0.24322978411863463 + 0.24323638874229231 + 0.2432429935477203 + 0.24324959853492742 + 0.24325620370391926 + 0.24326280905470363 + 0.24326941458728765 + 0.24327602030167805 + 0.24328262619788263 + 0.24328923227590801 + 0.24329583853576145 + 0.24330244497744954 + 0.24330905160098021 + 0.24331565840636055 + 0.24332226539359725 + 0.24332887256269758 + 0.2433354799136688 + 0.24334208744651806 + 0.24334869516125199 + 0.24335530305787845 + 0.24336191113640407 + 0.24336851939683554 + 0.24337512783918186 + 0.24338173646344782 + 0.24338834526964187 + 0.24339495425777075 + 0.2434015634278415 + 0.24340817277986218 + 0.24341478231383865 + 0.24342139202977825 + 0.24342800192768874 + 0.24343461200757741 + 0.24344122226945031 + 0.24344783271331591 + 0.24345444333918009 + 0.24346105414705027 + 0.24346766513693421 + 0.24347427630883858 + 0.24348088766277115 + 0.24348749919873741 + 0.2434941109167465 + 0.24350072281680429 + 0.24350733489891865 + 0.24351394716309571 + 0.24352055960934393 + 0.24352717223766923 + 0.24353378504807957 + 0.2435403980405815 + 0.2435470112151823 + 0.24355362457188989 + 0.24356023811071079 + 0.24356685183165169 + 0.24357346573471994 + 0.24358007981992322 + 0.24358669408726885 + 0.24359330853676292 + 0.2435999231684132 + 0.24360653798222642 + 0.24361315297821098 + 0.24361976815637232 + 0.24362638351671884 + 0.24363299905925676 + 0.24363961478399374 + 0.2436462306909371 + 0.24365284678009355 + 0.2436594630514709 + 0.2436660795050751 + 0.24367269614091419 + 0.24367931295899586 + 0.2436859299593257 + 0.24369254714191202 + 0.24369916450676155 + 0.2437057820538816 + 0.2437123997832793 + 0.24371901769496199 + 0.24372563578893633 + 0.24373225406520949 + 0.24373887252378937 + 0.243745491164682 + 0.24375210998789537 + 0.24375872899343656 + 0.24376534818131232 + 0.24377196755152988 + 0.24377858710409711 + 0.24378520683902008 + 0.24379182675630662 + 0.24379844685596339 + 0.24380506713799829 + 0.24381168760241792 + 0.24381830824922957 + 0.2438249290784405 + 0.24383155009005794 + 0.24383817128408861 + 0.24384479266053971 + 0.24385141421941917 + 0.24385803596073297 + 0.24386465788448908 + 0.24387127999069466 + 0.24387790227935632 + 0.2438845247504815 + 0.24389114740407739 + 0.2438977702401518 + 0.24390439325871019 + 0.24391101645976174 + 0.24391763984331241 + 0.24392426340936951 + 0.24393088715794028 + 0.24393751108903197 + 0.24394413520265201 + 0.24395075949880679 + 0.2439573839775038 + 0.24396400863875073 + 0.24397063348255385 + 0.24397725850892082 + 0.24398388371785909 + 0.2439905091093752 + 0.24399713468347711 + 0.24400376044017086 + 0.24401038637946482 + 0.24401701250136523 + 0.24402363880587985 + 0.24403026529301541 + 0.24403689196277972 + 0.24404351881517888 + 0.24405014585022083 + 0.24405677306791274 + 0.2440634004682613 + 0.24407002805127437 + 0.24407665581695873 + 0.2440832837653216 + 0.24408991189637017 + 0.24409654021011118 + 0.2441031687065526 + 0.24410979738570091 + 0.24411642624756358 + 0.2441230552921477 + 0.24412968451946071 + 0.24413631392950919 + 0.24414294352230106 + 0.24414957329784295 + 0.24415620325614221 + 0.2441628333972061 + 0.24416946372104129 + 0.24417609422765613 + 0.24418272491705631 + 0.24418935578925025 + 0.24419598684424451 + 0.24420261808204594 + 0.24420924950266223 + 0.2442158811061009 + 0.24422251289236843 + 0.24422914486147218 + 0.24423577701341939 + 0.24424240934821748 + 0.24424904186587351 + 0.24425567456639438 + 0.24426230744978725 + 0.24426894051605946 + 0.24427557376521827 + 0.24428220719727092 + 0.24428884081222421 + 0.24429547461008583 + 0.24430210859086274 + 0.2443087427545626 + 0.24431537710119158 + 0.24432201163075695 + 0.24432864634326662 + 0.24433528123872791 + 0.24434191631714677 + 0.24434855157853189 + 0.24435518702288986 + 0.24436182265022727 + 0.24436845846055158 + 0.24437509445387054 + 0.24438173063019089 + 0.24438836698952002 + 0.24439500353186513 + 0.24440164025723346 + 0.24440827716563179 + 0.24441491425706735 + 0.24442155153154752 + 0.2444281889890795 + 0.24443482662967064 + 0.24444146445332762 + 0.2444481024600583 + 0.24445474064986941 + 0.24446137902276824 + 0.2444680175787621 + 0.2444746563178577 + 0.24448129524006285 + 0.24448793434538488 + 0.24449457363383056 + 0.2445012131054066 + 0.24450785276012071 + 0.244514492597981 + 0.2445211326189928 + 0.24452777282316476 + 0.24453441321050348 + 0.24454105378101626 + 0.24454769453471045 + 0.24455433547159275 + 0.24456097659167161 + 0.24456761789495257 + 0.24457425938144353 + 0.24458090105115177 + 0.24458754290408455 + 0.2445941849402487 + 0.24460082715965198 + 0.2446074695623012 + 0.24461411214820367 + 0.24462075491736712 + 0.24462739786979731 + 0.24463404100550254 + 0.24464068432449021 + 0.24464732782676704 + 0.24465397151234025 + 0.24466061538121728 + 0.24466725943340464 + 0.24467390366891043 + 0.24468054808774123 + 0.24468719268990502 + 0.24469383747540788 + 0.24470048244425777 + 0.24470712759646188 + 0.24471377293202698 + 0.24472041845096104 + 0.24472706415327011 + 0.24473371003896263 + 0.24474035610804551 + 0.2447470023605253 + 0.2447536487964099 + 0.24476029541570551 + 0.24476694221842055 + 0.24477358920456185 + 0.24478023637413601 + 0.24478688372715102 + 0.24479353126361411 + 0.24480017898353212 + 0.24480682688691166 + 0.2448134749737613 + 0.24482012324408714 + 0.24482677169789702 + 0.24483342033519778 + 0.24484006915599724 + 0.24484671816030154 + 0.24485336734811861 + 0.24486001671945645 + 0.24486666627432047 + 0.24487331601271914 + 0.2448799659346593 + 0.24488661604014819 + 0.24489326632919317 + 0.24489991680180095 + 0.24490656745797948 + 0.24491321829773541 + 0.24491986932107662 + 0.24492652052800939 + 0.24493317191854164 + 0.24493982349268051 + 0.24494647525043278 + 0.24495312719180592 + 0.24495977931680762 + 0.24496643162544426 + 0.24497308411772417 + 0.24497973679365351 + 0.24498638965323966 + 0.24499304269648992 + 0.2449996959234122 + 0.24500634933401266 + 0.24501300292829978 + 0.24501965670627904 + 0.24502631066795913 + 0.24503296481334721 + 0.24503961914244951 + 0.24504627365527451 + 0.24505292835182832 + 0.24505958323211838 + 0.24506623829615246 + 0.24507289354393738 + 0.24507954897548048 + 0.24508620459078906 + 0.24509286038987044 + 0.24509951637273134 + 0.24510617253937911 + 0.24511282888982169 + 0.24511948542406589 + 0.24512614214211828 + 0.24513279904398685 + 0.24513945612967905 + 0.24514611339920142 + 0.24515277085256143 + 0.24515942848976638 + 0.24516608631082357 + 0.24517274431573979 + 0.24517940250452289 + 0.24518606087718031 + 0.24519271943371809 + 0.24519937817414425 + 0.24520603709846611 + 0.24521269620669095 + 0.24521935549882554 + 0.24522601497487723 + 0.24523267463485393 + 0.24523933447876184 + 0.24524599450660881 + 0.24525265471840219 + 0.24525931511414881 + 0.24526597569385655 + 0.24527263645753147 + 0.2452792974051817 + 0.24528595853681442 + 0.245292619852437 + 0.24529928135205617 + 0.24530594303568001 + 0.24531260490331447 + 0.24531926695496759 + 0.24532592919064672 + 0.24533259161035859 + 0.24533925421411118 + 0.24534591700191111 + 0.24535257997376581 + 0.24535924312968271 + 0.24536590646966894 + 0.2453725699937315 + 0.2453792337018775 + 0.24538589759411508 + 0.24539256167045084 + 0.24539922593089158 + 0.24540589037544588 + 0.24541255500411924 + 0.24541921981692028 + 0.2454258848138563 + 0.24543254999493333 + 0.24543921536015956 + 0.24544588090954217 + 0.24545254664308799 + 0.2454592125608043 + 0.24546587866269909 + 0.2454725449487791 + 0.2454792114190511 + 0.24548587807352359 + 0.24549254491220221 + 0.24549921193509541 + 0.24550587914221009 + 0.24551254653355339 + 0.24551921410913291 + 0.24552588186895521 + 0.24553254981302827 + 0.24553921794135897 + 0.24554588625395454 + 0.24555255475082235 + 0.24555922343197045 + 0.2455658922974043 + 0.24557256134713248 + 0.24557923058116232 + 0.24558589999950006 + 0.24559256960215423 + 0.24559923938913086 + 0.24560590936043805 + 0.24561257951608256 + 0.2456192498560717 + 0.24562592038041348 + 0.24563259108911392 + 0.24563926198218114 + 0.24564593305962243 + 0.24565260432144459 + 0.24565927576765556 + 0.24566594739826206 + 0.24567261921327085 + 0.24567929121268997 + 0.24568596339652676 + 0.24569263576478792 + 0.24569930831748152 + 0.24570598105461361 + 0.24571265397619282 + 0.24571932708222533 + 0.24572600037271908 + 0.2457326738476808 + 0.2457393475071179 + 0.24574602135103835 + 0.24575269537944827 + 0.24575936959235567 + 0.24576604398976726 + 0.24577271857169175 + 0.24577939333813451 + 0.24578606828910368 + 0.24579274342460652 + 0.24579941874465047 + 0.2458060942492428 + 0.24581276993838977 + 0.24581944581209997 + 0.24582612187038011 + 0.24583279811323816 + 0.24583947454067973 + 0.2458461511527133 + 0.24585282794934643 + 0.24585950493058567 + 0.24586618209643857 + 0.24587285944691178 + 0.24587953698201395 + 0.2458862147017512 + 0.24589289260613101 + 0.24589957069516116 + 0.24590624896884863 + 0.24591292742720008 + 0.24591960607022351 + 0.24592628489792634 + 0.24593296391031524 + 0.24593964310739772 + 0.24594632248918105 + 0.24595300205567328 + 0.24595968180688052 + 0.24596636174281014 + 0.24597304186347027 + 0.24597972216886746 + 0.24598640265900928 + 0.24599308333390243 + 0.2459997641935556 + 0.24600644523797474 + 0.24601312646716736 + 0.24601980788114153 + 0.24602648947990391 + 0.2460331712634613 + 0.24603985323182179 + 0.24604653538499255 + 0.24605321772298058 + 0.24605990024579308 + 0.24606658295343817 + 0.24607326584592207 + 0.24607994892325261 + 0.24608663218543658 + 0.24609331563248216 + 0.24609999926439596 + 0.24610668308118541 + 0.24611336708285789 + 0.24612005126942021 + 0.24612673564088028 + 0.24613342019724568 + 0.24614010493852242 + 0.24614678986471913 + 0.24615347497584203 + 0.24616016027189969 + 0.2461668457528976 + 0.24617353141884452 + 0.24618021726974781 + 0.2461869033056136 + 0.24619358952645051 + 0.2462002759322641 + 0.24620696252306354 + 0.24621364929885459 + 0.24622033625964559 + 0.24622702340544353 + 0.24623371073625575 + 0.24624039825208954 + 0.24624708595295186 + 0.24625377383885061 + 0.24626046190979259 + 0.24626715016578457 + 0.24627383860683524 + 0.24628052723295069 + 0.24628721604413906 + 0.24629390504040694 + 0.24630059422176248 + 0.24630728358821249 + 0.24631397313976364 + 0.24632066287642401 + 0.24632735279820042 + 0.24633404290510078 + 0.24634073319713262 + 0.24634742367430204 + 0.24635411433661769 + 0.24636080518408504 + 0.24636749621671353 + 0.24637418743450917 + 0.24638087883747942 + 0.24638757042563164 + 0.24639426219897337 + 0.24640095415751187 + 0.246407646301254 + 0.2464143386302077 + 0.24642103114437991 + 0.24642772384377792 + 0.24643441672840916 + 0.24644110979828099 + 0.24644780305340031 + 0.2464544964937751 + 0.24646119011941153 + 0.24646788393031882 + 0.24647457792650257 + 0.24648127210797022 + 0.24648796647472979 + 0.2464946610267886 + 0.2465013557641535 + 0.2465080506868319 + 0.24651474579483132 + 0.24652144108815899 + 0.24652813656682174 + 0.2465348322308277 + 0.24654152808018368 + 0.24654822411489691 + 0.24655492033497503 + 0.24656161674042529 + 0.24656831333125451 + 0.24657501010747077 + 0.24658170706908092 + 0.24658840421609285 + 0.24659510154851283 + 0.24660179906634891 + 0.2466084967696085 + 0.24661519465829834 + 0.24662189273242588 + 0.24662859099199855 + 0.2466352894370244 + 0.24664198806750953 + 0.24664868688346214 + 0.24665538588488947 + 0.24666208507179846 + 0.24666878444419646 + 0.24667548400209025 + 0.24668218374548859 + 0.24668888367439751 + 0.2466955837888252 + 0.24670228408877845 + 0.24670898457426518 + 0.24671568524529167 + 0.24672238610186659 + 0.24672908714399544 + 0.24673578837168691 + 0.2467424897849485 + 0.24674919138378687 + 0.24675589316820956 + 0.24676259513822399 + 0.24676929729383751 + 0.24677599963505706 + 0.24678270216188997 + 0.24678940487434423 + 0.24679610777242619 + 0.2468028108561437 + 0.246809514125505 + 0.24681621758051553 + 0.24682292122118468 + 0.2468296250475179 + 0.24683632905952332 + 0.24684303325720902 + 0.2468497376405811 + 0.24685644220964706 + 0.24686314696441558 + 0.24686985190489216 + 0.24687655703108491 + 0.24688326234300123 + 0.24688996784064851 + 0.24689667352403433 + 0.24690337939316542 + 0.24691008544804921 + 0.24691679168869371 + 0.24692349811510522 + 0.24693020472729169 + 0.24693691152526062 + 0.24694361850901878 + 0.2469503256785737 + 0.24695703303393327 + 0.24696374057510448 + 0.24697044830209405 + 0.24697715621491007 + 0.24698386431355995 + 0.24699057259805057 + 0.24699728106838931 + 0.24700398972458365 + 0.24701069856664037 + 0.24701740759456819 + 0.24702411680837327 + 0.24703082620806313 + 0.24703753579364571 + 0.24704424556512727 + 0.24705095552251655 + 0.24705766566581899 + 0.24706437599504408 + 0.24707108651019788 + 0.24707779721128784 + 0.2470845080983215 + 0.24709121917130686 + 0.24709793043025011 + 0.24710464187515876 + 0.24711135350604077 + 0.24711806532290309 + 0.24712477732575308 + 0.24713148951459821 + 0.24713820188944594 + 0.24714491445030309 + 0.24715162719717768 + 0.24715834013007665 + 0.24716505324900725 + 0.24717176655397718 + 0.24717848004499374 + 0.24718519372206438 + 0.24719190758519538 + 0.24719862163439602 + 0.24720533586967183 + 0.24721205029103099 + 0.24721876489848144 + 0.24722547969202952 + 0.24723219467168256 + 0.24723890983744876 + 0.24724562518933421 + 0.24725234072734772 + 0.24725905645149601 + 0.24726577236178601 + 0.2472724884582258 + 0.2472792047408221 + 0.24728592120958309 + 0.247292637864515 + 0.24729935470562639 + 0.24730607173292363 + 0.24731278894641467 + 0.24731950634610644 + 0.24732622393200643 + 0.24733294170412196 + 0.24733965966246058 + 0.2473463778070297 + 0.24735309613783685 + 0.24735981465488877 + 0.24736653335819306 + 0.24737325224775764 + 0.24737997132358885 + 0.24738669058569476 + 0.2473934100340828 + 0.24740012966876035 + 0.24740684948973379 + 0.24741356949701176 + 0.24742028969060106 + 0.24742701007050857 + 0.24743373063674232 + 0.2474404513893099 + 0.247447172328218 + 0.24745389345347482 + 0.24746061476508657 + 0.24746733626306122 + 0.2474740579474064 + 0.24748077981812949 + 0.24748750187523677 + 0.24749422411873684 + 0.24750094654863666 + 0.24750766916494354 + 0.24751439196766514 + 0.24752111495680887 + 0.24752783813238094 + 0.24753456149439002 + 0.24754128504284359 + 0.24754800877774796 + 0.24755473269911055 + 0.24756145680693997 + 0.24756818110124262 + 0.24757490558202652 + 0.24758163024929791 + 0.24758835510306484 + 0.24759508014333537 + 0.24760180537011586 + 0.24760853078341372 + 0.24761525638323706 + 0.24762198216959272 + 0.24762870814248816 + 0.24763543430193086 + 0.24764216064792827 + 0.2476488871804873 + 0.24765561389961546 + 0.24766234080532071 + 0.24766906789761003 + 0.24767579517649083 + 0.2476825226419706 + 0.24768925029405628 + 0.24769597813275579 + 0.24770270615807616 + 0.24770943437002482 + 0.24771616276860917 + 0.24772289135383679 + 0.24772962012571456 + 0.24773634908425041 + 0.24774307822945202 + 0.24774980756132547 + 0.24775653707987957 + 0.24776326678512062 + 0.24776999667705663 + 0.24777672675569506 + 0.24778345702104285 + 0.24779018747310738 + 0.2477969181118963 + 0.24780364893741691 + 0.24781037994967683 + 0.24781711114868357 + 0.24782384253444384 + 0.24783057410696518 + 0.24783730586625513 + 0.24784403781232184 + 0.24785076994517136 + 0.24785750226481143 + 0.24786423477125055 + 0.2478709674644945 + 0.247877700344552 + 0.24788443341142985 + 0.24789116666513547 + 0.24789790010567594 + 0.24790463373305865 + 0.24791136754729226 + 0.24791810154838245 + 0.24792483573633739 + 0.24793157011116507 + 0.24793830467287181 + 0.24794503942146512 + 0.24795177435695379 + 0.24795850947934334 + 0.24796524478864251 + 0.24797198028485753 + 0.24797871596799667 + 0.24798545183806728 + 0.24799218789507693 + 0.2479989241390318 + 0.24800566056994069 + 0.24801239718781048 + 0.2480191339926486 + 0.24802587098446199 + 0.24803260816325876 + 0.24803934552904633 + 0.24804608308183168 + 0.24805282082162167 + 0.24805955874842495 + 0.2480662968622479 + 0.24807303516309856 + 0.24807977365098385 + 0.24808651232591186 + 0.24809325118788952 + 0.24809999023692364 + 0.24810672947302298 + 0.24811346889619387 + 0.24812020850644431 + 0.24812694830378138 + 0.24813368828821236 + 0.24814042845974485 + 0.248147168818387 + 0.24815390936414439 + 0.24816065009702637 + 0.24816739101703941 + 0.24817413212419071 + 0.24818087341848799 + 0.24818761489993868 + 0.2481943565685503 + 0.24820109842432975 + 0.2482078404672857 + 0.24821458269742391 + 0.24822132511475245 + 0.24822806771927883 + 0.24823481051101115 + 0.24824155348995577 + 0.24824829665612008 + 0.24825504000951235 + 0.24826178355013928 + 0.24826852727800855 + 0.24827527119312759 + 0.24828201529550392 + 0.24828875958514443 + 0.24829550406205733 + 0.24830224872624942 + 0.2483089935777282 + 0.24831573861650122 + 0.24832248384257605 + 0.2483292292559601 + 0.24833597485666031 + 0.24834272064468482 + 0.24834946662003993 + 0.24835621278273431 + 0.24836295913277434 + 0.24836970567016811 + 0.24837645239492309 + 0.24838319930704689 + 0.24838994640654574 + 0.24839669369342834 + 0.24840344116770102 + 0.2484101888293726 + 0.24841693667844925 + 0.24842368471493853 + 0.24843043293884864 + 0.24843718135018639 + 0.24844392994895931 + 0.24845067873517504 + 0.24845742770884033 + 0.248464176869964 + 0.24847092621855169 + 0.24847767575461224 + 0.24848442547815247 + 0.24849117538917925 + 0.2484979254877015 + 0.24850467577372537 + 0.24851142624725839 + 0.24851817690830871 + 0.24852492775688334 + 0.24853167879298965 + 0.24853843001663525 + 0.24854518142782764 + 0.2485519330265738 + 0.24855868481288182 + 0.24856543678675791 + 0.24857218894821098 + 0.24857894129724786 + 0.24858569383387544 + 0.24859244655810186 + 0.24859919946993478 + 0.24860595256938095 + 0.24861270585644799 + 0.24861945933114335 + 0.24862621299347462 + 0.24863296684344871 + 0.24863972088107383 + 0.24864647510635679 + 0.24865322951930571 + 0.24865998411992765 + 0.24866673890823002 + 0.2486734938842198 + 0.24868024904790514 + 0.24868700439929292 + 0.24869375993839124 + 0.24870051566520715 + 0.24870727157974812 + 0.24871402768202105 + 0.2487207839720347 + 0.24872754044979542 + 0.24873429711531073 + 0.24874105396858873 + 0.24874781100963642 + 0.24875456823846068 + 0.24876132565506964 + 0.24876808325947092 + 0.2487748410516713 + 0.2487815990316791 + 0.24878835719950118 + 0.248795115555145 + 0.24880187409861762 + 0.24880863282992763 + 0.24881539174908152 + 0.24882215085608678 + 0.24882891015095154 + 0.24883566963368203 + 0.24884242930428724 + 0.24884918916277324 + 0.24885594920914833 + 0.24886270944341943 + 0.24886946986559469 + 0.248876230475681 + 0.24888299127368591 + 0.24888975225961635 + 0.24889651343348115 + 0.24890327479528659 + 0.24891003634504011 + 0.24891679808275013 + 0.2489235600084227 + 0.24893032212206673 + 0.24893708442368914 + 0.24894384691329621 + 0.24895060959089738 + 0.24895737245649896 + 0.24896413551010849 + 0.24897089875173345 + 0.24897766218138156 + 0.24898442579906016 + 0.24899118960477634 + 0.24899795359853752 + 0.24900471778035205 + 0.2490114821502267 + 0.24901824670816974 + 0.24902501145418682 + 0.24903177638828733 + 0.24903854151047763 + 0.2490453068207652 + 0.24905207231915769 + 0.2490588380056632 + 0.24906560388028817 + 0.24907236994304119 + 0.24907913619392882 + 0.24908590263295835 + 0.24909266926013762 + 0.24909943607547394 + 0.24910620307897557 + 0.24911297027064949 + 0.24911973765050263 + 0.24912650521854252 + 0.24913327297477739 + 0.24914004091921474 + 0.24914680905186087 + 0.24915357737272464 + 0.24916034588181177 + 0.2491671145791316 + 0.24917388346469049 + 0.24918065253849661 + 0.24918742180055634 + 0.24919419125087838 + 0.2492009608894698 + 0.24920773071633742 + 0.24921450073148943 + 0.2492212709349329 + 0.24922804132667589 + 0.24923481190672483 + 0.24924158267508842 + 0.24924835363177306 + 0.24925512477678688 + 0.24926189611013744 + 0.24926866763183173 + 0.24927543934187738 + 0.2492822112402818 + 0.24928898332705263 + 0.24929575560219749 + 0.24930252806572331 + 0.24930930071763821 + 0.24931607355794982 + 0.24932284658666445 + 0.24932961980379031 + 0.24933639320933551 + 0.24934316680330651 + 0.24934994058571078 + 0.24935671455655656 + 0.24936348871585082 + 0.24937026306360163 + 0.24937703759981547 + 0.24938381232450046 + 0.24939058723766427 + 0.2493973623393137 + 0.24940413762945643 + 0.24941091310810057 + 0.24941768877525319 + 0.24942446463092111 + 0.24943124067511327 + 0.2494380169078359 + 0.24944479332909666 + 0.2494515699389038 + 0.24945834673726408 + 0.24946512372418528 + 0.2494719008996748 + 0.24947867826373976 + 0.24948545581638884 + 0.24949223355762784 + 0.24949901148746562 + 0.24950578960590902 + 0.24951256791296572 + 0.24951934640864262 + 0.249526125092948 + 0.24953290396588931 + 0.24953968302747428 + 0.24954646227770916 + 0.24955324171660218 + 0.24956002134416153 + 0.24956680116039354 + 0.24957358116530584 + 0.24958036135890724 + 0.24958714174120342 + 0.24959392231220326 + 0.2496007030719137 + 0.24960748402034166 + 0.24961426515749549 + 0.2496210464833826 + 0.24962782799801073 + 0.24963460970138607 + 0.24964139159351759 + 0.24964817367441222 + 0.24965495594407686 + 0.24966173840252037 + 0.24966852104974854 + 0.24967530388577017 + 0.24968208691059282 + 0.24968887012422344 + 0.24969565352666906 + 0.24970243711793788 + 0.24970922089803743 + 0.24971600486697479 + 0.24972278902475809 + 0.24972957337139431 + 0.24973635790689103 + 0.24974314263125594 + 0.24974992754449593 + 0.24975671264661919 + 0.24976349793763339 + 0.24977028341754542 + 0.24977706908636355 + 0.24978385494409422 + 0.24979064099074547 + 0.24979742722632495 + 0.24980421365083971 + 0.24981100026429737 + 0.24981778706670663 + 0.24982457405807332 + 0.24983136123840563 + 0.24983814860771117 + 0.24984493616599751 + 0.24985172391327165 + 0.24985851184954183 + 0.24986529997481444 + 0.24987208828909821 + 0.24987887679240026 + 0.2498856654847281 + 0.24989245436608867 + 0.24989924343649028 + 0.24990603269594053 + 0.24991282214444568 + 0.24991961178201472 + 0.24992640160865393 + 0.24993319162437219 + 0.24993998182917521 + 0.24994677222307241 + 0.24995356280606967 + 0.2499603535781757 + 0.24996714453939761 + 0.24997393568974285 + 0.24998072702921853 + 0.24998751855783355 + 0.24999431027559346 + 0.25000110218250726 + 0.25000789427858189 + 0.25001468656382497 + 0.25002147903824407 + 0.25002827170184688 + 0.25003506455464031 + 0.25004185759663206 + 0.25004865082783029 + 0.25005544424824255 + 0.25006223785787535 + 0.25006903165673683 + 0.25007582564483405 + 0.25008261982217578 + 0.25008941418876784 + 0.25009620874461902 + 0.25010300348973641 + 0.25010979842412756 + 0.25011659354780003 + 0.25012338886076091 + 0.25013018436301843 + 0.25013698005458013 + 0.25014377593545245 + 0.25015057200564361 + 0.25015736826516188 + 0.25016416471401415 + 0.25017096135220751 + 0.25017775817974958 + 0.25018455519664856 + 0.25019135240291146 + 0.25019814979854654 + 0.25020494738356014 + 0.25021174515796057 + 0.25021854312175473 + 0.25022534127495155 + 0.2502321396175568 + 0.25023893814957865 + 0.25024573687102536 + 0.25025253578190404 + 0.25025933488222157 + 0.25026613417198623 + 0.25027293365120501 + 0.25027973331988618 + 0.25028653317803679 + 0.25029333322566433 + 0.25030013346277658 + 0.25030693388938102 + 0.25031373450548478 + 0.25032053531109599 + 0.25032733630622178 + 0.25033413749086963 + 0.25034093886504732 + 0.25034774042876301 + 0.25035454218202252 + 0.25036134412483524 + 0.2503681462572076 + 0.25037494857914738 + 0.25038175109066196 + 0.25038855379175917 + 0.25039535668244711 + 0.25040215976273228 + 0.25040896303262222 + 0.25041576649212594 + 0.25042257014124908 + 0.25042937397999993 + 0.25043617800838675 + 0.25044298222641598 + 0.25044978663409573 + 0.25045659123143382 + 0.25046339601843648 + 0.25047020099511336 + 0.25047700616147073 + 0.25048381151751564 + 0.25049061706325632 + 0.25049742279870046 + 0.25050422872385569 + 0.250511034838729 + 0.25051784114332809 + 0.25052464763766114 + 0.25053145432173518 + 0.25053826119555722 + 0.25054506825913558 + 0.25055187551247721 + 0.25055868295559042 + 0.25056549058848282 + 0.25057229841116085 + 0.25057910642363329 + 0.25058591462590601 + 0.25059272301798918 + 0.25059953159988779 + 0.25060634037161089 + 0.25061314933316547 + 0.2506199584845597 + 0.25062676782580007 + 0.25063357735689484 + 0.25064038707785158 + 0.25064719698867804 + 0.25065400708938118 + 0.25066081737996865 + 0.25066762786044811 + 0.25067443853082716 + 0.25068124939111347 + 0.25068806044131475 + 0.250694871681438 + 0.25070168311149144 + 0.2507084947314821 + 0.25071530654141827 + 0.25072211854130638 + 0.25072893073115471 + 0.25073574311097085 + 0.25074255568076181 + 0.25074936844053597 + 0.25075618139030031 + 0.25076299453006246 + 0.25076980785983005 + 0.25077662137961076 + 0.25078343508941231 + 0.25079024898924163 + 0.25079706307910704 + 0.25080387735901555 + 0.25081069182897481 + 0.25081750648899254 + 0.25082432133907634 + 0.25083113637923382 + 0.25083795160947209 + 0.25084476702979946 + 0.25085158264022284 + 0.25085839844074997 + 0.25086521443138915 + 0.25087203061214675 + 0.25087884698303098 + 0.25088566354404901 + 0.25089248029520911 + 0.25089929723651822 + 0.25090611436798405 + 0.25091293168961487 + 0.25091974920141713 + 0.25092656690339915 + 0.25093338479556782 + 0.25094020287793217 + 0.25094702115049794 + 0.25095383961327344 + 0.25096065826626696 + 0.25096747710948492 + 0.2509742961429362 + 0.25098111536662665 + 0.25098793478056569 + 0.25099475438475927 + 0.25100157417921615 + 0.25100839416394349 + 0.25101521433894886 + 0.25102203470424006 + 0.25102885525982399 + 0.25103567600570836 + 0.25104249694190156 + 0.25104931806841108 + 0.25105613938524346 + 0.25106296089240698 + 0.25106978258990931 + 0.25107660447775809 + 0.25108342655596039 + 0.25109024882452385 + 0.25109707128345682 + 0.25110389393276628 + 0.25111071677245933 + 0.25111753980254486 + 0.25112436302302932 + 0.25113118643392102 + 0.2511380100352269 + 0.25114483382695474 + 0.2511516578091128 + 0.25115848198170759 + 0.25116530634474793 + 0.2511721308982402 + 0.25117895564219223 + 0.25118578057661217 + 0.25119260570150725 + 0.25119943101688497 + 0.25120625652275369 + 0.25121308221911987 + 0.25121990810599115 + 0.25122673418337649 + 0.25123356045128231 + 0.25124038690971623 + 0.25124721355868601 + 0.25125404039819993 + 0.25126086742826381 + 0.25126769464888715 + 0.25127452206007705 + 0.25128134966184057 + 0.2512881774541853 + 0.25129500543711975 + 0.25130183361065017 + 0.25130866197478485 + 0.25131549052953228 + 0.25132231927489812 + 0.25132914821089197 + 0.25133597733751967 + 0.25134280665479009 + 0.25134963616271028 + 0.25135646586128807 + 0.25136329575053035 + 0.25137012583044616 + 0.25137695610104127 + 0.25138378656232463 + 0.25139061721430389 + 0.25139744805698555 + 0.25140427909037849 + 0.25141111031448921 + 0.25141794172932597 + 0.25142477333489588 + 0.25143160513120716 + 0.25143843711826702 + 0.25144526929608307 + 0.25145210166466359 + 0.25145893422401505 + 0.25146576697414585 + 0.25147259991506293 + 0.25147943304677467 + 0.25148626636928817 + 0.25149309988261098 + 0.25149993358675166 + 0.25150676748171641 + 0.25151360156751373 + 0.25152043584415118 + 0.25152727031163596 + 0.25153410496997625 + 0.25154093981917858 + 0.25154777485925195 + 0.25155461009020325 + 0.25156144551203974 + 0.2515682811247697 + 0.25157511692840073 + 0.25158195292294 + 0.25158878910839516 + 0.25159562548477399 + 0.25160246205208464 + 0.25160929881033378 + 0.25161613575952957 + 0.25162297289967916 + 0.25162981023079084 + 0.25163664775287176 + 0.25164348546593013 + 0.25165032336997251 + 0.25165716146500716 + 0.25166399975104181 + 0.25167083822808417 + 0.25167767689614062 + 0.25168451575522088 + 0.25169135480533067 + 0.25169819404647897 + 0.25170503347867224 + 0.25171187310191878 + 0.25171871291622638 + 0.25172555292160204 + 0.25173239311805412 + 0.25173923350558974 + 0.25174607408421651 + 0.25175291485394286 + 0.25175975581477461 + 0.25176659696672127 + 0.25177343830978932 + 0.25178027984398721 + 0.25178712156932126 + 0.25179396348580046 + 0.25180080559343199 + 0.25180764789222343 + 0.25181449038218262 + 0.2518213330633165 + 0.2518281759356335 + 0.25183501899914074 + 0.25184186225384586 + 0.25184870569975659 + 0.25185554933688131 + 0.25186239316522641 + 0.25186923718480031 + 0.25187608139561007 + 0.25188292579766336 + 0.2518897703909686 + 0.2518966151755328 + 0.25190346015136372 + 0.25191030531846909 + 0.25191715067685599 + 0.25192399622653272 + 0.25193084196750709 + 0.25193768789978616 + 0.25194453402337758 + 0.25195138033828907 + 0.25195822684452845 + 0.25196507354210279 + 0.25197192043102101 + 0.25197876751128961 + 0.25198561478291626 + 0.25199246224590882 + 0.25199930990027547 + 0.25200615774602275 + 0.25201300578315966 + 0.25201985401169269 + 0.2520267024316295 + 0.25203355104297842 + 0.25204039984574667 + 0.25204724883994251 + 0.25205409802557238 + 0.25206094740264468 + 0.25206779697116782 + 0.25207464673114754 + 0.2520814966825935 + 0.25208834682551157 + 0.25209519715991069 + 0.25210204768579736 + 0.25210889840318057 + 0.25211574931206732 + 0.25212260041246487 + 0.25212945170438145 + 0.25213630318782432 + 0.25214315486280103 + 0.25215000672932003 + 0.25215685878738836 + 0.25216371103701318 + 0.25217056347820355 + 0.25217741611096517 + 0.25218426893530771 + 0.25219112195123711 + 0.25219797515876224 + 0.25220482855789023 + 0.25221168214862888 + 0.25221853593098587 + 0.25222538990496829 + 0.25223224407058459 + 0.25223909842784237 + 0.25224595297674823 + 0.25225280771731112 + 0.25225966264953814 + 0.25226651777343639 + 0.25227337308901493 + 0.25228022859628019 + 0.25228708429523988 + 0.25229394018590245 + 0.2523007962682749 + 0.2523076525423657 + 0.25231450900818131 + 0.25232136566573005 + 0.25232822251501907 + 0.25233507955605677 + 0.25234193678885086 + 0.25234879421340844 + 0.25235565182973724 + 0.25236250963784507 + 0.25236936763773965 + 0.25237622582942865 + 0.25238308421291927 + 0.25238994278821986 + 0.2523968015553375 + 0.25240366051428065 + 0.25241051966505573 + 0.25241737900767175 + 0.25242423854213519 + 0.2524310982684545 + 0.25243795818663733 + 0.25244481829669024 + 0.25245167859862283 + 0.25245853909244159 + 0.25246539977815363 + 0.252472260655768 + 0.25247912172529113 + 0.25248598298673153 + 0.25249284444009618 + 0.25249970608539346 + 0.2525065679226306 + 0.25251342995181592 + 0.25252029217295585 + 0.2525271545860589 + 0.25253401719113278 + 0.25254087998818453 + 0.25254774297722266 + 0.25255460615825426 + 0.25256146953128761 + 0.25256833309632931 + 0.25257519685338836 + 0.25258206080247125 + 0.25258892494358637 + 0.25259578927674081 + 0.25260265380194302 + 0.25260951851920005 + 0.25261638342852039 + 0.25262324852991042 + 0.25263011382337863 + 0.2526369793089327 + 0.25264384498658043 + 0.25265071085632962 + 0.25265757691818669 + 0.25266444317216069 + 0.25267130961825879 + 0.25267817625648875 + 0.25268504308685824 + 0.25269191010937447 + 0.25269877732404583 + 0.25270564473088003 + 0.25271251232988429 + 0.25271938012106632 + 0.25272624810443389 + 0.2527331162799954 + 0.25273998464775732 + 0.2527468532077275 + 0.2527537219599148 + 0.25276059090432534 + 0.25276746004096862 + 0.25277432936985045 + 0.25278119889097939 + 0.25278806860436315 + 0.25279493851000945 + 0.25280180860792612 + 0.25280867889812025 + 0.25281554938059964 + 0.25282242005537264 + 0.25282929092244649 + 0.25283616198182823 + 0.25284303323352703 + 0.25284990467754981 + 0.25285677631390391 + 0.2528636481425976 + 0.25287052016363754 + 0.25287739237703322 + 0.25288426478279064 + 0.25289113738091812 + 0.25289801017142355 + 0.25290488315431464 + 0.25291175632959911 + 0.25291862969728418 + 0.25292550325737762 + 0.25293237700988713 + 0.25293925095482123 + 0.25294612509218639 + 0.25295299942199101 + 0.25295987394424285 + 0.25296674865894975 + 0.25297362356611874 + 0.25298049866575772 + 0.25298737395787441 + 0.25299424944247723 + 0.25300112511957268 + 0.25300800098916987 + 0.25301487705127523 + 0.25302175330589655 + 0.25302862975304174 + 0.25303550639271971 + 0.25304238322493633 + 0.25304926024970015 + 0.25305613746701883 + 0.25306301487690025 + 0.25306989247935208 + 0.25307677027438091 + 0.25308364826199642 + 0.2530905264422052 + 0.25309740481501486 + 0.25310428338043273 + 0.25311116213846774 + 0.25311804108912705 + 0.25312492023241795 + 0.25313179956834808 + 0.25313867909692594 + 0.25314555881815931 + 0.25315243873205462 + 0.25315931883862042 + 0.25316619913786442 + 0.25317307962979446 + 0.2531799603144177 + 0.25318684119174251 + 0.25319372226177672 + 0.25320060352452745 + 0.2532074849800019 + 0.25321436662820851 + 0.25322124846915567 + 0.25322813050284992 + 0.25323501272929966 + 0.25324189514851214 + 0.25324877776049565 + 0.25325566056525745 + 0.2532625435628047 + 0.25326942675314645 + 0.25327631013628976 + 0.25328319371224195 + 0.2532900774810114 + 0.25329696144260588 + 0.2533038455970319 + 0.2533107299442986 + 0.25331761448441309 + 0.25332449921738315 + 0.25333138414321665 + 0.25333826926192138 + 0.25334515457350376 + 0.25335204007797363 + 0.25335892577533747 + 0.25336581166560307 + 0.25337269774877824 + 0.25337958402487082 + 0.25338647049388857 + 0.25339335715583861 + 0.25340024401073008 + 0.25340713105856888 + 0.25341401829936411 + 0.25342090573312287 + 0.25342779335985299 + 0.2534346811795623 + 0.25344156919225858 + 0.25344845739794958 + 0.25345534579664264 + 0.25346223438834536 + 0.25346912317306636 + 0.25347601215081272 + 0.2534829013215929 + 0.25348979068541344 + 0.25349668024228217 + 0.25350356999220813 + 0.25351045993519783 + 0.25351735007125981 + 0.25352424040040117 + 0.2535311309226298 + 0.25353802163795341 + 0.25354491254638051 + 0.25355180364791702 + 0.25355869494257255 + 0.25356558643035382 + 0.25357247811126915 + 0.25357936998532571 + 0.25358626205253143 + 0.25359315431289459 + 0.25360004676642189 + 0.25360693941312173 + 0.25361383225300188 + 0.2536207252860696 + 0.25362761851233329 + 0.25363451193180014 + 0.25364140554447795 + 0.25364829935037514 + 0.25365519334949904 + 0.25366208754185665 + 0.25366898192745657 + 0.25367587650630591 + 0.25368277127841315 + 0.25368966624378608 + 0.2536965614024313 + 0.25370345675435779 + 0.25371035229957289 + 0.25371724803808371 + 0.25372414396989873 + 0.25373104009502567 + 0.25373793641347187 + 0.25374483292524569 + 0.25375172963035436 + 0.25375862652880565 + 0.2537655236206075 + 0.25377242090576763 + 0.25377931838429324 + 0.25378621605619284 + 0.25379311392147419 + 0.25380001198014457 + 0.25380691023221169 + 0.25381380867768411 + 0.25382070731656842 + 0.25382760614887356 + 0.25383450517460621 + 0.25384140439377478 + 0.25384830380638651 + 0.25385520341244927 + 0.25386210321197206 + 0.25386900320496081 + 0.25387590339142402 + 0.25388280377136957 + 0.25388970434480518 + 0.25389660511173817 + 0.25390350607217693 + 0.25391040722612868 + 0.25391730857360184 + 0.2539242101146037 + 0.25393111184914202 + 0.25393801377722464 + 0.25394491589885887 + 0.2539518182140536 + 0.25395872072281556 + 0.25396562342515261 + 0.25397252632107309 + 0.25397942941058427 + 0.25398633269369403 + 0.25399323617041014 + 0.25400013984073982 + 0.25400704370469157 + 0.25401394776227382 + 0.2540208520134925 + 0.25402775645835679 + 0.25403466109687384 + 0.25404156592905153 + 0.2540484709548983 + 0.25405537617442064 + 0.25406228158762723 + 0.25406918719452509 + 0.25407609299512279 + 0.25408299898942754 + 0.25408990517744778 + 0.25409681155919006 + 0.25410371813466359 + 0.25411062490387548 + 0.254117531866833 + 0.25412443902354459 + 0.25413134637401813 + 0.25413825391826084 + 0.25414516165628115 + 0.25415206958808567 + 0.25415897771368351 + 0.25416588603308127 + 0.25417279454628738 + 0.25417970325331035 + 0.25418661215415617 + 0.25419352124883388 + 0.25420043053735142 + 0.25420734001971529 + 0.25421424969593459 + 0.25422115956601665 + 0.25422806962996858 + 0.25423497988779953 + 0.25424189033951611 + 0.25424880098512614 + 0.25425571182463813 + 0.25426262285805934 + 0.25426953408539754 + 0.25427644550666056 + 0.2542833571218564 + 0.25429026893099277 + 0.2542971809340776 + 0.25430409313111807 + 0.2543110055221221 + 0.25431791810709808 + 0.25432483088605334 + 0.25433174385899632 + 0.25433865702593356 + 0.25434557038687367 + 0.25435248394182375 + 0.25435939769079235 + 0.25436631163378731 + 0.25437322577081589 + 0.25438014010188598 + 0.25438705462700534 + 0.25439396934618252 + 0.25440088425942414 + 0.25440779936673863 + 0.25441471466813392 + 0.25442163016361719 + 0.2544285458531963 + 0.25443546173687975 + 0.25444237781467482 + 0.25444929408658934 + 0.25445621055263112 + 0.25446312721280812 + 0.25447004406712814 + 0.25447696111559842 + 0.25448387835822683 + 0.25449079579502193 + 0.25449771342599087 + 0.25450463125114153 + 0.25451154927048242 + 0.25451846748402018 + 0.25452538589176327 + 0.25453230449371889 + 0.25453922328989564 + 0.25454614228030126 + 0.2545530614649425 + 0.25455998084382842 + 0.25456690041696622 + 0.25457382018436381 + 0.25458074014602905 + 0.25458766030196928 + 0.25459458065219281 + 0.25460150119670705 + 0.25460842193552041 + 0.25461534286864018 + 0.25462226399607424 + 0.25462918531783035 + 0.25463610683391652 + 0.25464302854434062 + 0.25464995044910976 + 0.2546568725482326 + 0.25466379484171697 + 0.25467071732956942 + 0.25467764001179916 + 0.25468456288841335 + 0.25469148595942004 + 0.25469840922482628 + 0.25470533268464068 + 0.25471225633887107 + 0.25471918018752537 + 0.25472610423061087 + 0.25473302846813539 + 0.25473995290010681 + 0.25474687752653302 + 0.25475380234742184 + 0.25476072736278127 + 0.25476765257261846 + 0.25477457797694264 + 0.25478150357575974 + 0.25478842936907892 + 0.25479535535690739 + 0.25480228153925316 + 0.25480920791612394 + 0.25481613448752777 + 0.25482306125347182 + 0.25482998821396524 + 0.2548369153690147 + 0.25484384271862798 + 0.25485077026281311 + 0.25485769800157854 + 0.25486462593493087 + 0.25487155406287931 + 0.25487848238543037 + 0.25488541090259337 + 0.25489233961437413 + 0.25489926852078254 + 0.25490619762182465 + 0.2549131269175095 + 0.25492005640784432 + 0.25492698609283715 + 0.25493391597249576 + 0.25494084604682743 + 0.25494777631584137 + 0.25495470677954418 + 0.2549616374379437 + 0.25496856829104853 + 0.25497549933886526 + 0.25498243058140307 + 0.25498936201866923 + 0.25499629365067156 + 0.25500322547741805 + 0.25501015749891598 + 0.25501708971517306 + 0.25502402212619868 + 0.25503095473199872 + 0.25503788753258239 + 0.2550448205279563 + 0.25505175371812955 + 0.25505868710310886 + 0.25506562068290273 + 0.25507255445751909 + 0.25507948842696582 + 0.25508642259124953 + 0.25509335695037944 + 0.2551002915043627 + 0.25510722625320797 + 0.25511416119692193 + 0.25512109633551294 + 0.25512803166898834 + 0.2551349671973574 + 0.255141902920626 + 0.25514883883880335 + 0.25515577495189673 + 0.25516271125991469 + 0.25516964776286444 + 0.25517658446075331 + 0.25518352135358985 + 0.25519045844138194 + 0.25519739572413686 + 0.25520433320186314 + 0.25521127087456807 + 0.25521820874226014 + 0.25522514680494607 + 0.25523208506263495 + 0.25523902351533417 + 0.2552459621630509 + 0.25525290100579373 + 0.25525984004357061 + 0.25526677927638874 + 0.25527371870425603 + 0.25528065832718044 + 0.25528759814517055 + 0.2552945381582335 + 0.25530147836637673 + 0.2553084187696093 + 0.25531535936793792 + 0.25532230016137053 + 0.25532924114991562 + 0.25533618233358113 + 0.25534312371237361 + 0.25535006528630244 + 0.25535700705537406 + 0.25536394901959786 + 0.25537089117898032 + 0.25537783353353011 + 0.25538477608325438 + 0.25539171882816181 + 0.25539866176826026 + 0.2554056049035564 + 0.2554125482340594 + 0.25541949175977591 + 0.25542643548071514 + 0.25543337939688376 + 0.25544032350829021 + 0.25544726781494198 + 0.2554542123168474 + 0.2554611570140139 + 0.25546810190644936 + 0.2554750469941624 + 0.25548199227715951 + 0.25548893775545012 + 0.25549588342904062 + 0.25550282929793916 + 0.25550977536215486 + 0.25551672162169436 + 0.25552366807656551 + 0.25553061472677641 + 0.25553756157233487 + 0.25554450861324945 + 0.25555145584952677 + 0.25555840328117552 + 0.25556535090820354 + 0.25557229873061821 + 0.25557924674842797 + 0.2555861949616402 + 0.25559314337026273 + 0.25560009197430428 + 0.25560704077377139 + 0.25561398976867267 + 0.25562093895901605 + 0.25562788834480948 + 0.25563483792606018 + 0.25564178770277679 + 0.25564873767496665 + 0.25565568784263826 + 0.25566263820579821 + 0.25566958876445589 + 0.2556765395186178 + 0.25568349046829258 + 0.25569044161348814 + 0.25569739295421245 + 0.25570434449047219 + 0.25571129622227712 + 0.25571824814963395 + 0.25572520027255008 + 0.25573215259103454 + 0.25573910510509479 + 0.25574605781473803 + 0.25575301071997286 + 0.25575996382080723 + 0.25576691711724847 + 0.25577387060930518 + 0.25578082429698445 + 0.25578777818029452 + 0.25579473225924321 + 0.255801686533839 + 0.25580864100408807 + 0.25581559567000023 + 0.2558225505315827 + 0.25582950558884227 + 0.25583646084178874 + 0.25584341629042812 + 0.25585037193476967 + 0.25585732777482068 + 0.25586428381058912 + 0.25587124004208228 + 0.25587819646930932 + 0.25588515309227705 + 0.25589210991099332 + 0.25589906692546732 + 0.25590602413570523 + 0.2559129815417161 + 0.25591993914350675 + 0.25592689694108628 + 0.25593385493446208 + 0.25594081312364148 + 0.25594777150863368 + 0.25595473008944464 + 0.25596168886608373 + 0.25596864783855877 + 0.25597560700687716 + 0.25598256637104683 + 0.25598952593107571 + 0.25599648568697181 + 0.25600344563874239 + 0.25601040578639606 + 0.25601736612994141 + 0.25602432666938446 + 0.25603128740473446 + 0.25603824833599942 + 0.25604520946318599 + 0.25605217078630332 + 0.25605913230535821 + 0.25606609402035985 + 0.25607305593131485 + 0.25608001803823127 + 0.25608698034111826 + 0.2560939428399826 + 0.25610090553483222 + 0.25610786842567501 + 0.25611483151251963 + 0.25612179479537278 + 0.25612875827424364 + 0.25613572194913892 + 0.25614268582006722 + 0.25614964988703587 + 0.25615661415005347 + 0.25616357860912736 + 0.25617054326426614 + 0.25617750811547707 + 0.25618447316276821 + 0.25619143840614744 + 0.2561984038456222 + 0.25620536948120159 + 0.25621233531289245 + 0.2562193013407032 + 0.25622626756464134 + 0.25623323398471476 + 0.25624020060093211 + 0.25624716741330067 + 0.25625413442182776 + 0.25626110162652266 + 0.25626806902739269 + 0.25627503662444517 + 0.25628200441768872 + 0.25628897240713078 + 0.2562959405927791 + 0.25630290897464308 + 0.25630987755272877 + 0.25631684632704471 + 0.25632381529759896 + 0.25633078446439944 + 0.25633775382745411 + 0.25634472338677033 + 0.25635169314235673 + 0.25635866309422062 + 0.25636563324237061 + 0.25637260358681402 + 0.25637957412755885 + 0.2563865448646131 + 0.25639351579798475 + 0.25640048692768169 + 0.25640745825371203 + 0.25641442977608297 + 0.25642140149480325 + 0.25642837340988017 + 0.25643534552132163 + 0.25644231782913635 + 0.25644929033333097 + 0.25645626303391483 + 0.25646323593089515 + 0.25647020902427942 + 0.25647718231407607 + 0.25648415580029327 + 0.25649112948293823 + 0.25649810336201967 + 0.25650507743754425 + 0.25651205170952118 + 0.25651902617795791 + 0.25652600084286237 + 0.25653297570424249 + 0.25653995076210573 + 0.25654692601646062 + 0.25655390146731522 + 0.25656087711467679 + 0.25656785295855405 + 0.25657482899895367 + 0.25658180523588486 + 0.25658878166935506 + 0.2565957582993722 + 0.25660273512594428 + 0.25660971214907868 + 0.25661668936878407 + 0.25662366678506826 + 0.25663064439793815 + 0.25663762220740355 + 0.25664460021347058 + 0.25665157841614844 + 0.25665855681544392 + 0.25666553541136633 + 0.25667251420392223 + 0.25667949319312039 + 0.25668647237896874 + 0.25669345176147468 + 0.2567004313406468 + 0.25670741111649248 + 0.25671439108901967 + 0.25672137125823641 + 0.2567283516241507 + 0.25673533218677058 + 0.25674231294610389 + 0.25674929390215812 + 0.25675627505494258 + 0.25676325640446324 + 0.25677023795072945 + 0.2567772196937485 + 0.25678420163352911 + 0.25679118377007798 + 0.25679816610340428 + 0.25680514863351489 + 0.25681213136041836 + 0.2568191142841228 + 0.25682609740463602 + 0.25683308072196498 + 0.25684006423611933 + 0.25684704794710539 + 0.25685403185493233 + 0.25686101595960753 + 0.25686800026113898 + 0.25687498475953413 + 0.25688196945480213 + 0.2568889543469498 + 0.25689593943598577 + 0.25690292472191739 + 0.25690991020475268 + 0.25691689588450028 + 0.25692388176116754 + 0.25693086783476254 + 0.25693785410529318 + 0.25694484057276817 + 0.25695182723719362 + 0.2569588140985794 + 0.25696580115693229 + 0.25697278841226034 + 0.25697977586457205 + 0.25698676351387495 + 0.25699375136017699 + 0.25700073940348683 + 0.25700772764381113 + 0.25701471608115867 + 0.25702170471553798 + 0.25702869354695529 + 0.25703568257541975 + 0.25704267180093948 + 0.2570496612235218 + 0.25705665084317542 + 0.25706364065990761 + 0.25707063067372588 + 0.25707762088463942 + 0.25708461129265564 + 0.25709160189778196 + 0.257098592700027 + 0.25710558369939873 + 0.25711257489590467 + 0.25711956628955335 + 0.25712655788035155 + 0.2571335496683092 + 0.25714054165343242 + 0.25714753383572986 + 0.25715452621520951 + 0.25716151879187943 + 0.25716851156574766 + 0.2571755045368222 + 0.25718249770510981 + 0.25718949107061972 + 0.25719648463336003 + 0.25720347839333807 + 0.25721047235056194 + 0.25721746650503963 + 0.25722446085677847 + 0.25723145540578785 + 0.25723845015207447 + 0.25724544509564762 + 0.25725244023651345 + 0.25725943557468123 + 0.25726643111015901 + 0.25727342684295418 + 0.25728042277307411 + 0.25728741890052814 + 0.25729441522532359 + 0.25730141174746796 + 0.25730840846697045 + 0.2573154053838379 + 0.25732240249807892 + 0.25732939980970093 + 0.25733639731871261 + 0.25734339502512132 + 0.25735039292893447 + 0.25735739103016203 + 0.2573643893288094 + 0.25737138782488728 + 0.25737838651840172 + 0.25738538540936073 + 0.25739238449777307 + 0.25739938378364674 + 0.25740638326698906 + 0.25741338294780819 + 0.25742038282611268 + 0.25742738290190947 + 0.25743438317520767 + 0.25744138364601477 + 0.2574483843143382 + 0.25745538518018724 + 0.25746238624356799 + 0.25746938750449044 + 0.25747638896296071 + 0.25748339061898873 + 0.25749039247258071 + 0.25749739452374587 + 0.25750439677249165 + 0.25751139921882543 + 0.2575184018627566 + 0.25752540470429186 + 0.25753240774344049 + 0.25753941098020877 + 0.25754641441460585 + 0.25755341804663989 + 0.25756042187631822 + 0.25756742590364895 + 0.25757443012864006 + 0.25758143455130028 + 0.25758843917163637 + 0.25759544398965706 + 0.25760244900537033 + 0.25760945421878362 + 0.25761645962990559 + 0.2576234652387443 + 0.25763047104530717 + 0.25763747704960227 + 0.25764448325163758 + 0.25765148965142126 + 0.25765849624896187 + 0.25766550304426628 + 0.25767251003734315 + 0.25767951722820054 + 0.25768652461684582 + 0.25769353220328772 + 0.25770053998753367 + 0.25770754796959233 + 0.25771455614947109 + 0.25772156452717809 + 0.25772857310272135 + 0.25773558187610884 + 0.25774259084734874 + 0.25774960001644903 + 0.25775660938341716 + 0.25776361894826177 + 0.25777062871099038 + 0.25777763867161158 + 0.25778464883013286 + 0.25779165918656288 + 0.25779866974090843 + 0.25780568049317892 + 0.25781269144338098 + 0.25781970259152343 + 0.25782671393761492 + 0.25783372548166161 + 0.25784073722367279 + 0.2578477491636566 + 0.25785476130162044 + 0.25786177363757301 + 0.25786878617152104 + 0.25787579890347395 + 0.25788281183343847 + 0.25788982496142399 + 0.25789683828743726 + 0.25790385181148701 + 0.25791086553358122 + 0.25791787945372813 + 0.25792489357193438 + 0.2579319078882093 + 0.25793892240256105 + 0.25794593711499642 + 0.25795295202552465 + 0.25795996713415331 + 0.25796698244088972 + 0.25797399794574261 + 0.25798101364872073 + 0.25798802954983019 + 0.25799504564908099 + 0.25800206194647929 + 0.25800907844203441 + 0.25801609513575452 + 0.25802311202764633 + 0.25803012911771916 + 0.25803714640597986 + 0.25804416389243773 + 0.25805118157709966 + 0.25805819945997427 + 0.25806521754106904 + 0.25807223582039335 + 0.25807925429795325 + 0.25808627297375825 + 0.25809329184781626 + 0.25810031092013419 + 0.25810733019072074 + 0.25811434965958457 + 0.25812136932673257 + 0.2581283891921734 + 0.25813540925591516 + 0.25814242951796523 + 0.25814944997833306 + 0.25815647063702468 + 0.2581634914940496 + 0.25817051254941525 + 0.25817753380312958 + 0.25818455525520079 + 0.25819157690563749 + 0.25819859875444656 + 0.25820562080163678 + 0.25821264304721614 + 0.25821966549119274 + 0.25822668813357341 + 0.25823371097436809 + 0.25824073401358372 + 0.25824775725122823 + 0.25825478068730978 + 0.2582618043218371 + 0.258268828154817 + 0.25827585218625815 + 0.25828287641616937 + 0.25828990084455739 + 0.25829692547143096 + 0.25830395029679692 + 0.25831097532066521 + 0.25831800054304271 + 0.25832502596393814 + 0.25833205158335826 + 0.25833907740131251 + 0.25834610341780823 + 0.25835312963285301 + 0.25836015604645612 + 0.25836718265862446 + 0.25837420946936662 + 0.25838123647869088 + 0.25838826368660389 + 0.25839529109311571 + 0.25840231869823321 + 0.25840934650196445 + 0.25841637450431754 + 0.25842340270530118 + 0.2584304311049222 + 0.25843745970318938 + 0.2584444885001107 + 0.25845151749569439 + 0.25845854668994783 + 0.25846557608287979 + 0.25847260567449776 + 0.2584796354648104 + 0.25848666545382515 + 0.25849369564155023 + 0.25850072602799368 + 0.25850775661316355 + 0.25851478739706801 + 0.25852181837971511 + 0.25852884956111305 + 0.25853588094126978 + 0.2585429125201929 + 0.25854994429789041 + 0.25855697627437119 + 0.2585640084496425 + 0.25857104082371263 + 0.25857807339659017 + 0.25858510616828279 + 0.25859213913879836 + 0.2585991723081445 + 0.25860620567633058 + 0.25861323924336271 + 0.258620273009251 + 0.25862730697400227 + 0.25863434113762518 + 0.25864137550012728 + 0.25864841006151668 + 0.25865544482180142 + 0.25866247978099033 + 0.25866951493909024 + 0.25867655029611047 + 0.25868358585205853 + 0.2586906216069419 + 0.25869765756076929 + 0.25870469371354821 + 0.25871173006528742 + 0.25871876661599441 + 0.25872580336567785 + 0.25873284031434529 + 0.25873987746200483 + 0.25874691480866452 + 0.25875395235433324 + 0.25876099009901699 + 0.25876802804272603 + 0.25877506618546769 + 0.25878210452724953 + 0.25878914306808026 + 0.25879618180796798 + 0.25880322074692025 + 0.25881025988494505 + 0.25881729922205066 + 0.25882433875824501 + 0.25883137849353705 + 0.25883841842793348 + 0.25884545856144381 + 0.25885249889407486 + 0.25885953942583528 + 0.25886658015673264 + 0.25887362108677636 + 0.25888066221597261 + 0.25888770354433077 + 0.25889474507185839 + 0.25890178679856418 + 0.25890882872445564 + 0.25891587084954082 + 0.25892291317382737 + 0.25892995569732391 + 0.25893699842003931 + 0.25894404134198035 + 0.25895108446315579 + 0.25895812778357313 + 0.25896517130324048 + 0.25897221502216733 + 0.25897925894035978 + 0.25898630305782666 + 0.25899334737457674 + 0.25900039189061752 + 0.25900743660595704 + 0.25901448152060291 + 0.25902152663456446 + 0.25902857194784856 + 0.259035617460464 + 0.25904266317241825 + 0.2590497090837201 + 0.2590567551943771 + 0.25906380150439723 + 0.25907084801378938 + 0.25907789472256099 + 0.25908494163072027 + 0.25909198873827527 + 0.25909903604523349 + 0.25910608355160442 + 0.25911313125739482 + 0.2591201791626136 + 0.25912722726726878 + 0.25913427557136787 + 0.25914132407491902 + 0.25914837277793107 + 0.25915542168041139 + 0.25916247078236826 + 0.25916952008380972 + 0.25917656958474394 + 0.25918361928517908 + 0.25919066918512329 + 0.25919771928458402 + 0.25920476958357003 + 0.25921182008208959 + 0.25921887078015071 + 0.25922592167776032 + 0.25923297277492841 + 0.2592400240716613 + 0.25924707556796778 + 0.25925412726385649 + 0.25926117915933444 + 0.25926823125441101 + 0.25927528354909307 + 0.25928233604338935 + 0.25928938873730811 + 0.25929644163085741 + 0.25930349472404474 + 0.25931054801687831 + 0.25931760150936689 + 0.25932465520151798 + 0.25933170909333975 + 0.25933876318484034 + 0.25934581747602847 + 0.25935287196691104 + 0.25935992665749763 + 0.25936698154779425 + 0.25937403663781111 + 0.25938109192755571 + 0.25938814741703548 + 0.25939520310625863 + 0.259402258995234 + 0.25940931508396903 + 0.25941637137247253 + 0.25942342786075206 + 0.25943048454881507 + 0.25943754143667103 + 0.25944459852432744 + 0.2594516558117918 + 0.259458713299073 + 0.25946577098617907 + 0.25947282887311823 + 0.25947988695989804 + 0.25948694524652649 + 0.25949400373301262 + 0.25950106241936377 + 0.25950812130558815 + 0.25951518039169463 + 0.25952223967769061 + 0.25952929916358369 + 0.25953635884938325 + 0.25954341873509623 + 0.2595504788207314 + 0.25955753910629698 + 0.25956459959180039 + 0.25957166027725054 + 0.25957872116265485 + 0.25958578224802153 + 0.25959284353335943 + 0.25959990501867597 + 0.25960696670397948 + 0.25961402858927796 + 0.25962109067457961 + 0.25962815295989333 + 0.25963521544522528 + 0.25964227813058555 + 0.25964934101598108 + 0.2596564041014206 + 0.25966346738691176 + 0.25967053087246322 + 0.25967759455808198 + 0.25968465844377808 + 0.2596917225295578 + 0.25969878681542991 + 0.25970585130140322 + 0.25971291598748536 + 0.2597199808736837 + 0.25972704596000717 + 0.25973411124646395 + 0.25974117673306146 + 0.25974824241980865 + 0.25975530830671362 + 0.25976237439378391 + 0.2597694406810277 + 0.2597765071684538 + 0.25978357385606909 + 0.25979064074388308 + 0.25979770783190326 + 0.25980477512013783 + 0.25981184260859497 + 0.25981891029728216 + 0.25982597818620828 + 0.25983304627538151 + 0.25984011456480932 + 0.25984718305450066 + 0.25985425174446358 + 0.25986132063470563 + 0.25986838972523441 + 0.25987545901605941 + 0.25988252850718874 + 0.25988959819862928 + 0.25989666809038997 + 0.25990373818247886 + 0.25991080847490422 + 0.25991787896767421 + 0.25992494966079632 + 0.25993202055427939 + 0.25993909164813173 + 0.25994616294236078 + 0.25995323443697471 + 0.25996030613198173 + 0.25996737802739067 + 0.25997445012320908 + 0.25998152241944517 + 0.2599885949161071 + 0.25999566761320236 + 0.26000274051074052 + 0.2600098136087291 + 0.26001688690717562 + 0.26002396040608827 + 0.26003103410547657 + 0.26003810800534671 + 0.26004518210570821 + 0.26005225640656932 + 0.26005933090793687 + 0.26006640560982031 + 0.26007348051222728 + 0.26008055561516591 + 0.2600876309186444 + 0.26009470642267096 + 0.26010178212725377 + 0.2601088580323998 + 0.26011593413811973 + 0.26012301044441921 + 0.26013008695130774 + 0.26013716365879286 + 0.26014424056688346 + 0.26015131767558702 + 0.26015839498491239 + 0.26016547249486649 + 0.26017255020545887 + 0.26017962811669637 + 0.26018670622858786 + 0.26019378454114156 + 0.26020086305436557 + 0.26020794176826828 + 0.26021502068285707 + 0.26022209979814082 + 0.26022917911412713 + 0.26023625863082483 + 0.26024333834824154 + 0.26025041826638534 + 0.26025749838526518 + 0.26026457870488795 + 0.26027165922526307 + 0.26027873994639822 + 0.26028582086830154 + 0.2602929019909806 + 0.26029998331444426 + 0.2603070648387007 + 0.26031414656375751 + 0.26032122848962352 + 0.26032831061630629 + 0.26033539294381469 + 0.26034247547215633 + 0.26034955820133937 + 0.26035664113137263 + 0.26036372426226373 + 0.26037080759402026 + 0.26037789112665161 + 0.26038497486016549 + 0.26039205879456934 + 0.26039914292987204 + 0.26040622726608192 + 0.26041331180320637 + 0.26042039654125437 + 0.26042748148023415 + 0.26043456662015252 + 0.26044165196101915 + 0.26044873750284209 + 0.26045582324562833 + 0.26046290918938736 + 0.26046999533412679 + 0.26047708167985417 + 0.26048416822657905 + 0.26049125497430831 + 0.26049834192305144 + 0.26050542907281476 + 0.2605125164236084 + 0.26051960397543933 + 0.26052669172831566 + 0.26053377968224645 + 0.26054086783723912 + 0.26054795619330257 + 0.26055504475044439 + 0.26056213350867219 + 0.26056922246799541 + 0.2605763116284216 + 0.26058340098995914 + 0.26059049055261552 + 0.26059758031640018 + 0.26060467028132017 + 0.26061176044738427 + 0.26061885081460018 + 0.26062594138297662 + 0.26063303215252132 + 0.26064012312324303 + 0.2606472142951487 + 0.2606543056682486 + 0.26066139724254889 + 0.26066848901805917 + 0.26067558099478638 + 0.26068267317273935 + 0.26068976555192697 + 0.26069685813235549 + 0.2607039509140352 + 0.26071104389697358 + 0.26071813708117825 + 0.26072523046665746 + 0.26073232405342006 + 0.26073941784147431 + 0.2607465118308277 + 0.26075360602148856 + 0.26076070041346516 + 0.26076779500676633 + 0.2607748898013989 + 0.26078198479737197 + 0.26078907999469425 + 0.26079617539337274 + 0.26080327099341633 + 0.26081036679483327 + 0.26081746279763113 + 0.26082455900181878 + 0.26083165540740444 + 0.26083875201439577 + 0.26084584882280099 + 0.26085294583262902 + 0.26086004304388732 + 0.26086714045658421 + 0.26087423807072796 + 0.26088133588632678 + 0.26088843390338895 + 0.26089553212192262 + 0.2609026305419368 + 0.26090972916343835 + 0.26091682798643551 + 0.26092392701093725 + 0.26093102623695175 + 0.2609381256644866 + 0.26094522529355069 + 0.26095232512415167 + 0.26095942515629778 + 0.26096652538999787 + 0.26097362582525957 + 0.26098072646209108 + 0.26098782730050074 + 0.2609949283404967 + 0.26100202958208724 + 0.26100913102528006 + 0.26101623267008456 + 0.26102333451650767 + 0.26103043656455843 + 0.26103753881424507 + 0.26104464126557508 + 0.26105174391855684 + 0.26105884677319918 + 0.2610659498295097 + 0.26107305308749729 + 0.26108015654716898 + 0.26108726020853423 + 0.26109436407160069 + 0.26110146813637664 + 0.26110857240286967 + 0.26111567687108928 + 0.26112278154104313 + 0.26112988641273882 + 0.26113699148618524 + 0.26114409676139 + 0.26115120223836269 + 0.26115830791710959 + 0.26116541379764019 + 0.26117251987996226 + 0.26117962616408458 + 0.2611867326500148 + 0.26119383933776108 + 0.26120094622733192 + 0.26120805331873537 + 0.26121516061197975 + 0.26122226810707333 + 0.26122937580402439 + 0.26123648370284119 + 0.26124359180353129 + 0.26125070010610363 + 0.26125780861056652 + 0.26126491731692686 + 0.26127202622519491 + 0.26127913533537755 + 0.26128624464748318 + 0.26129335416152061 + 0.26130046387749756 + 0.26130757379542219 + 0.26131468391530277 + 0.26132179423714763 + 0.26132890476096499 + 0.2613360154867625 + 0.26134312641454976 + 0.26135023754433434 + 0.26135734887612383 + 0.26136446040992717 + 0.26137157214575202 + 0.26137868408360732 + 0.26138579622350055 + 0.26139290856544078 + 0.26140002110943561 + 0.26140713385549325 + 0.26141424680362202 + 0.26142135995383081 + 0.26142847330612728 + 0.26143558686051971 + 0.26144270061701569 + 0.26144981457562483 + 0.26145692873635401 + 0.26146404309921295 + 0.26147115766420853 + 0.26147827243134902 + 0.26148538740064342 + 0.26149250257209999 + 0.26149961794572629 + 0.26150673352153064 + 0.26151384929952204 + 0.26152096527970797 + 0.26152808146209683 + 0.26153519784669749 + 0.261542314433517 + 0.2615494312225648 + 0.26155654821384805 + 0.26156366540737619 + 0.26157078280315693 + 0.26157790040119788 + 0.26158501820150798 + 0.26159213620409483 + 0.26159925440896742 + 0.2616063728161333 + 0.2616134914256022 + 0.26162061023738031 + 0.26162772925147726 + 0.26163484846790069 + 0.26164196788665961 + 0.26164908750776156 + 0.26165620733121414 + 0.26166332735702708 + 0.26167044758520791 + 0.26167756801576497 + 0.26168468864870648 + 0.26169180948404019 + 0.26169893052177495 + 0.26170605176191908 + 0.26171317320448084 + 0.26172029484946796 + 0.26172741669688931 + 0.26173453874675251 + 0.26174166099906593 + 0.2617487834538384 + 0.26175590611107835 + 0.26176302897079268 + 0.26177015203299103 + 0.26177727529768036 + 0.26178439876487025 + 0.26179152243456838 + 0.26179864630678312 + 0.26180577038152197 + 0.26181289465879459 + 0.26182001913860803 + 0.26182714382097111 + 0.26183426870589166 + 0.2618413937933784 + 0.26184851908343981 + 0.26185564457608351 + 0.26186277027131777 + 0.26186989616915146 + 0.26187702226959303 + 0.26188414857264941 + 0.26189127507832954 + 0.26189840178664242 + 0.26190552869759565 + 0.26191265581119688 + 0.26191978312745573 + 0.26192691064637991 + 0.26193403836797702 + 0.26194116629225594 + 0.26194829441922513 + 0.26195542274889272 + 0.2619625512812665 + 0.2619696800163554 + 0.26197680895416708 + 0.26198393809470982 + 0.26199106743799261 + 0.26199819698402299 + 0.26200532673281013 + 0.26201245668436146 + 0.26201958683868481 + 0.2620267171957904 + 0.26203384775568389 + 0.2620409785183756 + 0.26204810948387375 + 0.26205524065218477 + 0.26206237202331895 + 0.2620695035972832 + 0.26207663537408665 + 0.26208376735373745 + 0.26209089953624332 + 0.26209803192161324 + 0.26210516450985483 + 0.26211229730097713 + 0.26211943029498774 + 0.26212656349189495 + 0.26213369689170718 + 0.26214083049443332 + 0.26214796430008103 + 0.26215509830865869 + 0.26216223252017451 + 0.26216936693463699 + 0.26217650155205424 + 0.26218363637243469 + 0.26219077139578595 + 0.26219790662211712 + 0.26220504205143635 + 0.2622121776837521 + 0.26221931351907202 + 0.26222644955740493 + 0.26223358579875872 + 0.26224072224314154 + 0.26224785889056246 + 0.26225499574102973 + 0.26226213279455046 + 0.26226927005113421 + 0.26227640751078868 + 0.2622835451735222 + 0.26229068303934244 + 0.26229782110825967 + 0.26230495938027959 + 0.26231209785541254 + 0.26231923653366612 + 0.26232637541504805 + 0.26233351449956732 + 0.26234065378723226 + 0.26234779327805052 + 0.26235493297203105 + 0.26236207286918223 + 0.2623692129695111 + 0.26237635327302727 + 0.26238349377973907 + 0.26239063448965416 + 0.26239777540278086 + 0.26240491651912762 + 0.26241205783870331 + 0.26241919936151498 + 0.26242634108757162 + 0.26243348301688219 + 0.26244062514945377 + 0.26244776748529597 + 0.26245491002441518 + 0.26246205276682172 + 0.2624691957125232 + 0.26247633886152738 + 0.26248348221384254 + 0.26249062576947768 + 0.26249776952844117 + 0.26250491349074068 + 0.26251205765638513 + 0.26251920202538231 + 0.26252634659774055 + 0.26253349137346882 + 0.26254063635257413 + 0.26254778153506619 + 0.26255492692095256 + 0.26256207251024172 + 0.26256921830294128 + 0.26257636429906095 + 0.26258351049860768 + 0.26259065690159117 + 0.26259780350801848 + 0.2626049503178986 + 0.26261209733123914 + 0.26261924454804919 + 0.26262639196833709 + 0.2626335395921105 + 0.2626406874193784 + 0.26264783545014858 + 0.26265498368442985 + 0.26266213212223016 + 0.26266928076355767 + 0.2626764296084208 + 0.26268357865682784 + 0.26269072790878789 + 0.26269787736430789 + 0.26270502702339693 + 0.26271217688606396 + 0.26271932695231603 + 0.2627264772221628 + 0.26273362769561137 + 0.26274077837267062 + 0.26274792925334839 + 0.26275508033765366 + 0.26276223162559464 + 0.26276938311717918 + 0.26277653481241625 + 0.26278368671131358 + 0.2627908388138801 + 0.26279799112012364 + 0.26280514363005236 + 0.26281229634367542 + 0.26281944926100054 + 0.26282660238203598 + 0.26283375570678946 + 0.26284090923527142 + 0.26284806296748808 + 0.2628552169034486 + 0.26286237104316124 + 0.26286952538663438 + 0.26287667993387576 + 0.26288383468489501 + 0.26289098963969926 + 0.26289814479829682 + 0.2629053001606973 + 0.26291245572690786 + 0.26291961149693677 + 0.26292676747079313 + 0.26293392364848522 + 0.2629410800300202 + 0.26294823661540834 + 0.26295539340465601 + 0.26296255039777228 + 0.26296970759476612 + 0.26297686499564532 + 0.26298402260041814 + 0.26299118040909375 + 0.26299833842167908 + 0.26300549663818318 + 0.26301265505861376 + 0.26301981368298055 + 0.2630269725112912 + 0.26303413154355348 + 0.26304129077977639 + 0.26304845021996831 + 0.2630556098641369 + 0.26306276971229131 + 0.26306992976443977 + 0.26307709002058943 + 0.26308425048075063 + 0.2630914111449304 + 0.26309857201313708 + 0.26310573308537916 + 0.26311289436166491 + 0.26312005584200338 + 0.26312721752640233 + 0.26313437941487011 + 0.26314154150741503 + 0.26314870380404559 + 0.26315586630477011 + 0.26316302900959698 + 0.26317019191853452 + 0.26317735503159112 + 0.2631845183487746 + 0.26319168187009395 + 0.26319884559555751 + 0.26320600952517365 + 0.26321317365895014 + 0.26322033799689537 + 0.26322750253901833 + 0.26323466728532746 + 0.26324183223583042 + 0.26324899739053631 + 0.26325616274945213 + 0.26326332831258764 + 0.26327049407995057 + 0.2632776600515499 + 0.26328482622739274 + 0.26329199260748881 + 0.26329915919184582 + 0.26330632598047149 + 0.26331349297337553 + 0.26332066017056566 + 0.26332782757204964 + 0.26333499517783643 + 0.26334216298793517 + 0.2633493310023523 + 0.26335649922109805 + 0.26336366764417957 + 0.26337083627160596 + 0.26337800510338488 + 0.26338517413952539 + 0.26339234338003531 + 0.26339951282492352 + 0.26340668247419791 + 0.2634138523278674 + 0.26342102238593984 + 0.2634281926484236 + 0.263435363115327 + 0.26344253378665922 + 0.26344970466242718 + 0.26345687574264071 + 0.26346404702730747 + 0.26347121851643529 + 0.26347839021003389 + 0.26348556210811086 + 0.2634927342106741 + 0.2634999065177332 + 0.26350707902929532 + 0.26351425174536885 + 0.2635214246659634 + 0.26352859779108623 + 0.26353577112074633 + 0.26354294465495209 + 0.26355011839371123 + 0.26355729233703212 + 0.26356446648492393 + 0.26357164083739432 + 0.26357881539445238 + 0.26358599015610584 + 0.26359316512236314 + 0.26360034029323259 + 0.26360751566872337 + 0.26361469124884318 + 0.26362186703360041 + 0.26362904302300283 + 0.26363621921706076 + 0.26364339561578076 + 0.26365057221917176 + 0.26365774902724154 + 0.26366492603999991 + 0.26367210325745455 + 0.26367928067961321 + 0.26368645830648496 + 0.26369363613807822 + 0.26370081417440072 + 0.26370799241546156 + 0.26371517086126917 + 0.26372234951183127 + 0.26372952836715624 + 0.26373670742725319 + 0.2637438866921305 + 0.263751066161796 + 0.26375824583625807 + 0.26376542571552569 + 0.2637726057996061 + 0.26377978608850894 + 0.26378696658224199 + 0.26379414728081368 + 0.26380132818423307 + 0.26380850929250721 + 0.2638156906056453 + 0.26382287212365629 + 0.2638300538465474 + 0.26383723577432761 + 0.26384441790700536 + 0.26385160024458904 + 0.26385878278708652 + 0.26386596553450742 + 0.26387314848685894 + 0.26388033164414942 + 0.26388751500638863 + 0.26389469857358366 + 0.26390188234574297 + 0.26390906632287559 + 0.26391625050498996 + 0.26392343489209324 + 0.26393061948419516 + 0.26393780428130403 + 0.26394498928342774 + 0.26395217449057462 + 0.26395935990275321 + 0.26396654551997251 + 0.26397373134223967 + 0.26398091736956436 + 0.26398810360195446 + 0.2639952900394183 + 0.26400247668196442 + 0.26400966352960109 + 0.26401685058233626 + 0.26402403784017953 + 0.26403122530313872 + 0.2640384129712216 + 0.26404560084443734 + 0.26405278892279427 + 0.26405997720630014 + 0.26406716569496413 + 0.26407435438879467 + 0.26408154328780009 + 0.2640887323919876 + 0.26409592170136764 + 0.26410311121594721 + 0.26411030093573484 + 0.26411749086073955 + 0.26412468099096925 + 0.26413187132643284 + 0.26413906186713826 + 0.26414625261309316 + 0.26415344356430809 + 0.26416063472078938 + 0.26416782608254624 + 0.26417501764958773 + 0.26418220942192155 + 0.26418940139955627 + 0.26419659358249953 + 0.26420378597076122 + 0.26421097856434911 + 0.26421817136327086 + 0.26422536436753635 + 0.26423255757715269 + 0.26423975099212887 + 0.2642469446124735 + 0.26425413843819417 + 0.26426133246930023 + 0.26426852670579992 + 0.26427572114770109 + 0.26428291579501284 + 0.26429011064774366 + 0.26429730570590132 + 0.2643045009694942 + 0.26431169643853142 + 0.2643188921130209 + 0.26432608799297158 + 0.2643332840783913 + 0.26434048036928853 + 0.26434767686567245 + 0.26435487356755072 + 0.26436207047493182 + 0.26436926758782359 + 0.26437646490623645 + 0.2643836624301768 + 0.26439086015965452 + 0.2643980580946767 + 0.26440525623525241 + 0.26441245458139012 + 0.26441965313309901 + 0.26442685189038612 + 0.26443405085325994 + 0.2644412500217303 + 0.26444844939580486 + 0.26445564897549156 + 0.26446284876079945 + 0.26447004875173702 + 0.26447724894831198 + 0.26448444935053356 + 0.26449164995840951 + 0.2644988507719489 + 0.26450605179116027 + 0.26451325301605139 + 0.2645204544466313 + 0.2645276560829079 + 0.26453485792488962 + 0.26454205997258495 + 0.264549262226003 + 0.26455646468515215 + 0.26456366735003961 + 0.26457087022067521 + 0.26457807329706667 + 0.26458527657922248 + 0.26459248006715114 + 0.26459968376086107 + 0.26460688766036133 + 0.26461409176565925 + 0.26462129607676382 + 0.26462850059368354 + 0.26463570531642749 + 0.26464291024500292 + 0.26465011537941879 + 0.26465732071968312 + 0.26466452626580556 + 0.26467173201779393 + 0.26467893797565606 + 0.26468614413940039 + 0.26469335050903675 + 0.2647005570845723 + 0.26470776386601613 + 0.26471497085337609 + 0.26472217804666132 + 0.26472938544587954 + 0.26473659305104064 + 0.26474380086215099 + 0.2647510088792206 + 0.26475821710225705 + 0.26476542553126903 + 0.26477263416626617 + 0.26477984300725499 + 0.26478705205424469 + 0.26479426130724432 + 0.26480147076626182 + 0.26480868043130557 + 0.26481589030238467 + 0.26482310037950646 + 0.26483031066267987 + 0.26483752115191411 + 0.26484473184721707 + 0.26485194274859652 + 0.26485915385606218 + 0.26486636516962203 + 0.26487357668928374 + 0.26488078841505719 + 0.26488800034694954 + 0.26489521248496989 + 0.26490242482912679 + 0.26490963737942869 + 0.2649168501358834 + 0.26492406309850008 + 0.26493127626728713 + 0.26493848964225253 + 0.26494570322340599 + 0.26495291701075402 + 0.2649601310043071 + 0.26496734520407239 + 0.26497455961005845 + 0.26498177422227426 + 0.26498898904072776 + 0.26499620406542818 + 0.26500341929638316 + 0.26501063473360192 + 0.26501785037709169 + 0.26502506622686295 + 0.26503228228292214 + 0.26503949854527903 + 0.26504671501394156 + 0.26505393168891817 + 0.26506114857021734 + 0.26506836565784825 + 0.2650755829518181 + 0.26508280045213661 + 0.26509001815881172 + 0.26509723607185187 + 0.26510445419126483 + 0.26511167251706119 + 0.2651188910492468 + 0.26512610978783208 + 0.2651333287328248 + 0.26514054788423297 + 0.26514776724206629 + 0.26515498680633193 + 0.26516220657703909 + 0.26516942655419629 + 0.26517664673781138 + 0.26518386712789405 + 0.26519108772445099 + 0.26519830852749254 + 0.26520552953702592 + 0.26521275075306039 + 0.26521997217560433 + 0.26522719380466564 + 0.2652344156402528 + 0.26524163768237496 + 0.26524885993104069 + 0.26525608238625781 + 0.26526330504803541 + 0.26527052791638139 + 0.26527775099130424 + 0.2652849742728125 + 0.26529219776091534 + 0.26529942145562119 + 0.26530664535693732 + 0.26531386946487351 + 0.26532109377943836 + 0.26532831830063885 + 0.26533554302848439 + 0.26534276796298395 + 0.26534999310414553 + 0.26535721845197757 + 0.26536444400648862 + 0.26537166976768706 + 0.2653788957355816 + 0.26538612191018063 + 0.26539334829149269 + 0.26540057487952623 + 0.2654078016742899 + 0.26541502867579209 + 0.26542225588404134 + 0.2654294832990462 + 0.26543671092081456 + 0.26544393874935612 + 0.26545116678467823 + 0.26545839502678997 + 0.26546562347569924 + 0.2654728521314158 + 0.26548008099394693 + 0.26548731006330117 + 0.2654945393394883 + 0.26550176882251619 + 0.26550899851239196 + 0.26551622840912625 + 0.26552345851272557 + 0.26553068882320036 + 0.26553791934055787 + 0.26554515006480661 + 0.26555238099595574 + 0.26555961213401374 + 0.26556684347898796 + 0.26557407503088876 + 0.26558130678972275 + 0.26558853875549976 + 0.26559577092822767 + 0.26560300330791564 + 0.26561023589457156 + 0.26561746868820391 + 0.26562470168882196 + 0.26563193489643278 + 0.26563916831104639 + 0.26564640193267053 + 0.2656536357613144 + 0.26566086979698528 + 0.26566810403969232 + 0.26567533848944463 + 0.26568257314625027 + 0.26568980801011688 + 0.26569704308105446 + 0.2657042783590709 + 0.26571151384417463 + 0.2657187495363742 + 0.26572598543567821 + 0.2657332215420945 + 0.26574045785563288 + 0.2657476943763013 + 0.26575493110410758 + 0.26576216803906094 + 0.26576940518117054 + 0.26577664253044297 + 0.26578388008688875 + 0.26579111785051507 + 0.26579835582133182 + 0.26580559399934617 + 0.26581283238456671 + 0.26582007097700322 + 0.26582730977666302 + 0.26583454878355456 + 0.26584178799768776 + 0.26584902741906979 + 0.26585626704770932 + 0.26586350688361537 + 0.26587074692679652 + 0.2658779871772608 + 0.26588522763501721 + 0.26589246830007379 + 0.26589970917243894 + 0.26590695025212202 + 0.26591419153913148 + 0.26592143303347521 + 0.26592867473516174 + 0.26593591664420035 + 0.26594315876059887 + 0.26595040108436652 + 0.26595764361551116 + 0.26596488635404131 + 0.26597212929996561 + 0.26597937245329328 + 0.26598661581403205 + 0.26599385938219061 + 0.26600110315777747 + 0.26600834714080185 + 0.26601559133127095 + 0.26602283572919466 + 0.26603008033458087 + 0.26603732514743877 + 0.26604457016777566 + 0.26605181539560063 + 0.26605906083092301 + 0.26606630647375001 + 0.26607355232409141 + 0.26608079838195525 + 0.26608804464735003 + 0.26609529112028352 + 0.26610253780076576 + 0.26610978468880397 + 0.26611703178440788 + 0.2661242790875849 + 0.26613152659834483 + 0.26613877431669425 + 0.26614602224264439 + 0.26615327037620173 + 0.26616051871737562 + 0.26616776726617386 + 0.26617501602260574 + 0.26618226498668041 + 0.26618951415840514 + 0.26619676353778926 + 0.26620401312484043 + 0.26621126291956809 + 0.26621851292198073 + 0.2662257631320869 + 0.26623301354989448 + 0.2662402641754128 + 0.26624751500865029 + 0.2662547660496149 + 0.26626201729831589 + 0.26626926875476115 + 0.26627652041896055 + 0.26628377229092071 + 0.26629102437065211 + 0.26629827665816141 + 0.26630552915345845 + 0.26631278185655177 + 0.26632003476745009 + 0.26632728788616045 + 0.26633454121269362 + 0.26634179474705594 + 0.2663490484892575 + 0.2663563024393068 + 0.26636355659721178 + 0.2663708109629816 + 0.26637806553662358 + 0.26638532031814754 + 0.26639257530756216 + 0.26639983050487526 + 0.26640708591009549 + 0.2664143415232314 + 0.26642159734429216 + 0.2664288533732857 + 0.26643610961022068 + 0.26644336605510632 + 0.2664506227079505 + 0.26645787956876177 + 0.26646513663754867 + 0.26647239391432059 + 0.26647965139908536 + 0.26648690909185085 + 0.26649416699262768 + 0.2665014251014225 + 0.26650868341824441 + 0.2665159419431028 + 0.26652320067600482 + 0.26653045961696042 + 0.26653771876597754 + 0.26654497812306471 + 0.26655223768823055 + 0.26655949746148361 + 0.26656675744283248 + 0.26657401763228578 + 0.2665812780298521 + 0.26658853863554 + 0.26659579944935802 + 0.26660306047131482 + 0.26661032170141896 + 0.26661758313967898 + 0.26662484478610354 + 0.26663210664070125 + 0.26663936870348054 + 0.26664663097445018 + 0.26665389345361801 + 0.26666115614099395 + 0.26666841903658522 + 0.26667568214040183 + 0.26668294545245103 + 0.26669020897274198 + 0.26669747270128269 + 0.26670473663808308 + 0.26671200078315105 + 0.26671926513649458 + 0.26672652969812283 + 0.26673379446804446 + 0.26674105944626808 + 0.26674832463280157 + 0.26675559002765425 + 0.26676285563083463 + 0.26677012144235135 + 0.26677738746221236 + 0.26678465369042692 + 0.26679192012700365 + 0.26679918677195041 + 0.26680645362527716 + 0.26681372068699055 + 0.26682098795710107 + 0.26682825543561611 + 0.26683552312254488 + 0.26684279101789526 + 0.26685005912167664 + 0.26685732743389751 + 0.26686459595456585 + 0.26687186468369095 + 0.26687913362128135 + 0.26688640276734504 + 0.26689367212189063 + 0.26690094168492801 + 0.26690821145646382 + 0.26691548143650867 + 0.26692275162506979 + 0.26693002202215582 + 0.26693729262777544 + 0.2669445634419384 + 0.26695183446465209 + 0.26695910569592585 + 0.26696637713576682 + 0.26697364878418567 + 0.26698092064118972 + 0.26698819270678747 + 0.26699546498098836 + 0.26700273746380021 + 0.26701001015523229 + 0.26701728305529254 + 0.26702455616398968 + 0.26703182948133286 + 0.26703910300733075 + 0.26704637674199133 + 0.26705365068532322 + 0.2670609248373349 + 0.26706819919803582 + 0.26707547376743446 + 0.26708274854553821 + 0.26709002353235689 + 0.26709729872789928 + 0.2671045741321732 + 0.26711184974518737 + 0.26711912556695033 + 0.26712640159747136 + 0.2671336778367584 + 0.26714095428482076 + 0.26714823094166651 + 0.26715550780730407 + 0.26716278488174217 + 0.26717006216499006 + 0.26717733965705581 + 0.26718461735794785 + 0.26719189526767562 + 0.26719917338624694 + 0.26720645171367058 + 0.26721373024995504 + 0.2672210089951097 + 0.2672282879491425 + 0.26723556711206203 + 0.26724284648387692 + 0.26725012606459647 + 0.26725740585422869 + 0.26726468585278207 + 0.26727196606026538 + 0.26727924647668788 + 0.26728652710205747 + 0.2672938079363828 + 0.26730108897967253 + 0.26730837023193532 + 0.26731565169318039 + 0.26732293336341506 + 0.26733021524264933 + 0.26733749733089179 + 0.26734477962814973 + 0.26735206213443247 + 0.26735934484974927 + 0.26736662777410819 + 0.26737391090751778 + 0.26738119424998674 + 0.26738847780152358 + 0.26739576156213773 + 0.26740304553183714 + 0.26741032971063039 + 0.26741761409852544 + 0.26742489869553299 + 0.26743218350165965 + 0.26743946851691469 + 0.2674467537413075 + 0.26745403917484528 + 0.26746132481753809 + 0.26746861066939381 + 0.26747589673042121 + 0.26748318300062879 + 0.26749046948002519 + 0.26749775616861987 + 0.26750504306642003 + 0.26751233017343568 + 0.26751961748967407 + 0.26752690501514526 + 0.26753419274985718 + 0.26754148069381839 + 0.26754876884703765 + 0.26755605720952363 + 0.26756334578128549 + 0.26757063456233071 + 0.26757792355266852 + 0.26758521275230823 + 0.26759250216125779 + 0.26759979177952592 + 0.26760708160712121 + 0.26761437164405233 + 0.26762166189032799 + 0.26762895234595607 + 0.26763624301094724 + 0.26764353388530815 + 0.26765082496904813 + 0.26765811626217656 + 0.26766540776470132 + 0.26767269947663047 + 0.26767999139797394 + 0.26768728352873977 + 0.26769457586893652 + 0.26770186841857296 + 0.2677091611776577 + 0.26771645414619932 + 0.26772374732420662 + 0.26773104071168807 + 0.26773833430865313 + 0.26774562811510916 + 0.267752922131066 + 0.26776021635653102 + 0.26776751079151428 + 0.26777480543602378 + 0.26778210029006805 + 0.26778939535365587 + 0.26779669062679579 + 0.26780398610949663 + 0.26781128180176689 + 0.26781857770361528 + 0.26782587381505119 + 0.26783317013608254 + 0.26784046666671729 + 0.26784776340696492 + 0.26785506035683465 + 0.26786235751633447 + 0.26786965488547304 + 0.26787695246425908 + 0.26788425025270124 + 0.26789154825080885 + 0.26789884645858919 + 0.2679061448760523 + 0.26791344350320545 + 0.2679207423400588 + 0.26792804138662019 + 0.26793534064289837 + 0.26794264010890195 + 0.26794993978463966 + 0.26795723967012081 + 0.26796453976535273 + 0.26797184007034541 + 0.26797914058510625 + 0.26798644130964511 + 0.26799374224397016 + 0.26800104338809 + 0.26800834474201324 + 0.26801564630574937 + 0.26802294807930621 + 0.26803025006269193 + 0.26803755225591652 + 0.26804485465898781 + 0.26805215727191534 + 0.26805946009470638 + 0.26806676312737099 + 0.26807406636991638 + 0.26808136982235264 + 0.26808867348468779 + 0.26809597735693119 + 0.26810328143909018 + 0.26811058573117469 + 0.26811789023319282 + 0.26812519494515324 + 0.26813249986706461 + 0.26813980499893625 + 0.26814711034077554 + 0.26815441589259248 + 0.26816172165439578 + 0.26816902762619277 + 0.26817633380799344 + 0.26818364019980584 + 0.26819094680163869 + 0.26819825361350053 + 0.26820556063540085 + 0.2682128678673476 + 0.2682201753093495 + 0.26822748296141591 + 0.26823479082355484 + 0.26824209889577494 + 0.26824940717808493 + 0.26825671567049414 + 0.26826402437301061 + 0.26827133328564301 + 0.26827864240840005 + 0.26828595174129111 + 0.26829326128432485 + 0.26830057103750854 + 0.26830788100085234 + 0.26831519117436425 + 0.26832250155805359 + 0.26832981215192836 + 0.26833712295599793 + 0.26834443397026975 + 0.26835174519475441 + 0.26835905662945858 + 0.26836636827439242 + 0.26837368012956386 + 0.26838099219498229 + 0.2683883044706557 + 0.26839561695659347 + 0.26840292965280305 + 0.26841024255929502 + 0.26841755567607678 + 0.26842486900315704 + 0.26843218254054513 + 0.26843949628824981 + 0.26844681024627842 + 0.26845412441464162 + 0.26846143879334611 + 0.268468753382402 + 0.26847606818181796 + 0.26848338319160192 + 0.26849069841176337 + 0.26849801384231103 + 0.2685053294832529 + 0.26851264533459762 + 0.26851996139635453 + 0.26852727766853185 + 0.26853459415113951 + 0.26854191084418416 + 0.26854922774767659 + 0.26855654486162411 + 0.26856386218603551 + 0.26857117972092004 + 0.26857849746628654 + 0.2685858154221436 + 0.26859313358849934 + 0.26860045196536309 + 0.26860777055274299 + 0.26861508935064826 + 0.26862240835908774 + 0.26862972757807002 + 0.26863704700760321 + 0.26864436664769675 + 0.26865168649835924 + 0.26865900655959885 + 0.26866632683142483 + 0.26867364731384591 + 0.26868096800687086 + 0.26868828891050844 + 0.26869561002476655 + 0.26870293134965467 + 0.26871025288518152 + 0.26871757463135576 + 0.26872489658818549 + 0.26873221875568071 + 0.2687395411338489 + 0.26874686372269929 + 0.2687541865222407 + 0.2687615095324819 + 0.2687688327534315 + 0.26877615618509826 + 0.2687834798274909 + 0.26879080368061742 + 0.26879812774448802 + 0.2688054520191106 + 0.26881277650449331 + 0.26882010120064614 + 0.26882742610757654 + 0.26883475122529449 + 0.26884207655380749 + 0.26884940209312547 + 0.26885672784325659 + 0.2688640538042088 + 0.26887137997599225 + 0.26887870635861499 + 0.26888603295208574 + 0.26889335975641321 + 0.26890068677160611 + 0.26890801399767389 + 0.26891534143462387 + 0.26892266908246615 + 0.26892999694120884 + 0.2689373250108606 + 0.26894465329143014 + 0.26895198178292695 + 0.26895931048535832 + 0.26896663939873505 + 0.26897396852306321 + 0.26898129785835412 + 0.26898862740461532 + 0.26899595716185543 + 0.2690032871300832 + 0.26901061730930803 + 0.26901794769953802 + 0.26902527830078254 + 0.26903260911304894 + 0.26903994013634813 + 0.26904727137068668 + 0.26905460281607468 + 0.2690619344725203 + 0.26906926634003281 + 0.26907659841862097 + 0.26908393070829301 + 0.26909126320905746 + 0.26909859592092389 + 0.26910592884390028 + 0.26911326197799595 + 0.26912059532321919 + 0.26912792887957926 + 0.26913526264708498 + 0.26914259662574436 + 0.26914993081556682 + 0.26915726521656047 + 0.26916459982873464 + 0.26917193465209821 + 0.26917926968665912 + 0.2691866049324268 + 0.26919394038941014 + 0.26920127605761773 + 0.2692086119370577 + 0.26921594802773946 + 0.26922328432967174 + 0.26923062084286264 + 0.26923795756732222 + 0.2692452945030579 + 0.26925263165007918 + 0.26925996900839466 + 0.26926730657801257 + 0.26927464435894283 + 0.26928198235119305 + 0.26928932055477317 + 0.26929665896969129 + 0.26930399759595552 + 0.2693113364335753 + 0.26931867548256005 + 0.26932601474291712 + 0.26933335421465598 + 0.26934069389778609 + 0.26934803379231481 + 0.26935537389825226 + 0.26936271421560648 + 0.2693700547443863 + 0.26937739548460038 + 0.2693847364362576 + 0.26939207759936662 + 0.26939941897393688 + 0.26940676055997587 + 0.26941410235749363 + 0.26942144436649818 + 0.26942878658699909 + 0.26943612901900366 + 0.26944347166252208 + 0.26945081451756309 + 0.26945815758413405 + 0.2694655008622458 + 0.26947284435190505 + 0.26948018805312185 + 0.26948753196590447 + 0.26949487609026218 + 0.26950222042620314 + 0.26950956497373679 + 0.26951690973287118 + 0.26952425470361513 + 0.26953159988597869 + 0.26953894527996936 + 0.26954629088559579 + 0.26955363670286753 + 0.2695609827317933 + 0.2695683289723812 + 0.26957567542464 + 0.26958302208857982 + 0.26959036896420802 + 0.26959771605153482 + 0.26960506335056694 + 0.2696124108613151 + 0.26961975858378678 + 0.26962710651799149 + 0.26963445466393787 + 0.26964180302163476 + 0.26964915159109026 + 0.26965650037231448 + 0.26966384936531484 + 0.26967119857010086 + 0.26967854798668189 + 0.26968589761506534 + 0.2696932474552608 + 0.2697005975072776 + 0.26970794777112317 + 0.26971529824680773 + 0.26972264893433862 + 0.26972999983372592 + 0.26973735094497786 + 0.26974470226810254 + 0.26975205380310996 + 0.26975940555000899 + 0.26976675750880708 + 0.26977410967951432 + 0.26978146206213877 + 0.2697888146566893 + 0.26979616746317542 + 0.26980352048160505 + 0.26981087371198709 + 0.2698182271543309 + 0.26982558080864483 + 0.26983293467493807 + 0.26984028875321814 + 0.26984764304349595 + 0.26985499754577885 + 0.26986235226007554 + 0.26986970718639569 + 0.26987706232474795 + 0.26988441767514043 + 0.26989177323758257 + 0.26989912901208257 + 0.26990648499864989 + 0.26991384119729322 + 0.2699211976080208 + 0.26992855423084194 + 0.26993591106576559 + 0.26994326811280045 + 0.2699506253719553 + 0.2699579828432383 + 0.26996534052665966 + 0.26997269842222665 + 0.26998005652994889 + 0.26998741484983507 + 0.26999477338189409 + 0.27000213212613466 + 0.27000949108256561 + 0.27001685025119571 + 0.27002420963203377 + 0.27003156922508859 + 0.27003892903036897 + 0.27004628904788436 + 0.27005364927764225 + 0.27006100971965274 + 0.27006837037392395 + 0.2700757312404648 + 0.27008309231928462 + 0.27009045361039152 + 0.27009781511379444 + 0.27010517682950214 + 0.27011253875752395 + 0.27011990089786819 + 0.27012726325054426 + 0.27013462581556025 + 0.27014198859292499 + 0.27014935158264869 + 0.27015671478473802 + 0.27016407819920391 + 0.27017144182605307 + 0.2701788056652964 + 0.27018616971694126 + 0.27019353398099721 + 0.27020089845747236 + 0.27020826314637619 + 0.27021562804771754 + 0.27022299316150517 + 0.2702303584877479 + 0.27023772402645391 + 0.27024508977763256 + 0.27025245574129281 + 0.27025982191744335 + 0.27026718830609314 + 0.27027455490725083 + 0.2702819217209253 + 0.27028928874712538 + 0.27029665598585983 + 0.2703040234371375 + 0.27031139110096786 + 0.27031875897735846 + 0.27032612706631937 + 0.27033349536785872 + 0.27034086388198542 + 0.27034823260870816 + 0.27035560154803651 + 0.27036297069997794 + 0.2703703400645433 + 0.27037770964173935 + 0.27038507943157619 + 0.27039244943406282 + 0.27039981964920723 + 0.27040719007701902 + 0.27041456071750619 + 0.27042193157067768 + 0.27042930263654302 + 0.27043667391511089 + 0.27044404540639022 + 0.27045141711038911 + 0.27045878902711712 + 0.27046616115658234 + 0.27047353349879488 + 0.27048090605376235 + 0.27048827882149423 + 0.2704956518019993 + 0.27050302499528633 + 0.27051039840136426 + 0.27051777202024119 + 0.27052514585192727 + 0.27053251989643062 + 0.27053989415376017 + 0.27054726862392409 + 0.27055464330693246 + 0.27056201820279413 + 0.27056939331151658 + 0.27057676863311009 + 0.27058414416758197 + 0.27059151991494251 + 0.27059889587520058 + 0.27060627204836352 + 0.2706136484344423 + 0.27062102503344371 + 0.27062840184537795 + 0.27063577887025309 + 0.27064315610807876 + 0.27065053355886365 + 0.2706579112226154 + 0.27066528909934479 + 0.27067266718905991 + 0.27068004549176844 + 0.27068742400748103 + 0.27069480273620533 + 0.27070218167795079 + 0.27070956083272624 + 0.27071694020054049 + 0.27072431978140177 + 0.27073169957532023 + 0.27073907958230409 + 0.27074645980236139 + 0.27075384023550181 + 0.27076122088173471 + 0.2707686017410677 + 0.27077598281351095 + 0.27078336409907255 + 0.27079074559776145 + 0.27079812730958641 + 0.27080550923455637 + 0.27081289137268072 + 0.27082027372396772 + 0.2708276562884262 + 0.27083503906606565 + 0.27084242205689429 + 0.27084980526092095 + 0.27085718867815511 + 0.27086457230860572 + 0.27087195615228082 + 0.27087934020918936 + 0.27088672447934148 + 0.27089410896274474 + 0.27090149365940863 + 0.27090887856934132 + 0.27091626369255234 + 0.27092364902905053 + 0.27093103457884476 + 0.27093842034194388 + 0.27094580631835613 + 0.27095319250809158 + 0.27096057891115782 + 0.27096796552756502 + 0.2709753523573214 + 0.27098273940043516 + 0.27099012665691641 + 0.27099751412677342 + 0.27100490181001502 + 0.2710122897066507 + 0.27101967781668801 + 0.27102706614013716 + 0.27103445467700704 + 0.27104184342730508 + 0.27104923239104223 + 0.27105662156822524 + 0.27106401095886512 + 0.27107140056296858 + 0.27107879038054594 + 0.27108618041160604 + 0.27109357065615763 + 0.27110096111420906 + 0.27110835178576975 + 0.27111574267084859 + 0.27112313376945452 + 0.27113052508159563 + 0.27113791660728148 + 0.27114530834652101 + 0.27115270029932298 + 0.27116009246569633 + 0.27116748484565056 + 0.27117487743919322 + 0.27118227024633385 + 0.27118966326708133 + 0.2711970565014451 + 0.27120444994943355 + 0.27121184361105533 + 0.2712192374863201 + 0.27122663157523608 + 0.27123402587781209 + 0.27124142039405702 + 0.27124881512398041 + 0.27125621006759121 + 0.27126360522489745 + 0.27127100059590881 + 0.27127839618063343 + 0.27128579197908093 + 0.27129318799126007 + 0.27130058421717912 + 0.27130798065684769 + 0.27131537731027455 + 0.27132277417746864 + 0.27133017125843883 + 0.27133756855319396 + 0.27134496606174291 + 0.27135236378409394 + 0.27135976172025722 + 0.27136715987024101 + 0.27137455823405415 + 0.27138195681170546 + 0.27138935560320465 + 0.27139675460855983 + 0.27140415382777983 + 0.27141155326087363 + 0.27141895290785079 + 0.2714263527687194 + 0.27143375284348914 + 0.27144115313216821 + 0.27144855363476611 + 0.27145595435129172 + 0.27146335528175336 + 0.27147075642616042 + 0.27147815778452128 + 0.27148555935684604 + 0.27149296114314231 + 0.27150036314341969 + 0.27150776535768689 + 0.27151516778595303 + 0.27152257042822625 + 0.27152997328451672 + 0.27153737635483272 + 0.27154477963918305 + 0.27155218313757734 + 0.27155958685002318 + 0.27156699077653079 + 0.27157439491710833 + 0.27158179927176473 + 0.2715892038405095 + 0.27159660862335094 + 0.27160401362029796 + 0.2716114188313607 + 0.27161882425654615 + 0.27162622989586444 + 0.27163363574932453 + 0.27164104181693527 + 0.27164844809870503 + 0.2716558545946432 + 0.27166326130475876 + 0.27167066822906061 + 0.27167807536755756 + 0.271685482720258 + 0.27169289028717208 + 0.27170029806830737 + 0.27170770606367406 + 0.27171511427328049 + 0.27172252269713543 + 0.27172993133524787 + 0.27173734018762741 + 0.27174474925428216 + 0.27175215853522117 + 0.27175956803045326 + 0.27176697773998798 + 0.27177438766383433 + 0.2717817978020004 + 0.27178920815449525 + 0.2717966187213291 + 0.27180402950250943 + 0.27181144049804584 + 0.27181885170794662 + 0.27182626313222202 + 0.27183367477087955 + 0.27184108662392886 + 0.27184849869137878 + 0.2718559109732383 + 0.27186332346951625 + 0.27187073618022156 + 0.27187814910536384 + 0.2718855622449507 + 0.27189297559899234 + 0.27190038916749698 + 0.27190780295047356 + 0.27191521694793164 + 0.27192263115987958 + 0.27193004558632683 + 0.27193746022728166 + 0.27194487508275367 + 0.27195229015275113 + 0.27195970543728432 + 0.27196712093636005 + 0.27197453664998933 + 0.2719819525781797 + 0.27198936872094143 + 0.27199678507828212 + 0.27200420165021133 + 0.27201161843673799 + 0.27201903543787098 + 0.27202645265361924 + 0.27203387008399249 + 0.27204128772899816 + 0.27204870558864652 + 0.27205612366294585 + 0.2720635419519058 + 0.27207096045553447 + 0.27207837917384103 + 0.27208579810683481 + 0.27209321725452423 + 0.27210063661691952 + 0.27210805619402761 + 0.27211547598585872 + 0.27212289599242179 + 0.27213031621372574 + 0.27213773664977958 + 0.27214515730059213 + 0.27215257816617172 + 0.27215999924652856 + 0.27216742054167026 + 0.27217484205160714 + 0.27218226377634741 + 0.27218968571590002 + 0.2721971078702739 + 0.27220453023947855 + 0.27221195282352245 + 0.27221937562241433 + 0.27222679863616395 + 0.27223422186477947 + 0.2722416453082705 + 0.27224906896664597 + 0.27225649283991427 + 0.27226391692808483 + 0.27227134123116603 + 0.27227876574916809 + 0.27228619048209862 + 0.27229361542996727 + 0.27230104059278293 + 0.27230846597055453 + 0.27231589156329172 + 0.27232331737100202 + 0.27233074339369584 + 0.27233816963138135 + 0.27234559608406755 + 0.27235302275176332 + 0.27236044963447836 + 0.27236787673222085 + 0.27237530404500038 + 0.27238273157282533 + 0.27239015931570532 + 0.27239758727364921 + 0.27240501544666523 + 0.2724124438347631 + 0.27241987243795174 + 0.27242730125624015 + 0.2724347302896365 + 0.27244215953815115 + 0.27244958900179228 + 0.27245701868056826 + 0.27246444857448937 + 0.27247187868356393 + 0.27247930900780143 + 0.27248673954720953 + 0.27249417030179862 + 0.27250160127157685 + 0.27250903245655395 + 0.27251646385673878 + 0.27252389547213901 + 0.27253132730276552 + 0.27253875934862609 + 0.27254619160973015 + 0.27255362408608674 + 0.27256105677770415 + 0.27256848968459274 + 0.27257592280675996 + 0.2725833561442163 + 0.2725907896969692 + 0.27259822346502904 + 0.27260565744840343 + 0.2726130916471034 + 0.27262052606113574 + 0.27262796069051093 + 0.27263539553523708 + 0.27264283059532335 + 0.27265026587077923 + 0.27265770136161366 + 0.27266513706783507 + 0.27267257298945297 + 0.27268000912647633 + 0.27268744547891344 + 0.27269488204677467 + 0.27270231883006762 + 0.27270975582880191 + 0.27271719304298647 + 0.27272463047263035 + 0.27273206811774309 + 0.27273950597833302 + 0.27274694405440847 + 0.27275438234598037 + 0.27276182085305573 + 0.2727692595756448 + 0.27277669851375652 + 0.27278413766739934 + 0.27279157703658202 + 0.27279901662131512 + 0.272806456421606 + 0.27281389643746451 + 0.2728213366688988 + 0.2728287771159193 + 0.27283621777853356 + 0.27284365865675198 + 0.27285109975058208 + 0.27285854106003427 + 0.2728659825851168 + 0.27287342432583866 + 0.27288086628220881 + 0.27288830845423689 + 0.27289575084193118 + 0.27290319344530145 + 0.27291063626435591 + 0.27291807929910422 + 0.27292552254955466 + 0.27293296601571693 + 0.27294040969759992 + 0.27294785359521279 + 0.27295529770856364 + 0.27296274203766357 + 0.27297018658251881 + 0.27297763134314051 + 0.27298507631953678 + 0.27299252151171677 + 0.27299996691968931 + 0.27300741254346417 + 0.2730148583830489 + 0.2730223044384546 + 0.27302975070968888 + 0.27303719719676062 + 0.27304464389968025 + 0.27305209081845477 + 0.27305953795309507 + 0.27306698530360884 + 0.27307443287000649 + 0.27308188065229561 + 0.27308932865048574 + 0.27309677686458605 + 0.2731042252946061 + 0.27311167394055352 + 0.27311912280243872 + 0.27312657188026995 + 0.27313402117405627 + 0.27314147068380729 + 0.27314892040953132 + 0.27315637035123808 + 0.27316382050893578 + 0.27317127088263493 + 0.27317872147234307 + 0.27318617227806907 + 0.2731936232998235 + 0.27320107453761394 + 0.27320852599145068 + 0.27321597766134131 + 0.27322342954729634 + 0.2732308816493233 + 0.27323833396743258 + 0.27324578650163311 + 0.27325323925193334 + 0.27326069221834215 + 0.27326814540086858 + 0.27327559879952301 + 0.27328305241431239 + 0.2732905062452477 + 0.27329796029233666 + 0.27330541455558893 + 0.27331286903501345 + 0.27332032373061932 + 0.27332777864241548 + 0.27333523377041091 + 0.27334268911461468 + 0.27335014467503577 + 0.27335760045168378 + 0.27336505644456716 + 0.27337251265369489 + 0.27337996907907663 + 0.27338742572072061 + 0.27339488257863676 + 0.27340233965283317 + 0.27340979694331957 + 0.27341725445010506 + 0.27342471217319858 + 0.27343217011260923 + 0.27343962826834589 + 0.27344708664041761 + 0.27345454522883345 + 0.27346200403360238 + 0.27346946305473341 + 0.27347692229223625 + 0.27348438174611917 + 0.27349184141639127 + 0.27349930130306216 + 0.273506761406141 + 0.27351422172563594 + 0.27352168226155676 + 0.27352914301391251 + 0.27353660398271212 + 0.27354406516796403 + 0.27355152656967852 + 0.27355898818786323 + 0.27356645002252866 + 0.27357391207368309 + 0.2735813743413355 + 0.2735888368254949 + 0.27359629952617109 + 0.27360376244337226 + 0.27361122557710826 + 0.27361868892738805 + 0.27362615249421995 + 0.27363361627761296 + 0.2736410802775775 + 0.2736485444941219 + 0.27365600892725456 + 0.27366347357698512 + 0.27367093844332258 + 0.2736784035262767 + 0.27368586882585583 + 0.27369333434206894 + 0.27370080007492509 + 0.27370826602443399 + 0.27371573219060397 + 0.27372319857344474 + 0.27373066517296535 + 0.27373813198917407 + 0.27374559902208073 + 0.27375306627169432 + 0.27376053373802312 + 0.2737680014210776 + 0.27377546932086599 + 0.27378293743739751 + 0.27379040577068031 + 0.27379787432072494 + 0.27380534308754034 + 0.273812812071135 + 0.2738202812715177 + 0.27382775068869836 + 0.27383522032268598 + 0.27384269017348883 + 0.27385016024111669 + 0.27385763052557865 + 0.27386510102688294 + 0.27387257174504004 + 0.27388004268005833 + 0.27388751383194676 + 0.2738949852007137 + 0.27390245678636965 + 0.27390992858892349 + 0.27391740060838377 + 0.27392487284475936 + 0.27393234529806004 + 0.2739398179682942 + 0.2739472908554722 + 0.27395476395960111 + 0.27396223728069197 + 0.27396971081875304 + 0.27397718457379283 + 0.27398465854582171 + 0.27399213273484729 + 0.27399960714088079 + 0.27400708176392841 + 0.27401455660400192 + 0.27402203166110911 + 0.27402950693525885 + 0.27403698242646107 + 0.27404445813472472 + 0.27405193406005818 + 0.27405941020247115 + 0.27406688656197264 + 0.27407436313857114 + 0.27408183993227703 + 0.27408931694309857 + 0.27409679417104493 + 0.27410427161612511 + 0.27411174927834814 + 0.27411922715772385 + 0.27412670525426047 + 0.27413418356796715 + 0.27414166209885427 + 0.27414914084692954 + 0.27415661981220202 + 0.27416409899468208 + 0.27417157839437745 + 0.27417905801129788 + 0.2741865378454531 + 0.27419401789685083 + 0.27420149816550138 + 0.27420897865141319 + 0.27421645935459543 + 0.27422394027505764 + 0.27423142141280765 + 0.27423890276785651 + 0.27424638434021192 + 0.27425386612988373 + 0.2742613481368808 + 0.2742688303612123 + 0.27427631280288667 + 0.27428379546191423 + 0.27429127833830269 + 0.2742987614320625 + 0.27430624474320214 + 0.27431372827173123 + 0.27432121201765747 + 0.27432869598099202 + 0.2743361801617426 + 0.27434366455991821 + 0.27435114917552866 + 0.27435863400858296 + 0.2743661190590902 + 0.27437360432705948 + 0.2743810898124992 + 0.27438857551541967 + 0.2743960614358294 + 0.27440354757373742 + 0.2744110339291535 + 0.27441852050208598 + 0.27442600729254396 + 0.27443349430053726 + 0.27444098152607477 + 0.27444846896916514 + 0.27445595662981787 + 0.27446344450804283 + 0.27447093260384714 + 0.27447842091724173 + 0.27448590944823514 + 0.27449339819683705 + 0.27450088716305526 + 0.27450837634690006 + 0.27451586574837994 + 0.27452335536750472 + 0.27453084520428339 + 0.27453833525872434 + 0.2745458255308374 + 0.27455331602063088 + 0.27456080672811528 + 0.27456829765329832 + 0.27457578879619043 + 0.27458328015679934 + 0.27459077173513541 + 0.2745982635312072 + 0.27460575554502431 + 0.27461324777659529 + 0.2746207402259298 + 0.27462823289303623 + 0.27463572577792444 + 0.27464321888060278 + 0.27465071220108167 + 0.27465820573936961 + 0.27466569949547492 + 0.27467319346940799 + 0.27468068766117743 + 0.27468818207079215 + 0.27469567669826123 + 0.27470317154359458 + 0.27471066660680049 + 0.2747181618878895 + 0.27472565738686855 + 0.27473315310374891 + 0.27474064903853818 + 0.27474814519124618 + 0.27475564156188204 + 0.27476313815045544 + 0.27477063495697429 + 0.27477813198144885 + 0.27478562922388755 + 0.27479312668430028 + 0.2748006243626947 + 0.27480812225908208 + 0.2748156203734699 + 0.27482311870586812 + 0.27483061725628583 + 0.2748381160247314 + 0.27484561501121529 + 0.27485311421574593 + 0.27486061363833236 + 0.27486811327898381 + 0.27487561313770997 + 0.2748831132145193 + 0.27489061350942079 + 0.27489811402242509 + 0.27490561475353908 + 0.27491311570277405 + 0.27492061687013764 + 0.27492811825563968 + 0.27493561985928994 + 0.27494312168109614 + 0.27495062372106877 + 0.2749581259792156 + 0.27496562845554701 + 0.27497313115007227 + 0.2749806340627996 + 0.27498813719373894 + 0.27499564054289866 + 0.27500314411028859 + 0.27501064789591773 + 0.27501815189979528 + 0.27502565612193036 + 0.27503316056233207 + 0.27504066522100945 + 0.27504817009797239 + 0.27505567519322921 + 0.27506318050678913 + 0.27507068603866192 + 0.27507819178885662 + 0.27508569775738173 + 0.27509320394424702 + 0.27510071034946093 + 0.27510821697303395 + 0.27511572381497446 + 0.27512323087529234 + 0.27513073815399525 + 0.27513824565109307 + 0.27514575336659558 + 0.27515326130051188 + 0.2751607694528504 + 0.27516827782362091 + 0.27517578641283263 + 0.2751832952204939 + 0.27519080424661457 + 0.27519831349120438 + 0.27520582295427121 + 0.27521333263582543 + 0.27522084253587548 + 0.27522835265443057 + 0.27523586299150044 + 0.27524337354709355 + 0.27525088432121975 + 0.27525839531388802 + 0.27526590652510763 + 0.27527341795488697 + 0.27528092960323652 + 0.27528844147016412 + 0.2752959535556801 + 0.27530346585979304 + 0.27531097838251201 + 0.27531849112384688 + 0.27532600408380603 + 0.2753335172623993 + 0.27534103065963572 + 0.27534854427552397 + 0.27535605811007369 + 0.27536357216329466 + 0.27537108643519476 + 0.27537860092578442 + 0.27538611563507143 + 0.27539363056306626 + 0.27540114570977808 + 0.27540866107521533 + 0.27541617665938717 + 0.27542369246230397 + 0.27543120848397301 + 0.275438724724406 + 0.27544624118361016 + 0.27545375786159521 + 0.27546127475837029 + 0.27546879187394457 + 0.27547630920832789 + 0.27548382676152866 + 0.27549134453355673 + 0.27549886252442052 + 0.27550638073412986 + 0.27551389916269398 + 0.2755214178101219 + 0.27552893667642214 + 0.27553645576160518 + 0.27554397506567951 + 0.2755514945886543 + 0.27555901433053853 + 0.27556653429134226 + 0.27557405447107447 + 0.27558157486974366 + 0.27558909548735971 + 0.27559661632393101 + 0.27560413737946809 + 0.2756116586539788 + 0.2756191801474735 + 0.27562670185996085 + 0.27563422379144981 + 0.27564174594194968 + 0.27564926831147024 + 0.27565679090001993 + 0.27566431370760924 + 0.27567183673424528 + 0.27567935997993936 + 0.27568688344469922 + 0.27569440712853521 + 0.27570193103145607 + 0.27570945515347067 + 0.2757169794945884 + 0.27572450405481902 + 0.27573202883417092 + 0.27573955383265408 + 0.27574707905027679 + 0.27575460448704908 + 0.27576213014298062 + 0.27576965601807935 + 0.27577718211235508 + 0.27578470842581682 + 0.2757922349584746 + 0.27579976171033677 + 0.27580728868141258 + 0.2758148158717118 + 0.27582234328124361 + 0.27582987091001648 + 0.27583739875804025 + 0.27584492682532419 + 0.27585245511187728 + 0.2758599836177088 + 0.27586751234282852 + 0.27587504128724505 + 0.27588257045096748 + 0.27589009983400486 + 0.27589762943636786 + 0.2759051592580643 + 0.27591268929910323 + 0.27592021955949531 + 0.27592775003924824 + 0.27593528073837259 + 0.27594281165687679 + 0.27595034279477004 + 0.2759578741520623 + 0.27596540572876194 + 0.27597293752487811 + 0.27598046954042144 + 0.27598800177539967 + 0.2759955342298227 + 0.27600306690369963 + 0.27601059979703968 + 0.27601813290985194 + 0.27602566624214575 + 0.27603319979393082 + 0.27604073356521575 + 0.27604826755601025 + 0.27605580176632366 + 0.27606333619616436 + 0.2760708708455416 + 0.27607840571446585 + 0.27608594080294563 + 0.27609347611099083 + 0.27610101163860923 + 0.27610854738581136 + 0.27611608335260646 + 0.27612361953900227 + 0.27613115594501009 + 0.27613869257063767 + 0.27614622941589489 + 0.27615376648079099 + 0.27616130376533504 + 0.27616884126953634 + 0.27617637899340469 + 0.27618391693694855 + 0.27619145510017723 + 0.27619899348309979 + 0.27620653208572682 + 0.27621407090806616 + 0.27622160995012768 + 0.27622914921192049 + 0.27623668869345386 + 0.27624422839473767 + 0.27625176831577969 + 0.27625930845659047 + 0.27626684881717856 + 0.27627438939755378 + 0.27628193019772534 + 0.27628947121770181 + 0.27629701245749294 + 0.27630455391710801 + 0.27631209559655617 + 0.27631963749584737 + 0.27632717961498998 + 0.27633472195399328 + 0.27634226451286653 + 0.27634980729161951 + 0.27635735029026137 + 0.27636489350880145 + 0.27637243694724811 + 0.27637998060561203 + 0.27638752448390097 + 0.27639506858212554 + 0.27640261290029416 + 0.2764101574384169 + 0.27641770219650202 + 0.27642524717455963 + 0.2764327923725981 + 0.27644033779062743 + 0.27644788342865667 + 0.27645542928669586 + 0.27646297536475273 + 0.27647052166283714 + 0.2764780681809591 + 0.27648561491912704 + 0.27649316187735085 + 0.27650070905563978 + 0.27650825645400229 + 0.2765158040724483 + 0.27652335191098704 + 0.27653089996962765 + 0.27653844824838003 + 0.27654599674725272 + 0.27655354546625432 + 0.27656109440539595 + 0.27656864356468558 + 0.27657619294413294 + 0.27658374254374746 + 0.27659129236353747 + 0.27659884240351362 + 0.27660639266368442 + 0.27661394314405913 + 0.2766214938446469 + 0.27662904476545763 + 0.27663659590649992 + 0.27664414726778352 + 0.27665169884931784 + 0.27665925065111197 + 0.27666680267317439 + 0.27667435491551579 + 0.27668190737814469 + 0.27668946006107026 + 0.27669701296430238 + 0.27670456608784966 + 0.27671211943172197 + 0.27671967299592781 + 0.27672722678047779 + 0.27673478078537977 + 0.2767423350106436 + 0.27674988945627921 + 0.27675744412229453 + 0.27676499900870077 + 0.27677255411550505 + 0.27678010944271869 + 0.27678766499034951 + 0.27679522075840679 + 0.27680277674690107 + 0.27681033295584095 + 0.2768178893852356 + 0.27682544603509429 + 0.27683300290542617 + 0.27684055999624119 + 0.2768481173075486 + 0.27685567483935691 + 0.276863232591676 + 0.27687079056451519 + 0.27687834875788359 + 0.27688590717179051 + 0.27689346580624524 + 0.27690102466125682 + 0.2769085837368353 + 0.27691614303298995 + 0.27692370254972914 + 0.27693126228706294 + 0.27693882224500055 + 0.27694638242355113 + 0.27695394282272401 + 0.27696150344252835 + 0.27696906428297408 + 0.27697662534406975 + 0.27698418662582469 + 0.27699174812824934 + 0.27699930985135168 + 0.27700687179514155 + 0.27701443395962827 + 0.27702199634482105 + 0.27702955895072912 + 0.27703712177736167 + 0.27704468482472872 + 0.2770522480928394 + 0.27705981158170229 + 0.27706737529132741 + 0.27707493922172394 + 0.27708250337290102 + 0.27709006774486805 + 0.27709763233763418 + 0.2771051971512094 + 0.27711276218560216 + 0.27712032744082249 + 0.27712789291687895 + 0.2771354586137813 + 0.27714302453153905 + 0.27715059067016123 + 0.27715815702965785 + 0.27716572361003677 + 0.27717329041130867 + 0.27718085743348209 + 0.27718842467656685 + 0.27719599214057167 + 0.27720355982550704 + 0.2772111277313809 + 0.27721869585820325 + 0.27722626420598384 + 0.2772338327747314 + 0.27724140156445509 + 0.27724897057516423 + 0.27725653980686937 + 0.27726410925957778 + 0.27727167893330074 + 0.27727924882804678 + 0.27728681894382518 + 0.27729438928064526 + 0.27730195983851608 + 0.27730953061744784 + 0.27731710161744888 + 0.2773246728385293 + 0.2773322442806983 + 0.27733981594396445 + 0.27734738782833834 + 0.27735495993382864 + 0.27736253226044449 + 0.27737010480819518 + 0.27737767757709075 + 0.2773852505671397 + 0.27739282377835189 + 0.27740039721073673 + 0.27740797086430274 + 0.27741554473906055 + 0.27742311883501874 + 0.27743069315218655 + 0.27743826769057395 + 0.27744584245018955 + 0.27745341743104318 + 0.27746099263314355 + 0.27746856805650055 + 0.27747614370112411 + 0.27748371956702222 + 0.27749129565420477 + 0.27749887196268169 + 0.27750644849246225 + 0.27751402524355506 + 0.27752160221596939 + 0.27752917940971589 + 0.27753675682480239 + 0.27754433446123961 + 0.27755191231903542 + 0.27755949039820044 + 0.27756706869874326 + 0.27757464722067388 + 0.27758222596400084 + 0.27758980492873414 + 0.27759738411488299 + 0.27760496352245678 + 0.27761254315146466 + 0.27762012300191591 + 0.27762770307382056 + 0.27763528336718724 + 0.2776428638820258 + 0.27765044461834487 + 0.2776580255761551 + 0.27766560675546442 + 0.27767318815628272 + 0.27768076977861944 + 0.27768835162248429 + 0.27769593368788609 + 0.27770351597483472 + 0.2777110984833388 + 0.27771868121340831 + 0.27772626416505314 + 0.27773384733828121 + 0.27774143073310259 + 0.27774901434952648 + 0.27775659818756282 + 0.27776418224722099 + 0.27777176652850954 + 0.27777935103143769 + 0.27778693575601621 + 0.27779452070225369 + 0.2778021058701593 + 0.27780969125974248 + 0.27781727687101238 + 0.27782486270397905 + 0.27783244875865182 + 0.27784003503503918 + 0.27784762153315112 + 0.27785520825299703 + 0.27786279519458612 + 0.27787038235792838 + 0.27787796974303242 + 0.27788555734990755 + 0.27789314517856306 + 0.2779007332290096 + 0.27790832150125505 + 0.27791590999531013 + 0.27792349871118277 + 0.27793108764888363 + 0.27793867680842133 + 0.27794626618980506 + 0.27795385579304493 + 0.27796144561815017 + 0.27796903566512943 + 0.27797662593399336 + 0.27798421642474985 + 0.27799180713740962 + 0.27799939807198132 + 0.27800698922847417 + 0.27801458060689815 + 0.27802217220726261 + 0.27802976402957691 + 0.27803735607384955 + 0.27804494834009119 + 0.27805254082831055 + 0.27806013353851688 + 0.2780677264707202 + 0.2780753196249291 + 0.27808291300115284 + 0.27809050659940215 + 0.27809810041968563 + 0.278105694462012 + 0.27811328872639179 + 0.27812088321283374 + 0.27812847792134771 + 0.27813607285194242 + 0.27814366800462786 + 0.27815126337941332 + 0.2781588589763081 + 0.27816645479532154 + 0.2781740508364629 + 0.27818164709974152 + 0.27818924358516744 + 0.27819684029274988 + 0.27820443722249755 + 0.27821203437442038 + 0.27821963174852776 + 0.27822722934482891 + 0.27823482716333325 + 0.27824242520405074 + 0.27825002346698996 + 0.27825762195216097 + 0.27826522065957232 + 0.27827281958923478 + 0.27828041874115633 + 0.27828801811534754 + 0.27829561771181716 + 0.27830321753057441 + 0.27831081757162934 + 0.27831841783499062 + 0.27832601832066817 + 0.27833361902867138 + 0.27834121995900951 + 0.27834882111169196 + 0.27835642248672876 + 0.27836402408412836 + 0.2783716259039003 + 0.27837922794605446 + 0.27838683021060018 + 0.27839443269754682 + 0.27840203540690373 + 0.27840963833868015 + 0.27841724149288549 + 0.27842484486952973 + 0.2784324484686222 + 0.27844005229017144 + 0.27844765633418767 + 0.27845526060068004 + 0.2784628650896579 + 0.27847046980113138 + 0.27847807473510838 + 0.27848567989159961 + 0.27849328527061434 + 0.27850089087216195 + 0.27850849669625105 + 0.2785161027428924 + 0.27852370901209395 + 0.27853131550386639 + 0.27853892221821902 + 0.27854652915516054 + 0.27855413631470027 + 0.27856174369684894 + 0.27856935130161442 + 0.27857695912900687 + 0.27858456717903624 + 0.27859217545171111 + 0.27859978394704166 + 0.27860739266503642 + 0.27861500160570474 + 0.27862261076905742 + 0.27863022015510303 + 0.27863782976385093 + 0.27864543959531046 + 0.27865304964949167 + 0.27866065992640254 + 0.27866827042605441 + 0.27867588114845593 + 0.27868349209361587 + 0.27869110326154484 + 0.27869871465225149 + 0.27870632626574532 + 0.2787139381020361 + 0.27872155016113276 + 0.27872916244304513 + 0.27873677494778265 + 0.27874438767535398 + 0.27875200062576982 + 0.27875961379903952 + 0.27876722719517111 + 0.2787748408141752 + 0.27878245465606122 + 0.27879006872083917 + 0.27879768300851643 + 0.27880529751910427 + 0.2788129122526114 + 0.27882052720904726 + 0.2788281423884218 + 0.27883575779074438 + 0.27884337341602378 + 0.27885098926426982 + 0.27885860533549278 + 0.27886622162970043 + 0.27887383814690364 + 0.27888145488711102 + 0.27888907185033268 + 0.27889668903657716 + 0.27890430644585534 + 0.27891192407817517 + 0.27891954193354729 + 0.2789271600119797 + 0.27893477831348396 + 0.27894239683806787 + 0.27895001558574095 + 0.27895763455651312 + 0.27896525375039449 + 0.27897287316739311 + 0.27898049280751891 + 0.278988112670782 + 0.27899573275719175 + 0.27900335306675678 + 0.27901097359948723 + 0.27901859435539172 + 0.27902621533448102 + 0.27903383653676372 + 0.27904145796225005 + 0.27904907961094849 + 0.27905670148286854 + 0.27906432357802025 + 0.27907194589641354 + 0.27907956843805659 + 0.27908719120295938 + 0.27909481419113191 + 0.27910243740258289 + 0.27911006083732248 + 0.27911768449535923 + 0.27912530837670396 + 0.27913293248136462 + 0.27914055680935129 + 0.27914818136067404 + 0.27915580613534163 + 0.27916343113336395 + 0.27917105635475048 + 0.27917868179950994 + 0.27918630746765233 + 0.2791939333591878 + 0.27920155947412489 + 0.27920918581247306 + 0.2792168123742424 + 0.27922443915944162 + 0.27923206616808138 + 0.27923969340016974 + 0.27924732085571674 + 0.27925494853473248 + 0.27926257643722568 + 0.27927020456320634 + 0.27927783291268315 + 0.27928546148566624 + 0.27929309028216504 + 0.27930071930218875 + 0.27930834854574693 + 0.27931597801285024 + 0.27932360770350606 + 0.2793312376177251 + 0.27933886775551681 + 0.27934649811689044 + 0.27935412870185555 + 0.27936175951042147 + 0.27936939054259818 + 0.27937702179839446 + 0.27938465327782047 + 0.27939228498088475 + 0.27939991690759813 + 0.27940754905796938 + 0.27941518143200778 + 0.2794228140297228 + 0.27943044685112445 + 0.27943807989622216 + 0.27944571316502537 + 0.27945334665754273 + 0.27946098037378497 + 0.27946861431376085 + 0.27947624847747982 + 0.27948388286495185 + 0.27949151747618572 + 0.27949915231119216 + 0.27950678736997925 + 0.27951442265255766 + 0.27952205815893555 + 0.27952969388912424 + 0.27953732984313118 + 0.27954496602096779 + 0.27955260242264207 + 0.27956023904816479 + 0.27956787589754473 + 0.27957551297079047 + 0.27958315026791364 + 0.27959078778892216 + 0.27959842553382619 + 0.27960606350263434 + 0.27961370169535682 + 0.27962134011200368 + 0.27962897875258358 + 0.27963661761710668 + 0.27964425670558163 + 0.27965189601801865 + 0.27965953555442702 + 0.27966717531481622 + 0.27967481529919558 + 0.27968245550757453 + 0.2796900959399633 + 0.27969773659637109 + 0.27970537747680746 + 0.27971301858128106 + 0.27972065990980205 + 0.27972830146238042 + 0.27973594323902506 + 0.27974358523974585 + 0.27975122746455172 + 0.27975886991345267 + 0.27976651258645818 + 0.27977415548357754 + 0.27978179860482094 + 0.27978944195019712 + 0.27979708551971616 + 0.27980472931338679 + 0.27981237333121906 + 0.27982001757322245 + 0.27982766203940707 + 0.27983530672978157 + 0.27984295164435558 + 0.27985059678313889 + 0.27985824214614047 + 0.27986588773337107 + 0.27987353354483863 + 0.27988117958055408 + 0.2798888258405261 + 0.27989647232476478 + 0.27990411903327955 + 0.27991176596607914 + 0.2799194131231737 + 0.27992706050457261 + 0.27993470811028603 + 0.27994235594032263 + 0.27995000399469261 + 0.27995765227340463 + 0.27996530077646881 + 0.27997294950389462 + 0.27998059845569145 + 0.27998824763187019 + 0.27999589703243805 + 0.28000354665740596 + 0.28001119650678263 + 0.2800188465805788 + 0.28002649687880332 + 0.28003414740146554 + 0.2800417981485756 + 0.28004944912014162 + 0.28005710031617498 + 0.28006475173668449 + 0.28007240338167888 + 0.28008005525116902 + 0.28008770734516358 + 0.28009535966367272 + 0.28010301220670519 + 0.28011066497427101 + 0.28011831796637976 + 0.28012597118304083 + 0.28013362462426372 + 0.28014127829005764 + 0.28014893218043369 + 0.28015658629539975 + 0.28016424063496531 + 0.28017189519914121 + 0.28017954998793621 + 0.28018720500135968 + 0.28019486023942175 + 0.28020251570213128 + 0.28021017138949827 + 0.28021782730153227 + 0.28022548343824266 + 0.28023313979963965 + 0.28024079638573191 + 0.28024845319652891 + 0.28025611023204072 + 0.28026376749227694 + 0.28027142497724689 + 0.28027908268696006 + 0.28028674062142661 + 0.28029439878065454 + 0.28030205716465539 + 0.28030971577343794 + 0.28031737460701095 + 0.2803250336653853 + 0.28033269294856966 + 0.28034035245657346 + 0.28034801218940625 + 0.28035567214707885 + 0.2803633323295992 + 0.28037099273697835 + 0.28037865336922485 + 0.2803863142263483 + 0.28039397530835808 + 0.28040163661526502 + 0.28040929814707721 + 0.28041695990380483 + 0.28042462188545803 + 0.28043228409204479 + 0.28043994652357612 + 0.28044760918006129 + 0.28045527206150983 + 0.28046293516793053 + 0.2804705984993342 + 0.28047826205572968 + 0.28048592583712634 + 0.28049358984353434 + 0.28050125407496324 + 0.28050891853142168 + 0.28051658321292056 + 0.28052424811946869 + 0.28053191325107546 + 0.28053957860775103 + 0.28054724418950427 + 0.28055490999634525 + 0.28056257602828411 + 0.28057024228532967 + 0.28057790876749067 + 0.28058557547477869 + 0.28059324240720185 + 0.28060090956477018 + 0.28060857694749325 + 0.28061624455537976 + 0.28062391238844137 + 0.28063158044668612 + 0.28063924873012336 + 0.28064691723876345 + 0.28065458597261567 + 0.28066225493169028 + 0.2806699241159954 + 0.28067759352554184 + 0.28068526316033909 + 0.28069293302039589 + 0.28070060310572242 + 0.28070827341632826 + 0.28071594395222343 + 0.28072361471341672 + 0.28073128569991773 + 0.2807389569117365 + 0.28074662834888259 + 0.28075430001136542 + 0.28076197189919522 + 0.28076964401238003 + 0.28077731635093139 + 0.28078498891485754 + 0.28079266170416844 + 0.28080033471887372 + 0.28080800795898203 + 0.28081568142450508 + 0.28082335511545098 + 0.28083102903182905 + 0.28083870317365023 + 0.28084637754092268 + 0.28085405213365716 + 0.28086172695186262 + 0.28086940199554838 + 0.28087707726472472 + 0.28088475275940106 + 0.2808924284795869 + 0.28090010442529179 + 0.28090778059652516 + 0.28091545699329717 + 0.28092313361561733 + 0.28093081046349444 + 0.28093848753693879 + 0.2809461648359603 + 0.28095384236056736 + 0.28096152011077069 + 0.28096919808657977 + 0.28097687628800416 + 0.28098455471505329 + 0.28099223336773671 + 0.28099991224606397 + 0.28100759135004505 + 0.2810152706796889 + 0.28102295023500573 + 0.28103063001600492 + 0.28103831002269608 + 0.2810459902550887 + 0.28105367071319287 + 0.28106135139701816 + 0.28106903230657337 + 0.28107671344186863 + 0.28108439480291425 + 0.28109207638971828 + 0.28109975820229227 + 0.28110744024064366 + 0.28111512250478476 + 0.28112280499472225 + 0.28113048771046772 + 0.28113817065203001 + 0.28114585381941853 + 0.2811535372126443 + 0.28116122083171541 + 0.28116890467664196 + 0.28117658874743351 + 0.2811842730440996 + 0.28119195756665044 + 0.28119964231509548 + 0.28120732728944353 + 0.28121501248970548 + 0.28122269791589022 + 0.2812303835680065 + 0.28123806944606594 + 0.28124575555007664 + 0.28125344188004875 + 0.28126112843599194 + 0.28126881521791552 + 0.28127650222582984 + 0.28128418945974365 + 0.28129187691966651 + 0.28129956460560929 + 0.28130725251758082 + 0.2813149406555906 + 0.28132262901964811 + 0.28133031760976362 + 0.28133800642594597 + 0.28134569546820526 + 0.2813533847365518 + 0.28136107423099371 + 0.28136876395154192 + 0.28137645389820581 + 0.28138414407099432 + 0.28139183446991833 + 0.28139952509498595 + 0.28140721594620749 + 0.28141490702359373 + 0.28142259832715211 + 0.28143028985689367 + 0.28143798161282851 + 0.28144567359496486 + 0.28145336580331348 + 0.28146105823788337 + 0.28146875089868462 + 0.28147644378572612 + 0.2814841368990188 + 0.28149183023857149 + 0.28149952380439358 + 0.28150721759649544 + 0.2815149116148859 + 0.28152260585957511 + 0.28153030033057264 + 0.28153799502788868 + 0.2815456899515314 + 0.28155338510151168 + 0.28156108047783912 + 0.28156877608052322 + 0.28157647190957352 + 0.28158416796499947 + 0.28159186424681137 + 0.28159956075501807 + 0.28160725748962973 + 0.28161495445065593 + 0.28162265163810551 + 0.28163034905199008 + 0.28163804669231712 + 0.28164574455909819 + 0.28165344265234143 + 0.28166114097205724 + 0.28166883951825489 + 0.2816765382909448 + 0.28168423729013581 + 0.28169193651583802 + 0.28169963596806036 + 0.28170733564681377 + 0.28171503555210714 + 0.28172273568395056 + 0.28173043604235232 + 0.28173813662732389 + 0.28174583743887432 + 0.28175353847701234 + 0.28176123974174888 + 0.28176894123309282 + 0.28177664295105503 + 0.28178434489564308 + 0.28179204706686856 + 0.28179974946474023 + 0.28180745208926772 + 0.28181515494046128 + 0.2818228580183304 + 0.28183056132288403 + 0.28183826485413227 + 0.2818459686120855 + 0.28185367259675242 + 0.28186137680814344 + 0.28186908124626736 + 0.28187678591113507 + 0.28188449080275474 + 0.2818921959211374 + 0.28189990126629177 + 0.28190760683822824 + 0.28191531263695624 + 0.28192301866248537 + 0.28193072491482452 + 0.28193843139398528 + 0.28194613809997587 + 0.28195384503280579 + 0.28196155219248598 + 0.28196925957902469 + 0.28197696719243276 + 0.28198467503271984 + 0.28199238309989472 + 0.28200009139396703 + 0.28200779991494762 + 0.28201550866284547 + 0.2820232176376708 + 0.28203092683943243 + 0.28203863626813985 + 0.28204634592380351 + 0.28205405580643356 + 0.28206176591603882 + 0.28206947625262896 + 0.28207718681621424 + 0.28208489760680405 + 0.28209260862440744 + 0.28210031986903528 + 0.28210803134069651 + 0.28211574303940129 + 0.28212345496515856 + 0.28213116711797931 + 0.28213887949787164 + 0.28214659210484583 + 0.28215430493891291 + 0.28216201800008095 + 0.28216973128835959 + 0.28217744480375978 + 0.28218515854628967 + 0.28219287251596026 + 0.28220058671278114 + 0.2822083011367611 + 0.28221601578791045 + 0.28222373066623951 + 0.28223144577175641 + 0.28223916110447206 + 0.28224687666439618 + 0.2822545924515375 + 0.28226230846590716 + 0.28227002470751317 + 0.28227774117636656 + 0.28228545787247694 + 0.28229317479585386 + 0.2823008919465062 + 0.28230860932444429 + 0.28231632692967829 + 0.28232404476221717 + 0.28233176282207118 + 0.28233948110924989 + 0.2823471996237622 + 0.28235491836561916 + 0.28236263733483019 + 0.2823703565314043 + 0.28237807595535169 + 0.28238579560668137 + 0.2823935154854042 + 0.28240123559152908 + 0.28240895592506632 + 0.28241667648602548 + 0.28242439727441548 + 0.28243211829024734 + 0.28243983953352914 + 0.28244756100427265 + 0.28245528270248604 + 0.28246300462817886 + 0.2824707267813622 + 0.28247844916204479 + 0.28248617177023633 + 0.28249389460594715 + 0.28250161766918669 + 0.28250934095996399 + 0.28251706447828995 + 0.28252478822417354 + 0.28253251219762493 + 0.28254023639865383 + 0.28254796082726907 + 0.28255568548348103 + 0.28256341036729993 + 0.28257113547873464 + 0.28257886081779549 + 0.28258658638449136 + 0.2825943121788333 + 0.28260203820083013 + 0.28260976445049152 + 0.28261749092782773 + 0.2826252176328477 + 0.28263294456556237 + 0.28264067172598067 + 0.2826483991141121 + 0.28265612672996715 + 0.28266385457355464 + 0.28267158264488551 + 0.28267931094396803 + 0.28268703947081314 + 0.28269476822542988 + 0.28270249720782836 + 0.28271022641801835 + 0.28271795585600934 + 0.28272568552181104 + 0.28273341541543362 + 0.28274114553688612 + 0.28274887588617881 + 0.28275660646332124 + 0.28276433726832306 + 0.28277206830119461 + 0.28277979956194471 + 0.28278753105058441 + 0.28279526276712202 + 0.28280299471156772 + 0.28281072688393188 + 0.28281845928422333 + 0.28282619191245251 + 0.28283392476862895 + 0.28284165785276233 + 0.28284939116486219 + 0.28285712470493884 + 0.28286485847300191 + 0.2828725924690611 + 0.28288032669312524 + 0.28288806114520532 + 0.28289579582531033 + 0.28290353073345054 + 0.28291126586963555 + 0.28291900123387509 + 0.28292673682617936 + 0.2829344726465573 + 0.28294220869501857 + 0.28294994497157344 + 0.28295768147623163 + 0.28296541820900328 + 0.28297315516989746 + 0.28298089235892382 + 0.28298862977609324 + 0.28299636742141404 + 0.28300410529489722 + 0.28301184339655178 + 0.28301958172638786 + 0.28302732028441452 + 0.28303505907064286 + 0.28304279808508087 + 0.28305053732773977 + 0.28305827679862916 + 0.28306601649775792 + 0.28307375642513638 + 0.28308149658077492 + 0.28308923696468169 + 0.28309697757686852 + 0.28310471841734353 + 0.28311245948611713 + 0.28312020078319899 + 0.28312794230859933 + 0.28313568406232709 + 0.28314342604439269 + 0.28315116825480574 + 0.28315891069357513 + 0.28316665336071256 + 0.28317439625622637 + 0.28318213938012621 + 0.28318988273242229 + 0.28319762631312501 + 0.28320537012224328 + 0.28321311415978684 + 0.28322085842576594 + 0.28322860292019014 + 0.28323634764306926 + 0.2832440925944128 + 0.28325183777423119 + 0.28325958318253402 + 0.2832673288193302 + 0.28327507468463087 + 0.28328282077844485 + 0.28329056710078193 + 0.28329831365165231 + 0.28330606043106571 + 0.28331380743903173 + 0.2833215546755608 + 0.28332930214066177 + 0.28333704983434432 + 0.28334479775661953 + 0.28335254590749559 + 0.28336029428698356 + 0.28336804289509315 + 0.28337579173183325 + 0.28338354079721417 + 0.28339129009124564 + 0.28339903961393725 + 0.28340678936529945 + 0.28341453934534105 + 0.28342228955407323 + 0.28343003999150479 + 0.28343779065764557 + 0.28344554155250506 + 0.2834532926760937 + 0.28346104402842115 + 0.283468795609497 + 0.2834765474193317 + 0.28348429945793341 + 0.28349205172531394 + 0.28349980422148219 + 0.28350755694644786 + 0.28351530990022067 + 0.28352306308281083 + 0.2835308164942274 + 0.28353857013448081 + 0.28354632400358126 + 0.2835540781015371 + 0.28356183242835936 + 0.28356958698405837 + 0.28357734176864186 + 0.28358509678212207 + 0.28359285202450735 + 0.2836006074958074 + 0.28360836319603261 + 0.2836161191251918 + 0.28362387528329619 + 0.28363163167035527 + 0.28363938828637753 + 0.28364714513137457 + 0.28365490220535544 + 0.28366265950832975 + 0.28367041704030721 + 0.2836781748012982 + 0.28368593279131238 + 0.28369369101035929 + 0.28370144945844877 + 0.28370920813559042 + 0.28371696704179467 + 0.28372472617707112 + 0.28373248554142944 + 0.28374024513487928 + 0.28374800495743119 + 0.28375576500909394 + 0.28376352528987869 + 0.28377128579979366 + 0.28377904653884933 + 0.28378680750705593 + 0.28379456870442332 + 0.28380233013096101 + 0.28381009178667804 + 0.28381785367158552 + 0.28382561578569304 + 0.28383337812900972 + 0.28384114070154653 + 0.28384890350331171 + 0.28385666653431652 + 0.28386442979456972 + 0.28387219328408186 + 0.28387995700286256 + 0.28388772095092146 + 0.28389548512826901 + 0.28390324953491419 + 0.28391101417086728 + 0.2839187790361381 + 0.28392654413073698 + 0.28393430945467224 + 0.2839420750079556 + 0.28394984079059538 + 0.28395760680260196 + 0.28396537304398572 + 0.28397313951475567 + 0.2839809062149215 + 0.28398867314449427 + 0.28399644030348298 + 0.28400420769189733 + 0.28401197530974703 + 0.28401974315704243 + 0.28402751123379394 + 0.28403527954000984 + 0.28404304807570124 + 0.28405081684087713 + 0.2840585858355486 + 0.284066355059724 + 0.28407412451341363 + 0.28408189419662788 + 0.28408966410937653 + 0.28409743425166856 + 0.2841052046235143 + 0.28411297522492418 + 0.28412074605590726 + 0.2841285171164738 + 0.28413628840663302 + 0.28414405992639574 + 0.28415183167577118 + 0.28415960365476967 + 0.28416737586340018 + 0.2841751483016739 + 0.28418292096959968 + 0.28419069386718665 + 0.28419846699444656 + 0.2842062403513877 + 0.28421401393802131 + 0.28422178775435547 + 0.28422956180040149 + 0.28423733607616891 + 0.28424511058166751 + 0.28425288531690635 + 0.28426066028189717 + 0.28426843547664826 + 0.28427621090116945 + 0.28428398655547099 + 0.28429176243956267 + 0.28429953855345486 + 0.28430731489715738 + 0.28431509147067907 + 0.28432286827403047 + 0.28433064530722191 + 0.28433842257026182 + 0.28434620006316186 + 0.28435397778593113 + 0.28436175573857869 + 0.28436953392111558 + 0.28437731233355079 + 0.28438509097589554 + 0.28439286984815804 + 0.28440064895034878 + 0.28440842828247814 + 0.28441620784455512 + 0.28442398763659021 + 0.28443176765859374 + 0.28443954791057408 + 0.28444732839254233 + 0.2844551091045075 + 0.28446289004648084 + 0.28447067121847042 + 0.28447845262048754 + 0.28448623425254194 + 0.28449401611464259 + 0.28450179820679983 + 0.28450958052902425 + 0.28451736308132475 + 0.28452514586371103 + 0.28453292887619436 + 0.28454071211878301 + 0.28454849559148804 + 0.2845562792943192 + 0.28456406322728484 + 0.28457184739039681 + 0.28457963178366474 + 0.28458741640709706 + 0.28459520126070492 + 0.28460298634449793 + 0.28461077165848597 + 0.28461855720267931 + 0.28462634297708711 + 0.28463412898171903 + 0.28464191521658555 + 0.28464970168169701 + 0.28465748837706256 + 0.28466527530269192 + 0.28467306245859614 + 0.28468084984478359 + 0.28468863746126549 + 0.28469642530805073 + 0.28470421338514984 + 0.28471200169257188 + 0.28471979023032795 + 0.28472757899842704 + 0.28473536799687893 + 0.28474315722569482 + 0.28475094668488299 + 0.28475873637445454 + 0.28476652629441929 + 0.28477431644478557 + 0.28478210682556515 + 0.28478989743676714 + 0.28479768827840124 + 0.28480547935047723 + 0.28481327065300627 + 0.28482106218599729 + 0.2848288539494595 + 0.28483664594340391 + 0.28484443816784039 + 0.28485223062277859 + 0.28486002330822829 + 0.28486781622419916 + 0.28487560937070183 + 0.28488340274774587 + 0.28489119635534044 + 0.28489899019349596 + 0.28490678426222354 + 0.28491457856153152 + 0.28492237309143037 + 0.28493016785192926 + 0.28493796284303985 + 0.28494575806477068 + 0.28495355351713136 + 0.28496134920013311 + 0.28496914511378496 + 0.28497694125809664 + 0.28498473763307869 + 0.28499253423874077 + 0.28500033107509271 + 0.28500812814214493 + 0.28501592543990645 + 0.2850237229683879 + 0.2850315207275988 + 0.28503931871754906 + 0.28504711693824902 + 0.28505491538970862 + 0.28506271407193684 + 0.28507051298494474 + 0.28507831212874146 + 0.28508611150333679 + 0.28509391110874188 + 0.28510171094496511 + 0.28510951101201759 + 0.28511731130990908 + 0.28512511183864869 + 0.28513291259824686 + 0.28514071358871412 + 0.28514851481005871 + 0.2851563162622926 + 0.28516411794542407 + 0.28517191985946444 + 0.28517972200442193 + 0.28518752438030848 + 0.2851953269871324 + 0.28520312982490426 + 0.28521093289363442 + 0.28521873619333205 + 0.28522653972400752 + 0.28523434348567001 + 0.2852421474783306 + 0.28524995170199907 + 0.28525775615668386 + 0.28526556084239685 + 0.28527336575914697 + 0.28528117090694421 + 0.28528897628579886 + 0.28529678189572011 + 0.28530458773671907 + 0.28531239380880485 + 0.28532020011198728 + 0.28532800664627667 + 0.28533581341168301 + 0.28534362040821593 + 0.28535142763588528 + 0.28535923509470146 + 0.28536704278467434 + 0.2853748507058137 + 0.2853826588581293 + 0.28539046724163158 + 0.28539827585633043 + 0.28540608470223472 + 0.28541389377935589 + 0.28542170308770293 + 0.28542951262728622 + 0.2854373223981157 + 0.28544513240020103 + 0.28545294263355209 + 0.28546075309818009 + 0.28546856379409324 + 0.28547637472130227 + 0.28548418587981678 + 0.2854919972696473 + 0.28549980889080367 + 0.285507620743295 + 0.28551543282713238 + 0.28552324514232569 + 0.28553105768888404 + 0.28553887046681775 + 0.28554668347613754 + 0.28555449671685162 + 0.28556231018897205 + 0.28557012389250708 + 0.28557793782746732 + 0.28558575199386316 + 0.28559356639170375 + 0.28560138102099958 + 0.28560919588176042 + 0.28561701097399683 + 0.2856248262977179 + 0.28563264185293408 + 0.28564045763965523 + 0.28564827365789108 + 0.28565608990765146 + 0.28566390638894684 + 0.28567172310178712 + 0.28567954004618201 + 0.28568735722214206 + 0.28569517462967631 + 0.28570299226879603 + 0.28571081013950961 + 0.28571862824182825 + 0.28572644657576035 + 0.28573426514131844 + 0.28574208393851042 + 0.28574990296734665 + 0.28575772222783757 + 0.28576554171999247 + 0.28577336144382315 + 0.28578118139933667 + 0.28578900158654558 + 0.28579682200545831 + 0.28580464265608541 + 0.28581246353843665 + 0.28582028465252252 + 0.28582810599835218 + 0.28583592757593618 + 0.2858437493852849 + 0.28585157142640694 + 0.28585939369931401 + 0.28586721620401462 + 0.2858750389405193 + 0.28588286190883855 + 0.28589068510898152 + 0.28589850854095872 + 0.28590633220477984 + 0.2859141561004549 + 0.28592198022799425 + 0.28592980458740785 + 0.28593762917870469 + 0.28594545400189603 + 0.28595327905699108 + 0.28596110434400018 + 0.28596892986293398 + 0.28597675561380098 + 0.28598458159661155 + 0.28599240781137619 + 0.28600023425810556 + 0.28600806093680803 + 0.28601588784749482 + 0.28602371499017576 + 0.28603154236485995 + 0.28603936997155793 + 0.28604719781028026 + 0.28605502588103665 + 0.28606285418383637 + 0.28607068271868996 + 0.28607851148560781 + 0.28608634048459913 + 0.28609416971567447 + 0.28610199917884355 + 0.28610982887411707 + 0.28611765880150403 + 0.28612548896101431 + 0.28613331935265912 + 0.28614114997644768 + 0.28614898083239043 + 0.28615681192049647 + 0.28616464324077645 + 0.28617247479324082 + 0.28618030657789878 + 0.28618813859476011 + 0.28619597084383608 + 0.28620380332513579 + 0.28621163603866906 + 0.2862194689844465 + 0.28622730216247799 + 0.28623513557277319 + 0.28624296921534287 + 0.28625080309019668 + 0.28625863719734379 + 0.28626647153679485 + 0.28627430610856031 + 0.28628214091264925 + 0.28628997594907241 + 0.28629781121784015 + 0.28630564671896175 + 0.28631348245244692 + 0.28632131841830638 + 0.28632915461655045 + 0.28633699104718846 + 0.28634482771023018 + 0.28635266460568615 + 0.28636050173356697 + 0.28636833909388104 + 0.28637617668664034 + 0.2863840145118533 + 0.28639185256953043 + 0.28639969085968237 + 0.28640752938231823 + 0.2864153681374485 + 0.28642320712508318 + 0.28643104634523198 + 0.2864388857979055 + 0.28644672548311362 + 0.28645456540086611 + 0.28646240555117297 + 0.28647024593404463 + 0.28647808654949103 + 0.28648592739752121 + 0.2864937684781465 + 0.28650160979137612 + 0.28650945133722122 + 0.28651729311569035 + 0.28652513512679467 + 0.28653297737054273 + 0.28654081984694713 + 0.28654866255601569 + 0.28655650549775891 + 0.28656434867218661 + 0.28657219207931017 + 0.2865800357191387 + 0.28658787959168136 + 0.28659572369695013 + 0.28660356803495346 + 0.28661141260570189 + 0.28661925740920602 + 0.28662710244547501 + 0.28663494771451942 + 0.28664279321634911 + 0.28665063895097392 + 0.28665848491840457 + 0.28666633111865064 + 0.28667417755172164 + 0.28668202421762856 + 0.28668987111638072 + 0.28669771824798868 + 0.28670556561246291 + 0.28671341320981197 + 0.28672126104004719 + 0.28672910910317828 + 0.28673695739921523 + 0.28674480592816792 + 0.28675265469004679 + 0.28676050368486189 + 0.28676835291262232 + 0.28677620237333934 + 0.28678405206702284 + 0.28679190199368199 + 0.28679975215332743 + 0.2868076025459696 + 0.28681545317161777 + 0.28682330403028261 + 0.28683115512197455 + 0.28683900644670202 + 0.28684685800447651 + 0.28685470979530775 + 0.28686256181920566 + 0.28687041407618086 + 0.28687826656624249 + 0.28688611928940039 + 0.28689397224566665 + 0.28690182543504894 + 0.28690967885755869 + 0.28691753251320562 + 0.28692538640199905 + 0.28693324052395086 + 0.28694109487906966 + 0.28694894946736593 + 0.28695680428884957 + 0.28696465934353049 + 0.28697251463141932 + 0.28698037015252587 + 0.28698822590686007 + 0.28699608189443254 + 0.28700393811525315 + 0.28701179456933107 + 0.28701965125667689 + 0.28702750817730127 + 0.28703536533121327 + 0.28704322271842431 + 0.28705108033894355 + 0.28705893819278089 + 0.28706679627994691 + 0.28707465460045151 + 0.28708251315430455 + 0.28709037194151665 + 0.28709823096209708 + 0.28710609021605699 + 0.2871139497034057 + 0.28712180942415311 + 0.2871296693783098 + 0.28713752956588562 + 0.28714538998689121 + 0.28715325064133573 + 0.28716111152922985 + 0.28716897265058344 + 0.28717683400540639 + 0.28718469559370929 + 0.28719255741550215 + 0.28720041947079478 + 0.28720828175959701 + 0.28721614428191961 + 0.2872240070377724 + 0.28723187002716533 + 0.28723973325010815 + 0.28724759670661171 + 0.28725546039668581 + 0.28726332432034102 + 0.28727118847758587 + 0.28727905286843242 + 0.28728691749288909 + 0.28729478235096723 + 0.28730264744267614 + 0.28731051276802627 + 0.28731837832702695 + 0.2873262441196901 + 0.28733411014602439 + 0.28734197640603959 + 0.28734984289974708 + 0.28735770962715601 + 0.28736557658827638 + 0.28737344378311946 + 0.2873813112116938 + 0.28738917887401066 + 0.28739704677007932 + 0.28740491489991099 + 0.2874127832635151 + 0.2874206518609006 + 0.28742852069207975 + 0.28743638975706159 + 0.28744425905585619 + 0.28745212858847335 + 0.28745999835492381 + 0.28746786835521732 + 0.28747573858936465 + 0.28748360905737502 + 0.28749147975925826 + 0.2874993506950258 + 0.28750722186468675 + 0.28751509326825186 + 0.28752296490573098 + 0.28753083677713337 + 0.2875387088824703 + 0.28754658122175175 + 0.28755445379498695 + 0.28756232660218722 + 0.28757019964336183 + 0.28757807291852133 + 0.28758594642767565 + 0.28759382017083479 + 0.28760169414800862 + 0.28760956835920859 + 0.28761744280444307 + 0.2876253174837235 + 0.28763319239705976 + 0.28764106754446039 + 0.28764894292593823 + 0.28765681854150094 + 0.28766469439115994 + 0.28767257047492523 + 0.28768044679280663 + 0.28768832334481487 + 0.28769620013095981 + 0.28770407715125079 + 0.28771195440569836 + 0.28771983189431322 + 0.28772770961710525 + 0.28773558757408441 + 0.28774346576526066 + 0.28775134419064463 + 0.28775922285024558 + 0.28776710174407483 + 0.28777498087214165 + 0.28778286023445665 + 0.2877907398310291 + 0.28779861966187037 + 0.28780649972698963 + 0.28781438002639753 + 0.28782226056010413 + 0.28783014132811924 + 0.28783802233045291 + 0.28784590356711642 + 0.28785378503811837 + 0.28786166674347008 + 0.28786954868318082 + 0.28787743085726192 + 0.28788531326572259 + 0.28789319590857221 + 0.28790107878582272 + 0.28790896189748266 + 0.28791684524356348 + 0.28792472882407433 + 0.28793261263902598 + 0.28794049668842825 + 0.2879483809722912 + 0.28795626549062547 + 0.28796415024344102 + 0.28797203523074766 + 0.28797992045255555 + 0.28798780590887529 + 0.28799569159971611 + 0.28800357752508937 + 0.28801146368500502 + 0.28801935007947232 + 0.28802723670850194 + 0.28803512357210465 + 0.28804301067028948 + 0.28805089800306732 + 0.28805878557044801 + 0.28806667337244152 + 0.28807456140905852 + 0.28808244968030899 + 0.28809033818620361 + 0.28809822692675086 + 0.28810611590196294 + 0.28811400511184837 + 0.28812189455641846 + 0.28812978423568253 + 0.28813767414965114 + 0.28814556429833516 + 0.28815345468174303 + 0.2881613452998868 + 0.28816923615277507 + 0.28817712724041861 + 0.28818501856282858 + 0.28819291012001308 + 0.28820080191198399 + 0.28820869393875076 + 0.28821658620032392 + 0.28822447869671347 + 0.28823237142792874 + 0.28824026439398109 + 0.28824815759488048 + 0.2882560510306369 + 0.28826394470126027 + 0.28827183860676131 + 0.28827973274714935 + 0.288287627122435 + 0.28829552173262896 + 0.28830341657774045 + 0.28831131165778096 + 0.28831920697275898 + 0.28832710252268601 + 0.28833499830757181 + 0.28834289432742666 + 0.28835079058226026 + 0.28835868707208279 + 0.28836658379690555 + 0.28837448075673705 + 0.28838237795158889 + 0.28839027538147083 + 0.28839817304639231 + 0.28840607094636461 + 0.28841396908139716 + 0.28842186745150117 + 0.2884297660566853 + 0.28843766489696027 + 0.28844556397233673 + 0.28845346328282473 + 0.28846136282843488 + 0.28846926260917582 + 0.28847716262505968 + 0.28848506287609493 + 0.28849296336229308 + 0.28850086408366404 + 0.28850876504021716 + 0.28851666623196309 + 0.2885245676589126 + 0.2885324693210749 + 0.28854037121846138 + 0.28854827335108146 + 0.28855617571894498 + 0.28856407832206277 + 0.28857198116044547 + 0.28857988423410158 + 0.28858778754304337 + 0.28859569108727934 + 0.28860359486682025 + 0.28861149888167675 + 0.2886194031318588 + 0.28862730761737654 + 0.28863521233823985 + 0.28864311729445941 + 0.28865102248604535 + 0.28865892791300762 + 0.28866683357535688 + 0.28867473947310252 + 0.28868264560625584 + 0.28869055197482552 + 0.28869845857882365 + 0.28870636541825878 + 0.28871427249314169 + 0.28872217980348308 + 0.28873008734929295 + 0.28873799513058135 + 0.28874590314735821 + 0.28875381139963346 + 0.28876171988741878 + 0.28876962861072331 + 0.28877753756955699 + 0.2887854467639307 + 0.28879335619385432 + 0.28880126585933796 + 0.28880917576039222 + 0.28881708589702654 + 0.28882499626925229 + 0.28883290687707946 + 0.2888408177205174 + 0.28884872879957679 + 0.28885664011426765 + 0.28886455166460145 + 0.28887246345058676 + 0.28888037547223427 + 0.28888828772955405 + 0.28889620022255685 + 0.28890411295125334 + 0.28891202591565213 + 0.28891993911576469 + 0.28892785255160169 + 0.2889357662231718 + 0.28894368013048638 + 0.28895159427355482 + 0.28895950865238851 + 0.28896742326699615 + 0.28897533811738968 + 0.28898325320357793 + 0.28899116852557222 + 0.28899908408338187 + 0.28900699987701767 + 0.28901491590648892 + 0.28902283217180769 + 0.28903074867298201 + 0.28903866541002393 + 0.28904658238294284 + 0.28905449959174939 + 0.28906241703645302 + 0.28907033471706439 + 0.28907825263359355 + 0.28908617078605192 + 0.28909408917444818 + 0.28910200779879369 + 0.28910992665909779 + 0.28911784575537058 + 0.28912576508762344 + 0.28913368465586575 + 0.28914160446010823 + 0.28914952450036091 + 0.2891574447766338 + 0.28916536528893771 + 0.28917328603728265 + 0.28918120702167788 + 0.28918912824213494 + 0.28919704969866389 + 0.28920497139127466 + 0.28921289331997735 + 0.28922081548478273 + 0.2892287378857008 + 0.28923666052274088 + 0.28924458339591519 + 0.28925250650523165 + 0.28926042985070238 + 0.28926835343233742 + 0.28927627725014615 + 0.28928420130413929 + 0.28929212559432693 + 0.28930005012071974 + 0.28930797488332705 + 0.2893158998821605 + 0.28932382511722848 + 0.28933175058854338 + 0.2893396762961144 + 0.28934760223995165 + 0.28935552842006512 + 0.28936345483646558 + 0.28937138148916391 + 0.28937930837816855 + 0.28938723550349182 + 0.289395162865143 + 0.28940309046313217 + 0.28941101829747012 + 0.28941894636816612 + 0.28942687467523165 + 0.28943480321867604 + 0.28944273199851017 + 0.28945066101474398 + 0.28945859026738829 + 0.28946651975645243 + 0.28947444948194717 + 0.28948237944388328 + 0.28949030964227007 + 0.28949824007711839 + 0.28950617074843826 + 0.28951410165623964 + 0.28952203280053412 + 0.28952996418133037 + 0.28953789579863981 + 0.28954582765247178 + 0.28955375974283776 + 0.28956169206974719 + 0.28956962463320929 + 0.28957755743323632 + 0.28958549046983767 + 0.28959342374302416 + 0.28960135725280495 + 0.28960929099919164 + 0.28961722498219367 + 0.28962515920182091 + 0.28963309365808437 + 0.28964102835099398 + 0.28964896328056122 + 0.28965689844679404 + 0.28966483384970465 + 0.28967276948930243 + 0.28968070536559887 + 0.28968864147860263 + 0.28969657782832448 + 0.28970451441477513 + 0.28971245123796474 + 0.28972038829790336 + 0.28972832559460182 + 0.28973626312806944 + 0.28974420089831759 + 0.28975213890535589 + 0.28976007714919422 + 0.28976801562984417 + 0.28977595434731507 + 0.28978389330161769 + 0.28979183249276147 + 0.28979977192075784 + 0.28980771158561691 + 0.28981565148734806 + 0.28982359162596205 + 0.28983153200146966 + 0.28983947261388104 + 0.28984741346320553 + 0.28985535454945455 + 0.28986329587263759 + 0.28987123743276538 + 0.28987917922984874 + 0.28988712126389704 + 0.28989506353492112 + 0.28990300604293168 + 0.28991094878793738 + 0.28991889176994984 + 0.28992683498897981 + 0.28993477844503596 + 0.28994272213813044 + 0.28995066606827202 + 0.28995861023547215 + 0.28996655463974025 + 0.28997449928108709 + 0.28998244415952273 + 0.28999038927505805 + 0.28999833462770236 + 0.29000628021746722 + 0.290014226044362 + 0.29002217210839754 + 0.29003011840958381 + 0.29003806494793105 + 0.29004601172345001 + 0.29005395873615009 + 0.29006190598604276 + 0.29006985347313813 + 0.29007780119744564 + 0.29008574915897606 + 0.29009369735774021 + 0.2901016457937482 + 0.2901095944670094 + 0.29011754337753531 + 0.29012549252533609 + 0.29013344191042106 + 0.2901413915328025 + 0.29014934139248838 + 0.29015729148949021 + 0.29016524182381881 + 0.29017319239548356 + 0.29018114320449534 + 0.2901890942508642 + 0.29019704553460091 + 0.29020499705571495 + 0.29021294881421783 + 0.2902209008101182 + 0.29022885304342833 + 0.29023680551415693 + 0.29024475822231544 + 0.29025271116791335 + 0.29026066435096148 + 0.29026861777147062 + 0.2902765714294494 + 0.29028452532491011 + 0.2902924794578623 + 0.29030043382831583 + 0.29030838843628243 + 0.29031634328177069 + 0.29032429836479146 + 0.29033225368535626 + 0.29034020924347381 + 0.290348165039155 + 0.29035612107241049 + 0.29036407734325126 + 0.29037203385168597 + 0.2903799905977254 + 0.29038794758138115 + 0.29039590480266264 + 0.2904038622615806 + 0.29041181995814452 + 0.29041977789236517 + 0.29042773606425348 + 0.29043569447381884 + 0.29044365312107273 + 0.29045161200602387 + 0.29045957112868453 + 0.29046753048906421 + 0.29047549008717211 + 0.29048344992302072 + 0.2904914099966186 + 0.29049937030797668 + 0.29050733085710567 + 0.29051529164401585 + 0.2905232526687172 + 0.29053121393122067 + 0.29053917543153562 + 0.29054713716967367 + 0.29055509914564415 + 0.29056306135945725 + 0.29057102381112454 + 0.29057898650065539 + 0.29058694942805996 + 0.2905949125933498 + 0.29060287599653428 + 0.29061083963762441 + 0.29061880351662939 + 0.29062676763356088 + 0.29063473198842837 + 0.29064269658124264 + 0.29065066141201451 + 0.29065862648075347 + 0.29066659178746967 + 0.29067455733217457 + 0.29068252311487769 + 0.29069048913559059 + 0.29069845539432188 + 0.29070642189108264 + 0.29071438862588345 + 0.29072235559873533 + 0.29073032280964695 + 0.29073829025863063 + 0.29074625794569497 + 0.29075422587085098 + 0.29076219403411013 + 0.29077016243548121 + 0.29077813107497497 + 0.29078609995260313 + 0.29079406906837363 + 0.29080203842229863 + 0.2908100080143885 + 0.29081797784465252 + 0.29082594791310229 + 0.2908339182197473 + 0.29084188876459838 + 0.29084985954766568 + 0.29085783056895936 + 0.2908658018284902 + 0.29087377332626924 + 0.29088174506230507 + 0.29088971703660926 + 0.29089768924919279 + 0.29090566170006421 + 0.29091363438923606 + 0.29092160731671685 + 0.29092958048251821 + 0.29093755388664971 + 0.29094552752912206 + 0.29095350140994625 + 0.2909614755291316 + 0.29096944988668916 + 0.29097742448262887 + 0.29098539931696177 + 0.29099337438969719 + 0.29100134970084685 + 0.29100932525042011 + 0.29101730103842854 + 0.29102527706488096 + 0.29103325332978885 + 0.29104122983316177 + 0.29104920657501127 + 0.29105718355534671 + 0.2910651607741791 + 0.29107313823151859 + 0.29108111592737523 + 0.29108909386176002 + 0.29109707203468382 + 0.29110505044615537 + 0.29111302909618619 + 0.29112100798478718 + 0.29112898711196722 + 0.29113696647773779 + 0.29114494608210972 + 0.2911529259250919 + 0.29116090600669581 + 0.29116888632693239 + 0.2911768668858104 + 0.29118484768334135 + 0.29119282871953556 + 0.29120080999440379 + 0.29120879150795487 + 0.29121677326020101 + 0.29122475525115177 + 0.29123273748081735 + 0.29124071994920925 + 0.29124870265633696 + 0.2912566856022108 + 0.29126466878684143 + 0.29127265221023918 + 0.29128063587241493 + 0.29128861977337811 + 0.29129660391314033 + 0.29130458829171108 + 0.29131257290910123 + 0.29132055776532173 + 0.29132854286038135 + 0.29133652819429229 + 0.29134451376706333 + 0.29135249957870618 + 0.29136048562923106 + 0.29136847191864795 + 0.29137645844696725 + 0.29138444521419971 + 0.2913924322203556 + 0.29140041946544581 + 0.29140840694947984 + 0.29141639467246916 + 0.29142438263442272 + 0.29143237083535273 + 0.29144035927526807 + 0.29144834795418023 + 0.29145633687209949 + 0.29146432602903521 + 0.29147231542499918 + 0.2914803050600015 + 0.29148829493405171 + 0.29149628504716202 + 0.29150427539934126 + 0.29151226599059965 + 0.29152025682094884 + 0.29152824789039894 + 0.29153623919896027 + 0.29154423074664293 + 0.29155222253345786 + 0.29156021455941522 + 0.29156820682452522 + 0.29157619932879891 + 0.29158419207224628 + 0.291592185054877 + 0.29160017827670326 + 0.29160817173773462 + 0.29161616543798136 + 0.29162415937745428 + 0.29163215355616284 + 0.2916401479741188 + 0.29164814263133232 + 0.29165613752781289 + 0.29166413266357205 + 0.29167212803862019 + 0.29168012365296664 + 0.29168811950662316 + 0.29169611559959913 + 0.29170411193190621 + 0.29171210850355322 + 0.29172010531455256 + 0.29172810236491292 + 0.29173609965464598 + 0.29174409718376126 + 0.29175209495226967 + 0.29176009296018207 + 0.2917680912075073 + 0.29177608969425772 + 0.29178408842044357 + 0.29179208738607432 + 0.29180008659116091 + 0.29180808603571345 + 0.2918160857197431 + 0.29182408564325985 + 0.29183208580627407 + 0.29184008620879659 + 0.29184808685083774 + 0.29185608773240762 + 0.29186408885351722 + 0.29187209021417604 + 0.2918800918143965 + 0.29188809365418661 + 0.29189609573355868 + 0.29190409805252238 + 0.29191210061108852 + 0.29192010340926661 + 0.29192810644706912 + 0.29193610972450401 + 0.29194411324158376 + 0.29195211699831775 + 0.29196012099471708 + 0.29196812523079185 + 0.29197612970655229 + 0.29198413442200943 + 0.2919921393771735 + 0.29200014457205459 + 0.29200815000666452 + 0.29201615568101125 + 0.29202416159510797 + 0.29203216774896346 + 0.29204017414258931 + 0.29204818077599437 + 0.29205618764919106 + 0.29206419476218809 + 0.29207220211499724 + 0.29208020970762866 + 0.29208821754009257 + 0.29209622561239929 + 0.29210423392455975 + 0.29211224247658413 + 0.2921202512684834 + 0.29212826030026712 + 0.29213626957194683 + 0.2921442790835323 + 0.2921522888350343 + 0.29216029882646305 + 0.2921683090578297 + 0.29217631952914358 + 0.2921843302404164 + 0.29219234119165777 + 0.29220035238287856 + 0.29220836381408904 + 0.29221637548530022 + 0.29222438739652151 + 0.29223239954776475 + 0.29224041193904005 + 0.29224842457035699 + 0.29225643744172652 + 0.29226445055316036 + 0.29227246390466727 + 0.29228047749625824 + 0.29228849132794499 + 0.29229650539973628 + 0.29230451971164301 + 0.29231253426367632 + 0.29232054905584637 + 0.2923285640881641 + 0.29233657936063906 + 0.29234459487328224 + 0.29235261062610468 + 0.29236062661911577 + 0.2923686428523265 + 0.29237665932574797 + 0.29238467603938961 + 0.29239269299326315 + 0.29240071018737812 + 0.29240872762174552 + 0.29241674529637551 + 0.29242476321127847 + 0.292432781366466 + 0.29244079976194698 + 0.29244881839773312 + 0.29245683727383459 + 0.29246485639026176 + 0.29247287574702557 + 0.29248089534413552 + 0.29248891518160336 + 0.2924969352594386 + 0.29250495557765221 + 0.29251297613625521 + 0.29252099693525718 + 0.29252901797466974 + 0.29253703925450175 + 0.29254506077476489 + 0.29255308253547024 + 0.29256110453662648 + 0.29256912677824543 + 0.29257714926033801 + 0.29258517198291312 + 0.29259319494598318 + 0.29260121814955764 + 0.29260924159364687 + 0.29261726527826187 + 0.2926252892034128 + 0.29263331336911075 + 0.29264133777536516 + 0.29264936242218798 + 0.29265738730958851 + 0.29266541243757788 + 0.29267343780616628 + 0.29268146341536472 + 0.29268948926518362 + 0.2926975153556331 + 0.29270554168672414 + 0.29271356825846706 + 0.29272159507087225 + 0.29272962212395059 + 0.2927376494177123 + 0.29274567695216852 + 0.29275370472732876 + 0.29276173274320394 + 0.29276976099980523 + 0.292777789497142 + 0.29278581823522604 + 0.29279384721406698 + 0.29280187643367583 + 0.29280990589406275 + 0.29281793559523883 + 0.29282596553721441 + 0.29283399571999957 + 0.29284202614360483 + 0.29285005680804183 + 0.29285808771332006 + 0.29286611885944991 + 0.29287415024644309 + 0.29288218187430909 + 0.29289021374305829 + 0.29289824585270241 + 0.29290627820325099 + 0.29291431079471575 + 0.29292234362710556 + 0.29293037670043143 + 0.29293841001470511 + 0.29294644356993615 + 0.29295447736613484 + 0.29296251140331292 + 0.29297054568147929 + 0.29297858020064566 + 0.29298661496082223 + 0.29299464996202018 + 0.29300268520424899 + 0.29301072068751965 + 0.29301875641184327 + 0.29302679237722934 + 0.29303482858368968 + 0.29304286503123378 + 0.2930509017198728 + 0.29305893864961619 + 0.29306697582047642 + 0.2930750132324631 + 0.29308305088558584 + 0.29309108877985707 + 0.29309912691528572 + 0.29310716529188341 + 0.29311520390965984 + 0.29312324276862595 + 0.29313128186879284 + 0.29313932121017078 + 0.29314736079276937 + 0.29315540061660028 + 0.29316344068167394 + 0.29317148098800061 + 0.29317952153559129 + 0.29318756232445636 + 0.29319560335460532 + 0.2932036446260507 + 0.29321168613880133 + 0.29321972789286899 + 0.29322776988826332 + 0.293235812124996 + 0.29324385460307667 + 0.29325189732251555 + 0.29325994028332453 + 0.29326798348551386 + 0.29327602692909316 + 0.29328407061407341 + 0.29329211454046566 + 0.2933001587082803 + 0.29330820311752759 + 0.29331624776821857 + 0.29332429266036358 + 0.293332337793973 + 0.29334038316905769 + 0.29334842878562811 + 0.2933564746436953 + 0.2933645207432688 + 0.29337256708435971 + 0.29338061366697982 + 0.29338866049113788 + 0.29339670755684505 + 0.29340475486411233 + 0.29341280241295004 + 0.29342085020336861 + 0.29342889823537899 + 0.29343694650899144 + 0.29344499502421645 + 0.29345304378106568 + 0.29346109277954807 + 0.29346914201967533 + 0.29347719150145779 + 0.29348524122490594 + 0.29349329119003065 + 0.29350134139684153 + 0.29350939184535046 + 0.29351744253556772 + 0.29352549346750367 + 0.29353354464116865 + 0.29354159605657359 + 0.29354964771372977 + 0.29355769961264583 + 0.29356575175333449 + 0.29357380413580531 + 0.2935818567600692 + 0.29358990962613596 + 0.29359796273401795 + 0.2936060160837235 + 0.29361406967526493 + 0.29362212350865208 + 0.29363017758389581 + 0.29363823190100652 + 0.29364628645999535 + 0.29365434126087253 + 0.29366239630364849 + 0.29367045158833427 + 0.2936785071149402 + 0.29368656288347661 + 0.2936946188939546 + 0.29370267514638376 + 0.29371073164077666 + 0.2937187883771421 + 0.29372684535549198 + 0.2937349025758359 + 0.2937429600381849 + 0.29375101774255002 + 0.29375907568894094 + 0.29376713387736869 + 0.29377519230784443 + 0.29378325098037772 + 0.29379130989498037 + 0.29379936905166198 + 0.29380742845043439 + 0.29381548809130653 + 0.29382354797429011 + 0.29383160809939551 + 0.2938396684666339 + 0.29384772907601481 + 0.29385578992754935 + 0.29386385102124857 + 0.2938719123571229 + 0.29387997393518267 + 0.29388803575543815 + 0.29389609781790127 + 0.29390416012258158 + 0.29391222266949024 + 0.29392028545863685 + 0.29392834849003391 + 0.29393641176369034 + 0.29394447527961726 + 0.29395253903782576 + 0.29396060303832611 + 0.2939686672811288 + 0.29397673176624489 + 0.29398479649368392 + 0.29399286146345854 + 0.29400092667557759 + 0.29400899213005227 + 0.29401705782689358 + 0.29402512376611184 + 0.29403318994771749 + 0.29404125637172168 + 0.29404932303813469 + 0.2940573899469669 + 0.2940654570982294 + 0.29407352449193258 + 0.29408159212808754 + 0.29408966000670467 + 0.29409772812779428 + 0.29410579649136748 + 0.29411386509743398 + 0.29412193394600555 + 0.2941300030370933 + 0.29413807237070616 + 0.29414614194685523 + 0.29415421176555234 + 0.29416228182680715 + 0.29417035213062998 + 0.29417842267703276 + 0.29418649346602499 + 0.29419456449761794 + 0.29420263577182187 + 0.29421070728864729 + 0.29421877904810584 + 0.29422685105020663 + 0.29423492329496209 + 0.29424299578238117 + 0.29425106851247579 + 0.29425914148525628 + 0.29426721470073308 + 0.29427528815891718 + 0.29428336185981824 + 0.29429143580344824 + 0.29429950998981674 + 0.29430758441893562 + 0.29431565909081375 + 0.2943237340054638 + 0.29433180916289531 + 0.29433988456311944 + 0.29434796020614662 + 0.29435603609198724 + 0.29436411222065162 + 0.29437218859215164 + 0.29438026520649702 + 0.29438834206369874 + 0.29439641916376807 + 0.29440449650671457 + 0.29441257409254945 + 0.29442065192128297 + 0.29442872999292646 + 0.29443680830749008 + 0.29444488686498516 + 0.29445296566542195 + 0.29446104470881013 + 0.2944691239951624 + 0.29447720352448831 + 0.29448528329679824 + 0.29449336331210341 + 0.29450144357041425 + 0.29450952407174102 + 0.29451760481609568 + 0.29452568580348781 + 0.29453376703392864 + 0.29454184850742782 + 0.29454993022399717 + 0.29455801218364713 + 0.29456609438638875 + 0.29457417683223186 + 0.29458225952118744 + 0.29459034245326599 + 0.2945984256284786 + 0.29460650904683572 + 0.2946145927083485 + 0.29462267661302721 + 0.29463076076088235 + 0.29463884515192434 + 0.29464692978616508 + 0.29465501466361416 + 0.29466309978428351 + 0.29467118514818208 + 0.29467927075532169 + 0.29468735660571277 + 0.29469544269936582 + 0.29470352903629188 + 0.29471161561650211 + 0.2947197024400055 + 0.29472778950681455 + 0.29473587681693908 + 0.29474396437039024 + 0.29475205216717831 + 0.29476014020731384 + 0.29476822849080792 + 0.29477631701767093 + 0.29478440578791404 + 0.29479249480154773 + 0.29480058405858306 + 0.29480867355902979 + 0.29481676330289908 + 0.29482485329020197 + 0.29483294352094896 + 0.29484103399515055 + 0.29484912471281705 + 0.294857215673961 + 0.29486530687859092 + 0.29487339832671838 + 0.29488149001835467 + 0.29488958195350951 + 0.29489767413219481 + 0.29490576655441941 + 0.29491385922019603 + 0.29492195212953365 + 0.29493004528244476 + 0.29493813867893853 + 0.29494623231902667 + 0.29495432620271966 + 0.29496242033002723 + 0.29497051470096131 + 0.29497860931553294 + 0.29498670417375117 + 0.29499479927562866 + 0.29500289462117435 + 0.29501099021040006 + 0.29501908604331634 + 0.29502718211993278 + 0.29503527844026212 + 0.29504337500431405 + 0.2950514718120989 + 0.29505956886362794 + 0.29506766615891156 + 0.29507576369796101 + 0.29508386148078658 + 0.29509195950739886 + 0.29510005777780968 + 0.29510815629202797 + 0.29511625505006572 + 0.29512435405193332 + 0.29513245329764126 + 0.29514055278720069 + 0.29514865252062206 + 0.29515675249791651 + 0.29516485271909448 + 0.29517295318416575 + 0.29518105389314292 + 0.2951891548460357 + 0.29519725604285457 + 0.29520535748361137 + 0.29521345916831587 + 0.2952215610969785 + 0.29522966326961048 + 0.29523776568622295 + 0.29524586834682631 + 0.29525397125143116 + 0.29526207440004854 + 0.29527017779268894 + 0.29527828142936285 + 0.29528638531008139 + 0.29529448943485515 + 0.29530259380369511 + 0.29531069841661189 + 0.29531880327361665 + 0.29532690837471898 + 0.29533501371993098 + 0.29534311930926227 + 0.29535122514272411 + 0.29535933122032759 + 0.2953674375420825 + 0.29537554410800082 + 0.29538365091809216 + 0.29539175797236777 + 0.29539986527083889 + 0.29540797281351583 + 0.29541608060040847 + 0.29542418863152942 + 0.29543229690688771 + 0.29544040542649447 + 0.29544851419036167 + 0.2954566231984983 + 0.29546473245091698 + 0.2954728419476268 + 0.29548095168863964 + 0.29548906167396521 + 0.29549717190361552 + 0.29550528237760021 + 0.29551339309593055 + 0.29552150405861771 + 0.29552961526567145 + 0.29553772671710371 + 0.2955458384129242 + 0.29555395035314408 + 0.2955620625377739 + 0.29557017496682486 + 0.29557828764030813 + 0.29558640055823343 + 0.29559451372061207 + 0.29560262712745444 + 0.29561074077877175 + 0.29561885467457527 + 0.29562696881487466 + 0.29563508319968046 + 0.29564319782900528 + 0.29565131270285816 + 0.29565942782125038 + 0.29566754318419303 + 0.29567565879169672 + 0.2956837746437726 + 0.2956918907404304 + 0.29570000708168132 + 0.29570812366753663 + 0.29571624049800682 + 0.29572435757310306 + 0.29573247489283511 + 0.29574059245721418 + 0.29574871026625149 + 0.29575682831995753 + 0.29576494661834357 + 0.29577306516141927 + 0.29578118394919672 + 0.29578930298168549 + 0.29579742225889766 + 0.29580554178084228 + 0.29581366154753191 + 0.29582178155897637 + 0.29582990181518626 + 0.29583802231617334 + 0.29584614306194751 + 0.29585426405251991 + 0.29586238528790115 + 0.29587050676810306 + 0.29587862849313473 + 0.29588675046300744 + 0.29589487267773301 + 0.29590299513732127 + 0.29591111784178276 + 0.29591924079112941 + 0.29592736398537178 + 0.29593548742451947 + 0.29594361110858391 + 0.29595173503757688 + 0.29595985921150764 + 0.2959679836303879 + 0.29597610829422832 + 0.29598423320304007 + 0.29599235835683296 + 0.29600048375561899 + 0.29600860939940782 + 0.29601673528821082 + 0.29602486142203915 + 0.29603298780090254 + 0.29604111442481301 + 0.29604924129378041 + 0.29605736840781588 + 0.29606549576693064 + 0.2960736233711353 + 0.29608175122044028 + 0.29608987931485681 + 0.29609800765439553 + 0.29610613623906679 + 0.296114265068882 + 0.29612239414385222 + 0.29613052346398733 + 0.29613865302929931 + 0.29614678283979867 + 0.29615491289549523 + 0.29616304319640085 + 0.29617117374252544 + 0.29617930453388092 + 0.296187435570477 + 0.29619556685232507 + 0.29620369837943633 + 0.29621183015182123 + 0.29621996216949043 + 0.29622809443245507 + 0.29623622694072566 + 0.29624435969431273 + 0.29625249269322762 + 0.29626062593748148 + 0.29626875942708419 + 0.29627689316204764 + 0.2962850271423817 + 0.29629316136809758 + 0.29630129583920578 + 0.2963094305557184 + 0.29631756551764438 + 0.29632570072499648 + 0.2963338361777838 + 0.29634197187601835 + 0.29635010781970983 + 0.29635824400887101 + 0.29636638044351099 + 0.29637451712364027 + 0.29638265404927155 + 0.29639079122041395 + 0.29639892863707945 + 0.29640706629927849 + 0.29641520420702183 + 0.29642334236031975 + 0.29643148075918357 + 0.29643961940362468 + 0.29644775829365355 + 0.29645589742928141 + 0.29646403681051742 + 0.29647217643737495 + 0.29648031630986238 + 0.29648845642799243 + 0.29649659679177487 + 0.29650473740122107 + 0.29651287825634082 + 0.29652101935714675 + 0.2965291607036481 + 0.29653730229585745 + 0.29654544413378392 + 0.29655358621743882 + 0.29656172854683344 + 0.2965698711219783 + 0.29657801394288463 + 0.29658615700956303 + 0.29659430032202405 + 0.29660244388027895 + 0.29661058768433823 + 0.29661873173421327 + 0.29662687602991378 + 0.29663502057145258 + 0.29664316535883872 + 0.2966513103920842 + 0.29665945567119889 + 0.29666760119619479 + 0.29667574696708165 + 0.29668389298387082 + 0.29669203924657361 + 0.29670018575520046 + 0.29670833250976131 + 0.29671647951026886 + 0.29672462675673295 + 0.29673277424916406 + 0.29674092198757362 + 0.29674906997197203 + 0.29675721820237144 + 0.29676536667878084 + 0.29677351540121305 + 0.29678166436967718 + 0.29678981358418516 + 0.29679796304474693 + 0.29680611275137442 + 0.29681426270407824 + 0.29682241290286898 + 0.29683056334775709 + 0.29683871403875473 + 0.29684686497587243 + 0.29685501615911919 + 0.29686316758850861 + 0.29687131926404975 + 0.29687947118575397 + 0.29688762335363245 + 0.29689577576769582 + 0.29690392842795466 + 0.29691208133442026 + 0.2969202344871032 + 0.29692838788601478 + 0.2969365415311655 + 0.29694469542256668 + 0.29695284956022827 + 0.29696100394416297 + 0.29696915857437911 + 0.29697731345089029 + 0.29698546857370545 + 0.29699362394283607 + 0.29700177955829266 + 0.29700993542008652 + 0.29701809152822894 + 0.29702624788273052 + 0.29703440448360191 + 0.29704256133085349 + 0.29705071842449754 + 0.29705887576454371 + 0.29706703335100337 + 0.29707519118388792 + 0.29708334926320706 + 0.29709150758897224 + 0.29709966616119543 + 0.29710782497988575 + 0.29711598404505529 + 0.29712414335671455 + 0.29713230291487353 + 0.29714046271954553 + 0.29714862277073911 + 0.29715678306846555 + 0.29716494361273688 + 0.29717310440356365 + 0.29718126544095574 + 0.29718942672492521 + 0.29719758825548198 + 0.29720575003263805 + 0.29721391205640318 + 0.2972220743267896 + 0.29723023684380701 + 0.2972383996074669 + 0.29724656261778043 + 0.29725472587475754 + 0.2972628893784095 + 0.29727105312874852 + 0.29727921712578353 + 0.2972873813695267 + 0.29729554585998857 + 0.2973037105971798 + 0.29731187558111172 + 0.29732004081179558 + 0.29732820628924134 + 0.29733637201346025 + 0.2973445379844637 + 0.29735270420226223 + 0.29736087066686645 + 0.29736903737828774 + 0.29737720433653669 + 0.29738537154162531 + 0.2973935389935628 + 0.29740170669236121 + 0.29740987463803115 + 0.29741804283058387 + 0.29742621127002938 + 0.29743437995637972 + 0.29744254888964461 + 0.29745071806983631 + 0.29745888749696464 + 0.2974670571710416 + 0.29747522709207719 + 0.29748339726008194 + 0.29749156767506862 + 0.2974997383370464 + 0.29750790924602671 + 0.29751608040202071 + 0.29752425180504 + 0.29753242345509423 + 0.29754059535219413 + 0.29754876749635173 + 0.29755693988757764 + 0.29756511252588325 + 0.29757328541127842 + 0.29758145854377449 + 0.29758963192338284 + 0.29759780555011406 + 0.29760597942397948 + 0.29761415354498899 + 0.29762232791315474 + 0.2976305025284865 + 0.29763867739099653 + 0.29764685250069522 + 0.29765502785759335 + 0.29766320346170078 + 0.297671379313031 + 0.2976795554115933 + 0.29768773175739816 + 0.29769590835045773 + 0.2977040851907819 + 0.29771226227838277 + 0.29772043961327099 + 0.2977286171954564 + 0.29773679502495104 + 0.29774497310176568 + 0.29775315142591158 + 0.29776132999739868 + 0.29776950881623832 + 0.29777768788244258 + 0.29778586719602063 + 0.29779404675698462 + 0.29780222656534505 + 0.29781040662111347 + 0.29781858692429963 + 0.29782676747491571 + 0.29783494827297152 + 0.29784312931847928 + 0.29785131061144954 + 0.29785949215189228 + 0.29786767393982022 + 0.29787585597524263 + 0.2978840382581715 + 0.29789222078861682 + 0.29790040356659075 + 0.29790858659210379 + 0.29791676986516669 + 0.29792495338579006 + 0.29793313715398601 + 0.29794132116976513 + 0.29794950543313731 + 0.29795768994411476 + 0.29796587470270736 + 0.29797405970892715 + 0.2979822449627848 + 0.29799043046429102 + 0.29799861621345719 + 0.29800680221029313 + 0.29801498845481172 + 0.29802317494702218 + 0.29803136168693661 + 0.29803954867456561 + 0.2980477359099199 + 0.29805592339301001 + 0.29806411112384895 + 0.29807229910244509 + 0.29808048732881126 + 0.29808867580295811 + 0.29809686452489559 + 0.29810505349463584 + 0.29811324271218942 + 0.29812143217756709 + 0.29812962189078024 + 0.29813781185183935 + 0.29814600206075603 + 0.29815419251754155 + 0.29816238322220512 + 0.29817057417475962 + 0.29817876537521493 + 0.29818695682358248 + 0.29819514851987367 + 0.29820334046409835 + 0.29821153265626876 + 0.29821972509639472 + 0.29822791778448848 + 0.29823611072055983 + 0.29824430390462098 + 0.29825249733668108 + 0.29826069101675307 + 0.29826888494484755 + 0.29827707912097445 + 0.29828527354514522 + 0.29829346821737124 + 0.29830166313766382 + 0.29830985830603307 + 0.29831805372249093 + 0.29832624938704749 + 0.29833444529971331 + 0.29834264146050138 + 0.29835083786942079 + 0.29835903452648371 + 0.29836723143170008 + 0.29837542858508204 + 0.29838362598664031 + 0.29839182363638472 + 0.29840002153432826 + 0.29840821968048081 + 0.29841641807485303 + 0.2984246167174564 + 0.29843281560830148 + 0.29844101474740059 + 0.2984492141347635 + 0.29845741377040086 + 0.298465613654325 + 0.29847381378654653 + 0.29848201416707609 + 0.29849021479592436 + 0.29849841567310348 + 0.2985066167986235 + 0.29851481817249564 + 0.29852301979473073 + 0.29853122166534096 + 0.29853942378433612 + 0.29854762615172703 + 0.29855582876752579 + 0.29856403163174305 + 0.29857223474438888 + 0.29858043810547602 + 0.29858864171501448 + 0.29859684557301425 + 0.2986050496794882 + 0.298613254034447 + 0.29862145863790063 + 0.2986296634898612 + 0.29863786859033947 + 0.29864607393934606 + 0.29865427953689172 + 0.29866248538298856 + 0.29867069147764658 + 0.29867889782087792 + 0.29868710441269258 + 0.29869531125310195 + 0.29870351834211745 + 0.29871172567974907 + 0.29871993326600965 + 0.29872814110090773 + 0.29873634918445624 + 0.29874455751666656 + 0.29875276609754792 + 0.29876097492711184 + 0.29876918400537111 + 0.29877739333233427 + 0.2987856029080142 + 0.29879381273242095 + 0.29880202280556584 + 0.29881023312746041 + 0.29881844369811528 + 0.2988266545175412 + 0.29883486558574962 + 0.29884307690275119 + 0.29885128846855746 + 0.29885950028317892 + 0.29886771234662651 + 0.29887592465891238 + 0.29888413722004709 + 0.29889235003004067 + 0.29890056308890539 + 0.29890877639665181 + 0.29891698995329152 + 0.29892520375883441 + 0.29893341781329269 + 0.29894163211667707 + 0.29894984666899749 + 0.29895806147026693 + 0.29896627652049534 + 0.29897449181969343 + 0.29898270736787336 + 0.29899092316504516 + 0.29899913921122095 + 0.29900735550641083 + 0.29901557205062612 + 0.29902378884387765 + 0.29903200588617673 + 0.29904022317753493 + 0.29904844071796222 + 0.29905665850747076 + 0.29906487654607133 + 0.29907309483377453 + 0.29908131337059118 + 0.2990895321565335 + 0.29909775119161142 + 0.29910597047583709 + 0.29911419000922052 + 0.29912240979177324 + 0.29913062982350669 + 0.29913885010443081 + 0.29914707063455787 + 0.29915529141389852 + 0.29916351244246353 + 0.29917173372026507 + 0.29917995524731245 + 0.29918817702361783 + 0.29919639904919265 + 0.29920462132404696 + 0.29921284384819219 + 0.29922106662163983 + 0.2992292896444006 + 0.29923751291648598 + 0.29924573643790592 + 0.29925396020867273 + 0.29926218422879775 + 0.29927040849829106 + 0.2992786330171634 + 0.29928685778542696 + 0.29929508280309242 + 0.29930330807017064 + 0.29931153358667295 + 0.29931975935261018 + 0.29932798536799382 + 0.29933621163283458 + 0.2993444381471439 + 0.29935266491093254 + 0.29936089192421134 + 0.29936911918699227 + 0.29937734669928562 + 0.2993855744611027 + 0.29939380247245506 + 0.29940203073335336 + 0.29941025924380854 + 0.29941848800383181 + 0.2994267170134341 + 0.29943494627262679 + 0.29944317578142149 + 0.29945140553982807 + 0.29945963554785882 + 0.29946786580552381 + 0.29947609631283517 + 0.29948432706980294 + 0.29949255807643865 + 0.2995007893327537 + 0.29950902083875963 + 0.29951725259446577 + 0.29952548459988498 + 0.29953371685502811 + 0.29954194935990514 + 0.29955018211452822 + 0.29955841511890746 + 0.29956664837305513 + 0.29957488187698261 + 0.29958311563069923 + 0.29959134963421719 + 0.29959958388754809 + 0.29960781839070189 + 0.29961605314369 + 0.29962428814652481 + 0.29963252339921548 + 0.29964075890177505 + 0.2996489946542128 + 0.29965723065654093 + 0.29966546690877099 + 0.29967370341091221 + 0.29968194016297767 + 0.29969017716497798 + 0.2996984144169233 + 0.29970665191882578 + 0.29971488967069626 + 0.29972312767254544 + 0.29973136592438493 + 0.2997396044262261 + 0.29974784317807984 + 0.29975608217995681 + 0.2997643214318686 + 0.29977256093382593 + 0.29978080068584034 + 0.29978904068792261 + 0.29979728094008418 + 0.29980552144233591 + 0.29981376219468925 + 0.29982200319715496 + 0.29983024444974471 + 0.29983848595246904 + 0.2998467277053396 + 0.29985496970836639 + 0.29986321196156251 + 0.29987145446493713 + 0.29987969721850249 + 0.29988794022226944 + 0.29989618347624875 + 0.29990442698045267 + 0.2999126707348912 + 0.29992091473957594 + 0.29992915899451761 + 0.29993740349972775 + 0.29994564825521786 + 0.29995389326099803 + 0.29996213851708042 + 0.29997038402347598 + 0.29997862978019535 + 0.29998687578725008 + 0.29999512204465106 + 0.30000336855240967 + 0.30001161531053677 + 0.30001986231904393 + 0.30002810957794185 + 0.30003635708724208 + 0.30004460484695544 + 0.30005285285709343 + 0.30006110111766693 + 0.30006934962868659 + 0.30007759839016396 + 0.30008584740211142 + 0.30009409666453818 + 0.30010234617745662 + 0.30011059594087741 + 0.30011884595481142 + 0.30012709621927092 + 0.3001353467342659 + 0.30014359749980796 + 0.30015184851590793 + 0.30016009978257796 + 0.30016835129982822 + 0.30017660306766952 + 0.30018485508611481 + 0.30019310735517341 + 0.30020135987485691 + 0.30020961264517754 + 0.30021786566614467 + 0.30022611893777129 + 0.30023437246006746 + 0.30024262623304476 + 0.30025088025671393 + 0.3002591345310866 + 0.30026738905617345 + 0.3002756438319869 + 0.30028389885853624 + 0.30029215413583366 + 0.3003004096638901 + 0.30030866544271706 + 0.30031692147232603 + 0.30032517775272716 + 0.30033343428393122 + 0.30034169106595127 + 0.30034994809879728 + 0.30035820538248098 + 0.30036646291701302 + 0.30037472070240506 + 0.30038297873866709 + 0.30039123702581144 + 0.30039949556384971 + 0.30040775435279188 + 0.30041601339264956 + 0.30042427268343436 + 0.30043253222515626 + 0.30044079201782836 + 0.30044905206145994 + 0.30045731235606332 + 0.30046557290164938 + 0.30047383369822889 + 0.30048209474581339 + 0.30049035604441449 + 0.30049861759404367 + 0.30050687939471038 + 0.30051514144642683 + 0.30052340374920472 + 0.30053166630305472 + 0.30053992910798843 + 0.30054819216401596 + 0.30055645547114967 + 0.3005647190294003 + 0.3005729828387787 + 0.30058124689929644 + 0.30058951121096511 + 0.30059777577379476 + 0.30060604058779772 + 0.30061430565298491 + 0.30062257096936701 + 0.30063083653695566 + 0.30063910235576236 + 0.30064736842579737 + 0.30065563474707285 + 0.30066390131959969 + 0.30067216814338876 + 0.30068043521845156 + 0.3006887025447989 + 0.30069697012244251 + 0.30070523795139309 + 0.30071350603166302 + 0.30072177436326236 + 0.30073004294620198 + 0.30073831178049421 + 0.3007465808661498 + 0.30075485020317971 + 0.30076311979159465 + 0.30077138963140787 + 0.30077965972262782 + 0.30078793006526838 + 0.30079620065933887 + 0.30080447150485168 + 0.30081274260181684 + 0.30082101395024669 + 0.30082928555015137 + 0.3008375574015425 + 0.30084582950443228 + 0.30085410185883094 + 0.30086237446475006 + 0.30087064732219965 + 0.30087892043119285 + 0.30088719379173978 + 0.30089546740385203 + 0.30090374126754038 + 0.30091201538281653 + 0.30092028974969121 + 0.30092856436817689 + 0.30093683923828285 + 0.30094511436002142 + 0.3009533897334043 + 0.30096166535844143 + 0.30096994123514531 + 0.30097821736352598 + 0.30098649374359571 + 0.30099477037536476 + 0.30100304725884541 + 0.30101132439404849 + 0.30101960178098486 + 0.30102787941966619 + 0.30103615731010325 + 0.30104443545230769 + 0.3010527138462904 + 0.30106099249206297 + 0.30106927138963691 + 0.30107755053902246 + 0.30108582994023114 + 0.30109410959327537 + 0.30110238949816526 + 0.30111066965491157 + 0.30111895006352679 + 0.3011272307240217 + 0.30113551163640795 + 0.30114379280069492 + 0.30115207421689649 + 0.30116035588502188 + 0.30116863780508363 + 0.30117691997709178 + 0.30118520240105867 + 0.30119348507699606 + 0.30120176800491311 + 0.3012100511848223 + 0.30121833461673525 + 0.30122661830066205 + 0.30123490223661509 + 0.30124318642460518 + 0.30125147086464338 + 0.30125975555674112 + 0.30126804050091005 + 0.30127632569716106 + 0.30128461114550509 + 0.30129289684595367 + 0.30130118279851775 + 0.30130946900320965 + 0.30131775546003953 + 0.30132604216901904 + 0.30133432913015973 + 0.30134261634347181 + 0.30135090380896756 + 0.30135919152665797 + 0.30136747949655462 + 0.30137576771866836 + 0.30138405619301012 + 0.30139234491959149 + 0.30140063389842414 + 0.30140892312951895 + 0.30141721261288751 + 0.30142550234854076 + 0.30143379233648954 + 0.30144208257674548 + 0.30145037306932032 + 0.30145866381422554 + 0.30146695481147068 + 0.30147524606106946 + 0.30148353756303065 + 0.3014918293173674 + 0.30150012132409043 + 0.30150841358321084 + 0.30151670609474013 + 0.30152499885868927 + 0.30153329187506911 + 0.30154158514389207 + 0.30154987866516897 + 0.30155817243891009 + 0.30156646646512841 + 0.30157476074383421 + 0.30158305527503904 + 0.30159135005875387 + 0.3015996450949911 + 0.30160794038376004 + 0.3016162359250732 + 0.30162453171894216 + 0.30163282776537703 + 0.30164112406439025 + 0.30164942061599348 + 0.3016577174201962 + 0.30166601447701069 + 0.3016743117864486 + 0.30168260934852092 + 0.30169090716323854 + 0.30169920523061378 + 0.30170750355065684 + 0.3017158021233794 + 0.30172410094879237 + 0.30173240002690815 + 0.30174069935773684 + 0.30174899894129092 + 0.30175729877757973 + 0.30176559886661725 + 0.30177389920841213 + 0.30178219980297744 + 0.3017905006503242 + 0.30179880175046325 + 0.3018071031034063 + 0.30181540470916346 + 0.30182370656774798 + 0.30183200867916987 + 0.301840311043441 + 0.30184861366057214 + 0.301856916530575 + 0.30186521965346047 + 0.30187352302924025 + 0.30188182665792523 + 0.30189013053952785 + 0.30189843467405825 + 0.3019067390615281 + 0.30191504370194838 + 0.30192334859533071 + 0.30193165374168673 + 0.3019399591410275 + 0.30194826479336373 + 0.30195657069870802 + 0.30196487685707041 + 0.30197318326846273 + 0.30198148993289653 + 0.30198979685038274 + 0.30199810402093313 + 0.30200641144455848 + 0.30201471912126987 + 0.30202302705107958 + 0.30203133523399872 + 0.30203964367003727 + 0.30204795235920856 + 0.30205626130152269 + 0.30206457049699137 + 0.30207287994562554 + 0.30208118964743685 + 0.30208949960243697 + 0.30209780981063616 + 0.30210612027204675 + 0.30211443098667984 + 0.30212274195454691 + 0.30213105317565825 + 0.30213936465002628 + 0.30214767637766199 + 0.30215598835857699 + 0.30216430059278226 + 0.3021726130802887 + 0.30218092582110878 + 0.30218923881525273 + 0.30219755206273285 + 0.30220586556356027 + 0.30221417931774508 + 0.30222249332530049 + 0.30223080758623583 + 0.30223912210056447 + 0.30224743686829653 + 0.3022557518894437 + 0.30226406716401694 + 0.30227238269202861 + 0.3022806984734891 + 0.30228901450840917 + 0.3022973307968021 + 0.30230564733867732 + 0.30231396413404726 + 0.30232228118292293 + 0.30233059848531596 + 0.3023389160412373 + 0.30234723385069878 + 0.30235555191371122 + 0.30236387023028555 + 0.30237218880043432 + 0.30238050762416846 + 0.30238882670149891 + 0.30239714603243734 + 0.30240546561699549 + 0.3024137854551836 + 0.3024221055470141 + 0.30243042589249791 + 0.30243874649164604 + 0.30244706734447013 + 0.30245538845098197 + 0.30246370981119247 + 0.30247203142511336 + 0.30248035329275563 + 0.30248867541413016 + 0.30249699778924949 + 0.3025053204181245 + 0.30251364330076624 + 0.30252196643718637 + 0.30253028982739594 + 0.30253861347140654 + 0.30254693736922922 + 0.30255526152087636 + 0.30256358592635757 + 0.30257191058568594 + 0.30258023549887175 + 0.30258856066592749 + 0.3025968860868633 + 0.30260521176169092 + 0.3026135376904221 + 0.30262186387306783 + 0.30263019030963983 + 0.30263851700014976 + 0.30264684394460789 + 0.30265517114302593 + 0.30266349859541564 + 0.30267182630178863 + 0.30268015426215533 + 0.30268848247652874 + 0.30269681094491852 + 0.30270513966733631 + 0.30271346864379456 + 0.30272179787430431 + 0.30273012735887578 + 0.30273845709752145 + 0.30274678709025299 + 0.30275511733708071 + 0.30276344783801706 + 0.30277177859307225 + 0.30278010960225876 + 0.3027884408655877 + 0.3027967723830699 + 0.30280510415471712 + 0.30281343618054113 + 0.30282176846055292 + 0.30283010099476348 + 0.30283843378318454 + 0.30284676682582778 + 0.30285510012270506 + 0.30286343367382651 + 0.30287176747920391 + 0.3028801015388497 + 0.3028884358527742 + 0.30289677042098839 + 0.30290510524350472 + 0.30291344032033418 + 0.30292177565148787 + 0.30293011123697816 + 0.30293844707681533 + 0.30294678317101109 + 0.30295511951957732 + 0.3029634561225249 + 0.30297179297986554 + 0.30298013009161107 + 0.30298846745777175 + 0.3029968050783593 + 0.30300514295338615 + 0.30301348108286263 + 0.30302181946679979 + 0.30303015810521078 + 0.30303849699810514 + 0.30304683614549532 + 0.3030551755473932 + 0.30306351520380892 + 0.30307185511475432 + 0.30308019528024105 + 0.30308853570028088 + 0.30309687637488419 + 0.30310521730406348 + 0.3031135584878295 + 0.30312189992619354 + 0.30313024161916724 + 0.30313858356676243 + 0.30314692576898999 + 0.30315526822586181 + 0.30316361093738881 + 0.30317195390358287 + 0.30318029712445405 + 0.30318864060001577 + 0.30319698433027908 + 0.30320532831525415 + 0.30321367255495346 + 0.30322201704938739 + 0.30323036179856916 + 0.30323870680250825 + 0.30324705206121721 + 0.30325539757470782 + 0.30326374334299105 + 0.30327208936607725 + 0.30328043564397883 + 0.30328878217670763 + 0.30329712896427469 + 0.30330547600669094 + 0.30331382330396905 + 0.3033221708561184 + 0.30333051866315308 + 0.30333886672508187 + 0.30334721504191803 + 0.3033555636136725 + 0.30336391244035649 + 0.30337226152198166 + 0.30338061085855977 + 0.30338896045010116 + 0.30339731029661832 + 0.30340566039812228 + 0.30341401075462482 + 0.30342236136613693 + 0.30343071223267054 + 0.30343906335423654 + 0.30344741473084597 + 0.30345576636251143 + 0.30346411824924391 + 0.30347247039105518 + 0.30348082278795552 + 0.30348917543995757 + 0.30349752834707222 + 0.30350588150931135 + 0.30351423492668594 + 0.30352258859920783 + 0.303530942526888 + 0.30353929670973906 + 0.30354765114777049 + 0.30355600584099562 + 0.30356436078942473 + 0.30357271599306962 + 0.30358107145194124 + 0.30358942716605303 + 0.30359778313541447 + 0.30360613936003655 + 0.30361449583993261 + 0.30362285257511368 + 0.30363120956559009 + 0.30363956681137444 + 0.30364792431247756 + 0.30365628206891071 + 0.30366464008068633 + 0.30367299834781486 + 0.30368135687030862 + 0.30368971564817882 + 0.30369807468143656 + 0.30370643397009273 + 0.3037147935141607 + 0.30372315331365002 + 0.30373151336857329 + 0.30373987367894151 + 0.30374823424476655 + 0.30375659506605934 + 0.30376495614283255 + 0.30377331747509567 + 0.30378167906286135 + 0.30379004090614198 + 0.30379840300494648 + 0.30380676535928897 + 0.30381512796917887 + 0.30382349083462962 + 0.30383185395565143 + 0.30384021733225536 + 0.30384858096445477 + 0.30385694485225928 + 0.30386530899568059 + 0.30387367339473126 + 0.30388203804942171 + 0.30389040295976438 + 0.30389876812576971 + 0.30390713354744947 + 0.30391549922481542 + 0.30392386515787945 + 0.30393223134665259 + 0.30394059779114585 + 0.30394896449137193 + 0.30395733144734105 + 0.30396569865906586 + 0.30397406612655659 + 0.3039824338498251 + 0.30399080182888399 + 0.30399917006374283 + 0.30400753855441565 + 0.30401590730091127 + 0.30402427630324308 + 0.30403264556142134 + 0.30404101507545866 + 0.30404938484536542 + 0.30405775487115405 + 0.30406612515283576 + 0.30407449569042155 + 0.30408286648392407 + 0.3040912375333536 + 0.30409960883872272 + 0.30410798040004172 + 0.30411635221732258 + 0.30412472429057696 + 0.30413309661981675 + 0.30414146920505308 + 0.3041498420462978 + 0.30415821514356189 + 0.30416658849685652 + 0.30417496210619427 + 0.30418333597158542 + 0.30419171009304258 + 0.30420008447057689 + 0.30420845910419936 + 0.30421683399392263 + 0.30422520913975704 + 0.30423358454171512 + 0.30424196019980732 + 0.30425033611404606 + 0.3042587122844419 + 0.30426708871100722 + 0.30427546539375405 + 0.3042838423326919 + 0.30429221952783408 + 0.30430059697919171 + 0.30430897468677587 + 0.3043173526505985 + 0.30432573087067133 + 0.30433410934700472 + 0.30434248807961206 + 0.30435086706850295 + 0.30435924631369005 + 0.30436762581518428 + 0.30437600557299843 + 0.30438438558714198 + 0.30439276585762837 + 0.30440114638446786 + 0.30440952716767311 + 0.30441790820725445 + 0.30442628950322453 + 0.30443467105559358 + 0.3044430528643744 + 0.30445143492957716 + 0.30445981725121535 + 0.30446819982929851 + 0.30447658266383926 + 0.30448496575484946 + 0.30449334910233949 + 0.30450173270632191 + 0.30451011656680788 + 0.30451850068380848 + 0.30452688505733638 + 0.30453526968740185 + 0.30454365457401678 + 0.30455203971719308 + 0.30456042511694259 + 0.30456881077327641 + 0.30457719668620564 + 0.30458558285574294 + 0.30459396928189869 + 0.30460235596468477 + 0.30461074290411289 + 0.30461913010019515 + 0.30462751755294248 + 0.30463590526236606 + 0.30464429322847858 + 0.30465268145129032 + 0.30466106993081388 + 0.3046694586670598 + 0.30467784766004052 + 0.30468623690976648 + 0.30469462641625111 + 0.30470301617950468 + 0.3047114061995384 + 0.30471979647636488 + 0.30472818700999438 + 0.30473657780043967 + 0.30474496884771191 + 0.30475336015182286 + 0.30476175171278369 + 0.30477014353060627 + 0.30477853560530177 + 0.30478692793688206 + 0.30479532052535896 + 0.30480371337074291 + 0.30481210647304652 + 0.30482049983228166 + 0.30482889344845876 + 0.30483728732159049 + 0.30484568145168789 + 0.30485407583876217 + 0.30486247048282589 + 0.30487086538388941 + 0.30487926054196479 + 0.30488765595706457 + 0.30489605162919831 + 0.30490444755837948 + 0.30491284374461852 + 0.30492124018792799 + 0.30492963688831831 + 0.30493803384580209 + 0.30494643106039054 + 0.30495482853209471 + 0.30496322626092581 + 0.30497162424689728 + 0.30498002249002015 + 0.30498842099030415 + 0.30499681974776344 + 0.3050052187624076 + 0.30501361803424926 + 0.30502201756329966 + 0.30503041734957065 + 0.30503881739307331 + 0.30504721769381898 + 0.30505561825182087 + 0.30506401906708869 + 0.30507242013963515 + 0.30508082146947207 + 0.30508922305660996 + 0.30509762490106063 + 0.30510602700283601 + 0.30511442936194871 + 0.3051228319784085 + 0.30513123485222793 + 0.30513963798341825 + 0.30514804137199125 + 0.30515644501795819 + 0.30516484892133167 + 0.30517325308212212 + 0.30518165750034221 + 0.30519006217600242 + 0.30519846710911525 + 0.30520687229969196 + 0.30521527774774371 + 0.30522368345328238 + 0.30523208941631996 + 0.30524049563686828 + 0.30524890211493777 + 0.30525730885054109 + 0.3052657158436895 + 0.30527412309439406 + 0.30528253060266747 + 0.30529093836852095 + 0.30529934639196638 + 0.30530775467301408 + 0.30531616321167615 + 0.30532457200796509 + 0.30533298106189222 + 0.30534139037346864 + 0.30534979994270628 + 0.30535820976961703 + 0.3053666198542121 + 0.30537503019650269 + 0.30538344079650143 + 0.30539185165421956 + 0.30540026276966736 + 0.30540867414285922 + 0.30541708577380461 + 0.30542549766251564 + 0.30543390980900414 + 0.30544232221328121 + 0.30545073487535968 + 0.30545914779524996 + 0.3054675609729639 + 0.30547597440851348 + 0.30548438810191064 + 0.30549280205316587 + 0.30550121626229165 + 0.30550963072930015 + 0.30551804545420169 + 0.30552646043700815 + 0.30553487567773169 + 0.30554329117638401 + 0.30555170693297634 + 0.30556012294752 + 0.30556853922002752 + 0.30557695575051019 + 0.30558537253897999 + 0.30559378958544725 + 0.30560220688992468 + 0.30561062445242343 + 0.30561904227295639 + 0.30562746035153304 + 0.30563587868816694 + 0.30564429728286852 + 0.30565271613565048 + 0.30566113524652322 + 0.30566955461549944 + 0.30567797424259036 + 0.30568639412780718 + 0.30569481427116257 + 0.3057032346726678 + 0.30571165533233402 + 0.30572007625017317 + 0.30572849742619651 + 0.30573691886041665 + 0.30574534055284486 + 0.30575376250349151 + 0.30576218471237016 + 0.305770607179492 + 0.30577902990486744 + 0.30578745288850995 + 0.30579587613042997 + 0.30580429963063949 + 0.30581272338914967 + 0.30582114740597327 + 0.30582957168112074 + 0.305837996214604 + 0.30584642100643578 + 0.30585484605662661 + 0.30586327136518832 + 0.30587169693213373 + 0.30588012275747251 + 0.3058885488412173 + 0.30589697518338099 + 0.30590540178397241 + 0.30591382864300576 + 0.30592225576049237 + 0.30593068313644184 + 0.30593911077086844 + 0.30594753866378266 + 0.30595596681519643 + 0.30596439522512098 + 0.30597282389356756 + 0.30598125282054961 + 0.30598968200607757 + 0.30599811145016265 + 0.30600654115281767 + 0.30601497111405307 + 0.30602340133388223 + 0.30603183181231502 + 0.30604026254936401 + 0.30604869354504133 + 0.30605712479935732 + 0.30606555631232474 + 0.30607398808395564 + 0.30608242011426046 + 0.30609085240325112 + 0.30609928495094041 + 0.30610771775733803 + 0.30611615082245824 + 0.30612458414631077 + 0.30613301772890755 + 0.30614145157026063 + 0.30614988567038276 + 0.3061583200292835 + 0.30616675464697579 + 0.30617518952347078 + 0.30618362465878118 + 0.30619206005291749 + 0.30620049570589181 + 0.30620893161771667 + 0.30621736778840192 + 0.30622580421796108 + 0.30623424090640539 + 0.3062426778537452 + 0.30625111505999414 + 0.30625955252516274 + 0.30626799024926277 + 0.3062764282323065 + 0.30628486647430492 + 0.30629330497527019 + 0.30630174373521429 + 0.30631018275414762 + 0.30631862203208382 + 0.30632706156903322 + 0.3063355013650072 + 0.30634394142001914 + 0.30635238173407964 + 0.30636082230719991 + 0.30636926313939195 + 0.30637770423066851 + 0.3063861455810401 + 0.30639458719051943 + 0.30640302905911704 + 0.3064114711868457 + 0.30641991357371656 + 0.30642835621974102 + 0.30643679912493177 + 0.30644524228930003 + 0.30645368571285703 + 0.30646212939561496 + 0.30647057333758559 + 0.30647901753878104 + 0.3064874619992119 + 0.30649590671888993 + 0.30650435169782897 + 0.30651279693603772 + 0.30652124243352991 + 0.30652968819031667 + 0.30653813420641013 + 0.30654658048182143 + 0.3065550270165619 + 0.30656347381064503 + 0.30657192086408064 + 0.30658036817688139 + 0.30658881574905861 + 0.30659726358062434 + 0.30660571167159056 + 0.30661416002196851 + 0.30662260863176954 + 0.30663105750100633 + 0.30663950662969025 + 0.30664795601783251 + 0.30665640566544583 + 0.30666485557254153 + 0.30667330573913015 + 0.30668175616522519 + 0.30669020685083792 + 0.30669865779597971 + 0.30670710900066162 + 0.30671556046489734 + 0.30672401218869666 + 0.30673246417207228 + 0.3067409164150362 + 0.30674936891759907 + 0.30675782167977356 + 0.30676627470157175 + 0.30677472798300415 + 0.30678318152408279 + 0.30679163532482046 + 0.30680008938522846 + 0.30680854370531724 + 0.30681699828510045 + 0.30682545312458853 + 0.30683390822379353 + 0.30684236358272754 + 0.30685081920140261 + 0.30685927507982913 + 0.30686773121802002 + 0.30687618761598723 + 0.3068846442737414 + 0.30689310119129448 + 0.30690155836865929 + 0.30691001580584715 + 0.30691847350286933 + 0.30692693145973782 + 0.30693538967646405 + 0.30694384815306058 + 0.30695230688953895 + 0.30696076588591031 + 0.30696922514218672 + 0.30697768465838021 + 0.30698614443450217 + 0.30699460447056454 + 0.30700306476657946 + 0.30701152532255738 + 0.30701998613851195 + 0.3070284472144536 + 0.30703690855039517 + 0.30704537014634653 + 0.30705383200232117 + 0.30706229411833119 + 0.30707075649438631 + 0.30707921913050013 + 0.30708768202668396 + 0.30709614518294909 + 0.30710460859930755 + 0.30711307227577145 + 0.30712153621235205 + 0.30713000040906147 + 0.30713846486591173 + 0.30714692958291329 + 0.30715539456007984 + 0.30716385979742195 + 0.30717232529495159 + 0.30718079105268081 + 0.307189257070621 + 0.30719772334878342 + 0.30720618988718168 + 0.30721465668582632 + 0.30722312374472854 + 0.30723159106390135 + 0.30724005864335596 + 0.30724852648310441 + 0.30725699458315736 + 0.30726546294352908 + 0.30727393156422855 + 0.3072824004452695 + 0.30729086958666307 + 0.30729933898841993 + 0.30730780865055374 + 0.30731627857307564 + 0.3073247487559978 + 0.30733321919933076 + 0.30734168990308736 + 0.30735016086727895 + 0.30735863209191677 + 0.30736710357701447 + 0.30737557532258186 + 0.30738404732863173 + 0.30739251959517616 + 0.30740099212222655 + 0.30740946490979415 + 0.3074179379578918 + 0.30742641126653009 + 0.3074348848357219 + 0.30744335866547845 + 0.30745183275581189 + 0.30746030710673433 + 0.30746878171825631 + 0.30747725659039138 + 0.30748573172314936 + 0.30749420711654396 + 0.3075026827705849 + 0.30751115868528661 + 0.30751963486065881 + 0.30752811129671442 + 0.30753658799346473 + 0.3075450649509211 + 0.30755354216909636 + 0.30756201964800184 + 0.30757049738764969 + 0.30757897538805112 + 0.30758745364921836 + 0.30759593217116277 + 0.30760441095389701 + 0.3076128899974318 + 0.30762136930177997 + 0.30762984886695283 + 0.30763832869296254 + 0.30764680877982037 + 0.3076552891275392 + 0.30766376973612891 + 0.30767225060560383 + 0.30768073173597371 + 0.30768921312725078 + 0.30769769477944786 + 0.30770617669257627 + 0.30771465886664734 + 0.30772314130167322 + 0.30773162399766674 + 0.30774010695463777 + 0.30774859017259915 + 0.30775707365156368 + 0.30776555739154138 + 0.30777404139254483 + 0.30778252565458636 + 0.30779101017767729 + 0.30779949496182968 + 0.30780798000705489 + 0.30781646531336582 + 0.30782495088077305 + 0.30783343670928942 + 0.3078419227989263 + 0.30785040914969508 + 0.30785889576160858 + 0.30786738263467817 + 0.30787586976891529 + 0.30788435716433271 + 0.30789284482094176 + 0.30790133273875397 + 0.30790982091778124 + 0.30791830935803588 + 0.30792679805952994 + 0.30793528702227402 + 0.30794377624628172 + 0.30795226573156281 + 0.30796075547813112 + 0.30796924548599797 + 0.30797773575517462 + 0.30798622628567257 + 0.30799471707750531 + 0.30800320813068283 + 0.30801169944521867 + 0.30802019102112349 + 0.3080286828584094 + 0.30803717495708854 + 0.30804566731717231 + 0.30805415993867347 + 0.30806265282160283 + 0.30807114596597313 + 0.30807963937179578 + 0.30808813303908217 + 0.30809662696784518 + 0.30810512115809613 + 0.30811361560984651 + 0.30812211032310916 + 0.30813060529789466 + 0.30813910053421595 + 0.30814759603208436 + 0.30815609179151282 + 0.30816458781251121 + 0.30817308409509314 + 0.30818158063927004 + 0.30819007744505328 + 0.30819857451245497 + 0.30820707184148721 + 0.3082155694321615 + 0.30822406728448992 + 0.30823256539848459 + 0.30824106377415689 + 0.30824956241151896 + 0.30825806131058386 + 0.3082665604713612 + 0.30827505989386406 + 0.30828355957810377 + 0.30829205952409328 + 0.30830055973184395 + 0.30830906020136717 + 0.30831756093267504 + 0.30832606192578055 + 0.30833456318069352 + 0.30834306469742767 + 0.30835156647599432 + 0.30836006851640491 + 0.30836857081867158 + 0.30837707338280579 + 0.30838557620882112 + 0.30839407929672746 + 0.30840258264653775 + 0.30841108625826336 + 0.3084195901319165 + 0.30842809426750928 + 0.30843659866505313 + 0.30844510332456021 + 0.30845360824604262 + 0.3084621134295118 + 0.30847061887497923 + 0.30847912458245846 + 0.30848763055195944 + 0.3084961367834958 + 0.30850464327707827 + 0.30851315003271895 + 0.30852165705042928 + 0.3085301643302229 + 0.30853867187210976 + 0.30854717967610273 + 0.30855568774221404 + 0.30856419607045504 + 0.30857270466083786 + 0.30858121351337403 + 0.30858972262807566 + 0.30859823200495412 + 0.30860674164402313 + 0.30861525154529262 + 0.30862376170877548 + 0.30863227213448313 + 0.30864078282242774 + 0.30864929377262151 + 0.30865780498507583 + 0.30866631645980291 + 0.30867482819681491 + 0.30868334019612315 + 0.30869185245773995 + 0.30870036498167674 + 0.30870887776794631 + 0.30871739081656019 + 0.30872590412752976 + 0.30873441770086796 + 0.30874293153658555 + 0.30875144563469531 + 0.3087599599952095 + 0.30876847461813806 + 0.30877698950349541 + 0.30878550465129218 + 0.30879402006154072 + 0.3088025357342522 + 0.30881105166943895 + 0.30881956786711323 + 0.30882808432728709 + 0.30883660104997207 + 0.3088451180351795 + 0.30885363528292309 + 0.30886215279321289 + 0.30887067056606171 + 0.30887918860148184 + 0.30888770689948386 + 0.3088962254600815 + 0.30890474428328474 + 0.30891326336910724 + 0.30892178271756043 + 0.30893030232865576 + 0.3089388222024062 + 0.30894734233882243 + 0.30895586273791664 + 0.30896438339970178 + 0.30897290432418856 + 0.30898142551138985 + 0.30898994696131721 + 0.30899846867398273 + 0.30900699064939718 + 0.30901551288757428 + 0.30902403538852535 + 0.30903255815226277 + 0.30904108117879708 + 0.30904960446814139 + 0.30905812802030774 + 0.3090666518353069 + 0.30907517591315187 + 0.30908370025385479 + 0.3090922248574271 + 0.30910074972388035 + 0.30910927485322748 + 0.3091178002454798 + 0.30912632590064898 + 0.30913485181874778 + 0.30914337799978858 + 0.30915190444378193 + 0.30916043115074016 + 0.30916895812067541 + 0.30917748535360001 + 0.30918601284952602 + 0.30919454060846502 + 0.30920306863042835 + 0.30921159691542827 + 0.3092201254634786 + 0.3092286542745884 + 0.30923718334877154 + 0.30924571268603934 + 0.30925424228640414 + 0.3092627721498773 + 0.30927130227647182 + 0.30927983266619852 + 0.30928836331907028 + 0.30929689423509771 + 0.30930542541429473 + 0.30931395685667201 + 0.3093224885622417 + 0.30933102053101608 + 0.30933955276300656 + 0.30934808525822627 + 0.30935661801668579 + 0.30936515103839807 + 0.3093736843233747 + 0.3093822178716279 + 0.30939075168316904 + 0.30939928575801118 + 0.3094078200961658 + 0.30941635469764361 + 0.30942488956245834 + 0.30943342469062146 + 0.3094419600821452 + 0.30945049573704031 + 0.30945903165532057 + 0.30946756783699658 + 0.30947610428208144 + 0.30948464099058587 + 0.30949317796252362 + 0.30950171519790459 + 0.30951025269674182 + 0.30951879045904757 + 0.30952732848483333 + 0.30953586677411127 + 0.30954440532689365 + 0.30955294414319201 + 0.30956148322301863 + 0.30957002256638561 + 0.30957856217330448 + 0.30958710204378759 + 0.30959564217784707 + 0.30960418257549449 + 0.30961272323674283 + 0.30962126416160196 + 0.30962980535008661 + 0.30963834680220736 + 0.30964688851797567 + 0.30965543049740474 + 0.30966397274050583 + 0.30967251524729134 + 0.30968105801777274 + 0.30968960105196225 + 0.30969814434987292 + 0.30970668791151551 + 0.30971523173690213 + 0.30972377582604521 + 0.30973232017895613 + 0.309740864795648 + 0.30974940967613224 + 0.3097579548204204 + 0.30976650022852548 + 0.30977504590045823 + 0.30978359183623166 + 0.30979213803585803 + 0.30980068449934806 + 0.30980923122671561 + 0.30981777821797057 + 0.30982632547312677 + 0.3098348729921957 + 0.30984342077518817 + 0.3098519688221178 + 0.30986051713299628 + 0.30986906570783584 + 0.30987761454664714 + 0.30988616364944327 + 0.3098947130162365 + 0.30990326264703832 + 0.30991181254186101 + 0.30992036270071688 + 0.30992891312361659 + 0.30993746381057402 + 0.30994601476159989 + 0.30995456597670723 + 0.30996311745590754 + 0.30997166919921237 + 0.30998022120663477 + 0.30998877347818615 + 0.30999732601387814 + 0.31000587881372449 + 0.31001443187773531 + 0.31002298520592264 + 0.31003153879830048 + 0.31004009265487953 + 0.31004864677567129 + 0.31005720116068886 + 0.31006575580994367 + 0.31007431072344882 + 0.31008286590121431 + 0.31009142134325396 + 0.31009997704958003 + 0.31010853302020336 + 0.31011708925513609 + 0.31012564575439061 + 0.31013420251797919 + 0.31014275954591336 + 0.31015131683820618 + 0.31015987439486836 + 0.31016843221591306 + 0.31017699030135165 + 0.31018554865119657 + 0.31019410726546004 + 0.31020266614415365 + 0.31021122528728878 + 0.31021978469487943 + 0.31022834436693636 + 0.31023690430347095 + 0.31024546450449719 + 0.31025402497002491 + 0.31026258570006898 + 0.31027114669463829 + 0.31027970795374693 + 0.31028826947740717 + 0.31029683126562957 + 0.31030539331842827 + 0.31031395563581232 + 0.31032251821779711 + 0.31033108106439189 + 0.31033964417561127 + 0.31034820755146458 + 0.31035677119196625 + 0.31036533509712794 + 0.31037389926696035 + 0.31038246370147671 + 0.31039102840068911 + 0.31039959336460926 + 0.31040815859324866 + 0.31041672408662113 + 0.31042528984473738 + 0.31043385586760913 + 0.31044242215524936 + 0.31045098870767035 + 0.31045955552488369 + 0.31046812260690099 + 0.31047668995373517 + 0.31048525756539797 + 0.31049382544190157 + 0.31050239358325832 + 0.31051096198947903 + 0.31051953066057753 + 0.31052809959656469 + 0.31053666879745262 + 0.3105452382632547 + 0.31055380799398147 + 0.31056237798964609 + 0.31057094825026021 + 0.31057951877583606 + 0.31058808956638517 + 0.31059666062192076 + 0.31060523194245354 + 0.31061380352799656 + 0.31062237537856219 + 0.31063094749416126 + 0.31063951987480681 + 0.31064809252051123 + 0.31065666543128601 + 0.31066523860714279 + 0.31067381204809458 + 0.31068238575415302 + 0.3106909597253304 + 0.31069953396163907 + 0.3107081084630906 + 0.31071668322969731 + 0.31072525826147152 + 0.3107338335584256 + 0.31074240912057038 + 0.31075098494791886 + 0.31075956104048347 + 0.3107681373982758 + 0.31077671402130808 + 0.31078529090959273 + 0.31079386806314058 + 0.31080244548196539 + 0.31081102316607884 + 0.31081960111549251 + 0.31082817933021939 + 0.31083675781027043 + 0.31084533655565871 + 0.31085391556639569 + 0.3108624948424939 + 0.3108710743839655 + 0.3108796541908222 + 0.31088823426307632 + 0.31089681460074098 + 0.31090539520382621 + 0.31091397607234589 + 0.31092255720631079 + 0.3109311386057349 + 0.31093972027062894 + 0.31094830220100461 + 0.31095688439687569 + 0.31096546685825299 + 0.31097404958514896 + 0.31098263257757586 + 0.3109912158355454 + 0.31099979935907057 + 0.31100838314816298 + 0.31101696720283434 + 0.31102555152309763 + 0.31103413610896447 + 0.31104272096044733 + 0.31105130607755849 + 0.31105989146030871 + 0.31106847710871205 + 0.3110770630227791 + 0.31108564920252324 + 0.31109423564795513 + 0.31110282235908876 + 0.31111140933593495 + 0.31111999657850598 + 0.31112858408681437 + 0.31113717186087225 + 0.31114575990069149 + 0.31115434820628429 + 0.3111629367776631 + 0.31117152561484018 + 0.31118011471782725 + 0.31118870408663585 + 0.31119729372127913 + 0.31120588362176876 + 0.31121447378811773 + 0.31122306422033708 + 0.31123165491843974 + 0.31124024588243743 + 0.31124883711234175 + 0.31125742860816669 + 0.31126602036992285 + 0.31127461239762211 + 0.31128320469127824 + 0.31129179725090139 + 0.31130039007650612 + 0.31130898316810268 + 0.31131757652570324 + 0.31132617014932112 + 0.31133476403896787 + 0.31134335819465592 + 0.31135195261639681 + 0.31136054730420298 + 0.31136914225808754 + 0.31137773747806063 + 0.31138633296413687 + 0.31139492871632563 + 0.31140352473464233 + 0.31141212101909632 + 0.31142071756970152 + 0.3114293143864687 + 0.31143791146941119 + 0.31144650881854119 + 0.3114551064338697 + 0.31146370431540987 + 0.31147230246317475 + 0.3114809008771745 + 0.31148949955742233 + 0.31149809850392973 + 0.31150669771671002 + 0.3115152971957747 + 0.31152389694113702 + 0.31153249695280705 + 0.31154109723079876 + 0.31154969777512287 + 0.31155829858579348 + 0.31156689966282058 + 0.31157550100621823 + 0.31158410261599789 + 0.3115927044921713 + 0.31160130663475166 + 0.31160990904375052 + 0.31161851171917954 + 0.31162711466105197 + 0.31163571786937933 + 0.31164432134417408 + 0.3116529250854479 + 0.31166152909321471 + 0.31167013336748456 + 0.31167873790826989 + 0.31168734271558468 + 0.31169594778943893 + 0.31170455312984602 + 0.31171315873681887 + 0.31172176461036782 + 0.31173037075050669 + 0.31173897715724713 + 0.31174758383060086 + 0.3117561907705802 + 0.31176479797719842 + 0.31177340545046628 + 0.31178201319039639 + 0.31179062119700174 + 0.31179922947029409 + 0.31180783801028583 + 0.31181644681698778 + 0.31182505589041482 + 0.31183366523057615 + 0.31184227483748655 + 0.31185088471115696 + 0.31185949485159886 + 0.31186810525882641 + 0.31187671593284966 + 0.31188532687368253 + 0.31189393808133675 + 0.31190254955582464 + 0.31191116129715796 + 0.31191977330534904 + 0.31192838558041042 + 0.3119369981223537 + 0.31194561093119205 + 0.31195422400693718 + 0.31196283734960151 + 0.31197145095919593 + 0.31198006483573515 + 0.31198867897922933 + 0.31199729338969168 + 0.31200590806713385 + 0.31201452301156823 + 0.31202313822300815 + 0.31203175370146363 + 0.31204036944694941 + 0.31204898545947563 + 0.31205760173905561 + 0.31206621828570086 + 0.31207483509942463 + 0.31208345218023792 + 0.3120920695281546 + 0.31210068714318484 + 0.31210930502534262 + 0.3121179231746396 + 0.31212654159108827 + 0.31213516027469951 + 0.31214377922548725 + 0.31215239844346326 + 0.31216101792863987 + 0.31216963768102818 + 0.31217825770064195 + 0.31218687798749217 + 0.31219549854159218 + 0.3122041193629535 + 0.3122127404515887 + 0.31222136180751009 + 0.31222998343073022 + 0.31223860532126002 + 0.31224722747911265 + 0.31225584990430061 + 0.31226447259683632 + 0.31227309555673072 + 0.31228171878399702 + 0.31229034227864771 + 0.31229896604069513 + 0.31230759007015035 + 0.31231621436702656 + 0.31232483893133622 + 0.3123334637630909 + 0.31234208886230325 + 0.3123507142289848 + 0.31235933986314884 + 0.31236796576480785 + 0.31237659193397277 + 0.31238521837065675 + 0.31239384507487239 + 0.31240247204663046 + 0.31241109928594507 + 0.31241972679282715 + 0.31242835456728985 + 0.31243698260934494 + 0.31244561091900408 + 0.31245423949628137 + 0.31246286834118758 + 0.31247149745373448 + 0.31248012683393622 + 0.31248875648180352 + 0.31249738639734898 + 0.31250601658058497 + 0.31251464703152487 + 0.31252327775017874 + 0.31253190873656139 + 0.31254053999068299 + 0.31254917151255684 + 0.31255780330219457 + 0.31256643535960943 + 0.31257506768481236 + 0.31258370027781746 + 0.31259233313863483 + 0.31260096626727929 + 0.31260959966376095 + 0.31261823332809235 + 0.31262686726028749 + 0.31263550146035651 + 0.31264413592831275 + 0.31265277066416869 + 0.31266140566793671 + 0.3126700409396278 + 0.31267867647925601 + 0.31268731228683233 + 0.31269594836236919 + 0.31270458470587981 + 0.312713221317376 + 0.31272185819686937 + 0.3127304953443733 + 0.31273913275989867 + 0.31274777044345958 + 0.31275640839506685 + 0.31276504661473387 + 0.31277368510247228 + 0.31278232385829469 + 0.3127909628822127 + 0.31279960217423958 + 0.31280824173438637 + 0.31281688156266702 + 0.31282552165909261 + 0.31283416202367631 + 0.31284280265642905 + 0.31285144355736488 + 0.3128600847264949 + 0.31286872616383227 + 0.31287736786938791 + 0.31288600984317594 + 0.31289465208520728 + 0.31290329459549454 + 0.31291193737405082 + 0.31292058042088799 + 0.31292922373601773 + 0.3129378673194525 + 0.31294651117120487 + 0.31295515529128737 + 0.3129637996797125 + 0.31297244433649268 + 0.31298108926163898 + 0.31298973445516542 + 0.31299837991708218 + 0.31300702564740407 + 0.31301567164614141 + 0.31302431791330732 + 0.31303296444891443 + 0.31304161125297436 + 0.31305025832549982 + 0.31305890566650396 + 0.31306755327599772 + 0.31307620115399365 + 0.3130848493005044 + 0.31309349771554307 + 0.31310214639912076 + 0.31311079535124997 + 0.31311944457194313 + 0.31312809406121367 + 0.31313674381907247 + 0.31314539384553286 + 0.31315404414060583 + 0.31316269470430547 + 0.31317134553664266 + 0.3131799966376308 + 0.31318864800728163 + 0.31319729964560761 + 0.31320595155262138 + 0.3132146037283346 + 0.31322325617275981 + 0.31323190888591035 + 0.3132405618677972 + 0.31324921511843362 + 0.31325786863783134 + 0.31326652242600306 + 0.31327517648296038 + 0.31328383080871669 + 0.31329248540328447 + 0.31330114026667555 + 0.31330979539890164 + 0.313318450799976 + 0.31332710646991052 + 0.31333576240871835 + 0.31334441861641071 + 0.3133530750930007 + 0.31336173183850097 + 0.31337038885292245 + 0.31337904613627848 + 0.31338770368858165 + 0.31339636150984446 + 0.31340501960007788 + 0.31341367795929603 + 0.31342233658751001 + 0.31343099548473297 + 0.31343965465097673 + 0.3134483140862539 + 0.31345697379057613 + 0.31346563376395686 + 0.31347429400640869 + 0.31348295451794245 + 0.31349161529857156 + 0.31350027634830857 + 0.31350893766716603 + 0.31351759925515493 + 0.3135262611122886 + 0.31353492323857957 + 0.31354358563403972 + 0.3135522482986815 + 0.31356091123251745 + 0.31356957443556027 + 0.31357823790782235 + 0.3135869016493148 + 0.3135955656600517 + 0.313604229940044 + 0.31361289448930518 + 0.31362155930784691 + 0.31363022439568178 + 0.31363888975282234 + 0.31364755537928041 + 0.31365622127506926 + 0.31366488744019999 + 0.31367355387468671 + 0.31368222057854112 + 0.31369088755177432 + 0.31369955479440043 + 0.31370822230643114 + 0.31371689008787917 + 0.31372555813875624 + 0.31373422645907484 + 0.31374289504884845 + 0.313751563908088 + 0.31376023303680689 + 0.31376890243501687 + 0.31377757210273055 + 0.31378624203996053 + 0.31379491224671929 + 0.31380358272301795 + 0.31381225346887137 + 0.31382092448428978 + 0.31382959576928654 + 0.31383826732387349 + 0.31384693914806316 + 0.313855611241869 + 0.31386428360530272 + 0.31387295623837608 + 0.31388162914110179 + 0.31389030231349313 + 0.31389897575556119 + 0.31390764946731919 + 0.3139163234487799 + 0.31392499769995424 + 0.31393367222085633 + 0.31394234701149731 + 0.31395102207189041 + 0.31395969740204754 + 0.31396837300198205 + 0.31397704887170497 + 0.31398572501122962 + 0.31399440142056789 + 0.31400307809973227 + 0.31401175504873541 + 0.31402043226759002 + 0.31402910975630843 + 0.31403778751490269 + 0.31404646554338445 + 0.31405514384176803 + 0.31406382241006436 + 0.31407250124828684 + 0.31408118035644722 + 0.31408985973455816 + 0.3140985393826316 + 0.3141072193006807 + 0.31411589948871743 + 0.31412457994675508 + 0.31413326067480468 + 0.31414194167287901 + 0.31415062294099128 + 0.31415930447915336 + 0.31416798628737785 + 0.31417666836567737 + 0.3141853507140645 + 0.3141940333325503 + 0.31420271622114898 + 0.31421139937987153 + 0.31422008280873137 + 0.31422876650774112 + 0.31423745047691176 + 0.31424613471625751 + 0.31425481922578941 + 0.31426350400552089 + 0.31427218905546372 + 0.31428087437563057 + 0.31428955996603408 + 0.31429824582668675 + 0.31430693195760045 + 0.31431561835878791 + 0.3143243050302616 + 0.31433299197203418 + 0.3143416791841176 + 0.31435036666652588 + 0.31435905441926865 + 0.31436774244236071 + 0.31437643073581406 + 0.31438511929964047 + 0.31439380813385254 + 0.31440249723846297 + 0.31441118661348427 + 0.3144198762589292 + 0.31442856617480947 + 0.31443725636113784 + 0.31444594681792604 + 0.31445463754518832 + 0.31446332854293568 + 0.31447201981118161 + 0.31448071134993799 + 0.31448940315921659 + 0.31449809523903155 + 0.31450678758939327 + 0.31451548021031589 + 0.31452417310181124 + 0.31453286626389204 + 0.31454155969657005 + 0.31455025339985876 + 0.31455894737376999 + 0.3145676416183163 + 0.31457633613350972 + 0.31458503091936352 + 0.31459372597589036 + 0.31460242130310134 + 0.31461111690101073 + 0.31461981276962947 + 0.31462850890897032 + 0.31463720531904665 + 0.3146459019998703 + 0.31465459895145315 + 0.31466329617380939 + 0.3146719936669502 + 0.31468069143088734 + 0.31468938946563502 + 0.31469808777120517 + 0.31470678634761029 + 0.3147154851948617 + 0.31472418431297339 + 0.31473288370195734 + 0.31474158336182539 + 0.31475028329259103 + 0.3147589834942669 + 0.31476768396686394 + 0.31477638471039648 + 0.31478508572487568 + 0.31479378701031485 + 0.31480248856672588 + 0.31481119039412153 + 0.31481989249251435 + 0.31482859486191622 + 0.31483729750234141 + 0.31484600041380023 + 0.31485470359630613 + 0.31486340704987165 + 0.31487211077450955 + 0.31488081477023178 + 0.31488951903705159 + 0.31489822357498032 + 0.314906928384032 + 0.3149156334642178 + 0.31492433881555038 + 0.31493304443804315 + 0.31494175033170729 + 0.31495045649655695 + 0.31495916293260329 + 0.31496786963985896 + 0.31497657661833739 + 0.31498528386804975 + 0.31499399138901013 + 0.31500269918122981 + 0.31501140724472138 + 0.31502011557949827 + 0.3150288241855716 + 0.3150375330629549 + 0.31504624221166072 + 0.31505495163170177 + 0.31506366132308927 + 0.31507237128583654 + 0.31508108151995634 + 0.31508979202546133 + 0.31509850280236334 + 0.31510721385067514 + 0.31511592517041015 + 0.31512463676157948 + 0.31513334862419584 + 0.31514206075827261 + 0.31515077316382178 + 0.31515948584085601 + 0.31516819878938795 + 0.31517691200943043 + 0.3151856255009951 + 0.31519433926409485 + 0.31520305329874143 + 0.31521176760494923 + 0.31522048218273013 + 0.31522919703209595 + 0.31523791215305946 + 0.31524662754563249 + 0.31525534320982934 + 0.31526405914566125 + 0.31527277535314147 + 0.31528149183228205 + 0.31529020858309564 + 0.31529892560559497 + 0.31530764289979196 + 0.31531636046570005 + 0.31532507830333112 + 0.31533379641269788 + 0.31534251479381309 + 0.31535123344668947 + 0.31535995237133879 + 0.31536867156777393 + 0.31537739103600815 + 0.31538611077605277 + 0.31539483078792124 + 0.31540355107162549 + 0.31541227162717889 + 0.31542099245459343 + 0.31542971355388189 + 0.31543843492505608 + 0.31544715656812961 + 0.31545587848311424 + 0.31546460067002352 + 0.31547332312886872 + 0.31548204585966316 + 0.31549076886241967 + 0.31549949213715006 + 0.31550821568386717 + 0.31551693950258436 + 0.31552566359331286 + 0.31553438795606537 + 0.31554311259085538 + 0.31555183749769561 + 0.31556056267659716 + 0.31556928812757362 + 0.31557801385063761 + 0.31558673984580199 + 0.31559546611307771 + 0.31560419265247919 + 0.31561291946401832 + 0.31562164654770702 + 0.31563037390355886 + 0.31563910153158575 + 0.31564782943180109 + 0.31565655760421618 + 0.31566528604884453 + 0.31567401476569873 + 0.31568274375479077 + 0.31569147301613348 + 0.31570020254974024 + 0.31570893235562225 + 0.31571766243379301 + 0.31572639278426529 + 0.31573512340705023 + 0.31574385430216212 + 0.31575258546961288 + 0.31576131690941528 + 0.31577004862158048 + 0.31577878060612352 + 0.31578751286305479 + 0.31579624539238871 + 0.31580497819413622 + 0.31581371126831104 + 0.31582244461492587 + 0.31583117823399176 + 0.31583991212552309 + 0.31584864628953191 + 0.31585738072603076 + 0.31586611543503096 + 0.3158748504165475 + 0.31588358567059088 + 0.31589232119717459 + 0.31590105699631205 + 0.31590979306801453 + 0.31591852941229481 + 0.31592726602916632 + 0.31593600291864027 + 0.31594474008073103 + 0.31595347751544967 + 0.31596221522280982 + 0.31597095320282337 + 0.31597969145550386 + 0.31598842998086257 + 0.31599716877891293 + 0.31600590784966776 + 0.31601464719313888 + 0.31602338680933995 + 0.31603212669828218 + 0.31604086685997979 + 0.31604960729444398 + 0.31605834800168836 + 0.3160670889817257 + 0.31607583023456709 + 0.31608457176022686 + 0.31609331355871628 + 0.31610205563004884 + 0.3161107979742373 + 0.31611954059129282 + 0.31612828348122979 + 0.31613702664406085 + 0.31614577007979661 + 0.316154513788452 + 0.31616325777003834 + 0.3161720020245683 + 0.31618074655205469 + 0.31618949135251023 + 0.3161982364259478 + 0.31620698177237999 + 0.31621572739181814 + 0.31622447328427727 + 0.3162332194497679 + 0.3162419658883035 + 0.3162507125998969 + 0.31625945958455998 + 0.31626820684230639 + 0.31627695437314729 + 0.31628570217709706 + 0.31629445025416764 + 0.31630319860437106 + 0.31631194722772088 + 0.31632069612422903 + 0.31632944529390838 + 0.31633819473677161 + 0.31634694445283229 + 0.31635569444210088 + 0.3163644447045918 + 0.31637319524031771 + 0.31638194604928982 + 0.31639069713152251 + 0.316399448487027 + 0.31640820011581688 + 0.31641695201790415 + 0.31642570419330235 + 0.31643445664202263 + 0.31644320936407944 + 0.31645196235948475 + 0.31646071562825057 + 0.31646946917038965 + 0.3164782229859156 + 0.31648697707483958 + 0.31649573143717608 + 0.31650448607293691 + 0.31651324098213424 + 0.31652199616478077 + 0.31653075162089006 + 0.31653950735047426 + 0.31654826335354519 + 0.31655701963011734 + 0.31656577618020193 + 0.31657453300381161 + 0.31658329010096015 + 0.31659204747165948 + 0.31660080511592159 + 0.31660956303376092 + 0.31661832122518857 + 0.31662707969021747 + 0.31663583842886112 + 0.31664459744113155 + 0.31665335672704154 + 0.31666211628660323 + 0.3166708761198308 + 0.3166796362267349 + 0.31668839660732973 + 0.31669715726162745 + 0.31670591818964072 + 0.31671467939138248 + 0.31672344086686471 + 0.31673220261610091 + 0.31674096463910323 + 0.31674972693588516 + 0.31675848950645724 + 0.31676725235083536 + 0.31677601546903 + 0.31678477886105399 + 0.3167935425269201 + 0.31680230646664204 + 0.31681107068023162 + 0.31681983516770107 + 0.31682859992906465 + 0.31683736496433368 + 0.31684613027352093 + 0.31685489585663928 + 0.31686366171370228 + 0.31687242784472119 + 0.31688119424970962 + 0.31688996092868027 + 0.31689872788164541 + 0.31690749510861771 + 0.31691626260961081 + 0.31692503038463593 + 0.31693379843370745 + 0.31694256675683591 + 0.31695133535403569 + 0.31696010422531956 + 0.31696887337069968 + 0.3169776427901887 + 0.31698641248379877 + 0.31699518245154429 + 0.31700395269343645 + 0.3170127232094882 + 0.31702149399971224 + 0.3170302650641223 + 0.31703903640272951 + 0.31704780801554761 + 0.31705657990258934 + 0.3170653520638676 + 0.31707412449939371 + 0.31708289720918187 + 0.31709167019324352 + 0.31710044345159305 + 0.31710921698424166 + 0.31711799079120301 + 0.31712676487248914 + 0.31713553922811294 + 0.31714431385808711 + 0.31715308876242465 + 0.31716186394113915 + 0.31717063939424106 + 0.31717941512174475 + 0.31718819112366237 + 0.31719696740000747 + 0.31720574395079137 + 0.31721452077602852 + 0.31722329787573011 + 0.31723207524990982 + 0.31724085289857973 + 0.31724963082175262 + 0.31725840901944147 + 0.31726718749165972 + 0.31727596623841881 + 0.31728474525973155 + 0.31729352455561233 + 0.31730230412607163 + 0.31731108397112395 + 0.31731986409078133 + 0.31732864448505654 + 0.31733742515396179 + 0.31734620609751141 + 0.31735498731571593 + 0.3173637688085898 + 0.317372550576145 + 0.31738133261839452 + 0.31739011493535113 + 0.31739889752702771 + 0.31740768039343631 + 0.31741646353459063 + 0.31742524695050273 + 0.31743403064118547 + 0.31744281460665169 + 0.31745159884691426 + 0.31746038336198606 + 0.31746916815187914 + 0.31747795321660721 + 0.31748673855618237 + 0.31749552417061738 + 0.31750431005992513 + 0.31751309622411861 + 0.31752188266320974 + 0.31753066937721303 + 0.31753945636613901 + 0.31754824363000217 + 0.31755703116881451 + 0.3175658189825889 + 0.31757460707133828 + 0.31758339543507474 + 0.31759218407381185 + 0.31760097298756179 + 0.31760976217633813 + 0.31761855164015307 + 0.31762734137901866 + 0.31763613139294933 + 0.3176449216819564 + 0.31765371224605354 + 0.31766250308525368 + 0.31767129419956797 + 0.31768008558901101 + 0.3176888772535949 + 0.31769766919333164 + 0.317706461408235 + 0.31771525389831862 + 0.317724046663593 + 0.31773283970407179 + 0.31774163301976865 + 0.31775042661069586 + 0.31775922047686533 + 0.31776801461829157 + 0.31777680903498595 + 0.31778560372696124 + 0.31779439869423209 + 0.31780319393680811 + 0.31781198945470535 + 0.31782078524793439 + 0.3178295813165089 + 0.31783837766044093 + 0.31784717427974424 + 0.31785597117443171 + 0.3178647683445146 + 0.31787356579000742 + 0.31788236351092236 + 0.31789116150727142 + 0.31789995977906915 + 0.31790875832632676 + 0.31791755714905728 + 0.31792635624727439 + 0.31793515562098934 + 0.31794395527021663 + 0.31795275519496846 + 0.31796155539525756 + 0.31797035587109623 + 0.31797915662249732 + 0.31798795764947446 + 0.31799675895203988 + 0.31800556053020718 + 0.31801436238398767 + 0.31802316451339518 + 0.31803196691844254 + 0.31804076959914263 + 0.31804957255550687 + 0.31805837578755042 + 0.318067179295284 + 0.31807598307872115 + 0.31808478713787564 + 0.31809359147275879 + 0.31810239608338431 + 0.31811120096976436 + 0.3181200061319126 + 0.31812881156984119 + 0.31813761728356299 + 0.31814642327309106 + 0.31815522953843817 + 0.31816403607961735 + 0.31817284289664066 + 0.31818164998952181 + 0.31819045735827373 + 0.31819926500290785 + 0.31820807292343856 + 0.31821688111987723 + 0.31822568959223846 + 0.31823449834053352 + 0.31824330736477607 + 0.31825211666497916 + 0.31826092624115404 + 0.31826973609331527 + 0.318278546221475 + 0.31828735662564611 + 0.31829616730584159 + 0.31830497826207432 + 0.31831378949435651 + 0.31832260100270104 + 0.31833141278712163 + 0.31834022484763125 + 0.31834903718424123 + 0.3183578497969653 + 0.3183666626858172 + 0.31837547585080828 + 0.31838428929195145 + 0.31839310300926049 + 0.31840191700274839 + 0.31841073127242631 + 0.318419545818309 + 0.31842836064040847 + 0.31843717573873692 + 0.31844599111330807 + 0.31845480676413568 + 0.31846362269123035 + 0.31847243889460652 + 0.31848125537427641 + 0.31849007213025377 + 0.31849888916254987 + 0.31850770647117854 + 0.31851652405615272 + 0.31852534191748533 + 0.31853416005518853 + 0.31854297846927609 + 0.31855179715976017 + 0.31856061612665376 + 0.31856943536996973 + 0.3185782548897218 + 0.31858707468592073 + 0.31859589475858163 + 0.3186047151077161 + 0.31861353573333839 + 0.31862235663545857 + 0.31863117781409261 + 0.31863999926925118 + 0.31864882100094877 + 0.31865764300919674 + 0.31866646529400972 + 0.31867528785539823 + 0.3186841106933776 + 0.31869293380795921 + 0.31870175719915605 + 0.31871058086698106 + 0.31871940481144806 + 0.31872822903256842 + 0.31873705353035581 + 0.31874587830482332 + 0.31875470335598377 + 0.3187635286838495 + 0.31877235428843331 + 0.31878118016974916 + 0.31879000632780907 + 0.31879883276262605 + 0.31880765947421313 + 0.31881648646258243 + 0.31882531372774853 + 0.31883414126972287 + 0.31884296908851828 + 0.31885179718414869 + 0.3188606255566262 + 0.31886945420596458 + 0.31887828313217531 + 0.31888711233527206 + 0.31889594181526781 + 0.31890477157217562 + 0.31891360160600762 + 0.31892243191677766 + 0.31893126250449855 + 0.31894009336918183 + 0.31894892451084211 + 0.31895775592949149 + 0.31896658762514213 + 0.31897541959780873 + 0.31898425184750256 + 0.31899308437423746 + 0.31900191717802567 + 0.31901075025888009 + 0.31901958361681454 + 0.31902841725184128 + 0.31903725116397402 + 0.31904608535322415 + 0.31905491981960554 + 0.31906375456313107 + 0.31907258958381313 + 0.31908142488166524 + 0.3190902604566998 + 0.31909909630893057 + 0.31910793243836971 + 0.31911676884503026 + 0.31912560552892516 + 0.3191344424900675 + 0.31914327972846934 + 0.31915211724414544 + 0.31916095503710712 + 0.31916979310736732 + 0.31917863145494002 + 0.31918747007983728 + 0.31919630898207207 + 0.31920514816165757 + 0.31921398761860742 + 0.31922282735293311 + 0.31923166736464847 + 0.31924050765376566 + 0.31924934822029849 + 0.3192581890642599 + 0.31926703018566149 + 0.31927587158451853 + 0.31928471326084162 + 0.3192935552146447 + 0.31930239744594058 + 0.31931123995474242 + 0.31932008274106322 + 0.31932892580491523 + 0.31933776914631218 + 0.3193466127652671 + 0.31935545666179149 + 0.31936430083589984 + 0.31937314528760452 + 0.31938199001691842 + 0.31939083502385462 + 0.31939968030842614 + 0.31940852587064511 + 0.31941737171052631 + 0.31942621782808028 + 0.31943506422332169 + 0.31944391089626345 + 0.31945275784691718 + 0.31946160507529725 + 0.31947045258141604 + 0.31947930036528666 + 0.31948814842692197 + 0.31949699676633425 + 0.31950584538353738 + 0.31951469427854434 + 0.31952354345136741 + 0.3195323929020204 + 0.31954124263051553 + 0.31955009263686579 + 0.31955894292108433 + 0.31956779348318404 + 0.31957664432317806 + 0.31958549544107945 + 0.3195943468369003 + 0.31960319851065461 + 0.31961205046235536 + 0.31962090269201471 + 0.31962975519964654 + 0.31963860798526239 + 0.31964746104887681 + 0.31965631439050207 + 0.31966516801015121 + 0.31967402190783645 + 0.31968287608357249 + 0.31969173053737066 + 0.31970058526924494 + 0.3197094402792075 + 0.31971829556727216 + 0.31972715113345124 + 0.31973600697775778 + 0.31974486310020478 + 0.31975371950080611 + 0.31976257617957321 + 0.31977143313652001 + 0.31978029037165945 + 0.31978914788500462 + 0.3197980056765678 + 0.31980686374636286 + 0.31981572209440201 + 0.31982458072069903 + 0.31983343962526561 + 0.31984229880811693 + 0.31985115826926303 + 0.3198600180087201 + 0.31986887802649805 + 0.31987773832261224 + 0.31988659889707427 + 0.31989545974989786 + 0.31990432088109616 + 0.31991318229068139 + 0.31992204397866741 + 0.31993090594506574 + 0.31993976818989106 + 0.31994863071315549 + 0.31995749351487224 + 0.31996635659505435 + 0.31997521995371486 + 0.31998408359086677 + 0.31999294750652246 + 0.32000181170069575 + 0.3200106761733989 + 0.32001954092464585 + 0.32002840595444881 + 0.32003727126282089 + 0.3200461368497759 + 0.32005500271532616 + 0.3200638688594839 + 0.32007273528226382 + 0.3200816019836783 + 0.32009046896373944 + 0.32009933622246123 + 0.32010820375985671 + 0.32011707157593816 + 0.32012593967071867 + 0.32013480804421218 + 0.32014367669643162 + 0.3201525456273886 + 0.32016141483709698 + 0.32017028432557054 + 0.32017915409282094 + 0.32018802413886266 + 0.32019689446370742 + 0.32020576506736892 + 0.32021463594986033 + 0.32022350711119391 + 0.32023237855138276 + 0.32024125027044076 + 0.32025012226838095 + 0.32025899454521495 + 0.32026786710095728 + 0.32027673993562045 + 0.32028561304921738 + 0.32029448644176117 + 0.32030336011326416 + 0.3203122340637411 + 0.32032110829320332 + 0.32032998280166486 + 0.32033885758913799 + 0.3203477326556366 + 0.32035660800117299 + 0.32036548362576106 + 0.32037435952941229 + 0.32038323571214133 + 0.32039211217396141 + 0.32040098891488317 + 0.32040986593492204 + 0.32041874323409042 + 0.32042762081240134 + 0.32043649866986801 + 0.32044537680650259 + 0.32045425522231835 + 0.32046313391732989 + 0.32047201289154786 + 0.32048089214498715 + 0.32048977167765996 + 0.32049865148958012 + 0.32050753158075934 + 0.32051641195121211 + 0.32052529260095086 + 0.32053417352998875 + 0.320543054738338 + 0.32055193622601336 + 0.32056081799302633 + 0.32056970003939006 + 0.32057858236511849 + 0.32058746497022456 + 0.32059634785472085 + 0.32060523101862104 + 0.32061411446193677 + 0.32062299818468359 + 0.32063188218687216 + 0.32064076646851641 + 0.32064965102963028 + 0.32065853587022519 + 0.3206674209903152 + 0.32067630638991346 + 0.3206851920690329 + 0.32069407802768601 + 0.32070296426588674 + 0.32071185078364806 + 0.32072073758098241 + 0.32072962465790289 + 0.32073851201442422 + 0.32074739965055638 + 0.32075628756631558 + 0.32076517576171271 + 0.32077406423676236 + 0.32078295299147697 + 0.32079184202586886 + 0.32080073133995185 + 0.32080962093373999 + 0.32081851080724477 + 0.3208274009604794 + 0.32083629139345848 + 0.32084518210619367 + 0.32085407309869807 + 0.32086296437098555 + 0.32087185592306849 + 0.32088074775496017 + 0.32088963986667512 + 0.3208985322582234 + 0.32090742492962049 + 0.3209163178808796 + 0.32092521111201222 + 0.32093410462303229 + 0.32094299841395302 + 0.3209518924847875 + 0.32096078683554813 + 0.32096968146624877 + 0.32097857637690269 + 0.32098747156752289 + 0.32099636703812184 + 0.32100526278871261 + 0.32101415881930923 + 0.32102305512992396 + 0.32103195172057003 + 0.32104084859126136 + 0.32104974574201034 + 0.32105864317283006 + 0.32106754088373296 + 0.32107643887473447 + 0.3210853371458447 + 0.32109423569707907 + 0.32110313452844919 + 0.32111203363996987 + 0.32112093303165262 + 0.32112983270351059 + 0.32113873265555865 + 0.3211476328878074 + 0.32115653340027162 + 0.32116543419296456 + 0.32117433526589856 + 0.32118323661908682 + 0.32119213825254239 + 0.32120104016627932 + 0.32120994236031003 + 0.32121884483464752 + 0.32122774758930517 + 0.32123665062429596 + 0.32124555393963233 + 0.32125445753532911 + 0.32126336141139783 + 0.32127226556785321 + 0.32128117000470685 + 0.32129007472197202 + 0.32129897971966254 + 0.32130788499779167 + 0.3213167905563718 + 0.32132569639541686 + 0.32133460251493923 + 0.32134350891495217 + 0.32135241559546951 + 0.32136132255650374 + 0.32137022979806801 + 0.32137913732017548 + 0.32138804512283947 + 0.3213969532060737 + 0.32140586156988993 + 0.3214147702143022 + 0.32142367913932429 + 0.32143258834496719 + 0.32144149783124637 + 0.32145040759817423 + 0.32145931764576313 + 0.32146822797402719 + 0.32147713858297866 + 0.32148604947263154 + 0.32149496064299909 + 0.32150387209409292 + 0.32151278382592852 + 0.3215216958385167 + 0.32153060813187234 + 0.3215395207060085 + 0.32154843356093693 + 0.32155734669667146 + 0.32156626011322631 + 0.32157517381061362 + 0.32158408778884595 + 0.32159300204793806 + 0.32160191658790233 + 0.32161083140875196 + 0.32161974651049935 + 0.32162866189315859 + 0.32163757755674272 + 0.32164649350126506 + 0.32165540972673801 + 0.32166432623317548 + 0.3216732430205908 + 0.32168216008899625 + 0.32169107743840591 + 0.32169999506883223 + 0.32170891298028831 + 0.32171783117278824 + 0.3217267496463444 + 0.32173566840097079 + 0.321744587436679 + 0.32175350675348391 + 0.32176242635139796 + 0.32177134623043419 + 0.32178026639060675 + 0.3217891868319272 + 0.32179810755440963 + 0.32180702855806714 + 0.32181594984291384 + 0.32182487140896132 + 0.3218337932562228 + 0.3218427153847131 + 0.32185163779444464 + 0.32186056048542977 + 0.32186948345768179 + 0.32187840671121554 + 0.32188733024604255 + 0.32189625406217615 + 0.3219051781596311 + 0.32191410253841901 + 0.32192302719855315 + 0.32193195214004672 + 0.32194087736291371 + 0.32194980286716662 + 0.32195872865281944 + 0.32196765471988464 + 0.32197658106837534 + 0.32198550769830486 + 0.32199443460968646 + 0.32200336180253408 + 0.32201228927685943 + 0.32202121703267733 + 0.32203014507000016 + 0.32203907338884113 + 0.3220480019892128 + 0.32205693087112996 + 0.32206586003460497 + 0.32207478947965029 + 0.32208371920628004 + 0.32209264921450742 + 0.32210157950434559 + 0.32211051007580715 + 0.32211944092890604 + 0.32212837206365541 + 0.32213730348006792 + 0.32214623517815744 + 0.32215516715793646 + 0.32216409941941987 + 0.32217303196261843 + 0.32218196478754785 + 0.32219089789421895 + 0.32219983128264662 + 0.32220876495284323 + 0.3222176989048221 + 0.32222663313859806 + 0.32223556765418199 + 0.32224450245158781 + 0.3222534375308298 + 0.32226237289192011 + 0.32227130853487229 + 0.32228024445969944 + 0.32228918066641482 + 0.32229811715503254 + 0.32230705392556419 + 0.32231599097802388 + 0.32232492831242565 + 0.3223338659287811 + 0.32234280382710523 + 0.32235174200740957 + 0.32236068046970823 + 0.32236961921401525 + 0.32237855824034151 + 0.32238749754870272 + 0.3223964371391112 + 0.32240537701157956 + 0.32241431716612179 + 0.32242325760275126 + 0.32243219832148023 + 0.32244113932232382 + 0.32245008060529268 + 0.32245902217040262 + 0.32246796401766525 + 0.32247690614709462 + 0.32248584855870321 + 0.32249479125250435 + 0.32250373422851208 + 0.32251267748673962 + 0.3225216210271995 + 0.32253056484990578 + 0.32253950895487093 + 0.3225484533421083 + 0.32255739801163186 + 0.3225663429634541 + 0.32257528819758835 + 0.32258423371404865 + 0.32259317951284749 + 0.32260212559399815 + 0.32261107195751471 + 0.32262001860340972 + 0.32262896553169629 + 0.3226379127423879 + 0.32264686023549771 + 0.32265580801103988 + 0.322664756069026 + 0.32267370440947102 + 0.32268265303238741 + 0.32269160193778851 + 0.32270055112568757 + 0.32270950059609776 + 0.32271845034903257 + 0.3227274003845052 + 0.32273635070252815 + 0.32274530130311629 + 0.32275425218628212 + 0.3227632033520389 + 0.32277215480040006 + 0.32278110653137876 + 0.32279005854498755 + 0.32279901084124124 + 0.32280796342015167 + 0.32281691628173287 + 0.32282586942599811 + 0.32283482285296072 + 0.32284377656263402 + 0.32285273055503044 + 0.32286168483016414 + 0.32287063938804844 + 0.32287959422869572 + 0.32288854935212108 + 0.32289750475833606 + 0.32290646044735483 + 0.32291541641918992 + 0.32292437267385538 + 0.32293332921136458 + 0.32294228603173075 + 0.32295124313496648 + 0.32296020052108582 + 0.3229691581901013 + 0.32297811614202704 + 0.32298707437687629 + 0.32299603289466172 + 0.32300499169539731 + 0.3230139507790955 + 0.32302291014577139 + 0.3230318697954358 + 0.32304082972810366 + 0.32304978994378747 + 0.32305875044250221 + 0.3230677112242587 + 0.323076672289072 + 0.32308563363695519 + 0.32309459526792106 + 0.3231035571819828 + 0.32311251937915453 + 0.32312148185944956 + 0.32313044462288043 + 0.32313940766946053 + 0.32314837099920468 + 0.32315733461212304 + 0.32316629850823225 + 0.32317526268754382 + 0.32318422715007211 + 0.32319319189582946 + 0.32320215692482923 + 0.3232111222370857 + 0.32322008783261125 + 0.32322905371142002 + 0.32323801987352463 + 0.32324698631893839 + 0.32325595304767529 + 0.32326492005974811 + 0.32327388735517076 + 0.32328285493395592 + 0.32329182279611685 + 0.32330079094166775 + 0.32330975937062106 + 0.32331872808299023 + 0.32332769707878933 + 0.32333666635803099 + 0.3233456359207284 + 0.32335460576689579 + 0.32336357589654574 + 0.32337254630969237 + 0.32338151700634732 + 0.32339048798652648 + 0.32339945925024072 + 0.32340843079750498 + 0.32341740262833185 + 0.3234263747427355 + 0.32343534714072841 + 0.32344431982232386 + 0.32345329278753543 + 0.32346226603637707 + 0.3234712395688622 + 0.32348021338500338 + 0.32348918748481309 + 0.32349816186830721 + 0.3235071365354974 + 0.32351611148639703 + 0.32352508672101948 + 0.32353406223937892 + 0.32354303804148793 + 0.32355201412736057 + 0.32356099049700943 + 0.32356996715044789 + 0.32357894408769011 + 0.32358792130874869 + 0.32359689881363773 + 0.32360587660236978 + 0.32361485467495832 + 0.32362383303141656 + 0.32363281167175961 + 0.32364179059599907 + 0.32365076980414842 + 0.32365974929622104 + 0.3236687290722311 + 0.32367770913219107 + 0.32368668947611517 + 0.32369567010401606 + 0.32370465101590773 + 0.32371363221180294 + 0.32372261369171568 + 0.32373159545565872 + 0.32374057750364604 + 0.32374955983569037 + 0.32375854245180502 + 0.32376752535200493 + 0.32377650853630113 + 0.32378549200470941 + 0.32379447575724146 + 0.32380345979391073 + 0.32381244411473142 + 0.32382142871971681 + 0.3238304136088796 + 0.32383939878223389 + 0.32384838423979234 + 0.32385736998156905 + 0.32386635600757746 + 0.32387534231783011 + 0.3238843289123412 + 0.32389331579112418 + 0.32390230295419153 + 0.32391129040155753 + 0.32392027813323548 + 0.323929266149238 + 0.32393825444958013 + 0.32394724303427286 + 0.32395623190333195 + 0.32396522105676995 + 0.32397421049459946 + 0.3239832002168348 + 0.32399219022348918 + 0.32400118051457616 + 0.32401017109010827 + 0.32401916195010044 + 0.32402815309456456 + 0.32403714452351473 + 0.32404613623696527 + 0.32405512823492794 + 0.3240641205174169 + 0.32407311308444553 + 0.32408210593602738 + 0.32409109907217559 + 0.32410009249290389 + 0.32410908619822543 + 0.32411808018815369 + 0.32412707446270206 + 0.32413606902188402 + 0.32414506386571373 + 0.32415405899420296 + 0.32416305440736676 + 0.32417205010521777 + 0.32418104608776854 + 0.32419004235503412 + 0.32419903890702784 + 0.3242080357437625 + 0.3242170328652505 + 0.32422603027150693 + 0.32423502796254527 + 0.32424402593837726 + 0.32425302419901869 + 0.32426202274448074 + 0.32427102157477822 + 0.32428002068992384 + 0.32428902008993182 + 0.32429801977481482 + 0.32430701974458698 + 0.32431601999926096 + 0.32432502053885109 + 0.32433402136336975 + 0.32434302247283137 + 0.32435202386724843 + 0.32436102554663526 + 0.32437002751100447 + 0.32437902976037103 + 0.32438803229474683 + 0.3243970351141453 + 0.32440603821858144 + 0.32441504160806706 + 0.32442404528261642 + 0.32443304924224209 + 0.3244420534869592 + 0.32445105801678031 + 0.32446006283171813 + 0.32446906793178676 + 0.32447807331700057 + 0.3244870789873705 + 0.32449608494291327 + 0.3245050911836399 + 0.32451409770956452 + 0.32452310452070149 + 0.32453211161706264 + 0.32454111899866295 + 0.32455012666551503 + 0.32455913461763242 + 0.32456814285502855 + 0.32457715137771681 + 0.3245861601857114 + 0.32459516927902515 + 0.32460417865767216 + 0.32461318832166425 + 0.32462219827101652 + 0.3246312085057424 + 0.32464021902585455 + 0.32464922983136729 + 0.32465824092229317 + 0.32466725229864646 + 0.32467626396043986 + 0.32468527590768753 + 0.32469428814040302 + 0.32470330065859887 + 0.32471231346228946 + 0.32472132655148817 + 0.32473033992620765 + 0.324739353586463 + 0.32474836753226605 + 0.32475738176363111 + 0.32476639628057152 + 0.32477541108310082 + 0.32478442617123249 + 0.32479344154498074 + 0.32480245720435741 + 0.32481147314937686 + 0.32482048938005254 + 0.32482950589639858 + 0.32483852269842695 + 0.32484753978615349 + 0.32485655715958933 + 0.32486557481874939 + 0.3248745927636465 + 0.32488361099429408 + 0.32489262951070635 + 0.32490164831289592 + 0.32491066740087721 + 0.32491968677466282 + 0.32492870643426702 + 0.32493772637970336 + 0.32494674661098438 + 0.32495576712812441 + 0.32496478793113692 + 0.32497380902003464 + 0.32498283039483178 + 0.32499185205554182 + 0.32500087400217825 + 0.32500989623475462 + 0.32501891875328431 + 0.32502794155778086 + 0.32503696464825765 + 0.32504598802472834 + 0.32505501168720624 + 0.32506403563570574 + 0.3250730598702386 + 0.32508208439082009 + 0.32509110919746359 + 0.32510013429018092 + 0.32510915966898818 + 0.32511818533389619 + 0.32512721128492017 + 0.32513623752207282 + 0.32514526404536925 + 0.3251542908548205 + 0.32516331795044162 + 0.32517234533224698 + 0.32518137300024769 + 0.32519040095445961 + 0.32519942919489458 + 0.32520845772156776 + 0.32521748653449106 + 0.32522651563367871 + 0.32523554501914503 + 0.32524457469090196 + 0.32525360464896452 + 0.32526263489334467 + 0.32527166542405755 + 0.32528069624111577 + 0.32528972734453371 + 0.32529875873432312 + 0.32530779041049929 + 0.32531682237307569 + 0.32532585462206498 + 0.32533488715748143 + 0.32534391997933781 + 0.32535295308764839 + 0.32536198648242665 + 0.32537102016368535 + 0.32538005413143967 + 0.32538908838570141 + 0.32539812292648485 + 0.32540715775380358 + 0.32541619286767115 + 0.32542522826810094 + 0.32543426395510661 + 0.32544329992870158 + 0.32545233618889935 + 0.32546137273571429 + 0.32547040956915918 + 0.32547944668924816 + 0.32548848409599329 + 0.32549752178941044 + 0.32550655976951076 + 0.32551559803631008 + 0.32552463658982045 + 0.32553367543005612 + 0.32554271455702988 + 0.32555175397075592 + 0.32556079367124785 + 0.32556983365851921 + 0.32557887393258345 + 0.3255879144934542 + 0.32559695534114497 + 0.32560599647566918 + 0.32561503789704049 + 0.32562407960527312 + 0.32563312160037983 + 0.32564216388237421 + 0.3256512064512706 + 0.32566024930708165 + 0.3256692924498209 + 0.32567833587950362 + 0.32568737959614075 + 0.32569642359974832 + 0.32570546789033827 + 0.32571451246792499 + 0.32572355733252184 + 0.32573260248414254 + 0.32574164792280058 + 0.32575069364850945 + 0.32575973966128274 + 0.32576878596113401 + 0.32577783254807674 + 0.32578687942212531 + 0.32579592658329243 + 0.32580497403159175 + 0.32581402176703822 + 0.32582306978964315 + 0.32583211809942164 + 0.32584116669638724 + 0.32585021558055277 + 0.32585926475193244 + 0.3258683142105398 + 0.32587736395638939 + 0.32588641398949297 + 0.32589546430986499 + 0.32590451491751893 + 0.32591356581246839 + 0.32592261699472774 + 0.32593166846430888 + 0.32594072022122705 + 0.32594977226549571 + 0.32595882459712772 + 0.32596787721613735 + 0.32597693012253737 + 0.32598598331634221 + 0.32599503679756459 + 0.3260040905662196 + 0.32601314462231934 + 0.32602219896587803 + 0.32603125359691015 + 0.32604030851542759 + 0.32604936372144561 + 0.32605841921497597 + 0.32606747499603406 + 0.32607653106463258 + 0.32608558742078586 + 0.32609464406450667 + 0.32610370099580938 + 0.32611275821470681 + 0.32612181572121407 + 0.32613087351534242 + 0.32613993159710775 + 0.32614898996652281 + 0.32615804862360048 + 0.32616710756835587 + 0.32617616680080175 + 0.32618522632095087 + 0.32619428612881929 + 0.3262033462244181 + 0.32621240660776257 + 0.32622146727886542 + 0.32623052823774101 + 0.32623958948440296 + 0.32624865101886408 + 0.32625771284113869 + 0.3262667749512404 + 0.32627583734918197 + 0.32628490003497868 + 0.32629396300864233 + 0.32630302627018831 + 0.32631208981962934 + 0.32632115365697889 + 0.32633021778225146 + 0.32633928219545988 + 0.32634834689661846 + 0.32635741188573997 + 0.3263664771628389 + 0.32637554272792801 + 0.32638460858102236 + 0.32639367472213332 + 0.3264027411512776 + 0.32641180786846646 + 0.32642087487371418 + 0.32642994216703525 + 0.3264390097484417 + 0.32644807761794864 + 0.32645714577556889 + 0.32646621422131683 + 0.32647528295520611 + 0.32648435197724962 + 0.3264934212874615 + 0.32650249088585559 + 0.32651156077244536 + 0.32652063094724371 + 0.32652970141026583 + 0.32653877216152444 + 0.32654784320103242 + 0.32655691452880575 + 0.32656598614485566 + 0.3265750580491974 + 0.32658413024184446 + 0.32659320272280973 + 0.32660227549210763 + 0.32661134854975177 + 0.32662042189575491 + 0.32662949553013226 + 0.32663856945289593 + 0.32664764366406107 + 0.32665671816363973 + 0.3266657929516471 + 0.32667486802809675 + 0.32668394339300083 + 0.32669301904637515 + 0.32670209498823194 + 0.32671117121858556 + 0.32672024773744873 + 0.326729324544836 + 0.3267384016407609 + 0.32674747902523793 + 0.32675655669827908 + 0.32676563465989955 + 0.3267747129101114 + 0.32678379144893066 + 0.3267928702763685 + 0.32680194939244028 + 0.32681102879716023 + 0.32682010849053977 + 0.32682918847259407 + 0.32683826874333743 + 0.32684734930278214 + 0.32685643015094235 + 0.3268655112878327 + 0.32687459271346597 + 0.32688367442785571 + 0.32689275643101567 + 0.32690183872296019 + 0.32691092130370303 + 0.32692000417325695 + 0.32692908733163717 + 0.32693817077885579 + 0.32694725451492712 + 0.326956338539865 + 0.32696542285368285 + 0.32697450745639534 + 0.32698359234801433 + 0.32699267752855599 + 0.3270017629980323 + 0.32701084875645686 + 0.32701993480384423 + 0.32702902114020804 + 0.32703810776556097 + 0.3270471946799185 + 0.32705628188329339 + 0.32706536937569924 + 0.32707445715714972 + 0.32708354522765931 + 0.32709263358724083 + 0.327101722235908 + 0.32711081117367602 + 0.32711990040055694 + 0.32712898991656519 + 0.32713807972171371 + 0.32714716981601777 + 0.32715626019949007 + 0.32716535087214443 + 0.32717444183399524 + 0.32718353308505455 + 0.32719262462533844 + 0.32720171645485818 + 0.32721080857362983 + 0.32721990098166542 + 0.32722899367898028 + 0.32723808666558718 + 0.3272471799414991 + 0.3272562735067312 + 0.32726536736129641 + 0.32727446150520839 + 0.3272835559384808 + 0.32729265066112889 + 0.32730174567316478 + 0.32731084097460289 + 0.3273199365654561 + 0.32732903244573969 + 0.32733812861546657 + 0.32734722507465036 + 0.32735632182330476 + 0.32736541886144427 + 0.3273745161890817 + 0.3273836138062316 + 0.32739271171290757 + 0.3274018099091226 + 0.32741090839489101 + 0.32742000717022746 + 0.32742910623514387 + 0.32743820558965558 + 0.32744730523377474 + 0.32745640516751734 + 0.3274655053908947 + 0.32747460590392297 + 0.32748370670661409 + 0.32749280779898265 + 0.32750190918104238 + 0.32751101085280765 + 0.32752011281429055 + 0.3275292150655057 + 0.32753831760646746 + 0.32754742043718882 + 0.32755652355768416 + 0.32756562696796732 + 0.32757473066805104 + 0.32758383465794988 + 0.32759293893767838 + 0.32760204350724853 + 0.32761114836667576 + 0.32762025351597285 + 0.32762935895515349 + 0.3276384646842323 + 0.32764757070322292 + 0.32765667701213902 + 0.32766578361099352 + 0.32767489049980092 + 0.32768399767857576 + 0.32769310514733002 + 0.3277022129060792 + 0.32771132095483685 + 0.32772042929361589 + 0.32772953792243009 + 0.32773864684129472 + 0.32774775605022188 + 0.32775686554922612 + 0.32776597533832108 + 0.32777508541752132 + 0.32778419578683976 + 0.32779330644629007 + 0.32780241739588678 + 0.32781152863564367 + 0.32782064016557355 + 0.32782975198569092 + 0.32783886409601037 + 0.32784797649654407 + 0.32785708918730644 + 0.32786620216831197 + 0.32787531543957449 + 0.32788442900110681 + 0.32789354285292271 + 0.32790265699503751 + 0.32791177142746336 + 0.32792088615021553 + 0.32793000116330606 + 0.32793911646675045 + 0.32794823206056156 + 0.3279573479447539 + 0.32796646411934116 + 0.32797558058433635 + 0.32798469733975394 + 0.32799381438560765 + 0.3280029317219112 + 0.32801204934867839 + 0.32802116726592373 + 0.32803028547366009 + 0.32803940397190207 + 0.3280485227606626 + 0.32805764183995695 + 0.32806676120979728 + 0.32807588087019818 + 0.32808500082117331 + 0.32809412106273728 + 0.32810324159490295 + 0.32811236241768493 + 0.32812148353109616 + 0.32813060493515112 + 0.32813972662986352 + 0.32814884861524724 + 0.32815797089131593 + 0.32816709345808415 + 0.32817621631556482 + 0.32818533946377254 + 0.32819446290271942 + 0.32820358663242161 + 0.32821271065289198 + 0.32822183496414448 + 0.3282309595661918 + 0.32824008445905034 + 0.32824920964273124 + 0.32825833511724994 + 0.32826746088262027 + 0.32827658693885586 + 0.32828571328596973 + 0.3282948399239764 + 0.32830396685289037 + 0.32831309407272397 + 0.32832222158349322 + 0.32833134938520947 + 0.32834047747788891 + 0.32834960586154377 + 0.32835873453618852 + 0.32836786350183689 + 0.32837699275850268 + 0.32838612230619973 + 0.32839525214494253 + 0.32840438227474483 + 0.32841351269561964 + 0.32842264340758148 + 0.32843177441064414 + 0.32844090570482143 + 0.32845003729012701 + 0.32845916916657542 + 0.32846830133417987 + 0.32847743379295385 + 0.32848656654291214 + 0.32849569958406838 + 0.3285048329164364 + 0.32851396654003084 + 0.32852310045486371 + 0.3285322346609505 + 0.32854136915830412 + 0.32855050394693996 + 0.32855963902686947 + 0.32856877439810878 + 0.32857791006067083 + 0.32858704601456939 + 0.32859618225981829 + 0.32860531879643218 + 0.32861445562442382 + 0.32862359274380809 + 0.32863273015459848 + 0.32864186785680816 + 0.32865100585045243 + 0.32866014413554434 + 0.32866928271209844 + 0.32867842158012855 + 0.32868756073964683 + 0.32869670019066938 + 0.32870583993320934 + 0.32871497996727961 + 0.32872412029289561 + 0.32873326091007032 + 0.32874240181881831 + 0.3287515430191526 + 0.32876068451108781 + 0.32876982629463852 + 0.3287789683698169 + 0.32878811073663755 + 0.32879725339511423 + 0.32880639634526165 + 0.32881553958709353 + 0.32882468312062363 + 0.32883382694586505 + 0.32884297106283228 + 0.32885211547154009 + 0.3288612601720004 + 0.32887040516422894 + 0.32887955044824008 + 0.3288886960240453 + 0.32889784189166082 + 0.32890698805109886 + 0.32891613450237478 + 0.3289252812455008 + 0.32893442828049313 + 0.32894357560736404 + 0.32895272322612801 + 0.3289618711367982 + 0.32897101933938983 + 0.32898016783391615 + 0.32898931662039083 + 0.32899846569882762 + 0.32900761506924131 + 0.32901676473164643 + 0.32902591468605435 + 0.32903506493248136 + 0.32904421547094037 + 0.32905336630144533 + 0.32906251742401083 + 0.32907166883865063 + 0.32908082054537779 + 0.32908997254420697 + 0.32909912483515186 + 0.3291082774182264 + 0.3291174302934452 + 0.32912658346082208 + 0.32913573692037007 + 0.32914489067210295 + 0.32915404471603615 + 0.32916319905218278 + 0.32917235368055658 + 0.32918150860117223 + 0.32919066381404194 + 0.32919981931918191 + 0.3292089751166053 + 0.32921813120632498 + 0.32922728758835645 + 0.32923644426271276 + 0.32924560122940771 + 0.32925475848845676 + 0.32926391603987137 + 0.32927307388366778 + 0.32928223201985896 + 0.32929139044845873 + 0.32930054916948187 + 0.32930970818294125 + 0.32931886748885086 + 0.32932802708722608 + 0.32933718697807912 + 0.32934634716142547 + 0.32935550763727817 + 0.3293646684056511 + 0.32937382946655963 + 0.32938299082001515 + 0.32939215246603326 + 0.32940131440462855 + 0.32941047663581408 + 0.32941963915960448 + 0.32942880197601193 + 0.3294379650850528 + 0.32944712848673924 + 0.32945629218108685 + 0.32946545616810774 + 0.32947462044781817 + 0.32948378502022968 + 0.32949294988535777 + 0.32950211504321614 + 0.32951128049381867 + 0.32952044623717852 + 0.32952961227331184 + 0.32953877860223019 + 0.32954794522394903 + 0.3295571121384821 + 0.32956627934584426 + 0.32957544684604673 + 0.32958461463910671 + 0.3295937827250357 + 0.32960295110384907 + 0.32961211977556082 + 0.32962128874018459 + 0.32963045799773449 + 0.32963962754822346 + 0.32964879739166786 + 0.32965796752807985 + 0.32966713795747327 + 0.32967630867986369 + 0.32968547969526341 + 0.32969465100368789 + 0.32970382260515008 + 0.32971299449966396 + 0.32972216668724424 + 0.32973133916790548 + 0.32974051194165926 + 0.32974968500852181 + 0.32975885836850705 + 0.32976803202162797 + 0.32977720596789933 + 0.3297863802073342 + 0.32979555473994798 + 0.32980472956575391 + 0.3298139046847649 + 0.3298230800969974 + 0.32983225580246356 + 0.32984143180117814 + 0.3298506080931542 + 0.3298597846784081 + 0.32986896155695117 + 0.32987813872879901 + 0.32988731619396472 + 0.32989649395246373 + 0.3299056720043092 + 0.32991485034951412 + 0.32992402898809409 + 0.32993320792006292 + 0.32994238714543378 + 0.32995156666422132 + 0.32996074647643947 + 0.32996992658210206 + 0.3299791069812239 + 0.32998828767381788 + 0.32999746865989898 + 0.33000664993948087 + 0.33001583151257757 + 0.33002501337920293 + 0.33003419553937091 + 0.33004337799309613 + 0.33005256074039258 + 0.33006174378127412 + 0.33007092711575459 + 0.33008011074384802 + 0.33008929466556824 + 0.33009847888093002 + 0.33010766338994718 + 0.33011684819263365 + 0.33012603328900425 + 0.3301352186790712 + 0.33014440436284992 + 0.33015359034035369 + 0.3301627766115971 + 0.33017196317659497 + 0.33018115003535953 + 0.33019033718790641 + 0.3301995246342494 + 0.33020871237440241 + 0.33021790040837784 + 0.33022708873619283 + 0.33023627735785877 + 0.3302454662733913 + 0.3302546554828043 + 0.33026384498611089 + 0.33027303478332654 + 0.33028222487446368 + 0.33029141525953776 + 0.33030060593856198 + 0.33030979691155177 + 0.33031898817851951 + 0.33032817973947992 + 0.33033737159444687 + 0.33034656374343524 + 0.33035575618645713 + 0.33036494892352991 + 0.33037414195466497 + 0.33038333527987712 + 0.33039252889918103 + 0.330401722812589 + 0.33041091702011743 + 0.33042011152177869 + 0.33042930631758827 + 0.33043850140755926 + 0.33044769679170571 + 0.33045689247004223 + 0.33046608844258291 + 0.33047528470934157 + 0.33048448127033214 + 0.33049367812556857 + 0.33050287527506572 + 0.33051207271883665 + 0.330521270456896 + 0.33053046848925877 + 0.33053966681593788 + 0.33054886543694734 + 0.33055806435230195 + 0.33056726356201555 + 0.33057646306610139 + 0.33058566286457497 + 0.33059486295744944 + 0.33060406334474041 + 0.33061326402645941 + 0.33062246500262271 + 0.33063166627324359 + 0.33064086783833585 + 0.33065006969791438 + 0.33065927185199312 + 0.33066847430058516 + 0.33067767704370532 + 0.33068688008136826 + 0.33069608341358731 + 0.33070528704037705 + 0.33071449096175154 + 0.33072369517772476 + 0.33073289968831066 + 0.33074210449352387 + 0.33075130959337778 + 0.33076051498788694 + 0.33076972067706545 + 0.33077892666092729 + 0.33078813293948711 + 0.33079733951275814 + 0.33080654638075513 + 0.33081575354349213 + 0.33082496100098302 + 0.33083416875324262 + 0.33084337680028408 + 0.33085258514212218 + 0.33086179377877084 + 0.33087100271024417 + 0.33088021193655598 + 0.33088942145772121 + 0.33089863127375363 + 0.33090784138466744 + 0.3309170517904757 + 0.33092626249119395 + 0.33093547348683627 + 0.33094468477741573 + 0.33095389636294809 + 0.33096310824344549 + 0.33097232041892377 + 0.33098153288939591 + 0.33099074565487591 + 0.33099995871538035 + 0.33100917207091979 + 0.3310183857215116 + 0.33102759966716794 + 0.33103681390790302 + 0.33104602844373154 + 0.33105524327466823 + 0.3310644584007264 + 0.33107367382191999 + 0.33108288953826376 + 0.3310921055497717 + 0.33110132185645791 + 0.33111053845833621 + 0.33111975535542243 + 0.33112897254772794 + 0.33113819003526923 + 0.33114740781805946 + 0.33115662589611194 + 0.33116584426944301 + 0.33117506293806576 + 0.33118428190199267 + 0.33119350116124108 + 0.33120272071582324 + 0.33121194056575315 + 0.33122116071104563 + 0.33123038115171549 + 0.33123960188777518 + 0.33124882291923952 + 0.33125804424612404 + 0.33126726586844119 + 0.33127648778620572 + 0.33128570999943091 + 0.33129493250813319 + 0.33130415531232488 + 0.33131337841202091 + 0.33132260180723599 + 0.33133182549798257 + 0.33134104948427628 + 0.3313502737661303 + 0.33135949834355949 + 0.33136872321657784 + 0.33137794838520013 + 0.33138717384943966 + 0.33139639960931122 + 0.33140562566482884 + 0.33141485201600646 + 0.33142407866285822 + 0.33143330560539885 + 0.33144253284364161 + 0.33145176037760216 + 0.33146098820729286 + 0.33147021633272938 + 0.33147944475392571 + 0.33148867347089511 + 0.33149790248365324 + 0.33150713179221325 + 0.33151636139658919 + 0.3315255912967951 + 0.33153482149284669 + 0.33154405198475706 + 0.33155328277254031 + 0.33156251385621127 + 0.33157174523578314 + 0.33158097691127086 + 0.33159020888268836 + 0.33159944115005047 + 0.33160867371337133 + 0.3316179065726641 + 0.33162713972794361 + 0.33163637317922479 + 0.33164560692652079 + 0.33165484096984649 + 0.3316640753092151 + 0.33167330994464223 + 0.33168254487614041 + 0.33169178010372613 + 0.33170101562741167 + 0.33171025144721283 + 0.33171948756314201 + 0.3317287239752148 + 0.3317379606834453 + 0.33174719768784672 + 0.33175643498843399 + 0.33176567258522188 + 0.33177491047822366 + 0.33178414866745426 + 0.33179338715292767 + 0.33180262593465876 + 0.33181186501265986 + 0.33182110438694684 + 0.33183034405753364 + 0.33183958402443431 + 0.33184882428766294 + 0.33185806484723446 + 0.33186730570316275 + 0.3318765468554612 + 0.3318857883041455 + 0.33189503004922877 + 0.33190427209072604 + 0.33191351442865041 + 0.33192275706301771 + 0.3319319999938411 + 0.33194124322113466 + 0.33195048674491323 + 0.33195973056519101 + 0.33196897468198272 + 0.33197821909530173 + 0.33198746380516203 + 0.3319967088115785 + 0.33200595411456613 + 0.33201519971413807 + 0.33202444561030842 + 0.33203369180309206 + 0.33204293829250309 + 0.3320521850785555 + 0.33206143216126432 + 0.33207067954064351 + 0.33207992721670632 + 0.33208917518946857 + 0.33209842345894258 + 0.33210767202514496 + 0.33211692088808814 + 0.33212617004778699 + 0.33213541950425646 + 0.33214466925751057 + 0.33215391930756255 + 0.3321631696544266 + 0.33217242029811916 + 0.33218167123865189 + 0.33219092247604054 + 0.33220017401029994 + 0.33220942584144264 + 0.33221867796948423 + 0.33222793039443815 + 0.33223718311631995 + 0.33224643613514221 + 0.33225568945091977 + 0.33226494306366755 + 0.33227419697339966 + 0.3322834511801302 + 0.33229270568387326 + 0.33230196048464372 + 0.33231121558245486 + 0.33232047097732165 + 0.33232972666925886 + 0.33233898265827999 + 0.33234823894439974 + 0.33235749552763161 + 0.3323667524079903 + 0.33237600958549085 + 0.33238526706014726 + 0.33239452483197302 + 0.3324037829009836 + 0.33241304126719251 + 0.33242229993061378 + 0.3324315588912623 + 0.33244081814915216 + 0.33245007770429752 + 0.33245933755671325 + 0.33246859770641357 + 0.33247785815341246 + 0.33248711889772331 + 0.33249637993936254 + 0.33250564127834287 + 0.33251490291467894 + 0.3325241648483851 + 0.33253342707947536 + 0.33254268960796468 + 0.33255195243386793 + 0.33256121555719764 + 0.33257047897796954 + 0.33257974269619706 + 0.33258900671189495 + 0.33259827102507739 + 0.33260753563575934 + 0.33261680054395415 + 0.33262606574967668 + 0.33263533125294192 + 0.33264459705376231 + 0.33265386315215362 + 0.33266312954812999 + 0.33267239624170558 + 0.33268166323289527 + 0.33269093052171245 + 0.3327001981081712 + 0.33270946599228723 + 0.33271873417407394 + 0.33272800265354624 + 0.33273727143071741 + 0.33274654050560332 + 0.33275580987821635 + 0.33276507954857232 + 0.33277434951668544 + 0.33278361978256971 + 0.33279289034624016 + 0.33280216120771011 + 0.33281143236699368 + 0.33282070382410667 + 0.33282997557906235 + 0.33283924763187489 + 0.33284851998255927 + 0.33285779263112958 + 0.33286706557760082 + 0.33287633882198631 + 0.33288561236430109 + 0.33289488620455915 + 0.33290416034277476 + 0.33291343477896274 + 0.33292270951313663 + 0.3329319845453112 + 0.33294125987550149 + 0.33295053550372089 + 0.33295981142998438 + 0.33296908765430594 + 0.33297836417670074 + 0.33298764099718192 + 0.33299691811576382 + 0.33300619553246213 + 0.33301547324729019 + 0.33302475126026304 + 0.33303402957139394 + 0.33304330818069794 + 0.33305258708818997 + 0.33306186629388418 + 0.3330711457977939 + 0.33308042559993417 + 0.33308970570031993 + 0.33309898609896449 + 0.33310826679588373 + 0.33311754779109021 + 0.33312682908459962 + 0.33313611067642523 + 0.3331453925665831 + 0.33315467475508559 + 0.33316395724194769 + 0.33317324002718529 + 0.3331825231108117 + 0.33319180649284019 + 0.33320109017328664 + 0.33321037415216526 + 0.3332196584294902 + 0.33322894300527556 + 0.33323822787953561 + 0.33324751305228534 + 0.33325679852353884 + 0.33326608429331123 + 0.3332753703616157 + 0.33328465672846663 + 0.33329394339387969 + 0.33330323035786907 + 0.33331251762044739 + 0.33332180518163129 + 0.33333109304143399 + 0.33334038119986986 + 0.33334966965695378 + 0.33335895841269997 + 0.33336824746712185 + 0.33337753682023513 + 0.33338682647205409 + 0.33339611642259293 + 0.33340540667186574 + 0.33341469721988676 + 0.33342398806667189 + 0.33343327921223442 + 0.33344257065658778 + 0.33345186239974772 + 0.33346115444172852 + 0.33347044678254512 + 0.33347973942221015 + 0.3334890323607394 + 0.33349832559814702 + 0.33350761913444732 + 0.33351691296965519 + 0.33352620710378417 + 0.33353550153684913 + 0.33354479626886518 + 0.3335540912998457 + 0.33356338662980484 + 0.33357268225875852 + 0.33358197818672003 + 0.33359127441370445 + 0.33360057093972512 + 0.33360986776479795 + 0.33361916488893628 + 0.33362846231215521 + 0.33363776003446804 + 0.33364705805589068 + 0.33365635637643731 + 0.33366565499612133 + 0.33367495391495777 + 0.33368425313296085 + 0.33369355265014561 + 0.33370285246652626 + 0.33371215258211695 + 0.33372145299693207 + 0.33373075371098648 + 0.3337400547242953 + 0.33374935603687111 + 0.33375865764872886 + 0.33376795955988453 + 0.33377726177035066 + 0.33378656428014308 + 0.33379586708927605 + 0.33380517019776301 + 0.33381447360561889 + 0.33382377731285884 + 0.33383308131949702 + 0.33384238562554691 + 0.33385169023102429 + 0.33386099513594264 + 0.33387030034031778 + 0.33387960584416237 + 0.33388891164749135 + 0.33389821775032075 + 0.333907524152663 + 0.33391683085453316 + 0.33392613785594644 + 0.33393544515691698 + 0.333944752757459 + 0.33395406065758676 + 0.33396336885731448 + 0.33397267735665809 + 0.33398198615563013 + 0.33399129525424726 + 0.33400060465252218 + 0.33400991435046995 + 0.33401922434810472 + 0.33402853464544169 + 0.33403784524249408 + 0.33404715613927882 + 0.33405646733580757 + 0.33406577883209626 + 0.33407509062815827 + 0.3340844027240103 + 0.33409371511966507 + 0.33410302781513668 + 0.33411234081044194 + 0.33412165410559264 + 0.33413096770060463 + 0.33414028159549219 + 0.33414959579026959 + 0.33415891028495187 + 0.33416822507955324 + 0.33417754017408807 + 0.33418685556857053 + 0.33419617126301576 + 0.33420548725743798 + 0.3342148035518514 + 0.33422412014627118 + 0.33423343704071157 + 0.33424275423518685 + 0.33425207172971122 + 0.33426138952429979 + 0.33427070761896688 + 0.33428002601372664 + 0.33428934470859512 + 0.33429866370358396 + 0.33430798299871084 + 0.33431730259398756 + 0.33432662248943079 + 0.33433594268505318 + 0.33434526318086982 + 0.3343545839768966 + 0.33436390507314628 + 0.33437322646963458 + 0.33438254816637503 + 0.33439187016338284 + 0.33440119246067213 + 0.33441051505825725 + 0.33441983795615327 + 0.33442916115437449 + 0.33443848465293602 + 0.33444780845185129 + 0.33445713255113457 + 0.33446645695080179 + 0.33447578165086733 + 0.33448510665134451 + 0.33449443195224848 + 0.33450375755359441 + 0.33451308345539571 + 0.33452240965766744 + 0.33453173616042475 + 0.33454106296368114 + 0.33455039006745174 + 0.3345597174717499 + 0.33456904517659258 + 0.33457837318199135 + 0.33458770148796391 + 0.33459703009452219 + 0.33460635900168195 + 0.33461568820945758 + 0.33462501771786335 + 0.3346343475269144 + 0.33464367763662495 + 0.33465300804700859 + 0.33466233875808121 + 0.33467166976985713 + 0.3346810010823506 + 0.33469033269557596 + 0.33469966460954753 + 0.33470899682428112 + 0.33471832933979034 + 0.33472766215608957 + 0.33473699527319462 + 0.33474632869111814 + 0.3347556624098762 + 0.33476499642948215 + 0.33477433074995205 + 0.33478366537129933 + 0.33479300029353837 + 0.33480233551668498 + 0.33481167104075277 + 0.33482100686575689 + 0.33483034299171072 + 0.33483967941862952 + 0.33484901614652834 + 0.33485835317542151 + 0.33486769050532339 + 0.3348770281362482 + 0.33488636606821126 + 0.33489570430122667 + 0.33490504283530892 + 0.33491438167047305 + 0.33492372080673344 + 0.3349330602441043 + 0.334942399982601 + 0.33495174002223682 + 0.33496108036302868 + 0.33497042100498836 + 0.33497976194813189 + 0.3349891031924736 + 0.3349984447380277 + 0.33500778658480945 + 0.33501712873283407 + 0.33502647118211409 + 0.3350358139326664 + 0.33504515698450366 + 0.33505450033764184 + 0.33506384399209449 + 0.33507318794787672 + 0.33508253220500284 + 0.33509187676348812 + 0.33510122162334677 + 0.33511056678459239 + 0.33511991224724091 + 0.33512925801130672 + 0.33513860407680496 + 0.33514795044374918 + 0.33515729711215364 + 0.33516664408203356 + 0.33517599135340409 + 0.33518533892627878 + 0.33519468680067271 + 0.33520403497660117 + 0.3352133834540777 + 0.33522273223311727 + 0.33523208131373522 + 0.33524143069594503 + 0.33525078037976191 + 0.33526013036520019 + 0.33526948065227502 + 0.33527883124099994 + 0.33528818213139089 + 0.33529753332346157 + 0.33530688481722609 + 0.33531623661270149 + 0.33532558870989959 + 0.33533494110883638 + 0.33534429380952618 + 0.33535364681198426 + 0.33536300011622483 + 0.3353723537222616 + 0.33538170763011049 + 0.33539106183978512 + 0.33540041635130136 + 0.3354097711646728 + 0.33541912627991388 + 0.3354284816970397 + 0.33543783741606548 + 0.3354471934370048 + 0.33545654975987366 + 0.33546590638468471 + 0.33547526331145405 + 0.33548462054019601 + 0.33549397807092496 + 0.33550333590365611 + 0.335512694038403 + 0.33552205247518169 + 0.33553141121400565 + 0.3355407702548901 + 0.33555012959785036 + 0.33555948924289986 + 0.33556884919005292 + 0.33557820943932576 + 0.33558756999073253 + 0.33559693084428699 + 0.33560629200000425 + 0.33561565345789945 + 0.33562501521798632 + 0.33563437728028078 + 0.33564373964479638 + 0.33565310231154832 + 0.3356624652805511 + 0.33567182855181893 + 0.33568119212536801 + 0.335690556001211 + 0.33569992017936395 + 0.3357092846598404 + 0.33571864944265639 + 0.33572801452782469 + 0.33573737991536223 + 0.33574674560528245 + 0.33575611159759972 + 0.33576547789232947 + 0.33577484448948586 + 0.33578421138908426 + 0.33579357859113829 + 0.33580294609566302 + 0.33581231390267285 + 0.33582168201218393 + 0.33583105042420974 + 0.335840419138764 + 0.33584978815586347 + 0.33585915747552086 + 0.33586852709775322 + 0.33587789702257315 + 0.33588726724999507 + 0.33589663778003598 + 0.33590600861270847 + 0.33591537974802788 + 0.33592475118600945 + 0.33593412292666675 + 0.33594349497001574 + 0.33595286731607016 + 0.33596223996484431 + 0.3359716129163543 + 0.33598098617061373 + 0.33599035972763786 + 0.33599973358744184 + 0.3360091077500385 + 0.33601848221544467 + 0.33602785698367321 + 0.33603723205474012 + 0.33604660742865988 + 0.33605598310544688 + 0.33606535908511637 + 0.33607473536768184 + 0.33608411195315951 + 0.33609348884156298 + 0.33610286603290745 + 0.33611224352720726 + 0.33612162132447776 + 0.3361309994247334 + 0.33614037782798772 + 0.33614975653425766 + 0.33615913554355592 + 0.33616851485589871 + 0.33617789447129953 + 0.33618727438977375 + 0.33619665461133647 + 0.33620603513600139 + 0.33621541596378374 + 0.33622479709469888 + 0.33623417852876031 + 0.33624356026598329 + 0.33625294230638314 + 0.33626232464997341 + 0.33627170729676942 + 0.33628109024678643 + 0.33629047350003805 + 0.33629985705654036 + 0.33630924091630698 + 0.33631862507935317 + 0.33632800954569336 + 0.33633739431534204 + 0.33634677938831531 + 0.33635616476462676 + 0.33636555044429084 + 0.33637493642732197 + 0.33638432271373708 + 0.33639370930354912 + 0.33640309619677228 + 0.33641248339342367 + 0.33642187089351522 + 0.33643125869706392 + 0.3364406468040832 + 0.33645003521458861 + 0.33645942392859357 + 0.33646881294611514 + 0.33647820226716518 + 0.33648759189176158 + 0.33649698181991627 + 0.33650637205164535 + 0.33651576258696408 + 0.33652515342588613 + 0.33653454456842591 + 0.33654393601460048 + 0.33655332776442171 + 0.33656271981790664 + 0.33657211217506794 + 0.33658150483592275 + 0.33659089780048457 + 0.33660029106876782 + 0.33660968464078717 + 0.33661907851655853 + 0.33662847269609569 + 0.33663786717941385 + 0.33664726196652761 + 0.33665665705745212 + 0.3366660524522011 + 0.33667544815079065 + 0.33668484415323446 + 0.33669424045954777 + 0.33670363706974515 + 0.33671303398384189 + 0.3367224312018523 + 0.33673182872379187 + 0.33674122654967426 + 0.33675062467951467 + 0.33676002311332842 + 0.33676942185112929 + 0.33677882089293326 + 0.33678822023875404 + 0.33679761988860701 + 0.33680701984250744 + 0.33681642010046892 + 0.33682582066250599 + 0.33683522152863488 + 0.33684462269886994 + 0.33685402417322657 + 0.33686342595171753 + 0.33687282803435903 + 0.33688223042116644 + 0.33689163311215331 + 0.33690103610733507 + 0.33691043940672605 + 0.33691984301034178 + 0.33692924691819576 + 0.3369386511303043 + 0.33694805564668173 + 0.33695746046734271 + 0.3369668655923016 + 0.33697627102157296 + 0.33698567675517377 + 0.33699508279311691 + 0.3370044891354177 + 0.33701389578209062 + 0.33702330273315012 + 0.33703270998861251 + 0.33704211754849128 + 0.33705152541280198 + 0.33706093358155897 + 0.33707034205477676 + 0.3370797508324716 + 0.33708915991465621 + 0.33709856930134691 + 0.33710797899255895 + 0.33711738898830518 + 0.3371267992886019 + 0.33713620989346338 + 0.33714562080290522 + 0.33715503201694175 + 0.33716444353558678 + 0.33717385535885724 + 0.33718326748676597 + 0.33719267991932927 + 0.33720209265656076 + 0.33721150569847569 + 0.33722091904508955 + 0.33723033269641689 + 0.33723974665247208 + 0.33724916091326979 + 0.33725857547882526 + 0.33726799034915389 + 0.33727740552426938 + 0.33728682100418794 + 0.33729623678892329 + 0.33730565287848985 + 0.33731506927290389 + 0.3373244859721799 + 0.3373339029763317 + 0.33734332028537534 + 0.33735273789932452 + 0.33736215581819551 + 0.33737157404200208 + 0.33738099257075943 + 0.33739041140448223 + 0.3373998305431849 + 0.33740924998688376 + 0.33741866973559237 + 0.33742808978932542 + 0.33743751014809903 + 0.33744693081192778 + 0.33745635178082539 + 0.33746577305480718 + 0.33747519463388853 + 0.33748461651808404 + 0.33749403870740907 + 0.33750346120187724 + 0.33751288400150492 + 0.33752230710630571 + 0.33753173051629498 + 0.33754115423148739 + 0.33755057825189827 + 0.3375600025775421 + 0.33756942720843353 + 0.33757885214458871 + 0.3375882773860206 + 0.33759770293274532 + 0.33760712878477828 + 0.33761655494213244 + 0.33762598140482403 + 0.33763540817286836 + 0.33764483524627914 + 0.33765426262507187 + 0.33766369030926185 + 0.33767311829886282 + 0.33768254659389024 + 0.33769197519435862 + 0.33770140410028415 + 0.33771083331168067 + 0.33772026282856266 + 0.33772969265094638 + 0.33773912277884466 + 0.3377485532122747 + 0.33775798395125012 + 0.33776741499578561 + 0.33777684634589727 + 0.33778627800159894 + 0.33779570996290503 + 0.33780514222983199 + 0.33781457480239346 + 0.33782400768060489 + 0.33783344086448164 + 0.33784287435403743 + 0.33785230814928774 + 0.3378617422502479 + 0.33787117665693256 + 0.33788061136935627 + 0.33789004638753445 + 0.33789948171148165 + 0.33790891734121253 + 0.33791835327674236 + 0.33792778951808672 + 0.3379372260652585 + 0.33794666291827546 + 0.33795610007714988 + 0.33796553754189873 + 0.33797497531253506 + 0.33798441338907492 + 0.3379938517715339 + 0.33800329045992483 + 0.33801272945426486 + 0.3380221687545677 + 0.33803160836084806 + 0.3380410482731212 + 0.33805048849140268 + 0.33805992901570697 + 0.3380693698460488 + 0.33807881098244263 + 0.33808825242490403 + 0.33809769417344837 + 0.33810713622809024 + 0.33811657858884331 + 0.33812602125572488 + 0.33813546422874774 + 0.33814490750792825 + 0.33815435109328013 + 0.33816379498481958 + 0.33817323918256137 + 0.33818268368651916 + 0.33819212849670921 + 0.33820157361314618 + 0.33821101903584466 + 0.33822046476481926 + 0.3382299108000863 + 0.33823935714165948 + 0.3382488037895543 + 0.33825825074378535 + 0.33826769800436723 + 0.33827714557131627 + 0.33828659344464623 + 0.33829604162437249 + 0.33830549011050987 + 0.33831493890307351 + 0.33832438800207831 + 0.33833383740753953 + 0.33834328711947104 + 0.33835273713788921 + 0.33836218746280772 + 0.33837163809424198 + 0.33838108903220754 + 0.33839054027671983 + 0.33839999182779101 + 0.33840944368543902 + 0.33841889584967844 + 0.33842834832052227 + 0.33843780109798766 + 0.33844725418208838 + 0.33845670757283997 + 0.33846616127025686 + 0.33847561527435382 + 0.33848506958514724 + 0.33849452420265069 + 0.33850397912687985 + 0.33851343435784931 + 0.33852288989557444 + 0.33853234574006913 + 0.33854180189134964 + 0.33855125834943145 + 0.33856071511432762 + 0.33857017218605429 + 0.33857962956462712 + 0.33858908725005976 + 0.33859854524236782 + 0.33860800354156584 + 0.33861746214766936 + 0.33862692106069298 + 0.33863638028065218 + 0.33864583980756163 + 0.33865529964143687 + 0.33866475978229077 + 0.33867422023014138 + 0.33868368098500251 + 0.338693142046888 + 0.33870260341581326 + 0.33871206509179552 + 0.33872152707484693 + 0.33873098936498375 + 0.33874045196222069 + 0.33874991486657324 + 0.33875937807805601 + 0.33876884159668369 + 0.33877830542247178 + 0.33878776955543577 + 0.33879723399558948 + 0.33880669874294839 + 0.3388161637975281 + 0.33882562915934311 + 0.33883509482840901 + 0.33884456080473963 + 0.33885402708835044 + 0.33886349367925783 + 0.33887296057747468 + 0.33888242778301664 + 0.33889189529589997 + 0.3389013631161385 + 0.33891083124374777 + 0.33892029967874243 + 0.33892976842113715 + 0.33893923747094834 + 0.33894870682818973 + 0.33895817649287768 + 0.33896764646502525 + 0.33897711674464875 + 0.3389865873317629 + 0.33899605822638318 + 0.33900552942852424 + 0.33901500093820086 + 0.33902447275542924 + 0.33903394488022254 + 0.33904341731259785 + 0.33905289005256822 + 0.33906236310014998 + 0.33907183645535793 + 0.33908131011820741 + 0.33909078408871318 + 0.33910025836688912 + 0.33910973295275249 + 0.33911920784631616 + 0.33912868304759736 + 0.33913815855660923 + 0.33914763437336798 + 0.33915711049788749 + 0.33916658693018426 + 0.33917606367027286 + 0.33918554071816803 + 0.33919501807388441 + 0.33920449573743838 + 0.33921397370884399 + 0.3392234519881156 + 0.33923293057527071 + 0.3392424094703213 + 0.33925188867328565 + 0.33926136818417568 + 0.33927084800300966 + 0.33928032812979964 + 0.33928980856456209 + 0.33929928930731251 + 0.33930877035806556 + 0.33931825171683605 + 0.33932773338363859 + 0.33933721535848888 + 0.33934669764140307 + 0.33935618023239439 + 0.33936566313147831 + 0.33937514633867033 + 0.3393846298539861 + 0.33939411367743944 + 0.33940359780904672 + 0.33941308224882188 + 0.33942256699678125 + 0.33943205205293792 + 0.33944153741730904 + 0.33945102308990854 + 0.33946050907075209 + 0.33946999535985423 + 0.3394794819572306 + 0.33948896886289592 + 0.33949845607686574 + 0.33950794359915393 + 0.33951743142977686 + 0.33952691956874936 + 0.33953640801608603 + 0.33954589677180258 + 0.33955538583591366 + 0.33956487520843481 + 0.33957436488938075 + 0.3395838548787663 + 0.33959334517660772 + 0.33960283578291905 + 0.33961232669771585 + 0.33962181792101187 + 0.33963130945282533 + 0.33964080129316843 + 0.33965029344205672 + 0.33965978589950657 + 0.33966927866553198 + 0.33967877174014932 + 0.33968826512337247 + 0.33969775881521702 + 0.33970725281569686 + 0.3397167471248293 + 0.33972624174262817 + 0.33973573666910911 + 0.33974523190428685 + 0.33975472744817603 + 0.33976422330079242 + 0.33977371946215151 + 0.33978321593226885 + 0.3397927127111568 + 0.33980220979883413 + 0.33981170719531323 + 0.33982120490061035 + 0.33983070291474043 + 0.33984020123771813 + 0.33984969986956076 + 0.33985919881028043 + 0.33986869805989378 + 0.33987819761841626 + 0.33988769748586184 + 0.33989719766224774 + 0.33990669814758623 + 0.33991619894189462 + 0.33992570004518768 + 0.33993520145748007 + 0.33994470317878667 + 0.33995420520912306 + 0.33996370754850475 + 0.3399732101969466 + 0.33998271315446327 + 0.33999221642107053 + 0.34000171999678386 + 0.3400112238816172 + 0.34002072807558703 + 0.34003023257870729 + 0.34003973739099358 + 0.34004924251246149 + 0.34005874794312574 + 0.34006825368300209 + 0.34007775973210436 + 0.34008726609044904 + 0.34009677275805089 + 0.34010627973492463 + 0.34011578702108602 + 0.34012529461654972 + 0.34013480252133138 + 0.34014431073544582 + 0.34015381925890859 + 0.3401633280917345 + 0.34017283723393921 + 0.34018234668553654 + 0.34019185644654321 + 0.34020136651697369 + 0.34021087689684382 + 0.34022038758616746 + 0.34022989858496105 + 0.34023940989323864 + 0.34024892151101671 + 0.34025843343830908 + 0.34026794567513224 + 0.34027745822150024 + 0.34028697107742861 + 0.34029648424293307 + 0.34030599771802839 + 0.34031551150273021 + 0.34032502559705319 + 0.34033454000101149 + 0.34034405471462237 + 0.34035356973789971 + 0.34036308507085916 + 0.34037260071351644 + 0.34038211666588547 + 0.34039163292798275 + 0.3404011494998222 + 0.34041066638141942 + 0.34042018357279019 + 0.34042970107394921 + 0.34043921888491219 + 0.34044873700569306 + 0.34045825543630914 + 0.3404677741767736 + 0.34047729322710291 + 0.34048681258731101 + 0.34049633225741438 + 0.34050585223742791 + 0.34051537252736636 + 0.34052489312724543 + 0.34053441403708073 + 0.3405439352568862 + 0.34055345678667748 + 0.34056297862647045 + 0.34057250077627965 + 0.34058202323612086 + 0.34059154600600899 + 0.34060106908595861 + 0.34061059247598646 + 0.34062011617610644 + 0.34062964018633501 + 0.34063916450668547 + 0.340648689137175 + 0.34065821407781754 + 0.34066773932862898 + 0.34067726488962397 + 0.3406867907608182 + 0.34069631694222741 + 0.34070584343386551 + 0.3407153702357491 + 0.34072489734789291 + 0.34073442477031102 + 0.3407439525030207 + 0.3407534805460361 + 0.34076300889937183 + 0.34077253756304376 + 0.34078206653706827 + 0.34079159582145863 + 0.34080112541623131 + 0.34081065532140109 + 0.34082018553698373 + 0.34082971606299323 + 0.34083924689944611 + 0.34084877804635721 + 0.34085830950374213 + 0.34086784127161501 + 0.34087737334999307 + 0.3408869057388888 + 0.34089643843831946 + 0.34090597144830076 + 0.3409155047688458 + 0.34092503839997212 + 0.34093457234169361 + 0.34094410659402591 + 0.34095364115698323 + 0.34096317603058274 + 0.34097271121483852 + 0.34098224670976635 + 0.34099178251538098 + 0.34100131863169814 + 0.34101085505873269 + 0.34102039179650029 + 0.3410299288450151 + 0.34103946620429432 + 0.34104900387435205 + 0.34105854185520318 + 0.34106808014686418 + 0.34107761874934917 + 0.34108715766267461 + 0.34109669688685462 + 0.34110623642190485 + 0.34111577626784012 + 0.34112531642467703 + 0.34113485689242962 + 0.34114439767111354 + 0.34115393876074457 + 0.34116348016133757 + 0.34117302187290816 + 0.34118256389547053 + 0.34119210622904117 + 0.34120164887363491 + 0.34121119182926662 + 0.34122073509595208 + 0.34123027867370698 + 0.3412398225625462 + 0.34124936676248463 + 0.34125891127353791 + 0.34126845609572193 + 0.34127800122905139 + 0.34128754667354139 + 0.34129709242920742 + 0.34130663849606446 + 0.34131618487412907 + 0.34132573156341534 + 0.34133527856393814 + 0.34134482587571396 + 0.3413543734987578 + 0.3413639214330853 + 0.34137346967871068 + 0.34138301823565026 + 0.34139256710391824 + 0.34140211628353112 + 0.34141166577450394 + 0.34142121557685151 + 0.3414307656905895 + 0.34144031611573361 + 0.34144986685229811 + 0.34145941790029943 + 0.34146896925975168 + 0.34147852093067138 + 0.34148807291307354 + 0.34149762520697297 + 0.34150717781238538 + 0.34151673072932659 + 0.34152628395781065 + 0.34153583749785416 + 0.34154539134947198 + 0.34155494551267906 + 0.34156449998749111 + 0.34157405477392311 + 0.34158360987199071 + 0.34159316528170891 + 0.34160272100309419 + 0.34161227703616076 + 0.34162183338092433 + 0.34163139003739973 + 0.34164094700560282 + 0.34165050428554844 + 0.34166006187725328 + 0.34166961978073135 + 0.3416791779959984 + 0.3416887365230693 + 0.34169829536196 + 0.34170785451268604 + 0.34171741397526251 + 0.34172697374970423 + 0.34173653383602703 + 0.34174609423424662 + 0.34175565494437715 + 0.34176521596643511 + 0.34177477730043554 + 0.34178433894639421 + 0.34179390090432599 + 0.34180346317424581 + 0.34181302575616951 + 0.34182258865011278 + 0.34183215185609056 + 0.34184171537411873 + 0.34185127920421121 + 0.34186084334638556 + 0.34187040780065509 + 0.34187997256703628 + 0.34188953764554419 + 0.34189910303619458 + 0.34190866873900144 + 0.34191823475398236 + 0.34192780108115139 + 0.3419373677205243 + 0.34194693467211518 + 0.34195650193594163 + 0.34196606951201752 + 0.34197563740035802 + 0.34198520560097956 + 0.34199477411389728 + 0.34200434293912602 + 0.34201391207668064 + 0.34202348152657797 + 0.34203305128883282 + 0.34204262136346109 + 0.3420521917504768 + 0.34206176244989661 + 0.34207133346173463 + 0.3420809047860075 + 0.34209047642273022 + 0.34210004837191849 + 0.34210962063358652 + 0.34211919320775086 + 0.34212876609442744 + 0.34213833929362941 + 0.34214791280537438 + 0.34215748662967632 + 0.34216706076655196 + 0.34217663521601543 + 0.34218620997808258 + 0.3421957850527691 + 0.34220536044008998 + 0.34221493614006104 + 0.34222451215269739 + 0.34223408847801468 + 0.34224366511602788 + 0.34225324206675284 + 0.34226281933020541 + 0.34227239690639966 + 0.34228197479535227 + 0.3422915529970782 + 0.34230113151159242 + 0.34231071033891086 + 0.3423202894790483 + 0.34232986893202155 + 0.34233944869784472 + 0.34234902877653361 + 0.34235860916810401 + 0.34236818987257095 + 0.34237777088994942 + 0.34238735222025601 + 0.34239693386350578 + 0.34240651581971371 + 0.34241609808889473 + 0.34242568067106555 + 0.34243526356624115 + 0.34244484677443571 + 0.34245443029566669 + 0.34246401412994826 + 0.34247359827729623 + 0.34248318273772643 + 0.3424927675112539 + 0.34250235259789363 + 0.34251193799766233 + 0.34252152371057321 + 0.34253110973664375 + 0.34254069607588916 + 0.34255028272832427 + 0.34255986969396496 + 0.3425694569728262 + 0.34257904456492305 + 0.34258863247027305 + 0.34259822068888862 + 0.3426078092207881 + 0.3426173980659849 + 0.34262698722449558 + 0.34263657669633452 + 0.34264616648151819 + 0.3426557565800617 + 0.34266534699198176 + 0.3426749377172908 + 0.34268452875600719 + 0.34269412010814509 + 0.34270371177372044 + 0.34271330375274828 + 0.34272289604524336 + 0.34273248865122358 + 0.34274208157070196 + 0.34275167480369456 + 0.34276126835021803 + 0.34277086221028652 + 0.34278045638391591 + 0.34279005087112202 + 0.34279964567191995 + 0.34280924078632463 + 0.34281883621435277 + 0.34282843195601864 + 0.34283802801133895 + 0.34284762438032856 + 0.3428572210630027 + 0.34286681805937708 + 0.34287641536946684 + 0.3428860129932878 + 0.34289561093085663 + 0.34290520918218675 + 0.34291480774729405 + 0.34292440662619517 + 0.34293400581890515 + 0.34294360532543905 + 0.34295320514581279 + 0.34296280528004131 + 0.34297240572814053 + 0.34298200649012639 + 0.34299160756601299 + 0.34300120895581715 + 0.34301081065955374 + 0.34302041267723887 + 0.34303001500888741 + 0.34303961765451535 + 0.34304922061413767 + 0.34305882388776937 + 0.34306842747542815 + 0.34307803137712728 + 0.34308763559288358 + 0.34309724012271109 + 0.34310684496662663 + 0.3431164501246462 + 0.34312605559678389 + 0.34313566138305557 + 0.34314526748347723 + 0.34315487389806465 + 0.34316448062683214 + 0.3431740876697964 + 0.34318369502697166 + 0.34319330269837461 + 0.3432029106840212 + 0.34321251898392569 + 0.34322212759810383 + 0.34323173652657168 + 0.34324134576934429 + 0.3432509553264374 + 0.34326056519786707 + 0.34327017538364751 + 0.34327978588379543 + 0.34328939669832587 + 0.34329900782725475 + 0.34330861927059642 + 0.34331823102836823 + 0.34332784310058462 + 0.34333745548726058 + 0.34334706818841376 + 0.34335668120405743 + 0.34336629453420842 + 0.34337590817888103 + 0.3433855221380927 + 0.34339513641185698 + 0.34340475100019047 + 0.34341436590310925 + 0.34342398112062827 + 0.34343359665276191 + 0.34344321249952764 + 0.34345282866094057 + 0.34346244513701496 + 0.34347206192776841 + 0.3434816790332143 + 0.3434912964533704 + 0.34350091418824985 + 0.34351053223787043 + 0.34352015060224628 + 0.34352976928139345 + 0.34353938827532782 + 0.34354900758406443 + 0.34355862720761843 + 0.34356824714600659 + 0.34357786739924395 + 0.34358748796734567 + 0.34359710885032768 + 0.34360673004820586 + 0.34361635156099529 + 0.34362597338871126 + 0.3436355955313703 + 0.34364521798898762 + 0.34365484076157832 + 0.34366446384915833 + 0.34367408725174364 + 0.34368371096934841 + 0.34369333500198951 + 0.34370295934968287 + 0.3437125840124427 + 0.34372220899028588 + 0.34373183428322662 + 0.34374145989128174 + 0.34375108581446628 + 0.34376071205279618 + 0.3437703386062867 + 0.34377996547495365 + 0.3437895926588122 + 0.34379922015787751 + 0.3438088479721671 + 0.34381847610169447 + 0.34382810454647728 + 0.34383773330652889 + 0.3438473623818662 + 0.34385699177250512 + 0.34386662147845987 + 0.34387625149974732 + 0.34388588183638252 + 0.34389551248838157 + 0.34390514345575862 + 0.34391477473853144 + 0.34392440633671417 + 0.34393403825032287 + 0.34394367047937263 + 0.34395330302387944 + 0.34396293588386012 + 0.34397256905932805 + 0.34398220255030015 + 0.34399183635679226 + 0.34400147047881879 + 0.34401110491639741 + 0.34402073966954144 + 0.34403037473826775 + 0.3440400101225915 + 0.34404964582252867 + 0.34405928183809525 + 0.34406891816930552 + 0.34407855481617622 + 0.34408819177872346 + 0.34409782905696151 + 0.3441074666509063 + 0.3441171045605747 + 0.34412674278598016 + 0.34413638132714031 + 0.34414602018407031 + 0.34415565935678533 + 0.3441652988453005 + 0.34417493864963272 + 0.34418457876979702 + 0.34419421920580945 + 0.34420385995768515 + 0.34421350102543929 + 0.34422314240908874 + 0.34423278410864855 + 0.34424242612413397 + 0.34425206845556089 + 0.34426171110294546 + 0.34427135406630355 + 0.34428099734564949 + 0.34429064094099932 + 0.34430028485236908 + 0.34430992907977465 + 0.34431957362323212 + 0.34432921848275583 + 0.34433886365836169 + 0.34434850915006665 + 0.34435815495788413 + 0.34436780108183185 + 0.34437744752192495 + 0.3443870942781786 + 0.34439674135060883 + 0.34440638873923074 + 0.34441603644406127 + 0.34442568446511473 + 0.34443533280240712 + 0.34444498145595442 + 0.34445463042577273 + 0.34446427971187632 + 0.34447392931428289 + 0.34448357923300593 + 0.34449322946806238 + 0.34450288001946811 + 0.34451253088723849 + 0.34452218207138852 + 0.34453183357193429 + 0.34454148538889184 + 0.34455113752227634 + 0.34456078997210465 + 0.34457044273839116 + 0.34458009582115184 + 0.34458974922040181 + 0.34459940293615898 + 0.34460905696843674 + 0.34461871131725103 + 0.34462836598261887 + 0.34463802096455454 + 0.34464767626307574 + 0.34465733187819514 + 0.3446669878099306 + 0.34467664405829712 + 0.34468630062331079 + 0.34469595750498772 + 0.34470561470334216 + 0.34471527221839027 + 0.34472493005014881 + 0.34473458819863306 + 0.34474424666385733 + 0.34475390544583945 + 0.34476356454459361 + 0.34477322396013682 + 0.34478288369248256 + 0.34479254374164942 + 0.34480220410765089 + 0.34481186479050391 + 0.34482152579022279 + 0.34483118710682531 + 0.34484084874032578 + 0.34485051069074035 + 0.34486017295808413 + 0.34486983554237322 + 0.3448794984436237 + 0.34488916166185074 + 0.34489882519707121 + 0.34490848904929955 + 0.34491815321855179 + 0.34492781770484399 + 0.34493748250819134 + 0.34494714762861084 + 0.34495681306611592 + 0.34496647882072434 + 0.34497614489245138 + 0.34498581128131223 + 0.34499547798732383 + 0.34500514501049961 + 0.3450148123508574 + 0.34502448000841252 + 0.34503414798318083 + 0.34504381627517694 + 0.34505348488441762 + 0.34506315381091807 + 0.34507282305469528 + 0.34508249261576279 + 0.34509216249413838 + 0.34510183268983641 + 0.34511150320287387 + 0.34512117403326581 + 0.3451308451810276 + 0.34514051664617623 + 0.34515018842872591 + 0.34515986052869374 + 0.34516953294609404 + 0.34517920568094457 + 0.34518887873325882 + 0.34519855210305472 + 0.34520822579034655 + 0.34521789979515044 + 0.34522757411748162 + 0.34523724875735695 + 0.34524692371479188 + 0.34525659898980149 + 0.34526627458240278 + 0.34527595049261006 + 0.3452856267204395 + 0.34529530326590807 + 0.34530498012903016 + 0.34531465730982269 + 0.34532433480829999 + 0.34533401262447916 + 0.34534369075837529 + 0.34535336921000459 + 0.34536304797938233 + 0.34537272706652455 + 0.34538240647144658 + 0.34539208619416523 + 0.34540176623469593 + 0.34541144659305295 + 0.34542112726925417 + 0.34543080826331485 + 0.3454404895752502 + 0.34545017120507637 + 0.34545985315280947 + 0.34546953541846392 + 0.34547921800205755 + 0.34548890090360468 + 0.34549858412312157 + 0.34550826766062337 + 0.34551795151612702 + 0.34552763568964789 + 0.34553732018120131 + 0.34554700499080404 + 0.34555669011847068 + 0.34556637556421721 + 0.34557606132806074 + 0.34558574741001563 + 0.34559543381009888 + 0.34560512052832565 + 0.34561480756471136 + 0.34562449491927211 + 0.34563418259202483 + 0.34564387058298313 + 0.34565355889216481 + 0.34566324751958438 + 0.34567293646525782 + 0.34568262572920228 + 0.34569231531143207 + 0.34570200521196426 + 0.34571169543081331 + 0.34572138596799523 + 0.34573107682352705 + 0.34574076799742409 + 0.34575045948970168 + 0.34576015130037585 + 0.34576984342946204 + 0.34577953587697707 + 0.34578922864293549 + 0.34579892172735427 + 0.34580861513024957 + 0.34581830885163578 + 0.3458280028915291 + 0.34583769724994651 + 0.3458473919269025 + 0.34585708692241396 + 0.34586678223649547 + 0.34587647786916481 + 0.34588617382043557 + 0.3458958700903248 + 0.34590556667884859 + 0.34591526358602226 + 0.34592496081186208 + 0.34593465835638321 + 0.34594435621960185 + 0.34595405440153421 + 0.3459637529021955 + 0.34597345172160199 + 0.34598315085976977 + 0.34599285031671495 + 0.34600255009245218 + 0.34601225018699744 + 0.34602195060036695 + 0.34603165133257779 + 0.34604135238364425 + 0.34605105375358275 + 0.34606075544240933 + 0.3460704574501392 + 0.34608015977678869 + 0.34608986242237388 + 0.34609956538691022 + 0.34610926867041369 + 0.34611897227290062 + 0.34612867619438542 + 0.34613838043488676 + 0.34614808499441674 + 0.34615778987299473 + 0.34616749507063449 + 0.34617720058735302 + 0.34618690642316563 + 0.34619661257808854 + 0.346206319052137 + 0.34621602584532729 + 0.34622573295767556 + 0.34623544038919624 + 0.34624514813990814 + 0.34625485620982399 + 0.34626456459896177 + 0.34627427330733668 + 0.3462839823349641 + 0.34629369168186119 + 0.34630340134804233 + 0.34631311133352544 + 0.34632282163832323 + 0.34633253226245464 + 0.34634224320593476 + 0.34635195446877914 + 0.34636166605100305 + 0.34637137795262357 + 0.34638109017365598 + 0.34639080271411649 + 0.34640051557401969 + 0.34641022875338334 + 0.346419942252223 + 0.34642965607055376 + 0.34643937020839199 + 0.34644908466575391 + 0.34645879944265473 + 0.34646851453911087 + 0.34647822995513755 + 0.34648794569075175 + 0.34649766174596902 + 0.34650737812080462 + 0.34651709481527559 + 0.34652681182939643 + 0.34653652916318428 + 0.34654624681665452 + 0.3465559647898232 + 0.34656568308270674 + 0.34657540169531947 + 0.34658512062767943 + 0.34659483987980116 + 0.34660455945170077 + 0.34661427934339456 + 0.34662399955489792 + 0.34663372008622778 + 0.34664344093739879 + 0.34665316210842717 + 0.34666288359933001 + 0.34667260541012257 + 0.34668232754082029 + 0.34669204999143943 + 0.34670177276199621 + 0.34671149585250594 + 0.34672121926298588 + 0.34673094299344948 + 0.3467406670439156 + 0.34675039141439801 + 0.34676011610491458 + 0.34676984111547982 + 0.34677956644610913 + 0.34678929209681963 + 0.34679901806762758 + 0.34680874435854825 + 0.34681847096959711 + 0.34682819790079128 + 0.34683792515214612 + 0.34684765272367785 + 0.34685738061540194 + 0.34686710882733446 + 0.34687683735949176 + 0.34688656621188935 + 0.34689629538454331 + 0.34690602487747085 + 0.34691575469068553 + 0.3469254848242046 + 0.34693521527804422 + 0.34694494605221982 + 0.34695467714674844 + 0.34696440856164479 + 0.34697414029692575 + 0.34698387235260697 + 0.34699360472870366 + 0.34700333742523304 + 0.34701307044221047 + 0.34702280377965222 + 0.34703253743757362 + 0.34704227141599109 + 0.34705200571492079 + 0.34706174033437898 + 0.3470714752743802 + 0.34708121053494256 + 0.34709094611608049 + 0.34710068201781019 + 0.3471104182401481 + 0.34712015478310954 + 0.34712989164671082 + 0.34713962883096905 + 0.34714936633589794 + 0.34715910416151541 + 0.34716884230783779 + 0.34717858077487879 + 0.34718831956265639 + 0.34719805867118519 + 0.34720779810048219 + 0.34721753785056386 + 0.3472272779214447 + 0.3472370183131418 + 0.34724675902567143 + 0.34725650005904823 + 0.34726624141328843 + 0.34727598308841001 + 0.34728572508442679 + 0.34729546740135581 + 0.34730521003921339 + 0.34731495299801413 + 0.34732469627777512 + 0.3473344398785127 + 0.3473441838002414 + 0.34735392804297927 + 0.34736367260674084 + 0.34737341749154244 + 0.34738316269740044 + 0.34739290822433011 + 0.34740265407234872 + 0.34741240024147085 + 0.34742214673171357 + 0.34743189354309245 + 0.34744164067562455 + 0.34745138812932452 + 0.34746113590420857 + 0.34747088400029308 + 0.34748063241759436 + 0.34749038115612779 + 0.34750013021591064 + 0.34750987959695739 + 0.34751962929928526 + 0.34752937932290884 + 0.34753912966784611 + 0.34754888033411174 + 0.34755863132172199 + 0.34756838263069328 + 0.34757813426104084 + 0.34758788621278208 + 0.34759763848593228 + 0.34760739108050787 + 0.34761714399652427 + 0.34762689723399687 + 0.34763665079294387 + 0.34764640467337971 + 0.34765615887532075 + 0.34766591339878344 + 0.3476756682437831 + 0.34768542341033609 + 0.34769517889845958 + 0.34770493470816738 + 0.34771469083947831 + 0.34772444729240615 + 0.34773420406696814 + 0.34774396116317968 + 0.34775371858105719 + 0.34776347632061683 + 0.34777323438187424 + 0.3477829927648457 + 0.34779275146954758 + 0.34780251049599609 + 0.34781226984420771 + 0.34782202951419616 + 0.34783178950598026 + 0.34784154981957477 + 0.34785131045499595 + 0.34786107141225925 + 0.34787083269138197 + 0.3478805942923795 + 0.34789035621526826 + 0.34790011846006369 + 0.34790988102678205 + 0.34791964391544072 + 0.3479294071260543 + 0.34793917065863983 + 0.34794893451321213 + 0.34795869868978829 + 0.34796846318838381 + 0.34797822800901596 + 0.34798799315169937 + 0.34799775861645121 + 0.34800752440328703 + 0.34801729051222313 + 0.34802705694327585 + 0.34803682369646072 + 0.34804659077179412 + 0.34805635816929237 + 0.34806612588897101 + 0.34807589393084726 + 0.3480856622949357 + 0.34809543098125356 + 0.34810519998981559 + 0.34811496932063984 + 0.34812473897374169 + 0.34813450894913756 + 0.34814427924684227 + 0.34815404986687282 + 0.34816382080924563 + 0.34817359207397636 + 0.34818336366108033 + 0.34819313557057485 + 0.34820290780247715 + 0.3482126803568002 + 0.34822245323356293 + 0.34823222643277996 + 0.3482419999544677 + 0.34825177379864342 + 0.34826154796532166 + 0.34827132245451892 + 0.34828109726625156 + 0.34829087240053591 + 0.34830064785738751 + 0.34831042363682369 + 0.34832019973885986 + 0.34832997616351163 + 0.34833975291079528 + 0.3483495299807281 + 0.34835930737332482 + 0.34836908508860259 + 0.34837886312657707 + 0.34838864148726362 + 0.34839842017068051 + 0.34840819917684235 + 0.34841797850576472 + 0.34842775815746563 + 0.34843753813195977 + 0.34844731842926363 + 0.34845709904939354 + 0.34846687999236675 + 0.3484766612581971 + 0.34848644284690189 + 0.3484962247584974 + 0.34850600699300022 + 0.34851578955042567 + 0.34852557243078952 + 0.34853535563410976 + 0.34854513916040014 + 0.34855492300967894 + 0.34856470718196164 + 0.34857449167726468 + 0.3485842764956027 + 0.34859406163699391 + 0.34860384710145287 + 0.34861363288899705 + 0.34862341899964178 + 0.34863320543340276 + 0.34864299219029804 + 0.34865277927034238 + 0.34866256667355217 + 0.34867235439994387 + 0.34868214244953294 + 0.34869193082233585 + 0.34870171951836992 + 0.34871150853764982 + 0.34872129788019196 + 0.34873108754601362 + 0.34874087753513039 + 0.34875066784755787 + 0.34876045848331233 + 0.34877024944241125 + 0.34878004072487007 + 0.34878983233070354 + 0.34879962425992989 + 0.34880941651256453 + 0.34881920908862396 + 0.34882900198812383 + 0.3488387952110813 + 0.34884858875751118 + 0.34885838262743074 + 0.34886817682085552 + 0.34887797133780291 + 0.34888776617828754 + 0.34889756134232669 + 0.34890735682993512 + 0.34891715264113193 + 0.34892694877593083 + 0.34893674523434837 + 0.34894654201640102 + 0.348956339122106 + 0.34896613655147801 + 0.34897593430453355 + 0.34898573238128999 + 0.34899553078176276 + 0.34900532950596763 + 0.34901512855392181 + 0.34902492792563999 + 0.34903472762113957 + 0.34904452764043786 + 0.34905432798354863 + 0.3490641286504893 + 0.34907392964127626 + 0.3490837309559261 + 0.34909353259445425 + 0.3491033345568772 + 0.34911313684321149 + 0.3491229394534735 + 0.34913274238767805 + 0.34914254564584235 + 0.34915234922798299 + 0.34916215313411636 + 0.34917195736425805 + 0.34918176191842371 + 0.3491915667966306 + 0.34920137199889534 + 0.3492111775252334 + 0.34922098337566121 + 0.34923078955019454 + 0.3492405960488506 + 0.34925040287164505 + 0.34926021001859436 + 0.34927001748971415 + 0.34927982528502172 + 0.34928963340453267 + 0.34929944184826273 + 0.34930925061623003 + 0.3493190597084484 + 0.3493288691249361 + 0.34933867886570874 + 0.34934848893078119 + 0.34935829932017148 + 0.34936811003389617 + 0.34937792107197008 + 0.34938773243441129 + 0.34939754412123297 + 0.34940735613245505 + 0.34941716846809123 + 0.34942698112815918 + 0.34943679411267331 + 0.34944660742165212 + 0.34945642105511115 + 0.34946623501306601 + 0.34947604929553411 + 0.34948586390253106 + 0.3494956788340724 + 0.34950549409017651 + 0.3495153096708572 + 0.34952512557613186 + 0.3495349418060178 + 0.34954475836052901 + 0.34955457523968453 + 0.34956439244349835 + 0.34957420997198774 + 0.34958402782516923 + 0.34959384600305854 + 0.34960366450567204 + 0.34961348333302633 + 0.34962330248513795 + 0.34963312196202245 + 0.34964294176369637 + 0.3496527618901763 + 0.34966258234147868 + 0.34967240311761916 + 0.34968222421861428 + 0.34969204564448053 + 0.34970186739523446 + 0.34971168947089165 + 0.3497215118714696 + 0.34973133459698302 + 0.34974115764744929 + 0.34975098102288493 + 0.34976080472330479 + 0.34977062874872711 + 0.34978045309916744 + 0.34979027777464156 + 0.34980010277516604 + 0.34980992810075728 + 0.34981975375143182 + 0.34982957972720624 + 0.34983940602809621 + 0.34984923265411827 + 0.3498590596052889 + 0.3498688868816246 + 0.34987871448314112 + 0.34988854240985501 + 0.34989837066178275 + 0.34990819923894001 + 0.34991802814134421 + 0.34992785736901189 + 0.34993768692195781 + 0.34994751680019953 + 0.34995734700375342 + 0.34996717753263518 + 0.34997700838686052 + 0.34998683956644772 + 0.34999667107141164 + 0.35000650290176877 + 0.35001633505753654 + 0.35002616753872973 + 0.35003600034536664 + 0.35004583347746127 + 0.35005566693503182 + 0.35006550071809317 + 0.35007533482666359 + 0.35008516926075794 + 0.35009500402039267 + 0.35010483910558443 + 0.3501146745163497 + 0.35012451025270513 + 0.35013434631466639 + 0.35014418270224995 + 0.35015401941547247 + 0.35016385645435044 + 0.35017369381889962 + 0.3501835315091365 + 0.35019336952507774 + 0.35020320786674064 + 0.35021304653413932 + 0.35022288552729203 + 0.35023272484621526 + 0.350242564490923 + 0.35025240446143452 + 0.35026224475776452 + 0.35027208537992971 + 0.35028192632794652 + 0.35029176760183162 + 0.35030160920160158 + 0.35031145112727208 + 0.35032129337885964 + 0.35033113595638099 + 0.35034097885985171 + 0.35035082208928847 + 0.35036066564470941 + 0.35037050952612875 + 0.3503803537335638 + 0.35039019826703027 + 0.35040004312654566 + 0.35040988831212566 + 0.35041973382378599 + 0.35042957966154503 + 0.35043942582541754 + 0.35044927231542011 + 0.35045911913156946 + 0.35046896627388202 + 0.35047881374237361 + 0.35048866153706165 + 0.35049850965796275 + 0.35050835810509173 + 0.3505182068784653 + 0.35052805597810083 + 0.35053790540401486 + 0.35054775515622322 + 0.35055760523474166 + 0.35056745563958758 + 0.35057730637077761 + 0.35058715742832747 + 0.35059700881225375 + 0.35060686052257312 + 0.35061671255930116 + 0.35062656492245553 + 0.35063641761205194 + 0.35064627062810688 + 0.35065612397063617 + 0.35066597763965818 + 0.35067583163518684 + 0.35068568595724059 + 0.35069554060583508 + 0.35070539558098612 + 0.35071525088271116 + 0.35072510651102601 + 0.35073496246594715 + 0.35074481874749136 + 0.35075467535567517 + 0.3507645322905143 + 0.35077438955202539 + 0.35078424714022605 + 0.35079410505513092 + 0.35080396329675778 + 0.35081382186512305 + 0.35082368076024167 + 0.35083353998213201 + 0.35084339953080984 + 0.35085325940629097 + 0.3508631196085919 + 0.35087298013773016 + 0.35088284099372163 + 0.35089270217658192 + 0.35090256368632861 + 0.35091242552297836 + 0.35092228768654687 + 0.35093215017705087 + 0.350942012994506 + 0.35095187613892981 + 0.35096173961033894 + 0.35097160340874928 + 0.35098146753417642 + 0.35099133198663884 + 0.35100119676615144 + 0.35101106187273168 + 0.3510209273063945 + 0.35103079306715823 + 0.35104065915503796 + 0.35105052557005184 + 0.35106039231221403 + 0.3510702593815429 + 0.35108012677805422 + 0.3510899945017647 + 0.3510998625526901 + 0.3511097309308478 + 0.35111959963625294 + 0.35112946866892458 + 0.35113933802887598 + 0.35114920771612562 + 0.35115907773069094 + 0.35116894807258603 + 0.35117881874182832 + 0.35118868973843459 + 0.35119856106242142 + 0.35120843271380547 + 0.35121830469260173 + 0.35122817699882858 + 0.35123804963250094 + 0.35124792259363724 + 0.35125779588225231 + 0.35126766949836291 + 0.35127754344198564 + 0.35128741771313815 + 0.35129729231183532 + 0.35130716723809463 + 0.35131704249193191 + 0.35132691807336386 + 0.35133679398240808 + 0.35134667021907939 + 0.35135654678339534 + 0.35136642367537274 + 0.35137630089502642 + 0.3513861784423748 + 0.3513960563174337 + 0.35140593452021895 + 0.35141581305074809 + 0.351425691909037 + 0.35143557109510315 + 0.35144545060896148 + 0.3514553304506296 + 0.35146521062012409 + 0.35147509111746089 + 0.35148497194265754 + 0.35149485309572898 + 0.35150473457669357 + 0.35151461638556636 + 0.351524498522364 + 0.35153438098710399 + 0.35154426377980313 + 0.35155414690047637 + 0.35156403034914124 + 0.35157391412581351 + 0.35158379823051084 + 0.35159368266324897 + 0.35160356742404558 + 0.35161345251291559 + 0.35162333792987649 + 0.35163322367494426 + 0.35164310974813634 + 0.3516529961494686 + 0.35166288287895781 + 0.35167276993662061 + 0.35168265732247284 + 0.35169254503653297 + 0.35170243307881516 + 0.35171232144933684 + 0.35172221014811578 + 0.35173209917516673 + 0.35174198853050659 + 0.35175187821415382 + 0.35176176822612237 + 0.35177165856643078 + 0.35178154923509403 + 0.35179144023212972 + 0.3518013315575545 + 0.35181122321138436 + 0.35182111519363679 + 0.35183100750432678 + 0.35184090014347191 + 0.35185079311108897 + 0.35186068640719459 + 0.35187058003180383 + 0.35188047398493516 + 0.35189036826660525 + 0.35190026287682913 + 0.35191015781562351 + 0.35192005308300689 + 0.35192994867899335 + 0.35193984460360139 + 0.35194974085684688 + 0.35195963743874564 + 0.35196953434931538 + 0.3519794315885727 + 0.35198932915653353 + 0.35199922705321546 + 0.35200912527863359 + 0.35201902383280542 + 0.35202892271574771 + 0.35203882192747715 + 0.35204872146800886 + 0.35205862133736127 + 0.35206852153555029 + 0.3520784220625926 + 0.352088322918505 + 0.35209822410330333 + 0.35210812561700433 + 0.35211802745962567 + 0.35212792963118322 + 0.35213783213169364 + 0.35214773496117296 + 0.35215763811963874 + 0.35216754160710767 + 0.35217744542359491 + 0.35218734956911879 + 0.35219725404369445 + 0.35220715884734033 + 0.35221706398007147 + 0.35222696944190462 + 0.35223687523285829 + 0.35224678135294663 + 0.35225668780218644 + 0.35226659458059617 + 0.35227650168819163 + 0.35228640912498893 + 0.35229631689100466 + 0.35230622498625658 + 0.35231613341075962 + 0.35232604216453239 + 0.35233595124758976 + 0.35234586065994949 + 0.35235577040162758 + 0.3523656804726415 + 0.35237559087300629 + 0.35238550160274146 + 0.35239541266186025 + 0.35240532405038116 + 0.35241523576832001 + 0.35242514781569462 + 0.35243506019252169 + 0.35244497289881627 + 0.35245488593459595 + 0.35246479929987767 + 0.35247471299467803 + 0.35248462701901312 + 0.35249454137289959 + 0.35250445605635428 + 0.35251437106939482 + 0.35252428641203631 + 0.35253420208429725 + 0.35254411808619263 + 0.35255403441773941 + 0.35256395107895416 + 0.35257386806985391 + 0.35258378539045615 + 0.35259370304077603 + 0.35260362102083115 + 0.35261353933063833 + 0.35262345797021349 + 0.35263337693957353 + 0.35264329623873597 + 0.35265321586771592 + 0.35266313582653114 + 0.35267305611519828 + 0.35268297673373339 + 0.35269289768215417 + 0.35270281896047651 + 0.3527127405687171 + 0.35272266250689294 + 0.35273258477502073 + 0.35274250737311735 + 0.35275243030119863 + 0.35276235355928154 + 0.35277227714738357 + 0.35278220106552088 + 0.35279212531371013 + 0.35280204989196812 + 0.3528119748003109 + 0.35282190003875613 + 0.35283182560732063 + 0.35284175150602026 + 0.35285167773487197 + 0.35286160429389252 + 0.35287153118309794 + 0.35288145840250662 + 0.35289138595213376 + 0.35290131383199713 + 0.35291124204211249 + 0.35292117058249683 + 0.35293109945316697 + 0.35294102865414051 + 0.3529509581854326 + 0.35296088804706011 + 0.35297081823904153 + 0.35298074876139118 + 0.3529906796141275 + 0.35300061079726663 + 0.35301054231082607 + 0.35302047415482024 + 0.35303040632926941 + 0.35304033883418595 + 0.3530502716695903 + 0.35306020483549844 + 0.35307013833192535 + 0.35308007215888892 + 0.35309000631640675 + 0.35309994080449392 + 0.35310987562316815 + 0.35311981077244553 + 0.35312974625234372 + 0.35313968206287955 + 0.35314961820406804 + 0.35315955467592708 + 0.35316949147847437 + 0.35317942861172485 + 0.35318936607569645 + 0.35319930387040593 + 0.35320924199586839 + 0.35321918045210332 + 0.35322911923912503 + 0.35323905835695196 + 0.35324899780559937 + 0.35325893758508581 + 0.35326887769542642 + 0.35327881813663892 + 0.35328875890873845 + 0.35329870001174446 + 0.35330864144567126 + 0.35331858321053733 + 0.35332852530635794 + 0.35333846773315158 + 0.35334841049093352 + 0.35335835357972128 + 0.35336829699953115 + 0.35337824075037982 + 0.35338818483228496 + 0.35339812924526282 + 0.35340807398933005 + 0.35341801906450276 + 0.35342796447079955 + 0.35343791020823551 + 0.35344785627682845 + 0.35345780267659532 + 0.3534677494075511 + 0.3534776964697145 + 0.35348764386310066 + 0.3534975915877282 + 0.35350753964361226 + 0.35351748803077143 + 0.3535274367492201 + 0.35353738579897676 + 0.35354733518005832 + 0.35355728489248089 + 0.3535672349362613 + 0.35357718531141646 + 0.35358713601796327 + 0.35359708705591864 + 0.35360703842529845 + 0.35361699012612152 + 0.35362694215840201 + 0.35363689452215863 + 0.35364684721740741 + 0.35365680024416613 + 0.35366675360244987 + 0.3536767072922774 + 0.35368666131366377 + 0.35369661566662591 + 0.35370657035118247 + 0.35371652536734854 + 0.35372648071514118 + 0.35373643639457725 + 0.35374639240567446 + 0.35375634874844886 + 0.35376630542291743 + 0.35377626242909699 + 0.3537862197670037 + 0.35379617743665526 + 0.35380613543806855 + 0.35381609377125972 + 0.35382605243624565 + 0.353836011433044 + 0.35384597076167013 + 0.35385593042214258 + 0.35386589041447658 + 0.35387585073869088 + 0.35388581139480046 + 0.35389577238282238 + 0.35390573370277445 + 0.35391569535467349 + 0.3539256573385357 + 0.35393561965437781 + 0.35394558230221695 + 0.35395554528206991 + 0.35396550859395365 + 0.35397547223788511 + 0.35398543621388134 + 0.35399540052195821 + 0.35400536516213271 + 0.3540153301344236 + 0.35402529543884509 + 0.35403526107541505 + 0.35404522704415137 + 0.35405519334506902 + 0.35406515997818688 + 0.354075126943521 + 0.35408509424108742 + 0.35409506187090301 + 0.35410502983298653 + 0.3541149981273532 + 0.35412496675401905 + 0.35413493571300364 + 0.35414490500432128 + 0.35415487462799072 + 0.35416484458402808 + 0.35417481487244934 + 0.35418478549327237 + 0.3541947564465141 + 0.35420472773219147 + 0.35421469935032063 + 0.35422467130091845 + 0.35423464358400286 + 0.3542446161995898 + 0.35425458914769636 + 0.35426456242833948 + 0.35427453604153697 + 0.35428450998730399 + 0.35429448426565846 + 0.35430445887661638 + 0.35431443382019573 + 0.35432440909641338 + 0.35433438470528628 + 0.35434436064682961 + 0.35435433692106222 + 0.35436431352800019 + 0.35437429046766034 + 0.35438426774005977 + 0.35439424534521546 + 0.3544042232831443 + 0.35441420155386333 + 0.35442418015738864 + 0.35443415909373799 + 0.35444413836292848 + 0.35445411796497622 + 0.35446409789989813 + 0.35447407816771115 + 0.3544840587684332 + 0.35449403970207949 + 0.35450402096866879 + 0.35451400256821719 + 0.35452398450074163 + 0.35453396676625826 + 0.35454394936478495 + 0.35455393229633775 + 0.35456391556093553 + 0.35457389915859339 + 0.35458388308932748 + 0.35459386735315745 + 0.35460385195009769 + 0.35461383688016695 + 0.35462382214338123 + 0.35463380773975683 + 0.35464379366931231 + 0.3546537799320631 + 0.35466376652802778 + 0.35467375345722163 + 0.3546837407196618 + 0.354693728315366 + 0.35470371624435132 + 0.35471370450663298 + 0.35472369310222973 + 0.35473368203115857 + 0.3547436712934357 + 0.35475366088907723 + 0.35476365081810185 + 0.35477364108052573 + 0.35478363167636501 + 0.35479362260563846 + 0.35480361386836134 + 0.35481360546455154 + 0.3548235973942252 + 0.35483358965740014 + 0.35484358225409263 + 0.35485357518432042 + 0.35486356844809985 + 0.35487356204544779 + 0.35488355597638122 + 0.35489355024091812 + 0.35490354483907377 + 0.35491353977086693 + 0.3549235350363138 + 0.35493353063543032 + 0.35494352656823469 + 0.35495352283474285 + 0.35496351943497367 + 0.35497351636894231 + 0.35498351363666603 + 0.35499351123816253 + 0.35500350917344886 + 0.35501350744254045 + 0.35502350604545591 + 0.35503350498221153 + 0.35504350425282427 + 0.35505350385731121 + 0.35506350379569024 + 0.35507350406797666 + 0.35508350467418837 + 0.35509350561434239 + 0.35510350688845577 + 0.35511350849654472 + 0.35512351043862717 + 0.35513351271471921 + 0.35514351532483884 + 0.3551535182690031 + 0.35516352154722813 + 0.35517352515953093 + 0.35518352910592954 + 0.35519353338644005 + 0.35520353800107868 + 0.35521354294986507 + 0.35522354823281371 + 0.35523355384994248 + 0.35524355980126843 + 0.35525356608680864 + 0.35526357270658016 + 0.35527357966059914 + 0.35528358694888451 + 0.35529359457145054 + 0.35530360252831705 + 0.35531361081949925 + 0.35532361944501423 + 0.35533362840488097 + 0.35534363769911365 + 0.35535364732773123 + 0.35536365729074992 + 0.35537366758818667 + 0.35538367822005956 + 0.35539368918638464 + 0.35540370048717823 + 0.35541371212245915 + 0.3554237240922436 + 0.35543373639654852 + 0.35544374903539033 + 0.35545376200878764 + 0.35546377531675594 + 0.35547378895931303 + 0.35548380293647613 + 0.3554938172482614 + 0.35550383189468676 + 0.35551384687576937 + 0.35552386219152532 + 0.35553387784197182 + 0.3555438938271267 + 0.35555391014700638 + 0.35556392680162857 + 0.35557394379100876 + 0.35558396111516666 + 0.35559397877411669 + 0.35560399676787768 + 0.35561401509646501 + 0.35562403375989748 + 0.35563405275819143 + 0.35564407209136295 + 0.35565409175943091 + 0.3556641117624107 + 0.35567413210032028 + 0.35568415277317755 + 0.35569417378099799 + 0.35570419512379947 + 0.35571421680159832 + 0.3557242388144124 + 0.35573426116225804 + 0.355744283845154 + 0.35575430686311571 + 0.35576433021615939 + 0.35577435390430473 + 0.35578437792756717 + 0.35579440228596454 + 0.35580442697951326 + 0.35581445200823042 + 0.35582447737213302 + 0.35583450307123909 + 0.35584452910556491 + 0.35585455547512757 + 0.35586458217994421 + 0.35587460922003278 + 0.35588463659540864 + 0.3558946643060899 + 0.35590469235209443 + 0.35591472073343761 + 0.35592474945013847 + 0.35593477850221217 + 0.35594480788967675 + 0.35595483761254954 + 0.3559648676708474 + 0.35597489806458671 + 0.35598492879378552 + 0.35599495985846086 + 0.35600499125862994 + 0.35601502299430893 + 0.35602505506551596 + 0.35603508747226803 + 0.35604512021458157 + 0.35605515329247434 + 0.35606518670596282 + 0.35607522045506496 + 0.356085254539797 + 0.35609528896017706 + 0.35610532371622117 + 0.3561153588079467 + 0.35612539423537154 + 0.35613542999851205 + 0.35614546609738529 + 0.35615550253200939 + 0.35616553930240047 + 0.35617557640857583 + 0.35618561385055253 + 0.3561956516283486 + 0.35620568974197941 + 0.35621572819146485 + 0.35622576697681846 + 0.3562358060980601 + 0.35624584555520605 + 0.35625588534827424 + 0.35626592547728014 + 0.35627596594224187 + 0.35628600674317729 + 0.35629604788010194 + 0.35630608935303382 + 0.35631613116199007 + 0.3563261733069879 + 0.35633621578804447 + 0.35634625860517682 + 0.35635630175840144 + 0.35636634524773708 + 0.35637638907319924 + 0.35638643323480684 + 0.35639647773257527 + 0.35640652256652261 + 0.35641656773666519 + 0.35642661324302088 + 0.35643665908560707 + 0.35644670526444078 + 0.35645675177953845 + 0.35646679863091801 + 0.35647684581859668 + 0.35648689334259165 + 0.3564969412029193 + 0.35650698939959657 + 0.35651703793264267 + 0.35652708680207285 + 0.35653713600790532 + 0.35654718555015624 + 0.35655723542884288 + 0.3565672856439841 + 0.35657733619559551 + 0.35658738708369409 + 0.35659743830829799 + 0.35660748986942448 + 0.35661754176708976 + 0.35662759400131111 + 0.35663764657210739 + 0.35664769947949326 + 0.3566577527234876 + 0.35666780630410755 + 0.3566778602213696 + 0.35668791447529086 + 0.35669796906589019 + 0.35670802399318235 + 0.35671807925718618 + 0.35672813485791793 + 0.35673819079539587 + 0.3567482470696362 + 0.35675830368065709 + 0.35676836062847472 + 0.35677841791310733 + 0.35678847553457116 + 0.35679853349288349 + 0.3568085917880624 + 0.35681865042012501 + 0.35682870938908678 + 0.35683876869496772 + 0.35684882833778225 + 0.35685888831754947 + 0.35686894863428559 + 0.35687900928800875 + 0.35688907027873629 + 0.35689913160648346 + 0.35690919327127024 + 0.35691925527311119 + 0.35692931761202534 + 0.35693938028802991 + 0.3569494433011412 + 0.35695950665137638 + 0.35696957033875365 + 0.35697963436328933 + 0.35698969872500158 + 0.3569997634239066 + 0.35700982846002272 + 0.35701989383336608 + 0.35702995954395406 + 0.35704002559180464 + 0.35705009197693521 + 0.35706015869936203 + 0.35707022575910324 + 0.35708029315617523 + 0.35709036089059604 + 0.35710042896238209 + 0.35711049737155065 + 0.35712056611811976 + 0.35713063520210669 + 0.35714070462352782 + 0.35715077438240128 + 0.3571608444787443 + 0.35717091491257325 + 0.35718098568390633 + 0.35719105679275975 + 0.35720112823915173 + 0.35721120002309875 + 0.35722127214461963 + 0.35723134460372907 + 0.35724141740044696 + 0.35725149053478883 + 0.35726156400677278 + 0.35727163781641519 + 0.35728171196373509 + 0.35729178644874793 + 0.3573018612714719 + 0.35731193643192427 + 0.35732201193012136 + 0.35733208776608139 + 0.35734216393982243 + 0.35735224045136005 + 0.3573623173007115 + 0.35737239448789582 + 0.35738247201292933 + 0.35739254987582852 + 0.35740262807661227 + 0.35741270661529628 + 0.35742278549189943 + 0.35743286470643731 + 0.35744294425892897 + 0.35745302414938984 + 0.35746310437783901 + 0.35747318494429203 + 0.35748326584876788 + 0.357493347091283 + 0.35750342867185464 + 0.35751351059050007 + 0.35752359284723662 + 0.35753367544208248 + 0.35754375837505303 + 0.35755384164616744 + 0.357563925255443 + 0.35757400920289517 + 0.35758409348854309 + 0.35759417811240396 + 0.35760426307449417 + 0.35761434837483108 + 0.35762443401343202 + 0.35763451999031504 + 0.35764460630549755 + 0.35765469295899588 + 0.35766477995082829 + 0.35767486728101117 + 0.35768495494956171 + 0.35769504295649912 + 0.3577051313018389 + 0.35771521998559913 + 0.35772530900779642 + 0.35773539836844964 + 0.3577454880675745 + 0.35775557810518904 + 0.35776566848130981 + 0.35777575919595578 + 0.35778585024914344 + 0.35779594164088918 + 0.35780603337121214 + 0.35781612544012775 + 0.35782621784765523 + 0.35783631059380999 + 0.35784640367861126 + 0.35785649710207534 + 0.35786659086421957 + 0.35787668496506131 + 0.35788677940461877 + 0.35789687418290744 + 0.35790696929994736 + 0.35791706475575313 + 0.3579271605503439 + 0.35793725668373699 + 0.35794735315594794 + 0.35795744996699669 + 0.35796754711689882 + 0.35797764460567172 + 0.35798774243333353 + 0.3579978405999017 + 0.35800793910539336 + 0.35801803794982506 + 0.35802813713321507 + 0.35803823665558066 + 0.35804833651693918 + 0.35805843671730797 + 0.35806853725670434 + 0.35807863813514479 + 0.3580887393526484 + 0.35809884090923161 + 0.3581089428049109 + 0.35811904503970626 + 0.3581291476136324 + 0.35813925052670842 + 0.35814935377895069 + 0.35815945737037669 + 0.35816956130100464 + 0.3581796655708509 + 0.35818977017993292 + 0.35819987512826978 + 0.35820998041587615 + 0.35822008604277206 + 0.3582301920089731 + 0.35824029831449755 + 0.35825040495936178 + 0.35826051194358499 + 0.35827061926718279 + 0.35828072693017332 + 0.35829083493257485 + 0.35830094327440315 + 0.35831105195567708 + 0.35832116097641242 + 0.3583312703366282 + 0.35834138003634097 + 0.35835149007556805 + 0.35836160045432686 + 0.35837171117263644 + 0.35838182223051163 + 0.35839193362797145 + 0.35840204536503245 + 0.3584121574417129 + 0.35842226985803011 + 0.35843238261400057 + 0.35844249570964343 + 0.3584526091449744 + 0.3584627229200108 + 0.35847283703477167 + 0.35848295148927367 + 0.35849306628353406 + 0.35850318141757032 + 0.35851329689140055 + 0.35852341270504051 + 0.35853352885850931 + 0.35854364535182343 + 0.35855376218500035 + 0.35856387935805817 + 0.35857399687101438 + 0.35858411472388557 + 0.35859423291668896 + 0.35860435144944386 + 0.35861447032216576 + 0.35862458953487297 + 0.35863470908758294 + 0.35864482898031308 + 0.35865494921308072 + 0.35866506978590329 + 0.35867519069879805 + 0.35868531195178266 + 0.35869543354487521 + 0.3587055554780923 + 0.3587156777514513 + 0.35872580036497048 + 0.35873592331866733 + 0.35874604661255821 + 0.35875617024666068 + 0.35876629422099388 + 0.35877641853557335 + 0.35878654319041753 + 0.35879666818554368 + 0.35880679352096939 + 0.35881691919671188 + 0.35882704521278874 + 0.35883717156921724 + 0.3588472982660158 + 0.35885742530320169 + 0.35886755268079074 + 0.35887768039880197 + 0.35888780845725293 + 0.35889793685616 + 0.35890806559554073 + 0.3589181946754143 + 0.35892832409579728 + 0.35893845385670603 + 0.35894858395815993 + 0.35895871440017457 + 0.35896884518276923 + 0.35897897630596026 + 0.35898910776976528 + 0.35899923957420249 + 0.35900937171928854 + 0.35901950420504164 + 0.35902963703147833 + 0.35903977019861705 + 0.35904990370647427 + 0.35906003755506921 + 0.35907017174441752 + 0.35908030627453752 + 0.35909044114544758 + 0.35910057635716336 + 0.35911071190970406 + 0.35912084780308623 + 0.35913098403732818 + 0.35914112061244646 + 0.35915125752845861 + 0.35916139478538289 + 0.35917153238323668 + 0.35918167032203763 + 0.35919180860180211 + 0.3592019472225485 + 0.35921208618429518 + 0.35922222548705784 + 0.35923236513085571 + 0.35924250511570527 + 0.35925264544162488 + 0.35926278610863122 + 0.35927292711674169 + 0.35928306846597458 + 0.35929321015634741 + 0.35930335218787668 + 0.35931349456058176 + 0.3593236372744783 + 0.35933378032958535 + 0.35934392372591889 + 0.35935406746349796 + 0.35936421154233922 + 0.35937435596246009 + 0.35938450072387984 + 0.35939464582661418 + 0.35940479127068059 + 0.35941493705609734 + 0.35942508318288208 + 0.35943522965105207 + 0.35944537646062402 + 0.3594555236116172 + 0.35946567110404903 + 0.35947581893793523 + 0.359485967113295 + 0.359496115630146 + 0.35950626448850376 + 0.35951641368838849 + 0.35952656322981669 + 0.35953671311280516 + 0.35954686333737296 + 0.35955701390353589 + 0.35956716481131318 + 0.35957731606072069 + 0.35958746765177829 + 0.35959761958450109 + 0.35960777185890824 + 0.35961792447501711 + 0.35962807743284447 + 0.35963823073240964 + 0.35964838437372815 + 0.35965853835681938 + 0.35966869268169904 + 0.35967884734838634 + 0.35968900235689805 + 0.35969915770725153 + 0.35970931339946521 + 0.35971946943355654 + 0.35972962580954226 + 0.35973978252744071 + 0.35974993958726936 + 0.35976009698904576 + 0.35977025473278829 + 0.35978041281851258 + 0.35979057124623809 + 0.35980073001598228 + 0.35981088912776171 + 0.35982104858159386 + 0.35983120837749732 + 0.35984136851549026 + 0.35985152899558859 + 0.35986168981781069 + 0.35987185098217495 + 0.35988201248869706 + 0.3598921743373964 + 0.35990233652829035 + 0.35991249906139572 + 0.35992266193673078 + 0.35993282515431319 + 0.35994298871416036 + 0.35995315261628896 + 0.35996331686071831 + 0.35997348144746594 + 0.35998364637654851 + 0.3599938116479835 + 0.36000397726178845 + 0.36001414321798181 + 0.36002430951658199 + 0.36003447615760481 + 0.36004464314106849 + 0.36005481046699078 + 0.36006497813539007 + 0.36007514614628294 + 0.36008531449968784 + 0.36009548319562057 + 0.36010565223410218 + 0.36011582161514666 + 0.36012599133877432 + 0.36013616140500077 + 0.36014633181384542 + 0.36015650256532583 + 0.36016667365945776 + 0.36017684509626136 + 0.36018701687575244 + 0.36019718899794867 + 0.36020736146286919 + 0.36021753427052994 + 0.36022770742095012 + 0.36023788091414644 + 0.36024805475013733 + 0.36025822892893866 + 0.36026840345057054 + 0.36027857831504884 + 0.36028875352239198 + 0.36029892907261746 + 0.36030910496574287 + 0.36031928120178675 + 0.36032945778076575 + 0.36033963470269736 + 0.36034981196759913 + 0.36035998957549048 + 0.36037016752638718 + 0.3603803458203077 + 0.36039052445727049 + 0.3604007034372913 + 0.36041088276038963 + 0.36042106242658284 + 0.36043124243588781 + 0.36044142278832197 + 0.3604516034839047 + 0.36046178452265193 + 0.3604719659045828 + 0.3604821476297142 + 0.36049232969806366 + 0.36050251210964956 + 0.36051269486448867 + 0.36052287796259946 + 0.36053306140399949 + 0.3605432451887064 + 0.36055342931673862 + 0.36056361378811191 + 0.36057379860284577 + 0.36058398376095679 + 0.36059416926246346 + 0.36060435510738348 + 0.36061454129573334 + 0.36062472782753263 + 0.36063491470279802 + 0.36064510192154697 + 0.3606552894837981 + 0.36066547738956806 + 0.36067566563887532 + 0.3606858542317376 + 0.36069604316817239 + 0.36070623244819727 + 0.36071642207182997 + 0.36072661203908879 + 0.36073680234999156 + 0.36074699300455482 + 0.36075718400279716 + 0.3607673753447353 + 0.36077756703038855 + 0.36078775905977378 + 0.36079795143290938 + 0.36080814414981205 + 0.36081833721049944 + 0.36082853061499098 + 0.36083872436330333 + 0.3608489184554533 + 0.36085911289146028 + 0.36086930767134084 + 0.36087950279511366 + 0.36088969826279549 + 0.3608998940744047 + 0.36091009022995907 + 0.36092028672947696 + 0.3609304835729743 + 0.36094068076047048 + 0.3609508782919823 + 0.36096107616752821 + 0.36097127438712578 + 0.36098147295079275 + 0.36099167185854669 + 0.36100187111040533 + 0.36101207070638619 + 0.36102227064650877 + 0.36103247093078794 + 0.36104267155924408 + 0.36105287253189389 + 0.36106307384875419 + 0.3610732755098443 + 0.36108347751518194 + 0.36109367986478386 + 0.36110388255866854 + 0.36111408559685282 + 0.361124288979356 + 0.36113449270619497 + 0.36114469677738814 + 0.36115490119295152 + 0.36116510595290441 + 0.36117531105726541 + 0.36118551650605041 + 0.36119572229927788 + 0.36120592843696647 + 0.36121613491913285 + 0.36122634174579554 + 0.36123654891697143 + 0.36124675643267906 + 0.36125696429293691 + 0.3612671724977608 + 0.36127738104717028 + 0.3612875899411821 + 0.3612977991798148 + 0.361308008763086 + 0.36131821869101349 + 0.36132842896361483 + 0.36133863958090767 + 0.36134885054291149 + 0.36135906184964139 + 0.36136927350111669 + 0.36137948549735505 + 0.36138969783837421 + 0.36139991052419279 + 0.36141012355482743 + 0.3614203369302959 + 0.36143055065061763 + 0.36144076471580855 + 0.3614509791258872 + 0.36146119388087211 + 0.36147140898078012 + 0.36148162442562892 + 0.36149184021543795 + 0.36150205635022314 + 0.36151227283000298 + 0.36152248965479611 + 0.36153270682461941 + 0.36154292433949048 + 0.36155314219942875 + 0.36156336040444925 + 0.36157357895457332 + 0.36158379784981592 + 0.36159401709019656 + 0.36160423667573199 + 0.3616144566064417 + 0.36162467688234157 + 0.36163489750345029 + 0.36164511846978553 + 0.36165533978136583 + 0.36166556143820888 + 0.36167578344033158 + 0.3616860057877524 + 0.36169622848048916 + 0.3617064515185604 + 0.36171667490198295 + 0.36172689863077451 + 0.36173712270495456 + 0.36174734712453993 + 0.36175757188954738 + 0.3617677969999965 + 0.36177802245590412 + 0.36178824825728872 + 0.36179847440416812 + 0.36180870089656003 + 0.3618189277344821 + 0.36182915491795298 + 0.36183938244698949 + 0.36184961032161028 + 0.36185983854183207 + 0.36187006710767539 + 0.36188029601915522 + 0.36189052527629018 + 0.36190075487909973 + 0.36191098482759992 + 0.36192121512180842 + 0.36193144576174557 + 0.36194167674742656 + 0.36195190807887079 + 0.36196213975609604 + 0.36197237177912001 + 0.36198260414795957 + 0.36199283686263417 + 0.36200306992316172 + 0.36201330332955889 + 0.36202353708184437 + 0.36203377118003582 + 0.36204400562415118 + 0.36205424041420892 + 0.36206447555022586 + 0.36207471103221989 + 0.36208494686021042 + 0.36209518303421429 + 0.36210541955424935 + 0.36211565642033416 + 0.3621258936324856 + 0.3621361311907223 + 0.36214636909506204 + 0.36215660734552341 + 0.36216684594212328 + 0.36217708488488037 + 0.36218732417381144 + 0.36219756380893608 + 0.36220780379027029 + 0.36221804411783354 + 0.36222828479164276 + 0.36223852581171656 + 0.36224876717807364 + 0.36225900889072982 + 0.36226925094970486 + 0.36227949335501552 + 0.36228973610668047 + 0.36229997920471757 + 0.36231022264914442 + 0.36232046643997884 + 0.36233071057723953 + 0.36234095506094427 + 0.36235119989110998 + 0.36236144506775608 + 0.36237169059089946 + 0.36238193646055805 + 0.36239218267675039 + 0.36240242923949428 + 0.36241267614880751 + 0.36242292340470872 + 0.36243317100721484 + 0.36244341895634363 + 0.36245366725211381 + 0.36246391589454313 + 0.36247416488365014 + 0.36248441421945282 + 0.36249466390196794 + 0.36250491393121337 + 0.36251516430720859 + 0.3625254150299706 + 0.36253566609951798 + 0.36254591751586857 + 0.36255616927903928 + 0.36256642138904877 + 0.36257667384591574 + 0.36258692664965714 + 0.36259717980029149 + 0.36260743329783685 + 0.3626176871423108 + 0.36262794133373122 + 0.36263819587211676 + 0.36264845075748525 + 0.36265870598985372 + 0.36266896156924155 + 0.36267921749566573 + 0.36268947376914501 + 0.36269973038969627 + 0.36270998735733906 + 0.36272024467209041 + 0.36273050233396709 + 0.36274076034298969 + 0.36275101869917514 + 0.36276127740254027 + 0.36277153645310478 + 0.36278179585088549 + 0.36279205559590205 + 0.36280231568816962 + 0.36281257612770956 + 0.36282283691453704 + 0.36283309804867164 + 0.36284335953013119 + 0.36285362135893268 + 0.36286388353509552 + 0.36287414605863688 + 0.36288440892957535 + 0.36289467214792875 + 0.36290493571371502 + 0.36291519962695185 + 0.36292546388765712 + 0.3629357284958496 + 0.36294599345154704 + 0.36295625875476828 + 0.36296652440552923 + 0.36297679040384961 + 0.36298705674974724 + 0.36299732344323993 + 0.3630075904843455 + 0.36301785787308277 + 0.36302812560946857 + 0.36303839369352175 + 0.36304866212526093 + 0.36305893090470226 + 0.36306920003186621 + 0.36307946950676795 + 0.36308973932942812 + 0.36310000949986437 + 0.36311028001809376 + 0.36312055088413414 + 0.36313082209800435 + 0.36314109365972203 + 0.36315136556930605 + 0.36316163782677335 + 0.3631719104321427 + 0.36318218338543201 + 0.36319245668665989 + 0.36320273033584333 + 0.36321300433300036 + 0.36322327867815046 + 0.36323355337130969 + 0.3632438284124978 + 0.36325410380173262 + 0.36326437953903196 + 0.36327465562441291 + 0.36328493205789492 + 0.36329520883949612 + 0.36330548596923329 + 0.36331576344712524 + 0.36332604127319085 + 0.36333631944744693 + 0.36334659796991231 + 0.36335687684060403 + 0.36336715605954162 + 0.36337743562674218 + 0.36338771554222443 + 0.36339799580600629 + 0.36340827641810469 + 0.36341855737854023 + 0.36342883868732812 + 0.36343912034448889 + 0.36344940235003953 + 0.36345968470399792 + 0.36346996740638199 + 0.3634802504572105 + 0.36349053385650221 + 0.36350081760427322 + 0.36351110170054324 + 0.36352138614533019 + 0.36353167093865096 + 0.36354195608052531 + 0.36355224157097021 + 0.36356252741000444 + 0.36357281359764598 + 0.36358310013391265 + 0.36359338701882327 + 0.36360367425239393 + 0.36361396183464517 + 0.3636242497655951 + 0.36363453804525953 + 0.36364482667365833 + 0.36365511565080938 + 0.36366540497673067 + 0.3636756946514399 + 0.36368598467495605 + 0.36369627504729696 + 0.36370656576848054 + 0.36371685683852473 + 0.36372714825744829 + 0.3637374400252692 + 0.36374773214200445 + 0.36375802460767465 + 0.36376831742229493 + 0.36377861058588601 + 0.36378890409846398 + 0.36379919796004856 + 0.36380949217065678 + 0.36381978673030746 + 0.36383008163901942 + 0.3638403768968087 + 0.36385067250369513 + 0.36386096845969662 + 0.36387126476483106 + 0.36388156141911732 + 0.36389185842257232 + 0.36390215577521506 + 0.36391245347706241 + 0.36392275152813508 + 0.36393304992844838 + 0.36394334867802275 + 0.36395364777687539 + 0.36396394722502412 + 0.36397424702248699 + 0.36398454716928369 + 0.36399484766543116 + 0.36400514851094756 + 0.36401544970585148 + 0.36402575125016012 + 0.3640360531438932 + 0.36404635538706764 + 0.36405665797970255 + 0.36406696092181567 + 0.3640772642134249 + 0.36408756785454843 + 0.36409787184520487 + 0.36410817618541313 + 0.3641184808751895 + 0.36412878591455361 + 0.36413909130352246 + 0.36414939704211591 + 0.36415970313035101 + 0.36417000956824652 + 0.3641803163558196 + 0.36419062349309 + 0.36420093098007383 + 0.36421123881679091 + 0.36422154700325998 + 0.36423185553949733 + 0.36424216442552271 + 0.36425247366135322 + 0.36426278324700845 + 0.36427309318250473 + 0.36428340346786181 + 0.36429371410309758 + 0.36430402508822918 + 0.36431433642327726 + 0.36432464810825715 + 0.36433496014318856 + 0.36434527252809035 + 0.36435558526297956 + 0.36436589834787431 + 0.36437621178279428 + 0.36438652556775569 + 0.36439683970277831 + 0.36440715418787922 + 0.36441746902307809 + 0.36442778420839217 + 0.36443809974383939 + 0.36444841562943858 + 0.36445873186520777 + 0.36446904845116596 + 0.36447936538733089 + 0.36448968267371989 + 0.36450000031035162 + 0.36451031829724434 + 0.36452063663441764 + 0.36453095532188873 + 0.36454127435967459 + 0.36455159374779511 + 0.36456191348626826 + 0.36457223357511298 + 0.36458255401434536 + 0.36459287480398622 + 0.36460319594405166 + 0.36461351743456066 + 0.3646238392755321 + 0.36463416146698396 + 0.36464448400893429 + 0.36465480690140106 + 0.36466513014440233 + 0.36467545373795784 + 0.36468577768208471 + 0.36469610197680097 + 0.3647064266221256 + 0.36471675161807743 + 0.36472707696467266 + 0.36473740266193122 + 0.36474772870987099 + 0.36475805510851006 + 0.36476838185786731 + 0.36477870895795989 + 0.36478903640880767 + 0.3647993642104268 + 0.36480969236283706 + 0.36482002086605747 + 0.3648303497201042 + 0.36484067892499716 + 0.36485100848075425 + 0.3648613383873936 + 0.3648716686449332 + 0.36488199925339204 + 0.36489233021278716 + 0.36490266152313833 + 0.36491299318446291 + 0.36492332519677972 + 0.36493365756010759 + 0.36494399027446295 + 0.36495432333986638 + 0.36496465675633416 + 0.36497499052388532 + 0.36498532464253869 + 0.36499565911231235 + 0.36500599393322436 + 0.36501632910529369 + 0.36502666462853745 + 0.36503700050297455 + 0.36504733672862399 + 0.36505767330550287 + 0.36506801023363028 + 0.36507834751302404 + 0.3650886851437033 + 0.36509902312568604 + 0.36510936145898942 + 0.36511970014363321 + 0.36513003917963566 + 0.3651403785670147 + 0.36515071830578838 + 0.36516105839597479 + 0.36517139883759381 + 0.36518173963066258 + 0.36519208077519916 + 0.36520242227122246 + 0.3652127641187507 + 0.36522310631780269 + 0.36523344886839565 + 0.3652437917705495 + 0.36525413502428045 + 0.36526447862960926 + 0.36527482258655225 + 0.36528516689512841 + 0.36529551155535656 + 0.36530585656725495 + 0.36531620193084169 + 0.36532654764613465 + 0.36533689371315303 + 0.36534724013191561 + 0.3653575869024388 + 0.36536793402474332 + 0.36537828149884549 + 0.36538862932476424 + 0.36539897750251954 + 0.36540932603212678 + 0.36541967491360755 + 0.36543002414697817 + 0.36544037373225768 + 0.36545072366946413 + 0.36546107395861566 + 0.36547142459973109 + 0.36548177559282874 + 0.36549212693792749 + 0.36550247863504459 + 0.36551283068419987 + 0.36552318308540971 + 0.3655335358386948 + 0.36554388894407153 + 0.3655542424015597 + 0.36556459621117665 + 0.3655749503729413 + 0.36558530488687269 + 0.36559565975298797 + 0.36560601497130618 + 0.36561637054184548 + 0.3656267264646248 + 0.36563708273966133 + 0.36564743936697514 + 0.36565779634658324 + 0.36566815367850386 + 0.36567851136275692 + 0.36568886939936046 + 0.36569922778833175 + 0.36570958652968982 + 0.36571994562345278 + 0.36573030506963961 + 0.36574066486826934 + 0.3657510250193583 + 0.36576138552292736 + 0.36577174637899285 + 0.36578210758757368 + 0.36579246914868985 + 0.36580283106235767 + 0.36581319332859624 + 0.36582355594742538 + 0.36583391891886152 + 0.36584428224292359 + 0.36585464591963074 + 0.36586500994900101 + 0.36587537433105255 + 0.36588573906580441 + 0.36589610415327389 + 0.36590646959348083 + 0.36591683538644243 + 0.36592720153217884 + 0.36593756803070615 + 0.36594793488204452 + 0.36595830208621194 + 0.36596866964322661 + 0.36597903755310757 + 0.36598940581587208 + 0.36599977443154008 + 0.36601014340012883 + 0.36602051272165825 + 0.36603088239614473 + 0.3660412524236073 + 0.36605162280406589 + 0.36606199353753777 + 0.36607236462404202 + 0.36608273606359587 + 0.36609310785621846 + 0.36610348000192872 + 0.36611385250074485 + 0.36612422535268602 + 0.36613459855776836 + 0.36614497211601299 + 0.36615534602743705 + 0.36616572029205868 + 0.36617609490989694 + 0.36618646988097103 + 0.3661968452052981 + 0.36620722088289814 + 0.36621759691378752 + 0.36622797329798618 + 0.36623835003551153 + 0.36624872712638423 + 0.36625910457062083 + 0.36626948236823947 + 0.36627986051926009 + 0.36629023902370089 + 0.36630061788157914 + 0.36631099709291576 + 0.36632137665772613 + 0.36633175657603123 + 0.36634213684784828 + 0.36635251747319647 + 0.36636289845209391 + 0.36637327978455875 + 0.36638366147061008 + 0.36639404351026622 + 0.3664044259035461 + 0.36641480865046711 + 0.36642519175104926 + 0.36643557520530884 + 0.36644595901326682 + 0.36645634317494052 + 0.36646672769034894 + 0.36647711255950943 + 0.366487497782442 + 0.366497883359164 + 0.36650826928969532 + 0.36651865557405339 + 0.36652904221225535 + 0.36653942920432225 + 0.36654981655027224 + 0.36656020425012259 + 0.36657059230389338 + 0.366580980711601 + 0.36659136947326543 + 0.36660175858890581 + 0.36661214805853942 + 0.36662253788218546 + 0.36663292805986203 + 0.36664331859158827 + 0.36665370947738157 + 0.36666410071726185 + 0.36667449231124649 + 0.36668488425935464 + 0.3666952765616045 + 0.36670566921801601 + 0.3667160622286057 + 0.36672645559339345 + 0.36673684931239769 + 0.36674724338563564 + 0.36675763781312731 + 0.36676803259489099 + 0.36677842773094482 + 0.36678882322130796 + 0.36679921906599872 + 0.36680961526503436 + 0.36682001181843582 + 0.36683040872621953 + 0.36684080598840557 + 0.36685120360501217 + 0.36686160157605746 + 0.36687199990155989 + 0.36688239858153843 + 0.36689279761601135 + 0.36690319700499785 + 0.36691359674851615 + 0.36692399684658444 + 0.36693439729922195 + 0.36694479810644687 + 0.36695519926827747 + 0.36696560078473295 + 0.36697600265583141 + 0.36698640488159218 + 0.3669968074620325 + 0.36700721039717249 + 0.3670176136870294 + 0.36702801733162344 + 0.36703842133097186 + 0.36704882568509295 + 0.36705923039400584 + 0.36706963545773069 + 0.36708004087628382 + 0.3670904466496836 + 0.36710085277795096 + 0.36711125926110322 + 0.36712166609915869 + 0.3671320732921366 + 0.36714248084005502 + 0.3671528887429325 + 0.36716329700078804 + 0.36717370561364082 + 0.36718411458150818 + 0.36719452390440938 + 0.36720493358236261 + 0.36721534361538721 + 0.36722575400350127 + 0.36723616474672405 + 0.36724657584507381 + 0.36725698729856882 + 0.36726739910722739 + 0.36727781127106873 + 0.367288223790112 + 0.3672986366643754 + 0.36730904989387647 + 0.3673194634786352 + 0.36732987741867079 + 0.36734029171399973 + 0.36735070636464207 + 0.36736112137061716 + 0.36737153673194123 + 0.36738195244863553 + 0.36739236852071649 + 0.367402784948205 + 0.36741320173111763 + 0.36742361886947444 + 0.36743403636329292 + 0.36744445421259309 + 0.36745487241739233 + 0.36746529097770997 + 0.36747570989356415 + 0.36748612916497514 + 0.36749654879195931 + 0.36750696877453687 + 0.36751738911272508 + 0.3675278098065442 + 0.36753823085601156 + 0.36754865226114647 + 0.36755907402196802 + 0.36756949613849454 + 0.3675799186107444 + 0.36759034143873592 + 0.3676007646224892 + 0.36761118816202171 + 0.36762161205735161 + 0.36763203630849922 + 0.36764246091548264 + 0.36765288587831951 + 0.36766331119702977 + 0.36767373687163102 + 0.36768416290214329 + 0.36769458928858401 + 0.36770501603097239 + 0.36771544312932675 + 0.36772587058366735 + 0.36773629839401056 + 0.36774672656037666 + 0.36775715508278384 + 0.36776758396125048 + 0.36777801319579589 + 0.3677884427864383 + 0.367798872733197 + 0.3678093030360895 + 0.36781973369513582 + 0.36783016471035351 + 0.36784059608176251 + 0.36785102780938056 + 0.36786145989322755 + 0.36787189233332018 + 0.36788232512967856 + 0.36789275828232187 + 0.36790319179126679 + 0.36791362565653518 + 0.3679240598781427 + 0.36793449445610943 + 0.36794492939045387 + 0.36795536468119522 + 0.3679658003283518 + 0.36797623633194193 + 0.36798667269198504 + 0.36799710940849933 + 0.36800754648150413 + 0.36801798391101775 + 0.36802842169705857 + 0.3680388598396459 + 0.36804929833879896 + 0.36805973719453522 + 0.36807017640687306 + 0.36808061597583352 + 0.36809105590143421 + 0.36810149618369326 + 0.36811193682262916 + 0.36812237781826213 + 0.36813281917060958 + 0.36814326087969174 + 0.36815370294552513 + 0.36816414536813091 + 0.36817458814752552 + 0.36818503128373009 + 0.36819547477676129 + 0.36820591862663832 + 0.36821636283338138 + 0.36822680739700803 + 0.36823725231753646 + 0.36824769759498704 + 0.36825814322937811 + 0.36826858922072708 + 0.36827903556905334 + 0.36828948227437702 + 0.36829992933671474 + 0.36831037675608763 + 0.36832082453251225 + 0.36833127266600868 + 0.36834172115659464 + 0.3683521700042901 + 0.36836261920911362 + 0.36837306877108356 + 0.36838351869021829 + 0.36839396896653803 + 0.36840441960006032 + 0.36841487059080441 + 0.36842532193878869 + 0.36843577364403157 + 0.36844622570655339 + 0.36845667812637239 + 0.36846713090350613 + 0.36847758403797481 + 0.36848803752979692 + 0.36849849137898988 + 0.3685089455855749 + 0.36851940014956941 + 0.36852985507099273 + 0.3685403103498624 + 0.36855076598619774 + 0.36856122198001889 + 0.36857167833134358 + 0.36858213504019005 + 0.36859259210657863 + 0.36860304953052669 + 0.36861350731205372 + 0.36862396545117804 + 0.36863442394791995 + 0.36864488280229601 + 0.36865534201432737 + 0.36866580158403167 + 0.36867626151142718 + 0.36868672179653328 + 0.36869718243936939 + 0.36870764343995294 + 0.36871810479830419 + 0.36872856651444069 + 0.36873902858838276 + 0.3687494910201487 + 0.36875995380975607 + 0.36877041695722523 + 0.36878088046257451 + 0.36879134432582333 + 0.36880180854698918 + 0.36881227312609144 + 0.36882273806315025 + 0.36883320335818243 + 0.36884366901120819 + 0.36885413502224584 + 0.368864601391314 + 0.3688750681184319 + 0.36888553520361905 + 0.36889600264689287 + 0.36890647044827363 + 0.3689169386077798 + 0.36892740712542893 + 0.36893787600124139 + 0.36894834523523634 + 0.36895881482743059 + 0.36896928477784441 + 0.36897975508649705 + 0.36899022575340712 + 0.3690006967785921 + 0.36901116816207308 + 0.36902163990386783 + 0.36903211200399466 + 0.36904258446247296 + 0.36905305727932219 + 0.36906353045456075 + 0.36907400398820711 + 0.36908447788028065 + 0.36909495213079996 + 0.36910542673978425 + 0.369115901707253 + 0.36912637703322282 + 0.3691368527177149 + 0.36914732876074696 + 0.36915780516233909 + 0.369168281922509 + 0.36917875904127506 + 0.36918923651865776 + 0.36919971435467536 + 0.36921019254934651 + 0.36922067110269052 + 0.36923115001472595 + 0.36924162928547211 + 0.36925210891494753 + 0.36926258890317065 + 0.36927306925016101 + 0.36928354995593787 + 0.36929403102051889 + 0.36930451244392526 + 0.36931499422617364 + 0.36932547636728352 + 0.36933595886727422 + 0.36934644172616421 + 0.36935692494397221 + 0.3693674085207182 + 0.369377892456421 + 0.36938837675109804 + 0.36939886140476963 + 0.36940934641745438 + 0.36941983178917159 + 0.36943031751993893 + 0.36944080360977677 + 0.36945129005870353 + 0.36946177686673681 + 0.36947226403389793 + 0.36948275156020444 + 0.36949323944567575 + 0.36950372769033046 + 0.36951421629418701 + 0.36952470525726572 + 0.36953519457958339 + 0.36954568426116113 + 0.36955617430201765 + 0.36956666470217125 + 0.36957715546164072 + 0.36958764658044435 + 0.36959813805860342 + 0.36960862989613474 + 0.36961912209305775 + 0.3696296146493927 + 0.36964010756515636 + 0.3696506008403691 + 0.3696610944750503 + 0.36967158846921766 + 0.36968208282289061 + 0.36969257753608853 + 0.36970307260882912 + 0.36971356804113364 + 0.36972406383301881 + 0.36973455998450577 + 0.3697450564956114 + 0.36975555336635518 + 0.36976605059675649 + 0.36977654818683564 + 0.3697870461366094 + 0.3697975444460973 + 0.36980804311531867 + 0.36981854214429222 + 0.36982904153303725 + 0.36983954128157337 + 0.36985004138991806 + 0.36986054185809181 + 0.36987104268611221 + 0.3698815438739988 + 0.36989204542177095 + 0.36990254732944827 + 0.36991304959704824 + 0.36992355222459045 + 0.36993405521209433 + 0.36994455855957836 + 0.36995506226706132 + 0.3699655663345634 + 0.36997607076210232 + 0.3699865755496976 + 0.36999708069736775 + 0.37000758620513319 + 0.37001809207301156 + 0.3700285983010233 + 0.37003910488918507 + 0.37004961183751822 + 0.37006011914604053 + 0.37007062681477126 + 0.37008113484372923 + 0.3700916432329347 + 0.37010215198240526 + 0.37011266109215973 + 0.37012317056221827 + 0.37013368039259964 + 0.37014419058332326 + 0.37015470113440679 + 0.37016521204587072 + 0.37017572331773257 + 0.37018623495001202 + 0.37019674694272936 + 0.37020725929590231 + 0.37021777200955036 + 0.37022828508369215 + 0.37023879851834718 + 0.37024931231353397 + 0.37025982646927202 + 0.37027034098558004 + 0.3702808558624785 + 0.37029137109998395 + 0.37030188669811698 + 0.37031240265689702 + 0.37032291897634179 + 0.37033343565647087 + 0.37034395269730369 + 0.37035447009885986 + 0.37036498786115785 + 0.37037550598421554 + 0.37038602446805319 + 0.3703965433126904 + 0.37040706251814581 + 0.37041758208443709 + 0.37042810201158555 + 0.37043862229960894 + 0.37044914294852682 + 0.37045966395835778 + 0.37047018532912129 + 0.37048070706083513 + 0.37049122915352156 + 0.37050175160719651 + 0.37051227442188028 + 0.3705227975975916 + 0.37053332113435 + 0.37054384503217508 + 0.37055436929108443 + 0.37056489391109859 + 0.37057541889223616 + 0.3705859442345158 + 0.37059646993795703 + 0.37060699600257846 + 0.37061752242839968 + 0.37062804921544018 + 0.37063857636371772 + 0.37064910387325284 + 0.37065963174406402 + 0.37067015997617098 + 0.37068068856959135 + 0.37069121752434558 + 0.37070174684045243 + 0.37071227651793043 + 0.37072280655679912 + 0.37073333695707816 + 0.37074386771878615 + 0.37075439884194267 + 0.37076493032656543 + 0.37077546217267482 + 0.3707859943802907 + 0.37079652694943049 + 0.37080705988011392 + 0.37081759317236052 + 0.37082812682618888 + 0.37083866084161782 + 0.37084919521866772 + 0.37085972995735633 + 0.37087026505770504 + 0.37088080051972988 + 0.37089133634345206 + 0.37090187252889051 + 0.3709124090760636 + 0.37092294598499109 + 0.37093348325569248 + 0.37094402088818568 + 0.37095455888249101 + 0.37096509723862631 + 0.37097563595661204 + 0.3709861750364678 + 0.37099671447821048 + 0.37100725428186149 + 0.37101779444743949 + 0.37102833497496218 + 0.37103887586445017 + 0.37104941711592215 + 0.37105995872939845 + 0.37107050070489617 + 0.37108104304243567 + 0.37109158574203566 + 0.37110212880371574 + 0.37111267222749467 + 0.37112321601339193 + 0.37113376016142718 + 0.37114430467161824 + 0.37115484954398648 + 0.37116539477854882 + 0.37117594037532481 + 0.37118648633433504 + 0.37119703265559717 + 0.37120757933913101 + 0.3712181263849551 + 0.37122867379309088 + 0.37123922156355532 + 0.37124976969636708 + 0.37126031819154759 + 0.37127086704911466 + 0.37128141626908878 + 0.37129196585148688 + 0.3713025157963295 + 0.37131306610363618 + 0.37132361677342579 + 0.37133416780571693 + 0.37134471920052914 + 0.37135527095788229 + 0.37136582307779481 + 0.37137637556028741 + 0.37138692840537613 + 0.37139748161308322 + 0.37140803518342652 + 0.37141858911642572 + 0.37142914341210026 + 0.37143969807046823 + 0.37145025309154994 + 0.37146080847536522 + 0.37147136422193083 + 0.37148192033126742 + 0.37149247680339548 + 0.37150303363833281 + 0.37151359083609825 + 0.37152414839671138 + 0.3715347063201927 + 0.37154526460656012 + 0.37155582325583236 + 0.3715663822680309 + 0.37157694164317256 + 0.371587501381278 + 0.37159806148236502 + 0.37160862194645511 + 0.37161918277356615 + 0.37162974396371767 + 0.37164030551692862 + 0.3716508674332184 + 0.37166142971260591 + 0.37167199235511084 + 0.37168255536075273 + 0.37169311872955046 + 0.37170368246152363 + 0.37171424655669011 + 0.37172481101507132 + 0.3717353758366852 + 0.3717459410215504 + 0.37175650656968851 + 0.37176707248111646 + 0.37177763875585385 + 0.37178820539392138 + 0.37179877239533676 + 0.37180933976011971 + 0.37181990748829097 + 0.37183047557986731 + 0.37184104403487023 + 0.37185161285331675 + 0.37186218203522836 + 0.37187275158062294 + 0.37188332148952108 + 0.37189389176194054 + 0.37190446239790115 + 0.37191503339742249 + 0.37192560476052433 + 0.37193617648722455 + 0.37194674857754367 + 0.37195732103150042 + 0.37196789384911372 + 0.37197846703040421 + 0.37198904057538956 + 0.37199961448408964 + 0.37201018875652492 + 0.37202076339271251 + 0.37203133839267394 + 0.37204191375642781 + 0.37205248948399217 + 0.37206306557538754 + 0.37207364203063376 + 0.37208421884974852 + 0.37209479603275258 + 0.37210537357966378 + 0.37211595149050281 + 0.37212652976528832 + 0.37213710840404018 + 0.37214768740677706 + 0.37215826677351876 + 0.37216884650428406 + 0.37217942659909353 + 0.37219000705796423 + 0.37220058788091775 + 0.37221116906797275 + 0.3722217506191472 + 0.3722323325344627 + 0.37224291481393706 + 0.37225349745759007 + 0.37226408046544052 + 0.37227466383750812 + 0.37228524757381354 + 0.37229583167437375 + 0.37230641613921034 + 0.37231700096834019 + 0.37232758616178507 + 0.37233817171956274 + 0.37234875764169378 + 0.37235934392819631 + 0.37236993057909079 + 0.37238051759439522 + 0.37239110497413025 + 0.3724016927183138 + 0.37241228082696737 + 0.37242286930010898 + 0.37243345813775747 + 0.3724440473399333 + 0.37245463690665553 + 0.37246522683794298 + 0.37247581713381522 + 0.3724864077942931 + 0.37249699881939352 + 0.3725075902091381 + 0.3725181819635448 + 0.3725287740826333 + 0.3725393665664225 + 0.37254995941493302 + 0.37256055262818288 + 0.37257114620619264 + 0.37258174014898127 + 0.37259233445656842 + 0.37260292912897214 + 0.37261352416621391 + 0.37262411956831171 + 0.37263471533528442 + 0.37264531146715268 + 0.37265590796393633 + 0.37266650482565322 + 0.37267710205232324 + 0.37268769964396598 + 0.37269829760060136 + 0.37270889592224826 + 0.37271949460892545 + 0.37273009366065363 + 0.37274069307745078 + 0.37275129285933761 + 0.37276189300633306 + 0.37277249351845582 + 0.37278309439572666 + 0.3727936956381645 + 0.37280429724578817 + 0.37281489921861743 + 0.37282550155667127 + 0.37283610425997121 + 0.37284670732853337 + 0.37285731076237938 + 0.37286791456152912 + 0.37287851872599953 + 0.37288912325581225 + 0.37289972815098621 + 0.37291033341154034 + 0.37292093903749524 + 0.37293154502886799 + 0.37294215138568027 + 0.37295275810795098 + 0.37296336519569884 + 0.37297397264894483 + 0.37298458046770583 + 0.37299518865200448 + 0.37300579720185773 + 0.37301640611728554 + 0.37302701539830857 + 0.3730376250449447 + 0.37304823505721385 + 0.37305884543513684 + 0.37306945617873055 + 0.37308006728801768 + 0.37309067876301427 + 0.37310129060374114 + 0.37311190281021905 + 0.37312251538246682 + 0.37313312832050249 + 0.37314374162434671 + 0.37315435529401947 + 0.37316496932953869 + 0.37317558373092508 + 0.37318619849819756 + 0.37319681363137597 + 0.37320742913048016 + 0.37321804499552813 + 0.37322866122654058 + 0.3732392778235365 + 0.37324989478653653 + 0.37326051211555794 + 0.37327112981062222 + 0.37328174787174745 + 0.3732923662989544 + 0.37330298509226201 + 0.37331360425169002 + 0.37332422377725655 + 0.37333484366898234 + 0.37334546392688722 + 0.37335608455099012 + 0.37336670554130991 + 0.37337732689786657 + 0.37338794862068075 + 0.37339857070977056 + 0.37340919316515581 + 0.37341981598685636 + 0.3734304391748911 + 0.3734410627292809 + 0.37345168665004375 + 0.37346231093719945 + 0.37347293559076794 + 0.37348356061076804 + 0.37349418599722073 + 0.37350481175014388 + 0.37351543786955826 + 0.37352606435548291 + 0.37353669120793676 + 0.37354731842694061 + 0.37355794601251341 + 0.37356857396467402 + 0.37357920228344244 + 0.37358983096883841 + 0.37360046002088104 + 0.37361108943959004 + 0.37362171922498544 + 0.37363234937708611 + 0.373642979895912 + 0.3736536107814829 + 0.37366424203381782 + 0.37367487365293578 + 0.37368550563885833 + 0.37369613799160184 + 0.37370677071118896 + 0.37371740379763768 + 0.37372803725096787 + 0.3737386710711994 + 0.37374930525835137 + 0.37375993981244354 + 0.37377057473349501 + 0.37378121002152642 + 0.3737918456765551 + 0.37380248169860353 + 0.37381311808768902 + 0.37382375484383318 + 0.37383439196705409 + 0.37384502945737086 + 0.37385566731480413 + 0.37386630553937389 + 0.37387694413109823 + 0.37388758308999792 + 0.373898222416092 + 0.37390886210940033 + 0.37391950216994196 + 0.37393014259773677 + 0.37394078339280473 + 0.37395142455516467 + 0.37396206608483751 + 0.3739727079818414 + 0.37398335024619628 + 0.37399399287792279 + 0.37400463587703925 + 0.37401527924356542 + 0.37402592297752124 + 0.37403656707892668 + 0.3740472115477998 + 0.37405785638416239 + 0.37406850158803251 + 0.37407914715943003 + 0.37408979309837509 + 0.37410043940488641 + 0.37411108607898508 + 0.37412173312068908 + 0.37413238053001829 + 0.37414302830699375 + 0.37415367645163344 + 0.3741643249639573 + 0.37417497384398618 + 0.37418562309173814 + 0.37419627270723316 + 0.37420692269049216 + 0.37421757304153325 + 0.37422822376037629 + 0.37423887484704121 + 0.37424952630154712 + 0.37426017812391488 + 0.37427083031416347 + 0.37428148287231106 + 0.37429213579838028 + 0.37430278909238834 + 0.37431344275435624 + 0.37432409678430195 + 0.37433475118224735 + 0.37434540594821042 + 0.37435606108221126 + 0.37436671658426979 + 0.37437737245440511 + 0.37438802869263804 + 0.37439868529898573 + 0.374409342273471 + 0.37441999961611194 + 0.37443065732692854 + 0.37444131540593883 + 0.3744519738531647 + 0.37446263266862523 + 0.37447329185233941 + 0.37448395140432728 + 0.37449461132460782 + 0.37450527161320291 + 0.37451593227012964 + 0.37452659329540905 + 0.37453725468906113 + 0.37454791645110386 + 0.37455857858155833 + 0.37456924108044437 + 0.37457990394778018 + 0.37459056718358763 + 0.37460123078788482 + 0.37461189476069079 + 0.37462255910202746 + 0.37463322381191294 + 0.37464388889036709 + 0.37465455433741007 + 0.37466522015306097 + 0.37467588633733961 + 0.37468655289026609 + 0.37469721981186044 + 0.37470788710214165 + 0.37471855476112892 + 0.37472922278884302 + 0.37473989118530315 + 0.37475055995052931 + 0.37476122908454046 + 0.37477189858735771 + 0.37478256845899904 + 0.3747932386994855 + 0.37480390930883611 + 0.37481458028707093 + 0.37482525163420993 + 0.37483592335027133 + 0.37484659543527699 + 0.37485726788924589 + 0.37486794071219637 + 0.37487861390414923 + 0.37488928746512451 + 0.37489996139514231 + 0.37491063569422073 + 0.3749213103623808 + 0.3749319853996424 + 0.37494266080602384 + 0.37495333658154695 + 0.37496401272622898 + 0.37497468924009175 + 0.37498536612315447 + 0.3749960433754353 + 0.37500672099695698 + 0.37501739898773684 + 0.37502807734779486 + 0.37503875607715204 + 0.37504943517582656 + 0.37506011464384031 + 0.3750707944812105 + 0.37508147468795905 + 0.37509215526410422 + 0.375102836209666 + 0.37511351752466532 + 0.37512419920912049 + 0.37513488126305233 + 0.37514556368647917 + 0.37515624647942281 + 0.37516692964190151 + 0.37517761317393533 + 0.37518829707554424 + 0.37519898134674839 + 0.37520966598756689 + 0.3752203509980197 + 0.37523103637812616 + 0.37524172212790696 + 0.37525240824738149 + 0.37526309473656977 + 0.3752737815954908 + 0.37528446882416472 + 0.37529515642261163 + 0.37530584439085157 + 0.3753165327289037 + 0.37532722143678798 + 0.37533791051452281 + 0.37534859996213088 + 0.37535928977963051 + 0.37536997996704169 + 0.37538067052438367 + 0.37539136145167651 + 0.37540205274894012 + 0.37541274441619388 + 0.37542343645345866 + 0.37543412886075272 + 0.37544482163809795 + 0.37545551478551176 + 0.37546620830301503 + 0.3754769021906289 + 0.37548759644837154 + 0.37549829107626298 + 0.37550898607432343 + 0.37551968144257192 + 0.37553037718102955 + 0.37554107328971559 + 0.37555176976864896 + 0.37556246661785087 + 0.37557316383734041 + 0.37558386142713773 + 0.37559455938726194 + 0.37560525771773406 + 0.37561595641857243 + 0.3756266554897989 + 0.3756373549314318 + 0.37564805474349022 + 0.37565875492599626 + 0.37566945547896796 + 0.37568015640242564 + 0.37569085769639027 + 0.37570155936087907 + 0.37571226139591507 + 0.3757229638015156 + 0.37573366657770163 + 0.37574436972449321 + 0.37575507324190965 + 0.37576577712997106 + 0.37577648138869757 + 0.37578718601810829 + 0.37579789101822336 + 0.37580859638906294 + 0.37581930213064624 + 0.37583000824299417 + 0.37584071472612623 + 0.3758514215800613 + 0.37586212880482062 + 0.37587283640042324 + 0.37588354436688953 + 0.37589425270423849 + 0.37590496141249125 + 0.37591567049166696 + 0.37592637994178585 + 0.3759370897628671 + 0.37594779995493172 + 0.37595851051799806 + 0.37596922145208717 + 0.37597993275721825 + 0.37599064443341235 + 0.37600135648068778 + 0.37601206889906558 + 0.37602278168856507 + 0.37603349484920628 + 0.37604420838100944 + 0.37605492228399467 + 0.37606563655818026 + 0.37607635120358818 + 0.3760870662202368 + 0.37609778160814722 + 0.37610849736733765 + 0.37611921349783012 + 0.37612992999964295 + 0.3761406468727973 + 0.37615136411731132 + 0.3761620817332072 + 0.37617279972050216 + 0.37618351807921924 + 0.37619423680937586 + 0.3762049559109929 + 0.3762156753840899 + 0.37622639522868778 + 0.37623711544480576 + 0.37624783603246231 + 0.3762585569916802 + 0.37626927832247786 + 0.37628000002487549 + 0.37629072209889225 + 0.37630144454454928 + 0.3763121673618649 + 0.3763228905508611 + 0.37633361411155636 + 0.37634433804397066 + 0.37635506234812527 + 0.37636578702403845 + 0.37637651207173123 + 0.37638723749122305 + 0.37639796328253494 + 0.37640868944568517 + 0.37641941598069406 + 0.37643014288758259 + 0.37644087016637012 + 0.37645159781707682 + 0.37646232583972195 + 0.3764730542343257 + 0.37648378300090823 + 0.37649451213948981 + 0.37650524165009069 + 0.37651597153272998 + 0.37652670178742714 + 0.37653743241420407 + 0.37654816341307917 + 0.37655889478407267 + 0.37656962652720471 + 0.37658035864249562 + 0.37659109112996553 + 0.37660182398963277 + 0.37661255722151948 + 0.376623290825644 + 0.37663402480202746 + 0.37664475915068907 + 0.37665549387164921 + 0.37666622896492791 + 0.37667696443054555 + 0.37668770026852039 + 0.37669843647887363 + 0.37670917306162638 + 0.37671991001679711 + 0.37673064734440592 + 0.37674138504447313 + 0.37675212311701889 + 0.37676286156206346 + 0.37677360037962615 + 0.37678433956972723 + 0.37679507913238686 + 0.37680581906762439 + 0.37681655937546088 + 0.3768273000559158 + 0.37683804110900837 + 0.37684878253476078 + 0.37685952433319131 + 0.3768702665043201 + 0.37688100904816763 + 0.37689175196475311 + 0.37690249525409764 + 0.37691323891622064 + 0.37692398295114321 + 0.37693472735888289 + 0.37694547213946267 + 0.37695621729290091 + 0.37696696281921793 + 0.376977708718434 + 0.37698845499056827 + 0.37699920163564121 + 0.37700994865367388 + 0.37702069604468574 + 0.37703144380869597 + 0.37704219194572486 + 0.37705294045579363 + 0.37706368933892165 + 0.37707443859512912 + 0.37708518822443449 + 0.37709593822686083 + 0.37710668860242547 + 0.37711743935115077 + 0.37712819047305407 + 0.3771389419681575 + 0.37714969383648134 + 0.37716044607804411 + 0.37717119869286592 + 0.37718195168096896 + 0.37719270504237085 + 0.37720345877709355 + 0.37721421288515644 + 0.37722496736657896 + 0.37723572222138135 + 0.37724647744958478 + 0.37725723305120779 + 0.37726798902627146 + 0.37727874537479611 + 0.37728950209680118 + 0.37730025919230598 + 0.3773110166613326 + 0.37732177450389953 + 0.37733253272002804 + 0.37734329130973737 + 0.37735405027304691 + 0.37736480960997898 + 0.37737556932055183 + 0.37738632940478595 + 0.37739708986270137 + 0.37740785069431859 + 0.37741861189965786 + 0.37742937347873862 + 0.377440135431582 + 0.37745089775820656 + 0.37746166045863333 + 0.37747242353288285 + 0.37748318698097444 + 0.37749395080292925 + 0.37750471499876581 + 0.37751547956850529 + 0.37752624451216721 + 0.37753700982977267 + 0.37754777552134117 + 0.37755854158689295 + 0.37756930802644745 + 0.37758007484002587 + 0.3775908420276477 + 0.37760160958933403 + 0.37761237752510352 + 0.37762314583497636 + 0.37763391451897382 + 0.37764468357711628 + 0.37765545300942216 + 0.37766622281591372 + 0.37767699299660934 + 0.37768776355152944 + 0.37769853448069429 + 0.3777093057841252 + 0.3777200774618415 + 0.37773084951386177 + 0.3777416219402091 + 0.37775239474090094 + 0.37776316791595965 + 0.37777394146540366 + 0.37778471538925518 + 0.37779548968753168 + 0.37780626436025544 + 0.37781703940744593 + 0.37782781482912242 + 0.37783859062530634 + 0.37784936679601705 + 0.37786014334127582 + 0.37787092026110214 + 0.3778816975555162 + 0.37789247522453762 + 0.37790325326818758 + 0.37791403168648552 + 0.37792481047945181 + 0.37793558964710589 + 0.37794636918946994 + 0.37795714910656253 + 0.3779679293984049 + 0.37797871006501566 + 0.37798949110641594 + 0.37800027252262719 + 0.37801105431366694 + 0.37802183647955728 + 0.37803261902031787 + 0.37804340193596897 + 0.37805418522653095 + 0.37806496889202329 + 0.37807575293246737 + 0.37808653734788156 + 0.37809732213828912 + 0.37810810730370659 + 0.3781188928441564 + 0.37812967875965975 + 0.37814046505023424 + 0.37815125171590119 + 0.37816203875668197 + 0.37817282617259501 + 0.37818361396366074 + 0.37819440212990052 + 0.37820519067133374 + 0.37821597958797998 + 0.3782267688798614 + 0.37823755854699748 + 0.37824834858940765 + 0.37825913900711333 + 0.37826992980013296 + 0.37828072096848797 + 0.37829151251219867 + 0.37830230443128465 + 0.37831309672576796 + 0.37832388939566647 + 0.37833468244100127 + 0.37834547586179296 + 0.37835626965806191 + 0.37836706382982754 + 0.37837785837711119 + 0.37838865329993243 + 0.37839944859831165 + 0.37841024427226821 + 0.37842104032182355 + 0.37843183674699815 + 0.37844263354781138 + 0.37845343072428378 + 0.37846422827643567 + 0.37847502620428747 + 0.37848582450785873 + 0.3784966231871717 + 0.37850742224224315 + 0.37851822167309712 + 0.37852902147975126 + 0.37853982166222705 + 0.37855062222054486 + 0.37856142315472413 + 0.37857222446478533 + 0.37858302615074985 + 0.37859382821263626 + 0.37860463065046585 + 0.37861543346425919 + 0.37862623665403566 + 0.37863704021981676 + 0.37864784416162101 + 0.37865864847947067 + 0.37866945317338524 + 0.37868025824338342 + 0.37869106368948835 + 0.37870186951171775 + 0.37871267571009481 + 0.37872348228463626 + 0.3787342892353654 + 0.37874509656230165 + 0.37875590426546468 + 0.37876671234487475 + 0.37877752080055249 + 0.37878832963251918 + 0.37879913884079353 + 0.37880994842539772 + 0.3788207583863496 + 0.37883156872367224 + 0.37884237943738336 + 0.37885319052750449 + 0.37886400199405679 + 0.37887481383705907 + 0.37888562605653259 + 0.37889643865249711 + 0.37890725162497368 + 0.37891806497398217 + 0.37892887869954289 + 0.37893969280167633 + 0.37895050728040208 + 0.37896132213574241 + 0.37897213736771512 + 0.37898295297634244 + 0.37899376896164394 + 0.37900458532364006 + 0.37901540206235146 + 0.37902621917779844 + 0.3790370366700006 + 0.37904785453897849 + 0.37905867278475353 + 0.37906949140734519 + 0.37908031040677403 + 0.37909112978305959 + 0.37910194953622423 + 0.37911276966628654 + 0.37912359017326708 + 0.3791344110571872 + 0.37914523231806568 + 0.37915605395592472 + 0.37916687597078302 + 0.37917769836266202 + 0.37918852113158136 + 0.3791993442775633 + 0.37921016780062555 + 0.3792209917007896 + 0.37923181597807692 + 0.37924264063250612 + 0.37925346566409862 + 0.37926429107287496 + 0.37927511685885468 + 0.37928594302205831 + 0.37929676956250641 + 0.37930759648022033 + 0.3793184237752189 + 0.37932925144752438 + 0.37934007949715443 + 0.37935090792413245 + 0.37936173672847623 + 0.37937256591020807 + 0.37938339546934757 + 0.37939422540591528 + 0.37940505571993077 + 0.37941588641141649 + 0.37942671748039103 + 0.37943754892687503 + 0.37944838075088982 + 0.3794592129524551 + 0.3794700455315913 + 0.37948087848831913 + 0.37949171182265895 + 0.37950254553463042 + 0.37951337962425508 + 0.37952421409155246 + 0.37953504893654411 + 0.37954588415924967 + 0.37955671975968858 + 0.37956755573788337 + 0.37957839209385358 + 0.37958922882761897 + 0.37960006593919998 + 0.37961090342861903 + 0.37962174129589488 + 0.37963257954104712 + 0.37964341816409808 + 0.37965425716506651 + 0.3796650965439749 + 0.3796759363008419 + 0.37968677643568888 + 0.37969761694853571 + 0.37970845783940366 + 0.37971929910831254 + 0.37973014075528283 + 0.37974098278033502 + 0.37975182518348888 + 0.37976266796476676 + 0.37977351112418739 + 0.37978435466177224 + 0.37979519857754107 + 0.37980604287151432 + 0.37981688754371357 + 0.37982773259415842 + 0.37983857802286947 + 0.37984942382986631 + 0.37986027001517153 + 0.37987111657880368 + 0.37988196352078346 + 0.3798928108411323 + 0.3799036585398699 + 0.37991450661701687 + 0.37992535507259462 + 0.37993620390662208 + 0.37994705311912058 + 0.37995790271011076 + 0.37996875267961328 + 0.37997960302764766 + 0.37999045375423557 + 0.38000130485939565 + 0.3800121563431505 + 0.38002300820552054 + 0.3800338604465246 + 0.38004471306618415 + 0.3800555660645199 + 0.38006641944155234 + 0.38007727319730122 + 0.38008812733178809 + 0.38009898184503249 + 0.38010983673705523 + 0.38012069200787768 + 0.38013154765751866 + 0.38014240368600066 + 0.38015326009334333 + 0.38016411687956636 + 0.38017497404469131 + 0.38018583158873875 + 0.38019668951172841 + 0.38020754781368188 + 0.38021840649461885 + 0.38022926555455983 + 0.3802401249935255 + 0.38025098481153641 + 0.38026184500861432 + 0.38027270558477694 + 0.38028356654004769 + 0.38029442787444528 + 0.38030528958799142 + 0.38031615168070565 + 0.38032701415260961 + 0.38033787700372301 + 0.38034874023406751 + 0.38035960384366163 + 0.3803704678325272 + 0.38038133220068465 + 0.38039219694815574 + 0.38040306207495822 + 0.38041392758111553 + 0.38042479346664648 + 0.38043565973157162 + 0.38044652637591264 + 0.38045739339968926 + 0.38046826080292212 + 0.38047912858563271 + 0.38048999674783984 + 0.38050086528956611 + 0.38051173421083029 + 0.3805226035116539 + 0.38053347319205771 + 0.38054434325206221 + 0.38055521369168727 + 0.38056608451095353 + 0.38057695570988254 + 0.38058782728849411 + 0.38059869924680878 + 0.38060957158484821 + 0.38062044430263126 + 0.38063131740018036 + 0.38064219087751433 + 0.38065306473465582 + 0.3806639389716226 + 0.38067481358843813 + 0.38068568858512225 + 0.3806965639616946 + 0.38070743971817589 + 0.38071831585458682 + 0.38072919237094899 + 0.3807400692672831 + 0.38075094654360692 + 0.38076182419994503 + 0.38077270223631526 + 0.38078358065274004 + 0.38079445944923745 + 0.38080533862583088 + 0.38081621818254002 + 0.38082709811938481 + 0.38083797843638667 + 0.38084885913356553 + 0.38085974021094293 + 0.38087062166853858 + 0.38088150350637429 + 0.38089238572446865 + 0.38090326832284443 + 0.38091415130152129 + 0.38092503466051997 + 0.38093591839986118 + 0.38094680251956464 + 0.38095768701965305 + 0.3809685719001451 + 0.38097945716106246 + 0.38099034280242589 + 0.38100122882425519 + 0.38101211522657191 + 0.38102300200939587 + 0.38103388917274877 + 0.38104477671665038 + 0.3810556646411204 + 0.38106655294618241 + 0.38107744163185531 + 0.38108833069815878 + 0.38109922014511549 + 0.38111010997274425 + 0.3811210001810677 + 0.38113189077010462 + 0.3811427817398777 + 0.38115367309040482 + 0.38116456482170952 + 0.38117545693381061 + 0.3811863494267298 + 0.38119724230048785 + 0.38120813555510363 + 0.38121902919060063 + 0.38122992320699678 + 0.38124081760431477 + 0.38125171238257427 + 0.38126260754179614 + 0.38127350308200203 + 0.38128439900321165 + 0.38129529530544592 + 0.38130619198872445 + 0.38131708905307005 + 0.38132798649850147 + 0.38133888432504143 + 0.38134978253270774 + 0.38136068112152505 + 0.38137158009151023 + 0.381382479442686 + 0.3813933791750731 + 0.38140427928869225 + 0.38141517978356326 + 0.38142608065970701 + 0.38143698191714503 + 0.38144788355589726 + 0.38145878557598534 + 0.38146968797742919 + 0.38148059076025037 + 0.38149149392446791 + 0.38150239747010434 + 0.38151330139717871 + 0.38152420570571344 + 0.38153511039572857 + 0.38154601546724476 + 0.38155692092028282 + 0.3815678267548635 + 0.38157873297100769 + 0.3815896395687351 + 0.38160054654806841 + 0.38161145390902662 + 0.38162236165163127 + 0.38163326977590328 + 0.38164417828186253 + 0.38165508716953056 + 0.3816659964389284 + 0.38167690609007565 + 0.38168781612299429 + 0.38169872653770492 + 0.38170963733422653 + 0.38172054851258275 + 0.38173146007279152 + 0.38174237201487549 + 0.38175328433885553 + 0.38176419704475051 + 0.38177511013258408 + 0.38178602360237418 + 0.38179693745414356 + 0.38180785168791193 + 0.38181876630370032 + 0.3818296813015285 + 0.38184059668142001 + 0.38185151244339294 + 0.38186242858746994 + 0.38187334511366994 + 0.38188426202201564 + 0.38189517931252598 + 0.38190609698522365 + 0.38191701504012859 + 0.38192793347726051 + 0.38193885229664137 + 0.3819497714982919 + 0.38196069108223279 + 0.38197161104848509 + 0.38198253139706956 + 0.38199345212800689 + 0.38200437324131714 + 0.382015294737022 + 0.38202621661514236 + 0.3820371388756979 + 0.38204806151871157 + 0.38205898454420228 + 0.38206990795219081 + 0.38208083174269986 + 0.3820917559157484 + 0.38210268047135726 + 0.38211360540954825 + 0.38212453073034236 + 0.38213545643375918 + 0.38214638251982158 + 0.38215730898854761 + 0.38216823583996001 + 0.38217916307407962 + 0.38219009069092624 + 0.38220101869052187 + 0.38221194707288619 + 0.38222287583804015 + 0.38223380498600557 + 0.3822447345168033 + 0.38225566443045328 + 0.38226659472697627 + 0.38227752540639409 + 0.38228845646872767 + 0.38229938791399687 + 0.38231031974222263 + 0.3823212519534257 + 0.38233218454762796 + 0.38234311752485028 + 0.38235405088511254 + 0.38236498462843566 + 0.38237591875484145 + 0.38238685326434879 + 0.3823977881569815 + 0.38240872343275856 + 0.38241965909170073 + 0.38243059513382904 + 0.38244153155916527 + 0.38245246836773023 + 0.38246340555954383 + 0.38247434313462714 + 0.38248528109300084 + 0.38249621943468681 + 0.3825071581597051 + 0.38251809726807739 + 0.38252903675982375 + 0.38253997663496492 + 0.38255091689352294 + 0.38256185753551758 + 0.38257279856097071 + 0.38258373996990236 + 0.3825946817623343 + 0.38260562393828645 + 0.38261656649777975 + 0.38262750944083612 + 0.38263845276747538 + 0.38264939647771945 + 0.38266034057158832 + 0.38267128504910375 + 0.38268222991028583 + 0.38269317515515622 + 0.38270412078373506 + 0.38271506679604406 + 0.38272601319210331 + 0.38273695997193469 + 0.38274790713555795 + 0.38275885468299514 + 0.38276980261426624 + 0.38278075092939295 + 0.38279169962839638 + 0.38280264871129638 + 0.38281359817811489 + 0.38282454802887278 + 0.38283549826358998 + 0.38284644888228847 + 0.38285739988498907 + 0.38286835127171193 + 0.38287930304247964 + 0.38289025519731046 + 0.3829012077362281 + 0.38291216065925254 + 0.38292311396640377 + 0.38293406765770377 + 0.38294502173317324 + 0.38295597619283339 + 0.38296693103670493 + 0.382977886264808 + 0.38298884187716542 + 0.38299979787379707 + 0.38301075425472403 + 0.38302171101996718 + 0.38303266816954651 + 0.38304362570348488 + 0.38305458362180228 + 0.38306554192451975 + 0.38307650061165804 + 0.38308745968323832 + 0.38309841913928228 + 0.38310937897981018 + 0.38312033920484267 + 0.38313129981440103 + 0.38314226080850694 + 0.38315322218718051 + 0.38316418395044261 + 0.38317514609831621 + 0.38318610863081937 + 0.38319707154797494 + 0.38320803484980298 + 0.38321899853632541 + 0.38322996260756315 + 0.38324092706353624 + 0.38325189190426656 + 0.3832628571297742 + 0.38327382274008109 + 0.38328478873520822 + 0.38329575511517644 + 0.38330672188000586 + 0.38331768902971941 + 0.38332865656433607 + 0.38333962448387782 + 0.3833505927883657 + 0.38336156147782147 + 0.38337253055226439 + 0.38338350001171734 + 0.38339446985619929 + 0.38340544008573318 + 0.38341641070033911 + 0.38342738170003798 + 0.3834383530848518 + 0.38344932485480065 + 0.38346029700990536 + 0.38347126955018807 + 0.38348224247566964 + 0.38349321578636925 + 0.38350418948230974 + 0.38351516356351312 + 0.38352613802999747 + 0.38353711288178677 + 0.38354808811889995 + 0.38355906374135912 + 0.38357003974918519 + 0.38358101614239831 + 0.38359199292102125 + 0.38360297008507432 + 0.38361394763457823 + 0.38362492556955419 + 0.38363590389002317 + 0.38364688259600616 + 0.38365786168752519 + 0.38366884116460026 + 0.3836798210272524 + 0.38369080127550365 + 0.38370178190937398 + 0.38371276292888545 + 0.38372374433405815 + 0.38373472612491394 + 0.38374570830147398 + 0.38375669086375824 + 0.38376767381178972 + 0.38377865714558757 + 0.3837896408651737 + 0.38380062497056922 + 0.3838116094617951 + 0.38382259433887245 + 0.38383357960182318 + 0.38384456525066646 + 0.3838555512854262 + 0.38386653770612061 + 0.38387752451277157 + 0.38388851170540217 + 0.38389949928403061 + 0.38391048724868054 + 0.38392147559937145 + 0.38393246433612516 + 0.3839434534589618 + 0.38395444296790426 + 0.38396543286297175 + 0.38397642314418629 + 0.38398741381157081 + 0.3839984048651427 + 0.3840093963049247 + 0.38402038813093986 + 0.38403138034320644 + 0.38404237294174737 + 0.38405336592658273 + 0.38406435929773458 + 0.38407535305522306 + 0.38408634719907103 + 0.38409734172929777 + 0.38410833664592436 + 0.38411933194897369 + 0.38413032763846588 + 0.38414132371442111 + 0.38415232017686324 + 0.38416331702581064 + 0.38417431426128523 + 0.38418531188330901 + 0.38419630989190223 + 0.38420730828708677 + 0.38421830706888283 + 0.38422930623731255 + 0.38424030579239588 + 0.38425130573415595 + 0.38426230606261186 + 0.38427330677778571 + 0.38428430787969947 + 0.38429530936837247 + 0.38430631124382764 + 0.38431731350608495 + 0.38432831615516577 + 0.38433931919109199 + 0.38435032261388385 + 0.38436132642356424 + 0.38437233062015241 + 0.38438333520366952 + 0.38439434017413748 + 0.38440534553157857 + 0.38441635127601276 + 0.38442735740746026 + 0.38443836392594405 + 0.38444937083148434 + 0.38446037812410322 + 0.38447138580382073 + 0.38448239387065913 + 0.38449340232463841 + 0.38450441116578066 + 0.38451542039410713 + 0.38452643000963876 + 0.38453744001239587 + 0.38454845040240143 + 0.38455946117967649 + 0.3845704723442413 + 0.38458148389611702 + 0.38459249583532468 + 0.38460350816188643 + 0.38461452087582337 + 0.38462553397715576 + 0.38463654746590653 + 0.38464756134209488 + 0.38465857560574401 + 0.38466959025687297 + 0.38468060529550502 + 0.38469162072166102 + 0.38470263653536046 + 0.38471365273662622 + 0.38472466932547955 + 0.38473568630194155 + 0.38474670366603236 + 0.38475772141777509 + 0.38476873955718993 + 0.3847797580842971 + 0.38479077699911962 + 0.38480179630167766 + 0.38481281599199441 + 0.38482383607008802 + 0.3848348565359816 + 0.38484587738969628 + 0.38485689863125333 + 0.38486792026067279 + 0.38487894227797786 + 0.38488996468318876 + 0.38490098747632751 + 0.38491201065741337 + 0.3849230342264704 + 0.38493405818351789 + 0.3849450825285769 + 0.38495610726167073 + 0.38496713238281943 + 0.38497815789204315 + 0.38498918378936514 + 0.3850002100748055 + 0.38501123674838644 + 0.38502226381012811 + 0.3850332912600527 + 0.38504431909818049 + 0.3850553473245335 + 0.3850663759391339 + 0.38507740494200093 + 0.38508843433315776 + 0.38509946411262463 + 0.38511049428042365 + 0.38512152483657497 + 0.38513255578109995 + 0.38514358711402158 + 0.38515461883535917 + 0.38516565094513577 + 0.38517668344337075 + 0.38518771633008719 + 0.38519874960530626 + 0.3852097832690472 + 0.38522081732133423 + 0.38523185176218655 + 0.38524288659162631 + 0.38525392180967483 + 0.38526495741635403 + 0.38527599341168334 + 0.38528702979568596 + 0.38529806656838206 + 0.38530910372979382 + 0.38532014127994241 + 0.38533117921884913 + 0.38534221754653508 + 0.38535325626302158 + 0.38536429536832983 + 0.38537533486248193 + 0.38538637474549731 + 0.38539741501739994 + 0.38540845567821019 + 0.38541949672794829 + 0.38543053816663636 + 0.38544157999429662 + 0.38545262221094939 + 0.38546366481661581 + 0.38547470781131815 + 0.38548575119507766 + 0.38549679496791545 + 0.38550783912985193 + 0.38551888368091014 + 0.38552992862111041 + 0.38554097395047399 + 0.38555201966902214 + 0.38556306577677796 + 0.38557411227376076 + 0.38558515915999281 + 0.3855962064354963 + 0.38560725410029056 + 0.38561830215439863 + 0.38562935059784104 + 0.38564039943063882 + 0.38565144865281525 + 0.38566249826439059 + 0.38567354826538608 + 0.38568459865582205 + 0.38569564943572171 + 0.3857067006051062 + 0.3857177521639969 + 0.385728804112414 + 0.38573985645037884 + 0.3857509091779146 + 0.38576196229504245 + 0.38577301580178192 + 0.38578406969815598 + 0.38579512398418608 + 0.38580617865989242 + 0.38581723372529725 + 0.38582828918042278 + 0.38583934502528938 + 0.38585040125991832 + 0.38586145788433185 + 0.38587251489855018 + 0.38588357230259568 + 0.38589463009648955 + 0.38590568828025401 + 0.38591674685390848 + 0.3859278058174761 + 0.38593886517097831 + 0.38594992491443525 + 0.38596098504786924 + 0.38597204557130255 + 0.38598310648475453 + 0.38599416778824835 + 0.38600522948180538 + 0.38601629156544592 + 0.38602735403919219 + 0.38603841690306551 + 0.38604948015708718 + 0.38606054380127952 + 0.3860716078356628 + 0.38608267226025933 + 0.38609373707508932 + 0.38610480228017613 + 0.38611586787553914 + 0.3861269338612015 + 0.38613800023718364 + 0.38614906700350876 + 0.38616013416019523 + 0.38617120170726732 + 0.38618226964474539 + 0.38619333797265065 + 0.38620440669100459 + 0.38621547579982929 + 0.38622654529914624 + 0.38623761518897665 + 0.38624868546934182 + 0.38625975614026314 + 0.38627082720176292 + 0.38628189865386148 + 0.38629297049658112 + 0.38630404272994312 + 0.3863151153539689 + 0.38632618836867971 + 0.38633726177409788 + 0.38634833557024467 + 0.38635940975714061 + 0.38637048433480786 + 0.38638155930326873 + 0.3863926346625427 + 0.38640371041265298 + 0.38641478655362094 + 0.38642586308546795 + 0.38643694000821527 + 0.38644801732188422 + 0.38645909502649634 + 0.38647017312207371 + 0.38648125160863789 + 0.38649233048620901 + 0.38650340975481057 + 0.38651448941446287 + 0.38652556946518823 + 0.38653664990700703 + 0.3865477307399417 + 0.38655881196401343 + 0.38656989357924365 + 0.38658097558565374 + 0.38659205798326601 + 0.38660314077210178 + 0.38661422395218153 + 0.38662530752352847 + 0.38663639148616313 + 0.38664747584010672 + 0.38665856058538167 + 0.38666964572200929 + 0.38668073125001107 + 0.38669181716940826 + 0.38670290348022324 + 0.38671399018247637 + 0.38672507727619004 + 0.38673616476138567 + 0.38674725263808457 + 0.38675834090630917 + 0.38676942956607974 + 0.3867805186174178 + 0.38679160806034663 + 0.38680269789488658 + 0.38681378812105915 + 0.3868248787388866 + 0.38683596974838935 + 0.38684706114958989 + 0.38685815294250947 + 0.38686924512717052 + 0.38688033770359348 + 0.38689143067179965 + 0.38690252403181241 + 0.38691361778365219 + 0.38692471192734051 + 0.3869358064628986 + 0.38694690139034887 + 0.38695799670971276 + 0.38696909242101168 + 0.38698018852426702 + 0.3869912850195012 + 0.38700238190673458 + 0.38701347918598955 + 0.38702457685728853 + 0.38703567492065094 + 0.38704677337610116 + 0.38705787222365773 + 0.3870689714633449 + 0.38708007109518305 + 0.38709117111919378 + 0.38710227153539839 + 0.38711337234381932 + 0.38712447354447793 + 0.38713557513739671 + 0.38714667712259504 + 0.38715777950009639 + 0.38716888226992213 + 0.38717998543209364 + 0.3871910889866324 + 0.38720219293356084 + 0.38721329727289849 + 0.38722440200466962 + 0.38723550712889465 + 0.38724661264559512 + 0.38725771855479335 + 0.38726882485650993 + 0.38727993155076712 + 0.38729103863758652 + 0.38730214611698943 + 0.38731325398899841 + 0.38732436225363376 + 0.38733547091091902 + 0.38734657996087463 + 0.38735768940352194 + 0.38736879923888351 + 0.38737990946697975 + 0.3873910200878341 + 0.3874021311014661 + 0.38741324250789994 + 0.38742435430715533 + 0.38743546649925464 + 0.38744657908421937 + 0.38745769206207076 + 0.38746880543283158 + 0.38747991919652308 + 0.38749103335316581 + 0.3875021479027842 + 0.38751326284539667 + 0.38752437818102681 + 0.38753549390969594 + 0.38754661003142654 + 0.38755772654623821 + 0.38756884345415527 + 0.38757996075519729 + 0.38759107844938767 + 0.38760219653674594 + 0.38761331501729557 + 0.38762443389105794 + 0.3876355531580537 + 0.38764667281830711 + 0.38765779287183688 + 0.38766891331866632 + 0.38768003415881702 + 0.38769115539231042 + 0.38770227701916893 + 0.3877133990394131 + 0.38772452145306546 + 0.38773564426014751 + 0.38774676746068154 + 0.38775789105468728 + 0.38776901504218914 + 0.3877801394232076 + 0.38779126419776411 + 0.3878023893658803 + 0.38781351492757854 + 0.38782464088288132 + 0.38783576723180824 + 0.38784689397438277 + 0.38785802111062639 + 0.3878691486405596 + 0.38788027656420587 + 0.3878914048815858 + 0.38790253359272087 + 0.3879136626976345 + 0.38792479219634723 + 0.38793592208888078 + 0.38794705237525734 + 0.38795818305549862 + 0.3879693141296261 + 0.38798044559766121 + 0.38799157745962665 + 0.38800270971554285 + 0.38801384236543324 + 0.38802497540931846 + 0.38803610884722101 + 0.38804724267916135 + 0.38805837690516315 + 0.38806951152524677 + 0.3880806465394348 + 0.38809178194774785 + 0.38810291775020928 + 0.38811405394683984 + 0.38812519053766181 + 0.388136327522696 + 0.38814746490196478 + 0.38815860267549163 + 0.38816974084329531 + 0.38818087940540008 + 0.38819201836182571 + 0.38820315771259573 + 0.38821429745773156 + 0.38822543759725375 + 0.38823657813118595 + 0.38824771905954875 + 0.38825886038236451 + 0.3882700020996549 + 0.38828114421144144 + 0.38829228671774568 + 0.38830342961859127 + 0.38831457291399663 + 0.38832571660398735 + 0.38833686068858209 + 0.38834800516780532 + 0.38835915004167759 + 0.38837029531022044 + 0.38838144097345562 + 0.38839258703140644 + 0.38840373348409263 + 0.3884148803315377 + 0.38842602757376232 + 0.38843717521078985 + 0.38844832324264006 + 0.38845947166933642 + 0.38847062049090059 + 0.38848176970735299 + 0.38849291931871738 + 0.3885040693250143 + 0.38851521972626718 + 0.38852637052249572 + 0.38853752171372258 + 0.38854867329997023 + 0.38855982528126021 + 0.38857097765761334 + 0.38858213042905387 + 0.38859328359560169 + 0.38860443715727921 + 0.38861559111410804 + 0.38862674546611087 + 0.38863790021330824 + 0.38864905535572369 + 0.38866021089337788 + 0.38867136682629244 + 0.38868252315448992 + 0.38869367987799291 + 0.38870483699682201 + 0.38871599451099992 + 0.38872715242054712 + 0.38873831072548726 + 0.38874946942584193 + 0.38876062852163179 + 0.38877178801287943 + 0.38878294789960849 + 0.38879410818183752 + 0.3888052688595911 + 0.38881642993288901 + 0.38882759140175577 + 0.38883875326621092 + 0.38884991552627718 + 0.38886107818197713 + 0.38887224123333242 + 0.3888834046803637 + 0.38889456852309445 + 0.3889057327615455 + 0.38891689739573937 + 0.38892806242569766 + 0.38893922785144214 + 0.38895039367299616 + 0.38896155989037967 + 0.38897272650361608 + 0.38898389351272616 + 0.38899506091773256 + 0.38900622871865675 + 0.38901739691552156 + 0.38902856550834847 + 0.38903973449715828 + 0.3890509038819745 + 0.38906207366281781 + 0.38907324383971098 + 0.38908441441267644 + 0.389095585381735 + 0.38910675674690925 + 0.38911792850822086 + 0.38912910066569245 + 0.38914027321934475 + 0.38915144616920033 + 0.38916261951528186 + 0.38917379325761009 + 0.3891849673962085 + 0.38919614193109692 + 0.38920731686229898 + 0.38921849218983529 + 0.38922966791372954 + 0.38924084403400339 + 0.38925202055067748 + 0.38926319746377458 + 0.38927437477331622 + 0.38928555247932523 + 0.38929673058182407 + 0.38930790908083263 + 0.38931908797637355 + 0.38933026726847036 + 0.38934144695714384 + 0.38935262704241663 + 0.38936380752430949 + 0.38937498840284601 + 0.38938616967804696 + 0.38939735134993392 + 0.38940853341853071 + 0.38941971588385788 + 0.38943089874593728 + 0.38944208200479236 + 0.38945326566044403 + 0.38946444971291394 + 0.38947563416222569 + 0.38948681900839904 + 0.3894980042514587 + 0.3895091898914243 + 0.38952037592831962 + 0.38953156236216435 + 0.38954274919298321 + 0.38955393642079672 + 0.38956512404562682 + 0.38957631206749621 + 0.38958750048642732 + 0.38959868930244013 + 0.38960987851555928 + 0.38962106812580449 + 0.38963225813319946 + 0.38964344853776489 + 0.38965463933952449 + 0.38966583053849896 + 0.38967702213471106 + 0.3896882141281815 + 0.38969940651893403 + 0.38971059930699026 + 0.3897217924923711 + 0.3897329860751001 + 0.38974418005519901 + 0.38975537443268871 + 0.38976656920759273 + 0.38977776437993195 + 0.3897889599497299 + 0.38980015591700656 + 0.38981135228178559 + 0.38982254904408864 + 0.38983374620393846 + 0.38984494376135587 + 0.38985614171636362 + 0.38986734006898333 + 0.38987853881923779 + 0.38988973796714876 + 0.38990093751273702 + 0.38991213745602721 + 0.38992333779703925 + 0.38993453853579674 + 0.38994573967232055 + 0.38995694120663421 + 0.38996814313875772 + 0.38997934546871565 + 0.38999054819652795 + 0.39000175132221715 + 0.39001295484580617 + 0.39002415876731678 + 0.39003536308677161 + 0.39004656780419056 + 0.39005777291959826 + 0.39006897843301658 + 0.39008018434446629 + 0.39009139065397003 + 0.39010259736154967 + 0.39011380446722799 + 0.39012501197102772 + 0.39013621987296865 + 0.39014742817307557 + 0.39015863687136731 + 0.39016984596786947 + 0.39018105546260295 + 0.39019226535558948 + 0.39020347564685093 + 0.39021468633641004 + 0.39022589742428859 + 0.39023710891050928 + 0.39024832079509397 + 0.39025953307806355 + 0.39027074575944265 + 0.39028195883925104 + 0.39029317231751265 + 0.39030438619424823 + 0.39031560046948049 + 0.39032681514323236 + 0.3903380302155246 + 0.39034924568637985 + 0.3903604615558211 + 0.39037167782387006 + 0.39038289449054758 + 0.39039411155587739 + 0.39040532901988145 + 0.39041654688258143 + 0.39042776514400013 + 0.39043898380415931 + 0.39045020286308008 + 0.39046142232078684 + 0.39047264217729971 + 0.39048386243264233 + 0.39049508308683667 + 0.39050630413990345 + 0.39051752559186742 + 0.39052874744274751 + 0.39053996969256849 + 0.39055119234135227 + 0.39056241538911957 + 0.39057363883589424 + 0.39058486268169706 + 0.39059608692655101 + 0.39060731157047873 + 0.39061853661350221 + 0.3906297620556422 + 0.39064098789692253 + 0.39065221413736412 + 0.39066344077699161 + 0.39067466781582405 + 0.3906858952538852 + 0.39069712309119786 + 0.39070835132778386 + 0.39071957996366419 + 0.39073080899886259 + 0.39074203843340083 + 0.39075326826730084 + 0.39076449850058448 + 0.39077572913327557 + 0.39078696016539405 + 0.39079819159696455 + 0.39080942342800712 + 0.39082065565854557 + 0.39083188828860171 + 0.39084312131819743 + 0.39085435474735469 + 0.39086558857609621 + 0.39087682280444491 + 0.39088805743242155 + 0.39089929246004917 + 0.39091052788735053 + 0.39092176371434745 + 0.3909329999410619 + 0.3909442365675167 + 0.39095547359373273 + 0.39096671101973385 + 0.39097794884554199 + 0.39098918707117797 + 0.39100042569666665 + 0.39101166472202797 + 0.39102290414728574 + 0.39103414397246089 + 0.39104538419757628 + 0.39105662482265474 + 0.3910678658477183 + 0.39107910727278777 + 0.39109034909788798 + 0.3911015913230389 + 0.39111283394826429 + 0.3911240769735862 + 0.39113532039902649 + 0.39114656422460792 + 0.39115780845035159 + 0.39116905307628125 + 0.39118029810241783 + 0.39119154352878527 + 0.39120278935540448 + 0.39121403558229922 + 0.39122528220948954 + 0.39123652923700031 + 0.39124777666485144 + 0.39125902449306682 + 0.39127027272166837 + 0.3912815213506789 + 0.39129277038011856 + 0.391304019810012 + 0.39131526964038127 + 0.39132651987124828 + 0.39133777050263496 + 0.39134902153456319 + 0.39136027296705689 + 0.39137152480013698 + 0.3913827770338274 + 0.39139402966814812 + 0.39140528270312391 + 0.39141653613877492 + 0.39142778997512484 + 0.39143904421219577 + 0.39145029885000959 + 0.39146155388858928 + 0.39147280932795758 + 0.39148406516813566 + 0.39149532140914539 + 0.39150657805101158 + 0.39151783509375437 + 0.39152909253739648 + 0.39154035038196106 + 0.39155160862746996 + 0.39156286727394607 + 0.39157412632141042 + 0.39158538576988688 + 0.39159664561939656 + 0.39160790586996319 + 0.39161916652160689 + 0.39163042757435251 + 0.391641689028222 + 0.39165295088323643 + 0.39166421313941868 + 0.39167547579679068 + 0.39168673885537647 + 0.3916980023151978 + 0.39170926617627594 + 0.39172053043863464 + 0.39173179510229494 + 0.39174306016727983 + 0.39175432563361123 + 0.39176559150131307 + 0.39177685777040638 + 0.39178812444091515 + 0.39179939151285925 + 0.39181065898626183 + 0.39182192686114664 + 0.39183319513753495 + 0.39184446381545041 + 0.39185573289491415 + 0.39186700237594824 + 0.39187827225857558 + 0.3918895425428201 + 0.39190081322870185 + 0.39191208431624486 + 0.39192335580547005 + 0.39193462769640136 + 0.39194589998906082 + 0.39195717268347047 + 0.39196844577965329 + 0.39197971927763026 + 0.39199099317742636 + 0.39200226747906153 + 0.39201354218255891 + 0.39202481728794147 + 0.39203609279523211 + 0.39204736870445189 + 0.39205864501562387 + 0.39206992172877098 + 0.39208119884391424 + 0.39209247636107764 + 0.39210375428028327 + 0.39211503260155306 + 0.39212631132490999 + 0.39213759045037616 + 0.39214886997797466 + 0.39216014990772635 + 0.39217143023965523 + 0.39218271097378438 + 0.39219399211013389 + 0.3922052736487277 + 0.39221655558958884 + 0.39222783793273841 + 0.39223912067819933 + 0.39225040382599469 + 0.39226168737614647 + 0.39227297132867678 + 0.39228425568360858 + 0.39229554044096493 + 0.39230682560076685 + 0.39231811116303739 + 0.39232939712779952 + 0.39234068349507639 + 0.39235197026488894 + 0.3923632574372603 + 0.39237454501221253 + 0.39238583298976953 + 0.39239712136995147 + 0.39240841015278333 + 0.39241969933828624 + 0.39243098892648309 + 0.39244227891739508 + 0.39245356931104719 + 0.39246486010745962 + 0.39247615130665719 + 0.39248744290866 + 0.3924987349134923 + 0.39251002732117501 + 0.39252132013173213 + 0.39253261334518585 + 0.39254390696155816 + 0.39255520098087215 + 0.39256649540314986 + 0.39257779022841344 + 0.39258908545668686 + 0.39260038108799217 + 0.39261167712235057 + 0.39262297355978598 + 0.39263427040032056 + 0.39264556764397746 + 0.39265686529077753 + 0.39266816334074511 + 0.39267946179390112 + 0.39269076065026964 + 0.39270205990987184 + 0.39271335957273179 + 0.39272465963887143 + 0.39273596010831202 + 0.39274726098107859 + 0.39275856225719119 + 0.3927698639366739 + 0.39278116601954893 + 0.39279246850583827 + 0.39280377139556605 + 0.39281507468875337 + 0.39282637838542328 + 0.39283768248559792 + 0.39284898698930037 + 0.3928602918965528 + 0.39287159720737819 + 0.39288290292179973 + 0.39289420903983852 + 0.39290551556151765 + 0.39291682248686116 + 0.39292812981588932 + 0.39293943754862615 + 0.39295074568509364 + 0.3929620542253151 + 0.39297336316931164 + 0.39298467251710822 + 0.39299598226872506 + 0.39300729242418636 + 0.39301860298351404 + 0.39302991394673131 + 0.39304122531385932 + 0.39305253708492227 + 0.39306384925994209 + 0.39307516183894115 + 0.39308647482194131 + 0.3930977882089679 + 0.39310910200004195 + 0.39312041619518473 + 0.39313173079442115 + 0.3931430457977716 + 0.39315436120526193 + 0.39316567701691058 + 0.39317699323274347 + 0.39318830985278186 + 0.39319962687704885 + 0.39321094430556658 + 0.39322226213835815 + 0.39323358037544581 + 0.39324489901685161 + 0.3932562180625998 + 0.39326753751271243 + 0.39327885736721169 + 0.39329017762611979 + 0.39330149828946082 + 0.39331281935725687 + 0.39332414082952932 + 0.3933354627063031 + 0.39334678498759845 + 0.39335810767343959 + 0.39336943076384961 + 0.39338075425884877 + 0.39339207815846206 + 0.39340340246271183 + 0.39341472717162013 + 0.39342605228521016 + 0.39343737780350413 + 0.39344870372652424 + 0.39346003005429447 + 0.39347135678683631 + 0.39348268392417268 + 0.39349401146632684 + 0.39350533941332094 + 0.39351666776517824 + 0.39352799652192089 + 0.39353932568357203 + 0.39355065525015381 + 0.39356198522168961 + 0.39357331559820052 + 0.39358464637971152 + 0.39359597756624409 + 0.39360730915782038 + 0.39361864115446443 + 0.39362997355619755 + 0.3936413063630439 + 0.39365263957502472 + 0.39366397319216417 + 0.39367530721448341 + 0.39368664164200678 + 0.39369797647475629 + 0.39370931171275431 + 0.39372064735602302 + 0.39373198340458659 + 0.39374331985846817 + 0.39375465671768806 + 0.39376599398227041 + 0.39377733165223849 + 0.3937886697276145 + 0.39380000820841976 + 0.39381134709467919 + 0.39382268638641527 + 0.3938340260836492 + 0.39384536618640509 + 0.39385670669470524 + 0.3938680476085728 + 0.39387938892803009 + 0.39389073065309937 + 0.39390207278380468 + 0.39391341532016744 + 0.39392475826221074 + 0.39393610160995796 + 0.39394744536343124 + 0.39395878952265379 + 0.39397013408764792 + 0.39398147905843683 + 0.39399282443504374 + 0.3940041702174899 + 0.39401551640579868 + 0.39402686299999407 + 0.39403821000009748 + 0.39404955740613223 + 0.39406090521812137 + 0.39407225343608632 + 0.39408360206005127 + 0.39409495109003845 + 0.39410630052607104 + 0.39411765036817148 + 0.39412900061636186 + 0.3941403512706666 + 0.3941517023311078 + 0.39416305379770783 + 0.39417440567048884 + 0.39418575794947619 + 0.39419711063468915 + 0.39420846372615392 + 0.39421981722389182 + 0.39423117112792511 + 0.39424252543827604 + 0.39425388015496993 + 0.39426523527802698 + 0.39427659080747246 + 0.39428794674332768 + 0.394299303085615 + 0.39431065983435853 + 0.39432201698957975 + 0.39433337455130274 + 0.39434473251954993 + 0.39435609089434354 + 0.3943674496757078 + 0.39437880886366322 + 0.39439016845823482 + 0.39440152845944498 + 0.39441288886731607 + 0.39442424968187123 + 0.39443561090313295 + 0.39444697253112343 + 0.39445833456586699 + 0.39446969700738582 + 0.39448105985570331 + 0.39449242311084176 + 0.39450378677282349 + 0.39451515084167177 + 0.3945265153174099 + 0.3945378802000602 + 0.39454924548964604 + 0.39456061118619057 + 0.39457197728971521 + 0.39458334380024429 + 0.39459471071780006 + 0.39460607804240594 + 0.39461744577408314 + 0.39462881391285609 + 0.39464018245874788 + 0.3946515514117801 + 0.3946629207719769 + 0.39467429053936071 + 0.39468566071395367 + 0.39469703129577943 + 0.39470840228486098 + 0.39471977368122091 + 0.39473114548488236 + 0.39474251769586771 + 0.39475389031420038 + 0.39476526333990269 + 0.3947766367729989 + 0.39478801061351038 + 0.39479938486146043 + 0.3948107595168715 + 0.39482213457976884 + 0.39483351005017181 + 0.39484488592810574 + 0.39485626221359404 + 0.39486763890665699 + 0.39487901600731989 + 0.39489039351560529 + 0.39490177143153432 + 0.39491314975513248 + 0.39492452848642101 + 0.39493590762542247 + 0.39494728717216193 + 0.39495866712665995 + 0.39497004748894088 + 0.39498142825902699 + 0.39499280943694265 + 0.39500419102270823 + 0.39501557301634921 + 0.3950269554178869 + 0.39503833822734463 + 0.39504972144474576 + 0.39506110507011261 + 0.3950724891034687 + 0.39508387354483732 + 0.39509525839423987 + 0.39510664365170167 + 0.39511802931724321 + 0.39512941539088875 + 0.39514080187266171 + 0.39515218876258362 + 0.39516357606067759 + 0.39517496376696926 + 0.39518635188147777 + 0.39519774040422867 + 0.39520912933524427 + 0.39522051867454716 + 0.39523190842216049 + 0.39524329857810775 + 0.39525468914241041 + 0.39526608011509368 + 0.39527747149617914 + 0.39528886328569007 + 0.39530025548364994 + 0.39531164809008112 + 0.39532304110500605 + 0.39533443452844907 + 0.39534582836043264 + 0.39535722260097911 + 0.39536861725011202 + 0.39538001230785463 + 0.39539140777423049 + 0.39540280364926078 + 0.39541419993297022 + 0.39542559662538013 + 0.3954369937265157 + 0.39544839123639858 + 0.3954597891550512 + 0.39547118748249782 + 0.39548258621876109 + 0.39549398536386421 + 0.39550538491782977 + 0.39551678488068109 + 0.39552818525244066 + 0.39553958603313188 + 0.39555098722277821 + 0.39556238882140299 + 0.39557379082902777 + 0.39558519324567604 + 0.39559659607137204 + 0.39560799930613838 + 0.39561940294999637 + 0.39563080700297154 + 0.39564221146508538 + 0.3956536163363612 + 0.39566502161682249 + 0.39567642730649272 + 0.39568783340539332 + 0.39569923991354788 + 0.39571064683098067 + 0.39572205415771416 + 0.3957334618937699 + 0.39574487003917425 + 0.39575627859394674 + 0.39576768755811276 + 0.39577909693169377 + 0.39579050671471439 + 0.3958019169071969 + 0.39581332750916481 + 0.39582473852064065 + 0.39583614994164684 + 0.39584756177220887 + 0.3958589740123481 + 0.39587038666208718 + 0.39588179972144949 + 0.39589321319045945 + 0.39590462706913859 + 0.39591604135751046 + 0.39592745605559848 + 0.39593887116342608 + 0.39595028668101573 + 0.39596170260839014 + 0.39597311894557341 + 0.3959845356925884 + 0.39599595284945738 + 0.39600737041620387 + 0.39601878839285143 + 0.39603020677942347 + 0.39604162557594252 + 0.39605304478243208 + 0.39606446439891363 + 0.39607588442541264 + 0.39608730486195076 + 0.39609872570855131 + 0.39611014696523877 + 0.39612156863203479 + 0.39613299070896191 + 0.39614441319604543 + 0.39615583609330696 + 0.39616725940077008 + 0.39617868311845816 + 0.39619010724639381 + 0.3962015317845996 + 0.39621295673310086 + 0.39622438209191824 + 0.39623580786107615 + 0.39624723404059836 + 0.39625866063050608 + 0.39627008763082494 + 0.39628151504157655 + 0.39629294286278338 + 0.39630437109447098 + 0.39631579973665976 + 0.39632722878937443 + 0.39633865825263931 + 0.39635008812647515 + 0.39636151841090528 + 0.39637294910595544 + 0.39638438021164596 + 0.39639581172800253 + 0.39640724365504559 + 0.39641867599280078 + 0.39643010874128953 + 0.39644154190053649 + 0.39645297547056407 + 0.39646440945139499 + 0.39647584384305268 + 0.39648727864556071 + 0.39649871385894359 + 0.39651014948322189 + 0.39652158551842026 + 0.39653302196456119 + 0.39654445882166922 + 0.39655589608976582 + 0.39656733376887576 + 0.39657877185902135 + 0.39659021036022646 + 0.3966016492725134 + 0.39661308859590577 + 0.39662452833042722 + 0.39663596847610022 + 0.39664740903294948 + 0.39665885000099632 + 0.39667029138026466 + 0.39668173317077876 + 0.39669317537256032 + 0.39670461798563306 + 0.39671606101002027 + 0.39672750444574567 + 0.39673894829283196 + 0.39675039255130351 + 0.39676183722118197 + 0.39677328230249004 + 0.3967847277952532 + 0.39679617369949399 + 0.39680762001523501 + 0.39681906674250006 + 0.39683051388131141 + 0.39684196143169298 + 0.39685340939366909 + 0.39686485776726244 + 0.39687630655249467 + 0.39688775574939034 + 0.39689920535797307 + 0.39691065537826542 + 0.39692210581029097 + 0.39693355665407348 + 0.39694500790963533 + 0.39695645957700026 + 0.39696791165619094 + 0.39697936414723189 + 0.39699081705014566 + 0.39700227036495495 + 0.3970137240916834 + 0.39702517823035549 + 0.39703663278099305 + 0.39704808774362055 + 0.39705954311825964 + 0.39707099890493491 + 0.39708245510367002 + 0.39709391171448671 + 0.39710536873741031 + 0.39711682617246175 + 0.39712828401966643 + 0.39713974227904619 + 0.3971512009506255 + 0.39716266003442702 + 0.39717411953047443 + 0.39718557943879035 + 0.39719703975939846 + 0.39720850049232331 + 0.39721996163758561 + 0.39723142319521093 + 0.39724288516522199 + 0.39725434754764138 + 0.39726581034249375 + 0.39727727354980086 + 0.39728873716958713 + 0.39730020120187554 + 0.3973116656466894 + 0.39732313050405355 + 0.39733459577398855 + 0.39734606145652018 + 0.39735752755167003 + 0.39736899405946174 + 0.39738046097991997 + 0.39739192831306736 + 0.39740339605892672 + 0.39741486421752154 + 0.39742633278887662 + 0.39743780177301347 + 0.39744927116995588 + 0.39746074097972756 + 0.39747221120235199 + 0.3974836818378521 + 0.39749515288625137 + 0.39750662434757444 + 0.39751809622184225 + 0.39752956850908022 + 0.39754104120931022 + 0.39755251432255767 + 0.39756398784884356 + 0.39757546178819236 + 0.3975869361406279 + 0.39759841090617376 + 0.39760988608485165 + 0.39762136167668732 + 0.39763283768170238 + 0.39764431409992057 + 0.3976557909313656 + 0.39766726817606018 + 0.3976787458340289 + 0.39769022390529452 + 0.3977017023898799 + 0.39771318128780941 + 0.39772466059910605 + 0.39773614032379351 + 0.39774762046189521 + 0.39775910101343415 + 0.39777058197843296 + 0.39778206335691729 + 0.3977935451489088 + 0.39780502735443141 + 0.39781650997350776 + 0.39782799300616245 + 0.39783947645241929 + 0.39785096031230099 + 0.39786244458583037 + 0.39787392927303183 + 0.39788541437392749 + 0.39789689988854182 + 0.39790838581689975 + 0.39791987215902169 + 0.3979313589149337 + 0.39794284608465635 + 0.39795433366821642 + 0.3979658216656346 + 0.3979773100769366 + 0.39798879890214423 + 0.39800028814128124 + 0.3980117777943723 + 0.39802326786143821 + 0.39803475834250568 + 0.39804624923759641 + 0.39805774054673432 + 0.3980692322699419 + 0.39808072440724407 + 0.39809221695866359 + 0.39810370992422311 + 0.39811520330394751 + 0.39812669709786042 + 0.39813819130598366 + 0.39814968592834299 + 0.39816118096495906 + 0.39817267641585785 + 0.3981841722810619 + 0.39819566856059413 + 0.39820716525447925 + 0.39821866236273995 + 0.39823015988540011 + 0.3982416578224835 + 0.3982531561740118 + 0.39826465494001084 + 0.39827615412050338 + 0.39828765371551217 + 0.39829915372506208 + 0.39831065414917471 + 0.39832215498787604 + 0.39833365624118677 + 0.39834515790913261 + 0.39835665999173636 + 0.39836816248902196 + 0.39837966540101205 + 0.39839116872773039 + 0.39840267246920097 + 0.39841417662544731 + 0.39842568119649341 + 0.39843718618236101 + 0.39844869158307483 + 0.39846019739865868 + 0.39847170362913548 + 0.39848321027452993 + 0.39849471733486386 + 0.39850622481016201 + 0.39851773270044827 + 0.39852924100574449 + 0.39854074972607634 + 0.39855225886146567 + 0.39856376841193625 + 0.39857527837751305 + 0.39858678875821774 + 0.39859829955407516 + 0.39860981076510915 + 0.39862132239134157 + 0.39863283443279712 + 0.39864434688950068 + 0.39865585976147311 + 0.39866737304873923 + 0.39867888675132374 + 0.39869040086924856 + 0.39870191540253863 + 0.39871343035121659 + 0.39872494571530542 + 0.39873646149483077 + 0.39874797768981463 + 0.39875949430027985 + 0.39877101132625203 + 0.39878252876775433 + 0.39879404662480944 + 0.39880556489744207 + 0.39881708358567525 + 0.39882860268953174 + 0.39884012220903653 + 0.3988516421442112 + 0.3988631624950828 + 0.39887468326167219 + 0.39888620444400402 + 0.39889772604210139 + 0.39890924805598793 + 0.39892077048568764 + 0.39893229333122437 + 0.3989438165926209 + 0.39895534026990115 + 0.39896686436308898 + 0.39897838887220832 + 0.39898991379728282 + 0.39900143913833547 + 0.39901296489539023 + 0.39902449106847082 + 0.39903601765760022 + 0.39904754466280323 + 0.39905907208410279 + 0.39907059992152261 + 0.39908212817508681 + 0.39909365684481807 + 0.3991051859307404 + 0.39911671543287758 + 0.39912824535125452 + 0.39913977568589215 + 0.39915130643681729 + 0.39916283760405086 + 0.39917436918761873 + 0.39918590118754183 + 0.39919743360384702 + 0.39920896643655618 + 0.39922049968569223 + 0.39923203335128099 + 0.39924356743334544 + 0.39925510193190755 + 0.39926663684699298 + 0.39927817217862488 + 0.399289707926827 + 0.39930124409162226 + 0.39931278067303566 + 0.39932431767108895 + 0.39933585508580821 + 0.39934739291721627 + 0.399358931165336 + 0.39937046983019131 + 0.3993820089118062 + 0.39939354841020447 + 0.39940508832541022 + 0.3994166286574462 + 0.39942816940633641 + 0.3994397105721057 + 0.39945125215477606 + 0.39946279415437241 + 0.39947433657091858 + 0.39948587940443658 + 0.39949742265495247 + 0.39950896632248889 + 0.39952051040706893 + 0.39953205490871663 + 0.39954359982745669 + 0.3995551451633112 + 0.39956669091630609 + 0.39957823708646328 + 0.3995897836738066 + 0.39960133067836123 + 0.39961287810014989 + 0.39962442593919661 + 0.39963597419552443 + 0.39964752286915711 + 0.39965907196011963 + 0.39967062146843513 + 0.39968217139412737 + 0.3996937217372194 + 0.39970527249773613 + 0.39971682367570049 + 0.39972837527113653 + 0.39973992728406915 + 0.39975147971451924 + 0.39976303256251294 + 0.39977458582807412 + 0.39978613951122471 + 0.39979769361199069 + 0.39980924813039403 + 0.39982080306645973 + 0.39983235842021081 + 0.39984391419167209 + 0.39985547038086566 + 0.39986702698781745 + 0.3998785840125485 + 0.39989014145508567 + 0.39990169931545105 + 0.39991325759366758 + 0.39992481628976023 + 0.39993637540375404 + 0.39994793493566999 + 0.39995949488553395 + 0.39997105525337001 + 0.39998261603920016 + 0.39999417724304936 + 0.40000573886494173 + 0.40001730090489995 + 0.40002886336294841 + 0.40004042623911179 + 0.40005198953341325 + 0.40006355324587578 + 0.4000751173765234 + 0.40008668192538199 + 0.40009824689247281 + 0.40010981227782144 + 0.40012137808145032 + 0.40013294430338425 + 0.40014451094364722 + 0.40015607800226233 + 0.40016764547925354 + 0.4001792133746459 + 0.40019078168846145 + 0.40020235042072511 + 0.40021391957146002 + 0.40022548914069112 + 0.40023705912844149 + 0.40024862953473411 + 0.40026020035959498 + 0.40027177160304717 + 0.40028334326511372 + 0.40029491534581862 + 0.40030648784518691 + 0.40031806076324072 + 0.40032963410000599 + 0.4003412078555047 + 0.40035278202976199 + 0.4003643566228009 + 0.40037593163464641 + 0.40038750706532056 + 0.40039908291484944 + 0.40041065918325514 + 0.40042223587056258 + 0.40043381297679487 + 0.40044539050197703 + 0.40045696844613227 + 0.40046854680928445 + 0.40048012559145663 + 0.40049170479267499 + 0.40050328441296151 + 0.40051486445234025 + 0.40052644491083533 + 0.40053802578847175 + 0.40054960708527154 + 0.4005611888012599 + 0.40057277093646076 + 0.40058435349089822 + 0.40059593646459435 + 0.40060751985757531 + 0.40061910366986403 + 0.40063068790148465 + 0.40064227255246027 + 0.40065385762281597 + 0.40066544311257574 + 0.40067702902176272 + 0.40068861535040107 + 0.40070020209851476 + 0.40071178926612688 + 0.40072337685326354 + 0.40073496485994681 + 0.40074655328620185 + 0.40075814213205163 + 0.40076973139752037 + 0.40078132108263309 + 0.40079291118741184 + 0.40080450171188087 + 0.40081609265606616 + 0.40082768401998975 + 0.40083927580367584 + 0.40085086800714959 + 0.4008624606304339 + 0.40087405367355211 + 0.40088564713652913 + 0.40089724101939023 + 0.40090883532215643 + 0.40092043004485378 + 0.40093202518750554 + 0.40094362075013673 + 0.4009552167327694 + 0.40096681313542992 + 0.40097840995814016 + 0.4009900072009252 + 0.40100160486380843 + 0.40101320294681375 + 0.40102480144996733 + 0.40103640037328941 + 0.40104799971680799 + 0.40105959948054326 + 0.40107119966452232 + 0.40108280026876725 + 0.40109440129330332 + 0.40110600273815356 + 0.40111760460334311 + 0.4011292068888942 + 0.40114080959483278 + 0.40115241272118124 + 0.40116401626796555 + 0.40117562023520781 + 0.40118722462293233 + 0.40119882943116419 + 0.40121043465992651 + 0.40122204030924447 + 0.40123364637914016 + 0.40124525286963886 + 0.40125685978076564 + 0.4012684671125426 + 0.40128007486499401 + 0.40129168303814594 + 0.40130329163201961 + 0.4013149006466411 + 0.40132651008203374 + 0.40133811993822149 + 0.40134973021522863 + 0.40136134091307935 + 0.40137295203179768 + 0.401384563571407 + 0.40139617553193235 + 0.40140778791339687 + 0.40141940071582488 + 0.40143101393924141 + 0.40144262758366872 + 0.4014542416491329 + 0.40146585613565727 + 0.40147747104326492 + 0.40148908637198105 + 0.40150070212182887 + 0.40151231829283451 + 0.40152393488501914 + 0.40153555189840912 + 0.40154716933302748 + 0.40155878718889743 + 0.40157040546604628 + 0.40158202416449407 + 0.401593643284268 + 0.40160526282539044 + 0.40161688278788654 + 0.40162850317177934 + 0.4016401239770942 + 0.40165174520385422 + 0.4016633668520837 + 0.40167498892180786 + 0.40168661141304884 + 0.40169823432583185 + 0.40170985766018114 + 0.40172148141612091 + 0.40173310559367448 + 0.40174473019286677 + 0.40175635521372227 + 0.40176798065626418 + 0.40177960652051664 + 0.40179123280650386 + 0.40180285951425121 + 0.40181448664378072 + 0.40182611419511871 + 0.40183774216828744 + 0.40184937056331205 + 0.40186099938021691 + 0.40187262861902512 + 0.40188425827976199 + 0.40189588836245077 + 0.40190751886711656 + 0.40191914979378285 + 0.40193078114247366 + 0.40194241291321425 + 0.401954045106027 + 0.40196567772093705 + 0.40197731075796966 + 0.40198894421714715 + 0.40200057809849471 + 0.40201221240203555 + 0.40202384712779499 + 0.40203548227579622 + 0.40204711784606467 + 0.40205875383862438 + 0.40207039025349772 + 0.40208202709071095 + 0.40209366435028721 + 0.40210530203225103 + 0.40211694013662636 + 0.40212857866343776 + 0.40214021761270929 + 0.40215185698446432 + 0.40216349677872903 + 0.40217513699552482 + 0.40218677763487881 + 0.40219841869681344 + 0.40221006018135291 + 0.40222170208852248 + 0.40223334441834541 + 0.40224498717084706 + 0.40225663034604975 + 0.40226827394397963 + 0.40227991796466001 + 0.40229156240811426 + 0.40230320727436969 + 0.4023148525634464 + 0.40232649827537187 + 0.40233814441016835 + 0.40234979096786111 + 0.40236143794847451 + 0.40237308535203076 + 0.40238473317855711 + 0.40239638142807604 + 0.40240803010061282 + 0.40241967919619065 + 0.40243132871483384 + 0.40244297865656775 + 0.40245462902141477 + 0.40246627980940103 + 0.40247793102054991 + 0.40248958265488588 + 0.4025012347124331 + 0.40251288719321582 + 0.40252454009725747 + 0.40253619342458435 + 0.40254784717521885 + 0.40255950134918617 + 0.40257115594651072 + 0.40258281096721676 + 0.40259446641132768 + 0.40260612227886883 + 0.40261777856986342 + 0.40262943528433687 + 0.40264109242231155 + 0.40265274998381467 + 0.40266440796886871 + 0.40267606637749687 + 0.40268772520972668 + 0.40269938446557924 + 0.40271104414508102 + 0.4027227042482554 + 0.40273436477512675 + 0.40274602572571827 + 0.40275768710005738 + 0.40276934889816446 + 0.40278101112006787 + 0.40279267376578798 + 0.40280433683535199 + 0.4028160003287834 + 0.4028276642461055 + 0.40283932858734378 + 0.4028509933525225 + 0.40286265854166503 + 0.40287432415479668 + 0.40288599019194188 + 0.40289765665312505 + 0.40290932353836845 + 0.4029209908476995 + 0.40293265858114052 + 0.40294432673871705 + 0.40295599532045123 + 0.40296766432637066 + 0.40297933375649753 + 0.40299100361085627 + 0.40300267388947242 + 0.40301434459236912 + 0.40302601571957097 + 0.40303768727110212 + 0.40304935924698815 + 0.40306103164725243 + 0.40307270447191929 + 0.40308437772101313 + 0.40309605139455934 + 0.40310772549258139 + 0.40311940001510349 + 0.40313107496215028 + 0.40314275033374503 + 0.40315442612991509 + 0.40316610235068195 + 0.40317777899607105 + 0.40318945606610768 + 0.40320113356081427 + 0.40321281148021632 + 0.40322448982433917 + 0.40323616859320521 + 0.40324784778683986 + 0.4032595274052676 + 0.4032712074485128 + 0.40328288791659994 + 0.40329456880955333 + 0.4033062501273974 + 0.40331793187015674 + 0.40332961403785544 + 0.40334129663051738 + 0.40335297964816857 + 0.40336466309083163 + 0.40337634695853197 + 0.40338803125129408 + 0.40339971596914131 + 0.40341140111210005 + 0.40342308668019389 + 0.40343477267344613 + 0.40344645909188231 + 0.40345814593552681 + 0.40346983320440405 + 0.4034815208985385 + 0.4034932090179536 + 0.40350489756267582 + 0.40351658653272765 + 0.40352827592813445 + 0.40353996574891976 + 0.40355165599510984 + 0.40356334666672838 + 0.40357503776379877 + 0.40358672928634742 + 0.40359842123439676 + 0.40361011360797233 + 0.40362180640709761 + 0.4036334996317989 + 0.40364519328209986 + 0.4036568873580238 + 0.40366858185959731 + 0.40368027678684287 + 0.4036919721397858 + 0.40370366791845175 + 0.40371536412286302 + 0.40372706075304521 + 0.4037387578090228 + 0.40375045529082026 + 0.40376215319846104 + 0.40377385153197248 + 0.40378555029137631 + 0.40379724947669798 + 0.40380894908796183 + 0.40382064912519344 + 0.4038323495884153 + 0.40384405047765293 + 0.40385575179293171 + 0.40386745353427422 + 0.40387915570170801 + 0.40389085829525445 + 0.40390256131493907 + 0.40391426476078651 + 0.4039259686328221 + 0.40393767293106941 + 0.40394937765555389 + 0.40396108280629817 + 0.40397278838332962 + 0.40398449438666989 + 0.40399620081634535 + 0.4040079076723796 + 0.40401961495479816 + 0.40403132266362451 + 0.40404303079888315 + 0.40405473936060071 + 0.40406644834879951 + 0.40407815776350431 + 0.40408986760474036 + 0.40410157787253248 + 0.40411328856690404 + 0.40412499968788046 + 0.4041367112354865 + 0.40414842320974659 + 0.4041601356106852 + 0.40417184843832593 + 0.40418356169269437 + 0.40419527537381594 + 0.40420698948171324 + 0.40421870401641175 + 0.40423041897793616 + 0.4042421343663119 + 0.40425385018156157 + 0.40426556642371153 + 0.4042772830927856 + 0.4042890001888082 + 0.40430071771180487 + 0.4043124356617982 + 0.40432415403881478 + 0.40433587284287897 + 0.40434759207401461 + 0.40435931173224704 + 0.40437103181759992 + 0.40438275233009885 + 0.4043944732697673 + 0.40440619463663091 + 0.40441791643071412 + 0.40442963865204068 + 0.40444136130063696 + 0.40445308437652572 + 0.40446480787973343 + 0.40447653181028281 + 0.40448825616819911 + 0.40449998095350825 + 0.40451170616623267 + 0.40452343180639883 + 0.40453515787403055 + 0.4045468843691522 + 0.4045586112917896 + 0.40457033864196612 + 0.40458206641970745 + 0.40459379462503714 + 0.40460552325798077 + 0.40461725231856199 + 0.4046289818068064 + 0.40464071172273852 + 0.40465244206638301 + 0.40466417283776446 + 0.40467590403690651 + 0.40468763566383564 + 0.40469936771857562 + 0.40471110020115081 + 0.40472283311158608 + 0.40473456644990596 + 0.40474630021613595 + 0.40475803441029884 + 0.40476976903242201 + 0.40478150408252839 + 0.40479323956064328 + 0.40480497546679045 + 0.40481671180099549 + 0.40482844856328309 + 0.40484018575367786 + 0.40485192337220433 + 0.40486366141888613 + 0.40487539989374999 + 0.40488713879681953 + 0.40489887812811926 + 0.40491061788767496 + 0.40492235807551014 + 0.40493409869164954 + 0.40494583973611858 + 0.40495758120894221 + 0.40496932311014389 + 0.40498106543974932 + 0.40499280819778311 + 0.40500455138426988 + 0.40501629499923436 + 0.40502803904270107 + 0.40503978351469477 + 0.40505152841524006 + 0.40506327374436263 + 0.40507501950208513 + 0.40508676568843516 + 0.40509851230343535 + 0.40511025934711148 + 0.40512200681948818 + 0.40513375472058905 + 0.40514550305043978 + 0.40515725180906509 + 0.40516900099649056 + 0.40518075061273895 + 0.40519250065783674 + 0.40520425113180791 + 0.40521600203467778 + 0.40522775336647038 + 0.40523950512721107 + 0.40525125731692363 + 0.40526300993563485 + 0.40527476298336734 + 0.4052865164601468 + 0.40529827036599886 + 0.40531002470094624 + 0.40532177946501557 + 0.40533353465823069 + 0.40534529028061711 + 0.4053570463321986 + 0.40536880281300086 + 0.40538055972304859 + 0.4053923170623655 + 0.40540407483097823 + 0.40541583302890943 + 0.40542759165618597 + 0.40543935071283144 + 0.40545111019887059 + 0.40546287011432902 + 0.4054746304592306 + 0.40548639123360103 + 0.40549815243746484 + 0.40550991407084686 + 0.40552167613377177 + 0.40553343862626434 + 0.40554520154834922 + 0.40555696490005116 + 0.40556872868139593 + 0.40558049289240722 + 0.40559225753311062 + 0.40560402260353107 + 0.40561578810369209 + 0.40562755403362061 + 0.40563932039334022 + 0.40565108718287568 + 0.40566285440225175 + 0.40567462205149313 + 0.40568639013062657 + 0.40569815863967484 + 0.40570992757866259 + 0.40572169694761656 + 0.40573346674655975 + 0.40574523697551851 + 0.40575700763451583 + 0.40576877872357942 + 0.40578055024273102 + 0.40579232219199834 + 0.40580409457140415 + 0.40581586738097414 + 0.40582764062073323 + 0.40583941429070608 + 0.40585118839091738 + 0.4058629629213919 + 0.40587473788215561 + 0.40588651327323305 + 0.40589828909464803 + 0.40591006534642637 + 0.40592184202859277 + 0.40593361914117204 + 0.40594539668418994 + 0.40595717465766928 + 0.40596895306163672 + 0.40598073189611711 + 0.40599251116113522 + 0.40600429085671486 + 0.40601607098288178 + 0.40602785153966175 + 0.40603963252707859 + 0.40605141394515698 + 0.40606319579392292 + 0.40607497807339987 + 0.40608676078361389 + 0.40609854392459072 + 0.40611032749635312 + 0.40612211149892691 + 0.40613389593233773 + 0.40614568079660962 + 0.40615746609176817 + 0.40616925181783831 + 0.40618103797484384 + 0.40619282456281142 + 0.40620461158176502 + 0.4062163990317294 + 0.40622818691273038 + 0.40623997522479166 + 0.40625176396793916 + 0.4062635531421977 + 0.40627534274759203 + 0.40628713278414691 + 0.40629892325188832 + 0.40631071415083997 + 0.40632250548102772 + 0.40633429724247538 + 0.40634608943520978 + 0.40635788205925372 + 0.40636967511463407 + 0.40638146860137464 + 0.4063932625195012 + 0.40640505686903761 + 0.40641685165000974 + 0.40642864686244351 + 0.40644044250636152 + 0.40645223858179075 + 0.40646403508875512 + 0.40647583202728033 + 0.4064876293973913 + 0.40649942719911275 + 0.40651122543246865 + 0.40652302409748592 + 0.40653482319418915 + 0.40654662272260256 + 0.40655842268275055 + 0.4065702230746604 + 0.40658202389835568 + 0.40659382515386133 + 0.40660562684120222 + 0.40661742896040426 + 0.40662923151149222 + 0.40664103449449007 + 0.40665283790942452 + 0.40666464175631856 + 0.40667644603519898 + 0.40668825074609077 + 0.40670005588901864 + 0.40671186146400667 + 0.40672366747108046 + 0.4067354739102661 + 0.40674728078158739 + 0.40675908808506922 + 0.40677089582073844 + 0.40678270398861793 + 0.40679451258873367 + 0.40680632162111141 + 0.40681813108577419 + 0.40682994098274977 + 0.40684175131206107 + 0.40685356207373402 + 0.40686537326779448 + 0.40687718489426633 + 0.40688899695317443 + 0.40690080944454488 + 0.4069126223684022 + 0.40692443572477072 + 0.40693624951367713 + 0.40694806373514625 + 0.40695987838920217 + 0.40697169347586964 + 0.40698350899517566 + 0.40699532494714419 + 0.40700714133179999 + 0.40701895814916916 + 0.4070307753992754 + 0.40704259308214474 + 0.40705441119780211 + 0.40706622974627338 + 0.40707804872758258 + 0.40708986814175457 + 0.40710168798881624 + 0.40711350826879045 + 0.40712532898170339 + 0.40713715012758067 + 0.40714897170644637 + 0.40716079371832642 + 0.40717261616324685 + 0.40718443904123042 + 0.40719626235230416 + 0.40720808609649201 + 0.40721991027381893 + 0.40723173488431175 + 0.40724355992799449 + 0.4072553854048932 + 0.40726721131503063 + 0.40727903765843482 + 0.4072908644351298 + 0.40730269164513944 + 0.40731451928849061 + 0.4073263473652084 + 0.40733817587531568 + 0.40735000481884048 + 0.40736183419580768 + 0.40737366400624042 + 0.4073854942501654 + 0.40739732492760877 + 0.4074091560385924 + 0.40742098758314432 + 0.40743281956128846 + 0.4074446519730518 + 0.40745648481845642 + 0.40746831809753009 + 0.4074801518102969 + 0.40749198595678188 + 0.4075038205370109 + 0.40751565555100894 + 0.40752749099880109 + 0.40753932688041222 + 0.40755116319586737 + 0.40756299994519357 + 0.40757483712841375 + 0.40758667474555382 + 0.40759851279663994 + 0.40761035128169604 + 0.40762219020074808 + 0.40763402955382105 + 0.40764586934094005 + 0.40765770956212988 + 0.4076695502174178 + 0.40768139130682657 + 0.40769323283038233 + 0.40770507478811008 + 0.40771691718003583 + 0.40772876000618452 + 0.40774060326658124 + 0.40775244696125096 + 0.40776429109021861 + 0.4077761356535104 + 0.40778798065115124 + 0.40779982608316606 + 0.40781167194958007 + 0.40782351825041907 + 0.40783536498570833 + 0.40784721215547171 + 0.4078590597597363 + 0.40787090779852708 + 0.4078827562718681 + 0.40789460517978537 + 0.40790645452230406 + 0.40791830429944903 + 0.40793015451124742 + 0.40794200515772217 + 0.4079538562388994 + 0.40796570775480517 + 0.40797755970546351 + 0.40798941209090034 + 0.40800126491114086 + 0.408013118166211 + 0.4080249718561339 + 0.40803682598093766 + 0.40804868054064619 + 0.4080605355352836 + 0.40807239096487796 + 0.40808424682945238 + 0.40809610312903277 + 0.40810795986364429 + 0.40811981703331313 + 0.40813167463806405 + 0.4081435326779223 + 0.40815539115291205 + 0.40816725006306115 + 0.40817910940839169 + 0.408190969188932 + 0.40820282940470587 + 0.40821469005573846 + 0.40822655114205691 + 0.40823841266368421 + 0.40825027462064645 + 0.40826213701296982 + 0.40827399984067825 + 0.408285863103799 + 0.40829772680235504 + 0.40830959093637348 + 0.40832145550587928 + 0.40833332051089777 + 0.40834518595145386 + 0.40835705182757276 + 0.40836891813928045 + 0.40838078488660212 + 0.40839265206956388 + 0.4084045196881898 + 0.40841638774250488 + 0.40842825623253642 + 0.40844012515830841 + 0.40845199451984693 + 0.40846386431717613 + 0.40847573455032316 + 0.4084876052193111 + 0.408499476324168 + 0.40851134786491711 + 0.40852321984158535 + 0.40853509225419604 + 0.4085469651027771 + 0.40855883838735291 + 0.40857071210794743 + 0.40858258626458877 + 0.40859446085730006 + 0.40860633588610756 + 0.40861821135103615 + 0.40863008725211131 + 0.40864196358935984 + 0.40865384036280594 + 0.408665717572475 + 0.40867759521839286 + 0.4086894733005848 + 0.40870135181907591 + 0.40871323077389138 + 0.4087251101650573 + 0.40873698999259989 + 0.40874887025654222 + 0.4087607509569125 + 0.40877263209373282 + 0.40878451366703239 + 0.40879639567683329 + 0.40880827812316278 + 0.4088201610060469 + 0.4088320443255089 + 0.40884392808157594 + 0.40885581227427309 + 0.40886769690362568 + 0.40887958196965968 + 0.40889146747239941 + 0.40890335341187084 + 0.40891523978810046 + 0.40892712660111213 + 0.40893901385093223 + 0.40895090153758484 + 0.40896278966109811 + 0.40897467822149525 + 0.40898656721880255 + 0.40899845665304502 + 0.40901034652424895 + 0.40902223683244038 + 0.40903412757764168 + 0.40904601875988195 + 0.40905791037918449 + 0.40906980243557634 + 0.4090816949290817 + 0.40909358785972588 + 0.40910548122753493 + 0.4091173750325352 + 0.40912926927475074 + 0.40914116395420785 + 0.40915305907093175 + 0.40916495462494856 + 0.40917685061628251 + 0.40918874704495989 + 0.4092006439110068 + 0.40921254121444756 + 0.40922443895530825 + 0.40923633713361524 + 0.40924823574939251 + 0.40926013480266654 + 0.40927203429346237 + 0.40928393422180631 + 0.40929583458772251 + 0.40930773539123833 + 0.40931963663237791 + 0.40933153831116736 + 0.40934344042763116 + 0.40935534298179627 + 0.40936724597368807 + 0.40937914940333187 + 0.4093910532707527 + 0.409402957575976 + 0.40941486231902779 + 0.40942676749993456 + 0.4094386731187204 + 0.40945057917541156 + 0.40946248567003329 + 0.40947439260261193 + 0.40948629997317154 + 0.40949820778173951 + 0.40951011602834009 + 0.40952202471299842 + 0.40953393383574199 + 0.40954584339659478 + 0.4095577533955842 + 0.40956966383273247 + 0.40958157470806889 + 0.40959348602161666 + 0.40960539777340216 + 0.40961730996345047 + 0.40962922259178808 + 0.40964113565844007 + 0.4096530491634317 + 0.40966496310678946 + 0.40967687748853848 + 0.40968879230870497 + 0.40970070756731236 + 0.4097126232643889 + 0.40972453939995868 + 0.40973645597404817 + 0.40974837298668265 + 0.40976029043788725 + 0.40977220832768757 + 0.40978412665611058 + 0.40979604542318065 + 0.40980796462892322 + 0.40981988427336546 + 0.40983180435653055 + 0.409843724878447 + 0.40985564583913803 + 0.40986756723863099 + 0.4098794890769501 + 0.40989141135412172 + 0.40990333407017204 + 0.40991525722512551 + 0.40992718081900836 + 0.40993910485184698 + 0.40995102932366662 + 0.40996295423449158 + 0.40997487958434919 + 0.40998680537326376 + 0.4099987316012626 + 0.41001065826837013 + 0.41002258537461256 + 0.41003451292001519 + 0.41004644090460352 + 0.41005836932840362 + 0.41007029819144103 + 0.41008222749374296 + 0.41009415723533282 + 0.41010608741623583 + 0.41011801803648046 + 0.41012994909609007 + 0.41014188059509182 + 0.41015381253351019 + 0.41016574491137137 + 0.41017767772870195 + 0.41018961098552603 + 0.41020154468187114 + 0.41021347881776155 + 0.4102254133932226 + 0.41023734840828163 + 0.410249283862963 + 0.41026121975729313 + 0.41027315609129827 + 0.41028509286500281 + 0.41029703007843316 + 0.41030896773161363 + 0.4103209058245727 + 0.41033284435733453 + 0.41034478332992463 + 0.4103567227423694 + 0.41036866259469407 + 0.41038060288692502 + 0.41039254361908678 + 0.41040448479120661 + 0.41041642640330883 + 0.41042836845542002 + 0.41044031094756633 + 0.41045225387977224 + 0.41046419725206418 + 0.41047614106446756 + 0.41048808531700953 + 0.41050003000971469 + 0.4105119751426084 + 0.41052392071571808 + 0.410535866729067 + 0.41054781318268263 + 0.41055976007659045 + 0.41057170741081661 + 0.41058365518538681 + 0.41059560340032525 + 0.41060755205565941 + 0.4106195011514156 + 0.41063145068761742 + 0.41064340066429206 + 0.41065535108146606 + 0.41066730193916384 + 0.41067925323741067 + 0.41069120497623407 + 0.41070315715565953 + 0.41071510977571224 + 0.41072706283641791 + 0.4107390163378028 + 0.41075097027989221 + 0.4107629246627118 + 0.41077487948628794 + 0.41078683475064792 + 0.41079879045581419 + 0.41081074660181532 + 0.41082270318867475 + 0.41083466021642179 + 0.41084661768507891 + 0.41085857559467354 + 0.4108705339452311 + 0.41088249273677807 + 0.41089445196933894 + 0.41090641164294106 + 0.41091837175760987 + 0.41093033231336989 + 0.41094229331024856 + 0.41095425474827141 + 0.41096621662746363 + 0.41097817894785083 + 0.41099014170946052 + 0.41100210491231709 + 0.41101406855644712 + 0.41102603264187576 + 0.41103799716862977 + 0.41104996213673461 + 0.41106192754621551 + 0.41107389339710015 + 0.41108585968941286 + 0.41109782642317927 + 0.41110979359842575 + 0.41112176121517868 + 0.4111337292734637 + 0.41114569777330628 + 0.41115766671473281 + 0.41116963609776869 + 0.41118160592243963 + 0.41119357618877295 + 0.41120554689679217 + 0.41121751804652584 + 0.41122948963799733 + 0.41124146167123526 + 0.41125343414626292 + 0.4112654070631081 + 0.41127738042179601 + 0.4112893542223523 + 0.4113013284648035 + 0.41131330314917397 + 0.41132527827549137 + 0.411337253843782 + 0.41134922985406958 + 0.41136120630638151 + 0.41137318320074429 + 0.41138516053718244 + 0.4113971383157225 + 0.41140911653639095 + 0.41142109519921233 + 0.41143307430421416 + 0.41144505385142188 + 0.41145703384086013 + 0.41146901427255739 + 0.41148099514653708 + 0.41149297646282684 + 0.41150495822145122 + 0.41151694042243758 + 0.41152892306581174 + 0.411540906151599 + 0.41155288967982584 + 0.41156487365051703 + 0.41157685806369987 + 0.41158884291940007 + 0.4116008282176431 + 0.41161281395845545 + 0.41162480014186281 + 0.41163678676789156 + 0.41164877383656734 + 0.41166076134791568 + 0.41167274930196324 + 0.41168473769873626 + 0.41169672653825967 + 0.41170871582056073 + 0.4117207055456652 + 0.41173269571359744 + 0.41174468632438521 + 0.41175667737805499 + 0.41176866887463026 + 0.41178066081413972 + 0.41179265319660785 + 0.41180464602206129 + 0.41181663929052453 + 0.4118286330020261 + 0.4118406271565907 + 0.41185262175424392 + 0.41186461679501324 + 0.41187661227892325 + 0.41188860820600054 + 0.41190060457627065 + 0.41191260138976027 + 0.41192459864649494 + 0.41193659634650115 + 0.41194859448980564 + 0.4119605930764329 + 0.41197259210640952 + 0.41198459157976119 + 0.41199659149651541 + 0.41200859185669675 + 0.41202059266033192 + 0.41203259390744745 + 0.41204459559806794 + 0.41205659773222003 + 0.41206860030993125 + 0.41208060333122531 + 0.41209260679613074 + 0.41210461070467119 + 0.41211661505687419 + 0.4121286198527655 + 0.41214062509237165 + 0.41215263077571718 + 0.41216463690282978 + 0.41217664347373517 + 0.41218865048845887 + 0.41220065794702843 + 0.41221266584946764 + 0.412224674195804 + 0.4122366829860642 + 0.41224869222027277 + 0.41226070189845754 + 0.41227271202064297 + 0.41228472258685567 + 0.41229673359712243 + 0.41230874505146881 + 0.41232075694992149 + 0.41233276929250501 + 0.41234478207924813 + 0.41235679531017444 + 0.41236880898531159 + 0.41238082310468421 + 0.41239283766831997 + 0.41240485267624444 + 0.41241686812848349 + 0.41242888402506356 + 0.41244090036601144 + 0.41245291715135163 + 0.41246493438111193 + 0.41247695205531698 + 0.41248897017399344 + 0.41250098873716889 + 0.41251300774486821 + 0.41252502719711681 + 0.41253704709394151 + 0.41254906743536995 + 0.41256108822142579 + 0.41257310945213665 + 0.41258513112752843 + 0.41259715324762758 + 0.41260917581245982 + 0.41262119882205195 + 0.4126332222764294 + 0.41264524617561815 + 0.41265727051964579 + 0.41266929530853685 + 0.41268132054231821 + 0.4126933462210165 + 0.41270537234465643 + 0.41271739891326664 + 0.41272942592687095 + 0.41274145338549689 + 0.41275348128917028 + 0.41276550963791775 + 0.41277753843176512 + 0.41278956767073793 + 0.41280159735486299 + 0.41281362748416706 + 0.41282565805867572 + 0.41283768907841573 + 0.41284972054341179 + 0.41286175245369172 + 0.41287378480928116 + 0.41288581761020682 + 0.41289785085649433 + 0.41290988454816957 + 0.41292191868526024 + 0.41293395326779098 + 0.41294598829578966 + 0.41295802376928087 + 0.41297005968829031 + 0.41298209605284686 + 0.41299413286297521 + 0.41300617011870205 + 0.41301820782005216 + 0.41303024596705412 + 0.41304228455973296 + 0.41305432359811423 + 0.41306636308222466 + 0.41307840301209209 + 0.4130904433877402 + 0.41310248420919682 + 0.41311452547648869 + 0.41312656718964141 + 0.41313860934868091 + 0.41315065195363276 + 0.41316269500452502 + 0.41317473850138314 + 0.41318678244423401 + 0.41319882683310244 + 0.41321087166801618 + 0.41322291694900093 + 0.41323496267608245 + 0.41324700884928856 + 0.413259055468644 + 0.41327110253417559 + 0.4132831500459101 + 0.41329519800387327 + 0.41330724640809086 + 0.41331929525859074 + 0.41333134455539861 + 0.41334339429853922 + 0.41335544448804151 + 0.41336749512393012 + 0.4133795462062318 + 0.41339159773497253 + 0.41340364971017995 + 0.413415702131878 + 0.41342775500009532 + 0.41343980831485666 + 0.413451862076189 + 0.41346391628411905 + 0.41347597093867267 + 0.4134880260398765 + 0.41350008158775658 + 0.41351213758233957 + 0.4135241940236512 + 0.41353625091171758 + 0.41354830824656713 + 0.41356036602822399 + 0.41357242425671575 + 0.4135844829320684 + 0.41359654205430768 + 0.41360860162346141 + 0.41362066163955441 + 0.41363272210261348 + 0.41364478301266544 + 0.41365684436973721 + 0.4136689061738536 + 0.41368096842504237 + 0.41369303112332828 + 0.41370509426873936 + 0.41371715786130236 + 0.41372922190104211 + 0.41374128638798535 + 0.41375335132215918 + 0.41376541670358924 + 0.41377748253230229 + 0.41378954880832441 + 0.41380161553168238 + 0.41381368270240287 + 0.41382575032051094 + 0.41383781838603545 + 0.41384988689900015 + 0.41386195585943381 + 0.4138740252673605 + 0.41388609512280899 + 0.41389816542580404 + 0.41391023617637163 + 0.41392230737454061 + 0.41393437902033492 + 0.41394645111378325 + 0.4139585236549097 + 0.41397059664374186 + 0.41398267008030676 + 0.41399474396462932 + 0.4140068182967373 + 0.41401889307665668 + 0.41403096830441433 + 0.414043043980036 + 0.41405512010354878 + 0.41406719667497838 + 0.41407927369435177 + 0.41409135116169576 + 0.4141034290770354 + 0.41411550744039949 + 0.41412758625181184 + 0.41413966551130055 + 0.41415174521889231 + 0.41416382537461205 + 0.41417590597848775 + 0.41418798703054632 + 0.41420006853081265 + 0.41421215047931365 + 0.41422423287607613 + 0.41423631572112701 + 0.4142483990144914 + 0.41426048275619698 + 0.41427256694627074 + 0.41428465158473771 + 0.41429673667162464 + 0.41430882220695858 + 0.41432090819076622 + 0.41433299462307382 + 0.41434508150390814 + 0.41435716883329499 + 0.41436925661126051 + 0.41438134483783251 + 0.41439343351303787 + 0.41440552263690067 + 0.41441761220945078 + 0.41442970223071202 + 0.41444179270071158 + 0.41445388361947721 + 0.41446597498703286 + 0.41447806680340854 + 0.41449015906862813 + 0.41450225178271866 + 0.41451434494570694 + 0.41452643855762011 + 0.414538532618484 + 0.41455062712832552 + 0.41456272208717071 + 0.41457481749504654 + 0.41458691335197995 + 0.41459900965799679 + 0.41461110641312321 + 0.41462320361738703 + 0.41463530127081538 + 0.41464739937343198 + 0.41465949792526602 + 0.41467159692634237 + 0.41468369637668895 + 0.41469579627633285 + 0.41470789662529806 + 0.41471999742361337 + 0.41473209867130495 + 0.41474420036839871 + 0.41475630251492163 + 0.41476840511090068 + 0.41478050815636192 + 0.4147926116513323 + 0.4148047155958387 + 0.41481681998990727 + 0.41482892483356393 + 0.41484103012683571 + 0.41485313586975053 + 0.41486524206233444 + 0.41487734870461251 + 0.41488945579661263 + 0.41490156333836187 + 0.4149136713298861 + 0.41492577977121259 + 0.41493788866236719 + 0.41494999800337579 + 0.41496210779426657 + 0.41497421803506657 + 0.41498632872580066 + 0.41499843986649698 + 0.41501055145718047 + 0.41502266349787914 + 0.41503477598862015 + 0.41504688892942937 + 0.41505900232033199 + 0.41507111616135783 + 0.41508323045253104 + 0.41509534519387864 + 0.41510746038542756 + 0.41511957602720606 + 0.415131692119238 + 0.41514380866155254 + 0.41515592565417447 + 0.41516804309713118 + 0.41518016099044946 + 0.41519227933415542 + 0.41520439812827709 + 0.41521651737284065 + 0.415228637067872 + 0.41524075721339726 + 0.41525287780944542 + 0.41526499885604157 + 0.41527712035321285 + 0.41528924230098513 + 0.41530136469938667 + 0.41531348754844244 + 0.41532561084818048 + 0.41533773459862788 + 0.41534985879980973 + 0.41536198345175307 + 0.41537410855448598 + 0.41538623410803355 + 0.41539836011242387 + 0.41541048656768198 + 0.4154226134738368 + 0.41543474083091375 + 0.41544686863893865 + 0.41545899689794069 + 0.41547112560794497 + 0.41548325476897752 + 0.41549538438106637 + 0.41550751444423878 + 0.41551964495851967 + 0.41553177592393725 + 0.41554390734051755 + 0.41555603920828765 + 0.41556817152727488 + 0.41558030429750392 + 0.41559243751900421 + 0.41560457119180066 + 0.41561670531592054 + 0.41562883989139082 + 0.41564097491823776 + 0.41565311039648928 + 0.41566524632617163 + 0.41567738270730986 + 0.41568951953993311 + 0.41570165682406757 + 0.41571379455973917 + 0.41572593274697517 + 0.41573807138580371 + 0.41575021047624883 + 0.41576235001833978 + 0.41577449001210148 + 0.41578663045756231 + 0.41579877135474819 + 0.41581091270368631 + 0.41582305450440288 + 0.41583519675692598 + 0.41584733946128083 + 0.41585948261749545 + 0.41587162622559504 + 0.41588377028560969 + 0.41589591479756266 + 0.41590805976148199 + 0.41592020517739492 + 0.41593235104532839 + 0.41594449736530886 + 0.41595664413736327 + 0.41596879136151887 + 0.41598093903780187 + 0.41599308716623817 + 0.41600523574685716 + 0.41601738477968297 + 0.4160295342647447 + 0.41604168420206761 + 0.41605383459167983 + 0.41606598543360751 + 0.4160781367278768 + 0.41609028847451596 + 0.41610244067354996 + 0.41611459332500927 + 0.41612674642891689 + 0.41613889998530101 + 0.41615105399418889 + 0.4161632084556075 + 0.41617536336958333 + 0.4161875187361434 + 0.41619967455531387 + 0.41621183082712304 + 0.4162239875515969 + 0.41623614472876191 + 0.41624830235864607 + 0.41626046044127574 + 0.41627261897667794 + 0.416284777964879 + 0.41629693740590606 + 0.41630909729978738 + 0.41632125764654815 + 0.41633341844621552 + 0.41634557969881675 + 0.41635774140437898 + 0.41636990356292858 + 0.41638206617449353 + 0.4163942292390993 + 0.41640639275677299 + 0.41641855672754285 + 0.41643072115143498 + 0.41644288602847579 + 0.41645505135869337 + 0.41646721714211399 + 0.41647938337876389 + 0.41649155006867133 + 0.41650371721186241 + 0.41651588480836454 + 0.41652805285820482 + 0.41654022136140961 + 0.41655239031800606 + 0.41656455972802037 + 0.41657672959148095 + 0.41658889990841391 + 0.4166010706788475 + 0.41661324190280596 + 0.41662541358031863 + 0.41663758571141168 + 0.41664975829611245 + 0.41666193133444707 + 0.4166741048264429 + 0.41668627877212716 + 0.41669845317152709 + 0.41671062802467002 + 0.41672280333158107 + 0.41673497909228868 + 0.41674715530681905 + 0.41675933197520043 + 0.41677150909745919 + 0.41678368667362231 + 0.41679586470371544 + 0.4168080431877676 + 0.41682022212580511 + 0.41683240151785539 + 0.41684458136394364 + 0.41685676166409907 + 0.4168689424183481 + 0.41688112362671781 + 0.4168933052892338 + 0.41690548740592404 + 0.41691766997681601 + 0.41692985300193691 + 0.41694203648131306 + 0.41695422041497088 + 0.41696640480293956 + 0.41697858964524431 + 0.41699077494191261 + 0.41700296069297171 + 0.41701514689844776 + 0.41702733355836935 + 0.41703952067276151 + 0.41705170824165477 + 0.41706389626507234 + 0.41707608474304353 + 0.4170882736755937 + 0.41710046306275211 + 0.41711265290454419 + 0.41712484320099708 + 0.41713703395213925 + 0.41714922515799596 + 0.41716141681859564 + 0.41717360893396449 + 0.41718580150412993 + 0.41719799452911921 + 0.41721018800895976 + 0.41722238194367778 + 0.4172345763333008 + 0.41724677117785497 + 0.41725896647736982 + 0.41727116223186944 + 0.41728335844138337 + 0.41729555510593802 + 0.41730775222555949 + 0.41731994980027537 + 0.41733214783011385 + 0.41734434631510031 + 0.41735654525526311 + 0.41736874465062984 + 0.41738094450122548 + 0.41739314480707962 + 0.41740534556821751 + 0.41741754678466764 + 0.41742974845645525 + 0.41744195058360983 + 0.41745415316615664 + 0.4174663562041242 + 0.41747855969753866 + 0.41749076364642762 + 0.41750296805081827 + 0.41751517291073709 + 0.41752737822621244 + 0.4175395839972707 + 0.41755179022393929 + 0.41756399690624452 + 0.41757620404421486 + 0.41758841163787663 + 0.41760061968725731 + 0.41761282819238416 + 0.4176250371532837 + 0.41763724656998319 + 0.41764945644251122 + 0.417661666770893 + 0.417673877555157 + 0.41768608879532965 + 0.41769830049143936 + 0.41771051264351156 + 0.41772272525157461 + 0.41773493831565583 + 0.41774715183578182 + 0.41775936581197992 + 0.41777158024427641 + 0.41778379513270086 + 0.41779601047727877 + 0.41780822627803732 + 0.41782044253500517 + 0.41783265924820756 + 0.41784487641767193 + 0.41785709404342691 + 0.4178693121254986 + 0.41788153066391476 + 0.41789374965870163 + 0.41790596910988875 + 0.4179181890175005 + 0.41793040938156623 + 0.41794263020211148 + 0.41795485147916583 + 0.4179670732127535 + 0.41797929540290496 + 0.41799151804964479 + 0.41800374115300026 + 0.41801596471300106 + 0.4180281887296724 + 0.41804041320304186 + 0.41805263813313787 + 0.41806486351998595 + 0.41807708936361443 + 0.41808931566405089 + 0.4181015424213218 + 0.41811376963545349 + 0.41812599730647554 + 0.41813822543441337 + 0.41815045401929551 + 0.41816268306114945 + 0.4181749125600005 + 0.4181871425158773 + 0.41819937292880727 + 0.41821160379881789 + 0.41822383512593464 + 0.418236066910187 + 0.4182482991516015 + 0.41826053185020551 + 0.41827276500602562 + 0.4182849986190903 + 0.41829723268942615 + 0.41830946721706042 + 0.41832170220202081 + 0.41833393764433374 + 0.41834617354402764 + 0.4183584099011291 + 0.41837064671566676 + 0.41838288398766588 + 0.41839512171715498 + 0.41840735990416178 + 0.41841959854871252 + 0.41843183765083497 + 0.41844407721055643 + 0.41845631722790461 + 0.41846855770290675 + 0.41848079863559073 + 0.41849304002598187 + 0.41850528187410962 + 0.41851752418000066 + 0.41852976694368244 + 0.41854201016518144 + 0.41855425384452632 + 0.41856649798174345 + 0.41857874257686045 + 0.41859098762990488 + 0.41860323314090431 + 0.41861547910988617 + 0.41862772553687705 + 0.41863997242190448 + 0.41865221976499706 + 0.41866446756618131 + 0.41867671582548371 + 0.41868896454293281 + 0.41870121371855529 + 0.41871346335237963 + 0.41872571344443232 + 0.41873796399474089 + 0.41875021500333315 + 0.41876246647023541 + 0.41877471839547631 + 0.41878697077908245 + 0.41879922362108229 + 0.41881147692150145 + 0.41882373068036965 + 0.41883598489771229 + 0.41884823957355799 + 0.41886049470793324 + 0.41887275030086668 + 0.41888500635238396 + 0.41889726286251455 + 0.41890951983128405 + 0.41892177725872221 + 0.41893403514485333 + 0.41894629348970724 + 0.41895855229331147 + 0.41897081155569149 + 0.41898307127687595 + 0.4189953314568936 + 0.41900759209576977 + 0.41901985319353224 + 0.41903211475020857 + 0.41904437676582729 + 0.4190566392404152 + 0.41906890217399961 + 0.4190811655666084 + 0.4190934294182691 + 0.41910569372900713 + 0.41911795849885336 + 0.41913022372783332 + 0.4191424894159736 + 0.41915475556330378 + 0.41916702216984952 + 0.41917928923563952 + 0.41919155676070124 + 0.41920382474506246 + 0.4192160931887487 + 0.41922836209178865 + 0.41924063145421192 + 0.41925290127604209 + 0.41926517155730991 + 0.41927744229804093 + 0.41928971349826272 + 0.4193019851580051 + 0.41931425727729255 + 0.41932652985615476 + 0.41933880289461745 + 0.4193510763927103 + 0.41936335035045874 + 0.41937562476789153 + 0.41938789964503537 + 0.41940017498191889 + 0.41941245077856876 + 0.41942472703501255 + 0.41943700375127901 + 0.41944928092739375 + 0.41946155856338552 + 0.41947383665928184 + 0.41948611521510942 + 0.41949839423089708 + 0.41951067370667133 + 0.41952295364246078 + 0.41953523403829129 + 0.41954751489419245 + 0.41955979621019096 + 0.41957207798631352 + 0.41958436022258866 + 0.41959664291904419 + 0.41960892607570571 + 0.41962120969260414 + 0.41963349376976494 + 0.41964577830721483 + 0.41965806330498345 + 0.41967034876309767 + 0.41968263468158407 + 0.41969492106047124 + 0.41970720789978705 + 0.41971949519955931 + 0.41973178295981434 + 0.41974407118058021 + 0.41975635986188448 + 0.41976864900375582 + 0.41978093860621996 + 0.41979322866930668 + 0.4198055191930416 + 0.41981781017745345 + 0.41983010162256906 + 0.41984239352841696 + 0.41985468589502506 + 0.41986697872241996 + 0.41987927201062941 + 0.41989156575968117 + 0.41990385996960289 + 0.41991615464042337 + 0.41992844977216837 + 0.41994074536486647 + 0.41995304141854561 + 0.41996533793323243 + 0.41997763490895557 + 0.41998993234574195 + 0.42000223024361916 + 0.42001452860261601 + 0.42002682742276032 + 0.42003912670407667 + 0.42005142644659599 + 0.42006372665034586 + 0.42007602731535215 + 0.42008832844164262 + 0.42010063002924697 + 0.42011293207819089 + 0.42012523458850332 + 0.42013753756021088 + 0.42014984099334135 + 0.42016214488792364 + 0.42017444924398423 + 0.4201867540615512 + 0.42019905934065321 + 0.4202113650813149 + 0.42022367128356819 + 0.42023597794743778 + 0.42024828507295253 + 0.4202605926601391 + 0.42027290070902645 + 0.42028520921964224 + 0.42029751819201322 + 0.42030982762616836 + 0.42032213752213415 + 0.42033444787993968 + 0.42034675869961052 + 0.42035906998117661 + 0.42037138172466576 + 0.42038369393010266 + 0.42039600659751808 + 0.42040831972693904 + 0.42042063331839297 + 0.42043294737190817 + 0.42044526188751097 + 0.42045757686523155 + 0.42046989230509446 + 0.42048220820712967 + 0.42049452457136494 + 0.42050684139782812 + 0.42051915868654594 + 0.42053147643754629 + 0.42054379465085695 + 0.42055611332650583 + 0.42056843246452263 + 0.42058075206493128 + 0.42059307212776365 + 0.42060539265304336 + 0.42061771364080242 + 0.42063003509106567 + 0.42064235700386082 + 0.42065467937921885 + 0.42066700221716363 + 0.4206793255177258 + 0.42069164928093122 + 0.42070397350680788 + 0.4207162981953857 + 0.42072862334669031 + 0.42074094896074965 + 0.42075327503759263 + 0.42076560157724702 + 0.42077792857973872 + 0.42079025604509862 + 0.42080258397335146 + 0.42081491236452828 + 0.42082724121865378 + 0.42083957053575688 + 0.4208519003158665 + 0.4208642305590094 + 0.42087656126521256 + 0.42088889243450578 + 0.42090122406691605 + 0.42091355616247217 + 0.4209258887211999 + 0.42093822174312834 + 0.42095055522828423 + 0.4209628891766975 + 0.42097522358839601 + 0.42098755846340463 + 0.42099989380175334 + 0.42101222960347101 + 0.42102456586858339 + 0.42103690259711946 + 0.42104923978910624 + 0.42106157744457251 + 0.42107391556354612 + 0.42108625414605516 + 0.42109859319212634 + 0.42111093270178868 + 0.42112327267506999 + 0.42113561311199627 + 0.42114795401259847 + 0.42116029537690336 + 0.42117263720493686 + 0.42118497949672906 + 0.42119732225230777 + 0.42120966547170091 + 0.42122200915493424 + 0.42123435330203807 + 0.42124669791304004 + 0.42125904298796718 + 0.42127138852684837 + 0.42128373452970952 + 0.42129608099658156 + 0.42130842792749057 + 0.42132077532246437 + 0.42133312318153088 + 0.42134547150471907 + 0.42135782029205687 + 0.42137016954357026 + 0.42138251925928921 + 0.42139486943924054 + 0.42140722008345338 + 0.42141957119195561 + 0.42143192276477309 + 0.42144427480193586 + 0.42145662730347083 + 0.4214689802694071 + 0.42148133369977037 + 0.42149368759459188 + 0.4215060419538964 + 0.42151839677771508 + 0.42153075206607266 + 0.42154310781899929 + 0.42155546403652289 + 0.42156782071866938 + 0.42158017786546881 + 0.42159253547694808 + 0.4216048935531363 + 0.42161725209406131 + 0.42162961109975028 + 0.4216419705702309 + 0.42165433050553136 + 0.42166669090568171 + 0.4216790517707078 + 0.42169141310063757 + 0.42170377489549915 + 0.42171613715532263 + 0.42172849988013378 + 0.42174086306996067 + 0.42175322672483334 + 0.42176559084477688 + 0.42177795542982105 + 0.4217903204799951 + 0.42180268599532394 + 0.42181505197583852 + 0.4218274184215639 + 0.42183978533253219 + 0.4218521527087673 + 0.42186452055030033 + 0.42187688885715718 + 0.42188925762936696 + 0.4219016268669577 + 0.42191399656995732 + 0.42192636673839395 + 0.42193873737229559 + 0.42195110847169037 + 0.42196348003660517 + 0.42197585206707106 + 0.42198822456311308 + 0.42200059752476027 + 0.42201297095204077 + 0.4220253448449835 + 0.4220377192036156 + 0.42205009402796506 + 0.42206246931805985 + 0.42207484507392917 + 0.42208722129559995 + 0.42209959798310026 + 0.42211197513645932 + 0.42212435275570392 + 0.42213673084086339 + 0.42214910939196565 + 0.42216148840903767 + 0.42217386789210865 + 0.42218624784120562 + 0.42219862825635873 + 0.42221100913759391 + 0.42222339048494029 + 0.4222357722984259 + 0.42224815457807896 + 0.42226053732392743 + 0.4222729205359993 + 0.42228530421432187 + 0.42229768835892606 + 0.42231007296983702 + 0.42232245804708479 + 0.42233484359069662 + 0.42234722960070037 + 0.4223596160771253 + 0.42237200301999833 + 0.42238439042934778 + 0.42239677830520361 + 0.42240916664759193 + 0.42242155545654086 + 0.42243394473208051 + 0.42244633447423685 + 0.4224587246830393 + 0.42247111535851573 + 0.42248350650069527 + 0.42249589810960408 + 0.42250829018527125 + 0.42252068272772592 + 0.42253307573699422 + 0.42254546921310626 + 0.42255786315609006 + 0.42257025756597288 + 0.42258265244278281 + 0.42259504778654899 + 0.42260744359729946 + 0.42261983987506146 + 0.4226322366198651 + 0.42264463383173645 + 0.42265703151070472 + 0.42266942965679799 + 0.42268182827004558 + 0.42269422735047324 + 0.42270662689811156 + 0.42271902691298735 + 0.42273142739512898 + 0.42274382834456553 + 0.4227562297613251 + 0.42276863164543488 + 0.42278103399692396 + 0.42279343681582066 + 0.42280584010215305 + 0.42281824385594824 + 0.42283064807723647 + 0.42284305276604484 + 0.42285545792240159 + 0.42286786354633482 + 0.42288026963787373 + 0.42289267619704546 + 0.42290508322387932 + 0.42291749071840223 + 0.42292989868064362 + 0.42294230711063263 + 0.42295471600839529 + 0.42296712537396086 + 0.42297953520735759 + 0.42299194550861363 + 0.42300435627775812 + 0.42301676751481826 + 0.42302917921982336 + 0.42304159139280051 + 0.42305400403377891 + 0.42306641714278576 + 0.42307883071985136 + 0.42309124476500165 + 0.42310365927826721 + 0.42311607425967485 + 0.42312848970925304 + 0.42314090562703 + 0.42315332201303485 + 0.42316573886729481 + 0.42317815618984006 + 0.42319057398069693 + 0.42320299223989449 + 0.42321541096746113 + 0.42322783016342491 + 0.42324024982781416 + 0.42325266996065813 + 0.42326509056198397 + 0.42327751163182092 + 0.4232899331701962 + 0.42330235517713916 + 0.42331477765267789 + 0.42332720059684076 + 0.42333962400965575 + 0.42335204789115249 + 0.42336447224135693 + 0.42337689706030041 + 0.42338932234800819 + 0.42340174810451159 + 0.42341417432983669 + 0.42342660102401281 + 0.42343902818706824 + 0.42345145581903226 + 0.423463883919932 + 0.42347631248979595 + 0.42348874152865318 + 0.42350117103653195 + 0.42351360101345958 + 0.42352603145946549 + 0.42353846237457765 + 0.4235508937588256 + 0.42356332561223536 + 0.42357575793483843 + 0.4235881907266611 + 0.42360062398773135 + 0.42361305771807878 + 0.42362549191773252 + 0.42363792658671895 + 0.4236503617250682 + 0.42366279733280671 + 0.42367523340996577 + 0.42368766995657153 + 0.42370010697265337 + 0.42371254445823969 + 0.42372498241335749 + 0.42373742083803845 + 0.42374985973230767 + 0.42376229909619439 + 0.42377473892972911 + 0.42378717923293785 + 0.42379962000585025 + 0.42381206124849441 + 0.42382450296089874 + 0.4238369451430915 + 0.42384938779510195 + 0.42386183091695856 + 0.42387427450868853 + 0.42388671857032134 + 0.42389916310188502 + 0.42391160810340822 + 0.42392405357492113 + 0.42393649951644902 + 0.42394894592802224 + 0.42396139280966816 + 0.4239738401614172 + 0.42398628798329652 + 0.42399873627533463 + 0.42401118503755969 + 0.42402363427000134 + 0.42403608397268755 + 0.42404853414564597 + 0.4240609847889068 + 0.42407343590249735 + 0.42408588748644604 + 0.42409833954078235 + 0.42411079206553343 + 0.42412324506072874 + 0.42413569852639771 + 0.42414815246256649 + 0.42416060686926566 + 0.42417306174652353 + 0.42418551709436625 + 0.42419797291282552 + 0.42421042920192858 + 0.42422288596170371 + 0.42423534319217943 + 0.4242478008933851 + 0.42426025906534792 + 0.42427271770809849 + 0.42428517682166311 + 0.4242976364060711 + 0.42431009646135193 + 0.42432255698753407 + 0.42433501798464479 + 0.42434747945271334 + 0.42435994139176841 + 0.42437240380183927 + 0.42438486668295228 + 0.42439733003513885 + 0.42440979385842548 + 0.4244222581528414 + 0.42443472291841522 + 0.42444718815517612 + 0.42445965386315176 + 0.42447212004237134 + 0.42448458669286232 + 0.42449705381465525 + 0.42450952140777737 + 0.42452198947225728 + 0.42453445800812417 + 0.42454692701540669 + 0.42455939649413316 + 0.42457186644433204 + 0.42458433686603159 + 0.42459680775926251 + 0.42460927912405011 + 0.42462175096042576 + 0.42463422326841599 + 0.42464669604805222 + 0.42465916929935976 + 0.42467164302237032 + 0.42468411721711014 + 0.4246965918836087 + 0.42470906702189548 + 0.42472154263199896 + 0.42473401871394545 + 0.42474649526776659 + 0.42475897229348963 + 0.42477144979114423 + 0.42478392776075674 + 0.4247964062023587 + 0.42480888511597747 + 0.42482136450164054 + 0.42483384435937838 + 0.42484632468921946 + 0.42485880549119132 + 0.42487128676532343 + 0.42488376851164517 + 0.42489625073018406 + 0.42490873342096847 + 0.42492121658402809 + 0.42493370021939131 + 0.42494618432708758 + 0.4249586689071434 + 0.42497115395959029 + 0.42498363948445467 + 0.42499612548176713 + 0.42500861195155404 + 0.42502109889384604 + 0.42503358630867255 + 0.425046074196059 + 0.42505856255603813 + 0.42507105138863516 + 0.42508354069388066 + 0.42509603047180317 + 0.42510852072243133 + 0.42512101144579456 + 0.42513350264191924 + 0.42514599431083711 + 0.42515848645257448 + 0.42517097906716195 + 0.4251834721546271 + 0.4251959657149994 + 0.42520845974830646 + 0.42522095425457745 + 0.42523344923384349 + 0.42524594468612958 + 0.4252584406114665 + 0.42527093700988283 + 0.42528343388140794 + 0.42529593122606951 + 0.42530842904389699 + 0.42532092733491789 + 0.42533342609916286 + 0.42534592533665938 + 0.42535842504743698 + 0.42537092523152431 + 0.4253834258889499 + 0.42539592701974321 + 0.4254084286239318 + 0.4254209307015453 + 0.42543343325261224 + 0.4254459362771611 + 0.42545843977522163 + 0.42547094374682221 + 0.42548344819199152 + 0.42549595311075805 + 0.42550845850315144 + 0.42552096436919917 + 0.42553347070893188 + 0.42554597752237716 + 0.4255584848095646 + 0.42557099257052172 + 0.42558350080527813 + 0.42559600951386445 + 0.42560851869630623 + 0.42562102835263393 + 0.42563353848287733 + 0.42564604908706299 + 0.42565856016522241 + 0.42567107171738122 + 0.42568358374357212 + 0.42569609624382054 + 0.42570860921815723 + 0.42572112266661183 + 0.42573363658921065 + 0.42574615098598462 + 0.42575866585696115 + 0.42577118120217095 + 0.42578369702164154 + 0.42579621331540168 + 0.42580873008347991 + 0.42582124732590676 + 0.42583376504270998 + 0.42584628323391915 + 0.42585880189956177 + 0.42587132103966874 + 0.42588384065426638 + 0.4258963607433866 + 0.42590888130705579 + 0.42592140234530479 + 0.42593392385816115 + 0.42594644584565444 + 0.42595896830781232 + 0.42597149124466549 + 0.42598401465624269 + 0.42599653854257119 + 0.42600906290368212 + 0.42602158773960175 + 0.42603411305036204 + 0.42604663883598937 + 0.42605916509651459 + 0.42607169183196508 + 0.42608421904237093 + 0.42609674672776038 + 0.42610927488816236 + 0.42612180352360651 + 0.42613433263412132 + 0.42614686221973563 + 0.42615939228047905 + 0.42617192281637928 + 0.42618445382746695 + 0.42619698531376971 + 0.42620951727531636 + 0.4262220497121364 + 0.42623458262425967 + 0.42624711601171389 + 0.42625964987452847 + 0.42627218421273244 + 0.42628471902635529 + 0.4262972543154247 + 0.42630979007997039 + 0.42632232632002215 + 0.42633486303560764 + 0.42634740022675754 + 0.42635993789349741 + 0.42637247603586009 + 0.42638501465387341 + 0.42639755374756483 + 0.42641009331696622 + 0.42642263336210323 + 0.42643517388300756 + 0.42644771487970695 + 0.42646025635223117 + 0.42647279830060886 + 0.42648534072486866 + 0.42649788362503954 + 0.42651042700115099 + 0.42652297085323282 + 0.42653551518131283 + 0.42654805998542067 + 0.42656060526558404 + 0.4265731510218348 + 0.42658569725419954 + 0.42659824396270807 + 0.42661079114738909 + 0.42662333880827241 + 0.42663588694538679 + 0.42664843555876186 + 0.42666098464842539 + 0.42667353421440724 + 0.42668608425673721 + 0.42669863477544173 + 0.42671118577055278 + 0.42672373724209817 + 0.42673628919010759 + 0.4267488416146088 + 0.42676139451563255 + 0.4267739478932065 + 0.4267865017473606 + 0.42679905607812363 + 0.42681161088552527 + 0.42682416616959429 + 0.42683672193035938 + 0.42684927816784957 + 0.42686183488209434 + 0.42687439207312267 + 0.42688694974096436 + 0.42689950788564801 + 0.42691206650720259 + 0.42692462560565686 + 0.42693718518104051 + 0.42694974523338336 + 0.42696230576271327 + 0.42697486676905899 + 0.42698742825245128 + 0.42699999021291907 + 0.42701255265049004 + 0.42702511556519396 + 0.42703767895706185 + 0.42705024282612031 + 0.42706280717239925 + 0.42707537199592838 + 0.42708793729673561 + 0.42710050307485276 + 0.42711306933030552 + 0.42712563606312592 + 0.42713820327334162 + 0.42715077096098142 + 0.42716333912607635 + 0.427175907768654 + 0.42718847688874423 + 0.42720104648637602 + 0.42721361656157819 + 0.42722618711438048 + 0.42723875814481177 + 0.42725132965290175 + 0.42726390163867956 + 0.42727647410217273 + 0.42728904704341347 + 0.42730162046242826 + 0.42731419435924711 + 0.42732676873389985 + 0.42733934358641634 + 0.4273519189168235 + 0.42736449472515209 + 0.42737707101143202 + 0.42738964777569011 + 0.42740222501795821 + 0.42741480273826321 + 0.42742738093663712 + 0.42743995961310655 + 0.42745253876770251 + 0.42746511840045287 + 0.4274776985113875 + 0.42749027910053633 + 0.4275028601679281 + 0.42751544171359074 + 0.42752802373755522 + 0.4275406062398503 + 0.42755318922050489 + 0.42756577267954904 + 0.42757835661701143 + 0.42759094103292211 + 0.42760352592730888 + 0.42761611130020155 + 0.42762869715163027 + 0.42764128348162378 + 0.42765387029021085 + 0.42766645757742061 + 0.42767904534328288 + 0.42769163358782858 + 0.42770422231108463 + 0.42771681151308083 + 0.42772940119384623 + 0.42774199135341184 + 0.42775458199180527 + 0.42776717310905665 + 0.42777976470519485 + 0.42779235678024985 + 0.42780494933424951 + 0.42781754236722475 + 0.42783013587920349 + 0.42784272987021577 + 0.42785532434029239 + 0.42786791928946033 + 0.42788051471774963 + 0.42789311062519003 + 0.42790570701180958 + 0.42791830387764029 + 0.42793090122270899 + 0.42794349904704676 + 0.4279560973506813 + 0.4279686961336428 + 0.42798129539596119 + 0.42799389513766534 + 0.42800649535878321 + 0.42801909605934679 + 0.428031697239384 + 0.42804429889892387 + 0.42805690103799637 + 0.42806950365663038 + 0.42808210675485586 + 0.42809471033270191 + 0.42810731439019839 + 0.42811991892737439 + 0.42813252394425771 + 0.42814512944088051 + 0.42815773541727065 + 0.42817034187345709 + 0.42818294880947094 + 0.42819555622534011 + 0.42820816412109364 + 0.42822077249676244 + 0.42823338135237549 + 0.42824599068796193 + 0.42825860050355058 + 0.42827121079917158 + 0.42828382157485489 + 0.42829643283062829 + 0.42830904456652213 + 0.42832165678256623 + 0.42833426947878972 + 0.42834688265522253 + 0.42835949631189252 + 0.428372110448831 + 0.42838472506606579 + 0.42839734016362796 + 0.42840995574154545 + 0.42842257179984838 + 0.42843518833856686 + 0.42844780535772981 + 0.42846042285736607 + 0.42847304083750498 + 0.42848565929817739 + 0.42849827823941145 + 0.42851089766123712 + 0.42852351756368545 + 0.42853613794678241 + 0.4285487588105612 + 0.4285613801550488 + 0.42857400198027512 + 0.42858662428627031 + 0.42859924707306357 + 0.42861187034068471 + 0.42862449408916187 + 0.42863711831852608 + 0.4286497430288066 + 0.42866236822003212 + 0.42867499389223301 + 0.4286876200454382 + 0.42870024667967788 + 0.42871287379498091 + 0.42872550139137744 + 0.42873812946889567 + 0.42875075802756757 + 0.42876338706741912 + 0.42877601658848363 + 0.42878864659078791 + 0.42880127707436222 + 0.42881390803923664 + 0.42882653948544119 + 0.42883917141300398 + 0.42885180382195504 + 0.42886443671232355 + 0.42887707008414061 + 0.42888970393743431 + 0.42890233827223462 + 0.42891497308857079 + 0.42892760838647281 + 0.42894024416597093 + 0.42895288042709306 + 0.42896551716987052 + 0.42897815439433123 + 0.42899079210050534 + 0.42900343028842414 + 0.42901606895811445 + 0.42902870810960769 + 0.42904134774293168 + 0.42905398785811882 + 0.42906662845519494 + 0.42907926953419356 + 0.42909191109514244 + 0.42910455313807083 + 0.42911719566300888 + 0.42912983866998583 + 0.42914248215903161 + 0.42915512613017542 + 0.42916777058344746 + 0.42918041551887692 + 0.42919306093649473 + 0.42920570683632825 + 0.42921835321840851 + 0.42923100008276471 + 0.42924364742942595 + 0.4292562952584234 + 0.42926894356978629 + 0.4292815923635438 + 0.42929424163972485 + 0.42930689139835981 + 0.42931954163947772 + 0.42933219236310982 + 0.42934484356928432 + 0.42935749525803141 + 0.42937014742938107 + 0.42938280008336266 + 0.42939545322000627 + 0.42940810683934005 + 0.4294207609413942 + 0.42943341552620007 + 0.42944607059378559 + 0.42945872614418101 + 0.42947138217741654 + 0.42948403869352042 + 0.42949669569252386 + 0.42950935317445593 + 0.42952201113934596 + 0.42953466958722392 + 0.42954732851812033 + 0.42955998793206318 + 0.42957264782908372 + 0.42958530820921109 + 0.42959796907247561 + 0.4296106304189054 + 0.4296232922485318 + 0.42963595456138387 + 0.42964861735749083 + 0.42966128063688297 + 0.42967394439959056 + 0.42968660864564268 + 0.42969927337506869 + 0.42971193858789875 + 0.42972460428416304 + 0.42973727046389082 + 0.4297499371271124 + 0.42976260427385587 + 0.42977527190415254 + 0.42978794001803172 + 0.42980060861552349 + 0.42981327769665723 + 0.42982594726146311 + 0.42983861730996931 + 0.42985128784220838 + 0.42986395885820816 + 0.42987663035799811 + 0.42988930234160944 + 0.4299019748090705 + 0.42991464776041244 + 0.42992732119566457 + 0.42993999511485614 + 0.42995266951801731 + 0.42996534440517753 + 0.4299780197763669 + 0.42999069563161585 + 0.43000337197095351 + 0.43001604879440924 + 0.43002872610201326 + 0.4300414038937958 + 0.43005408216978624 + 0.43006676093001495 + 0.430079440174511 + 0.43009211990330476 + 0.43010480011642549 + 0.4301174808139025 + 0.43013016199576715 + 0.43014284366204869 + 0.43015552581277738 + 0.43016820844798148 + 0.43018089156769235 + 0.4301935751719394 + 0.43020625926075268 + 0.43021894383416065 + 0.43023162889219568 + 0.43024431443488598 + 0.43025700046226084 + 0.43026968697435058 + 0.43028237397118657 + 0.43029506145279717 + 0.43030774941921257 + 0.43032043787046209 + 0.43033312680657715 + 0.43034581622758616 + 0.43035850613352028 + 0.43037119652440681 + 0.43038388740027922 + 0.43039657876116472 + 0.43040927060709477 + 0.43042196293809754 + 0.43043465575420459 + 0.43044734905544502 + 0.43046004284184941 + 0.43047273711344697 + 0.43048543187026805 + 0.43049812711234103 + 0.43051082283969822 + 0.43052351905236796 + 0.4305362157503817 + 0.43054891293376785 + 0.43056161060255543 + 0.43057430875677721 + 0.43058700739646127 + 0.4305997065216382 + 0.4306124061323372 + 0.43062510622858868 + 0.43063780681042302 + 0.43065050787786852 + 0.43066320943095776 + 0.43067591146971784 + 0.43068861399418146 + 0.43070131700437669 + 0.43071402050033303 + 0.43072672448208305 + 0.43073942894965489 + 0.43075213390307793 + 0.43076483934238274 + 0.43077754526760065 + 0.43079025167876001 + 0.43080295857589124 + 0.43081566595902476 + 0.43082837382818895 + 0.43084108218341516 + 0.43085379102473492 + 0.4308665003521745 + 0.43087921016576741 + 0.43089192046554109 + 0.43090463125152784 + 0.43091734252375513 + 0.43093005428225434 + 0.43094276652705604 + 0.43095547925818944 + 0.43096819247568519 + 0.43098090617957252 + 0.43099362036988081 + 0.43100633504664287 + 0.43101905020988568 + 0.43103176585964087 + 0.43104448199593792 + 0.4310571986188072 + 0.43106991572827819 + 0.43108263332438235 + 0.43109535140714805 + 0.43110806997660572 + 0.43112078903278589 + 0.43113350857571792 + 0.43114622860543345 + 0.43115894912196079 + 0.43117167012533142 + 0.4311843916155737 + 0.43119711359271928 + 0.43120983605679647 + 0.43122255900783779 + 0.43123528244587178 + 0.43124800637092775 + 0.43126073078303723 + 0.4312734556822308 + 0.43128618106853689 + 0.43129890694198691 + 0.4313116333026083 + 0.43132436015043574 + 0.43133708748549437 + 0.43134981530781913 + 0.43136254361743609 + 0.43137527241437701 + 0.43138800169867231 + 0.43140073147035241 + 0.43141346172944584 + 0.43142619247598313 + 0.4314389237099957 + 0.4314516554315132 + 0.43146438764056505 + 0.43147712033718166 + 0.43148985352139374 + 0.43150258719323065 + 0.43151532135272291 + 0.43152805599990007 + 0.43154079113479266 + 0.43155352675743214 + 0.43156626286784605 + 0.43157899946606693 + 0.43159173655212441 + 0.43160447412604774 + 0.43161721218786675 + 0.43162995073761379 + 0.43164268977531639 + 0.43165542930100614 + 0.43166816931471363 + 0.43168090981646828 + 0.43169365080630068 + 0.43170639228424046 + 0.43171913425031905 + 0.43173187670456387 + 0.43174461964700778 + 0.43175736307768114 + 0.43177010699661156 + 0.43178285140383255 + 0.4317955962993717 + 0.43180834168325954 + 0.43182108755552762 + 0.43183383391620556 + 0.43184658076532184 + 0.43185932810291017 + 0.43187207592899801 + 0.4318848242436169 + 0.43189757304679549 + 0.4319103223385653 + 0.43192307211895692 + 0.43193582238800005 + 0.43194857314572399 + 0.43196132439216067 + 0.43197407612733935 + 0.43198682835129093 + 0.43199958106404474 + 0.4320123342656314 + 0.43202508795608069 + 0.43203784213542507 + 0.43205059680369107 + 0.4320633519609125 + 0.43207610760711773 + 0.43208886374233751 + 0.43210162036660243 + 0.43211437747994202 + 0.43212713508238598 + 0.43213989317396678 + 0.43215265175471329 + 0.43216541082465593 + 0.43217817038382539 + 0.4321909304322501 + 0.43220369096996303 + 0.43221645199699349 + 0.43222921351337124 + 0.43224197551912702 + 0.43225473801429015 + 0.43226750099889255 + 0.4322802644729638 + 0.43229302843653444 + 0.43230579288963417 + 0.43231855783229367 + 0.43233132326454349 + 0.43234408918641432 + 0.43235685559793585 + 0.43236962249913757 + 0.4323823898900514 + 0.4323951577707067 + 0.43240792614113427 + 0.43242069500136493 + 0.43243346435142799 + 0.43244623419135442 + 0.43245900452117364 + 0.43247177534091646 + 0.43248454665061453 + 0.43249731845029643 + 0.43251009073999402 + 0.43252286351973679 + 0.43253563678955559 + 0.4325484105494799 + 0.43256118479954053 + 0.43257395953976802 + 0.43258673477019216 + 0.43259951049084583 + 0.43261228670175539 + 0.43262506340295465 + 0.43263784059447224 + 0.43265061827633805 + 0.43266339644858454 + 0.43267617511124068 + 0.4326889542643379 + 0.43270173390790506 + 0.43271451404197381 + 0.43272729466657384 + 0.43274007578173601 + 0.43275285738748959 + 0.43276563948386687 + 0.43277842207089834 + 0.43279120514861252 + 0.43280398871704023 + 0.43281677277621339 + 0.43282955732616152 + 0.43284234236691438 + 0.43285512789850383 + 0.43286791392095941 + 0.43288070043431193 + 0.43289348743859113 + 0.43290627493382772 + 0.4329190629200535 + 0.43293185139729717 + 0.43294464036559044 + 0.43295742982496205 + 0.43297021977544481 + 0.43298301021706748 + 0.4329958011498618 + 0.43300859257385632 + 0.43302138448908301 + 0.43303417689557372 + 0.43304696979335594 + 0.43305976318246048 + 0.43307255706292036 + 0.43308535143476412 + 0.43309814629802251 + 0.43311094165272629 + 0.43312373749890543 + 0.43313653383659151 + 0.4331493306658144 + 0.43316212798660475 + 0.43317492579899247 + 0.43318772410300938 + 0.43320052289868416 + 0.43321332218604852 + 0.43322612196513344 + 0.4332389222359686 + 0.43325172299858478 + 0.43326452425301182 + 0.43327732599928248 + 0.43329012823742458 + 0.43330293096746991 + 0.43331573418944924 + 0.43332853790339249 + 0.43334134210933134 + 0.43335414680729462 + 0.43336695199731418 + 0.43337975767941977 + 0.43339256385364328 + 0.43340537052001454 + 0.43341817767856328 + 0.4334309853293204 + 0.4334437934723176 + 0.4334566021075848 + 0.43346941123515187 + 0.43348222085505062 + 0.43349503096731079 + 0.43350784157196326 + 0.43352065266903783 + 0.43353346425856748 + 0.43354627634057991 + 0.43355908891510692 + 0.43357190198217949 + 0.43358471554182848 + 0.4335975295940836 + 0.43361034413897576 + 0.43362315917653588 + 0.43363597470679371 + 0.43364879072978008 + 0.43366160724552699 + 0.43367442425406416 + 0.43368724175542156 + 0.433700059749631 + 0.43371287823672239 + 0.43372569721672549 + 0.43373851668967334 + 0.43375133665559468 + 0.43376415711452043 + 0.43377697806648252 + 0.43378979951150959 + 0.43380262144963377 + 0.43381544388088494 + 0.43382826680529496 + 0.43384109022289252 + 0.43385391413370972 + 0.43386673853777641 + 0.43387956343512446 + 0.43389238882578485 + 0.43390521470978527 + 0.43391804108715876 + 0.43393086795793628 + 0.4339436953221476 + 0.43395652317982369 + 0.43396935153099558 + 0.43398218037569397 + 0.43399500971394778 + 0.4340078395457902 + 0.43402066987125082 + 0.43403350069036073 + 0.43404633200314979 + 0.43405916380964993 + 0.43407199610989006 + 0.43408482890390321 + 0.43409766219171814 + 0.43411049597336704 + 0.4341233302488795 + 0.43413616501828667 + 0.43414900028161951 + 0.4341618360389089 + 0.43417467229018464 + 0.43418750903547904 + 0.43420034627482162 + 0.4342131840082426 + 0.43422602223577489 + 0.43423886095744629 + 0.43425170017329101 + 0.4342645398833368 + 0.43427738008761574 + 0.43429022078615981 + 0.43430306197899776 + 0.43431590366615969 + 0.43432874584767966 + 0.43434158852358545 + 0.43435443169390919 + 0.43436727535868075 + 0.43438011951793321 + 0.43439296417169554 + 0.43440580931999756 + 0.4344186549628713 + 0.43443150110034789 + 0.43444434773245821 + 0.43445719485923223 + 0.43447004248070104 + 0.43448289059689654 + 0.43449573920784773 + 0.43450858831358669 + 0.43452143791414327 + 0.43453428800954857 + 0.43454713859983457 + 0.43455998968503029 + 0.43457284126516876 + 0.43458569334027891 + 0.43459854591039176 + 0.43461139897553946 + 0.43462425253575182 + 0.43463710659106009 + 0.43464996114149407 + 0.43466281618708585 + 0.43467567172786653 + 0.43468852776386602 + 0.43470138429511546 + 0.43471424132164471 + 0.43472709884348709 + 0.43473995686067129 + 0.43475281537322963 + 0.43476567438119201 + 0.43477853388458948 + 0.43479139388345422 + 0.43480425437781506 + 0.43481711536770312 + 0.43482997685315039 + 0.43484283883418817 + 0.43485570131084622 + 0.43486856428315579 + 0.43488142775114791 + 0.43489429171485244 + 0.43490715617430159 + 0.4349200211295266 + 0.43493288658055729 + 0.43494575252742479 + 0.43495861897016008 + 0.43497148590879442 + 0.43498435334335894 + 0.43499722127388341 + 0.43501008970040012 + 0.43502295862293905 + 0.43503582804153129 + 0.43504869795620804 + 0.43506156836700033 + 0.43507443927394029 + 0.43508731067705586 + 0.43510018257638033 + 0.43511305497194358 + 0.4351259278637768 + 0.43513880125191223 + 0.43515167513637981 + 0.43516454951720973 + 0.43517742439443396 + 0.43519029976808377 + 0.43520317563818806 + 0.43521605200478025 + 0.43522892886789122 + 0.4352418062275501 + 0.43525468408378909 + 0.43526756243663933 + 0.43528044128613191 + 0.43529332063229687 + 0.43530620047516538 + 0.43531908081476961 + 0.43533196165113974 + 0.43534484298430681 + 0.43535772481430202 + 0.43537060714115638 + 0.43538348996490017 + 0.43539637328556552 + 0.43540925710318251 + 0.43542214141778329 + 0.43543502622939906 + 0.4354479115380579 + 0.43546079734379411 + 0.43547368364663758 + 0.43548657044661976 + 0.43549945774377058 + 0.43551234553812235 + 0.43552523382970515 + 0.43553812261855013 + 0.43555101190468959 + 0.43556390168815351 + 0.43557679196897331 + 0.43558968274717991 + 0.4356025740228035 + 0.43561546579587757 + 0.43562835806643091 + 0.43564125083449484 + 0.43565414410010173 + 0.43566703786328154 + 0.43567993212406658 + 0.43569282688248584 + 0.43570572213857178 + 0.4357186178923565 + 0.43573151414386913 + 0.43574441089314186 + 0.43575730814020497 + 0.43577020588509069 + 0.43578310412783017 + 0.43579600286845255 + 0.43580890210699225 + 0.43582180184347719 + 0.43583470207793978 + 0.43584760281041229 + 0.43586050404092375 + 0.43587340576950645 + 0.43588630799619166 + 0.43589921072101068 + 0.43591211394399249 + 0.43592501766517155 + 0.43593792188457692 + 0.43595082660224105 + 0.43596373181819298 + 0.43597663753246602 + 0.43598954374509041 + 0.43600245045609731 + 0.43601535766551819 + 0.43602826537338407 + 0.43604117357972522 + 0.43605408228457498 + 0.43606699148796263 + 0.43607990118991924 + 0.43609281139047723 + 0.4361057220896678 + 0.43611863328752126 + 0.43613154498406881 + 0.43614445717934291 + 0.4361573698733725 + 0.43617028306619093 + 0.43618319675782768 + 0.4361961109483159 + 0.43620902563768588 + 0.43622194082596888 + 0.43623485651319505 + 0.43624777269939691 + 0.43626068938460566 + 0.43627360656885256 + 0.43628652425216685 + 0.43629944243458302 + 0.43631236111613003 + 0.43632528029683948 + 0.4363381999767435 + 0.43635112015587246 + 0.43636404083425767 + 0.43637696201193032 + 0.4363898836889229 + 0.43640280586526564 + 0.43641572854098876 + 0.43642865171612566 + 0.43644157539070561 + 0.43645449956476201 + 0.43646742423832408 + 0.43648034941142416 + 0.43649327508409363 + 0.43650620125636391 + 0.43651912792826503 + 0.43653205509983062 + 0.43654498277108877 + 0.43655791094207402 + 0.43657083961281457 + 0.43658376878334371 + 0.43659669845369298 + 0.43660962862389263 + 0.43662255929397387 + 0.43663549046396927 + 0.43664842213390909 + 0.43666135430382452 + 0.43667428697374822 + 0.43668722014371031 + 0.43670015381374222 + 0.43671308798387531 + 0.43672602265414096 + 0.43673895782457156 + 0.43675189349519633 + 0.43676482966604885 + 0.43677776633715831 + 0.43679070350855814 + 0.43680364118027881 + 0.43681657935235052 + 0.4368295180248058 + 0.436842457197677 + 0.4368553968709934 + 0.4368683370447875 + 0.43688127771909063 + 0.43689421889393526 + 0.43690716056934975 + 0.43692010274536841 + 0.43693304542202066 + 0.43694598859933897 + 0.43695893227735466 + 0.43697187645609931 + 0.43698482113560416 + 0.43699776631589954 + 0.43701071199701802 + 0.43702365817898986 + 0.43703660486184875 + 0.43704955204562379 + 0.43706249973034766 + 0.43707544791605163 + 0.43708839660276594 + 0.43710134579052345 + 0.43711429547935532 + 0.43712724566929195 + 0.43714019636036588 + 0.43715314755260853 + 0.43716609924605138 + 0.43717905144072466 + 0.43719200413666087 + 0.43720495733389175 + 0.43721791103244734 + 0.43723086523236138 + 0.43724381993366318 + 0.43725677513638406 + 0.43726973084055776 + 0.43728268704621359 + 0.43729564375338403 + 0.43730860096210056 + 0.43732155867239453 + 0.43733451688429653 + 0.43734747559784004 + 0.43736043481305326 + 0.43737339452997198 + 0.43738635474862353 + 0.43739931546904243 + 0.43741227669125921 + 0.43742523841530412 + 0.43743820064121092 + 0.43745116336900886 + 0.43746412659873163 + 0.4374770903304096 + 0.43749005456407319 + 0.43750301929975605 + 0.43751598453748858 + 0.43752895027730232 + 0.4375419165192288 + 0.43755488326329939 + 0.43756785050954661 + 0.43758081825800116 + 0.4375937865086944 + 0.43760675526165776 + 0.43761972451692382 + 0.43763269427452323 + 0.43764566453448728 + 0.43765863529684862 + 0.43767160656163778 + 0.43768457832888724 + 0.43769755059862858 + 0.43771052337089217 + 0.4377234966457107 + 0.43773647042311464 + 0.43774944470313654 + 0.43776241948580791 + 0.43777539477116029 + 0.43778837055922426 + 0.4378013468500323 + 0.43781432364361705 + 0.43782730094000782 + 0.43784027873923742 + 0.43785325704133737 + 0.43786623584634121 + 0.4378792151542763 + 0.43789219496517739 + 0.43790517527907502 + 0.43791815609600171 + 0.43793113741598805 + 0.43794411923906545 + 0.43795710156526674 + 0.43797008439462343 + 0.43798306772716594 + 0.43799605156292698 + 0.43800903590193691 + 0.43802202074422969 + 0.43803500608983353 + 0.4380479919387843 + 0.4380609782911104 + 0.43807396514684449 + 0.43808695250601809 + 0.43809994036866384 + 0.43811292873481139 + 0.43812591760449426 + 0.43813890697774299 + 0.43815189685459138 + 0.43816488723506786 + 0.43817787811920611 + 0.43819086950703673 + 0.43820386139859219 + 0.43821685379390435 + 0.43822984669300469 + 0.43824284009592585 + 0.43825583400269735 + 0.43826882841335196 + 0.43828182332792121 + 0.43829481874643778 + 0.43830781466893215 + 0.43832081109543614 + 0.43833380802598226 + 0.43834680546060117 + 0.43835980339932562 + 0.43837280184218708 + 0.43838580078921729 + 0.43839880024044681 + 0.43841180019591042 + 0.4384248006556356 + 0.43843780161965701 + 0.43845080308800544 + 0.43846380506071353 + 0.43847680753781187 + 0.438489810519333 + 0.43850281400530777 + 0.43851581799576883 + 0.43852882249074771 + 0.4385418274902762 + 0.43855483299438591 + 0.43856783900310847 + 0.43858084551647564 + 0.4385938525345201 + 0.43860686005727245 + 0.43861986808476533 + 0.4386328766170296 + 0.43864588565409679 + 0.43865889519600065 + 0.43867190524277172 + 0.43868491579444202 + 0.43869792685104186 + 0.43871093841260633 + 0.43872395047916479 + 0.43873696305074911 + 0.43874997612739081 + 0.43876298970912392 + 0.43877600379597781 + 0.43878901838798534 + 0.43880203348517827 + 0.43881504908758812 + 0.43882806519524786 + 0.43884108180818809 + 0.43885409892644045 + 0.43886711655003774 + 0.43888013467901171 + 0.43889315331339401 + 0.43890617245321539 + 0.43891919209850966 + 0.43893221224930745 + 0.43894523290564164 + 0.43895825406754163 + 0.43897127573504252 + 0.43898429790817384 + 0.43899732058696855 + 0.43901034377145809 + 0.43902336746167447 + 0.4390363916576504 + 0.43904941635941536 + 0.43906244156700341 + 0.43907546728044733 + 0.43908849349977563 + 0.43910152022502325 + 0.43911454745621986 + 0.43912757519339923 + 0.43914060343659228 + 0.43915363218583159 + 0.43916666144114797 + 0.43917969120257427 + 0.43919272147014121 + 0.43920575224388259 + 0.4392187835238292 + 0.43923181531001271 + 0.43924484760246607 + 0.43925788040121994 + 0.43927091370630728 + 0.43928394751775962 + 0.43929698183560906 + 0.43931001665988706 + 0.43932305199062566 + 0.43933608782785766 + 0.43934912417161365 + 0.43936216102192777 + 0.43937519837882949 + 0.43938823624235174 + 0.43940127461252748 + 0.43941431348938725 + 0.43942735287296308 + 0.43944039276328878 + 0.43945343316039409 + 0.43946647406431183 + 0.43947951547507369 + 0.43949255739271287 + 0.43950559981725995 + 0.4395186427487478 + 0.43953168618720817 + 0.43954473013267187 + 0.43955777458517303 + 0.43957081954474225 + 0.43958386501141233 + 0.43959691098521425 + 0.43960995746618192 + 0.43962300445434499 + 0.43963605194973748 + 0.4396490999523901 + 0.4396621484623347 + 0.43967519747960426 + 0.43968824700423059 + 0.4397012970362445 + 0.43971434757568101 + 0.43972739862256888 + 0.43974045017694185 + 0.43975350223883303 + 0.43976655480827115 + 0.43977960788529108 + 0.43979266146992479 + 0.43980571556220305 + 0.43981877016215781 + 0.43983182526982306 + 0.43984488088522838 + 0.43985793700840797 + 0.43987099363939258 + 0.43988405077821507 + 0.43989710842490748 + 0.43991016657950049 + 0.4399232252420282 + 0.43993628441252142 + 0.43994934409101194 + 0.43996240427753397 + 0.4399754649721172 + 0.43998852617479561 + 0.44000158788559995 + 0.44001465010456242 + 0.44002771283171571 + 0.44004077606709185 + 0.44005383981072271 + 0.44006690406264132 + 0.44007996882287842 + 0.44009303409146711 + 0.44010609986843918 + 0.44011916615382668 + 0.44013223294766146 + 0.44014530024997656 + 0.44015836806080383 + 0.4401714363801752 + 0.44018450520812274 + 0.44019757454467823 + 0.44021064438987367 + 0.44022371474374317 + 0.4402367856063174 + 0.44024985697762864 + 0.44026292885770962 + 0.44027600124659128 + 0.44028907414430668 + 0.44030214755088781 + 0.44031522146636765 + 0.44032829589077699 + 0.44034137082414893 + 0.44035444626651443 + 0.44036752221790848 + 0.44038059867835994 + 0.4403936756479031 + 0.44040675312656963 + 0.4404198311143927 + 0.44043290961140208 + 0.44044598861763196 + 0.44045906813311425 + 0.44047214815788099 + 0.44048522869196416 + 0.44049830973539672 + 0.44051139128821082 + 0.44052447335043604 + 0.44053755592210891 + 0.44055063900325919 + 0.4405637225939199 + 0.44057680669412203 + 0.44058989130389964 + 0.44060297642328367 + 0.44061606205230736 + 0.44062914819100141 + 0.44064223483940002 + 0.44065532199753421 + 0.44066840966543597 + 0.44068149784313942 + 0.44069458653067334 + 0.44070767572807412 + 0.44072076543537264 + 0.44073385565259987 + 0.44074694637978779 + 0.44076003761697169 + 0.44077312936418139 + 0.44078622162145015 + 0.44079931438880876 + 0.44081240766629254 + 0.44082550145393024 + 0.44083859575175716 + 0.44085169055980328 + 0.44086478587810263 + 0.44087788170668735 + 0.44089097804558852 + 0.44090407489483896 + 0.44091717225447213 + 0.44093027012451869 + 0.44094336850501314 + 0.44095646739598521 + 0.44096956679746918 + 0.44098266670949599 + 0.44099576713209987 + 0.44100886806531181 + 0.44102196950916384 + 0.44103507146368914 + 0.44104817392891876 + 0.44106127690488794 + 0.44107438039162661 + 0.44108748438916684 + 0.44110058889754294 + 0.44111369391678573 + 0.44112679944692856 + 0.44113990548800242 + 0.44115301204004143 + 0.44116611910307774 + 0.44117922667714143 + 0.4411923347622686 + 0.44120544335848844 + 0.44121855246583497 + 0.4412316620843415 + 0.44124477221403674 + 0.44125788285495737 + 0.44127099400713321 + 0.44128410567059739 + 0.44129721784538306 + 0.44131033053152147 + 0.44132344372904669 + 0.44133655743798872 + 0.44134967165838196 + 0.44136278639025733 + 0.44137590163364915 + 0.44138901738858738 + 0.44140213365510744 + 0.44141525043324037 + 0.44142836772301708 + 0.44144148552447204 + 0.44145460383763729 + 0.44146772266254619 + 0.4414808419992286 + 0.44149396184771983 + 0.44150708220805007 + 0.44152020308025341 + 0.44153332446436111 + 0.4415464463604063 + 0.44155956876842223 + 0.44157269168843999 + 0.44158581512049289 + 0.4415989390646119 + 0.44161206352083243 + 0.44162518848918453 + 0.44163831396970249 + 0.44165143996241751 + 0.44166456646736163 + 0.44167769348456926 + 0.44169082101407148 + 0.44170394905590044 + 0.44171707761009049 + 0.44173020667667179 + 0.44174333625567952 + 0.44175646634714394 + 0.44176959695109808 + 0.44178272806757646 + 0.44179585969660912 + 0.44180899183822936 + 0.44182212449247038 + 0.44183525765936432 + 0.44184839133894355 + 0.44186152553124008 + 0.44187466023628735 + 0.4418877954541176 + 0.44190093118476403 + 0.44191406742825884 + 0.44192720418463438 + 0.44194034145392269 + 0.44195347923615819 + 0.44196661753137106 + 0.44197975633959558 + 0.44199289566086403 + 0.44200603549520745 + 0.44201917584266154 + 0.44203231670325616 + 0.44204545807702472 + 0.44205859996400049 + 0.44207174236421581 + 0.44208488527770284 + 0.44209802870449383 + 0.44211117264462318 + 0.442124317098121 + 0.44213746206502175 + 0.44215060754535868 + 0.44216375353916193 + 0.44217690004646587 + 0.44219004706730286 + 0.44220319460170621 + 0.44221634264970699 + 0.44222949121133853 + 0.44224264028663346 + 0.44225578987562586 + 0.44226893997834593 + 0.44228209059482809 + 0.44229524172510354 + 0.4423083933692068 + 0.44232154552716907 + 0.44233469819902355 + 0.44234785138480387 + 0.44236100508454096 + 0.4423741592982684 + 0.44238731402601839 + 0.44240046926782428 + 0.44241362502371839 + 0.44242678129373419 + 0.44243993807790283 + 0.44245309537625771 + 0.4424662531888322 + 0.44247941151565862 + 0.44249257035676925 + 0.44250572971219743 + 0.44251888958197561 + 0.4425320499661361 + 0.44254521086471221 + 0.44255837227773753 + 0.44257153420524187 + 0.44258469664726113 + 0.44259785960382647 + 0.44261102307497008 + 0.44262418706072665 + 0.44263735156112621 + 0.44265051657620447 + 0.44266368210599255 + 0.44267684815052394 + 0.44269001470982994 + 0.44270318178394502 + 0.44271634937290039 + 0.44272951747673073 + 0.44274268609546713 + 0.44275585522914307 + 0.44276902487779207 + 0.44278219504144534 + 0.44279536572013628 + 0.44280853691389743 + 0.44282170862276204 + 0.4428348808467637 + 0.44284805358593365 + 0.44286122684030527 + 0.44287440060991312 + 0.44288757489478653 + 0.4429007496949609 + 0.4429139250104675 + 0.44292710084134113 + 0.44294027718761292 + 0.4429534540493163 + 0.44296663142648368 + 0.44297980931914765 + 0.44299298772734241 + 0.44300616665109965 + 0.44301934609045257 + 0.44303252604543486 + 0.44304570651607772 + 0.44305888750241457 + 0.4430720690044791 + 0.44308525102230245 + 0.44309843355591932 + 0.44311161660536208 + 0.44312480017066314 + 0.44313798425185602 + 0.4431511688489721 + 0.44316435396204584 + 0.44317753959110973 + 0.44319072573619628 + 0.44320391239733886 + 0.44321709957457001 + 0.44323028726792213 + 0.44324347547742987 + 0.44325666420312443 + 0.4432698534450385 + 0.44328304320320638 + 0.44329623347766084 + 0.44330942426843412 + 0.44332261557555863 + 0.44333580739906808 + 0.44334899973899589 + 0.44336219259537352 + 0.4433753859682355 + 0.44338857985761321 + 0.44340177426354144 + 0.44341496918605139 + 0.44342816462517665 + 0.44344136058094968 + 0.44345455705340409 + 0.44346775404257344 + 0.44348095154849021 + 0.44349414957118571 + 0.4435073481106947 + 0.44352054716705064 + 0.44353374674028501 + 0.44354694683043128 + 0.44356014743752209 + 0.44357334856159203 + 0.44358655020267135 + 0.4435997523607948 + 0.44361295503599596 + 0.44362615822830626 + 0.44363936193775916 + 0.44365256616438847 + 0.44366577090822651 + 0.44367897616930696 + 0.44369218194766125 + 0.44370538824332395 + 0.44371859505632777 + 0.44373180238670501 + 0.44374501023448948 + 0.44375821859971359 + 0.44377142748241089 + 0.44378463688261294 + 0.44379784680035561 + 0.4438110572356701 + 0.44382426818858911 + 0.44383747965914616 + 0.4438506916473749 + 0.44386390415330806 + 0.44387711717697781 + 0.44389033071841816 + 0.44390354477766142 + 0.4439167593547424 + 0.4439299744496914 + 0.4439431900625444 + 0.44395640619333271 + 0.44396962284208891 + 0.44398284000884775 + 0.44399605769364081 + 0.44400927589650152 + 0.44402249461746474 + 0.44403571385656093 + 0.44404893361382486 + 0.44406215388928894 + 0.44407537468298686 + 0.44408859599495126 + 0.4441018178252148 + 0.44411504017381093 + 0.44412826304077346 + 0.4441414864261351 + 0.4441547103299292 + 0.44416793475218763 + 0.44418115969294486 + 0.4441943851522337 + 0.44420761113008655 + 0.44422083762653836 + 0.44423406464162046 + 0.44424729217536674 + 0.44426052022780965 + 0.44427374879898307 + 0.44428697788892058 + 0.4443002074976537 + 0.44431343762521819 + 0.44432666827164469 + 0.44433989943696789 + 0.44435313112121944 + 0.44436636332443402 + 0.44437959604664434 + 0.44439282928788393 + 0.44440606304818464 + 0.44441929732758101 + 0.44443253212610573 + 0.44444576744379161 + 0.44445900328067323 + 0.4444722396367824 + 0.44448547651215248 + 0.44449871390681761 + 0.44451195182081016 + 0.44452519025416298 + 0.44453842920691072 + 0.44455166867908497 + 0.44456490867071968 + 0.44457814918184835 + 0.44459139021250377 + 0.44460463176271964 + 0.44461787383252865 + 0.44463111642196457 + 0.44464435953106013 + 0.44465760315984887 + 0.44467084730836481 + 0.44468409197663933 + 0.44469733716470633 + 0.44471058287260073 + 0.44472382910035291 + 0.44473707584799993 + 0.44475032311557122 + 0.44476357090310165 + 0.44477681921062501 + 0.44479006803817517 + 0.44480331738578355 + 0.44481656725348406 + 0.44482981764130947 + 0.44484306854929556 + 0.44485631997747305 + 0.44486957192587562 + 0.44488282439453702 + 0.44489607738349013 + 0.44490933089276974 + 0.44492258492240755 + 0.44493583947243726 + 0.44494909454289272 + 0.44496235013380664 + 0.44497560624521193 + 0.44498886287714312 + 0.44500212002963341 + 0.44501537770271521 + 0.44502863589642233 + 0.44504189461078764 + 0.4450551538458461 + 0.44506841360162919 + 0.44508167387817088 + 0.44509493467550504 + 0.44510819599366425 + 0.44512145783268253 + 0.44513472019259248 + 0.44514798307342912 + 0.44516124647522304 + 0.44517451039801026 + 0.44518777484182237 + 0.4452010398066944 + 0.44521430529265804 + 0.4452275712997471 + 0.44524083782799656 + 0.44525410487743805 + 0.44526737244810549 + 0.44528064054003164 + 0.44529390915325157 + 0.44530717828779676 + 0.44532044794370235 + 0.44533371812100103 + 0.44534698881972556 + 0.44536026003991003 + 0.44537353178158806 + 0.44538680404479258 + 0.4454000768295564 + 0.44541335013591449 + 0.44542662396389954 + 0.44543989831354458 + 0.44545317318488442 + 0.44546644857795081 + 0.44547972449277767 + 0.44549300092939892 + 0.44550627788784847 + 0.44551955536815913 + 0.44553283337036365 + 0.44554611189449717 + 0.44555939094059127 + 0.4455726705086811 + 0.44558595059879841 + 0.44559923121097916 + 0.44561251234525401 + 0.44562579400165808 + 0.44563907618022425 + 0.44565235888098748 + 0.44566564210397941 + 0.44567892584923419 + 0.4456922101167855 + 0.44570549490666644 + 0.44571878021891087 + 0.44573206605355264 + 0.44574535241062474 + 0.44575863929016096 + 0.4457719266921944 + 0.44578521461675874 + 0.44579850306388702 + 0.44581179203361443 + 0.4458250815259735 + 0.44583837154099615 + 0.44585166207871979 + 0.44586495313917374 + 0.4458782447223944 + 0.44589153682841448 + 0.445904829457267 + 0.44591812260898578 + 0.44593141628360605 + 0.44594471048115836 + 0.44595800520167794 + 0.44597130044519978 + 0.44598459621175357 + 0.4459978925013765 + 0.4460111893141015 + 0.44602448664996036 + 0.44603778450898823 + 0.44605108289121914 + 0.44606438179668478 + 0.44607768122542024 + 0.44609098117745866 + 0.44610428165283378 + 0.4461175826515798 + 0.44613088417372843 + 0.44614418621931479 + 0.44615748878837302 + 0.44617079188093595 + 0.44618409549703653 + 0.44619739963670979 + 0.44621070429998783 + 0.44622400948690549 + 0.44623731519749588 + 0.44625062143179295 + 0.44626392818983068 + 0.44627723547164216 + 0.44629054327726042 + 0.44630385160672026 + 0.44631716046005387 + 0.44633046983729724 + 0.44634377973848249 + 0.44635709016364239 + 0.44637040111281318 + 0.44638371258602677 + 0.44639702458331626 + 0.44641033710471767 + 0.44642365015026197 + 0.44643696371998526 + 0.4464502778139196 + 0.44646359243209888 + 0.44647690757455738 + 0.44649022324132781 + 0.44650353943244564 + 0.44651685614794356 + 0.44653017338785478 + 0.44654349115221337 + 0.4465568094410533 + 0.44657012825440873 + 0.44658344759231267 + 0.4465967674547992 + 0.44661008784190137 + 0.44662340875365314 + 0.44663673019008887 + 0.44665005215124232 + 0.44666337463714678 + 0.44667669764783507 + 0.44669002118334372 + 0.44670334524370336 + 0.44671666982894931 + 0.44672999493911558 + 0.44674332057423527 + 0.44675664673434251 + 0.44676997341947139 + 0.44678330062965388 + 0.44679662836492628 + 0.44680995662532158 + 0.44682328541087191 + 0.4468366147216134 + 0.44684994455757804 + 0.44686327491880107 + 0.44687660580531446 + 0.44688993721715464 + 0.44690326915435336 + 0.4469166016169438 + 0.44692993460496244 + 0.44694326811844198 + 0.44695660215741478 + 0.44696993672191587 + 0.44698327181197939 + 0.44699660742763847 + 0.44700994356892737 + 0.44702328023588012 + 0.4470366174285299 + 0.44704995514691076 + 0.44706329339105705 + 0.44707663216100274 + 0.44708997145677992 + 0.44710331127842395 + 0.44711665162596886 + 0.44712999249944785 + 0.44714333389889616 + 0.44715667582434582 + 0.44717001827583097 + 0.44718336125338592 + 0.44719670475704476 + 0.44721004878684173 + 0.44722339334280997 + 0.44723673842498357 + 0.44725008403339689 + 0.44726343016808284 + 0.44727677682907585 + 0.44729012401641011 + 0.44730347173011864 + 0.44731681997023565 + 0.44733016873679654 + 0.4473435180298333 + 0.44735686784938128 + 0.44737021819547362 + 0.44738356906814447 + 0.44739692046742702 + 0.44741027239335668 + 0.44742362484596543 + 0.44743697782528852 + 0.44745033133136131 + 0.44746368536421388 + 0.4474770399238846 + 0.44749039501040344 + 0.44750375062380687 + 0.44751710676412904 + 0.44753046343140218 + 0.44754382062566156 + 0.4475571783469402 + 0.44757053659527263 + 0.44758389537069293 + 0.44759725467323547 + 0.44761061450293338 + 0.44762397485982081 + 0.44763733574393222 + 0.44765069715530081 + 0.44766405909396073 + 0.44767742155994733 + 0.44769078455329397 + 0.44770414807403269 + 0.44771751212219979 + 0.44773087669782979 + 0.44774424180095468 + 0.44775760743160875 + 0.44777097358982743 + 0.44778434027564401 + 0.44779770748909153 + 0.44781107523020547 + 0.44782444349902001 + 0.44783781229556857 + 0.44785118161988435 + 0.44786455147200271 + 0.44787792185195674 + 0.4478912927597809 + 0.44790466419550945 + 0.44791803615917691 + 0.44793140865081615 + 0.44794478167046176 + 0.44795815521814802 + 0.44797152929390932 + 0.44798490389777867 + 0.44799827902979178 + 0.44801165468998067 + 0.4480250308783808 + 0.44803840759502644 + 0.4480517848399509 + 0.44806516261318852 + 0.44807854091477478 + 0.44809191974474072 + 0.44810529910312291 + 0.44811867898995461 + 0.44813205940527007 + 0.44814544034910386 + 0.44815882182148908 + 0.44817220382246131 + 0.44818558635205369 + 0.44819896941030068 + 0.44821235299723561 + 0.44822573711289382 + 0.44823912175730762 + 0.44825250693051344 + 0.44826589263254474 + 0.44827927886343466 + 0.44829266562321879 + 0.44830605291193043 + 0.44831944072960384 + 0.44833282907627359 + 0.44834621795197288 + 0.44835960735673613 + 0.44837299729059882 + 0.44838638775359313 + 0.44839977874575582 + 0.44841317026711885 + 0.44842656231771694 + 0.44843995489758537 + 0.4484533480067564 + 0.44846674164526562 + 0.44848013581314738 + 0.44849353051043511 + 0.44850692573716311 + 0.4485203214933659 + 0.44853371777907775 + 0.44854711459433333 + 0.44856051193916585 + 0.44857390981360973 + 0.44858730821769943 + 0.44860070715146944 + 0.44861410661495421 + 0.44862750660818695 + 0.44864090713120336 + 0.44865430818403562 + 0.44866770976672044 + 0.44868111187928994 + 0.44869451452177994 + 0.44870791769422352 + 0.44872132139665638 + 0.44873472562911082 + 0.44874813039162348 + 0.44876153568422655 + 0.44877494150695457 + 0.44878834785984317 + 0.44880175474292661 + 0.44881516215623646 + 0.44882857009981014 + 0.44884197857368008 + 0.44885538757788296 + 0.44886879711245098 + 0.44888220717741772 + 0.44889561777281867 + 0.44890902889868939 + 0.44892244055506225 + 0.44893585274197273 + 0.44894926545945329 + 0.44896267870754059 + 0.44897609248626907 + 0.44898950679567001 + 0.44900292163578115 + 0.44901633700663601 + 0.4490297529082668 + 0.44904316934071031 + 0.44905658630400003 + 0.4490700037981703 + 0.44908342182325584 + 0.44909684037929093 + 0.44911025946630928 + 0.44912367908434525 + 0.44913709923343337 + 0.44915051991360944 + 0.44916394112490676 + 0.44917736286735882 + 0.44919078514100125 + 0.44920420794586752 + 0.44921763128199327 + 0.44923105514941192 + 0.44924447954815805 + 0.44925790447826625 + 0.44927132993977098 + 0.44928475593270584 + 0.44929818245710745 + 0.44931160951300725 + 0.44932503710044192 + 0.44933846521944376 + 0.44935189387004959 + 0.44936532305229299 + 0.44937875276620731 + 0.44939218301182937 + 0.44940561378919047 + 0.44941904509832736 + 0.44943247693927363 + 0.44944590931206363 + 0.44945934221673228 + 0.44947277565331506 + 0.44948620962184438 + 0.44949964412235488 + 0.44951307915488226 + 0.44952651471946115 + 0.44953995081612397 + 0.44955338744490747 + 0.44956682460584518 + 0.44958026229897158 + 0.44959370052432157 + 0.44960713928192847 + 0.44962057857182808 + 0.44963401839405492 + 0.44964745874864276 + 0.44966089963562589 + 0.44967434105503917 + 0.44968778300691825 + 0.44970122549129565 + 0.44971466850820702 + 0.44972811205768698 + 0.44974155613977024 + 0.44975500075449032 + 0.44976844590188297 + 0.44978189158198167 + 0.44979533779482239 + 0.44980878454043738 + 0.44982223181886233 + 0.44983567963013321 + 0.44984912797428345 + 0.44986257685134673 + 0.4498760262613587 + 0.44988947620435293 + 0.4499029266803653 + 0.44991637768943032 + 0.4499298292315817 + 0.44994328130685407 + 0.44995673391528213 + 0.44997018705690051 + 0.44998364073174502 + 0.44999709493984819 + 0.45001054968124582 + 0.4500240049559725 + 0.45003746076406298 + 0.45005091710555084 + 0.45006437398047189 + 0.45007783138885976 + 0.45009128933075027 + 0.45010474780617699 + 0.45011820681517345 + 0.45013166635777779 + 0.45014512643402144 + 0.45015858704394107 + 0.45017204818756945 + 0.45018550986494238 + 0.45019897207609555 + 0.45021243482106055 + 0.45022589809987523 + 0.4502393619125723 + 0.45025282625918739 + 0.45026629113975425 + 0.45027975655430769 + 0.45029322250288345 + 0.45030668898551629 + 0.45032015600223863 + 0.4503336235530877 + 0.450347091638097 + 0.45036056025730115 + 0.45037402941073507 + 0.45038749909843351 + 0.45040096932043122 + 0.45041444007676279 + 0.45042791136746324 + 0.4504413831925661 + 0.45045485555210718 + 0.45046832844612139 + 0.45048180187464343 + 0.45049527583770693 + 0.45050875033534782 + 0.45052222536759989 + 0.45053570093449768 + 0.45054917703607833 + 0.4505626536723733 + 0.45057613084341963 + 0.45058960854925095 + 0.45060308678990318 + 0.45061656556540997 + 0.4506300448758061 + 0.45064352472112651 + 0.45065700510140588 + 0.45067048601667897 + 0.45068396746698186 + 0.45069744945234713 + 0.45071093197281165 + 0.4507244150284081 + 0.45073789861917346 + 0.45075138274514048 + 0.45076486740634508 + 0.45077835260282301 + 0.4507918383346069 + 0.45080532460173289 + 0.45081881140423463 + 0.45083229874214908 + 0.45084578661551 + 0.45085927502435119 + 0.45087276396870846 + 0.45088625344861688 + 0.45089974346410994 + 0.45091323401522487 + 0.45092672510199311 + 0.45094021672445284 + 0.45095370888263681 + 0.45096720157658088 + 0.45098069480631992 + 0.45099418857188778 + 0.45100768287332021 + 0.45102117771065231 + 0.45103467308391787 + 0.45104816899315264 + 0.45106166543839155 + 0.45107516241966855 + 0.45108865993701941 + 0.45110215799047804 + 0.4511156565800804 + 0.45112915570586248 + 0.4511426553678558 + 0.45115615556609756 + 0.45116965630062267 + 0.45118315757146582 + 0.45119665937865999 + 0.4512101617222431 + 0.45122366460224922 + 0.45123716801871189 + 0.45125067197166741 + 0.45126417646115041 + 0.45127768148719488 + 0.45129118704983784 + 0.45130469314911209 + 0.45131819978505361 + 0.45133170695769631 + 0.45134521466707711 + 0.45135872291322893 + 0.45137223169618873 + 0.45138574101598938 + 0.45139925087266702 + 0.45141276126625629 + 0.45142627219679232 + 0.45143978366430998 + 0.45145329566884435 + 0.45146680821043023 + 0.45148032128910365 + 0.45149383490489747 + 0.45150734905784878 + 0.45152086374799039 + 0.45153437897535942 + 0.45154789473999085 + 0.45156141104191738 + 0.4515749278811762 + 0.45158844525780234 + 0.45160196317182855 + 0.45161548162329201 + 0.4516290006122276 + 0.45164252013866929 + 0.45165604020265315 + 0.45166956080421311 + 0.45168308194338513 + 0.45169660362020314 + 0.45171012583470438 + 0.45172364858692271 + 0.45173717187689094 + 0.45175069570464849 + 0.45176422007022704 + 0.45177774497366263 + 0.45179127041499029 + 0.45180479639424509 + 0.45181832291146318 + 0.45183184996667725 + 0.45184537755992443 + 0.45185890569123999 + 0.45187243436065661 + 0.45188596356821253 + 0.45189949331393958 + 0.45191302359787505 + 0.45192655442005392 + 0.45194008578051109 + 0.45195361767928177 + 0.45196715011639976 + 0.45198068309190126 + 0.4519942166058224 + 0.45200775065819604 + 0.45202128524905832 + 0.4520348203784455 + 0.45204835604639126 + 0.45206189225293086 + 0.45207542899810033 + 0.45208896628193385 + 0.4521025041044674 + 0.45211604246573595 + 0.45212958136577369 + 0.45214312080461655 + 0.45215666078229982 + 0.45217020129885854 + 0.45218374235432773 + 0.45219728394874237 + 0.45221082608213881 + 0.45222436875455085 + 0.45223791196601376 + 0.4522514557165625 + 0.45226500000623449 + 0.45227854483506252 + 0.45229209020308159 + 0.4523056361103292 + 0.45231918255683812 + 0.45233272954264575 + 0.45234627706778591 + 0.45235982513229389 + 0.45237337373620479 + 0.45238692287955468 + 0.45240047256237764 + 0.45241402278470993 + 0.45242757354658658 + 0.45244112484804294 + 0.45245467668911271 + 0.45246822906983331 + 0.45248178199023786 + 0.45249533545036469 + 0.45250888945024542 + 0.45252244398991764 + 0.45253599906941538 + 0.45254955468877583 + 0.45256311084803214 + 0.45257666754722031 + 0.45259022478637556 + 0.45260378256553313 + 0.45261734088472927 + 0.45263089974399795 + 0.45264445914337426 + 0.45265801908289471 + 0.45267157956259424 + 0.45268514058250814 + 0.45269870214267149 + 0.4527122642431195 + 0.45272582688388741 + 0.45273939006501124 + 0.45275295378652425 + 0.45276651804846485 + 0.45278008285086707 + 0.45279364819376489 + 0.45280721407719488 + 0.45282078050119307 + 0.4528343474657936 + 0.45284791497103172 + 0.45286148301694384 + 0.45287505160356489 + 0.45288862073092911 + 0.45290219039907292 + 0.4529157606080324 + 0.4529293313578418 + 0.45294290264853632 + 0.45295647448015108 + 0.45297004685272363 + 0.45298361976628687 + 0.45299719322087828 + 0.45301076721653089 + 0.45302434175328105 + 0.4530379168311649 + 0.45305149245021797 + 0.45306506861047413 + 0.45307864531196995 + 0.45309222255474141 + 0.45310580033882192 + 0.45311937866424884 + 0.4531329575310562 + 0.45314653693928031 + 0.45316011688895658 + 0.45317369738011909 + 0.45318727841280537 + 0.4532008599870494 + 0.45321444210288764 + 0.45322802476035434 + 0.45324160795948565 + 0.45325519170031714 + 0.45326877598288368 + 0.45328236080722084 + 0.45329594617336499 + 0.45330953208134911 + 0.45332311853121288 + 0.45333670552298833 + 0.45335029305671176 + 0.45336388113241854 + 0.45337746975014492 + 0.45339105890992643 + 0.45340464861179819 + 0.45341823885579446 + 0.45343182964195272 + 0.45344542097030716 + 0.45345901284089418 + 0.45347260525374794 + 0.45348619820890496 + 0.45349979170640053 + 0.45351338574627098 + 0.45352698032855171 + 0.45354057545327575 + 0.45355417112048174 + 0.45356776733020393 + 0.45358136408247773 + 0.45359496137733835 + 0.45360855921482224 + 0.45362215759496471 + 0.45363575651780119 + 0.45364935598336692 + 0.45366295599169731 + 0.45367655654282868 + 0.4536901576367966 + 0.45370375927363621 + 0.45371736145338298 + 0.45373096417607328 + 0.45374456744174141 + 0.45375817125042373 + 0.45377177560215576 + 0.45378538049697281 + 0.45379898593491014 + 0.45381259191600554 + 0.45382619844029187 + 0.45383980550780467 + 0.45385341311858274 + 0.4538670212726591 + 0.45388062997006917 + 0.45389423921085043 + 0.45390784899503617 + 0.45392145932266398 + 0.45393507019376927 + 0.45394868160838631 + 0.45396229356655149 + 0.4539759060683014 + 0.45398951911367036 + 0.45400313270269482 + 0.4540167468354091 + 0.45403036151185083 + 0.45404397673205432 + 0.45405759249605493 + 0.45407120880389029 + 0.4540848256555936 + 0.45409844305120267 + 0.45411206099075158 + 0.45412567947427684 + 0.454139298501814 + 0.45415291807339853 + 0.45416653818906677 + 0.45418015884885327 + 0.45419378005279448 + 0.45420740180092578 + 0.45422102409328369 + 0.45423464692990262 + 0.45424827031082032 + 0.45426189423606878 + 0.454275518705689 + 0.45428914371971202 + 0.45430276927817559 + 0.45431639538111501 + 0.45433002202856693 + 0.45434364922056569 + 0.45435727695714789 + 0.454370905238349 + 0.45438453406420448 + 0.45439816343475081 + 0.45441179335002468 + 0.45442542381005818 + 0.45443905481489139 + 0.45445268636455732 + 0.45446631845909269 + 0.45447995109853301 + 0.45449358428291481 + 0.45450721801227251 + 0.45452085228664274 + 0.45453448710606204 + 0.45454812247056486 + 0.45456175838018659 + 0.45457539483496512 + 0.45458903183493471 + 0.45460266938013089 + 0.45461630747059145 + 0.45462994610634955 + 0.45464358528744314 + 0.45465722501390649 + 0.45467086528577721 + 0.45468450610308891 + 0.45469814746587911 + 0.45471178937418338 + 0.45472543182803737 + 0.45473907482747644 + 0.45475271837253722 + 0.4547663624632543 + 0.45478000709966537 + 0.45479365228180491 + 0.45480729800970937 + 0.45482094428341452 + 0.45483459110295577 + 0.45484823846836991 + 0.45486188637969138 + 0.45487553483695775 + 0.45488918384020482 + 0.45490283338946685 + 0.4549164834847797 + 0.45493013412618188 + 0.45494378531370705 + 0.45495743704739167 + 0.45497108932727254 + 0.45498474215338297 + 0.45499839552576188 + 0.45501204944444384 + 0.45502570390946434 + 0.45503935892086 + 0.45505301447866658 + 0.45506667058292072 + 0.45508032723365677 + 0.45509398443091165 + 0.45510764217472083 + 0.45512130046512106 + 0.4551349593021467 + 0.455148618685837 + 0.45516227861622388 + 0.45517593909334647 + 0.45518960011723819 + 0.45520326168793684 + 0.45521692380547918 + 0.45523058646989834 + 0.45524424968123151 + 0.45525791343951511 + 0.45527157774478594 + 0.45528524259707864 + 0.45529890799642864 + 0.45531257394287283 + 0.45532624043644793 + 0.45533990747718961 + 0.45535357506513346 + 0.45536724320031513 + 0.45538091188277136 + 0.45539458111253678 + 0.4554082508896492 + 0.45542192121414421 + 0.45543559208605761 + 0.45544926350542497 + 0.45546293547228311 + 0.45547660798666767 + 0.45549028104861539 + 0.45550395465816085 + 0.45551762881534091 + 0.45553130352019233 + 0.45554497877274963 + 0.45555865457304945 + 0.45557233092112892 + 0.45558600781702352 + 0.45559968526076899 + 0.45561336325240098 + 0.4556270417919564 + 0.45564072087947077 + 0.45565440051498091 + 0.45566808069852272 + 0.45568176143013184 + 0.4556954427098438 + 0.4557091245376968 + 0.45572280691372513 + 0.45573648983796589 + 0.45575017331045348 + 0.45576385733122599 + 0.45577754190031905 + 0.45579122701776736 + 0.45580491268360979 + 0.45581859889788012 + 0.45583228566061501 + 0.45584597297185231 + 0.45585966083162582 + 0.45587334923997225 + 0.45588703819692844 + 0.45590072770253004 + 0.45591441775681296 + 0.45592810835981512 + 0.45594179951157005 + 0.45595549121211565 + 0.45596918346148763 + 0.455982876259722 + 0.45599656960685547 + 0.45601026350292384 + 0.4560239579479628 + 0.45603765294201037 + 0.45605134848510126 + 0.4560650445772701 + 0.45607874121855702 + 0.45609243840899466 + 0.456106136148622 + 0.45611983443747262 + 0.45613353327558448 + 0.45614723266299356 + 0.45616093259973539 + 0.45617463308584699 + 0.45618833412136423 + 0.45620203570632395 + 0.4562157378407608 + 0.45622944052471287 + 0.45624314375821595 + 0.4562568475413058 + 0.45627055187401827 + 0.45628425675639028 + 0.4562979621884577 + 0.45631166817025742 + 0.45632537470182521 + 0.45633908178319804 + 0.4563527894144106 + 0.45636649759550213 + 0.456380206326505 + 0.45639391560745857 + 0.45640762543839741 + 0.45642133581935956 + 0.45643504675037977 + 0.45644875823149506 + 0.45646247026274023 + 0.45647618284415431 + 0.45648989597577094 + 0.45650360965762826 + 0.45651732388976207 + 0.45653103867220945 + 0.45654475400500505 + 0.45655846988818582 + 0.45657218632178886 + 0.45658590330584881 + 0.45659962084040484 + 0.45661333892549077 + 0.45662705756114347 + 0.45664077674740106 + 0.45665449648429729 + 0.45666821677187003 + 0.4566819376101553 + 0.45669565899918912 + 0.45670938093900831 + 0.45672310342964995 + 0.45673682647114883 + 0.45675055006354304 + 0.45676427420686738 + 0.45677799890116005 + 0.45679172414645458 + 0.45680544994279032 + 0.45681917629020308 + 0.45683290318872782 + 0.45684663063840147 + 0.45686035863926105 + 0.45687408719134365 + 0.45688781629468289 + 0.45690154594931925 + 0.45691527615528632 + 0.45692900691262006 + 0.45694273822135884 + 0.45695647008153933 + 0.45697020249319548 + 0.45698393545636651 + 0.45699766897108618 + 0.45701140303739268 + 0.45702513765532288 + 0.4570388728249119 + 0.45705260854619773 + 0.45706634481921526 + 0.45708008164400149 + 0.45709381902059254 + 0.45710755694902649 + 0.45712129542933821 + 0.45713503446156478 + 0.45714877404574328 + 0.45716251418190867 + 0.45717625487009789 + 0.45718999611034916 + 0.45720373790269631 + 0.45721748024717868 + 0.45723122314383102 + 0.45724496659268948 + 0.45725871059379203 + 0.4572724551471738 + 0.45728620025287303 + 0.45729994591092432 + 0.45731369212136508 + 0.45732743888423227 + 0.45734118619956188 + 0.45735493406739119 + 0.45736868248775603 + 0.45738243146069252 + 0.45739618098623774 + 0.4574099310644289 + 0.45742368169530195 + 0.45743743287889282 + 0.45745118461524004 + 0.45746493690437712 + 0.4574786897463447 + 0.45749244314117549 + 0.45750619708890872 + 0.45751995158957842 + 0.45753370664322485 + 0.45754746224988091 + 0.4575612184095858 + 0.45757497512237466 + 0.45758873238828457 + 0.45760249020735272 + 0.45761624857961386 + 0.45763000750510657 + 0.45764376698386783 + 0.45765752701593271 + 0.45767128760133818 + 0.45768504874012178 + 0.45769881043231808 + 0.45771257267796572 + 0.45772633547710051 + 0.45774009882976086 + 0.45775386273598073 + 0.45776762719579828 + 0.45778139220924963 + 0.45779515777637203 + 0.45780892389720151 + 0.45782269057177538 + 0.45783645780012966 + 0.45785022558230154 + 0.45786399391832833 + 0.45787776280824488 + 0.45789153225208962 + 0.45790530224989756 + 0.45791907280170813 + 0.45793284390755518 + 0.45794661556747601 + 0.45796038778151016 + 0.45797416054969015 + 0.45798793387205572 + 0.45800170774864163 + 0.45801548217948523 + 0.45802925716462506 + 0.4580430327040948 + 0.45805680879793398 + 0.45807058544617774 + 0.45808436264886315 + 0.45809814040602642 + 0.45811191871770496 + 0.4581256975839359 + 0.45813947700475538 + 0.45815325698020071 + 0.45816703751030802 + 0.45818081859511456 + 0.45819460023465663 + 0.45820838242897138 + 0.45822216517809511 + 0.458235948482066 + 0.45824973234091926 + 0.45826351675469224 + 0.45827730172342207 + 0.45829108724714501 + 0.45830487332589837 + 0.45831865995971943 + 0.45833244714864341 + 0.45834623489270843 + 0.4583600231919509 + 0.45837381204640693 + 0.45838760145611512 + 0.4584013914211103 + 0.45841518194143099 + 0.45842897301711349 + 0.45844276464819395 + 0.45845655683470965 + 0.45847034957669919 + 0.45848414287419637 + 0.45849793672723976 + 0.45851173113586546 + 0.45852552610011199 + 0.45853932162001459 + 0.45855311769561041 + 0.45856691432693575 + 0.45858071151402907 + 0.45859450925692785 + 0.4586083075556659 + 0.45862210641028178 + 0.45863590582081293 + 0.45864970578729647 + 0.45866350630976777 + 0.45867730738826412 + 0.45869110902282406 + 0.45870491121348267 + 0.4587187139602773 + 0.45873251726324643 + 0.45874632112242425 + 0.45876012553785028 + 0.45877393050955961 + 0.45878773603758971 + 0.45880154212197899 + 0.45881534876276164 + 0.45882915595997714 + 0.45884296371366079 + 0.45885677202385095 + 0.45887058089058302 + 0.45888439031389427 + 0.45889820029382311 + 0.45891201083040606 + 0.45892582192367809 + 0.45893963357367801 + 0.45895344578044406 + 0.45896725854401049 + 0.45898107186441572 + 0.45899488574169622 + 0.45900870017588924 + 0.45902251516703235 + 0.45903633071516181 + 0.45905014682031509 + 0.45906396348252854 + 0.45907778070183952 + 0.45909159847828551 + 0.45910541681190392 + 0.45911923570272994 + 0.45913305515080238 + 0.45914687515615732 + 0.45916069571883339 + 0.45917451683886479 + 0.45918833851629004 + 0.45920216075114773 + 0.45921598354347187 + 0.45922980689330234 + 0.45924363080067543 + 0.45925745526562745 + 0.45927128028819492 + 0.45928510586841625 + 0.45929893200632893 + 0.45931275870196836 + 0.45932658595537312 + 0.45934041376657941 + 0.45935424213562492 + 0.45936807106254585 + 0.45938190054738109 + 0.4593957305901657 + 0.45940956119093712 + 0.45942339234973417 + 0.45943722406659204 + 0.45945105634154931 + 0.45946488917464134 + 0.45947872256590783 + 0.45949255651538301 + 0.45950639102310648 + 0.45952022608911375 + 0.45953406171344335 + 0.45954789789613165 + 0.45956173463721522 + 0.45957557193673254 + 0.45958940979471902 + 0.45960324821121329 + 0.45961708718625288 + 0.45963092671987421 + 0.4596447668121138 + 0.45965860746300907 + 0.45967244867259877 + 0.45968629044091824 + 0.45970013276800498 + 0.45971397565389766 + 0.4597278190986317 + 0.45974166310224457 + 0.45975550766477502 + 0.45976935278625952 + 0.45978319846673449 + 0.45979704470623622 + 0.45981089150480492 + 0.45982473886247566 + 0.45983858677928596 + 0.45985243525527475 + 0.45986628429047616 + 0.4598801338849301 + 0.45989398403867282 + 0.45990783475174096 + 0.45992168602417322 + 0.45993553785600511 + 0.45994939024727627 + 0.45996324319802101 + 0.45997709670827919 + 0.45999095077808727 + 0.46000480540748184 + 0.46001866059650048 + 0.46003251634518078 + 0.4600463726535603 + 0.4600602295216758 + 0.46007408694956342 + 0.46008794493726335 + 0.46010180348481083 + 0.46011566259224357 + 0.46012952225959919 + 0.46014338248691522 + 0.4601572432742283 + 0.46017110462157507 + 0.46018496652899521 + 0.4601988289965242 + 0.46021269202419868 + 0.46022655561205844 + 0.46024041976013874 + 0.46025428446847877 + 0.46026814973711366 + 0.46028201556608223 + 0.46029588195542231 + 0.46030974890517024 + 0.46032361641536274 + 0.46033748448603962 + 0.46035135311723524 + 0.46036522230898952 + 0.46037909206133798 + 0.46039296237431943 + 0.46040683324797027 + 0.46042070468232832 + 0.46043457667743132 + 0.46044844923331685 + 0.46046232235002044 + 0.460476196027581 + 0.46049007026603728 + 0.46050394506542347 + 0.46051782042577982 + 0.46053169634714275 + 0.46054557282954778 + 0.4605594498730371 + 0.4605733274776429 + 0.46058720564340611 + 0.46060108437036235 + 0.46061496365855048 + 0.46062884350800698 + 0.46064272391876865 + 0.46065660489087423 + 0.46067048642436143 + 0.46068436851926703 + 0.46069825117562863 + 0.46071213439348291 + 0.46072601817286873 + 0.4607399025138228 + 0.46075378741638168 + 0.46076767288058534 + 0.46078155890646938 + 0.46079544549407159 + 0.46080933264342966 + 0.46082322035458134 + 0.46083710862756444 + 0.46085099746241459 + 0.46086488685917165 + 0.46087877681787243 + 0.4608926673385535 + 0.46090655842125383 + 0.4609204500660089 + 0.46093434227285868 + 0.46094823504184002 + 0.4609621283729895 + 0.46097602226634493 + 0.460989916721943 + 0.46100381173982485 + 0.4610177073200239 + 0.46103160346257999 + 0.4610455001675301 + 0.46105939743491292 + 0.46107329526476298 + 0.46108719365712164 + 0.46110109261202309 + 0.46111499212950752 + 0.46112889220961051 + 0.4611427928523722 + 0.46115669405782816 + 0.46117059582601605 + 0.46118449815697388 + 0.46119840105073945 + 0.46121230450735068 + 0.46122620852684426 + 0.46124011310925789 + 0.46125401825463064 + 0.46126792396299826 + 0.46128183023439956 + 0.4612957370688725 + 0.46130964446645378 + 0.46132355242717998 + 0.46133746095109157 + 0.46135137003822502 + 0.46136527968861724 + 0.46137918990230598 + 0.46139310067933026 + 0.46140701201972684 + 0.46142092392353262 + 0.46143483639078642 + 0.46144874942152508 + 0.46146266301578776 + 0.46147657717360985 + 0.46149049189503166 + 0.46150440718008878 + 0.46151832302882029 + 0.46153223944126293 + 0.46154615641745456 + 0.4615600739574332 + 0.46157399206123678 + 0.46158791072890304 + 0.46160182996046895 + 0.46161574975597347 + 0.46162967011545236 + 0.46164359103894564 + 0.46165751252648907 + 0.46167143457812182 + 0.46168535719388171 + 0.46169928037380442 + 0.46171320411793015 + 0.46172712842629687 + 0.46174105329894022 + 0.46175497873589821 + 0.46176890473720988 + 0.46178283130291325 + 0.46179675843304513 + 0.46181068612764226 + 0.46182461438674488 + 0.46183854321038997 + 0.46185247259861423 + 0.46186640255145561 + 0.46188033306895332 + 0.46189426415114521 + 0.46190819579806597 + 0.46192212800975807 + 0.46193606078625499 + 0.46194999412759813 + 0.46196392803382319 + 0.46197786250496797 + 0.46199179754107078 + 0.46200573314216942 + 0.46201966930830318 + 0.4620336060395076 + 0.46204754333582193 + 0.46206148119728302 + 0.46207541962393006 + 0.46208935861579992 + 0.46210329817293044 + 0.46211723829535989 + 0.46213117898312628 + 0.46214512023626736 + 0.46215906205482027 + 0.46217300443882414 + 0.46218694738831573 + 0.46220089090333444 + 0.46221483498391697 + 0.46222877963010023 + 0.46224272484192469 + 0.4622566706194271 + 0.46227061696264454 + 0.46228456387161482 + 0.4622985113463785 + 0.46231245938697013 + 0.46232640799342994 + 0.46234035716579391 + 0.46235430690410223 + 0.46236825720839192 + 0.46238220807870095 + 0.46239615951506641 + 0.46241011151752731 + 0.4624240640861208 + 0.4624380172208859 + 0.46245197092185969 + 0.4624659251890802 + 0.46247988002258561 + 0.46249383542241485 + 0.46250779138860415 + 0.46252174792119244 + 0.4625357050202179 + 0.46254966268571873 + 0.46256362091773184 + 0.46257757971629526 + 0.46259153908144829 + 0.46260549901322784 + 0.46261945951167333 + 0.46263342057682044 + 0.46264738220870966 + 0.46266134440737672 + 0.46267530717286098 + 0.46268927050520059 + 0.4627032344044324 + 0.46271719887059698 + 0.46273116390373009 + 0.46274512950387003 + 0.46275909567105578 + 0.46277306240532451 + 0.46278702970671448 + 0.46280099757526483 + 0.46281496601101141 + 0.46282893501399475 + 0.46284290458425176 + 0.46285687472181963 + 0.46287084542673862 + 0.46288481669904463 + 0.46289878853877597 + 0.462912760945973 + 0.46292673392067163 + 0.46294070746291105 + 0.46295468157272851 + 0.46296865625016326 + 0.4629826314952511 + 0.46299660730803371 + 0.46301058368854586 + 0.46302456063682806 + 0.46303853815291729 + 0.46305251623685173 + 0.46306649488866969 + 0.46308047410840925 + 0.46309445389610865 + 0.4631084342518062 + 0.46312241517553987 + 0.46313639666734707 + 0.46315037872726805 + 0.46316436135533867 + 0.46317834455159856 + 0.46319232831608581 + 0.46320631264883744 + 0.46322029754989291 + 0.46323428301928932 + 0.46324826905706712 + 0.46326225566326112 + 0.46327624283791075 + 0.46329023058105651 + 0.46330421889273443 + 0.46331820777298255 + 0.46333219722183933 + 0.46334618723934412 + 0.4633601778255339 + 0.46337416898044825 + 0.46338816070412425 + 0.46340215299660004 + 0.46341614585791407 + 0.4634301392881045 + 0.46344413328721062 + 0.46345812785526863 + 0.46347212299231894 + 0.46348611869839884 + 0.46350011497354654 + 0.46351411181780144 + 0.46352810923119953 + 0.46354210721378025 + 0.46355610576558309 + 0.46357010488664513 + 0.46358410457700461 + 0.46359810483669894 + 0.4636121056657696 + 0.46362610706425045 + 0.46364010903218306 + 0.4636541115696049 + 0.46366811467655394 + 0.46368211835306994 + 0.46369612259918874 + 0.46371012741495093 + 0.46372413280039282 + 0.46373813875555353 + 0.46375214528047382 + 0.46376615237518753 + 0.46378016003973632 + 0.46379416827415754 + 0.46380817707848915 + 0.46382218645277107 + 0.46383619639704021 + 0.46385020691133405 + 0.46386421799569294 + 0.46387822965015424 + 0.46389224187475747 + 0.46390625466953966 + 0.4639202680345394 + 0.46393428196979497 + 0.46394829647534586 + 0.46396231155122936 + 0.46397632719748372 + 0.46399034341414969 + 0.46400436020126223 + 0.46401837755886188 + 0.46403239548698605 + 0.46404641398567542 + 0.46406043305496475 + 0.46407445269489489 + 0.46408847290550415 + 0.46410249368683093 + 0.46411651503891244 + 0.46413053696178846 + 0.46414455945549721 + 0.46415858252007691 + 0.46417260615556521 + 0.46418663036200258 + 0.46420065513942638 + 0.46421468048787384 + 0.46422870640738562 + 0.46424273289799911 + 0.46425675995975257 + 0.46427078759268581 + 0.46428481579683584 + 0.46429884457224141 + 0.46431287391894066 + 0.46432690383697334 + 0.4643409343263778 + 0.46435496538719145 + 0.46436899701945383 + 0.46438302922320218 + 0.4643970619984773 + 0.46441109534531427 + 0.46442512926375479 + 0.46443916375383648 + 0.46445319881559749 + 0.4644672344490765 + 0.46448127065431305 + 0.46449530743134332 + 0.464509344780208 + 0.46452338270094462 + 0.46453742119359248 + 0.46455146025818933 + 0.4645654998947733 + 0.46457954010338531 + 0.46459358088406166 + 0.46460762223684299 + 0.46462166416176437 + 0.46463570665886772 + 0.46464974972819167 + 0.46466379336977237 + 0.4646778375836505 + 0.46469188236986358 + 0.46470592772845004 + 0.4647199736594495 + 0.46473402016290066 + 0.46474806723884071 + 0.46476211488731051 + 0.4647761631083463 + 0.46479021190198777 + 0.46480426126827346 + 0.46481831120724304 + 0.46483236171893266 + 0.46484641280338335 + 0.46486046446063228 + 0.4648745166907205 + 0.46488856949368296 + 0.46490262286956169 + 0.46491667681839405 + 0.46493073134021878 + 0.46494478643507414 + 0.46495884210299904 + 0.46497289834403177 + 0.46498695515821209 + 0.46500101254557874 + 0.46501507050616897 + 0.46502912904002247 + 0.46504318814717793 + 0.46505724782767399 + 0.46507130808154895 + 0.46508536890884283 + 0.46509943030959294 + 0.4651134922838378 + 0.46512755483161744 + 0.4651416179529701 + 0.46515568164793464 + 0.46516974591654947 + 0.46518381075885329 + 0.46519787617488478 + 0.46521194216468353 + 0.46522600872828701 + 0.46524007586573518 + 0.46525414357706646 + 0.4652682118623197 + 0.46528228072153316 + 0.46529635015474569 + 0.4653104201619972 + 0.46532449074332477 + 0.46533856189876854 + 0.46535263362836721 + 0.4653667059321579 + 0.46538077881018175 + 0.46539485226247629 + 0.46540892628908004 + 0.46542300089003291 + 0.46543707606537355 + 0.46545115181513952 + 0.46546522813937047 + 0.46547930503810619 + 0.46549338251138439 + 0.46550746055924358 + 0.46552153918172473 + 0.4655356183788632 + 0.46554969815070107 + 0.46556377849727559 + 0.46557785941862584 + 0.46559194091479156 + 0.46560602298581 + 0.46562010563172135 + 0.46563418885256397 + 0.46564827264837688 + 0.46566235701919856 + 0.4656764419650678 + 0.46569052748602557 + 0.46570461358210818 + 0.46571870025335571 + 0.46573278749980779 + 0.46574687532150094 + 0.4657609637184762 + 0.4657750526907723 + 0.46578914223842666 + 0.46580323236147936 + 0.46581732305997015 + 0.4658314143339376 + 0.46584550618341841 + 0.46585959860845472 + 0.46587369160908287 + 0.46588778518534396 + 0.46590187933727562 + 0.46591597406491647 + 0.46593006936830761 + 0.46594416524748544 + 0.46595826170249005 + 0.46597235873336118 + 0.46598645634013652 + 0.46600055452285472 + 0.46601465328155689 + 0.46602875261628074 + 0.46604285252706484 + 0.46605695301394934 + 0.46607105407697175 + 0.46608515571617198 + 0.46609925793158991 + 0.46611336072326337 + 0.46612746409123096 + 0.46614156803553275 + 0.46615567255620738 + 0.46616977765329254 + 0.46618388332683058 + 0.46619798957685787 + 0.46621209640341454 + 0.46622620380653917 + 0.46624031178627184 + 0.46625442034264908 + 0.46626852947571296 + 0.46628263918550023 + 0.46629674947205196 + 0.4663108603354057 + 0.46632497177560039 + 0.46633908379267597 + 0.46635319638667244 + 0.46636730955762751 + 0.4663814233055788 + 0.46639553763056851 + 0.46640965253263456 + 0.46642376801181668 + 0.46643788406815162 + 0.46645200070168047 + 0.46646611791244202 + 0.46648023570047631 + 0.46649435406582102 + 0.46650847300851517 + 0.46652259252859857 + 0.46653671262611124 + 0.46655083330109109 + 0.46656495455357677 + 0.4665790763836084 + 0.46659319879122613 + 0.46660732177646624 + 0.46662144533937128 + 0.46663556947997792 + 0.46664969419832703 + 0.46666381949445546 + 0.46667794536840546 + 0.46669207182021366 + 0.46670619884992115 + 0.46672032645756467 + 0.46673445464318652 + 0.4667485834068244 + 0.46676271274851611 + 0.46677684266830416 + 0.46679097316622487 + 0.46680510424231847 + 0.46681923589662394 + 0.46683336812918114 + 0.46684750094002814 + 0.46686163432920597 + 0.46687576829675237 + 0.46688990284270748 + 0.46690403796711039 + 0.46691817366999872 + 0.46693230995141488 + 0.46694644681139552 + 0.4669605842499796 + 0.46697472226720949 + 0.46698886086312191 + 0.46700300003775691 + 0.4670171397911535 + 0.46703128012335049 + 0.46704542103438818 + 0.46705956252430547 + 0.46707370459314129 + 0.46708784724093694 + 0.46710199046772799 + 0.46711613427355786 + 0.46713027865846224 + 0.46714442362248354 + 0.46715856916565951 + 0.46717271528802817 + 0.46718686198963172 + 0.46720100927050706 + 0.46721515713069528 + 0.4672293055702344 + 0.46724345458916461 + 0.46725760418752582 + 0.46727175436535606 + 0.46728590512269558 + 0.46730005645958311 + 0.46731420837605792 + 0.46732836087216012 + 0.46734251394792875 + 0.46735666760340383 + 0.46737082183862333 + 0.46738497665362749 + 0.46739913204845657 + 0.46741328802314819 + 0.4674274445777426 + 0.467441601712279 + 0.46745575942679757 + 0.46746991772133728 + 0.46748407659593716 + 0.46749823605063739 + 0.46751239608547701 + 0.46752655670049531 + 0.46754071789573109 + 0.46755487967122461 + 0.46756904202701627 + 0.46758320496314371 + 0.46759736847964734 + 0.46761153257656723 + 0.46762569725394143 + 0.46763986251181022 + 0.46765402835021264 + 0.46766819476918764 + 0.46768236176877676 + 0.4676965293490179 + 0.46771069750995009 + 0.4677248662516148 + 0.46773903557404989 + 0.4677532054772946 + 0.46776737596139023 + 0.46778154702637481 + 0.46779571867228742 + 0.46780989089916936 + 0.46782406370705881 + 0.46783823709599698 + 0.46785241106602082 + 0.46786658561717176 + 0.46788076074948765 + 0.46789493646301 + 0.46790911275777686 + 0.46792328963382834 + 0.46793746709120493 + 0.46795164512994453 + 0.46796582375008744 + 0.46798000295167391 + 0.46799418273474308 + 0.46800836309933308 + 0.46802254404548632 + 0.46803672557323983 + 0.46805090768263385 + 0.46806509037370875 + 0.46807927364650365 + 0.46809345750105874 + 0.46810764193741222 + 0.46812182695560556 + 0.46813601255567666 + 0.46815019873766595 + 0.46816438550161255 + 0.46817857284755687 + 0.46819276077553917 + 0.46820694928559631 + 0.46822113837776996 + 0.46823532805210027 + 0.46824951830862543 + 0.46826370914738691 + 0.46827790056842267 + 0.46829209257177323 + 0.46830628515747652 + 0.46832047832557522 + 0.46833467207610741 + 0.46834886640911227 + 0.46836306132462907 + 0.46837725682270048 + 0.46839145290336232 + 0.4684056495666572 + 0.46841984681262322 + 0.46843404464130078 + 0.46844824305273014 + 0.4684624420469497 + 0.4684766416239996 + 0.46849084178391909 + 0.46850504252674985 + 0.46851924385252869 + 0.46853344576129841 + 0.46854764825309708 + 0.46856185132796396 + 0.46857605498593952 + 0.4685902592270641 + 0.46860446405137701 + 0.46861866945891745 + 0.46863287544972593 + 0.46864708202384053 + 0.46866128918130295 + 0.46867549692215221 + 0.46868970524642906 + 0.46870391415417256 + 0.46871812364542098 + 0.468732333720217 + 0.46874654437859875 + 0.46876075562060554 + 0.46877496744627783 + 0.46878917985565494 + 0.46880339284877853 + 0.46881760642568665 + 0.46883182058641865 + 0.46884603533101621 + 0.46886025065951858 + 0.46887446657196385 + 0.46888868306839393 + 0.46890290014884789 + 0.4689171178133662 + 0.46893133606198723 + 0.46894555489475365 + 0.46895977431170133 + 0.46897399431287312 + 0.46898821489830828 + 0.46900243606804626 + 0.46901665782212637 + 0.46903088016059025 + 0.46904510308347608 + 0.46905932659082444 + 0.46907355068267581 + 0.46908777535906843 + 0.46910200062004381 + 0.46911622646564149 + 0.46913045289590199 + 0.46914467991086234 + 0.46915890751056649 + 0.46917313569505154 + 0.46918736446435799 + 0.46920159381852655 + 0.46921582375759752 + 0.46923005428160819 + 0.46924428539060242 + 0.46925851708461613 + 0.46927274936369234 + 0.46928698222786913 + 0.46930121567718835 + 0.4693154497116882 + 0.4693296843314092 + 0.46934391953639087 + 0.46935815532667474 + 0.46937239170229927 + 0.46938662866330499 + 0.4694008662097312 + 0.46941510434161982 + 0.46942934305900896 + 0.46944358236193928 + 0.46945782225045024 + 0.46947206272458353 + 0.46948630378437639 + 0.46950054542987163 + 0.4695147876611076 + 0.46952903047812478 + 0.4695432738809639 + 0.46955751786966438 + 0.46957176244426568 + 0.46958600760480845 + 0.4696002533513321 + 0.46961449968387836 + 0.46962874660248571 + 0.46964299410719568 + 0.46965724219804567 + 0.46967149087507853 + 0.4696857401383337 + 0.46969998998784956 + 0.46971424042366794 + 0.4697284914458294 + 0.4697427430543723 + 0.46975699524933728 + 0.46977124803076509 + 0.46978550139869513 + 0.46979975535316809 + 0.46981400989422345 + 0.46982826502190189 + 0.46984252073624305 + 0.4698567770372884 + 0.46987103392507545 + 0.46988529139964602 + 0.46989954946104184 + 0.46991380810930011 + 0.4699280673444628 + 0.46994232716656814 + 0.46995658757565922 + 0.46997084857177329 + 0.46998511015495215 + 0.46999937232523642 + 0.47001363508266458 + 0.47002789842727843 + 0.47004216235911767 + 0.47005642687822169 + 0.47007069198463131 + 0.47008495767838709 + 0.4700992239595288 + 0.47011349082809695 + 0.47012775828413006 + 0.47014202632767133 + 0.47015629495875882 + 0.47017056417743353 + 0.47018483398373501 + 0.4701991043777039 + 0.47021337535938218 + 0.47022764692880592 + 0.47024191908601926 + 0.47025619183106088 + 0.47027046516397125 + 0.47028473908479129 + 0.47029901359355941 + 0.47031328869031752 + 0.4703275643751052 + 0.47034184064796219 + 0.47035611750893142 + 0.47037039495805022 + 0.47038467299535941 + 0.47039895162090084 + 0.47041323083471193 + 0.47042751063683685 + 0.47044179102731298 + 0.47045607200618111 + 0.4704703535734831 + 0.47048463572925747 + 0.47049891847354397 + 0.47051320180638556 + 0.47052748572782077 + 0.47054177023789051 + 0.47055605533663436 + 0.47057034102409417 + 0.47058462730030859 + 0.47059891416531957 + 0.47061320161916442 + 0.47062748966188866 + 0.47064177829352727 + 0.47065606751412459 + 0.47067035732371898 + 0.47068464772235036 + 0.4706989387100618 + 0.47071323028689055 + 0.47072752245287874 + 0.47074181520806607 + 0.47075610855249328 + 0.47077040248620122 + 0.47078469700922981 + 0.47079899212161963 + 0.47081328782341053 + 0.47082758411464337 + 0.47084188099535895 + 0.47085617846559702 + 0.47087047652539843 + 0.47088477517480287 + 0.47089907441385254 + 0.47091337424258589 + 0.47092767466104368 + 0.4709419756692681 + 0.47095627726729777 + 0.47097057945517351 + 0.47098488223293616 + 0.4709991856006267 + 0.47101348955828487 + 0.47102779410595152 + 0.47104209924366641 + 0.4710564049714705 + 0.47107071128940464 + 0.4710850181975087 + 0.47109932569582458 + 0.47111363378438975 + 0.47112794246324885 + 0.47114225173243901 + 0.47115656159200142 + 0.47117087204197794 + 0.47118518308240848 + 0.47119949471333289 + 0.47121380693479198 + 0.47122811974682677 + 0.47124243314947806 + 0.47125674714278581 + 0.47127106172678979 + 0.4712853769015321 + 0.47129969266705252 + 0.47131400902339082 + 0.47132832597059038 + 0.47134264350868849 + 0.47135696163772756 + 0.47137128035774839 + 0.47138559966878957 + 0.47139991957089339 + 0.47141424006410076 + 0.47142856114845155 + 0.4714428828239855 + 0.4714572050907449 + 0.4714715279487694 + 0.47148585139810012 + 0.47150017543877693 + 0.47151450007084078 + 0.47152882529433371 + 0.47154315110929457 + 0.47155747751576327 + 0.47157180451378289 + 0.47158613210339234 + 0.4716004602846337 + 0.47161478905754578 + 0.47162911842217065 + 0.47164344837854943 + 0.47165777892672067 + 0.47167211006672677 + 0.47168644179860747 + 0.47170077412240496 + 0.47171510703815811 + 0.47172944054590898 + 0.47174377464569744 + 0.47175810933756462 + 0.47177244462155044 + 0.47178678049769696 + 0.47180111696604315 + 0.47181545402663222 + 0.47182979167950301 + 0.47184412992469527 + 0.47185846876225152 + 0.47187280819221367 + 0.47188714821461952 + 0.47190148882951133 + 0.47191583003692994 + 0.47193017183691671 + 0.47194451422951028 + 0.47195885721475295 + 0.47197320079268573 + 0.47198754496334744 + 0.47200188972678153 + 0.47201623508302798 + 0.47203058103212664 + 0.47204492757411859 + 0.47205927470904502 + 0.47207362243694595 + 0.47208797075786468 + 0.47210231967183774 + 0.47211666917890971 + 0.47213101927911955 + 0.47214536997250928 + 0.47215972125911793 + 0.47217407313898768 + 0.47218842561215979 + 0.47220277867867405 + 0.47221713233857182 + 0.47223148659189285 + 0.47224584143867959 + 0.47226019687897214 + 0.47227455291281256 + 0.47228890954023867 + 0.47230326676129397 + 0.4723176245760195 + 0.47233198298445439 + 0.47234634198664066 + 0.47236070158261839 + 0.47237506177242994 + 0.47238942255611432 + 0.47240378393371368 + 0.4724181459052692 + 0.47243250847082102 + 0.47244687163041033 + 0.47246123538407697 + 0.47247559973186354 + 0.4724899646738111 + 0.47250433020995852 + 0.47251869634034943 + 0.47253306306502152 + 0.4725474303840182 + 0.47256179829738082 + 0.47257616680514825 + 0.47259053590736172 + 0.47260490560406465 + 0.4726192758952949 + 0.47263364678109598 + 0.47264801826150682 + 0.47266239033656982 + 0.47267676300632511 + 0.47269113627081488 + 0.47270551013007822 + 0.47271988458415759 + 0.4727342596330929 + 0.47274863527692551 + 0.47276301151569783 + 0.47277738834944993 + 0.47279176577822196 + 0.47280614380205621 + 0.47282052242099176 + 0.47283490163507336 + 0.47284928144433752 + 0.47286366184882789 + 0.47287804284858698 + 0.47289242444365259 + 0.47290680663406698 + 0.47292118941987155 + 0.47293557280110654 + 0.47294995677781537 + 0.47296434135003607 + 0.47297872651781087 + 0.47299311228118118 + 0.47300749864018832 + 0.47302188559487346 + 0.47303627314527702 + 0.4730506612914388 + 0.47306505003340282 + 0.47307943937120889 + 0.4730938293048973 + 0.47310821983451073 + 0.47312261096008901 + 0.47313700268167364 + 0.47315139499930481 + 0.4731657879130261 + 0.47318018142287666 + 0.47319457552889771 + 0.47320897023113173 + 0.47322336552961897 + 0.47323776142439961 + 0.47325215791551734 + 0.47326655500301013 + 0.47328095268692255 + 0.47329535096729258 + 0.47330974984416296 + 0.47332414931757599 + 0.47333854938757075 + 0.47335295005418876 + 0.47336735131747237 + 0.47338175317746295 + 0.47339615563419979 + 0.4734105586877253 + 0.47342496233808073 + 0.47343936658530761 + 0.47345377142944739 + 0.47346817687053899 + 0.47348258290862633 + 0.47349698954374952 + 0.47351139677594989 + 0.47352580460526905 + 0.47354021303174709 + 0.47355462205542664 + 0.47356903167634795 + 0.47358344189455248 + 0.47359785271008381 + 0.47361226412297891 + 0.47362667613328147 + 0.47364108874103295 + 0.47365550194627482 + 0.47366991574904721 + 0.47368433014939276 + 0.47369874514735183 + 0.47371316074296466 + 0.4737275769362751 + 0.47374199372732217 + 0.47375641111614847 + 0.47377082910279561 + 0.47378524768730484 + 0.47379966686971547 + 0.4738140866500713 + 0.47382850702841245 + 0.47384292800478062 + 0.4738573495792171 + 0.47387177175176354 + 0.47388619452246011 + 0.47390061789135074 + 0.47391504185847327 + 0.47392946642387174 + 0.47394389158758626 + 0.47395831734965843 + 0.47397274371013093 + 0.47398717066904289 + 0.47400159822643706 + 0.47401602638235479 + 0.47403045513683773 + 0.47404488448992621 + 0.47405931444166288 + 0.47407374499208804 + 0.47408817614124338 + 0.47410260788917147 + 0.47411704023591156 + 0.47413147318150733 + 0.47414590672599943 + 0.4741603408694281 + 0.47417477561183713 + 0.47418921095326588 + 0.47420364689375694 + 0.47421808343335081 + 0.4742325205720902 + 0.4742469583100154 + 0.47426139664716793 + 0.47427583558359077 + 0.47429027511932403 + 0.47430471525440943 + 0.47431915598888852 + 0.47433359732280284 + 0.47434803925619407 + 0.47436248178910356 + 0.47437692492157207 + 0.47439136865364323 + 0.47440581298535528 + 0.47442025791675313 + 0.47443470344787619 + 0.47444914957876727 + 0.47446359630946561 + 0.47447804364001617 + 0.47449249157045714 + 0.47450694010083255 + 0.47452138923118264 + 0.47453583896155049 + 0.47455028929197501 + 0.47456474022249939 + 0.47457919175316621 + 0.47459364388401465 + 0.4746080966150889 + 0.47462254994642805 + 0.47463700387807506 + 0.47465145841007039 + 0.47466591354245796 + 0.47468036927527824 + 0.47469482560857179 + 0.47470928254238015 + 0.47472374007674739 + 0.4747381982117127 + 0.47475265694731911 + 0.47476711628360696 + 0.47478157622061917 + 0.47479603675839505 + 0.47481049789697977 + 0.47482495963641258 + 0.47483942197673529 + 0.47485388491799069 + 0.4748683484602193 + 0.47488281260346393 + 0.47489727734776527 + 0.47491174269316472 + 0.47492620863970536 + 0.47494067518742772 + 0.47495514233637337 + 0.47496961008658534 + 0.47498407843810286 + 0.47499854739097119 + 0.47501301694522735 + 0.47502748710091791 + 0.47504195785808206 + 0.47505642921676139 + 0.47507090117699796 + 0.47508537373883442 + 0.4750998469023115 + 0.47511432066747078 + 0.47512879503435407 + 0.47514327000300427 + 0.47515774557346196 + 0.4751722217457689 + 0.47518669851996798 + 0.47520117589609862 + 0.47521565387420606 + 0.47523013245432855 + 0.47524461163651027 + 0.4752590914207917 + 0.4752735718072158 + 0.4752880527958232 + 0.47530253438665571 + 0.47531701657975622 + 0.47533149937516539 + 0.475345982772926 + 0.47536046677307892 + 0.47537495137566693 + 0.47538943658073191 + 0.47540392238831436 + 0.47541840879845626 + 0.47543289581120152 + 0.47544738342658988 + 0.47546187164466291 + 0.47547636046546482 + 0.47549084988903628 + 0.47550533991541799 + 0.4755198305446528 + 0.47553432177678262 + 0.4755488136118492 + 0.47556330604989444 + 0.4755777990909601 + 0.47559229273508818 + 0.47560678698232151 + 0.47562128183269964 + 0.47563577728626671 + 0.47565027334306342 + 0.47566477000313279 + 0.47567926726651555 + 0.47569376513325468 + 0.47570826360338975 + 0.47572276267696595 + 0.47573726235402292 + 0.475751762634605 + 0.47576626351875029 + 0.47578076500650318 + 0.47579526709790665 + 0.47580976979300016 + 0.47582427309182812 + 0.47583877699443117 + 0.47585328150085104 + 0.47586778661112977 + 0.47588229232530921 + 0.47589679864343243 + 0.47591130556554023 + 0.47592581309167548 + 0.47594032122188029 + 0.47595482995619537 + 0.47596933929466367 + 0.47598384923732717 + 0.47599835978422789 + 0.47601287093540751 + 0.47602738269090933 + 0.47604189505077282 + 0.47605640801504245 + 0.47607092158375863 + 0.47608543575696477 + 0.47609995053470155 + 0.4761144659170119 + 0.4761289819039381 + 0.47614349849552051 + 0.47615801569180377 + 0.47617253349282856 + 0.47618705189863686 + 0.4762015709092704 + 0.47621609052477265 + 0.47623061074518419 + 0.47624513157054815 + 0.47625965300090545 + 0.47627417503629915 + 0.47628869767677245 + 0.47630322092236488 + 0.47631774477312089 + 0.47633226922907995 + 0.47634679429028776 + 0.47636131995678271 + 0.47637584622861034 + 0.47639037310581023 + 0.4764049005884255 + 0.47641942867649834 + 0.47643395737007183 + 0.47644848666918554 + 0.47646301657388401 + 0.47647754708420798 + 0.47649207820020062 + 0.47650660992190402 + 0.4765211422493601 + 0.47653567518260981 + 0.47655020872169745 + 0.47656474286666389 + 0.47657927761755248 + 0.47659381297440384 + 0.47660834893726139 + 0.4766228855061671 + 0.47663742268116294 + 0.47665196046229108 + 0.47666649884959461 + 0.47668103784311344 + 0.47669557744289298 + 0.47671011764897309 + 0.47672465846139672 + 0.4767391998802063 + 0.47675374190544489 + 0.47676828453715214 + 0.4767828277753739 + 0.47679737162014968 + 0.47681191607152279 + 0.47682646112953531 + 0.47684100679422936 + 0.47685555306564703 + 0.4768700999438315 + 0.4768846474288238 + 0.4768991955206684 + 0.47691374421940502 + 0.4769282935250781 + 0.47694284343772853 + 0.4769573939573985 + 0.47697194508413249 + 0.47698649681796895 + 0.47700104915895369 + 0.47701560210712873 + 0.47703015566253498 + 0.4770447098252148 + 0.47705926459521131 + 0.4770738199725667 + 0.47708837595732312 + 0.47710293254952379 + 0.47711748974920981 + 0.47713204755642324 + 0.47714660597120861 + 0.477161164993607 + 0.47717572462365926 + 0.47719028486141102 + 0.47720484570690236 + 0.4772194071601763 + 0.4772339692212752 + 0.4772485318902413 + 0.47726309516711779 + 0.47727765905194691 + 0.47729222354476958 + 0.47730678864563053 + 0.4773213543545694 + 0.47733592067163089 + 0.47735048759685705 + 0.47736505513029143 + 0.47737962327197259 + 0.47739419202194733 + 0.47740876138025568 + 0.47742333134694098 + 0.47743790192204433 + 0.47745247310561018 + 0.47746704489768077 + 0.47748161729829586 + 0.47749619030750262 + 0.47751076392533859 + 0.47752533815185039 + 0.47753991298707815 + 0.47755448843106396 + 0.47756906448385261 + 0.47758364114548496 + 0.47759821841600336 + 0.4776127962954525 + 0.47762737478387213 + 0.47764195388130559 + 0.47765653358779664 + 0.47767111390338607 + 0.47768569482811862 + 0.47770027636203422 + 0.47771485850517631 + 0.47772944125758937 + 0.4777440246193147 + 0.47775860859039332 + 0.47777319317086986 + 0.47778777836078667 + 0.47780236416018473 + 0.47781695056910872 + 0.47783153758759989 + 0.47784612521570036 + 0.47786071345345488 + 0.47787530230090342 + 0.47788989175809177 + 0.47790448182505985 + 0.47791907250185006 + 0.47793366378850827 + 0.4779482556850731 + 0.47796284819159052 + 0.47797744130809944 + 0.4779920350346466 + 0.47800662937127342 + 0.47802122431802085 + 0.47803581987493254 + 0.4780504160420509 + 0.47806501281941927 + 0.47807961020708006 + 0.4780942082050757 + 0.47810880681344964 + 0.47812340603224418 + 0.47813800586150063 + 0.47815260630126366 + 0.47816720735157553 + 0.47818180901247753 + 0.47819641128401441 + 0.47821101416622741 + 0.47822561765915983 + 0.47824022176285441 + 0.47825482647735429 + 0.47826943180270109 + 0.47828403773893818 + 0.47829864428610785 + 0.47831325144425396 + 0.47832785921341864 + 0.47834246759364435 + 0.47835707658497478 + 0.47837168618745102 + 0.47838629640111685 + 0.47840090722601558 + 0.47841551866218873 + 0.47843013070968082 + 0.47844474336853338 + 0.47845935663878852 + 0.47847397052049007 + 0.47848858501368163 + 0.47850320011840441 + 0.47851781583470304 + 0.47853243216261787 + 0.47854704910219348 + 0.47856166665347255 + 0.47857628481649739 + 0.47859090359131035 + 0.47860552297795533 + 0.4786201429764757 + 0.47863476358691293 + 0.47864938480931057 + 0.47866400664371106 + 0.47867862909015807 + 0.47869325214869418 + 0.47870787581936186 + 0.47872250010220346 + 0.47873712499726262 + 0.47875175050458191 + 0.47876637662420513 + 0.47878100335617335 + 0.47879563070053155 + 0.47881025865732219 + 0.47882488722658662 + 0.4788395164083698 + 0.47885414620271283 + 0.47886877660966076 + 0.47888340762925363 + 0.47889803926153757 + 0.47891267150655281 + 0.478927304364344 + 0.47894193783495387 + 0.47895657191842372 + 0.47897120661479847 + 0.47898584192412175 + 0.47900047784643374 + 0.47901511438177935 + 0.47902975153020017 + 0.47904438929174192 + 0.47905902766644382 + 0.47907366665435197 + 0.47908830625550763 + 0.47910294646995588 + 0.47911758729773679 + 0.47913222873889533 + 0.4791468707934729 + 0.47916151346151564 + 0.47917615674306252 + 0.47919080063815961 + 0.47920544514684849 + 0.47922009026917273 + 0.47923473600517624 + 0.47924938235490039 + 0.47926402931838885 + 0.47927867689568437 + 0.4792933250868307 + 0.47930797389187152 + 0.47932262331084841 + 0.47933727334380499 + 0.47935192399078397 + 0.47936657525182919 + 0.47938122712698306 + 0.47939587961628977 + 0.47941053271979145 + 0.47942518643753113 + 0.47943984076955237 + 0.47945449571589804 + 0.47946915127661177 + 0.47948380745173619 + 0.4794984642413152 + 0.47951312164539023 + 0.47952777966400512 + 0.47954243829720378 + 0.47955709754502868 + 0.47957175740752389 + 0.47958641788473078 + 0.47960107897669435 + 0.47961574068345719 + 0.4796304030050621 + 0.47964506594155176 + 0.4796597294929712 + 0.47967439365936182 + 0.47968905844076754 + 0.47970372383723114 + 0.47971838984879628 + 0.47973305647550696 + 0.47974772371740476 + 0.47976239157453349 + 0.47977706004693582 + 0.47979172913465568 + 0.47980639883773818 + 0.47982106915622236 + 0.47983574009015451 + 0.47985041163957753 + 0.4798650838045338 + 0.47987975658506754 + 0.47989442998122017 + 0.47990910399303677 + 0.47992377862056007 + 0.47993845386383283 + 0.47995312972290016 + 0.47996780619780355 + 0.47998248328858584 + 0.47999716099529205 + 0.48001183931796382 + 0.48002651825664627 + 0.48004119781138216 + 0.48005587798221289 + 0.48007055876918386 + 0.48008524017233767 + 0.4800999221917171 + 0.48011460482736745 + 0.48012928807933003 + 0.48014397194764896 + 0.48015865643236705 + 0.48017334153352825 + 0.48018802725117526 + 0.48020271358535327 + 0.48021740053610285 + 0.48023208810347012 + 0.48024677628749568 + 0.48026146508822581 + 0.48027615450570105 + 0.48029084453996757 + 0.48030553519106589 + 0.48032022645904243 + 0.48033491834393766 + 0.48034961084579786 + 0.48036430396466356 + 0.4803789977005799 + 0.48039369205358973 + 0.48040838702373712 + 0.48042308261106487 + 0.480437778815617 + 0.48045247563743632 + 0.48046717307656561 + 0.48048187113305035 + 0.48049656980693306 + 0.48051126909825559 + 0.48052596900706451 + 0.48054066953339997 + 0.48055537067730741 + 0.48057007243883204 + 0.48058477481801315 + 0.48059947781489598 + 0.48061418142952589 + 0.48062888566194317 + 0.48064359051219435 + 0.48065829598032117 + 0.48067300206636782 + 0.48068770877037698 + 0.48070241609239273 + 0.48071712403245942 + 0.48073183259061841 + 0.48074654176691639 + 0.48076125156139393 + 0.480775961974095 + 0.48079067300506489 + 0.48080538465434536 + 0.48082009692198163 + 0.48083480980801674 + 0.48084952331249248 + 0.48086423743545509 + 0.48087895217694659 + 0.4808936675370109 + 0.48090838351569121 + 0.4809231001130313 + 0.48093781732907553 + 0.48095253516386671 + 0.48096725361744797 + 0.48098197268986453 + 0.48099669238115933 + 0.48101141269137415 + 0.48102613362055563 + 0.48104085516874534 + 0.48105557733598758 + 0.48107030012232532 + 0.48108502352780386 + 0.48109974755246621 + 0.48111447219635417 + 0.48112919745951427 + 0.48114392334198708 + 0.48115864984381929 + 0.48117337696505369 + 0.4811881047057322 + 0.48120283306590028 + 0.48121756204560073 + 0.48123229164487791 + 0.48124702186377483 + 0.48126175270233673 + 0.48127648416060564 + 0.48129121623862564 + 0.48130594893644091 + 0.48132068225409458 + 0.48133541619163084 + 0.4813501507490926 + 0.48136488592652549 + 0.48137962172397109 + 0.48139435814147502 + 0.48140909517907904 + 0.48142383283682871 + 0.4814385711147669 + 0.48145331001293679 + 0.48146804953138378 + 0.48148278967015085 + 0.48149753042927995 + 0.48151227180881884 + 0.48152701380880719 + 0.48154175642929153 + 0.48155649967031594 + 0.48157124353192027 + 0.48158598801415337 + 0.48160073311705581 + 0.48161547884067329 + 0.48163022518504761 + 0.48164497215022428 + 0.48165971973624638 + 0.4816744679431581 + 0.48168921677100268 + 0.48170396621982442 + 0.48171871628966756 + 0.48173346698057629 + 0.48174821829259279 + 0.4817629702257612 + 0.48177772278012698 + 0.48179247595573327 + 0.48180722975262336 + 0.48182198417084149 + 0.48183673921043185 + 0.4818514948714378 + 0.48186625115390347 + 0.48188100805787332 + 0.48189576558339042 + 0.48191052373049909 + 0.48192528249924271 + 0.48194004188966649 + 0.4819548019018125 + 0.48196956253572648 + 0.4819843237914514 + 0.4819990856690316 + 0.48201384816851034 + 0.48202861128993318 + 0.48204337503334088 + 0.48205813939878145 + 0.48207290438629674 + 0.48208766999592889 + 0.48210243622772575 + 0.4821172030817294 + 0.48213197055798301 + 0.48214673865653213 + 0.48216150737741886 + 0.48217627672068986 + 0.48219104668638602 + 0.4822058172745553 + 0.4822205884852373 + 0.48223536031847891 + 0.48225013277432333 + 0.4822649058528149 + 0.48227967955399698 + 0.48229445387791386 + 0.48230922882460997 + 0.48232400439412865 + 0.48233878058651541 + 0.48235355740181352 + 0.48236833484006519 + 0.48238311290131819 + 0.48239789158561353 + 0.48241267089299683 + 0.48242745082351135 + 0.48244223137720044 + 0.48245701255411078 + 0.4824717943542845 + 0.48248657677776607 + 0.48250135982460002 + 0.48251614349482835 + 0.48253092778849915 + 0.48254571270565322 + 0.48256049824633646 + 0.48257528441059189 + 0.48259007119846425 + 0.48260485860999786 + 0.48261964664523727 + 0.4826344353042234 + 0.48264922458700543 + 0.48266401449362323 + 0.48267880502412364 + 0.4826935961785499 + 0.48270838795694671 + 0.48272318035935718 + 0.48273797338582597 + 0.48275276703639747 + 0.48276756131111626 + 0.48278235621002574 + 0.48279715173317045 + 0.48281194788059473 + 0.48282674465234227 + 0.48284154204845842 + 0.48285634006898559 + 0.48287113871397058 + 0.48288593798345442 + 0.48290073787748528 + 0.48291553839610291 + 0.48293033953935544 + 0.48294514130728494 + 0.48295994369993628 + 0.48297474671735369 + 0.48298955035958074 + 0.48300435462666425 + 0.48301915951864538 + 0.48303396503556983 + 0.48304877117748224 + 0.48306357794442578 + 0.48307838533644543 + 0.48309319335358664 + 0.48310800199589177 + 0.48312281126340534 + 0.48313762115617326 + 0.48315243167423766 + 0.48316724281764556 + 0.48318205458643809 + 0.48319686698066328 + 0.48321168000036224 + 0.48322649364558073 + 0.48324130791636238 + 0.48325612281275288 + 0.4832709383347944 + 0.48328575448253408 + 0.48330057125601522 + 0.48331538865528145 + 0.48333020668037741 + 0.4833450253313476 + 0.48335984460823672 + 0.48337466451108957 + 0.48338948503994938 + 0.48340430619486091 + 0.48341912797586895 + 0.48343395038301795 + 0.48344877341635156 + 0.48346359707591441 + 0.48347842136175234 + 0.48349324627390883 + 0.48350807181242739 + 0.48352289797735393 + 0.48353772476873197 + 0.48355255218660598 + 0.48356738023102097 + 0.48358220890202142 + 0.48359703819965211 + 0.48361186812395662 + 0.48362669867497959 + 0.48364152985276448 + 0.48365636165735848 + 0.48367119408880388 + 0.4836860271471467 + 0.48370086083243036 + 0.48371569514469837 + 0.48373053008399791 + 0.4837453656503713 + 0.48376020184386453 + 0.48377503866452221 + 0.48378987611238689 + 0.48380471418750431 + 0.4838195528899194 + 0.48383439221967678 + 0.48384923217682008 + 0.48386407276139409 + 0.48387891397344479 + 0.48389375581301436 + 0.48390859828015015 + 0.4839234413748944 + 0.48393828509729214 + 0.48395312944738911 + 0.48396797442522776 + 0.48398282003085646 + 0.48399766626431534 + 0.48401251312565136 + 0.4840273606149107 + 0.48404220873213449 + 0.48405705747736877 + 0.48407190685065943 + 0.48408675685205022 + 0.48410160748158476 + 0.48411645873931008 + 0.48413131062526765 + 0.48414616313950448 + 0.48416101628206437 + 0.48417587005299323 + 0.48419072445233363 + 0.48420557948013138 + 0.48422043513643143 + 0.48423529142127869 + 0.48425014833471552 + 0.48426500587678922 + 0.48427986404754464 + 0.48429472284702418 + 0.48430958227527399 + 0.48432444233234007 + 0.48433930301826483 + 0.4843541643330932 + 0.48436902627687134 + 0.48438388884964267 + 0.48439875205145361 + 0.4844136158823476 + 0.48442848034236835 + 0.48444334543156203 + 0.48445821114997462 + 0.48447307749764884 + 0.48448794447463051 + 0.48450281208096341 + 0.48451768031669246 + 0.48453254918186384 + 0.48454741867652001 + 0.48456228880070823 + 0.48457715955447239 + 0.48459203093785713 + 0.48460690295090764 + 0.48462177559366748 + 0.48463664886618157 + 0.48465152276849743 + 0.48466639730065625 + 0.48468127246270648 + 0.48469614825468965 + 0.48471102467665184 + 0.48472590172863789 + 0.48474077941069421 + 0.48475565772286305 + 0.48477053666519077 + 0.48478541623772348 + 0.48480029644050249 + 0.4848151772735752 + 0.48483005873698659 + 0.48484494083078056 + 0.48485982355500307 + 0.48487470690969803 + 0.48488959089491029 + 0.48490447551068622 + 0.48491936075706832 + 0.484934246634104 + 0.48494913314183585 + 0.48496402028031127 + 0.48497890804957405 + 0.484993796449668 + 0.48500868548063941 + 0.48502357514253319 + 0.48503846543539325 + 0.48505335635926561 + 0.48506824791419551 + 0.48508314010022674 + 0.48509803291740544 + 0.48511292636577552 + 0.48512782044538311 + 0.485142715156271 + 0.48515761049848771 + 0.48517250647207477 + 0.48518740307707964 + 0.48520230031354494 + 0.4852171981815192 + 0.48523209668104406 + 0.48524699581216574 + 0.48526189557492921 + 0.48527679596938078 + 0.48529169699556329 + 0.48530659865352399 + 0.48532150094330567 + 0.48533640386495575 + 0.4853513074185169 + 0.48536621160403554 + 0.48538111642155662 + 0.48539602187112529 + 0.48541092795278673 + 0.48542583466658601 + 0.48544074201256676 + 0.48545564999077689 + 0.48547055860125887 + 0.4854854678440591 + 0.48550037771922266 + 0.48551528822679352 + 0.48553019936681918 + 0.48554511113934229 + 0.4855600235444093 + 0.4855749365820653 + 0.48558985025235535 + 0.48560476455532353 + 0.48561967949101598 + 0.48563459505947815 + 0.48564951126075501 + 0.48566442809489158 + 0.48567934556193204 + 0.48569426366192386 + 0.48570918239490984 + 0.48572410176093628 + 0.48573902176004841 + 0.48575394239229136 + 0.48576886365771033 + 0.48578378555635054 + 0.48579870808825709 + 0.48581363125347521 + 0.48582855505205003 + 0.48584347948402684 + 0.48585840454945073 + 0.4858733302483671 + 0.48588825658082208 + 0.48590318354685857 + 0.48591811114652433 + 0.48593303937986448 + 0.48594796824692177 + 0.48596289774774382 + 0.48597782788237476 + 0.48599275865086095 + 0.4860076900532464 + 0.48602262208957747 + 0.4860375547598984 + 0.48605248806425549 + 0.48606742200269271 + 0.48608235657525667 + 0.48609729178199385 + 0.48611222762294676 + 0.48612716409816231 + 0.48614210120768547 + 0.48615703895156037 + 0.48617197732983464 + 0.4861869163425524 + 0.48620185598975896 + 0.48621679627150072 + 0.48623173718782053 + 0.48624667873876615 + 0.4862616209243828 + 0.48627656374471462 + 0.48629150719980818 + 0.48630645128970856 + 0.48632139601446001 + 0.48633634137410897 + 0.48635128736870081 + 0.48636623399828072 + 0.4863811812628942 + 0.48639612916258745 + 0.48641107769740383 + 0.48642602686739067 + 0.48644097667259228 + 0.48645592711305519 + 0.48647087818882456 + 0.48648582989994471 + 0.48650078224646209 + 0.48651573522842217 + 0.48653068884586886 + 0.48654564309885134 + 0.48656059798741003 + 0.48657555351159515 + 0.48659050967144835 + 0.48660546646701747 + 0.48662042389834792 + 0.48663538196548489 + 0.48665034066847279 + 0.48666530000735914 + 0.48668025998218711 + 0.4866952205930033 + 0.48671018183985415 + 0.4867251437227838 + 0.48674010624183911 + 0.48675506939706409 + 0.48677003318850404 + 0.48678499761620814 + 0.48679996268021691 + 0.48681492838057938 + 0.48682989471734095 + 0.48684486169054347 + 0.48685982930023819 + 0.48687479754646595 + 0.48688976642927573 + 0.48690473594871053 + 0.48691970610481677 + 0.48693467689764147 + 0.48694964832722742 + 0.48696462039362359 + 0.48697959309687205 + 0.48699456643702171 + 0.48700954041411565 + 0.48702451502820165 + 0.48703949027932297 + 0.48705446616752718 + 0.48706944269285873 + 0.48708441985536433 + 0.48709939765508936 + 0.48711437609207914 + 0.48712935516637945 + 0.48714433487803438 + 0.48715931522709305 + 0.48717429621359859 + 0.48718927783759763 + 0.48720426009913442 + 0.48721924299825703 + 0.48723422653500953 + 0.48724921070943761 + 0.4872641955215879 + 0.48727918097150591 + 0.48729416705923584 + 0.48730915378482592 + 0.48732414114832018 + 0.48733912914976424 + 0.48735411778920479 + 0.4873691070666874 + 0.48738409698225632 + 0.48739908753596078 + 0.48741407872784281 + 0.48742907055795015 + 0.48744406302632842 + 0.48745905613302204 + 0.48747404987807758 + 0.48748904426154194 + 0.4875040392834607 + 0.48751903494387816 + 0.48753403124284123 + 0.48754902818039514 + 0.48756402575658692 + 0.48757902397146091 + 0.4875940228250627 + 0.48760902231743913 + 0.48762402244863678 + 0.48763902321870023 + 0.4876540246276761 + 0.48766902667560891 + 0.48768402936254551 + 0.4876990326885326 + 0.4877140366536134 + 0.48772904125783711 + 0.48774404650124703 + 0.48775905238388989 + 0.48777405890581249 + 0.48778906606705924 + 0.48780407386767705 + 0.48781908230770926 + 0.48783409138720724 + 0.48784910110621188 + 0.48786411146477138 + 0.48787912246292997 + 0.4878941341007359 + 0.48790914637823352 + 0.48792415929546967 + 0.48793917285249 + 0.48795418704933907 + 0.4879692018860648 + 0.48798421736271164 + 0.48799923347932661 + 0.48801425023595646 + 0.48802926763264465 + 0.48804428566943897 + 0.48805930434638539 + 0.48807432366352937 + 0.48808934362091672 + 0.48810436421859427 + 0.48811938545660655 + 0.48813440733500058 + 0.48814942985382298 + 0.4881644530131185 + 0.48817947681293516 + 0.48819450125331626 + 0.48820952633430864 + 0.48822455205596055 + 0.48823957841831528 + 0.48825460542142107 + 0.48826963306532106 + 0.48828466135006454 + 0.48829969027569503 + 0.4883147198422606 + 0.48832975004980705 + 0.48834478089837868 + 0.48835981238802278 + 0.4883748445187861 + 0.48838987729071326 + 0.48840491070385117 + 0.48841994475824679 + 0.48843497945394471 + 0.48845001479099193 + 0.48846505076943425 + 0.48848008738931847 + 0.48849512465068945 + 0.48851016255359392 + 0.48852520109807901 + 0.48854024028418919 + 0.48855528011197152 + 0.48857032058147182 + 0.48858536169273714 + 0.48860040344581201 + 0.48861544584074457 + 0.48863048887757948 + 0.48864553255636395 + 0.48866057687714337 + 0.48867562183996516 + 0.48869066744487377 + 0.48870571369191612 + 0.48872076058113834 + 0.48873580811258716 + 0.48875085628630871 + 0.48876590510234857 + 0.48878095456075388 + 0.48879600466157047 + 0.48881105540484426 + 0.48882610679062211 + 0.48884115881895018 + 0.4888562114898729 + 0.48887126480343979 + 0.48888631875969435 + 0.48890137335868478 + 0.48891642860045592 + 0.48893148448505463 + 0.48894654101252816 + 0.48896159818292106 + 0.48897665599628043 + 0.48899171445265233 + 0.48900677355208366 + 0.48902183329462046 + 0.48903689368030967 + 0.48905195470919616 + 0.48906701638132694 + 0.48908207869674786 + 0.48909714165550744 + 0.48911220525764904 + 0.489127269503221 + 0.48914233439226923 + 0.48915739992483975 + 0.4891724661009797 + 0.48918753292073358 + 0.48920260038415003 + 0.48921766849127474 + 0.48923273724215272 + 0.48924780663683204 + 0.48926287667536 + 0.48927794735778019 + 0.48929301868413966 + 0.48930809065448688 + 0.48932316326886643 + 0.4893382365273245 + 0.48935331042990932 + 0.48936838497666579 + 0.489383460167641 + 0.48939853600288097 + 0.48941361248243276 + 0.48942868960634134 + 0.48944376737465622 + 0.48945884578742094 + 0.48947392484468283 + 0.48948900454648769 + 0.48950408489288422 + 0.48951916588391819 + 0.48953424751963437 + 0.48954932980008026 + 0.48956441272530166 + 0.48957949629534703 + 0.48959458051026117 + 0.48960966537009143 + 0.48962475087488372 + 0.48963983702468533 + 0.48965492381954223 + 0.4896700112595006 + 0.48968509934460763 + 0.4897001880749105 + 0.48971527745045407 + 0.4897303674712869 + 0.48974545813745379 + 0.48976054944900199 + 0.48977564140597757 + 0.48979073400842782 + 0.48980582725639993 + 0.48982092114993891 + 0.48983601568909196 + 0.48985111087390637 + 0.48986620670442832 + 0.48988130318070378 + 0.48989640030278131 + 0.4899114980707045 + 0.48992659648452319 + 0.48994169554428108 + 0.48995679525002778 + 0.48997189560180587 + 0.48998699659966743 + 0.49000209824365376 + 0.4900172005338147 + 0.49003230347019744 + 0.49004740705284572 + 0.49006251128180817 + 0.49007761615713197 + 0.49009272167886347 + 0.49010782784704743 + 0.49012293466173251 + 0.49013804212296597 + 0.49015315023079159 + 0.49016825898526045 + 0.49018336838641485 + 0.49019847843430353 + 0.49021358912897384 + 0.49022870047047196 + 0.49024381245884402 + 0.49025892509413749 + 0.49027403837639949 + 0.49028915230567532 + 0.49030426688201229 + 0.49031938210545878 + 0.49033449797605999 + 0.49034961449386211 + 0.49036473165891359 + 0.49037984947125973 + 0.49039496793094872 + 0.49041008703802591 + 0.49042520679253981 + 0.49044032719453545 + 0.49045544824406018 + 0.49047056994116262 + 0.49048569228588673 + 0.49050081527828104 + 0.49051593891839185 + 0.49053106320626649 + 0.49054618814195128 + 0.49056131372549361 + 0.49057643995694106 + 0.4905915668363372 + 0.49060669436373228 + 0.4906218225391723 + 0.49063695136270352 + 0.49065208083437345 + 0.4906672109542296 + 0.49068234172231706 + 0.49069747313868323 + 0.49071260520337678 + 0.49072773791644164 + 0.49074287127792771 + 0.49075800528788011 + 0.49077313994634614 + 0.49078827525337354 + 0.49080341120900844 + 0.49081854781329726 + 0.49083368506628738 + 0.49084882296802657 + 0.49086396151856071 + 0.49087910071793772 + 0.4908942405662049 + 0.49090938106340742 + 0.49092452220959282 + 0.49093966400480998 + 0.49095480644910255 + 0.49096994954252077 + 0.49098509328510942 + 0.49100023767691758 + 0.49101538271799017 + 0.49103052840837486 + 0.49104567474811922 + 0.49106082173726956 + 0.49107596937587467 + 0.49109111766397834 + 0.49110626660163087 + 0.49112141618887839 + 0.4911365664257662 + 0.49115171731234297 + 0.4911668688486564 + 0.4911820210347515 + 0.49119717387067718 + 0.49121232735647991 + 0.49122748149220724 + 0.49124263627790415 + 0.49125779171361977 + 0.4912729477994015 + 0.49128810453529587 + 0.49130326192134915 + 0.49131841995760905 + 0.49133357864412208 + 0.49134873798093681 + 0.49136389796809998 + 0.49137905860565895 + 0.49139421989365917 + 0.49140938183214927 + 0.49142454442117584 + 0.49143970766078654 + 0.49145487155102885 + 0.49147003609194828 + 0.49148520128359346 + 0.49150036712601208 + 0.49151553361924954 + 0.49153070076335337 + 0.4915458685583724 + 0.49156103700435216 + 0.49157620610134006 + 0.49159137584938506 + 0.49160654624853245 + 0.49162171729882997 + 0.49163688900032521 + 0.49165206135306477 + 0.49166723435709625 + 0.49168240801246627 + 0.49169758231922361 + 0.49171275727741492 + 0.49172793288708766 + 0.49174310914828739 + 0.49175828606106287 + 0.49177346362546076 + 0.49178864184152993 + 0.49180382070931555 + 0.49181900022886688 + 0.49183418040022892 + 0.49184936122345208 + 0.49186454269858026 + 0.4918797248256615 + 0.49189490760474558 + 0.49191009103587824 + 0.49192527511910566 + 0.49194045985447704 + 0.49195564524203889 + 0.49197083128183899 + 0.49198601797392405 + 0.49200120531834146 + 0.4920163933151393 + 0.49203158196436414 + 0.49204677126606478 + 0.49206196122028678 + 0.49207715182707912 + 0.49209234308648714 + 0.49210753499855975 + 0.49212272756334491 + 0.49213792078088803 + 0.49215311465123923 + 0.49216830917444382 + 0.49218350435054875 + 0.49219870017960382 + 0.49221389666165488 + 0.4922290937967494 + 0.49224429158493532 + 0.49225949002626052 + 0.49227468912077055 + 0.49228988886851421 + 0.49230508926953953 + 0.49232029032389418 + 0.49233549203162374 + 0.49235069439277723 + 0.4923658974074 + 0.49238110107554267 + 0.49239630539725149 + 0.4924115103725733 + 0.49242671600155602 + 0.4924419222842486 + 0.4924571292206954 + 0.49247233681094671 + 0.49248754505504805 + 0.49250275395304954 + 0.49251796350499688 + 0.49253317371093663 + 0.49254838457091915 + 0.4925635960849899 + 0.49257880825319683 + 0.49259402107558786 + 0.49260923455221084 + 0.4926244486831125 + 0.49263966346834082 + 0.49265487890794363 + 0.49267009500196779 + 0.49268531175046354 + 0.4927005291534739 + 0.49271574721105071 + 0.49273096592323923 + 0.49274618529008751 + 0.49276140531164364 + 0.49277662598795524 + 0.49279184731907055 + 0.49280706930503504 + 0.49282229194589783 + 0.49283751524170699 + 0.49285273919251038 + 0.49286796379835363 + 0.49288318905928713 + 0.49289841497535641 + 0.49291364154660949 + 0.49292886877309433 + 0.49294409665486011 + 0.49295932519195251 + 0.49297455438441951 + 0.49298978423231016 + 0.49300501473567271 + 0.49302024589455129 + 0.49303547770899653 + 0.49305071017905516 + 0.49306594330477516 + 0.49308117708620475 + 0.49309641152339045 + 0.49311164661638168 + 0.49312688236522534 + 0.49314211876996805 + 0.49315735583066034 + 0.49317259354734799 + 0.49318783192007892 + 0.4932030709489012 + 0.49321831063386284 + 0.49323355097501081 + 0.49324879197239424 + 0.49326403362605997 + 0.49327927593605631 + 0.49329451890243114 + 0.4933097625252314 + 0.49332500680450503 + 0.49334025174030149 + 0.49335549733266648 + 0.49337074358164906 + 0.49338599048729759 + 0.49340123804965874 + 0.49341648626878082 + 0.49343173514471178 + 0.49344698467749976 + 0.49346223486719293 + 0.49347748571383815 + 0.49349273721748244 + 0.4935079893781773 + 0.49352324219596622 + 0.49353849567090091 + 0.49355374980302713 + 0.49356900459239295 + 0.49358426003904649 + 0.49359951614303599 + 0.49361477290440953 + 0.49363003032321529 + 0.49364528839950006 + 0.49366054713331231 + 0.4936758065247 + 0.49369106657371248 + 0.4937063272803956 + 0.49372158864479754 + 0.49373685066696754 + 0.49375211334695279 + 0.49376737668480236 + 0.49378264068056238 + 0.49379790533428203 + 0.49381317064600955 + 0.4938284366157919 + 0.49384370324367738 + 0.49385897052971539 + 0.49387423847395273 + 0.49388950707643786 + 0.49390477633721763 + 0.49392004625634156 + 0.49393531683385783 + 0.49395058806981357 + 0.49396585996425679 + 0.49398113251723574 + 0.49399640572880016 + 0.49401167959899561 + 0.49402695412787151 + 0.49404222931547498 + 0.49405750516185559 + 0.49407278166706026 + 0.49408805883113738 + 0.49410333665413486 + 0.49411861513610256 + 0.49413389427708621 + 0.49414917407713521 + 0.4941644545362967 + 0.49417973565462014 + 0.49419501743215261 + 0.49421029986894238 + 0.49422558296503905 + 0.49424086672048961 + 0.4942561511353411 + 0.49427143620964442 + 0.4942867219434452 + 0.49430200833679322 + 0.49431729538973529 + 0.49433258310232114 + 0.49434787147459791 + 0.494363160506615 + 0.49437845019841836 + 0.49439374055005875 + 0.49440903156158333 + 0.49442432323303914 + 0.49443961556447708 + 0.49445490855594287 + 0.494470202207485 + 0.49448549651915302 + 0.49450079149099518 + 0.49451608712305872 + 0.49453138341539327 + 0.49454668036804472 + 0.49456197798106366 + 0.49457727625449766 + 0.49459257518839467 + 0.49460787478280333 + 0.49462317503777203 + 0.49463847595334898 + 0.49465377752958151 + 0.49466907976652041 + 0.4946843826642115 + 0.49469968622270344 + 0.4947149904420457 + 0.49473029532228541 + 0.49474560086347358 + 0.49476090706565479 + 0.49477621392888005 + 0.49479152145319522 + 0.49480682963865241 + 0.4948221384852966 + 0.49483744799317714 + 0.49485275816234381 + 0.49486806899284375 + 0.49488338048472563 + 0.49489869263803654 + 0.49491400545282721 + 0.49492931892914516 + 0.49494463306703745 + 0.49495994786655495 + 0.49497526332774383 + 0.49499057945065372 + 0.49500589623533309 + 0.49502121368183027 + 0.4950365317901928 + 0.49505185056047019 + 0.49506716999271089 + 0.49508249008696231 + 0.49509781084327414 + 0.49511313226169484 + 0.49512845434227282 + 0.49514377708505541 + 0.49515910049009138 + 0.49517442455743121 + 0.49518974928712128 + 0.49520507467921138 + 0.4952204007337474 + 0.49523572745078165 + 0.49525105483036136 + 0.49526638287253388 + 0.49528171157734774 + 0.49529704094485272 + 0.49531237097509739 + 0.49532770166813017 + 0.49534303302399857 + 0.49535836504275221 + 0.49537369772443851 + 0.49538903106910714 + 0.49540436507680685 + 0.49541969974758604 + 0.49543503508149328 + 0.49545037107857615 + 0.4954657077388831 + 0.49548104506246499 + 0.49549638304936938 + 0.49551172169964469 + 0.49552706101333854 + 0.49554240099050179 + 0.4955577416311806 + 0.49557308293542485 + 0.49558842490328442 + 0.49560376753480528 + 0.49561911083003873 + 0.49563445478903195 + 0.49564979941183379 + 0.49566514469849271 + 0.4956804906490585 + 0.4956958372635788 + 0.49571118454210211 + 0.49572653248467824 + 0.49574188109135464 + 0.49575723036218128 + 0.49577258029720672 + 0.49578793089647843 + 0.49580328216004627 + 0.4958186340879589 + 0.49583398668026502 + 0.49584933993701197 + 0.49586469385825094 + 0.49588004844402939 + 0.495895403694396 + 0.49591075960939951 + 0.49592611618908838 + 0.4959414734335128 + 0.49595683134272139 + 0.49597218991676029 + 0.49598754915568066 + 0.49600290905953143 + 0.49601826962836099 + 0.49603363086221819 + 0.49604899276115172 + 0.49606435532520926 + 0.49607971855444172 + 0.49609508244889666 + 0.49611044700862417 + 0.49612581223367169 + 0.49614117812408787 + 0.49615654467992276 + 0.49617191190122384 + 0.49618727978804245 + 0.4962026483404246 + 0.49621801755842043 + 0.49623338744208007 + 0.49624875799144963 + 0.49626412920658036 + 0.49627950108751989 + 0.49629487363431929 + 0.49631024684702391 + 0.49632562072568581 + 0.49634099527035175 + 0.49635637048107267 + 0.49637174635789505 + 0.49638712290087017 + 0.4964025001100455 + 0.49641787798547099 + 0.49643325652719561 + 0.49644863573526687 + 0.49646401560973502 + 0.49647939615064846 + 0.49649477735805753 + 0.49651015923200975 + 0.49652554177255392 + 0.49654092497974017 + 0.49655630885361729 + 0.49657169339423279 + 0.49658707860163814 + 0.49660246447588097 + 0.49661785101700995 + 0.49663323822507399 + 0.49664862610012328 + 0.49666401464220655 + 0.49667940385137271 + 0.49669479372767178 + 0.49671018427115027 + 0.49672557548185958 + 0.49674096735984724 + 0.49675635990516337 + 0.49677175311785804 + 0.49678714699797782 + 0.4968025415455728 + 0.49681793676069291 + 0.49683333264338603 + 0.49684872919370215 + 0.49686412641169031 + 0.49687952429740057 + 0.49689492285087938 + 0.49691032207217822 + 0.49692572196134588 + 0.49694112251843003 + 0.4969565237434822 + 0.4969719256365499 + 0.49698732819768232 + 0.49700273142692941 + 0.49701813532434008 + 0.49703353988996235 + 0.49704894512384729 + 0.49706435102604285 + 0.49707975759659911 + 0.49709516483556376 + 0.49711057274298831 + 0.49712598131892044 + 0.49714139056340922 + 0.49715680047650351 + 0.4971722110582536 + 0.49718762230870961 + 0.49720303422791923 + 0.49721844681593175 + 0.49723386007279718 + 0.49724927399856439 + 0.49726468859328143 + 0.49728010385699961 + 0.49729551978976799 + 0.49731093639163537 + 0.49732635366264999 + 0.49734177160286286 + 0.49735719021232205 + 0.49737260949107642 + 0.49738802943917876 + 0.4974034500566733 + 0.49741887134361262 + 0.49743429330004574 + 0.49744971592602172 + 0.49746513922158975 + 0.49748056318679867 + 0.49749598782169779 + 0.49751141312633823 + 0.49752683910076706 + 0.49754226574503552 + 0.49755769305919267 + 0.49757312104328649 + 0.49758854969736716 + 0.49760397902148507 + 0.4976194090156893 + 0.49763483968002759 + 0.49765027101455045 + 0.49766570301930807 + 0.49768113569434963 + 0.49769656903972165 + 0.4977120030554783 + 0.49772743774166611 + 0.49774287309833554 + 0.49775830912553432 + 0.49777374582331418 + 0.49778918319172299 + 0.49780462123081232 + 0.49782005994062867 + 0.4978354993212239 + 0.49785093937264574 + 0.49786638009494583 + 0.49788182148817212 + 0.49789726355237379 + 0.4979127062876012 + 0.49792814969390348 + 0.49794359377132968 + 0.49795903851993167 + 0.4979744839397548 + 0.49798993003085301 + 0.49800537679327328 + 0.49802082422706584 + 0.49803627233227993 + 0.49805172110896601 + 0.49806717055717203 + 0.49808262067694947 + 0.49809807146834656 + 0.49811352293141353 + 0.49812897506619963 + 0.49814442787275409 + 0.49815988135112743 + 0.49817533550136878 + 0.49819079032352737 + 0.49820624581765366 + 0.49822170198379673 + 0.49823715882200609 + 0.49825261633233192 + 0.49826807451482363 + 0.49828353336952935 + 0.4982989928965017 + 0.49831445309578887 + 0.49832991396744014 + 0.49834537551150471 + 0.4983608377280343 + 0.49837630061707699 + 0.49839176417868197 + 0.49840722841289975 + 0.4984226933197809 + 0.49843815889937454 + 0.49845362515172909 + 0.49846909207689583 + 0.49848455967492428 + 0.49850002794586262 + 0.49851549688976238 + 0.49853096650667406 + 0.49854643679664473 + 0.49856190775972486 + 0.49857737939596614 + 0.4985928517054154 + 0.49860832468812577 + 0.49862379834414405 + 0.49863927267352204 + 0.4986547476763078 + 0.49867022335255307 + 0.49868569970230614 + 0.49870117672561737 + 0.49871665442253621 + 0.49873213279311446 + 0.49874761183739785 + 0.49876309155544063 + 0.49877857194728953 + 0.49879405301299401 + 0.49880953475260725 + 0.49882501716617733 + 0.49884050025375221 + 0.49885598401538522 + 0.49887146845112429 + 0.49888695356101886 + 0.49890243934511969 + 0.49891792580347732 + 0.49893341293613985 + 0.4989489007431579 + 0.49896438922458219 + 0.49897987838046221 + 0.49899536821084706 + 0.49901085871578649 + 0.49902634989533212 + 0.49904184174953359 + 0.49905733427844018 + 0.49907282748210008 + 0.49908832136056658 + 0.49910381591388764 + 0.49911931114211405 + 0.49913480704529528 + 0.49915030362348078 + 0.49916580087672241 + 0.49918129880506712 + 0.49919679740856704 + 0.49921229668727257 + 0.4992277966412334 + 0.49924329727049771 + 0.49925879857511729 + 0.49927430055514188 + 0.49928980321062194 + 0.49930530654160588 + 0.49932081054814559 + 0.49933631523028937 + 0.49935182058808913 + 0.49936732662159322 + 0.49938283333085343 + 0.49939834071591821 + 0.4994138487768382 + 0.49942935751366413 + 0.49944486692644441 + 0.49946037701523094 + 0.49947588778007318 + 0.4994913992210207 + 0.49950691133812436 + 0.49952242413143372 + 0.49953793760099929 + 0.49955345174687088 + 0.4995689665690991 + 0.49958448206773354 + 0.49959999824282508 + 0.49961551509442309 + 0.49963103262257741 + 0.49964655082733861 + 0.49966206970875876 + 0.49967758926688388 + 0.49969310950176821 + 0.49970863041346025 + 0.49972415200200843 + 0.49973967426746579 + 0.49975519720988221 + 0.49977072082930712 + 0.49978624512578901 + 0.49980177009938087 + 0.49981729575013145 + 0.49983282207809265 + 0.49984834908331283 + 0.49986387676584293 + 0.49987940512573242 + 0.49989493416303343 + 0.49991046387779448 + 0.49992599427006523 + 0.49994152533989877 + 0.49995705708734245 + 0.49997258951244961 + 0.49998812261526737 + 0.50000365639584787 + 0.50001919085424085 + 0.50003472599049692 + 0.50005026180466605 + 0.50006579829679776 + 0.50008133546694422 + 0.50009687331515507 + 0.50011241184147892 + 0.50012795104596885 + 0.5001434909286735 + 0.50015903148964369 + 0.50017457272893051 + 0.50019011464658236 + 0.5002056572426512 + 0.5002212005171871 + 0.50023674447024191 + 0.50025228910186303 + 0.50026783441210132 + 0.50028338040100906 + 0.50029892706863588 + 0.50031447441503152 + 0.50033002244024827 + 0.50034557114433453 + 0.50036112052734005 + 0.50037667058931834 + 0.50039222133031658 + 0.50040777275038828 + 0.50042332484958185 + 0.50043887762794725 + 0.50045443108553778 + 0.50046998522240072 + 0.50048554003858836 + 0.50050109553415045 + 0.50051665170913817 + 0.50053220856360092 + 0.50054776609759 + 0.50056332431115647 + 0.50057888320434984 + 0.50059444277722009 + 0.50061000302981962 + 0.50062556396219793 + 0.50064112557440499 + 0.50065668786649176 + 0.50067225083850941 + 0.5006878144905077 + 0.50070337882253879 + 0.5007189438346501 + 0.50073450952689413 + 0.50075007589932286 + 0.50076564295198389 + 0.50078121068493064 + 0.50079677909821052 + 0.50081234819187714 + 0.50082791796598014 + 0.50084348842056958 + 0.50085905955569643 + 0.50087463137141175 + 0.50089020386776573 + 0.50090577704480777 + 0.50092135090259049 + 0.50093692544116375 + 0.50095250066057728 + 0.50096807656088482 + 0.50098365314213378 + 0.50099923040437522 + 0.50101480834766143 + 0.50103038697204239 + 0.50104596627756803 + 0.50106154626428956 + 0.50107712693225792 + 0.5010927082815243 + 0.50110829031213755 + 0.50112387302415107 + 0.50113945641761259 + 0.50115504049257409 + 0.5011706252490884 + 0.5011862106872027 + 0.50120179680697075 + 0.50121738360844126 + 0.50123297109166554 + 0.50124855925669443 + 0.50126414810357933 + 0.50127973763237021 + 0.50129532784311936 + 0.50131091873587463 + 0.50132651031068931 + 0.50134210256761347 + 0.5013576955066984 + 0.50137328912799273 + 0.50138888343155019 + 0.50140447841741964 + 0.50142007408565348 + 0.50143567043630044 + 0.50145126746941415 + 0.50146686518504358 + 0.50148246358323967 + 0.50149806266405272 + 0.50151366242753515 + 0.50152926287373689 + 0.50154486400270915 + 0.50156046581450209 + 0.50157606830916812 + 0.50159167148675743 + 0.50160727534731975 + 0.5016228798909067 + 0.50163848511757048 + 0.50165409102736014 + 0.50166969762032809 + 0.50168530489652319 + 0.50170091285599927 + 0.50171652149880497 + 0.50173213082499168 + 0.50174774083461193 + 0.50176335152771467 + 0.50177896290435231 + 0.50179457496457502 + 0.50181018770843278 + 0.50182580113597819 + 0.50184141524726278 + 0.50185703004233628 + 0.50187264552124899 + 0.50188826168405354 + 0.50190387853080121 + 0.50191949606154096 + 0.5019351142763252 + 0.50195073317520411 + 0.50196635275823032 + 0.50198197302545389 + 0.50199759397692512 + 0.50201321561269652 + 0.50202883793281805 + 0.50204446093734134 + 0.50206008462631768 + 0.50207570899979725 + 0.50209133405783257 + 0.50210695980047271 + 0.50212258622777017 + 0.50213821333977648 + 0.5021538411365416 + 0.50216946961811593 + 0.5021850987845532 + 0.50220072863590248 + 0.50221635917221641 + 0.50223199039354494 + 0.50224762229993858 + 0.50226325489144974 + 0.50227888816813016 + 0.50229452213002967 + 0.50231015677719881 + 0.5023257921096913 + 0.50234142812755622 + 0.50235706483084486 + 0.50237270221961006 + 0.50238834029390089 + 0.50240397905376977 + 0.50241961849926853 + 0.50243525863044702 + 0.5024508994473571 + 0.50246654095004861 + 0.50248218313857584 + 0.50249782601298765 + 0.50251346957333565 + 0.50252911381967236 + 0.50254475875204829 + 0.5025604043705123 + 0.50257605067511968 + 0.50259169766591938 + 0.50260734534296303 + 0.50262299370630203 + 0.50263864275598813 + 0.50265429249207139 + 0.50266994291460465 + 0.5026855940236381 + 0.50270124581922349 + 0.50271689830141342 + 0.50273255147025597 + 0.50274820532580478 + 0.50276385986811178 + 0.50277951509722696 + 0.50279517101320226 + 0.50281082761608764 + 0.50282648490593729 + 0.50284214288280038 + 0.50285780154672954 + 0.5028734608977754 + 0.50288912093598925 + 0.50290478166142283 + 0.50292044307412653 + 0.50293610517415432 + 0.50295176796155416 + 0.50296743143638123 + 0.50298309559868359 + 0.50299876044851521 + 0.50301442598592527 + 0.50303009221096795 + 0.5030457591236922 + 0.50306142672415111 + 0.50307709501239362 + 0.50309276398847536 + 0.50310843365244384 + 0.50312410400435237 + 0.50313977504425356 + 0.5031554467721967 + 0.50317111918823343 + 0.50318679229241781 + 0.50320246608479913 + 0.50321814056542769 + 0.50323381573435777 + 0.5032494915916409 + 0.50326516813732514 + 0.50328084537146722 + 0.50329652329411367 + 0.50331220190531867 + 0.50332788120513539 + 0.50334356119361146 + 0.50335924187080128 + 0.50337492323675537 + 0.50339060529152402 + 0.50340628803516152 + 0.50342197146771961 + 0.50343765558924614 + 0.50345334039979672 + 0.50346902589942177 + 0.50348471208817047 + 0.50350039896609844 + 0.50351608653325475 + 0.50353177478969136 + 0.50354746373545978 + 0.50356315337061319 + 0.50357884369520201 + 0.50359453470927795 + 0.50361022641289288 + 0.50362591880609719 + 0.50364161188894541 + 0.50365730566148648 + 0.5036730001237737 + 0.50368869527585858 + 0.50370439111779186 + 0.50372008764962661 + 0.50373578487141324 + 0.50375148278320481 + 0.50376718138505194 + 0.50378288067700761 + 0.5037985806591212 + 0.5038142813314469 + 0.50382998269403545 + 0.50384568474693858 + 0.50386138749020937 + 0.50387709092389721 + 0.50389279504805506 + 0.50390849986273478 + 0.50392420536798832 + 0.50393991156386853 + 0.50395561845042502 + 0.50397132602770955 + 0.5039870342957764 + 0.50400274325467631 + 0.50401845290445857 + 0.5040341632451788 + 0.50404987427688763 + 0.50406558599963569 + 0.50408129841347604 + 0.50409701151846065 + 0.50411272531464002 + 0.50412843980206745 + 0.50414415498079479 + 0.50415987085087266 + 0.50417558741235424 + 0.50419130466529016 + 0.5042070226097336 + 0.50422274124573518 + 0.50423846057334798 + 0.50425418059262539 + 0.50426990130361538 + 0.50428562270637256 + 0.50430134480094879 + 0.50431706758739481 + 0.50433279106576356 + 0.50434851523610713 + 0.50436424009847636 + 0.50437996565292442 + 0.50439569189950295 + 0.50441141883826313 + 0.5044271464692589 + 0.50444287479254024 + 0.50445860380816021 + 0.50447433351616922 + 0.50449006391662221 + 0.50450579500956949 + 0.50452152679506213 + 0.50453725927315318 + 0.50455299244389606 + 0.50456872630734007 + 0.5045844608635397 + 0.5046001961125447 + 0.50461593205440936 + 0.50463166868918452 + 0.50464740601692337 + 0.50466314403767565 + 0.50467888275149564 + 0.50469462215843541 + 0.50471036225854471 + 0.50472610305187904 + 0.50474184453848803 + 0.50475758671842497 + 0.50477332959174204 + 0.50478907315848998 + 0.50480481741872196 + 0.50482056237249018 + 0.50483630801984658 + 0.50485205436084346 + 0.50486780139553267 + 0.5048835491239676 + 0.50489929754619789 + 0.50491504666227927 + 0.50493079647226013 + 0.50494654697619501 + 0.50496229817413607 + 0.50497805006613417 + 0.50499380265224392 + 0.50500955593251484 + 0.50502530990700023 + 0.5050410645757526 + 0.50505681993882356 + 0.50507257599626665 + 0.50508833274813292 + 0.50510409019447444 + 0.5051198483353444 + 0.5051356071707952 + 0.50515136670087868 + 0.5051671269256448 + 0.50518288784515042 + 0.50519864945944426 + 0.50521441176858073 + 0.5052301747726109 + 0.50524593847158794 + 0.50526170286556304 + 0.50527746795458828 + 0.50529323373871815 + 0.50530900021800396 + 0.50532476739249632 + 0.50534053526225009 + 0.50535630382731611 + 0.50537207308774668 + 0.50538784304359641 + 0.50540361369491504 + 0.50541938504175477 + 0.50543515708417031 + 0.50545092982221262 + 0.50546670325593401 + 0.50548247738538787 + 0.50549825221062505 + 0.50551402773169929 + 0.50552980394866265 + 0.50554558086156742 + 0.5055613584704659 + 0.50557713677541138 + 0.50559291577645393 + 0.50560869547364928 + 0.50562447586704862 + 0.505640256956704 + 0.50565603874266674 + 0.50567182122499144 + 0.50568760440373028 + 0.50570338827893446 + 0.50571917285065737 + 0.50573495811895142 + 0.50575074408386889 + 0.50576653074546318 + 0.50578231810378427 + 0.50579810615888932 + 0.50581389491082696 + 0.50582968435964948 + 0.50584547450541184 + 0.505861265348166 + 0.50587705688796336 + 0.50589284912485744 + 0.50590864205890052 + 0.50592443569014611 + 0.50594023001864541 + 0.50595602504445059 + 0.50597182076761671 + 0.50598761718819363 + 0.50600341430623597 + 0.50601921212179513 + 0.5060350106349244 + 0.50605080984567641 + 0.50606660975410334 + 0.50608241036025781 + 0.50609821166419311 + 0.50611401366596065 + 0.50612981636561516 + 0.50614561976320671 + 0.50616142385879115 + 0.50617722865241743 + 0.50619303414414152 + 0.50620884033401337 + 0.50622464722208904 + 0.50624045480841739 + 0.50625626309305449 + 0.50627207207605029 + 0.50628788175745953 + 0.50630369213733495 + 0.50631950321572761 + 0.50633531499269102 + 0.50635112746827771 + 0.50636694064254151 + 0.50638275451553472 + 0.50639856908730885 + 0.5064143843579183 + 0.50643020032741592 + 0.5064460169958529 + 0.50646183436328285 + 0.50647765242975951 + 0.50649347119533428 + 0.50650929066006056 + 0.50652511082399121 + 0.5065409316871784 + 0.50655675324967731 + 0.50657257551153778 + 0.50658839847281367 + 0.50660422213355871 + 0.50662004649382431 + 0.50663587155366407 + 0.50665169731313164 + 0.50666752377227842 + 0.50668335093115957 + 0.50669917878982351 + 0.50671500734832819 + 0.50673083660672469 + 0.50674666656506417 + 0.50676249722340194 + 0.50677832858179039 + 0.50679416064028082 + 0.50680999339892818 + 0.5068258268577841 + 0.5068416610169022 + 0.50685749587633366 + 0.50687333143613511 + 0.50688916769635639 + 0.50690500465705268 + 0.50692084231827517 + 0.50693668068007658 + 0.50695251974251077 + 0.50696835950563157 + 0.50698419996949029 + 0.50700004113414199 + 0.50701588299963685 + 0.50703172556603116 + 0.5070475688333751 + 0.50706341280172385 + 0.5070792574711287 + 0.5070951028416435 + 0.50711094891332087 + 0.50712679568621488 + 0.50714264316037783 + 0.50715849133586266 + 0.50717434021272312 + 0.50719018979101205 + 0.50720604007078185 + 0.50722189105208648 + 0.5072377427349799 + 0.5072535951195124 + 0.50726944820573905 + 0.50728530199371247 + 0.50730115648348661 + 0.50731701167511289 + 0.50733286756864659 + 0.50734872416413912 + 0.50736458146164432 + 0.50738043946121625 + 0.50739629816290632 + 0.5074121575667685 + 0.5074280176728555 + 0.50744387848122241 + 0.50745973999191962 + 0.50747560220500243 + 0.50749146512052334 + 0.50750732873853521 + 0.50752319305909188 + 0.50753905808224631 + 0.50755492380805112 + 0.50757079023656027 + 0.50758665736782782 + 0.5076025252019053 + 0.50761839373884665 + 0.50763426297870584 + 0.5076501329215346 + 0.50766600356738667 + 0.50768187491631755 + 0.50769774696837744 + 0.50771361972362028 + 0.50772949318210148 + 0.50774536734387266 + 0.50776124220898633 + 0.50777711777749679 + 0.50779299404945921 + 0.50780887102492278 + 0.5078247487039439 + 0.50784062708657662 + 0.50785650617287148 + 0.50787238596288242 + 0.50788826645666474 + 0.50790414765427128 + 0.50792002955575366 + 0.50793591216116718 + 0.50795179547056346 + 0.50796767948399657 + 0.50798356420152191 + 0.50799944962318988 + 0.50801533574905566 + 0.50803122257917233 + 0.50804711011359238 + 0.50806299835237045 + 0.50807888729556039 + 0.5080947769432137 + 0.50811066729538479 + 0.50812655835212761 + 0.50814245011349635 + 0.50815834257954151 + 0.5081742357503195 + 0.50819012962588228 + 0.50820602420628491 + 0.50822191949157935 + 0.50823781548181968 + 0.50825371217705873 + 0.50826960957735079 + 0.50828550768274983 + 0.50830140649330779 + 0.50831730600907998 + 0.50833320623011813 + 0.50834910715647774 + 0.50836500878821023 + 0.50838091112537132 + 0.50839681416801275 + 0.5084127179161898 + 0.50842862236995423 + 0.50844452752936165 + 0.50846043339446345 + 0.50847633996531549 + 0.50849224724196929 + 0.50850815522447912 + 0.50852406391289928 + 0.50853997330728384 + 0.50855588340768465 + 0.5085717942141561 + 0.50858770572675227 + 0.50860361794552611 + 0.50861953087053213 + 0.50863544450182319 + 0.50865135883945478 + 0.50866727388347743 + 0.50868318963394676 + 0.50869910609091695 + 0.50871502325443985 + 0.50873094112457107 + 0.50874685970136346 + 0.5087627789848701 + 0.50877869897514683 + 0.50879461967224515 + 0.50881054107621937 + 0.50882646318712277 + 0.50884238600501075 + 0.50885830952993649 + 0.50887423376195295 + 0.50889015870111332 + 0.5089060843474732 + 0.50892201070108545 + 0.50893793776200469 + 0.50895386553028255 + 0.50896979400597486 + 0.50898572318913449 + 0.50900165307981593 + 0.50901758367807237 + 0.50903351498395799 + 0.5090494469975273 + 0.50906537971883092 + 0.50908131314792693 + 0.50909724728486716 + 0.50911318212970613 + 0.50912911768249558 + 0.50914505394329257 + 0.50916099091214884 + 0.509176928589119 + 0.50919286697425725 + 0.50920880606761554 + 0.50922474586925093 + 0.50924068637921516 + 0.50925662759756152 + 0.50927256952434696 + 0.50928851215962201 + 0.5093044555034425 + 0.50932039955586283 + 0.50933634431693497 + 0.50935228978671454 + 0.50936823596525349 + 0.509384182852609 + 0.5094001304488327 + 0.50941607875397932 + 0.50943202776810315 + 0.50944797749125625 + 0.5094639279234956 + 0.50947987906487202 + 0.50949583091544226 + 0.50951178347525972 + 0.50952773674437646 + 0.50954369072284933 + 0.50955964541073029 + 0.50957560080807529 + 0.50959155691493496 + 0.5096075137313677 + 0.50962347125742535 + 0.50963942949316121 + 0.50965538843863123 + 0.50967134809388726 + 0.50968730845898513 + 0.50970326953397938 + 0.50971923131892216 + 0.509735193813869 + 0.50975115701887352 + 0.50976712093399001 + 0.50978308555927199 + 0.50979905089477517 + 0.50981501694055154 + 0.50983098369665714 + 0.50984695116314505 + 0.50986291934007011 + 0.50987888822748539 + 0.50989485782544697 + 0.50991082813400668 + 0.50992679915321937 + 0.50994277088314066 + 0.50995874332382407 + 0.50997471647532289 + 0.50999069033769306 + 0.51000666491098656 + 0.51002264019525945 + 0.51003861619056501 + 0.51005459289695776 + 0.51007057031449243 + 0.51008654844322121 + 0.51010252728320116 + 0.51011850683448567 + 0.51013448709712816 + 0.51015046807118347 + 0.51016644975670589 + 0.51018243215375036 + 0.51019841526236898 + 0.51021439908261879 + 0.51023038361455209 + 0.51024636885822372 + 0.51026235481368931 + 0.51027834148100115 + 0.5102943288602152 + 0.51031031695138507 + 0.51032630575456395 + 0.51034229526980912 + 0.51035828549717155 + 0.51037427643670852 + 0.51039026808847343 + 0.5104062604525198 + 0.51042225352890214 + 0.51043824731767673 + 0.51045424181889565 + 0.51047023703261363 + 0.51048623295888673 + 0.51050222959776836 + 0.51051822694931337 + 0.51053422501357393 + 0.51055022379060855 + 0.5105662232804683 + 0.51058222348320781 + 0.51059822439888336 + 0.51061422602754947 + 0.51063022836925842 + 0.51064623142406651 + 0.51066223519202825 + 0.51067823967319714 + 0.51069424486762716 + 0.51071025077537502 + 0.51072625739649335 + 0.51074226473103712 + 0.51075827277906205 + 0.51077428154062054 + 0.51079029101576878 + 0.51080630120456028 + 0.51082231210704976 + 0.51083832372329352 + 0.51085433605334374 + 0.51087034909725659 + 0.51088636285508549 + 0.51090237732688559 + 0.51091839251271143 + 0.51093440841261806 + 0.51095042502665899 + 0.51096644235488919 + 0.51098246039736472 + 0.5109984791541391 + 0.51101449862526627 + 0.51103051881080197 + 0.51104653971080005 + 0.51106256132531536 + 0.51107858365440284 + 0.51109460669811735 + 0.5111106304565125 + 0.51112665492964449 + 0.51114268011756703 + 0.51115870602033486 + 0.51117473263800317 + 0.51119075997062657 + 0.51120678801825903 + 0.51122281678095527 + 0.51123884625877158 + 0.51125487645176038 + 0.51127090735997782 + 0.51128693898347888 + 0.5113029713223185 + 0.5113190043765492 + 0.51133503814622838 + 0.51135107263140978 + 0.51136710783214834 + 0.51138314374849891 + 0.51139918038051557 + 0.51141521772825294 + 0.5114312557917674 + 0.51144729457111282 + 0.51146333406634392 + 0.51147937427751589 + 0.51149541520468245 + 0.51151145684789978 + 0.51152749920722296 + 0.51154354228270582 + 0.51155958607440322 + 0.51157563058237032 + 0.51159167580666198 + 0.51160772174733216 + 0.51162376840443835 + 0.51163981577803297 + 0.5116558638681713 + 0.51167191267490941 + 0.51168796219830115 + 0.51170401243840158 + 0.51172006339526588 + 0.511736115068949 + 0.51175216745950602 + 0.51176822056699089 + 0.51178427439145968 + 0.51180032893296645 + 0.51181638419156739 + 0.51183244016731644 + 0.51184849686026856 + 0.51186455427048028 + 0.5118806123980042 + 0.51189667124289651 + 0.51191273080521238 + 0.511928791085007 + 0.51194485208233409 + 0.51196091379725006 + 0.51197697622980898 + 0.51199303938006713 + 0.51200910324807825 + 0.51202516783389895 + 0.51204123313758165 + 0.51205729915918419 + 0.5120733658987604 + 0.51208943335636414 + 0.51210550153205303 + 0.51212157042588125 + 0.51213764003790241 + 0.51215371036817303 + 0.5121697814167484 + 0.51218585318368237 + 0.51220192566903266 + 0.51221799887285058 + 0.51223407279519395 + 0.51225014743611674 + 0.51226622279567535 + 0.51228229887392496 + 0.51229837567091818 + 0.51231445318671298 + 0.5123305314213632 + 0.51234661037492535 + 0.51236269004745205 + 0.51237877043900115 + 0.51239485154962539 + 0.51241093337938237 + 0.51242701592832618 + 0.5124430991965121 + 0.51245918318399541 + 0.5124752678908312 + 0.51249135331707496 + 0.51250743946278177 + 0.51252352632800691 + 0.51253961391280578 + 0.51255570221723357 + 0.51257179124134566 + 0.51258788098519714 + 0.51260397144884229 + 0.51262006263233872 + 0.51263615453574052 + 0.51265224715910296 + 0.51266834050248034 + 0.51268443456592883 + 0.51270052934950539 + 0.51271662485326386 + 0.51273272107725831 + 0.51274881802154537 + 0.51276491568618177 + 0.51278101407122134 + 0.51279711317671817 + 0.51281321300273031 + 0.51282931354931183 + 0.51284541481651802 + 0.51286151680440417 + 0.51287761951302702 + 0.5128937229424394 + 0.51290982709269917 + 0.51292593196386038 + 0.51294203755597978 + 0.51295814386911132 + 0.51297425090331072 + 0.51299035865863429 + 0.51300646713513764 + 0.51302257633287485 + 0.51303868625190263 + 0.51305479689227618 + 0.51307090825404855 + 0.51308702033728026 + 0.51310313314202161 + 0.51311924666833186 + 0.51313536091626522 + 0.51315147588587695 + 0.51316759157722258 + 0.51318370799035751 + 0.51319982512533846 + 0.51321594298221851 + 0.5132320615610555 + 0.51324818086190482 + 0.51326430088482222 + 0.51328042162986154 + 0.51329654309707973 + 0.51331266528653097 + 0.51332878819827332 + 0.51334491183235953 + 0.51336103618884776 + 0.51337716126779109 + 0.51339328706924747 + 0.5134094135932723 + 0.51342554083991854 + 0.51344166880924558 + 0.5134577975013066 + 0.51347392691615801 + 0.51349005705385553 + 0.51350618791445468 + 0.51352231949801097 + 0.51353845180457991 + 0.51355458483421834 + 0.51357071858698045 + 0.51358685306292196 + 0.51360298826209971 + 0.51361912418456901 + 0.51363526083038691 + 0.51365139819960615 + 0.51366753629228523 + 0.51368367510847701 + 0.51369981464823955 + 0.51371595491162836 + 0.51373209589869917 + 0.51374823760950639 + 0.51376438004410785 + 0.51378052320255818 + 0.51379666708491278 + 0.5138128116912275 + 0.51382895702155884 + 0.51384510307596276 + 0.51386124985449477 + 0.51387739735721039 + 0.51389354558416533 + 0.51390969453541657 + 0.51392584421101839 + 0.51394199461102763 + 0.51395814573549881 + 0.51397429758449131 + 0.513990450158057 + 0.51400660345625282 + 0.51402275747913562 + 0.51403891222676112 + 0.51405506769918385 + 0.51407122389646176 + 0.51408738081864946 + 0.51410353846580392 + 0.51411969683797931 + 0.51413585593523281 + 0.51415201575762137 + 0.51416817630519818 + 0.51418433757802129 + 0.51420049957614533 + 0.51421666229962715 + 0.51423282574852269 + 0.51424898992288859 + 0.51426515482277957 + 0.5142813204482527 + 0.51429748679936216 + 0.51431365387616523 + 0.51432982167871866 + 0.51434599020707716 + 0.5143621594612976 + 0.5143783294414358 + 0.51439450014754751 + 0.51441067157968856 + 0.51442684373791459 + 0.51444301662228398 + 0.51445919023285125 + 0.51447536456967213 + 0.51449153963280247 + 0.51450771542230045 + 0.51452389193821846 + 0.51454006918061679 + 0.51455624714954917 + 0.51457242584507124 + 0.51458860526724126 + 0.51460478541611254 + 0.51462096629174359 + 0.51463714789418891 + 0.51465333022350679 + 0.51466951327975174 + 0.51468569706297973 + 0.51470188157324792 + 0.51471806681061183 + 0.51473425277512774 + 0.51475043946685239 + 0.51476662688584074 + 0.51478281503214962 + 0.51479900390583633 + 0.51481519350695537 + 0.51483138383556404 + 0.51484757489171795 + 0.5148637666754744 + 0.51487995918688823 + 0.51489615242601627 + 0.51491234639291572 + 0.51492854108764141 + 0.51494473651025041 + 0.51496093266079856 + 0.51497712953934183 + 0.51499332714593737 + 0.51500952548064127 + 0.51502572454350937 + 0.51504192433459861 + 0.51505812485396529 + 0.51507432610166515 + 0.51509052807775424 + 0.51510673078229097 + 0.51512293421532884 + 0.51513913837692626 + 0.51515534326713919 + 0.51517154888602357 + 0.51518775523363547 + 0.51520396231003218 + 0.51522017011526944 + 0.51523637864940341 + 0.51525258791249251 + 0.51526879790459035 + 0.5152850086257541 + 0.51530122007604107 + 0.5153174322555083 + 0.51533364516420965 + 0.51534985880220341 + 0.51536607316954686 + 0.51538228826629495 + 0.51539850409250354 + 0.51541472064823124 + 0.51543093793353145 + 0.51544715594846424 + 0.51546337469308423 + 0.51547959416744871 + 0.5154958143716124 + 0.51551203530563428 + 0.51552825696956861 + 0.51554447936347303 + 0.5155607024874036 + 0.51557692634141883 + 0.51559315092557245 + 0.51560937623992154 + 0.51562560228452481 + 0.51564182905943723 + 0.51565805656471475 + 0.51567428480041477 + 0.51569051376659469 + 0.51570674346330825 + 0.51572297389061617 + 0.51573920504857118 + 0.51575543693723302 + 0.51577166955665654 + 0.51578790290689802 + 0.51580413698801586 + 0.51582037180006535 + 0.51583660734310344 + 0.51585284361718664 + 0.51586908062237213 + 0.51588531835871609 + 0.51590155682627614 + 0.51591779602510701 + 0.51593403595526743 + 0.51595027661681225 + 0.5159665180098002 + 0.51598276013428623 + 0.51599900299032797 + 0.51601524657798137 + 0.51603149089730527 + 0.5160477359483544 + 0.51606398173118528 + 0.5160802282458552 + 0.51609647549242166 + 0.51611272347094095 + 0.51612897218147036 + 0.51614522162406506 + 0.51616147179878369 + 0.5161777227056813 + 0.51619397434481662 + 0.51621022671624583 + 0.51622647982002401 + 0.51624273365620998 + 0.51625898822485983 + 0.51627524352603127 + 0.51629149955977915 + 0.51630775632616233 + 0.51632401382523707 + 0.51634027205705968 + 0.51635653102168766 + 0.51637279071917741 + 0.51638905114958633 + 0.51640531231297082 + 0.51642157420938839 + 0.51643783683889544 + 0.51645410020154936 + 0.51647036429740545 + 0.51648662912652354 + 0.5165028946889576 + 0.51651916098476647 + 0.51653542801400643 + 0.5165516957767351 + 0.51656796427300888 + 0.51658423350288407 + 0.5166005034664195 + 0.51661677416367024 + 0.51663304559469414 + 0.51664931775954714 + 0.51666559065828865 + 0.51668186429097329 + 0.51669813865765901 + 0.51671441375840343 + 0.51673068959326274 + 0.51674696616229354 + 0.51676324346555591 + 0.51677952150310236 + 0.51679580027499206 + 0.51681207978128374 + 0.5168283600220327 + 0.5168446409972951 + 0.51686092270713024 + 0.51687720515159297 + 0.51689348833074256 + 0.51690977224463508 + 0.51692605689332849 + 0.51694234227687785 + 0.5169586283953409 + 0.51697491524877792 + 0.51699120283724143 + 0.51700749116079192 + 0.51702378021948558 + 0.51704007001337904 + 0.51705636054252868 + 0.51707265180699369 + 0.51708894380683035 + 0.51710523654209661 + 0.51712153001284755 + 0.51713782421914201 + 0.51715411916103804 + 0.51717041483859094 + 0.51718671125185944 + 0.51720300840090017 + 0.51721930628576973 + 0.51723560490652709 + 0.51725190426322765 + 0.51726820435592891 + 0.51728450518468894 + 0.51730080674956547 + 0.51731710905061368 + 0.51733341208789407 + 0.5173497158614605 + 0.51736602037137214 + 0.51738232561768682 + 0.51739863160046107 + 0.51741493831975138 + 0.51743124577561717 + 0.51744755396811326 + 0.51746386289729907 + 0.5174801725632312 + 0.51749648296596751 + 0.51751279410556317 + 0.51752910598207857 + 0.51754541859556935 + 0.51756173194609434 + 0.51757804603370894 + 0.51759436085847099 + 0.5176106764204399 + 0.51762699271967083 + 0.51764330975622275 + 0.51765962753015149 + 0.5176759460415159 + 0.5176922652903726 + 0.51770858527677965 + 0.51772490600079368 + 0.51774122746247253 + 0.51775754966187548 + 0.51777387259905661 + 0.5177901962740763 + 0.51780652068699007 + 0.5178228458378572 + 0.51783917172673422 + 0.51785549835367783 + 0.51787182571874613 + 0.51788815382199938 + 0.51790448266348943 + 0.51792081224328046 + 0.5179371425614242 + 0.51795347361798105 + 0.51796980541300908 + 0.51798613794656501 + 0.51800247121870546 + 0.51801880522948995 + 0.51803513997897366 + 0.51805147546721719 + 0.51806781169427618 + 0.51808414866020835 + 0.51810048636507211 + 0.51811682480892385 + 0.51813316399182308 + 0.51814950391382519 + 0.5181658445749896 + 0.51818218597537302 + 0.51819852811503464 + 0.51821487099403019 + 0.5182312146124175 + 0.51824755897025609 + 0.51826390406760148 + 0.51828024990451294 + 0.5182965964810472 + 0.51831294379726245 + 0.51832929185321663 + 0.51834564064896682 + 0.51836199018457096 + 0.51837834046008702 + 0.51839469147557338 + 0.51841104323108644 + 0.51842739572668484 + 0.51844374896242629 + 0.51846010293836908 + 0.51847645765456873 + 0.51849281311108597 + 0.5185091693079763 + 0.51852552624529924 + 0.51854188392311162 + 0.51855824234147152 + 0.5185746015004371 + 0.51859096140006522 + 0.51860732204041549 + 0.51862368342154341 + 0.51864004554350962 + 0.51865640840636973 + 0.51867277201018203 + 0.5186891363550048 + 0.51870550144089589 + 0.51872186726791381 + 0.51873823383611528 + 0.5187546011455586 + 0.51877096919630195 + 0.5187873379884036 + 0.5188037075219204 + 0.51882007779691175 + 0.51883644881343338 + 0.51885282057154636 + 0.51886919307130586 + 0.51888556631277061 + 0.51890194029599968 + 0.51891831502104913 + 0.51893469048797958 + 0.51895106669684665 + 0.51896744364770886 + 0.51898382134062548 + 0.51900019977565359 + 0.51901657895285025 + 0.51903295887227496 + 0.51904933953398602 + 0.51906572093803904 + 0.51908210308449509 + 0.51909848597341091 + 0.51911486960484499 + 0.51913125397885296 + 0.5191476390954971 + 0.51916402495483316 + 0.51918041155691796 + 0.51919679890181258 + 0.51921318698957275 + 0.51922957582025686 + 0.51924596539392553 + 0.51926235571063362 + 0.5192787467704405 + 0.51929513857340581 + 0.51931153111958539 + 0.51932792440903774 + 0.51934431844182227 + 0.51936071321799748 + 0.51937710873761911 + 0.51939350500074688 + 0.51940990200744042 + 0.51942629975775545 + 0.51944269825175049 + 0.5194590974894866 + 0.51947549747101796 + 0.51949189819640462 + 0.51950829966570611 + 0.51952470187897948 + 0.51954110483628202 + 0.51955750853767468 + 0.51957391298321187 + 0.51959031817295609 + 0.51960672410696174 + 0.51962313078528999 + 0.5196395382079978 + 0.5196559463751439 + 0.51967235528678635 + 0.51968876494298388 + 0.51970517534379379 + 0.51972158648927547 + 0.51973799837948642 + 0.51975441101448605 + 0.51977082439433309 + 0.51978723851908348 + 0.51980365338879819 + 0.51982006900353306 + 0.51983648536334925 + 0.51985290246830396 + 0.51986932031845334 + 0.51988573891386047 + 0.51990215825457931 + 0.5199185783406719 + 0.51993499917219299 + 0.51995142074920497 + 0.51996784307176269 + 0.51998426613992688 + 0.52000068995375504 + 0.52001711451330568 + 0.52003353981863865 + 0.52004996586980989 + 0.52006639266688048 + 0.52008282020990659 + 0.52009924849894906 + 0.52011567753406429 + 0.52013210731531168 + 0.52014853784275017 + 0.52016496911643706 + 0.52018140113643196 + 0.52019783390279362 + 0.5202142674155793 + 0.52023070167484897 + 0.52024713668066114 + 0.5202635724330732 + 0.52028000893214377 + 0.52029644617793269 + 0.5203128841704987 + 0.52032932290989897 + 0.52034576239619235 + 0.52036220262943855 + 0.5203786436096951 + 0.52039508533702061 + 0.52041152781147493 + 0.52042797103311544 + 0.52044441500200211 + 0.52046085971819234 + 0.52047730518174484 + 0.52049375139271814 + 0.5205101983511724 + 0.52052664605716492 + 0.52054309451075564 + 0.52055954371200197 + 0.52057599366096263 + 0.52059244435769636 + 0.52060889580226311 + 0.52062534799472171 + 0.52064180093512924 + 0.52065825462354609 + 0.52067470906002822 + 0.52069116424463824 + 0.52070762017743233 + 0.52072407685846933 + 0.5207405342878102 + 0.52075699246551033 + 0.52077345139163189 + 0.52078991106623129 + 0.52080637148936859 + 0.52082283266110252 + 0.5208392945814917 + 0.52085575725059385 + 0.52087222066847016 + 0.52088868483517814 + 0.5209051497507754 + 0.52092161541532322 + 0.52093808182887913 + 0.52095454899150195 + 0.52097101690325165 + 0.5209874855641845 + 0.52100395497436347 + 0.52102042513384428 + 0.52103689604268622 + 0.52105336770095045 + 0.52106984010869328 + 0.52108631326597354 + 0.52110278717285274 + 0.52111926182938828 + 0.52113573723563789 + 0.52115221339166284 + 0.52116869029752078 + 0.52118516795327186 + 0.52120164635897359 + 0.52121812551468494 + 0.52123460542046729 + 0.52125108607637582 + 0.52126756748247316 + 0.52128404963881547 + 0.52130053254546438 + 0.52131701620247761 + 0.5213335006099139 + 0.52134998576783342 + 0.52136647167629269 + 0.52138295833535431 + 0.5213994457450748 + 0.52141593390551422 + 0.52143242281673141 + 0.521448912478787 + 0.52146540289173682 + 0.52148189405564283 + 0.52149838597056375 + 0.52151487863655743 + 0.52153137205368383 + 0.521547866222001 + 0.52156436114157012 + 0.52158085681244903 + 0.52159735323469814 + 0.52161385040837482 + 0.52163034833353827 + 0.5216468470102501 + 0.5216633464385666 + 0.52167984661854816 + 0.52169634755025496 + 0.52171284923374484 + 0.5217293516690793 + 0.52174585485631353 + 0.52176235879551036 + 0.52177886348672642 + 0.52179536893002321 + 0.52181187512545835 + 0.52182838207309223 + 0.52184488977298404 + 0.52186139822519262 + 0.52187790742977735 + 0.5218944173867982 + 0.5219109280963119 + 0.52192743955838128 + 0.52194395177306419 + 0.52196046474041957 + 0.52197697846050672 + 0.52199349293338571 + 0.52201000815911469 + 0.52202652413775397 + 0.52204304086936359 + 0.52205955835400175 + 0.5220760765917275 + 0.52209259558260113 + 0.52210911532668169 + 0.52212563582402993 + 0.52214215707470202 + 0.52215867907876112 + 0.52217520183626387 + 0.52219172534727176 + 0.52220824961184298 + 0.52222477463003636 + 0.52224130040191252 + 0.52225782692753053 + 0.52227435420694956 + 0.52229088224023024 + 0.5223074110274315 + 0.52232394056861142 + 0.52234047086383173 + 0.52235700191315015 + 0.52237353371662731 + 0.52239006627432238 + 0.52240659958629465 + 0.5224231336526044 + 0.5224396684733098 + 0.52245620404847104 + 0.52247274037814906 + 0.52248927746240137 + 0.52250581530128881 + 0.52252235389487034 + 0.52253889324320668 + 0.52255543334635579 + 0.52257197420437684 + 0.5225885158173329 + 0.52260505818527947 + 0.52262160130827817 + 0.52263814518638874 + 0.52265468981967111 + 0.52267123520818382 + 0.52268778135198712 + 0.52270432825114155 + 0.52272087590570404 + 0.52273742431573644 + 0.52275397348129926 + 0.52277052340245045 + 0.52278707407925051 + 0.52280362551175774 + 0.52282017770003397 + 0.52283673064413716 + 0.52285328434412914 + 0.52286983880006799 + 0.5228863940120132 + 0.52290294998002529 + 0.52291950670416354 + 0.52293606418448857 + 0.52295262242105867 + 0.52296918141393556 + 0.52298574116317864 + 0.52300230166884598 + 0.52301886293099831 + 0.52303542494969635 + 0.52305198772499928 + 0.52306855125696539 + 0.52308511554565773 + 0.52310168059113338 + 0.52311824639345395 + 0.52313481295267927 + 0.52315138026886721 + 0.52316794834207858 + 0.52318451717237391 + 0.52320108675981269 + 0.52321765710445578 + 0.52323422820636112 + 0.52325080006559099 + 0.52326737268220203 + 0.5232839460562575 + 0.52330052018781581 + 0.52331709507693625 + 0.52333367072368076 + 0.52335024712810774 + 0.52336682429027792 + 0.52338340221025048 + 0.52339998088808537 + 0.52341656032384298 + 0.52343314051758416 + 0.52344972146936719 + 0.52346630317925291 + 0.52348288564730194 + 0.5234994688735739 + 0.52351605285812708 + 0.52353263760102464 + 0.52354922310232499 + 0.52356580936208885 + 0.5235823963803744 + 0.52359898415724282 + 0.52361557269275572 + 0.52363216198697049 + 0.52364875203994898 + 0.52366534285175081 + 0.52368193442243693 + 0.52369852675206563 + 0.52371511984069874 + 0.52373171368839622 + 0.52374830829521613 + 0.52376490366122064 + 0.52378149978646937 + 0.52379809667102328 + 0.52381469431494054 + 0.52383129271828344 + 0.52384789188111147 + 0.52386449180348438 + 0.52388109248546288 + 0.52389769392710672 + 0.52391429612847562 + 0.52393089908963153 + 0.52394750281063296 + 0.52396410729154208 + 0.52398071253241596 + 0.52399731853331821 + 0.5240139252943069 + 0.52403053281544332 + 0.52404714109678696 + 0.52406375013839868 + 0.5240803599403383 + 0.52409697050266679 + 0.52411358182544499 + 0.52413019390873139 + 0.52414680675258707 + 0.52416342035707397 + 0.5241800347222495 + 0.52419664984817582 + 0.52421326573491267 + 0.52422988238252111 + 0.52424649979106064 + 0.52426311796059255 + 0.52427973689117768 + 0.52429635658287455 + 0.52431297703574409 + 0.52432959824984726 + 0.52434622022524424 + 0.52436284296199553 + 0.52437946646016109 + 0.52439609071980209 + 0.52441271574097936 + 0.52442934152375154 + 0.52444596806818089 + 0.52446259537432727 + 0.5244792234422504 + 0.52449585227201134 + 0.52451248186367128 + 0.5245291122172886 + 0.5245457433329257 + 0.52456237521064364 + 0.52457900785050104 + 0.5245956412525602 + 0.52461227541687971 + 0.52462891034352199 + 0.52464554603254554 + 0.52466218248401275 + 0.5246788196979848 + 0.52469545767452019 + 0.52471209641367877 + 0.52472873591552427 + 0.5247453761801153 + 0.52476201720751281 + 0.52477865899777698 + 0.52479530155096887 + 0.52481194486714944 + 0.52482858894637752 + 0.52484523378871673 + 0.52486187939422568 + 0.5248785257629669 + 0.52489517289499765 + 0.52491182079038179 + 0.52492846944917781 + 0.52494511887144824 + 0.52496176905725189 + 0.52497842000665107 + 0.52499507171970561 + 0.52501172419647701 + 0.52502837743702491 + 0.52504503144141079 + 0.5250616862096944 + 0.52507834174193968 + 0.5250949980382027 + 0.52511165509854729 + 0.52512831292303341 + 0.52514497151172101 + 0.5251616308646726 + 0.5251782909819469 + 0.52519495186360776 + 0.52521161350971146 + 0.52522827592032284 + 0.52524493909550218 + 0.525261603035308 + 0.52527826773980302 + 0.52529493320904841 + 0.52531159944310302 + 0.52532826644202935 + 0.52534493420588746 + 0.52536160273473997 + 0.5253782720286444 + 0.52539494208766591 + 0.52541161291186056 + 0.52542828450129353 + 0.52544495685602388 + 0.52546162997611146 + 0.52547830386161887 + 0.52549497851260762 + 0.52551165392913635 + 0.52552833011126776 + 0.52554500705906204 + 0.52556168477258036 + 0.52557836325188301 + 0.52559504249703259 + 0.52561172250809041 + 0.52562840328511407 + 0.52564508482816752 + 0.52566176713731094 + 0.52567845021260573 + 0.52569513405411195 + 0.52571181866189232 + 0.52572850403600568 + 0.52574519017651367 + 0.52576187708347988 + 0.52577856475696227 + 0.52579525319702336 + 0.52581194240372209 + 0.52582863237712374 + 0.52584532311728593 + 0.5258620146242714 + 0.52587870689814042 + 0.52589539993895429 + 0.52591209374677328 + 0.52592878832166023 + 0.52594548366367655 + 0.52596217977288118 + 0.52597887664933685 + 0.52599557429310373 + 0.52601227270424478 + 0.52602897188281883 + 0.52604567182888873 + 0.52606237254251587 + 0.52607907402375931 + 0.52609577627268311 + 0.52611247928934635 + 0.52612918307381162 + 0.52614588762613812 + 0.52616259294638978 + 0.52617929903462568 + 0.52619600589090876 + 0.52621271351529919 + 0.52622942190785837 + 0.52624613106864804 + 0.52626284099772858 + 0.52627955169516283 + 0.52629626316100964 + 0.52631297539533328 + 0.52632968839819272 + 0.5263464021696509 + 0.52636311670976688 + 0.52637983201860594 + 0.52639654809622605 + 0.52641326494268892 + 0.52642998255805706 + 0.5264467009423911 + 0.52646342009575398 + 0.52648014001820465 + 0.52649686070980473 + 0.5265135821706185 + 0.52653030440070392 + 0.52654702740012493 + 0.52656375116894072 + 0.52658047570721433 + 0.52659720101500596 + 0.52661392709238009 + 0.52663065393939446 + 0.5266473815561119 + 0.52666410994259427 + 0.52668083909890329 + 0.52669756902509923 + 0.52671429972124495 + 0.52673103118740128 + 0.52674776342362972 + 0.5267644964299919 + 0.52678123020654832 + 0.52679796475336349 + 0.52681470007049491 + 0.5268314361580072 + 0.52684817301596065 + 0.52686491064441709 + 0.52688164904343826 + 0.52689838821308588 + 0.52691512815342034 + 0.52693186886450494 + 0.52694861034639995 + 0.52696535259916721 + 0.52698209562286857 + 0.52699883941756709 + 0.52701558398332182 + 0.52703232932019606 + 0.52704907542825019 + 0.52706582230754739 + 0.52708256995814928 + 0.52709931838011548 + 0.52711606757351004 + 0.52713281753839347 + 0.52714956827482795 + 0.52716631978287509 + 0.52718307206259529 + 0.52719982511405206 + 0.52721657893730689 + 0.52723333353242052 + 0.52725008889945613 + 0.52726684503847421 + 0.52728360194953672 + 0.52730035963270538 + 0.52731711808804349 + 0.52733387731561032 + 0.52735063731546894 + 0.52736739808768152 + 0.52738415963230967 + 0.52740092194941546 + 0.5274176850390595 + 0.52743444890130475 + 0.52745121353621227 + 0.5274679789438449 + 0.52748474512426469 + 0.52750151207753104 + 0.52751827980370847 + 0.52753504830285758 + 0.52755181757504155 + 0.52756858762031988 + 0.52758535843875709 + 0.52760213003041367 + 0.52761890239535181 + 0.52763567553363344 + 0.52765244944531919 + 0.52766922413047346 + 0.5276859995891573 + 0.52770277582143121 + 0.52771955282735972 + 0.52773633060700231 + 0.52775310916042228 + 0.52776988848768291 + 0.5277866685888436 + 0.52780344946396651 + 0.52782023111311616 + 0.52783701353635193 + 0.52785379673373589 + 0.52787058070533277 + 0.52788736545120318 + 0.52790415097140797 + 0.52792093726601164 + 0.52793772433507391 + 0.52795451217865652 + 0.52797130079682442 + 0.52798809018963688 + 0.52800488035715742 + 0.5280216712994481 + 0.5280384630165722 + 0.52805525550858801 + 0.52807204877556146 + 0.52808884281755353 + 0.52810563763462604 + 0.52812243322684127 + 0.52813922959426141 + 0.52815602673694839 + 0.52817282465496451 + 0.52818962334837172 + 0.52820642281723373 + 0.52822322306161096 + 0.52824002408156601 + 0.52825682587716205 + 0.52827362844845871 + 0.52829043179552204 + 0.52830723591841156 + 0.52832404081719098 + 0.52834084649192081 + 0.52835765294266479 + 0.52837446016948486 + 0.52839126817244353 + 0.52840807695160275 + 0.52842488650702479 + 0.52844169683877196 + 0.52845850794690508 + 0.5284753198314901 + 0.52849213249258686 + 0.52850894593025621 + 0.52852576014456554 + 0.52854257513557079 + 0.52855939090334036 + 0.52857620744793155 + 0.52859302476941039 + 0.52860984286783785 + 0.52862666174327622 + 0.52864348139578776 + 0.52866030182543589 + 0.52867712303228054 + 0.52869394501638778 + 0.52871076777781723 + 0.52872759131663238 + 0.52874441563289576 + 0.52876124072666952 + 0.52877806659801607 + 0.52879489324699758 + 0.52881172067367777 + 0.52882854887811759 + 0.52884537786038077 + 0.52886220762052938 + 0.52887903815862602 + 0.52889586947473288 + 0.52891270156891235 + 0.5289295344412267 + 0.52894636809173967 + 0.52896320252051365 + 0.52898003772760971 + 0.52899687371309256 + 0.52901371047702361 + 0.52903054801946492 + 0.52904738634048054 + 0.5290642254401311 + 0.52908106531848065 + 0.52909790597559025 + 0.52911474741152587 + 0.52913158962634643 + 0.52914843262011668 + 0.52916527639289912 + 0.52918212094475614 + 0.52919896627574892 + 0.52921581238594129 + 0.52923265927539798 + 0.52924950694417894 + 0.52926635539234812 + 0.52928320461996636 + 0.52930005462709895 + 0.52931690541380694 + 0.52933375698015417 + 0.52935060932620304 + 0.52936746245201594 + 0.52938431635765548 + 0.52940117104318418 + 0.52941802650866565 + 0.52943488275416251 + 0.52945173977973714 + 0.52946859758545228 + 0.52948545617137155 + 0.52950231553755744 + 0.52951917568407258 + 0.52953603661097803 + 0.5295528983183404 + 0.52956976080621954 + 0.52958662407467927 + 0.52960348812378211 + 0.529620352953592 + 0.52963721856417012 + 0.52965408495558042 + 0.52967095212788651 + 0.52968782008114856 + 0.52970468881543187 + 0.52972155833079992 + 0.52973842862731435 + 0.52975529970503765 + 0.52977217156403356 + 0.52978904420436346 + 0.52980591762609264 + 0.52982279182928371 + 0.52983966681399786 + 0.52985654258029902 + 0.52987341912825126 + 0.52989029645791574 + 0.52990717456935765 + 0.52992405346263716 + 0.52994093313781954 + 0.5299578135949673 + 0.52997469483414317 + 0.52999157685540976 + 0.53000845965883114 + 0.53002534324447104 + 0.53004222761238973 + 0.5300591127626525 + 0.53007599869532063 + 0.53009288541045951 + 0.53010977290813022 + 0.53012666118839846 + 0.53014355025132531 + 0.53016044009697261 + 0.5301773307254064 + 0.53019422213668843 + 0.53021111433088142 + 0.53022800730804931 + 0.53024490106825484 + 0.53026179561156206 + 0.53027869093803237 + 0.53029558704773117 + 0.53031248394071984 + 0.53032938161706256 + 0.53034628007682194 + 0.53036317932006083 + 0.53038007934684328 + 0.53039698015723336 + 0.53041388175129245 + 0.53043078412908362 + 0.53044768729067315 + 0.53046459123612033 + 0.53048149596549166 + 0.53049840147884997 + 0.53051530777625666 + 0.53053221485777602 + 0.53054912272347077 + 0.53056603137340497 + 0.53058294080764301 + 0.53059985102624607 + 0.53061676202927976 + 0.53063367381680449 + 0.5306505863888854 + 0.5306674997455868 + 0.53068441388697163 + 0.53070132881310117 + 0.53071824452403993 + 0.53073516101985319 + 0.53075207830060112 + 0.53076899636635078 + 0.53078591521716234 + 0.53080283485309998 + 0.53081975527422776 + 0.53083667648061006 + 0.53085359847230851 + 0.53087052124938849 + 0.53088744481191041 + 0.53090436915994099 + 0.53092129429354207 + 0.53093822021277648 + 0.53095514691770951 + 0.53097207440840444 + 0.53098900268492277 + 0.53100593174733135 + 0.53102286159569057 + 0.53103979223006592 + 0.53105672365051915 + 0.53107365585711597 + 0.531090588849919 + 0.53110752262899141 + 0.53112445719439627 + 0.53114139254619774 + 0.53115832868446045 + 0.5311752656092481 + 0.53119220332062278 + 0.53120914181864887 + 0.53122608110338787 + 0.53124302117490818 + 0.53125996203326875 + 0.53127690367853664 + 0.53129384611077357 + 0.5313107893300425 + 0.53132773333640926 + 0.53134467812993669 + 0.53136162371068796 + 0.53137857007872735 + 0.53139551723411815 + 0.53141246517692586 + 0.53142941390721088 + 0.53144636342503904 + 0.53146331373047462 + 0.53148026482358079 + 0.5314972167044193 + 0.53151416937305718 + 0.53153112282955495 + 0.53154807707397966 + 0.53156503210639428 + 0.53158198792686073 + 0.53159894453544354 + 0.5316159019322082 + 0.53163286011721678 + 0.53164981909053355 + 0.53166677885222302 + 0.53168373940234848 + 0.53170070074097286 + 0.53171766286816202 + 0.53173462578397801 + 0.53175158948848622 + 0.53176855398175005 + 0.53178551926383144 + 0.53180248533479735 + 0.53181945219470972 + 0.5318364198436345 + 0.53185338828163331 + 0.53187035750877087 + 0.53188732752511159 + 0.53190429833071873 + 0.5319212699256568 + 0.53193824230999021 + 0.53195521548378244 + 0.53197218944709657 + 0.5319891641999972 + 0.53200613974254884 + 0.53202311607481612 + 0.53204009319686085 + 0.53205707110875045 + 0.53207404981054385 + 0.53209102930231 + 0.53210800958411186 + 0.53212499065601149 + 0.53214197251807371 + 0.53215895517036405 + 0.53217593861294599 + 0.53219292284588293 + 0.53220990786923916 + 0.53222689368307841 + 0.53224388028746628 + 0.53226086768246494 + 0.53227785586814036 + 0.5322948448445558 + 0.53231183461177567 + 0.5323288251698638 + 0.53234581651888446 + 0.53236280865890251 + 0.53237980158998111 + 0.5323967953121852 + 0.53241378982557785 + 0.53243078513022402 + 0.53244778122618808 + 0.5324647781135351 + 0.53248177579232803 + 0.53249877426263059 + 0.53251577352450874 + 0.53253277357802564 + 0.53254977442324647 + 0.53256677606023417 + 0.53258377848905358 + 0.53260078170976966 + 0.53261778572244556 + 0.53263479052714746 + 0.53265179612393765 + 0.53266880251288184 + 0.53268580969404355 + 0.53270281766748651 + 0.53271982643327653 + 0.53273683599147847 + 0.53275384634215439 + 0.53277085748536923 + 0.53278786942118894 + 0.53280488214967703 + 0.53282189567089844 + 0.53283890998491656 + 0.53285592509179613 + 0.53287294099160065 + 0.53288995768439762 + 0.53290697517024799 + 0.53292399344921781 + 0.53294101252137316 + 0.53295803238677508 + 0.53297505304548964 + 0.53299207449758301 + 0.53300909674311603 + 0.53302611978215764 + 0.53304314361476879 + 0.53306016824101421 + 0.53307719366096129 + 0.53309421987467132 + 0.53311124688221012 + 0.53312827468364288 + 0.53314530327903431 + 0.53316233266844804 + 0.533179362851949 + 0.53319639382960082 + 0.53321342560146956 + 0.53323045816761894 + 0.5332474915281139 + 0.53326452568301941 + 0.53328156063239895 + 0.53329859637631882 + 0.53331563291484274 + 0.53333267024803555 + 0.53334970837596096 + 0.53336674729868383 + 0.53338378701627187 + 0.5334008275287847 + 0.53341786883629139 + 0.53343491093885409 + 0.53345195383653776 + 0.53346899752940902 + 0.53348604201752992 + 0.53350308730096818 + 0.53352013337978488 + 0.53353718025404773 + 0.53355422792382035 + 0.53357127638916901 + 0.53358832565015613 + 0.53360537570684685 + 0.53362242655930758 + 0.53363947820760171 + 0.53365653065179464 + 0.53367358389195252 + 0.53369063792813776 + 0.53370769276041563 + 0.53372474838885109 + 0.53374180481351041 + 0.53375886203445744 + 0.53377592005175734 + 0.53379297886547372 + 0.53381003847567321 + 0.53382709888242064 + 0.53384416008577862 + 0.53386122208581499 + 0.53387828488259337 + 0.53389534847617759 + 0.53391241286663416 + 0.53392947805402813 + 0.53394654403842323 + 0.5339636108198863 + 0.5339806783984794 + 0.53399774677427059 + 0.53401481594732347 + 0.53403188591770212 + 0.53404895668547303 + 0.53406602825069982 + 0.53408310061344777 + 0.53410017377378471 + 0.53411724773177183 + 0.53413432248747705 + 0.5341513980409629 + 0.53416847439229587 + 0.53418555154154113 + 0.53420262948876396 + 0.5342197082340282 + 0.53423678777740036 + 0.53425386811894437 + 0.53427094925872554 + 0.53428803119681034 + 0.53430511393326141 + 0.53432219746814791 + 0.5343392818015299 + 0.53435636693347632 + 0.53437345286405158 + 0.53439053959331928 + 0.53440762712134604 + 0.53442471544819725 + 0.53444180457393675 + 0.53445889449863127 + 0.53447598522234474 + 0.53449307674514235 + 0.53451016906709092 + 0.53452726218825564 + 0.53454435610869899 + 0.53456145082848927 + 0.53457854634769042 + 0.5345956426663675 + 0.53461273978458612 + 0.53462983770241157 + 0.53464693641990912 + 0.53466403593714407 + 0.5346811362541819 + 0.53469823737108657 + 0.53471533928792614 + 0.53473244200476455 + 0.53474954552166731 + 0.53476664983869837 + 0.53478375495592445 + 0.53480086087341228 + 0.53481796759122469 + 0.53483507510942696 + 0.53485218342808727 + 0.53486929254726823 + 0.53488640246703667 + 0.53490351318745799 + 0.53492062470859747 + 0.53493773703052083 + 0.53495485015329203 + 0.53497196407697911 + 0.53498907880164492 + 0.5350061943273563 + 0.53502331065417863 + 0.53504042778217731 + 0.53505754571141917 + 0.53507466444196583 + 0.5350917839738879 + 0.53510890430724689 + 0.53512602544210974 + 0.53514314737854329 + 0.53516027011661027 + 0.53517739365637873 + 0.53519451799791318 + 0.53521164314128022 + 0.53522876908654271 + 0.53524589583377014 + 0.53526302338302545 + 0.5352801517343756 + 0.5352972808878832 + 0.53531441084361808 + 0.53533154160164431 + 0.53534867316202606 + 0.53536580552483171 + 0.53538293869012399 + 0.53540007265796996 + 0.53541720742843624 + 0.5354343430015861 + 0.53545147937748905 + 0.53546861655620648 + 0.53548575453780678 + 0.53550289332235546 + 0.53552003290991701 + 0.53553717330055817 + 0.53555431449434454 + 0.53557145649134197 + 0.53558859929161573 + 0.53560574289523188 + 0.53562288730225693 + 0.5356400325127556 + 0.53565717852679329 + 0.53567432534443837 + 0.53569147296575248 + 0.53570862139080533 + 0.53572577061966131 + 0.53574292065238582 + 0.53576007148904614 + 0.53577722312970533 + 0.53579437557443277 + 0.53581152882329186 + 0.53582868287634922 + 0.53584583773367078 + 0.5358629933953224 + 0.53588014986136956 + 0.53589730713187944 + 0.53591446520691766 + 0.5359316240865486 + 0.53594878377083943 + 0.53596594425985589 + 0.53598310555366369 + 0.53600026765233111 + 0.53601743055591999 + 0.53603459426449895 + 0.5360517587781336 + 0.53606892409688955 + 0.5360860902208342 + 0.53610325715003182 + 0.53612042488454825 + 0.536137593424452 + 0.536154762769806 + 0.53617193292067888 + 0.53618910387713514 + 0.53620627563924184 + 0.53622344820706347 + 0.53624062158066865 + 0.53625779576012167 + 0.53627497074548847 + 0.53629214653683621 + 0.53630932313423063 + 0.53632650053773645 + 0.53634367874742217 + 0.53636085776335352 + 0.53637803758559488 + 0.53639521821421388 + 0.53641239964927723 + 0.53642958189084999 + 0.53644676493899768 + 0.53646394879378767 + 0.53648113345528703 + 0.53649831892356048 + 0.53651550519867519 + 0.53653269228069589 + 0.53654988016969096 + 0.53656706886572514 + 0.53658425836886425 + 0.53660144867917681 + 0.53661863979672764 + 0.53663583172158125 + 0.53665302445380747 + 0.53667021799346981 + 0.53668741234063666 + 0.53670460749537297 + 0.53672180345774556 + 0.53673900022782095 + 0.53675619780566597 + 0.53677339619134556 + 0.53679059538492557 + 0.53680779538647483 + 0.53682499619605772 + 0.53684219781374198 + 0.53685940023959444 + 0.53687660347367894 + 0.53689380751606386 + 0.53691101236681538 + 0.53692821802599933 + 0.53694542449368332 + 0.53696263176993331 + 0.53697983985481401 + 0.53699704874839538 + 0.53701425845074091 + 0.53703146896191789 + 0.53704868028199393 + 0.53706589241103486 + 0.53708310534910564 + 0.53710031909627476 + 0.53711753365260995 + 0.53713474901817304 + 0.53715196519303554 + 0.53716918217726095 + 0.53718639997091677 + 0.53720361857407017 + 0.53722083798678621 + 0.53723805820913495 + 0.53725527924117833 + 0.53727250108298552 + 0.53728972373462369 + 0.53730694719615779 + 0.5373241714676551 + 0.53734139654918345 + 0.53735862244080612 + 0.53737584914259451 + 0.53739307665461244 + 0.53741030497692577 + 0.53742753410960342 + 0.53744476405271191 + 0.53746199480631551 + 0.53747922637048362 + 0.53749645874528218 + 0.53751369193077603 + 0.53753092592703555 + 0.53754816073412426 + 0.53756539635211087 + 0.53758263278106178 + 0.53759987002104181 + 0.53761710807212004 + 0.53763434693436374 + 0.53765158660783674 + 0.53766882709260921 + 0.53768606838874611 + 0.5377033104963137 + 0.53772055341538094 + 0.53773779714601255 + 0.53775504168827648 + 0.53777228704223889 + 0.53778953320796741 + 0.53780678018552952 + 0.5378240279749904 + 0.53784127657641756 + 0.53785852598987871 + 0.53787577621544014 + 0.53789302725316823 + 0.53791027910313194 + 0.53792753176539621 + 0.53794478524002753 + 0.53796203952709476 + 0.53797929462666427 + 0.53799655053880246 + 0.53801380726357573 + 0.53803106480105445 + 0.5380483231513008 + 0.5380655823143855 + 0.53808284229037318 + 0.53810010307933198 + 0.53811736468132931 + 0.53813462709643167 + 0.53815189032470689 + 0.53816915436622004 + 0.53818641922104005 + 0.53820368488923465 + 0.53822095137086912 + 0.53823821866600985 + 0.53825548677472712 + 0.53827275569708488 + 0.53829002543315219 + 0.53830729598299543 + 0.53832456734668244 + 0.53834183952427972 + 0.53835911251585378 + 0.53837638632147355 + 0.53839366094120444 + 0.53841093637511406 + 0.53842821262327167 + 0.53844548968574113 + 0.53846276756259148 + 0.53848004625389057 + 0.53849732575970499 + 0.53851460608010127 + 0.53853188721514722 + 0.53854916916490936 + 0.53856645192945685 + 0.53858373550885497 + 0.53860101990317288 + 0.53861830511247588 + 0.53863559113683168 + 0.53865287797630967 + 0.53867016563097503 + 0.53868745410089558 + 0.53870474338613938 + 0.53872203348677283 + 0.53873932440286265 + 0.53875661613447812 + 0.53877390868168706 + 0.53879120204455211 + 0.53880849622314653 + 0.53882579121753427 + 0.53884308702778472 + 0.53886038365396294 + 0.53887768109613843 + 0.53889497935437769 + 0.53891227842874878 + 0.53892957831931843 + 0.53894687902615435 + 0.53896418054932349 + 0.53898148288889358 + 0.53899878604493279 + 0.53901609001751027 + 0.53903339480668899 + 0.53905070041254077 + 0.53906800683512968 + 0.53908531407452631 + 0.53910262213079618 + 0.53911993100400712 + 0.53913724069422753 + 0.539154551201525 + 0.53917186252596527 + 0.53918917466761762 + 0.53920648762654999 + 0.53922380140282922 + 0.53924111599652214 + 0.53925843140769669 + 0.53927574763642239 + 0.53929306468276583 + 0.53931038254679253 + 0.53932770122857332 + 0.53934502072817359 + 0.53936234104566272 + 0.53937966218110778 + 0.53939698413457648 + 0.53941430690613446 + 0.53943163049585385 + 0.53944895490379752 + 0.53946628013003739 + 0.53948360617463798 + 0.53950093303766833 + 0.53951826071919695 + 0.53953558921929068 + 0.53955291853801746 + 0.53957024867544423 + 0.53958757963164039 + 0.5396049114066731 + 0.53962224400061021 + 0.53963957741351876 + 0.53965691164546836 + 0.53967424669652442 + 0.53969158256675642 + 0.53970891925623143 + 0.53972625676501873 + 0.53974359509318426 + 0.53976093424079741 + 0.53977827420792501 + 0.53979561499463524 + 0.5398129566009966 + 0.53983029902707713 + 0.53984764227294391 + 0.5398649863386652 + 0.53988233122430906 + 0.53989967692994267 + 0.5399170234556343 + 0.53993437080145334 + 0.53995171896746563 + 0.53996906795374211 + 0.53998641776034706 + 0.54000376838735142 + 0.54002111983482082 + 0.54003847210282507 + 0.54005582519143236 + 0.54007317910070962 + 0.54009053383072536 + 0.54010788938154775 + 0.54012524575324405 + 0.54014260294588368 + 0.54015996095953389 + 0.54017731979426276 + 0.54019467945013888 + 0.54021203992722933 + 0.54022940122560359 + 0.54024676334532895 + 0.54026412628647369 + 0.54028149004910619 + 0.54029885463329497 + 0.54031622003910695 + 0.54033358626661054 + 0.54035095331587557 + 0.54036832118696787 + 0.54038568987995839 + 0.54040305939491284 + 0.54042042973189997 + 0.54043780089098925 + 0.54045517287224665 + 0.54047254567574321 + 0.540489919301546 + 0.54050729374972217 + 0.54052466902034169 + 0.54054204511347281 + 0.5405594220291815 + 0.54057679976753892 + 0.54059417832861079 + 0.54061155771246705 + 0.54062893791917743 + 0.54064631894880655 + 0.54066370080142545 + 0.54068108347710286 + 0.5406984669759044 + 0.54071585129790145 + 0.54073323644316107 + 0.54075062241175065 + 0.54076800920374002 + 0.54078539681919746 + 0.54080278525819192 + 0.54082017452078912 + 0.54083756460706156 + 0.54085495551707397 + 0.54087234725089739 + 0.540889739808598 + 0.54090713319024564 + 0.54092452739591002 + 0.54094192242565742 + 0.54095931827955757 + 0.54097671495767774 + 0.54099411246008788 + 0.54101151078685683 + 0.54102890993805164 + 0.54104630991374092 + 0.54106371071399362 + 0.54108111233887934 + 0.5410985147884656 + 0.54111591806282111 + 0.54113332216201449 + 0.54115072708611422 + 0.54116813283518928 + 0.5411855394093068 + 0.5412029468085382 + 0.54122035503295085 + 0.54123776408261204 + 0.54125517395759182 + 0.5412725846579578 + 0.54128999618378093 + 0.54130740853512627 + 0.54132482171206642 + 0.54134223571466877 + 0.54135965054299939 + 0.541377066197131 + 0.54139448267712842 + 0.54141189998306427 + 0.54142931811500483 + 0.5414467370730186 + 0.54146415685717597 + 0.54148157746754555 + 0.54149899890419484 + 0.54151642116719245 + 0.54153384425660878 + 0.54155126817251109 + 0.5415686929149709 + 0.54158611848405436 + 0.54160354487983031 + 0.54162097210236881 + 0.54163840015173881 + 0.54165582902800768 + 0.54167325873124561 + 0.54169068926152153 + 0.54170812061890283 + 0.54172555280346113 + 0.54174298581526248 + 0.54176041965437727 + 0.54177785432087289 + 0.54179528981482084 + 0.54181272613628872 + 0.5418301632853455 + 0.54184760126206133 + 0.54186504006650238 + 0.54188247969874026 + 0.54189992015884259 + 0.54191736144687819 + 0.54193480356291734 + 0.54195224650702767 + 0.54196969027927944 + 0.54198713487974159 + 0.54200458030848164 + 0.54202202656557119 + 0.54203947365107663 + 0.54205692156506824 + 0.54207437030761474 + 0.54209181987878685 + 0.54210927027865174 + 0.54212672150727881 + 0.54214417356473943 + 0.54216162645109867 + 0.54217908016642824 + 0.54219653471079843 + 0.54221399008427551 + 0.54223144628692999 + 0.54224890331883069 + 0.54226636118004801 + 0.54228381987064977 + 0.54230127939070627 + 0.54231873974028644 + 0.54233620091945678 + 0.54235366292829157 + 0.54237112576685598 + 0.54238858943522172 + 0.54240605393345642 + 0.54242351926162924 + 0.54244098541981178 + 0.54245845240807078 + 0.54247592022647628 + 0.54249338887509757 + 0.5425108583540037 + 0.54252832866326506 + 0.54254579980295092 + 0.54256327177313024 + 0.54258074457387084 + 0.54259821820524456 + 0.54261569266731779 + 0.5426331679601637 + 0.54265064408384889 + 0.54266812103844497 + 0.54268559882401857 + 0.54270307744064006 + 0.54272055688838006 + 0.54273803716730762 + 0.54275551827749069 + 0.54277300021899966 + 0.54279048299190524 + 0.54280796659627506 + 0.5428254510321785 + 0.54284293629968738 + 0.54286042239886956 + 0.54287790932979407 + 0.54289539709253187 + 0.54291288568715057 + 0.54293037511372211 + 0.5429478653723131 + 0.54296535646299537 + 0.54298284838583821 + 0.54300034114091089 + 0.54301783472828136 + 0.54303532914802155 + 0.54305282440020186 + 0.5430703204848879 + 0.54308781740215284 + 0.54310531515206439 + 0.5431228137346934 + 0.54314031315010924 + 0.5431578133983811 + 0.54317531447957956 + 0.5431928163937727 + 0.54321031914103102 + 0.54322782272142411 + 0.54324532713502249 + 0.54326283238189543 + 0.5432803384621111 + 0.54329784537574266 + 0.54331535312285706 + 0.54333286170352457 + 0.5433503711178137 + 0.54336788136579739 + 0.54338539244754269 + 0.54340290436312155 + 0.54342041711260192 + 0.54343793069605451 + 0.54345544511354771 + 0.54347296036515447 + 0.54349047645094051 + 0.5435079933709791 + 0.54352551112533831 + 0.54354302971408908 + 0.54356054913730067 + 0.5435780693950425 + 0.54359559048738559 + 0.5436131124143978 + 0.54363063517615129 + 0.54364815877271433 + 0.54366568320415753 + 0.54368320847055318 + 0.54370073457196666 + 0.54371826150847014 + 0.54373578928013444 + 0.54375331788702908 + 0.54377084732922232 + 0.54378837760678611 + 0.54380590871979018 + 0.5438234406683039 + 0.54384097345239801 + 0.54385850707214112 + 0.54387604152760505 + 0.54389357681885941 + 0.54391111294597261 + 0.54392864990901657 + 0.54394618770806114 + 0.54396372634317558 + 0.54398126581442963 + 0.54399880612189555 + 0.54401634726564152 + 0.54403388924573859 + 0.54405143206225604 + 0.54406897571526391 + 0.54408652020483395 + 0.54410406553103485 + 0.54412161169393747 + 0.54413915869361129 + 0.54415670653012738 + 0.54417425520355411 + 0.54419180471396345 + 0.54420935506142676 + 0.54422690624601211 + 0.54424445826778933 + 0.54426201112683048 + 0.54427956482320416 + 0.54429711935698255 + 0.54431467472823403 + 0.54433223093702965 + 0.54434978798344036 + 0.54436734586753466 + 0.54438490458938471 + 0.54440246414906035 + 0.54442002454663119 + 0.54443758578216839 + 0.54445514785574167 + 0.54447271076742199 + 0.54449027451727916 + 0.54450783910538281 + 0.54452540453180542 + 0.54454297079661673 + 0.54456053789988523 + 0.54457810584168331 + 0.54459567462208047 + 0.54461324424114832 + 0.54463081469895491 + 0.54464838599557419 + 0.54466595813107321 + 0.54468353110552437 + 0.5447011049189977 + 0.54471867957156417 + 0.54473625506329226 + 0.54475383139425437 + 0.54477140856452178 + 0.54478898657416297 + 0.54480656542324923 + 0.54482414511185151 + 0.54484172564003974 + 0.54485930700788499 + 0.54487688921545741 + 0.54489447226282783 + 0.54491205615006644 + 0.54492964087724549 + 0.5449472264444325 + 0.54496481285170117 + 0.54498240009912002 + 0.54499998818676032 + 0.54501757711469334 + 0.54503516688299025 + 0.54505275749171977 + 0.54507034894095308 + 0.54508794123076132 + 0.54510553436121589 + 0.54512312833238663 + 0.5451407231443437 + 0.54515831879715937 + 0.54517591529090259 + 0.54519351262564575 + 0.54521111080145879 + 0.54522870981841198 + 0.54524630967657639 + 0.54526391037602462 + 0.54528151191682417 + 0.54529911429904887 + 0.54531671752276756 + 0.54533432158805129 + 0.54535192649497177 + 0.54536953224360007 + 0.54538713883400503 + 0.54540474626625923 + 0.54542235454043286 + 0.54543996365659697 + 0.54545757361482339 + 0.54547518441518184 + 0.54549279605774248 + 0.54551040854257804 + 0.54552802186975857 + 0.54554563603935546 + 0.54556325105143877 + 0.54558086690607999 + 0.5455984836033505 + 0.54561610114331904 + 0.54563371952605977 + 0.5456513387516414 + 0.54566895882013688 + 0.54568657973161472 + 0.54570420148614784 + 0.54572182408380654 + 0.54573944752466319 + 0.54575707180878574 + 0.54577469693624803 + 0.54579232290712032 + 0.54580994972147423 + 0.54582757737937959 + 0.5458452058809069 + 0.54586283522613011 + 0.54588046541511814 + 0.54589809644794385 + 0.54591572832467494 + 0.54593336104538659 + 0.54595099461014795 + 0.54596862901902921 + 0.54598626427210306 + 0.54600390036944124 + 0.54602153731111269 + 0.54603917509719002 + 0.54605681372774506 + 0.54607445320284798 + 0.54609209352257027 + 0.54610973468698376 + 0.54612737669615852 + 0.54614501955016748 + 0.54616266324907958 + 0.54618030779296656 + 0.54619795318190256 + 0.54621559941595532 + 0.54623324649519767 + 0.54625089441970154 + 0.5462685431895381 + 0.54628619280477808 + 0.54630384326549164 + 0.54632149457175161 + 0.5463391467236286 + 0.54635679972119555 + 0.54637445356452263 + 0.54639210825368167 + 0.54640976378874295 + 0.5464274201697783 + 0.54644507739686066 + 0.5464627354700603 + 0.54648039438944773 + 0.546498054155096 + 0.5465157147670755 + 0.54653337622545783 + 0.54655103853031617 + 0.54656870168171823 + 0.54658636567973984 + 0.54660403052445006 + 0.54662169621592038 + 0.54663936275422165 + 0.54665703013942801 + 0.54667469837160865 + 0.54669236745083671 + 0.5467100373771826 + 0.54672770815071825 + 0.54674537977151516 + 0.54676305223964661 + 0.54678072555518065 + 0.54679839971819144 + 0.54681607472874971 + 0.54683375058692829 + 0.54685142729279668 + 0.54686910484642792 + 0.54688678324789519 + 0.54690446249726632 + 0.5469221425946158 + 0.54693982354001558 + 0.54695750533353493 + 0.54697518797524813 + 0.54699287146522457 + 0.54701055580353886 + 0.54702824099026004 + 0.54704592702546007 + 0.54706361390921354 + 0.54708130164158852 + 0.54709899022265807 + 0.54711667965249544 + 0.54713436993117126 + 0.54715206105875736 + 0.54716975303532589 + 0.54718744586094736 + 0.54720513953569505 + 0.54722283405963945 + 0.54724052943285417 + 0.54725822565541082 + 0.54727592272737891 + 0.54729362064883302 + 0.54731131941984512 + 0.54732901904048459 + 0.54734671951082481 + 0.54736442083093895 + 0.5473821230008965 + 0.54739982602076942 + 0.5474175298906323 + 0.54743523461055599 + 0.54745294018061119 + 0.54747064660087097 + 0.54748835387140637 + 0.54750606199229213 + 0.54752377096359595 + 0.54754148078539289 + 0.54755919145775356 + 0.54757690298075135 + 0.54759461535445708 + 0.54761232857894404 + 0.54763004265428306 + 0.54764775758054629 + 0.54766547335780569 + 0.54768318998613486 + 0.5477009074656044 + 0.54771862579628661 + 0.54773634497825618 + 0.54775406501157986 + 0.54777178589633391 + 0.54778950763259049 + 0.54780723022042022 + 0.54782495365989547 + 0.5478426779510881 + 0.54786040309407202 + 0.54787812908891764 + 0.54789585593569889 + 0.54791358363448495 + 0.54793131218535085 + 0.54794904158836866 + 0.54796677184360942 + 0.54798450295114653 + 0.54800223491105227 + 0.54801996772339612 + 0.54803770138825436 + 0.54805543590569661 + 0.54807317127579624 + 0.54809090749862432 + 0.54810864457425579 + 0.54812638250276147 + 0.54814412128421364 + 0.54816186091868335 + 0.548179601406244 + 0.54819734274696941 + 0.54821508494093163 + 0.54823282798820039 + 0.54825057188885085 + 0.54826831664295361 + 0.54828606225058263 + 0.54830380871181006 + 0.54832155602670685 + 0.54833930419534671 + 0.54835705321780204 + 0.54837480309414643 + 0.54839255382444962 + 0.54841030540878644 + 0.54842805784722803 + 0.54844581113984825 + 0.54846356528671802 + 0.54848132028791086 + 0.54849907614349791 + 0.54851683285355435 + 0.54853459041815122 + 0.5485523488373607 + 0.54857010811125551 + 0.54858786823990902 + 0.54860562922339395 + 0.54862339106178126 + 0.54864115375514477 + 0.54865891730355676 + 0.54867668170709116 + 0.54869444696581893 + 0.54871221307981266 + 0.54872998004914608 + 0.54874774787389169 + 0.54876551655412187 + 0.54878328608990923 + 0.54880105648132593 + 0.54881882772844626 + 0.54883659983134225 + 0.54885437279008542 + 0.54887214660475081 + 0.54888992127540948 + 0.54890769680213403 + 0.5489254731849984 + 0.54894325042407499 + 0.54896102851943496 + 0.54897880747115368 + 0.54899658727930367 + 0.54901436794395475 + 0.54903214946518331 + 0.54904993184306083 + 0.54906771507765983 + 0.54908549916905269 + 0.54910328411731502 + 0.54912106992251641 + 0.54913885658473083 + 0.54915664410403231 + 0.54917443248049214 + 0.54919222171418547 + 0.54921001180518103 + 0.54922780275355665 + 0.54924559455938238 + 0.54926338722273227 + 0.54928118074367871 + 0.54929897512229464 + 0.54931677035865389 + 0.54933456645282908 + 0.54935236340489146 + 0.54937016121491655 + 0.54938795988297695 + 0.54940575940914538 + 0.54942355979349311 + 0.54944136103609686 + 0.54945916313702681 + 0.54947696609635677 + 0.54949476991415958 + 0.54951257459050906 + 0.54953038012547828 + 0.5495481865191385 + 0.54956599377156645 + 0.54958380188283074 + 0.54960161085300829 + 0.54961942068217173 + 0.54963723137039266 + 0.54965504291774492 + 0.54967285532430288 + 0.54969066859013782 + 0.54970848271532247 + 0.54972629769993364 + 0.5497441135440404 + 0.54976193024772047 + 0.54977974781104155 + 0.54979756623408182 + 0.54981538551691134 + 0.54983320565960558 + 0.54985102666223606 + 0.54986884852487838 + 0.54988667124760382 + 0.54990449483048542 + 0.54992231927359747 + 0.5499401445770139 + 0.54995797074080766 + 0.54997579776505034 + 0.54999362564981735 + 0.55001145439518173 + 0.55002928400121642 + 0.55004711446799537 + 0.5500649457955904 + 0.55008277798407845 + 0.55010061103352814 + 0.55011844494401674 + 0.55013627971561552 + 0.55015411534840031 + 0.55017195184244128 + 0.55018978919781536 + 0.55020762741459295 + 0.55022546649285087 + 0.55024330643265806 + 0.5502611472340917 + 0.55027898889722582 + 0.55029683142213093 + 0.55031467480888252 + 0.55033251905755254 + 0.5503503641682177 + 0.55036821014094828 + 0.55038605697582033 + 0.55040390467290523 + 0.55042175323227738 + 0.55043960265401115 + 0.55045745293817971 + 0.55047530408485712 + 0.55049315609411675 + 0.55051100896603156 + 0.5505288627006758 + 0.55054671729812399 + 0.55056457275844795 + 0.55058242908172195 + 0.55060028626802171 + 0.55061814431741773 + 0.55063600322998585 + 0.55065386300579888 + 0.550671723644933 + 0.55068958514745703 + 0.55070744751344947 + 0.55072531074298214 + 0.55074317483612956 + 0.55076103979296342 + 0.55077890561355958 + 0.55079677229799262 + 0.55081463984633416 + 0.55083250825865893 + 0.55085037753503985 + 0.55086824767555287 + 0.55088611868027115 + 0.55090399054926809 + 0.5509218632826165 + 0.55093973688039111 + 0.55095761134266785 + 0.55097548666951712 + 0.5509933628610163 + 0.55101123991723588 + 0.55102911783825292 + 0.55104699662413947 + 0.55106487627497147 + 0.55108275679082086 + 0.55110063817176069 + 0.55111852041786846 + 0.55113640352921578 + 0.55115428750587636 + 0.55117217234792582 + 0.55119005805543742 + 0.55120794462848466 + 0.55122583206714204 + 0.55124372037148406 + 0.55126160954158432 + 0.55127949957751743 + 0.55129739047935777 + 0.55131528224717763 + 0.55133317488105271 + 0.55135106838105652 + 0.55136896274726244 + 0.55138685797974785 + 0.55140475407858336 + 0.55142265104384491 + 0.55144054887560456 + 0.55145844757393991 + 0.55147634713892268 + 0.55149424757062782 + 0.55151214886912991 + 0.55153005103450248 + 0.55154795406682022 + 0.55156585796615643 + 0.55158376273258602 + 0.55160166836618507 + 0.5516195748670254 + 0.55163748223518083 + 0.55165539047072853 + 0.55167329957374078 + 0.55169120954429229 + 0.55170912038245778 + 0.55172703208831098 + 0.55174494466192769 + 0.55176285810337888 + 0.55178077241274204 + 0.55179868759009187 + 0.55181660363549945 + 0.55183452054904214 + 0.55185243833079467 + 0.55187035698082798 + 0.55188827649922101 + 0.55190619688604436 + 0.5519241181413761 + 0.55194204026528637 + 0.55195996325785324 + 0.55197788711915008 + 0.55199581184925062 + 0.55201373744823079 + 0.55203166391616432 + 0.55204959125312481 + 0.55206751945918842 + 0.55208544853442887 + 0.55210337847892088 + 0.55212130929273828 + 0.5521392409759559 + 0.55215717352865001 + 0.55217510695089422 + 0.55219304124276214 + 0.55221097640433014 + 0.55222891243567052 + 0.55224684933685941 + 0.55226478710797211 + 0.55228272574908199 + 0.55230066526026411 + 0.55231860564159219 + 0.55233654689314393 + 0.5523544890149904 + 0.55237243200720776 + 0.55239037586987239 + 0.55240832060305678 + 0.55242626620683721 + 0.55244421268128618 + 0.55246216002647996 + 0.55248010824249494 + 0.55249805732940349 + 0.55251600728728079 + 0.55253395811620187 + 0.55255190981624169 + 0.55256986238747541 + 0.55258781582997696 + 0.55260577014382262 + 0.55262372532908599 + 0.55264168138584258 + 0.55265963831416587 + 0.55267759611413236 + 0.55269555478581722 + 0.55271351432929283 + 0.55273147474463724 + 0.55274943603192406 + 0.55276739819122722 + 0.55278536122262301 + 0.55280332512618557 + 0.55282128990199109 + 0.55283925555011237 + 0.55285722207062704 + 0.5528751894636077 + 0.55289315772913228 + 0.55291112686727195 + 0.55292909687810443 + 0.55294706776170388 + 0.55296503951814535 + 0.55298301214750545 + 0.55300098564985667 + 0.55301896002527573 + 0.55303693527383635 + 0.55305491139561536 + 0.55307288839068647 + 0.55309086625912496 + 0.55310884500100754 + 0.55312682461640816 + 0.55314480510540076 + 0.55316278646806316 + 0.55318076870446808 + 0.55319875181469236 + 0.55321673579881092 + 0.55323472065689672 + 0.5532527063890289 + 0.5532706929952802 + 0.55328868047572599 + 0.55330666883044155 + 0.55332465805950226 + 0.5533426481629834 + 0.55336063914096167 + 0.55337863099350992 + 0.55339662372070464 + 0.55341461732262143 + 0.55343261179933556 + 0.55345060715092098 + 0.55346860337745452 + 0.55348660047901044 + 0.55350459845566635 + 0.55352259730749553 + 0.55354059703457303 + 0.55355859763697435 + 0.55357659911477763 + 0.55359460146805584 + 0.55361260469688267 + 0.55363060880133785 + 0.55364861378149421 + 0.55366661963742569 + 0.55368462636921201 + 0.55370263397692565 + 0.55372064246064245 + 0.55373865182043769 + 0.55375666205638807 + 0.55377467316856821 + 0.55379268515705449 + 0.55381069802192129 + 0.55382871176324411 + 0.55384672638109977 + 0.55386474187556256 + 0.55388275824670796 + 0.55390077549461292 + 0.55391879361935281 + 0.55393681262100214 + 0.55395483249963751 + 0.5539728532553333 + 0.55399087488816645 + 0.55400889739821246 + 0.55402692078554572 + 0.55404494505024438 + 0.55406297019238138 + 0.55408099621203366 + 0.55409902310927683 + 0.55411705088418661 + 0.55413507953683849 + 0.55415310906730963 + 0.55417113947567398 + 0.55418917076200758 + 0.55420720292638581 + 0.55422523596888595 + 0.55424326988958339 + 0.55426130468855384 + 0.55427934036587045 + 0.55429737692161274 + 0.55431541435585507 + 0.55433345266867473 + 0.55435149186014443 + 0.55436953193034277 + 0.55438757287934404 + 0.55440561470722394 + 0.55442365741405952 + 0.55444170099992662 + 0.55445974546490084 + 0.55447779080905812 + 0.55449583703247396 + 0.55451388413522573 + 0.55453193211738627 + 0.55454998097903541 + 0.55456803072024641 + 0.55458608134109633 + 0.55460413284165955 + 0.5546221852220159 + 0.55464023848223731 + 0.55465829262240063 + 0.55467634764258456 + 0.55469440354286359 + 0.55471246032331223 + 0.55473051798400752 + 0.55474857652502663 + 0.55476663594644426 + 0.55478469624833748 + 0.554802757430782 + 0.55482081949385265 + 0.5548388824376278 + 0.55485694626218207 + 0.55487501096759251 + 0.55489307655393527 + 0.55491114302128608 + 0.55492921036972087 + 0.55494727859931692 + 0.55496534771014738 + 0.55498341770229365 + 0.55500148857582743 + 0.55501956033082622 + 0.55503763296736741 + 0.55505570648552527 + 0.55507378088537851 + 0.55509185616700185 + 0.55510993233047135 + 0.55512800937586404 + 0.5551460873032561 + 0.55516416611272357 + 0.55518224580434239 + 0.55520032637819094 + 0.55521840783434306 + 0.5552364901728758 + 0.55525457339386641 + 0.55527265749738974 + 0.55529074248352461 + 0.55530882835234419 + 0.55532691510392851 + 0.55534500273835108 + 0.55536309125568928 + 0.55538118065602049 + 0.55539927093941932 + 0.55541736210596326 + 0.55543545415572981 + 0.55545354708879369 + 0.55547164090523093 + 0.55548973560512027 + 0.55550783118853797 + 0.55552592765555864 + 0.55554402500625988 + 0.55556212324071907 + 0.55558022235901094 + 0.55559832236121443 + 0.55561642324740435 + 0.55563452501765664 + 0.55565262767205048 + 0.55567073121066046 + 0.55568883563356264 + 0.55570694094083617 + 0.55572504713255566 + 0.5557431542087975 + 0.55576126216964039 + 0.55577937101515928 + 0.55579748074543167 + 0.55581559136053371 + 0.55583370286054312 + 0.55585181524553473 + 0.55586992851558725 + 0.55588804267077596 + 0.55590615771117824 + 0.55592427363687158 + 0.55594239044793226 + 0.55596050814443554 + 0.55597862672645992 + 0.5559967461940819 + 0.55601486654737908 + 0.55603298778642518 + 0.55605110991130013 + 0.55606923292208077 + 0.55608735681884169 + 0.55610548160166196 + 0.55612360727061805 + 0.55614173382578469 + 0.55615986126724248 + 0.55617798959506504 + 0.55619611880932995 + 0.55621424891011617 + 0.55623237989749896 + 0.55625051177155449 + 0.55626864453236191 + 0.55628677817999628 + 0.5563049127145353 + 0.5563230481360566 + 0.55634118444463676 + 0.55635932164035207 + 0.55637745972328023 + 0.55639559869349775 + 0.55641373855108378 + 0.55643187929611182 + 0.55645002092866136 + 0.55646816344880856 + 0.55648630685663136 + 0.55650445115220604 + 0.55652259633561063 + 0.55654074240692142 + 0.556558889366215 + 0.5565770372135691 + 0.55659518594906288 + 0.55661333557277026 + 0.55663148608477042 + 0.55664963748513852 + 0.55666778977395481 + 0.55668594295129492 + 0.556704097017235 + 0.55672225197185321 + 0.55674040781522716 + 0.55675856454743367 + 0.55677672216855179 + 0.55679488067865546 + 0.55681304007782395 + 0.55683120036613376 + 0.55684936154366427 + 0.55686752361048919 + 0.55688568656668924 + 0.5569038504123397 + 0.55692201514751838 + 0.55694018077230356 + 0.5569583472867714 + 0.55697651469100162 + 0.55699468298506793 + 0.55701285216904828 + 0.55703102224302359 + 0.5570491932070688 + 0.55706736506126087 + 0.5570855378056776 + 0.55710371144039716 + 0.5571218859654975 + 0.55714006138105399 + 0.5571582376871459 + 0.55717641488384995 + 0.5571945929712443 + 0.55721277194940544 + 0.55723095181841165 + 0.55724913257834086 + 0.55726731422926978 + 0.55728549677127537 + 0.55730368020443666 + 0.55732186452883203 + 0.55734004974453688 + 0.55735823585162914 + 0.55737642285018707 + 0.55739461074028862 + 0.55741279952201084 + 0.55743098919543022 + 0.55744917976062769 + 0.55746737121767875 + 0.55748556356666013 + 0.55750375680765007 + 0.55752195094072787 + 0.55754014596597057 + 0.5575583418834551 + 0.55757653869325929 + 0.55759473639546142 + 0.55761293499013997 + 0.55763113447737001 + 0.55764933485723278 + 0.55766753612980369 + 0.55768573829516088 + 0.55770394135338264 + 0.55772214530454711 + 0.55774035014873147 + 0.55775855588601364 + 0.55777676251647057 + 0.55779497004018208 + 0.55781317845722489 + 0.55783138776767716 + 0.55784959797161759 + 0.55786780906912137 + 0.55788602106026952 + 0.55790423394513922 + 0.55792244772380584 + 0.55794066239635187 + 0.55795887796285015 + 0.55797709442338317 + 0.55799531177802641 + 0.55801353002685827 + 0.55803174916995846 + 0.55804996920740135 + 0.55806819013926767 + 0.55808641196563624 + 0.55810463468658233 + 0.55812285830218455 + 0.55814108281252395 + 0.5581593082176749 + 0.55817753451771823 + 0.55819576171272989 + 0.55821398980278958 + 0.5582322187879758 + 0.55825044866836415 + 0.55826867944403447 + 0.55828691111506501 + 0.55830514368153439 + 0.55832337714351832 + 0.55834161150109807 + 0.55835984675435191 + 0.55837808290335422 + 0.55839631994818639 + 0.55841455788892669 + 0.55843279672565238 + 0.55845103645844196 + 0.55846927708737248 + 0.55848751861252388 + 0.55850576103397465 + 0.55852400435180327 + 0.55854224856608548 + 0.55856049367690275 + 0.55857873968433069 + 0.55859698658844936 + 0.55861523438933713 + 0.5586334830870715 + 0.55865173268173063 + 0.55866998317339467 + 0.55868823456213956 + 0.55870648684804636 + 0.55872474003119132 + 0.55874299411165396 + 0.55876124908951175 + 0.55877950496484463 + 0.55879776173772999 + 0.55881601940824754 + 0.55883427797647323 + 0.55885253744248731 + 0.5588707978063695 + 0.55888905906819464 + 0.55890732122804521 + 0.5589255842859987 + 0.55894384824213084 + 0.55896211309652455 + 0.55898037884925456 + 0.55899864550040201 + 0.5590169130500442 + 0.55903518149826015 + 0.55905345084512836 + 0.55907172109072756 + 0.55908999223513633 + 0.55910826427843363 + 0.55912653722069816 + 0.5591448110620072 + 0.5591630858024409 + 0.55918136144207797 + 0.55919963798099592 + 0.55921791541927612 + 0.5592361937569934 + 0.55925447299422903 + 0.55927275313106206 + 0.55929103416756965 + 0.55930931610383083 + 0.55932759893992556 + 0.55934588267593166 + 0.55936416731192884 + 0.55938245284799482 + 0.55940073928420841 + 0.5594190266206498 + 0.55943731485739634 + 0.5594556039945271 + 0.55947389403212222 + 0.5594921849702591 + 0.559510476809018 + 0.55952876954847663 + 0.55954706318871361 + 0.55956535772980931 + 0.55958365317184133 + 0.55960194951488984 + 0.55962024675903244 + 0.55963854490435072 + 0.55965684395091952 + 0.55967514389882056 + 0.55969344474813409 + 0.55971174649893485 + 0.55973004915130609 + 0.55974835270532386 + 0.55976665716106999 + 0.55978496251862209 + 0.55980326877805753 + 0.55982157593945836 + 0.55983988400290052 + 0.55985819296846751 + 0.55987650283623369 + 0.55989481360628124 + 0.55991312527868753 + 0.55993143785353305 + 0.55994975133089708 + 0.55996806571085822 + 0.55998638099349429 + 0.56000469717888723 + 0.56002301426711332 + 0.56004133225825425 + 0.56005965115238754 + 0.56007797094959411 + 0.56009629164995123 + 0.56011461325353951 + 0.56013293576043821 + 0.56015125917072484 + 0.56016958348448131 + 0.56018790870178548 + 0.56020623482271747 + 0.56022456184735414 + 0.56024288977577841 + 0.56026121860806677 + 0.56027954834429983 + 0.56029787898455796 + 0.56031621052891756 + 0.56033454297746077 + 0.56035287633026654 + 0.56037121058741268 + 0.56038954574897992 + 0.56040788181504864 + 0.56042621878569676 + 0.56044455666100346 + 0.56046289544104932 + 0.56048123512591208 + 0.56049957571567399 + 0.56051791721041122 + 0.56053625961020737 + 0.5605546029151387 + 0.56057294712528605 + 0.56059129224072857 + 0.5606096382615442 + 0.5606279851878162 + 0.5606463330196213 + 0.56066468175704143 + 0.56068303140015308 + 0.56070138194903829 + 0.56071973340377501 + 0.56073808576444395 + 0.56075643903112449 + 0.56077479320389589 + 0.56079314828283888 + 0.56081150426803272 + 0.56082986115955669 + 0.56084821895749037 + 0.56086657766191417 + 0.56088493727290789 + 0.56090329779054915 + 0.56092165921492021 + 0.56094002154610034 + 0.56095838478416915 + 0.5609767489292059 + 0.56099511398128998 + 0.5610134799405021 + 0.56103184680692186 + 0.56105021458062854 + 0.56106858326170439 + 0.56108695285022459 + 0.56110532334627428 + 0.56112369474993007 + 0.56114206706127134 + 0.56116044028038037 + 0.56117881440733519 + 0.56119718944221808 + 0.56121556538510575 + 0.56123394223607925 + 0.56125231999522041 + 0.56127069866260637 + 0.56128907823831908 + 0.56130745872243837 + 0.5613258401150435 + 0.56134422241621418 + 0.56136260562603113 + 0.5613809897445754 + 0.56139937477192514 + 0.56141776070815985 + 0.56143614755336191 + 0.56145453530761091 + 0.56147292397098481 + 0.56149131354356618 + 0.56150970402543454 + 0.56152809541666959 + 0.56154648771735083 + 0.56156488092756041 + 0.5615832750473756 + 0.56160167007687845 + 0.56162006601614878 + 0.56163846286526742 + 0.56165686062431408 + 0.56167525929336726 + 0.56169365887250888 + 0.56171205936182045 + 0.56173046076138 + 0.5617488630712687 + 0.56176726629156604 + 0.56178567042235328 + 0.56180407546371003 + 0.56182248141571733 + 0.56184088827845491 + 0.56185929605200402 + 0.56187770473644283 + 0.56189611433185371 + 0.56191452483831661 + 0.56193293625591123 + 0.56195134858471729 + 0.56196976182481717 + 0.5619881759762908 + 0.5620065910392178 + 0.56202500701367808 + 0.56204342389975415 + 0.56206184169752427 + 0.56208026040706993 + 0.56209868002847041 + 0.56211710056180875 + 0.56213552200716321 + 0.56215394436461497 + 0.56217236763424527 + 0.56219079181613385 + 0.56220921691036074 + 0.562227642917007 + 0.56224606983615377 + 0.56226449766788111 + 0.56228292641226885 + 0.56230135606939813 + 0.56231978663935034 + 0.56233821812220519 + 0.56235665051804418 + 0.56237508382694701 + 0.56239351804899507 + 0.56241195318426829 + 0.56243038923284772 + 0.56244882619481362 + 0.56246726407024705 + 0.56248570285922961 + 0.56250414256183956 + 0.56252258317815984 + 0.56254102470827161 + 0.56255946715225347 + 0.56257791051018691 + 0.5625963547821532 + 0.56261479996823371 + 0.5626332460685084 + 0.56265169308305729 + 0.56267014101196311 + 0.56268858985530457 + 0.56270703961316448 + 0.56272549028562269 + 0.56274394187275945 + 0.56276239437465736 + 0.56278084779139514 + 0.56279930212305573 + 0.56281775736971751 + 0.56283621353146507 + 0.56285467060837679 + 0.56287312860053285 + 0.5628915875080176 + 0.56291004733090821 + 0.56292850806928751 + 0.56294696972323721 + 0.56296543229283713 + 0.56298389577816765 + 0.56300236017931005 + 0.56302082549634869 + 0.56303929172935974 + 0.56305775887842724 + 0.56307622694363146 + 0.56309469592505379 + 0.56311316582277471 + 0.56313163663687538 + 0.56315010836743629 + 0.56316858101454159 + 0.56318705457826879 + 0.56320552905870092 + 0.56322400445591803 + 0.56324248077000316 + 0.56326095800103648 + 0.56327943614909703 + 0.5632979152142702 + 0.5633163951966339 + 0.56333487609627075 + 0.56335335791326124 + 0.56337184064768708 + 0.56339032429963098 + 0.56340880886917066 + 0.5634272943563905 + 0.56344578076137086 + 0.56346426808419348 + 0.56348275632493972 + 0.56350124548368874 + 0.56351973556052493 + 0.56353822655552732 + 0.56355671846877753 + 0.56357521130035859 + 0.563593705050351 + 0.56361219971883658 + 0.56363069530589527 + 0.56364919181161044 + 0.56366768923606125 + 0.56368618757933198 + 0.56370468684150166 + 0.56372318702265345 + 0.5637416881228664 + 0.56376019014222511 + 0.56377869308080841 + 0.56379719693869967 + 0.56381570171598072 + 0.56383420741273038 + 0.56385271402903336 + 0.56387122156496883 + 0.56388973002061982 + 0.56390823939606693 + 0.56392674969139323 + 0.56394526090667918 + 0.56396377304200551 + 0.5639822860974566 + 0.5640008000731116 + 0.56401931496905378 + 0.5640378307853624 + 0.56405634752212197 + 0.56407486517941297 + 0.5640933837573161 + 0.56411190325591587 + 0.56413042367529009 + 0.56414894501552348 + 0.56416746727669798 + 0.56418599045889406 + 0.56420451456219245 + 0.56422303958667763 + 0.56424156553242899 + 0.56426009239952846 + 0.56427862018806063 + 0.56429714889810501 + 0.56431567852974318 + 0.56433420908305765 + 0.56435274055813134 + 0.56437127295504375 + 0.56438980627387803 + 0.56440834051471656 + 0.56442687567764094 + 0.56444541176273366 + 0.564463948770075 + 0.56448248669974854 + 0.56450102555183512 + 0.56451956532641645 + 0.56453810602357635 + 0.56455664764339519 + 0.56457519018595514 + 0.56459373365133991 + 0.56461227803962843 + 0.56463082335090597 + 0.56464936958525147 + 0.56466791674275008 + 0.56468646482348128 + 0.56470501382752825 + 0.56472356375497335 + 0.56474211460589996 + 0.56476066638038747 + 0.56477921907851825 + 0.56479777270037568 + 0.56481632724604336 + 0.56483488271560056 + 0.56485343910912966 + 0.56487199642671415 + 0.56489055466843752 + 0.56490911383437947 + 0.56492767392462329 + 0.56494623493925011 + 0.56496479687834333 + 0.56498335974198499 + 0.56500192353025791 + 0.5650204882432438 + 0.56503905388102516 + 0.56505762044368302 + 0.56507618793130199 + 0.56509475634396322 + 0.56511332568174755 + 0.56513189594474011 + 0.56515046713302175 + 0.56516903924667483 + 0.56518761228578152 + 0.56520618625042551 + 0.56522476114068798 + 0.56524333695665108 + 0.56526191369839862 + 0.56528049136601277 + 0.56529906995957457 + 0.56531764947916929 + 0.56533622992487498 + 0.56535481129677834 + 0.56537339359495997 + 0.56539197681950282 + 0.56541056097048881 + 0.56542914604800054 + 0.56544773205212306 + 0.56546631898293487 + 0.565484906840521 + 0.56550349562496371 + 0.56552208533634563 + 0.56554067597474933 + 0.56555926754025698 + 0.56557786003295119 + 0.56559645345291576 + 0.56561504780023175 + 0.56563364307498298 + 0.56565223927725206 + 0.56567083640712135 + 0.56568943446467346 + 0.56570803344998943 + 0.56572663336315598 + 0.56574523420425415 + 0.5657638359733651 + 0.56578243867057276 + 0.56580104229595984 + 0.56581964684960995 + 0.56583825233160301 + 0.56585685874202574 + 0.5658754660809594 + 0.56589407434848504 + 0.56591268354468804 + 0.56593129366964978 + 0.56594990472345386 + 0.5659685167061832 + 0.56598712961791886 + 0.56600574345874621 + 0.56602435822874797 + 0.56604297392800551 + 0.56606159055660399 + 0.56608020811462312 + 0.56609882660214739 + 0.56611744601926195 + 0.56613606636604674 + 0.56615468764258581 + 0.56617330984896319 + 0.56619193298526027 + 0.56621055705156098 + 0.56622918204794803 + 0.56624780797450436 + 0.56626643483131378 + 0.56628506261845912 + 0.56630369133602443 + 0.56632232098408986 + 0.56634095156274067 + 0.56635958307205969 + 0.56637821551213097 + 0.56639684888303621 + 0.56641548318485924 + 0.56643411841768287 + 0.56645275458158995 + 0.56647139167666472 + 0.56649002970298978 + 0.56650866866064942 + 0.56652730854972511 + 0.56654594937030101 + 0.56656459112245994 + 0.56658323380628606 + 0.5666018774218623 + 0.56662052196927137 + 0.56663916744859755 + 0.56665781385992242 + 0.56667646120333293 + 0.56669510947890767 + 0.56671375868673379 + 0.56673240882689147 + 0.56675105989946761 + 0.56676971190454239 + 0.56678836484220163 + 0.56680701871252792 + 0.56682567351560442 + 0.56684432925151407 + 0.56686298592034112 + 0.56688164352216852 + 0.56690030205708042 + 0.56691896152516008 + 0.56693762192649022 + 0.56695628326115532 + 0.56697494552923844 + 0.56699360873082361 + 0.5670122728659942 + 0.56703093793483295 + 0.56704960393742443 + 0.56706827087385148 + 0.56708693874419858 + 0.56710560754854877 + 0.56712427728698644 + 0.5671429479595933 + 0.56716161956645494 + 0.56718029210765331 + 0.56719896558327421 + 0.56721763999339914 + 0.56723631533811258 + 0.56725499161750037 + 0.5672736688316431 + 0.56729234698062503 + 0.56731102606453199 + 0.56732970608344568 + 0.5673483870374495 + 0.56736706892662903 + 0.56738575175106754 + 0.56740443551084796 + 0.56742312020605512 + 0.56744180583677351 + 0.56746049240308472 + 0.56747917990507202 + 0.56749786834282268 + 0.56751655771641851 + 0.56753524802594557 + 0.56755393927148279 + 0.56757263145311887 + 0.56759132457093708 + 0.56761001862501803 + 0.56762871361545009 + 0.56764740954231407 + 0.56766610640569581 + 0.56768480420567713 + 0.56770350294234417 + 0.56772220261577999 + 0.56774090322606818 + 0.56775960477329324 + 0.56777830725754108 + 0.56779701067889221 + 0.56781571503743289 + 0.56783442033324638 + 0.56785312656641718 + 0.56787183373702887 + 0.5678905418451673 + 0.5679092508909146 + 0.5679279608743566 + 0.56794667179557556 + 0.5679653836546561 + 0.56798409645168302 + 0.56800281018674081 + 0.56802152485991175 + 0.56804024047128321 + 0.56805895702093723 + 0.5680776745089573 + 0.56809639293543079 + 0.56811511230043976 + 0.56813383260406769 + 0.56815255384639929 + 0.56817127602752093 + 0.56818999914751445 + 0.56820872320646632 + 0.56822744820445836 + 0.56824617414157685 + 0.56826490101790517 + 0.56828362883352845 + 0.5683023575885312 + 0.56832108728299713 + 0.56833981791700972 + 0.56835854949065512 + 0.56837728200401683 + 0.56839601545717999 + 0.56841474985022911 + 0.56843348518324677 + 0.56845222145631891 + 0.56847095866953068 + 0.56848969682296546 + 0.5685084359167083 + 0.56852717595084401 + 0.56854591692545631 + 0.56856465884063023 + 0.56858340169645039 + 0.56860214549299926 + 0.56862089023036599 + 0.56863963590863131 + 0.5686583825278817 + 0.5686771300881992 + 0.56869587858967185 + 0.56871462803238304 + 0.56873337841641658 + 0.5687521297418574 + 0.56877088200879067 + 0.56878963521730119 + 0.56880838936747424 + 0.56882714445939342 + 0.56884590049314243 + 0.56886465746880899 + 0.56888341538647558 + 0.56890217424622724 + 0.56892093404814892 + 0.56893969479232587 + 0.5689584564788418 + 0.56897721910778465 + 0.5689959826792339 + 0.56901474719328027 + 0.56903351265000324 + 0.56905227904949085 + 0.56907104639182837 + 0.56908981467709929 + 0.56910858390538743 + 0.56912735407678106 + 0.56914612519136221 + 0.56916489724921637 + 0.56918367025042982 + 0.56920244419508526 + 0.56922121908327039 + 0.56923999491506794 + 0.56925877169056438 + 0.56927754940984354 + 0.5692963280729908 + 0.56931510768009264 + 0.56933388823123143 + 0.56935266972649412 + 0.56937145216596574 + 0.56939023554973023 + 0.56940901987787451 + 0.56942780515048208 + 0.56944659136763842 + 0.5694653785294288 + 0.56948416663593859 + 0.56950295568725162 + 0.56952174568345482 + 0.56954053662463322 + 0.5695593285108711 + 0.5695781213422535 + 0.56959691511886723 + 0.56961570984079635 + 0.56963450550812622 + 0.5696533021209409 + 0.56967209967932841 + 0.5696908981833726 + 0.56970969763315793 + 0.56972849802877079 + 0.56974729937029545 + 0.56976610165781838 + 0.56978490489142541 + 0.56980370907119904 + 0.5698225141972274 + 0.56984132026959611 + 0.56986012728838753 + 0.56987893525369038 + 0.56989774416558825 + 0.56991655402416819 + 0.56993536482951312 + 0.56995417658170955 + 0.56997298928084472 + 0.56999180292700102 + 0.57001061752026705 + 0.5700294330607254 + 0.57004824954846423 + 0.57006706698356657 + 0.57008588536611926 + 0.57010470469620911 + 0.57012352497392049 + 0.57014234619933735 + 0.57016116837254671 + 0.57017999149363585 + 0.57019881556268837 + 0.57021764057978896 + 0.57023646654502591 + 0.57025529345848325 + 0.57027412132024546 + 0.57029295013040193 + 0.57031177988903459 + 0.57033061059623158 + 0.57034944225207718 + 0.57036827485665853 + 0.57038710841005968 + 0.57040594291236801 + 0.57042477836366756 + 0.57044361476404404 + 0.57046245211358604 + 0.57048129041237616 + 0.57050012966050323 + 0.57051896985805006 + 0.5705378110051037 + 0.57055665310174986 + 0.57057549614807579 + 0.57059434014416566 + 0.57061318509010672 + 0.57063203098598336 + 0.57065087783188129 + 0.57066972562788898 + 0.57068857437408949 + 0.57070742407056996 + 0.57072627471741622 + 0.57074512631471552 + 0.57076397886255359 + 0.57078283236101335 + 0.57080168681018362 + 0.57082054221014999 + 0.57083939856099974 + 0.57085825586281602 + 0.57087711411568609 + 0.5708959733196971 + 0.57091483347493355 + 0.57093369458148269 + 0.57095255663943034 + 0.57097141964886244 + 0.57099028360986626 + 0.57100914852252493 + 0.57102801438692852 + 0.57104688120316016 + 0.57106574897130857 + 0.57108461769145691 + 0.57110348736369365 + 0.57112235798810362 + 0.57114122956477553 + 0.57116010209379242 + 0.57117897557524178 + 0.57119785000921086 + 0.57121672539578572 + 0.57123560173505217 + 0.57125447902709514 + 0.57127335727200312 + 0.57129223646986205 + 0.57131111662075684 + 0.57132999772477622 + 0.57134887978200333 + 0.57136776279252832 + 0.57138664675643325 + 0.57140553167380959 + 0.57142441754474071 + 0.57144330436931268 + 0.57146219214761274 + 0.57148108087972738 + 0.57149997056574364 + 0.57151886120574646 + 0.57153775279982333 + 0.57155664534806172 + 0.57157553885054624 + 0.57159443330736459 + 0.57161332871860282 + 0.57163222508434841 + 0.57165112240468763 + 0.57167002067970507 + 0.57168891990948978 + 0.57170782009412791 + 0.5717267212337056 + 0.57174562332830914 + 0.57176452637802599 + 0.57178343038294233 + 0.57180233534314451 + 0.57182124125872003 + 0.57184014812975503 + 0.57185905595633602 + 0.57187796473855024 + 0.57189687447648552 + 0.57191578517022679 + 0.57193469681986009 + 0.5719536094254748 + 0.5719725229871554 + 0.57199143750498971 + 0.57201035297906566 + 0.57202926940946786 + 0.57204818679628522 + 0.57206710513960324 + 0.57208602443950907 + 0.57210494469608941 + 0.57212386590943032 + 0.57214278807962105 + 0.57216171120674653 + 0.57218063529089447 + 0.57219956033215258 + 0.57221848633060601 + 0.5722374132863437 + 0.57225634119945079 + 0.57227527007001511 + 0.5722941998981228 + 0.5723131306838618 + 0.57233206242731993 + 0.57235099512858378 + 0.5723699287877394 + 0.57238886340487349 + 0.57240779898007377 + 0.57242673551342815 + 0.57244567300502425 + 0.57246461145494754 + 0.57248355086328417 + 0.57250249123012353 + 0.57252143255555343 + 0.57254037483965903 + 0.5725593180825268 + 0.57257826228424613 + 0.57259720744490328 + 0.57261615356458495 + 0.57263510064338041 + 0.57265404868137493 + 0.57267299767865487 + 0.57269194763531095 + 0.57271089855142565 + 0.57272985042709113 + 0.57274880326239253 + 0.57276775705741634 + 0.57278671181225216 + 0.57280566752698348 + 0.57282462420170133 + 0.57284358183649364 + 0.57286254043144413 + 0.5728814999866424 + 0.57290046050217502 + 0.57291942197812995 + 0.57293838441459521 + 0.57295734781165764 + 0.57297631216940359 + 0.57299527748792145 + 0.57301424376730037 + 0.57303321100762594 + 0.5730521792089861 + 0.57307114837146755 + 0.57309011849515834 + 0.57310908958014672 + 0.57312806162652052 + 0.57314703463436678 + 0.57316600860377231 + 0.57318498353482472 + 0.5732039594276126 + 0.57322293628222276 + 0.57324191409874437 + 0.57326089287726301 + 0.57327987261786695 + 0.57329885332064423 + 0.57331783498568323 + 0.57333681761307054 + 0.57335580120289564 + 0.57337478575524148 + 0.57339377127020186 + 0.57341275774786182 + 0.57343174518830864 + 0.57345073359163035 + 0.57346972295791532 + 0.57348871328725015 + 0.57350770457972478 + 0.57352669683542579 + 0.57354569005443912 + 0.5735646842368568 + 0.57358367938276322 + 0.57360267549224775 + 0.57362167256539776 + 0.57364067060230128 + 0.57365966960304648 + 0.57367866956772073 + 0.5736976704964134 + 0.57371667238921153 + 0.57373567524620217 + 0.57375467906747368 + 0.57377368385311567 + 0.57379268960321383 + 0.57381169631785789 + 0.57383070399713487 + 0.57384971264113471 + 0.57386872224994134 + 0.57388773282364769 + 0.57390674436233902 + 0.57392575686610403 + 0.573944770335031 + 0.57396378476920717 + 0.57398280016872227 + 0.57400181653366322 + 0.57402083386411873 + 0.57403985216017717 + 0.57405887142192547 + 0.57407789164945255 + 0.57409691284284792 + 0.57411593500219715 + 0.57413495812759197 + 0.57415398221911662 + 0.5741730072768636 + 0.57419203330091728 + 0.57421106029136781 + 0.57423008824830357 + 0.57424911717181182 + 0.57426814706198248 + 0.57428717791890405 + 0.57430620974266378 + 0.57432524253334882 + 0.57434427629104912 + 0.57436331101585358 + 0.57438234670785027 + 0.57440138336712687 + 0.57442042099377189 + 0.5744394595878739 + 0.57445849914952152 + 0.57447753967880488 + 0.57449658117580826 + 0.57451562364062481 + 0.57453466707334011 + 0.57455371147404299 + 0.57457275684282361 + 0.57459180317976766 + 0.57461085048496818 + 0.57462989875850956 + 0.57464894800048205 + 0.57466799821097292 + 0.57468704939007365 + 0.57470610153787027 + 0.57472515465445284 + 0.57474420873990872 + 0.57476326379432685 + 0.57478231981779848 + 0.57480137681040833 + 0.57482043477224798 + 0.57483949370340492 + 0.57485855360396654 + 0.57487761447402552 + 0.57489667631366692 + 0.57491573912298077 + 0.57493480290205723 + 0.57495386765098233 + 0.57497293336984645 + 0.57499200005873841 + 0.5750110677177469 + 0.57503013634696098 + 0.57504920594646947 + 0.57506827651636117 + 0.57508734805672501 + 0.57510642056764871 + 0.57512549404922353 + 0.57514456850153595 + 0.57516364392467756 + 0.57518272031873441 + 0.57520179768379698 + 0.57522087601995409 + 0.5752399553272961 + 0.5752590356059093 + 0.57527811685588393 + 0.57529719907731036 + 0.57531628227027487 + 0.57533536643486916 + 0.5753544515711807 + 0.57537353767930155 + 0.57539262475931507 + 0.57541171281131576 + 0.57543080183538975 + 0.57544989183162631 + 0.57546898280011582 + 0.57548807474094721 + 0.57550716765421106 + 0.57552626153999231 + 0.575545356398384 + 0.57556445222947394 + 0.57558354903335118 + 0.5756026468101062 + 0.5756217455598267 + 0.57564084528260329 + 0.57565994597852366 + 0.57567904764767686 + 0.57569815029015481 + 0.57571725390604522 + 0.57573635849543736 + 0.57575546405842171 + 0.57577457059508619 + 0.57579367810551974 + 0.57581278658981294 + 0.57583189604805518 + 0.57585100648033549 + 0.57587011788674314 + 0.5758892302673686 + 0.57590834362229992 + 0.57592745795162748 + 0.57594657325544074 + 0.57596568953382743 + 0.57598480678688091 + 0.57600392501468645 + 0.57602304421733574 + 0.57604216439491851 + 0.57606128554752367 + 0.57608040767524071 + 0.57609953077816034 + 0.57611865485637026 + 0.5761377799099614 + 0.57615690593902291 + 0.57617603294364417 + 0.57619516092391598 + 0.57621428987992607 + 0.5762334198117669 + 0.57625255071952464 + 0.57627168260329176 + 0.57629081546315764 + 0.57630994929921142 + 0.57632908411154271 + 0.57634821990024077 + 0.57636735666539629 + 0.57638649440709899 + 0.57640563312543935 + 0.57642477282050431 + 0.57644391349238722 + 0.57646305514117635 + 0.57648219776696097 + 0.576501341369832 + 0.57652048594987748 + 0.57653963150718979 + 0.57655877804185829 + 0.57657792555397114 + 0.57659707404361904 + 0.57661622351089303 + 0.57663537395588271 + 0.57665452537867745 + 0.57667367777936684 + 0.57669283115804182 + 0.57671198551479186 + 0.576731140849708 + 0.57675029716287829 + 0.57676945445439376 + 0.57678861272434534 + 0.57680777197282129 + 0.57682693219991388 + 0.57684609340571269 + 0.5768652555903061 + 0.57688441875378493 + 0.57690358289624166 + 0.57692274801776311 + 0.57694191411844031 + 0.57696108119836431 + 0.57698024925762625 + 0.57699941829631418 + 0.57701858831451913 + 0.57703775931233114 + 0.57705693128984092 + 0.57707610424713829 + 0.57709527818431439 + 0.57711445310145881 + 0.57713362899866139 + 0.57715280587601314 + 0.57717198373360379 + 0.57719116257152459 + 0.57721034238986502 + 0.57722952318871634 + 0.57724870496816849 + 0.57726788772831117 + 0.57728707146923397 + 0.57730625619103093 + 0.5773254418937892 + 0.57734462857760116 + 0.57736381624255528 + 0.57738300488874428 + 0.57740219451625641 + 0.57742138512518304 + 0.57744057671561533 + 0.57745976928764442 + 0.57747896284135747 + 0.57749815737684862 + 0.57751735289420758 + 0.57753654939352428 + 0.57755574687488864 + 0.57757494533839315 + 0.57759414478412663 + 0.57761334521218011 + 0.5776325466226464 + 0.57765174901561278 + 0.57767095239117161 + 0.57769015674941449 + 0.57770936209042989 + 0.57772856841431053 + 0.57774777572114644 + 0.57776698401102755 + 0.57778619328404512 + 0.5778054035402922 + 0.57782461477985569 + 0.57784382700282722 + 0.57786304020930079 + 0.57788225439936369 + 0.5779014695731074 + 0.57792068573062472 + 0.57793990287200425 + 0.57795912099733882 + 0.57797834010671711 + 0.57799756020023185 + 0.57801678127797329 + 0.57803600334003158 + 0.57805522638649931 + 0.5780744504174653 + 0.57809367543302392 + 0.57811290143326244 + 0.57813212841827388 + 0.57815135638814807 + 0.57817058534297672 + 0.57818981528285285 + 0.57820904620786362 + 0.57822827811810196 + 0.57824751101365968 + 0.57826674489462537 + 0.57828597976109475 + 0.57830521561315407 + 0.57832445245089747 + 0.57834369027441523 + 0.57836292908379749 + 0.57838216887913718 + 0.57840140966052345 + 0.57842065142805055 + 0.57843989418180586 + 0.57845913792188397 + 0.57847838264837348 + 0.57849762836136776 + 0.57851687506095684 + 0.57853612274723243 + 0.57855537142028501 + 0.57857462108020752 + 0.57859387172708876 + 0.57861312336102344 + 0.57863237598210038 + 0.57865162959041139 + 0.57867088418604806 + 0.57869013976910222 + 0.57870939633966423 + 0.57872865389782713 + 0.57874791244368007 + 0.57876717197731598 + 0.57878643249882689 + 0.57880569400830306 + 0.57882495650583632 + 0.57884421999151836 + 0.57886348446543978 + 0.57888274992769362 + 0.57890201637837047 + 0.57892128381756347 + 0.57894055224536023 + 0.57895982166185567 + 0.57897909206714115 + 0.57899836346130751 + 0.57901763584444654 + 0.57903690921664874 + 0.57905618357800881 + 0.57907545892861434 + 0.57909473526856148 + 0.57911401259793804 + 0.5791332909168373 + 0.57915257022535116 + 0.57917185052357012 + 0.57919113181158888 + 0.57921041408949536 + 0.57922969735738428 + 0.5792489816153461 + 0.57926826686347144 + 0.5792875531018552 + 0.57930684033058644 + 0.57932612854975862 + 0.57934541775946236 + 0.579364707959791 + 0.57938399915083527 + 0.57940329133268709 + 0.5794225845054386 + 0.57944187866918184 + 0.57946117382400875 + 0.57948046997001013 + 0.57949976710727946 + 0.57951906523590868 + 0.57953836435598849 + 0.57955766446761259 + 0.57957696557087146 + 0.57959626766585881 + 0.57961557075266379 + 0.57963487483138143 + 0.57965417990210233 + 0.57967348596492019 + 0.57969279301992427 + 0.57971210106720827 + 0.57973141010686413 + 0.57975072013898421 + 0.57977003116366199 + 0.57978934318098696 + 0.57980865619105271 + 0.57982797019394994 + 0.57984728518977369 + 0.57986660117861333 + 0.57988591816056267 + 0.57990523613571399 + 0.57992455510415919 + 0.57994387506599088 + 0.57996319602130109 + 0.57998251797018086 + 0.58000184091272533 + 0.58002116484902366 + 0.58004048977916978 + 0.58005981570325738 + 0.58007914262137728 + 0.58009847053362051 + 0.58011779944008224 + 0.58013712934085315 + 0.58015646023602585 + 0.58017579212569403 + 0.58019512500994719 + 0.58021445888888179 + 0.58023379376258633 + 0.58025312963115705 + 0.58027246649468378 + 0.58029180435325878 + 0.5803111432069773 + 0.58033048305593038 + 0.58034982390020906 + 0.58036916573990849 + 0.58038850857511981 + 0.58040785240593529 + 0.58042719723244773 + 0.58044654305475207 + 0.58046588987293801 + 0.58048523768709948 + 0.58050458649732772 + 0.58052393630371779 + 0.58054328710636105 + 0.58056263890534976 + 0.58058199170077796 + 0.58060134549273801 + 0.5806207002813214 + 0.58064005606662183 + 0.58065941284873324 + 0.58067877062774542 + 0.58069812940375531 + 0.5807174891768524 + 0.58073684994712949 + 0.58075621171468184 + 0.58077557447959927 + 0.58079493824197725 + 0.58081430300190851 + 0.58083366875948539 + 0.58085303551479928 + 0.58087240326794554 + 0.58089177201901565 + 0.58091114176810332 + 0.58093051251530159 + 0.58094988426070138 + 0.58096925700439839 + 0.58098863074648521 + 0.58100800548705323 + 0.58102738122619646 + 0.58104675796400906 + 0.58106613570058241 + 0.58108551443600909 + 0.58110489417038469 + 0.5811242749038007 + 0.58114365663635115 + 0.5811630393681273 + 0.58118242309922352 + 0.58120180782973385 + 0.58122119355975121 + 0.58124058028936676 + 0.58125996801867641 + 0.58127935674776987 + 0.5812987464767444 + 0.58131813720569125 + 0.58133752893470492 + 0.58135692166387642 + 0.58137631539330181 + 0.5813957101230709 + 0.58141510585327949 + 0.58143450258402185 + 0.58145390031538924 + 0.5814732990474748 + 0.5814926987803728 + 0.58151209951417748 + 0.58153150124898179 + 0.58155090398487863 + 0.58157030772196106 + 0.5815897124603232 + 0.58160911820005812 + 0.58162852494125883 + 0.58164793268402082 + 0.58166734142843601 + 0.58168675117459867 + 0.58170616192260027 + 0.58172557367253686 + 0.58174498642450112 + 0.58176440017858622 + 0.58178381493488662 + 0.58180323069349527 + 0.58182264745450674 + 0.58184206521801252 + 0.5818614839841072 + 0.58188090375288648 + 0.58190032452444074 + 0.58191974629886589 + 0.58193916907625631 + 0.5819585928567037 + 0.58197801764030144 + 0.5819974434271451 + 0.58201687021732784 + 0.58203629801094281 + 0.58205572680808471 + 0.58207515660884646 + 0.58209458741332154 + 0.58211401922160688 + 0.58213345203379174 + 0.58215288584997205 + 0.58217232067024371 + 0.58219175649469856 + 0.58221119332342974 + 0.58223063115653206 + 0.58225006999409989 + 0.58226950983622527 + 0.58228895068300546 + 0.58230839253453237 + 0.58232783539089927 + 0.58234727925220209 + 0.58236672411853296 + 0.58238616998998771 + 0.58240561686665826 + 0.58242506474864086 + 0.58244451363602723 + 0.58246396352891505 + 0.58248341442739326 + 0.58250286633156079 + 0.58252231924150977 + 0.58254177315733335 + 0.58256122807912769 + 0.58258068400698482 + 0.58260014094100077 + 0.58261959888126924 + 0.58263905782788317 + 0.58265851778093913 + 0.58267797874053029 + 0.58269744070675022 + 0.5827169036796922 + 0.5827363676594538 + 0.58275583264612585 + 0.58277529863980571 + 0.58279476564058585 + 0.58281423364856055 + 0.58283370266382517 + 0.58285317268647308 + 0.58287264371659897 + 0.58289211575429789 + 0.58291158879966332 + 0.58293106285279006 + 0.58295053791377305 + 0.58297001398270454 + 0.58298949105968223 + 0.58300896914479805 + 0.58302844823814859 + 0.58304792833982599 + 0.58306740944992652 + 0.58308689156854498 + 0.58310637469577387 + 0.58312585883171086 + 0.58314534397644668 + 0.5831648301300778 + 0.58318431729270059 + 0.58320380546440731 + 0.58322329464529288 + 0.58324278483545267 + 0.58326227603497982 + 0.5832817682439726 + 0.5833012614625217 + 0.58332075569072495 + 0.58334025092867325 + 0.58335974717646455 + 0.58337924443419398 + 0.58339874270195369 + 0.58341824197984038 + 0.58343774226794753 + 0.58345724356637052 + 0.58347674587520437 + 0.58349624919454557 + 0.58351575352448504 + 0.58353525886512103 + 0.58355476521654692 + 0.58357427257885686 + 0.58359378095214853 + 0.58361329033651443 + 0.58363280073204982 + 0.58365231213884983 + 0.58367182455700972 + 0.58369133798662487 + 0.58371085242778875 + 0.58373036788059685 + 0.58374988434514585 + 0.58376940182152948 + 0.58378892030984308 + 0.5838084398101806 + 0.58382796032263851 + 0.58384748184731095 + 0.58386700438429451 + 0.58388652793368157 + 0.58390605249557048 + 0.58392557807005518 + 0.58394510465722926 + 0.58396463225718986 + 0.5839841608700308 + 0.58400369049584866 + 0.58402322113473748 + 0.58404275278679296 + 0.58406228545211014 + 0.58408181913078594 + 0.58410135382291295 + 0.58412088952858787 + 0.58414042624790485 + 0.58415996398096204 + 0.5841795027278508 + 0.58419904248867072 + 0.58421858326351295 + 0.58423812505247719 + 0.58425766785565481 + 0.5842772116731425 + 0.58429675650503887 + 0.58431630235143484 + 0.58433584921242754 + 0.58435539708811235 + 0.58437494597858497 + 0.58439449588394221 + 0.58441404680427678 + 0.58443359873968714 + 0.58445315169026579 + 0.58447270565610987 + 0.58449226063731508 + 0.58451181663397678 + 0.58453137364619068 + 0.58455093167405225 + 0.58457049071765865 + 0.58459005077710113 + 0.58460961185247962 + 0.58462917394388825 + 0.58464873705142439 + 0.58466830117518043 + 0.58468786631525493 + 0.58470743247174095 + 0.58472699964473673 + 0.58474656783433687 + 0.58476613704063818 + 0.58478570726373491 + 0.58480527850372299 + 0.58482485076069934 + 0.58484442403475845 + 0.58486399832599867 + 0.58488357363451315 + 0.58490314996039749 + 0.58492272730375017 + 0.58494230566466565 + 0.58496188504323976 + 0.58498146543956819 + 0.58500104685374676 + 0.58502062928587262 + 0.58504021273604034 + 0.58505979720434687 + 0.58507938269088966 + 0.58509896919576176 + 0.58511855671905877 + 0.58513814526088082 + 0.58515773482131972 + 0.58517732540047396 + 0.58519691699843945 + 0.5852165096153108 + 0.58523610325118647 + 0.58525569790615983 + 0.58527529358032937 + 0.58529489027378967 + 0.5853144879866381 + 0.58533408671897047 + 0.58535368647088282 + 0.58537328724247106 + 0.58539288903383135 + 0.58541249184506061 + 0.58543209567625532 + 0.58545170052750961 + 0.58547130639892397 + 0.58549091329059 + 0.58551052120260672 + 0.58553013013506994 + 0.58554974008807603 + 0.58556935106172192 + 0.58558896305610109 + 0.585608576071314 + 0.58562819010745493 + 0.58564780516462034 + 0.58566742124290727 + 0.58568703834241076 + 0.5857066564632295 + 0.58572627560545842 + 0.58574589576919323 + 0.58576551695453316 + 0.58578513916157304 + 0.58580476239040868 + 0.58582438664113778 + 0.58584401191385649 + 0.5858636382086625 + 0.58588326552565029 + 0.58590289386491767 + 0.58592252322656058 + 0.58594215361067703 + 0.58596178501736285 + 0.58598141744671439 + 0.58600105089882915 + 0.58602068537380225 + 0.58604032087173374 + 0.58605995739271599 + 0.58607959493684803 + 0.58609923350422732 + 0.5861188730949487 + 0.58613851370911152 + 0.58615815534680915 + 0.58617779800814207 + 0.58619744169320365 + 0.58621708640209325 + 0.58623673213490701 + 0.58625637889174287 + 0.58627602667269407 + 0.58629567547786143 + 0.5863153253073411 + 0.58633497616122821 + 0.58635462803962035 + 0.5863742809426169 + 0.58639393487031144 + 0.58641358982280289 + 0.58643324580018663 + 0.58645290280256157 + 0.58647256083002441 + 0.58649221988267131 + 0.58651187996060028 + 0.58653154106390781 + 0.58655120319269161 + 0.5865708663470468 + 0.58659053052707277 + 0.58661019573286588 + 0.58662986196452405 + 0.58664952922214242 + 0.58666919750582014 + 0.58668886681565391 + 0.58670853715174032 + 0.58672820851417706 + 0.58674788090306085 + 0.58676755431849104 + 0.58678722876056122 + 0.58680690422937098 + 0.58682658072501959 + 0.58684625824759951 + 0.58686593679721155 + 0.58688561637395342 + 0.58690529697791927 + 0.58692497860920989 + 0.58694466126792044 + 0.58696434495415017 + 0.58698402966799323 + 0.58700371540955187 + 0.58702340217891957 + 0.58704308997619492 + 0.58706277880147706 + 0.58708246865486002 + 0.58710215953644462 + 0.58712185144632756 + 0.58714154438460575 + 0.58716123835137568 + 0.58718093334673693 + 0.58720062937078643 + 0.58722032642362199 + 0.58724002450534085 + 0.58725972361603929 + 0.5872794237558171 + 0.58729912492477243 + 0.58731882712300076 + 0.58733853035060035 + 0.58735823460766912 + 0.58737793989430542 + 0.58739764621060631 + 0.5874173535566698 + 0.58743706193259282 + 0.58745677133847629 + 0.58747648177441303 + 0.58749619324050406 + 0.5875159057368462 + 0.58753561926353781 + 0.58755533382067715 + 0.58757504940836125 + 0.58759476602668825 + 0.58761448367575642 + 0.58763420235566299 + 0.58765392206650469 + 0.58767364280838275 + 0.5876933645813941 + 0.58771308738563288 + 0.58773281122120302 + 0.58775253608819755 + 0.58777226198671728 + 0.58779198891685958 + 0.58781171687872258 + 0.58783144587240332 + 0.58785117589800207 + 0.58787090695561373 + 0.58789063904534011 + 0.58791037216727682 + 0.58793010632152198 + 0.58794984150817586 + 0.58796957772733394 + 0.58798931497909601 + 0.58800905326355934 + 0.58802879258082241 + 0.58804853293098502 + 0.5880682743141431 + 0.58808801673039646 + 0.58810776017984212 + 0.58812750466257879 + 0.58814725017870506 + 0.58816699672832085 + 0.58818674431152196 + 0.58820649292840677 + 0.58822624257907419 + 0.58824599326362392 + 0.58826574498215345 + 0.5882854977347598 + 0.58830525152154312 + 0.58832500634260199 + 0.58834476219803367 + 0.58836451908793819 + 0.58838427701241147 + 0.58840403597155488 + 0.58842379596546435 + 0.58844355699424 + 0.58846331905798066 + 0.58848308215678335 + 0.58850284629074834 + 0.58852261145997153 + 0.58854237766455586 + 0.58856214490459602 + 0.58858191318019193 + 0.58860168249144373 + 0.58862145283844769 + 0.58864122422130361 + 0.58866099664011062 + 0.58868077009496589 + 0.58870054458596965 + 0.58872032011322084 + 0.5887400966768167 + 0.58875987427685628 + 0.58877965291343959 + 0.58879943258666423 + 0.58881921329663034 + 0.58883899504343407 + 0.58885877782717844 + 0.58887856164795827 + 0.58889834650587514 + 0.58891813240102653 + 0.58893791933351136 + 0.58895770730342867 + 0.58897749631087848 + 0.58899728635595872 + 0.58901707743876808 + 0.58903686955940548 + 0.58905666271797152 + 0.58907645691456356 + 0.58909625214928063 + 0.58911604842222176 + 0.58913584573348876 + 0.58915564408317778 + 0.5891754434713864 + 0.58919524389821787 + 0.58921504536376856 + 0.58923484786813873 + 0.58925465141142763 + 0.58927445599373263 + 0.58929426161515575 + 0.58931406827579336 + 0.58933387597574582 + 0.58935368471511373 + 0.58937349449399479 + 0.58939330531248635 + 0.58941311717069222 + 0.58943293006870856 + 0.58945274400663583 + 0.58947255898457185 + 0.58949237500261853 + 0.58951219206087235 + 0.58953201015943502 + 0.58955182929840466 + 0.58957164947788021 + 0.58959147069796247 + 0.58961129295875048 + 0.58963111626034204 + 0.58965094060283796 + 0.58967076598633861 + 0.58969059241094224 + 0.58971041987674766 + 0.58973024838385724 + 0.58975007793236733 + 0.58976990852237854 + 0.58978974015399177 + 0.58980957282730317 + 0.58982940654241656 + 0.5898492412994284 + 0.58986907709844072 + 0.58988891393955023 + 0.58990875182286029 + 0.58992859074846749 + 0.58994843071647118 + 0.58996827172697353 + 0.58998811378007399 + 0.59000795687587049 + 0.59002780101446384 + 0.59004764619595351 + 0.59006749242043866 + 0.59008733968802052 + 0.59010718799879813 + 0.59012703735287264 + 0.5901468877503403 + 0.5901667391913038 + 0.59018659167586252 + 0.59020644520411703 + 0.59022629977616581 + 0.59024615539210956 + 0.59026601205204909 + 0.59028586975608266 + 0.59030572850430962 + 0.59032558829683124 + 0.59034544913374953 + 0.59036531101515999 + 0.5903851739411663 + 0.5904050379118666 + 0.59042490292736205 + 0.590444768987752 + 0.5904646360931376 + 0.59048450424361709 + 0.59050437343929119 + 0.59052424368026124 + 0.59054411496662529 + 0.59056398729848592 + 0.5905838606759426 + 0.59060373509909359 + 0.59062361056804158 + 0.59064348708288461 + 0.59066336464372537 + 0.5906832432506619 + 0.59070312290379534 + 0.59072300360322705 + 0.59074288534905361 + 0.59076276814138073 + 0.59078265198030344 + 0.59080253686592621 + 0.59082242279834851 + 0.59084230977766727 + 0.59086219780398797 + 0.59088208687740762 + 0.59090197699802727 + 0.59092186816594816 + 0.59094176038127022 + 0.59096165364409448 + 0.59098154795451951 + 0.59100144331264781 + 0.5910213397185794 + 0.59104123717241541 + 0.59106113567425433 + 0.59108103522419875 + 0.59110093582234735 + 0.59112083746880406 + 0.59114074016366591 + 0.59116064390703438 + 0.5911805486990106 + 0.59120045453969616 + 0.59122036142919077 + 0.59124026936759444 + 0.59126017835500855 + 0.59128008839153434 + 0.59129999947727185 + 0.59131991161232111 + 0.59133982479678482 + 0.59135973903076167 + 0.59137965431435446 + 0.59139957064766313 + 0.5914194880307877 + 0.59143940646382964 + 0.59145932594688899 + 0.59147924648006855 + 0.59149916806346847 + 0.59151909069718889 + 0.5915390143813295 + 0.591558939115995 + 0.59157886490128253 + 0.59159879173729502 + 0.59161871962413248 + 0.59163864856189807 + 0.59165857855069026 + 0.59167850959061064 + 0.59169844168176089 + 0.59171837482424261 + 0.59173830901815572 + 0.59175824426360057 + 0.59177818056068154 + 0.59179811790949444 + 0.59181805631014528 + 0.59183799576273433 + 0.59185793626736016 + 0.59187787782412604 + 0.59189782043313355 + 0.59191776409448138 + 0.59193770880827412 + 0.59195765457461058 + 0.59197760139359401 + 0.59199754926532311 + 0.59201749818989946 + 0.59203744816742643 + 0.59205739919800437 + 0.59207735128173467 + 0.59209730441871944 + 0.59211725860905873 + 0.59213721385285301 + 0.59215717015020541 + 0.59217712750121776 + 0.59219708590599029 + 0.59221704536462505 + 0.59223700587722206 + 0.59225696744388623 + 0.59227693006471505 + 0.59229689373981176 + 0.59231685846927973 + 0.59233682425321621 + 0.59235679109172623 + 0.59237675898491016 + 0.59239672793287113 + 0.59241669793570839 + 0.59243666899352376 + 0.59245664110642049 + 0.59247661427449905 + 0.59249658849786158 + 0.59251656377660977 + 0.59253654011084556 + 0.59255651750066962 + 0.59257649594618378 + 0.5925964754474915 + 0.59261645600469326 + 0.59263643761788976 + 0.59265642028718424 + 0.59267640401267885 + 0.59269638879447395 + 0.59271637463267324 + 0.59273636152737719 + 0.59275634947868783 + 0.59277633848670719 + 0.59279632855153741 + 0.59281631967327897 + 0.592836311852037 + 0.59285630508790921 + 0.59287629938100184 + 0.59289629473141436 + 0.59291629113924882 + 0.59293628860460712 + 0.59295628712759296 + 0.59297628670830582 + 0.59299628734685039 + 0.59301628904332759 + 0.59303629179783801 + 0.59305629561048689 + 0.59307630048137328 + 0.59309630641060096 + 0.59311631339827209 + 0.59313632144448891 + 0.59315633054935224 + 0.59317634071296566 + 0.5931963519354313 + 0.5932163642168502 + 0.59323637755732583 + 0.59325639195696211 + 0.59327640741585685 + 0.5932964239341153 + 0.59331644151183971 + 0.59333646014913077 + 0.59335647984609396 + 0.59337650060282854 + 0.5933965224194383 + 0.59341654529602561 + 0.59343656923269117 + 0.59345659422954056 + 0.59347662028667447 + 0.59349664740419394 + 0.59351667558220411 + 0.59353670482080612 + 0.5935567351201021 + 0.59357676648019597 + 0.59359679890118899 + 0.59361683238318319 + 0.5936368669262827 + 0.59365690253058989 + 0.59367693919620568 + 0.59369697692323553 + 0.59371701571177904 + 0.59373705556194001 + 0.59375709647382247 + 0.59377713844752744 + 0.59379718148315752 + 0.5938172255808164 + 0.59383727074060688 + 0.59385731696263144 + 0.593877364246991 + 0.59389741259379125 + 0.59391746200313456 + 0.59393751247512205 + 0.59395756400985655 + 0.59397761660744319 + 0.593997670267982 + 0.59401772499157668 + 0.59403778077833158 + 0.59405783762834929 + 0.59407789554173085 + 0.59409795451858038 + 0.5941180145590006 + 0.59413807566309573 + 0.59415813783096671 + 0.59417820106271935 + 0.59419826535845321 + 0.59421833071827412 + 0.59423839714228321 + 0.59425846463058318 + 0.59427853318328117 + 0.59429860280047409 + 0.59431867348227041 + 0.59433874522876995 + 0.59435881804007729 + 0.594378891916296 + 0.59439896685752802 + 0.59441904286387726 + 0.59443911993544651 + 0.59445919807234027 + 0.59447927727465955 + 0.59449935754250893 + 0.59451943887599235 + 0.5945395212752117 + 0.59455960474027081 + 0.59457968927127269 + 0.59459977486832027 + 0.59461986153151924 + 0.59463994926097119 + 0.59466003805677892 + 0.59468012791904679 + 0.59470021884787905 + 0.59472031084337718 + 0.59474040390564586 + 0.5947604980347877 + 0.59478059323090726 + 0.59480068949410592 + 0.59482078682448969 + 0.59484088522216294 + 0.59486098468722581 + 0.594881085219784 + 0.59490118681993931 + 0.59492128948779754 + 0.59494139322346173 + 0.59496149802703335 + 0.59498160389861998 + 0.59500171083832165 + 0.59502181884624428 + 0.59504192792248967 + 0.59506203806716362 + 0.59508214928036773 + 0.59510226156220825 + 0.59512237491278652 + 0.59514248933220737 + 0.59516260482057526 + 0.59518272137799189 + 0.59520283900456328 + 0.59522295770039257 + 0.5952430774655828 + 0.59526319830023899 + 0.59528332020446528 + 0.59530344317836359 + 0.59532356722203883 + 0.59534369233559525 + 0.59536381851913778 + 0.5953839457727681 + 0.5954040740965908 + 0.59542420349071223 + 0.59544433395523411 + 0.59546446549026089 + 0.59548459809589627 + 0.59550473177224472 + 0.59552486651941106 + 0.59554500233749719 + 0.59556513922660903 + 0.59558527718685172 + 0.59560541621832697 + 0.59562555632113956 + 0.5956456974953942 + 0.59566583974119724 + 0.59568598305864773 + 0.59570612744785478 + 0.59572627290891889 + 0.59574641944194784 + 0.59576656704704345 + 0.59578671572431063 + 0.59580686547385286 + 0.59582701629577639 + 0.59584716819018324 + 0.59586732115718133 + 0.59588747519687091 + 0.59590763030935867 + 0.59592778649474798 + 0.59594794375314342 + 0.59596810208465056 + 0.59598826148937245 + 0.59600842196741566 + 0.59602858351888222 + 0.59604874614387859 + 0.59606890984250671 + 0.59608907461487326 + 0.59610924046108305 + 0.59612940738123821 + 0.59614957537544688 + 0.59616974444381099 + 0.59618991458643433 + 0.59621008580342594 + 0.59623025809488528 + 0.59625043146092049 + 0.59627060590163483 + 0.59629078141713232 + 0.59631095800751932 + 0.59633113567290108 + 0.59635131441337952 + 0.59637149422906144 + 0.59639167512005187 + 0.59641185708645461 + 0.59643204012837481 + 0.59645222424591615 + 0.59647240943918511 + 0.59649259570828705 + 0.59651278305332422 + 0.59653297147440476 + 0.59655316097163091 + 0.59657335154510782 + 0.59659354319494373 + 0.59661373592123812 + 0.59663392972410056 + 0.59665412460363465 + 0.59667432055994452 + 0.59669451759313663 + 0.59671471570331502 + 0.59673491489058494 + 0.59675511515505142 + 0.5967753164968187 + 0.59679551891599347 + 0.59681572241267944 + 0.59683592698698351 + 0.59685613263900961 + 0.59687633936886297 + 0.59689654717664908 + 0.59691675606247319 + 0.59693696602644097 + 0.59695717706865459 + 0.59697738918922394 + 0.59699760238825161 + 0.59701781666584419 + 0.59703803202210448 + 0.59705824845713951 + 0.59707846597105585 + 0.59709868456395609 + 0.59711890423594882 + 0.5971391249871365 + 0.59715934681762606 + 0.59717956972752162 + 0.59719979371693144 + 0.59722001878595821 + 0.5972402449347074 + 0.59726047216328626 + 0.59728070047180004 + 0.59730092986035432 + 0.59732116032905203 + 0.59734139187800128 + 0.59736162450730779 + 0.5973818582170759 + 0.59740209300741098 + 0.59742232887842017 + 0.59744256583020761 + 0.59746280386288053 + 0.59748304297654276 + 0.59750328317130175 + 0.59752352444726309 + 0.59754376680453081 + 0.59756401024321226 + 0.59758425476341148 + 0.59760450036523594 + 0.59762474704879087 + 0.59764499481418243 + 0.59766524366151463 + 0.59768549359089618 + 0.59770574460243131 + 0.5977259966962245 + 0.59774624987238423 + 0.59776650413101629 + 0.59778675947222504 + 0.59780701589611496 + 0.59782727340279596 + 0.59784753199237262 + 0.59786779166494908 + 0.59788805242063281 + 0.59790831425953095 + 0.59792857718174808 + 0.59794884118738989 + 0.59796910627656374 + 0.59798937244937256 + 0.59800963970592669 + 0.5980299080463306 + 0.59805017747069 + 0.59807044797911091 + 0.59809071957170079 + 0.59811099224856545 + 0.59813126600980793 + 0.59815154085553868 + 0.59817181678586195 + 0.59819209380088534 + 0.59821237190071341 + 0.59823265108545354 + 0.59825293135521163 + 0.59827321271009382 + 0.59829349515020769 + 0.59831377867565605 + 0.59833406328654937 + 0.59835434898299389 + 0.59837463576509264 + 0.59839492363295321 + 0.5984152125866844 + 0.59843550262639233 + 0.59845579375218028 + 0.59847608596415736 + 0.59849637926242805 + 0.59851667364710137 + 0.59853696911828358 + 0.5985572656760777 + 0.59857756332059453 + 0.59859786205193999 + 0.59861816187022032 + 0.59863846277554023 + 0.59865876476800739 + 0.59867906784772806 + 0.59869937201481116 + 0.59871967726936171 + 0.59873998361148562 + 0.59876029104129236 + 0.59878059955888507 + 0.5988009091643729 + 0.59882121985786219 + 0.59884153163945919 + 0.59886184450927171 + 0.59888215846740434 + 0.59890247351396797 + 0.59892278964906587 + 0.59894310687280605 + 0.59896342518529455 + 0.59898374458664072 + 0.59900406507694959 + 0.59902438665632729 + 0.59904470932488174 + 0.59906503308272085 + 0.59908535792995088 + 0.59910568386667828 + 0.59912601089301087 + 0.59914633900905667 + 0.59916666821492037 + 0.59918699851070878 + 0.59920732989653236 + 0.59922766237249492 + 0.59924799593870692 + 0.59926833059527085 + 0.59928866634229727 + 0.59930900317989433 + 0.59932934110816571 + 0.59934968012722201 + 0.5993700202371669 + 0.59939036143811131 + 0.59941070373015903 + 0.59943104711341932 + 0.5994513915880002 + 0.59947173715400826 + 0.59949208381155006 + 0.59951243156073231 + 0.59953278040166436 + 0.59955313033445301 + 0.59957348135920463 + 0.5995938334760289 + 0.59961418668503108 + 0.59963454098631908 + 0.59965489638000102 + 0.59967525286618373 + 0.5996956104449751 + 0.59971596911648206 + 0.59973632888081263 + 0.5997566897380735 + 0.59977705168837436 + 0.5997974147318218 + 0.59981777886852128 + 0.59983814409858383 + 0.59985851042211602 + 0.59987887783922345 + 0.59989924635001557 + 0.59991961595459919 + 0.59993998665308423 + 0.59996035844557583 + 0.59998073133218222 + 0.60000110531301321 + 0.60002148038817416 + 0.60004185655777342 + 0.60006223382192048 + 0.60008261218071957 + 0.60010299163428193 + 0.60012337218271428 + 0.60014375382612495 + 0.60016413656462098 + 0.60018452039831072 + 0.60020490532730086 + 0.60022529135170144 + 0.60024567847161925 + 0.60026606668716287 + 0.60028645599843911 + 0.60030684640555798 + 0.60032723790862474 + 0.60034763050775097 + 0.60036802420304214 + 0.60038841899460516 + 0.6004088148825516 + 0.60042921186698683 + 0.60044960994802077 + 0.60047000912576221 + 0.60049040940031639 + 0.60051081077179203 + 0.60053121324030045 + 0.60055161680594737 + 0.60057202146884126 + 0.60059242722909068 + 0.60061283408680277 + 0.60063324204208768 + 0.60065365109505231 + 0.60067406124580669 + 0.60069447249445673 + 0.60071488484111224 + 0.60073529828588201 + 0.6007557128288733 + 0.6007761284701959 + 0.60079654520995585 + 0.6008169630482646 + 0.60083738198522785 + 0.60085780202095573 + 0.60087822315555717 + 0.60089864538913917 + 0.60091906872181178 + 0.60093949315368111 + 0.60095991868485854 + 0.60098034531545164 + 0.60100077304556887 + 0.60102120187531771 + 0.6010416318048083 + 0.60106206283414798 + 0.6010824949634469 + 0.60110292819281397 + 0.60112336252235654 + 0.60114379795218342 + 0.60116423448240486 + 0.60118467211312665 + 0.60120511084446215 + 0.60122555067651451 + 0.60124599160939685 + 0.60126643364321641 + 0.60128687677808224 + 0.60130732101410322 + 0.60132776635138829 + 0.60134821279004624 + 0.6013686603301861 + 0.60138910897191533 + 0.60140955871534574 + 0.60143000956058479 + 0.60145046150774006 + 0.60147091455692203 + 0.60149136870824094 + 0.60151182396180303 + 0.60153228031771877 + 0.60155273777609852 + 0.60157319633704842 + 0.60159365600068049 + 0.60161411676710208 + 0.60163457863642267 + 0.60165504160875227 + 0.60167550568419881 + 0.60169597086287274 + 0.60171643714488021 + 0.60173690453033479 + 0.60175737301934396 + 0.6017778426120155 + 0.60179831330846001 + 0.6018187851087865 + 0.60183925801310434 + 0.60185973202152376 + 0.60188020713415291 + 0.6019006833511007 + 0.60192116067247781 + 0.6019416390983936 + 0.60196211862895688 + 0.60198259926427733 + 0.60200308100446387 + 0.6020235638496273 + 0.60204404779987553 + 0.60206453285531758 + 0.60208501901606559 + 0.60210550628222759 + 0.60212599465391281 + 0.60214648413123051 + 0.60216697471429148 + 0.60218746640320509 + 0.60220795919808034 + 0.60222845309902695 + 0.60224894810615426 + 0.60226944421957418 + 0.60228994143939341 + 0.60231043976572285 + 0.6023309391986732 + 0.60235143973835226 + 0.60237194138487127 + 0.60239244413833926 + 0.60241294799886735 + 0.60243345296656348 + 0.60245395904153842 + 0.60247446622390177 + 0.60249497451376433 + 0.60251548391123411 + 0.60253599441642225 + 0.60255650602943955 + 0.60257701875039538 + 0.60259753257939808 + 0.60261804751655978 + 0.60263856356198875 + 0.60265908071579599 + 0.60267959897809098 + 0.60270011834898329 + 0.6027206388285854 + 0.60274116041700554 + 0.60276168311435308 + 0.60278220692073925 + 0.60280273183627497 + 0.60282325786106872 + 0.60284378499523117 + 0.60286431323887224 + 0.60288484259210295 + 0.60290537305503444 + 0.60292590462777329 + 0.60294643731043385 + 0.60296697110312425 + 0.60298750600595397 + 0.60300804201903602 + 0.6030285791424782 + 0.60304911737639355 + 0.60306965672088875 + 0.60309019717607637 + 0.60311073874206778 + 0.60313128141897254 + 0.60315182520689925 + 0.60317237010596036 + 0.60319291611626602 + 0.60321346323792702 + 0.60323401147105338 + 0.60325456081575513 + 0.60327511127214339 + 0.60329566284032787 + 0.60331621552042003 + 0.60333676931253122 + 0.60335732421676991 + 0.60337788023325012 + 0.60339843736207777 + 0.6034189956033682 + 0.60343955495722856 + 0.60346011542377176 + 0.60348067700310615 + 0.6035012396953463 + 0.60352180350059892 + 0.60354236841897713 + 0.60356293445059084 + 0.60358350159555141 + 0.60360406985396886 + 0.60362463922595477 + 0.6036452097116205 + 0.60366578131107618 + 0.60368635402443183 + 0.60370692785179891 + 0.60372750279329035 + 0.60374807884901338 + 0.60376865601908247 + 0.60378923430360609 + 0.60380981370269593 + 0.60383039421646501 + 0.6038509758450219 + 0.60387155858847841 + 0.60389214244694434 + 0.60391272742053448 + 0.60393331350935597 + 0.60395390071352195 + 0.60397448903314244 + 0.60399507846832923 + 0.60401566901919401 + 0.60403626068584837 + 0.60405685346840099 + 0.60407744736696667 + 0.60409804238165243 + 0.6041186385125733 + 0.60413923575983774 + 0.60415983412356056 + 0.60418043360384899 + 0.60420103420081639 + 0.60422163591457434 + 0.60424223874523475 + 0.60426284269290786 + 0.60428344775770415 + 0.60430405393973663 + 0.60432466123911743 + 0.60434526965595647 + 0.604365879190366 + 0.60438648984245602 + 0.60440710161234024 + 0.60442771450012867 + 0.60444832850593344 + 0.60446894362986636 + 0.60448955987203923 + 0.60451017723256262 + 0.60453079571154678 + 0.60455141530910816 + 0.60457203602535448 + 0.60459265786039729 + 0.60461328081435028 + 0.60463390488732516 + 0.60465453007943137 + 0.60467515639078329 + 0.60469578382149047 + 0.60471641237166629 + 0.60473704204142242 + 0.60475767283086956 + 0.60477830474011995 + 0.60479893776928551 + 0.60481957191847979 + 0.60484020718781306 + 0.604860843577395 + 0.60488148108734319 + 0.60490211971776386 + 0.60492275946877228 + 0.60494340034047878 + 0.60496404233299728 + 0.60498468544643813 + 0.60500532968091358 + 0.60502597503653588 + 0.60504662151341715 + 0.60506726911167097 + 0.60508791783140803 + 0.60510856767273913 + 0.60512921863577795 + 0.60514987072063664 + 0.60517052392742599 + 0.60519117825626112 + 0.60521183370725129 + 0.6052324902805104 + 0.6052531479761506 + 0.60527380679428266 + 0.60529446673502196 + 0.60531512779847763 + 0.60533578998476356 + 0.60535645329399212 + 0.60537711772627389 + 0.60539778328172456 + 0.60541844996045313 + 0.60543911776257364 + 0.60545978668819855 + 0.60548045673744 + 0.60550112791041188 + 0.6055218002072239 + 0.60554247362799107 + 0.60556314817282453 + 0.60558382384183651 + 0.60560450063514126 + 0.60562517855285081 + 0.60564585759507505 + 0.60566653776193069 + 0.60568721905352862 + 0.60570790146997999 + 0.60572858501140014 + 0.60574926967790022 + 0.60576995546959422 + 0.60579064238659164 + 0.60581133042900948 + 0.60583201959695721 + 0.60585270989054907 + 0.60587340130989742 + 0.60589409385511506 + 0.60591478752631589 + 0.60593548232361094 + 0.60595617824711612 + 0.60597687529694066 + 0.60599757347319905 + 0.60601827277600362 + 0.60603897320546851 + 0.60605967476170663 + 0.60608037744483056 + 0.60610108125495277 + 0.60612178619218615 + 0.60614249225664329 + 0.60616319944843988 + 0.60618390776768727 + 0.60620461721449814 + 0.60622532778898652 + 0.60624603949126388 + 0.60626675232144434 + 0.60628746627964225 + 0.60630818136597031 + 0.60632889758053987 + 0.60634961492346662 + 0.60637033339486202 + 0.60639105299483886 + 0.60641177372351274 + 0.60643249558099521 + 0.60645321856740053 + 0.60647394268284149 + 0.60649466792743112 + 0.60651539430128232 + 0.60653612180451066 + 0.60655685043722929 + 0.60657758019954811 + 0.60659831109158435 + 0.60661904311344972 + 0.60663977626525845 + 0.60666051054712189 + 0.60668124595915629 + 0.60670198250147589 + 0.6067227201741906 + 0.60674345897741522 + 0.60676419891126554 + 0.60678493997585303 + 0.60680568217129216 + 0.6068264254976975 + 0.60684716995517929 + 0.60686791554385489 + 0.60688866226383575 + 0.60690941011523669 + 0.60693015909817061 + 0.60695090921275219 + 0.60697166045909579 + 0.60699241283731331 + 0.60701316634751923 + 0.60703392098982678 + 0.60705467676435199 + 0.60707543367120642 + 0.60709619171050488 + 0.60711695088236195 + 0.60713771118688942 + 0.60715847262420342 + 0.60717923519441708 + 0.6071999988976452 + 0.60722076373399936 + 0.60724152970359746 + 0.60726229680654809 + 0.60728306504297058 + 0.60730383441297664 + 0.60732460491667961 + 0.60734537655419563 + 0.60736614932563671 + 0.60738692323111743 + 0.60740769827075425 + 0.60742847444465886 + 0.60744925175294606 + 0.60747003019572954 + 0.6074908097731252 + 0.60751159048524661 + 0.60753237233220569 + 0.60755315531412013 + 0.60757393943110205 + 0.60759472468326758 + 0.60761551107072898 + 0.60763629859360235 + 0.60765708725200118 + 0.60767787704603915 + 0.60769866797583239 + 0.60771946004149313 + 0.60774025324313918 + 0.60776104758088245 + 0.60778184305483662 + 0.60780263966511827 + 0.60782343741184197 + 0.60784423629512174 + 0.60786503631507072 + 0.6078858374718058 + 0.60790663976543868 + 0.60792744319608771 + 0.60794824776386491 + 0.6079690534688853 + 0.60798986031126401 + 0.6080106682911145 + 0.60803147740855357 + 0.60805228766369479 + 0.60807309905665341 + 0.60809391158754433 + 0.6081147252564798 + 0.60813554006357806 + 0.60815635600895279 + 0.60817717309271746 + 0.60819799131498764 + 0.60821881067588113 + 0.6082396311755075 + 0.60826045281398622 + 0.60828127559142964 + 0.60830209950795311 + 0.60832292456367321 + 0.60834375075870373 + 0.60836457809315858 + 0.60838540656715578 + 0.60840623618080647 + 0.60842706693422877 + 0.60844789882753503 + 0.60846873186084505 + 0.60848956603426829 + 0.60851040134792445 + 0.60853123780192586 + 0.60855207539638823 + 0.608572914131428 + 0.60859375400715932 + 0.60861459502369752 + 0.60863543718115798 + 0.60865628047965625 + 0.60867712491930615 + 0.608697970500226 + 0.60871881722252863 + 0.60873966508632915 + 0.60876051409174481 + 0.6087813642388894 + 0.60880221552787983 + 0.60882306795883034 + 0.60884392153185485 + 0.60886477624707336 + 0.6088856321045969 + 0.60890648910454415 + 0.60892734724702746 + 0.60894820653216408 + 0.60896906696007091 + 0.60898992853086076 + 0.60901079124465196 + 0.60903165510155888 + 0.60905252010169542 + 0.60907338624518037 + 0.60909425353212632 + 0.60911512196265194 + 0.60913599153686981 + 0.60915686225489873 + 0.60917773411685427 + 0.60919860712284912 + 0.60921948127300063 + 0.60924035656742581 + 0.60926123300623902 + 0.6092821105895575 + 0.60930298931749527 + 0.6093238691901699 + 0.60934475020769552 + 0.60936563237019081 + 0.60938651567776869 + 0.60940740013054651 + 0.60942828572863983 + 0.60944917247216612 + 0.6094700603612383 + 0.60949094939597515 + 0.60951183957649235 + 0.60953273090290438 + 0.6095536233753287 + 0.60957451699388254 + 0.60959541175867893 + 0.60961630766983665 + 0.60963720472747007 + 0.60965810293169675 + 0.60967900228263117 + 0.6096999027803921 + 0.60972080442509258 + 0.6097417072168515 + 0.60976261115578489 + 0.60978351624200877 + 0.60980442247563749 + 0.60982532985679017 + 0.60984623838558139 + 0.60986714806212861 + 0.6098880588865464 + 0.60990897085895357 + 0.60992988397946502 + 0.60995079824819809 + 0.60997171366526892 + 0.6099926302307922 + 0.61001354794488838 + 0.61003446680766926 + 0.6100553868192552 + 0.61007630797976087 + 0.61009723028930407 + 0.61011815374799938 + 0.61013907835596448 + 0.61016000411331706 + 0.61018093102017312 + 0.61020185907664914 + 0.61022278828286103 + 0.61024371863892535 + 0.61026465014496101 + 0.61028558280108436 + 0.61030651660740876 + 0.61032745156405477 + 0.61034838767113875 + 0.61036932492877538 + 0.61039026333708413 + 0.61041120289617967 + 0.61043214360617981 + 0.61045308546720101 + 0.61047402847936094 + 0.61049497264277597 + 0.61051591795756399 + 0.61053686442384125 + 0.61055781204172288 + 0.61057876081132945 + 0.61059971073277608 + 0.61062066180618058 + 0.6106416140316594 + 0.61066256740932878 + 0.61068352193930697 + 0.61070447762171032 + 0.61072543445665806 + 0.61074639244426387 + 0.61076735158464879 + 0.61078831187792759 + 0.6108092733242183 + 0.61083023592363761 + 0.61085119967630352 + 0.61087216458233096 + 0.61089313064184081 + 0.61091409785494843 + 0.61093506622177174 + 0.61095603574242874 + 0.61097700641703456 + 0.61099797824570756 + 0.61101895122856686 + 0.61103992536572793 + 0.61106090065730878 + 0.61108187710342754 + 0.61110285470419945 + 0.61112383345974541 + 0.61114481337018101 + 0.61116579443562402 + 0.61118677665619137 + 0.61120776003200261 + 0.61122874456317156 + 0.61124973024982088 + 0.61127071709206438 + 0.61129170509002173 + 0.61131269424380952 + 0.61133368455354642 + 0.6113546760193489 + 0.61137566864133686 + 0.61139666241962398 + 0.61141765735433307 + 0.61143865344557824 + 0.61145965069347907 + 0.61148064909815369 + 0.61150164865971779 + 0.61152264937829115 + 0.61154365125399224 + 0.61156465428693763 + 0.61158565847724444 + 0.61160666382503248 + 0.61162767033041876 + 0.61164867799352152 + 0.61166968681445932 + 0.61169069679334931 + 0.6117117079303096 + 0.61173272022545877 + 0.61175373367891395 + 0.61177474829079481 + 0.61179576406121861 + 0.61181678099030379 + 0.61183779907816882 + 0.61185881832493094 + 0.61187983873070828 + 0.6119008602956183 + 0.61192188301978379 + 0.61194290690331743 + 0.6119639319463408 + 0.61198495814896958 + 0.61200598551132512 + 0.61202701403352489 + 0.61204804371568577 + 0.61206907455792781 + 0.61209010656036844 + 0.61211113972312614 + 0.61213217404632103 + 0.6121532095300688 + 0.6121742461744899 + 0.6121952839797028 + 0.61221632294582484 + 0.61223736307297449 + 0.61225840436127077 + 0.61227944681083379 + 0.6123004904217807 + 0.61232153519422905 + 0.61234258112829876 + 0.6123636282241105 + 0.61238467648177819 + 0.6124057259014255 + 0.61242677648316646 + 0.61244782822712451 + 0.61246888113341547 + 0.61248993520215822 + 0.61251099043347179 + 0.6125320468274762 + 0.612553104384289 + 0.61257416310402912 + 0.61259522298681546 + 0.61261628403276847 + 0.61263734624200528 + 0.61265840961464524 + 0.6126794741508057 + 0.61270053985061002 + 0.61272160671417264 + 0.61274267474161548 + 0.61276374393305633 + 0.61278481428861387 + 0.61280588580840734 + 0.61282695849255708 + 0.61284803234118068 + 0.61286910735439892 + 0.61289018353232905 + 0.61291126087509173 + 0.61293233938280456 + 0.61295341905558809 + 0.61297449989356156 + 0.61299558189684533 + 0.61301666506555574 + 0.61303774939981182 + 0.61305883489973578 + 0.61307992156544655 + 0.61310100939706225 + 0.61312209839470311 + 0.61314318855848704 + 0.61316427988853461 + 0.61318537238496507 + 0.6132064660478993 + 0.61322756087745478 + 0.61324865687375085 + 0.61326975403690831 + 0.61329085236704495 + 0.61331195186428289 + 0.61333305252874004 + 0.61335415436053564 + 0.61337525735979059 + 0.61339636152662402 + 0.61341746686115395 + 0.6134385733635026 + 0.61345968103378778 + 0.61348078987213051 + 0.61350189987864856 + 0.6135230110534643 + 0.61354412339669717 + 0.61356523690846343 + 0.61358635158888719 + 0.61360746743808625 + 0.61362858445618018 + 0.61364970264328977 + 0.61367082199953316 + 0.61369194252503412 + 0.61371306421990912 + 0.61373418708427785 + 0.6137553111182612 + 0.61377643632198153 + 0.61379756269555574 + 0.61381869023910307 + 0.61383981895274764 + 0.61386094883660602 + 0.61388207989079913 + 0.61390321211544818 + 0.61392434551067143 + 0.61394548007659122 + 0.61396661581332568 + 0.61398775272099615 + 0.61400889079972198 + 0.61403003004962442 + 0.61405117047082325 + 0.61407231206343937 + 0.61409345482759115 + 0.6141145987633998 + 0.61413574387098646 + 0.61415689015047081 + 0.6141780376019742 + 0.61419918622561476 + 0.61422033602151505 + 0.61424148698979519 + 0.61426263913057455 + 0.61428379244397324 + 0.61430494693011395 + 0.6143261025891148 + 0.61434725942109891 + 0.61436841742618431 + 0.61438957660449245 + 0.61441073695614479 + 0.61443189848125945 + 0.61445306117995946 + 0.61447422505236604 + 0.61449539009859777 + 0.61451655631877578 + 0.61453772371302029 + 0.61455889228145411 + 0.61458006202419557 + 0.61460123294136759 + 0.61462240503308885 + 0.61464357829948202 + 0.61466475274066568 + 0.61468592835676295 + 0.61470710514789362 + 0.61472828311417949 + 0.61474946225574023 + 0.61477064257269598 + 0.61479182406516986 + 0.61481300673328343 + 0.61483419057715361 + 0.61485537559690506 + 0.61487656179265637 + 0.61489774916453221 + 0.61491893771264949 + 0.61494012743713156 + 0.61496131833809831 + 0.61498251041567153 + 0.61500370366997281 + 0.61502489810112382 + 0.61504609370924324 + 0.6150672904944543 + 0.61508848845687858 + 0.61510968759663487 + 0.61513088791384785 + 0.6151520894086363 + 0.61517329208112181 + 0.61519449593142495 + 0.61521570095967015 + 0.61523690716597623 + 0.61525811455046509 + 0.61527932311325695 + 0.61530053285447661 + 0.61532174377424154 + 0.61534295587267629 + 0.6153641691499 + 0.61538538360603579 + 0.61540659924120555 + 0.61542781605552821 + 0.61544903404912721 + 0.61547025322212423 + 0.6154914735746414 + 0.61551269510679896 + 0.61553391781871913 + 0.61555514171052195 + 0.61557636678233263 + 0.61559759303426997 + 0.61561882046645766 + 0.61564004907901448 + 0.61566127887206556 + 0.61568250984573114 + 0.61570374200013367 + 0.61572497533539328 + 0.61574620985163375 + 0.61576744554897556 + 0.61578868242754214 + 0.61580992048745431 + 0.61583115972883384 + 0.61585240015180176 + 0.61587364175648274 + 0.61589488454299757 + 0.61591612851146693 + 0.6159373736620144 + 0.61595861999476054 + 0.61597986750983069 + 0.61600111620734255 + 0.61602236608742111 + 0.61604361715018696 + 0.61606486939576421 + 0.61608612282427178 + 0.61610737743583499 + 0.61612863323057609 + 0.61614989020861421 + 0.61617114837007481 + 0.61619240771507844 + 0.61621366824374757 + 0.61623492995620599 + 0.61625619285257283 + 0.61627745693297353 + 0.61629872219753046 + 0.61631998864636273 + 0.61634125627959613 + 0.61636252509735256 + 0.61638379509975161 + 0.61640506628692016 + 0.61642633865897767 + 0.61644761221604638 + 0.61646888695825175 + 0.61649016288571334 + 0.61651143999855507 + 0.61653271829690071 + 0.61655399778086983 + 0.6165752784505879 + 0.61659656030617604 + 0.61661784334775649 + 0.61663912757545347 + 0.61666041298938934 + 0.61668169958968533 + 0.61670298737646678 + 0.61672427634985483 + 0.61674556650997059 + 0.61676685785694252 + 0.6167881503908873 + 0.6168094441119305 + 0.61683073902019481 + 0.61685203511580267 + 0.61687333239887843 + 0.61689463086954299 + 0.6169159305279206 + 0.61693723137413403 + 0.61695853340830742 + 0.61697983663056188 + 0.61700114104102022 + 0.61702244663980654 + 0.61704375342704498 + 0.61706506140285711 + 0.61708637056736682 + 0.61710768092069557 + 0.61712899246296904 + 0.61715030519431013 + 0.61717161911483986 + 0.6171929342246828 + 0.61721425052396173 + 0.61723556801280244 + 0.61725688669132461 + 0.61727820655965271 + 0.61729952761791118 + 0.61732084986622282 + 0.61734217330471053 + 0.61736349793349865 + 0.61738482375271009 + 0.61740615076246785 + 0.61742747896289485 + 0.61744880835411675 + 0.61747013893625546 + 0.61749147070943344 + 0.61751280367377714 + 0.6175341378294078 + 0.61755547317644988 + 0.61757680971502793 + 0.61759814744526353 + 0.61761948636728115 + 0.61764082648120533 + 0.61766216778715766 + 0.61768351028526414 + 0.61770485397564789 + 0.61772619885843205 + 0.61774754493374107 + 0.61776889220169817 + 0.61779024066242638 + 0.61781159031605204 + 0.6178329411626966 + 0.61785429320248464 + 0.61787564643554105 + 0.61789700086198884 + 0.61791835648195137 + 0.61793971329555308 + 0.61796107130291889 + 0.61798243050417045 + 0.61800379089943558 + 0.61802515248883438 + 0.61804651527249321 + 0.61806787925053674 + 0.61808924442308677 + 0.6181106107902683 + 0.6181319783522059 + 0.61815334710902292 + 0.6181747170608457 + 0.61819608820779626 + 0.61821746054999904 + 0.6182388340875794 + 0.61826020882066024 + 0.61828158474936667 + 0.61830296187382361 + 0.61832434019415294 + 0.61834571971048258 + 0.61836710042293441 + 0.61838848233163346 + 0.61840986543670451 + 0.61843124973827124 + 0.61845263523645844 + 0.61847402193139134 + 0.61849540982319151 + 0.61851679891198885 + 0.61853818919790227 + 0.61855958068105976 + 0.61858097336158635 + 0.61860236723960427 + 0.6186237623152383 + 0.61864515858861369 + 0.61866655605985554 + 0.61868795472909044 + 0.61870935459643883 + 0.61873075566202751 + 0.61875215792598326 + 0.61877356138842643 + 0.61879496604948536 + 0.61881637190928362 + 0.618837778967948 + 0.61885918722559907 + 0.61888059668236495 + 0.61890200733836975 + 0.61892341919373983 + 0.61894483224859742 + 0.61896624650306797 + 0.61898766195727828 + 0.6190090786113519 + 0.61903049646541575 + 0.6190519155195906 + 0.61907333577400625 + 0.61909475722878515 + 0.61911617988405387 + 0.61913760373993643 + 0.61915902879655815 + 0.6191804550540444 + 0.61920188251252051 + 0.61922331117211193 + 0.61924474103294269 + 0.61926617209513934 + 0.61928760435882613 + 0.61930903782412983 + 0.61933047249117457 + 0.61935190836008402 + 0.61937334543098688 + 0.61939478370400858 + 0.61941622317927159 + 0.61943766385690147 + 0.61945910573702656 + 0.6194805488197711 + 0.61950199310525922 + 0.61952343859361758 + 0.61954488528497198 + 0.61956633317944654 + 0.61958778227716826 + 0.61960923257826273 + 0.61963068408285571 + 0.61965213679107112 + 0.61967359070303618 + 0.61969504581887658 + 0.61971650213871632 + 0.61973795966268275 + 0.61975941839090143 + 0.61978087832349826 + 0.61980233946059715 + 0.61982380180232699 + 0.6198452653488119 + 0.61986673010017779 + 0.61988819605655021 + 0.61990966321805496 + 0.61993113158481961 + 0.61995260115696793 + 0.61997407193462917 + 0.61999554391792433 + 0.62001701710698243 + 0.62003849150192925 + 0.62005996710289191 + 0.62008144390999376 + 0.62010292192336314 + 0.62012440114312473 + 0.62014588156940587 + 0.6201673632023309 + 0.62018884604203028 + 0.62021033008862403 + 0.62023181534224237 + 0.6202533018030113 + 0.62027478947105552 + 0.62029627834650225 + 0.62031776842947761 + 0.62033925972010895 + 0.62036075221852083 + 0.62038224592484081 + 0.62040374083919492 + 0.62042523696170926 + 0.62044673429250974 + 0.62046823283172403 + 0.6204897325794797 + 0.62051123353589965 + 0.62053273570111345 + 0.6205542390752451 + 0.62057574365842427 + 0.62059724945077521 + 0.62061875645242581 + 0.62064026466350064 + 0.62066177408413037 + 0.62068328471443657 + 0.62070479655454869 + 0.62072630960459418 + 0.62074782386469796 + 0.62076933933498757 + 0.62079085601558948 + 0.62081237390663124 + 0.6208338930082391 + 0.62085541332053962 + 0.62087693484366047 + 0.6208984575777261 + 0.62091998152286776 + 0.62094150667920855 + 0.62096303304687639 + 0.62098456062599927 + 0.62100608941670321 + 0.62102761941911622 + 0.62104915063336341 + 0.62107068305957391 + 0.62109221669787273 + 0.62111375154838921 + 0.62113528761124981 + 0.62115682488657964 + 0.62117836337450938 + 0.62119990307516271 + 0.62122144398866752 + 0.62124298611515316 + 0.62126452945474508 + 0.62128607400757074 + 0.62130761977375848 + 0.62132916675343497 + 0.62135071494672633 + 0.62137226435376103 + 0.62139381497466539 + 0.62141536680957055 + 0.62143691985859861 + 0.62145847412188071 + 0.62148002959954207 + 0.62150158629171215 + 0.62152314419851773 + 0.62154470332008371 + 0.62156626365654155 + 0.62158782520801792 + 0.62160938797463916 + 0.6216309519565324 + 0.62165251715382708 + 0.62167408356665177 + 0.62169565119512971 + 0.62171722003939256 + 0.62173879009956678 + 0.6217603613757795 + 0.62178193386816016 + 0.62180350757683422 + 0.62182508250193158 + 0.62184665864357724 + 0.62186823600190289 + 0.62188981457703518 + 0.62191139436909959 + 0.62193297537822601 + 0.62195455760454255 + 0.62197614104817645 + 0.62199772570925582 + 0.62201931158790769 + 0.6220408986842636 + 0.62206248699844602 + 0.62208407653058906 + 0.62210566728081551 + 0.62212725924925671 + 0.62214885243603979 + 0.62217044684129319 + 0.62219204246514526 + 0.62221363930772322 + 0.62223523736915543 + 0.62225683664957221 + 0.62227843714909736 + 0.62230003886786411 + 0.62232164180599792 + 0.62234324596362756 + 0.62236485134088282 + 0.62238645793788971 + 0.62240806575477681 + 0.62242967479167544 + 0.62245128504871006 + 0.62247289652601223 + 0.62249450922371063 + 0.62251612314192939 + 0.62253773828080183 + 0.62255935464045375 + 0.62258097222101505 + 0.62260259102261484 + 0.62262421104538024 + 0.62264583228943993 + 0.62266745475492269 + 0.62268907844195898 + 0.62271070335067435 + 0.62273232948120083 + 0.62275395683366419 + 0.62277558540819467 + 0.62279721520492126 + 0.62281884622397266 + 0.62284047846547796 + 0.62286211192956442 + 0.62288374661636225 + 0.62290538252600081 + 0.62292701965860697 + 0.62294865801431165 + 0.62297029759324363 + 0.62299193839553024 + 0.62301358042130217 + 0.6230352236706882 + 0.62305686814381589 + 0.62307851384081581 + 0.62310016076181829 + 0.62312180890694968 + 0.62314345827633877 + 0.62316510887011767 + 0.62318676068841405 + 0.62320841373135683 + 0.62323006799907665 + 0.62325172349169977 + 0.62327338020935807 + 0.62329503815218068 + 0.6233166973202956 + 0.62333835771383306 + 0.62336001933292229 + 0.62338168217769263 + 0.62340334624827332 + 0.62342501154479335 + 0.62344667806738208 + 0.62346834581617161 + 0.62349001479128674 + 0.62351168499286125 + 0.62353335642102437 + 0.62355502907590232 + 0.62357670295762602 + 0.62359837806632767 + 0.62362005440213342 + 0.62364173196517603 + 0.6236634107555814 + 0.62368509077348211 + 0.62370677201900737 + 0.62372845449228664 + 0.62375013819344927 + 0.62377182312262636 + 0.62379350927994548 + 0.62381519666553775 + 0.62383688527953407 + 0.62385857512206233 + 0.62388026619325343 + 0.62390195849323715 + 0.62392365202214251 + 0.62394534678010238 + 0.62396704276724169 + 0.62398873998369575 + 0.62401043842959136 + 0.62403213810505931 + 0.62405383901022937 + 0.62407554114523389 + 0.6240972445101981 + 0.62411894910525756 + 0.62414065493053894 + 0.6241623619861747 + 0.62418407027229306 + 0.6242057797890237 + 0.62422749053649917 + 0.62424920251484761 + 0.62427091572420179 + 0.62429263016468983 + 0.62431434583644307 + 0.62433606273959108 + 0.62435778087426519 + 0.62437950024059496 + 0.62440122083871186 + 0.62442294266874543 + 0.62444466573082569 + 0.62446639002508353 + 0.62448811555165074 + 0.62450984231065532 + 0.62453157030223017 + 0.62455329952650507 + 0.62457502998360992 + 0.62459676167367761 + 0.62461849459683505 + 0.6246402287532149 + 0.62466196414295039 + 0.62468370076616653 + 0.62470543862299965 + 0.62472717771357633 + 0.62474891803802979 + 0.62477065959649125 + 0.6247924023890894 + 0.62481414641595567 + 0.62483589167722131 + 0.62485763817301665 + 0.62487938590347458 + 0.62490113486872356 + 0.62492288506889515 + 0.62494463650412269 + 0.62496638917453429 + 0.62498814308026196 + 0.62500989822143549 + 0.62503165459818799 + 0.62505341221064981 + 0.62507517105895238 + 0.62509693114322584 + 0.62511869246360208 + 0.62514045502021243 + 0.62516221881318734 + 0.62518398384265839 + 0.62520575010875712 + 0.6252275176116141 + 0.6252492863513609 + 0.62527105632812907 + 0.62529282754205062 + 0.62531459999325578 + 0.62533637368187622 + 0.62535814860804229 + 0.62537992477188875 + 0.62540170217354307 + 0.62542348081313826 + 0.62544526069080653 + 0.62546704180667945 + 0.62548882416088913 + 0.62551060775356426 + 0.62553239258483806 + 0.62555417865484142 + 0.6255759659637089 + 0.62559775451156796 + 0.62561954429855371 + 0.62564133532479649 + 0.62566312759042675 + 0.62568492109557949 + 0.62570671584038207 + 0.62572851182496969 + 0.62575030904947271 + 0.62577210751402479 + 0.62579390721875494 + 0.62581570816379661 + 0.62583751034928203 + 0.62585931377534154 + 0.62588111844210903 + 0.62590292434971628 + 0.62592473149829408 + 0.62594653988797455 + 0.62596834951888991 + 0.62599016039117217 + 0.62601197250495511 + 0.62603378586036773 + 0.62605560045754527 + 0.62607741629661706 + 0.62609923337771667 + 0.62612105170097654 + 0.62614287126653012 + 0.62616469207450698 + 0.62618651412504045 + 0.62620833741826176 + 0.62623016195430448 + 0.62625198773330237 + 0.62627381475538491 + 0.62629564302068708 + 0.62631747252933867 + 0.6263393032814748 + 0.6263611352772247 + 0.62638296851672404 + 0.62640480300010204 + 0.6264266387274956 + 0.62644847569903261 + 0.62647031391484864 + 0.62649215337507447 + 0.62651399407984565 + 0.62653583602929164 + 0.62655767922354488 + 0.62657952366274083 + 0.6266013693470105 + 0.62662321627648798 + 0.62664506445130275 + 0.62666691387159024 + 0.62668876453748323 + 0.62671061644911408 + 0.62673246960661388 + 0.62675432401011844 + 0.62677617965975863 + 0.62679803655567012 + 0.62681989469798116 + 0.62684175408682719 + 0.62686361472234242 + 0.6268854766046581 + 0.62690733973391 + 0.62692920411022601 + 0.62695106973374359 + 0.62697293660459374 + 0.6269948047229108 + 0.62701667408882755 + 0.62703854470247533 + 0.6270604165639897 + 0.62708228967350343 + 0.62710416403114955 + 0.62712603963705904 + 0.62714791649136958 + 0.62716979459421218 + 0.6271916739457184 + 0.62721355454602401 + 0.6272354363952618 + 0.62725731949356478 + 0.62727920384106572 + 0.62730108943790064 + 0.62732297628420086 + 0.62734486438009951 + 0.62736675372572914 + 0.62738864432122765 + 0.62741053616672471 + 0.62743242926235476 + 0.6274543236082526 + 0.62747621920454955 + 0.6274981160513815 + 0.62752001414888026 + 0.62754191349718014 + 0.62756381409641737 + 0.62758571594672197 + 0.62760761904822848 + 0.62762952340107281 + 0.6276514290053854 + 0.62767333586130369 + 0.62769524396895948 + 0.62771715332848721 + 0.62773906394001866 + 0.62776097580369139 + 0.62778288891963718 + 0.62780480328799082 + 0.6278267189088852 + 0.62784863578245376 + 0.62787055390883273 + 0.62789247328815556 + 0.62791439392055648 + 0.62793631580616771 + 0.62795823894512537 + 0.62798016333756279 + 0.62800208898361343 + 0.62802401588341328 + 0.62804594403709435 + 0.62806787344479309 + 0.62808980410664272 + 0.62811173602277681 + 0.62813366919333147 + 0.62815560361844014 + 0.62817753929823639 + 0.6281994762328551 + 0.62822141442243129 + 0.62824335386709818 + 0.62826529456699087 + 0.62828723652224439 + 0.62830917973299361 + 0.62833112419937065 + 0.62835306992151196 + 0.62837501689955111 + 0.62839696513362442 + 0.62841891462386446 + 0.62844086537040722 + 0.62846281737338661 + 0.62848477063293751 + 0.62850672514919537 + 0.62852868092229341 + 0.62855063795236699 + 0.62857259623955275 + 0.62859455578398282 + 0.62861651658579232 + 0.6286384786451179 + 0.62866044196209181 + 0.62868240653685237 + 0.62870437236953158 + 0.6287263394602649 + 0.62874830780918889 + 0.62877027741643587 + 0.62879224828214419 + 0.62881422040644608 + 0.62883619378947675 + 0.62885816843137465 + 0.62888014433227057 + 0.62890212149230118 + 0.62892409991160214 + 0.62894607959030857 + 0.62896806052855592 + 0.62899004272647641 + 0.62901202618421026 + 0.62903401090188971 + 0.6290559968796503 + 0.62907798411762716 + 0.62909997261595751 + 0.6291219623747738 + 0.62914395339421458 + 0.62916594567441209 + 0.62918793921550353 + 0.62920993401762426 + 0.62923193008091005 + 0.62925392740549468 + 0.62927592599151527 + 0.62929792583910604 + 0.62931992694840544 + 0.62934192931954624 + 0.62936393295266524 + 0.62938593784789831 + 0.62940794400537947 + 0.62942995142524594 + 0.62945196010763327 + 0.62947397005267569 + 0.62949598126051198 + 0.62951799373127471 + 0.62954000746510252 + 0.62956202246212845 + 0.62958403872249091 + 0.62960605624632426 + 0.62962807503376439 + 0.62965009508494674 + 0.62967211640000897 + 0.62969413897908666 + 0.62971616282231424 + 0.6297381879298305 + 0.62976021430176832 + 0.62978224193826648 + 0.62980427083945933 + 0.6298263010054812 + 0.62984833243647276 + 0.62987036513256811 + 0.62989239909390338 + 0.62991443432061434 + 0.62993647081283699 + 0.62995850857070745 + 0.62998054759436295 + 0.63000258788394092 + 0.63002462943957471 + 0.6300466722614031 + 0.63006871634956063 + 0.63009076170418621 + 0.63011280832541317 + 0.63013485621338039 + 0.630156905368224 + 0.63017895579007854 + 0.6302010074790817 + 0.63022306043537102 + 0.63024511465908251 + 0.63026717015035261 + 0.63028922690931732 + 0.63031128493611421 + 0.63033334423087795 + 0.63035540479374952 + 0.63037746662486027 + 0.6303995297243512 + 0.63042159409235687 + 0.63044365972901506 + 0.63046572663446065 + 0.63048779480883266 + 0.63050986425226907 + 0.63053193496490323 + 0.63055400694687269 + 0.63057608019831701 + 0.63059815471937097 + 0.63062023051017091 + 0.63064230757085626 + 0.63066438590156315 + 0.63068646550242813 + 0.63070854637358775 + 0.6307306285151798 + 0.63075271192734217 + 0.63077479661020974 + 0.63079688256392208 + 0.63081896978861562 + 0.63084105828442538 + 0.63086314805149246 + 0.63088523908995164 + 0.63090733139994104 + 0.6309294249815971 + 0.63095151983505804 + 0.63097361596046042 + 0.63099571335794202 + 0.63101781202763985 + 0.63103991196969322 + 0.63106201318423738 + 0.63108411567141032 + 0.6311062194313487 + 0.63112832446419376 + 0.63115043077007771 + 0.63117253834914311 + 0.63119464720152374 + 0.63121675732735927 + 0.63123886872678636 + 0.63126098139994324 + 0.63128309534696836 + 0.63130521056799671 + 0.63132732706316985 + 0.63134944483262256 + 0.63137156387649374 + 0.63139368419491992 + 0.63141580578804091 + 0.63143792865599346 + 0.63146005279891626 + 0.6314821782169473 + 0.63150430491022203 + 0.63152643287888199 + 0.63154856212306254 + 0.63157069264290355 + 0.63159282443854059 + 0.63161495751011332 + 0.63163709185776051 + 0.63165922748161885 + 0.63168136438182709 + 0.63170350255852348 + 0.63172564201184511 + 0.63174778274193211 + 0.63176992474892146 + 0.63179206803295163 + 0.63181421259415982 + 0.63183635843268748 + 0.63185850554866874 + 0.63188065394224524 + 0.63190280361355256 + 0.63192495456273234 + 0.63194710678992172 + 0.63196926029525635 + 0.63199141507887957 + 0.63201357114092527 + 0.63203572848153522 + 0.63205788710084676 + 0.63208004699899845 + 0.63210220817612772 + 0.63212437063237625 + 0.63214653436787971 + 0.63216869938277842 + 0.63219086567720828 + 0.6322130332513124 + 0.63223520210522666 + 0.63225737223909018 + 0.63227954365304273 + 0.63230171634722065 + 0.63232389032176572 + 0.63234606557681516 + 0.63236824211250953 + 0.63239041992898448 + 0.63241259902638225 + 0.63243477940483861 + 0.63245696106449723 + 0.6324791440054921 + 0.63250132822796412 + 0.63252351373205373 + 0.63254570051789827 + 0.63256788858563695 + 0.63259007793541011 + 0.63261226856735531 + 0.6326344604816132 + 0.63265665367832136 + 0.63267884815762176 + 0.63270104391965065 + 0.63272324096454857 + 0.63274543929245464 + 0.63276763890350807 + 0.63278983979784942 + 0.63281204197561469 + 0.63283424543694644 + 0.63285645018198355 + 0.63287865621086525 + 0.63290086352373109 + 0.63292307212072152 + 0.63294528200197275 + 0.63296749316762713 + 0.63298970561782242 + 0.63301191935270085 + 0.6330341343724003 + 0.63305635067706012 + 0.63307856826682107 + 0.63310078714182094 + 0.63312300730220217 + 0.63314522874810109 + 0.63316745147966147 + 0.63318967549701999 + 0.63321190080031731 + 0.63323412738969287 + 0.63325635526528778 + 0.63327858442724139 + 0.63330081487569301 + 0.63332304661078243 + 0.63334527963265019 + 0.63336751394143775 + 0.63338974953728133 + 0.63341198642032515 + 0.63343422459070564 + 0.63345646404856526 + 0.63347870479404378 + 0.63350094682728075 + 0.63352319014841563 + 0.63354543475759129 + 0.63356768065494395 + 0.63358992784061663 + 0.63361217631475031 + 0.63363442607748321 + 0.6336566771289549 + 0.63367892946930815 + 0.63370118309868118 + 0.63372343801721676 + 0.63374569422505433 + 0.63376795172233258 + 0.63379021050919393 + 0.63381247058577683 + 0.63383473195222551 + 0.63385699460867673 + 0.63387925855527327 + 0.6339015237921537 + 0.63392379031946056 + 0.63394605813733396 + 0.63396832724591357 + 0.63399059764534227 + 0.63401286933575707 + 0.6340351423173024 + 0.63405741659011661 + 0.63407969215434268 + 0.63410196901011895 + 0.63412424715758697 + 0.63414652659688819 + 0.63416880732816416 + 0.63419108935155488 + 0.63421337266719879 + 0.63423565727524189 + 0.6342579431758214 + 0.63428023036908043 + 0.63430251885515865 + 0.63432480863419649 + 0.63434709970633707 + 0.63436939207171872 + 0.63439168573048643 + 0.63441398068277843 + 0.63443627692873672 + 0.63445857446850129 + 0.63448087330221559 + 0.63450317343001938 + 0.63452547485205313 + 0.63454777756846159 + 0.63457008157938199 + 0.63459238688495734 + 0.63461469348532973 + 0.63463700138063928 + 0.63465931057102931 + 0.63468162105663861 + 0.6347039328376104 + 0.63472624591408522 + 0.6347485602862063 + 0.63477087595411263 + 0.63479319291794889 + 0.63481551117785395 + 0.6348378307339716 + 0.63486015158644016 + 0.63488247373540496 + 0.6349047971810049 + 0.63492712192338496 + 0.63494944796268382 + 0.63497177529904392 + 0.6349941039326068 + 0.63501643386351481 + 0.63503876509191137 + 0.63506109761793705 + 0.63508343144173229 + 0.63510576656344231 + 0.63512810298320443 + 0.63515044070116411 + 0.63517277971746322 + 0.63519512003224254 + 0.63521746164564397 + 0.63523980455780971 + 0.63526214876888365 + 0.63528449427900624 + 0.63530684108831981 + 0.63532918919696502 + 0.63535153860508853 + 0.63537388931282812 + 0.63539624132032768 + 0.63541859462772909 + 0.63544094923517658 + 0.63546330514280902 + 0.63548566235077208 + 0.63550802085920644 + 0.63553038066825429 + 0.63555274177805798 + 0.63557510418876173 + 0.63559746790050442 + 0.63561983291343327 + 0.63564219922768761 + 0.63566456684341133 + 0.6356869357607452 + 0.63570930597983344 + 0.63573167750081827 + 0.63575405032384236 + 0.63577642444904958 + 0.63579879987657939 + 0.63582117660657722 + 0.63584355463918596 + 0.63586593397454638 + 0.63588831461280393 + 0.63591069655409838 + 0.63593307979857527 + 0.63595546434637562 + 0.63597785019764352 + 0.63600023735252165 + 0.6360226258111511 + 0.63604501557367765 + 0.63606740664024397 + 0.63608979901099105 + 0.63611219268606323 + 0.63613458766560305 + 0.63615698394975628 + 0.63617938153866282 + 0.63620178043246689 + 0.63622418063131114 + 0.63624658213533825 + 0.63626898494469419 + 0.63629138905951876 + 0.63631379447995906 + 0.63633620120615531 + 0.63635860923825149 + 0.63638101857639051 + 0.63640342922071858 + 0.63642584117137513 + 0.63644825442850783 + 0.63647066899225491 + 0.63649308486276568 + 0.63651550204017959 + 0.63653792052464142 + 0.63656034031629405 + 0.63658276141528192 + 0.63660518382174802 + 0.63662760753583691 + 0.6366500325576917 + 0.63667245888745538 + 0.6366948865252724 + 0.63671731547128751 + 0.63673974572564362 + 0.63676217728848228 + 0.63678461015995136 + 0.63680704434019231 + 0.63682947982934979 + 0.63685191662756546 + 0.63687435473498688 + 0.63689679415175449 + 0.63691923487801572 + 0.63694167691391246 + 0.63696412025958782 + 0.63698656491518812 + 0.63700901088085504 + 0.6370314581567349 + 0.63705390674297246 + 0.63707635663970807 + 0.63709880784708939 + 0.63712126036525984 + 0.63714371419436278 + 0.63716616933454306 + 0.63718862578594404 + 0.63721108354871048 + 0.63723354262298892 + 0.63725600300892116 + 0.63727846470665217 + 0.6373009277163254 + 0.6373233920380873 + 0.6373458576720813 + 0.63736832461845094 + 0.63739079287734257 + 0.63741326244889984 + 0.63743573333326786 + 0.63745820553058974 + 0.63748067904101102 + 0.63750315386467804 + 0.63752563000173279 + 0.6375481074523206 + 0.63757058621658635 + 0.63759306629467527 + 0.63761554768673245 + 0.63763803039290146 + 0.63766051441332772 + 0.63768299974815612 + 0.637705486397532 + 0.637727974361599 + 0.63775046364050403 + 0.63777295423438907 + 0.637795446143401 + 0.63781793936768638 + 0.63784043390738787 + 0.63786292976265047 + 0.63788542693361938 + 0.63790792542044172 + 0.63793042522325971 + 0.63795292634222156 + 0.63797542877746993 + 0.63799793252915138 + 0.63802043759741001 + 0.63804294398239259 + 0.638065451684243 + 0.6380879607031068 + 0.63811047103913099 + 0.63813298269245777 + 0.63815549566323593 + 0.63817800995160934 + 0.63820052555772178 + 0.63822304248172212 + 0.6382455607237526 + 0.63826808028396198 + 0.6382906011624927 + 0.63831312335949186 + 0.63833564687510502 + 0.63835817170947795 + 0.63838069786275753 + 0.63840322533508498 + 0.63842575412661051 + 0.63844828423747824 + 0.63847081566783381 + 0.6384933484178229 + 0.63851588248759128 + 0.63853841787728605 + 0.63856095458705153 + 0.63858349261703362 + 0.63860603196738086 + 0.63862857263823447 + 0.638651114629745 + 0.638673657942055 + 0.63869620257531345 + 0.63871874852966304 + 0.63874129580525274 + 0.63876384440222844 + 0.63878639432073436 + 0.6388089455609165 + 0.63883149812292528 + 0.63885405200690204 + 0.63887660721299422 + 0.63889916374134936 + 0.63892172159211325 + 0.63894428076543208 + 0.63896684126145165 + 0.63898940308031804 + 0.63901196622218037 + 0.63903453068718152 + 0.63905709647546904 + 0.6390796635871907 + 0.63910223202249228 + 0.63912480178151854 + 0.63914737286441858 + 0.63916994527133852 + 0.63919251900242446 + 0.63921509405782106 + 0.63923767043767887 + 0.63926024814214133 + 0.63928282717135587 + 0.63930540752547049 + 0.63932798920463096 + 0.63935057220898406 + 0.63937315653867555 + 0.63939574219385487 + 0.63941832917466856 + 0.63944091748125942 + 0.63946350711378019 + 0.63948609807237244 + 0.63950869035718727 + 0.63953128396836922 + 0.6395538789060663 + 0.63957647517042482 + 0.63959907276159289 + 0.63962167167971651 + 0.639644271924944 + 0.63966687349742313 + 0.63968947639729745 + 0.63971208062471774 + 0.63973468617983065 + 0.63975729306278106 + 0.63977990127371853 + 0.63980251081278972 + 0.63982512168014238 + 0.6398477338759232 + 0.63987034740028037 + 0.63989296225336045 + 0.63991557843531133 + 0.63993819594627976 + 0.63996081478641542 + 0.63998343495586185 + 0.64000605645477027 + 0.64002867928328722 + 0.64005130344155958 + 0.64007392892973547 + 0.6400965557479632 + 0.64011918389638911 + 0.64014181337516185 + 0.64016444418442819 + 0.64018707632433614 + 0.64020970979503555 + 0.64023234459667033 + 0.6402549807293918 + 0.64027761819334672 + 0.64030025698868187 + 0.64032289711554724 + 0.64034553857408827 + 0.64036818136445461 + 0.64039082548679471 + 0.64041347094125578 + 0.64043611772798437 + 0.64045876584713213 + 0.64048141529884295 + 0.64050406608326849 + 0.64052671820055551 + 0.64054937165085113 + 0.64057202643430533 + 0.64059468255106511 + 0.64061734000128057 + 0.64063999878509736 + 0.64066265890266538 + 0.64068532035413184 + 0.64070798313964672 + 0.64073064725935736 + 0.64075331271341385 + 0.64077597950196163 + 0.64079864762515115 + 0.64082131708313084 + 0.64084398787604802 + 0.64086666000405446 + 0.64088933346729426 + 0.64091200826591921 + 0.64093468440007662 + 0.64095736186991525 + 0.64098004067558378 + 0.64100272081723109 + 0.64102540229500604 + 0.64104808510905731 + 0.64107076925953388 + 0.64109345474658463 + 0.64111614157035823 + 0.64113882973100389 + 0.6411615192286686 + 0.64118421006350312 + 0.64120690223565613 + 0.64122959574527849 + 0.64125229059251565 + 0.64127498677751849 + 0.64129768430043577 + 0.64132038316141637 + 0.6413430833606113 + 0.64136578489816765 + 0.64138848777423307 + 0.64141119198895979 + 0.64143389754249669 + 0.64145660443499142 + 0.64147931266659619 + 0.641502022237457 + 0.64152473314772451 + 0.64154744539754638 + 0.64157015898707492 + 0.64159287391645914 + 0.6416155901858468 + 0.64163830779538855 + 0.64166102674523207 + 0.64168374703552999 + 0.641706468666431 + 0.64172919163808173 + 0.64175191595063452 + 0.64177464160423847 + 0.64179736859904279 + 0.6418200969351987 + 0.64184282661285541 + 0.64186555763216058 + 0.64188828999326519 + 0.64191102369631858 + 0.64193375874147185 + 0.64195649512887576 + 0.64197923285867686 + 0.64200197193102748 + 0.64202471234607705 + 0.64204745410397512 + 0.64207019720487135 + 0.64209294164891662 + 0.6421156874362618 + 0.64213843456705355 + 0.64216118304144765 + 0.64218393285958719 + 0.64220668402162828 + 0.64222943652771858 + 0.64225219037800796 + 0.64227494557264586 + 0.64229770211178516 + 0.64232045999557552 + 0.64234321922416482 + 0.64236597979770593 + 0.64238874171634708 + 0.64241150498024246 + 0.64243426958953875 + 0.64245703554438738 + 0.64247980284493789 + 0.64250257149134316 + 0.64252534148375295 + 0.64254811282231561 + 0.64257088550718544 + 0.64259365953851078 + 0.64261643491644149 + 0.64263921164113058 + 0.6426619897127277 + 0.64268476913138128 + 0.64270754989724588 + 0.64273033201046992 + 0.64275311547120462 + 0.64277590027960152 + 0.64279868643581084 + 0.64282147393998235 + 0.64284426279226903 + 0.64286705299282099 + 0.64288984454178977 + 0.64291263743932381 + 0.64293543168557787 + 0.64295822728070029 + 0.64298102422484293 + 0.64300382251815869 + 0.64302662216079465 + 0.6430494231529057 + 0.64307222549464016 + 0.64309502918615158 + 0.64311783422759128 + 0.6431406406191098 + 0.64316344836085559 + 0.64318625745298497 + 0.64320906789564525 + 0.64323187968899109 + 0.64325469283317138 + 0.64327750732833766 + 0.64330032317464358 + 0.6433231403722377 + 0.64334595892127344 + 0.6433687788219028 + 0.64339160007427576 + 0.64341442267854465 + 0.64343724663486102 + 0.64346007194337707 + 0.64348289860424446 + 0.64350572661761218 + 0.6435285559836369 + 0.64355138670246581 + 0.64357421877425258 + 0.6435970521991492 + 0.6436198869773091 + 0.64364272310887982 + 0.64366556059401647 + 0.64368839943287104 + 0.64371123962559429 + 0.6437340811723381 + 0.64375692407325613 + 0.64377976832849904 + 0.64380261393821903 + 0.64382546090256809 + 0.64384830922169844 + 0.64387115889576241 + 0.64389400992491208 + 0.64391686230930112 + 0.64393971604907874 + 0.64396257114439881 + 0.64398542759541366 + 0.64400828540227528 + 0.64403114456513777 + 0.64405400508415023 + 0.64407686695946798 + 0.64409973019124189 + 0.64412259477962441 + 0.6441454607247693 + 0.64416832802682888 + 0.64419119668595271 + 0.64421406670229764 + 0.64423693807601312 + 0.64425981080725303 + 0.6442826848961698 + 0.64430556034291597 + 0.64432843714764565 + 0.64435131531050971 + 0.64437419483166203 + 0.64439707571125371 + 0.64441995794944062 + 0.64444284154637188 + 0.64446572650220324 + 0.64448861281708592 + 0.64451150049117556 + 0.6445343895246215 + 0.64455727991757805 + 0.64458017167019943 + 0.64460306478263663 + 0.64462595925504396 + 0.64464885508757563 + 0.64467175228038132 + 0.64469465083361832 + 0.64471755074743797 + 0.64474045202199115 + 0.64476335465743551 + 0.64478625865392059 + 0.64480916401160249 + 0.64483207073063076 + 0.64485497881116449 + 0.64487788825335179 + 0.64490079905734721 + 0.6449237112233065 + 0.6449466247513812 + 0.64496953964172576 + 0.64499245589449283 + 0.64501537350983562 + 0.64503829248790845 + 0.64506121282886442 + 0.64508413453285962 + 0.64510705760004217 + 0.64512998203057137 + 0.64515290782459878 + 0.64517583498227893 + 0.64519876350376337 + 0.6452216933892081 + 0.64524462463876475 + 0.64526755725258811 + 0.64529049123083404 + 0.64531342657365454 + 0.64533636328120381 + 0.64535930135363551 + 0.64538224079110407 + 0.64540518159376425 + 0.64542812376176928 + 0.64545106729527224 + 0.64547401219442824 + 0.6454969584593917 + 0.64551990609031784 + 0.64554285508735787 + 0.645565805450667 + 0.64558875718040143 + 0.64561171027671316 + 0.6456346647397585 + 0.64565762056969067 + 0.64568057776666332 + 0.64570353633083255 + 0.64572649626235068 + 0.64574945756137381 + 0.64577242022805548 + 0.64579538426255079 + 0.64581834966501306 + 0.64584131643559906 + 0.64586428457446188 + 0.64588725408175707 + 0.64591022495763772 + 0.64593319720225917 + 0.64595617081577639 + 0.64597914579834448 + 0.6460021221501171 + 0.64602509987125101 + 0.64604807896189809 + 0.6460710594222151 + 0.64609404125235737 + 0.64611702445247832 + 0.64614000902273327 + 0.64616299496327756 + 0.64618598227426627 + 0.64620897095585328 + 0.6462319610081968 + 0.64625495243144759 + 0.64627794522576398 + 0.64630093939129829 + 0.64632393492820883 + 0.64634693183664937 + 0.64636993011677402 + 0.6463929297687393 + 0.64641593079269943 + 0.64643893318881118 + 0.64646193695722842 + 0.64648494209810836 + 0.64650794861160454 + 0.64653095649787273 + 0.64655396575706836 + 0.6465769763893483 + 0.64659998839486676 + 0.64662300177377763 + 0.64664601652623965 + 0.64666903265240827 + 0.64669205015243592 + 0.64671506902647979 + 0.64673808927469723 + 0.64676111089724198 + 0.64678413389427158 + 0.64680715826593838 + 0.64683018401240122 + 0.64685321113381578 + 0.64687623963033614 + 0.64689926950211962 + 0.646922300749322 + 0.64694533337209892 + 0.64696836737060637 + 0.64699140274499833 + 0.64701443949543536 + 0.64703747762207009 + 0.64706051712505686 + 0.64708355800455619 + 0.64710660026072386 + 0.64712964389371119 + 0.64715268890368016 + 0.64717573529078376 + 0.64719878305517753 + 0.64722183219701934 + 0.64724488271646652 + 0.6472679346136736 + 0.64729098788879791 + 0.64731404254199409 + 0.64733709857342103 + 0.64736015598323193 + 0.64738321477158711 + 0.64740627493864145 + 0.64742933648454937 + 0.64745239940946986 + 0.64747546371356079 + 0.64749852939697516 + 0.64752159645987206 + 0.64754466490240614 + 0.64756773472473672 + 0.64759080592701845 + 0.6476138785094091 + 0.64763695247206476 + 0.64766002781514309 + 0.64768310453880074 + 0.64770618264319513 + 0.64772926212848114 + 0.64775234299481665 + 0.64777542524235932 + 0.64779850887126578 + 0.64782159388169358 + 0.64784468027379916 + 0.64786776804773916 + 0.64789085720367112 + 0.64791394774175159 + 0.64793703966213878 + 0.64796013296499022 + 0.64798322765046257 + 0.64800632371871081 + 0.64802942116989604 + 0.64805252000417135 + 0.64807562022169996 + 0.64809872182263328 + 0.6481218248071311 + 0.6481449291753516 + 0.6481680349274529 + 0.64819114206358841 + 0.6482142505839209 + 0.64823736048860392 + 0.64826047177779567 + 0.64828358445165579 + 0.64830669851034106 + 0.64832981395400813 + 0.6483529307828152 + 0.64837604899692047 + 0.64839916859648095 + 0.64842228958165449 + 0.64844541195259964 + 0.64846853570947316 + 0.64849166085243348 + 0.64851478738163859 + 0.64853791529724725 + 0.6485610445994161 + 0.64858417528830192 + 0.64860730736406647 + 0.64863044082686327 + 0.648653575676854 + 0.6486767119141954 + 0.64869984953904469 + 0.64872298855156163 + 0.64874612895190342 + 0.64876927074022983 + 0.64879241391669651 + 0.64881555848146344 + 0.64883870443468783 + 0.64886185177652955 + 0.64888500050714593 + 0.64890815062669538 + 0.64893130213533645 + 0.64895445503322657 + 0.64897760932052717 + 0.6490007649973939 + 0.64902392206398574 + 0.64904708052046256 + 0.64907024036698169 + 0.64909340160370166 + 0.64911656423078168 + 0.64913972824838029 + 0.64916289365665603 + 0.6491860604557681 + 0.64920922864587505 + 0.6492323982271373 + 0.64925556919971072 + 0.64927874156375409 + 0.64930191531942794 + 0.64932509046689246 + 0.64934826700630377 + 0.64937144493782362 + 0.6493946242616081 + 0.64941780497781743 + 0.64944098708661246 + 0.64946417058814887 + 0.64948735548258729 + 0.64951054177008827 + 0.64953372945081078 + 0.64955691852491249 + 0.64958010899255225 + 0.64960330085389084 + 0.64962649410908735 + 0.64964968875830087 + 0.64967288480168905 + 0.649696082239414 + 0.6497192810716349 + 0.64974248129850953 + 0.64976568292019843 + 0.64978888593686102 + 0.64981209034865639 + 0.64983529615574531 + 0.64985850335828399 + 0.6498817119564364 + 0.64990492195035865 + 0.64992813334021315 + 0.64995134612615935 + 0.64997456030835643 + 0.64999777588696217 + 0.65002099286213766 + 0.65004421123404521 + 0.65006743100284126 + 0.65009065216868667 + 0.65011387473174242 + 0.65013709869216652 + 0.65016032405012147 + 0.65018355080576662 + 0.65020677895926016 + 0.65023000851076296 + 0.65025323946043623 + 0.65027647180843939 + 0.65029970555493355 + 0.6503229407000769 + 0.65034617724403032 + 0.65036941518695357 + 0.65039265452900952 + 0.65041589527035593 + 0.65043913741115422 + 0.65046238095156406 + 0.65048562589174652 + 0.65050887223186316 + 0.65053211997207017 + 0.65055536911253242 + 0.65057861965340924 + 0.6506018715948606 + 0.65062512493704616 + 0.65064837968012901 + 0.65067163582426712 + 0.65069489336962216 + 0.6507181523163571 + 0.65074141266462837 + 0.65076467441460073 + 0.65078793756643261 + 0.6508112021202852 + 0.65083446807631851 + 0.65085773543469572 + 0.65088100419557671 + 0.65090427435912301 + 0.65092754592549307 + 0.65095081889484985 + 0.650974093267355 + 0.65099736904316874 + 0.65102064622245082 + 0.65104392480536466 + 0.65106720479207014 + 0.65109048618272769 + 0.65111376897749995 + 0.65113705317654758 + 0.65116033878003221 + 0.65118362578811539 + 0.65120691420095567 + 0.65123020401871967 + 0.6512534952415644 + 0.65127678786965171 + 0.6513000819031447 + 0.65132337734220247 + 0.65134667418698955 + 0.65136997243766648 + 0.65139327209439202 + 0.65141657315733259 + 0.65143987562664707 + 0.65146317950249577 + 0.65148648478504367 + 0.65150979147444965 + 0.65153309957087735 + 0.65155640907448686 + 0.65157971998544206 + 0.65160303230390171 + 0.65162634603003078 + 0.65164966116399003 + 0.65167297770594135 + 0.65169629565604692 + 0.65171961501446862 + 0.65174293578136722 + 0.65176625795690624 + 0.65178958154124644 + 0.65181290653455282 + 0.65183623293698301 + 0.65185956074870388 + 0.65188288996987465 + 0.65190622060065873 + 0.6519295526412171 + 0.65195288609171342 + 0.65197622095230834 + 0.65199955722316738 + 0.65202289490444976 + 0.65204623399631934 + 0.65206957449893821 + 0.65209291641246903 + 0.65211625973707221 + 0.6521396044729153 + 0.6521629506201555 + 0.65218629817895879 + 0.65220964714948571 + 0.65223299753190045 + 0.65225634932636534 + 0.65227970253304279 + 0.65230305715209402 + 0.652326413183686 + 0.6523497706279765 + 0.65237312948513293 + 0.65239648975531461 + 0.65241985143868719 + 0.65244321453541021 + 0.65246657904564931 + 0.65248994496956725 + 0.65251331230732668 + 0.65253668105908991 + 0.65256005122502148 + 0.65258342280528403 + 0.65260679580003855 + 0.65263017020945102 + 0.6526535460336842 + 0.65267692327289917 + 0.65270030192726181 + 0.65272368199693487 + 0.65274706348207978 + 0.6527704463828623 + 0.65279383069944519 + 0.65281721643198987 + 0.65284060358066243 + 0.6528639921456254 + 0.652887382127042 + 0.65291077352507487 + 0.65293416633989032 + 0.65295756057164955 + 0.65298095622051722 + 0.65300435328665607 + 0.65302775177023087 + 0.65305115167140304 + 0.65307455299034012 + 0.65309795572720375 + 0.65312135988215847 + 0.65314476545536571 + 0.65316817244699199 + 0.65319158085720008 + 0.65321499068615463 + 0.65323840193402072 + 0.65326181460095811 + 0.65328522868713457 + 0.65330864419271506 + 0.65333206111785946 + 0.65335547946273442 + 0.65337889922750425 + 0.65340232041233259 + 0.65342574301738421 + 0.6534491670428223 + 0.65347259248881173 + 0.65349601935551727 + 0.65351944764310255 + 0.65354287735173222 + 0.65356630848157127 + 0.65358974103278311 + 0.65361317500553118 + 0.65363661039998344 + 0.65366004721630044 + 0.65368348545464994 + 0.65370692511519568 + 0.6537303661981011 + 0.65375380870353117 + 0.6537772526316511 + 0.65380069798262586 + 0.65382414475662054 + 0.6538475929537988 + 0.65387104257432416 + 0.65389449361836327 + 0.65391794608608311 + 0.65394139997764378 + 0.65396485529321391 + 0.65398831203295715 + 0.6540117701970386 + 0.65403522978562201 + 0.65405869079887424 + 0.65408215323696062 + 0.65410561710004478 + 0.65412908238829204 + 0.65415254910186937 + 0.65417601724093899 + 0.65419948680566919 + 0.65422295779622264 + 0.65424643021276596 + 0.65426990405546481 + 0.65429337932448273 + 0.65431685601998701 + 0.65434033414214321 + 0.6543638136911164 + 0.65438729466707091 + 0.65441077707017214 + 0.65443426090058709 + 0.65445774615848129 + 0.6544812328440206 + 0.65450472095736867 + 0.65452821049869281 + 0.65455170146815722 + 0.65457519386593044 + 0.65459868769217511 + 0.65462218294705987 + 0.65464567963074749 + 0.65466917774340672 + 0.65469267728519998 + 0.65471617825629802 + 0.65473968065686328 + 0.65476318448706139 + 0.65478668974706145 + 0.65481019643702598 + 0.6548337045571242 + 0.65485721410751851 + 0.65488072508837958 + 0.65490423749986848 + 0.65492775134215597 + 0.65495126661540615 + 0.65497478331978676 + 0.65499830145546045 + 0.65502182102259798 + 0.65504534202136344 + 0.65506886445192314 + 0.65509238831444438 + 0.65511591360909194 + 0.65513944033603477 + 0.6551629684954372 + 0.65518649808746721 + 0.65521002911229054 + 0.65523356157007351 + 0.65525709546098365 + 0.65528063078518883 + 0.65530416754285192 + 0.65532770573414389 + 0.65535124535922917 + 0.65537478641827407 + 0.65539832891144645 + 0.6554218728389124 + 0.65544541820084135 + 0.65546896499739804 + 0.6554925132287488 + 0.65551606289506126 + 0.65553961399650351 + 0.6555631665332402 + 0.65558672050544242 + 0.65561027591327337 + 0.65563383275690268 + 0.65565739103649501 + 0.65568095075221999 + 0.65570451190424239 + 0.65572807449273363 + 0.65575163851785667 + 0.6557752039797814 + 0.65579877087867411 + 0.65582233921470312 + 0.65584590898803319 + 0.65586948019883562 + 0.65589305284727539 + 0.65591662693352071 + 0.65594020245773965 + 0.65596377942009898 + 0.65598735782076512 + 0.65601093765990948 + 0.65603451893769571 + 0.65605810165429512 + 0.65608168580987114 + 0.65610527140459551 + 0.65612885843863467 + 0.65615244691215546 + 0.65617603682532766 + 0.65619962817831823 + 0.65622322097129382 + 0.65624681520442452 + 0.65627041087787719 + 0.65629400799181992 + 0.65631760654642157 + 0.65634120654184869 + 0.65636480797827002 + 0.65638841085585531 + 0.6564120151747701 + 0.65643562093518448 + 0.65645922813726698 + 0.65648283678118291 + 0.65650644686710558 + 0.65653005839519907 + 0.65655367136563325 + 0.65657728577857533 + 0.65660090163419549 + 0.65662451893266227 + 0.65664813767414454 + 0.6566717578588076 + 0.65669537948682521 + 0.65671900255836102 + 0.65674262707358388 + 0.65676625303266734 + 0.65678988043577535 + 0.65681350928308002 + 0.65683713957474676 + 0.65686077131094611 + 0.65688440449184693 + 0.65690803911761797 + 0.6569316751884281 + 0.65695531270444629 + 0.65697895166584297 + 0.65700259207278389 + 0.65702623392543968 + 0.65704987722398067 + 0.65707352196857294 + 0.6570971681593899 + 0.65712081579659609 + 0.65714446488036338 + 0.65716811541086129 + 0.65719176738825835 + 0.65721542081272233 + 0.65723907568442397 + 0.6572627320035338 + 0.65728638977021936 + 0.6573100489846514 + 0.657333709646996 + 0.65735737175742859 + 0.65738103531611358 + 0.65740470032322174 + 0.65742836677892402 + 0.65745203468338775 + 0.65747570403678579 + 0.65749937483928556 + 0.65752304709105802 + 0.65754672079227094 + 0.65757039594309497 + 0.65759407254370139 + 0.65761775059425764 + 0.65764143009493337 + 0.65766511104590264 + 0.65768879344733155 + 0.65771247729938964 + 0.65773616260224965 + 0.65775984935608078 + 0.65778353756105101 + 0.65780722721733309 + 0.65783091832509499 + 0.65785461088450914 + 0.65787830489574384 + 0.65790200035896984 + 0.65792569727435712 + 0.65794939564207666 + 0.65797309546229965 + 0.65799679673519407 + 0.65802049946092978 + 0.65804420363968097 + 0.65806790927161585 + 0.65809161635690405 + 0.65811532489571867 + 0.65813903488822745 + 0.65816274633460214 + 0.65818645923501373 + 0.65821017358963241 + 0.65823388939862759 + 0.65825760666217237 + 0.6582813253804366 + 0.65830504555359026 + 0.65832876718180466 + 0.65835249026525122 + 0.65837621480409991 + 0.65839994079852238 + 0.65842366824868837 + 0.6584473971547693 + 0.65847112751693715 + 0.658494859335363 + 0.65851859261021561 + 0.65854232734166973 + 0.65856606352989344 + 0.65858980117505894 + 0.65861354027733743 + 0.65863728083689921 + 0.65866102285391759 + 0.65868476632856099 + 0.65870851126100427 + 0.65873225765141452 + 0.65875600549996827 + 0.65877975480683248 + 0.65880350557218048 + 0.65882725779618423 + 0.65885101147901382 + 0.65887476662084277 + 0.65889852322183973 + 0.65892228128217978 + 0.65894604080203156 + 0.65896980178156861 + 0.65899356422096145 + 0.65901732812038327 + 0.65904109348000472 + 0.65906486029999922 + 0.65908862858053563 + 0.65911239832178781 + 0.65913616952392728 + 0.65915994218712504 + 0.65918371631155581 + 0.65920749189739047 + 0.65923126894479778 + 0.65925504745395458 + 0.65927882742503008 + 0.6593026088581978 + 0.65932639175362995 + 0.65935017611149715 + 0.65937396193197162 + 0.65939774921522853 + 0.65942153796143732 + 0.65944532817077173 + 0.65946911984340384 + 0.65949291297950607 + 0.65951670757924918 + 0.65954050364280858 + 0.65956430117035669 + 0.65958810016206249 + 0.65961190061810182 + 0.65963570253864534 + 0.65965950592386713 + 0.65968331077393949 + 0.65970711708903507 + 0.65973092486932594 + 0.65975473411498664 + 0.65977854482618781 + 0.65980235700310197 + 0.65982617064590487 + 0.65984998575476739 + 0.65987380232986392 + 0.65989762037136523 + 0.65992143987944563 + 0.65994526085427752 + 0.65996908329603388 + 0.65999290720489034 + 0.66001673258101634 + 0.66004055942458784 + 0.66006438773577591 + 0.66008821751475655 + 0.66011204876170071 + 0.66013588147678148 + 0.66015971566017284 + 0.66018355131204942 + 0.6602073884325822 + 0.66023122702194592 + 0.66025506708031645 + 0.66027890860786176 + 0.66030275160476115 + 0.66032659607118294 + 0.66035044200730453 + 0.66037428941329912 + 0.66039813828933769 + 0.66042198863559676 + 0.66044584045225085 + 0.66046969373947106 + 0.6604935484974308 + 0.66051740472630605 + 0.66054126242626998 + 0.66056512159749536 + 0.66058898224015894 + 0.66061284435443191 + 0.6606367079404889 + 0.660660572998505 + 0.66068443952865474 + 0.66070830753110799 + 0.66073217700604447 + 0.66075604795363418 + 0.66077992037405353 + 0.66080379426747737 + 0.66082766963407724 + 0.66085154647402977 + 0.66087542478750805 + 0.66089930457468726 + 0.66092318583574039 + 0.6609470685708444 + 0.66097095278017071 + 0.6609948384638975 + 0.6610187256221951 + 0.66104261425524169 + 0.66106650436320913 + 0.66109039594627406 + 0.66111428900460978 + 0.66113818353839149 + 0.66116207954779427 + 0.66118597703299187 + 0.66120987599416214 + 0.66123377643147585 + 0.66125767834510951 + 0.66128158173523854 + 0.66130548660203792 + 0.66132939294568138 + 0.66135330076634558 + 0.66137721006420291 + 0.66140112083943159 + 0.66142503309220535 + 0.6614489468226995 + 0.66147286203108957 + 0.66149677871755053 + 0.66152069688225479 + 0.66154461652538243 + 0.66156853764710555 + 0.66159246024760143 + 0.66161638432704373 + 0.66164030988560951 + 0.66166423692347265 + 0.66168816544080855 + 0.66171209543779463 + 0.66173602691460431 + 0.66175995987141512 + 0.66178389430840079 + 0.66180783022573852 + 0.6618317676236023 + 0.66185570650217118 + 0.6618796468616156 + 0.6619035887021163 + 0.66192753202384713 + 0.66195147682698219 + 0.66197542311170054 + 0.66199937087817762 + 0.66202332012658638 + 0.6620472708571068 + 0.66207122306991195 + 0.66209517676517893 + 0.66211913194308358 + 0.66214308860380333 + 0.66216704674751092 + 0.66219100637438677 + 0.6622149674846054 + 0.66223893007834089 + 0.66226289415577411 + 0.66228685971707768 + 0.66231082676242914 + 0.6623347952920029 + 0.66235876530597959 + 0.66238273680453374 + 0.66240670978783978 + 0.66243068425607698 + 0.66245466020942112 + 0.66247863764804693 + 0.6625026165721335 + 0.66252659698185712 + 0.66255057887739377 + 0.6625745622589212 + 0.66259854712661403 + 0.66262253348065148 + 0.66264652132120827 + 0.66267051064846383 + 0.66269450146259268 + 0.66271849376377268 + 0.66274248755218168 + 0.66276648282799444 + 0.66279047959139037 + 0.66281447784254577 + 0.66283847758163694 + 0.66286247880884042 + 0.66288648152433716 + 0.66291048572830047 + 0.66293449142090821 + 0.66295849860233846 + 0.66298250727276931 + 0.66300651743237726 + 0.66303052908134019 + 0.66305454221983307 + 0.66307855684803729 + 0.66310257296612773 + 0.66312659057428247 + 0.6631506096726798 + 0.66317463026149448 + 0.66319865234090813 + 0.66322267591109729 + 0.66324670097223692 + 0.66327072752450844 + 0.66329475556808715 + 0.66331878510315256 + 0.66334281612988022 + 0.66336684864844964 + 0.66339088265903789 + 0.66341491816182463 + 0.6634389551569867 + 0.66346299364470118 + 0.66348703362514772 + 0.66351107509850338 + 0.66353511806494636 + 0.66355916252465696 + 0.66358320847780883 + 0.66360725592458347 + 0.66363130486515964 + 0.66365535529971253 + 0.663679407228424 + 0.66370346065146923 + 0.66372751556902865 + 0.66375157198128065 + 0.66377562988840244 + 0.66379968929057409 + 0.66382375018797279 + 0.66384781258077863 + 0.66387187646916745 + 0.66389594185332079 + 0.66392000873341439 + 0.66394407710963022 + 0.66396814698214535 + 0.66399221835113853 + 0.66401629121678873 + 0.66404036557927471 + 0.66406444143877352 + 0.66408851879546904 + 0.66411259764953534 + 0.66413667800115284 + 0.66416075985050183 + 0.6641848431977585 + 0.66420892804310627 + 0.66423301438672111 + 0.66425710222878176 + 0.66428119156946897 + 0.66430528240896181 + 0.66432937474743925 + 0.66435346858508026 + 0.66437756392206559 + 0.66440166075857132 + 0.66442575909477941 + 0.66444985893086927 + 0.66447396026701977 + 0.66449806310341208 + 0.66452216744022186 + 0.66454627327763305 + 0.66457038061582185 + 0.66459448945496913 + 0.66461859979525573 + 0.66464271163686073 + 0.66466682497996188 + 0.66469093982474037 + 0.66471505617137838 + 0.66473917402005223 + 0.66476329337094442 + 0.66478741422423115 + 0.66481153658009673 + 0.66483566043871878 + 0.66485978580027683 + 0.6648839126649535 + 0.66490804103292678 + 0.66493217090437606 + 0.66495630227948399 + 0.66498043515842864 + 0.66500456954139098 + 0.66502870542855241 + 0.66505284282009236 + 0.66507698171619034 + 0.66510112211702621 + 0.66512526402278416 + 0.66514940743364082 + 0.66517355234977737 + 0.66519769877137669 + 0.6652218466986155 + 0.6652459961316779 + 0.66527014707074084 + 0.66529429951599028 + 0.66531845346760121 + 0.6653426089257567 + 0.66536676589063981 + 0.66539092436242708 + 0.66541508434130314 + 0.6654392458274464 + 0.66546340882103971 + 0.66548757332226005 + 0.66551173933129359 + 0.66553590684831876 + 0.66556007587351707 + 0.66558424640706848 + 0.66560841844915475 + 0.66563259199995717 + 0.66565676705965926 + 0.66568094362843777 + 0.66570512170647622 + 0.66572930129395747 + 0.66575348239105869 + 0.66577766499796465 + 0.6658018491148574 + 0.66582603474191515 + 0.66585022187932164 + 0.66587441052725838 + 0.66589860068590567 + 0.66592279235544538 + 0.66594698553605947 + 0.66597118022793123 + 0.66599537643123941 + 0.66601957414616597 + 0.666043773372896 + 0.66606797411160668 + 0.66609217636248308 + 0.66611638012570573 + 0.66614058540145671 + 0.66616479218991942 + 0.66618900049127427 + 0.66621321030570357 + 0.66623742163338773 + 0.66626163447451181 + 0.66628584882925657 + 0.66631006469780407 + 0.66633428208033663 + 0.66635850097703453 + 0.66638272138808319 + 0.66640694331366501 + 0.66643116675395897 + 0.6664553917091488 + 0.66647961817942003 + 0.66650384616495029 + 0.66652807566592476 + 0.66655230668252441 + 0.66657653921493476 + 0.66660077326333478 + 0.66662500882790854 + 0.66664924590884023 + 0.66667348450631037 + 0.66669772462050159 + 0.66672196625159941 + 0.66674620939978313 + 0.66677045406523683 + 0.6667947002481448 + 0.66681894794868768 + 0.66684319716705132 + 0.66686744790341512 + 0.66689170015796484 + 0.66691595393088154 + 0.6669402092223492 + 0.66696446603255244 + 0.66698872436167189 + 0.66701298420989208 + 0.66703724557739574 + 0.6670615084643654 + 0.66708577287098703 + 0.66711003879744191 + 0.66713430624391257 + 0.66715857521058375 + 0.66718284569763953 + 0.66720711770526109 + 0.66723139123363473 + 0.66725566628294164 + 0.66727994285336623 + 0.66730422094509301 + 0.66732850055830484 + 0.66735278169318468 + 0.66737706434991884 + 0.66740134852868682 + 0.66742563422967671 + 0.66744992145306958 + 0.66747421019904873 + 0.66749850046780179 + 0.66752279225950895 + 0.66754708557435616 + 0.66757138041252662 + 0.66759567677420506 + 0.66761997465957623 + 0.66764427406882176 + 0.66766857500212795 + 0.66769287745967631 + 0.66771718144165493 + 0.66774148694824553 + 0.66776579397963276 + 0.66779010253600168 + 0.6678144126175356 + 0.66783872422442081 + 0.66786303735683916 + 0.66788735201497729 + 0.66791166819901837 + 0.6679359859091476 + 0.66796030514554816 + 0.66798462590840835 + 0.66800894819790835 + 0.66803327201423512 + 0.66805759735757497 + 0.66808192422810997 + 0.66810625262602519 + 0.6681305825515057 + 0.66815491400473837 + 0.66817924698590514 + 0.66820358149519288 + 0.66822791753278654 + 0.66825225509886998 + 0.66827659419362995 + 0.66830093481725017 + 0.66832527696991584 + 0.66834962065181236 + 0.66837396586312503 + 0.66839831260403915 + 0.66842266087474 + 0.66844701067541312 + 0.6684713620062438 + 0.66849571486741599 + 0.66852006925911656 + 0.6685444251815309 + 0.66856878263484643 + 0.66859314161924521 + 0.66861750213491422 + 0.66864186418203764 + 0.66866622776080409 + 0.66869059287139754 + 0.66871495951400362 + 0.66873932768880795 + 0.66876369739599761 + 0.66878806863575679 + 0.66881244140827112 + 0.66883681571372944 + 0.66886119155231427 + 0.66888556892421469 + 0.66890994782961466 + 0.66893432826869981 + 0.66895871024165621 + 0.6689830937486726 + 0.66900747878993339 + 0.66903186536562276 + 0.66905625347593123 + 0.66908064312104165 + 0.66910503430114143 + 0.66912942701641642 + 0.66915382126705436 + 0.66917821705324088 + 0.66920261437516071 + 0.66922701323300426 + 0.66925141362695295 + 0.66927581555719928 + 0.66930021902392434 + 0.66932462402731907 + 0.66934903056756789 + 0.66937343864485688 + 0.66939784825937543 + 0.66942225941130651 + 0.6694466721008393 + 0.66947108632816177 + 0.6694955020934602 + 0.66951991939691891 + 0.66954433823872739 + 0.66956875861907206 + 0.66959318053814065 + 0.66961760399611958 + 0.66964202899319514 + 0.66966645552955517 + 0.66969088360538598 + 0.66971531322087741 + 0.66973974437621542 + 0.66976417707158686 + 0.66978861130717771 + 0.66981304708317813 + 0.66983748439977409 + 0.66986192325715244 + 0.66988636365550269 + 0.66991080559500971 + 0.66993524907586344 + 0.66995969409825029 + 0.6699841406623569 + 0.67000858876837299 + 0.67003303841648687 + 0.67005748960688205 + 0.67008194233975138 + 0.67010639661527993 + 0.67013085243365478 + 0.67015530979506699 + 0.67017976869970186 + 0.6702042291477478 + 0.67022869113939321 + 0.6702531546748246 + 0.67027761975423406 + 0.67030208637780631 + 0.67032655454572865 + 0.67035102425819237 + 0.67037549551538456 + 0.67039996831749216 + 0.6704244426647068 + 0.67044891855721223 + 0.67047339599520017 + 0.67049787497885782 + 0.67052235550837358 + 0.67054683758393618 + 0.67057132120573415 + 0.67059580637395622 + 0.67062029308879101 + 0.67064478135042738 + 0.67066927115905228 + 0.67069376251485779 + 0.67071825541802921 + 0.67074274986875726 + 0.67076724586723058 + 0.67079174341363634 + 0.67081624250816674 + 0.67084074315100717 + 0.67086524534234981 + 0.67088974908238219 + 0.67091425437129137 + 0.6709387612092711 + 0.67096326959650565 + 0.67098777953318711 + 0.67101229101950444 + 0.67103680405564514 + 0.67106131864179985 + 0.67108583477815908 + 0.67111035246491035 + 0.67113487170224284 + 0.67115939249034728 + 0.67118391482941264 + 0.67120843871962976 + 0.67123296416118461 + 0.67125749115426969 + 0.67128201969907386 + 0.67130654979578674 + 0.67133108144459741 + 0.67135561464569837 + 0.67138014939927548 + 0.67140468570552003 + 0.67142922356462253 + 0.67145376297677428 + 0.67147830394216124 + 0.67150284646097613 + 0.67152739053340982 + 0.67155193615965025 + 0.67157648333988662 + 0.67160103207431199 + 0.67162558236311554 + 0.67165013420648678 + 0.67167468760461535 + 0.67169924255769387 + 0.67172379906590896 + 0.67174835712945469 + 0.67177291674851913 + 0.67179747792329347 + 0.67182204065396922 + 0.67184660494073412 + 0.67187117078378111 + 0.67189573818330006 + 0.67192030713948214 + 0.67194487765251698 + 0.67196944972259454 + 0.67199402334990777 + 0.67201859853464629 + 0.67204317527700008 + 0.67206775357716064 + 0.67209233343531927 + 0.67211691485166736 + 0.6721414978263951 + 0.67216608235969377 + 0.67219066845175335 + 0.67221525610276545 + 0.67223984531292158 + 0.67226443608241182 + 0.67228902841142912 + 0.67231362230016378 + 0.67233821774880742 + 0.67236281475755011 + 0.67238741332658347 + 0.6724120134561008 + 0.67243661514629238 + 0.67246121839734807 + 0.67248582320945982 + 0.67251042958282115 + 0.67253503751762211 + 0.67255964701405613 + 0.67258425807231181 + 0.67260887069258435 + 0.67263348487506081 + 0.67265810061993614 + 0.67268271792740253 + 0.67270733679765027 + 0.67273195723087109 + 0.67275657922725884 + 0.67278120278700382 + 0.67280582791029797 + 0.67283045459733515 + 0.67285508284830553 + 0.67287971266339985 + 0.6729043440428133 + 0.67292897698673659 + 0.67295361149536326 + 0.67297824756888391 + 0.67300288520749085 + 0.6730275244113777 + 0.67305216518073518 + 0.67307680751575716 + 0.67310145141663591 + 0.67312609688356217 + 0.67315074391673124 + 0.67317539251633396 + 0.67320004268256117 + 0.67322469441560995 + 0.67324934771566936 + 0.67327400258293357 + 0.67329865901759511 + 0.67332331701984616 + 0.67334797658988099 + 0.67337263772789036 + 0.67339730043406831 + 0.67342196470860927 + 0.67344663055170384 + 0.67347129796354643 + 0.6734959669443279 + 0.67352063749424573 + 0.67354530961348769 + 0.67356998330225271 + 0.67359465856072898 + 0.67361933538911045 + 0.67364401378759475 + 0.67366869375637006 + 0.67369337529563189 + 0.67371805840557486 + 0.67374274308639015 + 0.67376742933827194 + 0.67379211716141496 + 0.67381680655601039 + 0.67384149752225408 + 0.67386619006033921 + 0.67389088417046006 + 0.67391557985280803 + 0.67394027710757787 + 0.67396497593496529 + 0.67398967633516049 + 0.6740143783083612 + 0.6740390818547588 + 0.67406378697454772 + 0.67408849366792301 + 0.67411320193507751 + 0.67413791177620586 + 0.67416262319150155 + 0.67418733618116056 + 0.67421205074537305 + 0.67423676688433853 + 0.67426148459824697 + 0.67428620388729499 + 0.67431092475167564 + 0.6743356471915839 + 0.67436037120721459 + 0.67438509679876113 + 0.67440982396641991 + 0.67443455271038266 + 0.67445928303084624 + 0.67448401492800514 + 0.67450874840205177 + 0.67453348345318387 + 0.6745582200815935 + 0.67458295828747739 + 0.67460769807102883 + 0.67463243943244477 + 0.67465718237191852 + 0.67468192688964557 + 0.67470667298581888 + 0.67473142066063596 + 0.67475616991429144 + 0.67478092074698104 + 0.6748056731588965 + 0.67483042715023633 + 0.67485518272119582 + 0.67487993987196726 + 0.67490469860274893 + 0.67492945891373324 + 0.67495422080512013 + 0.67497898427710046 + 0.67500374932987095 + 0.67502851596362723 + 0.67505328417856791 + 0.67507805397488208 + 0.67510282535277166 + 0.67512759831242719 + 0.67515237285404939 + 0.67517714897783021 + 0.6752019266839655 + 0.67522670597265233 + 0.67525148684408798 + 0.67527626929846485 + 0.67530105333598178 + 0.67532583895683129 + 0.675350626161214 + 0.67537541494932218 + 0.67540020532135336 + 0.67542499727750338 + 0.6754497908179693 + 0.67547458594294563 + 0.67549938265263132 + 0.675524180947219 + 0.67554898082690762 + 0.67557378229189158 + 0.67559858534237016 + 0.67562338997853733 + 0.67564819620058925 + 0.67567300400872521 + 0.67569781340313917 + 0.67572262438402764 + 0.6757474369515879 + 0.6757722511060178 + 0.67579706684751173 + 0.67582188417627065 + 0.67584670309248562 + 0.67587152359635627 + 0.67589634568808032 + 0.67592116936785374 + 0.67594599463587302 + 0.67597082149233734 + 0.67599564993743977 + 0.67602047997138137 + 0.67604531159435532 + 0.6760701448065628 + 0.6760949796081982 + 0.67611981599945969 + 0.67614465398054513 + 0.67616949355165101 + 0.67619433471297374 + 0.67621917746471283 + 0.67624402180706467 + 0.67626886774022754 + 0.67629371526439619 + 0.67631856437977023 + 0.67634341508654805 + 0.67636826738492595 + 0.67639312127510232 + 0.67641797675727333 + 0.67644283383163772 + 0.67646769249839334 + 0.67649255275773867 + 0.6765174146098718 + 0.67654227805498801 + 0.67656714309328858 + 0.6765920097249688 + 0.67661687795022862 + 0.67664174776926478 + 0.676666619182274 + 0.67669149218945956 + 0.67671636679101366 + 0.67674124298713756 + 0.67676612077803011 + 0.67679100016388816 + 0.67681588114491165 + 0.67684076372129609 + 0.67686564789324155 + 0.6768905336609482 + 0.67691542102461133 + 0.67694030998443311 + 0.67696520054060716 + 0.67699009269333688 + 0.67701498644281954 + 0.67703988178925212 + 0.67706477873283488 + 0.67708967727376668 + 0.67711457741224468 + 0.67713947914847084 + 0.67716438248264088 + 0.6771892874149551 + 0.677214193945614 + 0.67723910207481308 + 0.67726401180275486 + 0.67728892312963618 + 0.6773138360556562 + 0.67733875058101722 + 0.67736366670591475 + 0.6773885844305495 + 0.67741350375512055 + 0.67743842467982684 + 0.67746334720486912 + 0.67748827133044642 + 0.67751319705675628 + 0.67753812438400085 + 0.67756305331237798 + 0.67758798384208818 + 0.67761291597333073 + 0.67763784970630658 + 0.67766278504121147 + 0.67768772197824956 + 0.67771266051761703 + 0.67773760065951794 + 0.67776254240414824 + 0.67778748575171066 + 0.67781243070240305 + 0.67783737725642601 + 0.67786232541398084 + 0.67788727517526526 + 0.67791222654048189 + 0.67793717950982857 + 0.67796213408350814 + 0.67798709026171833 + 0.67801204804466031 + 0.67803700743253359 + 0.67806196842554101 + 0.67808693102388062 + 0.67811189522775517 + 0.67813686103736093 + 0.67816182845290252 + 0.67818679747457955 + 0.6782117681025901 + 0.67823674033713877 + 0.67826171417842518 + 0.67828668962664762 + 0.67831166668200726 + 0.67833664534470894 + 0.67836162561494917 + 0.678386607492931 + 0.67841159097885262 + 0.67843657607291885 + 0.67846156277532943 + 0.67848655108628275 + 0.67851154100598365 + 0.67853653253463198 + 0.67856152567242778 + 0.67858652041957424 + 0.67861151677626974 + 0.67863651474271769 + 0.6786615143191197 + 0.67868651550567582 + 0.67871151830258936 + 0.6787365227100588 + 0.6787615287282891 + 0.6787865363574791 + 0.67881154559783197 + 0.67883655644954954 + 0.67886156891283045 + 0.67888658298787996 + 0.67891159867489803 + 0.67893661597408672 + 0.67896163488564976 + 0.67898665540978553 + 0.67901167754669944 + 0.67903670129659033 + 0.67906172665966158 + 0.67908675363611704 + 0.67911178222615542 + 0.67913681242998047 + 0.67916184424779424 + 0.67918687767980068 + 0.6792119127261983 + 0.67923694938719292 + 0.67926198766298473 + 0.67928702755377623 + 0.67931206905977104 + 0.67933711218117154 + 0.67936215691817825 + 0.679387203270997 + 0.67941225123982651 + 0.67943730082487264 + 0.67946235202633576 + 0.67948740484442027 + 0.67951245927932824 + 0.67953751533126228 + 0.67956257300042466 + 0.67958763228701968 + 0.67961269319124962 + 0.67963775571331708 + 0.67966281985342469 + 0.67968788561177806 + 0.67971295298857493 + 0.67973802198402422 + 0.67976309259832557 + 0.67978816483168314 + 0.6798132386843011 + 0.67983831415638052 + 0.67986339124812756 + 0.67988846995974461 + 0.67991355029143297 + 0.67993863224339857 + 0.67996371581584425 + 0.67998880100897274 + 0.68001388782298677 + 0.68003897625809273 + 0.68006406631449312 + 0.68008915799239122 + 0.6801142512919911 + 0.68013934621349603 + 0.68016444275711041 + 0.68018954092303718 + 0.68021464071148263 + 0.68023974212264837 + 0.68026484515673868 + 0.68028994981395685 + 0.68031505609451071 + 0.68034016399859853 + 0.68036527352642995 + 0.68039038467820645 + 0.68041549745413277 + 0.68044061185441207 + 0.68046572787925086 + 0.68049084552885097 + 0.68051596480342003 + 0.68054108570316008 + 0.68056620822827407 + 0.68059133237897218 + 0.68061645815545424 + 0.68064158555792376 + 0.68066671458659045 + 0.68069184524165605 + 0.68071697752332416 + 0.68074211143180141 + 0.68076724696729107 + 0.68079238413000176 + 0.68081752292013364 + 0.680842663337895 + 0.68086780538348946 + 0.68089294905712061 + 0.68091809435899686 + 0.68094324128932027 + 0.68096838984829922 + 0.68099354003613577 + 0.68101869185303543 + 0.68104384529920481 + 0.68106900037484952 + 0.68109415708017296 + 0.68111931541538417 + 0.68114447538068501 + 0.68116963697628263 + 0.68119480020238266 + 0.68121996505918858 + 0.68124513154690935 + 0.68127029966574726 + 0.6812954694159109 + 0.68132064079760446 + 0.68134581381103498 + 0.68137098845640653 + 0.68139616473392617 + 0.68142134264379961 + 0.68144652218623269 + 0.68147170336143081 + 0.68149688616960169 + 0.6815220706109506 + 0.68154725668568195 + 0.68157244439400477 + 0.68159763373612459 + 0.681622824712246 + 0.68164801732257618 + 0.68167321156732275 + 0.68169840744668975 + 0.68172360496088491 + 0.68174880411011574 + 0.68177400489458651 + 0.68179920731450472 + 0.68182441137007987 + 0.68184961706151292 + 0.6818748243890147 + 0.68190003335279148 + 0.68192524395304766 + 0.68195045618999217 + 0.68197567006383353 + 0.6820008855747739 + 0.68202610272302311 + 0.68205132150879044 + 0.68207654193227729 + 0.68210176399369626 + 0.68212698769325042 + 0.68215221303114937 + 0.68217744000759939 + 0.68220266862280821 + 0.68222789887698077 + 0.68225313077032834 + 0.68227836430305533 + 0.68230359947537023 + 0.68232883628748064 + 0.68235407473959331 + 0.68237931483191616 + 0.68240455656465737 + 0.68242979993802522 + 0.68245504495222431 + 0.68248029160746482 + 0.68250553990395446 + 0.68253078984189863 + 0.68255604142150861 + 0.68258129464299122 + 0.68260654950655297 + 0.68263180601240214 + 0.68265706416074867 + 0.68268232395179951 + 0.68270758538576126 + 0.68273284846284388 + 0.6827581131832543 + 0.68278337954720247 + 0.68280864755489523 + 0.68283391720654285 + 0.68285918850234872 + 0.68288446144252646 + 0.68290973602728289 + 0.68293501225682662 + 0.68296029013136617 + 0.68298556965110857 + 0.68301085081626411 + 0.68303613362704141 + 0.68306141808364917 + 0.68308670418629458 + 0.68311199193518768 + 0.68313728133053764 + 0.6831625723725514 + 0.6831878650614408 + 0.68321315939741334 + 0.68323845538067773 + 0.68326375301144437 + 0.68328905228992065 + 0.68331435321631551 + 0.68333965579083933 + 0.68336496001370117 + 0.68339026588510998 + 0.68341557340527637 + 0.68344088257440772 + 0.68346619339271297 + 0.68349150586040464 + 0.68351681997768832 + 0.68354213574477651 + 0.6835674531618785 + 0.68359277222920145 + 0.68361809294695963 + 0.68364341531535722 + 0.68366873933460848 + 0.68369406500491925 + 0.68371939232650203 + 0.68374472129956787 + 0.68377005192432427 + 0.68379538420098063 + 0.6838207181297481 + 0.68384605371083729 + 0.68387139094445781 + 0.68389672983082062 + 0.68392207037013375 + 0.68394741256260805 + 0.68397275640845623 + 0.68399810190788635 + 0.68402344906110779 + 0.6840487978683335 + 0.68407414832977276 + 0.68409950044563539 + 0.68412485421613267 + 0.68415020964147566 + 0.68417556672187407 + 0.6842009254575393 + 0.68422628584868095 + 0.68425164789551063 + 0.68427701159823928 + 0.68430237695707685 + 0.68432774397223495 + 0.68435311264392473 + 0.6843784829723546 + 0.68440385495773914 + 0.68442922860028832 + 0.68445460390021207 + 0.68447998085772177 + 0.68450535947302926 + 0.68453073974634759 + 0.68455612167788338 + 0.68458150526785189 + 0.68460689051646273 + 0.68463227742392785 + 0.68465766599045896 + 0.68468305621626591 + 0.68470844810156395 + 0.68473384164656004 + 0.68475923685146889 + 0.68478463371649922 + 0.68481003224186632 + 0.68483543242778189 + 0.68486083427445454 + 0.6848862377820979 + 0.68491164295092366 + 0.68493704978114245 + 0.68496245827296931 + 0.68498786842661463 + 0.68501328024228891 + 0.68503869372020743 + 0.68506410886057889 + 0.68508952566361869 + 0.68511494412953566 + 0.68514036425854674 + 0.68516578605085932 + 0.68519120950668899 + 0.68521663462624594 + 0.68524206140974431 + 0.68526748985739627 + 0.68529291996941388 + 0.68531835174600986 + 0.6853437851873978 + 0.68536922029379022 + 0.68539465706539759 + 0.68542009550243588 + 0.6854455356051139 + 0.68547097737364926 + 0.68549642080825113 + 0.685521865909135 + 0.68554731267651192 + 0.68557276111059595 + 0.6855982112115997 + 0.68562366297973565 + 0.68564911641521975 + 0.68567457151826117 + 0.68570002828907595 + 0.68572548672787836 + 0.68575094683487769 + 0.68577640861029165 + 0.68580187205432974 + 0.68582733716720934 + 0.68585280394914183 + 0.68587827240033994 + 0.6859037425210196 + 0.68592921431139209 + 0.68595468777167212 + 0.68598016290207553 + 0.68600563970281203 + 0.6860311181740979 + 0.68605659831614763 + 0.68608208012917249 + 0.68610756361339054 + 0.68613304876901293 + 0.68615853559625295 + 0.68618402409532675 + 0.68620951426644572 + 0.68623500610982813 + 0.68626049962568525 + 0.6862859948142318 + 0.68631149167568284 + 0.68633699021025307 + 0.68636249041815556 + 0.68638799229960534 + 0.68641349585481726 + 0.68643900108400624 + 0.68646450798738556 + 0.68649001656516861 + 0.68651552681757533 + 0.68654103874481553 + 0.68656655234710451 + 0.68659206762465896 + 0.68661758457769395 + 0.68664310320642274 + 0.68666862351106062 + 0.68669414549182262 + 0.6867196691489259 + 0.68674519448258009 + 0.68677072149300755 + 0.68679625018041845 + 0.68682178054502951 + 0.68684731258705445 + 0.68687284630671186 + 0.68689838170421391 + 0.68692391877977732 + 0.68694945753361947 + 0.68697499796595207 + 0.68700054007699252 + 0.68702608386695607 + 0.68705162933606156 + 0.68707717648451783 + 0.6871027253125469 + 0.68712827582036118 + 0.68715382800817781 + 0.68717938187621397 + 0.68720493742468192 + 0.68723049465379915 + 0.68725605356378272 + 0.68728161415484823 + 0.68730717642721162 + 0.68733274038109016 + 0.68735830601669634 + 0.68738387333425066 + 0.68740944233396761 + 0.68743501301606247 + 0.68746058538075328 + 0.68748615942825542 + 0.68751173515878516 + 0.68753731257255968 + 0.68756289166979678 + 0.68758847245071064 + 0.68761405491551741 + 0.68763963906443615 + 0.68766522489768289 + 0.6876908124154737 + 0.68771640161802639 + 0.6877419925055569 + 0.68776758507828317 + 0.68779317933641937 + 0.68781877528018687 + 0.68784437290979827 + 0.68786997222547497 + 0.68789557322742978 + 0.6879211759158822 + 0.68794678029105016 + 0.68797238635315006 + 0.68799799410239804 + 0.68802360353901226 + 0.68804921466321212 + 0.68807482747521242 + 0.68810044197523146 + 0.68812605816348693 + 0.68815167604019556 + 0.68817729560557706 + 0.68820291685984614 + 0.6882285398032244 + 0.68825416443592657 + 0.68827979075817103 + 0.68830541877017593 + 0.68833104847215787 + 0.68835667986433857 + 0.68838231294693109 + 0.68840794772015723 + 0.68843358418423373 + 0.68845922233937884 + 0.68848486218580951 + 0.68851050372374722 + 0.68853614695340548 + 0.6885617918750061 + 0.68858743848876769 + 0.68861308679490696 + 0.68863873679364251 + 0.68866438848519274 + 0.68869004186977811 + 0.68871569694761559 + 0.68874135371892342 + 0.68876701218392067 + 0.68879267234282737 + 0.68881833419586069 + 0.68884399774323946 + 0.68886966298518382 + 0.68889532992191105 + 0.68892099855364153 + 0.68894666888059408 + 0.68897234090298753 + 0.68899801462104082 + 0.6890236900349711 + 0.68904936714500209 + 0.68907504595135116 + 0.68910072645423415 + 0.68912640865387476 + 0.68915209255049192 + 0.68917777814430159 + 0.68920346543552768 + 0.68922915442438581 + 0.68925484511109847 + 0.68928053749588325 + 0.68930623157896065 + 0.68933192736055171 + 0.68935762484087393 + 0.68938332402014968 + 0.68940902489859501 + 0.68943472747643231 + 0.68946043175388272 + 0.6894861377311623 + 0.68951184540849486 + 0.68953755478610024 + 0.68956326586419425 + 0.68958897864300284 + 0.68961469312274237 + 0.68964040930363535 + 0.68966612718590126 + 0.68969184676975803 + 0.68971756805543016 + 0.68974329104313381 + 0.6897690157330949 + 0.68979474212552849 + 0.68982047022065884 + 0.689846200018704 + 0.68987193151988691 + 0.68989766472442893 + 0.68992339963254645 + 0.68994913624446397 + 0.68997487456040152 + 0.69000061458058037 + 0.69002635630522013 + 0.69005209973454429 + 0.69007784486877055 + 0.69010359170812263 + 0.69012934025282169 + 0.69015509050308599 + 0.69018084245914058 + 0.69020659612120516 + 0.69023235148950013 + 0.69025810856424663 + 0.69028386734566838 + 0.6903096278339852 + 0.6903353900294189 + 0.69036115393219122 + 0.69038691954252385 + 0.69041268686063706 + 0.6904384558867559 + 0.69046422662109885 + 0.69048999906388797 + 0.69051577321534652 + 0.69054154907569654 + 0.6905673266451583 + 0.6905931059239554 + 0.69061888691230822 + 0.69064466961044213 + 0.69067045401857563 + 0.69069624013693254 + 0.69072202796573323 + 0.69074781750520331 + 0.69077360875556304 + 0.69079940171703458 + 0.6908251963898403 + 0.69085099277420359 + 0.69087679087034726 + 0.69090259067849302 + 0.69092839219886348 + 0.69095419543168068 + 0.69098000037716889 + 0.69100580703555015 + 0.69103161540704694 + 0.69105742549188154 + 0.6910832372902781 + 0.69110905080245921 + 0.69113486602864715 + 0.69116068296906596 + 0.69118650162393813 + 0.69121232199348648 + 0.69123814407793494 + 0.6912639678775061 + 0.69128979339242269 + 0.69131562062290897 + 0.69134144956918897 + 0.69136728023148575 + 0.69139311261002001 + 0.69141894670501958 + 0.69144478251670394 + 0.69147062004530069 + 0.69149645929102943 + 0.69152230025411776 + 0.69154814293478706 + 0.69157398733325992 + 0.6915998334497645 + 0.69162568128452029 + 0.69165153083775333 + 0.69167738210968677 + 0.69170323510054521 + 0.69172908981055325 + 0.69175494623993394 + 0.69178080438891199 + 0.69180666425771054 + 0.69183252584655575 + 0.69185838915567099 + 0.69188425418527932 + 0.69191012093560722 + 0.69193598940687784 + 0.69196185959931766 + 0.69198773151314852 + 0.69201360514859667 + 0.6920394805058856 + 0.69206535758524013 + 0.69209123638688697 + 0.69211711691104949 + 0.69214299915795108 + 0.69216888312781844 + 0.6921947688208766 + 0.69222065623735085 + 0.69224654537746455 + 0.6922724362414443 + 0.69229832882951392 + 0.69232422314190012 + 0.69235011917882661 + 0.69237601694051842 + 0.69240191642720272 + 0.69242781763910466 + 0.69245372057644639 + 0.69247962523945805 + 0.69250553162836337 + 0.69253143974338638 + 0.69255734958475379 + 0.69258326115269109 + 0.69260917444742398 + 0.6926350894691794 + 0.69266100621818139 + 0.69268692469465687 + 0.69271284489883 + 0.69273876683093127 + 0.69276469049118128 + 0.69279061587980739 + 0.69281654299703688 + 0.692842471843097 + 0.69286840241821201 + 0.6928943347226092 + 0.69292026875651413 + 0.69294620452015132 + 0.69297214201375112 + 0.69299808123753637 + 0.69302402219173775 + 0.69304996487657622 + 0.69307590929228258 + 0.69310185543908298 + 0.69312780331720136 + 0.69315375292686721 + 0.69317970426830655 + 0.69320565734174533 + 0.69323161214741136 + 0.69325756868553223 + 0.69328352695633411 + 0.69330948696004324 + 0.69333544869688712 + 0.69336141216709213 + 0.69338737737088774 + 0.69341334430849855 + 0.69343931298015404 + 0.69346528338607893 + 0.6934912555265027 + 0.69351722940165339 + 0.69354320501175559 + 0.69356918235703913 + 0.69359516143773015 + 0.69362114225405869 + 0.69364712480624779 + 0.69367310909453028 + 0.69369909511912975 + 0.69372508288027734 + 0.693751072378198 + 0.69377706361312175 + 0.69380305658527497 + 0.69382905129488615 + 0.69385504774218498 + 0.69388104592739663 + 0.69390704585075103 + 0.69393304751247664 + 0.69395905091279997 + 0.69398505605195138 + 0.69401106293015746 + 0.69403707154764671 + 0.69406308190464916 + 0.69408909400139185 + 0.69411510783810326 + 0.69414112341501355 + 0.69416714073234953 + 0.69419315979033847 + 0.69421918058921384 + 0.69424520312920079 + 0.69427122741052993 + 0.69429725343342641 + 0.69432328119812403 + 0.69434931070484995 + 0.69437534195383122 + 0.69440137494529997 + 0.69442740967948346 + 0.69445344615661031 + 0.6944794843769112 + 0.69450552434061519 + 0.69453156604795097 + 0.69455760949914758 + 0.69458365469443561 + 0.69460970163404401 + 0.69463575031820202 + 0.69466180074714012 + 0.69468785292108592 + 0.69471390684027001 + 0.6947399625049232 + 0.69476601991527476 + 0.69479207907155205 + 0.69481813997398756 + 0.69484420262281066 + 0.69487026701825227 + 0.69489633316054156 + 0.69492240104990777 + 0.69494847068658039 + 0.6949745420707919 + 0.69500061520277012 + 0.69502669008274776 + 0.69505276671095251 + 0.69507884508761708 + 0.69510492521297118 + 0.69513100708724418 + 0.69515709071066711 + 0.69518317608347135 + 0.69520926320588472 + 0.69523535207814191 + 0.69526144270047074 + 0.69528753507310259 + 0.6953136291962686 + 0.69533972507020037 + 0.69536582269512759 + 0.69539192207128142 + 0.6954180231988919 + 0.69544412607819206 + 0.69547023070941161 + 0.69549633709278225 + 0.69552244522853524 + 0.69554855511690061 + 0.69557466675810986 + 0.69560078015239823 + 0.69562689529999189 + 0.69565301220112441 + 0.69567913085602573 + 0.69570525126493088 + 0.69573137342806834 + 0.69575749734567149 + 0.69578362301797037 + 0.69580975044519855 + 0.69583587962758597 + 0.69586201056536634 + 0.6958881432587698 + 0.69591427770802838 + 0.69594041391337547 + 0.69596655187504297 + 0.69599269159326149 + 0.6960188330682644 + 0.69604497630028395 + 0.69607112128955029 + 0.6960972680362989 + 0.69612341654076049 + 0.69614956680316664 + 0.69617571882375162 + 0.69620187260274569 + 0.69622802814038298 + 0.69625418543689699 + 0.69628034449251863 + 0.69630650530748006 + 0.69633266788201509 + 0.6963588322163563 + 0.69638499831073764 + 0.69641116616539123 + 0.69643733578054801 + 0.69646350715644378 + 0.69648968029330915 + 0.69651585519138026 + 0.69654203185088748 + 0.69656821027206539 + 0.69659439045514782 + 0.69662057240036612 + 0.69664675610795412 + 0.69667294157814652 + 0.69669912881117568 + 0.6967253178072742 + 0.69675150856667822 + 0.69677770108961901 + 0.69680389537633247 + 0.69683009142704966 + 0.69685628924200671 + 0.69688248882143489 + 0.69690869016557022 + 0.69693489327464564 + 0.69696109814889595 + 0.69698730478855353 + 0.69701351319385352 + 0.69703972336502862 + 0.69706593530231531 + 0.69709214900594652 + 0.69711836447615694 + 0.69714458171318139 + 0.69717080071725124 + 0.69719702148860463 + 0.69722324402747293 + 0.69724946833409285 + 0.6972756944086993 + 0.69730192225152521 + 0.69732815186280572 + 0.69735438324277577 + 0.69738061639167015 + 0.69740685130972246 + 0.69743308799716908 + 0.69745932645424358 + 0.69748556668118433 + 0.69751180867822149 + 0.69753805244559342 + 0.69756429798353348 + 0.69759054529227704 + 0.69761679437206092 + 0.69764304522312026 + 0.6976692978456871 + 0.69769555224000002 + 0.69772180840629416 + 0.69774806634480491 + 0.69777432605576606 + 0.69780058753941465 + 0.69782685079598594 + 0.6978531158257153 + 0.69787938262884019 + 0.697905651205594 + 0.69793192155621431 + 0.69795819368093615 + 0.69798446757999388 + 0.69801074325362789 + 0.69803702070206852 + 0.69806329992555682 + 0.6980895809243266 + 0.69811586369861522 + 0.69814214824865672 + 0.69816843457469013 + 0.69819472267694938 + 0.69822101255567226 + 0.69824730421109438 + 0.6982735976434532 + 0.69829989285298311 + 0.69832618983992456 + 0.69835248860451249 + 0.69837878914698048 + 0.69840509146756979 + 0.69843139556651479 + 0.69845770144405295 + 0.69848400910042052 + 0.69851031853585521 + 0.69853662975059472 + 0.69856294274487507 + 0.69858925751893253 + 0.69861557407300645 + 0.69864189240733321 + 0.69866821252214717 + 0.69869453441769147 + 0.69872085809419882 + 0.69874718355190724 + 0.69877351079105643 + 0.6987998398118811 + 0.69882617061462249 + 0.69885250319951364 + 0.69887883756679459 + 0.69890517371670491 + 0.69893151164947931 + 0.69895785136535771 + 0.69898419286457503 + 0.69901053614737274 + 0.69903688121398755 + 0.69906322806465759 + 0.69908957669961946 + 0.6991159271191133 + 0.69914227932337725 + 0.69916863331264822 + 0.69919498908716449 + 0.69922134664716618 + 0.6992477059928901 + 0.69927406712457463 + 0.69930043004245834 + 0.69932679474678139 + 0.69935316123778246 + 0.69937952951569826 + 0.69940589958076749 + 0.69943227143323039 + 0.69945864507332411 + 0.69948502050129047 + 0.69951139771736504 + 0.69953777672178796 + 0.69956415751479972 + 0.69959054009663768 + 0.6996169244675422 + 0.69964331062775031 + 0.69966969857750438 + 0.69969608831703978 + 0.69972247984660063 + 0.69974887316642242 + 0.6997752682767473 + 0.69980166517781128 + 0.69982806386985641 + 0.69985446435312348 + 0.6998808666278501 + 0.69990727069427683 + 0.69993367655264271 + 0.69996008420318712 + 0.6999864936461524 + 0.70001290488177603 + 0.70003931791029905 + 0.70006573273196071 + 0.70009214934700192 + 0.70011856775566372 + 0.70014498795818347 + 0.70017140995480265 + 0.70019783374576372 + 0.70022425933130439 + 0.70025068671166579 + 0.70027711588708741 + 0.70030354685781371 + 0.70032997962407928 + 0.70035641418612871 + 0.70038285054420302 + 0.70040928869854024 + 0.70043572864938342 + 0.70046217039697201 + 0.70048861394154582 + 0.70051505928334956 + 0.70054150642262125 + 0.70056795535960237 + 0.70059440609453405 + 0.70062085862765811 + 0.70064731295921434 + 0.70067376908944579 + 0.70070022701859069 + 0.70072668674689575 + 0.70075314827459745 + 0.70077961160193902 + 0.7008060767291624 + 0.70083254365650727 + 0.70085901238421699 + 0.70088548291253361 + 0.70091195524169703 + 0.70093842937195072 + 0.70096490530353484 + 0.7009913830366945 + 0.70101786257166654 + 0.7010443439086963 + 0.70107082704802737 + 0.70109731198989655 + 0.70112379873455255 + 0.70115028728223083 + 0.70117677763317821 + 0.70120326978763681 + 0.701229763745847 + 0.70125625950805259 + 0.70128275707449406 + 0.70130925644541697 + 0.70133575762106148 + 0.7013622606016704 + 0.70138876538748873 + 0.70141527197875553 + 0.70144178037571658 + 0.70146829057861426 + 0.70149480258768893 + 0.70152131640318816 + 0.70154783202534943 + 0.70157434945441988 + 0.70160086869064209 + 0.70162738973425853 + 0.70165391258551013 + 0.70168043724464435 + 0.70170696371190033 + 0.70173349198752577 + 0.70176002207176147 + 0.70178655396485023 + 0.70181308766703621 + 0.70183962317856563 + 0.7018661604996792 + 0.70189269963062162 + 0.70191924057163391 + 0.70194578332296376 + 0.70197232788485409 + 0.7019988742575477 + 0.70202542244128918 + 0.70205197243632311 + 0.70207852424289241 + 0.70210507786124154 + 0.70213163329161532 + 0.70215819053425665 + 0.70218474958941035 + 0.70221131045732266 + 0.70223787313823505 + 0.70226443763239232 + 0.70229100394004096 + 0.70231757206142575 + 0.70234414199678818 + 0.70237071374637505 + 0.70239728731043094 + 0.70242386268920098 + 0.70245043988292843 + 0.70247701889185821 + 0.70250359971623699 + 0.70253018235631004 + 0.7025567668123206 + 0.7025833530845137 + 0.70260994117313458 + 0.70263653107843005 + 0.70266312280064536 + 0.70268971634002375 + 0.70271631169681081 + 0.70274290887125324 + 0.70276950786359638 + 0.70279610867408571 + 0.70282271130296636 + 0.70284931575048371 + 0.7028759220168832 + 0.7029025301024121 + 0.70292914000731388 + 0.70295575173183744 + 0.70298236527622682 + 0.70300898064072737 + 0.70303559782558456 + 0.70306221683104753 + 0.70308883765736008 + 0.70311546030476957 + 0.70314208477352158 + 0.70316871106386192 + 0.70319533917603783 + 0.70322196911029522 + 0.70324860086687813 + 0.7032752344460389 + 0.70330186984801857 + 0.70332850707306627 + 0.70335514612142946 + 0.70338178699335241 + 0.70340842968908279 + 0.70343507420886819 + 0.70346172055295453 + 0.70348836872159115 + 0.70351501871502098 + 0.70354167053349481 + 0.70356832417725557 + 0.70359497964655426 + 0.70362163694163893 + 0.70364829606275225 + 0.70367495701014382 + 0.70370161978406309 + 0.70372828438475477 + 0.70375495081246686 + 0.70378161906744718 + 0.7038082891499422 + 0.7038349610602016 + 0.70386163479847175 + 0.70388831036500232 + 0.70391498776003836 + 0.70394166698382943 + 0.70396834803662212 + 0.70399503091866622 + 0.70402171563020843 + 0.70404840217149711 + 0.70407509054278028 + 0.70410178074430618 + 0.7041284727763234 + 0.70415516663908029 + 0.7041818623328252 + 0.70420855985780639 + 0.70423525921427077 + 0.70426196040247013 + 0.7042886634226514 + 0.70431536827506136 + 0.70434207495995016 + 0.70436878347756982 + 0.7043954938281638 + 0.70442220601198424 + 0.70444892002927817 + 0.70447563588029583 + 0.70450235356528601 + 0.7045290730844973 + 0.70455579443817873 + 0.70458251762658042 + 0.70460924264995162 + 0.70463596950854079 + 0.70466269820259719 + 0.70468942873237117 + 0.70471616109811164 + 0.70474289530006762 + 0.70476963133848991 + 0.70479636921362732 + 0.70482310892572908 + 0.70484985047504567 + 0.70487659386182477 + 0.7049033390863223 + 0.70493008614878028 + 0.70495683504945506 + 0.70498358578859222 + 0.70501033836644444 + 0.70503709278326099 + 0.70506384903929298 + 0.70509060713478944 + 0.70511736706999972 + 0.70514412884517685 + 0.70517089246056841 + 0.70519765791642719 + 0.70522442521300244 + 0.70525119435054562 + 0.7052779653293062 + 0.7053047381495352 + 0.70533151281148398 + 0.7053582893154039 + 0.70538506766154441 + 0.70541184785015709 + 0.70543862988149131 + 0.7054654137558003 + 0.70549219947333541 + 0.7055189870343449 + 0.70554577643908334 + 0.70557256768780074 + 0.7055993607807467 + 0.70562615571817311 + 0.70565295250033455 + 0.70567975112747794 + 0.70570655159985807 + 0.7057333539177264 + 0.7057601580813333 + 0.70578696409092867 + 0.70581377194676753 + 0.70584058164910179 + 0.70586739319818148 + 0.70589420659425839 + 0.7059210218375862 + 0.70594783892841484 + 0.70597465786699809 + 0.7060014786535862 + 0.70602830128843463 + 0.70605512577179164 + 0.706081952103913 + 0.70610878028505053 + 0.70613561031545291 + 0.70616244219537749 + 0.70618927592507452 + 0.70621611150479624 + 0.70624294893479478 + 0.70626978821532582 + 0.70629662934663984 + 0.70632347232899084 + 0.70635031716262942 + 0.70637716384781113 + 0.70640401238478678 + 0.7064308627738104 + 0.70645771501513621 + 0.70648456910901647 + 0.70651142505570375 + 0.70653828285545039 + 0.70656514250851232 + 0.70659200401514222 + 0.70661886737559254 + 0.70664573259011765 + 0.70667259965896845 + 0.7066994685824044 + 0.70672633936067464 + 0.70675321199403196 + 0.70678008648273249 + 0.7068069628270307 + 0.70683384102717939 + 0.70686072108343301 + 0.70688760299604292 + 0.70691448676526669 + 0.70694137239135746 + 0.70696825987456824 + 0.7069951492151535 + 0.70702204041336969 + 0.70704893346946818 + 0.7070758283837052 + 0.7071027251563341 + 0.70712962378761113 + 0.70715652427778786 + 0.70718342662712252 + 0.70721033083586804 + 0.70723723690427809 + 0.70726414483261058 + 0.70729105462111719 + 0.70731796627005294 + 0.70734487977967619 + 0.70737179515023874 + 0.70739871238199536 + 0.70742563147520321 + 0.70745255243011718 + 0.70747947524699228 + 0.707506399926084 + 0.70753332646764577 + 0.70756025487193608 + 0.70758718513920693 + 0.70761411726971857 + 0.70764105126372323 + 0.70766798712147583 + 0.70769492484323371 + 0.70772186442925389 + 0.70774880587979017 + 0.707775749195098 + 0.70780269437543608 + 0.70782964142105853 + 0.7078565903322207 + 0.70788354110917973 + 0.70791049375219151 + 0.70793744826151328 + 0.70796440463739896 + 0.70799136288010744 + 0.70801832298989464 + 0.70804528496701469 + 0.70807224881172814 + 0.7080992145242877 + 0.7081261821049526 + 0.70815315155397829 + 0.70818012287162102 + 0.70820709605813992 + 0.70823407111378933 + 0.70826104803882695 + 0.70828802683351022 + 0.70831500749809717 + 0.70834199003284359 + 0.70836897443800417 + 0.7083959607138397 + 0.7084229488606083 + 0.70844993887856433 + 0.70847693076796558 + 0.70850392452907196 + 0.7085309201621377 + 0.70855791766742271 + 0.708584917045183 + 0.70861191829567693 + 0.70863892141916407 + 0.70866592641589921 + 0.70869293328614036 + 0.70871994203014899 + 0.70874695264818011 + 0.70877396514049162 + 0.708800979507342 + 0.70882799574898947 + 0.70885501386569216 + 0.70888203385770998 + 0.70890905572530005 + 0.70893607946871862 + 0.70896310508822924 + 0.70899013258408361 + 0.70901716195654552 + 0.7090441932058712 + 0.70907122633232134 + 0.70909826133615417 + 0.70912529821762504 + 0.70915233697699587 + 0.70917937761452698 + 0.70920642013047375 + 0.70923346452509628 + 0.70926051079865693 + 0.70928755895141093 + 0.70931460898361876 + 0.70934166089553929 + 0.70936871468743279 + 0.7093957703595567 + 0.70942282791217315 + 0.70944988734554104 + 0.70947694865991773 + 0.70950401185556367 + 0.70953107693273987 + 0.70955814389170491 + 0.70958521273271991 + 0.7096122834560421 + 0.70963935606193407 + 0.70966643055065481 + 0.70969350692246358 + 0.70972058517762293 + 0.70974766531638878 + 0.70977474733902357 + 0.70980183124579033 + 0.70982891703694284 + 0.70985600471274934 + 0.70988309427346197 + 0.70991018571934894 + 0.70993727905066617 + 0.70996437426767478 + 0.70999147137063612 + 0.7100185703598112 + 0.71004567123546125 + 0.71007277399784596 + 0.71009987864722646 + 0.71012698518386252 + 0.71015409360801884 + 0.71018120391995176 + 0.71020831611992596 + 0.71023543020820112 + 0.71026254618503892 + 0.71028966405070082 + 0.71031678380544661 + 0.71034390544954107 + 0.71037102898324256 + 0.71039815440681275 + 0.71042528172051467 + 0.71045241092461042 + 0.71047954201935959 + 0.71050667500502596 + 0.71053380988187098 + 0.71056094665015657 + 0.71058808531014273 + 0.71061522586209314 + 0.71064236830626981 + 0.71066951264293587 + 0.71069665887235212 + 0.71072380699477999 + 0.71075095701048518 + 0.71077810891972615 + 0.71080526272276845 + 0.71083241841987066 + 0.71085957601130001 + 0.71088673549731707 + 0.71091389687818207 + 0.71094106015416247 + 0.71096822532551696 + 0.71099539239251119 + 0.71102256135540753 + 0.71104973221446832 + 0.71107690496995568 + 0.71110407962213384 + 0.71113125617126516 + 0.7111584346176153 + 0.71118561496144361 + 0.71121279720301744 + 0.71123998134259758 + 0.71126716738044848 + 0.71129435531683249 + 0.71132154515201396 + 0.71134873688625744 + 0.71137593051982517 + 0.71140312605298162 + 0.71143032348599156 + 0.71145752281911556 + 0.71148472405262186 + 0.71151192718677148 + 0.71153913222182874 + 0.71156633915805834 + 0.71159354799572483 + 0.7116207587350929 + 0.71164797137642544 + 0.71167518591998713 + 0.71170240236604432 + 0.71172962071485835 + 0.711756840966694 + 0.71178406312181786 + 0.71181128718049469 + 0.71183851314298741 + 0.71186574100956124 + 0.71189297078048253 + 0.71192020245601484 + 0.71194743603642097 + 0.71197467152197147 + 0.71200190891292758 + 0.71202914820955288 + 0.71205638941211746 + 0.71208363252088314 + 0.71211087753611502 + 0.71213812445808 + 0.71216537328704299 + 0.71219262402326966 + 0.71221987666702491 + 0.71224713121857253 + 0.71227438767818463 + 0.71230164604612134 + 0.71232890632264811 + 0.71235616850803396 + 0.71238343260254211 + 0.71241069860644179 + 0.71243796651999691 + 0.7124652363434727 + 0.71249250807713638 + 0.71251978172125385 + 0.71254705727609213 + 0.71257433474191711 + 0.71260161411899425 + 0.71262889540759267 + 0.71265617860797825 + 0.71268346372041491 + 0.71271075074517032 + 0.7127380396825117 + 0.71276533053270674 + 0.71279262329601978 + 0.71281991797272182 + 0.71284721456307665 + 0.71287451306735072 + 0.71290181348581327 + 0.71292911581873031 + 0.71295642006636961 + 0.71298372622899719 + 0.71301103430688273 + 0.71303834430029045 + 0.71306565620949014 + 0.71309297003474792 + 0.71312028577633335 + 0.71314760343451111 + 0.71317492300955254 + 0.7132022445017222 + 0.71322956791128833 + 0.7132568932385206 + 0.71328422048368534 + 0.71331154964705068 + 0.71333888072888496 + 0.71336621372945797 + 0.7133935486490347 + 0.71342088548788651 + 0.71344822424627863 + 0.71347556492448094 + 0.71350290752276335 + 0.71353025204139087 + 0.7135575984806356 + 0.7135849468407639 + 0.71361229712204455 + 0.71363964932474755 + 0.71366700344914158 + 0.71369435949549354 + 0.71372171746407331 + 0.7137490773551517 + 0.71377643916899547 + 0.71380380290587497 + 0.71383116856605722 + 0.71385853614981443 + 0.71388590565741517 + 0.71391327708912689 + 0.7139406504452197 + 0.71396802572596629 + 0.71399540293163188 + 0.71402278206248704 + 0.71405016311880254 + 0.71407754610084917 + 0.71410493100889239 + 0.7141323178432063 + 0.71415970660406014 + 0.71418709729172281 + 0.71421448990646363 + 0.7142418844485533 + 0.71426928091826281 + 0.71429667931586127 + 0.71432407964161981 + 0.71435148189580944 + 0.71437888607869915 + 0.71440629219056018 + 0.71443370023166031 + 0.71446111020227565 + 0.71448852210267211 + 0.71451593593312113 + 0.71454335169389527 + 0.71457076938526431 + 0.71459818900749938 + 0.71462561056087182 + 0.71465303404565106 + 0.71468045946210879 + 0.71470788681051778 + 0.71473531609114793 + 0.71476274730427058 + 0.71479018045015719 + 0.71481761552907763 + 0.7148450525413067 + 0.71487249148711107 + 0.71489993236676885 + 0.71492737518054661 + 0.71495481992871623 + 0.71498226661155084 + 0.71500971522932411 + 0.71503716578230392 + 0.71506461827076595 + 0.71509207269497832 + 0.71511952905521636 + 0.71514698735175353 + 0.71517444758485671 + 0.71520190975480291 + 0.7152293738618607 + 0.7152568399063054 + 0.71528430788840891 + 0.71531177780844357 + 0.7153392496666795 + 0.71536672346339403 + 0.71539419919885594 + 0.71542167687333891 + 0.71544915648711871 + 0.71547663804046402 + 0.71550412153364884 + 0.71553160696694906 + 0.71555909434063336 + 0.71558658365497918 + 0.71561407491025564 + 0.71564156810674018 + 0.71566906324470181 + 0.71569656032441653 + 0.71572405934615835 + 0.71575156031019993 + 0.71577906321681395 + 0.71580656806627607 + 0.71583407485885742 + 0.71586158359483409 + 0.715889094274477 + 0.71591660689806569 + 0.71594412146586772 + 0.71597163797815944 + 0.71599915643521683 + 0.71602667683731136 + 0.71605419918471891 + 0.7160817234777126 + 0.7161092497165672 + 0.71613677790155872 + 0.71616430803295872 + 0.71619184011104509 + 0.71621937413608949 + 0.71624691010836827 + 0.71627444802815443 + 0.71630198789572641 + 0.71632952971135377 + 0.7163570734753133 + 0.71638461918788332 + 0.71641216684933695 + 0.71643971645994597 + 0.7164672680199905 + 0.71649482152974209 + 0.71652237698947918 + 0.71654993439947556 + 0.71657749376000424 + 0.71660505507134398 + 0.71663261833377012 + 0.71666018354755778 + 0.71668775071298063 + 0.716715319830319 + 0.716742890899843 + 0.71677046392183164 + 0.71679803889656191 + 0.7168256158243077 + 0.71685319470534759 + 0.71688077553995233 + 0.71690835832840383 + 0.7169359430709763 + 0.71696352976794686 + 0.71699111841958951 + 0.71701870902618148 + 0.71704630158800209 + 0.71707389610532335 + 0.71710149257842637 + 0.71712909100758504 + 0.71715669139307692 + 0.71718429373517978 + 0.71721189803416741 + 0.71723950429031935 + 0.71726711250391306 + 0.71729472267522298 + 0.71732233480453034 + 0.71734994889210912 + 0.71737756493823712 + 0.71740518294319233 + 0.71743280290725076 + 0.71746042483069195 + 0.71748804871379224 + 0.7175156745568293 + 0.71754330236008113 + 0.71757093212382594 + 0.71759856384833975 + 0.71762619753390078 + 0.71765383318078868 + 0.71768147078928168 + 0.71770911035965423 + 0.71773675189218833 + 0.71776439538715853 + 0.71779204084484816 + 0.71781968826552867 + 0.71784733764948516 + 0.71787498899699265 + 0.71790264230832934 + 0.71793029758377536 + 0.71795795482360925 + 0.71798561402810768 + 0.71801327519755076 + 0.71804093833221694 + 0.71806860343238665 + 0.7180962704983368 + 0.71812393953034748 + 0.71815161052869747 + 0.71817928349366711 + 0.71820695842553339 + 0.71823463532457676 + 0.71826231419107589 + 0.71828999502531143 + 0.71831767782756206 + 0.71834536259810844 + 0.71837304933722945 + 0.7184007380452021 + 0.71842842872230916 + 0.71845612136883086 + 0.71848381598504663 + 0.71851151257123358 + 0.71853921112767583 + 0.71856691165465103 + 0.71859461415243797 + 0.71862231862132142 + 0.7186500250615766 + 0.71867773347348662 + 0.71870544385733237 + 0.71873315621339295 + 0.71876087054194793 + 0.71878858684327973 + 0.71881630511766803 + 0.71884402536539393 + 0.71887174758673866 + 0.7188994717819831 + 0.71892719795140714 + 0.71895492609529177 + 0.71898265621391844 + 0.71901038830756847 + 0.71903812237652298 + 0.71906585842106185 + 0.71909359644147008 + 0.71912133643802534 + 0.71914907841100928 + 0.71917682236070524 + 0.71920456828739443 + 0.71923231619135697 + 0.71926006607287607 + 0.71928781793223362 + 0.71931557176970917 + 0.71934332758558639 + 0.71937108538014871 + 0.71939884515367614 + 0.71942660690644866 + 0.7194543706387535 + 0.71948213635086877 + 0.71950990404308002 + 0.71953767371566746 + 0.71956544536891287 + 0.71959321900310014 + 0.71962099461851115 + 0.719648772215428 + 0.71967655179413625 + 0.71970433335491446 + 0.71973211689805006 + 0.71975990242382171 + 0.7197876899325133 + 0.7198154794244106 + 0.71984327089979239 + 0.7198710643589461 + 0.71989885980215251 + 0.71992665722969551 + 0.71995445664185764 + 0.71998225803892291 + 0.72001006142117374 + 0.72003786678889625 + 0.72006567414237299 + 0.72009348348188629 + 0.72012129480772058 + 0.7201491081201602 + 0.7201769234194878 + 0.72020474070598961 + 0.72023255997994806 + 0.72026038124164615 + 0.72028820449136999 + 0.72031602972940423 + 0.72034385695602976 + 0.72037168617153313 + 0.72039951737620056 + 0.72042735057031337 + 0.7204551857541579 + 0.72048302292801891 + 0.72051086209217929 + 0.7205387032469257 + 0.72056654639254136 + 0.72059439152931248 + 0.72062223865752417 + 0.72065008777745787 + 0.7206779388894039 + 0.72070579199364504 + 0.72073364709046672 + 0.72076150418015217 + 0.7207893632629897 + 0.72081722433926299 + 0.72084508740925868 + 0.72087295247326033 + 0.7209008195315566 + 0.72092868858443082 + 0.72095655963216865 + 0.72098443267505663 + 0.72101230771338221 + 0.72104018474742881 + 0.72106806377748189 + 0.72109594480383032 + 0.72112382782675954 + 0.72115171284655344 + 0.72117959986350078 + 0.72120748887788733 + 0.72123537988999842 + 0.72126327290012171 + 0.72129116790854431 + 0.72131906491555209 + 0.72134696392143061 + 0.72137486492646752 + 0.72140276793095015 + 0.72143067293516439 + 0.72145857993939788 + 0.72148648894393652 + 0.72151439994906941 + 0.72154231295508287 + 0.72157022796226422 + 0.72159814497089969 + 0.72162606398127704 + 0.72165398499368572 + 0.72168190800841014 + 0.72170983302573999 + 0.72173776004596124 + 0.721765689069362 + 0.72179362009623171 + 0.72182155312685692 + 0.72184948816152561 + 0.72187742520052556 + 0.72190536424414509 + 0.72193330529267064 + 0.72196124834639375 + 0.72198919340560086 + 0.72201714047058019 + 0.72204508954162006 + 0.72207304061900857 + 0.72210099370303416 + 0.72212894879398692 + 0.72215690589215353 + 0.72218486499782408 + 0.72221282611128701 + 0.72224078923283086 + 0.72226875436274396 + 0.72229672150131852 + 0.72232469064883964 + 0.72235266180559754 + 0.72238063497188254 + 0.72240861014798174 + 0.72243658733418903 + 0.72246456653078783 + 0.72249254773807237 + 0.72252053095632751 + 0.72254851618584781 + 0.72257650342692004 + 0.72260449267983495 + 0.72263248394488167 + 0.72266047722235049 + 0.72268847251253243 + 0.72271646981571469 + 0.72274446913218993 + 0.72277247046224691 + 0.72280047380617518 + 0.72282847916426707 + 0.722856486536812 + 0.72288449592410231 + 0.7229125073264242 + 0.72294052074407011 + 0.72296853617733303 + 0.7229965536265005 + 0.72302457309186363 + 0.7230525945737154 + 0.72308061807234503 + 0.72310864358804405 + 0.72313667112110358 + 0.72316470067181471 + 0.72319273224046732 + 0.72322076582735273 + 0.72324880143276549 + 0.72327683905699403 + 0.723304878700331 + 0.72333292036306662 + 0.72336096404549377 + 0.72338900974790243 + 0.72341705747058604 + 0.72344510721383604 + 0.72347315897794418 + 0.72350121276320356 + 0.72352926856990296 + 0.72355732639833703 + 0.72358538624879809 + 0.7236134481215758 + 0.72364151201696558 + 0.72366957793525777 + 0.72369764587674579 + 0.72372571584172163 + 0.72375378783047728 + 0.72378186184330651 + 0.72380993788050307 + 0.72383801594235553 + 0.72386609602916119 + 0.7238941781412106 + 0.72392226227879752 + 0.72395034844221418 + 0.72397843663175465 + 0.72400652684771105 + 0.72403461909037758 + 0.72406271336004802 + 0.72409080965701345 + 0.72411890798157119 + 0.72414700833401013 + 0.72417511071462648 + 0.72420321512371433 + 0.72423132156156622 + 0.72425943002847648 + 0.7242875405247392 + 0.72431565305064916 + 0.72434376760649721 + 0.72437188419258092 + 0.7244000028091917 + 0.72442812345662555 + 0.72445624613517712 + 0.72448437084513917 + 0.72451249758680791 + 0.72454062636047489 + 0.72456875716643798 + 0.72459689000499006 + 0.72462502487642777 + 0.72465316178104244 + 0.72468130071913039 + 0.72470944169098861 + 0.72473758469690974 + 0.72476572973719067 + 0.72479387681212459 + 0.7248220259220064 + 0.72485017706713462 + 0.72487833024780091 + 0.72490648546430358 + 0.7249346427169362 + 0.72496280200599383 + 0.72499096333177515 + 0.7250191266945718 + 0.72504729209468255 + 0.72507545953240449 + 0.72510362900802938 + 0.72513180052185588 + 0.72515997407417787 + 0.72518814966529399 + 0.7252163272954999 + 0.72524450696508924 + 0.72527268867436256 + 0.72530087242361396 + 0.72532905821313887 + 0.72535724604323626 + 0.7253854359142019 + 0.72541362782632979 + 0.72544182177992056 + 0.72547001777527031 + 0.72549821581267282 + 0.72552641589242928 + 0.72555461801483356 + 0.72558282218018533 + 0.72561102838877833 + 0.72563923664091423 + 0.72566744693688678 + 0.72569565927699575 + 0.72572387366153546 + 0.72575209009080699 + 0.72578030856510489 + 0.7258085290847287 + 0.72583675164997619 + 0.72586497626114554 + 0.72589320291853299 + 0.72592143162243816 + 0.72594966237315739 + 0.72597789517098887 + 0.72600613001623404 + 0.72603436690918588 + 0.72606260585014781 + 0.72609084683941449 + 0.72611908987728613 + 0.72614733496406081 + 0.72617558210003863 + 0.72620383128551447 + 0.7262320825207903 + 0.72626033580616434 + 0.72628859114193678 + 0.72631684852840284 + 0.72634510796586449 + 0.72637336945461828 + 0.72640163299496652 + 0.72642989858720786 + 0.72645816623164083 + 0.72648643592856399 + 0.72651470767827819 + 0.72654298148108187 + 0.72657125733727568 + 0.72659953524715837 + 0.72662781521103059 + 0.72665609722919133 + 0.72668438130193935 + 0.72671266742957719 + 0.72674095561240393 + 0.72676924585072011 + 0.72679753814482306 + 0.72682583249501742 + 0.72685412890160028 + 0.72688242736487441 + 0.72691072788513711 + 0.72693903046269137 + 0.72696733509783618 + 0.7269956417908745 + 0.72702395054210567 + 0.72705226135182899 + 0.72708057422034911 + 0.72710888914796368 + 0.72713720613497568 + 0.72716552518168287 + 0.72719384628839179 + 0.72722216945539864 + 0.72725049468300973 + 0.72727882197152305 + 0.72730715132123835 + 0.72733548273246229 + 0.72736381620549118 + 0.72739215174063165 + 0.72742048933818193 + 0.7274488289984451 + 0.72747717072172302 + 0.72750551450831713 + 0.72753386035853118 + 0.72756220827266482 + 0.7275905582510217 + 0.7276189102939038 + 0.7276472644016142 + 0.72767562057445356 + 0.72770397881272531 + 0.72773233911673296 + 0.72776070148677852 + 0.72778906592316261 + 0.72781743242619201 + 0.72784580099616736 + 0.72787417163339074 + 0.72790254433816581 + 0.72793091911079666 + 0.72795929595158548 + 0.72798767486083449 + 0.72801605583884954 + 0.72804443888593096 + 0.72807282400238482 + 0.72810121118851345 + 0.72812960044462105 + 0.72815799177101159 + 0.72818638516798595 + 0.72821478063585021 + 0.72824317817490858 + 0.72827157778546359 + 0.72829997946782155 + 0.72832838322228488 + 0.72835678904915635 + 0.72838519694874226 + 0.72841360692134705 + 0.72844201896727345 + 0.7284704330868278 + 0.72849884928031317 + 0.72852726754803387 + 0.72855568789029657 + 0.72858411030740577 + 0.72861253479966459 + 0.72864096136737788 + 0.72866939001085218 + 0.72869782073039047 + 0.72872625352629938 + 0.72875468839888569 + 0.72878312534845258 + 0.72881156437530503 + 0.72884000547974803 + 0.72886844866209022 + 0.7288968939226329 + 0.72892534126168507 + 0.72895379067955179 + 0.7289822421765364 + 0.72901069575294775 + 0.72903915140909092 + 0.72906760914527136 + 0.72909606896179435 + 0.72912453085896878 + 0.72915299483709661 + 0.7291814608964885 + 0.72920992903744797 + 0.72923839926028433 + 0.72926687156529935 + 0.72929534595280421 + 0.72932382242310412 + 0.72935230097650505 + 0.72938078161331421 + 0.72940926433383746 + 0.729437749138384 + 0.72946623602725957 + 0.72949472500077184 + 0.72952321605922832 + 0.72955170920293488 + 0.72958020443219762 + 0.72960870174732761 + 0.72963720114863084 + 0.72966570263641339 + 0.7296942062109848 + 0.72972271187265114 + 0.72975121962172218 + 0.72977972945850222 + 0.72980824138330447 + 0.72983675539643356 + 0.72986527149819724 + 0.72989378968890384 + 0.72992230996886309 + 0.72995083233838309 + 0.72997935679777037 + 0.73000788334733469 + 0.73003641198738456 + 0.73006494271822964 + 0.73009347554017512 + 0.73012201045353264 + 0.7301505474586123 + 0.73017908655571906 + 0.73020762774516479 + 0.73023617102725646 + 0.73026471640230595 + 0.73029326387061999 + 0.73032181343250724 + 0.73035036508827988 + 0.73037891883824635 + 0.73040747468271572 + 0.73043603262199619 + 0.73046459265640051 + 0.73049315478623567 + 0.73052171901181195 + 0.73055028533344191 + 0.73057885375143106 + 0.73060742426609337 + 0.73063599687773628 + 0.73066457158667053 + 0.73069314839320854 + 0.73072172729765761 + 0.73075030830032872 + 0.7307788914015344 + 0.73080747660158241 + 0.73083606390078515 + 0.73086465329945205 + 0.73089324479789575 + 0.73092183839642566 + 0.73095043409535299 + 0.73097903189499058 + 0.7310076317956461 + 0.7310362337976325 + 0.73106483790126109 + 0.73109344410684307 + 0.73112205241468997 + 0.7311506628251111 + 0.73117927533842175 + 0.73120788995492958 + 0.73123650667495133 + 0.7312651254987933 + 0.73129374642677059 + 0.73132236945919471 + 0.73135099459637554 + 0.73137962183862826 + 0.73140825118626274 + 0.73143688263959261 + 0.73146551619892775 + 0.73149415186458333 + 0.73152278963687145 + 0.73155142951610397 + 0.73158007150259241 + 0.73160871559665086 + 0.73163736179859118 + 0.73166601010872701 + 0.73169466052737064 + 0.73172331305483562 + 0.73175196769143414 + 0.73178062443748026 + 0.73180928329328609 + 0.73183794425916548 + 0.73186660733543252 + 0.73189527252239972 + 0.73192393982037895 + 0.7319526092296883 + 0.73198128075063806 + 0.73200995438354277 + 0.73203863012871462 + 0.73206730798646968 + 0.73209598795712061 + 0.73212467004098336 + 0.73215335423837058 + 0.73218204054959679 + 0.7322107289749763 + 0.73223941951482008 + 0.73226811216944798 + 0.73229680693917276 + 0.73232550382430728 + 0.73235420282516805 + 0.7323829039420694 + 0.73241160717532616 + 0.73244031252525144 + 0.73246901999216163 + 0.73249772957637327 + 0.73252644127819788 + 0.73255515509795366 + 0.73258387103595557 + 0.7326125890925167 + 0.73264130926795568 + 0.7326700315625857 + 0.73269875597672374 + 0.73272748251068465 + 0.73275621116478362 + 0.73278494193933597 + 0.7328136748346622 + 0.73284240985107008 + 0.73287114698888411 + 0.73289988624841584 + 0.73292862762998079 + 0.73295737113389603 + 0.73298611676048042 + 0.73301486451004771 + 0.7330436143829151 + 0.73307236637939999 + 0.7331011204998179 + 0.73312987674448615 + 0.73315863511372026 + 0.73318739560783963 + 0.73321615822715802 + 0.73324492297199484 + 0.73327368984266761 + 0.73330245883949208 + 0.73333122996278399 + 0.73336000321286654 + 0.73338877859005014 + 0.7334175560946562 + 0.73344633572700058 + 0.73347511748740279 + 0.73350390137618093 + 0.73353268739365074 + 0.73356147554012863 + 0.73359026581593778 + 0.73361905822139239 + 0.73364785275681088 + 0.73367664942251276 + 0.73370544821881623 + 0.73373424914603746 + 0.73376305220449844 + 0.73379185739451369 + 0.73382066471640484 + 0.73384947417049029 + 0.73387828575708658 + 0.73390709947651567 + 0.73393591532909386 + 0.73396473331513978 + 0.73399355343497541 + 0.73402237568891748 + 0.73405120007728797 + 0.73408002660040361 + 0.73410885525858305 + 0.7341376860521468 + 0.73416651898141527 + 0.73419535404670866 + 0.73422419124834415 + 0.73425303058664404 + 0.73428187206192719 + 0.73431071567451234 + 0.73433956142472023 + 0.73436840931287151 + 0.73439725933928679 + 0.73442611150428527 + 0.73445496580818581 + 0.73448382225131292 + 0.7345126808339838 + 0.73454154155651952 + 0.73457040441924082 + 0.73459926942247056 + 0.73462813656652604 + 0.73465700585173044 + 0.73468587727840473 + 0.73471475084686799 + 0.73474362655744352 + 0.7347725044104505 + 0.73480138440621201 + 0.73483026654504768 + 0.73485915082728037 + 0.73488803725323149 + 0.73491692582322266 + 0.73494581653757507 + 0.73497470939661003 + 0.73500360440064938 + 0.73503250155001632 + 0.73506140084503213 + 0.7350903022860189 + 0.73511920587329604 + 0.73514811160719096 + 0.73517701948802328 + 0.73520592951611485 + 0.7352348416917891 + 0.73526375601536642 + 0.73529267248717367 + 0.73532159110752937 + 0.73535051187675904 + 0.73537943479518275 + 0.73540835986312603 + 0.73543728708091116 + 0.73546621644886168 + 0.73549514796729987 + 0.73552408163654781 + 0.73555301745693147 + 0.7355819554287728 + 0.73561089555239434 + 0.73563983782812337 + 0.73566878225627896 + 0.73569772883718709 + 0.73572667757117338 + 0.73575562845855869 + 0.73578458149966741 + 0.73581353669482374 + 0.73584249404435365 + 0.73587145354857819 + 0.73590041520782523 + 0.73592937902241562 + 0.73595834499267576 + 0.73598731311893173 + 0.73601628340150471 + 0.736045255840721 + 0.73607423043690523 + 0.73610320719038402 + 0.73613218610147835 + 0.73616116717051816 + 0.73619015039782321 + 0.73621913578372344 + 0.73624812332854028 + 0.73627711303260202 + 0.73630610489623383 + 0.73633509891975868 + 0.7363640951035052 + 0.73639309344779669 + 0.73642209395295799 + 0.73645109661931829 + 0.73648010144720222 + 0.73650910843693529 + 0.73653811758884258 + 0.73656712890325304 + 0.73659614238048998 + 0.73662515802088258 + 0.73665417582475234 + 0.73668319579243213 + 0.73671221792424357 + 0.73674124222051407 + 0.73677026868157247 + 0.73679929730774474 + 0.73682832809935628 + 0.73685736105673438 + 0.73688639618020857 + 0.73691543347010424 + 0.73694447292674736 + 0.73697351455046545 + 0.73700255834158779 + 0.73703160430044223 + 0.73706065242735275 + 0.73708970272264873 + 0.73711875518665992 + 0.7371478098197104 + 0.73717686662213178 + 0.73720592559424802 + 0.73723498673639087 + 0.73726405004888629 + 0.73729311553206256 + 0.73732218318624732 + 0.73735125301177074 + 0.73738032500896067 + 0.73740939917814363 + 0.73743847551965114 + 0.73746755403380981 + 0.73749663472094795 + 0.73752571758139707 + 0.73755480261548412 + 0.73758388982353895 + 0.73761297920588997 + 0.7376420707628657 + 0.73767116449479631 + 0.73770026040201053 + 0.73772935848483845 + 0.73775845874360868 + 0.7377875611786533 + 0.7378166657902977 + 0.73784577257887396 + 0.7378748815447127 + 0.73790399268814078 + 0.73793310600949402 + 0.73796222150909441 + 0.73799133918727966 + 0.7380204590443733 + 0.73804958108071139 + 0.73807870529662123 + 0.73810783169243532 + 0.73813696026848108 + 0.73816609102509101 + 0.73819522396259629 + 0.73822435908132589 + 0.73825349638161075 + 0.73828263586378573 + 0.73831177752817645 + 0.73834092137511753 + 0.73837006740494027 + 0.73839921561797406 + 0.73842836601455175 + 0.73845751859500297 + 0.73848667335966067 + 0.7385158303088547 + 0.73854498944292146 + 0.73857415076218724 + 0.73860331426698533 + 0.73863247995765058 + 0.73866164783451127 + 0.73869081789790225 + 0.73871999014815515 + 0.73874916458559992 + 0.73877834121057018 + 0.738807520023401 + 0.73883670102442067 + 0.7388658842139646 + 0.73889506959236462 + 0.73892425715995436 + 0.73895344691706566 + 0.73898263886403237 + 0.73901183300118467 + 0.73904102932886007 + 0.73907022784738696 + 0.73909942855710276 + 0.73912863145833785 + 0.73915783655142986 + 0.73918704383670553 + 0.73921625331450447 + 0.73924546498515864 + 0.73927467884900089 + 0.73930389490636483 + 0.73933311315758676 + 0.73936233360299908 + 0.73939155624293429 + 0.73942078107772857 + 0.73945000810771599 + 0.73947923733323129 + 0.73950846875460696 + 0.7395377023721792 + 0.73956693818628261 + 0.7395961761972516 + 0.73962541640542101 + 0.73965465881112535 + 0.73968390341469914 + 0.73971315021647899 + 0.73974239921679785 + 0.73977165041599235 + 0.73980090381439723 + 0.73983015941234909 + 0.739859417210181 + 0.73988867720822982 + 0.73991793940683237 + 0.73994720380632339 + 0.7399764704070364 + 0.74000573920930979 + 0.74003501021348073 + 0.74006428341988073 + 0.74009355882885042 + 0.74012283644072485 + 0.74015211625583766 + 0.74018139827452767 + 0.74021068249713207 + 0.74023996892398447 + 0.74026925755542383 + 0.74029854839178755 + 0.74032784143340924 + 0.74035713668062786 + 0.74038643413377936 + 0.74041573379320269 + 0.74044503565923536 + 0.74047433973220955 + 0.7405036460124681 + 0.74053295450034506 + 0.74056226519618151 + 0.74059157810030984 + 0.74062089321307134 + 0.74065021053480362 + 0.74067953006584275 + 0.74070885180652646 + 0.74073817575719625 + 0.7407675019181863 + 0.74079683028983478 + 0.74082616087248288 + 0.74085549366646708 + 0.74088482867212713 + 0.74091416588979753 + 0.74094350531982178 + 0.74097284696253618 + 0.74100219081827889 + 0.74103153688739021 + 0.74106088517020807 + 0.74109023566707255 + 0.74111958837832059 + 0.74114894330429382 + 0.74117830044532906 + 0.74120765980176828 + 0.7412370213739482 + 0.74126638516221099 + 0.74129575116689506 + 0.74132511938833756 + 0.74135448982688223 + 0.74138386248286614 + 0.74141323735663167 + 0.74144261444851733 + 0.74147199375886397 + 0.74150137528800852 + 0.74153075903629706 + 0.7415601450040652 + 0.7415895331916551 + 0.74161892359940784 + 0.74164831622766225 + 0.74167771107675962 + 0.74170710814704399 + 0.74173650743885111 + 0.7417659089525257 + 0.74179531268840515 + 0.74182471864683575 + 0.74185412682815355 + 0.74188353723270306 + 0.74191294986082545 + 0.74194236471286046 + 0.7419717817891508 + 0.7420012010900362 + 0.74203062261586328 + 0.74206004636696832 + 0.7420894723436976 + 0.74211890054638974 + 0.74214833097538746 + 0.74217776363103427 + 0.7422071985136719 + 0.74223663562364361 + 0.74226607496128949 + 0.74229551652695269 + 0.74232496032097706 + 0.74235440634370609 + 0.74238385459547984 + 0.74241330507664183 + 0.74244275778753599 + 0.74247221272850605 + 0.74250166989989375 + 0.74253112930204135 + 0.74256059093529425 + 0.74259005479999496 + 0.74261952089648531 + 0.74264898922511113 + 0.74267845978621649 + 0.74270793258014367 + 0.74273740760723495 + 0.74276688486783804 + 0.74279636436229346 + 0.74282584609094748 + 0.74285533005414406 + 0.74288481625222591 + 0.74291430468553898 + 0.74294379535442601 + 0.74297328825923314 + 0.74300278340030479 + 0.74303228077798378 + 0.74306178039261828 + 0.74309128224454901 + 0.74312078633412437 + 0.74315029266168731 + 0.74317980122758409 + 0.74320931203215956 + 0.74323882507575856 + 0.7432683403587258 + 0.74329785788140978 + 0.7433273776441518 + 0.74335689964730223 + 0.74338642389120224 + 0.74341595037620078 + 0.7434454791026408 + 0.74347501007087125 + 0.74350454328123883 + 0.74353407873408706 + 0.74356361642976287 + 0.74359315636861156 + 0.74362269855098206 + 0.74365224297721955 + 0.74368178964766962 + 0.74371133856268112 + 0.74374088972259966 + 0.74377044312777063 + 0.74379999877854486 + 0.74382955667526629 + 0.74385911681828409 + 0.74388867920794199 + 0.7439182438445896 + 0.74394781072857596 + 0.74397737986024504 + 0.74400695123994653 + 0.74403652486802963 + 0.74406610074483848 + 0.74409567887072259 + 0.7441252592460299 + 0.74415484187110981 + 0.74418442674630692 + 0.74421401387197395 + 0.74424360324845573 + 0.74427319487610022 + 0.74430278875525868 + 0.74433238488627762 + 0.74436198326950886 + 0.74439158390529492 + 0.74442118679399116 + 0.74445079193594221 + 0.74448039933149834 + 0.74451000898100961 + 0.74453962088482406 + 0.74456923504329031 + 0.7445988514567603 + 0.74462847012558075 + 0.74465809105010194 + 0.74468771423067248 + 0.74471733966764453 + 0.74474696736136825 + 0.74477659731218915 + 0.74480622952046094 + 0.74483586398653256 + 0.74486550071075464 + 0.74489513969347765 + 0.74492478093505066 + 0.74495442443582416 + 0.7449840701961491 + 0.74501371821637608 + 0.74504336849685771 + 0.74507302103794149 + 0.74510267583998002 + 0.74513233290332237 + 0.74516199222832324 + 0.74519165381533004 + 0.74522131766469557 + 0.74525098377677279 + 0.74528065215190931 + 0.74531032279045983 + 0.74533999569277554 + 0.74536967085920613 + 0.74539934829010468 + 0.74542902798582233 + 0.74545870994671415 + 0.7454883941731264 + 0.74551808066541747 + 0.74554776942393386 + 0.74557746044903206 + 0.74560715374106223 + 0.74563684930037766 + 0.74566654712733182 + 0.7456962472222749 + 0.74572594958556182 + 0.74575565421754475 + 0.7457853611185753 + 0.74581507028900917 + 0.74584478172919633 + 0.74587449543949258 + 0.74590421142024965 + 0.74593392967182159 + 0.74596365019456223 + 0.7459933729888254 + 0.7460230980549617 + 0.74605282539332873 + 0.74608255500427845 + 0.74611228688816522 + 0.74614202104534144 + 0.7461717574761646 + 0.74620149618098575 + 0.7462312371601606 + 0.74626098041404354 + 0.74629072594298729 + 0.74632047374734789 + 0.74635022382748162 + 0.74637997618374097 + 0.74640973081648254 + 0.74643948772605717 + 0.74646924691282313 + 0.74649900837713667 + 0.74652877211935076 + 0.74655853813982198 + 0.74658830643890328 + 0.74661807701695304 + 0.74664784987432598 + 0.74667762501137547 + 0.7467074024284599 + 0.74673718212593421 + 0.74676696410415511 + 0.74679674836347787 + 0.74682653490425754 + 0.74685632372685273 + 0.74688611483161693 + 0.74691590821890885 + 0.74694570388908388 + 0.74697550184249906 + 0.74700530207951155 + 0.74703510460047495 + 0.7470649094057501 + 0.74709471649569059 + 0.74712452587065736 + 0.74715433753100413 + 0.7471841514770885 + 0.74721396770926773 + 0.747243786227901 + 0.74727360703334433 + 0.74730343012595501 + 0.74733325550609253 + 0.74736308317411282 + 0.74739291313037526 + 0.74742274537523401 + 0.74745257990905223 + 0.74748241673218407 + 0.74751225584498937 + 0.74754209724782783 + 0.74757194094105706 + 0.74760178692503176 + 0.74763163520011533 + 0.74766148576666558 + 0.747691338625039 + 0.74772119377559565 + 0.74775105121869545 + 0.74778091095469645 + 0.74781077298395704 + 0.74784063730683747 + 0.7478705039236978 + 0.7479003728348963 + 0.74793024404079345 + 0.74796011754174574 + 0.74798999333811733 + 0.7480198714302646 + 0.74804975181854838 + 0.74807963450333059 + 0.74810951948496829 + 0.74813940676382396 + 0.74816929634025597 + 0.74819918821462539 + 0.74822908238729269 + 0.74825897885861847 + 0.74828887762896357 + 0.7483187786986889 + 0.74834868206815341 + 0.74837858773771959 + 0.74840849570774859 + 0.74843840597860134 + 0.748468318550637 + 0.74849823342422206 + 0.74852815059971212 + 0.74855807007747022 + 0.74858799185785929 + 0.7486179159412405 + 0.74864784232797499 + 0.74867777101842437 + 0.74870770201295167 + 0.74873763531191639 + 0.74876757091568524 + 0.74879750882461638 + 0.74882744903907472 + 0.74885739155941844 + 0.74888733638601424 + 0.74891728351922393 + 0.74894723295940901 + 0.74897718470693342 + 0.74900713876215852 + 0.74903709512544814 + 0.74906705379716587 + 0.74909701477767354 + 0.74912697806733497 + 0.74915694366651386 + 0.74918691157557238 + 0.74921688179487611 + 0.7492468543247871 + 0.74927682916566951 + 0.74930680631788715 + 0.74933678578180396 + 0.7493667675577842 + 0.74939675164619024 + 0.74942673804738802 + 0.7494567267617398 + 0.74948671778961351 + 0.74951671113137164 + 0.74954670678737689 + 0.74957670475799698 + 0.74960670504359295 + 0.74963670764453449 + 0.74966671256118256 + 0.74969671979390362 + 0.74972672934306395 + 0.74975674120902647 + 0.74978675539215578 + 0.74981677189282037 + 0.74984679071138483 + 0.74987681184821398 + 0.74990683530367286 + 0.74993686107812962 + 0.74996688917194776 + 0.74999691958549386 + 0.75002695231913497 + 0.75005698737323578 + 0.75008702474816369 + 0.75011706444428339 + 0.75014710646196392 + 0.75017715080156877 + 0.75020719746346831 + 0.7502372464480247 + 0.75026729775560852 + 0.75029735138658515 + 0.75032740734132186 + 0.75035746562018601 + 0.7503875262235431 + 0.7504175891517606 + 0.75044765440521111 + 0.75047772198425344 + 0.75050779188926198 + 0.75053786412060275 + 0.75056793867864158 + 0.75059801556374939 + 0.75062809477629244 + 0.75065817631663656 + 0.75068826018515289 + 0.75071834638220958 + 0.75074843490817433 + 0.75077852576341508 + 0.75080861894829998 + 0.7508387144631985 + 0.75086881230848068 + 0.75089891248451279 + 0.75092901499166631 + 0.75095911983030628 + 0.75098922700080772 + 0.75101933650353381 + 0.75104944833885789 + 0.75107956250714869 + 0.75110967900877257 + 0.75113979784410323 + 0.75116991901350771 + 0.75120004251735795 + 0.75123016835602241 + 0.75126029652986992 + 0.75129042703927262 + 0.751320559884601 + 0.75135069506622365 + 0.75138083258451149 + 0.75141097243983512 + 0.75144111463256491 + 0.75147125916307167 + 0.75150140603172466 + 0.75153155523889792 + 0.75156170678495882 + 0.75159186067028194 + 0.75162201689523633 + 0.75165217546019314 + 0.75168233636552317 + 0.75171249961159936 + 0.75174266519879285 + 0.75177283312747478 + 0.75180300339801809 + 0.75183317601079247 + 0.75186335096617074 + 0.75189352826452605 + 0.75192370790622809 + 0.75195388989165202 + 0.75198407422116731 + 0.75201426089514722 + 0.75204444991396702 + 0.75207464127799462 + 0.75210483498760727 + 0.75213503104317281 + 0.75216522944506858 + 0.75219543019366431 + 0.75222563328933567 + 0.75225583873245438 + 0.75228604652339426 + 0.75231625666252888 + 0.75234646915023051 + 0.75237668398687274 + 0.75240690117283138 + 0.75243712070847679 + 0.75246734259418646 + 0.75249756683033087 + 0.75252779341728759 + 0.75255802235542901 + 0.75258825364512938 + 0.75261848728676106 + 0.75264872328070176 + 0.75267896162732395 + 0.75270920232700389 + 0.75273944538011595 + 0.75276969078703282 + 0.75279993854813232 + 0.75283018866378737 + 0.75286044113437434 + 0.75289069596026947 + 0.75292095314184404 + 0.75295121267947784 + 0.75298147457354403 + 0.75301173882441741 + 0.75304200543247612 + 0.75307227439809543 + 0.75310254572164992 + 0.75313281940351839 + 0.75316309544407212 + 0.75319337384369323 + 0.75322365460275353 + 0.75325393772162974 + 0.75328422320070065 + 0.75331451104034164 + 0.75334480124092951 + 0.75337509380284162 + 0.75340538872645335 + 0.7534356860121435 + 0.75346598566028755 + 0.75349628767126309 + 0.75352659204544892 + 0.75355689878322085 + 0.75358720788495626 + 0.75361751935103238 + 0.75364783318183071 + 0.75367814937772326 + 0.75370846793909119 + 0.75373878886631418 + 0.75376911215976605 + 0.75379943781982828 + 0.75382976584687678 + 0.75386009624129136 + 0.75389042900345149 + 0.75392076413373355 + 0.75395110163251711 + 0.75398144150018198 + 0.75401178373710642 + 0.75404212834366846 + 0.75407247532024801 + 0.75410282466722334 + 0.75413317638497424 + 0.75416353047388118 + 0.7541938869343241 + 0.75422424576667957 + 0.75425460697132962 + 0.75428497054865296 + 0.7543153364990276 + 0.7543457048228398 + 0.7543760755204626 + 0.75440644859228012 + 0.75443682403867274 + 0.75446720186001925 + 0.75449758205670014 + 0.7545279646290981 + 0.75455834957759182 + 0.75458873690256201 + 0.75461912660438968 + 0.7546495186834572 + 0.75467991314014371 + 0.75471030997483013 + 0.75474070918790115 + 0.75477111077973558 + 0.754801514750715 + 0.75483192110122022 + 0.75486232983163593 + 0.75489274094233982 + 0.75492315443371849 + 0.75495357030614962 + 0.75498398856001625 + 0.75501440919570184 + 0.75504483221358931 + 0.75507525761405825 + 0.75510568539749423 + 0.75513611556427829 + 0.75516654811479234 + 0.75519698304942151 + 0.75522742036854573 + 0.75525786007255047 + 0.75528830216181719 + 0.75531874663672971 + 0.75534919349767171 + 0.75537964274502689 + 0.75541009437917728 + 0.75544054840050656 + 0.75547100480940055 + 0.75550146360624304 + 0.7555319247914144 + 0.75556238836530054 + 0.75559285432828716 + 0.75562332268075649 + 0.75565379342309469 + 0.75568426655568388 + 0.75571474207890865 + 0.75574521999315658 + 0.75577570029881025 + 0.75580618299625413 + 0.75583666808587424 + 0.75586715556805351 + 0.75589764544317972 + 0.7559281377116378 + 0.755958632373812 + 0.75598912943008723 + 0.75601962888084973 + 0.7560501307264863 + 0.75608063496738165 + 0.75611114160392046 + 0.75614165063649141 + 0.75617216206547744 + 0.75620267589126722 + 0.75623319211424589 + 0.75626371073479826 + 0.756294231753315 + 0.75632475517017772 + 0.75635528098577687 + 0.75638580920049769 + 0.75641633981472756 + 0.75644687282885137 + 0.7564774082432586 + 0.75650794605833616 + 0.75653848627446962 + 0.75656902889204802 + 0.75659957391145904 + 0.75663012133308993 + 0.75666067115732616 + 0.75669122338455908 + 0.75672177801517437 + 0.75675233504956152 + 0.75678289448810632 + 0.75681345633119823 + 0.75684402057922695 + 0.75687458723257839 + 0.75690515629164212 + 0.75693572775680629 + 0.75696630162846212 + 0.75699687790699421 + 0.75702745659279591 + 0.75705803768625346 + 0.75708862118775699 + 0.75711920709769442 + 0.75714979541645588 + 0.75718038614443151 + 0.75721097928201131 + 0.75724157482958188 + 0.757272172787537 + 0.75730277315626349 + 0.75733337593615146 + 0.75736398112759329 + 0.7573945887309772 + 0.75742519874669401 + 0.75745581117513394 + 0.75748642601668781 + 0.75751704327174429 + 0.75754766294069753 + 0.75757828502393632 + 0.75760890952185167 + 0.75763953643483595 + 0.75767016576327662 + 0.7577007975075678 + 0.75773143166810064 + 0.75776206824526615 + 0.75779270723945524 + 0.7578233486510626 + 0.7578539924804738 + 0.75788463872808753 + 0.75791528739429104 + 0.75794593847947755 + 0.75797659198404022 + 0.75800724790837026 + 0.75803790625285916 + 0.75806856701790193 + 0.75809923020389003 + 0.75812989581121693 + 0.75816056384027219 + 0.75819123429145119 + 0.75822190716514559 + 0.75825258246175076 + 0.75828326018165837 + 0.75831394032526389 + 0.75834462289295557 + 0.75837530788513086 + 0.75840599530218333 + 0.75843668514450702 + 0.75846737741249193 + 0.75849807210653575 + 0.75852876922703238 + 0.75855946877437408 + 0.75859017074895663 + 0.75862087515117416 + 0.7586515819814208 + 0.75868229124008901 + 0.75871300292757826 + 0.75874371704427956 + 0.75877443359058883 + 0.7588051525669004 + 0.75883587397361074 + 0.7588665978111141 + 0.75889732407980515 + 0.75892805278008024 + 0.75895878391233573 + 0.75898951747696641 + 0.75902025347436519 + 0.75905099190493386 + 0.7590817327690621 + 0.75911247606715015 + 0.75914322179959459 + 0.75917396996678865 + 0.75920472056912902 + 0.75923547360701282 + 0.75926622908083696 + 0.7592969869909999 + 0.75932774733789521 + 0.75935851012192168 + 0.75938927534347667 + 0.75942004300295352 + 0.7594508131007548 + 0.75948158563727419 + 0.75951236061291083 + 0.75954313802806028 + 0.75957391788312179 + 0.75960470017849446 + 0.75963548491457411 + 0.75966627209175808 + 0.75969706171044604 + 0.75972785377103536 + 0.75975864827392403 + 0.75978944521951131 + 0.75982024460819497 + 0.75985104644037316 + 0.75988185071644698 + 0.75991265743681291 + 0.7599434666018704 + 0.75997427821201768 + 0.76000509226765633 + 0.7600359087691827 + 0.76006672771699701 + 0.76009754911150063 + 0.76012837295309033 + 0.76015919924216802 + 0.76019002797913193 + 0.76022085916438231 + 0.76025169279831939 + 0.76028252888134373 + 0.76031336741385547 + 0.76034420839625338 + 0.7603750518289395 + 0.7604058977123126 + 0.76043674604677702 + 0.76046759683272958 + 0.76049845007057282 + 0.76052930576070576 + 0.76056016390353243 + 0.76059102449945215 + 0.76062188754886739 + 0.76065275305217916 + 0.76068362100978659 + 0.76071449142209602 + 0.76074536428950501 + 0.76077623961241636 + 0.76080711739123297 + 0.76083799762635618 + 0.76086888031818889 + 0.76089976546713267 + 0.76093065307358854 + 0.76096154313796172 + 0.76099243566065355 + 0.76102333064206729 + 0.76105422808260448 + 0.76108512798266681 + 0.76111603034266129 + 0.76114693516298781 + 0.76117784244405162 + 0.76120875218625295 + 0.76123966438999868 + 0.76127057905569295 + 0.76130149618373544 + 0.76133241577453192 + 0.76136333782848631 + 0.76139426234600249 + 0.76142518932748426 + 0.76145611877333752 + 0.76148705068396449 + 0.76151798505977097 + 0.7615489219011613 + 0.7615798612085376 + 0.76161080298230777 + 0.76164174722287625 + 0.76167269393064729 + 0.76170364310602712 + 0.7617345947494164 + 0.76176554886122705 + 0.7617965054418615 + 0.76182746449172289 + 0.761858426011221 + 0.76188939000075873 + 0.76192035646074274 + 0.76195132539157961 + 0.76198229679367402 + 0.76201327066743274 + 0.76204424701326423 + 0.76207522583157161 + 0.762106207122764 + 0.76213719088724408 + 0.76216817712542262 + 0.76219916583770675 + 0.76223015702449959 + 0.76226115068621025 + 0.76229214682324753 + 0.76232314543601509 + 0.76235414652492395 + 0.76238515009037922 + 0.76241615613278835 + 0.76244716465256246 + 0.76247817565010534 + 0.76250918912582788 + 0.7625402050801362 + 0.76257122351343742 + 0.76260224442614311 + 0.76263326781865903 + 0.76266429369139477 + 0.7626953220447581 + 0.76272635287916035 + 0.76275738619500588 + 0.76278842199270802 + 0.76281946027267311 + 0.7628505010353106 + 0.76288154428103072 + 0.76291259001024159 + 0.76294363822335487 + 0.7629746889207788 + 0.76300574210292171 + 0.76303679777019562 + 0.76306785592300885 + 0.76309891656177153 + 0.763129979686896 + 0.76316104529879059 + 0.76319211339786563 + 0.7632231839845337 + 0.76325425705920324 + 0.76328533262228293 + 0.76331641067418898 + 0.76334749121532641 + 0.76337857424611155 + 0.76340965976695319 + 0.7634407477782621 + 0.76347183828045118 + 0.7635029312739311 + 0.76353402675911097 + 0.76356512473640725 + 0.76359622520622938 + 0.76362732816898826 + 0.76365843362509866 + 0.76368954157497004 + 0.76372065201901551 + 0.76375176495764796 + 0.76378288039127906 + 0.76381399832032171 + 0.76384511874519112 + 0.76387624166629531 + 0.76390736708405282 + 0.76393849499887012 + 0.76396962541116575 + 0.76400075832135173 + 0.76403189372984137 + 0.76406303163704681 + 0.76409417204338315 + 0.7641253149492625 + 0.76415646035510054 + 0.76418760826131094 + 0.76421875866830746 + 0.76424991157650257 + 0.76428106698631348 + 0.76431222489815276 + 0.76434338531243606 + 0.7643745482295774 + 0.76440571364999133 + 0.76443688157409184 + 0.76446805200229695 + 0.76449922493501898 + 0.76453040037267417 + 0.76456157831567717 + 0.76459275876444421 + 0.76462394171938963 + 0.76465512718092998 + 0.7646863151494816 + 0.76471750562545948 + 0.76474869860928163 + 0.76477989410136127 + 0.76481109210211484 + 0.76484229261195913 + 0.76487349563131279 + 0.76490470116059084 + 0.76493590920020826 + 0.76496711975058551 + 0.76499833281213614 + 0.76502954838527693 + 0.76506076647042864 + 0.76509198706800663 + 0.76512321017842633 + 0.76515443580210829 + 0.7651856639394683 + 0.76521689459092357 + 0.76524812775689499 + 0.76527936343779646 + 0.7653106016340474 + 0.76534184234606684 + 0.76537308557427441 + 0.76540433131908403 + 0.7654355795809189 + 0.76546683036019669 + 0.76549808365733152 + 0.76552933947274859 + 0.76556059780686381 + 0.76559185866009538 + 0.76562312203286653 + 0.76565438792558982 + 0.76568565633869079 + 0.76571692727258756 + 0.76574820072769811 + 0.76577947670444291 + 0.7658107552032416 + 0.76584203622451463 + 0.76587331976868234 + 0.7659046058361646 + 0.76593589442738219 + 0.76596718554275511 + 0.76599847918270403 + 0.76602977534765115 + 0.76606107403801338 + 0.76609237525421492 + 0.76612367899667644 + 0.76615498526581682 + 0.7661862940620604 + 0.76621760538582795 + 0.76624891923753857 + 0.76628023561761682 + 0.7663115545264817 + 0.76634287596455786 + 0.76637419993226652 + 0.76640552643002668 + 0.76643685545826523 + 0.76646818701740149 + 0.76649952110785846 + 0.76653085773006102 + 0.76656219688442695 + 0.76659353857138335 + 0.76662488279134966 + 0.76665622954475099 + 0.76668757883201266 + 0.76671893065355257 + 0.7667502850097998 + 0.76678164190117237 + 0.76681300132809749 + 0.76684436329099703 + 0.76687572779029645 + 0.76690709482641961 + 0.76693846439978841 + 0.76696983651082862 + 0.76700121115996589 + 0.76703258834762045 + 0.76706396807422028 + 0.76709535034018927 + 0.7671267351459532 + 0.7671581224919346 + 0.76718951237856126 + 0.76722090480625404 + 0.7672522997754424 + 0.76728369728654922 + 0.76731509734000236 + 0.76734649993622461 + 0.76737790507564219 + 0.76740931275868352 + 0.76744072298577126 + 0.76747213575733386 + 0.7675035510737942 + 0.7675349689355826 + 0.76756638934312404 + 0.7675978122968431 + 0.76762923779716852 + 0.76766066584452541 + 0.76769209643934433 + 0.76772352958204848 + 0.76775496527306497 + 0.76778640351282246 + 0.76781784430174826 + 0.76784928764026927 + 0.76788073352881314 + 0.76791218196780842 + 0.76794363295768275 + 0.7679750864988617 + 0.76800654259177614 + 0.76803800123685362 + 0.76806946243452001 + 0.76810092618520809 + 0.76813239248934384 + 0.76816386134735481 + 0.76819533275967256 + 0.76822680672672283 + 0.76825828324893741 + 0.76828976232674395 + 0.76832124396057044 + 0.76835272815084854 + 0.76838421489800623 + 0.76841570420247551 + 0.76844719606468259 + 0.76847869048506101 + 0.76851018746403732 + 0.76854168700204173 + 0.76857318909950811 + 0.76860469375686291 + 0.76863620097453833 + 0.76866771075296458 + 0.76869922309257066 + 0.76873073799379033 + 0.76876225545705412 + 0.76879377548279071 + 0.76882529807143118 + 0.7688568232234092 + 0.76888835093915608 + 0.76891988121910049 + 0.76895141406367873 + 0.76898294947331614 + 0.76901448744845136 + 0.7690460279895095 + 0.76907757109692909 + 0.76910911677113747 + 0.76914066501256961 + 0.7691722158216584 + 0.76920376919883526 + 0.76923532514453141 + 0.76926688365918183 + 0.76929844474321973 + 0.7693300083970751 + 0.7693615746211846 + 0.76939314341597986 + 0.76942471478189434 + 0.76945628871936178 + 0.7694878652288174 + 0.76951944431069108 + 0.76955102596542035 + 0.7695826101934371 + 0.76961419699517686 + 0.7696457863710735 + 0.76967737832156091 + 0.76970897284707296 + 0.76974056994804574 + 0.76977216962491291 + 0.76980377187811089 + 0.76983537670807334 + 0.7698669841152348 + 0.76989859410003136 + 0.76993020666289735 + 0.76996182180427053 + 0.76999343952458565 + 0.77002505982427716 + 0.77005668270378136 + 0.77008830816353269 + 0.77011993620397157 + 0.77015156682553088 + 0.77018320002864682 + 0.77021483581375638 + 0.7702464741812981 + 0.77027811513170497 + 0.7703097586654154 + 0.7703414047828685 + 0.77037305348449736 + 0.77040470477074241 + 0.77043635864203919 + 0.77046801509882623 + 0.77049967414153908 + 0.77053133577061683 + 0.77056299998649824 + 0.77059466678961897 + 0.77062633618041998 + 0.77065800815933505 + 0.77068968272680538 + 0.77072135988327006 + 0.77075303962916686 + 0.77078472196493331 + 0.77081640689100905 + 0.77084809440783153 + 0.7708797845158406 + 0.7709114772154777 + 0.77094317250717881 + 0.77097487039138568 + 0.77100657086853441 + 0.77103827393906854 + 0.77106997960342616 + 0.77110168786204725 + 0.77113339871537012 + 0.77116511216383665 + 0.77119682820788704 + 0.77122854684796138 + 0.77126026808449999 + 0.77129199191794517 + 0.77132371834873348 + 0.77135544737730899 + 0.77138717900411236 + 0.77141891322958378 + 0.77145065005416436 + 0.77148238947829628 + 0.7715141315024221 + 0.77154587612698067 + 0.77157762335241475 + 0.77160937317916711 + 0.7716411256076785 + 0.77167288063839001 + 0.77170463827174818 + 0.77173639850819042 + 0.77176816134816151 + 0.77179992679210263 + 0.77183169484045888 + 0.77186346549367135 + 0.77189523875218335 + 0.7719270146164362 + 0.77195879308687709 + 0.77199057416394545 + 0.7720223578480867 + 0.77205414413974427 + 0.77208593303936179 + 0.77211772454738081 + 0.77214951866424886 + 0.77218131539040757 + 0.77221311472630261 + 0.77224491667237605 + 0.77227672122907542 + 0.77230852839684261 + 0.77234033817612369 + 0.77237215056736253 + 0.77240396557100499 + 0.77243578318749528 + 0.7724676034172796 + 0.77249942626080192 + 0.77253125171850845 + 0.77256307979084549 + 0.77259491047825735 + 0.77262674378119045 + 0.772658579700091 + 0.77269041823540374 + 0.77272225938757688 + 0.77275410315705506 + 0.77278594954428503 + 0.77281779854971333 + 0.77284965017378848 + 0.77288150441695358 + 0.77291336127965715 + 0.77294522076234817 + 0.7729770828654734 + 0.7730089475894778 + 0.77304081493481058 + 0.77307268490191683 + 0.77310455749124907 + 0.77313643270325094 + 0.77316831053836976 + 0.77320019099705828 + 0.77323207407976025 + 0.77326395978692664 + 0.77329584811900309 + 0.77332773907644092 + 0.77335963265968954 + 0.77339152886919282 + 0.77342342770540584 + 0.77345532916877291 + 0.77348723325974511 + 0.77351913997877253 + 0.7735510493263027 + 0.7735829613027877 + 0.77361487590867528 + 0.77364679314441365 + 0.77367871301045643 + 0.77371063550725361 + 0.7737425606352516 + 0.77377448839490426 + 0.77380641878666023 + 0.77383835181097127 + 0.77387028746828779 + 0.7739022257590602 + 0.77393416668373893 + 0.77396611024277628 + 0.77399805643662289 + 0.77403000526572918 + 0.77406195673054967 + 0.77409391083153134 + 0.7741258675691306 + 0.77415782694379609 + 0.77418978895598101 + 0.77422175360613765 + 0.77425372089471745 + 0.77428569082217291 + 0.77431766338895724 + 0.77434963859552353 + 0.77438161644232462 + 0.77441359692980993 + 0.77444558005843644 + 0.77447756582865557 + 0.77450955424092061 + 0.77454154529568475 + 0.77457353899340353 + 0.77460553533452814 + 0.77463753431951254 + 0.77466953594881183 + 0.77470154022287985 + 0.77473354714217002 + 0.7747655567071382 + 0.77479756891823626 + 0.7748295837759217 + 0.77486160128064485 + 0.774893621432867 + 0.77492564423303645 + 0.77495766968161317 + 0.77498969777904925 + 0.77502172852580076 + 0.77505376192232367 + 0.7750857979690744 + 0.77511783666650713 + 0.77514987801507629 + 0.77518192201524205 + 0.77521396866745873 + 0.77524601797218118 + 0.77527806992986559 + 0.77531012454097059 + 0.77534218180595083 + 0.77537424172526503 + 0.77540630429936774 + 0.77543836952871781 + 0.77547043741377208 + 0.77550250795498554 + 0.7755345811528187 + 0.77556665700772875 + 0.77559873552017111 + 0.7756308166906043 + 0.77566290051948761 + 0.77569498700727824 + 0.77572707615443348 + 0.77575916796141431 + 0.77579126242867635 + 0.77582335955667903 + 0.77585545934588152 + 0.77588756179674156 + 0.77591966690971859 + 0.77595177468527199 + 0.77598388512385996 + 0.77601599822594336 + 0.77604811399198248 + 0.77608023242243496 + 0.77611235351776064 + 0.77614447727841962 + 0.77617660370487163 + 0.77620873279757663 + 0.7762408645569967 + 0.77627299898359192 + 0.77630513607782059 + 0.77633727584014467 + 0.77636941827102468 + 0.77640156337092081 + 0.77643371114029736 + 0.77646586157961073 + 0.77649801468932556 + 0.77653017046990214 + 0.77656232892180299 + 0.77659449004548708 + 0.77662665384142071 + 0.77665882031006273 + 0.77669098945187409 + 0.77672316126731933 + 0.77675533575686129 + 0.77678751292096115 + 0.77681969276008167 + 0.77685187527468602 + 0.77688406046523539 + 0.77691624833219475 + 0.77694843887602716 + 0.77698063209719592 + 0.77701282799616056 + 0.77704502657339025 + 0.7770772278293463 + 0.77710943176449232 + 0.77714163837929362 + 0.77717384767421183 + 0.77720605964971268 + 0.77723827430625969 + 0.77727049164431861 + 0.77730271166435305 + 0.77733493436682899 + 0.77736715975220838 + 0.77739938782095885 + 0.77743161857354659 + 0.77746385201043344 + 0.77749608813208582 + 0.77752832693897134 + 0.77756056843155263 + 0.77759281261029778 + 0.77762505947567107 + 0.77765730902814245 + 0.77768956126817279 + 0.77772181619623049 + 0.77775407381278205 + 0.77778633411829556 + 0.77781859711323609 + 0.77785086279807014 + 0.77788313117326657 + 0.7779154022392899 + 0.77794767599661085 + 0.77797995244569251 + 0.77801223158700594 + 0.77804451342101766 + 0.77807679794819495 + 0.77810908516900679 + 0.77814137508392045 + 0.77817366769340135 + 0.77820596299792388 + 0.77823826099795379 + 0.7782705616939587 + 0.77830286508640756 + 0.77833517117576823 + 0.77836747996251188 + 0.77839979144710791 + 0.77843210563002418 + 0.77846442251172854 + 0.77849674209269437 + 0.77852906437338931 + 0.77856138935428343 + 0.77859371703584468 + 0.7786260474185448 + 0.77865838050285563 + 0.77869071628924547 + 0.77872305477818615 + 0.77875539597014598 + 0.77878773986559902 + 0.77882008646501177 + 0.7788524357688601 + 0.77888478777761261 + 0.7789171424917396 + 0.77894949991171381 + 0.77898186003800718 + 0.77901422287109068 + 0.77904658841143859 + 0.7790789566595181 + 0.77911132761580371 + 0.77914370128076971 + 0.7791760776548855 + 0.77920845673862571 + 0.7792408385324614 + 0.77927322303686541 + 0.7793056102523126 + 0.77933800017927446 + 0.77937039281822396 + 0.77940278816963438 + 0.77943518623397889 + 0.77946758701173269 + 0.77949999050336916 + 0.77953239670935992 + 0.77956480563018404 + 0.77959721726630948 + 0.77962963161821364 + 0.77966204868637201 + 0.77969446847125645 + 0.77972689097334258 + 0.77975931619310634 + 0.77979174413102315 + 0.77982417478756549 + 0.7798566081632109 + 0.77988904425843353 + 0.77992148307370945 + 0.77995392460951474 + 0.77998636886632344 + 0.78001881584461386 + 0.78005126554486037 + 0.78008371796753728 + 0.78011617311312664 + 0.78014863098209941 + 0.78018109157493576 + 0.78021355489211019 + 0.78024602093409967 + 0.78027848970138225 + 0.78031096119443499 + 0.78034343541373652 + 0.78037591235976 + 0.78040839203298606 + 0.78044087443389343 + 0.78047335956295916 + 0.78050584742066043 + 0.7805383380074743 + 0.78057083132388005 + 0.78060332737035654 + 0.78063582614738303 + 0.78066832765543714 + 0.78070083189499795 + 0.78073333886654306 + 0.78076584857055376 + 0.78079836100750777 + 0.78083087617788627 + 0.78086339408216532 + 0.78089591472082853 + 0.78092843809435342 + 0.78096096420321992 + 0.78099349304790988 + 0.78102602462889925 + 0.78105855894667386 + 0.78109109600171167 + 0.78112363579449118 + 0.781156178325496 + 0.78118872359520641 + 0.78122127160410282 + 0.78125382235266749 + 0.78128637584138239 + 0.78131893207072634 + 0.78135149104118162 + 0.78138405275323097 + 0.78141661720735656 + 0.78144918440403732 + 0.78148175434376155 + 0.78151432702700441 + 0.78154690245425251 + 0.7815794806259887 + 0.78161206154269358 + 0.78164464520485244 + 0.78167723161294433 + 0.78170982076745776 + 0.78174241266887057 + 0.78177500731766958 + 0.78180760471433774 + 0.78184020485935879 + 0.78187280775321388 + 0.7819054133963923 + 0.78193802178937366 + 0.78197063293264324 + 0.78200324682668676 + 0.78203586347198772 + 0.78206848286903008 + 0.7821011050183011 + 0.78213372992028463 + 0.78216635757546293 + 0.78219898798432552 + 0.78223162114735623 + 0.78226425706503744 + 0.78229689573785899 + 0.78232953716630682 + 0.78236218135086333 + 0.78239482829201679 + 0.78242747799025325 + 0.782460130446061 + 0.78249278565992264 + 0.78252544363232657 + 0.78255810436375939 + 0.78259076785470927 + 0.78262343410566315 + 0.78265610311710743 + 0.78268877488952737 + 0.78272144942341493 + 0.7827541267192536 + 0.78278680677753398 + 0.78281948959874292 + 0.78285217518336969 + 0.78288486353189923 + 0.7829175546448246 + 0.78295024852262918 + 0.7829829451658058 + 0.78301564457483996 + 0.78304834675022295 + 0.78308105169244435 + 0.78311375940198935 + 0.78314646987935355 + 0.78317918312502055 + 0.78321189913948186 + 0.78324461792322719 + 0.78327733947675027 + 0.78331006380053492 + 0.78334279089507508 + 0.78337552076086214 + 0.78340825339838271 + 0.78344098880813051 + 0.78347372699059359 + 0.78350646794626599 + 0.78353921167563789 + 0.783571958179198 + 0.78360470745744004 + 0.78363745951085639 + 0.78367021433993567 + 0.78370297194517236 + 0.78373573232705684 + 0.78376849548608363 + 0.78380126142274154 + 0.78383403013752317 + 0.78386680163092326 + 0.78389957590343273 + 0.7839323529555462 + 0.78396513278775459 + 0.78399791540055308 + 0.7840307007944326 + 0.7840634889698862 + 0.78409627992741093 + 0.7841290736674964 + 0.7841618701906411 + 0.78419466949733307 + 0.78422747158806938 + 0.78426027646334551 + 0.78429308412365473 + 0.78432589456949098 + 0.78435870780134942 + 0.78439152381972421 + 0.7844243426251124 + 0.78445716421800615 + 0.7844899885989014 + 0.78452281576829574 + 0.78455564572668135 + 0.78458847847455804 + 0.78462131401241975 + 0.78465415234076086 + 0.78468699346007764 + 0.78471983737086792 + 0.78475268407362808 + 0.78478553356885272 + 0.78481838585704189 + 0.7848512409386903 + 0.78488409881429255 + 0.7849169594843507 + 0.78494982294935978 + 0.78498268920981462 + 0.78501555826621927 + 0.78504843011906333 + 0.78508130476885118 + 0.78511418221607776 + 0.78514706246124211 + 0.78517994550484149 + 0.78521283134737463 + 0.78524571998934267 + 0.78527861143124111 + 0.78531150567356911 + 0.78534440271682771 + 0.78537730256151261 + 0.7854102052081271 + 0.78544311065717054 + 0.78547601890914065 + 0.78550892996453692 + 0.78554184382385928 + 0.78557476048760921 + 0.78560767995628455 + 0.7856406022303889 + 0.78567352731042039 + 0.78570645519688109 + 0.7857393858902707 + 0.78577231939108949 + 0.78580525569983972 + 0.78583819481702322 + 0.78587113674314024 + 0.78590408147869328 + 0.78593702902418272 + 0.78596997938011104 + 0.78600293254698039 + 0.78603588852529349 + 0.78606884731555093 + 0.78610180891825732 + 0.78613477333391146 + 0.78616774056302008 + 0.78620071060608565 + 0.78623368346360778 + 0.78626665913609473 + 0.78629963762404387 + 0.78633261892796391 + 0.78636560304835434 + 0.78639858998572221 + 0.78643157974057065 + 0.78646457231340117 + 0.7864975677047209 + 0.78653056591503323 + 0.78656356694484175 + 0.78659657079465384 + 0.78662957746497131 + 0.78666258695630142 + 0.78669559926914634 + 0.78672861440401354 + 0.78676163236140895 + 0.78679465314183439 + 0.78682767674579979 + 0.78686070317380907 + 0.78689373242637017 + 0.7869267645039858 + 0.78695979940716343 + 0.78699283713641166 + 0.78702587769223464 + 0.78705892107513886 + 0.78709196728563446 + 0.78712501632422616 + 0.78715806819142031 + 0.78719112288772564 + 0.78722418041364683 + 0.78725724076969816 + 0.78729030395637911 + 0.78732336997420382 + 0.78735643882367934 + 0.78738951050530881 + 0.78742258501960705 + 0.78745566236707931 + 0.78748874254823642 + 0.78752182556358385 + 0.78755491141363454 + 0.78758800009889585 + 0.78762109161987526 + 0.78765418597708414 + 0.78768728317103198 + 0.78772038320222815 + 0.78775348607118245 + 0.78778659177840638 + 0.78781970032440585 + 0.78785281170969823 + 0.78788592593478768 + 0.787919043000188 + 0.78795216290640901 + 0.78798528565396109 + 0.78801841124335592 + 0.78805153967510566 + 0.78808467094972068 + 0.78811780506771312 + 0.78815094202959513 + 0.78818408183587552 + 0.7882172244870701 + 0.7882503699836898 + 0.78828351832624699 + 0.78831666951525248 + 0.78834982355122063 + 0.78838298043466426 + 0.78841614016609629 + 0.78844930274602743 + 0.78848246817497458 + 0.78851563645344691 + 0.78854880758196289 + 0.78858198156103232 + 0.7886151583911718 + 0.78864833807289281 + 0.7886815206067106 + 0.78871470599314031 + 0.78874789423269531 + 0.78878108532588942 + 0.78881427927323977 + 0.78884747607525996 + 0.78888067573246201 + 0.78891387824536696 + 0.78894708361448707 + 0.7889802918403378 + 0.78901350292343519 + 0.78904671686429528 + 0.78907993366343376 + 0.78911315332136678 + 0.78914637583861069 + 0.78917960121568131 + 0.78921282945309712 + 0.78924606055137214 + 0.78927929451102519 + 0.78931253133257406 + 0.7893457710165338 + 0.78937901356342244 + 0.789412258973757 + 0.78944550724805784 + 0.78947875838683967 + 0.78951201239062152 + 0.78954526925992197 + 0.78957852899526004 + 0.78961179159715078 + 0.78964505706611687 + 0.78967832540267568 + 0.78971159660734613 + 0.78974487068064569 + 0.78977814762309551 + 0.78981142743521304 + 0.78984471011752122 + 0.78987799567053585 + 0.78991128409477851 + 0.78994457539077034 + 0.78997786955903126 + 0.79001116660007908 + 0.79004446651443727 + 0.79007776930262397 + 0.79011107496515887 + 0.79014438350256777 + 0.79017769491536871 + 0.79021100920408383 + 0.79024432636923325 + 0.79027764641133902 + 0.79031096933092182 + 0.79034429512850723 + 0.79037762380461229 + 0.79041095535976302 + 0.79044428979448011 + 0.79047762710928771 + 0.79051096730470494 + 0.79054431038125828 + 0.7905776563394683 + 0.79061100517985994 + 0.7906443569029542 + 0.79067771150927568 + 0.79071106899934951 + 0.79074442937369682 + 0.79077779263284431 + 0.79081115877731178 + 0.79084452780762815 + 0.79087789972431455 + 0.79091127452789833 + 0.7909446522189012 + 0.7909780327978484 + 0.79101141626526739 + 0.79104480262168198 + 0.79107819186761585 + 0.7911115840035966 + 0.79114497903014991 + 0.79117837694779969 + 0.79121177775707385 + 0.79124518145849654 + 0.79127858805259554 + 0.79131199753989712 + 0.79134540992092917 + 0.79137882519621428 + 0.79141224336628246 + 0.7914456644316602 + 0.79147908839287573 + 0.79151251525045552 + 0.79154594500492625 + 0.79157937765681463 + 0.79161281320665289 + 0.79164625165496416 + 0.7916796930022808 + 0.79171313724912806 + 0.79174658439603463 + 0.79178003444353151 + 0.79181348739214386 + 0.79184694324240446 + 0.79188040199484055 + 0.79191386364998162 + 0.79194732820835478 + 0.79198079567049517 + 0.7920142660369266 + 0.79204773930818195 + 0.79208121548479149 + 0.79211469456728612 + 0.79214817655619196 + 0.79218166145204638 + 0.7922151492553734 + 0.79224863996670691 + 0.79228213358657851 + 0.79231563011551853 + 0.79234912955405878 + 0.79238263190273117 + 0.79241613716206438 + 0.79244964533259421 + 0.79248315641484912 + 0.79251667040936524 + 0.79255018731667148 + 0.79258370713730164 + 0.79261722987178862 + 0.79265075552066511 + 0.79268428408446168 + 0.79271781556371501 + 0.79275134995895757 + 0.79278488727072094 + 0.79281842749953946 + 0.79285197064594815 + 0.79288551671048035 + 0.79291906569366899 + 0.79295261759604929 + 0.79298617241815617 + 0.79301973016052341 + 0.79305329082368603 + 0.7930868544081775 + 0.7931204209145355 + 0.79315399034329348 + 0.79318756269498703 + 0.79322113797014981 + 0.79325471616932142 + 0.79328829729303774 + 0.79332188134182902 + 0.79335546831623849 + 0.79338905821679684 + 0.79342265104404364 + 0.79345624679851545 + 0.79348984548074974 + 0.79352344709127964 + 0.79355705163064683 + 0.79359065909938586 + 0.79362426949803533 + 0.79365788282713345 + 0.79369149908721537 + 0.79372511827882297 + 0.79375874040249128 + 0.7937923654587592 + 0.79382599344816551 + 0.79385962437124891 + 0.7938932582285485 + 0.7939268950206031 + 0.79396053474795203 + 0.79399417741113254 + 0.79402782301068753 + 0.79406147154715423 + 0.79409512302107244 + 0.79412877743298316 + 0.79416243478342596 + 0.79419609507293865 + 0.79422975830206632 + 0.79426342447134701 + 0.79429709358132217 + 0.79433076563252991 + 0.79436444062551581 + 0.79439811856081799 + 0.79443179943897824 + 0.7944654832605389 + 0.79449917002604165 + 0.79453285973602905 + 0.79456655239104113 + 0.79460024799162232 + 0.79463394653831099 + 0.79466764803165746 + 0.79470135247219442 + 0.79473505986047233 + 0.79476877019703174 + 0.79480248348241744 + 0.79483619971716823 + 0.79486991890183289 + 0.79490364103695221 + 0.79493736612307142 + 0.79497109416073319 + 0.79500482515048287 + 0.79503855909286547 + 0.79507229598842244 + 0.79510603583770079 + 0.79513977864124585 + 0.79517352439960132 + 0.79520727311331441 + 0.7952410247829288 + 0.79527477940899005 + 0.79530853699204196 + 0.79534229753263408 + 0.7953760610313122 + 0.79540982748862032 + 0.79544359690510447 + 0.79547736928131252 + 0.79551114461779238 + 0.79554492291508838 + 0.79557870417375076 + 0.79561248839432164 + 0.79564627557735335 + 0.79568006572339056 + 0.79571385883298329 + 0.79574765490667632 + 0.79578145394502042 + 0.79581525594856184 + 0.79584906091784946 + 0.79588286885343229 + 0.79591667975586089 + 0.79595049362568038 + 0.79598431046343976 + 0.79601813026969193 + 0.79605195304498388 + 0.79608577878986531 + 0.79611960750488875 + 0.79615343919059811 + 0.79618727384754862 + 0.79622111147628771 + 0.79625495207736685 + 0.79628879565133748 + 0.79632264219874949 + 0.79635649172015255 + 0.79639034421609833 + 0.79642419968713896 + 0.79645805813382398 + 0.79649191955670751 + 0.79652578395634144 + 0.79655965133327433 + 0.79659352168806008 + 0.79662739502125079 + 0.79666127133340092 + 0.79669515062505902 + 0.79672903289677921 + 0.79676291814911815 + 0.79679680638262251 + 0.79683069759785263 + 0.79686459179535563 + 0.79689848897568805 + 0.79693238913940279 + 0.79696629228705462 + 0.79700019841919867 + 0.79703410753638593 + 0.79706801963917351 + 0.79710193472811453 + 0.79713585280376464 + 0.79716977386668042 + 0.79720369791741186 + 0.79723762495652006 + 0.79727155498455671 + 0.79730548800207757 + 0.79733942400964164 + 0.79737336300780137 + 0.79740730499711399 + 0.7974412499781377 + 0.7974751979514263 + 0.79750914891753577 + 0.79754310287702612 + 0.79757705983045346 + 0.79761101977837401 + 0.79764498272134399 + 0.79767894865992195 + 0.79771291759466778 + 0.79774688952613637 + 0.79778086445488805 + 0.7978148423814776 + 0.79784882330646723 + 0.79788280723041227 + 0.79791679415387495 + 0.79795078407741038 + 0.79798477700157955 + 0.79801877292694334 + 0.79805277185405687 + 0.79808677378348325 + 0.79812077871578146 + 0.79815478665150941 + 0.79818879759122963 + 0.79822281153550001 + 0.79825682848488388 + 0.79829084843994069 + 0.79832487140123032 + 0.7983588973693142 + 0.79839292634475389 + 0.79842695832810973 + 0.79846099331994302 + 0.79849503132081812 + 0.79852907233129289 + 0.79856311635193333 + 0.79859716338329767 + 0.79863121342595023 + 0.79866526648045311 + 0.79869932254737064 + 0.79873338162726326 + 0.79876744372069575 + 0.79880150882822842 + 0.79883557695042973 + 0.79886964808785865 + 0.79890372224107797 + 0.79893779941065812 + 0.79897187959715654 + 0.79900596280113978 + 0.79904004902317494 + 0.79907413826382123 + 0.79910823052364788 + 0.79914232580321798 + 0.79917642410309697 + 0.79921052542385007 + 0.79924462976604094 + 0.79927873713023878 + 0.79931284751700737 + 0.79934696092691249 + 0.79938107736052155 + 0.79941519681839868 + 0.7994493193011134 + 0.79948344480922984 + 0.79951757334331397 + 0.7995517049039359 + 0.79958583949166162 + 0.79961997710705945 + 0.79965411775069362 + 0.79968826142313443 + 0.79972240812495032 + 0.79975655785670974 + 0.79979071061897755 + 0.79982486641232575 + 0.79985902523732155 + 0.79989318709453161 + 0.79992735198452847 + 0.79996151990788134 + 0.7999956908651551 + 0.80002986485692273 + 0.80006404188375335 + 0.80009822194621805 + 0.80013240504488436 + 0.80016659118032329 + 0.80020078035310616 + 0.80023497256380272 + 0.80026916781298441 + 0.80030336610122244 + 0.80033756742908513 + 0.8003717717971458 + 0.80040597920597623 + 0.80044018965614827 + 0.80047440314823393 + 0.80050861968280151 + 0.80054283926042658 + 0.80057706188168154 + 0.80061128754713673 + 0.80064551625736813 + 0.80067974801294617 + 0.8007139828144435 + 0.80074822066243456 + 0.80078246155749355 + 0.80081670550019157 + 0.80085095249110316 + 0.80088520253080309 + 0.80091945561986611 + 0.80095371175886521 + 0.80098797094837348 + 0.80102223318896981 + 0.8010564984812234 + 0.80109076682571534 + 0.80112503822301517 + 0.801159312673702 + 0.80119359017834946 + 0.80122787073753454 + 0.80126215435183323 + 0.80129644102181907 + 0.80133073074807171 + 0.8013650235311649 + 0.80139931937167852 + 0.80143361827018444 + 0.80146792022726265 + 0.80150222524349102 + 0.80153653331944585 + 0.80157084445570348 + 0.80160515865284376 + 0.80163947591144324 + 0.80167379623208046 + 0.80170811961533361 + 0.80174244606178136 + 0.80177677557200033 + 0.80181110814657308 + 0.8018454437860727 + 0.80187978249108549 + 0.80191412426218489 + 0.80194846909995332 + 0.80198281700497032 + 0.80201716797781453 + 0.80205152201906749 + 0.8020858791293084 + 0.80212023930911647 + 0.80215460255907689 + 0.80218896887976365 + 0.80222333827176184 + 0.80225771073565322 + 0.80229208627201754 + 0.80232646488143633 + 0.80236084656449169 + 0.80239523132176327 + 0.80242961915383726 + 0.80246401006129331 + 0.80249840404471406 + 0.80253280110468117 + 0.80256720124177916 + 0.80260160445659035 + 0.80263601074969726 + 0.80267042012168399 + 0.80270483257313507 + 0.8027392481046316 + 0.80277366671675787 + 0.80280808841009876 + 0.80284251318523903 + 0.80287694104276164 + 0.80291137198325335 + 0.80294580600729559 + 0.802980243115477 + 0.80301468330837911 + 0.80304912658659111 + 0.80308357295069621 + 0.80311802240127794 + 0.80315247493892561 + 0.80318693056422497 + 0.80322138927776143 + 0.80325585108012088 + 0.80329031597189093 + 0.80332478395365747 + 0.80335925502600825 + 0.80339372918952945 + 0.80342820644480917 + 0.80346268679243527 + 0.80349717023299416 + 0.80353165676707405 + 0.80356614639526514 + 0.80360063911815405 + 0.80363513493632721 + 0.80366963385037704 + 0.80370413586089018 + 0.80373864096845549 + 0.80377314917366183 + 0.80380766047710173 + 0.80384217487936038 + 0.80387669238103043 + 0.8039112129826993 + 0.80394573668496006 + 0.80398026348840179 + 0.80401479339361392 + 0.80404932640118787 + 0.80408386251171649 + 0.80411840172578608 + 0.80415294404399185 + 0.80418748946692531 + 0.80422203799517444 + 0.80425658962933477 + 0.80429114436999649 + 0.80432570221775146 + 0.80436026317319331 + 0.80439482723691469 + 0.80442939440950734 + 0.80446396469156367 + 0.80449853808367811 + 0.80453311458644083 + 0.80456769420045027 + 0.80460227692629704 + 0.80463686276457402 + 0.80467145171587751 + 0.80470604378080213 + 0.80474063895993919 + 0.80477523725388522 + 0.80480983866323341 + 0.80484444318858261 + 0.80487905083052413 + 0.80491366158965494 + 0.80494827546657033 + 0.80498289246186783 + 0.80501751257613885 + 0.8050521358099807 + 0.805086762163993 + 0.80512139163877139 + 0.80515602423490973 + 0.80519065995300565 + 0.80522529879365889 + 0.80525994075746354 + 0.80529458584501967 + 0.80532923405692125 + 0.80536388539376835 + 0.80539853985615939 + 0.80543319744469255 + 0.80546785815996425 + 0.80550252200257499 + 0.8055371889731231 + 0.80557185907220541 + 0.80560653230042445 + 0.80564120865837707 + 0.80567588814666402 + 0.80571057076588426 + 0.80574525651663664 + 0.80577994539952424 + 0.80581463741514425 + 0.80584933256409796 + 0.80588403084698834 + 0.80591873226441102 + 0.80595343681697329 + 0.80598814450527079 + 0.80602285532990869 + 0.80605756929148709 + 0.80609228639060748 + 0.80612700662787173 + 0.80616173000388358 + 0.80619645651924321 + 0.80623118617455447 + 0.80626591897041755 + 0.80630065490744041 + 0.80633539398622156 + 0.80637013620736708 + 0.80640488157147949 + 0.80643963007916142 + 0.80647438173101715 + 0.80650913652765333 + 0.8065438944696689 + 0.80657865555767427 + 0.80661341979226864 + 0.80664818717406073 + 0.8066829577036555 + 0.80671773138165614 + 0.80675250820866762 + 0.80678728818529932 + 0.80682207131215067 + 0.80685685758983483 + 0.80689164701895322 + 0.80692643960011168 + 0.80696123533392128 + 0.8069960342209842 + 0.80703083626190986 + 0.80706564145730442 + 0.80710044980777562 + 0.8071352613139311 + 0.80717007597637946 + 0.80720489379572469 + 0.80723971477257872 + 0.80727453890754997 + 0.80730936620124505 + 0.80734419665427415 + 0.80737903026724389 + 0.80741386704076479 + 0.80744870697544735 + 0.80748355007189865 + 0.80751839633072942 + 0.80755324575255039 + 0.80758809833796863 + 0.8076229540875991 + 0.8076578130020472 + 0.80769267508192588 + 0.80772754032784644 + 0.80776240874042027 + 0.80779728032025677 + 0.80783215506796946 + 0.80786703298416807 + 0.80790191406946399 + 0.80793679832447107 + 0.80797168574980127 + 0.80800657634606421 + 0.80804147011387617 + 0.80807636705384878 + 0.80811126716659454 + 0.80814617045272541 + 0.8081810769128559 + 0.80821598654760018 + 0.80825089935756889 + 0.80828581534338206 + 0.80832073450564867 + 0.80835565684498534 + 0.80839058236200467 + 0.80842551105732163 + 0.80846044293155295 + 0.80849537798531379 + 0.80853031621921689 + 0.80856525763387976 + 0.80860020222991924 + 0.80863515000794894 + 0.80867010096858394 + 0.80870505511244373 + 0.80874001244014393 + 0.80877497295229994 + 0.80880993664952772 + 0.80884490353244864 + 0.8088798736016749 + 0.80891484685782811 + 0.80894982330152232 + 0.80898480293337971 + 0.80901978575401412 + 0.80905477176404617 + 0.8090897609640938 + 0.80912475335477541 + 0.80915974893670961 + 0.8091947477105168 + 0.8092297496768156 + 0.80926475483622273 + 0.80929976318936281 + 0.80933477473685478 + 0.80936978947931359 + 0.80940480741736409 + 0.80943982855162555 + 0.80947485288272081 + 0.80950988041126537 + 0.8095449111378844 + 0.8095799450632013 + 0.80961498218783157 + 0.8096500225124007 + 0.80968506603752821 + 0.80972011276383793 + 0.80975516269195358 + 0.80979021582249511 + 0.80982527215608435 + 0.80986033169334726 + 0.80989539443490388 + 0.80993046038137861 + 0.80996552953339562 + 0.81000060189157896 + 0.81003567745654936 + 0.81007075622893499 + 0.81010583820935667 + 0.81014092339844113 + 0.81017601179681265 + 0.81021110340509439 + 0.81024619822391297 + 0.81028129625389356 + 0.81031639749566109 + 0.81035150194984085 + 0.81038660961705977 + 0.81042172049794325 + 0.81045683459311835 + 0.810491951903209 + 0.81052707242884636 + 0.81056219617065217 + 0.81059732312925803 + 0.81063245330528755 + 0.81066758669937089 + 0.81070272331213367 + 0.81073786314420582 + 0.81077300619621351 + 0.81080815246878712 + 0.81084330196255239 + 0.81087845467813813 + 0.81091361061617639 + 0.81094876977729546 + 0.8109839321621205 + 0.81101909777128556 + 0.81105426660541957 + 0.81108943866515115 + 0.81112461395111146 + 0.81115979246392722 + 0.81119497420423536 + 0.81123015917266139 + 0.81126534736983791 + 0.81130053879639852 + 0.8113357334529705 + 0.81137093134018723 + 0.81140613245868032 + 0.81144133680908137 + 0.81147654439202188 + 0.81151175520813557 + 0.81154696925805458 + 0.81158218654241232 + 0.81161740706184105 + 0.81165263081697292 + 0.81168785780844377 + 0.81172308803688409 + 0.81175832150293015 + 0.81179355820721621 + 0.8118287981503729 + 0.81186404133303847 + 0.81189928775584597 + 0.81193453741942778 + 0.81196979032442473 + 0.81200504647146576 + 0.81204030586119169 + 0.81207556849423368 + 0.81211083437123099 + 0.81214610349281835 + 0.81218137585963146 + 0.8122166514723056 + 0.81225193033147991 + 0.81228721243779034 + 0.81232249779187404 + 0.81235778639436695 + 0.81239307824591078 + 0.81242837334713747 + 0.81246367169868872 + 0.81249897330120069 + 0.81253427815531343 + 0.81256958626166309 + 0.81260489762088994 + 0.81264021223363414 + 0.81267553010053428 + 0.81271085122222697 + 0.81274617559935447 + 0.81278150323255549 + 0.81281683412246919 + 0.81285216826973783 + 0.81288750567500234 + 0.81292284633889822 + 0.81295819026207383 + 0.81299353744516301 + 0.81302888788881056 + 0.81306424159365787 + 0.81309959856034619 + 0.81313495878951725 + 0.81317032228181441 + 0.8132056890378756 + 0.81324105905834809 + 0.81327643234387392 + 0.81331180889509302 + 0.81334718871265121 + 0.81338257179719065 + 0.81341795814935536 + 0.81345334776978773 + 0.81348874065913379 + 0.81352413681803626 + 0.81355953624713928 + 0.81359493894708745 + 0.81363034491852748 + 0.81366575416210396 + 0.81370116667845793 + 0.81373658246823999 + 0.81377200153209317 + 0.81380742387066263 + 0.81384284948459718 + 0.81387827837454019 + 0.81391371054114103 + 0.81394914598504309 + 0.81398458470689561 + 0.8140200267073443 + 0.81405547198703665 + 0.81409092054662247 + 0.81412637238674546 + 0.81416182750805743 + 0.81419728591120244 + 0.8142327475968324 + 0.81426821256559367 + 0.8143036808181382 + 0.81433915235511034 + 0.81437462717716247 + 0.81441010528494306 + 0.81444558667910061 + 0.81448107136028758 + 0.81451655932915279 + 0.81455205058634705 + 0.81458754513251919 + 0.81462304296832022 + 0.8146585440944013 + 0.81469404851141503 + 0.81472955622001297 + 0.81476506722084263 + 0.81480058151455881 + 0.81483609910181332 + 0.81487161998325963 + 0.81490714415954546 + 0.81494267163132839 + 0.81497820239926 + 0.81501373646399056 + 0.81504927382617576 + 0.81508481448646963 + 0.81512035844552444 + 0.81515590570399621 + 0.81519145626253553 + 0.81522701012180032 + 0.81526256728243951 + 0.81529812774511512 + 0.81533369151047819 + 0.81536925857918341 + 0.81540482895188737 + 0.81544040262924511 + 0.81547597961191343 + 0.81551155990054747 + 0.81554714349580437 + 0.8155827303983374 + 0.81561832060880757 + 0.8156539141278687 + 0.81568951095618003 + 0.81572511109439905 + 0.81576071454318133 + 0.81579632130318502 + 0.81583193137506749 + 0.81586754475949075 + 0.81590316145710884 + 0.8159387814685819 + 0.81597440479456795 + 0.81601003143572903 + 0.81604566139271983 + 0.8160812946662046 + 0.81611693125683982 + 0.81615257116528606 + 0.8161882143922059 + 0.81622386093825428 + 0.81625951080409587 + 0.81629516399039148 + 0.81633082049780048 + 0.81636648032698556 + 0.81640214347860807 + 0.81643780995332937 + 0.81647347975180862 + 0.81650915287471126 + 0.8165448293226989 + 0.81658050909643309 + 0.81661619219657766 + 0.81665187862379596 + 0.81668756837875023 + 0.8167232614621025 + 0.81675895787452035 + 0.81679465761666414 + 0.81683036068919823 + 0.81686606709278853 + 0.81690177682809784 + 0.81693748989579218 + 0.81697320629653647 + 0.81700892603099329 + 0.8170446490998311 + 0.81708037550371482 + 0.81711610524331135 + 0.81715183831928373 + 0.81718757473229908 + 0.81722331448302443 + 0.8172590575721288 + 0.81729480400027577 + 0.81733055376813291 + 0.81736630687636735 + 0.8174020633256508 + 0.81743782311664492 + 0.81747358625002164 + 0.81750935272644865 + 0.81754512254659184 + 0.81758089571112513 + 0.81761667222071277 + 0.81765245207602322 + 0.81768823527773005 + 0.81772402182650028 + 0.81775981172300405 + 0.81779560496791193 + 0.81783140156189249 + 0.81786720150561854 + 0.81790300479975886 + 0.81793881144498637 + 0.81797462144196975 + 0.81801043479138047 + 0.81804625149389154 + 0.81808207155017409 + 0.81811789496090137 + 0.81815372172674306 + 0.8181895518483725 + 0.81822538532646327 + 0.81826122216168895 + 0.81829706235472133 + 0.81833290590623242 + 0.81836875281689814 + 0.81840460308739416 + 0.81844045671838694 + 0.81847631371055862 + 0.81851217406457932 + 0.81854803778112561 + 0.81858390486087185 + 0.81861977530449259 + 0.81865564911266442 + 0.81869152628606023 + 0.81872740682535861 + 0.81876329073123644 + 0.81879917800436697 + 0.81883506864542721 + 0.81887096265509596 + 0.81890686003404689 + 0.81894276078295936 + 0.81897866490251048 + 0.81901457239337805 + 0.81905048325623953 + 0.81908639749177248 + 0.81912231510065681 + 0.81915823608356853 + 0.81919416044118931 + 0.81923008817419563 + 0.81926601928326714 + 0.81930195376908432 + 0.81933789163232562 + 0.81937383287367127 + 0.81940977749380151 + 0.81944572549339545 + 0.81948167687313522 + 0.81951763163370195 + 0.8195535897757763 + 0.81958955130003741 + 0.81962551620716995 + 0.81966148449785148 + 0.81969745617276901 + 0.81973343123259967 + 0.81976940967802903 + 0.81980539150973841 + 0.81984137672841151 + 0.81987736533472988 + 0.81991335732937742 + 0.81994935271303782 + 0.81998535148639506 + 0.82002135365013307 + 0.82005735920493594 + 0.82009336815148803 + 0.82012938049047335 + 0.82016539622257645 + 0.82020141534848179 + 0.82023743786887982 + 0.82027346378444932 + 0.82030949309588086 + 0.82034552580385733 + 0.82038156190906553 + 0.82041760141219466 + 0.82045364431392764 + 0.82048969061495358 + 0.82052574031595815 + 0.82056179341763213 + 0.82059784992065743 + 0.82063390982572726 + 0.82066997313352741 + 0.82070603984474555 + 0.82074210996007169 + 0.82077818348019349 + 0.82081426040580097 + 0.82085034073758012 + 0.8208864244762254 + 0.8209225116224228 + 0.82095860217686489 + 0.8209946961402379 + 0.82103079351323638 + 0.82106689429654711 + 0.82110299849086665 + 0.82113910609687979 + 0.82117521711527974 + 0.82121133154675907 + 0.82124744939200911 + 0.82128357065172286 + 0.82131969532659166 + 0.82135582341730695 + 0.82139195492456218 + 0.82142808984905058 + 0.82146422819146425 + 0.82150036995249842 + 0.8215365151328452 + 0.82157266373319826 + 0.82160881575425382 + 0.82164497119670388 + 0.82168113006124466 + 0.82171729234856838 + 0.82175345805937317 + 0.82178962719435 + 0.82182579975420089 + 0.82186197573961661 + 0.82189815515129216 + 0.82193433798992799 + 0.82197052425621908 + 0.82200671395085878 + 0.82204290707454963 + 0.8220791036279832 + 0.82211530361186069 + 0.82215150702687723 + 0.82218771387373257 + 0.82222392415312229 + 0.82226013786574759 + 0.82229635501230458 + 0.82233257559349326 + 0.82236879961001308 + 0.82240502706256247 + 0.82244125795184109 + 0.82247749227854938 + 0.82251373004338579 + 0.82254997124705043 + 0.82258621589024594 + 0.82262246397366878 + 0.82265871549802372 + 0.8226949704640133 + 0.82273122887233263 + 0.82276749072368849 + 0.82280375601877997 + 0.8228400247583102 + 0.82287629694298225 + 0.82291257257349748 + 0.82294885165055942 + 0.82298513417486951 + 0.82302142014713331 + 0.82305770956805446 + 0.82309400243833286 + 0.82313029875867616 + 0.82316659852978857 + 0.82320290175236999 + 0.82323920842713061 + 0.82327551855477454 + 0.82331183213600234 + 0.82334814917152443 + 0.82338446966204315 + 0.82342079360826703 + 0.82345712101089918 + 0.82349345187065004 + 0.8235297861882227 + 0.82356612396432405 + 0.82360246519966118 + 0.82363880989494531 + 0.82367515805087954 + 0.82371150966817364 + 0.82374786474753248 + 0.82378422328967005 + 0.82382058529529001 + 0.82385695076510201 + 0.82389331969981772 + 0.82392969210014322 + 0.82396606796678651 + 0.82400244730046179 + 0.82403883010187895 + 0.82407521637174275 + 0.82411160611076928 + 0.82414799931966709 + 0.82418439599914495 + 0.82422079614991728 + 0.82425719977269496 + 0.82429360686818698 + 0.8243300174371081 + 0.82436643148016753 + 0.82440284899808036 + 0.82443926999155792 + 0.8244756944613133 + 0.82451212240806038 + 0.82454855383251036 + 0.824584988735377 + 0.82462142711737607 + 0.82465786897922122 + 0.82469431432162643 + 0.82473076314530391 + 0.82476721545097142 + 0.82480367123934151 + 0.82484013051113214 + 0.82487659326705798 + 0.82491305950783334 + 0.82494952923417497 + 0.82498600244679943 + 0.82502247914642157 + 0.82505895933376006 + 0.82509544300953219 + 0.82513193017445285 + 0.82516842082924113 + 0.82520491497461435 + 0.8252414126112898 + 0.82527791373998716 + 0.8253144183614235 + 0.82535092647631703 + 0.82538743808538717 + 0.82542395318935369 + 0.82546047178893656 + 0.82549699388485409 + 0.82553351947782594 + 0.82557004856857263 + 0.82560658115781638 + 0.82564311724627348 + 0.82567965683466871 + 0.82571619992372236 + 0.82575274651415342 + 0.82578929660668843 + 0.82582585020204247 + 0.82586240730094429 + 0.82589896790411121 + 0.82593553201226844 + 0.82597209962613682 + 0.82600867074644235 + 0.82604524537390789 + 0.82608182350925363 + 0.82611840515320667 + 0.82615499030648898 + 0.82619157896982642 + 0.8262281711439412 + 0.82626476682956285 + 0.82630136602741 + 0.82633796873821463 + 0.82637457496269717 + 0.82641118470158581 + 0.82644779795560552 + 0.82648441472548273 + 0.82652103501194407 + 0.82655765881571841 + 0.82659428613752894 + 0.82663091697810631 + 0.82666755133817582 + 0.82670418921846678 + 0.82674083061970616 + 0.82677747554262182 + 0.82681412398794296 + 0.82685077595639933 + 0.82688743144871857 + 0.82692409046562854 + 0.8269607530078632 + 0.82699741907614832 + 0.82703408867121631 + 0.82707076179379524 + 0.8271074384446172 + 0.82714411862441284 + 0.82718080233391267 + 0.827217489573849 + 0.8272541803449508 + 0.82729087464795281 + 0.8273275724835859 + 0.82736427385258093 + 0.82740097875567309 + 0.82743768719359168 + 0.82747439916707366 + 0.82751111467685079 + 0.82754783372365426 + 0.8275845563082217 + 0.82762128243128286 + 0.82765801209357759 + 0.82769474529583542 + 0.82773148203879476 + 0.82776822232318537 + 0.82780496614974963 + 0.82784171351921765 + 0.82787846443232593 + 0.82791521888981479 + 0.82795197689241495 + 0.82798873844086707 + 0.82802550353590565 + 0.82806227217826589 + 0.82809904436869064 + 0.82813582010791298 + 0.82817259939667387 + 0.82820938223570684 + 0.82824616862575506 + 0.82828295856755418 + 0.8283197520618456 + 0.82835654910936518 + 0.82839334971085254 + 0.82843015386705154 + 0.82846696157869804 + 0.8285037728465322 + 0.82854058767129635 + 0.82857740605372854 + 0.82861422799457318 + 0.82865105349456669 + 0.8286878825544558 + 0.82872471517497903 + 0.82876155135687912 + 0.82879839110089704 + 0.82883523440777573 + 0.82887208127826006 + 0.82890893171308955 + 0.82894578571300725 + 0.82898264327876037 + 0.82901950441108885 + 0.82905636911073977 + 0.82909323737845508 + 0.82913010921498032 + 0.82916698462105765 + 0.8292038635974367 + 0.82924074614485799 + 0.82927763226407125 + 0.82931452195581901 + 0.82935141522084965 + 0.82938831205990726 + 0.82942521247373902 + 0.82946211646309131 + 0.82949902402871289 + 0.8295359351713486 + 0.8295728498917494 + 0.82960976819065857 + 0.82964669006882918 + 0.82968361552700653 + 0.82972054456593791 + 0.82975747718637494 + 0.82979441338906512 + 0.82983135317476042 + 0.82986829654420602 + 0.82990524349815453 + 0.82994219403735547 + 0.82997914816256124 + 0.83001610587451968 + 0.83005306717398353 + 0.83009003206170273 + 0.83012700053842814 + 0.83016397260491426 + 0.83020094826190993 + 0.83023792751016967 + 0.83027491035044476 + 0.83031189678348793 + 0.83034888681005226 + 0.83038588043089134 + 0.83042287764675804 + 0.83045987845840818 + 0.83049688286659307 + 0.83053389087206853 + 0.83057090247559007 + 0.83060791767790965 + 0.83064493647978321 + 0.83068195888196883 + 0.83071898488521856 + 0.83075601449029279 + 0.8307930476979396 + 0.83083008450892581 + 0.83086712492399983 + 0.83090416894392216 + 0.83094121656944997 + 0.83097826780133965 + 0.8310153226403485 + 0.83105238108723545 + 0.8310894431427599 + 0.8311265088076788 + 0.83116357808275165 + 0.83120065096873608 + 0.83123772746639368 + 0.83127480757648187 + 0.8313118912997608 + 0.83134897863699209 + 0.83138606958893602 + 0.83142316415635054 + 0.83146026233999792 + 0.83149736414064235 + 0.83153446955904053 + 0.83157157859595676 + 0.83160869125215164 + 0.83164580752838824 + 0.83168292742542893 + 0.831720050944037 + 0.8317571780849754 + 0.83179430884900729 + 0.83183144323689395 + 0.83186858124940266 + 0.83190572288729503 + 0.83194286815133833 + 0.83198001704229074 + 0.83201716956092564 + 0.83205432570800308 + 0.83209148548428891 + 0.83212864889054938 + 0.83216581592755068 + 0.83220298659605896 + 0.83224016089683894 + 0.8322773388306608 + 0.83231452039828735 + 0.83235170560048932 + 0.83238889443803332 + 0.83242608691168862 + 0.83246328302221806 + 0.8325004827703969 + 0.8325376861569882 + 0.83257489318276356 + 0.83261210384849227 + 0.83264931815494192 + 0.83268653610288423 + 0.83272375769308904 + 0.83276098292632428 + 0.83279821180336366 + 0.83283544432497358 + 0.83287268049193197 + 0.83290992030500333 + 0.83294716376496025 + 0.8329844108725788 + 0.83302166162862989 + 0.83305891603388227 + 0.83309617408911074 + 0.83313343579509025 + 0.83317070115258962 + 0.83320797016238635 + 0.8332452428252537 + 0.83328251914196283 + 0.83331979911329124 + 0.83335708274001064 + 0.83339437002289862 + 0.83343166096272914 + 0.83346895556027789 + 0.83350625381631893 + 0.83354355573162853 + 0.83358086130698472 + 0.83361817054316401 + 0.83365548344094076 + 0.83369280000109347 + 0.83373012022439885 + 0.83376744411163572 + 0.8338047716635808 + 0.83384210288101301 + 0.83387943776470963 + 0.83391677631544803 + 0.83395411853401291 + 0.83399146442117611 + 0.83402881397772122 + 0.8340661672044275 + 0.834103524102075 + 0.83414088467144343 + 0.8341782489133126 + 0.8342156168284669 + 0.83425298841768203 + 0.83429036368174658 + 0.83432774262143483 + 0.83436512523753137 + 0.83440251153081868 + 0.83443990150208136 + 0.83447729515209834 + 0.83451469248165655 + 0.83455209349153703 + 0.8345894981825227 + 0.83462690655539729 + 0.83466431861094947 + 0.83470173434995709 + 0.83473915377320984 + 0.83477657688149109 + 0.83481400367558289 + 0.83485143415627683 + 0.83488886832435516 + 0.83492630618060382 + 0.83496374772581106 + 0.83500119296076136 + 0.83503864188624299 + 0.83507609450304054 + 0.83511355081194671 + 0.83515101081374421 + 0.83518847450922373 + 0.83522594189917265 + 0.83526341298437967 + 0.83530088776563438 + 0.83533836624372371 + 0.83537584841944124 + 0.83541333429357245 + 0.83545082386690905 + 0.83548831714024085 + 0.83552581411436144 + 0.83556331479005697 + 0.83560081916811957 + 0.83563832724934317 + 0.83567583903451637 + 0.8357133545244334 + 0.83575087371988488 + 0.83578839662166526 + 0.83582592323056748 + 0.83586345354738023 + 0.83590098757290043 + 0.83593852530792334 + 0.83597606675323799 + 0.83601361190964174 + 0.83605116077793185 + 0.83608871335889601 + 0.8361262696533337 + 0.83616382966204073 + 0.83620139338580879 + 0.83623896082543803 + 0.83627653198172436 + 0.83631410685546204 + 0.8363516854474472 + 0.83638926775848044 + 0.83642685378935611 + 0.83646444354087091 + 0.83650203701382542 + 0.83653963420901667 + 0.83657723512724358 + 0.83661483976930495 + 0.83665244813599637 + 0.83669006022812276 + 0.83672767604647957 + 0.83676529559186652 + 0.83680291886508906 + 0.83684054586694079 + 0.83687817659822383 + 0.83691581105974189 + 0.8369534492522952 + 0.8369910911766858 + 0.83702873683371404 + 0.83706638622418039 + 0.83710403934889133 + 0.8371416962086472 + 0.83717935680425315 + 0.83721702113650953 + 0.83725468920622181 + 0.83729236101419291 + 0.83733003656122584 + 0.83736771584812808 + 0.83740539887570087 + 0.83744308564475178 + 0.83748077615608651 + 0.83751847041050687 + 0.83755616840882241 + 0.83759387015183728 + 0.83763157564035962 + 0.83766928487519365 + 0.83770699785714753 + 0.83774471458702993 + 0.83778243506564698 + 0.83782015929380549 + 0.83785788727231636 + 0.83789561900198639 + 0.8379333544836246 + 0.83797109371803791 + 0.83800883670603776 + 0.8380465834484353 + 0.8380843339460361 + 0.83812208819965361 + 0.83815984621009754 + 0.83819760797817955 + 0.83823537350470767 + 0.83827314279049592 + 0.83831091583635642 + 0.83834869264309719 + 0.83838647321153481 + 0.83842425754247962 + 0.83846204563674442 + 0.83849983749514156 + 0.83853763311848595 + 0.83857543250759059 + 0.83861323566327051 + 0.83865104258633894 + 0.83868885327760878 + 0.83872666773789584 + 0.83876448596801723 + 0.83880230796878474 + 0.83884013374101818 + 0.83887796328552922 + 0.83891579660313786 + 0.83895363369466025 + 0.83899147456091028 + 0.83902931920270662 + 0.83906716762086742 + 0.83910501981621122 + 0.83914287578955282 + 0.8391807355417148 + 0.83921859907350993 + 0.83925646638576346 + 0.83929433747929227 + 0.83933221235491184 + 0.83937009101344717 + 0.83940797345571794 + 0.83944585968254148 + 0.83948374969473971 + 0.8395216434931343 + 0.83955954107854724 + 0.83959744245179635 + 0.83963534761370984 + 0.83967325656510394 + 0.83971116930680334 + 0.83974908583963004 + 0.83978700616440882 + 0.83982493028196059 + 0.83986285819311179 + 0.83990078989868378 + 0.83993872539950132 + 0.83997666469639176 + 0.84001460779017445 + 0.8400525546816785 + 0.84009050537172969 + 0.84012845986114959 + 0.84016641815077009 + 0.84020438024141075 + 0.84024234613390392 + 0.84028031582907348 + 0.84031828932774766 + 0.84035626663075302 + 0.8403942477389198 + 0.84043223265307265 + 0.84047022137404015 + 0.84050821390265329 + 0.84054621023974108 + 0.84058421038613018 + 0.84062221434265416 + 0.84066022211013824 + 0.84069823368941354 + 0.84073624908131372 + 0.84077426828666857 + 0.84081229130630564 + 0.84085031814106093 + 0.84088834879176233 + 0.84092638325924396 + 0.84096442154433604 + 0.8410024636478749 + 0.84104050957068921 + 0.84107855931361519 + 0.84111661287748385 + 0.84115467026313162 + 0.84119273147138984 + 0.8412307965030954 + 0.84126886535908141 + 0.84130693804018319 + 0.84134501454723609 + 0.84138309488107577 + 0.84142117904253577 + 0.84145926703245577 + 0.84149735885167187 + 0.84153545450101785 + 0.84157355398133393 + 0.84161165729345433 + 0.84164976443822137 + 0.84168787541646961 + 0.8417259902290396 + 0.84176410887676589 + 0.84180223136049148 + 0.84184035768105314 + 0.84187848783929231 + 0.84191662183604787 + 0.84195475967215716 + 0.84199290134846561 + 0.84203104686581087 + 0.84206919622503451 + 0.84210734942698007 + 0.84214550647248398 + 0.84218366736239392 + 0.84222183209754797 + 0.8422600006787927 + 0.8422981731069662 + 0.84233634938291524 + 0.84237452950748204 + 0.8424127134815097 + 0.84245090130584299 + 0.84248909298132679 + 0.84252728850880432 + 0.84256548788912289 + 0.8426036911231255 + 0.84264189821165991 + 0.84268010915557157 + 0.84271832395570423 + 0.84275654261290778 + 0.84279476512802609 + 0.84283299150190927 + 0.84287122173540141 + 0.84290945582935273 + 0.84294769378461198 + 0.8429859356020255 + 0.84302418128244205 + 0.84306243082671228 + 0.84310068423568318 + 0.84313894151020796 + 0.84317720265113349 + 0.84321546765931121 + 0.84325373653559033 + 0.84329200928082471 + 0.84333028589586168 + 0.84336856638155511 + 0.84340685073875687 + 0.84344513896831719 + 0.8434834310710918 + 0.84352172704792916 + 0.84356002689968568 + 0.84359833062721379 + 0.84363663823136603 + 0.84367494971299728 + 0.84371326507296229 + 0.84375158431211628 + 0.84378990743130999 + 0.84382823443140487 + 0.8438665653132521 + 0.84390490007770746 + 0.84394323872562826 + 0.84398158125787237 + 0.84401992767529543 + 0.84405827797875366 + 0.84409663216910502 + 0.84413499024720773 + 0.8441733522139182 + 0.84421171807009665 + 0.84425008781660182 + 0.84428846145429048 + 0.84432683898402527 + 0.84436522040666129 + 0.84440360572306161 + 0.84444199493408734 + 0.84448038804059766 + 0.84451878504345235 + 0.84455718594351281 + 0.84459559074164248 + 0.84463399943870165 + 0.84467241203555188 + 0.84471082853305746 + 0.84474924893208037 + 0.84478767323348292 + 0.84482610143812753 + 0.84486453354688096 + 0.84490296956060584 + 0.84494140948016694 + 0.84497985330642511 + 0.84501830104025144 + 0.84505675268250713 + 0.84509520823405948 + 0.84513366769577369 + 0.84517213106851385 + 0.84521059835315293 + 0.84524906955054924 + 0.84528754466157674 + 0.84532602368710108 + 0.84536450662798868 + 0.84540299348510761 + 0.84544148425932852 + 0.84547997895151816 + 0.84551847756254883 + 0.84555698009328339 + 0.84559548654459893 + 0.84563399691736019 + 0.84567251121244058 + 0.84571102943070953 + 0.84574955157304021 + 0.84578807764030006 + 0.84582660763336337 + 0.84586514155310111 + 0.8459036794003878 + 0.8459422211760913 + 0.8459807668810897 + 0.84601931651625362 + 0.84605787008245692 + 0.8460964275805728 + 0.84613498901147743 + 0.84617355437604402 + 0.84621212367514731 + 0.84625069690966404 + 0.84628927408046828 + 0.84632785518843623 + 0.84636644023444219 + 0.84640502921936744 + 0.84644362214408375 + 0.8464822190094704 + 0.84652081981640426 + 0.84655942456576483 + 0.8465980332584282 + 0.84663664589527321 + 0.84667526247717984 + 0.84671388300502692 + 0.84675250747969122 + 0.84679113590205513 + 0.84682976827299805 + 0.84686840459340096 + 0.84690704486414325 + 0.8469456890861059 + 0.84698433726017053 + 0.84702298938722109 + 0.84706164546813656 + 0.84710030550380178 + 0.8471389694950956 + 0.8471776374429052 + 0.8472163093481121 + 0.84725498521159892 + 0.84729366503425019 + 0.84733234881695052 + 0.84737103656058677 + 0.84740972826603966 + 0.84744842393419595 + 0.84748712356594547 + 0.84752582716216684 + 0.84756453472375171 + 0.84760324625158368 + 0.84764196174655027 + 0.84768068120954121 + 0.84771940464144069 + 0.84775813204313866 + 0.84779686341552285 + 0.84783559875948022 + 0.84787433807590262 + 0.84791308136567722 + 0.84795182862969398 + 0.8479905798688423 + 0.84802933508401501 + 0.84806809427609875 + 0.84810685744598524 + 0.84814562459456766 + 0.84818439572273541 + 0.84822317083138421 + 0.84826194992140147 + 0.84830073299368158 + 0.84833952004911584 + 0.84837831108860118 + 0.84841710611302901 + 0.84845590512329228 + 0.84849470812028505 + 0.84853351510490427 + 0.84857232607804278 + 0.84861114104059521 + 0.84864995999346071 + 0.84868878293753036 + 0.84872760987370166 + 0.84876644080287367 + 0.84880527572594022 + 0.84884411464379905 + 0.84888295755734966 + 0.84892180446748811 + 0.84896065537511245 + 0.84899951028112108 + 0.84903836918641407 + 0.84907723209189023 + 0.84911609899844953 + 0.84915496990698924 + 0.84919384481841231 + 0.84923272373361935 + 0.84927160665350732 + 0.84931049357898214 + 0.84934938451094255 + 0.84938827945029249 + 0.84942717839793136 + 0.8494660813547632 + 0.84950498832169163 + 0.84954389929961871 + 0.84958281428944871 + 0.84962173329208612 + 0.84966065630843335 + 0.84969958333939444 + 0.84973851438587855 + 0.84977744944878475 + 0.8498163885290233 + 0.84985533162749793 + 0.84989427874511569 + 0.84993322988278375 + 0.84997218504140792 + 0.8500111442218955 + 0.85005010742515641 + 0.85008907465209471 + 0.85012804590362046 + 0.85016702118064325 + 0.85020600048406991 + 0.85024498381481117 + 0.85028397117377663 + 0.85032296256187589 + 0.85036195798001923 + 0.8504009574291197 + 0.85043996091008467 + 0.85047896842382531 + 0.85051797997125678 + 0.85055699555328845 + 0.8505960151708345 + 0.85063503882480407 + 0.85067406651611555 + 0.85071309824567698 + 0.85075213401440608 + 0.85079117382321578 + 0.8508302176730197 + 0.85086926556473308 + 0.85090831749926865 + 0.85094737347754668 + 0.85098643350048064 + 0.8510254975689856 + 0.85106456568397859 + 0.85110363784637511 + 0.85114271405709652 + 0.85118179431705676 + 0.85122087862717355 + 0.85125996698836848 + 0.85129905940155604 + 0.85133815586765627 + 0.85137725638758954 + 0.85141636096227591 + 0.85145546959263263 + 0.85149458227958408 + 0.85153369902404485 + 0.85157281982694066 + 0.85161194468919188 + 0.85165107361172032 + 0.85169020659544747 + 0.85172934364129438 + 0.85176848475018474 + 0.85180762992304304 + 0.85184677916079066 + 0.85188593246435174 + 0.85192508983465254 + 0.85196425127261577 + 0.85200341677916358 + 0.85204258635522445 + 0.85208176000172375 + 0.85212093771958775 + 0.8521601195097398 + 0.85219930537310917 + 0.8522384953106209 + 0.85227768932320291 + 0.85231688741178235 + 0.85235608957728892 + 0.85239529582064877 + 0.85243450614278993 + 0.85247372054464254 + 0.85251293902713865 + 0.85255216159120462 + 0.85259138823777147 + 0.85263061896776748 + 0.85266985378212568 + 0.85270909268177697 + 0.85274833566765429 + 0.85278758274068522 + 0.85282683390180491 + 0.85286608915194495 + 0.85290534849203925 + 0.85294461192301918 + 0.85298387944581866 + 0.85302315106137216 + 0.85306242677061572 + 0.85310170657448148 + 0.85314099047390435 + 0.85318027846982059 + 0.85321957056316522 + 0.85325886675487483 + 0.8532981670458849 + 0.85333747143713423 + 0.8533767799295563 + 0.85341609252409267 + 0.85345540922167862 + 0.85349473002325227 + 0.85353405492975332 + 0.85357338394211968 + 0.85361271706128972 + 0.85365205428820556 + 0.85369139562380592 + 0.85373074106902891 + 0.85377009062481979 + 0.85380944429211314 + 0.85384880207185765 + 0.85388816396498923 + 0.85392752997245247 + 0.85396690009518905 + 0.85400627433414422 + 0.85404565269025612 + 0.85408503516447276 + 0.85412442175773529 + 0.8541638124709886 + 0.85420320730517862 + 0.8542426062612497 + 0.85428200934014431 + 0.85432141654281146 + 0.85436082787019596 + 0.85440024332324427 + 0.85443966290290418 + 0.85447908661012029 + 0.8545185144458427 + 0.85455794641101823 + 0.85459738250659301 + 0.8546368227335186 + 0.85467626709274291 + 0.85471571558521631 + 0.8547551682118828 + 0.85479462497370096 + 0.85483408587161303 + 0.85487355090657402 + 0.85491302007953662 + 0.85495249339144941 + 0.85499197084326384 + 0.85503145243593115 + 0.85507093817040847 + 0.85511042804764359 + 0.85514992206859386 + 0.85518942023420941 + 0.85522892254544625 + 0.85526842900325784 + 0.85530793960860085 + 0.85534745436242599 + 0.8553869732656928 + 0.85542649631935697 + 0.85546602352437062 + 0.85550555488169489 + 0.8555450903922831 + 0.85558463005709384 + 0.85562417387708523 + 0.85566372185321637 + 0.85570327398644319 + 0.85574283027772502 + 0.85578239072802209 + 0.85582195533829253 + 0.85586152410949445 + 0.85590109704259243 + 0.85594067413854469 + 0.85598025539831224 + 0.85601984082285554 + 0.8560594304131377 + 0.85609902417011774 + 0.85613862209476299 + 0.85617822418803302 + 0.85621783045088895 + 0.85625744088429878 + 0.85629705548922408 + 0.85633667426662896 + 0.85637629721747743 + 0.85641592434273772 + 0.85645555564337028 + 0.85649519112034389 + 0.85653483077462489 + 0.85657447460717628 + 0.85661412261896919 + 0.85665377481096827 + 0.85669343118414309 + 0.85673309173945922 + 0.85677275647788598 + 0.85681242540039082 + 0.85685209850794619 + 0.85689177580151776 + 0.85693145728207576 + 0.85697114295059429 + 0.85701083280803791 + 0.85705052685538119 + 0.85709022509359678 + 0.8571299275236538 + 0.85716963414652292 + 0.85720934496317769 + 0.85724905997459522 + 0.85728877918174284 + 0.85732850258559423 + 0.85736823018712904 + 0.8574079619873155 + 0.8574476979871295 + 0.85748743818754725 + 0.85752718258954475 + 0.85756693119409688 + 0.85760668400218021 + 0.85764644101476928 + 0.85768620223284142 + 0.8577259676573773 + 0.85776573728935024 + 0.85780551112974202 + 0.8578452891795274 + 0.85788507143968873 + 0.85792485791120332 + 0.85796464859504973 + 0.85800444349220761 + 0.85804424260366108 + 0.85808404593038479 + 0.85812385347336528 + 0.85816366523358334 + 0.85820348121201562 + 0.85824330140965144 + 0.85828312582746757 + 0.85832295446644924 + 0.85836278732758042 + 0.85840262441184434 + 0.85844246572022453 + 0.85848231125370322 + 0.85852216101327061 + 0.85856201499990858 + 0.85860187321460124 + 0.85864173565833768 + 0.858681602332104 + 0.85872147323688308 + 0.85876134837366613 + 0.85880122774344014 + 0.8588411113471921 + 0.85888099918590977 + 0.85892089126058246 + 0.85896078757219962 + 0.85900068812174968 + 0.85904059291022206 + 0.85908050193860908 + 0.85912041520789906 + 0.85916033271908465 + 0.85920025447315584 + 0.85924018047110384 + 0.85928011071392152 + 0.85932004520260374 + 0.85935998393813984 + 0.85939992692152511 + 0.859439874153751 + 0.85947982563581304 + 0.8595197813687051 + 0.85955974135342306 + 0.85959970559096333 + 0.8596396740823179 + 0.85967964682848308 + 0.85971962383045974 + 0.8597596050892381 + 0.85979959060581912 + 0.85983958038120045 + 0.85987957441637819 + 0.85991957271235253 + 0.85995957527012057 + 0.85999958209068184 + 0.86003959317503631 + 0.86007960852418375 + 0.86011962813912424 + 0.86015965202085576 + 0.86019968017038306 + 0.8602397125887048 + 0.86027974927682493 + 0.86031979023574501 + 0.86035983546646777 + 0.8603998849699942 + 0.8604399387473276 + 0.86047999679947573 + 0.86052005912743978 + 0.86056012573222163 + 0.86060019661483333 + 0.86064027177627289 + 0.86068035121754827 + 0.86072043493966799 + 0.86076052294363448 + 0.8608006152304587 + 0.86084071180114496 + 0.8608808126567028 + 0.86092091779813906 + 0.86096102722646095 + 0.8610011409426801 + 0.86104125894780403 + 0.86108138124284228 + 0.86112150782880503 + 0.86116163870670204 + 0.86120177387754782 + 0.86124191334234657 + 0.86128205710211481 + 0.86132220515786517 + 0.86136235751060664 + 0.86140251416135405 + 0.86144267511112071 + 0.8614828403609196 + 0.86152300991176456 + 0.86156318376466889 + 0.86160336192065023 + 0.8616435443807211 + 0.8616837311458968 + 0.86172392221719407 + 0.8617641175956311 + 0.86180431728222029 + 0.86184452127798483 + 0.86188472958393691 + 0.86192494220109406 + 0.86196515913048133 + 0.86200538037310981 + 0.8620456059300009 + 0.86208583580217679 + 0.86212606999065455 + 0.86216630849645681 + 0.86220655132060098 + 0.86224679846411201 + 0.86228704992800764 + 0.86232730571331284 + 0.86236756582104834 + 0.86240783025223677 + 0.86244809900790131 + 0.86248837208906526 + 0.86252864949675401 + 0.86256893123199085 + 0.86260921729579965 + 0.86264950768920778 + 0.86268980241323789 + 0.86273010146891771 + 0.86277040485727363 + 0.86281071257933195 + 0.86285102463611951 + 0.86289134102866516 + 0.86293166175799352 + 0.86297198682513598 + 0.8630123162311214 + 0.86305264997697761 + 0.86309298806373391 + 0.86313333049242236 + 0.86317367726407024 + 0.86321402837971228 + 0.86325438384037378 + 0.86329474364709213 + 0.86333510780089728 + 0.86337547630281986 + 0.86341584915389502 + 0.86345622635515551 + 0.8634966079076325 + 0.86353699381236537 + 0.86357738407038365 + 0.86361777868272294 + 0.86365817765041886 + 0.86369858097450947 + 0.86373898865602694 + 0.86377940069600956 + 0.86381981709549582 + 0.86386023785552191 + 0.86390066297712309 + 0.8639410924613401 + 0.86398152630920988 + 0.86402196452177382 + 0.8640624071000691 + 0.86410285404513543 + 0.86414330535801276 + 0.8641837610397447 + 0.86422422109136721 + 0.86426468551392877 + 0.86430515430846333 + 0.86434562747601562 + 0.86438610501763036 + 0.86442658693435082 + 0.86446707322721916 + 0.86450756389727701 + 0.86454805894557174 + 0.86458855837314674 + 0.86462906218104774 + 0.86466957037032022 + 0.86471008294200857 + 0.86475059989716119 + 0.86479112123682556 + 0.86483164696204451 + 0.86487217707387121 + 0.86491271157334748 + 0.86495325046152682 + 0.8649937937394564 + 0.86503434140818336 + 0.8650748934687611 + 0.86511544992223743 + 0.86515601076966364 + 0.86519657601209021 + 0.86523714565056908 + 0.86527771968615041 + 0.86531829811988836 + 0.86535888095283398 + 0.86539946818604185 + 0.86544005982056293 + 0.86548065585745215 + 0.86552125629776488 + 0.86556186114255429 + 0.86560247039287819 + 0.8656430840497884 + 0.86568370211434242 + 0.86572432458759663 + 0.86576495147060717 + 0.86580558276443453 + 0.86584621847013088 + 0.86588685858875747 + 0.86592750312137279 + 0.86596815206903399 + 0.86600880543280245 + 0.86604946321373522 + 0.86609012541289798 + 0.86613079203134458 + 0.86617146307013881 + 0.86621213853034273 + 0.86625281841301638 + 0.86629350271922434 + 0.86633419145002699 + 0.86637488460648904 + 0.86641558218967341 + 0.86645628420064325 + 0.86649699064046348 + 0.86653770151019982 + 0.8665784168109173 + 0.86661913654368017 + 0.86665986070955592 + 0.86670058930960858 + 0.86674132234490875 + 0.86678205981652034 + 0.86682280172551218 + 0.86686354807295474 + 0.86690429885991305 + 0.86694505408745981 + 0.86698581375666051 + 0.86702657786858872 + 0.86706734642431171 + 0.86710811942490318 + 0.86714889687143093 + 0.867189678764969 + 0.86723046510658774 + 0.86727125589736154 + 0.86731205113836274 + 0.86735285083066438 + 0.86739365497533893 + 0.86743446357346143 + 0.86747527662610768 + 0.86751609413435027 + 0.86755691609926755 + 0.86759774252193256 + 0.86763857340342554 + 0.86767940874481841 + 0.86772024854719332 + 0.86776109281162284 + 0.86780194153918755 + 0.86784279473096615 + 0.86788365238803733 + 0.86792451451148056 + 0.86796538110237453 + 0.86800625216180116 + 0.86804712769083969 + 0.86808800769057204 + 0.868128892162078 + 0.86816978110644194 + 0.86821067452474388 + 0.86825157241807005 + 0.86829247478749949 + 0.86833338163411888 + 0.86837429295901081 + 0.86841520876326073 + 0.86845612904795577 + 0.8684970538141753 + 0.86853798306301122 + 0.868578916795545 + 0.86861985501286676 + 0.86866079771606275 + 0.86870174490621899 + 0.86874269658442849 + 0.86878365275177305 + 0.86882461340934425 + 0.86886557855823277 + 0.86890654819952984 + 0.86894752233432071 + 0.86898850096369873 + 0.86902948408875602 + 0.86907047171058194 + 0.86911146383027094 + 0.86915246044891292 + 0.86919346156760258 + 0.8692344671874338 + 0.86927547730949817 + 0.86931649193488991 + 0.86935751106470416 + 0.86939853470003847 + 0.8694395628419842 + 0.86948059549164047 + 0.86952163265010352 + 0.86956267431846679 + 0.86960372049783108 + 0.86964477118929384 + 0.86968582639395031 + 0.86972688611290239 + 0.8697679503472493 + 0.86980901909808594 + 0.86985009236651933 + 0.86989117015364292 + 0.86993225246056205 + 0.86997333928837661 + 0.87001443063818806 + 0.87005552651109652 + 0.87009662690821055 + 0.87013773183062804 + 0.87017884127945389 + 0.87021995525579032 + 0.8702610737607448 + 0.87030219679542209 + 0.87034332436092532 + 0.87038445645835993 + 0.87042559308883571 + 0.87046673425345433 + 0.87050787995332546 + 0.87054903018955754 + 0.87059018496325891 + 0.87063134427553546 + 0.87067250812749664 + 0.87071367652025233 + 0.87075484945491233 + 0.8707960269325874 + 0.8708372089543871 + 0.87087839552142265 + 0.87091958663480618 + 0.87096078229565088 + 0.87100198250506755 + 0.87104318726416974 + 0.87108439657406833 + 0.87112561043588199 + 0.87116682885072072 + 0.87120805181970218 + 0.87124927934394147 + 0.87129051142455138 + 0.87133174806264768 + 0.87137298925935192 + 0.87141423501577597 + 0.87145548533303985 + 0.87149674021226375 + 0.87153799965455991 + 0.87157926366105076 + 0.87162053223285751 + 0.87166180537109428 + 0.87170308307688893 + 0.87174436535135424 + 0.87178565219561766 + 0.87182694361079471 + 0.87186823959801352 + 0.87190954015839162 + 0.87195084529305544 + 0.87199215500312521 + 0.87203346928972747 + 0.87207478815398698 + 0.87211611159702607 + 0.8721574396199685 + 0.87219877222394482 + 0.87224010941007701 + 0.87228145117949429 + 0.87232279753332254 + 0.8723641484726874 + 0.8724055039987213 + 0.87244686411254857 + 0.87248822881529964 + 0.87252959810810493 + 0.87257097199209355 + 0.87261235046839403 + 0.87265373353814046 + 0.87269512120246129 + 0.87273651346248671 + 0.87277791031935203 + 0.87281931177418925 + 0.8728607178281329 + 0.87290212848231263 + 0.87294354373786331 + 0.87298496359592348 + 0.87302638805762189 + 0.87306781712409764 + 0.87310925079648793 + 0.87315068907592397 + 0.8731921319635475 + 0.87323357946049229 + 0.87327503156789799 + 0.87331648828690311 + 0.87335794961864344 + 0.87339941556426159 + 0.87344088612489645 + 0.87348236130168466 + 0.87352384109577141 + 0.87356532550829347 + 0.87360681454039502 + 0.87364830819321659 + 0.87368980646790051 + 0.87373130936559096 + 0.87377281688743147 + 0.8738143290345628 + 0.87385584580813114 + 0.87389736720928124 + 0.87393889323915785 + 0.87398042389890818 + 0.87402195918967518 + 0.8740634991126085 + 0.87410504366885378 + 0.87414659285955887 + 0.87418814668587108 + 0.87422970514893716 + 0.87427126824991153 + 0.87431283598994025 + 0.8743544083701722 + 0.87439598539175811 + 0.8744375670558493 + 0.87447915336359883 + 0.87452074431615612 + 0.87456233991467291 + 0.87460394016030507 + 0.87464554505420267 + 0.87468715459752133 + 0.87472876879141392 + 0.87477038763703474 + 0.87481201113554086 + 0.87485363928808679 + 0.87489527209582807 + 0.87493690955992165 + 0.87497855168152516 + 0.87502019846179402 + 0.87506184990188818 + 0.87510350600296616 + 0.87514516676618337 + 0.87518683219270488 + 0.8752285022836872 + 0.87527017704029098 + 0.87531185646367693 + 0.87535354055500703 + 0.87539522931544167 + 0.87543692274614493 + 0.87547862084827821 + 0.8755203236230058 + 0.87556203107148978 + 0.87560374319489609 + 0.87564545999438759 + 0.87568718147113078 + 0.87572890762629252 + 0.87577063846103587 + 0.87581237397653011 + 0.87585411417393833 + 0.87589585905443257 + 0.87593760861917858 + 0.87597936286934608 + 0.8760211218061037 + 0.87606288543062139 + 0.87610465374406565 + 0.8761464267476119 + 0.87618820444242829 + 0.87622998682968622 + 0.87627177391055933 + 0.87631356568621643 + 0.87635536215783394 + 0.87639716332658357 + 0.87643896919364095 + 0.87648077976017913 + 0.87652259502737184 + 0.87656441499639581 + 0.87660623966842655 + 0.87664806904464043 + 0.87668990312621475 + 0.87673174191432512 + 0.87677358541015138 + 0.87681543361486869 + 0.87685728652965944 + 0.87689914415570192 + 0.87694100649417406 + 0.87698287354625715 + 0.8770247453131309 + 0.87706662179597938 + 0.87710850299597876 + 0.87715038891431918 + 0.8771922795521756 + 0.87723417491073608 + 0.87727607499118243 + 0.8773179797946965 + 0.87735988932246911 + 0.87740180357567821 + 0.87744372255551495 + 0.87748564626316383 + 0.87752757469981002 + 0.87756950786664079 + 0.87761144576484384 + 0.87765338839561058 + 0.87769533576012482 + 0.8777372878595785 + 0.87777924469515833 + 0.87782120626805826 + 0.87786317257946722 + 0.8779051436305737 + 0.87794711942257264 + 0.87798909995665608 + 0.87803108523401674 + 0.87807307525584388 + 0.878115070023334 + 0.8781570695376808 + 0.87819907380007822 + 0.87824108281172331 + 0.87828309657380987 + 0.87832511508753286 + 0.87836713835408975 + 0.87840916637467892 + 0.87845119915049641 + 0.87849323668274137 + 0.87853527897261174 + 0.87857732602130512 + 0.87861937783002397 + 0.87866143439996658 + 0.87870349573233142 + 0.87874556182832531 + 0.87878763268914295 + 0.87882970831599183 + 0.87887178871007088 + 0.87891387387258568 + 0.87895596380474028 + 0.87899805850773394 + 0.87904015798277746 + 0.87908226223107078 + 0.8791243712538227 + 0.87916648505223738 + 0.87920860362752395 + 0.87925072698088569 + 0.87929285511353372 + 0.87933498802667354 + 0.87937712572151694 + 0.87941926819926985 + 0.87946141546114198 + 0.87950356750834613 + 0.87954572434209255 + 0.87958788596358761 + 0.87963005237404868 + 0.87967222357468677 + 0.87971439956671271 + 0.87975658035134052 + 0.87979876592978357 + 0.87984095630325776 + 0.87988315147297536 + 0.87992535144015249 + 0.87996755620600542 + 0.88000976577174927 + 0.88005198013860275 + 0.88009419930778077 + 0.8801364232805029 + 0.88017865205798818 + 0.88022088564145284 + 0.88026312403211826 + 0.8803053672312029 + 0.88034761523992666 + 0.88038986805951447 + 0.88043212569118068 + 0.88047438813615231 + 0.88051665539565227 + 0.88055892747090225 + 0.88060120436312128 + 0.88064348607354137 + 0.88068577260338043 + 0.88072806395386605 + 0.88077036012622523 + 0.88081266112168 + 0.88085496694146126 + 0.88089727758679415 + 0.88093959305890501 + 0.88098191335902387 + 0.88102423848837819 + 0.8810665684481952 + 0.88110890323970925 + 0.88115124286414626 + 0.88119358732274078 + 0.88123593661672106 + 0.88127829074731812 + 0.88132064971576696 + 0.88136301352330015 + 0.8814053821711475 + 0.88144775566054645 + 0.88149013399273102 + 0.88153251716893244 + 0.88157490519039194 + 0.88161729805833888 + 0.88165969577401437 + 0.88170209833865498 + 0.88174450575349794 + 0.88178691801978037 + 0.88182933513873718 + 0.88187175711161458 + 0.88191418393964838 + 0.88195661562407812 + 0.88199905216614638 + 0.88204149356709127 + 0.8820839398281578 + 0.88212639095058865 + 0.88216884693562081 + 0.8822113077845033 + 0.882253773498478 + 0.88229624407878848 + 0.8823387195266803 + 0.88238119984339991 + 0.88242368503019142 + 0.88246617508830116 + 0.88250867001897804 + 0.88255116982346693 + 0.88259367450301895 + 0.88263618405887934 + 0.88267869849229974 + 0.8827212178045275 + 0.88276374199681307 + 0.88280627107041054 + 0.88284880502656793 + 0.88289134386653589 + 0.88293388759157154 + 0.88297643620292132 + 0.88301898970184289 + 0.88306154808958948 + 0.88310411136741451 + 0.88314667953657411 + 0.88318925259832015 + 0.88323183055391485 + 0.88327441340460866 + 0.88331700115166223 + 0.88335959379633244 + 0.88340219133987863 + 0.88344479378355745 + 0.88348740112862689 + 0.88353001337634862 + 0.8835726305279844 + 0.88361525258479234 + 0.88365787954803698 + 0.88370051141897488 + 0.88374314819887445 + 0.88378578988899481 + 0.88382843649060117 + 0.88387108800495706 + 0.88391374443332593 + 0.88395640577697543 + 0.88399907203716788 + 0.88404174321517348 + 0.88408441931225457 + 0.88412710032968378 + 0.88416978626872422 + 0.88421247713064666 + 0.88425517291672051 + 0.88429787362821122 + 0.88434057926639476 + 0.88438328983253467 + 0.8844260053279116 + 0.88446872575378743 + 0.88451145111143881 + 0.88455418140213882 + 0.88459691662716011 + 0.88463965678777634 + 0.88468240188526237 + 0.88472515192089241 + 0.88476790689594365 + 0.88481066681168885 + 0.88485343166940578 + 0.88489620147037329 + 0.88493897621586981 + 0.88498175590716843 + 0.88502454054555202 + 0.88506733013229844 + 0.88511012466869088 + 0.88515292415600533 + 0.8851957285955232 + 0.8852385379885277 + 0.88528135233629834 + 0.88532417164012245 + 0.88536699590127854 + 0.88540982512105371 + 0.88545265930072936 + 0.88549549844159259 + 0.88553834254492569 + 0.88558119161201854 + 0.88562404564415287 + 0.88566690464262132 + 0.88570976860870854 + 0.88575263754370115 + 0.88579551144888835 + 0.88583839032556133 + 0.88588127417500939 + 0.88592416299852261 + 0.88596705679739041 + 0.88600995557290518 + 0.88605285932636102 + 0.88609576805904688 + 0.8861386817722593 + 0.88618160046728889 + 0.8862245241454314 + 0.88626745280798203 + 0.88631038645623439 + 0.88635332509148645 + 0.88639626871503419 + 0.88643921732817399 + 0.88648217093220438 + 0.88652512952842166 + 0.88656809311812745 + 0.88661106170261839 + 0.88665403528319409 + 0.88669701386115629 + 0.88673999743780652 + 0.88678298601444505 + 0.88682597959237419 + 0.88686897817289612 + 0.886911981757318 + 0.88695499034693637 + 0.8869980039430605 + 0.8870410225469938 + 0.88708404616004366 + 0.88712707478351427 + 0.88717010841871369 + 0.88721314706694576 + 0.88725619072952111 + 0.88729923940774635 + 0.88734229310293278 + 0.88738535181638722 + 0.8874284155494212 + 0.8874714843033441 + 0.88751455807947 + 0.8875576368791066 + 0.88760072070356866 + 0.88764380955416611 + 0.88768690343221579 + 0.88773000233903065 + 0.8877731062759262 + 0.88781621524421306 + 0.88785932924521382 + 0.88790244828023923 + 0.88794557235060811 + 0.88798870145763864 + 0.88803183560264465 + 0.88807497478695163 + 0.88811811901187199 + 0.8881612682787291 + 0.88820442258884258 + 0.88824758194353359 + 0.88829074634412208 + 0.88833391579193244 + 0.88837709028828471 + 0.88842026983450351 + 0.8884634544319111 + 0.88850664408183277 + 0.88854983878559402 + 0.88859303854451988 + 0.88863624335993607 + 0.88867945323316844 + 0.8887226681655449 + 0.8887658881583963 + 0.88880911321304468 + 0.88885234333082297 + 0.88889557851306022 + 0.88893881876108538 + 0.88898206407623026 + 0.88902531445982425 + 0.88906856991320338 + 0.88911183043769382 + 0.88915509603463361 + 0.88919836670535601 + 0.88924164245119108 + 0.88928492327347852 + 0.88932820917354904 + 0.88937150015274236 + 0.88941479621239217 + 0.88945809735383652 + 0.88950140357841345 + 0.88954471488746156 + 0.88958803128231745 + 0.8896313527643237 + 0.8896746793348177 + 0.8897180109951407 + 0.88976134774663629 + 0.88980468959063996 + 0.88984803652850009 + 0.8898913885615567 + 0.88993474569115638 + 0.88997810791863807 + 0.89002147524535002 + 0.89006484767263594 + 0.89010822520184318 + 0.89015160783431735 + 0.89019499557140602 + 0.89023838841445557 + 0.89028178636481647 + 0.89032518942383476 + 0.89036859759285936 + 0.89041201087324362 + 0.89045542926633681 + 0.89049885277348773 + 0.89054228139605063 + 0.89058571513537954 + 0.89062915399282228 + 0.89067259796973752 + 0.89071604706747542 + 0.89075950128739378 + 0.89080296063084474 + 0.89084642509918588 + 0.89088989469377522 + 0.89093336941596812 + 0.89097684926712295 + 0.89102033424859761 + 0.89106382436175069 + 0.89110731960794098 + 0.89115081998853174 + 0.89119432550487943 + 0.8912378361583484 + 0.89128135195029967 + 0.89132487288209539 + 0.89136839895509956 + 0.89141193017067455 + 0.89145546653018526 + 0.89149900803499627 + 0.8915425546864727 + 0.89158610648598202 + 0.89162966343489181 + 0.89167322553456552 + 0.89171679278637528 + 0.89176036519168533 + 0.89180394275186847 + 0.89184752546829327 + 0.8918911133423284 + 0.89193470637534755 + 0.89197830456871763 + 0.89202190792381697 + 0.89206551644201471 + 0.89210913012468585 + 0.89215274897320196 + 0.89219637298893828 + 0.89224000217327137 + 0.89228363652757425 + 0.89232727605322859 + 0.89237092075160585 + 0.89241457062408547 + 0.89245822567204613 + 0.89250188589686574 + 0.89254555129992674 + 0.89258922188260614 + 0.89263289764628273 + 0.89267657859234217 + 0.89272026472216559 + 0.89276395603713266 + 0.89280765253862937 + 0.89285135422803608 + 0.89289506110674155 + 0.89293877317612558 + 0.89298249043757794 + 0.89302621289248341 + 0.89306994054222943 + 0.89311367338820169 + 0.89315741143178762 + 0.89320115467437833 + 0.89324490311736338 + 0.89328865676212954 + 0.89333241561006993 + 0.89337617966257543 + 0.89341994892103549 + 0.89346372338684332 + 0.89350750306139315 + 0.89355128794607919 + 0.8935950780422911 + 0.89363887335142989 + 0.89368267387488609 + 0.89372647961405915 + 0.89377029057034174 + 0.89381410674513384 + 0.89385792813983511 + 0.89390175475583944 + 0.89394558659454904 + 0.89398942365736445 + 0.89403326594568266 + 0.89407711346090823 + 0.89412096620444093 + 0.89416482417768361 + 0.89420868738203818 + 0.89425255581890639 + 0.89429642948969923 + 0.89434030839581424 + 0.89438419253866042 + 0.89442808191964074 + 0.89447197654016675 + 0.8945158764016411 + 0.89455978150547411 + 0.8946036918530752 + 0.89464760744585103 + 0.89469152828521159 + 0.89473545437256985 + 0.89477938570933202 + 0.89482332229691419 + 0.89486726413672713 + 0.89491121014217379 + 0.89495515973388962 + 0.89499911291241607 + 0.89504306967817293 + 0.89508703003157408 + 0.89513099397303519 + 0.89517496150297493 + 0.89521893262180618 + 0.89526290732994784 + 0.8953068856278138 + 0.89535086751582427 + 0.89539485299439325 + 0.89543884206393687 + 0.89548283472487378 + 0.8955268309776202 + 0.89557083082259037 + 0.89561483426020483 + 0.89565884129087603 + 0.89570285191502463 + 0.89574686613306731 + 0.89579088394542017 + 0.89583490535249821 + 0.89587893035472443 + 0.89592295895250895 + 0.89596699114627532 + 0.89601102693643819 + 0.89605506632341425 + 0.8960991093076206 + 0.89614315588947824 + 0.89618720606940228 + 0.89623125984780971 + 0.89627531722511999 + 0.89631937820175023 + 0.89636344277811764 + 0.89640751095464122 + 0.89645158273173919 + 0.89649565810982812 + 0.89653973708932766 + 0.8965838196706557 + 0.89662790585423147 + 0.89667199564047062 + 0.89671608902979283 + 0.89676018602261554 + 0.89680428661936129 + 0.89684839082044521 + 0.8968924986262834 + 0.89693661003730163 + 0.89698072505391191 + 0.89702484367653612 + 0.8970689659055946 + 0.89711309174150333 + 0.89715722118468244 + 0.89720135423555203 + 0.89724549089453065 + 0.89728963116203408 + 0.89733377503848921 + 0.89737792252430826 + 0.89742207361991355 + 0.89746622832572343 + 0.89751038664215899 + 0.89755454856963823 + 0.89759871410858227 + 0.89764288325940944 + 0.89768705602254284 + 0.89773123239839681 + 0.89777541238739456 + 0.89781959598995686 + 0.89786378320650073 + 0.89790797403744693 + 0.89795216848321868 + 0.8979963665442352 + 0.89804056822091305 + 0.8980847735136761 + 0.89812898242294348 + 0.89817319494913594 + 0.8982174110926755 + 0.89826163085397892 + 0.89830585423347198 + 0.89835008123157223 + 0.89839431184869922 + 0.89843854608527629 + 0.89848278394172298 + 0.8985270254184613 + 0.89857127051591101 + 0.89861551923449567 + 0.89865977157463062 + 0.89870402753674494 + 0.89874828712125576 + 0.89879255032858307 + 0.89883681715915098 + 0.89888108761338192 + 0.89892536169169135 + 0.89896963939450791 + 0.89901392072224984 + 0.89905820567533923 + 0.89910249425419819 + 0.89914678645924784 + 0.89919108229090983 + 0.89923538174960893 + 0.89927968483576382 + 0.89932399154979881 + 0.89936830189213446 + 0.89941261586319388 + 0.89945693346339939 + 0.89950125469317388 + 0.89954557955293846 + 0.89958990804311734 + 0.89963424016413007 + 0.89967857591640121 + 0.89972291530035386 + 0.89976725831641158 + 0.89981160496499479 + 0.89985595524652684 + 0.89990030916143127 + 0.89994466671013318 + 0.89998902789305146 + 0.90003339271061222 + 0.90007776116323623 + 0.90012213325134949 + 0.9001665089753752 + 0.90021088833573304 + 0.90025527133285033 + 0.90029965796714928 + 0.90034404823905312 + 0.90038844214898583 + 0.90043283969737142 + 0.90047724088463343 + 0.90052164571119375 + 0.90056605417747848 + 0.90061046628391173 + 0.90065488203091781 + 0.90069930141892007 + 0.90074372444834117 + 0.90078815111960753 + 0.9008325814331406 + 0.90087701538936771 + 0.90092145298871285 + 0.90096589423159801 + 0.90101033911845008 + 0.90105478764969349 + 0.90109923982575257 + 0.90114369564705055 + 0.90118815511401562 + 0.90123261822706846 + 0.90127708498663794 + 0.90132155539314507 + 0.90136602944701849 + 0.90141050714868109 + 0.90145498849855998 + 0.90149947349707593 + 0.90154396214466048 + 0.90158845444173419 + 0.90163295038872671 + 0.90167744998605892 + 0.90172195323415838 + 0.90176646013345008 + 0.90181097068436145 + 0.90185548488731593 + 0.90190000274274107 + 0.90194452425106475 + 0.90198904941270774 + 0.90203357822810037 + 0.90207811069766364 + 0.90212264682182985 + 0.90216718660102069 + 0.90221173003566579 + 0.90225627712618683 + 0.90230082787301646 + 0.90234538227657568 + 0.90238994033729325 + 0.90243450205559683 + 0.90247906743191086 + 0.90252363646666112 + 0.90256820916028058 + 0.90261278551318647 + 0.90265736552581388 + 0.90270194919858693 + 0.90274653653193204 + 0.90279112752627544 + 0.902835722182046 + 0.9028803204996726 + 0.90292492247957912 + 0.90296952812219267 + 0.90301413742794379 + 0.90305875039725725 + 0.90310336703056437 + 0.90314798732828738 + 0.90319261129085748 + 0.90323723891870156 + 0.90328187021224704 + 0.90332650517192248 + 0.90337114379815497 + 0.90341578609137208 + 0.9034604320520051 + 0.90350508168047916 + 0.90354973497722102 + 0.90359439194266289 + 0.90363905257722976 + 0.90368371688135363 + 0.90372838485545948 + 0.90377305649997663 + 0.90381773181533354 + 0.90386241080196161 + 0.90390709346028619 + 0.90395177979073549 + 0.90399646979374115 + 0.90404116346973085 + 0.90408586081913545 + 0.90413056184237961 + 0.90417526653989622 + 0.90421997491211137 + 0.90426468695945694 + 0.90430940268236115 + 0.90435412208125443 + 0.90439884515656466 + 0.9044435719087226 + 0.9044883023381568 + 0.90453303644529481 + 0.90457777423057029 + 0.9046225156944111 + 0.90466726083724791 + 0.90471200965950949 + 0.90475676216162615 + 0.90480151834402744 + 0.90484627820714547 + 0.90489104175140733 + 0.90493580897724379 + 0.90498057988508807 + 0.90502535447536703 + 0.90507013274851178 + 0.90511491470495331 + 0.90515970034512272 + 0.90520448966945144 + 0.90524928267836668 + 0.90529407937230166 + 0.90533887975168781 + 0.90538368381695422 + 0.905428491568531 + 0.90547330300685125 + 0.90551811813234662 + 0.90556293694544454 + 0.90560775944657912 + 0.90565258563618145 + 0.90569741551468197 + 0.90574224908251422 + 0.90578708634010574 + 0.90583192728788886 + 0.90587677192629956 + 0.9059216202557635 + 0.90596647227671512 + 0.90601132798958883 + 0.90605618739480986 + 0.90610105049281719 + 0.90614591728403682 + 0.90619078776890549 + 0.9062356619478531 + 0.90628053982131007 + 0.90632542138971117 + 0.90637030665348861 + 0.90641519561307349 + 0.90646008826890023 + 0.90650498462139706 + 0.90654988467100139 + 0.90659478841814156 + 0.90663969586325455 + 0.90668460700676923 + 0.9067295218491207 + 0.90677444039074206 + 0.90681936263206386 + 0.90686428857352164 + 0.90690921821554649 + 0.9069541515585734 + 0.9069990886030338 + 0.90704402934936079 + 0.90708897379799014 + 0.90713392194935283 + 0.90717887380388251 + 0.90722382936201473 + 0.90726878862418103 + 0.90731375159081473 + 0.90735871826235215 + 0.90740368863922449 + 0.9074486627218652 + 0.90749364051071091 + 0.90753862200619517 + 0.90758360720874998 + 0.90762859611880897 + 0.90767358873680826 + 0.90771858506318215 + 0.90776358509836463 + 0.90780858884279003 + 0.90785359629689233 + 0.90789860746110629 + 0.90794362233586534 + 0.90798864092160703 + 0.90803366321876278 + 0.90807868922776946 + 0.90812371894905974 + 0.90816875238307226 + 0.90821378953023735 + 0.90825883039099375 + 0.90830387496577447 + 0.90834892325501648 + 0.90839397525915189 + 0.90843903097862011 + 0.90848409041385203 + 0.90852915356528685 + 0.908574220433357 + 0.90861929101850236 + 0.90866436532115369 + 0.90870944334174808 + 0.90875452508072307 + 0.90879961053851388 + 0.90884469971555359 + 0.9088897926122822 + 0.90893488922913479 + 0.90897998956654491 + 0.9090250936249501 + 0.90907020140478634 + 0.90911531290649272 + 0.90916042813050146 + 0.90920554707724999 + 0.90925066974717661 + 0.90929579614071687 + 0.90934092625830654 + 0.90938606010038392 + 0.90943119766738478 + 0.90947633895974567 + 0.90952148397790211 + 0.90956663272229288 + 0.90961178519335817 + 0.90965694139152764 + 0.90970210131724438 + 0.90974726497094438 + 0.90979243235306217 + 0.90983760346403642 + 0.90988277830430753 + 0.90992795687430805 + 0.90997313917447886 + 0.91001832520525872 + 0.91006351496708204 + 0.91010870846038561 + 0.91015390568561283 + 0.91019910664319437 + 0.91024431133357486 + 0.91028951975718786 + 0.91033473191447412 + 0.91037994780586906 + 0.91042516743181345 + 0.91047039079274283 + 0.91051561788909841 + 0.91056084872131737 + 0.9106060832898395 + 0.91065132159509776 + 0.91069656363753793 + 0.91074180941759575 + 0.91078705893570855 + 0.91083231219231775 + 0.91087756918785945 + 0.9109228299227754 + 0.91096809439750093 + 0.91101336261247867 + 0.91105863456814584 + 0.91110391026494275 + 0.91114918970330949 + 0.91119447288368216 + 0.9112397598065004 + 0.91128505047220676 + 0.91133034488123943 + 0.91137564303403651 + 0.91142094493104087 + 0.91146625057268826 + 0.91151155995942146 + 0.91155687309168087 + 0.91160218996990305 + 0.91164751059452842 + 0.91169283496600007 + 0.91173816308475619 + 0.91178349495123978 + 0.91182883056588349 + 0.9118741699291365 + 0.91191951304143348 + 0.91196485990321752 + 0.91201021051492948 + 0.91205556487700856 + 0.91210092298989376 + 0.91214628485402827 + 0.91219165046985329 + 0.91223701983780814 + 0.91228239295833424 + 0.9123277698318748 + 0.91237315045886547 + 0.91241853483975333 + 0.91246392297497647 + 0.91250931486497411 + 0.9125547105101921 + 0.91260010991106977 + 0.91264551306804931 + 0.91269091998157026 + 0.91273633065207449 + 0.91278174508000609 + 0.91282716326580471 + 0.91287258520991243 + 0.9129180109127718 + 0.91296344037482635 + 0.91300887359651461 + 0.91305431057827835 + 0.9130997513205622 + 0.91314519582380882 + 0.91319064408846007 + 0.91323609611495626 + 0.91328155190374005 + 0.91332701145525641 + 0.91337247476994299 + 0.91341794184824954 + 0.91346341269061426 + 0.9135088872974777 + 0.91355436566928883 + 0.91359984780648651 + 0.91364533370951173 + 0.91369082337881324 + 0.91373631681482814 + 0.91378181401800362 + 0.91382731498878289 + 0.91387281972760692 + 0.91391832823491881 + 0.91396384051116608 + 0.91400935655678794 + 0.91405487637222749 + 0.91410039995793313 + 0.9141459273143433 + 0.91419145844190375 + 0.91423699334106068 + 0.91428253201225285 + 0.9143280744559289 + 0.91437362067253181 + 0.91441917066250367 + 0.91446472442629056 + 0.91451028196433826 + 0.91455584327708439 + 0.91460140836498161 + 0.91464697722846966 + 0.9146925498679922 + 0.91473812628399609 + 0.9147837064769252 + 0.91482929044722638 + 0.91487487819533897 + 0.91492046972171404 + 0.91496606502679201 + 0.9150116641110192 + 0.91505726697484024 + 0.91510287361870191 + 0.9151484840430486 + 0.91519409824832265 + 0.91523971623497369 + 0.91528533800344603 + 0.91533096355418264 + 0.91537659288763251 + 0.91542222600423828 + 0.91546786290444526 + 0.91551350358870476 + 0.91555914805745564 + 0.91560479631114677 + 0.91565044835022191 + 0.91569610417513236 + 0.915741763786319 + 0.91578742718422967 + 0.9158330943693096 + 0.91587876534200618 + 0.91592444010276552 + 0.91597011865203448 + 0.91601580099025948 + 0.91606148711788549 + 0.91610717703536115 + 0.91615287074312934 + 0.91619856824164236 + 0.91624426953134264 + 0.91628997461267947 + 0.91633568348609917 + 0.91638139615204772 + 0.91642711261097343 + 0.91647283286332049 + 0.91651855690954109 + 0.91656428475007945 + 0.91661001638538209 + 0.9166557518158992 + 0.91670149104207543 + 0.91674723406435943 + 0.91679298088319949 + 0.91683873149904249 + 0.91688448591233696 + 0.91693024412352964 + 0.91697600613306951 + 0.91702177194140089 + 0.91706754154897729 + 0.91711331495624349 + 0.91715909216365044 + 0.9172048731716429 + 0.91725065798067063 + 0.91729644659117993 + 0.91734223900362499 + 0.91738803521844858 + 0.91743383523610211 + 0.91747963905703256 + 0.91752544668168778 + 0.9175712581105212 + 0.91761707334397669 + 0.91766289238250509 + 0.91770871522655684 + 0.91775454187657701 + 0.91780037233301948 + 0.91784620659633043 + 0.91789204466695729 + 0.91793788654535458 + 0.91798373223196961 + 0.91802958172724858 + 0.91807543503164568 + 0.91812129214560723 + 0.91816715306958496 + 0.91821301780402531 + 0.9182588863493828 + 0.91830475870610362 + 0.91835063487464019 + 0.91839651485544049 + 0.91844239864895594 + 0.91848828625563439 + 0.9185341776759286 + 0.91858007291028987 + 0.91862597195916607 + 0.91867187482300616 + 0.91871778150226302 + 0.91876369199738805 + 0.91880960630882924 + 0.91885552443704077 + 0.91890144638246851 + 0.91894737214556843 + 0.91899330172678906 + 0.91903923512658015 + 0.91908517234539477 + 0.91913111338368203 + 0.91917705824189555 + 0.91922300692048231 + 0.9192689594198985 + 0.91931491574059332 + 0.91936087588302051 + 0.91940683984762717 + 0.91945280763486781 + 0.91949877924519119 + 0.91954475467905417 + 0.91959073393690394 + 0.91963671701919447 + 0.91968270392637819 + 0.91972869465890461 + 0.91977468921722783 + 0.91982068760180036 + 0.91986668981307229 + 0.91991269585149538 + 0.91995870571752658 + 0.92000471941161366 + 0.92005073693421169 + 0.92009675828577253 + 0.92014278346674694 + 0.92018881247759143 + 0.92023484531875466 + 0.92028088199069336 + 0.92032692249385606 + 0.92037296682869751 + 0.92041901499567291 + 0.92046506699523511 + 0.92051112282783243 + 0.92055718249392504 + 0.92060324599395871 + 0.92064931332839328 + 0.92069538449767985 + 0.92074145950227149 + 0.92078753834262173 + 0.92083362101918353 + 0.92087970753241466 + 0.92092579788276396 + 0.92097189207068542 + 0.92101799009663654 + 0.92106409196106898 + 0.92111019766443825 + 0.92115630720719788 + 0.92120242058979995 + 0.92124853781270222 + 0.92129465887635642 + 0.92134078378121664 + 0.92138691252774074 + 0.92143304511638091 + 0.92147918154759079 + 0.921525321821827 + 0.92157146593954375 + 0.92161761390119523 + 0.92166376570723541 + 0.92170992135812302 + 0.92175608085430849 + 0.92180224419624979 + 0.92184841138440221 + 0.92189458241921984 + 0.92194075730115754 + 0.92198693603067172 + 0.92203311860821935 + 0.9220793050342514 + 0.92212549530922838 + 0.92217168943360117 + 0.92221788740783106 + 0.9222640892323688 + 0.92231029490767358 + 0.92235650443420081 + 0.92240271781240302 + 0.92244893504274206 + 0.9224951561256689 + 0.92254138106164296 + 0.92258760985111987 + 0.92263384249455471 + 0.92268007899240734 + 0.92272631934512894 + 0.92277256355317949 + 0.92281881161701429 + 0.92286506353709363 + 0.92291131931386883 + 0.92295757894779973 + 0.92300384243934264 + 0.92305010978895508 + 0.92309638099709346 + 0.92314265606421531 + 0.92318893499077737 + 0.92323521777723727 + 0.92328150442405366 + 0.92332779493168071 + 0.92337408930058062 + 0.9234203875312057 + 0.92346668962401657 + 0.92351299557946998 + 0.923559305398024 + 0.92360561908013528 + 0.9236519366262651 + 0.92369825803686767 + 0.92374458331240383 + 0.92379091245333023 + 0.92383724546010415 + 0.92388358233318435 + 0.9239299230730319 + 0.92397626768010177 + 0.92402261615485526 + 0.92406896849774722 + 0.92411532470923907 + 0.924161684789788 + 0.92420804873985363 + 0.92425441655989471 + 0.92430078825037132 + 0.92434716381173865 + 0.92439354324445833 + 0.9244399265489901 + 0.92448631372579326 + 0.92453270477532368 + 0.92457909969804564 + 0.92462549849441411 + 0.92467190116489162 + 0.92471830770993602 + 0.9247647181300046 + 0.92481113242556257 + 0.92485755059706509 + 0.92490397264497271 + 0.92495039856974981 + 0.92499682837184838 + 0.92504326205173493 + 0.92508969960986775 + 0.92513614104670527 + 0.92518258636270767 + 0.92522903555834024 + 0.92527548863405717 + 0.92532194559032099 + 0.92536840642759233 + 0.92541487114633247 + 0.92546133974700195 + 0.92550781223006162 + 0.92555428859597055 + 0.92560076884519138 + 0.92564725297818351 + 0.92569374099540791 + 0.92574023289732799 + 0.92578672868440481 + 0.92583322835709314 + 0.92587973191586304 + 0.92592623936117169 + 0.92597275069348028 + 0.92601926591325046 + 0.92606578502094394 + 0.92611230801702404 + 0.92615883490195061 + 0.92620536567618539 + 0.92625190034019211 + 0.92629843889442853 + 0.92634498133936061 + 0.92639152767544797 + 0.92643807790315535 + 0.92648463202294407 + 0.92653119003527462 + 0.92657775194060865 + 0.92662431773941345 + 0.92667088743214621 + 0.92671746101927399 + 0.92676403850125433 + 0.92681061987855451 + 0.92685720515163494 + 0.92690379432095782 + 0.92695038738698976 + 0.92699698435018985 + 0.92704358521102015 + 0.92709018996995018 + 0.92713679862743625 + 0.92718341118394321 + 0.92723002763993845 + 0.92727664799588072 + 0.92732327225223499 + 0.92736990040946687 + 0.92741653246803668 + 0.92746316842841026 + 0.92750980829105079 + 0.92755645205642157 + 0.92760309972498567 + 0.92764975129720917 + 0.92769640677355514 + 0.92774306615448698 + 0.92778972944047111 + 0.92783639663197048 + 0.92788306772944684 + 0.92792974273337037 + 0.92797642164419836 + 0.92802310446240133 + 0.92806979118844068 + 0.92811648182278284 + 0.92816317636589207 + 0.92820987481823169 + 0.92825657718026844 + 0.92830328345246649 + 0.92834999363529025 + 0.92839670772920779 + 0.92844342573467953 + 0.92849014765217619 + 0.92853687348215797 + 0.92858360322509381 + 0.92863033688144603 + 0.92867707445168324 + 0.92872381593626863 + 0.92877056133567049 + 0.92881731065035222 + 0.92886406388078024 + 0.92891082102741962 + 0.92895758209073964 + 0.92900434707120338 + 0.92905111596927736 + 0.92909788878542765 + 0.92914466552012054 + 0.92919144617382432 + 0.92923823074700396 + 0.92928501924012452 + 0.92933181165365386 + 0.9293786079880596 + 0.92942540824380704 + 0.9294722124213618 + 0.92951902052119373 + 0.92956583254376657 + 0.92961264848955039 + 0.9296594683590087 + 0.92970629215261336 + 0.92975311987082676 + 0.92979995151411654 + 0.92984678708295498 + 0.92989362657780428 + 0.92994046999913471 + 0.92998731734741213 + 0.9300341686231034 + 0.93008102382668079 + 0.93012788295860604 + 0.93017474601935279 + 0.93022161300938477 + 0.93026848392917061 + 0.93031535877917959 + 0.93036223755987757 + 0.93040912027173617 + 0.93045600691521924 + 0.93050289749080095 + 0.93054979199894527 + 0.93059669044012139 + 0.93064359281479869 + 0.93069049912344592 + 0.93073740936653016 + 0.93078432354452123 + 0.93083124165788789 + 0.93087816370710197 + 0.93092508969262611 + 0.93097201961493437 + 0.93101895347449448 + 0.9310658912717753 + 0.93111283300724679 + 0.93115977868137667 + 0.93120672829463669 + 0.93125368184749469 + 0.93130063934042051 + 0.93134760077388579 + 0.93139456614835703 + 0.93144153546430586 + 0.93148850872220024 + 0.93153548592251245 + 0.93158246706571091 + 0.93162945215226578 + 0.93167644118265158 + 0.93172343415733194 + 0.93177043107677793 + 0.93181743194146616 + 0.93186443675185837 + 0.93191144550843197 + 0.93195845821165524 + 0.93200547486199681 + 0.93205249545992974 + 0.93209952000592478 + 0.93214654850045264 + 0.9321935809439823 + 0.93224061733698693 + 0.93228765767993738 + 0.93233470197330504 + 0.93238175021755876 + 0.93242880241317205 + 0.93247585856061788 + 0.93252291866036385 + 0.93256998271288316 + 0.93261705071864731 + 0.93266412267812793 + 0.93271119859179874 + 0.93275827846012671 + 0.93280536228359034 + 0.93285245006265471 + 0.93289954179779622 + 0.93294663748948847 + 0.93299373713819667 + 0.93304084074439997 + 0.93308794830856778 + 0.93313505983117218 + 0.93318217531268544 + 0.93322929475358396 + 0.93327641815433515 + 0.93332354551541219 + 0.93337067683729147 + 0.93341781212044284 + 0.93346495136534113 + 0.93351209457245887 + 0.93355924174226657 + 0.93360639287524105 + 0.93365354797185296 + 0.9337007070325769 + 0.93374787005788618 + 0.93379503704825062 + 0.93384220800415074 + 0.93388938292605428 + 0.93393656181443652 + 0.93398374466977108 + 0.93403093149253269 + 0.93407812228319498 + 0.93412531704223078 + 0.93417251577011362 + 0.93421971846731888 + 0.93426692513432219 + 0.93431413577159506 + 0.9343613503796131 + 0.93440856895884961 + 0.93445579150977831 + 0.93450301803287539 + 0.93455024852861834 + 0.93459748299747514 + 0.93464472143992561 + 0.93469196385644182 + 0.93473921024749995 + 0.93478646061357584 + 0.93483371495514167 + 0.93488097327267583 + 0.93492823556665039 + 0.93497550183754174 + 0.93502277208582663 + 0.93507004631197899 + 0.93511732451647556 + 0.93516460669978874 + 0.93521189286239748 + 0.93525918300477606 + 0.93530647712739967 + 0.9353537752307467 + 0.9354010773152881 + 0.93544838338150471 + 0.93549569342987182 + 0.93554300746086438 + 0.93559032547495713 + 0.93563764747262723 + 0.93568497345435464 + 0.93573230342060953 + 0.93577963737187397 + 0.93582697530862313 + 0.93587431723133019 + 0.9359216631404752 + 0.93596901303653501 + 0.93601636691998602 + 0.93606372479130084 + 0.9361110866509641 + 0.93615845249944729 + 0.93620582233723038 + 0.93625319616478908 + 0.93630057398260147 + 0.93634795579114516 + 0.93639534159089466 + 0.93644273138233236 + 0.93649012516593155 + 0.93653752294217318 + 0.93658492471153354 + 0.93663233047448857 + 0.93667974023151901 + 0.93672715398310125 + 0.9367745717297139 + 0.93682199347183559 + 0.93686941920994482 + 0.9369168489445161 + 0.93696428267603282 + 0.93701172040497138 + 0.93705916213180851 + 0.9371066078570256 + 0.93715405758109727 + 0.93720151130450668 + 0.93724896902773103 + 0.93729643075124958 + 0.93734389647553973 + 0.93739136620107999 + 0.9374388399283502 + 0.93748631765783208 + 0.93753379939000281 + 0.93758128512534211 + 0.93762877486432705 + 0.93767626860743947 + 0.93772376635515964 + 0.93777126810796463 + 0.93781877386633439 + 0.9378662836307512 + 0.93791379740169256 + 0.93796131517963643 + 0.93800883696506965 + 0.93805636275846516 + 0.9381038925603058 + 0.93815142637107207 + 0.9381989641912436 + 0.93824650602130089 + 0.93829405186172676 + 0.9383416017129973 + 0.93838915557559521 + 0.93843671345000101 + 0.93848427533669543 + 0.93853184123615896 + 0.93857941114887444 + 0.93862698507531861 + 0.93867456301597674 + 0.93872214497132733 + 0.93876973094185345 + 0.93881732092803427 + 0.93886491493035096 + 0.93891251294928635 + 0.93896011498532228 + 0.93900772103893704 + 0.93905533111061701 + 0.93910294520083903 + 0.93915056331008873 + 0.93919818543884559 + 0.93924581158759313 + 0.93929344175681129 + 0.93934107594698335 + 0.93938871415859326 + 0.93943635639211887 + 0.93948400264804832 + 0.93953165292685692 + 0.93957930722903071 + 0.93962696555505454 + 0.93967462790540768 + 0.93972229428057286 + 0.93976996468103169 + 0.93981763910727101 + 0.93986531755977332 + 0.93991300003901601 + 0.93996068654548659 + 0.94000837707966933 + 0.94005607164204263 + 0.94010377023309311 + 0.94015147285330547 + 0.94019917950315868 + 0.94024689018313945 + 0.94029460489373085 + 0.94034232363541537 + 0.9403900464086784 + 0.94043777321400068 + 0.94048550405186959 + 0.94053323892276608 + 0.94058097782717776 + 0.94062872076558546 + 0.94067646773847258 + 0.94072421874632706 + 0.94077197378962985 + 0.94081973286886889 + 0.94086749598452291 + 0.94091526313708063 + 0.94096303432702688 + 0.94101080955484417 + 0.94105858882101989 + 0.94110637212603598 + 0.9411541594703785 + 0.94120195085453318 + 0.94124974627898461 + 0.9412975457442162 + 0.94134534925071689 + 0.94139315679896607 + 0.94144096838945479 + 0.94148878402266722 + 0.94153660369908765 + 0.94158442741920034 + 0.94163225518349225 + 0.94168008699245187 + 0.94172792284656193 + 0.9417757627463067 + 0.94182360669217524 + 0.94187145468465028 + 0.94191930672422319 + 0.94196716281137671 + 0.94201502294659745 + 0.94206288713037067 + 0.94211075536318367 + 0.94215862764552372 + 0.94220650397787575 + 0.94225438436072939 + 0.9423022687945678 + 0.94235015727987836 + 0.9423980498171507 + 0.94244594640686818 + 0.94249384704951877 + 0.94254175174559174 + 0.94258966049557136 + 0.94263757329994668 + 0.94268549015920411 + 0.94273341107383124 + 0.94278133604431635 + 0.94282926507114539 + 0.9428771981548062 + 0.94292513529578903 + 0.9429730764945784 + 0.94302102175166191 + 0.94306897106753029 + 0.94311692444267037 + 0.94316488187756975 + 0.9432128433727156 + 0.94326080892859809 + 0.94330877854570394 + 0.94335675222452176 + 0.94340472996554292 + 0.94345271176925116 + 0.94350069763613797 + 0.94354868756669263 + 0.94359668156140142 + 0.94364467962075327 + 0.94369268174523824 + 0.94374068793534438 + 0.94378869819156397 + 0.94383671251438139 + 0.94388473090429081 + 0.94393275336177696 + 0.94398077988733153 + 0.94402881048144194 + 0.94407684514460022 + 0.94412488387729554 + 0.94417292668001584 + 0.94422097355325052 + 0.94426902449749184 + 0.94431707951322963 + 0.9443651386009515 + 0.94441320176114774 + 0.94446126899431049 + 0.94450934030092981 + 0.94455741568149354 + 0.94460549513649239 + 0.94465357866642041 + 0.94470166627176433 + 0.94474975795301608 + 0.94479785371066416 + 0.9448459535452034 + 0.94489405745712052 + 0.94494216544690979 + 0.94499027751505793 + 0.94503839366206033 + 0.94508651388840748 + 0.94513463819458809 + 0.94518276658109524 + 0.94523089904841995 + 0.94527903559705329 + 0.94532717622748463 + 0.94537532094021104 + 0.94542346973571756 + 0.94547162261450002 + 0.94551977957705158 + 0.94556794062385718 + 0.94561610575541721 + 0.94566427497221872 + 0.94571244827475553 + 0.94576062566351926 + 0.94580880713899929 + 0.94585699270169421 + 0.94590518235209142 + 0.94595337609068486 + 0.94600157391796647 + 0.94604977583443051 + 0.94609798184056704 + 0.94614619193687 + 0.94619440612383632 + 0.94624262440195117 + 0.94629084677171393 + 0.94633907323361466 + 0.94638730378814773 + 0.94643553843580586 + 0.94648377717708154 + 0.94653202001246928 + 0.946580266942462 + 0.94662851796755254 + 0.94667677308823794 + 0.94672503230500848 + 0.94677329561835755 + 0.94682156302878229 + 0.9468698345367732 + 0.94691811014282634 + 0.94696638984743398 + 0.94701467365109204 + 0.94706296155429537 + 0.94711125355753589 + 0.94715954966130855 + 0.94720784986610917 + 0.94725615417243125 + 0.94730446258076839 + 0.94735277509161853 + 0.94740109170547282 + 0.94744941242282998 + 0.94749773724418096 + 0.94754606617002213 + 0.94759439920084954 + 0.94764273633715945 + 0.94769107757944349 + 0.94773942292819813 + 0.94778777238392142 + 0.94783612594710598 + 0.94788448361824773 + 0.9479328453978435 + 0.94798121128638757 + 0.94802958128437664 + 0.94807795539230511 + 0.948126333610672 + 0.94817471593997149 + 0.94822310238069907 + 0.94827149293335078 + 0.94831988759842456 + 0.94836828637641435 + 0.94841668926781764 + 0.9484650962731338 + 0.94851350739285323 + 0.94856192262747807 + 0.94861034197750294 + 0.94865876544342587 + 0.94870719302573925 + 0.94875562472494535 + 0.94880406054153732 + 0.94885250047601477 + 0.94890094452887586 + 0.94894939270061351 + 0.94899784499172801 + 0.94904630140271706 + 0.9490947619340766 + 0.94914322658630434 + 0.949191695359901 + 0.94924016825535973 + 0.94928864527318102 + 0.94933712641386137 + 0.9493856116779007 + 0.9494341010657934 + 0.94948259457804429 + 0.94953109221514287 + 0.94957959397759462 + 0.94962809986589114 + 0.94967660988053837 + 0.94972512402202991 + 0.94977364229086458 + 0.94982216468754166 + 0.94987069121256207 + 0.94991922186642008 + 0.94996775664961952 + 0.9500162955626551 + 0.95006483860602731 + 0.95011338578023863 + 0.95016193708578334 + 0.9502104925231607 + 0.95025905209287476 + 0.95030761579542034 + 0.95035618363129937 + 0.9504047556010089 + 0.95045333170505297 + 0.95050191194392719 + 0.95055049631813315 + 0.95059908482817324 + 0.95064767747454004 + 0.95069627425774061 + 0.95074487517827255 + 0.95079348023663612 + 0.95084208943333304 + 0.95089070276885979 + 0.95093932024372052 + 0.95098794185841329 + 0.95103656761344302 + 0.95108519750930343 + 0.95113383154650177 + 0.95118246972553588 + 0.95123111204690447 + 0.95127975851111479 + 0.95132840911866079 + 0.95137706387004772 + 0.95142572276577642 + 0.9514743858063478 + 0.95152305299226503 + 0.95157172432402426 + 0.95162039980213142 + 0.95166907942708745 + 0.9517177631993935 + 0.95176645111955305 + 0.95181514318806326 + 0.95186383940543151 + 0.95191253977215751 + 0.95196124428874285 + 0.95200995295568858 + 0.95205866577350073 + 0.95210738274267914 + 0.95215610386372529 + 0.95220482913714333 + 0.95225355856343497 + 0.95230229214310413 + 0.9523510298766511 + 0.95239977176457935 + 0.95244851780739381 + 0.95249726800559631 + 0.95254602235968922 + 0.95259478087017468 + 0.95264354353755976 + 0.95269231036234392 + 0.95274108134503022 + 0.95278985648612535 + 0.95283863578612948 + 0.95288741924554798 + 0.95293620686488545 + 0.95298499864464226 + 0.95303379458532556 + 0.95308259468743661 + 0.95313139895148447 + 0.95318020737796572 + 0.95322901996738973 + 0.95327783672025745 + 0.9533266576370768 + 0.95337548271834882 + 0.95342431196458099 + 0.95347314537627437 + 0.95352198295393453 + 0.95357082469806953 + 0.95361967060918096 + 0.95366852068777208 + 0.95371737493435071 + 0.95376623334942123 + 0.95381509593348934 + 0.95386396268705842 + 0.95391283361063539 + 0.95396170870472363 + 0.95401058796982952 + 0.95405947140645952 + 0.95410835901511737 + 0.95415725079631208 + 0.95420614675054349 + 0.9542550468783223 + 0.95430395118015288 + 0.95435285965653993 + 0.95440177230799217 + 0.95445068913501419 + 0.95449961013811102 + 0.95454853531779094 + 0.95459746467455742 + 0.95464639820892128 + 0.95469533592138545 + 0.95474427781245708 + 0.95479322388264076 + 0.95484217413245098 + 0.95489112856238578 + 0.95494008717295731 + 0.95498904996466816 + 0.95503801693803092 + 0.95508698809354797 + 0.95513596343172957 + 0.95518494295308143 + 0.9552339266581088 + 0.95528291454732372 + 0.95533190662123213 + 0.95538090288033961 + 0.95542990332515454 + 0.95547890795618662 + 0.95552791677394233 + 0.95557692977892927 + 0.95562594697165615 + 0.9556749683526311 + 0.95572399392236251 + 0.95577302368135653 + 0.95582205763012396 + 0.95587109576917106 + 0.95592013809900878 + 0.95596918462014335 + 0.95601823533308361 + 0.95606729023834081 + 0.95611634933642131 + 0.95616541262783383 + 0.95621448011309007 + 0.95626355179269673 + 0.95631262766716019 + 0.95636170773699491 + 0.9564107920027094 + 0.95645988046480857 + 0.956508973123809 + 0.95655806998021298 + 0.9566071710345343 + 0.95665627628727823 + 0.95670538573896124 + 0.95675449939008816 + 0.95680361724117335 + 0.95685273929272241 + 0.9569018655452447 + 0.95695099599925471 + 0.95700013065526024 + 0.95704926951377112 + 0.95709841257529804 + 0.95714755984035249 + 0.9571967113094455 + 0.95724586698308689 + 0.95729502686178691 + 0.95734419094605605 + 0.95739335923640512 + 0.95744253173334648 + 0.9574917084373884 + 0.95754088934904624 + 0.9575900744688286 + 0.95763926379724573 + 0.95768845733481101 + 0.95773765508203534 + 0.95778685703942956 + 0.95783606320750458 + 0.95788527358677622 + 0.95793448817775084 + 0.95798370698094248 + 0.95803292999686362 + 0.95808215722602652 + 0.95813138866894187 + 0.95818062432612139 + 0.95822986419808109 + 0.95827910828532825 + 0.95832835658837845 + 0.95837760910774361 + 0.95842686584393555 + 0.95847612679746863 + 0.95852539196885178 + 0.95857466135860192 + 0.95862393496723086 + 0.95867321279525042 + 0.9587224948431734 + 0.95877178111151573 + 0.95882107160078778 + 0.95887036631150158 + 0.95891966524417438 + 0.95896896839931822 + 0.95901827577744347 + 0.95906758737906961 + 0.95911690320470466 + 0.95916622325486789 + 0.95921554753006733 + 0.95926487603082056 + 0.95931420875764084 + 0.95936354571104454 + 0.95941288689153881 + 0.95946223229964545 + 0.95951158193587516 + 0.95956093580074342 + 0.95961029389476338 + 0.95965965621845062 + 0.95970902277232073 + 0.95975839355688719 + 0.95980776857266548 + 0.95985714782016951 + 0.95990653129991288 + 0.95995591901241561 + 0.96000531095818709 + 0.96005470713774799 + 0.96010410755160958 + 0.96015351220028811 + 0.96020292108430039 + 0.96025233420415956 + 0.96030175156038233 + 0.96035117315348739 + 0.960400598983987 + 0.96045002905239718 + 0.96049946335923464 + 0.96054890190501396 + 0.96059834469025396 + 0.96064779171547166 + 0.96069724298117665 + 0.96074669848789307 + 0.96079615823613307 + 0.9608456222264159 + 0.96089509045925459 + 0.96094456293516806 + 0.96099403965467145 + 0.96104352061828424 + 0.96109300582652168 + 0.96114249527990103 + 0.96119198897893954 + 0.9612414869241529 + 0.96129098911606092 + 0.96134049555517842 + 0.96139000624202597 + 0.96143952117711673 + 0.96148904036097282 + 0.96153856379410763 + 0.96158809147704372 + 0.96163762341029468 + 0.96168715959437889 + 0.96173670002981582 + 0.96178624471712237 + 0.96183579365681859 + 0.96188534684942295 + 0.96193490429544937 + 0.96198446599542076 + 0.96203403194985326 + 0.96208360215926569 + 0.96213317662417652 + 0.96218275534510667 + 0.96223233832257293 + 0.9622819255570938 + 0.96233151704918862 + 0.9623811127993781 + 0.96243071280817938 + 0.96248031707611115 + 0.96252992560369532 + 0.96257953839144816 + 0.96262915543989191 + 0.96267877674954339 + 0.96272840232092649 + 0.96277803215455626 + 0.96282766625095406 + 0.96287730461063969 + 0.96292694723413563 + 0.96297659412195635 + 0.96302624527462843 + 0.96307590069266524 + 0.96312556037659547 + 0.96317522432693048 + 0.96322489254419652 + 0.96327456502891418 + 0.96332424178160092 + 0.96337392280277712 + 0.96342360809296745 + 0.9634732976526903 + 0.96352299148246556 + 0.96357268958281683 + 0.96362239195426136 + 0.96367209859732483 + 0.96372180951252806 + 0.96377152470038885 + 0.96382124416143067 + 0.96387096789617444 + 0.96392069590514329 + 0.96397042818885781 + 0.96402016474783747 + 0.96406990558260908 + 0.96411965069369032 + 0.96416940008160434 + 0.96421915374687428 + 0.96426891169002182 + 0.96431867391156867 + 0.96436844041203573 + 0.96441821119194926 + 0.96446798625182895 + 0.96451776559219593 + 0.96456754921357668 + 0.96461733711649267 + 0.96466712930146403 + 0.96471692576901935 + 0.96476672651967332 + 0.96481653155395541 + 0.96486634087238965 + 0.96491615447549361 + 0.96496597236379422 + 0.96501579453781361 + 0.96506562099807658 + 0.96511545174510738 + 0.96516528677942692 + 0.96521512610155968 + 0.96526496971203024 + 0.96531481761136395 + 0.96536466980008095 + 0.96541452627870894 + 0.96546438704777027 + 0.96551425210778841 + 0.96556412145928816 + 0.96561399510279522 + 0.9656638730388345 + 0.96571375526792702 + 0.96576364179060104 + 0.96581353260737957 + 0.96586342771878786 + 0.96591332712535005 + 0.96596323082759361 + 0.9660131388260399 + 0.96606305112121704 + 0.96611296771364674 + 0.96616288860385702 + 0.96621281379237411 + 0.96626274327971973 + 0.96631267706642421 + 0.96636261515301158 + 0.96641255754000399 + 0.96646250422793212 + 0.9665124552173181 + 0.9665624105086903 + 0.9666123701025735 + 0.96666233399949408 + 0.96671230219997883 + 0.96676227470455223 + 0.9668122515137435 + 0.96686223262807691 + 0.96691221804807992 + 0.96696220777427921 + 0.96701220180719982 + 0.96706220014737343 + 0.96711220279531995 + 0.96716220975156975 + 0.96721222101665194 + 0.96726223659108901 + 0.96731225647541186 + 0.96736228067014662 + 0.9674123091758221 + 0.96746234199296077 + 0.96751237912209742 + 0.96756242056375297 + 0.96761246631845976 + 0.96766251638674317 + 0.96771257076913197 + 0.9677626294661531 + 0.9678126924783359 + 0.96786275980620762 + 0.96791283145029894 + 0.96796290741113389 + 0.96801298768924315 + 0.96806307228515476 + 0.96811316119939772 + 0.96816325443250206 + 0.96821335198499292 + 0.96826345385740042 + 0.9683135600502556 + 0.96836367056408557 + 0.96841378539941914 + 0.96846390455678466 + 0.96851402803671394 + 0.96856415583973354 + 0.96861428796637494 + 0.96866442441716716 + 0.96871456519263988 + 0.9687647102933219 + 0.9688148597197408 + 0.96886501347243048 + 0.96891517155192031 + 0.96896533395873752 + 0.96901550069341413 + 0.96906567175648006 + 0.96911584714846477 + 0.9691660268699005 + 0.96921621092131494 + 0.9692663993032381 + 0.96931659201620435 + 0.96936678906074181 + 0.96941699043738039 + 0.96946719614665244 + 0.96951740618908888 + 0.96956762056521928 + 0.9696178392755791 + 0.96966806232069203 + 0.96971828970109508 + 0.96976852141731662 + 0.96981875746988999 + 0.96986899785934577 + 0.96991924258621454 + 0.96996949165102953 + 0.97001974505432198 + 0.97007000279662481 + 0.97012026487846681 + 0.97017053130038133 + 0.9702208020629024 + 0.97027107716655836 + 0.97032135661188523 + 0.97037164039941448 + 0.97042192852967779 + 0.97047222100320585 + 0.97052251782053345 + 0.97057281898219194 + 0.97062312448871746 + 0.97067343434063935 + 0.97072374853848986 + 0.97077406708280489 + 0.9708243899741148 + 0.97087471721295548 + 0.97092504879985952 + 0.97097538473535661 + 0.97102572501998607 + 0.9710760696542774 + 0.97112641863876548 + 0.97117677197398267 + 0.97122712966046398 + 0.97127749169874145 + 0.97132785808935063 + 0.97137822883282587 + 0.97142860392970043 + 0.97147898338051109 + 0.97152936718578631 + 0.97157975534606633 + 0.9716301478618814 + 0.97168054473376719 + 0.97173094596226117 + 0.97178135154789413 + 0.97183176149120165 + 0.97188217579271963 + 0.97193259445298363 + 0.97198301747252658 + 0.97203344485188514 + 0.97208387659159456 + 0.97213431269218875 + 0.97218475315420316 + 0.97223519797817459 + 0.97228564716463894 + 0.97233610071412757 + 0.9723865586271816 + 0.97243702090433459 + 0.97248748754612135 + 0.9725379585530799 + 0.97258843392574268 + 0.97263891366465283 + 0.97268939777033792 + 0.9727398862433394 + 0.97279037908419175 + 0.97284087629343374 + 0.97289137787160007 + 0.97294188381922797 + 0.97299239413685434 + 0.97304290882501387 + 0.97309342788424635 + 0.97314395131508613 + 0.973194479118071 + 0.97324501129374053 + 0.9732955478426295 + 0.97334608876527606 + 0.9733966340622171 + 0.97344718373399064 + 0.9734977377811318 + 0.97354829620418315 + 0.9735988590036776 + 0.97364942618015782 + 0.97369999773415516 + 0.97375057366621398 + 0.97380115397687028 + 0.97385173866666008 + 0.97390232773612118 + 0.9739529211857969 + 0.97400351901622073 + 0.97405412122793555 + 0.97410472782147539 + 0.97415533879738114 + 0.97420595415619127 + 0.97425657389844667 + 0.9743071980246818 + 0.97435782653543968 + 0.97440845943125687 + 0.97445909671267472 + 0.97450973838023003 + 0.97456038443446646 + 0.97461103487591583 + 0.9746616897051269 + 0.97471234892263214 + 0.9747630125289749 + 0.97481368052469486 + 0.97486435291032703 + 0.97491502968641786 + 0.97496571085350625 + 0.97501639641213056 + 0.97506708636282968 + 0.97511778070614386 + 0.9751684794426192 + 0.9752191825727895 + 0.97526989009719889 + 0.97532060201638526 + 0.9753713183308933 + 0.97542203904126046 + 0.97547276414802986 + 0.97552349365174151 + 0.97557422755293599 + 0.97562496585215319 + 0.97567570854993646 + 0.97572645564682858 + 0.97577720714336746 + 0.97582796304009667 + 0.97587872333755843 + 0.97592948803629231 + 0.97598025713684078 + 0.97603103063974495 + 0.97608180854555071 + 0.97613259085479409 + 0.97618337756802342 + 0.97623416868577551 + 0.97628496420859334 + 0.97633576413702328 + 0.97638656847160454 + 0.9764373772128806 + 0.97648819036139289 + 0.97653900791768578 + 0.97658982988230292 + 0.97664065625578411 + 0.97669148703867292 + 0.97674232223151425 + 0.97679316183485132 + 0.97684400584922471 + 0.97689485427517853 + 0.97694570711325701 + 0.97699656436400717 + 0.97704742602796435 + 0.97709829210568011 + 0.97714916259769458 + 0.97720003750455009 + 0.97725091682679377 + 0.97730180056496829 + 0.97735268871961622 + 0.97740358129128524 + 0.97745447828051524 + 0.97750537968785434 + 0.97755628551384732 + 0.97760719575903499 + 0.97765811042396278 + 0.97770902950917848 + 0.97775995301522278 + 0.97781088094264357 + 0.97786181329198685 + 0.97791275006379297 + 0.97796369125861071 + 0.97801463687698331 + 0.97806558691945888 + 0.97811654138657922 + 0.9781675002788941 + 0.97821846359694364 + 0.97826943134127786 + 0.97832040351244121 + 0.97837138011097946 + 0.97842236113743741 + 0.97847334659236307 + 0.97852433647629855 + 0.97857533078979764 + 0.97862632953339956 + 0.97867733270765345 + 0.97872834031310407 + 0.97877935235030034 + 0.97883036881978891 + 0.97888138972211258 + 0.97893241505782247 + 0.97898344482746136 + 0.97903447903158114 + 0.97908551767072416 + 0.97913656074544242 + 0.9791876082562786 + 0.97923866020378258 + 0.97928971658850172 + 0.97934077741097925 + 0.97939184267176926 + 0.9794429123714149 + 0.97949398651046637 + 0.97954506508947159 + 0.97959614810897588 + 0.97964723556952749 + 0.97969832747167662 + 0.97974942381597363 + 0.97980052460295963 + 0.97985162983318752 + 0.97990273950720808 + 0.97995385362556475 + 0.98000497218880889 + 0.98005609519748826 + 0.98010722265215167 + 0.98015835455334988 + 0.98020949090162957 + 0.98026063169753952 + 0.98031177694163063 + 0.9803629266344519 + 0.98041408077655212 + 0.98046523936848062 + 0.9805164024107863 + 0.98056756990402072 + 0.98061874184873055 + 0.98066991824546756 + 0.98072109909478344 + 0.98077228439722286 + 0.98082347415334015 + 0.98087466836368487 + 0.98092586702880624 + 0.9809770701492545 + 0.98102827772557877 + 0.98107948975833204 + 0.98113070624806575 + 0.9811819271953256 + 0.9812331526006659 + 0.98128438246463745 + 0.9813356167877918 + 0.98138685557067518 + 0.98143809881384458 + 0.98148934651784825 + 0.98154059868323862 + 0.98159185531056425 + 0.98164311640038004 + 0.98169438195323444 + 0.98174565196968266 + 0.9817969264502735 + 0.98184820539555939 + 0.98189948880609179 + 0.98195077668242181 + 0.98200206902510456 + 0.98205336583469116 + 0.9821046671117335 + 0.98215597285678202 + 0.98220728307039062 + 0.98225859775311086 + 0.98230991690549851 + 0.98236124052810092 + 0.98241256862147563 + 0.98246390118617322 + 0.98251523822274678 + 0.98256657973175066 + 0.98261792571373441 + 0.98266927616925681 + 0.98272063109886532 + 0.98277199050311426 + 0.98282335438256274 + 0.98287472273775811 + 0.98292609556925759 + 0.98297747287761084 + 0.98302885466337475 + 0.98308024092710478 + 0.98313163166935258 + 0.98318302689066905 + 0.9832344265916132 + 0.98328583077274068 + 0.98333723943459939 + 0.98338865257774899 + 0.98344007020274238 + 0.98349149231013311 + 0.98354291890047563 + 0.98359434997432837 + 0.98364578553224202 + 0.98369722557477435 + 0.98374867010247669 + 0.98380011911590914 + 0.98385157261562506 + 0.98390303060217565 + 0.98395449307612171 + 0.9840059600380191 + 0.98405743148841918 + 0.98410890742787815 + 0.98416038785695426 + 0.98421187277620192 + 0.98426336218617694 + 0.98431485608743596 + 0.98436635448053544 + 0.98441785736602982 + 0.98446936474447733 + 0.98452087661643517 + 0.98457239298245536 + 0.98462391384309911 + 0.98467543919891909 + 0.98472696905047619 + 0.9847785033983234 + 0.98483004224302195 + 0.98488158558512251 + 0.98493313342518862 + 0.98498468576377329 + 0.98503624260143652 + 0.98508780393873252 + 0.98513936977622185 + 0.98519094011445918 + 0.98524251495400483 + 0.98529409429541637 + 0.98534567813924934 + 0.98539726648606352 + 0.9854488593364148 + 0.98550045669086328 + 0.98555205854996697 + 0.98560366491428408 + 0.9856552757843704 + 0.98570689116078647 + 0.98575851104409273 + 0.9858101354348453 + 0.98586176433360051 + 0.98591339774092368 + 0.98596503565736637 + 0.98601667808349391 + 0.98606832501986308 + 0.98611997646702998 + 0.98617163242555639 + 0.98622329289600286 + 0.98627495787892638 + 0.9863266273748883 + 0.98637830138444738 + 0.98642997990816339 + 0.98648166294659523 + 0.98653335050030433 + 0.98658504256985047 + 0.98663673915579053 + 0.98668844025868874 + 0.98674014587910464 + 0.98679185601759578 + 0.98684357067472417 + 0.98689528985105146 + 0.98694701354713799 + 0.98699874176354363 + 0.98705047450082806 + 0.98710221175955171 + 0.98715395354027946 + 0.98720569984356865 + 0.98725745066998227 + 0.98730920602008065 + 0.98736096589442379 + 0.98741273029357535 + 0.98746449921809731 + 0.98751627266854847 + 0.98756805064549147 + 0.98761983314948965 + 0.98767162018110399 + 0.98772341174089506 + 0.98777520782942596 + 0.98782700844725846 + 0.987878813594953 + 0.98793062327307557 + 0.98798243748218728 + 0.9880342562228499 + 0.98808607949562632 + 0.98813790730107898 + 0.98818973963977097 + 0.98824157651226163 + 0.98829341791911962 + 0.98834526386090482 + 0.98839711433818045 + 0.98844896935151161 + 0.98850082890145718 + 0.98855269298858628 + 0.98860456161345667 + 0.98865643477663723 + 0.9887083124786874 + 0.98876019472017274 + 0.98881208150165467 + 0.98886397282370087 + 0.98891586868687331 + 0.98896776909173711 + 0.98901967403885449 + 0.98907158352879143 + 0.98912349756211204 + 0.98917541613938198 + 0.98922733926116158 + 0.98927926692802071 + 0.98933119914051793 + 0.98938313589922533 + 0.98943507720470192 + 0.98948702305751557 + 0.98953897345823127 + 0.98959092840741258 + 0.98964288790562582 + 0.98969485195343654 + 0.98974682055141006 + 0.98979879370011326 + 0.98985077140010691 + 0.98990275365196234 + 0.98995474045624265 + 0.99000673181351451 + 0.99005872772434222 + 0.99011072818929391 + 0.99016273320893389 + 0.99021474278383115 + 0.99026675691454979 + 0.9903187756016566 + 0.99037079884572066 + 0.99042282664730408 + 0.99047485900697618 + 0.9905268959253013 + 0.99057893740285152 + 0.99063098344018852 + 0.9906830340378826 + 0.99073508919650055 + 0.99078714891660746 + 0.99083921319877288 + 0.99089128204356192 + 0.99094335545154699 + 0.99099543342329099 + 0.99104751595936091 + 0.99109960306032774 + 0.99115169472675846 + 0.99120379095922162 + 0.99125589175828455 + 0.99130799712451523 + 0.99136010705848243 + 0.99141222156075348 + 0.99146434063189925 + 0.99151646427248319 + 0.99156859248308071 + 0.99162072526425582 + 0.99167286261657883 + 0.9917250045406163 + 0.99177715103694142 + 0.99182930210612053 + 0.99188145774872438 + 0.99193361796532042 + 0.99198578275647886 + 0.99203795212276891 + 0.99209012606476221 + 0.99214230458302555 + 0.99219448767812757 + 0.99224667535064281 + 0.99229886760113561 + 0.99235106443018228 + 0.99240326583834781 + 0.99245547182620397 + 0.9925076823943223 + 0.99255989754326845 + 0.99261211727361887 + 0.99266434158594341 + 0.99271657048080919 + 0.99276880395878708 + 0.99282104202045285 + 0.99287328466637048 + 0.99292553189711696 + 0.99297778371326018 + 0.99303004011537244 + 0.99308230110402429 + 0.99313456667978639 + 0.9931868368432335 + 0.99323911159493194 + 0.99329139093545926 + 0.99334367486538333 + 0.99339596338527791 + 0.99344825649571122 + 0.99350055419726124 + 0.9935528564904943 + 0.99360516337598581 + 0.99365747485430744 + 0.9937097909260324 + 0.99376211159173233 + 0.99381443685198045 + 0.99386676670734586 + 0.99391910115840743 + 0.99397144020573158 + 0.99402378384989709 + 0.99407613209147361 + 0.99412848493103501 + 0.99418084236915305 + 0.99423320440640417 + 0.99428557104335857 + 0.99433794228059269 + 0.99439031811867584 + 0.9944426985581879 + 0.99449508359969585 + 0.99454747324377957 + 0.99459986749100882 + 0.99465226634196102 + 0.99470466979720595 + 0.99475707785732115 + 0.99480949052288159 + 0.9948619077944576 + 0.99491432967262905 + 0.99496675615796648 + 0.99501918725104532 + 0.99507162295244089 + 0.99512406326273062 + 0.99517650818248382 + 0.9952289577122797 + 0.99528141185269237 + 0.99533387060429745 + 0.99538633396766807 + 0.99543880194338241 + 0.99549127453201691 + 0.99554375173414444 + 0.99559623355033966 + 0.99564871998118032 + 0.99570121102724296 + 0.99575370668910612 + 0.99580620696733957 + 0.9958587118625235 + 0.9959112213752328 + 0.99596373550604389 + 0.99601625425553331 + 0.99606877762428003 + 0.99612130561285661 + 0.99617383822184158 + 0.99622637545181236 + 0.99627891730334583 + 0.99633146377701876 + 0.99638401487340611 + 0.99643657059309032 + 0.99648913093664315 + 0.99654169590464248 + 0.99659426549767238 + 0.9966468397163013 + 0.99669941856111166 + 0.99675200203268277 + 0.99680459013159062 + 0.99685718285841007 + 0.99690978021372423 + 0.99696238219810607 + 0.99701498881214068 + 0.99706760005639883 + 0.99712021593146594 + 0.99717283643791566 + 0.99722546157632574 + 0.99727809134727996 + 0.99733072575135351 + 0.99738336478912559 + 0.99743600846117464 + 0.99748865676808363 + 0.99754130971042698 + 0.99759396728878547 + 0.99764662950373806 + 0.99769929635586596 + 0.99775196784574605 + 0.99780464397396185 + 0.99785732474108779 + 0.99791001014770819 + 0.9979627001944017 + 0.99801539488174773 + 0.99806809421032616 + 0.99812079818071608 + 0.99817350679350181 + 0.99822622004925854 + 0.99827893794857003 + 0.99833166049201694 + 0.99838438768017868 + 0.99843711951363712 + 0.99848985599297035 + 0.99854259711876303 + 0.99859534289159324 + 0.99864809331204518 + 0.99870084838069728 + 0.99875360809813207 + 0.99880637246492998 + 0.99885914148167165 + 0.99891191514894195 + 0.99896469346732186 + 0.9990174764373897 + 0.99907026405973076 + 0.99912305633492626 + 0.99917585326355662 + 0.99922865484620749 + 0.99928146108345828 + 0.99933427197588931 + 0.99938708752408945 + 0.999439907728635 + 0.99949273259011417 + 0.99954556210910395 + 0.99959839628619052 + 0.99965123512195508 + 0.99970407861698207 + 0.99975692677185291 + 0.99980977958715211 + 0.99986263706346346 + 0.99991549920137102 + 0.99996836600145511 + 1.000021237464302 + 1.000074113590494 + 1.0001269943806155 + 1.0001798798352493 + 1.0002327699549816 + 1.0002856647403933 + 1.0003385641920708 + 1.0003914683105972 + 1.0004443770965574 + 1.0004972905505389 + 1.0005502086731195 + 1.0006031314648869 + 1.0006560589264288 + 1.000708991058326 + 1.0007619278611632 + 1.0008148693355292 + 1.0008678154820065 + 1.000920766301181 + 1.0009737217936361 + 1.0010266819599623 + 1.0010796468007381 + 1.0011326163165521 + 1.0011855905079903 + 1.0012385693756385 + 1.0012915529200828 + 1.00134454114191 + 1.0013975340417036 + 1.0014505316200497 + 1.0015035338775378 + 1.0015565408147491 + 1.001609552432275 + 1.0016625687306999 + 1.0017155897106105 + 1.0017686153725913 + 1.0018216457172338 + 1.0018746807451224 + 1.001927720456842 + 1.0019807648529842 + 1.0020338139341316 + 1.0020868677008736 + 1.002139926153798 + 1.0021929892934915 + 1.002246057120542 + 1.0022991296355344 + 1.0023522068390611 + 1.0024052887317074 + 1.0024583753140612 + 1.0025114665867125 + 1.0025645625502466 + 1.0026176632052517 + 1.0026707685523186 + 1.0027238785920347 + 1.0027769933249882 + 1.0028301127517676 + 1.002883236872959 + 1.0029363656891574 + 1.0029894992009447 + 1.0030426374089161 + 1.0030957803136558 + 1.0031489279157546 + 1.0032020802158039 + 1.0032552372143921 + 1.0033083989121059 + 1.0033615653095367 + 1.0034147364072736 + 1.003467912205908 + 1.003521092706027 + 1.0035742779082235 + 1.0036274678130861 + 1.0036806624212051 + 1.0037338617331708 + 1.0037870657495729 + 1.0038402744710002 + 1.0038934878980477 + 1.0039467060313028 + 1.0039999288713553 + 1.0040531564187993 + 1.0041063886742234 + 1.0041596256382193 + 1.004212867311375 + 1.0042661136942876 + 1.0043193647875435 + 1.0043726205917387 + 1.0044258811074576 + 1.0044791463352998 + 1.0045324162758489 + 1.0045856909297026 + 1.0046389702974514 + 1.0046922543796863 + 1.0047455431770007 + 1.0047988366899852 + 1.004852134919231 + 1.0049054378653337 + 1.0049587455288822 + 1.0050120579104727 + 1.0050653750106959 + 1.0051186968301438 + 1.0051720233694077 + 1.0052253546290857 + 1.0052786906097653 + 1.0053320313120451 + 1.0053853767365144 + 1.005438726883765 + 1.005492081754396 + 1.0055454413489946 + 1.0055988056681571 + 1.0056521747124787 + 1.005705548482551 + 1.0057589269789691 + 1.0058123102023249 + 1.0058656981532157 + 1.0059190908322342 + 1.0059724882399723 + 1.0060258903770278 + 1.006079297243994 + 1.0061327088414649 + 1.0061861251700337 + 1.0062395462302987 + 1.006292972022852 + 1.0063464025482893 + 1.0063998378072039 + 1.0064532778001962 + 1.0065067225278546 + 1.0065601719907795 + 1.0066136261895642 + 1.0066670851248023 + 1.0067205487970921 + 1.0067740172070323 + 1.0068274903552112 + 1.0068809682422308 + 1.0069344508686839 + 1.0069879382351672 + 1.0070414303422772 + 1.0070949271906098 + 1.0071484287807599 + 1.0072019351133286 + 1.0072554461889103 + 1.0073089620080991 + 1.0073624825714942 + 1.0074160078796901 + 1.0074695379332868 + 1.0075230727328803 + 1.0075766122790661 + 1.0076301565724437 + 1.0076837056136103 + 1.0077372594031626 + 1.0077908179416968 + 1.0078443812298117 + 1.0078979492681055 + 1.007951522057176 + 1.0080050995976226 + 1.0080586818900388 + 1.0081122689350248 + 1.0081658607331807 + 1.0082194572851046 + 1.0082730585913924 + 1.0083266646526443 + 1.0083802754694586 + 1.008433891042434 + 1.0084875113721687 + 1.0085411364592607 + 1.0085947663043136 + 1.0086484009079215 + 1.008702040270685 + 1.0087556843932057 + 1.0088093332760795 + 1.0088629869199057 + 1.0089166453252878 + 1.0089703084928225 + 1.0090239764231115 + 1.0090776491167515 + 1.0091313265743465 + 1.0091850087964935 + 1.0092386957837916 + 1.0092923875368454 + 1.0093460840562523 + 1.0093997853426135 + 1.0094534913965298 + 1.0095072022186022 + 1.0095609178094294 + 1.0096146381696125 + 1.0096683632997547 + 1.009722093200456 + 1.0097758278723161 + 1.0098295673159381 + 1.0098833115319246 + 1.0099370605208733 + 1.0099908142833873 + 1.0100445728200695 + 1.0100983361315183 + 1.0101521042183388 + 1.0102058770811317 + 1.0102596547205005 + 1.0103134371370459 + 1.0103672243313688 + 1.0104210163040728 + 1.0104748130557615 + 1.0105286145870362 + 1.0105824208984999 + 1.0106362319907525 + 1.0106900478644016 + 1.0107438685200472 + 1.010797693958295 + 1.0108515241797422 + 1.0109053591849977 + 1.0109591989746627 + 1.0110130435493421 + 1.0110668929096354 + 1.0111207470561518 + 1.0111746059894884 + 1.0112284697102545 + 1.0112823382190526 + 1.0113362115164846 + 1.0113900896031558 + 1.0114439724796729 + 1.0114978601466365 + 1.0115517526046516 + 1.0116056498543253 + 1.0116595518962581 + 1.0117134587310577 + 1.0117673703593295 + 1.011821286781674 + 1.0118752079987017 + 1.0119291340110126 + 1.0119830648192154 + 1.0120370004239154 + 1.0120909408257162 + 1.0121448860252236 + 1.0121988360230432 + 1.0122527908197789 + 1.0123067504160417 + 1.0123607148124298 + 1.0124146840095576 + 1.0124686580080255 + 1.012522636808441 + 1.0125766204114095 + 1.0126306088175381 + 1.0126846020274334 + 1.0127386000417042 + 1.0127926028609526 + 1.0128466104857898 + 1.0129006229168185 + 1.0129546401546476 + 1.0130086621998868 + 1.0130626890531378 + 1.0131167207150114 + 1.0131707571861135 + 1.0132247984670548 + 1.0132788445584373 + 1.0133328954608716 + 1.0133869511749665 + 1.0134410117013282 + 1.0134950770405642 + 1.0135491471932847 + 1.0136032221600948 + 1.0136573019416075 + 1.0137113865384237 + 1.0137654759511583 + 1.01381957018042 + 1.013873669226812 + 1.0139277730909473 + 1.0139818817734343 + 1.014035995274879 + 1.0140901135958924 + 1.0141442367370859 + 1.0141983646990651 + 1.0142524974824418 + 1.014306635087824 + 1.0143607775158217 + 1.0144149247670431 + 1.0144690768421001 + 1.0145232337416015 + 1.014577395466159 + 1.0146315620163795 + 1.0146857333928749 + 1.0147399095962544 + 1.0147940906271302 + 1.0148482764861091 + 1.0149024671738061 + 1.0149566626908304 + 1.0150108630377899 + 1.0150650682152969 + 1.0151192782239655 + 1.0151734930644016 + 1.01522771273722 + 1.0152819372430331 + 1.0153361665824463 + 1.0153904007560752 + 1.0154446397645325 + 1.0154988836084258 + 1.0155531322883686 + 1.0156073858049763 + 1.0156616441588546 + 1.0157159073506192 + 1.015770175380881 + 1.0158244482502534 + 1.0158787259593476 + 1.0159330085087768 + 1.015987295899152 + 1.0160415881310876 + 1.0160958852051942 + 1.0161501871220884 + 1.0162044938823793 + 1.0162588054866806 + 1.0163131219356061 + 1.0163674432297709 + 1.0164217693697835 + 1.0164761003562612 + 1.016530436189818 + 1.0165847768710656 + 1.0166391224006166 + 1.0166934727790877 + 1.0167478280070916 + 1.01680218808524 + 1.0168565530141509 + 1.016910922794438 + 1.0169652974267125 + 1.0170196769115889 + 1.0170740612496871 + 1.0171284504416156 + 1.0171828444879918 + 1.0172372433894306 + 1.0172916471465481 + 1.0173460557599572 + 1.0174004692302705 + 1.0174548875581113 + 1.0175093107440856 + 1.0175637387888146 + 1.0176181716929134 + 1.0176726094569954 + 1.0177270520816775 + 1.0177814995675754 + 1.0178359519153051 + 1.0178904091254826 + 1.0179448711987249 + 1.0179993381356458 + 1.0180538099368639 + 1.0181082866029962 + 1.0181627681346566 + 1.0182172545324639 + 1.0182717457970332 + 1.0183262419289814 + 1.0183807429289271 + 1.0184352487974853 + 1.0184897595352758 + 1.018544275142913 + 1.0185987956210165 + 1.0186533209702013 + 1.0187078511910876 + 1.0187623862842901 + 1.0188169262504312 + 1.0188714710901212 + 1.0189260208039854 + 1.0189805753926389 + 1.0190351348566997 + 1.0190896991967855 + 1.0191442684135148 + 1.0191988425075076 + 1.0192534214793798 + 1.0193080053297545 + 1.0193625940592455 + 1.0194171876684732 + 1.0194717861580587 + 1.0195263895286202 + 1.0195809977807746 + 1.0196356109151425 + 1.0196902289323428 + 1.019744851832997 + 1.0197994796177214 + 1.0198541122871401 + 1.0199087498418691 + 1.0199633922825282 + 1.0200180396097389 + 1.0200726918241232 + 1.0201273489262974 + 1.0201820109168818 + 1.0202366777965002 + 1.0202913495657724 + 1.0203460262253159 + 1.0204007077757526 + 1.020455394217705 + 1.0205100855517908 + 1.0205647817786367 + 1.0206194828988584 + 1.0206741889130779 + 1.0207288998219166 + 1.0207836156259988 + 1.0208383363259423 + 1.0208930619223711 + 1.0209477924159069 + 1.0210025278071686 + 1.0210572680967815 + 1.0211120132853668 + 1.0211667633735451 + 1.0212215183619395 + 1.0212762782511713 + 1.0213310430418665 + 1.0213858127346414 + 1.0214405873301244 + 1.0214953668289368 + 1.0215501512317005 + 1.0216049405390364 + 1.0216597347515708 + 1.0217145338699261 + 1.0217693378947257 + 1.0218241468265916 + 1.0218789606661463 + 1.0219337794140178 + 1.0219886030708267 + 1.0220434316371949 + 1.0220982651137493 + 1.0221531035011122 + 1.0222079467999081 + 1.0222627950107621 + 1.0223176481342993 + 1.0223725061711397 + 1.0224273691219108 + 1.0224822369872375 + 1.0225371097677427 + 1.0225919874640546 + 1.0226468700767928 + 1.0227017576065862 + 1.0227566500540599 + 1.0228115474198369 + 1.0228664497045432 + 1.0229213569088047 + 1.0229762690332489 + 1.0230311860784951 + 1.0230861080451743 + 1.0231410349339123 + 1.0231959667453328 + 1.0232509034800619 + 1.0233058451387287 + 1.0233607917219547 + 1.0234157432303708 + 1.0234706996645995 + 1.023525661025269 + 1.0235806273130064 + 1.0236355985284389 + 1.0236905746721898 + 1.023745555744892 + 1.0238005417471674 + 1.0238555326796428 + 1.0239105285429504 + 1.0239655293377123 + 1.024020535064559 + 1.0240755457241197 + 1.0241305613170171 + 1.0241855818438814 + 1.0242406073053405 + 1.0242956377020216 + 1.0243506730345551 + 1.0244057133035662 + 1.0244607585096834 + 1.0245158086535393 + 1.0245708637357549 + 1.0246259237569653 + 1.0246809887177966 + 1.0247360586188796 + 1.0247911334608379 + 1.024846213244307 + 1.0249012979699108 + 1.024956387638281 + 1.0250114822500476 + 1.0250665818058378 + 1.0251216863062826 + 1.0251767957520115 + 1.0252319101436553 + 1.0252870294818408 + 1.0253421537671976 + 1.0253972830003597 + 1.0254524171819561 + 1.0255075563126146 + 1.0255627003929642 + 1.0256178494236416 + 1.0256730034052721 + 1.0257281623384897 + 1.0257833262239224 + 1.0258384950622026 + 1.0258936688539624 + 1.0259488475998269 + 1.0260040313004342 + 1.0260592199564136 + 1.0261144135683935 + 1.0261696121370092 + 1.0262248156628915 + 1.0262800241466699 + 1.026335237588976 + 1.0263904559904451 + 1.0264456793517076 + 1.0265009076733949 + 1.0265561409561377 + 1.0266113792005718 + 1.0266666224073284 + 1.0267218705770387 + 1.0267771237103367 + 1.0268323818078531 + 1.0268876448702244 + 1.02694291289808 + 1.0269981858920538 + 1.0270534638527791 + 1.027108746780891 + 1.027164034677019 + 1.0272193275418013 + 1.0272746253758684 + 1.0273299281798542 + 1.0273852359543909 + 1.0274405487001157 + 1.027495866417661 + 1.027551189107659 + 1.0276065167707471 + 1.0276618494075576 + 1.0277171870187281 + 1.027772529604889 + 1.0278278771666753 + 1.0278832297047225 + 1.0279385872196656 + 1.02799394971214 + 1.0280493171827818 + 1.0281046896322212 + 1.0281600670610989 + 1.0282154494700479 + 1.0282708368597049 + 1.0283262292307023 + 1.0283816265836792 + 1.0284370289192712 + 1.0284924362381103 + 1.0285478485408346 + 1.0286032658280828 + 1.0286586881004867 + 1.0287141153586852 + 1.0287695476033145 + 1.0288249848350111 + 1.0288804270544101 + 1.0289358742621497 + 1.0289913264588653 + 1.0290467836451955 + 1.0291022458217776 + 1.0291577129892464 + 1.0292131851482389 + 1.0292686622993974 + 1.0293241444433519 + 1.0293796315807471 + 1.029435123712215 + 1.0294906208383967 + 1.0295461229599268 + 1.029601630077448 + 1.0296571421915954 + 1.0297126593030073 + 1.0297681814123218 + 1.0298237085201765 + 1.0298792406272124 + 1.0299347777340673 + 1.0299903198413776 + 1.0300458669497834 + 1.0301014190599236 + 1.0301569761724412 + 1.0302125382879659 + 1.0302681054071454 + 1.0303236775306166 + 1.0303792546590174 + 1.0304348367929903 + 1.0304904239331711 + 1.0305460160802042 + 1.0306016132347238 + 1.0306572153973739 + 1.0307128225687936 + 1.0307684347496229 + 1.030824051940501 + 1.0308796741420698 + 1.0309353013549694 + 1.0309909335798413 + 1.0310465708173233 + 1.0311022130680576 + 1.0311578603326867 + 1.0312135126118505 + 1.0312691699061893 + 1.0313248322163462 + 1.0313804995429603 + 1.0314361718866756 + 1.0314918492481293 + 1.0315475316279672 + 1.0316032190268301 + 1.031658911445358 + 1.0317146088841951 + 1.031770311343984 + 1.0318260188253632 + 1.0318817313289765 + 1.0319374488554696 + 1.0319931714054813 + 1.0320488989796555 + 1.0321046315786357 + 1.032160369203061 + 1.032216111853578 + 1.03227185953083 + 1.032327612235457 + 1.0323833699681055 + 1.0324391327294169 + 1.0324949005200337 + 1.0325506733406018 + 1.0326064511917643 + 1.0326622340741654 + 1.0327180219884449 + 1.0327738149352521 + 1.0328296129152299 + 1.0328854159290206 + 1.0329412239772691 + 1.0329970370606227 + 1.0330528551797198 + 1.0331086783352099 + 1.0331645065277362 + 1.0332203397579438 + 1.0332761780264765 + 1.0333320213339814 + 1.0333878696811023 + 1.0334437230684845 + 1.033499581496774 + 1.0335554449666142 + 1.0336113134786533 + 1.0336671870335354 + 1.0337230656319087 + 1.0337789492744147 + 1.0338348379617044 + 1.0338907316944215 + 1.0339466304732106 + 1.03400253429872 + 1.0340584431715945 + 1.0341143570924827 + 1.0341702760620315 + 1.0342262000808857 + 1.0342821291496918 + 1.0343380632690995 + 1.0343940024397531 + 1.0344499466623001 + 1.0345058959373903 + 1.0345618502656679 + 1.0346178096477836 + 1.0346737740843823 + 1.0347297435761136 + 1.0347857181236229 + 1.0348416977275603 + 1.0348976823885743 + 1.0349536721073094 + 1.0350096668844166 + 1.0350656667205462 + 1.0351216716163418 + 1.0351776815724558 + 1.0352336965895348 + 1.0352897166682291 + 1.0353457418091878 + 1.0354017720130588 + 1.035457807280491 + 1.0355138476121331 + 1.0355698930086341 + 1.0356259434706476 + 1.0356819989988202 + 1.0357380595937984 + 1.0357941252562382 + 1.0358501959867827 + 1.0359062717860896 + 1.0359623526548019 + 1.0360184385935733 + 1.036074529603054 + 1.0361306256838956 + 1.0361867268367431 + 1.0362428330622533 + 1.0362989443610739 + 1.0363550607338572 + 1.0364111821812507 + 1.0364673087039096 + 1.0365234403024839 + 1.036579576977624 + 1.0366357187299804 + 1.036691865560208 + 1.0367480174689527 + 1.036804174456875 + 1.0368603365246176 + 1.0369165036728372 + 1.0369726759021836 + 1.0370288532133107 + 1.0370850356068697 + 1.0371412230835138 + 1.0371974156438941 + 1.0372536132886645 + 1.0373098160184788 + 1.0373660238339857 + 1.0374222367358419 + 1.0374784547246989 + 1.0375346778012107 + 1.0375909059660267 + 1.0376471392198059 + 1.0377033775631983 + 1.0377596209968576 + 1.0378158695214386 + 1.0378721231375958 + 1.0379283818459795 + 1.0379846456472461 + 1.0380409145420488 + 1.0380971885310444 + 1.0381534676148836 + 1.038209751794221 + 1.038266041069714 + 1.0383223354420161 + 1.0383786349117798 + 1.038434939479663 + 1.038491249146319 + 1.0385475639124029 + 1.0386038837785709 + 1.0386602087454759 + 1.038716538813774 + 1.0387728739841233 + 1.0388292142571776 + 1.0388855596335929 + 1.0389419101140229 + 1.0389982656991263 + 1.0390546263895573 + 1.039110992185974 + 1.0391673630890288 + 1.039223739099385 + 1.0392801202176922 + 1.0393365064446098 + 1.0393928977807942 + 1.0394492942269005 + 1.0395056957835898 + 1.0395621024515149 + 1.0396185142313346 + 1.039674931123707 + 1.0397313531292893 + 1.0397877802487336 + 1.0398442124827076 + 1.039900649831861 + 1.039957092296852 + 1.040013539878343 + 1.0400699925769894 + 1.0401264503934466 + 1.0401829133283775 + 1.0402393813824375 + 1.0402958545562879 + 1.0403523328505815 + 1.0404088162659835 + 1.0404653048031487 + 1.0405217984627366 + 1.0405782972454067 + 1.0406348011518198 + 1.0406913101826301 + 1.0407478243385031 + 1.0408043436200931 + 1.0408608680280615 + 1.0409173975630701 + 1.0409739322257729 + 1.0410304720168364 + 1.0410870169369175 + 1.0411435669866758 + 1.0412001221667728 + 1.0412566824778688 + 1.0413132479206202 + 1.0413698184956923 + 1.0414263942037467 + 1.0414829750454366 + 1.0415395610214311 + 1.0415961521323884 + 1.0416527483789659 + 1.0417093497618286 + 1.0417659562816399 + 1.0418225679390545 + 1.0418791847347408 + 1.0419358066693543 + 1.0419924337435627 + 1.0420490659580222 + 1.0421057033133982 + 1.0421623458103522 + 1.0422189934495445 + 1.0422756462316389 + 1.0423323041572987 + 1.0423889672271858 + 1.0424456354419633 + 1.0425023088022909 + 1.0425589873088339 + 1.0426156709622547 + 1.042672359763215 + 1.0427290537123834 + 1.0427857528104167 + 1.04284245705798 + 1.0428991664557368 + 1.0429558810043551 + 1.0430126007044913 + 1.0430693255568126 + 1.0431260555619843 + 1.0431827907206688 + 1.0432395310335305 + 1.0432962765012348 + 1.0433530271244438 + 1.0434097829038234 + 1.0434665438400383 + 1.043523309933752 + 1.0435800811856299 + 1.0436368575963393 + 1.0436936391665415 + 1.0437504258969017 + 1.0438072177880886 + 1.0438640148407656 + 1.0439208170555958 + 1.0439776244332482 + 1.0440344369743884 + 1.0440912546796801 + 1.0441480775497904 + 1.0442049055853846 + 1.04426173878713 + 1.0443185771556924 + 1.0443754206917393 + 1.0444322693959343 + 1.0444891232689444 + 1.0445459823114385 + 1.0446028465240818 + 1.0446597159075433 + 1.0447165904624856 + 1.0447734701895803 + 1.0448303550894924 + 1.0448872451628899 + 1.0449441404104418 + 1.0450010408328136 + 1.0450579464306706 + 1.0451148572046853 + 1.045171773155523 + 1.0452286942838542 + 1.0452856205903418 + 1.0453425520756607 + 1.0453994887404754 + 1.045456430585453 + 1.0455133776112646 + 1.045570329818579 + 1.0456272872080641 + 1.0456842497803887 + 1.0457412175362235 + 1.0457981904762357 + 1.0458551686010933 + 1.04591215191147 + 1.0459691404080307 + 1.0460261340914487 + 1.0460831329623907 + 1.0461401370215264 + 1.0461971462695299 + 1.0462541607070677 + 1.0463111803348095 + 1.0463682051534278 + 1.0464252351635914 + 1.0464822703659711 + 1.0465393107612355 + 1.0465963563500604 + 1.0466534071331131 + 1.0467104631110635 + 1.0467675242845842 + 1.0468245906543459 + 1.0468816622210206 + 1.0469387389852793 + 1.046995820947795 + 1.0470529081092355 + 1.0471100004702767 + 1.0471670980315866 + 1.0472242007938388 + 1.0472813087577066 + 1.0473384219238608 + 1.0473955402929731 + 1.0474526638657164 + 1.0475097926427621 + 1.0475669266247871 + 1.0476240658124598 + 1.0476812102064543 + 1.0477383598074448 + 1.0477955146161002 + 1.0478526746331001 + 1.0479098398591109 + 1.0479670102948102 + 1.0480241859408721 + 1.0480813667979685 + 1.0481385528667722 + 1.0481957441479572 + 1.048252940642199 + 1.0483101423501719 + 1.0483673492725492 + 1.0484245614100032 + 1.0484817787632137 + 1.0485390013328488 + 1.0485962291195889 + 1.0486534621241046 + 1.0487107003470706 + 1.0487679437891637 + 1.048825192451059 + 1.0488824463334321 + 1.0489397054369567 + 1.0489969697623089 + 1.0490542393101641 + 1.0491115140811991 + 1.049168794076087 + 1.0492260792955073 + 1.0492833697401334 + 1.0493406654106416 + 1.0493979663077067 + 1.0494552724320094 + 1.0495125837842223 + 1.0495699003650241 + 1.0496272221750897 + 1.0496845492150979 + 1.0497418814857213 + 1.0497992189876419 + 1.049856561721535 + 1.0499139096880767 + 1.0499712628879452 + 1.0500286213218202 + 1.050085984990375 + 1.0501433538942908 + 1.0502007280342422 + 1.0502581074109083 + 1.0503154920249695 + 1.0503728818771016 + 1.0504302769679832 + 1.0504876772982916 + 1.0505450828687057 + 1.0506024936799059 + 1.0506599097325708 + 1.050717331027377 + 1.0507747575650044 + 1.0508321893461325 + 1.0508896263714398 + 1.0509470686416058 + 1.0510045161573085 + 1.0510619689192326 + 1.0511194269280495 + 1.0511768901844456 + 1.0512343586890982 + 1.0512918324426865 + 1.0513493114458923 + 1.0514067956993955 + 1.0514642852038751 + 1.0515217799600114 + 1.0515792799684867 + 1.0516367852299808 + 1.0516942957451758 + 1.0517518115147473 + 1.0518093325393829 + 1.0518668588197597 + 1.0519243903565587 + 1.0519819271504651 + 1.0520394692021546 + 1.0520970165123149 + 1.0521545690816241 + 1.0522121269107612 + 1.0522696900004138 + 1.0523272583512628 + 1.0523848319639848 + 1.0524424108392703 + 1.0524999949777962 + 1.0525575843802455 + 1.0526151790473002 + 1.052672778979646 + 1.0527303841779625 + 1.0527879946429335 + 1.0528456103752439 + 1.0529032313755744 + 1.0529608576446106 + 1.0530184891830332 + 1.0530761259915276 + 1.0531337680707755 + 1.0531914154214645 + 1.0532490680442743 + 1.0533067259398894 + 1.0533643891089952 + 1.053422057552277 + 1.0534797312704145 + 1.0535374102640975 + 1.0535950945340076 + 1.0536527840808292 + 1.053710478905248 + 1.0537681790079498 + 1.0538258843896151 + 1.0538835950509347 + 1.0539413109925919 + 1.0539990322152704 + 1.0540567587196559 + 1.0541144905064348 + 1.0541722275762928 + 1.0542299699299165 + 1.0542877175679901 + 1.0543454704911996 + 1.0544032287002316 + 1.054460992195775 + 1.054518760978512 + 1.0545765350491298 + 1.0546343144083163 + 1.0546920990567576 + 1.0547498889951397 + 1.0548076842241525 + 1.0548654847444783 + 1.0549232905568098 + 1.0549811016618313 + 1.055038918060228 + 1.0550967397526902 + 1.0551545667399056 + 1.0552123990225613 + 1.055270236601346 + 1.0553280794769448 + 1.0553859276500479 + 1.0554437811213437 + 1.0555016398915231 + 1.0555595039612666 + 1.0556173733312699 + 1.0556752480022193 + 1.0557331279748037 + 1.055791013249713 + 1.0558489038276322 + 1.0559067997092568 + 1.0559647008952715 + 1.0560226073863666 + 1.0560805191832299 + 1.0561384362865525 + 1.056196358697028 + 1.0562542864153395 + 1.0563122194421803 + 1.0563701577782407 + 1.0564281014242103 + 1.056486050380778 + 1.0565440046486365 + 1.0566019642284761 + 1.0566599291209837 + 1.0567178993268569 + 1.0567758748467782 + 1.0568338556814456 + 1.0568918418315469 + 1.0569498332977747 + 1.0570078300808172 + 1.0570658321813704 + 1.0571238396001212 + 1.0571818523377665 + 1.0572398703949941 + 1.0572978937724953 + 1.0573559224709657 + 1.0574139564910938 + 1.0574719958335734 + 1.0575300404990984 + 1.0575880904883601 + 1.0576461458020501 + 1.0577042064408619 + 1.0577622724054876 + 1.0578203436966211 + 1.0578784203149547 + 1.0579365022611824 + 1.0579945895359957 + 1.0580526821400924 + 1.0581107800741596 + 1.0581688833388965 + 1.0582269919349934 + 1.0582851058631475 + 1.0583432251240488 + 1.0584013497183948 + 1.0584594796468758 + 1.0585176149101898 + 1.0585757555090314 + 1.0586339014440918 + 1.0586920527160686 + 1.0587502093256553 + 1.0588083712735468 + 1.0588665385604399 + 1.0589247111870272 + 1.0589828891540052 + 1.0590410724620696 + 1.0590992611119143 + 1.0591574551042378 + 1.0592156544397338 + 1.0592738591190991 + 1.0593320691430248 + 1.0593902845122156 + 1.0594485052273623 + 1.0595067312891622 + 1.0595649626983124 + 1.0596231994555068 + 1.0596814415614451 + 1.0597396890168269 + 1.0597979418223396 + 1.0598561999786904 + 1.0599144634865689 + 1.0599727323466752 + 1.0600310065597098 + 1.0600892861263669 + 1.0601475710473427 + 1.0602058613233374 + 1.0602641569550486 + 1.0603224579431738 + 1.0603807642884095 + 1.0604390759914588 + 1.0604973930530122 + 1.060555715473775 + 1.0606140432544444 + 1.060672376395718 + 1.0607307148982943 + 1.0607890587628728 + 1.0608474079901518 + 1.06090576258083 + 1.0609641225356095 + 1.0610224878551866 + 1.0610808585402625 + 1.0611392345915345 + 1.0611976160097067 + 1.061256002795476 + 1.0613143949495401 + 1.0613727924726024 + 1.0614311953653635 + 1.0614896036285226 + 1.06154801726278 + 1.0616064362688356 + 1.0616648606473915 + 1.0617232903991485 + 1.0617817255248068 + 1.061840166025066 + 1.0618986119006273 + 1.0619570631521957 + 1.0620155197804695 + 1.0620739817861515 + 1.0621324491699429 + 1.0621909219325449 + 1.0622494000746576 + 1.0623078835969872 + 1.062366372500233 + 1.062424866785098 + 1.0624833664522837 + 1.0625418715024941 + 1.0626003819364329 + 1.0626588977547973 + 1.0627174189582931 + 1.0627759455476256 + 1.0628344775234955 + 1.062893014886608 + 1.0629515576376598 + 1.0630101057773629 + 1.0630686593064174 + 1.0631272182255256 + 1.0631857825353921 + 1.0632443522367214 + 1.063302927330217 + 1.063361507816581 + 1.0634200936965215 + 1.0634786849707407 + 1.0635372816399447 + 1.0635958837048338 + 1.0636544911661181 + 1.0637131040244991 + 1.063771722280682 + 1.0638303459353726 + 1.0638889749892748 + 1.0639476094430969 + 1.0640062492975402 + 1.0640648945533158 + 1.0641235452111224 + 1.0641822012716691 + 1.0642408627356645 + 1.0642995296038111 + 1.0643582018768147 + 1.0644168795553848 + 1.0644755626402256 + 1.0645342511320419 + 1.0645929450315432 + 1.0646516443394343 + 1.0647103490564243 + 1.0647690591832155 + 1.0648277747205213 + 1.0648864956690456 + 1.0649452220294966 + 1.0650039538025791 + 1.0650626909890011 + 1.0651214335894756 + 1.0651801816047051 + 1.0652389350353981 + 1.0652976938822647 + 1.0653564581460111 + 1.0654152278273477 + 1.0654740029269785 + 1.0655327834456159 + 1.0655915693839697 + 1.0656503607427454 + 1.0657091575226545 + 1.0657679597244027 + 1.0658267673487003 + 1.0658855803962572 + 1.0659443988677839 + 1.0660032227639886 + 1.0660620520855812 + 1.0661208868332708 + 1.0661797270077669 + 1.0662385726097796 + 1.0662974236400202 + 1.066356280099199 + 1.0664151419880259 + 1.066474009307208 + 1.0665328820574604 + 1.0665917602394934 + 1.0666506438540144 + 1.0667095329017393 + 1.0667684273833729 + 1.0668273272996305 + 1.0668862326512236 + 1.0669451434388619 + 1.0670040596632571 + 1.0670629813251216 + 1.0671219084251669 + 1.0671808409641037 + 1.0672397789426458 + 1.0672987223615047 + 1.0673576712213935 + 1.067416625523022 + 1.0674755852671034 + 1.0675345504543519 + 1.0675935210854794 + 1.0676524971612003 + 1.0677114786822237 + 1.0677704656492664 + 1.0678294580630383 + 1.0678884559242585 + 1.0679474592336322 + 1.068006467991879 + 1.0680654821997089 + 1.0681245018578394 + 1.0681835269669828 + 1.068242557527852 + 1.0683015935411626 + 1.0683606350076291 + 1.0684196819279626 + 1.068478734302881 + 1.0685377921330999 + 1.0685968554193301 + 1.0686559241622897 + 1.0687149983626922 + 1.0687740780212536 + 1.0688331631386876 + 1.0688922537157128 + 1.0689513497530405 + 1.0690104512513894 + 1.069069558211474 + 1.0691286706340102 + 1.0691877885197145 + 1.0692469118693018 + 1.0693060406834913 + 1.0693651749629942 + 1.0694243147085309 + 1.0694834599208156 + 1.0695426106005679 + 1.0696017667485029 + 1.0696609283653373 + 1.0697200954517896 + 1.0697792680085763 + 1.0698384460364134 + 1.0698976295360179 + 1.0699568185081108 + 1.0700160129534071 + 1.0700752128726252 + 1.0701344182664827 + 1.0701936291356979 + 1.070252845480987 + 1.070312067303073 + 1.070371294602672 + 1.0704305273805004 + 1.0704897656372787 + 1.070549009373726 + 1.0706082585905587 + 1.0706675132885006 + 1.0707267734682662 + 1.0707860391305786 + 1.070845310276153 + 1.0709045869057108 + 1.0709638690199739 + 1.0710231566196593 + 1.0710824497054867 + 1.0711417482781782 + 1.0712010523384512 + 1.0712603618870253 + 1.0713196769246256 + 1.0713789974519694 + 1.0714383234697773 + 1.071497654978772 + 1.071556991979671 + 1.0716163344731973 + 1.0716756824600715 + 1.0717350359410165 + 1.0717943949167505 + 1.0718537593879973 + 1.0719131293554773 + 1.0719725048199142 + 1.0720318857820268 + 1.0720912722425404 + 1.0721506642021716 + 1.0722100616616499 + 1.072269464621691 + 1.0723288730830194 + 1.0723882870463612 + 1.0724477065124363 + 1.0725071314819636 + 1.0725665619556748 + 1.0726259979342847 + 1.0726854394185203 + 1.0727448864091063 + 1.0728043389067625 + 1.0728637969122141 + 1.0729232604261827 + 1.0729827294493965 + 1.0730422039825782 + 1.0731016840264476 + 1.0731611695817329 + 1.0732206606491594 + 1.073280157229445 + 1.0733396593233231 + 1.0733991669315115 + 1.0734586800547392 + 1.0735181986937286 + 1.0735777228492038 + 1.0736372525218911 + 1.0736967877125188 + 1.0737563284218079 + 1.0738158746504853 + 1.0738754263992774 + 1.0739349836689105 + 1.0739945464601062 + 1.0740541147735962 + 1.0741136886101028 + 1.0741732679703551 + 1.0742328528550775 + 1.0742924432649945 + 1.0743520392008361 + 1.0744116406633273 + 1.0744712476531975 + 1.0745308601711716 + 1.0745904782179756 + 1.0746501017943386 + 1.0747097309009863 + 1.074769365538649 + 1.0748290057080523 + 1.0748886514099243 + 1.0749483026449924 + 1.0750079594139834 + 1.07506762171763 + 1.075127289556653 + 1.0751869629317887 + 1.0752466418437585 + 1.0753063262932954 + 1.0753660162811287 + 1.0754257118079844 + 1.0754854128745921 + 1.0755451194816803 + 1.0756048316299831 + 1.075664549320223 + 1.0757242725531337 + 1.0757840013294422 + 1.075843735649878 + 1.075903475515176 + 1.075963220926061 + 1.0760229718832652 + 1.0760827283875161 + 1.0761424904395485 + 1.0762022580400896 + 1.0762620311898707 + 1.0763218098896239 + 1.0763815941400747 + 1.0764413839419633 + 1.0765011792960135 + 1.0765609802029552 + 1.0766207866635271 + 1.0766805986784553 + 1.0767404162484728 + 1.0768002393743108 + 1.0768600680567029 + 1.0769199022963778 + 1.0769797420940694 + 1.0770395874505092 + 1.0770994383664312 + 1.0771592948425672 + 1.0772191568796483 + 1.077279024478407 + 1.0773388976395799 + 1.0773987763638966 + 1.0774586606520888 + 1.0775185505048941 + 1.0775784459230398 + 1.0776383469072681 + 1.0776982534583039 + 1.0777581655768855 + 1.0778180832637445 + 1.0778780065196163 + 1.0779379353452347 + 1.0779978697413342 + 1.0780578097086482 + 1.0781177552479122 + 1.078177706359857 + 1.0782376630452235 + 1.0782976253047423 + 1.07835759313915 + 1.0784175665491795 + 1.0784775455355702 + 1.078537530099053 + 1.0785975202403646 + 1.078657515960241 + 1.0787175172594194 + 1.078777524138633 + 1.0788375365986196 + 1.0788975546401129 + 1.0789575782638507 + 1.0790176074705717 + 1.0790776422610082 + 1.0791376826358978 + 1.0791977285959775 + 1.0792577801419876 + 1.0793178372746575 + 1.0793778999947308 + 1.0794379683029418 + 1.0794980422000313 + 1.0795581216867296 + 1.0796182067637825 + 1.0796782974319201 + 1.0797383936918861 + 1.0797984955444158 + 1.0798586029902475 + 1.079918716030118 + 1.0799788346647703 + 1.0800389588949357 + 1.0800990887213606 + 1.0801592241447788 + 1.0802193651659291 + 1.080279511785553 + 1.080339664004385 + 1.0803998218231718 + 1.0804599852426449 + 1.0805201542635487 + 1.0805803288866214 + 1.0806405091126012 + 1.0807006949422284 + 1.0807608863762452 + 1.080821083415392 + 1.0808812860604036 + 1.080941494312027 + 1.0810017081709982 + 1.0810619276380597 + 1.0811221527139518 + 1.0811823833994127 + 1.0812426196951905 + 1.0813028616020179 + 1.0813631091206415 + 1.0814233622518019 + 1.0814836209962371 + 1.0815438853546937 + 1.0816041553279123 + 1.0816644309166299 + 1.0817247121215927 + 1.0817849989435444 + 1.0818452913832239 + 1.0819055894413736 + 1.0819658931187366 + 1.0820262024160583 + 1.0820865173340779 + 1.0821468378735368 + 1.0822071640351827 + 1.082267495819758 + 1.0823278332280022 + 1.0823881762606626 + 1.0824485249184821 + 1.0825088792022008 + 1.0825692391125659 + 1.0826296046503205 + 1.0826899758162079 + 1.082750352610973 + 1.0828107350353591 + 1.082871123090112 + 1.0829315167759777 + 1.0829919160936965 + 1.0830523210440146 + 1.0831127316276785 + 1.0831731478454312 + 1.0832335696980195 + 1.0832939971861899 + 1.0833544303106835 + 1.0834148690722489 + 1.0834753134716315 + 1.0835357635095768 + 1.0835962191868325 + 1.0836566805041403 + 1.0837171474622471 + 1.0837776200619049 + 1.083838098303854 + 1.0838985821888441 + 1.0839590717176195 + 1.0840195668909309 + 1.0840800677095208 + 1.0841405741741392 + 1.084201086285532 + 1.0842616040444464 + 1.0843221274516281 + 1.0843826565078305 + 1.0844431912137937 + 1.0845037315702721 + 1.0845642775780107 + 1.084624829237758 + 1.0846853865502608 + 1.0847459495162695 + 1.084806518136531 + 1.0848670924117965 + 1.0849276723428121 + 1.0849882579303247 + 1.0850488491750887 + 1.0851094460778481 + 1.0851700486393572 + 1.0852306568603607 + 1.0852912707416109 + 1.0853518902838568 + 1.0854125154878462 + 1.0854731463543312 + 1.0855337828840621 + 1.0855944250777887 + 1.0856550729362584 + 1.0857157264602246 + 1.0857763856504368 + 1.0858370505076489 + 1.0858977210326033 + 1.0859583972260607 + 1.0860190790887647 + 1.0860797666214732 + 1.0861404598249322 + 1.0862011586998934 + 1.0862618632471095 + 1.0863225734673323 + 1.0863832893613155 + 1.0864440109298079 + 1.0865047381735611 + 1.0865654710933317 + 1.0866262096898667 + 1.0866869539639226 + 1.0867477039162514 + 1.0868084595476026 + 1.0868692208587309 + 1.0869299878503911 + 1.0869907605233349 + 1.0870515388783131 + 1.0871123229160846 + 1.0871731126373982 + 1.0872339080430085 + 1.0872947091336707 + 1.0873555159101354 + 1.0874163283731604 + 1.0874771465234967 + 1.0875379703619021 + 1.0875987998891277 + 1.0876596351059287 + 1.0877204760130619 + 1.0877813226112782 + 1.0878421749013363 + 1.0879030328839892 + 1.0879638965599918 + 1.0880247659301028 + 1.0880856409950708 + 1.0881465217556581 + 1.0882074082126163 + 1.088268300366702 + 1.088329198218672 + 1.0883901017692843 + 1.0884510110192902 + 1.0885119259694498 + 1.0885728466205176 + 1.0886337729732516 + 1.0886947050284066 + 1.0887556427867404 + 1.0888165862490105 + 1.0888775354159748 + 1.088938490288389 + 1.0889994508670109 + 1.0890604171525988 + 1.0891213891459084 + 1.0891823668476981 + 1.089243350258726 + 1.0893043393797515 + 1.0893653342115297 + 1.0894263347548223 + 1.089487341010386 + 1.0895483529789767 + 1.0896093706613588 + 1.0896703940582861 + 1.0897314231705204 + 1.0897924579988192 + 1.0898534985439412 + 1.0899145448066483 + 1.0899755967876983 + 1.0900366544878506 + 1.0900977179078648 + 1.0901587870485012 + 1.0902198619105201 + 1.0902809424946782 + 1.0903420288017438 + 1.0904031208324676 + 1.0904642185876143 + 1.0905253220679474 + 1.0905864312742224 + 1.0906475462072049 + 1.0907086668676533 + 1.0907697932563287 + 1.0908309253739916 + 1.0908920632214041 + 1.0909532067993286 + 1.0910143561085279 + 1.0910755111497621 + 1.0911366719237909 + 1.091197838431381 + 1.0912590106732913 + 1.0913201886502839 + 1.0913813723631229 + 1.0914425618125705 + 1.0915037569993888 + 1.0915649579243425 + 1.0916261645881913 + 1.0916873769917028 + 1.0917485951356347 + 1.0918098190207517 + 1.091871048647822 + 1.0919322840176053 + 1.0919935251308648 + 1.092054771988366 + 1.0921160245908723 + 1.0921772829391492 + 1.0922385470339573 + 1.0922998168760654 + 1.0923610924662337 + 1.0924223738052321 + 1.0924836608938211 + 1.0925449537327667 + 1.0926062523228335 + 1.0926675566647901 + 1.0927288667593982 + 1.092790182607422 + 1.0928515042096307 + 1.0929128315667889 + 1.0929741646796611 + 1.0930355035490169 + 1.0930968481756185 + 1.0931581985602332 + 1.0932195547036287 + 1.0932809166065696 + 1.0933422842698206 + 1.0934036576941555 + 1.093465036880334 + 1.0935264218291292 + 1.0935878125413012 + 1.0936492090176237 + 1.0937106112588622 + 1.0937720192657825 + 1.0938334330391526 + 1.0938948525797416 + 1.0939562778883181 + 1.0940177089656482 + 1.094079145812503 + 1.0941405884296465 + 1.0942020368178531 + 1.0942634909778839 + 1.0943249509105133 + 1.0943864166165083 + 1.0944478880966382 + 1.0945093653516726 + 1.0945708483823811 + 1.0946323371895306 + 1.0946938317738917 + 1.094755332136236 + 1.0948168382773313 + 1.0948783501979478 + 1.094939867898856 + 1.0950013913808283 + 1.0950629206446301 + 1.0951244556910371 + 1.0951859965208155 + 1.0952475431347375 + 1.0953090955335747 + 1.0953706537180976 + 1.0954322176890798 + 1.0954937874472879 + 1.0955553629934975 + 1.0956169443284751 + 1.0956785314529975 + 1.095740124367836 + 1.0958017230737573 + 1.0958633275715404 + 1.0959249378619527 + 1.0959865539457705 + 1.096048175823761 + 1.0961098034966992 + 1.0961714369653621 + 1.0962330762305146 + 1.0962947212929341 + 1.0963563721533958 + 1.0964180288126697 + 1.0964796912715311 + 1.0965413595307505 + 1.0966030335911059 + 1.0966647134533671 + 1.0967263991183109 + 1.0967880905867076 + 1.0968497878593348 + 1.0969114909369675 + 1.0969731998203778 + 1.0970349145103402 + 1.097096635007631 + 1.0971583613130238 + 1.0972200934272949 + 1.0972818313512192 + 1.0973435750855696 + 1.0974053246311264 + 1.0974670799886586 + 1.0975288411589459 + 1.0975906081427649 + 1.0976523809408882 + 1.0977141595540936 + 1.0977759439831598 + 1.0978377342288599 + 1.0978995302919716 + 1.0979613321732702 + 1.0980231398735332 + 1.0980849533935384 + 1.098146772734059 + 1.0982085978958787 + 1.0982704288797696 + 1.0983322656865131 + 1.0983941083168827 + 1.0984559567716563 + 1.0985178110516136 + 1.0985796711575324 + 1.0986415370901916 + 1.0987034088503658 + 1.0987652864388382 + 1.0988271698563807 + 1.0988890591037808 + 1.098950954181809 + 1.0990128550912479 + 1.0990747618328773 + 1.0991366744074766 + 1.0991985928158206 + 1.0992605170586938 + 1.0993224471368739 + 1.0993843830511383 + 1.0994463248022703 + 1.0995082723910494 + 1.0995702258182536 + 1.0996321850846635 + 1.0996941501910624 + 1.0997561211382256 + 1.099818097926939 + 1.0998800805579807 + 1.0999420690321322 + 1.1000040633501715 + 1.1000660635128852 + 1.1001280695210518 + 1.100190081375453 + 1.1002520990768676 + 1.1003141226260849 + 1.1003761520238784 + 1.1004381872710336 + 1.1005002283683307 + 1.1005622753165558 + 1.1006243281164905 + 1.1006863867689143 + 1.1007484512746122 + 1.1008105216343638 + 1.1008725978489569 + 1.1009346799191715 + 1.1009967678457906 + 1.1010588616295993 + 1.1011209612713801 + 1.1011830667719167 + 1.1012451781319923 + 1.1013072953523919 + 1.1013694184338969 + 1.1014315473772955 + 1.1014936821833692 + 1.1015558228529012 + 1.1016179693866779 + 1.1016801217854855 + 1.1017422800501055 + 1.1018044441813273 + 1.1018666141799294 + 1.1019287900467043 + 1.1019909717824332 + 1.1020531593878988 + 1.1021153528638929 + 1.1021775522111996 + 1.102239757430602 + 1.1023019685228896 + 1.1023641854888451 + 1.1024264083292559 + 1.1024886370449096 + 1.1025508716365946 + 1.1026131121050906 + 1.1026753584511932 + 1.1027376106756837 + 1.1027998687793519 + 1.1028621327629817 + 1.1029244026273637 + 1.1029866783732842 + 1.1030489600015321 + 1.1031112475128928 + 1.1031735409081558 + 1.1032358401881099 + 1.1032981453535418 + 1.1033604564052399 + 1.1034227733439947 + 1.103485096170592 + 1.1035474248858217 + 1.1036097594904761 + 1.1036720999853369 + 1.1037344463711991 + 1.1037967986488502 + 1.1038591568190799 + 1.103921520882676 + 1.1039838908404309 + 1.1040462666931332 + 1.1041086484415747 + 1.1041710360865418 + 1.1042334296288272 + 1.1042958290692215 + 1.1043582344085137 + 1.1044206456474936 + 1.1044830627869584 + 1.1045454858276909 + 1.104607914770485 + 1.104670349616135 + 1.1047327903654292 + 1.1047952370191596 + 1.1048576895781179 + 1.1049201480430955 + 1.1049826124148845 + 1.1050450826942768 + 1.1051075588820669 + 1.1051700409790421 + 1.1052325289859999 + 1.1052950229037297 + 1.1053575227330268 + 1.1054200284746811 + 1.1054825401294881 + 1.1055450576982406 + 1.1056075811817312 + 1.1056701105807505 + 1.1057326458960968 + 1.1057951871285607 + 1.1058577342789377 + 1.1059202873480221 + 1.1059828463366068 + 1.1060454112454852 + 1.106107982075454 + 1.1061705588273076 + 1.1062331415018363 + 1.1062957300998395 + 1.106358324622112 + 1.1064209250694479 + 1.1064835314426407 + 1.1065461437424882 + 1.1066087619697824 + 1.1066713861253228 + 1.1067340162099046 + 1.106796652224322 + 1.1068592941693707 + 1.1069219420458503 + 1.1069845958545514 + 1.1070472555962743 + 1.1071099212718192 + 1.107172592881974 + 1.1072352704275423 + 1.1072979539093197 + 1.1073606433280996 + 1.1074233386846855 + 1.1074860399798705 + 1.1075487472144512 + 1.1076114603892289 + 1.1076741795049994 + 1.1077369045625627 + 1.1077996355627147 + 1.107862372506252 + 1.1079251153939769 + 1.1079878642266856 + 1.1080506190051786 + 1.1081133797302523 + 1.1081761464027067 + 1.1082389190233415 + 1.1083016975929543 + 1.1083644821123473 + 1.1084272725823161 + 1.1084900690036628 + 1.1085528713771886 + 1.1086156797036888 + 1.1086784939839684 + 1.1087413142188234 + 1.1088041404090572 + 1.1088669725554681 + 1.1089298106588572 + 1.1089926547200277 + 1.1090555047397761 + 1.1091183607189092 + 1.1091812226582198 + 1.1092440905585181 + 1.1093069644206 + 1.1093698442452702 + 1.1094327300333251 + 1.1094956217855745 + 1.1095585195028124 + 1.1096214231858468 + 1.1096843328354768 + 1.1097472484525053 + 1.1098101700377367 + 1.1098730975919717 + 1.1099360311160125 + 1.1099989706106645 + 1.1100619160767309 + 1.1101248675150122 + 1.1101878249263135 + 1.1102507883114361 + 1.1103137576711881 + 1.1103767330063703 + 1.1104397143177867 + 1.1105027016062403 + 1.110565694872538 + 1.1106286941174832 + 1.1106916993418803 + 1.1107547105465332 + 1.1108177277322457 + 1.1108807508998251 + 1.1109437800500783 + 1.1110068151838044 + 1.1110698563018135 + 1.1111329034049102 + 1.1111959564938991 + 1.111259015569585 + 1.1113220806327759 + 1.1113851516842792 + 1.1114482287248952 + 1.1115113117554369 + 1.111574400776707 + 1.1116374957895143 + 1.1117005967946607 + 1.1117637037929604 + 1.1118268167852143 + 1.1118899357722329 + 1.1119530607548205 + 1.1120161917337903 + 1.1120793287099411 + 1.11214247168409 + 1.1122056206570374 + 1.1122687756295964 + 1.1123319366025699 + 1.1123951035767703 + 1.1124582765530076 + 1.1125214555320853 + 1.1125846405148165 + 1.1126478315020081 + 1.1127110284944677 + 1.1127742314930051 + 1.1128374404984303 + 1.1129006555115539 + 1.1129638765331835 + 1.1130271035641297 + 1.1130903366052032 + 1.1131535756572113 + 1.1132168207209685 + 1.1132800717972797 + 1.1133433288869561 + 1.1134065919908116 + 1.1134698611096572 + 1.1135331362442991 + 1.113596417395551 + 1.1136597045642254 + 1.1137229977511303 + 1.1137862969570804 + 1.113849602182885 + 1.1139129134293562 + 1.113976230697306 + 1.1140395539875463 + 1.1141028833008897 + 1.1141662186381456 + 1.1142295600001322 + 1.1142929073876564 + 1.1143562608015318 + 1.1144196202425751 + 1.114482985711595 + 1.1145463572094041 + 1.1146097347368211 + 1.1146731182946537 + 1.1147365078837179 + 1.114799903504827 + 1.1148633051587951 + 1.1149267128464353 + 1.1149901265685616 + 1.1150535463259881 + 1.1151169721195309 + 1.1151804039500022 + 1.1152438418182204 + 1.115307285724993 + 1.115370735671144 + 1.1154341916574813 + 1.1154976536848258 + 1.1155611217539856 + 1.1156245958657829 + 1.1156880760210326 + 1.1157515622205447 + 1.115815054465142 + 1.1158785527556352 + 1.1159420570928464 + 1.1160055674775866 + 1.1160690839106742 + 1.1161326063929244 + 1.1161961349251559 + 1.116259669508187 + 1.1163232101428313 + 1.1163867568299077 + 1.1164503095702345 + 1.1165138683646261 + 1.1165774332139036 + 1.1166410041188837 + 1.1167045810803806 + 1.1167681640992189 + 1.1168317531762104 + 1.1168953483121797 + 1.1169589495079388 + 1.1170225567643124 + 1.1170861700821155 + 1.1171497894621685 + 1.1172134149052881 + 1.117277046412295 + 1.1173406839840099 + 1.1174043276212526 + 1.1174679773248388 + 1.117531633095592 + 1.1175952949343297 + 1.117658962841876 + 1.1177226368190438 + 1.1177863168666597 + 1.1178500029855418 + 1.1179136951765147 + 1.1179773934403916 + 1.1180410977779995 + 1.1181048081901568 + 1.118168524677686 + 1.1182322472414059 + 1.1182959758821416 + 1.1183597106007122 + 1.1184234513979396 + 1.1184871982746467 + 1.1185509512316554 + 1.1186147102697885 + 1.1186784753898662 + 1.1187422465927108 + 1.118806023879148 + 1.1188698072500007 + 1.1189335967060892 + 1.1189973922482366 + 1.119061193877267 + 1.1191250015940029 + 1.1191888153992704 + 1.1192526352938907 + 1.1193164612786881 + 1.1193802933544854 + 1.1194441315221098 + 1.1195079757823823 + 1.1195718261361276 + 1.1196356825841745 + 1.1196995451273426 + 1.1197634137664563 + 1.119827288502345 + 1.1198911693358289 + 1.1199550562677401 + 1.1200189492988932 + 1.1200828484301262 + 1.1201467536622536 + 1.120210664996109 + 1.1202745824325149 + 1.1203385059722988 + 1.1204024356162845 + 1.1204663713653027 + 1.1205303132201732 + 1.1205942611817303 + 1.1206582152507951 + 1.120722175428196 + 1.1207861417147615 + 1.120850114111321 + 1.1209140926186949 + 1.1209780772377163 + 1.1210420679692106 + 1.1211060648140079 + 1.1211700677729319 + 1.1212340768468154 + 1.1212980920364852 + 1.1213621133427685 + 1.1214261407664952 + 1.1214901743084924 + 1.1215542139695882 + 1.1216182597506152 + 1.1216823116524011 + 1.121746369675771 + 1.1218104338215613 + 1.1218745040905964 + 1.1219385804837083 + 1.1220026630017292 + 1.122066751645481 + 1.1221308464158042 + 1.1221949473135202 + 1.1222590543394626 + 1.1223231674944654 + 1.1223872867793554 + 1.122451412194964 + 1.1225155437421228 + 1.1225796814216613 + 1.1226438252344142 + 1.1227079751812132 + 1.1227721312628831 + 1.122836293480264 + 1.1229004618341829 + 1.1229646363254724 + 1.1230288169549649 + 1.1230930037234936 + 1.1231571966318914 + 1.1232213956809884 + 1.1232856008716203 + 1.1233498122046182 + 1.1234140296808146 + 1.1234782533010459 + 1.1235424830661431 + 1.1236067189769374 + 1.1236709610342674 + 1.1237352092389616 + 1.1237994635918576 + 1.1238637240937881 + 1.1239279907455906 + 1.1239922635480943 + 1.1240565425021365 + 1.124120827608551 + 1.1241851188681724 + 1.1242494162818364 + 1.1243137198503792 + 1.1243780295746315 + 1.124442345455436 + 1.1245066674936224 + 1.1245709956900261 + 1.1246353300454881 + 1.1246996705608381 + 1.1247640172369173 + 1.1248283700745618 + 1.124892729074604 + 1.1249570942378826 + 1.1250214655652346 + 1.1250858430574953 + 1.1251502267155038 + 1.1252146165400967 + 1.1252790125321128 + 1.1253434146923862 + 1.1254078230217566 + 1.1254722375210604 + 1.1255366581911375 + 1.1256010850328222 + 1.125665518046957 + 1.1257299572343764 + 1.1257944025959232 + 1.1258588541324321 + 1.1259233118447436 + 1.1259877757336978 + 1.1260522458001327 + 1.1261167220448836 + 1.1261812044687967 + 1.1262456930727094 + 1.1263101878574555 + 1.1263746888238835 + 1.126439195972827 + 1.1265037093051296 + 1.1265682288216299 + 1.1266327545231694 + 1.1266972864105875 + 1.1267618244847253 + 1.1268263687464226 + 1.1268909191965235 + 1.1269554758358646 + 1.1270200386652911 + 1.1270846076856424 + 1.1271491828977611 + 1.1272137643024864 + 1.1272783519006642 + 1.1273429456931314 + 1.1274075456807364 + 1.1274721518643169 + 1.1275367642447185 + 1.1276013828227813 + 1.1276660075993465 + 1.1277306385752626 + 1.1277952757513647 + 1.1278599191285048 + 1.1279245687075186 + 1.1279892244892549 + 1.1280538864745551 + 1.1281185546642658 + 1.128183229059224 + 1.1282479096602807 + 1.1283125964682783 + 1.1283772894840582 + 1.1284419887084685 + 1.1285066941423503 + 1.1285714057865539 + 1.1286361236419193 + 1.1287008477092939 + 1.1287655779895229 + 1.1288303144834517 + 1.1288950571919225 + 1.1289598061157871 + 1.1290245612558849 + 1.1290893226130696 + 1.1291540901881796 + 1.1292188639820653 + 1.1292836439955711 + 1.1293484302295476 + 1.1294132226848361 + 1.1294780213622859 + 1.1295428262627458 + 1.1296076373870623 + 1.1296724547360824 + 1.1297372783106527 + 1.1298021081116205 + 1.1298669441398348 + 1.1299317863961409 + 1.1299966348813908 + 1.1300614895964318 + 1.1301263505421122 + 1.1301912177192788 + 1.1302560911287822 + 1.1303209707714679 + 1.1303858566481912 + 1.1304507487597952 + 1.1305156471071309 + 1.1305805516910492 + 1.1306454625124005 + 1.1307103795720286 + 1.1307753028707901 + 1.1308402324095335 + 1.1309051681891047 + 1.1309701102103615 + 1.1310350584741466 + 1.1311000129813154 + 1.1311649737327194 + 1.1312299407292055 + 1.1312949139716282 + 1.1313598934608347 + 1.1314248791976802 + 1.131489871183017 + 1.1315548694176949 + 1.1316198739025618 + 1.1316848846384779 + 1.1317499016262891 + 1.1318149248668501 + 1.1318799543610123 + 1.1319449901096283 + 1.1320100321135518 + 1.1320750803736361 + 1.1321401348907327 + 1.1322051956656953 + 1.1322702626993795 + 1.1323353359926325 + 1.1324004155463154 + 1.1324655013612779 + 1.1325305934383738 + 1.1325956917784576 + 1.1326607963823867 + 1.1327259072510099 + 1.1327910243851853 + 1.1328561477857675 + 1.1329212774536088 + 1.1329864133895666 + 1.1330515555944969 + 1.1331167040692545 + 1.1331818588146922 + 1.133247019831666 + 1.1333121871210337 + 1.1333773606836537 + 1.1334425405203743 + 1.1335077266320568 + 1.1335729190195598 + 1.133638117683734 + 1.1337033226254418 + 1.1337685338455339 + 1.1338337513448717 + 1.1338989751243127 + 1.1339642051847107 + 1.1340294415269254 + 1.1340946841518109 + 1.1341599330602326 + 1.1342251882530399 + 1.1342904497310948 + 1.1343557174952581 + 1.1344209915463821 + 1.1344862718853295 + 1.1345515585129582 + 1.1346168514301236 + 1.1346821506376892 + 1.1347474561365125 + 1.1348127679274556 + 1.1348780860113703 + 1.1349434103891212 + 1.1350087410615697 + 1.1350740780295709 + 1.1351394212939878 + 1.1352047708556809 + 1.1352701267155068 + 1.135335488874333 + 1.1354008573330108 + 1.1354662320924096 + 1.1355316131533846 + 1.1355970005167975 + 1.1356623941835133 + 1.1357277941543873 + 1.1357932004302893 + 1.135858613012072 + 1.1359240319006028 + 1.1359894570967406 + 1.13605488860135 + 1.1361203264152924 + 1.1361857705394278 + 1.1362512209746229 + 1.1363166777217382 + 1.1363821407816377 + 1.1364476101551824 + 1.136513085843236 + 1.1365785678466629 + 1.1366440561663269 + 1.1367095508030902 + 1.1367750517578188 + 1.1368405590313699 + 1.1369060726246165 + 1.1369715925384194 + 1.1370371187736419 + 1.1371026513311484 + 1.137168190211804 + 1.1372337354164745 + 1.1372992869460241 + 1.1373648448013192 + 1.1374304089832217 + 1.1374959794926036 + 1.1375615563303214 + 1.1376271394972479 + 1.1376927289942478 + 1.137758324822185 + 1.1378239269819279 + 1.137889535474341 + 1.13795515030029 + 1.1380207714606447 + 1.1380863989562715 + 1.138152032788037 + 1.1382176729568059 + 1.1382833194634472 + 1.1383489723088287 + 1.1384146314938199 + 1.1384802970192827 + 1.1385459688860904 + 1.138611647095108 + 1.1386773316472076 + 1.1387430225432527 + 1.1388087197841161 + 1.1388744233706629 + 1.1389401333037648 + 1.1390058495842892 + 1.1390715722131051 + 1.1391373011910808 + 1.1392030365190899 + 1.1392687781979967 + 1.1393345262286769 + 1.1394002806119925 + 1.1394660413488225 + 1.1395318084400288 + 1.1395975818864856 + 1.1396633616890675 + 1.1397291478486369 + 1.1397949403660705 + 1.139860739242236 + 1.1399265444780082 + 1.1399923560742546 + 1.1400581740318483 + 1.1401239983516622 + 1.1401898290345662 + 1.1402556660814311 + 1.1403215094931332 + 1.140387359270542 + 1.1404532154145268 + 1.1405190779259637 + 1.140584946805729 + 1.1406508220546885 + 1.1407167036737185 + 1.1407825916636907 + 1.1408484860254822 + 1.1409143867599589 + 1.1409802938680031 + 1.1410462073504848 + 1.1411121272082752 + 1.1411780534422524 + 1.1412439860532879 + 1.1413099250422596 + 1.1413758704100379 + 1.1414418221575 + 1.1415077802855189 + 1.1415737447949721 + 1.1416397156867335 + 1.1417056929616756 + 1.14177167662068 + 1.1418376666646166 + 1.1419036630943644 + 1.1419696659107972 + 1.1420356751147935 + 1.1421016907072277 + 1.1421677126889755 + 1.1422337410609169 + 1.1422997758239255 + 1.142365816978878 + 1.1424318645266522 + 1.1424979184681272 + 1.1425639788041781 + 1.1426300455356815 + 1.1426961186635156 + 1.1427621981885625 + 1.1428282841116955 + 1.1428943764337915 + 1.1429604751557321 + 1.1430265802783943 + 1.1430926918026596 + 1.1431588097294032 + 1.143224934059504 + 1.1432910647938421 + 1.1433572019332952 + 1.1434233454787457 + 1.1434894954310708 + 1.1435556517911518 + 1.1436218145598649 + 1.1436879837380949 + 1.1437541593267186 + 1.1438203413266157 + 1.1438865297386704 + 1.1439527245637597 + 1.1440189258027669 + 1.1440851334565738 + 1.1441513475260554 + 1.1442175680121001 + 1.1442837949155822 + 1.1443500282373904 + 1.1444162679784027 + 1.1444825141394996 + 1.1445487667215672 + 1.1446150257254837 + 1.1446812911521327 + 1.144747563002398 + 1.1448138412771609 + 1.1448801259773049 + 1.144946417103712 + 1.1450127146572664 + 1.1450790186388495 + 1.1451453290493461 + 1.1452116458896402 + 1.1452779691606148 + 1.1453442988631535 + 1.1454106349981421 + 1.1454769775664606 + 1.1455433265689985 + 1.145609682006639 + 1.145676043880262 + 1.1457424121907587 + 1.1458087869390119 + 1.1458751681259045 + 1.1459415557523227 + 1.1460079498191549 + 1.146074350327285 + 1.1461407572775955 + 1.1462071706709793 + 1.1462735905083148 + 1.1463400167904927 + 1.1464064495183983 + 1.1464728886929181 + 1.1465393343149415 + 1.1466057863853505 + 1.1466722449050346 + 1.1467387098748811 + 1.1468051812957756 + 1.1468716591686101 + 1.1469381434942671 + 1.1470046342736371 + 1.1470711315076079 + 1.1471376351970652 + 1.1472041453429023 + 1.1472706619460047 + 1.1473371850072578 + 1.147403714527556 + 1.1474702505077825 + 1.1475367929488334 + 1.147603341851593 + 1.1476698972169526 + 1.147736459045799 + 1.147803027339023 + 1.1478696020975176 + 1.1479361833221722 + 1.1480027710138705 + 1.1480693651735103 + 1.1481359658019792 + 1.1482025729001695 + 1.1482691864689685 + 1.1483358065092715 + 1.1484024330219664 + 1.148469066007944 + 1.1485357054680967 + 1.1486023514033179 + 1.1486690038144989 + 1.1487356627025302 + 1.1488023280683057 + 1.1488689999127137 + 1.1489356782366504 + 1.1490023630410078 + 1.1490690543266768 + 1.1491357520945518 + 1.1492024563455279 + 1.1492691670804931 + 1.1493358843003454 + 1.1494026080059743 + 1.1494693381982795 + 1.1495360748781482 + 1.1496028180464755 + 1.1496695677041595 + 1.1497363238520952 + 1.1498030864911701 + 1.1498698556222826 + 1.1499366312463284 + 1.1500034133642034 + 1.1500702019768003 + 1.150136997085013 + 1.1502037986897404 + 1.150270606791876 + 1.1503374213923188 + 1.1504042424919598 + 1.1504710700916989 + 1.1505379041924269 + 1.1506047447950492 + 1.1506715919004546 + 1.1507384455095429 + 1.150805305623209 + 1.1508721722423523 + 1.1509390453678705 + 1.1510059250006561 + 1.1510728111416124 + 1.1511397037916342 + 1.1512066029516197 + 1.1512735086224668 + 1.151340420805071 + 1.1514073395003388 + 1.151474264709158 + 1.1515411964324354 + 1.1516081346710663 + 1.1516750794259476 + 1.1517420306979858 + 1.1518089884880722 + 1.1518759527971087 + 1.1519429236259944 + 1.1520099009756315 + 1.1520768848469196 + 1.1521438752407556 + 1.1522108721580415 + 1.1522778755996785 + 1.1523448855665681 + 1.152411902059608 + 1.152478925079699 + 1.1525459546277463 + 1.1526129907046476 + 1.1526800333113041 + 1.1527470824486163 + 1.1528141381174908 + 1.1528812003188249 + 1.1529482690535235 + 1.1530153443224846 + 1.1530824261266146 + 1.153149514466816 + 1.1532166093439866 + 1.1532837107590344 + 1.1533508187128607 + 1.153417933206367 + 1.1534850542404593 + 1.1535521818160417 + 1.1536193159340113 + 1.1536864565952785 + 1.1537536038007459 + 1.153820757551316 + 1.153887917847892 + 1.1539550846913822 + 1.1540222580826895 + 1.1540894380227171 + 1.1541566245123707 + 1.1542238175525543 + 1.154291017144176 + 1.1543582232881375 + 1.1544254359853476 + 1.1544926552367103 + 1.154559881043135 + 1.1546271134055204 + 1.154694352324779 + 1.154761597801812 + 1.1548288498375328 + 1.1548961084328426 + 1.1549633735886491 + 1.1550306453058596 + 1.1550979235853824 + 1.1551652084281248 + 1.1552324998349923 + 1.1552997978068928 + 1.1553671023447374 + 1.1554344134494312 + 1.1555017311218803 + 1.1555690553629958 + 1.1556363861736862 + 1.1557037235548633 + 1.1557710675074278 + 1.1558384180322938 + 1.1559057751303712 + 1.155973138802566 + 1.1560405090497901 + 1.1561078858729534 + 1.1561752692729628 + 1.1562426592507309 + 1.1563100558071642 + 1.1563774589431786 + 1.1564448686596818 + 1.1565122849575806 + 1.1565797078377913 + 1.1566471373012217 + 1.1567145733487847 + 1.1567820159813889 + 1.1568494651999501 + 1.156916921005374 + 1.1569843833985771 + 1.1570518523804678 + 1.1571193279519605 + 1.1571868101139664 + 1.1572542988673997 + 1.1573217942131695 + 1.1573892961521881 + 1.1574568046853746 + 1.1575243198136362 + 1.1575918415378881 + 1.1576593698590423 + 1.1577269047780139 + 1.1577944462957153 + 1.1578619944130626 + 1.1579295491309651 + 1.1579971104503441 + 1.1580646783721049 + 1.1581322528971683 + 1.1581998340264477 + 1.1582674217608595 + 1.1583350161013144 + 1.1584026170487312 + 1.1584702246040244 + 1.1585378387681071 + 1.1586054595418966 + 1.1586730869263093 + 1.1587407209222624 + 1.1588083615306684 + 1.1588760087524459 + 1.1589436625885101 + 1.1590113230397787 + 1.1590789901071692 + 1.1591466637915964 + 1.1592143440939786 + 1.1592820310152332 + 1.1593497245562758 + 1.1594174247180278 + 1.1594851315014014 + 1.1595528449073211 + 1.1596205649366995 + 1.1596882915904587 + 1.1597560248695113 + 1.1598237647747827 + 1.1598915113071881 + 1.1599592644676473 + 1.1600270242570798 + 1.1600947906764052 + 1.1601625637265396 + 1.1602303434084063 + 1.1602981297229218 + 1.1603659226710086 + 1.1604337222535874 + 1.1605015284715752 + 1.1605693413258955 + 1.1606371608174657 + 1.1607049869472092 + 1.1607728197160438 + 1.1608406591248959 + 1.160908505174681 + 1.1609763578663255 + 1.1610442172007454 + 1.1611120831788668 + 1.1611799558016096 + 1.1612478350698967 + 1.1613157209846481 + 1.1613836135467901 + 1.1614515127572431 + 1.1615194186169282 + 1.1615873311267706 + 1.1616552502876929 + 1.1617231761006173 + 1.1617911085664685 + 1.1618590476861674 + 1.1619269934606415 + 1.1619949458908141 + 1.1620629049776054 + 1.1621308707219415 + 1.1621988431247483 + 1.1622668221869488 + 1.1623348079094671 + 1.1624028002932321 + 1.1624707993391623 + 1.1625388050481895 + 1.1626068174212323 + 1.1626748364592232 + 1.1627428621630838 + 1.1628108945337383 + 1.162878933572117 + 1.1629469792791445 + 1.1630150316557453 + 1.1630830907028469 + 1.1631511564213775 + 1.1632192288122625 + 1.163287307876429 + 1.1633553936148031 + 1.1634234860283181 + 1.163491585117892 + 1.1635596908844581 + 1.1636278033289431 + 1.1636959224522778 + 1.1637640482553857 + 1.1638321807391965 + 1.1639003199046412 + 1.1639684657526463 + 1.1640366182841422 + 1.1641047775000544 + 1.1641729434013135 + 1.1642411159888513 + 1.1643092952635983 + 1.1643774812264787 + 1.1644456738784255 + 1.1645138732203684 + 1.1645820792532386 + 1.1646502919779662 + 1.1647185113954788 + 1.1647867375067105 + 1.1648549703125894 + 1.1649232098140487 + 1.1649914560120198 + 1.1650597089074315 + 1.1651279685012175 + 1.1651962347943094 + 1.1652645077876393 + 1.1653327874821353 + 1.1654010738787328 + 1.1654693669783662 + 1.1655376667819652 + 1.1656059732904618 + 1.1656742865047911 + 1.1657426064258853 + 1.165810933054678 + 1.1658792663921014 + 1.1659476064390879 + 1.1660159531965739 + 1.1660843066654925 + 1.1661526668467763 + 1.1662210337413621 + 1.1662894073501808 + 1.1663577876741711 + 1.1664261747142639 + 1.1664945684713963 + 1.166562968946502 + 1.1666313761405152 + 1.1666997900543759 + 1.1667682106890152 + 1.1668366380453707 + 1.1669050721243772 + 1.1669735129269692 + 1.1670419604540874 + 1.1671104147066664 + 1.1671788756856414 + 1.1672473433919479 + 1.1673158178265266 + 1.1673842989903105 + 1.1674527868842408 + 1.1675212815092531 + 1.1675897828662829 + 1.1676582909562725 + 1.1677268057801549 + 1.1677953273388717 + 1.1678638556333594 + 1.1679323906645547 + 1.1680009324334024 + 1.1680694809408343 + 1.1681380361877918 + 1.1682065981752154 + 1.1682751669040421 + 1.1683437423752121 + 1.1684123245896678 + 1.1684809135483416 + 1.1685495092521823 + 1.1686181117021244 + 1.1686867208991119 + 1.1687553368440802 + 1.168823959537975 + 1.1688925889817323 + 1.1689612251762964 + 1.1690298681226077 + 1.1690985178216058 + 1.169167174274234 + 1.1692358374814349 + 1.1693045074441473 + 1.1693731841633159 + 1.1694418676398797 + 1.169510557874784 + 1.1695792548689707 + 1.1696479586233828 + 1.1697166691389598 + 1.1697853864166472 + 1.1698541104573903 + 1.169922841262127 + 1.1699915788318056 + 1.1700603231673641 + 1.1701290742697541 + 1.1701978321399156 + 1.1702665967787929 + 1.1703353681873294 + 1.1704041463664718 + 1.1704729313171616 + 1.1705417230403448 + 1.1706105215369667 + 1.1706793268079734 + 1.1707481388543104 + 1.1708169576769214 + 1.1708857832767545 + 1.1709546156547541 + 1.1710234548118654 + 1.1710923007490335 + 1.1711611534672119 + 1.1712300129673379 + 1.1712988792503651 + 1.1713677523172337 + 1.1714366321688969 + 1.1715055188062995 + 1.1715744122303886 + 1.1716433124421139 + 1.1717122194424192 + 1.1717811332322559 + 1.1718500538125702 + 1.1719189811843096 + 1.1719879153484258 + 1.1720568563058658 + 1.1721258040575766 + 1.1721947586045085 + 1.1722637199476111 + 1.1723326880878344 + 1.1724016630261238 + 1.172470644763435 + 1.172539633300713 + 1.1726086286389081 + 1.1726776307789746 + 1.1727466397218573 + 1.1728156554685076 + 1.1728846780198823 + 1.1729537073769238 + 1.1730227435405869 + 1.173091786511826 + 1.1731608362915871 + 1.1732298928808247 + 1.1732989562804881 + 1.1733680264915325 + 1.1734371035149067 + 1.1735061873515633 + 1.1735752780024578 + 1.1736443754685397 + 1.173713479750762 + 1.1737825908500774 + 1.1738517087674416 + 1.1739208335038052 + 1.173989965060124 + 1.1740591034373458 + 1.1741282486364302 + 1.1741974006583302 + 1.1742665595039967 + 1.1743357251743898 + 1.1744048976704575 + 1.1744740769931565 + 1.1745432631434447 + 1.1746124561222728 + 1.1746816559306015 + 1.174750862569377 + 1.1748200760395622 + 1.1748892963421123 + 1.1749585234779791 + 1.1750277574481214 + 1.1750969982534938 + 1.1751662458950547 + 1.1752355003737625 + 1.175304761690567 + 1.1753740298464301 + 1.1754433048423076 + 1.1755125866791558 + 1.1755818753579355 + 1.1756511708795985 + 1.1757204732451094 + 1.1757897824554189 + 1.1758590985114923 + 1.1759284214142809 + 1.175997751164747 + 1.1760670877638482 + 1.1761364312125466 + 1.176205781511795 + 1.1762751386625556 + 1.1763445026657888 + 1.1764138735224505 + 1.1764832512335059 + 1.1765526357999108 + 1.1766220272226227 + 1.1766914255026093 + 1.1767608306408255 + 1.1768302426382298 + 1.1768996614957896 + 1.1769690872144605 + 1.1770385197952016 + 1.177107959238983 + 1.1771774055467588 + 1.1772468587194902 + 1.1773163187581406 + 1.1773857856636738 + 1.1774552594370506 + 1.177524740079233 + 1.1775942275911842 + 1.1776637219738637 + 1.1777332232282374 + 1.1778027313552664 + 1.1778722463559157 + 1.1779417682311468 + 1.1780112969819228 + 1.1780808326092096 + 1.1781503751139697 + 1.1782199244971683 + 1.1782894807597646 + 1.1783590439027281 + 1.1784286139270228 + 1.1784981908336116 + 1.1785677746234602 + 1.1786373652975344 + 1.1787069628567961 + 1.1787765673022128 + 1.1788461786347524 + 1.1789157968553772 + 1.1789854219650557 + 1.1790550539647504 + 1.1791246928554322 + 1.1791943386380643 + 1.1792639913136131 + 1.1793336508830465 + 1.1794033173473313 + 1.1794729907074359 + 1.1795426709643244 + 1.1796123581189659 + 1.1796820521723272 + 1.1797517531253805 + 1.1798214609790874 + 1.1798911757344202 + 1.1799608973923461 + 1.1800306259538327 + 1.18010036141985 + 1.1801701037913683 + 1.1802398530693528 + 1.1803096092547736 + 1.1803793723486022 + 1.1804491423518086 + 1.1805189192653591 + 1.1805887030902267 + 1.1806584938273783 + 1.1807282914777868 + 1.1807980960424245 + 1.1808679075222575 + 1.1809377259182601 + 1.1810075512314013 + 1.1810773834626511 + 1.1811472226129838 + 1.1812170686833692 + 1.1812869216747823 + 1.1813567815881876 + 1.1814266484245632 + 1.1814965221848794 + 1.1815664028701118 + 1.1816362904812252 + 1.181706185019201 + 1.1817760864850047 + 1.1818459948796149 + 1.1819159102040027 + 1.1819858324591415 + 1.1820557616460057 + 1.1821256977655692 + 1.1821956408188032 + 1.1822655908066875 + 1.1823355477301885 + 1.1824055115902863 + 1.1824754823879553 + 1.1825454601241705 + 1.1826154447999044 + 1.1826854364161343 + 1.182755434973833 + 1.1828254404739782 + 1.1828954529175486 + 1.1829654723055141 + 1.1830354986388534 + 1.1831055319185446 + 1.1831755721455619 + 1.1832456193208805 + 1.1833156734454831 + 1.18338573452034 + 1.1834558025464332 + 1.1835258775247339 + 1.1835959594562275 + 1.1836660483418882 + 1.1837361441826901 + 1.1838062469796182 + 1.1838763567336457 + 1.1839464734457543 + 1.1840165971169165 + 1.1840867277481186 + 1.1841568653403354 + 1.1842270098945478 + 1.1842971614117341 + 1.1843673198928724 + 1.1844374853389461 + 1.1845076577509317 + 1.1845778371298081 + 1.1846480234765591 + 1.1847182167921635 + 1.1847884170776009 + 1.1848586243338555 + 1.1849288385619043 + 1.1849990597627296 + 1.1850692879373133 + 1.1851395230866355 + 1.1852097652116789 + 1.1852800143134232 + 1.1853502703928545 + 1.1854205334509522 + 1.1854908034887006 + 1.1855610805070769 + 1.18563136450707 + 1.1857016554896584 + 1.185771953455828 + 1.1858422584065602 + 1.1859125703428417 + 1.1859828892656512 + 1.1860532151759728 + 1.1861235480747958 + 1.1861938879631004 + 1.1862642348418682 + 1.1863345887120911 + 1.1864049495747473 + 1.1864753174308238 + 1.1865456922813058 + 1.1866160741271783 + 1.1866864629694274 + 1.186756858809036 + 1.1868272616469919 + 1.1868976714842816 + 1.1869680883218905 + 1.1870385121608051 + 1.187108943002009 + 1.1871793808464937 + 1.1872498256952431 + 1.1873202775492415 + 1.1873907364094838 + 1.1874612022769508 + 1.1875316751526304 + 1.187602155037512 + 1.1876726419325858 + 1.1877431358388342 + 1.18781363675725 + 1.1878841446888209 + 1.1879546596345347 + 1.1880251815953793 + 1.1880957105723433 + 1.1881662465664173 + 1.188236789578593 + 1.1883073396098556 + 1.1883778966611969 + 1.1884484607336026 + 1.1885190318280701 + 1.1885896099455862 + 1.188660195087142 + 1.1887307872537223 + 1.1888013864463272 + 1.1888719926659406 + 1.1889426059135577 + 1.1890132261901663 + 1.1890838534967612 + 1.1891544878343301 + 1.1892251292038691 + 1.1892957776063686 + 1.1893664330428215 + 1.1894370955142188 + 1.1895077650215518 + 1.1895784415658159 + 1.189649125148003 + 1.1897198157691071 + 1.1897905134301221 + 1.1898612181320367 + 1.1899319298758488 + 1.1900026486625519 + 1.1900733744931413 + 1.1901441073686065 + 1.1902148472899445 + 1.1902855942581514 + 1.1903563482742214 + 1.1904271093391479 + 1.1904978774539257 + 1.1905686526195509 + 1.1906394348370193 + 1.1907102241073269 + 1.1907810204314695 + 1.1908518238104406 + 1.1909226342452393 + 1.1909934517368623 + 1.1910642762863028 + 1.1911351078945607 + 1.1912059465626303 + 1.1912767922915113 + 1.1913476450822005 + 1.1914185049356953 + 1.1914893718529906 + 1.1915602458350867 + 1.1916311268829836 + 1.191702014997674 + 1.1917729101801611 + 1.1918438124314408 + 1.1919147217525135 + 1.1919856381443779 + 1.1920565616080321 + 1.1921274921444753 + 1.1921984297547061 + 1.1922693744397264 + 1.192340326200537 + 1.1924112850381356 + 1.1924822509535233 + 1.1925532239476975 + 1.1926242040216628 + 1.1926951911764194 + 1.1927661854129643 + 1.1928371867323055 + 1.1929081951354379 + 1.1929792106233648 + 1.1930502331970887 + 1.1931212628576131 + 1.1931922996059368 + 1.1932633434430622 + 1.1933343943699937 + 1.1934054523877322 + 1.1934765174972821 + 1.1935475896996468 + 1.1936186689958257 + 1.1936897553868255 + 1.1937608488736486 + 1.1938319494572964 + 1.1939030571387768 + 1.1939741719190917 + 1.1940452937992465 + 1.1941164227802439 + 1.1941875588630915 + 1.1942587020487894 + 1.1943298523383463 + 1.1944010097327622 + 1.1944721742330513 + 1.1945433458402119 + 1.1946145245552526 + 1.1946857103791768 + 1.1947569033129939 + 1.1948281033577077 + 1.1948993105143255 + 1.194970524783856 + 1.1950417461673015 + 1.1951129746656717 + 1.1951842102799737 + 1.1952554530112123 + 1.1953267028603984 + 1.1953979598285387 + 1.195469223916642 + 1.1955404951257129 + 1.1956117734567655 + 1.1956830589108021 + 1.1957543514888342 + 1.1958256511918708 + 1.1958969580209224 + 1.1959682719769931 + 1.1960395930610968 + 1.1961109212742405 + 1.196182256617438 + 1.196253599091694 + 1.196324948698021 + 1.1963963054374303 + 1.1964676693109302 + 1.1965390403195324 + 1.1966104184642476 + 1.1966818037460885 + 1.1967531961660658 + 1.1968245957251868 + 1.1968960024244677 + 1.1969674162649195 + 1.1970388372475531 + 1.1971102653733823 + 1.1971817006434153 + 1.1972531430586693 + 1.1973245926201528 + 1.1973960493288829 + 1.1974675131858714 + 1.1975389841921302 + 1.1976104623486719 + 1.1976819476565128 + 1.1977534401166665 + 1.1978249397301448 + 1.1978964464979636 + 1.1979679604211375 + 1.1980394815006803 + 1.1981110097376071 + 1.1981825451329313 + 1.1982540876876715 + 1.1983256374028359 + 1.1983971942794489 + 1.1984687583185218 + 1.1985403295210681 + 1.1986119078881099 + 1.1986834934206563 + 1.198755086119732 + 1.1988266859863466 + 1.1988982930215168 + 1.1989699072262656 + 1.1990415286016052 + 1.1991131571485536 + 1.199184792868131 + 1.1992564357613502 + 1.1993280858292346 + 1.1993997430728001 + 1.1994714074930644 + 1.199543079091044 + 1.1996147578677625 + 1.1996864438242338 + 1.1997581369614796 + 1.1998298372805185 + 1.1999015447823727 + 1.1999732594680563 + 1.2000449813385918 + 1.2001167103950012 + 1.200188446638299 + 1.2002601900695136 + 1.2003319406896564 + 1.2004036984997566 + 1.2004754635008308 + 1.2005472356938975 + 1.2006190150799858 + 1.2006908016601103 + 1.2007625954352925 + 1.2008343964065586 + 1.2009062045749277 + 1.2009780199414257 + 1.201049842507067 + 1.2011216722728837 + 1.2011935092398915 + 1.201265353409116 + 1.2013372047815818 + 1.201409063358311 + 1.201480929140323 + 1.2015528021286486 + 1.2016246823243053 + 1.2016965697283242 + 1.201768464341725 + 1.2018403661655308 + 1.2019122752007705 + 1.2019841914484648 + 1.2020561149096425 + 1.2021280455853249 + 1.2021999834765407 + 1.202271928584314 + 1.2023438809096714 + 1.2024158404536349 + 1.2024878072172367 + 1.2025597812015012 + 1.2026317624074532 + 1.2027037508361202 + 1.2027757464885276 + 1.2028477493657048 + 1.2029197594686805 + 1.2029917767984797 + 1.2030638013561286 + 1.2031358331426576 + 1.2032078721590953 + 1.2032799184064678 + 1.2033519718858039 + 1.203424032598132 + 1.203496100544482 + 1.2035681757258854 + 1.2036402581433634 + 1.2037123477979532 + 1.20378444469068 + 1.2038565488225759 + 1.2039286601946704 + 1.2040007788079914 + 1.2040729046635741 + 1.2041450377624436 + 1.2042171781056334 + 1.2042893256941738 + 1.2043614805290932 + 1.2044336426114275 + 1.2045058119422054 + 1.2045779885224608 + 1.2046501723532246 + 1.2047223634355264 + 1.2047945617704001 + 1.20486676735888 + 1.2049389802019956 + 1.2050112003007791 + 1.2050834276562676 + 1.2051556622694943 + 1.2052279041414855 + 1.2053001532732794 + 1.2053724096659124 + 1.2054446733204163 + 1.205516944237822 + 1.2055892224191682 + 1.2056615078654878 + 1.205733800577812 + 1.2058061005571798 + 1.2058784078046281 + 1.2059507223211874 + 1.206023044107895 + 1.2060953731657877 + 1.2061677094958998 + 1.2062400530992685 + 1.2063124039769288 + 1.2063847621299151 + 1.2064571275592681 + 1.2065295002660228 + 1.2066018802512168 + 1.2066742675158864 + 1.2067466620610685 + 1.2068190638878027 + 1.2068914729971245 + 1.2069638893900692 + 1.2070363130676849 + 1.2071087440309987 + 1.2071811822810528 + 1.2072536278188917 + 1.2073260806455441 + 1.2073985407620555 + 1.2074710081694648 + 1.2075434828688121 + 1.2076159648611344 + 1.2076884541474726 + 1.207760950728866 + 1.207833454606356 + 1.2079059657809823 + 1.207978484253786 + 1.2080510100258048 + 1.2081235430980861 + 1.2081960834716672 + 1.2082686311475872 + 1.2083411861268933 + 1.2084137484106212 + 1.2084863179998175 + 1.2085588948955197 + 1.2086314790987778 + 1.2087040706106251 + 1.2087766694321096 + 1.2088492755642741 + 1.2089218890081608 + 1.2089945097648127 + 1.2090671378352722 + 1.209139773220586 + 1.2092124159217936 + 1.2092850659399441 + 1.2093577232760782 + 1.209430387931242 + 1.2095030599064798 + 1.2095757392028352 + 1.2096484258213549 + 1.2097211197630831 + 1.2097938210290666 + 1.2098665296203479 + 1.209939245537976 + 1.2100119687829942 + 1.210084699356452 + 1.210157437259392 + 1.2102301824928645 + 1.2103029350579126 + 1.2103756949555844 + 1.2104484621869307 + 1.2105212367529918 + 1.2105940186548199 + 1.210666807893463 + 1.2107396044699674 + 1.2108124083853826 + 1.2108852196407549 + 1.2109580382371361 + 1.2110308641755678 + 1.2111036974571081 + 1.2111765380827983 + 1.2112493860536941 + 1.21132224137084 + 1.2113951040352888 + 1.2114679740480856 + 1.2115408514102868 + 1.2116137361229402 + 1.2116866281870962 + 1.2117595276038007 + 1.2118324343741098 + 1.2119053484990785 + 1.2119782699797468 + 1.212051198817174 + 1.2121241350124126 + 1.2121970785665086 + 1.2122700294805169 + 1.2123429877554923 + 1.2124159533924816 + 1.2124889263925429 + 1.2125619067567233 + 1.2126348944860807 + 1.2127078895816659 + 1.2127808920445342 + 1.2128539018757363 + 1.2129269190763248 + 1.2129999436473597 + 1.2130729755898917 + 1.2131460149049713 + 1.2132190615936584 + 1.2132921156570071 + 1.2133651770960712 + 1.2134382459119026 + 1.2135113221055609 + 1.2135844056781016 + 1.2136574966305762 + 1.2137305949640476 + 1.2138037006795637 + 1.2138768137781841 + 1.2139499342609703 + 1.214023062128972 + 1.2140961973832483 + 1.214169340024857 + 1.2142424900548519 + 1.2143156474742969 + 1.2143888122842457 + 1.2144619844857552 + 1.2145351640798838 + 1.2146083510676919 + 1.2146815454502358 + 1.2147547472285756 + 1.2148279564037709 + 1.2149011729768766 + 1.2149743969489524 + 1.2150476283210621 + 1.2151208670942628 + 1.2151941132696154 + 1.2152673668481782 + 1.2153406278310117 + 1.2154138962191772 + 1.2154871720137306 + 1.2155604552157413 + 1.2156337458262627 + 1.2157070438463593 + 1.2157803492770927 + 1.2158536621195251 + 1.215926982374713 + 1.2160003100437269 + 1.2160736451276186 + 1.2161469876274584 + 1.216220337544309 + 1.2162936948792287 + 1.2163670596332792 + 1.2164404318075301 + 1.2165138114030385 + 1.2165871984208745 + 1.216660592862095 + 1.2167339947277671 + 1.2168074040189547 + 1.2168808207367243 + 1.2169542448821351 + 1.2170276764562562 + 1.2171011154601503 + 1.2171745618948842 + 1.2172480157615202 + 1.217321477061128 + 1.2173949457947684 + 1.2174684219635141 + 1.2175419055684225 + 1.2176153966105676 + 1.2176888950910116 + 1.2177624010108214 + 1.2178359143710646 + 1.2179094351728084 + 1.2179829634171209 + 1.2180564991050662 + 1.2181300422377168 + 1.2182035928161363 + 1.218277150841397 + 1.2183507163145628 + 1.2184242892367048 + 1.2184978696088891 + 1.2185714574321869 + 1.2186450527076651 + 1.2187186554363971 + 1.2187922656194485 + 1.21886588325789 + 1.2189395083527899 + 1.2190131409052214 + 1.2190867809162533 + 1.2191604283869577 + 1.2192340833184001 + 1.2193077457116552 + 1.2193814155677918 + 1.2194550928878878 + 1.2195287776730042 + 1.2196024699242214 + 1.2196761696426042 + 1.2197498768292327 + 1.2198235914851692 + 1.2198973136114948 + 1.2199710432092794 + 1.2200447802795944 + 1.2201185248235122 + 1.220192276842107 + 1.2202660363364517 + 1.2203398033076238 + 1.2204135777566911 + 1.2204873596847339 + 1.2205611490928203 + 1.2206349459820276 + 1.2207087503534306 + 1.2207825622081039 + 1.2208563815471223 + 1.2209302083715583 + 1.2210040426824957 + 1.2210778844810004 + 1.2211517337681514 + 1.2212255905450271 + 1.2212994548127034 + 1.2213733265722502 + 1.2214472058247523 + 1.2215210925712856 + 1.2215949868129212 + 1.2216688885507414 + 1.221742797785822 + 1.2218167145192407 + 1.2218906387520772 + 1.221964570485405 + 1.2220385097203053 + 1.2221124564578574 + 1.2221864106991365 + 1.2222603724452232 + 1.2223343416972008 + 1.2224083184561392 + 1.2224823027231271 + 1.2225562944992376 + 1.2226302937855551 + 1.2227043005831553 + 1.2227783148931224 + 1.2228523367165323 + 1.22292636605447 + 1.2230004029080148 + 1.2230744472782458 + 1.2231484991662454 + 1.2232225585730963 + 1.2232966254998783 + 1.2233706999476766 + 1.2234447819175687 + 1.223518871410638 + 1.2235929684279698 + 1.2236670729706429 + 1.2237411850397428 + 1.2238153046363509 + 1.2238894317615532 + 1.223963566416429 + 1.224037708602062 + 1.2241118583195387 + 1.2241860155699442 + 1.2242601803543605 + 1.224334352673869 + 1.2244085325295604 + 1.224482719922517 + 1.2245569148538209 + 1.2246311173245603 + 1.2247053273358239 + 1.2247795448886891 + 1.2248537699842492 + 1.224928002623588 + 1.2250022428077891 + 1.2250764905379408 + 1.2251507458151296 + 1.2252250086404426 + 1.2252992790149693 + 1.2253735569397928 + 1.2254478424160014 + 1.2255221354446839 + 1.2255964360269289 + 1.2256707441638226 + 1.225745059856453 + 1.2258193831059112 + 1.2258937139132846 + 1.2259680522796588 + 1.2260423982061273 + 1.2261167516937788 + 1.2261911127437015 + 1.2262654813569844 + 1.226339857534716 + 1.2264142412779941 + 1.2264886325878994 + 1.2265630314655291 + 1.2266374379119678 + 1.2267118519283124 + 1.2267862735156512 + 1.2268607026750786 + 1.2269351394076795 + 1.2270095837145498 + 1.2270840355967829 + 1.2271584950554657 + 1.227232962091698 + 1.2273074367065646 + 1.2273819189011623 + 1.2274564086765853 + 1.2275309060339237 + 1.2276054109742731 + 1.2276799234987248 + 1.2277544436083754 + 1.2278289713043145 + 1.2279035065876402 + 1.2279780494594468 + 1.2280525999208265 + 1.2281271579728723 + 1.2282017236166853 + 1.2282762968533578 + 1.2283508776839835 + 1.2284254661096576 + 1.2285000621314797 + 1.228574665750545 + 1.2286492769679453 + 1.2287238957847819 + 1.2287985222021494 + 1.2288731562211415 + 1.2289477978428633 + 1.2290224470684039 + 1.2290971038988634 + 1.229171768335342 + 1.2292464403789316 + 1.2293211200307357 + 1.2293958072918518 + 1.2294705021633785 + 1.2295452046464113 + 1.2296199147420506 + 1.2296946324513987 + 1.2297693577755504 + 1.2298440907156056 + 1.2299188312726654 + 1.2299935794478321 + 1.2300683352422019 + 1.2301430986568742 + 1.230217869692952 + 1.2302926483515373 + 1.2303674346337299 + 1.2304422285406278 + 1.2305170300733357 + 1.2305918392329549 + 1.2306666560205857 + 1.2307414804373289 + 1.230816312484293 + 1.2308911521625714 + 1.2309659994732733 + 1.2310408544174978 + 1.2311157169963507 + 1.2311905872109319 + 1.2312654650623485 + 1.2313403505516995 + 1.2314152436800925 + 1.2314901444486326 + 1.2315650528584194 + 1.2316399689105582 + 1.2317148926061547 + 1.231789823946317 + 1.2318647629321458 + 1.2319397095647464 + 1.2320146638452252 + 1.2320896257746889 + 1.2321645953542433 + 1.2322395725849924 + 1.232314557468043 + 1.2323895500045048 + 1.2324645501954792 + 1.2325395580420759 + 1.2326145735454028 + 1.2326895967065672 + 1.2327646275266733 + 1.2328396660068301 + 1.2329147121481479 + 1.2329897659517344 + 1.2330648274186953 + 1.2331398965501423 + 1.2332149733471831 + 1.233290057810922 + 1.2333651499424754 + 1.2334402497429497 + 1.2335153572134516 + 1.2335904723550961 + 1.2336655951689899 + 1.2337407256562452 + 1.2338158638179693 + 1.2338910096552744 + 1.2339661631692693 + 1.2340413243610713 + 1.2341164932317854 + 1.2341916697825259 + 1.2342668540144028 + 1.2343420459285301 + 1.2344172455260158 + 1.2344924528079777 + 1.2345676677755233 + 1.2346428904297702 + 1.2347181207718243 + 1.2347933588028064 + 1.2348686045238253 + 1.2349438579359959 + 1.2350191190404309 + 1.2350943878382428 + 1.2351696643305521 + 1.2352449485184638 + 1.2353202404031021 + 1.2353955399855765 + 1.2354708472669982 + 1.2355461622484922 + 1.2356214849311655 + 1.2356968153161352 + 1.2357721534045241 + 1.2358474991974369 + 1.2359228526959964 + 1.2359982139013204 + 1.2360735828145228 + 1.2361489594367214 + 1.2362243437690312 + 1.2362997358125725 + 1.2363751355684607 + 1.2364505430378134 + 1.2365259582217498 + 1.2366013811213874 + 1.2366768117378457 + 1.2367522500722399 + 1.2368276961256919 + 1.2369031498993206 + 1.2369786113942431 + 1.2370540806115806 + 1.2371295575524508 + 1.2372050422179757 + 1.2372805346092726 + 1.2373560347274639 + 1.2374315425736702 + 1.2375070581490089 + 1.2375825814546058 + 1.2376581124915762 + 1.2377336512610466 + 1.2378091977641377 + 1.2378847520019678 + 1.2379603139756612 + 1.2380358836863421 + 1.2381114611351265 + 1.2381870463231417 + 1.2382626392515097 + 1.2383382399213525 + 1.2384138483337948 + 1.2384894644899593 + 1.2385650883909685 + 1.2386407200379452 + 1.2387163594320176 + 1.2387920065743063 + 1.2388676614659371 + 1.238943324108033 + 1.2390189945017207 + 1.2390946726481267 + 1.2391703585483713 + 1.2392460522035851 + 1.2393217536148886 + 1.239397462783415 + 1.2394731797102829 + 1.2395489043966199 + 1.2396246368435586 + 1.2397003770522192 + 1.2397761250237285 + 1.2398518807592185 + 1.2399276442598135 + 1.2400034155266428 + 1.2400791945608318 + 1.2401549813635084 + 1.2402307759358029 + 1.2403065782788456 + 1.2403823883937584 + 1.2404582062816758 + 1.2405340319437268 + 1.240609865381036 + 1.2406857065947388 + 1.240761555585959 + 1.2408374123558301 + 1.2409132769054823 + 1.2409891492360461 + 1.2410650293486483 + 1.2411409172444239 + 1.2412168129245027 + 1.2412927163900165 + 1.2413686276420957 + 1.2414445466818698 + 1.2415204735104755 + 1.2415964081290387 + 1.2416723505386971 + 1.2417483007405827 + 1.241824258735825 + 1.2419002245255562 + 1.2419761981109143 + 1.2420521794930297 + 1.2421281686730341 + 1.2422041656520644 + 1.2422801704312536 + 1.2423561830117344 + 1.2424322033946436 + 1.242508231581114 + 1.2425842675722809 + 1.2426603113692793 + 1.2427363629732449 + 1.2428124223853108 + 1.2428884896066148 + 1.2429645646382943 + 1.2430406474814808 + 1.2431167381373149 + 1.2431928366069323 + 1.2432689428914674 + 1.2433450569920592 + 1.2434211789098426 + 1.2434973086459562 + 1.2435734462015418 + 1.2436495915777295 + 1.2437257447756611 + 1.2438019057964762 + 1.2438780746413134 + 1.2439542513113073 + 1.2440304358075971 + 1.2441066281313282 + 1.2441828282836325 + 1.2442590362656525 + 1.2443352520785289 + 1.2444114757234015 + 1.2444877072014089 + 1.2445639465136911 + 1.2446401936613896 + 1.2447164486456452 + 1.2447927114675996 + 1.244868982128396 + 1.2449452606291687 + 1.2450215469710675 + 1.2450978411552283 + 1.2451741431827932 + 1.2452504530549078 + 1.2453267707727167 + 1.2454030963373544 + 1.2454794297499721 + 1.2455557710117091 + 1.2456321201237091 + 1.2457084770871152 + 1.2457848419030733 + 1.2458612145727221 + 1.2459375950972127 + 1.2460139834776864 + 1.2460903797152876 + 1.2461667838111601 + 1.2462431957664508 + 1.2463196155823046 + 1.2463960432598664 + 1.246472478800283 + 1.2465489222046975 + 1.2466253734742629 + 1.246701832610116 + 1.2467782996134109 + 1.2468547744852903 + 1.2469312572269027 + 1.2470077478393973 + 1.2470842463239198 + 1.2471607526816137 + 1.2472372669136338 + 1.2473137890211241 + 1.2473903190052342 + 1.2474668568671108 + 1.2475434026079069 + 1.2476199562287664 + 1.247696517730843 + 1.2477730871152837 + 1.2478496643832364 + 1.2479262495358545 + 1.2480028425742868 + 1.2480794434996836 + 1.2481560523131932 + 1.2482326690159673 + 1.2483092936091604 + 1.2483859260939181 + 1.2484625664713951 + 1.2485392147427437 + 1.2486158709091133 + 1.248692534971656 + 1.2487692069315242 + 1.2488458867898735 + 1.2489225745478545 + 1.2489992702066164 + 1.2490759737673158 + 1.2491526852311086 + 1.2492294045991426 + 1.2493061318725747 + 1.249382867052558 + 1.2494596101402498 + 1.2495363611367984 + 1.2496131200433636 + 1.2496898868611002 + 1.2497666615911571 + 1.2498434442346948 + 1.2499202347928706 + 1.2499970332668346 + 1.2500738396577473 + 1.2501506539667646 + 1.2502274761950383 + 1.2503043063437282 + 1.2503811444139923 + 1.2504579904069846 + 1.2505348443238631 + 1.250611706165788 + 1.2506885759339152 + 1.2507654536294017 + 1.2508423392534076 + 1.2509192328070868 + 1.2509961342916023 + 1.2510730437081115 + 1.2511499610577721 + 1.2512268863417444 + 1.251303819561189 + 1.2513807607172647 + 1.2514577098111288 + 1.251534666843946 + 1.2516116318168748 + 1.2516886047310709 + 1.2517655855877046 + 1.2518425743879293 + 1.251919571132907 + 1.2519965758237996 + 1.2520735884617704 + 1.2521506090479808 + 1.2522276375835886 + 1.2523046740697619 + 1.2523817185076644 + 1.2524587708984527 + 1.252535831243291 + 1.2526128995433452 + 1.2526899757997763 + 1.2527670600137508 + 1.2528441521864275 + 1.2529212523189759 + 1.2529983604125579 + 1.2530754764683372 + 1.2531526004874765 + 1.2532297324711459 + 1.2533068724205074 + 1.2533840203367268 + 1.2534611762209693 + 1.2535383400743998 + 1.2536155118981873 + 1.253692691693495 + 1.2537698794614915 + 1.2538470752033424 + 1.2539242789202121 + 1.2540014906132728 + 1.2540787102836874 + 1.2541559379326264 + 1.2542331735612566 + 1.2543104171707451 + 1.2543876687622617 + 1.2544649283369718 + 1.2545421958960485 + 1.2546194714406567 + 1.2546967549719665 + 1.2547740464911501 + 1.2548513459993726 + 1.2549286534978077 + 1.2550059689876218 + 1.2550832924699866 + 1.2551606239460731 + 1.2552379634170514 + 1.2553153108840933 + 1.2553926663483683 + 1.2554700298110486 + 1.2555474012733043 + 1.2556247807363081 + 1.2557021682012337 + 1.2557795636692533 + 1.2558569671415349 + 1.2559343786192549 + 1.2560117981035868 + 1.2560892255956992 + 1.2561666610967679 + 1.2562441046079682 + 1.2563215561304741 + 1.256399015665457 + 1.2564764832140918 + 1.2565539587775498 + 1.2566314423570129 + 1.2567089339536497 + 1.2567864335686387 + 1.2568639412031521 + 1.256941456858369 + 1.2570189805354648 + 1.2570965122356101 + 1.2571740519599892 + 1.2572515997097706 + 1.2573291554861357 + 1.2574067192902618 + 1.2574842911233255 + 1.2575618709865009 + 1.2576394588809676 + 1.2577170548079009 + 1.2577946587684861 + 1.2578722707638927 + 1.2579498907953044 + 1.2580275188639016 + 1.2581051549708542 + 1.2581827991173524 + 1.2582604513045652 + 1.2583381115336802 + 1.2584157798058735 + 1.2584934561223242 + 1.2585711404842166 + 1.2586488328927252 + 1.2587265333490347 + 1.2588042418543246 + 1.2588819584097783 + 1.258959683016575 + 1.2590374156758954 + 1.2591151563889225 + 1.25919290515684 + 1.2592706619808252 + 1.2593484268620647 + 1.25942619980174 + 1.2595039808010378 + 1.2595817698611305 + 1.259659566983214 + 1.2597373721684646 + 1.2598151854180675 + 1.2598930067332061 + 1.2599708361150641 + 1.2600486735648286 + 1.2601265190836857 + 1.2602043726728143 + 1.2602822343334039 + 1.2603601040666401 + 1.2604379818737057 + 1.2605158677557875 + 1.2605937617140719 + 1.2606716637497475 + 1.2607495738639933 + 1.2608274920580049 + 1.260905418332966 + 1.2609833526900638 + 1.2610612951304829 + 1.2611392456554142 + 1.2612172042660452 + 1.2612951709635605 + 1.2613731457491517 + 1.2614511286240095 + 1.2615291195893197 + 1.2616071186462681 + 1.2616851257960486 + 1.2617631410398509 + 1.2618411643788607 + 1.2619191958142704 + 1.2619972353472693 + 1.26207528297905 + 1.2621533387107993 + 1.2622314025437102 + 1.2623094744789727 + 1.2623875545177825 + 1.2624656426613217 + 1.2625437389107925 + 1.2626218432673804 + 1.2626999557322749 + 1.2627780763066747 + 1.2628562049917724 + 1.2629343417887575 + 1.2630124866988219 + 1.263090639723162 + 1.2631688008629707 + 1.2632469701194402 + 1.263325147493765 + 1.2634033329871408 + 1.2634815266007604 + 1.2635597283358195 + 1.2636379381935108 + 1.2637161561750336 + 1.263794382281578 + 1.2638726165143435 + 1.2639508588745234 + 1.2640291093633123 + 1.2641073679819121 + 1.2641856347315146 + 1.264263909613319 + 1.2643421926285183 + 1.2644204837783148 + 1.2644987830639012 + 1.2645770904864777 + 1.2646554060472426 + 1.2647337297473913 + 1.2648120615881251 + 1.2648904015706397 + 1.2649687496961339 + 1.2650471059658119 + 1.265125470380865 + 1.2652038429424977 + 1.2652822236519072 + 1.265360612510295 + 1.2654390095188612 + 1.2655174146788062 + 1.2655958279913271 + 1.2656742494576296 + 1.2657526790789118 + 1.2658311168563767 + 1.2659095627912227 + 1.2659880168846538 + 1.2660664791378731 + 1.2661449495520798 + 1.2662234281284781 + 1.2663019148682695 + 1.2663804097726592 + 1.2664589128428461 + 1.2665374240800378 + 1.2666159434854343 + 1.266694471060243 + 1.2667730068056646 + 1.2668515507229021 + 1.2669301028131639 + 1.2670086630776556 + 1.2670872315175785 + 1.2671658081341357 + 1.2672443929285371 + 1.2673229859019861 + 1.2674015870556925 + 1.2674801963908551 + 1.2675588139086844 + 1.2676374396103898 + 1.2677160734971713 + 1.2677947155702416 + 1.2678733658308035 + 1.2679520242800679 + 1.2680306909192405 + 1.2681093657495293 + 1.2681880487721426 + 1.2682667399882903 + 1.268345439399178 + 1.2684241470060178 + 1.2685028628100159 + 1.2685815868123826 + 1.2686603190143266 + 1.2687390594170587 + 1.2688178080217911 + 1.2688965648297286 + 1.2689753298420847 + 1.2690541030600695 + 1.2691328844848966 + 1.2692116741177717 + 1.2692904719599112 + 1.2693692780125234 + 1.2694480922768201 + 1.2695269147540154 + 1.2696057454453216 + 1.26968458435195 + 1.2697634314751105 + 1.2698422868160235 + 1.2699211503758929 + 1.27000002215594 + 1.2700789021573751 + 1.270157790381411 + 1.2702366868292634 + 1.2703155915021487 + 1.2703945044012745 + 1.270473425527864 + 1.270552354883127 + 1.2706312924682783 + 1.2707102382845374 + 1.2707891923331187 + 1.2708681546152345 + 1.2709471251321074 + 1.2710261038849469 + 1.2711050908749737 + 1.2711840861034034 + 1.2712630895714565 + 1.2713421012803461 + 1.271421121231288 + 1.2715001494255067 + 1.2715791858642156 + 1.2716582305486364 + 1.2717372834799832 + 1.2718163446594748 + 1.2718954140883343 + 1.2719744917677784 + 1.2720535776990276 + 1.2721326718833017 + 1.272211774321818 + 1.2722908850157977 + 1.2723700039664643 + 1.2724491311750381 + 1.2725282666427316 + 1.2726074103707756 + 1.2726865623603909 + 1.2727657226127931 + 1.2728448911292072 + 1.2729240679108553 + 1.2730032529589566 + 1.2730824462747388 + 1.2731616478594214 + 1.2732408577142309 + 1.2733200758403866 + 1.273399302239111 + 1.2734785369116284 + 1.2735577798591671 + 1.273637031082945 + 1.2737162905841914 + 1.2737955583641283 + 1.2738748344239812 + 1.2739541187649757 + 1.274033411388338 + 1.2741127122952902 + 1.2741920214870601 + 1.2742713389648725 + 1.2743506647299554 + 1.2744299987835341 + 1.2745093411268369 + 1.2745886917610894 + 1.2746680506875174 + 1.2747474179073499 + 1.274826793421816 + 1.2749061772321388 + 1.2749855693395538 + 1.2750649697452821 + 1.275144378450553 + 1.2752237954566024 + 1.2753032207646515 + 1.2753826543759337 + 1.2754620962916765 + 1.2755415465131077 + 1.2756210050414643 + 1.2757004718779705 + 1.2757799470238582 + 1.2758594304803588 + 1.2759389222487005 + 1.2760184223301179 + 1.2760979307258431 + 1.2761774474371026 + 1.2762569724651338 + 1.2763365058111666 + 1.2764160474764306 + 1.276495597462161 + 1.2765751557695915 + 1.2766547223999549 + 1.2767342973544809 + 1.27681388063441 + 1.2768934722409691 + 1.2769730721753954 + 1.2770526804389224 + 1.277132297032785 + 1.2772119219582163 + 1.2772915552164523 + 1.2773711968087293 + 1.27745084673628 + 1.2775305050003452 + 1.2776101716021542 + 1.2776898465429478 + 1.2777695298239595 + 1.2778492214464303 + 1.2779289214115905 + 1.2780086297206816 + 1.2780883463749406 + 1.2781680713756003 + 1.2782478047239068 + 1.2783275464210935 + 1.2784072964683972 + 1.2784870548670586 + 1.2785668216183146 + 1.2786465967234086 + 1.2787263801835729 + 1.2788061720000534 + 1.2788859721740824 + 1.2789657807069077 + 1.279045597599767 + 1.2791254228538991 + 1.2792052564705454 + 1.2792850984509447 + 1.2793649487963428 + 1.2794448075079754 + 1.2795246745870876 + 1.2796045500349227 + 1.2796844338527169 + 1.2797643260417195 + 1.2798442266031671 + 1.2799241355383066 + 1.2800040528483783 + 1.2800839785346256 + 1.2801639125982955 + 1.280243855040629 + 1.2803238058628672 + 1.2804037650662603 + 1.2804837326520471 + 1.2805637086214778 + 1.2806436929757921 + 1.2807236857162372 + 1.2808036868440589 + 1.2808836963605055 + 1.2809637142668164 + 1.2810437405642405 + 1.2811237752540265 + 1.2812038183374208 + 1.2812838698156666 + 1.2813639296900134 + 1.2814439979617076 + 1.2815240746319994 + 1.2816041597021324 + 1.281684253173357 + 1.2817643550469235 + 1.2818444653240766 + 1.281924584006064 + 1.2820047110941388 + 1.2820848465895502 + 1.2821649904935455 + 1.2822451428073738 + 1.2823253035322864 + 1.282405472669532 + 1.2824856502203597 + 1.2825658361860275 + 1.2826460305677818 + 1.282726233366869 + 1.2828064445845475 + 1.2828866642220675 + 1.2829668922806765 + 1.2830471287616325 + 1.2831273736661835 + 1.2832076269955832 + 1.283287888751085 + 1.2833681589339432 + 1.283448437545408 + 1.2835287245867348 + 1.2836090200591774 + 1.2836893239639877 + 1.2837696363024258 + 1.2838499570757389 + 1.2839302862851865 + 1.2840106239320197 + 1.2840909700174985 + 1.2841713245428767 + 1.2842516875094065 + 1.2843320589183498 + 1.2844124387709579 + 1.284492827068489 + 1.284573223812197 + 1.2846536290033448 + 1.2847340426431866 + 1.2848144647329789 + 1.2848948952739796 + 1.2849753342674455 + 1.285055781714638 + 1.2851362376168141 + 1.2852167019752296 + 1.2852971747911484 + 1.2853776560658257 + 1.2854581458005201 + 1.2855386439964933 + 1.2856191506550074 + 1.2856996657773185 + 1.2857801893646885 + 1.2858607214183768 + 1.2859412619396464 + 1.2860218109297543 + 1.2861023683899688 + 1.2861829343215416 + 1.2862635087257448 + 1.2863440916038327 + 1.2864246829570729 + 1.286505282786722 + 1.2865858910940478 + 1.2866665078803117 + 1.2867471331467775 + 1.2868277668947072 + 1.2869084091253655 + 1.2869890598400144 + 1.2870697190399221 + 1.287150386726351 + 1.2872310629005628 + 1.2873117475638272 + 1.2873924407174067 + 1.2874731423625669 + 1.2875538525005747 + 1.2876345711326929 + 1.2877152982601914 + 1.2877960338843342 + 1.287876778006388 + 1.2879575306276227 + 1.2880382917493027 + 1.2881190613726925 + 1.2881998394990659 + 1.2882806261296877 + 1.2883614212658261 + 1.288442224908749 + 1.2885230370597245 + 1.2886038577200218 + 1.2886846868909123 + 1.288765524573662 + 1.288846370769543 + 1.2889272254798219 + 1.2890080887057735 + 1.2890889604486619 + 1.2891698407097656 + 1.2892507294903492 + 1.2893316267916826 + 1.2894125326150423 + 1.2894934469616979 + 1.2895743698329214 + 1.2896553012299805 + 1.2897362411541518 + 1.2898171896067099 + 1.2898981465889232 + 1.2899791121020661 + 1.290060086147411 + 1.2901410687262327 + 1.2902220598398029 + 1.2903030594894005 + 1.2903840676762948 + 1.2904650844017618 + 1.2905461096670743 + 1.290627143473511 + 1.2907081858223428 + 1.2907892367148492 + 1.2908702961523031 + 1.2909513641359849 + 1.2910324406671656 + 1.2911135257471222 + 1.2911946193771324 + 1.2912757215584763 + 1.291356832292426 + 1.291437951580259 + 1.2915190794232569 + 1.2916002158226982 + 1.2916813607798543 + 1.2917625142960081 + 1.2918436763724406 + 1.2919248470104248 + 1.2920060262112465 + 1.2920872139761785 + 1.2921684103065039 + 1.292249615203505 + 1.2923308286684563 + 1.2924120507026433 + 1.2924932813073402 + 1.2925745204838373 + 1.2926557682334086 + 1.2927370245573353 + 1.2928182894569009 + 1.292899562933387 + 1.2929808449880784 + 1.2930621356222531 + 1.2931434348371988 + 1.2932247426341921 + 1.2933060590145202 + 1.2933873839794634 + 1.2934687175303095 + 1.2935500596683416 + 1.293631410394839 + 1.2937127697110915 + 1.2937941376183821 + 1.2938755141179907 + 1.2939568992112107 + 1.2940382928993253 + 1.2941196951836127 + 1.2942011060653686 + 1.2942825255458723 + 1.2943639536264138 + 1.2944453903082775 + 1.2945268355927517 + 1.2946082894811239 + 1.2946897519746774 + 1.2947712230747059 + 1.2948527027824925 + 1.2949341910993282 + 1.2950156880264967 + 1.2950971935652926 + 1.2951787077170003 + 1.2952602304829115 + 1.2953417618643159 + 1.2954233018624981 + 1.2955048504787534 + 1.2955864077143697 + 1.2956679735706367 + 1.295749548048849 + 1.2958311311502912 + 1.295912722876257 + 1.295994323228038 + 1.2960759322069251 + 1.2961575498142128 + 1.296239176051188 + 1.2963208109191477 + 1.2964024544193842 + 1.2964841065531867 + 1.2965657673218509 + 1.2966474367266725 + 1.2967291147689384 + 1.2968108014499478 + 1.2968924967709936 + 1.2969742007333693 + 1.297055913338369 + 1.2971376345872889 + 1.2972193644814236 + 1.2973011030220696 + 1.2973828502105185 + 1.2974646060480683 + 1.2975463705360162 + 1.2976281436756605 + 1.2977099254682931 + 1.2977917159152124 + 1.2978735150177139 + 1.2979553227771019 + 1.2980371391946608 + 1.2981189642717044 + 1.2982007980095196 + 1.2982826404094063 + 1.2983644914726671 + 1.2984463512005986 + 1.2985282195945005 + 1.2986100966556708 + 1.2986919823854062 + 1.298773876785013 + 1.2988557798557896 + 1.2989376915990334 + 1.2990196120160458 + 1.2991015411081279 + 1.2991834788765813 + 1.2992654253227076 + 1.2993473804478115 + 1.2994293442531863 + 1.2995113167401431 + 1.299593297909978 + 1.2996752877639972 + 1.2997572863035001 + 1.2998392935297922 + 1.2999213094441808 + 1.3000033340479595 + 1.3000853673424437 + 1.3001674093289286 + 1.3002494600087238 + 1.3003315193831273 + 1.3004135874534526 + 1.300495664221001 + 1.300577749687077 + 1.3006598438529864 + 1.3007419467200356 + 1.3008240582895314 + 1.3009061785627785 + 1.3009883075410853 + 1.3010704452257578 + 1.3011525916181017 + 1.3012347467194301 + 1.301316910531042 + 1.3013990830542539 + 1.3014812642903661 + 1.3015634542406944 + 1.3016456529065437 + 1.3017278602892202 + 1.301810076390038 + 1.301892301210305 + 1.3019745347513283 + 1.3020567770144225 + 1.3021390280008953 + 1.3022212877120556 + 1.3023035561492182 + 1.3023858333136884 + 1.3024681192067813 + 1.302550413829809 + 1.302632717184081 + 1.3027150292709098 + 1.3027973500916112 + 1.3028796796474924 + 1.3029620179398658 + 1.3030443649700481 + 1.3031267207393529 + 1.3032090852490881 + 1.3032914585005757 + 1.3033738404951247 + 1.3034562312340487 + 1.3035386307186652 + 1.3036210389502867 + 1.3037034559302267 + 1.3037858816598074 + 1.3038683161403368 + 1.3039507593731343 + 1.3040332113595154 + 1.3041156721007954 + 1.3041981415982933 + 1.3042806198533223 + 1.304363106867205 + 1.3044456026412519 + 1.3045281071767854 + 1.3046106204751222 + 1.304693142537577 + 1.3047756733654761 + 1.3048582129601305 + 1.3049407613228643 + 1.305023318454992 + 1.3051058843578347 + 1.3051884590327139 + 1.3052710424809479 + 1.3053536347038581 + 1.3054362357027631 + 1.3055188454789861 + 1.3056014640338447 + 1.3056840913686625 + 1.3057667274847586 + 1.3058493723834586 + 1.3059320260660827 + 1.3060146885339481 + 1.3060973597883869 + 1.3061800398307135 + 1.3062627286622555 + 1.3063454262843324 + 1.3064281326982725 + 1.3065108479053964 + 1.306593571907029 + 1.3066763047044947 + 1.3067590462991157 + 1.3068417966922192 + 1.3069245558851317 + 1.3070073238791744 + 1.3070901006756768 + 1.3071728862759642 + 1.3072556806813571 + 1.3073384838931903 + 1.3074212959127847 + 1.3075041167414689 + 1.3075869463805705 + 1.3076697848314163 + 1.3077526320953334 + 1.3078354881736491 + 1.3079183530676943 + 1.3080012267787935 + 1.3080841093082776 + 1.308167000657477 + 1.3082499008277184 + 1.3083328098203353 + 1.3084157276366506 + 1.3084986542779997 + 1.308581589745708 + 1.3086645340411109 + 1.3087474871655382 + 1.3088304491203195 + 1.3089134199067876 + 1.3089963995262723 + 1.3090793879801039 + 1.3091623852696159 + 1.3092453913961453 + 1.3093284063610193 + 1.309411430165569 + 1.3094944628111347 + 1.3095775042990423 + 1.3096605546306288 + 1.3097436138072289 + 1.3098266818301749 + 1.309909758700802 + 1.3099928444204452 + 1.3100759389904375 + 1.3101590424121143 + 1.3102421546868148 + 1.3103252758158717 + 1.3104084058006189 + 1.3104915446423984 + 1.3105746923425408 + 1.3106578489023839 + 1.3107410143232667 + 1.3108241886065273 + 1.3109073717534998 + 1.3109905637655253 + 1.3110737646439381 + 1.3111569743900795 + 1.3112401930052877 + 1.3113234204908983 + 1.3114066568482561 + 1.3114899020786963 + 1.3115731561835586 + 1.3116564191641817 + 1.3117396910219119 + 1.3118229717580816 + 1.3119062613740373 + 1.3119895598711191 + 1.3120728672506643 + 1.3121561835140154 + 1.3122395086625198 + 1.3123228426975126 + 1.3124061856203371 + 1.3124895374323373 + 1.3125728981348581 + 1.3126562677292377 + 1.3127396462168246 + 1.3128230335989566 + 1.3129064298769826 + 1.3129898350522418 + 1.3130732491260826 + 1.313156672099848 + 1.3132401039748838 + 1.3133235447525329 + 1.313406994434142 + 1.3134904530210543 + 1.3135739205146195 + 1.3136573969161822 + 1.3137408822270884 + 1.3138243764486861 + 1.3139078795823196 + 1.3139913916293393 + 1.3140749125910907 + 1.3141584424689212 + 1.3142419812641795 + 1.3143255289782143 + 1.3144090856123738 + 1.3144926511680037 + 1.3145762256464568 + 1.3146598090490846 + 1.3147434013772306 + 1.3148270026322482 + 1.3149106128154864 + 1.3149942319282957 + 1.3150778599720261 + 1.315161496948031 + 1.3152451428576584 + 1.3153287977022614 + 1.3154124614831917 + 1.3154961342018003 + 1.3155798158594383 + 1.3156635064574611 + 1.3157472059972226 + 1.3158309144800693 + 1.3159146319073622 + 1.3159983582804475 + 1.3160820936006843 + 1.316165837869425 + 1.3162495910880232 + 1.3163333532578338 + 1.3164171243802112 + 1.3165009044565119 + 1.3165846934880923 + 1.3166684914763034 + 1.3167522984225057 + 1.3168361143280536 + 1.3169199391943041 + 1.3170037730226125 + 1.3170876158143363 + 1.3171714675708308 + 1.3172553282934578 + 1.3173391979835751 + 1.3174230766425359 + 1.3175069642717021 + 1.3175908608724296 + 1.3176747664460811 + 1.3177586809940125 + 1.3178426045175844 + 1.3179265370181561 + 1.3180104784970876 + 1.3180944289557373 + 1.3181783883954703 + 1.3182623568176421 + 1.3183463342236166 + 1.3184303206147516 + 1.3185143159924149 + 1.3185983203579645 + 1.3186823337127589 + 1.3187663560581668 + 1.3188503873955471 + 1.3189344277262651 + 1.3190184770516797 + 1.3191025353731571 + 1.31918660269206 + 1.319270679009755 + 1.3193547643276016 + 1.319438858646967 + 1.3195229619692177 + 1.3196070742957142 + 1.319691195627827 + 1.3197753259669145 + 1.3198594653143496 + 1.3199436136714944 + 1.3200277710397137 + 1.3201119374203787 + 1.3201961128148545 + 1.3202802972245069 + 1.3203644906507015 + 1.3204486930948127 + 1.3205329045582013 + 1.3206171250422392 + 1.3207013545482926 + 1.3207855930777344 + 1.3208698406319259 + 1.320954097212246 + 1.3210383628200555 + 1.3211226374567309 + 1.3212069211236375 + 1.321291213822146 + 1.32137551555363 + 1.3214598263194586 + 1.3215441461210022 + 1.3216284749596332 + 1.3217128128367237 + 1.3217971597536453 + 1.3218815157117672 + 1.3219658807124677 + 1.3220502547571147 + 1.3221346378470826 + 1.3222190299837455 + 1.3223034311684791 + 1.322387841402648 + 1.3224722606876382 + 1.322556689024817 + 1.3226411264155586 + 1.322725572861241 + 1.3228100283632382 + 1.3228944929229247 + 1.3229789665416785 + 1.3230634492208748 + 1.3231479409618858 + 1.3232324417660959 + 1.3233169516348751 + 1.323401470569602 + 1.3234859985716558 + 1.3235705356424123 + 1.3236550817832491 + 1.3237396369955452 + 1.3238242012806802 + 1.3239087746400313 + 1.3239933570749767 + 1.324077948586899 + 1.3241625491771729 + 1.3242471588471827 + 1.3243317775983035 + 1.3244164054319194 + 1.3245010423494117 + 1.3245856883521536 + 1.324670343441539 + 1.3247550076189372 + 1.3248396808857377 + 1.324924363243319 + 1.3250090546930644 + 1.3250937552363538 + 1.3251784648745757 + 1.3252631836091058 + 1.325347911441332 + 1.325432648372636 + 1.3255173944044045 + 1.3256021495380188 + 1.3256869137748657 + 1.3257716871163243 + 1.3258564695637851 + 1.3259412611186336 + 1.326026061782251 + 1.3261108715560259 + 1.3261956904413414 + 1.3262805184395892 + 1.3263653555521513 + 1.326450201780415 + 1.3265350571257688 + 1.3266199215896 + 1.3267047951732951 + 1.326789677878244 + 1.3268745697058306 + 1.3269594706574488 + 1.3270443807344825 + 1.3271292999383235 + 1.3272142282703618 + 1.3272991657319866 + 1.3273841123245849 + 1.3274690680495498 + 1.3275540329082691 + 1.3276390069021351 + 1.3277239900325375 + 1.3278089823008707 + 1.3278939837085222 + 1.3279789942568871 + 1.3280640139473532 + 1.3281490427813192 + 1.3282340807601698 + 1.3283191278853046 + 1.3284041841581113 + 1.3284892495799869 + 1.3285743241523258 + 1.3286594078765195 + 1.3287445007539624 + 1.3288296027860498 + 1.3289147139741737 + 1.3289998343197349 + 1.3290849638241229 + 1.329170102488737 + 1.3292552503149697 + 1.3293404073042201 + 1.3294255734578844 + 1.3295107487773563 + 1.3295959332640384 + 1.3296811269193216 + 1.3297663297446063 + 1.3298515417412924 + 1.3299367629107748 + 1.3300219932544506 + 1.3301072327737216 + 1.3301924814699881 + 1.3302777393446432 + 1.3303630063990941 + 1.3304482826347332 + 1.3305335680529631 + 1.3306188626551856 + 1.3307041664428003 + 1.3307894794172095 + 1.3308748015798102 + 1.3309601329320051 + 1.3310454734752009 + 1.3311308232107915 + 1.3312161821401869 + 1.3313015502647816 + 1.3313869275859858 + 1.3314723141051978 + 1.3315577098238216 + 1.3316431147432621 + 1.3317285288649245 + 1.3318139521902075 + 1.3318993847205194 + 1.3319848264572656 + 1.3320702774018518 + 1.3321557375556781 + 1.3322412069201561 + 1.3323266854966831 + 1.3324121732866754 + 1.332497670291533 + 1.3325831765126657 + 1.3326686919514783 + 1.3327542166093773 + 1.3328397504877707 + 1.3329252935880693 + 1.3330108459116781 + 1.3330964074600047 + 1.3331819782344612 + 1.3332675582364524 + 1.3333531474673874 + 1.3334387459286781 + 1.3335243536217345 + 1.3336099705479645 + 1.3336955967087818 + 1.3337812321055931 + 1.3338668767398079 + 1.3339525306128428 + 1.3340381937261054 + 1.334123866081006 + 1.3342095476789613 + 1.3342952385213793 + 1.3343809386096752 + 1.3344666479452596 + 1.3345523665295471 + 1.3346380943639473 + 1.3347238314498777 + 1.3348095777887536 + 1.3348953333819846 + 1.3349810982309867 + 1.3350668723371759 + 1.3351526557019675 + 1.3352384483267727 + 1.3353242502130105 + 1.3354100613620983 + 1.3354958817754459 + 1.3355817114544777 + 1.3356675504006048 + 1.3357533986152441 + 1.3358392560998174 + 1.3359251228557385 + 1.3360109988844238 + 1.3360968841872942 + 1.3361827787657683 + 1.336268682621262 + 1.3363545957551943 + 1.3364405181689878 + 1.3365264498640614 + 1.3366123908418326 + 1.3366983411037201 + 1.3367843006511479 + 1.3368702694855361 + 1.3369562476083021 + 1.3370422350208699 + 1.3371282317246602 + 1.3372142377210943 + 1.3373002530115963 + 1.3373862775975878 + 1.3374723114804876 + 1.3375583546617213 + 1.3376444071427132 + 1.3377304689248828 + 1.3378165400096593 + 1.3379026203984623 + 1.3379887100927177 + 1.3380748090938517 + 1.3381609174032847 + 1.3382470350224438 + 1.3383331619527552 + 1.3384192981956466 + 1.3385054437525388 + 1.3385915986248629 + 1.3386777628140401 + 1.3387639363215016 + 1.3388501191486721 + 1.3389363112969808 + 1.3390225127678521 + 1.3391087235627186 + 1.3391949436830064 + 1.3392811731301413 + 1.3393674119055554 + 1.3394536600106728 + 1.3395399174469327 + 1.3396261842157551 + 1.3397124603185737 + 1.339798745756819 + 1.3398850405319191 + 1.3399713446453074 + 1.3400576580984116 + 1.3401439808926703 + 1.3402303130295046 + 1.3403166545103558 + 1.3404030053366502 + 1.3404893655098191 + 1.3405757350313017 + 1.3406621139025272 + 1.340748502124925 + 1.3408348996999377 + 1.3409213066289924 + 1.341007722913522 + 1.341094148554967 + 1.3411805835547579 + 1.3412670279143311 + 1.3413534816351216 + 1.3414399447185639 + 1.341526417166095 + 1.3416128989791509 + 1.3416993901591685 + 1.3417858907075806 + 1.3418724006258291 + 1.3419589199153497 + 1.342045448577581 + 1.3421319866139592 + 1.342218534025921 + 1.3423050908149088 + 1.3423916569823562 + 1.3424782325297064 + 1.3425648174584002 + 1.342651411769868 + 1.3427380154655606 + 1.3428246285469114 + 1.3429112510153631 + 1.3429978828723532 + 1.3430845241193292 + 1.3431711747577271 + 1.3432578347889885 + 1.3433445042145589 + 1.3434311830358772 + 1.3435178712543865 + 1.3436045688715292 + 1.3436912758887489 + 1.3437779923074884 + 1.3438647181291907 + 1.3439514533553034 + 1.3440381979872635 + 1.3441249520265219 + 1.3442117154745195 + 1.3442984883327065 + 1.344385270602519 + 1.3444720622854107 + 1.344558863382824 + 1.3446456738962038 + 1.3447324938269998 + 1.3448193231766561 + 1.3449061619466232 + 1.3449930101383436 + 1.3450798677532669 + 1.3451667347928429 + 1.3452536112585183 + 1.3453404971517366 + 1.3454273924739553 + 1.3455142972266183 + 1.3456012114111762 + 1.3456881350290768 + 1.3457750680817719 + 1.3458620105707091 + 1.3459489624973437 + 1.346035923863121 + 1.3461228946694961 + 1.3462098749179152 + 1.3462968646098372 + 1.346383863746708 + 1.3464708723299841 + 1.3465578903611124 + 1.3466449178415492 + 1.3467319547727477 + 1.3468190011561623 + 1.3469060569932434 + 1.3469931222854454 + 1.3470801970342257 + 1.3471672812410356 + 1.3472543749073305 + 1.3473414780345678 + 1.3474285906241974 + 1.34751571267768 + 1.3476028441964718 + 1.3476899851820254 + 1.3477771356358004 + 1.3478642955592495 + 1.3479514649538329 + 1.3480386438210068 + 1.3481258321622311 + 1.348213029978961 + 1.3483002372726556 + 1.3483874540447762 + 1.3484746802967778 + 1.3485619160301179 + 1.3486491612462614 + 1.3487364159466659 + 1.3488236801327884 + 1.348910953806093 + 1.3489982369680384 + 1.3490855296200852 + 1.349172831763698 + 1.3492601434003337 + 1.3493474645314563 + 1.3494347951585244 + 1.3495221352830056 + 1.3496094849063571 + 1.3496968440300494 + 1.3497842126555364 + 1.3498715907842866 + 1.3499589784177672 + 1.3500463755574335 + 1.350133782204757 + 1.3502211983611996 + 1.3503086240282267 + 1.3503960592073012 + 1.3504835038998912 + 1.3505709581074639 + 1.350658421831485 + 1.3507458950734177 + 1.3508333778347292 + 1.350920870116886 + 1.3510083719213586 + 1.3510958832496143 + 1.3511834041031172 + 1.3512709344833389 + 1.3513584743917471 + 1.3514460238298096 + 1.3515335827989958 + 1.3516211513007734 + 1.3517087293366175 + 1.3517963169079918 + 1.3518839140163681 + 1.3519715206632161 + 1.3520591368500114 + 1.352146762578222 + 1.3522343978493132 + 1.3523220426647662 + 1.3524096970260506 + 1.3524973609346347 + 1.3525850343919927 + 1.3526727173996016 + 1.3527604099589272 + 1.3528481120714497 + 1.3529358237386386 + 1.3530235449619692 + 1.3531112757429165 + 1.353199016082953 + 1.3532867659835548 + 1.3533745254461982 + 1.353462294472356 + 1.3535500730635051 + 1.353637861221122 + 1.3537256589466835 + 1.3538134662416672 + 1.353901283107547 + 1.3539891095458041 + 1.3540769455579096 + 1.354164791145348 + 1.3542526463095914 + 1.3543405110521247 + 1.354428385374423 + 1.3545162692779653 + 1.3546041627642311 + 1.3546920658346995 + 1.354779978490853 + 1.3548679007341657 + 1.3549558325661266 + 1.3550437739882095 + 1.3551317250018984 + 1.355219685608674 + 1.3553076558100199 + 1.3553956356074142 + 1.3554836250023414 + 1.3555716239962863 + 1.3556596325907271 + 1.3557476507871491 + 1.3558356785870349 + 1.3559237159918727 + 1.356011763003139 + 1.3560998196223255 + 1.35618788585091 + 1.3562759616903817 + 1.3563640471422267 + 1.3564521422079261 + 1.3565402468889669 + 1.3566283611868388 + 1.3567164851030276 + 1.3568046186390164 + 1.3568927617962943 + 1.3569809145763456 + 1.3570690769806653 + 1.3571572490107353 + 1.3572454306680417 + 1.3573336219540801 + 1.3574218228703328 + 1.3575100334182955 + 1.3575982535994491 + 1.3576864834152895 + 1.3577747228673036 + 1.3578629719569846 + 1.3579512306858208 + 1.3580394990553051 + 1.3581277770669262 + 1.3582160647221777 + 1.3583043620225488 + 1.3583926689695336 + 1.358480985564624 + 1.3585693118093098 + 1.3586576477050885 + 1.3587459932534529 + 1.3588343484558933 + 1.358922713313905 + 1.3590110878289818 + 1.3590994720026199 + 1.3591878658363132 + 1.3592762693315552 + 1.3593646824898435 + 1.3594531053126719 + 1.359541537801539 + 1.3596299799579354 + 1.3597184317833628 + 1.3598068932793164 + 1.3598953644472944 + 1.3599838452887929 + 1.3600723358053104 + 1.3601608359983437 + 1.3602493458693912 + 1.3603378654199534 + 1.3604263946515267 + 1.3605149335656144 + 1.3606034821637103 + 1.3606920404473188 + 1.3607806084179397 + 1.360869186077071 + 1.3609577734262142 + 1.3610463704668709 + 1.3611349772005394 + 1.3612235936287271 + 1.361312219752931 + 1.3614008555746595 + 1.3614895010954078 + 1.3615781563166796 + 1.3616668212399838 + 1.3617554958668177 + 1.36184418019869 + 1.3619328742371024 + 1.3620215779835552 + 1.3621102914395609 + 1.362199014606619 + 1.3622877474862363 + 1.3623764900799182 + 1.3624652423891717 + 1.3625540044154998 + 1.3626427761604107 + 1.3627315576254131 + 1.3628203488120134 + 1.3629091497217167 + 1.3629979603560303 + 1.3630867807164662 + 1.3631756108045283 + 1.3632644506217266 + 1.3633533001695717 + 1.3634421594495709 + 1.3635310284632349 + 1.3636199072120712 + 1.3637087956975917 + 1.3637976939213077 + 1.3638866018847273 + 1.3639755195893657 + 1.364064447036726 + 1.3641533842283291 + 1.3642423311656819 + 1.3643312878502971 + 1.3644202542836881 + 1.3645092304673669 + 1.3645982164028483 + 1.3646872120916422 + 1.3647762175352682 + 1.3648652327352322 + 1.3649542576930542 + 1.3650432924102458 + 1.3651323368883246 + 1.3652213911288058 + 1.3653104551332047 + 1.3653995289030336 + 1.3654886124398145 + 1.36557770574506 + 1.3656668088202861 + 1.365755921667013 + 1.3658450442867531 + 1.3659341766810305 + 1.3660233188513555 + 1.3661124707992547 + 1.3662016325262427 + 1.3662908040338371 + 1.3663799853235585 + 1.366469176396929 + 1.3665583772554628 + 1.3666475879006827 + 1.3667368083341103 + 1.366826038557265 + 1.3669152785716681 + 1.367004528378843 + 1.3670937879803067 + 1.3671830573775816 + 1.3672723365721975 + 1.3673616255656655 + 1.3674509243595188 + 1.367540232955275 + 1.3676295513544583 + 1.3677188795585931 + 1.3678082175692012 + 1.3678975653878105 + 1.3679869230159458 + 1.3680762904551298 + 1.3681656677068876 + 1.3682550547727457 + 1.3683444516542296 + 1.3684338583528619 + 1.3685232748701799 + 1.3686127012076994 + 1.3687021373669517 + 1.3687915833494666 + 1.3688810391567678 + 1.368970504790384 + 1.3690599802518479 + 1.3691494655426797 + 1.3692389606644193 + 1.3693284656185862 + 1.3694179804067146 + 1.3695075050303345 + 1.3695970394909749 + 1.3696865837901675 + 1.3697761379294431 + 1.3698657019103311 + 1.3699552757343645 + 1.370044859403071 + 1.37013445291799 + 1.3702240562806494 + 1.3703136694925804 + 1.3704032925553205 + 1.3704929254704006 + 1.3705825682393529 + 1.3706722208637128 + 1.3707618833450148 + 1.3708515556847918 + 1.3709412378845824 + 1.3710309299459162 + 1.3711206318703331 + 1.3712103436593657 + 1.3713000653145542 + 1.3713897968374298 + 1.3714795382295346 + 1.3715692894924003 + 1.3716590506275648 + 1.3717488216365712 + 1.3718386025209521 + 1.3719283932822488 + 1.3720181939219964 + 1.3721080044417369 + 1.3721978248430091 + 1.3722876551273524 + 1.372377495296303 + 1.3724673453514065 + 1.3725572052941997 + 1.3726470751262227 + 1.3727369548490194 + 1.3728268444641298 + 1.3729167439730952 + 1.3730066533774588 + 1.3730965726787627 + 1.3731865018785478 + 1.3732764409783562 + 1.373366389979733 + 1.3734563488842231 + 1.3735463176933687 + 1.3736362964087103 + 1.3737262850317991 + 1.3738162835641781 + 1.3739062920073883 + 1.3739963103629791 + 1.3740863386324942 + 1.3741763768174804 + 1.3742664249194823 + 1.3743564829400507 + 1.3744465508807266 + 1.374536628743062 + 1.3746267165286048 + 1.3747168142388968 + 1.374806921875493 + 1.3748970394399402 + 1.3749871669337808 + 1.3750773043585762 + 1.3751674517158639 + 1.3752576090072 + 1.3753477762341348 + 1.3754379533982157 + 1.3755281405009927 + 1.3756183375440232 + 1.3757085445288522 + 1.3757987614570335 + 1.3758889883301157 + 1.3759792251496568 + 1.376069471917206 + 1.3761597286343181 + 1.3762499953025429 + 1.3763402719234357 + 1.3764305584985523 + 1.3765208550294437 + 1.3766111615176655 + 1.3767014779647746 + 1.376791804372322 + 1.3768821407418639 + 1.3769724870749591 + 1.3770628433731644 + 1.3771532096380286 + 1.3772435858711156 + 1.3773339720739779 + 1.3774243682481773 + 1.3775147743952656 + 1.3776051905168087 + 1.3776956166143539 + 1.3777860526894719 + 1.3778764987437107 + 1.3779669547786366 + 1.3780574207958032 + 1.3781478967967771 + 1.3782383827831133 + 1.378328878756375 + 1.3784193847181208 + 1.3785099006699149 + 1.3786004266133127 + 1.3786909625498824 + 1.3787815084811796 + 1.3788720644087731 + 1.378962630334222 + 1.3790532062590926 + 1.3791437921849412 + 1.3792343881133373 + 1.3793249940458412 + 1.3794156099840202 + 1.3795062359294379 + 1.3795968718836582 + 1.3796875178482464 + 1.3797781738247659 + 1.3798688398147883 + 1.3799595158198759 + 1.3800502018415906 + 1.3801408978815104 + 1.3802316039411919 + 1.3803223200222074 + 1.3804130461261233 + 1.3805037822545088 + 1.3805945284089274 + 1.3806852845909527 + 1.3807760508021554 + 1.3808668270441022 + 1.3809576133183612 + 1.3810484096265001 + 1.3811392159700964 + 1.3812300323507156 + 1.3813208587699288 + 1.381411695229309 + 1.3815025417304245 + 1.3815933982748478 + 1.381684264864155 + 1.3817751414999158 + 1.3818660281837032 + 1.3819569249170909 + 1.3820478317016491 + 1.3821387485389549 + 1.3822296754305818 + 1.3823206123781022 + 1.3824115593830928 + 1.3825025164471316 + 1.382593483571785 + 1.3826844607586339 + 1.3827754480092569 + 1.3828664453252266 + 1.3829574527081225 + 1.3830484701595143 + 1.3831394976809877 + 1.3832305352741201 + 1.3833215829404808 + 1.3834126406816547 + 1.383503708499221 + 1.3835947863947551 + 1.3836858743698379 + 1.3837769724260469 + 1.3838680805649641 + 1.3839591987881683 + 1.3840503270972406 + 1.384141465493764 + 1.3842326139793146 + 1.3843237725554776 + 1.3844149412238329 + 1.3845061199859607 + 1.3845973088434473 + 1.3846885077978768 + 1.3847797168508234 + 1.38487093600388 + 1.3849621652586226 + 1.3850534046166407 + 1.3851446540795171 + 1.3852359136488361 + 1.3853271833261835 + 1.3854184631131414 + 1.3855097530112952 + 1.3856010530222345 + 1.3856923631475455 + 1.3857836833888111 + 1.3858750137476212 + 1.3859663542255602 + 1.3860577048242182 + 1.386149065545182 + 1.3862404363900394 + 1.3863318173603785 + 1.3864232084577879 + 1.3865146096838579 + 1.3866060210401783 + 1.3866974425283405 + 1.3867888741499272 + 1.3868803159065339 + 1.3869717677997535 + 1.3870632298311729 + 1.3871547020023849 + 1.387246184314983 + 1.3873376767705548 + 1.3874291793706965 + 1.387520692117 + 1.3876122150110564 + 1.3877037480544596 + 1.3877952912488021 + 1.3878868445956842 + 1.387978408096693 + 1.3880699817534237 + 1.3881615655674748 + 1.3882531595404395 + 1.3883447636739139 + 1.3884363779694946 + 1.3885280024287754 + 1.388619637053353 + 1.3887112818448246 + 1.3888029368047909 + 1.3888946019348436 + 1.3889862772365866 + 1.3890779627116119 + 1.3891696583615241 + 1.3892613641879159 + 1.3893530801923883 + 1.3894448063765454 + 1.3895365427419819 + 1.3896282892902978 + 1.3897200460230967 + 1.3898118129419748 + 1.389903590048539 + 1.3899953773443838 + 1.3900871748311194 + 1.3901789825103403 + 1.3902708003836513 + 1.3903626284526565 + 1.3904544667189553 + 1.3905463151841555 + 1.3906381738498594 + 1.3907300427176701 + 1.3908219217891928 + 1.3909138110660308 + 1.3910057105497906 + 1.3910976202420717 + 1.3911895401444914 + 1.3912814702586442 + 1.3913734105861428 + 1.3914653611285925 + 1.3915573218875976 + 1.3916492928647692 + 1.391741274061713 + 1.3918332654800372 + 1.3919252671213502 + 1.3920172789872589 + 1.3921093010793748 + 1.3922013333993073 + 1.3922933759486611 + 1.3923854287290511 + 1.3924774917420819 + 1.3925695649893737 + 1.3926616484725267 + 1.3927537421931597 + 1.3928458461528828 + 1.3929379603533043 + 1.39303008479604 + 1.3931222194826973 + 1.393214364414896 + 1.3933065195942447 + 1.3933986850223588 + 1.3934908607008492 + 1.3935830466313341 + 1.3936752428154247 + 1.3937674492547369 + 1.393859665950886 + 1.3939518929054879 + 1.3940441301201574 + 1.3941363775965123 + 1.3942286353361644 + 1.3943209033407382 + 1.3944131816118424 + 1.3945054701510995 + 1.3945977689601279 + 1.3946900780405438 + 1.3947823973939604 + 1.394874727022007 + 1.3949670669262975 + 1.3950594171084483 + 1.395151777570083 + 1.3952441483128195 + 1.395336529338282 + 1.3954289206480881 + 1.3955213222438565 + 1.3956137341272148 + 1.3957061562997783 + 1.395798588763173 + 1.3958910315190207 + 1.3959834845689418 + 1.3960759479145612 + 1.3961684215575025 + 1.3962609054993922 + 1.3963533997418476 + 1.3964459042864961 + 1.3965384191349639 + 1.3966309442888765 + 1.3967234797498544 + 1.3968160255195297 + 1.3969085815995235 + 1.3970011479914615 + 1.3970937246969755 + 1.3971863117176913 + 1.3972789090552316 + 1.3973715167112293 + 1.3974641346873078 + 1.3975567629851 + 1.39764940160623 + 1.3977420505523312 + 1.3978347098250312 + 1.3979273794259581 + 1.3980200593567425 + 1.398112749619016 + 1.398205450214407 + 1.3982981611445513 + 1.3983908824110736 + 1.3984836140156105 + 1.3985763559597908 + 1.3986691082452509 + 1.3987618708736205 + 1.3988546438465304 + 1.3989474271656195 + 1.3990402208325168 + 1.3991330248488585 + 1.399225839216276 + 1.3993186639364104 + 1.3994114990108899 + 1.3995043444413506 + 1.399597200229433 + 1.39969006637677 + 1.3997829428849975 + 1.3998758297557485 + 1.3999687269906691 + 1.4000616345913888 + 1.4001545525595513 + 1.40024748089679 + 1.4003404196047435 + 1.4004333686850508 + 1.4005263281393512 + 1.4006192979692884 + 1.4007122781764942 + 1.4008052687626138 + 1.4008982697292864 + 1.4009912810781504 + 1.4010843028108519 + 1.4011773349290271 + 1.4012703774343187 + 1.4013634303283737 + 1.4014564936128253 + 1.4015495672893241 + 1.4016426513595108 + 1.4017357458250297 + 1.4018288506875189 + 1.4019219659486324 + 1.402015091610002 + 1.4021082276732839 + 1.4022013741401156 + 1.4022945310121471 + 1.4023876982910204 + 1.4024808759783824 + 1.4025740640758819 + 1.4026672625851664 + 1.4027604715078761 + 1.4028536908456677 + 1.402946920600179 + 1.4030401607730643 + 1.4031334113659748 + 1.4032266723805515 + 1.4033199438184474 + 1.4034132256813134 + 1.4035065179707982 + 1.4035998206885485 + 1.4036931338362195 + 1.4037864574154586 + 1.4038797914279211 + 1.4039731358752516 + 1.4040664907591089 + 1.4041598560811388 + 1.4042532318429977 + 1.4043466180463395 + 1.4044400146928138 + 1.4045334217840775 + 1.4046268393217798 + 1.4047202673075789 + 1.4048137057431309 + 1.4049071546300851 + 1.405000613970097 + 1.4050940837648274 + 1.4051875640159284 + 1.405281054725054 + 1.4053745558938684 + 1.4054680675240219 + 1.4055615896171723 + 1.4056551221749771 + 1.4057486651990949 + 1.4058422186911868 + 1.4059357826529089 + 1.4060293570859161 + 1.4061229419918746 + 1.4062165373724427 + 1.4063101432292748 + 1.4064037595640331 + 1.4064973863783845 + 1.4065910236739827 + 1.4066846714524914 + 1.406778329715572 + 1.4068719984648888 + 1.4069656777020991 + 1.4070593674288687 + 1.4071530676468651 + 1.4072467783577409 + 1.4073404995631689 + 1.4074342312648072 + 1.4075279734643229 + 1.4076217261633821 + 1.4077154893636474 + 1.4078092630667833 + 1.40790304727446 + 1.4079968419883411 + 1.4080906472100914 + 1.4081844629413753 + 1.4082782891838672 + 1.4083721259392292 + 1.4084659732091298 + 1.4085598309952381 + 1.4086536992992229 + 1.4087475781227532 + 1.4088414674674956 + 1.4089353673351206 + 1.409029277727297 + 1.4091231986456998 + 1.409217130091992 + 1.4093110720678514 + 1.4094050245749461 + 1.4094989876149466 + 1.4095929611895255 + 1.4096869453003571 + 1.4097809399491075 + 1.4098749451374584 + 1.4099689608670791 + 1.41006298713964 + 1.4101570239568202 + 1.4102510713202925 + 1.4103451292317279 + 1.4104391976928035 + 1.4105332767051997 + 1.4106273662705842 + 1.4107214663906353 + 1.410815577067031 + 1.4109096983014493 + 1.4110038300955663 + 1.4110979724510533 + 1.4111921253695967 + 1.4112862888528694 + 1.4113804629025506 + 1.4114746475203241 + 1.4115688427078592 + 1.411663048466844 + 1.4117572647989518 + 1.4118514917058669 + 1.4119457291892674 + 1.4120399772508376 + 1.4121342358922531 + 1.4122285051152017 + 1.41232278492136 + 1.412417075312413 + 1.4125113762900428 + 1.4126056878559305 + 1.4127000100117615 + 1.4127943427592193 + 1.4128886860999874 + 1.4129830400357506 + 1.4130774045681891 + 1.4131717796989907 + 1.4132661654298466 + 1.4133605617624323 + 1.4134549686984421 + 1.4135493862395554 + 1.4136438143874677 + 1.4137382531438554 + 1.4138327025104136 + 1.4139271624888261 + 1.4140216330807864 + 1.4141161142879748 + 1.4142106061120845 + 1.4143051085548031 + 1.4143996216178258 + 1.4144941453028328 + 1.4145886796115228 + 1.4146832245455814 + 1.4147777801067001 + 1.4148723462965709 + 1.4149669231168864 + 1.4150615105693365 + 1.4151561086556144 + 1.4152507173774098 + 1.4153453367364224 + 1.41543996673434 + 1.4155346073728567 + 1.4156292586536694 + 1.4157239205784669 + 1.4158185931489498 + 1.4159132763668105 + 1.4160079702337445 + 1.4161026747514467 + 1.4161973899216134 + 1.4162921157459434 + 1.4163868522261303 + 1.4164815993638744 + 1.4165763571608683 + 1.4166711256188131 + 1.4167659047394088 + 1.4168606945243534 + 1.4169554949753385 + 1.4170503060940747 + 1.4171451278822544 + 1.417239960341576 + 1.417334803473745 + 1.4174296572804603 + 1.4175245217634216 + 1.4176193969243289 + 1.4177142827648881 + 1.4178091792867995 + 1.4179040864917636 + 1.4179990043814845 + 1.4180939329576661 + 1.41818887222201 + 1.4182838221762204 + 1.4183787828219996 + 1.418473754161059 + 1.4185687361950978 + 1.4186637289258186 + 1.4187587323549335 + 1.4188537464841464 + 1.4189487713151594 + 1.4190438068496829 + 1.4191388530894213 + 1.4192339100360878 + 1.419328977691384 + 1.4194240560570173 + 1.4195191451346989 + 1.4196142449261406 + 1.4197093554330444 + 1.4198044766571261 + 1.4198996086000915 + 1.4199947512636493 + 1.420089904649513 + 1.4201850687593953 + 1.4202802435950004 + 1.4203754291580475 + 1.4204706254502453 + 1.4205658324733039 + 1.4206610502289378 + 1.4207562787188621 + 1.4208515179447849 + 1.4209467679084278 + 1.4210420286114933 + 1.4211373000557077 + 1.4212325822427758 + 1.4213278751744216 + 1.4214231788523513 + 1.4215184932782883 + 1.4216138184539431 + 1.4217091543810358 + 1.421804501061285 + 1.4218998584964011 + 1.4219952266881088 + 1.42209060563812 + 1.422185995348157 + 1.4222813958199347 + 1.4223768070551761 + 1.4224722290556004 + 1.4225676618229202 + 1.4226631053588652 + 1.4227585596651533 + 1.4228540247435004 + 1.4229495005956316 + 1.4230449872232669 + 1.4231404846281244 + 1.4232359928119358 + 1.4233315117764158 + 1.4234270415232895 + 1.4235225820542803 + 1.4236181333711124 + 1.4237136954755063 + 1.4238092683691914 + 1.4239048520538906 + 1.4240004465313245 + 1.4240960518032233 + 1.4241916678713111 + 1.4242872947373153 + 1.4243829324029609 + 1.4244785808699756 + 1.4245742401400847 + 1.4246699102150171 + 1.4247655910965011 + 1.4248612827862628 + 1.4249569852860318 + 1.4250526985975378 + 1.4251484227225109 + 1.4252441576626804 + 1.4253399034197713 + 1.4254356599955202 + 1.4255314273916555 + 1.4256272056099109 + 1.4257229946520116 + 1.4258187945196927 + 1.4259146052146869 + 1.4260104267387286 + 1.4261062590935449 + 1.4262021022808775 + 1.4262979563024503 + 1.4263938211600062 + 1.4264896968552725 + 1.4265855833899863 + 1.4266814807658814 + 1.4267773889846991 + 1.4268733080481673 + 1.4269692379580243 + 1.4270651787160087 + 1.4271611303238587 + 1.4272570927833044 + 1.4273530660960907 + 1.4274490502639512 + 1.4275450452886285 + 1.4276410511718529 + 1.4277370679153745 + 1.4278330955209213 + 1.4279291339902433 + 1.4280251833250719 + 1.4281212435271553 + 1.4282173145982253 + 1.4283133965400299 + 1.4284094893543082 + 1.428505593042803 + 1.4286017076072564 + 1.4286978330494084 + 1.4287939693710052 + 1.4288901165737908 + 1.4289862746595017 + 1.4290824436298923 + 1.4291786234867001 + 1.4292748142316696 + 1.4293710158665487 + 1.4294672283930829 + 1.4295634518130169 + 1.429659686128097 + 1.4297559313400685 + 1.4298521874506784 + 1.429948454461675 + 1.4300447323748093 + 1.4301410211918242 + 1.4302373209144672 + 1.4303336315444928 + 1.4304299530836448 + 1.4305262855336744 + 1.4306226288963337 + 1.4307189831733673 + 1.4308153483665311 + 1.4309117244775735 + 1.4310081115082474 + 1.4311045094603028 + 1.431200918335489 + 1.4312973381355627 + 1.4313937688622775 + 1.4314902105173843 + 1.4315866631026342 + 1.4316831266197838 + 1.4317796010705888 + 1.4318760864567979 + 1.4319725827801721 + 1.4320690900424637 + 1.4321656082454293 + 1.432262137390824 + 1.4323586774804047 + 1.4324552285159275 + 1.4325517904991496 + 1.4326483634318279 + 1.4327449473157232 + 1.43284154215259 + 1.4329381479441856 + 1.4330347646922754 + 1.4331313923986149 + 1.4332280310649614 + 1.4333246806930786 + 1.4334213412847217 + 1.4335180128416598 + 1.433614695365647 + 1.4337113888584461 + 1.4338080933218176 + 1.4339048087575286 + 1.4340015351673396 + 1.4340982725530125 + 1.4341950209163081 + 1.4342917802589943 + 1.434388550582834 + 1.4344853318895918 + 1.4345821241810306 + 1.4346789274589162 + 1.4347757417250118 + 1.4348725669810902 + 1.4349694032289093 + 1.4350662504702412 + 1.4351631087068546 + 1.43525997794051 + 1.4353568581729785 + 1.4354537494060284 + 1.4355506516414287 + 1.435647564880947 + 1.4357444891263529 + 1.4358414243794155 + 1.4359383706419042 + 1.4360353279155926 + 1.4361322962022467 + 1.4362292755036408 + 1.4363262658215419 + 1.4364232671577268 + 1.4365202795139644 + 1.4366173028920288 + 1.4367143372936919 + 1.4368113827207289 + 1.4369084391749083 + 1.437005506658013 + 1.4371025851718053 + 1.4371996747180686 + 1.4372967752985795 + 1.4373938869151044 + 1.4374910095694244 + 1.4375881432633197 + 1.4376852879985582 + 1.4377824437769244 + 1.4378796106001899 + 1.4379767884701331 + 1.438073977388536 + 1.4381711773571746 + 1.4382683883778247 + 1.4383656104522724 + 1.4384628435822877 + 1.4385600877696607 + 1.4386573430161649 + 1.4387546093235808 + 1.4388518866936932 + 1.4389491751282795 + 1.4390464746291247 + 1.4391437851980102 + 1.4392411068367152 + 1.4393384395470246 + 1.4394357833307247 + 1.4395331381895946 + 1.4396305041254212 + 1.4397278811399843 + 1.4398252692350744 + 1.4399226684124746 + 1.4400200786739661 + 1.4401175000213404 + 1.4402149324563787 + 1.4403123759808754 + 1.4404098305966067 + 1.4405072963053669 + 1.4406047731089426 + 1.4407022610091231 + 1.4407997600076916 + 1.4408972701064406 + 1.4409947913071608 + 1.441092323611636 + 1.4411898670216634 + 1.4412874215390274 + 1.4413849871655229 + 1.4414825639029376 + 1.4415801517530606 + 1.4416777507176937 + 1.441775360798619 + 1.4418729819976297 + 1.441970614316525 + 1.4420682577570945 + 1.4421659123211323 + 1.442263578010428 + 1.4423612548267832 + 1.4424589427719883 + 1.4425566418478377 + 1.4426543520561301 + 1.4427520733986565 + 1.4428498058772197 + 1.4429475494936117 + 1.4430453042496314 + 1.4431430701470755 + 1.4432408471877407 + 1.4433386353734261 + 1.4434364347059323 + 1.4435342451870539 + 1.4436320668185914 + 1.443729899602346 + 1.4438277435401186 + 1.443925598633705 + 1.4440234648849104 + 1.4441213422955339 + 1.4442192308673767 + 1.4443171306022435 + 1.4444150415019295 + 1.444512963568245 + 1.4446108968029898 + 1.4447088412079687 + 1.4448067967849825 + 1.4449047635358379 + 1.4450027414623372 + 1.4451007305662857 + 1.4451987308494911 + 1.4452967423137597 + 1.4453947649608934 + 1.4454927987926982 + 1.4455908438109846 + 1.4456889000175583 + 1.4457869674142239 + 1.4458850460027979 + 1.4459831357850781 + 1.4460812367628784 + 1.4461793489380073 + 1.4462774723122762 + 1.4463756068874873 + 1.4464737526654625 + 1.4465719096480014 + 1.4466700778369195 + 1.4467682572340299 + 1.4468664478411424 + 1.4469646496600677 + 1.4470628626926196 + 1.4471610869406117 + 1.4472593224058554 + 1.4473575690901623 + 1.4474558269953537 + 1.4475540961232378 + 1.4476523764756311 + 1.4477506680543482 + 1.4478489708612026 + 1.4479472848980171 + 1.4480456101665982 + 1.4481439466687696 + 1.4482422944063484 + 1.4483406533811451 + 1.4484390235949844 + 1.4485374050496811 + 1.4486357977470532 + 1.4487342016889226 + 1.4488326168771042 + 1.4489310433134253 + 1.4490294809996971 + 1.4491279299377435 + 1.4492263901293869 + 1.4493248615764454 + 1.4494233442807414 + 1.4495218382441002 + 1.4496203434683423 + 1.4497188599552859 + 1.4498173877067588 + 1.4499159267245834 + 1.4500144770105852 + 1.4501130385665824 + 1.450211611394409 + 1.4503101954958806 + 1.4504087908728271 + 1.4505073975270757 + 1.4506060154604503 + 1.4507046446747773 + 1.4508032851718831 + 1.4509019369535971 + 1.451000600021745 + 1.4510992743781554 + 1.4511979600246574 + 1.451296656963079 + 1.4513953651952509 + 1.4514940847229991 + 1.4515928155481566 + 1.45169155767255 + 1.4517903110980175 + 1.4518890758263856 + 1.4519878518594793 + 1.4520866391991427 + 1.4521854378472012 + 1.4522842478054867 + 1.4523830690758346 + 1.4524819016600807 + 1.4525807455600512 + 1.4526796007775857 + 1.4527784673145179 + 1.4528773451726837 + 1.4529762343539148 + 1.453075134860055 + 1.4531740466929284 + 1.45327296985438 + 1.4533719043462443 + 1.453470850170361 + 1.4535698073285614 + 1.4536687758226918 + 1.4537677556545809 + 1.4538667468260764 + 1.4539657493390139 + 1.4540647631952339 + 1.4541637883965741 + 1.454262824944875 + 1.4543618728419814 + 1.4544609320897275 + 1.4545600026899623 + 1.454659084644524 + 1.4547581779552514 + 1.4548572826239945 + 1.4549563986525889 + 1.4550555260428839 + 1.4551546647967204 + 1.4552538149159422 + 1.4553529764023958 + 1.4554521492579264 + 1.4555513334843744 + 1.4556505290835915 + 1.4557497360574225 + 1.4558489544077107 + 1.4559481841363071 + 1.4560474252450544 + 1.4561466777358028 + 1.4562459416104052 + 1.4563452168707018 + 1.456444503518546 + 1.4565438015557854 + 1.4566431109842715 + 1.4567424318058511 + 1.456841764022377 + 1.4569411076357 + 1.4570404626476692 + 1.4571398290601407 + 1.45723920687496 + 1.4573385960939809 + 1.4574379967190623 + 1.4575374087520514 + 1.4576368321948052 + 1.4577362670491718 + 1.4578357133170119 + 1.4579351710001762 + 1.4580346401005242 + 1.4581341206199068 + 1.45823361256018 + 1.4583331159232027 + 1.4584326307108277 + 1.458532156924915 + 1.4586316945673243 + 1.4587312436399096 + 1.4588308041445277 + 1.4589303760830397 + 1.4590299594573062 + 1.4591295542691829 + 1.4592291605205343 + 1.4593287782132123 + 1.4594284073490891 + 1.4595280479300143 + 1.4596276999578539 + 1.4597273634344716 + 1.4598270383617262 + 1.4599267247414798 + 1.4600264225756012 + 1.460126131865946 + 1.4602258526143814 + 1.4603255848227727 + 1.4604253284929851 + 1.4605250836268773 + 1.460624850226321 + 1.4607246282931796 + 1.4608244178293157 + 1.4609242188365998 + 1.4610240313168983 + 1.461123855272078 + 1.4612236907040066 + 1.461323537614549 + 1.4614233960055791 + 1.4615232658789628 + 1.4616231472365675 + 1.4617230400802632 + 1.4618229444119248 + 1.4619228602334158 + 1.4620227875466123 + 1.4621227263533807 + 1.4622226766555955 + 1.4623226384551293 + 1.4624226117538541 + 1.4625225965536375 + 1.4626225928563574 + 1.4627226006638889 + 1.4628226199781011 + 1.4629226508008724 + 1.463022693134076 + 1.463122746979584 + 1.4632228123392774 + 1.4633228892150287 + 1.4634229776087151 + 1.4635230775222079 + 1.4636231889573947 + 1.463723311916143 + 1.4638234464003379 + 1.4639235924118514 + 1.4640237499525688 + 1.4641239190243631 + 1.4642240996291163 + 1.4643242917687083 + 1.4644244954450196 + 1.4645247106599266 + 1.4646249374153171 + 1.4647251757130679 + 1.4648254255550637 + 1.4649256869431833 + 1.4650259598793107 + 1.4651262443653323 + 1.4652265404031264 + 1.4653268479945787 + 1.4654271671415733 + 1.4655274978459953 + 1.4656278401097258 + 1.4657281939346578 + 1.4658285593226728 + 1.4659289362756547 + 1.4660293247954916 + 1.4661297248840719 + 1.4662301365432837 + 1.4663305597750098 + 1.4664309945811453 + 1.4665314409635735 + 1.4666318989241869 + 1.4667323684648668 + 1.4668328495875149 + 1.4669333422940167 + 1.4670338465862556 + 1.4671343624661335 + 1.4672348899355343 + 1.4673354289963538 + 1.4674359796504803 + 1.4675365418998065 + 1.4676371157462309 + 1.4677377011916408 + 1.4678382982379359 + 1.4679389068870023 + 1.4680395271407407 + 1.4681401590010461 + 1.4682408024698086 + 1.4683414575489269 + 1.4684421242403014 + 1.4685428025458223 + 1.4686434924673879 + 1.4687441940068999 + 1.4688449071662486 + 1.4689456319473371 + 1.4690463683520651 + 1.4691471163823271 + 1.469247876040026 + 1.4693486473270601 + 1.4694494302453271 + 1.4695502247967351 + 1.4696510309831763 + 1.4697518488065555 + 1.4698526782687755 + 1.4699535193717395 + 1.470054372117346 + 1.4701552365074999 + 1.470256112544106 + 1.4703570002290669 + 1.4704578995642856 + 1.4705588105516674 + 1.4706597331931195 + 1.470760667490544 + 1.4708616134458463 + 1.4709625710609358 + 1.4710635403377175 + 1.4711645212780979 + 1.4712655138839845 + 1.4713665181572864 + 1.471467534099911 + 1.4715685617137628 + 1.4716696010007586 + 1.4717706519628009 + 1.4718717146018039 + 1.4719727889196765 + 1.4720738749183271 + 1.4721749725996724 + 1.4722760819656147 + 1.472377203018074 + 1.4724783357589599 + 1.4725794801901866 + 1.4726806363136611 + 1.4727818041313017 + 1.4728829836450223 + 1.4729841748567378 + 1.4730853777683606 + 1.4731865923818059 + 1.4732878186989893 + 1.4733890567218271 + 1.4734903064522358 + 1.4735915678921347 + 1.4736928410434353 + 1.4737941259080571 + 1.4738954224879217 + 1.4739967307849433 + 1.4740980508010399 + 1.4741993825381337 + 1.47430072599814 + 1.4744020811829872 + 1.4745034480945862 + 1.4746048267348617 + 1.4747062171057341 + 1.4748076192091277 + 1.4749090330469592 + 1.475010458621159 + 1.4751118959336393 + 1.4752133449863305 + 1.475314805781158 + 1.4754162783200406 + 1.4755177626049008 + 1.4756192586376704 + 1.4757207664202705 + 1.4758222859546293 + 1.4759238172426683 + 1.4760253602863169 + 1.4761269150875036 + 1.4762284816481488 + 1.476330059970191 + 1.4764316500555481 + 1.476533251906156 + 1.4766348655239363 + 1.4767364909108252 + 1.4768381280687493 + 1.4769397769996377 + 1.4770414377054246 + 1.4771431101880366 + 1.4772447944494047 + 1.4773464904914664 + 1.47744819831615 + 1.477549917925387 + 1.4776516493211096 + 1.4777533925052564 + 1.4778551474797597 + 1.4779569142465494 + 1.4780586928075623 + 1.4781604831647348 + 1.4782622853200003 + 1.4783640992753 + 1.4784659250325611 + 1.4785677625937295 + 1.4786696119607354 + 1.4787714731355177 + 1.4788733461200159 + 1.4789752309161681 + 1.4790771275259154 + 1.4791790359511896 + 1.4792809561939375 + 1.4793828882560971 + 1.4794848321396081 + 1.4795867878464122 + 1.479688755378447 + 1.4797907347376575 + 1.4798927259259855 + 1.4799947289453734 + 1.4800967437977637 + 1.4801987704850994 + 1.4803008090093228 + 1.4804028593723813 + 1.4805049215762185 + 1.4806069956227754 + 1.4807090815140027 + 1.4808111792518448 + 1.4809132888382435 + 1.4810154102751503 + 1.4811175435645088 + 1.4812196887082694 + 1.4813218457083799 + 1.4814240145667863 + 1.4815261952854382 + 1.481628387866283 + 1.4817305923112751 + 1.4818328086223549 + 1.4819350368014839 + 1.4820372768506067 + 1.4821395287716759 + 1.4822417925666431 + 1.4823440682374578 + 1.4824463557860725 + 1.4825486552144445 + 1.4826509665245229 + 1.4827532897182616 + 1.4828556247976181 + 1.4829579717645436 + 1.4830603306209924 + 1.4831627013689195 + 1.483265084010287 + 1.4833674785470403 + 1.4834698849811456 + 1.4835723033145554 + 1.4836747335492255 + 1.4837771756871174 + 1.4838796297301873 + 1.483982095680396 + 1.4840845735396981 + 1.4841870633100547 + 1.4842895649934305 + 1.4843920785917781 + 1.4844946041070626 + 1.4845971415412433 + 1.4846996908962831 + 1.484802252174142 + 1.4849048253767865 + 1.4850074105061772 + 1.4851100075642745 + 1.4852126165530437 + 1.4853152374744483 + 1.4854178703304572 + 1.4855205151230293 + 1.4856231718541328 + 1.4857258405257345 + 1.4858285211397972 + 1.4859312136982898 + 1.4860339182031801 + 1.4861366346564311 + 1.4862393630600181 + 1.4863421034159008 + 1.4864448557260515 + 1.4865476199924419 + 1.4866503962170368 + 1.4867531844018087 + 1.4868559845487275 + 1.4869587966597655 + 1.4870616207368894 + 1.4871644567820759 + 1.4872673047972924 + 1.4873701647845168 + 1.4874730367457132 + 1.4875759206828658 + 1.4876788165979404 + 1.4877817244929126 + 1.4878846443697575 + 1.4879875762304515 + 1.4880905200769672 + 1.4881934759112851 + 1.488296443735375 + 1.4883994235512177 + 1.4885024153607878 + 1.4886054191660658 + 1.4887084349690265 + 1.4888114627716491 + 1.4889145025759154 + 1.4890175543838009 + 1.4891206181972823 + 1.4892236940183452 + 1.4893267818489702 + 1.489429881691134 + 1.4895329935468209 + 1.4896361174180117 + 1.4897392533066878 + 1.4898424012148306 + 1.4899455611444286 + 1.490048733097457 + 1.4901519170759061 + 1.4902551130817576 + 1.4903583211169953 + 1.4904615411836057 + 1.4905647732835758 + 1.4906680174188869 + 1.4907712735915291 + 1.4908745418034879 + 1.4909778220567482 + 1.4910811143533045 + 1.4911844186951366 + 1.4912877350842371 + 1.4913910635225953 + 1.4914944040121978 + 1.491597756555038 + 1.4917011211531033 + 1.4918044978083844 + 1.4919078865228754 + 1.492011287298562 + 1.492114700137442 + 1.4922181250415039 + 1.4923215620127377 + 1.492425011053145 + 1.4925284721647125 + 1.4926319453494374 + 1.4927354306093092 + 1.4928389279463323 + 1.4929424373624911 + 1.4930459588597895 + 1.4931494924402167 + 1.4932530381057771 + 1.4933565958584594 + 1.4934601657002669 + 1.4935637476331987 + 1.4936673416592443 + 1.4937709477804106 + 1.4938745659986916 + 1.493978196316091 + 1.4940818387346066 + 1.4941854932562368 + 1.4942891598829893 + 1.4943928386168568 + 1.4944965294598442 + 1.4946002324139578 + 1.4947039474811936 + 1.4948076746635588 + 1.4949114139630526 + 1.4950151653816832 + 1.4951189289214541 + 1.4952227045843667 + 1.4953264923724292 + 1.4954302922876501 + 1.4955341043320278 + 1.4956379285075685 + 1.4957417648162876 + 1.4958456132601861 + 1.4959494738412726 + 1.4960533465615582 + 1.4961572314230462 + 1.4962611284277492 + 1.4963650375776762 + 1.4964689588748341 + 1.4965728923212369 + 1.4966768379188944 + 1.4967807956698151 + 1.4968847655760125 + 1.4969887476394954 + 1.4970927418622852 + 1.497196748246385 + 1.4973007667938125 + 1.4974047975065818 + 1.497508840386705 + 1.4976128954361931 + 1.4977169626570721 + 1.4978210420513443 + 1.4979251336210389 + 1.4980292373681618 + 1.4981333532947303 + 1.4982374814027677 + 1.4983416216942853 + 1.4984457741713064 + 1.4985499388358461 + 1.4986541156899227 + 1.4987583047355579 + 1.4988625059747709 + 1.4989667194095806 + 1.4990709450420032 + 1.499175182874072 + 1.4992794329077972 + 1.4993836951452058 + 1.4994879695883185 + 1.4995922562391599 + 1.4996965550997516 + 1.4998008661721149 + 1.4999051894582791 + 1.5000095249602661 + 1.5001138726800984 + 1.5002182326198035 + 1.5003226047814098 + 1.5004269891669388 + 1.5005313857784177 + 1.500635794617877 + 1.5007402156873417 + 1.5008446489888398 + 1.5009490945244031 + 1.5010535522960542 + 1.501158022305829 + 1.5012625045557533 + 1.501366999047854 + 1.5014715057841714 + 1.501576024766726 + 1.5016805559975546 + 1.501785099478689 + 1.5018896552121603 + 1.5019942232000008 + 1.5020988034442453 + 1.5022033959469303 + 1.5023080007100809 + 1.5024126177357375 + 1.5025172470259371 + 1.5026218885827125 + 1.5027265424080989 + 1.5028312085041329 + 1.5029358868728495 + 1.5030405775162874 + 1.5031452804364882 + 1.5032499956354808 + 1.5033547231153115 + 1.5034594628780165 + 1.503564214925635 + 1.5036689792602085 + 1.5037737558837734 + 1.5038785447983711 + 1.5039833460060457 + 1.5040881595088353 + 1.5041929853087859 + 1.5042978234079356 + 1.50440267380833 + 1.50450753651201 + 1.5046124115210204 + 1.5047172988374058 + 1.5048221984632126 + 1.5049271104004824 + 1.5050320346512589 + 1.5051369712175937 + 1.5052419201015288 + 1.505346881305113 + 1.5054518548303948 + 1.5055568406794178 + 1.5056618388542311 + 1.5057668493568845 + 1.5058718721894291 + 1.5059769073539082 + 1.5060819548523798 + 1.5061870146868892 + 1.5062920868594869 + 1.506397171372222 + 1.5065022682271503 + 1.5066073774263247 + 1.5067124989717942 + 1.5068176328656122 + 1.5069227791098323 + 1.5070279377065092 + 1.5071331086576996 + 1.5072382919654481 + 1.5073434876318235 + 1.5074486956588737 + 1.5075539160486542 + 1.5076591488032223 + 1.5077643939246359 + 1.507869651414955 + 1.5079749212762308 + 1.5080802035105296 + 1.5081854981199028 + 1.5082908051064114 + 1.508396124472116 + 1.5085014562190802 + 1.5086068003493576 + 1.5087121568650117 + 1.5088175257681051 + 1.5089229070607013 + 1.5090283007448564 + 1.5091337068226376 + 1.5092391252961066 + 1.5093445561673293 + 1.5094499994383657 + 1.5095554551112833 + 1.5096609231881442 + 1.5097664036710172 + 1.5098718965619653 + 1.5099774018630554 + 1.5100829195763568 + 1.5101884497039333 + 1.5102939922478527 + 1.5103995472101825 + 1.510505114592994 + 1.5106106943983522 + 1.5107162866283281 + 1.510821891284996 + 1.5109275083704206 + 1.5110331378866722 + 1.5111387798358231 + 1.5112444342199483 + 1.5113501010411174 + 1.5114557803013986 + 1.5115614720028729 + 1.5116671761476088 + 1.5117728927376779 + 1.5118786217751563 + 1.5119843632621233 + 1.5120901172006478 + 1.5121958835928064 + 1.5123016624406809 + 1.5124074537463401 + 1.5125132575118656 + 1.512619073739329 + 1.5127249024308183 + 1.5128307435884019 + 1.5129365972141651 + 1.5130424633101844 + 1.5131483418785359 + 1.5132542329213061 + 1.5133601364405753 + 1.5134660524384174 + 1.5135719809169195 + 1.5136779218781631 + 1.5137838753242268 + 1.5138898412571986 + 1.5139958196791579 + 1.5141018105921897 + 1.5142078139983779 + 1.5143138298998087 + 1.5144198582985653 + 1.5145258991967316 + 1.5146319525963958 + 1.5147380184996415 + 1.5148440969085606 + 1.5149501878252349 + 1.5150562912517571 + 1.5151624071902092 + 1.5152685356426869 + 1.5153746766112748 + 1.5154808300980649 + 1.5155869961051422 + 1.5156931746346036 + 1.5157993656885334 + 1.5159055692690269 + 1.5160117853781792 + 1.5161180140180721 + 1.5162242551908089 + 1.5163305088984784 + 1.516436775143174 + 1.5165430539269893 + 1.5166493452520178 + 1.5167556491203569 + 1.516861965534102 + 1.5169682944953502 + 1.5170746360061944 + 1.517180990068729 + 1.5172873566850569 + 1.5173937358572747 + 1.5175001275874784 + 1.5176065318777652 + 1.5177129487302383 + 1.517819378146996 + 1.5179258201301358 + 1.5180322746817623 + 1.5181387418039707 + 1.5182452214988635 + 1.5183517137685467 + 1.518458218615119 + 1.518564736040684 + 1.5186712660473456 + 1.5187778086372075 + 1.5188843638123699 + 1.5189909315749379 + 1.5190975119270225 + 1.5192041048707234 + 1.5193107104081442 + 1.5194173285413994 + 1.5195239592725907 + 1.5196306026038249 + 1.519737258537212 + 1.5198439270748563 + 1.5199506082188681 + 1.5200573019713595 + 1.5201640083344374 + 1.5202707273102081 + 1.5203774589007897 + 1.5204842031082855 + 1.5205909599348146 + 1.5206977293824799 + 1.520804511453399 + 1.520911306149682 + 1.5210181134734466 + 1.5211249334268011 + 1.5212317660118624 + 1.5213386112307443 + 1.5214454690855608 + 1.5215523395784283 + 1.5216592227114634 + 1.5217661184867823 + 1.5218730269064982 + 1.5219799479727332 + 1.5220868816876028 + 1.5221938280532235 + 1.5223007870717158 + 1.5224077587451983 + 1.5225147430757942 + 1.5226217400656179 + 1.5227287497167905 + 1.5228357720314352 + 1.5229428070116746 + 1.5230498546596263 + 1.5231569149774156 + 1.5232639879671623 + 1.5233710736309929 + 1.5234781719710315 + 1.5235852829893977 + 1.5236924066882211 + 1.5237995430696241 + 1.5239066921357338 + 1.5240138538886703 + 1.5241210283305708 + 1.5242282154635536 + 1.5243354152897459 + 1.5244426278112804 + 1.5245498530302817 + 1.5246570909488824 + 1.5247643415692054 + 1.5248716048933875 + 1.5249788809235543 + 1.5250861696618367 + 1.5251934711103663 + 1.5253007852712765 + 1.5254081121466958 + 1.5255154517387592 + 1.5256228040495992 + 1.5257301690813476 + 1.5258375468361409 + 1.5259449373161091 + 1.5260523405233921 + 1.5261597564601206 + 1.5262671851284315 + 1.5263746265304639 + 1.526482080668351 + 1.5265895475442293 + 1.5266970271602402 + 1.52680451951852 + 1.5269120246212049 + 1.5270195424704383 + 1.5271270730683535 + 1.527234616417094 + 1.5273421725187979 + 1.5274497413756098 + 1.5275573229896711 + 1.5276649173631209 + 1.5277725244980971 + 1.5278801443967502 + 1.5279877770612191 + 1.5280954224936472 + 1.5282030806961819 + 1.5283107516709635 + 1.5284184354201393 + 1.5285261319458516 + 1.5286338412502511 + 1.5287415633354842 + 1.528849298203693 + 1.5289570458570259 + 1.529064806297634 + 1.5291725795276629 + 1.5292803655492611 + 1.5293881643645777 + 1.5294959759757614 + 1.5296038003849703 + 1.5297116375943431 + 1.5298194876060383 + 1.5299273504222046 + 1.5300352260449921 + 1.5301431144765609 + 1.5302510157190536 + 1.5303589297746318 + 1.5304668566454456 + 1.5305747963336498 + 1.5306827488413994 + 1.5307907141708492 + 1.5308986923241557 + 1.5310066833034708 + 1.5311146871109613 + 1.5312227037487731 + 1.5313307332190704 + 1.5314387755240069 + 1.5315468306657436 + 1.5316548986464424 + 1.5317629794682577 + 1.531871073133352 + 1.5319791796438837 + 1.5320872990020162 + 1.5321954312099093 + 1.5323035762697264 + 1.532411734183627 + 1.5325199049537763 + 1.5326280885823347 + 1.532736285071471 + 1.5328444944233435 + 1.5329527166401171 + 1.5330609517239617 + 1.53316919967704 + 1.5332774605015187 + 1.5333857341995647 + 1.5334940207733447 + 1.5336023202250233 + 1.5337106325567722 + 1.5338189577707555 + 1.5339272958691494 + 1.5340356468541154 + 1.5341440107278268 + 1.5342523874924563 + 1.5343607771501706 + 1.5344691797031407 + 1.5345775951535428 + 1.5346860235035422 + 1.5347944647553204 + 1.5349029189110417 + 1.5350113859728858 + 1.5351198659430247 + 1.5352283588236282 + 1.5353368646168821 + 1.5354453833249508 + 1.5355539149500177 + 1.5356624594942572 + 1.5357710169598435 + 1.5358795873489586 + 1.5359881706637777 + 1.5360967669064762 + 1.5362053760792374 + 1.5363139981842397 + 1.5364226332236648 + 1.5365312811996878 + 1.5366399421144945 + 1.5367486159702615 + 1.5368573027691705 + 1.5369660025134066 + 1.5370747152051523 + 1.5371834408465899 + 1.5372921794399046 + 1.5374009309872776 + 1.5375096954908949 + 1.5376184729529376 + 1.5377272633755994 + 1.5378360667610582 + 1.5379448831115063 + 1.538053712429128 + 1.5381625547161064 + 1.5382714099746371 + 1.538380278206906 + 1.5384891594151011 + 1.5385980536014081 + 1.538706960768021 + 1.5388158809171291 + 1.5389248140509222 + 1.5390337601715962 + 1.5391427192813361 + 1.5392516913823384 + 1.5393606764767922 + 1.5394696745668937 + 1.5395786856548337 + 1.5396877097428123 + 1.5397967468330138 + 1.5399057969276433 + 1.5400148600288883 + 1.540123936138952 + 1.5402330252600251 + 1.5403421273943083 + 1.5404512425439976 + 1.5405603707112889 + 1.5406695118983871 + 1.5407786661074825 + 1.5408878333407765 + 1.5409970136004734 + 1.5411062068887718 + 1.5412154132078704 + 1.5413246325599728 + 1.541433864947277 + 1.5415431103719908 + 1.5416523688363106 + 1.5417616403424443 + 1.541870924892595 + 1.5419802224889652 + 1.5420895331337594 + 1.5421988568291829 + 1.5423081935774454 + 1.5424175433807452 + 1.5425269062412967 + 1.5426362821613027 + 1.5427456711429701 + 1.5428550731885069 + 1.5429644883001243 + 1.5430739164800302 + 1.5431833577304335 + 1.5432928120535427 + 1.5434022794515709 + 1.5435117599267276 + 1.5436212534812266 + 1.5437307601172743 + 1.5438402798370878 + 1.5439498126428792 + 1.5440593585368592 + 1.5441689175212463 + 1.54427848959825 + 1.5443880747700853 + 1.5444976730389721 + 1.5446072844071239 + 1.5447169088767538 + 1.5448265464500797 + 1.544936197129325 + 1.5450458609166982 + 1.5451555378144211 + 1.5452652278247159 + 1.5453749309497977 + 1.5454846471918866 + 1.5455943765532021 + 1.5457041190359675 + 1.5458138746424002 + 1.5459236433747241 + 1.5460334252351646 + 1.5461432202259391 + 1.5462530283492697 + 1.5463628496073856 + 1.5464726840025058 + 1.5465825315368569 + 1.5466923922126623 + 1.5468022660321494 + 1.5469121529975416 + 1.5470220531110703 + 1.5471319663749568 + 1.5472418927914304 + 1.5473518323627222 + 1.5474617850910557 + 1.5475717509786637 + 1.5476817300277721 + 1.5477917222406152 + 1.5479017276194167 + 1.5480117461664147 + 1.5481217778838336 + 1.548231822773912 + 1.5483418808388754 + 1.5484519520809623 + 1.5485620365024033 + 1.5486721341054344 + 1.5487822448922852 + 1.5488923688651943 + 1.5490025060263948 + 1.5491126563781252 + 1.5492228199226208 + 1.5493329966621165 + 1.5494431865988516 + 1.5495533897350586 + 1.5496636060729845 + 1.5497738356148589 + 1.549884078362926 + 1.5499943343194265 + 1.5501046034865986 + 1.5502148858666835 + 1.5503251814619201 + 1.5504354902745507 + 1.5505458123068212 + 1.5506561475609684 + 1.5507664960392389 + 1.5508768577438792 + 1.5509872326771279 + 1.5510976208412315 + 1.551208022238433 + 1.5513184368709836 + 1.5514288647411254 + 1.5515393058511013 + 1.551649760203164 + 1.5517602277995612 + 1.5518707086425387 + 1.5519812027343447 + 1.5520917100772298 + 1.5522022306734393 + 1.5523127645252284 + 1.5524233116348458 + 1.5525338720045443 + 1.5526444456365698 + 1.5527550325331789 + 1.5528656326966228 + 1.5529762461291545 + 1.5530868728330294 + 1.5531975128104982 + 1.5533081660638166 + 1.5534188325952398 + 1.5535295124070232 + 1.5536402055014209 + 1.5537509118806914 + 1.553861631547093 + 1.5539723645028791 + 1.5540831107503079 + 1.5541938702916431 + 1.5543046431291376 + 1.5544154292650563 + 1.5545262287016548 + 1.5546370414411967 + 1.5547478674859383 + 1.5548587068381434 + 1.5549695595000754 + 1.5550804254739956 + 1.5551913047621655 + 1.5553021973668504 + 1.5554131032903118 + 1.5555240225348161 + 1.5556349551026292 + 1.5557459009960151 + 1.5558568602172391 + 1.5559678327685662 + 1.5560788186522676 + 1.5561898178706046 + 1.5563008304258519 + 1.5564118563202713 + 1.5565228955561361 + 1.5566339481357154 + 1.5567450140612795 + 1.5568560933350943 + 1.556967185959435 + 1.5570782919365713 + 1.5571894112687721 + 1.5573005439583156 + 1.5574116900074706 + 1.5575228494185134 + 1.5576340221937155 + 1.5577452083353511 + 1.5578564078456967 + 1.5579676207270265 + 1.5580788469816154 + 1.5581900866117437 + 1.5583013396196834 + 1.5584126060077133 + 1.5585238857781163 + 1.5586351789331614 + 1.5587464854751352 + 1.5588578054063151 + 1.5589691387289779 + 1.5590804854454041 + 1.5591918455578795 + 1.5593032190686822 + 1.5594146059800933 + 1.5595260062944003 + 1.5596374200138778 + 1.5597488471408132 + 1.5598602876774932 + 1.5599717416261984 + 1.5600832089892169 + 1.5601946897688297 + 1.5603061839673247 + 1.5604176915869921 + 1.5605292126301091 + 1.5606407470989734 + 1.5607522949958712 + 1.5608638563230828 + 1.5609754310829089 + 1.5610870192776263 + 1.5611986209095343 + 1.5613102359809243 + 1.561421864494078 + 1.561533506451295 + 1.561645161854865 + 1.5617568307070777 + 1.5618685130102294 + 1.5619802087666153 + 1.5620919179785226 + 1.5622036406482491 + 1.5623153767780906 + 1.5624271263703455 + 1.562538889427306 + 1.5626506659512693 + 1.562762455944531 + 1.5628742594093887 + 1.5629860763481433 + 1.5630979067630923 + 1.5632097506565334 + 1.5633216080307657 + 1.563433478888091 + 1.5635453632308096 + 1.5636572610612232 + 1.563769172381632 + 1.5638810971943369 + 1.5639930355016418 + 1.564104987305851 + 1.5642169526092662 + 1.5643289314141922 + 1.5644409237229353 + 1.564552929537798 + 1.564664948861086 + 1.5647769816951105 + 1.5648890280421708 + 1.5650010879045781 + 1.5651131612846374 + 1.5652252481846596 + 1.5653373486069535 + 1.5654494625538284 + 1.5655615900275934 + 1.5656737310305548 + 1.56578588556503 + 1.5658980536333251 + 1.5660102352377556 + 1.5661224303806316 + 1.5662346390642656 + 1.5663468612909688 + 1.5664590970630616 + 1.566571346382855 + 1.5666836092526601 + 1.566795885674797 + 1.5669081756515786 + 1.5670204791853237 + 1.5671327962783497 + 1.5672451269329686 + 1.5673574711515057 + 1.5674698289362734 + 1.5675822002895914 + 1.567694585213782 + 1.5678069837111637 + 1.5679193957840598 + 1.5680318214347839 + 1.568144260665665 + 1.5682567134790184 + 1.5683691798771724 + 1.5684816598624496 + 1.5685941534371697 + 1.568706660603659 + 1.568819181364242 + 1.5689317157212455 + 1.5690442636769908 + 1.5691568252338093 + 1.5692694003940233 + 1.5693819891599605 + 1.569494591533952 + 1.5696072075183196 + 1.5697198371154009 + 1.569832480327515 + 1.5699451371569977 + 1.5700578076061789 + 1.5701704916773909 + 1.5702831893729587 + 1.5703959006952184 + 1.5705086256465024 + 1.5706213642291442 + 1.5707341164454736 + 1.5708468822978277 + 1.5709596617885413 + 1.5710724549199457 + 1.5711852616943789 + 1.5712980821141764 + 1.5714109161816741 + 1.5715237638992119 + 1.5716366252691223 + 1.5717495002937463 + 1.5718623889754206 + 1.5719752913164831 + 1.5720882073192823 + 1.5722011369861433 + 1.5723140803194213 + 1.5724270373214491 + 1.5725400079945695 + 1.5726529923411228 + 1.5727659903634561 + 1.5728790020639136 + 1.5729920274448324 + 1.5731050665085586 + 1.573218119257443 + 1.5733311856938224 + 1.5734442658200485 + 1.5735573596384649 + 1.5736704671514183 + 1.5737835883612594 + 1.5738967232703327 + 1.5740098718809856 + 1.5741230341955665 + 1.5742362102164311 + 1.5743493999459222 + 1.5744626033863924 + 1.5745758205401947 + 1.5746890514096796 + 1.5748022959972015 + 1.5749155543051072 + 1.5750288263357519 + 1.575142112091491 + 1.5752554115746769 + 1.5753687247876651 + 1.5754820517328092 + 1.5755953924124686 + 1.5757087468289943 + 1.57582211498475 + 1.5759354968820869 + 1.5760488925233602 + 1.5761623019109356 + 1.5762757250471715 + 1.5763891619344208 + 1.5765026125750472 + 1.5766160769714139 + 1.5767295551258742 + 1.5768430470407973 + 1.5769565527185392 + 1.577070072161467 + 1.5771836053719417 + 1.577297152352326 + 1.5774107131049864 + 1.5775242876322826 + 1.5776378759365859 + 1.5777514780202591 + 1.5778650938856638 + 1.5779787235351754 + 1.5780923669711555 + 1.5782060241959728 + 1.578319695211994 + 1.5784333800215913 + 1.5785470786271325 + 1.5786607910309844 + 1.5787745172355243 + 1.5788882572431175 + 1.5790020110561322 + 1.5791157786769503 + 1.5792295601079378 + 1.5793433553514671 + 1.5794571644099125 + 1.5795709872856503 + 1.5796848239810544 + 1.5797986744984966 + 1.5799125388403583 + 1.580026417009011 + 1.580140309006834 + 1.5802542148361995 + 1.5803681344994911 + 1.5804820679990823 + 1.5805960153373566 + 1.5807099765166921 + 1.5808239515394664 + 1.5809379404080615 + 1.5810519431248558 + 1.5811659596922352 + 1.581279990112576 + 1.5813940343882686 + 1.58150809252169 + 1.5816221645152231 + 1.5817362503712569 + 1.5818503500921723 + 1.5819644636803518 + 1.5820785911381905 + 1.5821927324680649 + 1.5823068876723678 + 1.5824210567534789 + 1.5825352397137964 + 1.5826494365557007 + 1.5827636472815869 + 1.5828778718938361 + 1.582992110394847 + 1.5831063627870035 + 1.5832206290727 + 1.5833349092543276 + 1.5834492033342764 + 1.5835635113149438 + 1.5836778331987147 + 1.5837921689879904 + 1.5839065186851626 + 1.5840208822926236 + 1.5841352598127771 + 1.5842496512480049 + 1.5843640566007147 + 1.5844784758733006 + 1.5845929090681561 + 1.5847073561876834 + 1.5848218172342807 + 1.5849362922103434 + 1.5850507811182739 + 1.585165283960472 + 1.5852798007393381 + 1.5853943314572758 + 1.5855088761166829 + 1.5856234347199631 + 1.5857380072695149 + 1.585852593767751 + 1.585967194217067 + 1.586081808619872 + 1.5861964369785657 + 1.586311079295559 + 1.5864257355732556 + 1.5865404058140604 + 1.5866550900203842 + 1.5867697881946321 + 1.5868845003392138 + 1.5869992264565314 + 1.5871139665490051 + 1.5872287206190343 + 1.5873434886690372 + 1.5874582707014167 + 1.5875730667185888 + 1.5876878767229683 + 1.5878027007169635 + 1.5879175387029874 + 1.5880323906834559 + 1.5881472566607793 + 1.5882621366373744 + 1.5883770306156555 + 1.5884919385980365 + 1.5886068605869401 + 1.5887217965847746 + 1.5888367465939652 + 1.588951710616922 + 1.5890666886560714 + 1.5891816807138233 + 1.5892966867926051 + 1.5894117068948317 + 1.5895267410229239 + 1.5896417891793073 + 1.5897568513663978 + 1.5898719275866207 + 1.5899870178423994 + 1.5901021221361507 + 1.5902172404703054 + 1.5903323728472869 + 1.5904475192695178 + 1.5905626797394257 + 1.5906778542594331 + 1.590793042831969 + 1.5909082454594594 + 1.5910234621443318 + 1.5911386928890157 + 1.5912539376959396 + 1.591369196567527 + 1.5914844695062174 + 1.5915997565144313 + 1.5917150575946057 + 1.5918303727491698 + 1.5919457019805567 + 1.5920610452911965 + 1.5921764026835272 + 1.5922917741599762 + 1.5924071597229785 + 1.5925225593749726 + 1.5926379731183873 + 1.5927534009556659 + 1.5928688428892408 + 1.5929842989215466 + 1.5930997690550228 + 1.5932152532921111 + 1.5933307516352389 + 1.5934462640868556 + 1.5935617906493997 + 1.593677331325307 + 1.5937928861170207 + 1.5939084550269778 + 1.5940240380576252 + 1.5941396352114037 + 1.5942552464907551 + 1.5943708718981242 + 1.5944865114359534 + 1.5946021651066844 + 1.594717832912768 + 1.5948335148566433 + 1.594949210940765 + 1.5950649211675731 + 1.5951806455395126 + 1.595296384059038 + 1.5954121367285954 + 1.5955279035506302 + 1.5956436845275923 + 1.5957594796619343 + 1.5958752889561074 + 1.5959911124125583 + 1.5961069500337419 + 1.5962228018221096 + 1.5963386677801135 + 1.5964545479102066 + 1.5965704422148437 + 1.5966863506964755 + 1.5968022733575624 + 1.5969182102005584 + 1.5970341612279142 + 1.5971501264420882 + 1.5972661058455422 + 1.5973820994407326 + 1.5974981072301147 + 1.5976141292161445 + 1.597730165401287 + 1.5978462157880016 + 1.597962280378747 + 1.59807835917598 + 1.5981944521821674 + 1.5983105593997702 + 1.5984266808312513 + 1.5985428164790714 + 1.598658966345696 + 1.5987751304335904 + 1.5988913087452143 + 1.5990075012830398 + 1.5991237080495249 + 1.5992399290471457 + 1.5993561642783582 + 1.5994724137456415 + 1.5995886774514529 + 1.5997049553982696 + 1.5998212475885558 + 1.5999375540247789 + 1.6000538747094151 + 1.6001702096449359 + 1.6002865588338038 + 1.6004029222784986 + 1.6005192999814908 + 1.6006356919452538 + 1.6007520981722585 + 1.6008685186649827 + 1.6009849534258989 + 1.6011014024574819 + 1.6012178657622111 + 1.6013343433425595 + 1.601450835201004 + 1.6015673413400209 + 1.6016838617620959 + 1.601800396469695 + 1.6019169454653086 + 1.6020335087514106 + 1.6021500863304847 + 1.6022666782050095 + 1.6023832843774624 + 1.6024999048503328 + 1.6026165396260965 + 1.6027331887072431 + 1.6028498520962524 + 1.6029665297956091 + 1.6030832218077988 + 1.6031999281353051 + 1.6033166487806141 + 1.6034333837462129 + 1.6035501330345896 + 1.6036668966482277 + 1.6037836745896201 + 1.6039004668612515 + 1.6040172734656146 + 1.6041340944051958 + 1.6042509296824878 + 1.6043677792999815 + 1.6044846432601647 + 1.6046015215655347 + 1.6047184142185797 + 1.6048353212217958 + 1.6049522425776748 + 1.6050691782887103 + 1.6051861283573985 + 1.6053030927862366 + 1.6054200715777154 + 1.6055370647343399 + 1.6056540722585977 + 1.6057710941529875 + 1.6058881304200161 + 1.606005181062172 + 1.6061222460819591 + 1.6062393254818814 + 1.6063564192644286 + 1.6064735274321134 + 1.6065906499874298 + 1.6067077869328803 + 1.6068249382709705 + 1.6069421040042005 + 1.6070592841350766 + 1.6071764786661054 + 1.6072936875997854 + 1.607410910938627 + 1.6075281486851325 + 1.6076454008418104 + 1.6077626674111698 + 1.6078799483957174 + 1.6079972437979597 + 1.6081145536204065 + 1.608231877865566 + 1.6083492165359534 + 1.6084665696340728 + 1.608583937162436 + 1.6087013191235597 + 1.6088187155199503 + 1.6089361263541242 + 1.6090535516285949 + 1.6091709913458734 + 1.6092884455084786 + 1.609405914118921 + 1.6095233971797167 + 1.6096408946933847 + 1.609758406662442 + 1.6098759330894012 + 1.6099934739767863 + 1.6101110293271124 + 1.6102285991428997 + 1.6103461834266639 + 1.6104637821809309 + 1.6105813954082193 + 1.610699023111049 + 1.61081666529194 + 1.6109343219534238 + 1.6110519930980136 + 1.6111696787282341 + 1.6112873788466149 + 1.6114050934556774 + 1.6115228225579477 + 1.6116405661559523 + 1.6117583242522111 + 1.6118760968492625 + 1.6119938839496259 + 1.6121116855558308 + 1.6122295016704085 + 1.6123473322958848 + 1.6124651774347918 + 1.6125830370896568 + 1.6127009112630166 + 1.6128187999573984 + 1.612936703175333 + 1.613054620919359 + 1.6131725531920047 + 1.6132904999958062 + 1.6134084613332962 + 1.6135264372070106 + 1.6136444276194875 + 1.6137624325732569 + 1.6138804520708601 + 1.6139984861148315 + 1.6141165347077147 + 1.6142345978520403 + 1.6143526755503526 + 1.6144707678051904 + 1.6145888746190915 + 1.6147069959946003 + 1.6148251319342537 + 1.6149432824405974 + 1.6150614475161738 + 1.6151796271635213 + 1.6152978213851898 + 1.6154160301837199 + 1.6155342535616513 + 1.6156524915215384 + 1.6157707440659266 + 1.6158890111973532 + 1.6160072929183744 + 1.616125589231536 + 1.6162439001393814 + 1.6163622256444634 + 1.6164805657493331 + 1.6165989204565345 + 1.6167172897686222 + 1.6168356736881486 + 1.6169540722176592 + 1.6170724853597132 + 1.6171909131168605 + 1.6173093554916538 + 1.6174278124866452 + 1.6175462841043953 + 1.6176647703474556 + 1.6177832712183806 + 1.6179017867197238 + 1.6180203168540508 + 1.6181388616239119 + 1.6182574210318665 + 1.6183759950804766 + 1.6184945837722995 + 1.6186131871098897 + 1.6187318050958135 + 1.6188504377326332 + 1.6189690850229042 + 1.6190877469691909 + 1.6192064235740564 + 1.6193251148400654 + 1.6194438207697821 + 1.6195625413657655 + 1.619681276630587 + 1.6198000265668064 + 1.6199187911769939 + 1.6200375704637151 + 1.6201563644295349 + 1.6202751730770275 + 1.6203939964087537 + 1.6205128344272859 + 1.6206316871351965 + 1.6207505545350513 + 1.6208694366294205 + 1.6209883334208803 + 1.6211072449119954 + 1.6212261711053473 + 1.6213451120035036 + 1.6214640676090393 + 1.621583037924524 + 1.6217020229525407 + 1.6218210226956593 + 1.6219400371564563 + 1.6220590663375103 + 1.6221781102413988 + 1.6222971688706962 + 1.6224162422279822 + 1.6225353303158354 + 1.6226544331368393 + 1.6227735506935705 + 1.6228926829886063 + 1.6230118300245342 + 1.6231309918039321 + 1.6232501683293856 + 1.6233693596034737 + 1.6234885656287823 + 1.6236077864078977 + 1.6237270219434006 + 1.6238462722378746 + 1.6239655372939146 + 1.6240848171140987 + 1.6242041117010155 + 1.6243234210572575 + 1.6244427451854073 + 1.6245620840880557 + 1.6246814377677923 + 1.6248008062272083 + 1.6249201894688916 + 1.6250395874954342 + 1.6251590003094314 + 1.6252784279134729 + 1.6253978703101506 + 1.6255173275020596 + 1.6256367994917926 + 1.6257562862819446 + 1.6258757878751129 + 1.6259953042738906 + 1.6261148354808763 + 1.6262343814986695 + 1.6263539423298596 + 1.6264735179770542 + 1.6265931084428435 + 1.6267127137298363 + 1.6268323338406263 + 1.6269519687778136 + 1.6270716185440033 + 1.627191283141795 + 1.6273109625737929 + 1.6274306568426 + 1.6275503659508139 + 1.6276700899010466 + 1.6277898286958927 + 1.6279095823379719 + 1.6280293508298793 + 1.6281491341742256 + 1.6282689323736173 + 1.6283887454306625 + 1.6285085733479676 + 1.6286284161281452 + 1.6287482737738006 + 1.6288681462875463 + 1.628988033671988 + 1.6291079359297467 + 1.6292278530634285 + 1.6293477850756453 + 1.6294677319690112 + 1.6295876937461375 + 1.6297076704096409 + 1.6298276619621406 + 1.6299476684062417 + 1.6300676897445696 + 1.6301877259797373 + 1.6303077771143593 + 1.6304278431510577 + 1.630547924092451 + 1.6306680199411543 + 1.6307881306997909 + 1.6309082563709776 + 1.6310283969573389 + 1.6311485524614906 + 1.6312687228860627 + 1.6313889082336683 + 1.6315091085069413 + 1.6316293237084971 + 1.6317495538409623 + 1.6318697989069637 + 1.6319900589091283 + 1.6321103338500742 + 1.6322306237324367 + 1.6323509285588369 + 1.6324712483319115 + 1.6325915830542761 + 1.6327119327285711 + 1.6328322973574236 + 1.6329526769434572 + 1.6330730714893111 + 1.6331934809976161 + 1.6333139054709982 + 1.6334343449120929 + 1.633554799323538 + 1.6336752687079659 + 1.6337957530680041 + 1.6339162524062978 + 1.634036766725474 + 1.6341572960281727 + 1.6342778403170324 + 1.6343983995946889 + 1.6345189738637804 + 1.6346395631269459 + 1.6347601673868277 + 1.6348807866460591 + 1.6350014209072861 + 1.6351220701731444 + 1.635242734446283 + 1.6353634137293389 + 1.6354841080249582 + 1.6356048173357793 + 1.6357255416644534 + 1.6358462810136212 + 1.6359670353859255 + 1.6360878047840188 + 1.6362085892105447 + 1.6363293886681485 + 1.6364502031594783 + 1.6365710326871852 + 1.6366918772539174 + 1.63681273686232 + 1.6369336115150488 + 1.6370545012147526 + 1.637175405964082 + 1.6372963257656914 + 1.6374172606222301 + 1.6375382105363536 + 1.6376591755107133 + 1.6377801555479652 + 1.6379011506507655 + 1.6380221608217695 + 1.6381431860636317 + 1.638264226379009 + 1.6383852817705591 + 1.6385063522409444 + 1.6386274377928158 + 1.6387485384288363 + 1.638869654151669 + 1.6389907849639669 + 1.6391119308683975 + 1.6392330918676219 + 1.6393542679642972 + 1.6394754591610927 + 1.6395966654606711 + 1.639717886865691 + 1.6398391233788228 + 1.6399603750027301 + 1.6400816417400763 + 1.640202923593534 + 1.6403242205657604 + 1.6404455326594312 + 1.640566859877217 + 1.6406882022217788 + 1.6408095596957915 + 1.6409309323019214 + 1.641052320042844 + 1.6411737229212267 + 1.6412951409397456 + 1.6414165741010691 + 1.6415380224078735 + 1.6416594858628293 + 1.641780964468617 + 1.6419024582279038 + 1.6420239671433714 + 1.6421454912176945 + 1.64226703045355 + 1.6423885848536119 + 1.6425101544205656 + 1.6426317391570837 + 1.6427533390658469 + 1.6428749541495371 + 1.6429965844108319 + 1.6431182298524143 + 1.6432398904769663 + 1.6433615662871708 + 1.643483257285709 + 1.6436049634752641 + 1.6437266848585284 + 1.643848421438175 + 1.6439701732168936 + 1.6440919401973733 + 1.644213722382301 + 1.6443355197743588 + 1.6444573323762384 + 1.6445791601906272 + 1.6447010032202163 + 1.644822861467691 + 1.6449447349357476 + 1.6450666236270719 + 1.6451885275443605 + 1.6453104466903037 + 1.6454323810675893 + 1.6455543306789189 + 1.6456762955269801 + 1.6457982756144729 + 1.6459202709440894 + 1.6460422815185261 + 1.6461643073404804 + 1.6462863484126462 + 1.6464084047377241 + 1.6465304763184139 + 1.6466525631574129 + 1.6467746652574216 + 1.6468967826211389 + 1.6470189152512658 + 1.6471410631505055 + 1.6472632263215563 + 1.6473854047671266 + 1.6475075984899143 + 1.6476298074926261 + 1.6477520317779681 + 1.6478742713486401 + 1.6479965262073566 + 1.6481187963568145 + 1.6482410817997262 + 1.6483633825388035 + 1.6484856985767444 + 1.6486080299162633 + 1.6487303765600727 + 1.64885273851088 + 1.6489751157713926 + 1.6490975083443251 + 1.6492199162323937 + 1.6493423394383029 + 1.6494647779647731 + 1.6495872318145135 + 1.6497097009902377 + 1.6498321854946678 + 1.6499546853305103 + 1.6500772005004916 + 1.6501997310073195 + 1.6503222768537171 + 1.6504448380424017 + 1.6505674145760927 + 1.6506900064575081 + 1.6508126136893655 + 1.6509352362743897 + 1.6510578742153035 + 1.6511805275148257 + 1.6513031961756797 + 1.6514258802005892 + 1.6515485795922746 + 1.6516712943534673 + 1.6517940244868892 + 1.6519167699952615 + 1.6520395308813178 + 1.6521623071477807 + 1.6522850987973769 + 1.6524079058328371 + 1.6525307282568931 + 1.652653566072269 + 1.6527764192816974 + 1.6528992878879105 + 1.6530221718936344 + 1.6531450713016058 + 1.6532679861145561 + 1.6533909163352196 + 1.6535138619663274 + 1.6536368230106178 + 1.6537597994708206 + 1.653882791349679 + 1.6540057986499257 + 1.6541288213742944 + 1.6542518595255236 + 1.6543749131063576 + 1.6544979821195323 + 1.6546210665677861 + 1.6547441664538551 + 1.6548672817804901 + 1.654990412550424 + 1.6551135587664023 + 1.6552367204311651 + 1.6553598975474582 + 1.655483090118028 + 1.6556062981456134 + 1.6557295216329642 + 1.6558527605828242 + 1.6559760149979417 + 1.6560992848810612 + 1.6562225702349267 + 1.6563458710622989 + 1.656469187365913 + 1.6565925191485298 + 1.6567158664128916 + 1.6568392291617542 + 1.6569626073978683 + 1.6570860011239819 + 1.6572094103428514 + 1.6573328350572332 + 1.6574562752698769 + 1.6575797309835352 + 1.6577032022009701 + 1.6578266889249333 + 1.6579501911581791 + 1.6580737089034701 + 1.6581972421635622 + 1.6583207909412125 + 1.6584443552391812 + 1.6585679350602289 + 1.6586915304071137 + 1.6588151412826009 + 1.6589387676894425 + 1.6590624096304121 + 1.6591860671082685 + 1.6593097401257764 + 1.6594334286856953 + 1.6595571327907952 + 1.6596808524438396 + 1.6598045876475946 + 1.6599283384048262 + 1.660052104718305 + 1.6601758865907938 + 1.6602996840250639 + 1.6604234970238902 + 1.660547325590034 + 1.6606711697262675 + 1.6607950294353642 + 1.6609189047200965 + 1.6610427955832352 + 1.6611667020275551 + 1.6612906240558261 + 1.6614145616708278 + 1.6615385148753326 + 1.6616624836721197 + 1.6617864680639587 + 1.6619104680536294 + 1.6620344836439109 + 1.6621585148375804 + 1.6622825616374195 + 1.6624066240462045 + 1.6625307020667142 + 1.6626547957017319 + 1.6627789049540418 + 1.6629030298264214 + 1.6630271703216517 + 1.6631513264425255 + 1.663275498191817 + 1.663399685572313 + 1.6635238885868038 + 1.6636481072380696 + 1.6637723415289016 + 1.6638965914620838 + 1.6640208570404023 + 1.6641451382666481 + 1.664269435143616 + 1.6643937476740844 + 1.6645180758608551 + 1.6646424197067109 + 1.6647667792144472 + 1.6648911543868565 + 1.665015545226727 + 1.665139951736859 + 1.665264373920045 + 1.6653888117790796 + 1.6655132653167533 + 1.6656377345358715 + 1.6657622194392256 + 1.6658867200296148 + 1.6660112363098361 + 1.6661357682826881 + 1.6662603159509688 + 1.6663848793174829 + 1.6665094583850284 + 1.6666340531564074 + 1.6667586636344183 + 1.6668832898218682 + 1.6670079317215609 + 1.6671325893362992 + 1.6672572626688884 + 1.6673819517221293 + 1.667506656498835 + 1.6676313770018076 + 1.6677561132338528 + 1.6678808651977817 + 1.668005632896405 + 1.6681304163325259 + 1.6682552155089581 + 1.6683800304285081 + 1.6685048610939932 + 1.6686297075082235 + 1.6687545696740087 + 1.6688794475941626 + 1.6690043412714963 + 1.6691292507088324 + 1.6692541759089796 + 1.6693791168747529 + 1.669504073608973 + 1.6696290461144536 + 1.6697540343940154 + 1.6698790384504689 + 1.6700040582866476 + 1.6701290939053555 + 1.6702541453094186 + 1.6703792125016621 + 1.6705042954849005 + 1.6706293942619634 + 1.6707545088356681 + 1.6708796392088399 + 1.6710047853843042 + 1.671129947364884 + 1.6712551251534029 + 1.6713803187526906 + 1.6715055281655757 + 1.6716307533948791 + 1.6717559944434333 + 1.6718812513140668 + 1.6720065240096096 + 1.6721318125328881 + 1.6722571168867364 + 1.6723824370739859 + 1.6725077730974642 + 1.6726331249600073 + 1.6727584926644503 + 1.6728838762136276 + 1.6730092756103678 + 1.6731346908575091 + 1.6732601219578926 + 1.6733855689143466 + 1.6735110317297135 + 1.673636510406832 + 1.6737620049485396 + 1.673887515357672 + 1.6740130416370709 + 1.6741385837895775 + 1.6742641418180362 + 1.6743897157252836 + 1.6745153055141613 + 1.6746409111875205 + 1.6747665327481973 + 1.67489217019904 + 1.675017823542893 + 1.6751434927826017 + 1.6752691779210112 + 1.6753948789609716 + 1.6755205959053299 + 1.6756463287569325 + 1.6757720775186309 + 1.6758978421932733 + 1.6760236227837086 + 1.6761494192927919 + 1.676275231723374 + 1.6764010600783039 + 1.6765269043604396 + 1.6766527645726323 + 1.6767786407177336 + 1.6769045327986021 + 1.677030440818094 + 1.6771563647790657 + 1.6772823046843701 + 1.6774082605368696 + 1.6775342323394176 + 1.6776602200948796 + 1.677786223806111 + 1.6779122434759717 + 1.6780382791073245 + 1.6781643307030338 + 1.6782903982659532 + 1.6784164817989584 + 1.6785425813049 + 1.6786686967866513 + 1.6787948282470722 + 1.678920975689032 + 1.6790471391153949 + 1.6791733185290292 + 1.6792995139328024 + 1.6794257253295806 + 1.6795519527222358 + 1.6796781961136344 + 1.6798044555066505 + 1.6799307309041549 + 1.6800570223090152 + 1.6801833297241064 + 1.680309653152301 + 1.6804359925964749 + 1.6805623480594982 + 1.6806887195442475 + 1.6808151070536015 + 1.6809415105904337 + 1.6810679301576199 + 1.6811943657580388 + 1.6813208173945713 + 1.6814472850700961 + 1.6815737687874874 + 1.6817002685496298 + 1.6818267843594048 + 1.6819533162196951 + 1.6820798641333792 + 1.6822064281033404 + 1.6823330081324652 + 1.6824596042236355 + 1.6825862163797423 + 1.6827128446036628 + 1.6828394888982836 + 1.6829661492665011 + 1.6830928257111946 + 1.6832195182352545 + 1.6833462268415724 + 1.6834729515330324 + 1.6835996923125338 + 1.6837264491829584 + 1.6838532221472031 + 1.6839800112081575 + 1.6841068163687194 + 1.6842336376317797 + 1.6843604750002299 + 1.684487328476969 + 1.6846141980648894 + 1.6847410837668912 + 1.6848679855858717 + 1.6849949035247245 + 1.6851218375863513 + 1.6852487877736504 + 1.6853757540895242 + 1.6855027365368689 + 1.685629735118588 + 1.6857567498375823 + 1.6858837806967553 + 1.686010827699006 + 1.6861378908472497 + 1.6862649701443788 + 1.6863920655933027 + 1.686519177196925 + 1.686646304958161 + 1.6867734488799073 + 1.6869006089650798 + 1.6870277852165836 + 1.6871549776373245 + 1.6872821862302203 + 1.6874094109981732 + 1.6875366519441024 + 1.6876639090709116 + 1.6877911823815237 + 1.6879184718788438 + 1.6880457775657884 + 1.6881730994452711 + 1.6883004375202095 + 1.6884277917935213 + 1.6885551622681176 + 1.6886825489469182 + 1.6888099518328461 + 1.6889373709288127 + 1.6890648062377402 + 1.6891922577625527 + 1.6893197255061636 + 1.6894472094714994 + 1.6895747096614826 + 1.6897022260790322 + 1.689829758727075 + 1.6899573076085357 + 1.6900848727263382 + 1.6902124540834083 + 1.6903400516826703 + 1.6904676655270545 + 1.6905952956194834 + 1.6907229419628913 + 1.6908506045602021 + 1.690978283414351 + 1.6911059785282629 + 1.6912336899048737 + 1.6913614175471126 + 1.6914891614579104 + 1.6916169216402035 + 1.6917446980969209 + 1.6918724908310032 + 1.6920002998453834 + 1.6921281251429938 + 1.6922559667267776 + 1.6923838245996656 + 1.6925116987646014 + 1.6926395892245167 + 1.6927674959823569 + 1.692895419041061 + 1.693023358403565 + 1.6931513140728125 + 1.6932792860517516 + 1.6934072743433159 + 1.6935352789504539 + 1.6936632998761079 + 1.6937913371232243 + 1.6939193906947496 + 1.6940474605936233 + 1.6941755468228006 + 1.6943036493852262 + 1.6944317682838455 + 1.6945599035216101 + 1.6946880551014669 + 1.6948162230263701 + 1.6949444072992699 + 1.6950726079231133 + 1.6952008249008597 + 1.6953290582354543 + 1.6954573079298567 + 1.6955855739870203 + 1.6957138564098986 + 1.69584215520145 + 1.6959704703646281 + 1.6960988019023924 + 1.6962271498176988 + 1.6963555141135065 + 1.6964838947927767 + 1.6966122918584658 + 1.6967407053135353 + 1.6968691351609475 + 1.696997581403668 + 1.6971260440446523 + 1.6972545230868681 + 1.6973830185332779 + 1.6975115303868511 + 1.6976400586505482 + 1.6977686033273347 + 1.6978971644201806 + 1.698025741932051 + 1.6981543358659184 + 1.6982829462247442 + 1.6984115730115061 + 1.6985402162291701 + 1.6986688758807069 + 1.6987975519690923 + 1.6989262444972928 + 1.6990549534682866 + 1.6991836788850434 + 1.6993124207505392 + 1.6994411790677497 + 1.6995699538396547 + 1.6996987450692262 + 1.6998275527594426 + 1.6999563769132802 + 1.7000852175337182 + 1.7002140746237382 + 1.7003429481863155 + 1.7004718382244417 + 1.7006007447410854 + 1.7007296677392345 + 1.7008586072218739 + 1.7009875631919817 + 1.7011165356525473 + 1.701245524606557 + 1.70137453005699 + 1.701503552006834 + 1.7016325904590812 + 1.7017616454167188 + 1.7018907168827291 + 1.7020198048601047 + 1.7021489093518358 + 1.7022780303609124 + 1.7024071678903263 + 1.7025363219430716 + 1.7026654925221374 + 1.7027946796305191 + 1.7029238832712066 + 1.7030531034472034 + 1.7031823401614974 + 1.7033115934170859 + 1.7034408632169673 + 1.703570149564142 + 1.7036994524616009 + 1.703828771912353 + 1.7039581079193862 + 1.7040874604857106 + 1.7042168296143239 + 1.7043462153082278 + 1.7044756175704212 + 1.704605036403916 + 1.704734471811707 + 1.7048639237968035 + 1.7049933923622129 + 1.7051228775109339 + 1.7052523792459831 + 1.7053818975703592 + 1.7055114324870768 + 1.7056409839991393 + 1.7057705521095581 + 1.7059001368213456 + 1.7060297381375102 + 1.7061593560610691 + 1.7062889905950245 + 1.7064186417423983 + 1.7065483095062011 + 1.7066779938894481 + 1.7068076948951509 + 1.7069374125263335 + 1.707067146786005 + 1.7071968976771865 + 1.7073266652028951 + 1.7074564493661459 + 1.7075862501699608 + 1.7077160676173628 + 1.7078459017113756 + 1.7079757524550123 + 1.7081056198513005 + 1.708235503903262 + 1.7083654046139212 + 1.7084953219862979 + 1.7086252560234256 + 1.7087552067283203 + 1.7088851741040199 + 1.7090151581535429 + 1.70914515887992 + 1.7092751762861811 + 1.7094052103753519 + 1.7095352611504664 + 1.7096653286145591 + 1.7097954127706496 + 1.7099255136217806 + 1.7100556311709809 + 1.7101857654212833 + 1.7103159163757278 + 1.7104460840373417 + 1.7105762684091659 + 1.7107064694942387 + 1.7108366872955891 + 1.7109669218162629 + 1.7110971730592999 + 1.7112274410277308 + 1.7113577257246031 + 1.7114880271529549 + 1.7116183453158318 + 1.7117486802162658 + 1.7118790318573107 + 1.7120094002420063 + 1.7121397853733933 + 1.7122701872545241 + 1.7124006058884398 + 1.7125310412781858 + 1.7126614934268125 + 1.7127919623373671 + 1.7129224480128999 + 1.7130529504564582 + 1.7131834696710915 + 1.7133140056598517 + 1.713444558425788 + 1.713575127971958 + 1.7137057143014116 + 1.7138363174172004 + 1.7139669373223829 + 1.7140975740200146 + 1.7142282275131446 + 1.7143588978048367 + 1.7144895848981445 + 1.7146202887961335 + 1.7147510095018463 + 1.7148817470183608 + 1.715012501348725 + 1.7151432724960032 + 1.7152740604632581 + 1.7154048652535516 + 1.7155356868699481 + 1.7156665253155097 + 1.7157973805932996 + 1.7159282527063835 + 1.7160591416578288 + 1.7161900474507068 + 1.7163209700880748 + 1.7164519095730133 + 1.716582865908576 + 1.7167138390978471 + 1.7168448291438871 + 1.7169758360497729 + 1.7171068598185728 + 1.7172379004533593 + 1.7173689579572071 + 1.7175000323331906 + 1.7176311235843824 + 1.7177622317138603 + 1.717893356724699 + 1.718024498619974 + 1.718155657402767 + 1.7182868330761556 + 1.7184180256432153 + 1.7185492351070233 + 1.718680461470669 + 1.7188117047372264 + 1.718942964909782 + 1.7190742419914151 + 1.7192055359852125 + 1.7193368468942543 + 1.7194681747216298 + 1.7195995194704192 + 1.7197308811437124 + 1.7198622597445994 + 1.7199936552761588 + 1.7201250677414892 + 1.7202564971436709 + 1.7203879434858034 + 1.7205194067709679 + 1.7206508870022612 + 1.7207823841827727 + 1.7209138983156009 + 1.7210454294038287 + 1.7211769774505623 + 1.7213085424588899 + 1.7214401244319122 + 1.7215717233727172 + 1.7217033392844103 + 1.7218349721700894 + 1.7219666220328449 + 1.7220982888757832 + 1.7222299727020038 + 1.7223616735146063 + 1.7224933913166949 + 1.722625126111367 + 1.7227568779017315 + 1.7228886466908868 + 1.723020432481942 + 1.7231522352779973 + 1.7232840550821673 + 1.7234158918975484 + 1.7235477457272568 + 1.7236796165743937 + 1.7238115044420723 + 1.7239434093334023 + 1.7240753312514947 + 1.724207270199456 + 1.7243392261804025 + 1.7244711991974457 + 1.7246031892536979 + 1.724735196352277 + 1.7248672204962958 + 1.724999261688869 + 1.7251313199331109 + 1.7252633952321448 + 1.7253954875890785 + 1.7255275970070438 + 1.7256597234891491 + 1.7257918670385173 + 1.7259240276582721 + 1.7260562053515327 + 1.7261884001214216 + 1.7263206119710626 + 1.7264528409035793 + 1.7265850869220956 + 1.7267173500297333 + 1.7268496302296248 + 1.7269819275248925 + 1.7271142419186667 + 1.7272465734140707 + 1.727378922014239 + 1.7275112877223007 + 1.7276436705413791 + 1.7277760704746163 + 1.7279084875251334 + 1.728040921696069 + 1.7281733729905606 + 1.7283058414117323 + 1.7284383269627233 + 1.7285708296466731 + 1.7287033494667121 + 1.7288358864259796 + 1.7289684405276149 + 1.7291010117747549 + 1.7292336001705391 + 1.729366205718107 + 1.7294988284206017 + 1.729631468281164 + 1.7297641253029308 + 1.7298967994890551 + 1.7300294908426712 + 1.7301621993669292 + 1.7302949250649724 + 1.7304276679399477 + 1.7305604279949995 + 1.7306932052332804 + 1.7308259996579352 + 1.7309588112721097 + 1.731091640078958 + 1.731224486081631 + 1.731357349283279 + 1.73149022968705 + 1.7316231272961009 + 1.7317560421135871 + 1.7318889741426591 + 1.732021923386474 + 1.7321548898481827 + 1.7322878735309473 + 1.7324208744379235 + 1.7325538925722668 + 1.7326869279371386 + 1.7328199805356987 + 1.7329530503711053 + 1.7330861374465201 + 1.7332192417651056 + 1.7333523633300247 + 1.7334855021444415 + 1.7336186582115118 + 1.733751831534412 + 1.7338850221162996 + 1.7340182299603402 + 1.7341514550697119 + 1.7342846974475692 + 1.7344179570970839 + 1.734551234021428 + 1.7346845282237728 + 1.7348178397072882 + 1.7349511684751424 + 1.7350845145305069 + 1.735217877876559 + 1.7353512585164699 + 1.7354846564534154 + 1.7356180716905716 + 1.735751504231114 + 1.7358849540782169 + 1.7360184212350578 + 1.7361519057048185 + 1.7362854074906742 + 1.7364189265958072 + 1.7365524630233977 + 1.7366860167766265 + 1.7368195878586776 + 1.736953176272729 + 1.7370867820219664 + 1.7372204051095765 + 1.7373540455387451 + 1.7374877033126528 + 1.7376213784344918 + 1.7377550709074454 + 1.7378887807347001 + 1.7380225079194522 + 1.738156252464885 + 1.7382900143741886 + 1.7384237936505622 + 1.7385575902971859 + 1.7386914043172594 + 1.7388252357139762 + 1.7389590844905292 + 1.739092950650112 + 1.7392268341959201 + 1.7393607351311517 + 1.7394946534590059 + 1.739628589182679 + 1.7397625423053684 + 1.7398965128302746 + 1.740030500760595 + 1.7401645060995361 + 1.7402985288502959 + 1.7404325690160787 + 1.7405666266000841 + 1.7407007016055234 + 1.7408347940355946 + 1.7409689038935034 + 1.741103031182462 + 1.7412371759056737 + 1.7413713380663463 + 1.741505517667687 + 1.7416397147129112 + 1.7417739292052197 + 1.7419081611478338 + 1.7420424105439556 + 1.7421766773968033 + 1.7423109617095904 + 1.7424452634855299 + 1.7425795827278363 + 1.7427139194397232 + 1.7428482736244071 + 1.7429826452851087 + 1.7431170344250426 + 1.743251441047428 + 1.743385865155487 + 1.7435203067524392 + 1.7436547658415016 + 1.7437892424258943 + 1.7439237365088465 + 1.7440582480935767 + 1.7441927771833139 + 1.7443273237812786 + 1.7444618878906968 + 1.7445964695147933 + 1.7447310686568003 + 1.7448656853199385 + 1.7450003195074384 + 1.7451349712225372 + 1.7452696404684542 + 1.7454043272484283 + 1.7455390315656873 + 1.7456737534234634 + 1.7458084928249931 + 1.7459432497735063 + 1.7460780242722374 + 1.7462128163244277 + 1.7463476259333093 + 1.7464824531021166 + 1.7466172978340948 + 1.746752160132476 + 1.7468870400005012 + 1.7470219374414124 + 1.7471568524584482 + 1.7472917850548548 + 1.7474267352338679 + 1.7475617029987351 + 1.747696688352701 + 1.7478316912990035 + 1.7479667118408986 + 1.7481017499816296 + 1.7482368057244382 + 1.7483718790725762 + 1.7485069700292912 + 1.7486420785978354 + 1.748777204781454 + 1.7489123485834035 + 1.7490475100069343 + 1.7491826890552935 + 1.7493178857317395 + 1.7494531000395273 + 1.7495883319819097 + 1.7497235815621437 + 1.7498588487834821 + 1.749994133649186 + 1.7501294361625148 + 1.7502647563267222 + 1.7504000941450728 + 1.7505354496208219 + 1.7506708227572343 + 1.7508062135575702 + 1.7509416220250924 + 1.751077048163066 + 1.7512124919747547 + 1.7513479534634204 + 1.7514834326323288 + 1.751618929484754 + 1.7517544440239585 + 1.7518899762532072 + 1.7520255261757738 + 1.7521610937949259 + 1.7522966791139372 + 1.7524322821360723 + 1.7525679028646108 + 1.7527035413028187 + 1.7528391974539714 + 1.752974871321348 + 1.7531105629082191 + 1.7532462722178623 + 1.7533819992535551 + 1.7535177440185716 + 1.7536535065161936 + 1.753789286749698 + 1.7539250847223664 + 1.7540609004374772 + 1.7541967338983171 + 1.7543325851081617 + 1.7544684540702986 + 1.7546043407880085 + 1.7547402452645806 + 1.754876167503296 + 1.7550121075074412 + 1.7551480652803035 + 1.7552840408251693 + 1.7554200341453343 + 1.7555560452440793 + 1.7556920741246973 + 1.7558281207904816 + 1.7559641852447185 + 1.756100267490706 + 1.7562363675317401 + 1.7563724853711038 + 1.7565086210120973 + 1.756644774458022 + 1.7567809457121668 + 1.7569171347778303 + 1.7570533416583105 + 1.7571895663569101 + 1.7573258088769292 + 1.7574620692216598 + 1.757598347394407 + 1.7577346433984757 + 1.7578709572371709 + 1.758007288913789 + 1.7581436384316353 + 1.7582800057940218 + 1.758416391004245 + 1.7585527940656209 + 1.758689214981447 + 1.7588256537550411 + 1.7589621103897051 + 1.7590985848887541 + 1.7592350772554957 + 1.7593715874932458 + 1.7595081156053094 + 1.7596446615950023 + 1.7597812254656435 + 1.7599178072205428 + 1.7600544068630148 + 1.7601910243963748 + 1.760327659823947 + 1.7604643131490436 + 1.7606009843749821 + 1.7607376735050877 + 1.7608743805426748 + 1.761011105491066 + 1.7611478483535843 + 1.7612846091335499 + 1.7614213878342913 + 1.761558184459129 + 1.7616949990113853 + 1.761831831494389 + 1.7619686819114719 + 1.7621055502659531 + 1.7622424365611642 + 1.7623793408004336 + 1.7625162629870943 + 1.7626532031244717 + 1.7627901612158994 + 1.7629271372647122 + 1.7630641312742379 + 1.7632011432478156 + 1.7633381731887743 + 1.7634752211004538 + 1.7636122869861928 + 1.7637493708493199 + 1.7638864726931791 + 1.7640235925211081 + 1.7641607303364435 + 1.7642978861425296 + 1.7644350599427037 + 1.7645722517403133 + 1.764709461538694 + 1.7648466893411925 + 1.7649839351511545 + 1.7651211989719209 + 1.7652584808068434 + 1.7653957806592635 + 1.7655330985325295 + 1.7656704344299914 + 1.7658077883549967 + 1.7659451603108958 + 1.7660825503010402 + 1.7662199583287825 + 1.7663573843974718 + 1.7664948285104642 + 1.7666322906711074 + 1.7667697708827659 + 1.7669072691487884 + 1.7670447854725337 + 1.7671823198573582 + 1.767319872306615 + 1.7674574428236722 + 1.7675950314118818 + 1.7677326380746119 + 1.7678702628152154 + 1.7680079056370552 + 1.7681455665434993 + 1.7682832455379127 + 1.7684209426236495 + 1.7685586578040859 + 1.7686963910825777 + 1.7688341424625 + 1.7689719119472198 + 1.769109699540101 + 1.7692475052445173 + 1.7693853290638299 + 1.7695231710014241 + 1.7696610310606629 + 1.7697989092449169 + 1.7699368055575664 + 1.7700747200019751 + 1.7702126525815278 + 1.7703506032995979 + 1.77048857215956 + 1.7706265591647958 + 1.7707645643186762 + 1.7709025876245854 + 1.7710406290858998 + 1.7711786887060037 + 1.7713167664882785 + 1.7714548624361024 + 1.771592976552866 + 1.7717311088419445 + 1.7718692593067253 + 1.7720074279505964 + 1.7721456147769432 + 1.7722838197891548 + 1.7724220429906132 + 1.7725602843847132 + 1.7726985439748417 + 1.7728368217643902 + 1.7729751177567477 + 1.7731134319553108 + 1.7732517643634644 + 1.773390114984611 + 1.7735284838221417 + 1.7736668708794503 + 1.7738052761599343 + 1.7739436996669926 + 1.7740821414040191 + 1.7742206013744151 + 1.774359079581578 + 1.7744975760289112 + 1.7746360907198135 + 1.7747746236576891 + 1.7749131748459384 + 1.7750517442879625 + 1.7751903319871698 + 1.7753289379469677 + 1.7754675621707547 + 1.7756062046619459 + 1.7757448654239414 + 1.7758835444601577 + 1.776022241773995 + 1.7761609573688717 + 1.7762996912481908 + 1.7764384434153693 + 1.7765772138738201 + 1.7767160026269582 + 1.7768548096781964 + 1.7769936350309441 + 1.7771324786886229 + 1.7772713406546472 + 1.7774102209324356 + 1.7775491195254074 + 1.7776880364369834 + 1.777826971670579 + 1.7779659252296167 + 1.7781048971175175 + 1.7782438873377078 + 1.7783828958936077 + 1.7785219227886386 + 1.7786609680262346 + 1.7788000316098116 + 1.778939113542799 + 1.7790782138286263 + 1.779217332470725 + 1.779356469472517 + 1.779495624837435 + 1.7796347985689138 + 1.77977399067038 + 1.7799132011452699 + 1.7800524299970093 + 1.7801916772290414 + 1.7803309428447933 + 1.7804702268477086 + 1.7806095292412196 + 1.7807488500287634 + 1.7808881892137807 + 1.781027546799707 + 1.7811669227899845 + 1.7813063171880554 + 1.7814457299973574 + 1.7815851612213374 + 1.7817246108634333 + 1.7818640789270948 + 1.7820035654157671 + 1.7821430703328864 + 1.7822825936819113 + 1.7824221354662817 + 1.7825616956894508 + 1.7827012743548631 + 1.7828408714659683 + 1.782980487026222 + 1.7831201210390737 + 1.7832597735079718 + 1.7833994444363797 + 1.7835391338277431 + 1.7836788416855107 + 1.7838185680131564 + 1.7839583128141225 + 1.7840980760918723 + 1.7842378578498623 + 1.7843776580915476 + 1.7845174768203977 + 1.784657314039866 + 1.784797169753418 + 1.7849370439645165 + 1.7850769366766175 + 1.7852168478931925 + 1.7853567776177088 + 1.7854967258536212 + 1.78563669260441 + 1.7857766778735307 + 1.7859166816644605 + 1.7860567039806601 + 1.7861967448256122 + 1.786336804202775 + 1.7864768821156249 + 1.7866169785676389 + 1.7867570935622807 + 1.7868972271030368 + 1.7870373791933707 + 1.7871775498367661 + 1.7873177390366963 + 1.7874579467966387 + 1.7875981731200745 + 1.7877384180104792 + 1.7878786814713357 + 1.7880189635061277 + 1.7881592641183273 + 1.7882995833114277 + 1.7884399210889104 + 1.7885802774542532 + 1.7887206524109509 + 1.7888610459624836 + 1.7890014581123383 + 1.7891418888640005 + 1.7892823382209659 + 1.7894228061867217 + 1.7895632927647531 + 1.7897037979585553 + 1.7898443217716209 + 1.7899848642074443 + 1.790125425269512 + 1.7902660049613237 + 1.7904066032863781 + 1.7905472202481658 + 1.7906878558501855 + 1.7908285100959336 + 1.7909691829889103 + 1.7911098745326197 + 1.7912505847305558 + 1.7913913135862216 + 1.7915320611031222 + 1.7916728272847584 + 1.7918136121346333 + 1.7919544156562521 + 1.7920952378531234 + 1.7922360787287492 + 1.7923769382866392 + 1.7925178165303013 + 1.7926587134632428 + 1.7927996290889798 + 1.7929405634110125 + 1.7930815164328633 + 1.7932224881580379 + 1.7933634785900501 + 1.7935044877324158 + 1.7936455155886504 + 1.7937865621622706 + 1.7939276274567897 + 1.7940687114757283 + 1.794209814222598 + 1.7943509357009284 + 1.7944920759142353 + 1.7946332348660348 + 1.7947744125598597 + 1.7949156089992229 + 1.7950568241876506 + 1.7951980581286688 + 1.7953393108258016 + 1.795480582282575 + 1.795621872502515 + 1.7957631814891533 + 1.7959045092460153 + 1.7960458557766286 + 1.7961872210845302 + 1.7963286051732439 + 1.7964700080463101 + 1.7966114297072531 + 1.7967528701596143 + 1.7968943294069188 + 1.7970358074527135 + 1.7971773043005292 + 1.7973188199539014 + 1.7974603544163708 + 1.7976019076914811 + 1.7977434797827629 + 1.7978850706937617 + 1.7980266804280198 + 1.798168308989077 + 1.798309956380477 + 1.7984516226057679 + 1.7985933076684919 + 1.7987350115721934 + 1.7988767343204233 + 1.7990184759167243 + 1.7991602363646484 + 1.7993020156677466 + 1.7994438138295612 + 1.7995856308536524 + 1.799727466743567 + 1.7998693215028629 + 1.8000111951350879 + 1.8001530876438006 + 1.800294999032551 + 1.8004369293049001 + 1.8005788784644081 + 1.8007208465146225 + 1.8008628334591172 + 1.8010048393014371 + 1.8011468640451529 + 1.8012889076938228 + 1.8014309702510067 + 1.8015730517202715 + 1.8017151521051833 + 1.8018572714092973 + 1.80199940963619 + 1.8021415667894249 + 1.8022837428725638 + 1.8024259378891874 + 1.8025681518428551 + 1.8027103847371375 + 1.8028526365756055 + 1.8029949073618401 + 1.8031371970994015 + 1.8032795057918709 + 1.8034218334428271 + 1.8035641800558357 + 1.8037065456344761 + 1.8038489301823293 + 1.8039913337029705 + 1.8041337561999768 + 1.8042761976769306 + 1.8044186581374142 + 1.8045611375850057 + 1.80470363602329 + 1.8048461534558495 + 1.8049886898862664 + 1.8051312453181299 + 1.8052738197550218 + 1.8054164132005288 + 1.8055590256582457 + 1.8057016571317495 + 1.805844307624644 + 1.8059869771405062 + 1.806129665682934 + 1.8062723732555184 + 1.8064150998618538 + 1.8065578455055318 + 1.8067006101901448 + 1.8068433939192938 + 1.8069861966965719 + 1.8071290185255777 + 1.80727185940991 + 1.807414719353168 + 1.8075575983589476 + 1.8077004964308534 + 1.8078434135724901 + 1.8079863497874531 + 1.8081293050793514 + 1.8082722794517847 + 1.8084152729083653 + 1.8085582854526923 + 1.8087013170883761 + 1.8088443678190249 + 1.8089874376482462 + 1.8091305265796538 + 1.8092736346168521 + 1.8094167617634529 + 1.8095599080230731 + 1.8097030733993216 + 1.8098462578958205 + 1.8099894615161729 + 1.8101326842640062 + 1.8102759261429269 + 1.8104191871565571 + 1.8105624673085174 + 1.8107057666024253 + 1.8108490850419035 + 1.8109924226305709 + 1.8111357793720471 + 1.8112791552699565 + 1.811422550327928 + 1.8115659645495827 + 1.8117093979385435 + 1.8118528504984368 + 1.8119963222328945 + 1.812139813145544 + 1.812283323240014 + 1.8124268525199345 + 1.812570400988931 + 1.8127139686506462 + 1.812857555508707 + 1.8130011615667458 + 1.8131447868283987 + 1.8132884312972986 + 1.8134320949770841 + 1.8135757778713961 + 1.8137194799838636 + 1.8138632013181362 + 1.8140069418778439 + 1.8141507016666341 + 1.8142944806881454 + 1.8144382789460234 + 1.8145820964439074 + 1.8147259331854448 + 1.8148697891742791 + 1.8150136644140553 + 1.8151575589084268 + 1.8153014726610357 + 1.8154454056755289 + 1.8155893579555609 + 1.8157333295047835 + 1.8158773203268419 + 1.8160213304253929 + 1.8161653598040868 + 1.816309408466581 + 1.8164534764165317 + 1.8165975636575933 + 1.8167416701934154 + 1.8168857960276701 + 1.8170299411640036 + 1.8171741056060775 + 1.8173182893575597 + 1.8174624924221083 + 1.817606714803377 + 1.8177509565050414 + 1.817895217530759 + 1.8180394978841969 + 1.8181837975690172 + 1.8183281165888903 + 1.8184724549474856 + 1.8186168126484672 + 1.8187611896955043 + 1.8189055860922705 + 1.8190500018424374 + 1.8191944369496744 + 1.8193388914176551 + 1.8194833652500555 + 1.8196278584505479 + 1.8197723710228113 + 1.8199169029705189 + 1.8200614542973499 + 1.8202060250069847 + 1.820350615103099 + 1.8204952245893742 + 1.8206398534694914 + 1.8207845017471334 + 1.8209291694259861 + 1.821073856509726 + 1.8212185630020452 + 1.8213632889066278 + 1.8215080342271563 + 1.8216527989673197 + 1.8217975831308091 + 1.8219423867213163 + 1.8220872097425247 + 1.8222320521981319 + 1.8223769140918218 + 1.8225217954272974 + 1.8226666962082454 + 1.8228116164383608 + 1.8229565561213432 + 1.8231015152608849 + 1.823246493860688 + 1.8233914919244494 + 1.8235365094558686 + 1.8236815464586436 + 1.8238266029364751 + 1.8239716788930669 + 1.8241167743321243 + 1.824261889257349 + 1.8244070236724437 + 1.8245521775811184 + 1.8246973509870779 + 1.8248425438940259 + 1.8249877563056796 + 1.8251329882257405 + 1.8252782396579184 + 1.8254235106059291 + 1.825568801073487 + 1.8257141110643007 + 1.825859440582084 + 1.8260047896305494 + 1.8261501582134156 + 1.8262955463344044 + 1.8264409539972246 + 1.8265863812055996 + 1.8267318279632494 + 1.8268772942738924 + 1.8270227801412469 + 1.827168285569047 + 1.8273138105609994 + 1.8274593551208376 + 1.8276049192522852 + 1.8277505029590673 + 1.8278961062449106 + 1.828041729113546 + 1.8281873715686994 + 1.8283330336140997 + 1.8284787152534754 + 1.8286244164905636 + 1.8287701373290943 + 1.8289158777727972 + 1.829061637825409 + 1.8292074174906681 + 1.8293532167723034 + 1.8294990356740564 + 1.8296448741996649 + 1.829790732352867 + 1.8299366101374017 + 1.8300825075570093 + 1.8302284246154339 + 1.8303743613164167 + 1.830520317663699 + 1.8306662936610281 + 1.8308122893121461 + 1.8309583046207971 + 1.8311043395907372 + 1.8312503942257077 + 1.8313964685294581 + 1.8315425625057389 + 1.8316886761583011 + 1.8318348094908925 + 1.8319809625072765 + 1.832127135211191 + 1.8322733276064056 + 1.8324195396966658 + 1.8325657714857315 + 1.8327120229773617 + 1.832858294175308 + 1.8330045850833367 + 1.833150895705205 + 1.8332972260446705 + 1.8334435761055003 + 1.8335899458914584 + 1.8337363354063008 + 1.8338827446538 + 1.8340291736377139 + 1.8341756223618173 + 1.8343220908298719 + 1.8344685790456494 + 1.8346150870129145 + 1.8347616147354435 + 1.8349081622170067 + 1.8350547294613699 + 1.835201316472312 + 1.8353479232536039 + 1.8354945498090263 + 1.8356411961423473 + 1.8357878622573498 + 1.8359345481578069 + 1.8360812538475013 + 1.8362279793302057 + 1.8363747246097104 + 1.8365214896897897 + 1.836668274574228 + 1.8368150792668083 + 1.8369619037713132 + 1.8371087480915336 + 1.8372556122312547 + 1.8374024961942561 + 1.8375493999843318 + 1.8376963236052684 + 1.8378432670608598 + 1.8379902303548898 + 1.8381372134911551 + 1.8382842164734521 + 1.8384312393055653 + 1.8385782819912946 + 1.8387253445344374 + 1.8388724269387857 + 1.8390195292081357 + 1.8391666513462921 + 1.8393137933570525 + 1.8394609552442105 + 1.8396081370115736 + 1.8397553386629451 + 1.8399025602021208 + 1.8400498016329141 + 1.8401970629591218 + 1.8403443441845546 + 1.8404916453130151 + 1.8406389663483154 + 1.8407863072942621 + 1.8409336681546653 + 1.8410810489333347 + 1.8412284496340836 + 1.8413758702607237 + 1.8415233108170659 + 1.8416707713069302 + 1.8418182517341266 + 1.8419657521024713 + 1.8421132724157874 + 1.8422608126778857 + 1.8424083728925897 + 1.8425559530637194 + 1.8427035531950913 + 1.8428511732905324 + 1.8429988133538633 + 1.8431464733889076 + 1.8432941533994935 + 1.843441853389441 + 1.8435895733625822 + 1.8437373133227399 + 1.8438850732737475 + 1.8440328532194286 + 1.8441806531636225 + 1.8443284731101497 + 1.8444763130628508 + 1.8446241730255601 + 1.8447720530021001 + 1.8449199529963207 + 1.8450678730120467 + 1.8452158130531222 + 1.8453637731233836 + 1.8455117532266658 + 1.8456597533668151 + 1.8458077735476692 + 1.8459558137730692 + 1.8461038740468594 + 1.8462519543728848 + 1.846400054754987 + 1.8465481751970165 + 1.8466963157028129 + 1.8468444762762277 + 1.8469926569211133 + 1.8471408576413118 + 1.8472890784406795 + 1.8474373193230607 + 1.8475855802923178 + 1.8477338613522982 + 1.8478821625068558 + 1.8480304837598465 + 1.8481788251151252 + 1.8483271865765547 + 1.8484755681479899 + 1.8486239698332834 + 1.8487723916363066 + 1.8489208335609142 + 1.8490692956109633 + 1.8492177777903298 + 1.8493662801028683 + 1.8495148025524428 + 1.8496633451429272 + 1.8498119078781738 + 1.8499604907620693 + 1.8501090937984679 + 1.8502577169912464 + 1.8504063603442678 + 1.8505550238614139 + 1.8507037075465542 + 1.8508524114035543 + 1.8510011354362939 + 1.8511498796486565 + 1.8512986440445063 + 1.8514474286277238 + 1.8515962334021916 + 1.8517450583717878 + 1.8518939035403876 + 1.8520427689118784 + 1.8521916544901369 + 1.8523405602790524 + 1.8524894862825028 + 1.8526384325043781 + 1.8527873989485619 + 1.8529363856189422 + 1.8530853925194035 + 1.8532344196538426 + 1.8533834670261382 + 1.8535325346401927 + 1.8536816224998935 + 1.8538307306091286 + 1.8539798589717986 + 1.8541290075917931 + 1.8542781764730094 + 1.854427365619348 + 1.854576575034707 + 1.8547258047229751 + 1.854875054688061 + 1.8550243249338627 + 1.8551736154642819 + 1.8553229262832216 + 1.8554722573945817 + 1.8556216088022703 + 1.8557709805101967 + 1.8559203725222588 + 1.8560697848423706 + 1.8562192174744352 + 1.8563686704223652 + 1.8565181436900713 + 1.8566676372814648 + 1.8568171512004581 + 1.8569666854509583 + 1.8571162400368888 + 1.8572658149621575 + 1.857415410230685 + 1.8575650258463887 + 1.857714661813183 + 1.8578643181349894 + 1.858013994815729 + 1.858163691859321 + 1.8583134092696902 + 1.8584631470507544 + 1.85861290520644 + 1.8587626837406739 + 1.8589124826573831 + 1.8590623019604888 + 1.8592121416539191 + 1.8593620017416124 + 1.8595118822274872 + 1.8596617831154825 + 1.8598117044095255 + 1.8599616461135537 + 1.8601116082314917 + 1.8602615907672853 + 1.8604115937248615 + 1.8605616171081638 + 1.8607116609211236 + 1.8608617251676862 + 1.8610118098517847 + 1.8611619149773651 + 1.8613120405483661 + 1.8614621865687317 + 1.8616123530424022 + 1.861762539973326 + 1.8619127473654495 + 1.862062975222714 + 1.8622132235490749 + 1.8623634923484724 + 1.8625137816248627 + 1.8626640913821904 + 1.8628144216244102 + 1.8629647723554763 + 1.8631151435793396 + 1.8632655352999565 + 1.8634159475212795 + 1.8635663802472657 + 1.8637168334818737 + 1.8638673072290659 + 1.8640178014927939 + 1.8641683162770259 + 1.8643188515857148 + 1.8644694074228265 + 1.8646199837923305 + 1.8647705806981825 + 1.8649211981443539 + 1.8650718361348047 + 1.8652224946735088 + 1.8653731737644279 + 1.8655238734115362 + 1.8656745936188055 + 1.8658253343902036 + 1.8659760957297022 + 1.8661268776412798 + 1.8662776801289021 + 1.8664285031965522 + 1.8665793468482013 + 1.866730211087829 + 1.8668810959194175 + 1.867032001346935 + 1.8671829273743734 + 1.8673338740057106 + 1.8674848412449228 + 1.8676358290960025 + 1.8677868375629261 + 1.8679378666496844 + 1.8680889163602563 + 1.8682399866986403 + 1.8683910776688124 + 1.8685421892747696 + 1.8686933215205062 + 1.8688444744099981 + 1.8689956479472507 + 1.8691468421362545 + 1.8692980569810012 + 1.8694492924854886 + 1.8696005486537146 + 1.869751825489673 + 1.8699031229973593 + 1.8700544411807767 + 1.8702057800439273 + 1.870357139590807 + 1.8705085198254225 + 1.8706599207517762 + 1.8708113423738715 + 1.8709627846957126 + 1.871114247721305 + 1.8712657314546619 + 1.8714172358997847 + 1.8715687610606901 + 1.8717203069413804 + 1.8718718735458686 + 1.8720234608781685 + 1.8721750689422969 + 1.872326697742261 + 1.8724783472820838 + 1.872630017565774 + 1.8727817085973517 + 1.8729334203808383 + 1.873085152920253 + 1.8732369062196097 + 1.8733886802829365 + 1.8735404751142535 + 1.8736922907175817 + 1.8738441270969517 + 1.8739959842563809 + 1.8741478621999013 + 1.8742997609315371 + 1.8744516804553202 + 1.8746036207752761 + 1.8747555818954389 + 1.8749075638198363 + 1.8750595665525032 + 1.8752115900974717 + 1.8753636344587794 + 1.8755156996404601 + 1.8756677856465471 + 1.8758198924810812 + 1.8759720201481007 + 1.8761241686516472 + 1.8762763379957539 + 1.8764285281844704 + 1.8765807392218365 + 1.876732971111895 + 1.8768852238586902 + 1.8770374974662674 + 1.877189791938676 + 1.8773421072799623 + 1.877494443494174 + 1.8776468005853626 + 1.8777991785575805 + 1.877951577414869 + 1.8781039971612945 + 1.8782564378009043 + 1.8784088993377532 + 1.8785613817758928 + 1.8787138851193896 + 1.8788664093722962 + 1.8790189545386753 + 1.8791715206225781 + 1.8793241076280724 + 1.8794767155592189 + 1.8796293444200791 + 1.8797819942147187 + 1.8799346649472004 + 1.8800873566215963 + 1.8802400692419661 + 1.8803928028123793 + 1.8805455573369088 + 1.8806983328196218 + 1.8808511292645895 + 1.8810039466758832 + 1.8811567850575801 + 1.8813096444137491 + 1.8814625247484689 + 1.8816154260658182 + 1.8817683483698679 + 1.8819212916646983 + 1.8820742559543917 + 1.8822272412430248 + 1.882380247534684 + 1.8825332748334451 + 1.8826863231433955 + 1.8828393924686209 + 1.8829924828132054 + 1.8831455941812323 + 1.8832987265767958 + 1.8834518800039795 + 1.8836050544668723 + 1.8837582499695666 + 1.8839114665161567 + 1.8840647041107337 + 1.8842179627573881 + 1.8843712424602204 + 1.8845245432233189 + 1.8846778650507852 + 1.884831207946718 + 1.8849845719152118 + 1.8851379569603752 + 1.8852913630862993 + 1.8854447902970906 + 1.8855982385968546 + 1.8857517079896897 + 1.8859051984797035 + 1.886058710071008 + 1.8862122427676964 + 1.8863657965738942 + 1.8865193714936959 + 1.8866729675312206 + 1.8868265846905761 + 1.8869802229758712 + 1.8871338823912305 + 1.8872875629407571 + 1.8874412646285692 + 1.8875949874587863 + 1.887748731435529 + 1.8879024965629065 + 1.8880562828450442 + 1.8882100902860606 + 1.8883639188900838 + 1.8885177686612247 + 1.8886716396036163 + 1.8888255317213809 + 1.8889794450186439 + 1.8891333794995324 + 1.8892873351681747 + 1.8894413120287028 + 1.8895953100852418 + 1.8897493293419221 + 1.8899033698028824 + 1.8900574314722458 + 1.8902115143541569 + 1.8903656184527438 + 1.8905197437721493 + 1.890673890316499 + 1.8908280580899486 + 1.890982247096622 + 1.8911364573406677 + 1.8912906888262238 + 1.8914449415574353 + 1.8915992155384413 + 1.8917535107733945 + 1.8919078272664303 + 1.8920621650217064 + 1.8922165240433646 + 1.8923709043355512 + 1.8925253059024227 + 1.8926797287481216 + 1.8928341728768108 + 1.8929886382926302 + 1.8931431249997466 + 1.8932976330023079 + 1.893452162304474 + 1.8936067129103964 + 1.8937612848242416 + 1.8939158780501595 + 1.8940704925923164 + 1.8942251284548728 + 1.8943797856419931 + 1.8945344641578379 + 1.8946891640065695 + 1.8948438851923624 + 1.8949986277193727 + 1.8951533915917758 + 1.8953081768137365 + 1.895462983389425 + 1.8956178113230153 + 1.8957726606186758 + 1.8959275312805766 + 1.8960824233129037 + 1.8962373367198229 + 1.896392271505507 + 1.8965472276741437 + 1.8967022052299007 + 1.8968572041769667 + 1.8970122245195196 + 1.8971672662617356 + 1.8973223294078023 + 1.8974774139619039 + 1.8976325199282158 + 1.8977876473109396 + 1.897942796114249 + 1.8980979663423379 + 1.8982531579993904 + 1.8984083710896023 + 1.898563605617162 + 1.8987188615862594 + 1.8988741390010895 + 1.8990294378658499 + 1.8991847581847339 + 1.8993400999619332 + 1.8994954632016494 + 1.8996508479080811 + 1.8998062540854266 + 1.8999616817378859 + 1.9001171308696592 + 1.900272601484956 + 1.9004280935879738 + 1.9005836071829194 + 1.9007391422740008 + 1.9008946988654174 + 1.9010502769613868 + 1.9012058765661106 + 1.9013614976838029 + 1.9015171403186755 + 1.9016728044749405 + 1.9018284901568103 + 1.9019841973684948 + 1.90213992611422 + 1.9022956763981931 + 1.902451448224634 + 1.9026072415977635 + 1.9027630565217988 + 1.9029188930009662 + 1.903074751039481 + 1.9032306306415701 + 1.9033865318114576 + 1.9035424545533624 + 1.9036983988715208 + 1.9038543647701522 + 1.9040103522534932 + 1.9041663613257622 + 1.9043223919911969 + 1.9044784442540239 + 1.9046345181184849 + 1.9047906135888037 + 1.9049467306692212 + 1.9051028693639729 + 1.9052590296772924 + 1.9054152116134193 + 1.9055714151765963 + 1.9057276403710555 + 1.9058838872010451 + 1.9060401556708071 + 1.9061964457845841 + 1.9063527575466139 + 1.90650909096115 + 1.9066654460324401 + 1.9068218227647258 + 1.9069782211622608 + 1.9071346412292887 + 1.9072910829700687 + 1.9074475463888454 + 1.9076040314898803 + 1.9077605382774192 + 1.9079170667557204 + 1.9080736169290404 + 1.9082301888016391 + 1.9083867823777694 + 1.9085433976616968 + 1.9087000346576819 + 1.9088566933699778 + 1.9090133738028576 + 1.9091700759605827 + 1.9093267998474142 + 1.9094835454676233 + 1.9096403128254731 + 1.9097971019252351 + 1.9099539127711751 + 1.9101107453675661 + 1.9102675997186782 + 1.9104244758287834 + 1.9105813737021615 + 1.910738293343081 + 1.9108952347558155 + 1.9110521979446515 + 1.9112091829138604 + 1.9113661896677172 + 1.9115232182105109 + 1.9116802685465228 + 1.9118373406800278 + 1.9119944346153122 + 1.912151550356664 + 1.9123086879083677 + 1.9124658472747089 + 1.912623028459973 + 1.9127802314684517 + 1.9129374563044361 + 1.913094702972219 + 1.9132519714760858 + 1.9134092618203336 + 1.9135665740092582 + 1.9137239080471593 + 1.9138812639383205 + 1.9140386416870507 + 1.9141960412976453 + 1.9143534627744057 + 1.9145109061216281 + 1.9146683713436159 + 1.9148258584446798 + 1.9149833674291161 + 1.9151408983012319 + 1.9152984510653348 + 1.9154560257257336 + 1.9156136222867315 + 1.9157712407526446 + 1.9159288811277817 + 1.9160865434164551 + 1.9162442276229725 + 1.9164019337516587 + 1.9165596618068204 + 1.9167174117927706 + 1.916875183713842 + 1.9170329775743382 + 1.9171907933785832 + 1.9173486311309043 + 1.9175064908356152 + 1.9176643724970424 + 1.9178222761195072 + 1.9179802017073415 + 1.918138149264863 + 1.9182961187964032 + 1.9184541103062915 + 1.9186121237988534 + 1.9187701592784245 + 1.9189282167493358 + 1.9190862962159203 + 1.91924439768251 + 1.9194025211534407 + 1.9195606666330487 + 1.9197188341256715 + 1.9198770236356482 + 1.9200352351673133 + 1.9201934687250144 + 1.9203517243130939 + 1.9205100019358869 + 1.9206683015977455 + 1.920826623303008 + 1.9209849670560264 + 1.9211433328611454 + 1.9213017207227103 + 1.9214601306450758 + 1.9216185626325928 + 1.9217770166896089 + 1.9219354928204775 + 1.9220939910295549 + 1.9222525113211917 + 1.9224110536997516 + 1.9225696181695864 + 1.9227282047350602 + 1.9228868134005224 + 1.9230454441703433 + 1.9232040970488786 + 1.9233627720404951 + 1.9235214691495548 + 1.9236801883804218 + 1.9238389297374665 + 1.9239976932250529 + 1.924156478847548 + 1.9243152866093243 + 1.9244741165147525 + 1.9246329685682051 + 1.9247918427740505 + 1.924950739136668 + 1.9251096576604301 + 1.92526859834971 + 1.9254275612088949 + 1.9255865462423547 + 1.9257455534544707 + 1.925904582849622 + 1.9260636344321953 + 1.9262227082065715 + 1.9263818041771312 + 1.9265409223482697 + 1.9267000627243589 + 1.9268592253097974 + 1.9270184101089707 + 1.927177617126266 + 1.9273368463660798 + 1.9274960978328002 + 1.9276553715308209 + 1.927814667464536 + 1.9279739856383367 + 1.9281333260566271 + 1.9282926887238001 + 1.9284520736442565 + 1.9286114808223955 + 1.9287709102626158 + 1.9289303619693259 + 1.9290898359469215 + 1.9292493321998132 + 1.9294088507324028 + 1.9295683915490971 + 1.9297279546543009 + 1.9298875400524313 + 1.9300471477478931 + 1.9302067777450971 + 1.9303664300484586 + 1.9305261046623894 + 1.9306858015913027 + 1.9308455208396162 + 1.9310052624117395 + 1.9311650263121047 + 1.9313248125451161 + 1.9314846211152061 + 1.931644452026789 + 1.931804305284287 + 1.9319641808921273 + 1.9321240788547338 + 1.9322839991765328 + 1.9324439418619441 + 1.9326039069154048 + 1.9327638943413439 + 1.9329239041441832 + 1.9330839363283672 + 1.9332439908983181 + 1.9334040678584701 + 1.9335641672132633 + 1.9337242889671333 + 1.9338844331245144 + 1.9340445996898472 + 1.9342047886675711 + 1.934365000062126 + 1.9345252338779513 + 1.9346854901194934 + 1.9348457687911942 + 1.9350060698974996 + 1.935166393442858 + 1.9353267394317182 + 1.9354871078685205 + 1.9356474987577241 + 1.9358079121037757 + 1.9359683479111267 + 1.9361288061842294 + 1.9362892869275425 + 1.9364497901455151 + 1.9366103158426107 + 1.9367708640232846 + 1.9369314346919948 + 1.9370920278532016 + 1.9372526435113677 + 1.9374132816709524 + 1.9375739423364196 + 1.9377346255122383 + 1.9378953312028697 + 1.9380560594127847 + 1.9382168101464463 + 1.9383775834083272 + 1.9385383792028994 + 1.9386991975346288 + 1.9388600384079948 + 1.9390209018274687 + 1.9391817877975217 + 1.9393426963226357 + 1.9395036274072841 + 1.9396645810559459 + 1.9398255572731007 + 1.939986556063233 + 1.9401475774308239 + 1.9403086213803507 + 1.940469687916301 + 1.9406307770431583 + 1.9407918887654154 + 1.9409530230875531 + 1.9411141800140661 + 1.9412753595494407 + 1.9414365616981646 + 1.94159778646474 + 1.9417590338536506 + 1.9419203038693953 + 1.9420815965164693 + 1.9422429117993689 + 1.9424042497225944 + 1.9425656102906435 + 1.9427269935080145 + 1.9428883993792156 + 1.943049827908742 + 1.9432112791011029 + 1.9433727529607956 + 1.9435342494923395 + 1.9436957687002301 + 1.9438573105889791 + 1.944018875163096 + 1.9441804624270984 + 1.9443420723854892 + 1.944503705042784 + 1.9446653604034994 + 1.9448270384721491 + 1.9449887392532501 + 1.9451504627513225 + 1.945312208970877 + 1.9454739779164472 + 1.9456357695925424 + 1.9457975840036927 + 1.9459594211544167 + 1.9461212810492436 + 1.9462831636926972 + 1.9464450690892989 + 1.9466069972435882 + 1.9467689481600881 + 1.9469309218433346 + 1.9470929182978487 + 1.9472549375281727 + 1.9474169795388363 + 1.9475790443343759 + 1.9477411319193314 + 1.9479032422982319 + 1.9480653754756281 + 1.94822753145605 + 1.948389710244042 + 1.9485519118441486 + 1.9487141362609108 + 1.9488763834988754 + 1.9490386535625852 + 1.9492009464565883 + 1.9493632621854324 + 1.949525600753673 + 1.9496879621658509 + 1.9498503464265269 + 1.9500127535402476 + 1.950175183511571 + 1.9503376363450506 + 1.9505001120452372 + 1.9506626106166978 + 1.9508251320639898 + 1.9509876763916654 + 1.9511502436042953 + 1.9513128337064343 + 1.9514754467026503 + 1.951638082597507 + 1.9518007413955707 + 1.951963423101408 + 1.9521261277195809 + 1.9522888552546704 + 1.9524516057112407 + 1.9526143790938622 + 1.9527771754071124 + 1.9529399946555637 + 1.9531028368437873 + 1.9532657019763657 + 1.9534285900578714 + 1.9535915010928842 + 1.9537544350859868 + 1.9539173920417601 + 1.9540803719647861 + 1.9542433748596459 + 1.9544064007309274 + 1.9545694495832182 + 1.9547325214210984 + 1.9548956162491626 + 1.9550587340719967 + 1.9552218748941961 + 1.9553850387203444 + 1.9555482255550396 + 1.9557114354028788 + 1.9558746682684534 + 1.9560379241563621 + 1.9562012030712022 + 1.9563645050175744 + 1.9565278300000724 + 1.9566911780233085 + 1.9568545490918694 + 1.957017943210376 + 1.9571813603834263 + 1.9573448006156222 + 1.9575082639115755 + 1.9576717502758936 + 1.9578352597131856 + 1.9579987922280662 + 1.9581623478251413 + 1.9583259265090263 + 1.9584895282843424 + 1.9586531531556983 + 1.9588168011277121 + 1.9589804722049986 + 1.9591441663921867 + 1.959307883693888 + 1.9594716241147243 + 1.959635387659322 + 1.9597991743323093 + 1.9599629841383046 + 1.9601268170819346 + 1.9602906731678276 + 1.9604545524006205 + 1.9606184547849304 + 1.9607823803253954 + 1.9609463290266524 + 1.9611103008933233 + 1.9612742959300515 + 1.9614383141414726 + 1.9616023555322237 + 1.961766420106938 + 1.9619305078702627 + 1.9620946188268324 + 1.9622587529812963 + 1.9624229103382902 + 1.9625870909024605 + 1.9627512946784547 + 1.9629155216709242 + 1.9630797718845048 + 1.9632440453238591 + 1.9634083419936283 + 1.9635726618984688 + 1.9637370050430309 + 1.9639013714319735 + 1.9640657610699446 + 1.9642301739616033 + 1.9643946101116103 + 1.9645590695246247 + 1.9647235522053041 + 1.9648880581583106 + 1.9650525873883067 + 1.9652171398999572 + 1.9653817156979221 + 1.9655463147868755 + 1.9657109371714832 + 1.9658755828564092 + 1.9660402518463249 + 1.9662049441459049 + 1.9663696597598175 + 1.9665343986927377 + 1.9666991609493421 + 1.9668639465343027 + 1.9670287554523014 + 1.9671935877080118 + 1.9673584433061133 + 1.9675233222512944 + 1.9676882245482321 + 1.9678531502016032 + 1.9680180992160987 + 1.9681830715964075 + 1.9683480673472122 + 1.9685130864731992 + 1.9686781289790627 + 1.9688431948694893 + 1.9690082841491707 + 1.9691733968228047 + 1.9693385328950801 + 1.9695036923706923 + 1.9696688752543394 + 1.9698340815507231 + 1.969999311264536 + 1.9701645644004804 + 1.9703298409632632 + 1.9704951409575762 + 1.9706604643881358 + 1.9708258112596402 + 1.9709911815767955 + 1.9711565753443134 + 1.9713219925668974 + 1.9714874332492618 + 1.9716528973961158 + 1.9718183850121698 + 1.9719838961021448 + 1.972149430670749 + 1.9723149887226996 + 1.9724805702627191 + 1.9726461752955193 + 1.972811803825824 + 1.9729774558583542 + 1.9731431313978274 + 1.9733088304489796 + 1.9734745530165179 + 1.9736402991051869 + 1.9738060687196961 + 1.9739718618647881 + 1.9741376785451863 + 1.9743035187656219 + 1.9744693825308248 + 1.9746352698455369 + 1.9748011807144845 + 1.9749671151424082 + 1.9751330731340391 + 1.9752990546941243 + 1.9754650598273973 + 1.9756310885385975 + 1.9757971408324733 + 1.9759632167137655 + 1.976129316187216 + 1.9762954392575716 + 1.9764615859295793 + 1.9766277562079893 + 1.9767939500975502 + 1.976960167603012 + 1.9771264087291311 + 1.97729267348065 + 1.9774589618623355 + 1.9776252738789317 + 1.9777916095352028 + 1.9779579688359128 + 1.9781243517858051 + 1.9782907583896541 + 1.9784571886522175 + 1.9786236425782513 + 1.9787901201725318 + 1.9789566214398195 + 1.979123146384876 + 1.9792896950124772 + 1.9794562673273906 + 1.9796228633343844 + 1.9797894830382285 + 1.979956126443706 + 1.9801227935555785 + 1.9802894843786323 + 1.9804561989176355 + 1.9806229371773654 + 1.9807896991626146 + 1.98095648487815 + 1.9811232943287609 + 1.9812901275192276 + 1.9814569844543304 + 1.981623865138864 + 1.9817907695776085 + 1.981957697775357 + 1.9821246497368923 + 1.9822916254670095 + 1.9824586249704956 + 1.9826256482521476 + 1.9827926953167649 + 1.9829597661691321 + 1.9831268608140535 + 1.983293979256326 + 1.9834611215007467 + 1.9836282875521176 + 1.9837954774152418 + 1.9839626910949197 + 1.9841299285959517 + 1.984297189923157 + 1.9844644750813294 + 1.9846317840752841 + 1.9847991169098265 + 1.9849664735897656 + 1.9851338541199208 + 1.9853012585051024 + 1.9854686867501188 + 1.9856361388597912 + 1.9858036148389377 + 1.9859711146923729 + 1.9861386384249171 + 1.9863061860413911 + 1.9864737575466156 + 1.9866413529454188 + 1.9868089722426188 + 1.9869766154430442 + 1.9871442825515251 + 1.9873119735728824 + 1.9874796885119528 + 1.9876474273735631 + 1.9878151901625463 + 1.9879829768837409 + 1.9881507875419693 + 1.9883186221420794 + 1.9884864806888993 + 1.9886543631872748 + 1.9888222696420403 + 1.9889902000580391 + 1.9891581544401113 + 1.9893261327931064 + 1.9894941351218616 + 1.9896621614312291 + 1.9898302117260476 + 1.9899982860111751 + 1.9901663842914563 + 1.9903345065717419 + 1.9905026528568885 + 1.9906708231517429 + 1.9908390174611683 + 1.9910072357900135 + 1.9911754781431383 + 1.9913437445254074 + 1.9915120349416688 + 1.9916803493967929 + 1.9918486878956387 + 1.9920170504430734 + 1.9921854370439591 + 1.9923538477031602 + 1.9925222824255471 + 1.9926907412159882 + 1.9928592240793557 + 1.993027731020518 + 1.9931962620443511 + 1.9933648171557246 + 1.9935333963595148 + 1.9937019996606031 + 1.9938706270638593 + 1.9940392785741698 + 1.9942079541964117 + 1.9943766539354681 + 1.9945453777962172 + 1.9947141257835497 + 1.9948828979023447 + 1.9950516941575001 + 1.9952205145538906 + 1.9953893590964167 + 1.9955582277899557 + 1.9957271206394132 + 1.9958960376496773 + 1.996064978825643 + 1.9962339441721995 + 1.9964029336942559 + 1.9965719473967003 + 1.9967409852844387 + 1.9969100473623655 + 1.9970791336353921 + 1.997248244108411 + 1.9974173787863352 + 1.9975865376740718 + 1.9977557207765193 + 1.997924928098594 + 1.9980941596452053 + 1.9982634154212626 + 1.9984326954316773 + 1.9986019996813653 + 1.9987713281752386 + 1.9989406809182202 + 1.9991100579152192 + 1.9992794591711607 + 1.9994488846909642 + 1.9996183344795475 + 1.9997878085418406 + 1.9999573068827599 + 2.0001268295072321 + 2.0002963764201871 + 2.0004659476265516 + 2.0006355431312604 + 2.0008051629392325 + 2.0009748070554094 + 2.001144475484721 + 2.0013141682321023 + 2.001483885302485 + 2.0016536267008131 + 2.0018233924320215 + 2.0019931825010469 + 2.0021629969128343 + 2.0023328356723278 + 2.0025026987844674 + 2.0026725862542016 + 2.0028424980864723 + 2.003012434286227 + 2.0031823948584209 + 2.003352379807998 + 2.0035223891399059 + 2.0036924228591091 + 2.0038624809705512 + 2.0040325634791958 + 2.0042026703899922 + 2.0043728017079046 + 2.0045429574378852 + 2.0047131375849001 + 2.004883342153907 + 2.0050535711498743 + 2.005223824577762 + 2.0053941024425388 + 2.0055644047491725 + 2.005734731502625 + 2.0059050827078728 + 2.0060754583698852 + 2.0062458584936356 + 2.0064162830840959 + 2.0065867321462378 + 2.0067572056850369 + 2.0069277037054811 + 2.0070982262125443 + 2.0072687732112016 + 2.0074393447064378 + 2.0076099407032397 + 2.0077805612065847 + 2.0079512062214606 + 2.0081218757528561 + 2.0082925698057608 + 2.0084632883851556 + 2.0086340314960416 + 2.0088047991434062 + 2.0089755913322391 + 2.009146408067537 + 2.0093172493543006 + 2.0094881151975259 + 2.009659005602205 + 2.0098299205733445 + 2.0100008601159427 + 2.0101718242350044 + 2.0103428129355292 + 2.0105138262225286 + 2.0106848641010031 + 2.0108559265759665 + 2.0110270136524178 + 2.0111981253353797 + 2.011369261629854 + 2.0115404225408597 + 2.0117116080734108 + 2.0118828182325244 + 2.0120540530232134 + 2.0122253124504939 + 2.0123965965193951 + 2.0125679052349295 + 2.0127392386021268 + 2.0129105966260026 + 2.0130819793115839 + 2.013253386663898 + 2.0134248186879815 + 2.0135962753888492 + 2.0137677567715415 + 2.0139392628410877 + 2.0141107936025167 + 2.0142823490608674 + 2.0144539292211721 + 2.0146255340884673 + 2.0147971636677986 + 2.0149688179641974 + 2.0151404969827098 + 2.0153122007283728 + 2.015483929206237 + 2.0156556824213445 + 2.0158274603787385 + 2.0159992630834709 + 2.0161710905405874 + 2.0163429427551391 + 2.0165148197321798 + 2.0166867214767592 + 2.0168586479939385 + 2.0170305992887632 + 2.0172025753662965 + 2.0173745762315987 + 2.0175466018897268 + 2.0177186523457356 + 2.0178907276046991 + 2.0180628276716739 + 2.0182349525517242 + 2.0184071022499257 + 2.0185792767713306 + 2.0187514761210217 + 2.0189237003040619 + 2.0190959493255254 + 2.0192682231904833 + 2.0194405219040146 + 2.0196128454711935 + 2.0197851938970923 + 2.0199575671867938 + 2.0201299653453786 + 2.0203023883779263 + 2.0204748362895146 + 2.020647309085239 + 2.0208198067701733 + 2.0209923293494114 + 2.0211648768280388 + 2.0213374492111367 + 2.0215100465038134 + 2.0216826687111453 + 2.0218553158382297 + 2.0220279878901644 + 2.0222006848720455 + 2.0223734067889687 + 2.0225461536460272 + 2.0227189254483324 + 2.0228917222009732 + 2.0230645439090646 + 2.0232373905776972 + 2.0234102622119905 + 2.0235831588170439 + 2.0237560803979604 + 2.0239290269598618 + 2.0241019985078457 + 2.0242749950470351 + 2.0244480165825389 + 2.0246210631194739 + 2.0247941346629572 + 2.0249672312180995 + 2.025140352790026 + 2.0253134993838571 + 2.0254866710047148 + 2.0256598676577178 + 2.0258330893479939 + 2.0260063360806675 + 2.0261796078608652 + 2.026352904693717 + 2.0265262265843549 + 2.0266995735379045 + 2.0268729455595031 + 2.0270463426542813 + 2.027219764827378 + 2.0273932120839278 + 2.0275666844290705 + 2.0277401818679417 + 2.0279137044056808 + 2.0280872520474404 + 2.0282608247983509 + 2.0284344226635658 + 2.0286080456482294 + 2.0287816937574901 + 2.028955366996493 + 2.0291290653703897 + 2.0293027888843391 + 2.0294765375434816 + 2.0296503113529791 + 2.0298241103179895 + 2.0299979344436654 + 2.0301717837351667 + 2.0303456581976542 + 2.0305195578362878 + 2.03069348265623 + 2.0308674326626446 + 2.0310414078607031 + 2.0312154082555622 + 2.0313894338523988 + 2.0315634846563757 + 2.0317375606726671 + 2.0319116619064479 + 2.0320857883628842 + 2.0322599400471582 + 2.032434116964442 + 2.0326083191199142 + 2.0327825465187583 + 2.032956799166147 + 2.033131077067269 + 2.0333053802273029 + 2.0334797086514418 + 2.0336540623448589 + 2.0338284413127456 + 2.0340028455603001 + 2.0341772750927021 + 2.0343517299151466 + 2.0345262100328281 + 2.0347007154509367 + 2.0348752461746713 + 2.0350498022092292 + 2.0352243835598065 + 2.0353989902316072 + 2.0355736222298288 + 2.0357482795596735 + 2.0359229622263491 + 2.0360976702350593 + 2.0362724035910063 + 2.0364471622994076 + 2.0366219463654631 + 2.0367967557943887 + 2.0369715905913992 + 2.0371464507617021 + 2.0373213363105163 + 2.0374962472430593 + 2.0376711835645427 + 2.0378461452801946 + 2.0380211323952295 + 2.0381961449148722 + 2.0383711828443429 + 2.0385462461888699 + 2.0387213349536797 + 2.0388964491439974 + 2.0390715887650548 + 2.0392467538220758 + 2.0394219443202988 + 2.0395971602649583 + 2.0397724016612817 + 2.0399476685145124 + 2.0401229608298812 + 2.0402982786126298 + 2.0404736218680024 + 2.0406489906012308 + 2.0408243848175687 + 2.0409998045222513 + 2.0411752497205344 + 2.0413507204176566 + 2.0415262166188697 + 2.0417017383294183 + 2.0418772855545639 + 2.0420528582995541 + 2.0422284565696431 + 2.0424040803700811 + 2.0425797297061359 + 2.04275540458306 + 2.0429311050061107 + 2.0431068309805558 + 2.0432825825116505 + 2.043458359604664 + 2.0436341622648566 + 2.0438099904975005 + 2.0439858443078633 + 2.0441617237012095 + 2.0443376286828174 + 2.0445135592579526 + 2.0446895154318967 + 2.0448654972099169 + 2.0450415045972967 + 2.045217537599306 + 2.0453935962212331 + 2.0455696804683501 + 2.0457457903459488 + 2.045921925859302 + 2.046098087013708 + 2.0462742738144377 + 2.0464504862667905 + 2.0466267243760572 + 2.0468029881475189 + 2.0469792775864746 + 2.0471555926982199 + 2.0473319334880413 + 2.04750829996124 + 2.0476846921231169 + 2.0478611099789652 + 2.0480375535340931 + 2.0482140227937933 + 2.0483905177633783 + 2.0485670384481431 + 2.0487435848534021 + 2.0489201569844657 + 2.0490967548466323 + 2.0492733784452195 + 2.0494500277855412 + 2.0496267028729012 + 2.0498034037126271 + 2.0499801303100278 + 2.0501568826704197 + 2.0503336607991272 + 2.0505104647014631 + 2.0506872943827608 + 2.0508641498483331 + 2.0510410311035097 + 2.0512179381536169 + 2.0513948710039775 + 2.0515718296599315 + 2.0517488141267988 + 2.0519258244099134 + 2.0521028605146117 + 2.0522799224462283 + 2.0524570102100967 + 2.0526341238115551 + 2.0528112632559465 + 2.0529884285486073 + 2.0531656196948815 + 2.053342836700109 + 2.05352007956964 + 2.0536973483088192 + 2.0538746429229913 + 2.0540519634175025 + 2.054229309797718 + 2.0544066820689717 + 2.0545840802366269 + 2.0547615043060383 + 2.0549389542825596 + 2.055116430171549 + 2.0552939319783672 + 2.055471459708373 + 2.055649013366931 + 2.0558265929594004 + 2.0560041984911486 + 2.0561818299675414 + 2.056359487393947 + 2.0565371707757381 + 2.0567148801182769 + 2.0568926154269422 + 2.0570703767071055 + 2.0572481639641409 + 2.0574259772034309 + 2.0576038164303454 + 2.057781681650265 + 2.0579595728685711 + 2.0581374900906493 + 2.0583154333218801 + 2.058493402567652 + 2.0586713978333449 + 2.0588494191243543 + 2.0590274664460639 + 2.059205539803866 + 2.0593836392031588 + 2.0595617646493234 + 2.0597399161477696 + 2.0599180937038803 + 2.0600962973230668 + 2.0602745270107197 + 2.0604527827722414 + 2.0606310646130352 + 2.0608093725385048 + 2.0609877065540547 + 2.0611660666650979 + 2.0613444528770337 + 2.0615228651952768 + 2.0617013036252394 + 2.0618797681723287 + 2.062058258841962 + 2.0622367756395557 + 2.0624153185705225 + 2.0625938876402894 + 2.0627724828542688 + 2.0629511042178876 + 2.0631297517365614 + 2.0633084254157228 + 2.0634871252607905 + 2.0636658512771939 + 2.0638446034703626 + 2.064023381845729 + 2.0642021864087186 + 2.0643810171647665 + 2.0645598741193094 + 2.0647387572777851 + 2.0649176666456266 + 2.065096602228274 + 2.0652755640311669 + 2.065454552059748 + 2.0656335663194634 + 2.0658126068157525 + 2.065991673554064 + 2.0661707665398477 + 2.0663498857785503 + 2.066529031275619 + 2.0667082030365118 + 2.066887401066678 + 2.0670666253715773 + 2.0672458759566652 + 2.0674251528273948 + 2.0676044559892288 + 2.0677837854476264 + 2.0679631412080508 + 2.0681425232759691 + 2.0683219316568429 + 2.06850136635614 + 2.0686808273793291 + 2.0688603147318751 + 2.0690398284192582 + 2.0692193684469404 + 2.0693989348204043 + 2.0695785275451226 + 2.0697581466265715 + 2.0699377920702302 + 2.07011746388158 + 2.0702971620661033 + 2.0704768866292795 + 2.0706566375765925 + 2.0708364149135283 + 2.0710162186455818 + 2.0711960487782353 + 2.071375905316978 + 2.0715557882673044 + 2.0717356976347081 + 2.0719156334246778 + 2.0720955956427223 + 2.0722755842943275 + 2.0724555993850005 + 2.0726356409202378 + 2.0728157089055399 + 2.0729958033464144 + 2.0731759242483676 + 2.0733560716169004 + 2.0735362454575257 + 2.0737164457757511 + 2.0738966725770922 + 2.0740769258670535 + 2.0742572056511528 + 2.0744375119349048 + 2.0746178447238344 + 2.0747982040234505 + 2.0749785898392736 + 2.0751590021768296 + 2.075339441041641 + 2.0755199064392302 + 2.075700398375123 + 2.0758809168548518 + 2.0760614618839401 + 2.0762420334679188 + 2.076422631612318 + 2.0766032563226777 + 2.0767839076045318 + 2.0769645854634131 + 2.0771452899048577 + 2.0773260209344135 + 2.0775067785576096 + 2.0776875627800009 + 2.0778683736071226 + 2.0780492110445232 + 2.0782300750977485 + 2.07841096577235 + 2.0785918830738748 + 2.0787728270078758 + 2.0789537975799028 + 2.0791347947955114 + 2.0793158186602625 + 2.079496869179708 + 2.0796779463594115 + 2.0798590502049228 + 2.0800401807218161 + 2.0802213379156531 + 2.0804025217919957 + 2.0805837323564034 + 2.0807649696144583 + 2.0809462335717179 + 2.0811275242337608 + 2.0813088416061563 + 2.0814901856944767 + 2.0816715565043058 + 2.0818529540412092 + 2.0820343783107678 + 2.0822158293185691 + 2.0823973070701904 + 2.0825788115712158 + 2.0827603428272261 + 2.0829419008438075 + 2.083123485626551 + 2.0833050971810452 + 2.0834867355128801 + 2.0836684006276487 + 2.0838500925309438 + 2.0840318112283525 + 2.0842135567254862 + 2.0843953290279353 + 2.0845771281412993 + 2.0847589540711788 + 2.0849408068231816 + 2.0851226864029102 + 2.0853045928159641 + 2.0854865260679532 + 2.0856684861644927 + 2.0858504731111855 + 2.0860324869136444 + 2.0862145275774884 + 2.0863965951083268 + 2.0865786895117764 + 2.086760810793459 + 2.0869429589589918 + 2.0871251340139905 + 2.0873073359640846 + 2.0874895648148986 + 2.0876718205720546 + 2.0878541032411779 + 2.0880364128279005 + 2.0882187493378535 + 2.0884011127766668 + 2.0885835031499687 + 2.0887659204634015 + 2.0889483647225986 + 2.0891308359331999 + 2.0893133341008383 + 2.0894958592311599 + 2.0896784113298073 + 2.0898609904024195 + 2.0900435964546467 + 2.0902262294921359 + 2.0904088895205319 + 2.0905915765454899 + 2.0907742905726585 + 2.0909570316076871 + 2.0911397996562324 + 2.0913225947239513 + 2.0915054168165073 + 2.0916882659395535 + 2.0918711420987464 + 2.0920540452997565 + 2.0922369755482455 + 2.0924199328498725 + 2.0926029172103155 + 2.0927859286352306 + 2.0929689671303029 + 2.0931520327011861 + 2.0933351253535672 + 2.093518245093116 + 2.0937013919255043 + 2.0938845658564196 + 2.094067766891528 + 2.094250995036524 + 2.0944342502970805 + 2.0946175326788818 + 2.0948008421876225 + 2.0949841788289767 + 2.095167542608642 + 2.0953509335323033 + 2.095534351605655 + 2.0957177968343856 + 2.0959012692242003 + 2.0960847687807838 + 2.09626829550984 + 2.0964518494170696 + 2.0966354305081638 + 2.0968190387888361 + 2.0970026742647883 + 2.0971863369417174 + 2.0973700268253417 + 2.0975537439213632 + 2.0977374882354956 + 2.0979212597734471 + 2.098105058540932 + 2.098288884543662 + 2.0984727377873624 + 2.0986566182777464 + 2.0988405260205285 + 2.0990244610214379 + 2.0992084232861945 + 2.0993924128205173 + 2.0995764296301371 + 2.0997604737207793 + 2.0999445450981771 + 2.1001286437680537 + 2.1003127697361488 + 2.1004969230081869 + 2.1006811035899116 + 2.1008653114870572 + 2.1010495467053567 + 2.1012338092505547 + 2.1014180991283915 + 2.1016024163446101 + 2.1017867609049552 + 2.1019711328151742 + 2.1021555320810092 + 2.1023399587082174 + 2.102524412702544 + 2.1027088940697394 + 2.1028934028155644 + 2.1030779389457668 + 2.10326250246611 + 2.1034470933823486 + 2.1036317117002472 + 2.1038163574255586 + 2.1040010305640551 + 2.1041857311214986 + 2.1043704591036474 + 2.1045552145162829 + 2.1047399973651699 + 2.1049248076560745 + 2.1051096453947764 + 2.1052945105870493 + 2.1054794032386641 + 2.1056643233553998 + 2.105849270943037 + 2.1060342460073556 + 2.1062192485541353 + 2.1064042785891623 + 2.106589336118224 + 2.1067744211471027 + 2.1069595336815929 + 2.1071446737274799 + 2.1073298412905506 + 2.1075150363766104 + 2.1077002589914402 + 2.1078855091408517 + 2.1080707868306314 + 2.1082560920665823 + 2.108441424854504 + 2.1086267852002019 + 2.1088121731094751 + 2.1089975885881391 + 2.1091830316419906 + 2.1093685022768471 + 2.1095540004985174 + 2.1097395263128074 + 2.1099250797255364 + 2.1101106607425213 + 2.1102962693695759 + 2.1104819056125144 + 2.1106675694771653 + 2.1108532609693511 + 2.1110389800948832 + 2.1112247268596001 + 2.1114105012693209 + 2.1115963033298746 + 2.1117821330470945 + 2.1119679904268027 + 2.1121538754748461 + 2.1123397881970454 + 2.1125257285992456 + 2.1127116966872781 + 2.1128976924669907 + 2.1130837159442177 + 2.1132697671247986 + 2.1134558460145829 + 2.1136419526194188 + 2.1138280869451482 + 2.1140142489976208 + 2.1142004387826905 + 2.1143866563062041 + 2.1145729015740149 + 2.1147591745919838 + 2.1149454753659658 + 2.115131803901821 + 2.1153181602054016 + 2.1155045442825786 + 2.1156909561392077 + 2.1158773957811552 + 2.1160638632142938 + 2.1162503584444847 + 2.1164368814776044 + 2.1166234323195181 + 2.1168100109761001 + 2.1169966174532258 + 2.1171832517567721 + 2.1173699138926128 + 2.1175566038666309 + 2.1177433216847072 + 2.1179300673527273 + 2.1181168408765636 + 2.1183036422621146 + 2.1184904715152637 + 2.1186773286418967 + 2.1188642136479103 + 2.1190511265391874 + 2.1192380673216307 + 2.1194250360011351 + 2.119612032583591 + 2.1197990570749012 + 2.1199861094809678 + 2.1201731898076885 + 2.1203602980609708 + 2.1205474342467188 + 2.1207345983708406 + 2.1209217904392381 + 2.1211090104578267 + 2.1212962584325168 + 2.1214835343692231 + 2.12167083827386 + 2.1218581701523451 + 2.1220455300105923 + 2.1222329178545283 + 2.1224203336900649 + 2.1226077775231289 + 2.1227952493596502 + 2.1229827492055522 + 2.1231702770667575 + 2.1233578329492029 + 2.1235454168588155 + 2.1237330288015301 + 2.1239206687832777 + 2.1241083368099982 + 2.1242960328876292 + 2.1244837570221011 + 2.1246715092193713 + 2.1248592894853671 + 2.1250470978260396 + 2.1252349342473353 + 2.1254227987551948 + 2.1256106913555772 + 2.125798612054429 + 2.1259865608576973 + 2.1261745377713446 + 2.1263625428013211 + 2.1265505759535865 + 2.1267386372340971 + 2.1269267266488159 + 2.1271148442037013 + 2.1273029899047229 + 2.1274911637578415 + 2.1276793657690245 + 2.1278675959442435 + 2.1280558542894634 + 2.1282441408106592 + 2.1284324555138117 + 2.1286207984048837 + 2.128809169489863 + 2.1289975687747189 + 2.1291859962654374 + 2.1293744519679998 + 2.1295629358883836 + 2.1297514480325823 + 2.1299399884065822 + 2.1301285570163668 + 2.1303171538679253 + 2.130505778967255 + 2.1306944323203449 + 2.1308831139331903 + 2.1310718238117921 + 2.1312605619621396 + 2.1314493283902438 + 2.1316381231021007 + 2.1318269461037156 + 2.1320157974010856 + 2.1322046770002334 + 2.132393584907148 + 2.132582521127854 + 2.1327714856683544 + 2.1329604785346645 + 2.1331494997328071 + 2.133338549268784 + 2.1335276271486237 + 2.133716733378344 + 2.1339058679639624 + 2.1340950309115065 + 2.1342842222270031 + 2.1344734419164766 + 2.1346626899859502 + 2.1348519664414565 + 2.1350412712890305 + 2.1352306045346969 + 2.1354199661845015 + 2.1356093562444736 + 2.135798774720655 + 2.135988221619082 + 2.1361776969457948 + 2.1363672007068408 + 2.1365567329082618 + 2.1367462935561088 + 2.1369358826564246 + 2.1371255002152587 + 2.1373151462386661 + 2.1375048207326968 + 2.1376945237034093 + 2.1378842551568553 + 2.1380740150990962 + 2.1382638035361898 + 2.1384536204742006 + 2.1386434659191886 + 2.1388333398772157 + 2.1390232423543583 + 2.1392131733566702 + 2.1394031328902363 + 2.1395931209611216 + 2.1397831375753942 + 2.1399731827391313 + 2.1401632564584117 + 2.1403533587393158 + 2.1405434895879241 + 2.1407336490103095 + 2.1409238370125614 + 2.1411140536007678 + 2.1413042987810051 + 2.1414945725593704 + 2.141684874941951 + 2.1418752059348409 + 2.1420655655441259 + 2.1422559537759112 + 2.1424463706362804 + 2.1426368161313456 + 2.1428272902671974 + 2.1430177930499457 + 2.1432083244856828 + 2.1433988845805216 + 2.1435894733405707 + 2.1437800907719309 + 2.1439707368807177 + 2.1441614116730388 + 2.1443521151550122 + 2.1445428473327537 + 2.1447336082123734 + 2.1449243977999974 + 2.1451152161017393 + 2.1453060631237277 + 2.1454969388720833 + 2.1456878433529272 + 2.1458787765723968 + 2.1460697385366099 + 2.1462607292516989 + 2.1464517487238011 + 2.1466427969590494 + 2.1468338739635731 + 2.1470249797435197 + 2.1472161143050159 + 2.1474072776542119 + 2.1475984697972463 + 2.1477896907402658 + 2.1479809404894121 + 2.1481722190508354 + 2.1483635264306784 + 2.1485548626351019 + 2.1487462276702525 + 2.1489376215422848 + 2.1491290442573554 + 2.1493204958216214 + 2.1495119762412425 + 2.149703485522382 + 2.1498950236711969 + 2.1500865906938595 + 2.1502781865965277 + 2.150469811385376 + 2.1506614650665701 + 2.1508531476462815 + 2.1510448591306823 + 2.1512365995259524 + 2.1514283688382614 + 2.1516201670737947 + 2.151811994238721 + 2.1520038503392325 + 2.1521957353815089 + 2.1523876493717373 + 2.1525795923160937 + 2.1527715642207839 + 2.1529635650919854 + 2.153155594935896 + 2.1533476537587029 + 2.153539741566604 + 2.1537318583658021 + 2.1539240041624925 + 2.1541161789628664 + 2.1543083827731397 + 2.1545006155995061 + 2.1546928774481802 + 2.1548851683253627 + 2.155077488237259 + 2.1552698371900929 + 2.1554622151900626 + 2.1556546222433934 + 2.1558470583562914 + 2.1560395235349836 + 2.1562320177856846 + 2.156424541114617 + 2.1566170935279976 + 2.1568096750320582 + 2.1570022856330215 + 2.1571949253371172 + 2.1573875941505745 + 2.1575802920796257 + 2.1577730191304982 + 2.1579657753094357 + 2.1581585606226725 + 2.1583513750764403 + 2.158544218676981 + 2.1587370914305475 + 2.1589299933433699 + 2.1591229244217027 + 2.1593158846717837 + 2.1595088740998705 + 2.1597018927122109 + 2.1598949405150525 + 2.1600880175146542 + 2.1602811237172701 + 2.160474259129157 + 2.1606674237565815 + 2.1608606176057892 + 2.1610538406830555 + 2.1612470929946404 + 2.161440374546808 + 2.1616336853458331 + 2.1618270253979781 + 2.1620203947095145 + 2.1622137932867189 + 2.1624072211358678 + 2.1626006782632357 + 2.1627941646750974 + 2.1629876803777344 + 2.1631812253774334 + 2.1633747996804726 + 2.1635684032931426 + 2.1637620362217223 + 2.163955698472511 + 2.1641493900517887 + 2.1643431109658531 + 2.1645368612210012 + 2.1647306408235178 + 2.1649244497797113 + 2.1651182880958801 + 2.1653121557783255 + 2.1655060528333405 + 2.165699979267242 + 2.1658939350863289 + 2.1660879202969143 + 2.1662819349053017 + 2.1664759789178141 + 2.1666700523407489 + 2.166864155180432 + 2.1670582874431763 + 2.1672524491353014 + 2.1674466402631314 + 2.1676408608329836 + 2.1678351108511813 + 2.1680293903240515 + 2.1682236992579251 + 2.1684180376591282 + 2.168612405533993 + 2.1688068028888483 + 2.1690012297300325 + 2.1691956860638868 + 2.1693901718967341 + 2.1695846872349271 + 2.1697792320848044 + 2.1699738064527105 + 2.170168410344985 + 2.1703630437679835 + 2.170557706728045 + 2.170752399231525 + 2.1709471212847755 + 2.1711418728941472 + 2.1713366540660006 + 2.1715314648066943 + 2.1717263051225797 + 2.1719211750200236 + 2.1721160745053858 + 2.1723110035850377 + 2.1725059622653382 + 2.1727009505526573 + 2.1728959684533642 + 2.1730910159738364 + 2.1732860931204363 + 2.1734811998995491 + 2.173676336317548 + 2.1738715023808122 + 2.1740666980957206 + 2.1742619234686607 + 2.1744571785060094 + 2.1746524632141608 + 2.1748477775994943 + 2.1750431216684056 + 2.1752384954272825 + 2.1754338988825181 + 2.1756293320405073 + 2.1758247949076499 + 2.1760202874903389 + 2.1762158097949817 + 2.1764113618279772 + 2.176606943595722 + 2.1768025551046271 + 2.1769981963611094 + 2.1771938673715603 + 2.1773895681424023 + 2.1775852986800435 + 2.1777810589909015 + 2.1779768490813933 + 2.1781726689579362 + 2.1783685186269448 + 2.178564398094847 + 2.1787603073680657 + 2.178956246453021 + 2.1791522153561491 + 2.1793482140838667 + 2.1795442426426166 + 2.1797403010388252 + 2.1799363892789207 + 2.1801325073693514 + 2.1803286553165497 + 2.1805248331269556 + 2.1807210408070086 + 2.1809172783631547 + 2.1811135458018343 + 2.1813098431294988 + 2.1815061703525997 + 2.181702527477579 + 2.1818989145108971 + 2.1820953314589997 + 2.1822917783283504 + 2.1824882551254023 + 2.182684761856621 + 2.1828812985284607 + 2.1830778651473861 + 2.1832744617198632 + 2.1834710882523596 + 2.1836677447513382 + 2.1838644312232782 + 2.1840611476746465 + 2.1842578941119233 + 2.1844546705415739 + 2.1846514769700822 + 2.1848483134039269 + 2.1850451798495865 + 2.1852420763135534 + 2.1854390028023016 + 2.1856359593223229 + 2.1858329458801022 + 2.1860299624821331 + 2.1862270091349094 + 2.1864240858449215 + 2.1866211926186656 + 2.1868183294626449 + 2.187015496383347 + 2.1872126933872829 + 2.1874099204809538 + 2.1876071776708614 + 2.1878044649635209 + 2.1880017823654261 + 2.1881991298830981 + 2.1883965075230485 + 2.1885939152917926 + 2.1887913531958385 + 2.1889888212417126 + 2.1891863194359278 + 2.1893838477850074 + 2.189581406295479 + 2.1897789949738553 + 2.1899766138266781 + 2.1901742628604697 + 2.1903719420817609 + 2.1905696514970807 + 2.1907673911129675 + 2.1909651609359582 + 2.1911629609725871 + 2.1913607912293913 + 2.1915586517129202 + 2.191756542429713 + 2.1919544633863097 + 2.1921524145892692 + 2.1923503960451285 + 2.1925484077604449 + 2.1927464497417688 + 2.192944521995654 + 2.1931426245286589 + 2.1933407573473436 + 2.1935389204582592 + 2.1937371138679747 + 2.1939353375830515 + 2.1941335916100573 + 2.1943318759555561 + 2.1945301906261179 + 2.1947285356283142 + 2.1949269109687171 + 2.1951253166539004 + 2.1953237526904434 + 2.1955222190849231 + 2.1957207158439171 + 2.1959192429740133 + 2.1961178004817872 + 2.196316388373833 + 2.1965150066567358 + 2.1967136553370823 + 2.1969123344214627 + 2.197111043916478 + 2.1973097838287146 + 2.1975085541647728 + 2.19770735493125 + 2.1979061861347495 + 2.1981050477818713 + 2.1983039398792199 + 2.1985028624334051 + 2.1987018154510269 + 2.1989007989387028 + 2.1990998129030461 + 2.1992988573506604 + 2.1994979322881685 + 2.1996970377221854 + 2.1998961736593263 + 2.2000953401062233 + 2.2002945370694893 + 2.2004937645557545 + 2.2006930225716386 + 2.2008923111237797 + 2.2010916302188046 + 2.20129097986334 + 2.2014903600640272 + 2.2016897708274938 + 2.2018892121603875 + 2.2020886840693423 + 2.2022881865610002 + 2.2024877196420052 + 2.2026872833190039 + 2.2028868775986377 + 2.2030865024875643 + 2.2032861579924328 + 2.2034858441198897 + 2.203685560876592 + 2.2038853082692018 + 2.2040850863043731 + 2.204284894988763 + 2.2044847343290419 + 2.2046846043318684 + 2.204884505003907 + 2.2050844363518269 + 2.2052843983823016 + 2.2054843911019937 + 2.2056844145175867 + 2.2058844686357517 + 2.2060845534631701 + 2.2062846690065108 + 2.2064848152724625 + 2.2066849922677099 + 2.2068851999989305 + 2.2070854384728134 + 2.2072857076960513 + 2.2074860076753295 + 2.207686338417342 + 2.2078866999287849 + 2.208087092216358 + 2.2082875152867465 + 2.2084879691466583 + 2.2086884538027998 + 2.2088889692618672 + 2.2090895155305694 + 2.2092900926156047 + 2.2094907005237001 + 2.2096913392615547 + 2.2098920088358809 + 2.2100927092533991 + 2.2102934405208217 + 2.2104942026448753 + 2.2106949956322683 + 2.2108958194897346 + 2.2110966742239908 + 2.2112975598417717 + 2.2114984763497936 + 2.2116994237547978 + 2.2119004020635127 + 2.2121014112826685 + 2.2123024514190051 + 2.2125035224792593 + 2.2127046244701747 + 2.2129057573984863 + 2.2131069212709398 + 2.2133081160942818 + 2.2135093418752598 + 2.2137105986206209 + 2.2139118863371188 + 2.2141132050315058 + 2.2143145547105321 + 2.2145159353809656 + 2.2147173470495574 + 2.214918789723066 + 2.2151202634082581 + 2.2153217681118949 + 2.2155233038407469 + 2.2157248706015809 + 2.2159264684011708 + 2.2161280972462825 + 2.2163297571436904 + 2.2165314481001781 + 2.2167331701225135 + 2.2169349232174826 + 2.2171367073918655 + 2.2173385226524451 + 2.2175403690060103 + 2.2177422464593457 + 2.2179441550192385 + 2.2181460946924854 + 2.2183480654858756 + 2.2185500674062095 + 2.2187521004602786 + 2.2189541646548854 + 2.2191562599968231 + 2.2193583864929081 + 2.2195605441499371 + 2.2197627329747167 + 2.219964952974057 + 2.2201672041547682 + 2.2203694865236621 + 2.2205718000875518 + 2.2207741448532605 + 2.2209765208275996 + 2.2211789280173959 + 2.2213813664294673 + 2.221583836070633 + 2.22178633694773 + 2.221988869067578 + 2.222191432437012 + 2.2223940270628564 + 2.2225966529519514 + 2.2227993101111343 + 2.2230019985472431 + 2.2232047182671084 + 2.2234074692775807 + 2.2236102515855021 + 2.223813065197711 + 2.224015910121063 + 2.2242187863624037 + 2.2244216939285906 + 2.2246246328264681 + 2.2248276030628951 + 2.2250306046447279 + 2.2252336375788304 + 2.2254367018720549 + 2.2256397975312732 + 2.225842924563346 + 2.2260460829751354 + 2.2262492727735212 + 2.2264524939653647 + 2.2266557465575407 + 2.2268590305569287 + 2.2270623459704022 + 2.2272656928048362 + 2.2274690710671141 + 2.2276724807641188 + 2.2278759219027382 + 2.2280793944898543 + 2.2282828985323544 + 2.2284864340371264 + 2.2286900010110746 + 2.228893599461081 + 2.2290972293940472 + 2.2293008908168712 + 2.2295045837364542 + 2.229708308159692 + 2.2299120640934964 + 2.2301158515447668 + 2.2303196705204131 + 2.2305235210273513 + 2.2307274030724851 + 2.2309313166627329 + 2.2311352618050102 + 2.2313392385062287 + 2.2315432467733207 + 2.2317472866131971 + 2.2319513580327817 + 2.2321554610390071 + 2.2323595956387963 + 2.2325637618390792 + 2.2327679596467864 + 2.2329721890688545 + 2.2331764501122175 + 2.2333807427838108 + 2.2335850670905795 + 2.233789423039461 + 2.2339938106373944 + 2.2341982298913345 + 2.2344026808082225 + 2.2346071633950064 + 2.2348116776586444 + 2.235016223606082 + 2.235220801244282 + 2.235425410580191 + 2.2356300516207797 + 2.2358347243730057 + 2.2360394288438288 + 2.2362441650402163 + 2.2364489329691368 + 2.2366537326375573 + 2.2368585640524494 + 2.2370634272207872 + 2.2372683221495446 + 2.2374732488456983 + 2.2376782073162347 + 2.2378831975681188 + 2.2380882196083496 + 2.2382932734439005 + 2.2384983590817722 + 2.2387034765289391 + 2.2389086257924018 + 2.2391138068791481 + 2.2393190197961741 + 2.2395242645504805 + 2.2397295411490625 + 2.2399348495989178 + 2.2401401899070579 + 2.2403455620804844 + 2.2405509661262024 + 2.2407564020512205 + 2.2409618698625504 + 2.2411673695672083 + 2.2413729011722014 + 2.2415784646845598 + 2.2417840601112893 + 2.2419896874594154 + 2.2421953467359645 + 2.2424010379479586 + 2.2426067611024281 + 2.242812516206393 + 2.2430183032668958 + 2.2432241222909601 + 2.2434299732856249 + 2.2436358562579315 + 2.2438417712149121 + 2.2440477181636065 + 2.2442536971110627 + 2.2444597080643294 + 2.2446657510304471 + 2.2448718260164657 + 2.2450779330294357 + 2.2452840720764096 + 2.2454902431644546 + 2.2456964463006095 + 2.2459026814919412 + 2.2461089487455164 + 2.246315248068393 + 2.246521579467637 + 2.2467279429503093 + 2.2469343385234914 + 2.2471407661942471 + 2.2473472259696528 + 2.2475537178567793 + 2.247760241862709 + 2.247966797994517 + 2.248173386259289 + 2.2483800066641053 + 2.2485866592160511 + 2.2487933439222152 + 2.2490000607896881 + 2.2492068098255578 + 2.2494135910369222 + 2.249620404430877 + 2.2498272500145133 + 2.2500341277949345 + 2.2502410377792486 + 2.2504479799745467 + 2.2506549543879446 + 2.2508619610265472 + 2.2510689998974671 + 2.2512760710078061 + 2.2514831743646915 + 2.2516903099752272 + 2.2518974778465424 + 2.2521046779857481 + 2.2523119103999676 + 2.2525191750963294 + 2.2527264720819589 + 2.2529338013639832 + 2.2531411629495297 + 2.253348556845729 + 2.253555983059726 + 2.2537634415986476 + 2.2539709324696338 + 2.2541784556798277 + 2.2543860112363658 + 2.2545935991463972 + 2.2548012194170695 + 2.2550088720555279 + 2.2552165570689251 + 2.2554242744644175 + 2.2556320242491563 + 2.2558398064302958 + 2.2560476210149951 + 2.256255468010421 + 2.2564633474237294 + 2.2566712592620903 + 2.2568792035326672 + 2.2570871802426304 + 2.2572951893991524 + 2.2575032310094021 + 2.2577113050805622 + 2.2579194116198065 + 2.2581275506343115 + 2.2583357221312599 + 2.2585439261178433 + 2.2587521626012337 + 2.2589604315886271 + 2.2591687330872112 + 2.2593770671041749 + 2.259585433646722 + 2.2597938327220324 + 2.2600022643373223 + 2.2602107284997772 + 2.2604192252166073 + 2.2606277544950109 + 2.2608363163422012 + 2.2610449107653783 + 2.2612535377717586 + 2.2614621973685547 + 2.2616708895629771 + 2.2618796143622455 + 2.2620883717735771 + 2.2622971618041956 + 2.2625059844613151 + 2.2627148397521721 + 2.2629237276839844 + 2.2631326482639857 + 2.2633416014994063 + 2.263550587397483 + 2.2637596059654395 + 2.2639686572105235 + 2.2641777411399739 + 2.2643868577610289 + 2.264596007080931 + 2.2648051891069332 + 2.2650144038462767 + 2.2652236513062101 + 2.2654329314939878 + 2.2656422444168651 + 2.2658515900820944 + 2.2660609684969377 + 2.2662703796686556 + 2.2664798236045094 + 2.2666893003117572 + 2.2668988097976768 + 2.267108352069529 + 2.2673179271345858 + 2.2675275350001245 + 2.2677371756734113 + 2.2679468491617261 + 2.2681565554723555 + 2.2683662946125742 + 2.268576066589667 + 2.2687858714109148 + 2.2689957090836126 + 2.269205579615047 + 2.2694154830125055 + 2.269625419283285 + 2.269835388434688 + 2.2700453904740008 + 2.2702554254085281 + 2.2704654932455743 + 2.2706755939924426 + 2.2708857276564389 + 2.2710958942448696 + 2.2713060937650487 + 2.271516326224285 + 2.2717265916298959 + 2.2719368899891981 + 2.2721472213095111 + 2.2723575855981544 + 2.2725679828624505 + 2.2727784131097319 + 2.2729888763473198 + 2.273199372582543 + 2.2734099018227352 + 2.2736204640752251 + 2.2738310593473576 + 2.2740416876464646 + 2.2742523489798847 + 2.2744630433549662 + 2.2746737707790508 + 2.274884531259485 + 2.2750953248036181 + 2.2753061514187958 + 2.2755170111123784 + 2.2757279038917142 + 2.2759388297641641 + 2.2761497887370865 + 2.2763607808178445 + 2.2765718060137967 + 2.2767828643323145 + 2.2769939557807573 + 2.2772050803665094 + 2.2774162380969241 + 2.2776274289793923 + 2.2778386530212815 + 2.2780499102299658 + 2.2782612006128389 + 2.278472524177273 + 2.2786838809306551 + 2.2788952708803709 + 2.2791066940338101 + 2.2793181503983693 + 2.2795296399814333 + 2.2797411627904012 + 2.279952718832674 + 2.280164308115646 + 2.28037593064672 + 2.2805875864333021 + 2.2807992754827993 + 2.2810109978026101 + 2.2812227534001597 + 2.2814345422828497 + 2.2816463644580969 + 2.2818582199333215 + 2.2820701087159434 + 2.2822820308133802 + 2.2824939862330509 + 2.282705974982389 + 2.2829179970688172 + 2.2831300524997675 + 2.2833421412826742 + 2.2835542634249593 + 2.2837664189340732 + 2.2839786078174455 + 2.2841908300825207 + 2.284403085736741 + 2.2846153747875477 + 2.2848276972423913 + 2.2850400531087178 + 2.2852524423939835 + 2.2854648651056331 + 2.2856773212511308 + 2.2858898108379333 + 2.2861023338734938 + 2.286314890365281 + 2.2865274803207516 + 2.2867401037473778 + 2.2869527606526274 + 2.2871654510439767 + 2.287378174928882 + 2.2875909323148313 + 2.2878037232093029 + 2.2880165476197698 + 2.2882294055537131 + 2.2884422970186176 + 2.2886552220219776 + 2.2888681805712645 + 2.2890811726739835 + 2.2892941983376169 + 2.2895072575696669 + 2.2897203503776216 + 2.2899334767689843 + 2.2901466367512606 + 2.2903598303319419 + 2.290573057518547 + 2.2907863183185762 + 2.2909996127395398 + 2.2912129407889505 + 2.2914263024743184 + 2.2916396978031637 + 2.2918531267830038 + 2.2920665894213568 + 2.2922800857257517 + 2.2924936157037061 + 2.292707179362754 + 2.2929207767104223 + 2.2931344077542386 + 2.2933480725017397 + 2.293561770960459 + 2.2937755031379368 + 2.2939892690417105 + 2.2942030686793324 + 2.294416902058332 + 2.2946307691862668 + 2.2948446700706824 + 2.295058604719129 + 2.2952725731391612 + 2.295486575338332 + 2.2957006113242087 + 2.2959146811043367 + 2.2961287846862874 + 2.2963429220776232 + 2.2965570932859136 + 2.2967712983187192 + 2.296985537183617 + 2.297199809888177 + 2.2974141164399766 + 2.2976284568465952 + 2.2978428311156094 + 2.2980572392546033 + 2.2982716812711548 + 2.2984861571728596 + 2.2987006669672976 + 2.2989152106620683 + 2.2991297882647546 + 2.2993443997829597 + 2.2995590452242727 + 2.2997737245963052 + 2.2999884379066509 + 2.3002031851629132 + 2.3004179663726987 + 2.3006327815436185 + 2.3008476306832817 + 2.3010625137992986 + 2.3012774308992867 + 2.3014923819908679 + 2.3017073670816526 + 2.3019223861792666 + 2.3021374392913372 + 2.3023525264254849 + 2.3025676475893384 + 2.302782802790531 + 2.3029979920366954 + 2.3032132153354676 + 2.3034284726944789 + 2.3036437641213761 + 2.3038590896237952 + 2.3040744492093861 + 2.3042898428857828 + 2.304505270660647 + 2.3047207325416257 + 2.3049362285363655 + 2.3051517586525296 + 2.305367322897768 + 2.3055829212797474 + 2.3057985538061208 + 2.3060142204845615 + 2.3062299213227266 + 2.3064456563282931 + 2.3066614255089242 + 2.3068772288723012 + 2.3070930664260851 + 2.3073089381779699 + 2.3075248441356209 + 2.3077407843067279 + 2.30795675869898 + 2.3081727673200514 + 2.308388810177632 + 2.3086048872794209 + 2.3088209986331045 + 2.3090371442463806 + 2.3092533241269448 + 2.3094695382825003 + 2.3096857867207476 + 2.3099020694493873 + 2.3101183864761272 + 2.3103347378086827 + 2.3105511234547591 + 2.3107675434220685 + 2.3109839977183295 + 2.3112004863512534 + 2.3114170093285669 + 2.3116335666579926 + 2.3118501583472506 + 2.3120667844040725 + 2.3122834448361811 + 2.3125001396513114 + 2.3127168688571982 + 2.3129336324615704 + 2.3131504304721764 + 2.3133672628967452 + 2.3135841297430306 + 2.3138010310187656 + 2.3140179667317051 + 2.3142349368896005 + 2.3144519415001943 + 2.3146689805712475 + 2.3148860541105147 + 2.3151031621257592 + 2.3153203046247248 + 2.3155374816151921 + 2.3157546931049184 + 2.3159719391016731 + 2.3161892196132245 + 2.3164065346473453 + 2.3166238842118094 + 2.31684126831439 + 2.3170586869628744 + 2.3172761401650357 + 2.3174936279286618 + 2.3177111502615397 + 2.3179287071714465 + 2.3181462986661852 + 2.3183639247535379 + 2.3185815854413097 + 2.3187992807372897 + 2.319017010649278 + 2.3192347751850813 + 2.3194525743524972 + 2.3196704081593351 + 2.3198882766134021 + 2.3201061797225146 + 2.3203241174944713 + 2.3205420899371041 + 2.3207600970582209 + 2.3209781388656432 + 2.3211962153671872 + 2.3214143265706904 + 2.3216324724839708 + 2.3218506531148613 + 2.3220688684711863 + 2.3222871185607876 + 2.3225054033914936 + 2.3227237229711473 + 2.3229420773075891 + 2.3231604664086634 + 2.323378890282207 + 2.3235973489360768 + 2.3238158423781154 + 2.3240343706161792 + 2.3242529336581188 + 2.3244715315117985 + 2.3246901641850632 + 2.324908831685784 + 2.3251275340218229 + 2.3253462712010511 + 2.3255650432313222 + 2.325783850120517 + 2.3260026918765067 + 2.3262215685071679 + 2.3264404800203735 + 2.3266594264240061 + 2.3268784077259426 + 2.3270974239340729 + 2.3273164750562865 + 2.3275355611004631 + 2.3277546820744943 + 2.3279738379862827 + 2.3281930288437178 + 2.3284122546546966 + 2.3286315154271211 + 2.3288508111689015 + 2.3290701418879269 + 2.3292895075921161 + 2.3295089082893718 + 2.3297283439876155 + 2.3299478146947581 + 2.3301673204187097 + 2.3303868611673932 + 2.3306064369487332 + 2.3308260477706497 + 2.3310456936410655 + 2.331265374567915 + 2.3314850905591267 + 2.3317048416226349 + 2.3319246277663708 + 2.3321444489982768 + 2.3323643053262875 + 2.332584196758348 + 2.3328041233024006 + 2.3330240849663952 + 2.3332440817582851 + 2.3334641136860101 + 2.3336841807575359 + 2.333904282980809 + 2.3341244203637967 + 2.3343445929144511 + 2.3345648006407425 + 2.3347850435506365 + 2.3350053216520918 + 2.3352256349530931 + 2.3354459834616015 + 2.3356663671855933 + 2.3358867861330492 + 2.3361072403119492 + 2.336327729730276 + 2.3365482543960039 + 2.3367688143171321 + 2.3369894095016392 + 2.3372100399575331 + 2.3374307056927885 + 2.3376514067154139 + 2.3378721430334006 + 2.3380929146547551 + 2.3383137215874727 + 2.338534563839568 + 2.3387554414190395 + 2.3389763543339086 + 2.3391973025921788 + 2.3394182862018691 + 2.3396393051709956 + 2.3398603595075751 + 2.3400814492196336 + 2.3403025743151953 + 2.3405237348022827 + 2.3407449306889307 + 2.3409661619831681 + 2.3411874286930243 + 2.3414087308265459 + 2.3416300683917592 + 2.3418514413967162 + 2.3420728498494543 + 2.3422942937580196 + 2.3425157731304584 + 2.3427372879748236 + 2.3429588382991655 + 2.3431804241115404 + 2.3434020454200115 + 2.3436237022326325 + 2.3438453945574649 + 2.3440671224025724 + 2.3442888857760331 + 2.3445106846858983 + 2.3447325191402562 + 2.3449543891471696 + 2.345176294714721 + 2.3453982358509915 + 2.3456202125640555 + 2.3458422248619981 + 2.3460642727529071 + 2.346286356244875 + 2.3465084753459835 + 2.3467306300643336 + 2.3469528204080201 + 2.3471750463851322 + 2.3473973080037807 + 2.3476196052720657 + 2.3478419381980911 + 2.3480643067899636 + 2.3482867110557915 + 2.34850915100369 + 2.3487316266417788 + 2.3489541379781631 + 2.349176685020971 + 2.3493992677783244 + 2.34962188625834 + 2.3498445404691579 + 2.3500672304188952 + 2.3502899561156827 + 2.3505127175676659 + 2.3507355147829698 + 2.3509583477697373 + 2.3511812165361072 + 2.3514041210902303 + 2.3516270614402495 + 2.3518500375943074 + 2.352073049560556 + 2.3522960973471565 + 2.3525191809622568 + 2.3527423004140151 + 2.3529654557105952 + 2.3531886468601622 + 2.3534118738708716 + 2.3536351367508952 + 2.3538584355084105 + 2.3540817701515784 + 2.3543051406885804 + 2.354528547127595 + 2.3547519894767963 + 2.3549754677443673 + 2.3551989819385009 + 2.355422532067375 + 2.3556461181391786 + 2.3558697401621083 + 2.3560933981443588 + 2.3563170920941223 + 2.3565408220196065 + 2.3567645879290002 + 2.3569883898305108 + 2.35721222773235 + 2.3574361016427274 + 2.3576600115698452 + 2.3578839575219246 + 2.3581079395071813 + 2.3583319575338306 + 2.3585560116100952 + 2.3587801017441943 + 2.3590042279443586 + 2.3592283902188163 + 2.3594525885757962 + 2.3596768230235337 + 2.3599010935702616 + 2.3601254002242142 + 2.3603497429936415 + 2.3605741218867822 + 2.3607985369118785 + 2.361022988077182 + 2.361247475390936 + 2.3614719988614024 + 2.3616965584968317 + 2.3619211543054783 + 2.3621457862956099 + 2.3623704544754816 + 2.3625951588533654 + 2.3628198994375209 + 2.3630446762362225 + 2.3632694892577386 + 2.3634943385103511 + 2.363719224002327 + 2.3639441457419577 + 2.3641691037375168 + 2.3643940979972844 + 2.3646191285295624 + 2.3648441953426249 + 2.365069298444777 + 2.3652944378443004 + 2.3655196135494938 + 2.3657448255686724 + 2.3659700739101175 + 2.3661953585821442 + 2.3664206795930558 + 2.3666460369511646 + 2.3668714306647742 + 2.3670968607422109 + 2.36732232719178 + 2.367547830021806 + 2.3677733692406076 + 2.3679989448565126 + 2.3682245568778444 + 2.3684502053129282 + 2.3686758901701053 + 2.3689016114576997 + 2.3691273691840511 + 2.3693531633575051 + 2.3695789939863867 + 2.3698048610790559 + 2.370030764643849 + 2.370256704689119 + 2.3704826812232165 + 2.370708694254493 + 2.3709347437913069 + 2.3711608298420135 + 2.3713869524149791 + 2.3716131115185681 + 2.3718393071611343 + 2.3720655393510541 + 2.3722918080967084 + 2.3725181134064548 + 2.3727444552886765 + 2.3729708337517508 + 2.3731972488040576 + 2.3734237004539858 + 2.3736501887099122 + 2.3738767135802319 + 2.3741032750733368 + 2.3743298731976159 + 2.3745565079614694 + 2.3747831793732885 + 2.3750098874414816 + 2.3752366321744494 + 2.3754634135805994 + 2.3756902316683335 + 2.3759170864460679 + 2.3761439779222147 + 2.3763709061051981 + 2.3765978710034212 + 2.3768248726253183 + 2.377051910979302 + 2.3772789860738071 + 2.3775060979172569 + 2.3777332465180843 + 2.3779604318847194 + 2.3781876540256057 + 2.3784149129491756 + 2.378642208663869 + 2.378869541178136 + 2.3790969105004174 + 2.3793243166391647 + 2.3795517596028248 + 2.3797792393998529 + 2.3800067560387035 + 2.3802343095278391 + 2.3804618998757237 + 2.3806895270908135 + 2.3809171911815805 + 2.3811448921564882 + 2.3813726300240132 + 2.3816004047926276 + 2.3818282164708005 + 2.3820560650670188 + 2.3822839505897631 + 2.3825118730475197 + 2.3827398324487641 + 2.3829678288019975 + 2.3831958621157057 + 2.3834239323983799 + 2.3836520396585219 + 2.3838801839046275 + 2.3841083651452015 + 2.3843365833887469 + 2.3845648386437706 + 2.3847931309187751 + 2.3850214602222817 + 2.385249826562799 + 2.385478229948848 + 2.3857066703889469 + 2.3859351478916109 + 2.3861636624653721 + 2.3863922141187577 + 2.3866208028602935 + 2.3868494286985156 + 2.3870780916419534 + 2.3873067916991504 + 2.3875355288786344 + 2.3877643031889648 + 2.3879931146386699 + 2.3882219632363086 + 2.3884508489904293 + 2.3886797719095814 + 2.3889087320023217 + 2.389137729277206 + 2.3893667637427889 + 2.3895958354076474 + 2.3898249442803357 + 2.3900540903694245 + 2.3902832736834871 + 2.3905124942310962 + 2.3907417520208187 + 2.3909710470612469 + 2.3912003793609458 + 2.3914297489285103 + 2.391659155772524 + 2.3918885999015727 + 2.3921180813242446 + 2.392347600049141 + 2.3925771560848537 + 2.3928067494399814 + 2.3930363801231254 + 2.3932660481428876 + 2.393495753507878 + 2.3937254962267014 + 2.3939552763079717 + 2.394185093760306 + 2.3944149485923192 + 2.3946448408126195 + 2.394874770429845 + 2.3951047374526149 + 2.3953347418895543 + 2.395564783749295 + 2.3957948630404675 + 2.3960249797717013 + 2.3962551339516431 + 2.3964853255889285 + 2.3967155546921992 + 2.3969458212701005 + 2.3971761253312787 + 2.3974064668843891 + 2.3976368459380808 + 2.3978672625010118 + 2.3980977165818351 + 2.3983282081892225 + 2.39855873733182 + 2.3987893040183086 + 2.3990199082573471 + 2.39925055005761 + 2.3994812294277752 + 2.3997119463765113 + 2.3999427009125029 + 2.4001734930444267 + 2.4004043227809682 + 2.4006351901308229 + 2.4008660951026619 + 2.4010970377051954 + 2.4013280179471082 + 2.401559035837094 + 2.4017900913838579 + 2.4020211845961046 + 2.4022523154825377 + 2.4024834840518623 + 2.4027146903127838 + 2.402945934274026 + 2.4031772159442943 + 2.4034085353323156 + 2.4036398924468023 + 2.4038712872964849 + 2.4041027198900813 + 2.4043341902363249 + 2.4045656983439456 + 2.4047972442216765 + 2.4050288278782563 + 2.4052604493224163 + 2.4054921085629086 + 2.4057238056084729 + 2.4059555404678594 + 2.4061873131498079 + 2.4064191236630768 + 2.4066509720164229 + 2.4068828582185988 + 2.4071147822783701 + 2.4073467442044891 + 2.407578744005733 + 2.4078107816908636 + 2.4080428572686521 + 2.408274970747867 + 2.4085071221372898 + 2.4087393114457023 + 2.4089715386818744 + 2.4092038038545969 + 2.4094361069726569 + 2.4096684480448438 + 2.4099008270799454 + 2.4101332440867589 + 2.4103656990740783 + 2.4105981920507018 + 2.4108307230254362 + 2.4110632920070838 + 2.4112958990044544 + 2.4115285440263579 + 2.4117612270816053 + 2.411993948179008 + 2.412226707327386 + 2.4124595045355695 + 2.412692339812371 + 2.4129252131666217 + 2.4131581246071461 + 2.4133910741427771 + 2.4136240617823517 + 2.4138570875347045 + 2.4140901514086748 + 2.4143232534131074 + 2.4145563935568348 + 2.4147895718487211 + 2.4150227882976063 + 2.4152560429123486 + 2.4154893357017961 + 2.4157226666748057 + 2.4159560358402499 + 2.4161894432069833 + 2.4164228887838717 + 2.4166563725797898 + 2.4168898946036017 + 2.4171234548641847 + 2.4173570533704161 + 2.4175906901311728 + 2.4178243651553362 + 2.4180580784517951 + 2.4182918300294367 + 2.4185256198971468 + 2.4187594480638217 + 2.4189933145383513 + 2.4192272193296449 + 2.4194611624465852 + 2.419695143898096 + 2.41992916369307 + 2.4201632218404221 + 2.4203973183490599 + 2.4206314532279016 + 2.4208656264858592 + 2.4210998381318545 + 2.4213340881748069 + 2.4215683766236524 + 2.4218027034873093 + 2.4220370687747068 + 2.4222714724947769 + 2.422505914656464 + 2.4227403952687014 + 2.4229749143404273 + 2.4232094718805901 + 2.4234440678981364 + 2.4236787024020079 + 2.423913375401169 + 2.4241480869045664 + 2.4243828369211533 + 2.4246176254598977 + 2.424852452529763 + 2.425087318139707 + 2.4253222222987052 + 2.4255571650157246 + 2.4257921462997394 + 2.4260271661597299 + 2.426262224604669 + 2.4264973216435357 + 2.4267324572853268 + 2.4269676315390147 + 2.4272028444136007 + 2.4274380959180748 + 2.4276733860614317 + 2.4279087148526663 + 2.4281440823007814 + 2.4283794884147807 + 2.4286149332036695 + 2.4288504166764557 + 2.4290859388421557 + 2.4293214997097792 + 2.4295570992883446 + 2.4297927375868769 + 2.4300284146143878 + 2.4302641303799128 + 2.430499884892471 + 2.4307356781611005 + 2.430971510194829 + 2.4312073810026957 + 2.4314432905937453 + 2.4316792389770048 + 2.4319152261615358 + 2.4321512521563706 + 2.4323873169705705 + 2.4326234206131772 + 2.4328595630932552 + 2.4330957444198598 + 2.4333319646020501 + 2.4335682236488894 + 2.4338045215694493 + 2.4340408583727933 + 2.4342772340679972 + 2.4345136486641272 + 2.4347501021702671 + 2.4349865945954985 + 2.4352231259489079 + 2.4354596962395658 + 2.4356963054765779 + 2.4359329536690226 + 2.4361696408259994 + 2.4364063669566005 + 2.4366431320699351 + 2.4368799361750932 + 2.4371167792811872 + 2.4373536613973226 + 2.4375905825326138 + 2.4378275426961644 + 2.4380645418970999 + 2.4383015801445316 + 2.4385386574475834 + 2.4387757738153857 + 2.4390129292570562 + 2.4392501237817279 + 2.4394873573985332 + 2.43972463011661 + 2.4399619419450973 + 2.4401992928931318 + 2.4404366829698541 + 2.4406741121844169 + 2.4409115805459685 + 2.4411490880636642 + 2.4413866347466442 + 2.4416242206040808 + 2.4418618456451298 + 2.4420995098789575 + 2.4423372133147181 + 2.4425749559615912 + 2.4428127378287492 + 2.4430505589253566 + 2.443288419260595 + 2.4435263188436513 + 2.4437642576836964 + 2.4440022357899207 + 2.4442402531715142 + 2.4444783098376672 + 2.4447164057975712 + 2.4449545410604205 + 2.4451927156354225 + 2.4454309295317693 + 2.4456691827586714 + 2.4459074753253396 + 2.446145807240979 + 2.4463841785148035 + 2.4466225891560325 + 2.4468610391738834 + 2.4470995285775743 + 2.4473380573763324 + 2.4475766255793876 + 2.4478152331959624 + 2.4480538802352951 + 2.4482925667066269 + 2.4485312926191853 + 2.4487700579822151 + 2.4490088628049662 + 2.4492477070966792 + 2.4494865908666084 + 2.4497255141240046 + 2.4499644768781192 + 2.4502034791382115 + 2.4504425209135499 + 2.4506816022133888 + 2.4509207230470058 + 2.4511598834236574 + 2.4513990833526207 + 2.4516383228431775 + 2.4518776019045978 + 2.4521169205461621 + 2.4523562787771631 + 2.4525956766068764 + 2.4528351140445985 + 2.4530745910996186 + 2.4533141077812322 + 2.4535536640987363 + 2.4537932600614321 + 2.454032895678619 + 2.454272570959612 + 2.4545122859137103 + 2.4547520405502321 + 2.4549918348784909 + 2.4552316689078069 + 2.4554715426475 + 2.4557114561068882 + 2.4559514092953036 + 2.456191402222065 + 2.4564314348965195 + 2.4566715073279886 + 2.4569116195258154 + 2.4571517714993432 + 2.457391963257904 + 2.4576321948108593 + 2.4578724661675508 + 2.4581127773373264 + 2.4583531283295437 + 2.4585935191535597 + 2.4588339498187395 + 2.459074420334435 + 2.4593149307100246 + 2.4595554809548692 + 2.4597960710783471 + 2.4600367010898263 + 2.4602773709986892 + 2.460518080814309 + 2.460758830546081 + 2.4609996202033781 + 2.4612404497955978 + 2.4614813193321283 + 2.4617222288223664 + 2.4619631782757065 + 2.462204167701552 + 2.4624451971093055 + 2.4626862665083742 + 2.4629273759081651 + 2.4631685253180868 + 2.4634097147475584 + 2.463650944205996 + 2.4638922137028265 + 2.4641335232474622 + 2.4643748728493367 + 2.4646162625178722 + 2.4648576922625129 + 2.4650991620926872 + 2.4653406720178275 + 2.4655822220473849 + 2.4658238121907932 + 2.4660654424575013 + 2.4663071128569651 + 2.4665488233986301 + 2.4667905740919509 + 2.4670323649463874 + 2.4672741959714046 + 2.4675160671764611 + 2.4677579785710226 + 2.4679999301645692 + 2.4682419219665608 + 2.4684839539864756 + 2.4687260262337918 + 2.4689681387179978 + 2.4692102914485714 + 2.469452484434997 + 2.4696947176867683 + 2.4699369912133791 + 2.4701793050243204 + 2.4704216591290966 + 2.4706640535372117 + 2.4709064882581591 + 2.4711489633014567 + 2.4713914786766069 + 2.4716340343931265 + 2.4718766304605317 + 2.4721192668883396 + 2.472361943686078 + 2.4726046608632597 + 2.4728474184294265 + 2.4730902163941031 + 2.4733330547668171 + 2.4735759335571172 + 2.4738188527745297 + 2.4740618124286065 + 2.4743048125288882 + 2.4745478530849256 + 2.4747909341062693 + 2.4750340556024684 + 2.4752772175830864 + 2.4755204200576828 + 2.4757636630358197 + 2.4760069465270598 + 2.4762502705409699 + 2.4764936350871269 + 2.4767370401751108 + 2.4769804858144835 + 2.4772239720148375 + 2.4774674987857597 + 2.4777110661368171 + 2.477954674077619 + 2.4781983226177524 + 2.4784420117668002 + 2.4786857415343797 + 2.4789295119300814 + 2.4791733229635051 + 2.4794171746442681 + 2.4796610669819739 + 2.4799049999862377 + 2.480148973666672 + 2.4803929880329014 + 2.4806370430945424 + 2.4808811388612177 + 2.4811252753425639 + 2.4813694525482033 + 2.4816136704877754 + 2.4818579291709106 + 2.4821022286072489 + 2.4823465688064403 + 2.4825909497781216 + 2.4828353715319427 + 2.4830798340775613 + 2.4833243374246248 + 2.4835688815827921 + 2.4838134665617244 + 2.4840580923710887 + 2.484302759020542 + 2.4845474665197576 + 2.4847922148784121 + 2.485037004106172 + 2.4852818342127216 + 2.485526705207739 + 2.4857716171009065 + 2.486016569901921 + 2.4862615636204639 + 2.4865065982662249 + 2.4867516738489117 + 2.4869967903782122 + 2.4872419478638323 + 2.4874871463154795 + 2.4877323857428539 + 2.4879776661556723 + 2.4882229875636486 + 2.4884683499764972 + 2.4887137534039439 + 2.4889591978557002 + 2.4892046833415047 + 2.4894502098710762 + 2.4896957774541462 + 2.4899413861004618 + 2.4901870358197424 + 2.4904327266217465 + 2.4906784585162081 + 2.4909242315128766 + 2.4911700456214971 + 2.4914159008518277 + 2.4916617972136224 + 2.4919077347166447 + 2.4921537133706457 + 2.4923997331853984 + 2.4926457941706692 + 2.4928918963362294 + 2.4931380396918539 + 2.4933842242473139 + 2.4936304500123936 + 2.4938767169968719 + 2.4941230252105431 + 2.4943693746631852 + 2.4946157653646006 + 2.4948621973245735 + 2.4951086705529142 + 2.49535518505941 + 2.4956017408538762 + 2.4958483379461192 + 2.4960949763459386 + 2.4963416560631542 + 2.4965883771075852 + 2.496835139489046 + 2.4970819432173594 + 2.4973287883023589 + 2.4975756747538553 + 2.4978226025816923 + 2.498069571795706 + 2.4983165824057272 + 2.4985636344215969 + 2.4988107278531602 + 2.499057862710266 + 2.4993050390027611 + 2.4995522567404964 + 2.4997995159333275 + 2.5000468165911212 + 2.5002941587237255 + 2.5005415423410127 + 2.5007889674528538 + 2.5010364340691162 + 2.5012839421996649 + 2.5015314918543905 + 2.5017790830431679 + 2.5020267157758815 + 2.5022743900624107 + 2.5025221059126537 + 2.5027698633364994 + 2.5030176623438396 + 2.503265502944573 + 2.5035133851486053 + 2.5037613089658386 + 2.5040092744061835 + 2.5042572814795419 + 2.5045053301958369 + 2.5047534205649753 + 2.5050015525968856 + 2.505249726301487 + 2.505497941688708 + 2.5057461987684722 + 2.5059944975507147 + 2.5062428380453716 + 2.5064912202623821 + 2.5067396442116792 + 2.5069881099032174 + 2.5072366173469387 + 2.5074851665527969 + 2.5077337575307386 + 2.5079823902907314 + 2.5082310648427257 + 2.5084797811966828 + 2.5087285393625782 + 2.5089773393503738 + 2.5092261811700474 + 2.5094750648315642 + 2.509723990344912 + 2.5099729577200667 + 2.5102219669670145 + 2.5104710180957444 + 2.510720111116242 + 2.5109692460385067 + 2.5112184228725334 + 2.5114676416283186 + 2.5117169023158676 + 2.5119662049451872 + 2.5122155495262852 + 2.5124649360691786 + 2.5127143645838803 + 2.5129638350804031 + 2.5132133475687763 + 2.5134629020590187 + 2.5137124985611616 + 2.5139621370852328 + 2.5142118176412684 + 2.514461540239306 + 2.5147113048893894 + 2.514961111601552 + 2.5152109603858523 + 2.5154608512523251 + 2.5157107842110356 + 2.5159607592720379 + 2.5162107764453898 + 2.5164608357411451 + 2.5167109371693814 + 2.5169610807401619 + 2.5172112664635571 + 2.5174614943496358 + 2.5177117644084879 + 2.517962076650186 + 2.5182124310848182 + 2.5184628277224728 + 2.5187132665732315 + 2.5189637476471956 + 2.5192142709544592 + 2.5194648365051209 + 2.5197154443092882 + 2.5199660943770548 + 2.5202167867185432 + 2.520467521343861 + 2.5207182982631182 + 2.5209691174864388 + 2.5212199790239476 + 2.5214708828857613 + 2.5217218290820131 + 2.5219728176228307 + 2.5222238485183515 + 2.5224749217787115 + 2.5227260374140483 + 2.5229771954345108 + 2.5232283958502424 + 2.5234796386713914 + 2.5237309239081149 + 2.523982251570569 + 2.5242336216689112 + 2.5244850342133041 + 2.5247364892139115 + 2.5249879866809053 + 2.5252395266244556 + 2.5254911090547432 + 2.5257427339819358 + 2.5259944014162241 + 2.5262461113677923 + 2.5264978638468221 + 2.5267496588635088 + 2.5270014964280492 + 2.5272533765506351 + 2.5275052992414651 + 2.5277572645107544 + 2.5280092723686964 + 2.5282613228255109 + 2.5285134158914087 + 2.5287655515766057 + 2.5290177298913163 + 2.5292699508457757 + 2.5295222144501981 + 2.5297745207148177 + 2.5300268696498636 + 2.5302792612655773 + 2.5305316955721948 + 2.5307841725799567 + 2.5310366922991054 + 2.5312892547398937 + 2.5315418599125734 + 2.5317945078273998 + 2.53204719849463 + 2.5322999319245185 + 2.532552708127342 + 2.5328055271133545 + 2.5330583888928362 + 2.5333112934760558 + 2.533564240873293 + 2.5338172310948317 + 2.5340702641509503 + 2.534323340051936 + 2.5345764588080768 + 2.5348296204296705 + 2.5350828249270094 + 2.5353360723104044 + 2.5355893625901378 + 2.5358426957765294 + 2.5360960718798924 + 2.5363494909105291 + 2.5366029528787579 + 2.5368564577949013 + 2.5371100056692755 + 2.5373635965122077 + 2.5376172303340283 + 2.53787090714507 + 2.5381246269556628 + 2.5383783897761534 + 2.538632195616874 + 2.5388860444881782 + 2.5391399364004017 + 2.5393938713639121 + 2.5396478493890506 + 2.5399018704861729 + 2.540155934665651 + 2.5404100419378439 + 2.5406641923131237 + 2.5409183858018478 + 2.5411726224144036 + 2.5414269021611626 + 2.5416812250525007 + 2.5419355910988108 + 2.5421900003104723 + 2.5424444526978762 + 2.542698948271418 + 2.542953487041498 + 2.5432080690185037 + 2.5434626942128542 + 2.5437173626349381 + 2.5439720742951843 + 2.5442268292039874 + 2.5444816273717783 + 2.5447364688089675 + 2.5449913535259752 + 2.5452462815332368 + 2.5455012528411709 + 2.5457562674602232 + 2.5460113254008157 + 2.5462664266733945 + 2.5465215712883968 + 2.5467767592562711 + 2.547031990587469 + 2.5472872652924403 + 2.5475425833816412 + 2.5477979448655237 + 2.5480533497545594 + 2.5483087980592058 + 2.5485642897899328 + 2.5488198249572118 + 2.5490754035715248 + 2.5493310256433408 + 2.5495866911831442 + 2.5498424002014168 + 2.5500981527086517 + 2.5503539487153395 + 2.5506097882319683 + 2.5508656712690518 + 2.5511215978370743 + 2.5513775679465485 + 2.5516335816079763 + 2.5518896388318786 + 2.552145739628759 + 2.5524018840091376 + 2.5526580719835446 + 2.5529143035624928 + 2.5531705787565127 + 2.5534268975761414 + 2.5536832600319088 + 2.553939666134347 + 2.5541961158940047 + 2.5544526093214226 + 2.554709146427145 + 2.5549657272217283 + 2.5552223517157255 + 2.5554790199196908 + 2.5557357318441878 + 2.5559924874997764 + 2.5562492868970277 + 2.5565061300465071 + 2.5567630169588011 + 2.5570199476444682 + 2.5572769221141045 + 2.557533940378284 + 2.5577910024476012 + 2.5580481083326454 + 2.5583052580439998 + 2.5585624515922789 + 2.5588196889880717 + 2.5590769702419842 + 2.559334295364621 + 2.5595916643665997 + 2.5598490772585274 + 2.5601065340510258 + 2.5603640347547079 + 2.5606215793802103 + 2.5608791679381491 + 2.5611368004391548 + 2.5613944768938706 + 2.5616521973129256 + 2.5619099617069607 + 2.5621677700866221 + 2.5624256224625537 + 2.5626835188454109 + 2.5629414592458435 + 2.5631994436745167 + 2.563457472142078 + 2.5637155446592028 + 2.5639736612365494 + 2.5642318218848019 + 2.5644900266146173 + 2.5647482754366804 + 2.5650065683616781 + 2.5652649054002827 + 2.5655232865631881 + 2.5657817118610904 + 2.5660401813046723 + 2.5662986949046402 + 2.5665572526716911 + 2.5668158546165301 + 2.5670745007498654 + 2.5673331910824069 + 2.5675919256248756 + 2.567850704387971 + 2.5681095273824357 + 2.5683683946189824 + 2.5686273061083433 + 2.5688862618612518 + 2.569145261888433 + 2.5694043062006298 + 2.5696633948085883 + 2.5699225277230462 + 2.570181704954758 + 2.570440926514471 + 2.5707001924129407 + 2.5709595026609278 + 2.5712188572691925 + 2.5714782562484948 + 2.5717376996096148 + 2.5719971873633138 + 2.5722567195203743 + 2.5725162960915671 + 2.5727759170876858 + 2.5730355825195108 + 2.5732952923978192 + 2.5735550467334205 + 2.573814845537103 + 2.5740746888196666 + 2.5743345765919061 + 2.5745945088646431 + 2.5748544856486788 + 2.5751145069548254 + 2.575374572793895 + 2.5756346831767165 + 2.5758948381141056 + 2.5761550376168949 + 2.5764152816959105 + 2.5766755703619841 + 2.576935903625952 + 2.5771962814986558 + 2.5774567039909457 + 2.5777171711136591 + 2.5779776828776444 + 2.5782382392937695 + 2.578498840372883 + 2.5787594861258349 + 2.5790201765635112 + 2.579280911696761 + 2.5795416915364693 + 2.5798025160934954 + 2.5800633853787289 + 2.5803242994030495 + 2.5805852581773387 + 2.5808462617124834 + 2.5811073100193807 + 2.5813684031089243 + 2.5816295409920076 + 2.5818907236795328 + 2.5821519511824147 + 2.5824132235115553 + 2.5826745406778611 + 2.582935902692252 + 2.5831973095656537 + 2.5834587613089841 + 2.58372025793317 + 2.5839817994491443 + 2.5842433858678273 + 2.584505017200172 + 2.5847666934571087 + 2.5850284146495794 + 2.5852901807885345 + 2.5855519918849215 + 2.5858138479497006 + 2.586075748993828 + 2.5863376950282526 + 2.5865996860639529 + 2.586861722111891 + 2.5871238031830344 + 2.5873859292883621 + 2.5876481004388552 + 2.5879103166454858 + 2.5881725779192473 + 2.588434884271126 + 2.5886972357121079 + 2.5889596322531974 + 2.5892220739053933 + 2.589484560679689 + 2.5897470925870993 + 2.590009669638627 + 2.5902722918452863 + 2.5905349592181004 + 2.5907976717680774 + 2.5910604295062525 + 2.5913232324436462 + 2.5915860805912927 + 2.5918489739602206 + 2.5921119125614704 + 2.5923748964060813 + 2.5926379255051013 + 2.5929009998695771 + 2.5931641195105497 + 2.5934272844390893 + 2.5936904946662498 + 2.5939537502030849 + 2.5942170510606757 + 2.594480397250075 + 2.5947437887823619 + 2.5950072256686112 + 2.5952707079199069 + 2.5955342355473259 + 2.5957978085619531 + 2.5960614269748872 + 2.596325090797218 + 2.5965888000400406 + 2.5968525547144603 + 2.5971163548315697 + 2.5973802004024873 + 2.5976440914383203 + 2.5979080279501878 + 2.5981720099492001 + 2.5984360374464823 + 2.5987001104531604 + 2.5989642289803681 + 2.5992283930392257 + 2.5994926026408778 + 2.5997568577964656 + 2.6000211585171313 + 2.6002855048140101 + 2.6005498966982667 + 2.6008143341810457 + 2.6010788172735095 + 2.601343345986816 + 2.6016079203321296 + 2.6018725403206178 + 2.6021372059634471 + 2.6024019172718029 + 2.602666674256858 + 2.6029314769297969 + 2.6031963253017953 + 2.6034612193840561 + 2.6037261591877643 + 2.6039911447241204 + 2.6042561760043146 + 2.6045212530395574 + 2.6047863758410563 + 2.6050515444200255 + 2.6053167587876707 + 2.6055820189552104 + 2.6058473249338676 + 2.6061126767348717 + 2.6063780743694469 + 2.6066435178488185 + 2.6069090071842331 + 2.6071745423869284 + 2.607440123468141 + 2.607705750439119 + 2.6079714233111133 + 2.6082371420953785 + 2.6085029068031695 + 2.6087687174457446 + 2.609034574034375 + 2.6093004765803234 + 2.6095664250948611 + 2.6098324195892597 + 2.6100984600748069 + 2.6103645465627738 + 2.6106306790644562 + 2.6108968575911438 + 2.6111630821541194 + 2.6114293527646812 + 2.6116956694341353 + 2.6119620321737842 + 2.612228440994933 + 2.6124948959088941 + 2.612761396926977 + 2.6130279440605109 + 2.613294537320809 + 2.6135611767191986 + 2.6138278622670006 + 2.6140945939755618 + 2.6143613718562126 + 2.6146281959202895 + 2.6148950661791424 + 2.6151619826441075 + 2.6154289453265469 + 2.6156959542378106 + 2.6159630093892536 + 2.6162301107922432 + 2.6164972584581392 + 2.6167644523983076 + 2.6170316926241286 + 2.617298979146979 + 2.6175663119782278 + 2.6178336911292774 + 2.6181011166114918 + 2.6183685884362728 + 2.6186361066150146 + 2.6189036711591203 + 2.6191712820799817 + 2.6194389393890072 + 2.6197066430976066 + 2.6199743932171944 + 2.620242189759181 + 2.6205100327349884 + 2.6207779221560408 + 2.6210458580337685 + 2.6213138403795968 + 2.6215818692049617 + 2.621849944521303 + 2.6221180663400623 + 2.6223862346726778 + 2.6226544495306108 + 2.6229227109253022 + 2.6231910188682166 + 2.6234593733708089 + 2.6237277744445455 + 2.623996222100891 + 2.6242647163513211 + 2.6245332572073048 + 2.624801844680325 + 2.6250704787818595 + 2.6253391595233944 + 2.6256078869164243 + 2.6258766609724371 + 2.6261454817029297 + 2.626414349119405 + 2.6266832632333661 + 2.6269522240563199 + 2.627221231599782 + 2.6274902858752567 + 2.6277593868942746 + 2.6280285346683514 + 2.6282977292090113 + 2.6285669705277974 + 2.6288362586362219 + 2.6291055935458423 + 2.6293749752681879 + 2.6296444038148103 + 2.6299138791972489 + 2.6301834014270602 + 2.6304529705158091 + 2.6307225864750419 + 2.6309922493163223 + 2.6312619590512272 + 2.6315317156913176 + 2.6318015192481741 + 2.632071369733366 + 2.6323412671584858 + 2.6326112115351123 + 2.632881202874839 + 2.6331512411892537 + 2.6334213264899602 + 2.6336914587885403 + 2.6339616380966189 + 2.6342318644258005 + 2.6345021377876909 + 2.6347724581939111 + 2.6350428256560674 + 2.6353132401857953 + 2.635583701794717 + 2.6358542104944571 + 2.6361247662966583 + 2.6363953692129511 + 2.6366660192549825 + 2.6369367164343922 + 2.63720746076284 + 2.6374782522519626 + 2.6377490909134256 + 2.6380199767588883 + 2.6382909098000082 + 2.6385618900484671 + 2.6388329175159217 + 2.6391039922140522 + 2.6393751141545376 + 2.6396462833490579 + 2.6399174998093065 + 2.6401887635469645 + 2.6404600745737294 + 2.6407314329012976 + 2.6410028385413788 + 2.6412742915056664 + 2.6415457918058758 + 2.6418173394537123 + 2.6420889344608995 + 2.6423605768391543 + 2.6426322666002102 + 2.6429040037557736 + 2.6431757883175986 + 2.6434476202974069 + 2.6437194997069411 + 2.6439914265579398 + 2.6442634008621568 + 2.6445354226313378 + 2.6448074918772395 + 2.6450796086116162 + 2.6453517728462348 + 2.6456239845928549 + 2.6458962438632478 + 2.6461685506691923 + 2.6464409050224553 + 2.6467133069348208 + 2.6469857564180739 + 2.6472582534840066 + 2.647530798144405 + 2.6478033904110716 + 2.6480760302957971 + 2.6483487178103875 + 2.6486214529666565 + 2.6488942357764049 + 2.6491670662514553 + 2.6494399444036292 + 2.6497128702447386 + 2.6499858437866122 + 2.6502588650410859 + 2.6505319340199875 + 2.6508050507351606 + 2.6510782151984422 + 2.651351427421675 + 2.6516246874167178 + 2.6518979951954118 + 2.6521713507696223 + 2.6524447541512055 + 2.6527182053520262 + 2.6529917043839579 + 2.6532652512588624 + 2.6535388459886251 + 2.6538124885851202 + 2.654086179060235 + 2.6543599174258548 + 2.6546337036938668 + 2.6549075378761722 + 2.6551814199846646 + 2.6554553500312537 + 2.6557293280278387 + 2.6560033539863359 + 2.6562774279186572 + 2.6565515498367156 + 2.6568257197524492 + 2.6570999376777591 + 2.6573742036245944 + 2.6576485176048821 + 2.6579228796305565 + 2.6581972897135655 + 2.6584717478658471 + 2.6587462540993538 + 2.6590208084260416 + 2.659295410857863 + 2.6595700614067765 + 2.6598447600847508 + 2.6601195069037513 + 2.6603943018757508 + 2.6606691450127258 + 2.6609440363266588 + 2.6612189758295313 + 2.6614939635333261 + 2.6617689994500404 + 2.662044083591673 + 2.6623192159702089 + 2.6625943965976635 + 2.6628696254860391 + 2.6631449026473493 + 2.663420228093607 + 2.6636956018368307 + 2.6639710238890446 + 2.6642464942622777 + 2.6645220129685527 + 2.6647975800199051 + 2.6650731954283775 + 2.6653488592060071 + 2.6656245713648454 + 2.665900331916935 + 2.6661761408743381 + 2.6664519982491073 + 2.6667279040533005 + 2.6670038582989908 + 2.6672798609982462 + 2.6675559121631292 + 2.6678320118057299 + 2.6681081599381247 + 2.6683843565723988 + 2.668660601720636 + 2.6689368953949351 + 2.6692132376073952 + 2.6694896283701062 + 2.6697660676951873 + 2.6700425555947347 + 2.6703190920808662 + 2.6705956771656933 + 2.6708723108613404 + 2.6711489931799335 + 2.6714257241335986 + 2.6717025037344664 + 2.6719793319946672 + 2.6722562089263544 + 2.6725331345416672 + 2.6728101088527372 + 2.6730871318717369 + 2.6733642036108196 + 2.6736413240821348 + 2.6739184932978528 + 2.674195711270138 + 2.6744729780111607 + 2.6747502935330973 + 2.6750276578481325 + 2.6753050709684425 + 2.6755825329062182 + 2.6758600436736515 + 2.6761376032829323 + 2.6764152117462641 + 2.6766928690758527 + 2.676970575283895 + 2.6772483303826138 + 2.677526134384216 + 2.6778039873009196 + 2.6780818891449529 + 2.6783598399285431 + 2.6786378396639141 + 2.6789158883633091 + 2.6791939860389618 + 2.6794721327031108 + 2.6797503283680122 + 2.6800285730459121 + 2.680306866749063 + 2.680585209489728 + 2.6808636012801683 + 2.6811420421326475 + 2.6814205320594375 + 2.6816990710728135 + 2.6819776591850562 + 2.6822562964084469 + 2.6825349827552669 + 2.6828137182378127 + 2.6830925028683823 + 2.683371336659266 + 2.6836502196227667 + 2.6839291517711956 + 2.6842081331168588 + 2.6844871636720762 + 2.6847662434491624 + 2.6850453724604453 + 2.6853245507182439 + 2.685603778234892 + 2.6858830550227286 + 2.686162381094078 + 2.6864417564613055 + 2.6867211811367286 + 2.6870006551327266 + 2.6872801784616414 + 2.6875597511358311 + 2.6878393731676584 + 2.6881190445694925 + 2.6883987653537025 + 2.6886785355326617 + 2.6889583551187508 + 2.6892382241243529 + 2.6895181425618597 + 2.6897981104436539 + 2.6900781277821331 + 2.6903581945896962 + 2.6906383108787453 + 2.6909184766616905 + 2.691198691950945 + 2.6914789567589188 + 2.6917592710980349 + 2.6920396349807083 + 2.6923200484193748 + 2.6926005114264648 + 2.6928810240144117 + 2.6931615861956537 + 2.6934421979826415 + 2.69372285938781 + 2.6940035704236269 + 2.694284331102534 + 2.694565141436998 + 2.6948460014394819 + 2.695126911122447 + 2.6954078704983782 + 2.6956888795797425 + 2.6959699383790188 + 2.6962510469086958 + 2.696532205181263 + 2.6968134132092088 + 2.6970946710050292 + 2.697375978581233 + 2.6976573359503107 + 2.6979387431247823 + 2.6982202001171562 + 2.6985017069399504 + 2.6987832636056823 + 2.6990648701268838 + 2.6993465265160776 + 2.6996282327857992 + 2.6999099889485874 + 2.7001917950169805 + 2.7004736510035254 + 2.7007555569207704 + 2.7010375127812711 + 2.7013195185975905 + 2.7016015743822783 + 2.7018836801479136 + 2.7021658359070515 + 2.7024480416722767 + 2.7027302974561724 + 2.7030126032713113 + 2.7032949591302762 + 2.7035773650456685 + 2.7038598210300804 + 2.7041423270961085 + 2.7044248832563502 + 2.704707489523428 + 2.7049901459099361 + 2.7052728524285072 + 2.7055556090917454 + 2.7058384159122797 + 2.7061212729027448 + 2.7064041800757588 + 2.7066871374439683 + 2.7069701450200081 + 2.7072532028165295 + 2.7075363108461725 + 2.7078194691215951 + 2.7081026776554515 + 2.7083859364604064 + 2.7086692455491197 + 2.7089526049342614 + 2.7092360146285075 + 2.709519474644539 + 2.7098029849950254 + 2.7100865456926644 + 2.7103701567501384 + 2.7106538181801492 + 2.7109375299953835 + 2.7112212922085548 + 2.7115051048323684 + 2.7117889678795284 + 2.712072881362753 + 2.7123568452947584 + 2.7126408596882765 + 2.7129249245560252 + 2.7132090399107427 + 2.7134932057651611 + 2.7137774221320248 + 2.7140616890240676 + 2.7143460064540532 + 2.7146303744347224 + 2.7149147929788278 + 2.7151992620991479 + 2.7154837818084361 + 2.7157683521194533 + 2.7160529730449929 + 2.7163376445978149 + 2.7166223667907117 + 2.7169071396364672 + 2.7171919631478674 + 2.7174768373377121 + 2.7177617622187928 + 2.7180467378039213 + 2.7183317641058999 + 2.7186168411375395 + 2.7189019689116538 + 2.7191871474410649 + 2.7194723767385978 + 2.7197576568170732 + 2.7200429876893391 + 2.7203283693682119 + 2.7206138018665484 + 2.7208992851971883 + 2.7211848193729766 + 2.7214704044067699 + 2.7217560403114245 + 2.7220417270998021 + 2.7223274647847764 + 2.7226132533792073 + 2.7228990928959695 + 2.7231849833479465 + 2.7234709247480215 + 2.7237569171090836 + 2.7240429604440188 + 2.7243290547657244 + 2.7246152000870985 + 2.7249013964210502 + 2.7251876437804863 + 2.7254739421783127 + 2.7257602916274575 + 2.7260466921408324 + 2.7263331437313711 + 2.7266196464119949 + 2.7269062001956388 + 2.7271928050952465 + 2.7274794611237581 + 2.7277661682941168 + 2.7280529266192755 + 2.7283397361121917 + 2.7286265967858241 + 2.7289135086531378 + 2.7292004717270903 + 2.7294874860206684 + 2.729774551546841 + 2.7300616683185894 + 2.7303488363488997 + 2.7306360556507587 + 2.7309233262371682 + 2.7312106481211158 + 2.7314980213156077 + 2.7317854458336486 + 2.7320729216882582 + 2.7323604488924391 + 2.7326480274592151 + 2.7329356574016135 + 2.733223338732663 + 2.7335110714653852 + 2.7337988556128261 + 2.7340866911880277 + 2.7343745782040263 + 2.7346625166738816 + 2.7349505066106392 + 2.7352385480273598 + 2.7355266409371048 + 2.7358147853529466 + 2.7361029812879467 + 2.7363912287551893 + 2.7366795277677469 + 2.736967878338707 + 2.7372562804811618 + 2.7375447342081927 + 2.7378332395329119 + 2.7381217964684037 + 2.7384104050277847 + 2.7386990652241607 + 2.7389877770706441 + 2.739276540580363 + 2.7395653557664299 + 2.7398542226419762 + 2.740143141220122 + 2.7404321115140284 + 2.7407211335368116 + 2.7410102073016245 + 2.741299332821622 + 2.7415885101099486 + 2.7418777391797686 + 2.7421670200442372 + 2.7424563527165229 + 2.7427457372098027 + 2.7430351735372409 + 2.7433246617120215 + 2.7436142017473277 + 2.7439037936563508 + 2.7441934374522821 + 2.7444831331483144 + 2.7447728807576519 + 2.7450626802935005 + 2.745352531769067 + 2.7456424351975697 + 2.7459323905922171 + 2.7462223979662479 + 2.746512457332877 + 2.7468025687053421 + 2.7470927320968768 + 2.7473829475207241 + 2.7476732149901215 + 2.747963534518326 + 2.7482539061185896 + 2.7485443298041696 + 2.7488348055883307 + 2.7491253334843284 + 2.7494159135054521 + 2.7497065456649628 + 2.7499972299761422 + 2.7502879664522863 + 2.7505787551066705 + 2.7508695959525866 + 2.7511604890033499 + 2.7514514342722438 + 2.7517424317725805 + 2.752033481517671 + 2.7523245835208372 + 2.7526157377953879 + 2.7529069443546534 + 2.7531982032119542 + 2.7534895143806337 + 2.7537808778740271 + 2.754072293705474 + 2.7543637618883152 + 2.754655282435905 + 2.7549468553616037 + 2.7552384806787655 + 2.755530158400755 + 2.7558218885409445 + 2.756113671112697 + 2.7564055061293926 + 2.7566973936044175 + 2.7569893335511604 + 2.7572813259829978 + 2.7575733709133412 + 2.7578654683555777 + 2.7581576183231196 + 2.758449820829366 + 2.7587420758877386 + 2.7590343835116489 + 2.7593267437145195 + 2.7596191565097778 + 2.7599116219108475 + 2.7602041399311719 + 2.7604967105841869 + 2.7607893338833467 + 2.7610820098420765 + 2.7613747384738532 + 2.7616675197921174 + 2.7619603538103368 + 2.7622532405419808 + 2.7625461800005153 + 2.7628391721994165 + 2.7631322171521613 + 2.7634253148722374 + 2.7637184653731337 + 2.7640116686683429 + 2.7643049247713654 + 2.7645982336956942 + 2.7648915954548419 + 2.7651850100623241 + 2.7654784775316403 + 2.76577199787633 + 2.7660655711099054 + 2.7663591972458996 + 2.7666528762978464 + 2.7669466082792797 + 2.7672403932037457 + 2.7675342310847952 + 2.7678281219359735 + 2.7681220657708323 + 2.7684160626029448 + 2.7687101124458642 + 2.769004215313168 + 2.7692983712184254 + 2.7695925801752184 + 2.7698868421971294 + 2.7701811572977424 + 2.7704755254906503 + 2.7707699467894593 + 2.7710644212077531 + 2.7713589487591532 + 2.7716535294572577 + 2.7719481633156962 + 2.7722428503480736 + 2.772537590568021 + 2.7728323839891695 + 2.7731272306251404 + 2.7734221304895836 + 2.7737170835961296 + 2.7740120899584402 + 2.7743071495901521 + 2.7746022625049265 + 2.7748974287164256 + 2.7751926482383076 + 2.7754879210842525 + 2.7757832472679245 + 2.776078626803006 + 2.7763740597031772 + 2.7766695459821293 + 2.7769650856535577 + 2.7772606787311465 + 2.7775563252286082 + 2.7778520251596439 + 2.7781477785379676 + 2.7784435853772855 + 2.7787394456913344 + 2.7790353594938213 + 2.7793313267984816 + 2.7796273476190474 + 2.7799234219692579 + 2.7802195498628635 + 2.7805157313135926 + 2.7808119663352073 + 2.7811082549414694 + 2.7814045971461296 + 2.7817009929629579 + 2.781997442405725 + 2.7822939454882074 + 2.7825905022241724 + 2.7828871126274177 + 2.7831837767117285 + 2.7834804944908909 + 2.783777265978713 + 2.7840740911889923 + 2.7843709701355324 + 2.7846679028321439 + 2.7849648892926493 + 2.7852619295308667 + 2.7855590235606216 + 2.7858561713957415 + 2.7861533730500625 + 2.7864506285374238 + 2.7867479378716755 + 2.7870453010666556 + 2.7873427181362187 + 2.7876401890942288 + 2.7879377139545398 + 2.7882352927310263 + 2.7885329254375599 + 2.7888306120880095 + 2.7891283526962654 + 2.7894261472762065 + 2.7897239958417299 + 2.7900218984067204 + 2.790319854985075 + 2.7906178655907148 + 2.790915930237539 + 2.7912140489394606 + 2.7915122217103967 + 2.7918104485642692 + 2.7921087295150091 + 2.7924070645765497 + 2.7927054537628209 + 2.793003897087774 + 2.793302394565345 + 2.7936009462094917 + 2.7938995520341687 + 2.7941982120533315 + 2.7944969262809525 + 2.7947956947309889 + 2.7950945174174286 + 2.7953933943542428 + 2.7956923255554131 + 2.7959913110349333 + 2.7962903508067969 + 2.7965894448849977 + 2.796888593283537 + 2.7971877960164235 + 2.7974870530976705 + 2.797786364541289 + 2.7980857303613043 + 2.7983851505717472 + 2.7986846251866395 + 2.7989841542200193 + 2.7992837376859301 + 2.7995833755984112 + 2.7998830679715163 + 2.8001828148192907 + 2.8004826161558074 + 2.8007824719951189 + 2.8010823823512956 + 2.8013823472384072 + 2.801682366670537 + 2.8019824406617735 + 2.8022825692261875 + 2.8025827523778837 + 2.8028829901309535 + 2.8031832824994951 + 2.8034836294976211 + 2.8037840311394437 + 2.8040844874390691 + 2.8043849984106219 + 2.8046855640682264 + 2.804986184426022 + 2.8052868594981244 + 2.805587589298685 + 2.805888373841853 + 2.8061892131417641 + 2.8064901072125767 + 2.8067910560684526 + 2.8070920597235514 + 2.8073931181920426 + 2.8076942314880937 + 2.8079953996258937 + 2.8082966226196096 + 2.8085979004834396 + 2.8088992332315663 + 2.8092006208781983 + 2.809502063437523 + 2.8098035609237515 + 2.8101051133511037 + 2.8104067207337811 + 2.81070838308601 + 2.8110101004220143 + 2.8113118727560273 + 2.8116137001022841 + 2.8119155824750184 + 2.8122175198884709 + 2.8125195123569053 + 2.8128215598945636 + 2.8131236625157081 + 2.8134258202345985 + 2.8137280330655101 + 2.8140303010227141 + 2.81433262412048 + 2.8146350023731022 + 2.8149374357948571 + 2.8152399244000459 + 2.8155424682029611 + 2.8158450672179041 + 2.8161477214591861 + 2.8164504309411154 + 2.8167531956780025 + 2.8170560156841788 + 2.8173588909739675 + 2.817661821561694 + 2.8179648074617045 + 2.8182678486883272 + 2.818570945255912 + 2.8188740971788171 + 2.8191773044713822 + 2.8194805671479806 + 2.8197838852229729 + 2.82008725871072 + 2.8203906876256108 + 2.8206941719820127 + 2.820997711794317 + 2.8213013070769124 + 2.8216049578441909 + 2.8219086641105426 + 2.8222124258903878 + 2.8225162431981183 + 2.8228201160481583 + 2.8231240444549193 + 2.8234280284328372 + 2.8237320679963194 + 2.8240361631598163 + 2.8243403139377543 + 2.8246445203445805 + 2.8249487823947481 + 2.825253100102695 + 2.8255574734828905 + 2.825861902549792 + 2.8261663873178624 + 2.8264709278015814 + 2.8267755240154213 + 2.8270801759738649 + 2.8273848836913924 + 2.8276896471825057 + 2.8279944664616932 + 2.8282993415434605 + 2.8286042724423077 + 2.828909259172756 + 2.8292143017493134 + 2.8295194001864976 + 2.8298245544988432 + 2.8301297647008736 + 2.8304350308071258 + 2.8307403528321471 + 2.8310457307904686 + 2.8313511646966547 + 2.8316566545652546 + 2.8319622004108225 + 2.832267802247936 + 2.8325734600911616 + 2.8328791739550607 + 2.8331849438542278 + 2.8334907698032441 + 2.8337966518166979 + 2.834102589909187 + 2.8344085840953017 + 2.8347146343896528 + 2.8350207408068577 + 2.8353269033615116 + 2.835633122068256 + 2.8359393969416971 + 2.8362457279964715 + 2.8365521152472146 + 2.8368585587085597 + 2.8371650583951578 + 2.8374716143216534 + 2.8377782265027078 + 2.8380848949529747 + 2.838391619687116 + 2.8386984007197982 + 2.8390052380657065 + 2.8393121317395087 + 2.8396190817558948 + 2.8399260881295474 + 2.8402331508751661 + 2.8405402700074522 + 2.8408474455411006 + 2.8411546774908296 + 2.8414619658713418 + 2.8417693106973658 + 2.8420767119836232 + 2.8423841697448378 + 2.842691683995743 + 2.8429992547510858 + 2.8433068820256069 + 2.8436145658340539 + 2.8439223061911774 + 2.8442301031117396 + 2.8445379566105031 + 2.8448458667022414 + 2.8451538334017177 + 2.8454618567237189 + 2.8457699366830309 + 2.8460780732944344 + 2.84638626657273 + 2.8466945165327089 + 2.8470028231891842 + 2.84731118655696 + 2.847619606650849 + 2.8479280834856735 + 2.8482366170762576 + 2.8485452074374265 + 2.8488538545840161 + 2.8491625585308729 + 2.8494713192928298 + 2.8497801368847386 + 2.8500890113214572 + 2.8503979426178434 + 2.8507069307887609 + 2.851015975849081 + 2.8513250778136725 + 2.851634236697425 + 2.8519434525152136 + 2.8522527252819354 + 2.8525620550124775 + 2.852871441721748 + 2.8531808854246483 + 2.853490386136079 + 2.853799943870972 + 2.8541095586442364 + 2.854419230470802 + 2.8547289593655965 + 2.8550387453435513 + 2.8553485884196173 + 2.8556584886087322 + 2.8559684459258436 + 2.8562784603859117 + 2.8565885320039066 + 2.8568986607947799 + 2.8572088467735073 + 2.8575190899550686 + 2.8578293903544423 + 2.8581397479866091 + 2.8584501628665704 + 2.8587606350093187 + 2.8590711644298503 + 2.8593817511431774 + 2.8596923951643141 + 2.8600030965082661 + 2.860313855190066 + 2.860624671224743 + 2.860935544627321 + 2.8612464754128406 + 2.8615574635963483 + 2.8618685091928859 + 2.8621796122175072 + 2.8624907726852729 + 2.8628019906112407 + 2.8631132660104912 + 2.8634245988980829 + 2.8637359892891023 + 2.8640474371986269 + 2.8643589426417546 + 2.8646705056335815 + 2.8649821261891897 + 2.8652938043236982 + 2.8656055400522127 + 2.8659173333898416 + 2.8662291843517154 + 2.8665410929529549 + 2.8668530592086783 + 2.8671650831340432 + 2.8674771647441748 + 2.8677893040542193 + 2.8681015010793303 + 2.8684137558346627 + 2.8687260683353828 + 2.8690384385966436 + 2.8693508666336314 + 2.8696633524615174 + 2.8699758960954771 + 2.8702884975507059 + 2.8706011568423961 + 2.8709138739857401 + 2.8712266489959415 + 2.8715394818882101 + 2.8718523726777518 + 2.8721653213797995 + 2.8724783280095672 + 2.8727913925822754 + 2.8731045151131736 + 2.8734176956174915 + 2.8737309341104709 + 2.874044230607371 + 2.8743575851234424 + 2.8746709976739444 + 2.8749844682741337 + 2.875297996939294 + 2.8756115836846945 + 2.8759252285256154 + 2.8762389314773413 + 2.876552692555165 + 2.8768665117743866 + 2.8771803891503032 + 2.8774943246982225 + 2.8778083184334649 + 2.8781223703713339 + 2.8784364805271627 + 2.878750648916272 + 2.8790648755539952 + 2.8793791604556791 + 2.8796935036366582 + 2.8800079051122895 + 2.8803223648979164 + 2.8806368830089069 + 2.8809514594606234 + 2.8812660942684345 + 2.8815807874477213 + 2.8818955390138532 + 2.8822103489822291 + 2.8825252173682321 + 2.882840144187254 + 2.8831551294547046 + 2.8834701731859873 + 2.8837852753965181 + 2.8841004361017082 + 2.884415655316984 + 2.8847309330577713 + 2.8850462693395142 + 2.8853616641776338 + 2.8856771175875875 + 2.8859926295848126 + 2.8863082001847751 + 2.8866238294029301 + 2.8869395172547381 + 2.8872552637556792 + 2.8875710689212215 + 2.8878869327668499 + 2.8882028553080508 + 2.8885188365603125 + 2.8888348765391325 + 2.8891509752600175 + 2.8894671327384667 + 2.8897833489900036 + 2.8900996240301398 + 2.8904159578744024 + 2.8907323505383142 + 2.8910488020374139 + 2.8913653123872387 + 2.8916818816033394 + 2.8919985097012648 + 2.892315196696567 + 2.8926319426048011 + 2.8929487474415514 + 2.8932656112223731 + 2.8935825339628445 + 2.893899515678557 + 2.8942165563850968 + 2.8945336560980506 + 2.8948508148330148 + 2.8951680326056031 + 2.8954853094314243 + 2.8958026453260799 + 2.896120040305203 + 2.8964374943844153 + 2.8967550075793453 + 2.8970725799056298 + 2.8973902113789127 + 2.8977079020148384 + 2.8980256518290619 + 2.8983434608372343 + 2.8986613290550296 + 2.8989792564981007 + 2.8992972431821387 + 2.8996152891228095 + 2.8999333943358057 + 2.9002515588368127 + 2.9005697826415218 + 2.9008880657656446 + 2.9012064082248794 + 2.9015248100349429 + 2.9018432712115469 + 2.9021617917704159 + 2.9024803717272798 + 2.9027990110978692 + 2.9031177098979217 + 2.9034364681431857 + 2.9037552858494071 + 2.9040741630323463 + 2.9043930997077552 + 2.9047120958914023 + 2.9050311515990699 + 2.905350266846515 + 2.9056694416495379 + 2.9059886760239095 + 2.9063079699854373 + 2.9066273235499103 + 2.9069467367331434 + 2.9072662095509312 + 2.9075857420191022 + 2.9079053341534635 + 2.9082249859698512 + 2.9085446974840976 + 2.908864468712026 + 2.9091842996694934 + 2.9095041903723438 + 2.9098241408364229 + 2.9101441510775978 + 2.9104642211117215 + 2.91078435095468 + 2.9111045406223353 + 2.9114247901305665 + 2.9117450994952718 + 2.9120654687323371 + 2.9123858978576509 + 2.9127063868871241 + 2.9130269358366676 + 2.9133475447221842 + 2.9136682135596019 + 2.9139889423648428 + 2.9143097311538364 + 2.9146305799425156 + 2.9149514887468193 + 2.9152724575827045 + 2.9155934864661095 + 2.915914575413006 + 2.9162357244393458 + 2.916556933561099 + 2.916878202794237 + 2.9171995321547515 + 2.9175209216586242 + 2.9178423713218349 + 2.918163881160392 + 2.9184854511902891 + 2.9188070814275342 + 2.9191287718881442 + 2.9194505225881366 + 2.9197723335435288 + 2.9200942047703613 + 2.9204161362846555 + 2.9207381281024576 + 2.9210601802398184 + 2.9213822927127868 + 2.9217044655374202 + 2.9220266987297792 + 2.9223489923059303 + 2.9226713462819522 + 2.9229937606739225 + 2.9233162354979232 + 2.923638770770046 + 2.923961366506389 + 2.924284022723056 + 2.9246067394361495 + 2.9249295166617864 + 2.9252523544160787 + 2.9255752527151522 + 2.9258982115751442 + 2.9262212310121818 + 2.9265443110424085 + 2.9268674516819688 + 2.9271906529470222 + 2.9275139148537148 + 2.9278372374182151 + 2.9281606206566906 + 2.9284840645853234 + 2.9288075692202802 + 2.9291311345777573 + 2.9294547606739472 + 2.9297784475250346 + 2.9301021951472284 + 2.9304260035567427 + 2.9307498727697801 + 2.9310738028025658 + 2.9313977936713282 + 2.9317218453922949 + 2.9320459579816998 + 2.9323701314557846 + 2.9326943658307965 + 2.933018661122996 + 2.9333430173486312 + 2.9336674345239784 + 2.9339919126652925 + 2.9343164517888667 + 2.9346410519109676 + 2.9349657130478852 + 2.9352904352159208 + 2.9356152184313675 + 2.9359400627105217 + 2.9362649680697075 + 2.9365899345252284 + 2.9369149620934145 + 2.9372400507905767 + 2.9375652006330646 + 2.9378904116372095 + 2.9382156838193603 + 2.9385410171958615 + 2.9388664117830641 + 2.9391918675973367 + 2.9395173846550389 + 2.9398429629725507 + 2.9401686025662395 + 2.9404943034524997 + 2.9408200656477148 + 2.9411458891682765 + 2.9414717740305956 + 2.9417977202510719 + 2.9421237278461136 + 2.9424497968321415 + 2.9427759272255876 + 2.9431021190428672 + 2.9434283723004255 + 2.9437546870146978 + 2.9440810632021299 + 2.944407500879183 + 2.944734000062303 + 2.9450605607679581 + 2.9453871830126213 + 2.9457138668127669 + 2.9460406121848681 + 2.9463674191454197 + 2.946694287710907 + 2.947021217897833 + 2.9473482097227026 + 2.9476752632020182 + 2.9480023783523053 + 2.9483295551900799 + 2.9486567937318608 + 2.9489840939941905 + 2.9493114559936067 + 2.949638879746654 + 2.9499663652698773 + 2.9502939125798324 + 2.9506215216930842 + 2.9509491926261977 + 2.9512769253957498 + 2.9516047200183171 + 2.9519325765104805 + 2.9522604948888347 + 2.9525884751699727 + 2.9529165173704977 + 2.9532446215070172 + 2.9535727875961451 + 2.9539010156544969 + 2.9542293056987008 + 2.9545576577453905 + 2.954886071811202 + 2.9552145479127754 + 2.955543086066756 + 2.9558716862898069 + 2.9562003485985762 + 2.9565290730097407 + 2.9568578595399586 + 2.9571867082059238 + 2.9575156190243126 + 2.9578445920118073 + 2.95817362718511 + 2.9585027245609221 + 2.9588318841559409 + 2.9591611059868881 + 2.959490390070481 + 2.9598197364234511 + 2.9601491450625077 + 2.9604786160044023 + 2.9608081492658682 + 2.9611377448636635 + 2.9614674028145358 + 2.9617971231352342 + 2.962126905842541 + 2.9624567509532134 + 2.9627866584840348 + 2.9631166284517949 + 2.9634466608732719 + 2.9637767557652559 + 2.9641069131445579 + 2.9644371330279746 + 2.9647674154323247 + 2.9650977603744297 + 2.9654281678711047 + 2.9657586379391896 + 2.9660891705955068 + 2.9664197658569051 + 2.9667504237402307 + 2.9670811442623406 + 2.9674119274400872 + 2.967742773290341 + 2.9680736818299707 + 2.9684046530758517 + 2.9687356870448718 + 2.9690667837539144 + 2.9693979432198754 + 2.969729165459658 + 2.9700604504901627 + 2.9703917983283139 + 2.9707232089910156 + 2.9710546824952022 + 2.9713862188577926 + 2.9717178180957355 + 2.9720494802259738 + 2.972381205265441 + 2.9727129932311032 + 2.97304484413992 + 2.9733767580088504 + 2.9737087348548705 + 2.9740407746949584 + 2.974372877546092 + 2.9747050434252689 + 2.975037272349482 + 2.9753695643357343 + 2.9757019194010335 + 2.9760343375623837 + 2.9763668188368171 + 2.9766993632413477 + 2.9770319707930248 + 2.9773646415088639 + 2.9776973754059242 + 2.9780301725012452 + 2.9783630328118922 + 2.9786959563549198 + 2.9790289431473904 + 2.9793619932063868 + 2.9796951065489865 + 2.9800282831922686 + 2.9803615231533351 + 2.9806948264492772 + 2.9810281930972007 + 2.9813616231142119 + 2.9816951165174199 + 2.9820286733239585 + 2.9823622935509504 + 2.9826959772155317 + 2.9830297243348385 + 2.9833635349260126 + 2.9836974090062109 + 2.9840313465925936 + 2.9843653477023109 + 2.9846994123525512 + 2.9850335405604782 + 2.9853677323432724 + 2.9857019877181314 + 2.9860363067022404 + 2.9863706893128041 + 2.98670513556702 + 2.9870396454821129 + 2.9873742190752881 + 2.9877088563637777 + 2.9880435573648132 + 2.9883783220956284 + 2.988713150573461 + 2.9890480428155661 + 2.9893829988391891 + 2.9897180186616028 + 2.9900531023000609 + 2.9903882497718519 + 2.990723461094241 + 2.9910587362845167 + 2.9913940753599682 + 2.9917294783378958 + 2.9920649452356067 + 2.9924004760703982 + 2.9927360708595976 + 2.9930717296205209 + 2.9934074523704912 + 2.993743239126851 + 2.9940790899069367 + 2.9944150047280913 + 2.9947509836076724 + 2.9950870265630245 + 2.99542313361153 + 2.9957593047705475 + 2.9960955400574609 + 2.9964318394896488 + 2.9967682030844971 + 2.997104630859404 + 2.9974411228317672 + 2.9977776790190016 + 2.9981142994385115 + 2.9984509841077251 + 2.9987877330440598 + 2.9991245462649521 + 2.9994614237878339 + 2.9997983656301597 + 3.0001353718093715 + 3.0004724423429305 + 3.0008095772482903 + 3.0011467765429289 + 3.0014840402443133 + 3.0018213683699386 + 3.002158760937276 + 3.0024962179638344 + 3.0028337394670972 + 3.0031713254645815 + 3.0035089759737921 + 3.0038466910122525 + 3.0041844705974801 + 3.0045223147470139 + 3.0048602234783908 + 3.0051981968091459 + 3.0055362347568289 + 3.0058743373390007 + 3.0062125045732202 + 3.0065507364770547 + 3.0068890330680826 + 3.0072273943638801 + 3.0075658203820339 + 3.0079043111401327 + 3.0082428666557774 + 3.0085814869465763 + 3.0089201720301375 + 3.0092589219240851 + 3.0095977366460342 + 3.0099366162136216 + 3.0102755606444771 + 3.0106145699562461 + 3.0109536441665772 + 3.0112927832931291 + 3.0116319873535535 + 3.0119712563655283 + 3.0123105903467193 + 3.0126499893148124 + 3.0129894532874983 + 3.0133289822824545 + 3.0136685763173836 + 3.0140082354100022 + 3.0143479595780089 + 3.0146877488391324 + 3.0150276032110885 + 3.0153675227116103 + 3.0157075073584356 + 3.0160475571693 + 3.0163876721619634 + 3.0167278523541663 + 3.0170680977636901 + 3.0174084084082864 + 3.0177487843057316 + 3.0180892254738132 + 3.0184297319303117 + 3.0187703036930298 + 3.0191109407797576 + 3.0194516432082983 + 3.0197924109964718 + 3.0201332441620927 + 3.0204741427229882 + 3.0208151066969839 + 3.0211561361019248 + 3.0214972309556489 + 3.0218383912760092 + 3.0221796170808561 + 3.0225209083880586 + 3.0228622652154868 + 3.0232036875810109 + 3.0235451755025156 + 3.0238867289978901 + 3.0242283480850221 + 3.0245700327818277 + 3.0249117831061945 + 3.0252535990760521 + 3.025595480709304 + 3.0259374280238949 + 3.026279441037746 + 3.0266215197688022 + 3.0269636642349971 + 3.0273058744543002 + 3.0276481504446573 + 3.0279904922240357 + 3.0283328998104069 + 3.0286753732217453 + 3.029017912476037 + 3.0293605175912708 + 3.0297031885854464 + 3.0300459254765606 + 3.0303887282826341 + 3.0307315970216711 + 3.0310745317116994 + 3.0314175323707446 + 3.0317605990168475 + 3.0321037316680353 + 3.0324469303423713 + 3.0327901950579084 + 3.0331335258326915 + 3.0334769226848062 + 3.033820385632318 + 3.0341639146933042 + 3.0345075098858549 + 3.0348511712280617 + 3.035194898738022 + 3.0355386924338474 + 3.035882552333645 + 3.036226478455534 + 3.0365704708176406 + 3.0369145294380986 + 3.0372586543350368 + 3.0376028455266089 + 3.0379471030309642 + 3.0382914268662571 + 3.0386358170506513 + 3.0389802736023177 + 3.0393247965394381 + 3.0396693858801909 + 3.0400140416427615 + 3.0403587638453531 + 3.0407035525061725 + 3.0410484076434199 + 3.0413933292753081 + 3.0417383174200689 + 3.0420833720959268 + 3.0424284933211196 + 3.0427736811138848 + 3.0431189354924699 + 3.0434642564751386 + 3.0438096440801403 + 3.0441550983257533 + 3.0445006192302397 + 3.0448462068118869 + 3.0451918610889845 + 3.0455375820798323 + 3.0458833698027168 + 3.0462292242759461 + 3.0465751455178447 + 3.0469211335467281 + 3.0472671883809186 + 3.0476133100387517 + 3.0479594985385625 + 3.0483057538987088 + 3.048652076137532 + 3.0489984652733981 + 3.0493449213246713 + 3.0496914443097229 + 3.0500380342469331 + 3.0503846911546812 + 3.050731415051366 + 3.0510782059553896 + 3.0514250638851452 + 3.0517719888590622 + 3.0521189808955422 + 3.0524660400130159 + 3.0528131662299178 + 3.0531603595646866 + 3.0535076200357598 + 3.0538549476615953 + 3.0542023424606572 + 3.0545498044513941 + 3.0548973336522893 + 3.0552449300818143 + 3.0555925937584529 + 3.0559403247007078 + 3.0562881229270609 + 3.0566359884560295 + 3.0569839213061143 + 3.0573319214958414 + 3.0576799890437325 + 3.0580281239683145 + 3.0583763262881196 + 3.058724596021706 + 3.0590729331876192 + 3.0594213378044217 + 3.0597698098906601 + 3.0601183494649238 + 3.0604669565457794 + 3.0608156311518124 + 3.0611643733016169 + 3.0615131830137861 + 3.0618620603069333 + 3.0622110051996554 + 3.0625600177105752 + 3.0629090978583244 + 3.0632582456615203 + 3.0636074611388135 + 3.0639567443088391 + 3.0643060951902537 + 3.0646555138017062 + 3.0650050001618658 + 3.0653545542894078 + 3.0657041762030066 + 3.0660538659213392 + 3.0664036234631036 + 3.0667534488469919 + 3.0671033420917198 + 3.0674533032159914 + 3.0678033322385243 + 3.0681534291780457 + 3.0685035940532783 + 3.0688538268829708 + 3.0692041276858624 + 3.0695544964807024 + 3.069904933286256 + 3.0702554381212814 + 3.0706060110045534 + 3.0709566519548446 + 3.0713073609909483 + 3.0716581381316588 + 3.0720089833957611 + 3.0723598968020682 + 3.0727108783693984 + 3.0730619281165552 + 3.0734130460623827 + 3.0737642322256988 + 3.0741154866253511 + 3.0744668092801795 + 3.0748182002090418 + 3.0751696594307951 + 3.0755211869643078 + 3.0758727828284473 + 3.0762244470420987 + 3.0765761796241438 + 3.0769279805934886 + 3.0772798499690173 + 3.0776317877696422 + 3.0779837940142829 + 3.0783358687218549 + 3.0786880119112898 + 3.0790402236015115 + 3.0793925038114747 + 3.0797448525601165 + 3.0800972698663984 + 3.0804497557492811 + 3.0808023102277229 + 3.0811549333207138 + 3.0815076250472346 + 3.0818603854262605 + 3.0822132144768037 + 3.0825661122178487 + 3.0829190786684282 + 3.083272113847535 + 3.0836252177742045 + 3.0839783904674687 + 3.0843316319463585 + 3.0846849422299218 + 3.0850383213372043 + 3.0853917692872668 + 3.0857452860991699 + 3.086098871791997 + 3.0864525263848095 + 3.0868062498966995 + 3.0871600423467562 + 3.0875139037540928 + 3.0878678341377932 + 3.0882218335169793 + 3.088575901910775 + 3.088930039338305 + 3.0892842458186953 + 3.0896385213710849 + 3.0899928660146383 + 3.0903472797684923 + 3.0907017626518143 + 3.091056314683772 + 3.0914109358835371 + 3.0917656262702971 + 3.0921203858632262 + 3.0924752146815409 + 3.0928301127444269 + 3.0931850800710987 + 3.0935401166807761 + 3.0938952225926739 + 3.0942503978260354 + 3.0946056424000812 + 3.094960956334071 + 3.0953163396472467 + 3.0956717923588628 + 3.0960273144881962 + 3.0963829060545094 + 3.0967385670770859 + 3.0970942975752056 + 3.0974500975681671 + 3.097805967075268 + 3.0981619061158114 + 3.0985179147091171 + 3.0988739928745037 + 3.0992301406313021 + 3.0995863579988394 + 3.0999426449964584 + 3.1002990016435139 + 3.1006554279593543 + 3.1010119239633496 + 3.1013684896748712 + 3.1017251251132842 + 3.102081830297974 + 3.1024386052483406 + 3.1027954499837782 + 3.1031523645236887 + 3.1035093488874863 + 3.1038664030945937 + 3.1042235271644243 + 3.104580721116414 + 3.1049379849700163 + 3.1052953187446679 + 3.1056527224598258 + 3.1060101961349487 + 3.1063677397895013 + 3.1067253534429633 + 3.1070830371148217 + 3.1074407908245516 + 3.1077986145916601 + 3.1081565084356515 + 3.1085144723760352 + 3.1088725064323226 + 3.1092306106240395 + 3.1095887849707244 + 3.1099470294919116 + 3.110305344207148 + 3.1106637291359829 + 3.1110221842979855 + 3.1113807097127126 + 3.1117393053997433 + 3.1120979713786476 + 3.1124567076690388 + 3.1128155142904976 + 3.1131743912626244 + 3.1135333386050297 + 3.1138923563373342 + 3.1142514444791622 + 3.1146106030501399 + 3.1149698320699097 + 3.11532913155812 + 3.1156885015344118 + 3.1160479420184521 + 3.1164074530299146 + 3.1167670345884595 + 3.1171266867137808 + 3.1174864094255521 + 3.1178462027434835 + 3.1182060666872706 + 3.1185660012766259 + 3.1189260065312592 + 3.119286082470905 + 3.1196462291152867 + 3.1200064464841422 + 3.1203667345972184 + 3.1207270934742777 + 3.121087523135063 + 3.1214480235993483 + 3.1218085948869225 + 3.1221692370175411 + 3.1225299500110162 + 3.1228907338871239 + 3.1232515886656844 + 3.1236125143664966 + 3.1239735110093769 + 3.1243345786141639 + 3.1246957172006762 + 3.1250569267887554 + 3.1254182073982539 + 3.1257795590490161 + 3.1261409817609032 + 3.1265024755538002 + 3.1268640404475576 + 3.1272256764620745 + 3.127587383617243 + 3.1279491619329414 + 3.1283110114290946 + 3.1286729321256002 + 3.129034924042386 + 3.1293969871993683 + 3.1297591216164871 + 3.1301213273136854 + 3.1304836043109043 + 3.1308459526281038 + 3.13120837228524 + 3.131570863302291 + 3.1319334256992279 + 3.132296059496035 + 3.1326587647127062 + 3.1330215413692364 + 3.1333843894856384 + 3.1337473090819179 + 3.1341103001781017 + 3.1344733627942101 + 3.1348364969502938 + 3.1351997026663754 + 3.1355629799625131 + 3.1359263288587695 + 3.1362897493752002 + 3.1366532415318895 + 3.1370168053489018 + 3.1373804408463295 + 3.1377441480442716 + 3.1381079269628191 + 3.1384717776220898 + 3.138835700042196 + 3.1391996942432598 + 3.1395637602454078 + 3.139927898068791 + 3.1402921077335386 + 3.1406563892598154 + 3.1410207426677732 + 3.1413851679775866 + 3.1417496652094217 + 3.1421142343834734 + 3.1424788755199131 + 3.1428435886389501 + 3.1432083737607894 + 3.1435732309056377 + 3.1439381600937089 + 3.1443031613452423 + 3.1446682346804611 + 3.1450333801196164 + 3.1453985976829451 + 3.145763887390713 + 3.1461292492631716 + 3.1464946833206047 + 3.1468601895832844 + 3.147225768071495 + 3.147591418805527 + 3.1479571418056924 + 3.1483229370922881 + 3.1486888046856314 + 3.1490547446060528 + 3.1494207568738735 + 3.1497868415094308 + 3.1501529985330738 + 3.1505192279651588 + 3.1508855298260356 + 3.1512519041360747 + 3.1516183509156606 + 3.1519848701851676 + 3.1523514619649822 + 3.1527181262755022 + 3.1530848631371406 + 3.1534516725703097 + 3.1538185545954143 + 3.1541855092329003 + 3.1545525365031892 + 3.1549196364267291 + 3.1552868090239614 + 3.1556540543153582 + 3.1560213723213768 + 3.1563887630624836 + 3.1567562265591653 + 3.15712376283191 + 3.1574913719012012 + 3.1578590537875542 + 3.1582268085114755 + 3.1585946360934707 + 3.158962536554085 + 3.1593305099138353 + 3.159698556193268 + 3.1600666754129296 + 3.1604348675933771 + 3.1608031327551624 + 3.1611714709188665 + 3.1615398821050635 + 3.1619083663343419 + 3.1622769236272812 + 3.1626455540045026 + 3.1630142574865943 + 3.1633830340941884 + 3.1637518838478891 + 3.164120806768342 + 3.1644898028761861 + 3.1648588721920521 + 3.1652280147366065 + 3.1655972305305085 + 3.1659665195944218 + 3.1663358819490268 + 3.1667053176150022 + 3.1670748266130446 + 3.1674444089638487 + 3.1678140646881268 + 3.1681837938065818 + 3.1685535963399487 + 3.1689234723089523 + 3.1692934217343178 + 3.169663444636805 + 3.1700335410371601 + 3.1704037109561467 + 3.1707739544145261 + 3.1711442714330791 + 3.1715146620325805 + 3.1718851262338266 + 3.1722556640576172 + 3.1726262755247556 + 3.1729969606560569 + 3.1733677194723344 + 3.1737385519944246 + 3.1741094582431653 + 3.1744804382393941 + 3.1748514920039628 + 3.1752226195577404 + 3.1755938209215806 + 3.175965096116367 + 3.1763364451629834 + 3.1767078680823095 + 3.17707936489525 + 3.1774509356227156 + 3.1778225802856115 + 3.1781942989048653 + 3.1785660915013914 + 3.1789379580961445 + 3.1793098987100579 + 3.1796819133640861 + 3.1800540020791859 + 3.1804261648763288 + 3.1807984017764914 + 3.181170712800649 + 3.181543097969795 + 3.1819155573049316 + 3.1822880908270621 + 3.1826606985571879 + 3.1830333805163562 + 3.183406136725579 + 3.1837789672058951 + 3.1841518719783561 + 3.1845248510640043 + 3.1848979044839014 + 3.1852710322591249 + 3.1856442344107387 + 3.1860175109598363 + 3.1863908619275092 + 3.1867642873348432 + 3.187137787202964 + 3.1875113615529664 + 3.1878850104059864 + 3.1882587337831585 + 3.1886325317056032 + 3.1890064041944859 + 3.1893803512709411 + 3.1897543729561426 + 3.1901284692712619 + 3.1905026402374745 + 3.190876885875956 + 3.1912512062079106 + 3.1916256012545356 + 3.192000071037032 + 3.192374615576631 + 3.1927492348945448 + 3.1931239290120086 + 3.1934986979502678 + 3.1938735417305613 + 3.1942484603741494 + 3.1946234539022957 + 3.1949985223362747 + 3.1953736656973524 + 3.195748884006834 + 3.196124177286007 + 3.1964995455561662 + 3.1968749888386414 + 3.197250507154731 + 3.1976261005257736 + 3.1980017689730911 + 3.1983775125180425 + 3.1987533311819729 + 3.1991292249862324 + 3.1995051939521946 + 3.1998812381012378 + 3.2002573574547326 + 3.2006335520340743 + 3.2010098218606604 + 3.2013861669558961 + 3.2017625873411979 + 3.2021390830379839 + 3.2025156540676862 + 3.2028923004517353 + 3.2032690222115843 + 3.2036458193686852 + 3.2040226919445014 + 3.2043996399604953 + 3.2047766634381518 + 3.2051537623989499 + 3.2055309368643843 + 3.2059081868559618 + 3.2062855123951755 + 3.20666291350356 + 3.2070403902026308 + 3.2074179425139322 + 3.2077955704589889 + 3.2081732740593578 + 3.2085510533366084 + 3.2089289083122758 + 3.209306839007966 + 3.2096848454452358 + 3.2100629276456885 + 3.2104410856309156 + 3.2108193194225185 + 3.2111976290421169 + 3.2115760145113339 + 3.2119544758517864 + 3.2123330130851273 + 3.2127116262329842 + 3.2130903153170247 + 3.2134690803589105 + 3.2138479213803017 + 3.2142268384028752 + 3.2146058314483268 + 3.2149849005383495 + 3.2153640456946309 + 3.2157432669388912 + 3.2161225642928533 + 3.2165019377782356 + 3.2168813874167701 + 3.2172609132301981 + 3.2176405152402796 + 3.2180201934687616 + 3.2183999479374124 + 3.2187797786680199 + 3.2191596856823446 + 3.2195396690021947 + 3.2199197286493635 + 3.2202998646456482 + 3.2206800770128807 + 3.2210603657728729 + 3.2214407309474584 + 3.2218211725584767 + 3.2222016906277786 + 3.2225822851772077 + 3.2229629562286441 + 3.2233437038039519 + 3.2237245279250102 + 3.2241054286136994 + 3.2244864058919327 + 3.2248674597816018 + 3.2252485903046293 + 3.2256297974829233 + 3.2260110813384224 + 3.2263924418930632 + 3.2267738791687877 + 3.2271553931875445 + 3.2275369839713108 + 3.2279186515420437 + 3.2283003959217176 + 3.2286822171323304 + 3.2290641151958694 + 3.2294460901343482 + 3.2298281419697612 + 3.2302102707241285 + 3.2305924764194995 + 3.2309747590778772 + 3.231357118721327 + 3.2317395553718993 + 3.2321220690516532 + 3.2325046597826486 + 3.2328873275869734 + 3.2332700724867087 + 3.2336528945039458 + 3.2340357936607789 + 3.2344187699793263 + 3.2348018234817122 + 3.2351849541900517 + 3.2355681621264782 + 3.2359514473131434 + 3.2363348097721985 + 3.23671824952579 + 3.2371017665960973 + 3.2374853610052874 + 3.2378690327755542 + 3.2382527819290798 + 3.2386366084880756 + 3.2390205124747351 + 3.2394044939112909 + 3.2397885528199657 + 3.2401726892229901 + 3.2405569031426036 + 3.2409411946010591 + 3.241325563620618 + 3.2417100102235445 + 3.2420945344321161 + 3.2424791362686212 + 3.2428638157553324 + 3.2432485729145757 + 3.2436334077686455 + 3.244018320339852 + 3.2444033106505401 + 3.2447883787230341 + 3.2451735245796716 + 3.2455587482428117 + 3.2459440497348084 + 3.2463294290780245 + 3.2467148862948441 + 3.2471004214076533 + 3.2474860344388321 + 3.2478717254107914 + 3.2482574943459386 + 3.2486433412666895 + 3.2490292661954681 + 3.2494152691547122 + 3.2498013501668641 + 3.2501875092543773 + 3.2505737464397102 + 3.2509600617453263 + 3.2513464551937079 + 3.2517329268073367 + 3.2521194766087085 + 3.2525061046203221 + 3.2528928108646911 + 3.253279595364337 + 3.2536664581417716 + 3.2540533992195511 + 3.254440418620197 + 3.2548275163662832 + 3.2552146924803562 + 3.2556019469849962 + 3.2559892799027734 + 3.2563766912562815 + 3.2567641810681054 + 3.2571517493608551 + 3.2575393961571391 + 3.2579271214795824 + 3.2583149253508066 + 3.2587028077934521 + 3.2590907688301693 + 3.2594788084836037 + 3.2598669267764286 + 3.2602551237313127 + 3.2606433993709198 + 3.2610317537179614 + 3.2614201867951231 + 3.2618086986251091 + 3.262197289230635 + 3.2625859586344261 + 3.2629747068592101 + 3.2633635339277287 + 3.263752439862726 + 3.2641414246869611 + 3.2645304884231998 + 3.2649196310942199 + 3.265308852722796 + 3.2656981533317171 + 3.2660875329437933 + 3.2664769915818241 + 3.2668665292686323 + 3.2672561460270364 + 3.2676458418798777 + 3.2680356168499878 + 3.2684254709602349 + 3.2688154042334601 + 3.2692054166925382 + 3.2695955083603505 + 3.269985679259777 + 3.2703759294137176 + 3.2707662588450712 + 3.2711566675767463 + 3.2715471556316627 + 3.271937723032758 + 3.2723283698029575 + 3.2727190959652144 + 3.2731099015424787 + 3.2735007865577144 + 3.2738917510338994 + 3.2742827949940074 + 3.2746739184610303 + 3.2750651214579625 + 3.2754564040078136 + 3.2758477661336025 + 3.276239207858346 + 3.2766307292050767 + 3.2770223301968335 + 3.2774140108566781 + 3.2778057712076549 + 3.2781976112728364 + 3.2785895310753079 + 3.2789815306381396 + 3.2793736099844284 + 3.2797657691372808 + 3.2801580081198107 + 3.2805503269551153 + 3.2809427256663519 + 3.281335204276647 + 3.2817277628091359 + 3.282120401286988 + 3.2825131197333559 + 3.282905918171414 + 3.2832987966243503 + 3.2836917551153411 + 3.2840847936675948 + 3.2844779123043182 + 3.284871111048715 + 3.2852643899240217 + 3.2856577489534673 + 3.2860511881602905 + 3.2864447075677519 + 3.2868383071990999 + 3.2872319870776128 + 3.2876257472265564 + 3.2880195876692238 + 3.2884135084289063 + 3.288807509528914 + 3.2892015909925543 + 3.2895957528431494 + 3.2899899951040297 + 3.2903843177985275 + 3.2907787209500032 + 3.2911732045817996 + 3.2915677687172886 + 3.2919624133798489 + 3.2923571385928505 + 3.2927519443797024 + 3.2931468307637966 + 3.2935417977685288 + 3.2939368454173401 + 3.2943319737336485 + 3.294727182740889 + 3.2951224724625066 + 3.2955178429219543 + 3.2959132941427027 + 3.2963088261482074 + 3.2967044389619629 + 3.2971001326074543 + 3.2974959071081806 + 3.2978917624876454 + 3.2982876987693768 + 3.2986837159768769 + 3.2990798141337025 + 3.2994759932633859 + 3.2998722533894842 + 3.3002685945355514 + 3.3006650167251546 + 3.3010615199818849 + 3.3014581043293214 + 3.3018547697910536 + 3.3022515163907018 + 3.3026483441518795 + 3.3030452530981926 + 3.3034422432532917 + 3.3038393146408049 + 3.3042364672843942 + 3.3046337012077123 + 3.3050310164344308 + 3.3054284129882143 + 3.3058258908927702 + 3.3062234501717755 + 3.3066210908489402 + 3.3070188129479843 + 3.3074166164926173 + 3.3078145015065887 + 3.3082124680136187 + 3.3086105160374673 + 3.3090086456018857 + 3.3094068567306452 + 3.3098051494475262 + 3.3102035237763108 + 3.3106019797407922 + 3.311000517364767 + 3.3113991366720601 + 3.3117978376864805 + 3.3121966204318745 + 3.3125954849320687 + 3.3129944312109214 + 3.3133934592922714 + 3.313792569200011 + 3.3141917609579972 + 3.3145910345901215 + 3.3149903901202769 + 3.3153898275723659 + 3.315789346970305 + 3.3161889483380156 + 3.3165886316994162 + 3.3169883970784531 + 3.3173882444990834 + 3.3177881739852562 + 3.3181881855609396 + 3.3185882792501085 + 3.3189884550767452 + 3.3193887130648565 + 3.3197890532384373 + 3.3201894756214907 + 3.3205899802380556 + 3.3209905671121458 + 3.3213912362678171 + 3.3217919877291147 + 3.3221928215200873 + 3.3225937376648074 + 3.3229947361873498 + 3.3233958171118099 + 3.3237969804622742 + 3.3241982262628449 + 3.3245995545376412 + 3.3250009653107853 + 3.3254024586064013 + 3.3258040344486388 + 3.326205692861643 + 3.3266074338695675 + 3.3270092574965942 + 3.3274111637668948 + 3.3278131527046528 + 3.3282152243340666 + 3.3286173786793443 + 3.3290196157647012 + 3.3294219356143491 + 3.329824338252541 + 3.330226823703506 + 3.33062939199149 + 3.3310320431407718 + 3.3314347771755997 + 3.3318375941202736 + 3.3322404939990764 + 3.3326434768362927 + 3.3330465426562452 + 3.3334496914832483 + 3.3338529233416279 + 3.3342562382557097 + 3.3346596362498397 + 3.3350631173483793 + 3.3354666815756966 + 3.3358703289561458 + 3.3362740595141211 + 3.3366778732740161 + 3.3370817702602169 + 3.3374857504971427 + 3.3378898140092148 + 3.3382939608208519 + 3.3386981909565026 + 3.3391025044406093 + 3.3395069012976233 + 3.3399113815520161 + 3.3403159452282645 + 3.3407205923508405 + 3.3411253229442535 + 3.3415301370330019 + 3.341935034641589 + 3.3423400157945449 + 3.342745080516397 + 3.3431502288316937 + 3.3435554607649776 + 3.3439607763408095 + 3.3443661755837577 + 3.3447716585184004 + 3.3451772251693215 + 3.3455828755611319 + 3.3459886097184222 + 3.3463944276658166 + 3.3468003294279383 + 3.3472063150294264 + 3.3476123844949113 + 3.3480185378490619 + 3.3484247751165381 + 3.3488310963220043 + 3.3492375014901481 + 3.349643990645665 + 3.3500505638132427 + 3.350457221017606 + 3.3508639622834724 + 3.351270787635563 + 3.351677697098618 + 3.3520846906973958 + 3.3524917684566442 + 3.3528989304011318 + 3.3533061765556424 + 3.3537135069449509 + 3.3541209215938594 + 3.3545284205271777 + 3.3549360037697173 + 3.3553436713462887 + 3.3557514232817489 + 3.3561592596009286 + 3.3565671803286792 + 3.3569751854898651 + 3.3573832751093602 + 3.3577914492120473 + 3.3581997078228154 + 3.3586080509665677 + 3.35901647866821 + 3.3594249909526632 + 3.35983358784486 + 3.3602422693697362 + 3.3606510355522401 + 3.3610598864173342 + 3.3614688219899755 + 3.3618778422951539 + 3.3622869473578496 + 3.3626961372030642 + 3.3631054118557997 + 3.3635147713410687 + 3.3639242156839018 + 3.3643337449093278 + 3.3647433590423956 + 3.3651530581081683 + 3.3655628421316988 + 3.365972711138054 + 3.3663826651523365 + 3.3667927041996246 + 3.367202828305027 + 3.3676130374936499 + 3.3680233317906216 + 3.3684337112210678 + 3.3688441758101315 + 3.3692547255829659 + 3.3696653605647326 + 3.3700760807805947 + 3.3704868862557382 + 3.3708977770153523 + 3.3713087530846342 + 3.3717198144887988 + 3.3721309612530512 + 3.3725421934026349 + 3.3729535109627786 + 3.3733649139587305 + 3.373776402415757 + 3.3741879763591109 + 3.3745996358140866 + 3.375011380805951 + 3.3754232113600233 + 3.3758351275015923 + 3.3762471292559733 + 3.3766592166485112 + 3.3770713897045175 + 3.3774836484493527 + 3.3778959929083645 + 3.3783084231069287 + 3.3787209390704032 + 3.3791335408241925 + 3.3795462283936715 + 3.3799590018042598 + 3.380371861081362 + 3.3807848062503991 + 3.3811978373368143 + 3.3816109543660446 + 3.3820241573635519 + 3.3824374463547859 + 3.3828508213652206 + 3.3832642824203543 + 3.3836778295456549 + 3.3840914627666465 + 3.3845051821088332 + 3.3849189875977381 + 3.3853328792588977 + 3.3857468571178404 + 3.386160921200132 + 3.3865750715313161 + 3.3869893081369873 + 3.387403631042714 + 3.3878180402740838 + 3.3882325358567051 + 3.3886471178161863 + 3.3890617861781513 + 3.3894765409682188 + 3.3898913822120442 + 3.3903063099352733 + 3.3907213241635592 + 3.3911364249225837 + 3.3915516122380192 + 3.3919668861355623 + 3.3923822466409108 + 3.392797693779769 + 3.3932132275778675 + 3.3936288480609305 + 3.3940445552546921 + 3.3944603491849121 + 3.3948762298773469 + 3.3952921973577692 + 3.3957082516519508 + 3.3961243927856914 + 3.3965406207847866 + 3.39695693567504 + 3.3973733374822808 + 3.3977898262323403 + 3.3982064019510498 + 3.398623064664263 + 3.3990398143978426 + 3.3994566511776569 + 3.3998735750295808 + 3.4002905859795098 + 3.400707684053343 + 3.4011248692769933 + 3.4015421416763756 + 3.4019595012774206 + 3.4023769481060682 + 3.4027944821882752 + 3.4032121035499983 + 3.403629812217198 + 3.4040476082158695 + 3.404465491571993 + 3.4048834623115876 + 3.4053015204606387 + 3.4057196660451829 + 3.4061378990912479 + 3.4065562196248744 + 3.4069746276721053 + 3.4073931232590153 + 3.4078117064116697 + 3.40823037715615 + 3.4086491355185475 + 3.4090679815249691 + 3.4094869152015148 + 3.4099059365743156 + 3.4103250456695071 + 3.4107442425132199 + 3.4111635271316225 + 3.4115828995508659 + 3.4120023597971296 + 3.4124219078965807 + 3.4128415438754387 + 3.4132612677598861 + 3.4136810795761434 + 3.4141009793504336 + 3.4145209671089898 + 3.414941042878064 + 3.4153612066838983 + 3.4157814585527633 + 3.4162017985109299 + 3.4166222265846975 + 3.4170427428003438 + 3.4174633471841811 + 3.4178840397625292 + 3.418304820561707 + 3.4187256896080553 + 3.4191466469279117 + 3.4195676925476461 + 3.4199888264936189 + 3.4204100487922084 + 3.4208313594698012 + 3.4212527585527979 + 3.4216742460675991 + 3.4220958220406326 + 3.4225174864983208 + 3.4229392394671074 + 3.4233610809734323 + 3.4237830110437679 + 3.4242050297045754 + 3.4246271369823367 + 3.4250493329035399 + 3.4254716174946949 + 3.4258939907823018 + 3.426316452792888 + 3.4267390035529819 + 3.4271616430891392 + 3.4275843714278849 + 3.4280071885958043 + 3.4284300946194732 + 3.4288530895254512 + 3.4292761733403605 + 3.4296993460907865 + 3.4301226078033484 + 3.430545958504672 + 3.4309693982214 + 3.4313929269801728 + 3.4318165448076439 + 3.4322402517304722 + 3.4326640477753534 + 3.4330879329689625 + 3.4335119073380009 + 3.4339359709091779 + 3.4343601237092121 + 3.4347843657648305 + 3.4352086971027753 + 3.4356331177497954 + 3.4360576277326524 + 3.4364822270781161 + 3.4369069158129713 + 3.4373316939639933 + 3.4377565615580106 + 3.4381815186218203 + 3.4386065651822486 + 3.4390317012661287 + 3.4394569269003101 + 3.4398822421116471 + 3.4403076469269931 + 3.4407331413732396 + 3.4411587254772584 + 3.4415843992659636 + 3.4420101627662487 + 3.4424360160050318 + 3.442861959009246 + 3.4432879918058337 + 3.4437141144217396 + 3.4441403268839195 + 3.4445666292193566 + 3.4449930214550197 + 3.4454195036179103 + 3.4458460757350169 + 3.4462727378333691 + 3.4466994899399794 + 3.4471263320818863 + 3.447553264286134 + 3.447980286579778 + 3.4484073989898798 + 3.4488346015435165 + 3.4492618942677886 + 3.4496892771897714 + 3.4501167503365902 + 3.4505443137353575 + 3.4509719674132073 + 3.4513997113972708 + 3.4518275457147083 + 3.4522554703926795 + 3.4526834854583499 + 3.4531115909389016 + 3.4535397868615418 + 3.4539680732534608 + 3.4543964501418842 + 3.4548249175540318 + 3.4552534755171362 + 3.4556821240584434 + 3.4561108632052213 + 3.4565396929847259 + 3.4569686134242437 + 3.4573976245510663 + 3.4578267263924913 + 3.4582559189758229 + 3.4586852023283892 + 3.4591145764775248 + 3.4595440414505751 + 3.4599735972748786 + 3.4604032439778174 + 3.4608329815867664 + 3.4612628101290932 + 3.4616927296322144 + 3.462122740123533 + 3.4625528416304592 + 3.4629830341804224 + 3.4634133178008746 + 3.4638436925192653 + 3.4642741583630396 + 3.4647047153596833 + 3.4651353635366897 + 3.465566102921529 + 3.4659969335417218 + 3.4664278554247803 + 3.4668588685982353 + 3.4672899730896094 + 3.4677211689264698 + 3.4681524561363584 + 3.4685838347468612 + 3.4690153047855445 + 3.4694468662800086 + 3.4698785192578492 + 3.4703102637466876 + 3.4707420997741405 + 3.4711740273678484 + 3.4716060465554572 + 3.4720381573646182 + 3.4724703598230016 + 3.4729026539582821 + 3.4733350397981604 + 3.4737675173703306 + 3.4742000867025005 + 3.4746327478223966 + 3.4750655007577458 + 3.4754983455363013 + 3.4759312821858117 + 3.4763643107340476 + 3.4767974312087833 + 3.477230643637804 + 3.4776639480489107 + 3.4780973444699108 + 3.4785308329286355 + 3.478964413452899 + 3.4793980860705562 + 3.4798318508094566 + 3.4802657076974639 + 3.4806996567624582 + 3.4811336980323304 + 3.4815678315349579 + 3.4820020572982706 + 3.4824363753501775 + 3.482870785718613 + 3.4833052884315179 + 3.4837398835168432 + 3.4841745710025513 + 3.4846093509166272 + 3.4850442232870376 + 3.4854791881418028 + 3.4859142455089072 + 3.4863493954163909 + 3.4867846378922693 + 3.4872199729645912 + 3.4876554006614033 + 3.4880909210107687 + 3.4885265340407643 + 3.4889622397794859 + 3.4893980382550116 + 3.4898339294954548 + 3.4902699135289463 + 3.4907059903835953 + 3.4911421600875663 + 3.4915784226689892 + 3.4920147781560438 + 3.4924512265768852 + 3.4928877679597208 + 3.4933244023327403 + 3.4937611297241489 + 3.4941979501621638 + 3.4946348636750204 + 3.4950718702909516 + 3.4955089700382223 + 3.4959461629450828 + 3.4963834490398211 + 3.4968208283507103 + 3.4972583009060547 + 3.4976958667341695 + 3.4981335258633606 + 3.4985712783219634 + 3.4990091241383285 + 3.499447063340801 + 3.4998850959577439 + 3.5003232220175393 + 3.5007614415485713 + 3.501199754579233 + 3.501638161137945 + 3.5020766612531218 + 3.5025152549531935 + 3.5029539422666085 + 3.5033927232218218 + 3.5038315978472854 + 3.504270566171495 + 3.5047096282229342 + 3.5051487840300943 + 3.5055880336214975 + 3.5060273770256547 + 3.5064668142711111 + 3.5069063453864087 + 3.5073459704000989 + 3.5077856893407424 + 3.5082255022369417 + 3.50866540911727 + 3.5091054100103332 + 3.5095455049447404 + 3.5099856939491176 + 3.5104259770521105 + 3.5108663542823524 + 3.5113068256685041 + 3.5117473912392434 + 3.5121880510232462 + 3.5126288050492018 + 3.513069653345831 + 3.513510595941828 + 3.5139516328659255 + 3.5143927641468706 + 3.5148339898134049 + 3.5152753098942977 + 3.5157167244183136 + 3.5161582334142292 + 3.5165998369108618 + 3.5170415349370052 + 3.5174833275214752 + 3.5179252146931068 + 3.5183671964807348 + 3.5188092729132285 + 3.5192514440194329 + 3.5196937098282262 + 3.520136070368503 + 3.5205785256691677 + 3.5210210757591147 + 3.5214637206672785 + 3.5219064604225876 + 3.5223492950539943 + 3.5227922245904324 + 3.5232352490608974 + 3.5236783684943558 + 3.5241215829197912 + 3.5245648923662172 + 3.5250082968626435 + 3.5254517964380958 + 3.5258953911216113 + 3.526339080942241 + 3.526782865929043 + 3.5272267461110896 + 3.527670721517461 + 3.528114792177254 + 3.5285589581195773 + 3.5290032193735539 + 3.5294475759683039 + 3.5298920279329677 + 3.530336575296706 + 3.5307812180886851 + 3.531225956338071 + 3.5316707900740583 + 3.532115719325847 + 3.5325607441226525 + 3.5330058644936835 + 3.5334510804681862 + 3.5338963920754027 + 3.5343417993445905 + 3.534787302305022 + 3.5352329009859744 + 3.5356785954167522 + 3.5361243856266409 + 3.5365702716449725 + 3.5370162535010632 + 3.537462331224265 + 3.5379085048439194 + 3.5383547743893931 + 3.5388011398900625 + 3.5392476013753131 + 3.5396941588745467 + 3.5401408124171612 + 3.5405875620325906 + 3.5410344077502685 + 3.5414813495996351 + 3.5419283876101453 + 3.5423755218112687 + 3.5428227522325018 + 3.5432700789033178 + 3.5437175018532234 + 3.544165021111743 + 3.5446126367084005 + 3.5450603486727266 + 3.5455081570342917 + 3.5459560618226433 + 3.5464040630673725 + 3.5468521607980459 + 3.5473003550442774 + 3.547748645835668 + 3.5481970332018511 + 3.5486455171724507 + 3.5490940977771106 + 3.5495427750455053 + 3.5499915490072964 + 3.5504404196921606 + 3.5508893871297893 + 3.5513384513499013 + 3.5517876123822059 + 3.5522368702564351 + 3.5526862250023332 + 3.553135676649644 + 3.5535852252281424 + 3.5540348707675897 + 3.5544846132977956 + 3.5549344528485469 + 3.5553843894496731 + 3.5558344231309795 + 3.5562845539223087 + 3.5567347818535087 + 3.5571851069544556 + 3.557635529255001 + 3.5580860487850394 + 3.5585366655744681 + 3.5589873796531903 + 3.5594381910511323 + 3.559889099798236 + 3.5603401059244195 + 3.5607912094596617 + 3.5612424104339295 + 3.5616937088771983 + 3.5621451048194559 + 3.5625965982907193 + 3.5630481893209986 + 3.5634998779403229 + 3.563951664178731 + 3.564403548066287 + 3.5648555296330389 + 3.5653076089090772 + 3.5657597859244845 + 3.5662120607093692 + 3.5666644332938358 + 3.5671169037080173 + 3.5675694719820528 + 3.5680221381460786 + 3.5684749022302711 + 3.5689277642648021 + 3.5693807242798492 + 3.5698337823056239 + 3.5702869383723215 + 3.57074019251018 + 3.5711935447494141 + 3.5716469951202945 + 3.5721005436530748 + 3.572554190378014 + 3.5730079353253932 + 3.5734617785255329 + 3.5739157200087104 + 3.574369759805275 + 3.5748238979455316 + 3.5752781344598494 + 3.5757324693785626 + 3.5761869027320539 + 3.5766414345507016 + 3.5770960648648984 + 3.5775507937050532 + 3.5780056211015707 + 3.5784605470849034 + 3.5789155716854797 + 3.5793706949337536 + 3.57982591686019 + 3.580281237495281 + 3.5807366568695018 + 3.5811921750133755 + 3.5816477919573986 + 3.5821035077321022 + 3.5825593223680388 + 3.5830152358957523 + 3.583471248345814 + 3.5839273597487975 + 3.5843835701352864 + 3.584839879535898 + 3.5852962879812353 + 3.5857527955019242 + 3.5862094021286124 + 3.5866661078919497 + 3.5871229128225908 + 3.5875798169512305 + 3.5880368203085364 + 3.5884939229252244 + 3.5889511248320045 + 3.5894084260595966 + 3.5898658266387522 + 3.5903233266002084 + 3.5907809259747339 + 3.5912386247931116 + 3.5916964230861157 + 3.5921543208845508 + 3.5926123182192375 + 3.5930704151210007 + 3.5935286116206724 + 3.593986907749092 + 3.5944453035371504 + 3.5949037990156998 + 3.5953623942156376 + 3.5958210891678601 + 3.5962798839032866 + 3.59673877845283 + 3.5971977728474478 + 3.5976568671180678 + 3.5981160612956695 + 3.5985753554112212 + 3.599034749495702 + 3.599494243580132 + 3.5999538376955122 + 3.6004135318728663 + 3.6008733261432369 + 3.6013332205376742 + 3.6017932150872412 + 3.6022533098230136 + 3.6027135047760752 + 3.6031737999775344 + 3.6036341954585001 + 3.6040946912501028 + 3.6045552873834725 + 3.6050159838897686 + 3.6054767808001502 + 3.6059376781457964 + 3.6063986759578972 + 3.6068597742676567 + 3.6073209731062739 + 3.6077822725049975 + 3.6082436724950595 + 3.6087051731077069 + 3.6091667743742133 + 3.6096284763258439 + 3.6100902789939044 + 3.6105521824096805 + 3.6110141866045029 + 3.6114762916097001 + 3.6119384974566051 + 3.6124008041765796 + 3.6128632118009771 + 3.6133257203611913 + 3.6137883298886115 + 3.6142510404146373 + 3.6147138519706927 + 3.6151767645881971 + 3.6156397782986072 + 3.6161028931333687 + 3.6165661091239536 + 3.6170294263018521 + 3.6174928446985475 + 3.6179563643455439 + 3.6184199852743784 + 3.6188837075165616 + 3.619347531103656 + 3.6198114560672114 + 3.6202754824388101 + 3.6207396102500149 + 3.6212038395324417 + 3.6216681703176925 + 3.6221326026373899 + 3.6225971365231668 + 3.6230617720066807 + 3.6235265091195878 + 3.6239913478935573 + 3.6244562883602751 + 3.624921330551456 + 3.6253864744987894 + 3.6258517202340195 + 3.6263170677888827 + 3.6267825171951191 + 3.6272480684845028 + 3.6277137216888082 + 3.628179476839827 + 3.6286453339693603 + 3.6291112931092218 + 3.6295773542912495 + 3.6300435175472678 + 3.6305097829091522 + 3.630976150408761 + 3.6314426200779724 + 3.6319091919486803 + 3.6323758660527963 + 3.6328426424222409 + 3.633309521088941 + 3.633776502084844 + 3.6342435854419155 + 3.6347107711921134 + 3.6351780593674419 + 3.6356454499998829 + 3.6361129431214523 + 3.6365805387641679 + 3.6370482369600881 + 3.6375160377412348 + 3.637983941139693 + 3.638451947187535 + 3.6389200559168393 + 3.6393882673597133 + 3.639856581548282 + 3.6403249985146653 + 3.6407935182910007 + 3.6412621409094545 + 3.6417308664021872 + 3.6421996948013788 + 3.6426686261392303 + 3.6431376604479442 + 3.6436067977597455 + 3.6440760381068595 + 3.6445453815215401 + 3.6450148280360515 + 3.6454843776826524 + 3.6459540304936433 + 3.6464237865013174 + 3.6468936457379901 + 3.6473636082359837 + 3.6478336740276425 + 3.6483038431453148 + 3.6487741156213707 + 3.6492444914881852 + 3.6497149707781493 + 3.6501855535236682 + 3.6506562397571707 + 3.6511270295110796 + 3.651597922817845 + 3.6520689197099188 + 3.65254002021977 + 3.6530112243798993 + 3.6534825322227866 + 3.6539539437809601 + 3.6544254590869376 + 3.6548970781732475 + 3.655368801072457 + 3.6558406278171236 + 3.6563125584398257 + 3.6567845929731622 + 3.657256731449722 + 3.6577289739021404 + 3.6582013203630352 + 3.6586737708650654 + 3.6591463254408754 + 3.6596189841231461 + 3.6600917469445551 + 3.6605646139378099 + 3.6610375851356238 + 3.6615106605707064 + 3.6619838402758127 + 3.6624571242836801 + 3.6629305126270877 + 3.6634040053388168 + 3.6638776024516431 + 3.6643513039983868 + 3.6648251100118578 + 3.6652990205249001 + 3.6657730355703473 + 3.6662471551810656 + 3.66672137938993 + 3.6671957082298201 + 3.6676701417336468 + 3.6681446799343109 + 3.6686193228647554 + 3.6690940705579109 + 3.6695689230467377 + 3.6700438803641933 + 3.670518942543266 + 3.6709941096169509 + 3.6714693816182598 + 3.6719447585801985 + 3.6724202405358266 + 3.6728958275181767 + 3.6733715195603129 + 3.6738473166953169 + 3.6743232189562742 + 3.6747992263762903 + 3.6752753389884849 + 3.675751556825984 + 3.6762278799219335 + 3.6767043083094939 + 3.677180842021837 + 3.6776574810921394 + 3.6781342255536047 + 3.6786110754394588 + 3.6790880307829066 + 3.679565091617198 + 3.6800422579755918 + 3.6805195298913467 + 3.6809969073977378 + 3.6814743905280749 + 3.6819519793156621 + 3.6824296737938145 + 3.6829074739958756 + 3.6833853799551934 + 3.6838633917051209 + 3.6843415092790543 + 3.6848197327103676 + 3.6852980620324711 + 3.6857764972787783 + 3.6862550384827357 + 3.6867336856777739 + 3.6872124388973493 + 3.6876912981749541 + 3.6881702635440643 + 3.6886493350381824 + 3.6891285126908144 + 3.6896077965355007 + 3.6900871866057847 + 3.6905666829352026 + 3.6910462855573547 + 3.6915259945058039 + 3.6920058098141499 + 3.6924857315160104 + 3.6929657596450003 + 3.6934458942347792 + 3.6939261353189803 + 3.6944064829312788 + 3.694886937105347 + 3.6953674978748969 + 3.6958481652736284 + 3.6963289393352627 + 3.6968098200935389 + 3.6972908075821951 + 3.6977719018350159 + 3.698253102885765 + 3.6987344107682474 + 3.6992158255162586 + 3.699697347163617 + 3.7001789757441679 + 3.7006607112917593 + 3.7011425538402407 + 3.7016245034235005 + 3.7021065600754204 + 3.7025887238299062 + 3.7030709947208869 + 3.7035533727822787 + 3.704035858048035 + 3.7045184505521158 + 3.7050011503284948 + 3.705483957411166 + 3.7059668718341312 + 3.706449893631397 + 3.7069330228370037 + 3.7074162594849893 + 3.7078996036094183 + 3.708383055244358 + 3.7088666144239029 + 3.709350281182147 + 3.7098340555532014 + 3.710317937571213 + 3.7108019272703081 + 3.7112860246846564 + 3.7117702298484163 + 3.7122545427957911 + 3.7127389635609589 + 3.7132234921781522 + 3.7137081286815894 + 3.7141928731055178 + 3.7146777254841985 + 3.7151626858518929 + 3.7156477542428932 + 3.7161329306914856 + 3.7166182152320051 + 3.7171036078987605 + 3.7175891087261048 + 3.7180747177483942 + 3.7185604349999899 + 3.7190462605152903 + 3.7195321943286763 + 3.7200182364745804 + 3.7205043869874186 + 3.7209906459016326 + 3.7214770132516866 + 3.7219634890720421 + 3.722450073397193 + 3.7229367662616339 + 3.723423567699867 + 3.723910477746442 + 3.7243974964358806 + 3.72488462380276 + 3.7253718598816237 + 3.7258592047070818 + 3.726346658313727 + 3.7268342207361611 + 3.727321892009027 + 3.7278096721669538 + 3.728297561244613 + 3.7287855592766599 + 3.7292736662978023 + 3.729761882342725 + 3.7302502074461432 + 3.7307386416427879 + 3.7312271849674019 + 3.7317158374547423 + 3.7322045991395916 + 3.7326934700567187 + 3.7331824502409368 + 3.733671539727069 + 3.7341607385499334 + 3.7346500467443708 + 3.7351394643452513 + 3.7356289913874359 + 3.7361186279058378 + 3.736608373935328 + 3.737098229510849 + 3.7375881946673166 + 3.7380782694396846 + 3.73856845386292 + 3.7390587479719901 + 3.7395491518018793 + 3.7400396653875965 + 3.7405302887641767 + 3.7410210219666347 + 3.7415118650300165 + 3.7420028179894063 + 3.7424938808798616 + 3.742985053736485 + 3.7434763365943815 + 3.743967729488674 + 3.7444592324544868 + 3.7449508455269847 + 3.7454425687413297 + 3.7459344021327059 + 3.7464263457362934 + 3.7469183995873165 + 3.7474105637209925 + 3.747902838172561 + 3.7483952229772872 + 3.748887718170415 + 3.7493803237872454 + 3.7498730398630764 + 3.7503658664332127 + 3.7508588035329775 + 3.7513518511977315 + 3.7518450094628095 + 3.7523382783636015 + 3.7528316579354768 + 3.7533251482138517 + 3.7538187492341351 + 3.7543124610317582 + 3.7548062836421616 + 3.7553002171008139 + 3.7557942614431776 + 3.7562884167047637 + 3.7567826829210569 + 3.757277060127576 + 3.757771548359881 + 3.758266147653492 + 3.7587608580439782 + 3.7592556795669361 + 3.7597506122579354 + 3.7602456561526032 + 3.7607408112865648 + 3.761236077695445 + 3.7617314554149033 + 3.7622269444806107 + 3.7627225449282458 + 3.7632182567935066 + 3.7637140801121114 + 3.7642100149197817 + 3.7647060612522716 + 3.7652022191453183 + 3.7656984886347207 + 3.7661948697562417 + 3.7666913625457115 + 3.7671879670389212 + 3.7676846832717188 + 3.7681815112799488 + 3.7686784510994671 + 3.7691755027661693 + 3.7696726663159321 + 3.7701699417846624 + 3.7706673292082971 + 3.7711648286227719 + 3.7716624400640293 + 3.7721601635680382 + 3.7726579991707934 + 3.7731559469082878 + 3.7736540068165247 + 3.7741521789315522 + 3.7746504632894005 + 3.7751488599261318 + 3.7756473688778258 + 3.7761459901805572 + 3.7766447238704348 + 3.7771435699835942 + 3.777642528556151 + 3.778141599624266 + 3.7786407832240947 + 3.7791400793918246 + 3.7796394881636539 + 3.7801390095757745 + 3.7806386436644339 + 3.7811383904658622 + 3.781638250016325 + 3.782138222352077 + 3.7826383075094152 + 3.7831385055246467 + 3.7836388164340793 + 3.784139240274043 + 3.7846397770808919 + 3.7851404268909898 + 3.7856411897407169 + 3.7861420656664575 + 3.7866430547046197 + 3.7871441568916424 + 3.787645372263952 + 3.7881467008580043 + 3.7886481427102732 + 3.7891496978572441 + 3.7896513663354172 + 3.7901531481813038 + 3.7906550434314443 + 3.7911570521223692 + 3.791659174290662 + 3.7921614099728811 + 3.7926637592056345 + 3.793166222025528 + 3.7936687984691706 + 3.7941714885732285 + 3.7946742923743284 + 3.7951772099091556 + 3.7956802412143946 + 3.7961833863267418 + 3.7966866452829215 + 3.7971900181196521 + 3.7976935048736924 + 3.7981971055818002 + 3.7987008202807608 + 3.7992046490073581 + 3.799708591798415 + 3.8002126486907355 + 3.8007168197211776 + 3.8012211049265914 + 3.80172550434385 + 3.8022300180098392 + 3.8027346459614595 + 3.803239388235629 + 3.8037442448692862 + 3.8042492158993779 + 3.8047543013628711 + 3.8052595012967383 + 3.8057648157379891 + 3.8062702447236156 + 3.8067757882906665 + 3.8072814464761793 + 3.8077872193171975 + 3.8082931068508117 + 3.8087991091141018 + 3.8093052261441871 + 3.8098114579781774 + 3.8103178046532062 + 3.8108242662064327 + 3.8113308426750323 + 3.8118375340961692 + 3.8123443405070621 + 3.8128512619449215 + 3.8133582984469765 + 3.8138654500504718 + 3.8143727167926724 + 3.8148800987108551 + 3.8153875958423211 + 3.8158952082243691 + 3.8164029358943385 + 3.8169107788895538 + 3.81741873724738 + 3.8179268110052011 + 3.8184350002003935 + 3.8189433048703689 + 3.8194517250525428 + 3.8199602607843475 + 3.8204689121032422 + 3.8209776790466958 + 3.8214865616521831 + 3.8219955599572213 + 3.8225046739993092 + 3.8230139038159896 + 3.8235232494448046 + 3.8240327109233054 + 3.8245422882891011 + 3.8250519815797626 + 3.8255617908329054 + 3.8260717160861697 + 3.8265817573771828 + 3.8270919147436091 + 3.8276021882231337 + 3.8281125778534246 + 3.8286230836722162 + 3.8291337057172048 + 3.8296444440261501 + 3.8301552986367908 + 3.8306662695869202 + 3.831177356914294 + 3.831688560656739 + 3.8321998808520772 + 3.8327113175381187 + 3.8332228707527336 + 3.8337345405337881 + 3.8342463269191631 + 3.8347582299467589 + 3.8352702496544815 + 3.8357823860802802 + 3.8362946392620856 + 3.8368070092378739 + 3.8373194960456178 + 3.837832099723316 + 3.8383448203089712 + 3.838857657840637 + 3.8393706123563276 + 3.8398836838941177 + 3.8403968724920885 + 3.8409101781883224 + 3.8414236010209404 + 3.8419371410280578 + 3.8424507982478207 + 3.8429645727183934 + 3.8434784644779367 + 3.8439924735646467 + 3.8445066000167278 + 3.8450208438724074 + 3.845535205169921 + 3.8460496839475282 + 3.8465642802434932 + 3.8470789940961114 + 3.8475938255436808 + 3.8481087746245168 + 3.8486238413769782 + 3.8491390258393974 + 3.8496543280501498 + 3.8501697480476178 + 3.8506852858702079 + 3.8512009415563448 + 3.8517167151444434 + 3.852232606672982 + 3.8527486161804023 + 3.8532647437052021 + 3.8537809892858754 + 3.8542973529609523 + 3.8548138347689407 + 3.8553304347484234 + 3.8558471529379417 + 3.8563639893760797 + 3.85688094410144 + 3.8573980171526441 + 3.8579152085683108 + 3.8584325183871071 + 3.8589499466476793 + 3.8594674933887263 + 3.8599851586489269 + 3.8605029424670114 + 3.8610208448817027 + 3.8615388659317493 + 3.8620570056559096 + 3.8625752640929729 + 3.8630936412817332 + 3.8636121372609988 + 3.8641307520696082 + 3.8646494857464035 + 3.8651683383302418 + 3.8656873098600202 + 3.8662064003746219 + 3.8667256099129617 + 3.8672449385139607 + 3.8677643862165829 + 3.8682839530597861 + 3.86880363908254 + 3.8693234443238516 + 3.8698433688227269 + 3.8703634126182016 + 3.8708835757493141 + 3.8714038582551353 + 3.8719242601747372 + 3.8724447815472303 + 3.8729654224117125 + 3.8734861828073206 + 3.8740070627731966 + 3.8745280623485061 + 3.8750491815724319 + 3.8755704204841712 + 3.8760917791229339 + 3.8766132575279504 + 3.8771348557384697 + 3.8776565737937538 + 3.8781784117330971 + 3.8787003695957747 + 3.8792224474211081 + 3.8797446452484392 + 3.8802669631171045 + 3.8807894010664725 + 3.881311959135938 + 3.8818346373648782 + 3.8823574357927151 + 3.8828803544588903 + 3.8834033934028489 + 3.8839265526640512 + 3.8844498322819874 + 3.884973232296157 + 3.8854967527460724 + 3.8860203936712736 + 3.8865441551113027 + 3.8870680371057298 + 3.887592039694153 + 3.8881161629161642 + 3.8886404068113793 + 3.8891647714194439 + 3.8896892567799966 + 3.8902138629327148 + 3.8907385899172886 + 3.8912634377734201 + 3.8917884065408224 + 3.892313496259256 + 3.8928387069684489 + 3.8933640387081869 + 3.8938894915182569 + 3.8944150654384675 + 3.8949407605086432 + 3.895466576768623 + 3.895992514258261 + 3.8965185730174303 + 3.8970447530860302 + 3.8975710545039695 + 3.8980974773111656 + 3.8986240215475765 + 3.8991506872531461 + 3.8996774744678606 + 3.9002043832317179 + 3.9007314135847229 + 3.901258565566911 + 3.901785839218324 + 3.9023132345790348 + 3.9028407516891135 + 3.9033683905886676 + 3.9038961513177992 + 3.9044240339166492 + 3.904952038425376 + 3.9054801648841408 + 3.906008413333117 + 3.9065367838125162 + 3.9070652763625637 + 3.9075938910234846 + 3.9081226278355397 + 3.9086514868390059 + 3.9091804680741582 + 3.9097095715813004 + 3.910238797400774 + 3.9107681455729075 + 3.9112976161380653 + 3.911827209136614 + 3.9123569246089516 + 3.9128867625954826 + 3.9134167231366499 + 3.9139468062728833 + 3.9144770120446446 + 3.9150073404924313 + 3.9155377916567256 + 3.9160683655780399 + 3.9165990622969176 + 3.9171298818539064 + 3.9176608242895679 + 3.9181918896444938 + 3.9187230779592785 + 3.9192543892745459 + 3.9197858236309377 + 3.9203173810690992 + 3.9208490616297174 + 3.9213808653534667 + 3.9219127922810588 + 3.9224448424532259 + 3.9229770159107078 + 3.9235093126942679 + 3.9240417328446733 + 3.9245742764027201 + 3.92510694340924 + 3.925639733905042 + 3.9261726479309891 + 3.9267056855279492 + 3.9272388467367989 + 3.9277721315984344 + 3.9283055401537856 + 3.9288390724437816 + 3.9293727285093842 + 3.9299065083915585 + 3.9304404121313015 + 3.930974439769614 + 3.9315085913475292 + 3.932042866906083 + 3.9325772664863359 + 3.9331117901293777 + 3.9336464378762965 + 3.9341812097682127 + 3.934716105846241 + 3.9352511261515541 + 3.9357862707253126 + 3.9363215396086932 + 3.9368569328429039 + 3.9373924504691704 + 3.9379280925287219 + 3.9384638590628307 + 3.9389997501127652 + 3.9395357657198118 + 3.9400719059252829 + 3.9406081707705209 + 3.9411445602968538 + 3.9416810745456519 + 3.9422177135583034 + 3.9427544773761949 + 3.9432913660407669 + 3.9438283795934388 + 3.9443655180756649 + 3.9449027815289202 + 3.9454401699947002 + 3.9459776835145095 + 3.9465153221298661 + 3.947053085882327 + 3.9475909748134459 + 3.9481289889648106 + 3.9486671283780108 + 3.9492053930946684 + 3.9497437831564093 + 3.9502822986049035 + 3.9508209394818028 + 3.9513597058288061 + 3.9518985976876131 + 3.9524376150999654 + 3.9529767581075812 + 3.9535160267522387 + 3.9540554210757115 + 3.9545949411198045 + 3.9551345869263206 + 3.9556743585370966 + 3.9562142559939932 + 3.9567542793388757 + 3.9572944286136318 + 3.9578347038601662 + 3.9583751051203948 + 3.9589156324362897 + 3.9594562858497815 + 3.9599970654028724 + 3.9605379711375441 + 3.9610790030958163 + 3.9616201613197348 + 3.9621614458513315 + 3.9627028567326974 + 3.9632443940059052 + 3.9637860577130781 + 3.9643278478963317 + 3.9648697645978102 + 3.9654118078596787 + 3.9659539777241184 + 3.9664962742333274 + 3.9670386974295244 + 3.9675812473549481 + 3.9681239240518447 + 3.9686667275624985 + 3.9692096579291869 + 3.9697527151942364 + 3.9702958993999622 + 3.9708392105887209 + 3.9713826488028587 + 3.9719262140847831 + 3.9724699064768876 + 3.973013726021581 + 3.9735576727613164 + 3.9741017467385475 + 3.9746459479957417 + 3.9751902765754115 + 3.975734732520054 + 3.9762793158722105 + 3.9768240266744228 + 3.9773688649692684 + 3.9779138307993289 + 3.9784589242072212 + 3.9790041452355451 + 3.9795494939269682 + 3.9800949703241426 + 3.9806405744697497 + 3.9811863064064923 + 3.9817321661770828 + 3.9822781538242573 + 3.9828242693907696 + 3.9833705129194019 + 3.9839168844529449 + 3.9844633840342052 + 3.9850100117060014 + 3.9855567675112082 + 3.9861036514926784 + 3.9866506636932963 + 3.9871978041559681 + 3.9877450729236119 + 3.9882924700391933 + 3.9888399955456464 + 3.9893876494859613 + 3.9899354319031359 + 3.9904833428401933 + 3.9910313823401622 + 3.9915795504461076 + 3.9921278472010933 + 3.9926762726482123 + 3.9932248268305841 + 3.9937735097913252 + 3.9943223215736046 + 3.9948712622205771 + 3.9954203317754402 + 3.9959695302813936 + 3.9965188577816608 + 3.9970683143194892 + 3.9976178999381409 + 3.9981676146808951 + 3.9987174585910576 + 3.9992674317119437 + 3.9998175340869073 + 4.000367765759278 + 4.0009181267724552 + 4.0014686171698282 + 4.002019236994812 + 4.0025699862908359 + 4.0031208651013674 + 4.0036718734698633 + 4.004223011439823 + 4.0047742790547494 + 4.0053256763581881 + 4.0058772033936654 + 4.0064288602047684 + 4.0069806468350739 + 4.0075325633281755 + 4.0080846097277316 + 4.0086367860773571 + 4.0091890924207227 + 4.0097415288015119 + 4.0102940952634363 + 4.0108467918502058 + 4.0113996186055552 + 4.011952575573261 + 4.0125056627970901 + 4.0130588803208349 + 4.0136122281883253 + 4.0141657064433973 + 4.0147193151298985 + 4.0152730542916979 + 4.0158269239727078 + 4.0163809242168291 + 4.016935055067993 + 4.0174893165701633 + 4.0180437087673022 + 4.0185982317034004 + 4.0191528854224687 + 4.0197076699685379 + 4.0202625853856615 + 4.0208176317178985 + 4.0213728090093417 + 4.0219281173040988 + 4.0224835566462938 + 4.0230391270800725 + 4.0235948286495962 + 4.0241506613990667 + 4.024706625372664 + 4.0252627206146299 + 4.0258189471692027 + 4.0263753050806352 + 4.0269317943932341 + 4.0274884151512689 + 4.0280451673990889 + 4.028602051181009 + 4.029159066541415 + 4.0297162135246642 + 4.0302734921751755 + 4.0308309025373541 + 4.0313884446556436 + 4.0319461185745133 + 4.0325039243384202 + 4.0330618619918752 + 4.0336199315793912 + 4.0341781331454998 + 4.0347364667347625 + 4.0352949323917597 + 4.0358535301610852 + 4.0364122600873458 + 4.0369711222151778 + 4.0375301165892452 + 4.0380892432542259 + 4.0386485022547882 + 4.0392078936356812 + 4.0397674174416114 + 4.0403270737173393 + 4.0408868625076408 + 4.0414467838573209 + 4.0420068378111642 + 4.0425670244140308 + 4.043127343710748 + 4.0436877957462114 + 4.0442483805653016 + 4.0448090982129274 + 4.0453699487340247 + 4.0459309321735493 + 4.0464920485764697 + 4.0470532979877687 + 4.0476146804524671 + 4.0481761960155973 + 4.0487378447222122 + 4.0492996266173682 + 4.0498615417461608 + 4.0504235901537102 + 4.0509857718851459 + 4.0515480869856217 + 4.0521105355002938 + 4.0526731174743604 + 4.0532358329530354 + 4.0537986819815535 + 4.0543616646051479 + 4.054924780869106 + 4.0554880308187187 + 4.0560514144992927 + 4.0566149319561573 + 4.0571785832346654 + 4.0577423683801932 + 4.0583062874381257 + 4.0588703404538657 + 4.0594345274728703 + 4.0599988485405678 + 4.0605633037024402 + 4.0611278930039738 + 4.0616926164906921 + 4.0622574742081206 + 4.0628224662018138 + 4.0633875925173379 + 4.063952853200294 + 4.0645182482962943 + 4.0650837778509628 + 4.0656494419099678 + 4.0662152405189742 + 4.0667811737236859 + 4.0673472415698075 + 4.0679134441030866 + 4.0684797813692537 + 4.0690462534141103 + 4.0696128602834349 + 4.0701796020230612 + 4.070746478678811 + 4.0713134902965438 + 4.0718806369221392 + 4.072447918601501 + 4.0730153353805392 + 4.0735828873051885 + 4.0741505744214184 + 4.074718396775209 + 4.0752863544125519 + 4.0758544473794744 + 4.0764226757220046 + 4.0769910394862192 + 4.0775595387181935 + 4.0781281734640258 + 4.0786969437698524 + 4.0792658496817999 + 4.0798348912460458 + 4.0804040685087548 + 4.0809733815161522 + 4.0815428303144659 + 4.0821124149499211 + 4.0826821354688008 + 4.0832519919173906 + 4.0838219843419887 + 4.084392112788934 + 4.0849623773045778 + 4.0855327779352697 + 4.0861033147274322 + 4.0866739877274494 + 4.0872447969817625 + 4.0878157425368222 + 4.0883868244391079 + 4.0889580427351095 + 4.0895293974713391 + 4.0901008886943337 + 4.0906725164506597 + 4.0912442807868734 + 4.0918161817495919 + 4.092388219385418 + 4.0929603937410031 + 4.0935327048630024 + 4.0941051527980905 + 4.0946777375929839 + 4.0952504592943999 + 4.0958233179490655 + 4.0963963136037727 + 4.096969446305291 + 4.0975427161004241 + 4.0981161230360019 + 4.0986896671588733 + 4.0992633485159118 + 4.0998371671540008 + 4.1004111231200513 + 4.1009852164609892 + 4.1015594472237789 + 4.1021338154553932 + 4.1027083212028215 + 4.1032829645130775 + 4.103857745433209 + 4.1044326640102637 + 4.1050077202913196 + 4.1055829143234828 + 4.1061582461538713 + 4.106733715829618 + 4.1073093233978977 + 4.1078850689058966 + 4.1084609524008107 + 4.109036973929868 + 4.1096131335403205 + 4.1101894312794345 + 4.1107658671944938 + 4.1113424413328215 + 4.1119191537417343 + 4.1124960044686034 + 4.1130729935607846 + 4.1136501210656977 + 4.114227387030728 + 4.1148047915033388 + 4.1153823345309881 + 4.1159600161611429 + 4.1165378364413057 + 4.1171157954190143 + 4.1176938931417997 + 4.118272129657246 + 4.1188505050129125 + 4.1194290192564313 + 4.1200076724354213 + 4.120586464597535 + 4.1211653957904408 + 4.1217444660618474 + 4.122323675459449 + 4.1229030240310083 + 4.1234825118242684 + 4.1240621388869991 + 4.1246419052670173 + 4.1252218110121373 + 4.1258018561702103 + 4.126382040789097 + 4.126962364916686 + 4.1275428286008786 + 4.1281234318896161 + 4.1287041748308519 + 4.1292850574725311 + 4.1298660798626896 + 4.1304472420493106 + 4.1310285440804462 + 4.1316099860041522 + 4.1321915678685199 + 4.1327732897216345 + 4.1333551516116289 + 4.1339371535866549 + 4.1345192956948678 + 4.1351015779844538 + 4.1356840005036455 + 4.1362665633006559 + 4.1368492664237451 + 4.137432109921189 + 4.1380150938412887 + 4.138598218232346 + 4.1391814831427283 + 4.1397648886207783 + 4.1403484347148929 + 4.1409321214734689 + 4.1415159489449405 + 4.1420999171777559 + 4.1426840262203877 + 4.1432682761213284 + 4.1438526669290958 + 4.1444371986922199 + 4.1450218714592699 + 4.1456066852788132 + 4.1461916401994632 + 4.146776736269846 + 4.1473619735386045 + 4.147947352054409 + 4.1485328718659424 + 4.149118533021924 + 4.1497043355710908 + 4.1502902795621859 + 4.1508763650440015 + 4.1514625920653465 + 4.1520489606750148 + 4.1526354709218811 + 4.153222122854781 + 4.1538089165226308 + 4.1543958519743303 + 4.1549829292588045 + 4.1555701484250269 + 4.1561575095219432 + 4.1567450125985834 + 4.1573326577039573 + 4.1579204448871083 + 4.1585083741970994 + 4.1590964456830219 + 4.1596846593939807 + 4.1602730153791159 + 4.1608615136875668 + 4.1614501543685236 + 4.1620389374711753 + 4.1626278630447544 + 4.1632169311384919 + 4.163806141801655 + 4.1643954950835402 + 4.1649849910334567 + 4.1655746297007177 + 4.1661644111346963 + 4.1667543353847627 + 4.1673444025003219 + 4.1679346125307823 + 4.1685249655256023 + 4.1691154615342381 + 4.1697061006061817 + 4.1702968827909448 + 4.1708878081380618 + 4.1714788766970834 + 4.1720700885175797 + 4.1726614436491811 + 4.1732529421414783 + 4.1738445840441374 + 4.1744363694068163 + 4.1750282982792024 + 4.1756203707110231 + 4.1762125867519986 + 4.176804946451897 + 4.1773974498604982 + 4.1779900970276076 + 4.1785828880030333 + 4.1791758228366502 + 4.1797689015783082 + 4.1803621242779112 + 4.1809554909853723 + 4.1815490017506276 + 4.1821426566236486 + 4.1827364556544095 + 4.1833303988929158 + 4.1839244863892082 + 4.184518718193325 + 4.1851130943553541 + 4.1857076149253762 + 4.1863022799535337 + 4.1868970894899515 + 4.1874920435848084 + 4.1880871422882855 + 4.1886823856505941 + 4.1892777737219671 + 4.189873306552669 + 4.1904689841929734 + 4.1910648066931913 + 4.1916607741036414 + 4.1922568864746612 + 4.1928531438566479 + 4.1934495462999717 + 4.1940460938550617 + 4.1946427865723628 + 4.1952396245023182 + 4.1958366076954405 + 4.1964337362022199 + 4.1970310100731831 + 4.1976284293589083 + 4.1982259941099551 + 4.1988237043769345 + 4.1994215602104576 + 4.2000195616611791 + 4.2006177087797711 + 4.2012160016169258 + 4.2018144402233562 + 4.2024130246498022 + 4.2030117549470303 + 4.2036106311658141 + 4.2042096533569762 + 4.2048088215713486 + 4.2054081358597726 + 4.2060075962731345 + 4.2066072028623358 + 4.2072069556783021 + 4.2078068547719774 + 4.2084069001943307 + 4.2090070919963578 + 4.2096074302290853 + 4.2102079149435374 + 4.2108085461907869 + 4.2114093240219255 + 4.2120102484880597 + 4.2126113196403123 + 4.2132125375298592 + 4.213813902207864 + 4.2144154137255363 + 4.2150170721341027 + 4.215618877484828 + 4.2162208298289672 + 4.2168229292178179 + 4.2174251757027168 + 4.2180275693349909 + 4.2186301101660151 + 4.2192327982471856 + 4.2198356336299065 + 4.2204386163656187 + 4.2210417465057866 + 4.2216450241018979 + 4.2222484492054484 + 4.2228520218679924 + 4.2234557421410566 + 4.2240596100762415 + 4.2246636257251442 + 4.2252677891393908 + 4.2258721003706334 + 4.2264765594705347 + 4.2270811664908043 + 4.2276859214831575 + 4.2282908244993447 + 4.2288958755911183 + 4.2295010748102868 + 4.2301064222086557 + 4.2307119178380761 + 4.2313175617503953 + 4.2319233539975132 + 4.2325292946313331 + 4.2331353837037886 + 4.2337416212668364 + 4.2343480073724704 + 4.2349545420726766 + 4.2355612254195032 + 4.2361680574649929 + 4.236775038261217 + 4.2373821678602921 + 4.2379894463143382 + 4.2385968736754958 + 4.2392044499959427 + 4.2398121753278772 + 4.2404200497235101 + 4.2410280732350936 + 4.2416362459149104 + 4.2422445678152245 + 4.2428530389883692 + 4.2434616594866759 + 4.2440704293625195 + 4.2446793486682823 + 4.2452884174563774 + 4.2458976357792348 + 4.2465070036893238 + 4.247116521239132 + 4.2477261884811508 + 4.2483360054679338 + 4.2489459722520282 + 4.2495560888860009 + 4.2501663554224836 + 4.250776771914091 + 4.2513873384134744 + 4.2519980549733178 + 4.2526089216463099 + 4.2532199384851932 + 4.2538311055427114 + 4.2544424228716453 + 4.2550538905247821 + 4.2556655085549506 + 4.2562772770150019 + 4.2568891959577941 + 4.2575012654362387 + 4.2581134855032587 + 4.2587258562117771 + 4.2593383776147764 + 4.2599510497652471 + 4.2605638727162143 + 4.261176846520712 + 4.2617899712318126 + 4.2624032469025925 + 4.2630166735861881 + 4.2636302513357212 + 4.2642439802043652 + 4.2648578602453187 + 4.2654718915117646 + 4.266086074056969 + 4.2667004079341853 + 4.2673148931966942 + 4.2679295298978221 + 4.2685443180908846 + 4.2691592578292559 + 4.2697743491663189 + 4.2703895921554835 + 4.2710049868501718 + 4.2716205333038664 + 4.2722362315700337 + 4.2728520817021867 + 4.2734680837538574 + 4.2740842377785953 + 4.2747005438300016 + 4.2753170019616666 + 4.27593361222723 + 4.2765503746803457 + 4.2771672893746908 + 4.2777843563639832 + 4.2784015757019427 + 4.2790189474423288 + 4.2796364716389217 + 4.2802541483455316 + 4.2808719776159814 + 4.2814899595041203 + 4.282108094063843 + 4.2827263813490442 + 4.2833448214136576 + 4.2839634143116383 + 4.2845821600969662 + 4.2852010588236364 + 4.2858201105456875 + 4.2864393153171756 + 4.287058673192166 + 4.2876781842247826 + 4.2882978484691483 + 4.2889176659794028 + 4.2895376368097429 + 4.2901577610143722 + 4.2907780386475034 + 4.2913984697634184 + 4.2920190544163734 + 4.2926397926606681 + 4.293260684550658 + 4.2938817301406855 + 4.294502929485132 + 4.295124282638402 + 4.2957457896549238 + 4.296367450589166 + 4.2969892654955864 + 4.2976112344287127 + 4.2982333574430713 + 4.2988556345932061 + 4.2994780659337097 + 4.3001006515191929 + 4.3007233914042855 + 4.3013462856436426 + 4.3019693342919512 + 4.302592537403914 + 4.3032158950342749 + 4.3038394072377804 + 4.3044630740692256 + 4.3050868955834254 + 4.3057108718351929 + 4.306335002879413 + 4.3069592887709529 + 4.3075837295647483 + 4.3082083253157224 + 4.3088330760788267 + 4.3094579819090777 + 4.3100830428614589 + 4.3107082589910277 + 4.3113336303528511 + 4.3119591570020175 + 4.3125848389936356 + 4.3132106763828562 + 4.3138366692248384 + 4.3144628175747792 + 4.3150891214878948 + 4.3157155810194379 + 4.3163421962246762 + 4.3169689671588971 + 4.3175958938774333 + 4.3182229764356217 + 4.3188502148888315 + 4.319477609292484 + 4.3201051597019795 + 4.320732866172782 + 4.3213607287603661 + 4.3219887475202245 + 4.3226169225079003 + 4.3232452537789303 + 4.323873741388903 + 4.3245023853934166 + 4.3251311858481154 + 4.3257601428086456 + 4.3263892563306934 + 4.3270185264699679 + 4.3276479532821952 + 4.3282775368231556 + 4.3289072771486223 + 4.3295371743143969 + 4.3301672283763413 + 4.3307974393903068 + 4.331427807412191 + 4.3320583324978941 + 4.3326890147033783 + 4.3333198540846096 + 4.3339508506975726 + 4.3345820045982899 + 4.3352133158428234 + 4.3358447844872403 + 4.3364764105876246 + 4.3371081942001224 + 4.3377401353808676 + 4.338372234186048 + 4.3390044906718739 + 4.339636904894566 + 4.340269476910378 + 4.3409022067756018 + 4.3415350945465461 + 4.3421681402795445 + 4.3428013440309527 + 4.343434705857173 + 4.3440682258146008 + 4.3447019039596908 + 4.3453357403489026 + 4.3459697350387403 + 4.3466038880857107 + 4.3472381995463714 + 4.3478726694772893 + 4.3485072979350647 + 4.3491420849763189 + 4.3497770306577186 + 4.3504121350359233 + 4.3510473981676467 + 4.3516828201096285 + 4.3523184009186133 + 4.3529541406513914 + 4.3535900393647742 + 4.3542260971156042 + 4.3548623139607363 + 4.3554986899570753 + 4.3561352251615189 + 4.3567719196310275 + 4.357408773422569 + 4.3580457865931397 + 4.3586829591997596 + 4.3593202912994871 + 4.3599577829494036 + 4.3605954342065951 + 4.3612332451282105 + 4.3618712157714024 + 4.3625093461933568 + 4.3631476364512798 + 4.3637860866024223 + 4.3644246967040257 + 4.3650634668134094 + 4.3657023969878761 + 4.3663414872847763 + 4.3669807377614847 + 4.3676201484753978 + 4.368259719483941 + 4.3688994508445695 + 4.3695393426147628 + 4.3701793948520384 + 4.3708196076139103 + 4.3714599809579555 + 4.37210051494176 + 4.3727412096229354 + 4.3733820650591166 + 4.374023081307989 + 4.374664258427253 + 4.3753055964746101 + 4.3759470955078283 + 4.3765887555846845 + 4.3772305767629804 + 4.3778725591005445 + 4.3785147026552318 + 4.3791570074849426 + 4.3797994736475871 + 4.3804421012011039 + 4.3810848902034634 + 4.3817278407126494 + 4.382370952786693 + 4.3830142264836542 + 4.3836576618616041 + 4.3843012589786321 + 4.3849450178928935 + 4.3855889386625364 + 4.3862330213457401 + 4.3868772660007318 + 4.3875216726857511 + 4.388166241459059 + 4.3888109723789581 + 4.3894558655037752 + 4.3901009208918538 + 4.3907461386015711 + 4.3913915186913446 + 4.3920370612196065 + 4.3926827662448051 + 4.3933286338254369 + 4.3939746640200257 + 4.3946208568870953 + 4.3952672124852432 + 4.3959137308730583 + 4.3965604121091539 + 4.3972072562521936 + 4.3978542633608679 + 4.3985014334938732 + 4.3991487667099642 + 4.3997962630678851 + 4.4004439226264429 + 4.4010917454444511 + 4.4017397315807587 + 4.4023878810942545 + 4.4030361940438238 + 4.4036846704884063 + 4.4043333104869546 + 4.4049821140984733 + 4.4056310813819621 + 4.4062802123964726 + 4.406929507201065 + 4.4075789658548494 + 4.4082285884169474 + 4.4088783749465179 + 4.4095283255027331 + 4.4101784401448176 + 4.4108287189319881 + 4.4114791619235421 + 4.4121297691787484 + 4.412780540756934 + 4.41343147671747 + 4.4140825771196956 + 4.4147338420230557 + 4.4153852714869677 + 4.4160368655709057 + 4.4166886243343413 + 4.4173405478368055 + 4.4179926361378508 + 4.4186448892970418 + 4.419297307373995 + 4.4199498904283301 + 4.4206026385197115 + 4.4212555517078291 + 4.4219086300523909 + 4.4225618736131649 + 4.423215282449898 + 4.4238688566223976 + 4.4245225961905064 + 4.4251765012140698 + 4.4258305717529831 + 4.4264848078671575 + 4.4271392096165352 + 4.4277937770610967 + 4.4284485102608233 + 4.4291034092757595 + 4.4297584741659559 + 4.4304137049915031 + 4.4310691018125112 + 4.4317246646891242 + 4.4323803936815098 + 4.433036288849868 + 4.4336923502544323 + 4.4343485779554586 + 4.4350049720132239 +} diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index 74bb720b618..8b632ef8891 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -467,7 +467,7 @@ class RENDER_PT_output(RenderButtonsPanel, Panel): flow.prop(rd, "use_placeholder") flow.prop(rd, "use_file_extension") - layout.template_image_settings(image_settings) + layout.template_image_settings(image_settings, color_management=False) if file_format == 'QUICKTIME_CARBON': layout.operator("scene.render_data_set_quicktime_codec") diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py index 8449d26f6e6..fcfd29c0b27 100644 --- a/release/scripts/startup/bl_ui/properties_scene.py +++ b/release/scripts/startup/bl_ui/properties_scene.py @@ -231,6 +231,21 @@ class SCENE_PT_simplify(SceneButtonsPanel, Panel): col.prop(rd, "simplify_ao_sss", text="AO and SSS") +class SCENE_PT_color_management(Panel): + bl_label = "Color Management" + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = "scene" + + def draw(self, context): + layout = self.layout + + scene = context.scene + + layout.prop(scene.display_settings, "display_device") + layout.template_colormanaged_view_settings(scene, "view_settings") + + class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, Panel): COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} _context_path = "scene" diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 124ea2b0014..efac7a66086 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -829,19 +829,6 @@ class CLIP_PT_proxy(CLIP_PT_clip_view_panel, Panel): col.prop(sc.clip_user, "use_render_undistorted") -class CLIP_PT_display_properties(Panel): - bl_space_type = 'CLIP_EDITOR' - bl_region_type = 'UI' - bl_label = "Display Properties" - bl_options = {'DEFAULT_CLOSED'} - - def draw(self, context): - layout = self.layout - space = context.space_data - - layout.template_colormanaged_view_settings(space, "view_settings", True) - - class CLIP_PT_footage(CLIP_PT_clip_view_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 37395639682..0b4d4cd19e4 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -436,18 +436,6 @@ class IMAGE_HT_header(Header): layout.prop(sima, "use_realtime_update", text="", icon_only=True, icon='LOCKED') -class IMAGE_PT_display_properties(Panel): - bl_space_type = 'IMAGE_EDITOR' - bl_region_type = 'UI' - bl_label = "Display Properties" - - def draw(self, context): - layout = self.layout - space = context.space_data - - layout.template_colormanaged_view_settings(space, "view_settings", True) - - class IMAGE_PT_image_properties(Panel): bl_space_type = 'IMAGE_EDITOR' bl_region_type = 'UI' diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py index e4a21507864..d2d8dc22aea 100644 --- a/release/scripts/startup/bl_ui/space_info.py +++ b/release/scripts/startup/bl_ui/space_info.py @@ -357,7 +357,6 @@ class INFO_MT_window(Menu): import sys window = context.window - display_settings = window.display_settings layout = self.layout @@ -367,9 +366,6 @@ class INFO_MT_window(Menu): layout.separator() layout.operator("wm.console_toggle", icon='CONSOLE') - layout.separator() - layout.prop_menu_enum(display_settings, "display_device", text="Display") - class INFO_MT_help(Menu): bl_label = "Help" diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index 3a0f64e66de..5b7ecbfb618 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -191,18 +191,6 @@ class NODE_MT_node(Menu): layout.operator("node.read_fullsamplelayers") -class NODE_PT_display_properties(Panel): - bl_space_type = 'NODE_EDITOR' - bl_region_type = 'UI' - bl_label = "Display Properties" - - def draw(self, context): - layout = self.layout - space = context.space_data - - layout.template_colormanaged_view_settings(space, "view_settings", True) - - # Node Backdrop options class NODE_PT_properties(Panel): bl_space_type = 'NODE_EDITOR' diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 4f453e4320a..a0121867199 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -882,10 +882,10 @@ class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel): col.prop(st, "show_separate_color") col.prop(st, "proxy_render_size") - col = layout.column() - col.separator() - col.label(text="Color Management:") - col.template_colormanaged_view_settings(st, "view_settings", True) + #col = layout.column() + #col.separator() + #col.label(text="Color Management:") + #col.template_colormanaged_view_settings(st, "view_settings", True) class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel): diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index d0901ad93ff..5138d68cf79 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -1273,8 +1273,6 @@ void BKE_color_managed_view_settings_init(ColorManagedViewSettings *settings) settings->gamma = 1.0f; settings->exposure = 0.0f; - - settings->flag |= COLORMANAGE_VIEW_USE_GLOBAL; } void BKE_color_managed_view_settings_copy(ColorManagedViewSettings *new_settings, diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index c0ec1cc9297..e74413c3198 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -175,8 +175,8 @@ Scene *BKE_scene_copy(Scene *sce, int type) im_format = &sce->r.im_format; im_formatn = &scen->r.im_format; - BKE_color_managed_display_settings_copy(&im_formatn->display_settings, &im_format->display_settings); - BKE_color_managed_view_settings_copy(&im_formatn->view_settings, &im_format->view_settings); + BKE_color_managed_display_settings_copy(&scen->display_settings, &sce->display_settings); + BKE_color_managed_view_settings_copy(&scen->view_settings, &sce->view_settings); } /* tool settings */ @@ -556,8 +556,8 @@ Scene *BKE_scene_add(const char *name) sound_create_scene(sce); - BKE_color_managed_display_settings_init(&sce->r.im_format.display_settings); - BKE_color_managed_view_settings_init(&sce->r.im_format.view_settings); + BKE_color_managed_display_settings_init(&sce->display_settings); + BKE_color_managed_view_settings_init(&sce->view_settings); return sce; } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 01ae4a35f3c..9156debc80c 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -72,6 +72,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "IMB_colormanagement.h" #include "BKE_context.h" #include "BKE_sound.h" @@ -1838,8 +1839,9 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, } if (seq->flag & SEQ_MAKE_FLOAT) { - if (!ibuf->rect_float) - IMB_float_from_rect_simple(ibuf); + if (!ibuf->rect_float) { + IMB_colormanagement_imbuf_to_sequencer_space(ibuf, TRUE); + } if (ibuf->rect) { imb_freerectImBuf(ibuf); @@ -2350,11 +2352,8 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float } /* float buffers in the sequencer are not linear */ - if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) - ibuf->profile = IB_PROFILE_LINEAR_RGB; - else - ibuf->profile = IB_PROFILE_NONE; - IMB_convert_profile(ibuf, IB_PROFILE_SRGB); + ibuf->profile = IB_PROFILE_LINEAR_RGB; + IMB_colormanagement_imbuf_to_sequencer_space(ibuf, FALSE); } else if (rres.rect32) { ibuf = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect); @@ -2460,8 +2459,7 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo imb_freerectImBuf(ibuf); /* all sequencer color is done in SRGB space, linear gives odd crossfades */ - if (ibuf->profile == IB_PROFILE_LINEAR_RGB) - IMB_convert_profile(ibuf, IB_PROFILE_NONE); + IMB_colormanagement_imbuf_to_sequencer_space(ibuf, FALSE); copy_to_ibuf_still(context, seq, nr, ibuf); @@ -2653,6 +2651,12 @@ static ImBuf *seq_render_strip_stack(SeqRenderData context, ListBase *seqbasep, if (count == 1) { out = seq_render_strip(context, seq_arr[0], cfra); + + if (out) { + /* put buffer back to linear space */ + IMB_colormanagement_imbuf_from_sequencer_space(out); + } + BKE_sequencer_cache_put(context, seq_arr[0], cfra, SEQ_STRIPELEM_IBUF_COMP, out); return out; @@ -2732,6 +2736,11 @@ static ImBuf *seq_render_strip_stack(SeqRenderData context, ListBase *seqbasep, BKE_sequencer_cache_put(context, seq_arr[i], cfra, SEQ_STRIPELEM_IBUF_COMP, out); } + if (out) { + /* put buffer back to linear space */ + IMB_colormanagement_imbuf_from_sequencer_space(out); + } + return out; } diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 19946971411..e668b6a39fa 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -803,7 +803,7 @@ void uiTemplateColorWheel(uiLayout *layout, struct PointerRNA *ptr, const char * void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, const char *propname, PointerRNA *used_ptr, const char *used_propname, int active_layer); void uiTemplateImage(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, struct PointerRNA *userptr, int compact); -void uiTemplateImageSettings(uiLayout *layout, struct PointerRNA *imfptr); +void uiTemplateImageSettings(uiLayout *layout, struct PointerRNA *imfptr, int color_management); void uiTemplateImageLayers(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser); void uiTemplateRunningJobs(uiLayout *layout, struct bContext *C); void uiTemplateOperatorSearch(uiLayout *layout); @@ -824,7 +824,7 @@ void uiTemplateTrack(struct uiLayout *layout, struct PointerRNA *ptr, const char void uiTemplateMarker(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, PointerRNA *userptr, PointerRNA *trackptr, int cmpact); void uiTemplateColorspaceSettings(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname); -void uiTemplateColormanagedViewSettings(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, int show_global_settings); +void uiTemplateColormanagedViewSettings(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname); /* items */ void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index a7934687e9a..7e0fe4d277e 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2814,11 +2814,11 @@ void uiTemplateColorspaceSettings(uiLayout *layout, PointerRNA *ptr, const char uiItemR(layout, &colorspace_settings_ptr, "name", 0, "", ICON_NONE); } -void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, int show_global_settings) +void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr, const char *propname) { PropertyRNA *prop; PointerRNA view_transform_ptr; - uiLayout *col; + uiLayout *col, *row; ColorManagedViewSettings *view_settings; prop = RNA_struct_find_property(ptr, propname); @@ -2834,23 +2834,8 @@ void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *C, PointerRN col = uiLayoutColumn(layout, FALSE); - if (show_global_settings) { - wmWindow *win = CTX_wm_window(C); - bScreen *screen = CTX_wm_screen(C); - - uiItemR(col, &view_transform_ptr, "use_global_settings", 0, NULL, ICON_NONE); - - if (view_settings->flag & COLORMANAGE_VIEW_USE_GLOBAL) { - PointerRNA window_ptr; - - RNA_pointer_create(&screen->id, &RNA_Window, win, &window_ptr); - - prop = RNA_struct_find_property(&window_ptr, "view_settings"); - view_transform_ptr = RNA_property_pointer_get(&window_ptr, prop); - } - } - - uiItemR(col, &view_transform_ptr, "view_transform", 0, "View", ICON_NONE); + row = uiLayoutRow(col, FALSE); + uiItemR(row, &view_transform_ptr, "view_transform", UI_ITEM_R_EXPAND, IFACE_("View"), ICON_NONE); col = uiLayoutColumn(layout, FALSE); uiItemR(col, &view_transform_ptr, "exposure", 0, NULL, ICON_NONE); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index f2f37583ce9..80b55979bbc 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -853,10 +853,6 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, wmEvent *event) BLI_rcti_translate(&rect, win->posx, win->posy); newwin = WM_window_open(C, &rect); - /* copy color management settings from the current window */ - BKE_color_managed_display_settings_copy(&newwin->display_settings, &win->display_settings); - BKE_color_managed_view_settings_copy(&newwin->view_settings, &win->view_settings); - /* allocs new screen and adds to newly created window, using window size */ newsc = ED_screen_add(newwin, CTX_data_scene(C), sc->id.name + 2); newwin->screen = newsc; diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 4e71c49465f..5e54119118a 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -245,7 +245,7 @@ static void screenshot_draw(bContext *UNUSED(C), wmOperator *op) /* image template */ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &scd->im_format, &ptr); - uiTemplateImageSettings(layout, &ptr); + uiTemplateImageSettings(layout, &ptr, TRUE); /* main draw call */ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 14197a46663..507e8591c6b 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -260,7 +260,7 @@ static void verify_buffer_float(ImBuf *ibuf) } #endif -static void draw_movieclip_buffer(wmWindow *win, SpaceClip *sc, ARegion *ar, ImBuf *ibuf, +static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, ImBuf *ibuf, int width, int height, float zoomx, float zoomy) { int x, y; @@ -274,15 +274,13 @@ static void draw_movieclip_buffer(wmWindow *win, SpaceClip *sc, ARegion *ar, ImB glRectf(x, y, x + zoomx * width, y + zoomy * height); } else { - const ColorManagedViewSettings *view_settings; unsigned char *display_buffer; void *cache_handle; /* OCIO_TODO: finally get rid of this stuff */ /* verify_buffer_float(ibuf); */ - view_settings = IMB_view_settings_get_effective(win, &sc->view_settings); - display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, &win->display_settings, &cache_handle); + display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); if (display_buffer) { int need_fallback = 1; @@ -1429,7 +1427,6 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar) { - wmWindow *win = CTX_wm_window(C); MovieClip *clip = ED_space_clip_get_clip(sc); Scene *scene = CTX_data_scene(C); ImBuf *ibuf; @@ -1479,7 +1476,7 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar) } if (ibuf) { - draw_movieclip_buffer(win, sc, ar, ibuf, width, height, zoomx, zoomy); + draw_movieclip_buffer(C, sc, ar, ibuf, width, height, zoomx, zoomy); IMB_freeImBuf(ibuf); } else { diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index b2186891df0..803a9dd2d1d 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -253,8 +253,6 @@ static SpaceLink *clip_new(const bContext *C) sc->scopes.track_preview_height = 120; sc->around = V3D_LOCAL; - BKE_color_managed_view_settings_init(&sc->view_settings); - /* header */ ar = MEM_callocN(sizeof(ARegion), "header for clip"); @@ -335,7 +333,6 @@ static void clip_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa) static SpaceLink *clip_duplicate(SpaceLink *sl) { - SpaceClip *sc = (SpaceClip *) sl; SpaceClip *scn = MEM_dupallocN(sl); /* clear or remove stuff from old */ @@ -344,8 +341,6 @@ static SpaceLink *clip_duplicate(SpaceLink *sl) scn->scopes.ok = FALSE; scn->draw_context = NULL; - BKE_color_managed_view_settings_copy(&scn->view_settings, &sc->view_settings); - return (SpaceLink *)scn; } diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index bc22a220adf..e33291e460f 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -798,7 +798,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char MEM_freeN(cb); } -void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr) +void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_management) { ImageFormatData *imf = imfptr->data; ID *id = imfptr->id.data; @@ -874,8 +874,9 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr) } /* color management */ - if (!BKE_imtype_supports_float(imf->imtype) || - (show_preview && imf->flag & R_IMF_FLAG_PREVIEW_JPG)) + if (color_management && + (!BKE_imtype_supports_float(imf->imtype) || + (show_preview && imf->flag & R_IMF_FLAG_PREVIEW_JPG))) { prop = RNA_struct_find_property(imfptr, "display_settings"); display_settings_ptr = RNA_property_pointer_get(imfptr, prop); @@ -885,7 +886,7 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr) uiItemR(col, &display_settings_ptr, "display_device", 0, NULL, ICON_NONE); - uiTemplateColormanagedViewSettings(col, NULL, imfptr, "view_settings", FALSE); + uiTemplateColormanagedViewSettings(col, NULL, imfptr, "view_settings"); } } diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 8867f5bba0d..3b18c9a4a2d 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -430,7 +430,7 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rec MEM_freeN(rectf); } -static void draw_image_buffer(wmWindow *win, SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy) +static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy) { int x, y; int color_manage = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT; @@ -457,7 +457,6 @@ static void draw_image_buffer(wmWindow *win, SpaceImage *sima, ARegion *ar, Scen sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float); } else { - const ColorManagedViewSettings *view_settings; unsigned char *display_buffer; void *cache_handle; @@ -472,8 +471,7 @@ static void draw_image_buffer(wmWindow *win, SpaceImage *sima, ARegion *ar, Scen * convert them, and optionally apply curves */ image_verify_buffer_float(ima, ibuf, color_manage); - view_settings = IMB_view_settings_get_effective(win, &sima->view_settings); - display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, &win->display_settings, &cache_handle); + display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); if (display_buffer) glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer); @@ -553,7 +551,7 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene, MEM_freeN(rect); } -static void draw_image_buffer_repeated(wmWindow *win, SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float zoomx, float zoomy) +static void draw_image_buffer_repeated(const bContext *C, SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float zoomx, float zoomy) { const double time_current = PIL_check_seconds_timer(); @@ -570,7 +568,7 @@ static void draw_image_buffer_repeated(wmWindow *win, SpaceImage *sima, ARegion if (ima && (ima->tpageflag & IMA_TILES)) draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, x, y, zoomx, zoomy); else - draw_image_buffer(win, sima, ar, scene, ima, ibuf, x, y, zoomx, zoomy); + draw_image_buffer(C, sima, ar, scene, ima, ibuf, x, y, zoomx, zoomy); /* only draw until running out of time */ if ((PIL_check_seconds_timer() - time_current) > 0.25) @@ -723,7 +721,6 @@ void draw_image_main(const bContext *C, ARegion *ar) { SpaceImage *sima = CTX_wm_space_image(C); Scene *scene = CTX_data_scene(C); - wmWindow *win = CTX_wm_window(C); Image *ima; ImBuf *ibuf; float zoomx, zoomy; @@ -772,11 +769,11 @@ void draw_image_main(const bContext *C, ARegion *ar) if (ibuf == NULL) ED_region_grid_draw(ar, zoomx, zoomy); else if (sima->flag & SI_DRAW_TILE) - draw_image_buffer_repeated(win, sima, ar, scene, ima, ibuf, zoomx, zoomy); + draw_image_buffer_repeated(C, sima, ar, scene, ima, ibuf, zoomx, zoomy); else if (ima && (ima->tpageflag & IMA_TILES)) draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, 0.0f, 0.0, zoomx, zoomy); else - draw_image_buffer(win, sima, ar, scene, ima, ibuf, 0.0f, 0.0f, zoomx, zoomy); + draw_image_buffer(C, sima, ar, scene, ima, ibuf, 0.0f, 0.0f, zoomx, zoomy); /* paint helpers */ if (sima->mode == SI_MODE_PAINT) diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 6d88fa02b4a..43fe4594406 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1115,14 +1115,12 @@ static char imtype_best_depth(ImBuf *ibuf, const char imtype) } } -static int save_image_options_init(bContext *C, SaveImageOptions *simopts, SpaceImage *sima, Scene *scene, const short guess_path) +static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima, Scene *scene, const short guess_path) { void *lock; ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock); if (ibuf) { - wmWindow *win = CTX_wm_window(C); - const ColorManagedViewSettings *view_settings; Image *ima = sima->image; short is_depth_set = FALSE; @@ -1173,10 +1171,8 @@ static int save_image_options_init(bContext *C, SaveImageOptions *simopts, Space } /* color management */ - view_settings = IMB_view_settings_get_effective(win, &sima->view_settings); - - BKE_color_managed_display_settings_copy(&simopts->im_format.display_settings, &win->display_settings); - BKE_color_managed_view_settings_copy(&simopts->im_format.view_settings, view_settings); + BKE_color_managed_display_settings_copy(&simopts->im_format.display_settings, &scene->display_settings); + BKE_color_managed_view_settings_copy(&simopts->im_format.view_settings, &scene->view_settings); } ED_space_image_release_buffer(sima, lock); @@ -1368,7 +1364,7 @@ static int image_save_as_exec(bContext *C, wmOperator *op) /* just in case to initialize values, * these should be set on invoke or by the caller. */ - save_image_options_init(C, &simopts, sima, CTX_data_scene(C), 0); + save_image_options_init(&simopts, sima, CTX_data_scene(C), 0); save_image_options_from_op(&simopts, op); @@ -1397,7 +1393,7 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(eve save_image_options_defaults(&simopts); - if (save_image_options_init(C, &simopts, sima, scene, TRUE) == 0) + if (save_image_options_init(&simopts, sima, scene, TRUE) == 0) return OPERATOR_CANCELLED; save_image_options_to_op(&simopts, op); @@ -1441,7 +1437,7 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op) /* image template */ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &ptr); - uiTemplateImageSettings(layout, &ptr); + uiTemplateImageSettings(layout, &ptr, TRUE); /* main draw call */ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); @@ -1483,7 +1479,7 @@ static int image_save_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); SaveImageOptions simopts; - if (save_image_options_init(C, &simopts, sima, scene, FALSE) == 0) + if (save_image_options_init(&simopts, sima, scene, FALSE) == 0) return OPERATOR_CANCELLED; save_image_options_from_op(&simopts, op); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 886d778ec15..d232a86f9e5 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -152,8 +152,6 @@ static SpaceLink *image_new(const bContext *UNUSED(C)) simage->zoom = 1.0f; simage->lock = TRUE; - BKE_color_managed_view_settings_init(&simage->view_settings); - simage->iuser.ok = TRUE; simage->iuser.fie_ima = 2; simage->iuser.frames = 100; @@ -216,7 +214,6 @@ static void image_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa) static SpaceLink *image_duplicate(SpaceLink *sl) { - SpaceImage *simage = (SpaceImage *) sl; SpaceImage *simagen = MEM_dupallocN(sl); /* clear or remove stuff from old */ @@ -225,8 +222,6 @@ static SpaceLink *image_duplicate(SpaceLink *sl) scopes_new(&simagen->scopes); - BKE_color_managed_view_settings_copy(&simagen->view_settings, &simage->view_settings); - return (SpaceLink *)simagen; } diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 2a6fd3b8417..a77a7e47816 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1999,7 +1999,7 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER); node_composit_buts_file_output(layout, C, ptr); - uiTemplateImageSettings(layout, &imfptr); + uiTemplateImageSettings(layout, &imfptr, TRUE); uiItemS(layout); @@ -2058,7 +2058,7 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C col = uiLayoutColumn(layout, FALSE); uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format") == FALSE); - uiTemplateImageSettings(col, &imfptr); + uiTemplateImageSettings(col, &imfptr, TRUE); } } } @@ -3033,8 +3033,6 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode) ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (ibuf) { SpaceNode *snode = CTX_wm_space_node(C); - wmWindow *win = CTX_wm_window(C); - const ColorManagedViewSettings *view_settings; float x, y; unsigned char *display_buffer; void *cache_handle; @@ -3057,8 +3055,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode) y = (ar->winy - snode->zoom * ibuf->y) / 2 + snode->yof; - view_settings = IMB_view_settings_get_effective(win, &snode->view_settings); - display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, &win->display_settings, &cache_handle); + display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); if (display_buffer) { if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B)) { diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index fbe28291500..a8e43563649 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -98,8 +98,6 @@ static SpaceLink *node_new(const bContext *UNUSED(C)) /* backdrop */ snode->zoom = 1.0f; - BKE_color_managed_view_settings_init(&snode->view_settings); - /* header */ ar = MEM_callocN(sizeof(ARegion), "header for node"); @@ -308,15 +306,12 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa) static SpaceLink *node_duplicate(SpaceLink *sl) { - SpaceImage *snode = (SpaceImage *) sl; SpaceNode *snoden = MEM_dupallocN(sl); /* clear or remove stuff from old */ snoden->nodetree = NULL; snoden->linkdrag.first = snoden->linkdrag.last = NULL; - BKE_color_managed_view_settings_copy(&snoden->view_settings, &snode->view_settings); - return (SpaceLink *)snoden; } diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 19da6e91247..50fffeac09d 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -919,13 +919,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq display_buffer = (unsigned char *)ibuf->rect; } else { - const ColorManagedViewSettings *view_settings; - wmWindow *win = CTX_wm_window(C); - - ibuf->colormanagement_flags |= IMB_COLORMANAGEMENT_SRGB_SOURCE; - - view_settings = IMB_view_settings_get_effective(win, &sseq->view_settings); - display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, &win->display_settings, &cache_handle); + display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); } /* setting up the view - actual drawing starts here */ diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 08c9fd7d19a..41055e135e3 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -33,6 +33,7 @@ #define BCM_CONFIG_FILE "config.ocio" +struct bContext; struct ColorManagedColorspaceSettings; struct ColorManagedDisplaySettings; struct ColorManagedViewSettings; @@ -42,6 +43,7 @@ struct Main; struct rcti; struct PartialBufferUpdateContext; struct wmWindow; +struct Scene; /* ** Initialization / De-initialization ** */ @@ -52,15 +54,23 @@ void IMB_colormanagement_exit(void); void IMB_colormanagement_colorspace_transform(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace); +void IMB_colormanagement_imbuf_to_role(struct ImBuf *ibuf, int role); +void IMB_colormanagement_imbuf_from_role(struct ImBuf *ibuf, int role); + void IMB_colormanagement_imbuf_make_scene_linear(struct ImBuf *ibuf, struct ColorManagedColorspaceSettings *colorspace_settings); +void IMB_colormanagement_imbuf_to_sequencer_space(struct ImBuf *ibuf, int make_float); +void IMB_colormanagement_imbuf_from_sequencer_space(struct ImBuf *ibuf); + /* ** Public display buffers interfaces ** */ void IMB_colormanage_cache_free(struct ImBuf *ibuf); unsigned char *IMB_display_buffer_acquire(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, void **cache_handle); +unsigned char *IMB_display_buffer_acquire_ctx(const struct bContext *C, struct ImBuf *ibuf, void **cache_handle); + void IMB_display_buffer_to_imbuf_rect(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings); @@ -70,8 +80,8 @@ void IMB_display_buffer_invalidate(struct ImBuf *ibuf); void IMB_colormanagement_check_file_config(struct Main *bmain); -const struct ColorManagedViewSettings *IMB_view_settings_get_effective(struct wmWindow *win, - const struct ColorManagedViewSettings *view_settings); +void IMB_colormanagement_validate_settings(struct ColorManagedDisplaySettings *display_settings, + struct ColorManagedViewSettings *view_settings); /* ** Display funcrions ** */ int IMB_colormanagement_display_get_named_index(const char *name); @@ -96,4 +106,11 @@ void IMB_partial_display_buffer_update(struct ImBuf *ibuf, const float *linear_b int stride, int offset_x, int offset_y, int xmin, int ymin, int xmax, int ymax); +enum { + COLOR_ROLE_SCENE_LINEAR = 0, + COLOR_ROLE_COLOR_PICKING, + COLOR_ROLE_TEXTURE_PAINTING, + COLOR_ROLE_SEQUENCER, +}; + #endif // IMB_COLORMANAGEMENT_H diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index f6dc6735567..db19a2a1fd2 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -396,6 +396,11 @@ void IMB_buffer_float_clamp(float *buf, int width, int height); typedef void (*imb_tonecurveCb) (float rgbOut[3], const float rgbIn[3]); +void IMB_buffer_float_from_float_tonecurve(float *rect_to, const float *rect_from, + int channels_from, int profile_to, int profile_from, int predivide, + int width, int height, int stride_to, int stride_from, + imb_tonecurveCb tonecurve_func); + void IMB_buffer_byte_from_float_tonecurve(unsigned char *rect_to, const float *rect_from, int channels_from, float dither, int profile_to, int profile_from, int predivide, int width, int height, int stride_to, int stride_from, diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 697a64ae744..d6d500976d1 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -261,10 +261,9 @@ extern const char *imb_ext_audio[]; /* imbuf->colormanagement_flags */ -/* special flag used for color management of compositor results, - * which are in sRGB space and requires extra step in color conversions - * could be replaced with something more general in the future +/* special flag for image buffers used in sequencer, which stores all + * images in display space, even float buffers */ -#define IMB_COLORMANAGEMENT_SRGB_SOURCE (1 << 0) +#define IMB_COLORMANAGEMENT_NONLINEAR_FLOAT (1 << 0) #endif diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 76f1128b8fc..46f6509526d 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -56,6 +56,7 @@ #include "BLI_string.h" #include "BLI_threads.h" +#include "BKE_context.h" #include "BKE_utildefines.h" #include "BKE_main.h" @@ -69,14 +70,16 @@ /* define this to allow byte buffers be color managed */ #undef COLORMANAGE_BYTE_BUFFER +#undef COLORMANAGE_USE_ACES_ODT -#define ACES_ODT_TONECORVE "ACES ODT Tonecurve" +#define ACES_ODT_TONECORVE "ACES" /* ** list of all supported color spaces, displays and views */ #ifdef WITH_OCIO static char global_role_scene_linear[64]; static char global_role_color_picking[64]; static char global_role_texture_painting[64]; +static char global_role_sequencer[64]; #endif static ListBase global_colorspaces = {NULL}; @@ -445,7 +448,10 @@ static void colormanage_load_config(ConstConfigRcPtr *config) OCIO_ROLE_COLOR_PICKING, "color picking"); colormanage_role_color_space_name_get(config, global_role_texture_painting, sizeof(global_role_texture_painting), - OCIO_ROLE_TEXTURE_PAINT, "texture_painting"); + OCIO_ROLE_TEXTURE_PAINT, "texture painting"); + + colormanage_role_color_space_name_get(config, global_role_sequencer, sizeof(global_role_sequencer), + OCIO_ROLE_SEQUENCER, "sequencer"); /* load colorspaces */ tot_colorspace = OCIO_configGetNumColorSpaces(config); @@ -571,8 +577,11 @@ void IMB_colormanagement_init(void) OCIO_configRelease(config); +#ifdef COLORMANAGE_USE_ACES_ODT /* special views, which does not depend on OCIO */ colormanage_view_add(ACES_ODT_TONECORVE); +#endif + #endif BLI_init_srgb_conversion(); @@ -602,8 +611,6 @@ typedef struct DisplayBufferThread { int channels; int dither; int predivide; - - int buffer_in_srgb; } DisplayBufferThread; typedef struct DisplayBufferInitData { @@ -647,8 +654,6 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l handle->channels = channels; handle->dither = dither; handle->predivide = predivide; - - handle->buffer_in_srgb = ibuf->colormanagement_flags & IMB_COLORMANAGEMENT_SRGB_SOURCE; } static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned char *byte_buffer, @@ -693,17 +698,6 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide, width, height, width, width); } - else if (handle->buffer_in_srgb) { - /* sequencer is working with float buffers which are in sRGB space, - * so we need to ensure float buffer is in linear space before - * applying all the view transformations - */ - float *buffer = handle->buffer; - - IMB_buffer_float_from_float(linear_buffer, buffer, channels, - IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, - predivide, width, height, width, width); - } else { /* some processors would want to modify float original buffer * before converting it into display byte buffer, so we need to @@ -720,6 +714,7 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) return linear_buffer; } +#ifdef COLORMANAGE_USE_ACES_ODT static void *do_display_buffer_apply_tonemap_thread(void *handle_v) { DisplayBufferThread *handle = (DisplayBufferThread *) handle_v; @@ -754,6 +749,7 @@ static void display_buffer_apply_tonemap(ImBuf *ibuf, unsigned char *display_buf display_buffer, tonecurve_func, do_display_buffer_apply_tonemap_thread); } +#endif static void *do_display_buffer_apply_ocio_thread(void *handle_v) { @@ -861,6 +857,7 @@ static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *displ const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { +#ifdef COLORMANAGE_USE_ACES_ODT const char *view_transform = view_settings->view_transform; if (!strcmp(view_transform, ACES_ODT_TONECORVE)) { @@ -870,10 +867,11 @@ static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *displ */ display_buffer_apply_tonemap(ibuf, display_buffer, IMB_ratio_preserving_odt_tonecurve); } - else { + else +#endif + { display_buffer_apply_ocio(ibuf, display_buffer, view_settings, display_settings); } - } /*********************** Threaded color space transform routines *************************/ @@ -1001,6 +999,72 @@ void IMB_colormanagement_colorspace_transform(float *buffer, int width, int heig #endif } +#ifdef WITH_OCIO +static char *role_colorspace_name_get(int role) +{ + switch (role) { + case COLOR_ROLE_SCENE_LINEAR: + return global_role_scene_linear; + break; + case COLOR_ROLE_COLOR_PICKING: + return global_role_color_picking; + break; + case COLOR_ROLE_TEXTURE_PAINTING: + return global_role_texture_painting; + break; + case COLOR_ROLE_SEQUENCER: + return global_role_sequencer; + break; + default: + printf("Unknown role was passed to %s\n", __func__); + BLI_assert(0); + } + + return NULL; +} +#endif + +void IMB_colormanagement_imbuf_to_role(ImBuf *ibuf, int role) +{ +#ifdef WITH_OCIO + if (ibuf->rect_float) { + const char *from_colorspace = global_role_scene_linear; + const char *to_colorspace = role_colorspace_name_get(role); + + if (ibuf->rect) + imb_freerectImBuf(ibuf); + + IMB_colormanagement_colorspace_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, + from_colorspace, to_colorspace); + } +#else + (void) ibuf; + (void) role; +#endif +} + +void IMB_colormanagement_imbuf_from_role(ImBuf *ibuf, int role) +{ +#ifdef WITH_OCIO + if (ibuf->rect_float) { + const char *from_colorspace = role_colorspace_name_get(role); + const char *to_colorspace = global_role_scene_linear; + + if (ibuf->rect) + imb_freerectImBuf(ibuf); + + IMB_colormanagement_colorspace_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, + from_colorspace, to_colorspace); + + /* buffer in now in scene linear space */ + ibuf->profile = IB_PROFILE_LINEAR_RGB; + } +#else + (void) ibuf; + (void) role; +#endif +} + void IMB_colormanagement_imbuf_make_scene_linear(ImBuf *ibuf, ColorManagedColorspaceSettings *colorspace_settings) { #ifdef WITH_OCIO @@ -1017,6 +1081,64 @@ void IMB_colormanagement_imbuf_make_scene_linear(ImBuf *ibuf, ColorManagedColors #endif } +void IMB_colormanagement_imbuf_to_sequencer_space(ImBuf *ibuf, int make_float) +{ + (void) make_float; + + if (!ibuf->rect_float) { + if (make_float) { + /* when converting byte buffer to float in sequencer we need to make float + * buffer be in sequencer's working space, which is currently only doable + * from linear space. + * + */ + + /* + * OCIO_TODO: would be nice to support direct single transform from byte to sequencer's + */ + + ibuf->profile = IB_PROFILE_SRGB; + IMB_float_from_rect(ibuf); + } + else { + /* if there's only byte buffer in image it's already in compositor's working space, + * nothing to do here + */ + + return; + } + } + +#ifdef WITH_OCIO + if (global_role_sequencer[0]) { + IMB_colormanagement_imbuf_to_role(ibuf, COLOR_ROLE_SEQUENCER); + } + else +#endif + { + /* if no sequencer's working space defined fallback to legacy sRGB space */ + IMB_convert_profile(ibuf, IB_PROFILE_SRGB); + } +} + +void IMB_colormanagement_imbuf_from_sequencer_space(ImBuf *ibuf) +{ + if (!ibuf->rect_float) + return; + +#ifdef WITH_OCIO + if (global_role_sequencer[0]) { + IMB_colormanagement_imbuf_from_role(ibuf, COLOR_ROLE_SEQUENCER); + } + else +#endif + { + /* if no sequencer's working space defined fallback to legacy sRGB space */ + + IMB_convert_profile(ibuf, IB_PROFILE_LINEAR_RGB); + } +} + #ifdef WITH_OCIO static void colormanage_flags_allocate(ImBuf *ibuf) { @@ -1074,8 +1196,6 @@ void IMB_colormanage_cache_free(ImBuf *ibuf) unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, void **cache_handle) { - const char *view_transform = view_settings->view_transform; - *cache_handle = NULL; #ifdef WITH_OCIO @@ -1091,10 +1211,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet } #endif - if (!strcmp(view_transform, "NONE") || - global_tot_display == 0 || - global_tot_view == 0) - { + if (global_tot_display == 0 || global_tot_view == 0) { /* currently only view-transformation is allowed, input and display * spaces are hard-coded, so if there's no view transform applying * it's safe to suppose standard byte buffer is used for display @@ -1143,7 +1260,6 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet * profiles without applying any view / display transformation */ (void) view_settings; - (void) view_transform; (void) display_settings; imbuf_verify_float(ibuf); @@ -1152,21 +1268,35 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet #endif } +static void display_transform_settings_get(const bContext *C, ColorManagedViewSettings **view_settings_r, ColorManagedDisplaySettings **display_settings_r) +{ + Scene *scene = CTX_data_scene(C); + + *view_settings_r = &scene->view_settings; + *display_settings_r = &scene->display_settings; +} + +unsigned char *IMB_display_buffer_acquire_ctx(const bContext *C, ImBuf *ibuf, void **cache_handle) +{ + ColorManagedViewSettings *view_settings; + ColorManagedDisplaySettings *display_settings; + + display_transform_settings_get(C, &view_settings, &display_settings); + + return IMB_display_buffer_acquire(ibuf, view_settings, display_settings, cache_handle); +} + void IMB_display_buffer_to_imbuf_rect(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { #ifdef WITH_OCIO - const char *view_transform = view_settings->view_transform; #if !defined(COLORMANAGE_BYTE_BUFFER) if (!ibuf->rect_float) return; #endif - if (!strcmp(view_transform, "NONE") || - global_tot_display == 0 || - global_tot_view == 0) - { + if (global_tot_display == 0 || global_tot_view == 0) { imbuf_verify_float(ibuf); } else { @@ -1229,10 +1359,7 @@ static void colormanage_check_view_settings(ColorManagedViewSettings *view_setti const ColorManagedView *default_view) { if (view_settings->view_transform[0] == '\0') { - BLI_strncpy(view_settings->view_transform, "NONE", sizeof(view_settings->view_transform)); - } - else if (!strcmp(view_settings->view_transform, "NONE")) { - /* pass */ + BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform)); } else { ColorManagedView *view = colormanage_view_get_named(view_settings->view_transform); @@ -1247,7 +1374,6 @@ static void colormanage_check_view_settings(ColorManagedViewSettings *view_setti /* OCIO_TODO: move to do_versions() */ if (view_settings->exposure == 0.0f && view_settings->gamma == 0.0f) { - view_settings->flag |= COLORMANAGE_VIEW_USE_GLOBAL; view_settings->exposure = 0.0f; view_settings->gamma = 1.0f; } @@ -1279,9 +1405,6 @@ static void colormanage_check_colorspace_settings(ColorManagedColorspaceSettings void IMB_colormanagement_check_file_config(Main *bmain) { #ifdef WITH_OCIO - wmWindowManager *wm = bmain->wm.first; - wmWindow *win; - bScreen *sc; Scene *scene; Image *image; MovieClip *clip; @@ -1303,54 +1426,9 @@ void IMB_colormanagement_check_file_config(Main *bmain) return; } - /* ** check display device settings ** */ - - if (wm) { - for (win = wm->windows.first; win; win = win->next) { - colormanage_check_display_settings(&win->display_settings, "window", default_display); - - colormanage_check_view_settings(&win->view_settings, "window", default_view); - } - } - - /* ** check view transform settings ** */ - for (sc = bmain->screen.first; sc; sc = sc->id.next) { - ScrArea *sa; - - for (sa = sc->areabase.first; sa; sa = sa->next) { - SpaceLink *sl; - for (sl = sa->spacedata.first; sl; sl = sl->next) { - - if (sl->spacetype == SPACE_IMAGE) { - SpaceImage *sima = (SpaceImage *) sl; - - colormanage_check_view_settings(&sima->view_settings, "image editor", default_view); - } - else if (sl->spacetype == SPACE_NODE) { - SpaceNode *snode = (SpaceNode *) sl; - - colormanage_check_view_settings(&snode->view_settings, "node editor", default_view); - } - else if (sl->spacetype == SPACE_CLIP) { - SpaceClip *sclip = (SpaceClip *) sl; - - colormanage_check_view_settings(&sclip->view_settings, "clip editor", default_view); - } - else if (sl->spacetype == SPACE_SEQ) { - SpaceSeq *sseq = (SpaceSeq *) sl; - - colormanage_check_view_settings(&sseq->view_settings, "sequencer editor", default_view); - } - } - } - } - for (scene = bmain->scene.first; scene; scene = scene->id.next) { - ImageFormatData *imf = &scene->r.im_format; - - colormanage_check_display_settings(&imf->display_settings, "scene", default_display); - - colormanage_check_view_settings(&imf->view_settings, "scene", default_view); + colormanage_check_display_settings(&scene->display_settings, "scene", default_display); + colormanage_check_view_settings(&scene->view_settings, "scene", default_view); } /* ** check input color space settings ** */ @@ -1360,21 +1438,34 @@ void IMB_colormanagement_check_file_config(Main *bmain) } for (clip = bmain->movieclip.first; clip; clip = clip->id.next) { - colormanage_check_colorspace_settings(&clip->colorspace_settings, "image"); + colormanage_check_colorspace_settings(&clip->colorspace_settings, "clip"); } #else (void) bmain; #endif } -const ColorManagedViewSettings *IMB_view_settings_get_effective(wmWindow *win, - const ColorManagedViewSettings *view_settings) +void IMB_colormanagement_validate_settings(ColorManagedDisplaySettings *display_settings, + ColorManagedViewSettings *view_settings) { - if (view_settings->flag & COLORMANAGE_VIEW_USE_GLOBAL) { - return &win->view_settings; +#ifdef WITH_OCIO + ColorManagedDisplay *display; + ColorManagedView *default_view, *view; + + display = colormanage_display_get_named(display_settings->display_device); + default_view = colormanage_view_get_default(display); + + for (view = display->views.first; view; view = view->next) { + if (!strcmp(view->name, view_settings->view_transform)) + break; } - return view_settings; + if (view == NULL) + BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform)); +#else + (void) display_settings; + (void) view_settings; +#endif } /*********************** Display functions *************************/ @@ -1685,11 +1776,13 @@ void IMB_colormanagement_view_items_add(EnumPropertyItem **items, int *totitem, ColorManagedDisplay *display = colormanage_display_get_named(display_name); ColorManagedView *view; +#ifdef COLORMANAGE_USE_ACES_ODT /* OCIO_TODO: try to get rid of such a hackish stuff */ view = colormanage_view_get_named(ACES_ODT_TONECORVE); if (view) { colormanagement_view_item_add(items, totitem, view); } +#endif if (display) { LinkData *display_view; @@ -1833,10 +1926,13 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, ConstProcessorRcPtr *processor = NULL; imb_tonecurveCb tonecurve_func = NULL; +#ifdef COLORMANAGE_USE_ACES_ODT if (!strcmp(view_name, ACES_ODT_TONECORVE)) { tonecurve_func = IMB_ratio_preserving_odt_tonecurve; } - else { + else +#endif + { processor = create_display_buffer_processor(view_name, display_name, exposure, gamma); } @@ -1864,5 +1960,8 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, (void) ymin; (void) xmax; (void) ymax; + (void) stride; + (void) offset_x; + (void) offset_y; #endif } diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h index f2702980bb7..5ccc2579179 100644 --- a/source/blender/makesdna/DNA_color_types.h +++ b/source/blender/makesdna/DNA_color_types.h @@ -161,17 +161,11 @@ typedef struct Scopes { #define SCOPES_WAVEFRM_YCC_JPEG 4 typedef struct ColorManagedViewSettings { - int flag; /* assodted flags such as using global settings from window and so */ char view_transform[64]; /* view transform which is being applied when displaying buffer on the screen */ float exposure; /* fstop exposure */ float gamma; /* post-display gamma transform */ - int pad; } ColorManagedViewSettings; -enum { - COLORMANAGE_VIEW_USE_GLOBAL = (1 << 0) /* use global display settings instead of per-space setting */ -}; - typedef struct ColorManagedDisplaySettings { char display_device[64]; } ColorManagedDisplaySettings; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 83050561cc4..ed0e27917ad 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -274,7 +274,7 @@ typedef struct ImageFormatData { char pad[7]; - /* --- color management --- */ + /* color management */ ColorManagedViewSettings view_settings; ColorManagedDisplaySettings display_settings; } ImageFormatData; @@ -1137,6 +1137,10 @@ typedef struct Scene { uint64_t customdata_mask; /* XXX. runtime flag for drawing, actually belongs in the window, only used by BKE_object_handle_update() */ uint64_t customdata_mask_modal; /* XXX. same as above but for temp operator use (gl renders) */ + + /* Color Management */ + ColorManagedViewSettings view_settings; + ColorManagedDisplaySettings display_settings; } Scene; diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 89a027cbcfb..b828247c816 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -35,7 +35,7 @@ #include "DNA_defs.h" #include "DNA_listBase.h" -#include "DNA_color_types.h" /* for Histogram and color management */ +#include "DNA_color_types.h" /* for Histogram */ #include "DNA_vec_types.h" #include "DNA_outliner_types.h" /* for TreeStoreElem */ #include "DNA_image_types.h" /* ImageUser */ @@ -473,9 +473,6 @@ typedef struct SpaceSeq { int overlay_type; struct bGPdata *gpd; /* grease-pencil data */ - - /* **** color management **** */ - ColorManagedViewSettings view_settings; } SpaceSeq; @@ -711,9 +708,6 @@ typedef struct SpaceImage { char around; MaskSpaceInfo mask_info; - - /* **** color management **** */ - ColorManagedViewSettings view_settings; } SpaceImage; @@ -903,9 +897,6 @@ typedef struct SpaceNode { ListBase linkdrag; /* temporary data for modal linking operator */ struct bGPdata *gpd; /* grease-pencil data */ - - /* **** color management **** */ - ColorManagedViewSettings view_settings; } SpaceNode; /* snode->flag */ @@ -1049,9 +1040,6 @@ typedef struct SpaceClip { int around, pad4; /* pivot point for transforms */ MaskSpaceInfo mask_info; - - /* **** color management **** */ - ColorManagedViewSettings view_settings; } SpaceClip; /* SpaceClip->flag */ diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 7cf9ae97640..780ca0b5878 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -31,7 +31,6 @@ #ifndef __DNA_WINDOWMANAGER_TYPES_H__ #define __DNA_WINDOWMANAGER_TYPES_H__ -#include "DNA_color_types.h" /* for color management */ #include "DNA_listBase.h" #include "DNA_vec_types.h" @@ -196,11 +195,6 @@ typedef struct wmWindow { ListBase subwindows; /* opengl stuff for sub windows, see notes in wm_subwindow.c */ ListBase gesture; /* gesture stuff */ - - /* color management */ - - ColorManagedDisplaySettings display_settings; /* display-specific settings */ - ColorManagedViewSettings view_settings; /* global view settings */ } wmWindow; /* should be something like DNA_EXCLUDE diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index b6625a97c5b..5f1669cd3c8 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -37,11 +37,6 @@ #include "WM_api.h" #include "WM_types.h" -static EnumPropertyItem view_transform_items[] = { - {0, "NONE", 0, "None", "Do not perform any color transform on display, use old non-color managed technique for display"}, - {0, NULL, 0, NULL, NULL} -}; - static EnumPropertyItem color_space_items[] = { {0, "NONE", 0, "None", "Do not perform any color transform on load, treat colors as in scene linear space already"}, {0, NULL, 0, NULL, NULL} @@ -383,6 +378,17 @@ static EnumPropertyItem *rna_ColorManagedDisplaySettings_display_device_itemf(bC return items; } +static void rna_ColorManagedDisplaySettings_display_device_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + ID *id = ptr->id.data; + + if (GS(id->name) == ID_SCE) { + Scene *scene = (Scene *) id; + + IMB_colormanagement_validate_settings(&scene->display_settings, &scene->view_settings); + } +} + static int rna_ColorManagedViewSettings_view_transform_get(PointerRNA *ptr) { ColorManagedViewSettings *view = (ColorManagedViewSettings *) ptr->data; @@ -403,12 +409,11 @@ static void rna_ColorManagedViewSettings_view_transform_set(PointerRNA *ptr, int static EnumPropertyItem* rna_ColorManagedViewSettings_view_transform_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free) { - wmWindow *win = CTX_wm_window(C); + Scene *scene = CTX_data_scene(C); EnumPropertyItem *items = NULL; - ColorManagedDisplaySettings *display_settings = &win->display_settings; + ColorManagedDisplaySettings *display_settings = &scene->display_settings; int totitem = 0; - RNA_enum_item_add(&items, &totitem, &view_transform_items[0]); IMB_colormanagement_view_items_add(&items, &totitem, display_settings->display_device); RNA_enum_item_end(&items, &totitem); @@ -820,6 +825,11 @@ static void rna_def_colormanage(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem view_transform_items[] = { + {0, "NONE", 0, "None", "Do not perform any color transform on display, use old non-color managed technique for display"}, + {0, NULL, 0, NULL, NULL} + }; + /* ** Display Settings ** */ srna = RNA_def_struct(brna, "ColorManagedDisplaySettings", NULL); RNA_def_struct_ui_text(srna, "ColorManagedDisplaySettings", "Color management specific to display device"); @@ -830,23 +840,18 @@ static void rna_def_colormanage(BlenderRNA *brna) "rna_ColorManagedDisplaySettings_display_device_set", "rna_ColorManagedDisplaySettings_display_device_itemf"); RNA_def_property_ui_text(prop, "Display Device", "Display device name"); - RNA_def_property_update(prop, NC_WINDOW, NULL); + RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedDisplaySettings_display_device_update"); /* ** View Settings ** */ srna = RNA_def_struct(brna, "ColorManagedViewSettings", NULL); RNA_def_struct_ui_text(srna, "ColorManagedViewSettings", "Color management settings used for displaying images on the display"); - prop = RNA_def_property(srna, "use_global_settings", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", COLORMANAGE_VIEW_USE_GLOBAL); - RNA_def_property_ui_text(prop, "Use Global Settings", "Use global display settings instead of per-space setting"); - RNA_def_property_update(prop, NC_WINDOW, NULL); - prop= RNA_def_property(srna, "view_transform", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, view_transform_items); RNA_def_property_enum_funcs(prop, "rna_ColorManagedViewSettings_view_transform_get", "rna_ColorManagedViewSettings_view_transform_set", "rna_ColorManagedViewSettings_view_transform_itemf"); - RNA_def_property_ui_text(prop, "View Transform", "View transform used for this image editor"); + RNA_def_property_ui_text(prop, "View Transform", "View used "); RNA_def_property_update(prop, NC_WINDOW, NULL); prop = RNA_def_property(srna, "exposure", PROP_FLOAT, PROP_FACTOR); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index c23508be45a..aca1b3d3a8f 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -4583,6 +4583,17 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Active Movie Clip", "Active movie clip used for constraints and viewport drawing"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + /* color management */ + prop = RNA_def_property(srna, "view_settings", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "view_settings"); + RNA_def_property_struct_type(prop, "ColorManagedViewSettings"); + RNA_def_property_ui_text(prop, "View Settings", "Color management settings applied on image before saving"); + + prop = RNA_def_property(srna, "display_settings", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "display_settings"); + RNA_def_property_struct_type(prop, "ColorManagedDisplaySettings"); + RNA_def_property_ui_text(prop, "Display Settings", "Settings of device saved image would be displayed on"); + /* Nestled Data */ rna_def_tool_settings(brna); rna_def_unified_paint_settings(brna); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index c00a6670102..ce5f39d0b42 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2086,11 +2086,6 @@ static void rna_def_space_image(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Show UV Editor", "Show UV editing related properties"); - prop = RNA_def_property(srna, "view_settings", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "view_settings"); - RNA_def_property_struct_type(prop, "ColorManagedViewSettings"); - RNA_def_property_ui_text(prop, "View Settings", "Color management settings used for displaying images on the display"); - prop = RNA_def_property(srna, "show_maskedit", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_SpaceImageEditor_show_maskedit_get", NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -2218,11 +2213,6 @@ static void rna_def_space_sequencer(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this space"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); - prop = RNA_def_property(srna, "view_settings", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "view_settings"); - RNA_def_property_struct_type(prop, "ColorManagedViewSettings"); - RNA_def_property_ui_text(prop, "View Settings", "Color management settings used for displaying images on the display"); - prop = RNA_def_property(srna, "overlay_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "overlay_type"); RNA_def_property_enum_items(prop, overlay_type_items); @@ -3040,11 +3030,6 @@ static void rna_def_space_node(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Draw Channels", "Channels of the image to draw"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL); - prop = RNA_def_property(srna, "view_settings", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "view_settings"); - RNA_def_property_struct_type(prop, "ColorManagedViewSettings"); - RNA_def_property_ui_text(prop, "View Settings", "Color management settings used for displaying images on the display"); - prop = RNA_def_property(srna, "show_highlight", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_SHOW_HIGHLIGHT); RNA_def_property_ui_text(prop, "Highlight", "Highlight nodes that are being calculated"); @@ -3368,12 +3353,6 @@ static void rna_def_space_clip(BlenderRNA *brna) RNA_def_property_enum_items(prop, pivot_items); RNA_def_property_ui_text(prop, "Pivot Point", "Pivot center for rotation/scaling"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL); - - /* color management view settings */ - prop = RNA_def_property(srna, "view_settings", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "view_settings"); - RNA_def_property_struct_type(prop, "ColorManagedViewSettings"); - RNA_def_property_ui_text(prop, "View Settings", "Color management settings used for displaying images on the display"); } diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 592385a60d1..ea38b60b25f 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -415,6 +415,7 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_function_ui_description(func, "User interface for setting image format options"); parm = RNA_def_pointer(func, "image_settings", "ImageFormatSettings", "", ""); RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL); + RNA_def_boolean(func, "color_management", 0, "", "Show color management settings"); func = RNA_def_function(srna, "template_movieclip", "uiTemplateMovieClip"); RNA_def_function_ui_description(func, "Item(s). User interface for selecting movie clips and their source paths"); @@ -507,7 +508,7 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_function_ui_description(func, "Item. A widget to control color managed view settings settings."); RNA_def_function_flag(func, FUNC_USE_CONTEXT); api_ui_item_rna_common(func); - RNA_def_boolean(func, "show_global_settings", 0, "", "Show widgets to control global color management settings"); + /* RNA_def_boolean(func, "show_global_settings", 0, "", "Show widgets to control global color management settings"); */ } #endif diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index baf01e489ff..cd6517b8d40 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -1591,17 +1591,6 @@ static void rna_def_window(BlenderRNA *brna) RNA_def_property_pointer_funcs(prop, NULL, "rna_Window_screen_set", NULL, NULL); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_update(prop, 0, "rna_Window_screen_update"); - - /* Color Management Display */ - prop = RNA_def_property(srna, "display_settings", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "display_settings"); - RNA_def_property_struct_type(prop, "ColorManagedDisplaySettings"); - RNA_def_property_ui_text(prop, "Display Settings", "Display device settings used by this window"); - - prop = RNA_def_property(srna, "view_settings", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "view_settings"); - RNA_def_property_struct_type(prop, "ColorManagedViewSettings"); - RNA_def_property_ui_text(prop, "View Settings", "Global color management settings used for displaying images on the display"); } /* curve.splines */ diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 2d4a39c51b8..badbf48338d 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2072,8 +2072,7 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr static void colormanage_image_for_write(Scene *scene, ImBuf *ibuf) { - IMB_display_buffer_to_imbuf_rect(ibuf, &scene->r.im_format.view_settings, - &scene->r.im_format.display_settings); + IMB_display_buffer_to_imbuf_rect(ibuf, &scene->view_settings, &scene->display_settings); if (ibuf) imb_freerectfloatImBuf(ibuf); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 17c45d467a0..ad1b80ed651 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -245,8 +245,6 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *winorig) win->drawmethod = -1; win->drawdata = NULL; - BKE_color_managed_display_settings_copy(&win->display_settings, &winorig->display_settings); - return win; } From b2483c3dbe523dac48846ac05d5fdf9c2ba3cdfd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 22 Aug 2012 15:08:41 +0000 Subject: [PATCH 079/160] despeckle node for tomato only --- source/blender/blenkernel/BKE_node.h | 3 +- source/blender/blenkernel/intern/node.c | 1 + source/blender/compositor/CMakeLists.txt | 4 + source/blender/compositor/COM_defines.h | 2 +- .../compositor/intern/COM_Converter.cpp | 4 + .../compositor/nodes/COM_DespeckleNode.cpp | 50 +++++++ .../compositor/nodes/COM_DespeckleNode.h | 36 +++++ .../operations/COM_DespeckleOperation.cpp | 139 ++++++++++++++++++ .../operations/COM_DespeckleOperation.h | 49 ++++++ source/blender/editors/space_node/drawnode.c | 12 ++ source/blender/makesrna/intern/rna_nodetree.c | 17 +++ .../makesrna/intern/rna_nodetree_types.h | 1 + source/blender/nodes/CMakeLists.txt | 1 + source/blender/nodes/NOD_composite.h | 1 + .../nodes/node_composite_despeckle.c | 66 +++++++++ 15 files changed, 384 insertions(+), 2 deletions(-) create mode 100644 source/blender/compositor/nodes/COM_DespeckleNode.cpp create mode 100644 source/blender/compositor/nodes/COM_DespeckleNode.h create mode 100644 source/blender/compositor/operations/COM_DespeckleOperation.cpp create mode 100644 source/blender/compositor/operations/COM_DespeckleOperation.h create mode 100644 source/blender/nodes/composite/nodes/node_composite_despeckle.c diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 2a0679e3977..4748267278e 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -680,7 +680,8 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria #define CMP_NODE_KEYINGSCREEN 269 #define CMP_NODE_KEYING 270 #define CMP_NODE_TRACKPOS 271 -#define CMP_NODE_INPAINT 272 +#define CMP_NODE_INPAINT 272 +#define CMP_NODE_DESPECKLE 273 #define CMP_NODE_GLARE 301 #define CMP_NODE_TONEMAP 302 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 37562686a99..22b0cccf175 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2139,6 +2139,7 @@ static void registerCompositNodes(bNodeTreeType *ttype) register_node_type_cmp_vecblur(ttype); register_node_type_cmp_dilateerode(ttype); register_node_type_cmp_inpaint(ttype); + register_node_type_cmp_despeckle(ttype); register_node_type_cmp_defocus(ttype); register_node_type_cmp_valtorgb(ttype); diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index c110d4f077e..9932ed17378 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -284,6 +284,8 @@ set(SRC nodes/COM_FilterNode.cpp nodes/COM_FilterNode.h + nodes/COM_DespeckleNode.cpp + nodes/COM_DespeckleNode.h nodes/COM_DilateErodeNode.cpp nodes/COM_DilateErodeNode.h nodes/COM_InpaintNode.cpp @@ -592,6 +594,8 @@ set(SRC operations/COM_ConvolutionFilterOperation.cpp operations/COM_ConvolutionEdgeFilterOperation.h operations/COM_ConvolutionEdgeFilterOperation.cpp + operations/COM_DespeckleOperation.cpp + operations/COM_DespeckleOperation.h operations/COM_DilateErodeOperation.cpp operations/COM_DilateErodeOperation.h operations/COM_InpaintOperation.cpp diff --git a/source/blender/compositor/COM_defines.h b/source/blender/compositor/COM_defines.h index 3cc161a5877..9d9033962db 100644 --- a/source/blender/compositor/COM_defines.h +++ b/source/blender/compositor/COM_defines.h @@ -84,7 +84,7 @@ typedef enum CompositorPriority { /** * COM_CURRENT_THREADING_MODEL can be one of the above, COM_TM_QUEUE is currently default. */ -#define COM_CURRENT_THREADING_MODEL COM_TM_QUEUE +#define COM_CURRENT_THREADING_MODEL COM_TM_NOTHREAD // chunk order /** * @brief The order of chunks to be scheduled diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index 37b53c44ef7..d4fad80ed07 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -56,6 +56,7 @@ #include "COM_Converter.h" #include "COM_CropNode.h" #include "COM_DefocusNode.h" +#include "COM_DespeckleNode.h" #include "COM_DifferenceMatteNode.h" #include "COM_DilateErodeNode.h" #include "COM_DirectionalBlurNode.h" @@ -307,6 +308,9 @@ Node *Converter::convert(bNode *b_node, bool fast) case CMP_NODE_INPAINT: node = new InpaintNode(b_node); break; + case CMP_NODE_DESPECKLE: + node = new DespeckleNode(b_node); + break; case CMP_NODE_LENSDIST: node = new LensDistortionNode(b_node); break; diff --git a/source/blender/compositor/nodes/COM_DespeckleNode.cpp b/source/blender/compositor/nodes/COM_DespeckleNode.cpp new file mode 100644 index 00000000000..603ddcd1389 --- /dev/null +++ b/source/blender/compositor/nodes/COM_DespeckleNode.cpp @@ -0,0 +1,50 @@ +/* + * 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. + * + * Contributor: Campbell Barton + */ + +#include "COM_DespeckleNode.h" +#include "DNA_scene_types.h" +#include "COM_ExecutionSystem.h" +#include "COM_DespeckleOperation.h" +#include "BLI_math.h" + +DespeckleNode::DespeckleNode(bNode *editorNode) : Node(editorNode) +{ + /* pass */ +} + +void DespeckleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) +{ + bNode *editorNode = this->getbNode(); + InputSocket *inputSocket = this->getInputSocket(0); + InputSocket *inputImageSocket = this->getInputSocket(1); + OutputSocket *outputSocket = this->getOutputSocket(0); + DespeckleOperation *operation = new DespeckleOperation(); + + operation->setbNode(editorNode); + operation->setThreshold(editorNode->custom3); + operation->setThresholdNeighbour(editorNode->custom4); + + inputImageSocket->relinkConnections(operation->getInputSocket(0), 1, graph); + inputSocket->relinkConnections(operation->getInputSocket(1), 0, graph); + outputSocket->relinkConnections(operation->getOutputSocket()); + addPreviewOperation(graph, operation->getOutputSocket(0)); + + graph->addOperation(operation); +} diff --git a/source/blender/compositor/nodes/COM_DespeckleNode.h b/source/blender/compositor/nodes/COM_DespeckleNode.h new file mode 100644 index 00000000000..2b8ab9d0226 --- /dev/null +++ b/source/blender/compositor/nodes/COM_DespeckleNode.h @@ -0,0 +1,36 @@ +/* + * 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. + * + * Contributor: Campbell Barton + */ + +#ifndef _COM_DespeckleNode_h_ +#define _COM_DespeckleNode_h_ + +#include "COM_Node.h" + +/** + * @brief DespeckleNode + * @ingroup Node + */ +class DespeckleNode : public Node { +public: + DespeckleNode(bNode *editorNode); + void convertToOperations(ExecutionSystem *graph, CompositorContext *context); +}; + +#endif diff --git a/source/blender/compositor/operations/COM_DespeckleOperation.cpp b/source/blender/compositor/operations/COM_DespeckleOperation.cpp new file mode 100644 index 00000000000..6e2f9ab4351 --- /dev/null +++ b/source/blender/compositor/operations/COM_DespeckleOperation.cpp @@ -0,0 +1,139 @@ +/* + * 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. + * + * Contributor: Campbell Barton + */ + +#include "MEM_guardedalloc.h" + +#include "COM_DespeckleOperation.h" + +#include "BLI_utildefines.h" + +DespeckleOperation::DespeckleOperation() : NodeOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + this->setResolutionInputSocketIndex(0); + this->m_inputOperation = NULL; + this->setComplex(true); +} +void DespeckleOperation::initExecution() +{ + this->m_inputOperation = this->getInputSocketReader(0); + this->m_inputValueOperation = this->getInputSocketReader(1); +} + +void DespeckleOperation::deinitExecution() +{ + this->m_inputOperation = NULL; + this->m_inputValueOperation = NULL; +} + +BLI_INLINE int color_diff(const float a[3], const float b[3], const float threshold) +{ + return ((fabsf(a[0] - b[0]) > threshold) || + (fabsf(a[1] - b[1]) > threshold) || + (fabsf(a[2] - b[2]) > threshold)); +} + +void DespeckleOperation::executePixel(float output[4], int x, int y, void *data) +{ + float w = 0.0f; + float color_org[4]; + float color_mid[4]; + float color_mid_ok[4]; + float in1[4]; + int x1 = x - 1; + int x2 = x; + int x3 = x + 1; + int y1 = y - 1; + int y2 = y; + int y3 = y + 1; + CLAMP(x1, 0, getWidth() - 1); + CLAMP(x2, 0, getWidth() - 1); + CLAMP(x3, 0, getWidth() - 1); + CLAMP(y1, 0, getHeight() - 1); + CLAMP(y2, 0, getHeight() - 1); + CLAMP(y3, 0, getHeight() - 1); + float value[4]; + this->m_inputValueOperation->read(value, x2, y2, NULL); + //const float mval = 1.0f - value[0]; + + + this->m_inputOperation->read(color_org, x2, y2, NULL); + +#define TOT_DIV_ONE 1.0 +#define TOT_DIV_CNR M_SQRT1_2 + +#define WTOT (TOT_DIV_ONE * 4 + TOT_DIV_CNR * 4) + +#define COLOR_ADD(fac) \ +{ \ + madd_v4_v4fl(color_mid, in1, fac); \ + if (color_diff(in1, color_org, this->m_threshold)) { \ + w += fac; \ + madd_v4_v4fl(color_mid_ok, in1, fac); \ + } \ +} + + zero_v4(color_mid); + zero_v4(color_mid_ok); + + this->m_inputOperation->read(in1, x1, y1, NULL); COLOR_ADD(TOT_DIV_CNR) + this->m_inputOperation->read(in1, x2, y1, NULL); COLOR_ADD(TOT_DIV_ONE) + this->m_inputOperation->read(in1, x3, y1, NULL); COLOR_ADD(TOT_DIV_CNR) + this->m_inputOperation->read(in1, x1, y2, NULL); COLOR_ADD(TOT_DIV_ONE) + +#if 0 + this->m_inputOperation->read(in2, x2, y2, NULL); + madd_v4_v4fl(color_mid, in2, this->m_filter[4]); +#endif + + this->m_inputOperation->read(in1, x3, y2, NULL); COLOR_ADD(TOT_DIV_ONE) + this->m_inputOperation->read(in1, x1, y3, NULL); COLOR_ADD(TOT_DIV_CNR) + this->m_inputOperation->read(in1, x2, y3, NULL); COLOR_ADD(TOT_DIV_ONE) + this->m_inputOperation->read(in1, x3, y3, NULL); COLOR_ADD(TOT_DIV_CNR) + + mul_v4_fl(color_mid, 1.0f / (4.0f + (4.0f * M_SQRT1_2))); + //mul_v4_fl(color_mid, 1.0f / w); + + if ((w != 0.0f) && + ((w / WTOT) > (this->m_threshold_neighbour)) && + color_diff(color_mid, color_org, this->m_threshold)) + { + mul_v4_fl(color_mid_ok, 1.0f / w); + interp_v4_v4v4(output, color_org, color_mid_ok, value[0]); + } + else { + copy_v4_v4(output, color_org); + } +} + +bool DespeckleOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +{ + rcti newInput; + int addx = 1; //(this->m_filterWidth - 1) / 2 + 1; + int addy = 1; //(this->m_filterHeight - 1) / 2 + 1; + newInput.xmax = input->xmax + addx; + newInput.xmin = input->xmin - addx; + newInput.ymax = input->ymax + addy; + newInput.ymin = input->ymin - addy; + + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); +} diff --git a/source/blender/compositor/operations/COM_DespeckleOperation.h b/source/blender/compositor/operations/COM_DespeckleOperation.h new file mode 100644 index 00000000000..5b79d7cb7e0 --- /dev/null +++ b/source/blender/compositor/operations/COM_DespeckleOperation.h @@ -0,0 +1,49 @@ +/* + * 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. + * + * Contributor: Campbell Barton + */ + +#ifndef _COM_DespeckleOperation_h +#define _COM_DespeckleOperation_h +#include "COM_NodeOperation.h" + +class DespeckleOperation : public NodeOperation { +private: + float m_threshold; + float m_threshold_neighbour; + + int m_filterWidth; + int m_filterHeight; + +protected: + SocketReader *m_inputOperation; + SocketReader *m_inputValueOperation; + +public: + DespeckleOperation(); + bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + void executePixel(float output[4], int x, int y, void *data); + + void setThreshold(float threshold) { this->m_threshold = threshold; } + void setThresholdNeighbour(float threshold) { this->m_threshold_neighbour = threshold; } + + void initExecution(); + void deinitExecution(); +}; + +#endif diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index a77a7e47816..ad61fe571c2 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1817,6 +1817,15 @@ static void node_composit_buts_inpaint(uiLayout *layout, bContext *UNUSED(C), Po uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE); } +static void node_composit_buts_despeckle(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiLayout *col; + + col = uiLayoutColumn(layout, FALSE); + uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "threshold_neighbour", 0, NULL, ICON_NONE); +} + static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *col; @@ -2679,6 +2688,9 @@ static void node_composit_set_butfunc(bNodeType *ntype) case CMP_NODE_INPAINT: ntype->uifunc = node_composit_buts_inpaint; break; + case CMP_NODE_DESPECKLE: + ntype->uifunc = node_composit_buts_despeckle; + break; case CMP_NODE_OUTPUT_FILE: ntype->uifunc = node_composit_buts_file_output; ntype->uifuncbut = node_composit_buts_file_output_details; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 667d85706e0..29288612aa6 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -2166,6 +2166,23 @@ static void def_cmp_inpaint(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_cmp_despeckle(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "custom3"); + RNA_def_property_range(prop, 0.0, 1.0f); + RNA_def_property_ui_text(prop, "Threshold", "Threshold for detecting pixels to despeckle"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "threshold_neighbour", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "custom4"); + RNA_def_property_range(prop, 0.0, 1.0f); + RNA_def_property_ui_text(prop, "Neighbour", "Threshold for the number of neighbour pixels that must match"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + static void def_cmp_scale(StructRNA *srna) { PropertyRNA *prop; diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index c70dd01cd57..15ad1c557a5 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -122,6 +122,7 @@ DefNode( CompositorNode, CMP_NODE_ZCOMBINE, def_cmp_zcombine, "ZCOMB DefNode( CompositorNode, CMP_NODE_COMBRGBA, 0, "COMBRGBA", CombRGBA, "Combine RGBA", "" ) DefNode( CompositorNode, CMP_NODE_DILATEERODE, def_cmp_dilate_erode, "DILATEERODE", DilateErode, "Dilate/Erode", "" ) DefNode( CompositorNode, CMP_NODE_INPAINT, def_cmp_inpaint, "INPAINT", Inpaint, "Inpaint", "" ) +DefNode( CompositorNode, CMP_NODE_DESPECKLE, def_cmp_despeckle, "DESPECKLE", Despeckle, "Despeckle", "" ) DefNode( CompositorNode, CMP_NODE_ROTATE, def_cmp_rotate, "ROTATE", Rotate, "Rotate", "" ) DefNode( CompositorNode, CMP_NODE_SCALE, def_cmp_scale, "SCALE", Scale, "Scale", "" ) DefNode( CompositorNode, CMP_NODE_SEPYCCA, def_cmp_ycc, "SEPYCCA", SepYCCA, "Separate YCCA", "" ) diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 64987a52a21..e1adb419a8a 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -59,6 +59,7 @@ set(SRC composite/nodes/node_composite_composite.c composite/nodes/node_composite_crop.c composite/nodes/node_composite_curves.c + composite/nodes/node_composite_despeckle.c composite/nodes/node_composite_doubleEdgeMask.c composite/nodes/node_composite_defocus.c composite/nodes/node_composite_diffMatte.c diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index 92e547288c9..bcef230e1d0 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -81,6 +81,7 @@ void register_node_type_cmp_bilateralblur(struct bNodeTreeType *ttype); void register_node_type_cmp_vecblur(struct bNodeTreeType *ttype); void register_node_type_cmp_dilateerode(struct bNodeTreeType *ttype); void register_node_type_cmp_inpaint(struct bNodeTreeType *ttype); +void register_node_type_cmp_despeckle(struct bNodeTreeType *ttype); void register_node_type_cmp_defocus(struct bNodeTreeType *ttype); void register_node_type_cmp_valtorgb(struct bNodeTreeType *ttype); diff --git a/source/blender/nodes/composite/nodes/node_composite_despeckle.c b/source/blender/nodes/composite/nodes/node_composite_despeckle.c new file mode 100644 index 00000000000..c1861ca9d86 --- /dev/null +++ b/source/blender/nodes/composite/nodes/node_composite_despeckle.c @@ -0,0 +1,66 @@ +/* + * ***** 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) 2006 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/composite/nodes/node_composite_despeckle.c + * \ingroup cmpnodes + */ + +#include "node_composite_util.h" + +/* **************** FILTER ******************** */ +static bNodeSocketTemplate cmp_node_despeckle_in[]= { + { SOCK_FLOAT, 1, N_("Fac"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, + { -1, 0, "" } +}; +static bNodeSocketTemplate cmp_node_despeckle_out[]= { + { SOCK_RGBA, 0, N_("Image")}, + { -1, 0, "" } +}; + +#ifdef WITH_COMPOSITOR_LEGACY + +static void node_composit_exec_despeckle(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **UNUSED(in), bNodeStack **UNUSED(out)) +{ + /* pass */ +} + +#endif /* WITH_COMPOSITOR_LEGACY */ + +void register_node_type_cmp_despeckle(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, CMP_NODE_DESPECKLE, "Despeckle", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS); + node_type_socket_templates(&ntype, cmp_node_despeckle_in, cmp_node_despeckle_out); + node_type_size(&ntype, 80, 40, 120); +#ifdef WITH_COMPOSITOR_LEGACY + node_type_exec(&ntype, node_composit_exec_despeckle); +#endif + + nodeRegisterType(ttype, &ntype); +} From 78ea8df3417a053109a487d9483851151ea068f1 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 22 Aug 2012 15:13:14 +0000 Subject: [PATCH 080/160] Movie cache: made it thread safe to operate with memory limitor Movie cache is using global memory limitor, which isn't thread safe in some of operations, so it required to add mutex around limitor operations in movie cache. It's probably could be solved in a way with less locks involved bu using different limitor for different areas (like use own limitor for clips, own limitor for sequencer and so), but that wouldn't be so easy to control overall memory usage. --- source/blender/imbuf/intern/moviecache.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/source/blender/imbuf/intern/moviecache.c b/source/blender/imbuf/intern/moviecache.c index 71eae6c6c21..dd6ccbb1dab 100644 --- a/source/blender/imbuf/intern/moviecache.c +++ b/source/blender/imbuf/intern/moviecache.c @@ -41,6 +41,7 @@ #include "BLI_utildefines.h" #include "BLI_ghash.h" #include "BLI_mempool.h" +#include "BLI_threads.h" #include "IMB_moviecache.h" @@ -58,6 +59,7 @@ #endif static MEM_CacheLimiterC *limitor = NULL; +static pthread_mutex_t limitor_lock = BLI_MUTEX_INITIALIZER; typedef struct MovieCache { char name[64]; @@ -334,16 +336,20 @@ void IMB_moviecache_put(MovieCache *cache, void *userkey, ImBuf *ibuf) BLI_ghash_remove(cache->hash, key, moviecache_keyfree, moviecache_valfree); BLI_ghash_insert(cache->hash, key, item); - item->c_handle = MEM_CacheLimiter_insert(limitor, item); - if (cache->last_userkey) { memcpy(cache->last_userkey, userkey, cache->keysize); } + BLI_mutex_lock(&limitor_lock); + + item->c_handle = MEM_CacheLimiter_insert(limitor, item); + MEM_CacheLimiter_ref(item->c_handle); MEM_CacheLimiter_enforce_limits(limitor); MEM_CacheLimiter_unref(item->c_handle); + BLI_mutex_unlock(&limitor_lock); + /* cache limiter can't remove unused keys which points to destoryed values */ check_unused_keys(cache); @@ -364,7 +370,10 @@ ImBuf *IMB_moviecache_get(MovieCache *cache, void *userkey) if (item) { if (item->ibuf) { + BLI_mutex_lock(&limitor_lock); MEM_CacheLimiter_touch(item->c_handle); + BLI_mutex_unlock(&limitor_lock); + IMB_refImBuf(item->ibuf); return item->ibuf; From 2dcaa8f863216426e3ad51a0a6821b569f85cab7 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 22 Aug 2012 16:16:38 +0000 Subject: [PATCH 081/160] Sequencer: fix sequence color space applying twice when rendering meta strips --- source/blender/imbuf/intern/colormanagement.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 46f6509526d..1480fe2738c 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1086,7 +1086,7 @@ void IMB_colormanagement_imbuf_to_sequencer_space(ImBuf *ibuf, int make_float) (void) make_float; if (!ibuf->rect_float) { - if (make_float) { + if (make_float && ibuf->rect) { /* when converting byte buffer to float in sequencer we need to make float * buffer be in sequencer's working space, which is currently only doable * from linear space. @@ -1112,6 +1112,8 @@ void IMB_colormanagement_imbuf_to_sequencer_space(ImBuf *ibuf, int make_float) #ifdef WITH_OCIO if (global_role_sequencer[0]) { IMB_colormanagement_imbuf_to_role(ibuf, COLOR_ROLE_SEQUENCER); + + ibuf->profile = IB_PROFILE_SRGB; } else #endif @@ -1128,7 +1130,10 @@ void IMB_colormanagement_imbuf_from_sequencer_space(ImBuf *ibuf) #ifdef WITH_OCIO if (global_role_sequencer[0]) { - IMB_colormanagement_imbuf_from_role(ibuf, COLOR_ROLE_SEQUENCER); + if (ibuf->profile == IB_PROFILE_SRGB) { + IMB_colormanagement_imbuf_from_role(ibuf, COLOR_ROLE_SEQUENCER); + ibuf->profile = IB_PROFILE_LINEAR_RGB; + } } else #endif From 93ca64c12afbb91610dae9f007bc2d1d6f4cf79c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 22 Aug 2012 16:45:09 +0000 Subject: [PATCH 082/160] Sequencer: fix crash caused by incorrect handling of color management on ImBuf duplicate --- source/blender/imbuf/intern/allocimbuf.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index b1606b6aff5..bee4758dd07 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -446,9 +446,10 @@ ImBuf *IMB_dupImBuf(ImBuf *ibuf1) /* for now don't duplicate metadata */ tbuf.metadata = NULL; - *ibuf2 = tbuf; + tbuf.display_buffer_flags = NULL; + tbuf.colormanage_cache = NULL; - IMB_colormanage_cache_free(ibuf2); + *ibuf2 = tbuf; return(ibuf2); } From df3c9eb1f791cccc2b0f13836ecfe7a28c8f6e4c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 22 Aug 2012 16:48:22 +0000 Subject: [PATCH 083/160] Color management: code cleanup --- source/blender/imbuf/IMB_imbuf.h | 5 ----- source/blender/imbuf/IMB_imbuf_types.h | 8 -------- 2 files changed, 13 deletions(-) diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index db19a2a1fd2..f6dc6735567 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -396,11 +396,6 @@ void IMB_buffer_float_clamp(float *buf, int width, int height); typedef void (*imb_tonecurveCb) (float rgbOut[3], const float rgbIn[3]); -void IMB_buffer_float_from_float_tonecurve(float *rect_to, const float *rect_from, - int channels_from, int profile_to, int profile_from, int predivide, - int width, int height, int stride_to, int stride_from, - imb_tonecurveCb tonecurve_func); - void IMB_buffer_byte_from_float_tonecurve(unsigned char *rect_to, const float *rect_from, int channels_from, float dither, int profile_to, int profile_from, int predivide, int width, int height, int stride_to, int stride_from, diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index d6d500976d1..72ddd67258a 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -128,7 +128,6 @@ typedef struct ImBuf { unsigned int encodedbuffersize; /* Size of encodedbuffer */ /* color management */ - unsigned int colormanagement_flags; /* flags filed used by color management rutines */ unsigned int *display_buffer_flags; /* array of per-display display buffers dirty flags */ struct ColormanageCache *colormanage_cache; /* cache used by color management */ @@ -259,11 +258,4 @@ extern const char *imb_ext_image_qt[]; extern const char *imb_ext_movie[]; extern const char *imb_ext_audio[]; -/* imbuf->colormanagement_flags */ - -/* special flag for image buffers used in sequencer, which stores all - * images in display space, even float buffers - */ -#define IMB_COLORMANAGEMENT_NONLINEAR_FLOAT (1 << 0) - #endif From 2ddb37b98b567291fe6083a1c75b4d54a84a1220 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 23 Aug 2012 06:40:19 +0000 Subject: [PATCH 084/160] nothread was committed to tomato by accident --- source/blender/compositor/COM_defines.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/compositor/COM_defines.h b/source/blender/compositor/COM_defines.h index 9d9033962db..3cc161a5877 100644 --- a/source/blender/compositor/COM_defines.h +++ b/source/blender/compositor/COM_defines.h @@ -84,7 +84,7 @@ typedef enum CompositorPriority { /** * COM_CURRENT_THREADING_MODEL can be one of the above, COM_TM_QUEUE is currently default. */ -#define COM_CURRENT_THREADING_MODEL COM_TM_NOTHREAD +#define COM_CURRENT_THREADING_MODEL COM_TM_QUEUE // chunk order /** * @brief The order of chunks to be scheduled From c54b1c5172424a3cd8f6bb0f0d501131e82ea0b4 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 24 Aug 2012 11:02:01 +0000 Subject: [PATCH 085/160] Color management: fix regression with updating image while painting It'll update image properly but it seems it behaves slower then in trunk, would investigate further. --- source/blender/imbuf/intern/colormanagement.c | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 1480fe2738c..39b2964ee8c 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1164,9 +1164,12 @@ 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_RECT_INVALID))) { IMB_rect_from_float(ibuf); + ibuf->userflags &= ~IB_RECT_INVALID; + } + BLI_unlock_thread(LOCK_COLORMANAGE); } @@ -1232,6 +1235,22 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet ColormanageCacheViewSettings cache_view_settings; ColormanageCacheDisplaySettings cache_display_settings; + if (ibuf->userflags & IB_RECT_INVALID) { + /* if byte buffer is marked as invalid, it means that float buffer was modified + * and display buffer should be updated + * mark all existing color managed display buffers as invalid, also free + * legacy byte buffer to be sure all users would re-calculate display buffers + * after removing RECT_INVALID flag + */ + + IMB_display_buffer_invalidate(ibuf); + + if (ibuf->rect) + imb_freerectImBuf(ibuf); + + ibuf->userflags &= ~IB_RECT_INVALID; + } + colormanage_view_settings_to_cache(&cache_view_settings, view_settings); colormanage_display_settings_to_cache(&cache_display_settings, display_settings); From e3abd8553fa33c91fa54ef38f9ceb2acd8e17d88 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 24 Aug 2012 12:17:07 +0000 Subject: [PATCH 086/160] Color management: use partial buffer update when painting image Makes it much more responsible, especially when small brushes are used. Could make sense look into using full multithreaded buffer update when brush is large enough. --- .../editors/sculpt_paint/paint_image.c | 9 ++- source/blender/imbuf/intern/colormanagement.c | 65 ++++++++++++------- 2 files changed, 50 insertions(+), 24 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index d916ee299b6..66b78f238b4 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -104,6 +104,8 @@ #include "GPU_draw.h" #include "GPU_extensions.h" +#include "IMB_colormanagement.h" + #include "paint_intern.h" /* Defines and Structs */ @@ -4220,8 +4222,11 @@ static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint) { - if (ibuf->rect_float) - ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */ + if (ibuf->rect_float) { + IMB_partial_display_buffer_update(ibuf, ibuf->rect_float, ibuf->x, 0, 0, + imapaintpartial.x1, imapaintpartial.y1, + imapaintpartial.x2, imapaintpartial.y2); + } if (ibuf->mipmap[0]) ibuf->userflags |= IB_MIPMAP_INVALID; diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 39b2964ee8c..4ecc64708bf 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -64,6 +64,11 @@ #ifdef WITH_OCIO # include +#else +/* so function can accept processor and care about disabled OCIO inside */ +typedef struct ConstProcessorRcPtr { + int pad; +} ConstProcessorRcPtr; #endif /*********************** Global declarations *************************/ @@ -1853,55 +1858,73 @@ void IMB_colormanagement_colorspace_items_add(EnumPropertyItem **items, int *tot * ImBuf at the time function is being called. */ -#ifdef WITH_OCIO static void partial_buffer_update_rect(unsigned char *display_buffer, const float *linear_buffer, int display_stride, int linear_stride, int linear_offset_x, int linear_offset_y, - int channels, int dither, int predivide, + int channels, int dither, int predivide, int profile_from, ConstProcessorRcPtr *processor, imb_tonecurveCb tonecurve_func, int xmin, int ymin, int xmax, int ymax) { int x, y; + (void) processor; /* silent down compiler when building without OCIO */ + + if (profile_from == IB_PROFILE_NONE) + profile_from = IB_PROFILE_SRGB; + for (y = ymin; y < ymax; y++) { for (x = xmin; x < xmax; x++) { int display_index = (y * display_stride + x) * channels; int linear_index = ((y - linear_offset_y) * linear_stride + (x - linear_offset_x)) * channels; - float pixel[4]; +#ifdef WITH_OCIO if (processor) { + float pixel[4]; + copy_v4_v4(pixel, (float *) linear_buffer + linear_index); OCIO_processorApplyRGBA(processor, pixel); rgba_float_to_uchar(display_buffer + display_index, pixel); } - else { + else +#endif + if (tonecurve_func) { IMB_buffer_byte_from_float_tonecurve(display_buffer + display_index, linear_buffer + linear_index, channels, dither, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide, 1, 1, 1, 1, tonecurve_func); } + else { + IMB_buffer_byte_from_float(display_buffer + display_index, linear_buffer + linear_index, channels, + dither, IB_PROFILE_SRGB, profile_from, predivide, 1, 1, 1, 1); + } } } } -#endif -void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, - int stride, int offset_x, int offset_y, +void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, int stride, int offset_x, int offset_y, int xmin, int ymin, int xmax, int ymax) { + int channels = ibuf->channels; + int predivide = ibuf->flags & IB_cm_predivide; + int dither = ibuf->dither; + int profile_from = ibuf->profile; + #ifdef WITH_OCIO int display; int *display_buffer_flags; - int channels = ibuf->channels; - int predivide = ibuf->flags & IB_cm_predivide; - int dither = ibuf->dither; - BLI_lock_thread(LOCK_COLORMANAGE); if (!ibuf->display_buffer_flags) { /* there's no cached display buffers, so no need to iterate though bit fields */ + + if (ibuf->rect && ibuf->rect_float) { + /* update byte buffer created by legacy color management */ + partial_buffer_update_rect((unsigned char *) ibuf->rect, linear_buffer, ibuf->x, stride, offset_x, offset_y, + channels, dither, predivide, profile_from, NULL, NULL, xmin, ymin, xmax, ymax); + } + BLI_unlock_thread(LOCK_COLORMANAGE); return; @@ -1961,7 +1984,7 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, } partial_buffer_update_rect(display_buffer, linear_buffer, buffer_width, stride, - offset_x, offset_y, channels, dither, predivide, + offset_x, offset_y, channels, dither, predivide, profile_from, processor, tonecurve_func, xmin, ymin, xmax, ymax); if (processor) @@ -1977,15 +2000,13 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, } MEM_freeN(display_buffer_flags); -#else - (void) ibuf; - (void) linear_buffer; - (void) xmin; - (void) ymin; - (void) xmax; - (void) ymax; - (void) stride; - (void) offset_x; - (void) offset_y; #endif + + BLI_lock_thread(LOCK_COLORMANAGE); + if (ibuf->rect && ibuf->rect_float) { + /* update byte buffer created by legacy color management */ + partial_buffer_update_rect((unsigned char *) ibuf->rect, linear_buffer, ibuf->x, stride, offset_x, offset_y, + channels, dither, predivide, profile_from, NULL, NULL, xmin, ymin, xmax, ymax); + } + BLI_unlock_thread(LOCK_COLORMANAGE); } From 049df11a70c612dfc175d180b6cbe9d62b3438b3 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 24 Aug 2012 13:12:18 +0000 Subject: [PATCH 087/160] Color management: fix for clone brush It was using ibuf->rect for drawing alpha over, now it's using actual display buffer. --- .../blender/editors/space_image/image_draw.c | 25 ++++++++++++++----- source/blender/imbuf/intern/colormanagement.c | 2 +- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 3b18c9a4a2d..5d6ecd6effe 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -651,22 +651,35 @@ static void draw_image_view_tool(Scene *scene) } #endif -static unsigned char *get_alpha_clone_image(Scene *scene, int *width, int *height) +static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int *width, int *height) { Brush *brush = paint_brush(&scene->toolsettings->imapaint.paint); ImBuf *ibuf; unsigned int size, alpha; + unsigned char *display_buffer; unsigned char *rect, *cp; + void *cache_handle; if (!brush || !brush->clone.image) return NULL; ibuf = BKE_image_get_ibuf(brush->clone.image, NULL); - if (!ibuf || !ibuf->rect) + if (!ibuf) return NULL; - rect = MEM_dupallocN(ibuf->rect); + display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); + + if (!display_buffer) { + IMB_display_buffer_release(cache_handle); + + return NULL; + } + + rect = MEM_dupallocN(display_buffer); + + IMB_display_buffer_release(cache_handle); + if (!rect) return NULL; @@ -685,7 +698,7 @@ static unsigned char *get_alpha_clone_image(Scene *scene, int *width, int *heigh return rect; } -static void draw_image_paint_helpers(ARegion *ar, Scene *scene, float zoomx, float zoomy) +static void draw_image_paint_helpers(const bContext *C, ARegion *ar, Scene *scene, float zoomx, float zoomy) { Brush *brush; int x, y, w, h; @@ -696,7 +709,7 @@ static void draw_image_paint_helpers(ARegion *ar, Scene *scene, float zoomx, flo if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE)) { /* this is not very efficient, but glDrawPixels doesn't allow * drawing with alpha */ - clonerect = get_alpha_clone_image(scene, &w, &h); + clonerect = get_alpha_clone_image(C, scene, &w, &h); if (clonerect) { UI_view2d_to_region_no_clip(&ar->v2d, brush->clone.offset[0], brush->clone.offset[1], &x, &y); @@ -777,7 +790,7 @@ void draw_image_main(const bContext *C, ARegion *ar) /* paint helpers */ if (sima->mode == SI_MODE_PAINT) - draw_image_paint_helpers(ar, scene, zoomx, zoomy); + draw_image_paint_helpers(C, ar, scene, zoomx, zoomy); /* XXX integrate this code */ diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 4ecc64708bf..deffe9f49f1 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1950,7 +1950,7 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, if (view_flags % 2 == 1) { ColormanageCacheViewSettings view_settings = {0}; unsigned char *display_buffer; - void *cache_handle; + void *cache_handle = NULL; int view_index = view + 1; /* views in configuration are 1-based */ float exposure, gamma; int buffer_width; From 56d71219da46ff2cfc214cee4d3aec9626daa87d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 24 Aug 2012 13:17:57 +0000 Subject: [PATCH 088/160] Merging r50179 from trunk into soc-2011-tomato --- source/blender/compositor/nodes/COM_BlurNode.cpp | 6 +++++- .../blender/compositor/operations/COM_BlurBaseOperation.cpp | 5 +++++ .../operations/COM_GaussianAlphaXBlurOperation.cpp | 1 + .../operations/COM_GaussianAlphaYBlurOperation.cpp | 1 + 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/source/blender/compositor/nodes/COM_BlurNode.cpp b/source/blender/compositor/nodes/COM_BlurNode.cpp index 93ef002c8d7..e39ef2b3f23 100644 --- a/source/blender/compositor/nodes/COM_BlurNode.cpp +++ b/source/blender/compositor/nodes/COM_BlurNode.cpp @@ -74,14 +74,18 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co operationx->setbNode(editorNode); operationx->setQuality(quality); operationx->setSize(1.0f); + operationx->setFalloff(PROP_SMOOTH); + operationx->setSubtract(false); addLink(graph, clamp->getOutputSocket(), operationx->getInputSocket(0)); graph->addOperation(operationx); - GaussianYBlurOperation *operationy = new GaussianYBlurOperation(); + GaussianAlphaYBlurOperation *operationy = new GaussianAlphaYBlurOperation(); operationy->setData(data); operationy->setbNode(editorNode); operationy->setQuality(quality); operationy->setSize(1.0f); + operationy->setFalloff(PROP_SMOOTH); + operationy->setSubtract(false); addLink(graph, operationx->getOutputSocket(), operationy->getInputSocket(0)); graph->addOperation(operationy); diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp index c527807f839..39a0014ac41 100644 --- a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp @@ -121,6 +121,11 @@ float *BlurBaseOperation::make_dist_fac_inverse(int rad, int falloff) val = val * val; break; case PROP_LIN: +#ifndef NDEBUG + /* uninitialized! */ + case -1: + BLI_assert(0); +#endif default: /* nothing */ break; diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp index 82f38556e82..8c5e5faf12a 100644 --- a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp @@ -33,6 +33,7 @@ GaussianAlphaXBlurOperation::GaussianAlphaXBlurOperation() : BlurBaseOperation(C { this->m_gausstab = NULL; this->m_rad = 0; + this->m_falloff = -1; /* intentionally invalid, so we can detect uninitialized values */ } void *GaussianAlphaXBlurOperation::initializeTileData(rcti *rect) diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp index bfd9564817e..197715595ed 100644 --- a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp @@ -33,6 +33,7 @@ GaussianAlphaYBlurOperation::GaussianAlphaYBlurOperation() : BlurBaseOperation(C { this->m_gausstab = NULL; this->m_rad = 0; + this->m_falloff = -1; /* intentionally invalid, so we can detect uninitialized values */ } void *GaussianAlphaYBlurOperation::initializeTileData(rcti *rect) From 54c64cb443bd1ce452b3d9a5738a7aca8dc952a1 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 24 Aug 2012 14:01:01 +0000 Subject: [PATCH 089/160] Color management: initialize input color space on movie clip load --- source/blender/blenkernel/intern/movieclip.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index c56bb761579..50628ac857a 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -66,6 +66,7 @@ #include "BKE_animsys.h" #include "BKE_constraint.h" +#include "BKE_colortools.h" #include "BKE_library.h" #include "BKE_global.h" #include "BKE_main.h" @@ -480,6 +481,7 @@ static MovieClip *movieclip_alloc(const char *name) clip->aspx = clip->aspy = 1.0f; BKE_tracking_settings_init(&clip->tracking); + BKE_color_managed_colorspace_settings_init(&clip->colorspace_settings); clip->proxy.build_size_flag = IMB_PROXY_25; clip->proxy.build_tc_flag = IMB_TC_RECORD_RUN | From 614a82cb8cb11533b7f4161ac323d4374986e9cc Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Sat, 25 Aug 2012 16:52:55 +0000 Subject: [PATCH 090/160] Tomato Cycles: * Added a Brick Texture Node to Cycles. * Based on the Blender Internal Brick Texture with some modifications. * Tested on CPU and GPU (CUDA & OpenCL) Documentation: http://wiki.blender.org/index.php/User:DingTo/CyclesBrickTexture ToDo: Only works correct on flat surfaces, like a Plane. If you attach the shader to 3D objects like a cube, the mapping is not correct on the Y/Z vector. Thanks to Lukas Toenne for fixing a issue I had with the Node code! :) --- intern/cycles/app/cycles_xml.cpp | 3 + intern/cycles/blender/blender_shader.cpp | 11 ++ intern/cycles/kernel/CMakeLists.txt | 1 + intern/cycles/kernel/svm/svm.h | 4 + intern/cycles/kernel/svm/svm_brick.h | 114 ++++++++++++++++++ intern/cycles/kernel/svm/svm_types.h | 3 +- intern/cycles/render/nodes.cpp | 92 ++++++++++++++ intern/cycles/render/nodes.h | 8 ++ source/blender/blenkernel/BKE_node.h | 1 + source/blender/blenkernel/intern/node.c | 1 + source/blender/editors/space_node/drawnode.c | 16 +++ source/blender/makesdna/DNA_node_types.h | 6 + source/blender/makesrna/intern/rna_nodetree.c | 37 ++++++ .../makesrna/intern/rna_nodetree_types.h | 1 + source/blender/nodes/CMakeLists.txt | 1 + source/blender/nodes/NOD_shader.h | 1 + .../shader/nodes/node_shader_tex_brick.c | 90 ++++++++++++++ 17 files changed, 389 insertions(+), 1 deletion(-) create mode 100644 intern/cycles/kernel/svm/svm_brick.h create mode 100644 source/blender/nodes/shader/nodes/node_shader_tex_brick.c diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 5ec5cb929d6..922a96dc4df 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -379,6 +379,9 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug else if(string_iequals(node.name(), "checker_texture")) { snode = new CheckerTextureNode(); } + else if(string_iequals(node.name(), "brick_texture")) { + snode = new BrickTextureNode(); + } else if(string_iequals(node.name(), "gradient_texture")) { GradientTextureNode *blend = new GradientTextureNode(); xml_read_enum(&blend->type, GradientTextureNode::type_enum, node, "type"); diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 7b1b4d5c6ba..2309cc6eb40 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -461,6 +461,17 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph node = checker; break; } + case BL::ShaderNode::type_TEX_BRICK: { + BL::ShaderNodeTexBrick b_brick_node(b_node); + BrickTextureNode *brick = new BrickTextureNode(); + brick->offset = b_brick_node.offset(); + brick->offset_frequency = b_brick_node.offset_frequency(); + brick->squash = b_brick_node.squash(); + brick->squash_frequency = b_brick_node.squash_frequency(); + get_tex_mapping(&brick->tex_mapping, b_brick_node.texture_mapping()); + node = brick; + break; + } case BL::ShaderNode::type_TEX_NOISE: { BL::ShaderNodeTexNoise b_noise_node(b_node); NoiseTextureNode *noise = new NoiseTextureNode(); diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 98cb16d5dfc..c26954e23b6 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -61,6 +61,7 @@ set(SRC_SVM_HEADERS svm/svm_closure.h svm/svm_convert.h svm/svm_checker.h + svm/svm_brick.h svm/svm_displace.h svm/svm_fresnel.h svm/svm_gamma.h diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 56a40620765..5b0f192ea47 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -154,6 +154,7 @@ CCL_NAMESPACE_END #include "svm_value.h" #include "svm_voronoi.h" #include "svm_checker.h" +#include "svm_brick.h" CCL_NAMESPACE_BEGIN @@ -252,6 +253,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT case NODE_TEX_CHECKER: svm_node_tex_checker(kg, sd, stack, node, &offset); break; + case NODE_TEX_BRICK: + svm_node_tex_brick(kg, sd, stack, node, &offset); + break; #endif case NODE_CAMERA: svm_node_camera(kg, sd, stack, node.y, node.z, node.w); diff --git a/intern/cycles/kernel/svm/svm_brick.h b/intern/cycles/kernel/svm/svm_brick.h new file mode 100644 index 00000000000..50de19b825d --- /dev/null +++ b/intern/cycles/kernel/svm/svm_brick.h @@ -0,0 +1,114 @@ +/* + * Copyright 2012, 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 + +/* Brick */ + +__device_noinline float brick_noise(int n) /* fast integer noise */ +{ + int nn; + n = (n >> 13) ^ n; + nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; + return 0.5f * ((float)nn / 1073741824.0f); +} + +__device_noinline float svm_brick(float3 p, float scale, float mortar_size, float bias, + float brick_width, float row_height, float offset_amount, int offset_frequency, + float squash_amount, int squash_frequency, float *tint) +{ + p *= scale; + + int bricknum, rownum; + float offset = 0.0f; + float x, y; + + rownum = (int)floor(p.y / row_height); + + if(offset_frequency && squash_frequency) { + brick_width *= ((int)(rownum) % squash_frequency ) ? 1.0f : squash_amount; /* squash */ + offset = ((int)(rownum) % offset_frequency ) ? 0 : (brick_width*offset_amount); /* offset */ + } + + bricknum = (int)floor((p.x+offset) / brick_width); + + x = (p.x+offset) - brick_width*bricknum; + y = p.y - row_height*rownum; + + *tint = clamp((brick_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0f, 1.0f); + + return (x < mortar_size || y < mortar_size || + x > (brick_width - mortar_size) || + y > (row_height - mortar_size)) ? 1.0f : 0.0f; +} + +__device void svm_node_tex_brick(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset) +{ + uint4 node2 = read_node(kg, offset); + uint4 node3 = read_node(kg, offset); + + /* Input and Output Sockets */ + uint co_offset, color1_offset, color2_offset, mortar_offset, scale_offset; + uint mortar_size_offset, bias_offset, brick_width_offset, row_height_offset; + uint color_offset, fac_offset; + + /* RNA properties */ + uint offset_frequency, squash_frequency; + + float tint = 0; + + decode_node_uchar4(node.y, &co_offset, &color1_offset, &color2_offset, &mortar_offset); + decode_node_uchar4(node.z, &scale_offset, &mortar_size_offset, &bias_offset, &brick_width_offset); + decode_node_uchar4(node.w, &row_height_offset, &color_offset, &fac_offset, NULL); + + decode_node_uchar4(node2.x, &offset_frequency, &squash_frequency, NULL, NULL); + + float3 co = stack_load_float3(stack, co_offset); + + float3 color1 = stack_load_float3(stack, color1_offset); + float3 color2 = stack_load_float3(stack, color2_offset); + float3 mortar = stack_load_float3(stack, mortar_offset); + + float scale = stack_load_float_default(stack, scale_offset, node2.y); + float mortar_size = stack_load_float_default(stack, mortar_size_offset, node2.z); + float bias = stack_load_float_default(stack, bias_offset, node2.w); + float brick_width = stack_load_float_default(stack, brick_width_offset, node3.x); + float row_height = stack_load_float_default(stack, row_height_offset, node3.y); + float offset_amount = __int_as_float(node3.z); + float squash_amount = __int_as_float(node3.w); + + float f = svm_brick(co, scale, mortar_size, bias, brick_width, row_height, + offset_amount, offset_frequency, squash_amount, squash_frequency, + &tint); + + if(f != 1.0f) { + float facm = 1.0f - tint; + + color1.x = facm * (color1.x) + tint * color2.x; + color1.y = facm * (color1.y) + tint * color2.y; + color1.z = facm * (color1.z) + tint * color2.z; + } + + if(stack_valid(color_offset)) + stack_store_float3(stack, color_offset, (f == 1.0f)? mortar: color1); + if(stack_valid(fac_offset)) + stack_store_float(stack, fac_offset, f); +} + +CCL_NAMESPACE_END + diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 65e6c050b83..a577f8b12f7 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -90,7 +90,8 @@ typedef enum NodeType { NODE_MIN_MAX, NODE_LIGHT_FALLOFF, NODE_OBJECT_INFO, - NODE_PARTICLE_INFO + NODE_PARTICLE_INFO, + NODE_TEX_BRICK } NodeType; typedef enum NodeAttributeType { diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 43d6e2c7aac..b8678005438 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -898,6 +898,98 @@ void CheckerTextureNode::compile(OSLCompiler& compiler) compiler.add(this, "node_checker_texture"); } +/* Brick Texture */ + +BrickTextureNode::BrickTextureNode() +: TextureNode("brick_texture") +{ + offset = 0.5f; + offset_frequency = 2; + squash = 1.0f; + squash_frequency = 2; + + add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_GENERATED); + add_input("Color1", SHADER_SOCKET_COLOR); + add_input("Color2", SHADER_SOCKET_COLOR); + add_input("Mortar", SHADER_SOCKET_COLOR); + add_input("Scale", SHADER_SOCKET_FLOAT, 5.0f); + add_input("Mortar Size", SHADER_SOCKET_FLOAT, 0.02f); + add_input("Bias", SHADER_SOCKET_FLOAT, 0.0f); + add_input("Brick Width", SHADER_SOCKET_FLOAT, 0.5f); + add_input("Row Height", SHADER_SOCKET_FLOAT, 0.25f); + + add_output("Color", SHADER_SOCKET_COLOR); + add_output("Fac", SHADER_SOCKET_FLOAT); +} + +void BrickTextureNode::compile(SVMCompiler& compiler) +{ + ShaderInput *vector_in = input("Vector"); + ShaderInput *color1_in = input("Color1"); + ShaderInput *color2_in = input("Color2"); + ShaderInput *mortar_in = input("Mortar"); + ShaderInput *scale_in = input("Scale"); + ShaderInput *mortar_size_in = input("Mortar Size"); + ShaderInput *bias_in = input("Bias"); + ShaderInput *brick_width_in = input("Brick Width"); + ShaderInput *row_height_in = input("Row Height"); + + ShaderOutput *color_out = output("Color"); + ShaderOutput *fac_out = output("Fac"); + + compiler.stack_assign(vector_in); + compiler.stack_assign(color1_in); + compiler.stack_assign(color2_in); + compiler.stack_assign(mortar_in); + if(scale_in->link) compiler.stack_assign(scale_in); + if(mortar_size_in->link) compiler.stack_assign(mortar_size_in); + if(bias_in->link) compiler.stack_assign(bias_in); + if(brick_width_in->link) compiler.stack_assign(brick_width_in); + if(row_height_in->link) compiler.stack_assign(row_height_in); + + int vector_offset = vector_in->stack_offset; + + if(!tex_mapping.skip()) { + vector_offset = compiler.stack_find_offset(SHADER_SOCKET_VECTOR); + tex_mapping.compile(compiler, vector_in->stack_offset, vector_offset); + } + + if(!color_out->links.empty()) + compiler.stack_assign(color_out); + if(!fac_out->links.empty()) + compiler.stack_assign(fac_out); + + compiler.add_node(NODE_TEX_BRICK, + compiler.encode_uchar4(vector_offset, + color1_in->stack_offset, color2_in->stack_offset, mortar_in->stack_offset), + compiler.encode_uchar4(scale_in->stack_offset, + mortar_size_in->stack_offset, bias_in->stack_offset, brick_width_in->stack_offset), + compiler.encode_uchar4(row_height_in->stack_offset, + color_out->stack_offset, fac_out->stack_offset)); + + compiler.add_node(compiler.encode_uchar4(offset_frequency, squash_frequency), + __float_as_int(scale_in->value.x), + __float_as_int(mortar_size_in->value.x), + __float_as_int(bias_in->value.x)); + + compiler.add_node(__float_as_int(brick_width_in->value.x), + __float_as_int(row_height_in->value.x), + __float_as_int(offset), + __float_as_int(squash)); + + if(vector_offset != vector_in->stack_offset) + compiler.stack_clear_offset(vector_in->type, vector_offset); +} + +void BrickTextureNode::compile(OSLCompiler& compiler) +{ + compiler.parameter("Offset", offset); + compiler.parameter("Offset Frequency", offset_frequency); + compiler.parameter("Squash", squash); + compiler.parameter("Squash Frequency", squash_frequency); + compiler.add(this, "node_brick_texture"); +} + /* Normal */ NormalNode::NormalNode() diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index ed283492d7b..da5b90bfdda 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -158,6 +158,14 @@ public: SHADER_NODE_CLASS(CheckerTextureNode) }; +class BrickTextureNode : public TextureNode { +public: + SHADER_NODE_CLASS(BrickTextureNode) + + float offset, squash; + int offset_frequency, squash_frequency; +}; + class MappingNode : public ShaderNode { public: SHADER_NODE_CLASS(MappingNode) diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index c8b69898daa..438d5110666 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -546,6 +546,7 @@ struct ShadeResult; #define SH_NODE_LIGHT_FALLOFF 166 #define SH_NODE_OBJECT_INFO 167 #define SH_NODE_PARTICLE_INFO 168 +#define SH_NODE_TEX_BRICK 169 /* custom defines options for Material node */ #define SH_NODE_MAT_DIFF 1 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index bf5fc6449f8..3b860cfaa10 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2265,6 +2265,7 @@ static void registerShaderNodes(bNodeTreeType *ttype) register_node_type_sh_tex_gradient(ttype); register_node_type_sh_tex_magic(ttype); register_node_type_sh_tex_checker(ttype); + register_node_type_sh_tex_brick(ttype); } static void registerTextureNodes(bNodeTreeType *ttype) diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index b8de995b742..1981d085583 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1364,6 +1364,19 @@ static void node_shader_buts_tex_magic(uiLayout *layout, bContext *UNUSED(C), Po uiItemR(layout, ptr, "turbulence_depth", 0, NULL, ICON_NONE); } +static void node_shader_buts_tex_brick(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiLayout *col; + + col = uiLayoutColumn(layout, TRUE); + uiItemR(col, ptr, "offset", 0, IFACE_("Offset"), ICON_NONE); + uiItemR(col, ptr, "offset_frequency", 0, IFACE_("Frequency"), ICON_NONE); + + col = uiLayoutColumn(layout, TRUE); + uiItemR(col, ptr, "squash", 0, IFACE_("Squash"), ICON_NONE); + uiItemR(col, ptr, "squash_frequency", 0, IFACE_("Frequency"), ICON_NONE); +} + static void node_shader_buts_tex_wave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiItemR(layout, ptr, "wave_type", 0, "", ICON_NONE); @@ -1448,6 +1461,9 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_TEX_MAGIC: ntype->uifunc = node_shader_buts_tex_magic; break; + case SH_NODE_TEX_BRICK: + ntype->uifunc = node_shader_buts_tex_brick; + break; case SH_NODE_TEX_WAVE: ntype->uifunc = node_shader_buts_tex_wave; break; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 541593aa810..3f1f4933585 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -624,6 +624,12 @@ typedef struct NodeTexChecker { NodeTexBase base; } NodeTexChecker; +typedef struct NodeTexBrick { + NodeTexBase base; + int offset_freq, squash_freq; + float offset, squash; +} NodeTexBrick; + typedef struct NodeTexEnvironment { NodeTexBase base; ImageUser iuser; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 1fa1e395b95..b66a5e4567a 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -1598,6 +1598,43 @@ static void def_sh_tex_checker(StructRNA *srna) def_sh_tex(srna); } +static void def_sh_tex_brick(StructRNA *srna) +{ + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeTexBrick", "storage"); + def_sh_tex(srna); + + prop = RNA_def_property(srna, "offset_frequency", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "offset_freq"); + RNA_def_property_int_default(prop, 2); + RNA_def_property_range(prop, 1, 99); + RNA_def_property_ui_text(prop, "Offset Frequency", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); + + prop = RNA_def_property(srna, "squash_frequency", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "squash_freq"); + RNA_def_property_int_default(prop, 2); + RNA_def_property_range(prop, 1, 99); + RNA_def_property_ui_text(prop, "Squash Frequency", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); + + prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "offset"); + RNA_def_property_float_default(prop, 0.5f); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Offset Amount", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); + + prop = RNA_def_property(srna, "squash", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "squash"); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_range(prop, 0.0f, 99.0f); + RNA_def_property_ui_text(prop, "Squash Amount", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); + +} + static void def_sh_tex_magic(StructRNA *srna) { PropertyRNA *prop; diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index 15ad1c557a5..0baa4cc0838 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -91,6 +91,7 @@ DefNode( ShaderNode, SH_NODE_TEX_WAVE, def_sh_tex_wave, "TE DefNode( ShaderNode, SH_NODE_TEX_MUSGRAVE, def_sh_tex_musgrave, "TEX_MUSGRAVE", TexMusgrave, "Musgrave Texture", "" ) DefNode( ShaderNode, SH_NODE_TEX_VORONOI, def_sh_tex_voronoi, "TEX_VORONOI", TexVoronoi, "Voronoi Texture", "" ) DefNode( ShaderNode, SH_NODE_TEX_CHECKER, def_sh_tex_checker, "TEX_CHECKER", TexChecker, "Checker Texture", "" ) +DefNode( ShaderNode, SH_NODE_TEX_BRICK, def_sh_tex_brick, "TEX_BRICK", TexBrick, "Brick Texture", "" ) DefNode( ShaderNode, SH_NODE_TEX_COORD, 0, "TEX_COORD", TexCoord, "Texture Coordinate","" ) DefNode( CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" ) diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index e1adb419a8a..08e0e7b0f93 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -180,6 +180,7 @@ set(SRC shader/nodes/node_shader_tex_voronoi.c shader/nodes/node_shader_tex_wave.c shader/nodes/node_shader_tex_checker.c + shader/nodes/node_shader_tex_brick.c shader/node_shader_tree.c shader/node_shader_util.c diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 6b000181953..360b343daa9 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -108,6 +108,7 @@ void register_node_type_sh_tex_wave(struct bNodeTreeType *ttype); void register_node_type_sh_tex_musgrave(struct bNodeTreeType *ttype); void register_node_type_sh_tex_noise(struct bNodeTreeType *ttype); void register_node_type_sh_tex_checker(struct bNodeTreeType *ttype); +void register_node_type_sh_tex_brick(struct bNodeTreeType *ttype); #endif diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c new file mode 100644 index 00000000000..11f7fb94ae0 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c @@ -0,0 +1,90 @@ +/* + * ***** 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_tex_brick_in[]= { + { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, + { SOCK_RGBA, 1, N_("Color1"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 1, N_("Color2"), 0.2f, 0.2f, 0.2f, 1.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 1, N_("Mortar"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, + { SOCK_FLOAT, 1, N_("Mortar Size"), 0.02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.125f}, + { SOCK_FLOAT, 1, N_("Bias"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Brick Width"), 0.5f, 0.0f, 0.0f, 0.0f, 0.01f, 100.0f}, + { SOCK_FLOAT, 1, N_("Row Height"), 0.25f, 0.0f, 0.0f, 0.0f, 0.01f, 100.0f}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_tex_brick_out[]= { + { SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp)) +{ + NodeTexBrick *tex = MEM_callocN(sizeof(NodeTexBrick), "NodeTexBrick"); + default_tex_mapping(&tex->base.tex_mapping); + default_color_mapping(&tex->base.color_mapping); + + tex->offset = 0.5f; + tex->squash = 1.0f; + tex->offset_freq = 2; + tex->squash_freq = 2; + + node->storage = tex; +} + +static int node_shader_gpu_tex_brick(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + if (!in[0].link) + in[0].link = GPU_attribute(CD_ORCO, ""); + + node_shader_gpu_tex_mapping(mat, node, in, out); + + return GPU_stack_link(mat, "node_tex_brick", in, out); +} + +/* node type definition */ +void register_node_type_sh_tex_brick(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, SH_NODE_TEX_BRICK, "Brick Texture", NODE_CLASS_TEXTURE, NODE_OPTIONS); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, sh_node_tex_brick_in, sh_node_tex_brick_out); + node_type_size(&ntype, 150, 60, 200); + node_type_init(&ntype, node_shader_init_tex_brick); + node_type_storage(&ntype, "NodeTexBrick", node_free_standard_storage, node_copy_standard_storage); + node_type_exec(&ntype, NULL); + node_type_gpu(&ntype, node_shader_gpu_tex_brick); + + nodeRegisterType(ttype, &ntype); +} From 31705361ecad55769b782b33a78024f5b8dd8ac6 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 26 Aug 2012 11:34:33 +0000 Subject: [PATCH 091/160] Color Management: CMake should detect yaml-cpp and tinyxml libraries automatically This makes Blender compilable with CMake and OCIO libraries from SVN. --- .../cmake/Modules/FindOpenColorIO.cmake | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/build_files/cmake/Modules/FindOpenColorIO.cmake b/build_files/cmake/Modules/FindOpenColorIO.cmake index 78539aec82b..0443d7e29f5 100644 --- a/build_files/cmake/Modules/FindOpenColorIO.cmake +++ b/build_files/cmake/Modules/FindOpenColorIO.cmake @@ -27,6 +27,12 @@ IF(NOT OPENCOLORIO_ROOT_DIR AND NOT $ENV{OPENCOLORIO_ROOT_DIR} STREQUAL "") SET(OPENCOLORIO_ROOT_DIR $ENV{OPENCOLORIO_ROOT_DIR}) ENDIF() +SET(_opencolorio_FIND_COMPONENTS + OpenColorIO + yaml-cpp + tinyxml +) + SET(_opencolorio_SEARCH_DIRS ${OPENCOLORIO_ROOT_DIR} /usr/local @@ -44,14 +50,20 @@ FIND_PATH(OPENCOLORIO_INCLUDE_DIR include ) -FIND_LIBRARY(OPENCOLORIO_LIBRARY - NAMES - OCIO OpenColorIO - HINTS - ${_opencolorio_SEARCH_DIRS} - PATH_SUFFIXES - lib64 lib - ) +SET(_opencolorio_LIBRARIES) +FOREACH(COMPONENT ${_opencolorio_FIND_COMPONENTS}) + STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT) + + FIND_LIBRARY(OPENCOLORIO_${UPPERCOMPONENT}_LIBRARY + NAMES + ${COMPONENT} + HINTS + ${_opencolorio_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + LIST(APPEND _opencolorio_LIBRARIES "${OPENCOLORIO_${UPPERCOMPONENT}_LIBRARY}") +ENDFOREACH() # handle the QUIETLY and REQUIRED arguments and set OPENCOLORIO_FOUND to TRUE if # all listed variables are TRUE @@ -60,7 +72,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenColorIO DEFAULT_MSG OPENCOLORIO_LIBRARY OPENCOLORIO_INCLUDE_DIR) IF(OPENCOLORIO_FOUND) - SET(OPENCOLORIO_LIBRARIES ${OPENCOLORIO_LIBRARY}) + SET(OPENCOLORIO_LIBRARIES ${_opencolorio_LIBRARIES}) SET(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO_INCLUDE_DIR}) ENDIF(OPENCOLORIO_FOUND) From 09e340fdf7051dd66f767851d94ee34fbf8877b2 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 26 Aug 2012 13:18:43 +0000 Subject: [PATCH 092/160] Color Management: correction to previous commit --- build_files/cmake/Modules/FindOpenColorIO.cmake | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/build_files/cmake/Modules/FindOpenColorIO.cmake b/build_files/cmake/Modules/FindOpenColorIO.cmake index 0443d7e29f5..79bc0127674 100644 --- a/build_files/cmake/Modules/FindOpenColorIO.cmake +++ b/build_files/cmake/Modules/FindOpenColorIO.cmake @@ -62,14 +62,16 @@ FOREACH(COMPONENT ${_opencolorio_FIND_COMPONENTS}) PATH_SUFFIXES lib64 lib ) - LIST(APPEND _opencolorio_LIBRARIES "${OPENCOLORIO_${UPPERCOMPONENT}_LIBRARY}") + if(OPENCOLORIO_${UPPERCOMPONENT}_LIBRARY) + LIST(APPEND _opencolorio_LIBRARIES "${OPENCOLORIO_${UPPERCOMPONENT}_LIBRARY}") + endif() ENDFOREACH() # handle the QUIETLY and REQUIRED arguments and set OPENCOLORIO_FOUND to TRUE if # all listed variables are TRUE INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenColorIO DEFAULT_MSG - OPENCOLORIO_LIBRARY OPENCOLORIO_INCLUDE_DIR) + _opencolorio_LIBRARIES OPENCOLORIO_INCLUDE_DIR) IF(OPENCOLORIO_FOUND) SET(OPENCOLORIO_LIBRARIES ${_opencolorio_LIBRARIES}) From f31d17220d611368a0e74da91b2981a3221b60b2 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 26 Aug 2012 23:57:55 +0000 Subject: [PATCH 093/160] Sequencer: fix for wrong color space sequencer effects were working in --- source/blender/blenkernel/intern/seqeffects.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 87906337ca2..e1fd5a1639f 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -53,6 +53,7 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "IMB_colormanagement.h" #include "RNA_access.h" @@ -120,13 +121,13 @@ static ImBuf *prepare_effect_imbufs(SeqRenderData context, ImBuf *ibuf1, ImBuf * } if (ibuf1 && !ibuf1->rect_float && out->rect_float) { - IMB_float_from_rect_simple(ibuf1); + IMB_colormanagement_imbuf_to_sequencer_space(ibuf1, TRUE); } if (ibuf2 && !ibuf2->rect_float && out->rect_float) { - IMB_float_from_rect_simple(ibuf2); + IMB_colormanagement_imbuf_to_sequencer_space(ibuf2, TRUE); } if (ibuf3 && !ibuf3->rect_float && out->rect_float) { - IMB_float_from_rect_simple(ibuf3); + IMB_colormanagement_imbuf_to_sequencer_space(ibuf3, TRUE); } if (ibuf1 && !ibuf1->rect && !out->rect_float) { @@ -138,7 +139,9 @@ static ImBuf *prepare_effect_imbufs(SeqRenderData context, ImBuf *ibuf1, ImBuf * if (ibuf3 && !ibuf3->rect && !out->rect_float) { IMB_rect_from_float(ibuf3); } - + + out->profile = IB_PROFILE_SRGB; + return out; } From 6a5d8e355d731b7943bf4bf174f1c106da4c1f1c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 27 Aug 2012 15:23:14 +0000 Subject: [PATCH 094/160] Color management: display color managed RGB values in color sample line Makes it possible to investigate color managed ranges. Not ideal but it's the quickest thing which could be done to remove current grading stoppers for Mango. --- source/blender/editors/include/ED_image.h | 3 ++- source/blender/editors/space_image/image_draw.c | 14 +++++++++++++- source/blender/editors/space_image/image_ops.c | 6 ++++-- source/blender/editors/space_node/node_view.c | 2 +- .../editors/space_sequencer/sequencer_view.c | 2 +- source/blender/imbuf/IMB_colormanagement.h | 3 +++ source/blender/imbuf/intern/colormanagement.c | 17 +++++++++++++++++ 7 files changed, 41 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index 6f41bef81f4..70fea4a45fb 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -39,6 +39,7 @@ struct ToolSettings; struct uiBlock; struct wmWindowManager; struct ARegion; +struct Scene; /* image_edit.c, exported for transform */ struct Image *ED_space_image(struct SpaceImage *sima); @@ -79,7 +80,7 @@ int ED_space_image_maskedit_mask_poll(struct bContext *C); /* UI level image (texture) updating... render calls own stuff (too) */ void ED_image_update_frame(const struct Main *mainp, int cfra); -void ED_image_draw_info(struct ARegion *ar, int color_manage, int channels, int x, int y, +void ED_image_draw_info(struct Scene *scene, struct ARegion *ar, int color_manage, int channels, int x, int y, const unsigned char cp[4], const float fp[4], int *zp, float *zpf); #endif /* __ED_IMAGE_H__ */ diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 5d6ecd6effe..1fd29c0163d 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -124,7 +124,7 @@ static void draw_render_info(Scene *scene, Image *ima, ARegion *ar) } /* used by node view too */ -void ED_image_draw_info(ARegion *ar, int color_manage, int channels, int x, int y, +void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int channels, int x, int y, const unsigned char cp[4], const float fp[4], int *zp, float *zpf) { char str[256]; @@ -221,6 +221,18 @@ void ED_image_draw_info(ARegion *ar, int color_manage, int channels, int x, int BLF_draw_ascii(blf_mono_font, str, sizeof(str)); dx += BLF_width(blf_mono_font, str); } + + /* OCIO_TODO: make it fit better to overall color interaction */ + if (fp && channels == 4) { + float pixel[4]; + + IMB_display_buffer_pixel(pixel, fp, &scene->view_settings, &scene->display_settings); + + BLI_snprintf(str, sizeof(str), " | CM R:%-.4f G:%-.4f B:%-.4f", pixel[0], pixel[1], pixel[2]); + BLF_position(blf_mono_font, dx, 6, 0); + BLF_draw_ascii(blf_mono_font, str, sizeof(str)); + dx += BLF_width(blf_mono_font, str); + } } /* color rectangle */ diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 43fe4594406..0b5216a9893 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1987,12 +1987,14 @@ typedef struct ImageSampleInfo { int draw; } ImageSampleInfo; -static void image_sample_draw(const bContext *UNUSED(C), ARegion *ar, void *arg_info) +static void image_sample_draw(const bContext *C, ARegion *ar, void *arg_info) { ImageSampleInfo *info = arg_info; if (info->draw) { + Scene *scene = CTX_data_scene(C); + /* no color management needed for images (color_manage=0) */ - ED_image_draw_info(ar, 0, info->channels, info->x, info->y, info->colp, info->colfp, info->zp, info->zfp); + ED_image_draw_info(scene, ar, 0, info->channels, info->x, info->y, info->colp, info->colfp, info->zp, info->zfp); } } diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index e89e798a6fa..dfceb832b65 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -341,7 +341,7 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) ImageSampleInfo *info = arg_info; if (info->draw) { - ED_image_draw_info(ar, (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT), info->channels, + ED_image_draw_info(scene, ar, (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT), info->channels, info->x, info->y, info->col, info->colf, NULL, NULL /* zbuf - unused for nodes */ ); diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index fa39003bd55..f83a903c358 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -78,7 +78,7 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) ImageSampleInfo *info = arg_info; if (info->draw) { - ED_image_draw_info(ar, (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT), info->channels, + ED_image_draw_info(scene, ar, (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT), info->channels, info->x, info->y, info->col, info->colf, NULL, NULL); } } diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 41055e135e3..551251565de 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -71,6 +71,9 @@ unsigned char *IMB_display_buffer_acquire(struct ImBuf *ibuf, const struct Color const struct ColorManagedDisplaySettings *display_settings, void **cache_handle); unsigned char *IMB_display_buffer_acquire_ctx(const struct bContext *C, struct ImBuf *ibuf, void **cache_handle); +void IMB_display_buffer_pixel(float result[4], const float pixel[4], const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings); + void IMB_display_buffer_to_imbuf_rect(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index deffe9f49f1..954b7540c72 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1315,6 +1315,23 @@ unsigned char *IMB_display_buffer_acquire_ctx(const bContext *C, ImBuf *ibuf, vo return IMB_display_buffer_acquire(ibuf, view_settings, display_settings, cache_handle); } +void IMB_display_buffer_pixel(float result[4], const float pixel[4], const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) +{ + ConstProcessorRcPtr *processor; + const float gamma = view_settings->gamma; + const float exposure = view_settings->exposure; + const char *view_transform = view_settings->view_transform; + const char *display = display_settings->display_device; + + copy_v4_v4(result, pixel); + + processor = create_display_buffer_processor(view_transform, display, exposure, gamma); + + if (processor) + OCIO_processorApplyRGBA(processor, result); +} + void IMB_display_buffer_to_imbuf_rect(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { From 2e1568d64e86720dd2a4f8d0a98e5feac4631f6e Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 29 Aug 2012 18:08:34 +0000 Subject: [PATCH 095/160] Color management: fix for wrong view being used as default in configuration file check Also marked Jpeg2K as non-float format. --- source/blender/blenkernel/intern/image.c | 1 - source/blender/imbuf/intern/colormanagement.c | 30 +++++++++++-------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index d74a7f6e374..6d0a67f520f 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1024,7 +1024,6 @@ int BKE_imtype_supports_float(const char imtype) case R_IMF_IMTYPE_RADHDR: case R_IMF_IMTYPE_OPENEXR: case R_IMF_IMTYPE_MULTILAYER: - case R_IMF_IMTYPE_JP2: return TRUE; } return 0; diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 954b7540c72..d4ea88c061f 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1404,17 +1404,29 @@ static void colormanage_check_display_settings(ColorManagedDisplaySettings *disp static void colormanage_check_view_settings(ColorManagedViewSettings *view_settings, const char *what, const ColorManagedView *default_view) { + ColorManagedDisplay *display; + ColorManagedView *default_view; + if (view_settings->view_transform[0] == '\0') { - BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform)); + display = colormanage_display_get_named(display_settings->display_device); + default_view = colormanage_view_get_default(display); + + if (default_view) + BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform)); } else { ColorManagedView *view = colormanage_view_get_named(view_settings->view_transform); if (!view) { - printf("Blender color management: %s view \"%s\" not found, setting default \"%s\".\n", - what, view_settings->view_transform, default_view->name); + display = colormanage_display_get_named(display_settings->display_device); + default_view = colormanage_view_get_default(display); - BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform)); + if (default_view) { + printf("Blender color management: %s view \"%s\" not found, setting default \"%s\".\n", + what, view_settings->view_transform, default_view->name); + + BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform)); + } } } @@ -1456,7 +1468,6 @@ void IMB_colormanagement_check_file_config(Main *bmain) MovieClip *clip; ColorManagedDisplay *default_display; - ColorManagedView *default_view; default_display = colormanage_display_get_default(); @@ -1465,16 +1476,9 @@ void IMB_colormanagement_check_file_config(Main *bmain) return; } - default_view = colormanage_view_get_default(default_display); - - if (!default_view) { - /* happens when OCIO configuration is incorrect */ - return; - } - for (scene = bmain->scene.first; scene; scene = scene->id.next) { colormanage_check_display_settings(&scene->display_settings, "scene", default_display); - colormanage_check_view_settings(&scene->view_settings, "scene", default_view); + colormanage_check_view_settings(&scene->display_settings, &scene->view_settings, "scene", default_view); } /* ** check input color space settings ** */ From 63197444b46a48a48ffb805c4ca207245e9bf515 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 29 Aug 2012 18:11:51 +0000 Subject: [PATCH 096/160] Color management: some parts of previous commit were incorrect merged from WIP patch --- source/blender/imbuf/intern/colormanagement.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index d4ea88c061f..41cff9d2c35 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1401,8 +1401,7 @@ static void colormanage_check_display_settings(ColorManagedDisplaySettings *disp } } -static void colormanage_check_view_settings(ColorManagedViewSettings *view_settings, const char *what, - const ColorManagedView *default_view) +static void colormanage_check_view_settings(ColorManagedDisplaySettings *display_settings, ColorManagedViewSettings *view_settings, const char *what) { ColorManagedDisplay *display; ColorManagedView *default_view; @@ -1478,7 +1477,7 @@ void IMB_colormanagement_check_file_config(Main *bmain) for (scene = bmain->scene.first; scene; scene = scene->id.next) { colormanage_check_display_settings(&scene->display_settings, "scene", default_display); - colormanage_check_view_settings(&scene->display_settings, &scene->view_settings, "scene", default_view); + colormanage_check_view_settings(&scene->display_settings, &scene->view_settings, "scene"); } /* ** check input color space settings ** */ From 70301f431c7b53e06ba243b19997c7c56f0a9d3a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 30 Aug 2012 13:40:31 +0000 Subject: [PATCH 097/160] Color management: make it behave closer to trunk Avoid using tricks with ibuf->profile to check whether image buffer is in sequencer or linear space. Assume the whole sequencer works in non linear float space and do transformation to linear where it;s needed only. This removes confusion from the code, fixes wrong behavior of some effects. --- source/blender/blenkernel/intern/seqeffects.c | 2 -- source/blender/blenkernel/intern/sequencer.c | 15 +++------ source/blender/imbuf/IMB_imbuf_types.h | 6 ++++ source/blender/imbuf/intern/colormanagement.c | 31 +++++++++++++------ .../blender/render/intern/source/pipeline.c | 8 +++-- .../render/intern/source/render_result.c | 14 ++------- 6 files changed, 41 insertions(+), 35 deletions(-) diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index e1c3decf24f..0abd3444c54 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -140,8 +140,6 @@ static ImBuf *prepare_effect_imbufs(SeqRenderData context, ImBuf *ibuf1, ImBuf * IMB_rect_from_float(ibuf3); } - out->profile = IB_PROFILE_SRGB; - return out; } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 84da45294a6..dcf72c37f52 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -2461,7 +2461,8 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo imb_freerectImBuf(ibuf); /* all sequencer color is done in SRGB space, linear gives odd crossfades */ - IMB_colormanagement_imbuf_to_sequencer_space(ibuf, FALSE); + if (ibuf->profile == IB_PROFILE_LINEAR_RGB) + IMB_colormanagement_imbuf_to_sequencer_space(ibuf, FALSE); copy_to_ibuf_still(context, seq, nr, ibuf); @@ -2653,18 +2654,13 @@ static ImBuf *seq_render_strip_stack(SeqRenderData context, ListBase *seqbasep, if (count == 1) { out = seq_render_strip(context, seq_arr[0], cfra); - - if (out) { - /* put buffer back to linear space */ - IMB_colormanagement_imbuf_from_sequencer_space(out); - } + out->colormanage_flags |= IMB_COLORMANAGE_NOLINEAR_FLOAT; BKE_sequencer_cache_put(context, seq_arr[0], cfra, SEQ_STRIPELEM_IBUF_COMP, out); return out; } - for (i = count - 1; i >= 0; i--) { int early_out; Sequence *seq = seq_arr[i]; @@ -2738,10 +2734,7 @@ static ImBuf *seq_render_strip_stack(SeqRenderData context, ListBase *seqbasep, BKE_sequencer_cache_put(context, seq_arr[i], cfra, SEQ_STRIPELEM_IBUF_COMP, out); } - if (out) { - /* put buffer back to linear space */ - IMB_colormanagement_imbuf_from_sequencer_space(out); - } + out->colormanage_flags |= IMB_COLORMANAGE_NOLINEAR_FLOAT; return out; } diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 72ddd67258a..9466be12b08 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -128,6 +128,7 @@ typedef struct ImBuf { unsigned int encodedbuffersize; /* Size of encodedbuffer */ /* color management */ + int colormanage_flags; unsigned int *display_buffer_flags; /* array of per-display display buffers dirty flags */ struct ColormanageCache *colormanage_cache; /* cache used by color management */ @@ -258,4 +259,9 @@ extern const char *imb_ext_image_qt[]; extern const char *imb_ext_movie[]; extern const char *imb_ext_audio[]; +/* ImBuf->colormanage_flags */ +enum { + IMB_COLORMANAGE_NOLINEAR_FLOAT = (1 << 0) +}; + #endif diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 41cff9d2c35..36b58031537 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -616,6 +616,8 @@ typedef struct DisplayBufferThread { int channels; int dither; int predivide; + + int nolinear_float; } DisplayBufferThread; typedef struct DisplayBufferInitData { @@ -659,6 +661,8 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l handle->channels = channels; handle->dither = dither; handle->predivide = predivide; + + handle->nolinear_float = ibuf->colormanage_flags & IMB_COLORMANAGE_NOLINEAR_FLOAT; } static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned char *byte_buffer, @@ -703,6 +707,20 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide, width, height, width, width); } + else if (handle->nolinear_float) { + /* currently float is non-linear only in sequencer, which is working + * in it's own color space even to handle float buffers, so we need to ensure + * float buffer is in linear space before applying all the view transformations + */ + + const char *from_colorspace = global_role_sequencer; + const char *to_colorspace = global_role_scene_linear; + + memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float)); + + IMB_colormanagement_colorspace_transform(linear_buffer, width, height, channels, + from_colorspace, to_colorspace); + } else { /* some processors would want to modify float original buffer * before converting it into display byte buffer, so we need to @@ -1060,9 +1078,6 @@ void IMB_colormanagement_imbuf_from_role(ImBuf *ibuf, int role) IMB_colormanagement_colorspace_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace); - - /* buffer in now in scene linear space */ - ibuf->profile = IB_PROFILE_LINEAR_RGB; } #else (void) ibuf; @@ -1118,13 +1133,13 @@ void IMB_colormanagement_imbuf_to_sequencer_space(ImBuf *ibuf, int make_float) if (global_role_sequencer[0]) { IMB_colormanagement_imbuf_to_role(ibuf, COLOR_ROLE_SEQUENCER); - ibuf->profile = IB_PROFILE_SRGB; + ibuf->profile = IB_PROFILE_NONE; } else #endif { /* if no sequencer's working space defined fallback to legacy sRGB space */ - IMB_convert_profile(ibuf, IB_PROFILE_SRGB); + IMB_convert_profile(ibuf, IB_PROFILE_NONE); } } @@ -1135,10 +1150,8 @@ void IMB_colormanagement_imbuf_from_sequencer_space(ImBuf *ibuf) #ifdef WITH_OCIO if (global_role_sequencer[0]) { - if (ibuf->profile == IB_PROFILE_SRGB) { - IMB_colormanagement_imbuf_from_role(ibuf, COLOR_ROLE_SEQUENCER); - ibuf->profile = IB_PROFILE_LINEAR_RGB; - } + IMB_colormanagement_imbuf_from_role(ibuf, COLOR_ROLE_SEQUENCER); + ibuf->profile = IB_PROFILE_LINEAR_RGB; } else #endif diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index badbf48338d..667429ca106 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1648,7 +1648,7 @@ int RE_seq_render_active(Scene *scene, RenderData *rd) static void do_render_seq(Render *re) { static int recurs_depth = 0; - struct ImBuf *ibuf; + struct ImBuf *ibuf, *out; RenderResult *rr; /* don't assign re->result here as it might change during give_ibuf_seq */ int cfra = re->r.cfra; SeqRenderData context; @@ -1675,7 +1675,11 @@ static void do_render_seq(Render *re) 100); } - ibuf = BKE_sequencer_give_ibuf(context, cfra, 0); + out = BKE_sequencer_give_ibuf(context, cfra, 0); + + ibuf = IMB_dupImBuf(out); + IMB_freeImBuf(out); + IMB_colormanagement_imbuf_from_sequencer_space(ibuf); recurs_depth--; diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 022d7846d80..a2b0cd09932 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -1089,22 +1089,14 @@ ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd) return ibuf; } -void render_result_rect_from_ibuf(RenderResult *rr, RenderData *rd, ImBuf *ibuf) +void render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBuf *ibuf) { if (ibuf->rect_float) { - /* color management: when off ensure rectf is non-lin, since thats what the internal - * render engine delivers */ - int profile_to = (rd->color_mgt_flag & R_COLOR_MANAGEMENT) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB; - int profile_from = (ibuf->profile == IB_PROFILE_LINEAR_RGB) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB; - int predivide = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE); - if (!rr->rectf) rr->rectf = MEM_mallocN(4 * sizeof(float) * rr->rectx * rr->recty, "render_seq rectf"); - IMB_buffer_float_from_float(rr->rectf, ibuf->rect_float, - 4, profile_to, profile_from, predivide, - rr->rectx, rr->recty, rr->rectx, rr->rectx); - + memcpy(rr->rectf, ibuf->rect_float, 4 * sizeof(float) * rr->rectx * rr->recty); + /* TSK! Since sequence render doesn't free the *rr render result, the old rect32 * can hang around when sequence render has rendered a 32 bits one before */ if (rr->rect32) { From 5dd9960369834cf73e443230c952e5c54b5d4542 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 30 Aug 2012 15:02:20 +0000 Subject: [PATCH 098/160] Color management: new View for xyz display is added This view is currently called DCI and it implements the same conversion into xyz space as OpenDCP does. This is aimed to be used for Jpeg2K in xyz space generation used for DCP creation directly from Blender. --- release/datafiles/colormanagement/config.ocio | 17 + .../colormanagement/luts/srgb_to_xyz.spimtx | 3 + .../colormanagement/luts/xyz_dci.spi1d | 65542 ++++++++++++++++ 3 files changed, 65562 insertions(+) create mode 100644 release/datafiles/colormanagement/luts/srgb_to_xyz.spimtx create mode 100644 release/datafiles/colormanagement/luts/xyz_dci.spi1d diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio index 571c0f8f339..1b714c09bf5 100644 --- a/release/datafiles/colormanagement/config.ocio +++ b/release/datafiles/colormanagement/config.ocio @@ -29,6 +29,7 @@ displays: - ! {name: Raw, colorspace: raw} - ! {name: Log, colorspace: adx10} - ! {name: RRT, colorspace: rrt_xyz} + - ! {name: DCI, colorspace: xyz_DCI} active_displays: [sRGB, p3dci, xyz] active_views: [Gamma2.2, RRT, Log, Film, Log, Raw, rec709] @@ -337,3 +338,19 @@ colorspaces: #- ! {src: rec709.spi1d, interpolation: linear} - ! {value: [2.2, 2.2, 2.2, 1]} - ! {src: rec709_to_aces.spimtx, interpolation: linear} + + - ! + name: xyz_DCI + family: "" + equalitygroup: "" + bitdepth: 16f + description: | + OpenDCP output LUT with DCI reference white and Gamma 2.6 + isdata: false + allocation: uniform + allocationvars: [0, 1] + from_reference: ! + children: + - ! {src: rec709_to_aces.spimtx, interpolation: linear, direction: inverse} + - ! {src: srgb_to_xyz.spimtx, interpolation: linear} + - ! {src: xyz_dci.spi1d, interpolation: linear} diff --git a/release/datafiles/colormanagement/luts/srgb_to_xyz.spimtx b/release/datafiles/colormanagement/luts/srgb_to_xyz.spimtx new file mode 100644 index 00000000000..decaa0e9f91 --- /dev/null +++ b/release/datafiles/colormanagement/luts/srgb_to_xyz.spimtx @@ -0,0 +1,3 @@ +0.4124564 0.3575761 0.1804375 0 +0.2126729 0.7151522 0.0721750 0 +0.0193339 0.1191920 0.9503041 0 diff --git a/release/datafiles/colormanagement/luts/xyz_dci.spi1d b/release/datafiles/colormanagement/luts/xyz_dci.spi1d new file mode 100644 index 00000000000..548956c2825 --- /dev/null +++ b/release/datafiles/colormanagement/luts/xyz_dci.spi1d @@ -0,0 +1,65542 @@ +Version 1 +From 0.0 1.0910416666666667 +Length 65536 +Components 1 +{ + 0.000000 + 0.013916 + 0.018311 + 0.021240 + 0.023926 + 0.025879 + 0.027832 + 0.029541 + 0.031006 + 0.032471 + 0.033936 + 0.035156 + 0.036377 + 0.037598 + 0.038574 + 0.039551 + 0.040771 + 0.041748 + 0.042480 + 0.043457 + 0.044434 + 0.045166 + 0.045898 + 0.046875 + 0.047607 + 0.048340 + 0.049072 + 0.049805 + 0.050537 + 0.051270 + 0.051758 + 0.052490 + 0.053223 + 0.053711 + 0.054443 + 0.054932 + 0.055664 + 0.056152 + 0.056885 + 0.057373 + 0.057861 + 0.058350 + 0.059082 + 0.059570 + 0.060059 + 0.060547 + 0.061035 + 0.061523 + 0.062012 + 0.062500 + 0.062988 + 0.063477 + 0.063965 + 0.064453 + 0.064941 + 0.065430 + 0.065918 + 0.066406 + 0.066895 + 0.067139 + 0.067627 + 0.068115 + 0.068604 + 0.069092 + 0.069336 + 0.069824 + 0.070312 + 0.070557 + 0.071045 + 0.071533 + 0.071777 + 0.072266 + 0.072510 + 0.072998 + 0.073486 + 0.073730 + 0.074219 + 0.074463 + 0.074951 + 0.075195 + 0.075684 + 0.075928 + 0.076416 + 0.076660 + 0.077148 + 0.077393 + 0.077881 + 0.078125 + 0.078369 + 0.078857 + 0.079102 + 0.079590 + 0.079834 + 0.080078 + 0.080566 + 0.080811 + 0.081055 + 0.081543 + 0.081787 + 0.082031 + 0.082520 + 0.082764 + 0.083008 + 0.083252 + 0.083740 + 0.083984 + 0.084229 + 0.084473 + 0.084961 + 0.085205 + 0.085449 + 0.085693 + 0.086182 + 0.086426 + 0.086670 + 0.086914 + 0.087158 + 0.087646 + 0.087891 + 0.088135 + 0.088379 + 0.088623 + 0.088867 + 0.089355 + 0.089600 + 0.089844 + 0.090088 + 0.090332 + 0.090576 + 0.090820 + 0.091064 + 0.091553 + 0.091797 + 0.092041 + 0.092285 + 0.092529 + 0.092773 + 0.093018 + 0.093262 + 0.093506 + 0.093750 + 0.093994 + 0.094238 + 0.094482 + 0.094727 + 0.094971 + 0.095459 + 0.095703 + 0.095947 + 0.096191 + 0.096436 + 0.096680 + 0.096924 + 0.097168 + 0.097412 + 0.097656 + 0.097900 + 0.098145 + 0.098389 + 0.098633 + 0.098877 + 0.099121 + 0.099121 + 0.099365 + 0.099609 + 0.099854 + 0.100098 + 0.100342 + 0.100586 + 0.100830 + 0.101074 + 0.101318 + 0.101562 + 0.101807 + 0.102051 + 0.102295 + 0.102539 + 0.102783 + 0.102783 + 0.103027 + 0.103271 + 0.103516 + 0.103760 + 0.104004 + 0.104248 + 0.104492 + 0.104736 + 0.104980 + 0.104980 + 0.105225 + 0.105469 + 0.105713 + 0.105957 + 0.106201 + 0.106445 + 0.106689 + 0.106689 + 0.106934 + 0.107178 + 0.107422 + 0.107666 + 0.107910 + 0.108154 + 0.108154 + 0.108398 + 0.108643 + 0.108887 + 0.109131 + 0.109375 + 0.109375 + 0.109619 + 0.109863 + 0.110107 + 0.110352 + 0.110352 + 0.110596 + 0.110840 + 0.111084 + 0.111328 + 0.111572 + 0.111572 + 0.111816 + 0.112061 + 0.112305 + 0.112549 + 0.112549 + 0.112793 + 0.113037 + 0.113281 + 0.113281 + 0.113525 + 0.113770 + 0.114014 + 0.114258 + 0.114258 + 0.114502 + 0.114746 + 0.114990 + 0.114990 + 0.115234 + 0.115479 + 0.115723 + 0.115723 + 0.115967 + 0.116211 + 0.116455 + 0.116455 + 0.116699 + 0.116943 + 0.117188 + 0.117188 + 0.117432 + 0.117676 + 0.117920 + 0.117920 + 0.118164 + 0.118408 + 0.118652 + 0.118652 + 0.118896 + 0.119141 + 0.119141 + 0.119385 + 0.119629 + 0.119873 + 0.119873 + 0.120117 + 0.120361 + 0.120361 + 0.120605 + 0.120850 + 0.121094 + 0.121094 + 0.121338 + 0.121582 + 0.121582 + 0.121826 + 0.122070 + 0.122070 + 0.122314 + 0.122559 + 0.122803 + 0.122803 + 0.123047 + 0.123291 + 0.123291 + 0.123535 + 0.123779 + 0.123779 + 0.124023 + 0.124268 + 0.124268 + 0.124512 + 0.124756 + 0.124756 + 0.125000 + 0.125244 + 0.125244 + 0.125488 + 0.125732 + 0.125732 + 0.125977 + 0.126221 + 0.126221 + 0.126465 + 0.126709 + 0.126709 + 0.126953 + 0.127197 + 0.127197 + 0.127441 + 0.127686 + 0.127686 + 0.127930 + 0.127930 + 0.128174 + 0.128418 + 0.128418 + 0.128662 + 0.128906 + 0.128906 + 0.129150 + 0.129395 + 0.129395 + 0.129639 + 0.129639 + 0.129883 + 0.130127 + 0.130127 + 0.130371 + 0.130615 + 0.130615 + 0.130859 + 0.130859 + 0.131104 + 0.131348 + 0.131348 + 0.131592 + 0.131836 + 0.131836 + 0.132080 + 0.132080 + 0.132324 + 0.132568 + 0.132568 + 0.132812 + 0.132812 + 0.133057 + 0.133301 + 0.133301 + 0.133545 + 0.133545 + 0.133789 + 0.134033 + 0.134033 + 0.134277 + 0.134277 + 0.134521 + 0.134766 + 0.134766 + 0.135010 + 0.135010 + 0.135254 + 0.135498 + 0.135498 + 0.135742 + 0.135742 + 0.135986 + 0.135986 + 0.136230 + 0.136475 + 0.136475 + 0.136719 + 0.136719 + 0.136963 + 0.137207 + 0.137207 + 0.137451 + 0.137451 + 0.137695 + 0.137695 + 0.137939 + 0.138184 + 0.138184 + 0.138428 + 0.138428 + 0.138672 + 0.138672 + 0.138916 + 0.139160 + 0.139160 + 0.139404 + 0.139404 + 0.139648 + 0.139648 + 0.139893 + 0.139893 + 0.140137 + 0.140381 + 0.140381 + 0.140625 + 0.140625 + 0.140869 + 0.140869 + 0.141113 + 0.141113 + 0.141357 + 0.141602 + 0.141602 + 0.141846 + 0.141846 + 0.142090 + 0.142090 + 0.142334 + 0.142334 + 0.142578 + 0.142578 + 0.142822 + 0.143066 + 0.143066 + 0.143311 + 0.143311 + 0.143555 + 0.143555 + 0.143799 + 0.143799 + 0.144043 + 0.144043 + 0.144287 + 0.144287 + 0.144531 + 0.144531 + 0.144775 + 0.145020 + 0.145020 + 0.145264 + 0.145264 + 0.145508 + 0.145508 + 0.145752 + 0.145752 + 0.145996 + 0.145996 + 0.146240 + 0.146240 + 0.146484 + 0.146484 + 0.146729 + 0.146729 + 0.146973 + 0.146973 + 0.147217 + 0.147217 + 0.147461 + 0.147461 + 0.147705 + 0.147705 + 0.147949 + 0.147949 + 0.148193 + 0.148193 + 0.148438 + 0.148682 + 0.148682 + 0.148926 + 0.148926 + 0.149170 + 0.149170 + 0.149414 + 0.149414 + 0.149658 + 0.149658 + 0.149902 + 0.149902 + 0.150146 + 0.150146 + 0.150391 + 0.150391 + 0.150635 + 0.150635 + 0.150879 + 0.150879 + 0.151123 + 0.151123 + 0.151367 + 0.151367 + 0.151367 + 0.151611 + 0.151611 + 0.151855 + 0.151855 + 0.152100 + 0.152100 + 0.152344 + 0.152344 + 0.152588 + 0.152588 + 0.152832 + 0.152832 + 0.153076 + 0.153076 + 0.153320 + 0.153320 + 0.153564 + 0.153564 + 0.153809 + 0.153809 + 0.154053 + 0.154053 + 0.154297 + 0.154297 + 0.154541 + 0.154541 + 0.154785 + 0.154785 + 0.154785 + 0.155029 + 0.155029 + 0.155273 + 0.155273 + 0.155518 + 0.155518 + 0.155762 + 0.155762 + 0.156006 + 0.156006 + 0.156250 + 0.156250 + 0.156494 + 0.156494 + 0.156738 + 0.156738 + 0.156738 + 0.156982 + 0.156982 + 0.157227 + 0.157227 + 0.157471 + 0.157471 + 0.157715 + 0.157715 + 0.157959 + 0.157959 + 0.158203 + 0.158203 + 0.158203 + 0.158447 + 0.158447 + 0.158691 + 0.158691 + 0.158936 + 0.158936 + 0.159180 + 0.159180 + 0.159424 + 0.159424 + 0.159424 + 0.159668 + 0.159668 + 0.159912 + 0.159912 + 0.160156 + 0.160156 + 0.160400 + 0.160400 + 0.160645 + 0.160645 + 0.160645 + 0.160889 + 0.160889 + 0.161133 + 0.161133 + 0.161377 + 0.161377 + 0.161621 + 0.161621 + 0.161621 + 0.161865 + 0.161865 + 0.162109 + 0.162109 + 0.162354 + 0.162354 + 0.162598 + 0.162598 + 0.162598 + 0.162842 + 0.162842 + 0.163086 + 0.163086 + 0.163330 + 0.163330 + 0.163330 + 0.163574 + 0.163574 + 0.163818 + 0.163818 + 0.164062 + 0.164062 + 0.164062 + 0.164307 + 0.164307 + 0.164551 + 0.164551 + 0.164795 + 0.164795 + 0.164795 + 0.165039 + 0.165039 + 0.165283 + 0.165283 + 0.165527 + 0.165527 + 0.165527 + 0.165771 + 0.165771 + 0.166016 + 0.166016 + 0.166260 + 0.166260 + 0.166260 + 0.166504 + 0.166504 + 0.166748 + 0.166748 + 0.166992 + 0.166992 + 0.166992 + 0.167236 + 0.167236 + 0.167480 + 0.167480 + 0.167725 + 0.167725 + 0.167725 + 0.167969 + 0.167969 + 0.168213 + 0.168213 + 0.168213 + 0.168457 + 0.168457 + 0.168701 + 0.168701 + 0.168701 + 0.168945 + 0.168945 + 0.169189 + 0.169189 + 0.169434 + 0.169434 + 0.169434 + 0.169678 + 0.169678 + 0.169922 + 0.169922 + 0.169922 + 0.170166 + 0.170166 + 0.170410 + 0.170410 + 0.170410 + 0.170654 + 0.170654 + 0.170898 + 0.170898 + 0.170898 + 0.171143 + 0.171143 + 0.171387 + 0.171387 + 0.171631 + 0.171631 + 0.171631 + 0.171875 + 0.171875 + 0.172119 + 0.172119 + 0.172119 + 0.172363 + 0.172363 + 0.172607 + 0.172607 + 0.172607 + 0.172852 + 0.172852 + 0.173096 + 0.173096 + 0.173096 + 0.173340 + 0.173340 + 0.173584 + 0.173584 + 0.173584 + 0.173828 + 0.173828 + 0.173828 + 0.174072 + 0.174072 + 0.174316 + 0.174316 + 0.174316 + 0.174561 + 0.174561 + 0.174805 + 0.174805 + 0.174805 + 0.175049 + 0.175049 + 0.175293 + 0.175293 + 0.175293 + 0.175537 + 0.175537 + 0.175781 + 0.175781 + 0.175781 + 0.176025 + 0.176025 + 0.176025 + 0.176270 + 0.176270 + 0.176514 + 0.176514 + 0.176514 + 0.176758 + 0.176758 + 0.177002 + 0.177002 + 0.177002 + 0.177246 + 0.177246 + 0.177246 + 0.177490 + 0.177490 + 0.177734 + 0.177734 + 0.177734 + 0.177979 + 0.177979 + 0.177979 + 0.178223 + 0.178223 + 0.178467 + 0.178467 + 0.178467 + 0.178711 + 0.178711 + 0.178955 + 0.178955 + 0.178955 + 0.179199 + 0.179199 + 0.179199 + 0.179443 + 0.179443 + 0.179688 + 0.179688 + 0.179688 + 0.179932 + 0.179932 + 0.179932 + 0.180176 + 0.180176 + 0.180420 + 0.180420 + 0.180420 + 0.180664 + 0.180664 + 0.180664 + 0.180908 + 0.180908 + 0.180908 + 0.181152 + 0.181152 + 0.181396 + 0.181396 + 0.181396 + 0.181641 + 0.181641 + 0.181641 + 0.181885 + 0.181885 + 0.182129 + 0.182129 + 0.182129 + 0.182373 + 0.182373 + 0.182373 + 0.182617 + 0.182617 + 0.182617 + 0.182861 + 0.182861 + 0.183105 + 0.183105 + 0.183105 + 0.183350 + 0.183350 + 0.183350 + 0.183594 + 0.183594 + 0.183594 + 0.183838 + 0.183838 + 0.184082 + 0.184082 + 0.184082 + 0.184326 + 0.184326 + 0.184326 + 0.184570 + 0.184570 + 0.184570 + 0.184814 + 0.184814 + 0.184814 + 0.185059 + 0.185059 + 0.185303 + 0.185303 + 0.185303 + 0.185547 + 0.185547 + 0.185547 + 0.185791 + 0.185791 + 0.185791 + 0.186035 + 0.186035 + 0.186035 + 0.186279 + 0.186279 + 0.186279 + 0.186523 + 0.186523 + 0.186768 + 0.186768 + 0.186768 + 0.187012 + 0.187012 + 0.187012 + 0.187256 + 0.187256 + 0.187256 + 0.187500 + 0.187500 + 0.187500 + 0.187744 + 0.187744 + 0.187744 + 0.187988 + 0.187988 + 0.187988 + 0.188232 + 0.188232 + 0.188477 + 0.188477 + 0.188477 + 0.188721 + 0.188721 + 0.188721 + 0.188965 + 0.188965 + 0.188965 + 0.189209 + 0.189209 + 0.189209 + 0.189453 + 0.189453 + 0.189453 + 0.189697 + 0.189697 + 0.189697 + 0.189941 + 0.189941 + 0.189941 + 0.190186 + 0.190186 + 0.190186 + 0.190430 + 0.190430 + 0.190430 + 0.190674 + 0.190674 + 0.190674 + 0.190918 + 0.190918 + 0.191162 + 0.191162 + 0.191162 + 0.191406 + 0.191406 + 0.191406 + 0.191650 + 0.191650 + 0.191650 + 0.191895 + 0.191895 + 0.191895 + 0.192139 + 0.192139 + 0.192139 + 0.192383 + 0.192383 + 0.192383 + 0.192627 + 0.192627 + 0.192627 + 0.192871 + 0.192871 + 0.192871 + 0.193115 + 0.193115 + 0.193115 + 0.193359 + 0.193359 + 0.193359 + 0.193604 + 0.193604 + 0.193604 + 0.193848 + 0.193848 + 0.193848 + 0.194092 + 0.194092 + 0.194092 + 0.194336 + 0.194336 + 0.194336 + 0.194580 + 0.194580 + 0.194580 + 0.194824 + 0.194824 + 0.194824 + 0.195068 + 0.195068 + 0.195068 + 0.195312 + 0.195312 + 0.195312 + 0.195312 + 0.195557 + 0.195557 + 0.195557 + 0.195801 + 0.195801 + 0.195801 + 0.196045 + 0.196045 + 0.196045 + 0.196289 + 0.196289 + 0.196289 + 0.196533 + 0.196533 + 0.196533 + 0.196777 + 0.196777 + 0.196777 + 0.197021 + 0.197021 + 0.197021 + 0.197266 + 0.197266 + 0.197266 + 0.197510 + 0.197510 + 0.197510 + 0.197754 + 0.197754 + 0.197754 + 0.197998 + 0.197998 + 0.197998 + 0.197998 + 0.198242 + 0.198242 + 0.198242 + 0.198486 + 0.198486 + 0.198486 + 0.198730 + 0.198730 + 0.198730 + 0.198975 + 0.198975 + 0.198975 + 0.199219 + 0.199219 + 0.199219 + 0.199463 + 0.199463 + 0.199463 + 0.199707 + 0.199707 + 0.199707 + 0.199707 + 0.199951 + 0.199951 + 0.199951 + 0.200195 + 0.200195 + 0.200195 + 0.200439 + 0.200439 + 0.200439 + 0.200684 + 0.200684 + 0.200684 + 0.200928 + 0.200928 + 0.200928 + 0.201172 + 0.201172 + 0.201172 + 0.201172 + 0.201416 + 0.201416 + 0.201416 + 0.201660 + 0.201660 + 0.201660 + 0.201904 + 0.201904 + 0.201904 + 0.202148 + 0.202148 + 0.202148 + 0.202148 + 0.202393 + 0.202393 + 0.202393 + 0.202637 + 0.202637 + 0.202637 + 0.202881 + 0.202881 + 0.202881 + 0.203125 + 0.203125 + 0.203125 + 0.203125 + 0.203369 + 0.203369 + 0.203369 + 0.203613 + 0.203613 + 0.203613 + 0.203857 + 0.203857 + 0.203857 + 0.204102 + 0.204102 + 0.204102 + 0.204102 + 0.204346 + 0.204346 + 0.204346 + 0.204590 + 0.204590 + 0.204590 + 0.204834 + 0.204834 + 0.204834 + 0.205078 + 0.205078 + 0.205078 + 0.205078 + 0.205322 + 0.205322 + 0.205322 + 0.205566 + 0.205566 + 0.205566 + 0.205811 + 0.205811 + 0.205811 + 0.205811 + 0.206055 + 0.206055 + 0.206055 + 0.206299 + 0.206299 + 0.206299 + 0.206543 + 0.206543 + 0.206543 + 0.206543 + 0.206787 + 0.206787 + 0.206787 + 0.207031 + 0.207031 + 0.207031 + 0.207275 + 0.207275 + 0.207275 + 0.207275 + 0.207520 + 0.207520 + 0.207520 + 0.207764 + 0.207764 + 0.207764 + 0.207764 + 0.208008 + 0.208008 + 0.208008 + 0.208252 + 0.208252 + 0.208252 + 0.208496 + 0.208496 + 0.208496 + 0.208496 + 0.208740 + 0.208740 + 0.208740 + 0.208984 + 0.208984 + 0.208984 + 0.209229 + 0.209229 + 0.209229 + 0.209229 + 0.209473 + 0.209473 + 0.209473 + 0.209717 + 0.209717 + 0.209717 + 0.209717 + 0.209961 + 0.209961 + 0.209961 + 0.210205 + 0.210205 + 0.210205 + 0.210205 + 0.210449 + 0.210449 + 0.210449 + 0.210693 + 0.210693 + 0.210693 + 0.210938 + 0.210938 + 0.210938 + 0.210938 + 0.211182 + 0.211182 + 0.211182 + 0.211426 + 0.211426 + 0.211426 + 0.211426 + 0.211670 + 0.211670 + 0.211670 + 0.211914 + 0.211914 + 0.211914 + 0.211914 + 0.212158 + 0.212158 + 0.212158 + 0.212402 + 0.212402 + 0.212402 + 0.212402 + 0.212646 + 0.212646 + 0.212646 + 0.212891 + 0.212891 + 0.212891 + 0.212891 + 0.213135 + 0.213135 + 0.213135 + 0.213379 + 0.213379 + 0.213379 + 0.213379 + 0.213623 + 0.213623 + 0.213623 + 0.213867 + 0.213867 + 0.213867 + 0.213867 + 0.214111 + 0.214111 + 0.214111 + 0.214355 + 0.214355 + 0.214355 + 0.214355 + 0.214600 + 0.214600 + 0.214600 + 0.214600 + 0.214844 + 0.214844 + 0.214844 + 0.215088 + 0.215088 + 0.215088 + 0.215088 + 0.215332 + 0.215332 + 0.215332 + 0.215576 + 0.215576 + 0.215576 + 0.215576 + 0.215820 + 0.215820 + 0.215820 + 0.216064 + 0.216064 + 0.216064 + 0.216064 + 0.216309 + 0.216309 + 0.216309 + 0.216309 + 0.216553 + 0.216553 + 0.216553 + 0.216797 + 0.216797 + 0.216797 + 0.216797 + 0.217041 + 0.217041 + 0.217041 + 0.217285 + 0.217285 + 0.217285 + 0.217285 + 0.217529 + 0.217529 + 0.217529 + 0.217529 + 0.217773 + 0.217773 + 0.217773 + 0.218018 + 0.218018 + 0.218018 + 0.218018 + 0.218262 + 0.218262 + 0.218262 + 0.218262 + 0.218506 + 0.218506 + 0.218506 + 0.218750 + 0.218750 + 0.218750 + 0.218750 + 0.218994 + 0.218994 + 0.218994 + 0.218994 + 0.219238 + 0.219238 + 0.219238 + 0.219482 + 0.219482 + 0.219482 + 0.219482 + 0.219727 + 0.219727 + 0.219727 + 0.219727 + 0.219971 + 0.219971 + 0.219971 + 0.220215 + 0.220215 + 0.220215 + 0.220215 + 0.220459 + 0.220459 + 0.220459 + 0.220459 + 0.220703 + 0.220703 + 0.220703 + 0.220947 + 0.220947 + 0.220947 + 0.220947 + 0.221191 + 0.221191 + 0.221191 + 0.221191 + 0.221436 + 0.221436 + 0.221436 + 0.221436 + 0.221680 + 0.221680 + 0.221680 + 0.221924 + 0.221924 + 0.221924 + 0.221924 + 0.222168 + 0.222168 + 0.222168 + 0.222168 + 0.222412 + 0.222412 + 0.222412 + 0.222412 + 0.222656 + 0.222656 + 0.222656 + 0.222900 + 0.222900 + 0.222900 + 0.222900 + 0.223145 + 0.223145 + 0.223145 + 0.223145 + 0.223389 + 0.223389 + 0.223389 + 0.223389 + 0.223633 + 0.223633 + 0.223633 + 0.223877 + 0.223877 + 0.223877 + 0.223877 + 0.224121 + 0.224121 + 0.224121 + 0.224121 + 0.224365 + 0.224365 + 0.224365 + 0.224365 + 0.224609 + 0.224609 + 0.224609 + 0.224609 + 0.224854 + 0.224854 + 0.224854 + 0.224854 + 0.225098 + 0.225098 + 0.225098 + 0.225342 + 0.225342 + 0.225342 + 0.225342 + 0.225586 + 0.225586 + 0.225586 + 0.225586 + 0.225830 + 0.225830 + 0.225830 + 0.225830 + 0.226074 + 0.226074 + 0.226074 + 0.226074 + 0.226318 + 0.226318 + 0.226318 + 0.226318 + 0.226562 + 0.226562 + 0.226562 + 0.226562 + 0.226807 + 0.226807 + 0.226807 + 0.227051 + 0.227051 + 0.227051 + 0.227051 + 0.227295 + 0.227295 + 0.227295 + 0.227295 + 0.227539 + 0.227539 + 0.227539 + 0.227539 + 0.227783 + 0.227783 + 0.227783 + 0.227783 + 0.228027 + 0.228027 + 0.228027 + 0.228027 + 0.228271 + 0.228271 + 0.228271 + 0.228271 + 0.228516 + 0.228516 + 0.228516 + 0.228516 + 0.228760 + 0.228760 + 0.228760 + 0.228760 + 0.229004 + 0.229004 + 0.229004 + 0.229004 + 0.229248 + 0.229248 + 0.229248 + 0.229248 + 0.229492 + 0.229492 + 0.229492 + 0.229492 + 0.229736 + 0.229736 + 0.229736 + 0.229980 + 0.229980 + 0.229980 + 0.229980 + 0.230225 + 0.230225 + 0.230225 + 0.230225 + 0.230469 + 0.230469 + 0.230469 + 0.230469 + 0.230713 + 0.230713 + 0.230713 + 0.230713 + 0.230957 + 0.230957 + 0.230957 + 0.230957 + 0.231201 + 0.231201 + 0.231201 + 0.231201 + 0.231445 + 0.231445 + 0.231445 + 0.231445 + 0.231689 + 0.231689 + 0.231689 + 0.231689 + 0.231934 + 0.231934 + 0.231934 + 0.231934 + 0.232178 + 0.232178 + 0.232178 + 0.232178 + 0.232422 + 0.232422 + 0.232422 + 0.232422 + 0.232666 + 0.232666 + 0.232666 + 0.232666 + 0.232666 + 0.232910 + 0.232910 + 0.232910 + 0.232910 + 0.233154 + 0.233154 + 0.233154 + 0.233154 + 0.233398 + 0.233398 + 0.233398 + 0.233398 + 0.233643 + 0.233643 + 0.233643 + 0.233643 + 0.233887 + 0.233887 + 0.233887 + 0.233887 + 0.234131 + 0.234131 + 0.234131 + 0.234131 + 0.234375 + 0.234375 + 0.234375 + 0.234375 + 0.234619 + 0.234619 + 0.234619 + 0.234619 + 0.234863 + 0.234863 + 0.234863 + 0.234863 + 0.235107 + 0.235107 + 0.235107 + 0.235107 + 0.235352 + 0.235352 + 0.235352 + 0.235352 + 0.235596 + 0.235596 + 0.235596 + 0.235596 + 0.235596 + 0.235840 + 0.235840 + 0.235840 + 0.235840 + 0.236084 + 0.236084 + 0.236084 + 0.236084 + 0.236328 + 0.236328 + 0.236328 + 0.236328 + 0.236572 + 0.236572 + 0.236572 + 0.236572 + 0.236816 + 0.236816 + 0.236816 + 0.236816 + 0.237061 + 0.237061 + 0.237061 + 0.237061 + 0.237305 + 0.237305 + 0.237305 + 0.237305 + 0.237305 + 0.237549 + 0.237549 + 0.237549 + 0.237549 + 0.237793 + 0.237793 + 0.237793 + 0.237793 + 0.238037 + 0.238037 + 0.238037 + 0.238037 + 0.238281 + 0.238281 + 0.238281 + 0.238281 + 0.238525 + 0.238525 + 0.238525 + 0.238525 + 0.238525 + 0.238770 + 0.238770 + 0.238770 + 0.238770 + 0.239014 + 0.239014 + 0.239014 + 0.239014 + 0.239258 + 0.239258 + 0.239258 + 0.239258 + 0.239502 + 0.239502 + 0.239502 + 0.239502 + 0.239746 + 0.239746 + 0.239746 + 0.239746 + 0.239746 + 0.239990 + 0.239990 + 0.239990 + 0.239990 + 0.240234 + 0.240234 + 0.240234 + 0.240234 + 0.240479 + 0.240479 + 0.240479 + 0.240479 + 0.240723 + 0.240723 + 0.240723 + 0.240723 + 0.240723 + 0.240967 + 0.240967 + 0.240967 + 0.240967 + 0.241211 + 0.241211 + 0.241211 + 0.241211 + 0.241455 + 0.241455 + 0.241455 + 0.241455 + 0.241455 + 0.241699 + 0.241699 + 0.241699 + 0.241699 + 0.241943 + 0.241943 + 0.241943 + 0.241943 + 0.242188 + 0.242188 + 0.242188 + 0.242188 + 0.242432 + 0.242432 + 0.242432 + 0.242432 + 0.242432 + 0.242676 + 0.242676 + 0.242676 + 0.242676 + 0.242920 + 0.242920 + 0.242920 + 0.242920 + 0.243164 + 0.243164 + 0.243164 + 0.243164 + 0.243164 + 0.243408 + 0.243408 + 0.243408 + 0.243408 + 0.243652 + 0.243652 + 0.243652 + 0.243652 + 0.243896 + 0.243896 + 0.243896 + 0.243896 + 0.243896 + 0.244141 + 0.244141 + 0.244141 + 0.244141 + 0.244385 + 0.244385 + 0.244385 + 0.244385 + 0.244385 + 0.244629 + 0.244629 + 0.244629 + 0.244629 + 0.244873 + 0.244873 + 0.244873 + 0.244873 + 0.245117 + 0.245117 + 0.245117 + 0.245117 + 0.245117 + 0.245361 + 0.245361 + 0.245361 + 0.245361 + 0.245605 + 0.245605 + 0.245605 + 0.245605 + 0.245605 + 0.245850 + 0.245850 + 0.245850 + 0.245850 + 0.246094 + 0.246094 + 0.246094 + 0.246094 + 0.246338 + 0.246338 + 0.246338 + 0.246338 + 0.246338 + 0.246582 + 0.246582 + 0.246582 + 0.246582 + 0.246826 + 0.246826 + 0.246826 + 0.246826 + 0.246826 + 0.247070 + 0.247070 + 0.247070 + 0.247070 + 0.247314 + 0.247314 + 0.247314 + 0.247314 + 0.247314 + 0.247559 + 0.247559 + 0.247559 + 0.247559 + 0.247803 + 0.247803 + 0.247803 + 0.247803 + 0.248047 + 0.248047 + 0.248047 + 0.248047 + 0.248047 + 0.248291 + 0.248291 + 0.248291 + 0.248291 + 0.248535 + 0.248535 + 0.248535 + 0.248535 + 0.248535 + 0.248779 + 0.248779 + 0.248779 + 0.248779 + 0.249023 + 0.249023 + 0.249023 + 0.249023 + 0.249023 + 0.249268 + 0.249268 + 0.249268 + 0.249268 + 0.249512 + 0.249512 + 0.249512 + 0.249512 + 0.249512 + 0.249756 + 0.249756 + 0.249756 + 0.249756 + 0.250000 + 0.250000 + 0.250000 + 0.250000 + 0.250000 + 0.250244 + 0.250244 + 0.250244 + 0.250244 + 0.250244 + 0.250488 + 0.250488 + 0.250488 + 0.250488 + 0.250732 + 0.250732 + 0.250732 + 0.250732 + 0.250732 + 0.250977 + 0.250977 + 0.250977 + 0.250977 + 0.251221 + 0.251221 + 0.251221 + 0.251221 + 0.251221 + 0.251465 + 0.251465 + 0.251465 + 0.251465 + 0.251709 + 0.251709 + 0.251709 + 0.251709 + 0.251709 + 0.251953 + 0.251953 + 0.251953 + 0.251953 + 0.251953 + 0.252197 + 0.252197 + 0.252197 + 0.252197 + 0.252441 + 0.252441 + 0.252441 + 0.252441 + 0.252441 + 0.252686 + 0.252686 + 0.252686 + 0.252686 + 0.252930 + 0.252930 + 0.252930 + 0.252930 + 0.252930 + 0.253174 + 0.253174 + 0.253174 + 0.253174 + 0.253174 + 0.253418 + 0.253418 + 0.253418 + 0.253418 + 0.253662 + 0.253662 + 0.253662 + 0.253662 + 0.253662 + 0.253906 + 0.253906 + 0.253906 + 0.253906 + 0.253906 + 0.254150 + 0.254150 + 0.254150 + 0.254150 + 0.254395 + 0.254395 + 0.254395 + 0.254395 + 0.254395 + 0.254639 + 0.254639 + 0.254639 + 0.254639 + 0.254639 + 0.254883 + 0.254883 + 0.254883 + 0.254883 + 0.255127 + 0.255127 + 0.255127 + 0.255127 + 0.255127 + 0.255371 + 0.255371 + 0.255371 + 0.255371 + 0.255371 + 0.255615 + 0.255615 + 0.255615 + 0.255615 + 0.255859 + 0.255859 + 0.255859 + 0.255859 + 0.255859 + 0.256104 + 0.256104 + 0.256104 + 0.256104 + 0.256104 + 0.256348 + 0.256348 + 0.256348 + 0.256348 + 0.256592 + 0.256592 + 0.256592 + 0.256592 + 0.256592 + 0.256836 + 0.256836 + 0.256836 + 0.256836 + 0.256836 + 0.257080 + 0.257080 + 0.257080 + 0.257080 + 0.257080 + 0.257324 + 0.257324 + 0.257324 + 0.257324 + 0.257568 + 0.257568 + 0.257568 + 0.257568 + 0.257568 + 0.257812 + 0.257812 + 0.257812 + 0.257812 + 0.257812 + 0.258057 + 0.258057 + 0.258057 + 0.258057 + 0.258057 + 0.258301 + 0.258301 + 0.258301 + 0.258301 + 0.258545 + 0.258545 + 0.258545 + 0.258545 + 0.258545 + 0.258789 + 0.258789 + 0.258789 + 0.258789 + 0.258789 + 0.259033 + 0.259033 + 0.259033 + 0.259033 + 0.259033 + 0.259277 + 0.259277 + 0.259277 + 0.259277 + 0.259277 + 0.259521 + 0.259521 + 0.259521 + 0.259521 + 0.259766 + 0.259766 + 0.259766 + 0.259766 + 0.259766 + 0.260010 + 0.260010 + 0.260010 + 0.260010 + 0.260010 + 0.260254 + 0.260254 + 0.260254 + 0.260254 + 0.260254 + 0.260498 + 0.260498 + 0.260498 + 0.260498 + 0.260498 + 0.260742 + 0.260742 + 0.260742 + 0.260742 + 0.260742 + 0.260986 + 0.260986 + 0.260986 + 0.260986 + 0.261230 + 0.261230 + 0.261230 + 0.261230 + 0.261230 + 0.261475 + 0.261475 + 0.261475 + 0.261475 + 0.261475 + 0.261719 + 0.261719 + 0.261719 + 0.261719 + 0.261719 + 0.261963 + 0.261963 + 0.261963 + 0.261963 + 0.261963 + 0.262207 + 0.262207 + 0.262207 + 0.262207 + 0.262207 + 0.262451 + 0.262451 + 0.262451 + 0.262451 + 0.262451 + 0.262695 + 0.262695 + 0.262695 + 0.262695 + 0.262695 + 0.262939 + 0.262939 + 0.262939 + 0.262939 + 0.262939 + 0.263184 + 0.263184 + 0.263184 + 0.263184 + 0.263428 + 0.263428 + 0.263428 + 0.263428 + 0.263428 + 0.263672 + 0.263672 + 0.263672 + 0.263672 + 0.263672 + 0.263916 + 0.263916 + 0.263916 + 0.263916 + 0.263916 + 0.264160 + 0.264160 + 0.264160 + 0.264160 + 0.264160 + 0.264404 + 0.264404 + 0.264404 + 0.264404 + 0.264404 + 0.264648 + 0.264648 + 0.264648 + 0.264648 + 0.264648 + 0.264893 + 0.264893 + 0.264893 + 0.264893 + 0.264893 + 0.265137 + 0.265137 + 0.265137 + 0.265137 + 0.265137 + 0.265381 + 0.265381 + 0.265381 + 0.265381 + 0.265381 + 0.265625 + 0.265625 + 0.265625 + 0.265625 + 0.265625 + 0.265869 + 0.265869 + 0.265869 + 0.265869 + 0.265869 + 0.266113 + 0.266113 + 0.266113 + 0.266113 + 0.266113 + 0.266357 + 0.266357 + 0.266357 + 0.266357 + 0.266357 + 0.266602 + 0.266602 + 0.266602 + 0.266602 + 0.266602 + 0.266846 + 0.266846 + 0.266846 + 0.266846 + 0.266846 + 0.267090 + 0.267090 + 0.267090 + 0.267090 + 0.267090 + 0.267334 + 0.267334 + 0.267334 + 0.267334 + 0.267334 + 0.267578 + 0.267578 + 0.267578 + 0.267578 + 0.267578 + 0.267822 + 0.267822 + 0.267822 + 0.267822 + 0.267822 + 0.268066 + 0.268066 + 0.268066 + 0.268066 + 0.268066 + 0.268311 + 0.268311 + 0.268311 + 0.268311 + 0.268311 + 0.268555 + 0.268555 + 0.268555 + 0.268555 + 0.268555 + 0.268555 + 0.268799 + 0.268799 + 0.268799 + 0.268799 + 0.268799 + 0.269043 + 0.269043 + 0.269043 + 0.269043 + 0.269043 + 0.269287 + 0.269287 + 0.269287 + 0.269287 + 0.269287 + 0.269531 + 0.269531 + 0.269531 + 0.269531 + 0.269531 + 0.269775 + 0.269775 + 0.269775 + 0.269775 + 0.269775 + 0.270020 + 0.270020 + 0.270020 + 0.270020 + 0.270020 + 0.270264 + 0.270264 + 0.270264 + 0.270264 + 0.270264 + 0.270508 + 0.270508 + 0.270508 + 0.270508 + 0.270508 + 0.270508 + 0.270752 + 0.270752 + 0.270752 + 0.270752 + 0.270752 + 0.270996 + 0.270996 + 0.270996 + 0.270996 + 0.270996 + 0.271240 + 0.271240 + 0.271240 + 0.271240 + 0.271240 + 0.271484 + 0.271484 + 0.271484 + 0.271484 + 0.271484 + 0.271729 + 0.271729 + 0.271729 + 0.271729 + 0.271729 + 0.271973 + 0.271973 + 0.271973 + 0.271973 + 0.271973 + 0.271973 + 0.272217 + 0.272217 + 0.272217 + 0.272217 + 0.272217 + 0.272461 + 0.272461 + 0.272461 + 0.272461 + 0.272461 + 0.272705 + 0.272705 + 0.272705 + 0.272705 + 0.272705 + 0.272949 + 0.272949 + 0.272949 + 0.272949 + 0.272949 + 0.273193 + 0.273193 + 0.273193 + 0.273193 + 0.273193 + 0.273193 + 0.273438 + 0.273438 + 0.273438 + 0.273438 + 0.273438 + 0.273682 + 0.273682 + 0.273682 + 0.273682 + 0.273682 + 0.273926 + 0.273926 + 0.273926 + 0.273926 + 0.273926 + 0.274170 + 0.274170 + 0.274170 + 0.274170 + 0.274170 + 0.274170 + 0.274414 + 0.274414 + 0.274414 + 0.274414 + 0.274414 + 0.274658 + 0.274658 + 0.274658 + 0.274658 + 0.274658 + 0.274902 + 0.274902 + 0.274902 + 0.274902 + 0.274902 + 0.275146 + 0.275146 + 0.275146 + 0.275146 + 0.275146 + 0.275146 + 0.275391 + 0.275391 + 0.275391 + 0.275391 + 0.275391 + 0.275635 + 0.275635 + 0.275635 + 0.275635 + 0.275635 + 0.275879 + 0.275879 + 0.275879 + 0.275879 + 0.275879 + 0.275879 + 0.276123 + 0.276123 + 0.276123 + 0.276123 + 0.276123 + 0.276367 + 0.276367 + 0.276367 + 0.276367 + 0.276367 + 0.276611 + 0.276611 + 0.276611 + 0.276611 + 0.276611 + 0.276855 + 0.276855 + 0.276855 + 0.276855 + 0.276855 + 0.276855 + 0.277100 + 0.277100 + 0.277100 + 0.277100 + 0.277100 + 0.277344 + 0.277344 + 0.277344 + 0.277344 + 0.277344 + 0.277344 + 0.277588 + 0.277588 + 0.277588 + 0.277588 + 0.277588 + 0.277832 + 0.277832 + 0.277832 + 0.277832 + 0.277832 + 0.278076 + 0.278076 + 0.278076 + 0.278076 + 0.278076 + 0.278076 + 0.278320 + 0.278320 + 0.278320 + 0.278320 + 0.278320 + 0.278564 + 0.278564 + 0.278564 + 0.278564 + 0.278564 + 0.278809 + 0.278809 + 0.278809 + 0.278809 + 0.278809 + 0.278809 + 0.279053 + 0.279053 + 0.279053 + 0.279053 + 0.279053 + 0.279297 + 0.279297 + 0.279297 + 0.279297 + 0.279297 + 0.279297 + 0.279541 + 0.279541 + 0.279541 + 0.279541 + 0.279541 + 0.279785 + 0.279785 + 0.279785 + 0.279785 + 0.279785 + 0.280029 + 0.280029 + 0.280029 + 0.280029 + 0.280029 + 0.280029 + 0.280273 + 0.280273 + 0.280273 + 0.280273 + 0.280273 + 0.280518 + 0.280518 + 0.280518 + 0.280518 + 0.280518 + 0.280518 + 0.280762 + 0.280762 + 0.280762 + 0.280762 + 0.280762 + 0.281006 + 0.281006 + 0.281006 + 0.281006 + 0.281006 + 0.281006 + 0.281250 + 0.281250 + 0.281250 + 0.281250 + 0.281250 + 0.281494 + 0.281494 + 0.281494 + 0.281494 + 0.281494 + 0.281494 + 0.281738 + 0.281738 + 0.281738 + 0.281738 + 0.281738 + 0.281982 + 0.281982 + 0.281982 + 0.281982 + 0.281982 + 0.281982 + 0.282227 + 0.282227 + 0.282227 + 0.282227 + 0.282227 + 0.282471 + 0.282471 + 0.282471 + 0.282471 + 0.282471 + 0.282471 + 0.282715 + 0.282715 + 0.282715 + 0.282715 + 0.282715 + 0.282959 + 0.282959 + 0.282959 + 0.282959 + 0.282959 + 0.282959 + 0.283203 + 0.283203 + 0.283203 + 0.283203 + 0.283203 + 0.283447 + 0.283447 + 0.283447 + 0.283447 + 0.283447 + 0.283447 + 0.283691 + 0.283691 + 0.283691 + 0.283691 + 0.283691 + 0.283936 + 0.283936 + 0.283936 + 0.283936 + 0.283936 + 0.283936 + 0.284180 + 0.284180 + 0.284180 + 0.284180 + 0.284180 + 0.284424 + 0.284424 + 0.284424 + 0.284424 + 0.284424 + 0.284424 + 0.284668 + 0.284668 + 0.284668 + 0.284668 + 0.284668 + 0.284668 + 0.284912 + 0.284912 + 0.284912 + 0.284912 + 0.284912 + 0.285156 + 0.285156 + 0.285156 + 0.285156 + 0.285156 + 0.285156 + 0.285400 + 0.285400 + 0.285400 + 0.285400 + 0.285400 + 0.285645 + 0.285645 + 0.285645 + 0.285645 + 0.285645 + 0.285645 + 0.285889 + 0.285889 + 0.285889 + 0.285889 + 0.285889 + 0.285889 + 0.286133 + 0.286133 + 0.286133 + 0.286133 + 0.286133 + 0.286377 + 0.286377 + 0.286377 + 0.286377 + 0.286377 + 0.286377 + 0.286621 + 0.286621 + 0.286621 + 0.286621 + 0.286621 + 0.286621 + 0.286865 + 0.286865 + 0.286865 + 0.286865 + 0.286865 + 0.287109 + 0.287109 + 0.287109 + 0.287109 + 0.287109 + 0.287109 + 0.287354 + 0.287354 + 0.287354 + 0.287354 + 0.287354 + 0.287598 + 0.287598 + 0.287598 + 0.287598 + 0.287598 + 0.287598 + 0.287842 + 0.287842 + 0.287842 + 0.287842 + 0.287842 + 0.287842 + 0.288086 + 0.288086 + 0.288086 + 0.288086 + 0.288086 + 0.288086 + 0.288330 + 0.288330 + 0.288330 + 0.288330 + 0.288330 + 0.288574 + 0.288574 + 0.288574 + 0.288574 + 0.288574 + 0.288574 + 0.288818 + 0.288818 + 0.288818 + 0.288818 + 0.288818 + 0.288818 + 0.289062 + 0.289062 + 0.289062 + 0.289062 + 0.289062 + 0.289307 + 0.289307 + 0.289307 + 0.289307 + 0.289307 + 0.289307 + 0.289551 + 0.289551 + 0.289551 + 0.289551 + 0.289551 + 0.289551 + 0.289795 + 0.289795 + 0.289795 + 0.289795 + 0.289795 + 0.289795 + 0.290039 + 0.290039 + 0.290039 + 0.290039 + 0.290039 + 0.290283 + 0.290283 + 0.290283 + 0.290283 + 0.290283 + 0.290283 + 0.290527 + 0.290527 + 0.290527 + 0.290527 + 0.290527 + 0.290527 + 0.290771 + 0.290771 + 0.290771 + 0.290771 + 0.290771 + 0.290771 + 0.291016 + 0.291016 + 0.291016 + 0.291016 + 0.291016 + 0.291260 + 0.291260 + 0.291260 + 0.291260 + 0.291260 + 0.291260 + 0.291504 + 0.291504 + 0.291504 + 0.291504 + 0.291504 + 0.291504 + 0.291748 + 0.291748 + 0.291748 + 0.291748 + 0.291748 + 0.291748 + 0.291992 + 0.291992 + 0.291992 + 0.291992 + 0.291992 + 0.291992 + 0.292236 + 0.292236 + 0.292236 + 0.292236 + 0.292236 + 0.292480 + 0.292480 + 0.292480 + 0.292480 + 0.292480 + 0.292480 + 0.292725 + 0.292725 + 0.292725 + 0.292725 + 0.292725 + 0.292725 + 0.292969 + 0.292969 + 0.292969 + 0.292969 + 0.292969 + 0.292969 + 0.293213 + 0.293213 + 0.293213 + 0.293213 + 0.293213 + 0.293213 + 0.293457 + 0.293457 + 0.293457 + 0.293457 + 0.293457 + 0.293457 + 0.293701 + 0.293701 + 0.293701 + 0.293701 + 0.293701 + 0.293945 + 0.293945 + 0.293945 + 0.293945 + 0.293945 + 0.293945 + 0.294189 + 0.294189 + 0.294189 + 0.294189 + 0.294189 + 0.294189 + 0.294434 + 0.294434 + 0.294434 + 0.294434 + 0.294434 + 0.294434 + 0.294678 + 0.294678 + 0.294678 + 0.294678 + 0.294678 + 0.294678 + 0.294922 + 0.294922 + 0.294922 + 0.294922 + 0.294922 + 0.294922 + 0.295166 + 0.295166 + 0.295166 + 0.295166 + 0.295166 + 0.295166 + 0.295410 + 0.295410 + 0.295410 + 0.295410 + 0.295410 + 0.295410 + 0.295654 + 0.295654 + 0.295654 + 0.295654 + 0.295654 + 0.295654 + 0.295898 + 0.295898 + 0.295898 + 0.295898 + 0.295898 + 0.295898 + 0.296143 + 0.296143 + 0.296143 + 0.296143 + 0.296143 + 0.296143 + 0.296387 + 0.296387 + 0.296387 + 0.296387 + 0.296387 + 0.296631 + 0.296631 + 0.296631 + 0.296631 + 0.296631 + 0.296631 + 0.296875 + 0.296875 + 0.296875 + 0.296875 + 0.296875 + 0.296875 + 0.297119 + 0.297119 + 0.297119 + 0.297119 + 0.297119 + 0.297119 + 0.297363 + 0.297363 + 0.297363 + 0.297363 + 0.297363 + 0.297363 + 0.297607 + 0.297607 + 0.297607 + 0.297607 + 0.297607 + 0.297607 + 0.297852 + 0.297852 + 0.297852 + 0.297852 + 0.297852 + 0.297852 + 0.298096 + 0.298096 + 0.298096 + 0.298096 + 0.298096 + 0.298096 + 0.298340 + 0.298340 + 0.298340 + 0.298340 + 0.298340 + 0.298340 + 0.298584 + 0.298584 + 0.298584 + 0.298584 + 0.298584 + 0.298584 + 0.298828 + 0.298828 + 0.298828 + 0.298828 + 0.298828 + 0.298828 + 0.299072 + 0.299072 + 0.299072 + 0.299072 + 0.299072 + 0.299072 + 0.299316 + 0.299316 + 0.299316 + 0.299316 + 0.299316 + 0.299316 + 0.299316 + 0.299561 + 0.299561 + 0.299561 + 0.299561 + 0.299561 + 0.299561 + 0.299805 + 0.299805 + 0.299805 + 0.299805 + 0.299805 + 0.299805 + 0.300049 + 0.300049 + 0.300049 + 0.300049 + 0.300049 + 0.300049 + 0.300293 + 0.300293 + 0.300293 + 0.300293 + 0.300293 + 0.300293 + 0.300537 + 0.300537 + 0.300537 + 0.300537 + 0.300537 + 0.300537 + 0.300781 + 0.300781 + 0.300781 + 0.300781 + 0.300781 + 0.300781 + 0.301025 + 0.301025 + 0.301025 + 0.301025 + 0.301025 + 0.301025 + 0.301270 + 0.301270 + 0.301270 + 0.301270 + 0.301270 + 0.301270 + 0.301514 + 0.301514 + 0.301514 + 0.301514 + 0.301514 + 0.301514 + 0.301758 + 0.301758 + 0.301758 + 0.301758 + 0.301758 + 0.301758 + 0.302002 + 0.302002 + 0.302002 + 0.302002 + 0.302002 + 0.302002 + 0.302002 + 0.302246 + 0.302246 + 0.302246 + 0.302246 + 0.302246 + 0.302246 + 0.302490 + 0.302490 + 0.302490 + 0.302490 + 0.302490 + 0.302490 + 0.302734 + 0.302734 + 0.302734 + 0.302734 + 0.302734 + 0.302734 + 0.302979 + 0.302979 + 0.302979 + 0.302979 + 0.302979 + 0.302979 + 0.303223 + 0.303223 + 0.303223 + 0.303223 + 0.303223 + 0.303223 + 0.303467 + 0.303467 + 0.303467 + 0.303467 + 0.303467 + 0.303467 + 0.303467 + 0.303711 + 0.303711 + 0.303711 + 0.303711 + 0.303711 + 0.303711 + 0.303955 + 0.303955 + 0.303955 + 0.303955 + 0.303955 + 0.303955 + 0.304199 + 0.304199 + 0.304199 + 0.304199 + 0.304199 + 0.304199 + 0.304443 + 0.304443 + 0.304443 + 0.304443 + 0.304443 + 0.304443 + 0.304688 + 0.304688 + 0.304688 + 0.304688 + 0.304688 + 0.304688 + 0.304688 + 0.304932 + 0.304932 + 0.304932 + 0.304932 + 0.304932 + 0.304932 + 0.305176 + 0.305176 + 0.305176 + 0.305176 + 0.305176 + 0.305176 + 0.305420 + 0.305420 + 0.305420 + 0.305420 + 0.305420 + 0.305420 + 0.305664 + 0.305664 + 0.305664 + 0.305664 + 0.305664 + 0.305664 + 0.305908 + 0.305908 + 0.305908 + 0.305908 + 0.305908 + 0.305908 + 0.305908 + 0.306152 + 0.306152 + 0.306152 + 0.306152 + 0.306152 + 0.306152 + 0.306396 + 0.306396 + 0.306396 + 0.306396 + 0.306396 + 0.306396 + 0.306641 + 0.306641 + 0.306641 + 0.306641 + 0.306641 + 0.306641 + 0.306641 + 0.306885 + 0.306885 + 0.306885 + 0.306885 + 0.306885 + 0.306885 + 0.307129 + 0.307129 + 0.307129 + 0.307129 + 0.307129 + 0.307129 + 0.307373 + 0.307373 + 0.307373 + 0.307373 + 0.307373 + 0.307373 + 0.307617 + 0.307617 + 0.307617 + 0.307617 + 0.307617 + 0.307617 + 0.307617 + 0.307861 + 0.307861 + 0.307861 + 0.307861 + 0.307861 + 0.307861 + 0.308105 + 0.308105 + 0.308105 + 0.308105 + 0.308105 + 0.308105 + 0.308350 + 0.308350 + 0.308350 + 0.308350 + 0.308350 + 0.308350 + 0.308350 + 0.308594 + 0.308594 + 0.308594 + 0.308594 + 0.308594 + 0.308594 + 0.308838 + 0.308838 + 0.308838 + 0.308838 + 0.308838 + 0.308838 + 0.309082 + 0.309082 + 0.309082 + 0.309082 + 0.309082 + 0.309082 + 0.309082 + 0.309326 + 0.309326 + 0.309326 + 0.309326 + 0.309326 + 0.309326 + 0.309570 + 0.309570 + 0.309570 + 0.309570 + 0.309570 + 0.309570 + 0.309570 + 0.309814 + 0.309814 + 0.309814 + 0.309814 + 0.309814 + 0.309814 + 0.310059 + 0.310059 + 0.310059 + 0.310059 + 0.310059 + 0.310059 + 0.310303 + 0.310303 + 0.310303 + 0.310303 + 0.310303 + 0.310303 + 0.310303 + 0.310547 + 0.310547 + 0.310547 + 0.310547 + 0.310547 + 0.310547 + 0.310791 + 0.310791 + 0.310791 + 0.310791 + 0.310791 + 0.310791 + 0.310791 + 0.311035 + 0.311035 + 0.311035 + 0.311035 + 0.311035 + 0.311035 + 0.311279 + 0.311279 + 0.311279 + 0.311279 + 0.311279 + 0.311279 + 0.311279 + 0.311523 + 0.311523 + 0.311523 + 0.311523 + 0.311523 + 0.311523 + 0.311768 + 0.311768 + 0.311768 + 0.311768 + 0.311768 + 0.311768 + 0.312012 + 0.312012 + 0.312012 + 0.312012 + 0.312012 + 0.312012 + 0.312012 + 0.312256 + 0.312256 + 0.312256 + 0.312256 + 0.312256 + 0.312256 + 0.312500 + 0.312500 + 0.312500 + 0.312500 + 0.312500 + 0.312500 + 0.312500 + 0.312744 + 0.312744 + 0.312744 + 0.312744 + 0.312744 + 0.312744 + 0.312988 + 0.312988 + 0.312988 + 0.312988 + 0.312988 + 0.312988 + 0.312988 + 0.313232 + 0.313232 + 0.313232 + 0.313232 + 0.313232 + 0.313232 + 0.313477 + 0.313477 + 0.313477 + 0.313477 + 0.313477 + 0.313477 + 0.313477 + 0.313721 + 0.313721 + 0.313721 + 0.313721 + 0.313721 + 0.313721 + 0.313965 + 0.313965 + 0.313965 + 0.313965 + 0.313965 + 0.313965 + 0.313965 + 0.314209 + 0.314209 + 0.314209 + 0.314209 + 0.314209 + 0.314209 + 0.314453 + 0.314453 + 0.314453 + 0.314453 + 0.314453 + 0.314453 + 0.314453 + 0.314697 + 0.314697 + 0.314697 + 0.314697 + 0.314697 + 0.314697 + 0.314941 + 0.314941 + 0.314941 + 0.314941 + 0.314941 + 0.314941 + 0.314941 + 0.315186 + 0.315186 + 0.315186 + 0.315186 + 0.315186 + 0.315186 + 0.315186 + 0.315430 + 0.315430 + 0.315430 + 0.315430 + 0.315430 + 0.315430 + 0.315674 + 0.315674 + 0.315674 + 0.315674 + 0.315674 + 0.315674 + 0.315674 + 0.315918 + 0.315918 + 0.315918 + 0.315918 + 0.315918 + 0.315918 + 0.316162 + 0.316162 + 0.316162 + 0.316162 + 0.316162 + 0.316162 + 0.316162 + 0.316406 + 0.316406 + 0.316406 + 0.316406 + 0.316406 + 0.316406 + 0.316406 + 0.316650 + 0.316650 + 0.316650 + 0.316650 + 0.316650 + 0.316650 + 0.316895 + 0.316895 + 0.316895 + 0.316895 + 0.316895 + 0.316895 + 0.316895 + 0.317139 + 0.317139 + 0.317139 + 0.317139 + 0.317139 + 0.317139 + 0.317383 + 0.317383 + 0.317383 + 0.317383 + 0.317383 + 0.317383 + 0.317383 + 0.317627 + 0.317627 + 0.317627 + 0.317627 + 0.317627 + 0.317627 + 0.317627 + 0.317871 + 0.317871 + 0.317871 + 0.317871 + 0.317871 + 0.317871 + 0.318115 + 0.318115 + 0.318115 + 0.318115 + 0.318115 + 0.318115 + 0.318115 + 0.318359 + 0.318359 + 0.318359 + 0.318359 + 0.318359 + 0.318359 + 0.318359 + 0.318604 + 0.318604 + 0.318604 + 0.318604 + 0.318604 + 0.318604 + 0.318848 + 0.318848 + 0.318848 + 0.318848 + 0.318848 + 0.318848 + 0.318848 + 0.319092 + 0.319092 + 0.319092 + 0.319092 + 0.319092 + 0.319092 + 0.319092 + 0.319336 + 0.319336 + 0.319336 + 0.319336 + 0.319336 + 0.319336 + 0.319580 + 0.319580 + 0.319580 + 0.319580 + 0.319580 + 0.319580 + 0.319580 + 0.319824 + 0.319824 + 0.319824 + 0.319824 + 0.319824 + 0.319824 + 0.319824 + 0.320068 + 0.320068 + 0.320068 + 0.320068 + 0.320068 + 0.320068 + 0.320068 + 0.320312 + 0.320312 + 0.320312 + 0.320312 + 0.320312 + 0.320312 + 0.320557 + 0.320557 + 0.320557 + 0.320557 + 0.320557 + 0.320557 + 0.320557 + 0.320801 + 0.320801 + 0.320801 + 0.320801 + 0.320801 + 0.320801 + 0.320801 + 0.321045 + 0.321045 + 0.321045 + 0.321045 + 0.321045 + 0.321045 + 0.321045 + 0.321289 + 0.321289 + 0.321289 + 0.321289 + 0.321289 + 0.321289 + 0.321533 + 0.321533 + 0.321533 + 0.321533 + 0.321533 + 0.321533 + 0.321533 + 0.321777 + 0.321777 + 0.321777 + 0.321777 + 0.321777 + 0.321777 + 0.321777 + 0.322021 + 0.322021 + 0.322021 + 0.322021 + 0.322021 + 0.322021 + 0.322021 + 0.322266 + 0.322266 + 0.322266 + 0.322266 + 0.322266 + 0.322266 + 0.322266 + 0.322510 + 0.322510 + 0.322510 + 0.322510 + 0.322510 + 0.322510 + 0.322754 + 0.322754 + 0.322754 + 0.322754 + 0.322754 + 0.322754 + 0.322754 + 0.322998 + 0.322998 + 0.322998 + 0.322998 + 0.322998 + 0.322998 + 0.322998 + 0.323242 + 0.323242 + 0.323242 + 0.323242 + 0.323242 + 0.323242 + 0.323242 + 0.323486 + 0.323486 + 0.323486 + 0.323486 + 0.323486 + 0.323486 + 0.323486 + 0.323730 + 0.323730 + 0.323730 + 0.323730 + 0.323730 + 0.323730 + 0.323730 + 0.323975 + 0.323975 + 0.323975 + 0.323975 + 0.323975 + 0.323975 + 0.324219 + 0.324219 + 0.324219 + 0.324219 + 0.324219 + 0.324219 + 0.324219 + 0.324463 + 0.324463 + 0.324463 + 0.324463 + 0.324463 + 0.324463 + 0.324463 + 0.324707 + 0.324707 + 0.324707 + 0.324707 + 0.324707 + 0.324707 + 0.324707 + 0.324951 + 0.324951 + 0.324951 + 0.324951 + 0.324951 + 0.324951 + 0.324951 + 0.325195 + 0.325195 + 0.325195 + 0.325195 + 0.325195 + 0.325195 + 0.325195 + 0.325439 + 0.325439 + 0.325439 + 0.325439 + 0.325439 + 0.325439 + 0.325439 + 0.325684 + 0.325684 + 0.325684 + 0.325684 + 0.325684 + 0.325684 + 0.325684 + 0.325928 + 0.325928 + 0.325928 + 0.325928 + 0.325928 + 0.325928 + 0.325928 + 0.326172 + 0.326172 + 0.326172 + 0.326172 + 0.326172 + 0.326172 + 0.326172 + 0.326416 + 0.326416 + 0.326416 + 0.326416 + 0.326416 + 0.326416 + 0.326416 + 0.326660 + 0.326660 + 0.326660 + 0.326660 + 0.326660 + 0.326660 + 0.326904 + 0.326904 + 0.326904 + 0.326904 + 0.326904 + 0.326904 + 0.326904 + 0.327148 + 0.327148 + 0.327148 + 0.327148 + 0.327148 + 0.327148 + 0.327148 + 0.327393 + 0.327393 + 0.327393 + 0.327393 + 0.327393 + 0.327393 + 0.327393 + 0.327637 + 0.327637 + 0.327637 + 0.327637 + 0.327637 + 0.327637 + 0.327637 + 0.327881 + 0.327881 + 0.327881 + 0.327881 + 0.327881 + 0.327881 + 0.327881 + 0.328125 + 0.328125 + 0.328125 + 0.328125 + 0.328125 + 0.328125 + 0.328125 + 0.328369 + 0.328369 + 0.328369 + 0.328369 + 0.328369 + 0.328369 + 0.328369 + 0.328613 + 0.328613 + 0.328613 + 0.328613 + 0.328613 + 0.328613 + 0.328613 + 0.328857 + 0.328857 + 0.328857 + 0.328857 + 0.328857 + 0.328857 + 0.328857 + 0.329102 + 0.329102 + 0.329102 + 0.329102 + 0.329102 + 0.329102 + 0.329102 + 0.329346 + 0.329346 + 0.329346 + 0.329346 + 0.329346 + 0.329346 + 0.329346 + 0.329590 + 0.329590 + 0.329590 + 0.329590 + 0.329590 + 0.329590 + 0.329590 + 0.329590 + 0.329834 + 0.329834 + 0.329834 + 0.329834 + 0.329834 + 0.329834 + 0.329834 + 0.330078 + 0.330078 + 0.330078 + 0.330078 + 0.330078 + 0.330078 + 0.330078 + 0.330322 + 0.330322 + 0.330322 + 0.330322 + 0.330322 + 0.330322 + 0.330322 + 0.330566 + 0.330566 + 0.330566 + 0.330566 + 0.330566 + 0.330566 + 0.330566 + 0.330811 + 0.330811 + 0.330811 + 0.330811 + 0.330811 + 0.330811 + 0.330811 + 0.331055 + 0.331055 + 0.331055 + 0.331055 + 0.331055 + 0.331055 + 0.331055 + 0.331299 + 0.331299 + 0.331299 + 0.331299 + 0.331299 + 0.331299 + 0.331299 + 0.331543 + 0.331543 + 0.331543 + 0.331543 + 0.331543 + 0.331543 + 0.331543 + 0.331787 + 0.331787 + 0.331787 + 0.331787 + 0.331787 + 0.331787 + 0.331787 + 0.332031 + 0.332031 + 0.332031 + 0.332031 + 0.332031 + 0.332031 + 0.332031 + 0.332031 + 0.332275 + 0.332275 + 0.332275 + 0.332275 + 0.332275 + 0.332275 + 0.332275 + 0.332520 + 0.332520 + 0.332520 + 0.332520 + 0.332520 + 0.332520 + 0.332520 + 0.332764 + 0.332764 + 0.332764 + 0.332764 + 0.332764 + 0.332764 + 0.332764 + 0.333008 + 0.333008 + 0.333008 + 0.333008 + 0.333008 + 0.333008 + 0.333008 + 0.333252 + 0.333252 + 0.333252 + 0.333252 + 0.333252 + 0.333252 + 0.333252 + 0.333496 + 0.333496 + 0.333496 + 0.333496 + 0.333496 + 0.333496 + 0.333496 + 0.333496 + 0.333740 + 0.333740 + 0.333740 + 0.333740 + 0.333740 + 0.333740 + 0.333740 + 0.333984 + 0.333984 + 0.333984 + 0.333984 + 0.333984 + 0.333984 + 0.333984 + 0.334229 + 0.334229 + 0.334229 + 0.334229 + 0.334229 + 0.334229 + 0.334229 + 0.334473 + 0.334473 + 0.334473 + 0.334473 + 0.334473 + 0.334473 + 0.334473 + 0.334717 + 0.334717 + 0.334717 + 0.334717 + 0.334717 + 0.334717 + 0.334717 + 0.334717 + 0.334961 + 0.334961 + 0.334961 + 0.334961 + 0.334961 + 0.334961 + 0.334961 + 0.335205 + 0.335205 + 0.335205 + 0.335205 + 0.335205 + 0.335205 + 0.335205 + 0.335449 + 0.335449 + 0.335449 + 0.335449 + 0.335449 + 0.335449 + 0.335449 + 0.335693 + 0.335693 + 0.335693 + 0.335693 + 0.335693 + 0.335693 + 0.335693 + 0.335693 + 0.335938 + 0.335938 + 0.335938 + 0.335938 + 0.335938 + 0.335938 + 0.335938 + 0.336182 + 0.336182 + 0.336182 + 0.336182 + 0.336182 + 0.336182 + 0.336182 + 0.336426 + 0.336426 + 0.336426 + 0.336426 + 0.336426 + 0.336426 + 0.336426 + 0.336670 + 0.336670 + 0.336670 + 0.336670 + 0.336670 + 0.336670 + 0.336670 + 0.336670 + 0.336914 + 0.336914 + 0.336914 + 0.336914 + 0.336914 + 0.336914 + 0.336914 + 0.337158 + 0.337158 + 0.337158 + 0.337158 + 0.337158 + 0.337158 + 0.337158 + 0.337402 + 0.337402 + 0.337402 + 0.337402 + 0.337402 + 0.337402 + 0.337402 + 0.337402 + 0.337646 + 0.337646 + 0.337646 + 0.337646 + 0.337646 + 0.337646 + 0.337646 + 0.337891 + 0.337891 + 0.337891 + 0.337891 + 0.337891 + 0.337891 + 0.337891 + 0.338135 + 0.338135 + 0.338135 + 0.338135 + 0.338135 + 0.338135 + 0.338135 + 0.338135 + 0.338379 + 0.338379 + 0.338379 + 0.338379 + 0.338379 + 0.338379 + 0.338379 + 0.338623 + 0.338623 + 0.338623 + 0.338623 + 0.338623 + 0.338623 + 0.338623 + 0.338867 + 0.338867 + 0.338867 + 0.338867 + 0.338867 + 0.338867 + 0.338867 + 0.338867 + 0.339111 + 0.339111 + 0.339111 + 0.339111 + 0.339111 + 0.339111 + 0.339111 + 0.339355 + 0.339355 + 0.339355 + 0.339355 + 0.339355 + 0.339355 + 0.339355 + 0.339355 + 0.339600 + 0.339600 + 0.339600 + 0.339600 + 0.339600 + 0.339600 + 0.339600 + 0.339844 + 0.339844 + 0.339844 + 0.339844 + 0.339844 + 0.339844 + 0.339844 + 0.340088 + 0.340088 + 0.340088 + 0.340088 + 0.340088 + 0.340088 + 0.340088 + 0.340088 + 0.340332 + 0.340332 + 0.340332 + 0.340332 + 0.340332 + 0.340332 + 0.340332 + 0.340576 + 0.340576 + 0.340576 + 0.340576 + 0.340576 + 0.340576 + 0.340576 + 0.340576 + 0.340820 + 0.340820 + 0.340820 + 0.340820 + 0.340820 + 0.340820 + 0.340820 + 0.341064 + 0.341064 + 0.341064 + 0.341064 + 0.341064 + 0.341064 + 0.341064 + 0.341064 + 0.341309 + 0.341309 + 0.341309 + 0.341309 + 0.341309 + 0.341309 + 0.341309 + 0.341553 + 0.341553 + 0.341553 + 0.341553 + 0.341553 + 0.341553 + 0.341553 + 0.341797 + 0.341797 + 0.341797 + 0.341797 + 0.341797 + 0.341797 + 0.341797 + 0.341797 + 0.342041 + 0.342041 + 0.342041 + 0.342041 + 0.342041 + 0.342041 + 0.342041 + 0.342285 + 0.342285 + 0.342285 + 0.342285 + 0.342285 + 0.342285 + 0.342285 + 0.342285 + 0.342529 + 0.342529 + 0.342529 + 0.342529 + 0.342529 + 0.342529 + 0.342529 + 0.342773 + 0.342773 + 0.342773 + 0.342773 + 0.342773 + 0.342773 + 0.342773 + 0.342773 + 0.343018 + 0.343018 + 0.343018 + 0.343018 + 0.343018 + 0.343018 + 0.343018 + 0.343262 + 0.343262 + 0.343262 + 0.343262 + 0.343262 + 0.343262 + 0.343262 + 0.343262 + 0.343506 + 0.343506 + 0.343506 + 0.343506 + 0.343506 + 0.343506 + 0.343506 + 0.343506 + 0.343750 + 0.343750 + 0.343750 + 0.343750 + 0.343750 + 0.343750 + 0.343750 + 0.343994 + 0.343994 + 0.343994 + 0.343994 + 0.343994 + 0.343994 + 0.343994 + 0.343994 + 0.344238 + 0.344238 + 0.344238 + 0.344238 + 0.344238 + 0.344238 + 0.344238 + 0.344482 + 0.344482 + 0.344482 + 0.344482 + 0.344482 + 0.344482 + 0.344482 + 0.344482 + 0.344727 + 0.344727 + 0.344727 + 0.344727 + 0.344727 + 0.344727 + 0.344727 + 0.344971 + 0.344971 + 0.344971 + 0.344971 + 0.344971 + 0.344971 + 0.344971 + 0.344971 + 0.345215 + 0.345215 + 0.345215 + 0.345215 + 0.345215 + 0.345215 + 0.345215 + 0.345459 + 0.345459 + 0.345459 + 0.345459 + 0.345459 + 0.345459 + 0.345459 + 0.345459 + 0.345703 + 0.345703 + 0.345703 + 0.345703 + 0.345703 + 0.345703 + 0.345703 + 0.345703 + 0.345947 + 0.345947 + 0.345947 + 0.345947 + 0.345947 + 0.345947 + 0.345947 + 0.346191 + 0.346191 + 0.346191 + 0.346191 + 0.346191 + 0.346191 + 0.346191 + 0.346191 + 0.346436 + 0.346436 + 0.346436 + 0.346436 + 0.346436 + 0.346436 + 0.346436 + 0.346436 + 0.346680 + 0.346680 + 0.346680 + 0.346680 + 0.346680 + 0.346680 + 0.346680 + 0.346924 + 0.346924 + 0.346924 + 0.346924 + 0.346924 + 0.346924 + 0.346924 + 0.346924 + 0.347168 + 0.347168 + 0.347168 + 0.347168 + 0.347168 + 0.347168 + 0.347168 + 0.347168 + 0.347412 + 0.347412 + 0.347412 + 0.347412 + 0.347412 + 0.347412 + 0.347412 + 0.347656 + 0.347656 + 0.347656 + 0.347656 + 0.347656 + 0.347656 + 0.347656 + 0.347656 + 0.347900 + 0.347900 + 0.347900 + 0.347900 + 0.347900 + 0.347900 + 0.347900 + 0.347900 + 0.348145 + 0.348145 + 0.348145 + 0.348145 + 0.348145 + 0.348145 + 0.348145 + 0.348389 + 0.348389 + 0.348389 + 0.348389 + 0.348389 + 0.348389 + 0.348389 + 0.348389 + 0.348633 + 0.348633 + 0.348633 + 0.348633 + 0.348633 + 0.348633 + 0.348633 + 0.348633 + 0.348877 + 0.348877 + 0.348877 + 0.348877 + 0.348877 + 0.348877 + 0.348877 + 0.349121 + 0.349121 + 0.349121 + 0.349121 + 0.349121 + 0.349121 + 0.349121 + 0.349121 + 0.349365 + 0.349365 + 0.349365 + 0.349365 + 0.349365 + 0.349365 + 0.349365 + 0.349365 + 0.349609 + 0.349609 + 0.349609 + 0.349609 + 0.349609 + 0.349609 + 0.349609 + 0.349609 + 0.349854 + 0.349854 + 0.349854 + 0.349854 + 0.349854 + 0.349854 + 0.349854 + 0.350098 + 0.350098 + 0.350098 + 0.350098 + 0.350098 + 0.350098 + 0.350098 + 0.350098 + 0.350342 + 0.350342 + 0.350342 + 0.350342 + 0.350342 + 0.350342 + 0.350342 + 0.350342 + 0.350586 + 0.350586 + 0.350586 + 0.350586 + 0.350586 + 0.350586 + 0.350586 + 0.350586 + 0.350830 + 0.350830 + 0.350830 + 0.350830 + 0.350830 + 0.350830 + 0.350830 + 0.350830 + 0.351074 + 0.351074 + 0.351074 + 0.351074 + 0.351074 + 0.351074 + 0.351074 + 0.351318 + 0.351318 + 0.351318 + 0.351318 + 0.351318 + 0.351318 + 0.351318 + 0.351318 + 0.351562 + 0.351562 + 0.351562 + 0.351562 + 0.351562 + 0.351562 + 0.351562 + 0.351562 + 0.351807 + 0.351807 + 0.351807 + 0.351807 + 0.351807 + 0.351807 + 0.351807 + 0.351807 + 0.352051 + 0.352051 + 0.352051 + 0.352051 + 0.352051 + 0.352051 + 0.352051 + 0.352051 + 0.352295 + 0.352295 + 0.352295 + 0.352295 + 0.352295 + 0.352295 + 0.352295 + 0.352295 + 0.352539 + 0.352539 + 0.352539 + 0.352539 + 0.352539 + 0.352539 + 0.352539 + 0.352783 + 0.352783 + 0.352783 + 0.352783 + 0.352783 + 0.352783 + 0.352783 + 0.352783 + 0.353027 + 0.353027 + 0.353027 + 0.353027 + 0.353027 + 0.353027 + 0.353027 + 0.353027 + 0.353271 + 0.353271 + 0.353271 + 0.353271 + 0.353271 + 0.353271 + 0.353271 + 0.353271 + 0.353516 + 0.353516 + 0.353516 + 0.353516 + 0.353516 + 0.353516 + 0.353516 + 0.353516 + 0.353760 + 0.353760 + 0.353760 + 0.353760 + 0.353760 + 0.353760 + 0.353760 + 0.353760 + 0.354004 + 0.354004 + 0.354004 + 0.354004 + 0.354004 + 0.354004 + 0.354004 + 0.354004 + 0.354248 + 0.354248 + 0.354248 + 0.354248 + 0.354248 + 0.354248 + 0.354248 + 0.354248 + 0.354492 + 0.354492 + 0.354492 + 0.354492 + 0.354492 + 0.354492 + 0.354492 + 0.354492 + 0.354736 + 0.354736 + 0.354736 + 0.354736 + 0.354736 + 0.354736 + 0.354736 + 0.354980 + 0.354980 + 0.354980 + 0.354980 + 0.354980 + 0.354980 + 0.354980 + 0.354980 + 0.355225 + 0.355225 + 0.355225 + 0.355225 + 0.355225 + 0.355225 + 0.355225 + 0.355225 + 0.355469 + 0.355469 + 0.355469 + 0.355469 + 0.355469 + 0.355469 + 0.355469 + 0.355469 + 0.355713 + 0.355713 + 0.355713 + 0.355713 + 0.355713 + 0.355713 + 0.355713 + 0.355713 + 0.355957 + 0.355957 + 0.355957 + 0.355957 + 0.355957 + 0.355957 + 0.355957 + 0.355957 + 0.356201 + 0.356201 + 0.356201 + 0.356201 + 0.356201 + 0.356201 + 0.356201 + 0.356201 + 0.356445 + 0.356445 + 0.356445 + 0.356445 + 0.356445 + 0.356445 + 0.356445 + 0.356445 + 0.356689 + 0.356689 + 0.356689 + 0.356689 + 0.356689 + 0.356689 + 0.356689 + 0.356689 + 0.356934 + 0.356934 + 0.356934 + 0.356934 + 0.356934 + 0.356934 + 0.356934 + 0.356934 + 0.357178 + 0.357178 + 0.357178 + 0.357178 + 0.357178 + 0.357178 + 0.357178 + 0.357178 + 0.357422 + 0.357422 + 0.357422 + 0.357422 + 0.357422 + 0.357422 + 0.357422 + 0.357422 + 0.357666 + 0.357666 + 0.357666 + 0.357666 + 0.357666 + 0.357666 + 0.357666 + 0.357666 + 0.357910 + 0.357910 + 0.357910 + 0.357910 + 0.357910 + 0.357910 + 0.357910 + 0.357910 + 0.358154 + 0.358154 + 0.358154 + 0.358154 + 0.358154 + 0.358154 + 0.358154 + 0.358154 + 0.358398 + 0.358398 + 0.358398 + 0.358398 + 0.358398 + 0.358398 + 0.358398 + 0.358398 + 0.358398 + 0.358643 + 0.358643 + 0.358643 + 0.358643 + 0.358643 + 0.358643 + 0.358643 + 0.358643 + 0.358887 + 0.358887 + 0.358887 + 0.358887 + 0.358887 + 0.358887 + 0.358887 + 0.358887 + 0.359131 + 0.359131 + 0.359131 + 0.359131 + 0.359131 + 0.359131 + 0.359131 + 0.359131 + 0.359375 + 0.359375 + 0.359375 + 0.359375 + 0.359375 + 0.359375 + 0.359375 + 0.359375 + 0.359619 + 0.359619 + 0.359619 + 0.359619 + 0.359619 + 0.359619 + 0.359619 + 0.359619 + 0.359863 + 0.359863 + 0.359863 + 0.359863 + 0.359863 + 0.359863 + 0.359863 + 0.359863 + 0.360107 + 0.360107 + 0.360107 + 0.360107 + 0.360107 + 0.360107 + 0.360107 + 0.360107 + 0.360352 + 0.360352 + 0.360352 + 0.360352 + 0.360352 + 0.360352 + 0.360352 + 0.360352 + 0.360596 + 0.360596 + 0.360596 + 0.360596 + 0.360596 + 0.360596 + 0.360596 + 0.360596 + 0.360840 + 0.360840 + 0.360840 + 0.360840 + 0.360840 + 0.360840 + 0.360840 + 0.360840 + 0.360840 + 0.361084 + 0.361084 + 0.361084 + 0.361084 + 0.361084 + 0.361084 + 0.361084 + 0.361084 + 0.361328 + 0.361328 + 0.361328 + 0.361328 + 0.361328 + 0.361328 + 0.361328 + 0.361328 + 0.361572 + 0.361572 + 0.361572 + 0.361572 + 0.361572 + 0.361572 + 0.361572 + 0.361572 + 0.361816 + 0.361816 + 0.361816 + 0.361816 + 0.361816 + 0.361816 + 0.361816 + 0.361816 + 0.362061 + 0.362061 + 0.362061 + 0.362061 + 0.362061 + 0.362061 + 0.362061 + 0.362061 + 0.362061 + 0.362305 + 0.362305 + 0.362305 + 0.362305 + 0.362305 + 0.362305 + 0.362305 + 0.362305 + 0.362549 + 0.362549 + 0.362549 + 0.362549 + 0.362549 + 0.362549 + 0.362549 + 0.362549 + 0.362793 + 0.362793 + 0.362793 + 0.362793 + 0.362793 + 0.362793 + 0.362793 + 0.362793 + 0.363037 + 0.363037 + 0.363037 + 0.363037 + 0.363037 + 0.363037 + 0.363037 + 0.363037 + 0.363281 + 0.363281 + 0.363281 + 0.363281 + 0.363281 + 0.363281 + 0.363281 + 0.363281 + 0.363281 + 0.363525 + 0.363525 + 0.363525 + 0.363525 + 0.363525 + 0.363525 + 0.363525 + 0.363525 + 0.363770 + 0.363770 + 0.363770 + 0.363770 + 0.363770 + 0.363770 + 0.363770 + 0.363770 + 0.364014 + 0.364014 + 0.364014 + 0.364014 + 0.364014 + 0.364014 + 0.364014 + 0.364014 + 0.364258 + 0.364258 + 0.364258 + 0.364258 + 0.364258 + 0.364258 + 0.364258 + 0.364258 + 0.364258 + 0.364502 + 0.364502 + 0.364502 + 0.364502 + 0.364502 + 0.364502 + 0.364502 + 0.364502 + 0.364746 + 0.364746 + 0.364746 + 0.364746 + 0.364746 + 0.364746 + 0.364746 + 0.364746 + 0.364990 + 0.364990 + 0.364990 + 0.364990 + 0.364990 + 0.364990 + 0.364990 + 0.364990 + 0.364990 + 0.365234 + 0.365234 + 0.365234 + 0.365234 + 0.365234 + 0.365234 + 0.365234 + 0.365234 + 0.365479 + 0.365479 + 0.365479 + 0.365479 + 0.365479 + 0.365479 + 0.365479 + 0.365479 + 0.365723 + 0.365723 + 0.365723 + 0.365723 + 0.365723 + 0.365723 + 0.365723 + 0.365723 + 0.365723 + 0.365967 + 0.365967 + 0.365967 + 0.365967 + 0.365967 + 0.365967 + 0.365967 + 0.365967 + 0.366211 + 0.366211 + 0.366211 + 0.366211 + 0.366211 + 0.366211 + 0.366211 + 0.366211 + 0.366455 + 0.366455 + 0.366455 + 0.366455 + 0.366455 + 0.366455 + 0.366455 + 0.366455 + 0.366455 + 0.366699 + 0.366699 + 0.366699 + 0.366699 + 0.366699 + 0.366699 + 0.366699 + 0.366699 + 0.366943 + 0.366943 + 0.366943 + 0.366943 + 0.366943 + 0.366943 + 0.366943 + 0.366943 + 0.367188 + 0.367188 + 0.367188 + 0.367188 + 0.367188 + 0.367188 + 0.367188 + 0.367188 + 0.367188 + 0.367432 + 0.367432 + 0.367432 + 0.367432 + 0.367432 + 0.367432 + 0.367432 + 0.367432 + 0.367676 + 0.367676 + 0.367676 + 0.367676 + 0.367676 + 0.367676 + 0.367676 + 0.367676 + 0.367676 + 0.367920 + 0.367920 + 0.367920 + 0.367920 + 0.367920 + 0.367920 + 0.367920 + 0.367920 + 0.368164 + 0.368164 + 0.368164 + 0.368164 + 0.368164 + 0.368164 + 0.368164 + 0.368164 + 0.368408 + 0.368408 + 0.368408 + 0.368408 + 0.368408 + 0.368408 + 0.368408 + 0.368408 + 0.368408 + 0.368652 + 0.368652 + 0.368652 + 0.368652 + 0.368652 + 0.368652 + 0.368652 + 0.368652 + 0.368896 + 0.368896 + 0.368896 + 0.368896 + 0.368896 + 0.368896 + 0.368896 + 0.368896 + 0.368896 + 0.369141 + 0.369141 + 0.369141 + 0.369141 + 0.369141 + 0.369141 + 0.369141 + 0.369141 + 0.369385 + 0.369385 + 0.369385 + 0.369385 + 0.369385 + 0.369385 + 0.369385 + 0.369385 + 0.369385 + 0.369629 + 0.369629 + 0.369629 + 0.369629 + 0.369629 + 0.369629 + 0.369629 + 0.369629 + 0.369873 + 0.369873 + 0.369873 + 0.369873 + 0.369873 + 0.369873 + 0.369873 + 0.369873 + 0.369873 + 0.370117 + 0.370117 + 0.370117 + 0.370117 + 0.370117 + 0.370117 + 0.370117 + 0.370117 + 0.370361 + 0.370361 + 0.370361 + 0.370361 + 0.370361 + 0.370361 + 0.370361 + 0.370361 + 0.370361 + 0.370605 + 0.370605 + 0.370605 + 0.370605 + 0.370605 + 0.370605 + 0.370605 + 0.370605 + 0.370850 + 0.370850 + 0.370850 + 0.370850 + 0.370850 + 0.370850 + 0.370850 + 0.370850 + 0.370850 + 0.371094 + 0.371094 + 0.371094 + 0.371094 + 0.371094 + 0.371094 + 0.371094 + 0.371094 + 0.371338 + 0.371338 + 0.371338 + 0.371338 + 0.371338 + 0.371338 + 0.371338 + 0.371338 + 0.371338 + 0.371582 + 0.371582 + 0.371582 + 0.371582 + 0.371582 + 0.371582 + 0.371582 + 0.371582 + 0.371826 + 0.371826 + 0.371826 + 0.371826 + 0.371826 + 0.371826 + 0.371826 + 0.371826 + 0.371826 + 0.372070 + 0.372070 + 0.372070 + 0.372070 + 0.372070 + 0.372070 + 0.372070 + 0.372070 + 0.372314 + 0.372314 + 0.372314 + 0.372314 + 0.372314 + 0.372314 + 0.372314 + 0.372314 + 0.372314 + 0.372559 + 0.372559 + 0.372559 + 0.372559 + 0.372559 + 0.372559 + 0.372559 + 0.372559 + 0.372803 + 0.372803 + 0.372803 + 0.372803 + 0.372803 + 0.372803 + 0.372803 + 0.372803 + 0.372803 + 0.373047 + 0.373047 + 0.373047 + 0.373047 + 0.373047 + 0.373047 + 0.373047 + 0.373047 + 0.373047 + 0.373291 + 0.373291 + 0.373291 + 0.373291 + 0.373291 + 0.373291 + 0.373291 + 0.373291 + 0.373535 + 0.373535 + 0.373535 + 0.373535 + 0.373535 + 0.373535 + 0.373535 + 0.373535 + 0.373535 + 0.373779 + 0.373779 + 0.373779 + 0.373779 + 0.373779 + 0.373779 + 0.373779 + 0.373779 + 0.374023 + 0.374023 + 0.374023 + 0.374023 + 0.374023 + 0.374023 + 0.374023 + 0.374023 + 0.374023 + 0.374268 + 0.374268 + 0.374268 + 0.374268 + 0.374268 + 0.374268 + 0.374268 + 0.374268 + 0.374268 + 0.374512 + 0.374512 + 0.374512 + 0.374512 + 0.374512 + 0.374512 + 0.374512 + 0.374512 + 0.374756 + 0.374756 + 0.374756 + 0.374756 + 0.374756 + 0.374756 + 0.374756 + 0.374756 + 0.374756 + 0.375000 + 0.375000 + 0.375000 + 0.375000 + 0.375000 + 0.375000 + 0.375000 + 0.375000 + 0.375000 + 0.375244 + 0.375244 + 0.375244 + 0.375244 + 0.375244 + 0.375244 + 0.375244 + 0.375244 + 0.375488 + 0.375488 + 0.375488 + 0.375488 + 0.375488 + 0.375488 + 0.375488 + 0.375488 + 0.375488 + 0.375732 + 0.375732 + 0.375732 + 0.375732 + 0.375732 + 0.375732 + 0.375732 + 0.375732 + 0.375732 + 0.375977 + 0.375977 + 0.375977 + 0.375977 + 0.375977 + 0.375977 + 0.375977 + 0.375977 + 0.376221 + 0.376221 + 0.376221 + 0.376221 + 0.376221 + 0.376221 + 0.376221 + 0.376221 + 0.376221 + 0.376465 + 0.376465 + 0.376465 + 0.376465 + 0.376465 + 0.376465 + 0.376465 + 0.376465 + 0.376465 + 0.376709 + 0.376709 + 0.376709 + 0.376709 + 0.376709 + 0.376709 + 0.376709 + 0.376709 + 0.376709 + 0.376953 + 0.376953 + 0.376953 + 0.376953 + 0.376953 + 0.376953 + 0.376953 + 0.376953 + 0.377197 + 0.377197 + 0.377197 + 0.377197 + 0.377197 + 0.377197 + 0.377197 + 0.377197 + 0.377197 + 0.377441 + 0.377441 + 0.377441 + 0.377441 + 0.377441 + 0.377441 + 0.377441 + 0.377441 + 0.377441 + 0.377686 + 0.377686 + 0.377686 + 0.377686 + 0.377686 + 0.377686 + 0.377686 + 0.377686 + 0.377686 + 0.377930 + 0.377930 + 0.377930 + 0.377930 + 0.377930 + 0.377930 + 0.377930 + 0.377930 + 0.378174 + 0.378174 + 0.378174 + 0.378174 + 0.378174 + 0.378174 + 0.378174 + 0.378174 + 0.378174 + 0.378418 + 0.378418 + 0.378418 + 0.378418 + 0.378418 + 0.378418 + 0.378418 + 0.378418 + 0.378418 + 0.378662 + 0.378662 + 0.378662 + 0.378662 + 0.378662 + 0.378662 + 0.378662 + 0.378662 + 0.378662 + 0.378906 + 0.378906 + 0.378906 + 0.378906 + 0.378906 + 0.378906 + 0.378906 + 0.378906 + 0.378906 + 0.379150 + 0.379150 + 0.379150 + 0.379150 + 0.379150 + 0.379150 + 0.379150 + 0.379150 + 0.379395 + 0.379395 + 0.379395 + 0.379395 + 0.379395 + 0.379395 + 0.379395 + 0.379395 + 0.379395 + 0.379639 + 0.379639 + 0.379639 + 0.379639 + 0.379639 + 0.379639 + 0.379639 + 0.379639 + 0.379639 + 0.379883 + 0.379883 + 0.379883 + 0.379883 + 0.379883 + 0.379883 + 0.379883 + 0.379883 + 0.379883 + 0.380127 + 0.380127 + 0.380127 + 0.380127 + 0.380127 + 0.380127 + 0.380127 + 0.380127 + 0.380127 + 0.380371 + 0.380371 + 0.380371 + 0.380371 + 0.380371 + 0.380371 + 0.380371 + 0.380371 + 0.380371 + 0.380615 + 0.380615 + 0.380615 + 0.380615 + 0.380615 + 0.380615 + 0.380615 + 0.380615 + 0.380615 + 0.380859 + 0.380859 + 0.380859 + 0.380859 + 0.380859 + 0.380859 + 0.380859 + 0.380859 + 0.380859 + 0.381104 + 0.381104 + 0.381104 + 0.381104 + 0.381104 + 0.381104 + 0.381104 + 0.381104 + 0.381348 + 0.381348 + 0.381348 + 0.381348 + 0.381348 + 0.381348 + 0.381348 + 0.381348 + 0.381348 + 0.381592 + 0.381592 + 0.381592 + 0.381592 + 0.381592 + 0.381592 + 0.381592 + 0.381592 + 0.381592 + 0.381836 + 0.381836 + 0.381836 + 0.381836 + 0.381836 + 0.381836 + 0.381836 + 0.381836 + 0.381836 + 0.382080 + 0.382080 + 0.382080 + 0.382080 + 0.382080 + 0.382080 + 0.382080 + 0.382080 + 0.382080 + 0.382324 + 0.382324 + 0.382324 + 0.382324 + 0.382324 + 0.382324 + 0.382324 + 0.382324 + 0.382324 + 0.382568 + 0.382568 + 0.382568 + 0.382568 + 0.382568 + 0.382568 + 0.382568 + 0.382568 + 0.382568 + 0.382812 + 0.382812 + 0.382812 + 0.382812 + 0.382812 + 0.382812 + 0.382812 + 0.382812 + 0.382812 + 0.383057 + 0.383057 + 0.383057 + 0.383057 + 0.383057 + 0.383057 + 0.383057 + 0.383057 + 0.383057 + 0.383301 + 0.383301 + 0.383301 + 0.383301 + 0.383301 + 0.383301 + 0.383301 + 0.383301 + 0.383301 + 0.383545 + 0.383545 + 0.383545 + 0.383545 + 0.383545 + 0.383545 + 0.383545 + 0.383545 + 0.383545 + 0.383789 + 0.383789 + 0.383789 + 0.383789 + 0.383789 + 0.383789 + 0.383789 + 0.383789 + 0.383789 + 0.384033 + 0.384033 + 0.384033 + 0.384033 + 0.384033 + 0.384033 + 0.384033 + 0.384033 + 0.384033 + 0.384277 + 0.384277 + 0.384277 + 0.384277 + 0.384277 + 0.384277 + 0.384277 + 0.384277 + 0.384277 + 0.384521 + 0.384521 + 0.384521 + 0.384521 + 0.384521 + 0.384521 + 0.384521 + 0.384521 + 0.384521 + 0.384766 + 0.384766 + 0.384766 + 0.384766 + 0.384766 + 0.384766 + 0.384766 + 0.384766 + 0.384766 + 0.385010 + 0.385010 + 0.385010 + 0.385010 + 0.385010 + 0.385010 + 0.385010 + 0.385010 + 0.385010 + 0.385254 + 0.385254 + 0.385254 + 0.385254 + 0.385254 + 0.385254 + 0.385254 + 0.385254 + 0.385254 + 0.385498 + 0.385498 + 0.385498 + 0.385498 + 0.385498 + 0.385498 + 0.385498 + 0.385498 + 0.385498 + 0.385742 + 0.385742 + 0.385742 + 0.385742 + 0.385742 + 0.385742 + 0.385742 + 0.385742 + 0.385742 + 0.385986 + 0.385986 + 0.385986 + 0.385986 + 0.385986 + 0.385986 + 0.385986 + 0.385986 + 0.385986 + 0.386230 + 0.386230 + 0.386230 + 0.386230 + 0.386230 + 0.386230 + 0.386230 + 0.386230 + 0.386230 + 0.386475 + 0.386475 + 0.386475 + 0.386475 + 0.386475 + 0.386475 + 0.386475 + 0.386475 + 0.386475 + 0.386719 + 0.386719 + 0.386719 + 0.386719 + 0.386719 + 0.386719 + 0.386719 + 0.386719 + 0.386719 + 0.386719 + 0.386963 + 0.386963 + 0.386963 + 0.386963 + 0.386963 + 0.386963 + 0.386963 + 0.386963 + 0.386963 + 0.387207 + 0.387207 + 0.387207 + 0.387207 + 0.387207 + 0.387207 + 0.387207 + 0.387207 + 0.387207 + 0.387451 + 0.387451 + 0.387451 + 0.387451 + 0.387451 + 0.387451 + 0.387451 + 0.387451 + 0.387451 + 0.387695 + 0.387695 + 0.387695 + 0.387695 + 0.387695 + 0.387695 + 0.387695 + 0.387695 + 0.387695 + 0.387939 + 0.387939 + 0.387939 + 0.387939 + 0.387939 + 0.387939 + 0.387939 + 0.387939 + 0.387939 + 0.388184 + 0.388184 + 0.388184 + 0.388184 + 0.388184 + 0.388184 + 0.388184 + 0.388184 + 0.388184 + 0.388428 + 0.388428 + 0.388428 + 0.388428 + 0.388428 + 0.388428 + 0.388428 + 0.388428 + 0.388428 + 0.388428 + 0.388672 + 0.388672 + 0.388672 + 0.388672 + 0.388672 + 0.388672 + 0.388672 + 0.388672 + 0.388672 + 0.388916 + 0.388916 + 0.388916 + 0.388916 + 0.388916 + 0.388916 + 0.388916 + 0.388916 + 0.388916 + 0.389160 + 0.389160 + 0.389160 + 0.389160 + 0.389160 + 0.389160 + 0.389160 + 0.389160 + 0.389160 + 0.389404 + 0.389404 + 0.389404 + 0.389404 + 0.389404 + 0.389404 + 0.389404 + 0.389404 + 0.389404 + 0.389648 + 0.389648 + 0.389648 + 0.389648 + 0.389648 + 0.389648 + 0.389648 + 0.389648 + 0.389648 + 0.389648 + 0.389893 + 0.389893 + 0.389893 + 0.389893 + 0.389893 + 0.389893 + 0.389893 + 0.389893 + 0.389893 + 0.390137 + 0.390137 + 0.390137 + 0.390137 + 0.390137 + 0.390137 + 0.390137 + 0.390137 + 0.390137 + 0.390381 + 0.390381 + 0.390381 + 0.390381 + 0.390381 + 0.390381 + 0.390381 + 0.390381 + 0.390381 + 0.390625 + 0.390625 + 0.390625 + 0.390625 + 0.390625 + 0.390625 + 0.390625 + 0.390625 + 0.390625 + 0.390625 + 0.390869 + 0.390869 + 0.390869 + 0.390869 + 0.390869 + 0.390869 + 0.390869 + 0.390869 + 0.390869 + 0.391113 + 0.391113 + 0.391113 + 0.391113 + 0.391113 + 0.391113 + 0.391113 + 0.391113 + 0.391113 + 0.391357 + 0.391357 + 0.391357 + 0.391357 + 0.391357 + 0.391357 + 0.391357 + 0.391357 + 0.391357 + 0.391602 + 0.391602 + 0.391602 + 0.391602 + 0.391602 + 0.391602 + 0.391602 + 0.391602 + 0.391602 + 0.391602 + 0.391846 + 0.391846 + 0.391846 + 0.391846 + 0.391846 + 0.391846 + 0.391846 + 0.391846 + 0.391846 + 0.392090 + 0.392090 + 0.392090 + 0.392090 + 0.392090 + 0.392090 + 0.392090 + 0.392090 + 0.392090 + 0.392334 + 0.392334 + 0.392334 + 0.392334 + 0.392334 + 0.392334 + 0.392334 + 0.392334 + 0.392334 + 0.392334 + 0.392578 + 0.392578 + 0.392578 + 0.392578 + 0.392578 + 0.392578 + 0.392578 + 0.392578 + 0.392578 + 0.392822 + 0.392822 + 0.392822 + 0.392822 + 0.392822 + 0.392822 + 0.392822 + 0.392822 + 0.392822 + 0.393066 + 0.393066 + 0.393066 + 0.393066 + 0.393066 + 0.393066 + 0.393066 + 0.393066 + 0.393066 + 0.393066 + 0.393311 + 0.393311 + 0.393311 + 0.393311 + 0.393311 + 0.393311 + 0.393311 + 0.393311 + 0.393311 + 0.393555 + 0.393555 + 0.393555 + 0.393555 + 0.393555 + 0.393555 + 0.393555 + 0.393555 + 0.393555 + 0.393799 + 0.393799 + 0.393799 + 0.393799 + 0.393799 + 0.393799 + 0.393799 + 0.393799 + 0.393799 + 0.393799 + 0.394043 + 0.394043 + 0.394043 + 0.394043 + 0.394043 + 0.394043 + 0.394043 + 0.394043 + 0.394043 + 0.394287 + 0.394287 + 0.394287 + 0.394287 + 0.394287 + 0.394287 + 0.394287 + 0.394287 + 0.394287 + 0.394531 + 0.394531 + 0.394531 + 0.394531 + 0.394531 + 0.394531 + 0.394531 + 0.394531 + 0.394531 + 0.394531 + 0.394775 + 0.394775 + 0.394775 + 0.394775 + 0.394775 + 0.394775 + 0.394775 + 0.394775 + 0.394775 + 0.395020 + 0.395020 + 0.395020 + 0.395020 + 0.395020 + 0.395020 + 0.395020 + 0.395020 + 0.395020 + 0.395020 + 0.395264 + 0.395264 + 0.395264 + 0.395264 + 0.395264 + 0.395264 + 0.395264 + 0.395264 + 0.395264 + 0.395508 + 0.395508 + 0.395508 + 0.395508 + 0.395508 + 0.395508 + 0.395508 + 0.395508 + 0.395508 + 0.395508 + 0.395752 + 0.395752 + 0.395752 + 0.395752 + 0.395752 + 0.395752 + 0.395752 + 0.395752 + 0.395752 + 0.395996 + 0.395996 + 0.395996 + 0.395996 + 0.395996 + 0.395996 + 0.395996 + 0.395996 + 0.395996 + 0.395996 + 0.396240 + 0.396240 + 0.396240 + 0.396240 + 0.396240 + 0.396240 + 0.396240 + 0.396240 + 0.396240 + 0.396484 + 0.396484 + 0.396484 + 0.396484 + 0.396484 + 0.396484 + 0.396484 + 0.396484 + 0.396484 + 0.396729 + 0.396729 + 0.396729 + 0.396729 + 0.396729 + 0.396729 + 0.396729 + 0.396729 + 0.396729 + 0.396729 + 0.396973 + 0.396973 + 0.396973 + 0.396973 + 0.396973 + 0.396973 + 0.396973 + 0.396973 + 0.396973 + 0.397217 + 0.397217 + 0.397217 + 0.397217 + 0.397217 + 0.397217 + 0.397217 + 0.397217 + 0.397217 + 0.397217 + 0.397461 + 0.397461 + 0.397461 + 0.397461 + 0.397461 + 0.397461 + 0.397461 + 0.397461 + 0.397461 + 0.397705 + 0.397705 + 0.397705 + 0.397705 + 0.397705 + 0.397705 + 0.397705 + 0.397705 + 0.397705 + 0.397705 + 0.397949 + 0.397949 + 0.397949 + 0.397949 + 0.397949 + 0.397949 + 0.397949 + 0.397949 + 0.397949 + 0.397949 + 0.398193 + 0.398193 + 0.398193 + 0.398193 + 0.398193 + 0.398193 + 0.398193 + 0.398193 + 0.398193 + 0.398438 + 0.398438 + 0.398438 + 0.398438 + 0.398438 + 0.398438 + 0.398438 + 0.398438 + 0.398438 + 0.398438 + 0.398682 + 0.398682 + 0.398682 + 0.398682 + 0.398682 + 0.398682 + 0.398682 + 0.398682 + 0.398682 + 0.398926 + 0.398926 + 0.398926 + 0.398926 + 0.398926 + 0.398926 + 0.398926 + 0.398926 + 0.398926 + 0.398926 + 0.399170 + 0.399170 + 0.399170 + 0.399170 + 0.399170 + 0.399170 + 0.399170 + 0.399170 + 0.399170 + 0.399414 + 0.399414 + 0.399414 + 0.399414 + 0.399414 + 0.399414 + 0.399414 + 0.399414 + 0.399414 + 0.399414 + 0.399658 + 0.399658 + 0.399658 + 0.399658 + 0.399658 + 0.399658 + 0.399658 + 0.399658 + 0.399658 + 0.399658 + 0.399902 + 0.399902 + 0.399902 + 0.399902 + 0.399902 + 0.399902 + 0.399902 + 0.399902 + 0.399902 + 0.400146 + 0.400146 + 0.400146 + 0.400146 + 0.400146 + 0.400146 + 0.400146 + 0.400146 + 0.400146 + 0.400146 + 0.400391 + 0.400391 + 0.400391 + 0.400391 + 0.400391 + 0.400391 + 0.400391 + 0.400391 + 0.400391 + 0.400635 + 0.400635 + 0.400635 + 0.400635 + 0.400635 + 0.400635 + 0.400635 + 0.400635 + 0.400635 + 0.400635 + 0.400879 + 0.400879 + 0.400879 + 0.400879 + 0.400879 + 0.400879 + 0.400879 + 0.400879 + 0.400879 + 0.400879 + 0.401123 + 0.401123 + 0.401123 + 0.401123 + 0.401123 + 0.401123 + 0.401123 + 0.401123 + 0.401123 + 0.401367 + 0.401367 + 0.401367 + 0.401367 + 0.401367 + 0.401367 + 0.401367 + 0.401367 + 0.401367 + 0.401367 + 0.401611 + 0.401611 + 0.401611 + 0.401611 + 0.401611 + 0.401611 + 0.401611 + 0.401611 + 0.401611 + 0.401611 + 0.401855 + 0.401855 + 0.401855 + 0.401855 + 0.401855 + 0.401855 + 0.401855 + 0.401855 + 0.401855 + 0.402100 + 0.402100 + 0.402100 + 0.402100 + 0.402100 + 0.402100 + 0.402100 + 0.402100 + 0.402100 + 0.402100 + 0.402344 + 0.402344 + 0.402344 + 0.402344 + 0.402344 + 0.402344 + 0.402344 + 0.402344 + 0.402344 + 0.402344 + 0.402588 + 0.402588 + 0.402588 + 0.402588 + 0.402588 + 0.402588 + 0.402588 + 0.402588 + 0.402588 + 0.402832 + 0.402832 + 0.402832 + 0.402832 + 0.402832 + 0.402832 + 0.402832 + 0.402832 + 0.402832 + 0.402832 + 0.403076 + 0.403076 + 0.403076 + 0.403076 + 0.403076 + 0.403076 + 0.403076 + 0.403076 + 0.403076 + 0.403076 + 0.403320 + 0.403320 + 0.403320 + 0.403320 + 0.403320 + 0.403320 + 0.403320 + 0.403320 + 0.403320 + 0.403320 + 0.403564 + 0.403564 + 0.403564 + 0.403564 + 0.403564 + 0.403564 + 0.403564 + 0.403564 + 0.403564 + 0.403809 + 0.403809 + 0.403809 + 0.403809 + 0.403809 + 0.403809 + 0.403809 + 0.403809 + 0.403809 + 0.403809 + 0.404053 + 0.404053 + 0.404053 + 0.404053 + 0.404053 + 0.404053 + 0.404053 + 0.404053 + 0.404053 + 0.404053 + 0.404297 + 0.404297 + 0.404297 + 0.404297 + 0.404297 + 0.404297 + 0.404297 + 0.404297 + 0.404297 + 0.404297 + 0.404541 + 0.404541 + 0.404541 + 0.404541 + 0.404541 + 0.404541 + 0.404541 + 0.404541 + 0.404541 + 0.404541 + 0.404785 + 0.404785 + 0.404785 + 0.404785 + 0.404785 + 0.404785 + 0.404785 + 0.404785 + 0.404785 + 0.405029 + 0.405029 + 0.405029 + 0.405029 + 0.405029 + 0.405029 + 0.405029 + 0.405029 + 0.405029 + 0.405029 + 0.405273 + 0.405273 + 0.405273 + 0.405273 + 0.405273 + 0.405273 + 0.405273 + 0.405273 + 0.405273 + 0.405273 + 0.405518 + 0.405518 + 0.405518 + 0.405518 + 0.405518 + 0.405518 + 0.405518 + 0.405518 + 0.405518 + 0.405518 + 0.405762 + 0.405762 + 0.405762 + 0.405762 + 0.405762 + 0.405762 + 0.405762 + 0.405762 + 0.405762 + 0.405762 + 0.406006 + 0.406006 + 0.406006 + 0.406006 + 0.406006 + 0.406006 + 0.406006 + 0.406006 + 0.406006 + 0.406250 + 0.406250 + 0.406250 + 0.406250 + 0.406250 + 0.406250 + 0.406250 + 0.406250 + 0.406250 + 0.406250 + 0.406494 + 0.406494 + 0.406494 + 0.406494 + 0.406494 + 0.406494 + 0.406494 + 0.406494 + 0.406494 + 0.406494 + 0.406738 + 0.406738 + 0.406738 + 0.406738 + 0.406738 + 0.406738 + 0.406738 + 0.406738 + 0.406738 + 0.406738 + 0.406982 + 0.406982 + 0.406982 + 0.406982 + 0.406982 + 0.406982 + 0.406982 + 0.406982 + 0.406982 + 0.406982 + 0.407227 + 0.407227 + 0.407227 + 0.407227 + 0.407227 + 0.407227 + 0.407227 + 0.407227 + 0.407227 + 0.407227 + 0.407471 + 0.407471 + 0.407471 + 0.407471 + 0.407471 + 0.407471 + 0.407471 + 0.407471 + 0.407471 + 0.407471 + 0.407715 + 0.407715 + 0.407715 + 0.407715 + 0.407715 + 0.407715 + 0.407715 + 0.407715 + 0.407715 + 0.407715 + 0.407959 + 0.407959 + 0.407959 + 0.407959 + 0.407959 + 0.407959 + 0.407959 + 0.407959 + 0.407959 + 0.407959 + 0.408203 + 0.408203 + 0.408203 + 0.408203 + 0.408203 + 0.408203 + 0.408203 + 0.408203 + 0.408203 + 0.408447 + 0.408447 + 0.408447 + 0.408447 + 0.408447 + 0.408447 + 0.408447 + 0.408447 + 0.408447 + 0.408447 + 0.408691 + 0.408691 + 0.408691 + 0.408691 + 0.408691 + 0.408691 + 0.408691 + 0.408691 + 0.408691 + 0.408691 + 0.408936 + 0.408936 + 0.408936 + 0.408936 + 0.408936 + 0.408936 + 0.408936 + 0.408936 + 0.408936 + 0.408936 + 0.409180 + 0.409180 + 0.409180 + 0.409180 + 0.409180 + 0.409180 + 0.409180 + 0.409180 + 0.409180 + 0.409180 + 0.409424 + 0.409424 + 0.409424 + 0.409424 + 0.409424 + 0.409424 + 0.409424 + 0.409424 + 0.409424 + 0.409424 + 0.409668 + 0.409668 + 0.409668 + 0.409668 + 0.409668 + 0.409668 + 0.409668 + 0.409668 + 0.409668 + 0.409668 + 0.409912 + 0.409912 + 0.409912 + 0.409912 + 0.409912 + 0.409912 + 0.409912 + 0.409912 + 0.409912 + 0.409912 + 0.410156 + 0.410156 + 0.410156 + 0.410156 + 0.410156 + 0.410156 + 0.410156 + 0.410156 + 0.410156 + 0.410156 + 0.410400 + 0.410400 + 0.410400 + 0.410400 + 0.410400 + 0.410400 + 0.410400 + 0.410400 + 0.410400 + 0.410400 + 0.410645 + 0.410645 + 0.410645 + 0.410645 + 0.410645 + 0.410645 + 0.410645 + 0.410645 + 0.410645 + 0.410645 + 0.410889 + 0.410889 + 0.410889 + 0.410889 + 0.410889 + 0.410889 + 0.410889 + 0.410889 + 0.410889 + 0.410889 + 0.411133 + 0.411133 + 0.411133 + 0.411133 + 0.411133 + 0.411133 + 0.411133 + 0.411133 + 0.411133 + 0.411133 + 0.411377 + 0.411377 + 0.411377 + 0.411377 + 0.411377 + 0.411377 + 0.411377 + 0.411377 + 0.411377 + 0.411377 + 0.411621 + 0.411621 + 0.411621 + 0.411621 + 0.411621 + 0.411621 + 0.411621 + 0.411621 + 0.411621 + 0.411621 + 0.411865 + 0.411865 + 0.411865 + 0.411865 + 0.411865 + 0.411865 + 0.411865 + 0.411865 + 0.411865 + 0.411865 + 0.411865 + 0.412109 + 0.412109 + 0.412109 + 0.412109 + 0.412109 + 0.412109 + 0.412109 + 0.412109 + 0.412109 + 0.412109 + 0.412354 + 0.412354 + 0.412354 + 0.412354 + 0.412354 + 0.412354 + 0.412354 + 0.412354 + 0.412354 + 0.412354 + 0.412598 + 0.412598 + 0.412598 + 0.412598 + 0.412598 + 0.412598 + 0.412598 + 0.412598 + 0.412598 + 0.412598 + 0.412842 + 0.412842 + 0.412842 + 0.412842 + 0.412842 + 0.412842 + 0.412842 + 0.412842 + 0.412842 + 0.412842 + 0.413086 + 0.413086 + 0.413086 + 0.413086 + 0.413086 + 0.413086 + 0.413086 + 0.413086 + 0.413086 + 0.413086 + 0.413330 + 0.413330 + 0.413330 + 0.413330 + 0.413330 + 0.413330 + 0.413330 + 0.413330 + 0.413330 + 0.413330 + 0.413574 + 0.413574 + 0.413574 + 0.413574 + 0.413574 + 0.413574 + 0.413574 + 0.413574 + 0.413574 + 0.413574 + 0.413818 + 0.413818 + 0.413818 + 0.413818 + 0.413818 + 0.413818 + 0.413818 + 0.413818 + 0.413818 + 0.413818 + 0.413818 + 0.414062 + 0.414062 + 0.414062 + 0.414062 + 0.414062 + 0.414062 + 0.414062 + 0.414062 + 0.414062 + 0.414062 + 0.414307 + 0.414307 + 0.414307 + 0.414307 + 0.414307 + 0.414307 + 0.414307 + 0.414307 + 0.414307 + 0.414307 + 0.414551 + 0.414551 + 0.414551 + 0.414551 + 0.414551 + 0.414551 + 0.414551 + 0.414551 + 0.414551 + 0.414551 + 0.414795 + 0.414795 + 0.414795 + 0.414795 + 0.414795 + 0.414795 + 0.414795 + 0.414795 + 0.414795 + 0.414795 + 0.415039 + 0.415039 + 0.415039 + 0.415039 + 0.415039 + 0.415039 + 0.415039 + 0.415039 + 0.415039 + 0.415039 + 0.415283 + 0.415283 + 0.415283 + 0.415283 + 0.415283 + 0.415283 + 0.415283 + 0.415283 + 0.415283 + 0.415283 + 0.415283 + 0.415527 + 0.415527 + 0.415527 + 0.415527 + 0.415527 + 0.415527 + 0.415527 + 0.415527 + 0.415527 + 0.415527 + 0.415771 + 0.415771 + 0.415771 + 0.415771 + 0.415771 + 0.415771 + 0.415771 + 0.415771 + 0.415771 + 0.415771 + 0.416016 + 0.416016 + 0.416016 + 0.416016 + 0.416016 + 0.416016 + 0.416016 + 0.416016 + 0.416016 + 0.416016 + 0.416260 + 0.416260 + 0.416260 + 0.416260 + 0.416260 + 0.416260 + 0.416260 + 0.416260 + 0.416260 + 0.416260 + 0.416260 + 0.416504 + 0.416504 + 0.416504 + 0.416504 + 0.416504 + 0.416504 + 0.416504 + 0.416504 + 0.416504 + 0.416504 + 0.416748 + 0.416748 + 0.416748 + 0.416748 + 0.416748 + 0.416748 + 0.416748 + 0.416748 + 0.416748 + 0.416748 + 0.416992 + 0.416992 + 0.416992 + 0.416992 + 0.416992 + 0.416992 + 0.416992 + 0.416992 + 0.416992 + 0.416992 + 0.417236 + 0.417236 + 0.417236 + 0.417236 + 0.417236 + 0.417236 + 0.417236 + 0.417236 + 0.417236 + 0.417236 + 0.417236 + 0.417480 + 0.417480 + 0.417480 + 0.417480 + 0.417480 + 0.417480 + 0.417480 + 0.417480 + 0.417480 + 0.417480 + 0.417725 + 0.417725 + 0.417725 + 0.417725 + 0.417725 + 0.417725 + 0.417725 + 0.417725 + 0.417725 + 0.417725 + 0.417969 + 0.417969 + 0.417969 + 0.417969 + 0.417969 + 0.417969 + 0.417969 + 0.417969 + 0.417969 + 0.417969 + 0.417969 + 0.418213 + 0.418213 + 0.418213 + 0.418213 + 0.418213 + 0.418213 + 0.418213 + 0.418213 + 0.418213 + 0.418213 + 0.418457 + 0.418457 + 0.418457 + 0.418457 + 0.418457 + 0.418457 + 0.418457 + 0.418457 + 0.418457 + 0.418457 + 0.418701 + 0.418701 + 0.418701 + 0.418701 + 0.418701 + 0.418701 + 0.418701 + 0.418701 + 0.418701 + 0.418701 + 0.418701 + 0.418945 + 0.418945 + 0.418945 + 0.418945 + 0.418945 + 0.418945 + 0.418945 + 0.418945 + 0.418945 + 0.418945 + 0.419189 + 0.419189 + 0.419189 + 0.419189 + 0.419189 + 0.419189 + 0.419189 + 0.419189 + 0.419189 + 0.419189 + 0.419434 + 0.419434 + 0.419434 + 0.419434 + 0.419434 + 0.419434 + 0.419434 + 0.419434 + 0.419434 + 0.419434 + 0.419434 + 0.419678 + 0.419678 + 0.419678 + 0.419678 + 0.419678 + 0.419678 + 0.419678 + 0.419678 + 0.419678 + 0.419678 + 0.419922 + 0.419922 + 0.419922 + 0.419922 + 0.419922 + 0.419922 + 0.419922 + 0.419922 + 0.419922 + 0.419922 + 0.420166 + 0.420166 + 0.420166 + 0.420166 + 0.420166 + 0.420166 + 0.420166 + 0.420166 + 0.420166 + 0.420166 + 0.420166 + 0.420410 + 0.420410 + 0.420410 + 0.420410 + 0.420410 + 0.420410 + 0.420410 + 0.420410 + 0.420410 + 0.420410 + 0.420654 + 0.420654 + 0.420654 + 0.420654 + 0.420654 + 0.420654 + 0.420654 + 0.420654 + 0.420654 + 0.420654 + 0.420654 + 0.420898 + 0.420898 + 0.420898 + 0.420898 + 0.420898 + 0.420898 + 0.420898 + 0.420898 + 0.420898 + 0.420898 + 0.421143 + 0.421143 + 0.421143 + 0.421143 + 0.421143 + 0.421143 + 0.421143 + 0.421143 + 0.421143 + 0.421143 + 0.421387 + 0.421387 + 0.421387 + 0.421387 + 0.421387 + 0.421387 + 0.421387 + 0.421387 + 0.421387 + 0.421387 + 0.421387 + 0.421631 + 0.421631 + 0.421631 + 0.421631 + 0.421631 + 0.421631 + 0.421631 + 0.421631 + 0.421631 + 0.421631 + 0.421875 + 0.421875 + 0.421875 + 0.421875 + 0.421875 + 0.421875 + 0.421875 + 0.421875 + 0.421875 + 0.421875 + 0.421875 + 0.422119 + 0.422119 + 0.422119 + 0.422119 + 0.422119 + 0.422119 + 0.422119 + 0.422119 + 0.422119 + 0.422119 + 0.422363 + 0.422363 + 0.422363 + 0.422363 + 0.422363 + 0.422363 + 0.422363 + 0.422363 + 0.422363 + 0.422363 + 0.422363 + 0.422607 + 0.422607 + 0.422607 + 0.422607 + 0.422607 + 0.422607 + 0.422607 + 0.422607 + 0.422607 + 0.422607 + 0.422852 + 0.422852 + 0.422852 + 0.422852 + 0.422852 + 0.422852 + 0.422852 + 0.422852 + 0.422852 + 0.422852 + 0.422852 + 0.423096 + 0.423096 + 0.423096 + 0.423096 + 0.423096 + 0.423096 + 0.423096 + 0.423096 + 0.423096 + 0.423096 + 0.423340 + 0.423340 + 0.423340 + 0.423340 + 0.423340 + 0.423340 + 0.423340 + 0.423340 + 0.423340 + 0.423340 + 0.423340 + 0.423584 + 0.423584 + 0.423584 + 0.423584 + 0.423584 + 0.423584 + 0.423584 + 0.423584 + 0.423584 + 0.423584 + 0.423828 + 0.423828 + 0.423828 + 0.423828 + 0.423828 + 0.423828 + 0.423828 + 0.423828 + 0.423828 + 0.423828 + 0.423828 + 0.424072 + 0.424072 + 0.424072 + 0.424072 + 0.424072 + 0.424072 + 0.424072 + 0.424072 + 0.424072 + 0.424072 + 0.424316 + 0.424316 + 0.424316 + 0.424316 + 0.424316 + 0.424316 + 0.424316 + 0.424316 + 0.424316 + 0.424316 + 0.424316 + 0.424561 + 0.424561 + 0.424561 + 0.424561 + 0.424561 + 0.424561 + 0.424561 + 0.424561 + 0.424561 + 0.424561 + 0.424561 + 0.424805 + 0.424805 + 0.424805 + 0.424805 + 0.424805 + 0.424805 + 0.424805 + 0.424805 + 0.424805 + 0.424805 + 0.425049 + 0.425049 + 0.425049 + 0.425049 + 0.425049 + 0.425049 + 0.425049 + 0.425049 + 0.425049 + 0.425049 + 0.425049 + 0.425293 + 0.425293 + 0.425293 + 0.425293 + 0.425293 + 0.425293 + 0.425293 + 0.425293 + 0.425293 + 0.425293 + 0.425537 + 0.425537 + 0.425537 + 0.425537 + 0.425537 + 0.425537 + 0.425537 + 0.425537 + 0.425537 + 0.425537 + 0.425537 + 0.425781 + 0.425781 + 0.425781 + 0.425781 + 0.425781 + 0.425781 + 0.425781 + 0.425781 + 0.425781 + 0.425781 + 0.425781 + 0.426025 + 0.426025 + 0.426025 + 0.426025 + 0.426025 + 0.426025 + 0.426025 + 0.426025 + 0.426025 + 0.426025 + 0.426270 + 0.426270 + 0.426270 + 0.426270 + 0.426270 + 0.426270 + 0.426270 + 0.426270 + 0.426270 + 0.426270 + 0.426270 + 0.426514 + 0.426514 + 0.426514 + 0.426514 + 0.426514 + 0.426514 + 0.426514 + 0.426514 + 0.426514 + 0.426514 + 0.426514 + 0.426758 + 0.426758 + 0.426758 + 0.426758 + 0.426758 + 0.426758 + 0.426758 + 0.426758 + 0.426758 + 0.426758 + 0.427002 + 0.427002 + 0.427002 + 0.427002 + 0.427002 + 0.427002 + 0.427002 + 0.427002 + 0.427002 + 0.427002 + 0.427002 + 0.427246 + 0.427246 + 0.427246 + 0.427246 + 0.427246 + 0.427246 + 0.427246 + 0.427246 + 0.427246 + 0.427246 + 0.427246 + 0.427490 + 0.427490 + 0.427490 + 0.427490 + 0.427490 + 0.427490 + 0.427490 + 0.427490 + 0.427490 + 0.427490 + 0.427734 + 0.427734 + 0.427734 + 0.427734 + 0.427734 + 0.427734 + 0.427734 + 0.427734 + 0.427734 + 0.427734 + 0.427734 + 0.427979 + 0.427979 + 0.427979 + 0.427979 + 0.427979 + 0.427979 + 0.427979 + 0.427979 + 0.427979 + 0.427979 + 0.427979 + 0.428223 + 0.428223 + 0.428223 + 0.428223 + 0.428223 + 0.428223 + 0.428223 + 0.428223 + 0.428223 + 0.428223 + 0.428467 + 0.428467 + 0.428467 + 0.428467 + 0.428467 + 0.428467 + 0.428467 + 0.428467 + 0.428467 + 0.428467 + 0.428467 + 0.428711 + 0.428711 + 0.428711 + 0.428711 + 0.428711 + 0.428711 + 0.428711 + 0.428711 + 0.428711 + 0.428711 + 0.428711 + 0.428955 + 0.428955 + 0.428955 + 0.428955 + 0.428955 + 0.428955 + 0.428955 + 0.428955 + 0.428955 + 0.428955 + 0.428955 + 0.429199 + 0.429199 + 0.429199 + 0.429199 + 0.429199 + 0.429199 + 0.429199 + 0.429199 + 0.429199 + 0.429199 + 0.429443 + 0.429443 + 0.429443 + 0.429443 + 0.429443 + 0.429443 + 0.429443 + 0.429443 + 0.429443 + 0.429443 + 0.429443 + 0.429688 + 0.429688 + 0.429688 + 0.429688 + 0.429688 + 0.429688 + 0.429688 + 0.429688 + 0.429688 + 0.429688 + 0.429688 + 0.429932 + 0.429932 + 0.429932 + 0.429932 + 0.429932 + 0.429932 + 0.429932 + 0.429932 + 0.429932 + 0.429932 + 0.429932 + 0.430176 + 0.430176 + 0.430176 + 0.430176 + 0.430176 + 0.430176 + 0.430176 + 0.430176 + 0.430176 + 0.430176 + 0.430176 + 0.430420 + 0.430420 + 0.430420 + 0.430420 + 0.430420 + 0.430420 + 0.430420 + 0.430420 + 0.430420 + 0.430420 + 0.430664 + 0.430664 + 0.430664 + 0.430664 + 0.430664 + 0.430664 + 0.430664 + 0.430664 + 0.430664 + 0.430664 + 0.430664 + 0.430908 + 0.430908 + 0.430908 + 0.430908 + 0.430908 + 0.430908 + 0.430908 + 0.430908 + 0.430908 + 0.430908 + 0.430908 + 0.431152 + 0.431152 + 0.431152 + 0.431152 + 0.431152 + 0.431152 + 0.431152 + 0.431152 + 0.431152 + 0.431152 + 0.431152 + 0.431396 + 0.431396 + 0.431396 + 0.431396 + 0.431396 + 0.431396 + 0.431396 + 0.431396 + 0.431396 + 0.431396 + 0.431396 + 0.431641 + 0.431641 + 0.431641 + 0.431641 + 0.431641 + 0.431641 + 0.431641 + 0.431641 + 0.431641 + 0.431641 + 0.431641 + 0.431885 + 0.431885 + 0.431885 + 0.431885 + 0.431885 + 0.431885 + 0.431885 + 0.431885 + 0.431885 + 0.431885 + 0.432129 + 0.432129 + 0.432129 + 0.432129 + 0.432129 + 0.432129 + 0.432129 + 0.432129 + 0.432129 + 0.432129 + 0.432129 + 0.432373 + 0.432373 + 0.432373 + 0.432373 + 0.432373 + 0.432373 + 0.432373 + 0.432373 + 0.432373 + 0.432373 + 0.432373 + 0.432617 + 0.432617 + 0.432617 + 0.432617 + 0.432617 + 0.432617 + 0.432617 + 0.432617 + 0.432617 + 0.432617 + 0.432617 + 0.432861 + 0.432861 + 0.432861 + 0.432861 + 0.432861 + 0.432861 + 0.432861 + 0.432861 + 0.432861 + 0.432861 + 0.432861 + 0.433105 + 0.433105 + 0.433105 + 0.433105 + 0.433105 + 0.433105 + 0.433105 + 0.433105 + 0.433105 + 0.433105 + 0.433105 + 0.433350 + 0.433350 + 0.433350 + 0.433350 + 0.433350 + 0.433350 + 0.433350 + 0.433350 + 0.433350 + 0.433350 + 0.433350 + 0.433594 + 0.433594 + 0.433594 + 0.433594 + 0.433594 + 0.433594 + 0.433594 + 0.433594 + 0.433594 + 0.433594 + 0.433594 + 0.433838 + 0.433838 + 0.433838 + 0.433838 + 0.433838 + 0.433838 + 0.433838 + 0.433838 + 0.433838 + 0.433838 + 0.433838 + 0.434082 + 0.434082 + 0.434082 + 0.434082 + 0.434082 + 0.434082 + 0.434082 + 0.434082 + 0.434082 + 0.434082 + 0.434082 + 0.434326 + 0.434326 + 0.434326 + 0.434326 + 0.434326 + 0.434326 + 0.434326 + 0.434326 + 0.434326 + 0.434326 + 0.434326 + 0.434570 + 0.434570 + 0.434570 + 0.434570 + 0.434570 + 0.434570 + 0.434570 + 0.434570 + 0.434570 + 0.434570 + 0.434570 + 0.434814 + 0.434814 + 0.434814 + 0.434814 + 0.434814 + 0.434814 + 0.434814 + 0.434814 + 0.434814 + 0.434814 + 0.434814 + 0.435059 + 0.435059 + 0.435059 + 0.435059 + 0.435059 + 0.435059 + 0.435059 + 0.435059 + 0.435059 + 0.435059 + 0.435059 + 0.435303 + 0.435303 + 0.435303 + 0.435303 + 0.435303 + 0.435303 + 0.435303 + 0.435303 + 0.435303 + 0.435303 + 0.435303 + 0.435547 + 0.435547 + 0.435547 + 0.435547 + 0.435547 + 0.435547 + 0.435547 + 0.435547 + 0.435547 + 0.435547 + 0.435547 + 0.435791 + 0.435791 + 0.435791 + 0.435791 + 0.435791 + 0.435791 + 0.435791 + 0.435791 + 0.435791 + 0.435791 + 0.435791 + 0.436035 + 0.436035 + 0.436035 + 0.436035 + 0.436035 + 0.436035 + 0.436035 + 0.436035 + 0.436035 + 0.436035 + 0.436035 + 0.436279 + 0.436279 + 0.436279 + 0.436279 + 0.436279 + 0.436279 + 0.436279 + 0.436279 + 0.436279 + 0.436279 + 0.436279 + 0.436523 + 0.436523 + 0.436523 + 0.436523 + 0.436523 + 0.436523 + 0.436523 + 0.436523 + 0.436523 + 0.436523 + 0.436523 + 0.436768 + 0.436768 + 0.436768 + 0.436768 + 0.436768 + 0.436768 + 0.436768 + 0.436768 + 0.436768 + 0.436768 + 0.436768 + 0.437012 + 0.437012 + 0.437012 + 0.437012 + 0.437012 + 0.437012 + 0.437012 + 0.437012 + 0.437012 + 0.437012 + 0.437012 + 0.437256 + 0.437256 + 0.437256 + 0.437256 + 0.437256 + 0.437256 + 0.437256 + 0.437256 + 0.437256 + 0.437256 + 0.437256 + 0.437500 + 0.437500 + 0.437500 + 0.437500 + 0.437500 + 0.437500 + 0.437500 + 0.437500 + 0.437500 + 0.437500 + 0.437500 + 0.437744 + 0.437744 + 0.437744 + 0.437744 + 0.437744 + 0.437744 + 0.437744 + 0.437744 + 0.437744 + 0.437744 + 0.437744 + 0.437988 + 0.437988 + 0.437988 + 0.437988 + 0.437988 + 0.437988 + 0.437988 + 0.437988 + 0.437988 + 0.437988 + 0.437988 + 0.438232 + 0.438232 + 0.438232 + 0.438232 + 0.438232 + 0.438232 + 0.438232 + 0.438232 + 0.438232 + 0.438232 + 0.438232 + 0.438477 + 0.438477 + 0.438477 + 0.438477 + 0.438477 + 0.438477 + 0.438477 + 0.438477 + 0.438477 + 0.438477 + 0.438477 + 0.438477 + 0.438721 + 0.438721 + 0.438721 + 0.438721 + 0.438721 + 0.438721 + 0.438721 + 0.438721 + 0.438721 + 0.438721 + 0.438721 + 0.438965 + 0.438965 + 0.438965 + 0.438965 + 0.438965 + 0.438965 + 0.438965 + 0.438965 + 0.438965 + 0.438965 + 0.438965 + 0.439209 + 0.439209 + 0.439209 + 0.439209 + 0.439209 + 0.439209 + 0.439209 + 0.439209 + 0.439209 + 0.439209 + 0.439209 + 0.439453 + 0.439453 + 0.439453 + 0.439453 + 0.439453 + 0.439453 + 0.439453 + 0.439453 + 0.439453 + 0.439453 + 0.439453 + 0.439697 + 0.439697 + 0.439697 + 0.439697 + 0.439697 + 0.439697 + 0.439697 + 0.439697 + 0.439697 + 0.439697 + 0.439697 + 0.439941 + 0.439941 + 0.439941 + 0.439941 + 0.439941 + 0.439941 + 0.439941 + 0.439941 + 0.439941 + 0.439941 + 0.439941 + 0.439941 + 0.440186 + 0.440186 + 0.440186 + 0.440186 + 0.440186 + 0.440186 + 0.440186 + 0.440186 + 0.440186 + 0.440186 + 0.440186 + 0.440430 + 0.440430 + 0.440430 + 0.440430 + 0.440430 + 0.440430 + 0.440430 + 0.440430 + 0.440430 + 0.440430 + 0.440430 + 0.440674 + 0.440674 + 0.440674 + 0.440674 + 0.440674 + 0.440674 + 0.440674 + 0.440674 + 0.440674 + 0.440674 + 0.440674 + 0.440918 + 0.440918 + 0.440918 + 0.440918 + 0.440918 + 0.440918 + 0.440918 + 0.440918 + 0.440918 + 0.440918 + 0.440918 + 0.441162 + 0.441162 + 0.441162 + 0.441162 + 0.441162 + 0.441162 + 0.441162 + 0.441162 + 0.441162 + 0.441162 + 0.441162 + 0.441162 + 0.441406 + 0.441406 + 0.441406 + 0.441406 + 0.441406 + 0.441406 + 0.441406 + 0.441406 + 0.441406 + 0.441406 + 0.441406 + 0.441650 + 0.441650 + 0.441650 + 0.441650 + 0.441650 + 0.441650 + 0.441650 + 0.441650 + 0.441650 + 0.441650 + 0.441650 + 0.441895 + 0.441895 + 0.441895 + 0.441895 + 0.441895 + 0.441895 + 0.441895 + 0.441895 + 0.441895 + 0.441895 + 0.441895 + 0.442139 + 0.442139 + 0.442139 + 0.442139 + 0.442139 + 0.442139 + 0.442139 + 0.442139 + 0.442139 + 0.442139 + 0.442139 + 0.442139 + 0.442383 + 0.442383 + 0.442383 + 0.442383 + 0.442383 + 0.442383 + 0.442383 + 0.442383 + 0.442383 + 0.442383 + 0.442383 + 0.442627 + 0.442627 + 0.442627 + 0.442627 + 0.442627 + 0.442627 + 0.442627 + 0.442627 + 0.442627 + 0.442627 + 0.442627 + 0.442871 + 0.442871 + 0.442871 + 0.442871 + 0.442871 + 0.442871 + 0.442871 + 0.442871 + 0.442871 + 0.442871 + 0.442871 + 0.442871 + 0.443115 + 0.443115 + 0.443115 + 0.443115 + 0.443115 + 0.443115 + 0.443115 + 0.443115 + 0.443115 + 0.443115 + 0.443115 + 0.443359 + 0.443359 + 0.443359 + 0.443359 + 0.443359 + 0.443359 + 0.443359 + 0.443359 + 0.443359 + 0.443359 + 0.443359 + 0.443604 + 0.443604 + 0.443604 + 0.443604 + 0.443604 + 0.443604 + 0.443604 + 0.443604 + 0.443604 + 0.443604 + 0.443604 + 0.443604 + 0.443848 + 0.443848 + 0.443848 + 0.443848 + 0.443848 + 0.443848 + 0.443848 + 0.443848 + 0.443848 + 0.443848 + 0.443848 + 0.444092 + 0.444092 + 0.444092 + 0.444092 + 0.444092 + 0.444092 + 0.444092 + 0.444092 + 0.444092 + 0.444092 + 0.444092 + 0.444336 + 0.444336 + 0.444336 + 0.444336 + 0.444336 + 0.444336 + 0.444336 + 0.444336 + 0.444336 + 0.444336 + 0.444336 + 0.444336 + 0.444580 + 0.444580 + 0.444580 + 0.444580 + 0.444580 + 0.444580 + 0.444580 + 0.444580 + 0.444580 + 0.444580 + 0.444580 + 0.444824 + 0.444824 + 0.444824 + 0.444824 + 0.444824 + 0.444824 + 0.444824 + 0.444824 + 0.444824 + 0.444824 + 0.444824 + 0.444824 + 0.445068 + 0.445068 + 0.445068 + 0.445068 + 0.445068 + 0.445068 + 0.445068 + 0.445068 + 0.445068 + 0.445068 + 0.445068 + 0.445312 + 0.445312 + 0.445312 + 0.445312 + 0.445312 + 0.445312 + 0.445312 + 0.445312 + 0.445312 + 0.445312 + 0.445312 + 0.445557 + 0.445557 + 0.445557 + 0.445557 + 0.445557 + 0.445557 + 0.445557 + 0.445557 + 0.445557 + 0.445557 + 0.445557 + 0.445557 + 0.445801 + 0.445801 + 0.445801 + 0.445801 + 0.445801 + 0.445801 + 0.445801 + 0.445801 + 0.445801 + 0.445801 + 0.445801 + 0.446045 + 0.446045 + 0.446045 + 0.446045 + 0.446045 + 0.446045 + 0.446045 + 0.446045 + 0.446045 + 0.446045 + 0.446045 + 0.446045 + 0.446289 + 0.446289 + 0.446289 + 0.446289 + 0.446289 + 0.446289 + 0.446289 + 0.446289 + 0.446289 + 0.446289 + 0.446289 + 0.446533 + 0.446533 + 0.446533 + 0.446533 + 0.446533 + 0.446533 + 0.446533 + 0.446533 + 0.446533 + 0.446533 + 0.446533 + 0.446533 + 0.446777 + 0.446777 + 0.446777 + 0.446777 + 0.446777 + 0.446777 + 0.446777 + 0.446777 + 0.446777 + 0.446777 + 0.446777 + 0.447021 + 0.447021 + 0.447021 + 0.447021 + 0.447021 + 0.447021 + 0.447021 + 0.447021 + 0.447021 + 0.447021 + 0.447021 + 0.447021 + 0.447266 + 0.447266 + 0.447266 + 0.447266 + 0.447266 + 0.447266 + 0.447266 + 0.447266 + 0.447266 + 0.447266 + 0.447266 + 0.447510 + 0.447510 + 0.447510 + 0.447510 + 0.447510 + 0.447510 + 0.447510 + 0.447510 + 0.447510 + 0.447510 + 0.447510 + 0.447510 + 0.447754 + 0.447754 + 0.447754 + 0.447754 + 0.447754 + 0.447754 + 0.447754 + 0.447754 + 0.447754 + 0.447754 + 0.447754 + 0.447998 + 0.447998 + 0.447998 + 0.447998 + 0.447998 + 0.447998 + 0.447998 + 0.447998 + 0.447998 + 0.447998 + 0.447998 + 0.447998 + 0.448242 + 0.448242 + 0.448242 + 0.448242 + 0.448242 + 0.448242 + 0.448242 + 0.448242 + 0.448242 + 0.448242 + 0.448242 + 0.448486 + 0.448486 + 0.448486 + 0.448486 + 0.448486 + 0.448486 + 0.448486 + 0.448486 + 0.448486 + 0.448486 + 0.448486 + 0.448486 + 0.448730 + 0.448730 + 0.448730 + 0.448730 + 0.448730 + 0.448730 + 0.448730 + 0.448730 + 0.448730 + 0.448730 + 0.448730 + 0.448975 + 0.448975 + 0.448975 + 0.448975 + 0.448975 + 0.448975 + 0.448975 + 0.448975 + 0.448975 + 0.448975 + 0.448975 + 0.448975 + 0.449219 + 0.449219 + 0.449219 + 0.449219 + 0.449219 + 0.449219 + 0.449219 + 0.449219 + 0.449219 + 0.449219 + 0.449219 + 0.449463 + 0.449463 + 0.449463 + 0.449463 + 0.449463 + 0.449463 + 0.449463 + 0.449463 + 0.449463 + 0.449463 + 0.449463 + 0.449463 + 0.449707 + 0.449707 + 0.449707 + 0.449707 + 0.449707 + 0.449707 + 0.449707 + 0.449707 + 0.449707 + 0.449707 + 0.449707 + 0.449707 + 0.449951 + 0.449951 + 0.449951 + 0.449951 + 0.449951 + 0.449951 + 0.449951 + 0.449951 + 0.449951 + 0.449951 + 0.449951 + 0.450195 + 0.450195 + 0.450195 + 0.450195 + 0.450195 + 0.450195 + 0.450195 + 0.450195 + 0.450195 + 0.450195 + 0.450195 + 0.450195 + 0.450439 + 0.450439 + 0.450439 + 0.450439 + 0.450439 + 0.450439 + 0.450439 + 0.450439 + 0.450439 + 0.450439 + 0.450439 + 0.450684 + 0.450684 + 0.450684 + 0.450684 + 0.450684 + 0.450684 + 0.450684 + 0.450684 + 0.450684 + 0.450684 + 0.450684 + 0.450684 + 0.450928 + 0.450928 + 0.450928 + 0.450928 + 0.450928 + 0.450928 + 0.450928 + 0.450928 + 0.450928 + 0.450928 + 0.450928 + 0.450928 + 0.451172 + 0.451172 + 0.451172 + 0.451172 + 0.451172 + 0.451172 + 0.451172 + 0.451172 + 0.451172 + 0.451172 + 0.451172 + 0.451416 + 0.451416 + 0.451416 + 0.451416 + 0.451416 + 0.451416 + 0.451416 + 0.451416 + 0.451416 + 0.451416 + 0.451416 + 0.451416 + 0.451660 + 0.451660 + 0.451660 + 0.451660 + 0.451660 + 0.451660 + 0.451660 + 0.451660 + 0.451660 + 0.451660 + 0.451660 + 0.451660 + 0.451904 + 0.451904 + 0.451904 + 0.451904 + 0.451904 + 0.451904 + 0.451904 + 0.451904 + 0.451904 + 0.451904 + 0.451904 + 0.452148 + 0.452148 + 0.452148 + 0.452148 + 0.452148 + 0.452148 + 0.452148 + 0.452148 + 0.452148 + 0.452148 + 0.452148 + 0.452148 + 0.452393 + 0.452393 + 0.452393 + 0.452393 + 0.452393 + 0.452393 + 0.452393 + 0.452393 + 0.452393 + 0.452393 + 0.452393 + 0.452393 + 0.452637 + 0.452637 + 0.452637 + 0.452637 + 0.452637 + 0.452637 + 0.452637 + 0.452637 + 0.452637 + 0.452637 + 0.452637 + 0.452881 + 0.452881 + 0.452881 + 0.452881 + 0.452881 + 0.452881 + 0.452881 + 0.452881 + 0.452881 + 0.452881 + 0.452881 + 0.452881 + 0.453125 + 0.453125 + 0.453125 + 0.453125 + 0.453125 + 0.453125 + 0.453125 + 0.453125 + 0.453125 + 0.453125 + 0.453125 + 0.453125 + 0.453369 + 0.453369 + 0.453369 + 0.453369 + 0.453369 + 0.453369 + 0.453369 + 0.453369 + 0.453369 + 0.453369 + 0.453369 + 0.453369 + 0.453613 + 0.453613 + 0.453613 + 0.453613 + 0.453613 + 0.453613 + 0.453613 + 0.453613 + 0.453613 + 0.453613 + 0.453613 + 0.453857 + 0.453857 + 0.453857 + 0.453857 + 0.453857 + 0.453857 + 0.453857 + 0.453857 + 0.453857 + 0.453857 + 0.453857 + 0.453857 + 0.454102 + 0.454102 + 0.454102 + 0.454102 + 0.454102 + 0.454102 + 0.454102 + 0.454102 + 0.454102 + 0.454102 + 0.454102 + 0.454102 + 0.454346 + 0.454346 + 0.454346 + 0.454346 + 0.454346 + 0.454346 + 0.454346 + 0.454346 + 0.454346 + 0.454346 + 0.454346 + 0.454346 + 0.454590 + 0.454590 + 0.454590 + 0.454590 + 0.454590 + 0.454590 + 0.454590 + 0.454590 + 0.454590 + 0.454590 + 0.454590 + 0.454590 + 0.454834 + 0.454834 + 0.454834 + 0.454834 + 0.454834 + 0.454834 + 0.454834 + 0.454834 + 0.454834 + 0.454834 + 0.454834 + 0.455078 + 0.455078 + 0.455078 + 0.455078 + 0.455078 + 0.455078 + 0.455078 + 0.455078 + 0.455078 + 0.455078 + 0.455078 + 0.455078 + 0.455322 + 0.455322 + 0.455322 + 0.455322 + 0.455322 + 0.455322 + 0.455322 + 0.455322 + 0.455322 + 0.455322 + 0.455322 + 0.455322 + 0.455566 + 0.455566 + 0.455566 + 0.455566 + 0.455566 + 0.455566 + 0.455566 + 0.455566 + 0.455566 + 0.455566 + 0.455566 + 0.455566 + 0.455811 + 0.455811 + 0.455811 + 0.455811 + 0.455811 + 0.455811 + 0.455811 + 0.455811 + 0.455811 + 0.455811 + 0.455811 + 0.455811 + 0.456055 + 0.456055 + 0.456055 + 0.456055 + 0.456055 + 0.456055 + 0.456055 + 0.456055 + 0.456055 + 0.456055 + 0.456055 + 0.456055 + 0.456299 + 0.456299 + 0.456299 + 0.456299 + 0.456299 + 0.456299 + 0.456299 + 0.456299 + 0.456299 + 0.456299 + 0.456299 + 0.456543 + 0.456543 + 0.456543 + 0.456543 + 0.456543 + 0.456543 + 0.456543 + 0.456543 + 0.456543 + 0.456543 + 0.456543 + 0.456543 + 0.456787 + 0.456787 + 0.456787 + 0.456787 + 0.456787 + 0.456787 + 0.456787 + 0.456787 + 0.456787 + 0.456787 + 0.456787 + 0.456787 + 0.457031 + 0.457031 + 0.457031 + 0.457031 + 0.457031 + 0.457031 + 0.457031 + 0.457031 + 0.457031 + 0.457031 + 0.457031 + 0.457031 + 0.457275 + 0.457275 + 0.457275 + 0.457275 + 0.457275 + 0.457275 + 0.457275 + 0.457275 + 0.457275 + 0.457275 + 0.457275 + 0.457275 + 0.457520 + 0.457520 + 0.457520 + 0.457520 + 0.457520 + 0.457520 + 0.457520 + 0.457520 + 0.457520 + 0.457520 + 0.457520 + 0.457520 + 0.457764 + 0.457764 + 0.457764 + 0.457764 + 0.457764 + 0.457764 + 0.457764 + 0.457764 + 0.457764 + 0.457764 + 0.457764 + 0.457764 + 0.458008 + 0.458008 + 0.458008 + 0.458008 + 0.458008 + 0.458008 + 0.458008 + 0.458008 + 0.458008 + 0.458008 + 0.458008 + 0.458008 + 0.458252 + 0.458252 + 0.458252 + 0.458252 + 0.458252 + 0.458252 + 0.458252 + 0.458252 + 0.458252 + 0.458252 + 0.458252 + 0.458252 + 0.458496 + 0.458496 + 0.458496 + 0.458496 + 0.458496 + 0.458496 + 0.458496 + 0.458496 + 0.458496 + 0.458496 + 0.458496 + 0.458496 + 0.458740 + 0.458740 + 0.458740 + 0.458740 + 0.458740 + 0.458740 + 0.458740 + 0.458740 + 0.458740 + 0.458740 + 0.458740 + 0.458740 + 0.458984 + 0.458984 + 0.458984 + 0.458984 + 0.458984 + 0.458984 + 0.458984 + 0.458984 + 0.458984 + 0.458984 + 0.458984 + 0.458984 + 0.459229 + 0.459229 + 0.459229 + 0.459229 + 0.459229 + 0.459229 + 0.459229 + 0.459229 + 0.459229 + 0.459229 + 0.459229 + 0.459229 + 0.459473 + 0.459473 + 0.459473 + 0.459473 + 0.459473 + 0.459473 + 0.459473 + 0.459473 + 0.459473 + 0.459473 + 0.459473 + 0.459473 + 0.459717 + 0.459717 + 0.459717 + 0.459717 + 0.459717 + 0.459717 + 0.459717 + 0.459717 + 0.459717 + 0.459717 + 0.459717 + 0.459717 + 0.459961 + 0.459961 + 0.459961 + 0.459961 + 0.459961 + 0.459961 + 0.459961 + 0.459961 + 0.459961 + 0.459961 + 0.459961 + 0.459961 + 0.460205 + 0.460205 + 0.460205 + 0.460205 + 0.460205 + 0.460205 + 0.460205 + 0.460205 + 0.460205 + 0.460205 + 0.460205 + 0.460205 + 0.460449 + 0.460449 + 0.460449 + 0.460449 + 0.460449 + 0.460449 + 0.460449 + 0.460449 + 0.460449 + 0.460449 + 0.460449 + 0.460449 + 0.460693 + 0.460693 + 0.460693 + 0.460693 + 0.460693 + 0.460693 + 0.460693 + 0.460693 + 0.460693 + 0.460693 + 0.460693 + 0.460693 + 0.460938 + 0.460938 + 0.460938 + 0.460938 + 0.460938 + 0.460938 + 0.460938 + 0.460938 + 0.460938 + 0.460938 + 0.460938 + 0.460938 + 0.461182 + 0.461182 + 0.461182 + 0.461182 + 0.461182 + 0.461182 + 0.461182 + 0.461182 + 0.461182 + 0.461182 + 0.461182 + 0.461182 + 0.461426 + 0.461426 + 0.461426 + 0.461426 + 0.461426 + 0.461426 + 0.461426 + 0.461426 + 0.461426 + 0.461426 + 0.461426 + 0.461426 + 0.461670 + 0.461670 + 0.461670 + 0.461670 + 0.461670 + 0.461670 + 0.461670 + 0.461670 + 0.461670 + 0.461670 + 0.461670 + 0.461670 + 0.461914 + 0.461914 + 0.461914 + 0.461914 + 0.461914 + 0.461914 + 0.461914 + 0.461914 + 0.461914 + 0.461914 + 0.461914 + 0.461914 + 0.462158 + 0.462158 + 0.462158 + 0.462158 + 0.462158 + 0.462158 + 0.462158 + 0.462158 + 0.462158 + 0.462158 + 0.462158 + 0.462158 + 0.462402 + 0.462402 + 0.462402 + 0.462402 + 0.462402 + 0.462402 + 0.462402 + 0.462402 + 0.462402 + 0.462402 + 0.462402 + 0.462402 + 0.462646 + 0.462646 + 0.462646 + 0.462646 + 0.462646 + 0.462646 + 0.462646 + 0.462646 + 0.462646 + 0.462646 + 0.462646 + 0.462646 + 0.462646 + 0.462891 + 0.462891 + 0.462891 + 0.462891 + 0.462891 + 0.462891 + 0.462891 + 0.462891 + 0.462891 + 0.462891 + 0.462891 + 0.462891 + 0.463135 + 0.463135 + 0.463135 + 0.463135 + 0.463135 + 0.463135 + 0.463135 + 0.463135 + 0.463135 + 0.463135 + 0.463135 + 0.463135 + 0.463379 + 0.463379 + 0.463379 + 0.463379 + 0.463379 + 0.463379 + 0.463379 + 0.463379 + 0.463379 + 0.463379 + 0.463379 + 0.463379 + 0.463623 + 0.463623 + 0.463623 + 0.463623 + 0.463623 + 0.463623 + 0.463623 + 0.463623 + 0.463623 + 0.463623 + 0.463623 + 0.463623 + 0.463867 + 0.463867 + 0.463867 + 0.463867 + 0.463867 + 0.463867 + 0.463867 + 0.463867 + 0.463867 + 0.463867 + 0.463867 + 0.463867 + 0.464111 + 0.464111 + 0.464111 + 0.464111 + 0.464111 + 0.464111 + 0.464111 + 0.464111 + 0.464111 + 0.464111 + 0.464111 + 0.464111 + 0.464111 + 0.464355 + 0.464355 + 0.464355 + 0.464355 + 0.464355 + 0.464355 + 0.464355 + 0.464355 + 0.464355 + 0.464355 + 0.464355 + 0.464355 + 0.464600 + 0.464600 + 0.464600 + 0.464600 + 0.464600 + 0.464600 + 0.464600 + 0.464600 + 0.464600 + 0.464600 + 0.464600 + 0.464600 + 0.464844 + 0.464844 + 0.464844 + 0.464844 + 0.464844 + 0.464844 + 0.464844 + 0.464844 + 0.464844 + 0.464844 + 0.464844 + 0.464844 + 0.465088 + 0.465088 + 0.465088 + 0.465088 + 0.465088 + 0.465088 + 0.465088 + 0.465088 + 0.465088 + 0.465088 + 0.465088 + 0.465088 + 0.465332 + 0.465332 + 0.465332 + 0.465332 + 0.465332 + 0.465332 + 0.465332 + 0.465332 + 0.465332 + 0.465332 + 0.465332 + 0.465332 + 0.465332 + 0.465576 + 0.465576 + 0.465576 + 0.465576 + 0.465576 + 0.465576 + 0.465576 + 0.465576 + 0.465576 + 0.465576 + 0.465576 + 0.465576 + 0.465820 + 0.465820 + 0.465820 + 0.465820 + 0.465820 + 0.465820 + 0.465820 + 0.465820 + 0.465820 + 0.465820 + 0.465820 + 0.465820 + 0.466064 + 0.466064 + 0.466064 + 0.466064 + 0.466064 + 0.466064 + 0.466064 + 0.466064 + 0.466064 + 0.466064 + 0.466064 + 0.466064 + 0.466309 + 0.466309 + 0.466309 + 0.466309 + 0.466309 + 0.466309 + 0.466309 + 0.466309 + 0.466309 + 0.466309 + 0.466309 + 0.466309 + 0.466309 + 0.466553 + 0.466553 + 0.466553 + 0.466553 + 0.466553 + 0.466553 + 0.466553 + 0.466553 + 0.466553 + 0.466553 + 0.466553 + 0.466553 + 0.466797 + 0.466797 + 0.466797 + 0.466797 + 0.466797 + 0.466797 + 0.466797 + 0.466797 + 0.466797 + 0.466797 + 0.466797 + 0.466797 + 0.467041 + 0.467041 + 0.467041 + 0.467041 + 0.467041 + 0.467041 + 0.467041 + 0.467041 + 0.467041 + 0.467041 + 0.467041 + 0.467041 + 0.467041 + 0.467285 + 0.467285 + 0.467285 + 0.467285 + 0.467285 + 0.467285 + 0.467285 + 0.467285 + 0.467285 + 0.467285 + 0.467285 + 0.467285 + 0.467529 + 0.467529 + 0.467529 + 0.467529 + 0.467529 + 0.467529 + 0.467529 + 0.467529 + 0.467529 + 0.467529 + 0.467529 + 0.467529 + 0.467773 + 0.467773 + 0.467773 + 0.467773 + 0.467773 + 0.467773 + 0.467773 + 0.467773 + 0.467773 + 0.467773 + 0.467773 + 0.467773 + 0.467773 + 0.468018 + 0.468018 + 0.468018 + 0.468018 + 0.468018 + 0.468018 + 0.468018 + 0.468018 + 0.468018 + 0.468018 + 0.468018 + 0.468018 + 0.468262 + 0.468262 + 0.468262 + 0.468262 + 0.468262 + 0.468262 + 0.468262 + 0.468262 + 0.468262 + 0.468262 + 0.468262 + 0.468262 + 0.468506 + 0.468506 + 0.468506 + 0.468506 + 0.468506 + 0.468506 + 0.468506 + 0.468506 + 0.468506 + 0.468506 + 0.468506 + 0.468506 + 0.468506 + 0.468750 + 0.468750 + 0.468750 + 0.468750 + 0.468750 + 0.468750 + 0.468750 + 0.468750 + 0.468750 + 0.468750 + 0.468750 + 0.468750 + 0.468994 + 0.468994 + 0.468994 + 0.468994 + 0.468994 + 0.468994 + 0.468994 + 0.468994 + 0.468994 + 0.468994 + 0.468994 + 0.468994 + 0.468994 + 0.469238 + 0.469238 + 0.469238 + 0.469238 + 0.469238 + 0.469238 + 0.469238 + 0.469238 + 0.469238 + 0.469238 + 0.469238 + 0.469238 + 0.469482 + 0.469482 + 0.469482 + 0.469482 + 0.469482 + 0.469482 + 0.469482 + 0.469482 + 0.469482 + 0.469482 + 0.469482 + 0.469482 + 0.469727 + 0.469727 + 0.469727 + 0.469727 + 0.469727 + 0.469727 + 0.469727 + 0.469727 + 0.469727 + 0.469727 + 0.469727 + 0.469727 + 0.469727 + 0.469971 + 0.469971 + 0.469971 + 0.469971 + 0.469971 + 0.469971 + 0.469971 + 0.469971 + 0.469971 + 0.469971 + 0.469971 + 0.469971 + 0.470215 + 0.470215 + 0.470215 + 0.470215 + 0.470215 + 0.470215 + 0.470215 + 0.470215 + 0.470215 + 0.470215 + 0.470215 + 0.470215 + 0.470215 + 0.470459 + 0.470459 + 0.470459 + 0.470459 + 0.470459 + 0.470459 + 0.470459 + 0.470459 + 0.470459 + 0.470459 + 0.470459 + 0.470459 + 0.470703 + 0.470703 + 0.470703 + 0.470703 + 0.470703 + 0.470703 + 0.470703 + 0.470703 + 0.470703 + 0.470703 + 0.470703 + 0.470703 + 0.470703 + 0.470947 + 0.470947 + 0.470947 + 0.470947 + 0.470947 + 0.470947 + 0.470947 + 0.470947 + 0.470947 + 0.470947 + 0.470947 + 0.470947 + 0.471191 + 0.471191 + 0.471191 + 0.471191 + 0.471191 + 0.471191 + 0.471191 + 0.471191 + 0.471191 + 0.471191 + 0.471191 + 0.471191 + 0.471191 + 0.471436 + 0.471436 + 0.471436 + 0.471436 + 0.471436 + 0.471436 + 0.471436 + 0.471436 + 0.471436 + 0.471436 + 0.471436 + 0.471436 + 0.471680 + 0.471680 + 0.471680 + 0.471680 + 0.471680 + 0.471680 + 0.471680 + 0.471680 + 0.471680 + 0.471680 + 0.471680 + 0.471680 + 0.471680 + 0.471924 + 0.471924 + 0.471924 + 0.471924 + 0.471924 + 0.471924 + 0.471924 + 0.471924 + 0.471924 + 0.471924 + 0.471924 + 0.471924 + 0.472168 + 0.472168 + 0.472168 + 0.472168 + 0.472168 + 0.472168 + 0.472168 + 0.472168 + 0.472168 + 0.472168 + 0.472168 + 0.472168 + 0.472168 + 0.472412 + 0.472412 + 0.472412 + 0.472412 + 0.472412 + 0.472412 + 0.472412 + 0.472412 + 0.472412 + 0.472412 + 0.472412 + 0.472412 + 0.472656 + 0.472656 + 0.472656 + 0.472656 + 0.472656 + 0.472656 + 0.472656 + 0.472656 + 0.472656 + 0.472656 + 0.472656 + 0.472656 + 0.472656 + 0.472900 + 0.472900 + 0.472900 + 0.472900 + 0.472900 + 0.472900 + 0.472900 + 0.472900 + 0.472900 + 0.472900 + 0.472900 + 0.472900 + 0.473145 + 0.473145 + 0.473145 + 0.473145 + 0.473145 + 0.473145 + 0.473145 + 0.473145 + 0.473145 + 0.473145 + 0.473145 + 0.473145 + 0.473145 + 0.473389 + 0.473389 + 0.473389 + 0.473389 + 0.473389 + 0.473389 + 0.473389 + 0.473389 + 0.473389 + 0.473389 + 0.473389 + 0.473389 + 0.473389 + 0.473633 + 0.473633 + 0.473633 + 0.473633 + 0.473633 + 0.473633 + 0.473633 + 0.473633 + 0.473633 + 0.473633 + 0.473633 + 0.473633 + 0.473877 + 0.473877 + 0.473877 + 0.473877 + 0.473877 + 0.473877 + 0.473877 + 0.473877 + 0.473877 + 0.473877 + 0.473877 + 0.473877 + 0.473877 + 0.474121 + 0.474121 + 0.474121 + 0.474121 + 0.474121 + 0.474121 + 0.474121 + 0.474121 + 0.474121 + 0.474121 + 0.474121 + 0.474121 + 0.474365 + 0.474365 + 0.474365 + 0.474365 + 0.474365 + 0.474365 + 0.474365 + 0.474365 + 0.474365 + 0.474365 + 0.474365 + 0.474365 + 0.474365 + 0.474609 + 0.474609 + 0.474609 + 0.474609 + 0.474609 + 0.474609 + 0.474609 + 0.474609 + 0.474609 + 0.474609 + 0.474609 + 0.474609 + 0.474609 + 0.474854 + 0.474854 + 0.474854 + 0.474854 + 0.474854 + 0.474854 + 0.474854 + 0.474854 + 0.474854 + 0.474854 + 0.474854 + 0.474854 + 0.475098 + 0.475098 + 0.475098 + 0.475098 + 0.475098 + 0.475098 + 0.475098 + 0.475098 + 0.475098 + 0.475098 + 0.475098 + 0.475098 + 0.475098 + 0.475342 + 0.475342 + 0.475342 + 0.475342 + 0.475342 + 0.475342 + 0.475342 + 0.475342 + 0.475342 + 0.475342 + 0.475342 + 0.475342 + 0.475342 + 0.475586 + 0.475586 + 0.475586 + 0.475586 + 0.475586 + 0.475586 + 0.475586 + 0.475586 + 0.475586 + 0.475586 + 0.475586 + 0.475586 + 0.475830 + 0.475830 + 0.475830 + 0.475830 + 0.475830 + 0.475830 + 0.475830 + 0.475830 + 0.475830 + 0.475830 + 0.475830 + 0.475830 + 0.475830 + 0.476074 + 0.476074 + 0.476074 + 0.476074 + 0.476074 + 0.476074 + 0.476074 + 0.476074 + 0.476074 + 0.476074 + 0.476074 + 0.476074 + 0.476074 + 0.476318 + 0.476318 + 0.476318 + 0.476318 + 0.476318 + 0.476318 + 0.476318 + 0.476318 + 0.476318 + 0.476318 + 0.476318 + 0.476318 + 0.476562 + 0.476562 + 0.476562 + 0.476562 + 0.476562 + 0.476562 + 0.476562 + 0.476562 + 0.476562 + 0.476562 + 0.476562 + 0.476562 + 0.476562 + 0.476807 + 0.476807 + 0.476807 + 0.476807 + 0.476807 + 0.476807 + 0.476807 + 0.476807 + 0.476807 + 0.476807 + 0.476807 + 0.476807 + 0.476807 + 0.477051 + 0.477051 + 0.477051 + 0.477051 + 0.477051 + 0.477051 + 0.477051 + 0.477051 + 0.477051 + 0.477051 + 0.477051 + 0.477051 + 0.477051 + 0.477295 + 0.477295 + 0.477295 + 0.477295 + 0.477295 + 0.477295 + 0.477295 + 0.477295 + 0.477295 + 0.477295 + 0.477295 + 0.477295 + 0.477539 + 0.477539 + 0.477539 + 0.477539 + 0.477539 + 0.477539 + 0.477539 + 0.477539 + 0.477539 + 0.477539 + 0.477539 + 0.477539 + 0.477539 + 0.477783 + 0.477783 + 0.477783 + 0.477783 + 0.477783 + 0.477783 + 0.477783 + 0.477783 + 0.477783 + 0.477783 + 0.477783 + 0.477783 + 0.477783 + 0.478027 + 0.478027 + 0.478027 + 0.478027 + 0.478027 + 0.478027 + 0.478027 + 0.478027 + 0.478027 + 0.478027 + 0.478027 + 0.478027 + 0.478027 + 0.478271 + 0.478271 + 0.478271 + 0.478271 + 0.478271 + 0.478271 + 0.478271 + 0.478271 + 0.478271 + 0.478271 + 0.478271 + 0.478271 + 0.478516 + 0.478516 + 0.478516 + 0.478516 + 0.478516 + 0.478516 + 0.478516 + 0.478516 + 0.478516 + 0.478516 + 0.478516 + 0.478516 + 0.478516 + 0.478760 + 0.478760 + 0.478760 + 0.478760 + 0.478760 + 0.478760 + 0.478760 + 0.478760 + 0.478760 + 0.478760 + 0.478760 + 0.478760 + 0.478760 + 0.479004 + 0.479004 + 0.479004 + 0.479004 + 0.479004 + 0.479004 + 0.479004 + 0.479004 + 0.479004 + 0.479004 + 0.479004 + 0.479004 + 0.479004 + 0.479248 + 0.479248 + 0.479248 + 0.479248 + 0.479248 + 0.479248 + 0.479248 + 0.479248 + 0.479248 + 0.479248 + 0.479248 + 0.479248 + 0.479248 + 0.479492 + 0.479492 + 0.479492 + 0.479492 + 0.479492 + 0.479492 + 0.479492 + 0.479492 + 0.479492 + 0.479492 + 0.479492 + 0.479492 + 0.479492 + 0.479736 + 0.479736 + 0.479736 + 0.479736 + 0.479736 + 0.479736 + 0.479736 + 0.479736 + 0.479736 + 0.479736 + 0.479736 + 0.479736 + 0.479980 + 0.479980 + 0.479980 + 0.479980 + 0.479980 + 0.479980 + 0.479980 + 0.479980 + 0.479980 + 0.479980 + 0.479980 + 0.479980 + 0.479980 + 0.480225 + 0.480225 + 0.480225 + 0.480225 + 0.480225 + 0.480225 + 0.480225 + 0.480225 + 0.480225 + 0.480225 + 0.480225 + 0.480225 + 0.480225 + 0.480469 + 0.480469 + 0.480469 + 0.480469 + 0.480469 + 0.480469 + 0.480469 + 0.480469 + 0.480469 + 0.480469 + 0.480469 + 0.480469 + 0.480469 + 0.480713 + 0.480713 + 0.480713 + 0.480713 + 0.480713 + 0.480713 + 0.480713 + 0.480713 + 0.480713 + 0.480713 + 0.480713 + 0.480713 + 0.480713 + 0.480957 + 0.480957 + 0.480957 + 0.480957 + 0.480957 + 0.480957 + 0.480957 + 0.480957 + 0.480957 + 0.480957 + 0.480957 + 0.480957 + 0.480957 + 0.481201 + 0.481201 + 0.481201 + 0.481201 + 0.481201 + 0.481201 + 0.481201 + 0.481201 + 0.481201 + 0.481201 + 0.481201 + 0.481201 + 0.481201 + 0.481445 + 0.481445 + 0.481445 + 0.481445 + 0.481445 + 0.481445 + 0.481445 + 0.481445 + 0.481445 + 0.481445 + 0.481445 + 0.481445 + 0.481445 + 0.481689 + 0.481689 + 0.481689 + 0.481689 + 0.481689 + 0.481689 + 0.481689 + 0.481689 + 0.481689 + 0.481689 + 0.481689 + 0.481689 + 0.481689 + 0.481934 + 0.481934 + 0.481934 + 0.481934 + 0.481934 + 0.481934 + 0.481934 + 0.481934 + 0.481934 + 0.481934 + 0.481934 + 0.481934 + 0.481934 + 0.482178 + 0.482178 + 0.482178 + 0.482178 + 0.482178 + 0.482178 + 0.482178 + 0.482178 + 0.482178 + 0.482178 + 0.482178 + 0.482178 + 0.482178 + 0.482422 + 0.482422 + 0.482422 + 0.482422 + 0.482422 + 0.482422 + 0.482422 + 0.482422 + 0.482422 + 0.482422 + 0.482422 + 0.482422 + 0.482422 + 0.482666 + 0.482666 + 0.482666 + 0.482666 + 0.482666 + 0.482666 + 0.482666 + 0.482666 + 0.482666 + 0.482666 + 0.482666 + 0.482666 + 0.482666 + 0.482910 + 0.482910 + 0.482910 + 0.482910 + 0.482910 + 0.482910 + 0.482910 + 0.482910 + 0.482910 + 0.482910 + 0.482910 + 0.482910 + 0.482910 + 0.483154 + 0.483154 + 0.483154 + 0.483154 + 0.483154 + 0.483154 + 0.483154 + 0.483154 + 0.483154 + 0.483154 + 0.483154 + 0.483154 + 0.483154 + 0.483398 + 0.483398 + 0.483398 + 0.483398 + 0.483398 + 0.483398 + 0.483398 + 0.483398 + 0.483398 + 0.483398 + 0.483398 + 0.483398 + 0.483398 + 0.483643 + 0.483643 + 0.483643 + 0.483643 + 0.483643 + 0.483643 + 0.483643 + 0.483643 + 0.483643 + 0.483643 + 0.483643 + 0.483643 + 0.483643 + 0.483887 + 0.483887 + 0.483887 + 0.483887 + 0.483887 + 0.483887 + 0.483887 + 0.483887 + 0.483887 + 0.483887 + 0.483887 + 0.483887 + 0.483887 + 0.484131 + 0.484131 + 0.484131 + 0.484131 + 0.484131 + 0.484131 + 0.484131 + 0.484131 + 0.484131 + 0.484131 + 0.484131 + 0.484131 + 0.484131 + 0.484375 + 0.484375 + 0.484375 + 0.484375 + 0.484375 + 0.484375 + 0.484375 + 0.484375 + 0.484375 + 0.484375 + 0.484375 + 0.484375 + 0.484375 + 0.484619 + 0.484619 + 0.484619 + 0.484619 + 0.484619 + 0.484619 + 0.484619 + 0.484619 + 0.484619 + 0.484619 + 0.484619 + 0.484619 + 0.484619 + 0.484863 + 0.484863 + 0.484863 + 0.484863 + 0.484863 + 0.484863 + 0.484863 + 0.484863 + 0.484863 + 0.484863 + 0.484863 + 0.484863 + 0.484863 + 0.485107 + 0.485107 + 0.485107 + 0.485107 + 0.485107 + 0.485107 + 0.485107 + 0.485107 + 0.485107 + 0.485107 + 0.485107 + 0.485107 + 0.485107 + 0.485352 + 0.485352 + 0.485352 + 0.485352 + 0.485352 + 0.485352 + 0.485352 + 0.485352 + 0.485352 + 0.485352 + 0.485352 + 0.485352 + 0.485352 + 0.485596 + 0.485596 + 0.485596 + 0.485596 + 0.485596 + 0.485596 + 0.485596 + 0.485596 + 0.485596 + 0.485596 + 0.485596 + 0.485596 + 0.485596 + 0.485840 + 0.485840 + 0.485840 + 0.485840 + 0.485840 + 0.485840 + 0.485840 + 0.485840 + 0.485840 + 0.485840 + 0.485840 + 0.485840 + 0.485840 + 0.486084 + 0.486084 + 0.486084 + 0.486084 + 0.486084 + 0.486084 + 0.486084 + 0.486084 + 0.486084 + 0.486084 + 0.486084 + 0.486084 + 0.486084 + 0.486328 + 0.486328 + 0.486328 + 0.486328 + 0.486328 + 0.486328 + 0.486328 + 0.486328 + 0.486328 + 0.486328 + 0.486328 + 0.486328 + 0.486328 + 0.486328 + 0.486572 + 0.486572 + 0.486572 + 0.486572 + 0.486572 + 0.486572 + 0.486572 + 0.486572 + 0.486572 + 0.486572 + 0.486572 + 0.486572 + 0.486572 + 0.486816 + 0.486816 + 0.486816 + 0.486816 + 0.486816 + 0.486816 + 0.486816 + 0.486816 + 0.486816 + 0.486816 + 0.486816 + 0.486816 + 0.486816 + 0.487061 + 0.487061 + 0.487061 + 0.487061 + 0.487061 + 0.487061 + 0.487061 + 0.487061 + 0.487061 + 0.487061 + 0.487061 + 0.487061 + 0.487061 + 0.487305 + 0.487305 + 0.487305 + 0.487305 + 0.487305 + 0.487305 + 0.487305 + 0.487305 + 0.487305 + 0.487305 + 0.487305 + 0.487305 + 0.487305 + 0.487549 + 0.487549 + 0.487549 + 0.487549 + 0.487549 + 0.487549 + 0.487549 + 0.487549 + 0.487549 + 0.487549 + 0.487549 + 0.487549 + 0.487549 + 0.487793 + 0.487793 + 0.487793 + 0.487793 + 0.487793 + 0.487793 + 0.487793 + 0.487793 + 0.487793 + 0.487793 + 0.487793 + 0.487793 + 0.487793 + 0.487793 + 0.488037 + 0.488037 + 0.488037 + 0.488037 + 0.488037 + 0.488037 + 0.488037 + 0.488037 + 0.488037 + 0.488037 + 0.488037 + 0.488037 + 0.488037 + 0.488281 + 0.488281 + 0.488281 + 0.488281 + 0.488281 + 0.488281 + 0.488281 + 0.488281 + 0.488281 + 0.488281 + 0.488281 + 0.488281 + 0.488281 + 0.488525 + 0.488525 + 0.488525 + 0.488525 + 0.488525 + 0.488525 + 0.488525 + 0.488525 + 0.488525 + 0.488525 + 0.488525 + 0.488525 + 0.488525 + 0.488770 + 0.488770 + 0.488770 + 0.488770 + 0.488770 + 0.488770 + 0.488770 + 0.488770 + 0.488770 + 0.488770 + 0.488770 + 0.488770 + 0.488770 + 0.488770 + 0.489014 + 0.489014 + 0.489014 + 0.489014 + 0.489014 + 0.489014 + 0.489014 + 0.489014 + 0.489014 + 0.489014 + 0.489014 + 0.489014 + 0.489014 + 0.489258 + 0.489258 + 0.489258 + 0.489258 + 0.489258 + 0.489258 + 0.489258 + 0.489258 + 0.489258 + 0.489258 + 0.489258 + 0.489258 + 0.489258 + 0.489502 + 0.489502 + 0.489502 + 0.489502 + 0.489502 + 0.489502 + 0.489502 + 0.489502 + 0.489502 + 0.489502 + 0.489502 + 0.489502 + 0.489502 + 0.489746 + 0.489746 + 0.489746 + 0.489746 + 0.489746 + 0.489746 + 0.489746 + 0.489746 + 0.489746 + 0.489746 + 0.489746 + 0.489746 + 0.489746 + 0.489746 + 0.489990 + 0.489990 + 0.489990 + 0.489990 + 0.489990 + 0.489990 + 0.489990 + 0.489990 + 0.489990 + 0.489990 + 0.489990 + 0.489990 + 0.489990 + 0.490234 + 0.490234 + 0.490234 + 0.490234 + 0.490234 + 0.490234 + 0.490234 + 0.490234 + 0.490234 + 0.490234 + 0.490234 + 0.490234 + 0.490234 + 0.490479 + 0.490479 + 0.490479 + 0.490479 + 0.490479 + 0.490479 + 0.490479 + 0.490479 + 0.490479 + 0.490479 + 0.490479 + 0.490479 + 0.490479 + 0.490479 + 0.490723 + 0.490723 + 0.490723 + 0.490723 + 0.490723 + 0.490723 + 0.490723 + 0.490723 + 0.490723 + 0.490723 + 0.490723 + 0.490723 + 0.490723 + 0.490967 + 0.490967 + 0.490967 + 0.490967 + 0.490967 + 0.490967 + 0.490967 + 0.490967 + 0.490967 + 0.490967 + 0.490967 + 0.490967 + 0.490967 + 0.491211 + 0.491211 + 0.491211 + 0.491211 + 0.491211 + 0.491211 + 0.491211 + 0.491211 + 0.491211 + 0.491211 + 0.491211 + 0.491211 + 0.491211 + 0.491211 + 0.491455 + 0.491455 + 0.491455 + 0.491455 + 0.491455 + 0.491455 + 0.491455 + 0.491455 + 0.491455 + 0.491455 + 0.491455 + 0.491455 + 0.491455 + 0.491699 + 0.491699 + 0.491699 + 0.491699 + 0.491699 + 0.491699 + 0.491699 + 0.491699 + 0.491699 + 0.491699 + 0.491699 + 0.491699 + 0.491699 + 0.491943 + 0.491943 + 0.491943 + 0.491943 + 0.491943 + 0.491943 + 0.491943 + 0.491943 + 0.491943 + 0.491943 + 0.491943 + 0.491943 + 0.491943 + 0.491943 + 0.492188 + 0.492188 + 0.492188 + 0.492188 + 0.492188 + 0.492188 + 0.492188 + 0.492188 + 0.492188 + 0.492188 + 0.492188 + 0.492188 + 0.492188 + 0.492432 + 0.492432 + 0.492432 + 0.492432 + 0.492432 + 0.492432 + 0.492432 + 0.492432 + 0.492432 + 0.492432 + 0.492432 + 0.492432 + 0.492432 + 0.492676 + 0.492676 + 0.492676 + 0.492676 + 0.492676 + 0.492676 + 0.492676 + 0.492676 + 0.492676 + 0.492676 + 0.492676 + 0.492676 + 0.492676 + 0.492676 + 0.492920 + 0.492920 + 0.492920 + 0.492920 + 0.492920 + 0.492920 + 0.492920 + 0.492920 + 0.492920 + 0.492920 + 0.492920 + 0.492920 + 0.492920 + 0.493164 + 0.493164 + 0.493164 + 0.493164 + 0.493164 + 0.493164 + 0.493164 + 0.493164 + 0.493164 + 0.493164 + 0.493164 + 0.493164 + 0.493164 + 0.493164 + 0.493408 + 0.493408 + 0.493408 + 0.493408 + 0.493408 + 0.493408 + 0.493408 + 0.493408 + 0.493408 + 0.493408 + 0.493408 + 0.493408 + 0.493408 + 0.493652 + 0.493652 + 0.493652 + 0.493652 + 0.493652 + 0.493652 + 0.493652 + 0.493652 + 0.493652 + 0.493652 + 0.493652 + 0.493652 + 0.493652 + 0.493652 + 0.493896 + 0.493896 + 0.493896 + 0.493896 + 0.493896 + 0.493896 + 0.493896 + 0.493896 + 0.493896 + 0.493896 + 0.493896 + 0.493896 + 0.493896 + 0.494141 + 0.494141 + 0.494141 + 0.494141 + 0.494141 + 0.494141 + 0.494141 + 0.494141 + 0.494141 + 0.494141 + 0.494141 + 0.494141 + 0.494141 + 0.494141 + 0.494385 + 0.494385 + 0.494385 + 0.494385 + 0.494385 + 0.494385 + 0.494385 + 0.494385 + 0.494385 + 0.494385 + 0.494385 + 0.494385 + 0.494385 + 0.494629 + 0.494629 + 0.494629 + 0.494629 + 0.494629 + 0.494629 + 0.494629 + 0.494629 + 0.494629 + 0.494629 + 0.494629 + 0.494629 + 0.494629 + 0.494629 + 0.494873 + 0.494873 + 0.494873 + 0.494873 + 0.494873 + 0.494873 + 0.494873 + 0.494873 + 0.494873 + 0.494873 + 0.494873 + 0.494873 + 0.494873 + 0.495117 + 0.495117 + 0.495117 + 0.495117 + 0.495117 + 0.495117 + 0.495117 + 0.495117 + 0.495117 + 0.495117 + 0.495117 + 0.495117 + 0.495117 + 0.495117 + 0.495361 + 0.495361 + 0.495361 + 0.495361 + 0.495361 + 0.495361 + 0.495361 + 0.495361 + 0.495361 + 0.495361 + 0.495361 + 0.495361 + 0.495361 + 0.495605 + 0.495605 + 0.495605 + 0.495605 + 0.495605 + 0.495605 + 0.495605 + 0.495605 + 0.495605 + 0.495605 + 0.495605 + 0.495605 + 0.495605 + 0.495605 + 0.495850 + 0.495850 + 0.495850 + 0.495850 + 0.495850 + 0.495850 + 0.495850 + 0.495850 + 0.495850 + 0.495850 + 0.495850 + 0.495850 + 0.495850 + 0.496094 + 0.496094 + 0.496094 + 0.496094 + 0.496094 + 0.496094 + 0.496094 + 0.496094 + 0.496094 + 0.496094 + 0.496094 + 0.496094 + 0.496094 + 0.496094 + 0.496338 + 0.496338 + 0.496338 + 0.496338 + 0.496338 + 0.496338 + 0.496338 + 0.496338 + 0.496338 + 0.496338 + 0.496338 + 0.496338 + 0.496338 + 0.496582 + 0.496582 + 0.496582 + 0.496582 + 0.496582 + 0.496582 + 0.496582 + 0.496582 + 0.496582 + 0.496582 + 0.496582 + 0.496582 + 0.496582 + 0.496582 + 0.496826 + 0.496826 + 0.496826 + 0.496826 + 0.496826 + 0.496826 + 0.496826 + 0.496826 + 0.496826 + 0.496826 + 0.496826 + 0.496826 + 0.496826 + 0.496826 + 0.497070 + 0.497070 + 0.497070 + 0.497070 + 0.497070 + 0.497070 + 0.497070 + 0.497070 + 0.497070 + 0.497070 + 0.497070 + 0.497070 + 0.497070 + 0.497314 + 0.497314 + 0.497314 + 0.497314 + 0.497314 + 0.497314 + 0.497314 + 0.497314 + 0.497314 + 0.497314 + 0.497314 + 0.497314 + 0.497314 + 0.497314 + 0.497559 + 0.497559 + 0.497559 + 0.497559 + 0.497559 + 0.497559 + 0.497559 + 0.497559 + 0.497559 + 0.497559 + 0.497559 + 0.497559 + 0.497559 + 0.497803 + 0.497803 + 0.497803 + 0.497803 + 0.497803 + 0.497803 + 0.497803 + 0.497803 + 0.497803 + 0.497803 + 0.497803 + 0.497803 + 0.497803 + 0.497803 + 0.498047 + 0.498047 + 0.498047 + 0.498047 + 0.498047 + 0.498047 + 0.498047 + 0.498047 + 0.498047 + 0.498047 + 0.498047 + 0.498047 + 0.498047 + 0.498047 + 0.498291 + 0.498291 + 0.498291 + 0.498291 + 0.498291 + 0.498291 + 0.498291 + 0.498291 + 0.498291 + 0.498291 + 0.498291 + 0.498291 + 0.498291 + 0.498535 + 0.498535 + 0.498535 + 0.498535 + 0.498535 + 0.498535 + 0.498535 + 0.498535 + 0.498535 + 0.498535 + 0.498535 + 0.498535 + 0.498535 + 0.498535 + 0.498779 + 0.498779 + 0.498779 + 0.498779 + 0.498779 + 0.498779 + 0.498779 + 0.498779 + 0.498779 + 0.498779 + 0.498779 + 0.498779 + 0.498779 + 0.498779 + 0.499023 + 0.499023 + 0.499023 + 0.499023 + 0.499023 + 0.499023 + 0.499023 + 0.499023 + 0.499023 + 0.499023 + 0.499023 + 0.499023 + 0.499023 + 0.499268 + 0.499268 + 0.499268 + 0.499268 + 0.499268 + 0.499268 + 0.499268 + 0.499268 + 0.499268 + 0.499268 + 0.499268 + 0.499268 + 0.499268 + 0.499268 + 0.499512 + 0.499512 + 0.499512 + 0.499512 + 0.499512 + 0.499512 + 0.499512 + 0.499512 + 0.499512 + 0.499512 + 0.499512 + 0.499512 + 0.499512 + 0.499512 + 0.499756 + 0.499756 + 0.499756 + 0.499756 + 0.499756 + 0.499756 + 0.499756 + 0.499756 + 0.499756 + 0.499756 + 0.499756 + 0.499756 + 0.499756 + 0.499756 + 0.500000 + 0.500000 + 0.500000 + 0.500000 + 0.500000 + 0.500000 + 0.500000 + 0.500000 + 0.500000 + 0.500000 + 0.500000 + 0.500000 + 0.500000 + 0.500244 + 0.500244 + 0.500244 + 0.500244 + 0.500244 + 0.500244 + 0.500244 + 0.500244 + 0.500244 + 0.500244 + 0.500244 + 0.500244 + 0.500244 + 0.500244 + 0.500488 + 0.500488 + 0.500488 + 0.500488 + 0.500488 + 0.500488 + 0.500488 + 0.500488 + 0.500488 + 0.500488 + 0.500488 + 0.500488 + 0.500488 + 0.500488 + 0.500732 + 0.500732 + 0.500732 + 0.500732 + 0.500732 + 0.500732 + 0.500732 + 0.500732 + 0.500732 + 0.500732 + 0.500732 + 0.500732 + 0.500732 + 0.500732 + 0.500977 + 0.500977 + 0.500977 + 0.500977 + 0.500977 + 0.500977 + 0.500977 + 0.500977 + 0.500977 + 0.500977 + 0.500977 + 0.500977 + 0.500977 + 0.501221 + 0.501221 + 0.501221 + 0.501221 + 0.501221 + 0.501221 + 0.501221 + 0.501221 + 0.501221 + 0.501221 + 0.501221 + 0.501221 + 0.501221 + 0.501221 + 0.501465 + 0.501465 + 0.501465 + 0.501465 + 0.501465 + 0.501465 + 0.501465 + 0.501465 + 0.501465 + 0.501465 + 0.501465 + 0.501465 + 0.501465 + 0.501465 + 0.501709 + 0.501709 + 0.501709 + 0.501709 + 0.501709 + 0.501709 + 0.501709 + 0.501709 + 0.501709 + 0.501709 + 0.501709 + 0.501709 + 0.501709 + 0.501709 + 0.501953 + 0.501953 + 0.501953 + 0.501953 + 0.501953 + 0.501953 + 0.501953 + 0.501953 + 0.501953 + 0.501953 + 0.501953 + 0.501953 + 0.501953 + 0.501953 + 0.502197 + 0.502197 + 0.502197 + 0.502197 + 0.502197 + 0.502197 + 0.502197 + 0.502197 + 0.502197 + 0.502197 + 0.502197 + 0.502197 + 0.502197 + 0.502441 + 0.502441 + 0.502441 + 0.502441 + 0.502441 + 0.502441 + 0.502441 + 0.502441 + 0.502441 + 0.502441 + 0.502441 + 0.502441 + 0.502441 + 0.502441 + 0.502686 + 0.502686 + 0.502686 + 0.502686 + 0.502686 + 0.502686 + 0.502686 + 0.502686 + 0.502686 + 0.502686 + 0.502686 + 0.502686 + 0.502686 + 0.502686 + 0.502930 + 0.502930 + 0.502930 + 0.502930 + 0.502930 + 0.502930 + 0.502930 + 0.502930 + 0.502930 + 0.502930 + 0.502930 + 0.502930 + 0.502930 + 0.502930 + 0.503174 + 0.503174 + 0.503174 + 0.503174 + 0.503174 + 0.503174 + 0.503174 + 0.503174 + 0.503174 + 0.503174 + 0.503174 + 0.503174 + 0.503174 + 0.503174 + 0.503418 + 0.503418 + 0.503418 + 0.503418 + 0.503418 + 0.503418 + 0.503418 + 0.503418 + 0.503418 + 0.503418 + 0.503418 + 0.503418 + 0.503418 + 0.503418 + 0.503662 + 0.503662 + 0.503662 + 0.503662 + 0.503662 + 0.503662 + 0.503662 + 0.503662 + 0.503662 + 0.503662 + 0.503662 + 0.503662 + 0.503662 + 0.503662 + 0.503906 + 0.503906 + 0.503906 + 0.503906 + 0.503906 + 0.503906 + 0.503906 + 0.503906 + 0.503906 + 0.503906 + 0.503906 + 0.503906 + 0.503906 + 0.503906 + 0.504150 + 0.504150 + 0.504150 + 0.504150 + 0.504150 + 0.504150 + 0.504150 + 0.504150 + 0.504150 + 0.504150 + 0.504150 + 0.504150 + 0.504150 + 0.504150 + 0.504395 + 0.504395 + 0.504395 + 0.504395 + 0.504395 + 0.504395 + 0.504395 + 0.504395 + 0.504395 + 0.504395 + 0.504395 + 0.504395 + 0.504395 + 0.504639 + 0.504639 + 0.504639 + 0.504639 + 0.504639 + 0.504639 + 0.504639 + 0.504639 + 0.504639 + 0.504639 + 0.504639 + 0.504639 + 0.504639 + 0.504639 + 0.504883 + 0.504883 + 0.504883 + 0.504883 + 0.504883 + 0.504883 + 0.504883 + 0.504883 + 0.504883 + 0.504883 + 0.504883 + 0.504883 + 0.504883 + 0.504883 + 0.505127 + 0.505127 + 0.505127 + 0.505127 + 0.505127 + 0.505127 + 0.505127 + 0.505127 + 0.505127 + 0.505127 + 0.505127 + 0.505127 + 0.505127 + 0.505127 + 0.505371 + 0.505371 + 0.505371 + 0.505371 + 0.505371 + 0.505371 + 0.505371 + 0.505371 + 0.505371 + 0.505371 + 0.505371 + 0.505371 + 0.505371 + 0.505371 + 0.505615 + 0.505615 + 0.505615 + 0.505615 + 0.505615 + 0.505615 + 0.505615 + 0.505615 + 0.505615 + 0.505615 + 0.505615 + 0.505615 + 0.505615 + 0.505615 + 0.505859 + 0.505859 + 0.505859 + 0.505859 + 0.505859 + 0.505859 + 0.505859 + 0.505859 + 0.505859 + 0.505859 + 0.505859 + 0.505859 + 0.505859 + 0.505859 + 0.506104 + 0.506104 + 0.506104 + 0.506104 + 0.506104 + 0.506104 + 0.506104 + 0.506104 + 0.506104 + 0.506104 + 0.506104 + 0.506104 + 0.506104 + 0.506104 + 0.506348 + 0.506348 + 0.506348 + 0.506348 + 0.506348 + 0.506348 + 0.506348 + 0.506348 + 0.506348 + 0.506348 + 0.506348 + 0.506348 + 0.506348 + 0.506348 + 0.506592 + 0.506592 + 0.506592 + 0.506592 + 0.506592 + 0.506592 + 0.506592 + 0.506592 + 0.506592 + 0.506592 + 0.506592 + 0.506592 + 0.506592 + 0.506592 + 0.506836 + 0.506836 + 0.506836 + 0.506836 + 0.506836 + 0.506836 + 0.506836 + 0.506836 + 0.506836 + 0.506836 + 0.506836 + 0.506836 + 0.506836 + 0.506836 + 0.507080 + 0.507080 + 0.507080 + 0.507080 + 0.507080 + 0.507080 + 0.507080 + 0.507080 + 0.507080 + 0.507080 + 0.507080 + 0.507080 + 0.507080 + 0.507080 + 0.507324 + 0.507324 + 0.507324 + 0.507324 + 0.507324 + 0.507324 + 0.507324 + 0.507324 + 0.507324 + 0.507324 + 0.507324 + 0.507324 + 0.507324 + 0.507324 + 0.507568 + 0.507568 + 0.507568 + 0.507568 + 0.507568 + 0.507568 + 0.507568 + 0.507568 + 0.507568 + 0.507568 + 0.507568 + 0.507568 + 0.507568 + 0.507568 + 0.507568 + 0.507812 + 0.507812 + 0.507812 + 0.507812 + 0.507812 + 0.507812 + 0.507812 + 0.507812 + 0.507812 + 0.507812 + 0.507812 + 0.507812 + 0.507812 + 0.507812 + 0.508057 + 0.508057 + 0.508057 + 0.508057 + 0.508057 + 0.508057 + 0.508057 + 0.508057 + 0.508057 + 0.508057 + 0.508057 + 0.508057 + 0.508057 + 0.508057 + 0.508301 + 0.508301 + 0.508301 + 0.508301 + 0.508301 + 0.508301 + 0.508301 + 0.508301 + 0.508301 + 0.508301 + 0.508301 + 0.508301 + 0.508301 + 0.508301 + 0.508545 + 0.508545 + 0.508545 + 0.508545 + 0.508545 + 0.508545 + 0.508545 + 0.508545 + 0.508545 + 0.508545 + 0.508545 + 0.508545 + 0.508545 + 0.508545 + 0.508789 + 0.508789 + 0.508789 + 0.508789 + 0.508789 + 0.508789 + 0.508789 + 0.508789 + 0.508789 + 0.508789 + 0.508789 + 0.508789 + 0.508789 + 0.508789 + 0.509033 + 0.509033 + 0.509033 + 0.509033 + 0.509033 + 0.509033 + 0.509033 + 0.509033 + 0.509033 + 0.509033 + 0.509033 + 0.509033 + 0.509033 + 0.509033 + 0.509277 + 0.509277 + 0.509277 + 0.509277 + 0.509277 + 0.509277 + 0.509277 + 0.509277 + 0.509277 + 0.509277 + 0.509277 + 0.509277 + 0.509277 + 0.509277 + 0.509521 + 0.509521 + 0.509521 + 0.509521 + 0.509521 + 0.509521 + 0.509521 + 0.509521 + 0.509521 + 0.509521 + 0.509521 + 0.509521 + 0.509521 + 0.509521 + 0.509766 + 0.509766 + 0.509766 + 0.509766 + 0.509766 + 0.509766 + 0.509766 + 0.509766 + 0.509766 + 0.509766 + 0.509766 + 0.509766 + 0.509766 + 0.509766 + 0.509766 + 0.510010 + 0.510010 + 0.510010 + 0.510010 + 0.510010 + 0.510010 + 0.510010 + 0.510010 + 0.510010 + 0.510010 + 0.510010 + 0.510010 + 0.510010 + 0.510010 + 0.510254 + 0.510254 + 0.510254 + 0.510254 + 0.510254 + 0.510254 + 0.510254 + 0.510254 + 0.510254 + 0.510254 + 0.510254 + 0.510254 + 0.510254 + 0.510254 + 0.510498 + 0.510498 + 0.510498 + 0.510498 + 0.510498 + 0.510498 + 0.510498 + 0.510498 + 0.510498 + 0.510498 + 0.510498 + 0.510498 + 0.510498 + 0.510498 + 0.510742 + 0.510742 + 0.510742 + 0.510742 + 0.510742 + 0.510742 + 0.510742 + 0.510742 + 0.510742 + 0.510742 + 0.510742 + 0.510742 + 0.510742 + 0.510742 + 0.510986 + 0.510986 + 0.510986 + 0.510986 + 0.510986 + 0.510986 + 0.510986 + 0.510986 + 0.510986 + 0.510986 + 0.510986 + 0.510986 + 0.510986 + 0.510986 + 0.510986 + 0.511230 + 0.511230 + 0.511230 + 0.511230 + 0.511230 + 0.511230 + 0.511230 + 0.511230 + 0.511230 + 0.511230 + 0.511230 + 0.511230 + 0.511230 + 0.511230 + 0.511475 + 0.511475 + 0.511475 + 0.511475 + 0.511475 + 0.511475 + 0.511475 + 0.511475 + 0.511475 + 0.511475 + 0.511475 + 0.511475 + 0.511475 + 0.511475 + 0.511719 + 0.511719 + 0.511719 + 0.511719 + 0.511719 + 0.511719 + 0.511719 + 0.511719 + 0.511719 + 0.511719 + 0.511719 + 0.511719 + 0.511719 + 0.511719 + 0.511963 + 0.511963 + 0.511963 + 0.511963 + 0.511963 + 0.511963 + 0.511963 + 0.511963 + 0.511963 + 0.511963 + 0.511963 + 0.511963 + 0.511963 + 0.511963 + 0.511963 + 0.512207 + 0.512207 + 0.512207 + 0.512207 + 0.512207 + 0.512207 + 0.512207 + 0.512207 + 0.512207 + 0.512207 + 0.512207 + 0.512207 + 0.512207 + 0.512207 + 0.512451 + 0.512451 + 0.512451 + 0.512451 + 0.512451 + 0.512451 + 0.512451 + 0.512451 + 0.512451 + 0.512451 + 0.512451 + 0.512451 + 0.512451 + 0.512451 + 0.512695 + 0.512695 + 0.512695 + 0.512695 + 0.512695 + 0.512695 + 0.512695 + 0.512695 + 0.512695 + 0.512695 + 0.512695 + 0.512695 + 0.512695 + 0.512695 + 0.512695 + 0.512939 + 0.512939 + 0.512939 + 0.512939 + 0.512939 + 0.512939 + 0.512939 + 0.512939 + 0.512939 + 0.512939 + 0.512939 + 0.512939 + 0.512939 + 0.512939 + 0.513184 + 0.513184 + 0.513184 + 0.513184 + 0.513184 + 0.513184 + 0.513184 + 0.513184 + 0.513184 + 0.513184 + 0.513184 + 0.513184 + 0.513184 + 0.513184 + 0.513428 + 0.513428 + 0.513428 + 0.513428 + 0.513428 + 0.513428 + 0.513428 + 0.513428 + 0.513428 + 0.513428 + 0.513428 + 0.513428 + 0.513428 + 0.513428 + 0.513672 + 0.513672 + 0.513672 + 0.513672 + 0.513672 + 0.513672 + 0.513672 + 0.513672 + 0.513672 + 0.513672 + 0.513672 + 0.513672 + 0.513672 + 0.513672 + 0.513672 + 0.513916 + 0.513916 + 0.513916 + 0.513916 + 0.513916 + 0.513916 + 0.513916 + 0.513916 + 0.513916 + 0.513916 + 0.513916 + 0.513916 + 0.513916 + 0.513916 + 0.514160 + 0.514160 + 0.514160 + 0.514160 + 0.514160 + 0.514160 + 0.514160 + 0.514160 + 0.514160 + 0.514160 + 0.514160 + 0.514160 + 0.514160 + 0.514160 + 0.514160 + 0.514404 + 0.514404 + 0.514404 + 0.514404 + 0.514404 + 0.514404 + 0.514404 + 0.514404 + 0.514404 + 0.514404 + 0.514404 + 0.514404 + 0.514404 + 0.514404 + 0.514648 + 0.514648 + 0.514648 + 0.514648 + 0.514648 + 0.514648 + 0.514648 + 0.514648 + 0.514648 + 0.514648 + 0.514648 + 0.514648 + 0.514648 + 0.514648 + 0.514893 + 0.514893 + 0.514893 + 0.514893 + 0.514893 + 0.514893 + 0.514893 + 0.514893 + 0.514893 + 0.514893 + 0.514893 + 0.514893 + 0.514893 + 0.514893 + 0.514893 + 0.515137 + 0.515137 + 0.515137 + 0.515137 + 0.515137 + 0.515137 + 0.515137 + 0.515137 + 0.515137 + 0.515137 + 0.515137 + 0.515137 + 0.515137 + 0.515137 + 0.515381 + 0.515381 + 0.515381 + 0.515381 + 0.515381 + 0.515381 + 0.515381 + 0.515381 + 0.515381 + 0.515381 + 0.515381 + 0.515381 + 0.515381 + 0.515381 + 0.515381 + 0.515625 + 0.515625 + 0.515625 + 0.515625 + 0.515625 + 0.515625 + 0.515625 + 0.515625 + 0.515625 + 0.515625 + 0.515625 + 0.515625 + 0.515625 + 0.515625 + 0.515869 + 0.515869 + 0.515869 + 0.515869 + 0.515869 + 0.515869 + 0.515869 + 0.515869 + 0.515869 + 0.515869 + 0.515869 + 0.515869 + 0.515869 + 0.515869 + 0.516113 + 0.516113 + 0.516113 + 0.516113 + 0.516113 + 0.516113 + 0.516113 + 0.516113 + 0.516113 + 0.516113 + 0.516113 + 0.516113 + 0.516113 + 0.516113 + 0.516113 + 0.516357 + 0.516357 + 0.516357 + 0.516357 + 0.516357 + 0.516357 + 0.516357 + 0.516357 + 0.516357 + 0.516357 + 0.516357 + 0.516357 + 0.516357 + 0.516357 + 0.516602 + 0.516602 + 0.516602 + 0.516602 + 0.516602 + 0.516602 + 0.516602 + 0.516602 + 0.516602 + 0.516602 + 0.516602 + 0.516602 + 0.516602 + 0.516602 + 0.516602 + 0.516846 + 0.516846 + 0.516846 + 0.516846 + 0.516846 + 0.516846 + 0.516846 + 0.516846 + 0.516846 + 0.516846 + 0.516846 + 0.516846 + 0.516846 + 0.516846 + 0.517090 + 0.517090 + 0.517090 + 0.517090 + 0.517090 + 0.517090 + 0.517090 + 0.517090 + 0.517090 + 0.517090 + 0.517090 + 0.517090 + 0.517090 + 0.517090 + 0.517090 + 0.517334 + 0.517334 + 0.517334 + 0.517334 + 0.517334 + 0.517334 + 0.517334 + 0.517334 + 0.517334 + 0.517334 + 0.517334 + 0.517334 + 0.517334 + 0.517334 + 0.517578 + 0.517578 + 0.517578 + 0.517578 + 0.517578 + 0.517578 + 0.517578 + 0.517578 + 0.517578 + 0.517578 + 0.517578 + 0.517578 + 0.517578 + 0.517578 + 0.517578 + 0.517822 + 0.517822 + 0.517822 + 0.517822 + 0.517822 + 0.517822 + 0.517822 + 0.517822 + 0.517822 + 0.517822 + 0.517822 + 0.517822 + 0.517822 + 0.517822 + 0.518066 + 0.518066 + 0.518066 + 0.518066 + 0.518066 + 0.518066 + 0.518066 + 0.518066 + 0.518066 + 0.518066 + 0.518066 + 0.518066 + 0.518066 + 0.518066 + 0.518066 + 0.518311 + 0.518311 + 0.518311 + 0.518311 + 0.518311 + 0.518311 + 0.518311 + 0.518311 + 0.518311 + 0.518311 + 0.518311 + 0.518311 + 0.518311 + 0.518311 + 0.518555 + 0.518555 + 0.518555 + 0.518555 + 0.518555 + 0.518555 + 0.518555 + 0.518555 + 0.518555 + 0.518555 + 0.518555 + 0.518555 + 0.518555 + 0.518555 + 0.518555 + 0.518799 + 0.518799 + 0.518799 + 0.518799 + 0.518799 + 0.518799 + 0.518799 + 0.518799 + 0.518799 + 0.518799 + 0.518799 + 0.518799 + 0.518799 + 0.518799 + 0.518799 + 0.519043 + 0.519043 + 0.519043 + 0.519043 + 0.519043 + 0.519043 + 0.519043 + 0.519043 + 0.519043 + 0.519043 + 0.519043 + 0.519043 + 0.519043 + 0.519043 + 0.519287 + 0.519287 + 0.519287 + 0.519287 + 0.519287 + 0.519287 + 0.519287 + 0.519287 + 0.519287 + 0.519287 + 0.519287 + 0.519287 + 0.519287 + 0.519287 + 0.519287 + 0.519531 + 0.519531 + 0.519531 + 0.519531 + 0.519531 + 0.519531 + 0.519531 + 0.519531 + 0.519531 + 0.519531 + 0.519531 + 0.519531 + 0.519531 + 0.519531 + 0.519775 + 0.519775 + 0.519775 + 0.519775 + 0.519775 + 0.519775 + 0.519775 + 0.519775 + 0.519775 + 0.519775 + 0.519775 + 0.519775 + 0.519775 + 0.519775 + 0.519775 + 0.520020 + 0.520020 + 0.520020 + 0.520020 + 0.520020 + 0.520020 + 0.520020 + 0.520020 + 0.520020 + 0.520020 + 0.520020 + 0.520020 + 0.520020 + 0.520020 + 0.520020 + 0.520264 + 0.520264 + 0.520264 + 0.520264 + 0.520264 + 0.520264 + 0.520264 + 0.520264 + 0.520264 + 0.520264 + 0.520264 + 0.520264 + 0.520264 + 0.520264 + 0.520508 + 0.520508 + 0.520508 + 0.520508 + 0.520508 + 0.520508 + 0.520508 + 0.520508 + 0.520508 + 0.520508 + 0.520508 + 0.520508 + 0.520508 + 0.520508 + 0.520508 + 0.520752 + 0.520752 + 0.520752 + 0.520752 + 0.520752 + 0.520752 + 0.520752 + 0.520752 + 0.520752 + 0.520752 + 0.520752 + 0.520752 + 0.520752 + 0.520752 + 0.520752 + 0.520996 + 0.520996 + 0.520996 + 0.520996 + 0.520996 + 0.520996 + 0.520996 + 0.520996 + 0.520996 + 0.520996 + 0.520996 + 0.520996 + 0.520996 + 0.520996 + 0.521240 + 0.521240 + 0.521240 + 0.521240 + 0.521240 + 0.521240 + 0.521240 + 0.521240 + 0.521240 + 0.521240 + 0.521240 + 0.521240 + 0.521240 + 0.521240 + 0.521240 + 0.521484 + 0.521484 + 0.521484 + 0.521484 + 0.521484 + 0.521484 + 0.521484 + 0.521484 + 0.521484 + 0.521484 + 0.521484 + 0.521484 + 0.521484 + 0.521484 + 0.521484 + 0.521729 + 0.521729 + 0.521729 + 0.521729 + 0.521729 + 0.521729 + 0.521729 + 0.521729 + 0.521729 + 0.521729 + 0.521729 + 0.521729 + 0.521729 + 0.521729 + 0.521973 + 0.521973 + 0.521973 + 0.521973 + 0.521973 + 0.521973 + 0.521973 + 0.521973 + 0.521973 + 0.521973 + 0.521973 + 0.521973 + 0.521973 + 0.521973 + 0.521973 + 0.522217 + 0.522217 + 0.522217 + 0.522217 + 0.522217 + 0.522217 + 0.522217 + 0.522217 + 0.522217 + 0.522217 + 0.522217 + 0.522217 + 0.522217 + 0.522217 + 0.522217 + 0.522461 + 0.522461 + 0.522461 + 0.522461 + 0.522461 + 0.522461 + 0.522461 + 0.522461 + 0.522461 + 0.522461 + 0.522461 + 0.522461 + 0.522461 + 0.522461 + 0.522705 + 0.522705 + 0.522705 + 0.522705 + 0.522705 + 0.522705 + 0.522705 + 0.522705 + 0.522705 + 0.522705 + 0.522705 + 0.522705 + 0.522705 + 0.522705 + 0.522705 + 0.522949 + 0.522949 + 0.522949 + 0.522949 + 0.522949 + 0.522949 + 0.522949 + 0.522949 + 0.522949 + 0.522949 + 0.522949 + 0.522949 + 0.522949 + 0.522949 + 0.522949 + 0.523193 + 0.523193 + 0.523193 + 0.523193 + 0.523193 + 0.523193 + 0.523193 + 0.523193 + 0.523193 + 0.523193 + 0.523193 + 0.523193 + 0.523193 + 0.523193 + 0.523193 + 0.523438 + 0.523438 + 0.523438 + 0.523438 + 0.523438 + 0.523438 + 0.523438 + 0.523438 + 0.523438 + 0.523438 + 0.523438 + 0.523438 + 0.523438 + 0.523438 + 0.523682 + 0.523682 + 0.523682 + 0.523682 + 0.523682 + 0.523682 + 0.523682 + 0.523682 + 0.523682 + 0.523682 + 0.523682 + 0.523682 + 0.523682 + 0.523682 + 0.523682 + 0.523926 + 0.523926 + 0.523926 + 0.523926 + 0.523926 + 0.523926 + 0.523926 + 0.523926 + 0.523926 + 0.523926 + 0.523926 + 0.523926 + 0.523926 + 0.523926 + 0.523926 + 0.524170 + 0.524170 + 0.524170 + 0.524170 + 0.524170 + 0.524170 + 0.524170 + 0.524170 + 0.524170 + 0.524170 + 0.524170 + 0.524170 + 0.524170 + 0.524170 + 0.524170 + 0.524414 + 0.524414 + 0.524414 + 0.524414 + 0.524414 + 0.524414 + 0.524414 + 0.524414 + 0.524414 + 0.524414 + 0.524414 + 0.524414 + 0.524414 + 0.524414 + 0.524414 + 0.524658 + 0.524658 + 0.524658 + 0.524658 + 0.524658 + 0.524658 + 0.524658 + 0.524658 + 0.524658 + 0.524658 + 0.524658 + 0.524658 + 0.524658 + 0.524658 + 0.524658 + 0.524902 + 0.524902 + 0.524902 + 0.524902 + 0.524902 + 0.524902 + 0.524902 + 0.524902 + 0.524902 + 0.524902 + 0.524902 + 0.524902 + 0.524902 + 0.524902 + 0.525146 + 0.525146 + 0.525146 + 0.525146 + 0.525146 + 0.525146 + 0.525146 + 0.525146 + 0.525146 + 0.525146 + 0.525146 + 0.525146 + 0.525146 + 0.525146 + 0.525146 + 0.525391 + 0.525391 + 0.525391 + 0.525391 + 0.525391 + 0.525391 + 0.525391 + 0.525391 + 0.525391 + 0.525391 + 0.525391 + 0.525391 + 0.525391 + 0.525391 + 0.525391 + 0.525635 + 0.525635 + 0.525635 + 0.525635 + 0.525635 + 0.525635 + 0.525635 + 0.525635 + 0.525635 + 0.525635 + 0.525635 + 0.525635 + 0.525635 + 0.525635 + 0.525635 + 0.525879 + 0.525879 + 0.525879 + 0.525879 + 0.525879 + 0.525879 + 0.525879 + 0.525879 + 0.525879 + 0.525879 + 0.525879 + 0.525879 + 0.525879 + 0.525879 + 0.525879 + 0.526123 + 0.526123 + 0.526123 + 0.526123 + 0.526123 + 0.526123 + 0.526123 + 0.526123 + 0.526123 + 0.526123 + 0.526123 + 0.526123 + 0.526123 + 0.526123 + 0.526123 + 0.526367 + 0.526367 + 0.526367 + 0.526367 + 0.526367 + 0.526367 + 0.526367 + 0.526367 + 0.526367 + 0.526367 + 0.526367 + 0.526367 + 0.526367 + 0.526367 + 0.526367 + 0.526611 + 0.526611 + 0.526611 + 0.526611 + 0.526611 + 0.526611 + 0.526611 + 0.526611 + 0.526611 + 0.526611 + 0.526611 + 0.526611 + 0.526611 + 0.526611 + 0.526611 + 0.526855 + 0.526855 + 0.526855 + 0.526855 + 0.526855 + 0.526855 + 0.526855 + 0.526855 + 0.526855 + 0.526855 + 0.526855 + 0.526855 + 0.526855 + 0.526855 + 0.526855 + 0.527100 + 0.527100 + 0.527100 + 0.527100 + 0.527100 + 0.527100 + 0.527100 + 0.527100 + 0.527100 + 0.527100 + 0.527100 + 0.527100 + 0.527100 + 0.527100 + 0.527100 + 0.527344 + 0.527344 + 0.527344 + 0.527344 + 0.527344 + 0.527344 + 0.527344 + 0.527344 + 0.527344 + 0.527344 + 0.527344 + 0.527344 + 0.527344 + 0.527344 + 0.527588 + 0.527588 + 0.527588 + 0.527588 + 0.527588 + 0.527588 + 0.527588 + 0.527588 + 0.527588 + 0.527588 + 0.527588 + 0.527588 + 0.527588 + 0.527588 + 0.527588 + 0.527832 + 0.527832 + 0.527832 + 0.527832 + 0.527832 + 0.527832 + 0.527832 + 0.527832 + 0.527832 + 0.527832 + 0.527832 + 0.527832 + 0.527832 + 0.527832 + 0.527832 + 0.528076 + 0.528076 + 0.528076 + 0.528076 + 0.528076 + 0.528076 + 0.528076 + 0.528076 + 0.528076 + 0.528076 + 0.528076 + 0.528076 + 0.528076 + 0.528076 + 0.528076 + 0.528320 + 0.528320 + 0.528320 + 0.528320 + 0.528320 + 0.528320 + 0.528320 + 0.528320 + 0.528320 + 0.528320 + 0.528320 + 0.528320 + 0.528320 + 0.528320 + 0.528320 + 0.528564 + 0.528564 + 0.528564 + 0.528564 + 0.528564 + 0.528564 + 0.528564 + 0.528564 + 0.528564 + 0.528564 + 0.528564 + 0.528564 + 0.528564 + 0.528564 + 0.528564 + 0.528809 + 0.528809 + 0.528809 + 0.528809 + 0.528809 + 0.528809 + 0.528809 + 0.528809 + 0.528809 + 0.528809 + 0.528809 + 0.528809 + 0.528809 + 0.528809 + 0.528809 + 0.529053 + 0.529053 + 0.529053 + 0.529053 + 0.529053 + 0.529053 + 0.529053 + 0.529053 + 0.529053 + 0.529053 + 0.529053 + 0.529053 + 0.529053 + 0.529053 + 0.529053 + 0.529053 + 0.529297 + 0.529297 + 0.529297 + 0.529297 + 0.529297 + 0.529297 + 0.529297 + 0.529297 + 0.529297 + 0.529297 + 0.529297 + 0.529297 + 0.529297 + 0.529297 + 0.529297 + 0.529541 + 0.529541 + 0.529541 + 0.529541 + 0.529541 + 0.529541 + 0.529541 + 0.529541 + 0.529541 + 0.529541 + 0.529541 + 0.529541 + 0.529541 + 0.529541 + 0.529541 + 0.529785 + 0.529785 + 0.529785 + 0.529785 + 0.529785 + 0.529785 + 0.529785 + 0.529785 + 0.529785 + 0.529785 + 0.529785 + 0.529785 + 0.529785 + 0.529785 + 0.529785 + 0.530029 + 0.530029 + 0.530029 + 0.530029 + 0.530029 + 0.530029 + 0.530029 + 0.530029 + 0.530029 + 0.530029 + 0.530029 + 0.530029 + 0.530029 + 0.530029 + 0.530029 + 0.530273 + 0.530273 + 0.530273 + 0.530273 + 0.530273 + 0.530273 + 0.530273 + 0.530273 + 0.530273 + 0.530273 + 0.530273 + 0.530273 + 0.530273 + 0.530273 + 0.530273 + 0.530518 + 0.530518 + 0.530518 + 0.530518 + 0.530518 + 0.530518 + 0.530518 + 0.530518 + 0.530518 + 0.530518 + 0.530518 + 0.530518 + 0.530518 + 0.530518 + 0.530518 + 0.530762 + 0.530762 + 0.530762 + 0.530762 + 0.530762 + 0.530762 + 0.530762 + 0.530762 + 0.530762 + 0.530762 + 0.530762 + 0.530762 + 0.530762 + 0.530762 + 0.530762 + 0.531006 + 0.531006 + 0.531006 + 0.531006 + 0.531006 + 0.531006 + 0.531006 + 0.531006 + 0.531006 + 0.531006 + 0.531006 + 0.531006 + 0.531006 + 0.531006 + 0.531006 + 0.531250 + 0.531250 + 0.531250 + 0.531250 + 0.531250 + 0.531250 + 0.531250 + 0.531250 + 0.531250 + 0.531250 + 0.531250 + 0.531250 + 0.531250 + 0.531250 + 0.531250 + 0.531494 + 0.531494 + 0.531494 + 0.531494 + 0.531494 + 0.531494 + 0.531494 + 0.531494 + 0.531494 + 0.531494 + 0.531494 + 0.531494 + 0.531494 + 0.531494 + 0.531494 + 0.531738 + 0.531738 + 0.531738 + 0.531738 + 0.531738 + 0.531738 + 0.531738 + 0.531738 + 0.531738 + 0.531738 + 0.531738 + 0.531738 + 0.531738 + 0.531738 + 0.531738 + 0.531738 + 0.531982 + 0.531982 + 0.531982 + 0.531982 + 0.531982 + 0.531982 + 0.531982 + 0.531982 + 0.531982 + 0.531982 + 0.531982 + 0.531982 + 0.531982 + 0.531982 + 0.531982 + 0.532227 + 0.532227 + 0.532227 + 0.532227 + 0.532227 + 0.532227 + 0.532227 + 0.532227 + 0.532227 + 0.532227 + 0.532227 + 0.532227 + 0.532227 + 0.532227 + 0.532227 + 0.532471 + 0.532471 + 0.532471 + 0.532471 + 0.532471 + 0.532471 + 0.532471 + 0.532471 + 0.532471 + 0.532471 + 0.532471 + 0.532471 + 0.532471 + 0.532471 + 0.532471 + 0.532715 + 0.532715 + 0.532715 + 0.532715 + 0.532715 + 0.532715 + 0.532715 + 0.532715 + 0.532715 + 0.532715 + 0.532715 + 0.532715 + 0.532715 + 0.532715 + 0.532715 + 0.532959 + 0.532959 + 0.532959 + 0.532959 + 0.532959 + 0.532959 + 0.532959 + 0.532959 + 0.532959 + 0.532959 + 0.532959 + 0.532959 + 0.532959 + 0.532959 + 0.532959 + 0.532959 + 0.533203 + 0.533203 + 0.533203 + 0.533203 + 0.533203 + 0.533203 + 0.533203 + 0.533203 + 0.533203 + 0.533203 + 0.533203 + 0.533203 + 0.533203 + 0.533203 + 0.533203 + 0.533447 + 0.533447 + 0.533447 + 0.533447 + 0.533447 + 0.533447 + 0.533447 + 0.533447 + 0.533447 + 0.533447 + 0.533447 + 0.533447 + 0.533447 + 0.533447 + 0.533447 + 0.533691 + 0.533691 + 0.533691 + 0.533691 + 0.533691 + 0.533691 + 0.533691 + 0.533691 + 0.533691 + 0.533691 + 0.533691 + 0.533691 + 0.533691 + 0.533691 + 0.533691 + 0.533936 + 0.533936 + 0.533936 + 0.533936 + 0.533936 + 0.533936 + 0.533936 + 0.533936 + 0.533936 + 0.533936 + 0.533936 + 0.533936 + 0.533936 + 0.533936 + 0.533936 + 0.533936 + 0.534180 + 0.534180 + 0.534180 + 0.534180 + 0.534180 + 0.534180 + 0.534180 + 0.534180 + 0.534180 + 0.534180 + 0.534180 + 0.534180 + 0.534180 + 0.534180 + 0.534180 + 0.534424 + 0.534424 + 0.534424 + 0.534424 + 0.534424 + 0.534424 + 0.534424 + 0.534424 + 0.534424 + 0.534424 + 0.534424 + 0.534424 + 0.534424 + 0.534424 + 0.534424 + 0.534668 + 0.534668 + 0.534668 + 0.534668 + 0.534668 + 0.534668 + 0.534668 + 0.534668 + 0.534668 + 0.534668 + 0.534668 + 0.534668 + 0.534668 + 0.534668 + 0.534668 + 0.534912 + 0.534912 + 0.534912 + 0.534912 + 0.534912 + 0.534912 + 0.534912 + 0.534912 + 0.534912 + 0.534912 + 0.534912 + 0.534912 + 0.534912 + 0.534912 + 0.534912 + 0.534912 + 0.535156 + 0.535156 + 0.535156 + 0.535156 + 0.535156 + 0.535156 + 0.535156 + 0.535156 + 0.535156 + 0.535156 + 0.535156 + 0.535156 + 0.535156 + 0.535156 + 0.535156 + 0.535400 + 0.535400 + 0.535400 + 0.535400 + 0.535400 + 0.535400 + 0.535400 + 0.535400 + 0.535400 + 0.535400 + 0.535400 + 0.535400 + 0.535400 + 0.535400 + 0.535400 + 0.535645 + 0.535645 + 0.535645 + 0.535645 + 0.535645 + 0.535645 + 0.535645 + 0.535645 + 0.535645 + 0.535645 + 0.535645 + 0.535645 + 0.535645 + 0.535645 + 0.535645 + 0.535645 + 0.535889 + 0.535889 + 0.535889 + 0.535889 + 0.535889 + 0.535889 + 0.535889 + 0.535889 + 0.535889 + 0.535889 + 0.535889 + 0.535889 + 0.535889 + 0.535889 + 0.535889 + 0.536133 + 0.536133 + 0.536133 + 0.536133 + 0.536133 + 0.536133 + 0.536133 + 0.536133 + 0.536133 + 0.536133 + 0.536133 + 0.536133 + 0.536133 + 0.536133 + 0.536133 + 0.536377 + 0.536377 + 0.536377 + 0.536377 + 0.536377 + 0.536377 + 0.536377 + 0.536377 + 0.536377 + 0.536377 + 0.536377 + 0.536377 + 0.536377 + 0.536377 + 0.536377 + 0.536377 + 0.536621 + 0.536621 + 0.536621 + 0.536621 + 0.536621 + 0.536621 + 0.536621 + 0.536621 + 0.536621 + 0.536621 + 0.536621 + 0.536621 + 0.536621 + 0.536621 + 0.536621 + 0.536865 + 0.536865 + 0.536865 + 0.536865 + 0.536865 + 0.536865 + 0.536865 + 0.536865 + 0.536865 + 0.536865 + 0.536865 + 0.536865 + 0.536865 + 0.536865 + 0.536865 + 0.536865 + 0.537109 + 0.537109 + 0.537109 + 0.537109 + 0.537109 + 0.537109 + 0.537109 + 0.537109 + 0.537109 + 0.537109 + 0.537109 + 0.537109 + 0.537109 + 0.537109 + 0.537109 + 0.537354 + 0.537354 + 0.537354 + 0.537354 + 0.537354 + 0.537354 + 0.537354 + 0.537354 + 0.537354 + 0.537354 + 0.537354 + 0.537354 + 0.537354 + 0.537354 + 0.537354 + 0.537598 + 0.537598 + 0.537598 + 0.537598 + 0.537598 + 0.537598 + 0.537598 + 0.537598 + 0.537598 + 0.537598 + 0.537598 + 0.537598 + 0.537598 + 0.537598 + 0.537598 + 0.537598 + 0.537842 + 0.537842 + 0.537842 + 0.537842 + 0.537842 + 0.537842 + 0.537842 + 0.537842 + 0.537842 + 0.537842 + 0.537842 + 0.537842 + 0.537842 + 0.537842 + 0.537842 + 0.538086 + 0.538086 + 0.538086 + 0.538086 + 0.538086 + 0.538086 + 0.538086 + 0.538086 + 0.538086 + 0.538086 + 0.538086 + 0.538086 + 0.538086 + 0.538086 + 0.538086 + 0.538086 + 0.538330 + 0.538330 + 0.538330 + 0.538330 + 0.538330 + 0.538330 + 0.538330 + 0.538330 + 0.538330 + 0.538330 + 0.538330 + 0.538330 + 0.538330 + 0.538330 + 0.538330 + 0.538574 + 0.538574 + 0.538574 + 0.538574 + 0.538574 + 0.538574 + 0.538574 + 0.538574 + 0.538574 + 0.538574 + 0.538574 + 0.538574 + 0.538574 + 0.538574 + 0.538574 + 0.538574 + 0.538818 + 0.538818 + 0.538818 + 0.538818 + 0.538818 + 0.538818 + 0.538818 + 0.538818 + 0.538818 + 0.538818 + 0.538818 + 0.538818 + 0.538818 + 0.538818 + 0.538818 + 0.539062 + 0.539062 + 0.539062 + 0.539062 + 0.539062 + 0.539062 + 0.539062 + 0.539062 + 0.539062 + 0.539062 + 0.539062 + 0.539062 + 0.539062 + 0.539062 + 0.539062 + 0.539062 + 0.539307 + 0.539307 + 0.539307 + 0.539307 + 0.539307 + 0.539307 + 0.539307 + 0.539307 + 0.539307 + 0.539307 + 0.539307 + 0.539307 + 0.539307 + 0.539307 + 0.539307 + 0.539551 + 0.539551 + 0.539551 + 0.539551 + 0.539551 + 0.539551 + 0.539551 + 0.539551 + 0.539551 + 0.539551 + 0.539551 + 0.539551 + 0.539551 + 0.539551 + 0.539551 + 0.539551 + 0.539795 + 0.539795 + 0.539795 + 0.539795 + 0.539795 + 0.539795 + 0.539795 + 0.539795 + 0.539795 + 0.539795 + 0.539795 + 0.539795 + 0.539795 + 0.539795 + 0.539795 + 0.540039 + 0.540039 + 0.540039 + 0.540039 + 0.540039 + 0.540039 + 0.540039 + 0.540039 + 0.540039 + 0.540039 + 0.540039 + 0.540039 + 0.540039 + 0.540039 + 0.540039 + 0.540039 + 0.540283 + 0.540283 + 0.540283 + 0.540283 + 0.540283 + 0.540283 + 0.540283 + 0.540283 + 0.540283 + 0.540283 + 0.540283 + 0.540283 + 0.540283 + 0.540283 + 0.540283 + 0.540527 + 0.540527 + 0.540527 + 0.540527 + 0.540527 + 0.540527 + 0.540527 + 0.540527 + 0.540527 + 0.540527 + 0.540527 + 0.540527 + 0.540527 + 0.540527 + 0.540527 + 0.540527 + 0.540771 + 0.540771 + 0.540771 + 0.540771 + 0.540771 + 0.540771 + 0.540771 + 0.540771 + 0.540771 + 0.540771 + 0.540771 + 0.540771 + 0.540771 + 0.540771 + 0.540771 + 0.541016 + 0.541016 + 0.541016 + 0.541016 + 0.541016 + 0.541016 + 0.541016 + 0.541016 + 0.541016 + 0.541016 + 0.541016 + 0.541016 + 0.541016 + 0.541016 + 0.541016 + 0.541016 + 0.541260 + 0.541260 + 0.541260 + 0.541260 + 0.541260 + 0.541260 + 0.541260 + 0.541260 + 0.541260 + 0.541260 + 0.541260 + 0.541260 + 0.541260 + 0.541260 + 0.541260 + 0.541260 + 0.541504 + 0.541504 + 0.541504 + 0.541504 + 0.541504 + 0.541504 + 0.541504 + 0.541504 + 0.541504 + 0.541504 + 0.541504 + 0.541504 + 0.541504 + 0.541504 + 0.541504 + 0.541748 + 0.541748 + 0.541748 + 0.541748 + 0.541748 + 0.541748 + 0.541748 + 0.541748 + 0.541748 + 0.541748 + 0.541748 + 0.541748 + 0.541748 + 0.541748 + 0.541748 + 0.541748 + 0.541992 + 0.541992 + 0.541992 + 0.541992 + 0.541992 + 0.541992 + 0.541992 + 0.541992 + 0.541992 + 0.541992 + 0.541992 + 0.541992 + 0.541992 + 0.541992 + 0.541992 + 0.542236 + 0.542236 + 0.542236 + 0.542236 + 0.542236 + 0.542236 + 0.542236 + 0.542236 + 0.542236 + 0.542236 + 0.542236 + 0.542236 + 0.542236 + 0.542236 + 0.542236 + 0.542236 + 0.542480 + 0.542480 + 0.542480 + 0.542480 + 0.542480 + 0.542480 + 0.542480 + 0.542480 + 0.542480 + 0.542480 + 0.542480 + 0.542480 + 0.542480 + 0.542480 + 0.542480 + 0.542480 + 0.542725 + 0.542725 + 0.542725 + 0.542725 + 0.542725 + 0.542725 + 0.542725 + 0.542725 + 0.542725 + 0.542725 + 0.542725 + 0.542725 + 0.542725 + 0.542725 + 0.542725 + 0.542969 + 0.542969 + 0.542969 + 0.542969 + 0.542969 + 0.542969 + 0.542969 + 0.542969 + 0.542969 + 0.542969 + 0.542969 + 0.542969 + 0.542969 + 0.542969 + 0.542969 + 0.542969 + 0.543213 + 0.543213 + 0.543213 + 0.543213 + 0.543213 + 0.543213 + 0.543213 + 0.543213 + 0.543213 + 0.543213 + 0.543213 + 0.543213 + 0.543213 + 0.543213 + 0.543213 + 0.543213 + 0.543457 + 0.543457 + 0.543457 + 0.543457 + 0.543457 + 0.543457 + 0.543457 + 0.543457 + 0.543457 + 0.543457 + 0.543457 + 0.543457 + 0.543457 + 0.543457 + 0.543457 + 0.543701 + 0.543701 + 0.543701 + 0.543701 + 0.543701 + 0.543701 + 0.543701 + 0.543701 + 0.543701 + 0.543701 + 0.543701 + 0.543701 + 0.543701 + 0.543701 + 0.543701 + 0.543701 + 0.543945 + 0.543945 + 0.543945 + 0.543945 + 0.543945 + 0.543945 + 0.543945 + 0.543945 + 0.543945 + 0.543945 + 0.543945 + 0.543945 + 0.543945 + 0.543945 + 0.543945 + 0.543945 + 0.544189 + 0.544189 + 0.544189 + 0.544189 + 0.544189 + 0.544189 + 0.544189 + 0.544189 + 0.544189 + 0.544189 + 0.544189 + 0.544189 + 0.544189 + 0.544189 + 0.544189 + 0.544189 + 0.544434 + 0.544434 + 0.544434 + 0.544434 + 0.544434 + 0.544434 + 0.544434 + 0.544434 + 0.544434 + 0.544434 + 0.544434 + 0.544434 + 0.544434 + 0.544434 + 0.544434 + 0.544678 + 0.544678 + 0.544678 + 0.544678 + 0.544678 + 0.544678 + 0.544678 + 0.544678 + 0.544678 + 0.544678 + 0.544678 + 0.544678 + 0.544678 + 0.544678 + 0.544678 + 0.544678 + 0.544922 + 0.544922 + 0.544922 + 0.544922 + 0.544922 + 0.544922 + 0.544922 + 0.544922 + 0.544922 + 0.544922 + 0.544922 + 0.544922 + 0.544922 + 0.544922 + 0.544922 + 0.544922 + 0.545166 + 0.545166 + 0.545166 + 0.545166 + 0.545166 + 0.545166 + 0.545166 + 0.545166 + 0.545166 + 0.545166 + 0.545166 + 0.545166 + 0.545166 + 0.545166 + 0.545166 + 0.545166 + 0.545410 + 0.545410 + 0.545410 + 0.545410 + 0.545410 + 0.545410 + 0.545410 + 0.545410 + 0.545410 + 0.545410 + 0.545410 + 0.545410 + 0.545410 + 0.545410 + 0.545410 + 0.545654 + 0.545654 + 0.545654 + 0.545654 + 0.545654 + 0.545654 + 0.545654 + 0.545654 + 0.545654 + 0.545654 + 0.545654 + 0.545654 + 0.545654 + 0.545654 + 0.545654 + 0.545654 + 0.545898 + 0.545898 + 0.545898 + 0.545898 + 0.545898 + 0.545898 + 0.545898 + 0.545898 + 0.545898 + 0.545898 + 0.545898 + 0.545898 + 0.545898 + 0.545898 + 0.545898 + 0.545898 + 0.546143 + 0.546143 + 0.546143 + 0.546143 + 0.546143 + 0.546143 + 0.546143 + 0.546143 + 0.546143 + 0.546143 + 0.546143 + 0.546143 + 0.546143 + 0.546143 + 0.546143 + 0.546143 + 0.546387 + 0.546387 + 0.546387 + 0.546387 + 0.546387 + 0.546387 + 0.546387 + 0.546387 + 0.546387 + 0.546387 + 0.546387 + 0.546387 + 0.546387 + 0.546387 + 0.546387 + 0.546387 + 0.546631 + 0.546631 + 0.546631 + 0.546631 + 0.546631 + 0.546631 + 0.546631 + 0.546631 + 0.546631 + 0.546631 + 0.546631 + 0.546631 + 0.546631 + 0.546631 + 0.546631 + 0.546875 + 0.546875 + 0.546875 + 0.546875 + 0.546875 + 0.546875 + 0.546875 + 0.546875 + 0.546875 + 0.546875 + 0.546875 + 0.546875 + 0.546875 + 0.546875 + 0.546875 + 0.546875 + 0.547119 + 0.547119 + 0.547119 + 0.547119 + 0.547119 + 0.547119 + 0.547119 + 0.547119 + 0.547119 + 0.547119 + 0.547119 + 0.547119 + 0.547119 + 0.547119 + 0.547119 + 0.547119 + 0.547363 + 0.547363 + 0.547363 + 0.547363 + 0.547363 + 0.547363 + 0.547363 + 0.547363 + 0.547363 + 0.547363 + 0.547363 + 0.547363 + 0.547363 + 0.547363 + 0.547363 + 0.547363 + 0.547607 + 0.547607 + 0.547607 + 0.547607 + 0.547607 + 0.547607 + 0.547607 + 0.547607 + 0.547607 + 0.547607 + 0.547607 + 0.547607 + 0.547607 + 0.547607 + 0.547607 + 0.547607 + 0.547852 + 0.547852 + 0.547852 + 0.547852 + 0.547852 + 0.547852 + 0.547852 + 0.547852 + 0.547852 + 0.547852 + 0.547852 + 0.547852 + 0.547852 + 0.547852 + 0.547852 + 0.547852 + 0.548096 + 0.548096 + 0.548096 + 0.548096 + 0.548096 + 0.548096 + 0.548096 + 0.548096 + 0.548096 + 0.548096 + 0.548096 + 0.548096 + 0.548096 + 0.548096 + 0.548096 + 0.548096 + 0.548340 + 0.548340 + 0.548340 + 0.548340 + 0.548340 + 0.548340 + 0.548340 + 0.548340 + 0.548340 + 0.548340 + 0.548340 + 0.548340 + 0.548340 + 0.548340 + 0.548340 + 0.548340 + 0.548584 + 0.548584 + 0.548584 + 0.548584 + 0.548584 + 0.548584 + 0.548584 + 0.548584 + 0.548584 + 0.548584 + 0.548584 + 0.548584 + 0.548584 + 0.548584 + 0.548584 + 0.548584 + 0.548828 + 0.548828 + 0.548828 + 0.548828 + 0.548828 + 0.548828 + 0.548828 + 0.548828 + 0.548828 + 0.548828 + 0.548828 + 0.548828 + 0.548828 + 0.548828 + 0.548828 + 0.548828 + 0.549072 + 0.549072 + 0.549072 + 0.549072 + 0.549072 + 0.549072 + 0.549072 + 0.549072 + 0.549072 + 0.549072 + 0.549072 + 0.549072 + 0.549072 + 0.549072 + 0.549072 + 0.549316 + 0.549316 + 0.549316 + 0.549316 + 0.549316 + 0.549316 + 0.549316 + 0.549316 + 0.549316 + 0.549316 + 0.549316 + 0.549316 + 0.549316 + 0.549316 + 0.549316 + 0.549316 + 0.549561 + 0.549561 + 0.549561 + 0.549561 + 0.549561 + 0.549561 + 0.549561 + 0.549561 + 0.549561 + 0.549561 + 0.549561 + 0.549561 + 0.549561 + 0.549561 + 0.549561 + 0.549561 + 0.549805 + 0.549805 + 0.549805 + 0.549805 + 0.549805 + 0.549805 + 0.549805 + 0.549805 + 0.549805 + 0.549805 + 0.549805 + 0.549805 + 0.549805 + 0.549805 + 0.549805 + 0.549805 + 0.550049 + 0.550049 + 0.550049 + 0.550049 + 0.550049 + 0.550049 + 0.550049 + 0.550049 + 0.550049 + 0.550049 + 0.550049 + 0.550049 + 0.550049 + 0.550049 + 0.550049 + 0.550049 + 0.550293 + 0.550293 + 0.550293 + 0.550293 + 0.550293 + 0.550293 + 0.550293 + 0.550293 + 0.550293 + 0.550293 + 0.550293 + 0.550293 + 0.550293 + 0.550293 + 0.550293 + 0.550293 + 0.550537 + 0.550537 + 0.550537 + 0.550537 + 0.550537 + 0.550537 + 0.550537 + 0.550537 + 0.550537 + 0.550537 + 0.550537 + 0.550537 + 0.550537 + 0.550537 + 0.550537 + 0.550537 + 0.550781 + 0.550781 + 0.550781 + 0.550781 + 0.550781 + 0.550781 + 0.550781 + 0.550781 + 0.550781 + 0.550781 + 0.550781 + 0.550781 + 0.550781 + 0.550781 + 0.550781 + 0.550781 + 0.551025 + 0.551025 + 0.551025 + 0.551025 + 0.551025 + 0.551025 + 0.551025 + 0.551025 + 0.551025 + 0.551025 + 0.551025 + 0.551025 + 0.551025 + 0.551025 + 0.551025 + 0.551025 + 0.551025 + 0.551270 + 0.551270 + 0.551270 + 0.551270 + 0.551270 + 0.551270 + 0.551270 + 0.551270 + 0.551270 + 0.551270 + 0.551270 + 0.551270 + 0.551270 + 0.551270 + 0.551270 + 0.551270 + 0.551514 + 0.551514 + 0.551514 + 0.551514 + 0.551514 + 0.551514 + 0.551514 + 0.551514 + 0.551514 + 0.551514 + 0.551514 + 0.551514 + 0.551514 + 0.551514 + 0.551514 + 0.551514 + 0.551758 + 0.551758 + 0.551758 + 0.551758 + 0.551758 + 0.551758 + 0.551758 + 0.551758 + 0.551758 + 0.551758 + 0.551758 + 0.551758 + 0.551758 + 0.551758 + 0.551758 + 0.551758 + 0.552002 + 0.552002 + 0.552002 + 0.552002 + 0.552002 + 0.552002 + 0.552002 + 0.552002 + 0.552002 + 0.552002 + 0.552002 + 0.552002 + 0.552002 + 0.552002 + 0.552002 + 0.552002 + 0.552246 + 0.552246 + 0.552246 + 0.552246 + 0.552246 + 0.552246 + 0.552246 + 0.552246 + 0.552246 + 0.552246 + 0.552246 + 0.552246 + 0.552246 + 0.552246 + 0.552246 + 0.552246 + 0.552490 + 0.552490 + 0.552490 + 0.552490 + 0.552490 + 0.552490 + 0.552490 + 0.552490 + 0.552490 + 0.552490 + 0.552490 + 0.552490 + 0.552490 + 0.552490 + 0.552490 + 0.552490 + 0.552734 + 0.552734 + 0.552734 + 0.552734 + 0.552734 + 0.552734 + 0.552734 + 0.552734 + 0.552734 + 0.552734 + 0.552734 + 0.552734 + 0.552734 + 0.552734 + 0.552734 + 0.552734 + 0.552979 + 0.552979 + 0.552979 + 0.552979 + 0.552979 + 0.552979 + 0.552979 + 0.552979 + 0.552979 + 0.552979 + 0.552979 + 0.552979 + 0.552979 + 0.552979 + 0.552979 + 0.552979 + 0.553223 + 0.553223 + 0.553223 + 0.553223 + 0.553223 + 0.553223 + 0.553223 + 0.553223 + 0.553223 + 0.553223 + 0.553223 + 0.553223 + 0.553223 + 0.553223 + 0.553223 + 0.553223 + 0.553467 + 0.553467 + 0.553467 + 0.553467 + 0.553467 + 0.553467 + 0.553467 + 0.553467 + 0.553467 + 0.553467 + 0.553467 + 0.553467 + 0.553467 + 0.553467 + 0.553467 + 0.553467 + 0.553467 + 0.553711 + 0.553711 + 0.553711 + 0.553711 + 0.553711 + 0.553711 + 0.553711 + 0.553711 + 0.553711 + 0.553711 + 0.553711 + 0.553711 + 0.553711 + 0.553711 + 0.553711 + 0.553711 + 0.553955 + 0.553955 + 0.553955 + 0.553955 + 0.553955 + 0.553955 + 0.553955 + 0.553955 + 0.553955 + 0.553955 + 0.553955 + 0.553955 + 0.553955 + 0.553955 + 0.553955 + 0.553955 + 0.554199 + 0.554199 + 0.554199 + 0.554199 + 0.554199 + 0.554199 + 0.554199 + 0.554199 + 0.554199 + 0.554199 + 0.554199 + 0.554199 + 0.554199 + 0.554199 + 0.554199 + 0.554199 + 0.554443 + 0.554443 + 0.554443 + 0.554443 + 0.554443 + 0.554443 + 0.554443 + 0.554443 + 0.554443 + 0.554443 + 0.554443 + 0.554443 + 0.554443 + 0.554443 + 0.554443 + 0.554443 + 0.554688 + 0.554688 + 0.554688 + 0.554688 + 0.554688 + 0.554688 + 0.554688 + 0.554688 + 0.554688 + 0.554688 + 0.554688 + 0.554688 + 0.554688 + 0.554688 + 0.554688 + 0.554688 + 0.554688 + 0.554932 + 0.554932 + 0.554932 + 0.554932 + 0.554932 + 0.554932 + 0.554932 + 0.554932 + 0.554932 + 0.554932 + 0.554932 + 0.554932 + 0.554932 + 0.554932 + 0.554932 + 0.554932 + 0.555176 + 0.555176 + 0.555176 + 0.555176 + 0.555176 + 0.555176 + 0.555176 + 0.555176 + 0.555176 + 0.555176 + 0.555176 + 0.555176 + 0.555176 + 0.555176 + 0.555176 + 0.555176 + 0.555420 + 0.555420 + 0.555420 + 0.555420 + 0.555420 + 0.555420 + 0.555420 + 0.555420 + 0.555420 + 0.555420 + 0.555420 + 0.555420 + 0.555420 + 0.555420 + 0.555420 + 0.555420 + 0.555664 + 0.555664 + 0.555664 + 0.555664 + 0.555664 + 0.555664 + 0.555664 + 0.555664 + 0.555664 + 0.555664 + 0.555664 + 0.555664 + 0.555664 + 0.555664 + 0.555664 + 0.555664 + 0.555664 + 0.555908 + 0.555908 + 0.555908 + 0.555908 + 0.555908 + 0.555908 + 0.555908 + 0.555908 + 0.555908 + 0.555908 + 0.555908 + 0.555908 + 0.555908 + 0.555908 + 0.555908 + 0.555908 + 0.556152 + 0.556152 + 0.556152 + 0.556152 + 0.556152 + 0.556152 + 0.556152 + 0.556152 + 0.556152 + 0.556152 + 0.556152 + 0.556152 + 0.556152 + 0.556152 + 0.556152 + 0.556152 + 0.556396 + 0.556396 + 0.556396 + 0.556396 + 0.556396 + 0.556396 + 0.556396 + 0.556396 + 0.556396 + 0.556396 + 0.556396 + 0.556396 + 0.556396 + 0.556396 + 0.556396 + 0.556396 + 0.556641 + 0.556641 + 0.556641 + 0.556641 + 0.556641 + 0.556641 + 0.556641 + 0.556641 + 0.556641 + 0.556641 + 0.556641 + 0.556641 + 0.556641 + 0.556641 + 0.556641 + 0.556641 + 0.556641 + 0.556885 + 0.556885 + 0.556885 + 0.556885 + 0.556885 + 0.556885 + 0.556885 + 0.556885 + 0.556885 + 0.556885 + 0.556885 + 0.556885 + 0.556885 + 0.556885 + 0.556885 + 0.556885 + 0.557129 + 0.557129 + 0.557129 + 0.557129 + 0.557129 + 0.557129 + 0.557129 + 0.557129 + 0.557129 + 0.557129 + 0.557129 + 0.557129 + 0.557129 + 0.557129 + 0.557129 + 0.557129 + 0.557373 + 0.557373 + 0.557373 + 0.557373 + 0.557373 + 0.557373 + 0.557373 + 0.557373 + 0.557373 + 0.557373 + 0.557373 + 0.557373 + 0.557373 + 0.557373 + 0.557373 + 0.557373 + 0.557373 + 0.557617 + 0.557617 + 0.557617 + 0.557617 + 0.557617 + 0.557617 + 0.557617 + 0.557617 + 0.557617 + 0.557617 + 0.557617 + 0.557617 + 0.557617 + 0.557617 + 0.557617 + 0.557617 + 0.557861 + 0.557861 + 0.557861 + 0.557861 + 0.557861 + 0.557861 + 0.557861 + 0.557861 + 0.557861 + 0.557861 + 0.557861 + 0.557861 + 0.557861 + 0.557861 + 0.557861 + 0.557861 + 0.558105 + 0.558105 + 0.558105 + 0.558105 + 0.558105 + 0.558105 + 0.558105 + 0.558105 + 0.558105 + 0.558105 + 0.558105 + 0.558105 + 0.558105 + 0.558105 + 0.558105 + 0.558105 + 0.558105 + 0.558350 + 0.558350 + 0.558350 + 0.558350 + 0.558350 + 0.558350 + 0.558350 + 0.558350 + 0.558350 + 0.558350 + 0.558350 + 0.558350 + 0.558350 + 0.558350 + 0.558350 + 0.558350 + 0.558594 + 0.558594 + 0.558594 + 0.558594 + 0.558594 + 0.558594 + 0.558594 + 0.558594 + 0.558594 + 0.558594 + 0.558594 + 0.558594 + 0.558594 + 0.558594 + 0.558594 + 0.558594 + 0.558594 + 0.558838 + 0.558838 + 0.558838 + 0.558838 + 0.558838 + 0.558838 + 0.558838 + 0.558838 + 0.558838 + 0.558838 + 0.558838 + 0.558838 + 0.558838 + 0.558838 + 0.558838 + 0.558838 + 0.559082 + 0.559082 + 0.559082 + 0.559082 + 0.559082 + 0.559082 + 0.559082 + 0.559082 + 0.559082 + 0.559082 + 0.559082 + 0.559082 + 0.559082 + 0.559082 + 0.559082 + 0.559082 + 0.559326 + 0.559326 + 0.559326 + 0.559326 + 0.559326 + 0.559326 + 0.559326 + 0.559326 + 0.559326 + 0.559326 + 0.559326 + 0.559326 + 0.559326 + 0.559326 + 0.559326 + 0.559326 + 0.559326 + 0.559570 + 0.559570 + 0.559570 + 0.559570 + 0.559570 + 0.559570 + 0.559570 + 0.559570 + 0.559570 + 0.559570 + 0.559570 + 0.559570 + 0.559570 + 0.559570 + 0.559570 + 0.559570 + 0.559814 + 0.559814 + 0.559814 + 0.559814 + 0.559814 + 0.559814 + 0.559814 + 0.559814 + 0.559814 + 0.559814 + 0.559814 + 0.559814 + 0.559814 + 0.559814 + 0.559814 + 0.559814 + 0.559814 + 0.560059 + 0.560059 + 0.560059 + 0.560059 + 0.560059 + 0.560059 + 0.560059 + 0.560059 + 0.560059 + 0.560059 + 0.560059 + 0.560059 + 0.560059 + 0.560059 + 0.560059 + 0.560059 + 0.560303 + 0.560303 + 0.560303 + 0.560303 + 0.560303 + 0.560303 + 0.560303 + 0.560303 + 0.560303 + 0.560303 + 0.560303 + 0.560303 + 0.560303 + 0.560303 + 0.560303 + 0.560303 + 0.560303 + 0.560547 + 0.560547 + 0.560547 + 0.560547 + 0.560547 + 0.560547 + 0.560547 + 0.560547 + 0.560547 + 0.560547 + 0.560547 + 0.560547 + 0.560547 + 0.560547 + 0.560547 + 0.560547 + 0.560791 + 0.560791 + 0.560791 + 0.560791 + 0.560791 + 0.560791 + 0.560791 + 0.560791 + 0.560791 + 0.560791 + 0.560791 + 0.560791 + 0.560791 + 0.560791 + 0.560791 + 0.560791 + 0.560791 + 0.561035 + 0.561035 + 0.561035 + 0.561035 + 0.561035 + 0.561035 + 0.561035 + 0.561035 + 0.561035 + 0.561035 + 0.561035 + 0.561035 + 0.561035 + 0.561035 + 0.561035 + 0.561035 + 0.561279 + 0.561279 + 0.561279 + 0.561279 + 0.561279 + 0.561279 + 0.561279 + 0.561279 + 0.561279 + 0.561279 + 0.561279 + 0.561279 + 0.561279 + 0.561279 + 0.561279 + 0.561279 + 0.561279 + 0.561523 + 0.561523 + 0.561523 + 0.561523 + 0.561523 + 0.561523 + 0.561523 + 0.561523 + 0.561523 + 0.561523 + 0.561523 + 0.561523 + 0.561523 + 0.561523 + 0.561523 + 0.561523 + 0.561768 + 0.561768 + 0.561768 + 0.561768 + 0.561768 + 0.561768 + 0.561768 + 0.561768 + 0.561768 + 0.561768 + 0.561768 + 0.561768 + 0.561768 + 0.561768 + 0.561768 + 0.561768 + 0.561768 + 0.562012 + 0.562012 + 0.562012 + 0.562012 + 0.562012 + 0.562012 + 0.562012 + 0.562012 + 0.562012 + 0.562012 + 0.562012 + 0.562012 + 0.562012 + 0.562012 + 0.562012 + 0.562012 + 0.562256 + 0.562256 + 0.562256 + 0.562256 + 0.562256 + 0.562256 + 0.562256 + 0.562256 + 0.562256 + 0.562256 + 0.562256 + 0.562256 + 0.562256 + 0.562256 + 0.562256 + 0.562256 + 0.562256 + 0.562500 + 0.562500 + 0.562500 + 0.562500 + 0.562500 + 0.562500 + 0.562500 + 0.562500 + 0.562500 + 0.562500 + 0.562500 + 0.562500 + 0.562500 + 0.562500 + 0.562500 + 0.562500 + 0.562500 + 0.562744 + 0.562744 + 0.562744 + 0.562744 + 0.562744 + 0.562744 + 0.562744 + 0.562744 + 0.562744 + 0.562744 + 0.562744 + 0.562744 + 0.562744 + 0.562744 + 0.562744 + 0.562744 + 0.562988 + 0.562988 + 0.562988 + 0.562988 + 0.562988 + 0.562988 + 0.562988 + 0.562988 + 0.562988 + 0.562988 + 0.562988 + 0.562988 + 0.562988 + 0.562988 + 0.562988 + 0.562988 + 0.562988 + 0.563232 + 0.563232 + 0.563232 + 0.563232 + 0.563232 + 0.563232 + 0.563232 + 0.563232 + 0.563232 + 0.563232 + 0.563232 + 0.563232 + 0.563232 + 0.563232 + 0.563232 + 0.563232 + 0.563477 + 0.563477 + 0.563477 + 0.563477 + 0.563477 + 0.563477 + 0.563477 + 0.563477 + 0.563477 + 0.563477 + 0.563477 + 0.563477 + 0.563477 + 0.563477 + 0.563477 + 0.563477 + 0.563477 + 0.563721 + 0.563721 + 0.563721 + 0.563721 + 0.563721 + 0.563721 + 0.563721 + 0.563721 + 0.563721 + 0.563721 + 0.563721 + 0.563721 + 0.563721 + 0.563721 + 0.563721 + 0.563721 + 0.563721 + 0.563965 + 0.563965 + 0.563965 + 0.563965 + 0.563965 + 0.563965 + 0.563965 + 0.563965 + 0.563965 + 0.563965 + 0.563965 + 0.563965 + 0.563965 + 0.563965 + 0.563965 + 0.563965 + 0.564209 + 0.564209 + 0.564209 + 0.564209 + 0.564209 + 0.564209 + 0.564209 + 0.564209 + 0.564209 + 0.564209 + 0.564209 + 0.564209 + 0.564209 + 0.564209 + 0.564209 + 0.564209 + 0.564209 + 0.564453 + 0.564453 + 0.564453 + 0.564453 + 0.564453 + 0.564453 + 0.564453 + 0.564453 + 0.564453 + 0.564453 + 0.564453 + 0.564453 + 0.564453 + 0.564453 + 0.564453 + 0.564453 + 0.564453 + 0.564697 + 0.564697 + 0.564697 + 0.564697 + 0.564697 + 0.564697 + 0.564697 + 0.564697 + 0.564697 + 0.564697 + 0.564697 + 0.564697 + 0.564697 + 0.564697 + 0.564697 + 0.564697 + 0.564941 + 0.564941 + 0.564941 + 0.564941 + 0.564941 + 0.564941 + 0.564941 + 0.564941 + 0.564941 + 0.564941 + 0.564941 + 0.564941 + 0.564941 + 0.564941 + 0.564941 + 0.564941 + 0.564941 + 0.565186 + 0.565186 + 0.565186 + 0.565186 + 0.565186 + 0.565186 + 0.565186 + 0.565186 + 0.565186 + 0.565186 + 0.565186 + 0.565186 + 0.565186 + 0.565186 + 0.565186 + 0.565186 + 0.565186 + 0.565430 + 0.565430 + 0.565430 + 0.565430 + 0.565430 + 0.565430 + 0.565430 + 0.565430 + 0.565430 + 0.565430 + 0.565430 + 0.565430 + 0.565430 + 0.565430 + 0.565430 + 0.565430 + 0.565430 + 0.565674 + 0.565674 + 0.565674 + 0.565674 + 0.565674 + 0.565674 + 0.565674 + 0.565674 + 0.565674 + 0.565674 + 0.565674 + 0.565674 + 0.565674 + 0.565674 + 0.565674 + 0.565674 + 0.565918 + 0.565918 + 0.565918 + 0.565918 + 0.565918 + 0.565918 + 0.565918 + 0.565918 + 0.565918 + 0.565918 + 0.565918 + 0.565918 + 0.565918 + 0.565918 + 0.565918 + 0.565918 + 0.565918 + 0.566162 + 0.566162 + 0.566162 + 0.566162 + 0.566162 + 0.566162 + 0.566162 + 0.566162 + 0.566162 + 0.566162 + 0.566162 + 0.566162 + 0.566162 + 0.566162 + 0.566162 + 0.566162 + 0.566162 + 0.566406 + 0.566406 + 0.566406 + 0.566406 + 0.566406 + 0.566406 + 0.566406 + 0.566406 + 0.566406 + 0.566406 + 0.566406 + 0.566406 + 0.566406 + 0.566406 + 0.566406 + 0.566406 + 0.566406 + 0.566650 + 0.566650 + 0.566650 + 0.566650 + 0.566650 + 0.566650 + 0.566650 + 0.566650 + 0.566650 + 0.566650 + 0.566650 + 0.566650 + 0.566650 + 0.566650 + 0.566650 + 0.566650 + 0.566895 + 0.566895 + 0.566895 + 0.566895 + 0.566895 + 0.566895 + 0.566895 + 0.566895 + 0.566895 + 0.566895 + 0.566895 + 0.566895 + 0.566895 + 0.566895 + 0.566895 + 0.566895 + 0.566895 + 0.567139 + 0.567139 + 0.567139 + 0.567139 + 0.567139 + 0.567139 + 0.567139 + 0.567139 + 0.567139 + 0.567139 + 0.567139 + 0.567139 + 0.567139 + 0.567139 + 0.567139 + 0.567139 + 0.567139 + 0.567383 + 0.567383 + 0.567383 + 0.567383 + 0.567383 + 0.567383 + 0.567383 + 0.567383 + 0.567383 + 0.567383 + 0.567383 + 0.567383 + 0.567383 + 0.567383 + 0.567383 + 0.567383 + 0.567383 + 0.567627 + 0.567627 + 0.567627 + 0.567627 + 0.567627 + 0.567627 + 0.567627 + 0.567627 + 0.567627 + 0.567627 + 0.567627 + 0.567627 + 0.567627 + 0.567627 + 0.567627 + 0.567627 + 0.567627 + 0.567871 + 0.567871 + 0.567871 + 0.567871 + 0.567871 + 0.567871 + 0.567871 + 0.567871 + 0.567871 + 0.567871 + 0.567871 + 0.567871 + 0.567871 + 0.567871 + 0.567871 + 0.567871 + 0.568115 + 0.568115 + 0.568115 + 0.568115 + 0.568115 + 0.568115 + 0.568115 + 0.568115 + 0.568115 + 0.568115 + 0.568115 + 0.568115 + 0.568115 + 0.568115 + 0.568115 + 0.568115 + 0.568115 + 0.568359 + 0.568359 + 0.568359 + 0.568359 + 0.568359 + 0.568359 + 0.568359 + 0.568359 + 0.568359 + 0.568359 + 0.568359 + 0.568359 + 0.568359 + 0.568359 + 0.568359 + 0.568359 + 0.568359 + 0.568604 + 0.568604 + 0.568604 + 0.568604 + 0.568604 + 0.568604 + 0.568604 + 0.568604 + 0.568604 + 0.568604 + 0.568604 + 0.568604 + 0.568604 + 0.568604 + 0.568604 + 0.568604 + 0.568604 + 0.568848 + 0.568848 + 0.568848 + 0.568848 + 0.568848 + 0.568848 + 0.568848 + 0.568848 + 0.568848 + 0.568848 + 0.568848 + 0.568848 + 0.568848 + 0.568848 + 0.568848 + 0.568848 + 0.568848 + 0.569092 + 0.569092 + 0.569092 + 0.569092 + 0.569092 + 0.569092 + 0.569092 + 0.569092 + 0.569092 + 0.569092 + 0.569092 + 0.569092 + 0.569092 + 0.569092 + 0.569092 + 0.569092 + 0.569092 + 0.569336 + 0.569336 + 0.569336 + 0.569336 + 0.569336 + 0.569336 + 0.569336 + 0.569336 + 0.569336 + 0.569336 + 0.569336 + 0.569336 + 0.569336 + 0.569336 + 0.569336 + 0.569336 + 0.569336 + 0.569580 + 0.569580 + 0.569580 + 0.569580 + 0.569580 + 0.569580 + 0.569580 + 0.569580 + 0.569580 + 0.569580 + 0.569580 + 0.569580 + 0.569580 + 0.569580 + 0.569580 + 0.569580 + 0.569580 + 0.569824 + 0.569824 + 0.569824 + 0.569824 + 0.569824 + 0.569824 + 0.569824 + 0.569824 + 0.569824 + 0.569824 + 0.569824 + 0.569824 + 0.569824 + 0.569824 + 0.569824 + 0.569824 + 0.569824 + 0.570068 + 0.570068 + 0.570068 + 0.570068 + 0.570068 + 0.570068 + 0.570068 + 0.570068 + 0.570068 + 0.570068 + 0.570068 + 0.570068 + 0.570068 + 0.570068 + 0.570068 + 0.570068 + 0.570312 + 0.570312 + 0.570312 + 0.570312 + 0.570312 + 0.570312 + 0.570312 + 0.570312 + 0.570312 + 0.570312 + 0.570312 + 0.570312 + 0.570312 + 0.570312 + 0.570312 + 0.570312 + 0.570312 + 0.570557 + 0.570557 + 0.570557 + 0.570557 + 0.570557 + 0.570557 + 0.570557 + 0.570557 + 0.570557 + 0.570557 + 0.570557 + 0.570557 + 0.570557 + 0.570557 + 0.570557 + 0.570557 + 0.570557 + 0.570801 + 0.570801 + 0.570801 + 0.570801 + 0.570801 + 0.570801 + 0.570801 + 0.570801 + 0.570801 + 0.570801 + 0.570801 + 0.570801 + 0.570801 + 0.570801 + 0.570801 + 0.570801 + 0.570801 + 0.571045 + 0.571045 + 0.571045 + 0.571045 + 0.571045 + 0.571045 + 0.571045 + 0.571045 + 0.571045 + 0.571045 + 0.571045 + 0.571045 + 0.571045 + 0.571045 + 0.571045 + 0.571045 + 0.571045 + 0.571289 + 0.571289 + 0.571289 + 0.571289 + 0.571289 + 0.571289 + 0.571289 + 0.571289 + 0.571289 + 0.571289 + 0.571289 + 0.571289 + 0.571289 + 0.571289 + 0.571289 + 0.571289 + 0.571289 + 0.571533 + 0.571533 + 0.571533 + 0.571533 + 0.571533 + 0.571533 + 0.571533 + 0.571533 + 0.571533 + 0.571533 + 0.571533 + 0.571533 + 0.571533 + 0.571533 + 0.571533 + 0.571533 + 0.571533 + 0.571777 + 0.571777 + 0.571777 + 0.571777 + 0.571777 + 0.571777 + 0.571777 + 0.571777 + 0.571777 + 0.571777 + 0.571777 + 0.571777 + 0.571777 + 0.571777 + 0.571777 + 0.571777 + 0.571777 + 0.572021 + 0.572021 + 0.572021 + 0.572021 + 0.572021 + 0.572021 + 0.572021 + 0.572021 + 0.572021 + 0.572021 + 0.572021 + 0.572021 + 0.572021 + 0.572021 + 0.572021 + 0.572021 + 0.572021 + 0.572266 + 0.572266 + 0.572266 + 0.572266 + 0.572266 + 0.572266 + 0.572266 + 0.572266 + 0.572266 + 0.572266 + 0.572266 + 0.572266 + 0.572266 + 0.572266 + 0.572266 + 0.572266 + 0.572266 + 0.572510 + 0.572510 + 0.572510 + 0.572510 + 0.572510 + 0.572510 + 0.572510 + 0.572510 + 0.572510 + 0.572510 + 0.572510 + 0.572510 + 0.572510 + 0.572510 + 0.572510 + 0.572510 + 0.572510 + 0.572510 + 0.572754 + 0.572754 + 0.572754 + 0.572754 + 0.572754 + 0.572754 + 0.572754 + 0.572754 + 0.572754 + 0.572754 + 0.572754 + 0.572754 + 0.572754 + 0.572754 + 0.572754 + 0.572754 + 0.572754 + 0.572998 + 0.572998 + 0.572998 + 0.572998 + 0.572998 + 0.572998 + 0.572998 + 0.572998 + 0.572998 + 0.572998 + 0.572998 + 0.572998 + 0.572998 + 0.572998 + 0.572998 + 0.572998 + 0.572998 + 0.573242 + 0.573242 + 0.573242 + 0.573242 + 0.573242 + 0.573242 + 0.573242 + 0.573242 + 0.573242 + 0.573242 + 0.573242 + 0.573242 + 0.573242 + 0.573242 + 0.573242 + 0.573242 + 0.573242 + 0.573486 + 0.573486 + 0.573486 + 0.573486 + 0.573486 + 0.573486 + 0.573486 + 0.573486 + 0.573486 + 0.573486 + 0.573486 + 0.573486 + 0.573486 + 0.573486 + 0.573486 + 0.573486 + 0.573486 + 0.573730 + 0.573730 + 0.573730 + 0.573730 + 0.573730 + 0.573730 + 0.573730 + 0.573730 + 0.573730 + 0.573730 + 0.573730 + 0.573730 + 0.573730 + 0.573730 + 0.573730 + 0.573730 + 0.573730 + 0.573975 + 0.573975 + 0.573975 + 0.573975 + 0.573975 + 0.573975 + 0.573975 + 0.573975 + 0.573975 + 0.573975 + 0.573975 + 0.573975 + 0.573975 + 0.573975 + 0.573975 + 0.573975 + 0.573975 + 0.574219 + 0.574219 + 0.574219 + 0.574219 + 0.574219 + 0.574219 + 0.574219 + 0.574219 + 0.574219 + 0.574219 + 0.574219 + 0.574219 + 0.574219 + 0.574219 + 0.574219 + 0.574219 + 0.574219 + 0.574463 + 0.574463 + 0.574463 + 0.574463 + 0.574463 + 0.574463 + 0.574463 + 0.574463 + 0.574463 + 0.574463 + 0.574463 + 0.574463 + 0.574463 + 0.574463 + 0.574463 + 0.574463 + 0.574463 + 0.574707 + 0.574707 + 0.574707 + 0.574707 + 0.574707 + 0.574707 + 0.574707 + 0.574707 + 0.574707 + 0.574707 + 0.574707 + 0.574707 + 0.574707 + 0.574707 + 0.574707 + 0.574707 + 0.574707 + 0.574707 + 0.574951 + 0.574951 + 0.574951 + 0.574951 + 0.574951 + 0.574951 + 0.574951 + 0.574951 + 0.574951 + 0.574951 + 0.574951 + 0.574951 + 0.574951 + 0.574951 + 0.574951 + 0.574951 + 0.574951 + 0.575195 + 0.575195 + 0.575195 + 0.575195 + 0.575195 + 0.575195 + 0.575195 + 0.575195 + 0.575195 + 0.575195 + 0.575195 + 0.575195 + 0.575195 + 0.575195 + 0.575195 + 0.575195 + 0.575195 + 0.575439 + 0.575439 + 0.575439 + 0.575439 + 0.575439 + 0.575439 + 0.575439 + 0.575439 + 0.575439 + 0.575439 + 0.575439 + 0.575439 + 0.575439 + 0.575439 + 0.575439 + 0.575439 + 0.575439 + 0.575684 + 0.575684 + 0.575684 + 0.575684 + 0.575684 + 0.575684 + 0.575684 + 0.575684 + 0.575684 + 0.575684 + 0.575684 + 0.575684 + 0.575684 + 0.575684 + 0.575684 + 0.575684 + 0.575684 + 0.575928 + 0.575928 + 0.575928 + 0.575928 + 0.575928 + 0.575928 + 0.575928 + 0.575928 + 0.575928 + 0.575928 + 0.575928 + 0.575928 + 0.575928 + 0.575928 + 0.575928 + 0.575928 + 0.575928 + 0.575928 + 0.576172 + 0.576172 + 0.576172 + 0.576172 + 0.576172 + 0.576172 + 0.576172 + 0.576172 + 0.576172 + 0.576172 + 0.576172 + 0.576172 + 0.576172 + 0.576172 + 0.576172 + 0.576172 + 0.576172 + 0.576416 + 0.576416 + 0.576416 + 0.576416 + 0.576416 + 0.576416 + 0.576416 + 0.576416 + 0.576416 + 0.576416 + 0.576416 + 0.576416 + 0.576416 + 0.576416 + 0.576416 + 0.576416 + 0.576416 + 0.576660 + 0.576660 + 0.576660 + 0.576660 + 0.576660 + 0.576660 + 0.576660 + 0.576660 + 0.576660 + 0.576660 + 0.576660 + 0.576660 + 0.576660 + 0.576660 + 0.576660 + 0.576660 + 0.576660 + 0.576904 + 0.576904 + 0.576904 + 0.576904 + 0.576904 + 0.576904 + 0.576904 + 0.576904 + 0.576904 + 0.576904 + 0.576904 + 0.576904 + 0.576904 + 0.576904 + 0.576904 + 0.576904 + 0.576904 + 0.576904 + 0.577148 + 0.577148 + 0.577148 + 0.577148 + 0.577148 + 0.577148 + 0.577148 + 0.577148 + 0.577148 + 0.577148 + 0.577148 + 0.577148 + 0.577148 + 0.577148 + 0.577148 + 0.577148 + 0.577148 + 0.577393 + 0.577393 + 0.577393 + 0.577393 + 0.577393 + 0.577393 + 0.577393 + 0.577393 + 0.577393 + 0.577393 + 0.577393 + 0.577393 + 0.577393 + 0.577393 + 0.577393 + 0.577393 + 0.577393 + 0.577637 + 0.577637 + 0.577637 + 0.577637 + 0.577637 + 0.577637 + 0.577637 + 0.577637 + 0.577637 + 0.577637 + 0.577637 + 0.577637 + 0.577637 + 0.577637 + 0.577637 + 0.577637 + 0.577637 + 0.577881 + 0.577881 + 0.577881 + 0.577881 + 0.577881 + 0.577881 + 0.577881 + 0.577881 + 0.577881 + 0.577881 + 0.577881 + 0.577881 + 0.577881 + 0.577881 + 0.577881 + 0.577881 + 0.577881 + 0.577881 + 0.578125 + 0.578125 + 0.578125 + 0.578125 + 0.578125 + 0.578125 + 0.578125 + 0.578125 + 0.578125 + 0.578125 + 0.578125 + 0.578125 + 0.578125 + 0.578125 + 0.578125 + 0.578125 + 0.578125 + 0.578369 + 0.578369 + 0.578369 + 0.578369 + 0.578369 + 0.578369 + 0.578369 + 0.578369 + 0.578369 + 0.578369 + 0.578369 + 0.578369 + 0.578369 + 0.578369 + 0.578369 + 0.578369 + 0.578369 + 0.578613 + 0.578613 + 0.578613 + 0.578613 + 0.578613 + 0.578613 + 0.578613 + 0.578613 + 0.578613 + 0.578613 + 0.578613 + 0.578613 + 0.578613 + 0.578613 + 0.578613 + 0.578613 + 0.578613 + 0.578613 + 0.578857 + 0.578857 + 0.578857 + 0.578857 + 0.578857 + 0.578857 + 0.578857 + 0.578857 + 0.578857 + 0.578857 + 0.578857 + 0.578857 + 0.578857 + 0.578857 + 0.578857 + 0.578857 + 0.578857 + 0.579102 + 0.579102 + 0.579102 + 0.579102 + 0.579102 + 0.579102 + 0.579102 + 0.579102 + 0.579102 + 0.579102 + 0.579102 + 0.579102 + 0.579102 + 0.579102 + 0.579102 + 0.579102 + 0.579102 + 0.579102 + 0.579346 + 0.579346 + 0.579346 + 0.579346 + 0.579346 + 0.579346 + 0.579346 + 0.579346 + 0.579346 + 0.579346 + 0.579346 + 0.579346 + 0.579346 + 0.579346 + 0.579346 + 0.579346 + 0.579346 + 0.579590 + 0.579590 + 0.579590 + 0.579590 + 0.579590 + 0.579590 + 0.579590 + 0.579590 + 0.579590 + 0.579590 + 0.579590 + 0.579590 + 0.579590 + 0.579590 + 0.579590 + 0.579590 + 0.579590 + 0.579834 + 0.579834 + 0.579834 + 0.579834 + 0.579834 + 0.579834 + 0.579834 + 0.579834 + 0.579834 + 0.579834 + 0.579834 + 0.579834 + 0.579834 + 0.579834 + 0.579834 + 0.579834 + 0.579834 + 0.579834 + 0.580078 + 0.580078 + 0.580078 + 0.580078 + 0.580078 + 0.580078 + 0.580078 + 0.580078 + 0.580078 + 0.580078 + 0.580078 + 0.580078 + 0.580078 + 0.580078 + 0.580078 + 0.580078 + 0.580078 + 0.580322 + 0.580322 + 0.580322 + 0.580322 + 0.580322 + 0.580322 + 0.580322 + 0.580322 + 0.580322 + 0.580322 + 0.580322 + 0.580322 + 0.580322 + 0.580322 + 0.580322 + 0.580322 + 0.580322 + 0.580322 + 0.580566 + 0.580566 + 0.580566 + 0.580566 + 0.580566 + 0.580566 + 0.580566 + 0.580566 + 0.580566 + 0.580566 + 0.580566 + 0.580566 + 0.580566 + 0.580566 + 0.580566 + 0.580566 + 0.580566 + 0.580811 + 0.580811 + 0.580811 + 0.580811 + 0.580811 + 0.580811 + 0.580811 + 0.580811 + 0.580811 + 0.580811 + 0.580811 + 0.580811 + 0.580811 + 0.580811 + 0.580811 + 0.580811 + 0.580811 + 0.580811 + 0.581055 + 0.581055 + 0.581055 + 0.581055 + 0.581055 + 0.581055 + 0.581055 + 0.581055 + 0.581055 + 0.581055 + 0.581055 + 0.581055 + 0.581055 + 0.581055 + 0.581055 + 0.581055 + 0.581055 + 0.581299 + 0.581299 + 0.581299 + 0.581299 + 0.581299 + 0.581299 + 0.581299 + 0.581299 + 0.581299 + 0.581299 + 0.581299 + 0.581299 + 0.581299 + 0.581299 + 0.581299 + 0.581299 + 0.581299 + 0.581543 + 0.581543 + 0.581543 + 0.581543 + 0.581543 + 0.581543 + 0.581543 + 0.581543 + 0.581543 + 0.581543 + 0.581543 + 0.581543 + 0.581543 + 0.581543 + 0.581543 + 0.581543 + 0.581543 + 0.581543 + 0.581787 + 0.581787 + 0.581787 + 0.581787 + 0.581787 + 0.581787 + 0.581787 + 0.581787 + 0.581787 + 0.581787 + 0.581787 + 0.581787 + 0.581787 + 0.581787 + 0.581787 + 0.581787 + 0.581787 + 0.582031 + 0.582031 + 0.582031 + 0.582031 + 0.582031 + 0.582031 + 0.582031 + 0.582031 + 0.582031 + 0.582031 + 0.582031 + 0.582031 + 0.582031 + 0.582031 + 0.582031 + 0.582031 + 0.582031 + 0.582031 + 0.582275 + 0.582275 + 0.582275 + 0.582275 + 0.582275 + 0.582275 + 0.582275 + 0.582275 + 0.582275 + 0.582275 + 0.582275 + 0.582275 + 0.582275 + 0.582275 + 0.582275 + 0.582275 + 0.582275 + 0.582275 + 0.582520 + 0.582520 + 0.582520 + 0.582520 + 0.582520 + 0.582520 + 0.582520 + 0.582520 + 0.582520 + 0.582520 + 0.582520 + 0.582520 + 0.582520 + 0.582520 + 0.582520 + 0.582520 + 0.582520 + 0.582764 + 0.582764 + 0.582764 + 0.582764 + 0.582764 + 0.582764 + 0.582764 + 0.582764 + 0.582764 + 0.582764 + 0.582764 + 0.582764 + 0.582764 + 0.582764 + 0.582764 + 0.582764 + 0.582764 + 0.582764 + 0.583008 + 0.583008 + 0.583008 + 0.583008 + 0.583008 + 0.583008 + 0.583008 + 0.583008 + 0.583008 + 0.583008 + 0.583008 + 0.583008 + 0.583008 + 0.583008 + 0.583008 + 0.583008 + 0.583008 + 0.583252 + 0.583252 + 0.583252 + 0.583252 + 0.583252 + 0.583252 + 0.583252 + 0.583252 + 0.583252 + 0.583252 + 0.583252 + 0.583252 + 0.583252 + 0.583252 + 0.583252 + 0.583252 + 0.583252 + 0.583252 + 0.583496 + 0.583496 + 0.583496 + 0.583496 + 0.583496 + 0.583496 + 0.583496 + 0.583496 + 0.583496 + 0.583496 + 0.583496 + 0.583496 + 0.583496 + 0.583496 + 0.583496 + 0.583496 + 0.583496 + 0.583740 + 0.583740 + 0.583740 + 0.583740 + 0.583740 + 0.583740 + 0.583740 + 0.583740 + 0.583740 + 0.583740 + 0.583740 + 0.583740 + 0.583740 + 0.583740 + 0.583740 + 0.583740 + 0.583740 + 0.583740 + 0.583984 + 0.583984 + 0.583984 + 0.583984 + 0.583984 + 0.583984 + 0.583984 + 0.583984 + 0.583984 + 0.583984 + 0.583984 + 0.583984 + 0.583984 + 0.583984 + 0.583984 + 0.583984 + 0.583984 + 0.583984 + 0.584229 + 0.584229 + 0.584229 + 0.584229 + 0.584229 + 0.584229 + 0.584229 + 0.584229 + 0.584229 + 0.584229 + 0.584229 + 0.584229 + 0.584229 + 0.584229 + 0.584229 + 0.584229 + 0.584229 + 0.584473 + 0.584473 + 0.584473 + 0.584473 + 0.584473 + 0.584473 + 0.584473 + 0.584473 + 0.584473 + 0.584473 + 0.584473 + 0.584473 + 0.584473 + 0.584473 + 0.584473 + 0.584473 + 0.584473 + 0.584473 + 0.584717 + 0.584717 + 0.584717 + 0.584717 + 0.584717 + 0.584717 + 0.584717 + 0.584717 + 0.584717 + 0.584717 + 0.584717 + 0.584717 + 0.584717 + 0.584717 + 0.584717 + 0.584717 + 0.584717 + 0.584961 + 0.584961 + 0.584961 + 0.584961 + 0.584961 + 0.584961 + 0.584961 + 0.584961 + 0.584961 + 0.584961 + 0.584961 + 0.584961 + 0.584961 + 0.584961 + 0.584961 + 0.584961 + 0.584961 + 0.584961 + 0.585205 + 0.585205 + 0.585205 + 0.585205 + 0.585205 + 0.585205 + 0.585205 + 0.585205 + 0.585205 + 0.585205 + 0.585205 + 0.585205 + 0.585205 + 0.585205 + 0.585205 + 0.585205 + 0.585205 + 0.585205 + 0.585449 + 0.585449 + 0.585449 + 0.585449 + 0.585449 + 0.585449 + 0.585449 + 0.585449 + 0.585449 + 0.585449 + 0.585449 + 0.585449 + 0.585449 + 0.585449 + 0.585449 + 0.585449 + 0.585449 + 0.585693 + 0.585693 + 0.585693 + 0.585693 + 0.585693 + 0.585693 + 0.585693 + 0.585693 + 0.585693 + 0.585693 + 0.585693 + 0.585693 + 0.585693 + 0.585693 + 0.585693 + 0.585693 + 0.585693 + 0.585693 + 0.585938 + 0.585938 + 0.585938 + 0.585938 + 0.585938 + 0.585938 + 0.585938 + 0.585938 + 0.585938 + 0.585938 + 0.585938 + 0.585938 + 0.585938 + 0.585938 + 0.585938 + 0.585938 + 0.585938 + 0.585938 + 0.586182 + 0.586182 + 0.586182 + 0.586182 + 0.586182 + 0.586182 + 0.586182 + 0.586182 + 0.586182 + 0.586182 + 0.586182 + 0.586182 + 0.586182 + 0.586182 + 0.586182 + 0.586182 + 0.586182 + 0.586182 + 0.586426 + 0.586426 + 0.586426 + 0.586426 + 0.586426 + 0.586426 + 0.586426 + 0.586426 + 0.586426 + 0.586426 + 0.586426 + 0.586426 + 0.586426 + 0.586426 + 0.586426 + 0.586426 + 0.586426 + 0.586670 + 0.586670 + 0.586670 + 0.586670 + 0.586670 + 0.586670 + 0.586670 + 0.586670 + 0.586670 + 0.586670 + 0.586670 + 0.586670 + 0.586670 + 0.586670 + 0.586670 + 0.586670 + 0.586670 + 0.586670 + 0.586914 + 0.586914 + 0.586914 + 0.586914 + 0.586914 + 0.586914 + 0.586914 + 0.586914 + 0.586914 + 0.586914 + 0.586914 + 0.586914 + 0.586914 + 0.586914 + 0.586914 + 0.586914 + 0.586914 + 0.586914 + 0.587158 + 0.587158 + 0.587158 + 0.587158 + 0.587158 + 0.587158 + 0.587158 + 0.587158 + 0.587158 + 0.587158 + 0.587158 + 0.587158 + 0.587158 + 0.587158 + 0.587158 + 0.587158 + 0.587158 + 0.587158 + 0.587402 + 0.587402 + 0.587402 + 0.587402 + 0.587402 + 0.587402 + 0.587402 + 0.587402 + 0.587402 + 0.587402 + 0.587402 + 0.587402 + 0.587402 + 0.587402 + 0.587402 + 0.587402 + 0.587402 + 0.587646 + 0.587646 + 0.587646 + 0.587646 + 0.587646 + 0.587646 + 0.587646 + 0.587646 + 0.587646 + 0.587646 + 0.587646 + 0.587646 + 0.587646 + 0.587646 + 0.587646 + 0.587646 + 0.587646 + 0.587646 + 0.587891 + 0.587891 + 0.587891 + 0.587891 + 0.587891 + 0.587891 + 0.587891 + 0.587891 + 0.587891 + 0.587891 + 0.587891 + 0.587891 + 0.587891 + 0.587891 + 0.587891 + 0.587891 + 0.587891 + 0.587891 + 0.588135 + 0.588135 + 0.588135 + 0.588135 + 0.588135 + 0.588135 + 0.588135 + 0.588135 + 0.588135 + 0.588135 + 0.588135 + 0.588135 + 0.588135 + 0.588135 + 0.588135 + 0.588135 + 0.588135 + 0.588135 + 0.588379 + 0.588379 + 0.588379 + 0.588379 + 0.588379 + 0.588379 + 0.588379 + 0.588379 + 0.588379 + 0.588379 + 0.588379 + 0.588379 + 0.588379 + 0.588379 + 0.588379 + 0.588379 + 0.588379 + 0.588379 + 0.588623 + 0.588623 + 0.588623 + 0.588623 + 0.588623 + 0.588623 + 0.588623 + 0.588623 + 0.588623 + 0.588623 + 0.588623 + 0.588623 + 0.588623 + 0.588623 + 0.588623 + 0.588623 + 0.588623 + 0.588867 + 0.588867 + 0.588867 + 0.588867 + 0.588867 + 0.588867 + 0.588867 + 0.588867 + 0.588867 + 0.588867 + 0.588867 + 0.588867 + 0.588867 + 0.588867 + 0.588867 + 0.588867 + 0.588867 + 0.588867 + 0.589111 + 0.589111 + 0.589111 + 0.589111 + 0.589111 + 0.589111 + 0.589111 + 0.589111 + 0.589111 + 0.589111 + 0.589111 + 0.589111 + 0.589111 + 0.589111 + 0.589111 + 0.589111 + 0.589111 + 0.589111 + 0.589355 + 0.589355 + 0.589355 + 0.589355 + 0.589355 + 0.589355 + 0.589355 + 0.589355 + 0.589355 + 0.589355 + 0.589355 + 0.589355 + 0.589355 + 0.589355 + 0.589355 + 0.589355 + 0.589355 + 0.589355 + 0.589600 + 0.589600 + 0.589600 + 0.589600 + 0.589600 + 0.589600 + 0.589600 + 0.589600 + 0.589600 + 0.589600 + 0.589600 + 0.589600 + 0.589600 + 0.589600 + 0.589600 + 0.589600 + 0.589600 + 0.589600 + 0.589844 + 0.589844 + 0.589844 + 0.589844 + 0.589844 + 0.589844 + 0.589844 + 0.589844 + 0.589844 + 0.589844 + 0.589844 + 0.589844 + 0.589844 + 0.589844 + 0.589844 + 0.589844 + 0.589844 + 0.589844 + 0.590088 + 0.590088 + 0.590088 + 0.590088 + 0.590088 + 0.590088 + 0.590088 + 0.590088 + 0.590088 + 0.590088 + 0.590088 + 0.590088 + 0.590088 + 0.590088 + 0.590088 + 0.590088 + 0.590088 + 0.590088 + 0.590332 + 0.590332 + 0.590332 + 0.590332 + 0.590332 + 0.590332 + 0.590332 + 0.590332 + 0.590332 + 0.590332 + 0.590332 + 0.590332 + 0.590332 + 0.590332 + 0.590332 + 0.590332 + 0.590332 + 0.590332 + 0.590576 + 0.590576 + 0.590576 + 0.590576 + 0.590576 + 0.590576 + 0.590576 + 0.590576 + 0.590576 + 0.590576 + 0.590576 + 0.590576 + 0.590576 + 0.590576 + 0.590576 + 0.590576 + 0.590576 + 0.590820 + 0.590820 + 0.590820 + 0.590820 + 0.590820 + 0.590820 + 0.590820 + 0.590820 + 0.590820 + 0.590820 + 0.590820 + 0.590820 + 0.590820 + 0.590820 + 0.590820 + 0.590820 + 0.590820 + 0.590820 + 0.591064 + 0.591064 + 0.591064 + 0.591064 + 0.591064 + 0.591064 + 0.591064 + 0.591064 + 0.591064 + 0.591064 + 0.591064 + 0.591064 + 0.591064 + 0.591064 + 0.591064 + 0.591064 + 0.591064 + 0.591064 + 0.591309 + 0.591309 + 0.591309 + 0.591309 + 0.591309 + 0.591309 + 0.591309 + 0.591309 + 0.591309 + 0.591309 + 0.591309 + 0.591309 + 0.591309 + 0.591309 + 0.591309 + 0.591309 + 0.591309 + 0.591309 + 0.591553 + 0.591553 + 0.591553 + 0.591553 + 0.591553 + 0.591553 + 0.591553 + 0.591553 + 0.591553 + 0.591553 + 0.591553 + 0.591553 + 0.591553 + 0.591553 + 0.591553 + 0.591553 + 0.591553 + 0.591553 + 0.591797 + 0.591797 + 0.591797 + 0.591797 + 0.591797 + 0.591797 + 0.591797 + 0.591797 + 0.591797 + 0.591797 + 0.591797 + 0.591797 + 0.591797 + 0.591797 + 0.591797 + 0.591797 + 0.591797 + 0.591797 + 0.592041 + 0.592041 + 0.592041 + 0.592041 + 0.592041 + 0.592041 + 0.592041 + 0.592041 + 0.592041 + 0.592041 + 0.592041 + 0.592041 + 0.592041 + 0.592041 + 0.592041 + 0.592041 + 0.592041 + 0.592041 + 0.592285 + 0.592285 + 0.592285 + 0.592285 + 0.592285 + 0.592285 + 0.592285 + 0.592285 + 0.592285 + 0.592285 + 0.592285 + 0.592285 + 0.592285 + 0.592285 + 0.592285 + 0.592285 + 0.592285 + 0.592285 + 0.592529 + 0.592529 + 0.592529 + 0.592529 + 0.592529 + 0.592529 + 0.592529 + 0.592529 + 0.592529 + 0.592529 + 0.592529 + 0.592529 + 0.592529 + 0.592529 + 0.592529 + 0.592529 + 0.592529 + 0.592529 + 0.592773 + 0.592773 + 0.592773 + 0.592773 + 0.592773 + 0.592773 + 0.592773 + 0.592773 + 0.592773 + 0.592773 + 0.592773 + 0.592773 + 0.592773 + 0.592773 + 0.592773 + 0.592773 + 0.592773 + 0.592773 + 0.593018 + 0.593018 + 0.593018 + 0.593018 + 0.593018 + 0.593018 + 0.593018 + 0.593018 + 0.593018 + 0.593018 + 0.593018 + 0.593018 + 0.593018 + 0.593018 + 0.593018 + 0.593018 + 0.593018 + 0.593018 + 0.593262 + 0.593262 + 0.593262 + 0.593262 + 0.593262 + 0.593262 + 0.593262 + 0.593262 + 0.593262 + 0.593262 + 0.593262 + 0.593262 + 0.593262 + 0.593262 + 0.593262 + 0.593262 + 0.593262 + 0.593262 + 0.593506 + 0.593506 + 0.593506 + 0.593506 + 0.593506 + 0.593506 + 0.593506 + 0.593506 + 0.593506 + 0.593506 + 0.593506 + 0.593506 + 0.593506 + 0.593506 + 0.593506 + 0.593506 + 0.593506 + 0.593506 + 0.593506 + 0.593750 + 0.593750 + 0.593750 + 0.593750 + 0.593750 + 0.593750 + 0.593750 + 0.593750 + 0.593750 + 0.593750 + 0.593750 + 0.593750 + 0.593750 + 0.593750 + 0.593750 + 0.593750 + 0.593750 + 0.593750 + 0.593994 + 0.593994 + 0.593994 + 0.593994 + 0.593994 + 0.593994 + 0.593994 + 0.593994 + 0.593994 + 0.593994 + 0.593994 + 0.593994 + 0.593994 + 0.593994 + 0.593994 + 0.593994 + 0.593994 + 0.593994 + 0.594238 + 0.594238 + 0.594238 + 0.594238 + 0.594238 + 0.594238 + 0.594238 + 0.594238 + 0.594238 + 0.594238 + 0.594238 + 0.594238 + 0.594238 + 0.594238 + 0.594238 + 0.594238 + 0.594238 + 0.594238 + 0.594482 + 0.594482 + 0.594482 + 0.594482 + 0.594482 + 0.594482 + 0.594482 + 0.594482 + 0.594482 + 0.594482 + 0.594482 + 0.594482 + 0.594482 + 0.594482 + 0.594482 + 0.594482 + 0.594482 + 0.594482 + 0.594727 + 0.594727 + 0.594727 + 0.594727 + 0.594727 + 0.594727 + 0.594727 + 0.594727 + 0.594727 + 0.594727 + 0.594727 + 0.594727 + 0.594727 + 0.594727 + 0.594727 + 0.594727 + 0.594727 + 0.594727 + 0.594971 + 0.594971 + 0.594971 + 0.594971 + 0.594971 + 0.594971 + 0.594971 + 0.594971 + 0.594971 + 0.594971 + 0.594971 + 0.594971 + 0.594971 + 0.594971 + 0.594971 + 0.594971 + 0.594971 + 0.594971 + 0.595215 + 0.595215 + 0.595215 + 0.595215 + 0.595215 + 0.595215 + 0.595215 + 0.595215 + 0.595215 + 0.595215 + 0.595215 + 0.595215 + 0.595215 + 0.595215 + 0.595215 + 0.595215 + 0.595215 + 0.595215 + 0.595459 + 0.595459 + 0.595459 + 0.595459 + 0.595459 + 0.595459 + 0.595459 + 0.595459 + 0.595459 + 0.595459 + 0.595459 + 0.595459 + 0.595459 + 0.595459 + 0.595459 + 0.595459 + 0.595459 + 0.595459 + 0.595459 + 0.595703 + 0.595703 + 0.595703 + 0.595703 + 0.595703 + 0.595703 + 0.595703 + 0.595703 + 0.595703 + 0.595703 + 0.595703 + 0.595703 + 0.595703 + 0.595703 + 0.595703 + 0.595703 + 0.595703 + 0.595703 + 0.595947 + 0.595947 + 0.595947 + 0.595947 + 0.595947 + 0.595947 + 0.595947 + 0.595947 + 0.595947 + 0.595947 + 0.595947 + 0.595947 + 0.595947 + 0.595947 + 0.595947 + 0.595947 + 0.595947 + 0.595947 + 0.596191 + 0.596191 + 0.596191 + 0.596191 + 0.596191 + 0.596191 + 0.596191 + 0.596191 + 0.596191 + 0.596191 + 0.596191 + 0.596191 + 0.596191 + 0.596191 + 0.596191 + 0.596191 + 0.596191 + 0.596191 + 0.596436 + 0.596436 + 0.596436 + 0.596436 + 0.596436 + 0.596436 + 0.596436 + 0.596436 + 0.596436 + 0.596436 + 0.596436 + 0.596436 + 0.596436 + 0.596436 + 0.596436 + 0.596436 + 0.596436 + 0.596436 + 0.596680 + 0.596680 + 0.596680 + 0.596680 + 0.596680 + 0.596680 + 0.596680 + 0.596680 + 0.596680 + 0.596680 + 0.596680 + 0.596680 + 0.596680 + 0.596680 + 0.596680 + 0.596680 + 0.596680 + 0.596680 + 0.596680 + 0.596924 + 0.596924 + 0.596924 + 0.596924 + 0.596924 + 0.596924 + 0.596924 + 0.596924 + 0.596924 + 0.596924 + 0.596924 + 0.596924 + 0.596924 + 0.596924 + 0.596924 + 0.596924 + 0.596924 + 0.596924 + 0.597168 + 0.597168 + 0.597168 + 0.597168 + 0.597168 + 0.597168 + 0.597168 + 0.597168 + 0.597168 + 0.597168 + 0.597168 + 0.597168 + 0.597168 + 0.597168 + 0.597168 + 0.597168 + 0.597168 + 0.597168 + 0.597412 + 0.597412 + 0.597412 + 0.597412 + 0.597412 + 0.597412 + 0.597412 + 0.597412 + 0.597412 + 0.597412 + 0.597412 + 0.597412 + 0.597412 + 0.597412 + 0.597412 + 0.597412 + 0.597412 + 0.597412 + 0.597656 + 0.597656 + 0.597656 + 0.597656 + 0.597656 + 0.597656 + 0.597656 + 0.597656 + 0.597656 + 0.597656 + 0.597656 + 0.597656 + 0.597656 + 0.597656 + 0.597656 + 0.597656 + 0.597656 + 0.597656 + 0.597656 + 0.597900 + 0.597900 + 0.597900 + 0.597900 + 0.597900 + 0.597900 + 0.597900 + 0.597900 + 0.597900 + 0.597900 + 0.597900 + 0.597900 + 0.597900 + 0.597900 + 0.597900 + 0.597900 + 0.597900 + 0.597900 + 0.598145 + 0.598145 + 0.598145 + 0.598145 + 0.598145 + 0.598145 + 0.598145 + 0.598145 + 0.598145 + 0.598145 + 0.598145 + 0.598145 + 0.598145 + 0.598145 + 0.598145 + 0.598145 + 0.598145 + 0.598145 + 0.598389 + 0.598389 + 0.598389 + 0.598389 + 0.598389 + 0.598389 + 0.598389 + 0.598389 + 0.598389 + 0.598389 + 0.598389 + 0.598389 + 0.598389 + 0.598389 + 0.598389 + 0.598389 + 0.598389 + 0.598389 + 0.598633 + 0.598633 + 0.598633 + 0.598633 + 0.598633 + 0.598633 + 0.598633 + 0.598633 + 0.598633 + 0.598633 + 0.598633 + 0.598633 + 0.598633 + 0.598633 + 0.598633 + 0.598633 + 0.598633 + 0.598633 + 0.598633 + 0.598877 + 0.598877 + 0.598877 + 0.598877 + 0.598877 + 0.598877 + 0.598877 + 0.598877 + 0.598877 + 0.598877 + 0.598877 + 0.598877 + 0.598877 + 0.598877 + 0.598877 + 0.598877 + 0.598877 + 0.598877 + 0.599121 + 0.599121 + 0.599121 + 0.599121 + 0.599121 + 0.599121 + 0.599121 + 0.599121 + 0.599121 + 0.599121 + 0.599121 + 0.599121 + 0.599121 + 0.599121 + 0.599121 + 0.599121 + 0.599121 + 0.599121 + 0.599365 + 0.599365 + 0.599365 + 0.599365 + 0.599365 + 0.599365 + 0.599365 + 0.599365 + 0.599365 + 0.599365 + 0.599365 + 0.599365 + 0.599365 + 0.599365 + 0.599365 + 0.599365 + 0.599365 + 0.599365 + 0.599365 + 0.599609 + 0.599609 + 0.599609 + 0.599609 + 0.599609 + 0.599609 + 0.599609 + 0.599609 + 0.599609 + 0.599609 + 0.599609 + 0.599609 + 0.599609 + 0.599609 + 0.599609 + 0.599609 + 0.599609 + 0.599609 + 0.599854 + 0.599854 + 0.599854 + 0.599854 + 0.599854 + 0.599854 + 0.599854 + 0.599854 + 0.599854 + 0.599854 + 0.599854 + 0.599854 + 0.599854 + 0.599854 + 0.599854 + 0.599854 + 0.599854 + 0.599854 + 0.599854 + 0.600098 + 0.600098 + 0.600098 + 0.600098 + 0.600098 + 0.600098 + 0.600098 + 0.600098 + 0.600098 + 0.600098 + 0.600098 + 0.600098 + 0.600098 + 0.600098 + 0.600098 + 0.600098 + 0.600098 + 0.600098 + 0.600342 + 0.600342 + 0.600342 + 0.600342 + 0.600342 + 0.600342 + 0.600342 + 0.600342 + 0.600342 + 0.600342 + 0.600342 + 0.600342 + 0.600342 + 0.600342 + 0.600342 + 0.600342 + 0.600342 + 0.600342 + 0.600586 + 0.600586 + 0.600586 + 0.600586 + 0.600586 + 0.600586 + 0.600586 + 0.600586 + 0.600586 + 0.600586 + 0.600586 + 0.600586 + 0.600586 + 0.600586 + 0.600586 + 0.600586 + 0.600586 + 0.600586 + 0.600586 + 0.600830 + 0.600830 + 0.600830 + 0.600830 + 0.600830 + 0.600830 + 0.600830 + 0.600830 + 0.600830 + 0.600830 + 0.600830 + 0.600830 + 0.600830 + 0.600830 + 0.600830 + 0.600830 + 0.600830 + 0.600830 + 0.601074 + 0.601074 + 0.601074 + 0.601074 + 0.601074 + 0.601074 + 0.601074 + 0.601074 + 0.601074 + 0.601074 + 0.601074 + 0.601074 + 0.601074 + 0.601074 + 0.601074 + 0.601074 + 0.601074 + 0.601074 + 0.601074 + 0.601318 + 0.601318 + 0.601318 + 0.601318 + 0.601318 + 0.601318 + 0.601318 + 0.601318 + 0.601318 + 0.601318 + 0.601318 + 0.601318 + 0.601318 + 0.601318 + 0.601318 + 0.601318 + 0.601318 + 0.601318 + 0.601562 + 0.601562 + 0.601562 + 0.601562 + 0.601562 + 0.601562 + 0.601562 + 0.601562 + 0.601562 + 0.601562 + 0.601562 + 0.601562 + 0.601562 + 0.601562 + 0.601562 + 0.601562 + 0.601562 + 0.601562 + 0.601562 + 0.601807 + 0.601807 + 0.601807 + 0.601807 + 0.601807 + 0.601807 + 0.601807 + 0.601807 + 0.601807 + 0.601807 + 0.601807 + 0.601807 + 0.601807 + 0.601807 + 0.601807 + 0.601807 + 0.601807 + 0.601807 + 0.602051 + 0.602051 + 0.602051 + 0.602051 + 0.602051 + 0.602051 + 0.602051 + 0.602051 + 0.602051 + 0.602051 + 0.602051 + 0.602051 + 0.602051 + 0.602051 + 0.602051 + 0.602051 + 0.602051 + 0.602051 + 0.602051 + 0.602295 + 0.602295 + 0.602295 + 0.602295 + 0.602295 + 0.602295 + 0.602295 + 0.602295 + 0.602295 + 0.602295 + 0.602295 + 0.602295 + 0.602295 + 0.602295 + 0.602295 + 0.602295 + 0.602295 + 0.602295 + 0.602539 + 0.602539 + 0.602539 + 0.602539 + 0.602539 + 0.602539 + 0.602539 + 0.602539 + 0.602539 + 0.602539 + 0.602539 + 0.602539 + 0.602539 + 0.602539 + 0.602539 + 0.602539 + 0.602539 + 0.602539 + 0.602539 + 0.602783 + 0.602783 + 0.602783 + 0.602783 + 0.602783 + 0.602783 + 0.602783 + 0.602783 + 0.602783 + 0.602783 + 0.602783 + 0.602783 + 0.602783 + 0.602783 + 0.602783 + 0.602783 + 0.602783 + 0.602783 + 0.603027 + 0.603027 + 0.603027 + 0.603027 + 0.603027 + 0.603027 + 0.603027 + 0.603027 + 0.603027 + 0.603027 + 0.603027 + 0.603027 + 0.603027 + 0.603027 + 0.603027 + 0.603027 + 0.603027 + 0.603027 + 0.603027 + 0.603271 + 0.603271 + 0.603271 + 0.603271 + 0.603271 + 0.603271 + 0.603271 + 0.603271 + 0.603271 + 0.603271 + 0.603271 + 0.603271 + 0.603271 + 0.603271 + 0.603271 + 0.603271 + 0.603271 + 0.603271 + 0.603516 + 0.603516 + 0.603516 + 0.603516 + 0.603516 + 0.603516 + 0.603516 + 0.603516 + 0.603516 + 0.603516 + 0.603516 + 0.603516 + 0.603516 + 0.603516 + 0.603516 + 0.603516 + 0.603516 + 0.603516 + 0.603516 + 0.603760 + 0.603760 + 0.603760 + 0.603760 + 0.603760 + 0.603760 + 0.603760 + 0.603760 + 0.603760 + 0.603760 + 0.603760 + 0.603760 + 0.603760 + 0.603760 + 0.603760 + 0.603760 + 0.603760 + 0.603760 + 0.604004 + 0.604004 + 0.604004 + 0.604004 + 0.604004 + 0.604004 + 0.604004 + 0.604004 + 0.604004 + 0.604004 + 0.604004 + 0.604004 + 0.604004 + 0.604004 + 0.604004 + 0.604004 + 0.604004 + 0.604004 + 0.604004 + 0.604248 + 0.604248 + 0.604248 + 0.604248 + 0.604248 + 0.604248 + 0.604248 + 0.604248 + 0.604248 + 0.604248 + 0.604248 + 0.604248 + 0.604248 + 0.604248 + 0.604248 + 0.604248 + 0.604248 + 0.604248 + 0.604492 + 0.604492 + 0.604492 + 0.604492 + 0.604492 + 0.604492 + 0.604492 + 0.604492 + 0.604492 + 0.604492 + 0.604492 + 0.604492 + 0.604492 + 0.604492 + 0.604492 + 0.604492 + 0.604492 + 0.604492 + 0.604492 + 0.604736 + 0.604736 + 0.604736 + 0.604736 + 0.604736 + 0.604736 + 0.604736 + 0.604736 + 0.604736 + 0.604736 + 0.604736 + 0.604736 + 0.604736 + 0.604736 + 0.604736 + 0.604736 + 0.604736 + 0.604736 + 0.604736 + 0.604980 + 0.604980 + 0.604980 + 0.604980 + 0.604980 + 0.604980 + 0.604980 + 0.604980 + 0.604980 + 0.604980 + 0.604980 + 0.604980 + 0.604980 + 0.604980 + 0.604980 + 0.604980 + 0.604980 + 0.604980 + 0.605225 + 0.605225 + 0.605225 + 0.605225 + 0.605225 + 0.605225 + 0.605225 + 0.605225 + 0.605225 + 0.605225 + 0.605225 + 0.605225 + 0.605225 + 0.605225 + 0.605225 + 0.605225 + 0.605225 + 0.605225 + 0.605225 + 0.605469 + 0.605469 + 0.605469 + 0.605469 + 0.605469 + 0.605469 + 0.605469 + 0.605469 + 0.605469 + 0.605469 + 0.605469 + 0.605469 + 0.605469 + 0.605469 + 0.605469 + 0.605469 + 0.605469 + 0.605469 + 0.605469 + 0.605713 + 0.605713 + 0.605713 + 0.605713 + 0.605713 + 0.605713 + 0.605713 + 0.605713 + 0.605713 + 0.605713 + 0.605713 + 0.605713 + 0.605713 + 0.605713 + 0.605713 + 0.605713 + 0.605713 + 0.605713 + 0.605957 + 0.605957 + 0.605957 + 0.605957 + 0.605957 + 0.605957 + 0.605957 + 0.605957 + 0.605957 + 0.605957 + 0.605957 + 0.605957 + 0.605957 + 0.605957 + 0.605957 + 0.605957 + 0.605957 + 0.605957 + 0.605957 + 0.606201 + 0.606201 + 0.606201 + 0.606201 + 0.606201 + 0.606201 + 0.606201 + 0.606201 + 0.606201 + 0.606201 + 0.606201 + 0.606201 + 0.606201 + 0.606201 + 0.606201 + 0.606201 + 0.606201 + 0.606201 + 0.606201 + 0.606445 + 0.606445 + 0.606445 + 0.606445 + 0.606445 + 0.606445 + 0.606445 + 0.606445 + 0.606445 + 0.606445 + 0.606445 + 0.606445 + 0.606445 + 0.606445 + 0.606445 + 0.606445 + 0.606445 + 0.606445 + 0.606689 + 0.606689 + 0.606689 + 0.606689 + 0.606689 + 0.606689 + 0.606689 + 0.606689 + 0.606689 + 0.606689 + 0.606689 + 0.606689 + 0.606689 + 0.606689 + 0.606689 + 0.606689 + 0.606689 + 0.606689 + 0.606689 + 0.606934 + 0.606934 + 0.606934 + 0.606934 + 0.606934 + 0.606934 + 0.606934 + 0.606934 + 0.606934 + 0.606934 + 0.606934 + 0.606934 + 0.606934 + 0.606934 + 0.606934 + 0.606934 + 0.606934 + 0.606934 + 0.606934 + 0.607178 + 0.607178 + 0.607178 + 0.607178 + 0.607178 + 0.607178 + 0.607178 + 0.607178 + 0.607178 + 0.607178 + 0.607178 + 0.607178 + 0.607178 + 0.607178 + 0.607178 + 0.607178 + 0.607178 + 0.607178 + 0.607178 + 0.607422 + 0.607422 + 0.607422 + 0.607422 + 0.607422 + 0.607422 + 0.607422 + 0.607422 + 0.607422 + 0.607422 + 0.607422 + 0.607422 + 0.607422 + 0.607422 + 0.607422 + 0.607422 + 0.607422 + 0.607422 + 0.607666 + 0.607666 + 0.607666 + 0.607666 + 0.607666 + 0.607666 + 0.607666 + 0.607666 + 0.607666 + 0.607666 + 0.607666 + 0.607666 + 0.607666 + 0.607666 + 0.607666 + 0.607666 + 0.607666 + 0.607666 + 0.607666 + 0.607910 + 0.607910 + 0.607910 + 0.607910 + 0.607910 + 0.607910 + 0.607910 + 0.607910 + 0.607910 + 0.607910 + 0.607910 + 0.607910 + 0.607910 + 0.607910 + 0.607910 + 0.607910 + 0.607910 + 0.607910 + 0.607910 + 0.608154 + 0.608154 + 0.608154 + 0.608154 + 0.608154 + 0.608154 + 0.608154 + 0.608154 + 0.608154 + 0.608154 + 0.608154 + 0.608154 + 0.608154 + 0.608154 + 0.608154 + 0.608154 + 0.608154 + 0.608154 + 0.608154 + 0.608398 + 0.608398 + 0.608398 + 0.608398 + 0.608398 + 0.608398 + 0.608398 + 0.608398 + 0.608398 + 0.608398 + 0.608398 + 0.608398 + 0.608398 + 0.608398 + 0.608398 + 0.608398 + 0.608398 + 0.608398 + 0.608643 + 0.608643 + 0.608643 + 0.608643 + 0.608643 + 0.608643 + 0.608643 + 0.608643 + 0.608643 + 0.608643 + 0.608643 + 0.608643 + 0.608643 + 0.608643 + 0.608643 + 0.608643 + 0.608643 + 0.608643 + 0.608643 + 0.608887 + 0.608887 + 0.608887 + 0.608887 + 0.608887 + 0.608887 + 0.608887 + 0.608887 + 0.608887 + 0.608887 + 0.608887 + 0.608887 + 0.608887 + 0.608887 + 0.608887 + 0.608887 + 0.608887 + 0.608887 + 0.608887 + 0.609131 + 0.609131 + 0.609131 + 0.609131 + 0.609131 + 0.609131 + 0.609131 + 0.609131 + 0.609131 + 0.609131 + 0.609131 + 0.609131 + 0.609131 + 0.609131 + 0.609131 + 0.609131 + 0.609131 + 0.609131 + 0.609131 + 0.609375 + 0.609375 + 0.609375 + 0.609375 + 0.609375 + 0.609375 + 0.609375 + 0.609375 + 0.609375 + 0.609375 + 0.609375 + 0.609375 + 0.609375 + 0.609375 + 0.609375 + 0.609375 + 0.609375 + 0.609375 + 0.609375 + 0.609619 + 0.609619 + 0.609619 + 0.609619 + 0.609619 + 0.609619 + 0.609619 + 0.609619 + 0.609619 + 0.609619 + 0.609619 + 0.609619 + 0.609619 + 0.609619 + 0.609619 + 0.609619 + 0.609619 + 0.609619 + 0.609619 + 0.609863 + 0.609863 + 0.609863 + 0.609863 + 0.609863 + 0.609863 + 0.609863 + 0.609863 + 0.609863 + 0.609863 + 0.609863 + 0.609863 + 0.609863 + 0.609863 + 0.609863 + 0.609863 + 0.609863 + 0.609863 + 0.609863 + 0.610107 + 0.610107 + 0.610107 + 0.610107 + 0.610107 + 0.610107 + 0.610107 + 0.610107 + 0.610107 + 0.610107 + 0.610107 + 0.610107 + 0.610107 + 0.610107 + 0.610107 + 0.610107 + 0.610107 + 0.610107 + 0.610352 + 0.610352 + 0.610352 + 0.610352 + 0.610352 + 0.610352 + 0.610352 + 0.610352 + 0.610352 + 0.610352 + 0.610352 + 0.610352 + 0.610352 + 0.610352 + 0.610352 + 0.610352 + 0.610352 + 0.610352 + 0.610352 + 0.610596 + 0.610596 + 0.610596 + 0.610596 + 0.610596 + 0.610596 + 0.610596 + 0.610596 + 0.610596 + 0.610596 + 0.610596 + 0.610596 + 0.610596 + 0.610596 + 0.610596 + 0.610596 + 0.610596 + 0.610596 + 0.610596 + 0.610840 + 0.610840 + 0.610840 + 0.610840 + 0.610840 + 0.610840 + 0.610840 + 0.610840 + 0.610840 + 0.610840 + 0.610840 + 0.610840 + 0.610840 + 0.610840 + 0.610840 + 0.610840 + 0.610840 + 0.610840 + 0.610840 + 0.611084 + 0.611084 + 0.611084 + 0.611084 + 0.611084 + 0.611084 + 0.611084 + 0.611084 + 0.611084 + 0.611084 + 0.611084 + 0.611084 + 0.611084 + 0.611084 + 0.611084 + 0.611084 + 0.611084 + 0.611084 + 0.611084 + 0.611328 + 0.611328 + 0.611328 + 0.611328 + 0.611328 + 0.611328 + 0.611328 + 0.611328 + 0.611328 + 0.611328 + 0.611328 + 0.611328 + 0.611328 + 0.611328 + 0.611328 + 0.611328 + 0.611328 + 0.611328 + 0.611328 + 0.611572 + 0.611572 + 0.611572 + 0.611572 + 0.611572 + 0.611572 + 0.611572 + 0.611572 + 0.611572 + 0.611572 + 0.611572 + 0.611572 + 0.611572 + 0.611572 + 0.611572 + 0.611572 + 0.611572 + 0.611572 + 0.611572 + 0.611816 + 0.611816 + 0.611816 + 0.611816 + 0.611816 + 0.611816 + 0.611816 + 0.611816 + 0.611816 + 0.611816 + 0.611816 + 0.611816 + 0.611816 + 0.611816 + 0.611816 + 0.611816 + 0.611816 + 0.611816 + 0.611816 + 0.612061 + 0.612061 + 0.612061 + 0.612061 + 0.612061 + 0.612061 + 0.612061 + 0.612061 + 0.612061 + 0.612061 + 0.612061 + 0.612061 + 0.612061 + 0.612061 + 0.612061 + 0.612061 + 0.612061 + 0.612061 + 0.612061 + 0.612305 + 0.612305 + 0.612305 + 0.612305 + 0.612305 + 0.612305 + 0.612305 + 0.612305 + 0.612305 + 0.612305 + 0.612305 + 0.612305 + 0.612305 + 0.612305 + 0.612305 + 0.612305 + 0.612305 + 0.612305 + 0.612305 + 0.612549 + 0.612549 + 0.612549 + 0.612549 + 0.612549 + 0.612549 + 0.612549 + 0.612549 + 0.612549 + 0.612549 + 0.612549 + 0.612549 + 0.612549 + 0.612549 + 0.612549 + 0.612549 + 0.612549 + 0.612549 + 0.612549 + 0.612793 + 0.612793 + 0.612793 + 0.612793 + 0.612793 + 0.612793 + 0.612793 + 0.612793 + 0.612793 + 0.612793 + 0.612793 + 0.612793 + 0.612793 + 0.612793 + 0.612793 + 0.612793 + 0.612793 + 0.612793 + 0.612793 + 0.613037 + 0.613037 + 0.613037 + 0.613037 + 0.613037 + 0.613037 + 0.613037 + 0.613037 + 0.613037 + 0.613037 + 0.613037 + 0.613037 + 0.613037 + 0.613037 + 0.613037 + 0.613037 + 0.613037 + 0.613037 + 0.613037 + 0.613281 + 0.613281 + 0.613281 + 0.613281 + 0.613281 + 0.613281 + 0.613281 + 0.613281 + 0.613281 + 0.613281 + 0.613281 + 0.613281 + 0.613281 + 0.613281 + 0.613281 + 0.613281 + 0.613281 + 0.613281 + 0.613281 + 0.613525 + 0.613525 + 0.613525 + 0.613525 + 0.613525 + 0.613525 + 0.613525 + 0.613525 + 0.613525 + 0.613525 + 0.613525 + 0.613525 + 0.613525 + 0.613525 + 0.613525 + 0.613525 + 0.613525 + 0.613525 + 0.613525 + 0.613770 + 0.613770 + 0.613770 + 0.613770 + 0.613770 + 0.613770 + 0.613770 + 0.613770 + 0.613770 + 0.613770 + 0.613770 + 0.613770 + 0.613770 + 0.613770 + 0.613770 + 0.613770 + 0.613770 + 0.613770 + 0.613770 + 0.614014 + 0.614014 + 0.614014 + 0.614014 + 0.614014 + 0.614014 + 0.614014 + 0.614014 + 0.614014 + 0.614014 + 0.614014 + 0.614014 + 0.614014 + 0.614014 + 0.614014 + 0.614014 + 0.614014 + 0.614014 + 0.614014 + 0.614258 + 0.614258 + 0.614258 + 0.614258 + 0.614258 + 0.614258 + 0.614258 + 0.614258 + 0.614258 + 0.614258 + 0.614258 + 0.614258 + 0.614258 + 0.614258 + 0.614258 + 0.614258 + 0.614258 + 0.614258 + 0.614258 + 0.614502 + 0.614502 + 0.614502 + 0.614502 + 0.614502 + 0.614502 + 0.614502 + 0.614502 + 0.614502 + 0.614502 + 0.614502 + 0.614502 + 0.614502 + 0.614502 + 0.614502 + 0.614502 + 0.614502 + 0.614502 + 0.614502 + 0.614746 + 0.614746 + 0.614746 + 0.614746 + 0.614746 + 0.614746 + 0.614746 + 0.614746 + 0.614746 + 0.614746 + 0.614746 + 0.614746 + 0.614746 + 0.614746 + 0.614746 + 0.614746 + 0.614746 + 0.614746 + 0.614746 + 0.614746 + 0.614990 + 0.614990 + 0.614990 + 0.614990 + 0.614990 + 0.614990 + 0.614990 + 0.614990 + 0.614990 + 0.614990 + 0.614990 + 0.614990 + 0.614990 + 0.614990 + 0.614990 + 0.614990 + 0.614990 + 0.614990 + 0.614990 + 0.615234 + 0.615234 + 0.615234 + 0.615234 + 0.615234 + 0.615234 + 0.615234 + 0.615234 + 0.615234 + 0.615234 + 0.615234 + 0.615234 + 0.615234 + 0.615234 + 0.615234 + 0.615234 + 0.615234 + 0.615234 + 0.615234 + 0.615479 + 0.615479 + 0.615479 + 0.615479 + 0.615479 + 0.615479 + 0.615479 + 0.615479 + 0.615479 + 0.615479 + 0.615479 + 0.615479 + 0.615479 + 0.615479 + 0.615479 + 0.615479 + 0.615479 + 0.615479 + 0.615479 + 0.615723 + 0.615723 + 0.615723 + 0.615723 + 0.615723 + 0.615723 + 0.615723 + 0.615723 + 0.615723 + 0.615723 + 0.615723 + 0.615723 + 0.615723 + 0.615723 + 0.615723 + 0.615723 + 0.615723 + 0.615723 + 0.615723 + 0.615967 + 0.615967 + 0.615967 + 0.615967 + 0.615967 + 0.615967 + 0.615967 + 0.615967 + 0.615967 + 0.615967 + 0.615967 + 0.615967 + 0.615967 + 0.615967 + 0.615967 + 0.615967 + 0.615967 + 0.615967 + 0.615967 + 0.616211 + 0.616211 + 0.616211 + 0.616211 + 0.616211 + 0.616211 + 0.616211 + 0.616211 + 0.616211 + 0.616211 + 0.616211 + 0.616211 + 0.616211 + 0.616211 + 0.616211 + 0.616211 + 0.616211 + 0.616211 + 0.616211 + 0.616211 + 0.616455 + 0.616455 + 0.616455 + 0.616455 + 0.616455 + 0.616455 + 0.616455 + 0.616455 + 0.616455 + 0.616455 + 0.616455 + 0.616455 + 0.616455 + 0.616455 + 0.616455 + 0.616455 + 0.616455 + 0.616455 + 0.616455 + 0.616699 + 0.616699 + 0.616699 + 0.616699 + 0.616699 + 0.616699 + 0.616699 + 0.616699 + 0.616699 + 0.616699 + 0.616699 + 0.616699 + 0.616699 + 0.616699 + 0.616699 + 0.616699 + 0.616699 + 0.616699 + 0.616699 + 0.616943 + 0.616943 + 0.616943 + 0.616943 + 0.616943 + 0.616943 + 0.616943 + 0.616943 + 0.616943 + 0.616943 + 0.616943 + 0.616943 + 0.616943 + 0.616943 + 0.616943 + 0.616943 + 0.616943 + 0.616943 + 0.616943 + 0.617188 + 0.617188 + 0.617188 + 0.617188 + 0.617188 + 0.617188 + 0.617188 + 0.617188 + 0.617188 + 0.617188 + 0.617188 + 0.617188 + 0.617188 + 0.617188 + 0.617188 + 0.617188 + 0.617188 + 0.617188 + 0.617188 + 0.617432 + 0.617432 + 0.617432 + 0.617432 + 0.617432 + 0.617432 + 0.617432 + 0.617432 + 0.617432 + 0.617432 + 0.617432 + 0.617432 + 0.617432 + 0.617432 + 0.617432 + 0.617432 + 0.617432 + 0.617432 + 0.617432 + 0.617432 + 0.617676 + 0.617676 + 0.617676 + 0.617676 + 0.617676 + 0.617676 + 0.617676 + 0.617676 + 0.617676 + 0.617676 + 0.617676 + 0.617676 + 0.617676 + 0.617676 + 0.617676 + 0.617676 + 0.617676 + 0.617676 + 0.617676 + 0.617920 + 0.617920 + 0.617920 + 0.617920 + 0.617920 + 0.617920 + 0.617920 + 0.617920 + 0.617920 + 0.617920 + 0.617920 + 0.617920 + 0.617920 + 0.617920 + 0.617920 + 0.617920 + 0.617920 + 0.617920 + 0.617920 + 0.618164 + 0.618164 + 0.618164 + 0.618164 + 0.618164 + 0.618164 + 0.618164 + 0.618164 + 0.618164 + 0.618164 + 0.618164 + 0.618164 + 0.618164 + 0.618164 + 0.618164 + 0.618164 + 0.618164 + 0.618164 + 0.618164 + 0.618408 + 0.618408 + 0.618408 + 0.618408 + 0.618408 + 0.618408 + 0.618408 + 0.618408 + 0.618408 + 0.618408 + 0.618408 + 0.618408 + 0.618408 + 0.618408 + 0.618408 + 0.618408 + 0.618408 + 0.618408 + 0.618408 + 0.618408 + 0.618652 + 0.618652 + 0.618652 + 0.618652 + 0.618652 + 0.618652 + 0.618652 + 0.618652 + 0.618652 + 0.618652 + 0.618652 + 0.618652 + 0.618652 + 0.618652 + 0.618652 + 0.618652 + 0.618652 + 0.618652 + 0.618652 + 0.618896 + 0.618896 + 0.618896 + 0.618896 + 0.618896 + 0.618896 + 0.618896 + 0.618896 + 0.618896 + 0.618896 + 0.618896 + 0.618896 + 0.618896 + 0.618896 + 0.618896 + 0.618896 + 0.618896 + 0.618896 + 0.618896 + 0.619141 + 0.619141 + 0.619141 + 0.619141 + 0.619141 + 0.619141 + 0.619141 + 0.619141 + 0.619141 + 0.619141 + 0.619141 + 0.619141 + 0.619141 + 0.619141 + 0.619141 + 0.619141 + 0.619141 + 0.619141 + 0.619141 + 0.619141 + 0.619385 + 0.619385 + 0.619385 + 0.619385 + 0.619385 + 0.619385 + 0.619385 + 0.619385 + 0.619385 + 0.619385 + 0.619385 + 0.619385 + 0.619385 + 0.619385 + 0.619385 + 0.619385 + 0.619385 + 0.619385 + 0.619385 + 0.619629 + 0.619629 + 0.619629 + 0.619629 + 0.619629 + 0.619629 + 0.619629 + 0.619629 + 0.619629 + 0.619629 + 0.619629 + 0.619629 + 0.619629 + 0.619629 + 0.619629 + 0.619629 + 0.619629 + 0.619629 + 0.619629 + 0.619873 + 0.619873 + 0.619873 + 0.619873 + 0.619873 + 0.619873 + 0.619873 + 0.619873 + 0.619873 + 0.619873 + 0.619873 + 0.619873 + 0.619873 + 0.619873 + 0.619873 + 0.619873 + 0.619873 + 0.619873 + 0.619873 + 0.619873 + 0.620117 + 0.620117 + 0.620117 + 0.620117 + 0.620117 + 0.620117 + 0.620117 + 0.620117 + 0.620117 + 0.620117 + 0.620117 + 0.620117 + 0.620117 + 0.620117 + 0.620117 + 0.620117 + 0.620117 + 0.620117 + 0.620117 + 0.620361 + 0.620361 + 0.620361 + 0.620361 + 0.620361 + 0.620361 + 0.620361 + 0.620361 + 0.620361 + 0.620361 + 0.620361 + 0.620361 + 0.620361 + 0.620361 + 0.620361 + 0.620361 + 0.620361 + 0.620361 + 0.620361 + 0.620361 + 0.620605 + 0.620605 + 0.620605 + 0.620605 + 0.620605 + 0.620605 + 0.620605 + 0.620605 + 0.620605 + 0.620605 + 0.620605 + 0.620605 + 0.620605 + 0.620605 + 0.620605 + 0.620605 + 0.620605 + 0.620605 + 0.620605 + 0.620850 + 0.620850 + 0.620850 + 0.620850 + 0.620850 + 0.620850 + 0.620850 + 0.620850 + 0.620850 + 0.620850 + 0.620850 + 0.620850 + 0.620850 + 0.620850 + 0.620850 + 0.620850 + 0.620850 + 0.620850 + 0.620850 + 0.621094 + 0.621094 + 0.621094 + 0.621094 + 0.621094 + 0.621094 + 0.621094 + 0.621094 + 0.621094 + 0.621094 + 0.621094 + 0.621094 + 0.621094 + 0.621094 + 0.621094 + 0.621094 + 0.621094 + 0.621094 + 0.621094 + 0.621094 + 0.621338 + 0.621338 + 0.621338 + 0.621338 + 0.621338 + 0.621338 + 0.621338 + 0.621338 + 0.621338 + 0.621338 + 0.621338 + 0.621338 + 0.621338 + 0.621338 + 0.621338 + 0.621338 + 0.621338 + 0.621338 + 0.621338 + 0.621582 + 0.621582 + 0.621582 + 0.621582 + 0.621582 + 0.621582 + 0.621582 + 0.621582 + 0.621582 + 0.621582 + 0.621582 + 0.621582 + 0.621582 + 0.621582 + 0.621582 + 0.621582 + 0.621582 + 0.621582 + 0.621582 + 0.621582 + 0.621826 + 0.621826 + 0.621826 + 0.621826 + 0.621826 + 0.621826 + 0.621826 + 0.621826 + 0.621826 + 0.621826 + 0.621826 + 0.621826 + 0.621826 + 0.621826 + 0.621826 + 0.621826 + 0.621826 + 0.621826 + 0.621826 + 0.622070 + 0.622070 + 0.622070 + 0.622070 + 0.622070 + 0.622070 + 0.622070 + 0.622070 + 0.622070 + 0.622070 + 0.622070 + 0.622070 + 0.622070 + 0.622070 + 0.622070 + 0.622070 + 0.622070 + 0.622070 + 0.622070 + 0.622070 + 0.622314 + 0.622314 + 0.622314 + 0.622314 + 0.622314 + 0.622314 + 0.622314 + 0.622314 + 0.622314 + 0.622314 + 0.622314 + 0.622314 + 0.622314 + 0.622314 + 0.622314 + 0.622314 + 0.622314 + 0.622314 + 0.622314 + 0.622559 + 0.622559 + 0.622559 + 0.622559 + 0.622559 + 0.622559 + 0.622559 + 0.622559 + 0.622559 + 0.622559 + 0.622559 + 0.622559 + 0.622559 + 0.622559 + 0.622559 + 0.622559 + 0.622559 + 0.622559 + 0.622559 + 0.622559 + 0.622803 + 0.622803 + 0.622803 + 0.622803 + 0.622803 + 0.622803 + 0.622803 + 0.622803 + 0.622803 + 0.622803 + 0.622803 + 0.622803 + 0.622803 + 0.622803 + 0.622803 + 0.622803 + 0.622803 + 0.622803 + 0.622803 + 0.623047 + 0.623047 + 0.623047 + 0.623047 + 0.623047 + 0.623047 + 0.623047 + 0.623047 + 0.623047 + 0.623047 + 0.623047 + 0.623047 + 0.623047 + 0.623047 + 0.623047 + 0.623047 + 0.623047 + 0.623047 + 0.623047 + 0.623047 + 0.623291 + 0.623291 + 0.623291 + 0.623291 + 0.623291 + 0.623291 + 0.623291 + 0.623291 + 0.623291 + 0.623291 + 0.623291 + 0.623291 + 0.623291 + 0.623291 + 0.623291 + 0.623291 + 0.623291 + 0.623291 + 0.623291 + 0.623535 + 0.623535 + 0.623535 + 0.623535 + 0.623535 + 0.623535 + 0.623535 + 0.623535 + 0.623535 + 0.623535 + 0.623535 + 0.623535 + 0.623535 + 0.623535 + 0.623535 + 0.623535 + 0.623535 + 0.623535 + 0.623535 + 0.623535 + 0.623779 + 0.623779 + 0.623779 + 0.623779 + 0.623779 + 0.623779 + 0.623779 + 0.623779 + 0.623779 + 0.623779 + 0.623779 + 0.623779 + 0.623779 + 0.623779 + 0.623779 + 0.623779 + 0.623779 + 0.623779 + 0.623779 + 0.624023 + 0.624023 + 0.624023 + 0.624023 + 0.624023 + 0.624023 + 0.624023 + 0.624023 + 0.624023 + 0.624023 + 0.624023 + 0.624023 + 0.624023 + 0.624023 + 0.624023 + 0.624023 + 0.624023 + 0.624023 + 0.624023 + 0.624023 + 0.624268 + 0.624268 + 0.624268 + 0.624268 + 0.624268 + 0.624268 + 0.624268 + 0.624268 + 0.624268 + 0.624268 + 0.624268 + 0.624268 + 0.624268 + 0.624268 + 0.624268 + 0.624268 + 0.624268 + 0.624268 + 0.624268 + 0.624268 + 0.624512 + 0.624512 + 0.624512 + 0.624512 + 0.624512 + 0.624512 + 0.624512 + 0.624512 + 0.624512 + 0.624512 + 0.624512 + 0.624512 + 0.624512 + 0.624512 + 0.624512 + 0.624512 + 0.624512 + 0.624512 + 0.624512 + 0.624756 + 0.624756 + 0.624756 + 0.624756 + 0.624756 + 0.624756 + 0.624756 + 0.624756 + 0.624756 + 0.624756 + 0.624756 + 0.624756 + 0.624756 + 0.624756 + 0.624756 + 0.624756 + 0.624756 + 0.624756 + 0.624756 + 0.624756 + 0.625000 + 0.625000 + 0.625000 + 0.625000 + 0.625000 + 0.625000 + 0.625000 + 0.625000 + 0.625000 + 0.625000 + 0.625000 + 0.625000 + 0.625000 + 0.625000 + 0.625000 + 0.625000 + 0.625000 + 0.625000 + 0.625000 + 0.625244 + 0.625244 + 0.625244 + 0.625244 + 0.625244 + 0.625244 + 0.625244 + 0.625244 + 0.625244 + 0.625244 + 0.625244 + 0.625244 + 0.625244 + 0.625244 + 0.625244 + 0.625244 + 0.625244 + 0.625244 + 0.625244 + 0.625244 + 0.625488 + 0.625488 + 0.625488 + 0.625488 + 0.625488 + 0.625488 + 0.625488 + 0.625488 + 0.625488 + 0.625488 + 0.625488 + 0.625488 + 0.625488 + 0.625488 + 0.625488 + 0.625488 + 0.625488 + 0.625488 + 0.625488 + 0.625488 + 0.625732 + 0.625732 + 0.625732 + 0.625732 + 0.625732 + 0.625732 + 0.625732 + 0.625732 + 0.625732 + 0.625732 + 0.625732 + 0.625732 + 0.625732 + 0.625732 + 0.625732 + 0.625732 + 0.625732 + 0.625732 + 0.625732 + 0.625977 + 0.625977 + 0.625977 + 0.625977 + 0.625977 + 0.625977 + 0.625977 + 0.625977 + 0.625977 + 0.625977 + 0.625977 + 0.625977 + 0.625977 + 0.625977 + 0.625977 + 0.625977 + 0.625977 + 0.625977 + 0.625977 + 0.625977 + 0.626221 + 0.626221 + 0.626221 + 0.626221 + 0.626221 + 0.626221 + 0.626221 + 0.626221 + 0.626221 + 0.626221 + 0.626221 + 0.626221 + 0.626221 + 0.626221 + 0.626221 + 0.626221 + 0.626221 + 0.626221 + 0.626221 + 0.626221 + 0.626465 + 0.626465 + 0.626465 + 0.626465 + 0.626465 + 0.626465 + 0.626465 + 0.626465 + 0.626465 + 0.626465 + 0.626465 + 0.626465 + 0.626465 + 0.626465 + 0.626465 + 0.626465 + 0.626465 + 0.626465 + 0.626465 + 0.626709 + 0.626709 + 0.626709 + 0.626709 + 0.626709 + 0.626709 + 0.626709 + 0.626709 + 0.626709 + 0.626709 + 0.626709 + 0.626709 + 0.626709 + 0.626709 + 0.626709 + 0.626709 + 0.626709 + 0.626709 + 0.626709 + 0.626709 + 0.626953 + 0.626953 + 0.626953 + 0.626953 + 0.626953 + 0.626953 + 0.626953 + 0.626953 + 0.626953 + 0.626953 + 0.626953 + 0.626953 + 0.626953 + 0.626953 + 0.626953 + 0.626953 + 0.626953 + 0.626953 + 0.626953 + 0.626953 + 0.627197 + 0.627197 + 0.627197 + 0.627197 + 0.627197 + 0.627197 + 0.627197 + 0.627197 + 0.627197 + 0.627197 + 0.627197 + 0.627197 + 0.627197 + 0.627197 + 0.627197 + 0.627197 + 0.627197 + 0.627197 + 0.627197 + 0.627197 + 0.627441 + 0.627441 + 0.627441 + 0.627441 + 0.627441 + 0.627441 + 0.627441 + 0.627441 + 0.627441 + 0.627441 + 0.627441 + 0.627441 + 0.627441 + 0.627441 + 0.627441 + 0.627441 + 0.627441 + 0.627441 + 0.627441 + 0.627686 + 0.627686 + 0.627686 + 0.627686 + 0.627686 + 0.627686 + 0.627686 + 0.627686 + 0.627686 + 0.627686 + 0.627686 + 0.627686 + 0.627686 + 0.627686 + 0.627686 + 0.627686 + 0.627686 + 0.627686 + 0.627686 + 0.627686 + 0.627930 + 0.627930 + 0.627930 + 0.627930 + 0.627930 + 0.627930 + 0.627930 + 0.627930 + 0.627930 + 0.627930 + 0.627930 + 0.627930 + 0.627930 + 0.627930 + 0.627930 + 0.627930 + 0.627930 + 0.627930 + 0.627930 + 0.627930 + 0.628174 + 0.628174 + 0.628174 + 0.628174 + 0.628174 + 0.628174 + 0.628174 + 0.628174 + 0.628174 + 0.628174 + 0.628174 + 0.628174 + 0.628174 + 0.628174 + 0.628174 + 0.628174 + 0.628174 + 0.628174 + 0.628174 + 0.628174 + 0.628418 + 0.628418 + 0.628418 + 0.628418 + 0.628418 + 0.628418 + 0.628418 + 0.628418 + 0.628418 + 0.628418 + 0.628418 + 0.628418 + 0.628418 + 0.628418 + 0.628418 + 0.628418 + 0.628418 + 0.628418 + 0.628418 + 0.628418 + 0.628662 + 0.628662 + 0.628662 + 0.628662 + 0.628662 + 0.628662 + 0.628662 + 0.628662 + 0.628662 + 0.628662 + 0.628662 + 0.628662 + 0.628662 + 0.628662 + 0.628662 + 0.628662 + 0.628662 + 0.628662 + 0.628662 + 0.628906 + 0.628906 + 0.628906 + 0.628906 + 0.628906 + 0.628906 + 0.628906 + 0.628906 + 0.628906 + 0.628906 + 0.628906 + 0.628906 + 0.628906 + 0.628906 + 0.628906 + 0.628906 + 0.628906 + 0.628906 + 0.628906 + 0.628906 + 0.629150 + 0.629150 + 0.629150 + 0.629150 + 0.629150 + 0.629150 + 0.629150 + 0.629150 + 0.629150 + 0.629150 + 0.629150 + 0.629150 + 0.629150 + 0.629150 + 0.629150 + 0.629150 + 0.629150 + 0.629150 + 0.629150 + 0.629150 + 0.629395 + 0.629395 + 0.629395 + 0.629395 + 0.629395 + 0.629395 + 0.629395 + 0.629395 + 0.629395 + 0.629395 + 0.629395 + 0.629395 + 0.629395 + 0.629395 + 0.629395 + 0.629395 + 0.629395 + 0.629395 + 0.629395 + 0.629395 + 0.629639 + 0.629639 + 0.629639 + 0.629639 + 0.629639 + 0.629639 + 0.629639 + 0.629639 + 0.629639 + 0.629639 + 0.629639 + 0.629639 + 0.629639 + 0.629639 + 0.629639 + 0.629639 + 0.629639 + 0.629639 + 0.629639 + 0.629639 + 0.629883 + 0.629883 + 0.629883 + 0.629883 + 0.629883 + 0.629883 + 0.629883 + 0.629883 + 0.629883 + 0.629883 + 0.629883 + 0.629883 + 0.629883 + 0.629883 + 0.629883 + 0.629883 + 0.629883 + 0.629883 + 0.629883 + 0.629883 + 0.630127 + 0.630127 + 0.630127 + 0.630127 + 0.630127 + 0.630127 + 0.630127 + 0.630127 + 0.630127 + 0.630127 + 0.630127 + 0.630127 + 0.630127 + 0.630127 + 0.630127 + 0.630127 + 0.630127 + 0.630127 + 0.630127 + 0.630127 + 0.630371 + 0.630371 + 0.630371 + 0.630371 + 0.630371 + 0.630371 + 0.630371 + 0.630371 + 0.630371 + 0.630371 + 0.630371 + 0.630371 + 0.630371 + 0.630371 + 0.630371 + 0.630371 + 0.630371 + 0.630371 + 0.630371 + 0.630615 + 0.630615 + 0.630615 + 0.630615 + 0.630615 + 0.630615 + 0.630615 + 0.630615 + 0.630615 + 0.630615 + 0.630615 + 0.630615 + 0.630615 + 0.630615 + 0.630615 + 0.630615 + 0.630615 + 0.630615 + 0.630615 + 0.630615 + 0.630859 + 0.630859 + 0.630859 + 0.630859 + 0.630859 + 0.630859 + 0.630859 + 0.630859 + 0.630859 + 0.630859 + 0.630859 + 0.630859 + 0.630859 + 0.630859 + 0.630859 + 0.630859 + 0.630859 + 0.630859 + 0.630859 + 0.630859 + 0.631104 + 0.631104 + 0.631104 + 0.631104 + 0.631104 + 0.631104 + 0.631104 + 0.631104 + 0.631104 + 0.631104 + 0.631104 + 0.631104 + 0.631104 + 0.631104 + 0.631104 + 0.631104 + 0.631104 + 0.631104 + 0.631104 + 0.631104 + 0.631348 + 0.631348 + 0.631348 + 0.631348 + 0.631348 + 0.631348 + 0.631348 + 0.631348 + 0.631348 + 0.631348 + 0.631348 + 0.631348 + 0.631348 + 0.631348 + 0.631348 + 0.631348 + 0.631348 + 0.631348 + 0.631348 + 0.631348 + 0.631592 + 0.631592 + 0.631592 + 0.631592 + 0.631592 + 0.631592 + 0.631592 + 0.631592 + 0.631592 + 0.631592 + 0.631592 + 0.631592 + 0.631592 + 0.631592 + 0.631592 + 0.631592 + 0.631592 + 0.631592 + 0.631592 + 0.631592 + 0.631836 + 0.631836 + 0.631836 + 0.631836 + 0.631836 + 0.631836 + 0.631836 + 0.631836 + 0.631836 + 0.631836 + 0.631836 + 0.631836 + 0.631836 + 0.631836 + 0.631836 + 0.631836 + 0.631836 + 0.631836 + 0.631836 + 0.631836 + 0.632080 + 0.632080 + 0.632080 + 0.632080 + 0.632080 + 0.632080 + 0.632080 + 0.632080 + 0.632080 + 0.632080 + 0.632080 + 0.632080 + 0.632080 + 0.632080 + 0.632080 + 0.632080 + 0.632080 + 0.632080 + 0.632080 + 0.632080 + 0.632324 + 0.632324 + 0.632324 + 0.632324 + 0.632324 + 0.632324 + 0.632324 + 0.632324 + 0.632324 + 0.632324 + 0.632324 + 0.632324 + 0.632324 + 0.632324 + 0.632324 + 0.632324 + 0.632324 + 0.632324 + 0.632324 + 0.632324 + 0.632568 + 0.632568 + 0.632568 + 0.632568 + 0.632568 + 0.632568 + 0.632568 + 0.632568 + 0.632568 + 0.632568 + 0.632568 + 0.632568 + 0.632568 + 0.632568 + 0.632568 + 0.632568 + 0.632568 + 0.632568 + 0.632568 + 0.632568 + 0.632812 + 0.632812 + 0.632812 + 0.632812 + 0.632812 + 0.632812 + 0.632812 + 0.632812 + 0.632812 + 0.632812 + 0.632812 + 0.632812 + 0.632812 + 0.632812 + 0.632812 + 0.632812 + 0.632812 + 0.632812 + 0.632812 + 0.632812 + 0.633057 + 0.633057 + 0.633057 + 0.633057 + 0.633057 + 0.633057 + 0.633057 + 0.633057 + 0.633057 + 0.633057 + 0.633057 + 0.633057 + 0.633057 + 0.633057 + 0.633057 + 0.633057 + 0.633057 + 0.633057 + 0.633057 + 0.633057 + 0.633301 + 0.633301 + 0.633301 + 0.633301 + 0.633301 + 0.633301 + 0.633301 + 0.633301 + 0.633301 + 0.633301 + 0.633301 + 0.633301 + 0.633301 + 0.633301 + 0.633301 + 0.633301 + 0.633301 + 0.633301 + 0.633301 + 0.633301 + 0.633545 + 0.633545 + 0.633545 + 0.633545 + 0.633545 + 0.633545 + 0.633545 + 0.633545 + 0.633545 + 0.633545 + 0.633545 + 0.633545 + 0.633545 + 0.633545 + 0.633545 + 0.633545 + 0.633545 + 0.633545 + 0.633545 + 0.633545 + 0.633789 + 0.633789 + 0.633789 + 0.633789 + 0.633789 + 0.633789 + 0.633789 + 0.633789 + 0.633789 + 0.633789 + 0.633789 + 0.633789 + 0.633789 + 0.633789 + 0.633789 + 0.633789 + 0.633789 + 0.633789 + 0.633789 + 0.633789 + 0.634033 + 0.634033 + 0.634033 + 0.634033 + 0.634033 + 0.634033 + 0.634033 + 0.634033 + 0.634033 + 0.634033 + 0.634033 + 0.634033 + 0.634033 + 0.634033 + 0.634033 + 0.634033 + 0.634033 + 0.634033 + 0.634033 + 0.634033 + 0.634277 + 0.634277 + 0.634277 + 0.634277 + 0.634277 + 0.634277 + 0.634277 + 0.634277 + 0.634277 + 0.634277 + 0.634277 + 0.634277 + 0.634277 + 0.634277 + 0.634277 + 0.634277 + 0.634277 + 0.634277 + 0.634277 + 0.634277 + 0.634521 + 0.634521 + 0.634521 + 0.634521 + 0.634521 + 0.634521 + 0.634521 + 0.634521 + 0.634521 + 0.634521 + 0.634521 + 0.634521 + 0.634521 + 0.634521 + 0.634521 + 0.634521 + 0.634521 + 0.634521 + 0.634521 + 0.634521 + 0.634521 + 0.634766 + 0.634766 + 0.634766 + 0.634766 + 0.634766 + 0.634766 + 0.634766 + 0.634766 + 0.634766 + 0.634766 + 0.634766 + 0.634766 + 0.634766 + 0.634766 + 0.634766 + 0.634766 + 0.634766 + 0.634766 + 0.634766 + 0.634766 + 0.635010 + 0.635010 + 0.635010 + 0.635010 + 0.635010 + 0.635010 + 0.635010 + 0.635010 + 0.635010 + 0.635010 + 0.635010 + 0.635010 + 0.635010 + 0.635010 + 0.635010 + 0.635010 + 0.635010 + 0.635010 + 0.635010 + 0.635010 + 0.635254 + 0.635254 + 0.635254 + 0.635254 + 0.635254 + 0.635254 + 0.635254 + 0.635254 + 0.635254 + 0.635254 + 0.635254 + 0.635254 + 0.635254 + 0.635254 + 0.635254 + 0.635254 + 0.635254 + 0.635254 + 0.635254 + 0.635254 + 0.635498 + 0.635498 + 0.635498 + 0.635498 + 0.635498 + 0.635498 + 0.635498 + 0.635498 + 0.635498 + 0.635498 + 0.635498 + 0.635498 + 0.635498 + 0.635498 + 0.635498 + 0.635498 + 0.635498 + 0.635498 + 0.635498 + 0.635498 + 0.635742 + 0.635742 + 0.635742 + 0.635742 + 0.635742 + 0.635742 + 0.635742 + 0.635742 + 0.635742 + 0.635742 + 0.635742 + 0.635742 + 0.635742 + 0.635742 + 0.635742 + 0.635742 + 0.635742 + 0.635742 + 0.635742 + 0.635742 + 0.635986 + 0.635986 + 0.635986 + 0.635986 + 0.635986 + 0.635986 + 0.635986 + 0.635986 + 0.635986 + 0.635986 + 0.635986 + 0.635986 + 0.635986 + 0.635986 + 0.635986 + 0.635986 + 0.635986 + 0.635986 + 0.635986 + 0.635986 + 0.635986 + 0.636230 + 0.636230 + 0.636230 + 0.636230 + 0.636230 + 0.636230 + 0.636230 + 0.636230 + 0.636230 + 0.636230 + 0.636230 + 0.636230 + 0.636230 + 0.636230 + 0.636230 + 0.636230 + 0.636230 + 0.636230 + 0.636230 + 0.636230 + 0.636475 + 0.636475 + 0.636475 + 0.636475 + 0.636475 + 0.636475 + 0.636475 + 0.636475 + 0.636475 + 0.636475 + 0.636475 + 0.636475 + 0.636475 + 0.636475 + 0.636475 + 0.636475 + 0.636475 + 0.636475 + 0.636475 + 0.636475 + 0.636719 + 0.636719 + 0.636719 + 0.636719 + 0.636719 + 0.636719 + 0.636719 + 0.636719 + 0.636719 + 0.636719 + 0.636719 + 0.636719 + 0.636719 + 0.636719 + 0.636719 + 0.636719 + 0.636719 + 0.636719 + 0.636719 + 0.636719 + 0.636963 + 0.636963 + 0.636963 + 0.636963 + 0.636963 + 0.636963 + 0.636963 + 0.636963 + 0.636963 + 0.636963 + 0.636963 + 0.636963 + 0.636963 + 0.636963 + 0.636963 + 0.636963 + 0.636963 + 0.636963 + 0.636963 + 0.636963 + 0.637207 + 0.637207 + 0.637207 + 0.637207 + 0.637207 + 0.637207 + 0.637207 + 0.637207 + 0.637207 + 0.637207 + 0.637207 + 0.637207 + 0.637207 + 0.637207 + 0.637207 + 0.637207 + 0.637207 + 0.637207 + 0.637207 + 0.637207 + 0.637207 + 0.637451 + 0.637451 + 0.637451 + 0.637451 + 0.637451 + 0.637451 + 0.637451 + 0.637451 + 0.637451 + 0.637451 + 0.637451 + 0.637451 + 0.637451 + 0.637451 + 0.637451 + 0.637451 + 0.637451 + 0.637451 + 0.637451 + 0.637451 + 0.637695 + 0.637695 + 0.637695 + 0.637695 + 0.637695 + 0.637695 + 0.637695 + 0.637695 + 0.637695 + 0.637695 + 0.637695 + 0.637695 + 0.637695 + 0.637695 + 0.637695 + 0.637695 + 0.637695 + 0.637695 + 0.637695 + 0.637695 + 0.637939 + 0.637939 + 0.637939 + 0.637939 + 0.637939 + 0.637939 + 0.637939 + 0.637939 + 0.637939 + 0.637939 + 0.637939 + 0.637939 + 0.637939 + 0.637939 + 0.637939 + 0.637939 + 0.637939 + 0.637939 + 0.637939 + 0.637939 + 0.638184 + 0.638184 + 0.638184 + 0.638184 + 0.638184 + 0.638184 + 0.638184 + 0.638184 + 0.638184 + 0.638184 + 0.638184 + 0.638184 + 0.638184 + 0.638184 + 0.638184 + 0.638184 + 0.638184 + 0.638184 + 0.638184 + 0.638184 + 0.638184 + 0.638428 + 0.638428 + 0.638428 + 0.638428 + 0.638428 + 0.638428 + 0.638428 + 0.638428 + 0.638428 + 0.638428 + 0.638428 + 0.638428 + 0.638428 + 0.638428 + 0.638428 + 0.638428 + 0.638428 + 0.638428 + 0.638428 + 0.638428 + 0.638672 + 0.638672 + 0.638672 + 0.638672 + 0.638672 + 0.638672 + 0.638672 + 0.638672 + 0.638672 + 0.638672 + 0.638672 + 0.638672 + 0.638672 + 0.638672 + 0.638672 + 0.638672 + 0.638672 + 0.638672 + 0.638672 + 0.638672 + 0.638916 + 0.638916 + 0.638916 + 0.638916 + 0.638916 + 0.638916 + 0.638916 + 0.638916 + 0.638916 + 0.638916 + 0.638916 + 0.638916 + 0.638916 + 0.638916 + 0.638916 + 0.638916 + 0.638916 + 0.638916 + 0.638916 + 0.638916 + 0.638916 + 0.639160 + 0.639160 + 0.639160 + 0.639160 + 0.639160 + 0.639160 + 0.639160 + 0.639160 + 0.639160 + 0.639160 + 0.639160 + 0.639160 + 0.639160 + 0.639160 + 0.639160 + 0.639160 + 0.639160 + 0.639160 + 0.639160 + 0.639160 + 0.639404 + 0.639404 + 0.639404 + 0.639404 + 0.639404 + 0.639404 + 0.639404 + 0.639404 + 0.639404 + 0.639404 + 0.639404 + 0.639404 + 0.639404 + 0.639404 + 0.639404 + 0.639404 + 0.639404 + 0.639404 + 0.639404 + 0.639404 + 0.639648 + 0.639648 + 0.639648 + 0.639648 + 0.639648 + 0.639648 + 0.639648 + 0.639648 + 0.639648 + 0.639648 + 0.639648 + 0.639648 + 0.639648 + 0.639648 + 0.639648 + 0.639648 + 0.639648 + 0.639648 + 0.639648 + 0.639648 + 0.639648 + 0.639893 + 0.639893 + 0.639893 + 0.639893 + 0.639893 + 0.639893 + 0.639893 + 0.639893 + 0.639893 + 0.639893 + 0.639893 + 0.639893 + 0.639893 + 0.639893 + 0.639893 + 0.639893 + 0.639893 + 0.639893 + 0.639893 + 0.639893 + 0.640137 + 0.640137 + 0.640137 + 0.640137 + 0.640137 + 0.640137 + 0.640137 + 0.640137 + 0.640137 + 0.640137 + 0.640137 + 0.640137 + 0.640137 + 0.640137 + 0.640137 + 0.640137 + 0.640137 + 0.640137 + 0.640137 + 0.640137 + 0.640137 + 0.640381 + 0.640381 + 0.640381 + 0.640381 + 0.640381 + 0.640381 + 0.640381 + 0.640381 + 0.640381 + 0.640381 + 0.640381 + 0.640381 + 0.640381 + 0.640381 + 0.640381 + 0.640381 + 0.640381 + 0.640381 + 0.640381 + 0.640381 + 0.640625 + 0.640625 + 0.640625 + 0.640625 + 0.640625 + 0.640625 + 0.640625 + 0.640625 + 0.640625 + 0.640625 + 0.640625 + 0.640625 + 0.640625 + 0.640625 + 0.640625 + 0.640625 + 0.640625 + 0.640625 + 0.640625 + 0.640625 + 0.640869 + 0.640869 + 0.640869 + 0.640869 + 0.640869 + 0.640869 + 0.640869 + 0.640869 + 0.640869 + 0.640869 + 0.640869 + 0.640869 + 0.640869 + 0.640869 + 0.640869 + 0.640869 + 0.640869 + 0.640869 + 0.640869 + 0.640869 + 0.640869 + 0.641113 + 0.641113 + 0.641113 + 0.641113 + 0.641113 + 0.641113 + 0.641113 + 0.641113 + 0.641113 + 0.641113 + 0.641113 + 0.641113 + 0.641113 + 0.641113 + 0.641113 + 0.641113 + 0.641113 + 0.641113 + 0.641113 + 0.641113 + 0.641357 + 0.641357 + 0.641357 + 0.641357 + 0.641357 + 0.641357 + 0.641357 + 0.641357 + 0.641357 + 0.641357 + 0.641357 + 0.641357 + 0.641357 + 0.641357 + 0.641357 + 0.641357 + 0.641357 + 0.641357 + 0.641357 + 0.641357 + 0.641357 + 0.641602 + 0.641602 + 0.641602 + 0.641602 + 0.641602 + 0.641602 + 0.641602 + 0.641602 + 0.641602 + 0.641602 + 0.641602 + 0.641602 + 0.641602 + 0.641602 + 0.641602 + 0.641602 + 0.641602 + 0.641602 + 0.641602 + 0.641602 + 0.641846 + 0.641846 + 0.641846 + 0.641846 + 0.641846 + 0.641846 + 0.641846 + 0.641846 + 0.641846 + 0.641846 + 0.641846 + 0.641846 + 0.641846 + 0.641846 + 0.641846 + 0.641846 + 0.641846 + 0.641846 + 0.641846 + 0.641846 + 0.641846 + 0.642090 + 0.642090 + 0.642090 + 0.642090 + 0.642090 + 0.642090 + 0.642090 + 0.642090 + 0.642090 + 0.642090 + 0.642090 + 0.642090 + 0.642090 + 0.642090 + 0.642090 + 0.642090 + 0.642090 + 0.642090 + 0.642090 + 0.642090 + 0.642334 + 0.642334 + 0.642334 + 0.642334 + 0.642334 + 0.642334 + 0.642334 + 0.642334 + 0.642334 + 0.642334 + 0.642334 + 0.642334 + 0.642334 + 0.642334 + 0.642334 + 0.642334 + 0.642334 + 0.642334 + 0.642334 + 0.642334 + 0.642334 + 0.642578 + 0.642578 + 0.642578 + 0.642578 + 0.642578 + 0.642578 + 0.642578 + 0.642578 + 0.642578 + 0.642578 + 0.642578 + 0.642578 + 0.642578 + 0.642578 + 0.642578 + 0.642578 + 0.642578 + 0.642578 + 0.642578 + 0.642578 + 0.642822 + 0.642822 + 0.642822 + 0.642822 + 0.642822 + 0.642822 + 0.642822 + 0.642822 + 0.642822 + 0.642822 + 0.642822 + 0.642822 + 0.642822 + 0.642822 + 0.642822 + 0.642822 + 0.642822 + 0.642822 + 0.642822 + 0.642822 + 0.642822 + 0.643066 + 0.643066 + 0.643066 + 0.643066 + 0.643066 + 0.643066 + 0.643066 + 0.643066 + 0.643066 + 0.643066 + 0.643066 + 0.643066 + 0.643066 + 0.643066 + 0.643066 + 0.643066 + 0.643066 + 0.643066 + 0.643066 + 0.643066 + 0.643311 + 0.643311 + 0.643311 + 0.643311 + 0.643311 + 0.643311 + 0.643311 + 0.643311 + 0.643311 + 0.643311 + 0.643311 + 0.643311 + 0.643311 + 0.643311 + 0.643311 + 0.643311 + 0.643311 + 0.643311 + 0.643311 + 0.643311 + 0.643311 + 0.643555 + 0.643555 + 0.643555 + 0.643555 + 0.643555 + 0.643555 + 0.643555 + 0.643555 + 0.643555 + 0.643555 + 0.643555 + 0.643555 + 0.643555 + 0.643555 + 0.643555 + 0.643555 + 0.643555 + 0.643555 + 0.643555 + 0.643555 + 0.643799 + 0.643799 + 0.643799 + 0.643799 + 0.643799 + 0.643799 + 0.643799 + 0.643799 + 0.643799 + 0.643799 + 0.643799 + 0.643799 + 0.643799 + 0.643799 + 0.643799 + 0.643799 + 0.643799 + 0.643799 + 0.643799 + 0.643799 + 0.643799 + 0.644043 + 0.644043 + 0.644043 + 0.644043 + 0.644043 + 0.644043 + 0.644043 + 0.644043 + 0.644043 + 0.644043 + 0.644043 + 0.644043 + 0.644043 + 0.644043 + 0.644043 + 0.644043 + 0.644043 + 0.644043 + 0.644043 + 0.644043 + 0.644043 + 0.644287 + 0.644287 + 0.644287 + 0.644287 + 0.644287 + 0.644287 + 0.644287 + 0.644287 + 0.644287 + 0.644287 + 0.644287 + 0.644287 + 0.644287 + 0.644287 + 0.644287 + 0.644287 + 0.644287 + 0.644287 + 0.644287 + 0.644287 + 0.644531 + 0.644531 + 0.644531 + 0.644531 + 0.644531 + 0.644531 + 0.644531 + 0.644531 + 0.644531 + 0.644531 + 0.644531 + 0.644531 + 0.644531 + 0.644531 + 0.644531 + 0.644531 + 0.644531 + 0.644531 + 0.644531 + 0.644531 + 0.644531 + 0.644775 + 0.644775 + 0.644775 + 0.644775 + 0.644775 + 0.644775 + 0.644775 + 0.644775 + 0.644775 + 0.644775 + 0.644775 + 0.644775 + 0.644775 + 0.644775 + 0.644775 + 0.644775 + 0.644775 + 0.644775 + 0.644775 + 0.644775 + 0.645020 + 0.645020 + 0.645020 + 0.645020 + 0.645020 + 0.645020 + 0.645020 + 0.645020 + 0.645020 + 0.645020 + 0.645020 + 0.645020 + 0.645020 + 0.645020 + 0.645020 + 0.645020 + 0.645020 + 0.645020 + 0.645020 + 0.645020 + 0.645020 + 0.645264 + 0.645264 + 0.645264 + 0.645264 + 0.645264 + 0.645264 + 0.645264 + 0.645264 + 0.645264 + 0.645264 + 0.645264 + 0.645264 + 0.645264 + 0.645264 + 0.645264 + 0.645264 + 0.645264 + 0.645264 + 0.645264 + 0.645264 + 0.645264 + 0.645508 + 0.645508 + 0.645508 + 0.645508 + 0.645508 + 0.645508 + 0.645508 + 0.645508 + 0.645508 + 0.645508 + 0.645508 + 0.645508 + 0.645508 + 0.645508 + 0.645508 + 0.645508 + 0.645508 + 0.645508 + 0.645508 + 0.645508 + 0.645752 + 0.645752 + 0.645752 + 0.645752 + 0.645752 + 0.645752 + 0.645752 + 0.645752 + 0.645752 + 0.645752 + 0.645752 + 0.645752 + 0.645752 + 0.645752 + 0.645752 + 0.645752 + 0.645752 + 0.645752 + 0.645752 + 0.645752 + 0.645752 + 0.645996 + 0.645996 + 0.645996 + 0.645996 + 0.645996 + 0.645996 + 0.645996 + 0.645996 + 0.645996 + 0.645996 + 0.645996 + 0.645996 + 0.645996 + 0.645996 + 0.645996 + 0.645996 + 0.645996 + 0.645996 + 0.645996 + 0.645996 + 0.645996 + 0.646240 + 0.646240 + 0.646240 + 0.646240 + 0.646240 + 0.646240 + 0.646240 + 0.646240 + 0.646240 + 0.646240 + 0.646240 + 0.646240 + 0.646240 + 0.646240 + 0.646240 + 0.646240 + 0.646240 + 0.646240 + 0.646240 + 0.646240 + 0.646484 + 0.646484 + 0.646484 + 0.646484 + 0.646484 + 0.646484 + 0.646484 + 0.646484 + 0.646484 + 0.646484 + 0.646484 + 0.646484 + 0.646484 + 0.646484 + 0.646484 + 0.646484 + 0.646484 + 0.646484 + 0.646484 + 0.646484 + 0.646484 + 0.646729 + 0.646729 + 0.646729 + 0.646729 + 0.646729 + 0.646729 + 0.646729 + 0.646729 + 0.646729 + 0.646729 + 0.646729 + 0.646729 + 0.646729 + 0.646729 + 0.646729 + 0.646729 + 0.646729 + 0.646729 + 0.646729 + 0.646729 + 0.646729 + 0.646973 + 0.646973 + 0.646973 + 0.646973 + 0.646973 + 0.646973 + 0.646973 + 0.646973 + 0.646973 + 0.646973 + 0.646973 + 0.646973 + 0.646973 + 0.646973 + 0.646973 + 0.646973 + 0.646973 + 0.646973 + 0.646973 + 0.646973 + 0.646973 + 0.647217 + 0.647217 + 0.647217 + 0.647217 + 0.647217 + 0.647217 + 0.647217 + 0.647217 + 0.647217 + 0.647217 + 0.647217 + 0.647217 + 0.647217 + 0.647217 + 0.647217 + 0.647217 + 0.647217 + 0.647217 + 0.647217 + 0.647217 + 0.647461 + 0.647461 + 0.647461 + 0.647461 + 0.647461 + 0.647461 + 0.647461 + 0.647461 + 0.647461 + 0.647461 + 0.647461 + 0.647461 + 0.647461 + 0.647461 + 0.647461 + 0.647461 + 0.647461 + 0.647461 + 0.647461 + 0.647461 + 0.647461 + 0.647705 + 0.647705 + 0.647705 + 0.647705 + 0.647705 + 0.647705 + 0.647705 + 0.647705 + 0.647705 + 0.647705 + 0.647705 + 0.647705 + 0.647705 + 0.647705 + 0.647705 + 0.647705 + 0.647705 + 0.647705 + 0.647705 + 0.647705 + 0.647705 + 0.647949 + 0.647949 + 0.647949 + 0.647949 + 0.647949 + 0.647949 + 0.647949 + 0.647949 + 0.647949 + 0.647949 + 0.647949 + 0.647949 + 0.647949 + 0.647949 + 0.647949 + 0.647949 + 0.647949 + 0.647949 + 0.647949 + 0.647949 + 0.647949 + 0.648193 + 0.648193 + 0.648193 + 0.648193 + 0.648193 + 0.648193 + 0.648193 + 0.648193 + 0.648193 + 0.648193 + 0.648193 + 0.648193 + 0.648193 + 0.648193 + 0.648193 + 0.648193 + 0.648193 + 0.648193 + 0.648193 + 0.648193 + 0.648193 + 0.648438 + 0.648438 + 0.648438 + 0.648438 + 0.648438 + 0.648438 + 0.648438 + 0.648438 + 0.648438 + 0.648438 + 0.648438 + 0.648438 + 0.648438 + 0.648438 + 0.648438 + 0.648438 + 0.648438 + 0.648438 + 0.648438 + 0.648438 + 0.648682 + 0.648682 + 0.648682 + 0.648682 + 0.648682 + 0.648682 + 0.648682 + 0.648682 + 0.648682 + 0.648682 + 0.648682 + 0.648682 + 0.648682 + 0.648682 + 0.648682 + 0.648682 + 0.648682 + 0.648682 + 0.648682 + 0.648682 + 0.648682 + 0.648926 + 0.648926 + 0.648926 + 0.648926 + 0.648926 + 0.648926 + 0.648926 + 0.648926 + 0.648926 + 0.648926 + 0.648926 + 0.648926 + 0.648926 + 0.648926 + 0.648926 + 0.648926 + 0.648926 + 0.648926 + 0.648926 + 0.648926 + 0.648926 + 0.649170 + 0.649170 + 0.649170 + 0.649170 + 0.649170 + 0.649170 + 0.649170 + 0.649170 + 0.649170 + 0.649170 + 0.649170 + 0.649170 + 0.649170 + 0.649170 + 0.649170 + 0.649170 + 0.649170 + 0.649170 + 0.649170 + 0.649170 + 0.649170 + 0.649414 + 0.649414 + 0.649414 + 0.649414 + 0.649414 + 0.649414 + 0.649414 + 0.649414 + 0.649414 + 0.649414 + 0.649414 + 0.649414 + 0.649414 + 0.649414 + 0.649414 + 0.649414 + 0.649414 + 0.649414 + 0.649414 + 0.649414 + 0.649414 + 0.649658 + 0.649658 + 0.649658 + 0.649658 + 0.649658 + 0.649658 + 0.649658 + 0.649658 + 0.649658 + 0.649658 + 0.649658 + 0.649658 + 0.649658 + 0.649658 + 0.649658 + 0.649658 + 0.649658 + 0.649658 + 0.649658 + 0.649658 + 0.649658 + 0.649902 + 0.649902 + 0.649902 + 0.649902 + 0.649902 + 0.649902 + 0.649902 + 0.649902 + 0.649902 + 0.649902 + 0.649902 + 0.649902 + 0.649902 + 0.649902 + 0.649902 + 0.649902 + 0.649902 + 0.649902 + 0.649902 + 0.649902 + 0.649902 + 0.650146 + 0.650146 + 0.650146 + 0.650146 + 0.650146 + 0.650146 + 0.650146 + 0.650146 + 0.650146 + 0.650146 + 0.650146 + 0.650146 + 0.650146 + 0.650146 + 0.650146 + 0.650146 + 0.650146 + 0.650146 + 0.650146 + 0.650146 + 0.650146 + 0.650391 + 0.650391 + 0.650391 + 0.650391 + 0.650391 + 0.650391 + 0.650391 + 0.650391 + 0.650391 + 0.650391 + 0.650391 + 0.650391 + 0.650391 + 0.650391 + 0.650391 + 0.650391 + 0.650391 + 0.650391 + 0.650391 + 0.650391 + 0.650635 + 0.650635 + 0.650635 + 0.650635 + 0.650635 + 0.650635 + 0.650635 + 0.650635 + 0.650635 + 0.650635 + 0.650635 + 0.650635 + 0.650635 + 0.650635 + 0.650635 + 0.650635 + 0.650635 + 0.650635 + 0.650635 + 0.650635 + 0.650635 + 0.650879 + 0.650879 + 0.650879 + 0.650879 + 0.650879 + 0.650879 + 0.650879 + 0.650879 + 0.650879 + 0.650879 + 0.650879 + 0.650879 + 0.650879 + 0.650879 + 0.650879 + 0.650879 + 0.650879 + 0.650879 + 0.650879 + 0.650879 + 0.650879 + 0.651123 + 0.651123 + 0.651123 + 0.651123 + 0.651123 + 0.651123 + 0.651123 + 0.651123 + 0.651123 + 0.651123 + 0.651123 + 0.651123 + 0.651123 + 0.651123 + 0.651123 + 0.651123 + 0.651123 + 0.651123 + 0.651123 + 0.651123 + 0.651123 + 0.651367 + 0.651367 + 0.651367 + 0.651367 + 0.651367 + 0.651367 + 0.651367 + 0.651367 + 0.651367 + 0.651367 + 0.651367 + 0.651367 + 0.651367 + 0.651367 + 0.651367 + 0.651367 + 0.651367 + 0.651367 + 0.651367 + 0.651367 + 0.651367 + 0.651611 + 0.651611 + 0.651611 + 0.651611 + 0.651611 + 0.651611 + 0.651611 + 0.651611 + 0.651611 + 0.651611 + 0.651611 + 0.651611 + 0.651611 + 0.651611 + 0.651611 + 0.651611 + 0.651611 + 0.651611 + 0.651611 + 0.651611 + 0.651611 + 0.651855 + 0.651855 + 0.651855 + 0.651855 + 0.651855 + 0.651855 + 0.651855 + 0.651855 + 0.651855 + 0.651855 + 0.651855 + 0.651855 + 0.651855 + 0.651855 + 0.651855 + 0.651855 + 0.651855 + 0.651855 + 0.651855 + 0.651855 + 0.651855 + 0.652100 + 0.652100 + 0.652100 + 0.652100 + 0.652100 + 0.652100 + 0.652100 + 0.652100 + 0.652100 + 0.652100 + 0.652100 + 0.652100 + 0.652100 + 0.652100 + 0.652100 + 0.652100 + 0.652100 + 0.652100 + 0.652100 + 0.652100 + 0.652100 + 0.652344 + 0.652344 + 0.652344 + 0.652344 + 0.652344 + 0.652344 + 0.652344 + 0.652344 + 0.652344 + 0.652344 + 0.652344 + 0.652344 + 0.652344 + 0.652344 + 0.652344 + 0.652344 + 0.652344 + 0.652344 + 0.652344 + 0.652344 + 0.652344 + 0.652588 + 0.652588 + 0.652588 + 0.652588 + 0.652588 + 0.652588 + 0.652588 + 0.652588 + 0.652588 + 0.652588 + 0.652588 + 0.652588 + 0.652588 + 0.652588 + 0.652588 + 0.652588 + 0.652588 + 0.652588 + 0.652588 + 0.652588 + 0.652588 + 0.652832 + 0.652832 + 0.652832 + 0.652832 + 0.652832 + 0.652832 + 0.652832 + 0.652832 + 0.652832 + 0.652832 + 0.652832 + 0.652832 + 0.652832 + 0.652832 + 0.652832 + 0.652832 + 0.652832 + 0.652832 + 0.652832 + 0.652832 + 0.652832 + 0.653076 + 0.653076 + 0.653076 + 0.653076 + 0.653076 + 0.653076 + 0.653076 + 0.653076 + 0.653076 + 0.653076 + 0.653076 + 0.653076 + 0.653076 + 0.653076 + 0.653076 + 0.653076 + 0.653076 + 0.653076 + 0.653076 + 0.653076 + 0.653076 + 0.653320 + 0.653320 + 0.653320 + 0.653320 + 0.653320 + 0.653320 + 0.653320 + 0.653320 + 0.653320 + 0.653320 + 0.653320 + 0.653320 + 0.653320 + 0.653320 + 0.653320 + 0.653320 + 0.653320 + 0.653320 + 0.653320 + 0.653320 + 0.653320 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653564 + 0.653809 + 0.653809 + 0.653809 + 0.653809 + 0.653809 + 0.653809 + 0.653809 + 0.653809 + 0.653809 + 0.653809 + 0.653809 + 0.653809 + 0.653809 + 0.653809 + 0.653809 + 0.653809 + 0.653809 + 0.653809 + 0.653809 + 0.653809 + 0.653809 + 0.654053 + 0.654053 + 0.654053 + 0.654053 + 0.654053 + 0.654053 + 0.654053 + 0.654053 + 0.654053 + 0.654053 + 0.654053 + 0.654053 + 0.654053 + 0.654053 + 0.654053 + 0.654053 + 0.654053 + 0.654053 + 0.654053 + 0.654053 + 0.654053 + 0.654297 + 0.654297 + 0.654297 + 0.654297 + 0.654297 + 0.654297 + 0.654297 + 0.654297 + 0.654297 + 0.654297 + 0.654297 + 0.654297 + 0.654297 + 0.654297 + 0.654297 + 0.654297 + 0.654297 + 0.654297 + 0.654297 + 0.654297 + 0.654297 + 0.654541 + 0.654541 + 0.654541 + 0.654541 + 0.654541 + 0.654541 + 0.654541 + 0.654541 + 0.654541 + 0.654541 + 0.654541 + 0.654541 + 0.654541 + 0.654541 + 0.654541 + 0.654541 + 0.654541 + 0.654541 + 0.654541 + 0.654541 + 0.654541 + 0.654785 + 0.654785 + 0.654785 + 0.654785 + 0.654785 + 0.654785 + 0.654785 + 0.654785 + 0.654785 + 0.654785 + 0.654785 + 0.654785 + 0.654785 + 0.654785 + 0.654785 + 0.654785 + 0.654785 + 0.654785 + 0.654785 + 0.654785 + 0.654785 + 0.655029 + 0.655029 + 0.655029 + 0.655029 + 0.655029 + 0.655029 + 0.655029 + 0.655029 + 0.655029 + 0.655029 + 0.655029 + 0.655029 + 0.655029 + 0.655029 + 0.655029 + 0.655029 + 0.655029 + 0.655029 + 0.655029 + 0.655029 + 0.655029 + 0.655273 + 0.655273 + 0.655273 + 0.655273 + 0.655273 + 0.655273 + 0.655273 + 0.655273 + 0.655273 + 0.655273 + 0.655273 + 0.655273 + 0.655273 + 0.655273 + 0.655273 + 0.655273 + 0.655273 + 0.655273 + 0.655273 + 0.655273 + 0.655273 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655518 + 0.655762 + 0.655762 + 0.655762 + 0.655762 + 0.655762 + 0.655762 + 0.655762 + 0.655762 + 0.655762 + 0.655762 + 0.655762 + 0.655762 + 0.655762 + 0.655762 + 0.655762 + 0.655762 + 0.655762 + 0.655762 + 0.655762 + 0.655762 + 0.655762 + 0.656006 + 0.656006 + 0.656006 + 0.656006 + 0.656006 + 0.656006 + 0.656006 + 0.656006 + 0.656006 + 0.656006 + 0.656006 + 0.656006 + 0.656006 + 0.656006 + 0.656006 + 0.656006 + 0.656006 + 0.656006 + 0.656006 + 0.656006 + 0.656006 + 0.656250 + 0.656250 + 0.656250 + 0.656250 + 0.656250 + 0.656250 + 0.656250 + 0.656250 + 0.656250 + 0.656250 + 0.656250 + 0.656250 + 0.656250 + 0.656250 + 0.656250 + 0.656250 + 0.656250 + 0.656250 + 0.656250 + 0.656250 + 0.656250 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656494 + 0.656738 + 0.656738 + 0.656738 + 0.656738 + 0.656738 + 0.656738 + 0.656738 + 0.656738 + 0.656738 + 0.656738 + 0.656738 + 0.656738 + 0.656738 + 0.656738 + 0.656738 + 0.656738 + 0.656738 + 0.656738 + 0.656738 + 0.656738 + 0.656738 + 0.656982 + 0.656982 + 0.656982 + 0.656982 + 0.656982 + 0.656982 + 0.656982 + 0.656982 + 0.656982 + 0.656982 + 0.656982 + 0.656982 + 0.656982 + 0.656982 + 0.656982 + 0.656982 + 0.656982 + 0.656982 + 0.656982 + 0.656982 + 0.656982 + 0.657227 + 0.657227 + 0.657227 + 0.657227 + 0.657227 + 0.657227 + 0.657227 + 0.657227 + 0.657227 + 0.657227 + 0.657227 + 0.657227 + 0.657227 + 0.657227 + 0.657227 + 0.657227 + 0.657227 + 0.657227 + 0.657227 + 0.657227 + 0.657227 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657471 + 0.657715 + 0.657715 + 0.657715 + 0.657715 + 0.657715 + 0.657715 + 0.657715 + 0.657715 + 0.657715 + 0.657715 + 0.657715 + 0.657715 + 0.657715 + 0.657715 + 0.657715 + 0.657715 + 0.657715 + 0.657715 + 0.657715 + 0.657715 + 0.657715 + 0.657959 + 0.657959 + 0.657959 + 0.657959 + 0.657959 + 0.657959 + 0.657959 + 0.657959 + 0.657959 + 0.657959 + 0.657959 + 0.657959 + 0.657959 + 0.657959 + 0.657959 + 0.657959 + 0.657959 + 0.657959 + 0.657959 + 0.657959 + 0.657959 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658203 + 0.658447 + 0.658447 + 0.658447 + 0.658447 + 0.658447 + 0.658447 + 0.658447 + 0.658447 + 0.658447 + 0.658447 + 0.658447 + 0.658447 + 0.658447 + 0.658447 + 0.658447 + 0.658447 + 0.658447 + 0.658447 + 0.658447 + 0.658447 + 0.658447 + 0.658691 + 0.658691 + 0.658691 + 0.658691 + 0.658691 + 0.658691 + 0.658691 + 0.658691 + 0.658691 + 0.658691 + 0.658691 + 0.658691 + 0.658691 + 0.658691 + 0.658691 + 0.658691 + 0.658691 + 0.658691 + 0.658691 + 0.658691 + 0.658691 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.658936 + 0.659180 + 0.659180 + 0.659180 + 0.659180 + 0.659180 + 0.659180 + 0.659180 + 0.659180 + 0.659180 + 0.659180 + 0.659180 + 0.659180 + 0.659180 + 0.659180 + 0.659180 + 0.659180 + 0.659180 + 0.659180 + 0.659180 + 0.659180 + 0.659180 + 0.659424 + 0.659424 + 0.659424 + 0.659424 + 0.659424 + 0.659424 + 0.659424 + 0.659424 + 0.659424 + 0.659424 + 0.659424 + 0.659424 + 0.659424 + 0.659424 + 0.659424 + 0.659424 + 0.659424 + 0.659424 + 0.659424 + 0.659424 + 0.659424 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659668 + 0.659912 + 0.659912 + 0.659912 + 0.659912 + 0.659912 + 0.659912 + 0.659912 + 0.659912 + 0.659912 + 0.659912 + 0.659912 + 0.659912 + 0.659912 + 0.659912 + 0.659912 + 0.659912 + 0.659912 + 0.659912 + 0.659912 + 0.659912 + 0.659912 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660156 + 0.660400 + 0.660400 + 0.660400 + 0.660400 + 0.660400 + 0.660400 + 0.660400 + 0.660400 + 0.660400 + 0.660400 + 0.660400 + 0.660400 + 0.660400 + 0.660400 + 0.660400 + 0.660400 + 0.660400 + 0.660400 + 0.660400 + 0.660400 + 0.660400 + 0.660645 + 0.660645 + 0.660645 + 0.660645 + 0.660645 + 0.660645 + 0.660645 + 0.660645 + 0.660645 + 0.660645 + 0.660645 + 0.660645 + 0.660645 + 0.660645 + 0.660645 + 0.660645 + 0.660645 + 0.660645 + 0.660645 + 0.660645 + 0.660645 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.660889 + 0.661133 + 0.661133 + 0.661133 + 0.661133 + 0.661133 + 0.661133 + 0.661133 + 0.661133 + 0.661133 + 0.661133 + 0.661133 + 0.661133 + 0.661133 + 0.661133 + 0.661133 + 0.661133 + 0.661133 + 0.661133 + 0.661133 + 0.661133 + 0.661133 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661377 + 0.661621 + 0.661621 + 0.661621 + 0.661621 + 0.661621 + 0.661621 + 0.661621 + 0.661621 + 0.661621 + 0.661621 + 0.661621 + 0.661621 + 0.661621 + 0.661621 + 0.661621 + 0.661621 + 0.661621 + 0.661621 + 0.661621 + 0.661621 + 0.661621 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.661865 + 0.662109 + 0.662109 + 0.662109 + 0.662109 + 0.662109 + 0.662109 + 0.662109 + 0.662109 + 0.662109 + 0.662109 + 0.662109 + 0.662109 + 0.662109 + 0.662109 + 0.662109 + 0.662109 + 0.662109 + 0.662109 + 0.662109 + 0.662109 + 0.662109 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662354 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662598 + 0.662842 + 0.662842 + 0.662842 + 0.662842 + 0.662842 + 0.662842 + 0.662842 + 0.662842 + 0.662842 + 0.662842 + 0.662842 + 0.662842 + 0.662842 + 0.662842 + 0.662842 + 0.662842 + 0.662842 + 0.662842 + 0.662842 + 0.662842 + 0.662842 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663086 + 0.663330 + 0.663330 + 0.663330 + 0.663330 + 0.663330 + 0.663330 + 0.663330 + 0.663330 + 0.663330 + 0.663330 + 0.663330 + 0.663330 + 0.663330 + 0.663330 + 0.663330 + 0.663330 + 0.663330 + 0.663330 + 0.663330 + 0.663330 + 0.663330 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663574 + 0.663818 + 0.663818 + 0.663818 + 0.663818 + 0.663818 + 0.663818 + 0.663818 + 0.663818 + 0.663818 + 0.663818 + 0.663818 + 0.663818 + 0.663818 + 0.663818 + 0.663818 + 0.663818 + 0.663818 + 0.663818 + 0.663818 + 0.663818 + 0.663818 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664062 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664307 + 0.664551 + 0.664551 + 0.664551 + 0.664551 + 0.664551 + 0.664551 + 0.664551 + 0.664551 + 0.664551 + 0.664551 + 0.664551 + 0.664551 + 0.664551 + 0.664551 + 0.664551 + 0.664551 + 0.664551 + 0.664551 + 0.664551 + 0.664551 + 0.664551 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.664795 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665039 + 0.665283 + 0.665283 + 0.665283 + 0.665283 + 0.665283 + 0.665283 + 0.665283 + 0.665283 + 0.665283 + 0.665283 + 0.665283 + 0.665283 + 0.665283 + 0.665283 + 0.665283 + 0.665283 + 0.665283 + 0.665283 + 0.665283 + 0.665283 + 0.665283 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665527 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.665771 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666016 + 0.666260 + 0.666260 + 0.666260 + 0.666260 + 0.666260 + 0.666260 + 0.666260 + 0.666260 + 0.666260 + 0.666260 + 0.666260 + 0.666260 + 0.666260 + 0.666260 + 0.666260 + 0.666260 + 0.666260 + 0.666260 + 0.666260 + 0.666260 + 0.666260 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666504 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666748 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.666992 + 0.667236 + 0.667236 + 0.667236 + 0.667236 + 0.667236 + 0.667236 + 0.667236 + 0.667236 + 0.667236 + 0.667236 + 0.667236 + 0.667236 + 0.667236 + 0.667236 + 0.667236 + 0.667236 + 0.667236 + 0.667236 + 0.667236 + 0.667236 + 0.667236 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667480 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667725 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.667969 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668213 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668457 + 0.668701 + 0.668701 + 0.668701 + 0.668701 + 0.668701 + 0.668701 + 0.668701 + 0.668701 + 0.668701 + 0.668701 + 0.668701 + 0.668701 + 0.668701 + 0.668701 + 0.668701 + 0.668701 + 0.668701 + 0.668701 + 0.668701 + 0.668701 + 0.668701 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.668945 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669189 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669434 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669678 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.669922 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670166 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670410 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670654 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.670898 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671143 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671387 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671631 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.671875 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672119 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672363 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672607 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.672852 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673096 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673340 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673584 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.673828 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674072 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674316 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674561 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.674805 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675049 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675293 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675537 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.675781 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676025 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676270 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676514 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.676758 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677002 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677246 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677490 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677734 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.677979 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678223 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678467 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678711 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.678955 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679199 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679443 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679688 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.679932 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680176 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680420 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680664 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.680908 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681152 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681396 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681641 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.681885 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682129 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682373 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682617 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.682861 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683105 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683350 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683594 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.683838 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684082 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684326 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684570 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.684814 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685059 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685303 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685547 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.685791 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686035 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686279 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686523 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.686768 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687012 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687256 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687500 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687744 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.687988 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688232 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688477 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688721 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.688965 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689209 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689453 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689697 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.689941 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690186 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690430 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690674 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.690918 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691162 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691406 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691650 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.691895 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692139 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692383 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692627 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.692871 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693115 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693359 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693604 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.693848 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694092 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694336 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694580 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.694824 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695068 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695312 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695557 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.695801 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696045 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696289 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696533 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.696777 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697021 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697266 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697510 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697754 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.697998 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698242 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698486 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698730 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.698975 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699219 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699463 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699707 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.699951 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700195 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700439 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700684 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.700928 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701172 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701416 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701660 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.701904 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702148 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702393 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702637 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.702881 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703125 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703369 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703613 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.703857 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704102 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704346 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704590 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.704834 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705078 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705322 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705566 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.705811 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706055 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706299 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706543 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.706787 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707031 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707275 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707520 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.707764 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708008 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708252 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708496 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708740 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.708984 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709229 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709473 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709717 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.709961 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710205 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710449 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710693 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.710938 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711182 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711426 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711670 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.711914 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712158 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712402 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712646 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.712891 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713135 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713379 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713623 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.713867 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714111 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714355 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714600 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.714844 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715088 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715332 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715576 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.715820 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716064 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716309 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716553 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.716797 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717041 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717285 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717529 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.717773 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718018 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718262 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718506 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718750 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.718994 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719238 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719482 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719727 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.719971 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720215 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720459 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720703 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.720947 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721191 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721436 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721680 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.721924 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722168 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722412 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722656 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.722900 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723145 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723389 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723633 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.723877 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724121 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724365 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724609 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.724854 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725098 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725342 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725586 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.725830 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726074 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726318 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726562 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.726807 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727051 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727295 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727539 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.727783 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728027 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728271 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728516 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.728760 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729004 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729248 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729492 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729736 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.729980 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730225 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730469 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730713 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.730957 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731201 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731445 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731689 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.731934 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732178 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732422 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732666 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.732910 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733154 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733398 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733643 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.733887 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734131 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734375 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734619 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.734863 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735107 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735352 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735596 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.735840 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736084 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736328 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736572 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.736816 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737061 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737305 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737549 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.737793 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738037 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738281 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738525 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.738770 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739014 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739258 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739502 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739746 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.739990 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740234 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740479 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740723 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.740967 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741211 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741455 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741699 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.741943 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742188 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742432 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742676 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.742920 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743164 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743408 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743652 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.743896 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744141 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744385 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744629 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.744873 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745117 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745361 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745605 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.745850 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746094 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746338 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746582 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.746826 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747070 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747314 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747559 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.747803 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748047 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748291 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748535 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.748779 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749023 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749268 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749512 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.749756 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750000 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750244 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750488 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750732 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.750977 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751221 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751465 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751709 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.751953 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752197 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752441 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752686 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.752930 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753174 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753418 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753662 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.753906 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754150 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754395 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754639 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.754883 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755127 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755371 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755615 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.755859 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756104 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756348 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756592 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.756836 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757080 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757324 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757568 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.757812 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758057 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758301 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758545 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.758789 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759033 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759277 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759521 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.759766 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760010 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760254 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760498 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760742 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.760986 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761230 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761475 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761719 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.761963 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762207 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762451 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762695 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.762939 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763184 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763428 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763672 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.763916 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764160 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764404 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764648 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.764893 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765137 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765381 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765625 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.765869 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766113 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766357 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766602 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.766846 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767090 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767334 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767578 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.767822 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768066 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768311 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768555 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.768799 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769043 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769287 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769531 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.769775 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770020 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770264 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770508 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770752 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.770996 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771240 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771484 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771729 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.771973 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772217 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772461 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772705 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.772949 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773193 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773438 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773682 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.773926 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774170 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774414 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774658 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.774902 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775146 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775391 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775635 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.775879 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776123 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776367 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776611 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.776855 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777100 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777344 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777588 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.777832 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778076 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778320 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778564 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.778809 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779053 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779297 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779541 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.779785 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780029 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780273 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780518 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.780762 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781006 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781250 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781494 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781738 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.781982 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782227 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782471 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782715 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.782959 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783203 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783447 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783691 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.783936 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784180 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784424 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784668 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.784912 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785156 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785400 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785645 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.785889 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786133 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786377 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786621 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.786865 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787109 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787354 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787598 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.787842 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788086 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788330 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788574 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.788818 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789062 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789307 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789551 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.789795 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790039 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790283 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790527 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.790771 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791016 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791260 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791504 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791748 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.791992 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792236 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792480 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792725 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.792969 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793213 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793457 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793701 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.793945 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794189 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794434 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794678 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.794922 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795166 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795410 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795654 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.795898 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796143 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796387 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796631 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.796875 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797119 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797363 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797607 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.797852 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798096 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798340 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798584 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.798828 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799072 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799316 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799561 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.799805 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800049 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800293 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800537 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.800781 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801025 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801270 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801514 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.801758 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802002 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802246 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802490 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802734 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.802979 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803223 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803467 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803711 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.803955 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804199 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804443 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804688 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.804932 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805176 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805420 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805664 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.805908 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806152 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806396 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806641 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.806885 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807129 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807373 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807617 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.807861 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808105 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808350 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808594 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.808838 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809082 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809326 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809570 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.809814 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810059 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810303 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810547 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.810791 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811035 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811279 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811523 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.811768 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812012 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812256 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812500 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812744 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.812988 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813232 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813477 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813721 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.813965 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814209 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814453 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814697 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.814941 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815186 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815430 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815674 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.815918 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816162 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816406 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816650 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.816895 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817139 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817383 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817627 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.817871 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818115 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818359 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818604 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.818848 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819092 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819336 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819580 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.819824 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820068 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820312 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820557 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.820801 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821045 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821289 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821533 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.821777 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822021 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822266 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822510 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822754 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.822998 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823242 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823486 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823730 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.823975 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824219 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824463 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824707 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.824951 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825195 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825439 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825684 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.825928 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826172 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826416 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826660 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.826904 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827148 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827393 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827637 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.827881 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828125 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828369 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828613 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.828857 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829102 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829346 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829590 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.829834 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830078 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830322 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830566 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.830811 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831055 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831299 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831543 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.831787 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832031 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832275 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832520 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.832764 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833008 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833252 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833496 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833740 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.833984 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834229 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834473 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834717 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.834961 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835205 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835449 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835693 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.835938 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836182 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836426 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836670 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.836914 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837158 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837402 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837646 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.837891 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838135 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838379 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838623 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.838867 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839111 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839355 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839600 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.839844 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840088 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840332 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840576 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.840820 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841064 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841309 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841553 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.841797 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842041 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842285 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842529 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.842773 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843018 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843262 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843506 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843750 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.843994 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844238 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844482 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844727 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.844971 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845215 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845459 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845703 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.845947 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846191 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846436 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846680 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.846924 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847168 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847412 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847656 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.847900 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848145 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848389 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848633 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.848877 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849121 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849365 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849609 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.849854 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850098 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850342 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850586 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.850830 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851074 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851318 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851562 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.851807 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852051 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852295 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852539 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.852783 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853027 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853271 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853516 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.853760 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854004 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854248 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854492 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854736 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.854980 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855225 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855469 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855713 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.855957 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856201 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856445 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856689 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.856934 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857178 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857422 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857666 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.857910 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858154 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858398 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858643 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.858887 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859131 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859375 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859619 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.859863 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860107 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860352 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860596 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.860840 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861084 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861328 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861572 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.861816 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862061 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862305 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862549 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.862793 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863037 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863281 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863525 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.863770 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864014 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864258 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864502 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864746 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.864990 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865234 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865479 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865723 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.865967 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866211 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866455 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866699 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.866943 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867188 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867432 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867676 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.867920 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868164 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868408 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868652 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.868896 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869141 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869385 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869629 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.869873 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870117 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870361 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870605 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.870850 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871094 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871338 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871582 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.871826 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872070 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872314 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872559 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.872803 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873047 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873291 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873535 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.873779 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874023 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874268 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874512 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.874756 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875000 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875244 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875488 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875732 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.875977 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876221 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876465 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876709 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.876953 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877197 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877441 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877686 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.877930 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878174 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878418 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878662 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.878906 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879150 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879395 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879639 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.879883 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880127 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880371 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880615 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.880859 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881104 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881348 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881592 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.881836 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882080 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882324 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882568 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.882812 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883057 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883301 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883545 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.883789 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884033 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884277 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884521 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.884766 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885010 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885254 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885498 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885742 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.885986 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886230 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886475 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886719 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.886963 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887207 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887451 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887695 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.887939 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888184 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888428 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888672 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.888916 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889160 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889404 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889648 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.889893 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890137 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890381 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890625 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.890869 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891113 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891357 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891602 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.891846 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892090 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892334 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892578 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.892822 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893066 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893311 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893555 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.893799 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894043 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894287 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894531 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.894775 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895020 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895264 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895508 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895752 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.895996 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896240 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896484 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896729 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.896973 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897217 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897461 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897705 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.897949 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898193 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898438 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898682 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.898926 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899170 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899414 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899658 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.899902 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900146 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900391 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900635 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.900879 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901123 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901367 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901611 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.901855 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902100 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902344 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902588 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.902832 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903076 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903320 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903564 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.903809 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904053 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904297 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904541 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.904785 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905029 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905273 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905518 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.905762 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906006 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906250 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906494 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906738 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.906982 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907227 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907471 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907715 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.907959 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908203 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908447 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908691 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.908936 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909180 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909424 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909668 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.909912 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910156 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910400 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910645 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.910889 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911133 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911377 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911621 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.911865 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912109 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912354 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912598 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.912842 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913086 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913330 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913574 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.913818 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914062 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914307 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914551 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.914795 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915039 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915283 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915527 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.915771 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916016 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916260 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916504 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916748 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.916992 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917236 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917480 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917725 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.917969 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918213 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918457 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918701 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.918945 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919189 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919434 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919678 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.919922 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920166 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920410 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920654 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.920898 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921143 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921387 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921631 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.921875 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922119 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922363 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922607 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.922852 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923096 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923340 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923584 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.923828 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924072 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924316 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924561 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.924805 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925049 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925293 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925537 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.925781 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926025 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926270 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926514 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.926758 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927002 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927246 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927490 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927734 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.927979 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928223 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928467 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928711 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.928955 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929199 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929443 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929688 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.929932 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930176 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930420 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930664 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.930908 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931152 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931396 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931641 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.931885 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932129 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932373 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932617 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.932861 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933105 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933350 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933594 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.933838 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934082 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934326 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934570 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.934814 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935059 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935303 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935547 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.935791 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936035 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936279 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936523 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.936768 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937012 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937256 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937500 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937744 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.937988 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938232 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938477 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938721 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.938965 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939209 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939453 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939697 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.939941 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940186 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940430 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940674 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.940918 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941162 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941406 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941650 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.941895 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942139 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942383 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942627 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.942871 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943115 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943359 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943604 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.943848 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944092 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944336 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944580 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.944824 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945068 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945312 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945557 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.945801 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946045 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946289 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946533 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.946777 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947021 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947266 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947510 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947754 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.947998 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948242 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948486 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948730 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.948975 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949219 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949463 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949707 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.949951 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950195 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950439 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950684 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.950928 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951172 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951416 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951660 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.951904 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952148 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952393 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952637 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.952881 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953125 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953369 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953613 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.953857 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954102 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954346 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954590 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.954834 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955078 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955322 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955566 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.955811 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956055 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956299 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956543 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.956787 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957031 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957275 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957520 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.957764 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958008 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958252 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958496 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958740 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.958984 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959229 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959473 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959717 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.959961 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960205 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960449 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960693 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.960938 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961182 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961426 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961670 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.961914 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962158 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962402 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962646 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.962891 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963135 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963379 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963623 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.963867 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964111 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964355 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964600 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.964844 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965088 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965332 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965576 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.965820 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966064 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966309 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966553 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.966797 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967041 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967285 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967529 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.967773 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968018 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968262 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968506 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968750 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.968994 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969238 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969482 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969727 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.969971 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970215 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970459 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970703 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.970947 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971191 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971436 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971680 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.971924 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972168 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972412 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972656 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.972900 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973145 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973389 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973633 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.973877 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974121 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974365 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974609 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.974854 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975098 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975342 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975586 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.975830 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976074 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976318 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976562 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.976807 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977051 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977295 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977539 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.977783 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978027 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978271 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978516 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.978760 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979004 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979248 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979492 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979736 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.979980 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980225 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980469 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980713 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.980957 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981201 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981445 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981689 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.981934 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982178 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982422 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982666 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.982910 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983154 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983398 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983643 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.983887 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984131 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984375 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984619 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.984863 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985107 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985352 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985596 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.985840 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986084 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986328 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986572 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.986816 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987061 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987305 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987549 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.987793 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988037 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988281 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988525 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.988770 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989014 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989258 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989502 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989746 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.989990 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990234 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990479 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990723 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.990967 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991211 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991455 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991699 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.991943 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992188 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992432 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992676 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.992920 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993164 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993408 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993652 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.993896 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994141 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994385 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994629 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.994873 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995117 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995361 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995605 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.995850 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996094 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996338 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996582 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.996826 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997070 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997314 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997559 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.997803 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998047 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998291 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998535 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.998779 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999023 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999268 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999512 + 0.999756 +} From 6acb586c95885a8fe1edfc2118e9142521de9614 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Thu, 30 Aug 2012 20:45:01 +0000 Subject: [PATCH 099/160] Cycles / Brick Texture: * Added GLSL stub for the Brick texture, fixes an error in the console when switching to Material Shading in the 3D View. --- source/blender/gpu/shaders/gpu_shader_material.glsl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index fb248f1b016..81c3cab97d4 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -2114,6 +2114,12 @@ void node_tex_checker(vec3 co, vec4 color1, vec4 color2, float scale, out vec4 c fac = 1.0; } +void node_tex_brick(vec3 co, vec4 color1, vec4 color2, vec4 mortar, float scale, float mortar_size, float bias, float brick_width, float row_height, out vec4 color, out float fac) +{ + color = vec4(1.0); + fac = 1.0; +} + void node_tex_clouds(vec3 co, float size, out vec4 color, out float fac) { color = vec4(1.0); From 86ff6cc346dd89b087de62a55598f5fead17fdd1 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 3 Sep 2012 10:08:55 +0000 Subject: [PATCH 100/160] Color Management: fix compilation error when OCIO is disabled --- source/blender/imbuf/intern/colormanagement.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 36b58031537..a9962cee4d8 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1331,6 +1331,7 @@ unsigned char *IMB_display_buffer_acquire_ctx(const bContext *C, ImBuf *ibuf, vo void IMB_display_buffer_pixel(float result[4], const float pixel[4], const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { +#ifdef WITH_OCIO ConstProcessorRcPtr *processor; const float gamma = view_settings->gamma; const float exposure = view_settings->exposure; @@ -1343,6 +1344,12 @@ void IMB_display_buffer_pixel(float result[4], const float pixel[4], const Colo if (processor) OCIO_processorApplyRGBA(processor, result); +#else + (void) view_settings; + (void) display_settings; + + copy_v4_v4(result, pixel); +#endif } void IMB_display_buffer_to_imbuf_rect(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, From e15f352831b9cc9fa1a85a0cdadf6d4b4b1f8731 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 4 Sep 2012 09:06:37 +0000 Subject: [PATCH 101/160] Merging r50265 through r50373 from trunk into soc-2011-tomato --- .../scons/config/win32-mingw-config.py | 2 +- .../scons/config/win64-mingw-config.py | 2 +- doc/python_api/sphinx_doc_gen.py | 2 +- intern/cycles/CMakeLists.txt | 4 +- intern/cycles/app/cycles_xml.cpp | 2 + intern/cycles/blender/addon/ui.py | 3 + intern/cycles/blender/blender_object.cpp | 13 +- intern/cycles/blender/blender_particles.cpp | 129 +++-- intern/cycles/blender/blender_shader.cpp | 2 + intern/cycles/blender/blender_sync.cpp | 9 + intern/cycles/blender/blender_sync.h | 6 +- intern/cycles/blender/blender_util.h | 16 + intern/cycles/cmake/external_libs.cmake | 2 +- intern/cycles/kernel/kernel_accumulate.h | 4 + intern/cycles/kernel/kernel_object.h | 43 +- intern/cycles/kernel/kernel_path.h | 17 +- intern/cycles/kernel/kernel_shader.h | 161 ++++-- intern/cycles/kernel/kernel_triangle.h | 2 + intern/cycles/kernel/kernel_types.h | 5 +- intern/cycles/kernel/osl/CMakeLists.txt | 4 + intern/cycles/kernel/osl/nodes/CMakeLists.txt | 9 +- .../kernel/osl/nodes/node_brightness.osl | 11 +- .../kernel/osl/nodes/node_checker_texture.osl | 4 +- .../kernel/osl/nodes/node_combine_rgb.osl | 29 + intern/cycles/kernel/osl/nodes/node_gamma.osl | 10 +- .../kernel/osl/nodes/node_glass_bsdf.osl | 4 +- .../kernel/osl/nodes/node_glossy_bsdf.osl | 4 +- .../cycles/kernel/osl/nodes/node_invert.osl | 2 +- intern/cycles/kernel/osl/nodes/node_math.osl | 4 + intern/cycles/kernel/osl/nodes/node_mix.osl | 15 + .../kernel/osl/nodes/node_noise_texture.osl | 2 +- .../cycles/kernel/osl/nodes/node_normal.osl | 7 +- ..._sepcomb_rgb.osl => node_separate_rgb.osl} | 16 +- intern/cycles/kernel/osl/nodes/node_texture.h | 29 +- .../kernel/osl/nodes/node_velvet_bsdf.osl | 2 +- .../kernel/osl/nodes/node_wave_texture.osl | 4 +- intern/cycles/kernel/osl/nodes/oslutil.h | 91 +++ intern/cycles/kernel/osl/nodes/stdosl.h | 532 ++++++++++-------- intern/cycles/kernel/osl/osl_globals.h | 5 +- intern/cycles/kernel/osl/osl_services.cpp | 145 +---- intern/cycles/kernel/osl/osl_services.h | 39 +- intern/cycles/kernel/osl/osl_shader.cpp | 81 ++- intern/cycles/kernel/svm/svm_geometry.h | 38 +- intern/cycles/kernel/svm/svm_math.h | 2 + intern/cycles/kernel/svm/svm_mix.h | 12 + intern/cycles/kernel/svm/svm_tex_coord.h | 2 +- intern/cycles/kernel/svm/svm_types.h | 13 +- intern/cycles/render/CMakeLists.txt | 2 + intern/cycles/render/graph.cpp | 10 +- intern/cycles/render/graph.h | 13 + intern/cycles/render/light.cpp | 6 +- intern/cycles/render/nodes.cpp | 72 ++- intern/cycles/render/nodes.h | 4 + intern/cycles/render/object.cpp | 40 -- intern/cycles/render/object.h | 8 - intern/cycles/render/osl.cpp | 3 +- intern/cycles/render/particles.cpp | 123 ++++ intern/cycles/render/particles.h | 74 +++ intern/cycles/render/scene.cpp | 15 +- intern/cycles/render/scene.h | 4 + intern/ghost/intern/GHOST_DropTargetWin32.cpp | 4 - intern/ghost/intern/GHOST_SystemWin32.cpp | 2 +- intern/ghost/intern/GHOST_WindowWin32.cpp | 12 +- intern/guardedalloc/intern/mmap_win.c | 2 +- intern/opennl/intern/opennl.c | 2 + .../bl_operators/object_quick_effects.py | 2 +- source/blender/blenfont/intern/blf_dir.c | 2 - source/blender/blenkernel/BKE_DerivedMesh.h | 1 + source/blender/blenkernel/BKE_anim.h | 1 - source/blender/blenkernel/BKE_utildefines.h | 50 +- .../blender/blenkernel/intern/DerivedMesh.c | 21 + source/blender/blenkernel/intern/anim.c | 50 +- source/blender/blenkernel/intern/anim_sys.c | 37 +- source/blender/blenkernel/intern/armature.c | 27 +- source/blender/blenkernel/intern/blender.c | 3 - .../blender/blenkernel/intern/cdderivedmesh.c | 1 - source/blender/blenkernel/intern/constraint.c | 2 +- source/blender/blenkernel/intern/customdata.c | 1 - .../blenkernel/intern/customdata_file.c | 34 +- source/blender/blenkernel/intern/depsgraph.c | 1 - source/blender/blenkernel/intern/fcurve.c | 1 - source/blender/blenkernel/intern/font.c | 1 - source/blender/blenkernel/intern/idprop.c | 12 - source/blender/blenkernel/intern/image.c | 1 - source/blender/blenkernel/intern/library.c | 1 - .../blender/blenkernel/intern/mask_evaluate.c | 1 - source/blender/blenkernel/intern/mball.c | 2 +- source/blender/blenkernel/intern/movieclip.c | 1 - source/blender/blenkernel/intern/node.c | 2 - source/blender/blenkernel/intern/ocean.c | 2 - source/blender/blenkernel/intern/packedFile.c | 1 - source/blender/blenkernel/intern/pointcache.c | 1 - source/blender/blenkernel/intern/sca.c | 1 - source/blender/blenkernel/intern/seqeffects.c | 1 - .../blender/blenkernel/intern/seqmodifier.c | 1 - source/blender/blenkernel/intern/sequencer.c | 1 - source/blender/blenkernel/intern/sound.c | 1 - source/blender/blenkernel/intern/texture.c | 1 - source/blender/blenkernel/intern/tracking.c | 2 + source/blender/blenlib/BLI_endian_switch.h | 42 ++ .../blenlib/BLI_endian_switch_inline.h | 116 ++++ source/blender/blenlib/BLI_fileops.h | 7 + source/blender/blenlib/BLI_path_util.h | 8 + source/blender/blenlib/BLI_utildefines.h | 24 - source/blender/blenlib/CMakeLists.txt | 3 + source/blender/blenlib/intern/BLI_memarena.c | 4 +- source/blender/blenlib/intern/BLI_mempool.c | 2 +- source/blender/blenlib/intern/bpath.c | 1 - source/blender/blenlib/intern/endian_switch.c | 118 ++++ source/blender/blenlib/intern/fileops.c | 2 - source/blender/blenlib/intern/path_util.c | 1 - source/blender/blenlib/intern/storage.c | 7 +- source/blender/blenlib/intern/winstuff.c | 2 +- source/blender/blenloader/BLO_blend_defs.h | 47 ++ source/blender/blenloader/CMakeLists.txt | 1 + .../blender/blenloader/intern/readblenentry.c | 5 +- source/blender/blenloader/intern/readfile.c | 129 ++--- source/blender/blenloader/intern/runtime.c | 1 - .../blenloader/intern/versioning_250.c | 1 - .../blenloader/intern/versioning_legacy.c | 1 - source/blender/blenloader/intern/writefile.c | 2 +- source/blender/bmesh/intern/bmesh_marking.c | 9 +- source/blender/bmesh/intern/bmesh_marking.h | 2 +- source/blender/bmesh/intern/bmesh_polygon.c | 8 +- source/blender/bmesh/operators/bmo_extrude.c | 2 +- source/blender/bmesh/operators/bmo_inset.c | 3 +- source/blender/bmesh/tools/BME_bevel.c | 1 - source/blender/collada/AnimationImporter.cpp | 7 +- source/blender/collada/DocumentExporter.cpp | 1 - source/blender/collada/DocumentImporter.cpp | 12 +- source/blender/collada/ImageExporter.cpp | 1 - source/blender/collada/MeshImporter.cpp | 2 +- .../compositor/intern/COM_WorkScheduler.cpp | 145 +++-- .../compositor/intern/COM_WorkScheduler.h | 4 +- .../compositor/intern/COM_compositor.cpp | 20 +- .../compositor/nodes/COM_MovieClipNode.cpp | 11 +- .../compositor/nodes/COM_OutputFileNode.cpp | 2 +- .../operations/COM_AntiAliasOperation.cpp | 1 - .../operations/COM_MovieClipOperation.cpp | 10 +- .../operations/COM_OutputFileOperation.h | 3 +- .../editors/animation/anim_channels_defines.c | 1 - source/blender/editors/animation/anim_deps.c | 1 - .../blender/editors/animation/anim_filter.c | 1 - .../editors/animation/keyframes_general.c | 1 - source/blender/editors/include/ED_mesh.h | 2 +- source/blender/editors/include/UI_interface.h | 10 +- source/blender/editors/include/UI_view2d.h | 2 +- source/blender/editors/interface/interface.c | 19 +- .../editors/interface/interface_handlers.c | 38 +- .../editors/interface/interface_icons.c | 1 - .../editors/interface/interface_intern.h | 8 + .../editors/interface/interface_regions.c | 33 +- .../editors/interface/interface_style.c | 2 +- .../editors/interface/interface_templates.c | 8 + .../editors/interface/interface_widgets.c | 5 +- source/blender/editors/mesh/editmesh_knife.c | 245 +++++--- source/blender/editors/mesh/editmesh_select.c | 2 +- source/blender/editors/mesh/editmesh_utils.c | 7 +- source/blender/editors/mesh/mesh_data.c | 2 +- source/blender/editors/mesh/mesh_navmesh.c | 2 +- source/blender/editors/object/object_vgroup.c | 21 +- .../editors/sculpt_paint/paint_image.c | 21 +- .../blender/editors/sculpt_paint/paint_ops.c | 8 +- .../blender/editors/space_image/space_image.c | 9 +- .../editors/space_view3d/drawarmature.c | 21 +- .../blender/editors/space_view3d/drawmesh.c | 11 +- .../blender/editors/space_view3d/drawobject.c | 16 +- .../editors/space_view3d/view3d_draw.c | 5 +- .../editors/space_view3d/view3d_intern.h | 2 +- .../editors/space_view3d/view3d_select.c | 1 + source/blender/editors/transform/transform.c | 78 ++- source/blender/editors/transform/transform.h | 2 + .../editors/transform/transform_conversions.c | 2 +- .../editors/transform/transform_snap.c | 3 +- source/blender/editors/util/ed_util.c | 6 +- source/blender/editors/uvedit/uvedit_draw.c | 6 +- source/blender/editors/uvedit/uvedit_ops.c | 11 +- .../editors/uvedit/uvedit_unwrap_ops.c | 14 +- source/blender/gpu/GPU_buffers.h | 12 +- source/blender/gpu/GPU_draw.h | 2 +- source/blender/gpu/GPU_extensions.h | 2 +- source/blender/gpu/GPU_material.h | 2 +- source/blender/gpu/intern/gpu_codegen.c | 6 +- source/blender/gpu/intern/gpu_codegen.h | 2 + source/blender/gpu/intern/gpu_draw.c | 6 +- source/blender/gpu/intern/gpu_extensions.c | 4 +- source/blender/gpu/intern/gpu_material.c | 25 +- .../blender/ikplugin/intern/itasc_plugin.cpp | 1 - source/blender/imbuf/IMB_imbuf.h | 4 +- source/blender/imbuf/intern/IMB_indexer.h | 1 - source/blender/imbuf/intern/bmp.c | 2 +- source/blender/imbuf/intern/indexer.c | 19 +- source/blender/imbuf/intern/indexer_dv.c | 5 +- source/blender/imbuf/intern/thumbs.c | 2 - source/blender/imbuf/intern/thumbs_blend.c | 14 +- source/blender/imbuf/intern/util.c | 23 +- source/blender/makesdna/DNA_ipo_types.h | 4 +- source/blender/makesdna/DNA_sdna_types.h | 7 +- source/blender/makesrna/intern/makesrna.c | 6 +- source/blender/makesrna/intern/rna_armature.c | 14 +- .../blender/makesrna/intern/rna_camera_api.c | 2 - source/blender/makesrna/intern/rna_fluidsim.c | 7 +- source/blender/makesrna/intern/rna_gpencil.c | 2 +- source/blender/makesrna/intern/rna_main.c | 5 +- source/blender/makesrna/intern/rna_main_api.c | 5 +- source/blender/makesrna/intern/rna_render.c | 4 +- .../blender/makesrna/intern/rna_scene_api.c | 4 +- source/blender/makesrna/intern/rna_space.c | 7 +- .../blender/makesrna/intern/rna_texture_api.c | 3 +- source/blender/makesrna/intern/rna_wm_api.c | 21 +- .../modifiers/intern/MOD_fluidsim_util.c | 1 - source/blender/modifiers/intern/MOD_mirror.c | 1 - source/blender/modifiers/intern/MOD_ocean.c | 1 - .../nodes/composite/node_composite_tree.c | 1 - .../nodes/node_composite_outputFile.c | 2 - source/blender/nodes/intern/node_common.c | 1 - .../blender/nodes/shader/node_shader_tree.c | 47 +- .../shader/nodes/node_shader_particle_info.c | 7 + .../nodes/node_shader_tex_environment.c | 4 +- .../shader/nodes/node_shader_tex_image.c | 4 +- .../nodes/shader/nodes/node_shader_texture.c | 2 +- .../blender/nodes/texture/node_texture_tree.c | 60 +- source/blender/python/generic/py_capi_utils.c | 9 + source/blender/quicktime/apple/qtkit_export.m | 51 +- .../render/extern/include/RE_render_ext.h | 2 +- .../render/intern/include/pixelshading.h | 6 +- .../blender/render/intern/source/pipeline.c | 1 - .../render/intern/source/render_result.c | 1 - .../render/intern/source/texture_ocean.c | 1 - source/blender/windowmanager/WM_keymap.h | 6 +- source/blender/windowmanager/WM_types.h | 1 - .../windowmanager/intern/wm_playanim.c | 1 - source/creator/CMakeLists.txt | 8 + source/creator/creator.c | 1 - .../BlenderRoutines/BL_KetsjiEmbedStart.cpp | 183 ++++-- .../Converter/KX_ConvertActuators.cpp | 3 +- .../gameengine/GamePlayer/ghost/GPG_ghost.cpp | 78 ++- source/gameengine/Ketsji/CMakeLists.txt | 2 + source/gameengine/Ketsji/KX_PythonInit.cpp | 20 +- source/gameengine/Ketsji/KX_PythonInit.h | 10 + source/gameengine/Ketsji/KX_PythonMain.cpp | 77 +++ source/gameengine/Ketsji/KX_PythonMain.h | 41 ++ 242 files changed, 2877 insertions(+), 1577 deletions(-) create mode 100644 intern/cycles/kernel/osl/nodes/node_combine_rgb.osl rename intern/cycles/kernel/osl/nodes/{node_sepcomb_rgb.osl => node_separate_rgb.osl} (82%) create mode 100644 intern/cycles/kernel/osl/nodes/oslutil.h create mode 100644 intern/cycles/render/particles.cpp create mode 100644 intern/cycles/render/particles.h create mode 100644 source/blender/blenlib/BLI_endian_switch.h create mode 100644 source/blender/blenlib/BLI_endian_switch_inline.h create mode 100644 source/blender/blenlib/intern/endian_switch.c create mode 100644 source/blender/blenloader/BLO_blend_defs.h create mode 100644 source/gameengine/Ketsji/KX_PythonMain.cpp create mode 100644 source/gameengine/Ketsji/KX_PythonMain.h diff --git a/build_files/scons/config/win32-mingw-config.py b/build_files/scons/config/win32-mingw-config.py index f61b128fe9f..95b2329f426 100644 --- a/build_files/scons/config/win32-mingw-config.py +++ b/build_files/scons/config/win32-mingw-config.py @@ -178,7 +178,7 @@ BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse'] #CUDA WITH_BF_CYCLES_CUDA_BINARIES = False #BF_CYCLES_CUDA_NVCC = "" # Path to the nvidia compiler -BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21'] # don't build sm_13 until the compile can fit in 32bit process again :) +BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30'] ## CC = 'gcc' diff --git a/build_files/scons/config/win64-mingw-config.py b/build_files/scons/config/win64-mingw-config.py index 6848d78d959..c2bf2df6d00 100644 --- a/build_files/scons/config/win64-mingw-config.py +++ b/build_files/scons/config/win64-mingw-config.py @@ -151,7 +151,7 @@ BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib' WITH_BF_CYCLES = True WITH_BF_CYCLES_CUDA_BINARIES = False BF_CYCLES_CUDA_NVCC = "" # Path to the NVIDIA CUDA compiler -BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21'] +BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30'] WITH_BF_OIIO = True BF_OIIO = LIBDIR + '/openimageio' diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 805954968b9..186f67b0df6 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -849,7 +849,7 @@ def pymodule2sphinx(basepath, module_name, module, title): elif value_type in (bool, int, float, str, tuple): # constant, not much fun we can do here except to list it. # TODO, figure out some way to document these! - #fw(".. data:: %s\n\n" % attribute) + fw(".. data:: %s\n\n" % attribute) write_indented_lines(" ", fw, "constant value %s" % repr(value), False) fw("\n") else: diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 697427081c3..337eebe4be0 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -20,8 +20,8 @@ elseif(CMAKE_COMPILER_IS_GNUCC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math") endif() -# for OSL, not needed yet -# set(RTTI_DISABLE_FLAGS "-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID") +# for OSL +set(RTTI_DISABLE_FLAGS "-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID") # set(RTTI_DISABLE_FLAGS "/GR- -DBOOST_NO_RTTI -DBOOST_NO_TYPEID") # Definitions and Includes diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 922a96dc4df..87a238e508c 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -487,6 +487,7 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug else if(string_iequals(node.name(), "mix")) { MixNode *mix = new MixNode(); xml_read_enum(&mix->type, MixNode::type_enum, node, "type"); + xml_read_bool(&mix->use_clamp, node, "use_clamp"); snode = mix; } else if(string_iequals(node.name(), "gamma")) { @@ -518,6 +519,7 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug else if(string_iequals(node.name(), "math")) { MathNode *math = new MathNode(); xml_read_enum(&math->type, MathNode::type_enum, node, "type"); + xml_read_bool(&math->use_clamp, node, "use_clamp"); snode = math; } else if(string_iequals(node.name(), "vector_math")) { diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 561ccbbe3d1..885b488a3ea 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -927,6 +927,9 @@ def draw_device(self, context): layout.prop(cscene, "device") elif device_type == 'OPENCL' and cscene.feature_set == 'EXPERIMENTAL': layout.prop(cscene, "device") + + if cscene.feature_set == 'EXPERIMENTAL' and cscene.device == 'CPU' and engine.with_osl(): + layout.prop(cscene, "shading_system") def draw_pause(self, context): diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 813314f67a6..fd9f836eec0 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -247,11 +247,10 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, scene->object_manager->tag_update(scene); } - /* updated dupli objects require particle sync */ - bool need_particle_update = object_need_particle_update(b_ob); - /* object sync */ - if(object_updated || (object->mesh && object->mesh->need_update) || need_particle_update) { + /* transform comparison should not be needed, but duplis don't work perfect + * in the depsgraph and may not signal changes, so this is a workaround */ + if(object_updated || (object->mesh && object->mesh->need_update) || tfm != object->tfm) { object->name = b_ob.name().c_str(); object->pass_id = b_ob.pass_index(); object->tfm = tfm; @@ -277,10 +276,6 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, object->particle_id = particle_id; - /* particle sync */ - if (need_particle_update) - sync_particles(object, b_ob); - object->tag_update(scene); } } @@ -303,7 +298,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) /* object loop */ BL::Scene::objects_iterator b_ob; BL::Scene b_sce = b_scene; - int particle_offset = 0; + int particle_offset = 1; /* first particle is dummy for regular, non-instanced objects */ bool cancel = false; diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp index e32c80a51b5..177912cd8f0 100644 --- a/intern/cycles/blender/blender_particles.cpp +++ b/intern/cycles/blender/blender_particles.cpp @@ -16,9 +16,9 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "object.h" - #include "mesh.h" +#include "particles.h" + #include "blender_sync.h" #include "blender_util.h" @@ -31,7 +31,7 @@ CCL_NAMESPACE_BEGIN /* Particles Sync */ -bool BlenderSync::object_need_particle_update(BL::Object b_ob) +bool BlenderSync::psys_need_update(BL::ParticleSystem b_psys) { /* Particle data is only needed for * a) Billboard render mode if object's own material uses particle info @@ -41,9 +41,7 @@ bool BlenderSync::object_need_particle_update(BL::Object b_ob) */ bool need_update = false; - BL::Object::particle_systems_iterator b_psys; - for (b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) { - switch (b_psys->settings().render_type()) { + switch (b_psys.settings().render_type()) { /* XXX not implemented yet! * billboards/strands would become part of the mesh data (?), * so the mesh attributes would store whether particle info is required. @@ -61,7 +59,7 @@ bool BlenderSync::object_need_particle_update(BL::Object b_ob) #endif case BL::ParticleSettings::render_type_OBJECT: { - BL::Object b_dupli_ob = b_psys->settings().dupli_object(); + BL::Object b_dupli_ob = b_psys.settings().dupli_object(); if (b_dupli_ob) { BL::ID key = (BKE_object_is_modified(b_dupli_ob))? b_dupli_ob: b_dupli_ob.data(); Mesh *mesh = mesh_map.find(key); @@ -73,7 +71,7 @@ bool BlenderSync::object_need_particle_update(BL::Object b_ob) } case BL::ParticleSettings::render_type_GROUP: { - BL::Group b_dupli_group = b_psys->settings().dupli_group(); + BL::Group b_dupli_group = b_psys.settings().dupli_group(); if (b_dupli_group) { BL::Group::objects_iterator b_gob; for (b_dupli_group.objects.begin(b_gob); b_gob != b_dupli_group.objects.end(); ++b_gob) { @@ -90,7 +88,6 @@ bool BlenderSync::object_need_particle_update(BL::Object b_ob) default: /* avoid compiler warning */ break; - } } return need_update; @@ -114,7 +111,19 @@ static bool use_particle_system(BL::ParticleSystem b_psys) static bool use_particle(BL::Particle b_pa) { - return b_pa.is_exist() && b_pa.is_visible() && b_pa.alive_state()==BL::Particle::alive_state_ALIVE; + return b_pa.is_exist() && b_pa.is_visible() && + (b_pa.alive_state()==BL::Particle::alive_state_ALIVE || b_pa.alive_state()==BL::Particle::alive_state_DYING); +} + +static int psys_count_particles(BL::ParticleSystem b_psys) +{ + int tot = 0; + BL::ParticleSystem::particles_iterator b_pa; + for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) { + if(use_particle(*b_pa)) + ++tot; + } + return tot; } int BlenderSync::object_count_particles(BL::Object b_ob) @@ -122,45 +131,89 @@ int BlenderSync::object_count_particles(BL::Object b_ob) int tot = 0; BL::Object::particle_systems_iterator b_psys; for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) { - if (use_particle_system(*b_psys)) { - BL::ParticleSystem::particles_iterator b_pa; - for(b_psys->particles.begin(b_pa); b_pa != b_psys->particles.end(); ++b_pa) { - if(use_particle(*b_pa)) - ++tot; - } - } + if (use_particle_system(*b_psys)) + tot += psys_count_particles(*b_psys); } return tot; } -void BlenderSync::sync_particles(Object *ob, BL::Object b_ob) +void BlenderSync::sync_particles(BL::Object b_ob, BL::ParticleSystem b_psys) { - int tot = object_count_particles(b_ob); + /* depending on settings the psys may not even be rendered */ + if (!use_particle_system(b_psys)) + return; - ob->particles.clear(); - ob->particles.reserve(tot); + /* key to lookup particle system */ + ParticleSystemKey key(b_ob, b_psys); + ParticleSystem *psys; - int index; - BL::Object::particle_systems_iterator b_psys; - for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) { - if (use_particle_system(*b_psys)) { - int pa_index = 0; - BL::ParticleSystem::particles_iterator b_pa; - for(b_psys->particles.begin(b_pa), index = 0; b_pa != b_psys->particles.end(); ++b_pa, ++index) { - if(use_particle(*b_pa)) { - Particle pa; - - pa.index = pa_index; - pa.age = b_scene.frame_current() - b_pa->birth_time(); - pa.lifetime = b_pa->lifetime(); - - ob->particles.push_back(pa); - } + /* test if we need to sync */ + bool object_updated = false; + + if(particle_system_map.sync(&psys, b_ob, b_ob, key)) + object_updated = true; + + bool need_update = psys_need_update(b_psys); + + if (object_updated || need_update) { + int tot = psys_count_particles(b_psys); + psys->particles.clear(); + psys->particles.reserve(tot); + + int index = 0; + BL::ParticleSystem::particles_iterator b_pa; + for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) { + if(use_particle(*b_pa)) { + Particle pa; - ++pa_index; + pa.index = index; + pa.age = b_scene.frame_current() - b_pa->birth_time(); + pa.lifetime = b_pa->lifetime(); + pa.location = get_float3(b_pa->location()); + pa.rotation = get_float4(b_pa->rotation()); + pa.size = b_pa->size(); + pa.velocity = get_float3(b_pa->velocity()); + pa.angular_velocity = get_float3(b_pa->angular_velocity()); + + psys->particles.push_back(pa); } + + ++index; } + + psys->tag_update(scene); } } +void BlenderSync::sync_particle_systems() +{ + /* layer data */ + uint scene_layer = render_layer.scene_layer; + + particle_system_map.pre_sync(); + + /* object loop */ + BL::Scene::objects_iterator b_ob; + BL::Scene b_sce = b_scene; + + for(; b_sce; b_sce = b_sce.background_set()) { + for(b_sce.objects.begin(b_ob); b_ob != b_sce.objects.end(); ++b_ob) { + bool hide = (render_layer.use_viewport_visibility)? b_ob->hide(): b_ob->hide_render(); + uint ob_layer = get_layer(b_ob->layers(), b_ob->layers_local_view(), object_is_light(*b_ob)); + CYCLES_LOCAL_LAYER_HACK(render_layer.use_localview, ob_layer); + hide = hide || !(ob_layer & scene_layer); + + if(!hide) { + BL::Object::particle_systems_iterator b_psys; + for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) + sync_particles(*b_ob, *b_psys); + } + } + } + + /* handle removed data and modified pointers */ + if(particle_system_map.post_sync()) + scene->particle_system_manager->tag_update(scene); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 2309cc6eb40..9758d9bf92a 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -221,6 +221,7 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph BL::ShaderNodeMixRGB b_mix_node(b_node); MixNode *mix = new MixNode(); mix->type = MixNode::type_enum[b_mix_node.blend_type()]; + mix->use_clamp = b_mix_node.use_clamp(); node = mix; break; } @@ -244,6 +245,7 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph BL::ShaderNodeMath b_math_node(b_node); MathNode *math = new MathNode(); math->type = MathNode::type_enum[b_math_node.operation()]; + math->use_clamp = b_math_node.use_clamp(); node = math; break; } diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index d35c93ccbd2..cb83309cc00 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -47,6 +47,7 @@ BlenderSync::BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL:: object_map(&scene_->objects), mesh_map(&scene_->meshes), light_map(&scene_->lights), + particle_system_map(&scene_->particle_systems), world_map(NULL), world_recalc(false), experimental(false), @@ -97,6 +98,12 @@ bool BlenderSync::sync_recalc() if(b_ob->is_updated_data() || b_ob->data().is_updated()) light_map.set_recalc(*b_ob); } + + if(b_ob->is_updated_data()) { + BL::Object::particle_systems_iterator b_psys; + for (b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) + particle_system_map.set_recalc(*b_ob); + } } BL::BlendData::meshes_iterator b_mesh; @@ -120,6 +127,7 @@ bool BlenderSync::sync_recalc() object_map.has_recalc() || light_map.has_recalc() || mesh_map.has_recalc() || + particle_system_map.has_recalc() || BlendDataObjects_is_updated_get(&b_data.ptr) || world_recalc; @@ -133,6 +141,7 @@ void BlenderSync::sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, const sync_film(); sync_shaders(); sync_objects(b_v3d); + sync_particle_systems(); sync_motion(b_v3d, b_override); } diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index ac1fed060ee..ac4cc37b74a 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -77,6 +77,7 @@ private: void sync_world(); void sync_render_layers(BL::SpaceView3D b_v3d, const char *layer); void sync_shaders(); + void sync_particle_systems(); void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree); Mesh *sync_mesh(BL::Object b_ob, bool object_updated); @@ -85,14 +86,14 @@ private: void sync_background_light(); void sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion); void sync_camera_motion(BL::Object b_ob, int motion); - void sync_particles(Object *ob, BL::Object b_ob); + void sync_particles(BL::Object b_ob, BL::ParticleSystem b_psys); /* util */ void find_shader(BL::ID id, vector& used_shaders, int default_shader); bool BKE_object_is_modified(BL::Object b_ob); bool object_is_mesh(BL::Object b_ob); bool object_is_light(BL::Object b_ob); - bool object_need_particle_update(BL::Object b_ob); + bool psys_need_update(BL::ParticleSystem b_psys); int object_count_particles(BL::Object b_ob); /* variables */ @@ -104,6 +105,7 @@ private: id_map object_map; id_map mesh_map; id_map light_map; + id_map particle_system_map; set mesh_synced; void *world_map; bool world_recalc; diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index b08c1e7e765..b0febcc23d4 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -149,6 +149,11 @@ static inline float3 get_float3(BL::Array array) return make_float3(array[0], array[1], array[2]); } +static inline float4 get_float4(BL::Array array) +{ + return make_float4(array[0], array[1], array[2], array[3]); +} + static inline int4 get_int4(BL::Array array) { return make_int4(array[0], array[1], array[2], array[3]); @@ -388,6 +393,17 @@ struct ObjectKey { { return (parent < k.parent || (parent == k.parent && (index < k.index || (index == k.index && ob < k.ob)))); } }; +struct ParticleSystemKey { + void *ob; + void *psys; + + ParticleSystemKey(void *ob_, void *psys_) + : ob(ob_), psys(psys_) {} + + bool operator<(const ParticleSystemKey& k) const + { return (ob < k.ob && psys < k.psys); } +}; + CCL_NAMESPACE_END #endif /* __BLENDER_UTIL_H__ */ diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake index 23a919530f9..4f547a5b644 100644 --- a/intern/cycles/cmake/external_libs.cmake +++ b/intern/cycles/cmake/external_libs.cmake @@ -22,7 +22,7 @@ endif() if(WITH_CYCLES_OSL) - set(CYCLES_OSL "" CACHE PATH "Path to OpenShadingLanguage installation") + set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation") message(STATUS "CYCLES_OSL = ${CYCLES_OSL}") diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index d99beb8905a..e73b2ba70b8 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -301,6 +301,10 @@ __device_inline float3 path_radiance_sum(KernelGlobals *kg, PathRadiance *L) __device_inline void path_radiance_clamp(PathRadiance *L, float3 *L_sum, float clamp) { + #ifdef WITH_OSL + using std::isfinite; + #endif + float sum = fabsf((*L_sum).x) + fabsf((*L_sum).y) + fabsf((*L_sum).z); if(!isfinite(sum)) { diff --git a/intern/cycles/kernel/kernel_object.h b/intern/cycles/kernel/kernel_object.h index 4ff315ca265..222ade504cc 100644 --- a/intern/cycles/kernel/kernel_object.h +++ b/intern/cycles/kernel/kernel_object.h @@ -172,24 +172,61 @@ __device int shader_pass_id(KernelGlobals *kg, ShaderData *sd) __device_inline float particle_index(KernelGlobals *kg, int particle) { int offset = particle*PARTICLE_SIZE; - float4 f = kernel_tex_fetch(__particles, offset); + float4 f = kernel_tex_fetch(__particles, offset + 0); return f.x; } __device float particle_age(KernelGlobals *kg, int particle) { int offset = particle*PARTICLE_SIZE; - float4 f = kernel_tex_fetch(__particles, offset); + float4 f = kernel_tex_fetch(__particles, offset + 0); return f.y; } __device float particle_lifetime(KernelGlobals *kg, int particle) { int offset = particle*PARTICLE_SIZE; - float4 f = kernel_tex_fetch(__particles, offset); + float4 f = kernel_tex_fetch(__particles, offset + 0); return f.z; } +__device float particle_size(KernelGlobals *kg, int particle) +{ + int offset = particle*PARTICLE_SIZE; + float4 f = kernel_tex_fetch(__particles, offset + 0); + return f.w; +} + +__device float4 particle_rotation(KernelGlobals *kg, int particle) +{ + int offset = particle*PARTICLE_SIZE; + float4 f = kernel_tex_fetch(__particles, offset + 1); + return f; +} + +__device float3 particle_location(KernelGlobals *kg, int particle) +{ + int offset = particle*PARTICLE_SIZE; + float4 f = kernel_tex_fetch(__particles, offset + 2); + return make_float3(f.x, f.y, f.z); +} + +__device float3 particle_velocity(KernelGlobals *kg, int particle) +{ + int offset = particle*PARTICLE_SIZE; + float4 f2 = kernel_tex_fetch(__particles, offset + 2); + float4 f3 = kernel_tex_fetch(__particles, offset + 3); + return make_float3(f2.w, f3.x, f3.y); +} + +__device float3 particle_angular_velocity(KernelGlobals *kg, int particle) +{ + int offset = particle*PARTICLE_SIZE; + float4 f3 = kernel_tex_fetch(__particles, offset + 3); + float4 f4 = kernel_tex_fetch(__particles, offset + 4); + return make_float3(f3.z, f3.w, f4.x); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 8d983a4ec75..6c81fa4cfca 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -842,15 +842,20 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam path_state_next(kg, &ps, label); /* setup ray */ - ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng); - ray.D = bsdf_omega_in; - ray.t = FLT_MAX; + 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__ - ray.dP = sd.dP; - ray.dD = bsdf_domega_in; + bsdf_ray.dP = sd.dP; + bsdf_ray.dD = bsdf_domega_in; +#endif +#ifdef __MOTION__ + bsdf_ray.time = sd.time; #endif - kernel_path_indirect(kg, rng, sample*num_samples, ray, buffer, + kernel_path_indirect(kg, rng, sample*num_samples, bsdf_ray, buffer, tp*num_samples_inv, min_ray_pdf, bsdf_pdf, ps, rng_offset+PRNG_BOUNCE_NUM, &L); } } diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index bc873f4e112..5ab3c2c2545 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -30,7 +30,7 @@ #include "osl_shader.h" -#else +#endif #include "svm/bsdf.h" #include "svm/emissive.h" @@ -38,7 +38,6 @@ #include "svm/svm_bsdf.h" #include "svm/svm.h" -#endif CCL_NAMESPACE_BEGIN @@ -294,7 +293,8 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData #ifdef __MULTI_CLOSURE__ -__device_inline void _shader_bsdf_multi_eval(const ShaderData *sd, const float3 omega_in, float *pdf, +#ifdef __OSL__ +__device_inline void _shader_bsdf_multi_eval_osl(const ShaderData *sd, const float3 omega_in, float *pdf, int skip_bsdf, BsdfEval *bsdf_eval, float sum_pdf, float sum_sample_weight) { for(int i = 0; i< sd->num_closure; i++) { @@ -305,12 +305,36 @@ __device_inline void _shader_bsdf_multi_eval(const ShaderData *sd, const float3 if(CLOSURE_IS_BSDF(sc->type)) { float bsdf_pdf = 0.0f; -#ifdef __OSL__ + float3 eval = OSLShader::bsdf_eval(sd, sc, omega_in, bsdf_pdf); -#else - float3 eval = svm_bsdf_eval(sd, sc, omega_in, &bsdf_pdf); + + if(bsdf_pdf != 0.0f) { + bsdf_eval_accum(bsdf_eval, sc->type, eval*sc->weight); + sum_pdf += bsdf_pdf*sc->sample_weight; + } + + sum_sample_weight += sc->sample_weight; + } + } + + *pdf = (sum_sample_weight > 0.0f)? sum_pdf/sum_sample_weight: 0.0f; +} #endif +__device_inline void _shader_bsdf_multi_eval_svm(const ShaderData *sd, const float3 omega_in, float *pdf, + int skip_bsdf, BsdfEval *bsdf_eval, float sum_pdf, float sum_sample_weight) +{ + for(int i = 0; i< sd->num_closure; i++) { + if(i == skip_bsdf) + continue; + + const ShaderClosure *sc = &sd->closure[i]; + + if(CLOSURE_IS_BSDF(sc->type)) { + float bsdf_pdf = 0.0f; + + float3 eval = svm_bsdf_eval(sd, sc, omega_in, &bsdf_pdf); + if(bsdf_pdf != 0.0f) { bsdf_eval_accum(bsdf_eval, sc->type, eval*sc->weight); sum_pdf += bsdf_pdf*sc->sample_weight; @@ -331,7 +355,12 @@ __device void shader_bsdf_eval(KernelGlobals *kg, const ShaderData *sd, #ifdef __MULTI_CLOSURE__ bsdf_eval_init(eval, NBUILTIN_CLOSURES, make_float3(0.0f, 0.0f, 0.0f), kernel_data.film.use_light_pass); - return _shader_bsdf_multi_eval(sd, omega_in, pdf, -1, eval, 0.0f, 0.0f); +#ifdef __OSL__ + if (kernel_osl_use(kg)) + return _shader_bsdf_multi_eval_osl(sd, omega_in, pdf, -1, eval, 0.0f, 0.0f); + else +#endif + return _shader_bsdf_multi_eval_svm(sd, omega_in, pdf, -1, eval, 0.0f, 0.0f); #else const ShaderClosure *sc = &sd->closure; @@ -384,16 +413,23 @@ __device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd, *pdf = 0.0f; #ifdef __OSL__ - label = OSLShader::bsdf_sample(sd, sc, randu, randv, eval, *omega_in, *domega_in, *pdf); -#else - label = svm_bsdf_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf); + if (kernel_osl_use(kg)) + label = OSLShader::bsdf_sample(sd, sc, randu, randv, eval, *omega_in, *domega_in, *pdf); + else #endif + label = svm_bsdf_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf); + if(*pdf != 0.0f) { bsdf_eval_init(bsdf_eval, sc->type, eval*sc->weight, kernel_data.film.use_light_pass); if(sd->num_closure > 1) { float sweight = sc->sample_weight; - _shader_bsdf_multi_eval(sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight); +#ifdef __OSL__ + if (kernel_osl_use(kg)) + _shader_bsdf_multi_eval_osl(sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight); + else +#endif + _shader_bsdf_multi_eval_svm(sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight); } } @@ -416,10 +452,12 @@ __device int shader_bsdf_sample_closure(KernelGlobals *kg, const ShaderData *sd, *pdf = 0.0f; #ifdef __OSL__ - label = OSLShader::bsdf_sample(sd, sc, randu, randv, eval, *omega_in, *domega_in, *pdf); -#else - label = svm_bsdf_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf); + if (kernel_osl_use(kg)) + label = OSLShader::bsdf_sample(sd, sc, randu, randv, eval, *omega_in, *domega_in, *pdf); + else #endif + label = svm_bsdf_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf); + if(*pdf != 0.0f) bsdf_eval_init(bsdf_eval, sc->type, eval*sc->weight, kernel_data.film.use_light_pass); @@ -539,10 +577,12 @@ __device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd) if(CLOSURE_IS_EMISSION(sc->type)) { #ifdef __OSL__ - eval += OSLShader::emissive_eval(sd, sc)*sc->weight; -#else - eval += svm_emissive_eval(sd, sc)*sc->weight; + if (kernel_osl_use(kg)) + eval += OSLShader::emissive_eval(sd, sc)*sc->weight; + else #endif + eval += svm_emissive_eval(sd, sc)*sc->weight; + } } #else @@ -581,17 +621,18 @@ __device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag) { #ifdef __OSL__ - OSLShader::eval_surface(kg, sd, randb, path_flag); -#else - + if (kernel_osl_use(kg)) + OSLShader::eval_surface(kg, sd, randb, path_flag); + else +#endif + { #ifdef __SVM__ - svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, randb, path_flag); + svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, randb, path_flag); #else - bsdf_diffuse_setup(sd, &sd->closure); - sd->closure.weight = make_float3(0.8f, 0.8f, 0.8f); -#endif - + bsdf_diffuse_setup(sd, &sd->closure); + sd->closure.weight = make_float3(0.8f, 0.8f, 0.8f); #endif + } } /* Background Evaluation */ @@ -599,35 +640,37 @@ __device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, __device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag) { #ifdef __OSL__ - return OSLShader::eval_background(kg, sd, path_flag); -#else + if (kernel_osl_use(kg)) + return OSLShader::eval_background(kg, sd, path_flag); + else +#endif + { #ifdef __SVM__ - svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, 0.0f, path_flag); + svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, 0.0f, path_flag); #ifdef __MULTI_CLOSURE__ - float3 eval = make_float3(0.0f, 0.0f, 0.0f); + float3 eval = make_float3(0.0f, 0.0f, 0.0f); - for(int i = 0; i< sd->num_closure; i++) { - const ShaderClosure *sc = &sd->closure[i]; + for(int i = 0; i< sd->num_closure; i++) { + const ShaderClosure *sc = &sd->closure[i]; - if(CLOSURE_IS_BACKGROUND(sc->type)) - eval += sc->weight; + if(CLOSURE_IS_BACKGROUND(sc->type)) + eval += sc->weight; + } + + return eval; +#else + if(sd->closure.type == CLOSURE_BACKGROUND_ID) + return sd->closure.weight; + else + return make_float3(0.0f, 0.0f, 0.0f); +#endif + +#else + return make_float3(0.8f, 0.8f, 0.8f); +#endif } - - return eval; -#else - if(sd->closure.type == CLOSURE_BACKGROUND_ID) - return sd->closure.weight; - else - return make_float3(0.0f, 0.0f, 0.0f); -#endif - -#else - return make_float3(0.8f, 0.8f, 0.8f); -#endif - -#endif } /* Volume */ @@ -643,10 +686,11 @@ __device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd, if(CLOSURE_IS_VOLUME(sc->type)) { #ifdef __OSL__ - eval += OSLShader::volume_eval_phase(sd, sc, omega_in, omega_out); -#else - eval += volume_eval_phase(sd, sc, omega_in, omega_out); + if (kernel_osl_use(kg)) + eval += OSLShader::volume_eval_phase(sd, sc, omega_in, omega_out); + else #endif + eval += volume_eval_phase(sd, sc, omega_in, omega_out); } } @@ -663,10 +707,11 @@ __device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd, { #ifdef __SVM__ #ifdef __OSL__ - OSLShader::eval_volume(kg, sd, randb, path_flag); -#else - svm_eval_nodes(kg, sd, SHADER_TYPE_VOLUME, randb, path_flag); + if (kernel_osl_use(kg)) + OSLShader::eval_volume(kg, sd, randb, path_flag); + else #endif + svm_eval_nodes(kg, sd, SHADER_TYPE_VOLUME, randb, path_flag); #endif } @@ -677,10 +722,11 @@ __device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd) /* this will modify sd->P */ #ifdef __SVM__ #ifdef __OSL__ - OSLShader::eval_displacement(kg, sd); -#else - svm_eval_nodes(kg, sd, SHADER_TYPE_DISPLACEMENT, 0.0f, 0); + if (kernel_osl_use(kg)) + OSLShader::eval_displacement(kg, sd); + else #endif + svm_eval_nodes(kg, sd, SHADER_TYPE_DISPLACEMENT, 0.0f, 0); #endif } @@ -732,7 +778,8 @@ __device void shader_merge_closures(KernelGlobals *kg, ShaderData *sd) __device void shader_release(KernelGlobals *kg, ShaderData *sd) { #ifdef __OSL__ - OSLShader::release(kg, sd); + if (kernel_osl_use(kg)) + OSLShader::release(kg, sd); #endif } diff --git a/intern/cycles/kernel/kernel_triangle.h b/intern/cycles/kernel/kernel_triangle.h index 6c1ea465515..492800e8aab 100644 --- a/intern/cycles/kernel/kernel_triangle.h +++ b/intern/cycles/kernel/kernel_triangle.h @@ -15,6 +15,8 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#include "kernel_projection.h" CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 30d45ad1118..39e088583c4 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -33,7 +33,7 @@ CCL_NAMESPACE_BEGIN #define LIGHT_SIZE 4 #define FILTER_TABLE_SIZE 256 #define RAMP_TABLE_SIZE 256 -#define PARTICLE_SIZE 1 +#define PARTICLE_SIZE 5 #define TIME_INVALID FLT_MAX /* device capabilities */ @@ -382,10 +382,9 @@ typedef struct ShaderClosure { #ifdef __OSL__ void *prim; -#else +#endif float data0; float data1; -#endif } ShaderClosure; diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt index 13b2a39d7d0..ce82d901c44 100644 --- a/intern/cycles/kernel/osl/CMakeLists.txt +++ b/intern/cycles/kernel/osl/CMakeLists.txt @@ -42,3 +42,7 @@ include_directories(${INC}) add_library(cycles_kernel_osl ${SRC} ${HEADER_SRC}) add_subdirectory(nodes) + +if(WITH_CYCLES_OSL) + target_link_libraries(cycles_kernel_osl ${OSL_LIBRARIES}) +endif() diff --git a/intern/cycles/kernel/osl/nodes/CMakeLists.txt b/intern/cycles/kernel/osl/nodes/CMakeLists.txt index 5a645919358..2d2b5b10ce6 100644 --- a/intern/cycles/kernel/osl/nodes/CMakeLists.txt +++ b/intern/cycles/kernel/osl/nodes/CMakeLists.txt @@ -8,6 +8,7 @@ set(SRC_OSL node_bump.osl node_camera.osl node_checker_texture.osl + node_combine_rgb.osl node_convert_from_color.osl node_convert_from_float.osl node_convert_from_normal.osl @@ -23,6 +24,7 @@ set(SRC_OSL node_geometry.osl node_glass_bsdf.osl node_glossy_bsdf.osl + node_holdout.osl node_hsv.osl node_image_texture.osl node_invert.osl @@ -34,12 +36,11 @@ set(SRC_OSL node_mix_closure.osl node_musgrave_texture.osl node_normal.osl - node_blend_weight_texture.osl node_noise_texture.osl node_output_displacement.osl node_output_surface.osl node_output_volume.osl - node_sepcomb_rgb.osl + node_separate_rgb.osl node_sky_texture.osl node_texture_coordinate.osl node_translucent_bsdf.osl @@ -57,6 +58,7 @@ set(SRC_OSL_HEADERS node_color.h node_fresnel.h stdosl.h + oslutil.h ) set(SRC_OSO @@ -82,4 +84,5 @@ endforeach() add_custom_target(shader ALL DEPENDS ${SRC_OSO} ${SRC_OSL_HEADERS}) -delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_OSO}" ${CYCLES_INSTALL_PATH}/shader) +# CMAKE_CURRENT_SOURCE_DIR is already included in OSO paths +delayed_install("" "${SRC_OSO}" ${CYCLES_INSTALL_PATH}/shader) diff --git a/intern/cycles/kernel/osl/nodes/node_brightness.osl b/intern/cycles/kernel/osl/nodes/node_brightness.osl index a93ff06d443..4f19a20f736 100644 --- a/intern/cycles/kernel/osl/nodes/node_brightness.osl +++ b/intern/cycles/kernel/osl/nodes/node_brightness.osl @@ -20,15 +20,16 @@ shader node_brightness( color ColorIn = color(0.8, 0.8, 0.8), - float Bright = 0.0, + float Brightness = 0.0, float Contrast = 0.0, - output ColorOut = color(0.8, 0.8, 0.8) + output color ColorOut = color(0.8, 0.8, 0.8)) { float delta = Contrast * (1.0/200.0); float a = 1.0 - delta * 2.0; float b; - Bright *= 1.0/100.0; + /* input value is a percentage */ + float bright_factor = Brightness / 100.0; /* * The algorithm is by Werner D. Streidt @@ -38,11 +39,11 @@ shader node_brightness( if (Contrast > 0.0) { a = (a < 0.0 ? 1.0/a : 0.0); - b = a * (Brightness - delta); + b = a * (bright_factor - delta); } else { delta *= -1.0; - b = a * (Brightness + delta); + b = a * (bright_factor + delta); } ColorOut = a * ColorIn + b; diff --git a/intern/cycles/kernel/osl/nodes/node_checker_texture.osl b/intern/cycles/kernel/osl/nodes/node_checker_texture.osl index 306798b645f..e92d7be34fc 100644 --- a/intern/cycles/kernel/osl/nodes/node_checker_texture.osl +++ b/intern/cycles/kernel/osl/nodes/node_checker_texture.osl @@ -49,10 +49,10 @@ shader node_checker_texture( { Fac = checker(Vector*Scale); if(Fac == 1.0) { - Color = color(Color1, Color1, Color1); + Color = Color1; } else { - Color = color(Color2, Color2, Color2); + Color = Color2; } } diff --git a/intern/cycles/kernel/osl/nodes/node_combine_rgb.osl b/intern/cycles/kernel/osl/nodes/node_combine_rgb.osl new file mode 100644 index 00000000000..546369f660e --- /dev/null +++ b/intern/cycles/kernel/osl/nodes/node_combine_rgb.osl @@ -0,0 +1,29 @@ +/* + * 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_combine_rgb( + float R = 0.0, + float G = 0.0, + float B = 0.0, + output color Image = color(0.8, 0.8, 0.8)) +{ + Image = color(R, G, B); +} + diff --git a/intern/cycles/kernel/osl/nodes/node_gamma.osl b/intern/cycles/kernel/osl/nodes/node_gamma.osl index 4dae07d70bc..d55e908b0b7 100644 --- a/intern/cycles/kernel/osl/nodes/node_gamma.osl +++ b/intern/cycles/kernel/osl/nodes/node_gamma.osl @@ -21,13 +21,7 @@ shader node_gamma( color ColorIn = color(0.8, 0.8, 0.8), float Gamma = 1.0, - output ColorOut = color(0.8, 0.8, 0.8) + output color ColorOut = color(0.0, 0.0, 0.0)) { - int i; - for (i=0;i<3;i++) { - if (ColorIn[i] > 0.0) - ColorIn[i] = powf(ColorIn[i], Gamma); - } - - ColorOut = ColorIn; + ColorOut = pow(ColorIn, Gamma); } diff --git a/intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl b/intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl index cc2104af56f..52743669c99 100644 --- a/intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl +++ b/intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl @@ -34,8 +34,8 @@ shader node_glass_bsdf( if(distribution == "Sharp") BSDF = Color*(Fr*reflection(Normal) + (1.0-Fr)*refraction(Normal, eta)); else if(distribution == "Beckmann") - BSDF = Color*(Fr*microfacet_beckmann(Normal, Roughness) + (1.0-Fr)*microfacet_beckmann_refraction(Normal, Roughness, eta)); + BSDF = Color*(Fr*microfacet_beckmann(Normal, Roughness, eta) + (1.0-Fr)*microfacet_beckmann_refraction(Normal, Roughness, eta)); else if(distribution == "GGX") - BSDF = Color*(Fr*microfacet_ggx(Normal, Roughness) + (1.0-Fr)*microfacet_ggx_refraction(Normal, Roughness, eta)); + BSDF = Color*(Fr*microfacet_ggx(Normal, Roughness, eta) + (1.0-Fr)*microfacet_ggx_refraction(Normal, Roughness, eta)); } diff --git a/intern/cycles/kernel/osl/nodes/node_glossy_bsdf.osl b/intern/cycles/kernel/osl/nodes/node_glossy_bsdf.osl index aa446b66cfb..3890630e8a2 100644 --- a/intern/cycles/kernel/osl/nodes/node_glossy_bsdf.osl +++ b/intern/cycles/kernel/osl/nodes/node_glossy_bsdf.osl @@ -29,9 +29,9 @@ shader node_glossy_bsdf( if(distribution == "Sharp") BSDF = Color*reflection(Normal); else if(distribution == "Beckmann") - BSDF = Color*microfacet_beckmann(Normal, Roughness); + BSDF = Color*microfacet_beckmann(Normal, Roughness, 1.0); else if(distribution == "GGX") - BSDF = Color*microfacet_ggx(Normal, Roughness); + BSDF = Color*microfacet_ggx(Normal, Roughness, 1.0); } diff --git a/intern/cycles/kernel/osl/nodes/node_invert.osl b/intern/cycles/kernel/osl/nodes/node_invert.osl index 817198c4561..27021942558 100644 --- a/intern/cycles/kernel/osl/nodes/node_invert.osl +++ b/intern/cycles/kernel/osl/nodes/node_invert.osl @@ -21,7 +21,7 @@ shader node_invert( float Fac = 1.0, color ColorIn = color(0.8, 0.8, 0.8), - output ColorOut = color(0.8, 0.8, 0.8) + output color ColorOut = color(0.8, 0.8, 0.8)) { color ColorInv = color(1.0) - ColorIn; ColorOut = mix(ColorIn, ColorInv, Fac); diff --git a/intern/cycles/kernel/osl/nodes/node_math.osl b/intern/cycles/kernel/osl/nodes/node_math.osl index be9bb71d511..3327795286a 100644 --- a/intern/cycles/kernel/osl/nodes/node_math.osl +++ b/intern/cycles/kernel/osl/nodes/node_math.osl @@ -40,6 +40,7 @@ float safe_log(float a, float b) shader node_math( string type = "Add", + int Clamp = 0, float Value1 = 0.0, float Value2 = 0.0, output float Value = 0.0) @@ -80,5 +81,8 @@ shader node_math( Value = Value1 < Value2; if(type == "Greater Than") Value = Value1 > Value2; + + if(Clamp) + Value = clamp(Value1, 0.0, 1.0); } diff --git a/intern/cycles/kernel/osl/nodes/node_mix.osl b/intern/cycles/kernel/osl/nodes/node_mix.osl index 8a462c995d3..661e543fdd8 100644 --- a/intern/cycles/kernel/osl/nodes/node_mix.osl +++ b/intern/cycles/kernel/osl/nodes/node_mix.osl @@ -267,8 +267,20 @@ color node_mix_linear(float t, color col1, color col2) return outcol; } +color node_mix_clamp(color col) +{ + color outcol = col; + + outcol[0] = clamp(col[0], 0.0, 1.0); + outcol[1] = clamp(col[2], 0.0, 1.0); + outcol[2] = clamp(col[2], 0.0, 1.0); + + return outcol; +} + shader node_mix( string type = "Mix", + int Clamp = 0, float Fac = 0.5, color Color1 = color(0.0, 0.0, 0.0), color Color2 = color(0.0, 0.0, 0.0), @@ -312,5 +324,8 @@ shader node_mix( Color = node_mix_soft(t, Color1, Color2); if(type == "Linear Light") Color = node_mix_linear(t, Color1, Color2); + + if(Clamp) + Color = node_mix_clamp(Color); } diff --git a/intern/cycles/kernel/osl/nodes/node_noise_texture.osl b/intern/cycles/kernel/osl/nodes/node_noise_texture.osl index fd9fc1dedc0..7738902f529 100644 --- a/intern/cycles/kernel/osl/nodes/node_noise_texture.osl +++ b/intern/cycles/kernel/osl/nodes/node_noise_texture.osl @@ -27,7 +27,7 @@ float noise(point p, string basis, float distortion, float detail) int hard = 0; float fac = 0.0; - if(distortion != 0.0( { + if(distortion != 0.0) { r[0] = noise_basis(p + point(13.5), basis) * distortion; r[1] = noise_basis(p, basis) * distortion; r[2] = noise_basis(p - point(13.5), basis) * distortion; diff --git a/intern/cycles/kernel/osl/nodes/node_normal.osl b/intern/cycles/kernel/osl/nodes/node_normal.osl index 038a33c9898..d5f16acb88c 100644 --- a/intern/cycles/kernel/osl/nodes/node_normal.osl +++ b/intern/cycles/kernel/osl/nodes/node_normal.osl @@ -22,10 +22,9 @@ shader node_normal( normal Direction = normal(0.0, 0.0, 0.0), normal NormalIn = normal(0.0, 0.0, 0.0), output normal NormalOut = normal(0.0, 0.0, 0.0), - output float Dot = 1.0 + output float Dot = 1.0) { - Direction = normalize(Direction); - NormalOut = Direction; - Dot = dot(Direction, NormalIn); + NormalOut = normalize(Direction); + Dot = dot(NormalOut, NormalIn); } diff --git a/intern/cycles/kernel/osl/nodes/node_sepcomb_rgb.osl b/intern/cycles/kernel/osl/nodes/node_separate_rgb.osl similarity index 82% rename from intern/cycles/kernel/osl/nodes/node_sepcomb_rgb.osl rename to intern/cycles/kernel/osl/nodes/node_separate_rgb.osl index a02f31f4b07..b48bd7e59d6 100644 --- a/intern/cycles/kernel/osl/nodes/node_sepcomb_rgb.osl +++ b/intern/cycles/kernel/osl/nodes/node_separate_rgb.osl @@ -24,17 +24,7 @@ shader node_separate_rgb( output float G = 0.0, output float B = 0.0) { - R = Image[0]; - G = Image[1]; - B = Image[2]; + R = Image[0]; + G = Image[1]; + B = Image[2]; } - -shader node_combine_rgb( - float R = 0.0, - float G = 0.0, - float B = 0.0, - output color Image = color(0.8, 0.8, 0.8) -{ - Image = color(R, G, B) -} - diff --git a/intern/cycles/kernel/osl/nodes/node_texture.h b/intern/cycles/kernel/osl/nodes/node_texture.h index d2dbd6db8b3..b00bf6ab31f 100644 --- a/intern/cycles/kernel/osl/nodes/node_texture.h +++ b/intern/cycles/kernel/osl/nodes/node_texture.h @@ -212,14 +212,17 @@ float noise_wave(string wave, float a) /* Turbulence */ -float noise_turbulence(point p, string basis, int octaves, int hard) +float noise_turbulence(point p, string basis, float details, int hard) { float fscale = 1.0; float amp = 1.0; float sum = 0.0; - int i; + int i, n; + + float octaves = clamp(details, 0.0, 16.0); + n = (int)octaves; - for (i = 0; i <= octaves; i++) { + for (i = 0; i <= n; i++) { float t = noise_basis(fscale * p, basis); if (hard) @@ -229,10 +232,26 @@ float noise_turbulence(point p, string basis, int octaves, int hard) amp *= 0.5; fscale *= 2.0; } + + float rmd = octaves - floor(octaves); - sum *= ((float)(1 << octaves) / (float)((1 << (octaves + 1)) - 1)); + if(rmd != 0.0) { + float t = noise_basis(fscale*p, basis); - return sum; + if(hard) + t = fabs(2.0*t - 1.0); + + float sum2 = sum + t*amp; + + sum *= ((float)(1 << n)/(float)((1 << (n+1)) - 1)); + sum2 *= ((float)(1 << (n+1))/(float)((1 << (n+2)) - 1)); + + return (1.0 - rmd)*sum + rmd*sum2; + } + else { + sum *= ((float)(1 << n)/(float)((1 << (n+1)) - 1)); + return sum; + } } /* Utility */ diff --git a/intern/cycles/kernel/osl/nodes/node_velvet_bsdf.osl b/intern/cycles/kernel/osl/nodes/node_velvet_bsdf.osl index 7a336c148db..5e0cae8cbd1 100644 --- a/intern/cycles/kernel/osl/nodes/node_velvet_bsdf.osl +++ b/intern/cycles/kernel/osl/nodes/node_velvet_bsdf.osl @@ -27,6 +27,6 @@ shader node_velvet_bsdf( { float sigma = clamp(Sigma, 0.0, 1.0); - BSDF = Color*ashikhmin_velvet(Normal, sigma); + BSDF = Color*ashikhmin_velvet(Normal, sigma, 1.0); } diff --git a/intern/cycles/kernel/osl/nodes/node_wave_texture.osl b/intern/cycles/kernel/osl/nodes/node_wave_texture.osl index b55ec771be8..693f09ae24c 100644 --- a/intern/cycles/kernel/osl/nodes/node_wave_texture.osl +++ b/intern/cycles/kernel/osl/nodes/node_wave_texture.osl @@ -31,14 +31,14 @@ float wave(point p, float scale, string type, float detail, float distortion, fl float n = 0.0; if(type == "Bands") { - n = (x + y + z)*10.0); + n = (x + y + z)*10.0; } else if(type == "Rings") { n = (sqrt(x*x + y*y + z*z)*20.0); } if(distortion != 0.0) { - n = n +(distortion * noise_turbulence(p*dscale, "Perlin", detail, 0); + n = n +(distortion * noise_turbulence(p*dscale, "Perlin", detail, 0)); } result = noise_wave("Sine", n); diff --git a/intern/cycles/kernel/osl/nodes/oslutil.h b/intern/cycles/kernel/osl/nodes/oslutil.h new file mode 100644 index 00000000000..08611187a3c --- /dev/null +++ b/intern/cycles/kernel/osl/nodes/oslutil.h @@ -0,0 +1,91 @@ +///////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved. +// +// 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 CCL_OSLUTIL_H +#define CCL_OSLUTIL_H + +// Return wireframe opacity factor [0, 1] given a geometry type in +// ("triangles", "polygons" or "patches"), and a line_width in raster +// or world space depending on the last (raster) boolean argument. +// +float wireframe(string edge_type, float line_width, int raster) +{ + // ray differentials are so big in diffuse context that this function would always return "wire" + if (raytype("path:diffuse")) return 0.0; + + int np = 0; + point p[64]; + float pixelWidth = 1; + + if (edge_type == "triangles") + { + np = 3; + if (!getattribute("geom:trianglevertices", p)) + return 0.0; + } + else if (edge_type == "polygons" || edge_type == "patches") + { + getattribute("geom:numpolyvertices", np); + if (np < 3 || !getattribute("geom:polyvertices", p)) + return 0.0; + } + + if (raster) + { + // Project the derivatives of P to the viewing plane defined + // by I so we have a measure of how big is a pixel at this point + float pixelWidthX = length(Dx(P) - dot(Dx(P), I) * I); + float pixelWidthY = length(Dy(P) - dot(Dy(P), I) * I); + // Take the average of both axis' length + pixelWidth = (pixelWidthX + pixelWidthY) / 2; + } + + // Use half the width as the neighbor face will render the + // other half. And take the square for fast comparison + pixelWidth *= 0.5 * line_width; + pixelWidth *= pixelWidth; + for (int i = 0; i < np; i++) + { + int i2 = i ? i - 1 : np - 1; + vector dir = P - p[i]; + vector edge = p[i] - p[i2]; + vector crs = cross(edge, dir); + // At this point dot(crs, crs) / dot(edge, edge) is + // the square of area / length(edge) == square of the + // distance to the edge. + if (dot(crs, crs) < (dot(edge, edge) * pixelWidth)) + return 1; + } + return 0; +} + +float wireframe(string edge_type, float line_width) { return wireframe(edge_type, line_width, 1); } +float wireframe(string edge_type) { return wireframe(edge_type, 1.0, 1); } +float wireframe() { return wireframe("polygons", 1.0, 1); } + +#endif /* CCL_OSLUTIL_H */ diff --git a/intern/cycles/kernel/osl/nodes/stdosl.h b/intern/cycles/kernel/osl/nodes/stdosl.h index 0c07c501d69..e5accf4eb54 100644 --- a/intern/cycles/kernel/osl/nodes/stdosl.h +++ b/intern/cycles/kernel/osl/nodes/stdosl.h @@ -35,6 +35,8 @@ #define M_PI_2 1.5707963267948966 /* pi/2 */ #define M_PI_4 0.7853981633974483 /* pi/4 */ #define M_2_PI 0.6366197723675813 /* 2/pi */ +#define M_2PI 6.2831853071795865 /* 2*pi */ +#define M_4PI 12.566370614359173 /* 4*pi */ #define M_2_SQRTPI 1.1283791670955126 /* 2/sqrt(pi) */ #define M_E 2.7182818284590452 /* e (Euler's number) */ #define M_LN2 0.6931471805599453 /* ln(2) */ @@ -121,9 +123,16 @@ PERCOMP1 (round) PERCOMP1 (trunc) PERCOMP2 (fmod) PERCOMP2F (fmod) -PERCOMP2 (mod) -PERCOMP2F (mod) -int mod (int x, int y) BUILTIN; +int mod (int a, int b) { return a - b*(int)floor(a/b); } +point mod (point a, point b) { return a - b*floor(a/b); } +vector mod (vector a, vector b) { return a - b*floor(a/b); } +normal mod (normal a, normal b) { return a - b*floor(a/b); } +color mod (color a, color b) { return a - b*floor(a/b); } +point mod (point a, float b) { return a - b*floor(a/b); } +vector mod (vector a, float b) { return a - b*floor(a/b); } +normal mod (normal a, float b) { return a - b*floor(a/b); } +color mod (color a, float b) { return a - b*floor(a/b); } +float mod (float a, float b) { return a - b*floor(a/b); } PERCOMP2 (min) PERCOMP2 (max) normal clamp (normal x, normal minval, normal maxval) { return max(min(x,maxval),minval); } @@ -131,11 +140,6 @@ vector clamp (vector x, vector minval, vector maxval) { return max(min(x,maxval) point clamp (point x, point minval, point maxval) { return max(min(x,maxval),minval); } color clamp (color x, color minval, color maxval) { return max(min(x,maxval),minval); } float clamp (float x, float minval, float maxval) { return max(min(x,maxval),minval); } -//normal clamp (normal x, normal minval, normal maxval) BUILTIN; -//vector clamp (vector x, vector minval, vector maxval) BUILTIN; -//point clamp (point x, point minval, point maxval) BUILTIN; -//color clamp (color x, color minval, color maxval) BUILTIN; -//float clamp (float x, float minval, float maxval) BUILTIN; normal mix (normal x, normal y, normal a) { return x*(1-a) + y*a; } normal mix (normal x, normal y, float a) { return x*(1-a) + y*a; } vector mix (vector x, vector y, vector a) { return x*(1-a) + y*a; } @@ -163,246 +167,234 @@ vector normalize (vector v) BUILTIN; vector faceforward (vector N, vector I, vector Nref) BUILTIN; vector faceforward (vector N, vector I) BUILTIN; vector reflect (vector I, vector N) { return I - 2*dot(N,I)*N; } -vector refract(vector I, vector N, float eta) { - float IdotN = dot(I, N); - float k = 1 - eta * eta * (1 - IdotN * IdotN); - return (k < 0) ? vector(0, 0, 0) : (eta * I - N * (eta * IdotN + sqrt(k))); +vector refract (vector I, vector N, float eta) { + float IdotN = dot (I, N); + float k = 1 - eta*eta * (1 - IdotN*IdotN); + return (k < 0) ? vector(0,0,0) : (eta*I - N * (eta*IdotN + sqrt(k))); } -void fresnel(vector I, normal N, float eta, - output float Kr, output float Kt, - output vector R, output vector T) +void fresnel (vector I, normal N, float eta, + output float Kr, output float Kt, + output vector R, output vector T) { - float sqr(float x) { - return x * x; - } - float c = dot(I, N); - if (c < 0) - c = -c; - R = reflect(I, N); - float g = 1.0 / sqr(eta) - 1.0 + c * c; - if (g >= 0.0) { - g = sqrt(g); - float beta = g - c; - float F = (c * (g + c) - 1.0) / (c * beta + 1.0); - F = 0.5 * (1.0 + sqr(F)); - F *= sqr(beta / (g + c)); - Kr = F; - Kt = (1.0 - Kr) * eta * eta; - // OPT: the following recomputes some of the above values, but it - // gives us the same result as if the shader-writer called refract() - T = refract(I, N, eta); - } - else { - // total internal reflection - Kr = 1.0; - Kt = 0.0; - T = vector(0, 0, 0); - } -#undef sqr + float sqr(float x) { return x*x; } + float c = dot(I, N); + if (c < 0) + c = -c; + R = reflect(I, N); + float g = 1.0 / sqr(eta) - 1.0 + c * c; + if (g >= 0.0) { + g = sqrt (g); + float beta = g - c; + float F = (c * (g+c) - 1.0) / (c * beta + 1.0); + F = 0.5 * (1.0 + sqr(F)); + F *= sqr (beta / (g+c)); + Kr = F; + Kt = (1.0 - Kr) * eta*eta; + // OPT: the following recomputes some of the above values, but it + // gives us the same result as if the shader-writer called refract() + T = refract(I, N, eta); + } else { + // total internal reflection + Kr = 1.0; + Kt = 0.0; + T = vector (0,0,0); + } } -void fresnel(vector I, normal N, float eta, - output float Kr, output float Kt) +void fresnel (vector I, normal N, float eta, + output float Kr, output float Kt) { - vector R, T; - fresnel(I, N, eta, Kr, Kt, R, T); + vector R, T; + fresnel(I, N, eta, Kr, Kt, R, T); } -point rotate(point q, float angle, point a, point b) BUILTIN; -normal transform(matrix Mto, normal p) BUILTIN; -vector transform(matrix Mto, vector p) BUILTIN; -point transform(matrix Mto, point p) BUILTIN; +normal transform (matrix Mto, normal p) BUILTIN; +vector transform (matrix Mto, vector p) BUILTIN; +point transform (matrix Mto, point p) BUILTIN; +normal transform (string from, string to, normal p) BUILTIN; +vector transform (string from, string to, vector p) BUILTIN; +point transform (string from, string to, point p) BUILTIN; +normal transform (string to, normal p) { return transform("common",to,p); } +vector transform (string to, vector p) { return transform("common",to,p); } +point transform (string to, point p) { return transform("common",to,p); } -// Implementation of transform-with-named-space in terms of matrices: +float transformu (string tounits, float x) BUILTIN; +float transformu (string fromunits, string tounits, float x) BUILTIN; -point transform(string tospace, point x) +point rotate (point p, float angle, point a, point b) { - return transform(matrix("common", tospace), x); + vector axis = normalize (b - a); + float cosang, sinang; + sincos (angle, sinang, cosang); + float cosang1 = 1.0 - cosang; + float x = axis[0], y = axis[1], z = axis[2]; + matrix M = matrix (x * x + (1.0 - x * x) * cosang, + x * y * cosang1 + z * sinang, + x * z * cosang1 - y * sinang, + 0.0, + x * y * cosang1 - z * sinang, + y * y + (1.0 - y * y) * cosang, + y * z * cosang1 + x * sinang, + 0.0, + x * z * cosang1 + y * sinang, + y * z * cosang1 - x * sinang, + z * z + (1.0 - z * z) * cosang, + 0.0, + 0.0, 0.0, 0.0, 1.0); + return transform (M, p-a) + a; } -point transform(string fromspace, string tospace, point x) -{ - return transform(matrix(fromspace, tospace), x); -} - - -vector transform(string tospace, vector x) -{ - return transform(matrix("common", tospace), x); -} - -vector transform(string fromspace, string tospace, vector x) -{ - return transform(matrix(fromspace, tospace), x); -} - - -normal transform(string tospace, normal x) -{ - return transform(matrix("common", tospace), x); -} - -normal transform(string fromspace, string tospace, normal x) -{ - return transform(matrix(fromspace, tospace), x); -} - -float transformu(string tounits, float x) BUILTIN; -float transformu(string fromunits, string tounits, float x) BUILTIN; // Color functions -float luminance(color c) { - return dot((vector)c, vector(0.2126, 0.7152, 0.0722)); +float luminance (color c) BUILTIN; +color blackbody (float temperatureK) BUILTIN; +color wavelength_color (float wavelength_nm) BUILTIN; + + +color transformc (string to, color x) +{ + color rgb_to_hsv (color rgb) { // See Foley & van Dam + float r = rgb[0], g = rgb[1], b = rgb[2]; + float mincomp = min (r, min (g, b)); + float maxcomp = max (r, max (g, b)); + float delta = maxcomp - mincomp; // chroma + float h, s, v; + v = maxcomp; + if (maxcomp > 0) + s = delta / maxcomp; + else s = 0; + if (s <= 0) + h = 0; + else { + if (r >= maxcomp) h = (g-b) / delta; + else if (g >= maxcomp) h = 2 + (b-r) / delta; + else h = 4 + (r-g) / delta; + h /= 6; + if (h < 0) + h += 1; + } + return color (h, s, v); + } + + color rgb_to_hsl (color rgb) { // See Foley & van Dam + // First convert rgb to hsv, then to hsl + float minval = min (rgb[0], min (rgb[1], rgb[2])); + color hsv = rgb_to_hsv (rgb); + float maxval = hsv[2]; // v == maxval + float h = hsv[0], s, l = (minval+maxval) / 2; + if (minval == maxval) + s = 0; // special 'achromatic' case, hue is 0 + else if (l <= 0.5) + s = (maxval - minval) / (maxval + minval); + else + s = (maxval - minval) / (2 - maxval - minval); + return color (h, s, l); + } + + color r; + if (to == "rgb" || to == "RGB") + r = x; + else if (to == "hsv") + r = rgb_to_hsv (x); + else if (to == "hsl") + r = rgb_to_hsl (x); + else if (to == "YIQ") + r = color (dot (vector(0.299, 0.587, 0.114), (vector)x), + dot (vector(0.596, -0.275, -0.321), (vector)x), + dot (vector(0.212, -0.523, 0.311), (vector)x)); + else if (to == "xyz") + r = color (dot (vector(0.412453, 0.357580, 0.180423), (vector)x), + dot (vector(0.212671, 0.715160, 0.072169), (vector)x), + dot (vector(0.019334, 0.119193, 0.950227), (vector)x)); + else { + error ("Unknown color space \"%s\"", to); + r = x; + } + return r; } - -color transformc(string to, color x) +color transformc (string from, string to, color x) { - color rgb_to_hsv(color rgb) { // See Foley & van Dam - float r = rgb[0], g = rgb[1], b = rgb[2]; - float mincomp = min(r, min(g, b)); - float maxcomp = max(r, max(g, b)); - float delta = maxcomp - mincomp; // chroma - float h, s, v; - v = maxcomp; - if (maxcomp > 0) - s = delta / maxcomp; - else s = 0; - if (s <= 0) - h = 0; - else { - if (r >= maxcomp) h = (g - b) / delta; - else if (g >= maxcomp) h = 2 + (b - r) / delta; - else h = 4 + (r - g) / delta; - h /= 6; - if (h < 0) - h += 1; - } - return color(h, s, v); - } + color hsv_to_rgb (color c) { // Reference: Foley & van Dam + float h = c[0], s = c[1], v = c[2]; + color r; + if (s < 0.0001) { + r = v; + } else { + h = 6 * (h - floor(h)); // expand to [0..6) + int hi = (int)h; + float f = h - hi; + float p = v * (1-s); + float q = v * (1-s*f); + float t = v * (1-s*(1-f)); + if (hi == 0) r = color (v, t, p); + else if (hi == 1) r = color (q, v, p); + else if (hi == 2) r = color (p, v, t); + else if (hi == 3) r = color (p, q, v); + else if (hi == 4) r = color (t, p, v); + else r = color (v, p, q); + } + return r; + } - color rgb_to_hsl(color rgb) { // See Foley & van Dam - // First convert rgb to hsv, then to hsl - float minval = min(rgb[0], min(rgb[1], rgb[2])); - color hsv = rgb_to_hsv(rgb); - float maxval = hsv[2]; // v == maxval - float h = hsv[0], s, l = (minval + maxval) / 2; - if (minval == maxval) - s = 0; // special 'achromatic' case, hue is 0 - else if (l <= 0.5) - s = (maxval - minval) / (maxval + minval); - else - s = (maxval - minval) / (2 - maxval - minval); - return color(h, s, l); - } + color hsl_to_rgb (color c) { + float h = c[0], s = c[1], l = c[2]; + // Easiest to convert hsl -> hsv, then hsv -> RGB (per Foley & van Dam) + float v = (l <= 0.5) ? (l * (1 + s)) : (l * (1 - s) + s); + color r; + if (v <= 0) { + r = 0; + } else { + float min = 2 * l - v; + s = (v - min) / v; + r = hsv_to_rgb (color (h, s, v)); + } + return r; + } - color r; - if (to == "rgb" || to == "RGB") - r = x; - else if (to == "hsv") - r = rgb_to_hsv(x); - else if (to == "hsl") - r = rgb_to_hsl(x); - else if (to == "YIQ") - r = color(dot(vector(0.299, 0.587, 0.114), (vector)x), - dot(vector(0.596, -0.275, -0.321), (vector)x), - dot(vector(0.212, -0.523, 0.311), (vector)x)); - else if (to == "xyz") - r = color(dot(vector(0.412453, 0.357580, 0.180423), (vector)x), - dot(vector(0.212671, 0.715160, 0.072169), (vector)x), - dot(vector(0.019334, 0.119193, 0.950227), (vector)x)); - else { - error("Unknown color space \"%s\"", to); - r = x; - } - return r; -} - - -color transformc(string from, string to, color x) -{ - color hsv_to_rgb(color c) { // Reference: Foley & van Dam - float h = c[0], s = c[1], v = c[2]; - color r; - if (s < 0.0001) { - r = v; - } - else { - h = 6 * (h - floor(h)); // expand to [0..6) - int hi = (int)h; - float f = h - hi; - float p = v * (1 - s); - float q = v * (1 - s * f); - float t = v * (1 - s * (1 - f)); - if (hi == 0) r = color(v, t, p); - else if (hi == 1) r = color(q, v, p); - else if (hi == 2) r = color(p, v, t); - else if (hi == 3) r = color(p, q, v); - else if (hi == 4) r = color(t, p, v); - else r = color(v, p, q); - } - return r; - } - - color hsl_to_rgb(color c) { - float h = c[0], s = c[1], l = c[2]; - // Easiest to convert hsl -> hsv, then hsv -> RGB (per Foley & van Dam) - float v = (l <= 0.5) ? (l * (1 + s)) : (l * (1 - s) + s); - color r; - if (v <= 0) { - r = 0; - } - else { - float min = 2 * l - v; - s = (v - min) / v; - r = hsv_to_rgb(color(h, s, v)); - } - return r; - } - - color r; - if (from == "rgb" || from == "RGB") - r = x; - else if (from == "hsv") - r = hsv_to_rgb(x); - else if (from == "hsl") - r = hsl_to_rgb(x); - else if (from == "YIQ") - r = color(dot(vector(1, 0.9557, 0.6199), (vector)x), - dot(vector(1, -0.2716, -0.6469), (vector)x), - dot(vector(1, -1.1082, 1.7051), (vector)x)); - else if (from == "xyz") - r = color(dot(vector(3.240479, -1.537150, -0.498535), (vector)x), - dot(vector(-0.969256, 1.875991, 0.041556), (vector)x), - dot(vector(0.055648, -0.204043, 1.057311), (vector)x)); - else { - error("Unknown color space \"%s\"", to); - r = x; - } - return transformc(to, r); + color r; + if (from == "rgb" || from == "RGB") + r = x; + else if (from == "hsv") + r = hsv_to_rgb (x); + else if (from == "hsl") + r = hsl_to_rgb (x); + else if (from == "YIQ") + r = color (dot (vector(1, 0.9557, 0.6199), (vector)x), + dot (vector(1, -0.2716, -0.6469), (vector)x), + dot (vector(1, -1.1082, 1.7051), (vector)x)); + else if (from == "xyz") + r = color (dot (vector( 3.240479, -1.537150, -0.498535), (vector)x), + dot (vector(-0.969256, 1.875991, 0.041556), (vector)x), + dot (vector( 0.055648, -0.204043, 1.057311), (vector)x)); + else { + error ("Unknown color space \"%s\"", to); + r = x; + } + return transformc (to, r); } // Matrix functions -float determinant(matrix m) BUILTIN; -matrix transpose(matrix m) BUILTIN; +float determinant (matrix m) BUILTIN; +matrix transpose (matrix m) BUILTIN; // Pattern generation -float step(float edge, float x) BUILTIN; -color step(color edge, color x) BUILTIN; -point step(point edge, point x) BUILTIN; -vector step(vector edge, vector x) BUILTIN; -normal step(normal edge, normal x) BUILTIN; -float smoothstep(float edge0, float edge1, float x) BUILTIN; +float step (float edge, float x) BUILTIN; +color step (color edge, color x) BUILTIN; +point step (point edge, point x) BUILTIN; +vector step (vector edge, vector x) BUILTIN; +normal step (normal edge, normal x) BUILTIN; +float smoothstep (float edge0, float edge1, float x) BUILTIN; // Derivatives and area operators @@ -413,26 +405,24 @@ float smoothstep(float edge0, float edge1, float x) BUILTIN; // String functions -int strlen(string s) BUILTIN; -int startswith(string s, string prefix) BUILTIN; -int endswith(string s, string suffix) BUILTIN; -string substr(string s, int start, int len) BUILTIN; -string substr(string s, int start) { - return substr(s, start, strlen(s)); -} +int strlen (string s) BUILTIN; +int startswith (string s, string prefix) BUILTIN; +int endswith (string s, string suffix) BUILTIN; +string substr (string s, int start, int len) BUILTIN; +string substr (string s, int start) { return substr (s, start, strlen(s)); } // Define concat in terms of shorter concat -string concat(string a, string b, string c) { - return concat(concat(a, b), c); +string concat (string a, string b, string c) { + return concat(concat(a,b), c); } -string concat(string a, string b, string c, string d) { - return concat(concat(a, b, c), d); +string concat (string a, string b, string c, string d) { + return concat(concat(a,b,c), d); } -string concat(string a, string b, string c, string d, string e) { - return concat(concat(a, b, c, d), e); +string concat (string a, string b, string c, string d, string e) { + return concat(concat(a,b,c,d), e); } -string concat(string a, string b, string c, string d, string e, string f) { - return concat(concat(a, b, c, d, e), f); +string concat (string a, string b, string c, string d, string e, string f) { + return concat(concat(a,b,c,d,e), f); } @@ -445,16 +435,20 @@ closure color diffuse(normal N) BUILTIN; closure color oren_nayar(normal N, float sigma) BUILTIN; closure color translucent(normal N) BUILTIN; closure color reflection(normal N, float eta) BUILTIN; -closure color reflection(normal N) { return reflection(N, 0.0); } +closure color reflection(normal N) { return reflection (N, 0.0); } closure color refraction(normal N, float eta) BUILTIN; closure color dielectric(normal N, float eta) BUILTIN; closure color transparent() BUILTIN; -closure color microfacet_ggx(normal N, float ag) BUILTIN; +closure color microfacet_ggx(normal N, float ag, float eta) BUILTIN; closure color microfacet_ggx_refraction(normal N, float ag, float eta) BUILTIN; -closure color microfacet_beckmann(normal N, float ab) BUILTIN; +closure color microfacet_beckmann(normal N, float ab, float eta) BUILTIN; closure color microfacet_beckmann_refraction(normal N, float ab, float eta) BUILTIN; -closure color ward(normal N, vector T, float ax, float ay) BUILTIN; -closure color ashikhmin_velvet(normal N, float sigma) BUILTIN; +closure color ward(normal N, vector T,float ax, float ay) BUILTIN; +closure color phong(normal N, float exponent) BUILTIN; +closure color phong_ramp(normal N, float exponent, color colors[8]) BUILTIN; +closure color hair_diffuse(vector T) BUILTIN; +closure color hair_specular(vector T, float offset, float exponent) BUILTIN; +closure color ashikhmin_velvet(normal N, float sigma, float eta) BUILTIN; closure color westin_backscatter(normal N, float roughness) BUILTIN; closure color westin_sheen(normal N, float edginess) BUILTIN; closure color bssrdf_cubic(color radius) BUILTIN; @@ -464,10 +458,75 @@ closure color emission() BUILTIN; closure color debug(string tag) BUILTIN; closure color background() BUILTIN; closure color holdout() BUILTIN; -closure color subsurface(float eta, float g, float mfp, float albedo) BUILTIN; +closure color subsurface(float eta, float g, color mfp, color albedo) BUILTIN; + +closure color cloth(normal N, float s, float t, float dsdx, float dtdx, float dsdy, float dtdy, + float area_scaled, vector dPdu, color diff_warp_col, color diff_weft_col, + color spec_warp_col, color spec_weft_col, float fresnel_warp, float fresnel_weft, + float spread_x_mult, float spread_y_mult, int pattern, float pattern_angle, + float warp_width_scale, float weft_width_scale, float thread_count_mult_u, + float thread_count_mult_v) BUILTIN; +closure color cloth_specular(normal N, color spec_col[4], float eta[4], int thread_pattern[4], + float pattern_weight[4], int current_thread, float brdf_interp, + float btf_interp, float uux, float vvx, float area_scaled, vector dPdu, + float eccentricity[4], float angle[4], float Kx[4], float Ky[4], + float Sx[4], float Sy[4]) BUILTIN; +closure color fakefur_diffuse(normal N, vector T, float fur_reflectivity, float fur_transmission, + float shadow_start, float shadow_end, float fur_attenuation, float fur_density, + float fur_avg_radius, float fur_length, float fur_shadow_fraction) BUILTIN; +closure color fakefur_specular(normal N, vector T, float offset, float exp, float fur_reflectivity, + float fur_transmission, float shadow_start, float shadow_end, + float fur_attenuation, float fur_density, float fur_avg_radius, + float fur_length, float fur_shadow_fraction) BUILTIN; + +closure color fakefur_skin(vector N, vector T, float fur_reflectivity, float fur_transmission, + float shadow_start, float shadow_end, float fur_attenuation, float fur_density, + float fur_avg_radius, float fur_length) BUILTIN; + + +closure color cloth(normal N, float s, float t, color diff_warp, color diff_weft, + color spec_warp, color spec_weft, float fresnel_warp, float fresnel_weft, + float spread_x_mult, float spread_y_mult, int pattern, float pattern_angle, + float warp_width_scale, float weft_width_scale, float thread_count_mult_u, + float thread_count_mult_v) +{ + + return cloth(N, s, t, Dx(s), Dx(t), Dy(s), Dy(t), area(P), dPdu, diff_warp, diff_weft, spec_warp, spec_weft, + fresnel_warp, fresnel_weft, spread_x_mult, spread_y_mult, pattern, pattern_angle, + warp_width_scale, weft_width_scale, thread_count_mult_u, thread_count_mult_v); +} + +closure color cloth(normal N, float s, float t, color diff_warp, color diff_weft, + color spec_warp, color spec_weft, float fresnel_warp, float fresnel_weft, + float spread_x_mult, float spread_y_mult, int pattern, float pattern_angle, + float warp_width_scale, float weft_width_scale, float thread_count_mult_u, + float thread_count_mult_v, string tok, string val) +{ + + return cloth(N, s, t, Dx(s), Dx(t), Dy(s), Dy(t), area(P), dPdu, diff_warp, diff_weft, spec_warp, spec_weft, + fresnel_warp, fresnel_weft, spread_x_mult, spread_y_mult, pattern, pattern_angle, + warp_width_scale, weft_width_scale, thread_count_mult_u, thread_count_mult_v, tok, val); +} + + // Renderer state -int raytype(string typename) BUILTIN; +int raytype (string typename) BUILTIN; +// the individual 'isFOOray' functions are deprecated +int iscameraray () { return raytype("camera"); } +int isdiffuseray () { return raytype("diffuse"); } +int isglossyray () { return raytype("glossy"); } +int isshadowray () { return raytype("shadow"); } +int getmatrix (string fromspace, string tospace, output matrix M) BUILTIN; +int getmatrix (string fromspace, output matrix M) { + return getmatrix (fromspace, "common", M); +} + + +// Miscellaneous + + + #undef BUILTIN #undef BUILTIN_DERIV @@ -476,4 +535,3 @@ int raytype(string typename) BUILTIN; #undef PERCOMP2F #endif /* CCL_STDOSL_H */ - diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h index 90746c385c7..075c68824e6 100644 --- a/intern/cycles/kernel/osl/osl_globals.h +++ b/intern/cycles/kernel/osl/osl_globals.h @@ -30,12 +30,15 @@ CCL_NAMESPACE_BEGIN +class OSLRenderServices; + struct OSLGlobals { /* use */ bool use; /* shading system */ OSL::ShadingSystem *ss; + OSLRenderServices *services; /* shader states */ vector surface_state; @@ -60,7 +63,7 @@ struct OSLGlobals { /* thread key for thread specific data lookup */ struct ThreadData { OSL::ShaderGlobals globals; - void *thread_info; + OSL::PerThreadInfo *thread_info; }; static tls_ptr(ThreadData, thread_data); diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index a1574d6e0db..a3f2c2ea369 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -160,6 +160,18 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to, fl return false; } +bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform) +{ + // XXX implementation + return true; +} + +bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from) +{ + // XXX implementation + return true; +} + bool OSLRenderServices::get_array_attribute(void *renderstate, bool derivatives, ustring object, TypeDesc type, ustring name, int index, void *val) @@ -297,137 +309,16 @@ bool OSLRenderServices::has_userdata(ustring name, TypeDesc type, void *renderst return false; /* never called by OSL */ } -void *OSLRenderServices::get_pointcloud_attr_query(ustring *attr_names, - TypeDesc *attr_types, int nattrs) +int OSLRenderServices::pointcloud_search(OSL::ShaderGlobals *sg, ustring filename, const OSL::Vec3 ¢er, + float radius, int max_points, bool sort, size_t *out_indices, float *out_distances, int derivs_offset) { -#ifdef WITH_PARTIO - m_attr_queries.push_back(AttrQuery()); - AttrQuery &query = m_attr_queries.back(); - - /* make space for what we need. the only reason to use - * std::vector is to skip the delete */ - query.attr_names.resize(nattrs); - query.attr_partio_types.resize(nattrs); - /* capacity will keep the length of the smallest array passed - * to the query. Just to prevent buffer overruns */ - query.capacity = -1; - - for (int i = 0; i < nattrs; ++i) { - query.attr_names[i] = attr_names[i]; - - TypeDesc element_type = attr_types[i].elementtype(); - - if (query.capacity < 0) - query.capacity = attr_types[i].numelements(); - else - query.capacity = min(query.capacity, (int)attr_types[i].numelements()); - - /* convert the OSL (OIIO) type to the equivalent Partio type so - * we can do a fast check at query time. */ - if (element_type == TypeDesc::TypeFloat) { - query.attr_partio_types[i] = Partio::FLOAT; - } - else if (element_type == TypeDesc::TypeInt) { - query.attr_partio_types[i] = Partio::INT; - } - else if (element_type == TypeDesc::TypeColor || element_type == TypeDesc::TypePoint || - element_type == TypeDesc::TypeVector || element_type == TypeDesc::TypeNormal) - { - query.attr_partio_types[i] = Partio::VECTOR; - } - else { - return NULL; /* report some error of unknown type */ - } - } - - /* this is valid until the end of RenderServices */ - return &query; -#else - return NULL; -#endif + return 0; } -#ifdef WITH_PARTIO -Partio::ParticlesData *OSLRenderServices::get_pointcloud(ustring filename) +int OSLRenderServices::pointcloud_get(ustring filename, size_t *indices, int count, + ustring attr_name, TypeDesc attr_type, void *out_data) { - return Partio::readCached(filename.c_str(), true); -} - -#endif - -int OSLRenderServices::pointcloud(ustring filename, const OSL::Vec3 ¢er, float radius, - int max_points, void *_attr_query, void **attr_outdata) -{ - /* todo: this code has never been tested, and most likely does not - * work. it's based on the example code in OSL */ - -#ifdef WITH_PARTIO - /* query Partio for this pointcloud lookup using cached attr_query */ - if (!_attr_query) - return 0; - - AttrQuery *attr_query = (AttrQuery *)_attr_query; - if (attr_query->capacity < max_points) - return 0; - - /* get the pointcloud entry for the given filename */ - Partio::ParticlesData *cloud = get_pointcloud(filename); - - /* now we have to look up all the attributes in the file. we can't do this - * before hand cause we never know what we are going to load. */ - int nattrs = attr_query->attr_names.size(); - Partio::ParticleAttribute *attr = (Partio::ParticleAttribute *)alloca(sizeof(Partio::ParticleAttribute) * nattrs); - - for (int i = 0; i < nattrs; ++i) { - /* special case attributes */ - if (attr_query->attr_names[i] == u_distance || attr_query->attr_names[i] == u_index) - continue; - - /* lookup the attribute by name*/ - if (!cloud->attributeInfo(attr_query->attr_names[i].c_str(), attr[i])) { - /* issue an error here and return, types don't match */ - Partio::endCachedAccess(cloud); - cloud->release(); - return 0; - } - } - - std::vector indices; - std::vector dist2; - - Partio::beginCachedAccess(cloud); - - /* finally, do the lookup */ - cloud->findNPoints((const float *)¢er, max_points, radius, indices, dist2); - int count = indices.size(); - - /* retrieve the attributes directly to user space */ - for (int j = 0; j < nattrs; ++j) { - /* special cases */ - if (attr_query->attr_names[j] == u_distance) { - for (int i = 0; i < count; ++i) - ((float *)attr_outdata[j])[i] = sqrtf(dist2[i]); - } - else if (attr_query->attr_names[j] == u_index) { - for (int i = 0; i < count; ++i) - ((int *)attr_outdata[j])[i] = indices[i]; - } - else { - /* note we make a single call per attribute, we don't loop over the - * points. Partio does it, so it is there that we have to care about - * performance */ - cloud->data(attr[j], count, &indices[0], true, attr_outdata[j]); - } - } - - Partio::endCachedAccess(cloud); - cloud->release(); - - return count; -#else - return 0; -#endif + return 0; } CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h index e637b53ab78..60ff463f033 100644 --- a/intern/cycles/kernel/osl/osl_services.h +++ b/intern/cycles/kernel/osl/osl_services.h @@ -30,10 +30,6 @@ #include #include -#ifdef WITH_PARTIO -#include -#endif - CCL_NAMESPACE_BEGIN class Object; @@ -53,8 +49,12 @@ public: bool get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time); bool get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time); + bool get_matrix(OSL::Matrix44 &result, ustring from, float time); bool get_inverse_matrix(OSL::Matrix44 &result, ustring to, float time); + + bool get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform); + bool get_matrix(OSL::Matrix44 &result, ustring from); bool get_array_attribute(void *renderstate, bool derivatives, ustring object, TypeDesc type, ustring name, @@ -65,36 +65,17 @@ public: bool get_userdata(bool derivatives, ustring name, TypeDesc type, void *renderstate, void *val); bool has_userdata(ustring name, TypeDesc type, void *renderstate); + + int pointcloud_search(OSL::ShaderGlobals *sg, ustring filename, const OSL::Vec3 ¢er, + float radius, int max_points, bool sort, size_t *out_indices, + float *out_distances, int derivs_offset); - void *get_pointcloud_attr_query(ustring *attr_names, - TypeDesc *attr_types, int nattrs); - int pointcloud(ustring filename, const OSL::Vec3 ¢er, float radius, - int max_points, void *attr_query, void **attr_outdata); + int pointcloud_get(ustring filename, size_t *indices, int count, ustring attr_name, + TypeDesc attr_type, void *out_data); private: KernelGlobals *kernel_globals; -#ifdef WITH_PARTIO - /* OSL gets pointers to this but its definition is private. - * right now it only caches the types already converted to - * Partio constants. this is what get_pointcloud_attr_query - * returns */ - struct AttrQuery { - /* names of the attributes to query */ - std::vector attr_names; - /* types as (enum Partio::ParticleAttributeType) of the - * attributes in the query */ - std::vector attr_partio_types; - /* for sanity checks, capacity of the output arrays */ - int capacity; - }; - - Partio::ParticlesData *get_pointcloud(ustring filename); - - /* keep a list so adding elements doesn't invalidate pointers */ - std::list m_attr_queries; -#endif - static ustring u_distance; static ustring u_index; static ustring u_camera; diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index d8d510a7c9b..345614c2868 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -36,25 +36,25 @@ tls_ptr(OSLGlobals::ThreadData, OSLGlobals::thread_data); void OSLShader::thread_init(KernelGlobals *kg) { - OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss; + OSL::ShadingSystem *ss = kg->osl.ss; OSLGlobals::ThreadData *tdata = new OSLGlobals::ThreadData(); memset(&tdata->globals, 0, sizeof(OSL::ShaderGlobals)); - tdata->thread_info = ssi->create_thread_info(); + tdata->thread_info = ss->create_thread_info(); tls_set(kg->osl.thread_data, tdata); - ((OSLRenderServices *)ssi->renderer())->thread_init(kg); + kg->osl.services->thread_init(kg); } void OSLShader::thread_free(KernelGlobals *kg) { - OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss; + OSL::ShadingSystem *ss = kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); - ssi->destroy_thread_info(tdata->thread_info); + ss->destroy_thread_info(tdata->thread_info); delete tdata; } @@ -123,7 +123,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, sc.weight = weight; switch (prim->category()) { - case ClosurePrimitive::BSDF: { + case OSL::ClosurePrimitive::BSDF: { if (sd->num_closure == MAX_CLOSURE) return; @@ -137,11 +137,9 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, /* sample weight */ float albedo = bsdf->albedo(TO_VEC3(sd->I)); float sample_weight = fabsf(average(weight)) * albedo; - float sample_sum = sd->osl_closure.bsdf_sample_sum + sample_weight; sc.sample_weight = sample_weight; sc.type = CLOSURE_BSDF_ID; - sd->osl_closure.bsdf_sample_sum = sample_sum; /* scattering flags */ if (scattering == OSL::Labels::DIFFUSE) @@ -155,17 +153,15 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, sd->closure[sd->num_closure++] = sc; break; } - case ClosurePrimitive::Emissive: { + case OSL::ClosurePrimitive::Emissive: { if (sd->num_closure == MAX_CLOSURE) return; /* sample weight */ float sample_weight = fabsf(average(weight)); - float sample_sum = sd->osl_closure.emissive_sample_sum + sample_weight; sc.sample_weight = sample_weight; sc.type = CLOSURE_EMISSION_ID; - sd->osl_closure.emissive_sample_sum = sample_sum; /* flag */ sd->flag |= SD_EMISSION; @@ -173,7 +169,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, sd->closure[sd->num_closure++] = sc; break; } - case ClosurePrimitive::Holdout: + case OSL::ClosurePrimitive::Holdout: if (sd->num_closure == MAX_CLOSURE) return; @@ -182,11 +178,11 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, sd->flag |= SD_HOLDOUT; sd->closure[sd->num_closure++] = sc; break; - case ClosurePrimitive::BSSRDF: - case ClosurePrimitive::Debug: + case OSL::ClosurePrimitive::BSSRDF: + case OSL::ClosurePrimitive::Debug: break; /* not implemented */ - case ClosurePrimitive::Background: - case ClosurePrimitive::Volume: + case OSL::ClosurePrimitive::Background: + case OSL::ClosurePrimitive::Volume: break; /* not relevant */ } } @@ -205,10 +201,10 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag) { /* gather pointers */ - OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss; + OSL::ShadingSystem *ss = kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); OSL::ShaderGlobals *globals = &tdata->globals; - OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info); + OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info); /* setup shader globals from shader data */ sd->osl_ctx = ctx; @@ -218,7 +214,7 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int int shader = sd->shader & SHADER_MASK; if (kg->osl.surface_state[shader]) - ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.surface_state[shader]), *globals); + ss->execute(*ctx, *(kg->osl.surface_state[shader]), *globals); /* flatten closure tree */ sd->num_closure = 0; @@ -263,10 +259,10 @@ static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure) float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag) { /* gather pointers */ - OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss; + OSL::ShadingSystem *ss = kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); OSL::ShaderGlobals *globals = &tdata->globals; - OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info); + OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info); /* setup shader globals from shader data */ sd->osl_ctx = ctx; @@ -274,7 +270,7 @@ float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_fl /* execute shader for this point */ if (kg->osl.background_state) - ctx->execute(OSL::pvt::ShadUseSurface, *kg->osl.background_state, *globals); + ss->execute(*ctx, *(kg->osl.background_state), *globals); /* return background color immediately */ if (globals->Ci) @@ -301,29 +297,27 @@ static void flatten_volume_closure_tree(ShaderData *sd, sc.weight = weight; switch (prim->category()) { - case ClosurePrimitive::Volume: { + case OSL::ClosurePrimitive::Volume: { if (sd->num_closure == MAX_CLOSURE) return; /* sample weight */ float sample_weight = fabsf(average(weight)); - float sample_sum = sd->osl_closure.volume_sample_sum + sample_weight; sc.sample_weight = sample_weight; sc.type = CLOSURE_VOLUME_ID; - sd->osl_closure.volume_sample_sum = sample_sum; /* add */ sd->closure[sd->num_closure++] = sc; break; } - case ClosurePrimitive::Holdout: - case ClosurePrimitive::Debug: + case OSL::ClosurePrimitive::Holdout: + case OSL::ClosurePrimitive::Debug: break; /* not implemented */ - case ClosurePrimitive::Background: - case ClosurePrimitive::BSDF: - case ClosurePrimitive::Emissive: - case ClosurePrimitive::BSSRDF: + case OSL::ClosurePrimitive::Background: + case OSL::ClosurePrimitive::BSDF: + case OSL::ClosurePrimitive::Emissive: + case OSL::ClosurePrimitive::BSSRDF: break; /* not relevant */ } } @@ -342,10 +336,10 @@ static void flatten_volume_closure_tree(ShaderData *sd, void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag) { /* gather pointers */ - OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss; + OSL::ShadingSystem *ss = kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); OSL::ShaderGlobals *globals = &tdata->globals; - OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info); + OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info); /* setup shader globals from shader data */ sd->osl_ctx = ctx; @@ -355,12 +349,7 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int int shader = sd->shader & SHADER_MASK; if (kg->osl.volume_state[shader]) - ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.volume_state[shader]), *globals); - - /* retrieve resulting closures */ - sd->osl_closure.volume_sample_sum = 0.0f; - sd->osl_closure.num_volume = 0; - sd->osl_closure.randb = randb; + ss->execute(*ctx, *(kg->osl.volume_state[shader]), *globals); if (globals->Ci) flatten_volume_closure_tree(sd, globals->Ci); @@ -371,10 +360,10 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) { /* gather pointers */ - OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss; + OSL::ShadingSystem *ss = kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); OSL::ShaderGlobals *globals = &tdata->globals; - OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info); + OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info); /* setup shader globals from shader data */ sd->osl_ctx = ctx; @@ -384,7 +373,7 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) int shader = sd->shader & SHADER_MASK; if (kg->osl.displacement_state[shader]) - ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.displacement_state[shader]), *globals); + ss->execute(*ctx, *(kg->osl.displacement_state[shader]), *globals); /* get back position */ sd->P = TO_FLOAT3(globals->P); @@ -392,10 +381,11 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) void OSLShader::release(KernelGlobals *kg, const ShaderData *sd) { - OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss; + OSL::ShadingSystem *ss = kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); + OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info); - ssi->release_context((OSL::pvt::ShadingContext *)sd->osl_ctx, tdata->thread_info); + ss->release_context(ctx); } /* BSDF Closure */ @@ -458,9 +448,8 @@ float3 OSLShader::emissive_eval(const ShaderData *sd, const ShaderClosure *sc) { OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure *)sc->prim; OSL::Color3 emissive_eval = emissive->eval(TO_VEC3(sd->Ng), TO_VEC3(sd->I)); - eval += TO_FLOAT3(emissive_eval); - return eval; + return TO_FLOAT3(emissive_eval); } /* Volume Closure */ diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h index 3cfce1d087a..22741bdb067 100644 --- a/intern/cycles/kernel/svm/svm_geometry.h +++ b/intern/cycles/kernel/svm/svm_geometry.h @@ -98,25 +98,47 @@ __device void svm_node_object_info(KernelGlobals *kg, ShaderData *sd, float *sta __device void svm_node_particle_info(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset) { - float data; - switch(type) { case NODE_INFO_PAR_INDEX: { uint particle_id = object_particle_id(kg, sd->object); - data = particle_index(kg, particle_id); - stack_store_float(stack, out_offset, data); + stack_store_float(stack, out_offset, particle_index(kg, particle_id)); break; } case NODE_INFO_PAR_AGE: { uint particle_id = object_particle_id(kg, sd->object); - data = particle_age(kg, particle_id); - stack_store_float(stack, out_offset, data); + stack_store_float(stack, out_offset, particle_age(kg, particle_id)); break; } case NODE_INFO_PAR_LIFETIME: { uint particle_id = object_particle_id(kg, sd->object); - data = particle_lifetime(kg, particle_id); - stack_store_float(stack, out_offset, data); + stack_store_float(stack, out_offset, particle_lifetime(kg, particle_id)); + break; + } + case NODE_INFO_PAR_LOCATION: { + uint particle_id = object_particle_id(kg, sd->object); + stack_store_float3(stack, out_offset, particle_location(kg, particle_id)); + break; + } + #if 0 /* XXX float4 currently not supported in SVM stack */ + case NODE_INFO_PAR_ROTATION: { + uint particle_id = object_particle_id(kg, sd->object); + stack_store_float4(stack, out_offset, particle_rotation(kg, particle_id)); + break; + } + #endif + case NODE_INFO_PAR_SIZE: { + uint particle_id = object_particle_id(kg, sd->object); + stack_store_float(stack, out_offset, particle_size(kg, particle_id)); + break; + } + case NODE_INFO_PAR_VELOCITY: { + uint particle_id = object_particle_id(kg, sd->object); + stack_store_float3(stack, out_offset, particle_velocity(kg, particle_id)); + break; + } + case NODE_INFO_PAR_ANGULAR_VELOCITY: { + uint particle_id = object_particle_id(kg, sd->object); + stack_store_float3(stack, out_offset, particle_angular_velocity(kg, particle_id)); break; } } diff --git a/intern/cycles/kernel/svm/svm_math.h b/intern/cycles/kernel/svm/svm_math.h index bc2f774097e..e39c7a4ba6c 100644 --- a/intern/cycles/kernel/svm/svm_math.h +++ b/intern/cycles/kernel/svm/svm_math.h @@ -108,6 +108,8 @@ __device float svm_math(NodeMath type, float Fac1, float Fac2) Fac = Fac1 < Fac2; else if(type == NODE_MATH_GREATER_THAN) Fac = Fac1 > Fac2; + else if(type == NODE_MATH_CLAMP) + Fac = clamp(Fac1, 0.0f, 1.0f); else Fac = 0.0f; diff --git a/intern/cycles/kernel/svm/svm_mix.h b/intern/cycles/kernel/svm/svm_mix.h index 6b455e713c2..888e4d9645e 100644 --- a/intern/cycles/kernel/svm/svm_mix.h +++ b/intern/cycles/kernel/svm/svm_mix.h @@ -276,6 +276,17 @@ __device float3 svm_mix_linear(float t, float3 col1, float3 col2) return outcol; } +__device float3 svm_mix_clamp(float3 col) +{ + float3 outcol = col; + + outcol.x = clamp(col.x, 0.0f, 1.0f); + outcol.y = clamp(col.y, 0.0f, 1.0f); + outcol.z = clamp(col.z, 0.0f, 1.0f); + + return outcol; +} + __device float3 svm_mix(NodeMix type, float fac, float3 c1, float3 c2) { float t = clamp(fac, 0.0f, 1.0f); @@ -299,6 +310,7 @@ __device float3 svm_mix(NodeMix type, float fac, float3 c1, float3 c2) case NODE_MIX_COLOR: return svm_mix_color(t, c1, c2); case NODE_MIX_SOFT: return svm_mix_soft(t, c1, c2); case NODE_MIX_LINEAR: return svm_mix_linear(t, c1, c2); + case NODE_MIX_CLAMP: return svm_mix_clamp(c1); } return make_float3(0.0f, 0.0f, 0.0f); diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index 854a708a988..fbaf253177d 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -29,7 +29,7 @@ __device_inline float3 svm_background_offset(KernelGlobals *kg) __device_inline float3 svm_world_to_ndc(KernelGlobals *kg, ShaderData *sd, float3 P) { if(kernel_data.cam.type != CAMERA_PANORAMA) { - if(sd->object != ~0) + if(sd->object == ~0) P += svm_background_offset(kg); Transform tfm = kernel_data.cam.worldtondc; diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index a577f8b12f7..c82eafc790a 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -118,7 +118,12 @@ typedef enum NodeObjectInfo { typedef enum NodeParticleInfo { NODE_INFO_PAR_INDEX, NODE_INFO_PAR_AGE, - NODE_INFO_PAR_LIFETIME + NODE_INFO_PAR_LIFETIME, + NODE_INFO_PAR_LOCATION, + NODE_INFO_PAR_ROTATION, + NODE_INFO_PAR_SIZE, + NODE_INFO_PAR_VELOCITY, + NODE_INFO_PAR_ANGULAR_VELOCITY } NodeParticleInfo; typedef enum NodeLightPath { @@ -165,7 +170,8 @@ typedef enum NodeMix { NODE_MIX_VAL, NODE_MIX_COLOR, NODE_MIX_SOFT, - NODE_MIX_LINEAR + NODE_MIX_LINEAR, + NODE_MIX_CLAMP /* used for the clamp UI option */ } NodeMix; typedef enum NodeMath { @@ -185,7 +191,8 @@ typedef enum NodeMath { NODE_MATH_MAXIMUM, NODE_MATH_ROUND, NODE_MATH_LESS_THAN, - NODE_MATH_GREATER_THAN + NODE_MATH_GREATER_THAN, + NODE_MATH_CLAMP /* used for the clamp UI option */ } NodeMath; typedef enum NodeVectorMath { diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt index 4d4fbfe6814..85b476e60d9 100644 --- a/intern/cycles/render/CMakeLists.txt +++ b/intern/cycles/render/CMakeLists.txt @@ -27,6 +27,7 @@ set(SRC nodes.cpp object.cpp osl.cpp + particles.cpp scene.cpp session.cpp shader.cpp @@ -51,6 +52,7 @@ set(SRC_HEADERS nodes.h object.h osl.h + particles.h scene.h session.h shader.h diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index ce715ad3893..20fbfa0cf27 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -55,6 +55,7 @@ ShaderNode::ShaderNode(const char *name_) name = name_; id = -1; bump = SHADER_BUMP_NONE; + special_type = SHADER_SPECIAL_TYPE_NONE; } ShaderNode::~ShaderNode() @@ -298,8 +299,8 @@ void ShaderGraph::copy_nodes(set& nodes, map& removed) { foreach(ShaderNode *node, nodes) { - ProxyNode *proxy = dynamic_cast(node); - if (proxy) { + if (node->special_type == SHADER_SPECIAL_TYPE_PROXY) { + ProxyNode *proxy = static_cast(node); ShaderInput *input = proxy->inputs[0]; ShaderOutput *output = proxy->outputs[0]; @@ -330,9 +331,8 @@ void ShaderGraph::remove_proxy_nodes(vector& removed) } /* remove useless mix closures nodes */ - MixClosureNode *mix = dynamic_cast(node); - - if(mix) { + if(node->special_type == SHADER_SPECIAL_TYPE_MIX_CLOSURE) { + MixClosureNode *mix = static_cast(node); if(mix->outputs[0]->links.size() && mix->inputs[1]->link == mix->inputs[2]->link) { ShaderOutput *output = mix->inputs[1]->link; vector inputs = mix->outputs[0]->links; diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index 91ec83aba21..c3b674d0f23 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -63,6 +63,17 @@ enum ShaderBump { SHADER_BUMP_DY }; +/* Identifiers for some special node types. + * + * The graph needs to identify these in the clean function. + * Cannot use dynamic_cast, as this is disabled for OSL. */ + +enum ShaderNodeSpecialType { + SHADER_SPECIAL_TYPE_NONE, + SHADER_SPECIAL_TYPE_PROXY, + SHADER_SPECIAL_TYPE_MIX_CLOSURE +}; + /* Enum * * Utility class for enum values. */ @@ -167,6 +178,8 @@ public: ustring name; /* name, not required to be unique */ int id; /* index in graph node array */ ShaderBump bump; /* for bump mapping utility */ + + ShaderNodeSpecialType special_type; /* special node type */ }; diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 9d221d56efb..6445c04257f 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -290,12 +290,12 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen device->tex_alloc("__light_distribution", dscene->light_distribution); } else { + dscene->light_distribution.clear(); + kintegrator->num_distribution = 0; + kintegrator->num_all_lights = 0; kintegrator->pdf_triangles = 0.0f; kintegrator->pdf_lights = 0.0f; - kintegrator->num_all_lights = 0; - - dscene->light_distribution.clear(); } } diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index b8678005438..da511b2d2f4 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1153,6 +1153,7 @@ ProxyNode::ProxyNode(ShaderSocketType from_, ShaderSocketType to_) { from = from_; to = to_; + special_type = SHADER_SPECIAL_TYPE_PROXY; add_input("Input", from); add_output("Output", to); @@ -1918,6 +1919,13 @@ ParticleInfoNode::ParticleInfoNode() add_output("Index", SHADER_SOCKET_FLOAT); add_output("Age", SHADER_SOCKET_FLOAT); add_output("Lifetime", SHADER_SOCKET_FLOAT); + add_output("Location", SHADER_SOCKET_POINT); + #if 0 /* not yet supported */ + add_output("Rotation", SHADER_SOCKET_QUATERNION); + #endif + add_output("Size", SHADER_SOCKET_FLOAT); + add_output("Velocity", SHADER_SOCKET_VECTOR); + add_output("Angular Velocity", SHADER_SOCKET_VECTOR); } void ParticleInfoNode::attributes(AttributeRequestSet *attributes) @@ -1928,6 +1936,18 @@ void ParticleInfoNode::attributes(AttributeRequestSet *attributes) attributes->add(ATTR_STD_PARTICLE); if(!output("Lifetime")->links.empty()) attributes->add(ATTR_STD_PARTICLE); + if(!output("Location")->links.empty()) + attributes->add(ATTR_STD_PARTICLE); + #if 0 /* not yet supported */ + if(!output("Rotation")->links.empty()) + attributes->add(ATTR_STD_PARTICLE); + #endif + if(!output("Size")->links.empty()) + attributes->add(ATTR_STD_PARTICLE); + if(!output("Velocity")->links.empty()) + attributes->add(ATTR_STD_PARTICLE); + if(!output("Angular Velocity")->links.empty()) + attributes->add(ATTR_STD_PARTICLE); ShaderNode::attributes(attributes); } @@ -1953,6 +1973,38 @@ void ParticleInfoNode::compile(SVMCompiler& compiler) compiler.stack_assign(out); compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LIFETIME, out->stack_offset); } + + out = output("Location"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LOCATION, out->stack_offset); + } + + #if 0 /* XXX Quaternion data is not yet supported by Cycles */ + out = output("Rotation"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_ROTATION, out->stack_offset); + } + #endif + + out = output("Size"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_SIZE, out->stack_offset); + } + + out = output("Velocity"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_VELOCITY, out->stack_offset); + } + + out = output("Angular Velocity"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_ANGULAR_VELOCITY, out->stack_offset); + } } void ParticleInfoNode::compile(OSLCompiler& compiler) @@ -2037,6 +2089,8 @@ void AddClosureNode::compile(OSLCompiler& compiler) MixClosureNode::MixClosureNode() : ShaderNode("mix_closure") { + special_type = SHADER_SPECIAL_TYPE_MIX_CLOSURE; + add_input("Fac", SHADER_SOCKET_FLOAT, 0.5f); add_input("Closure1", SHADER_SOCKET_CLOSURE); add_input("Closure2", SHADER_SOCKET_CLOSURE); @@ -2088,6 +2142,8 @@ MixNode::MixNode() { type = ustring("Mix"); + use_clamp = false; + add_input("Fac", SHADER_SOCKET_FLOAT, 0.5f); add_input("Color1", SHADER_SOCKET_COLOR); add_input("Color2", SHADER_SOCKET_COLOR); @@ -2136,11 +2192,17 @@ void MixNode::compile(SVMCompiler& compiler) compiler.add_node(NODE_MIX, fac_in->stack_offset, color1_in->stack_offset, color2_in->stack_offset); compiler.add_node(NODE_MIX, type_enum[type], color_out->stack_offset); + + if(use_clamp) { + compiler.add_node(NODE_MIX, 0, color_out->stack_offset); + compiler.add_node(NODE_MIX, NODE_MIX_CLAMP, color_out->stack_offset); + } } void MixNode::compile(OSLCompiler& compiler) { compiler.parameter("type", type); + compiler.parameter("Clamp", use_clamp); compiler.add(this, "node_mix"); } @@ -2466,7 +2528,7 @@ void LayerWeightNode::compile(SVMCompiler& compiler) void LayerWeightNode::compile(OSLCompiler& compiler) { - compiler.add(this, "node_layer_height"); + compiler.add(this, "node_blend_weight"); } /* Output */ @@ -2508,6 +2570,8 @@ MathNode::MathNode() { type = ustring("Add"); + use_clamp = false; + add_input("Value1", SHADER_SOCKET_FLOAT); add_input("Value2", SHADER_SOCKET_FLOAT); add_output("Value", SHADER_SOCKET_FLOAT); @@ -2552,11 +2616,17 @@ void MathNode::compile(SVMCompiler& compiler) compiler.add_node(NODE_MATH, type_enum[type], value1_in->stack_offset, value2_in->stack_offset); compiler.add_node(NODE_MATH, value_out->stack_offset); + + if(use_clamp) { + compiler.add_node(NODE_MATH, NODE_MATH_CLAMP, value_out->stack_offset); + compiler.add_node(NODE_MATH, value_out->stack_offset); + } } void MathNode::compile(OSLCompiler& compiler) { compiler.parameter("type", type); + compiler.parameter("Clamp", use_clamp); compiler.add(this, "node_math"); } diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index da5b90bfdda..82bead7e41a 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -340,6 +340,8 @@ class MixNode : public ShaderNode { public: SHADER_NODE_CLASS(MixNode) + bool use_clamp; + ustring type; static ShaderEnum type_enum; }; @@ -396,6 +398,8 @@ class MathNode : public ShaderNode { public: SHADER_NODE_CLASS(MathNode) + bool use_clamp; + ustring type; static ShaderEnum type_enum; }; diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 0fe227fd171..7389b239627 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -249,38 +249,6 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene device->tex_alloc("__object_flag", dscene->object_flag); } -void ObjectManager::device_update_particles(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) -{ - /* count particles. - * adds one dummy particle at the beginning to avoid invalid lookups, - * in case a shader uses particle info without actual particle data. - */ - int num_particles = 1; - foreach(Object *ob, scene->objects) - num_particles += ob->particles.size(); - - float4 *particles = dscene->particles.resize(PARTICLE_SIZE*num_particles); - - /* dummy particle */ - particles[0] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); - - int i = 1; - foreach(Object *ob, scene->objects) { - foreach(Particle &pa, ob->particles) { - /* pack in texture */ - int offset = i*PARTICLE_SIZE; - - particles[offset] = make_float4(pa.index, pa.age, pa.lifetime, 0.0f); - - i++; - - if(progress.get_cancel()) return; - } - } - - device->tex_alloc("__particles", dscene->particles); -} - void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) { if(!need_update) @@ -306,11 +274,6 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc if(progress.get_cancel()) return; - progress.set_status("Updating Objects", "Copying Particles to device"); - device_update_particles(device, dscene, scene, progress); - - if(progress.get_cancel()) return; - need_update = false; } @@ -321,9 +284,6 @@ void ObjectManager::device_free(Device *device, DeviceScene *dscene) device->tex_free(dscene->object_flag); dscene->object_flag.clear(); - - device->tex_free(dscene->particles); - dscene->particles.clear(); } void ObjectManager::apply_static_transforms(Scene *scene, Progress& progress) diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index 9b2f5bc8768..88677d79dff 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -35,12 +35,6 @@ struct Transform; /* Object */ -struct Particle { - int index; - float age; - float lifetime; -}; - class Object { public: Mesh *mesh; @@ -56,7 +50,6 @@ public: bool use_holdout; int particle_id; - vector particles; Object(); ~Object(); @@ -78,7 +71,6 @@ public: void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); - void device_update_particles(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_free(Device *device, DeviceScene *dscene); void tag_update(Scene *scene); diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 04af9b48280..d4c93c07e2f 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -101,8 +101,9 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene /* setup shader engine */ og->ss = ss; + og->services = services; int background_id = scene->shader_manager->get_shader_id(scene->default_background); - og->background_state = og->surface_state[background_id]; + og->background_state = og->surface_state[background_id & SHADER_MASK]; og->use = true; tls_create(OSLGlobals::ThreadData, og->thread_data); diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp new file mode 100644 index 00000000000..9f951d9673f --- /dev/null +++ b/intern/cycles/render/particles.cpp @@ -0,0 +1,123 @@ +/* + * 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 "particles.h" +#include "scene.h" + +#include "util_foreach.h" +#include "util_map.h" +#include "util_progress.h" +#include "util_vector.h" + +CCL_NAMESPACE_BEGIN + +/* Particle System */ + +ParticleSystem::ParticleSystem() +{ +} + +ParticleSystem::~ParticleSystem() +{ +} + +void ParticleSystem::tag_update(Scene *scene) +{ + scene->particle_system_manager->need_update = true; +} + +/* Particle System Manager */ + +ParticleSystemManager::ParticleSystemManager() +{ + need_update = true; +} + +ParticleSystemManager::~ParticleSystemManager() +{ +} + +void ParticleSystemManager::device_update_particles(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) +{ + /* count particles. + * adds one dummy particle at the beginning to avoid invalid lookups, + * in case a shader uses particle info without actual particle data. + */ + int num_particles = 1; + foreach(ParticleSystem *psys, scene->particle_systems) + num_particles += psys->particles.size(); + + float4 *particles = dscene->particles.resize(PARTICLE_SIZE*num_particles); + + /* dummy particle */ + particles[0] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + particles[1] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + particles[2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + particles[3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + particles[4] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + + int i = 1; + foreach(ParticleSystem *psys, scene->particle_systems) { + foreach(Particle &pa, psys->particles) { + /* pack in texture */ + int offset = i*PARTICLE_SIZE; + + particles[offset] = make_float4(pa.index, pa.age, pa.lifetime, pa.size); + particles[offset+1] = pa.rotation; + particles[offset+2] = make_float4(pa.location.x, pa.location.y, pa.location.z, pa.velocity.x); + particles[offset+3] = make_float4(pa.velocity.y, pa.velocity.z, pa.angular_velocity.x, pa.angular_velocity.y); + particles[offset+4] = make_float4(pa.angular_velocity.z, 0.0f, 0.0f, 0.0f); + + i++; + + if(progress.get_cancel()) return; + } + } + + device->tex_alloc("__particles", dscene->particles); +} + +void ParticleSystemManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) +{ + if(!need_update) + return; + + device_free(device, dscene); + + progress.set_status("Updating Particle Systems", "Copying Particles to device"); + device_update_particles(device, dscene, scene, progress); + + if(progress.get_cancel()) return; + + need_update = false; +} + +void ParticleSystemManager::device_free(Device *device, DeviceScene *dscene) +{ + device->tex_free(dscene->particles); + dscene->particles.clear(); +} + +void ParticleSystemManager::tag_update(Scene *scene) +{ + need_update = true; +} + +CCL_NAMESPACE_END + diff --git a/intern/cycles/render/particles.h b/intern/cycles/render/particles.h new file mode 100644 index 00000000000..afc8b2b2dcb --- /dev/null +++ b/intern/cycles/render/particles.h @@ -0,0 +1,74 @@ +/* + * 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 __PARTICLES_H__ +#define __PARTICLES_H__ + +#include "util_types.h" +#include "util_vector.h" + +CCL_NAMESPACE_BEGIN + +class Device; +class DeviceScene; +class Progress; +class Scene; + +/* Particle System */ + +struct Particle { + int index; + float age; + float lifetime; + float3 location; + float4 rotation; + float size; + float3 velocity; + float3 angular_velocity; +}; + +class ParticleSystem { +public: + ParticleSystem(); + ~ParticleSystem(); + + void tag_update(Scene *scene); + + vector particles; +}; + +/* ParticleSystem Manager */ + +class ParticleSystemManager { +public: + bool need_update; + + ParticleSystemManager(); + ~ParticleSystemManager(); + + void device_update_particles(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); + void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); + void device_free(Device *device, DeviceScene *dscene); + + void tag_update(Scene *scene); +}; + +CCL_NAMESPACE_END + +#endif /* __PARTICLES_H__ */ + diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 33ebd7a59ef..071338d49c2 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -28,6 +28,7 @@ #include "shader.h" #include "mesh.h" #include "object.h" +#include "particles.h" #include "scene.h" #include "svm.h" #include "osl.h" @@ -53,6 +54,7 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_) integrator = new Integrator(); image_manager = new ImageManager(); shader_manager = ShaderManager::create(this); + particle_system_manager = new ParticleSystemManager(); if (device_info_.type == DEVICE_CPU) image_manager->set_extended_image_limits(); @@ -95,9 +97,14 @@ Scene::~Scene() delete o; foreach(Light *l, lights) delete l; + foreach(ParticleSystem *p, particle_systems) + delete p; if(device) image_manager->device_free(device, &dscene); delete image_manager; + + if(device) particle_system_manager->device_free(device, &dscene); + delete particle_system_manager; } void Scene::device_update(Device *device_, Progress& progress) @@ -152,6 +159,11 @@ void Scene::device_update(Device *device_, Progress& progress) if(progress.get_cancel()) return; + progress.set_status("Updating Particle Systems"); + particle_system_manager->device_update(device, &dscene, this, progress); + + if(progress.get_cancel()) return; + progress.set_status("Updating Filter"); filter->device_update(device, &dscene); @@ -213,7 +225,8 @@ bool Scene::need_reset() || light_manager->need_update || filter->need_update || integrator->need_update - || shader_manager->need_update); + || shader_manager->need_update + || particle_system_manager->need_update); } CCL_NAMESPACE_END diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 1a9540b319d..f6c1ef44146 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -47,6 +47,8 @@ class Mesh; class MeshManager; class Object; class ObjectManager; +class ParticleSystemManager; +class ParticleSystem; class Shader; class ShaderManager; class Progress; @@ -155,6 +157,7 @@ public: vector meshes; vector shaders; vector lights; + vector particle_systems; /* data managers */ ImageManager *image_manager; @@ -162,6 +165,7 @@ public: ShaderManager *shader_manager; MeshManager *mesh_manager; ObjectManager *object_manager; + ParticleSystemManager *particle_system_manager; /* default shaders */ int default_surface; diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.cpp b/intern/ghost/intern/GHOST_DropTargetWin32.cpp index 4142b19f21d..89e9a91b34c 100644 --- a/intern/ghost/intern/GHOST_DropTargetWin32.cpp +++ b/intern/ghost/intern/GHOST_DropTargetWin32.cpp @@ -51,14 +51,10 @@ GHOST_DropTargetWin32::GHOST_DropTargetWin32(GHOST_WindowWin32 *window, GHOST_Sy m_cRef = 1; m_hWnd = window->getHWND(); m_draggedObjectType = GHOST_kDragnDropTypeUnknown; - - // register our window as drop target - ::RegisterDragDrop(m_hWnd, this); } GHOST_DropTargetWin32::~GHOST_DropTargetWin32() { - ::RevokeDragDrop(m_hWnd); } diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 6c201c24c3d..52ebaf02404 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -724,7 +724,7 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINP int r; GetKeyboardState((PBYTE)state); - if (r = ToUnicodeEx(vk, 0, state, utf16, 2, 0, system->m_keylayout)) { + if ((r = ToUnicodeEx(vk, 0, state, utf16, 2, 0, system->m_keylayout))) { if ((r > 0 && r < 3)) { utf16[r] = 0; conv_utf_16_to_8(utf16, utf8_char, 6); diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 3a6e646de11..71a9db349ee 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -271,6 +271,10 @@ GHOST_WindowWin32::GHOST_WindowWin32( // Register this window as a droptarget. Requires m_hWnd to be valid. // Note that OleInitialize(0) has to be called prior to this. Done in GHOST_SystemWin32. m_dropTarget = new GHOST_DropTargetWin32(this, m_system); + if (m_dropTarget) { + ::RegisterDragDrop(m_hWnd, m_dropTarget); + } + // Store a pointer to this class in the window structure ::SetWindowLongPtr(m_hWnd, GWL_USERDATA, (LONG_PTR) this); @@ -415,7 +419,13 @@ GHOST_WindowWin32::~GHOST_WindowWin32() m_hDC = 0; } if (m_hWnd) { - m_dropTarget->Release(); // frees itself. + if (m_dropTarget) { + // Disable DragDrop + RevokeDragDrop(m_hWnd); + // Release our reference of the DropTarget and it will delete itself eventually. + m_dropTarget->Release(); + } + ::DestroyWindow(m_hWnd); m_hWnd = 0; } diff --git a/intern/guardedalloc/intern/mmap_win.c b/intern/guardedalloc/intern/mmap_win.c index a133f92fec4..ab50edb811e 100644 --- a/intern/guardedalloc/intern/mmap_win.c +++ b/intern/guardedalloc/intern/mmap_win.c @@ -44,7 +44,7 @@ #define FILE_MAP_EXECUTE 0x0020 #endif -/* copied from BKE_utildefines.h ugh */ +/* copied from BLI_utildefines.h, ugh */ #ifdef __GNUC__ # define UNUSED(x) UNUSED_ ## x __attribute__((__unused__)) #else diff --git a/intern/opennl/intern/opennl.c b/intern/opennl/intern/opennl.c index 20b4c0a6681..71809cc7480 100644 --- a/intern/opennl/intern/opennl.c +++ b/intern/opennl/intern/opennl.c @@ -569,6 +569,8 @@ void nlDeleteContext(NLContext context_in) { __NL_DELETE(context->variable[i].a); } } + + __NL_DELETE_ARRAY(context->variable); } if(context->alloc_b) { __NL_DELETE_ARRAY(context->b); diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py index 62844d11443..35b496b6dd0 100644 --- a/release/scripts/startup/bl_operators/object_quick_effects.py +++ b/release/scripts/startup/bl_operators/object_quick_effects.py @@ -510,6 +510,6 @@ class QuickFluid(Operator): mat.raytrace_transparency.depth = 4 if self.start_baking: - bpy.ops.fluid.bake() + bpy.ops.fluid.bake('INVOKE_DEFAULT') return {'FINISHED'} diff --git a/source/blender/blenfont/intern/blf_dir.c b/source/blender/blenfont/intern/blf_dir.c index da916067302..b6a98faa48c 100644 --- a/source/blender/blenfont/intern/blf_dir.c +++ b/source/blender/blenfont/intern/blf_dir.c @@ -41,8 +41,6 @@ #include "DNA_vec_types.h" -#include "BKE_utildefines.h" - #include "BLI_fileops.h" #include "BLI_listbase.h" #include "BLI_path_util.h" diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 64512dcaac8..fa9223ba6e2 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -698,6 +698,7 @@ void DM_init_origspace(DerivedMesh *dm); #ifndef NDEBUG char *DM_debug_info(DerivedMesh *dm); void DM_debug_print(DerivedMesh *dm); +void DM_debug_print_cdlayers(CustomData *cdata); #endif #endif diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h index acb9234b2d4..d1908fe7a3a 100644 --- a/source/blender/blenkernel/BKE_anim.h +++ b/source/blender/blenkernel/BKE_anim.h @@ -60,7 +60,6 @@ void animviz_calc_motionpaths(struct Scene *scene, ListBase *targets); void free_path(struct Path *path); void calc_curvepath(struct Object *ob); -int interval_test(int min, int max, int p1, int cycl); int where_on_path(struct Object *ob, float ctime, float vec[4], float dir[3], float quat[4], float *radius, float *weight); /* ---------------------------------------------------- */ diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index 0ed2db2aad2..63f5ec59a0b 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -15,13 +15,6 @@ * 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * * ***** END GPL LICENSE BLOCK ***** */ @@ -39,48 +32,7 @@ extern "C" { #endif -/* these values need to be hardcoded in structs, dna does not recognize defines */ -/* also defined in DNA_space_types.h */ -#ifndef FILE_MAXDIR -#define FILE_MAXDIR 768 -#define FILE_MAXFILE 256 -#define FILE_MAX 1024 -#endif - -/* this weirdo pops up in two places ... */ -#if !defined(WIN32) -# ifndef O_BINARY -# define O_BINARY 0 -# endif -#endif - -/* INTEGER CODES */ -#ifdef __BIG_ENDIAN__ -/* Big Endian */ -# define MAKE_ID(a, b, c, d) ( (int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d) ) -#else -/* Little Endian */ -# define MAKE_ID(a, b, c, d) ( (int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a) ) -#endif - -#define DATA MAKE_ID('D', 'A', 'T', 'A') -#define GLOB MAKE_ID('G', 'L', 'O', 'B') - -#define DNA1 MAKE_ID('D', 'N', 'A', '1') -#define TEST MAKE_ID('T', 'E', 'S', 'T') /* used as preview between 'REND' and 'GLOB' */ -#define REND MAKE_ID('R', 'E', 'N', 'D') -#define USER MAKE_ID('U', 'S', 'E', 'R') - -#define ENDB MAKE_ID('E', 'N', 'D', 'B') - -/* Bit operations */ -#define BTST(a, b) ( ( (a) & 1 << (b) ) != 0) -#define BNTST(a, b) ( ( (a) & 1 << (b) ) == 0) -#define BTST2(a, b, c) (BTST( (a), (b) ) || BTST( (a), (c) ) ) -#define BSET(a, b) ( (a) | 1 << (b) ) -#define BCLR(a, b) ( (a) & ~(1 << (b)) ) -/* bit-row */ -#define BROW(min, max) (((max) >= 31 ? 0xFFFFFFFF : (1 << (max + 1)) - 1) - ((min) ? ((1 << (min)) - 1) : 0) ) +/* currently unused but we may want to add macros here for BKE later */ #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index a29484638c0..1aa54307841 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -3187,4 +3187,25 @@ void DM_debug_print(DerivedMesh *dm) MEM_freeN(str); } +void DM_debug_print_cdlayers(CustomData *data) +{ + int i; + CustomDataLayer *layer; + + printf("{\n"); + + for (i = 0, layer = data->layers; i < data->totlayer; i++, layer++) { + + const char *name = CustomData_layertype_name(layer->type); + const int size = CustomData_sizeof(layer->type); + const char *structname; + int structnum; + CustomData_file_write_info(layer->type, &structname, &structnum); + printf(" dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n", + name, structname, layer->type, (void *)layer->data, size, (int)(MEM_allocN_len(layer->data) / size)); + } + + printf("}\n"); +} + #endif /* NDEBUG */ diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 9b4f0a31e28..f9954ff1dd0 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -63,7 +63,6 @@ #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_scene.h" -#include "BKE_utildefines.h" #include "BKE_tessmesh.h" #include "BKE_depsgraph.h" #include "BKE_anim.h" @@ -494,36 +493,42 @@ void calc_curvepath(Object *ob) /* in a path vertices are with equal differences: path->len = number of verts */ /* NOW WITH BEVELCURVE!!! */ - if (ob == NULL || ob->type != OB_CURVE) return; + if (ob == NULL || ob->type != OB_CURVE) { + return; + } cu = ob->data; - nurbs = BKE_curve_nurbs_get(cu); - nu = nurbs->first; - if (cu->path) free_path(cu->path); cu->path = NULL; + /* weak! can only use first curve */ bl = cu->bev.first; - if (bl == NULL || !bl->nr) return; + if (bl == NULL || !bl->nr) { + return; + } + + nurbs = BKE_curve_nurbs_get(cu); + nu = nurbs->first; cu->path = path = MEM_callocN(sizeof(Path), "calc_curvepath"); /* if POLY: last vertice != first vertice */ cycl = (bl->poly != -1); - if (cycl) tot = bl->nr; - else tot = bl->nr - 1; + tot = cycl ? bl->nr : bl->nr - 1; path->len = tot + 1; /* exception: vector handle paths and polygon paths should be subdivided at least a factor resolu */ - if (path->len < nu->resolu * SEGMENTSU(nu)) path->len = nu->resolu * SEGMENTSU(nu); + if (path->len < nu->resolu * SEGMENTSU(nu)) { + path->len = nu->resolu * SEGMENTSU(nu); + } dist = (float *)MEM_mallocN((tot + 1) * 4, "calcpathdist"); /* all lengths in *dist */ bevp = bevpfirst = (BevPoint *)(bl + 1); fp = dist; - *fp = 0; + *fp = 0.0f; for (a = 0; a < tot; a++) { fp++; if (cycl && a == tot - 1) @@ -558,19 +563,16 @@ void calc_curvepath(Object *ob) fp++; if (bevp < bevplast) bevp++; bevpn = bevp + 1; - if (bevpn > bevplast) { - if (cycl) bevpn = bevpfirst; - else bevpn = bevplast; + if (UNLIKELY(bevpn > bevplast)) { + bevpn = cycl ? bevpfirst : bevplast; } } - fac1 = *(fp) - *(fp - 1); - fac2 = *(fp) - d; - fac1 = fac2 / fac1; + fac1 = (*(fp) - d) / (*(fp) - *(fp - 1)); fac2 = 1.0f - fac1; - + interp_v3_v3v3(pp->vec, bevp->vec, bevpn->vec, fac2); - pp->vec[3] = fac1 * bevp->alfa + fac2 * bevpn->alfa; + pp->vec[3] = fac1 * bevp->alfa + fac2 * bevpn->alfa; pp->radius = fac1 * bevp->radius + fac2 * bevpn->radius; pp->weight = fac1 * bevp->weight + fac2 * bevpn->weight; interp_qt_qtqt(pp->quat, bevp->quat, bevpn->quat, fac2); @@ -582,18 +584,14 @@ void calc_curvepath(Object *ob) MEM_freeN(dist); } - -/* is this only used internally?*/ -int interval_test(int min, int max, int p1, int cycl) +static int interval_test(const int min, const int max, int p1, const int cycl) { if (cycl) { - if (p1 < min) - p1 = ((p1 - min) % (max - min + 1)) + max + 1; - else if (p1 > max) - p1 = ((p1 - min) % (max - min + 1)) + min; + if (p1 < min) p1 = ((p1 - min) % (max - min + 1)) + max + 1; + else if (p1 > max) p1 = ((p1 - min) % (max - min + 1)) + min; } else { - if (p1 < min) p1 = min; + if (p1 < min) p1 = min; else if (p1 > max) p1 = max; } return p1; diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index a4bf7bd9720..6a3dae93639 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -59,7 +59,6 @@ #include "BKE_main.h" #include "BKE_library.h" #include "BKE_report.h" -#include "BKE_utildefines.h" #include "RNA_access.h" @@ -621,15 +620,30 @@ static char *rna_path_rename_fix(ID *owner_id, const char *prefix, const char *o } /* Check RNA-Paths for a list of F-Curves */ -static void fcurves_path_rename_fix(ID *owner_id, const char *prefix, char *oldName, char *newName, ListBase *curves, int verify_paths) +static void fcurves_path_rename_fix(ID *owner_id, const char *prefix, const char *oldName, const char *newName, + const char *oldKey, const char *newKey, ListBase *curves, int verify_paths) { FCurve *fcu; /* we need to check every curve... */ for (fcu = curves->first; fcu; fcu = fcu->next) { - /* firstly, handle the F-Curve's own path */ - if (fcu->rna_path) - fcu->rna_path = rna_path_rename_fix(owner_id, prefix, oldName, newName, fcu->rna_path, verify_paths); + if (fcu->rna_path) { + char *old_path = fcu->rna_path; + + /* firstly, handle the F-Curve's own path */ + fcu->rna_path = rna_path_rename_fix(owner_id, prefix, oldKey, newKey, fcu->rna_path, verify_paths); + + /* if path changed and the F-Curve is grouped, check if its group also needs renaming + * (i.e. F-Curve is first of a bone's F-Curves; hence renaming this should also trigger rename) + */ + if (fcu->rna_path != old_path) { + bActionGroup *agrp = fcu->grp; + + if ((agrp) && strcmp(oldName, agrp->name)==0) { + BLI_strncpy(agrp->name, newName, sizeof(agrp->name)); + } + } + } } } @@ -675,7 +689,8 @@ static void drivers_path_rename_fix(ID *owner_id, ID *ref_id, const char *prefix } /* Fix all RNA-Paths for Actions linked to NLA Strips */ -static void nlastrips_path_rename_fix(ID *owner_id, const char *prefix, char *oldName, char *newName, ListBase *strips, int verify_paths) +static void nlastrips_path_rename_fix(ID *owner_id, const char *prefix, const char *oldName, const char *newName, + const char *oldKey, const char *newKey, ListBase *strips, int verify_paths) { NlaStrip *strip; @@ -683,11 +698,11 @@ static void nlastrips_path_rename_fix(ID *owner_id, const char *prefix, char *ol for (strip = strips->first; strip; strip = strip->next) { /* fix strip's action */ if (strip->act) - fcurves_path_rename_fix(owner_id, prefix, oldName, newName, &strip->act->curves, verify_paths); + fcurves_path_rename_fix(owner_id, prefix, oldName, newName, oldKey, newKey, &strip->act->curves, verify_paths); /* ignore own F-Curves, since those are local... */ /* check sub-strips (if metas) */ - nlastrips_path_rename_fix(owner_id, prefix, oldName, newName, &strip->strips, verify_paths); + nlastrips_path_rename_fix(owner_id, prefix, oldName, newName, oldKey, newKey, &strip->strips, verify_paths); } } @@ -717,16 +732,16 @@ void BKE_animdata_fix_paths_rename(ID *owner_id, AnimData *adt, ID *ref_id, cons /* Active action and temp action */ if (adt->action) - fcurves_path_rename_fix(owner_id, prefix, oldN, newN, &adt->action->curves, verify_paths); + fcurves_path_rename_fix(owner_id, prefix, oldName, newName, oldN, newN, &adt->action->curves, verify_paths); if (adt->tmpact) - fcurves_path_rename_fix(owner_id, prefix, oldN, newN, &adt->tmpact->curves, verify_paths); + fcurves_path_rename_fix(owner_id, prefix, oldName, newName, oldN, newN, &adt->tmpact->curves, verify_paths); /* Drivers - Drivers are really F-Curves */ drivers_path_rename_fix(owner_id, ref_id, prefix, oldName, newName, oldN, newN, &adt->drivers, verify_paths); /* NLA Data - Animation Data for Strips */ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) - nlastrips_path_rename_fix(owner_id, prefix, oldN, newN, &nlt->strips, verify_paths); + nlastrips_path_rename_fix(owner_id, prefix, oldName, newName, oldN, newN, &nlt->strips, verify_paths); /* free the temp names */ MEM_freeN(oldN); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 04585791135..aa834ff131b 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1551,7 +1551,7 @@ void BKE_armature_where_is(bArmature *arm) static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected) { bPose *pose = ob->pose, *frompose = from->pose; - bPoseChannel *pchan, *pchanp, pchanw; + bPoseChannel *pchan, *pchanp; bConstraint *con; int error = 0; @@ -1587,31 +1587,32 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { pchanp = BKE_pose_channel_find_name(frompose, pchan->name); - + if (UNLIKELY(pchanp == NULL)) { /* happens for proxies that become invalid because of a missing link * for regulat cases it shouldn't happen at all */ } else if (pchan->bone->layer & layer_protected) { ListBase proxylocal_constraints = {NULL, NULL}; - + bPoseChannel pchanw = {NULL}; + /* copy posechannel to temp, but restore important pointers */ pchanw = *pchanp; pchanw.prev = pchan->prev; pchanw.next = pchan->next; pchanw.parent = pchan->parent; pchanw.child = pchan->child; - + /* this is freed so copy a copy, else undo crashes */ if (pchanw.prop) { pchanw.prop = IDP_CopyProperty(pchanw.prop); - + /* use the values from the the existing props */ if (pchan->prop) { IDP_SyncGroupValues(pchanw.prop, pchan->prop); } } - + /* constraints - proxy constraints are flushed... local ones are added after * 1. extract constraints not from proxy (CONSTRAINT_PROXY_LOCAL) from pchan's constraints * 2. copy proxy-pchan's constraints on-to new @@ -1622,30 +1623,30 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected extract_proxylocal_constraints(&proxylocal_constraints, &pchan->constraints); copy_constraints(&pchanw.constraints, &pchanp->constraints, FALSE); BLI_movelisttolist(&pchanw.constraints, &proxylocal_constraints); - + /* constraints - set target ob pointer to own object */ for (con = pchanw.constraints.first; con; con = con->next) { bConstraintTypeInfo *cti = constraint_get_typeinfo(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; - + if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(con, &targets); - + for (ct = targets.first; ct; ct = ct->next) { if (ct->tar == from) ct->tar = ob; } - + if (cti->flush_constraint_targets) cti->flush_constraint_targets(con, &targets, 0); } } - + /* free stuff from current channel */ BKE_pose_channel_free(pchan); - - /* the final copy */ + + /* copy data in temp back over to the cleaned-out (but still allocated) original channel */ *pchan = pchanw; } else { diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 06ba0b47587..02ce3a36b14 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -80,13 +80,10 @@ #include "BKE_sound.h" #include "RE_pipeline.h" - #include "BLO_undofile.h" #include "BLO_readfile.h" #include "BLO_writefile.h" -#include "BKE_utildefines.h" - #include "RNA_access.h" #include "WM_api.h" // XXXXX BAD, very BAD dependency (bad level call) - remove asap, elubie diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 881caec8a58..b176ed429f8 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -50,7 +50,6 @@ #include "BKE_global.h" #include "BKE_mesh.h" #include "BKE_paint.h" -#include "BKE_utildefines.h" #include "BKE_tessmesh.h" #include "BKE_curve.h" diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 00130dd3583..391891d3985 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -4514,7 +4514,7 @@ static void con_relink_id_cb(bConstraint *UNUSED(con), ID **idpoin, short UNUSED * since we've got the actual ID block, let's just inline this * code. * - * See ID_NEW(a) in BKE_utildefines.h + * See ID_NEW(a) in DNA_ID.h */ if ((*idpoin) && (*idpoin)->newid) (*idpoin) = (void *)(*idpoin)->newid; diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index a00bea38e51..342ee5bba41 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -51,7 +51,6 @@ #include "BLI_mempool.h" #include "BLI_utildefines.h" -#include "BKE_utildefines.h" #include "BKE_customdata.h" #include "BKE_customdata_file.h" #include "BKE_global.h" diff --git a/source/blender/blenkernel/intern/customdata_file.c b/source/blender/blenkernel/intern/customdata_file.c index 71801c4729f..78449879f72 100644 --- a/source/blender/blenkernel/intern/customdata_file.c +++ b/source/blender/blenkernel/intern/customdata_file.c @@ -32,6 +32,7 @@ #include "BLI_fileops.h" #include "BLI_string.h" #include "BLI_utildefines.h" +#include "BLI_endian_switch.h" #include "BKE_customdata_file.h" #include "BKE_global.h" @@ -165,9 +166,9 @@ static int cdf_read_header(CDataFile *cdf) header->endian = cdf_endian(); if (cdf->switchendian) { - SWITCH_INT(header->type); - SWITCH_INT(header->totlayer); - SWITCH_INT(header->structbytes); + BLI_endian_switch_int32(&header->type); + BLI_endian_switch_int32(&header->totlayer); + BLI_endian_switch_int32(&header->structbytes); } if (!ELEM(header->type, CDF_TYPE_IMAGE, CDF_TYPE_MESH)) @@ -185,10 +186,10 @@ static int cdf_read_header(CDataFile *cdf) return 0; if (cdf->switchendian) { - SWITCH_INT(image->width); - SWITCH_INT(image->height); - SWITCH_INT(image->tile_size); - SWITCH_INT(image->structbytes); + BLI_endian_switch_int32(&image->width); + BLI_endian_switch_int32(&image->height); + BLI_endian_switch_int32(&image->tile_size); + BLI_endian_switch_int32(&image->structbytes); } offset += image->structbytes; @@ -200,7 +201,7 @@ static int cdf_read_header(CDataFile *cdf) return 0; if (cdf->switchendian) - SWITCH_INT(mesh->structbytes); + BLI_endian_switch_int32(&mesh->structbytes); offset += mesh->structbytes; mesh->structbytes = sizeof(CDataFileMeshHeader); @@ -219,10 +220,10 @@ static int cdf_read_header(CDataFile *cdf) return 0; if (cdf->switchendian) { - SWITCH_INT(layer->type); - SWITCH_INT(layer->datatype); - SWITCH_INT64(layer->datasize); - SWITCH_INT(layer->structbytes); + BLI_endian_switch_int32(&layer->type); + BLI_endian_switch_int32(&layer->datatype); + BLI_endian_switch_uint64(&layer->datasize); + BLI_endian_switch_int32(&layer->structbytes); } if (layer->datatype != CDF_DATA_FLOAT) @@ -317,20 +318,13 @@ int cdf_read_layer(CDataFile *cdf, CDataFileLayer *blay) int cdf_read_data(CDataFile *cdf, unsigned int size, void *data) { - float *fdata; - unsigned int a; - /* read data */ if (!fread(data, size, 1, cdf->readf)) return 0; /* switch endian if necessary */ if (cdf->switchendian) { - fdata = data; - - for (a = 0; a < size / sizeof(float); a++) { - SWITCH_INT(fdata[a]); - } + BLI_endian_switch_float_array(data, size / sizeof(float)); } return 1; diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 1b53f8980cb..b8d5294eabc 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -75,7 +75,6 @@ #include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_tracking.h" -#include "BKE_utildefines.h" #include "depsgraph_private.h" diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 53c12d32bc1..b78ab9b28cd 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -55,7 +55,6 @@ #include "BKE_curve.h" #include "BKE_global.h" #include "BKE_object.h" -#include "BKE_utildefines.h" #include "RNA_access.h" diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 0ffd68c9079..8b35974ea62 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -50,7 +50,6 @@ #include "DNA_scene_types.h" #include "DNA_object_types.h" -#include "BKE_utildefines.h" #include "BKE_packedFile.h" #include "BKE_library.h" #include "BKE_font.h" diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 7456f9aab8b..8229df28ab8 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -293,18 +293,6 @@ static IDProperty *IDP_CopyArray(IDProperty *prop) return newp; } -/*taken from readfile.c*/ -#define SWITCH_LONGINT(a) { \ - char s_i, *p_i; \ - p_i = (char *)& (a); \ - s_i = p_i[0]; p_i[0] = p_i[7]; p_i[7] = s_i; \ - s_i = p_i[1]; p_i[1] = p_i[6]; p_i[6] = s_i; \ - s_i = p_i[2]; p_i[2] = p_i[5]; p_i[5] = s_i; \ - s_i = p_i[3]; p_i[3] = p_i[4]; p_i[4] = s_i; \ - } (void)0 - - - /* ---------- String Type ------------ */ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen) { diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 6d0a67f520f..987963273bb 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -81,7 +81,6 @@ #include "BKE_scene.h" #include "BKE_node.h" #include "BKE_sequencer.h" /* seq_foreground_frame_get() */ -#include "BKE_utildefines.h" #include "BLF_api.h" diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 9f770e0a9a7..f099a79b520 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -107,7 +107,6 @@ #include "BKE_gpencil.h" #include "BKE_fcurve.h" #include "BKE_speaker.h" -#include "BKE_utildefines.h" #include "BKE_movieclip.h" #include "BKE_mask.h" diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c index 065dc38c81e..4a8601df0b8 100644 --- a/source/blender/blenkernel/intern/mask_evaluate.c +++ b/source/blender/blenkernel/intern/mask_evaluate.c @@ -61,7 +61,6 @@ #include "BKE_sequencer.h" #include "BKE_tracking.h" #include "BKE_movieclip.h" -#include "BKE_utildefines.h" unsigned int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height) diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index eebcf12a799..a4fec1c0de4 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -157,7 +157,7 @@ struct pgn_elements { /* Forward declarations */ static int vertid(const CORNER *c1, const CORNER *c2, PROCESS *p, MetaBall *mb); -static int setcenter(CENTERLIST *table[], int i, int j, int k); +static int setcenter(CENTERLIST *table[], const int i, const int j, const int k); static CORNER *setcorner(PROCESS *p, int i, int j, int k); static void converge(const float p1[3], const float p2[3], float v1, float v2, float (*function)(float, float, float), float p[3], MetaBall *mb, int f); diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 50628ac857a..aa7388abd58 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -70,7 +70,6 @@ #include "BKE_library.h" #include "BKE_global.h" #include "BKE_main.h" -#include "BKE_utildefines.h" #include "BKE_movieclip.h" #include "BKE_image.h" /* openanim */ #include "BKE_tracking.h" diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 52b1e1b869c..ade418e409f 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -58,8 +58,6 @@ #include "BKE_library.h" #include "BKE_main.h" #include "BKE_node.h" -#include "BKE_utildefines.h" -#include "BKE_utildefines.h" #include "RNA_access.h" diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 66b0cff691e..b862a824d50 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -37,8 +37,6 @@ #include "BKE_image.h" #include "BKE_ocean.h" -#include "BKE_utildefines.h" - #include "BKE_global.h" // XXX TESTING #include "BLI_math_base.h" diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 9787a5025f7..03342d0f6d1 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -57,7 +57,6 @@ #include "BKE_packedFile.h" #include "BKE_report.h" #include "BKE_sound.h" -#include "BKE_utildefines.h" #ifdef _WIN32 #define open _open diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 1588ec10b55..5e12b15a658 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -69,7 +69,6 @@ #include "BKE_scene.h" #include "BKE_smoke.h" #include "BKE_softbody.h" -#include "BKE_utildefines.h" #include "BIK_api.h" diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index c440d21f56d..7d9d2f02c06 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -44,7 +44,6 @@ #include "DNA_object_types.h" #include "BLI_blenlib.h" -#include "BKE_utildefines.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_library.h" diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 0abd3444c54..acf38ace00a 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -49,7 +49,6 @@ #include "BKE_main.h" #include "BKE_sequencer.h" #include "BKE_texture.h" -#include "BKE_utildefines.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c index 70f27db0f74..0a195210e38 100644 --- a/source/blender/blenkernel/intern/seqmodifier.c +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -43,7 +43,6 @@ #include "BKE_colortools.h" #include "BKE_sequencer.h" -#include "BKE_utildefines.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index dcf72c37f52..9aaa9fd79e8 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -62,7 +62,6 @@ #include "BKE_fcurve.h" #include "BKE_scene.h" #include "BKE_mask.h" -#include "BKE_utildefines.h" #include "RNA_access.h" diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 2462de07a18..f340bcb5b1e 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -50,7 +50,6 @@ # include "AUD_C-API.h" #endif -#include "BKE_utildefines.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_sound.h" diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 2f54fe6cebd..ee904de4af6 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -56,7 +56,6 @@ #include "IMB_imbuf.h" -#include "BKE_utildefines.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_ocean.h" diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 78e7dab045f..2ed9d992c3f 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -411,6 +411,8 @@ void BKE_tracking_clipboard_free(void) track = next_track; } + + tracking_clipboard.tracks.first = tracking_clipboard.tracks.last = NULL; } void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingObject *object) diff --git a/source/blender/blenlib/BLI_endian_switch.h b/source/blender/blenlib/BLI_endian_switch.h new file mode 100644 index 00000000000..7017e7ba789 --- /dev/null +++ b/source/blender/blenlib/BLI_endian_switch.h @@ -0,0 +1,42 @@ +/* + * ***** 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. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BLI_ENDIAN_SWITCH_H__ +#define __BLI_ENDIAN_SWITCH_H__ + +/** \file BLI_endian_switch.h + * \ingroup bli + */ + +#include "BLI_endian_switch_inline.h" + +/* endian_switch.c */ +void BLI_endian_switch_int16_array(short *val, const int size); +void BLI_endian_switch_uint16_array(unsigned short *val, const int size); +void BLI_endian_switch_int32_array(int *val, const int size); +void BLI_endian_switch_uint32_array(unsigned int *val, const int size); +void BLI_endian_switch_float_array(float *val, const int size); +void BLI_endian_switch_int64_array(int64_t *val, const int size); +void BLI_endian_switch_uint64_array(uint64_t *val, const int size); +void BLI_endian_switch_double_array(double *val, const int size); + +#endif /* __BLI_ENDIAN_SWITCH_H__ */ diff --git a/source/blender/blenlib/BLI_endian_switch_inline.h b/source/blender/blenlib/BLI_endian_switch_inline.h new file mode 100644 index 00000000000..b747da3b738 --- /dev/null +++ b/source/blender/blenlib/BLI_endian_switch_inline.h @@ -0,0 +1,116 @@ +/* + * ***** 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. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/* only include from header */ +#ifndef __BLI_ENDIAN_SWITCH_H__ +# error "this file isnt to be directly included" +#endif + +#ifndef __BLI_ENDIAN_SWITCH_INLINE_H__ +#define __BLI_ENDIAN_SWITCH_INLINE_H__ + +/** \file blender/blenlib/BLI_endian_switch_inline.h + * \ingroup bli + */ + + +BLI_INLINE void BLI_endian_switch_int16(short *val) +{ + char *p_i = (char *)val; + char s_i; + + s_i = p_i[0]; + p_i[0] = p_i[1]; + p_i[1] = s_i; +} + +BLI_INLINE void BLI_endian_switch_uint16(unsigned short *val) +{ + char *p_i = (char *)val; + char s_i; + + s_i = p_i[0]; + p_i[0] = p_i[1]; + p_i[1] = s_i; +} + +BLI_INLINE void BLI_endian_switch_int32(int *val) +{ + char *p_i = (char *)val; + char s_i; + + s_i = p_i[0]; p_i[0] = p_i[3]; p_i[3] = s_i; + s_i = p_i[1]; p_i[1] = p_i[2]; p_i[2] = s_i; +} + +BLI_INLINE void BLI_endian_switch_uint32(unsigned int *val) +{ + char *p_i = (char *)val; + char s_i; + + s_i = p_i[0]; p_i[0] = p_i[3]; p_i[3] = s_i; + s_i = p_i[1]; p_i[1] = p_i[2]; p_i[2] = s_i; +} + +BLI_INLINE void BLI_endian_switch_float(float *val) +{ + char *p_i = (char *)val; + char s_i; + + s_i = p_i[0]; p_i[0] = p_i[3]; p_i[3] = s_i; + s_i = p_i[1]; p_i[1] = p_i[2]; p_i[2] = s_i; +} + +BLI_INLINE void BLI_endian_switch_int64(int64_t *val) +{ + char *p_i = (char *)val; + char s_i; + + s_i = p_i[0]; p_i[0] = p_i[7]; p_i[7] = s_i; + s_i = p_i[1]; p_i[1] = p_i[6]; p_i[6] = s_i; + s_i = p_i[2]; p_i[2] = p_i[5]; p_i[5] = s_i; + s_i = p_i[3]; p_i[3] = p_i[4]; p_i[4] = s_i; +} + +BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val) +{ + char *p_i = (char *)val; + char s_i; + + s_i = p_i[0]; p_i[0] = p_i[7]; p_i[7] = s_i; + s_i = p_i[1]; p_i[1] = p_i[6]; p_i[6] = s_i; + s_i = p_i[2]; p_i[2] = p_i[5]; p_i[5] = s_i; + s_i = p_i[3]; p_i[3] = p_i[4]; p_i[4] = s_i; +} + +BLI_INLINE void BLI_endian_switch_double(double *val) +{ + char *p_i = (char *)val; + char s_i; + + s_i = p_i[0]; p_i[0] = p_i[7]; p_i[7] = s_i; + s_i = p_i[1]; p_i[1] = p_i[6]; p_i[6] = s_i; + s_i = p_i[2]; p_i[2] = p_i[5]; p_i[5] = s_i; + s_i = p_i[3]; p_i[3] = p_i[4]; p_i[4] = s_i; +} + +#endif /* __BLI_ENDIAN_SWITCH_INLINE_H__ */ diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h index ac0ec6a52a7..e8d6336a994 100644 --- a/source/blender/blenlib/BLI_fileops.h +++ b/source/blender/blenlib/BLI_fileops.h @@ -91,6 +91,13 @@ int BLI_file_older(const char *file1, const char *file2); struct LinkNode *BLI_file_read_as_lines(const char *file); void BLI_file_free_lines(struct LinkNode *lines); +/* this weirdo pops up in two places ... */ +#if !defined(WIN32) +# ifndef O_BINARY +# define O_BINARY 0 +# endif +#endif + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 35d7b8d9444..4bd21139545 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -193,6 +193,14 @@ void BLI_system_temporary_dir(char *dir); void BLI_string_to_utf8(char *original, char *utf_8, const char *code); #endif +/* these values need to be hardcoded in structs, dna does not recognize defines */ +/* also defined in DNA_space_types.h */ +#ifndef FILE_MAXDIR +# define FILE_MAXDIR 768 +# define FILE_MAXFILE 256 +# define FILE_MAX 1024 +#endif + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index 8a459b9b07c..c11d8ed55be 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -225,30 +225,6 @@ (item <= ARRAY_LAST_ITEM(arr_start, arr_dtype, elem_size, tot)) \ ) -/* This one rotates the bytes in an int64, int (32) and short (16) */ -#define SWITCH_INT64(a) { \ - char s_i, *p_i; \ - p_i = (char *)&(a); \ - s_i = p_i[0]; p_i[0] = p_i[7]; p_i[7] = s_i; \ - s_i = p_i[1]; p_i[1] = p_i[6]; p_i[6] = s_i; \ - s_i = p_i[2]; p_i[2] = p_i[5]; p_i[5] = s_i; \ - s_i = p_i[3]; p_i[3] = p_i[4]; p_i[4] = s_i; \ - } (void)0 - -#define SWITCH_INT(a) { \ - char s_i, *p_i; \ - p_i = (char *)&(a); \ - s_i = p_i[0]; p_i[0] = p_i[3]; p_i[3] = s_i; \ - s_i = p_i[1]; p_i[1] = p_i[2]; p_i[2] = s_i; \ - } (void)0 - -#define SWITCH_SHORT(a) { \ - char s_i, *p_i; \ - p_i = (char *)&(a); \ - s_i = p_i[0]; p_i[0] = p_i[1]; p_i[1] = s_i; \ - } (void)0 - - /* Warning-free macros for storing ints in pointers. Use these _only_ * for storing an int in a pointer, not a pointer in an int (64bit)! */ #define SET_INT_IN_POINTER(i) ((void *)(intptr_t)(i)) diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 0175076fab8..fd755943e70 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -55,6 +55,7 @@ set(SRC intern/cpu.c intern/dynlib.c intern/edgehash.c + intern/endian_switch.c intern/fileops.c intern/fnmatch.c intern/freetypefont.c @@ -105,6 +106,8 @@ set(SRC BLI_dynlib.h BLI_dynstr.h BLI_edgehash.h + BLI_endian_switch.h + BLI_endian_switch_inline.h BLI_fileops.h BLI_fileops_types.h BLI_fnmatch.h diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c index 8c9993afee8..0ac6209fc95 100644 --- a/source/blender/blenlib/intern/BLI_memarena.c +++ b/source/blender/blenlib/intern/BLI_memarena.c @@ -46,7 +46,7 @@ struct MemArena { LinkNode *bufs; }; -MemArena *BLI_memarena_new(int bufsize, const char *name) +MemArena *BLI_memarena_new(const int bufsize, const char *name) { MemArena *ma = MEM_callocN(sizeof(*ma), "memarena"); ma->bufsize = bufsize; @@ -66,7 +66,7 @@ void BLI_memarena_use_malloc(MemArena *ma) ma->use_calloc = 0; } -void BLI_memarena_use_align(struct MemArena *ma, int align) +void BLI_memarena_use_align(struct MemArena *ma, const int align) { /* align should be a power of two */ ma->align = align; diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c index c7e610edd9e..d98e63d88dd 100644 --- a/source/blender/blenlib/intern/BLI_mempool.c +++ b/source/blender/blenlib/intern/BLI_mempool.c @@ -45,7 +45,7 @@ #include #include -/* note: copied from BKE_utildefines.h, don't use here because we're in BLI */ +/* note: copied from BLO_blend_defs.h, don't use here because we're in BLI */ #ifdef __BIG_ENDIAN__ /* Big Endian */ # define MAKE_ID(a, b, c, d) ( (int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d) ) diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c index 2a750cb1a66..be1f4eb3a35 100644 --- a/source/blender/blenlib/intern/bpath.c +++ b/source/blender/blenlib/intern/bpath.c @@ -78,7 +78,6 @@ #include "BKE_main.h" #include "BKE_report.h" #include "BKE_sequencer.h" -#include "BKE_utildefines.h" #include "BKE_image.h" /* so we can check the image's type */ static int checkMissingFiles_visit_cb(void *userdata, char *UNUSED(path_dst), const char *path_src) diff --git a/source/blender/blenlib/intern/endian_switch.c b/source/blender/blenlib/intern/endian_switch.c new file mode 100644 index 00000000000..b9b18136863 --- /dev/null +++ b/source/blender/blenlib/intern/endian_switch.c @@ -0,0 +1,118 @@ +/* + * ***** 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. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenlib/intern/endian_switch.c + * \ingroup bli + */ + +#include "BLO_sys_types.h" +#include "BLI_utildefines.h" +#include "BLI_endian_switch.h" + +void BLI_endian_switch_int16_array(short *val, const int size) +{ + if (size > 0) { + int i = size; + val = val + (size - 1); + while (i--) { + BLI_endian_switch_int16(val--); + } + } +} + +void BLI_endian_switch_uint16_array(unsigned short *val, const int size) +{ + if (size > 0) { + int i = size; + val = val + (size - 1); + while (i--) { + BLI_endian_switch_uint16(val--); + } + } +} + +void BLI_endian_switch_int32_array(int *val, const int size) +{ + if (size > 0) { + int i = size; + val = val + (size - 1); + while (i--) { + BLI_endian_switch_int32(val--); + } + } +} + +void BLI_endian_switch_uint32_array(unsigned int *val, const int size) +{ + if (size > 0) { + int i = size; + val = val + (size - 1); + while (i--) { + BLI_endian_switch_uint32(val--); + } + } +} + +void BLI_endian_switch_float_array(float *val, const int size) +{ + if (size > 0) { + int i = size; + val = val + (size - 1); + while (i--) { + BLI_endian_switch_float(val--); + } + } +} + +void BLI_endian_switch_int64_array(int64_t *val, const int size) +{ + if (size > 0) { + int i = size; + val = val + (size - 1); + while (i--) { + BLI_endian_switch_int64(val--); + } + } +} + +void BLI_endian_switch_uint64_array(uint64_t *val, const int size) +{ + if (size > 0) { + int i = size; + val = val + (size - 1); + while (i--) { + BLI_endian_switch_uint64(val--); + } + } +} + + +void BLI_endian_switch_double_array(double *val, const int size) +{ + if (size > 0) { + int i = size; + val = val + (size - 1); + while (i--) { + BLI_endian_switch_double(val--); + } + } +} diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index 7aa956a0548..f3107b565b9 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -60,8 +60,6 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" -#include "BKE_utildefines.h" - #include "BLO_sys_types.h" // for intptr_t support diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index e6ecdeae2e9..a7a66718445 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -47,7 +47,6 @@ #include "BLI_string_utf8.h" #include "BLI_utildefines.h" -#include "BKE_utildefines.h" #include "BKE_blender.h" // BLENDER_VERSION #include "GHOST_Path-api.h" diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index 965e8b5eec3..0fccd91fc02 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -86,13 +86,10 @@ #include "BLI_listbase.h" #include "BLI_linklist.h" -#include "BLI_fileops.h" - -#include "BLI_fileops_types.h" #include "BLI_string.h" #include "BLI_fileops.h" - -#include "BKE_utildefines.h" +#include "BLI_fileops_types.h" +#include "BLI_path_util.h" /* vars: */ static int totnum, actnum; diff --git a/source/blender/blenlib/intern/winstuff.c b/source/blender/blenlib/intern/winstuff.c index 0dc4d3c2db6..5b5f4cf8b80 100644 --- a/source/blender/blenlib/intern/winstuff.c +++ b/source/blender/blenlib/intern/winstuff.c @@ -41,12 +41,12 @@ #include "BLI_path_util.h" #include "BLI_string.h" -#include "BKE_utildefines.h" #include "BKE_global.h" #define WIN32_SKIP_HKEY_PROTECTION // need to use HKEY #include "BLI_winstuff.h" #include "BLI_utildefines.h" +#include "BLI_path_util.h" #include "utf_winfunc.h" #include "utfconv.h" diff --git a/source/blender/blenloader/BLO_blend_defs.h b/source/blender/blenloader/BLO_blend_defs.h new file mode 100644 index 00000000000..8005be158ce --- /dev/null +++ b/source/blender/blenloader/BLO_blend_defs.h @@ -0,0 +1,47 @@ +/* + * ***** 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. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __BLO_BLEND_DEFS_H__ +#define __BLO_BLEND_DEFS_H__ + +/** \file BLO_blend_defs.h + * \ingroup blenloader + * \brief defines for blendfile codes + */ + +/* INTEGER CODES */ +#ifdef __BIG_ENDIAN__ +/* Big Endian */ +# define BLEND_MAKE_ID(a, b, c, d) ( (int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d) ) +#else +/* Little Endian */ +# define BLEND_MAKE_ID(a, b, c, d) ( (int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a) ) +#endif + +#define DATA BLEND_MAKE_ID('D', 'A', 'T', 'A') +#define GLOB BLEND_MAKE_ID('G', 'L', 'O', 'B') + +#define DNA1 BLEND_MAKE_ID('D', 'N', 'A', '1') +#define TEST BLEND_MAKE_ID('T', 'E', 'S', 'T') /* used as preview between 'REND' and 'GLOB' */ +#define REND BLEND_MAKE_ID('R', 'E', 'N', 'D') +#define USER BLEND_MAKE_ID('U', 'S', 'E', 'R') + +#define ENDB BLEND_MAKE_ID('E', 'N', 'D', 'B') + +#endif /* __BLO_BLEND_DEFS_H__ */ diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt index a0fe042e7fb..74df5211dad 100644 --- a/source/blender/blenloader/CMakeLists.txt +++ b/source/blender/blenloader/CMakeLists.txt @@ -48,6 +48,7 @@ set(SRC intern/versioning_legacy.c intern/writefile.c + BLO_blend_defs.h BLO_readfile.h BLO_runtime.h BLO_soundfile.h diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c index eb12a7bd837..e917ccdf342 100644 --- a/source/blender/blenloader/intern/readblenentry.c +++ b/source/blender/blenloader/intern/readblenentry.c @@ -40,12 +40,13 @@ #include "MEM_guardedalloc.h" +#include "BLI_utildefines.h" +#include "BLI_path_util.h" #include "BLI_fileops.h" #include "BLI_ghash.h" #include "BLI_linklist.h" #include "BLI_listbase.h" #include "BLI_string.h" -#include "BLI_utildefines.h" #include "DNA_genfile.h" #include "DNA_sdna_types.h" @@ -55,10 +56,10 @@ #include "BKE_library.h" // for free_main #include "BKE_idcode.h" #include "BKE_report.h" -#include "BKE_utildefines.h" #include "BLO_readfile.h" #include "BLO_undofile.h" +#include "BLO_blend_defs.h" #include "readfile.h" diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index ac792a90735..1021d2a794d 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -100,6 +100,7 @@ #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" +#include "BLI_endian_switch.h" #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_edgehash.h" @@ -140,7 +141,6 @@ #include "BKE_sequencer.h" #include "BKE_text.h" // for txt_extended_ascii_as_utf8 #include "BKE_tracking.h" -#include "BKE_utildefines.h" // SWITCH_INT DATA ENDB DNA1 O_BINARY GLOB USER TEST REND #include "BKE_sound.h" #include "IMB_imbuf.h" // for proxy / timecode versioning stuff @@ -149,6 +149,7 @@ #include "BLO_readfile.h" #include "BLO_undofile.h" +#include "BLO_blend_defs.h" #include "RE_engine.h" @@ -221,16 +222,6 @@ /* from misc_util: flip the bytes from x */ /* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */ -// only used here in readfile.c -#define SWITCH_LONGINT(a) { \ - char s_i, *p_i; \ - p_i= (char *)&(a); \ - s_i=p_i[0]; p_i[0]=p_i[7]; p_i[7]=s_i; \ - s_i=p_i[1]; p_i[1]=p_i[6]; p_i[6]=s_i; \ - s_i=p_i[2]; p_i[2]=p_i[5]; p_i[5]=s_i; \ - s_i=p_i[3]; p_i[3]=p_i[4]; p_i[4]=s_i; \ -} (void)0 - /***/ typedef struct OldNew { @@ -577,9 +568,9 @@ static void switch_endian_bh4(BHead4 *bhead) if ((bhead->code & 0xFFFF)==0) bhead->code >>= 16; if (bhead->code != ENDB) { - SWITCH_INT(bhead->len); - SWITCH_INT(bhead->SDNAnr); - SWITCH_INT(bhead->nr); + BLI_endian_switch_int32(&bhead->len); + BLI_endian_switch_int32(&bhead->SDNAnr); + BLI_endian_switch_int32(&bhead->nr); } } @@ -589,9 +580,9 @@ static void switch_endian_bh8(BHead8 *bhead) if ((bhead->code & 0xFFFF)==0) bhead->code >>= 16; if (bhead->code != ENDB) { - SWITCH_INT(bhead->len); - SWITCH_INT(bhead->SDNAnr); - SWITCH_INT(bhead->nr); + BLI_endian_switch_int32(&bhead->len); + BLI_endian_switch_int32(&bhead->SDNAnr); + BLI_endian_switch_int32(&bhead->nr); } } @@ -612,7 +603,7 @@ static void bh4_from_bh8(BHead *bhead, BHead8 *bhead8, int do_endian_swap) * 0x0000000000000000000012345678 would become 0x12345678000000000000000000000000 */ if (do_endian_swap) { - SWITCH_LONGINT(bhead8->old); + BLI_endian_switch_int64(&bhead8->old); } /* this patch is to avoid a long long being read from not-eight aligned positions @@ -1476,11 +1467,7 @@ static void link_glob_list(FileData *fd, ListBase *lb) /* for glob data */ static void test_pointer_array(FileData *fd, void **mat) { -#if defined(WIN32) && !defined(FREE_WINDOWS) - __int64 *lpoin, *lmat; -#else - long long *lpoin, *lmat; -#endif + int64_t *lpoin, *lmat; int *ipoin, *imat; size_t len; @@ -1497,7 +1484,7 @@ static void test_pointer_array(FileData *fd, void **mat) while (len-- > 0) { if ((fd->flags & FD_FLAGS_SWITCH_ENDIAN)) - SWITCH_LONGINT(*lpoin); + BLI_endian_switch_int64(lpoin); *ipoin = (int)((*lpoin) >> 3); ipoin++; lpoin++; @@ -1567,16 +1554,13 @@ static void IDP_DirectLinkArray(IDProperty *prop, int switch_endian, FileData *f } else if (prop->subtype == IDP_DOUBLE) { if (switch_endian) { - for (i = 0; i < prop->len; i++) { - SWITCH_LONGINT(((double *)prop->data.pointer)[i]); - } + BLI_endian_switch_double_array(prop->data.pointer, prop->len); } } else { if (switch_endian) { - for (i = 0; i < prop->len; i++) { - SWITCH_INT(((int *)prop->data.pointer)[i]); - } + /* also used for floats */ + BLI_endian_switch_int32_array(prop->data.pointer, prop->len); } } } @@ -1628,9 +1612,9 @@ static void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, FileData */ if (switch_endian) { - SWITCH_INT(prop->data.val); - SWITCH_INT(prop->data.val2); - SWITCH_LONGINT(prop->data.val); + BLI_endian_switch_int32(&prop->data.val); + BLI_endian_switch_int32(&prop->data.val2); + BLI_endian_switch_int64((int64_t *)&prop->data.val); } break; @@ -1871,9 +1855,7 @@ static void direct_link_fmodifiers(FileData *fd, ListBase *list) data->coefficients = newdataadr(fd, data->coefficients); if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) { - unsigned int a; - for (a = 0; a < data->arraysize; a++) - SWITCH_INT(data->coefficients[a]); + BLI_endian_switch_float_array(data->coefficients, data->arraysize); } } break; @@ -2777,11 +2759,8 @@ static void switch_endian_keyblock(Key *key, KeyBlock *kb) case IPO_BPOINT: case IPO_BEZTRIPLE: b = cp[0]; - - while (b--) { - SWITCH_INT((*poin)); - poin += 4; - } + BLI_endian_switch_float_array((float *)poin, b); + poin += sizeof(float) * b; break; } @@ -3072,19 +3051,11 @@ static void lib_link_curve(FileData *fd, Main *main) static void switch_endian_knots(Nurb *nu) { - int len; - if (nu->knotsu) { - len = KNOTSU(nu); - while (len--) { - SWITCH_INT(nu->knotsu[len]); - } + BLI_endian_switch_float_array(nu->knotsu, KNOTSU(nu)); } if (nu->knotsv) { - len = KNOTSV(nu); - while (len--) { - SWITCH_INT(nu->knotsv[len]); - } + BLI_endian_switch_float_array(nu->knotsv, KNOTSV(nu)); } } @@ -3302,11 +3273,10 @@ static void direct_link_pointcache(FileData *fd, PointCache *cache) /* the cache saves non-struct data without DNA */ if (pm->data[i] && ptcache_data_struct[i][0]=='\0' && (fd->flags & FD_FLAGS_SWITCH_ENDIAN)) { - int j, tot = (BKE_ptcache_data_size (i) * pm->totpoint)/4; /* data_size returns bytes */ + int tot = (BKE_ptcache_data_size (i) * pm->totpoint) / sizeof(int); /* data_size returns bytes */ int *poin = pm->data[i]; - for (j = 0; j < tot; j++) - SWITCH_INT(poin[j]); + BLI_endian_switch_int32_array(poin, tot); } } @@ -3775,12 +3745,7 @@ static void direct_link_mdisps(FileData *fd, int count, MDisps *mdisps, int exte if ((fd->flags & FD_FLAGS_SWITCH_ENDIAN) && (mdisps[i].disps)) { /* DNA_struct_switch_endian doesn't do endian swap for (*disps)[] */ /* this does swap for data written at write_mdisps() - readfile.c */ - int x; - float *tmpdisps = *mdisps[i].disps; - for (x = 0; x < mdisps[i].totdisp * 3; x++) { - SWITCH_INT(*tmpdisps); - tmpdisps++; - } + BLI_endian_switch_float_array(*mdisps[i].disps, mdisps[i].totdisp * 3); } if (!external && !mdisps[i].disps) mdisps[i].totdisp = 0; @@ -3950,11 +3915,8 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh) TFace *tf = mesh->tface; int i; - for (i = 0; i < (mesh->totface); i++, tf++) { - SWITCH_INT(tf->col[0]); - SWITCH_INT(tf->col[1]); - SWITCH_INT(tf->col[2]); - SWITCH_INT(tf->col[3]); + for (i = 0; i < mesh->totface; i++, tf++) { + BLI_endian_switch_uint32_array(tf->col, 4); } } } @@ -4480,10 +4442,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) hmd->indexar = newdataadr(fd, hmd->indexar); if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) { - int a; - for (a = 0; a < hmd->totindex; a++) { - SWITCH_INT(hmd->indexar[a]); - } + BLI_endian_switch_int32_array(hmd->indexar, hmd->totindex); } } else if (md->type == eModifierType_ParticleSystem) { @@ -4513,24 +4472,11 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) mmd->bindcos = newdataadr(fd, mmd->bindcos); if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) { - int a; - - if (mmd->bindoffsets) - for (a=0; atotvert+1; a++) - SWITCH_INT(mmd->bindoffsets[a]); - if (mmd->bindcagecos) - for (a=0; atotcagevert*3; a++) - SWITCH_INT(mmd->bindcagecos[a]); - if (mmd->dynverts) - for (a=0; atotvert; a++) - SWITCH_INT(mmd->dynverts[a]); - - if (mmd->bindweights) - for (a=0; atotcagevert*mmd->totvert; a++) - SWITCH_INT(mmd->bindweights[a]); - if (mmd->bindcos) - for (a=0; atotcagevert*3; a++) - SWITCH_INT(mmd->bindcos[a]); + if (mmd->bindoffsets) BLI_endian_switch_int32_array(mmd->bindoffsets, mmd->totvert + 1); + if (mmd->bindcagecos) BLI_endian_switch_float_array(mmd->bindcagecos, mmd->totcagevert * 3); + if (mmd->dynverts) BLI_endian_switch_int32_array(mmd->dynverts, mmd->totvert); + if (mmd->bindweights) BLI_endian_switch_float_array(mmd->bindweights, mmd->totvert); + if (mmd->bindcos) BLI_endian_switch_float_array(mmd->bindcos, mmd->totcagevert * 3); } } else if (md->type == eModifierType_Ocean) { @@ -4724,10 +4670,7 @@ static void direct_link_object(FileData *fd, Object *ob) hook->indexar= newdataadr(fd, hook->indexar); if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) { - int a; - for (a = 0; a < hook->totindex; a++) { - SWITCH_INT(hook->indexar[a]); - } + BLI_endian_switch_int32_array(hook->indexar, hook->totindex); } /* Do conversion here because if we have loaded @@ -7086,8 +7029,8 @@ static void do_version_ntree_mask_264(void *UNUSED(data), ID *UNUSED(id), bNodeT if (node->storage == NULL) { NodeMask *data = MEM_callocN(sizeof(NodeMask), __func__); /* move settings into own struct */ - data->size_x = node->custom3; - data->size_y = node->custom4; + data->size_x = (int)node->custom3; + data->size_y = (int)node->custom4; node->custom3 = 0.5f; /* default shutter */ node->storage = data; } diff --git a/source/blender/blenloader/intern/runtime.c b/source/blender/blenloader/intern/runtime.c index a7dae22cda2..eaf725dda9e 100644 --- a/source/blender/blenloader/intern/runtime.c +++ b/source/blender/blenloader/intern/runtime.c @@ -50,7 +50,6 @@ #include "BKE_blender.h" #include "BKE_report.h" -#include "BKE_utildefines.h" #include "BLI_blenlib.h" diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index 1bad1bd80df..a4f190c8167 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -89,7 +89,6 @@ #include "BKE_screen.h" #include "BKE_sequencer.h" #include "BKE_texture.h" -#include "BKE_utildefines.h" // SWITCH_INT DATA ENDB DNA1 O_BINARY GLOB USER TEST REND #include "BKE_sound.h" #include "NOD_socket.h" diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index 8ace277b42d..1cc0d4180ab 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -95,7 +95,6 @@ #include "BKE_property.h" // for get_ob_property #include "BKE_scene.h" #include "BKE_sequencer.h" -#include "BKE_utildefines.h" // SWITCH_INT DATA ENDB DNA1 O_BINARY GLOB USER TEST REND #include "IMB_imbuf.h" // for proxy / timecode versioning stuff diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 252e81537c4..f8b3a548345 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -154,7 +154,6 @@ Any case: direct data is ALWAYS after the lib block #include "BKE_report.h" #include "BKE_sequencer.h" #include "BKE_subsurf.h" -#include "BKE_utildefines.h" #include "BKE_modifier.h" #include "BKE_fcurve.h" #include "BKE_pointcache.h" @@ -163,6 +162,7 @@ Any case: direct data is ALWAYS after the lib block #include "BLO_writefile.h" #include "BLO_readfile.h" #include "BLO_undofile.h" +#include "BLO_blend_defs.h" #include "readfile.h" diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index 58ccfa79a02..c0439311104 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -527,9 +527,9 @@ void BM_active_face_set(BMesh *bm, BMFace *efa) bm->act_face = efa; } -BMFace *BM_active_face_get(BMesh *bm, int sloppy) +BMFace *BM_active_face_get(BMesh *bm, int sloppy, int selected) { - if (bm->act_face) { + if (bm->act_face && (!selected || BM_elem_flag_test(bm->act_face, BM_ELEM_SELECT))) { return bm->act_face; } else if (sloppy) { @@ -546,6 +546,9 @@ BMFace *BM_active_face_get(BMesh *bm, int sloppy) if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { f = NULL; } + else if (selected && !BM_elem_flag_test(f, BM_ELEM_SELECT)) { + f = NULL; + } else { break; } @@ -768,7 +771,7 @@ void BM_select_history_validate(BMesh *bm) int BM_select_history_active_get(BMesh *bm, BMEditSelection *ese) { BMEditSelection *ese_last = bm->selected.last; - BMFace *efa = BM_active_face_get(bm, FALSE); + BMFace *efa = BM_active_face_get(bm, FALSE, FALSE); ese->next = ese->prev = NULL; diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h index 9b73ed2c390..8d4397794d5 100644 --- a/source/blender/bmesh/intern/bmesh_marking.h +++ b/source/blender/bmesh/intern/bmesh_marking.h @@ -71,7 +71,7 @@ int BM_mesh_elem_hflag_count_disabled(BMesh *bm, const char htype, const char hf /* edit selection stuff */ void BM_active_face_set(BMesh *bm, BMFace *f); -BMFace *BM_active_face_get(BMesh *bm, int sloppy); +BMFace *BM_active_face_get(BMesh *bm, int sloppy, int selected); void BM_editselection_center(BMEditSelection *ese, float r_center[3]); void BM_editselection_normal(BMEditSelection *ese, float r_normal[3]); diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 807570f0d86..1d056dbfae7 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -606,11 +606,11 @@ int BM_face_point_inside_test(BMFace *f, const float co[3]) do { float v1[2], v2[2]; - v1[0] = (l_iter->prev->v->co[ax] - cent[ax]) * onepluseps + cent[ax]; - v1[1] = (l_iter->prev->v->co[ay] - cent[ay]) * onepluseps + cent[ay]; + v1[0] = (l_iter->prev->v->co[ax] - cent[0]) * onepluseps + cent[0]; + v1[1] = (l_iter->prev->v->co[ay] - cent[1]) * onepluseps + cent[1]; - v2[0] = (l_iter->v->co[ax] - cent[ax]) * onepluseps + cent[ax]; - v2[1] = (l_iter->v->co[ay] - cent[ay]) * onepluseps + cent[ay]; + v2[0] = (l_iter->v->co[ax] - cent[0]) * onepluseps + cent[0]; + v2[1] = (l_iter->v->co[ay] - cent[1]) * onepluseps + cent[1]; crosses += linecrossesf(v1, v2, co2, out) != 0; } while ((l_iter = l_iter->next) != l_first); diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c index 9ea8e631435..c8be7c9ce34 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -390,7 +390,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) if (!v1->e) BM_vert_kill(bm, v1); if (!v2->e) - BM_vert_kill(bm, v1); + BM_vert_kill(bm, v2); continue; } diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c index 3aa6e6dbe49..132d7050b31 100644 --- a/source/blender/bmesh/operators/bmo_inset.c +++ b/source/blender/bmesh/operators/bmo_inset.c @@ -283,7 +283,8 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) * cross product between both face normals */ add_v3_v3v3(tvec, e_info_a->no, e_info_b->no); - if ((f_a == f_b) || compare_v3v3(f_a->no, f_b->no, 0.00001f)) { + /* epsilon increased to fix [#32329] */ + if ((f_a == f_b) || compare_v3v3(f_a->no, f_b->no, 0.001f)) { normalize_v3(tvec); } else { diff --git a/source/blender/bmesh/tools/BME_bevel.c b/source/blender/bmesh/tools/BME_bevel.c index 85beb6d092b..91527313972 100644 --- a/source/blender/bmesh/tools/BME_bevel.c +++ b/source/blender/bmesh/tools/BME_bevel.c @@ -38,7 +38,6 @@ #include "BLI_ghash.h" #include "BLI_memarena.h" -#include "BKE_utildefines.h" #include "BKE_tessmesh.h" #include "BKE_bmesh.h" diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp index d241926c20c..b2748a55b6a 100644 --- a/source/blender/collada/AnimationImporter.cpp +++ b/source/blender/collada/AnimationImporter.cpp @@ -683,12 +683,11 @@ void AnimationImporter::Assign_lens_animations(const COLLADAFW::UniqueId& listid for (unsigned int i = 0; i < fcu->totvert; i++) { double input_fov = fcu->bezt[i].vec[1][1]; - double xfov = (fov_type == CAMERA_YFOV) ? aspect * input_fov : input_fov; - // fov is in degrees, cam->lens is in millimiters - double fov = fov_to_focallength(DEG2RADF(input_fov), cam->sensor_x); + // NOTE: Needs more testing (As we curretnly have no official test data for this) + double xfov = (fov_type == CAMERA_YFOV) ? (2.0f * atanf(aspect * tanf(DEG2RADF(input_fov) * 0.5f))) : DEG2RADF(input_fov); - fcu->bezt[i].vec[1][1] = fov; + fcu->bezt[i].vec[1][1] = fov_to_focallength(xfov, cam->sensor_x); } BLI_addtail(AnimCurves, fcu); diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index c47798ee804..baaa6dbeed2 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -99,7 +99,6 @@ extern char build_rev[]; #include "BKE_action.h" // pose functions #include "BKE_armature.h" #include "BKE_image.h" -#include "BKE_utildefines.h" #include "BKE_object.h" #include "BLI_math.h" diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 60b03a211ba..f29933ea0c1 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -62,13 +62,13 @@ extern "C" { #include "BKE_texture.h" #include "BKE_fcurve.h" #include "BKE_depsgraph.h" -#include "BLI_path_util.h" #include "BKE_scene.h" #include "BKE_global.h" #include "BKE_material.h" -#include "BKE_utildefines.h" #include "BKE_image.h" +#include "BLI_path_util.h" + #include "DNA_camera_types.h" #include "DNA_lamp_types.h" @@ -867,9 +867,11 @@ bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera) { double yfov = camera->getYFov().getValue(); double aspect = camera->getAspectRatio().getValue(); - double xfov = aspect * yfov; - // xfov is in degrees, cam->lens is in millimiters - cam->lens = fov_to_focallength(DEG2RADF(xfov), cam->sensor_x); + + // NOTE: Needs more testing (As we curretnly have no official test data for this) + + double xfov = 2.0f * atanf(aspect * tanf(DEG2RADF(yfov) * 0.5f)); + cam->lens = fov_to_focallength(xfov, cam->sensor_x); } break; } diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp index 66dcec7d8e4..ef714f2561f 100644 --- a/source/blender/collada/ImageExporter.cpp +++ b/source/blender/collada/ImageExporter.cpp @@ -39,7 +39,6 @@ extern "C" { #include "BKE_image.h" #include "BKE_main.h" #include "BKE_mesh.h" -#include "BKE_utildefines.h" #include "BLI_fileops.h" #include "BLI_path_util.h" #include "BLI_string.h" diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp index 5593fe993f4..cf211e2fbb1 100644 --- a/source/blender/collada/MeshImporter.cpp +++ b/source/blender/collada/MeshImporter.cpp @@ -570,7 +570,7 @@ void MeshImporter::read_lines(COLLADAFW::Mesh *mesh, Mesh *me) if (loose_edge_count > 0) { unsigned int face_edge_count = me->totedge; - unsigned int total_edge_count = loose_edge_count + face_edge_count; + /* unsigned int total_edge_count = loose_edge_count + face_edge_count; */ /* UNUSED */ mesh_add_edges(me, loose_edge_count); MEdge *med = me->medge + face_edge_count; diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp index 5f133fe071f..f9af23faea8 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.cpp +++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp @@ -54,6 +54,7 @@ static vector g_cpudevices; #if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE /// @brief list of all thread for every CPUDevice in cpudevices a thread exists static ListBase g_cputhreads; +static bool g_cpuInitialized = false; /// @brief all scheduled work for the cpu static ThreadQueue *g_cpuqueue; static ThreadQueue *g_gpuqueue; @@ -67,11 +68,13 @@ static ListBase g_gputhreads; /// @brief all scheduled work for the gpu #ifdef COM_OPENCL_ENABLED static bool g_openclActive = false; +static bool g_openclInitialized = false; #endif #endif #endif #define MAX_HIGHLIGHT 8 +static bool g_highlightInitialized = false; extern "C" { int g_highlightIndex; void **g_highlightedNodes; @@ -255,40 +258,59 @@ extern void clContextError(const char *errinfo, const void *private_info, size_t printf("OPENCL error: %s\n", errinfo); } -void WorkScheduler::initialize() +void WorkScheduler::initialize(bool use_opencl) { - if (g_highlightedNodesRead) MEM_freeN(g_highlightedNodesRead); - if (g_highlightedNodes) MEM_freeN(g_highlightedNodes); + /* initialize highlighting */ + if (!g_highlightInitialized) { + if (g_highlightedNodesRead) MEM_freeN(g_highlightedNodesRead); + if (g_highlightedNodes) MEM_freeN(g_highlightedNodes); - g_highlightedNodesRead = NULL; - g_highlightedNodes = NULL; + g_highlightedNodesRead = NULL; + g_highlightedNodes = NULL; - COM_startReadHighlights(); -#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE - int numberOfCPUThreads = BLI_system_thread_count(); + COM_startReadHighlights(); - for (int index = 0; index < numberOfCPUThreads; index++) { - CPUDevice *device = new CPUDevice(); - device->initialize(); - g_cpudevices.push_back(device); + g_highlightInitialized = true; } + +#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE + /* initialize CPU threads */ + if (!g_cpuInitialized) { + int numberOfCPUThreads = BLI_system_thread_count(); + + for (int index = 0; index < numberOfCPUThreads; index++) { + CPUDevice *device = new CPUDevice(); + device->initialize(); + g_cpudevices.push_back(device); + } + + g_cpuInitialized = true; + } + #ifdef COM_OPENCL_ENABLED - g_context = NULL; - g_program = NULL; - if (clCreateContextFromType) { - cl_uint numberOfPlatforms = 0; - cl_int error; - error = clGetPlatformIDs(0, 0, &numberOfPlatforms); - if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } - if (G.f & G_DEBUG) printf("%d number of platforms\n", numberOfPlatforms); - cl_platform_id *platforms = (cl_platform_id *)MEM_mallocN(sizeof(cl_platform_id) * numberOfPlatforms, __func__); - error = clGetPlatformIDs(numberOfPlatforms, platforms, 0); - unsigned int indexPlatform; - for (indexPlatform = 0; indexPlatform < numberOfPlatforms; indexPlatform++) { - cl_platform_id platform = platforms[indexPlatform]; - cl_uint numberOfDevices = 0; - clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, 0, &numberOfDevices); - if (numberOfDevices > 0) { + /* deinitialize OpenCL GPU's */ + if (use_opencl && !g_openclInitialized) { + g_context = NULL; + g_program = NULL; + + OCL_init(); /* this will check and skip if already initialized */ + + if (clCreateContextFromType) { + cl_uint numberOfPlatforms = 0; + cl_int error; + error = clGetPlatformIDs(0, 0, &numberOfPlatforms); + if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } + if (G.f & G_DEBUG) printf("%d number of platforms\n", numberOfPlatforms); + cl_platform_id *platforms = (cl_platform_id *)MEM_mallocN(sizeof(cl_platform_id) * numberOfPlatforms, __func__); + error = clGetPlatformIDs(numberOfPlatforms, platforms, 0); + unsigned int indexPlatform; + for (indexPlatform = 0; indexPlatform < numberOfPlatforms; indexPlatform++) { + cl_platform_id platform = platforms[indexPlatform]; + cl_uint numberOfDevices = 0; + clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, 0, &numberOfDevices); + if (numberOfDevices <= 0) + continue; + cl_device_id *cldevices = (cl_device_id *)MEM_mallocN(sizeof(cl_device_id) * numberOfDevices, __func__); clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, numberOfDevices, cldevices, 0); @@ -324,8 +346,10 @@ void WorkScheduler::initialize() } MEM_freeN(cldevices); } + MEM_freeN(platforms); } - MEM_freeN(platforms); + + g_openclInitialized = true; } #endif #endif @@ -334,37 +358,52 @@ void WorkScheduler::initialize() void WorkScheduler::deinitialize() { #if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE - Device *device; - while (g_cpudevices.size() > 0) { - device = g_cpudevices.back(); - g_cpudevices.pop_back(); - device->deinitialize(); - delete device; + /* deinitialize CPU threads */ + if (g_cpuInitialized) { + Device *device; + while (g_cpudevices.size() > 0) { + device = g_cpudevices.back(); + g_cpudevices.pop_back(); + device->deinitialize(); + delete device; + } + + g_cpuInitialized = false; } + #ifdef COM_OPENCL_ENABLED - while (g_gpudevices.size() > 0) { - device = g_gpudevices.back(); - g_gpudevices.pop_back(); - device->deinitialize(); - delete device; - } - if (g_program) { - clReleaseProgram(g_program); - g_program = NULL; - } - if (g_context) { - clReleaseContext(g_context); - g_context = NULL; + /* deinitialize OpenCL GPU's */ + if (g_openclInitialized) { + Device *device; + while (g_gpudevices.size() > 0) { + device = g_gpudevices.back(); + g_gpudevices.pop_back(); + device->deinitialize(); + delete device; + } + if (g_program) { + clReleaseProgram(g_program); + g_program = NULL; + } + if (g_context) { + clReleaseContext(g_context); + g_context = NULL; + } + + g_openclInitialized = false; } #endif #endif - if (g_highlightedNodes) { - MEM_freeN(g_highlightedNodes); - } + /* deinitialize highlighting */ + if (g_highlightInitialized) { + if (g_highlightedNodes) + MEM_freeN(g_highlightedNodes); - if (g_highlightedNodesRead) { - MEM_freeN(g_highlightedNodesRead); + if (g_highlightedNodesRead) + MEM_freeN(g_highlightedNodesRead); + + g_highlightInitialized = false; } } diff --git a/source/blender/compositor/intern/COM_WorkScheduler.h b/source/blender/compositor/intern/COM_WorkScheduler.h index f56fe94201e..4ab23cf9ae4 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.h +++ b/source/blender/compositor/intern/COM_WorkScheduler.h @@ -74,8 +74,10 @@ public: * After mutex initialization the system is queried in order to count the number of CPUDevices and GPUDevices to be created. * For every hardware thread a CPUDevice and for every OpenCL GPU device a OpenCLDevice is created. * these devices are stored in a separate list (cpudevices & gpudevices) + * + * This function can be called multiple times to lazily initialize OpenCL. */ - static void initialize(); + static void initialize(bool use_opencl); /** * @brief deinitialize the WorkScheduler diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp index 7dcb3572a14..daf48d65caf 100644 --- a/source/blender/compositor/intern/COM_compositor.cpp +++ b/source/blender/compositor/intern/COM_compositor.cpp @@ -36,24 +36,29 @@ extern "C" { static ThreadMutex s_compositorMutex; static char is_compositorMutex_init = FALSE; + void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering) { - if (is_compositorMutex_init == FALSE) { /// TODO: move to blender startup phase - memset(&s_compositorMutex, 0, sizeof(s_compositorMutex)); + /* initialize mutex, TODO this mutex init is actually not thread safe and + * should be done somewhere as part of blender startup, all the other + * initializations can be done lazily */ + if (is_compositorMutex_init == FALSE) { BLI_mutex_init(&s_compositorMutex); - OCL_init(); - WorkScheduler::initialize(); ///TODO: call workscheduler.deinitialize somewhere is_compositorMutex_init = TRUE; } + BLI_mutex_lock(&s_compositorMutex); + if (editingtree->test_break(editingtree->tbh)) { // during editing multiple calls to this method can be triggered. // make sure one the last one will be doing the work. BLI_mutex_unlock(&s_compositorMutex); return; - } + /* initialize workscheduler, will check if already done. TODO deinitialize somewhere */ + bool use_opencl = (editingtree->flag & NTREE_COM_OPENCL); + WorkScheduler::initialize(use_opencl); /* set progress bar to 0% and status to init compositing */ editingtree->progress(editingtree->prh, 0.0); @@ -83,11 +88,12 @@ void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering) void COM_deinitialize() { - if (is_compositorMutex_init) - { + if (is_compositorMutex_init) { BLI_mutex_lock(&s_compositorMutex); + deintializeDistortionCache(); WorkScheduler::deinitialize(); + is_compositorMutex_init = FALSE; BLI_mutex_unlock(&s_compositorMutex); BLI_mutex_end(&s_compositorMutex); diff --git a/source/blender/compositor/nodes/COM_MovieClipNode.cpp b/source/blender/compositor/nodes/COM_MovieClipNode.cpp index a250841b160..6d5b9bba8aa 100644 --- a/source/blender/compositor/nodes/COM_MovieClipNode.cpp +++ b/source/blender/compositor/nodes/COM_MovieClipNode.cpp @@ -49,10 +49,14 @@ void MovieClipNode::convertToOperations(ExecutionSystem *graph, CompositorContex bNode *editorNode = this->getbNode(); MovieClip *movieClip = (MovieClip *)editorNode->id; MovieClipUser *movieClipUser = (MovieClipUser *)editorNode->storage; - + bool cacheFrame = !context->isRendering(); + ImBuf *ibuf = NULL; if (movieClip) { - ibuf = BKE_movieclip_get_ibuf(movieClip, movieClipUser); + if (cacheFrame) + ibuf = BKE_movieclip_get_ibuf(movieClip, movieClipUser); + else + ibuf = BKE_movieclip_get_ibuf_flag(movieClip, movieClipUser, movieClip->flag, MOVIECLIP_CACHE_SKIP); } // always connect the output image @@ -78,10 +82,11 @@ void MovieClipNode::convertToOperations(ExecutionSystem *graph, CompositorContex outputMovieClip->relinkConnections(operation->getOutputSocket()); } } + operation->setMovieClip(movieClip); operation->setMovieClipUser(movieClipUser); operation->setFramenumber(context->getFramenumber()); - operation->setCacheFrame(!context->isRendering()); + operation->setCacheFrame(cacheFrame); graph->addOperation(operation); MovieTrackingStabilization *stab = &movieClip->tracking.stabilization; diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.cpp b/source/blender/compositor/nodes/COM_OutputFileNode.cpp index e85f521def0..b8cee29fee6 100644 --- a/source/blender/compositor/nodes/COM_OutputFileNode.cpp +++ b/source/blender/compositor/nodes/COM_OutputFileNode.cpp @@ -24,8 +24,8 @@ #include "COM_OutputFileNode.h" #include "COM_OutputFileOperation.h" #include "COM_ExecutionSystem.h" + #include "BLI_path_util.h" -#include "BKE_utildefines.h" OutputFileNode::OutputFileNode(bNode *editorNode) : Node(editorNode) { diff --git a/source/blender/compositor/operations/COM_AntiAliasOperation.cpp b/source/blender/compositor/operations/COM_AntiAliasOperation.cpp index c37830a9d92..867053bf1d2 100644 --- a/source/blender/compositor/operations/COM_AntiAliasOperation.cpp +++ b/source/blender/compositor/operations/COM_AntiAliasOperation.cpp @@ -23,7 +23,6 @@ #include "COM_AntiAliasOperation.h" #include "BLI_math.h" #include "BLI_utildefines.h" -#include "BKE_utildefines.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/compositor/operations/COM_MovieClipOperation.cpp b/source/blender/compositor/operations/COM_MovieClipOperation.cpp index b73db74b061..709e4b7d4b0 100644 --- a/source/blender/compositor/operations/COM_MovieClipOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieClipOperation.cpp @@ -48,14 +48,10 @@ void MovieClipOperation::initExecution() BKE_movieclip_user_set_frame(this->m_movieClipUser, this->m_framenumber); ImBuf *ibuf; - if (this->m_cacheFrame) { + if (this->m_cacheFrame) ibuf = BKE_movieclip_get_ibuf(this->m_movieClip, this->m_movieClipUser); - } - else { - int flag = this->m_movieClip->flag & MCLIP_TIMECODE_FLAGS; - - ibuf = BKE_movieclip_get_ibuf_flag(this->m_movieClip, this->m_movieClipUser, flag, MOVIECLIP_CACHE_SKIP); - } + else + ibuf = BKE_movieclip_get_ibuf_flag(this->m_movieClip, this->m_movieClipUser, this->m_movieClip->flag, MOVIECLIP_CACHE_SKIP); if (ibuf) { this->m_movieClipBuffer = ibuf; diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.h b/source/blender/compositor/operations/COM_OutputFileOperation.h index 0d6e5bfa61a..532242c97ce 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.h +++ b/source/blender/compositor/operations/COM_OutputFileOperation.h @@ -24,8 +24,9 @@ #ifndef _COM_OutputFileOperation_h #define _COM_OutputFileOperation_h #include "COM_NodeOperation.h" + #include "BLI_rect.h" -#include "BKE_utildefines.h" +#include "BLI_path_util.h" #include "intern/openexr/openexr_multi.h" diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 16168888573..86f729502bb 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -61,7 +61,6 @@ #include "BKE_curve.h" #include "BKE_key.h" #include "BKE_context.h" -#include "BKE_utildefines.h" /* FILE_MAX */ #include "UI_interface.h" #include "UI_interface_icons.h" diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index 3255bc47148..6ce9fc638be 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -50,7 +50,6 @@ #include "BKE_global.h" #include "BKE_node.h" #include "BKE_sequencer.h" -#include "BKE_utildefines.h" #include "RNA_access.h" diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index a0acdd710e0..c92b7ce2761 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -89,7 +89,6 @@ #include "BKE_node.h" #include "BKE_mask.h" #include "BKE_sequencer.h" -#include "BKE_utildefines.h" #include "ED_anim_api.h" #include "ED_markers.h" diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index 3883dce7671..b5c0555bf63 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -45,7 +45,6 @@ #include "BKE_fcurve.h" -#include "BKE_utildefines.h" #include "BKE_report.h" #include "BKE_library.h" #include "BKE_global.h" diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 35284b26d29..da440063552 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -135,7 +135,7 @@ struct UvElementMap *EDBM_uv_element_map_create(struct BMEditMesh *em, int selec void EDBM_uv_element_map_free(struct UvElementMap *vmap); int EDBM_mtexpoly_check(struct BMEditMesh *em); -struct MTexPoly *EDBM_mtexpoly_active_get(struct BMEditMesh *em, struct BMFace **r_act_efa, int sloppy); +struct MTexPoly *EDBM_mtexpoly_active_get(struct BMEditMesh *em, struct BMFace **r_act_efa, int sloppy, int selected); void EDBM_uv_vert_map_free(struct UvVertMap *vmap); struct UvMapVert *EDBM_uv_vert_map_at_index(struct UvVertMap *vmap, unsigned int v); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index e668b6a39fa..2dbaa2998e3 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -527,7 +527,7 @@ enum { BUT_GET_TIP, BUT_GET_RNA_TIP, BUT_GET_RNAENUM_TIP, - BUT_GET_OP_KEYMAP, + BUT_GET_OP_KEYMAP }; typedef struct uiStringInfo { @@ -538,7 +538,7 @@ typedef struct uiStringInfo { /* Note: Expects pointers to uiStringInfo structs as parameters. * Will fill them with translated strings, when possible. * Strings in uiStringInfo must be MEM_freeN'ed by caller. */ -void uiButGetStrInfo(struct bContext *C, uiBut *but, const int nbr, ...); +void uiButGetStrInfo(struct bContext *C, uiBut *but, int nbr, ...); /* Edit i18n stuff. */ /* Name of the main py op from i18n addon. */ @@ -573,7 +573,7 @@ typedef void (*uiIDPoinFuncFP)(struct bContext *C, const char *str, struct ID ** typedef void (*uiIDPoinFunc)(struct bContext *C, struct ID *id, int event); uiBut *uiDefIDPoinBut(uiBlock *block, uiIDPoinFuncFP func, short blocktype, int retval, const char *str, - int x, int y, short width, short height, void *idpp, const char *tip); + int x, int y, short width, short height, void *idpp, const char *tip); int uiIconFromID(struct ID *id); @@ -624,7 +624,9 @@ void uiButSetNFunc(uiBut *but, uiButHandleNFunc func, void *argN, void void uiButSetCompleteFunc(uiBut *but, uiButCompleteFunc func, void *arg); -void uiBlockSetDrawExtraFunc(uiBlock *block, void (*func)(const struct bContext *C, void *, void *, void *, struct rcti *rect), void *arg1, void *arg2); +void uiBlockSetDrawExtraFunc(uiBlock *block, + void (*func)(const struct bContext *C, void *, void *, void *, struct rcti *rect), + void *arg1, void *arg2); void uiButSetFocusOnEnter(struct wmWindow *win, uiBut *but); diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index 3a8f05a76f0..792c96fe7c8 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -203,7 +203,7 @@ void UI_view2d_operatortypes(void); void UI_view2d_keymap(struct wmKeyConfig *keyconf); void UI_view2d_smooth_view(struct bContext *C, struct ARegion *ar, - const struct rctf *cur); + const struct rctf *cur); #endif /* __UI_VIEW2D_H__ */ diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index afbabaaa8d7..ffce2b618a3 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -33,7 +33,8 @@ #include #include #include - +#include /* offsetof() */ + #include "MEM_guardedalloc.h" #include "DNA_scene_types.h" @@ -41,7 +42,12 @@ #include "DNA_userdef_types.h" #include "BLI_math.h" -#include "BLI_blenlib.h" +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_string_utf8.h" +#include "BLI_path_util.h" +#include "BLI_rect.h" + #include "BLI_dynstr.h" #include "BLI_utildefines.h" @@ -50,7 +56,6 @@ #include "BKE_unit.h" #include "BKE_screen.h" #include "BKE_idprop.h" -#include "BKE_utildefines.h" /* FILE_MAX */ #include "BIF_gl.h" @@ -1077,8 +1082,12 @@ static void ui_is_but_sel(uiBut *but, double *value) int lvalue; UI_GET_BUT_VALUE_INIT(but, *value); lvalue = (int)*value; - if (BTST(lvalue, (but->bitnr)) ) is_push = is_true; - else is_push = !is_true; + if (UI_BITBUT_TEST(lvalue, (but->bitnr))) { + is_push = is_true; + } + else { + is_push = !is_true; + } } else { switch (but->type) { diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index ca52daa8cd2..54b391bca6b 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -501,9 +501,9 @@ static void ui_apply_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data) lvalue = (int)value; if (but->bit) { - w = BTST(lvalue, but->bitnr); - if (w) lvalue = BCLR(lvalue, but->bitnr); - else lvalue = BSET(lvalue, but->bitnr); + w = UI_BITBUT_TEST(lvalue, but->bitnr); + if (w) lvalue = UI_BITBUT_CLR(lvalue, but->bitnr); + else lvalue = UI_BITBUT_SET(lvalue, but->bitnr); if (but->type == TOGR) { if (!data->togonly) { @@ -605,27 +605,27 @@ static void ui_apply_but_TOG3(bContext *C, uiBut *but, uiHandleButtonData *data) if (but->pointype == SHO) { short *sp = (short *)but->poin; - if (BTST(sp[1], but->bitnr)) { - sp[1] = BCLR(sp[1], but->bitnr); - sp[0] = BCLR(sp[0], but->bitnr); + if (UI_BITBUT_TEST(sp[1], but->bitnr)) { + sp[1] = UI_BITBUT_CLR(sp[1], but->bitnr); + sp[0] = UI_BITBUT_CLR(sp[0], but->bitnr); } - else if (BTST(sp[0], but->bitnr)) { - sp[1] = BSET(sp[1], but->bitnr); + else if (UI_BITBUT_TEST(sp[0], but->bitnr)) { + sp[1] = UI_BITBUT_SET(sp[1], but->bitnr); } else { - sp[0] = BSET(sp[0], but->bitnr); + sp[0] = UI_BITBUT_SET(sp[0], but->bitnr); } } else { - if (BTST(*(but->poin + 2), but->bitnr)) { - *(but->poin + 2) = BCLR(*(but->poin + 2), but->bitnr); - *(but->poin) = BCLR(*(but->poin), but->bitnr); + if (UI_BITBUT_TEST(*(but->poin + 2), but->bitnr)) { + *(but->poin + 2) = UI_BITBUT_CLR(*(but->poin + 2), but->bitnr); + *(but->poin) = UI_BITBUT_CLR(*(but->poin), but->bitnr); } - else if (BTST(*(but->poin), but->bitnr)) { - *(but->poin + 2) = BSET(*(but->poin + 2), but->bitnr); + else if (UI_BITBUT_TEST(*(but->poin), but->bitnr)) { + *(but->poin + 2) = UI_BITBUT_SET(*(but->poin + 2), but->bitnr); } else { - *(but->poin) = BSET(*(but->poin), but->bitnr); + *(but->poin) = UI_BITBUT_SET(*(but->poin), but->bitnr); } } @@ -1187,12 +1187,20 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, else if (mode == 'c') { ui_get_but_vectorf(but, rgb); + /* convert to linear color to do compatible copy between gamma and non-gamma */ + if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) + srgb_to_linearrgb_v3_v3(rgb, rgb); + BLI_snprintf(buf, sizeof(buf), "[%f, %f, %f]", rgb[0], rgb[1], rgb[2]); WM_clipboard_text_set(buf, 0); } else { if (sscanf(buf, "[%f, %f, %f]", &rgb[0], &rgb[1], &rgb[2]) == 3) { + /* assume linear colors in buffer */ + if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) + linearrgb_to_srgb_v3_v3(rgb, rgb); + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); ui_set_but_vectorf(but, rgb); button_activate_state(C, but, BUTTON_STATE_EXIT); diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index dd3c2e491a7..1871f3c8336 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -59,7 +59,6 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_icons.h" -#include "BKE_utildefines.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 567109e26d0..d39fbbf7e61 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -131,6 +131,14 @@ typedef enum { /* for scope resize zone */ #define SCOPE_RESIZE_PAD 9 +/* bit button defines */ +/* Bit operations */ +#define UI_BITBUT_TEST(a, b) ( ( (a) & 1 << (b) ) != 0) +#define UI_BITBUT_SET(a, b) ( (a) | 1 << (b) ) +#define UI_BITBUT_CLR(a, b) ( (a) & ~(1 << (b)) ) +/* bit-row */ +#define UI_BITBUT_ROW(min, max) (((max) >= 31 ? 0xFFFFFFFF : (1 << (max + 1)) - 1) - ((min) ? ((1 << (min)) - 1) : 0) ) + typedef struct uiLinkLine { /* only for draw/edit */ struct uiLinkLine *next, *prev; struct uiBut *from, *to; diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 96c1b00d46d..301aea896bc 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -2021,27 +2021,20 @@ static void picker_new_hide_reveal(uiBlock *block, short colormode) /* tag buttons */ for (bt = block->buttons.first; bt; bt = bt->next) { - - if (bt->type == LABEL) { - if (bt->str[1] == 'G') { - if (colormode == 2) bt->flag &= ~UI_HIDDEN; - else bt->flag |= UI_HIDDEN; - } + if (bt->func == do_picker_rna_cb && bt->type == NUMSLI) { + /* RGB sliders (color circle is always shown) */ + if (colormode == 0) bt->flag &= ~UI_HIDDEN; + else bt->flag |= UI_HIDDEN; } - - if (bt->type == NUMSLI || bt->type == TEX) { - if (bt->str[1] == 'e') { - if (colormode == 2) bt->flag &= ~UI_HIDDEN; - else bt->flag |= UI_HIDDEN; - } - else if (ELEM3(bt->str[0], 'R', 'G', 'B')) { - if (colormode == 0) bt->flag &= ~UI_HIDDEN; - else bt->flag |= UI_HIDDEN; - } - else if (ELEM3(bt->str[0], 'H', 'S', 'V')) { - if (colormode == 1) bt->flag &= ~UI_HIDDEN; - else bt->flag |= UI_HIDDEN; - } + else if (bt->func == do_hsv_rna_cb) { + /* HSV sliders */ + if (colormode == 1) bt->flag &= ~UI_HIDDEN; + else bt->flag |= UI_HIDDEN; + } + else if (bt->func == do_hex_rna_cb || bt->type == LABEL) { + /* hex input or gamma correction status label */ + if (colormode == 2) bt->flag &= ~UI_HIDDEN; + else bt->flag |= UI_HIDDEN; } } } diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c index ee0613ea0d0..b16250021d3 100644 --- a/source/blender/editors/interface/interface_style.c +++ b/source/blender/editors/interface/interface_style.c @@ -257,7 +257,7 @@ uiStyle *UI_GetStyle(void) { uiStyle *style = NULL; /* offset is two struct uiStyle pointers */ - /* style = BLI_findstring( &U.uistyles, "Unifont Style", sizeof(style)*2 ) */; + /* style = BLI_findstring(&U.uistyles, "Unifont Style", sizeof(style) * 2) */; return (style != NULL) ? style : U.uistyles.first; } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 7e0fe4d277e..9aaafe28377 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2581,6 +2581,7 @@ void uiTemplateOperatorSearch(uiLayout *layout) #define B_STOPCOMPO 4 #define B_STOPSEQ 5 #define B_STOPCLIP 6 +#define B_STOPOTHER 7 static void do_running_jobs(bContext *C, void *UNUSED(arg), int event) { @@ -2603,6 +2604,9 @@ static void do_running_jobs(bContext *C, void *UNUSED(arg), int event) case B_STOPCLIP: WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL); break; + case B_STOPOTHER: + G.is_break = TRUE; + break; } } @@ -2642,6 +2646,10 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C) handle_event = B_STOPCOMPO; break; } + else if (WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY)) { + handle_event = B_STOPOTHER; + break; + } } owner = scene; } diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index ef8d8302fa7..9131c2744cd 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -46,7 +46,6 @@ #include "BKE_context.h" #include "BKE_curve.h" -#include "BKE_utildefines.h" #include "RNA_access.h" @@ -1257,9 +1256,9 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB if (but->type == BUT_TOGDUAL) { int dualset = 0; if (but->pointype == SHO) - dualset = BTST(*(((short *)but->poin) + 1), but->bitnr); + dualset = UI_BITBUT_TEST(*(((short *)but->poin) + 1), but->bitnr); else if (but->pointype == INT) - dualset = BTST(*(((int *)but->poin) + 1), but->bitnr); + dualset = UI_BITBUT_TEST(*(((int *)but->poin) + 1), but->bitnr); widget_draw_icon(but, ICON_DOT, dualset ? 1.0f : 0.25f, rect); } diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 229bbdbefb7..8f08c3afc36 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -160,7 +160,7 @@ typedef struct KnifeTool_OpData { int totlinehit; /* Data for mouse-position-derived data (cur) and previous click (prev) */ - KnifePosData cur, prev; + KnifePosData curr, prev; int totkedge, totkvert; @@ -290,7 +290,7 @@ static void knife_add_edge_faces_to_vert(KnifeTool_OpData *kcd, KnifeVert *kfv, } /* Find a face in common in the two faces lists. - If more than one, return the first; if none, return NULL */ + * If more than one, return the first; if none, return NULL */ static BMFace *knife_find_common_face(ListBase *faces1, ListBase *faces2) { Ref *ref1, *ref2; @@ -368,22 +368,22 @@ static KnifeEdge *get_bm_knife_edge(KnifeTool_OpData *kcd, BMEdge *e) * Copy the current position data into prev. */ static void knife_start_cut(KnifeTool_OpData *kcd) { - kcd->prev = kcd->cur; - kcd->cur.is_space = 0; /*TODO: why do we do this? */ + kcd->prev = kcd->curr; + kcd->curr.is_space = 0; /*TODO: why do we do this? */ if (kcd->prev.vert == NULL && kcd->prev.edge == NULL && is_zero_v3(kcd->prev.cage)) { /* Make prevcage a point on the view ray to mouse closest to a point on model: choose vertex 0 */ float origin[3], ray[3], co[3]; BMVert *v0; - knife_input_ray_cast(kcd, kcd->cur.mval, origin, ray); + knife_input_ray_cast(kcd, kcd->curr.mval, origin, ray); add_v3_v3v3(co, origin, ray); v0 = BM_vert_at_index(kcd->em->bm, 0); if (v0) { closest_to_line_v3(kcd->prev.cage, v0->co, co, origin); copy_v3_v3(kcd->prev.co, kcd->prev.cage); /*TODO: do we need this? */ - copy_v3_v3(kcd->cur.cage, kcd->prev.cage); - copy_v3_v3(kcd->cur.co, kcd->prev.co); + copy_v3_v3(kcd->curr.cage, kcd->prev.cage); + copy_v3_v3(kcd->curr.co, kcd->prev.co); } } } @@ -471,15 +471,15 @@ static KnifeVert *knife_split_edge(KnifeTool_OpData *kcd, KnifeEdge *kfe, float return newkfe->v2; } -/* Make a single KnifeEdge for cut from kcd->prev to kcd->cur. +/* Make a single KnifeEdge for cut from kcd->prev to kcd->curr. * and move cur data to prev. */ static void knife_add_single_cut(KnifeTool_OpData *kcd) { KnifeEdge *kfe = new_knife_edge(kcd), *kfe2 = NULL, *kfe3 = NULL; - if (kcd->prev.vert && kcd->prev.vert == kcd->cur.vert) + if (kcd->prev.vert && kcd->prev.vert == kcd->curr.vert) return; - if (kcd->prev.edge && kcd->prev.edge == kcd->cur.edge) + if (kcd->prev.edge && kcd->prev.edge == kcd->curr.edge) return; kfe->draw = 1; @@ -500,25 +500,25 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd) knife_append_list(kcd, &kfe->v1->faces, kcd->prev.bmface); } - if (kcd->cur.vert) { - kfe->v2 = kcd->cur.vert; + if (kcd->curr.vert) { + kfe->v2 = kcd->curr.vert; } - else if (kcd->cur.edge) { - kfe->v2 = knife_split_edge(kcd, kcd->cur.edge, kcd->cur.co, &kfe3); - kcd->cur.vert = kfe->v2; + else if (kcd->curr.edge) { + kfe->v2 = knife_split_edge(kcd, kcd->curr.edge, kcd->curr.co, &kfe3); + kcd->curr.vert = kfe->v2; } else { - kfe->v2 = new_knife_vert(kcd, kcd->cur.co, kcd->cur.co); - kfe->v2->draw = !kcd->cur.is_space; + kfe->v2 = new_knife_vert(kcd, kcd->curr.co, kcd->curr.co); + kfe->v2->draw = !kcd->curr.is_space; kfe->v2->isface = 1; - kfe->v2->inspace = kcd->cur.is_space; - if (kfe->v2->draw && kcd->cur.bmface) - knife_append_list(kcd, &kfe->v2->faces, kcd->cur.bmface); + kfe->v2->inspace = kcd->curr.is_space; + if (kfe->v2->draw && kcd->curr.bmface) + knife_append_list(kcd, &kfe->v2->faces, kcd->curr.bmface); - if (kcd->cur.is_space) + if (kcd->curr.is_space) kfe->draw = 0; - kcd->cur.vert = kfe->v2; + kcd->curr.vert = kfe->v2; } knife_find_basef(kfe); @@ -529,12 +529,12 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd) knife_edge_append_face(kcd, kfe, kfe->basef); /* sanity check to make sure we're in the right edge/face lists */ - if (kcd->cur.bmface) { - if (!find_ref(&kfe->faces, kcd->cur.bmface)) { - knife_edge_append_face(kcd, kfe, kcd->cur.bmface); + if (kcd->curr.bmface) { + if (!find_ref(&kfe->faces, kcd->curr.bmface)) { + knife_edge_append_face(kcd, kfe, kcd->curr.bmface); } - if (kcd->prev.bmface && kcd->prev.bmface != kcd->cur.bmface) { + if (kcd->prev.bmface && kcd->prev.bmface != kcd->curr.bmface) { if (!find_ref(&kfe->faces, kcd->prev.bmface)) { knife_edge_append_face(kcd, kfe, kcd->prev.bmface); } @@ -542,7 +542,7 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd) } /* set up for next cut */ - kcd->prev = kcd->cur; + kcd->prev = kcd->curr; } static int verge_linehit(const void *vlh1, const void *vlh2) @@ -554,6 +554,64 @@ static int verge_linehit(const void *vlh1, const void *vlh2) else return 0; } +/* If there's a linehit connected (same face) as testi in range [firsti, lasti], return the first such, else -1. + * If testi is out of range, look for connection to f instead, if f is non-NULL */ +static int find_connected_linehit(KnifeTool_OpData *kcd, int testi, BMFace *f, int firsti, int lasti) +{ + int i; + + for (i = firsti; i <= lasti; i++) { + if (testi >= 0 && testi < kcd->totlinehit) { + if (knife_find_common_face(&kcd->linehits[testi].kfe->faces, + &kcd->linehits[i].kfe->faces)) + return i; + } else if (f) { + if (find_ref(&kcd->linehits[i].kfe->faces, f)) + return i; + } + } + return -1; +} + +/* Sort in order of distance along cut line, but take care when distances are equal */ +static void knife_sort_linehits(KnifeTool_OpData *kcd) +{ + int i, j, k, nexti, nsame; + + qsort(kcd->linehits, kcd->totlinehit, sizeof(BMEdgeHit), verge_linehit); + + /* for ranges of equal "l", swap if neccesary to make predecessor and + * successor faces connected to the linehits at either end of the range */ + for (i = 0; i < kcd->totlinehit -1; i = nexti) { + for (j = i + 1; j < kcd->totlinehit; j++) { + if (fabsf(kcd->linehits[j].l - kcd->linehits[i].l) > 80*FLT_EPSILON) + break; + } + nexti = j; + j--; + nsame = j - i; + if (nsame > 0) { + /* find something connected to predecessor of equal range */ + k = find_connected_linehit(kcd, i - 1, kcd->prev.bmface, i, j); + if (k != -1) { + if (k != i) { + SWAP(BMEdgeHit, kcd->linehits[i], kcd->linehits[k]); + } + i++; + nsame--; + } + if (nsame > 0) { + /* find something connected to successor of equal range */ + k = find_connected_linehit(kcd, j + 1, kcd->curr.bmface, i, j); + if (k != -1 && k != j) { + SWAP(BMEdgeHit, kcd->linehits[j], kcd->linehits[k]); + } + } + /* rest of same range doesn't matter because we won't connect them */ + } + } +} + static void knife_add_single_cut_through(KnifeTool_OpData *kcd, KnifeVert *v1, KnifeVert *v2, BMFace *f) { KnifeEdge *kfenew; @@ -618,29 +676,30 @@ static void knife_cut_through(KnifeTool_OpData *kcd) return; } + /* TODO: probably don't need to sort at all */ qsort(kcd->linehits, kcd->totlinehit, sizeof(BMEdgeHit), verge_linehit); splitkfe = MEM_callocN(kcd->totlinehit * sizeof(KnifeEdge *), "knife_cut_through"); if (kcd->prev.vert) { - if (kcd->prev.vert == kcd->cur.vert) + if (kcd->prev.vert == kcd->curr.vert) return; firstv = kcd->prev.vert; knife_get_vert_faces(kcd, firstv, kcd->prev.bmface, &firstfaces); } else if (kcd->prev.edge) { - if (kcd->prev.edge == kcd->cur.edge) + if (kcd->prev.edge == kcd->curr.edge) return; firstv = knife_split_edge(kcd, kcd->prev.edge, kcd->prev.co, &kfe3); knife_get_edge_faces(kcd, kcd->prev.edge, &firstfaces); } - if (kcd->cur.vert) { - lastv = kcd->cur.vert; - knife_get_vert_faces(kcd, lastv, kcd->cur.bmface, &lastfaces); + if (kcd->curr.vert) { + lastv = kcd->curr.vert; + knife_get_vert_faces(kcd, lastv, kcd->curr.bmface, &lastfaces); } - else if (kcd->cur.edge) { - lastv = knife_split_edge(kcd, kcd->cur.edge, kcd->cur.co, &kfe3); - knife_get_edge_faces(kcd, kcd->cur.edge, &lastfaces); + else if (kcd->curr.edge) { + lastv = knife_split_edge(kcd, kcd->curr.edge, kcd->curr.co, &kfe3); + knife_get_edge_faces(kcd, kcd->curr.edge, &lastfaces); } if (firstv) { @@ -709,15 +768,15 @@ static void knife_cut_through(KnifeTool_OpData *kcd) kcd->totlinehit = 0; /* set up for next cut */ - kcd->prev = kcd->cur; + kcd->prev = kcd->curr; } /* User has just left-clicked after the first time. - * Add all knife cuts implied by line from prev to cur. + * Add all knife cuts implied by line from prev to curr. * If that line crossed edges then kcd->linehits will be non-NULL. */ static void knife_add_cut(KnifeTool_OpData *kcd) { - KnifePosData savcur = kcd->cur; + KnifePosData savcur = kcd->curr; if (kcd->cut_through) { knife_cut_through(kcd); @@ -726,8 +785,7 @@ static void knife_add_cut(KnifeTool_OpData *kcd) BMEdgeHit *lh, *lastlh, *firstlh; int i; - /* TODO: not a stable sort! need to figure out what to do for equal lambdas */ - qsort(kcd->linehits, kcd->totlinehit, sizeof(BMEdgeHit), verge_linehit); + knife_sort_linehits(kcd); lh = kcd->linehits; lastlh = firstlh = NULL; @@ -755,7 +813,11 @@ static void knife_add_cut(KnifeTool_OpData *kcd) if (len_v3v3(kcd->prev.cage, lh->realhit) < FLT_EPSILON * 80) continue; - if (len_v3v3(kcd->cur.cage, lh->realhit) < FLT_EPSILON * 80) + if (len_v3v3(kcd->curr.cage, lh->realhit) < FLT_EPSILON * 80) + continue; + + /* first linehit may be down face parallel to view */ + if (!lastlh && fabsf(lh->l) < FLT_EPSILON * 80) continue; if (kcd->prev.is_space) { @@ -768,12 +830,18 @@ static void knife_add_cut(KnifeTool_OpData *kcd) continue; } - kcd->cur.is_space = 0; - kcd->cur.edge = lh->kfe; - kcd->cur.bmface = lh->f; - kcd->cur.vert = lh->v; - copy_v3_v3(kcd->cur.co, lh->hit); - copy_v3_v3(kcd->cur.cage, lh->cagehit); + kcd->curr.is_space = 0; + kcd->curr.edge = lh->kfe; + kcd->curr.bmface = lh->f; + kcd->curr.vert = lh->v; + copy_v3_v3(kcd->curr.co, lh->hit); + copy_v3_v3(kcd->curr.cage, lh->cagehit); + + /* don't draw edges down faces parallel to view */ + if (lastlh && fabsf(lastlh->l - lh->l) < FLT_EPSILON * 80) { + kcd->prev = kcd->curr; + continue; + } knife_add_single_cut(kcd); } @@ -782,7 +850,7 @@ static void knife_add_cut(KnifeTool_OpData *kcd) kcd->prev = savcur; } else { - kcd->cur = savcur; + kcd->curr = savcur; knife_add_single_cut(kcd); } @@ -935,38 +1003,38 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) glBegin(GL_LINES); glVertex3fv(kcd->prev.cage); - glVertex3fv(kcd->cur.cage); + glVertex3fv(kcd->curr.cage); glEnd(); glLineWidth(1.0); } - if (kcd->cur.edge) { + if (kcd->curr.edge) { glColor3ubv(kcd->colors.edge); glLineWidth(2.0); glBegin(GL_LINES); - glVertex3fv(kcd->cur.edge->v1->cageco); - glVertex3fv(kcd->cur.edge->v2->cageco); + glVertex3fv(kcd->curr.edge->v1->cageco); + glVertex3fv(kcd->curr.edge->v2->cageco); glEnd(); glLineWidth(1.0); } - else if (kcd->cur.vert) { + else if (kcd->curr.vert) { glColor3ubv(kcd->colors.point); glPointSize(11); glBegin(GL_POINTS); - glVertex3fv(kcd->cur.cage); + glVertex3fv(kcd->curr.cage); glEnd(); } - if (kcd->cur.bmface) { + if (kcd->curr.bmface) { glColor3ubv(kcd->colors.curpoint); glPointSize(9); glBegin(GL_POINTS); - glVertex3fv(kcd->cur.cage); + glVertex3fv(kcd->curr.cage); glEnd(); } @@ -1113,7 +1181,7 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, KnifeEdge *kfe = ref->ref; if (BLI_smallhash_haskey(ehash, (intptr_t)kfe)) { - continue; // We already found a hit on this knife edge + continue; /* We already found a hit on this knife edge */ } if (isect_line_tri_v3(kfe->v1->cageco, kfe->v2->cageco, v1, v2, v3, &lambda, NULL)) { @@ -1121,13 +1189,17 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, interp_v3_v3v3(p, kfe->v1->cageco, kfe->v2->cageco, lambda); - if (kcd->cur.vert && len_squared_v3v3(kcd->cur.vert->cageco, p) < depsilon_squared) + if (kcd->curr.vert && len_squared_v3v3(kcd->curr.vert->cageco, p) < depsilon_squared) { continue; - if (kcd->prev.vert && len_squared_v3v3(kcd->prev.vert->cageco, p) < depsilon_squared) + } + if (kcd->prev.vert && len_squared_v3v3(kcd->prev.vert->cageco, p) < depsilon_squared) { continue; + } if (len_squared_v3v3(kcd->prev.cage, p) < depsilon_squared || - len_squared_v3v3(kcd->cur.cage, p) < depsilon_squared) + len_squared_v3v3(kcd->curr.cage, p) < depsilon_squared) + { continue; + } knife_project_v3(kcd, p, sp); view3d_unproject(mats, view, sp[0], sp[1], 0.0f); @@ -1135,15 +1207,17 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, if (kcd->cut_through) { hitf = FALSE; - } else { + } + else { /* check if this point is visible in the viewport */ float p1[3], lambda1; /* if face isn't planer, p may be behind the current tesselated tri, - so move it onto that and then a little towards eye */ + * so move it onto that and then a little towards eye */ if (isect_line_tri_v3(p, view, ls[0]->v->co, ls[1]->v->co, ls[2]->v->co, &lambda1, NULL)) { interp_v3_v3v3(p1, p, view, lambda1); - } else { + } + else { copy_v3_v3(p1, p); } sub_v3_v3(view, p1); @@ -1163,9 +1237,11 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, if (!hitf && !BLI_smallhash_haskey(ehash, (intptr_t)kfe)) { BMEdgeHit hit; - if (len_squared_v3v3(p, kcd->cur.co) < depsilon_squared || + if (len_squared_v3v3(p, kcd->curr.co) < depsilon_squared || len_squared_v3v3(p, kcd->prev.co) < depsilon_squared) + { continue; + } hit.kfe = kfe; hit.v = NULL; @@ -1185,15 +1261,18 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, /* select the closest from the edge endpoints or the midpoint */ if (perc < 0.25f) { perc = 0.0f; - } else if (perc < 0.75f) { + } + else if (perc < 0.75f) { perc = 0.5f; - } else { + } + else { perc = 1.0f; } interp_v3_v3v3(hit.hit, kfe->v1->co, kfe->v2->co, perc); interp_v3_v3v3(hit.cagehit, kfe->v1->cageco, kfe->v2->cageco, perc); - } else { + } + else { copy_v3_v3(hit.hit, p); } knife_project_v3(kcd, hit.cagehit, hit.schit); @@ -1239,7 +1318,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) } copy_v3_v3(v1, kcd->prev.cage); - copy_v3_v3(v2, kcd->cur.cage); + copy_v3_v3(v2, kcd->curr.cage); /* project screen line's 3d coordinates back into 2d */ knife_project_v3(kcd, v1, s1); @@ -1435,7 +1514,7 @@ static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], flo copy_v3_v3(p, co); copy_v3_v3(cagep, cageco); - kcd->cur.bmface = f; + kcd->curr.bmface = f; if (f) { KnifeEdge *cure = NULL; @@ -1499,8 +1578,8 @@ static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], flo /* update mouse coordinates to the snapped-to edge's screen coordinates * this is important for angle snap, which uses the previous mouse position */ edgesnap = new_knife_vert(kcd, p, cagep); - kcd->cur.mval[0] = (int)edgesnap->sco[0]; - kcd->cur.mval[1] = (int)edgesnap->sco[1]; + kcd->curr.mval[0] = (int)edgesnap->sco[0]; + kcd->curr.mval[1] = (int)edgesnap->sco[1]; } else { @@ -1532,7 +1611,7 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo /* set p to co, in case we don't find anything, means a face cut */ copy_v3_v3(p, co); copy_v3_v3(cagep, p); - kcd->cur.bmface = f; + kcd->curr.bmface = f; if (f) { ListBase *lst; @@ -1583,8 +1662,8 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo /* update mouse coordinates to the snapped-to vertex's screen coordinates * this is important for angle snap, which uses the previous mouse position */ - kcd->cur.mval[0] = (int)curv->sco[0]; - kcd->cur.mval[1] = (int)curv->sco[1]; + kcd->curr.mval[0] = (int)curv->sco[0]; + kcd->curr.mval[1] = (int)curv->sco[1]; } return curv; @@ -1641,30 +1720,30 @@ static int knife_update_active(KnifeTool_OpData *kcd) if (kcd->angle_snapping != ANGLE_FREE && kcd->mode == MODE_DRAGGING) knife_snap_angle(kcd); - knife_pos_data_clear(&kcd->cur); - kcd->cur.mval[0] = kcd->vc.mval[0]; - kcd->cur.mval[1] = kcd->vc.mval[1]; + knife_pos_data_clear(&kcd->curr); + kcd->curr.mval[0] = kcd->vc.mval[0]; + kcd->curr.mval[1] = kcd->vc.mval[1]; /* XXX knife_snap_angle updates the view coordinate mouse values to constrained angles, * which current mouse values are set to current mouse values are then used * for vertex and edge snap detection, without regard to the exact angle constraint */ - kcd->cur.vert = knife_find_closest_vert(kcd, kcd->cur.co, kcd->cur.cage, &kcd->cur.bmface, &kcd->cur.is_space); + kcd->curr.vert = knife_find_closest_vert(kcd, kcd->curr.co, kcd->curr.cage, &kcd->curr.bmface, &kcd->curr.is_space); - if (!kcd->cur.vert) { - kcd->cur.edge = knife_find_closest_edge(kcd, kcd->cur.co, kcd->cur.cage, &kcd->cur.bmface, &kcd->cur.is_space); + if (!kcd->curr.vert) { + kcd->curr.edge = knife_find_closest_edge(kcd, kcd->curr.co, kcd->curr.cage, &kcd->curr.bmface, &kcd->curr.is_space); } /* if no hits are found this would normally default to (0, 0, 0) so instead * get a point at the mouse ray closest to the previous point. * Note that drawing lines in `free-space` isn't properly supported * but theres no guarantee (0, 0, 0) has any geometry either - campbell */ - if (kcd->cur.vert == NULL && kcd->cur.edge == NULL) { + if (kcd->curr.vert == NULL && kcd->curr.edge == NULL) { float origin[3], ray[3], co[3]; knife_input_ray_cast(kcd, kcd->vc.mval, origin, ray); add_v3_v3v3(co, origin, ray); - closest_to_line_v3(kcd->cur.cage, kcd->prev.cage, co, origin); + closest_to_line_v3(kcd->curr.cage, kcd->prev.cage, co, origin); } if (kcd->mode == MODE_DRAGGING) { @@ -2872,7 +2951,7 @@ static int knifetool_init(bContext *C, wmOperator *op, int UNUSED(do_cut)) /* can't usefully select resulting edges in face mode */ kcd->select_result = (kcd->em->selectmode != SCE_SELECT_FACE); - knife_pos_data_clear(&kcd->cur); + knife_pos_data_clear(&kcd->curr); knife_pos_data_clear(&kcd->prev); knife_init_colors(&kcd->colors); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 765091a3d1d..a9e8c253c82 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2221,7 +2221,7 @@ static void deselect_nth_active(BMEditMesh *em, BMVert **r_eve, BMEdge **r_eed, } } else if (em->selectmode & SCE_SELECT_FACE) { - f = BM_active_face_get(em->bm, TRUE); + f = BM_active_face_get(em->bm, TRUE, FALSE); if (f) { *r_efa = f; return; diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 6b7409cd031..a111c2ffafb 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -580,6 +580,7 @@ static void undoMesh_to_editbtMesh(void *umv, void *em_v, void *UNUSED(obdata)) *em = *em_tmp; em->selectmode = um->selectmode; + bm->selectmode = um->selectmode; em->ob = ob; MEM_freeN(em_tmp); @@ -991,15 +992,15 @@ void EDBM_uv_element_map_free(UvElementMap *element_map) /* last_sel, use em->act_face otherwise get the last selected face in the editselections * at the moment, last_sel is mainly useful for making sure the space image dosnt flicker */ -MTexPoly *EDBM_mtexpoly_active_get(BMEditMesh *em, BMFace **r_act_efa, int sloppy) +MTexPoly *EDBM_mtexpoly_active_get(BMEditMesh *em, BMFace **r_act_efa, int sloppy, int selected) { BMFace *efa = NULL; if (!EDBM_mtexpoly_check(em)) return NULL; - efa = BM_active_face_get(em->bm, sloppy); - + efa = BM_active_face_get(em->bm, sloppy, selected); + if (efa) { if (r_act_efa) *r_act_efa = efa; return CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 19ca30b9c45..09d89a961e4 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -43,10 +43,10 @@ #include "DNA_view3d_types.h" #include "BLI_utildefines.h" +#include "BLI_path_util.h" #include "BLI_array.h" #include "BLI_math.h" #include "BLI_edgehash.h" -#include "BLI_utildefines.h" #include "BKE_context.h" #include "BKE_depsgraph.h" diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c index 14d20d68455..88b1f191e3a 100644 --- a/source/blender/editors/mesh/mesh_navmesh.c +++ b/source/blender/editors/mesh/mesh_navmesh.c @@ -491,7 +491,7 @@ static int navmesh_face_copy_exec(bContext *C, wmOperator *op) BMEditMesh *em = BMEdit_FromObject(obedit); /* do work here */ - BMFace *efa_act = BM_active_face_get(em->bm, FALSE); + BMFace *efa_act = BM_active_face_get(em->bm, FALSE, FALSE); if (efa_act) { if (CustomData_has_layer(&em->bm->pdata, CD_RECAST)) { diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index c4616fc39c6..b13a299c4c7 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -1682,6 +1682,10 @@ void ED_vgroup_mirror(Object *ob, const short mirror_weights, const short flip_v } } + /* flip active group index */ + if (flip_vgroups && flip_map[def_nr] >= 0) + ob->actdef = flip_map[def_nr] + 1; + cleanup: if (flip_map) MEM_freeN(flip_map); @@ -1782,6 +1786,21 @@ static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg) if (ob->actdef < 1 && ob->defbase.first) ob->actdef = 1; + /* remove all dverts */ + if (ob->defbase.first == NULL) { + if (ob->type == OB_MESH) { + Mesh *me = ob->data; + CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert); + me->dvert = NULL; + } + else if (ob->type == OB_LATTICE) { + Lattice *lt = ob->data; + if (lt->dvert) { + MEM_freeN(lt->dvert); + lt->dvert = NULL; + } + } + } } /* only in editmode */ @@ -2674,7 +2693,7 @@ void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot) /* properties */ RNA_def_boolean(ot->srna, "mirror_weights", TRUE, "Mirror Weights", "Mirror weights"); - RNA_def_boolean(ot->srna, "flip_group_names", TRUE, "Flip Groups", "Flip vertex group names"); + RNA_def_boolean(ot->srna, "flip_group_names", TRUE, "Flip Group Names", "Flip vertex group names"); RNA_def_boolean(ot->srna, "all_groups", FALSE, "All Groups", "Mirror all vertex groups weights"); } diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 35db9658f39..b05766d3201 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -5339,12 +5339,25 @@ static void toggle_paint_cursor(bContext *C, int enable) * ensure that the cursor is hidden when not in paint mode */ void ED_space_image_paint_update(wmWindowManager *wm, ToolSettings *settings) { + wmWindow *win; + ScrArea *sa; ImagePaintSettings *imapaint = &settings->imapaint; + int enabled = FALSE; - if (!imapaint->paintcursor) { - imapaint->paintcursor = - WM_paint_cursor_activate(wm, image_paint_poll, - brush_drawcursor, NULL); + for (win = wm->windows.first; win; win = win->next) + for (sa = win->screen->areabase.first; sa; sa = sa->next) + if (sa->spacetype == SPACE_IMAGE) + if (((SpaceImage*)sa->spacedata.first)->mode == SI_MODE_PAINT) + enabled = TRUE; + + if (enabled) { + BKE_paint_init(&imapaint->paint, PAINT_CURSOR_TEXTURE_PAINT); + + if (!imapaint->paintcursor) { + imapaint->paintcursor = + WM_paint_cursor_activate(wm, image_paint_poll, + brush_drawcursor, NULL); + } } } diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index 104f727c603..cc71be4938e 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -584,19 +584,21 @@ static void ed_keymap_paint_brush_radial_control(wmKeyMap *keymap, const char *p RCFlags flags) { wmKeyMapItem *kmi; + /* only size needs to follow zoom, strength shows fixed size circle */ + int flags_nozoom = flags & (~RC_ZOOM); kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, 0, 0); set_brush_rc_props(kmi->ptr, paint, "size", "use_unified_size", flags); kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0); - set_brush_rc_props(kmi->ptr, paint, "strength", "use_unified_strength", flags); + set_brush_rc_props(kmi->ptr, paint, "strength", "use_unified_strength", flags_nozoom); kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", WKEY, KM_PRESS, 0, 0); - set_brush_rc_props(kmi->ptr, paint, "weight", "use_unified_weight", flags); + set_brush_rc_props(kmi->ptr, paint, "weight", "use_unified_weight", flags_nozoom); if (flags & RC_ROTATION) { kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_CTRL, 0); - set_brush_rc_props(kmi->ptr, paint, "texture_slot.angle", NULL, flags); + set_brush_rc_props(kmi->ptr, paint, "texture_slot.angle", NULL, flags_nozoom); } } diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index d232a86f9e5..cff1f987da6 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -392,11 +392,12 @@ static void image_refresh(const bContext *C, ScrArea *sa) else if (obedit && obedit->type == OB_MESH) { Mesh *me = (Mesh *)obedit->data; struct BMEditMesh *em = me->edit_btmesh; - int sloppy = 1; /* partially selected face is ok */ + int sloppy = TRUE; /* partially selected face is ok */ + int selected = !(scene->toolsettings->uv_flag & UV_SYNC_SELECTION); /* only selected active face? */ if (BKE_scene_use_new_shading_nodes(scene)) { /* new shading system, get image from material */ - BMFace *efa = BM_active_face_get(em->bm, sloppy); + BMFace *efa = BM_active_face_get(em->bm, sloppy, selected); if (efa) { Image *node_ima; @@ -413,8 +414,8 @@ static void image_refresh(const bContext *C, ScrArea *sa) if (em && EDBM_mtexpoly_check(em)) { sima->image = NULL; - tf = EDBM_mtexpoly_active_get(em, NULL, TRUE); /* partially selected face is ok */ - + tf = EDBM_mtexpoly_active_get(em, NULL, sloppy, selected); + if (tf) { /* don't need to check for pin here, see above */ sima->image = tf->tpage; diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index a05bc5eddc7..4472ff280e9 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -2378,7 +2378,11 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base } glDisable(GL_BLEND); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); - + + /* before disposing of temp pose, use it to restore object to a sane state */ + BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)cfrao, ADT_RECALC_ALL); + + /* clean up temporary pose */ ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */ BKE_pose_free(posen); @@ -2386,7 +2390,6 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base CFRA = cfrao; ob->pose = poseo; arm->flag = flago; - BKE_pose_rebuild(ob, ob->data); ob->mode |= OB_MODE_POSE; ob->ipoflag = ipoflago; } @@ -2457,7 +2460,11 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base * } glDisable(GL_BLEND); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); - + + /* before disposing of temp pose, use it to restore object to a sane state */ + BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)cfrao, ADT_RECALC_ALL); + + /* clean up temporary pose */ ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */ BLI_dlrbTree_free(&keys); BKE_pose_free(posen); @@ -2466,7 +2473,6 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base * CFRA = cfrao; ob->pose = poseo; arm->flag = flago; - BKE_pose_rebuild(ob, ob->data); ob->mode |= OB_MODE_POSE; } @@ -2544,7 +2550,11 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) } glDisable(GL_BLEND); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); - + + /* before disposing of temp pose, use it to restore object to a sane state */ + BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)cfrao, ADT_RECALC_ALL); + + /* clean up temporary pose */ ghost_poses_tag_unselected(ob, 1); /* unhide unselected bones if need be */ BKE_pose_free(posen); @@ -2552,7 +2562,6 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base) CFRA = cfrao; ob->pose = poseo; arm->flag = flago; - BKE_pose_rebuild(ob, ob->data); ob->mode |= OB_MODE_POSE; } diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index 5069c4219c3..d2b3bcf6825 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -772,7 +772,8 @@ static int compareDrawOptionsEm(void *userData, int cur_index, int next_index) return 1; } -void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, int draw_flags) +void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d, + Object *ob, DerivedMesh *dm, const int draw_flags) { Mesh *me = ob->data; @@ -871,7 +872,7 @@ static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs) if (ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node)) { /* get openl texture */ int mipmap = 1; - int bindcode = (ima) ? GPU_verify_image(ima, iuser, 0, 0, mipmap) : 0; + int bindcode = (ima) ? GPU_verify_image(ima, iuser, 0, 0, mipmap, FALSE) : 0; float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; if (bindcode) { @@ -941,7 +942,8 @@ static int tex_mat_set_face_editmesh_cb(void *userData, int index) return !BM_elem_flag_test(efa, BM_ELEM_HIDDEN); } -void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, const int draw_flags) +void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, + Object *ob, DerivedMesh *dm, const int draw_flags) { if ((!BKE_scene_use_new_shading_nodes(scene)) || (draw_flags & DRAW_MODIFIERS_PREVIEW)) { draw_mesh_textured_old(scene, v3d, rv3d, ob, dm, draw_flags); @@ -1017,7 +1019,8 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *o /* Vertex Paint and Weight Paint */ -void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, int draw_flags) +void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d, + Object *ob, DerivedMesh *dm, const int draw_flags) { DMSetDrawOptions facemask = NULL; Mesh *me = ob->data; diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 8e9776e0e17..9ebd2351142 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -3164,7 +3164,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, { Mesh *me = ob->data; - BMFace *efa_act = BM_active_face_get(em->bm, FALSE); /* annoying but active faces is stored differently */ + BMFace *efa_act = BM_active_face_get(em->bm, FALSE, FALSE); /* annoying but active faces is stored differently */ BMEdge *eed_act = NULL; BMVert *eve_act = NULL; @@ -3761,12 +3761,14 @@ static int drawDispListwire(ListBase *dlbase) } glEnd(); -/* (ton) this code crashes for me when resolv is 86 or higher... no clue */ -// glVertexPointer(3, GL_FLOAT, sizeof(float)*3*dl->nr, data + 3*nr); -// if (dl->flag & DL_CYCL_V) -// glDrawArrays(GL_LINE_LOOP, 0, dl->parts); -// else -// glDrawArrays(GL_LINE_STRIP, 0, dl->parts); +#if 0 + /* (ton) this code crashes for me when resolv is 86 or higher... no clue */ + glVertexPointer(3, GL_FLOAT, sizeof(float) * 3 * dl->nr, data + 3*nr); + if (dl->flag & DL_CYCL_V) + glDrawArrays(GL_LINE_LOOP, 0, dl->parts); + else + glDrawArrays(GL_LINE_STRIP, 0, dl->parts); +#endif } break; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 10352033741..97130390c14 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -48,6 +48,7 @@ #include "BLI_math.h" #include "BLI_rand.h" #include "BLI_utildefines.h" +#include "BLI_endian_switch.h" #include "BKE_anim.h" #include "BKE_camera.h" @@ -1397,7 +1398,9 @@ unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y) glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); glReadBuffer(GL_BACK); - if (ENDIAN_ORDER == B_ENDIAN) SWITCH_INT(col); + if (ENDIAN_ORDER == B_ENDIAN) { + BLI_endian_switch_uint32(&col); + } return WM_framebuffer_to_index(col); } diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 71e87e73747..5bfabf4fc4a 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -175,7 +175,7 @@ void VIEW3D_OT_game_start(struct wmOperatorType *ot); int ED_view3d_boundbox_clip(RegionView3D * rv3d, float obmat[][4], struct BoundBox *bb); void view3d_smooth_view(struct bContext *C, struct View3D *v3d, struct ARegion *ar, struct Object *, struct Object *, - float *ofs, float *quat, float *dist, float *lens); + float *ofs, float *quat, float *dist, float *lens); void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect); /* rect: for picking */ void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 6f3cc744537..d8e394ab68c 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -2268,6 +2268,7 @@ static void paint_facesel_circle_select(ViewContext *vc, int select, const int m /* bbsel= */ /* UNUSED */ EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); edbm_backbuf_check_and_select_tfaces(me, select == LEFTMOUSE); EDBM_backbuf_free(); + paintface_flush_flags(ob); } } diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 8259ca64bad..fa7964b31ca 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2431,8 +2431,9 @@ void initWarp(TransInfo *t) mul_m3_v3(t->data[i].mtx, center); mul_m4_v3(t->viewmat, center); sub_v3_v3(center, t->viewmat[3]); - if (i) + if (i) { minmax_v3v3_v3(min, max, center); + } else { copy_v3_v3(max, center); copy_v3_v3(min, center); @@ -2739,12 +2740,14 @@ static void headerResize(TransInfo *t, float vec[3], char *str) } } else { - if (t->flag & T_2D_EDIT) + if (t->flag & T_2D_EDIT) { spos += sprintf(spos, "Scale X: %s Y: %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], t->con.text, t->proptext); - else + } + else { spos += sprintf(spos, "Scale X: %s Y: %s Z: %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); + } } if (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) { @@ -3647,9 +3650,10 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) { int i, do_split = t->scene->unit.flag & USER_UNIT_OPT_SPLIT ? 1 : 0; - for (i = 0; i < 3; i++) + for (i = 0; i < 3; i++) { bUnit_AsString(&tvec[i * NUM_STR_REP_LEN], NUM_STR_REP_LEN, dvec[i] * t->scene->unit.scale_length, 4, t->scene->unit.system, B_UNIT_LENGTH, do_split, 1); + } } else { sprintf(&tvec[0], "%.4f", dvec[0]); @@ -3691,12 +3695,14 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) } } else { - if (t->flag & T_2D_EDIT) + if (t->flag & T_2D_EDIT) { spos += sprintf(spos, "Dx: %s Dy: %s (%s)%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], distvec, t->con.text, t->proptext); - else + } + else { spos += sprintf(spos, "Dx: %s Dy: %s Dz: %s (%s)%s %s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], distvec, t->con.text, t->proptext, &autoik[0]); + } } if (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) { @@ -4753,7 +4759,7 @@ static int createSlideVerts(TransInfo *t) BMEditMesh *em = me->edit_btmesh; BMesh *bm = em->bm; BMIter iter, iter2; - BMEdge *e, *e1 /*, *ee, *le */ /* UNUSED */; + BMEdge *e, *e1; BMVert *v, *v2, *first; BMLoop *l, *l1, *l2; TransDataSlideVert *sv_array; @@ -4765,9 +4771,10 @@ static int createSlideVerts(TransInfo *t) ARegion *ar = t->ar; float projectMat[4][4]; float mval[2] = {(float)t->mval[0], (float)t->mval[1]}; - float start[3] = {0.0f, 0.0f, 0.0f}, dir[3], end[3] = {0.0f, 0.0f, 0.0f}; + float start[3] = {0.0f, 0.0f, 0.0f}, end[3] = {0.0f, 0.0f, 0.0f}; float vec[3], vec2[3] /*, lastvec[3], size, dis=0.0, z */ /* UNUSED */; - int numsel, i, j; + float dir[3], maxdist, (*loop_dir)[3], *loop_maxdist; + int numsel, i, j, loop_nr, l_nr; if (t->spacetype == SPACE_VIEW3D) { /* background mode support */ @@ -4842,6 +4849,7 @@ static int createSlideVerts(TransInfo *t) } sv_array = MEM_callocN(sizeof(TransDataSlideVert) * j, "sv_array"); + loop_nr = 0; j = 0; while (1) { @@ -4904,6 +4912,8 @@ static int createSlideVerts(TransInfo *t) sv->v = v; sv->origvert = *v; + sv->loop_nr = loop_nr; + copy_v3_v3(sv->upvec, vec); if (l2) copy_v3_v3(sv->downvec, vec2); @@ -4926,6 +4936,7 @@ static int createSlideVerts(TransInfo *t) sv = sv_array + j + 1; sv->v = v; sv->origvert = *v; + sv->loop_nr = loop_nr; l = BM_face_other_edge_loop(l1->f, l1->e, v); sv->up = BM_edge_other_vert(l->e, v); @@ -4952,6 +4963,8 @@ static int createSlideVerts(TransInfo *t) BM_elem_flag_disable(v, BM_ELEM_TAG); BM_elem_flag_disable(v2, BM_ELEM_TAG); } while (e != first->e && l1); + + loop_nr++; } /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */ @@ -4959,21 +4972,24 @@ static int createSlideVerts(TransInfo *t) sld->sv = sv_array; sld->totsv = j; - /*find mouse vector*/ - /* dis = z = -1.0f; */ /* UNUSED */ - /* size = 50.0; */ /* UNUSED */ - /* zero_v3(lastvec); */ /* UNUSED */ + /* find mouse vectors, the global one, and one per loop in case we have + * multiple loops selected, in case they are oriented different */ zero_v3(dir); - /* ee = le = NULL; */ /* UNUSED */ + maxdist = -1.0f; + + loop_dir = MEM_callocN(sizeof(float) * 3 * loop_nr, "sv loop_dir"); + loop_maxdist = MEM_callocN(sizeof(float) * loop_nr, "sv loop_maxdist"); + for (j = 0; j < loop_nr; j++) + loop_maxdist[j] = -1.0f; + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { BMIter iter2; BMEdge *e2; - float vec1[3], dis2, mval[2] = {t->mval[0], t->mval[1]}, d; + float vec1[3], mval[2] = {t->mval[0], t->mval[1]}, d; /* search cross edges for visible edge to the mouse cursor, * then use the shared vertex to calculate screen vector*/ - dis2 = -1.0f; for (i = 0; i < 2; i++) { v = i ? e->v1 : e->v2; BM_ITER_ELEM (e2, &iter2, v, BM_EDGES_OF_VERT) { @@ -5001,17 +5017,23 @@ static int createSlideVerts(TransInfo *t) ED_view3d_project_float_v3(ar, sv_array[j].up->co, vec2, projectMat); } else { - add_v3_v3v3(vec1, v->co, sv_array[j].upvec); + add_v3_v3v3(vec2, v->co, sv_array[j].upvec); ED_view3d_project_float_v3(ar, vec2, vec2, projectMat); } - + + /* global direction */ d = dist_to_line_segment_v2(mval, vec1, vec2); - if (dis2 == -1.0f || d < dis2) { - dis2 = d; - /* ee = e2; */ /* UNUSED */ - /* size = len_v3v3(vec1, vec2); */ /* UNUSED */ + if (maxdist == -1.0f || d < maxdist) { + maxdist = d; sub_v3_v3v3(dir, vec1, vec2); } + + /* per loop direction */ + l_nr = sv_array[j].loop_nr; + if (loop_maxdist[l_nr] == -1.0f || d < loop_maxdist[l_nr]) { + loop_maxdist[l_nr] = d; + sub_v3_v3v3(loop_dir[l_nr], vec1, vec2); + } } } } @@ -5045,6 +5067,14 @@ static int createSlideVerts(TransInfo *t) } BLI_smallhash_insert(&sld->vhash, (uintptr_t)sv_array->v, sv_array); + + /* switch up/down if loop direction is different from global direction */ + l_nr = sv_array->loop_nr; + if (dot_v3v3(loop_dir[l_nr], dir) < 0.0f) { + swap_v3_v3(sv_array->upvec, sv_array->downvec); + SWAP(BMVert, sv_array->vup, sv_array->vdown); + SWAP(BMVert*, sv_array->up, sv_array->down); + } } if (rv3d) @@ -5055,7 +5085,7 @@ static int createSlideVerts(TransInfo *t) /*zero out start*/ zero_v3(start); - + /*dir holds a vector along edge loop*/ copy_v3_v3(end, dir); mul_v3_fl(end, 0.5f); @@ -5072,6 +5102,8 @@ static int createSlideVerts(TransInfo *t) BLI_smallhash_release(&table); BMBVH_FreeBVH(btree); + MEM_freeN(loop_dir); + MEM_freeN(loop_maxdist); return 1; } diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 8a7148aad95..e645cb2fed6 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -198,6 +198,8 @@ typedef struct TransDataSlideVert { float edge_len; float upvec[3], downvec[3]; + + int loop_nr; } TransDataSlideVert; typedef struct SlideData { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 7f77341447d..e635c4b3fb8 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -4990,7 +4990,7 @@ void autokeyframe_pose_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *o static void special_aftertrans_update__mask(bContext *C, TransInfo *t) { - Mask *mask; + Mask *mask = NULL; if (t->spacetype == SPACE_CLIP) { SpaceClip *sc = t->sa->spacedata.first; diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 89cb83e3661..b88ae68e00b 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -410,9 +410,8 @@ static void initSnappingMode(TransInfo *t) } else { /* force project off when not supported */ - if (ts->snap_mode != SCE_SNAP_MODE_FACE) { + if (t->spacetype == SPACE_IMAGE || ts->snap_mode != SCE_SNAP_MODE_FACE) t->tsnap.project = 0; - } t->tsnap.mode = ts->snap_mode; } diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 6d9f2732d8a..b0a2a24f25b 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -45,10 +45,10 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_main.h" -#include "BKE_utildefines.h" #include "BKE_packedFile.h" #include "ED_armature.h" +#include "ED_image.h" #include "ED_mesh.h" #include "ED_object.h" #include "ED_sculpt.h" @@ -67,6 +67,7 @@ void ED_editors_init(bContext *C) { + wmWindowManager *wm = CTX_wm_manager(C); Main *bmain = CTX_data_main(C); Scene *sce = CTX_data_scene(C); Object *ob, *obact = (sce && sce->basact) ? sce->basact->object : NULL; @@ -86,6 +87,9 @@ void ED_editors_init(bContext *C) ED_object_toggle_modes(C, mode); } } + + /* image editor paint mode */ + ED_space_image_paint_update(wm, sce->toolsettings); } /* frees all editmode stuff */ diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 1f78bc6bddf..d6794912043 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -415,7 +415,7 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob) glColor3ub(112, 112, 112); - if (me->mtface) { + if (me->mtpoly) { MPoly *mpoly = me->mpoly; MTexPoly *tface = me->mtpoly; MLoopUV *mloopuv; @@ -455,8 +455,8 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) StitchPreviewer *stitch_preview = uv_get_stitch_previewer(); - activetf = EDBM_mtexpoly_active_get(em, &efa_act, FALSE); /* will be set to NULL if hidden */ - activef = BM_active_face_get(bm, FALSE); + activetf = EDBM_mtexpoly_active_get(em, &efa_act, FALSE, FALSE); /* will be set to NULL if hidden */ + activef = BM_active_face_get(bm, FALSE, FALSE); ts = scene->toolsettings; drawfaces = draw_uvs_face_check(scene); diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 6f3e6bee850..5008c35e46a 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -174,6 +174,8 @@ void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *im BMIter iter; MTexPoly *tf; int update = 0; + int sloppy = TRUE; + int selected = !(scene->toolsettings->uv_flag & UV_SYNC_SELECTION); /* skip assigning these procedural images... */ if (ima && (ima->type == IMA_TYPE_R_RESULT || ima->type == IMA_TYPE_COMPOSITE)) @@ -190,8 +192,7 @@ void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *im if (BKE_scene_use_new_shading_nodes(scene)) { /* new shading system, assign image in material */ - int sloppy = 1; - BMFace *efa = BM_active_face_get(em->bm, sloppy); + BMFace *efa = BM_active_face_get(em->bm, sloppy, selected); if (efa) ED_object_assign_active_image(bmain, obedit, efa->mat_nr + 1, ima); @@ -2056,7 +2057,7 @@ static void UV_OT_select(wmOperatorType *ot) ot->name = "Select"; ot->description = "Select UV vertices"; ot->idname = "UV_OT_select"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->flag = OPTYPE_UNDO; /* api callbacks */ ot->exec = select_exec; @@ -2101,7 +2102,7 @@ static void UV_OT_select_loop(wmOperatorType *ot) ot->name = "Loop Select"; ot->description = "Select a loop of connected UV vertices"; ot->idname = "UV_OT_select_loop"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->flag = OPTYPE_UNDO; /* api callbacks */ ot->exec = select_loop_exec; @@ -2203,7 +2204,7 @@ static void UV_OT_select_linked_pick(wmOperatorType *ot) ot->name = "Select Linked Pick"; ot->description = "Select all UV vertices linked under the mouse"; ot->idname = "UV_OT_select_linked_pick"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->flag = OPTYPE_UNDO; /* api callbacks */ ot->invoke = select_linked_pick_invoke; diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index b4903390408..c1fb3ee3807 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -192,7 +192,10 @@ static ParamHandle *construct_param_handle(Scene *scene, BMEditMesh *em, handle = param_construct_begin(); if (correct_aspect) { - efa = BM_active_face_get(em->bm, TRUE); + int sloppy = TRUE; + int selected = FALSE; + + efa = BM_active_face_get(em->bm, sloppy, selected); if (efa) { float aspx, aspy; @@ -380,7 +383,10 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, BMEditMesh *e handle = param_construct_begin(); if (correct_aspect) { - editFace = BM_active_face_get(em->bm, TRUE); + int sloppy = TRUE; + int selected = FALSE; + + editFace = BM_active_face_get(em->bm, sloppy, selected); if (editFace) { MTexPoly *tf; @@ -1003,7 +1009,9 @@ static void uv_transform_properties(wmOperatorType *ot, int radius) static void correct_uv_aspect(BMEditMesh *em) { - BMFace *efa = BM_active_face_get(em->bm, TRUE); + int sloppy = TRUE; + int selected = FALSE; + BMFace *efa = BM_active_face_get(em->bm, sloppy, selected); BMLoop *l; BMIter iter, liter; MLoopUV *luv; diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h index 629283ce50d..1729ac06f5a 100644 --- a/source/blender/gpu/GPU_buffers.h +++ b/source/blender/gpu/GPU_buffers.h @@ -159,18 +159,18 @@ int GPU_buffer_legacy(struct DerivedMesh *dm ); typedef struct GPU_Buffers GPU_Buffers; GPU_Buffers *GPU_build_mesh_buffers(int (*face_vert_indices)[4], - struct MFace *mface, struct MVert *mvert, - int *face_indices, int totface); + struct MFace *mface, struct MVert *mvert, + int *face_indices, int totface); void GPU_update_mesh_buffers(GPU_Buffers *buffers, struct MVert *mvert, - int *vert_indices, int totvert, const float *vmask); + int *vert_indices, int totvert, const float *vmask); GPU_Buffers *GPU_build_grid_buffers(int *grid_indices, int totgrid, - unsigned int **grid_hidden, int gridsize); + unsigned int **grid_hidden, int gridsize); void GPU_update_grid_buffers(GPU_Buffers *buffers, struct CCGElem **grids, - const struct DMFlagMat *grid_flag_mats, - int *grid_indices, int totgrid, const struct CCGKey *key); + const struct DMFlagMat *grid_flag_mats, + int *grid_indices, int totgrid, const struct CCGKey *key); void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial); diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index 7a71f33d3d0..467adbe10b8 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -122,7 +122,7 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap); void GPU_paint_update_image(struct Image *ima, int x, int y, int w, int h, int mipmap); void GPU_update_images_framechange(void); int GPU_update_image_time(struct Image *ima, double time); -int GPU_verify_image(struct Image *ima, struct ImageUser *iuser, int tftile, int compare, int mipmap); +int GPU_verify_image(struct Image *ima, struct ImageUser *iuser, int tftile, int compare, int mipmap, int ncd); void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float *frect, int rectw, int recth, int mipmap, int use_hight_bit_depth, struct Image *ima); void GPU_create_gl_tex_compressed(unsigned int *bind, unsigned int *pix, int x, int y, int mipmap, struct Image *ima, struct ImBuf *ibuf); int GPU_upload_dxt_texture(struct ImBuf *ibuf); diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index b04da04258e..198d002ff0d 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -111,7 +111,7 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, float *fpixels); GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]); GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]); GPUTexture *GPU_texture_from_blender(struct Image *ima, - struct ImageUser *iuser, double time, int mipmap); + struct ImageUser *iuser, int ncd, double time, int mipmap); void GPU_texture_free(GPUTexture *tex); void GPU_texture_ref(GPUTexture *tex); diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index a725ff4385d..856b1f83001 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -107,7 +107,7 @@ typedef struct GPUNodeStack { GPUNodeLink *GPU_attribute(int type, const char *name); GPUNodeLink *GPU_uniform(float *num); GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data); -GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser); +GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, int ncd); GPUNodeLink *GPU_texture(int size, float *pixels); GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex, int dynamictype, void *data); GPUNodeLink *GPU_socket(GPUNodeStack *sock); diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index a88a075383d..25990e8fc6e 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -761,7 +761,7 @@ void GPU_pass_bind(GPUPass *pass, double time, int mipmap) /* now bind the textures */ for (input=inputs->first; input; input=input->next) { if (input->ima) - input->tex = GPU_texture_from_blender(input->ima, input->iuser, time, mipmap); + input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->imagencd, time, mipmap); if (input->tex && input->bindtex) { GPU_texture_bind(input->tex, input->texid); @@ -917,6 +917,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type) input->ima = link->ptr1; input->iuser = link->ptr2; + input->imagencd = link->imagencd; input->textarget = GL_TEXTURE_2D; input->textype = GPU_TEX2D; MEM_freeN(link); @@ -1109,13 +1110,14 @@ GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data) return link; } -GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser) +GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, int ncd) { GPUNodeLink *link = GPU_node_link_create(0); link->image= 1; link->ptr1= ima; link->ptr2= iuser; + link->imagencd= ncd; return link; } diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h index db334b8bf19..3010937a2f3 100644 --- a/source/blender/gpu/intern/gpu_codegen.h +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -91,6 +91,7 @@ struct GPUNodeLink { const char *attribname; int image; + int imagencd; int texture; int texturesize; @@ -137,6 +138,7 @@ typedef struct GPUInput { struct Image *ima; /* image */ struct ImageUser *iuser;/* image user */ + int imagencd; /* image does not contain color data */ float *dynamicvec; /* vector data in case it is dynamic */ int dynamictype; /* origin of the dynamic uniform (GPUDynamicType) */ void *dynamicdata; /* data source of the dynamic uniform */ diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index d03913af417..4314a784511 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -422,7 +422,7 @@ static void gpu_verify_reflection(Image *ima) } } -int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int mipmap) +int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int mipmap, int ncd) { ImBuf *ibuf = NULL; unsigned int *bind = NULL; @@ -492,7 +492,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int } /* TODO unneeded when float images are correctly treated as linear always */ - if (ibuf->profile == IB_PROFILE_LINEAR_RGB) + if (!ncd && ibuf->profile == IB_PROFILE_LINEAR_RGB) do_color_management = TRUE; if (ibuf->rect==NULL) @@ -807,7 +807,7 @@ int GPU_set_tpage(MTFace *tface, int mipmap, int alphablend) gpu_verify_alpha_blend(alphablend); gpu_verify_reflection(ima); - if (GPU_verify_image(ima, NULL, tface->tile, 1, mipmap)) { + if (GPU_verify_image(ima, NULL, tface->tile, 1, mipmap, FALSE)) { GTS.curtile= GTS.tile; GTS.curima= GTS.ima; GTS.curtilemode= GTS.tilemode; diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 4974d57d64c..c5f427fbcab 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -522,7 +522,7 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, float *fpixels) return tex; } -GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, double time, int mipmap) +GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int ncd, double time, int mipmap) { GPUTexture *tex; GLint w, h, border, lastbindcode, bindcode; @@ -530,7 +530,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, double time, glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode); GPU_update_image_time(ima, time); - bindcode = GPU_verify_image(ima, iuser, 0, 0, mipmap); + bindcode = GPU_verify_image(ima, iuser, 0, 0, mipmap, ncd); if (ima->gputexture) { ima->gputexture->bindcode = bindcode; diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index efb24375729..c831b92936f 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -645,7 +645,7 @@ static void shade_light_textures(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink ** GPU_link(mat, "shade_light_texture", GPU_builtin(GPU_VIEW_POSITION), - GPU_image(mtex->tex->ima, &mtex->tex->iuser), + GPU_image(mtex->tex->ima, &mtex->tex->iuser, FALSE), GPU_dynamic_uniform((float*)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob), &tex_rgb); texture_rgb_blend(mat, tex_rgb, *rgb, GPU_uniform(&one), GPU_uniform(&mtex->colfac), mtex->blendtype, rgb); @@ -1028,7 +1028,7 @@ static void do_material_tex(GPUShadeInput *shi) talpha = 0; if (tex && tex->type == TEX_IMAGE && tex->ima) { - GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser), &tin, &trgb); + GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser, FALSE), &tin, &trgb); rgbnor= TEX_RGB; if (tex->imaflag & TEX_USEALPHA) @@ -1104,7 +1104,7 @@ static void do_material_tex(GPUShadeInput *shi) if (tex->imaflag & TEX_NORMALMAP) { /* normalmap image */ - GPU_link(mat, "mtex_normal", texco, GPU_image(tex->ima, &tex->iuser), &tnor); + GPU_link(mat, "mtex_normal", texco, GPU_image(tex->ima, &tex->iuser, TRUE), &tnor); if (mtex->norfac < 0.0f) GPU_link(mat, "mtex_negate_texnormal", tnor, &tnor); @@ -1234,26 +1234,26 @@ static void do_material_tex(GPUShadeInput *shi) if (found_deriv_map) { GPU_link(mat, "mtex_bump_deriv", - texco, GPU_image(tex->ima, &tex->iuser), GPU_uniform(&ima_x), GPU_uniform(&ima_y), tnorfac, + texco, GPU_image(tex->ima, &tex->iuser, TRUE), GPU_uniform(&ima_x), GPU_uniform(&ima_y), tnorfac, &dBs, &dBt ); } else if ( mtex->texflag & MTEX_3TAP_BUMP) GPU_link(mat, "mtex_bump_tap3", - texco, GPU_image(tex->ima, &tex->iuser), tnorfac, + texco, GPU_image(tex->ima, &tex->iuser, TRUE), tnorfac, &dBs, &dBt ); else if ( mtex->texflag & MTEX_5TAP_BUMP) GPU_link(mat, "mtex_bump_tap5", - texco, GPU_image(tex->ima, &tex->iuser), tnorfac, + texco, GPU_image(tex->ima, &tex->iuser, TRUE), tnorfac, &dBs, &dBt ); else if ( mtex->texflag & MTEX_BICUBIC_BUMP ) { if (GPU_bicubic_bump_support()) { GPU_link(mat, "mtex_bump_bicubic", - texco, GPU_image(tex->ima, &tex->iuser), tnorfac, + texco, GPU_image(tex->ima, &tex->iuser, TRUE), tnorfac, &dBs, &dBt); } else { GPU_link(mat, "mtex_bump_tap5", - texco, GPU_image(tex->ima, &tex->iuser), tnorfac, + texco, GPU_image(tex->ima, &tex->iuser, TRUE), tnorfac, &dBs, &dBt); } } @@ -1263,7 +1263,7 @@ static void do_material_tex(GPUShadeInput *shi) float imag_tspace_dimension_y = aspect*imag_tspace_dimension_x; GPU_link(mat, "mtex_bump_apply_texspace", fDet, dBs, dBt, vR1, vR2, - GPU_image(tex->ima, &tex->iuser), texco, + GPU_image(tex->ima, &tex->iuser, TRUE), texco, GPU_uniform(&imag_tspace_dimension_x), GPU_uniform(&imag_tspace_dimension_y), vNacc, &vNacc, &shi->vn ); } @@ -1396,10 +1396,10 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) GPU_material_enable_alpha(mat); if ((mat->scene->gm.flag & GAME_GLSL_NO_LIGHTS) || (ma->mode & MA_SHLESS)) { - shr->combined = shi->rgb; - shr->alpha = shi->alpha; GPU_link(mat, "set_rgb", shi->rgb, &shr->diff); GPU_link(mat, "set_rgb_zero", &shr->spec); + GPU_link(mat, "set_value", shi->alpha, &shr->alpha); + shr->combined = shr->diff; } else { if (GPU_link_changed(shi->emit) || ma->emit != 0.0f) { @@ -1418,7 +1418,8 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) material_lights(shi, shr); shr->combined = shr->diff; - shr->alpha = shi->alpha; + + GPU_link(mat, "set_value", shi->alpha, &shr->alpha); if (world) { /* exposure correction */ diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp index 7a53fe247fe..c5722995d32 100644 --- a/source/blender/ikplugin/intern/itasc_plugin.cpp +++ b/source/blender/ikplugin/intern/itasc_plugin.cpp @@ -57,7 +57,6 @@ extern "C" { #include "BKE_global.h" #include "BKE_armature.h" #include "BKE_action.h" -#include "BKE_utildefines.h" #include "BKE_constraint.h" #include "DNA_object_types.h" #include "DNA_action_types.h" diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 439f52ed323..54a6a7f597e 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -492,8 +492,8 @@ void IMB_rectfill_alpha(struct ImBuf *ibuf, const float value); /* this should not be here, really, we needed it for operating on render data, IMB_rectfill_area calls it */ void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, - const float col[4], const int do_color_management, - int x1, int y1, int x2, int y2); + const float col[4], const int do_color_management, + int x1, int y1, int x2, int y2); /* defined in metadata.c */ int IMB_metadata_change_field(struct ImBuf *img, const char *key, const char *field); diff --git a/source/blender/imbuf/intern/IMB_indexer.h b/source/blender/imbuf/intern/IMB_indexer.h index 16d10a5c41c..18816924a9b 100644 --- a/source/blender/imbuf/intern/IMB_indexer.h +++ b/source/blender/imbuf/intern/IMB_indexer.h @@ -31,7 +31,6 @@ #include #include -#include "BKE_utildefines.h" #include "IMB_anim.h" /* * separate animation index files to solve the following problems: diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c index 60dd4f65594..8fa468949e7 100644 --- a/source/blender/imbuf/intern/bmp.c +++ b/source/blender/imbuf/intern/bmp.c @@ -69,7 +69,7 @@ typedef struct BMPHEADER { static int checkbmp(unsigned char *mem) { -#define CHECK_HEADER_FIELD(mem, field) ((mem[0] == field[0]) && (mem[1] == field[0])) +#define CHECK_HEADER_FIELD(mem, field) ((mem[0] == field[0]) && (mem[1] == field[1])) int ret_val = 0; BMPINFOHEADER bmi; diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index 4108f0d89d7..458f0198aed 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -24,18 +24,21 @@ #include -#include "IMB_indexer.h" -#include "IMB_anim.h" -#include "AVI_avi.h" -#include "imbuf.h" #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" +#include "BLI_endian_switch.h" +#include "BLI_path_util.h" #include "BLI_string.h" #include "BLI_path_util.h" #include "BLI_fileops.h" #include "BLI_math_base.h" +#include "IMB_indexer.h" +#include "IMB_anim.h" +#include "AVI_avi.h" +#include "imbuf.h" + #include "MEM_guardedalloc.h" #include "DNA_userdef_types.h" #include "BKE_global.h" @@ -208,10 +211,10 @@ struct anim_index *IMB_indexer_open(const char *name) if (((ENDIAN_ORDER == B_ENDIAN) != (header[8] == 'V'))) { for (i = 0; i < idx->num_entries; i++) { - SWITCH_INT(idx->entries[i].frameno); - SWITCH_INT64(idx->entries[i].seek_pos); - SWITCH_INT64(idx->entries[i].seek_pos_dts); - SWITCH_INT64(idx->entries[i].pts); + BLI_endian_switch_int32(&idx->entries[i].frameno); + BLI_endian_switch_int64((int64_t *)&idx->entries[i].seek_pos); + BLI_endian_switch_int64((int64_t *)&idx->entries[i].seek_pos_dts); + BLI_endian_switch_int64((int64_t *)&idx->entries[i].pts); } } diff --git a/source/blender/imbuf/intern/indexer_dv.c b/source/blender/imbuf/intern/indexer_dv.c index 4c6b750aa41..6b960a18277 100644 --- a/source/blender/imbuf/intern/indexer_dv.c +++ b/source/blender/imbuf/intern/indexer_dv.c @@ -22,9 +22,12 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include "IMB_indexer.h" #include "MEM_guardedalloc.h" + #include "BLI_utildefines.h" +#include "BLI_path_util.h" + +#include "IMB_indexer.h" #include typedef struct indexer_dv_bitstream { diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index 6a234b8e29a..2a2aedb49ff 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -39,8 +39,6 @@ #include "BLI_fileops.h" #include "BLI_md5.h" -#include "BKE_utildefines.h" - #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" #include "IMB_thumbs.h" diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c index afef2365de4..cfc49d8cef5 100644 --- a/source/blender/imbuf/intern/thumbs_blend.c +++ b/source/blender/imbuf/intern/thumbs_blend.c @@ -29,18 +29,20 @@ #include "zlib.h" +#include "MEM_guardedalloc.h" + #include "BLI_utildefines.h" +#include "BLI_endian_switch.h" #include "BLI_fileops.h" -#include "BKE_utildefines.h" +#include "BLO_blend_defs.h" + #include "BKE_global.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" #include "IMB_thumbs.h" -#include "MEM_guardedalloc.h" - /* extracts the thumbnail from between the 'REND' and the 'GLOB' * chunks of the header, don't use typical blend loader because its too slow */ @@ -78,7 +80,7 @@ static ImBuf *loadblend_thumb(gzFile gzfile) while (gzread(gzfile, bhead, sizeof_bhead) == sizeof_bhead) { if (endian_switch) - SWITCH_INT(bhead[1]); /* length */ + BLI_endian_switch_int32(&bhead[1]); /* length */ if (bhead[0] == REND) { gzseek(gzfile, bhead[1], SEEK_CUR); /* skip to the next */ @@ -97,8 +99,8 @@ static ImBuf *loadblend_thumb(gzFile gzfile) return NULL; if (endian_switch) { - SWITCH_INT(size[0]); - SWITCH_INT(size[1]); + BLI_endian_switch_int32(&size[0]); + BLI_endian_switch_int32(&size[1]); } /* length */ bhead[1] -= sizeof(int) * 2; diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index a765ac5c3b4..6d1e3c16631 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -225,16 +225,6 @@ static int isqtime(const char *name) static char ffmpeg_last_error[1024]; -void silence_log_ffmpeg(int quiet) -{ - if (quiet) { - av_log_set_level(AV_LOG_QUIET); - } - else { - av_log_set_level(AV_LOG_DEBUG); - } -} - void ffmpeg_log_callback(void *ptr, int level, const char *format, va_list arg) { if (ELEM(level, AV_LOG_FATAL, AV_LOG_ERROR)) { @@ -244,8 +234,10 @@ void ffmpeg_log_callback(void *ptr, int level, const char *format, va_list arg) ffmpeg_last_error[n - 1] = '\0'; } - /* call default logger to print all message to console */ - av_log_default_callback(ptr, level, format, arg); + if (G.debug & G_DEBUG_FFMPEG) { + /* call default logger to print all message to console */ + av_log_default_callback(ptr, level, format, arg); + } } void IMB_ffmpeg_init(void) @@ -253,13 +245,6 @@ void IMB_ffmpeg_init(void) av_register_all(); avdevice_register_all(); - if ((G.debug & G_DEBUG_FFMPEG) == 0) { - silence_log_ffmpeg(1); - } - else { - silence_log_ffmpeg(0); - } - ffmpeg_last_error[0] = '\0'; /* set own callback which could store last error to report to UI */ diff --git a/source/blender/makesdna/DNA_ipo_types.h b/source/blender/makesdna/DNA_ipo_types.h index e3ab6b4a7db..6bf8dbbe73a 100644 --- a/source/blender/makesdna/DNA_ipo_types.h +++ b/source/blender/makesdna/DNA_ipo_types.h @@ -65,8 +65,8 @@ typedef struct IpoDriver { typedef struct IpoCurve { struct IpoCurve *next, *prev; - struct BPoint *bp; /* array of BPoints (sizeof(BPoint)*totvert) - i.e. baked/imported data */ - struct BezTriple *bezt; /* array of BezTriples (sizeof(BezTriple)*totvert) - i.e. user-editable keyframes */ + struct BPoint *bp; /* array of BPoints (sizeof(BPoint) * totvert) - i.e. baked/imported data */ + struct BezTriple *bezt; /* array of BezTriples (sizeof(BezTriple) * totvert) - i.e. user-editable keyframes */ rctf maxrct, totrct; /* bounding boxes */ diff --git a/source/blender/makesdna/DNA_sdna_types.h b/source/blender/makesdna/DNA_sdna_types.h index ec02db192fd..8b2e7645823 100644 --- a/source/blender/makesdna/DNA_sdna_types.h +++ b/source/blender/makesdna/DNA_sdna_types.h @@ -81,12 +81,7 @@ typedef struct BHead4 { # typedef struct BHead8 { int code, len; -#if defined(WIN32) && !defined(FREE_WINDOWS) - /* This is a compiler type! */ - __int64 old; -#else - long long old; -#endif + int64_t old; int SDNAnr, nr; } BHead8; diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 62a09e65191..d2ff8d13124 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -51,7 +51,7 @@ # define __func__ __FUNCTION__ #endif -/* copied from BKE_utildefines.h ugh */ +/* copied from BLI_utildefines.h ugh */ #ifdef __GNUC__ # define UNUSED(x) UNUSED_ ## x __attribute__((__unused__)) #else @@ -2881,8 +2881,8 @@ static const char *cpp_classes = "" " T data[Tsize];\n" "\n" " Array() {}\n" -" Array(const Array& other) { memcpy(data, other.data, sizeof(T)*Tsize); }\n" -" const Array& operator=(const Array& other) { memcpy(data, other.data, sizeof(T)*Tsize); " +" Array(const Array& other) { memcpy(data, other.data, sizeof(T) * Tsize); }\n" +" const Array& operator=(const Array& other) { memcpy(data, other.data, sizeof(T) * Tsize); " "return *this; }\n" "\n" " operator T*() { return data; }\n" diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 738e7ad2219..be70405d165 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -146,6 +146,18 @@ static void rna_Armature_redraw_data(Main *UNUSED(bmain), Scene *UNUSED(scene), WM_main_add_notifier(NC_GEOM | ND_DATA, id); } +/* called whenever a bone is renamed */ +static void rna_Bone_update_renamed(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + ID *id = ptr->id.data; + + /* redraw view */ + WM_main_add_notifier(NC_GEOM | ND_DATA, id); + + /* update animation channels */ + WM_main_add_notifier(NC_ANIMATION | ND_ANIMCHAN, id); +} + static void rna_Bone_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { ID *id = ptr->id.data; @@ -470,7 +482,7 @@ static void rna_def_bone_common(StructRNA *srna, int editbone) RNA_def_struct_name_property(srna, prop); if (editbone) RNA_def_property_string_funcs(prop, NULL, NULL, "rna_EditBone_name_set"); else RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Bone_name_set"); - RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); + RNA_def_property_update(prop, 0, "rna_Bone_update_renamed"); /* flags */ prop = RNA_def_property(srna, "layers", PROP_BOOLEAN, PROP_LAYER_MEMBER); diff --git a/source/blender/makesrna/intern/rna_camera_api.c b/source/blender/makesrna/intern/rna_camera_api.c index 2d19047ef89..75941fa224f 100644 --- a/source/blender/makesrna/intern/rna_camera_api.c +++ b/source/blender/makesrna/intern/rna_camera_api.c @@ -29,9 +29,7 @@ #include #include - #include "RNA_define.h" -#include "BKE_utildefines.h" #ifdef RNA_RUNTIME diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c index e84a290acb8..daa661175a1 100644 --- a/source/blender/makesrna/intern/rna_fluidsim.c +++ b/source/blender/makesrna/intern/rna_fluidsim.c @@ -24,15 +24,16 @@ * \ingroup RNA */ - #include +#include "DNA_object_fluidsim.h" + +#include "BLI_path_util.h" + #include "RNA_define.h" #include "rna_internal.h" -#include "DNA_object_fluidsim.h" - #include "WM_api.h" #include "WM_types.h" diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index e246c6975b5..eb12a02aa99 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -203,7 +203,7 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) RNA_def_property_editable_func(prop, "rna_GPencilLayer_active_frame_editable"); /* Drawing Color */ - prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR); + prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Color", "Color for all strokes in this layer"); diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c index 96c5ff991f6..74b3c431183 100644 --- a/source/blender/makesrna/intern/rna_main.c +++ b/source/blender/makesrna/intern/rna_main.c @@ -24,16 +24,15 @@ * \ingroup RNA */ - #include #include +#include "BLI_path_util.h" + #include "RNA_define.h" #include "rna_internal.h" -#include "BKE_utildefines.h" - #ifdef RNA_RUNTIME #include "BKE_main.h" diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 59eae3259b4..8a2374060cf 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -35,12 +35,13 @@ #include "DNA_ID.h" +#include "BLI_path_util.h" + #include "RNA_define.h" #include "RNA_access.h" #include "RNA_enum_types.h" -#include "rna_internal.h" -#include "BKE_utildefines.h" +#include "rna_internal.h" #ifdef RNA_RUNTIME diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index c21d029a6b7..a755e130bb7 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -24,11 +24,12 @@ * \ingroup RNA */ - #include #include "DNA_scene_types.h" +#include "BLI_path_util.h" + #include "RNA_define.h" #include "RNA_enum_types.h" @@ -37,7 +38,6 @@ #include "RE_engine.h" #include "RE_pipeline.h" -#include "BKE_utildefines.h" #ifdef RNA_RUNTIME diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 61be48f3f02..69b61b47d8a 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -32,13 +32,13 @@ #include #include +#include "BLI_path_util.h" + #include "RNA_define.h" #include "DNA_anim_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "BKE_utildefines.h" - #ifdef RNA_RUNTIME diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index ce5f39d0b42..385e82cab35 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -532,12 +532,7 @@ static PointerRNA rna_SpaceImageEditor_uvedit_get(PointerRNA *ptr) static void rna_SpaceImageEditor_mode_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - SpaceImage *sima = (SpaceImage *)(ptr->data); - if (sima->mode == SI_MODE_PAINT) { - BKE_paint_init(&scene->toolsettings->imapaint.paint, PAINT_CURSOR_TEXTURE_PAINT); - - ED_space_image_paint_update(bmain->wm.first, scene->toolsettings); - } + ED_space_image_paint_update(bmain->wm.first, scene->toolsettings); } static int rna_SpaceImageEditor_show_render_get(PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_texture_api.c b/source/blender/makesrna/intern/rna_texture_api.c index ff8940129a1..e62b3ecd804 100644 --- a/source/blender/makesrna/intern/rna_texture_api.c +++ b/source/blender/makesrna/intern/rna_texture_api.c @@ -24,14 +24,13 @@ * \ingroup RNA */ - #include #include #include +#include "BLI_path_util.h" #include "RNA_define.h" -#include "BKE_utildefines.h" #ifdef RNA_RUNTIME diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index d910ed7900c..ae4d5dc493e 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -83,9 +83,10 @@ void rna_event_timer_remove(struct wmWindowManager *wm, wmTimer *timer) } static wmKeyMapItem *rna_KeyMap_item_new(wmKeyMap *km, ReportList *reports, const char *idname, int type, int value, - int any, int shift, int ctrl, int alt, int oskey, int keymodifier) + int any, int shift, int ctrl, int alt, int oskey, int keymodifier, int head) { /* wmWindowManager *wm = CTX_wm_manager(C); */ + wmKeyMapItem *kmi = NULL; char idname_bl[OP_MAX_TYPENAME]; int modifier = 0; @@ -103,8 +104,19 @@ static wmKeyMapItem *rna_KeyMap_item_new(wmKeyMap *km, ReportList *reports, cons if (oskey) modifier |= KM_OSKEY; if (any) modifier = KM_ANY; - - return WM_keymap_add_item(km, idname_bl, type, value, modifier, keymodifier); + + /* create keymap item */ + kmi = WM_keymap_add_item(km, idname_bl, type, value, modifier, keymodifier); + + /* [#32437] allow scripts to define hotkeys that get added to start of keymap + * so that they stand a chance against catch-all defines later on + */ + if (head) { + BLI_remlink(&km->items, kmi); + BLI_addhead(&km->items, kmi); + } + + return kmi; } static wmKeyMapItem *rna_KeyMap_item_new_modal(wmKeyMap *km, ReportList *reports, const char *propvalue_str, @@ -425,6 +437,9 @@ void RNA_api_keymapitems(StructRNA *srna) RNA_def_boolean(func, "alt", 0, "Alt", ""); RNA_def_boolean(func, "oskey", 0, "OS Key", ""); RNA_def_enum(func, "key_modifier", event_type_items, 0, "Key Modifier", ""); + RNA_def_boolean(func, "head", 0, "At Head", + "Force item to be added at start (not end) of key map so that " + "it doesn't get blocked by an existing key map item"); parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", "Added key map item"); RNA_def_function_return(func, parm); diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.c b/source/blender/modifiers/intern/MOD_fluidsim_util.c index 1c98880c3db..9acac6d00cd 100644 --- a/source/blender/modifiers/intern/MOD_fluidsim_util.c +++ b/source/blender/modifiers/intern/MOD_fluidsim_util.c @@ -51,7 +51,6 @@ #include "BKE_fluidsim.h" /* ensure definitions here match */ #include "BKE_cdderivedmesh.h" #include "BKE_mesh.h" -#include "BKE_utildefines.h" #include "BKE_global.h" /* G.main->name only */ #include "MOD_fluidsim_util.h" diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c index 6f3d47b3426..febc4190fdf 100644 --- a/source/blender/modifiers/intern/MOD_mirror.c +++ b/source/blender/modifiers/intern/MOD_mirror.c @@ -43,7 +43,6 @@ #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_deform.h" -#include "BKE_utildefines.h" #include "BKE_tessmesh.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index 21836453eed..3bf8b9ffacc 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -37,7 +37,6 @@ #include "BKE_global.h" #include "BKE_modifier.h" #include "BKE_ocean.h" -#include "BKE_utildefines.h" #include "BLI_blenlib.h" #include "BLI_math.h" diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index 37444b6da92..55750ca1bab 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -48,7 +48,6 @@ #include "BKE_main.h" #include "BKE_node.h" #include "BKE_tracking.h" -#include "BKE_utildefines.h" #include "node_common.h" #include "node_exec.h" diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c index 399cb1d1557..2d9b9348668 100644 --- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c +++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c @@ -33,8 +33,6 @@ #include #include "BLI_path_util.h" -#include "BKE_utildefines.h" - #include "node_composite_util.h" #include "IMB_imbuf.h" diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c index ffa636fa952..fdbe82efeda 100644 --- a/source/blender/nodes/intern/node_common.c +++ b/source/blender/nodes/intern/node_common.c @@ -45,7 +45,6 @@ #include "BKE_main.h" #include "BLI_math.h" #include "BKE_node.h" -#include "BKE_utildefines.h" #include "RNA_access.h" #include "RNA_types.h" diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index fa623eaad3d..ad907c317f8 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -49,7 +49,6 @@ #include "BKE_main.h" #include "BKE_node.h" #include "BKE_scene.h" -#include "BKE_utildefines.h" #include "GPU_material.h" @@ -66,15 +65,15 @@ static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func) Lamp *la; World *wo; - for (ma= main->mat.first; ma; ma= ma->id.next) + for (ma = main->mat.first; ma; ma = ma->id.next) if (ma->nodetree) func(calldata, &ma->id, ma->nodetree); - for (la= main->lamp.first; la; la= la->id.next) + for (la = main->lamp.first; la; la = la->id.next) if (la->nodetree) func(calldata, &la->id, la->nodetree); - for (wo= main->world.first; wo; wo= wo->id.next) + for (wo = main->world.first; wo; wo = wo->id.next) if (wo->nodetree) func(calldata, &wo->id, wo->nodetree); } @@ -101,7 +100,7 @@ static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree)) bNode *node, *node_next; /* replace muted nodes and reroute nodes by internal links */ - for (node= localtree->nodes.first; node; node= node_next) { + for (node = localtree->nodes.first; node; node = node_next) { node_next = node->next; if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) { @@ -116,15 +115,15 @@ static void local_sync(bNodeTree *localtree, bNodeTree *ntree) bNode *lnode; /* copy over contents of previews */ - for (lnode= localtree->nodes.first; lnode; lnode= lnode->next) { + for (lnode = localtree->nodes.first; lnode; lnode = lnode->next) { if (ntreeNodeExists(ntree, lnode->new_node)) { - bNode *node= lnode->new_node; + bNode *node = lnode->new_node; if (node->preview && node->preview->rect) { if (lnode->preview && lnode->preview->rect) { - int xsize= node->preview->xsize; - int ysize= node->preview->ysize; - memcpy(node->preview->rect, lnode->preview->rect, 4*xsize + xsize*ysize*sizeof(char)*4); + int xsize = node->preview->xsize; + int ysize = node->preview->ysize; + memcpy(node->preview->rect, lnode->preview->rect, 4 * xsize + xsize * ysize * sizeof(char) * 4); } } } @@ -176,7 +175,7 @@ void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *); void set_node_shader_lamp_loop(void (*lamp_loop_func)(ShadeInput *, ShadeResult *)) { - node_shader_lamp_loop= lamp_loop_func; + node_shader_lamp_loop = lamp_loop_func; } @@ -203,10 +202,10 @@ bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree, int use_tree_data) exec = ntree_exec_begin(ntree); /* allocate the thread stack listbase array */ - exec->threadstack= MEM_callocN(BLENDER_MAX_THREADS*sizeof(ListBase), "thread stack array"); + exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array"); - for (node= exec->nodetree->nodes.first; node; node= node->next) - node->need_exec= 1; + for (node = exec->nodetree->nodes.first; node; node = node->next) + node->need_exec = 1; if (use_tree_data) { /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes, @@ -224,19 +223,19 @@ bNodeTreeExec *ntreeShaderBeginExecTree(bNodeTree *ntree, int use_tree_data) void ntreeShaderEndExecTree(bNodeTreeExec *exec, int use_tree_data) { if (exec) { - bNodeTree *ntree= exec->nodetree; + bNodeTree *ntree = exec->nodetree; bNodeThreadStack *nts; int a; if (exec->threadstack) { - for (a=0; athreadstack[a].first; nts; nts=nts->next) + for (a = 0; a < BLENDER_MAX_THREADS; a++) { + for (nts = exec->threadstack[a].first; nts; nts = nts->next) if (nts->stack) MEM_freeN(nts->stack); BLI_freelistN(&exec->threadstack[a]); } MEM_freeN(exec->threadstack); - exec->threadstack= NULL; + exec->threadstack = NULL; } ntree_exec_end(exec); @@ -260,8 +259,8 @@ void ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr) bNodeTreeExec *exec = ntree->execdata; /* convert caller data to struct */ - scd.shi= shi; - scd.shr= shr; + scd.shi = shi; + scd.shr = shr; /* each material node has own local shaderesult, with optional copying */ memset(shr, 0, sizeof(ShadeResult)); @@ -276,14 +275,14 @@ void ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr) exec = ntree->execdata; } - nts= ntreeGetThreadStack(exec, shi->thread); + nts = ntreeGetThreadStack(exec, shi->thread); ntreeExecThreadNodes(exec, nts, &scd, shi->thread); ntreeReleaseThreadStack(nts); // \note: set material back to preserved material shi->mat = mat; /* better not allow negative for now */ - if (shr->combined[0]<0.0f) shr->combined[0]= 0.0f; - if (shr->combined[1]<0.0f) shr->combined[1]= 0.0f; - if (shr->combined[2]<0.0f) shr->combined[2]= 0.0f; + if (shr->combined[0] < 0.0f) shr->combined[0] = 0.0f; + if (shr->combined[1] < 0.0f) shr->combined[1] = 0.0f; + if (shr->combined[2] < 0.0f) shr->combined[2] = 0.0f; } diff --git a/source/blender/nodes/shader/nodes/node_shader_particle_info.c b/source/blender/nodes/shader/nodes/node_shader_particle_info.c index 5be8925b556..ddfcb9476f4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_particle_info.c +++ b/source/blender/nodes/shader/nodes/node_shader_particle_info.c @@ -31,6 +31,13 @@ static bNodeSocketTemplate outputs[] = { { SOCK_FLOAT, 0, "Index" }, { SOCK_FLOAT, 0, "Age" }, { SOCK_FLOAT, 0, "Lifetime" }, + { SOCK_VECTOR, 0, "Location" }, + #if 0 /* quaternion sockets not yet supported */ + { SOCK_QUATERNION, 0, "Rotation" }, + #endif + { SOCK_FLOAT, 0, "Size" }, + { SOCK_VECTOR, 0, "Velocity" }, + { SOCK_VECTOR, 0, "Angular Velocity" }, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c index 572f06e007b..e857d0571cd 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -58,6 +58,8 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, GPUNod { Image *ima= (Image*)node->id; ImageUser *iuser= NULL; + NodeTexImage *tex = node->storage; + int ncd = tex->color_space == SHD_COLORSPACE_NONE; if (!ima) return GPU_stack_link(mat, "node_tex_environment_empty", in, out); @@ -67,7 +69,7 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, GPUNod node_shader_gpu_tex_mapping(mat, node, in, out); - return GPU_stack_link(mat, "node_tex_environment", in, out, GPU_image(ima, iuser)); + return GPU_stack_link(mat, "node_tex_environment", in, out, GPU_image(ima, iuser, ncd)); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index 176c50bcabb..c492fe9efc7 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -58,6 +58,8 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, GPUNodeStack { Image *ima= (Image*)node->id; ImageUser *iuser= NULL; + NodeTexImage *tex = node->storage; + int ncd = tex->color_space == SHD_COLORSPACE_NONE; if (!ima) return GPU_stack_link(mat, "node_tex_image_empty", in, out); @@ -67,7 +69,7 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, GPUNodeStack node_shader_gpu_tex_mapping(mat, node, in, out); - return GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser)); + return GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, ncd)); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_texture.c b/source/blender/nodes/shader/nodes/node_shader_texture.c index 3f90d4fbcd5..73c3b846fe3 100644 --- a/source/blender/nodes/shader/nodes/node_shader_texture.c +++ b/source/blender/nodes/shader/nodes/node_shader_texture.c @@ -122,7 +122,7 @@ static int gpu_shader_texture(GPUMaterial *mat, bNode *node, GPUNodeStack *in, G Tex *tex = (Tex*)node->id; if (tex && tex->type == TEX_IMAGE && tex->ima) { - GPUNodeLink *texlink = GPU_image(tex->ima, NULL); + GPUNodeLink *texlink = GPU_image(tex->ima, NULL, FALSE); return GPU_stack_link(mat, "texture_image", in, out, texlink); } else diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c index 063cc31e6f6..9656d93f1b0 100644 --- a/source/blender/nodes/texture/node_texture_tree.c +++ b/source/blender/nodes/texture/node_texture_tree.c @@ -58,7 +58,7 @@ static void foreach_nodetree(Main *main, void *calldata, bNodeTreeCallback func) { Tex *tx; - for (tx= main->tex.first; tx; tx= tx->id.next) { + for (tx = main->tex.first; tx; tx = tx->id.next) { if (tx->nodetree) { func(calldata, &tx->id, tx->nodetree); } @@ -83,7 +83,7 @@ static void localize(bNodeTree *localtree, bNodeTree *UNUSED(ntree)) bNode *node, *node_next; /* replace muted nodes and reroute nodes by internal links */ - for (node= localtree->nodes.first; node; node= node_next) { + for (node = localtree->nodes.first; node; node = node_next) { node_next = node->next; if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) { @@ -98,15 +98,15 @@ static void local_sync(bNodeTree *localtree, bNodeTree *ntree) bNode *lnode; /* copy over contents of previews */ - for (lnode= localtree->nodes.first; lnode; lnode= lnode->next) { + for (lnode = localtree->nodes.first; lnode; lnode = lnode->next) { if (ntreeNodeExists(ntree, lnode->new_node)) { - bNode *node= lnode->new_node; + bNode *node = lnode->new_node; if (node->preview && node->preview->rect) { if (lnode->preview && lnode->preview->rect) { - int xsize= node->preview->xsize; - int ysize= node->preview->ysize; - memcpy(node->preview->rect, lnode->preview->rect, 4*xsize + xsize*ysize*sizeof(char)*4); + int xsize = node->preview->xsize; + int ysize = node->preview->ysize; + memcpy(node->preview->rect, lnode->preview->rect, 4 * xsize + xsize * ysize * sizeof(char) * 4); } } } @@ -141,15 +141,15 @@ int ntreeTexTagAnimated(bNodeTree *ntree) { bNode *node; - if (ntree==NULL) return 0; + if (ntree == NULL) return 0; - for (node= ntree->nodes.first; node; node= node->next) { - if (node->type==TEX_NODE_CURVE_TIME) { + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == TEX_NODE_CURVE_TIME) { nodeUpdate(ntree, node); return 1; } - else if (node->type==NODE_GROUP) { - if ( ntreeTexTagAnimated((bNodeTree *)node->id) ) { + else if (node->type == NODE_GROUP) { + if (ntreeTexTagAnimated((bNodeTree *)node->id) ) { return 1; } } @@ -178,10 +178,10 @@ bNodeTreeExec *ntreeTexBeginExecTree(bNodeTree *ntree, int use_tree_data) exec = ntree_exec_begin(ntree); /* allocate the thread stack listbase array */ - exec->threadstack= MEM_callocN(BLENDER_MAX_THREADS*sizeof(ListBase), "thread stack array"); + exec->threadstack = MEM_callocN(BLENDER_MAX_THREADS * sizeof(ListBase), "thread stack array"); - for (node= exec->nodetree->nodes.first; node; node= node->next) - node->need_exec= 1; + for (node = exec->nodetree->nodes.first; node; node = node->next) + node->need_exec = 1; if (use_tree_data) { /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes, @@ -200,9 +200,9 @@ static void tex_free_delegates(bNodeTreeExec *exec) bNodeStack *ns; int th, a; - for (th=0; ththreadstack[th].first; nts; nts=nts->next) - for (ns= nts->stack, a=0; astacksize; a++, ns++) + for (th = 0; th < BLENDER_MAX_THREADS; th++) + for (nts = exec->threadstack[th].first; nts; nts = nts->next) + for (ns = nts->stack, a = 0; a < exec->stacksize; a++, ns++) if (ns->data && !ns->is_copy) MEM_freeN(ns->data); } @@ -213,21 +213,21 @@ static void tex_free_delegates(bNodeTreeExec *exec) void ntreeTexEndExecTree(bNodeTreeExec *exec, int use_tree_data) { if (exec) { - bNodeTree *ntree= exec->nodetree; + bNodeTree *ntree = exec->nodetree; bNodeThreadStack *nts; int a; if (exec->threadstack) { tex_free_delegates(exec); - for (a=0; athreadstack[a].first; nts; nts=nts->next) + for (a = 0; a < BLENDER_MAX_THREADS; a++) { + for (nts = exec->threadstack[a].first; nts; nts = nts->next) if (nts->stack) MEM_freeN(nts->stack); BLI_freelistN(&exec->threadstack[a]); } MEM_freeN(exec->threadstack); - exec->threadstack= NULL; + exec->threadstack = NULL; } ntree_exec_end(exec); @@ -254,10 +254,10 @@ int ntreeTexExecTree( MTex *mtex ) { TexCallData data; - float *nor= texres->nor; + float *nor = texres->nor; int retval = TEX_INT; bNodeThreadStack *nts = NULL; - bNodeTreeExec *exec= nodes->execdata; + bNodeTreeExec *exec = nodes->execdata; data.co = co; data.dxt = dxt; @@ -267,9 +267,9 @@ int ntreeTexExecTree( data.do_preview = preview; data.thread = thread; data.which_output = which_output; - data.cfra= cfra; - data.mtex= mtex; - data.shi= shi; + data.cfra = cfra; + data.mtex = mtex; + data.shi = shi; /* ensure execdata is only initialized once */ if (!exec) { @@ -278,10 +278,10 @@ int ntreeTexExecTree( ntreeTexBeginExecTree(nodes, 1); BLI_unlock_thread(LOCK_NODES); - exec= nodes->execdata; + exec = nodes->execdata; } - nts= ntreeGetThreadStack(exec, thread); + nts = ntreeGetThreadStack(exec, thread); ntreeExecThreadNodes(exec, nts, &data, thread); ntreeReleaseThreadStack(nts); @@ -289,7 +289,7 @@ int ntreeTexExecTree( retval |= TEX_RGB; /* confusing stuff; the texture output node sets this to NULL to indicate no normal socket was set * however, the texture code checks this for other reasons (namely, a normal is required for material) */ - texres->nor= nor; + texres->nor = nor; return retval; } diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 520773c1ddf..2e4d4e870b8 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -402,6 +402,15 @@ const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce) if (PyBytes_Check(py_str)) { return PyBytes_AS_STRING(py_str); } +#ifdef WIN32 + /* bug [#31856] oddly enough, Python3.2 --> 3.3 on Windows will throw an + * exception here this needs to be fixed in python: + * see: bugs.python.org/issue15859 */ + else if (!PyUnicode_Check(py_str)) { + PyErr_BadArgument(); + return NULL; + } +#endif else if ((*coerce = PyUnicode_EncodeFSDefault(py_str))) { return PyBytes_AS_STRING(*coerce); } diff --git a/source/blender/quicktime/apple/qtkit_export.m b/source/blender/quicktime/apple/qtkit_export.m index 47df4c7363f..bb87fe21c49 100644 --- a/source/blender/quicktime/apple/qtkit_export.m +++ b/source/blender/quicktime/apple/qtkit_export.m @@ -318,7 +318,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R if(qtexport == NULL) qtexport = MEM_callocN(sizeof(QuicktimeExport), "QuicktimeExport"); - [QTMovie enterQTKitOnThread]; + [QTMovie enterQTKitOnThread]; /* Check first if the QuickTime 7.2.1 initToWritableFile: method is available */ if ([[[[QTMovie alloc] init] autorelease] respondsToSelector:@selector(initToWritableFile:error:)] != YES) { @@ -328,7 +328,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R else { makeqtstring(rd, name); qtexport->filename = [[NSString alloc] initWithCString:name - encoding:[NSString defaultCStringEncoding]]; + encoding:[NSString defaultCStringEncoding]]; qtexport->movie = nil; qtexport->audioFile = NULL; @@ -354,7 +354,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R strcpy(extension,".aiff"); break; } - + tmpnam(name); strcat(name, extension); outputFileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,(UInt8*) name, strlen(name), false); @@ -362,7 +362,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R if (outputFileURL) { qtexport->audioFileName = [[NSString alloc] initWithCString:name - encoding:[NSString defaultCStringEncoding]]; + encoding:[NSString defaultCStringEncoding]]; qtexport->audioInputFormat.mSampleRate = U.audiorate; qtexport->audioInputFormat.mFormatID = kAudioFormatLinearPCM; @@ -471,7 +471,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R qtexport->audioOutputFormat.mBytesPerFrame = qtexport->audioOutputFormat.mBytesPerPacket; break; } - + err = AudioFileCreateWithURL(outputFileURL, audioFileType, &qtexport->audioOutputFormat, kAudioFileFlags_EraseFile, &qtexport->audioFile); CFRelease(outputFileURL); @@ -489,27 +489,27 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R else { UInt32 prop,propSize; /* Set up codec properties */ - if (rd->qtcodecsettings.audiocodecType == kAudioFormatMPEG4AAC) { /*Lossy compressed format*/ + if (rd->qtcodecsettings.audiocodecType == kAudioFormatMPEG4AAC) { /* Lossy compressed format */ prop = rd->qtcodecsettings.audioBitRate; AudioConverterSetProperty(qtexport->audioConverter, kAudioConverterEncodeBitRate, - sizeof(prop), &prop); + sizeof(prop), &prop); if (rd->qtcodecsettings.audioCodecFlags & QTAUDIO_FLAG_CODEC_ISCBR) prop = kAudioCodecBitRateControlMode_Constant; else prop = kAudioCodecBitRateControlMode_LongTermAverage; AudioConverterSetProperty(qtexport->audioConverter, kAudioCodecPropertyBitRateControlMode, - sizeof(prop), &prop); + sizeof(prop), &prop); } /* Conversion quality : if performance impact then offer degraded option */ - if ((rd->qtcodecsettings.audioCodecFlags & QTAUDIO_FLAG_RESAMPLE_NOHQ) == 0) { + if ((rd->qtcodecsettings.audioCodecFlags & QTAUDIO_FLAG_RESAMPLE_NOHQ) == 0) { prop = kAudioConverterSampleRateConverterComplexity_Mastering; AudioConverterSetProperty(qtexport->audioConverter, kAudioConverterSampleRateConverterComplexity, - sizeof(prop), &prop); + sizeof(prop), &prop); prop = kAudioConverterQuality_Max; AudioConverterSetProperty(qtexport->audioConverter, kAudioConverterSampleRateConverterQuality, - sizeof(prop), &prop); + sizeof(prop), &prop); } write_cookie(qtexport->audioConverter, qtexport->audioFile); @@ -517,29 +517,30 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R /* Allocate output buffer */ if (qtexport->audioOutputFormat.mBytesPerPacket ==0) /* VBR */ AudioConverterGetProperty(qtexport->audioConverter, kAudioConverterPropertyMaximumOutputPacketSize, - &propSize, &qtexport->audioCodecMaxOutputPacketSize); + &propSize, &qtexport->audioCodecMaxOutputPacketSize); else qtexport->audioCodecMaxOutputPacketSize = qtexport->audioOutputFormat.mBytesPerPacket; qtexport->audioInputBuffer = MEM_mallocN(AUDIOOUTPUTBUFFERSIZE, "qt_audio_inputPacket"); qtexport->audioOutputBuffer = MEM_mallocN(AUDIOOUTPUTBUFFERSIZE, "qt_audio_outputPacket"); - qtexport->audioOutputPktDesc = MEM_mallocN(sizeof(AudioStreamPacketDescription)*AUDIOOUTPUTBUFFERSIZE/qtexport->audioCodecMaxOutputPacketSize, - "qt_audio_pktdesc"); + qtexport->audioOutputPktDesc = MEM_mallocN(sizeof(AudioStreamPacketDescription) * AUDIOOUTPUTBUFFERSIZE / qtexport->audioCodecMaxOutputPacketSize, + "qt_audio_pktdesc"); } } } - + if (err == noErr) { - qtexport->videoTempFileName = [[NSString alloc] initWithCString:tmpnam(nil) - encoding:[NSString defaultCStringEncoding]]; - if (qtexport->videoTempFileName) + qtexport->videoTempFileName = [[NSString alloc] initWithCString:tmpnam(nil) + encoding:[NSString defaultCStringEncoding]]; + if (qtexport->videoTempFileName) { qtexport->movie = [[QTMovie alloc] initToWritableFile:qtexport->videoTempFileName error:&error]; + } } } else qtexport->movie = [[QTMovie alloc] initToWritableFile:qtexport->filename error:&error]; - + if(qtexport->movie == nil) { BKE_report(reports, RPT_ERROR, "Unable to create quicktime movie."); success= 0; @@ -585,7 +586,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R specs.rate = U.audiorate; qtexport->audioInputDevice = AUD_openReadDevice(specs); AUD_playDevice(qtexport->audioInputDevice, scene->sound_scene, rd->sfra * rd->frs_sec_base / rd->frs_sec); - + qtexport->audioOutputPktPos = 0; qtexport->audioTotalExportedFrames = 0; qtexport->audioTotalSavedFrames = 0; @@ -655,13 +656,13 @@ int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, in audioPacketsConverted = AUDIOOUTPUTBUFFERSIZE / qtexport->audioCodecMaxOutputPacketSize; err = AudioConverterFillComplexBuffer(qtexport->audioConverter, AudioConverterInputCallback, - NULL, &audioPacketsConverted, &qtexport->audioBufferList, qtexport->audioOutputPktDesc); + NULL, &audioPacketsConverted, &qtexport->audioBufferList, qtexport->audioOutputPktDesc); if (audioPacketsConverted) { AudioFileWritePackets(qtexport->audioFile, false, qtexport->audioBufferList.mBuffers[0].mDataByteSize, - qtexport->audioOutputPktDesc, qtexport->audioOutputPktPos, &audioPacketsConverted, qtexport->audioOutputBuffer); + qtexport->audioOutputPktDesc, qtexport->audioOutputPktPos, &audioPacketsConverted, qtexport->audioOutputBuffer); qtexport->audioOutputPktPos += audioPacketsConverted; - if (qtexport->audioOutputFormat.mFramesPerPacket) { + if (qtexport->audioOutputFormat.mFramesPerPacket) { // this is the common case: format has constant frames per packet qtexport->audioTotalSavedFrames += (audioPacketsConverted * qtexport->audioOutputFormat.mFramesPerPacket); } @@ -751,8 +752,8 @@ void end_qt(void) } /* Save file */ - dict = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] - forKey:QTMovieFlatten]; + dict = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] + forKey:QTMovieFlatten]; if (dict) { [qtexport->movie writeToFile:qtexport->filename withAttributes:dict]; diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h index 604cd940fab..c07ed42332f 100644 --- a/source/blender/render/extern/include/RE_render_ext.h +++ b/source/blender/render/extern/include/RE_render_ext.h @@ -65,7 +65,7 @@ void antialias_tagbuf(int xsize, int ysize, char *rectmove); struct Material *RE_init_sample_material(struct Material *orig_mat, struct Scene *scene); void RE_free_sample_material(struct Material *mat); void RE_sample_material_color(struct Material *mat, float color[3], float *alpha, const float volume_co[3], const float surface_co[3], - int face_index, short hit_quad, struct DerivedMesh *orcoDm, struct Object *ob); + int face_index, short hit_quad, struct DerivedMesh *orcoDm, struct Object *ob); #endif /* __RE_RENDER_EXT_H__ */ diff --git a/source/blender/render/intern/include/pixelshading.h b/source/blender/render/intern/include/pixelshading.h index 00d731912b6..30d574694b2 100644 --- a/source/blender/render/intern/include/pixelshading.h +++ b/source/blender/render/intern/include/pixelshading.h @@ -44,9 +44,9 @@ * \return pointer to the object */ int shadeHaloFloat(HaloRen *har, - float *col, int zz, - float dist, float xn, - float yn, short flarec); + float *col, int zz, + float dist, float xn, + float yn, short flarec); /** * Render the sky at pixel (x, y). diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 667429ca106..984efdbb563 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -55,7 +55,6 @@ #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_sequencer.h" -#include "BKE_utildefines.h" #include "BKE_writeavi.h" /* <------ should be replaced once with generic movie module */ #include "BLI_math.h" diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index a2b0cd09932..603e49766b1 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -38,7 +38,6 @@ #include "BKE_global.h" #include "BKE_main.h" #include "BKE_report.h" -#include "BKE_utildefines.h" #include "BLI_fileops.h" #include "BLI_listbase.h" diff --git a/source/blender/render/intern/source/texture_ocean.c b/source/blender/render/intern/source/texture_ocean.c index b842cab1d29..8c9df496dd6 100644 --- a/source/blender/render/intern/source/texture_ocean.c +++ b/source/blender/render/intern/source/texture_ocean.c @@ -36,7 +36,6 @@ #include "BKE_modifier.h" #include "BKE_ocean.h" -#include "BKE_utildefines.h" #include "render_types.h" #include "RE_shader_ext.h" diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h index 78dbd253cd6..5c88babfb47 100644 --- a/source/blender/windowmanager/WM_keymap.h +++ b/source/blender/windowmanager/WM_keymap.h @@ -57,11 +57,11 @@ void WM_keymap_init (struct bContext *C); void WM_keymap_free (struct wmKeyMap *keymap); wmKeyMapItem *WM_keymap_verify_item(struct wmKeyMap *keymap, const char *idname, int type, - int val, int modifier, int keymodifier); + int val, int modifier, int keymodifier); wmKeyMapItem *WM_keymap_add_item(struct wmKeyMap *keymap, const char *idname, int type, - int val, int modifier, int keymodifier); + int val, int modifier, int keymodifier); wmKeyMapItem *WM_keymap_add_menu(struct wmKeyMap *keymap, const char *idname, int type, - int val, int modifier, int keymodifier); + int val, int modifier, int keymodifier); void WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi); char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 5f4d3f6194a..f9b22331f37 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -115,7 +115,6 @@ struct ImBuf; #include "RNA_types.h" #include "DNA_listBase.h" -#include "BKE_utildefines.h" /* FILE_MAX */ /* exported types for WM */ #include "wm_cursors.h" diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index 0074d6236db..b583c6fd7fe 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -61,7 +61,6 @@ #include "BKE_blender.h" #include "BKE_global.h" -#include "BKE_utildefines.h" #include "BIF_gl.h" #include "BIF_glutil.h" diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 2f4b2d200c3..439f528c0ef 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -810,6 +810,10 @@ if(WITH_CYCLES) cycles_kernel cycles_util cycles_subd) + + if(WITH_CYCLES_OSL) + list(APPEND BLENDER_LINK_LIBS cycles_kernel_osl) + endif() endif() #if(UNIX) @@ -974,6 +978,10 @@ endif() list(APPEND BLENDER_SORTED_LIBS extern_xdnd) endif() + if(WITH_CYCLES_OSL) + list_insert_after(BLENDER_SORTED_LIBS "cycles_kernel" "cycles_kernel_osl") + endif() + foreach(SORTLIB ${BLENDER_SORTED_LIBS}) set(REMLIB ${SORTLIB}) foreach(SEARCHLIB ${BLENDER_LINK_LIBS}) diff --git a/source/creator/creator.c b/source/creator/creator.c index 80981c08c5e..b3c11198403 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -68,7 +68,6 @@ #include "BLI_blenlib.h" -#include "BKE_utildefines.h" #include "BKE_blender.h" #include "BKE_context.h" #include "BKE_depsgraph.h" /* for DAG_on_visible_update */ diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 1b8f857c2cb..ed8a6cc7220 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -54,6 +54,7 @@ #include "KX_BlenderSceneConverter.h" #include "KX_PythonInit.h" #include "KX_PyConstraintBinding.h" +#include "KX_PythonMain.h" #include "RAS_GLExtensionManager.h" #include "RAS_OpenGLRasterizer.h" @@ -79,6 +80,9 @@ extern "C" { #include "DNA_windowmanager_types.h" #include "BKE_global.h" #include "BKE_report.h" + +#include "MEM_guardedalloc.h" + /* #include "BKE_screen.h" */ /* cant include this because of 'new' function name */ extern float BKE_screen_view3d_zoom_to_fac(float camzoom); @@ -121,6 +125,95 @@ static BlendFileData *load_game_data(char *filename) return bfd; } +int BL_KetsjiNextFrame(struct KX_KetsjiEngine* ketsjiengine, struct bContext *C, struct wmWindow* win, struct Scene* scene, struct ARegion *ar, + KX_BlenderKeyboardDevice* keyboarddevice, KX_BlenderMouseDevice* mousedevice, int draw_letterbox) +{ + int exitrequested; + + // first check if we want to exit + exitrequested = ketsjiengine->GetExitCode(); + + // kick the engine + bool render = ketsjiengine->NextFrame(); + + if (render) + { + if(draw_letterbox) { + // Clear screen to border color + // We do this here since we set the canvas to be within the frames. This means the engine + // itself is unaware of the extra space, so we clear the whole region for it. + glClearColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 1.0f); + glViewport(ar->winrct.xmin, ar->winrct.ymin, + BLI_RCT_SIZE_X(&ar->winrct), BLI_RCT_SIZE_Y(&ar->winrct)); + glClear(GL_COLOR_BUFFER_BIT); + } + + // render the frame + ketsjiengine->Render(); + } + + wm_window_process_events_nosleep(); + + // test for the ESC key + //XXX while (qtest()) + while(wmEvent *event= (wmEvent *)win->queue.first) + { + short val = 0; + //unsigned short event = 0; //XXX extern_qread(&val); + + if (keyboarddevice->ConvertBlenderEvent(event->type,event->val)) + exitrequested = KX_EXIT_REQUEST_BLENDER_ESC; + + /* Coordinate conversion... where + * should this really be? + */ + if (event->type==MOUSEMOVE) { + /* Note, not nice! XXX 2.5 event hack */ + val = event->x - ar->winrct.xmin; + mousedevice->ConvertBlenderEvent(MOUSEX, val); + + val = ar->winy - (event->y - ar->winrct.ymin) - 1; + mousedevice->ConvertBlenderEvent(MOUSEY, val); + } + else { + mousedevice->ConvertBlenderEvent(event->type,event->val); + } + + BLI_remlink(&win->queue, event); + wm_event_free(event); + } + + if(win != CTX_wm_window(C)) { + exitrequested= KX_EXIT_REQUEST_OUTSIDE; /* window closed while bge runs */ + } + return exitrequested; +} + +struct BL_KetsjiNextFrameState { + struct KX_KetsjiEngine* ketsjiengine; + struct bContext *C; + struct wmWindow* win; + struct Scene* scene; + struct ARegion *ar; + KX_BlenderKeyboardDevice* keyboarddevice; + KX_BlenderMouseDevice* mousedevice; + int draw_letterbox; +} ketsjinextframestate; + +int BL_KetsjiPyNextFrame(void *state0) +{ + BL_KetsjiNextFrameState *state = (BL_KetsjiNextFrameState *) state0; + return BL_KetsjiNextFrame( + state->ketsjiengine, + state->C, + state->win, + state->scene, + state->ar, + state->keyboarddevice, + state->mousedevice, + state->draw_letterbox); +} + extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *cam_frame, int always_use_expand_framing) { /* context values */ @@ -440,71 +533,49 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c // Could be in StartEngine set the framerate, we need the scene to do this ketsjiengine->SetAnimFrameRate(FPS); +#ifdef WITH_PYTHON + char *python_main = NULL; + pynextframestate.state = NULL; + pynextframestate.func = NULL; + python_main = KX_GetPythonMain(scene); + // the mainloop printf("\nBlender Game Engine Started\n"); - while (!exitrequested) + if (python_main) { + char *python_code = KX_GetPythonCode(blenderdata, python_main); + if (python_code) { + ketsjinextframestate.ketsjiengine = ketsjiengine; + ketsjinextframestate.C = C; + ketsjinextframestate.win = win; + ketsjinextframestate.scene = scene; + ketsjinextframestate.ar = ar; + ketsjinextframestate.keyboarddevice = keyboarddevice; + ketsjinextframestate.mousedevice = mousedevice; + ketsjinextframestate.draw_letterbox = draw_letterbox; + + pynextframestate.state = &ketsjinextframestate; + pynextframestate.func = &BL_KetsjiPyNextFrame; + printf("Yielding control to Python script '%s'...\n", python_main); + PyRun_SimpleString(python_code); + printf("Exit Python script '%s'\n", python_main); + MEM_freeN(python_code); + } + } + else +#endif /* WITH_PYTHON */ { - // first check if we want to exit - exitrequested = ketsjiengine->GetExitCode(); - - // kick the engine - bool render = ketsjiengine->NextFrame(); - - if (render) + while (!exitrequested) { - if (draw_letterbox) { - // Clear screen to border color - // We do this here since we set the canvas to be within the frames. This means the engine - // itself is unaware of the extra space, so we clear the whole region for it. - glClearColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 1.0f); - glViewport(ar->winrct.xmin, ar->winrct.ymin, - BLI_RCT_SIZE_X(&ar->winrct), BLI_RCT_SIZE_Y(&ar->winrct)); - glClear(GL_COLOR_BUFFER_BIT); - } - - // render the frame - ketsjiengine->Render(); - } - - wm_window_process_events_nosleep(); - - // test for the ESC key - //XXX while (qtest()) - while(wmEvent *event= (wmEvent *)win->queue.first) - { - short val = 0; - //unsigned short event = 0; //XXX extern_qread(&val); - - if (keyboarddevice->ConvertBlenderEvent(event->type,event->val)) - exitrequested = KX_EXIT_REQUEST_BLENDER_ESC; - - /* Coordinate conversion... where - * should this really be? - */ - if (event->type==MOUSEMOVE) { - /* Note, not nice! XXX 2.5 event hack */ - val = event->x - ar->winrct.xmin; - mousedevice->ConvertBlenderEvent(MOUSEX, val); - - val = ar->winy - (event->y - ar->winrct.ymin) - 1; - mousedevice->ConvertBlenderEvent(MOUSEY, val); - } - else { - mousedevice->ConvertBlenderEvent(event->type,event->val); - } - - BLI_remlink(&win->queue, event); - wm_event_free(event); - } - - if (win != CTX_wm_window(C)) { - exitrequested= KX_EXIT_REQUEST_OUTSIDE; /* window closed while bge runs */ + exitrequested = BL_KetsjiNextFrame(ketsjiengine, C, win, scene, ar, keyboarddevice, mousedevice, draw_letterbox); } } printf("Blender Game Engine Finished\n"); exitstring = ketsjiengine->GetExitString(); - gs = *(ketsjiengine->GetGlobalSettings()); +#ifdef WITH_PYTHON + if (python_main) MEM_freeN(python_main); +#endif /* WITH_PYTHON */ + gs = *(ketsjiengine->GetGlobalSettings()); // when exiting the mainloop #ifdef WITH_PYTHON diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 89a3f365140..9caa6bbf579 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -82,8 +82,7 @@ #include "BKE_text.h" #include "BLI_blenlib.h" #include "BLI_math_base.h" - -#define FILE_MAX 1024 // repeated here to avoid dependency from BKE_utildefines.h +#include "BLI_path_util.h" #include "KX_NetworkMessageActuator.h" diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 41f641b4368..6e1e8f5a8ec 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -47,6 +47,7 @@ #endif // __APPLE__ #include "KX_KetsjiEngine.h" #include "KX_PythonInit.h" +#include "KX_PythonMain.h" /********************************** * Begin Blender include block @@ -97,7 +98,6 @@ extern char datatoc_bfont_ttf[]; #include "RAS_IRasterizer.h" #include "BKE_main.h" -#include "BKE_utildefines.h" #include "RNA_define.h" @@ -332,6 +332,41 @@ static BlendFileData *load_game_data(const char *progname, char *filename = NULL return bfd; } +bool GPG_NextFrame(GHOST_ISystem* system, GPG_Application *app, int &exitcode, STR_String &exitstring, GlobalSettings *gs) +{ + bool run = true; + system->processEvents(false); + system->dispatchEvents(); + app->EngineNextFrame(); + if ((exitcode = app->getExitRequested())) + { + run = false; + exitstring = app->getExitString(); + *gs = *app->getGlobalSettings(); + } + return run; +} + +struct GPG_NextFrameState { + GHOST_ISystem* system; + GPG_Application *app; + GlobalSettings *gs; +} gpg_nextframestate; + +int GPG_PyNextFrame(void *state0) +{ + GPG_NextFrameState *state = (GPG_NextFrameState *) state0; + int exitcode; + STR_String exitstring; + bool run = GPG_NextFrame(state->system, state->app, exitcode, exitstring, state->gs); + if (run) return 0; + else { + if (exitcode) + fprintf(stderr, "Exit code %d: %s\n", exitcode, exitstring.ReadPtr()); + return 1; + } +} + int main(int argc, char** argv) { int i; @@ -966,17 +1001,39 @@ int main(int argc, char** argv) // Enter main loop bool run = true; - while (run) + char *python_main = NULL; + pynextframestate.state = NULL; + pynextframestate.func = NULL; +#ifdef WITH_PYTHON + python_main = KX_GetPythonMain(scene); +#endif // WITH_PYTHON + if (python_main) { - system->processEvents(false); - system->dispatchEvents(); - app.EngineNextFrame(); - - if ((exitcode = app.getExitRequested())) + char *python_code = KX_GetPythonCode(maggie, python_main); + if (python_code) { - run = false; - exitstring = app.getExitString(); - gs = *app.getGlobalSettings(); +#ifdef WITH_PYTHON + gpg_nextframestate.system = system; + gpg_nextframestate.app = &app; + gpg_nextframestate.gs = &gs; + pynextframestate.state = &gpg_nextframestate; + pynextframestate.func = &GPG_PyNextFrame; + + printf("Yielding control to Python script '%s'...\n", python_main); + PyRun_SimpleString(python_code); + printf("Exit Python script '%s'\n", python_main); +#endif // WITH_PYTHON + MEM_freeN(python_code); + } + else { + fprintf(stderr, "ERROR: cannot yield control to Python: no Python text data block named '%s'\n", python_main); + } + } + else + { + while (run) + { + run = GPG_NextFrame(system, &app, exitcode, exitstring, &gs); } } app.StopGameEngine(); @@ -986,6 +1043,7 @@ int main(int argc, char** argv) system->removeEventConsumer(&app); BLO_blendfiledata_free(bfd); + if (python_main) MEM_freeN(python_main); } } while (exitcode == KX_EXIT_REQUEST_RESTART_GAME || exitcode == KX_EXIT_REQUEST_START_OTHER_GAME); } diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt index 4b3426e0784..269311b7e00 100644 --- a/source/gameengine/Ketsji/CMakeLists.txt +++ b/source/gameengine/Ketsji/CMakeLists.txt @@ -107,6 +107,7 @@ set(SRC KX_PyMath.cpp KX_PythonInit.cpp KX_PythonInitTypes.cpp + KX_PythonMain.cpp KX_PythonSeq.cpp KX_RadarSensor.cpp KX_RayCast.cpp @@ -189,6 +190,7 @@ set(SRC KX_PyMath.h KX_PythonInit.h KX_PythonInitTypes.h + KX_PythonMain.h KX_PythonSeq.h KX_RadarSensor.h KX_RayCast.h diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 581b3712f97..7d29a20d1a2 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -133,7 +133,6 @@ extern "C" { #include "PHY_IPhysicsEnvironment.h" #include "BKE_main.h" -#include "BKE_utildefines.h" #include "BKE_global.h" #include "BLI_blenlib.h" #include "GPU_material.h" @@ -811,6 +810,23 @@ static PyObject *gLibList(PyObject*, PyObject* args) return list; } +struct PyNextFrameState pynextframestate; +static PyObject *gPyNextFrame(PyObject *) +{ + if (pynextframestate.func == NULL) Py_RETURN_NONE; + if (pynextframestate.state == NULL) Py_RETURN_NONE; //should never happen; raise exception instead? + + if (pynextframestate.func(pynextframestate.state)) //nonzero = stop + { + Py_RETURN_TRUE; + } + else // 0 = go on + { + Py_RETURN_FALSE; + } +} + + static struct PyMethodDef game_methods[] = { {"expandPath", (PyCFunction)gPyExpandPath, METH_VARARGS, (const char *)gPyExpandPath_doc}, {"startGame", (PyCFunction)gPyStartGame, METH_VARARGS, (const char *)gPyStartGame_doc}, @@ -840,7 +856,7 @@ static struct PyMethodDef game_methods[] = { {"getBlendFileList", (PyCFunction)gPyGetBlendFileList, METH_VARARGS, (const char *)"Gets a list of blend files in the same directory as the current blend file"}, {"PrintGLInfo", (PyCFunction)pyPrintExt, METH_NOARGS, (const char *)"Prints GL Extension Info"}, {"PrintMemInfo", (PyCFunction)pyPrintStats, METH_NOARGS, (const char *)"Print engine statistics"}, - + {"NextFrame", (PyCFunction)gPyNextFrame, METH_NOARGS, (const char *)"Render next frame (if Python has control)"}, /* library functions */ {"LibLoad", (PyCFunction)gLibLoad, METH_VARARGS|METH_KEYWORDS, (const char *)""}, {"LibNew", (PyCFunction)gLibNew, METH_VARARGS, (const char *)""}, diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h index 866681b9da7..1500dd97ae1 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.h +++ b/source/gameengine/Ketsji/KX_PythonInit.h @@ -70,6 +70,16 @@ class KX_Scene; void KX_SetActiveScene(class KX_Scene* scene); class KX_Scene* KX_GetActiveScene(); class KX_KetsjiEngine* KX_GetActiveEngine(); + +typedef int (*PyNextFrameFunc)(void *); +struct PyNextFrameState { + //state: can be either a GPG_NextFrameState or a BL_KetsjiNextFrameState + void *state; + //func: can be either GPG_PyNextFrame or BL_KetsjiPyNextFrame + PyNextFrameFunc func; +}; +extern struct PyNextFrameState pynextframestate; + #include "MT_Vector3.h" void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color); diff --git a/source/gameengine/Ketsji/KX_PythonMain.cpp b/source/gameengine/Ketsji/KX_PythonMain.cpp new file mode 100644 index 00000000000..d5550ce4380 --- /dev/null +++ b/source/gameengine/Ketsji/KX_PythonMain.cpp @@ -0,0 +1,77 @@ +/* + * $Id: KX_PythonMain.cpp 37750 2011-06-27 09:27:56Z sjoerd $ + * + * ***** 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +/** \file gameengine/Ketsji/KX_KetsjiPythonMain.cpp + * \ingroup ketsji + */ + +#include "KX_PythonMain.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include "MEM_guardedalloc.h" + +#include "BLI_string.h" +#include "BLI_listbase.h" + +#include "BKE_text.h" +#include "BKE_main.h" +#include "BKE_idprop.h" + + +#ifdef __cplusplus +} +#endif + +extern "C" char *KX_GetPythonMain(struct Scene *scene) +{ + /* examine custom scene properties */ + if (scene->id.properties) { + IDProperty *item = IDP_GetPropertyTypeFromGroup(scene->id.properties, "__main__", IDP_STRING); + if (item) { + return BLI_strdup(IDP_String(item)); + } + } + + return NULL; +} + +extern "C" char *KX_GetPythonCode(Main *bmain, char *python_main) +{ + Text *text; + + if ((text = (Text *)BLI_findstring(&bmain->text, python_main, offsetof(ID, name) + 2))) { + return txt_to_buf(text); + } + + return NULL; +} diff --git a/source/gameengine/Ketsji/KX_PythonMain.h b/source/gameengine/Ketsji/KX_PythonMain.h new file mode 100644 index 00000000000..1460ea2ca96 --- /dev/null +++ b/source/gameengine/Ketsji/KX_PythonMain.h @@ -0,0 +1,41 @@ +/* + * $Id: KX_PythonMain.h 37750 2011-06-27 09:27:56Z sjoerd $ + * + * ***** 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file KX_PythonMain.h + * \ingroup ketsji + */ + +#ifndef __KX_PYTHON_MAIN +#define __KX_PYTHON_MAIN + +#include "BKE_main.h" +#include "DNA_scene_types.h" +extern "C" char *KX_GetPythonMain(struct Scene* scene); +extern "C" char *KX_GetPythonCode(struct Main *main, char *python_main); +#endif From 3b9c3604c6e96cf4b460af3554355dbbe2f7752b Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 4 Sep 2012 12:32:12 +0000 Subject: [PATCH 102/160] Color Management: remove hardcoded ACES ODT tonemap This tonemap was added as a temporary option only and if it'll be needed again, it'll be better to implement is as either a spline in OCIO or as a film response curve (as some of such curves were added as a presets for RGB curves in Mango production SVN). Also revert changes made to IMB_buffer_byte_from_float since it's not actually needed anymore and makes it's clearer changes against trunk. --- source/blender/imbuf/IMB_imbuf.h | 9 - source/blender/imbuf/intern/colormanagement.c | 135 ++--------- source/blender/imbuf/intern/divers.c | 48 +--- source/blender/imbuf/intern/filter.c | 217 ------------------ 4 files changed, 28 insertions(+), 381 deletions(-) diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 54a6a7f597e..d23d42ddd0c 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -392,15 +392,6 @@ void IMB_buffer_byte_from_byte(unsigned char *rect_to, const unsigned char *rect int width, int height, int stride_to, int stride_from); void IMB_buffer_float_clamp(float *buf, int width, int height); -/* converting pixel buffers using tonecurve */ - -typedef void (*imb_tonecurveCb) (float rgbOut[3], const float rgbIn[3]); - -void IMB_buffer_byte_from_float_tonecurve(unsigned char *rect_to, const float *rect_from, - int channels_from, float dither, int profile_to, int profile_from, int predivide, - int width, int height, int stride_to, int stride_from, - imb_tonecurveCb tonecurve_func); - /** * Change the ordering of the color bytes pointed to by rect from * rgba to abgr. size * 4 color bytes are reordered. diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index a9962cee4d8..dff6990743c 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -75,9 +75,6 @@ typedef struct ConstProcessorRcPtr { /* define this to allow byte buffers be color managed */ #undef COLORMANAGE_BYTE_BUFFER -#undef COLORMANAGE_USE_ACES_ODT - -#define ACES_ODT_TONECORVE "ACES" /* ** list of all supported color spaces, displays and views */ #ifdef WITH_OCIO @@ -582,11 +579,6 @@ void IMB_colormanagement_init(void) OCIO_configRelease(config); -#ifdef COLORMANAGE_USE_ACES_ODT - /* special views, which does not depend on OCIO */ - colormanage_view_add(ACES_ODT_TONECORVE); -#endif - #endif BLI_init_srgb_conversion(); @@ -737,44 +729,7 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) return linear_buffer; } -#ifdef COLORMANAGE_USE_ACES_ODT -static void *do_display_buffer_apply_tonemap_thread(void *handle_v) -{ - DisplayBufferThread *handle = (DisplayBufferThread *) handle_v; - imb_tonecurveCb tonecurve_func = (imb_tonecurveCb) handle->processor; - - float *buffer = handle->buffer; - unsigned char *display_buffer = handle->display_buffer; - - int channels = handle->channels; - int width = handle->width; - int height = handle->tot_line; - int dither = handle->dither; - int predivide = handle->predivide; - - float *linear_buffer = display_buffer_apply_get_linear_buffer(handle); - - IMB_buffer_byte_from_float_tonecurve(display_buffer, linear_buffer, channels, dither, - IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, - predivide, width, height, width, width, - tonecurve_func); - - if (linear_buffer != buffer) - MEM_freeN(linear_buffer); - - return NULL; -} - -static void display_buffer_apply_tonemap(ImBuf *ibuf, unsigned char *display_buffer, - imb_tonecurveCb tonecurve_func) -{ - display_buffer_apply_threaded(ibuf, ibuf->rect_float, (unsigned char *)ibuf->rect, - display_buffer, tonecurve_func, - do_display_buffer_apply_tonemap_thread); -} -#endif - -static void *do_display_buffer_apply_ocio_thread(void *handle_v) +static void *do_display_buffer_apply_thread(void *handle_v) { DisplayBufferThread *handle = (DisplayBufferThread *) handle_v; ConstProcessorRcPtr *processor = (ConstProcessorRcPtr *) handle->processor; @@ -856,9 +811,9 @@ static ConstProcessorRcPtr *create_display_buffer_processor(const char *view_tra return processor; } -static void display_buffer_apply_ocio(ImBuf *ibuf, unsigned char *display_buffer, - const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) +static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *display_buffer, + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) { ConstProcessorRcPtr *processor; const float gamma = view_settings->gamma; @@ -870,33 +825,12 @@ static void display_buffer_apply_ocio(ImBuf *ibuf, unsigned char *display_buffer if (processor) { display_buffer_apply_threaded(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect, - display_buffer, processor, do_display_buffer_apply_ocio_thread); + display_buffer, processor, do_display_buffer_apply_thread); } OCIO_processorRelease(processor); } -static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *display_buffer, - const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) -{ -#ifdef COLORMANAGE_USE_ACES_ODT - const char *view_transform = view_settings->view_transform; - - if (!strcmp(view_transform, ACES_ODT_TONECORVE)) { - /* special case for Mango team, this does not actually apply - * any input space -> display space conversion and just applies - * a tonecurve for better linear float -> sRGB byte conversion - */ - display_buffer_apply_tonemap(ibuf, display_buffer, IMB_ratio_preserving_odt_tonecurve); - } - else -#endif - { - display_buffer_apply_ocio(ibuf, display_buffer, view_settings, display_settings); - } -} - /*********************** Threaded color space transform routines *************************/ typedef struct ColorspaceTransformThread { @@ -1845,14 +1779,6 @@ void IMB_colormanagement_view_items_add(EnumPropertyItem **items, int *totitem, ColorManagedDisplay *display = colormanage_display_get_named(display_name); ColorManagedView *view; -#ifdef COLORMANAGE_USE_ACES_ODT - /* OCIO_TODO: try to get rid of such a hackish stuff */ - view = colormanage_view_get_named(ACES_ODT_TONECORVE); - if (view) { - colormanagement_view_item_add(items, totitem, view); - } -#endif - if (display) { LinkData *display_view; @@ -1901,8 +1827,7 @@ void IMB_colormanagement_colorspace_items_add(EnumPropertyItem **items, int *tot static void partial_buffer_update_rect(unsigned char *display_buffer, const float *linear_buffer, int display_stride, int linear_stride, int linear_offset_x, int linear_offset_y, int channels, int dither, int predivide, int profile_from, - ConstProcessorRcPtr *processor, imb_tonecurveCb tonecurve_func, - int xmin, int ymin, int xmax, int ymax) + ConstProcessorRcPtr *processor, int xmin, int ymin, int xmax, int ymax) { int x, y; @@ -1928,12 +1853,7 @@ static void partial_buffer_update_rect(unsigned char *display_buffer, const floa } else #endif - if (tonecurve_func) { - IMB_buffer_byte_from_float_tonecurve(display_buffer + display_index, linear_buffer + linear_index, - channels, dither, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, - predivide, 1, 1, 1, 1, tonecurve_func); - } - else { + { IMB_buffer_byte_from_float(display_buffer + display_index, linear_buffer + linear_index, channels, dither, IB_PROFILE_SRGB, profile_from, predivide, 1, 1, 1, 1); } @@ -1948,23 +1868,22 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, int predivide = ibuf->flags & IB_cm_predivide; int dither = ibuf->dither; int profile_from = ibuf->profile; + int display; + int *display_buffer_flags; #ifdef WITH_OCIO - int display; - - int *display_buffer_flags; BLI_lock_thread(LOCK_COLORMANAGE); + if (ibuf->rect && ibuf->rect_float) { + /* update byte buffer created by legacy color management */ + partial_buffer_update_rect((unsigned char *) ibuf->rect, linear_buffer, ibuf->x, stride, offset_x, offset_y, + channels, dither, predivide, profile_from, NULL, xmin, ymin, xmax, ymax); + } + if (!ibuf->display_buffer_flags) { /* there's no cached display buffers, so no need to iterate though bit fields */ - if (ibuf->rect && ibuf->rect_float) { - /* update byte buffer created by legacy color management */ - partial_buffer_update_rect((unsigned char *) ibuf->rect, linear_buffer, ibuf->x, stride, offset_x, offset_y, - channels, dither, predivide, profile_from, NULL, NULL, xmin, ymin, xmax, ymax); - } - BLI_unlock_thread(LOCK_COLORMANAGE); return; @@ -2011,21 +1930,12 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, if (display_buffer) { const char *view_name = IMB_colormanagement_view_get_indexed_name(view_index); ConstProcessorRcPtr *processor = NULL; - imb_tonecurveCb tonecurve_func = NULL; -#ifdef COLORMANAGE_USE_ACES_ODT - if (!strcmp(view_name, ACES_ODT_TONECORVE)) { - tonecurve_func = IMB_ratio_preserving_odt_tonecurve; - } - else -#endif - { - processor = create_display_buffer_processor(view_name, display_name, exposure, gamma); - } + processor = create_display_buffer_processor(view_name, display_name, exposure, gamma); partial_buffer_update_rect(display_buffer, linear_buffer, buffer_width, stride, offset_x, offset_y, channels, dither, predivide, profile_from, - processor, tonecurve_func, xmin, ymin, xmax, ymax); + processor, xmin, ymin, xmax, ymax); if (processor) OCIO_processorRelease(processor); @@ -2040,13 +1950,8 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, } MEM_freeN(display_buffer_flags); +#else + (void) display; + (void) display_buffer_flags; #endif - - BLI_lock_thread(LOCK_COLORMANAGE); - if (ibuf->rect && ibuf->rect_float) { - /* update byte buffer created by legacy color management */ - partial_buffer_update_rect((unsigned char *) ibuf->rect, linear_buffer, ibuf->x, stride, offset_x, offset_y, - channels, dither, predivide, profile_from, NULL, NULL, xmin, ymin, xmax, ymax); - } - BLI_unlock_thread(LOCK_COLORMANAGE); } diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 581b55d4377..5ba08f1dd73 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -38,15 +38,10 @@ #include "imbuf.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" -#include "IMB_filter.h" #include "IMB_allocimbuf.h" #include "MEM_guardedalloc.h" -#ifdef WITH_OCIO -#include -#endif - /**************************** Interlace/Deinterlace **************************/ void IMB_de_interlace(ImBuf *ibuf) @@ -190,13 +185,11 @@ MINLINE void float_to_byte_dither_v4(uchar b[4], const float f[4], DitherContext } /* float to byte pixels, output 4-channel RGBA */ -void IMB_buffer_byte_from_float_tonecurve(uchar *rect_to, const float *rect_from, - int channels_from, float dither, int profile_to, int profile_from, int predivide, - int width, int height, int stride_to, int stride_from, - imb_tonecurveCb tonecurve_func) +void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, + int channels_from, float dither, int profile_to, int profile_from, int predivide, + int width, int height, int stride_to, int stride_from) { float tmp[4]; - float corrected[4]; int x, y; DitherContext *di; @@ -207,9 +200,6 @@ void IMB_buffer_byte_from_float_tonecurve(uchar *rect_to, const float *rect_from if (dither) di = create_dither_context(width, dither); - if (!tonecurve_func) - tonecurve_func = copy_v3_v3; - for (y = 0; y < height; y++) { if (channels_from == 1) { /* single channel input */ @@ -234,8 +224,7 @@ void IMB_buffer_byte_from_float_tonecurve(uchar *rect_to, const float *rect_from else if (profile_to == IB_PROFILE_SRGB) { /* convert from linear to sRGB */ for (x = 0; x < width; x++, from += 3, to += 4) { - tonecurve_func(corrected, from); - linearrgb_to_srgb_v3_v3(tmp, corrected); + linearrgb_to_srgb_v3_v3(tmp, from); rgb_float_to_uchar(to, tmp); to[3] = 255; } @@ -271,37 +260,25 @@ void IMB_buffer_byte_from_float_tonecurve(uchar *rect_to, const float *rect_from if (dither && predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { - tonecurve_func(corrected, from); - corrected[3] = from[3]; - - linearrgb_to_srgb_ushort4_predivide(us, corrected); + linearrgb_to_srgb_ushort4_predivide(us, from); ushort_to_byte_dither_v4(to, us, di); } } else if (dither) { for (x = 0; x < width; x++, from += 4, to += 4) { - tonecurve_func(corrected, from); - corrected[3] = from[3]; - - linearrgb_to_srgb_ushort4(us, corrected); + linearrgb_to_srgb_ushort4(us, from); ushort_to_byte_dither_v4(to, us, di); } } else if (predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { - tonecurve_func(corrected, from); - corrected[3] = from[3]; - - linearrgb_to_srgb_ushort4_predivide(us, corrected); + linearrgb_to_srgb_ushort4_predivide(us, from); ushort_to_byte_v4(to, us); } } else { for (x = 0; x < width; x++, from += 4, to += 4) { - tonecurve_func(corrected, from); - corrected[3] = from[3]; - - linearrgb_to_srgb_ushort4(us, corrected); + linearrgb_to_srgb_ushort4(us, from); ushort_to_byte_v4(to, us); } } @@ -343,15 +320,6 @@ void IMB_buffer_byte_from_float_tonecurve(uchar *rect_to, const float *rect_from clear_dither_context(di); } -void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, - int channels_from, float dither, int profile_to, int profile_from, int predivide, - int width, int height, int stride_to, int stride_from) -{ - IMB_buffer_byte_from_float_tonecurve(rect_to, rect_from, channels_from, dither, profile_to, profile_from, predivide, - width, height, stride_to, stride_from, NULL); -} - - /* byte to float pixels, input and output 4-channel RGBA */ void IMB_buffer_float_from_byte(float *rect_to, const uchar *rect_from, int profile_to, int profile_from, int predivide, diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c index 5f8e9bd4dec..678b2908b96 100644 --- a/source/blender/imbuf/intern/filter.c +++ b/source/blender/imbuf/intern/filter.c @@ -31,11 +31,8 @@ * \ingroup imbuf */ -#include - #include "MEM_guardedalloc.h" -#include "BLI_math.h" #include "BLI_utildefines.h" #include "IMB_imbuf_types.h" @@ -602,217 +599,3 @@ void IMB_premultiply_alpha(ImBuf *ibuf) IMB_premultiply_rect_float(ibuf->rect_float, ibuf->planes, ibuf->x, ibuf->y); } -/* Tonecurve corrections */ - -/* code of rdt_shaper_fwd and ratio_preserving_odt_tonecurve belongs to - * ACES project (https://github.com/ampas/aces-dev) - */ - -/* === ODT SPLINE === */ -/* - * Algorithm for applying ODT tone curve in forward direction. - * - * vers 1.0 Doug Walker 2012-01-23 - * modified by Scott Dyer 2012-02-28 - */ - -/* Input and output are in linear (not log) units. */ -static float rdt_shaper_fwd(float x) -{ - /* B-spline coefficients. - * The units are density of the output. - */ - const float COEFS0 = -0.008f; - const float COEFS1 = -0.00616f; - const float COEFS2 = 0.026f; - const float COEFS3 = 0.185f; - const float COEFS4 = 0.521f; - const float COEFS5 = 0.993f; - const float COEFS6 = 1.563f; - const float COEFS7 = 2.218f; - const float COEFS8 = 2.795f; - const float COEFS9 = 3.36f; - const float COEFS10 = 4.0f; /* NB: keep this less than or equal to -log10(FLARE) */ - /* The locations of these control points in OCES density space are: - * -1., -0.79, -0.44, -0.01, 0.48, 1.01, 1.58, 2.18, 2.82, 3.47, 4.15, 4.85 - */ - - /* The flare term allows the spline to more rapidly approach zero - * while keeping the shape of the curve well-behaved in density space. - */ - const float FLARE = 1e-4f; - - /* The last control point is fixed to yield a specific density at the - * end of the knot domain. - */ - /* const float COEFS11 = 2. * (-log10(FLARE) - 0.001) - COEFS10; */ - - /* Note: Apparently a CTL bug prevents calling log10() here, so - * you'll need to update this manually if you change FLARE. - */ - const float COEFS11 = COEFS10 + 2.0f * (4.0f - COEFS10); - - /* The knots are in units of OCES density. */ - const unsigned int KNOT_LEN = 11; - const float KNOT_START = -0.9f; - const float KNOT_END = 4.484256f; - - /* The KNOT_POW adjusts the spacing to put more knots near the toe (highlights). */ - const float KNOT_POW = 1.0f / 1.3f; - const float OFFS = KNOT_START; - const float SC = KNOT_END - KNOT_START; - - /* KNOT_DENS is density of the spline at the knots. */ - const float KNOT_DENS[11] = { - (COEFS0 + COEFS1) / 2.0f, - (COEFS1 + COEFS2) / 2.0f, - (COEFS2 + COEFS3) / 2.0f, - (COEFS3 + COEFS4) / 2.0f, - (COEFS4 + COEFS5) / 2.0f, - (COEFS5 + COEFS6) / 2.0f, - (COEFS6 + COEFS7) / 2.0f, - (COEFS7 + COEFS8) / 2.0f, - (COEFS8 + COEFS9) / 2.0f, - (COEFS9 + COEFS10) / 2.0f, - (COEFS10 + COEFS11) / 2.0f - }; - - /* Parameters controlling linear extrapolation. */ - const float LIGHT_SLOPE = 0.023; - const float CROSSOVER = pow(10,-KNOT_END); - const float REV_CROSSOVER = pow(10.0f, -KNOT_DENS[ KNOT_LEN - 1]) - FLARE; - const float DARK_SLOPE = REV_CROSSOVER / CROSSOVER; - - /* Textbook monomial to basis-function conversion matrix. */ - /*const*/ float M[3][3] = { - { 0.5f, -1.0f, 0.5f}, - {-1.0f, 1.0f, 0.5f}, - { 0.5f, 0.0f, 0.0f} - }; - - float y; - - /* Linear extrapolation in linear space for negative & very dark values. */ - if (x <= CROSSOVER) { - y = x * DARK_SLOPE; - } - else { - float in_dens = -log10(x); - float out_dens; - float knot_coord = (in_dens - OFFS) / SC; - - if (knot_coord <= 0.0f) { - /* Linear extrapolation in log space for very light values. */ - - out_dens = KNOT_DENS[0] - (KNOT_START - in_dens) * LIGHT_SLOPE; - } - else { - /* For typical OCES values, apply a B-spline curve. */ - - int j; - float t; - float cf[3], monomials[3], v[3]; - - knot_coord = ( KNOT_LEN - 1) * pow( knot_coord, KNOT_POW); - - j = knot_coord; - t = knot_coord - j; - - /* Would like to do this: */ - /* float cf[ 3] = { COEFS[ j], COEFS[ j + 1], COEFS[ j + 2]}; */ - /* or at least: */ - /* cf[0] = COEFS[j]; */ - /* cf[1] = COEFS[j + 1]; */ - /* cf[2] = COEFS[j + 2]; */ - /* But apparently CTL bugs prevent it, so we do the following: */ - if (j <= 0) { - cf[0] = COEFS0; cf[1] = COEFS1; cf[2] = COEFS2; - } - else if (j == 1) { - cf[0] = COEFS1; cf[1] = COEFS2; cf[2] = COEFS3; - } - else if (j == 2) { - cf[0] = COEFS2; cf[1] = COEFS3; cf[2] = COEFS4; - } - else if (j == 3) { - cf[0] = COEFS3; cf[1] = COEFS4; cf[2] = COEFS5; - } - else if (j == 4) { - cf[0] = COEFS4; cf[1] = COEFS5; cf[2] = COEFS6; - } - else if (j == 5) { - cf[0] = COEFS5; cf[1] = COEFS6; cf[2] = COEFS7; - } - else if (j == 6) { - cf[0] = COEFS6; cf[1] = COEFS7; cf[2] = COEFS8; - } - else if (j == 7) { - cf[0] = COEFS7; cf[1] = COEFS8; cf[2] = COEFS9; - } - else if (j == 8) { - cf[0] = COEFS8; cf[1] = COEFS9; cf[2] = COEFS10; - } - else { - cf[0] = COEFS9; cf[1] = COEFS10; cf[2] = COEFS11; - } - - monomials[0] = t * t; - monomials[1] = t; - monomials[2] = 1.0f; - - mul_v3_m3v3(v, M, cf); - out_dens = dot_v3v3( monomials, v); - } - - y = pow(10.0f, -out_dens) - FLARE; - } - - return y; -} - -void IMB_ratio_preserving_odt_tonecurve(float rgbOut[3], const float rgbIn[3]) -{ - float acesIn[3], acesOut[3]; - - float rec709_to_aces[3][3] = {{0.4395770431f, 0.0895979404f, 0.0174174830f}, - {0.3839148879f, 0.8147120476f, 0.1087378338f}, - {0.1765103489f, 0.0956883803f, 0.8738504052f}}; - - float aces_to_rec709[3][3] = {{ 2.5219228268f, -0.2754705548f, -0.0159884077f}, - {-1.1370280981f, 1.3698303699f, -0.1477921605f}, - {-0.3849000633f, -0.0943564922f, 1.1637737751f}}; - - /* The "ratio preserving tonecurve" is used to avoid hue/chroma shifts. - * It sends a norm through the tonecurve and scales the RGB values based on the output. - */ - - const float NTH_POWER = 2.0f; - const float TINY = 1e-12f; - float numerator, denominator; - float normRGB, normRGBo; - - mul_v3_m3v3(acesIn, rec709_to_aces, (float *) rgbIn); - - numerator = pow(acesIn[0], NTH_POWER) + pow(acesIn[1], NTH_POWER) + pow(acesIn[2], NTH_POWER); - - denominator = pow(acesIn[0], NTH_POWER - 1) + - pow(acesIn[1], NTH_POWER - 1) + - pow(acesIn[2], NTH_POWER - 1); - - /* use of max function to avoid divide by zero */ - denominator = MAX2(TINY, denominator); - - normRGB = numerator / denominator; - - if (normRGB <= 0.0f) { - normRGB = TINY; - } - - normRGBo = rdt_shaper_fwd(normRGB); - - acesOut[0] = acesIn[0] * normRGBo / normRGB; - acesOut[1] = acesIn[1] * normRGBo / normRGB; - acesOut[2] = acesIn[2] * normRGBo / normRGB; - - mul_v3_m3v3(rgbOut, aces_to_rec709, (float *) acesOut); -} From 1508f62169d3a0960ac52e2d2b5634ab0ae0efac Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 4 Sep 2012 12:32:18 +0000 Subject: [PATCH 103/160] Color Management: fix for view/display settings validation It was a misusage of LinkData and actual data leading to wrong string comparsion and possible wrong memory access. --- source/blender/imbuf/intern/colormanagement.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index dff6990743c..1bedfb58754 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1453,17 +1453,20 @@ void IMB_colormanagement_validate_settings(ColorManagedDisplaySettings *display_ { #ifdef WITH_OCIO ColorManagedDisplay *display; - ColorManagedView *default_view, *view; + ColorManagedView *default_view; + LinkData *view_link; display = colormanage_display_get_named(display_settings->display_device); default_view = colormanage_view_get_default(display); - for (view = display->views.first; view; view = view->next) { + for (view_link = display->views.first; view_link; view_link = view_link->next) { + ColorManagedView *view = view_link->data; + if (!strcmp(view->name, view_settings->view_transform)) break; } - if (view == NULL) + if (view_link == NULL) BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform)); #else (void) display_settings; From b0bf16b28c2d66d618df5246c04f584d74ef9760 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 4 Sep 2012 12:32:25 +0000 Subject: [PATCH 104/160] Color Management: OpenCOlorIO configuration file cleanup - Remove unused color space and LUTs/matrices There were couple of spaces for specific cameras which are unlikely be used by general blender users. Think better to keep this things as clean as possible for official builds, it could easily be extended for some specific pipeline. - Move rec709 view to it's own display. Such way makes more sense. Probably it'll actually make sense to remove p3dci and rec709 displays from default configuration. Not sure how often such a displays are used by blender users. XYZ display could still be useful to help generating DCP. - Reshuffled views a bit. Added Default view to most of displays which is default sRGB transformation for sRGB display, ACES -> CIE XYZ for XYZ display. Should make things a bit clearer for understanding. --- release/datafiles/colormanagement/config.ocio | 220 +- .../colormanagement/luts/aces_to_xyz.spimtx | 3 + .../luts/adx_adx16_to_cdd.spimtx | 4 - .../colormanagement/luts/adx_cid_to_rle.py | 95 - .../luts/{xyz_dci.spi1d => dci_xyz.spi1d} | 0 .../datafiles/colormanagement/luts/logc800.py | 51 - .../colormanagement/luts/logc800.spi1d | 16390 -------- .../colormanagement/luts/logc_to_aces.spimtx | 4 - .../colormanagement/luts/rrt_ut33_p3d60.spi3d | 32771 ---------------- .../datafiles/colormanagement/luts/slog.py | 58 - .../datafiles/colormanagement/luts/slog.spi1d | 4102 -- .../colormanagement/luts/slog10.spi1d | 2054 - .../datafiles/colormanagement/luts/slog2.py | 62 - .../luts/slogf35_to_aces.spimtx | 4 - .../luts/slogf65_to_aces_3200.spimtx | 4 - .../luts/slogf65_to_aces_5500.spimtx | 4 - .../colormanagement/luts/ten_bit_scale.spimtx | 3 - 17 files changed, 55 insertions(+), 55774 deletions(-) create mode 100644 release/datafiles/colormanagement/luts/aces_to_xyz.spimtx delete mode 100644 release/datafiles/colormanagement/luts/adx_adx16_to_cdd.spimtx delete mode 100644 release/datafiles/colormanagement/luts/adx_cid_to_rle.py rename release/datafiles/colormanagement/luts/{xyz_dci.spi1d => dci_xyz.spi1d} (100%) delete mode 100644 release/datafiles/colormanagement/luts/logc800.py delete mode 100644 release/datafiles/colormanagement/luts/logc800.spi1d delete mode 100644 release/datafiles/colormanagement/luts/logc_to_aces.spimtx delete mode 100644 release/datafiles/colormanagement/luts/rrt_ut33_p3d60.spi3d delete mode 100644 release/datafiles/colormanagement/luts/slog.py delete mode 100644 release/datafiles/colormanagement/luts/slog.spi1d delete mode 100644 release/datafiles/colormanagement/luts/slog10.spi1d delete mode 100644 release/datafiles/colormanagement/luts/slog2.py delete mode 100644 release/datafiles/colormanagement/luts/slogf35_to_aces.spimtx delete mode 100644 release/datafiles/colormanagement/luts/slogf65_to_aces_3200.spimtx delete mode 100644 release/datafiles/colormanagement/luts/slogf65_to_aces_5500.spimtx delete mode 100644 release/datafiles/colormanagement/luts/ten_bit_scale.spimtx diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio index 1b714c09bf5..674c2adba0f 100644 --- a/release/datafiles/colormanagement/config.ocio +++ b/release/datafiles/colormanagement/config.ocio @@ -14,25 +14,28 @@ roles: sequencer: vd16 displays: - p3dci: - - ! {name: Raw, colorspace: raw} - - ! {name: Log, colorspace: adx10} - - ! {name: RRT, colorspace: rrt_p3dci} sRGB: - - ! {name: Gamma2.2, colorspace: sRGB} - - ! {name: Raw, colorspace: raw} + - ! {name: Default, colorspace: sRGB} - ! {name: RRT, colorspace: rrt_srgb} - ! {name: Film, colorspace: srgb8} + - ! {name: Raw, colorspace: raw} - ! {name: Log, colorspace: lg10} - - ! {name: rec709, colorspace: nuke_rec709} - xyz: + P3DCI: + - ! {name: RRT, colorspace: rrt_p3dci} - ! {name: Raw, colorspace: raw} - ! {name: Log, colorspace: adx10} + Rec709: + - ! {name: Default, colorspace: nuke_rec709} + - ! {name: RRT, colorspace: rrt_rec709} + XYZ: + - ! {name: Default, colorspace: xyz} - ! {name: RRT, colorspace: rrt_xyz} - - ! {name: DCI, colorspace: xyz_DCI} + - ! {name: DCI, colorspace: dci_xyz} + - ! {name: Raw, colorspace: raw} + - ! {name: Log, colorspace: adx10} -active_displays: [sRGB, p3dci, xyz] -active_views: [Gamma2.2, RRT, Log, Film, Log, Raw, rec709] +active_displays: [sRGB, P3DCI, Rec709, XYZ] +active_views: [Default, RRT, Raw, Log] colorspaces: - ! @@ -72,110 +75,10 @@ colorspaces: - ! {base: 10, direction: inverse} - ! {src: adx_exp_to_aces.spimtx} - - ! - name: adx16 - family: adx - equalitygroup: - bitdepth: 16ui - description: | - Film Scan, using the 16-bit Academy Density Encoding - - isdata: false - allocation: uniform - allocationvars: [0, 1] - to_reference: ! - children: - - ! {src: adx_adx16_to_cdd.spimtx} - - ! {src: adx_cdd_to_cid.spimtx} - - ! {src: adx_cid_to_rle.spi1d, interpolation: linear} - - ! {base: 10, direction: inverse} - - ! {src: adx_exp_to_aces.spimtx} - - - ! - name: slogf35 - family: sony - equalitygroup: - bitdepth: 10ui - description: | - Sony 10-bit S-Log, with f35 color primaries - - isdata: false - allocation: uniform - allocationvars: [0, 1] - to_reference: ! - children: - - ! {src: slog10.spi1d, interpolation: linear} - - ! {src: slogf35_to_aces.spimtx, interpolation: linear} - - - ! - name: slogf65_3200 - family: sony - equalitygroup: - bitdepth: 10ui - description: | - Sony 10-bit S-Log, with f65 color primaries - - isdata: false - allocation: uniform - allocationvars: [0, 1] - to_reference: ! - children: - - ! {src: slog10.spi1d, interpolation: linear} - - ! {src: slogf65_to_aces_3200.spimtx, interpolation: linear} - - - ! - name: slogf65_5500 - family: sony - equalitygroup: - bitdepth: 10ui - description: | - Sony 10-bit S-Log, with f65 color primaries - - isdata: false - allocation: uniform - allocationvars: [0, 1] - to_reference: ! - children: - - ! {src: slog10.spi1d, interpolation: linear} - - ! {src: slogf65_to_aces_5500.spimtx, interpolation: linear} - - - ! - name: logc - family: arri - equalitygroup: - bitdepth: 10ui - description: | - Arri Alexa LogC, V3, Exposure Index 800 - - isdata: false - allocation: uniform - allocationvars: [0, 1] - to_reference: ! - children: - - ! {src: logc800.spi1d, interpolation: linear} - - ! {src: logc_to_aces.spimtx} - - - ! - name: log - family: log - equalitygroup: - bitdepth: 32f - description: | - A mathematically idealized log space, which spans the dynamic range - currently being utilized by the ACES RRT. Note: this does not correspond - to scanned plates, adx10 is preferred for that purpose. - - isdata: false - allocation: uniform - allocationvars: [0, 1] - from_reference: ! - children: - - ! {allocation: lg2, vars: [-8.5, 5]} - - ! name: rec709 - family: "" - equalitygroup: "" + family: + equalitygroup: bitdepth: 32f description: | Rec. 709 (Full Range), Blender native internal space @@ -197,6 +100,21 @@ colorspaces: - ! {allocation: lg2, vars: [-8.5, 5]} - ! {src: rrt_ut33_sRGB.spi3d, interpolation: tetrahedral} + - ! + name: nuke_rec709 + family: + equalitygroup: + bitdepth: 32f + description: | + Rec. 709 (Full Range) Display Space + isdata: false + allocation: uniform + allocationvars: [-0.125, 1.125] + to_reference: ! + children: + - ! {src: rec709.spi1d, interpolation: linear} + - ! {src: rec709_to_aces.spimtx, interpolation: nearest} + - ! name: rrt_rec709 family: rrt @@ -224,8 +142,8 @@ colorspaces: - ! {src: rrt_ut33_p3dci.spi3d, interpolation: tetrahedral} - ! - name: rrt_p3d60 - family: rrt + name: xyz + family: equalitygroup: bitdepth: 32f isdata: false @@ -233,8 +151,7 @@ colorspaces: allocationvars: [0, 1] from_reference: ! children: - - ! {allocation: lg2, vars: [-8.5, 5]} - - ! {src: rrt_ut33_p3d60.spi3d, interpolation: tetrahedral} + - ! {src: aces_to_xyz.spimtx, interpolation: linear} - ! name: rrt_xyz @@ -249,7 +166,22 @@ colorspaces: - ! {allocation: lg2, vars: [-8.5, 5]} - ! {src: rrt_ut33_dcdm.spi3d, interpolation: tetrahedral} - # spi-vfx + - ! + name: dci_xyz + family: + equalitygroup: + bitdepth: 16f + description: | + OpenDCP output LUT with DCI reference white and Gamma 2.6 + isdata: false + allocation: uniform + allocationvars: [0, 1] + from_reference: ! + children: + - ! {src: rec709_to_aces.spimtx, interpolation: linear, direction: inverse} + - ! {src: srgb_to_xyz.spimtx, interpolation: linear} + - ! {src: dci_xyz.spi1d, interpolation: linear} + - ! name: lg10 family: lg @@ -278,26 +210,10 @@ colorspaces: - ! {src: aces, dst: lg10} - ! {src: spi_ocio_srgb_test.spi3d, interpolation: linear} - # nuke-default - - ! - name: nuke_rec709 - family: "" - equalitygroup: "" - bitdepth: 32f - description: | - Rec. 709 (Full Range) Display Space - isdata: false - allocation: uniform - allocationvars: [-0.125, 1.125] - to_reference: ! - children: - - ! {src: rec709.spi1d, interpolation: linear} - - ! {src: rec709_to_aces.spimtx, interpolation: nearest} - - ! name: sRGB - family: "" - equalitygroup: "" + family: + equalitygroup: bitdepth: 32f description: | Standard RGB Display Space @@ -322,35 +238,3 @@ colorspaces: children: - ! {src: vd16.spi1d, interpolation: nearest} - ! {src: rec709_to_aces.spimtx, interpolation: linear} - - - ! - name: Gamma2.2 - family: "" - equalitygroup: "" - bitdepth: 32f - description: | - Emulates a idealized Gamma 2.2 display device. - isdata: false - allocation: uniform - allocationvars: [0, 1] - to_reference: ! - children: - #- ! {src: rec709.spi1d, interpolation: linear} - - ! {value: [2.2, 2.2, 2.2, 1]} - - ! {src: rec709_to_aces.spimtx, interpolation: linear} - - - ! - name: xyz_DCI - family: "" - equalitygroup: "" - bitdepth: 16f - description: | - OpenDCP output LUT with DCI reference white and Gamma 2.6 - isdata: false - allocation: uniform - allocationvars: [0, 1] - from_reference: ! - children: - - ! {src: rec709_to_aces.spimtx, interpolation: linear, direction: inverse} - - ! {src: srgb_to_xyz.spimtx, interpolation: linear} - - ! {src: xyz_dci.spi1d, interpolation: linear} diff --git a/release/datafiles/colormanagement/luts/aces_to_xyz.spimtx b/release/datafiles/colormanagement/luts/aces_to_xyz.spimtx new file mode 100644 index 00000000000..fbf52e63555 --- /dev/null +++ b/release/datafiles/colormanagement/luts/aces_to_xyz.spimtx @@ -0,0 +1,3 @@ +0.9525523959 0.0000000000 0.0000936786 0 +0.3439664498 0.7281660966 -0.072132546 0 +0.0000000000 0.0000000000 1.0088251844 0 diff --git a/release/datafiles/colormanagement/luts/adx_adx16_to_cdd.spimtx b/release/datafiles/colormanagement/luts/adx_adx16_to_cdd.spimtx deleted file mode 100644 index 348eafa21ce..00000000000 --- a/release/datafiles/colormanagement/luts/adx_adx16_to_cdd.spimtx +++ /dev/null @@ -1,4 +0,0 @@ -8.191875 0.0 0.0 -12451.65 -0.0 8.191875 0.0 -12451.65 -0.0 0.0 8.191875 -12451.65 - diff --git a/release/datafiles/colormanagement/luts/adx_cid_to_rle.py b/release/datafiles/colormanagement/luts/adx_cid_to_rle.py deleted file mode 100644 index c226d4fd2de..00000000000 --- a/release/datafiles/colormanagement/luts/adx_cid_to_rle.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python - -import math, numpy - -""" - -const float REF_PT = (7120.0 - 1520.0) / 8000.0 * (100.0 / 55.0) - log10(0.18); - -const float LUT_1D[11][2] = { - {-0.190000000000000, -6.000000000000000}, - { 0.010000000000000, -2.721718645000000}, - { 0.028000000000000, -2.521718645000000}, - { 0.054000000000000, -2.321718645000000}, - { 0.095000000000000, -2.121718645000000}, - { 0.145000000000000, -1.921718645000000}, - { 0.220000000000000, -1.721718645000000}, - { 0.300000000000000, -1.521718645000000}, - { 0.400000000000000, -1.321718645000000}, - { 0.500000000000000, -1.121718645000000}, - { 0.600000000000000, -0.926545676714876} -}; - - // Convert Channel Independent Density values to Relative Log Exposure values - float logE[3]; - if ( cid[0] <= 0.6) logE[0] = interpolate1D( LUT_1D, cid[0]); - if ( cid[1] <= 0.6) logE[1] = interpolate1D( LUT_1D, cid[1]); - if ( cid[2] <= 0.6) logE[2] = interpolate1D( LUT_1D, cid[2]); - - if ( cid[0] > 0.6) logE[0] = ( 100.0 / 55.0) * cid[0] - REF_PT; - if ( cid[1] > 0.6) logE[1] = ( 100.0 / 55.0) * cid[1] - REF_PT; - if ( cid[2] > 0.6) logE[2] = ( 100.0 / 55.0) * cid[2] - REF_PT; -""" - - -def interpolate1D(x, xp, fp): - return numpy.interp(x, xp, fp) - -LUT_1D_xp = [-0.190000000000000, - 0.010000000000000, - 0.028000000000000, - 0.054000000000000, - 0.095000000000000, - 0.145000000000000, - 0.220000000000000, - 0.300000000000000, - 0.400000000000000, - 0.500000000000000, - 0.600000000000000] - -LUT_1D_fp = [-6.000000000000000, - -2.721718645000000, - -2.521718645000000, - -2.321718645000000, - -2.121718645000000, - -1.921718645000000, - -1.721718645000000, - -1.521718645000000, - -1.321718645000000, - -1.121718645000000, - -0.926545676714876] - -REF_PT = (7120.0 - 1520.0) / 8000.0 * (100.0 / 55.0) - math.log(0.18, 10.0) - -def cid_to_rle(x): - if x <= 0.6: - return interpolate1D(x, LUT_1D_xp, LUT_1D_fp) - return (100.0 / 55.0) * x - REF_PT - -def WriteSPI1D(filename, fromMin, fromMax, data): - f = file(filename,'w') - f.write("Version 1\n") - f.write("From %s %s\n" % (fromMin, fromMax)) - f.write("Length %d\n" % len(data)) - f.write("Components 1\n") - f.write("{\n") - for value in data: - f.write(" %s\n" % value) - f.write("}\n") - f.close() - -def Fit(value, fromMin, fromMax, toMin, toMax): - if fromMin == fromMax: - raise ValueError("fromMin == fromMax") - return (value - fromMin) / (fromMax - fromMin) * (toMax - toMin) + toMin - -NUM_SAMPLES = 2**12 -RANGE = (-0.19, 3.0) -data = [] -for i in xrange(NUM_SAMPLES): - x = i/(NUM_SAMPLES-1.0) - x = Fit(x, 0.0, 1.0, RANGE[0], RANGE[1]) - data.append(cid_to_rle(x)) - -WriteSPI1D('adx_cid_to_rle.spi1d', RANGE[0], RANGE[1], data) - diff --git a/release/datafiles/colormanagement/luts/xyz_dci.spi1d b/release/datafiles/colormanagement/luts/dci_xyz.spi1d similarity index 100% rename from release/datafiles/colormanagement/luts/xyz_dci.spi1d rename to release/datafiles/colormanagement/luts/dci_xyz.spi1d diff --git a/release/datafiles/colormanagement/luts/logc800.py b/release/datafiles/colormanagement/luts/logc800.py deleted file mode 100644 index fd5bf01662b..00000000000 --- a/release/datafiles/colormanagement/luts/logc800.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python - -import math - -""" - -// ARRI ALEXA IDT for ALEXA logC files -// with camera EI set to 800 -// Written by v3_IDT_maker.py v0.06 on Thursday 01 March 2012 by alex - -float -normalizedLogCToRelativeExposure(float x) { - if (x > 0.149659) - return (pow(10,(x - 0.385537) / 0.247189) - 0.052272) / 5.555556; - else - return (x - 0.092809) / 5.367650; -} - -""" - -def logCToLinear(x): - if (x > 0.149659): - return (math.pow(10.0,(x - 0.385537) / 0.247189) - 0.052272) / 5.555556 - else: - return (x - 0.092809) / 5.367650 - -def WriteSPI1D(filename, fromMin, fromMax, data): - f = file(filename,'w') - f.write("Version 1\n") - f.write("From %s %s\n" % (fromMin, fromMax)) - f.write("Length %d\n" % len(data)) - f.write("Components 1\n") - f.write("{\n") - for value in data: - f.write(" %s\n" % value) - f.write("}\n") - f.close() - -def Fit(value, fromMin, fromMax, toMin, toMax): - if fromMin == fromMax: - raise ValueError("fromMin == fromMax") - return (value - fromMin) / (fromMax - fromMin) * (toMax - toMin) + toMin - -NUM_SAMPLES = 2**14 -RANGE = (-0.125, 1.125) -data = [] -for i in xrange(NUM_SAMPLES): - x = i/(NUM_SAMPLES-1.0) - x = Fit(x, 0.0, 1.0, RANGE[0], RANGE[1]) - data.append(logCToLinear(x)) -WriteSPI1D('logc800.spi1d', RANGE[0], RANGE[1], data) diff --git a/release/datafiles/colormanagement/luts/logc800.spi1d b/release/datafiles/colormanagement/luts/logc800.spi1d deleted file mode 100644 index 6f2bf1e7069..00000000000 --- a/release/datafiles/colormanagement/luts/logc800.spi1d +++ /dev/null @@ -1,16390 +0,0 @@ -Version 1 -From -0.125 1.125 -Length 16384 -Components 1 -{ - -0.0405780928339 - -0.0405638783076 - -0.0405496637813 - -0.040535449255 - -0.0405212347286 - -0.0405070202023 - -0.040492805676 - -0.0404785911497 - -0.0404643766233 - -0.040450162097 - -0.0404359475707 - -0.0404217330444 - -0.0404075185181 - -0.0403933039917 - -0.0403790894654 - -0.0403648749391 - -0.0403506604128 - -0.0403364458865 - -0.0403222313601 - -0.0403080168338 - -0.0402938023075 - -0.0402795877812 - -0.0402653732548 - -0.0402511587285 - -0.0402369442022 - -0.0402227296759 - -0.0402085151496 - -0.0401943006232 - -0.0401800860969 - -0.0401658715706 - -0.0401516570443 - -0.040137442518 - -0.0401232279916 - -0.0401090134653 - -0.040094798939 - -0.0400805844127 - -0.0400663698863 - -0.04005215536 - -0.0400379408337 - -0.0400237263074 - -0.0400095117811 - -0.0399952972547 - -0.0399810827284 - -0.0399668682021 - -0.0399526536758 - -0.0399384391495 - -0.0399242246231 - -0.0399100100968 - -0.0398957955705 - -0.0398815810442 - -0.0398673665178 - -0.0398531519915 - -0.0398389374652 - -0.0398247229389 - -0.0398105084126 - -0.0397962938862 - -0.0397820793599 - -0.0397678648336 - -0.0397536503073 - -0.039739435781 - -0.0397252212546 - -0.0397110067283 - -0.039696792202 - -0.0396825776757 - -0.0396683631493 - -0.039654148623 - -0.0396399340967 - -0.0396257195704 - -0.0396115050441 - -0.0395972905177 - -0.0395830759914 - -0.0395688614651 - -0.0395546469388 - -0.0395404324125 - -0.0395262178861 - -0.0395120033598 - -0.0394977888335 - -0.0394835743072 - -0.0394693597808 - -0.0394551452545 - -0.0394409307282 - -0.0394267162019 - -0.0394125016756 - -0.0393982871492 - -0.0393840726229 - -0.0393698580966 - -0.0393556435703 - -0.039341429044 - -0.0393272145176 - -0.0393129999913 - -0.039298785465 - -0.0392845709387 - -0.0392703564123 - -0.039256141886 - -0.0392419273597 - -0.0392277128334 - -0.0392134983071 - -0.0391992837807 - -0.0391850692544 - -0.0391708547281 - -0.0391566402018 - -0.0391424256755 - -0.0391282111491 - -0.0391139966228 - -0.0390997820965 - -0.0390855675702 - -0.0390713530438 - -0.0390571385175 - -0.0390429239912 - -0.0390287094649 - -0.0390144949386 - -0.0390002804122 - -0.0389860658859 - -0.0389718513596 - -0.0389576368333 - -0.0389434223069 - -0.0389292077806 - -0.0389149932543 - -0.038900778728 - -0.0388865642017 - -0.0388723496753 - -0.038858135149 - -0.0388439206227 - -0.0388297060964 - -0.0388154915701 - -0.0388012770437 - -0.0387870625174 - -0.0387728479911 - -0.0387586334648 - -0.0387444189384 - -0.0387302044121 - -0.0387159898858 - -0.0387017753595 - -0.0386875608332 - -0.0386733463068 - -0.0386591317805 - -0.0386449172542 - -0.0386307027279 - -0.0386164882016 - -0.0386022736752 - -0.0385880591489 - -0.0385738446226 - -0.0385596300963 - -0.0385454155699 - -0.0385312010436 - -0.0385169865173 - -0.038502771991 - -0.0384885574647 - -0.0384743429383 - -0.038460128412 - -0.0384459138857 - -0.0384316993594 - -0.0384174848331 - -0.0384032703067 - -0.0383890557804 - -0.0383748412541 - -0.0383606267278 - -0.0383464122014 - -0.0383321976751 - -0.0383179831488 - -0.0383037686225 - -0.0382895540962 - -0.0382753395698 - -0.0382611250435 - -0.0382469105172 - -0.0382326959909 - -0.0382184814646 - -0.0382042669382 - -0.0381900524119 - -0.0381758378856 - -0.0381616233593 - -0.0381474088329 - -0.0381331943066 - -0.0381189797803 - -0.038104765254 - -0.0380905507277 - -0.0380763362013 - -0.038062121675 - -0.0380479071487 - -0.0380336926224 - -0.0380194780961 - -0.0380052635697 - -0.0379910490434 - -0.0379768345171 - -0.0379626199908 - -0.0379484054644 - -0.0379341909381 - -0.0379199764118 - -0.0379057618855 - -0.0378915473592 - -0.0378773328328 - -0.0378631183065 - -0.0378489037802 - -0.0378346892539 - -0.0378204747276 - -0.0378062602012 - -0.0377920456749 - -0.0377778311486 - -0.0377636166223 - -0.0377494020959 - -0.0377351875696 - -0.0377209730433 - -0.037706758517 - -0.0376925439907 - -0.0376783294643 - -0.037664114938 - -0.0376499004117 - -0.0376356858854 - -0.037621471359 - -0.0376072568327 - -0.0375930423064 - -0.0375788277801 - -0.0375646132538 - -0.0375503987274 - -0.0375361842011 - -0.0375219696748 - -0.0375077551485 - -0.0374935406222 - -0.0374793260958 - -0.0374651115695 - -0.0374508970432 - -0.0374366825169 - -0.0374224679905 - -0.0374082534642 - -0.0373940389379 - -0.0373798244116 - -0.0373656098853 - -0.0373513953589 - -0.0373371808326 - -0.0373229663063 - -0.03730875178 - -0.0372945372537 - -0.0372803227273 - -0.037266108201 - -0.0372518936747 - -0.0372376791484 - -0.037223464622 - -0.0372092500957 - -0.0371950355694 - -0.0371808210431 - -0.0371666065168 - -0.0371523919904 - -0.0371381774641 - -0.0371239629378 - -0.0371097484115 - -0.0370955338852 - -0.0370813193588 - -0.0370671048325 - -0.0370528903062 - -0.0370386757799 - -0.0370244612535 - -0.0370102467272 - -0.0369960322009 - -0.0369818176746 - -0.0369676031483 - -0.0369533886219 - -0.0369391740956 - -0.0369249595693 - -0.036910745043 - -0.0368965305167 - -0.0368823159903 - -0.036868101464 - -0.0368538869377 - -0.0368396724114 - -0.036825457885 - -0.0368112433587 - -0.0367970288324 - -0.0367828143061 - -0.0367685997798 - -0.0367543852534 - -0.0367401707271 - -0.0367259562008 - -0.0367117416745 - -0.0366975271482 - -0.0366833126218 - -0.0366690980955 - -0.0366548835692 - -0.0366406690429 - -0.0366264545165 - -0.0366122399902 - -0.0365980254639 - -0.0365838109376 - -0.0365695964113 - -0.0365553818849 - -0.0365411673586 - -0.0365269528323 - -0.036512738306 - -0.0364985237797 - -0.0364843092533 - -0.036470094727 - -0.0364558802007 - -0.0364416656744 - -0.036427451148 - -0.0364132366217 - -0.0363990220954 - -0.0363848075691 - -0.0363705930428 - -0.0363563785164 - -0.0363421639901 - -0.0363279494638 - -0.0363137349375 - -0.0362995204111 - -0.0362853058848 - -0.0362710913585 - -0.0362568768322 - -0.0362426623059 - -0.0362284477795 - -0.0362142332532 - -0.0362000187269 - -0.0361858042006 - -0.0361715896743 - -0.0361573751479 - -0.0361431606216 - -0.0361289460953 - -0.036114731569 - -0.0361005170426 - -0.0360863025163 - -0.03607208799 - -0.0360578734637 - -0.0360436589374 - -0.036029444411 - -0.0360152298847 - -0.0360010153584 - -0.0359868008321 - -0.0359725863058 - -0.0359583717794 - -0.0359441572531 - -0.0359299427268 - -0.0359157282005 - -0.0359015136741 - -0.0358872991478 - -0.0358730846215 - -0.0358588700952 - -0.0358446555689 - -0.0358304410425 - -0.0358162265162 - -0.0358020119899 - -0.0357877974636 - -0.0357735829373 - -0.0357593684109 - -0.0357451538846 - -0.0357309393583 - -0.035716724832 - -0.0357025103056 - -0.0356882957793 - -0.035674081253 - -0.0356598667267 - -0.0356456522004 - -0.035631437674 - -0.0356172231477 - -0.0356030086214 - -0.0355887940951 - -0.0355745795688 - -0.0355603650424 - -0.0355461505161 - -0.0355319359898 - -0.0355177214635 - -0.0355035069371 - -0.0354892924108 - -0.0354750778845 - -0.0354608633582 - -0.0354466488319 - -0.0354324343055 - -0.0354182197792 - -0.0354040052529 - -0.0353897907266 - -0.0353755762003 - -0.0353613616739 - -0.0353471471476 - -0.0353329326213 - -0.035318718095 - -0.0353045035686 - -0.0352902890423 - -0.035276074516 - -0.0352618599897 - -0.0352476454634 - -0.035233430937 - -0.0352192164107 - -0.0352050018844 - -0.0351907873581 - -0.0351765728318 - -0.0351623583054 - -0.0351481437791 - -0.0351339292528 - -0.0351197147265 - -0.0351055002001 - -0.0350912856738 - -0.0350770711475 - -0.0350628566212 - -0.0350486420949 - -0.0350344275685 - -0.0350202130422 - -0.0350059985159 - -0.0349917839896 - -0.0349775694633 - -0.0349633549369 - -0.0349491404106 - -0.0349349258843 - -0.034920711358 - -0.0349064968316 - -0.0348922823053 - -0.034878067779 - -0.0348638532527 - -0.0348496387264 - -0.0348354242 - -0.0348212096737 - -0.0348069951474 - -0.0347927806211 - -0.0347785660947 - -0.0347643515684 - -0.0347501370421 - -0.0347359225158 - -0.0347217079895 - -0.0347074934631 - -0.0346932789368 - -0.0346790644105 - -0.0346648498842 - -0.0346506353579 - -0.0346364208315 - -0.0346222063052 - -0.0346079917789 - -0.0345937772526 - -0.0345795627262 - -0.0345653481999 - -0.0345511336736 - -0.0345369191473 - -0.034522704621 - -0.0345084900946 - -0.0344942755683 - -0.034480061042 - -0.0344658465157 - -0.0344516319894 - -0.034437417463 - -0.0344232029367 - -0.0344089884104 - -0.0343947738841 - -0.0343805593577 - -0.0343663448314 - -0.0343521303051 - -0.0343379157788 - -0.0343237012525 - -0.0343094867261 - -0.0342952721998 - -0.0342810576735 - -0.0342668431472 - -0.0342526286209 - -0.0342384140945 - -0.0342241995682 - -0.0342099850419 - -0.0341957705156 - -0.0341815559892 - -0.0341673414629 - -0.0341531269366 - -0.0341389124103 - -0.034124697884 - -0.0341104833576 - -0.0340962688313 - -0.034082054305 - -0.0340678397787 - -0.0340536252524 - -0.034039410726 - -0.0340251961997 - -0.0340109816734 - -0.0339967671471 - -0.0339825526207 - -0.0339683380944 - -0.0339541235681 - -0.0339399090418 - -0.0339256945155 - -0.0339114799891 - -0.0338972654628 - -0.0338830509365 - -0.0338688364102 - -0.0338546218839 - -0.0338404073575 - -0.0338261928312 - -0.0338119783049 - -0.0337977637786 - -0.0337835492522 - -0.0337693347259 - -0.0337551201996 - -0.0337409056733 - -0.033726691147 - -0.0337124766206 - -0.0336982620943 - -0.033684047568 - -0.0336698330417 - -0.0336556185154 - -0.033641403989 - -0.0336271894627 - -0.0336129749364 - -0.0335987604101 - -0.0335845458837 - -0.0335703313574 - -0.0335561168311 - -0.0335419023048 - -0.0335276877785 - -0.0335134732521 - -0.0334992587258 - -0.0334850441995 - -0.0334708296732 - -0.0334566151468 - -0.0334424006205 - -0.0334281860942 - -0.0334139715679 - -0.0333997570416 - -0.0333855425152 - -0.0333713279889 - -0.0333571134626 - -0.0333428989363 - -0.03332868441 - -0.0333144698836 - -0.0333002553573 - -0.033286040831 - -0.0332718263047 - -0.0332576117783 - -0.033243397252 - -0.0332291827257 - -0.0332149681994 - -0.0332007536731 - -0.0331865391467 - -0.0331723246204 - -0.0331581100941 - -0.0331438955678 - -0.0331296810415 - -0.0331154665151 - -0.0331012519888 - -0.0330870374625 - -0.0330728229362 - -0.0330586084098 - -0.0330443938835 - -0.0330301793572 - -0.0330159648309 - -0.0330017503046 - -0.0329875357782 - -0.0329733212519 - -0.0329591067256 - -0.0329448921993 - -0.032930677673 - -0.0329164631466 - -0.0329022486203 - -0.032888034094 - -0.0328738195677 - -0.0328596050413 - -0.032845390515 - -0.0328311759887 - -0.0328169614624 - -0.0328027469361 - -0.0327885324097 - -0.0327743178834 - -0.0327601033571 - -0.0327458888308 - -0.0327316743045 - -0.0327174597781 - -0.0327032452518 - -0.0326890307255 - -0.0326748161992 - -0.0326606016728 - -0.0326463871465 - -0.0326321726202 - -0.0326179580939 - -0.0326037435676 - -0.0325895290412 - -0.0325753145149 - -0.0325610999886 - -0.0325468854623 - -0.032532670936 - -0.0325184564096 - -0.0325042418833 - -0.032490027357 - -0.0324758128307 - -0.0324615983043 - -0.032447383778 - -0.0324331692517 - -0.0324189547254 - -0.0324047401991 - -0.0323905256727 - -0.0323763111464 - -0.0323620966201 - -0.0323478820938 - -0.0323336675675 - -0.0323194530411 - -0.0323052385148 - -0.0322910239885 - -0.0322768094622 - -0.0322625949358 - -0.0322483804095 - -0.0322341658832 - -0.0322199513569 - -0.0322057368306 - -0.0321915223042 - -0.0321773077779 - -0.0321630932516 - -0.0321488787253 - -0.0321346641989 - -0.0321204496726 - -0.0321062351463 - -0.03209202062 - -0.0320778060937 - -0.0320635915673 - -0.032049377041 - -0.0320351625147 - -0.0320209479884 - -0.0320067334621 - -0.0319925189357 - -0.0319783044094 - -0.0319640898831 - -0.0319498753568 - -0.0319356608304 - -0.0319214463041 - -0.0319072317778 - -0.0318930172515 - -0.0318788027252 - -0.0318645881988 - -0.0318503736725 - -0.0318361591462 - -0.0318219446199 - -0.0318077300936 - -0.0317935155672 - -0.0317793010409 - -0.0317650865146 - -0.0317508719883 - -0.0317366574619 - -0.0317224429356 - -0.0317082284093 - -0.031694013883 - -0.0316797993567 - -0.0316655848303 - -0.031651370304 - -0.0316371557777 - -0.0316229412514 - -0.0316087267251 - -0.0315945121987 - -0.0315802976724 - -0.0315660831461 - -0.0315518686198 - -0.0315376540934 - -0.0315234395671 - -0.0315092250408 - -0.0314950105145 - -0.0314807959882 - -0.0314665814618 - -0.0314523669355 - -0.0314381524092 - -0.0314239378829 - -0.0314097233566 - -0.0313955088302 - -0.0313812943039 - -0.0313670797776 - -0.0313528652513 - -0.0313386507249 - -0.0313244361986 - -0.0313102216723 - -0.031296007146 - -0.0312817926197 - -0.0312675780933 - -0.031253363567 - -0.0312391490407 - -0.0312249345144 - -0.0312107199881 - -0.0311965054617 - -0.0311822909354 - -0.0311680764091 - -0.0311538618828 - -0.0311396473564 - -0.0311254328301 - -0.0311112183038 - -0.0310970037775 - -0.0310827892512 - -0.0310685747248 - -0.0310543601985 - -0.0310401456722 - -0.0310259311459 - -0.0310117166196 - -0.0309975020932 - -0.0309832875669 - -0.0309690730406 - -0.0309548585143 - -0.0309406439879 - -0.0309264294616 - -0.0309122149353 - -0.030898000409 - -0.0308837858827 - -0.0308695713563 - -0.03085535683 - -0.0308411423037 - -0.0308269277774 - -0.0308127132511 - -0.0307984987247 - -0.0307842841984 - -0.0307700696721 - -0.0307558551458 - -0.0307416406194 - -0.0307274260931 - -0.0307132115668 - -0.0306989970405 - -0.0306847825142 - -0.0306705679878 - -0.0306563534615 - -0.0306421389352 - -0.0306279244089 - -0.0306137098825 - -0.0305994953562 - -0.0305852808299 - -0.0305710663036 - -0.0305568517773 - -0.0305426372509 - -0.0305284227246 - -0.0305142081983 - -0.030499993672 - -0.0304857791457 - -0.0304715646193 - -0.030457350093 - -0.0304431355667 - -0.0304289210404 - -0.030414706514 - -0.0304004919877 - -0.0303862774614 - -0.0303720629351 - -0.0303578484088 - -0.0303436338824 - -0.0303294193561 - -0.0303152048298 - -0.0303009903035 - -0.0302867757772 - -0.0302725612508 - -0.0302583467245 - -0.0302441321982 - -0.0302299176719 - -0.0302157031455 - -0.0302014886192 - -0.0301872740929 - -0.0301730595666 - -0.0301588450403 - -0.0301446305139 - -0.0301304159876 - -0.0301162014613 - -0.030101986935 - -0.0300877724087 - -0.0300735578823 - -0.030059343356 - -0.0300451288297 - -0.0300309143034 - -0.030016699777 - -0.0300024852507 - -0.0299882707244 - -0.0299740561981 - -0.0299598416718 - -0.0299456271454 - -0.0299314126191 - -0.0299171980928 - -0.0299029835665 - -0.0298887690402 - -0.0298745545138 - -0.0298603399875 - -0.0298461254612 - -0.0298319109349 - -0.0298176964085 - -0.0298034818822 - -0.0297892673559 - -0.0297750528296 - -0.0297608383033 - -0.0297466237769 - -0.0297324092506 - -0.0297181947243 - -0.029703980198 - -0.0296897656717 - -0.0296755511453 - -0.029661336619 - -0.0296471220927 - -0.0296329075664 - -0.02961869304 - -0.0296044785137 - -0.0295902639874 - -0.0295760494611 - -0.0295618349348 - -0.0295476204084 - -0.0295334058821 - -0.0295191913558 - -0.0295049768295 - -0.0294907623032 - -0.0294765477768 - -0.0294623332505 - -0.0294481187242 - -0.0294339041979 - -0.0294196896715 - -0.0294054751452 - -0.0293912606189 - -0.0293770460926 - -0.0293628315663 - -0.0293486170399 - -0.0293344025136 - -0.0293201879873 - -0.029305973461 - -0.0292917589346 - -0.0292775444083 - -0.029263329882 - -0.0292491153557 - -0.0292349008294 - -0.029220686303 - -0.0292064717767 - -0.0291922572504 - -0.0291780427241 - -0.0291638281978 - -0.0291496136714 - -0.0291353991451 - -0.0291211846188 - -0.0291069700925 - -0.0290927555661 - -0.0290785410398 - -0.0290643265135 - -0.0290501119872 - -0.0290358974609 - -0.0290216829345 - -0.0290074684082 - -0.0289932538819 - -0.0289790393556 - -0.0289648248293 - -0.0289506103029 - -0.0289363957766 - -0.0289221812503 - -0.028907966724 - -0.0288937521976 - -0.0288795376713 - -0.028865323145 - -0.0288511086187 - -0.0288368940924 - -0.028822679566 - -0.0288084650397 - -0.0287942505134 - -0.0287800359871 - -0.0287658214608 - -0.0287516069344 - -0.0287373924081 - -0.0287231778818 - -0.0287089633555 - -0.0286947488291 - -0.0286805343028 - -0.0286663197765 - -0.0286521052502 - -0.0286378907239 - -0.0286236761975 - -0.0286094616712 - -0.0285952471449 - -0.0285810326186 - -0.0285668180923 - -0.0285526035659 - -0.0285383890396 - -0.0285241745133 - -0.028509959987 - -0.0284957454606 - -0.0284815309343 - -0.028467316408 - -0.0284531018817 - -0.0284388873554 - -0.028424672829 - -0.0284104583027 - -0.0283962437764 - -0.0283820292501 - -0.0283678147238 - -0.0283536001974 - -0.0283393856711 - -0.0283251711448 - -0.0283109566185 - -0.0282967420921 - -0.0282825275658 - -0.0282683130395 - -0.0282540985132 - -0.0282398839869 - -0.0282256694605 - -0.0282114549342 - -0.0281972404079 - -0.0281830258816 - -0.0281688113553 - -0.0281545968289 - -0.0281403823026 - -0.0281261677763 - -0.02811195325 - -0.0280977387236 - -0.0280835241973 - -0.028069309671 - -0.0280550951447 - -0.0280408806184 - -0.028026666092 - -0.0280124515657 - -0.0279982370394 - -0.0279840225131 - -0.0279698079867 - -0.0279555934604 - -0.0279413789341 - -0.0279271644078 - -0.0279129498815 - -0.0278987353551 - -0.0278845208288 - -0.0278703063025 - -0.0278560917762 - -0.0278418772499 - -0.0278276627235 - -0.0278134481972 - -0.0277992336709 - -0.0277850191446 - -0.0277708046182 - -0.0277565900919 - -0.0277423755656 - -0.0277281610393 - -0.027713946513 - -0.0276997319866 - -0.0276855174603 - -0.027671302934 - -0.0276570884077 - -0.0276428738814 - -0.027628659355 - -0.0276144448287 - -0.0276002303024 - -0.0275860157761 - -0.0275718012497 - -0.0275575867234 - -0.0275433721971 - -0.0275291576708 - -0.0275149431445 - -0.0275007286181 - -0.0274865140918 - -0.0274722995655 - -0.0274580850392 - -0.0274438705129 - -0.0274296559865 - -0.0274154414602 - -0.0274012269339 - -0.0273870124076 - -0.0273727978812 - -0.0273585833549 - -0.0273443688286 - -0.0273301543023 - -0.027315939776 - -0.0273017252496 - -0.0272875107233 - -0.027273296197 - -0.0272590816707 - -0.0272448671444 - -0.027230652618 - -0.0272164380917 - -0.0272022235654 - -0.0271880090391 - -0.0271737945127 - -0.0271595799864 - -0.0271453654601 - -0.0271311509338 - -0.0271169364075 - -0.0271027218811 - -0.0270885073548 - -0.0270742928285 - -0.0270600783022 - -0.0270458637759 - -0.0270316492495 - -0.0270174347232 - -0.0270032201969 - -0.0269890056706 - -0.0269747911442 - -0.0269605766179 - -0.0269463620916 - -0.0269321475653 - -0.026917933039 - -0.0269037185126 - -0.0268895039863 - -0.02687528946 - -0.0268610749337 - -0.0268468604074 - -0.026832645881 - -0.0268184313547 - -0.0268042168284 - -0.0267900023021 - -0.0267757877757 - -0.0267615732494 - -0.0267473587231 - -0.0267331441968 - -0.0267189296705 - -0.0267047151441 - -0.0266905006178 - -0.0266762860915 - -0.0266620715652 - -0.0266478570389 - -0.0266336425125 - -0.0266194279862 - -0.0266052134599 - -0.0265909989336 - -0.0265767844072 - -0.0265625698809 - -0.0265483553546 - -0.0265341408283 - -0.026519926302 - -0.0265057117756 - -0.0264914972493 - -0.026477282723 - -0.0264630681967 - -0.0264488536703 - -0.026434639144 - -0.0264204246177 - -0.0264062100914 - -0.0263919955651 - -0.0263777810387 - -0.0263635665124 - -0.0263493519861 - -0.0263351374598 - -0.0263209229335 - -0.0263067084071 - -0.0262924938808 - -0.0262782793545 - -0.0262640648282 - -0.0262498503018 - -0.0262356357755 - -0.0262214212492 - -0.0262072067229 - -0.0261929921966 - -0.0261787776702 - -0.0261645631439 - -0.0261503486176 - -0.0261361340913 - -0.026121919565 - -0.0261077050386 - -0.0260934905123 - -0.026079275986 - -0.0260650614597 - -0.0260508469333 - -0.026036632407 - -0.0260224178807 - -0.0260082033544 - -0.0259939888281 - -0.0259797743017 - -0.0259655597754 - -0.0259513452491 - -0.0259371307228 - -0.0259229161965 - -0.0259087016701 - -0.0258944871438 - -0.0258802726175 - -0.0258660580912 - -0.0258518435648 - -0.0258376290385 - -0.0258234145122 - -0.0258091999859 - -0.0257949854596 - -0.0257807709332 - -0.0257665564069 - -0.0257523418806 - -0.0257381273543 - -0.025723912828 - -0.0257096983016 - -0.0256954837753 - -0.025681269249 - -0.0256670547227 - -0.0256528401963 - -0.02563862567 - -0.0256244111437 - -0.0256101966174 - -0.0255959820911 - -0.0255817675647 - -0.0255675530384 - -0.0255533385121 - -0.0255391239858 - -0.0255249094595 - -0.0255106949331 - -0.0254964804068 - -0.0254822658805 - -0.0254680513542 - -0.0254538368278 - -0.0254396223015 - -0.0254254077752 - -0.0254111932489 - -0.0253969787226 - -0.0253827641962 - -0.0253685496699 - -0.0253543351436 - -0.0253401206173 - -0.025325906091 - -0.0253116915646 - -0.0252974770383 - -0.025283262512 - -0.0252690479857 - -0.0252548334593 - -0.025240618933 - -0.0252264044067 - -0.0252121898804 - -0.0251979753541 - -0.0251837608277 - -0.0251695463014 - -0.0251553317751 - -0.0251411172488 - -0.0251269027224 - -0.0251126881961 - -0.0250984736698 - -0.0250842591435 - -0.0250700446172 - -0.0250558300908 - -0.0250416155645 - -0.0250274010382 - -0.0250131865119 - -0.0249989719856 - -0.0249847574592 - -0.0249705429329 - -0.0249563284066 - -0.0249421138803 - -0.0249278993539 - -0.0249136848276 - -0.0248994703013 - -0.024885255775 - -0.0248710412487 - -0.0248568267223 - -0.024842612196 - -0.0248283976697 - -0.0248141831434 - -0.0247999686171 - -0.0247857540907 - -0.0247715395644 - -0.0247573250381 - -0.0247431105118 - -0.0247288959854 - -0.0247146814591 - -0.0247004669328 - -0.0246862524065 - -0.0246720378802 - -0.0246578233538 - -0.0246436088275 - -0.0246293943012 - -0.0246151797749 - -0.0246009652486 - -0.0245867507222 - -0.0245725361959 - -0.0245583216696 - -0.0245441071433 - -0.0245298926169 - -0.0245156780906 - -0.0245014635643 - -0.024487249038 - -0.0244730345117 - -0.0244588199853 - -0.024444605459 - -0.0244303909327 - -0.0244161764064 - -0.0244019618801 - -0.0243877473537 - -0.0243735328274 - -0.0243593183011 - -0.0243451037748 - -0.0243308892484 - -0.0243166747221 - -0.0243024601958 - -0.0242882456695 - -0.0242740311432 - -0.0242598166168 - -0.0242456020905 - -0.0242313875642 - -0.0242171730379 - -0.0242029585116 - -0.0241887439852 - -0.0241745294589 - -0.0241603149326 - -0.0241461004063 - -0.0241318858799 - -0.0241176713536 - -0.0241034568273 - -0.024089242301 - -0.0240750277747 - -0.0240608132483 - -0.024046598722 - -0.0240323841957 - -0.0240181696694 - -0.0240039551431 - -0.0239897406167 - -0.0239755260904 - -0.0239613115641 - -0.0239470970378 - -0.0239328825114 - -0.0239186679851 - -0.0239044534588 - -0.0238902389325 - -0.0238760244062 - -0.0238618098798 - -0.0238475953535 - -0.0238333808272 - -0.0238191663009 - -0.0238049517745 - -0.0237907372482 - -0.0237765227219 - -0.0237623081956 - -0.0237480936693 - -0.0237338791429 - -0.0237196646166 - -0.0237054500903 - -0.023691235564 - -0.0236770210377 - -0.0236628065113 - -0.023648591985 - -0.0236343774587 - -0.0236201629324 - -0.023605948406 - -0.0235917338797 - -0.0235775193534 - -0.0235633048271 - -0.0235490903008 - -0.0235348757744 - -0.0235206612481 - -0.0235064467218 - -0.0234922321955 - -0.0234780176692 - -0.0234638031428 - -0.0234495886165 - -0.0234353740902 - -0.0234211595639 - -0.0234069450375 - -0.0233927305112 - -0.0233785159849 - -0.0233643014586 - -0.0233500869323 - -0.0233358724059 - -0.0233216578796 - -0.0233074433533 - -0.023293228827 - -0.0232790143007 - -0.0232647997743 - -0.023250585248 - -0.0232363707217 - -0.0232221561954 - -0.023207941669 - -0.0231937271427 - -0.0231795126164 - -0.0231652980901 - -0.0231510835638 - -0.0231368690374 - -0.0231226545111 - -0.0231084399848 - -0.0230942254585 - -0.0230800109322 - -0.0230657964058 - -0.0230515818795 - -0.0230373673532 - -0.0230231528269 - -0.0230089383005 - -0.0229947237742 - -0.0229805092479 - -0.0229662947216 - -0.0229520801953 - -0.0229378656689 - -0.0229236511426 - -0.0229094366163 - -0.02289522209 - -0.0228810075637 - -0.0228667930373 - -0.022852578511 - -0.0228383639847 - -0.0228241494584 - -0.022809934932 - -0.0227957204057 - -0.0227815058794 - -0.0227672913531 - -0.0227530768268 - -0.0227388623004 - -0.0227246477741 - -0.0227104332478 - -0.0226962187215 - -0.0226820041952 - -0.0226677896688 - -0.0226535751425 - -0.0226393606162 - -0.0226251460899 - -0.0226109315635 - -0.0225967170372 - -0.0225825025109 - -0.0225682879846 - -0.0225540734583 - -0.0225398589319 - -0.0225256444056 - -0.0225114298793 - -0.022497215353 - -0.0224830008267 - -0.0224687863003 - -0.022454571774 - -0.0224403572477 - -0.0224261427214 - -0.022411928195 - -0.0223977136687 - -0.0223834991424 - -0.0223692846161 - -0.0223550700898 - -0.0223408555634 - -0.0223266410371 - -0.0223124265108 - -0.0222982119845 - -0.0222839974581 - -0.0222697829318 - -0.0222555684055 - -0.0222413538792 - -0.0222271393529 - -0.0222129248265 - -0.0221987103002 - -0.0221844957739 - -0.0221702812476 - -0.0221560667213 - -0.0221418521949 - -0.0221276376686 - -0.0221134231423 - -0.022099208616 - -0.0220849940896 - -0.0220707795633 - -0.022056565037 - -0.0220423505107 - -0.0220281359844 - -0.022013921458 - -0.0219997069317 - -0.0219854924054 - -0.0219712778791 - -0.0219570633528 - -0.0219428488264 - -0.0219286343001 - -0.0219144197738 - -0.0219002052475 - -0.0218859907211 - -0.0218717761948 - -0.0218575616685 - -0.0218433471422 - -0.0218291326159 - -0.0218149180895 - -0.0218007035632 - -0.0217864890369 - -0.0217722745106 - -0.0217580599843 - -0.0217438454579 - -0.0217296309316 - -0.0217154164053 - -0.021701201879 - -0.0216869873526 - -0.0216727728263 - -0.0216585583 - -0.0216443437737 - -0.0216301292474 - -0.021615914721 - -0.0216017001947 - -0.0215874856684 - -0.0215732711421 - -0.0215590566158 - -0.0215448420894 - -0.0215306275631 - -0.0215164130368 - -0.0215021985105 - -0.0214879839841 - -0.0214737694578 - -0.0214595549315 - -0.0214453404052 - -0.0214311258789 - -0.0214169113525 - -0.0214026968262 - -0.0213884822999 - -0.0213742677736 - -0.0213600532473 - -0.0213458387209 - -0.0213316241946 - -0.0213174096683 - -0.021303195142 - -0.0212889806156 - -0.0212747660893 - -0.021260551563 - -0.0212463370367 - -0.0212321225104 - -0.021217907984 - -0.0212036934577 - -0.0211894789314 - -0.0211752644051 - -0.0211610498788 - -0.0211468353524 - -0.0211326208261 - -0.0211184062998 - -0.0211041917735 - -0.0210899772471 - -0.0210757627208 - -0.0210615481945 - -0.0210473336682 - -0.0210331191419 - -0.0210189046155 - -0.0210046900892 - -0.0209904755629 - -0.0209762610366 - -0.0209620465102 - -0.0209478319839 - -0.0209336174576 - -0.0209194029313 - -0.020905188405 - -0.0208909738786 - -0.0208767593523 - -0.020862544826 - -0.0208483302997 - -0.0208341157734 - -0.020819901247 - -0.0208056867207 - -0.0207914721944 - -0.0207772576681 - -0.0207630431417 - -0.0207488286154 - -0.0207346140891 - -0.0207203995628 - -0.0207061850365 - -0.0206919705101 - -0.0206777559838 - -0.0206635414575 - -0.0206493269312 - -0.0206351124049 - -0.0206208978785 - -0.0206066833522 - -0.0205924688259 - -0.0205782542996 - -0.0205640397732 - -0.0205498252469 - -0.0205356107206 - -0.0205213961943 - -0.020507181668 - -0.0204929671416 - -0.0204787526153 - -0.020464538089 - -0.0204503235627 - -0.0204361090364 - -0.02042189451 - -0.0204076799837 - -0.0203934654574 - -0.0203792509311 - -0.0203650364047 - -0.0203508218784 - -0.0203366073521 - -0.0203223928258 - -0.0203081782995 - -0.0202939637731 - -0.0202797492468 - -0.0202655347205 - -0.0202513201942 - -0.0202371056679 - -0.0202228911415 - -0.0202086766152 - -0.0201944620889 - -0.0201802475626 - -0.0201660330362 - -0.0201518185099 - -0.0201376039836 - -0.0201233894573 - -0.020109174931 - -0.0200949604046 - -0.0200807458783 - -0.020066531352 - -0.0200523168257 - -0.0200381022994 - -0.020023887773 - -0.0200096732467 - -0.0199954587204 - -0.0199812441941 - -0.0199670296677 - -0.0199528151414 - -0.0199386006151 - -0.0199243860888 - -0.0199101715625 - -0.0198959570361 - -0.0198817425098 - -0.0198675279835 - -0.0198533134572 - -0.0198390989309 - -0.0198248844045 - -0.0198106698782 - -0.0197964553519 - -0.0197822408256 - -0.0197680262992 - -0.0197538117729 - -0.0197395972466 - -0.0197253827203 - -0.019711168194 - -0.0196969536676 - -0.0196827391413 - -0.019668524615 - -0.0196543100887 - -0.0196400955624 - -0.019625881036 - -0.0196116665097 - -0.0195974519834 - -0.0195832374571 - -0.0195690229307 - -0.0195548084044 - -0.0195405938781 - -0.0195263793518 - -0.0195121648255 - -0.0194979502991 - -0.0194837357728 - -0.0194695212465 - -0.0194553067202 - -0.0194410921938 - -0.0194268776675 - -0.0194126631412 - -0.0193984486149 - -0.0193842340886 - -0.0193700195622 - -0.0193558050359 - -0.0193415905096 - -0.0193273759833 - -0.019313161457 - -0.0192989469306 - -0.0192847324043 - -0.019270517878 - -0.0192563033517 - -0.0192420888253 - -0.019227874299 - -0.0192136597727 - -0.0191994452464 - -0.0191852307201 - -0.0191710161937 - -0.0191568016674 - -0.0191425871411 - -0.0191283726148 - -0.0191141580885 - -0.0190999435621 - -0.0190857290358 - -0.0190715145095 - -0.0190572999832 - -0.0190430854568 - -0.0190288709305 - -0.0190146564042 - -0.0190004418779 - -0.0189862273516 - -0.0189720128252 - -0.0189577982989 - -0.0189435837726 - -0.0189293692463 - -0.01891515472 - -0.0189009401936 - -0.0188867256673 - -0.018872511141 - -0.0188582966147 - -0.0188440820883 - -0.018829867562 - -0.0188156530357 - -0.0188014385094 - -0.0187872239831 - -0.0187730094567 - -0.0187587949304 - -0.0187445804041 - -0.0187303658778 - -0.0187161513515 - -0.0187019368251 - -0.0186877222988 - -0.0186735077725 - -0.0186592932462 - -0.0186450787198 - -0.0186308641935 - -0.0186166496672 - -0.0186024351409 - -0.0185882206146 - -0.0185740060882 - -0.0185597915619 - -0.0185455770356 - -0.0185313625093 - -0.018517147983 - -0.0185029334566 - -0.0184887189303 - -0.018474504404 - -0.0184602898777 - -0.0184460753513 - -0.018431860825 - -0.0184176462987 - -0.0184034317724 - -0.0183892172461 - -0.0183750027197 - -0.0183607881934 - -0.0183465736671 - -0.0183323591408 - -0.0183181446145 - -0.0183039300881 - -0.0182897155618 - -0.0182755010355 - -0.0182612865092 - -0.0182470719828 - -0.0182328574565 - -0.0182186429302 - -0.0182044284039 - -0.0181902138776 - -0.0181759993512 - -0.0181617848249 - -0.0181475702986 - -0.0181333557723 - -0.0181191412459 - -0.0181049267196 - -0.0180907121933 - -0.018076497667 - -0.0180622831407 - -0.0180480686143 - -0.018033854088 - -0.0180196395617 - -0.0180054250354 - -0.0179912105091 - -0.0179769959827 - -0.0179627814564 - -0.0179485669301 - -0.0179343524038 - -0.0179201378774 - -0.0179059233511 - -0.0178917088248 - -0.0178774942985 - -0.0178632797722 - -0.0178490652458 - -0.0178348507195 - -0.0178206361932 - -0.0178064216669 - -0.0177922071406 - -0.0177779926142 - -0.0177637780879 - -0.0177495635616 - -0.0177353490353 - -0.0177211345089 - -0.0177069199826 - -0.0176927054563 - -0.01767849093 - -0.0176642764037 - -0.0176500618773 - -0.017635847351 - -0.0176216328247 - -0.0176074182984 - -0.0175932037721 - -0.0175789892457 - -0.0175647747194 - -0.0175505601931 - -0.0175363456668 - -0.0175221311404 - -0.0175079166141 - -0.0174937020878 - -0.0174794875615 - -0.0174652730352 - -0.0174510585088 - -0.0174368439825 - -0.0174226294562 - -0.0174084149299 - -0.0173942004036 - -0.0173799858772 - -0.0173657713509 - -0.0173515568246 - -0.0173373422983 - -0.0173231277719 - -0.0173089132456 - -0.0172946987193 - -0.017280484193 - -0.0172662696667 - -0.0172520551403 - -0.017237840614 - -0.0172236260877 - -0.0172094115614 - -0.0171951970351 - -0.0171809825087 - -0.0171667679824 - -0.0171525534561 - -0.0171383389298 - -0.0171241244034 - -0.0171099098771 - -0.0170956953508 - -0.0170814808245 - -0.0170672662982 - -0.0170530517718 - -0.0170388372455 - -0.0170246227192 - -0.0170104081929 - -0.0169961936666 - -0.0169819791402 - -0.0169677646139 - -0.0169535500876 - -0.0169393355613 - -0.0169251210349 - -0.0169109065086 - -0.0168966919823 - -0.016882477456 - -0.0168682629297 - -0.0168540484033 - -0.016839833877 - -0.0168256193507 - -0.0168114048244 - -0.016797190298 - -0.0167829757717 - -0.0167687612454 - -0.0167545467191 - -0.0167403321928 - -0.0167261176664 - -0.0167119031401 - -0.0166976886138 - -0.0166834740875 - -0.0166692595612 - -0.0166550450348 - -0.0166408305085 - -0.0166266159822 - -0.0166124014559 - -0.0165981869295 - -0.0165839724032 - -0.0165697578769 - -0.0165555433506 - -0.0165413288243 - -0.0165271142979 - -0.0165128997716 - -0.0164986852453 - -0.016484470719 - -0.0164702561927 - -0.0164560416663 - -0.01644182714 - -0.0164276126137 - -0.0164133980874 - -0.016399183561 - -0.0163849690347 - -0.0163707545084 - -0.0163565399821 - -0.0163423254558 - -0.0163281109294 - -0.0163138964031 - -0.0162996818768 - -0.0162854673505 - -0.0162712528242 - -0.0162570382978 - -0.0162428237715 - -0.0162286092452 - -0.0162143947189 - -0.0162001801925 - -0.0161859656662 - -0.0161717511399 - -0.0161575366136 - -0.0161433220873 - -0.0161291075609 - -0.0161148930346 - -0.0161006785083 - -0.016086463982 - -0.0160722494557 - -0.0160580349293 - -0.016043820403 - -0.0160296058767 - -0.0160153913504 - -0.016001176824 - -0.0159869622977 - -0.0159727477714 - -0.0159585332451 - -0.0159443187188 - -0.0159301041924 - -0.0159158896661 - -0.0159016751398 - -0.0158874606135 - -0.0158732460872 - -0.0158590315608 - -0.0158448170345 - -0.0158306025082 - -0.0158163879819 - -0.0158021734555 - -0.0157879589292 - -0.0157737444029 - -0.0157595298766 - -0.0157453153503 - -0.0157311008239 - -0.0157168862976 - -0.0157026717713 - -0.015688457245 - -0.0156742427187 - -0.0156600281923 - -0.015645813666 - -0.0156315991397 - -0.0156173846134 - -0.015603170087 - -0.0155889555607 - -0.0155747410344 - -0.0155605265081 - -0.0155463119818 - -0.0155320974554 - -0.0155178829291 - -0.0155036684028 - -0.0154894538765 - -0.0154752393502 - -0.0154610248238 - -0.0154468102975 - -0.0154325957712 - -0.0154183812449 - -0.0154041667185 - -0.0153899521922 - -0.0153757376659 - -0.0153615231396 - -0.0153473086133 - -0.0153330940869 - -0.0153188795606 - -0.0153046650343 - -0.015290450508 - -0.0152762359816 - -0.0152620214553 - -0.015247806929 - -0.0152335924027 - -0.0152193778764 - -0.01520516335 - -0.0151909488237 - -0.0151767342974 - -0.0151625197711 - -0.0151483052448 - -0.0151340907184 - -0.0151198761921 - -0.0151056616658 - -0.0150914471395 - -0.0150772326131 - -0.0150630180868 - -0.0150488035605 - -0.0150345890342 - -0.0150203745079 - -0.0150061599815 - -0.0149919454552 - -0.0149777309289 - -0.0149635164026 - -0.0149493018763 - -0.0149350873499 - -0.0149208728236 - -0.0149066582973 - -0.014892443771 - -0.0148782292446 - -0.0148640147183 - -0.014849800192 - -0.0148355856657 - -0.0148213711394 - -0.014807156613 - -0.0147929420867 - -0.0147787275604 - -0.0147645130341 - -0.0147502985078 - -0.0147360839814 - -0.0147218694551 - -0.0147076549288 - -0.0146934404025 - -0.0146792258761 - -0.0146650113498 - -0.0146507968235 - -0.0146365822972 - -0.0146223677709 - -0.0146081532445 - -0.0145939387182 - -0.0145797241919 - -0.0145655096656 - -0.0145512951393 - -0.0145370806129 - -0.0145228660866 - -0.0145086515603 - -0.014494437034 - -0.0144802225076 - -0.0144660079813 - -0.014451793455 - -0.0144375789287 - -0.0144233644024 - -0.014409149876 - -0.0143949353497 - -0.0143807208234 - -0.0143665062971 - -0.0143522917708 - -0.0143380772444 - -0.0143238627181 - -0.0143096481918 - -0.0142954336655 - -0.0142812191391 - -0.0142670046128 - -0.0142527900865 - -0.0142385755602 - -0.0142243610339 - -0.0142101465075 - -0.0141959319812 - -0.0141817174549 - -0.0141675029286 - -0.0141532884023 - -0.0141390738759 - -0.0141248593496 - -0.0141106448233 - -0.014096430297 - -0.0140822157706 - -0.0140680012443 - -0.014053786718 - -0.0140395721917 - -0.0140253576654 - -0.014011143139 - -0.0139969286127 - -0.0139827140864 - -0.0139684995601 - -0.0139542850337 - -0.0139400705074 - -0.0139258559811 - -0.0139116414548 - -0.0138974269285 - -0.0138832124021 - -0.0138689978758 - -0.0138547833495 - -0.0138405688232 - -0.0138263542969 - -0.0138121397705 - -0.0137979252442 - -0.0137837107179 - -0.0137694961916 - -0.0137552816652 - -0.0137410671389 - -0.0137268526126 - -0.0137126380863 - -0.01369842356 - -0.0136842090336 - -0.0136699945073 - -0.013655779981 - -0.0136415654547 - -0.0136273509284 - -0.013613136402 - -0.0135989218757 - -0.0135847073494 - -0.0135704928231 - -0.0135562782967 - -0.0135420637704 - -0.0135278492441 - -0.0135136347178 - -0.0134994201915 - -0.0134852056651 - -0.0134709911388 - -0.0134567766125 - -0.0134425620862 - -0.0134283475599 - -0.0134141330335 - -0.0133999185072 - -0.0133857039809 - -0.0133714894546 - -0.0133572749282 - -0.0133430604019 - -0.0133288458756 - -0.0133146313493 - -0.013300416823 - -0.0132862022966 - -0.0132719877703 - -0.013257773244 - -0.0132435587177 - -0.0132293441914 - -0.013215129665 - -0.0132009151387 - -0.0131867006124 - -0.0131724860861 - -0.0131582715597 - -0.0131440570334 - -0.0131298425071 - -0.0131156279808 - -0.0131014134545 - -0.0130871989281 - -0.0130729844018 - -0.0130587698755 - -0.0130445553492 - -0.0130303408229 - -0.0130161262965 - -0.0130019117702 - -0.0129876972439 - -0.0129734827176 - -0.0129592681912 - -0.0129450536649 - -0.0129308391386 - -0.0129166246123 - -0.012902410086 - -0.0128881955596 - -0.0128739810333 - -0.012859766507 - -0.0128455519807 - -0.0128313374544 - -0.012817122928 - -0.0128029084017 - -0.0127886938754 - -0.0127744793491 - -0.0127602648227 - -0.0127460502964 - -0.0127318357701 - -0.0127176212438 - -0.0127034067175 - -0.0126891921911 - -0.0126749776648 - -0.0126607631385 - -0.0126465486122 - -0.0126323340858 - -0.0126181195595 - -0.0126039050332 - -0.0125896905069 - -0.0125754759806 - -0.0125612614542 - -0.0125470469279 - -0.0125328324016 - -0.0125186178753 - -0.012504403349 - -0.0124901888226 - -0.0124759742963 - -0.01246175977 - -0.0124475452437 - -0.0124333307173 - -0.012419116191 - -0.0124049016647 - -0.0123906871384 - -0.0123764726121 - -0.0123622580857 - -0.0123480435594 - -0.0123338290331 - -0.0123196145068 - -0.0123053999805 - -0.0122911854541 - -0.0122769709278 - -0.0122627564015 - -0.0122485418752 - -0.0122343273488 - -0.0122201128225 - -0.0122058982962 - -0.0121916837699 - -0.0121774692436 - -0.0121632547172 - -0.0121490401909 - -0.0121348256646 - -0.0121206111383 - -0.012106396612 - -0.0120921820856 - -0.0120779675593 - -0.012063753033 - -0.0120495385067 - -0.0120353239803 - -0.012021109454 - -0.0120068949277 - -0.0119926804014 - -0.0119784658751 - -0.0119642513487 - -0.0119500368224 - -0.0119358222961 - -0.0119216077698 - -0.0119073932435 - -0.0118931787171 - -0.0118789641908 - -0.0118647496645 - -0.0118505351382 - -0.0118363206118 - -0.0118221060855 - -0.0118078915592 - -0.0117936770329 - -0.0117794625066 - -0.0117652479802 - -0.0117510334539 - -0.0117368189276 - -0.0117226044013 - -0.011708389875 - -0.0116941753486 - -0.0116799608223 - -0.011665746296 - -0.0116515317697 - -0.0116373172433 - -0.011623102717 - -0.0116088881907 - -0.0115946736644 - -0.0115804591381 - -0.0115662446117 - -0.0115520300854 - -0.0115378155591 - -0.0115236010328 - -0.0115093865065 - -0.0114951719801 - -0.0114809574538 - -0.0114667429275 - -0.0114525284012 - -0.0114383138748 - -0.0114240993485 - -0.0114098848222 - -0.0113956702959 - -0.0113814557696 - -0.0113672412432 - -0.0113530267169 - -0.0113388121906 - -0.0113245976643 - -0.011310383138 - -0.0112961686116 - -0.0112819540853 - -0.011267739559 - -0.0112535250327 - -0.0112393105063 - -0.01122509598 - -0.0112108814537 - -0.0111966669274 - -0.0111824524011 - -0.0111682378747 - -0.0111540233484 - -0.0111398088221 - -0.0111255942958 - -0.0111113797694 - -0.0110971652431 - -0.0110829507168 - -0.0110687361905 - -0.0110545216642 - -0.0110403071378 - -0.0110260926115 - -0.0110118780852 - -0.0109976635589 - -0.0109834490326 - -0.0109692345062 - -0.0109550199799 - -0.0109408054536 - -0.0109265909273 - -0.0109123764009 - -0.0108981618746 - -0.0108839473483 - -0.010869732822 - -0.0108555182957 - -0.0108413037693 - -0.010827089243 - -0.0108128747167 - -0.0107986601904 - -0.0107844456641 - -0.0107702311377 - -0.0107560166114 - -0.0107418020851 - -0.0107275875588 - -0.0107133730324 - -0.0106991585061 - -0.0106849439798 - -0.0106707294535 - -0.0106565149272 - -0.0106423004008 - -0.0106280858745 - -0.0106138713482 - -0.0105996568219 - -0.0105854422956 - -0.0105712277692 - -0.0105570132429 - -0.0105427987166 - -0.0105285841903 - -0.0105143696639 - -0.0105001551376 - -0.0104859406113 - -0.010471726085 - -0.0104575115587 - -0.0104432970323 - -0.010429082506 - -0.0104148679797 - -0.0104006534534 - -0.0103864389271 - -0.0103722244007 - -0.0103580098744 - -0.0103437953481 - -0.0103295808218 - -0.0103153662954 - -0.0103011517691 - -0.0102869372428 - -0.0102727227165 - -0.0102585081902 - -0.0102442936638 - -0.0102300791375 - -0.0102158646112 - -0.0102016500849 - -0.0101874355586 - -0.0101732210322 - -0.0101590065059 - -0.0101447919796 - -0.0101305774533 - -0.0101163629269 - -0.0101021484006 - -0.0100879338743 - -0.010073719348 - -0.0100595048217 - -0.0100452902953 - -0.010031075769 - -0.0100168612427 - -0.0100026467164 - -0.00998843219005 - -0.00997421766373 - -0.00996000313741 - -0.00994578861109 - -0.00993157408476 - -0.00991735955844 - -0.00990314503212 - -0.0098889305058 - -0.00987471597948 - -0.00986050145316 - -0.00984628692684 - -0.00983207240051 - -0.00981785787419 - -0.00980364334787 - -0.00978942882155 - -0.00977521429523 - -0.00976099976891 - -0.00974678524258 - -0.00973257071626 - -0.00971835618994 - -0.00970414166362 - -0.0096899271373 - -0.00967571261098 - -0.00966149808466 - -0.00964728355833 - -0.00963306903201 - -0.00961885450569 - -0.00960463997937 - -0.00959042545305 - -0.00957621092673 - -0.00956199640041 - -0.00954778187408 - -0.00953356734776 - -0.00951935282144 - -0.00950513829512 - -0.0094909237688 - -0.00947670924248 - -0.00946249471615 - -0.00944828018983 - -0.00943406566351 - -0.00941985113719 - -0.00940563661087 - -0.00939142208455 - -0.00937720755823 - -0.0093629930319 - -0.00934877850558 - -0.00933456397926 - -0.00932034945294 - -0.00930613492662 - -0.0092919204003 - -0.00927770587398 - -0.00926349134765 - -0.00924927682133 - -0.00923506229501 - -0.00922084776869 - -0.00920663324237 - -0.00919241871605 - -0.00917820418972 - -0.0091639896634 - -0.00914977513708 - -0.00913556061076 - -0.00912134608444 - -0.00910713155812 - -0.0090929170318 - -0.00907870250547 - -0.00906448797915 - -0.00905027345283 - -0.00903605892651 - -0.00902184440019 - -0.00900762987387 - -0.00899341534755 - -0.00897920082122 - -0.0089649862949 - -0.00895077176858 - -0.00893655724226 - -0.00892234271594 - -0.00890812818962 - -0.00889391366329 - -0.00887969913697 - -0.00886548461065 - -0.00885127008433 - -0.00883705555801 - -0.00882284103169 - -0.00880862650537 - -0.00879441197904 - -0.00878019745272 - -0.0087659829264 - -0.00875176840008 - -0.00873755387376 - -0.00872333934744 - -0.00870912482112 - -0.00869491029479 - -0.00868069576847 - -0.00866648124215 - -0.00865226671583 - -0.00863805218951 - -0.00862383766319 - -0.00860962313686 - -0.00859540861054 - -0.00858119408422 - -0.0085669795579 - -0.00855276503158 - -0.00853855050526 - -0.00852433597894 - -0.00851012145261 - -0.00849590692629 - -0.00848169239997 - -0.00846747787365 - -0.00845326334733 - -0.00843904882101 - -0.00842483429469 - -0.00841061976836 - -0.00839640524204 - -0.00838219071572 - -0.0083679761894 - -0.00835376166308 - -0.00833954713676 - -0.00832533261043 - -0.00831111808411 - -0.00829690355779 - -0.00828268903147 - -0.00826847450515 - -0.00825425997883 - -0.00824004545251 - -0.00822583092618 - -0.00821161639986 - -0.00819740187354 - -0.00818318734722 - -0.0081689728209 - -0.00815475829458 - -0.00814054376826 - -0.00812632924193 - -0.00811211471561 - -0.00809790018929 - -0.00808368566297 - -0.00806947113665 - -0.00805525661033 - -0.008041042084 - -0.00802682755768 - -0.00801261303136 - -0.00799839850504 - -0.00798418397872 - -0.0079699694524 - -0.00795575492608 - -0.00794154039975 - -0.00792732587343 - -0.00791311134711 - -0.00789889682079 - -0.00788468229447 - -0.00787046776815 - -0.00785625324183 - -0.0078420387155 - -0.00782782418918 - -0.00781360966286 - -0.00779939513654 - -0.00778518061022 - -0.0077709660839 - -0.00775675155757 - -0.00774253703125 - -0.00772832250493 - -0.00771410797861 - -0.00769989345229 - -0.00768567892597 - -0.00767146439965 - -0.00765724987332 - -0.007643035347 - -0.00762882082068 - -0.00761460629436 - -0.00760039176804 - -0.00758617724172 - -0.0075719627154 - -0.00755774818907 - -0.00754353366275 - -0.00752931913643 - -0.00751510461011 - -0.00750089008379 - -0.00748667555747 - -0.00747246103114 - -0.00745824650482 - -0.0074440319785 - -0.00742981745218 - -0.00741560292586 - -0.00740138839954 - -0.00738717387322 - -0.00737295934689 - -0.00735874482057 - -0.00734453029425 - -0.00733031576793 - -0.00731610124161 - -0.00730188671529 - -0.00728767218897 - -0.00727345766264 - -0.00725924313632 - -0.00724502861 - -0.00723081408368 - -0.00721659955736 - -0.00720238503104 - -0.00718817050471 - -0.00717395597839 - -0.00715974145207 - -0.00714552692575 - -0.00713131239943 - -0.00711709787311 - -0.00710288334679 - -0.00708866882046 - -0.00707445429414 - -0.00706023976782 - -0.0070460252415 - -0.00703181071518 - -0.00701759618886 - -0.00700338166254 - -0.00698916713621 - -0.00697495260989 - -0.00696073808357 - -0.00694652355725 - -0.00693230903093 - -0.00691809450461 - -0.00690387997828 - -0.00688966545196 - -0.00687545092564 - -0.00686123639932 - -0.006847021873 - -0.00683280734668 - -0.00681859282036 - -0.00680437829403 - -0.00679016376771 - -0.00677594924139 - -0.00676173471507 - -0.00674752018875 - -0.00673330566243 - -0.00671909113611 - -0.00670487660978 - -0.00669066208346 - -0.00667644755714 - -0.00666223303082 - -0.0066480185045 - -0.00663380397818 - -0.00661958945185 - -0.00660537492553 - -0.00659116039921 - -0.00657694587289 - -0.00656273134657 - -0.00654851682025 - -0.00653430229393 - -0.0065200877676 - -0.00650587324128 - -0.00649165871496 - -0.00647744418864 - -0.00646322966232 - -0.006449015136 - -0.00643480060968 - -0.00642058608335 - -0.00640637155703 - -0.00639215703071 - -0.00637794250439 - -0.00636372797807 - -0.00634951345175 - -0.00633529892542 - -0.0063210843991 - -0.00630686987278 - -0.00629265534646 - -0.00627844082014 - -0.00626422629382 - -0.0062500117675 - -0.00623579724117 - -0.00622158271485 - -0.00620736818853 - -0.00619315366221 - -0.00617893913589 - -0.00616472460957 - -0.00615051008325 - -0.00613629555692 - -0.0061220810306 - -0.00610786650428 - -0.00609365197796 - -0.00607943745164 - -0.00606522292532 - -0.00605100839899 - -0.00603679387267 - -0.00602257934635 - -0.00600836482003 - -0.00599415029371 - -0.00597993576739 - -0.00596572124107 - -0.00595150671474 - -0.00593729218842 - -0.0059230776621 - -0.00590886313578 - -0.00589464860946 - -0.00588043408314 - -0.00586621955682 - -0.00585200503049 - -0.00583779050417 - -0.00582357597785 - -0.00580936145153 - -0.00579514692521 - -0.00578093239889 - -0.00576671787256 - -0.00575250334624 - -0.00573828881992 - -0.0057240742936 - -0.00570985976728 - -0.00569564524096 - -0.00568143071464 - -0.00566721618831 - -0.00565300166199 - -0.00563878713567 - -0.00562457260935 - -0.00561035808303 - -0.00559614355671 - -0.00558192903039 - -0.00556771450406 - -0.00555349997774 - -0.00553928545142 - -0.0055250709251 - -0.00551085639878 - -0.00549664187246 - -0.00548242734613 - -0.00546821281981 - -0.00545399829349 - -0.00543978376717 - -0.00542556924085 - -0.00541135471453 - -0.00539714018821 - -0.00538292566188 - -0.00536871113556 - -0.00535449660924 - -0.00534028208292 - -0.0053260675566 - -0.00531185303028 - -0.00529763850396 - -0.00528342397763 - -0.00526920945131 - -0.00525499492499 - -0.00524078039867 - -0.00522656587235 - -0.00521235134603 - -0.0051981368197 - -0.00518392229338 - -0.00516970776706 - -0.00515549324074 - -0.00514127871442 - -0.0051270641881 - -0.00511284966178 - -0.00509863513545 - -0.00508442060913 - -0.00507020608281 - -0.00505599155649 - -0.00504177703017 - -0.00502756250385 - -0.00501334797752 - -0.0049991334512 - -0.00498491892488 - -0.00497070439856 - -0.00495648987224 - -0.00494227534592 - -0.0049280608196 - -0.00491384629327 - -0.00489963176695 - -0.00488541724063 - -0.00487120271431 - -0.00485698818799 - -0.00484277366167 - -0.00482855913535 - -0.00481434460902 - -0.0048001300827 - -0.00478591555638 - -0.00477170103006 - -0.00475748650374 - -0.00474327197742 - -0.00472905745109 - -0.00471484292477 - -0.00470062839845 - -0.00468641387213 - -0.00467219934581 - -0.00465798481949 - -0.00464377029317 - -0.00462955576684 - -0.00461534124052 - -0.0046011267142 - -0.00458691218788 - -0.00457269766156 - -0.00455848313524 - -0.00454426860892 - -0.00453005408259 - -0.00451583955627 - -0.00450162502995 - -0.00448741050363 - -0.00447319597731 - -0.00445898145099 - -0.00444476692466 - -0.00443055239834 - -0.00441633787202 - -0.0044021233457 - -0.00438790881938 - -0.00437369429306 - -0.00435947976674 - -0.00434526524041 - -0.00433105071409 - -0.00431683618777 - -0.00430262166145 - -0.00428840713513 - -0.00427419260881 - -0.00425997808249 - -0.00424576355616 - -0.00423154902984 - -0.00421733450352 - -0.0042031199772 - -0.00418890545088 - -0.00417469092456 - -0.00416047639823 - -0.00414626187191 - -0.00413204734559 - -0.00411783281927 - -0.00410361829295 - -0.00408940376663 - -0.00407518924031 - -0.00406097471398 - -0.00404676018766 - -0.00403254566134 - -0.00401833113502 - -0.0040041166087 - -0.00398990208238 - -0.00397568755606 - -0.00396147302973 - -0.00394725850341 - -0.00393304397709 - -0.00391882945077 - -0.00390461492445 - -0.00389040039813 - -0.0038761858718 - -0.00386197134548 - -0.00384775681916 - -0.00383354229284 - -0.00381932776652 - -0.0038051132402 - -0.00379089871388 - -0.00377668418755 - -0.00376246966123 - -0.00374825513491 - -0.00373404060859 - -0.00371982608227 - -0.00370561155595 - -0.00369139702963 - -0.0036771825033 - -0.00366296797698 - -0.00364875345066 - -0.00363453892434 - -0.00362032439802 - -0.0036061098717 - -0.00359189534537 - -0.00357768081905 - -0.00356346629273 - -0.00354925176641 - -0.00353503724009 - -0.00352082271377 - -0.00350660818745 - -0.00349239366112 - -0.0034781791348 - -0.00346396460848 - -0.00344975008216 - -0.00343553555584 - -0.00342132102952 - -0.0034071065032 - -0.00339289197687 - -0.00337867745055 - -0.00336446292423 - -0.00335024839791 - -0.00333603387159 - -0.00332181934527 - -0.00330760481894 - -0.00329339029262 - -0.0032791757663 - -0.00326496123998 - -0.00325074671366 - -0.00323653218734 - -0.00322231766102 - -0.00320810313469 - -0.00319388860837 - -0.00317967408205 - -0.00316545955573 - -0.00315124502941 - -0.00313703050309 - -0.00312281597677 - -0.00310860145044 - -0.00309438692412 - -0.0030801723978 - -0.00306595787148 - -0.00305174334516 - -0.00303752881884 - -0.00302331429251 - -0.00300909976619 - -0.00299488523987 - -0.00298067071355 - -0.00296645618723 - -0.00295224166091 - -0.00293802713459 - -0.00292381260826 - -0.00290959808194 - -0.00289538355562 - -0.0028811690293 - -0.00286695450298 - -0.00285273997666 - -0.00283852545034 - -0.00282431092401 - -0.00281009639769 - -0.00279588187137 - -0.00278166734505 - -0.00276745281873 - -0.00275323829241 - -0.00273902376608 - -0.00272480923976 - -0.00271059471344 - -0.00269638018712 - -0.0026821656608 - -0.00266795113448 - -0.00265373660816 - -0.00263952208183 - -0.00262530755551 - -0.00261109302919 - -0.00259687850287 - -0.00258266397655 - -0.00256844945023 - -0.00255423492391 - -0.00254002039758 - -0.00252580587126 - -0.00251159134494 - -0.00249737681862 - -0.0024831622923 - -0.00246894776598 - -0.00245473323965 - -0.00244051871333 - -0.00242630418701 - -0.00241208966069 - -0.00239787513437 - -0.00238366060805 - -0.00236944608173 - -0.0023552315554 - -0.00234101702908 - -0.00232680250276 - -0.00231258797644 - -0.00229837345012 - -0.0022841589238 - -0.00226994439748 - -0.00225572987115 - -0.00224151534483 - -0.00222730081851 - -0.00221308629219 - -0.00219887176587 - -0.00218465723955 - -0.00217044271322 - -0.0021562281869 - -0.00214201366058 - -0.00212779913426 - -0.00211358460794 - -0.00209937008162 - -0.0020851555553 - -0.00207094102897 - -0.00205672650265 - -0.00204251197633 - -0.00202829745001 - -0.00201408292369 - -0.00199986839737 - -0.00198565387105 - -0.00197143934472 - -0.0019572248184 - -0.00194301029208 - -0.00192879576576 - -0.00191458123944 - -0.00190036671312 - -0.00188615218679 - -0.00187193766047 - -0.00185772313415 - -0.00184350860783 - -0.00182929408151 - -0.00181507955519 - -0.00180086502887 - -0.00178665050254 - -0.00177243597622 - -0.0017582214499 - -0.00174400692358 - -0.00172979239726 - -0.00171557787094 - -0.00170136334462 - -0.00168714881829 - -0.00167293429197 - -0.00165871976565 - -0.00164450523933 - -0.00163029071301 - -0.00161607618669 - -0.00160186166036 - -0.00158764713404 - -0.00157343260772 - -0.0015592180814 - -0.00154500355508 - -0.00153078902876 - -0.00151657450244 - -0.00150235997611 - -0.00148814544979 - -0.00147393092347 - -0.00145971639715 - -0.00144550187083 - -0.00143128734451 - -0.00141707281819 - -0.00140285829186 - -0.00138864376554 - -0.00137442923922 - -0.0013602147129 - -0.00134600018658 - -0.00133178566026 - -0.00131757113393 - -0.00130335660761 - -0.00128914208129 - -0.00127492755497 - -0.00126071302865 - -0.00124649850233 - -0.00123228397601 - -0.00121806944968 - -0.00120385492336 - -0.00118964039704 - -0.00117542587072 - -0.0011612113444 - -0.00114699681808 - -0.00113278229176 - -0.00111856776543 - -0.00110435323911 - -0.00109013871279 - -0.00107592418647 - -0.00106170966015 - -0.00104749513383 - -0.0010332806075 - -0.00101906608118 - -0.00100485155486 - -0.00099063702854 - -0.000976422502219 - -0.000962207975897 - -0.000947993449576 - -0.000933778923254 - -0.000919564396933 - -0.000905349870611 - -0.00089113534429 - -0.000876920817968 - -0.000862706291647 - -0.000848491765325 - -0.000834277239004 - -0.000820062712682 - -0.000805848186361 - -0.000791633660039 - -0.000777419133718 - -0.000763204607396 - -0.000748990081075 - -0.000734775554753 - -0.000720561028432 - -0.00070634650211 - -0.000692131975789 - -0.000677917449467 - -0.000663702923146 - -0.000649488396824 - -0.000635273870503 - -0.000621059344181 - -0.00060684481786 - -0.000592630291538 - -0.000578415765217 - -0.000564201238895 - -0.000549986712574 - -0.000535772186252 - -0.000521557659931 - -0.000507343133609 - -0.000493128607288 - -0.000478914080966 - -0.000464699554645 - -0.000450485028323 - -0.000436270502002 - -0.00042205597568 - -0.000407841449359 - -0.000393626923037 - -0.000379412396715 - -0.000365197870394 - -0.000350983344072 - -0.000336768817751 - -0.000322554291429 - -0.000308339765108 - -0.000294125238786 - -0.000279910712465 - -0.000265696186143 - -0.000251481659822 - -0.0002372671335 - -0.000223052607179 - -0.000208838080857 - -0.000194623554536 - -0.000180409028214 - -0.000166194501893 - -0.000151979975571 - -0.00013776544925 - -0.000123550922928 - -0.000109336396607 - -9.51218702855e-05 - -8.0907343964e-05 - -6.66928176425e-05 - -5.2478291321e-05 - -3.82637649995e-05 - -2.4049238678e-05 - -9.83471235646e-06 - 4.37981396505e-06 - 1.85943402865e-05 - 3.2808866608e-05 - 4.70233929295e-05 - 6.12379192511e-05 - 7.54524455726e-05 - 8.96669718941e-05 - 0.000103881498216 - 0.000118096024537 - 0.000132310550859 - 0.00014652507718 - 0.000160739603502 - 0.000174954129823 - 0.000189168656145 - 0.000203383182466 - 0.000217597708788 - 0.000231812235109 - 0.000246026761431 - 0.000260241287752 - 0.000274455814074 - 0.000288670340395 - 0.000302884866717 - 0.000317099393038 - 0.00033131391936 - 0.000345528445681 - 0.000359742972003 - 0.000373957498324 - 0.000388172024646 - 0.000402386550967 - 0.000416601077289 - 0.00043081560361 - 0.000445030129932 - 0.000459244656253 - 0.000473459182575 - 0.000487673708896 - 0.000501888235218 - 0.000516102761539 - 0.000530317287861 - 0.000544531814182 - 0.000558746340504 - 0.000572960866825 - 0.000587175393147 - 0.000601389919468 - 0.00061560444579 - 0.000629818972111 - 0.000644033498433 - 0.000658248024754 - 0.000672462551076 - 0.000686677077397 - 0.000700891603719 - 0.00071510613004 - 0.000729320656362 - 0.000743535182683 - 0.000757749709005 - 0.000771964235326 - 0.000786178761648 - 0.000800393287969 - 0.000814607814291 - 0.000828822340612 - 0.000843036866934 - 0.000857251393255 - 0.000871465919577 - 0.000885680445898 - 0.00089989497222 - 0.000914109498541 - 0.000928324024863 - 0.000942538551184 - 0.000956753077506 - 0.000970967603827 - 0.000985182130149 - 0.00099939665647 - 0.00101361118279 - 0.00102782570911 - 0.00104204023543 - 0.00105625476176 - 0.00107046928808 - 0.0010846838144 - 0.00109889834072 - 0.00111311286704 - 0.00112732739336 - 0.00114154191969 - 0.00115575644601 - 0.00116997097233 - 0.00118418549865 - 0.00119840002497 - 0.00121261455129 - 0.00122682907761 - 0.00124104360394 - 0.00125525813026 - 0.00126947265658 - 0.0012836871829 - 0.00129790170922 - 0.00131211623554 - 0.00132633076186 - 0.00134054528819 - 0.00135475981451 - 0.00136897434083 - 0.00138318886715 - 0.00139740339347 - 0.00141161791979 - 0.00142583244612 - 0.00144004697244 - 0.00145426149876 - 0.00146847602508 - 0.0014826905514 - 0.00149690507772 - 0.00151111960404 - 0.00152533413037 - 0.00153954865669 - 0.00155376318301 - 0.00156797770933 - 0.00158219223565 - 0.00159640676197 - 0.00161062128829 - 0.00162483581462 - 0.00163905034094 - 0.00165326486726 - 0.00166747939358 - 0.0016816939199 - 0.00169590844622 - 0.00171012297255 - 0.00172433749887 - 0.00173855202519 - 0.00175276655151 - 0.00176698107783 - 0.00178119560415 - 0.00179541013047 - 0.0018096246568 - 0.00182383918312 - 0.00183805370944 - 0.00185226823576 - 0.00186648276208 - 0.0018806972884 - 0.00189491181472 - 0.00190912634105 - 0.00192334086737 - 0.00193755539369 - 0.00195176992001 - 0.00196598444633 - 0.00198019897265 - 0.00199441349898 - 0.0020086280253 - 0.00202284255162 - 0.00203705707794 - 0.00205127160426 - 0.00206548613058 - 0.0020797006569 - 0.00209391518323 - 0.00210812970955 - 0.00212234423587 - 0.00213655876219 - 0.00215077328851 - 0.00216498781483 - 0.00217920234115 - 0.00219341686748 - 0.0022076313938 - 0.00222184592012 - 0.00223606044644 - 0.00225027497276 - 0.00226448949908 - 0.00227870402541 - 0.00229291855173 - 0.00230713307805 - 0.00232134760437 - 0.00233556213069 - 0.00234977665701 - 0.00236399118333 - 0.00237820570966 - 0.00239242023598 - 0.0024066347623 - 0.00242084928862 - 0.00243506381494 - 0.00244927834126 - 0.00246349286758 - 0.00247770739391 - 0.00249192192023 - 0.00250613644655 - 0.00252035097287 - 0.00253456549919 - 0.00254878002551 - 0.00256299455184 - 0.00257720907816 - 0.00259142360448 - 0.0026056381308 - 0.00261985265712 - 0.00263406718344 - 0.00264828170976 - 0.00266249623609 - 0.00267671076241 - 0.00269092528873 - 0.00270513981505 - 0.00271935434137 - 0.00273356886769 - 0.00274778339401 - 0.00276199792034 - 0.00277621244666 - 0.00279042697298 - 0.0028046414993 - 0.00281885602562 - 0.00283307055194 - 0.00284728507827 - 0.00286149960459 - 0.00287571413091 - 0.00288992865723 - 0.00290414318355 - 0.00291835770987 - 0.00293257223619 - 0.00294678676252 - 0.00296100128884 - 0.00297521581516 - 0.00298943034148 - 0.0030036448678 - 0.00301785939412 - 0.00303207392044 - 0.00304628844677 - 0.00306050297309 - 0.00307471749941 - 0.00308893202573 - 0.00310314655205 - 0.00311736107837 - 0.0031315756047 - 0.00314579013102 - 0.00316000465734 - 0.00317421918366 - 0.00318843370998 - 0.0032026482363 - 0.00321686276262 - 0.00323107728895 - 0.00324529181527 - 0.00325950634159 - 0.00327372086791 - 0.00328793539423 - 0.00330214992055 - 0.00331636444687 - 0.0033305789732 - 0.00334479349952 - 0.00335900802584 - 0.00337322255216 - 0.00338743707848 - 0.0034016516048 - 0.00341586613113 - 0.00343008065745 - 0.00344429518377 - 0.00345850971009 - 0.00347272423641 - 0.00348693876273 - 0.00350115328905 - 0.00351536781538 - 0.0035295823417 - 0.00354379686802 - 0.00355801139434 - 0.00357222592066 - 0.00358644044698 - 0.0036006549733 - 0.00361486949963 - 0.00362908402595 - 0.00364329855227 - 0.00365751307859 - 0.00367172760491 - 0.00368594213123 - 0.00370015665756 - 0.00371437118388 - 0.0037285857102 - 0.00374280023652 - 0.00375701476284 - 0.00377122928916 - 0.00378544381548 - 0.00379965834181 - 0.00381387286813 - 0.00382808739445 - 0.00384230192077 - 0.00385651644709 - 0.00387073097341 - 0.00388494549973 - 0.00389916002606 - 0.00391337455238 - 0.0039275890787 - 0.00394180360502 - 0.00395601813134 - 0.00397023265766 - 0.00398444718399 - 0.00399866171031 - 0.00401287623663 - 0.00402709076295 - 0.00404130528927 - 0.00405551981559 - 0.00406973434191 - 0.00408394886824 - 0.00409816339456 - 0.00411237792088 - 0.0041265924472 - 0.00414080697352 - 0.00415502149984 - 0.00416923602616 - 0.00418345055249 - 0.00419766507881 - 0.00421187960513 - 0.00422609413145 - 0.00424030865777 - 0.00425452318409 - 0.00426873771042 - 0.00428295223674 - 0.00429716676306 - 0.00431138128938 - 0.0043255958157 - 0.00433981034202 - 0.00435402486834 - 0.00436823939467 - 0.00438245392099 - 0.00439666844731 - 0.00441088297363 - 0.00442509749995 - 0.00443931202627 - 0.0044535265526 - 0.00446774107892 - 0.00448195560524 - 0.00449617013156 - 0.00451038465788 - 0.0045245991842 - 0.00453881371052 - 0.00455302823685 - 0.00456724276317 - 0.00458145728949 - 0.00459567181581 - 0.00460988634213 - 0.00462410086845 - 0.00463831539477 - 0.0046525299211 - 0.00466674444742 - 0.00468095897374 - 0.00469517350006 - 0.00470938802638 - 0.0047236025527 - 0.00473781707903 - 0.00475203160535 - 0.00476624613167 - 0.00478046065799 - 0.00479467518431 - 0.00480888971063 - 0.00482310423695 - 0.00483731876328 - 0.0048515332896 - 0.00486574781592 - 0.00487996234224 - 0.00489417686856 - 0.00490839139488 - 0.0049226059212 - 0.00493682044753 - 0.00495103497385 - 0.00496524950017 - 0.00497946402649 - 0.00499367855281 - 0.00500789307913 - 0.00502210760546 - 0.00503632213178 - 0.0050505366581 - 0.00506475118442 - 0.00507896571074 - 0.00509318023706 - 0.00510739476338 - 0.00512160928971 - 0.00513582381603 - 0.00515003834235 - 0.00516425286867 - 0.00517846739499 - 0.00519268192131 - 0.00520689644763 - 0.00522111097396 - 0.00523532550028 - 0.0052495400266 - 0.00526375455292 - 0.00527796907924 - 0.00529218360556 - 0.00530639813189 - 0.00532061265821 - 0.00533482718453 - 0.00534904171085 - 0.00536325623717 - 0.00537747076349 - 0.00539168528981 - 0.00540589981614 - 0.00542011434246 - 0.00543432886878 - 0.0054485433951 - 0.00546275792142 - 0.00547697244774 - 0.00549118697406 - 0.00550540150039 - 0.00551961602671 - 0.00553383055303 - 0.00554804507935 - 0.00556225960567 - 0.00557647413199 - 0.00559068865832 - 0.00560490318464 - 0.00561911771096 - 0.00563333223728 - 0.0056475467636 - 0.00566176128992 - 0.00567597581624 - 0.00569019034257 - 0.00570440486889 - 0.00571861939521 - 0.00573283392153 - 0.00574704844785 - 0.00576126297417 - 0.00577547750049 - 0.00578969202682 - 0.00580390655314 - 0.00581812107946 - 0.00583233560578 - 0.0058465501321 - 0.00586076465842 - 0.00587497918475 - 0.00588919371107 - 0.00590340823739 - 0.00591762276371 - 0.00593183729003 - 0.00594605181635 - 0.00596026634267 - 0.005974480869 - 0.00598869539532 - 0.00600290992164 - 0.00601712444796 - 0.00603133897428 - 0.0060455535006 - 0.00605976802692 - 0.00607398255325 - 0.00608819707957 - 0.00610241160589 - 0.00611662613221 - 0.00613084065853 - 0.00614505518485 - 0.00615926971118 - 0.0061734842375 - 0.00618769876382 - 0.00620191329014 - 0.00621612781646 - 0.00623034234278 - 0.0062445568691 - 0.00625877139543 - 0.00627298592175 - 0.00628720044807 - 0.00630141497439 - 0.00631562950071 - 0.00632984402703 - 0.00634405855335 - 0.00635827307968 - 0.006372487606 - 0.00638670213232 - 0.00640091665864 - 0.00641513118496 - 0.00642934571128 - 0.00644356023761 - 0.00645777476393 - 0.00647198929025 - 0.00648620381657 - 0.00650041834289 - 0.00651463286921 - 0.00652884739553 - 0.00654306192186 - 0.00655727644818 - 0.0065714909745 - 0.00658570550082 - 0.00659992002714 - 0.00661413455346 - 0.00662834907978 - 0.00664256360611 - 0.00665677813243 - 0.00667099265875 - 0.00668520718507 - 0.00669942171139 - 0.00671363623771 - 0.00672785076404 - 0.00674206529036 - 0.00675627981668 - 0.006770494343 - 0.00678470886932 - 0.00679892339564 - 0.00681313792196 - 0.00682735244829 - 0.00684156697461 - 0.00685578150093 - 0.00686999602725 - 0.00688421055357 - 0.00689842507989 - 0.00691263960621 - 0.00692685413254 - 0.00694106865886 - 0.00695528318518 - 0.0069694977115 - 0.00698371223782 - 0.00699792676414 - 0.00701214129047 - 0.00702635581679 - 0.00704057034311 - 0.00705478486943 - 0.00706899939575 - 0.00708321392207 - 0.00709742844839 - 0.00711164297472 - 0.00712585750104 - 0.00714007202736 - 0.00715428655368 - 0.00716850108 - 0.00718271560632 - 0.00719693013264 - 0.00721114465897 - 0.00722535918529 - 0.00723957371161 - 0.00725378823793 - 0.00726800276425 - 0.00728221729057 - 0.0072964318169 - 0.00731064634322 - 0.00732486086954 - 0.00733907539586 - 0.00735328992218 - 0.0073675044485 - 0.00738171897482 - 0.00739593350115 - 0.00741014802747 - 0.00742436255379 - 0.00743857708011 - 0.00745279160643 - 0.00746700613275 - 0.00748122065907 - 0.0074954351854 - 0.00750964971172 - 0.00752386423804 - 0.00753807876436 - 0.00755229329068 - 0.007566507817 - 0.00758072234333 - 0.00759493686965 - 0.00760915139597 - 0.00762336592229 - 0.00763758044861 - 0.00765179497493 - 0.00766600950125 - 0.00768022402758 - 0.0076944385539 - 0.00770865308022 - 0.00772286760654 - 0.00773708213286 - 0.00775129665918 - 0.0077655111855 - 0.00777972571183 - 0.00779394023815 - 0.00780815476447 - 0.00782236929079 - 0.00783658381711 - 0.00785079834343 - 0.00786501286976 - 0.00787922739608 - 0.0078934419224 - 0.00790765644872 - 0.00792187097504 - 0.00793608550136 - 0.00795030002768 - 0.00796451455401 - 0.00797872908033 - 0.00799294360665 - 0.00800715813297 - 0.00802137265929 - 0.00803558718561 - 0.00804980171193 - 0.00806401623826 - 0.00807823076458 - 0.0080924452909 - 0.00810665981722 - 0.00812087434354 - 0.00813508886986 - 0.00814930339619 - 0.00816351792251 - 0.00817773244883 - 0.00819194697515 - 0.00820616150147 - 0.00822037602779 - 0.00823459055411 - 0.00824880508044 - 0.00826301960676 - 0.00827723413308 - 0.0082914486594 - 0.00830566318572 - 0.00831987771204 - 0.00833409223836 - 0.00834830676469 - 0.00836252129101 - 0.00837673581733 - 0.00839095034365 - 0.00840516486997 - 0.00841937939629 - 0.00843359392262 - 0.00844780844894 - 0.00846202297526 - 0.00847623750158 - 0.0084904520279 - 0.00850466655422 - 0.00851888108054 - 0.00853309560687 - 0.00854731013319 - 0.00856152465951 - 0.00857573918583 - 0.00858995371215 - 0.00860416823847 - 0.00861838276479 - 0.00863259729112 - 0.00864681181744 - 0.00866102634376 - 0.00867524087008 - 0.0086894553964 - 0.00870366992272 - 0.00871788444905 - 0.00873209897537 - 0.00874631350169 - 0.00876052802801 - 0.00877474255433 - 0.00878895708065 - 0.00880317160697 - 0.0088173861333 - 0.00883160065962 - 0.00884581518594 - 0.00886002971226 - 0.00887424423858 - 0.0088884587649 - 0.00890267329122 - 0.00891688781755 - 0.00893110234387 - 0.00894531687019 - 0.00895953139651 - 0.00897374592283 - 0.00898796044915 - 0.00900217497548 - 0.0090163895018 - 0.00903060402812 - 0.00904481855444 - 0.00905903308076 - 0.00907324760708 - 0.0090874621334 - 0.00910167665973 - 0.00911589118605 - 0.00913010571237 - 0.00914432023869 - 0.00915853476501 - 0.00917274929133 - 0.00918696381766 - 0.00920117834398 - 0.0092153928703 - 0.00922960739662 - 0.00924382192294 - 0.00925803644926 - 0.00927225097558 - 0.00928646550191 - 0.00930068002823 - 0.00931489455455 - 0.00932910908087 - 0.00934332360719 - 0.00935753813351 - 0.00937175265983 - 0.00938596718616 - 0.00940018171248 - 0.0094143962388 - 0.00942861076512 - 0.00944282529144 - 0.00945703981776 - 0.00947125434409 - 0.00948546887041 - 0.00949968339673 - 0.00951389792305 - 0.00952811244937 - 0.00954232697569 - 0.00955654150201 - 0.00957075602834 - 0.00958497055466 - 0.00959918508098 - 0.0096133996073 - 0.00962761413362 - 0.00964182865994 - 0.00965604318626 - 0.00967025771259 - 0.00968447223891 - 0.00969868676523 - 0.00971290129155 - 0.00972711581787 - 0.00974133034419 - 0.00975554487052 - 0.00976975939684 - 0.00978397392316 - 0.00979818844948 - 0.0098124029758 - 0.00982661750212 - 0.00984083202844 - 0.00985504655477 - 0.00986926108109 - 0.00988347560741 - 0.00989769013373 - 0.00991190466005 - 0.00992611918637 - 0.00994033371269 - 0.00995454823902 - 0.00996876276534 - 0.00998297729166 - 0.00999719181798 - 0.0100114063443 - 0.0100256208706 - 0.0100398353969 - 0.0100540499233 - 0.0100682644496 - 0.0100824789759 - 0.0100966935022 - 0.0101109080286 - 0.0101251225549 - 0.0101393370812 - 0.0101535516075 - 0.0101677661338 - 0.0101819806602 - 0.0101961951865 - 0.0102104097128 - 0.0102246242391 - 0.0102388387654 - 0.0102530532918 - 0.0102672678181 - 0.0102814823444 - 0.0102956968707 - 0.0103099113971 - 0.0103241259234 - 0.0103383404497 - 0.010352554976 - 0.0103667695023 - 0.0103809840287 - 0.010395198555 - 0.0104094130813 - 0.0104236276076 - 0.0104378421339 - 0.0104520566603 - 0.0104662711866 - 0.0104804857129 - 0.0104947002392 - 0.0105089147656 - 0.0105231292919 - 0.0105373438182 - 0.0105515583445 - 0.0105657728708 - 0.0105799873972 - 0.0105940611217 - 0.010608282872 - 0.0106225147337 - 0.0106367567139 - 0.0106510088199 - 0.0106652710589 - 0.010679543438 - 0.0106938259645 - 0.0107081186456 - 0.0107224214885 - 0.0107367345005 - 0.0107510576887 - 0.0107653910604 - 0.0107797346229 - 0.0107940883834 - 0.0108084523491 - 0.0108228265273 - 0.0108372109252 - 0.0108516055502 - 0.0108660104094 - 0.0108804255103 - 0.0108948508599 - 0.0109092864657 - 0.010923732335 - 0.010938188475 - 0.010952654893 - 0.0109671315963 - 0.0109816185923 - 0.0109961158882 - 0.0110106234915 - 0.0110251414093 - 0.0110396696491 - 0.0110542082182 - 0.011068757124 - 0.0110833163737 - 0.0110978859747 - 0.0111124659345 - 0.0111270562603 - 0.0111416569595 - 0.0111562680396 - 0.0111708895078 - 0.0111855213716 - 0.0112001636384 - 0.0112148163156 - 0.0112294794105 - 0.0112441529305 - 0.0112588368832 - 0.0112735312758 - 0.0112882361159 - 0.0113029514108 - 0.011317677168 - 0.011332413395 - 0.011347160099 - 0.0113619172877 - 0.0113766849685 - 0.0113914631488 - 0.0114062518361 - 0.0114210510379 - 0.0114358607616 - 0.0114506810147 - 0.0114655118047 - 0.0114803531391 - 0.0114952050254 - 0.0115100674711 - 0.0115249404837 - 0.0115398240708 - 0.0115547182397 - 0.0115696229981 - 0.0115845383535 - 0.0115994643135 - 0.0116144008855 - 0.0116293480771 - 0.0116443058958 - 0.0116592743493 - 0.011674253445 - 0.0116892431906 - 0.0117042435936 - 0.0117192546616 - 0.0117342764021 - 0.0117493088228 - 0.0117643519313 - 0.0117794057351 - 0.0117944702418 - 0.0118095454592 - 0.0118246313947 - 0.011839728056 - 0.0118548354507 - 0.0118699535865 - 0.011885082471 - 0.0119002221119 - 0.0119153725167 - 0.0119305336931 - 0.0119457056489 - 0.0119608883916 - 0.0119760819289 - 0.0119912862685 - 0.0120065014182 - 0.0120217273854 - 0.0120369641781 - 0.0120522118038 - 0.0120674702703 - 0.0120827395852 - 0.0120980197563 - 0.0121133107913 - 0.012128612698 - 0.0121439254839 - 0.012159249157 - 0.0121745837249 - 0.0121899291954 - 0.0122052855762 - 0.012220652875 - 0.0122360310998 - 0.0122514202581 - 0.0122668203578 - 0.0122822314067 - 0.0122976534125 - 0.0123130863831 - 0.0123285303262 - 0.0123439852497 - 0.0123594511613 - 0.0123749280688 - 0.0123904159801 - 0.0124059149031 - 0.0124214248454 - 0.012436945815 - 0.0124524778197 - 0.0124680208674 - 0.0124835749658 - 0.0124991401229 - 0.0125147163466 - 0.0125303036446 - 0.0125459020248 - 0.0125615114952 - 0.0125771320637 - 0.012592763738 - 0.0126084065262 - 0.0126240604361 - 0.0126397254755 - 0.0126554016526 - 0.012671088975 - 0.0126867874509 - 0.012702497088 - 0.0127182178944 - 0.012733949878 - 0.0127496930467 - 0.0127654474085 - 0.0127812129713 - 0.0127969897431 - 0.0128127777319 - 0.0128285769456 - 0.0128443873923 - 0.0128602090799 - 0.0128760420163 - 0.0128918862097 - 0.012907741668 - 0.0129236083992 - 0.0129394864114 - 0.0129553757125 - 0.0129712763105 - 0.0129871882136 - 0.0130031114298 - 0.013019045967 - 0.0130349918333 - 0.0130509490369 - 0.0130669175857 - 0.0130828974878 - 0.0130988887513 - 0.0131148913843 - 0.0131309053949 - 0.0131469307911 - 0.013162967581 - 0.0131790157727 - 0.0131950753745 - 0.0132111463942 - 0.0132272288402 - 0.0132433227204 - 0.0132594280431 - 0.0132755448163 - 0.0132916730483 - 0.0133078127471 - 0.0133239639209 - 0.0133401265778 - 0.0133563007261 - 0.0133724863739 - 0.0133886835294 - 0.0134048922007 - 0.0134211123961 - 0.0134373441237 - 0.0134535873917 - 0.0134698422084 - 0.013486108582 - 0.0135023865206 - 0.0135186760324 - 0.0135349771259 - 0.013551289809 - 0.0135676140902 - 0.0135839499776 - 0.0136002974795 - 0.0136166566041 - 0.0136330273598 - 0.0136494097547 - 0.0136658037972 - 0.0136822094955 - 0.013698626858 - 0.0137150558929 - 0.0137314966085 - 0.0137479490131 - 0.013764413115 - 0.0137808889226 - 0.0137973764442 - 0.0138138756881 - 0.0138303866626 - 0.013846909376 - 0.0138634438368 - 0.0138799900533 - 0.0138965480338 - 0.0139131177867 - 0.0139296993204 - 0.0139462926432 - 0.0139628977635 - 0.0139795146898 - 0.0139961434303 - 0.0140127839936 - 0.0140294363879 - 0.0140461006218 - 0.0140627767036 - 0.0140794646418 - 0.0140961644448 - 0.014112876121 - 0.0141295996789 - 0.0141463351269 - 0.0141630824734 - 0.014179841727 - 0.0141966128961 - 0.0142133959892 - 0.0142301910147 - 0.0142469979811 - 0.014263816897 - 0.0142806477708 - 0.0142974906109 - 0.0143143454261 - 0.0143312122246 - 0.0143480910151 - 0.0143649818061 - 0.0143818846061 - 0.0143987994237 - 0.0144157262674 - 0.0144326651457 - 0.0144496160672 - 0.0144665790405 - 0.0144835540741 - 0.0145005411767 - 0.0145175403567 - 0.0145345516228 - 0.0145515749836 - 0.0145686104477 - 0.0145856580236 - 0.01460271772 - 0.0146197895455 - 0.0146368735088 - 0.0146539696184 - 0.014671077883 - 0.0146881983113 - 0.0147053309118 - 0.0147224756932 - 0.0147396326643 - 0.0147568018336 - 0.0147739832099 - 0.0147911768018 - 0.014808382618 - 0.0148256006672 - 0.0148428309581 - 0.0148600734993 - 0.0148773282997 - 0.0148945953679 - 0.0149118747126 - 0.0149291663427 - 0.0149464702667 - 0.0149637864934 - 0.0149811150317 - 0.0149984558902 - 0.0150158090777 - 0.015033174603 - 0.0150505524748 - 0.0150679427019 - 0.0150853452932 - 0.0151027602573 - 0.0151201876032 - 0.0151376273395 - 0.0151550794752 - 0.0151725440189 - 0.0151900209796 - 0.0152075103661 - 0.0152250121872 - 0.0152425264517 - 0.0152600531686 - 0.0152775923465 - 0.0152951439945 - 0.0153127081214 - 0.015330284736 - 0.0153478738472 - 0.015365475464 - 0.0153830895951 - 0.0154007162495 - 0.0154183554362 - 0.0154360071639 - 0.0154536714417 - 0.0154713482784 - 0.015489037683 - 0.0155067396644 - 0.0155244542316 - 0.0155421813935 - 0.015559921159 - 0.0155776735372 - 0.015595438537 - 0.0156132161673 - 0.0156310064371 - 0.0156488093555 - 0.0156666249314 - 0.0156844531738 - 0.0157022940918 - 0.0157201476943 - 0.0157380139903 - 0.015755892989 - 0.0157737846992 - 0.0157916891301 - 0.0158096062907 - 0.01582753619 - 0.0158454788372 - 0.0158634342412 - 0.0158814024111 - 0.0158993833561 - 0.0159173770851 - 0.0159353836073 - 0.0159534029318 - 0.0159714350677 - 0.0159894800241 - 0.0160075378101 - 0.0160256084348 - 0.0160436919074 - 0.016061788237 - 0.0160798974326 - 0.0160980195036 - 0.016116154459 - 0.016134302308 - 0.0161524630598 - 0.0161706367235 - 0.0161888233083 - 0.0162070228234 - 0.016225235278 - 0.0162434606813 - 0.0162616990424 - 0.0162799503708 - 0.0162982146754 - 0.0163164919656 - 0.0163347822506 - 0.0163530855396 - 0.0163714018419 - 0.0163897311667 - 0.0164080735233 - 0.0164264289209 - 0.0164447973689 - 0.0164631788765 - 0.016481573453 - 0.0164999811076 - 0.0165184018497 - 0.0165368356886 - 0.0165552826336 - 0.016573742694 - 0.0165922158792 - 0.0166107021984 - 0.016629201661 - 0.0166477142764 - 0.0166662400538 - 0.0166847790028 - 0.0167033311325 - 0.0167218964525 - 0.016740474972 - 0.0167590667005 - 0.0167776716473 - 0.0167962898219 - 0.0168149212336 - 0.0168335658919 - 0.0168522238062 - 0.0168708949859 - 0.0168895794404 - 0.0169082771792 - 0.0169269882117 - 0.0169457125474 - 0.0169644501958 - 0.0169832011662 - 0.0170019654682 - 0.0170207431112 - 0.0170395341048 - 0.0170583384584 - 0.0170771561815 - 0.0170959872836 - 0.0171148317743 - 0.017133689663 - 0.0171525609593 - 0.0171714456728 - 0.0171903438129 - 0.0172092553892 - 0.0172281804112 - 0.0172471188886 - 0.0172660708308 - 0.0172850362475 - 0.0173040151483 - 0.0173230075426 - 0.0173420134402 - 0.0173610328506 - 0.0173800657834 - 0.0173991122483 - 0.0174181722548 - 0.0174372458126 - 0.0174563329313 - 0.0174754336205 - 0.01749454789 - 0.0175136757494 - 0.0175328172083 - 0.0175519722764 - 0.0175711409633 - 0.0175903232788 - 0.0176095192326 - 0.0176287288343 - 0.0176479520936 - 0.0176671890203 - 0.0176864396241 - 0.0177057039146 - 0.0177249819017 - 0.0177442735951 - 0.0177635790045 - 0.0177828981396 - 0.0178022310103 - 0.0178215776262 - 0.0178409379972 - 0.017860312133 - 0.0178797000435 - 0.0178991017384 - 0.0179185172275 - 0.0179379465206 - 0.0179573896276 - 0.0179768465583 - 0.0179963173224 - 0.0180158019298 - 0.0180353003905 - 0.0180548127141 - 0.0180743389106 - 0.0180938789899 - 0.0181134329618 - 0.0181330008361 - 0.0181525826228 - 0.0181721783318 - 0.018191787973 - 0.0182114115562 - 0.0182310490914 - 0.0182507005884 - 0.0182703660573 - 0.018290045508 - 0.0183097389504 - 0.0183294463944 - 0.01834916785 - 0.0183689033272 - 0.0183886528359 - 0.0184084163861 - 0.0184281939878 - 0.018447985651 - 0.0184677913857 - 0.0184876112018 - 0.0185074451095 - 0.0185272931186 - 0.0185471552393 - 0.0185670314816 - 0.0185869218555 - 0.0186068263711 - 0.0186267450383 - 0.0186466778674 - 0.0186666248683 - 0.0186865860511 - 0.0187065614259 - 0.0187265510028 - 0.0187465547919 - 0.0187665728033 - 0.0187866050471 - 0.0188066515335 - 0.0188267122724 - 0.0188467872742 - 0.0188668765489 - 0.0188869801067 - 0.0189070979577 - 0.0189272301121 - 0.0189473765801 - 0.0189675373718 - 0.0189877124974 - 0.0190079019672 - 0.0190281057912 - 0.0190483239798 - 0.0190685565431 - 0.0190888034913 - 0.0191090648348 - 0.0191293405836 - 0.0191496307481 - 0.0191699353385 - 0.0191902543651 - 0.0192105878381 - 0.0192309357677 - 0.0192512981644 - 0.0192716750383 - 0.0192920663998 - 0.0193124722591 - 0.0193328926266 - 0.0193533275125 - 0.0193737769273 - 0.0193942408812 - 0.0194147193845 - 0.0194352124477 - 0.019455720081 - 0.0194762422949 - 0.0194967790996 - 0.0195173305056 - 0.0195378965232 - 0.0195584771628 - 0.0195790724349 - 0.0195996823498 - 0.019620306918 - 0.0196409461498 - 0.0196616000557 - 0.0196822686461 - 0.0197029519315 - 0.0197236499223 - 0.0197443626289 - 0.0197650900619 - 0.0197858322316 - 0.0198065891486 - 0.0198273608234 - 0.0198481472664 - 0.0198689484882 - 0.0198897644993 - 0.0199105953101 - 0.0199314409311 - 0.0199523013731 - 0.0199731766463 - 0.0199940667615 - 0.0200149717292 - 0.0200358915598 - 0.0200568262641 - 0.0200777758525 - 0.0200987403356 - 0.0201197197241 - 0.0201407140285 - 0.0201617232594 - 0.0201827474275 - 0.0202037865433 - 0.0202248406176 - 0.0202459096608 - 0.0202669936838 - 0.020288092697 - 0.0203092067113 - 0.0203303357372 - 0.0203514797854 - 0.0203726388666 - 0.0203938129915 - 0.0204150021707 - 0.0204362064151 - 0.0204574257352 - 0.0204786601419 - 0.0204999096458 - 0.0205211742577 - 0.0205424539883 - 0.0205637488484 - 0.0205850588487 - 0.020606384 - 0.020627724313 - 0.0206490797986 - 0.0206704504675 - 0.0206918363305 - 0.0207132373984 - 0.0207346536821 - 0.0207560851924 - 0.02077753194 - 0.0207989939358 - 0.0208204711907 - 0.0208419637154 - 0.020863471521 - 0.0208849946181 - 0.0209065330178 - 0.0209280867308 - 0.0209496557681 - 0.0209712401406 - 0.0209928398591 - 0.0210144549346 - 0.0210360853779 - 0.0210577312001 - 0.021079392412 - 0.0211010690247 - 0.0211227610489 - 0.0211444684958 - 0.0211661913762 - 0.0211879297012 - 0.0212096834817 - 0.0212314527287 - 0.0212532374532 - 0.0212750376662 - 0.0212968533787 - 0.0213186846017 - 0.0213405313463 - 0.0213623936236 - 0.0213842714444 - 0.02140616482 - 0.0214280737613 - 0.0214499982795 - 0.0214719383855 - 0.0214938940905 - 0.0215158654056 - 0.0215378523419 - 0.0215598549104 - 0.0215818731223 - 0.0216039069887 - 0.0216259565208 - 0.0216480217297 - 0.0216701026265 - 0.0216921992223 - 0.0217143115284 - 0.0217364395559 - 0.021758583316 - 0.0217807428199 - 0.0218029180787 - 0.0218251091037 - 0.0218473159061 - 0.0218695384971 - 0.0218917768879 - 0.0219140310898 - 0.0219363011139 - 0.0219585869716 - 0.0219808886741 - 0.0220032062327 - 0.0220255396586 - 0.0220478889631 - 0.0220702541576 - 0.0220926352532 - 0.0221150322614 - 0.0221374451934 - 0.0221598740605 - 0.0221823188741 - 0.0222047796456 - 0.0222272563862 - 0.0222497491073 - 0.0222722578203 - 0.0222947825365 - 0.0223173232674 - 0.0223398800243 - 0.0223624528186 - 0.0223850416617 - 0.022407646565 - 0.0224302675399 - 0.022452904598 - 0.0224755577505 - 0.0224982270089 - 0.0225209123848 - 0.0225436138895 - 0.0225663315345 - 0.0225890653313 - 0.0226118152914 - 0.0226345814263 - 0.0226573637474 - 0.0226801622663 - 0.0227029769945 - 0.0227258079436 - 0.0227486551249 - 0.0227715185502 - 0.0227943982309 - 0.0228172941786 - 0.0228402064049 - 0.0228631349213 - 0.0228860797394 - 0.0229090408709 - 0.0229320183272 - 0.0229550121201 - 0.0229780222611 - 0.0230010487618 - 0.023024091634 - 0.0230471508891 - 0.0230702265389 - 0.0230933185951 - 0.0231164270692 - 0.0231395519731 - 0.0231626933182 - 0.0231858511164 - 0.0232090253794 - 0.0232322161187 - 0.0232554233463 - 0.0232786470737 - 0.0233018873127 - 0.0233251440751 - 0.0233484173725 - 0.0233717072169 - 0.0233950136198 - 0.0234183365931 - 0.0234416761486 - 0.0234650322981 - 0.0234884050533 - 0.0235117944261 - 0.0235352004282 - 0.0235586230716 - 0.023582062368 - 0.0236055183292 - 0.0236289909672 - 0.0236524802938 - 0.0236759863208 - 0.0236995090602 - 0.0237230485237 - 0.0237466047233 - 0.0237701776709 - 0.0237937673784 - 0.0238173738578 - 0.0238409971208 - 0.0238646371796 - 0.0238882940459 - 0.0239119677318 - 0.0239356582493 - 0.0239593656102 - 0.0239830898266 - 0.0240068309104 - 0.0240305888737 - 0.0240543637284 - 0.0240781554865 - 0.0241019641602 - 0.0241257897613 - 0.0241496323019 - 0.0241734917941 - 0.02419736825 - 0.0242212616815 - 0.0242451721008 - 0.0242690995199 - 0.024293043951 - 0.024317005406 - 0.0243409838972 - 0.0243649794366 - 0.0243889920364 - 0.0244130217086 - 0.0244370684655 - 0.0244611323191 - 0.0244852132816 - 0.0245093113653 - 0.0245334265822 - 0.0245575589445 - 0.0245817084645 - 0.0246058751543 - 0.0246300590261 - 0.0246542600922 - 0.0246784783647 - 0.024702713856 - 0.0247269665782 - 0.0247512365437 - 0.0247755237646 - 0.0247998282532 - 0.0248241500218 - 0.0248484890827 - 0.0248728454483 - 0.0248972191307 - 0.0249216101423 - 0.0249460184954 - 0.0249704442024 - 0.0249948872756 - 0.0250193477273 - 0.0250438255699 - 0.0250683208158 - 0.0250928334773 - 0.0251173635669 - 0.0251419110968 - 0.0251664760795 - 0.0251910585275 - 0.0252156584531 - 0.0252402758687 - 0.0252649107869 - 0.0252895632199 - 0.0253142331804 - 0.0253389206807 - 0.0253636257334 - 0.0253883483508 - 0.0254130885456 - 0.0254378463301 - 0.0254626217169 - 0.0254874147185 - 0.0255122253475 - 0.0255370536163 - 0.0255618995375 - 0.0255867631237 - 0.0256116443874 - 0.0256365433412 - 0.0256614599976 - 0.0256863943693 - 0.0257113464689 - 0.0257363163088 - 0.0257613039019 - 0.0257863092606 - 0.0258113323977 - 0.0258363733257 - 0.0258614320573 - 0.0258865086051 - 0.0259116029819 - 0.0259367152003 - 0.025961845273 - 0.0259869932126 - 0.026012159032 - 0.0260373427437 - 0.0260625443606 - 0.0260877638953 - 0.0261130013606 - 0.0261382567692 - 0.0261635301339 - 0.0261888214675 - 0.0262141307828 - 0.0262394580924 - 0.0262648034093 - 0.0262901667461 - 0.0263155481159 - 0.0263409475312 - 0.026366365005 - 0.0263918005502 - 0.0264172541795 - 0.0264427259059 - 0.0264682157421 - 0.0264937237011 - 0.0265192497958 - 0.026544794039 - 0.0265703564436 - 0.0265959370227 - 0.026621535789 - 0.0266471527555 - 0.0266727879352 - 0.0266984413409 - 0.0267241129858 - 0.0267498028826 - 0.0267755110445 - 0.0268012374844 - 0.0268269822152 - 0.0268527452501 - 0.0268785266019 - 0.0269043262838 - 0.0269301443088 - 0.0269559806898 - 0.02698183544 - 0.0270077085724 - 0.0270336001001 - 0.0270595100362 - 0.0270854383937 - 0.0271113851857 - 0.0271373504255 - 0.0271633341259 - 0.0271893363003 - 0.0272153569617 - 0.0272413961233 - 0.0272674537982 - 0.0272935299996 - 0.0273196247407 - 0.0273457380345 - 0.0273718698945 - 0.0273980203336 - 0.0274241893653 - 0.0274503770025 - 0.0274765832587 - 0.027502808147 - 0.0275290516806 - 0.0275553138729 - 0.0275815947371 - 0.0276078942865 - 0.0276342125343 - 0.0276605494939 - 0.0276869051785 - 0.0277132796015 - 0.0277396727762 - 0.0277660847159 - 0.027792515434 - 0.0278189649438 - 0.0278454332587 - 0.027871920392 - 0.0278984263571 - 0.0279249511675 - 0.0279514948364 - 0.0279780573774 - 0.0280046388039 - 0.0280312391292 - 0.0280578583668 - 0.0280844965301 - 0.0281111536327 - 0.0281378296879 - 0.0281645247093 - 0.0281912387103 - 0.0282179717044 - 0.0282447237051 - 0.028271494726 - 0.0282982847806 - 0.0283250938823 - 0.0283519220448 - 0.0283787692816 - 0.0284056356063 - 0.0284325210323 - 0.0284594255734 - 0.028486349243 - 0.0285132920549 - 0.0285402540225 - 0.0285672351596 - 0.0285942354798 - 0.0286212549966 - 0.0286482937238 - 0.0286753516749 - 0.0287024288637 - 0.0287295253039 - 0.0287566410091 - 0.0287837759931 - 0.0288109302694 - 0.0288381038519 - 0.0288652967543 - 0.0288925089903 - 0.0289197405737 - 0.0289469915182 - 0.0289742618376 - 0.0290015515456 - 0.029028860656 - 0.0290561891827 - 0.0290835371395 - 0.0291109045401 - 0.0291382913983 - 0.0291656977281 - 0.0291931235432 - 0.0292205688576 - 0.029248033685 - 0.0292755180394 - 0.0293030219346 - 0.0293305453845 - 0.029358088403 - 0.0293856510041 - 0.0294132332017 - 0.0294408350096 - 0.0294684564419 - 0.0294960975125 - 0.0295237582353 - 0.0295514386243 - 0.0295791386936 - 0.029606858457 - 0.0296345979287 - 0.0296623571226 - 0.0296901360527 - 0.029717934733 - 0.0297457531777 - 0.0297735914008 - 0.0298014494162 - 0.0298293272382 - 0.0298572248807 - 0.0298851423579 - 0.0299130796839 - 0.0299410368728 - 0.0299690139387 - 0.0299970108957 - 0.030025027758 - 0.0300530645397 - 0.030081121255 - 0.0301091979181 - 0.0301372945431 - 0.0301654111443 - 0.0301935477358 - 0.0302217043319 - 0.0302498809468 - 0.0302780775947 - 0.0303062942898 - 0.0303345310464 - 0.0303627878788 - 0.0303910648013 - 0.0304193618281 - 0.0304476789735 - 0.0304760162519 - 0.0305043736775 - 0.0305327512646 - 0.0305611490277 - 0.030589566981 - 0.0306180051389 - 0.0306464635157 - 0.0306749421259 - 0.0307034409839 - 0.0307319601039 - 0.0307604995005 - 0.030789059188 - 0.0308176391809 - 0.0308462394937 - 0.0308748601406 - 0.0309035011363 - 0.0309321624951 - 0.0309608442316 - 0.0309895463603 - 0.0310182688956 - 0.0310470118521 - 0.0310757752442 - 0.0311045590865 - 0.0311333633936 - 0.0311621881799 - 0.0311910334601 - 0.0312198992487 - 0.0312487855604 - 0.0312776924096 - 0.031306619811 - 0.0313355677792 - 0.0313645363289 - 0.0313935254746 - 0.031422535231 - 0.0314515656128 - 0.0314806166346 - 0.0315096883111 - 0.031538780657 - 0.031567893687 - 0.0315970274158 - 0.031626181858 - 0.0316553570285 - 0.031684552942 - 0.0317137696132 - 0.0317430070568 - 0.0317722652877 - 0.0318015443206 - 0.0318308441704 - 0.0318601648517 - 0.0318895063794 - 0.0319188687684 - 0.0319482520335 - 0.0319776561895 - 0.0320070812513 - 0.0320365272337 - 0.0320659941516 - 0.0320954820199 - 0.0321249908535 - 0.0321545206673 - 0.0321840714762 - 0.0322136432951 - 0.032243236139 - 0.0322728500229 - 0.0323024849616 - 0.0323321409701 - 0.0323618180636 - 0.0323915162568 - 0.0324212355648 - 0.0324509760027 - 0.0324807375855 - 0.0325105203281 - 0.0325403242457 - 0.0325701493533 - 0.0325999956659 - 0.0326298631987 - 0.0326597519667 - 0.032689661985 - 0.0327195932688 - 0.0327495458331 - 0.0327795196931 - 0.0328095148638 - 0.0328395313606 - 0.0328695691985 - 0.0328996283927 - 0.0329297089584 - 0.0329598109108 - 0.0329899342651 - 0.0330200790364 - 0.0330502452401 - 0.0330804328914 - 0.0331106420055 - 0.0331408725977 - 0.0331711246833 - 0.0332013982774 - 0.0332316933955 - 0.0332620100528 - 0.0332923482647 - 0.0333227080464 - 0.0333530894133 - 0.0333834923808 - 0.0334139169642 - 0.0334443631789 - 0.0334748310402 - 0.0335053205635 - 0.0335358317643 - 0.033566364658 - 0.0335969192599 - 0.0336274955856 - 0.0336580936504 - 0.0336887134698 - 0.0337193550593 - 0.0337500184344 - 0.0337807036105 - 0.0338114106032 - 0.033842139428 - 0.0338728901003 - 0.0339036626357 - 0.0339344570498 - 0.0339652733582 - 0.0339961115763 - 0.0340269717197 - 0.0340578538041 - 0.0340887578451 - 0.0341196838582 - 0.0341506318591 - 0.0341816018634 - 0.0342125938868 - 0.0342436079449 - 0.0342746440534 - 0.0343057022279 - 0.0343367824842 - 0.0343678848379 - 0.0343990093048 - 0.0344301559005 - 0.0344613246409 - 0.0344925155416 - 0.0345237286184 - 0.0345549638871 - 0.0345862213635 - 0.0346175010633 - 0.0346488030023 - 0.0346801271965 - 0.0347114736614 - 0.0347428424131 - 0.0347742334674 - 0.0348056468401 - 0.0348370825471 - 0.0348685406042 - 0.0349000210274 - 0.0349315238325 - 0.0349630490355 - 0.0349945966523 - 0.0350261666988 - 0.035057759191 - 0.0350893741449 - 0.0351210115763 - 0.0351526715013 - 0.0351843539359 - 0.0352160588961 - 0.0352477863979 - 0.0352795364573 - 0.0353113090904 - 0.0353431043132 - 0.0353749221417 - 0.0354067625921 - 0.0354386256805 - 0.0354705114228 - 0.0355024198353 - 0.035534350934 - 0.0355663047351 - 0.0355982812547 - 0.035630280509 - 0.0356623025142 - 0.0356943472863 - 0.0357264148416 - 0.0357585051964 - 0.0357906183667 - 0.0358227543689 - 0.0358549132191 - 0.0358870949336 - 0.0359192995287 - 0.0359515270206 - 0.0359837774256 - 0.03601605076 - 0.0360483470401 - 0.0360806662823 - 0.0361130085027 - 0.0361453737179 - 0.0361777619441 - 0.0362101731976 - 0.0362426074949 - 0.0362750648524 - 0.0363075452864 - 0.0363400488133 - 0.0363725754496 - 0.0364051252117 - 0.036437698116 - 0.036470294179 - 0.0365029134172 - 0.036535555847 - 0.0365682214849 - 0.0366009103474 - 0.0366336224511 - 0.0366663578124 - 0.036699116448 - 0.0367318983742 - 0.0367647036078 - 0.0367975321652 - 0.0368303840631 - 0.036863259318 - 0.0368961579466 - 0.0369290799654 - 0.0369620253912 - 0.0369949942405 - 0.03702798653 - 0.0370610022763 - 0.0370940414962 - 0.0371271042063 - 0.0371601904234 - 0.0371933001641 - 0.0372264334451 - 0.0372595902833 - 0.0372927706953 - 0.037325974698 - 0.037359202308 - 0.0373924535422 - 0.0374257284173 - 0.0374590269503 - 0.0374923491578 - 0.0375256950568 - 0.037559064664 - 0.0375924579964 - 0.0376258750707 - 0.037659315904 - 0.037692780513 - 0.0377262689146 - 0.0377597811259 - 0.0377933171637 - 0.0378268770449 - 0.0378604607866 - 0.0378940684056 - 0.037927699919 - 0.0379613553437 - 0.0379950346967 - 0.0380287379951 - 0.0380624652559 - 0.0380962164961 - 0.0381299917327 - 0.0381637909829 - 0.0381976142637 - 0.0382314615921 - 0.0382653329853 - 0.0382992284604 - 0.0383331480346 - 0.0383670917248 - 0.0384010595484 - 0.0384350515224 - 0.038469067664 - 0.0385031079904 - 0.0385371725189 - 0.0385712612665 - 0.0386053742505 - 0.0386395114882 - 0.0386736729968 - 0.0387078587936 - 0.0387420688958 - 0.0387763033206 - 0.0388105620855 - 0.0388448452077 - 0.0388791527045 - 0.0389134845932 - 0.0389478408913 - 0.038982221616 - 0.0390166267847 - 0.0390510564147 - 0.0390855105236 - 0.0391199891287 - 0.0391544922473 - 0.039189019897 - 0.0392235720952 - 0.0392581488593 - 0.0392927502068 - 0.0393273761551 - 0.0393620267218 - 0.0393967019244 - 0.0394314017804 - 0.0394661263073 - 0.0395008755226 - 0.0395356494439 - 0.0395704480888 - 0.0396052714748 - 0.0396401196196 - 0.0396749925407 - 0.0397098902558 - 0.0397448127824 - 0.0397797601383 - 0.0398147323411 - 0.0398497294083 - 0.0398847513579 - 0.0399197982073 - 0.0399548699743 - 0.0399899666767 - 0.0400250883321 - 0.0400602349583 - 0.0400954065731 - 0.0401306031942 - 0.0401658248394 - 0.0402010715265 - 0.0402363432732 - 0.0402716400975 - 0.0403069620172 - 0.04034230905 - 0.0403776812138 - 0.0404130785266 - 0.0404485010061 - 0.0404839486704 - 0.0405194215372 - 0.0405549196245 - 0.0405904429502 - 0.0406259915324 - 0.0406615653888 - 0.0406971645376 - 0.0407327889967 - 0.040768438784 - 0.0408041139176 - 0.0408398144156 - 0.0408755402959 - 0.0409112915766 - 0.0409470682757 - 0.0409828704113 - 0.0410186980016 - 0.0410545510646 - 0.0410904296184 - 0.0411263336811 - 0.0411622632709 - 0.0411982184059 - 0.0412341991043 - 0.0412702053843 - 0.041306237264 - 0.0413422947617 - 0.0413783778955 - 0.0414144866837 - 0.0414506211446 - 0.0414867812963 - 0.0415229671572 - 0.0415591787456 - 0.0415954160796 - 0.0416316791777 - 0.0416679680581 - 0.0417042827392 - 0.0417406232393 - 0.0417769895767 - 0.04181338177 - 0.0418497998373 - 0.0418862437972 - 0.041922713668 - 0.0419592094681 - 0.0419957312161 - 0.0420322789303 - 0.0420688526291 - 0.0421054523312 - 0.0421420780549 - 0.0421787298188 - 0.0422154076413 - 0.0422521115411 - 0.0422888415366 - 0.0423255976464 - 0.0423623798891 - 0.0423991882832 - 0.0424360228473 - 0.0424728836001 - 0.0425097705602 - 0.0425466837461 - 0.0425836231766 - 0.0426205888703 - 0.0426575808459 - 0.042694599122 - 0.0427316437174 - 0.0427687146507 - 0.0428058119408 - 0.0428429356063 - 0.042880085666 - 0.0429172621386 - 0.042954465043 - 0.0429916943978 - 0.0430289502221 - 0.0430662325345 - 0.0431035413538 - 0.043140876699 - 0.0431782385889 - 0.0432156270423 - 0.0432530420782 - 0.0432904837155 - 0.043327951973 - 0.0433654468696 - 0.0434029684245 - 0.0434405166564 - 0.0434780915843 - 0.0435156932273 - 0.0435533216043 - 0.0435909767343 - 0.0436286586363 - 0.0436663673295 - 0.0437041028328 - 0.0437418651653 - 0.043779654346 - 0.0438174703941 - 0.0438553133287 - 0.0438931831688 - 0.0439310799336 - 0.0439690036423 - 0.044006954314 - 0.0440449319679 - 0.0440829366231 - 0.0441209682989 - 0.0441590270145 - 0.044197112789 - 0.0442352256418 - 0.044273365592 - 0.044311532659 - 0.044349726862 - 0.0443879482204 - 0.0444261967533 - 0.0444644724803 - 0.0445027754205 - 0.0445411055933 - 0.0445794630181 - 0.0446178477143 - 0.0446562597012 - 0.0446946989983 - 0.044733165625 - 0.0447716596007 - 0.0448101809449 - 0.0448487296769 - 0.0448873058163 - 0.0449259093826 - 0.0449645403953 - 0.0450031988739 - 0.0450418848378 - 0.0450805983068 - 0.0451193393002 - 0.0451581078377 - 0.0451969039389 - 0.0452357276233 - 0.0452745789106 - 0.0453134578204 - 0.0453523643723 - 0.045391298586 - 0.0454302604811 - 0.0454692500774 - 0.0455082673945 - 0.0455473124522 - 0.0455863852701 - 0.045625485868 - 0.0456646142657 - 0.0457037704829 - 0.0457429545393 - 0.0457821664549 - 0.0458214062493 - 0.0458606739425 - 0.0458999695542 - 0.0459392931043 - 0.0459786446127 - 0.0460180240992 - 0.0460574315838 - 0.0460968670863 - 0.0461363306266 - 0.0461758222248 - 0.0462153419007 - 0.0462548896742 - 0.0462944655655 - 0.0463340695945 - 0.0463737017811 - 0.0464133621454 - 0.0464530507075 - 0.0464927674873 - 0.046532512505 - 0.0465722857806 - 0.0466120873342 - 0.0466519171859 - 0.0466917753558 - 0.0467316618641 - 0.046771576731 - 0.0468115199765 - 0.0468514916208 - 0.0468914916842 - 0.0469315201869 - 0.046971577149 - 0.0470116625909 - 0.0470517765327 - 0.0470919189947 - 0.0471320899972 - 0.0471722895604 - 0.0472125177048 - 0.0472527744506 - 0.0472930598181 - 0.0473333738278 - 0.0473737164999 - 0.0474140878548 - 0.0474544879129 - 0.0474949166947 - 0.0475353742206 - 0.047575860511 - 0.0476163755863 - 0.047656919467 - 0.0476974921736 - 0.0477380937266 - 0.0477787241465 - 0.0478193834538 - 0.0478600716691 - 0.0479007888129 - 0.0479415349058 - 0.0479823099683 - 0.0480231140211 - 0.0480639470848 - 0.04810480918 - 0.0481457003273 - 0.0481866205474 - 0.0482275698609 - 0.0482685482886 - 0.0483095558512 - 0.0483505925693 - 0.0483916584637 - 0.0484327535552 - 0.0484738778644 - 0.0485150314123 - 0.0485562142194 - 0.0485974263067 - 0.0486386676951 - 0.0486799384052 - 0.0487212384579 - 0.0487625678742 - 0.0488039266749 - 0.0488453148808 - 0.048886732513 - 0.0489281795923 - 0.0489696561396 - 0.0490111621759 - 0.0490526977222 - 0.0490942627994 - 0.0491358574286 - 0.0491774816308 - 0.0492191354269 - 0.049260818838 - 0.0493025318852 - 0.0493442745896 - 0.0493860469722 - 0.0494278490541 - 0.0494696808565 - 0.0495115424005 - 0.0495534337072 - 0.0495953547978 - 0.0496373056934 - 0.0496792864153 - 0.0497212969847 - 0.0497633374227 - 0.0498054077507 - 0.0498475079898 - 0.0498896381613 - 0.0499317982866 - 0.0499739883869 - 0.0500162084835 - 0.0500584585978 - 0.050100738751 - 0.0501430489646 - 0.0501853892599 - 0.0502277596584 - 0.0502701601813 - 0.0503125908502 - 0.0503550516864 - 0.0503975427114 - 0.0504400639468 - 0.0504826154138 - 0.0505251971342 - 0.0505678091292 - 0.0506104514206 - 0.0506531240298 - 0.0506958269784 - 0.0507385602879 - 0.0507813239799 - 0.0508241180761 - 0.050866942598 - 0.0509097975674 - 0.0509526830057 - 0.0509955989347 - 0.0510385453762 - 0.0510815223517 - 0.0511245298829 - 0.0511675679917 - 0.0512106366997 - 0.0512537360287 - 0.0512968660005 - 0.0513400266368 - 0.0513832179595 - 0.0514264399903 - 0.0514696927512 - 0.0515129762639 - 0.0515562905503 - 0.0515996356323 - 0.0516430115318 - 0.0516864182708 - 0.051729855871 - 0.0517733243545 - 0.0518168237433 - 0.0518603540592 - 0.0519039153244 - 0.0519475075607 - 0.0519911307903 - 0.0520347850351 - 0.0520784703172 - 0.0521221866586 - 0.0521659340816 - 0.052209712608 - 0.0522535222602 - 0.0522973630601 - 0.05234123503 - 0.0523851381919 - 0.0524290725682 - 0.0524730381809 - 0.0525170350523 - 0.0525610632045 - 0.05260512266 - 0.0526492134408 - 0.0526933355693 - 0.0527374890678 - 0.0527816739585 - 0.0528258902638 - 0.052870138006 - 0.0529144172075 - 0.0529587278906 - 0.0530030700777 - 0.0530474437912 - 0.0530918490536 - 0.0531362858872 - 0.0531807543146 - 0.0532252543581 - 0.0532697860402 - 0.0533143493835 - 0.0533589444105 - 0.0534035711436 - 0.0534482296054 - 0.0534929198186 - 0.0535376418055 - 0.053582395589 - 0.0536271811914 - 0.0536719986356 - 0.0537168479441 - 0.0537617291395 - 0.0538066422446 - 0.0538515872819 - 0.0538965642744 - 0.0539415732445 - 0.0539866142152 - 0.0540316872091 - 0.054076792249 - 0.0541219293577 - 0.0541670985579 - 0.0542122998726 - 0.0542575333245 - 0.0543027989365 - 0.0543480967315 - 0.0543934267323 - 0.0544387889618 - 0.0544841834429 - 0.0545296101987 - 0.0545750692519 - 0.0546205606257 - 0.0546660843429 - 0.0547116404265 - 0.0547572288997 - 0.0548028497853 - 0.0548485031065 - 0.0548941888862 - 0.0549399071477 - 0.0549856579139 - 0.0550314412081 - 0.0550772570532 - 0.0551231054725 - 0.0551689864891 - 0.0552149001262 - 0.055260846407 - 0.0553068253547 - 0.0553528369925 - 0.0553988813436 - 0.0554449584314 - 0.0554910682791 - 0.0555372109099 - 0.0555833863473 - 0.0556295946145 - 0.0556758357348 - 0.0557221097316 - 0.0557684166284 - 0.0558147564484 - 0.0558611292151 - 0.055907534952 - 0.0559539736823 - 0.0560004454298 - 0.0560469502177 - 0.0560934880695 - 0.0561400590089 - 0.0561866630593 - 0.0562333002442 - 0.0562799705873 - 0.056326674112 - 0.056373410842 - 0.0564201808009 - 0.0564669840123 - 0.0565138204999 - 0.0565606902873 - 0.0566075933981 - 0.0566545298562 - 0.0567014996851 - 0.0567485029087 - 0.0567955395506 - 0.0568426096346 - 0.0568897131845 - 0.0569368502241 - 0.0569840207773 - 0.0570312248677 - 0.0570784625193 - 0.0571257337559 - 0.0571730386015 - 0.0572203770799 - 0.0572677492149 - 0.0573151550307 - 0.057362594551 - 0.0574100677998 - 0.0574575748013 - 0.0575051155792 - 0.0575526901577 - 0.0576002985608 - 0.0576479408125 - 0.0576956169369 - 0.0577433269581 - 0.0577910709001 - 0.0578388487872 - 0.0578866606433 - 0.0579345064928 - 0.0579823863597 - 0.0580303002683 - 0.0580782482426 - 0.0581262303071 - 0.0581742464858 - 0.0582222968031 - 0.0582703812832 - 0.0583184999504 - 0.058366652829 - 0.0584148399434 - 0.0584630613179 - 0.0585113169768 - 0.0585596069445 - 0.0586079312454 - 0.0586562899039 - 0.0587046829445 - 0.0587531103916 - 0.0588015722696 - 0.0588500686031 - 0.0588985994165 - 0.0589471647343 - 0.0589957645811 - 0.0590443989814 - 0.0590930679599 - 0.059141771541 - 0.0591905097494 - 0.0592392826096 - 0.0592880901465 - 0.0593369323845 - 0.0593858093483 - 0.0594347210628 - 0.0594836675524 - 0.0595326488421 - 0.0595816649565 - 0.0596307159203 - 0.0596798017585 - 0.0597289224957 - 0.0597780781567 - 0.0598272687665 - 0.0598764943498 - 0.0599257549315 - 0.0599750505365 - 0.0600243811897 - 0.060073746916 - 0.0601231477404 - 0.0601725836878 - 0.0602220547831 - 0.0602715610514 - 0.0603211025177 - 0.060370679207 - 0.0604202911444 - 0.0604699383548 - 0.0605196208634 - 0.0605693386953 - 0.0606190918756 - 0.0606688804294 - 0.0607187043819 - 0.0607685637582 - 0.0608184585835 - 0.0608683888831 - 0.0609183546822 - 0.0609683560059 - 0.0610183928796 - 0.0610684653284 - 0.0611185733779 - 0.0611687170531 - 0.0612188963795 - 0.0612691113824 - 0.0613193620872 - 0.0613696485192 - 0.0614199707039 - 0.0614703286666 - 0.0615207224329 - 0.0615711520281 - 0.0616216174778 - 0.0616721188074 - 0.0617226560424 - 0.0617732292084 - 0.061823838331 - 0.0618744834356 - 0.0619251645479 - 0.0619758816934 - 0.0620266348978 - 0.0620774241868 - 0.0621282495859 - 0.0621791111209 - 0.0622300088174 - 0.0622809427012 - 0.0623319127979 - 0.0623829191334 - 0.0624339617334 - 0.0624850406236 - 0.0625361558299 - 0.0625873073781 - 0.0626384952941 - 0.0626897196036 - 0.0627409803326 - 0.062792277507 - 0.0628436111526 - 0.0628949812955 - 0.0629463879615 - 0.0629978311766 - 0.0630493109668 - 0.0631008273581 - 0.0631523803766 - 0.0632039700482 - 0.0632555963991 - 0.0633072594552 - 0.0633589592428 - 0.0634106957879 - 0.0634624691167 - 0.0635142792552 - 0.0635661262298 - 0.0636180100665 - 0.0636699307916 - 0.0637218884313 - 0.0637738830118 - 0.0638259145595 - 0.0638779831006 - 0.0639300886613 - 0.0639822312681 - 0.0640344109472 - 0.0640866277251 - 0.064138881628 - 0.0641911726824 - 0.0642435009148 - 0.0642958663514 - 0.0643482690189 - 0.0644007089436 - 0.0644531861521 - 0.0645057006708 - 0.0645582525262 - 0.0646108417451 - 0.0646634683538 - 0.0647161323789 - 0.0647688338472 - 0.0648215727851 - 0.0648743492194 - 0.0649271631767 - 0.0649800146837 - 0.065032903767 - 0.0650858304534 - 0.0651387947697 - 0.0651917967425 - 0.0652448363986 - 0.065297913765 - 0.0653510288682 - 0.0654041817353 - 0.0654573723929 - 0.0655106008681 - 0.0655638671877 - 0.0656171713786 - 0.0656705134677 - 0.0657238934819 - 0.0657773114483 - 0.0658307673938 - 0.0658842613454 - 0.0659377933302 - 0.0659913633751 - 0.0660449715073 - 0.0660986177537 - 0.0661523021416 - 0.0662060246981 - 0.0662597854502 - 0.0663135844251 - 0.0663674216501 - 0.0664212971522 - 0.0664752109587 - 0.0665291630969 - 0.066583153594 - 0.0666371824773 - 0.066691249774 - 0.0667453555115 - 0.0667994997171 - 0.0668536824182 - 0.0669079036421 - 0.0669621634162 - 0.0670164617679 - 0.0670707987246 - 0.0671251743139 - 0.0671795885631 - 0.0672340414998 - 0.0672885331515 - 0.0673430635456 - 0.0673976327097 - 0.0674522406715 - 0.0675068874584 - 0.0675615730981 - 0.0676162976182 - 0.0676710610463 - 0.0677258634102 - 0.0677807047374 - 0.0678355850558 - 0.067890504393 - 0.0679454627767 - 0.0680004602347 - 0.0680554967949 - 0.0681105724849 - 0.0681656873327 - 0.068220841366 - 0.0682760346127 - 0.0683312671008 - 0.068386538858 - 0.0684418499124 - 0.0684972002919 - 0.0685525900243 - 0.0686080191378 - 0.0686634876602 - 0.0687189956197 - 0.0687745430442 - 0.0688301299619 - 0.0688857564007 - 0.0689414223889 - 0.0689971279544 - 0.0690528731255 - 0.0691086579303 - 0.069164482397 - 0.0692203465538 - 0.0692762504289 - 0.0693321940505 - 0.069388177447 - 0.0694442006465 - 0.0695002636774 - 0.069556366568 - 0.0696125093466 - 0.0696686920417 - 0.0697249146815 - 0.0697811772945 - 0.0698374799091 - 0.0698938225538 - 0.0699502052569 - 0.0700066280471 - 0.0700630909527 - 0.0701195940023 - 0.0701761372245 - 0.0702327206478 - 0.0702893443007 - 0.070346008212 - 0.0704027124102 - 0.0704594569239 - 0.0705162417819 - 0.0705730670127 - 0.0706299326452 - 0.070686838708 - 0.0707437852299 - 0.0708007722396 - 0.070857799766 - 0.0709148678378 - 0.0709719764839 - 0.0710291257331 - 0.0710863156143 - 0.0711435461563 - 0.0712008173881 - 0.0712581293386 - 0.0713154820368 - 0.0713728755116 - 0.0714303097921 - 0.0714877849072 - 0.0715453008859 - 0.0716028577573 - 0.0716604555506 - 0.0717180942947 - 0.0717757740189 - 0.0718334947521 - 0.0718912565237 - 0.0719490593628 - 0.0720069032985 - 0.0720647883601 - 0.0721227145768 - 0.0721806819779 - 0.0722386905927 - 0.0722967404505 - 0.0723548315805 - 0.0724129640122 - 0.072471137775 - 0.0725293528981 - 0.0725876094109 - 0.0726459073431 - 0.0727042467239 - 0.0727626275828 - 0.0728210499494 - 0.0728795138531 - 0.0729380193234 - 0.07299656639 - 0.0730551550825 - 0.0731137854303 - 0.0731724574631 - 0.0732311712106 - 0.0732899267023 - 0.0733487239681 - 0.0734075630376 - 0.0734664439404 - 0.0735253667064 - 0.0735843313654 - 0.073643337947 - 0.0737023864811 - 0.0737614769976 - 0.0738206095263 - 0.073879784097 - 0.0739390007397 - 0.0739982594842 - 0.0740575603605 - 0.0741169033986 - 0.0741762886283 - 0.0742357160798 - 0.0742951857831 - 0.0743546977681 - 0.0744142520649 - 0.0744738487037 - 0.0745334877145 - 0.0745931691274 - 0.0746528929727 - 0.0747126592804 - 0.0747724680808 - 0.074832319404 - 0.0748922132804 - 0.0749521497401 - 0.0750121288134 - 0.0750721505307 - 0.0751322149222 - 0.0751923220183 - 0.0752524718494 - 0.0753126644458 - 0.0753728998379 - 0.0754331780562 - 0.0754934991312 - 0.0755538630932 - 0.0756142699728 - 0.0756747198004 - 0.0757352126067 - 0.0757957484222 - 0.0758563272775 - 0.0759169492031 - 0.0759776142297 - 0.0760383223879 - 0.0760990737084 - 0.076159868222 - 0.0762207059592 - 0.0762815869508 - 0.0763425112276 - 0.0764034788203 - 0.0764644897598 - 0.0765255440769 - 0.0765866418024 - 0.0766477829671 - 0.076708967602 - 0.0767701957379 - 0.0768314674059 - 0.0768927826368 - 0.0769541414616 - 0.0770155439113 - 0.0770769900169 - 0.0771384798095 - 0.0772000133201 - 0.0772615905798 - 0.0773232116197 - 0.077384876471 - 0.0774465851647 - 0.0775083377321 - 0.0775701342043 - 0.0776319746126 - 0.0776938589883 - 0.0777557873624 - 0.0778177597664 - 0.0778797762316 - 0.0779418367893 - 0.0780039414707 - 0.0780660903074 - 0.0781282833306 - 0.0781905205719 - 0.0782528020626 - 0.0783151278342 - 0.0783774979182 - 0.078439912346 - 0.0785023711493 - 0.0785648743596 - 0.0786274220084 - 0.0786900141274 - 0.0787526507481 - 0.0788153319021 - 0.0788780576213 - 0.0789408279372 - 0.0790036428815 - 0.079066502486 - 0.0791294067825 - 0.0791923558026 - 0.0792553495783 - 0.0793183881413 - 0.0793814715234 - 0.0794445997566 - 0.0795077728727 - 0.0795709909036 - 0.0796342538813 - 0.0796975618377 - 0.0797609148048 - 0.0798243128146 - 0.0798877558992 - 0.0799512440905 - 0.0800147774206 - 0.0800783559217 - 0.0801419796259 - 0.0802056485652 - 0.0802693627719 - 0.0803331222781 - 0.0803969271161 - 0.080460777318 - 0.0805246729162 - 0.0805886139428 - 0.0806526004303 - 0.0807166324109 - 0.0807807099169 - 0.0808448329808 - 0.0809090016349 - 0.0809732159117 - 0.0810374758435 - 0.0811017814629 - 0.0811661328023 - 0.0812305298942 - 0.0812949727711 - 0.0813594614657 - 0.0814239960105 - 0.081488576438 - 0.0815532027809 - 0.0816178750719 - 0.0816825933436 - 0.0817473576287 - 0.0818121679599 - 0.08187702437 - 0.0819419268917 - 0.0820068755578 - 0.0820718704011 - 0.0821369114544 - 0.0822019987507 - 0.0822671323227 - 0.0823323122034 - 0.0823975384257 - 0.0824628110226 - 0.0825281300269 - 0.0825934954718 - 0.0826589073902 - 0.0827243658152 - 0.0827898707799 - 0.0828554223172 - 0.0829210204605 - 0.0829866652426 - 0.083052356697 - 0.0831180948566 - 0.0831838797548 - 0.0832497114247 - 0.0833155898996 - 0.0833815152128 - 0.0834474873977 - 0.0835135064874 - 0.0835795725154 - 0.083645685515 - 0.0837118455196 - 0.0837780525627 - 0.0838443066777 - 0.0839106078981 - 0.0839769562573 - 0.0840433517888 - 0.0841097945263 - 0.0841762845033 - 0.0842428217533 - 0.0843094063099 - 0.0843760382069 - 0.0844427174778 - 0.0845094441563 - 0.0845762182762 - 0.0846430398712 - 0.084709908975 - 0.0847768256214 - 0.0848437898442 - 0.0849108016772 - 0.0849778611543 - 0.0850449683094 - 0.0851121231763 - 0.085179325789 - 0.0852465761815 - 0.0853138743876 - 0.0853812204414 - 0.0854486143769 - 0.0855160562282 - 0.0855835460293 - 0.0856510838143 - 0.0857186696173 - 0.0857863034725 - 0.085853985414 - 0.085921715476 - 0.0859894936928 - 0.0860573200985 - 0.0861251947275 - 0.0861931176139 - 0.0862610887922 - 0.0863291082966 - 0.0863971761616 - 0.0864652924215 - 0.0865334571106 - 0.0866016702636 - 0.0866699319147 - 0.0867382420985 - 0.0868066008494 - 0.0868750082021 - 0.0869434641911 - 0.0870119688509 - 0.0870805222161 - 0.0871491243215 - 0.0872177752015 - 0.087286474891 - 0.0873552234246 - 0.0874240208371 - 0.0874928671631 - 0.0875617624375 - 0.0876307066951 - 0.0876996999707 - 0.0877687422991 - 0.0878378337152 - 0.087906974254 - 0.0879761639503 - 0.0880454028392 - 0.0881146909555 - 0.0881840283343 - 0.0882534150105 - 0.0883228510194 - 0.0883923363958 - 0.088461871175 - 0.088531455392 - 0.088601089082 - 0.0886707722802 - 0.0887405050218 - 0.0888102873419 - 0.0888801192759 - 0.088950000859 - 0.0890199321265 - 0.0890899131138 - 0.0891599438562 - 0.089230024389 - 0.0893001547477 - 0.0893703349677 - 0.0894405650844 - 0.0895108451334 - 0.0895811751501 - 0.08965155517 - 0.0897219852287 - 0.0897924653618 - 0.0898629956049 - 0.0899335759935 - 0.0900042065635 - 0.0900748873503 - 0.0901456183898 - 0.0902163997177 - 0.0902872313696 - 0.0903581133815 - 0.0904290457891 - 0.0905000286282 - 0.0905710619347 - 0.0906421457444 - 0.0907132800934 - 0.0907844650174 - 0.0908557005526 - 0.0909269867347 - 0.0909983236 - 0.0910697111843 - 0.0911411495238 - 0.0912126386545 - 0.0912841786126 - 0.0913557694341 - 0.0914274111554 - 0.0914991038124 - 0.0915708474415 - 0.0916426420789 - 0.0917144877609 - 0.0917863845237 - 0.0918583324037 - 0.0919303314372 - 0.0920023816606 - 0.0920744831103 - 0.0921466358227 - 0.0922188398342 - 0.0922910951813 - 0.0923634019006 - 0.0924357600285 - 0.0925081696015 - 0.0925806306564 - 0.0926531432296 - 0.0927257073578 - 0.0927983230777 - 0.0928709904259 - 0.0929437094392 - 0.0930164801542 - 0.0930893026078 - 0.0931621768367 - 0.0932351028777 - 0.0933080807677 - 0.0933811105435 - 0.093454192242 - 0.0935273259002 - 0.0936005115549 - 0.0936737492432 - 0.093747039002 - 0.0938203808684 - 0.0938937748794 - 0.0939672210721 - 0.0940407194836 - 0.094114270151 - 0.0941878731114 - 0.0942615284021 - 0.0943352360603 - 0.0944089961231 - 0.0944828086279 - 0.0945566736119 - 0.0946305911124 - 0.0947045611668 - 0.0947785838124 - 0.0948526590867 - 0.094926787027 - 0.0950009676708 - 0.0950752010556 - 0.0951494872189 - 0.0952238261981 - 0.0952982180309 - 0.0953726627548 - 0.0954471604074 - 0.0955217110263 - 0.0955963146493 - 0.0956709713139 - 0.095745681058 - 0.0958204439192 - 0.0958952599353 - 0.0959701291442 - 0.0960450515835 - 0.0961200272912 - 0.0961950563052 - 0.0962701386633 - 0.0963452744034 - 0.0964204635636 - 0.0964957061818 - 0.0965710022959 - 0.0966463519442 - 0.0967217551645 - 0.096797211995 - 0.0968727224738 - 0.0969482866391 - 0.097023904529 - 0.0970995761817 - 0.0971753016355 - 0.0972510809286 - 0.0973269140992 - 0.0974028011857 - 0.0974787422264 - 0.0975547372597 - 0.0976307863239 - 0.0977068894576 - 0.097783046699 - 0.0978592580867 - 0.0979355236592 - 0.0980118434551 - 0.0980882175127 - 0.0981646458709 - 0.098241128568 - 0.0983176656429 - 0.098394257134 - 0.0984709030802 - 0.0985476035202 - 0.0986243584926 - 0.0987011680364 - 0.0987780321901 - 0.0988549509928 - 0.0989319244832 - 0.0990089527002 - 0.0990860356827 - 0.0991631734698 - 0.0992403661002 - 0.0993176136131 - 0.0993949160474 - 0.0994722734423 - 0.0995496858367 - 0.0996271532697 - 0.0997046757806 - 0.0997822534085 - 0.0998598861925 - 0.0999375741718 - 0.100015317386 - 0.100093115874 - 0.100170969675 - 0.100248878828 - 0.100326843374 - 0.10040486335 - 0.100482938798 - 0.100561069755 - 0.100639256262 - 0.100717498358 - 0.100795796083 - 0.100874149475 - 0.100952558576 - 0.101031023423 - 0.101109544058 - 0.101188120519 - 0.101266752847 - 0.101345441081 - 0.10142418526 - 0.101502985425 - 0.101581841615 - 0.101660753871 - 0.101739722231 - 0.101818746737 - 0.101897827427 - 0.101976964342 - 0.102056157522 - 0.102135407007 - 0.102214712836 - 0.102294075051 - 0.10237349369 - 0.102452968794 - 0.102532500404 - 0.102612088559 - 0.102691733299 - 0.102771434666 - 0.102851192698 - 0.102931007437 - 0.103010878923 - 0.103090807196 - 0.103170792296 - 0.103250834263 - 0.10333093314 - 0.103411088964 - 0.103491301778 - 0.103571571622 - 0.103651898536 - 0.103732282561 - 0.103812723737 - 0.103893222106 - 0.103973777707 - 0.104054390581 - 0.10413506077 - 0.104215788314 - 0.104296573253 - 0.104377415629 - 0.104458315482 - 0.104539272853 - 0.104620287783 - 0.104701360314 - 0.104782490485 - 0.104863678338 - 0.104944923915 - 0.105026227255 - 0.1051075884 - 0.105189007391 - 0.10527048427 - 0.105352019077 - 0.105433611854 - 0.105515262642 - 0.105596971482 - 0.105678738415 - 0.105760563482 - 0.105842446726 - 0.105924388187 - 0.106006387907 - 0.106088445927 - 0.106170562289 - 0.106252737034 - 0.106334970203 - 0.106417261838 - 0.106499611982 - 0.106582020674 - 0.106664487958 - 0.106747013874 - 0.106829598464 - 0.106912241771 - 0.106994943835 - 0.107077704698 - 0.107160524403 - 0.107243402992 - 0.107326340505 - 0.107409336985 - 0.107492392474 - 0.107575507014 - 0.107658680646 - 0.107741913414 - 0.107825205358 - 0.107908556521 - 0.107991966945 - 0.108075436672 - 0.108158965745 - 0.108242554205 - 0.108326202095 - 0.108409909457 - 0.108493676333 - 0.108577502766 - 0.108661388797 - 0.10874533447 - 0.108829339827 - 0.10891340491 - 0.108997529761 - 0.109081714424 - 0.10916595894 - 0.109250263352 - 0.109334627703 - 0.109419052036 - 0.109503536392 - 0.109588080815 - 0.109672685348 - 0.109757350033 - 0.109842074912 - 0.109926860029 - 0.110011705427 - 0.110096611149 - 0.110181577236 - 0.110266603733 - 0.110351690682 - 0.110436838126 - 0.110522046108 - 0.110607314671 - 0.110692643859 - 0.110778033714 - 0.110863484279 - 0.110948995598 - 0.111034567714 - 0.11112020067 - 0.11120589451 - 0.111291649276 - 0.111377465012 - 0.111463341761 - 0.111549279567 - 0.111635278473 - 0.111721338522 - 0.111807459759 - 0.111893642226 - 0.111979885967 - 0.112066191025 - 0.112152557445 - 0.112238985269 - 0.112325474542 - 0.112412025307 - 0.112498637608 - 0.112585311489 - 0.112672046993 - 0.112758844165 - 0.112845703047 - 0.112932623684 - 0.11301960612 - 0.113106650399 - 0.113193756565 - 0.113280924661 - 0.113368154733 - 0.113455446823 - 0.113542800976 - 0.113630217236 - 0.113717695647 - 0.113805236254 - 0.1138928391 - 0.11398050423 - 0.114068231689 - 0.11415602152 - 0.114243873767 - 0.114331788476 - 0.114419765691 - 0.114507805455 - 0.114595907814 - 0.114684072813 - 0.114772300494 - 0.114860590904 - 0.114948944087 - 0.115037360086 - 0.115125838948 - 0.115214380717 - 0.115302985437 - 0.115391653153 - 0.115480383911 - 0.115569177754 - 0.115658034727 - 0.115746954877 - 0.115835938246 - 0.115924984882 - 0.116014094827 - 0.116103268128 - 0.116192504829 - 0.116281804976 - 0.116371168614 - 0.116460595787 - 0.116550086541 - 0.116639640922 - 0.116729258974 - 0.116818940742 - 0.116908686272 - 0.11699849561 - 0.117088368801 - 0.117178305889 - 0.117268306921 - 0.117358371942 - 0.117448500997 - 0.117538694132 - 0.117628951393 - 0.117719272825 - 0.117809658473 - 0.117900108384 - 0.117990622604 - 0.118081201177 - 0.118171844149 - 0.118262551567 - 0.118353323476 - 0.118444159922 - 0.118535060951 - 0.118626026609 - 0.118717056941 - 0.118808151995 - 0.118899311815 - 0.118990536448 - 0.119081825939 - 0.119173180336 - 0.119264599684 - 0.11935608403 - 0.119447633419 - 0.119539247897 - 0.119630927512 - 0.119722672309 - 0.119814482335 - 0.119906357636 - 0.119998298258 - 0.120090304249 - 0.120182375654 - 0.12027451252 - 0.120366714893 - 0.12045898282 - 0.120551316348 - 0.120643715524 - 0.120736180393 - 0.120828711003 - 0.1209213074 - 0.121013969632 - 0.121106697745 - 0.121199491785 - 0.1212923518 - 0.121385277837 - 0.121478269943 - 0.121571328164 - 0.121664452547 - 0.12175764314 - 0.12185089999 - 0.121944223143 - 0.122037612648 - 0.12213106855 - 0.122224590898 - 0.122318179738 - 0.122411835119 - 0.122505557086 - 0.122599345688 - 0.122693200971 - 0.122787122984 - 0.122881111773 - 0.122975167387 - 0.123069289872 - 0.123163479277 - 0.123257735648 - 0.123352059034 - 0.123446449482 - 0.123540907039 - 0.123635431754 - 0.123730023674 - 0.123824682847 - 0.123919409321 - 0.124014203144 - 0.124109064363 - 0.124203993026 - 0.124298989182 - 0.124394052879 - 0.124489184163 - 0.124584383084 - 0.12467964969 - 0.124774984029 - 0.124870386148 - 0.124965856096 - 0.125061393921 - 0.125156999672 - 0.125252673397 - 0.125348415144 - 0.125444224961 - 0.125540102897 - 0.125636049001 - 0.12573206332 - 0.125828145904 - 0.1259242968 - 0.126020516058 - 0.126116803726 - 0.126213159852 - 0.126309584486 - 0.126406077675 - 0.12650263947 - 0.126599269918 - 0.126695969068 - 0.126792736969 - 0.126889573671 - 0.126986479221 - 0.12708345367 - 0.127180497065 - 0.127277609456 - 0.127374790892 - 0.127472041422 - 0.127569361096 - 0.127666749962 - 0.127764208069 - 0.127861735467 - 0.127959332205 - 0.128056998333 - 0.128154733899 - 0.128252538953 - 0.128350413545 - 0.128448357724 - 0.128546371538 - 0.128644455039 - 0.128742608276 - 0.128840831297 - 0.128939124153 - 0.129037486893 - 0.129135919567 - 0.129234422225 - 0.129332994916 - 0.12943163769 - 0.129530350598 - 0.129629133688 - 0.129727987011 - 0.129826910617 - 0.129925904556 - 0.130024968877 - 0.130124103632 - 0.130223308869 - 0.130322584639 - 0.130421930992 - 0.130521347978 - 0.130620835648 - 0.130720394051 - 0.130820023239 - 0.130919723261 - 0.131019494168 - 0.13111933601 - 0.131219248837 - 0.131319232701 - 0.131419287651 - 0.131519413738 - 0.131619611013 - 0.131719879526 - 0.131820219328 - 0.131920630469 - 0.132021113001 - 0.132121666974 - 0.132222292439 - 0.132322989447 - 0.132423758048 - 0.132524598294 - 0.132625510235 - 0.132726493922 - 0.132827549407 - 0.13292867674 - 0.133029875973 - 0.133131147156 - 0.133232490342 - 0.13333390558 - 0.133435392922 - 0.13353695242 - 0.133638584125 - 0.133740288088 - 0.13384206436 - 0.133943912994 - 0.134045834039 - 0.134147827549 - 0.134249893573 - 0.134352032165 - 0.134454243375 - 0.134556527256 - 0.134658883858 - 0.134761313234 - 0.134863815435 - 0.134966390513 - 0.135069038519 - 0.135171759507 - 0.135274553527 - 0.135377420632 - 0.135480360873 - 0.135583374302 - 0.135686460972 - 0.135789620935 - 0.135892854242 - 0.135996160947 - 0.1360995411 - 0.136202994754 - 0.136306521962 - 0.136410122776 - 0.136513797247 - 0.13661754543 - 0.136721367375 - 0.136825263135 - 0.136929232764 - 0.137033276313 - 0.137137393834 - 0.137241585381 - 0.137345851006 - 0.137450190762 - 0.137554604702 - 0.137659092878 - 0.137763655342 - 0.137868292149 - 0.13797300335 - 0.138077788999 - 0.138182649148 - 0.138287583851 - 0.138392593161 - 0.13849767713 - 0.138602835811 - 0.138708069258 - 0.138813377524 - 0.138918760663 - 0.139024218726 - 0.139129751768 - 0.139235359842 - 0.139341043002 - 0.139446801299 - 0.139552634789 - 0.139658543525 - 0.139764527559 - 0.139870586946 - 0.139976721739 - 0.140082931992 - 0.140189217758 - 0.140295579092 - 0.140402016046 - 0.140508528674 - 0.140615117031 - 0.140721781171 - 0.140828521146 - 0.140935337011 - 0.141042228821 - 0.141149196628 - 0.141256240487 - 0.141363360452 - 0.141470556578 - 0.141577828917 - 0.141685177526 - 0.141792602457 - 0.141900103765 - 0.142007681504 - 0.142115335729 - 0.142223066494 - 0.142330873853 - 0.142438757861 - 0.142546718573 - 0.142654756043 - 0.142762870325 - 0.142871061474 - 0.142979329545 - 0.143087674592 - 0.143196096671 - 0.143304595835 - 0.14341317214 - 0.143521825641 - 0.143630556393 - 0.143739364449 - 0.143848249866 - 0.143957212699 - 0.144066253002 - 0.14417537083 - 0.144284566239 - 0.144393839284 - 0.14450319002 - 0.144612618501 - 0.144722124785 - 0.144831708925 - 0.144941370977 - 0.145051110997 - 0.14516092904 - 0.145270825161 - 0.145380799417 - 0.145490851861 - 0.145600982551 - 0.145711191542 - 0.145821478889 - 0.145931844648 - 0.146042288875 - 0.146152811626 - 0.146263412956 - 0.146374092921 - 0.146484851578 - 0.146595688982 - 0.146706605189 - 0.146817600255 - 0.146928674237 - 0.14703982719 - 0.147151059171 - 0.147262370235 - 0.147373760439 - 0.14748522984 - 0.147596778493 - 0.147708406454 - 0.147820113782 - 0.14793190053 - 0.148043766757 - 0.148155712519 - 0.148267737872 - 0.148379842873 - 0.148492027578 - 0.148604292044 - 0.148716636328 - 0.148829060487 - 0.148941564576 - 0.149054148655 - 0.149166812778 - 0.149279557003 - 0.149392381387 - 0.149505285987 - 0.149618270859 - 0.149731336062 - 0.149844481652 - 0.149957707686 - 0.150071014222 - 0.150184401316 - 0.150297869027 - 0.15041141741 - 0.150525046525 - 0.150638756427 - 0.150752547175 - 0.150866418826 - 0.150980371437 - 0.151094405066 - 0.151208519771 - 0.151322715609 - 0.151436992638 - 0.151551350916 - 0.151665790501 - 0.151780311449 - 0.15189491382 - 0.152009597671 - 0.152124363059 - 0.152239210044 - 0.152354138683 - 0.152469149033 - 0.152584241154 - 0.152699415102 - 0.152814670938 - 0.152930008717 - 0.1530454285 - 0.153160930344 - 0.153276514307 - 0.153392180449 - 0.153507928826 - 0.153623759499 - 0.153739672524 - 0.153855667962 - 0.15397174587 - 0.154087906307 - 0.154204149332 - 0.154320475003 - 0.15443688338 - 0.15455337452 - 0.154669948484 - 0.154786605329 - 0.154903345115 - 0.155020167901 - 0.155137073745 - 0.155254062707 - 0.155371134846 - 0.155488290221 - 0.155605528891 - 0.155722850916 - 0.155840256354 - 0.155957745265 - 0.156075317708 - 0.156192973743 - 0.156310713429 - 0.156428536825 - 0.156546443992 - 0.156664434988 - 0.156782509874 - 0.156900668708 - 0.157018911552 - 0.157137238463 - 0.157255649502 - 0.15737414473 - 0.157492724205 - 0.157611387988 - 0.157730136138 - 0.157848968716 - 0.157967885782 - 0.158086887395 - 0.158205973616 - 0.158325144505 - 0.158444400122 - 0.158563740527 - 0.158683165781 - 0.158802675945 - 0.158922271077 - 0.159041951239 - 0.159161716492 - 0.159281566895 - 0.159401502509 - 0.159521523396 - 0.159641629614 - 0.159761821226 - 0.159882098292 - 0.160002460872 - 0.160122909028 - 0.16024344282 - 0.160364062309 - 0.160484767556 - 0.160605558622 - 0.160726435569 - 0.160847398456 - 0.160968447345 - 0.161089582298 - 0.161210803376 - 0.161332110639 - 0.161453504149 - 0.161574983968 - 0.161696550156 - 0.161818202776 - 0.161939941888 - 0.162061767554 - 0.162183679836 - 0.162305678795 - 0.162427764493 - 0.162549936992 - 0.162672196352 - 0.162794542637 - 0.162916975907 - 0.163039496225 - 0.163162103653 - 0.163284798252 - 0.163407580084 - 0.163530449212 - 0.163653405698 - 0.163776449603 - 0.163899580989 - 0.16402279992 - 0.164146106457 - 0.164269500663 - 0.164392982599 - 0.164516552328 - 0.164640209913 - 0.164763955417 - 0.1648877889 - 0.165011710427 - 0.16513572006 - 0.165259817861 - 0.165384003893 - 0.165508278219 - 0.165632640902 - 0.165757092004 - 0.165881631588 - 0.166006259717 - 0.166130976455 - 0.166255781863 - 0.166380676006 - 0.166505658946 - 0.166630730747 - 0.166755891471 - 0.166881141181 - 0.167006479942 - 0.167131907816 - 0.167257424867 - 0.167383031158 - 0.167508726753 - 0.167634511715 - 0.167760386107 - 0.167886349993 - 0.168012403438 - 0.168138546504 - 0.168264779255 - 0.168391101755 - 0.168517514068 - 0.168644016257 - 0.168770608387 - 0.168897290521 - 0.169024062724 - 0.16915092506 - 0.169277877592 - 0.169404920385 - 0.169532053503 - 0.169659277009 - 0.16978659097 - 0.169913995448 - 0.170041490508 - 0.170169076214 - 0.170296752631 - 0.170424519824 - 0.170552377857 - 0.170680326794 - 0.1708083667 - 0.170936497641 - 0.171064719679 - 0.171193032881 - 0.171321437312 - 0.171449933035 - 0.171578520116 - 0.17170719862 - 0.171835968612 - 0.171964830157 - 0.172093783319 - 0.172222828165 - 0.172351964759 - 0.172481193167 - 0.172610513454 - 0.172739925684 - 0.172869429925 - 0.17299902624 - 0.173128714696 - 0.173258495357 - 0.17338836829 - 0.17351833356 - 0.173648391233 - 0.173778541374 - 0.17390878405 - 0.174039119325 - 0.174169547266 - 0.174300067939 - 0.174430681409 - 0.174561387743 - 0.174692187007 - 0.174823079266 - 0.174954064588 - 0.175085143037 - 0.17521631468 - 0.175347579583 - 0.175478937814 - 0.175610389437 - 0.17574193452 - 0.175873573129 - 0.176005305331 - 0.176137131191 - 0.176269050777 - 0.176401064155 - 0.176533171392 - 0.176665372555 - 0.17679766771 - 0.176930056924 - 0.177062540265 - 0.177195117798 - 0.177327789591 - 0.177460555712 - 0.177593416226 - 0.177726371202 - 0.177859420706 - 0.177992564806 - 0.178125803568 - 0.17825913706 - 0.17839256535 - 0.178526088505 - 0.178659706592 - 0.178793419679 - 0.178927227834 - 0.179061131123 - 0.179195129615 - 0.179329223377 - 0.179463412477 - 0.179597696983 - 0.179732076962 - 0.179866552483 - 0.180001123614 - 0.180135790421 - 0.180270552975 - 0.180405411341 - 0.18054036559 - 0.180675415788 - 0.180810562004 - 0.180945804307 - 0.181081142764 - 0.181216577444 - 0.181352108415 - 0.181487735746 - 0.181623459506 - 0.181759279762 - 0.181895196584 - 0.18203121004 - 0.182167320199 - 0.18230352713 - 0.182439830901 - 0.182576231581 - 0.182712729239 - 0.182849323945 - 0.182986015767 - 0.183122804773 - 0.183259691035 - 0.183396674619 - 0.183533755596 - 0.183670934035 - 0.183808210005 - 0.183945583576 - 0.184083054817 - 0.184220623797 - 0.184358290585 - 0.184496055252 - 0.184633917867 - 0.1847718785 - 0.184909937219 - 0.185048094096 - 0.1851863492 - 0.1853247026 - 0.185463154367 - 0.18560170457 - 0.18574035328 - 0.185879100566 - 0.186017946499 - 0.186156891148 - 0.186295934584 - 0.186435076878 - 0.186574318099 - 0.186713658317 - 0.186853097604 - 0.186992636029 - 0.187132273663 - 0.187272010577 - 0.187411846841 - 0.187551782526 - 0.187691817703 - 0.187831952441 - 0.187972186813 - 0.188112520888 - 0.188252954739 - 0.188393488434 - 0.188534122047 - 0.188674855647 - 0.188815689306 - 0.188956623095 - 0.189097657085 - 0.189238791348 - 0.189380025954 - 0.189521360975 - 0.189662796483 - 0.189804332548 - 0.189945969243 - 0.190087706638 - 0.190229544807 - 0.190371483819 - 0.190513523747 - 0.190655664662 - 0.190797906637 - 0.190940249743 - 0.191082694053 - 0.191225239637 - 0.191367886568 - 0.191510634919 - 0.191653484761 - 0.191796436166 - 0.191939489207 - 0.192082643956 - 0.192225900484 - 0.192369258866 - 0.192512719172 - 0.192656281476 - 0.19279994585 - 0.192943712366 - 0.193087581098 - 0.193231552117 - 0.193375625497 - 0.19351980131 - 0.193664079629 - 0.193808460527 - 0.193952944077 - 0.194097530352 - 0.194242219425 - 0.19438701137 - 0.194531906258 - 0.194676904164 - 0.19482200516 - 0.19496720932 - 0.195112516718 - 0.195257927426 - 0.195403441519 - 0.195549059069 - 0.19569478015 - 0.195840604836 - 0.1959865332 - 0.196132565317 - 0.196278701259 - 0.196424941102 - 0.196571284918 - 0.196717732781 - 0.196864284766 - 0.197010940947 - 0.197157701397 - 0.197304566191 - 0.197451535403 - 0.197598609107 - 0.197745787377 - 0.197893070289 - 0.198040457915 - 0.198187950332 - 0.198335547612 - 0.198483249831 - 0.198631057064 - 0.198778969384 - 0.198926986868 - 0.199075109589 - 0.199223337622 - 0.199371671042 - 0.199520109924 - 0.199668654344 - 0.199817304375 - 0.199966060094 - 0.200114921575 - 0.200263888894 - 0.200412962126 - 0.200562141346 - 0.200711426629 - 0.200860818051 - 0.201010315687 - 0.201159919613 - 0.201309629905 - 0.201459446638 - 0.201609369887 - 0.201759399729 - 0.201909536239 - 0.202059779493 - 0.202210129567 - 0.202360586537 - 0.202511150479 - 0.202661821469 - 0.202812599583 - 0.202963484897 - 0.203114477488 - 0.203265577432 - 0.203416784804 - 0.203568099682 - 0.203719522142 - 0.20387105226 - 0.204022690113 - 0.204174435778 - 0.204326289331 - 0.204478250848 - 0.204630320407 - 0.204782498085 - 0.204934783958 - 0.205087178103 - 0.205239680598 - 0.205392291518 - 0.205545010942 - 0.205697838947 - 0.205850775609 - 0.206003821006 - 0.206156975215 - 0.206310238314 - 0.20646361038 - 0.206617091491 - 0.206770681723 - 0.206924381155 - 0.207078189865 - 0.207232107929 - 0.207386135426 - 0.207540272433 - 0.207694519029 - 0.207848875291 - 0.208003341297 - 0.208157917126 - 0.208312602855 - 0.208467398562 - 0.208622304326 - 0.208777320225 - 0.208932446337 - 0.209087682741 - 0.209243029515 - 0.209398486737 - 0.209554054487 - 0.209709732841 - 0.20986552188 - 0.210021421682 - 0.210177432326 - 0.21033355389 - 0.210489786454 - 0.210646130095 - 0.210802584894 - 0.210959150929 - 0.21111582828 - 0.211272617025 - 0.211429517244 - 0.211586529015 - 0.211743652419 - 0.211900887534 - 0.212058234441 - 0.212215693218 - 0.212373263945 - 0.212530946702 - 0.212688741568 - 0.212846648623 - 0.213004667947 - 0.21316279962 - 0.213321043721 - 0.21347940033 - 0.213637869528 - 0.213796451394 - 0.213955146009 - 0.214113953452 - 0.214272873805 - 0.214431907146 - 0.214591053558 - 0.214750313119 - 0.21490968591 - 0.215069172013 - 0.215228771507 - 0.215388484473 - 0.215548310991 - 0.215708251143 - 0.21586830501 - 0.216028472672 - 0.216188754209 - 0.216349149704 - 0.216509659236 - 0.216670282888 - 0.21683102074 - 0.216991872873 - 0.217152839369 - 0.217313920309 - 0.217475115775 - 0.217636425847 - 0.217797850607 - 0.217959390137 - 0.218121044519 - 0.218282813834 - 0.218444698163 - 0.218606697589 - 0.218768812193 - 0.218931042058 - 0.219093387265 - 0.219255847896 - 0.219418424033 - 0.219581115759 - 0.219743923155 - 0.219906846304 - 0.220069885288 - 0.22023304019 - 0.220396311092 - 0.220559698076 - 0.220723201225 - 0.220886820621 - 0.221050556348 - 0.221214408487 - 0.221378377122 - 0.221542462335 - 0.22170666421 - 0.221870982829 - 0.222035418275 - 0.222199970632 - 0.222364639982 - 0.222529426409 - 0.222694329996 - 0.222859350825 - 0.223024488982 - 0.223189744548 - 0.223355117608 - 0.223520608244 - 0.223686216542 - 0.223851942583 - 0.224017786452 - 0.224183748233 - 0.22434982801 - 0.224516025866 - 0.224682341885 - 0.224848776152 - 0.22501532875 - 0.225181999764 - 0.225348789278 - 0.225515697376 - 0.225682724142 - 0.22584986966 - 0.226017134016 - 0.226184517294 - 0.226352019577 - 0.226519640952 - 0.226687381502 - 0.226855241312 - 0.227023220467 - 0.227191319052 - 0.227359537152 - 0.227527874851 - 0.227696332235 - 0.227864909389 - 0.228033606398 - 0.228202423348 - 0.228371360322 - 0.228540417408 - 0.22870959469 - 0.228878892253 - 0.229048310184 - 0.229217848568 - 0.22938750749 - 0.229557287036 - 0.229727187292 - 0.229897208344 - 0.230067350277 - 0.230237613178 - 0.230407997132 - 0.230578502226 - 0.230749128546 - 0.230919876177 - 0.231090745207 - 0.231261735721 - 0.231432847806 - 0.231604081549 - 0.231775437035 - 0.231946914352 - 0.232118513585 - 0.232290234822 - 0.23246207815 - 0.232634043655 - 0.232806131424 - 0.232978341544 - 0.233150674101 - 0.233323129184 - 0.233495706879 - 0.233668407273 - 0.233841230454 - 0.234014176509 - 0.234187245525 - 0.234360437589 - 0.23453375279 - 0.234707191214 - 0.23488075295 - 0.235054438084 - 0.235228246706 - 0.235402178901 - 0.235576234759 - 0.235750414368 - 0.235924717814 - 0.236099145187 - 0.236273696574 - 0.236448372064 - 0.236623171745 - 0.236798095704 - 0.236973144031 - 0.237148316815 - 0.237323614142 - 0.237499036102 - 0.237674582784 - 0.237850254276 - 0.238026050667 - 0.238201972046 - 0.238378018501 - 0.238554190122 - 0.238730486998 - 0.238906909217 - 0.239083456868 - 0.239260130042 - 0.239436928827 - 0.239613853312 - 0.239790903587 - 0.239968079741 - 0.240145381864 - 0.240322810045 - 0.240500364374 - 0.240678044941 - 0.240855851835 - 0.241033785146 - 0.241211844964 - 0.241390031379 - 0.241568344481 - 0.241746784361 - 0.241925351107 - 0.242104044811 - 0.242282865563 - 0.242461813453 - 0.242640888571 - 0.242820091007 - 0.242999420854 - 0.2431788782 - 0.243358463137 - 0.243538175755 - 0.243718016145 - 0.243897984398 - 0.244078080605 - 0.244258304857 - 0.244438657245 - 0.24461913786 - 0.244799746792 - 0.244980484135 - 0.245161349977 - 0.245342344412 - 0.245523467531 - 0.245704719424 - 0.245886100184 - 0.246067609902 - 0.246249248669 - 0.246431016579 - 0.246612913721 - 0.246794940189 - 0.246977096074 - 0.247159381468 - 0.247341796464 - 0.247524341153 - 0.247707015628 - 0.24788981998 - 0.248072754303 - 0.248255818689 - 0.248439013229 - 0.248622338018 - 0.248805793146 - 0.248989378708 - 0.249173094795 - 0.249356941501 - 0.249540918918 - 0.24972502714 - 0.249909266258 - 0.250093636368 - 0.25027813756 - 0.250462769929 - 0.250647533569 - 0.250832428571 - 0.25101745503 - 0.251202613039 - 0.251387902692 - 0.251573324083 - 0.251758877304 - 0.25194456245 - 0.252130379614 - 0.25231632889 - 0.252502410373 - 0.252688624156 - 0.252874970334 - 0.253061448999 - 0.253248060248 - 0.253434804173 - 0.25362168087 - 0.253808690432 - 0.253995832954 - 0.254183108531 - 0.254370517257 - 0.254558059227 - 0.254745734536 - 0.254933543278 - 0.255121485548 - 0.255309561441 - 0.255497771053 - 0.255686114478 - 0.255874591811 - 0.256063203149 - 0.256251948585 - 0.256440828215 - 0.256629842135 - 0.25681899044 - 0.257008273226 - 0.257197690588 - 0.257387242622 - 0.257576929424 - 0.257766751089 - 0.257956707714 - 0.258146799394 - 0.258337026225 - 0.258527388304 - 0.258717885727 - 0.25890851859 - 0.259099286989 - 0.25929019102 - 0.25948123078 - 0.259672406366 - 0.259863717874 - 0.2600551654 - 0.260246749042 - 0.260438468896 - 0.260630325059 - 0.260822317628 - 0.2610144467 - 0.261206712372 - 0.261399114741 - 0.261591653904 - 0.261784329959 - 0.261977143002 - 0.262170093132 - 0.262363180446 - 0.262556405041 - 0.262749767014 - 0.262943266464 - 0.263136903489 - 0.263330678185 - 0.263524590652 - 0.263718640986 - 0.263912829286 - 0.264107155651 - 0.264301620177 - 0.264496222964 - 0.26469096411 - 0.264885843713 - 0.265080861871 - 0.265276018683 - 0.265471314248 - 0.265666748664 - 0.26586232203 - 0.266058034445 - 0.266253886008 - 0.266449876817 - 0.266646006972 - 0.266842276571 - 0.267038685714 - 0.267235234501 - 0.267431923029 - 0.267628751399 - 0.26782571971 - 0.268022828062 - 0.268220076554 - 0.268417465285 - 0.268614994356 - 0.268812663867 - 0.269010473916 - 0.269208424605 - 0.269406516032 - 0.269604748299 - 0.269803121504 - 0.270001635749 - 0.270200291134 - 0.270399087759 - 0.270598025724 - 0.270797105131 - 0.270996326078 - 0.271195688668 - 0.271395193001 - 0.271594839177 - 0.271794627298 - 0.271994557464 - 0.272194629777 - 0.272394844337 - 0.272595201246 - 0.272795700604 - 0.272996342513 - 0.273197127075 - 0.273398054391 - 0.273599124562 - 0.27380033769 - 0.274001693876 - 0.274203193223 - 0.274404835832 - 0.274606621804 - 0.274808551243 - 0.275010624249 - 0.275212840925 - 0.275415201374 - 0.275617705696 - 0.275820353995 - 0.276023146373 - 0.276226082932 - 0.276429163776 - 0.276632389005 - 0.276835758724 - 0.277039273034 - 0.27724293204 - 0.277446735842 - 0.277650684545 - 0.277854778252 - 0.278059017065 - 0.278263401088 - 0.278467930424 - 0.278672605176 - 0.278877425448 - 0.279082391343 - 0.279287502965 - 0.279492760417 - 0.279698163803 - 0.279903713227 - 0.280109408792 - 0.280315250603 - 0.280521238763 - 0.280727373377 - 0.280933654548 - 0.281140082381 - 0.28134665698 - 0.28155337845 - 0.281760246894 - 0.281967262418 - 0.282174425126 - 0.282381735122 - 0.282589192512 - 0.2827967974 - 0.28300454989 - 0.283212450089 - 0.2834204981 - 0.28362869403 - 0.283837037982 - 0.284045530064 - 0.284254170378 - 0.284462959032 - 0.284671896131 - 0.284880981779 - 0.285090216084 - 0.28529959915 - 0.285509131083 - 0.285718811989 - 0.285928641974 - 0.286138621144 - 0.286348749605 - 0.286559027463 - 0.286769454824 - 0.286980031796 - 0.287190758483 - 0.287401634993 - 0.287612661431 - 0.287823837906 - 0.288035164522 - 0.288246641388 - 0.28845826861 - 0.288670046294 - 0.288881974548 - 0.289094053479 - 0.289306283193 - 0.289518663799 - 0.289731195403 - 0.289943878113 - 0.290156712037 - 0.29036969728 - 0.290582833953 - 0.290796122161 - 0.291009562012 - 0.291223153616 - 0.291436897078 - 0.291650792508 - 0.291864840014 - 0.292079039702 - 0.292293391683 - 0.292507896064 - 0.292722552953 - 0.292937362458 - 0.29315232469 - 0.293367439755 - 0.293582707762 - 0.293798128821 - 0.29401370304 - 0.294229430527 - 0.294445311393 - 0.294661345746 - 0.294877533695 - 0.295093875349 - 0.295310370818 - 0.295527020211 - 0.295743823637 - 0.295960781207 - 0.296177893028 - 0.296395159212 - 0.296612579868 - 0.296830155106 - 0.297047885035 - 0.297265769766 - 0.297483809409 - 0.297702004074 - 0.29792035387 - 0.298138858909 - 0.298357519301 - 0.298576335156 - 0.298795306585 - 0.299014433698 - 0.299233716606 - 0.29945315542 - 0.29967275025 - 0.299892501208 - 0.300112408405 - 0.300332471951 - 0.300552691958 - 0.300773068537 - 0.3009936018 - 0.301214291857 - 0.301435138821 - 0.301656142802 - 0.301877303913 - 0.302098622265 - 0.302320097969 - 0.302541731139 - 0.302763521886 - 0.302985470321 - 0.303207576557 - 0.303429840707 - 0.303652262881 - 0.303874843194 - 0.304097581757 - 0.304320478682 - 0.304543534083 - 0.304766748071 - 0.304990120761 - 0.305213652263 - 0.305437342693 - 0.305661192162 - 0.305885200783 - 0.30610936867 - 0.306333695936 - 0.306558182694 - 0.306782829058 - 0.307007635141 - 0.307232601056 - 0.307457726918 - 0.30768301284 - 0.307908458936 - 0.308134065319 - 0.308359832104 - 0.308585759405 - 0.308811847336 - 0.30903809601 - 0.309264505543 - 0.309491076049 - 0.309717807641 - 0.309944700436 - 0.310171754546 - 0.310398970088 - 0.310626347175 - 0.310853885923 - 0.311081586447 - 0.311309448861 - 0.311537473281 - 0.311765659821 - 0.311994008598 - 0.312222519726 - 0.312451193321 - 0.312680029498 - 0.312909028373 - 0.313138190062 - 0.313367514681 - 0.313597002344 - 0.313826653169 - 0.314056467271 - 0.314286444766 - 0.314516585771 - 0.314746890401 - 0.314977358774 - 0.315207991005 - 0.31543878721 - 0.315669747508 - 0.315900872013 - 0.316132160843 - 0.316363614115 - 0.316595231946 - 0.316827014453 - 0.317058961752 - 0.317291073961 - 0.317523351198 - 0.317755793579 - 0.317988401221 - 0.318221174243 - 0.318454112763 - 0.318687216897 - 0.318920486763 - 0.319153922479 - 0.319387524164 - 0.319621291935 - 0.31985522591 - 0.320089326207 - 0.320323592945 - 0.320558026243 - 0.320792626217 - 0.321027392988 - 0.321262326673 - 0.321497427391 - 0.321732695261 - 0.321968130402 - 0.322203732933 - 0.322439502972 - 0.322675440639 - 0.322911546053 - 0.323147819334 - 0.3233842606 - 0.323620869971 - 0.323857647566 - 0.324094593506 - 0.32433170791 - 0.324568990897 - 0.324806442588 - 0.325044063102 - 0.32528185256 - 0.325519811081 - 0.325757938786 - 0.325996235795 - 0.326234702229 - 0.326473338207 - 0.326712143851 - 0.326951119281 - 0.327190264618 - 0.327429579982 - 0.327669065495 - 0.327908721277 - 0.32814854745 - 0.328388544135 - 0.328628711452 - 0.328869049523 - 0.32910955847 - 0.329350238415 - 0.329591089477 - 0.329832111781 - 0.330073305446 - 0.330314670595 - 0.33055620735 - 0.330797915833 - 0.331039796165 - 0.33128184847 - 0.331524072869 - 0.331766469485 - 0.332009038441 - 0.332251779857 - 0.332494693859 - 0.332737780567 - 0.332981040105 - 0.333224472596 - 0.333468078162 - 0.333711856927 - 0.333955809014 - 0.334199934546 - 0.334444233647 - 0.334688706439 - 0.334933353046 - 0.335178173593 - 0.335423168202 - 0.335668336997 - 0.335913680103 - 0.336159197642 - 0.33640488974 - 0.33665075652 - 0.336896798106 - 0.337143014623 - 0.337389406195 - 0.337635972946 - 0.337882715002 - 0.338129632486 - 0.338376725524 - 0.33862399424 - 0.338871438759 - 0.339119059206 - 0.339366855707 - 0.339614828385 - 0.339862977368 - 0.340111302779 - 0.340359804745 - 0.340608483391 - 0.340857338843 - 0.341106371225 - 0.341355580665 - 0.341604967288 - 0.34185453122 - 0.342104272586 - 0.342354191514 - 0.342604288129 - 0.342854562558 - 0.343105014928 - 0.343355645363 - 0.343606453992 - 0.343857440941 - 0.344108606337 - 0.344359950307 - 0.344611472977 - 0.344863174474 - 0.345115054926 - 0.345367114461 - 0.345619353204 - 0.345871771285 - 0.346124368829 - 0.346377145966 - 0.346630102822 - 0.346883239525 - 0.347136556204 - 0.347390052985 - 0.347643729998 - 0.34789758737 - 0.34815162523 - 0.348405843705 - 0.348660242925 - 0.348914823018 - 0.349169584112 - 0.349424526336 - 0.349679649819 - 0.349934954689 - 0.350190441077 - 0.35044610911 - 0.350701958918 - 0.35095799063 - 0.351214204376 - 0.351470600284 - 0.351727178485 - 0.351983939108 - 0.352240882282 - 0.352498008138 - 0.352755316806 - 0.353012808415 - 0.353270483095 - 0.353528340977 - 0.35378638219 - 0.354044606866 - 0.354303015135 - 0.354561607126 - 0.354820382972 - 0.355079342801 - 0.355338486747 - 0.355597814938 - 0.355857327507 - 0.356117024583 - 0.3563769063 - 0.356636972787 - 0.356897224176 - 0.357157660599 - 0.357418282186 - 0.357679089071 - 0.357940081384 - 0.358201259258 - 0.358462622823 - 0.358724172213 - 0.35898590756 - 0.359247828995 - 0.359509936651 - 0.35977223066 - 0.360034711156 - 0.360297378269 - 0.360560232134 - 0.360823272883 - 0.361086500648 - 0.361349915563 - 0.361613517761 - 0.361877307375 - 0.362141284538 - 0.362405449383 - 0.362669802045 - 0.362934342656 - 0.36319907135 - 0.363463988261 - 0.363729093522 - 0.363994387268 - 0.364259869633 - 0.364525540751 - 0.364791400755 - 0.36505744978 - 0.365323687961 - 0.365590115433 - 0.365856732328 - 0.366123538783 - 0.366390534933 - 0.366657720911 - 0.366925096853 - 0.367192662894 - 0.367460419169 - 0.367728365814 - 0.367996502963 - 0.368264830753 - 0.368533349318 - 0.368802058795 - 0.369070959318 - 0.369340051025 - 0.36960933405 - 0.369878808531 - 0.370148474602 - 0.370418332401 - 0.370688382063 - 0.370958623725 - 0.371229057524 - 0.371499683595 - 0.371770502077 - 0.372041513105 - 0.372312716816 - 0.372584113348 - 0.372855702837 - 0.373127485422 - 0.373399461238 - 0.373671630423 - 0.373943993116 - 0.374216549453 - 0.374489299572 - 0.374762243611 - 0.375035381708 - 0.375308714 - 0.375582240626 - 0.375855961725 - 0.376129877434 - 0.376403987891 - 0.376678293235 - 0.376952793605 - 0.377227489139 - 0.377502379977 - 0.377777466256 - 0.378052748116 - 0.378328225697 - 0.378603899136 - 0.378879768573 - 0.379155834149 - 0.379432096001 - 0.37970855427 - 0.379985209096 - 0.380262060617 - 0.380539108975 - 0.380816354308 - 0.381093796757 - 0.381371436463 - 0.381649273564 - 0.381927308203 - 0.382205540518 - 0.382483970651 - 0.382762598742 - 0.383041424933 - 0.383320449363 - 0.383599672174 - 0.383879093507 - 0.384158713503 - 0.384438532304 - 0.38471855005 - 0.384998766882 - 0.385279182944 - 0.385559798376 - 0.38584061332 - 0.386121627917 - 0.386402842311 - 0.386684256642 - 0.386965871053 - 0.387247685687 - 0.387529700685 - 0.38781191619 - 0.388094332345 - 0.388376949292 - 0.388659767175 - 0.388942786135 - 0.389226006316 - 0.38950942786 - 0.389793050912 - 0.390076875615 - 0.390360902111 - 0.390645130544 - 0.390929561058 - 0.391214193796 - 0.391499028903 - 0.391784066522 - 0.392069306797 - 0.392354749872 - 0.392640395891 - 0.392926244999 - 0.39321229734 - 0.393498553059 - 0.3937850123 - 0.394071675207 - 0.394358541927 - 0.394645612602 - 0.39493288738 - 0.395220366404 - 0.395508049819 - 0.395795937773 - 0.396084030408 - 0.396372327872 - 0.39666083031 - 0.396949537867 - 0.397238450689 - 0.397527568923 - 0.397816892714 - 0.398106422208 - 0.398396157553 - 0.398686098893 - 0.398976246376 - 0.399266600148 - 0.399557160355 - 0.399847927146 - 0.400138900665 - 0.400430081061 - 0.400721468481 - 0.401013063071 - 0.401304864979 - 0.401596874353 - 0.401889091339 - 0.402181516086 - 0.402474148741 - 0.402766989452 - 0.403060038367 - 0.403353295634 - 0.403646761401 - 0.403940435816 - 0.404234319028 - 0.404528411186 - 0.404822712436 - 0.40511722293 - 0.405411942814 - 0.405706872238 - 0.406002011352 - 0.406297360303 - 0.406592919241 - 0.406888688317 - 0.407184667678 - 0.407480857474 - 0.407777257856 - 0.408073868972 - 0.408370690973 - 0.408667724008 - 0.408964968228 - 0.409262423783 - 0.409560090823 - 0.409857969498 - 0.410156059959 - 0.410454362357 - 0.410752876841 - 0.411051603564 - 0.411350542675 - 0.411649694326 - 0.411949058667 - 0.412248635851 - 0.412548426028 - 0.412848429351 - 0.413148645969 - 0.413449076036 - 0.413749719702 - 0.41405057712 - 0.414351648442 - 0.41465293382 - 0.414954433405 - 0.415256147351 - 0.415558075809 - 0.415860218932 - 0.416162576874 - 0.416465149785 - 0.41676793782 - 0.417070941131 - 0.417374159872 - 0.417677594195 - 0.417981244254 - 0.418285110202 - 0.418589192193 - 0.41889349038 - 0.419198004917 - 0.419502735957 - 0.419807683656 - 0.420112848166 - 0.420418229642 - 0.420723828238 - 0.421029644109 - 0.421335677409 - 0.421641928292 - 0.421948396914 - 0.422255083429 - 0.422561987992 - 0.422869110758 - 0.423176451882 - 0.423484011519 - 0.423791789825 - 0.424099786956 - 0.424408003066 - 0.424716438312 - 0.42502509285 - 0.425333966834 - 0.425643060422 - 0.425952373769 - 0.426261907032 - 0.426571660367 - 0.42688163393 - 0.427191827879 - 0.427502242369 - 0.427812877557 - 0.428123733601 - 0.428434810658 - 0.428746108884 - 0.429057628437 - 0.429369369474 - 0.429681332153 - 0.429993516632 - 0.430305923067 - 0.430618551617 - 0.430931402439 - 0.431244475693 - 0.431557771535 - 0.431871290124 - 0.432185031619 - 0.432498996178 - 0.432813183959 - 0.433127595122 - 0.433442229825 - 0.433757088227 - 0.434072170486 - 0.434387476763 - 0.434703007217 - 0.435018762007 - 0.435334741291 - 0.435650945231 - 0.435967373986 - 0.436284027715 - 0.436600906579 - 0.436918010737 - 0.43723534035 - 0.437552895578 - 0.437870676581 - 0.438188683521 - 0.438506916557 - 0.43882537585 - 0.439144061562 - 0.439462973853 - 0.439782112884 - 0.440101478817 - 0.440421071813 - 0.440740892032 - 0.441060939638 - 0.441381214791 - 0.441701717654 - 0.442022448387 - 0.442343407154 - 0.442664594116 - 0.442986009436 - 0.443307653276 - 0.443629525797 - 0.443951627164 - 0.444273957539 - 0.444596517084 - 0.444919305963 - 0.445242324338 - 0.445565572372 - 0.44588905023 - 0.446212758074 - 0.446536696068 - 0.446860864375 - 0.447185263159 - 0.447509892585 - 0.447834752816 - 0.448159844015 - 0.448485166349 - 0.44881071998 - 0.449136505073 - 0.449462521793 - 0.449788770304 - 0.450115250771 - 0.45044196336 - 0.450768908235 - 0.451096085561 - 0.451423495503 - 0.451751138228 - 0.4520790139 - 0.452407122685 - 0.452735464749 - 0.453064040258 - 0.453392849377 - 0.453721892273 - 0.454051169113 - 0.454380680061 - 0.454710425285 - 0.455040404952 - 0.455370619227 - 0.455701068278 - 0.456031752272 - 0.456362671376 - 0.456693825756 - 0.457025215581 - 0.457356841017 - 0.457688702233 - 0.458020799395 - 0.458353132672 - 0.458685702231 - 0.45901850824 - 0.459351550868 - 0.459684830283 - 0.460018346652 - 0.460352100145 - 0.460686090931 - 0.461020319177 - 0.461354785052 - 0.461689488727 - 0.462024430369 - 0.462359610147 - 0.462695028232 - 0.463030684793 - 0.463366579999 - 0.463702714019 - 0.464039087024 - 0.464375699184 - 0.464712550668 - 0.465049641647 - 0.465386972291 - 0.465724542771 - 0.466062353256 - 0.466400403918 - 0.466738694927 - 0.467077226454 - 0.467415998671 - 0.467755011747 - 0.468094265856 - 0.468433761167 - 0.468773497853 - 0.469113476085 - 0.469453696034 - 0.469794157873 - 0.470134861774 - 0.470475807909 - 0.470816996449 - 0.471158427568 - 0.471500101437 - 0.47184201823 - 0.472184178119 - 0.472526581277 - 0.472869227876 - 0.473212118091 - 0.473555252093 - 0.473898630057 - 0.474242252156 - 0.474586118564 - 0.474930229454 - 0.475274584999 - 0.475619185375 - 0.475964030755 - 0.476309121312 - 0.476654457223 - 0.47700003866 - 0.477345865799 - 0.477691938814 - 0.478038257881 - 0.478384823173 - 0.478731634866 - 0.479078693135 - 0.479425998156 - 0.479773550104 - 0.480121349155 - 0.480469395484 - 0.480817689266 - 0.481166230679 - 0.481515019898 - 0.481864057099 - 0.482213342458 - 0.482562876153 - 0.482912658359 - 0.483262689253 - 0.483612969012 - 0.483963497813 - 0.484314275833 - 0.484665303249 - 0.485016580239 - 0.48536810698 - 0.485719883649 - 0.486071910425 - 0.486424187485 - 0.486776715006 - 0.487129493168 - 0.487482522148 - 0.487835802124 - 0.488189333276 - 0.488543115781 - 0.488897149819 - 0.489251435568 - 0.489605973206 - 0.489960762914 - 0.490315804871 - 0.490671099255 - 0.491026646247 - 0.491382446025 - 0.49173849877 - 0.492094804662 - 0.492451363879 - 0.492808176604 - 0.493165243015 - 0.493522563293 - 0.493880137619 - 0.494237966173 - 0.494596049136 - 0.494954386689 - 0.495312979013 - 0.495671826289 - 0.496030928698 - 0.496390286422 - 0.496749899642 - 0.49710976854 - 0.497469893298 - 0.497830274097 - 0.498190911119 - 0.498551804548 - 0.498912954564 - 0.499274361351 - 0.499636025092 - 0.499997945967 - 0.500360124162 - 0.500722559858 - 0.501085253238 - 0.501448204486 - 0.501811413786 - 0.50217488132 - 0.502538607272 - 0.502902591826 - 0.503266835166 - 0.503631337475 - 0.503996098939 - 0.504361119741 - 0.504726400065 - 0.505091940096 - 0.505457740019 - 0.505823800019 - 0.50619012028 - 0.506556700987 - 0.506923542326 - 0.507290644482 - 0.50765800764 - 0.508025631986 - 0.508393517706 - 0.508761664985 - 0.50913007401 - 0.509498744966 - 0.50986767804 - 0.510236873417 - 0.510606331286 - 0.510976051832 - 0.511346035241 - 0.511716281702 - 0.5120867914 - 0.512457564524 - 0.512828601259 - 0.513199901795 - 0.513571466318 - 0.513943295015 - 0.514315388076 - 0.514687745687 - 0.515060368038 - 0.515433255315 - 0.515806407708 - 0.516179825405 - 0.516553508594 - 0.516927457465 - 0.517301672206 - 0.517676153006 - 0.518050900054 - 0.51842591354 - 0.518801193654 - 0.519176740584 - 0.51955255452 - 0.519928635653 - 0.520304984172 - 0.520681600267 - 0.521058484129 - 0.521435635948 - 0.521813055914 - 0.522190744219 - 0.522568701052 - 0.522946926605 - 0.523325421069 - 0.523704184635 - 0.524083217494 - 0.524462519838 - 0.524842091859 - 0.525221933748 - 0.525602045697 - 0.525982427897 - 0.526363080542 - 0.526744003824 - 0.527125197934 - 0.527506663066 - 0.527888399412 - 0.528270407165 - 0.528652686518 - 0.529035237664 - 0.529418060796 - 0.529801156108 - 0.530184523793 - 0.530568164045 - 0.530952077057 - 0.531336263024 - 0.531720722139 - 0.532105454598 - 0.532490460593 - 0.53287574032 - 0.533261293974 - 0.533647121748 - 0.534033223838 - 0.534419600439 - 0.534806251746 - 0.535193177955 - 0.53558037926 - 0.535967855858 - 0.536355607944 - 0.536743635714 - 0.537131939364 - 0.537520519091 - 0.53790937509 - 0.538298507557 - 0.53868791669 - 0.539077602686 - 0.53946756574 - 0.53985780605 - 0.540248323814 - 0.540639119227 - 0.541030192489 - 0.541421543796 - 0.541813173346 - 0.542205081336 - 0.542597267966 - 0.542989733432 - 0.543382477934 - 0.543775501669 - 0.544168804836 - 0.544562387634 - 0.544956250262 - 0.545350392918 - 0.545744815801 - 0.546139519112 - 0.546534503048 - 0.546929767811 - 0.547325313598 - 0.547721140611 - 0.548117249049 - 0.548513639113 - 0.548910311002 - 0.549307264916 - 0.549704501057 - 0.550102019625 - 0.550499820821 - 0.550897904846 - 0.5512962719 - 0.551694922186 - 0.552093855903 - 0.552493073255 - 0.552892574443 - 0.553292359668 - 0.553692429132 - 0.554092783038 - 0.554493421587 - 0.554894344982 - 0.555295553426 - 0.555697047122 - 0.556098826271 - 0.556500891077 - 0.556903241744 - 0.557305878473 - 0.55770880147 - 0.558112010936 - 0.558515507077 - 0.558919290095 - 0.559323360195 - 0.559727717581 - 0.560132362457 - 0.560537295028 - 0.560942515497 - 0.56134802407 - 0.561753820952 - 0.562159906347 - 0.562566280461 - 0.562972943499 - 0.563379895666 - 0.563787137168 - 0.56419466821 - 0.564602489 - 0.565010599741 - 0.565419000641 - 0.565827691907 - 0.566236673743 - 0.566645946358 - 0.567055509957 - 0.567465364748 - 0.567875510937 - 0.568285948732 - 0.568696678341 - 0.56910769997 - 0.569519013827 - 0.56993062012 - 0.570342519057 - 0.570754710846 - 0.571167195695 - 0.571579973813 - 0.571993045408 - 0.572406410688 - 0.572820069863 - 0.573234023141 - 0.573648270732 - 0.574062812845 - 0.574477649689 - 0.574892781474 - 0.575308208409 - 0.575723930705 - 0.576139948571 - 0.576556262217 - 0.576972871854 - 0.577389777692 - 0.577806979942 - 0.578224478815 - 0.57864227452 - 0.579060367271 - 0.579478757277 - 0.57989744475 - 0.580316429901 - 0.580735712943 - 0.581155294086 - 0.581575173544 - 0.581995351527 - 0.582415828248 - 0.58283660392 - 0.583257678756 - 0.583679052967 - 0.584100726767 - 0.584522700368 - 0.584944973984 - 0.585367547829 - 0.585790422115 - 0.586213597056 - 0.586637072867 - 0.58706084976 - 0.58748492795 - 0.587909307651 - 0.588333989078 - 0.588758972445 - 0.589184257967 - 0.589609845858 - 0.590035736334 - 0.590461929609 - 0.5908884259 - 0.591315225421 - 0.591742328387 - 0.592169735016 - 0.592597445522 - 0.593025460122 - 0.593453779031 - 0.593882402467 - 0.594311330646 - 0.594740563784 - 0.595170102099 - 0.595599945806 - 0.596030095124 - 0.596460550269 - 0.59689131146 - 0.597322378913 - 0.597753752847 - 0.598185433479 - 0.598617421027 - 0.59904971571 - 0.599482317746 - 0.599915227353 - 0.60034844475 - 0.600781970157 - 0.601215803791 - 0.601649945872 - 0.60208439662 - 0.602519156254 - 0.602954224993 - 0.603389603057 - 0.603825290667 - 0.604261288042 - 0.604697595402 - 0.605134212968 - 0.605571140961 - 0.6060083796 - 0.606445929108 - 0.606883789704 - 0.607321961611 - 0.60776044505 - 0.608199240241 - 0.608638347407 - 0.60907776677 - 0.609517498551 - 0.609957542972 - 0.610397900257 - 0.610838570626 - 0.611279554304 - 0.611720851512 - 0.612162462474 - 0.612604387412 - 0.61304662655 - 0.613489180112 - 0.61393204832 - 0.614375231399 - 0.614818729572 - 0.615262543063 - 0.615706672097 - 0.616151116898 - 0.616595877691 - 0.617040954699 - 0.617486348149 - 0.617932058264 - 0.618378085271 - 0.618824429393 - 0.619271090858 - 0.61971806989 - 0.620165366715 - 0.62061298156 - 0.621060914649 - 0.62150916621 - 0.621957736469 - 0.622406625653 - 0.622855833988 - 0.623305361701 - 0.62375520902 - 0.624205376171 - 0.624655863382 - 0.62510667088 - 0.625557798893 - 0.62600924765 - 0.626461017378 - 0.626913108305 - 0.627365520659 - 0.62781825467 - 0.628271310566 - 0.628724688575 - 0.629178388928 - 0.629632411852 - 0.630086757577 - 0.630541426333 - 0.63099641835 - 0.631451733857 - 0.631907373084 - 0.632363336262 - 0.632819623621 - 0.63327623539 - 0.633733171802 - 0.634190433086 - 0.634648019475 - 0.635105931197 - 0.635564168486 - 0.636022731573 - 0.636481620689 - 0.636940836066 - 0.637400377936 - 0.637860246531 - 0.638320442084 - 0.638780964826 - 0.639241814991 - 0.639702992811 - 0.64016449852 - 0.64062633235 - 0.641088494534 - 0.641550985307 - 0.642013804902 - 0.642476953552 - 0.642940431491 - 0.643404238955 - 0.643868376176 - 0.644332843389 - 0.644797640829 - 0.645262768732 - 0.64572822733 - 0.646194016861 - 0.646660137559 - 0.647126589659 - 0.647593373398 - 0.64806048901 - 0.648527936733 - 0.648995716801 - 0.649463829452 - 0.649932274921 - 0.650401053446 - 0.650870165264 - 0.65133961061 - 0.651809389723 - 0.652279502839 - 0.652749950197 - 0.653220732033 - 0.653691848586 - 0.654163300093 - 0.654635086793 - 0.655107208924 - 0.655579666724 - 0.656052460432 - 0.656525590288 - 0.656999056529 - 0.657472859396 - 0.657946999126 - 0.658421475961 - 0.65889629014 - 0.659371441901 - 0.659846931487 - 0.660322759136 - 0.660798925089 - 0.661275429586 - 0.661752272869 - 0.662229455178 - 0.662706976754 - 0.663184837838 - 0.663663038672 - 0.664141579498 - 0.664620460556 - 0.665099682089 - 0.66557924434 - 0.666059147549 - 0.666539391961 - 0.667019977816 - 0.667500905359 - 0.667982174831 - 0.668463786476 - 0.668945740538 - 0.66942803726 - 0.669910676885 - 0.670393659657 - 0.67087698582 - 0.671360655618 - 0.671844669297 - 0.672329027099 - 0.67281372927 - 0.673298776055 - 0.673784167698 - 0.674269904445 - 0.674755986542 - 0.675242414233 - 0.675729187764 - 0.676216307382 - 0.676703773332 - 0.677191585861 - 0.677679745215 - 0.67816825164 - 0.678657105384 - 0.679146306693 - 0.679635855815 - 0.680125752996 - 0.680615998484 - 0.681106592527 - 0.681597535373 - 0.68208882727 - 0.682580468465 - 0.683072459207 - 0.683564799745 - 0.684057490327 - 0.684550531203 - 0.685043922621 - 0.68553766483 - 0.68603175808 - 0.686526202621 - 0.687020998702 - 0.687516146573 - 0.688011646485 - 0.688507498687 - 0.68900370343 - 0.689500260965 - 0.689997171542 - 0.690494435413 - 0.690992052829 - 0.691490024041 - 0.6919883493 - 0.692487028859 - 0.692986062969 - 0.693485451882 - 0.693985195851 - 0.694485295128 - 0.694985749966 - 0.695486560617 - 0.695987727335 - 0.696489250372 - 0.696991129982 - 0.697493366419 - 0.697995959935 - 0.698498910786 - 0.699002219225 - 0.699505885506 - 0.700009909883 - 0.700514292613 - 0.701019033948 - 0.701524134144 - 0.702029593456 - 0.702535412141 - 0.703041590452 - 0.703548128645 - 0.704055026978 - 0.704562285705 - 0.705069905083 - 0.705577885368 - 0.706086226817 - 0.706594929687 - 0.707103994234 - 0.707613420716 - 0.708123209391 - 0.708633360515 - 0.709143874346 - 0.709654751142 - 0.710165991162 - 0.710677594663 - 0.711189561904 - 0.711701893144 - 0.712214588641 - 0.712727648654 - 0.713241073443 - 0.713754863267 - 0.714269018385 - 0.714783539057 - 0.715298425543 - 0.715813678103 - 0.716329296998 - 0.716845282487 - 0.717361634832 - 0.717878354293 - 0.718395441131 - 0.718912895608 - 0.719430717984 - 0.719948908522 - 0.720467467483 - 0.72098639513 - 0.721505691723 - 0.722025357526 - 0.722545392802 - 0.723065797812 - 0.723586572819 - 0.724107718087 - 0.72462923388 - 0.725151120459 - 0.72567337809 - 0.726196007035 - 0.726719007559 - 0.727242379927 - 0.727766124401 - 0.728290241248 - 0.728814730731 - 0.729339593116 - 0.729864828667 - 0.730390437651 - 0.730916420332 - 0.731442776976 - 0.731969507849 - 0.732496613218 - 0.733024093348 - 0.733551948506 - 0.734080178959 - 0.734608784972 - 0.735137766815 - 0.735667124752 - 0.736196859053 - 0.736726969985 - 0.737257457814 - 0.73778832281 - 0.738319565241 - 0.738851185374 - 0.739383183479 - 0.739915559824 - 0.740448314678 - 0.74098144831 - 0.741514960989 - 0.742048852985 - 0.742583124568 - 0.743117776007 - 0.743652807573 - 0.744188219536 - 0.744724012166 - 0.745260185734 - 0.745796740511 - 0.746333676767 - 0.746870994775 - 0.747408694805 - 0.747946777129 - 0.748485242018 - 0.749024089746 - 0.749563320584 - 0.750102934804 - 0.750642932679 - 0.751183314482 - 0.751724080486 - 0.752265230963 - 0.752806766188 - 0.753348686433 - 0.753890991973 - 0.754433683082 - 0.754976760033 - 0.755520223101 - 0.756064072561 - 0.756608308686 - 0.757152931753 - 0.757697942036 - 0.758243339811 - 0.758789125352 - 0.759335298936 - 0.759881860839 - 0.760428811336 - 0.760976150704 - 0.76152387922 - 0.76207199716 - 0.762620504801 - 0.76316940242 - 0.763718690294 - 0.764268368701 - 0.764818437918 - 0.765368898224 - 0.765919749896 - 0.766470993212 - 0.767022628452 - 0.767574655893 - 0.768127075815 - 0.768679888496 - 0.769233094217 - 0.769786693255 - 0.770340685892 - 0.770895072406 - 0.771449853078 - 0.772005028188 - 0.772560598017 - 0.773116562845 - 0.773672922952 - 0.774229678621 - 0.774786830132 - 0.775344377766 - 0.775902321806 - 0.776460662533 - 0.777019400229 - 0.777578535177 - 0.778138067658 - 0.778697997956 - 0.779258326353 - 0.779819053133 - 0.780380178578 - 0.780941702972 - 0.781503626599 - 0.782065949743 - 0.782628672687 - 0.783191795716 - 0.783755319114 - 0.784319243166 - 0.784883568157 - 0.785448294372 - 0.786013422096 - 0.786578951614 - 0.787144883213 - 0.787711217178 - 0.788277953795 - 0.788845093351 - 0.789412636131 - 0.789980582423 - 0.790548932514 - 0.79111768669 - 0.79168684524 - 0.792256408449 - 0.792826376607 - 0.793396750001 - 0.793967528919 - 0.79453871365 - 0.795110304481 - 0.795682301703 - 0.796254705602 - 0.79682751647 - 0.797400734595 - 0.797974360267 - 0.798548393775 - 0.799122835409 - 0.79969768546 - 0.800272944218 - 0.800848611974 - 0.801424689018 - 0.802001175641 - 0.802578072135 - 0.803155378791 - 0.8037330959 - 0.804311223755 - 0.804889762647 - 0.805468712869 - 0.806048074713 - 0.806627848471 - 0.807208034438 - 0.807788632905 - 0.808369644166 - 0.808951068514 - 0.809532906244 - 0.810115157648 - 0.810697823022 - 0.81128090266 - 0.811864396855 - 0.812448305903 - 0.813032630099 - 0.813617369738 - 0.814202525116 - 0.814788096527 - 0.815374084267 - 0.815960488633 - 0.816547309922 - 0.817134548428 - 0.817722204449 - 0.818310278283 - 0.818898770225 - 0.819487680573 - 0.820077009624 - 0.820666757677 - 0.821256925029 - 0.821847511978 - 0.822438518823 - 0.823029945862 - 0.823621793394 - 0.824214061718 - 0.824806751132 - 0.825399861938 - 0.825993394433 - 0.826587348918 - 0.827181725693 - 0.827776525057 - 0.828371747313 - 0.828967392759 - 0.829563461698 - 0.83015995443 - 0.830756871256 - 0.831354212479 - 0.831951978399 - 0.832550169319 - 0.833148785541 - 0.833747827367 - 0.834347295099 - 0.834947189042 - 0.835547509497 - 0.836148256768 - 0.836749431158 - 0.837351032972 - 0.837953062512 - 0.838555520084 - 0.839158405991 - 0.839761720537 - 0.840365464029 - 0.84096963677 - 0.841574239066 - 0.842179271222 - 0.842784733544 - 0.843390626338 - 0.843996949909 - 0.844603704564 - 0.84521089061 - 0.845818508353 - 0.846426558101 - 0.847035040159 - 0.847643954837 - 0.84825330244 - 0.848863083278 - 0.849473297657 - 0.850083945887 - 0.850695028276 - 0.851306545132 - 0.851918496764 - 0.852530883482 - 0.853143705595 - 0.853756963412 - 0.854370657243 - 0.854984787399 - 0.855599354188 - 0.856214357923 - 0.856829798913 - 0.857445677469 - 0.858061993903 - 0.858678748525 - 0.859295941648 - 0.859913573583 - 0.860531644641 - 0.861150155136 - 0.86176910538 - 0.862388495685 - 0.863008326364 - 0.863628597731 - 0.864249310098 - 0.86487046378 - 0.865492059089 - 0.86611409634 - 0.866736575847 - 0.867359497925 - 0.867982862888 - 0.868606671052 - 0.86923092273 - 0.869855618239 - 0.870480757894 - 0.871106342011 - 0.871732370906 - 0.872358844895 - 0.872985764295 - 0.873613129422 - 0.874240940593 - 0.874869198125 - 0.875497902336 - 0.876127053543 - 0.876756652064 - 0.877386698217 - 0.87801719232 - 0.878648134693 - 0.879279525652 - 0.879911365519 - 0.88054365461 - 0.881176393247 - 0.881809581748 - 0.882443220434 - 0.883077309625 - 0.88371184964 - 0.8843468408 - 0.884982283427 - 0.885618177841 - 0.886254524363 - 0.886891323314 - 0.887528575017 - 0.888166279794 - 0.888804437966 - 0.889443049855 - 0.890082115786 - 0.890721636079 - 0.891361611058 - 0.892002041047 - 0.892642926369 - 0.893284267348 - 0.893926064307 - 0.894568317572 - 0.895211027465 - 0.895854194313 - 0.896497818439 - 0.89714190017 - 0.89778643983 - 0.898431437744 - 0.89907689424 - 0.899722809642 - 0.900369184277 - 0.901016018471 - 0.901663312552 - 0.902311066847 - 0.902959281681 - 0.903607957384 - 0.904257094282 - 0.904906692703 - 0.905556752976 - 0.906207275429 - 0.906858260391 - 0.90750970819 - 0.908161619155 - 0.908813993616 - 0.909466831903 - 0.910120134344 - 0.910773901271 - 0.911428133013 - 0.9120828299 - 0.912737992264 - 0.913393620436 - 0.914049714746 - 0.914706275526 - 0.915363303108 - 0.916020797824 - 0.916678760005 - 0.917337189984 - 0.917996088094 - 0.918655454667 - 0.919315290037 - 0.919975594536 - 0.920636368499 - 0.92129761226 - 0.921959326151 - 0.922621510508 - 0.923284165665 - 0.923947291956 - 0.924610889717 - 0.925274959283 - 0.925939500989 - 0.926604515171 - 0.927270002165 - 0.927935962307 - 0.928602395934 - 0.929269303381 - 0.929936684987 - 0.930604541087 - 0.93127287202 - 0.931941678123 - 0.932610959734 - 0.933280717191 - 0.933950950832 - 0.934621660996 - 0.935292848021 - 0.935964512247 - 0.936636654013 - 0.937309273659 - 0.937982371524 - 0.938655947948 - 0.939330003271 - 0.940004537834 - 0.940679551978 - 0.941355046044 - 0.942031020372 - 0.942707475305 - 0.943384411184 - 0.944061828351 - 0.944739727148 - 0.945418107918 - 0.946096971002 - 0.946776316746 - 0.94745614549 - 0.948136457579 - 0.948817253356 - 0.949498533166 - 0.950180297352 - 0.950862546259 - 0.951545280232 - 0.952228499614 - 0.952912204753 - 0.953596395991 - 0.954281073677 - 0.954966238154 - 0.95565188977 - 0.956338028871 - 0.957024655802 - 0.957711770912 - 0.958399374547 - 0.959087467055 - 0.959776048783 - 0.960465120079 - 0.96115468129 - 0.961844732766 - 0.962535274855 - 0.963226307906 - 0.963917832267 - 0.964609848289 - 0.96530235632 - 0.965995356711 - 0.966688849811 - 0.967382835971 - 0.968077315541 - 0.968772288873 - 0.969467756316 - 0.970163718224 - 0.970860174946 - 0.971557126835 - 0.972254574244 - 0.972952517523 - 0.973650957026 - 0.974349893106 - 0.975049326116 - 0.975749256409 - 0.976449684338 - 0.977150610257 - 0.977852034521 - 0.978553957484 - 0.9792563795 - 0.979959300924 - 0.980662722111 - 0.981366643417 - 0.982071065196 - 0.982775987806 - 0.983481411602 - 0.98418733694 - 0.984893764176 - 0.985600693669 - 0.986308125774 - 0.98701606085 - 0.987724499253 - 0.988433441342 - 0.989142887475 - 0.98985283801 - 0.990563293306 - 0.991274253721 - 0.991985719615 - 0.992697691347 - 0.993410169277 - 0.994123153764 - 0.99483664517 - 0.995550643853 - 0.996265150176 - 0.996980164498 - 0.997695687181 - 0.998411718587 - 0.999128259076 - 0.999845309012 - 1.00056286876 - 1.00128093867 - 1.00199951912 - 1.00271861046 - 1.00343821307 - 1.0041583273 - 1.00487895351 - 1.00560009208 - 1.00632174336 - 1.00704390772 - 1.00776658552 - 1.00848977714 - 1.00921348292 - 1.00993770325 - 1.01066243849 - 1.011387689 - 1.01211345515 - 1.0128397373 - 1.01356653582 - 1.01429385109 - 1.01502168346 - 1.0157500333 - 1.01647890099 - 1.01720828689 - 1.01793819136 - 1.01866861479 - 1.01939955753 - 1.02013101996 - 1.02086300244 - 1.02159550534 - 1.02232852905 - 1.02306207391 - 1.02379614032 - 1.02453072862 - 1.02526583921 - 1.02600147245 - 1.02673762871 - 1.02747430835 - 1.02821151177 - 1.02894923932 - 1.02968749138 - 1.03042626832 - 1.03116557052 - 1.03190539835 - 1.03264575218 - 1.03338663239 - 1.03412803935 - 1.03486997343 - 1.03561243502 - 1.03635542448 - 1.03709894219 - 1.03784298853 - 1.03858756387 - 1.03933266858 - 1.04007830306 - 1.04082446766 - 1.04157116277 - 1.04231838877 - 1.04306614603 - 1.04381443493 - 1.04456325585 - 1.04531260917 - 1.04606249526 - 1.04681291451 - 1.04756386728 - 1.04831535398 - 1.04906737496 - 1.04981993061 - 1.05057302132 - 1.05132664746 - 1.05208080942 - 1.05283550756 - 1.05359074229 - 1.05434651397 - 1.05510282299 - 1.05585966972 - 1.05661705457 - 1.05737497789 - 1.05813344009 - 1.05889244154 - 1.05965198262 - 1.06041206372 - 1.06117268523 - 1.06193384752 - 1.06269555098 - 1.063457796 - 1.06422058296 - 1.06498391224 - 1.06574778424 - 1.06651219934 - 1.06727715791 - 1.06804266036 - 1.06880870707 - 1.06957529842 - 1.0703424348 - 1.0711101166 - 1.07187834421 - 1.07264711801 - 1.0734164384 - 1.07418630575 - 1.07495672047 - 1.07572768294 - 1.07649919354 - 1.07727125268 - 1.07804386073 - 1.07881701809 - 1.07959072515 - 1.0803649823 - 1.08113978994 - 1.08191514844 - 1.08269105821 - 1.08346751964 - 1.08424453311 - 1.08502209903 - 1.08580021778 - 1.08657888976 - 1.08735811536 - 1.08813789497 - 1.08891822899 - 1.08969911781 - 1.09048056183 - 1.09126256144 - 1.09204511703 - 1.09282822901 - 1.09361189776 - 1.09439612369 - 1.09518090718 - 1.09596624864 - 1.09675214847 - 1.09753860705 - 1.09832562479 - 1.09911320208 - 1.09990133933 - 1.10069003692 - 1.10147929527 - 1.10226911476 - 1.10305949579 - 1.10385043877 - 1.1046419441 - 1.10543401217 - 1.10622664339 - 1.10701983815 - 1.10781359685 - 1.10860791991 - 1.10940280771 - 1.11019826066 - 1.11099427916 - 1.11179086361 - 1.11258801442 - 1.11338573199 - 1.11418401672 - 1.11498286902 - 1.11578228928 - 1.11658227791 - 1.11738283533 - 1.11818396192 - 1.11898565809 - 1.11978792426 - 1.12059076082 - 1.12139416818 - 1.12219814675 - 1.12300269694 - 1.12380781914 - 1.12461351376 - 1.12541978122 - 1.12622662192 - 1.12703403627 - 1.12784202468 - 1.12865058754 - 1.12945972528 - 1.1302694383 - 1.13107972701 - 1.13189059182 - 1.13270203314 - 1.13351405138 - 1.13432664694 - 1.13513982025 - 1.1359535717 - 1.13676790172 - 1.13758281071 - 1.13839829908 - 1.13921436725 - 1.14003101563 - 1.14084824462 - 1.14166605466 - 1.14248444613 - 1.14330341947 - 1.14412297508 - 1.14494311338 - 1.14576383479 - 1.1465851397 - 1.14740702855 - 1.14822950175 - 1.14905255971 - 1.14987620285 - 1.15070043158 - 1.15152524632 - 1.15235064748 - 1.1531766355 - 1.15400321077 - 1.15483037372 - 1.15565812477 - 1.15648646433 - 1.15731539282 - 1.15814491067 - 1.15897501829 - 1.1598057161 - 1.16063700451 - 1.16146888396 - 1.16230135486 - 1.16313441762 - 1.16396807268 - 1.16480232045 - 1.16563716136 - 1.16647259581 - 1.16730862425 - 1.16814524709 - 1.16898246474 - 1.16982027765 - 1.17065868622 - 1.17149769088 - 1.17233729206 - 1.17317749018 - 1.17401828566 - 1.17485967894 - 1.17570167042 - 1.17654426055 - 1.17738744974 - 1.17823123842 - 1.17907562702 - 1.17992061596 - 1.18076620567 - 1.18161239658 - 1.18245918911 - 1.1833065837 - 1.18415458076 - 1.18500318074 - 1.18585238406 - 1.18670219114 - 1.18755260241 - 1.18840361832 - 1.18925523927 - 1.19010746572 - 1.19096029808 - 1.19181373678 - 1.19266778227 - 1.19352243496 - 1.1943776953 - 1.1952335637 - 1.19609004062 - 1.19694712647 - 1.19780482169 - 1.19866312672 - 1.19952204198 - 1.20038156792 - 1.20124170496 - 1.20210245354 - 1.2029638141 - 1.20382578707 - 1.20468837288 - 1.20555157198 - 1.20641538479 - 1.20727981176 - 1.20814485331 - 1.2090105099 - 1.20987678194 - 1.2107436699 - 1.21161117419 - 1.21247929526 - 1.21334803354 - 1.21421738948 - 1.21508736352 - 1.21595795609 - 1.21682916763 - 1.21770099859 - 1.21857344941 - 1.21944652052 - 1.22032021236 - 1.22119452538 - 1.22206946002 - 1.22294501673 - 1.22382119593 - 1.22469799809 - 1.22557542363 - 1.226453473 - 1.22733214665 - 1.22821144502 - 1.22909136855 - 1.22997191769 - 1.23085309288 - 1.23173489457 - 1.23261732321 - 1.23350037923 - 1.23438406309 - 1.23526837523 - 1.2361533161 - 1.23703888615 - 1.23792508582 - 1.23881191555 - 1.23969937581 - 1.24058746703 - 1.24147618967 - 1.24236554417 - 1.24325553099 - 1.24414615057 - 1.24503740336 - 1.24592928981 - 1.24682181038 - 1.24771496551 - 1.24860875566 - 1.24950318128 - 1.25039824281 - 1.25129394071 - 1.25219027544 - 1.25308724745 - 1.25398485718 - 1.2548831051 - 1.25578199165 - 1.25668151729 - 1.25758168248 - 1.25848248767 - 1.25938393331 - 1.26028601986 - 1.26118874778 - 1.26209211752 - 1.26299612954 - 1.26390078429 - 1.26480608223 - 1.26571202383 - 1.26661860953 - 1.26752583979 - 1.26843371508 - 1.26934223584 - 1.27025140255 - 1.27116121566 - 1.27207167562 - 1.27298278291 - 1.27389453797 - 1.27480694128 - 1.27571999328 - 1.27663369445 - 1.27754804524 - 1.27846304611 - 1.27937869754 - 1.28029499997 - 1.28121195387 - 1.28212955972 - 1.28304781796 - 1.28396672906 - 1.28488629349 - 1.28580651172 - 1.2867273842 - 1.2876489114 - 1.28857109379 - 1.28949393184 - 1.290417426 - 1.29134157675 - 1.29226638455 - 1.29319184987 - 1.29411797318 - 1.29504475495 - 1.29597219564 - 1.29690029572 - 1.29782905566 - 1.29875847593 - 1.299688557 - 1.30061929934 - 1.30155070342 - 1.30248276971 - 1.30341549867 - 1.3043488908 - 1.30528294654 - 1.30621766638 - 1.30715305079 - 1.30808910023 - 1.30902581519 - 1.30996319614 - 1.31090124354 - 1.31183995788 - 1.31277933962 - 1.31371938925 - 1.31466010723 - 1.31560149404 - 1.31654355016 - 1.31748627607 - 1.31842967223 - 1.31937373913 - 1.32031847725 - 1.32126388705 - 1.32220996902 - 1.32315672364 - 1.32410415138 - 1.32505225272 - 1.32600102814 - 1.32695047813 - 1.32790060315 - 1.32885140369 - 1.32980288024 - 1.33075503326 - 1.33170786325 - 1.33266137068 - 1.33361555604 - 1.3345704198 - 1.33552596245 - 1.33648218447 - 1.33743908635 - 1.33839666857 - 1.33935493161 - 1.34031387595 - 1.34127350208 - 1.34223381049 - 1.34319480166 - 1.34415647608 - 1.34511883423 - 1.34608187659 - 1.34704560366 - 1.34801001592 - 1.34897511386 - 1.34994089796 - 1.35090736871 - 1.35187452661 - 1.35284237214 - 1.35381090579 - 1.35478012804 - 1.35575003939 - 1.35672064033 - 1.35769193135 - 1.35866391294 - 1.35963658558 - 1.36060994978 - 1.36158400602 - 1.3625587548 - 1.3635341966 - 1.36451033192 - 1.36548716125 - 1.36646468509 - 1.36744290394 - 1.36842181827 - 1.36940142859 - 1.3703817354 - 1.37136273919 - 1.37234444045 - 1.37332683968 - 1.37430993737 - 1.37529373403 - 1.37627823015 - 1.37726342623 - 1.37824932276 - 1.37923592024 - 1.38022321918 - 1.38121122006 - 1.38219992339 - 1.38318932968 - 1.38417943941 - 1.38517025309 - 1.38616177122 - 1.38715399429 - 1.38814692282 - 1.3891405573 - 1.39013489824 - 1.39112994613 - 1.39212570148 - 1.39312216479 - 1.39411933657 - 1.39511721732 - 1.39611580754 - 1.39711510774 - 1.39811511843 - 1.3991158401 - 1.40011727326 - 1.40111941842 - 1.40212227609 - 1.40312584677 - 1.40413013097 - 1.40513512919 - 1.40614084195 - 1.40714726975 - 1.4081544131 - 1.40916227251 - 1.41017084849 - 1.41118014154 - 1.41219015219 - 1.41320088093 - 1.41421232827 - 1.41522449474 - 1.41623738084 - 1.41725098708 - 1.41826531397 - 1.41928036203 - 1.42029613177 - 1.4213126237 - 1.42232983833 - 1.42334777619 - 1.42436643778 - 1.42538582361 - 1.42640593421 - 1.42742677009 - 1.42844833176 - 1.42947061975 - 1.43049363456 - 1.43151737671 - 1.43254184672 - 1.43356704511 - 1.4345929724 - 1.4356196291 - 1.43664701573 - 1.43767513281 - 1.43870398087 - 1.43973356041 - 1.44076387197 - 1.44179491606 - 1.4428266932 - 1.44385920391 - 1.44489244871 - 1.44592642814 - 1.4469611427 - 1.44799659292 - 1.44903277933 - 1.45006970245 - 1.45110736279 - 1.4521457609 - 1.45318489728 - 1.45422477247 - 1.45526538699 - 1.45630674137 - 1.45734883613 - 1.45839167179 - 1.4594352489 - 1.46047956796 - 1.46152462952 - 1.46257043409 - 1.46361698221 - 1.4646642744 - 1.4657123112 - 1.46676109314 - 1.46781062073 - 1.46886089452 - 1.46991191503 - 1.4709636828 - 1.47201619835 - 1.47306946222 - 1.47412347494 - 1.47517823704 - 1.47623374906 - 1.47729001153 - 1.47834702497 - 1.47940478994 - 1.48046330695 - 1.48152257655 - 1.48258259926 - 1.48364337563 - 1.4847049062 - 1.48576719149 - 1.48683023204 - 1.48789402839 - 1.48895858109 - 1.49002389066 - 1.49108995764 - 1.49215678257 - 1.493224366 - 1.49429270845 - 1.49536181048 - 1.49643167262 - 1.49750229541 - 1.49857367939 - 1.4996458251 - 1.50071873308 - 1.50179240389 - 1.50286683805 - 1.50394203611 - 1.50501799862 - 1.50609472611 - 1.50717221914 - 1.50825047824 - 1.50932950397 - 1.51040929686 - 1.51148985746 - 1.51257118632 - 1.51365328398 - 1.51473615099 - 1.5158197879 - 1.51690419525 - 1.5179893736 - 1.51907532348 - 1.52016204546 - 1.52124954007 - 1.52233780787 - 1.5234268494 - 1.52451666523 - 1.52560725589 - 1.52669862193 - 1.52779076392 - 1.5288836824 - 1.52997737792 - 1.53107185104 - 1.53216710231 - 1.53326313228 - 1.5343599415 - 1.53545753054 - 1.53655589993 - 1.53765505025 - 1.53875498204 - 1.53985569586 - 1.54095719227 - 1.54205947182 - 1.54316253506 - 1.54426638257 - 1.54537101488 - 1.54647643257 - 1.54758263619 - 1.5486896263 - 1.54979740345 - 1.55090596822 - 1.55201532115 - 1.55312546281 - 1.55423639375 - 1.55534811455 - 1.55646062576 - 1.55757392794 - 1.55868802166 - 1.55980290747 - 1.56091858595 - 1.56203505765 - 1.56315232314 - 1.56427038299 - 1.56538923775 - 1.566508888 - 1.5676293343 - 1.56875057721 - 1.5698726173 - 1.57099545514 - 1.5721190913 - 1.57324352634 - 1.57436876083 - 1.57549479534 - 1.57662163044 - 1.5777492667 - 1.57887770468 - 1.58000694496 - 1.5811369881 - 1.58226783469 - 1.58339948528 - 1.58453194046 - 1.58566520079 - 1.58679926684 - 1.5879341392 - 1.58906981842 - 1.59020630509 - 1.59134359978 - 1.59248170306 - 1.59362061552 - 1.59476033771 - 1.59590087023 - 1.59704221364 - 1.59818436853 - 1.59932733546 - 1.60047111502 - 1.60161570779 - 1.60276111434 - 1.60390733525 - 1.6050543711 - 1.60620222247 - 1.60735088993 - 1.60850037408 - 1.60965067549 - 1.61080179474 - 1.61195373242 - 1.6131064891 - 1.61426006536 - 1.6154144618 - 1.61656967899 - 1.61772571751 - 1.61888257796 - 1.62004026091 - 1.62119876695 - 1.62235809666 - 1.62351825063 - 1.62467922946 - 1.62584103371 - 1.62700366398 - 1.62816712087 - 1.62933140494 - 1.6304965168 - 1.63166245703 - 1.63282922622 - 1.63399682496 - 1.63516525384 - 1.63633451345 - 1.63750460438 - 1.63867552722 - 1.63984728256 - 1.641019871 - 1.64219329313 - 1.64336754953 - 1.64454264081 - 1.64571856756 - 1.64689533036 - 1.64807292983 - 1.64925136654 - 1.65043064109 - 1.65161075409 - 1.65279170612 - 1.65397349779 - 1.65515612969 - 1.65633960241 - 1.65752391656 - 1.65870907274 - 1.65989507153 - 1.66108191355 - 1.66226959939 - 1.66345812965 - 1.66464750493 - 1.66583772584 - 1.66702879297 - 1.66822070692 - 1.6694134683 - 1.67060707771 - 1.67180153575 - 1.67299684303 - 1.67419300015 - 1.67539000771 - 1.67658786632 - 1.67778657659 - 1.67898613911 - 1.6801865545 - 1.68138782336 - 1.6825899463 - 1.68379292392 - 1.68499675684 - 1.68620144566 - 1.68740699098 - 1.68861339343 - 1.68982065361 - 1.69102877212 - 1.69223774958 - 1.6934475866 - 1.69465828379 - 1.69586984177 - 1.69708226113 - 1.6982955425 - 1.69950968649 - 1.70072469372 - 1.70194056479 - 1.70315730032 - 1.70437490092 - 1.70559336721 - 1.70681269981 - 1.70803289934 - 1.70925396639 - 1.71047590161 - 1.71169870559 - 1.71292237896 - 1.71414692235 - 1.71537233635 - 1.71659862161 - 1.71782577872 - 1.71905380832 - 1.72028271103 - 1.72151248746 - 1.72274313824 - 1.72397466398 - 1.72520706532 - 1.72644034287 - 1.72767449726 - 1.7289095291 - 1.73014543903 - 1.73138222766 - 1.73261989563 - 1.73385844355 - 1.73509787206 - 1.73633818178 - 1.73757937333 - 1.73882144735 - 1.74006440445 - 1.74130824527 - 1.74255297044 - 1.74379858058 - 1.74504507633 - 1.74629245831 - 1.74754072716 - 1.7487898835 - 1.75003992796 - 1.75129086118 - 1.75254268379 - 1.75379539643 - 1.75504899971 - 1.75630349428 - 1.75755888078 - 1.75881515982 - 1.76007233206 - 1.76133039812 - 1.76258935864 - 1.76384921426 - 1.76510996561 - 1.76637161333 - 1.76763415806 - 1.76889760043 - 1.77016194108 - 1.77142718065 - 1.77269331979 - 1.77396035912 - 1.77522829929 - 1.77649714095 - 1.77776688472 - 1.77903753126 - 1.7803090812 - 1.78158153519 - 1.78285489387 - 1.78412915788 - 1.78540432786 - 1.78668040447 - 1.78795738834 - 1.78923528013 - 1.79051408047 - 1.79179379001 - 1.7930744094 - 1.79435593928 - 1.7956383803 - 1.79692173312 - 1.79820599837 - 1.79949117672 - 1.80077726879 - 1.80206427526 - 1.80335219676 - 1.80464103394 - 1.80593078747 - 1.80722145798 - 1.80851304613 - 1.80980555258 - 1.81109897797 - 1.81239332297 - 1.81368858821 - 1.81498477437 - 1.81628188209 - 1.81757991202 - 1.81887886483 - 1.82017874117 - 1.8214795417 - 1.82278126706 - 1.82408391793 - 1.82538749496 - 1.82669199881 - 1.82799743013 - 1.82930378959 - 1.83061107784 - 1.83191929555 - 1.83322844338 - 1.83453852198 - 1.83584953202 - 1.83716147417 - 1.83847434908 - 1.83978815742 - 1.84110289985 - 1.84241857704 - 1.84373518964 - 1.84505273834 - 1.84637122378 - 1.84769064664 - 1.84901100758 - 1.85033230728 - 1.85165454639 - 1.85297772559 - 1.85430184554 - 1.85562690691 - 1.85695291038 - 1.85827985661 - 1.85960774627 - 1.86093658004 - 1.86226635857 - 1.86359708256 - 1.86492875266 - 1.86626136956 - 1.86759493392 - 1.86892944641 - 1.87026490772 - 1.87160131852 - 1.87293867947 - 1.87427699127 - 1.87561625457 - 1.87695647007 - 1.87829763843 - 1.87963976034 - 1.88098283647 - 1.8823268675 - 1.88367185411 - 1.88501779697 - 1.88636469678 - 1.88771255421 - 1.88906136993 - 1.89041114464 - 1.89176187901 - 1.89311357372 - 1.89446622946 - 1.89581984692 - 1.89717442677 - 1.8985299697 - 1.89988647639 - 1.90124394753 - 1.90260238381 - 1.90396178591 - 1.90532215451 - 1.90668349031 - 1.908045794 - 1.90940906625 - 1.91077330777 - 1.91213851923 - 1.91350470133 - 1.91487185476 - 1.91623998021 - 1.91760907837 - 1.91897914993 - 1.92035019558 - 1.92172221602 - 1.92309521194 - 1.92446918403 - 1.92584413299 - 1.92722005951 - 1.92859696429 - 1.92997484802 - 1.93135371139 - 1.93273355512 - 1.93411437988 - 1.93549618638 - 1.93687897532 - 1.93826274739 - 1.9396475033 - 1.94103324375 - 1.94241996942 - 1.94380768103 - 1.94519637928 - 1.94658606486 - 1.94797673848 - 1.94936840085 - 1.95076105266 - 1.95215469461 - 1.95354932742 - 1.95494495178 - 1.95634156841 - 1.957739178 - 1.95913778126 - 1.96053737891 - 1.96193797164 - 1.96333956016 - 1.96474214518 - 1.96614572742 - 1.96755030757 - 1.96895588635 - 1.97036246447 - 1.97177004265 - 1.97317862158 - 1.97458820198 - 1.97599878456 - 1.97741037004 - 1.97882295914 - 1.98023655255 - 1.981651151 - 1.9830667552 - 1.98448336587 - 1.98590098372 - 1.98731960947 - 1.98873924383 - 1.99015988753 - 1.99158154127 - 1.99300420579 - 1.99442788179 - 1.99585256999 - 1.99727827112 - 1.99870498589 - 2.00013271503 - 2.00156145926 - 2.0029912193 - 2.00442199586 - 2.00585378968 - 2.00728660148 - 2.00872043198 - 2.0101552819 - 2.01159115198 - 2.01302804292 - 2.01446595547 - 2.01590489035 - 2.01734484828 - 2.01878582999 - 2.02022783621 - 2.02167086767 - 2.0231149251 - 2.02456000922 - 2.02600612077 - 2.02745326047 - 2.02890142907 - 2.03035062728 - 2.03180085584 - 2.03325211549 - 2.03470440695 - 2.03615773096 - 2.03761208826 - 2.03906747958 - 2.04052390565 - 2.04198136721 - 2.043439865 - 2.04489939975 - 2.0463599722 - 2.04782158309 - 2.04928423316 - 2.05074792314 - 2.05221265377 - 2.0536784258 - 2.05514523997 - 2.05661309701 - 2.05808199766 - 2.05955194268 - 2.0610229328 - 2.06249496876 - 2.06396805131 - 2.0654421812 - 2.06691735916 - 2.06839358594 - 2.06987086229 - 2.07134918896 - 2.07282856668 - 2.07430899622 - 2.07579047831 - 2.0772730137 - 2.07875660315 - 2.0802412474 - 2.0817269472 - 2.08321370331 - 2.08470151647 - 2.08619038743 - 2.08768031696 - 2.08917130579 - 2.09066335469 - 2.0921564644 - 2.09365063569 - 2.0951458693 - 2.09664216599 - 2.09813952652 - 2.09963795165 - 2.10113744212 - 2.1026379987 - 2.10413962215 - 2.10564231322 - 2.10714607268 - 2.10865090128 - 2.11015679978 - 2.11166376895 - 2.11317180954 - 2.11468092232 - 2.11619110805 - 2.11770236749 - 2.1192147014 - 2.12072811056 - 2.12224259572 - 2.12375815764 - 2.12527479711 - 2.12679251487 - 2.1283113117 - 2.12983118836 - 2.13135214563 - 2.13287418427 - 2.13439730504 - 2.13592150873 - 2.13744679609 - 2.1389731679 - 2.14050062493 - 2.14202916796 - 2.14355879775 - 2.14508951507 - 2.1466213207 - 2.14815421542 - 2.14968819999 - 2.1512232752 - 2.15275944182 - 2.15429670062 - 2.15583505238 - 2.15737449787 - 2.15891503789 - 2.16045667319 - 2.16199940457 - 2.1635432328 - 2.16508815866 - 2.16663418293 - 2.1681813064 - 2.16972952983 - 2.17127885403 - 2.17282927976 - 2.17438080782 - 2.17593343898 - 2.17748717403 - 2.17904201376 - 2.18059795894 - 2.18215501037 - 2.18371316884 - 2.18527243512 - 2.18683281002 - 2.1883942943 - 2.18995688877 - 2.19152059422 - 2.19308541143 - 2.19465134119 - 2.1962183843 - 2.19778654154 - 2.19935581372 - 2.20092620161 - 2.20249770602 - 2.20407032774 - 2.20564406756 - 2.20721892628 - 2.20879490469 - 2.21037200359 - 2.21195022377 - 2.21352956604 - 2.21511003119 - 2.21669162002 - 2.21827433333 - 2.21985817192 - 2.22144313658 - 2.22302922813 - 2.22461644735 - 2.22620479505 - 2.22779427204 - 2.22938487911 - 2.23097661707 - 2.23256948673 - 2.23416348889 - 2.23575862435 - 2.23735489392 - 2.2389522984 - 2.24055083861 - 2.24215051535 - 2.24375132943 - 2.24535328165 - 2.24695637283 - 2.24856060378 - 2.2501659753 - 2.25177248821 - 2.25338014332 - 2.25498894144 - 2.25659888339 - 2.25820996997 - 2.259822202 - 2.26143558029 - 2.26305010567 - 2.26466577894 - 2.26628260092 - 2.26790057243 - 2.26951969429 - 2.27113996731 - 2.27276139231 - 2.27438397012 - 2.27600770154 - 2.27763258741 - 2.27925862853 - 2.28088582574 - 2.28251417985 - 2.2841436917 - 2.28577436209 - 2.28740619185 - 2.28903918182 - 2.29067333281 - 2.29230864564 - 2.29394512116 - 2.29558276017 - 2.29722156351 - 2.29886153201 - 2.3005026665 - 2.30214496779 - 2.30378843674 - 2.30543307415 - 2.30707888087 - 2.30872585773 - 2.31037400555 - 2.31202332518 - 2.31367381743 - 2.31532548316 - 2.31697832319 - 2.31863233835 - 2.32028752948 - 2.32194389743 - 2.32360144301 - 2.32526016708 - 2.32692007047 - 2.32858115402 - 2.33024341857 - 2.33190686495 - 2.33357149401 - 2.33523730659 - 2.33690430352 - 2.33857248566 - 2.34024185385 - 2.34191240892 - 2.34358415172 - 2.3452570831 - 2.3469312039 - 2.34860651497 - 2.35028301714 - 2.35196071128 - 2.35363959823 - 2.35531967883 - 2.35700095394 - 2.3586834244 - 2.36036709106 - 2.36205195477 - 2.36373801639 - 2.36542527677 - 2.36711373675 - 2.3688033972 - 2.37049425896 - 2.37218632289 - 2.37387958985 - 2.37557406068 - 2.37726973625 - 2.37896661741 - 2.38066470502 - 2.38236399994 - 2.38406450302 - 2.38576621512 - 2.38746913711 - 2.38917326984 - 2.39087861418 - 2.39258517098 - 2.39429294111 - 2.39600192543 - 2.39771212481 - 2.3994235401 - 2.40113617217 - 2.4028500219 - 2.40456509013 - 2.40628137775 - 2.40799888561 - 2.40971761458 - 2.41143756554 - 2.41315873935 - 2.41488113688 - 2.416604759 - 2.41832960658 - 2.42005568049 - 2.42178298161 - 2.4235115108 - 2.42524126895 - 2.42697225692 - 2.42870447558 - 2.43043792582 - 2.43217260851 - 2.43390852452 - 2.43564567473 - 2.43738406003 - 2.43912368128 - 2.44086453937 - 2.44260663517 - 2.44434996957 - 2.44609454344 - 2.44784035767 - 2.44958741314 - 2.45133571074 - 2.45308525133 - 2.45483603582 - 2.45658806508 - 2.45834134 - 2.46009586146 - 2.46185163035 - 2.46360864756 - 2.46536691397 - 2.46712643047 - 2.46888719796 - 2.47064921732 - 2.47241248943 - 2.4741770152 - 2.47594279551 - 2.47770983126 - 2.47947812333 - 2.48124767263 - 2.48301848004 - 2.48479054645 - 2.48656387277 - 2.4883384599 - 2.49011430871 - 2.49189142012 - 2.49366979503 - 2.49544943432 - 2.4972303389 - 2.49901250966 - 2.50079594752 - 2.50258065336 - 2.50436662809 - 2.50615387262 - 2.50794238784 - 2.50973217466 - 2.51152323399 - 2.51331556672 - 2.51510917376 - 2.51690405603 - 2.51870021442 - 2.52049764984 - 2.5222963632 - 2.52409635541 - 2.52589762739 - 2.52770018003 - 2.52950401424 - 2.53130913095 - 2.53311553107 - 2.53492321549 - 2.53673218514 - 2.53854244094 - 2.54035398379 - 2.54216681461 - 2.54398093432 - 2.54579634383 - 2.54761304407 - 2.54943103594 - 2.55125032036 - 2.55307089826 - 2.55489277056 - 2.55671593817 - 2.55854040202 - 2.56036616302 - 2.5621932221 - 2.56402158019 - 2.5658512382 - 2.56768219707 - 2.56951445771 - 2.57134802105 - 2.57318288801 - 2.57501905954 - 2.57685653654 - 2.57869531995 - 2.5805354107 - 2.58237680972 - 2.58421951794 - 2.58606353628 - 2.58790886569 - 2.58975550709 - 2.59160346141 - 2.5934527296 - 2.59530331257 - 2.59715521128 - 2.59900842664 - 2.60086295961 - 2.60271881111 - 2.60457598209 - 2.60643447347 - 2.60829428621 - 2.61015542124 - 2.6120178795 - 2.61388166193 - 2.61574676947 - 2.61761320306 - 2.61948096366 - 2.62135005219 - 2.62322046961 - 2.62509221686 - 2.62696529488 - 2.62883970463 - 2.63071544704 - 2.63259252307 - 2.63447093366 - 2.63635067976 - 2.63823176233 - 2.64011418231 - 2.64199794065 - 2.64388303831 - 2.64576947623 - 2.64765725538 - 2.64954637669 - 2.65143684114 - 2.65332864967 - 2.65522180323 - 2.65711630279 - 2.65901214931 - 2.66090934373 - 2.66280788702 - 2.66470778013 - 2.66660902403 - 2.66851161968 - 2.67041556804 - 2.67232087007 - 2.67422752672 - 2.67613553898 - 2.67804490779 - 2.67995563412 - 2.68186771895 - 2.68378116322 - 2.68569596792 - 2.68761213401 - 2.68952966245 - 2.69144855422 - 2.69336881028 - 2.69529043161 - 2.69721341917 - 2.69913777393 - 2.70106349688 - 2.70299058897 - 2.70491905119 - 2.70684888451 - 2.7087800899 - 2.71071266834 - 2.7126466208 - 2.71458194827 - 2.71651865171 - 2.71845673211 - 2.72039619045 - 2.72233702771 - 2.72427924486 - 2.72622284289 - 2.72816782278 - 2.73011418552 - 2.73206193207 - 2.73401106344 - 2.7359615806 - 2.73791348454 - 2.73986677624 - 2.7418214567 - 2.74377752689 - 2.74573498782 - 2.74769384045 - 2.7496540858 - 2.75161572484 - 2.75357875856 - 2.75554318796 - 2.75750901404 - 2.75947623777 - 2.76144486017 - 2.76341488221 - 2.7653863049 - 2.76735912924 - 2.76933335621 - 2.77130898682 - 2.77328602206 - 2.77526446294 - 2.77724431045 - 2.77922556559 - 2.78120822936 - 2.78319230277 - 2.78517778681 - 2.7871646825 - 2.78915299083 - 2.7911427128 - 2.79313384943 - 2.79512640172 - 2.79712037067 - 2.7991157573 - 2.8011125626 - 2.80311078759 - 2.80511043329 - 2.80711150069 - 2.80911399081 - 2.81111790466 - 2.81312324325 - 2.8151300076 - 2.81713819872 - 2.81914781762 - 2.82115886532 - 2.82317134284 - 2.82518525119 - 2.82720059139 - 2.82921736445 - 2.8312355714 - 2.83325521325 - 2.83527629103 - 2.83729880576 - 2.83932275845 - 2.84134815014 - 2.84337498184 - 2.84540325457 - 2.84743296937 - 2.84946412725 - 2.85149672925 - 2.85353077638 - 2.85556626969 - 2.85760321018 - 2.85964159891 - 2.86168143688 - 2.86372272514 - 2.86576546472 - 2.86780965664 - 2.86985530195 - 2.87190240166 - 2.87395095683 - 2.87600096847 - 2.87805243764 - 2.88010536535 - 2.88215975266 - 2.8842156006 - 2.8862729102 - 2.88833168251 - 2.89039191857 - 2.89245361941 - 2.89451678608 - 2.89658141962 - 2.89864752108 - 2.90071509149 - 2.90278413191 - 2.90485464337 - 2.90692662692 - 2.90900008361 - 2.91107501449 - 2.9131514206 - 2.915229303 - 2.91730866273 - 2.91938950085 - 2.92147181839 - 2.92355561643 - 2.925640896 - 2.92772765817 - 2.92981590398 - 2.93190563449 - 2.93399685076 - 2.93608955385 - 2.9381837448 - 2.94027942469 - 2.94237659456 - 2.94447525547 - 2.94657540849 - 2.94867705468 - 2.9507801951 - 2.95288483081 - 2.95499096287 - 2.95709859235 - 2.95920772031 - 2.96131834783 - 2.96343047595 - 2.96554410576 - 2.96765923831 - 2.96977587469 - 2.97189401595 - 2.97401366316 - 2.97613481741 - 2.97825747975 - 2.98038165126 - 2.98250733302 - 2.98463452609 - 2.98676323156 - 2.98889345049 - 2.99102518396 - 2.99315843306 - 2.99529319886 - 2.99742948243 - 2.99956728485 - 3.00170660721 - 3.00384745059 - 3.00598981606 - 3.00813370471 - 3.01027911763 - 3.01242605589 - 3.01457452058 - 3.01672451279 - 3.0188760336 - 3.0210290841 - 3.02318366537 - 3.02533977851 - 3.0274974246 - 3.02965660473 - 3.03181732 - 3.0339795715 - 3.03614336031 - 3.03830868754 - 3.04047555427 - 3.04264396159 - 3.04481391062 - 3.04698540243 - 3.04915843813 - 3.05133301882 - 3.05350914558 - 3.05568681954 - 3.05786604177 - 3.06004681339 - 3.0622291355 - 3.06441300919 - 3.06659843557 - 3.06878541575 - 3.07097395083 - 3.07316404191 - 3.0753556901 - 3.07754889651 - 3.07974366225 - 3.08193998842 - 3.08413787614 - 3.08633732651 - 3.08853834065 - 3.09074091967 - 3.09294506467 - 3.09515077678 - 3.0973580571 - 3.09956690676 - 3.10177732687 - 3.10398931854 - 3.10620288289 - 3.10841802104 - 3.11063473412 - 3.11285302323 - 3.1150728895 - 3.11729433405 - 3.11951735801 - 3.12174196249 - 3.12396814862 - 3.12619591752 - 3.12842527033 - 3.13065620816 - 3.13288873214 - 3.1351228434 - 3.13735854307 - 3.13959583228 - 3.14183471216 - 3.14407518383 - 3.14631724844 - 3.14856090711 - 3.15080616098 - 3.15305301118 - 3.15530145884 - 3.15755150511 - 3.15980315111 - 3.16205639799 - 3.16431124689 - 3.16656769893 - 3.16882575527 - 3.17108541704 - 3.17334668539 - 3.17560956145 - 3.17787404638 - 3.1801401413 - 3.18240784738 - 3.18467716575 - 3.18694809756 - 3.18922064396 - 3.19149480609 - 3.19377058511 - 3.19604798216 - 3.19832699839 - 3.20060763496 - 3.20288989302 - 3.20517377372 - 3.20745927821 - 3.20974640765 - 3.21203516319 - 3.214325546 - 3.21661755722 - 3.21891119801 - 3.22120646954 - 3.22350337296 - 3.22580190943 - 3.22810208012 - 3.23040388618 - 3.23270732878 - 3.23501240908 - 3.23731912825 - 3.23962748745 - 3.24193748785 - 3.24424913061 - 3.24656241691 - 3.2488773479 - 3.25119392477 - 3.25351214867 - 3.25583202079 - 3.25815354229 - 3.26047671434 - 3.26280153813 - 3.26512801481 - 3.26745614558 - 3.2697859316 - 3.27211737405 - 3.27445047412 - 3.27678523297 - 3.27912165178 - 3.28145973175 - 3.28379947404 - 3.28614087984 - 3.28848395034 - 3.29082868671 - 3.29317509015 - 3.29552316183 - 3.29787290294 - 3.30022431467 - 3.30257739821 - 3.30493215474 - 3.30728858546 - 3.30964669156 - 3.31200647422 - 3.31436793464 - 3.31673107401 - 3.31909589353 - 3.32146239438 - 3.32383057778 - 3.3262004449 - 3.32857199695 - 3.33094523513 - 3.33332016063 - 3.33569677466 - 3.33807507841 - 3.34045507309 - 3.3428367599 - 3.34522014004 - 3.34760521472 - 3.34999198514 - 3.3523804525 - 3.35477061802 - 3.3571624829 - 3.35955604834 - 3.36195131556 - 3.36434828578 - 3.36674696018 - 3.36914734 - 3.37154942644 - 3.37395322072 - 3.37635872405 - 3.37876593764 - 3.38117486271 - 3.38358550048 - 3.38599785217 - 3.38841191899 - 3.39082770217 - 3.39324520291 - 3.39566442246 - 3.39808536202 - 3.40050802282 - 3.40293240608 - 3.40535851303 - 3.4077863449 - 3.41021590291 - 3.41264718828 - 3.41508020225 - 3.41751494604 - 3.41995142089 - 3.42238962802 - 3.42482956868 - 3.42727124408 - 3.42971465546 - 3.43215980406 - 3.43460669111 - 3.43705531785 - 3.43950568551 - 3.44195779534 - 3.44441164857 - 3.44686724644 - 3.44932459019 - 3.45178368107 - 3.45424452031 - 3.45670710915 - 3.45917144885 - 3.46163754065 - 3.46410538578 - 3.46657498551 - 3.46904634107 - 3.47151945372 - 3.4739943247 - 3.47647095526 - 3.47894934666 - 3.48142950015 - 3.48391141698 - 3.4863950984 - 3.48888054567 - 3.49136776004 - 3.49385674278 - 3.49634749513 - 3.49884001835 - 3.50133431371 - 3.50383038247 - 3.50632822588 - 3.5088278452 - 3.51132924171 - 3.51383241666 - 3.51633737132 - 3.51884410695 - 3.52135262482 - 3.52386292619 - 3.52637501234 - 3.52888888454 - 3.53140454405 - 3.53392199214 - 3.53644123008 - 3.53896225916 - 3.54148508064 - 3.54400969579 - 3.54653610589 - 3.54906431222 - 3.55159431606 - 3.55412611868 - 3.55665972136 - 3.55919512538 - 3.56173233202 - 3.56427134257 - 3.5668121583 - 3.5693547805 - 3.57189921046 - 3.57444544945 - 3.57699349877 - 3.57954335971 - 3.58209503354 - 3.58464852156 - 3.58720382506 - 3.58976094534 - 3.59231988367 - 3.59488064136 - 3.59744321969 - 3.60000761997 - 3.60257384349 - 3.60514189154 - 3.60771176542 - 3.61028346643 - 3.61285699587 - 3.61543235504 - 3.61800954523 - 3.62058856776 - 3.62316942392 - 3.62575211502 - 3.62833664236 - 3.63092300725 - 3.63351121099 - 3.63610125489 - 3.63869314027 - 3.64128686842 - 3.64388244066 - 3.6464798583 - 3.64907912266 - 3.65168023504 - 3.65428319676 - 3.65688800913 - 3.65949467348 - 3.66210319111 - 3.66471356334 - 3.6673257915 - 3.6699398769 - 3.67255582086 - 3.6751736247 - 3.67779328976 - 3.68041481734 - 3.68303820878 - 3.68566346539 - 3.68829058851 - 3.69091957947 - 3.69355043958 - 3.69618317018 - 3.69881777261 - 3.70145424818 - 3.70409259823 - 3.7067328241 - 3.70937492712 - 3.71201890862 - 3.71466476994 - 3.71731251241 - 3.71996213737 - 3.72261364617 - 3.72526704014 - 3.72792232061 - 3.73057948894 - 3.73323854646 - 3.73589949452 - 3.73856233446 - 3.74122706763 - 3.74389369537 - 3.74656221903 - 3.74923263995 - 3.75190495949 - 3.754579179 - 3.75725529983 - 3.75993332332 - 3.76261325084 - 3.76529508373 - 3.76797882335 - 3.77066447106 - 3.7733520282 - 3.77604149615 - 3.77873287626 - 3.78142616988 - 3.78412137838 - 3.78681850313 - 3.78951754547 - 3.79221850678 - 3.79492138842 - 3.79762619176 - 3.80033291815 - 3.80304156898 - 3.8057521456 - 3.80846464939 - 3.81117908171 - 3.81389544395 - 3.81661373746 - 3.81933396362 - 3.82205612381 - 3.82478021941 - 3.82750625178 - 3.8302342223 - 3.83296413236 - 3.83569598333 - 3.83842977659 - 3.84116551353 - 3.84390319552 - 3.84664282395 - 3.84938440019 - 3.85212792565 - 3.8548734017 - 3.85762082972 - 3.86037021111 - 3.86312154726 - 3.86587483956 - 3.86863008939 - 3.87138729814 - 3.87414646722 - 3.87690759802 - 3.87967069192 - 3.88243575032 - 3.88520277463 - 3.88797176624 - 3.89074272655 - 3.89351565695 - 3.89629055885 - 3.89906743365 - 3.90184628276 - 3.90462710757 - 3.90740990949 - 3.91019468993 - 3.9129814503 - 3.91577019199 - 3.91856091643 - 3.92135362501 - 3.92414831916 - 3.92694500027 - 3.92974366977 - 3.93254432907 - 3.93534697959 - 3.93815162273 - 3.94095825992 - 3.94376689257 - 3.9465775221 - 3.94939014993 - 3.95220477749 - 3.95502140619 - 3.95784003746 - 3.96066067272 - 3.9634833134 - 3.96630796091 - 3.9691346167 - 3.97196328218 - 3.97479395878 - 3.97762664794 - 3.98046135109 - 3.98329806966 - 3.98613680507 - 3.98897755877 - 3.99182033219 - 3.99466512676 - 3.99751194393 - 4.00036078513 - 4.00321165179 - 4.00606454537 - 4.0089194673 - 4.01177641902 - 4.01463540197 - 4.01749641761 - 4.02035946737 - 4.0232245527 - 4.02609167505 - 4.02896083587 - 4.03183203661 - 4.03470527871 - 4.03758056363 - 4.04045789282 - 4.04333726773 - 4.04621868982 - 4.04910216055 - 4.05198768137 - 4.05487525373 - 4.0577648791 - 4.06065655894 - 4.0635502947 - 4.06644608786 - 4.06934393986 - 4.07224385218 - 4.07514582628 - 4.07804986363 - 4.08095596569 - 4.08386413393 - 4.08677436982 - 4.08968667483 - 4.09260105043 - 4.09551749809 - 4.09843601929 - 4.1013566155 - 4.1042792882 - 4.10720403886 - 4.11013086895 - 4.11305977997 - 4.11599077339 - 4.11892385068 - 4.12185901333 - 4.12479626282 - 4.12773560064 - 4.13067702828 - 4.1336205472 - 4.13656615891 - 4.1395138649 - 4.14246366664 - 4.14541556563 - 4.14836956337 - 4.15132566134 - 4.15428386103 - 4.15724416395 - 4.16020657159 - 4.16317108543 - 4.16613770699 - 4.16910643776 - 4.17207727923 - 4.17505023291 - 4.17802530031 - 4.18100248292 - 4.18398178225 - 4.1869631998 - 4.18994673707 - 4.19293239559 - 4.19592017685 - 4.19891008236 - 4.20190211363 - 4.20489627218 - 4.20789255952 - 4.21089097715 - 4.21389152661 - 4.21689420939 - 4.21989902702 - 4.22290598102 - 4.2259150729 - 4.22892630419 - 4.2319396764 - 4.23495519106 - 4.23797284969 - 4.24099265382 - 4.24401460496 - 4.24703870466 - 4.25006495443 - 4.2530933558 - 4.25612391031 - 4.25915661948 - 4.26219148484 - 4.26522850794 - 4.26826769029 - 4.27130903345 - 4.27435253894 - 4.27739820831 - 4.28044604308 - 4.2834960448 - 4.28654821502 - 4.28960255526 - 4.29265906708 - 4.29571775203 - 4.29877861163 - 4.30184164745 - 4.30490686102 - 4.3079742539 - 4.31104382763 - 4.31411558377 - 4.31718952387 - 4.32026564948 - 4.32334396215 - 4.32642446345 - 4.32950715491 - 4.33259203811 - 4.3356791146 - 4.33876838594 - 4.3418598537 - 4.34495351942 - 4.34804938468 - 4.35114745103 - 4.35424772005 - 4.3573501933 - 4.36045487235 - 4.36356175876 - 4.36667085411 - 4.36978215996 - 4.37289567789 - 4.37601140947 - 4.37912935627 - 4.38224951987 - 4.38537190184 - 4.38849650377 - 4.39162332722 - 4.39475237379 - 4.39788364504 - 4.40101714257 - 4.40415286795 - 4.40729082277 - 4.41043100861 - 4.41357342707 - 4.41671807972 - 4.41986496815 - 4.42301409396 - 4.42616545874 - 4.42931906407 - 4.43247491156 - 4.43563300279 - 4.43879333936 - 4.44195592287 - 4.44512075491 - 4.44828783708 - 4.45145717099 - 4.45462875823 - 4.4578026004 - 4.46097869912 - 4.46415705597 - 4.46733767258 - 4.47052055054 - 4.47370569146 - 4.47689309696 - 4.48008276864 - 4.48327470811 - 4.48646891699 - 4.48966539688 - 4.49286414941 - 4.49606517619 - 4.49926847884 - 4.50247405897 - 4.5056819182 - 4.50889205816 - 4.51210448046 - 4.51531918673 - 4.5185361786 - 4.52175545768 - 4.52497702561 - 4.528200884 - 4.5314270345 - 4.53465547872 - 4.53788621831 - 4.54111925488 - 4.54435459008 - 4.54759222554 - 4.5508321629 - 4.55407440378 - 4.55731894984 - 4.5605658027 - 4.56381496401 - 4.56706643541 - 4.57032021854 - 4.57357631505 - 4.57683472657 - 4.58009545477 - 4.58335850127 - 4.58662386774 - 4.58989155581 - 4.59316156715 - 4.5964339034 - 4.59970856622 - 4.60298555726 - 4.60626487817 - 4.60954653062 - 4.61283051625 - 4.61611683674 - 4.61940549373 - 4.62269648889 - 4.62598982389 - 4.62928550038 - 4.63258352003 - 4.6358838845 - 4.63918659547 - 4.64249165461 - 4.64579906357 - 4.64910882404 - 4.65242093768 - 4.65573540617 - 4.65905223117 - 4.66237141438 - 4.66569295746 - 4.66901686209 - 4.67234312995 - 4.67567176272 - 4.67900276208 - 4.68233612972 - 4.68567186731 - 4.68900997655 - 4.69235045912 - 4.6956933167 - 4.69903855099 - 4.70238616367 - 4.70573615645 - 4.70908853099 - 4.71244328902 - 4.7158004322 - 4.71915996225 - 4.72252188086 - 4.72588618973 - 4.72925289055 - 4.73262198503 - 4.73599347487 - 4.73936736177 - 4.74274364744 - 4.74612233358 - 4.7495034219 - 4.7528869141 - 4.7562728119 - 4.75966111701 - 4.76305183114 - 4.76644495599 - 4.76984049329 - 4.77323844475 - 4.77663881209 - 4.78004159702 - 4.78344680126 - 4.78685442653 - 4.79026447456 - 4.79367694707 - 4.79709184577 - 4.8005091724 - 4.80392892868 - 4.80735111634 - 4.81077573711 - 4.81420279272 - 4.81763228489 - 4.82106421537 - 4.82449858587 - 4.82793539815 - 4.83137465394 - 4.83481635496 - 4.83826050297 - 4.8417070997 - 4.84515614689 - 4.84860764628 - 4.85206159962 - 4.85551800866 - 4.85897687513 - 4.86243820078 - 4.86590198738 - 4.86936823665 - 4.87283695036 - 4.87630813025 - 4.87978177809 - 4.88325789562 - 4.8867364846 - 4.89021754679 - 4.89370108394 - 4.89718709782 - 4.90067559019 - 4.90416656281 - 4.90766001743 - 4.91115595584 - 4.91465437979 - 4.91815529104 - 4.92165869138 - 4.92516458256 - 4.92867296637 - 4.93218384456 - 4.93569721892 - 4.93921309122 - 4.94273146323 - 4.94625233674 - 4.94977571351 - 4.95330159534 - 4.956829984 - 4.96036088128 - 4.96389428895 - 4.9674302088 - 4.97096864263 - 4.97450959221 - 4.97805305933 - 4.98159904579 - 4.98514755338 - 4.98869858388 - 4.9922521391 - 4.99580822082 - 4.99936683085 - 5.00292797098 - 5.00649164301 - 5.01005784873 - 5.01362658996 - 5.0171978685 - 5.02077168614 - 5.02434804469 - 5.02792694597 - 5.03150839177 - 5.03509238391 - 5.0386789242 - 5.04226801444 - 5.04585965646 - 5.04945385206 - 5.05305060307 - 5.05664991129 - 5.06025177855 - 5.06385620667 - 5.06746319746 - 5.07107275276 - 5.07468487437 - 5.07829956413 - 5.08191682387 - 5.0855366554 - 5.08915906056 - 5.09278404118 - 5.09641159909 - 5.10004173612 - 5.10367445411 - 5.10730975489 - 5.11094764029 - 5.11458811216 - 5.11823117233 - 5.12187682264 - 5.12552506494 - 5.12917590107 - 5.13282933287 - 5.13648536219 - 5.14014399087 - 5.14380522076 - 5.14746905372 - 5.15113549158 - 5.15480453622 - 5.15847618947 - 5.16215045319 - 5.16582732924 - 5.16950681948 - 5.17318892576 - 5.17687364995 - 5.1805609939 - 5.18425095948 - 5.18794354855 - 5.19163876298 - 5.19533660463 - 5.19903707538 - 5.20274017709 - 5.20644591162 - 5.21015428087 - 5.21386528669 - 5.21757893096 - 5.22129521555 - 5.22501414236 - 5.22873571324 - 5.23245993009 - 5.23618679479 - 5.23991630921 - 5.24364847524 - 5.24738329476 - 5.25112076967 - 5.25486090185 - 5.25860369319 - 5.26234914558 - 5.26609726091 - 5.26984804108 - 5.27360148798 - 5.2773576035 - 5.28111638955 - 5.28487784802 - 5.28864198081 - 5.29240878982 - 5.29617827697 - 5.29995044414 - 5.30372529325 - 5.3075028262 - 5.3112830449 - 5.31506595126 - 5.3188515472 - 5.32263983461 - 5.32643081543 - 5.33022449155 - 5.33402086491 - 5.33781993741 - 5.34162171098 - 5.34542618753 - 5.34923336899 - 5.35304325728 - 5.35685585432 - 5.36067116205 - 5.36448918238 - 5.36830991725 - 5.37213336858 - 5.37595953832 - 5.37978842838 - 5.38362004071 - 5.38745437724 - 5.39129143991 - 5.39513123065 - 5.39897375141 - 5.40281900413 - 5.40666699074 - 5.41051771319 - 5.41437117343 - 5.41822737341 - 5.42208631506 - 5.42594800035 - 5.42981243122 - 5.43367960962 - 5.43754953751 - 5.44142221684 - 5.44529764957 - 5.44917583766 - 5.45305678306 - 5.45694048773 - 5.46082695365 - 5.46471618276 - 5.46860817703 - 5.47250293844 - 5.47640046895 - 5.48030077052 - 5.48420384513 - 5.48810969475 - 5.49201832135 - 5.4959297269 - 5.49984391339 - 5.50376088278 - 5.50768063707 - 5.51160317822 - 5.51552850822 - 5.51945662905 - 5.5233875427 - 5.52732125114 - 5.53125775638 - 5.5351970604 - 5.53913916518 - 5.54308407272 - 5.54703178501 - 5.55098230404 - 5.55493563182 - 5.55889177033 - 5.56285072158 - 5.56681248757 - 5.57077707029 - 5.57474447175 - 5.57871469396 - 5.58268773891 - 5.58666360862 - 5.5906423051 - 5.59462383035 - 5.59860818638 - 5.60259537521 - 5.60658539886 - 5.61057825933 - 5.61457395865 - 5.61857249883 - 5.62257388189 - 5.62657810986 - 5.63058518475 - 5.63459510859 - 5.63860788341 - 5.64262351124 - 5.64664199409 - 5.65066333401 - 5.65468753302 - 5.65871459315 - 5.66274451644 - 5.66677730493 - 5.67081296066 - 5.67485148565 - 5.67889288195 - 5.68293715161 - 5.68698429666 - 5.69103431916 - 5.69508722113 - 5.69914300464 - 5.70320167174 - 5.70726322446 - 5.71132766487 - 5.71539499501 - 5.71946521695 - 5.72353833273 - 5.72761434441 - 5.73169325406 - 5.73577506374 - 5.7398597755 - 5.7439473914 - 5.74803791352 - 5.75213134393 - 5.75622768468 - 5.76032693784 - 5.76442910549 - 5.76853418971 - 5.77264219256 - 5.77675311611 - 5.78086696245 - 5.78498373365 - 5.7891034318 - 5.79322605897 - 5.79735161725 - 5.80148010871 - 5.80561153545 - 5.80974589956 - 5.81388320311 - 5.8180234482 - 5.82216663693 - 5.82631277138 - 5.83046185365 - 5.83461388584 - 5.83876887004 - 5.84292680835 - 5.84708770287 - 5.85125155571 - 5.85541836896 - 5.85958814473 - 5.86376088513 - 5.86793659227 - 5.87211526825 - 5.87629691519 - 5.88048153519 - 5.88466913038 - 5.88885970286 - 5.89305325476 - 5.89724978819 - 5.90144930527 - 5.90565180812 - 5.90985729887 - 5.91406577965 - 5.91827725256 - 5.92249171975 - 5.92670918335 - 5.93092964547 - 5.93515310827 - 5.93937957386 - 5.94360904438 - 5.94784152197 - 5.95207700877 - 5.95631550692 - 5.96055701855 - 5.96480154582 - 5.96904909086 - 5.97329965582 - 5.97755324284 - 5.98180985409 - 5.9860694917 - 5.99033215782 - 5.99459785462 - 5.99886658424 - 6.00313834885 - 6.0074131506 - 6.01169099164 - 6.01597187414 - 6.02025580027 - 6.02454277219 - 6.02883279205 - 6.03312586204 - 6.03742198431 - 6.04172116104 - 6.0460233944 - 6.05032868656 - 6.0546370397 - 6.05894845599 - 6.06326293761 - 6.06758048675 - 6.07190110557 - 6.07622479627 - 6.08055156103 - 6.08488140203 - 6.08921432147 - 6.09355032152 - 6.09788940438 - 6.10223157225 - 6.1065768273 - 6.11092517175 - 6.11527660779 - 6.11963113761 - 6.12398876342 - 6.12834948741 - 6.13271331179 - 6.13708023876 - 6.14145027053 - 6.1458234093 - 6.15019965729 - 6.15457901671 - 6.15896148976 - 6.16334707867 - 6.16773578564 - 6.17212761289 - 6.17652256265 - 6.18092063713 - 6.18532183855 - 6.18972616914 - 6.19413363112 - 6.19854422672 - 6.20295795816 - 6.20737482768 - 6.21179483751 - 6.21621798987 - 6.22064428701 - 6.22507373116 - 6.22950632456 - 6.23394206944 - 6.23838096805 - 6.24282302262 - 6.24726823541 - 6.25171660866 - 6.25616814461 - 6.26062284552 - 6.26508071363 - 6.26954175119 - 6.27400596047 - 6.27847334371 - 6.28294390317 - 6.2874176411 - 6.29189455978 - 6.29637466146 - 6.3008579484 - 6.30534442287 - 6.30983408713 - 6.31432694346 - 6.31882299411 - 6.32332224137 - 6.32782468751 - 6.33233033479 - 6.33683918551 - 6.34135124192 - 6.34586650632 - 6.35038498098 - 6.35490666818 - 6.35943157022 - 6.36395968937 - 6.36849102792 - 6.37302558817 - 6.3775633724 - 6.3821043829 - 6.38664862197 - 6.3911960919 - 6.395746795 - 6.40030073355 - 6.40485790987 - 6.40941832624 - 6.41398198499 - 6.4185488884 - 6.42311903879 - 6.42769243847 - 6.43226908974 - 6.43684899492 - 6.44143215632 - 6.44601857626 - 6.45060825705 - 6.45520120102 - 6.45979741048 - 6.46439688775 - 6.46899963515 - 6.47360565502 - 6.47821494968 - 6.48282752146 - 6.48744337268 - 6.49206250568 - 6.49668492279 - 6.50131062635 - 6.50593961869 - 6.51057190216 - 6.51520747908 - 6.51984635181 - 6.52448852269 - 6.52913399406 - 6.53378276826 - 6.53843484765 - 6.54309023458 - 6.54774893139 - 6.55241094045 - 6.5570762641 - 6.5617449047 - 6.56641686462 - 6.5710921462 - 6.57577075182 - 6.58045268383 - 6.58513794461 - 6.58982653651 - 6.59451846191 - 6.59921372317 - 6.60391232267 - 6.60861426278 - 6.61331954588 - 6.61802817434 - 6.62274015054 - 6.62745547686 - 6.63217415569 - 6.6368961894 - 6.64162158039 - 6.64635033103 - 6.65108244373 - 6.65581792086 - 6.66055676482 - 6.665298978 - 6.67004456281 - 6.67479352163 - 6.67954585686 - 6.68430157092 - 6.68906066619 - 6.69382314508 - 6.69858901 - 6.70335826336 - 6.70813090756 - 6.71290694501 - 6.71768637814 - 6.72246920934 - 6.72725544105 - 6.73204507567 - 6.73683811562 - 6.74163456333 - 6.74643442122 - 6.75123769171 - 6.75604437724 - 6.76085448022 - 6.76566800309 - 6.77048494828 - 6.77530531822 - 6.78012911534 - 6.7849563421 - 6.78978700091 - 6.79462109423 - 6.79945862449 - 6.80429959414 - 6.80914400562 - 6.81399186138 - 6.81884316387 - 6.82369791555 - 6.82855611885 - 6.83341777624 - 6.83828289017 - 6.8431514631 - 6.84802349749 - 6.8528989958 - 6.85777796049 - 6.86266039403 - 6.86754629888 - 6.87243567752 - 6.8773285324 - 6.88222486601 - 6.88712468081 - 6.89202797929 - 6.89693476391 - 6.90184503716 - 6.90675880151 - 6.91167605946 - 6.91659681347 - 6.92152106605 - 6.92644881967 - 6.93138007683 - 6.93631484001 - 6.94125311171 - 6.94619489442 - 6.95114019065 - 6.95608900288 - 6.96104133361 - 6.96599718536 - 6.97095656062 - 6.9759194619 - 6.9808858917 - 6.98585585253 - 6.99082934691 - 6.99580637734 - 7.00078694634 - 7.00577105643 - 7.01075871012 - 7.01574990994 - 7.02074465839 - 7.02574295802 - 7.03074481134 - 7.03575022087 - 7.04075918915 - 7.04577171871 - 7.05078781208 - 7.05580747179 - 7.06083070038 - 7.06585750038 - 7.07088787434 - 7.0759218248 - 7.0809593543 - 7.08600046537 - 7.09104516058 - 7.09609344247 - 7.10114531358 - 7.10620077648 - 7.1112598337 - 7.11632248782 - 7.12138874139 - 7.12645859696 - 7.13153205709 - 7.13660912436 - 7.14168980132 - 7.14677409054 - 7.15186199459 - 7.15695351603 - 7.16204865745 - 7.16714742141 - 7.1722498105 - 7.17735582728 - 7.18246547433 - 7.18757875425 - 7.1926956696 - 7.19781622298 - 7.20294041697 - 7.20806825416 - 7.21319973715 - 7.21833486851 - 7.22347365085 - 7.22861608676 - 7.23376217885 - 7.2389119297 - 7.24406534192 - 7.24922241812 - 7.25438316089 - 7.25954757286 - 7.26471565661 - 7.26988741477 - 7.27506284995 - 7.28024196476 - 7.28542476182 - 7.29061124374 - 7.29580141315 - 7.30099527266 - 7.30619282491 - 7.31139407251 - 7.3165990181 - 7.3218076643 - 7.32702001374 - 7.33223606907 - 7.3374558329 - 7.34267930788 - 7.34790649665 - 7.35313740184 - 7.35837202611 - 7.36361037209 - 7.36885244243 - 7.37409823977 - 7.37934776678 - 7.38460102609 - 7.38985802037 - 7.39511875227 - 7.40038322444 - 7.40565143955 - 7.41092340025 - 7.41619910921 - 7.4214785691 - 7.42676178258 - 7.43204875232 - 7.43733948098 - 7.44263397126 - 7.44793222581 - 7.45323424731 - 7.45854003844 - 7.46384960189 - 7.46916294033 - 7.47448005645 - 7.47980095293 - 7.48512563247 - 7.49045409775 - 7.49578635146 - 7.50112239629 - 7.50646223495 - 7.51180587013 - 7.51715330452 - 7.52250454084 - 7.52785958178 - 7.53321843004 - 7.53858108834 - 7.54394755939 - 7.54931784588 - 7.55469195055 - 7.5600698761 - 7.56545162524 - 7.5708372007 - 7.5762266052 - 7.58161984146 - 7.58701691221 - 7.59241782016 - 7.59782256805 - 7.60323115861 - 7.60864359457 - 7.61405987867 - 7.61948001363 - 7.62490400221 - 7.63033184713 - 7.63576355114 - 7.64119911698 - 7.64663854741 - 7.65208184516 - 7.65752901299 - 7.66298005365 - 7.66843496988 - 7.67389376446 - 7.67935644013 - 7.68482299965 - 7.69029344579 - 7.69576778131 - 7.70124600897 - 7.70672813154 - 7.7122141518 - 7.7177040725 - 7.72319789643 - 7.72869562636 - 7.73419726507 - 7.73970281533 - 7.74521227993 - 7.75072566164 - 7.75624296327 - 7.76176418758 - 7.76728933738 - 7.77281841545 - 7.77835142458 - 7.78388836757 - 7.78942924722 - 7.79497406632 - 7.80052282768 - 7.8060755341 - 7.81163218839 - 7.81719279334 - 7.82275735177 - 7.8283258665 - 7.83389834033 - 7.83947477607 - 7.84505517655 - 7.85063954459 - 7.856227883 - 7.86182019461 - 7.86741648224 - 7.87301674872 - 7.87862099688 - 7.88422922954 - 7.88984144955 - 7.89545765974 - 7.90107786294 - 7.90670206199 - 7.91233025974 - 7.91796245902 - 7.92359866269 - 7.92923887358 - 7.93488309455 - 7.94053132845 - 7.94618357814 - 7.95183984646 - 7.95750013627 - 7.96316445044 - 7.96883279182 - 7.97450516329 - 7.98018156769 - 7.98586200791 - 7.9915464868 - 7.99723500725 - 8.00292757213 - 8.0086241843 - 8.01432484665 - 8.02002956206 - 8.02573833341 - 8.03145116358 - 8.03716805546 - 8.04288901194 - 8.0486140359 - 8.05434313025 - 8.06007629786 - 8.06581354164 - 8.07155486449 - 8.07730026931 - 8.08304975899 - 8.08880333645 - 8.09456100459 - 8.10032276631 - 8.10608862453 - 8.11185858217 - 8.11763264213 - 8.12341080733 - 8.12919308069 - 8.13497946513 - 8.14076996358 - 8.14656457896 - 8.15236331419 - 8.15816617221 - 8.16397315594 - 8.16978426833 - 8.1755995123 - 8.1814188908 - 8.18724240675 - 8.19307006311 - 8.19890186282 - 8.20473780883 - 8.21057790407 - 8.21642215151 - 8.22227055409 - 8.22812311476 - 8.2339798365 - 8.23984072224 - 8.24570577496 - 8.25157499762 - 8.25744839317 - 8.2633259646 - 8.26920771486 - 8.27509364692 - 8.28098376377 - 8.28687806838 - 8.29277656371 - 8.29867925277 - 8.30458613851 - 8.31049722394 - 8.31641251202 - 8.32233200577 - 8.32825570815 - 8.33418362217 - 8.34011575082 - 8.34605209709 - 8.35199266399 - 8.35793745451 - 8.36388647166 - 8.36983971844 - 8.37579719787 - 8.38175891294 - 8.38772486667 - 8.39369506208 - 8.39966950218 - 8.40564818999 - 8.41163112853 - 8.41761832081 - 8.42360976988 - 8.42960547874 - 8.43560545043 - 8.44160968798 - 8.44761819443 - 8.45363097281 - 8.45964802615 - 8.4656693575 - 8.47169496989 - 8.47772486638 - 8.48375905 - 8.48979752381 - 8.49584029085 - 8.50188735418 - 8.50793871685 - 8.51399438192 - 8.52005435244 - 8.52611863149 - 8.53218722212 - 8.53826012739 - 8.54433735038 - 8.55041889416 - 8.55650476179 - 8.56259495635 - 8.56868948092 - 8.57478833858 - 8.5808915324 - 8.58699906548 - 8.59311094088 - 8.59922716171 - 8.60534773105 - 8.611472652 - 8.61760192764 - 8.62373556108 - 8.6298735554 - 8.63601591372 - 8.64216263913 - 8.64831373475 - 8.65446920367 - 8.660629049 - 8.66679327387 - 8.67296188137 - 8.67913487463 - 8.68531225677 - 8.69149403091 - 8.69768020016 - 8.70387076766 - 8.71006573652 - 8.71626510989 - 8.72246889089 - 8.72867708265 - 8.73488968832 - 8.74110671102 - 8.7473281539 - 8.75355402011 - 8.75978431278 - 8.76601903507 - 8.77225819012 - 8.77850178109 - 8.78474981112 - 8.79100228338 - 8.79725920103 - 8.80352056722 - 8.80978638511 - 8.81605665788 - 8.82233138869 - 8.82861058071 - 8.8348942371 - 8.84118236106 - 8.84747495574 - 8.85377202433 - 8.86007357002 - 8.86637959597 - 8.87269010539 - 8.87900510145 - 8.88532458736 - 8.89164856629 - 8.89797704144 - 8.90431001601 - 8.9106474932 - 8.91698947622 - 8.92333596825 - 8.92968697252 - 8.93604249223 - 8.94240253058 - 8.94876709079 - 8.95513617608 - 8.96150978967 - 8.96788793476 - 8.97427061459 - 8.98065783238 - 8.98704959136 - 8.99344589474 - 8.99984674578 - 9.00625214769 - 9.01266210371 - 9.01907661709 - 9.02549569105 - 9.03191932885 - 9.03834753373 - 9.04478030894 - 9.05121765772 - 9.05765958333 - 9.06410608902 - 9.07055717805 - 9.07701285367 - 9.08347311915 - 9.08993797775 - 9.09640743274 - 9.10288148738 - 9.10936014495 - 9.11584340871 - 9.12233128194 - 9.12882376793 - 9.13532086994 - 9.14182259126 - 9.14832893518 - 9.15483990498 - 9.16135550395 - 9.16787573538 - 9.17440060256 - 9.1809301088 - 9.18746425739 - 9.19400305162 - 9.20054649481 - 9.20709459026 - 9.21364734127 - 9.22020475116 - 9.22676682323 - 9.23333356081 - 9.23990496721 - 9.24648104575 - 9.25306179975 - 9.25964723254 - 9.26623734744 - 9.27283214777 - 9.27943163688 - 9.2860358181 - 9.29264469476 - 9.2992582702 - 9.30587654776 - 9.31249953078 - 9.31912722261 - 9.3257596266 - 9.3323967461 - 9.33903858445 - 9.34568514503 - 9.35233643117 - 9.35899244625 - 9.36565319362 - 9.37231867665 - 9.37898889871 - 9.38566386316 - 9.39234357338 - 9.39902803274 - 9.40571724462 - 9.4124112124 - 9.41910993945 - 9.42581342917 - 9.43252168493 - 9.43923471013 - 9.44595250816 - 9.45267508241 - 9.45940243627 - 9.46613457315 - 9.47287149645 - 9.47961320957 - 9.48635971591 - 9.49311101888 - 9.49986712189 - 9.50662802836 - 9.5133937417 - 9.52016426533 - 9.52693960266 - 9.53371975713 - 9.54050473215 - 9.54729453115 - 9.55408915756 - 9.56088861482 - 9.56769290636 - 9.57450203562 - 9.58131600603 - 9.58813482104 - 9.59495848409 - 9.60178699863 - 9.6086203681 - 9.61545859597 - 9.62230168568 - 9.6291496407 - 9.63600246447 - 9.64286016046 - 9.64972273214 - 9.65659018297 - 9.66346251643 - 9.67033973597 - 9.67722184509 - 9.68410884724 - 9.69100074592 - 9.6978975446 - 9.70479924677 - 9.71170585591 - 9.71861737551 - 9.72553380907 - 9.73245516007 - 9.73938143201 - 9.7463126284 - 9.75324875273 - 9.76018980851 - 9.76713579924 - 9.77408672843 - 9.78104259959 - 9.78800341624 - 9.7949691819 - 9.80193990007 - 9.80891557429 - 9.81589620807 - 9.82288180494 - 9.82987236844 - 9.83686790208 - 9.84386840941 - 9.85087389397 - 9.85788435928 - 9.8648998089 - 9.87192024636 - 9.87894567521 - 9.885976099 - 9.89301152129 - 9.90005194562 - 9.90709737555 - 9.91414781464 - 9.92120326646 - 9.92826373456 - 9.93532922251 - 9.94239973389 - 9.94947527226 - 9.9565558412 - 9.96364144428 - 9.97073208508 - 9.97782776719 - 9.98492849418 - 9.99203426966 - 9.99914509719 - 10.0062609804 - 10.0133819228 - 10.0205079281 - 10.0276389999 - 10.0347751417 - 10.0419163571 - 10.0490626498 - 10.0562140234 - 10.0633704815 - 10.0705320277 - 10.0776986655 - 10.0848703988 - 10.0920472309 - 10.0992291657 - 10.1064162067 - 10.1136083575 - 10.1208056218 - 10.1280080032 - 10.1352155054 - 10.1424281319 - 10.1496458865 - 10.1568687728 - 10.1640967944 - 10.171329955 - 10.1785682582 - 10.1858117077 - 10.1930603071 - 10.2003140602 - 10.2075729705 - 10.2148370418 - 10.2221062777 - 10.2293806818 - 10.236660258 - 10.2439450097 - 10.2512349408 - 10.2585300549 - 10.2658303556 - 10.2731358467 - 10.2804465319 - 10.2877624148 - 10.2950834992 - 10.3024097887 - 10.3097412871 - 10.317077998 - 10.3244199252 - 10.3317670723 - 10.3391194432 - 10.3464770414 - 10.3538398707 - 10.3612079348 - 10.3685812375 - 10.3759597825 - 10.3833435734 - 10.3907326141 - 10.3981269082 - 10.4055264596 - 10.4129312718 - 10.4203413488 - 10.4277566942 - 10.4351773117 - 10.4426032051 - 10.4500343782 - 10.4574708348 - 10.4649125785 - 10.4723596131 - 10.4798119424 - 10.4872695702 - 10.4947325002 - 10.5022007362 - 10.5096742819 - 10.5171531413 - 10.5246373179 - 10.5321268156 - 10.5396216382 - 10.5471217895 - 10.5546272733 - 10.5621380932 - 10.5696542533 - 10.5771757572 - 10.5847026087 - 10.5922348116 - 10.5997723698 - 10.6073152871 - 10.6148635672 - 10.622417214 - 10.6299762313 - 10.6375406229 - 10.6451103927 - 10.6526855444 - 10.6602660818 - 10.6678520089 - 10.6754433294 - 10.6830400473 - 10.6906421662 - 10.6982496901 - 10.7058626227 - 10.7134809681 - 10.7211047299 - 10.728733912 - 10.7363685184 - 10.7440085528 - 10.7516540191 - 10.7593049212 - 10.766961263 - 10.7746230482 - 10.7822902808 - 10.7899629647 - 10.7976411037 - 10.8053247017 - 10.8130137626 - 10.8207082902 - 10.8284082885 - 10.8361137614 - 10.8438247127 - 10.8515411463 - 10.8592630662 - 10.8669904762 - 10.8747233802 - 10.8824617822 - 10.890205686 - 10.8979550956 - 10.9057100148 - 10.9134704477 - 10.921236398 - 10.9290078698 - 10.936784867 - 10.9445673934 - 10.9523554531 - 10.96014905 - 10.9679481879 - 10.9757528708 - 10.9835631028 - 10.9913788876 - 10.9992002293 - 11.0070271319 - 11.0148595992 - 11.0226976352 - 11.0305412439 - 11.0383904293 - 11.0462451953 - 11.0541055459 - 11.061971485 - 11.0698430167 - 11.0777201448 - 11.0856028734 - 11.0934912065 - 11.1013851481 - 11.1092847021 - 11.1171898725 - 11.1251006633 - 11.1330170786 - 11.1409391222 - 11.1488667983 - 11.1568001108 - 11.1647390637 - 11.1726836611 - 11.1806339069 - 11.1885898052 - 11.1965513599 - 11.2045185752 - 11.212491455 - 11.2204700034 - 11.2284542243 - 11.2364441219 - 11.2444397001 - 11.2524409631 - 11.2604479147 - 11.2684605592 - 11.2764789005 - 11.2845029426 - 11.2925326897 - 11.3005681458 - 11.308609315 - 11.3166562012 - 11.3247088086 - 11.3327671413 - 11.3408312033 - 11.3489009987 - 11.3569765315 - 11.3650578059 - 11.3731448259 - 11.3812375956 - 11.3893361191 - 11.3974404005 - 11.4055504439 - 11.4136662534 - 11.4217878331 - 11.429915187 - 11.4380483193 - 11.4461872341 - 11.4543319355 - 11.4624824277 - 11.4706387147 - 11.4788008006 - 11.4869686896 - 11.4951423858 - 11.5033218934 - 11.5115072164 - 11.5196983591 - 11.5278953254 - 11.5360981197 - 11.544306746 - 11.5525212084 - 11.5607415112 - 11.5689676584 - 11.5771996543 - 11.5854375029 - 11.5936812085 - 11.6019307752 - 11.6101862072 - 11.6184475087 - 11.6267146837 - 11.6349877366 - 11.6432666714 - 11.6515514924 - 11.6598422037 - 11.6681388096 - 11.6764413142 - 11.6847497217 - 11.6930640363 - 11.7013842622 - 11.7097104036 - 11.7180424648 - 11.7263804499 - 11.7347243631 - 11.7430742087 - 11.7514299909 - 11.7597917138 - 11.7681593818 - 11.776532999 - 11.7849125697 - 11.7932980981 - 11.8016895885 - 11.810087045 - 11.818490472 - 11.8268998736 - 11.8353152542 - 11.8437366179 - 11.852163969 - 11.8605973118 - 11.8690366506 - 11.8774819896 - 11.885933333 - 11.8943906852 - 11.9028540503 - 11.9113234328 - 11.9197988368 - 11.9282802667 - 11.9367677267 - 11.9452612211 - 11.9537607542 - 11.9622663303 - 11.9707779537 - 11.9792956287 - 11.9878193596 - 11.9963491507 - 12.0048850064 - 12.0134269308 - 12.0219749284 - 12.0305290034 - 12.0390891602 - 12.0476554031 - 12.0562277365 - 12.0648061646 - 12.0733906918 - 12.0819813224 - 12.0905780608 - 12.0991809113 - 12.1077898783 - 12.116404966 - 12.125026179 - 12.1336535214 - 12.1422869977 - 12.1509266122 - 12.1595723693 - 12.1682242734 - 12.1768823288 - 12.18554654 - 12.1942169112 - 12.2028934468 - 12.2115761514 - 12.2202650291 - 12.2289600845 - 12.2376613218 - 12.2463687456 - 12.2550823602 - 12.26380217 - 12.2725281794 - 12.2812603928 - 12.2899988147 - 12.2987434494 - 12.3074943013 - 12.316251375 - 12.3250146747 - 12.333784205 - 12.3425599703 - 12.3513419749 - 12.3601302234 - 12.3689247201 - 12.3777254695 - 12.3865324762 - 12.3953457444 - 12.4041652786 - 12.4129910834 - 12.4218231632 - 12.4306615224 - 12.4395061655 - 12.4483570969 - 12.4572143212 - 12.4660778428 - 12.4749476662 - 12.4838237959 - 12.4927062363 - 12.5015949919 - 12.5104900673 - 12.5193914669 - 12.5282991953 - 12.5372132568 - 12.546133656 - 12.5550603975 - 12.5639934858 - 12.5729329252 - 12.5818787205 - 12.590830876 - 12.5997893963 - 12.6087542859 - 12.6177255495 - 12.6267031914 - 12.6356872162 - 12.6446776285 - 12.6536744328 - 12.6626776336 - 12.6716872355 - 12.6807032431 - 12.6897256609 - 12.6987544935 - 12.7077897453 - 12.7168314211 - 12.7258795253 - 12.7349340625 - 12.7439950374 - 12.7530624544 - 12.7621363181 - 12.7712166332 - 12.7803034042 - 12.7893966357 - 12.7984963324 - 12.8076024987 - 12.8167151393 - 12.8258342589 - 12.834959862 - 12.8440919531 - 12.8532305371 - 12.8623756183 - 12.8715272016 - 12.8806852914 - 12.8898498925 - 12.8990210094 - 12.9081986467 - 12.9173828092 - 12.9265735015 - 12.9357707282 - 12.9449744939 - 12.9541848033 - 12.963401661 - 12.9726250718 - 12.9818550402 - 12.9910915709 - 13.0003346687 - 13.009584338 - 13.0188405838 - 13.0281034105 - 13.0373728229 - 13.0466488257 - 13.0559314235 - 13.0652206211 - 13.0745164231 - 13.0838188342 - 13.0931278592 - 13.1024435027 - 13.1117657694 - 13.1210946641 - 13.1304301915 - 13.1397723562 - 13.149121163 - 13.1584766166 - 13.1678387218 - 13.1772074832 - 13.1865829057 - 13.1959649939 - 13.2053537525 - 13.2147491864 - 13.2241513003 - 13.2335600988 - 13.2429755869 - 13.2523977691 - 13.2618266504 - 13.2712622354 - 13.2807045289 - 13.2901535357 - 13.2996092605 - 13.3090717082 - 13.3185408835 - 13.3280167912 - 13.337499436 - 13.3469888229 - 13.3564849565 - 13.3659878417 - 13.3754974832 - 13.3850138859 - 13.3945370546 - 13.404066994 - 13.4136037091 - 13.4231472045 - 13.4326974852 - 13.442254556 - 13.4518184217 - 13.461389087 - 13.4709665569 - 13.4805508363 - 13.4901419298 - 13.4997398424 - 13.509344579 - 13.5189561443 - 13.5285745433 - 13.5381997807 - 13.5478318615 - 13.5574707905 - 13.5671165726 - 13.5767692127 - 13.5864287156 - 13.5960950862 - 13.6057683294 - 13.6154484501 - 13.6251354532 - 13.6348293435 - 13.644530126 - 13.6542378056 - 13.6639523871 - 13.6736738755 - 13.6834022757 - 13.6931375926 - 13.7028798311 - 13.7126289962 - 13.7223850927 - 13.7321481256 - 13.7419180998 - 13.7516950203 - 13.761478892 - 13.7712697198 - 13.7810675087 - 13.7908722636 - 13.8006839895 - 13.8105026914 - 13.8203283742 - 13.8301610428 - 13.8400007022 - 13.8498473575 - 13.8597010135 - 13.8695616753 - 13.8794293479 - 13.8893040361 - 13.8991857451 - 13.9090744797 - 13.9189702451 - 13.9288730461 - 13.9387828878 - 13.9486997753 - 13.9586237134 - 13.9685547073 - 13.9784927619 - 13.9884378823 - 13.9983900734 - 14.0083493404 - 14.0183156882 - 14.0282891219 - 14.0382696464 - 14.048257267 - 14.0582519885 - 14.0682538161 - 14.0782627548 - 14.0882788097 - 14.0983019857 - 14.1083322881 - 14.1183697218 - 14.1284142919 - 14.1384660035 - 14.1485248617 - 14.1585908715 - 14.168664038 - 14.1787443664 - 14.1888318617 - 14.198926529 - 14.2090283734 - 14.2191374 - 14.2292536139 - 14.2393770202 - 14.2495076241 - 14.2596454307 - 14.269790445 - 14.2799426723 - 14.2901021175 - 14.300268786 - 14.3104426827 - 14.3206238129 - 14.3308121816 - 14.3410077941 - 14.3512106554 - 14.3614207708 - 14.3716381454 - 14.3818627843 - 14.3920946928 - 14.4023338759 - 14.4125803389 - 14.4228340869 - 14.4330951251 - 14.4433634588 - 14.453639093 - 14.4639220329 - 14.4742122839 - 14.484509851 - 14.4948147394 - 14.5051269545 - 14.5154465013 - 14.5257733851 - 14.5361076111 - 14.5464491846 - 14.5567981107 - 14.5671543947 - 14.5775180418 - 14.5878890572 - 14.5982674463 - 14.6086532141 - 14.6190463661 - 14.6294469073 - 14.6398548432 - 14.6502701788 - 14.6606929196 - 14.6711230707 - 14.6815606375 - 14.6920056252 - 14.702458039 - 14.7129178843 - 14.7233851664 - 14.7338598904 - 14.7443420618 - 14.7548316859 - 14.7653287678 - 14.7758333129 - 14.7863453266 - 14.7968648141 - 14.8073917807 - 14.8179262318 - 14.8284681727 - 14.8390176087 - 14.8495745452 - 14.8601389874 - 14.8707109407 - 14.8812904105 - 14.8918774021 - 14.9024719208 - 14.913073972 - 14.923683561 - 14.9343006933 - 14.9449253741 - 14.9555576089 - 14.966197403 - 14.9768447617 - 14.9874996905 - 14.9981621948 - 15.0088322799 - 15.0195099512 - 15.0301952141 - 15.040888074 - 15.0515885364 - 15.0622966065 - 15.0730122899 - 15.0837355919 - 15.094466518 - 15.1052050735 - 15.115951264 - 15.1267050948 - 15.1374665713 - 15.148235699 - 15.1590124834 - 15.1697969298 - 15.1805890438 - 15.1913888308 - 15.2021962962 - 15.2130114454 - 15.2238342841 - 15.2346648175 - 15.2455030513 - 15.2563489908 - 15.2672026416 - 15.2780640091 - 15.2889330988 - 15.2998099162 - 15.3106944669 - 15.3215867562 - 15.3324867897 - 15.343394573 - 15.3543101114 - 15.3652334106 - 15.376164476 - 15.3871033132 - 15.3980499277 - 15.4090043251 - 15.4199665107 - 15.4309364903 - 15.4419142693 - 15.4528998533 - 15.4638932479 - 15.4748944585 - 15.4859034907 - 15.4969203502 - 15.5079450424 - 15.518977573 - 15.5300179475 - 15.5410661714 - 15.5521222505 - 15.5631861902 - 15.5742579961 - 15.5853376739 - 15.5964252291 - 15.6075206673 - 15.6186239941 - 15.6297352152 - 15.6408543362 - 15.6519813626 - 15.6631163002 - 15.6742591544 - 15.685409931 - 15.6965686356 - 15.7077352738 - 15.7189098513 - 15.7300923736 - 15.7412828465 - 15.7524812756 - 15.7636876666 - 15.7749020251 - 15.7861243568 - 15.7973546673 - 15.8085929624 - 15.8198392477 - 15.8310935288 - 15.8423558115 - 15.8536261015 - 15.8649044045 - 15.8761907261 - 15.887485072 - 15.898787448 - 15.9100978597 - 15.921416313 - 15.9327428134 - 15.9440773668 - 15.9554199788 - 15.9667706551 - 15.9781294016 - 15.9894962239 - 16.0008711278 - 16.012254119 - 16.0236452033 - 16.0350443865 - 16.0464516742 - 16.0578670723 - 16.0692905865 - 16.0807222226 - 16.0921619864 - 16.1036098836 - 16.11506592 - 16.1265301015 - 16.1380024338 - 16.1494829226 - 16.1609715739 - 16.1724683934 - 16.1839733868 - 16.1954865601 - 16.2070079191 - 16.2185374695 - 16.2300752171 - 16.2416211679 - 16.2531753276 - 16.2647377021 - 16.2763082973 - 16.2878871188 - 16.2994741727 - 16.3110694648 - 16.3226730009 - 16.3342847869 - 16.3459048286 - 16.3575331319 - 16.3691697028 - 16.380814547 - 16.3924676704 - 16.404129079 - 16.4157987786 - 16.4274767752 - 16.4391630745 - 16.4508576826 - 16.4625606054 - 16.4742718486 - 16.4859914184 - 16.4977193205 - 16.5094555609 - 16.5212001456 - 16.5329530804 - 16.5447143714 - 16.5564840243 - 16.5682620453 - 16.5800484402 - 16.591843215 - 16.6036463756 - 16.6154579281 - 16.6272778783 - 16.6391062323 - 16.650942996 - 16.6627881755 - 16.6746417766 - 16.6865038053 - 16.6983742678 - 16.7102531699 - 16.7221405177 - 16.7340363171 - 16.7459405742 - 16.757853295 - 16.7697744856 - 16.7817041518 - 16.7936422998 - 16.8055889356 - 16.8175440652 - 16.8295076947 - 16.84147983 - 16.8534604774 - 16.8654496427 - 16.8774473321 - 16.8894535516 - 16.9014683073 - 16.9134916052 - 16.9255234515 - 16.9375638521 - 16.9496128133 - 16.961670341 - 16.9737364414 - 16.9858111206 - 16.9978943846 - 17.0099862395 - 17.0220866916 - 17.0341957468 - 17.0463134113 - 17.0584396912 - 17.0705745927 - 17.0827181218 - 17.0948702848 - 17.1070310877 - 17.1192005367 - 17.1313786379 - 17.1435653975 - 17.1557608217 - 17.1679649166 - 17.1801776883 - 17.1923991431 - 17.2046292871 - 17.2168681265 - 17.2291156674 - 17.2413719161 - 17.2536368788 - 17.2659105616 - 17.2781929707 - 17.2904841124 - 17.3027839928 - 17.3150926183 - 17.3274099949 - 17.3397361289 - 17.3520710266 - 17.3644146941 - 17.3767671377 - 17.3891283637 - 17.4014983782 - 17.4138771876 - 17.4262647981 - 17.4386612159 - 17.4510664474 - 17.4634804987 - 17.4759033761 - 17.488335086 - 17.5007756345 - 17.5132250281 - 17.5256832729 - 17.5381503753 - 17.5506263415 - 17.563111178 - 17.5756048908 - 17.5881074865 - 17.6006189713 - 17.6131393514 - 17.6256686334 - 17.6382068233 - 17.6507539277 - 17.6633099529 - 17.6758749051 - 17.6884487908 - 17.7010316162 - 17.7136233878 - 17.7262241118 - 17.7388337948 - 17.7514524429 - 17.7640800627 - 17.7767166605 - 17.7893622426 - 17.8020168155 - 17.8146803856 - 17.8273529592 - 17.8400345427 - 17.8527251426 - 17.8654247653 - 17.8781334171 - 17.8908511045 - 17.903577834 - 17.9163136119 - 17.9290584447 - 17.9418123388 - 17.9545753007 - 17.9673473368 - 17.9801284536 - 17.9929186575 - 18.0057179549 - 18.0185263525 - 18.0313438565 - 18.0441704735 - 18.05700621 - 18.0698510724 - 18.0827050673 - 18.0955682011 - 18.1084404804 - 18.1213219116 - 18.1342125012 - 18.1471122558 - 18.1600211818 - 18.1729392859 - 18.1858665744 - 18.198803054 - 18.2117487312 - 18.2247036125 - 18.2376677045 - 18.2506410137 - 18.2636235466 - 18.2766153099 - 18.28961631 - 18.3026265536 - 18.3156460473 - 18.3286747975 - 18.3417128109 - 18.3547600941 - 18.3678166536 - 18.3808824961 - 18.3939576282 - 18.4070420564 - 18.4201357874 - 18.4332388277 - 18.4463511841 - 18.4594728631 - 18.4726038713 - 18.4857442154 - 18.4988939021 - 18.5120529379 - 18.5252213295 - 18.5383990836 - 18.5515862068 - 18.5647827058 - 18.5779885873 - 18.5912038579 - 18.6044285242 - 18.6176625931 - 18.6309060711 - 18.6441589649 - 18.6574212813 - 18.6706930269 - 18.6839742085 - 18.6972648328 - 18.7105649064 - 18.7238744361 - 18.7371934286 - 18.7505218906 - 18.7638598289 - 18.7772072503 - 18.7905641614 - 18.8039305689 - 18.8173064798 - 18.8306919006 - 18.8440868382 - 18.8574912993 - 18.8709052908 - 18.8843288193 - 18.8977618917 - 18.9112045147 - 18.9246566952 - 18.9381184399 - 18.9515897557 - 18.9650706493 - 18.9785611275 - 18.9920611972 - 19.0055708651 - 19.0190901382 - 19.0326190232 - 19.046157527 - 19.0597056564 - 19.0732634182 - 19.0868308194 - 19.1004078667 - 19.113994567 - 19.1275909271 - 19.1411969541 - 19.1548126546 - 19.1684380356 - 19.182073104 - 19.1957178667 - 19.2093723305 - 19.2230365024 - 19.2367103892 - 19.2503939979 - 19.2640873353 - 19.2777904085 - 19.2915032243 - 19.3052257896 - 19.3189581113 - 19.3327001965 - 19.3464520521 - 19.3602136849 - 19.373985102 - 19.3877663103 - 19.4015573167 - 19.4153581283 - 19.429168752 - 19.4429891947 - 19.4568194636 - 19.4706595654 - 19.4845095073 - 19.4983692963 - 19.5122389393 - 19.5261184433 - 19.5400078153 - 19.5539070625 - 19.5678161917 - 19.58173521 - 19.5956641245 - 19.6096029422 - 19.6235516701 - 19.6375103152 - 19.6514788847 - 19.6654573856 - 19.6794458249 - 19.6934442097 - 19.707452547 - 19.721470844 - 19.7354991078 - 19.7495373453 - 19.7635855638 - 19.7776437703 - 19.7917119719 - 19.8057901757 - 19.8198783888 - 19.8339766183 - 19.8480848715 - 19.8622031553 - 19.8763314769 - 19.8904698435 - 19.9046182621 - 19.9187767401 - 19.9329452844 - 19.9471239023 - 19.9613126008 - 19.9755113873 - 19.9897202688 - 20.0039392526 - 20.0181683458 - 20.0324075556 - 20.0466568891 - 20.0609163537 - 20.0751859565 - 20.0894657046 - 20.1037556054 - 20.118055666 - 20.1323658937 - 20.1466862957 - 20.1610168792 - 20.1753576514 - 20.1897086197 - 20.2040697912 - 20.2184411732 - 20.232822773 - 20.2472145978 - 20.2616166549 - 20.2760289516 - 20.2904514951 - 20.3048842928 - 20.319327352 - 20.3337806798 - 20.3482442837 - 20.3627181709 - 20.3772023488 - 20.3916968246 - 20.4062016057 - 20.4207166994 - 20.4352421131 - 20.449777854 - 20.4643239296 - 20.4788803471 - 20.493447114 - 20.5080242376 - 20.5226117251 - 20.5372095841 - 20.5518178219 - 20.5664364459 - 20.5810654634 - 20.5957048819 - 20.6103547086 - 20.6250149512 - 20.6396856168 - 20.6543667131 - 20.6690582472 - 20.6837602268 - 20.6984726592 - 20.7131955518 - 20.7279289122 - 20.7426727476 - 20.7574270656 - 20.7721918737 - 20.7869671792 - 20.8017529897 - 20.8165493126 - 20.8313561554 - 20.8461735255 - 20.8610014306 - 20.8758398779 - 20.8906888751 - 20.9055484297 - 20.9204185491 - 20.9352992408 - 20.9501905125 - 20.9650923715 - 20.9800048255 - 20.9949278819 - 21.0098615483 - 21.0248058322 - 21.0397607413 - 21.054726283 - 21.0697024649 - 21.0846892945 - 21.0996867795 - 21.1146949274 - 21.1297137458 - 21.1447432423 - 21.1597834245 - 21.1748342999 - 21.1898958762 - 21.204968161 - 21.2200511619 - 21.2351448865 - 21.2502493424 - 21.2653645373 - 21.2804904788 - 21.2956271746 - 21.3107746322 - 21.3259328594 - 21.3411018638 - 21.356281653 - 21.3714722348 - 21.3866736167 - 21.4018858066 - 21.417108812 - 21.4323426407 - 21.4475873003 - 21.4628427986 - 21.4781091432 - 21.4933863419 - 21.5086744024 - 21.5239733324 - 21.5392831396 - 21.5546038318 - 21.5699354167 - 21.585277902 - 21.6006312956 - 21.6159956051 - 21.6313708383 - 21.646757003 - 21.662154107 - 21.677562158 - 21.6929811639 - 21.7084111323 - 21.7238520711 - 21.7393039882 - 21.7547668912 - 21.7702407881 - 21.7857256866 - 21.8012215945 - 21.8167285197 - 21.8322464701 - 21.8477754534 - 21.8633154775 - 21.8788665502 - 21.8944286795 - 21.9100018731 - 21.925586139 - 21.9411814849 - 21.9567879189 - 21.9724054487 - 21.9880340822 - 22.0036738274 - 22.0193246922 - 22.0349866844 - 22.0506598119 - 22.0663440828 - 22.0820395048 - 22.097746086 - 22.1134638343 - 22.1291927576 - 22.1449328638 - 22.1606841609 - 22.1764466569 - 22.1922203597 - 22.2080052773 - 22.2238014176 - 22.2396087887 - 22.2554273985 - 22.2712572551 - 22.2870983663 - 22.3029507403 - 22.318814385 - 22.3346893084 - 22.3505755186 - 22.3664730236 - 22.3823818313 - 22.39830195 - 22.4142333875 - 22.4301761519 - 22.4461302513 - 22.4620956938 - 22.4780724874 - 22.4940606402 - 22.5100601602 - 22.5260710556 - 22.5420933344 - 22.5581270047 - 22.5741720747 - 22.5902285524 - 22.6062964459 - 22.6223757633 - 22.6384665129 - 22.6545687026 - 22.6706823407 - 22.6868074353 - 22.7029439945 - 22.7190920264 - 22.7352515393 - 22.7514225413 - 22.7676050405 - 22.7837990452 - 22.8000045635 - 22.8162216036 - 22.8324501736 - 22.8486902819 - 22.8649419366 - 22.8812051459 - 22.8974799179 - 22.9137662611 - 22.9300641835 - 22.9463736934 - 22.962694799 - 22.9790275086 - 22.9953718305 - 23.0117277728 - 23.0280953439 - 23.044474552 - 23.0608654054 - 23.0772679124 - 23.0936820812 - 23.1101079202 - 23.1265454376 - 23.1429946418 - 23.159455541 - 23.1759281436 - 23.1924124579 - 23.2089084922 - 23.2254162549 - 23.2419357542 - 23.2584669986 - 23.2750099964 - 23.2915647559 - 23.3081312855 - 23.3247095936 - 23.3412996886 - 23.3579015787 - 23.3745152725 - 23.3911407783 - 23.4077781045 - 23.4244272595 - 23.4410882518 - 23.4577610896 - 23.4744457816 - 23.491142336 - 23.5078507613 - 23.524571066 - 23.5413032585 - 23.5580473472 - 23.5748033407 - 23.5915712473 - 23.6083510756 - 23.625142834 - 23.641946531 - 23.6587621751 - 23.6755897748 - 23.6924293386 - 23.709280875 - 23.7261443925 - 23.7430198996 - 23.7599074049 - 23.7768069168 - 23.793718444 - 23.8106419949 - 23.8275775781 - 23.8445252022 - 23.8614848758 - 23.8784566073 - 23.8954404054 - 23.9124362786 - 23.9294442355 - 23.9464642848 - 23.963496435 - 23.9805406947 - 23.9975970725 - 24.0146655771 - 24.0317462171 - 24.048839001 - 24.0659439376 - 24.0830610354 - 24.1001903032 - 24.1173317495 - 24.1344853831 - 24.1516512126 - 24.1688292466 - 24.1860194938 - 24.203221963 - 24.2204366628 - 24.2376636019 - 24.254902789 - 24.2721542329 - 24.2894179422 - 24.3066939256 - 24.3239821919 - 24.3412827498 - 24.3585956081 - 24.3759207755 - 24.3932582607 - 24.4106080725 - 24.4279702197 - 24.4453447111 - 24.4627315553 - 24.4801307613 - 24.4975423378 - 24.5149662935 - 24.5324026373 - 24.549851378 - 24.5673125245 - 24.5847860854 - 24.6022720697 - 24.6197704862 - 24.6372813438 - 24.6548046512 - 24.6723404173 - 24.689888651 - 24.7074493611 - 24.7250225566 - 24.7426082463 - 24.760206439 - 24.7778171437 - 24.7954403693 - 24.8130761246 - 24.8307244186 - 24.8483852602 - 24.8660586583 - 24.8837446218 - 24.9014431597 - 24.9191542809 - 24.9368779943 - 24.954614309 - 24.9723632338 - 24.9901247778 - 25.0078989499 - 25.025685759 - 25.0434852143 - 25.0612973246 - 25.0791220989 - 25.0969595463 - 25.1148096758 - 25.1326724963 - 25.150548017 - 25.1684362468 - 25.1863371948 - 25.20425087 - 25.2221772815 - 25.2401164383 - 25.2580683495 - 25.2760330241 - 25.2940104712 - 25.3120007 - 25.3300037195 - 25.3480195387 - 25.3660481669 - 25.384089613 - 25.4021438863 - 25.4202109957 - 25.4382909506 - 25.4563837599 - 25.4744894329 - 25.4926079786 - 25.5107394062 - 25.528883725 - 25.547040944 - 25.5652110724 - 25.5833941194 - 25.6015900942 - 25.6197990059 - 25.6380208639 - 25.6562556772 - 25.6745034551 - 25.6927642068 - 25.7110379416 - 25.7293246686 - 25.7476243971 - 25.7659371364 - 25.7842628957 - 25.8026016842 - 25.8209535112 - 25.839318386 - 25.8576963179 - 25.8760873161 - 25.8944913899 - 25.9129085487 - 25.9313388017 - 25.9497821583 - 25.9682386277 - 25.9867082193 - 26.0051909424 - 26.0236868063 - 26.0421958205 - 26.0607179942 - 26.0792533368 - 26.0978018576 - 26.1163635661 - 26.1349384716 - 26.1535265835 - 26.1721279111 - 26.190742464 - 26.2093702514 - 26.2280112828 - 26.2466655676 - 26.2653331152 - 26.2840139351 - 26.3027080367 - 26.3214154294 - 26.3401361226 - 26.358870126 - 26.3776174488 - 26.3963781006 - 26.4151520909 - 26.4339394291 - 26.4527401247 - 26.4715541873 - 26.4903816262 - 26.5092224511 - 26.5280766715 - 26.5469442968 - 26.5658253366 - 26.5847198005 - 26.603627698 - 26.6225490386 - 26.6414838319 - 26.6604320875 - 26.6793938149 - 26.6983690237 - 26.7173577235 - 26.7363599239 - 26.7553756345 - 26.7744048649 - 26.7934476247 - 26.8125039235 - 26.8315737709 - 26.8506571767 - 26.8697541504 - 26.8888647016 - 26.90798884 - 26.9271265754 - 26.9462779173 - 26.9654428754 - 26.9846214594 - 27.003813679 - 27.0230195439 - 27.0422390638 - 27.0614722484 - 27.0807191074 - 27.0999796505 - 27.1192538875 - 27.1385418281 - 27.157843482 - 27.1771588591 - 27.1964879689 - 27.2158308214 - 27.2351874263 - 27.2545577933 - 27.2739419323 - 27.293339853 - 27.3127515653 - 27.3321770789 - 27.3516164036 - 27.3710695494 - 27.3905365259 - 27.4100173431 - 27.4295120107 - 27.4490205387 - 27.4685429368 - 27.488079215 - 27.507629383 - 27.5271934509 - 27.5467714284 - 27.5663633255 - 27.585969152 - 27.6055889179 - 27.625222633 - 27.6448703074 - 27.6645319508 - 27.6842075733 - 27.7038971847 - 27.7236007951 - 27.7433184143 - 27.7630500524 - 27.7827957193 - 27.8025554249 - 27.8223291794 - 27.8421169925 - 27.8619188744 - 27.8817348351 - 27.9015648845 - 27.9214090327 - 27.9412672896 - 27.9611396654 - 27.9810261701 - 28.0009268137 - 28.0208416062 - 28.0407705578 - 28.0607136784 - 28.0806709782 - 28.1006424673 - 28.1206281557 - 28.1406280535 - 28.1606421708 - 28.1806705178 - 28.2007131045 - 28.2207699412 - 28.2408410378 - 28.2609264046 - 28.2810260517 - 28.3011399892 - 28.3212682273 - 28.3414107763 - 28.3615676461 - 28.3817388471 - 28.4019243895 - 28.4221242833 - 28.4423385389 - 28.4625671664 - 28.4828101761 - 28.5030675781 - 28.5233393828 - 28.5436256003 - 28.5639262408 - 28.5842413148 - 28.6045708324 - 28.6249148038 - 28.6452732394 - 28.6656461495 - 28.6860335443 - 28.7064354341 - 28.7268518292 - 28.74728274 - 28.7677281768 - 28.7881881499 - 28.8086626696 - 28.8291517463 - 28.8496553903 - 28.870173612 - 28.8907064218 - 28.9112538299 - 28.9318158469 - 28.9523924831 - 28.9729837488 - 28.9935896545 - 29.0142102106 - 29.0348454275 - 29.0554953157 - 29.0761598855 - 29.0968391474 - 29.1175331118 - 29.1382417892 - 29.1589651901 - 29.179703325 - 29.2004562042 - 29.2212238383 - 29.2420062378 - 29.2628034132 - 29.2836153749 - 29.3044421335 - 29.3252836996 - 29.3461400836 - 29.367011296 - 29.3878973475 - 29.4087982485 - 29.4297140097 - 29.4506446416 - 29.4715901547 - 29.4925505597 - 29.5135258671 - 29.5345160875 - 29.5555212316 - 29.5765413099 - 29.597576333 - 29.6186263117 - 29.6396912564 - 29.6607711779 - 29.6818660868 - 29.7029759938 - 29.7241009095 - 29.7452408446 - 29.7663958098 - 29.7875658157 - 29.8087508731 - 29.8299509927 - 29.8511661851 - 29.8723964611 - 29.8936418314 - 29.9149023067 - 29.9361778978 - 29.9574686154 - 29.9787744703 - 30.0000954733 - 30.021431635 - 30.0427829664 - 30.0641494781 - 30.085531181 - 30.1069280858 - 30.1283402034 - 30.1497675447 - 30.1712101203 - 30.1926679412 - 30.2141410181 - 30.235629362 - 30.2571329837 - 30.278651894 - 30.3001861038 - 30.3217356241 - 30.3433004656 - 30.3648806393 - 30.386476156 - 30.4080870268 - 30.4297132624 - 30.4513548739 - 30.4730118721 - 30.4946842681 - 30.5163720726 - 30.5380752968 - 30.5597939515 - 30.5815280478 - 30.6032775966 - 30.6250426088 - 30.6468230956 - 30.6686190678 - 30.6904305366 - 30.7122575129 - 30.7341000077 - 30.7559580321 - 30.7778315971 - 30.7997207138 - 30.8216253933 - 30.8435456465 - 30.8654814846 - 30.8874329186 - 30.9093999596 - 30.9313826188 - 30.9533809072 - 30.975394836 - 30.9974244163 - 31.0194696591 - 31.0415305756 - 31.0636071771 - 31.0856994745 - 31.1078074792 - 31.1299312022 - 31.1520706547 - 31.1742258479 - 31.1963967931 - 31.2185835013 - 31.2407859839 - 31.2630042519 - 31.2852383168 - 31.3074881896 - 31.3297538816 - 31.3520354041 - 31.3743327683 - 31.3966459854 - 31.4189750669 - 31.4413200238 - 31.4636808676 - 31.4860576096 - 31.5084502609 - 31.5308588329 - 31.553283337 - 31.5757237845 - 31.5981801867 - 31.620652555 - 31.6431409006 - 31.6656452351 - 31.6881655696 - 31.7107019157 - 31.7332542847 - 31.7558226879 - 31.7784071369 - 31.8010076429 - 31.8236242175 - 31.8462568719 - 31.8689056178 - 31.8915704665 - 31.9142514294 - 31.936948518 - 31.9596617438 - 31.9823911183 - 32.0051366529 - 32.0278983591 - 32.0506762484 - 32.0734703324 - 32.0962806225 - 32.1191071303 - 32.1419498673 - 32.164808845 - 32.1876840749 - 32.2105755687 - 32.233483338 - 32.2564073941 - 32.2793477489 - 32.3023044137 - 32.3252774003 - 32.3482667203 - 32.3712723851 - 32.3942944066 - 32.4173327963 - 32.4403875658 - 32.4634587267 - 32.4865462908 - 32.5096502698 - 32.5327706751 - 32.5559075187 - 32.579060812 - 32.6022305669 - 32.6254167951 - 32.6486195082 - 32.6718387179 - 32.6950744361 - 32.7183266744 - 32.7415954445 - 32.7648807583 - 32.7881826275 - 32.8115010639 - 32.8348360792 - 32.8581876852 - 32.8815558938 - 32.9049407167 - 32.9283421657 - 32.9517602527 - 32.9751949895 - 32.998646388 - 33.0221144599 - 33.0455992171 - 33.0691006716 - 33.0926188351 - 33.1161537195 - 33.1397053368 - 33.1632736989 - 33.1868588175 - 33.2104607047 - 33.2340793724 - 33.2577148325 - 33.2813670969 - 33.3050361777 - 33.3287220866 - 33.3524248358 - 33.3761444372 - 33.3998809027 - 33.4236342444 - 33.4474044743 - 33.4711916043 - 33.4949956464 - 33.5188166128 - 33.5426545154 - 33.5665093663 - 33.5903811775 - 33.6142699611 - 33.6381757292 - 33.6620984938 - 33.6860382669 - 33.7099950608 - 33.7339688875 - 33.7579597591 - 33.7819676878 - 33.8059926856 - 33.8300347647 - 33.8540939372 - 33.8781702154 - 33.9022636113 - 33.9263741371 - 33.950501805 - 33.9746466272 - 33.9988086159 - 34.0229877833 - 34.0471841416 - 34.0713977031 - 34.0956284799 - 34.1198764843 - 34.1441417285 - 34.1684242249 - 34.1927239856 - 34.217041023 - 34.2413753493 - 34.2657269768 - 34.2900959179 - 34.3144821847 - 34.3388857898 - 34.3633067453 - 34.3877450636 - 34.4122007571 - 34.4366738381 - 34.461164319 - 34.4856722121 - 34.5101975299 - 34.5347402846 - 34.5593004888 - 34.5838781548 - 34.608473295 - 34.6330859219 - 34.6577160478 - 34.6823636853 - 34.7070288468 - 34.7317115447 - 34.7564117916 - 34.7811295998 - 34.8058649819 - 34.8306179503 - 34.8553885176 - 34.8801766963 - 34.9049824989 - 34.929805938 - 34.954647026 - 34.9795057755 - 35.0043821991 - 35.0292763094 - 35.0541881188 - 35.0791176401 - 35.1040648858 - 35.1290298684 - 35.1540126007 - 35.1790130952 - 35.2040313645 - 35.2290674214 - 35.2541212783 - 35.2791929481 - 35.3042824434 - 35.3293897767 - 35.3545149609 - 35.3796580086 - 35.4048189325 - 35.4299977453 - 35.4551944598 - 35.4804090886 - 35.5056416445 - 35.5308921402 - 35.5561605886 - 35.5814470023 - 35.6067513942 - 35.632073777 - 35.6574141635 - 35.6827725665 - 35.7081489988 - 35.7335434733 - 35.7589560027 - 35.7843866 - 35.8098352778 - 35.8353020492 - 35.860786927 - 35.886289924 - 35.9118110531 - 35.9373503273 - 35.9629077593 - 35.9884833622 - 36.0140771489 - 36.0396891322 - 36.0653193251 - 36.0909677406 - 36.1166343916 - 36.142319291 - 36.168022452 - 36.1937438873 - 36.2194836101 - 36.2452416333 - 36.27101797 - 36.2968126331 - 36.3226256357 - 36.3484569909 - 36.3743067116 - 36.400174811 - 36.4260613021 - 36.451966198 - 36.4778895117 - 36.5038312564 - 36.5297914451 - 36.5557700911 - 36.5817672073 - 36.607782807 - 36.6338169032 - 36.6598695092 - 36.685940638 - 36.7120303029 - 36.7381385171 - 36.7642652936 - 36.7904106458 - 36.8165745868 - 36.8427571299 - 36.8689582882 - 36.895178075 - 36.9214165036 - 36.9476735872 - 36.973949339 - 37.0002437724 - 37.0265569006 - 37.0528887369 - 37.0792392946 - 37.105608587 - 37.1319966275 - 37.1584034294 - 37.1848290059 - 37.2112733706 - 37.2377365366 - 37.2642185175 - 37.2907193265 - 37.317238977 - 37.3437774825 - 37.3703348563 - 37.3969111119 - 37.4235062627 - 37.4501203222 - 37.4767533037 - 37.5034052207 - 37.5300760867 - 37.5567659151 - 37.5834747195 - 37.6102025133 - 37.6369493101 - 37.6637151232 - 37.6904999664 - 37.717303853 - 37.7441267967 - 37.770968811 - 37.7978299094 - 37.8247101055 - 37.8516094129 - 37.8785278451 - 37.9054654158 - 37.9324221387 - 37.9593980272 - 37.986393095 - 38.0134073558 - 38.0404408231 - 38.0674935108 - 38.0945654324 - 38.1216566015 - 38.148767032 - 38.1758967374 - 38.2030457315 - 38.230214028 - 38.2574016406 - 38.2846085831 - 38.3118348692 - 38.3390805126 - 38.3663455271 - 38.3936299266 - 38.4209337246 - 38.4482569352 - 38.475599572 - 38.5029616488 - 38.5303431796 - 38.5577441781 - 38.5851646582 - 38.6126046336 - 38.6400641184 - 38.6675431263 - 38.6950416712 - 38.7225597671 - 38.7500974277 - 38.7776546671 - 38.8052314992 - 38.8328279378 - 38.8604439969 - 38.8880796906 - 38.9157350326 - 38.9434100371 - 38.9711047179 - 38.9988190891 - 39.0265531646 - 39.0543069586 - 39.0820804849 - 39.1098737577 - 39.1376867909 - 39.1655195986 - 39.1933721949 - 39.2212445939 - 39.2491368096 - 39.2770488561 - 39.3049807475 - 39.3329324979 - 39.3609041214 - 39.3888956323 - 39.4169070445 - 39.4449383723 - 39.4729896298 - 39.5010608312 - 39.5291519907 - 39.5572631224 - 39.5853942406 - 39.6135453594 - 39.6417164931 - 39.669907656 - 39.6981188622 - 39.726350126 - 39.7546014617 - 39.7828728835 - 39.8111644058 - 39.8394760427 - 39.8678078087 - 39.8961597179 - 39.9245317849 - 39.9529240238 - 39.981336449 - 40.0097690749 - 40.0382219158 - 40.0666949861 - 40.0951883003 - 40.1237018726 - 40.1522357174 - 40.1807898493 - 40.2093642826 - 40.2379590318 - 40.2665741112 - 40.2952095354 - 40.3238653189 - 40.352541476 - 40.3812380213 - 40.4099549693 - 40.4386923344 - 40.4674501312 - 40.4962283743 - 40.5250270781 - 40.5538462573 - 40.5826859263 - 40.6115460997 - 40.6404267921 - 40.6693280182 - 40.6982497924 - 40.7271921295 - 40.7561550439 - 40.7851385505 - 40.8141426637 - 40.8431673983 - 40.8722127689 - 40.9012787901 - 40.9303654768 - 40.9594728434 - 40.9886009049 - 41.0177496758 - 41.0469191709 - 41.076109405 - 41.1053203927 - 41.1345521489 - 41.1638046882 - 41.1930780255 - 41.2223721756 - 41.2516871533 - 41.2810229733 - 41.3103796505 - 41.3397571997 - 41.3691556358 - 41.3985749736 - 41.4280152279 - 41.4574764137 - 41.4869585458 - 41.5164616391 - 41.5459857085 - 41.575530769 - 41.6050968354 - 41.6346839227 - 41.6642920458 - 41.6939212197 - 41.7235714593 - 41.7532427797 - 41.7829351958 - 41.8126487227 - 41.8423833752 - 41.8721391685 - 41.9019161176 - 41.9317142375 - 41.9615335433 - 41.99137405 - 42.0212357727 - 42.0511187265 - 42.0810229265 - 42.1109483878 - 42.1408951255 - 42.1708631547 - 42.2008524906 - 42.2308631483 - 42.260895143 - 42.2909484899 - 42.3210232041 - 42.3511193008 - 42.3812367952 - 42.4113757026 - 42.4415360382 - 42.4717178171 - 42.5019210547 - 42.5321457662 - 42.5623919669 - 42.592659672 - 42.6229488969 - 42.6532596567 - 42.683591967 - 42.7139458429 - 42.7443212998 - 42.7747183531 - 42.805137018 - 42.83557731 - 42.8660392445 - 42.8965228368 - 42.9270281023 - 42.9575550565 - 42.9881037147 - 43.0186740924 - 43.0492662051 - 43.0798800681 - 43.110515697 - 43.1411731072 - 43.1718523142 - 43.2025533335 - 43.2332761807 - 43.2640208711 - 43.2947874205 - 43.3255758442 - 43.3563861579 - 43.3872183771 - 43.4180725174 - 43.4489485944 - 43.4798466237 - 43.5107666209 - 43.5417086015 - 43.5726725813 - 43.6036585759 - 43.6346666009 - 43.665696672 - 43.6967488048 - 43.7278230151 - 43.7589193186 - 43.7900377309 - 43.8211782677 - 43.8523409449 - 43.8835257782 - 43.9147327832 - 43.9459619758 - 43.9772133717 - 44.0084869867 - 44.0397828367 - 44.0711009374 - 44.1024413046 - 44.1338039542 - 44.165188902 - 44.1965961639 - 44.2280257558 - 44.2594776935 - 44.2909519928 - 44.3224486698 - 44.3539677403 - 44.3855092202 - 44.4170731255 - 44.4486594721 - 44.4802682759 - 44.511899553 - 44.5435533193 - 44.5752295908 - 44.6069283835 - 44.6386497134 - 44.6703935965 - 44.702160049 - 44.7339490867 - 44.7657607258 - 44.7975949823 - 44.8294518724 - 44.8613314121 - 44.8932336175 - 44.9251585048 - 44.95710609 - 44.9890763893 - 45.0210694188 - 45.0530851948 - 45.0851237333 - 45.1171850506 - 45.1492691629 - 45.1813760863 - 45.2135058372 - 45.2456584316 - 45.2778338859 - 45.3100322163 - 45.342253439 - 45.3744975705 - 45.4067646268 - 45.4390546244 - 45.4713675796 - 45.5037035086 - 45.5360624278 - 45.5684443536 - 45.6008493022 - 45.6332772902 - 45.6657283338 - 45.6982024494 - 45.7306996535 - 45.7632199625 - 45.7957633928 - 45.8283299607 - 45.8609196829 - 45.8935325757 - 45.9261686557 - 45.9588279392 - 45.9915104429 - 46.0242161831 - 46.0569451765 - 46.0896974396 - 46.1224729888 - 46.1552718409 - 46.1880940122 - 46.2209395195 - 46.2538083793 - 46.2867006082 - 46.3196162228 - 46.3525552397 - 46.3855176757 - 46.4185035473 - 46.4515128711 - 46.484545664 - 46.5176019425 - 46.5506817234 - 46.5837850233 - 46.616911859 - 46.6500622473 - 46.6832362048 - 46.7164337483 - 46.7496548947 - 46.7828996606 - 46.8161680628 - 46.8494601183 - 46.8827758437 - 46.916115256 - 46.9494783719 - 46.9828652084 - 47.0162757822 - 47.0497101102 - 47.0831682094 - 47.1166500967 - 47.1501557889 - 47.183685303 - 47.2172386559 - 47.2508158646 - 47.284416946 - 47.3180419171 - 47.3516907949 - 47.3853635964 - 47.4190603386 - 47.4527810385 - 47.4865257131 - 47.5202943795 - 47.5540870548 - 47.587903756 - 47.6217445002 - 47.6556093045 - 47.689498186 - 47.7234111618 - 47.7573482491 - 47.791309465 - 47.8252948266 - 47.8593043512 - 47.8933380558 - 47.9273959577 - 47.9614780742 - 47.9955844223 - 48.0297150193 - 48.0638698826 - 48.0980490293 - 48.1322524766 - 48.166480242 - 48.2007323426 - 48.2350087957 - 48.2693096188 - 48.303634829 - 48.3379844438 - 48.3723584805 - 48.4067569564 - 48.441179889 - 48.4756272956 - 48.5100991936 - 48.5445956004 - 48.5791165335 - 48.6136620104 - 48.6482320483 - 48.6828266649 - 48.7174458775 - 48.7520897038 - 48.786758161 - 48.8214512669 - 48.8561690389 - 48.8909114946 - 48.9256786514 - 48.960470527 - 48.9952871389 - 49.0301285048 - 49.0649946421 - 49.0998855686 - 49.1348013019 - 49.1697418595 - 49.2047072592 - 49.2396975186 - 49.2747126554 - 49.3097526872 - 49.3448176318 - 49.3799075069 - 49.4150223302 - 49.4501621194 - 49.4853268923 - 49.5205166667 - 49.5557314603 - 49.5909712909 - 49.6262361764 - 49.6615261345 - 49.696841183 - 49.7321813399 - 49.7675466228 - 49.8029370498 - 49.8383526387 - 49.8737934074 - 49.9092593738 - 49.9447505557 - 49.9802669712 - 50.0158086382 - 50.0513755745 - 50.0869677983 - 50.1225853274 - 50.1582281799 - 50.1938963737 - 50.2295899269 - 50.2653088575 - 50.3010531836 - 50.3368229232 - 50.3726180943 - 50.4084387151 - 50.4442848037 - 50.4801563781 - 50.5160534565 - 50.551976057 - 50.5879241977 - 50.6238978969 - 50.6598971726 - 50.6959220432 - 50.7319725267 - 50.7680486413 - 50.8041504054 - 50.8402778371 - 50.8764309547 - 50.9126097764 - 50.9488143206 - 50.9850446055 - 51.0213006494 - 51.0575824706 - 51.0938900875 - 51.1302235183 - 51.1665827816 - 51.2029678955 - 51.2393788785 - 51.275815749 - 51.3122785254 - 51.3487672261 - 51.3852818696 - 51.4218224742 - 51.4583890585 - 51.4949816409 - 51.5316002399 - 51.568244874 - 51.6049155617 - 51.6416123216 - 51.6783351721 - 51.7150841318 - 51.7518592193 - 51.7886604531 - 51.8254878519 - 51.8623414343 - 51.8992212188 - 51.9361272241 - 51.9730594689 - 52.0100179717 - 52.0470027513 - 52.0840138264 - 52.1210512155 - 52.1581149376 - 52.1952050112 - 52.2323214551 - 52.2694642881 - 52.3066335288 - 52.3438291962 - 52.381051309 - 52.4182998859 - 52.4555749458 - 52.4928765076 - 52.53020459 - 52.567559212 - 52.6049403924 - 52.64234815 - 52.6797825038 - 52.7172434727 - 52.7547310756 - 52.7922453314 - 52.8297862591 - 52.8673538777 - 52.9049482061 - 52.9425692633 - 52.9802170684 - 53.0178916403 - 53.0555929981 - 53.0933211607 - 53.1310761474 - 53.1688579771 - 53.2066666689 - 53.244502242 - 53.2823647154 - 53.3202541083 - 53.3581704398 - 53.396113729 - 53.4340839952 - 53.4720812574 - 53.510105535 - 53.5481568471 - 53.5862352129 - 53.6243406516 - 53.6624731826 - 53.7006328251 - 53.7388195983 - 53.7770335215 - 53.8152746141 - 53.8535428953 - 53.8918383845 - 53.9301611011 - 53.9685110643 - 54.0068882936 - 54.0452928083 - 54.0837246279 - 54.1221837718 - 54.1606702594 - 54.19918411 - 54.2377253433 - 54.2762939786 - 54.3148900354 - 54.3535135333 - 54.3921644917 - 54.4308429302 - 54.4695488683 - 54.5082823255 - 54.5470433215 - 54.5858318757 - 54.6246480079 - 54.6634917375 - 54.7023630843 - 54.7412620678 - 54.7801887077 - 54.8191430237 - 54.8581250354 - 54.8971347626 - 54.9361722249 - 54.9752374421 - 55.0143304338 - 55.0534512199 - 55.0925998202 - 55.1317762542 - 55.170980542 - 55.2102127032 - 55.2494727577 - 55.2887607254 - 55.328076626 - 55.3674204794 - 55.4067923055 - 55.4461921242 - 55.4856199554 - 55.525075819 - 55.5645597349 - 55.6040717231 - 55.6436118036 - 55.6831799963 - 55.7227763211 - 55.7624007982 - 55.8020534475 - 55.841734289 - 55.8814433428 - 55.921180629 - 55.9609461676 - 56.0007399787 - 56.0405620824 - 56.0804124988 - 56.1202912481 - 56.1601983504 - 56.2001338258 - 56.2400976946 - 56.2800899769 - 56.3201106929 - 56.3601598628 - 56.400237507 - 56.4403436455 - 56.4804782987 - 56.5206414868 - 56.5608332301 - 56.601053549 - 56.6413024638 - 56.6815799947 - 56.7218861621 - 56.7622209864 - 56.802584488 - 56.8429766873 - 56.8833976045 - 56.9238472603 - 56.9643256749 - 57.0048328689 - 57.0453688628 - 57.0859336769 - 57.1265273317 - 57.1671498479 - 57.2078012459 - 57.2484815462 - 57.2891907693 - 57.329928936 - 57.3706960666 - 57.4114921819 - 57.4523173024 - 57.4931714488 - 57.5340546416 - 57.5749669016 - 57.6159082494 - 57.6568787057 - 57.6978782911 - 57.7389070265 - 57.7799649325 - 57.8210520298 - 57.8621683392 - 57.9033138815 - 57.9444886775 - 57.9856927479 - 58.0269261136 - 58.0681887954 - 58.1094808142 - 58.1508021908 - 58.192152946 - 58.2335331008 - 58.2749426761 - 58.3163816928 - 58.3578501718 - 58.399348134 - 58.4408756005 - 58.4824325922 - 58.52401913 - 58.5656352351 - 58.6072809284 - 58.648956231 - 58.6906611639 - 58.7323957481 - 58.7741600048 - 58.8159539551 - 58.8577776201 - 58.8996310208 - 58.9415141785 - 58.9834271142 - 59.0253698493 - 59.0673424048 - 59.1093448019 - 59.1513770619 - 59.193439206 - 59.2355312555 - 59.2776532315 - 59.3198051555 - 59.3619870487 - 59.4041989323 - 59.4464408277 - 59.4887127563 - 59.5310147394 - 59.5733467984 - 59.6157089546 - 59.6581012294 - 59.7005236444 - 59.7429762208 - 59.7854589802 - 59.8279719439 - 59.8705151336 - 59.9130885706 - 59.9556922764 - 59.9983262727 - 60.0409905809 - 60.0836852225 - 60.1264102192 - 60.1691655926 - 60.2119513641 - 60.2547675555 - 60.2976141883 - 60.3404912843 - 60.383398865 - 60.4263369521 - 60.4693055674 - 60.5123047325 - 60.5553344692 - 60.5983947991 - 60.6414857441 - 60.6846073259 - 60.7277595663 - 60.7709424871 - 60.81415611 - 60.857400457 - 60.9006755499 - 60.9439814105 - 60.9873180607 - 61.0306855224 - 61.0740838175 - 61.117512968 - 61.1609729957 - 61.2044639226 - 61.2479857707 - 61.291538562 - 61.3351223184 - 61.378737062 - 61.4223828149 - 61.466059599 - 61.5097674364 - 61.5535063492 - 61.5972763596 - 61.6410774895 - 61.6849097612 - 61.7287731967 - 61.7726678183 - 61.8165936481 - 61.8605507083 - 61.9045390211 - 61.9485586087 - 61.9926094933 - 62.0366916973 - 62.0808052428 - 62.1249501522 - 62.1691264477 - 62.2133341517 - 62.2575732865 - 62.3018438745 - 62.3461459379 - 62.3904794993 - 62.4348445809 - 62.4792412052 - 62.5236693946 - 62.5681291716 - 62.6126205586 - 62.6571435782 - 62.7016982526 - 62.7462846046 - 62.7909026566 - 62.8355524312 - 62.8802339508 - 62.9249472381 - 62.9696923157 - 63.0144692061 - 63.059277932 - 63.1041185161 - 63.1489909809 - 63.1938953491 - 63.2388316434 - 63.2837998866 - 63.3288001013 - 63.3738323102 - 63.4188965362 - 63.4639928019 - 63.5091211301 - 63.5542815438 - 63.5994740655 - 63.6446987183 - 63.6899555249 - 63.7352445081 - 63.780565691 - 63.8259190963 - 63.871304747 - 63.9167226659 - 63.9621728762 - 64.0076554006 - 64.0531702621 - 64.0987174839 - 64.1442970888 - 64.1899090999 - 64.2355535402 - 64.2812304329 - 64.3269398009 - 64.3726816673 - 64.4184560553 - 64.464262988 - 64.5101024885 - 64.55597458 - 64.6018792856 - 64.6478166286 - 64.6937866321 - 64.7397893194 - 64.7858247136 - 64.8318928381 - 64.8779937161 - 64.924127371 - 64.9702938259 - 65.0164931043 - 65.0627252295 - 65.1089902248 - 65.1552881135 - 65.2016189192 - 65.2479826651 - 65.2943793747 - 65.3408090715 - 65.3872717789 - 65.4337675203 - 65.4802963193 - 65.5268581993 - 65.5734531839 - 65.6200812966 - 65.666742561 - 65.7134370006 - 65.760164639 - 65.8069254999 - 65.8537196068 - 65.9005469834 - 65.9474076533 - 65.9943016402 - 66.0412289678 - 66.0881896598 - 66.1351837399 - 66.1822112319 - 66.2292721595 - 66.2763665465 - 66.3234944166 - 66.3706557938 - 66.4178507017 - 66.4650791643 - 66.5123412054 - 66.5596368488 - 66.6069661185 - 66.6543290384 - 66.7017256324 - 66.7491559244 - 66.7966199384 - 66.8441176984 - 66.8916492284 - 66.9392145523 - 66.9868136942 - 67.0344466782 - 67.0821135282 - 67.1298142685 - 67.177548923 - 67.225317516 - 67.2731200714 - 67.3209566135 - 67.3688271665 - 67.4167317545 - 67.4646704016 - 67.5126431322 - 67.5606499705 - 67.6086909407 - 67.656766067 - 67.7048753738 - 67.7530188854 - 67.801196626 - 67.8494086201 - 67.8976548919 - 67.9459354659 - 67.9942503664 - 68.0425996178 - 68.0909832446 - 68.1394012712 - 68.1878537221 - 68.2363406216 - 68.2848619944 - 68.333417865 - 68.3820082578 - 68.4306331974 - 68.4792927083 - 68.5279868153 - 68.5767155427 - 68.6254789153 - 68.6742769577 - 68.7231096946 - 68.7719771505 - 68.8208793503 - 68.8698163185 - 68.9187880799 - 68.9677946593 - 69.0168360814 - 69.065912371 - 69.1150235528 - 69.1641696518 - 69.2133506926 - 69.2625667001 - 69.3118176993 - 69.361103715 - 69.410424772 - 69.4597808953 - 69.5091721099 - 69.5585984406 - 69.6080599124 - 69.6575565504 - 69.7070883795 - 69.7566554248 - 69.8062577112 - 69.8558952639 - 69.9055681079 - 69.9552762683 - 70.0050197702 - 70.0547986388 - 70.1046128991 - 70.1544625764 - 70.2043476958 - 70.2542682826 - 70.3042243619 - 70.354215959 - 70.4042430991 - 70.4543058075 - 70.5044041095 - 70.5545380304 - 70.6047075955 - 70.6549128302 - 70.7051537598 - 70.7554304098 - 70.8057428054 - 70.8560909721 - 70.9064749354 - 70.9568947207 - 71.0073503534 - 71.0578418591 - 71.1083692633 - 71.1589325914 - 71.2095318691 - 71.2601671218 - 71.3108383752 - 71.3615456549 - 71.4122889864 - 71.4630683954 - 71.5138839076 - 71.5647355486 - 71.6156233441 - 71.6665473198 - 71.7175075015 - 71.7685039148 - 71.8195365856 - 71.8706055395 - 71.9217108025 - 71.9728524004 - 72.0240303588 - 72.0752447038 - 72.1264954612 - 72.1777826569 - 72.2291063167 - 72.2804664666 - 72.3318631326 - 72.3832963406 - 72.4347661165 - 72.4862724865 - 72.5378154765 - 72.5893951125 - 72.6410114206 - 72.6926644269 - 72.7443541574 - 72.7960806383 - 72.8478438957 - 72.8996439558 - 72.9514808447 - 73.0033545885 - 73.0552652136 - 73.1072127461 - 73.1591972123 - 73.2112186384 - 73.2632770507 - 73.3153724754 - 73.367504939 - 73.4196744678 - 73.471881088 - 73.5241248261 - 73.5764057085 - 73.6287237616 - 73.6810790117 - 73.7334714854 - 73.7859012091 - 73.8383682093 - 73.8908725124 - 73.9434141451 - 73.9959931339 - 74.0486095052 - 74.1012632858 - 74.1539545022 - 74.2066831809 - 74.2594493487 - 74.3122530323 - 74.3650942581 - 74.4179730531 - 74.4708894438 - 74.523843457 - 74.5768351195 - 74.629864458 - 74.6829314993 - 74.7360362702 - 74.7891787975 - 74.8423591081 - 74.8955772289 - 74.9488331867 - 75.0021270084 - 75.055458721 - 75.1088283514 - 75.1622359265 - 75.2156814733 - 75.2691650189 - 75.3226865902 - 75.3762462143 - 75.4298439182 - 75.483479729 - 75.5371536738 - 75.5908657797 - 75.6446160738 - 75.6984045834 - 75.7522313355 - 75.8060963573 - 75.8599996762 - 75.9139413192 - 75.9679213136 - 76.0219396868 - 76.0759964659 - 76.1300916783 - 76.1842253514 - 76.2383975124 - 76.2926081888 - 76.3468574079 - 76.401145197 - 76.4554715838 - 76.5098365955 - 76.5642402596 - 76.6186826037 - 76.6731636552 - 76.7276834417 - 76.7822419906 - 76.8368393296 - 76.8914754862 - 76.946150488 - 77.0008643627 - 77.0556171378 - 77.1104088411 - 77.1652395002 - 77.2201091428 - 77.2750177966 - 77.3299654894 - 77.384952249 - 77.439978103 - 77.4950430793 - 77.5501472057 - 77.60529051 - 77.6604730201 - 77.7156947639 - 77.7709557693 - 77.8262560642 - 77.8815956764 - 77.936974634 - 77.992392965 - 78.0478506973 - 78.1033478589 - 78.1588844779 - 78.2144605824 - 78.2700762004 - 78.3257313599 - 78.3814260892 - 78.4371604163 - 78.4929343694 - 78.5487479767 - 78.6046012664 - 78.6604942666 - 78.7164270057 - 78.7723995118 - 78.8284118133 - 78.8844639384 - 78.9405559154 - 78.9966877727 - 79.0528595387 - 79.1090712417 - 79.16532291 - 79.2216145722 - 79.2779462567 - 79.3343179918 - 79.3907298062 - 79.4471817282 - 79.5036737864 - 79.5602060094 - 79.6167784256 - 79.6733910637 - 79.7300439523 - 79.7867371199 - 79.8434705953 - 79.900244407 - 79.9570585838 - 80.0139131543 - 80.0708081473 - 80.1277435915 - 80.1847195157 - 80.2417359487 - 80.2987929192 - 80.355890456 - 80.4130285881 - 80.4702073443 - 80.5274267534 - 80.5846868444 - 80.6419876461 - 80.6993291876 - 80.7567114978 - 80.8141346057 - 80.8715985403 - 80.9291033305 - 80.9866490056 - 81.0442355945 - 81.1018631263 - 81.1595316301 - 81.2172411351 - 81.2749916704 - 81.3327832652 - 81.3906159487 - 81.44848975 - 81.5064046985 - 81.5643608234 - 81.6223581539 - 81.6803967194 - 81.7384765491 - 81.7965976724 - 81.8547601187 - 81.9129639174 - 81.9712090978 - 82.0294956893 - 82.0878237215 - 82.1461932237 - 82.2046042255 - 82.2630567564 - 82.3215508458 - 82.3800865234 - 82.4386638187 - 82.4972827613 - 82.5559433808 - 82.6146457068 - 82.673389769 - 82.7321755971 - 82.7910032207 - 82.8498726696 - 82.9087839735 - 82.9677371622 - 83.0267322654 - 83.085769313 - 83.1448483347 - 83.2039693605 - 83.2631324201 - 83.3223375435 - 83.3815847605 - 83.4408741012 - 83.5002055954 - 83.5595792731 - 83.6189951643 - 83.678453299 - 83.7379537073 - 83.7974964192 - 83.8570814648 - 83.9167088741 - 83.9763786774 - 84.0360909047 - 84.0958455862 - 84.1556427522 - 84.2154824327 - 84.275364658 - 84.3352894584 - 84.3952568642 - 84.4552669055 - 84.5153196129 - 84.5754150165 - 84.6355531467 - 84.695734034 - 84.7559577087 - 84.8162242012 - 84.876533542 - 84.9368857616 - 84.9972808903 - 85.0577189589 - 85.1181999976 - 85.1787240372 - 85.2392911082 - 85.2999012412 - 85.3605544668 - 85.4212508156 - 85.4819903183 - 85.5427730056 - 85.6035989082 - 85.6644680568 - 85.7253804821 - 85.786336215 - 85.8473352861 - 85.9083777264 - 85.9694635667 - 86.0305928378 - 86.0917655706 - 86.152981796 - 86.2142415449 - 86.2755448483 - 86.3368917371 - 86.3982822423 - 86.459716395 - 86.5211942261 - 86.5827157667 - 86.6442810479 - 86.7058901009 - 86.7675429566 - 86.8292396463 - 86.8909802011 - 86.9527646522 - 87.0145930309 - 87.0764653682 - 87.1383816956 - 87.2003420443 - 87.2623464456 - 87.3243949307 - 87.3864875311 - 87.4486242781 - 87.5108052031 - 87.5730303375 - 87.6352997127 - 87.6976133602 - 87.7599713115 - 87.822373598 - 87.8848202514 - 87.947311303 - 88.0098467846 - 88.0724267276 - 88.1350511638 - 88.1977201246 - 88.2604336419 - 88.3231917472 - 88.3859944723 - 88.4488418489 - 88.5117339087 - 88.5746706835 - 88.6376522051 - 88.7006785054 - 88.7637496161 - 88.826865569 - 88.8900263962 - 88.9532321295 - 89.0164828008 - 89.079778442 - 89.1431190853 - 89.2065047624 - 89.2699355055 - 89.3334113466 - 89.3969323178 - 89.4604984511 - 89.5241097787 - 89.5877663326 - 89.6514681451 - 89.7152152484 - 89.7790076745 - 89.8428454558 - 89.9067286245 - 89.9706572129 - 90.0346312532 - 90.0986507778 - 90.162715819 - 90.2268264092 - 90.2909825807 - 90.355184366 - 90.4194317975 - 90.4837249077 - 90.5480637289 - 90.6124482938 - 90.6768786349 - 90.7413547846 - 90.8058767756 - 90.8704446404 - 90.9350584118 - 90.9997181222 - 91.0644238044 - 91.129175491 - 91.1939732148 - 91.2588170086 - 91.3237069049 - 91.3886429367 - 91.4536251367 - 91.5186535378 - 91.5837281728 - 91.6488490745 - 91.7140162759 - 91.7792298099 - 91.8444897094 - 91.9097960075 - 91.975148737 - 92.040547931 - 92.1059936225 - 92.1714858446 - 92.2370246304 - 92.3026100129 - 92.3682420254 - 92.4339207009 - 92.4996460726 - 92.5654181738 - 92.6312370377 - 92.6971026974 - 92.7630151863 - 92.8289745377 - 92.8949807849 - 92.9610339612 - 93.0271341 - 93.0932812347 - 93.1594753987 - 93.2257166255 - 93.2920049484 - 93.358340401 - 93.4247230168 - 93.4911528293 - 93.5576298721 - 93.6241541788 - 93.6907257829 - 93.7573447181 - 93.8240110181 - 93.8907247164 - 93.9574858469 - 94.0242944432 - 94.0911505391 - 94.1580541684 - 94.2250053648 - 94.2920041622 - 94.3590505944 - 94.4261446953 - 94.4932864987 - 94.5604760386 - 94.627713349 - 94.6949984638 - 94.7623314169 - 94.8297122424 - 94.8971409744 - 94.9646176469 - 95.0321422939 - 95.0997149496 - 95.1673356481 - 95.2350044236 - 95.3027213103 - 95.3704863423 - 95.4382995539 - 95.5061609794 - 95.574070653 - 95.642028609 - 95.7100348817 - 95.7780895056 - 95.846192515 - 95.9143439442 - 95.9825438278 - 96.0507922001 - 96.1190890957 - 96.187434549 - 96.2558285946 - 96.3242712669 - 96.3927626007 - 96.4613026304 - 96.5298913907 - 96.5985289163 - 96.6672152418 - 96.7359504019 - 96.8047344314 - 96.8735673649 - 96.9424492373 - 97.0113800833 - 97.0803599378 - 97.1493888355 - 97.2184668115 - 97.2875939005 - 97.3567701375 - 97.4259955575 - 97.4952701953 - 97.5645940861 - 97.6339672647 - 97.7033897663 - 97.7728616259 - 97.8423828787 - 97.9119535596 - 97.981573704 - 98.0512433469 - 98.1209625235 - 98.190731269 - 98.2605496188 - 98.330417608 - 98.400335272 - 98.470302646 - 98.5403197654 - 98.6103866657 - 98.6805033821 - 98.7506699501 - 98.8208864051 - 98.8911527826 - 98.9614691182 - 99.0318354472 - 99.1022518054 - 99.1727182281 - 99.2432347511 - 99.3138014099 - 99.3844182403 - 99.4550852777 - 99.5258025581 - 99.596570117 - 99.6673879903 - 99.7382562136 - 99.8091748229 - 99.8801438539 - 99.9511633424 - 100.022233324 - 100.093353836 - 100.164524912 - 100.23574659 - 100.307018905 - 100.378341893 - 100.449715591 - 100.521140034 - 100.592615258 - 100.664141299 - 100.735718195 - 100.807345979 - 100.87902469 - 100.950754363 - 101.022535035 - 101.094366741 - 101.166249518 - 101.238183402 - 101.310168429 - 101.382204637 - 101.454292061 - 101.526430738 - 101.598620704 - 101.670861995 - 101.743154649 - 101.815498701 - 101.887894188 - 101.960341147 - 102.032839615 - 102.105389627 - 102.177991222 - 102.250644434 - 102.323349301 - 102.39610586 - 102.468914148 - 102.541774201 - 102.614686056 - 102.68764975 - 102.760665319 - 102.833732801 - 102.906852233 - 102.980023651 - 103.053247092 - 103.126522594 - 103.199850194 - 103.273229928 - 103.346661833 - 103.420145947 - 103.493682307 - 103.567270949 - 103.640911912 - 103.714605232 - 103.788350946 - 103.862149093 - 103.935999708 - 104.009902829 - 104.083858495 - 104.157866741 - 104.231927605 - 104.306041126 - 104.380207339 - 104.454426284 - 104.528697996 - 104.603022514 - 104.677399876 - 104.751830118 - 104.826313279 - 104.900849396 - 104.975438506 - 105.050080648 - 105.124775859 - 105.199524177 - 105.274325639 - 105.349180284 - 105.424088149 - 105.499049272 - 105.57406369 - 105.649131443 - 105.724252567 - 105.799427101 - 105.874655082 - 105.949936549 - 106.02527154 - 106.100660092 - 106.176102244 - 106.251598034 - 106.3271475 - 106.40275068 - 106.478407613 - 106.554118336 - 106.629882888 - 106.705701307 - 106.781573631 - 106.857499899 - 106.933480149 - 107.00951442 - 107.085602749 - 107.161745176 - 107.237941739 - 107.314192475 - 107.390497425 - 107.466856626 - 107.543270116 - 107.619737936 - 107.696260122 - 107.772836714 - 107.84946775 - 107.92615327 - 108.002893311 - 108.079687914 - 108.156537115 - 108.233440955 - 108.310399472 - 108.387412705 - 108.464480693 - 108.541603474 - 108.618781088 - 108.696013575 - 108.773300971 - 108.850643318 - 108.928040654 - 109.005493017 - 109.083000448 - 109.160562985 - 109.238180667 - 109.315853534 - 109.393581625 - 109.471364978 - 109.549203635 - 109.627097633 - 109.705047012 - 109.783051812 - 109.861112071 - 109.93922783 - 110.017399127 - 110.095626003 - 110.173908497 - 110.252246647 - 110.330640495 - 110.409090079 - 110.48759544 - 110.566156616 - 110.644773647 - 110.723446574 - 110.802175435 - 110.880960271 - 110.959801122 - 111.038698027 - 111.117651026 - 111.196660159 - 111.275725466 - 111.354846986 - 111.434024761 - 111.513258829 - 111.592549232 - 111.671896008 - 111.751299198 - 111.830758842 - 111.910274981 - 111.989847654 - 112.069476901 - 112.149162764 - 112.228905281 - 112.308704494 - 112.388560442 - 112.468473166 - 112.548442707 - 112.628469105 - 112.708552399 - 112.788692632 - 112.868889842 - 112.949144071 - 113.029455359 - 113.109823747 - 113.190249275 - 113.270731985 - 113.351271915 - 113.431869109 - 113.512523605 - 113.593235445 - 113.674004669 - 113.754831319 - 113.835715434 - 113.916657057 - 113.997656228 - 114.078712988 - 114.159827377 - 114.240999437 - 114.322229208 - 114.403516733 - 114.484862051 - 114.566265204 - 114.647726234 - 114.72924518 - 114.810822085 - 114.892456989 - 114.974149934 - 115.055900961 - 115.137710112 - 115.219577427 - 115.301502948 - 115.383486717 - 115.465528774 - 115.547629162 - 115.629787922 - 115.712005094 - 115.794280722 - 115.876614846 - 115.959007508 - 116.041458749 - 116.123968611 - 116.206537137 - 116.289164367 - 116.371850343 - 116.454595107 - 116.537398702 - 116.620261168 - 116.703182547 - 116.786162882 - 116.869202215 - 116.952300586 - 117.035458039 - 117.118674616 - 117.201950357 - 117.285285306 - 117.368679505 - 117.452132995 - 117.535645819 - 117.619218019 - 117.702849637 - 117.786540715 - 117.870291296 - 117.954101423 - 118.037971136 - 118.121900479 - 118.205889495 - 118.289938224 - 118.374046711 - 118.458214997 - 118.542443126 - 118.626731138 - 118.711079078 - 118.795486988 - 118.87995491 - 118.964482887 - 119.049070961 - 119.133719176 - 119.218427575 - 119.303196199 - 119.388025092 - 119.472914297 - 119.557863856 - 119.642873813 - 119.72794421 - 119.81307509 - 119.898266497 - 119.983518474 - 120.068831062 - 120.154204307 - 120.23963825 - 120.325132934 - 120.410688404 - 120.496304702 - 120.581981872 - 120.667719956 - 120.753518998 - 120.839379042 - 120.925300131 - 121.011282308 - 121.097325616 - 121.183430099 - 121.269595801 - 121.355822766 - 121.442111035 - 121.528460655 - 121.614871666 - 121.701344115 - 121.787878044 - 121.874473496 - 121.961130516 - 122.047849148 - 122.134629435 - 122.221471421 - 122.308375149 - 122.395340665 - 122.482368011 - 122.569457233 - 122.656608372 - 122.743821475 - 122.831096584 - 122.918433745 - 123.005833 - 123.093294394 - 123.180817972 - 123.268403777 - 123.356051854 - 123.443762247 - 123.531535 - 123.619370158 - 123.707267765 - 123.795227866 - 123.883250504 - 123.971335725 - 124.059483573 - 124.147694091 - 124.235967326 - 124.324303322 - 124.412702122 - 124.501163773 - 124.589688317 - 124.678275802 - 124.766926269 - 124.855639766 - 124.944416336 - 125.033256025 - 125.122158877 - 125.211124937 - 125.30015425 - 125.389246861 - 125.478402815 - 125.567622158 - 125.656904933 - 125.746251187 - 125.835660964 - 125.92513431 - 126.01467127 - 126.104271888 - 126.193936211 - 126.283664284 - 126.373456151 - 126.463311858 - 126.553231452 - 126.643214976 - 126.733262476 - 126.823373999 - 126.913549589 - 127.003789293 - 127.094093154 - 127.184461221 - 127.274893537 - 127.365390148 - 127.455951101 - 127.546576441 - 127.637266214 - 127.728020465 - 127.818839241 - 127.909722587 - 128.00067055 - 128.091683174 - 128.182760507 - 128.273902594 - 128.365109481 - 128.456381215 - 128.547717841 - 128.639119405 - 128.730585954 - 128.822117534 - 128.913714191 - 129.005375972 - 129.097102922 - 129.188895088 - 129.280752517 - 129.372675255 - 129.464663347 - 129.556716842 - 129.648835784 - 129.741020222 - 129.833270201 - 129.925585767 - 130.017966968 - 130.110413851 - 130.202926461 - 130.295504846 - 130.388149052 - 130.480859127 - 130.573635116 - 130.666477067 - 130.759385027 - 130.852359043 - 130.945399162 - 131.03850543 - 131.131677895 - 131.224916604 - 131.318221603 - 131.411592941 - 131.505030664 - 131.598534819 - 131.692105453 - 131.785742615 - 131.879446351 - 131.973216708 - 132.067053734 - 132.160957476 - 132.254927982 - 132.3489653 - 132.443069475 - 132.537240558 - 132.631478593 - 132.725783631 - 132.820155717 - 132.9145949 - 133.009101227 - 133.103674746 - 133.198315506 - 133.293023553 - 133.387798935 - 133.482641701 - 133.577551898 - 133.672529575 - 133.767574779 - 133.862687558 - 133.95786796 - 134.053116034 - 134.148431827 - 134.243815388 - 134.339266765 - 134.434786005 - 134.530373158 - 134.626028272 - 134.721751394 - 134.817542574 - 134.913401859 - 135.009329299 - 135.10532494 - 135.201388833 - 135.297521026 - 135.393721566 - 135.489990503 - 135.586327886 - 135.682733762 - 135.779208181 - 135.875751191 - 135.972362842 - 136.069043182 - 136.165792259 - 136.262610123 - 136.359496823 - 136.456452407 - 136.553476925 - 136.650570425 - 136.747732956 - 136.844964569 - 136.942265311 - 137.039635232 - 137.137074381 - 137.234582807 - 137.33216056 - 137.429807689 - 137.527524243 - 137.625310271 - 137.723165824 - 137.821090949 - 137.919085698 - 138.017150119 - 138.115284261 - 138.213488176 - 138.311761911 - 138.410105517 - 138.508519043 - 138.607002539 - 138.705556055 - 138.804179641 - 138.902873346 - 139.00163722 - 139.100471314 - 139.199375676 - 139.298350358 - 139.397395409 - 139.496510878 - 139.595696817 - 139.694953275 - 139.794280303 - 139.89367795 - 139.993146266 - 140.092685303 - 140.19229511 - 140.291975738 - 140.391727236 - 140.491549656 - 140.591443048 - 140.691407462 - 140.791442948 - 140.891549558 - 140.991727342 - 141.09197635 - 141.192296633 - 141.292688242 - 141.393151227 - 141.49368564 - 141.59429153 - 141.694968949 - 141.795717948 - 141.896538578 - 141.997430889 - 142.098394932 - 142.199430759 - 142.30053842 - 142.401717967 - 142.50296945 - 142.604292921 - 142.705688431 - 142.807156032 - 142.908695774 - 143.010307708 - 143.111991887 - 143.213748361 - 143.315577182 - 143.417478401 - 143.51945207 - 143.62149824 - 143.723616963 - 143.82580829 - 143.928072274 - 144.030408965 - 144.132818415 - 144.235300676 - 144.337855801 - 144.44048384 - 144.543184845 - 144.645958869 - 144.748805963 - 144.851726179 - 144.95471957 - 145.057786187 - 145.160926082 - 145.264139308 - 145.367425916 - 145.470785959 - 145.574219488 - 145.677726557 - 145.781307218 - 145.884961522 - 145.988689522 - 146.092491271 - 146.196366821 - 146.300316225 - 146.404339534 - 146.508436802 - 146.612608081 - 146.716853424 - 146.821172883 - 146.925566511 - 147.030034361 - 147.134576485 - 147.239192937 - 147.343883769 - 147.448649034 - 147.553488785 - 147.658403075 - 147.763391957 - 147.868455485 - 147.97359371 - 148.078806686 - 148.184094467 - 148.289457105 - 148.394894654 - 148.500407167 - 148.605994698 - 148.711657299 - 148.817395024 - 148.923207926 - 149.029096059 - 149.135059477 - 149.241098232 - 149.347212379 - 149.453401971 - 149.559667062 - 149.666007705 - 149.772423954 - 149.878915863 - 149.985483486 - 150.092126876 - 150.198846087 - 150.305641174 - 150.41251219 - 150.519459189 - 150.626482225 - 150.733581353 - 150.840756625 - 150.948008098 - 151.055335824 - 151.162739858 - 151.270220254 - 151.377777066 - 151.485410349 - 151.593120158 - 151.700906545 - 151.808769567 - 151.916709278 - 152.024725731 - 152.132818982 - 152.240989085 - 152.349236094 - 152.457560066 - 152.565961053 - 152.674439112 - 152.782994296 - 152.89162666 - 153.000336261 - 153.109123151 - 153.217987387 - 153.326929023 - 153.435948115 - 153.545044717 - 153.654218884 - 153.763470672 - 153.872800136 - 153.982207331 - 154.091692313 - 154.201255136 - 154.310895856 - 154.420614528 - 154.530411208 - 154.640285952 - 154.750238814 - 154.86026985 - 154.970379117 - 155.080566669 - 155.190832562 - 155.301176852 - 155.411599594 - 155.522100845 - 155.63268066 - 155.743339095 - 155.854076207 - 155.96489205 - 156.07578668 - 156.186760155 - 156.29781253 - 156.40894386 - 156.520154203 - 156.631443615 - 156.74281215 - 156.854259867 - 156.965786821 - 157.077393068 - 157.189078665 - 157.300843668 - 157.412688134 - 157.524612119 - 157.63661568 - 157.748698873 - 157.860861755 - 157.973104383 - 158.085426813 - 158.197829102 - 158.310311306 - 158.422873484 - 158.535515691 - 158.648237984 - 158.76104042 - 158.873923057 - 158.986885951 - 159.09992916 - 159.21305274 - 159.326256748 - 159.439541243 - 159.55290628 - 159.666351918 - 159.779878213 - 159.893485224 - 160.007173006 - 160.120941619 - 160.234791118 - 160.348721562 - 160.462733009 - 160.576825515 - 160.690999139 - 160.805253939 - 160.919589971 - 161.034007293 - 161.148505964 - 161.263086042 - 161.377747583 - 161.492490647 - 161.607315291 - 161.722221573 - 161.83720955 - 161.952279282 - 162.067430827 - 162.182664241 - 162.297979585 - 162.413376915 - 162.528856291 - 162.64441777 - 162.760061411 - 162.875787272 - 162.991595412 - 163.10748589 - 163.223458763 - 163.33951409 - 163.455651931 - 163.571872344 - 163.688175386 - 163.804561118 - 163.921029598 - 164.037580885 - 164.154215037 - 164.270932114 - 164.387732174 - 164.504615277 - 164.621581482 - 164.738630847 - 164.855763432 - 164.972979296 - 165.090278498 - 165.207661097 - 165.325127153 - 165.442676725 - 165.560309873 - 165.678026655 - 165.795827132 - 165.913711363 - 166.031679406 - 166.149731323 - 166.267867173 - 166.386087014 - 166.504390908 - 166.622778913 - 166.74125109 - 166.859807498 - 166.978448197 - 167.097173248 - 167.21598271 - 167.334876642 - 167.453855107 - 167.572918162 - 167.692065869 - 167.811298287 - 167.930615478 - 168.050017501 - 168.169504416 - 168.289076284 - 168.408733165 - 168.528475119 - 168.648302208 - 168.768214492 - 168.888212031 - 169.008294886 - 169.128463117 - 169.248716785 - 169.369055952 - 169.489480677 - 169.609991022 - 169.730587047 - 169.851268814 - 169.972036383 - 170.092889815 - 170.213829172 - 170.334854514 - 170.455965903 - 170.577163399 - 170.698447065 - 170.819816961 - 170.941273148 - 171.062815689 - 171.184444644 - 171.306160074 - 171.427962042 - 171.549850609 - 171.671825835 - 171.793887784 - 171.916036517 - 172.038272095 - 172.16059458 - 172.283004033 - 172.405500518 - 172.528084095 - 172.650754826 - 172.773512774 - 172.896358001 - 173.019290568 - 173.142310537 - 173.265417971 - 173.388612933 - 173.511895483 - 173.635265685 - 173.758723601 - 173.882269292 - 174.005902823 - 174.129624254 - 174.253433649 - 174.377331069 - 174.501316579 - 174.625390239 - 174.749552114 - 174.873802265 - 174.998140756 - 175.122567648 - 175.247083006 - 175.371686892 - 175.496379369 - 175.621160499 - 175.746030346 - 175.870988974 - 175.996036444 - 176.121172821 - 176.246398167 - 176.371712546 - 176.497116021 -} diff --git a/release/datafiles/colormanagement/luts/logc_to_aces.spimtx b/release/datafiles/colormanagement/luts/logc_to_aces.spimtx deleted file mode 100644 index 5536fb88956..00000000000 --- a/release/datafiles/colormanagement/luts/logc_to_aces.spimtx +++ /dev/null @@ -1,4 +0,0 @@ -0.680206 0.236137 0.083658 0 -0.085415 1.017471 -0.102886 0 -0.002057 -0.062563 1.060506 0 - diff --git a/release/datafiles/colormanagement/luts/rrt_ut33_p3d60.spi3d b/release/datafiles/colormanagement/luts/rrt_ut33_p3d60.spi3d deleted file mode 100644 index c6530f056a5..00000000000 --- a/release/datafiles/colormanagement/luts/rrt_ut33_p3d60.spi3d +++ /dev/null @@ -1,32771 +0,0 @@ -SPILUT 1.0 -3 3 -32 32 32 -0 0 0 0.00109959 0.00109959 0.00109959 -0 0 1 0.00569153 0.00605011 0.00720215 -0 0 2 0.00891113 0.0108261 0.0154953 -0 0 3 0.00783539 0.0150299 0.0260162 -0 0 4 0 0.0188751 0.0394592 -0 0 5 0 0.0215912 0.053772 -0 0 6 0 0.0240784 0.0693359 -0 0 7 0 0.0274048 0.0880737 -0 0 8 0 0.0323486 0.111938 -0 0 9 0 0.0394897 0.142822 -0 0 10 0 0.049469 0.18335 -0 0 11 0 0.0626221 0.235352 -0 0 12 0 0.0783691 0.296387 -0 0 13 0 0.0962524 0.365723 -0 0 14 0 0.116089 0.442139 -0 0 15 0 0.137329 0.523926 -0 0 16 0 0.159424 0.608398 -0 0 17 0 0.180664 0.689941 -0 0 18 0 0.200317 0.764648 -0 0 19 0 0.217529 0.830566 -0 0 20 0 0.227051 0.867188 -0 0 21 0 0.228882 0.874512 -0 0 22 0 0.230835 0.881836 -0 0 23 0 0.23291 0.889648 -0 0 24 0 0.234863 0.897461 -0 0 25 0 0.237183 0.90625 -0 0 26 0 0.239624 0.915527 -0 0 27 0 0.24231 0.925781 -0 0 28 0 0.245483 0.937988 -0 0 29 0 0.248779 0.950684 -0 0 30 0 0.252197 0.963379 -0 0 31 0 0.255859 0.977051 -0 1 0 0.00445938 0.0057373 0.00481796 -0 1 1 0.0063858 0.0088501 0.00888824 -0 1 2 0.00794983 0.0131149 0.0159454 -0 1 3 0.00190449 0.0175018 0.0259552 -0 1 4 0 0.0216827 0.0393066 -0 1 5 0 0.0243988 0.0537109 -0 1 6 0 0.0265808 0.0693359 -0 1 7 0 0.0294342 0.0880737 -0 1 8 0 0.0338745 0.111938 -0 1 9 0 0.0405884 0.142822 -0 1 10 0 0.0502625 0.18335 -0 1 11 0 0.0632324 0.235352 -0 1 12 0 0.0787964 0.296387 -0 1 13 0 0.0965576 0.365723 -0 1 14 0 0.116333 0.442139 -0 1 15 0 0.137573 0.523926 -0 1 16 0 0.159546 0.608398 -0 1 17 0 0.180786 0.689941 -0 1 18 0 0.200317 0.764648 -0 1 19 0 0.217529 0.830566 -0 1 20 0 0.227051 0.867188 -0 1 21 0 0.228882 0.874512 -0 1 22 0 0.230957 0.881836 -0 1 23 0 0.23291 0.889648 -0 1 24 0 0.234985 0.897461 -0 1 25 0 0.237183 0.90625 -0 1 26 0 0.239624 0.915527 -0 1 27 0 0.242432 0.925781 -0 1 28 0 0.245483 0.937988 -0 1 29 0 0.248779 0.950684 -0 1 30 0 0.252197 0.963379 -0 1 31 0 0.255859 0.977051 -0 2 0 0.00665283 0.0129242 0.00886536 -0 2 1 0.00639725 0.0142593 0.011795 -0 2 2 0.0045166 0.0171051 0.0172424 -0 2 3 0 0.0211487 0.0261993 -0 2 4 0 0.025589 0.0391541 -0 2 5 0 0.0283966 0.0536194 -0 2 6 0 0.0302734 0.0693359 -0 2 7 0 0.0325623 0.0880737 -0 2 8 0 0.0363464 0.111938 -0 2 9 0 0.04245 0.142822 -0 2 10 0 0.0516052 0.18335 -0 2 11 0 0.064209 0.235352 -0 2 12 0 0.0794678 0.296387 -0 2 13 0 0.0971069 0.365723 -0 2 14 0 0.116699 0.442139 -0 2 15 0 0.137817 0.523926 -0 2 16 0 0.15979 0.608398 -0 2 17 0 0.180908 0.689941 -0 2 18 0 0.200439 0.764648 -0 2 19 0 0.217651 0.830566 -0 2 20 0 0.227173 0.867188 -0 2 21 0 0.229004 0.874512 -0 2 22 0 0.230957 0.881836 -0 2 23 0 0.23291 0.889648 -0 2 24 0 0.234985 0.897461 -0 2 25 0 0.237183 0.90625 -0 2 26 0 0.239624 0.915527 -0 2 27 0 0.242432 0.925781 -0 2 28 0 0.245483 0.937988 -0 2 29 0 0.248779 0.950684 -0 2 30 0 0.252197 0.963379 -0 2 31 0 0.255859 0.977051 -0 3 0 0 0.0228119 0.0123901 -0 3 1 0 0.023056 0.0152893 -0 3 2 0 0.024231 0.0197449 -0 3 3 0 0.0270081 0.0272675 -0 3 4 0 0.0311279 0.0392151 -0 3 5 0 0.0339661 0.0534668 -0 3 6 0 0.035614 0.0692749 -0 3 7 0 0.0372925 0.0880737 -0 3 8 0 0.0402832 0.111938 -0 3 9 0 0.0455322 0.142822 -0 3 10 0 0.0539551 0.18335 -0 3 11 0 0.065979 0.235352 -0 3 12 0 0.0808105 0.296387 -0 3 13 0 0.0980835 0.365723 -0 3 14 0 0.117432 0.442139 -0 3 15 0 0.138306 0.523926 -0 3 16 0 0.160156 0.608398 -0 3 17 0 0.181274 0.689941 -0 3 18 0 0.200684 0.764648 -0 3 19 0 0.217896 0.830566 -0 3 20 0 0.227295 0.867188 -0 3 21 0 0.229126 0.874512 -0 3 22 0 0.231079 0.881836 -0 3 23 0 0.233032 0.889648 -0 3 24 0 0.234985 0.897461 -0 3 25 0 0.237305 0.90625 -0 3 26 0 0.239746 0.915527 -0 3 27 0 0.242432 0.925781 -0 3 28 0 0.245483 0.937988 -0 3 29 0 0.248779 0.950684 -0 3 30 0 0.252197 0.963379 -0 3 31 0 0.255859 0.977051 -0 4 0 0 0.0359192 0.0146942 -0 4 1 0 0.0357361 0.0183411 -0 4 2 0 0.0358887 0.0230255 -0 4 3 0 0.0369873 0.0297241 -0 4 4 0 0.0393677 0.0397949 -0 4 5 0 0.0417786 0.0533447 -0 4 6 0 0.0431824 0.0691528 -0 4 7 0 0.0443115 0.0880127 -0 4 8 0 0.0464172 0.111938 -0 4 9 0 0.0505981 0.142822 -0 4 10 0 0.0580139 0.183228 -0 4 11 0 0.0691528 0.235229 -0 4 12 0 0.0831909 0.296387 -0 4 13 0 0.0998535 0.365723 -0 4 14 0 0.118774 0.442139 -0 4 15 0 0.139282 0.523926 -0 4 16 0 0.160889 0.608398 -0 4 17 0 0.181763 0.689941 -0 4 18 0 0.201172 0.764648 -0 4 19 0 0.21814 0.830566 -0 4 20 0 0.227661 0.867188 -0 4 21 0 0.22937 0.874512 -0 4 22 0 0.231201 0.881836 -0 4 23 0 0.233154 0.889648 -0 4 24 0 0.235229 0.897461 -0 4 25 0 0.237427 0.90625 -0 4 26 0 0.239868 0.915527 -0 4 27 0 0.242554 0.925781 -0 4 28 0 0.245605 0.937988 -0 4 29 0 0.248901 0.950684 -0 4 30 0 0.252197 0.963867 -0 4 31 0 0.255859 0.977051 -0 5 0 0 0.0509949 0.014122 -0 5 1 0 0.0509033 0.019104 -0 5 2 0 0.0508423 0.0247345 -0 5 3 0 0.0509033 0.0316772 -0 5 4 0 0.0514832 0.0408325 -0 5 5 0 0.0526733 0.0533142 -0 5 6 0 0.0536804 0.0689087 -0 5 7 0 0.0542908 0.0878906 -0 5 8 0 0.055542 0.111877 -0 5 9 0 0.0585938 0.1427 -0 5 10 0 0.0647583 0.183228 -0 5 11 0 0.074646 0.235229 -0 5 12 0 0.0875244 0.296387 -0 5 13 0 0.103149 0.365723 -0 5 14 0 0.121277 0.442139 -0 5 15 0 0.141235 0.523926 -0 5 16 0 0.162354 0.608398 -0 5 17 0 0.182861 0.689941 -0 5 18 0 0.202026 0.764648 -0 5 19 0 0.218872 0.830566 -0 5 20 0 0.228149 0.867188 -0 5 21 0 0.229736 0.874512 -0 5 22 0 0.231567 0.881836 -0 5 23 0 0.233521 0.889648 -0 5 24 0 0.235474 0.897461 -0 5 25 0 0.237549 0.90625 -0 5 26 0 0.23999 0.915527 -0 5 27 0 0.242676 0.92627 -0 5 28 0 0.245728 0.937988 -0 5 29 0 0.249023 0.950684 -0 5 30 0 0.252441 0.963867 -0 5 31 0 0.255859 0.977051 -0 6 0 0 0.0668335 0.00483322 -0 6 1 0 0.0668335 0.0158691 -0 6 2 0 0.0668335 0.0232544 -0 6 3 0 0.0668945 0.0312042 -0 6 4 0 0.0669556 0.0408325 -0 6 5 0 0.0672607 0.0530701 -0 6 6 0 0.0675659 0.0684204 -0 6 7 0 0.0678101 0.0875854 -0 6 8 0 0.0682983 0.111694 -0 6 9 0 0.0702515 0.142578 -0 6 10 0 0.0751953 0.183105 -0 6 11 0 0.0836792 0.235107 -0 6 12 0 0.0949707 0.296387 -0 6 13 0 0.10907 0.365723 -0 6 14 0 0.125854 0.442139 -0 6 15 0 0.144653 0.523926 -0 6 16 0 0.164917 0.608398 -0 6 17 0 0.184937 0.689941 -0 6 18 0 0.203613 0.764648 -0 6 19 0 0.220093 0.830566 -0 6 20 0 0.229126 0.867188 -0 6 21 0 0.230591 0.874512 -0 6 22 0 0.2323 0.882324 -0 6 23 0 0.234009 0.889648 -0 6 24 0 0.23584 0.897461 -0 6 25 0 0.238037 0.90625 -0 6 26 0 0.240356 0.915527 -0 6 27 0 0.243042 0.92627 -0 6 28 0 0.245972 0.937988 -0 6 29 0 0.249268 0.950684 -0 6 30 0 0.252686 0.963867 -0 6 31 0 0.256104 0.977051 -0 7 0 0 0.085144 0 -0 7 1 0 0.085144 0 -0 7 2 0 0.0852051 0.0171661 -0 7 3 0 0.0852661 0.0278015 -0 7 4 0 0.0853882 0.0386353 -0 7 5 0 0.0855713 0.0515137 -0 7 6 0 0.0857544 0.0671997 -0 7 7 0 0.0857544 0.086853 -0 7 8 0 0.0858154 0.111328 -0 7 9 0 0.086792 0.142334 -0 7 10 0 0.0905762 0.182739 -0 7 11 0 0.0977173 0.234863 -0 7 12 0 0.107178 0.296143 -0 7 13 0 0.119263 0.365723 -0 7 14 0 0.134033 0.442139 -0 7 15 0 0.151123 0.523926 -0 7 16 0 0.169922 0.608398 -0 7 17 0 0.188843 0.689941 -0 7 18 0 0.206665 0.764648 -0 7 19 0 0.222534 0.830566 -0 7 20 0 0.231201 0.867676 -0 7 21 0 0.232178 0.874512 -0 7 22 0 0.233521 0.882324 -0 7 23 0 0.235107 0.889648 -0 7 24 0 0.236816 0.897461 -0 7 25 0 0.23877 0.90625 -0 7 26 0 0.240967 0.915527 -0 7 27 0 0.24353 0.92627 -0 7 28 0 0.24646 0.937988 -0 7 29 0 0.249634 0.950684 -0 7 30 0 0.25293 0.963867 -0 7 31 0 0.256348 0.977051 -0 8 0 0 0.108215 0 -0 8 1 0 0.108215 0 -0 8 2 0 0.108276 0 -0 8 3 0 0.108337 0.0182037 -0 8 4 0 0.108459 0.0336304 -0 8 5 0 0.108643 0.0481567 -0 8 6 0 0.108826 0.0647583 -0 8 7 0 0.109009 0.085083 -0 8 8 0 0.109009 0.110352 -0 8 9 0 0.109497 0.141968 -0 8 10 0 0.112366 0.182373 -0 8 11 0 0.118469 0.234497 -0 8 12 0 0.126221 0.296143 -0 8 13 0 0.135864 0.365479 -0 8 14 0 0.148071 0.442139 -0 8 15 0 0.162598 0.523926 -0 8 16 0 0.179077 0.608398 -0 8 17 0 0.196045 0.689941 -0 8 18 0 0.212402 0.765137 -0 8 19 0 0.227295 0.831055 -0 8 20 0 0.234985 0.867676 -0 8 21 0 0.235229 0.875 -0 8 22 0 0.235962 0.882324 -0 8 23 0 0.237183 0.890137 -0 8 24 0 0.238647 0.897949 -0 8 25 0 0.240356 0.90625 -0 8 26 0 0.24231 0.915527 -0 8 27 0 0.244751 0.92627 -0 8 28 0 0.247437 0.937988 -0 8 29 0 0.250488 0.950684 -0 8 30 0 0.253662 0.963867 -0 8 31 0 0.25708 0.977051 -0 9 0 0 0.137573 0 -0 9 1 0 0.137573 0 -0 9 2 0 0.137573 0 -0 9 3 0 0.137573 0 -0 9 4 0 0.137695 0.0197449 -0 9 5 0 0.137817 0.041626 -0 9 6 0 0.137939 0.0604248 -0 9 7 0 0.138184 0.0819702 -0 9 8 0 0.13855 0.108337 -0 9 9 0 0.13916 0.140991 -0 9 10 0 0.141602 0.181763 -0 9 11 0 0.147095 0.233887 -0 9 12 0 0.153442 0.295654 -0 9 13 0 0.161011 0.365234 -0 9 14 0 0.170166 0.442139 -0 9 15 0 0.181519 0.523926 -0 9 16 0 0.194824 0.608398 -0 9 17 0 0.208862 0.689941 -0 9 18 0 0.2229 0.765137 -0 9 19 0 0.23584 0.831055 -0 9 20 0 0.241943 0.868164 -0 9 21 0 0.240845 0.875 -0 9 22 0 0.240723 0.882812 -0 9 23 0 0.241089 0.890137 -0 9 24 0 0.241943 0.897949 -0 9 25 0 0.243164 0.906738 -0 9 26 0 0.244873 0.916016 -0 9 27 0 0.246826 0.92627 -0 9 28 0 0.249268 0.937988 -0 9 29 0 0.251953 0.950684 -0 9 30 0 0.255127 0.963867 -0 9 31 0 0.258301 0.977539 -0 10 0 0 0.175293 0 -0 10 1 0 0.175293 0 -0 10 2 0 0.175415 0 -0 10 3 0 0.175415 0 -0 10 4 0 0.175415 0 -0 10 5 0 0.175537 0.0245056 -0 10 6 0 0.175537 0.0531616 -0 10 7 0 0.175537 0.0776978 -0 10 8 0 0.175903 0.105713 -0 10 9 0 0.176636 0.139648 -0 10 10 0 0.178833 0.181152 -0 10 11 0 0.183716 0.233154 -0 10 12 0 0.189209 0.294922 -0 10 13 0 0.195068 0.36499 -0 10 14 0 0.20166 0.441895 -0 10 15 0 0.209473 0.523926 -0 10 16 0 0.219116 0.608887 -0 10 17 0 0.229492 0.69043 -0 10 18 0 0.240112 0.765137 -0 10 19 0 0.250244 0.831543 -0 10 20 0 0.25415 0.869141 -0 10 21 0 0.250732 0.875977 -0 10 22 0 0.248779 0.883301 -0 10 23 0 0.248047 0.891113 -0 10 24 0 0.247925 0.898438 -0 10 25 0 0.248291 0.906738 -0 10 26 0 0.249268 0.916504 -0 10 27 0 0.250732 0.926758 -0 10 28 0 0.252686 0.938477 -0 10 29 0 0.254883 0.951172 -0 10 30 0 0.257568 0.964355 -0 10 31 0 0.260254 0.977539 -0 11 0 0 0.224365 0 -0 11 1 0 0.224365 0 -0 11 2 0 0.224365 0 -0 11 3 0 0.224487 0 -0 11 4 0 0.224487 0 -0 11 5 0 0.224487 0 -0 11 6 0 0.224609 0.0341797 -0 11 7 0 0.224487 0.0703735 -0 11 8 0 0.224365 0.102356 -0 11 9 0 0.224609 0.138428 -0 11 10 0 0.226196 0.18103 -0 11 11 0 0.229492 0.232422 -0 11 12 0 0.234009 0.293945 -0 11 13 0 0.238525 0.364258 -0 11 14 0 0.243042 0.44165 -0 11 15 0 0.247925 0.523926 -0 11 16 0 0.253662 0.608887 -0 11 17 0 0.259766 0.690918 -0 11 18 0 0.266357 0.765625 -0 11 19 0 0.272705 0.832031 -0 11 20 0 0.273438 0.870605 -0 11 21 0 0.266602 0.877441 -0 11 22 0 0.262207 0.884277 -0 11 23 0 0.259521 0.89209 -0 11 24 0 0.257812 0.899414 -0 11 25 0 0.25708 0.907715 -0 11 26 0 0.256836 0.916992 -0 11 27 0 0.25708 0.927246 -0 11 28 0 0.258301 0.938965 -0 11 29 0 0.259766 0.95166 -0 11 30 0 0.261719 0.964355 -0 11 31 0 0.263916 0.978027 -0 12 0 0 0.283691 0 -0 12 1 0 0.283936 0 -0 12 2 0 0.283936 0 -0 12 3 0 0.283936 0 -0 12 4 0 0.283936 0 -0 12 5 0 0.283936 0 -0 12 6 0 0.283936 0 -0 12 7 0 0.28418 0.050415 -0 12 8 0 0.28418 0.0944824 -0 12 9 0 0.28418 0.135132 -0 12 10 0 0.284668 0.17981 -0 12 11 0 0.286133 0.231567 -0 12 12 0 0.289062 0.292725 -0 12 13 0 0.292236 0.363037 -0 12 14 0 0.295166 0.440674 -0 12 15 0 0.297363 0.523438 -0 12 16 0 0.299561 0.608887 -0 12 17 0 0.301514 0.691406 -0 12 18 0 0.303467 0.766602 -0 12 19 0 0.305664 0.83252 -0 12 20 0 0.30249 0.873047 -0 12 21 0 0.291016 0.879395 -0 12 22 0 0.282959 0.88623 -0 12 23 0 0.277344 0.893555 -0 12 24 0 0.273682 0.900879 -0 12 25 0 0.270752 0.90918 -0 12 26 0 0.268799 0.918457 -0 12 27 0 0.267822 0.928223 -0 12 28 0 0.267578 0.939941 -0 12 29 0 0.267822 0.952148 -0 12 30 0 0.268799 0.965332 -0 12 31 0 0.27002 0.978516 -0 13 0 0 0.351318 0 -0 13 1 0 0.351318 0 -0 13 2 0 0.351318 0 -0 13 3 0 0.351562 0 -0 13 4 0 0.351562 0 -0 13 5 0 0.351562 0 -0 13 6 0 0.351562 0 -0 13 7 0 0.351807 0 -0 13 8 0 0.351807 0.0742188 -0 13 9 0 0.352051 0.125854 -0 13 10 0 0.352295 0.174805 -0 13 11 0 0.353027 0.228638 -0 13 12 0 0.354248 0.290527 -0 13 13 0 0.356201 0.36084 -0 13 14 0 0.357666 0.439209 -0 13 15 0 0.35791 0.522461 -0 13 16 0 0.357178 0.608887 -0 13 17 0 0.355225 0.691895 -0 13 18 0 0.352539 0.767578 -0 13 19 0 0.350098 0.833496 -0 13 20 0 0.342773 0.876953 -0 13 21 0 0.325439 0.882812 -0 13 22 0 0.312988 0.889648 -0 13 23 0 0.303711 0.896484 -0 13 24 0 0.297119 0.90332 -0 13 25 0 0.291504 0.911621 -0 13 26 0 0.287109 0.92041 -0 13 27 0 0.283936 0.930176 -0 13 28 0 0.281738 0.941406 -0 13 29 0 0.280273 0.953613 -0 13 30 0 0.279785 0.966309 -0 13 31 0 0.279541 0.979492 -0 14 0 0 0.426758 0 -0 14 1 0 0.426758 0 -0 14 2 0 0.426758 0 -0 14 3 0 0.426758 0 -0 14 4 0 0.426758 0 -0 14 5 0 0.426758 0 -0 14 6 0 0.426758 0 -0 14 7 0 0.427002 0 -0 14 8 0 0.427002 0 -0 14 9 0 0.427246 0.10553 -0 14 10 0 0.427734 0.163818 -0 14 11 0 0.428467 0.221802 -0 14 12 0 0.429199 0.285645 -0 14 13 0 0.430176 0.356689 -0 14 14 0 0.43042 0.435791 -0 14 15 0 0.429199 0.520508 -0 14 16 0 0.426025 0.60791 -0 14 17 0 0.420654 0.691895 -0 14 18 0 0.413818 0.768066 -0 14 19 0 0.406738 0.834961 -0 14 20 0 0.395752 0.882324 -0 14 21 0 0.371826 0.888184 -0 14 22 0 0.35376 0.894531 -0 14 23 0 0.340088 0.900879 -0 14 24 0 0.329834 0.907715 -0 14 25 0 0.321045 0.915039 -0 14 26 0 0.313477 0.923828 -0 14 27 0 0.307373 0.933105 -0 14 28 0 0.30249 0.944336 -0 14 29 0 0.298828 0.956055 -0 14 30 0 0.295898 0.968262 -0 14 31 0 0.293945 0.981445 -0 15 0 0 0.507324 0 -0 15 1 0 0.507324 0 -0 15 2 0 0.507324 0 -0 15 3 0 0.507812 0 -0 15 4 0 0.507812 0 -0 15 5 0 0.507812 0 -0 15 6 0 0.507812 0 -0 15 7 0 0.507812 0 -0 15 8 0 0.507812 0 -0 15 9 0 0.508301 0.0460205 -0 15 10 0 0.508789 0.143066 -0 15 11 0 0.509277 0.208618 -0 15 12 0 0.510254 0.276123 -0 15 13 0 0.51123 0.349365 -0 15 14 0 0.51123 0.429688 -0 15 15 0 0.509277 0.516113 -0 15 16 0 0.504883 0.60498 -0 15 17 0 0.496826 0.690918 -0 15 18 0 0.486328 0.768555 -0 15 19 0 0.474854 0.836426 -0 15 20 0 0.461182 0.88916 -0 15 21 0 0.43042 0.895996 -0 15 22 0 0.40625 0.902344 -0 15 23 0 0.387451 0.908203 -0 15 24 0 0.372803 0.914551 -0 15 25 0 0.359863 0.921387 -0 15 26 0 0.348633 0.929199 -0 15 27 0 0.339111 0.937988 -0 15 28 0 0.331055 0.948242 -0 15 29 0 0.324219 0.959473 -0 15 30 0 0.318604 0.97168 -0 15 31 0 0.314209 0.983887 -0 16 0 0 0.592773 0 -0 16 1 0 0.592773 0 -0 16 2 0 0.592773 0 -0 16 3 0 0.592773 0 -0 16 4 0 0.592773 0 -0 16 5 0 0.592773 0 -0 16 6 0 0.592773 0 -0 16 7 0 0.592773 0 -0 16 8 0 0.592773 0 -0 16 9 0 0.592773 0 -0 16 10 0 0.593262 0.101074 -0 16 11 0 0.594238 0.18689 -0 16 12 0 0.595703 0.260498 -0 16 13 0 0.597168 0.33667 -0 16 14 0 0.597656 0.419189 -0 16 15 0 0.596191 0.507324 -0 16 16 0 0.591309 0.598633 -0 16 17 0 0.582031 0.687012 -0 16 18 0 0.568848 0.76709 -0 16 19 0 0.553711 0.836426 -0 16 20 0 0.537598 0.893555 -0 16 21 0 0.501465 0.905762 -0 16 22 0 0.470947 0.913086 -0 16 23 0 0.446777 0.918945 -0 16 24 0 0.427246 0.924805 -0 16 25 0 0.409668 0.930664 -0 16 26 0 0.394043 0.9375 -0 16 27 0 0.380127 0.945312 -0 16 28 0 0.368164 0.955078 -0 16 29 0 0.357666 0.965332 -0 16 30 0 0.348877 0.976562 -0 16 31 0 0.341064 0.987793 -0 17 0 0 0.67627 0 -0 17 1 0 0.67627 0 -0 17 2 0 0.67627 0 -0 17 3 0 0.67627 0 -0 17 4 0 0.67627 0 -0 17 5 0 0.67627 0 -0 17 6 0 0.67627 0 -0 17 7 0 0.67627 0 -0 17 8 0 0.67627 0 -0 17 9 0 0.676758 0 -0 17 10 0 0.676758 0 -0 17 11 0 0.677734 0.151611 -0 17 12 0 0.679688 0.237915 -0 17 13 0 0.681641 0.318848 -0 17 14 0 0.683105 0.403564 -0 17 15 0 0.683105 0.493652 -0 17 16 0 0.678711 0.587402 -0 17 17 0 0.669922 0.678223 -0 17 18 0 0.655762 0.761719 -0 17 19 0 0.638672 0.833984 -0 17 20 0 0.619141 0.893066 -0 17 21 0 0.582031 0.916016 -0 17 22 0 0.546387 0.926758 -0 17 23 0 0.516602 0.933594 -0 17 24 0 0.491699 0.938965 -0 17 25 0 0.468994 0.944336 -0 17 26 0 0.448486 0.950195 -0 17 27 0 0.429688 0.957031 -0 17 28 0 0.41333 0.964844 -0 17 29 0 0.398682 0.973633 -0 17 30 0 0.385986 0.983398 -0 17 31 0 0.374512 0.994141 -0 18 0 0 0.754395 0 -0 18 1 0 0.754395 0 -0 18 2 0 0.754395 0 -0 18 3 0 0.754395 0 -0 18 4 0 0.754395 0 -0 18 5 0 0.754395 0 -0 18 6 0 0.754395 0 -0 18 7 0 0.754395 0 -0 18 8 0 0.754395 0 -0 18 9 0 0.754883 0 -0 18 10 0 0.754883 0 -0 18 11 0 0.755371 0.0774536 -0 18 12 0 0.757324 0.206421 -0 18 13 0 0.759766 0.294922 -0 18 14 0 0.762207 0.382812 -0 18 15 0 0.763672 0.474365 -0 18 16 0 0.762207 0.570312 -0 18 17 0 0.754883 0.664551 -0 18 18 0 0.742188 0.751465 -0 18 19 0 0.724121 0.827148 -0 18 20 0 0.702637 0.889648 -0 18 21 0 0.66748 0.924316 -0 18 22 0 0.629395 0.941406 -0 18 23 0 0.594727 0.951172 -0 18 24 0 0.564941 0.957031 -0 18 25 0 0.537109 0.962402 -0 18 26 0 0.510742 0.966797 -0 18 27 0 0.487061 0.972168 -0 18 28 0 0.465576 0.978516 -0 18 29 0 0.446289 0.985352 -0 18 30 0 0.428955 0.993652 -0 18 31 0 0.413574 1 -0 19 0 0 0.824707 0 -0 19 1 0 0.824707 0 -0 19 2 0 0.824707 0 -0 19 3 0 0.824707 0 -0 19 4 0 0.824707 0 -0 19 5 0 0.824707 0 -0 19 6 0 0.824707 0 -0 19 7 0 0.824707 0 -0 19 8 0 0.824707 0 -0 19 9 0 0.824707 0 -0 19 10 0 0.824707 0 -0 19 11 0 0.825195 0 -0 19 12 0 0.82666 0.162231 -0 19 13 0 0.82959 0.266113 -0 19 14 0 0.83252 0.358154 -0 19 15 0 0.835449 0.451416 -0 19 16 0 0.835938 0.54834 -0 19 17 0 0.832031 0.64502 -0 19 18 0 0.821777 0.73584 -0 19 19 0 0.805176 0.81543 -0 19 20 0 0.783691 0.881348 -0 19 21 0 0.751953 0.927246 -0 19 22 0 0.714355 0.953613 -0 19 23 0 0.677246 0.968262 -0 19 24 0 0.643555 0.977051 -0 19 25 0 0.610352 0.982422 -0 19 26 0 0.579102 0.986816 -0 19 27 0 0.549805 0.990723 -0 19 28 0 0.522949 0.995117 -0 19 29 0 0.498535 1 -0 19 30 0 0.476562 1 -0 19 31 0 0.456787 1 -0 20 0 0 0.885254 0 -0 20 1 0 0.885254 0 -0 20 2 0 0.885254 0 -0 20 3 0 0.885254 0 -0 20 4 0 0.885254 0 -0 20 5 0 0.885254 0 -0 20 6 0 0.885254 0 -0 20 7 0 0.885254 0 -0 20 8 0 0.885254 0 -0 20 9 0 0.885254 0 -0 20 10 0 0.885254 0 -0 20 11 0 0.885742 0 -0 20 12 0 0.88623 0.0790405 -0 20 13 0 0.88916 0.231934 -0 20 14 0 0.893066 0.330811 -0 20 15 0 0.896973 0.42627 -0 20 16 0 0.899414 0.524414 -0 20 17 0 0.898438 0.62207 -0 20 18 0 0.891113 0.715332 -0 20 19 0 0.876953 0.797852 -0 20 20 0 0.856934 0.867676 -0 20 21 0 0.830078 0.922852 -0 20 22 0 0.79541 0.959961 -0 20 23 0 0.758301 0.981445 -0 20 24 0 0.722656 0.994141 -0 20 25 0 0.686035 1 -0 20 26 0 0.649902 1 -0 20 27 0 0.615723 1 -0 20 28 0 0.583496 1 -0 20 29 0 0.553711 1 -0 20 30 0 0.526855 1 -0 20 31 0 0.502441 1 -0 21 0 0 0.936523 0 -0 21 1 0 0.936523 0 -0 21 2 0 0.936523 0 -0 21 3 0 0.936523 0 -0 21 4 0 0.936523 0 -0 21 5 0 0.936523 0 -0 21 6 0 0.936523 0 -0 21 7 0 0.936523 0 -0 21 8 0 0.936523 0 -0 21 9 0 0.936523 0 -0 21 10 0 0.937012 0 -0 21 11 0 0.937012 0 -0 21 12 0 0.937012 0 -0 21 13 0 0.939453 0.189331 -0 21 14 0 0.943848 0.300537 -0 21 15 0 0.94873 0.398682 -0 21 16 0 0.952637 0.497314 -0 21 17 0 0.954102 0.595703 -0 21 18 0 0.950195 0.69043 -0 21 19 0 0.939453 0.775879 -0 21 20 0 0.922363 0.849121 -0 21 21 0 0.899414 0.910645 -0 21 22 0 0.869629 0.957031 -0 21 23 0 0.835449 0.987305 -0 21 24 0 0.799805 1 -0 21 25 0 0.76123 1 -0 21 26 0 0.722168 1 -0 21 27 0 0.683594 1 -0 21 28 0 0.646484 1 -0 21 29 0 0.611816 1 -0 21 30 0 0.580078 1 -0 21 31 0 0.550781 1 -0 22 0 0 0.979492 0 -0 22 1 0 0.979492 0 -0 22 2 0 0.979492 0 -0 22 3 0 0.979492 0 -0 22 4 0 0.979492 0 -0 22 5 0 0.979492 0 -0 22 6 0 0.979492 0 -0 22 7 0 0.979492 0 -0 22 8 0 0.979492 0 -0 22 9 0 0.979492 0 -0 22 10 0 0.979492 0 -0 22 11 0 0.979492 0 -0 22 12 0 0.97998 0 -0 22 13 0 0.981445 0.128296 -0 22 14 0 0.985352 0.267334 -0 22 15 0 0.990723 0.369873 -0 22 16 0 0.996094 0.469238 -0 22 17 0 0.999512 0.567871 -0 22 18 0 0.999023 0.662598 -0 22 19 0 0.991699 0.750488 -0 22 20 0 0.978027 0.82666 -0 22 21 0 0.958008 0.891602 -0 22 22 0 0.933105 0.944824 -0 22 23 0 0.90332 0.983398 -0 22 24 0 0.870117 1 -0 22 25 0 0.83252 1 -0 22 26 0 0.791992 1 -0 22 27 0 0.750488 1 -0 22 28 0 0.709961 1 -0 22 29 0 0.670898 1 -0 22 30 0 0.634277 1 -0 22 31 0 0.600586 1 -0 23 0 0 1 0 -0 23 1 0 1 0 -0 23 2 0 1 0 -0 23 3 0 1 0 -0 23 4 0 1 0 -0 23 5 0 1 0 -0 23 6 0 1 0 -0 23 7 0 1 0 -0 23 8 0 1 0 -0 23 9 0 1 0 -0 23 10 0 1 0 -0 23 11 0 1 0 -0 23 12 0 1 0 -0 23 13 0 1 0 -0 23 14 0 1 0.231689 -0 23 15 0 1 0.341064 -0 23 16 0 1 0.44165 -0 23 17 0 1 0.539551 -0 23 18 0 1 0.634766 -0 23 19 0 1 0.723145 -0 23 20 0 1 0.80127 -0 23 21 0 1 0.869629 -0 23 22 0 0.984375 0.92627 -0 23 23 0 0.958984 0.970703 -0 23 24 0 0.929688 1 -0 23 25 0 0.89502 1 -0 23 26 0 0.85498 1 -0 23 27 0 0.8125 1 -0 23 28 0 0.769531 1 -0 23 29 0 0.727539 1 -0 23 30 0 0.687012 1 -0 23 31 0 0.648926 1 -0 24 0 0 1 0 -0 24 1 0 1 0 -0 24 2 0 1 0 -0 24 3 0 1 0 -0 24 4 0 1 0 -0 24 5 0 1 0 -0 24 6 0 1 0 -0 24 7 0 1 0 -0 24 8 0 1 0 -0 24 9 0 1 0 -0 24 10 0 1 0 -0 24 11 0 1 0 -0 24 12 0 1 0 -0 24 13 0 1 0 -0 24 14 0 1 0.191284 -0 24 15 0 1 0.312012 -0 24 16 0 1 0.414307 -0 24 17 0 1 0.512207 -0 24 18 0 1 0.606934 -0 24 19 0 1 0.695312 -0 24 20 0 1 0.774414 -0 24 21 0 1 0.845215 -0 24 22 0 1 0.904785 -0 24 23 0 1 0.953125 -0 24 24 0 0.979004 0.991699 -0 24 25 0 0.948242 1 -0 24 26 0 0.911133 1 -0 24 27 0 0.869141 1 -0 24 28 0 0.825195 1 -0 24 29 0 0.780762 1 -0 24 30 0 0.737305 1 -0 24 31 0 0.695801 1 -0 25 0 0 1 0 -0 25 1 0 1 0 -0 25 2 0 1 0 -0 25 3 0 1 0 -0 25 4 0 1 0 -0 25 5 0 1 0 -0 25 6 0 1 0 -0 25 7 0 1 0 -0 25 8 0 1 0 -0 25 9 0 1 0 -0 25 10 0 1 0 -0 25 11 0 1 0 -0 25 12 0 1 0 -0 25 13 0 1 0 -0 25 14 0 1 0.132568 -0 25 15 0 1 0.279541 -0 25 16 0 1 0.38501 -0 25 17 0 1 0.482666 -0 25 18 0 1 0.576172 -0 25 19 0 1 0.664062 -0 25 20 0 1 0.744141 -0 25 21 0 1 0.816406 -0 25 22 0 1 0.878906 -0 25 23 0 1 0.930176 -0 25 24 0 1 0.972656 -0 25 25 0 0.99707 1 -0 25 26 0 0.963379 1 -0 25 27 0 0.924316 1 -0 25 28 0 0.880371 1 -0 25 29 0 0.834961 1 -0 25 30 0 0.789551 1 -0 25 31 0 0.745117 1 -0 26 0 0 1 0 -0 26 1 0 1 0 -0 26 2 0 1 0 -0 26 3 0 1 0 -0 26 4 0 1 0 -0 26 5 0 1 0 -0 26 6 0 1 0 -0 26 7 0 1 0 -0 26 8 0 1 0 -0 26 9 0 1 0 -0 26 10 0 1 0 -0 26 11 0 1 0 -0 26 12 0 1 0 -0 26 13 0 1 0 -0 26 14 0 1 0 -0 26 15 0 1 0.241943 -0 26 16 0 1 0.353027 -0 26 17 0 1 0.451172 -0 26 18 0 1 0.543457 -0 26 19 0 1 0.630859 -0 26 20 0 1 0.710938 -0 26 21 0 1 0.783691 -0 26 22 0 1 0.848633 -0 26 23 0 1 0.902832 -0 26 24 0 1 0.948242 -0 26 25 0 1 0.989258 -0 26 26 0 1 1 -0 26 27 0 0.976074 1 -0 26 28 0 0.93457 1 -0 26 29 0 0.889648 1 -0 26 30 0 0.842773 1 -0 26 31 0 0.796387 1 -0 27 0 0 1 0 -0 27 1 0 1 0 -0 27 2 0 1 0 -0 27 3 0 1 0 -0 27 4 0 1 0 -0 27 5 0 1 0 -0 27 6 0 1 0 -0 27 7 0 1 0 -0 27 8 0 1 0 -0 27 9 0 1 0 -0 27 10 0 1 0 -0 27 11 0 1 0 -0 27 12 0 1 0 -0 27 13 0 1 0 -0 27 14 0 1 0 -0 27 15 0 1 0.195557 -0 27 16 0 1 0.318604 -0 27 17 0 1 0.417725 -0 27 18 0 1 0.509277 -0 27 19 0 1 0.595215 -0 27 20 0 1 0.674805 -0 27 21 0 1 0.748047 -0 27 22 0 1 0.813965 -0 27 23 0 1 0.870605 -0 27 24 0 1 0.918457 -0 27 25 0 1 0.962891 -0 27 26 0 1 1 -0 27 27 0 1 1 -0 27 28 0 0.98584 1 -0 27 29 0 0.941895 1 -0 27 30 0 0.895508 1 -0 27 31 0 0.848145 1 -0 28 0 0 1 0 -0 28 1 0 1 0 -0 28 2 0 1 0 -0 28 3 0 1 0 -0 28 4 0 1 0 -0 28 5 0 1 0 -0 28 6 0 1 0 -0 28 7 0 1 0 -0 28 8 0 1 0 -0 28 9 0 1 0 -0 28 10 0 1 0 -0 28 11 0 1 0 -0 28 12 0 1 0 -0 28 13 0 1 0 -0 28 14 0 1 0 -0 28 15 0 1 0.126831 -0 28 16 0 1 0.280518 -0 28 17 0 1 0.382568 -0 28 18 0 1 0.473633 -0 28 19 0 1 0.558105 -0 28 20 0 1 0.63623 -0 28 21 0 1 0.709473 -0 28 22 0 1 0.775879 -0 28 23 0 1 0.833496 -0 28 24 0 1 0.883789 -0 28 25 0 1 0.931152 -0 28 26 0 1 0.974609 -0 28 27 0 1 1 -0 28 28 0 1 1 -0 28 29 0 0.991699 1 -0 28 30 0 0.947266 1 -0 28 31 0 0.899902 1 -0 29 0 0 1 0 -0 29 1 0 1 0 -0 29 2 0 1 0 -0 29 3 0 1 0 -0 29 4 0 1 0 -0 29 5 0 1 0 -0 29 6 0 1 0 -0 29 7 0 1 0 -0 29 8 0 1 0 -0 29 9 0 1 0 -0 29 10 0 1 0 -0 29 11 0 1 0 -0 29 12 0 1 0 -0 29 13 0 1 0 -0 29 14 0 1 0 -0 29 15 0 1 0 -0 29 16 0 1 0.236572 -0 29 17 0 1 0.345215 -0 29 18 0 1 0.436279 -0 29 19 0 1 0.519531 -0 29 20 0 1 0.596191 -0 29 21 0 1 0.667969 -0 29 22 0 1 0.733887 -0 29 23 0 1 0.79248 -0 29 24 0 1 0.84375 -0 29 25 0 1 0.893555 -0 29 26 0 1 0.94043 -0 29 27 0 1 0.98291 -0 29 28 0 1 1 -0 29 29 0 1 1 -0 29 30 0 0.996582 1 -0 29 31 0 0.951172 1 -0 30 0 0 1 0 -0 30 1 0 1 0 -0 30 2 0 1 0 -0 30 3 0 1 0 -0 30 4 0 1 0 -0 30 5 0 1 0 -0 30 6 0 1 0 -0 30 7 0 1 0 -0 30 8 0 1 0 -0 30 9 0 1 0 -0 30 10 0 1 0 -0 30 11 0 1 0 -0 30 12 0 1 0 -0 30 13 0 1 0 -0 30 14 0 1 0 -0 30 15 0 1 0 -0 30 16 0 1 0.182007 -0 30 17 0 1 0.304688 -0 30 18 0 1 0.397217 -0 30 19 0 1 0.479248 -0 30 20 0 1 0.554199 -0 30 21 0 1 0.624512 -0 30 22 0 1 0.689453 -0 30 23 0 1 0.747559 -0 30 24 0 1 0.799805 -0 30 25 0 1 0.850586 -0 30 26 0 1 0.899902 -0 30 27 0 1 0.946289 -0 30 28 0 1 0.988281 -0 30 29 0 1 1 -0 30 30 0 1 1 -0 30 31 0 1 1 -0 31 0 0 1 0 -0 31 1 0 1 0 -0 31 2 0 1 0 -0 31 3 0 1 0 -0 31 4 0 1 0 -0 31 5 0 1 0 -0 31 6 0 1 0 -0 31 7 0 1 0 -0 31 8 0 1 0 -0 31 9 0 1 0 -0 31 10 0 1 0 -0 31 11 0 1 0 -0 31 12 0 1 0 -0 31 13 0 1 0 -0 31 14 0 1 0 -0 31 15 0 1 0 -0 31 16 0 1 0.0874634 -0 31 17 0 1 0.260742 -0 31 18 0 1 0.356934 -0 31 19 0 1 0.438232 -0 31 20 0 1 0.51123 -0 31 21 0 1 0.57959 -0 31 22 0 1 0.643066 -0 31 23 0 1 0.700684 -0 31 24 0 1 0.752441 -0 31 25 0 1 0.804199 -0 31 26 0 1 0.855469 -0 31 27 0 1 0.904785 -0 31 28 0 1 0.951172 -0 31 29 0 1 0.992676 -0 31 30 0 1 1 -0 31 31 0 1 1 -1 0 0 0.0115356 0.0089798 0.00888062 -1 0 1 0.00971222 0.00789642 0.00932312 -1 0 2 0.0130692 0.0113602 0.0161133 -1 0 3 0.0150833 0.0151596 0.026001 -1 0 4 0.0111313 0.0189667 0.0393372 -1 0 5 0 0.0217438 0.0537415 -1 0 6 0 0.024231 0.0693359 -1 0 7 0 0.0275269 0.0880737 -1 0 8 0 0.0324402 0.111938 -1 0 9 0 0.0395508 0.142822 -1 0 10 0 0.0494995 0.18335 -1 0 11 0 0.0626831 0.235352 -1 0 12 0 0.0783691 0.296387 -1 0 13 0 0.0963135 0.365723 -1 0 14 0 0.11615 0.442139 -1 0 15 0 0.137329 0.523926 -1 0 16 0 0.159424 0.608398 -1 0 17 0 0.180664 0.689941 -1 0 18 0 0.200317 0.764648 -1 0 19 0 0.217529 0.830566 -1 0 20 0 0.227051 0.867188 -1 0 21 0 0.228882 0.874512 -1 0 22 0 0.230835 0.881836 -1 0 23 0 0.23291 0.889648 -1 0 24 0 0.234863 0.897461 -1 0 25 0 0.237183 0.90625 -1 0 26 0 0.239624 0.915527 -1 0 27 0 0.242432 0.925781 -1 0 28 0 0.245483 0.937988 -1 0 29 0 0.248779 0.950684 -1 0 30 0 0.252197 0.963379 -1 0 31 0 0.255859 0.977051 -1 1 0 0.00896454 0.00865936 0.00724411 -1 1 1 0.0104752 0.0104752 0.0104752 -1 1 2 0.012764 0.0136795 0.0165405 -1 1 3 0.0140152 0.0176392 0.026001 -1 1 4 0.00753784 0.0217438 0.0392151 -1 1 5 0 0.0245209 0.0536804 -1 1 6 0 0.0267029 0.0693359 -1 1 7 0 0.029541 0.0880737 -1 1 8 0 0.0339661 0.111938 -1 1 9 0 0.0406494 0.142822 -1 1 10 0 0.050293 0.18335 -1 1 11 0 0.0632324 0.235352 -1 1 12 0 0.0787964 0.296387 -1 1 13 0 0.0965576 0.365723 -1 1 14 0 0.116333 0.442139 -1 1 15 0 0.137573 0.523926 -1 1 16 0 0.159546 0.608398 -1 1 17 0 0.180786 0.689941 -1 1 18 0 0.200317 0.764648 -1 1 19 0 0.217529 0.830566 -1 1 20 0 0.227051 0.867188 -1 1 21 0 0.228882 0.874512 -1 1 22 0 0.230957 0.881836 -1 1 23 0 0.23291 0.889648 -1 1 24 0 0.234985 0.897461 -1 1 25 0 0.237183 0.90625 -1 1 26 0 0.239624 0.915527 -1 1 27 0 0.242432 0.925781 -1 1 28 0 0.245483 0.937988 -1 1 29 0 0.248779 0.950684 -1 1 30 0 0.252197 0.963379 -1 1 31 0 0.255859 0.977051 -1 2 0 0.011322 0.0143585 0.00984955 -1 2 1 0.0115814 0.0153198 0.0126495 -1 2 2 0.0122299 0.0176239 0.0177155 -1 2 3 0.0118103 0.0213013 0.0262909 -1 2 4 0 0.0256348 0.039093 -1 2 5 0 0.0284729 0.0535889 -1 2 6 0 0.030365 0.0693359 -1 2 7 0 0.0326538 0.0880737 -1 2 8 0 0.036438 0.111938 -1 2 9 0 0.042511 0.142822 -1 2 10 0 0.0516663 0.18335 -1 2 11 0 0.06427 0.235352 -1 2 12 0 0.0795288 0.296387 -1 2 13 0 0.0971069 0.365723 -1 2 14 0 0.11676 0.442139 -1 2 15 0 0.137817 0.523926 -1 2 16 0 0.15979 0.608398 -1 2 17 0 0.180908 0.689941 -1 2 18 0 0.200439 0.764648 -1 2 19 0 0.217651 0.830566 -1 2 20 0 0.227173 0.867188 -1 2 21 0 0.229004 0.874512 -1 2 22 0 0.230957 0.881836 -1 2 23 0 0.23291 0.889648 -1 2 24 0 0.234985 0.897461 -1 2 25 0 0.237183 0.90625 -1 2 26 0 0.239624 0.915527 -1 2 27 0 0.242432 0.925781 -1 2 28 0 0.245483 0.937988 -1 2 29 0 0.248779 0.950684 -1 2 30 0 0.252197 0.963379 -1 2 31 0 0.255859 0.977051 -1 3 0 0.0116959 0.0232849 0.0126648 -1 3 1 0.01091 0.0234985 0.0155792 -1 3 2 0.00933838 0.0245514 0.019989 -1 3 3 0 0.0271454 0.0273743 -1 3 4 0 0.0311737 0.0391846 -1 3 5 0 0.0340271 0.0534668 -1 3 6 0 0.035675 0.0692749 -1 3 7 0 0.037384 0.0880737 -1 3 8 0 0.0403442 0.111938 -1 3 9 0 0.0455933 0.142822 -1 3 10 0 0.0540161 0.18335 -1 3 11 0 0.06604 0.235352 -1 3 12 0 0.0808105 0.296387 -1 3 13 0 0.0980835 0.365723 -1 3 14 0 0.117432 0.442139 -1 3 15 0 0.138306 0.523926 -1 3 16 0 0.160156 0.608398 -1 3 17 0 0.181274 0.689941 -1 3 18 0 0.200684 0.764648 -1 3 19 0 0.217896 0.830566 -1 3 20 0 0.227295 0.867188 -1 3 21 0 0.229126 0.874512 -1 3 22 0 0.231079 0.881836 -1 3 23 0 0.233032 0.889648 -1 3 24 0 0.234985 0.897461 -1 3 25 0 0.237305 0.90625 -1 3 26 0 0.239746 0.915527 -1 3 27 0 0.242432 0.925781 -1 3 28 0 0.245483 0.937988 -1 3 29 0 0.248779 0.950684 -1 3 30 0 0.252197 0.963867 -1 3 31 0 0.255859 0.977051 -1 4 0 0 0.0359802 0.0147781 -1 4 1 0 0.0358276 0.0184174 -1 4 2 0 0.0360107 0.0230865 -1 4 3 0 0.0370789 0.0297699 -1 4 4 0 0.0393982 0.0397949 -1 4 5 0 0.0418091 0.0533447 -1 4 6 0 0.0432434 0.0691528 -1 4 7 0 0.044342 0.0880127 -1 4 8 0 0.0464478 0.111938 -1 4 9 0 0.0506287 0.142822 -1 4 10 0 0.0580444 0.183228 -1 4 11 0 0.0691528 0.235229 -1 4 12 0 0.0831909 0.296387 -1 4 13 0 0.0998535 0.365723 -1 4 14 0 0.118774 0.442139 -1 4 15 0 0.139282 0.523926 -1 4 16 0 0.160889 0.608398 -1 4 17 0 0.181885 0.689941 -1 4 18 0 0.201172 0.764648 -1 4 19 0 0.21814 0.830566 -1 4 20 0 0.227661 0.867188 -1 4 21 0 0.22937 0.874512 -1 4 22 0 0.231201 0.881836 -1 4 23 0 0.233154 0.889648 -1 4 24 0 0.235229 0.897461 -1 4 25 0 0.237427 0.90625 -1 4 26 0 0.239868 0.915527 -1 4 27 0 0.242554 0.925781 -1 4 28 0 0.245605 0.937988 -1 4 29 0 0.248901 0.950684 -1 4 30 0 0.252197 0.963867 -1 4 31 0 0.255859 0.977051 -1 5 0 0 0.0509949 0.0142212 -1 5 1 0 0.0509338 0.0191498 -1 5 2 0 0.0508728 0.024765 -1 5 3 0 0.0509338 0.0316772 -1 5 4 0 0.0515137 0.0408325 -1 5 5 0 0.0527039 0.0533142 -1 5 6 0 0.0537109 0.0689087 -1 5 7 0 0.0543213 0.0878906 -1 5 8 0 0.0555725 0.111877 -1 5 9 0 0.0586243 0.1427 -1 5 10 0 0.0647583 0.183228 -1 5 11 0 0.074707 0.235229 -1 5 12 0 0.0875244 0.296387 -1 5 13 0 0.103149 0.365723 -1 5 14 0 0.121277 0.442139 -1 5 15 0 0.141235 0.523926 -1 5 16 0 0.162354 0.608398 -1 5 17 0 0.182861 0.689941 -1 5 18 0 0.202026 0.764648 -1 5 19 0 0.218872 0.830566 -1 5 20 0 0.228149 0.867188 -1 5 21 0 0.229736 0.874512 -1 5 22 0 0.231567 0.881836 -1 5 23 0 0.233521 0.889648 -1 5 24 0 0.235474 0.897461 -1 5 25 0 0.237549 0.90625 -1 5 26 0 0.23999 0.915527 -1 5 27 0 0.242676 0.92627 -1 5 28 0 0.245728 0.937988 -1 5 29 0 0.249023 0.950684 -1 5 30 0 0.252441 0.963867 -1 5 31 0 0.255859 0.977051 -1 6 0 0 0.0668335 0.0053978 -1 6 1 0 0.0668335 0.0159607 -1 6 2 0 0.0668335 0.0233002 -1 6 3 0 0.0668945 0.0312347 -1 6 4 0 0.0670166 0.040863 -1 6 5 0 0.0672607 0.0530701 -1 6 6 0 0.067627 0.0684204 -1 6 7 0 0.0678101 0.0875854 -1 6 8 0 0.0683594 0.111755 -1 6 9 0 0.0703125 0.142578 -1 6 10 0 0.0751953 0.183105 -1 6 11 0 0.0836792 0.235107 -1 6 12 0 0.0949707 0.296387 -1 6 13 0 0.10907 0.365723 -1 6 14 0 0.125854 0.442139 -1 6 15 0 0.144653 0.523926 -1 6 16 0 0.165039 0.608398 -1 6 17 0 0.184937 0.689941 -1 6 18 0 0.203613 0.764648 -1 6 19 0 0.220093 0.830566 -1 6 20 0 0.229126 0.867188 -1 6 21 0 0.230591 0.874512 -1 6 22 0 0.2323 0.882324 -1 6 23 0 0.234009 0.889648 -1 6 24 0 0.23584 0.897461 -1 6 25 0 0.238037 0.90625 -1 6 26 0 0.240356 0.915527 -1 6 27 0 0.243042 0.92627 -1 6 28 0 0.245972 0.937988 -1 6 29 0 0.249268 0.950684 -1 6 30 0 0.252686 0.963867 -1 6 31 0 0.256104 0.977051 -1 7 0 0 0.085144 0 -1 7 1 0 0.0852051 0 -1 7 2 0 0.0852661 0.0172424 -1 7 3 0 0.0853271 0.0278473 -1 7 4 0 0.0854492 0.0386658 -1 7 5 0 0.0855713 0.0515442 -1 7 6 0 0.0857544 0.0671997 -1 7 7 0 0.0857544 0.086853 -1 7 8 0 0.0858154 0.111389 -1 7 9 0 0.086853 0.142334 -1 7 10 0 0.0906372 0.182739 -1 7 11 0 0.0977783 0.234863 -1 7 12 0 0.107239 0.296143 -1 7 13 0 0.119263 0.365723 -1 7 14 0 0.134033 0.442139 -1 7 15 0 0.151123 0.523926 -1 7 16 0 0.169922 0.608398 -1 7 17 0 0.188843 0.689941 -1 7 18 0 0.206665 0.764648 -1 7 19 0 0.222534 0.830566 -1 7 20 0 0.231201 0.867676 -1 7 21 0 0.232178 0.874512 -1 7 22 0 0.233521 0.882324 -1 7 23 0 0.235107 0.889648 -1 7 24 0 0.236816 0.897461 -1 7 25 0 0.23877 0.90625 -1 7 26 0 0.240967 0.915527 -1 7 27 0 0.24353 0.92627 -1 7 28 0 0.24646 0.937988 -1 7 29 0 0.249634 0.950684 -1 7 30 0 0.25293 0.963867 -1 7 31 0 0.256348 0.977051 -1 8 0 0 0.108215 0 -1 8 1 0 0.108276 0 -1 8 2 0 0.108276 0 -1 8 3 0 0.108337 0.01828 -1 8 4 0 0.108459 0.0336609 -1 8 5 0 0.108643 0.0481567 -1 8 6 0 0.108887 0.0647583 -1 8 7 0 0.109009 0.085083 -1 8 8 0 0.109009 0.110352 -1 8 9 0 0.109497 0.141968 -1 8 10 0 0.112366 0.182373 -1 8 11 0 0.118469 0.234497 -1 8 12 0 0.126221 0.296143 -1 8 13 0 0.135864 0.365479 -1 8 14 0 0.148071 0.442139 -1 8 15 0 0.162598 0.523926 -1 8 16 0 0.179077 0.608398 -1 8 17 0 0.196045 0.689941 -1 8 18 0 0.212402 0.765137 -1 8 19 0 0.227295 0.831055 -1 8 20 0 0.234985 0.867676 -1 8 21 0 0.235229 0.875 -1 8 22 0 0.235962 0.882324 -1 8 23 0 0.237183 0.890137 -1 8 24 0 0.238647 0.897949 -1 8 25 0 0.240356 0.90625 -1 8 26 0 0.24231 0.915527 -1 8 27 0 0.244751 0.92627 -1 8 28 0 0.247437 0.937988 -1 8 29 0 0.250488 0.950684 -1 8 30 0 0.253662 0.963867 -1 8 31 0 0.25708 0.977051 -1 9 0 0 0.137573 0 -1 9 1 0 0.137573 0 -1 9 2 0 0.137573 0 -1 9 3 0 0.137573 0 -1 9 4 0 0.137695 0.0198059 -1 9 5 0 0.137817 0.041626 -1 9 6 0 0.137939 0.0604248 -1 9 7 0 0.138184 0.0819702 -1 9 8 0 0.13855 0.108337 -1 9 9 0 0.13916 0.140991 -1 9 10 0 0.141602 0.181763 -1 9 11 0 0.147095 0.233887 -1 9 12 0 0.153442 0.295654 -1 9 13 0 0.161011 0.365234 -1 9 14 0 0.170166 0.442139 -1 9 15 0 0.181519 0.523926 -1 9 16 0 0.194824 0.608398 -1 9 17 0 0.208862 0.689941 -1 9 18 0 0.2229 0.765137 -1 9 19 0 0.23584 0.831055 -1 9 20 0 0.242065 0.868164 -1 9 21 0 0.240845 0.875 -1 9 22 0 0.240723 0.882812 -1 9 23 0 0.241089 0.890137 -1 9 24 0 0.241943 0.897949 -1 9 25 0 0.243164 0.906738 -1 9 26 0 0.244873 0.916016 -1 9 27 0 0.246826 0.92627 -1 9 28 0 0.249268 0.937988 -1 9 29 0 0.251953 0.950684 -1 9 30 0 0.255127 0.963867 -1 9 31 0 0.258301 0.977539 -1 10 0 0 0.175293 0 -1 10 1 0 0.175293 0 -1 10 2 0 0.175415 0 -1 10 3 0 0.175415 0 -1 10 4 0 0.175415 0 -1 10 5 0 0.175537 0.0245514 -1 10 6 0 0.175537 0.0531616 -1 10 7 0 0.175537 0.0776978 -1 10 8 0 0.175903 0.105713 -1 10 9 0 0.176636 0.139648 -1 10 10 0 0.178833 0.181152 -1 10 11 0 0.183716 0.233154 -1 10 12 0 0.189209 0.294922 -1 10 13 0 0.195068 0.36499 -1 10 14 0 0.20166 0.441895 -1 10 15 0 0.209473 0.523926 -1 10 16 0 0.219116 0.608887 -1 10 17 0 0.229492 0.69043 -1 10 18 0 0.240112 0.765137 -1 10 19 0 0.250244 0.831543 -1 10 20 0 0.25415 0.869141 -1 10 21 0 0.250732 0.875977 -1 10 22 0 0.248779 0.883301 -1 10 23 0 0.248047 0.891113 -1 10 24 0 0.247925 0.898438 -1 10 25 0 0.248291 0.907227 -1 10 26 0 0.249268 0.916504 -1 10 27 0 0.250732 0.926758 -1 10 28 0 0.252686 0.938477 -1 10 29 0 0.254883 0.951172 -1 10 30 0 0.257568 0.964355 -1 10 31 0 0.260254 0.977539 -1 11 0 0 0.224365 0 -1 11 1 0 0.224365 0 -1 11 2 0 0.224365 0 -1 11 3 0 0.224487 0 -1 11 4 0 0.224487 0 -1 11 5 0 0.224487 0 -1 11 6 0 0.224609 0.0342102 -1 11 7 0 0.224487 0.0703735 -1 11 8 0 0.224365 0.102356 -1 11 9 0 0.224609 0.138428 -1 11 10 0 0.226196 0.18103 -1 11 11 0 0.229492 0.232422 -1 11 12 0 0.234009 0.293945 -1 11 13 0 0.238525 0.364258 -1 11 14 0 0.243042 0.44165 -1 11 15 0 0.247925 0.523926 -1 11 16 0 0.253662 0.608887 -1 11 17 0 0.259766 0.690918 -1 11 18 0 0.266357 0.765625 -1 11 19 0 0.272705 0.832031 -1 11 20 0 0.273438 0.870605 -1 11 21 0 0.266602 0.877441 -1 11 22 0 0.262207 0.884277 -1 11 23 0 0.259521 0.89209 -1 11 24 0 0.257812 0.899414 -1 11 25 0 0.25708 0.907715 -1 11 26 0 0.256836 0.916992 -1 11 27 0 0.25708 0.927246 -1 11 28 0 0.258301 0.938965 -1 11 29 0 0.259766 0.95166 -1 11 30 0 0.261719 0.964355 -1 11 31 0 0.263916 0.978027 -1 12 0 0 0.283936 0 -1 12 1 0 0.283936 0 -1 12 2 0 0.283936 0 -1 12 3 0 0.283936 0 -1 12 4 0 0.283936 0 -1 12 5 0 0.283936 0 -1 12 6 0 0.283936 0 -1 12 7 0 0.28418 0.0504456 -1 12 8 0 0.28418 0.0944824 -1 12 9 0 0.28418 0.135132 -1 12 10 0 0.284668 0.17981 -1 12 11 0 0.286133 0.231567 -1 12 12 0 0.289062 0.292725 -1 12 13 0 0.292236 0.363037 -1 12 14 0 0.295166 0.440674 -1 12 15 0 0.297363 0.523438 -1 12 16 0 0.299561 0.608887 -1 12 17 0 0.301514 0.691406 -1 12 18 0 0.303467 0.766602 -1 12 19 0 0.305664 0.83252 -1 12 20 0 0.30249 0.873047 -1 12 21 0 0.291016 0.879395 -1 12 22 0 0.282959 0.88623 -1 12 23 0 0.277344 0.893555 -1 12 24 0 0.273682 0.900879 -1 12 25 0 0.270752 0.90918 -1 12 26 0 0.268799 0.918457 -1 12 27 0 0.267822 0.928223 -1 12 28 0 0.267578 0.939941 -1 12 29 0 0.267822 0.952148 -1 12 30 0 0.268799 0.965332 -1 12 31 0 0.27002 0.978516 -1 13 0 0 0.351318 0 -1 13 1 0 0.351318 0 -1 13 2 0 0.351318 0 -1 13 3 0 0.351562 0 -1 13 4 0 0.351562 0 -1 13 5 0 0.351562 0 -1 13 6 0 0.351562 0 -1 13 7 0 0.351807 0 -1 13 8 0 0.351807 0.0742188 -1 13 9 0 0.352051 0.125854 -1 13 10 0 0.352295 0.174805 -1 13 11 0 0.353027 0.228638 -1 13 12 0 0.354248 0.290527 -1 13 13 0 0.356201 0.36084 -1 13 14 0 0.357666 0.439209 -1 13 15 0 0.35791 0.522461 -1 13 16 0 0.357178 0.608887 -1 13 17 0 0.355225 0.691895 -1 13 18 0 0.352539 0.767578 -1 13 19 0 0.350098 0.833496 -1 13 20 0 0.342773 0.876953 -1 13 21 0 0.325439 0.882812 -1 13 22 0 0.312988 0.889648 -1 13 23 0 0.303711 0.896484 -1 13 24 0 0.297119 0.90332 -1 13 25 0 0.291504 0.911621 -1 13 26 0 0.287354 0.92041 -1 13 27 0 0.283936 0.930176 -1 13 28 0 0.281738 0.941406 -1 13 29 0 0.280273 0.953613 -1 13 30 0 0.279785 0.966309 -1 13 31 0 0.279541 0.979492 -1 14 0 0 0.426758 0 -1 14 1 0 0.426758 0 -1 14 2 0 0.426758 0 -1 14 3 0 0.426758 0 -1 14 4 0 0.426758 0 -1 14 5 0 0.426758 0 -1 14 6 0 0.426758 0 -1 14 7 0 0.427002 0 -1 14 8 0 0.427002 0 -1 14 9 0 0.427246 0.10553 -1 14 10 0 0.427734 0.163818 -1 14 11 0 0.428467 0.221802 -1 14 12 0 0.429199 0.285645 -1 14 13 0 0.430176 0.356689 -1 14 14 0 0.43042 0.435791 -1 14 15 0 0.429199 0.520508 -1 14 16 0 0.426025 0.60791 -1 14 17 0 0.420654 0.691895 -1 14 18 0 0.413818 0.768066 -1 14 19 0 0.406738 0.834961 -1 14 20 0 0.395752 0.882324 -1 14 21 0 0.371826 0.888184 -1 14 22 0 0.35376 0.894531 -1 14 23 0 0.340088 0.900879 -1 14 24 0 0.329834 0.907715 -1 14 25 0 0.321045 0.915039 -1 14 26 0 0.313477 0.923828 -1 14 27 0 0.307373 0.933105 -1 14 28 0 0.30249 0.944336 -1 14 29 0 0.298828 0.956055 -1 14 30 0 0.295898 0.968262 -1 14 31 0 0.293945 0.981445 -1 15 0 0 0.507324 0 -1 15 1 0 0.507324 0 -1 15 2 0 0.507812 0 -1 15 3 0 0.507812 0 -1 15 4 0 0.507812 0 -1 15 5 0 0.507812 0 -1 15 6 0 0.507812 0 -1 15 7 0 0.507812 0 -1 15 8 0 0.507812 0 -1 15 9 0 0.508301 0.0460205 -1 15 10 0 0.508789 0.143066 -1 15 11 0 0.509277 0.208618 -1 15 12 0 0.510254 0.276123 -1 15 13 0 0.51123 0.349365 -1 15 14 0 0.51123 0.429688 -1 15 15 0 0.509277 0.516113 -1 15 16 0 0.504883 0.60498 -1 15 17 0 0.496826 0.690918 -1 15 18 0 0.486328 0.768555 -1 15 19 0 0.474854 0.836426 -1 15 20 0 0.461182 0.88916 -1 15 21 0 0.43042 0.895996 -1 15 22 0 0.40625 0.902344 -1 15 23 0 0.387451 0.908203 -1 15 24 0 0.372803 0.914551 -1 15 25 0 0.359863 0.921387 -1 15 26 0 0.348633 0.929199 -1 15 27 0 0.339111 0.937988 -1 15 28 0 0.331055 0.948242 -1 15 29 0 0.324219 0.959473 -1 15 30 0 0.318604 0.97168 -1 15 31 0 0.314209 0.983887 -1 16 0 0 0.592773 0 -1 16 1 0 0.592773 0 -1 16 2 0 0.592773 0 -1 16 3 0 0.592773 0 -1 16 4 0 0.592773 0 -1 16 5 0 0.592773 0 -1 16 6 0 0.592773 0 -1 16 7 0 0.592773 0 -1 16 8 0 0.592773 0 -1 16 9 0 0.592773 0 -1 16 10 0 0.593262 0.101074 -1 16 11 0 0.594238 0.18689 -1 16 12 0 0.595703 0.260498 -1 16 13 0 0.597168 0.33667 -1 16 14 0 0.597656 0.419189 -1 16 15 0 0.596191 0.507324 -1 16 16 0 0.591309 0.598633 -1 16 17 0 0.582031 0.687012 -1 16 18 0 0.568848 0.76709 -1 16 19 0 0.553711 0.836426 -1 16 20 0 0.537598 0.893555 -1 16 21 0 0.501465 0.905762 -1 16 22 0 0.470947 0.913086 -1 16 23 0 0.446777 0.918945 -1 16 24 0 0.427246 0.924805 -1 16 25 0 0.409668 0.930664 -1 16 26 0 0.394043 0.9375 -1 16 27 0 0.380127 0.945312 -1 16 28 0 0.368164 0.955078 -1 16 29 0 0.357666 0.965332 -1 16 30 0 0.348877 0.976562 -1 16 31 0 0.341064 0.987793 -1 17 0 0 0.67627 0 -1 17 1 0 0.67627 0 -1 17 2 0 0.67627 0 -1 17 3 0 0.67627 0 -1 17 4 0 0.67627 0 -1 17 5 0 0.67627 0 -1 17 6 0 0.67627 0 -1 17 7 0 0.67627 0 -1 17 8 0 0.67627 0 -1 17 9 0 0.676758 0 -1 17 10 0 0.676758 0 -1 17 11 0 0.677734 0.151611 -1 17 12 0 0.679688 0.237915 -1 17 13 0 0.681641 0.318848 -1 17 14 0 0.683105 0.403564 -1 17 15 0 0.683105 0.493652 -1 17 16 0 0.678711 0.587402 -1 17 17 0 0.669922 0.678223 -1 17 18 0 0.655762 0.761719 -1 17 19 0 0.638672 0.833984 -1 17 20 0 0.619141 0.893066 -1 17 21 0 0.582031 0.916016 -1 17 22 0 0.546387 0.926758 -1 17 23 0 0.516602 0.933594 -1 17 24 0 0.491699 0.938965 -1 17 25 0 0.468994 0.944336 -1 17 26 0 0.448486 0.950195 -1 17 27 0 0.429688 0.957031 -1 17 28 0 0.41333 0.964844 -1 17 29 0 0.398682 0.973633 -1 17 30 0 0.385986 0.983398 -1 17 31 0 0.374512 0.994141 -1 18 0 0 0.754395 0 -1 18 1 0 0.754395 0 -1 18 2 0 0.754395 0 -1 18 3 0 0.754395 0 -1 18 4 0 0.754395 0 -1 18 5 0 0.754395 0 -1 18 6 0 0.754395 0 -1 18 7 0 0.754395 0 -1 18 8 0 0.754395 0 -1 18 9 0 0.754883 0 -1 18 10 0 0.754883 0 -1 18 11 0 0.755371 0.0775146 -1 18 12 0 0.757324 0.206421 -1 18 13 0 0.759766 0.294922 -1 18 14 0 0.762207 0.382812 -1 18 15 0 0.763672 0.474365 -1 18 16 0 0.762207 0.570312 -1 18 17 0 0.754883 0.664551 -1 18 18 0 0.742188 0.751465 -1 18 19 0 0.724121 0.827148 -1 18 20 0 0.702637 0.889648 -1 18 21 0 0.66748 0.924316 -1 18 22 0 0.629395 0.941406 -1 18 23 0 0.594727 0.951172 -1 18 24 0 0.564941 0.957031 -1 18 25 0 0.537109 0.962402 -1 18 26 0 0.510742 0.966797 -1 18 27 0 0.487061 0.972168 -1 18 28 0 0.465576 0.978516 -1 18 29 0 0.446289 0.985352 -1 18 30 0 0.428955 0.993652 -1 18 31 0 0.413574 1 -1 19 0 0 0.824707 0 -1 19 1 0 0.824707 0 -1 19 2 0 0.824707 0 -1 19 3 0 0.824707 0 -1 19 4 0 0.824707 0 -1 19 5 0 0.824707 0 -1 19 6 0 0.824707 0 -1 19 7 0 0.824707 0 -1 19 8 0 0.824707 0 -1 19 9 0 0.824707 0 -1 19 10 0 0.824707 0 -1 19 11 0 0.825195 0 -1 19 12 0 0.82666 0.162231 -1 19 13 0 0.82959 0.266113 -1 19 14 0 0.83252 0.358154 -1 19 15 0 0.835449 0.451416 -1 19 16 0 0.835938 0.54834 -1 19 17 0 0.832031 0.64502 -1 19 18 0 0.821777 0.73584 -1 19 19 0 0.805176 0.81543 -1 19 20 0 0.783691 0.881348 -1 19 21 0 0.751953 0.927246 -1 19 22 0 0.714355 0.953613 -1 19 23 0 0.677246 0.968262 -1 19 24 0 0.643555 0.977051 -1 19 25 0 0.610352 0.982422 -1 19 26 0 0.579102 0.986816 -1 19 27 0 0.549805 0.990723 -1 19 28 0 0.522949 0.995117 -1 19 29 0 0.498535 1 -1 19 30 0 0.476562 1 -1 19 31 0 0.456787 1 -1 20 0 0 0.885254 0 -1 20 1 0 0.885254 0 -1 20 2 0 0.885254 0 -1 20 3 0 0.885254 0 -1 20 4 0 0.885254 0 -1 20 5 0 0.885254 0 -1 20 6 0 0.885254 0 -1 20 7 0 0.885254 0 -1 20 8 0 0.885254 0 -1 20 9 0 0.885254 0 -1 20 10 0 0.885254 0 -1 20 11 0 0.885742 0 -1 20 12 0 0.88623 0.0790405 -1 20 13 0 0.88916 0.231934 -1 20 14 0 0.893066 0.330811 -1 20 15 0 0.896973 0.42627 -1 20 16 0 0.899414 0.524414 -1 20 17 0 0.898438 0.62207 -1 20 18 0 0.891113 0.715332 -1 20 19 0 0.876953 0.797852 -1 20 20 0 0.856934 0.867676 -1 20 21 0 0.830078 0.922852 -1 20 22 0 0.79541 0.959961 -1 20 23 0 0.758301 0.981445 -1 20 24 0 0.722656 0.994141 -1 20 25 0 0.686035 1 -1 20 26 0 0.649902 1 -1 20 27 0 0.615723 1 -1 20 28 0 0.583496 1 -1 20 29 0 0.553711 1 -1 20 30 0 0.526855 1 -1 20 31 0 0.502441 1 -1 21 0 0 0.936523 0 -1 21 1 0 0.936523 0 -1 21 2 0 0.936523 0 -1 21 3 0 0.936523 0 -1 21 4 0 0.936523 0 -1 21 5 0 0.936523 0 -1 21 6 0 0.936523 0 -1 21 7 0 0.936523 0 -1 21 8 0 0.936523 0 -1 21 9 0 0.936523 0 -1 21 10 0 0.937012 0 -1 21 11 0 0.937012 0 -1 21 12 0 0.937012 0 -1 21 13 0 0.939453 0.189331 -1 21 14 0 0.943848 0.300537 -1 21 15 0 0.94873 0.398682 -1 21 16 0 0.952637 0.497314 -1 21 17 0 0.954102 0.595703 -1 21 18 0 0.950195 0.69043 -1 21 19 0 0.939453 0.775879 -1 21 20 0 0.922363 0.849121 -1 21 21 0 0.899414 0.910645 -1 21 22 0 0.869629 0.957031 -1 21 23 0 0.835449 0.987305 -1 21 24 0 0.799805 1 -1 21 25 0 0.76123 1 -1 21 26 0 0.722168 1 -1 21 27 0 0.683594 1 -1 21 28 0 0.646484 1 -1 21 29 0 0.611816 1 -1 21 30 0 0.580078 1 -1 21 31 0 0.550781 1 -1 22 0 0 0.979492 0 -1 22 1 0 0.979492 0 -1 22 2 0 0.979492 0 -1 22 3 0 0.979492 0 -1 22 4 0 0.979492 0 -1 22 5 0 0.979492 0 -1 22 6 0 0.979492 0 -1 22 7 0 0.979492 0 -1 22 8 0 0.979492 0 -1 22 9 0 0.979492 0 -1 22 10 0 0.979492 0 -1 22 11 0 0.979492 0 -1 22 12 0 0.97998 0 -1 22 13 0 0.981445 0.128296 -1 22 14 0 0.985352 0.267334 -1 22 15 0 0.990723 0.369873 -1 22 16 0 0.996094 0.469238 -1 22 17 0 0.999512 0.567871 -1 22 18 0 0.999023 0.662598 -1 22 19 0 0.991699 0.750488 -1 22 20 0 0.978027 0.82666 -1 22 21 0 0.958008 0.891602 -1 22 22 0 0.933105 0.944824 -1 22 23 0 0.90332 0.983398 -1 22 24 0 0.870117 1 -1 22 25 0 0.83252 1 -1 22 26 0 0.791992 1 -1 22 27 0 0.750488 1 -1 22 28 0 0.709961 1 -1 22 29 0 0.670898 1 -1 22 30 0 0.634277 1 -1 22 31 0 0.600586 1 -1 23 0 0 1 0 -1 23 1 0 1 0 -1 23 2 0 1 0 -1 23 3 0 1 0 -1 23 4 0 1 0 -1 23 5 0 1 0 -1 23 6 0 1 0 -1 23 7 0 1 0 -1 23 8 0 1 0 -1 23 9 0 1 0 -1 23 10 0 1 0 -1 23 11 0 1 0 -1 23 12 0 1 0 -1 23 13 0 1 0 -1 23 14 0 1 0.231689 -1 23 15 0 1 0.341064 -1 23 16 0 1 0.44165 -1 23 17 0 1 0.539551 -1 23 18 0 1 0.634766 -1 23 19 0 1 0.723145 -1 23 20 0 1 0.80127 -1 23 21 0 1 0.869629 -1 23 22 0 0.984375 0.92627 -1 23 23 0 0.958984 0.970703 -1 23 24 0 0.929688 1 -1 23 25 0 0.89502 1 -1 23 26 0 0.85498 1 -1 23 27 0 0.8125 1 -1 23 28 0 0.769531 1 -1 23 29 0 0.727539 1 -1 23 30 0 0.687012 1 -1 23 31 0 0.648926 1 -1 24 0 0 1 0 -1 24 1 0 1 0 -1 24 2 0 1 0 -1 24 3 0 1 0 -1 24 4 0 1 0 -1 24 5 0 1 0 -1 24 6 0 1 0 -1 24 7 0 1 0 -1 24 8 0 1 0 -1 24 9 0 1 0 -1 24 10 0 1 0 -1 24 11 0 1 0 -1 24 12 0 1 0 -1 24 13 0 1 0 -1 24 14 0 1 0.191284 -1 24 15 0 1 0.312012 -1 24 16 0 1 0.414307 -1 24 17 0 1 0.512207 -1 24 18 0 1 0.606934 -1 24 19 0 1 0.695312 -1 24 20 0 1 0.774414 -1 24 21 0 1 0.845215 -1 24 22 0 1 0.904785 -1 24 23 0 1 0.953125 -1 24 24 0 0.979004 0.991699 -1 24 25 0 0.948242 1 -1 24 26 0 0.911133 1 -1 24 27 0 0.869141 1 -1 24 28 0 0.825195 1 -1 24 29 0 0.780762 1 -1 24 30 0 0.737305 1 -1 24 31 0 0.695801 1 -1 25 0 0 1 0 -1 25 1 0 1 0 -1 25 2 0 1 0 -1 25 3 0 1 0 -1 25 4 0 1 0 -1 25 5 0 1 0 -1 25 6 0 1 0 -1 25 7 0 1 0 -1 25 8 0 1 0 -1 25 9 0 1 0 -1 25 10 0 1 0 -1 25 11 0 1 0 -1 25 12 0 1 0 -1 25 13 0 1 0 -1 25 14 0 1 0.132568 -1 25 15 0 1 0.279541 -1 25 16 0 1 0.38501 -1 25 17 0 1 0.482666 -1 25 18 0 1 0.576172 -1 25 19 0 1 0.664062 -1 25 20 0 1 0.744141 -1 25 21 0 1 0.816406 -1 25 22 0 1 0.878906 -1 25 23 0 1 0.930176 -1 25 24 0 1 0.972656 -1 25 25 0 0.99707 1 -1 25 26 0 0.963379 1 -1 25 27 0 0.924316 1 -1 25 28 0 0.880371 1 -1 25 29 0 0.834961 1 -1 25 30 0 0.789551 1 -1 25 31 0 0.745117 1 -1 26 0 0 1 0 -1 26 1 0 1 0 -1 26 2 0 1 0 -1 26 3 0 1 0 -1 26 4 0 1 0 -1 26 5 0 1 0 -1 26 6 0 1 0 -1 26 7 0 1 0 -1 26 8 0 1 0 -1 26 9 0 1 0 -1 26 10 0 1 0 -1 26 11 0 1 0 -1 26 12 0 1 0 -1 26 13 0 1 0 -1 26 14 0 1 0 -1 26 15 0 1 0.241943 -1 26 16 0 1 0.353027 -1 26 17 0 1 0.451172 -1 26 18 0 1 0.543457 -1 26 19 0 1 0.630859 -1 26 20 0 1 0.710938 -1 26 21 0 1 0.783691 -1 26 22 0 1 0.848633 -1 26 23 0 1 0.902832 -1 26 24 0 1 0.948242 -1 26 25 0 1 0.989258 -1 26 26 0 1 1 -1 26 27 0 0.976074 1 -1 26 28 0 0.93457 1 -1 26 29 0 0.889648 1 -1 26 30 0 0.842773 1 -1 26 31 0 0.796387 1 -1 27 0 0 1 0 -1 27 1 0 1 0 -1 27 2 0 1 0 -1 27 3 0 1 0 -1 27 4 0 1 0 -1 27 5 0 1 0 -1 27 6 0 1 0 -1 27 7 0 1 0 -1 27 8 0 1 0 -1 27 9 0 1 0 -1 27 10 0 1 0 -1 27 11 0 1 0 -1 27 12 0 1 0 -1 27 13 0 1 0 -1 27 14 0 1 0 -1 27 15 0 1 0.195557 -1 27 16 0 1 0.318604 -1 27 17 0 1 0.417725 -1 27 18 0 1 0.509277 -1 27 19 0 1 0.595215 -1 27 20 0 1 0.674805 -1 27 21 0 1 0.748047 -1 27 22 0 1 0.813965 -1 27 23 0 1 0.870605 -1 27 24 0 1 0.918457 -1 27 25 0 1 0.962891 -1 27 26 0 1 1 -1 27 27 0 1 1 -1 27 28 0 0.98584 1 -1 27 29 0 0.941895 1 -1 27 30 0 0.895508 1 -1 27 31 0 0.848145 1 -1 28 0 0 1 0 -1 28 1 0 1 0 -1 28 2 0 1 0 -1 28 3 0 1 0 -1 28 4 0 1 0 -1 28 5 0 1 0 -1 28 6 0 1 0 -1 28 7 0 1 0 -1 28 8 0 1 0 -1 28 9 0 1 0 -1 28 10 0 1 0 -1 28 11 0 1 0 -1 28 12 0 1 0 -1 28 13 0 1 0 -1 28 14 0 1 0 -1 28 15 0 1 0.126831 -1 28 16 0 1 0.280518 -1 28 17 0 1 0.382568 -1 28 18 0 1 0.473633 -1 28 19 0 1 0.558105 -1 28 20 0 1 0.63623 -1 28 21 0 1 0.709473 -1 28 22 0 1 0.775879 -1 28 23 0 1 0.833496 -1 28 24 0 1 0.883789 -1 28 25 0 1 0.931152 -1 28 26 0 1 0.974609 -1 28 27 0 1 1 -1 28 28 0 1 1 -1 28 29 0 0.991699 1 -1 28 30 0 0.947266 1 -1 28 31 0 0.899902 1 -1 29 0 0 1 0 -1 29 1 0 1 0 -1 29 2 0 1 0 -1 29 3 0 1 0 -1 29 4 0 1 0 -1 29 5 0 1 0 -1 29 6 0 1 0 -1 29 7 0 1 0 -1 29 8 0 1 0 -1 29 9 0 1 0 -1 29 10 0 1 0 -1 29 11 0 1 0 -1 29 12 0 1 0 -1 29 13 0 1 0 -1 29 14 0 1 0 -1 29 15 0 1 0 -1 29 16 0 1 0.236572 -1 29 17 0 1 0.345215 -1 29 18 0 1 0.436279 -1 29 19 0 1 0.519531 -1 29 20 0 1 0.596191 -1 29 21 0 1 0.667969 -1 29 22 0 1 0.733887 -1 29 23 0 1 0.79248 -1 29 24 0 1 0.84375 -1 29 25 0 1 0.893555 -1 29 26 0 1 0.94043 -1 29 27 0 1 0.98291 -1 29 28 0 1 1 -1 29 29 0 1 1 -1 29 30 0 0.996582 1 -1 29 31 0 0.951172 1 -1 30 0 0 1 0 -1 30 1 0 1 0 -1 30 2 0 1 0 -1 30 3 0 1 0 -1 30 4 0 1 0 -1 30 5 0 1 0 -1 30 6 0 1 0 -1 30 7 0 1 0 -1 30 8 0 1 0 -1 30 9 0 1 0 -1 30 10 0 1 0 -1 30 11 0 1 0 -1 30 12 0 1 0 -1 30 13 0 1 0 -1 30 14 0 1 0 -1 30 15 0 1 0 -1 30 16 0 1 0.182007 -1 30 17 0 1 0.304688 -1 30 18 0 1 0.397217 -1 30 19 0 1 0.479248 -1 30 20 0 1 0.554199 -1 30 21 0 1 0.624512 -1 30 22 0 1 0.689453 -1 30 23 0 1 0.747559 -1 30 24 0 1 0.799805 -1 30 25 0 1 0.850586 -1 30 26 0 1 0.899902 -1 30 27 0 1 0.946289 -1 30 28 0 1 0.988281 -1 30 29 0 1 1 -1 30 30 0 1 1 -1 30 31 0 1 1 -1 31 0 0 1 0 -1 31 1 0 1 0 -1 31 2 0 1 0 -1 31 3 0 1 0 -1 31 4 0 1 0 -1 31 5 0 1 0 -1 31 6 0 1 0 -1 31 7 0 1 0 -1 31 8 0 1 0 -1 31 9 0 1 0 -1 31 10 0 1 0 -1 31 11 0 1 0 -1 31 12 0 1 0 -1 31 13 0 1 0 -1 31 14 0 1 0 -1 31 15 0 1 0 -1 31 16 0 1 0.0874634 -1 31 17 0 1 0.260742 -1 31 18 0 1 0.356934 -1 31 19 0 1 0.438232 -1 31 20 0 1 0.51123 -1 31 21 0 1 0.57959 -1 31 22 0 1 0.643066 -1 31 23 0 1 0.700684 -1 31 24 0 1 0.752441 -1 31 25 0 1 0.804199 -1 31 26 0 1 0.855469 -1 31 27 0 1 0.904785 -1 31 28 0 1 0.951172 -1 31 29 0 1 0.992676 -1 31 30 0 1 1 -1 31 31 0 1 1 -2 0 0 0.0236969 0.0144577 0.013916 -2 0 1 0.0221558 0.0137405 0.0164337 -2 0 2 0.0190277 0.012764 0.0178375 -2 0 3 0.021637 0.0156555 0.0264435 -2 0 4 0.0224457 0.0192108 0.0392761 -2 0 5 0.0129471 0.0219879 0.0536804 -2 0 6 0 0.0244751 0.069397 -2 0 7 0 0.0277252 0.0881348 -2 0 8 0 0.0325928 0.112 -2 0 9 0 0.0396423 0.142944 -2 0 10 0 0.0495605 0.18335 -2 0 11 0 0.0627441 0.235352 -2 0 12 0 0.0784302 0.296387 -2 0 13 0 0.0963135 0.365723 -2 0 14 0 0.11615 0.442139 -2 0 15 0 0.137329 0.523926 -2 0 16 0 0.159424 0.608398 -2 0 17 0 0.180664 0.689941 -2 0 18 0 0.200317 0.764648 -2 0 19 0 0.217529 0.830566 -2 0 20 0 0.227051 0.867188 -2 0 21 0 0.228882 0.874512 -2 0 22 0 0.230835 0.881836 -2 0 23 0 0.23291 0.889648 -2 0 24 0 0.234863 0.897461 -2 0 25 0 0.237183 0.90625 -2 0 26 0 0.239624 0.915527 -2 0 27 0 0.242432 0.925781 -2 0 28 0 0.245483 0.937988 -2 0 29 0 0.248779 0.950684 -2 0 30 0 0.252197 0.963379 -2 0 31 0 0.255859 0.977051 -2 1 0 0.0195923 0.0147781 0.0119781 -2 1 1 0.0219269 0.0167084 0.0164948 -2 1 2 0.0189362 0.0151367 0.0181274 -2 1 3 0.0210876 0.0181427 0.0264893 -2 1 4 0.0214996 0.0219421 0.0391846 -2 1 5 0.00976562 0.0247192 0.0536499 -2 1 6 0 0.0269165 0.069397 -2 1 7 0 0.0297241 0.0881348 -2 1 8 0 0.0340881 0.112 -2 1 9 0 0.040741 0.142822 -2 1 10 0 0.050354 0.18335 -2 1 11 0 0.0632935 0.235352 -2 1 12 0 0.0787964 0.296387 -2 1 13 0 0.0966187 0.365723 -2 1 14 0 0.116394 0.442139 -2 1 15 0 0.137573 0.523926 -2 1 16 0 0.159546 0.608398 -2 1 17 0 0.180786 0.689941 -2 1 18 0 0.200317 0.764648 -2 1 19 0 0.217529 0.830566 -2 1 20 0 0.227051 0.867188 -2 1 21 0 0.229004 0.874512 -2 1 22 0 0.230957 0.881836 -2 1 23 0 0.23291 0.889648 -2 1 24 0 0.234985 0.897461 -2 1 25 0 0.237183 0.90625 -2 1 26 0 0.239624 0.915527 -2 1 27 0 0.242432 0.925781 -2 1 28 0 0.245483 0.937988 -2 1 29 0 0.248779 0.950684 -2 1 30 0 0.252197 0.963867 -2 1 31 0 0.255859 0.977051 -2 2 0 0.0180664 0.0170593 0.0116882 -2 2 1 0.0181885 0.0175171 0.0144196 -2 2 2 0.0189667 0.0189667 0.0189667 -2 2 3 0.0202026 0.0218201 0.0267792 -2 2 4 0.0197144 0.0258026 0.039093 -2 2 5 0 0.0286255 0.0535583 -2 2 6 0 0.0305481 0.0693359 -2 2 7 0 0.0328064 0.0881348 -2 2 8 0 0.0365601 0.112 -2 2 9 0 0.0426025 0.142822 -2 2 10 0 0.0517273 0.18335 -2 2 11 0 0.06427 0.235352 -2 2 12 0 0.0795288 0.296387 -2 2 13 0 0.097168 0.365723 -2 2 14 0 0.11676 0.442139 -2 2 15 0 0.137817 0.523926 -2 2 16 0 0.15979 0.608398 -2 2 17 0 0.180908 0.689941 -2 2 18 0 0.200439 0.764648 -2 2 19 0 0.217651 0.830566 -2 2 20 0 0.227173 0.867188 -2 2 21 0 0.229004 0.874512 -2 2 22 0 0.230957 0.881836 -2 2 23 0 0.23291 0.889648 -2 2 24 0 0.234985 0.897461 -2 2 25 0 0.237183 0.90625 -2 2 26 0 0.239624 0.915527 -2 2 27 0 0.242432 0.925781 -2 2 28 0 0.245483 0.937988 -2 2 29 0 0.248779 0.950684 -2 2 30 0 0.252197 0.963867 -2 2 31 0 0.255859 0.977051 -2 3 0 0.0193787 0.0245361 0.0133896 -2 3 1 0.0190277 0.0246735 0.0163574 -2 3 2 0.0187683 0.0254669 0.0207062 -2 3 3 0.0184479 0.0276489 0.0277863 -2 3 4 0.0156174 0.031311 0.0392456 -2 3 5 0 0.0341492 0.0534363 -2 3 6 0 0.0358276 0.0692749 -2 3 7 0 0.0375061 0.0880737 -2 3 8 0 0.0404663 0.111938 -2 3 9 0 0.0456543 0.142822 -2 3 10 0 0.0540771 0.18335 -2 3 11 0 0.06604 0.235352 -2 3 12 0 0.0808716 0.296387 -2 3 13 0 0.0980835 0.365723 -2 3 14 0 0.117493 0.442139 -2 3 15 0 0.138306 0.523926 -2 3 16 0 0.160156 0.608398 -2 3 17 0 0.181274 0.689941 -2 3 18 0 0.200684 0.764648 -2 3 19 0 0.217896 0.830566 -2 3 20 0 0.227295 0.867188 -2 3 21 0 0.229126 0.874512 -2 3 22 0 0.231079 0.881836 -2 3 23 0 0.233032 0.889648 -2 3 24 0 0.235107 0.897461 -2 3 25 0 0.237305 0.90625 -2 3 26 0 0.239746 0.915527 -2 3 27 0 0.242432 0.925781 -2 3 28 0 0.245483 0.937988 -2 3 29 0 0.248779 0.950684 -2 3 30 0 0.252197 0.963867 -2 3 31 0 0.255859 0.977051 -2 4 0 0.0174255 0.0364075 0.0150452 -2 4 1 0.0165253 0.0362854 0.0186768 -2 4 2 0.0149536 0.0364075 0.0233612 -2 4 3 0.0111465 0.037384 0.0299835 -2 4 4 0 0.0395203 0.039856 -2 4 5 0 0.0419006 0.0533142 -2 4 6 0 0.043335 0.0691528 -2 4 7 0 0.0444641 0.0880737 -2 4 8 0 0.0465393 0.111938 -2 4 9 0 0.0507202 0.142822 -2 4 10 0 0.0581055 0.183228 -2 4 11 0 0.0692139 0.235229 -2 4 12 0 0.083252 0.296387 -2 4 13 0 0.0999146 0.365723 -2 4 14 0 0.118774 0.442139 -2 4 15 0 0.139404 0.523926 -2 4 16 0 0.160889 0.608398 -2 4 17 0 0.181885 0.689941 -2 4 18 0 0.201172 0.764648 -2 4 19 0 0.218262 0.830566 -2 4 20 0 0.227661 0.867188 -2 4 21 0 0.22937 0.874512 -2 4 22 0 0.231201 0.881836 -2 4 23 0 0.233154 0.889648 -2 4 24 0 0.235229 0.897461 -2 4 25 0 0.237427 0.90625 -2 4 26 0 0.239868 0.915527 -2 4 27 0 0.242554 0.92627 -2 4 28 0 0.245605 0.937988 -2 4 29 0 0.248901 0.950684 -2 4 30 0 0.252197 0.963867 -2 4 31 0 0.255859 0.977051 -2 5 0 0 0.0510864 0.0144043 -2 5 1 0 0.0509949 0.0192566 -2 5 2 0 0.0509338 0.0248413 -2 5 3 0 0.0510254 0.0317383 -2 5 4 0 0.0515747 0.040863 -2 5 5 0 0.0527649 0.0533142 -2 5 6 0 0.0538025 0.0689697 -2 5 7 0 0.0544128 0.0879517 -2 5 8 0 0.0556335 0.111877 -2 5 9 0 0.0586853 0.1427 -2 5 10 0 0.0648193 0.183228 -2 5 11 0 0.074707 0.235229 -2 5 12 0 0.0875854 0.296387 -2 5 13 0 0.10321 0.365723 -2 5 14 0 0.121277 0.442139 -2 5 15 0 0.141235 0.523926 -2 5 16 0 0.162354 0.608398 -2 5 17 0 0.182861 0.689941 -2 5 18 0 0.202026 0.764648 -2 5 19 0 0.218872 0.830566 -2 5 20 0 0.228149 0.867188 -2 5 21 0 0.229736 0.874512 -2 5 22 0 0.231567 0.881836 -2 5 23 0 0.233521 0.889648 -2 5 24 0 0.235474 0.897461 -2 5 25 0 0.237549 0.90625 -2 5 26 0 0.23999 0.915527 -2 5 27 0 0.242676 0.92627 -2 5 28 0 0.245728 0.937988 -2 5 29 0 0.249023 0.950684 -2 5 30 0 0.252441 0.963867 -2 5 31 0 0.255859 0.977051 -2 6 0 0 0.0668945 0.00705719 -2 6 1 0 0.0668945 0.0161285 -2 6 2 0 0.0668945 0.0233917 -2 6 3 0 0.0669556 0.0312805 -2 6 4 0 0.0670166 0.0408936 -2 6 5 0 0.0673218 0.0531006 -2 6 6 0 0.067688 0.0684204 -2 6 7 0 0.0678711 0.0876465 -2 6 8 0 0.0684204 0.111755 -2 6 9 0 0.0703125 0.142578 -2 6 10 0 0.0752563 0.182983 -2 6 11 0 0.0837402 0.235107 -2 6 12 0 0.0949707 0.296387 -2 6 13 0 0.10907 0.365723 -2 6 14 0 0.125854 0.442139 -2 6 15 0 0.144653 0.523926 -2 6 16 0 0.165039 0.608398 -2 6 17 0 0.184937 0.689941 -2 6 18 0 0.203613 0.764648 -2 6 19 0 0.220093 0.830566 -2 6 20 0 0.229126 0.867188 -2 6 21 0 0.230591 0.874512 -2 6 22 0 0.2323 0.882324 -2 6 23 0 0.234009 0.889648 -2 6 24 0 0.23584 0.897461 -2 6 25 0 0.238037 0.90625 -2 6 26 0 0.240356 0.915527 -2 6 27 0 0.243042 0.92627 -2 6 28 0 0.245972 0.937988 -2 6 29 0 0.249268 0.950684 -2 6 30 0 0.252686 0.963867 -2 6 31 0 0.256104 0.977051 -2 7 0 0 0.0852051 0.00462723 -2 7 1 0 0.0852661 0.00469208 -2 7 2 0 0.0852661 0.0173798 -2 7 3 0 0.0853271 0.0279083 -2 7 4 0 0.0854492 0.0387268 -2 7 5 0 0.0856323 0.0515442 -2 7 6 0 0.0857544 0.0672607 -2 7 7 0 0.0858154 0.086853 -2 7 8 0 0.0858765 0.111389 -2 7 9 0 0.086853 0.142456 -2 7 10 0 0.0906372 0.182739 -2 7 11 0 0.0977783 0.234863 -2 7 12 0 0.107239 0.296143 -2 7 13 0 0.119263 0.365723 -2 7 14 0 0.134033 0.442139 -2 7 15 0 0.151123 0.523926 -2 7 16 0 0.169922 0.608398 -2 7 17 0 0.188843 0.689941 -2 7 18 0 0.206665 0.764648 -2 7 19 0 0.222656 0.830566 -2 7 20 0 0.231201 0.867676 -2 7 21 0 0.232178 0.874512 -2 7 22 0 0.233521 0.882324 -2 7 23 0 0.235107 0.890137 -2 7 24 0 0.236816 0.897461 -2 7 25 0 0.23877 0.90625 -2 7 26 0 0.240967 0.915527 -2 7 27 0 0.24353 0.92627 -2 7 28 0 0.24646 0.937988 -2 7 29 0 0.249634 0.950684 -2 7 30 0 0.25293 0.963867 -2 7 31 0 0.256348 0.977051 -2 8 0 0 0.108276 0 -2 8 1 0 0.108276 0 -2 8 2 0 0.108337 0 -2 8 3 0 0.108398 0.0184021 -2 8 4 0 0.108521 0.0336914 -2 8 5 0 0.108643 0.0481873 -2 8 6 0 0.108887 0.0647583 -2 8 7 0 0.10907 0.085083 -2 8 8 0 0.109009 0.110352 -2 8 9 0 0.109497 0.141968 -2 8 10 0 0.112427 0.182373 -2 8 11 0 0.11853 0.234497 -2 8 12 0 0.126221 0.296143 -2 8 13 0 0.135986 0.365479 -2 8 14 0 0.148071 0.442139 -2 8 15 0 0.162598 0.523926 -2 8 16 0 0.179077 0.608398 -2 8 17 0 0.196045 0.689941 -2 8 18 0 0.212402 0.765137 -2 8 19 0 0.227295 0.831055 -2 8 20 0 0.234985 0.867676 -2 8 21 0 0.235229 0.875 -2 8 22 0 0.235962 0.882324 -2 8 23 0 0.237183 0.890137 -2 8 24 0 0.238647 0.897949 -2 8 25 0 0.240356 0.90625 -2 8 26 0 0.24231 0.915527 -2 8 27 0 0.244751 0.92627 -2 8 28 0 0.247437 0.937988 -2 8 29 0 0.250488 0.950684 -2 8 30 0 0.253662 0.963867 -2 8 31 0 0.25708 0.977051 -2 9 0 0 0.137573 0 -2 9 1 0 0.137573 0 -2 9 2 0 0.137573 0 -2 9 3 0 0.137695 0 -2 9 4 0 0.137695 0.0199127 -2 9 5 0 0.137817 0.0416565 -2 9 6 0 0.137939 0.0604553 -2 9 7 0 0.138306 0.0819702 -2 9 8 0 0.13855 0.108337 -2 9 9 0 0.139282 0.140991 -2 9 10 0 0.141602 0.181763 -2 9 11 0 0.147095 0.233887 -2 9 12 0 0.153442 0.295654 -2 9 13 0 0.161011 0.365234 -2 9 14 0 0.170166 0.442139 -2 9 15 0 0.181519 0.523926 -2 9 16 0 0.194824 0.608398 -2 9 17 0 0.208862 0.689941 -2 9 18 0 0.2229 0.765137 -2 9 19 0 0.23584 0.831055 -2 9 20 0 0.242065 0.868164 -2 9 21 0 0.240845 0.875488 -2 9 22 0 0.240723 0.882812 -2 9 23 0 0.241089 0.890137 -2 9 24 0 0.241943 0.897949 -2 9 25 0 0.243164 0.906738 -2 9 26 0 0.244873 0.916016 -2 9 27 0 0.246826 0.92627 -2 9 28 0 0.249268 0.937988 -2 9 29 0 0.251953 0.950684 -2 9 30 0 0.255127 0.963867 -2 9 31 0 0.258301 0.977539 -2 10 0 0 0.175293 0 -2 10 1 0 0.175415 0 -2 10 2 0 0.175415 0 -2 10 3 0 0.175415 0 -2 10 4 0 0.175415 0 -2 10 5 0 0.175537 0.0246277 -2 10 6 0 0.175537 0.0531921 -2 10 7 0 0.175659 0.0776978 -2 10 8 0 0.175903 0.105713 -2 10 9 0 0.176636 0.139648 -2 10 10 0 0.178833 0.181152 -2 10 11 0 0.183716 0.233154 -2 10 12 0 0.189209 0.294922 -2 10 13 0 0.195068 0.36499 -2 10 14 0 0.20166 0.441895 -2 10 15 0 0.209473 0.523926 -2 10 16 0 0.219116 0.608887 -2 10 17 0 0.229492 0.69043 -2 10 18 0 0.240112 0.765137 -2 10 19 0 0.250244 0.831543 -2 10 20 0 0.25415 0.869141 -2 10 21 0 0.250732 0.875977 -2 10 22 0 0.248779 0.883301 -2 10 23 0 0.248047 0.891113 -2 10 24 0 0.247925 0.898438 -2 10 25 0 0.248291 0.907227 -2 10 26 0 0.249268 0.916504 -2 10 27 0 0.250732 0.926758 -2 10 28 0 0.252686 0.938477 -2 10 29 0 0.254883 0.951172 -2 10 30 0 0.257568 0.964355 -2 10 31 0 0.260254 0.977539 -2 11 0 0 0.224365 0 -2 11 1 0 0.224365 0 -2 11 2 0 0.224365 0 -2 11 3 0 0.224487 0 -2 11 4 0 0.224487 0 -2 11 5 0 0.224487 0 -2 11 6 0 0.224609 0.0342712 -2 11 7 0 0.224487 0.0703735 -2 11 8 0 0.224365 0.102356 -2 11 9 0 0.224609 0.138428 -2 11 10 0 0.226196 0.18103 -2 11 11 0 0.229492 0.232422 -2 11 12 0 0.234009 0.293945 -2 11 13 0 0.238525 0.364258 -2 11 14 0 0.243042 0.44165 -2 11 15 0 0.247925 0.523926 -2 11 16 0 0.253662 0.608887 -2 11 17 0 0.259766 0.690918 -2 11 18 0 0.266357 0.765625 -2 11 19 0 0.272705 0.832031 -2 11 20 0 0.273438 0.870605 -2 11 21 0 0.266602 0.877441 -2 11 22 0 0.262207 0.884277 -2 11 23 0 0.259521 0.89209 -2 11 24 0 0.257812 0.899414 -2 11 25 0 0.25708 0.907715 -2 11 26 0 0.256836 0.916992 -2 11 27 0 0.25708 0.927246 -2 11 28 0 0.258301 0.938965 -2 11 29 0 0.259766 0.95166 -2 11 30 0 0.261719 0.964355 -2 11 31 0 0.263916 0.978027 -2 12 0 0 0.283936 0 -2 12 1 0 0.283936 0 -2 12 2 0 0.283936 0 -2 12 3 0 0.283936 0 -2 12 4 0 0.283936 0 -2 12 5 0 0.283936 0 -2 12 6 0 0.283936 0 -2 12 7 0 0.28418 0.0504761 -2 12 8 0 0.28418 0.0944824 -2 12 9 0 0.28418 0.135132 -2 12 10 0 0.284668 0.17981 -2 12 11 0 0.286133 0.231567 -2 12 12 0 0.289062 0.292725 -2 12 13 0 0.29248 0.363037 -2 12 14 0 0.295166 0.440674 -2 12 15 0 0.297363 0.523438 -2 12 16 0 0.299561 0.608887 -2 12 17 0 0.301514 0.691406 -2 12 18 0 0.303467 0.766602 -2 12 19 0 0.305664 0.83252 -2 12 20 0 0.30249 0.873047 -2 12 21 0 0.291016 0.879395 -2 12 22 0 0.282959 0.88623 -2 12 23 0 0.277344 0.893555 -2 12 24 0 0.273682 0.900879 -2 12 25 0 0.270752 0.90918 -2 12 26 0 0.268799 0.918457 -2 12 27 0 0.267822 0.928223 -2 12 28 0 0.267578 0.939941 -2 12 29 0 0.267822 0.952148 -2 12 30 0 0.268799 0.965332 -2 12 31 0 0.27002 0.978516 -2 13 0 0 0.351318 0 -2 13 1 0 0.351318 0 -2 13 2 0 0.351318 0 -2 13 3 0 0.351562 0 -2 13 4 0 0.351562 0 -2 13 5 0 0.351562 0 -2 13 6 0 0.351562 0 -2 13 7 0 0.351807 0 -2 13 8 0 0.351807 0.0742798 -2 13 9 0 0.352051 0.125854 -2 13 10 0 0.352295 0.174927 -2 13 11 0 0.353027 0.22876 -2 13 12 0 0.354248 0.290527 -2 13 13 0 0.356201 0.36084 -2 13 14 0 0.357666 0.439209 -2 13 15 0 0.35791 0.522461 -2 13 16 0 0.357178 0.608887 -2 13 17 0 0.355225 0.691895 -2 13 18 0 0.352539 0.767578 -2 13 19 0 0.350098 0.833496 -2 13 20 0 0.342773 0.876953 -2 13 21 0 0.325684 0.882812 -2 13 22 0 0.312988 0.889648 -2 13 23 0 0.303711 0.896484 -2 13 24 0 0.297119 0.90332 -2 13 25 0 0.291504 0.911621 -2 13 26 0 0.287354 0.92041 -2 13 27 0 0.283936 0.930176 -2 13 28 0 0.281738 0.941406 -2 13 29 0 0.280273 0.953613 -2 13 30 0 0.279785 0.966309 -2 13 31 0 0.279541 0.979492 -2 14 0 0 0.426758 0 -2 14 1 0 0.426758 0 -2 14 2 0 0.426758 0 -2 14 3 0 0.426758 0 -2 14 4 0 0.426758 0 -2 14 5 0 0.426758 0 -2 14 6 0 0.426758 0 -2 14 7 0 0.427002 0 -2 14 8 0 0.427002 0 -2 14 9 0 0.42749 0.10553 -2 14 10 0 0.427734 0.163818 -2 14 11 0 0.428467 0.221802 -2 14 12 0 0.429199 0.285645 -2 14 13 0 0.430176 0.356934 -2 14 14 0 0.43042 0.435791 -2 14 15 0 0.429199 0.520508 -2 14 16 0 0.426025 0.60791 -2 14 17 0 0.420654 0.691895 -2 14 18 0 0.413818 0.768066 -2 14 19 0 0.406738 0.834961 -2 14 20 0 0.395752 0.882324 -2 14 21 0 0.371826 0.888184 -2 14 22 0 0.35376 0.894531 -2 14 23 0 0.340088 0.900879 -2 14 24 0 0.329834 0.907715 -2 14 25 0 0.321045 0.915039 -2 14 26 0 0.313477 0.923828 -2 14 27 0 0.307373 0.933105 -2 14 28 0 0.30249 0.944336 -2 14 29 0 0.298828 0.956055 -2 14 30 0 0.295898 0.968262 -2 14 31 0 0.293945 0.981445 -2 15 0 0 0.507812 0 -2 15 1 0 0.507812 0 -2 15 2 0 0.507812 0 -2 15 3 0 0.507812 0 -2 15 4 0 0.507812 0 -2 15 5 0 0.507812 0 -2 15 6 0 0.507812 0 -2 15 7 0 0.507812 0 -2 15 8 0 0.507812 0 -2 15 9 0 0.508301 0.046051 -2 15 10 0 0.508789 0.143066 -2 15 11 0 0.509277 0.208618 -2 15 12 0 0.510254 0.276123 -2 15 13 0 0.51123 0.349365 -2 15 14 0 0.51123 0.429688 -2 15 15 0 0.509277 0.516113 -2 15 16 0 0.504883 0.60498 -2 15 17 0 0.496826 0.690918 -2 15 18 0 0.486328 0.768555 -2 15 19 0 0.474854 0.836426 -2 15 20 0 0.461182 0.88916 -2 15 21 0 0.43042 0.895996 -2 15 22 0 0.40625 0.902344 -2 15 23 0 0.387451 0.908203 -2 15 24 0 0.372803 0.914551 -2 15 25 0 0.359863 0.921387 -2 15 26 0 0.348633 0.929199 -2 15 27 0 0.339111 0.937988 -2 15 28 0 0.331055 0.948242 -2 15 29 0 0.324219 0.959473 -2 15 30 0 0.318604 0.97168 -2 15 31 0 0.314209 0.983887 -2 16 0 0 0.592773 0 -2 16 1 0 0.592773 0 -2 16 2 0 0.592773 0 -2 16 3 0 0.592773 0 -2 16 4 0 0.592773 0 -2 16 5 0 0.592773 0 -2 16 6 0 0.592773 0 -2 16 7 0 0.592773 0 -2 16 8 0 0.592773 0 -2 16 9 0 0.592773 0 -2 16 10 0 0.593262 0.101074 -2 16 11 0 0.594238 0.18689 -2 16 12 0 0.595703 0.260498 -2 16 13 0 0.597168 0.33667 -2 16 14 0 0.597656 0.419189 -2 16 15 0 0.596191 0.507324 -2 16 16 0 0.591309 0.598633 -2 16 17 0 0.582031 0.687012 -2 16 18 0 0.568848 0.76709 -2 16 19 0 0.553711 0.836426 -2 16 20 0 0.537598 0.893555 -2 16 21 0 0.501465 0.905762 -2 16 22 0 0.471191 0.913086 -2 16 23 0 0.446777 0.918945 -2 16 24 0 0.427246 0.924805 -2 16 25 0 0.409668 0.930664 -2 16 26 0 0.394043 0.9375 -2 16 27 0 0.380127 0.945312 -2 16 28 0 0.368164 0.955078 -2 16 29 0 0.357666 0.965332 -2 16 30 0 0.348877 0.976562 -2 16 31 0 0.341064 0.987793 -2 17 0 0 0.67627 0 -2 17 1 0 0.67627 0 -2 17 2 0 0.67627 0 -2 17 3 0 0.67627 0 -2 17 4 0 0.67627 0 -2 17 5 0 0.67627 0 -2 17 6 0 0.67627 0 -2 17 7 0 0.67627 0 -2 17 8 0 0.67627 0 -2 17 9 0 0.676758 0 -2 17 10 0 0.676758 0 -2 17 11 0 0.677734 0.151611 -2 17 12 0 0.679688 0.237915 -2 17 13 0 0.681641 0.318848 -2 17 14 0 0.683105 0.403564 -2 17 15 0 0.683105 0.493652 -2 17 16 0 0.679199 0.587402 -2 17 17 0 0.669922 0.678223 -2 17 18 0 0.655762 0.761719 -2 17 19 0 0.638672 0.833984 -2 17 20 0 0.619141 0.893066 -2 17 21 0 0.582031 0.916016 -2 17 22 0 0.546387 0.926758 -2 17 23 0 0.516602 0.933594 -2 17 24 0 0.491699 0.938965 -2 17 25 0 0.468994 0.944336 -2 17 26 0 0.448486 0.950195 -2 17 27 0 0.429688 0.957031 -2 17 28 0 0.41333 0.964844 -2 17 29 0 0.398682 0.973633 -2 17 30 0 0.385986 0.983398 -2 17 31 0 0.374512 0.994141 -2 18 0 0 0.754395 0 -2 18 1 0 0.754395 0 -2 18 2 0 0.754395 0 -2 18 3 0 0.754395 0 -2 18 4 0 0.754395 0 -2 18 5 0 0.754395 0 -2 18 6 0 0.754395 0 -2 18 7 0 0.754395 0 -2 18 8 0 0.754395 0 -2 18 9 0 0.754883 0 -2 18 10 0 0.754883 0 -2 18 11 0 0.755371 0.0775146 -2 18 12 0 0.757324 0.206421 -2 18 13 0 0.759766 0.294922 -2 18 14 0 0.762207 0.382812 -2 18 15 0 0.763672 0.474365 -2 18 16 0 0.762207 0.570312 -2 18 17 0 0.754883 0.664551 -2 18 18 0 0.742188 0.751465 -2 18 19 0 0.724121 0.827148 -2 18 20 0 0.702637 0.889648 -2 18 21 0 0.66748 0.924316 -2 18 22 0 0.629395 0.941406 -2 18 23 0 0.594727 0.951172 -2 18 24 0 0.564941 0.957031 -2 18 25 0 0.537109 0.962402 -2 18 26 0 0.510742 0.966797 -2 18 27 0 0.487061 0.972168 -2 18 28 0 0.465576 0.978516 -2 18 29 0 0.446289 0.985352 -2 18 30 0 0.428955 0.993652 -2 18 31 0 0.413574 1 -2 19 0 0 0.824707 0 -2 19 1 0 0.824707 0 -2 19 2 0 0.824707 0 -2 19 3 0 0.824707 0 -2 19 4 0 0.824707 0 -2 19 5 0 0.824707 0 -2 19 6 0 0.824707 0 -2 19 7 0 0.824707 0 -2 19 8 0 0.824707 0 -2 19 9 0 0.824707 0 -2 19 10 0 0.824707 0 -2 19 11 0 0.825195 0 -2 19 12 0 0.82666 0.162231 -2 19 13 0 0.82959 0.266113 -2 19 14 0 0.83252 0.358154 -2 19 15 0 0.835449 0.451416 -2 19 16 0 0.835938 0.54834 -2 19 17 0 0.832031 0.64502 -2 19 18 0 0.821777 0.73584 -2 19 19 0 0.805176 0.81543 -2 19 20 0 0.783691 0.881348 -2 19 21 0 0.751953 0.927246 -2 19 22 0 0.714355 0.953613 -2 19 23 0 0.677246 0.968262 -2 19 24 0 0.643555 0.977051 -2 19 25 0 0.610352 0.982422 -2 19 26 0 0.579102 0.986816 -2 19 27 0 0.549805 0.990723 -2 19 28 0 0.522949 0.995117 -2 19 29 0 0.498535 1 -2 19 30 0 0.476562 1 -2 19 31 0 0.456787 1 -2 20 0 0 0.885254 0 -2 20 1 0 0.885254 0 -2 20 2 0 0.885254 0 -2 20 3 0 0.885254 0 -2 20 4 0 0.885254 0 -2 20 5 0 0.885254 0 -2 20 6 0 0.885254 0 -2 20 7 0 0.885254 0 -2 20 8 0 0.885254 0 -2 20 9 0 0.885254 0 -2 20 10 0 0.885254 0 -2 20 11 0 0.885742 0 -2 20 12 0 0.88623 0.0790405 -2 20 13 0 0.88916 0.231934 -2 20 14 0 0.893066 0.330811 -2 20 15 0 0.896973 0.42627 -2 20 16 0 0.899414 0.524414 -2 20 17 0 0.898438 0.62207 -2 20 18 0 0.891113 0.715332 -2 20 19 0 0.876953 0.797852 -2 20 20 0 0.856934 0.867676 -2 20 21 0 0.830078 0.922852 -2 20 22 0 0.79541 0.959961 -2 20 23 0 0.758301 0.981445 -2 20 24 0 0.722656 0.994141 -2 20 25 0 0.686035 1 -2 20 26 0 0.649902 1 -2 20 27 0 0.615723 1 -2 20 28 0 0.583496 1 -2 20 29 0 0.553711 1 -2 20 30 0 0.526855 1 -2 20 31 0 0.502441 1 -2 21 0 0 0.936523 0 -2 21 1 0 0.936523 0 -2 21 2 0 0.936523 0 -2 21 3 0 0.936523 0 -2 21 4 0 0.936523 0 -2 21 5 0 0.936523 0 -2 21 6 0 0.936523 0 -2 21 7 0 0.936523 0 -2 21 8 0 0.936523 0 -2 21 9 0 0.936523 0 -2 21 10 0 0.937012 0 -2 21 11 0 0.937012 0 -2 21 12 0 0.937012 0 -2 21 13 0 0.939453 0.189331 -2 21 14 0 0.943848 0.300537 -2 21 15 0 0.94873 0.398682 -2 21 16 0 0.952637 0.497314 -2 21 17 0 0.954102 0.595703 -2 21 18 0 0.950195 0.69043 -2 21 19 0 0.939453 0.775879 -2 21 20 0 0.922363 0.849121 -2 21 21 0 0.899414 0.910645 -2 21 22 0 0.869629 0.957031 -2 21 23 0 0.835449 0.987305 -2 21 24 0 0.799805 1 -2 21 25 0 0.76123 1 -2 21 26 0 0.722168 1 -2 21 27 0 0.683594 1 -2 21 28 0 0.646484 1 -2 21 29 0 0.611816 1 -2 21 30 0 0.580078 1 -2 21 31 0 0.550781 1 -2 22 0 0 0.979492 0 -2 22 1 0 0.979492 0 -2 22 2 0 0.979492 0 -2 22 3 0 0.979492 0 -2 22 4 0 0.979492 0 -2 22 5 0 0.979492 0 -2 22 6 0 0.979492 0 -2 22 7 0 0.979492 0 -2 22 8 0 0.979492 0 -2 22 9 0 0.979492 0 -2 22 10 0 0.979492 0 -2 22 11 0 0.979492 0 -2 22 12 0 0.97998 0 -2 22 13 0 0.981445 0.128296 -2 22 14 0 0.985352 0.267334 -2 22 15 0 0.990723 0.369873 -2 22 16 0 0.996094 0.469238 -2 22 17 0 0.999512 0.567871 -2 22 18 0 0.999023 0.662598 -2 22 19 0 0.991699 0.750488 -2 22 20 0 0.978027 0.82666 -2 22 21 0 0.958008 0.891602 -2 22 22 0 0.933105 0.944824 -2 22 23 0 0.90332 0.983398 -2 22 24 0 0.870117 1 -2 22 25 0 0.83252 1 -2 22 26 0 0.791992 1 -2 22 27 0 0.750488 1 -2 22 28 0 0.709961 1 -2 22 29 0 0.670898 1 -2 22 30 0 0.634277 1 -2 22 31 0 0.600586 1 -2 23 0 0 1 0 -2 23 1 0 1 0 -2 23 2 0 1 0 -2 23 3 0 1 0 -2 23 4 0 1 0 -2 23 5 0 1 0 -2 23 6 0 1 0 -2 23 7 0 1 0 -2 23 8 0 1 0 -2 23 9 0 1 0 -2 23 10 0 1 0 -2 23 11 0 1 0 -2 23 12 0 1 0 -2 23 13 0 1 0 -2 23 14 0 1 0.231689 -2 23 15 0 1 0.341064 -2 23 16 0 1 0.44165 -2 23 17 0 1 0.539551 -2 23 18 0 1 0.634766 -2 23 19 0 1 0.723145 -2 23 20 0 1 0.80127 -2 23 21 0 1 0.869629 -2 23 22 0 0.984375 0.92627 -2 23 23 0 0.958984 0.970703 -2 23 24 0 0.929688 1 -2 23 25 0 0.89502 1 -2 23 26 0 0.85498 1 -2 23 27 0 0.8125 1 -2 23 28 0 0.769531 1 -2 23 29 0 0.727539 1 -2 23 30 0 0.687012 1 -2 23 31 0 0.648926 1 -2 24 0 0 1 0 -2 24 1 0 1 0 -2 24 2 0 1 0 -2 24 3 0 1 0 -2 24 4 0 1 0 -2 24 5 0 1 0 -2 24 6 0 1 0 -2 24 7 0 1 0 -2 24 8 0 1 0 -2 24 9 0 1 0 -2 24 10 0 1 0 -2 24 11 0 1 0 -2 24 12 0 1 0 -2 24 13 0 1 0 -2 24 14 0 1 0.191284 -2 24 15 0 1 0.312012 -2 24 16 0 1 0.414307 -2 24 17 0 1 0.512207 -2 24 18 0 1 0.606934 -2 24 19 0 1 0.695312 -2 24 20 0 1 0.774414 -2 24 21 0 1 0.845215 -2 24 22 0 1 0.904785 -2 24 23 0 1 0.953125 -2 24 24 0 0.979004 0.991699 -2 24 25 0 0.948242 1 -2 24 26 0 0.911133 1 -2 24 27 0 0.869141 1 -2 24 28 0 0.825195 1 -2 24 29 0 0.780762 1 -2 24 30 0 0.737305 1 -2 24 31 0 0.695801 1 -2 25 0 0 1 0 -2 25 1 0 1 0 -2 25 2 0 1 0 -2 25 3 0 1 0 -2 25 4 0 1 0 -2 25 5 0 1 0 -2 25 6 0 1 0 -2 25 7 0 1 0 -2 25 8 0 1 0 -2 25 9 0 1 0 -2 25 10 0 1 0 -2 25 11 0 1 0 -2 25 12 0 1 0 -2 25 13 0 1 0 -2 25 14 0 1 0.132568 -2 25 15 0 1 0.279541 -2 25 16 0 1 0.38501 -2 25 17 0 1 0.482666 -2 25 18 0 1 0.576172 -2 25 19 0 1 0.664062 -2 25 20 0 1 0.744141 -2 25 21 0 1 0.816406 -2 25 22 0 1 0.878906 -2 25 23 0 1 0.930176 -2 25 24 0 1 0.972656 -2 25 25 0 0.99707 1 -2 25 26 0 0.963379 1 -2 25 27 0 0.924316 1 -2 25 28 0 0.880371 1 -2 25 29 0 0.834961 1 -2 25 30 0 0.789551 1 -2 25 31 0 0.745117 1 -2 26 0 0 1 0 -2 26 1 0 1 0 -2 26 2 0 1 0 -2 26 3 0 1 0 -2 26 4 0 1 0 -2 26 5 0 1 0 -2 26 6 0 1 0 -2 26 7 0 1 0 -2 26 8 0 1 0 -2 26 9 0 1 0 -2 26 10 0 1 0 -2 26 11 0 1 0 -2 26 12 0 1 0 -2 26 13 0 1 0 -2 26 14 0 1 0 -2 26 15 0 1 0.241943 -2 26 16 0 1 0.353027 -2 26 17 0 1 0.451172 -2 26 18 0 1 0.543457 -2 26 19 0 1 0.630859 -2 26 20 0 1 0.710938 -2 26 21 0 1 0.783691 -2 26 22 0 1 0.848633 -2 26 23 0 1 0.902832 -2 26 24 0 1 0.948242 -2 26 25 0 1 0.989258 -2 26 26 0 1 1 -2 26 27 0 0.976074 1 -2 26 28 0 0.93457 1 -2 26 29 0 0.889648 1 -2 26 30 0 0.842773 1 -2 26 31 0 0.796387 1 -2 27 0 0 1 0 -2 27 1 0 1 0 -2 27 2 0 1 0 -2 27 3 0 1 0 -2 27 4 0 1 0 -2 27 5 0 1 0 -2 27 6 0 1 0 -2 27 7 0 1 0 -2 27 8 0 1 0 -2 27 9 0 1 0 -2 27 10 0 1 0 -2 27 11 0 1 0 -2 27 12 0 1 0 -2 27 13 0 1 0 -2 27 14 0 1 0 -2 27 15 0 1 0.195557 -2 27 16 0 1 0.318604 -2 27 17 0 1 0.417725 -2 27 18 0 1 0.509277 -2 27 19 0 1 0.595215 -2 27 20 0 1 0.674805 -2 27 21 0 1 0.748047 -2 27 22 0 1 0.813965 -2 27 23 0 1 0.870605 -2 27 24 0 1 0.918457 -2 27 25 0 1 0.962891 -2 27 26 0 1 1 -2 27 27 0 1 1 -2 27 28 0 0.98584 1 -2 27 29 0 0.941895 1 -2 27 30 0 0.895508 1 -2 27 31 0 0.848145 1 -2 28 0 0 1 0 -2 28 1 0 1 0 -2 28 2 0 1 0 -2 28 3 0 1 0 -2 28 4 0 1 0 -2 28 5 0 1 0 -2 28 6 0 1 0 -2 28 7 0 1 0 -2 28 8 0 1 0 -2 28 9 0 1 0 -2 28 10 0 1 0 -2 28 11 0 1 0 -2 28 12 0 1 0 -2 28 13 0 1 0 -2 28 14 0 1 0 -2 28 15 0 1 0.126831 -2 28 16 0 1 0.280518 -2 28 17 0 1 0.382568 -2 28 18 0 1 0.473877 -2 28 19 0 1 0.558105 -2 28 20 0 1 0.63623 -2 28 21 0 1 0.709473 -2 28 22 0 1 0.775879 -2 28 23 0 1 0.833496 -2 28 24 0 1 0.883789 -2 28 25 0 1 0.931152 -2 28 26 0 1 0.974609 -2 28 27 0 1 1 -2 28 28 0 1 1 -2 28 29 0 0.991699 1 -2 28 30 0 0.947266 1 -2 28 31 0 0.899902 1 -2 29 0 0 1 0 -2 29 1 0 1 0 -2 29 2 0 1 0 -2 29 3 0 1 0 -2 29 4 0 1 0 -2 29 5 0 1 0 -2 29 6 0 1 0 -2 29 7 0 1 0 -2 29 8 0 1 0 -2 29 9 0 1 0 -2 29 10 0 1 0 -2 29 11 0 1 0 -2 29 12 0 1 0 -2 29 13 0 1 0 -2 29 14 0 1 0 -2 29 15 0 1 0 -2 29 16 0 1 0.236572 -2 29 17 0 1 0.345215 -2 29 18 0 1 0.436279 -2 29 19 0 1 0.519531 -2 29 20 0 1 0.596191 -2 29 21 0 1 0.667969 -2 29 22 0 1 0.733887 -2 29 23 0 1 0.79248 -2 29 24 0 1 0.84375 -2 29 25 0 1 0.893555 -2 29 26 0 1 0.94043 -2 29 27 0 1 0.98291 -2 29 28 0 1 1 -2 29 29 0 1 1 -2 29 30 0 0.996582 1 -2 29 31 0 0.951172 1 -2 30 0 0 1 0 -2 30 1 0 1 0 -2 30 2 0 1 0 -2 30 3 0 1 0 -2 30 4 0 1 0 -2 30 5 0 1 0 -2 30 6 0 1 0 -2 30 7 0 1 0 -2 30 8 0 1 0 -2 30 9 0 1 0 -2 30 10 0 1 0 -2 30 11 0 1 0 -2 30 12 0 1 0 -2 30 13 0 1 0 -2 30 14 0 1 0 -2 30 15 0 1 0 -2 30 16 0 1 0.182007 -2 30 17 0 1 0.304688 -2 30 18 0 1 0.397217 -2 30 19 0 1 0.479248 -2 30 20 0 1 0.554199 -2 30 21 0 1 0.624512 -2 30 22 0 1 0.689453 -2 30 23 0 1 0.747559 -2 30 24 0 1 0.799805 -2 30 25 0 1 0.850586 -2 30 26 0 1 0.899902 -2 30 27 0 1 0.946289 -2 30 28 0 1 0.988281 -2 30 29 0 1 1 -2 30 30 0 1 1 -2 30 31 0 1 1 -2 31 0 0 1 0 -2 31 1 0 1 0 -2 31 2 0 1 0 -2 31 3 0 1 0 -2 31 4 0 1 0 -2 31 5 0 1 0 -2 31 6 0 1 0 -2 31 7 0 1 0 -2 31 8 0 1 0 -2 31 9 0 1 0 -2 31 10 0 1 0 -2 31 11 0 1 0 -2 31 12 0 1 0 -2 31 13 0 1 0 -2 31 14 0 1 0 -2 31 15 0 1 0 -2 31 16 0 1 0.0875244 -2 31 17 0 1 0.260742 -2 31 18 0 1 0.356934 -2 31 19 0 1 0.438232 -2 31 20 0 1 0.51123 -2 31 21 0 1 0.57959 -2 31 22 0 1 0.643066 -2 31 23 0 1 0.700684 -2 31 24 0 1 0.752441 -2 31 25 0 1 0.804199 -2 31 26 0 1 0.855469 -2 31 27 0 1 0.904785 -2 31 28 0 1 0.951172 -2 31 29 0 1 0.992676 -2 31 30 0 1 1 -2 31 31 0 1 1 -3 0 0 0.0397644 0.0189362 0.0171509 -3 0 1 0.0387878 0.0184021 0.021698 -3 0 2 0.0338135 0.0168762 0.0244446 -3 0 3 0.0303497 0.0170288 0.0280304 -3 0 4 0.0322876 0.0198364 0.0395508 -3 0 5 0.0298615 0.0224762 0.0536804 -3 0 6 0.0131912 0.0249176 0.069458 -3 0 7 0 0.0280914 0.0881958 -3 0 8 0 0.0328674 0.112 -3 0 9 0 0.039856 0.142944 -3 0 10 0 0.0497131 0.18335 -3 0 11 0 0.0628052 0.235352 -3 0 12 0 0.0784912 0.296387 -3 0 13 0 0.0963745 0.365723 -3 0 14 0 0.116211 0.442139 -3 0 15 0 0.137451 0.523926 -3 0 16 0 0.159424 0.608398 -3 0 17 0 0.180786 0.689941 -3 0 18 0 0.200317 0.764648 -3 0 19 0 0.217529 0.830566 -3 0 20 0 0.227051 0.867188 -3 0 21 0 0.228882 0.874512 -3 0 22 0 0.230957 0.881836 -3 0 23 0 0.23291 0.889648 -3 0 24 0 0.234985 0.897461 -3 0 25 0 0.237183 0.90625 -3 0 26 0 0.239624 0.915527 -3 0 27 0 0.242432 0.925781 -3 0 28 0 0.245483 0.937988 -3 0 29 0 0.248779 0.950684 -3 0 30 0 0.252197 0.963867 -3 0 31 0 0.255859 0.977051 -3 1 0 0.036499 0.0214996 0.0160828 -3 1 1 0.0372925 0.0218964 0.0209503 -3 1 2 0.0350037 0.0208893 0.0254211 -3 1 3 0.0300293 0.0195618 0.0280609 -3 1 4 0.0317688 0.0225067 0.0394897 -3 1 5 0.0291595 0.025116 0.0536194 -3 1 6 0.0100098 0.027298 0.069397 -3 1 7 0 0.0300446 0.0881958 -3 1 8 0 0.0343628 0.112 -3 1 9 0 0.0409241 0.142944 -3 1 10 0 0.0504761 0.18335 -3 1 11 0 0.0634155 0.235352 -3 1 12 0 0.0789185 0.296387 -3 1 13 0 0.0966797 0.365723 -3 1 14 0 0.116394 0.442139 -3 1 15 0 0.137573 0.523926 -3 1 16 0 0.159546 0.608398 -3 1 17 0 0.180786 0.689941 -3 1 18 0 0.200317 0.764648 -3 1 19 0 0.217529 0.830566 -3 1 20 0 0.227051 0.867188 -3 1 21 0 0.229004 0.874512 -3 1 22 0 0.230957 0.881836 -3 1 23 0 0.23291 0.889648 -3 1 24 0 0.234985 0.897461 -3 1 25 0 0.237183 0.90625 -3 1 26 0 0.239624 0.915527 -3 1 27 0 0.242432 0.925781 -3 1 28 0 0.245483 0.937988 -3 1 29 0 0.248779 0.950684 -3 1 30 0 0.252197 0.963867 -3 1 31 0 0.255859 0.977051 -3 2 0 0.0310364 0.0227814 0.0148163 -3 2 1 0.0317688 0.0234985 0.018631 -3 2 2 0.0342102 0.0255585 0.0251923 -3 2 3 0.0296021 0.0232849 0.0282745 -3 2 4 0.0308685 0.0263214 0.0394592 -3 2 5 0.0278625 0.0289459 0.0535583 -3 2 6 0 0.0308533 0.069397 -3 2 7 0 0.0330811 0.0881348 -3 2 8 0 0.0367737 0.112 -3 2 9 0 0.0427551 0.142822 -3 2 10 0 0.0518494 0.18335 -3 2 11 0 0.0643921 0.235352 -3 2 12 0 0.0796509 0.296387 -3 2 13 0 0.097229 0.365723 -3 2 14 0 0.116821 0.442139 -3 2 15 0 0.137817 0.523926 -3 2 16 0 0.15979 0.608398 -3 2 17 0 0.18103 0.689941 -3 2 18 0 0.200562 0.764648 -3 2 19 0 0.217651 0.830566 -3 2 20 0 0.227173 0.867188 -3 2 21 0 0.229004 0.874512 -3 2 22 0 0.230957 0.881836 -3 2 23 0 0.233032 0.889648 -3 2 24 0 0.234985 0.897461 -3 2 25 0 0.237183 0.90625 -3 2 26 0 0.239624 0.915527 -3 2 27 0 0.242432 0.925781 -3 2 28 0 0.245483 0.937988 -3 2 29 0 0.248779 0.950684 -3 2 30 0 0.252197 0.963867 -3 2 31 0 0.255859 0.977051 -3 3 0 0.0291595 0.0271454 0.0148849 -3 3 1 0.0288544 0.0271759 0.0180054 -3 3 2 0.0287018 0.0275879 0.0223389 -3 3 3 0.0290222 0.0290222 0.0290222 -3 3 4 0.0292206 0.0317993 0.0395813 -3 3 5 0.0251923 0.0343933 0.0534668 -3 3 6 0 0.0360718 0.0693359 -3 3 7 0 0.0377197 0.0881348 -3 3 8 0 0.0406494 0.112 -3 3 9 0 0.0458069 0.142822 -3 3 10 0 0.0541687 0.18335 -3 3 11 0 0.0661621 0.235352 -3 3 12 0 0.0809326 0.296387 -3 3 13 0 0.0981445 0.365723 -3 3 14 0 0.117493 0.442139 -3 3 15 0 0.138428 0.523926 -3 3 16 0 0.160156 0.608398 -3 3 17 0 0.181274 0.689941 -3 3 18 0 0.200684 0.764648 -3 3 19 0 0.217896 0.830566 -3 3 20 0 0.227295 0.867188 -3 3 21 0 0.229126 0.874512 -3 3 22 0 0.231079 0.881836 -3 3 23 0 0.233032 0.889648 -3 3 24 0 0.235107 0.897461 -3 3 25 0 0.237305 0.90625 -3 3 26 0 0.239746 0.915527 -3 3 27 0 0.242432 0.92627 -3 3 28 0 0.245483 0.937988 -3 3 29 0 0.248779 0.950684 -3 3 30 0 0.252197 0.963867 -3 3 31 0 0.255859 0.977051 -3 4 0 0.0298004 0.0380554 0.0158844 -3 4 1 0.0292206 0.0378113 0.0195465 -3 4 2 0.0284119 0.0376892 0.0241852 -3 4 3 0.02742 0.038208 0.0305939 -3 4 4 0.025589 0.039917 0.0401611 -3 4 5 0.0183716 0.0420837 0.0533752 -3 4 6 0 0.0435181 0.0692139 -3 4 7 0 0.0446167 0.0880737 -3 4 8 0 0.0467224 0.112 -3 4 9 0 0.0508423 0.142822 -3 4 10 0 0.058197 0.183228 -3 4 11 0 0.0692749 0.235229 -3 4 12 0 0.083313 0.296387 -3 4 13 0 0.0999756 0.365723 -3 4 14 0 0.118835 0.442139 -3 4 15 0 0.139404 0.523926 -3 4 16 0 0.160889 0.608398 -3 4 17 0 0.181885 0.689941 -3 4 18 0 0.201172 0.764648 -3 4 19 0 0.218262 0.830566 -3 4 20 0 0.227661 0.867188 -3 4 21 0 0.22937 0.874512 -3 4 22 0 0.231201 0.881836 -3 4 23 0 0.233154 0.889648 -3 4 24 0 0.235229 0.897461 -3 4 25 0 0.237427 0.90625 -3 4 26 0 0.239868 0.915527 -3 4 27 0 0.242554 0.92627 -3 4 28 0 0.245605 0.937988 -3 4 29 0 0.248901 0.950684 -3 4 30 0 0.252197 0.963867 -3 4 31 0 0.255859 0.977051 -3 5 0 0.0230713 0.0515137 0.0148163 -3 5 1 0.0223083 0.0513916 0.0195618 -3 5 2 0.0209503 0.051239 0.0250702 -3 5 3 0.018158 0.0512695 0.0319214 -3 5 4 0.00904846 0.0517883 0.0410156 -3 5 5 0 0.0529175 0.0533752 -3 5 6 0 0.0539246 0.0689697 -3 5 7 0 0.0545349 0.0879517 -3 5 8 0 0.0557556 0.111938 -3 5 9 0 0.0587769 0.142822 -3 5 10 0 0.0649414 0.183228 -3 5 11 0 0.0747681 0.235229 -3 5 12 0 0.0876465 0.296387 -3 5 13 0 0.103271 0.365723 -3 5 14 0 0.121338 0.442139 -3 5 15 0 0.141235 0.523926 -3 5 16 0 0.162354 0.608398 -3 5 17 0 0.182983 0.689941 -3 5 18 0 0.202026 0.764648 -3 5 19 0 0.218872 0.830566 -3 5 20 0 0.228149 0.867188 -3 5 21 0 0.229736 0.874512 -3 5 22 0 0.231567 0.882324 -3 5 23 0 0.233521 0.889648 -3 5 24 0 0.235474 0.897461 -3 5 25 0 0.237549 0.90625 -3 5 26 0 0.23999 0.915527 -3 5 27 0 0.242676 0.92627 -3 5 28 0 0.245728 0.937988 -3 5 29 0 0.249023 0.950684 -3 5 30 0 0.252441 0.963867 -3 5 31 0 0.255859 0.977051 -3 6 0 0 0.0670166 0.00963593 -3 6 1 0 0.0670166 0.0164337 -3 6 2 0 0.0670166 0.0235596 -3 6 3 0 0.0670166 0.0314026 -3 6 4 0 0.0671387 0.0409546 -3 6 5 0 0.0673828 0.0531311 -3 6 6 0 0.067749 0.0684814 -3 6 7 0 0.0679932 0.0876465 -3 6 8 0 0.0684814 0.111755 -3 6 9 0 0.0704346 0.1427 -3 6 10 0 0.0753174 0.182983 -3 6 11 0 0.0838013 0.235107 -3 6 12 0 0.0950317 0.296387 -3 6 13 0 0.109131 0.365723 -3 6 14 0 0.125854 0.442139 -3 6 15 0 0.144775 0.523926 -3 6 16 0 0.165039 0.608398 -3 6 17 0 0.184937 0.689941 -3 6 18 0 0.203613 0.764648 -3 6 19 0 0.220215 0.830566 -3 6 20 0 0.229248 0.867188 -3 6 21 0 0.230591 0.874512 -3 6 22 0 0.2323 0.882324 -3 6 23 0 0.234009 0.889648 -3 6 24 0 0.235962 0.897461 -3 6 25 0 0.238037 0.90625 -3 6 26 0 0.240356 0.915527 -3 6 27 0 0.243042 0.92627 -3 6 28 0 0.245972 0.937988 -3 6 29 0 0.249268 0.950684 -3 6 30 0 0.252686 0.963867 -3 6 31 0 0.256104 0.977051 -3 7 0 0 0.0853271 0.00836945 -3 7 1 0 0.0853271 0.00839233 -3 7 2 0 0.0853882 0.0176392 -3 7 3 0 0.0854492 0.0280304 -3 7 4 0 0.0855103 0.0387878 -3 7 5 0 0.0856934 0.0516052 -3 7 6 0 0.0858765 0.0672607 -3 7 7 0 0.0858765 0.086853 -3 7 8 0 0.0859375 0.111389 -3 7 9 0 0.0869141 0.142456 -3 7 10 0 0.0906982 0.182739 -3 7 11 0 0.0978394 0.234863 -3 7 12 0 0.1073 0.296143 -3 7 13 0 0.119324 0.365723 -3 7 14 0 0.134033 0.442139 -3 7 15 0 0.151123 0.523926 -3 7 16 0 0.170044 0.608398 -3 7 17 0 0.188843 0.689941 -3 7 18 0 0.206665 0.764648 -3 7 19 0 0.222656 0.830566 -3 7 20 0 0.231201 0.867676 -3 7 21 0 0.232178 0.874512 -3 7 22 0 0.233521 0.882324 -3 7 23 0 0.235107 0.890137 -3 7 24 0 0.236816 0.897461 -3 7 25 0 0.23877 0.90625 -3 7 26 0 0.240967 0.915527 -3 7 27 0 0.24353 0.92627 -3 7 28 0 0.24646 0.937988 -3 7 29 0 0.249634 0.950684 -3 7 30 0 0.25293 0.963867 -3 7 31 0 0.256348 0.977051 -3 8 0 0 0.108337 0.00427628 -3 8 1 0 0.108337 0.00434494 -3 8 2 0 0.108398 0.00446701 -3 8 3 0 0.108459 0.018631 -3 8 4 0 0.108521 0.033783 -3 8 5 0 0.108704 0.0482483 -3 8 6 0 0.108948 0.0648193 -3 8 7 0 0.10907 0.085144 -3 8 8 0 0.10907 0.110413 -3 8 9 0 0.109558 0.141968 -3 8 10 0 0.112427 0.182373 -3 8 11 0 0.11853 0.234497 -3 8 12 0 0.126221 0.296143 -3 8 13 0 0.135986 0.365479 -3 8 14 0 0.148071 0.442139 -3 8 15 0 0.162598 0.523926 -3 8 16 0 0.179077 0.608398 -3 8 17 0 0.196167 0.689941 -3 8 18 0 0.212402 0.765137 -3 8 19 0 0.227295 0.831055 -3 8 20 0 0.234985 0.867676 -3 8 21 0 0.235229 0.875 -3 8 22 0 0.236084 0.882324 -3 8 23 0 0.237183 0.890137 -3 8 24 0 0.238647 0.897949 -3 8 25 0 0.240356 0.90625 -3 8 26 0 0.24231 0.915527 -3 8 27 0 0.244751 0.92627 -3 8 28 0 0.247437 0.937988 -3 8 29 0 0.250488 0.950684 -3 8 30 0 0.253662 0.963867 -3 8 31 0 0.25708 0.977051 -3 9 0 0 0.137573 0 -3 9 1 0 0.137573 0 -3 9 2 0 0.137695 0 -3 9 3 0 0.137695 0 -3 9 4 0 0.137695 0.0201111 -3 9 5 0 0.137817 0.0417175 -3 9 6 0 0.138062 0.0604858 -3 9 7 0 0.138306 0.0819702 -3 9 8 0 0.13855 0.108337 -3 9 9 0 0.139282 0.140991 -3 9 10 0 0.141602 0.181763 -3 9 11 0 0.147095 0.233887 -3 9 12 0 0.153564 0.295654 -3 9 13 0 0.161011 0.365234 -3 9 14 0 0.170166 0.442139 -3 9 15 0 0.181519 0.523926 -3 9 16 0 0.194824 0.608398 -3 9 17 0 0.208984 0.689941 -3 9 18 0 0.2229 0.765137 -3 9 19 0 0.23584 0.831055 -3 9 20 0 0.242065 0.868164 -3 9 21 0 0.240845 0.875488 -3 9 22 0 0.240723 0.882812 -3 9 23 0 0.241089 0.890137 -3 9 24 0 0.241943 0.897949 -3 9 25 0 0.243164 0.906738 -3 9 26 0 0.244873 0.916016 -3 9 27 0 0.246826 0.92627 -3 9 28 0 0.249268 0.937988 -3 9 29 0 0.252197 0.950684 -3 9 30 0 0.255127 0.963867 -3 9 31 0 0.258301 0.977539 -3 10 0 0 0.175415 0 -3 10 1 0 0.175415 0 -3 10 2 0 0.175415 0 -3 10 3 0 0.175415 0 -3 10 4 0 0.175415 0 -3 10 5 0 0.175537 0.024765 -3 10 6 0 0.175537 0.0532227 -3 10 7 0 0.175659 0.0776978 -3 10 8 0 0.175903 0.105713 -3 10 9 0 0.176636 0.139648 -3 10 10 0 0.178833 0.181152 -3 10 11 0 0.183716 0.233154 -3 10 12 0 0.189209 0.294922 -3 10 13 0 0.195068 0.36499 -3 10 14 0 0.20166 0.441895 -3 10 15 0 0.209595 0.523926 -3 10 16 0 0.219116 0.608887 -3 10 17 0 0.229492 0.69043 -3 10 18 0 0.240112 0.765625 -3 10 19 0 0.250244 0.831543 -3 10 20 0 0.25415 0.869141 -3 10 21 0 0.250732 0.875977 -3 10 22 0 0.248779 0.883301 -3 10 23 0 0.248047 0.891113 -3 10 24 0 0.247925 0.898438 -3 10 25 0 0.248291 0.907227 -3 10 26 0 0.249268 0.916504 -3 10 27 0 0.250732 0.926758 -3 10 28 0 0.252686 0.938477 -3 10 29 0 0.254883 0.951172 -3 10 30 0 0.257568 0.964355 -3 10 31 0 0.260254 0.977539 -3 11 0 0 0.224365 0 -3 11 1 0 0.224365 0 -3 11 2 0 0.224365 0 -3 11 3 0 0.224487 0 -3 11 4 0 0.224487 0 -3 11 5 0 0.224487 0 -3 11 6 0 0.224609 0.0343628 -3 11 7 0 0.224487 0.0704346 -3 11 8 0 0.224365 0.102356 -3 11 9 0 0.224609 0.138428 -3 11 10 0 0.226196 0.18103 -3 11 11 0 0.229492 0.232422 -3 11 12 0 0.234009 0.293945 -3 11 13 0 0.238525 0.364258 -3 11 14 0 0.243042 0.44165 -3 11 15 0 0.247925 0.523926 -3 11 16 0 0.253662 0.608887 -3 11 17 0 0.259766 0.690918 -3 11 18 0 0.266357 0.765625 -3 11 19 0 0.272705 0.832031 -3 11 20 0 0.273438 0.870605 -3 11 21 0 0.266602 0.877441 -3 11 22 0 0.262207 0.884277 -3 11 23 0 0.259521 0.89209 -3 11 24 0 0.257812 0.899414 -3 11 25 0 0.25708 0.907715 -3 11 26 0 0.256836 0.916992 -3 11 27 0 0.25708 0.927246 -3 11 28 0 0.258301 0.938965 -3 11 29 0 0.259766 0.95166 -3 11 30 0 0.261719 0.964355 -3 11 31 0 0.263916 0.978027 -3 12 0 0 0.283936 0 -3 12 1 0 0.283936 0 -3 12 2 0 0.283936 0 -3 12 3 0 0.283936 0 -3 12 4 0 0.283936 0 -3 12 5 0 0.283936 0 -3 12 6 0 0.283936 0 -3 12 7 0 0.28418 0.0505066 -3 12 8 0 0.28418 0.0944824 -3 12 9 0 0.28418 0.135132 -3 12 10 0 0.284668 0.17981 -3 12 11 0 0.286133 0.231567 -3 12 12 0 0.289062 0.292725 -3 12 13 0 0.29248 0.363037 -3 12 14 0 0.295166 0.440674 -3 12 15 0 0.297363 0.523438 -3 12 16 0 0.299561 0.608887 -3 12 17 0 0.301514 0.691406 -3 12 18 0 0.303467 0.766602 -3 12 19 0 0.305664 0.83252 -3 12 20 0 0.30249 0.873047 -3 12 21 0 0.291016 0.879395 -3 12 22 0 0.282959 0.88623 -3 12 23 0 0.277344 0.893555 -3 12 24 0 0.273682 0.900879 -3 12 25 0 0.270752 0.90918 -3 12 26 0 0.268799 0.918457 -3 12 27 0 0.267822 0.928223 -3 12 28 0 0.267578 0.939941 -3 12 29 0 0.267822 0.952148 -3 12 30 0 0.268799 0.965332 -3 12 31 0 0.27002 0.978516 -3 13 0 0 0.351318 0 -3 13 1 0 0.351318 0 -3 13 2 0 0.351562 0 -3 13 3 0 0.351562 0 -3 13 4 0 0.351562 0 -3 13 5 0 0.351562 0 -3 13 6 0 0.351562 0 -3 13 7 0 0.351807 0 -3 13 8 0 0.351807 0.0742798 -3 13 9 0 0.352051 0.125854 -3 13 10 0 0.352295 0.174927 -3 13 11 0 0.353027 0.22876 -3 13 12 0 0.354248 0.290527 -3 13 13 0 0.356201 0.36084 -3 13 14 0 0.357666 0.439209 -3 13 15 0 0.35791 0.522461 -3 13 16 0 0.357178 0.608887 -3 13 17 0 0.355225 0.691895 -3 13 18 0 0.352539 0.767578 -3 13 19 0 0.350098 0.833496 -3 13 20 0 0.342773 0.876953 -3 13 21 0 0.325684 0.882812 -3 13 22 0 0.312988 0.889648 -3 13 23 0 0.303711 0.896484 -3 13 24 0 0.297119 0.90332 -3 13 25 0 0.291504 0.911621 -3 13 26 0 0.287354 0.92041 -3 13 27 0 0.283936 0.930176 -3 13 28 0 0.281738 0.941406 -3 13 29 0 0.280273 0.953613 -3 13 30 0 0.279785 0.966309 -3 13 31 0 0.279541 0.979492 -3 14 0 0 0.426758 0 -3 14 1 0 0.426758 0 -3 14 2 0 0.426758 0 -3 14 3 0 0.426758 0 -3 14 4 0 0.426758 0 -3 14 5 0 0.426758 0 -3 14 6 0 0.426758 0 -3 14 7 0 0.427002 0 -3 14 8 0 0.427002 0 -3 14 9 0 0.42749 0.10553 -3 14 10 0 0.427734 0.163818 -3 14 11 0 0.428467 0.221802 -3 14 12 0 0.429199 0.285645 -3 14 13 0 0.430176 0.356934 -3 14 14 0 0.43042 0.435791 -3 14 15 0 0.429199 0.520508 -3 14 16 0 0.426025 0.60791 -3 14 17 0 0.420654 0.691895 -3 14 18 0 0.413818 0.768066 -3 14 19 0 0.406738 0.834961 -3 14 20 0 0.395752 0.882324 -3 14 21 0 0.371826 0.888184 -3 14 22 0 0.35376 0.894531 -3 14 23 0 0.340088 0.900879 -3 14 24 0 0.329834 0.907715 -3 14 25 0 0.321045 0.915039 -3 14 26 0 0.313477 0.923828 -3 14 27 0 0.307373 0.933105 -3 14 28 0 0.30249 0.944336 -3 14 29 0 0.298828 0.956055 -3 14 30 0 0.295898 0.968262 -3 14 31 0 0.293945 0.981445 -3 15 0 0 0.507812 0 -3 15 1 0 0.507812 0 -3 15 2 0 0.507812 0 -3 15 3 0 0.507812 0 -3 15 4 0 0.507812 0 -3 15 5 0 0.507812 0 -3 15 6 0 0.507812 0 -3 15 7 0 0.507812 0 -3 15 8 0 0.507812 0 -3 15 9 0 0.508301 0.0461121 -3 15 10 0 0.508789 0.143066 -3 15 11 0 0.509766 0.208618 -3 15 12 0 0.510742 0.276123 -3 15 13 0 0.51123 0.349365 -3 15 14 0 0.51123 0.429688 -3 15 15 0 0.509277 0.516113 -3 15 16 0 0.504883 0.60498 -3 15 17 0 0.496826 0.690918 -3 15 18 0 0.486328 0.768555 -3 15 19 0 0.474854 0.836426 -3 15 20 0 0.461182 0.88916 -3 15 21 0 0.43042 0.895996 -3 15 22 0 0.40625 0.902344 -3 15 23 0 0.387451 0.908203 -3 15 24 0 0.372803 0.914551 -3 15 25 0 0.359863 0.921387 -3 15 26 0 0.348633 0.929199 -3 15 27 0 0.339111 0.937988 -3 15 28 0 0.331055 0.948242 -3 15 29 0 0.324219 0.959473 -3 15 30 0 0.318604 0.97168 -3 15 31 0 0.314209 0.983887 -3 16 0 0 0.592773 0 -3 16 1 0 0.592773 0 -3 16 2 0 0.592773 0 -3 16 3 0 0.592773 0 -3 16 4 0 0.592773 0 -3 16 5 0 0.592773 0 -3 16 6 0 0.592773 0 -3 16 7 0 0.592773 0 -3 16 8 0 0.592773 0 -3 16 9 0 0.592773 0 -3 16 10 0 0.593262 0.101135 -3 16 11 0 0.594238 0.18689 -3 16 12 0 0.595703 0.260498 -3 16 13 0 0.597168 0.33667 -3 16 14 0 0.597656 0.419189 -3 16 15 0 0.596191 0.507324 -3 16 16 0 0.591309 0.598633 -3 16 17 0 0.582031 0.687012 -3 16 18 0 0.568848 0.76709 -3 16 19 0 0.553711 0.836426 -3 16 20 0 0.537598 0.893555 -3 16 21 0 0.501465 0.905762 -3 16 22 0 0.471191 0.913086 -3 16 23 0 0.446777 0.918945 -3 16 24 0 0.427246 0.924805 -3 16 25 0 0.409668 0.930664 -3 16 26 0 0.394043 0.9375 -3 16 27 0 0.380127 0.945312 -3 16 28 0 0.368164 0.955078 -3 16 29 0 0.357666 0.965332 -3 16 30 0 0.348877 0.976562 -3 16 31 0 0.341064 0.987793 -3 17 0 0 0.67627 0 -3 17 1 0 0.67627 0 -3 17 2 0 0.67627 0 -3 17 3 0 0.67627 0 -3 17 4 0 0.67627 0 -3 17 5 0 0.67627 0 -3 17 6 0 0.67627 0 -3 17 7 0 0.67627 0 -3 17 8 0 0.67627 0 -3 17 9 0 0.676758 0 -3 17 10 0 0.676758 0 -3 17 11 0 0.677734 0.151611 -3 17 12 0 0.679688 0.237915 -3 17 13 0 0.681641 0.318848 -3 17 14 0 0.683105 0.403564 -3 17 15 0 0.683105 0.493652 -3 17 16 0 0.679199 0.587402 -3 17 17 0 0.669922 0.678223 -3 17 18 0 0.655762 0.761719 -3 17 19 0 0.638672 0.833984 -3 17 20 0 0.619141 0.893066 -3 17 21 0 0.582031 0.916016 -3 17 22 0 0.546387 0.926758 -3 17 23 0 0.516602 0.933594 -3 17 24 0 0.491699 0.938965 -3 17 25 0 0.468994 0.944336 -3 17 26 0 0.448486 0.950195 -3 17 27 0 0.429688 0.957031 -3 17 28 0 0.41333 0.964844 -3 17 29 0 0.398682 0.973633 -3 17 30 0 0.385986 0.983398 -3 17 31 0 0.374512 0.994141 -3 18 0 0 0.754395 0 -3 18 1 0 0.754395 0 -3 18 2 0 0.754395 0 -3 18 3 0 0.754395 0 -3 18 4 0 0.754395 0 -3 18 5 0 0.754395 0 -3 18 6 0 0.754395 0 -3 18 7 0 0.754395 0 -3 18 8 0 0.754395 0 -3 18 9 0 0.754883 0 -3 18 10 0 0.754883 0 -3 18 11 0 0.755371 0.0775146 -3 18 12 0 0.757324 0.206421 -3 18 13 0 0.759766 0.294922 -3 18 14 0 0.762207 0.382812 -3 18 15 0 0.763672 0.474365 -3 18 16 0 0.762207 0.570312 -3 18 17 0 0.754883 0.664551 -3 18 18 0 0.742188 0.751465 -3 18 19 0 0.724121 0.827148 -3 18 20 0 0.702637 0.889648 -3 18 21 0 0.66748 0.924316 -3 18 22 0 0.629395 0.941406 -3 18 23 0 0.594727 0.951172 -3 18 24 0 0.564941 0.957031 -3 18 25 0 0.537109 0.962402 -3 18 26 0 0.510742 0.966797 -3 18 27 0 0.487061 0.972168 -3 18 28 0 0.465576 0.978516 -3 18 29 0 0.446289 0.985352 -3 18 30 0 0.428955 0.993652 -3 18 31 0 0.413574 1 -3 19 0 0 0.824707 0 -3 19 1 0 0.824707 0 -3 19 2 0 0.824707 0 -3 19 3 0 0.824707 0 -3 19 4 0 0.824707 0 -3 19 5 0 0.824707 0 -3 19 6 0 0.824707 0 -3 19 7 0 0.824707 0 -3 19 8 0 0.824707 0 -3 19 9 0 0.824707 0 -3 19 10 0 0.824707 0 -3 19 11 0 0.825195 0 -3 19 12 0 0.82666 0.162231 -3 19 13 0 0.82959 0.266113 -3 19 14 0 0.83252 0.358154 -3 19 15 0 0.835449 0.451416 -3 19 16 0 0.835938 0.54834 -3 19 17 0 0.832031 0.64502 -3 19 18 0 0.821777 0.73584 -3 19 19 0 0.805176 0.81543 -3 19 20 0 0.783691 0.881348 -3 19 21 0 0.751953 0.927246 -3 19 22 0 0.714355 0.953613 -3 19 23 0 0.677246 0.968262 -3 19 24 0 0.643555 0.977051 -3 19 25 0 0.610352 0.982422 -3 19 26 0 0.579102 0.986816 -3 19 27 0 0.549805 0.990723 -3 19 28 0 0.522949 0.995117 -3 19 29 0 0.498535 1 -3 19 30 0 0.476562 1 -3 19 31 0 0.456787 1 -3 20 0 0 0.885254 0 -3 20 1 0 0.885254 0 -3 20 2 0 0.885254 0 -3 20 3 0 0.885254 0 -3 20 4 0 0.885254 0 -3 20 5 0 0.885254 0 -3 20 6 0 0.885254 0 -3 20 7 0 0.885254 0 -3 20 8 0 0.885254 0 -3 20 9 0 0.885254 0 -3 20 10 0 0.885254 0 -3 20 11 0 0.885742 0 -3 20 12 0 0.88623 0.0791016 -3 20 13 0 0.88916 0.231934 -3 20 14 0 0.893066 0.330811 -3 20 15 0 0.896973 0.42627 -3 20 16 0 0.899414 0.524414 -3 20 17 0 0.898438 0.62207 -3 20 18 0 0.891113 0.715332 -3 20 19 0 0.876953 0.797852 -3 20 20 0 0.856934 0.867676 -3 20 21 0 0.830078 0.922852 -3 20 22 0 0.79541 0.959961 -3 20 23 0 0.758301 0.981445 -3 20 24 0 0.722656 0.994141 -3 20 25 0 0.686035 1 -3 20 26 0 0.649902 1 -3 20 27 0 0.615723 1 -3 20 28 0 0.583496 1 -3 20 29 0 0.553711 1 -3 20 30 0 0.526855 1 -3 20 31 0 0.502441 1 -3 21 0 0 0.936523 0 -3 21 1 0 0.936523 0 -3 21 2 0 0.936523 0 -3 21 3 0 0.936523 0 -3 21 4 0 0.936523 0 -3 21 5 0 0.936523 0 -3 21 6 0 0.936523 0 -3 21 7 0 0.936523 0 -3 21 8 0 0.936523 0 -3 21 9 0 0.936523 0 -3 21 10 0 0.937012 0 -3 21 11 0 0.937012 0 -3 21 12 0 0.937012 0 -3 21 13 0 0.939453 0.189331 -3 21 14 0 0.943848 0.300537 -3 21 15 0 0.94873 0.398682 -3 21 16 0 0.952637 0.497314 -3 21 17 0 0.954102 0.595703 -3 21 18 0 0.950195 0.69043 -3 21 19 0 0.939453 0.775879 -3 21 20 0 0.922363 0.849121 -3 21 21 0 0.899414 0.910645 -3 21 22 0 0.869629 0.957031 -3 21 23 0 0.835449 0.987305 -3 21 24 0 0.799805 1 -3 21 25 0 0.76123 1 -3 21 26 0 0.722168 1 -3 21 27 0 0.683594 1 -3 21 28 0 0.646484 1 -3 21 29 0 0.611816 1 -3 21 30 0 0.580078 1 -3 21 31 0 0.550781 1 -3 22 0 0 0.979492 0 -3 22 1 0 0.979492 0 -3 22 2 0 0.979492 0 -3 22 3 0 0.979492 0 -3 22 4 0 0.979492 0 -3 22 5 0 0.979492 0 -3 22 6 0 0.979492 0 -3 22 7 0 0.979492 0 -3 22 8 0 0.979492 0 -3 22 9 0 0.979492 0 -3 22 10 0 0.979492 0 -3 22 11 0 0.979492 0 -3 22 12 0 0.97998 0 -3 22 13 0 0.981445 0.128296 -3 22 14 0 0.985352 0.267334 -3 22 15 0 0.990723 0.369873 -3 22 16 0 0.996094 0.469238 -3 22 17 0 1 0.567871 -3 22 18 0 0.999023 0.662598 -3 22 19 0 0.991699 0.750488 -3 22 20 0 0.978027 0.82666 -3 22 21 0 0.958008 0.891602 -3 22 22 0 0.933105 0.944824 -3 22 23 0 0.90332 0.983398 -3 22 24 0 0.870117 1 -3 22 25 0 0.83252 1 -3 22 26 0 0.791992 1 -3 22 27 0 0.750488 1 -3 22 28 0 0.709961 1 -3 22 29 0 0.670898 1 -3 22 30 0 0.634277 1 -3 22 31 0 0.600586 1 -3 23 0 0 1 0 -3 23 1 0 1 0 -3 23 2 0 1 0 -3 23 3 0 1 0 -3 23 4 0 1 0 -3 23 5 0 1 0 -3 23 6 0 1 0 -3 23 7 0 1 0 -3 23 8 0 1 0 -3 23 9 0 1 0 -3 23 10 0 1 0 -3 23 11 0 1 0 -3 23 12 0 1 0 -3 23 13 0 1 0 -3 23 14 0 1 0.231689 -3 23 15 0 1 0.341064 -3 23 16 0 1 0.44165 -3 23 17 0 1 0.539551 -3 23 18 0 1 0.634766 -3 23 19 0 1 0.723145 -3 23 20 0 1 0.80127 -3 23 21 0 1 0.869629 -3 23 22 0 0.984375 0.92627 -3 23 23 0 0.958984 0.970703 -3 23 24 0 0.929688 1 -3 23 25 0 0.89502 1 -3 23 26 0 0.85498 1 -3 23 27 0 0.8125 1 -3 23 28 0 0.769531 1 -3 23 29 0 0.727539 1 -3 23 30 0 0.687012 1 -3 23 31 0 0.648926 1 -3 24 0 0 1 0 -3 24 1 0 1 0 -3 24 2 0 1 0 -3 24 3 0 1 0 -3 24 4 0 1 0 -3 24 5 0 1 0 -3 24 6 0 1 0 -3 24 7 0 1 0 -3 24 8 0 1 0 -3 24 9 0 1 0 -3 24 10 0 1 0 -3 24 11 0 1 0 -3 24 12 0 1 0 -3 24 13 0 1 0 -3 24 14 0 1 0.191284 -3 24 15 0 1 0.312012 -3 24 16 0 1 0.414307 -3 24 17 0 1 0.512207 -3 24 18 0 1 0.606934 -3 24 19 0 1 0.695312 -3 24 20 0 1 0.774414 -3 24 21 0 1 0.845215 -3 24 22 0 1 0.904785 -3 24 23 0 1 0.953125 -3 24 24 0 0.979004 0.991699 -3 24 25 0 0.948242 1 -3 24 26 0 0.911133 1 -3 24 27 0 0.869141 1 -3 24 28 0 0.825195 1 -3 24 29 0 0.780762 1 -3 24 30 0 0.737305 1 -3 24 31 0 0.695801 1 -3 25 0 0 1 0 -3 25 1 0 1 0 -3 25 2 0 1 0 -3 25 3 0 1 0 -3 25 4 0 1 0 -3 25 5 0 1 0 -3 25 6 0 1 0 -3 25 7 0 1 0 -3 25 8 0 1 0 -3 25 9 0 1 0 -3 25 10 0 1 0 -3 25 11 0 1 0 -3 25 12 0 1 0 -3 25 13 0 1 0 -3 25 14 0 1 0.132568 -3 25 15 0 1 0.279541 -3 25 16 0 1 0.38501 -3 25 17 0 1 0.482666 -3 25 18 0 1 0.576172 -3 25 19 0 1 0.664062 -3 25 20 0 1 0.744141 -3 25 21 0 1 0.816406 -3 25 22 0 1 0.878906 -3 25 23 0 1 0.930176 -3 25 24 0 1 0.972656 -3 25 25 0 0.99707 1 -3 25 26 0 0.963379 1 -3 25 27 0 0.924316 1 -3 25 28 0 0.880371 1 -3 25 29 0 0.834961 1 -3 25 30 0 0.789551 1 -3 25 31 0 0.745117 1 -3 26 0 0 1 0 -3 26 1 0 1 0 -3 26 2 0 1 0 -3 26 3 0 1 0 -3 26 4 0 1 0 -3 26 5 0 1 0 -3 26 6 0 1 0 -3 26 7 0 1 0 -3 26 8 0 1 0 -3 26 9 0 1 0 -3 26 10 0 1 0 -3 26 11 0 1 0 -3 26 12 0 1 0 -3 26 13 0 1 0 -3 26 14 0 1 0 -3 26 15 0 1 0.241943 -3 26 16 0 1 0.353027 -3 26 17 0 1 0.451172 -3 26 18 0 1 0.543457 -3 26 19 0 1 0.630859 -3 26 20 0 1 0.710938 -3 26 21 0 1 0.783691 -3 26 22 0 1 0.848633 -3 26 23 0 1 0.902832 -3 26 24 0 1 0.948242 -3 26 25 0 1 0.989258 -3 26 26 0 1 1 -3 26 27 0 0.976074 1 -3 26 28 0 0.93457 1 -3 26 29 0 0.889648 1 -3 26 30 0 0.842773 1 -3 26 31 0 0.796387 1 -3 27 0 0 1 0 -3 27 1 0 1 0 -3 27 2 0 1 0 -3 27 3 0 1 0 -3 27 4 0 1 0 -3 27 5 0 1 0 -3 27 6 0 1 0 -3 27 7 0 1 0 -3 27 8 0 1 0 -3 27 9 0 1 0 -3 27 10 0 1 0 -3 27 11 0 1 0 -3 27 12 0 1 0 -3 27 13 0 1 0 -3 27 14 0 1 0 -3 27 15 0 1 0.195557 -3 27 16 0 1 0.318604 -3 27 17 0 1 0.417725 -3 27 18 0 1 0.509277 -3 27 19 0 1 0.595215 -3 27 20 0 1 0.674805 -3 27 21 0 1 0.748047 -3 27 22 0 1 0.813965 -3 27 23 0 1 0.870605 -3 27 24 0 1 0.918457 -3 27 25 0 1 0.962891 -3 27 26 0 1 1 -3 27 27 0 1 1 -3 27 28 0 0.98584 1 -3 27 29 0 0.941895 1 -3 27 30 0 0.895508 1 -3 27 31 0 0.848145 1 -3 28 0 0 1 0 -3 28 1 0 1 0 -3 28 2 0 1 0 -3 28 3 0 1 0 -3 28 4 0 1 0 -3 28 5 0 1 0 -3 28 6 0 1 0 -3 28 7 0 1 0 -3 28 8 0 1 0 -3 28 9 0 1 0 -3 28 10 0 1 0 -3 28 11 0 1 0 -3 28 12 0 1 0 -3 28 13 0 1 0 -3 28 14 0 1 0 -3 28 15 0 1 0.126831 -3 28 16 0 1 0.280518 -3 28 17 0 1 0.382568 -3 28 18 0 1 0.473877 -3 28 19 0 1 0.558105 -3 28 20 0 1 0.63623 -3 28 21 0 1 0.709473 -3 28 22 0 1 0.775879 -3 28 23 0 1 0.833496 -3 28 24 0 1 0.883789 -3 28 25 0 1 0.931152 -3 28 26 0 1 0.974609 -3 28 27 0 1 1 -3 28 28 0 1 1 -3 28 29 0 0.991699 1 -3 28 30 0 0.947266 1 -3 28 31 0 0.899902 1 -3 29 0 0 1 0 -3 29 1 0 1 0 -3 29 2 0 1 0 -3 29 3 0 1 0 -3 29 4 0 1 0 -3 29 5 0 1 0 -3 29 6 0 1 0 -3 29 7 0 1 0 -3 29 8 0 1 0 -3 29 9 0 1 0 -3 29 10 0 1 0 -3 29 11 0 1 0 -3 29 12 0 1 0 -3 29 13 0 1 0 -3 29 14 0 1 0 -3 29 15 0 1 0 -3 29 16 0 1 0.236572 -3 29 17 0 1 0.345215 -3 29 18 0 1 0.436279 -3 29 19 0 1 0.519531 -3 29 20 0 1 0.596191 -3 29 21 0 1 0.667969 -3 29 22 0 1 0.733887 -3 29 23 0 1 0.79248 -3 29 24 0 1 0.84375 -3 29 25 0 1 0.893555 -3 29 26 0 1 0.94043 -3 29 27 0 1 0.98291 -3 29 28 0 1 1 -3 29 29 0 1 1 -3 29 30 0 0.996582 1 -3 29 31 0 0.951172 1 -3 30 0 0 1 0 -3 30 1 0 1 0 -3 30 2 0 1 0 -3 30 3 0 1 0 -3 30 4 0 1 0 -3 30 5 0 1 0 -3 30 6 0 1 0 -3 30 7 0 1 0 -3 30 8 0 1 0 -3 30 9 0 1 0 -3 30 10 0 1 0 -3 30 11 0 1 0 -3 30 12 0 1 0 -3 30 13 0 1 0 -3 30 14 0 1 0 -3 30 15 0 1 0 -3 30 16 0 1 0.182007 -3 30 17 0 1 0.304688 -3 30 18 0 1 0.397217 -3 30 19 0 1 0.479248 -3 30 20 0 1 0.554199 -3 30 21 0 1 0.624512 -3 30 22 0 1 0.689453 -3 30 23 0 1 0.747559 -3 30 24 0 1 0.799805 -3 30 25 0 1 0.850586 -3 30 26 0 1 0.899902 -3 30 27 0 1 0.946289 -3 30 28 0 1 0.988281 -3 30 29 0 1 1 -3 30 30 0 1 1 -3 30 31 0 1 1 -3 31 0 0 1 0 -3 31 1 0 1 0 -3 31 2 0 1 0 -3 31 3 0 1 0 -3 31 4 0 1 0 -3 31 5 0 1 0 -3 31 6 0 1 0 -3 31 7 0 1 0 -3 31 8 0 1 0 -3 31 9 0 1 0 -3 31 10 0 1 0 -3 31 11 0 1 0 -3 31 12 0 1 0 -3 31 13 0 1 0 -3 31 14 0 1 0 -3 31 15 0 1 0 -3 31 16 0 1 0.0875244 -3 31 17 0 1 0.260742 -3 31 18 0 1 0.356934 -3 31 19 0 1 0.438232 -3 31 20 0 1 0.51123 -3 31 21 0 1 0.57959 -3 31 22 0 1 0.643066 -3 31 23 0 1 0.700684 -3 31 24 0 1 0.752441 -3 31 25 0 1 0.804199 -3 31 26 0 1 0.855469 -3 31 27 0 1 0.904785 -3 31 28 0 1 0.951172 -3 31 29 0 1 0.992676 -3 31 30 0 1 1 -3 31 31 0 1 1 -4 0 0 0.0593872 0.0217133 0.01651 -4 0 1 0.0588684 0.0211945 0.0235291 -4 0 2 0.0570374 0.0203247 0.0306091 -4 0 3 0.0494995 0.0198669 0.0350037 -4 0 4 0.0444336 0.0213013 0.0406799 -4 0 5 0.0436707 0.0233917 0.0538025 -4 0 6 0.0379333 0.0257263 0.069519 -4 0 7 0.0107422 0.0287476 0.0882568 -4 0 8 0 0.0333557 0.112061 -4 0 9 0 0.0401917 0.142944 -4 0 10 0 0.0499573 0.18335 -4 0 11 0 0.0629883 0.235352 -4 0 12 0 0.0786133 0.296387 -4 0 13 0 0.0964355 0.365723 -4 0 14 0 0.116272 0.442139 -4 0 15 0 0.137451 0.523926 -4 0 16 0 0.159546 0.608398 -4 0 17 0 0.180786 0.689941 -4 0 18 0 0.200317 0.764648 -4 0 19 0 0.217529 0.830566 -4 0 20 0 0.227051 0.867188 -4 0 21 0 0.228882 0.874512 -4 0 22 0 0.230957 0.881836 -4 0 23 0 0.23291 0.889648 -4 0 24 0 0.234985 0.897461 -4 0 25 0 0.237183 0.90625 -4 0 26 0 0.239624 0.915527 -4 0 27 0 0.242432 0.92627 -4 0 28 0 0.245483 0.937988 -4 0 29 0 0.248779 0.950684 -4 0 30 0 0.252197 0.963867 -4 0 31 0 0.255859 0.977051 -4 1 0 0.0573425 0.026062 0.0160065 -4 1 1 0.0572815 0.0258331 0.0228577 -4 1 2 0.0560913 0.025116 0.0300903 -4 1 3 0.0501099 0.0236359 0.0354919 -4 1 4 0.0440979 0.02388 0.0406494 -4 1 5 0.0432739 0.0259094 0.053772 -4 1 6 0.0374451 0.0279999 0.069458 -4 1 7 0.00513458 0.0306396 0.0882568 -4 1 8 0 0.0348206 0.112061 -4 1 9 0 0.0412598 0.142944 -4 1 10 0 0.0507202 0.18335 -4 1 11 0 0.0635376 0.235352 -4 1 12 0 0.0790405 0.296387 -4 1 13 0 0.0967407 0.365723 -4 1 14 0 0.116455 0.442139 -4 1 15 0 0.137573 0.523926 -4 1 16 0 0.159668 0.608398 -4 1 17 0 0.180908 0.689941 -4 1 18 0 0.200439 0.764648 -4 1 19 0 0.217651 0.830566 -4 1 20 0 0.227173 0.867188 -4 1 21 0 0.229004 0.874512 -4 1 22 0 0.230957 0.881836 -4 1 23 0 0.23291 0.889648 -4 1 24 0 0.234985 0.897461 -4 1 25 0 0.237183 0.90625 -4 1 26 0 0.239624 0.915527 -4 1 27 0 0.242432 0.92627 -4 1 28 0 0.245483 0.937988 -4 1 29 0 0.248779 0.950684 -4 1 30 0 0.252197 0.963867 -4 1 31 0 0.255859 0.977051 -4 2 0 0.0532227 0.030304 0.0158386 -4 2 1 0.0535889 0.0304565 0.0218201 -4 2 2 0.0541382 0.0306549 0.0291138 -4 2 3 0.0511169 0.0293579 0.0363464 -4 2 4 0.0435791 0.0276184 0.0406189 -4 2 5 0.0426025 0.0296021 0.0537109 -4 2 6 0.0365601 0.0314331 0.069458 -4 2 7 0 0.0335999 0.0882568 -4 2 8 0 0.0372009 0.112061 -4 2 9 0 0.0430908 0.142944 -4 2 10 0 0.052063 0.18335 -4 2 11 0 0.0645752 0.235352 -4 2 12 0 0.0797729 0.296387 -4 2 13 0 0.09729 0.365723 -4 2 14 0 0.116882 0.442139 -4 2 15 0 0.137939 0.523926 -4 2 16 0 0.15979 0.608398 -4 2 17 0 0.18103 0.689941 -4 2 18 0 0.200562 0.764648 -4 2 19 0 0.217651 0.830566 -4 2 20 0 0.227173 0.867188 -4 2 21 0 0.229004 0.874512 -4 2 22 0 0.230957 0.881836 -4 2 23 0 0.233032 0.889648 -4 2 24 0 0.234985 0.897461 -4 2 25 0 0.237183 0.90625 -4 2 26 0 0.239624 0.915527 -4 2 27 0 0.242432 0.92627 -4 2 28 0 0.245483 0.937988 -4 2 29 0 0.248779 0.950684 -4 2 30 0 0.252197 0.963867 -4 2 31 0 0.255859 0.977051 -4 3 0 0.0469971 0.0336914 0.0167999 -4 3 1 0.046936 0.033844 0.0210114 -4 3 2 0.0474243 0.0344543 0.0266876 -4 3 3 0.0494995 0.0362549 0.035675 -4 3 4 0.0426331 0.03302 0.0406494 -4 3 5 0.0413208 0.0349121 0.0536499 -4 3 6 0.0348511 0.036499 0.069397 -4 3 7 0 0.038147 0.0881958 -4 3 8 0 0.0410156 0.112061 -4 3 9 0 0.0461121 0.142822 -4 3 10 0 0.0543823 0.18335 -4 3 11 0 0.0662842 0.235229 -4 3 12 0 0.0810547 0.296387 -4 3 13 0 0.0982666 0.365723 -4 3 14 0 0.117554 0.442139 -4 3 15 0 0.138428 0.523926 -4 3 16 0 0.160278 0.608398 -4 3 17 0 0.181274 0.689941 -4 3 18 0 0.200806 0.764648 -4 3 19 0 0.217896 0.830566 -4 3 20 0 0.227417 0.867188 -4 3 21 0 0.229126 0.874512 -4 3 22 0 0.231079 0.881836 -4 3 23 0 0.233032 0.889648 -4 3 24 0 0.235107 0.897461 -4 3 25 0 0.237305 0.90625 -4 3 26 0 0.239746 0.915527 -4 3 27 0 0.242432 0.92627 -4 3 28 0 0.245605 0.937988 -4 3 29 0 0.248779 0.950684 -4 3 30 0 0.252197 0.963867 -4 3 31 0 0.255859 0.977051 -4 4 0 0.045105 0.0416565 0.0177155 -4 4 1 0.0445557 0.0413818 0.0215607 -4 4 2 0.0437317 0.0410767 0.0263824 -4 4 3 0.0426331 0.0408936 0.0326233 -4 4 4 0.0409241 0.0409241 0.0409241 -4 4 5 0.0387878 0.042511 0.0535583 -4 4 6 0.0311584 0.0438538 0.0692749 -4 4 7 0 0.0449524 0.0881348 -4 4 8 0 0.0469971 0.112061 -4 4 9 0 0.0510864 0.142822 -4 4 10 0 0.0583801 0.183228 -4 4 11 0 0.069458 0.235229 -4 4 12 0 0.0834351 0.296387 -4 4 13 0 0.100037 0.365723 -4 4 14 0 0.118896 0.442139 -4 4 15 0 0.139404 0.523926 -4 4 16 0 0.161011 0.608398 -4 4 17 0 0.181885 0.689941 -4 4 18 0 0.201172 0.764648 -4 4 19 0 0.218262 0.830566 -4 4 20 0 0.227661 0.867188 -4 4 21 0 0.22937 0.874512 -4 4 22 0 0.231323 0.881836 -4 4 23 0 0.233276 0.889648 -4 4 24 0 0.235229 0.897461 -4 4 25 0 0.237427 0.90625 -4 4 26 0 0.239868 0.915527 -4 4 27 0 0.242554 0.92627 -4 4 28 0 0.245605 0.937988 -4 4 29 0 0.248901 0.950684 -4 4 30 0 0.252197 0.963867 -4 4 31 0 0.255859 0.977051 -4 5 0 0.0414124 0.0534363 0.0158844 -4 5 1 0.0409241 0.0531921 0.0205383 -4 5 2 0.0401001 0.0528259 0.0259857 -4 5 3 0.0387268 0.0523682 0.0326233 -4 5 4 0.0366821 0.0523071 0.0413513 -4 5 5 0.0328979 0.0532227 0.0535278 -4 5 6 0.020752 0.0541687 0.0690308 -4 5 7 0 0.0547791 0.0880127 -4 5 8 0 0.0559998 0.112 -4 5 9 0 0.05896 0.142822 -4 5 10 0 0.0650635 0.183228 -4 5 11 0 0.0749512 0.235229 -4 5 12 0 0.0877686 0.296387 -4 5 13 0 0.103333 0.365723 -4 5 14 0 0.121399 0.442139 -4 5 15 0 0.141357 0.523926 -4 5 16 0 0.162354 0.608398 -4 5 17 0 0.182983 0.689941 -4 5 18 0 0.202026 0.764648 -4 5 19 0 0.218872 0.830566 -4 5 20 0 0.228149 0.867188 -4 5 21 0 0.229858 0.874512 -4 5 22 0 0.231567 0.882324 -4 5 23 0 0.233521 0.889648 -4 5 24 0 0.235474 0.897461 -4 5 25 0 0.237549 0.90625 -4 5 26 0 0.23999 0.915527 -4 5 27 0 0.242676 0.92627 -4 5 28 0 0.245728 0.937988 -4 5 29 0 0.249023 0.950684 -4 5 30 0 0.252441 0.963867 -4 5 31 0 0.255859 0.977051 -4 6 0 0.0286102 0.0675659 0.012764 -4 6 1 0.0282593 0.0675659 0.0170441 -4 6 2 0.0272675 0.0674438 0.023941 -4 6 3 0.0253296 0.0673218 0.0316467 -4 6 4 0.0209961 0.0673218 0.0410767 -4 6 5 0 0.0675659 0.0532227 -4 6 6 0 0.0679321 0.0685425 -4 6 7 0 0.0681152 0.0877075 -4 6 8 0 0.0686646 0.111816 -4 6 9 0 0.0705566 0.1427 -4 6 10 0 0.0754395 0.182983 -4 6 11 0 0.0838623 0.235107 -4 6 12 0 0.0951538 0.296387 -4 6 13 0 0.109192 0.365723 -4 6 14 0 0.125977 0.442139 -4 6 15 0 0.144775 0.523926 -4 6 16 0 0.165039 0.608398 -4 6 17 0 0.185059 0.689941 -4 6 18 0 0.203613 0.764648 -4 6 19 0 0.220215 0.830566 -4 6 20 0 0.229248 0.867188 -4 6 21 0 0.230591 0.874512 -4 6 22 0 0.2323 0.882324 -4 6 23 0 0.234009 0.889648 -4 6 24 0 0.235962 0.897461 -4 6 25 0 0.238037 0.90625 -4 6 26 0 0.240356 0.915527 -4 6 27 0 0.243042 0.92627 -4 6 28 0 0.245972 0.937988 -4 6 29 0 0.249268 0.950684 -4 6 30 0 0.252686 0.963867 -4 6 31 0 0.256104 0.977051 -4 7 0 0 0.0855103 0.0118942 -4 7 1 0 0.0855103 0.0119095 -4 7 2 0 0.0855713 0.0181274 -4 7 3 0 0.0855713 0.0282745 -4 7 4 0 0.0856323 0.0389099 -4 7 5 0 0.0858154 0.0516968 -4 7 6 0 0.0859375 0.0673218 -4 7 7 0 0.0859985 0.0869141 -4 7 8 0 0.0860596 0.11145 -4 7 9 0 0.0870361 0.142456 -4 7 10 0 0.0907593 0.182739 -4 7 11 0 0.0979004 0.234863 -4 7 12 0 0.107361 0.296143 -4 7 13 0 0.119385 0.365723 -4 7 14 0 0.134155 0.442139 -4 7 15 0 0.151245 0.523926 -4 7 16 0 0.170044 0.608398 -4 7 17 0 0.188843 0.689941 -4 7 18 0 0.206665 0.764648 -4 7 19 0 0.222656 0.830566 -4 7 20 0 0.231201 0.867676 -4 7 21 0 0.232178 0.874512 -4 7 22 0 0.233521 0.882324 -4 7 23 0 0.235107 0.890137 -4 7 24 0 0.236816 0.897461 -4 7 25 0 0.23877 0.90625 -4 7 26 0 0.241089 0.915527 -4 7 27 0 0.24353 0.92627 -4 7 28 0 0.24646 0.937988 -4 7 29 0 0.249634 0.950684 -4 7 30 0 0.25293 0.963867 -4 7 31 0 0.256348 0.977051 -4 8 0 0 0.108459 0.0100555 -4 8 1 0 0.108459 0.0100708 -4 8 2 0 0.108521 0.0101013 -4 8 3 0 0.108582 0.0190582 -4 8 4 0 0.108643 0.0339661 -4 8 5 0 0.108826 0.0483398 -4 8 6 0 0.109009 0.0648804 -4 8 7 0 0.109192 0.085144 -4 8 8 0 0.109131 0.110413 -4 8 9 0 0.109619 0.141968 -4 8 10 0 0.112488 0.182373 -4 8 11 0 0.118591 0.234497 -4 8 12 0 0.126343 0.296143 -4 8 13 0 0.135986 0.365479 -4 8 14 0 0.148071 0.442139 -4 8 15 0 0.162598 0.523926 -4 8 16 0 0.179199 0.608398 -4 8 17 0 0.196167 0.689941 -4 8 18 0 0.212524 0.765137 -4 8 19 0 0.227295 0.831055 -4 8 20 0 0.234985 0.867676 -4 8 21 0 0.235229 0.875 -4 8 22 0 0.236084 0.882324 -4 8 23 0 0.237183 0.890137 -4 8 24 0 0.238647 0.897949 -4 8 25 0 0.240356 0.90625 -4 8 26 0 0.24231 0.915527 -4 8 27 0 0.244751 0.92627 -4 8 28 0 0.247437 0.937988 -4 8 29 0 0.250488 0.950684 -4 8 30 0 0.253662 0.963867 -4 8 31 0 0.25708 0.977051 -4 9 0 0 0.137695 0.00329781 -4 9 1 0 0.137695 0.0034008 -4 9 2 0 0.137695 0.00357056 -4 9 3 0 0.137695 0.00385094 -4 9 4 0 0.137817 0.020462 -4 9 5 0 0.137939 0.0418396 -4 9 6 0 0.138062 0.0605469 -4 9 7 0 0.138306 0.0820312 -4 9 8 0 0.138672 0.108398 -4 9 9 0 0.139282 0.140991 -4 9 10 0 0.141724 0.181763 -4 9 11 0 0.147095 0.233887 -4 9 12 0 0.153564 0.295654 -4 9 13 0 0.161011 0.365234 -4 9 14 0 0.170288 0.442139 -4 9 15 0 0.181519 0.523926 -4 9 16 0 0.194824 0.608398 -4 9 17 0 0.208984 0.689941 -4 9 18 0 0.2229 0.765137 -4 9 19 0 0.23584 0.831055 -4 9 20 0 0.242065 0.868164 -4 9 21 0 0.240845 0.875488 -4 9 22 0 0.240723 0.882812 -4 9 23 0 0.241089 0.890625 -4 9 24 0 0.241943 0.897949 -4 9 25 0 0.243164 0.906738 -4 9 26 0 0.244873 0.916016 -4 9 27 0 0.246826 0.92627 -4 9 28 0 0.249268 0.937988 -4 9 29 0 0.252197 0.950684 -4 9 30 0 0.255127 0.963867 -4 9 31 0 0.258301 0.977539 -4 10 0 0 0.175415 0 -4 10 1 0 0.175415 0 -4 10 2 0 0.175415 0 -4 10 3 0 0.175415 0 -4 10 4 0 0.175537 0 -4 10 5 0 0.175537 0.0250092 -4 10 6 0 0.175537 0.0532837 -4 10 7 0 0.175659 0.0777588 -4 10 8 0 0.175903 0.105774 -4 10 9 0 0.176758 0.139648 -4 10 10 0 0.178955 0.181152 -4 10 11 0 0.183716 0.233154 -4 10 12 0 0.189209 0.294922 -4 10 13 0 0.195068 0.36499 -4 10 14 0 0.20166 0.441895 -4 10 15 0 0.209595 0.523926 -4 10 16 0 0.219116 0.608887 -4 10 17 0 0.229492 0.69043 -4 10 18 0 0.240112 0.765625 -4 10 19 0 0.250244 0.831543 -4 10 20 0 0.25415 0.869141 -4 10 21 0 0.250732 0.875977 -4 10 22 0 0.248779 0.883301 -4 10 23 0 0.248047 0.891113 -4 10 24 0 0.247925 0.898438 -4 10 25 0 0.248291 0.907227 -4 10 26 0 0.249268 0.916504 -4 10 27 0 0.250732 0.926758 -4 10 28 0 0.252686 0.938477 -4 10 29 0 0.254883 0.951172 -4 10 30 0 0.257568 0.964355 -4 10 31 0 0.260254 0.977539 -4 11 0 0 0.224365 0 -4 11 1 0 0.224365 0 -4 11 2 0 0.224365 0 -4 11 3 0 0.224487 0 -4 11 4 0 0.224487 0 -4 11 5 0 0.224487 0 -4 11 6 0 0.224609 0.0345154 -4 11 7 0 0.224487 0.0704956 -4 11 8 0 0.224365 0.102417 -4 11 9 0 0.224731 0.138428 -4 11 10 0 0.226196 0.18103 -4 11 11 0 0.229614 0.232422 -4 11 12 0 0.234009 0.293945 -4 11 13 0 0.238647 0.364258 -4 11 14 0 0.243042 0.44165 -4 11 15 0 0.247925 0.523926 -4 11 16 0 0.253662 0.608887 -4 11 17 0 0.259766 0.690918 -4 11 18 0 0.266357 0.765625 -4 11 19 0 0.272705 0.832031 -4 11 20 0 0.273438 0.870605 -4 11 21 0 0.266602 0.877441 -4 11 22 0 0.262207 0.884766 -4 11 23 0 0.259521 0.89209 -4 11 24 0 0.257812 0.899414 -4 11 25 0 0.25708 0.907715 -4 11 26 0 0.256836 0.916992 -4 11 27 0 0.25708 0.927246 -4 11 28 0 0.258301 0.938965 -4 11 29 0 0.259766 0.95166 -4 11 30 0 0.261719 0.964355 -4 11 31 0 0.263916 0.978027 -4 12 0 0 0.283936 0 -4 12 1 0 0.283936 0 -4 12 2 0 0.283936 0 -4 12 3 0 0.283936 0 -4 12 4 0 0.283936 0 -4 12 5 0 0.283936 0 -4 12 6 0 0.283936 0 -4 12 7 0 0.28418 0.0505981 -4 12 8 0 0.28418 0.0945435 -4 12 9 0 0.28418 0.135132 -4 12 10 0 0.284668 0.17981 -4 12 11 0 0.286133 0.231567 -4 12 12 0 0.289062 0.292725 -4 12 13 0 0.29248 0.363037 -4 12 14 0 0.295166 0.440918 -4 12 15 0 0.297363 0.523438 -4 12 16 0 0.299561 0.608887 -4 12 17 0 0.301514 0.691406 -4 12 18 0 0.303467 0.766602 -4 12 19 0 0.305664 0.83252 -4 12 20 0 0.30249 0.873047 -4 12 21 0 0.291016 0.879395 -4 12 22 0 0.282959 0.88623 -4 12 23 0 0.277344 0.893555 -4 12 24 0 0.273682 0.900879 -4 12 25 0 0.270752 0.90918 -4 12 26 0 0.268799 0.918457 -4 12 27 0 0.267822 0.928223 -4 12 28 0 0.267578 0.939941 -4 12 29 0 0.267822 0.952148 -4 12 30 0 0.268799 0.965332 -4 12 31 0 0.27002 0.978516 -4 13 0 0 0.351562 0 -4 13 1 0 0.351562 0 -4 13 2 0 0.351562 0 -4 13 3 0 0.351562 0 -4 13 4 0 0.351562 0 -4 13 5 0 0.351562 0 -4 13 6 0 0.351562 0 -4 13 7 0 0.351807 0 -4 13 8 0 0.351807 0.0743408 -4 13 9 0 0.352051 0.125854 -4 13 10 0 0.352295 0.174927 -4 13 11 0 0.353027 0.22876 -4 13 12 0 0.354248 0.290527 -4 13 13 0 0.356445 0.36084 -4 13 14 0 0.357666 0.439209 -4 13 15 0 0.35791 0.522461 -4 13 16 0 0.357178 0.608887 -4 13 17 0 0.355225 0.691895 -4 13 18 0 0.352539 0.767578 -4 13 19 0 0.350098 0.833496 -4 13 20 0 0.342773 0.876953 -4 13 21 0 0.325684 0.882812 -4 13 22 0 0.312988 0.889648 -4 13 23 0 0.303711 0.896484 -4 13 24 0 0.297119 0.90332 -4 13 25 0 0.291504 0.911621 -4 13 26 0 0.287354 0.92041 -4 13 27 0 0.283936 0.930176 -4 13 28 0 0.281738 0.941406 -4 13 29 0 0.280273 0.953613 -4 13 30 0 0.279785 0.966309 -4 13 31 0 0.279541 0.979492 -4 14 0 0 0.426758 0 -4 14 1 0 0.426758 0 -4 14 2 0 0.426758 0 -4 14 3 0 0.426758 0 -4 14 4 0 0.426758 0 -4 14 5 0 0.426758 0 -4 14 6 0 0.426758 0 -4 14 7 0 0.427002 0 -4 14 8 0 0.427002 0 -4 14 9 0 0.42749 0.105591 -4 14 10 0 0.427734 0.163818 -4 14 11 0 0.428467 0.221802 -4 14 12 0 0.429199 0.285645 -4 14 13 0 0.430176 0.356934 -4 14 14 0 0.43042 0.435791 -4 14 15 0 0.429199 0.520508 -4 14 16 0 0.426025 0.60791 -4 14 17 0 0.420654 0.691895 -4 14 18 0 0.413818 0.768066 -4 14 19 0 0.406738 0.834961 -4 14 20 0 0.395752 0.882324 -4 14 21 0 0.371826 0.888184 -4 14 22 0 0.35376 0.894531 -4 14 23 0 0.340088 0.900879 -4 14 24 0 0.329834 0.907715 -4 14 25 0 0.321045 0.915039 -4 14 26 0 0.313477 0.923828 -4 14 27 0 0.307373 0.933105 -4 14 28 0 0.30249 0.944336 -4 14 29 0 0.298828 0.956055 -4 14 30 0 0.295898 0.968262 -4 14 31 0 0.293945 0.981445 -4 15 0 0 0.507812 0 -4 15 1 0 0.507812 0 -4 15 2 0 0.507812 0 -4 15 3 0 0.507812 0 -4 15 4 0 0.507812 0 -4 15 5 0 0.507812 0 -4 15 6 0 0.507812 0 -4 15 7 0 0.507812 0 -4 15 8 0 0.507812 0 -4 15 9 0 0.508301 0.0462036 -4 15 10 0 0.508789 0.143066 -4 15 11 0 0.509766 0.208618 -4 15 12 0 0.510742 0.276123 -4 15 13 0 0.51123 0.349365 -4 15 14 0 0.51123 0.429688 -4 15 15 0 0.509277 0.516113 -4 15 16 0 0.504883 0.60498 -4 15 17 0 0.496826 0.690918 -4 15 18 0 0.486328 0.768555 -4 15 19 0 0.474854 0.836426 -4 15 20 0 0.461182 0.88916 -4 15 21 0 0.43042 0.895996 -4 15 22 0 0.40625 0.902344 -4 15 23 0 0.387451 0.908203 -4 15 24 0 0.372803 0.914551 -4 15 25 0 0.359863 0.921387 -4 15 26 0 0.348633 0.929199 -4 15 27 0 0.339111 0.937988 -4 15 28 0 0.331055 0.948242 -4 15 29 0 0.324219 0.959473 -4 15 30 0 0.318604 0.97168 -4 15 31 0 0.314209 0.983887 -4 16 0 0 0.592773 0 -4 16 1 0 0.592773 0 -4 16 2 0 0.592773 0 -4 16 3 0 0.592773 0 -4 16 4 0 0.592773 0 -4 16 5 0 0.592773 0 -4 16 6 0 0.592773 0 -4 16 7 0 0.592773 0 -4 16 8 0 0.592773 0 -4 16 9 0 0.592773 0 -4 16 10 0 0.593262 0.101135 -4 16 11 0 0.594238 0.18689 -4 16 12 0 0.595703 0.260498 -4 16 13 0 0.597168 0.336914 -4 16 14 0 0.597656 0.419189 -4 16 15 0 0.596191 0.507324 -4 16 16 0 0.591309 0.598633 -4 16 17 0 0.582031 0.687012 -4 16 18 0 0.568848 0.76709 -4 16 19 0 0.553711 0.836426 -4 16 20 0 0.537598 0.893555 -4 16 21 0 0.501465 0.905762 -4 16 22 0 0.471191 0.913086 -4 16 23 0 0.446777 0.918945 -4 16 24 0 0.427246 0.924805 -4 16 25 0 0.409668 0.930664 -4 16 26 0 0.394043 0.9375 -4 16 27 0 0.380127 0.945801 -4 16 28 0 0.368164 0.955078 -4 16 29 0 0.357666 0.965332 -4 16 30 0 0.348877 0.976562 -4 16 31 0 0.341064 0.987793 -4 17 0 0 0.67627 0 -4 17 1 0 0.67627 0 -4 17 2 0 0.67627 0 -4 17 3 0 0.67627 0 -4 17 4 0 0.67627 0 -4 17 5 0 0.67627 0 -4 17 6 0 0.67627 0 -4 17 7 0 0.67627 0 -4 17 8 0 0.67627 0 -4 17 9 0 0.676758 0 -4 17 10 0 0.676758 0 -4 17 11 0 0.677734 0.151611 -4 17 12 0 0.679688 0.237915 -4 17 13 0 0.681641 0.318848 -4 17 14 0 0.683105 0.403564 -4 17 15 0 0.683105 0.493652 -4 17 16 0 0.679199 0.587402 -4 17 17 0 0.669922 0.678223 -4 17 18 0 0.655762 0.761719 -4 17 19 0 0.638672 0.833984 -4 17 20 0 0.619141 0.893066 -4 17 21 0 0.582031 0.916016 -4 17 22 0 0.546387 0.926758 -4 17 23 0 0.516602 0.933594 -4 17 24 0 0.491699 0.938965 -4 17 25 0 0.468994 0.944336 -4 17 26 0 0.448486 0.950195 -4 17 27 0 0.429688 0.957031 -4 17 28 0 0.41333 0.964844 -4 17 29 0 0.398682 0.973633 -4 17 30 0 0.385986 0.983398 -4 17 31 0 0.374512 0.994141 -4 18 0 0 0.754395 0 -4 18 1 0 0.754395 0 -4 18 2 0 0.754395 0 -4 18 3 0 0.754395 0 -4 18 4 0 0.754395 0 -4 18 5 0 0.754395 0 -4 18 6 0 0.754395 0 -4 18 7 0 0.754395 0 -4 18 8 0 0.754395 0 -4 18 9 0 0.754883 0 -4 18 10 0 0.754883 0 -4 18 11 0 0.755371 0.0775757 -4 18 12 0 0.757324 0.206421 -4 18 13 0 0.759766 0.294922 -4 18 14 0 0.762207 0.382812 -4 18 15 0 0.763672 0.474365 -4 18 16 0 0.762207 0.570312 -4 18 17 0 0.754883 0.664551 -4 18 18 0 0.742188 0.751465 -4 18 19 0 0.724121 0.827148 -4 18 20 0 0.702637 0.889648 -4 18 21 0 0.66748 0.924316 -4 18 22 0 0.629395 0.941406 -4 18 23 0 0.594727 0.951172 -4 18 24 0 0.564941 0.957031 -4 18 25 0 0.537109 0.962402 -4 18 26 0 0.510742 0.966797 -4 18 27 0 0.487061 0.972168 -4 18 28 0 0.465576 0.978516 -4 18 29 0 0.446289 0.985352 -4 18 30 0 0.428955 0.993652 -4 18 31 0 0.413574 1 -4 19 0 0 0.824707 0 -4 19 1 0 0.824707 0 -4 19 2 0 0.824707 0 -4 19 3 0 0.824707 0 -4 19 4 0 0.824707 0 -4 19 5 0 0.824707 0 -4 19 6 0 0.824707 0 -4 19 7 0 0.824707 0 -4 19 8 0 0.824707 0 -4 19 9 0 0.824707 0 -4 19 10 0 0.824707 0 -4 19 11 0 0.825195 0 -4 19 12 0 0.82666 0.162354 -4 19 13 0 0.82959 0.266113 -4 19 14 0 0.83252 0.358154 -4 19 15 0 0.835449 0.451416 -4 19 16 0 0.835938 0.54834 -4 19 17 0 0.832031 0.64502 -4 19 18 0 0.821777 0.73584 -4 19 19 0 0.805176 0.81543 -4 19 20 0 0.783691 0.881348 -4 19 21 0 0.751953 0.927246 -4 19 22 0 0.714355 0.953613 -4 19 23 0 0.677246 0.968262 -4 19 24 0 0.643555 0.977051 -4 19 25 0 0.610352 0.982422 -4 19 26 0 0.579102 0.986816 -4 19 27 0 0.549805 0.990723 -4 19 28 0 0.522949 0.995117 -4 19 29 0 0.498535 1 -4 19 30 0 0.476562 1 -4 19 31 0 0.456787 1 -4 20 0 0 0.885254 0 -4 20 1 0 0.885254 0 -4 20 2 0 0.885254 0 -4 20 3 0 0.885254 0 -4 20 4 0 0.885254 0 -4 20 5 0 0.885254 0 -4 20 6 0 0.885254 0 -4 20 7 0 0.885254 0 -4 20 8 0 0.885254 0 -4 20 9 0 0.885254 0 -4 20 10 0 0.885254 0 -4 20 11 0 0.885742 0 -4 20 12 0 0.88623 0.0791016 -4 20 13 0 0.88916 0.231934 -4 20 14 0 0.893066 0.330811 -4 20 15 0 0.896973 0.42627 -4 20 16 0 0.899414 0.524414 -4 20 17 0 0.898438 0.62207 -4 20 18 0 0.891113 0.715332 -4 20 19 0 0.876953 0.797852 -4 20 20 0 0.856934 0.867676 -4 20 21 0 0.830078 0.922852 -4 20 22 0 0.79541 0.959961 -4 20 23 0 0.758301 0.981445 -4 20 24 0 0.722656 0.994141 -4 20 25 0 0.686035 1 -4 20 26 0 0.649902 1 -4 20 27 0 0.615723 1 -4 20 28 0 0.583496 1 -4 20 29 0 0.553711 1 -4 20 30 0 0.526855 1 -4 20 31 0 0.502441 1 -4 21 0 0 0.936523 0 -4 21 1 0 0.936523 0 -4 21 2 0 0.936523 0 -4 21 3 0 0.936523 0 -4 21 4 0 0.936523 0 -4 21 5 0 0.936523 0 -4 21 6 0 0.936523 0 -4 21 7 0 0.936523 0 -4 21 8 0 0.936523 0 -4 21 9 0 0.936523 0 -4 21 10 0 0.937012 0 -4 21 11 0 0.937012 0 -4 21 12 0 0.937012 0 -4 21 13 0 0.939941 0.189331 -4 21 14 0 0.943848 0.300537 -4 21 15 0 0.94873 0.398682 -4 21 16 0 0.953125 0.497559 -4 21 17 0 0.954102 0.595703 -4 21 18 0 0.950195 0.69043 -4 21 19 0 0.939453 0.775879 -4 21 20 0 0.922363 0.849121 -4 21 21 0 0.899414 0.910645 -4 21 22 0 0.869629 0.957031 -4 21 23 0 0.835449 0.987305 -4 21 24 0 0.799805 1 -4 21 25 0 0.76123 1 -4 21 26 0 0.722168 1 -4 21 27 0 0.683594 1 -4 21 28 0 0.646484 1 -4 21 29 0 0.611816 1 -4 21 30 0 0.580078 1 -4 21 31 0 0.550781 1 -4 22 0 0 0.979492 0 -4 22 1 0 0.979492 0 -4 22 2 0 0.979492 0 -4 22 3 0 0.979492 0 -4 22 4 0 0.979492 0 -4 22 5 0 0.979492 0 -4 22 6 0 0.979492 0 -4 22 7 0 0.979492 0 -4 22 8 0 0.979492 0 -4 22 9 0 0.979492 0 -4 22 10 0 0.979492 0 -4 22 11 0 0.979492 0 -4 22 12 0 0.97998 0 -4 22 13 0 0.981445 0.128418 -4 22 14 0 0.985352 0.267334 -4 22 15 0 0.990723 0.369873 -4 22 16 0 0.996094 0.469238 -4 22 17 0 1 0.567871 -4 22 18 0 0.999023 0.662598 -4 22 19 0 0.991699 0.750488 -4 22 20 0 0.978027 0.82666 -4 22 21 0 0.958008 0.891602 -4 22 22 0 0.933105 0.944824 -4 22 23 0 0.90332 0.983398 -4 22 24 0 0.870117 1 -4 22 25 0 0.83252 1 -4 22 26 0 0.791992 1 -4 22 27 0 0.750488 1 -4 22 28 0 0.709961 1 -4 22 29 0 0.670898 1 -4 22 30 0 0.634277 1 -4 22 31 0 0.600586 1 -4 23 0 0 1 0 -4 23 1 0 1 0 -4 23 2 0 1 0 -4 23 3 0 1 0 -4 23 4 0 1 0 -4 23 5 0 1 0 -4 23 6 0 1 0 -4 23 7 0 1 0 -4 23 8 0 1 0 -4 23 9 0 1 0 -4 23 10 0 1 0 -4 23 11 0 1 0 -4 23 12 0 1 0 -4 23 13 0 1 0 -4 23 14 0 1 0.231689 -4 23 15 0 1 0.341064 -4 23 16 0 1 0.44165 -4 23 17 0 1 0.539551 -4 23 18 0 1 0.634766 -4 23 19 0 1 0.723145 -4 23 20 0 1 0.80127 -4 23 21 0 1 0.869629 -4 23 22 0 0.984375 0.92627 -4 23 23 0 0.958984 0.970703 -4 23 24 0 0.929688 1 -4 23 25 0 0.89502 1 -4 23 26 0 0.85498 1 -4 23 27 0 0.8125 1 -4 23 28 0 0.769531 1 -4 23 29 0 0.727539 1 -4 23 30 0 0.687012 1 -4 23 31 0 0.648926 1 -4 24 0 0 1 0 -4 24 1 0 1 0 -4 24 2 0 1 0 -4 24 3 0 1 0 -4 24 4 0 1 0 -4 24 5 0 1 0 -4 24 6 0 1 0 -4 24 7 0 1 0 -4 24 8 0 1 0 -4 24 9 0 1 0 -4 24 10 0 1 0 -4 24 11 0 1 0 -4 24 12 0 1 0 -4 24 13 0 1 0 -4 24 14 0 1 0.191284 -4 24 15 0 1 0.312012 -4 24 16 0 1 0.414307 -4 24 17 0 1 0.512207 -4 24 18 0 1 0.606934 -4 24 19 0 1 0.695312 -4 24 20 0 1 0.774414 -4 24 21 0 1 0.845215 -4 24 22 0 1 0.904785 -4 24 23 0 1 0.953125 -4 24 24 0 0.979004 0.991699 -4 24 25 0 0.948242 1 -4 24 26 0 0.911133 1 -4 24 27 0 0.869141 1 -4 24 28 0 0.825195 1 -4 24 29 0 0.780762 1 -4 24 30 0 0.737305 1 -4 24 31 0 0.695801 1 -4 25 0 0 1 0 -4 25 1 0 1 0 -4 25 2 0 1 0 -4 25 3 0 1 0 -4 25 4 0 1 0 -4 25 5 0 1 0 -4 25 6 0 1 0 -4 25 7 0 1 0 -4 25 8 0 1 0 -4 25 9 0 1 0 -4 25 10 0 1 0 -4 25 11 0 1 0 -4 25 12 0 1 0 -4 25 13 0 1 0 -4 25 14 0 1 0.132568 -4 25 15 0 1 0.279541 -4 25 16 0 1 0.38501 -4 25 17 0 1 0.482666 -4 25 18 0 1 0.576172 -4 25 19 0 1 0.664062 -4 25 20 0 1 0.744141 -4 25 21 0 1 0.816406 -4 25 22 0 1 0.878906 -4 25 23 0 1 0.930176 -4 25 24 0 1 0.972656 -4 25 25 0 0.99707 1 -4 25 26 0 0.963379 1 -4 25 27 0 0.924316 1 -4 25 28 0 0.880371 1 -4 25 29 0 0.834961 1 -4 25 30 0 0.789551 1 -4 25 31 0 0.745117 1 -4 26 0 0 1 0 -4 26 1 0 1 0 -4 26 2 0 1 0 -4 26 3 0 1 0 -4 26 4 0 1 0 -4 26 5 0 1 0 -4 26 6 0 1 0 -4 26 7 0 1 0 -4 26 8 0 1 0 -4 26 9 0 1 0 -4 26 10 0 1 0 -4 26 11 0 1 0 -4 26 12 0 1 0 -4 26 13 0 1 0 -4 26 14 0 1 0 -4 26 15 0 1 0.241943 -4 26 16 0 1 0.353027 -4 26 17 0 1 0.451172 -4 26 18 0 1 0.543457 -4 26 19 0 1 0.630859 -4 26 20 0 1 0.710938 -4 26 21 0 1 0.783691 -4 26 22 0 1 0.848633 -4 26 23 0 1 0.902832 -4 26 24 0 1 0.948242 -4 26 25 0 1 0.989258 -4 26 26 0 1 1 -4 26 27 0 0.976074 1 -4 26 28 0 0.93457 1 -4 26 29 0 0.889648 1 -4 26 30 0 0.842773 1 -4 26 31 0 0.796387 1 -4 27 0 0 1 0 -4 27 1 0 1 0 -4 27 2 0 1 0 -4 27 3 0 1 0 -4 27 4 0 1 0 -4 27 5 0 1 0 -4 27 6 0 1 0 -4 27 7 0 1 0 -4 27 8 0 1 0 -4 27 9 0 1 0 -4 27 10 0 1 0 -4 27 11 0 1 0 -4 27 12 0 1 0 -4 27 13 0 1 0 -4 27 14 0 1 0 -4 27 15 0 1 0.195557 -4 27 16 0 1 0.318604 -4 27 17 0 1 0.417725 -4 27 18 0 1 0.509277 -4 27 19 0 1 0.595215 -4 27 20 0 1 0.674805 -4 27 21 0 1 0.748047 -4 27 22 0 1 0.813965 -4 27 23 0 1 0.870605 -4 27 24 0 1 0.918457 -4 27 25 0 1 0.962891 -4 27 26 0 1 1 -4 27 27 0 1 1 -4 27 28 0 0.98584 1 -4 27 29 0 0.941895 1 -4 27 30 0 0.895508 1 -4 27 31 0 0.848145 1 -4 28 0 0 1 0 -4 28 1 0 1 0 -4 28 2 0 1 0 -4 28 3 0 1 0 -4 28 4 0 1 0 -4 28 5 0 1 0 -4 28 6 0 1 0 -4 28 7 0 1 0 -4 28 8 0 1 0 -4 28 9 0 1 0 -4 28 10 0 1 0 -4 28 11 0 1 0 -4 28 12 0 1 0 -4 28 13 0 1 0 -4 28 14 0 1 0 -4 28 15 0 1 0.126831 -4 28 16 0 1 0.280518 -4 28 17 0 1 0.382568 -4 28 18 0 1 0.473877 -4 28 19 0 1 0.558105 -4 28 20 0 1 0.63623 -4 28 21 0 1 0.709473 -4 28 22 0 1 0.775879 -4 28 23 0 1 0.833496 -4 28 24 0 1 0.883789 -4 28 25 0 1 0.931152 -4 28 26 0 1 0.974609 -4 28 27 0 1 1 -4 28 28 0 1 1 -4 28 29 0 0.991699 1 -4 28 30 0 0.947266 1 -4 28 31 0 0.899902 1 -4 29 0 0 1 0 -4 29 1 0 1 0 -4 29 2 0 1 0 -4 29 3 0 1 0 -4 29 4 0 1 0 -4 29 5 0 1 0 -4 29 6 0 1 0 -4 29 7 0 1 0 -4 29 8 0 1 0 -4 29 9 0 1 0 -4 29 10 0 1 0 -4 29 11 0 1 0 -4 29 12 0 1 0 -4 29 13 0 1 0 -4 29 14 0 1 0 -4 29 15 0 1 0 -4 29 16 0 1 0.236572 -4 29 17 0 1 0.345215 -4 29 18 0 1 0.436279 -4 29 19 0 1 0.519531 -4 29 20 0 1 0.596191 -4 29 21 0 1 0.667969 -4 29 22 0 1 0.733887 -4 29 23 0 1 0.79248 -4 29 24 0 1 0.84375 -4 29 25 0 1 0.893555 -4 29 26 0 1 0.94043 -4 29 27 0 1 0.98291 -4 29 28 0 1 1 -4 29 29 0 1 1 -4 29 30 0 0.996582 1 -4 29 31 0 0.951172 1 -4 30 0 0 1 0 -4 30 1 0 1 0 -4 30 2 0 1 0 -4 30 3 0 1 0 -4 30 4 0 1 0 -4 30 5 0 1 0 -4 30 6 0 1 0 -4 30 7 0 1 0 -4 30 8 0 1 0 -4 30 9 0 1 0 -4 30 10 0 1 0 -4 30 11 0 1 0 -4 30 12 0 1 0 -4 30 13 0 1 0 -4 30 14 0 1 0 -4 30 15 0 1 0 -4 30 16 0 1 0.182007 -4 30 17 0 1 0.304688 -4 30 18 0 1 0.397217 -4 30 19 0 1 0.479248 -4 30 20 0 1 0.554199 -4 30 21 0 1 0.624512 -4 30 22 0 1 0.689453 -4 30 23 0 1 0.747559 -4 30 24 0 1 0.799805 -4 30 25 0 1 0.850586 -4 30 26 0 1 0.899902 -4 30 27 0 1 0.946289 -4 30 28 0 1 0.988281 -4 30 29 0 1 1 -4 30 30 0 1 1 -4 30 31 0 1 1 -4 31 0 0 1 0 -4 31 1 0 1 0 -4 31 2 0 1 0 -4 31 3 0 1 0 -4 31 4 0 1 0 -4 31 5 0 1 0 -4 31 6 0 1 0 -4 31 7 0 1 0 -4 31 8 0 1 0 -4 31 9 0 1 0 -4 31 10 0 1 0 -4 31 11 0 1 0 -4 31 12 0 1 0 -4 31 13 0 1 0 -4 31 14 0 1 0 -4 31 15 0 1 0 -4 31 16 0 1 0.0875244 -4 31 17 0 1 0.260742 -4 31 18 0 1 0.356934 -4 31 19 0 1 0.438232 -4 31 20 0 1 0.51123 -4 31 21 0 1 0.57959 -4 31 22 0 1 0.643066 -4 31 23 0 1 0.700684 -4 31 24 0 1 0.752441 -4 31 25 0 1 0.804199 -4 31 26 0 1 0.855469 -4 31 27 0 1 0.904785 -4 31 28 0 1 0.951172 -4 31 29 0 1 0.992676 -4 31 30 0 1 1 -4 31 31 0 1 1 -5 0 0 0.0801392 0.0216522 0 -5 0 1 0.0800781 0.021225 0.0188599 -5 0 2 0.0794678 0.02034 0.0296631 -5 0 3 0.0772095 0.0191498 0.0399475 -5 0 4 0.0672607 0.0215759 0.0467224 -5 0 5 0.0596619 0.025177 0.0543518 -5 0 6 0.056427 0.0271606 0.0695801 -5 0 7 0.0476074 0.029953 0.0883789 -5 0 8 0 0.0343018 0.112183 -5 0 9 0 0.040863 0.142944 -5 0 10 0 0.050415 0.18335 -5 0 11 0 0.0633545 0.235229 -5 0 12 0 0.0788574 0.296387 -5 0 13 0 0.0966187 0.365723 -5 0 14 0 0.116394 0.442139 -5 0 15 0 0.137573 0.523926 -5 0 16 0 0.159546 0.608398 -5 0 17 0 0.180786 0.689941 -5 0 18 0 0.200439 0.764648 -5 0 19 0 0.217529 0.830566 -5 0 20 0 0.227173 0.867188 -5 0 21 0 0.229004 0.874512 -5 0 22 0 0.230957 0.882324 -5 0 23 0 0.23291 0.889648 -5 0 24 0 0.234985 0.897461 -5 0 25 0 0.237183 0.90625 -5 0 26 0 0.239624 0.915527 -5 0 27 0 0.242432 0.92627 -5 0 28 0 0.245483 0.937988 -5 0 29 0 0.248779 0.950684 -5 0 30 0 0.252197 0.963867 -5 0 31 0 0.255859 0.977051 -5 1 0 0.0789185 0.0271149 0 -5 1 1 0.0790405 0.0268707 0.0183411 -5 1 2 0.0786743 0.0262451 0.0292053 -5 1 3 0.0768433 0.025177 0.0396729 -5 1 4 0.0675659 0.0252075 0.0469971 -5 1 5 0.0594177 0.0274811 0.0543213 -5 1 6 0.0561523 0.0292664 0.0695801 -5 1 7 0.0472717 0.0317383 0.0883789 -5 1 8 0 0.0357056 0.112183 -5 1 9 0 0.0419006 0.142944 -5 1 10 0 0.051178 0.18335 -5 1 11 0 0.0639038 0.235229 -5 1 12 0 0.0792847 0.296387 -5 1 13 0 0.0969238 0.365723 -5 1 14 0 0.116638 0.442139 -5 1 15 0 0.137695 0.523926 -5 1 16 0 0.159668 0.608398 -5 1 17 0 0.180908 0.689941 -5 1 18 0 0.200439 0.764648 -5 1 19 0 0.217651 0.830566 -5 1 20 0 0.227173 0.867188 -5 1 21 0 0.229004 0.874512 -5 1 22 0 0.230957 0.882324 -5 1 23 0 0.23291 0.889648 -5 1 24 0 0.234985 0.897461 -5 1 25 0 0.237183 0.90625 -5 1 26 0 0.239624 0.915527 -5 1 27 0 0.242432 0.92627 -5 1 28 0 0.245483 0.937988 -5 1 29 0 0.248779 0.950684 -5 1 30 0 0.252197 0.963867 -5 1 31 0 0.255859 0.977051 -5 2 0 0.0765381 0.0333252 0 -5 2 1 0.0767822 0.0332031 0.017807 -5 2 2 0.0769043 0.032959 0.0284119 -5 2 3 0.0757446 0.0321045 0.039032 -5 2 4 0.0681763 0.0304871 0.0475159 -5 2 5 0.0589905 0.0309448 0.0542603 -5 2 6 0.0556946 0.0325012 0.069519 -5 2 7 0.0466919 0.0345764 0.0883789 -5 2 8 0 0.0379944 0.112183 -5 2 9 0 0.0436707 0.142944 -5 2 10 0 0.0525208 0.18335 -5 2 11 0 0.0648804 0.235229 -5 2 12 0 0.0800171 0.296387 -5 2 13 0 0.0974731 0.365723 -5 2 14 0 0.117004 0.442139 -5 2 15 0 0.138062 0.523926 -5 2 16 0 0.159912 0.608398 -5 2 17 0 0.18103 0.689941 -5 2 18 0 0.200562 0.764648 -5 2 19 0 0.217773 0.830566 -5 2 20 0 0.227295 0.867188 -5 2 21 0 0.229126 0.874512 -5 2 22 0 0.231079 0.882324 -5 2 23 0 0.233032 0.889648 -5 2 24 0 0.234985 0.897461 -5 2 25 0 0.237183 0.90625 -5 2 26 0 0.239746 0.915527 -5 2 27 0 0.242432 0.92627 -5 2 28 0 0.245483 0.937988 -5 2 29 0 0.248779 0.950684 -5 2 30 0 0.252197 0.963867 -5 2 31 0 0.255859 0.977051 -5 3 0 0.0717773 0.0396729 0 -5 3 1 0.0720215 0.0397644 0.018158 -5 3 2 0.0725098 0.0399475 0.0273285 -5 3 3 0.0731812 0.0401001 0.0377808 -5 3 4 0.0691528 0.0383301 0.0483093 -5 3 5 0.0582581 0.0360718 0.0541992 -5 3 6 0.0548401 0.0373535 0.069458 -5 3 7 0.0455627 0.0389404 0.0883179 -5 3 8 0 0.0417175 0.112183 -5 3 9 0 0.0466309 0.142944 -5 3 10 0 0.0548096 0.183228 -5 3 11 0 0.0666504 0.235229 -5 3 12 0 0.0812988 0.296387 -5 3 13 0 0.0984497 0.365723 -5 3 14 0 0.117737 0.442139 -5 3 15 0 0.13855 0.523926 -5 3 16 0 0.160278 0.608398 -5 3 17 0 0.181396 0.689941 -5 3 18 0 0.200806 0.764648 -5 3 19 0 0.217896 0.830566 -5 3 20 0 0.227417 0.867188 -5 3 21 0 0.229248 0.874512 -5 3 22 0 0.231079 0.882324 -5 3 23 0 0.233032 0.889648 -5 3 24 0 0.235107 0.897461 -5 3 25 0 0.237305 0.90625 -5 3 26 0 0.239746 0.915527 -5 3 27 0 0.242432 0.92627 -5 3 28 0 0.245605 0.937988 -5 3 29 0 0.248901 0.950684 -5 3 30 0 0.252197 0.963867 -5 3 31 0 0.255859 0.977051 -5 4 0 0.0646362 0.0455627 0.0157166 -5 4 1 0.0645142 0.0455933 0.0209656 -5 4 2 0.0644531 0.0457458 0.0270996 -5 4 3 0.0647583 0.0462952 0.0350647 -5 4 4 0.0665894 0.0479736 0.0471191 -5 4 5 0.0568237 0.043457 0.0540771 -5 4 6 0.0531616 0.0444641 0.0693359 -5 4 7 0.043335 0.0455627 0.0882568 -5 4 8 0 0.0475769 0.112122 -5 4 9 0 0.0515442 0.142822 -5 4 10 0 0.0587463 0.183228 -5 4 11 0 0.0697632 0.235229 -5 4 12 0 0.0836792 0.296387 -5 4 13 0 0.10022 0.365723 -5 4 14 0 0.119019 0.442139 -5 4 15 0 0.139526 0.523926 -5 4 16 0 0.161011 0.608398 -5 4 17 0 0.182007 0.689941 -5 4 18 0 0.201294 0.764648 -5 4 19 0 0.218262 0.830566 -5 4 20 0 0.227661 0.867188 -5 4 21 0 0.22937 0.874512 -5 4 22 0 0.231323 0.882324 -5 4 23 0 0.233276 0.889648 -5 4 24 0 0.235229 0.897461 -5 4 25 0 0.237427 0.90625 -5 4 26 0 0.239868 0.915527 -5 4 27 0 0.242554 0.92627 -5 4 28 0 0.245605 0.937988 -5 4 29 0 0.248901 0.950684 -5 4 30 0 0.252441 0.963867 -5 4 31 0 0.255859 0.977051 -5 5 0 0.0617676 0.0567627 0.0178528 -5 5 1 0.0613708 0.0566101 0.0224152 -5 5 2 0.06073 0.0563354 0.0279694 -5 5 3 0.0596008 0.0558777 0.0348511 -5 5 4 0.0576172 0.0551758 0.043457 -5 5 5 0.053894 0.053894 0.053894 -5 5 6 0.0496521 0.0545959 0.0690918 -5 5 7 0.0383911 0.0552368 0.0881348 -5 5 8 0 0.056427 0.112061 -5 5 9 0 0.0593262 0.142822 -5 5 10 0 0.0653687 0.183105 -5 5 11 0 0.0751953 0.235107 -5 5 12 0 0.0879517 0.296387 -5 5 13 0 0.103516 0.365723 -5 5 14 0 0.121521 0.442139 -5 5 15 0 0.141357 0.523926 -5 5 16 0 0.162476 0.608398 -5 5 17 0 0.182983 0.689941 -5 5 18 0 0.202148 0.764648 -5 5 19 0 0.218994 0.830566 -5 5 20 0 0.228271 0.867188 -5 5 21 0 0.229858 0.874512 -5 5 22 0 0.231689 0.882324 -5 5 23 0 0.233521 0.889648 -5 5 24 0 0.235474 0.897461 -5 5 25 0 0.237671 0.90625 -5 5 26 0 0.23999 0.915527 -5 5 27 0 0.242676 0.92627 -5 5 28 0 0.245728 0.937988 -5 5 29 0 0.249023 0.950684 -5 5 30 0 0.252441 0.963867 -5 5 31 0 0.255859 0.977051 -5 6 0 0.053772 0.0697632 0.0170898 -5 6 1 0.0537109 0.0697632 0.0184937 -5 6 2 0.0531311 0.069519 0.0251465 -5 6 3 0.0520935 0.0690918 0.0326843 -5 6 4 0.0502319 0.0683594 0.0417786 -5 6 5 0.0471802 0.0679321 0.0534058 -5 6 6 0.0415344 0.0681763 0.0686035 -5 6 7 0.0239105 0.0684814 0.0877686 -5 6 8 0 0.0689697 0.111938 -5 6 9 0 0.0708618 0.1427 -5 6 10 0 0.0756226 0.182983 -5 6 11 0 0.0841064 0.234985 -5 6 12 0 0.0953369 0.296387 -5 6 13 0 0.109375 0.365723 -5 6 14 0 0.126099 0.442139 -5 6 15 0 0.144897 0.523926 -5 6 16 0 0.165161 0.608398 -5 6 17 0 0.185059 0.689941 -5 6 18 0 0.203735 0.764648 -5 6 19 0 0.220215 0.830566 -5 6 20 0 0.229248 0.867676 -5 6 21 0 0.230713 0.874512 -5 6 22 0 0.2323 0.882324 -5 6 23 0 0.234131 0.889648 -5 6 24 0 0.235962 0.897461 -5 6 25 0 0.238037 0.90625 -5 6 26 0 0.240356 0.915527 -5 6 27 0 0.243042 0.92627 -5 6 28 0 0.245972 0.937988 -5 6 29 0 0.249268 0.950684 -5 6 30 0 0.252686 0.963867 -5 6 31 0 0.256104 0.977051 -5 7 0 0.0345764 0.0861816 0.0160675 -5 7 1 0.0346069 0.0861816 0.0160675 -5 7 2 0.0344238 0.0861816 0.0190582 -5 7 3 0.0331421 0.0861206 0.0288086 -5 7 4 0.0304871 0.0859985 0.0392456 -5 7 5 0.0241241 0.0859985 0.0518494 -5 7 6 0 0.0861206 0.0674438 -5 7 7 0 0.0862427 0.0869751 -5 7 8 0 0.0862427 0.111511 -5 7 9 0 0.0872192 0.142456 -5 7 10 0 0.0909424 0.182739 -5 7 11 0 0.0980835 0.234863 -5 7 12 0 0.107483 0.296143 -5 7 13 0 0.119507 0.365723 -5 7 14 0 0.134155 0.442139 -5 7 15 0 0.151245 0.523926 -5 7 16 0 0.170166 0.608398 -5 7 17 0 0.188965 0.689941 -5 7 18 0 0.206787 0.765137 -5 7 19 0 0.222656 0.831055 -5 7 20 0 0.231201 0.867676 -5 7 21 0 0.232178 0.874512 -5 7 22 0 0.233643 0.882324 -5 7 23 0 0.235107 0.890137 -5 7 24 0 0.236816 0.897461 -5 7 25 0 0.23877 0.90625 -5 7 26 0 0.241089 0.915527 -5 7 27 0 0.243652 0.92627 -5 7 28 0 0.246582 0.937988 -5 7 29 0 0.249634 0.950684 -5 7 30 0 0.25293 0.963867 -5 7 31 0 0.256348 0.977051 -5 8 0 0 0.108704 0.0147934 -5 8 1 0 0.108704 0.014801 -5 8 2 0 0.108765 0.0148239 -5 8 3 0 0.108826 0.0198364 -5 8 4 0 0.108826 0.0343018 -5 8 5 0 0.108948 0.0485229 -5 8 6 0 0.109192 0.0650024 -5 8 7 0 0.109314 0.0852661 -5 8 8 0 0.109314 0.110474 -5 8 9 0 0.109741 0.141968 -5 8 10 0 0.11261 0.182373 -5 8 11 0 0.118713 0.234497 -5 8 12 0 0.126465 0.295898 -5 8 13 0 0.136108 0.365479 -5 8 14 0 0.148193 0.442139 -5 8 15 0 0.16272 0.523926 -5 8 16 0 0.179199 0.608398 -5 8 17 0 0.196167 0.689941 -5 8 18 0 0.212524 0.765137 -5 8 19 0 0.227295 0.831055 -5 8 20 0 0.234985 0.867676 -5 8 21 0 0.235229 0.875 -5 8 22 0 0.236084 0.882324 -5 8 23 0 0.237305 0.890137 -5 8 24 0 0.238647 0.897949 -5 8 25 0 0.240356 0.90625 -5 8 26 0 0.24231 0.916016 -5 8 27 0 0.244751 0.92627 -5 8 28 0 0.247437 0.937988 -5 8 29 0 0.250488 0.950684 -5 8 30 0 0.253662 0.963867 -5 8 31 0 0.25708 0.977539 -5 9 0 0 0.137817 0.0123978 -5 9 1 0 0.137817 0.0124054 -5 9 2 0 0.137817 0.0124283 -5 9 3 0 0.137817 0.0124741 -5 9 4 0 0.137939 0.0211334 -5 9 5 0 0.138062 0.0420532 -5 9 6 0 0.138184 0.0606689 -5 9 7 0 0.138428 0.0820923 -5 9 8 0 0.138794 0.108398 -5 9 9 0 0.139404 0.140991 -5 9 10 0 0.141724 0.181763 -5 9 11 0 0.147217 0.233887 -5 9 12 0 0.153687 0.295654 -5 9 13 0 0.161133 0.365234 -5 9 14 0 0.170288 0.442139 -5 9 15 0 0.181641 0.523926 -5 9 16 0 0.194946 0.608398 -5 9 17 0 0.208984 0.689941 -5 9 18 0 0.2229 0.765137 -5 9 19 0 0.23584 0.831055 -5 9 20 0 0.242065 0.868164 -5 9 21 0 0.240967 0.875488 -5 9 22 0 0.240723 0.882812 -5 9 23 0 0.241211 0.890625 -5 9 24 0 0.241943 0.897949 -5 9 25 0 0.243286 0.906738 -5 9 26 0 0.244873 0.916016 -5 9 27 0 0.246826 0.92627 -5 9 28 0 0.24939 0.938477 -5 9 29 0 0.252197 0.950684 -5 9 30 0 0.255127 0.963867 -5 9 31 0 0.258301 0.977539 -5 10 0 0 0.175415 0.00350189 -5 10 1 0 0.175415 0.00359535 -5 10 2 0 0.175415 0.00375175 -5 10 3 0 0.175537 0.00401306 -5 10 4 0 0.175537 0.00444794 -5 10 5 0 0.175659 0.0254974 -5 10 6 0 0.175659 0.0534363 -5 10 7 0 0.175659 0.0778198 -5 10 8 0 0.176025 0.105774 -5 10 9 0 0.176758 0.139648 -5 10 10 0 0.178955 0.181152 -5 10 11 0 0.183716 0.233032 -5 10 12 0 0.189331 0.294922 -5 10 13 0 0.19519 0.36499 -5 10 14 0 0.201782 0.441895 -5 10 15 0 0.209595 0.523926 -5 10 16 0 0.219238 0.608887 -5 10 17 0 0.229614 0.69043 -5 10 18 0 0.240112 0.765625 -5 10 19 0 0.250244 0.831543 -5 10 20 0 0.25415 0.869141 -5 10 21 0 0.250732 0.875977 -5 10 22 0 0.248779 0.883301 -5 10 23 0 0.248047 0.891113 -5 10 24 0 0.247925 0.898438 -5 10 25 0 0.248413 0.907227 -5 10 26 0 0.249268 0.916504 -5 10 27 0 0.250732 0.926758 -5 10 28 0 0.252686 0.938477 -5 10 29 0 0.254883 0.951172 -5 10 30 0 0.257568 0.964355 -5 10 31 0 0.260254 0.977539 -5 11 0 0 0.224365 0 -5 11 1 0 0.224365 0 -5 11 2 0 0.224365 0 -5 11 3 0 0.224487 0 -5 11 4 0 0.224487 0 -5 11 5 0 0.224609 0 -5 11 6 0 0.224609 0.03479 -5 11 7 0 0.224487 0.0705566 -5 11 8 0 0.224365 0.102417 -5 11 9 0 0.224731 0.138428 -5 11 10 0 0.226196 0.18103 -5 11 11 0 0.229614 0.232422 -5 11 12 0 0.234131 0.293945 -5 11 13 0 0.238647 0.364258 -5 11 14 0 0.243164 0.44165 -5 11 15 0 0.247925 0.523926 -5 11 16 0 0.253662 0.608887 -5 11 17 0 0.259766 0.690918 -5 11 18 0 0.266357 0.765625 -5 11 19 0 0.272705 0.832031 -5 11 20 0 0.273438 0.870605 -5 11 21 0 0.266602 0.877441 -5 11 22 0 0.262207 0.884766 -5 11 23 0 0.259521 0.89209 -5 11 24 0 0.257812 0.899414 -5 11 25 0 0.25708 0.907715 -5 11 26 0 0.256836 0.916992 -5 11 27 0 0.25708 0.927246 -5 11 28 0 0.258301 0.938965 -5 11 29 0 0.259766 0.95166 -5 11 30 0 0.261719 0.964355 -5 11 31 0 0.263916 0.978027 -5 12 0 0 0.283936 0 -5 12 1 0 0.283936 0 -5 12 2 0 0.283936 0 -5 12 3 0 0.283936 0 -5 12 4 0 0.283936 0 -5 12 5 0 0.283936 0 -5 12 6 0 0.283936 0 -5 12 7 0 0.28418 0.0507812 -5 12 8 0 0.28418 0.0946045 -5 12 9 0 0.28418 0.135254 -5 12 10 0 0.284668 0.17981 -5 12 11 0 0.286133 0.231567 -5 12 12 0 0.289062 0.292725 -5 12 13 0 0.29248 0.363037 -5 12 14 0 0.295166 0.440918 -5 12 15 0 0.297607 0.523438 -5 12 16 0 0.299805 0.608887 -5 12 17 0 0.301514 0.691406 -5 12 18 0 0.303711 0.766602 -5 12 19 0 0.305664 0.83252 -5 12 20 0 0.30249 0.873047 -5 12 21 0 0.291016 0.879395 -5 12 22 0 0.282959 0.886719 -5 12 23 0 0.277588 0.893555 -5 12 24 0 0.273682 0.900879 -5 12 25 0 0.270752 0.90918 -5 12 26 0 0.268799 0.918457 -5 12 27 0 0.267822 0.928711 -5 12 28 0 0.267578 0.939941 -5 12 29 0 0.267822 0.952148 -5 12 30 0 0.268799 0.965332 -5 12 31 0 0.27002 0.978516 -5 13 0 0 0.351562 0 -5 13 1 0 0.351562 0 -5 13 2 0 0.351562 0 -5 13 3 0 0.351562 0 -5 13 4 0 0.351562 0 -5 13 5 0 0.351562 0 -5 13 6 0 0.351562 0 -5 13 7 0 0.351807 0 -5 13 8 0 0.351807 0.0744019 -5 13 9 0 0.352051 0.125854 -5 13 10 0 0.352295 0.174927 -5 13 11 0 0.353027 0.22876 -5 13 12 0 0.354492 0.290527 -5 13 13 0 0.356445 0.36084 -5 13 14 0 0.35791 0.439209 -5 13 15 0 0.35791 0.522949 -5 13 16 0 0.357178 0.608887 -5 13 17 0 0.355225 0.691895 -5 13 18 0 0.352539 0.767578 -5 13 19 0 0.350098 0.833496 -5 13 20 0 0.342773 0.876953 -5 13 21 0 0.325684 0.883301 -5 13 22 0 0.312988 0.889648 -5 13 23 0 0.303711 0.896484 -5 13 24 0 0.297119 0.903809 -5 13 25 0 0.291504 0.911621 -5 13 26 0 0.287354 0.92041 -5 13 27 0 0.283936 0.930176 -5 13 28 0 0.281738 0.941406 -5 13 29 0 0.280273 0.953613 -5 13 30 0 0.279785 0.966309 -5 13 31 0 0.279541 0.979492 -5 14 0 0 0.426758 0 -5 14 1 0 0.426758 0 -5 14 2 0 0.426758 0 -5 14 3 0 0.426758 0 -5 14 4 0 0.426758 0 -5 14 5 0 0.426758 0 -5 14 6 0 0.426758 0 -5 14 7 0 0.427002 0 -5 14 8 0 0.427246 0 -5 14 9 0 0.42749 0.105591 -5 14 10 0 0.427734 0.16394 -5 14 11 0 0.428467 0.221802 -5 14 12 0 0.429199 0.285645 -5 14 13 0 0.430176 0.356934 -5 14 14 0 0.43042 0.435791 -5 14 15 0 0.429199 0.520508 -5 14 16 0 0.42627 0.60791 -5 14 17 0 0.420654 0.691895 -5 14 18 0 0.413818 0.768066 -5 14 19 0 0.406738 0.834961 -5 14 20 0 0.395752 0.882324 -5 14 21 0 0.37207 0.888672 -5 14 22 0 0.35376 0.894531 -5 14 23 0 0.340088 0.901367 -5 14 24 0 0.329834 0.907715 -5 14 25 0 0.321045 0.915039 -5 14 26 0 0.313477 0.923828 -5 14 27 0 0.307373 0.933105 -5 14 28 0 0.30249 0.944336 -5 14 29 0 0.298828 0.956055 -5 14 30 0 0.295898 0.968262 -5 14 31 0 0.293945 0.981445 -5 15 0 0 0.507812 0 -5 15 1 0 0.507812 0 -5 15 2 0 0.507812 0 -5 15 3 0 0.507812 0 -5 15 4 0 0.507812 0 -5 15 5 0 0.507812 0 -5 15 6 0 0.507812 0 -5 15 7 0 0.507812 0 -5 15 8 0 0.507812 0 -5 15 9 0 0.508301 0.0464172 -5 15 10 0 0.508789 0.143066 -5 15 11 0 0.509766 0.208618 -5 15 12 0 0.510742 0.276123 -5 15 13 0 0.51123 0.349365 -5 15 14 0 0.51123 0.429688 -5 15 15 0 0.509277 0.516113 -5 15 16 0 0.504883 0.605469 -5 15 17 0 0.496826 0.690918 -5 15 18 0 0.486328 0.768555 -5 15 19 0 0.474854 0.836426 -5 15 20 0 0.461182 0.88916 -5 15 21 0 0.430664 0.895996 -5 15 22 0 0.40625 0.902344 -5 15 23 0 0.387451 0.908203 -5 15 24 0 0.372803 0.914551 -5 15 25 0 0.360107 0.921387 -5 15 26 0 0.348633 0.929199 -5 15 27 0 0.339111 0.937988 -5 15 28 0 0.331055 0.948242 -5 15 29 0 0.324219 0.959473 -5 15 30 0 0.318604 0.97168 -5 15 31 0 0.314209 0.983887 -5 16 0 0 0.592773 0 -5 16 1 0 0.592773 0 -5 16 2 0 0.592773 0 -5 16 3 0 0.592773 0 -5 16 4 0 0.592773 0 -5 16 5 0 0.592773 0 -5 16 6 0 0.592773 0 -5 16 7 0 0.592773 0 -5 16 8 0 0.592773 0 -5 16 9 0 0.592773 0 -5 16 10 0 0.593262 0.101196 -5 16 11 0 0.594238 0.187012 -5 16 12 0 0.595703 0.260498 -5 16 13 0 0.597168 0.336914 -5 16 14 0 0.597656 0.419189 -5 16 15 0 0.596191 0.507324 -5 16 16 0 0.591309 0.598633 -5 16 17 0 0.582031 0.687012 -5 16 18 0 0.568848 0.76709 -5 16 19 0 0.553711 0.836426 -5 16 20 0 0.537598 0.893555 -5 16 21 0 0.501465 0.905762 -5 16 22 0 0.471191 0.913086 -5 16 23 0 0.446777 0.918945 -5 16 24 0 0.427246 0.924805 -5 16 25 0 0.409668 0.930664 -5 16 26 0 0.394043 0.9375 -5 16 27 0 0.380127 0.945801 -5 16 28 0 0.368164 0.955078 -5 16 29 0 0.357666 0.965332 -5 16 30 0 0.348877 0.976562 -5 16 31 0 0.341064 0.988281 -5 17 0 0 0.67627 0 -5 17 1 0 0.67627 0 -5 17 2 0 0.67627 0 -5 17 3 0 0.67627 0 -5 17 4 0 0.67627 0 -5 17 5 0 0.67627 0 -5 17 6 0 0.67627 0 -5 17 7 0 0.67627 0 -5 17 8 0 0.676758 0 -5 17 9 0 0.676758 0 -5 17 10 0 0.676758 0 -5 17 11 0 0.678223 0.151733 -5 17 12 0 0.679688 0.237915 -5 17 13 0 0.681641 0.318848 -5 17 14 0 0.683105 0.403564 -5 17 15 0 0.683105 0.493652 -5 17 16 0 0.679199 0.587402 -5 17 17 0 0.669922 0.678223 -5 17 18 0 0.655762 0.761719 -5 17 19 0 0.638672 0.833984 -5 17 20 0 0.619141 0.893066 -5 17 21 0 0.582031 0.916016 -5 17 22 0 0.546387 0.926758 -5 17 23 0 0.516602 0.933594 -5 17 24 0 0.491699 0.938965 -5 17 25 0 0.468994 0.944336 -5 17 26 0 0.448486 0.950195 -5 17 27 0 0.429688 0.957031 -5 17 28 0 0.41333 0.964844 -5 17 29 0 0.398682 0.973633 -5 17 30 0 0.385986 0.983887 -5 17 31 0 0.374512 0.994141 -5 18 0 0 0.754395 0 -5 18 1 0 0.754395 0 -5 18 2 0 0.754395 0 -5 18 3 0 0.754395 0 -5 18 4 0 0.754395 0 -5 18 5 0 0.754395 0 -5 18 6 0 0.754395 0 -5 18 7 0 0.754395 0 -5 18 8 0 0.754395 0 -5 18 9 0 0.754883 0 -5 18 10 0 0.754883 0 -5 18 11 0 0.755371 0.0776367 -5 18 12 0 0.757324 0.206421 -5 18 13 0 0.759766 0.294922 -5 18 14 0 0.762207 0.382812 -5 18 15 0 0.763672 0.474365 -5 18 16 0 0.762207 0.570312 -5 18 17 0 0.754883 0.664551 -5 18 18 0 0.742188 0.751465 -5 18 19 0 0.724121 0.827148 -5 18 20 0 0.702637 0.889648 -5 18 21 0 0.66748 0.924316 -5 18 22 0 0.629395 0.941406 -5 18 23 0 0.594727 0.951172 -5 18 24 0 0.564941 0.957031 -5 18 25 0 0.537109 0.962402 -5 18 26 0 0.510742 0.966797 -5 18 27 0 0.487061 0.972168 -5 18 28 0 0.465576 0.978516 -5 18 29 0 0.446289 0.985352 -5 18 30 0 0.428955 0.993652 -5 18 31 0 0.413574 1 -5 19 0 0 0.824707 0 -5 19 1 0 0.824707 0 -5 19 2 0 0.824707 0 -5 19 3 0 0.824707 0 -5 19 4 0 0.824707 0 -5 19 5 0 0.824707 0 -5 19 6 0 0.824707 0 -5 19 7 0 0.824707 0 -5 19 8 0 0.824707 0 -5 19 9 0 0.824707 0 -5 19 10 0 0.824707 0 -5 19 11 0 0.825195 0 -5 19 12 0 0.82666 0.162354 -5 19 13 0 0.82959 0.266113 -5 19 14 0 0.83252 0.358154 -5 19 15 0 0.835449 0.451416 -5 19 16 0 0.835938 0.54834 -5 19 17 0 0.832031 0.64502 -5 19 18 0 0.821777 0.73584 -5 19 19 0 0.805176 0.81543 -5 19 20 0 0.783691 0.881348 -5 19 21 0 0.751953 0.927246 -5 19 22 0 0.714355 0.953613 -5 19 23 0 0.677246 0.968262 -5 19 24 0 0.643555 0.977051 -5 19 25 0 0.610352 0.982422 -5 19 26 0 0.579102 0.986816 -5 19 27 0 0.549805 0.990723 -5 19 28 0 0.522949 0.995117 -5 19 29 0 0.498535 1 -5 19 30 0 0.476562 1 -5 19 31 0 0.456787 1 -5 20 0 0 0.885254 0 -5 20 1 0 0.885254 0 -5 20 2 0 0.885254 0 -5 20 3 0 0.885254 0 -5 20 4 0 0.885254 0 -5 20 5 0 0.885254 0 -5 20 6 0 0.885254 0 -5 20 7 0 0.885254 0 -5 20 8 0 0.885254 0 -5 20 9 0 0.885254 0 -5 20 10 0 0.885254 0 -5 20 11 0 0.885742 0 -5 20 12 0 0.88623 0.0791626 -5 20 13 0 0.88916 0.231934 -5 20 14 0 0.893066 0.330811 -5 20 15 0 0.896973 0.42627 -5 20 16 0 0.899414 0.524414 -5 20 17 0 0.898438 0.62207 -5 20 18 0 0.891113 0.715332 -5 20 19 0 0.876953 0.797852 -5 20 20 0 0.856934 0.867676 -5 20 21 0 0.830078 0.922852 -5 20 22 0 0.79541 0.959961 -5 20 23 0 0.758301 0.981445 -5 20 24 0 0.722656 0.994141 -5 20 25 0 0.686035 1 -5 20 26 0 0.649902 1 -5 20 27 0 0.615723 1 -5 20 28 0 0.583496 1 -5 20 29 0 0.553711 1 -5 20 30 0 0.526855 1 -5 20 31 0 0.502441 1 -5 21 0 0 0.936523 0 -5 21 1 0 0.936523 0 -5 21 2 0 0.936523 0 -5 21 3 0 0.936523 0 -5 21 4 0 0.936523 0 -5 21 5 0 0.936523 0 -5 21 6 0 0.936523 0 -5 21 7 0 0.936523 0 -5 21 8 0 0.936523 0 -5 21 9 0 0.937012 0 -5 21 10 0 0.937012 0 -5 21 11 0 0.937012 0 -5 21 12 0 0.9375 0 -5 21 13 0 0.939941 0.189331 -5 21 14 0 0.943848 0.300537 -5 21 15 0 0.94873 0.398682 -5 21 16 0 0.953125 0.497559 -5 21 17 0 0.954102 0.595703 -5 21 18 0 0.950195 0.69043 -5 21 19 0 0.939453 0.775879 -5 21 20 0 0.922363 0.849121 -5 21 21 0 0.899414 0.910645 -5 21 22 0 0.869629 0.957031 -5 21 23 0 0.835449 0.987305 -5 21 24 0 0.799805 1 -5 21 25 0 0.76123 1 -5 21 26 0 0.722168 1 -5 21 27 0 0.683594 1 -5 21 28 0 0.646484 1 -5 21 29 0 0.611816 1 -5 21 30 0 0.580078 1 -5 21 31 0 0.550781 1 -5 22 0 0 0.979492 0 -5 22 1 0 0.979492 0 -5 22 2 0 0.979492 0 -5 22 3 0 0.979492 0 -5 22 4 0 0.979492 0 -5 22 5 0 0.979492 0 -5 22 6 0 0.979492 0 -5 22 7 0 0.979492 0 -5 22 8 0 0.979492 0 -5 22 9 0 0.979492 0 -5 22 10 0 0.979492 0 -5 22 11 0 0.979492 0 -5 22 12 0 0.97998 0 -5 22 13 0 0.981445 0.128418 -5 22 14 0 0.985352 0.267334 -5 22 15 0 0.990723 0.369873 -5 22 16 0 0.996094 0.469238 -5 22 17 0 1 0.567871 -5 22 18 0 0.999023 0.663086 -5 22 19 0 0.991699 0.750488 -5 22 20 0 0.978027 0.82666 -5 22 21 0 0.958008 0.891602 -5 22 22 0 0.933105 0.944824 -5 22 23 0 0.90332 0.983398 -5 22 24 0 0.870117 1 -5 22 25 0 0.83252 1 -5 22 26 0 0.791992 1 -5 22 27 0 0.750488 1 -5 22 28 0 0.709961 1 -5 22 29 0 0.670898 1 -5 22 30 0 0.634277 1 -5 22 31 0 0.600586 1 -5 23 0 0 1 0 -5 23 1 0 1 0 -5 23 2 0 1 0 -5 23 3 0 1 0 -5 23 4 0 1 0 -5 23 5 0 1 0 -5 23 6 0 1 0 -5 23 7 0 1 0 -5 23 8 0 1 0 -5 23 9 0 1 0 -5 23 10 0 1 0 -5 23 11 0 1 0 -5 23 12 0 1 0 -5 23 13 0 1 0 -5 23 14 0 1 0.231689 -5 23 15 0 1 0.341064 -5 23 16 0 1 0.44165 -5 23 17 0 1 0.539551 -5 23 18 0 1 0.634766 -5 23 19 0 1 0.723145 -5 23 20 0 1 0.80127 -5 23 21 0 1 0.869629 -5 23 22 0 0.984375 0.92627 -5 23 23 0 0.958984 0.970703 -5 23 24 0 0.929688 1 -5 23 25 0 0.89502 1 -5 23 26 0 0.85498 1 -5 23 27 0 0.8125 1 -5 23 28 0 0.769531 1 -5 23 29 0 0.727539 1 -5 23 30 0 0.687012 1 -5 23 31 0 0.648926 1 -5 24 0 0 1 0 -5 24 1 0 1 0 -5 24 2 0 1 0 -5 24 3 0 1 0 -5 24 4 0 1 0 -5 24 5 0 1 0 -5 24 6 0 1 0 -5 24 7 0 1 0 -5 24 8 0 1 0 -5 24 9 0 1 0 -5 24 10 0 1 0 -5 24 11 0 1 0 -5 24 12 0 1 0 -5 24 13 0 1 0 -5 24 14 0 1 0.191284 -5 24 15 0 1 0.312012 -5 24 16 0 1 0.414307 -5 24 17 0 1 0.512207 -5 24 18 0 1 0.606934 -5 24 19 0 1 0.695312 -5 24 20 0 1 0.774414 -5 24 21 0 1 0.845215 -5 24 22 0 1 0.904785 -5 24 23 0 1 0.953125 -5 24 24 0 0.979004 0.991699 -5 24 25 0 0.948242 1 -5 24 26 0 0.911133 1 -5 24 27 0 0.869141 1 -5 24 28 0 0.825195 1 -5 24 29 0 0.780762 1 -5 24 30 0 0.737305 1 -5 24 31 0 0.695801 1 -5 25 0 0 1 0 -5 25 1 0 1 0 -5 25 2 0 1 0 -5 25 3 0 1 0 -5 25 4 0 1 0 -5 25 5 0 1 0 -5 25 6 0 1 0 -5 25 7 0 1 0 -5 25 8 0 1 0 -5 25 9 0 1 0 -5 25 10 0 1 0 -5 25 11 0 1 0 -5 25 12 0 1 0 -5 25 13 0 1 0 -5 25 14 0 1 0.132568 -5 25 15 0 1 0.279541 -5 25 16 0 1 0.38501 -5 25 17 0 1 0.482666 -5 25 18 0 1 0.576172 -5 25 19 0 1 0.664062 -5 25 20 0 1 0.744141 -5 25 21 0 1 0.816406 -5 25 22 0 1 0.878906 -5 25 23 0 1 0.930176 -5 25 24 0 1 0.972656 -5 25 25 0 0.99707 1 -5 25 26 0 0.963379 1 -5 25 27 0 0.924316 1 -5 25 28 0 0.880371 1 -5 25 29 0 0.834961 1 -5 25 30 0 0.789551 1 -5 25 31 0 0.745117 1 -5 26 0 0 1 0 -5 26 1 0 1 0 -5 26 2 0 1 0 -5 26 3 0 1 0 -5 26 4 0 1 0 -5 26 5 0 1 0 -5 26 6 0 1 0 -5 26 7 0 1 0 -5 26 8 0 1 0 -5 26 9 0 1 0 -5 26 10 0 1 0 -5 26 11 0 1 0 -5 26 12 0 1 0 -5 26 13 0 1 0 -5 26 14 0 1 0 -5 26 15 0 1 0.241943 -5 26 16 0 1 0.353027 -5 26 17 0 1 0.451172 -5 26 18 0 1 0.543457 -5 26 19 0 1 0.630859 -5 26 20 0 1 0.710938 -5 26 21 0 1 0.783691 -5 26 22 0 1 0.848633 -5 26 23 0 1 0.902832 -5 26 24 0 1 0.948242 -5 26 25 0 1 0.989258 -5 26 26 0 1 1 -5 26 27 0 0.976074 1 -5 26 28 0 0.93457 1 -5 26 29 0 0.889648 1 -5 26 30 0 0.842773 1 -5 26 31 0 0.796387 1 -5 27 0 0 1 0 -5 27 1 0 1 0 -5 27 2 0 1 0 -5 27 3 0 1 0 -5 27 4 0 1 0 -5 27 5 0 1 0 -5 27 6 0 1 0 -5 27 7 0 1 0 -5 27 8 0 1 0 -5 27 9 0 1 0 -5 27 10 0 1 0 -5 27 11 0 1 0 -5 27 12 0 1 0 -5 27 13 0 1 0 -5 27 14 0 1 0 -5 27 15 0 1 0.195557 -5 27 16 0 1 0.318604 -5 27 17 0 1 0.417725 -5 27 18 0 1 0.509277 -5 27 19 0 1 0.595215 -5 27 20 0 1 0.674805 -5 27 21 0 1 0.748047 -5 27 22 0 1 0.813965 -5 27 23 0 1 0.870605 -5 27 24 0 1 0.918457 -5 27 25 0 1 0.962891 -5 27 26 0 1 1 -5 27 27 0 1 1 -5 27 28 0 0.98584 1 -5 27 29 0 0.941895 1 -5 27 30 0 0.895508 1 -5 27 31 0 0.848145 1 -5 28 0 0 1 0 -5 28 1 0 1 0 -5 28 2 0 1 0 -5 28 3 0 1 0 -5 28 4 0 1 0 -5 28 5 0 1 0 -5 28 6 0 1 0 -5 28 7 0 1 0 -5 28 8 0 1 0 -5 28 9 0 1 0 -5 28 10 0 1 0 -5 28 11 0 1 0 -5 28 12 0 1 0 -5 28 13 0 1 0 -5 28 14 0 1 0 -5 28 15 0 1 0.126831 -5 28 16 0 1 0.280518 -5 28 17 0 1 0.382568 -5 28 18 0 1 0.473877 -5 28 19 0 1 0.558105 -5 28 20 0 1 0.63623 -5 28 21 0 1 0.709473 -5 28 22 0 1 0.775879 -5 28 23 0 1 0.833496 -5 28 24 0 1 0.883789 -5 28 25 0 1 0.931152 -5 28 26 0 1 0.974609 -5 28 27 0 1 1 -5 28 28 0 1 1 -5 28 29 0 0.991699 1 -5 28 30 0 0.947266 1 -5 28 31 0 0.899902 1 -5 29 0 0 1 0 -5 29 1 0 1 0 -5 29 2 0 1 0 -5 29 3 0 1 0 -5 29 4 0 1 0 -5 29 5 0 1 0 -5 29 6 0 1 0 -5 29 7 0 1 0 -5 29 8 0 1 0 -5 29 9 0 1 0 -5 29 10 0 1 0 -5 29 11 0 1 0 -5 29 12 0 1 0 -5 29 13 0 1 0 -5 29 14 0 1 0 -5 29 15 0 1 0 -5 29 16 0 1 0.236572 -5 29 17 0 1 0.345215 -5 29 18 0 1 0.436279 -5 29 19 0 1 0.519531 -5 29 20 0 1 0.596191 -5 29 21 0 1 0.667969 -5 29 22 0 1 0.733887 -5 29 23 0 1 0.79248 -5 29 24 0 1 0.84375 -5 29 25 0 1 0.893555 -5 29 26 0 1 0.94043 -5 29 27 0 1 0.98291 -5 29 28 0 1 1 -5 29 29 0 1 1 -5 29 30 0 0.996582 1 -5 29 31 0 0.951172 1 -5 30 0 0 1 0 -5 30 1 0 1 0 -5 30 2 0 1 0 -5 30 3 0 1 0 -5 30 4 0 1 0 -5 30 5 0 1 0 -5 30 6 0 1 0 -5 30 7 0 1 0 -5 30 8 0 1 0 -5 30 9 0 1 0 -5 30 10 0 1 0 -5 30 11 0 1 0 -5 30 12 0 1 0 -5 30 13 0 1 0 -5 30 14 0 1 0 -5 30 15 0 1 0 -5 30 16 0 1 0.182007 -5 30 17 0 1 0.304688 -5 30 18 0 1 0.397217 -5 30 19 0 1 0.479248 -5 30 20 0 1 0.554199 -5 30 21 0 1 0.624512 -5 30 22 0 1 0.689453 -5 30 23 0 1 0.747559 -5 30 24 0 1 0.799805 -5 30 25 0 1 0.850586 -5 30 26 0 1 0.899902 -5 30 27 0 1 0.946289 -5 30 28 0 1 0.988281 -5 30 29 0 1 1 -5 30 30 0 1 1 -5 30 31 0 1 1 -5 31 0 0 1 0 -5 31 1 0 1 0 -5 31 2 0 1 0 -5 31 3 0 1 0 -5 31 4 0 1 0 -5 31 5 0 1 0 -5 31 6 0 1 0 -5 31 7 0 1 0 -5 31 8 0 1 0 -5 31 9 0 1 0 -5 31 10 0 1 0 -5 31 11 0 1 0 -5 31 12 0 1 0 -5 31 13 0 1 0 -5 31 14 0 1 0 -5 31 15 0 1 0 -5 31 16 0 1 0.0875244 -5 31 17 0 1 0.260742 -5 31 18 0 1 0.356934 -5 31 19 0 1 0.438232 -5 31 20 0 1 0.51123 -5 31 21 0 1 0.57959 -5 31 22 0 1 0.643066 -5 31 23 0 1 0.700684 -5 31 24 0 1 0.752441 -5 31 25 0 1 0.804199 -5 31 26 0 1 0.855469 -5 31 27 0 1 0.904785 -5 31 28 0 1 0.951172 -5 31 29 0 1 0.992676 -5 31 30 0 1 1 -5 31 31 0 1 1 -6 0 0 0.102905 0.0176544 0 -6 0 1 0.103088 0.0178833 0 -6 0 2 0.103088 0.017395 0.0204315 -6 0 3 0.102295 0.0152817 0.0361938 -6 0 4 0.0996094 0.0124588 0.050354 -6 0 5 0.086731 0.0227051 0.059845 -6 0 6 0.0766602 0.0295715 0.0697021 -6 0 7 0.0713501 0.0320435 0.088501 -6 0 8 0.0594788 0.0359497 0.112366 -6 0 9 0 0.0421143 0.143066 -6 0 10 0 0.0513 0.183228 -6 0 11 0 0.0639648 0.235229 -6 0 12 0 0.0793457 0.296387 -6 0 13 0 0.0969849 0.365723 -6 0 14 0 0.116638 0.442139 -6 0 15 0 0.137817 0.523926 -6 0 16 0 0.15979 0.608398 -6 0 17 0 0.180908 0.689941 -6 0 18 0 0.200439 0.764648 -6 0 19 0 0.217651 0.830566 -6 0 20 0 0.227173 0.867676 -6 0 21 0 0.229004 0.874512 -6 0 22 0 0.230957 0.882324 -6 0 23 0 0.233032 0.889648 -6 0 24 0 0.234985 0.897461 -6 0 25 0 0.237183 0.90625 -6 0 26 0 0.239746 0.915527 -6 0 27 0 0.242432 0.92627 -6 0 28 0 0.245483 0.937988 -6 0 29 0 0.248779 0.950684 -6 0 30 0 0.252197 0.963867 -6 0 31 0 0.255859 0.977051 -6 1 0 0.102173 0.0248566 0 -6 1 1 0.102356 0.0249939 0 -6 1 2 0.102478 0.024704 0.0199432 -6 1 3 0.101868 0.0234375 0.0358887 -6 1 4 0.0994263 0.021698 0.0501709 -6 1 5 0.0869141 0.026062 0.0599976 -6 1 6 0.0765381 0.0314331 0.0697021 -6 1 7 0.071228 0.0336304 0.088501 -6 1 8 0.0592651 0.037262 0.112366 -6 1 9 0 0.0430908 0.142944 -6 1 10 0 0.052063 0.183228 -6 1 11 0 0.0645142 0.235229 -6 1 12 0 0.0797729 0.296387 -6 1 13 0 0.09729 0.365723 -6 1 14 0 0.116882 0.442139 -6 1 15 0 0.137939 0.523926 -6 1 16 0 0.159912 0.608398 -6 1 17 0 0.18103 0.689941 -6 1 18 0 0.200562 0.764648 -6 1 19 0 0.217773 0.830566 -6 1 20 0 0.227295 0.867676 -6 1 21 0 0.229126 0.874512 -6 1 22 0 0.231079 0.882324 -6 1 23 0 0.233032 0.889648 -6 1 24 0 0.234985 0.897461 -6 1 25 0 0.237183 0.90625 -6 1 26 0 0.239746 0.915527 -6 1 27 0 0.242432 0.92627 -6 1 28 0 0.245483 0.937988 -6 1 29 0 0.248779 0.950684 -6 1 30 0 0.252197 0.963867 -6 1 31 0 0.255859 0.977051 -6 2 0 0.100769 0.0324707 0 -6 2 1 0.101013 0.0325928 0 -6 2 2 0.101257 0.0324402 0.0191956 -6 2 3 0.101013 0.0316162 0.0353088 -6 2 4 0.098938 0.0302124 0.0498352 -6 2 5 0.0872803 0.0308838 0.0603027 -6 2 6 0.0762329 0.0343323 0.0696411 -6 2 7 0.0709229 0.0362244 0.0884399 -6 2 8 0.0588684 0.0394287 0.112305 -6 2 9 0 0.0447998 0.142944 -6 2 10 0 0.0533447 0.183228 -6 2 11 0 0.0654907 0.235229 -6 2 12 0 0.0804443 0.296387 -6 2 13 0 0.0978394 0.365723 -6 2 14 0 0.117249 0.442139 -6 2 15 0 0.138184 0.523926 -6 2 16 0 0.160034 0.608398 -6 2 17 0 0.181152 0.689941 -6 2 18 0 0.200684 0.764648 -6 2 19 0 0.217773 0.830566 -6 2 20 0 0.227295 0.867676 -6 2 21 0 0.229126 0.874512 -6 2 22 0 0.231079 0.882324 -6 2 23 0 0.233032 0.889648 -6 2 24 0 0.235107 0.897461 -6 2 25 0 0.237305 0.90625 -6 2 26 0 0.239746 0.915527 -6 2 27 0 0.242432 0.92627 -6 2 28 0 0.245605 0.937988 -6 2 29 0 0.248779 0.950684 -6 2 30 0 0.252197 0.963867 -6 2 31 0 0.255859 0.977051 -6 3 0 0.0979004 0.0409546 0 -6 3 1 0.0982056 0.0411072 0 -6 3 2 0.0985718 0.0411072 0.0185089 -6 3 3 0.098877 0.0407715 0.0343323 -6 3 4 0.0975952 0.0397339 0.0490723 -6 3 5 0.0879517 0.0378723 0.0608826 -6 3 6 0.0757446 0.0388184 0.0695801 -6 3 7 0.0703125 0.0403442 0.0884399 -6 3 8 0.058136 0.0429382 0.112305 -6 3 9 0 0.0476379 0.142944 -6 3 10 0 0.0555725 0.183228 -6 3 11 0 0.0671997 0.235229 -6 3 12 0 0.0817261 0.296387 -6 3 13 0 0.0987549 0.365723 -6 3 14 0 0.117981 0.442139 -6 3 15 0 0.138794 0.523926 -6 3 16 0 0.160522 0.608398 -6 3 17 0 0.181519 0.689941 -6 3 18 0 0.200928 0.764648 -6 3 19 0 0.218018 0.830566 -6 3 20 0 0.227539 0.867676 -6 3 21 0 0.229248 0.874512 -6 3 22 0 0.231201 0.882324 -6 3 23 0 0.233154 0.889648 -6 3 24 0 0.235107 0.897461 -6 3 25 0 0.237305 0.90625 -6 3 26 0 0.239746 0.915527 -6 3 27 0 0.242554 0.92627 -6 3 28 0 0.245605 0.937988 -6 3 29 0 0.248901 0.950684 -6 3 30 0 0.252197 0.963867 -6 3 31 0 0.255859 0.977051 -6 4 0 0.0922852 0.0499573 0 -6 4 1 0.0924683 0.0501099 0 -6 4 2 0.0928345 0.0502625 0.0196686 -6 4 3 0.0935059 0.0504761 0.0331116 -6 4 4 0.0943604 0.0505981 0.0474548 -6 4 5 0.0890503 0.0483398 0.0617676 -6 4 6 0.0747681 0.0455933 0.069458 -6 4 7 0.0692749 0.0466614 0.0883789 -6 4 8 0.0567322 0.048584 0.112305 -6 4 9 0 0.0523987 0.142944 -6 4 10 0 0.0594482 0.183228 -6 4 11 0 0.0703125 0.235229 -6 4 12 0 0.0841064 0.296387 -6 4 13 0 0.100525 0.365723 -6 4 14 0 0.119324 0.442139 -6 4 15 0 0.139771 0.523926 -6 4 16 0 0.161255 0.608398 -6 4 17 0 0.182007 0.689941 -6 4 18 0 0.201294 0.764648 -6 4 19 0 0.218384 0.830566 -6 4 20 0 0.227783 0.867676 -6 4 21 0 0.229492 0.874512 -6 4 22 0 0.231323 0.882324 -6 4 23 0 0.233276 0.889648 -6 4 24 0 0.235229 0.897461 -6 4 25 0 0.237427 0.90625 -6 4 26 0 0.239868 0.915527 -6 4 27 0 0.242554 0.92627 -6 4 28 0 0.245605 0.937988 -6 4 29 0 0.248901 0.950684 -6 4 30 0 0.252441 0.963867 -6 4 31 0 0.255859 0.977051 -6 5 0 0.0837402 0.0585632 0.0157776 -6 5 1 0.0836792 0.0586243 0.0175171 -6 5 2 0.0835571 0.0586853 0.0251007 -6 5 3 0.0834351 0.0588379 0.0335388 -6 5 4 0.0836792 0.0594482 0.044281 -6 5 5 0.0855713 0.0612488 0.0601196 -6 5 6 0.0727539 0.0553589 0.0692139 -6 5 7 0.0670776 0.0559998 0.0881958 -6 5 8 0.053772 0.0572205 0.112183 -6 5 9 0 0.0600281 0.142944 -6 5 10 0 0.065918 0.183105 -6 5 11 0 0.0756836 0.235107 -6 5 12 0 0.0883789 0.296387 -6 5 13 0 0.103821 0.365723 -6 5 14 0 0.121765 0.442139 -6 5 15 0 0.141602 0.523926 -6 5 16 0 0.162598 0.608398 -6 5 17 0 0.183105 0.689941 -6 5 18 0 0.202148 0.764648 -6 5 19 0 0.218994 0.830566 -6 5 20 0 0.228271 0.867676 -6 5 21 0 0.229858 0.874512 -6 5 22 0 0.231689 0.882324 -6 5 23 0 0.233521 0.890137 -6 5 24 0 0.235474 0.897461 -6 5 25 0 0.237671 0.90625 -6 5 26 0 0.240112 0.915527 -6 5 27 0 0.242798 0.92627 -6 5 28 0 0.24585 0.937988 -6 5 29 0 0.249023 0.950684 -6 5 30 0 0.252441 0.963867 -6 5 31 0 0.255859 0.977051 -6 6 0 0.0795898 0.0730591 0.0229187 -6 6 1 0.0795898 0.0731201 0.022934 -6 6 2 0.0792847 0.072998 0.0272675 -6 6 3 0.0784912 0.0726929 0.0348206 -6 6 4 0.0770264 0.0721436 0.0441589 -6 6 5 0.0742188 0.0709839 0.0556335 -6 6 6 0.0686646 0.0686646 0.0686646 -6 6 7 0.0625 0.0689697 0.0878906 -6 6 8 0.0473022 0.069519 0.112061 -6 6 9 0 0.0713501 0.142822 -6 6 10 0 0.0761108 0.182983 -6 6 11 0 0.0844727 0.234985 -6 6 12 0 0.0957031 0.296387 -6 6 13 0 0.10968 0.365723 -6 6 14 0 0.126343 0.442139 -6 6 15 0 0.14502 0.523926 -6 6 16 0 0.165283 0.608398 -6 6 17 0 0.185181 0.689941 -6 6 18 0 0.203735 0.765137 -6 6 19 0 0.220337 0.831055 -6 6 20 0 0.22937 0.867676 -6 6 21 0 0.230713 0.874512 -6 6 22 0 0.232422 0.882324 -6 6 23 0 0.234131 0.890137 -6 6 24 0 0.235962 0.897461 -6 6 25 0 0.238037 0.90625 -6 6 26 0 0.240356 0.915527 -6 6 27 0 0.243042 0.92627 -6 6 28 0 0.246094 0.937988 -6 6 29 0 0.249268 0.950684 -6 6 30 0 0.252686 0.963867 -6 6 31 0 0.256104 0.977051 -6 7 0 0.0678101 0.0889282 0.021637 -6 7 1 0.0678711 0.0889893 0.021637 -6 7 2 0.0678711 0.0889893 0.0216522 -6 7 3 0.0671997 0.0887451 0.0303497 -6 7 4 0.0658569 0.0881348 0.0405273 -6 7 5 0.0634155 0.0871582 0.0526123 -6 7 6 0.0593872 0.0864258 0.0675049 -6 7 7 0.0516968 0.0865479 0.0870972 -6 7 8 0.0267181 0.0866699 0.111633 -6 7 9 0 0.0875854 0.142578 -6 7 10 0 0.0912476 0.182739 -6 7 11 0 0.0983887 0.234741 -6 7 12 0 0.107788 0.296143 -6 7 13 0 0.119751 0.365723 -6 7 14 0 0.134399 0.442139 -6 7 15 0 0.151489 0.523926 -6 7 16 0 0.170288 0.608398 -6 7 17 0 0.189087 0.689941 -6 7 18 0 0.206787 0.765137 -6 7 19 0 0.222778 0.831055 -6 7 20 0 0.231323 0.867676 -6 7 21 0 0.2323 0.875 -6 7 22 0 0.233643 0.882324 -6 7 23 0 0.235229 0.890137 -6 7 24 0 0.236938 0.897949 -6 7 25 0 0.238892 0.90625 -6 7 26 0 0.241089 0.915527 -6 7 27 0 0.243652 0.92627 -6 7 28 0 0.246582 0.937988 -6 7 29 0 0.249634 0.950684 -6 7 30 0 0.25293 0.963867 -6 7 31 0 0.256348 0.977051 -6 8 0 0.0415344 0.109558 0.0201721 -6 8 1 0.0415649 0.109558 0.0201721 -6 8 2 0.041626 0.109619 0.0201874 -6 8 3 0.041626 0.109619 0.0212708 -6 8 4 0.0398865 0.109497 0.0350037 -6 8 5 0.0361938 0.109375 0.0489197 -6 8 6 0.0269012 0.109375 0.0651855 -6 8 7 0 0.109558 0.0853271 -6 8 8 0 0.109558 0.110535 -6 8 9 0 0.110046 0.14209 -6 8 10 0 0.112854 0.182373 -6 8 11 0 0.118896 0.234375 -6 8 12 0 0.126709 0.295898 -6 8 13 0 0.136353 0.365479 -6 8 14 0 0.148438 0.442139 -6 8 15 0 0.162842 0.523926 -6 8 16 0 0.179321 0.608398 -6 8 17 0 0.196289 0.689941 -6 8 18 0 0.212646 0.765137 -6 8 19 0 0.227417 0.831055 -6 8 20 0 0.235107 0.868164 -6 8 21 0 0.235352 0.875 -6 8 22 0 0.236084 0.882324 -6 8 23 0 0.237305 0.890137 -6 8 24 0 0.238647 0.897949 -6 8 25 0 0.240356 0.90625 -6 8 26 0 0.242432 0.916016 -6 8 27 0 0.244751 0.92627 -6 8 28 0 0.247559 0.937988 -6 8 29 0 0.250488 0.950684 -6 8 30 0 0.253662 0.963867 -6 8 31 0 0.25708 0.977539 -6 9 0 0 0.138062 0.0185547 -6 9 1 0 0.138062 0.0185699 -6 9 2 0 0.138184 0.0185699 -6 9 3 0 0.138184 0.0186005 -6 9 4 0 0.138306 0.0223236 -6 9 5 0 0.138306 0.0424805 -6 9 6 0 0.138428 0.0609131 -6 9 7 0 0.138672 0.0822754 -6 9 8 0 0.138916 0.108521 -6 9 9 0 0.139526 0.141113 -6 9 10 0 0.141968 0.181763 -6 9 11 0 0.147339 0.233765 -6 9 12 0 0.153809 0.295654 -6 9 13 0 0.161255 0.365479 -6 9 14 0 0.170532 0.442139 -6 9 15 0 0.181763 0.523926 -6 9 16 0 0.195068 0.608398 -6 9 17 0 0.209106 0.689941 -6 9 18 0 0.223022 0.765137 -6 9 19 0 0.235962 0.831055 -6 9 20 0 0.242188 0.868652 -6 9 21 0 0.240967 0.875488 -6 9 22 0 0.240723 0.882812 -6 9 23 0 0.241211 0.890625 -6 9 24 0 0.242065 0.897949 -6 9 25 0 0.243286 0.906738 -6 9 26 0 0.244873 0.916016 -6 9 27 0 0.246948 0.92627 -6 9 28 0 0.24939 0.938477 -6 9 29 0 0.252197 0.950684 -6 9 30 0 0.255127 0.963867 -6 9 31 0 0.258301 0.977539 -6 10 0 0 0.175537 0.0158386 -6 10 1 0 0.175537 0.0158386 -6 10 2 0 0.175537 0.0158539 -6 10 3 0 0.175537 0.0158844 -6 10 4 0 0.175659 0.0159302 -6 10 5 0 0.175659 0.0263824 -6 10 6 0 0.175659 0.0537109 -6 10 7 0 0.175781 0.0780029 -6 10 8 0 0.176025 0.105896 -6 10 9 0 0.17688 0.139771 -6 10 10 0 0.179077 0.181152 -6 10 11 0 0.183838 0.233032 -6 10 12 0 0.189453 0.294922 -6 10 13 0 0.195312 0.36499 -6 10 14 0 0.201782 0.441895 -6 10 15 0 0.209717 0.523926 -6 10 16 0 0.219238 0.608887 -6 10 17 0 0.229614 0.69043 -6 10 18 0 0.240234 0.765625 -6 10 19 0 0.250244 0.831543 -6 10 20 0 0.25415 0.869141 -6 10 21 0 0.250732 0.875977 -6 10 22 0 0.248901 0.883301 -6 10 23 0 0.248047 0.891113 -6 10 24 0 0.247925 0.898438 -6 10 25 0 0.248413 0.907227 -6 10 26 0 0.249268 0.916504 -6 10 27 0 0.250732 0.926758 -6 10 28 0 0.252686 0.938477 -6 10 29 0 0.254883 0.951172 -6 10 30 0 0.257568 0.964355 -6 10 31 0 0.260254 0.977539 -6 11 0 0 0.224365 0.00674438 -6 11 1 0 0.224365 0.00677872 -6 11 2 0 0.224487 0.00683975 -6 11 3 0 0.224487 0.00695038 -6 11 4 0 0.224487 0.00714874 -6 11 5 0 0.224609 0.00751114 -6 11 6 0 0.224609 0.0353699 -6 11 7 0 0.224487 0.0707397 -6 11 8 0 0.224487 0.102539 -6 11 9 0 0.224731 0.13855 -6 11 10 0 0.226318 0.18103 -6 11 11 0 0.229614 0.232422 -6 11 12 0 0.234131 0.293945 -6 11 13 0 0.23877 0.364258 -6 11 14 0 0.243164 0.44165 -6 11 15 0 0.248047 0.523926 -6 11 16 0 0.253906 0.608887 -6 11 17 0 0.26001 0.690918 -6 11 18 0 0.266357 0.766113 -6 11 19 0 0.272949 0.832031 -6 11 20 0 0.273438 0.870605 -6 11 21 0 0.266602 0.877441 -6 11 22 0 0.262207 0.884766 -6 11 23 0 0.259521 0.89209 -6 11 24 0 0.257812 0.899414 -6 11 25 0 0.25708 0.907715 -6 11 26 0 0.256836 0.916992 -6 11 27 0 0.257324 0.927246 -6 11 28 0 0.258301 0.938965 -6 11 29 0 0.259766 0.95166 -6 11 30 0 0.261719 0.964355 -6 11 31 0 0.263916 0.978027 -6 12 0 0 0.283936 0 -6 12 1 0 0.283936 0 -6 12 2 0 0.283936 0 -6 12 3 0 0.283936 0 -6 12 4 0 0.283936 0 -6 12 5 0 0.283936 0 -6 12 6 0 0.28418 0 -6 12 7 0 0.28418 0.0510864 -6 12 8 0 0.28418 0.0946655 -6 12 9 0 0.28418 0.135254 -6 12 10 0 0.284668 0.17981 -6 12 11 0 0.286133 0.231567 -6 12 12 0 0.289062 0.292725 -6 12 13 0 0.29248 0.363037 -6 12 14 0 0.29541 0.440918 -6 12 15 0 0.297607 0.523438 -6 12 16 0 0.299805 0.608887 -6 12 17 0 0.301758 0.691406 -6 12 18 0 0.303711 0.766602 -6 12 19 0 0.305664 0.83252 -6 12 20 0 0.30249 0.873535 -6 12 21 0 0.291016 0.879395 -6 12 22 0 0.282959 0.886719 -6 12 23 0 0.277588 0.893555 -6 12 24 0 0.273682 0.900879 -6 12 25 0 0.270996 0.90918 -6 12 26 0 0.269043 0.918457 -6 12 27 0 0.267822 0.928711 -6 12 28 0 0.267578 0.939941 -6 12 29 0 0.267822 0.952637 -6 12 30 0 0.268799 0.965332 -6 12 31 0 0.27002 0.978516 -6 13 0 0 0.351562 0 -6 13 1 0 0.351562 0 -6 13 2 0 0.351562 0 -6 13 3 0 0.351562 0 -6 13 4 0 0.351562 0 -6 13 5 0 0.351562 0 -6 13 6 0 0.351562 0 -6 13 7 0 0.351807 0 -6 13 8 0 0.351807 0.074585 -6 13 9 0 0.352051 0.125977 -6 13 10 0 0.352295 0.174927 -6 13 11 0 0.353027 0.22876 -6 13 12 0 0.354492 0.290527 -6 13 13 0 0.356445 0.36084 -6 13 14 0 0.35791 0.439209 -6 13 15 0 0.358154 0.522949 -6 13 16 0 0.357178 0.608887 -6 13 17 0 0.355225 0.691895 -6 13 18 0 0.352783 0.767578 -6 13 19 0 0.350098 0.833984 -6 13 20 0 0.342773 0.876953 -6 13 21 0 0.325684 0.883301 -6 13 22 0 0.312988 0.889648 -6 13 23 0 0.303955 0.896484 -6 13 24 0 0.297119 0.903809 -6 13 25 0 0.291748 0.911621 -6 13 26 0 0.287354 0.92041 -6 13 27 0 0.283936 0.930176 -6 13 28 0 0.281738 0.941406 -6 13 29 0 0.280273 0.953613 -6 13 30 0 0.279785 0.966309 -6 13 31 0 0.279541 0.979492 -6 14 0 0 0.426758 0 -6 14 1 0 0.426758 0 -6 14 2 0 0.426758 0 -6 14 3 0 0.426758 0 -6 14 4 0 0.426758 0 -6 14 5 0 0.426758 0 -6 14 6 0 0.427002 0 -6 14 7 0 0.427002 0 -6 14 8 0 0.427246 0 -6 14 9 0 0.42749 0.105713 -6 14 10 0 0.427979 0.16394 -6 14 11 0 0.428467 0.221802 -6 14 12 0 0.429199 0.285645 -6 14 13 0 0.430176 0.356934 -6 14 14 0 0.43042 0.436035 -6 14 15 0 0.429199 0.520508 -6 14 16 0 0.42627 0.60791 -6 14 17 0 0.420654 0.691895 -6 14 18 0 0.413818 0.768555 -6 14 19 0 0.406738 0.834961 -6 14 20 0 0.395752 0.882812 -6 14 21 0 0.37207 0.888672 -6 14 22 0 0.35376 0.894531 -6 14 23 0 0.340332 0.901367 -6 14 24 0 0.329834 0.907715 -6 14 25 0 0.321045 0.915527 -6 14 26 0 0.313477 0.923828 -6 14 27 0 0.307373 0.933105 -6 14 28 0 0.30249 0.944336 -6 14 29 0 0.298828 0.956055 -6 14 30 0 0.295898 0.968262 -6 14 31 0 0.293945 0.981445 -6 15 0 0 0.507812 0 -6 15 1 0 0.507812 0 -6 15 2 0 0.507812 0 -6 15 3 0 0.507812 0 -6 15 4 0 0.507812 0 -6 15 5 0 0.507812 0 -6 15 6 0 0.507812 0 -6 15 7 0 0.507812 0 -6 15 8 0 0.507812 0 -6 15 9 0 0.508301 0.0467834 -6 15 10 0 0.508789 0.143188 -6 15 11 0 0.509766 0.20874 -6 15 12 0 0.510742 0.276123 -6 15 13 0 0.51123 0.349365 -6 15 14 0 0.51123 0.429688 -6 15 15 0 0.509766 0.516113 -6 15 16 0 0.504883 0.605469 -6 15 17 0 0.496826 0.690918 -6 15 18 0 0.486328 0.768555 -6 15 19 0 0.474854 0.836426 -6 15 20 0 0.461426 0.88916 -6 15 21 0 0.430664 0.895996 -6 15 22 0 0.40625 0.902344 -6 15 23 0 0.387695 0.908203 -6 15 24 0 0.372803 0.914551 -6 15 25 0 0.360107 0.921387 -6 15 26 0 0.348877 0.929199 -6 15 27 0 0.339111 0.937988 -6 15 28 0 0.331055 0.948242 -6 15 29 0 0.324219 0.959473 -6 15 30 0 0.318604 0.97168 -6 15 31 0 0.314209 0.983887 -6 16 0 0 0.592773 0 -6 16 1 0 0.592773 0 -6 16 2 0 0.592773 0 -6 16 3 0 0.592773 0 -6 16 4 0 0.592773 0 -6 16 5 0 0.592773 0 -6 16 6 0 0.592773 0 -6 16 7 0 0.592773 0 -6 16 8 0 0.592773 0 -6 16 9 0 0.593262 0 -6 16 10 0 0.59375 0.101318 -6 16 11 0 0.594727 0.187012 -6 16 12 0 0.595703 0.260498 -6 16 13 0 0.597168 0.336914 -6 16 14 0 0.597656 0.419189 -6 16 15 0 0.596191 0.507324 -6 16 16 0 0.591309 0.598633 -6 16 17 0 0.582031 0.687012 -6 16 18 0 0.568848 0.76709 -6 16 19 0 0.553711 0.836426 -6 16 20 0 0.537598 0.893555 -6 16 21 0 0.501953 0.905762 -6 16 22 0 0.471191 0.913086 -6 16 23 0 0.446777 0.918945 -6 16 24 0 0.427246 0.924805 -6 16 25 0 0.409668 0.930664 -6 16 26 0 0.394043 0.937988 -6 16 27 0 0.380127 0.945801 -6 16 28 0 0.368164 0.955078 -6 16 29 0 0.357666 0.965332 -6 16 30 0 0.348877 0.976562 -6 16 31 0 0.341064 0.988281 -6 17 0 0 0.67627 0 -6 17 1 0 0.67627 0 -6 17 2 0 0.67627 0 -6 17 3 0 0.67627 0 -6 17 4 0 0.67627 0 -6 17 5 0 0.67627 0 -6 17 6 0 0.67627 0 -6 17 7 0 0.67627 0 -6 17 8 0 0.676758 0 -6 17 9 0 0.676758 0 -6 17 10 0 0.676758 0 -6 17 11 0 0.678223 0.151733 -6 17 12 0 0.679688 0.237915 -6 17 13 0 0.681641 0.318848 -6 17 14 0 0.683105 0.403564 -6 17 15 0 0.683105 0.493652 -6 17 16 0 0.679199 0.587402 -6 17 17 0 0.669922 0.678223 -6 17 18 0 0.655762 0.761719 -6 17 19 0 0.638672 0.833984 -6 17 20 0 0.619141 0.893066 -6 17 21 0 0.58252 0.916504 -6 17 22 0 0.546387 0.926758 -6 17 23 0 0.516602 0.933594 -6 17 24 0 0.491699 0.938965 -6 17 25 0 0.469238 0.944336 -6 17 26 0 0.448486 0.950195 -6 17 27 0 0.429688 0.957031 -6 17 28 0 0.41333 0.964844 -6 17 29 0 0.398926 0.973633 -6 17 30 0 0.385986 0.983887 -6 17 31 0 0.374512 0.994141 -6 18 0 0 0.754395 0 -6 18 1 0 0.754395 0 -6 18 2 0 0.754395 0 -6 18 3 0 0.754395 0 -6 18 4 0 0.754395 0 -6 18 5 0 0.754395 0 -6 18 6 0 0.754395 0 -6 18 7 0 0.754395 0 -6 18 8 0 0.754883 0 -6 18 9 0 0.754883 0 -6 18 10 0 0.754883 0 -6 18 11 0 0.755371 0.0777588 -6 18 12 0 0.757324 0.206543 -6 18 13 0 0.759766 0.294922 -6 18 14 0 0.762695 0.382812 -6 18 15 0 0.763672 0.474609 -6 18 16 0 0.762207 0.570312 -6 18 17 0 0.754883 0.664551 -6 18 18 0 0.742188 0.751465 -6 18 19 0 0.724121 0.827148 -6 18 20 0 0.702637 0.889648 -6 18 21 0 0.66748 0.924316 -6 18 22 0 0.629395 0.941406 -6 18 23 0 0.594727 0.951172 -6 18 24 0 0.564941 0.957031 -6 18 25 0 0.537109 0.962402 -6 18 26 0 0.510742 0.966797 -6 18 27 0 0.487061 0.972168 -6 18 28 0 0.465576 0.978516 -6 18 29 0 0.446289 0.985352 -6 18 30 0 0.428955 0.993652 -6 18 31 0 0.413574 1 -6 19 0 0 0.824707 0 -6 19 1 0 0.824707 0 -6 19 2 0 0.824707 0 -6 19 3 0 0.824707 0 -6 19 4 0 0.824707 0 -6 19 5 0 0.824707 0 -6 19 6 0 0.824707 0 -6 19 7 0 0.824707 0 -6 19 8 0 0.824707 0 -6 19 9 0 0.824707 0 -6 19 10 0 0.825195 0 -6 19 11 0 0.825195 0 -6 19 12 0 0.82666 0.162354 -6 19 13 0 0.82959 0.266113 -6 19 14 0 0.833008 0.358154 -6 19 15 0 0.835449 0.451416 -6 19 16 0 0.836426 0.548828 -6 19 17 0 0.832031 0.64502 -6 19 18 0 0.821777 0.73584 -6 19 19 0 0.805176 0.81543 -6 19 20 0 0.783691 0.881348 -6 19 21 0 0.751953 0.927246 -6 19 22 0 0.714355 0.953613 -6 19 23 0 0.677246 0.968262 -6 19 24 0 0.643555 0.977051 -6 19 25 0 0.610352 0.982422 -6 19 26 0 0.579102 0.986816 -6 19 27 0 0.549805 0.990723 -6 19 28 0 0.522949 0.995117 -6 19 29 0 0.498779 1 -6 19 30 0 0.476562 1 -6 19 31 0 0.456787 1 -6 20 0 0 0.885254 0 -6 20 1 0 0.885254 0 -6 20 2 0 0.885254 0 -6 20 3 0 0.885254 0 -6 20 4 0 0.885254 0 -6 20 5 0 0.885254 0 -6 20 6 0 0.885254 0 -6 20 7 0 0.885254 0 -6 20 8 0 0.885254 0 -6 20 9 0 0.885254 0 -6 20 10 0 0.885254 0 -6 20 11 0 0.885742 0 -6 20 12 0 0.88623 0.0792847 -6 20 13 0 0.88916 0.232056 -6 20 14 0 0.893066 0.330811 -6 20 15 0 0.896973 0.42627 -6 20 16 0 0.899414 0.524414 -6 20 17 0 0.898438 0.62207 -6 20 18 0 0.891113 0.715332 -6 20 19 0 0.876953 0.797852 -6 20 20 0 0.856934 0.867676 -6 20 21 0 0.830078 0.922852 -6 20 22 0 0.79541 0.959961 -6 20 23 0 0.758789 0.981445 -6 20 24 0 0.722656 0.994141 -6 20 25 0 0.686035 1 -6 20 26 0 0.649902 1 -6 20 27 0 0.615723 1 -6 20 28 0 0.583496 1 -6 20 29 0 0.553711 1 -6 20 30 0 0.526855 1 -6 20 31 0 0.502441 1 -6 21 0 0 0.936523 0 -6 21 1 0 0.936523 0 -6 21 2 0 0.936523 0 -6 21 3 0 0.936523 0 -6 21 4 0 0.936523 0 -6 21 5 0 0.936523 0 -6 21 6 0 0.936523 0 -6 21 7 0 0.936523 0 -6 21 8 0 0.936523 0 -6 21 9 0 0.937012 0 -6 21 10 0 0.937012 0 -6 21 11 0 0.937012 0 -6 21 12 0 0.9375 0 -6 21 13 0 0.939941 0.189453 -6 21 14 0 0.943848 0.300537 -6 21 15 0 0.94873 0.398682 -6 21 16 0 0.953125 0.497559 -6 21 17 0 0.954102 0.595703 -6 21 18 0 0.950195 0.69043 -6 21 19 0 0.939453 0.775879 -6 21 20 0 0.922363 0.849121 -6 21 21 0 0.899414 0.910645 -6 21 22 0 0.869629 0.957031 -6 21 23 0 0.835449 0.987305 -6 21 24 0 0.799805 1 -6 21 25 0 0.76123 1 -6 21 26 0 0.722168 1 -6 21 27 0 0.683594 1 -6 21 28 0 0.646484 1 -6 21 29 0 0.611816 1 -6 21 30 0 0.580078 1 -6 21 31 0 0.550781 1 -6 22 0 0 0.979492 0 -6 22 1 0 0.979492 0 -6 22 2 0 0.979492 0 -6 22 3 0 0.979492 0 -6 22 4 0 0.979492 0 -6 22 5 0 0.979492 0 -6 22 6 0 0.979492 0 -6 22 7 0 0.979492 0 -6 22 8 0 0.979492 0 -6 22 9 0 0.979492 0 -6 22 10 0 0.979492 0 -6 22 11 0 0.979492 0 -6 22 12 0 0.97998 0 -6 22 13 0 0.981445 0.128418 -6 22 14 0 0.985352 0.267334 -6 22 15 0 0.990723 0.369873 -6 22 16 0 0.996094 0.469238 -6 22 17 0 1 0.567871 -6 22 18 0 0.999023 0.663086 -6 22 19 0 0.991699 0.750488 -6 22 20 0 0.978027 0.82666 -6 22 21 0 0.958008 0.891602 -6 22 22 0 0.933105 0.944824 -6 22 23 0 0.90332 0.983398 -6 22 24 0 0.870117 1 -6 22 25 0 0.83252 1 -6 22 26 0 0.791992 1 -6 22 27 0 0.750488 1 -6 22 28 0 0.709961 1 -6 22 29 0 0.670898 1 -6 22 30 0 0.634277 1 -6 22 31 0 0.600586 1 -6 23 0 0 1 0 -6 23 1 0 1 0 -6 23 2 0 1 0 -6 23 3 0 1 0 -6 23 4 0 1 0 -6 23 5 0 1 0 -6 23 6 0 1 0 -6 23 7 0 1 0 -6 23 8 0 1 0 -6 23 9 0 1 0 -6 23 10 0 1 0 -6 23 11 0 1 0 -6 23 12 0 1 0 -6 23 13 0 1 0 -6 23 14 0 1 0.231689 -6 23 15 0 1 0.341064 -6 23 16 0 1 0.44165 -6 23 17 0 1 0.539551 -6 23 18 0 1 0.634766 -6 23 19 0 1 0.723145 -6 23 20 0 1 0.80127 -6 23 21 0 1 0.869629 -6 23 22 0 0.984375 0.92627 -6 23 23 0 0.958984 0.970703 -6 23 24 0 0.929688 1 -6 23 25 0 0.89502 1 -6 23 26 0 0.85498 1 -6 23 27 0 0.8125 1 -6 23 28 0 0.769531 1 -6 23 29 0 0.727539 1 -6 23 30 0 0.687012 1 -6 23 31 0 0.648926 1 -6 24 0 0 1 0 -6 24 1 0 1 0 -6 24 2 0 1 0 -6 24 3 0 1 0 -6 24 4 0 1 0 -6 24 5 0 1 0 -6 24 6 0 1 0 -6 24 7 0 1 0 -6 24 8 0 1 0 -6 24 9 0 1 0 -6 24 10 0 1 0 -6 24 11 0 1 0 -6 24 12 0 1 0 -6 24 13 0 1 0 -6 24 14 0 1 0.191284 -6 24 15 0 1 0.312012 -6 24 16 0 1 0.414307 -6 24 17 0 1 0.512207 -6 24 18 0 1 0.606934 -6 24 19 0 1 0.695312 -6 24 20 0 1 0.774414 -6 24 21 0 1 0.845215 -6 24 22 0 1 0.904785 -6 24 23 0 1 0.953125 -6 24 24 0 0.979004 0.991699 -6 24 25 0 0.948242 1 -6 24 26 0 0.911133 1 -6 24 27 0 0.869141 1 -6 24 28 0 0.825195 1 -6 24 29 0 0.780762 1 -6 24 30 0 0.737305 1 -6 24 31 0 0.695801 1 -6 25 0 0 1 0 -6 25 1 0 1 0 -6 25 2 0 1 0 -6 25 3 0 1 0 -6 25 4 0 1 0 -6 25 5 0 1 0 -6 25 6 0 1 0 -6 25 7 0 1 0 -6 25 8 0 1 0 -6 25 9 0 1 0 -6 25 10 0 1 0 -6 25 11 0 1 0 -6 25 12 0 1 0 -6 25 13 0 1 0 -6 25 14 0 1 0.132568 -6 25 15 0 1 0.279541 -6 25 16 0 1 0.38501 -6 25 17 0 1 0.482666 -6 25 18 0 1 0.576172 -6 25 19 0 1 0.664551 -6 25 20 0 1 0.744141 -6 25 21 0 1 0.816406 -6 25 22 0 1 0.878906 -6 25 23 0 1 0.930176 -6 25 24 0 1 0.972656 -6 25 25 0 0.99707 1 -6 25 26 0 0.963867 1 -6 25 27 0 0.924316 1 -6 25 28 0 0.880371 1 -6 25 29 0 0.834961 1 -6 25 30 0 0.789551 1 -6 25 31 0 0.745117 1 -6 26 0 0 1 0 -6 26 1 0 1 0 -6 26 2 0 1 0 -6 26 3 0 1 0 -6 26 4 0 1 0 -6 26 5 0 1 0 -6 26 6 0 1 0 -6 26 7 0 1 0 -6 26 8 0 1 0 -6 26 9 0 1 0 -6 26 10 0 1 0 -6 26 11 0 1 0 -6 26 12 0 1 0 -6 26 13 0 1 0 -6 26 14 0 1 0 -6 26 15 0 1 0.241943 -6 26 16 0 1 0.353027 -6 26 17 0 1 0.451172 -6 26 18 0 1 0.543457 -6 26 19 0 1 0.630859 -6 26 20 0 1 0.710938 -6 26 21 0 1 0.783691 -6 26 22 0 1 0.848633 -6 26 23 0 1 0.902832 -6 26 24 0 1 0.948242 -6 26 25 0 1 0.989258 -6 26 26 0 1 1 -6 26 27 0 0.976074 1 -6 26 28 0 0.93457 1 -6 26 29 0 0.889648 1 -6 26 30 0 0.842773 1 -6 26 31 0 0.796387 1 -6 27 0 0 1 0 -6 27 1 0 1 0 -6 27 2 0 1 0 -6 27 3 0 1 0 -6 27 4 0 1 0 -6 27 5 0 1 0 -6 27 6 0 1 0 -6 27 7 0 1 0 -6 27 8 0 1 0 -6 27 9 0 1 0 -6 27 10 0 1 0 -6 27 11 0 1 0 -6 27 12 0 1 0 -6 27 13 0 1 0 -6 27 14 0 1 0 -6 27 15 0 1 0.195557 -6 27 16 0 1 0.318604 -6 27 17 0 1 0.417725 -6 27 18 0 1 0.509277 -6 27 19 0 1 0.595215 -6 27 20 0 1 0.674805 -6 27 21 0 1 0.748047 -6 27 22 0 1 0.813965 -6 27 23 0 1 0.870605 -6 27 24 0 1 0.918457 -6 27 25 0 1 0.962891 -6 27 26 0 1 1 -6 27 27 0 1 1 -6 27 28 0 0.98584 1 -6 27 29 0 0.941895 1 -6 27 30 0 0.895508 1 -6 27 31 0 0.848145 1 -6 28 0 0 1 0 -6 28 1 0 1 0 -6 28 2 0 1 0 -6 28 3 0 1 0 -6 28 4 0 1 0 -6 28 5 0 1 0 -6 28 6 0 1 0 -6 28 7 0 1 0 -6 28 8 0 1 0 -6 28 9 0 1 0 -6 28 10 0 1 0 -6 28 11 0 1 0 -6 28 12 0 1 0 -6 28 13 0 1 0 -6 28 14 0 1 0 -6 28 15 0 1 0.126831 -6 28 16 0 1 0.280518 -6 28 17 0 1 0.382812 -6 28 18 0 1 0.473877 -6 28 19 0 1 0.558105 -6 28 20 0 1 0.63623 -6 28 21 0 1 0.709473 -6 28 22 0 1 0.775879 -6 28 23 0 1 0.833496 -6 28 24 0 1 0.883789 -6 28 25 0 1 0.931152 -6 28 26 0 1 0.974609 -6 28 27 0 1 1 -6 28 28 0 1 1 -6 28 29 0 0.991699 1 -6 28 30 0 0.947266 1 -6 28 31 0 0.899902 1 -6 29 0 0 1 0 -6 29 1 0 1 0 -6 29 2 0 1 0 -6 29 3 0 1 0 -6 29 4 0 1 0 -6 29 5 0 1 0 -6 29 6 0 1 0 -6 29 7 0 1 0 -6 29 8 0 1 0 -6 29 9 0 1 0 -6 29 10 0 1 0 -6 29 11 0 1 0 -6 29 12 0 1 0 -6 29 13 0 1 0 -6 29 14 0 1 0 -6 29 15 0 1 0 -6 29 16 0 1 0.236572 -6 29 17 0 1 0.345215 -6 29 18 0 1 0.436279 -6 29 19 0 1 0.519531 -6 29 20 0 1 0.596191 -6 29 21 0 1 0.667969 -6 29 22 0 1 0.733887 -6 29 23 0 1 0.79248 -6 29 24 0 1 0.84375 -6 29 25 0 1 0.893555 -6 29 26 0 1 0.94043 -6 29 27 0 1 0.98291 -6 29 28 0 1 1 -6 29 29 0 1 1 -6 29 30 0 0.996582 1 -6 29 31 0 0.951172 1 -6 30 0 0 1 0 -6 30 1 0 1 0 -6 30 2 0 1 0 -6 30 3 0 1 0 -6 30 4 0 1 0 -6 30 5 0 1 0 -6 30 6 0 1 0 -6 30 7 0 1 0 -6 30 8 0 1 0 -6 30 9 0 1 0 -6 30 10 0 1 0 -6 30 11 0 1 0 -6 30 12 0 1 0 -6 30 13 0 1 0 -6 30 14 0 1 0 -6 30 15 0 1 0 -6 30 16 0 1 0.182007 -6 30 17 0 1 0.304932 -6 30 18 0 1 0.397217 -6 30 19 0 1 0.479248 -6 30 20 0 1 0.554199 -6 30 21 0 1 0.624512 -6 30 22 0 1 0.689453 -6 30 23 0 1 0.747559 -6 30 24 0 1 0.799805 -6 30 25 0 1 0.850586 -6 30 26 0 1 0.899902 -6 30 27 0 1 0.946289 -6 30 28 0 1 0.988281 -6 30 29 0 1 1 -6 30 30 0 1 1 -6 30 31 0 1 1 -6 31 0 0 1 0 -6 31 1 0 1 0 -6 31 2 0 1 0 -6 31 3 0 1 0 -6 31 4 0 1 0 -6 31 5 0 1 0 -6 31 6 0 1 0 -6 31 7 0 1 0 -6 31 8 0 1 0 -6 31 9 0 1 0 -6 31 10 0 1 0 -6 31 11 0 1 0 -6 31 12 0 1 0 -6 31 13 0 1 0 -6 31 14 0 1 0 -6 31 15 0 1 0 -6 31 16 0 1 0.0875244 -6 31 17 0 1 0.260742 -6 31 18 0 1 0.356934 -6 31 19 0 1 0.438232 -6 31 20 0 1 0.51123 -6 31 21 0 1 0.57959 -6 31 22 0 1 0.643066 -6 31 23 0 1 0.700684 -6 31 24 0 1 0.752441 -6 31 25 0 1 0.804199 -6 31 26 0 1 0.855469 -6 31 27 0 1 0.904785 -6 31 28 0 1 0.951172 -6 31 29 0 1 0.992676 -6 31 30 0 1 1 -6 31 31 0 1 1 -7 0 0 0.13147 0 0.00422287 -7 0 1 0.13147 0 0.00382805 -7 0 2 0.131592 0 0.00346375 -7 0 3 0.131714 0 0.0213013 -7 0 4 0.130615 0 0.044342 -7 0 5 0.127197 0 0.0633545 -7 0 6 0.110718 0.0237885 0.0758057 -7 0 7 0.0974731 0.0354614 0.088501 -7 0 8 0.090332 0.0388489 0.112488 -7 0 9 0.0755615 0.044342 0.143188 -7 0 10 0 0.052948 0.183228 -7 0 11 0 0.0651855 0.235107 -7 0 12 0 0.0802612 0.296387 -7 0 13 0 0.0977173 0.365723 -7 0 14 0 0.117188 0.442383 -7 0 15 0 0.138184 0.523926 -7 0 16 0 0.160034 0.608398 -7 0 17 0 0.181152 0.689941 -7 0 18 0 0.200684 0.765137 -7 0 19 0 0.217773 0.831055 -7 0 20 0 0.227417 0.867676 -7 0 21 0 0.229126 0.874512 -7 0 22 0 0.231079 0.882324 -7 0 23 0 0.233032 0.890137 -7 0 24 0 0.235107 0.897949 -7 0 25 0 0.237305 0.90625 -7 0 26 0 0.239746 0.915527 -7 0 27 0 0.242432 0.92627 -7 0 28 0 0.245605 0.937988 -7 0 29 0 0.248901 0.950684 -7 0 30 0 0.252197 0.963867 -7 0 31 0 0.255859 0.977051 -7 1 0 0.130981 0.0170593 0 -7 1 1 0.130981 0.0178528 0 -7 1 2 0.131104 0.0184631 0 -7 1 3 0.131226 0.0183105 0.0208282 -7 1 4 0.130371 0.0143051 0.0441284 -7 1 5 0.127075 0.00511551 0.0632324 -7 1 6 0.11084 0.0268402 0.0759277 -7 1 7 0.0974121 0.0368347 0.0884399 -7 1 8 0.09021 0.0400085 0.112488 -7 1 9 0.0753784 0.0452576 0.143188 -7 1 10 0 0.0536499 0.183228 -7 1 11 0 0.0657349 0.235107 -7 1 12 0 0.0806885 0.296387 -7 1 13 0 0.0979614 0.365723 -7 1 14 0 0.117371 0.442383 -7 1 15 0 0.138306 0.523926 -7 1 16 0 0.160156 0.608398 -7 1 17 0 0.181274 0.689941 -7 1 18 0 0.200684 0.765137 -7 1 19 0 0.217896 0.831055 -7 1 20 0 0.227417 0.867676 -7 1 21 0 0.229248 0.874512 -7 1 22 0 0.231079 0.882324 -7 1 23 0 0.233154 0.890137 -7 1 24 0 0.235107 0.897949 -7 1 25 0 0.237305 0.90625 -7 1 26 0 0.239746 0.915527 -7 1 27 0 0.242554 0.92627 -7 1 28 0 0.245605 0.937988 -7 1 29 0 0.248901 0.950684 -7 1 30 0 0.252197 0.963867 -7 1 31 0 0.255859 0.977051 -7 2 0 0.130127 0.0283356 0 -7 2 1 0.130127 0.0286865 0 -7 2 2 0.130371 0.0289917 0 -7 2 3 0.130493 0.0289154 0.0200348 -7 2 4 0.129883 0.0270538 0.0437317 -7 2 5 0.126831 0.0244446 0.0630493 -7 2 6 0.111084 0.0312805 0.0761108 -7 2 7 0.097229 0.0390625 0.0884399 -7 2 8 0.0900269 0.0419617 0.112488 -7 2 9 0.0751343 0.0468445 0.143066 -7 2 10 0 0.0549011 0.183228 -7 2 11 0 0.0667114 0.235107 -7 2 12 0 0.0813599 0.296387 -7 2 13 0 0.0985107 0.365723 -7 2 14 0 0.117798 0.442383 -7 2 15 0 0.13855 0.523926 -7 2 16 0 0.1604 0.608398 -7 2 17 0 0.181396 0.689941 -7 2 18 0 0.200806 0.765137 -7 2 19 0 0.218018 0.831055 -7 2 20 0 0.227539 0.867676 -7 2 21 0 0.229248 0.874512 -7 2 22 0 0.231201 0.882324 -7 2 23 0 0.233154 0.890137 -7 2 24 0 0.235107 0.897949 -7 2 25 0 0.237305 0.90625 -7 2 26 0 0.239746 0.915527 -7 2 27 0 0.242554 0.92627 -7 2 28 0 0.245605 0.937988 -7 2 29 0 0.248901 0.950684 -7 2 30 0 0.252197 0.963867 -7 2 31 0 0.255859 0.977051 -7 3 0 0.12854 0.0389709 0 -7 3 1 0.128418 0.0391846 0 -7 3 2 0.128662 0.0393982 0 -7 3 3 0.129028 0.0393677 0.0188293 -7 3 4 0.128906 0.038269 0.0429993 -7 3 5 0.126221 0.0363464 0.0626221 -7 3 6 0.111511 0.0376892 0.0764771 -7 3 7 0.0968628 0.0427246 0.0883789 -7 3 8 0.0896606 0.045166 0.112427 -7 3 9 0.074646 0.0494995 0.143066 -7 3 10 0 0.0570374 0.183228 -7 3 11 0 0.0683594 0.235107 -7 3 12 0 0.0826416 0.296387 -7 3 13 0 0.0994263 0.365723 -7 3 14 0 0.118469 0.442383 -7 3 15 0 0.13916 0.523926 -7 3 16 0 0.160767 0.608398 -7 3 17 0 0.181763 0.689941 -7 3 18 0 0.20105 0.765137 -7 3 19 0 0.21814 0.831055 -7 3 20 0 0.227661 0.867676 -7 3 21 0 0.22937 0.874512 -7 3 22 0 0.231323 0.882324 -7 3 23 0 0.233276 0.890137 -7 3 24 0 0.235229 0.897949 -7 3 25 0 0.237427 0.90625 -7 3 26 0 0.239868 0.915527 -7 3 27 0 0.242554 0.92627 -7 3 28 0 0.245605 0.937988 -7 3 29 0 0.248901 0.950684 -7 3 30 0 0.252441 0.963867 -7 3 31 0 0.255859 0.977051 -7 4 0 0.125 0.0505981 0 -7 4 1 0.124939 0.0507202 0 -7 4 2 0.125122 0.0509033 0 -7 4 3 0.125732 0.0510254 0.0177612 -7 4 4 0.126221 0.0505676 0.0417786 -7 4 5 0.124573 0.0491943 0.0616455 -7 4 6 0.112427 0.0469971 0.0771484 -7 4 7 0.0962524 0.0485535 0.0883179 -7 4 8 0.0889893 0.050415 0.112427 -7 4 9 0.0737305 0.0540161 0.143066 -7 4 10 0 0.06073 0.183105 -7 4 11 0 0.0713501 0.235107 -7 4 12 0 0.0849609 0.296387 -7 4 13 0 0.101196 0.365723 -7 4 14 0 0.119812 0.442383 -7 4 15 0 0.140137 0.523926 -7 4 16 0 0.161499 0.608398 -7 4 17 0 0.182251 0.689941 -7 4 18 0 0.201538 0.765137 -7 4 19 0 0.218506 0.831055 -7 4 20 0 0.227905 0.867676 -7 4 21 0 0.229614 0.875 -7 4 22 0 0.231445 0.882324 -7 4 23 0 0.233398 0.890137 -7 4 24 0 0.235352 0.897949 -7 4 25 0 0.237549 0.90625 -7 4 26 0 0.23999 0.915527 -7 4 27 0 0.242676 0.92627 -7 4 28 0 0.245728 0.937988 -7 4 29 0 0.249023 0.950684 -7 4 30 0 0.252441 0.963867 -7 4 31 0 0.255859 0.977051 -7 5 0 0.117859 0.0628662 0 -7 5 1 0.117798 0.0629272 0 -7 5 2 0.11792 0.0631104 0 -7 5 3 0.118408 0.0632935 0.0206146 -7 5 4 0.119324 0.0635986 0.0402832 -7 5 5 0.120422 0.0637207 0.0595398 -7 5 6 0.113708 0.0608521 0.0782471 -7 5 7 0.0949707 0.057373 0.0881958 -7 5 8 0.0875854 0.0586243 0.112305 -7 5 9 0.0718994 0.0613403 0.143066 -7 5 10 0 0.0670166 0.183105 -7 5 11 0 0.0765991 0.234985 -7 5 12 0 0.0891113 0.296387 -7 5 13 0 0.104431 0.365723 -7 5 14 0 0.122253 0.442383 -7 5 15 0 0.141968 0.523926 -7 5 16 0 0.162964 0.608398 -7 5 17 0 0.18335 0.689941 -7 5 18 0 0.202393 0.765137 -7 5 19 0 0.219116 0.831055 -7 5 20 0 0.228516 0.867676 -7 5 21 0 0.22998 0.875 -7 5 22 0 0.231812 0.882324 -7 5 23 0 0.233643 0.890137 -7 5 24 0 0.235596 0.897949 -7 5 25 0 0.237671 0.90625 -7 5 26 0 0.240112 0.915527 -7 5 27 0 0.242798 0.92627 -7 5 28 0 0.24585 0.937988 -7 5 29 0 0.249023 0.950684 -7 5 30 0 0.252441 0.963867 -7 5 31 0 0.255859 0.977051 -7 6 0 0.106934 0.0742188 0.0193634 -7 6 1 0.106873 0.0742798 0.0194244 -7 6 2 0.106873 0.0743408 0.019516 -7 6 3 0.10675 0.0744019 0.0298462 -7 6 4 0.106567 0.074646 0.0413513 -7 6 5 0.106873 0.0753784 0.0556335 -7 6 6 0.109192 0.0775146 0.0760498 -7 6 7 0.0924072 0.0698853 0.0878296 -7 6 8 0.0848389 0.0705566 0.112122 -7 6 9 0.0681152 0.0723877 0.142944 -7 6 10 0 0.0769653 0.182983 -7 6 11 0 0.0852661 0.234985 -7 6 12 0 0.0963745 0.296387 -7 6 13 0 0.110229 0.365723 -7 6 14 0 0.126709 0.442383 -7 6 15 0 0.145386 0.523926 -7 6 16 0 0.165527 0.608398 -7 6 17 0 0.185425 0.689941 -7 6 18 0 0.203979 0.765137 -7 6 19 0 0.220459 0.831055 -7 6 20 0 0.229492 0.867676 -7 6 21 0 0.230835 0.875 -7 6 22 0 0.232422 0.882324 -7 6 23 0 0.234253 0.890137 -7 6 24 0 0.236084 0.897949 -7 6 25 0 0.238159 0.90625 -7 6 26 0 0.240479 0.915527 -7 6 27 0 0.243042 0.92627 -7 6 28 0 0.246094 0.937988 -7 6 29 0 0.249268 0.950684 -7 6 30 0 0.252686 0.963867 -7 6 31 0 0.256104 0.977539 -7 7 0 0.10144 0.0931396 0.0292206 -7 7 1 0.10144 0.0932007 0.0292358 -7 7 2 0.101501 0.0932007 0.0292358 -7 7 3 0.101196 0.0932007 0.0331116 -7 7 4 0.10022 0.0927734 0.0432434 -7 7 5 0.0983276 0.09198 0.0556641 -7 7 6 0.0946045 0.0904541 0.0704346 -7 7 7 0.0870972 0.0870972 0.0870972 -7 7 8 0.0789795 0.0873413 0.111694 -7 7 9 0.0596924 0.0883179 0.1427 -7 7 10 0 0.0919189 0.182739 -7 7 11 0 0.098938 0.234741 -7 7 12 0 0.108337 0.296143 -7 7 13 0 0.120239 0.365723 -7 7 14 0 0.134888 0.442139 -7 7 15 0 0.151855 0.523926 -7 7 16 0 0.170532 0.608398 -7 7 17 0 0.189331 0.689941 -7 7 18 0 0.207031 0.765137 -7 7 19 0 0.2229 0.831055 -7 7 20 0 0.231445 0.867676 -7 7 21 0 0.232422 0.875 -7 7 22 0 0.233765 0.882324 -7 7 23 0 0.235352 0.890137 -7 7 24 0 0.236938 0.897949 -7 7 25 0 0.238892 0.90625 -7 7 26 0 0.241089 0.916016 -7 7 27 0 0.243652 0.92627 -7 7 28 0 0.246582 0.937988 -7 7 29 0 0.249756 0.950684 -7 7 30 0 0.25293 0.963867 -7 7 31 0 0.256348 0.977539 -7 8 0 0.0856934 0.113159 0.0274048 -7 8 1 0.0856934 0.113159 0.0274048 -7 8 2 0.0856934 0.11322 0.0274048 -7 8 3 0.0856934 0.113281 0.02742 -7 8 4 0.085022 0.112976 0.0370178 -7 8 5 0.083313 0.112183 0.0505981 -7 8 6 0.0801392 0.110901 0.0661621 -7 8 7 0.0748291 0.109924 0.0854492 -7 8 8 0.0647583 0.109985 0.110657 -7 8 9 0.0318909 0.110535 0.142212 -7 8 10 0 0.113281 0.182373 -7 8 11 0 0.119324 0.234375 -7 8 12 0 0.127075 0.295898 -7 8 13 0 0.136719 0.365723 -7 8 14 0 0.148804 0.442139 -7 8 15 0 0.163208 0.523926 -7 8 16 0 0.179565 0.608398 -7 8 17 0 0.196533 0.689941 -7 8 18 0 0.212769 0.765137 -7 8 19 0 0.227539 0.831055 -7 8 20 0 0.235229 0.868164 -7 8 21 0 0.235474 0.875 -7 8 22 0 0.236206 0.882812 -7 8 23 0 0.237427 0.890137 -7 8 24 0 0.23877 0.897949 -7 8 25 0 0.240479 0.906738 -7 8 26 0 0.242432 0.916016 -7 8 27 0 0.244751 0.92627 -7 8 28 0 0.247559 0.937988 -7 8 29 0 0.250488 0.950684 -7 8 30 0 0.253662 0.963867 -7 8 31 0 0.25708 0.977539 -7 9 0 0.0519104 0.13916 0.0255432 -7 9 1 0.0519409 0.139282 0.0255432 -7 9 2 0.0519714 0.139282 0.0255585 -7 9 3 0.0520325 0.139282 0.0255585 -7 9 4 0.0521851 0.139404 0.025589 -7 9 5 0.0499573 0.13916 0.0434265 -7 9 6 0.045166 0.138916 0.0614319 -7 9 7 0.0326843 0.138916 0.0825195 -7 9 8 0 0.139282 0.108643 -7 9 9 0 0.139893 0.141235 -7 9 10 0 0.142212 0.181763 -7 9 11 0 0.147583 0.233765 -7 9 12 0 0.154053 0.295654 -7 9 13 0 0.161621 0.365479 -7 9 14 0 0.170776 0.442139 -7 9 15 0 0.182007 0.523926 -7 9 16 0 0.195312 0.608887 -7 9 17 0 0.209351 0.69043 -7 9 18 0 0.223145 0.765137 -7 9 19 0 0.236084 0.831055 -7 9 20 0 0.24231 0.868652 -7 9 21 0 0.241089 0.875488 -7 9 22 0 0.240845 0.882812 -7 9 23 0 0.241333 0.890625 -7 9 24 0 0.242065 0.898438 -7 9 25 0 0.243286 0.906738 -7 9 26 0 0.244995 0.916016 -7 9 27 0 0.246948 0.926758 -7 9 28 0 0.24939 0.938477 -7 9 29 0 0.252197 0.950684 -7 9 30 0 0.255127 0.963867 -7 9 31 0 0.258301 0.977539 -7 10 0 0 0.175903 0.02388 -7 10 1 0 0.175903 0.02388 -7 10 2 0 0.175903 0.0238953 -7 10 3 0 0.175903 0.0239105 -7 10 4 0 0.176025 0.023941 -7 10 5 0 0.176025 0.0279999 -7 10 6 0 0.176025 0.0542603 -7 10 7 0 0.176025 0.0782471 -7 10 8 0 0.17627 0.106079 -7 10 9 0 0.177124 0.139893 -7 10 10 0 0.179199 0.181152 -7 10 11 0 0.184082 0.233032 -7 10 12 0 0.189575 0.294922 -7 10 13 0 0.195435 0.36499 -7 10 14 0 0.202026 0.441895 -7 10 15 0 0.209961 0.523926 -7 10 16 0 0.219482 0.608887 -7 10 17 0 0.229858 0.69043 -7 10 18 0 0.240356 0.765625 -7 10 19 0 0.250488 0.831543 -7 10 20 0 0.254395 0.869629 -7 10 21 0 0.250977 0.876465 -7 10 22 0 0.249023 0.883789 -7 10 23 0 0.248169 0.891113 -7 10 24 0 0.248047 0.898926 -7 10 25 0 0.248413 0.907227 -7 10 26 0 0.24939 0.916504 -7 10 27 0 0.250732 0.926758 -7 10 28 0 0.252686 0.938477 -7 10 29 0 0.254883 0.951172 -7 10 30 0 0.257568 0.964355 -7 10 31 0 0.260254 0.977539 -7 11 0 0 0.224487 0.0210571 -7 11 1 0 0.224487 0.0210571 -7 11 2 0 0.224487 0.0210724 -7 11 3 0 0.224487 0.0210876 -7 11 4 0 0.224609 0.0211182 -7 11 5 0 0.224609 0.0211945 -7 11 6 0 0.224731 0.0364075 -7 11 7 0 0.224609 0.0710449 -7 11 8 0 0.224487 0.102722 -7 11 9 0 0.224854 0.138672 -7 11 10 0 0.22644 0.18103 -7 11 11 0 0.229858 0.232422 -7 11 12 0 0.234253 0.293945 -7 11 13 0 0.238892 0.364258 -7 11 14 0 0.243408 0.44165 -7 11 15 0 0.248169 0.523926 -7 11 16 0 0.253906 0.608887 -7 11 17 0 0.26001 0.690918 -7 11 18 0 0.266602 0.766113 -7 11 19 0 0.272949 0.832031 -7 11 20 0 0.273682 0.871094 -7 11 21 0 0.266846 0.877441 -7 11 22 0 0.262451 0.884766 -7 11 23 0 0.259521 0.89209 -7 11 24 0 0.258057 0.899902 -7 11 25 0 0.25708 0.908203 -7 11 26 0 0.256836 0.916992 -7 11 27 0 0.257324 0.927734 -7 11 28 0 0.258301 0.939453 -7 11 29 0 0.259766 0.95166 -7 11 30 0 0.261719 0.964844 -7 11 31 0 0.263916 0.978027 -7 12 0 0 0.283936 0.0123444 -7 12 1 0 0.283936 0.0123596 -7 12 2 0 0.283936 0.0123825 -7 12 3 0 0.283936 0.0124283 -7 12 4 0 0.283936 0.0125122 -7 12 5 0 0.283936 0.0126648 -7 12 6 0 0.28418 0.0129623 -7 12 7 0 0.28418 0.0516968 -7 12 8 0 0.28418 0.0949097 -7 12 9 0 0.28418 0.135376 -7 12 10 0 0.284912 0.179932 -7 12 11 0 0.286377 0.231567 -7 12 12 0 0.289307 0.292725 -7 12 13 0 0.29248 0.363037 -7 12 14 0 0.29541 0.440918 -7 12 15 0 0.297607 0.523438 -7 12 16 0 0.299805 0.609375 -7 12 17 0 0.301758 0.691406 -7 12 18 0 0.303711 0.766602 -7 12 19 0 0.305908 0.83252 -7 12 20 0 0.302734 0.873535 -7 12 21 0 0.29126 0.879883 -7 12 22 0 0.283203 0.886719 -7 12 23 0 0.277588 0.894043 -7 12 24 0 0.273682 0.901367 -7 12 25 0 0.270996 0.90918 -7 12 26 0 0.269043 0.918457 -7 12 27 0 0.267822 0.928711 -7 12 28 0 0.267578 0.939941 -7 12 29 0 0.267822 0.952637 -7 12 30 0 0.268799 0.965332 -7 12 31 0 0.27002 0.978516 -7 13 0 0 0.351562 0 -7 13 1 0 0.351562 0 -7 13 2 0 0.351562 0 -7 13 3 0 0.351562 0 -7 13 4 0 0.351562 0 -7 13 5 0 0.351562 0 -7 13 6 0 0.351807 0 -7 13 7 0 0.351807 0 -7 13 8 0 0.352051 0.0749512 -7 13 9 0 0.352051 0.126099 -7 13 10 0 0.352539 0.175049 -7 13 11 0 0.353027 0.22876 -7 13 12 0 0.354492 0.290527 -7 13 13 0 0.356445 0.36084 -7 13 14 0 0.35791 0.439209 -7 13 15 0 0.358154 0.522949 -7 13 16 0 0.357422 0.608887 -7 13 17 0 0.355225 0.691895 -7 13 18 0 0.352783 0.767578 -7 13 19 0 0.350342 0.833984 -7 13 20 0 0.343018 0.877441 -7 13 21 0 0.325684 0.883301 -7 13 22 0 0.312988 0.889648 -7 13 23 0 0.303955 0.896484 -7 13 24 0 0.297119 0.903809 -7 13 25 0 0.291748 0.911621 -7 13 26 0 0.287354 0.92041 -7 13 27 0 0.283936 0.930176 -7 13 28 0 0.281738 0.941895 -7 13 29 0 0.280518 0.953613 -7 13 30 0 0.279785 0.966309 -7 13 31 0 0.279541 0.979492 -7 14 0 0 0.426758 0 -7 14 1 0 0.426758 0 -7 14 2 0 0.426758 0 -7 14 3 0 0.426758 0 -7 14 4 0 0.427002 0 -7 14 5 0 0.427002 0 -7 14 6 0 0.427002 0 -7 14 7 0 0.427002 0 -7 14 8 0 0.427246 0 -7 14 9 0 0.42749 0.105957 -7 14 10 0 0.427979 0.164062 -7 14 11 0 0.428467 0.221924 -7 14 12 0 0.429443 0.285645 -7 14 13 0 0.430176 0.356934 -7 14 14 0 0.430664 0.436035 -7 14 15 0 0.429443 0.520508 -7 14 16 0 0.42627 0.608398 -7 14 17 0 0.420898 0.691895 -7 14 18 0 0.414062 0.768555 -7 14 19 0 0.406738 0.834961 -7 14 20 0 0.395996 0.882812 -7 14 21 0 0.37207 0.888672 -7 14 22 0 0.354004 0.89502 -7 14 23 0 0.340332 0.901367 -7 14 24 0 0.329834 0.907715 -7 14 25 0 0.321045 0.915527 -7 14 26 0 0.313477 0.923828 -7 14 27 0 0.307373 0.933105 -7 14 28 0 0.30249 0.944336 -7 14 29 0 0.298828 0.956055 -7 14 30 0 0.295898 0.968262 -7 14 31 0 0.293945 0.981445 -7 15 0 0 0.507812 0 -7 15 1 0 0.507812 0 -7 15 2 0 0.507812 0 -7 15 3 0 0.507812 0 -7 15 4 0 0.507812 0 -7 15 5 0 0.507812 0 -7 15 6 0 0.507812 0 -7 15 7 0 0.507812 0 -7 15 8 0 0.507812 0 -7 15 9 0 0.508301 0.0475159 -7 15 10 0 0.508789 0.143311 -7 15 11 0 0.509766 0.20874 -7 15 12 0 0.510742 0.276123 -7 15 13 0 0.51123 0.349365 -7 15 14 0 0.51123 0.429688 -7 15 15 0 0.509766 0.516113 -7 15 16 0 0.504883 0.605469 -7 15 17 0 0.496826 0.690918 -7 15 18 0 0.486328 0.768555 -7 15 19 0 0.475098 0.836426 -7 15 20 0 0.461426 0.88916 -7 15 21 0 0.430664 0.896484 -7 15 22 0 0.406494 0.902344 -7 15 23 0 0.387695 0.908691 -7 15 24 0 0.373047 0.914551 -7 15 25 0 0.360107 0.921387 -7 15 26 0 0.348877 0.929199 -7 15 27 0 0.339111 0.937988 -7 15 28 0 0.331055 0.94873 -7 15 29 0 0.324219 0.959961 -7 15 30 0 0.318848 0.97168 -7 15 31 0 0.314209 0.983887 -7 16 0 0 0.592773 0 -7 16 1 0 0.592773 0 -7 16 2 0 0.592773 0 -7 16 3 0 0.592773 0 -7 16 4 0 0.592773 0 -7 16 5 0 0.592773 0 -7 16 6 0 0.592773 0 -7 16 7 0 0.592773 0 -7 16 8 0 0.592773 0 -7 16 9 0 0.593262 0 -7 16 10 0 0.59375 0.101501 -7 16 11 0 0.594727 0.187134 -7 16 12 0 0.595703 0.260498 -7 16 13 0 0.597168 0.336914 -7 16 14 0 0.597656 0.419434 -7 16 15 0 0.596191 0.507324 -7 16 16 0 0.591309 0.598633 -7 16 17 0 0.582031 0.687012 -7 16 18 0 0.568848 0.76709 -7 16 19 0 0.553711 0.836426 -7 16 20 0 0.537598 0.893555 -7 16 21 0 0.501953 0.90625 -7 16 22 0 0.471191 0.913574 -7 16 23 0 0.446777 0.919434 -7 16 24 0 0.427246 0.924805 -7 16 25 0 0.409668 0.930664 -7 16 26 0 0.394043 0.937988 -7 16 27 0 0.380127 0.945801 -7 16 28 0 0.368164 0.955078 -7 16 29 0 0.35791 0.965332 -7 16 30 0 0.348877 0.976562 -7 16 31 0 0.341064 0.988281 -7 17 0 0 0.67627 0 -7 17 1 0 0.67627 0 -7 17 2 0 0.67627 0 -7 17 3 0 0.67627 0 -7 17 4 0 0.67627 0 -7 17 5 0 0.676758 0 -7 17 6 0 0.676758 0 -7 17 7 0 0.676758 0 -7 17 8 0 0.676758 0 -7 17 9 0 0.676758 0 -7 17 10 0 0.677246 0 -7 17 11 0 0.678223 0.151855 -7 17 12 0 0.679688 0.238037 -7 17 13 0 0.681641 0.318848 -7 17 14 0 0.683105 0.403564 -7 17 15 0 0.683105 0.493652 -7 17 16 0 0.679199 0.587402 -7 17 17 0 0.669922 0.678223 -7 17 18 0 0.655762 0.761719 -7 17 19 0 0.638672 0.833984 -7 17 20 0 0.619141 0.893066 -7 17 21 0 0.58252 0.916504 -7 17 22 0 0.546387 0.927246 -7 17 23 0 0.516602 0.933594 -7 17 24 0 0.491943 0.938965 -7 17 25 0 0.469238 0.944336 -7 17 26 0 0.448486 0.950195 -7 17 27 0 0.429932 0.957031 -7 17 28 0 0.41333 0.964844 -7 17 29 0 0.398926 0.974121 -7 17 30 0 0.385986 0.983887 -7 17 31 0 0.374512 0.994141 -7 18 0 0 0.754395 0 -7 18 1 0 0.754395 0 -7 18 2 0 0.754395 0 -7 18 3 0 0.754395 0 -7 18 4 0 0.754395 0 -7 18 5 0 0.754395 0 -7 18 6 0 0.754883 0 -7 18 7 0 0.754883 0 -7 18 8 0 0.754883 0 -7 18 9 0 0.754883 0 -7 18 10 0 0.754883 0 -7 18 11 0 0.755371 0.078064 -7 18 12 0 0.757324 0.206543 -7 18 13 0 0.759766 0.294922 -7 18 14 0 0.762695 0.382812 -7 18 15 0 0.763672 0.474609 -7 18 16 0 0.762207 0.570312 -7 18 17 0 0.754883 0.664551 -7 18 18 0 0.742188 0.751465 -7 18 19 0 0.724121 0.827148 -7 18 20 0 0.702637 0.889648 -7 18 21 0 0.667969 0.924316 -7 18 22 0 0.629395 0.941406 -7 18 23 0 0.594727 0.951172 -7 18 24 0 0.564941 0.95752 -7 18 25 0 0.537109 0.962402 -7 18 26 0 0.510742 0.967285 -7 18 27 0 0.487061 0.972168 -7 18 28 0 0.465576 0.978516 -7 18 29 0 0.446289 0.98584 -7 18 30 0 0.429199 0.993652 -7 18 31 0 0.413574 1 -7 19 0 0 0.824707 0 -7 19 1 0 0.824707 0 -7 19 2 0 0.824707 0 -7 19 3 0 0.824707 0 -7 19 4 0 0.824707 0 -7 19 5 0 0.824707 0 -7 19 6 0 0.824707 0 -7 19 7 0 0.824707 0 -7 19 8 0 0.824707 0 -7 19 9 0 0.824707 0 -7 19 10 0 0.825195 0 -7 19 11 0 0.825195 0 -7 19 12 0 0.82666 0.162476 -7 19 13 0 0.82959 0.266113 -7 19 14 0 0.833008 0.358154 -7 19 15 0 0.835449 0.451416 -7 19 16 0 0.836426 0.548828 -7 19 17 0 0.832031 0.64502 -7 19 18 0 0.821777 0.73584 -7 19 19 0 0.805176 0.81543 -7 19 20 0 0.783691 0.881348 -7 19 21 0 0.751953 0.927246 -7 19 22 0 0.714355 0.953613 -7 19 23 0 0.677246 0.968262 -7 19 24 0 0.643555 0.977051 -7 19 25 0 0.610352 0.982422 -7 19 26 0 0.579102 0.986816 -7 19 27 0 0.549805 0.990723 -7 19 28 0 0.522949 0.995117 -7 19 29 0 0.498779 1 -7 19 30 0 0.476562 1 -7 19 31 0 0.456787 1 -7 20 0 0 0.885254 0 -7 20 1 0 0.885254 0 -7 20 2 0 0.885254 0 -7 20 3 0 0.885254 0 -7 20 4 0 0.885254 0 -7 20 5 0 0.885254 0 -7 20 6 0 0.885254 0 -7 20 7 0 0.885254 0 -7 20 8 0 0.885254 0 -7 20 9 0 0.885254 0 -7 20 10 0 0.885742 0 -7 20 11 0 0.885742 0 -7 20 12 0 0.88623 0.0795288 -7 20 13 0 0.88916 0.232056 -7 20 14 0 0.893066 0.330811 -7 20 15 0 0.896973 0.42627 -7 20 16 0 0.899902 0.524414 -7 20 17 0 0.898438 0.62207 -7 20 18 0 0.891113 0.715332 -7 20 19 0 0.876953 0.79834 -7 20 20 0 0.856934 0.867676 -7 20 21 0 0.830078 0.922852 -7 20 22 0 0.79541 0.959961 -7 20 23 0 0.758789 0.981934 -7 20 24 0 0.722656 0.994141 -7 20 25 0 0.686035 1 -7 20 26 0 0.649902 1 -7 20 27 0 0.615723 1 -7 20 28 0 0.583496 1 -7 20 29 0 0.553711 1 -7 20 30 0 0.526855 1 -7 20 31 0 0.502441 1 -7 21 0 0 0.937012 0 -7 21 1 0 0.937012 0 -7 21 2 0 0.937012 0 -7 21 3 0 0.937012 0 -7 21 4 0 0.937012 0 -7 21 5 0 0.937012 0 -7 21 6 0 0.937012 0 -7 21 7 0 0.937012 0 -7 21 8 0 0.937012 0 -7 21 9 0 0.937012 0 -7 21 10 0 0.937012 0 -7 21 11 0 0.937012 0 -7 21 12 0 0.9375 0 -7 21 13 0 0.939941 0.189453 -7 21 14 0 0.943848 0.300537 -7 21 15 0 0.94873 0.398926 -7 21 16 0 0.953125 0.497559 -7 21 17 0 0.954102 0.595703 -7 21 18 0 0.950195 0.69043 -7 21 19 0 0.939453 0.775879 -7 21 20 0 0.922363 0.849121 -7 21 21 0 0.899414 0.910645 -7 21 22 0 0.870117 0.957031 -7 21 23 0 0.835449 0.987305 -7 21 24 0 0.799805 1 -7 21 25 0 0.76123 1 -7 21 26 0 0.722168 1 -7 21 27 0 0.683594 1 -7 21 28 0 0.646484 1 -7 21 29 0 0.611816 1 -7 21 30 0 0.580078 1 -7 21 31 0 0.550781 1 -7 22 0 0 0.979492 0 -7 22 1 0 0.979492 0 -7 22 2 0 0.979492 0 -7 22 3 0 0.979492 0 -7 22 4 0 0.979492 0 -7 22 5 0 0.979492 0 -7 22 6 0 0.979492 0 -7 22 7 0 0.979492 0 -7 22 8 0 0.979492 0 -7 22 9 0 0.979492 0 -7 22 10 0 0.979492 0 -7 22 11 0 0.97998 0 -7 22 12 0 0.97998 0 -7 22 13 0 0.981445 0.12854 -7 22 14 0 0.98584 0.267334 -7 22 15 0 0.990723 0.369873 -7 22 16 0 0.996094 0.469482 -7 22 17 0 1 0.567871 -7 22 18 0 0.999023 0.663086 -7 22 19 0 0.991699 0.750488 -7 22 20 0 0.978027 0.82666 -7 22 21 0 0.958008 0.891602 -7 22 22 0 0.933105 0.944824 -7 22 23 0 0.90332 0.983398 -7 22 24 0 0.870117 1 -7 22 25 0 0.83252 1 -7 22 26 0 0.791992 1 -7 22 27 0 0.750488 1 -7 22 28 0 0.709961 1 -7 22 29 0 0.670898 1 -7 22 30 0 0.634277 1 -7 22 31 0 0.600586 1 -7 23 0 0 1 0 -7 23 1 0 1 0 -7 23 2 0 1 0 -7 23 3 0 1 0 -7 23 4 0 1 0 -7 23 5 0 1 0 -7 23 6 0 1 0 -7 23 7 0 1 0 -7 23 8 0 1 0 -7 23 9 0 1 0 -7 23 10 0 1 0 -7 23 11 0 1 0 -7 23 12 0 1 0 -7 23 13 0 1 0 -7 23 14 0 1 0.231689 -7 23 15 0 1 0.341064 -7 23 16 0 1 0.44165 -7 23 17 0 1 0.540039 -7 23 18 0 1 0.634766 -7 23 19 0 1 0.723145 -7 23 20 0 1 0.80127 -7 23 21 0 1 0.869629 -7 23 22 0 0.984375 0.92627 -7 23 23 0 0.958984 0.971191 -7 23 24 0 0.929688 1 -7 23 25 0 0.89502 1 -7 23 26 0 0.855469 1 -7 23 27 0 0.812988 1 -7 23 28 0 0.769531 1 -7 23 29 0 0.727539 1 -7 23 30 0 0.687012 1 -7 23 31 0 0.648926 1 -7 24 0 0 1 0 -7 24 1 0 1 0 -7 24 2 0 1 0 -7 24 3 0 1 0 -7 24 4 0 1 0 -7 24 5 0 1 0 -7 24 6 0 1 0 -7 24 7 0 1 0 -7 24 8 0 1 0 -7 24 9 0 1 0 -7 24 10 0 1 0 -7 24 11 0 1 0 -7 24 12 0 1 0 -7 24 13 0 1 0 -7 24 14 0 1 0.191284 -7 24 15 0 1 0.312256 -7 24 16 0 1 0.414307 -7 24 17 0 1 0.512207 -7 24 18 0 1 0.606934 -7 24 19 0 1 0.695312 -7 24 20 0 1 0.774902 -7 24 21 0 1 0.845215 -7 24 22 0 1 0.904785 -7 24 23 0 1 0.953125 -7 24 24 0 0.979004 0.991699 -7 24 25 0 0.948242 1 -7 24 26 0 0.911133 1 -7 24 27 0 0.869141 1 -7 24 28 0 0.825195 1 -7 24 29 0 0.780762 1 -7 24 30 0 0.737305 1 -7 24 31 0 0.695801 1 -7 25 0 0 1 0 -7 25 1 0 1 0 -7 25 2 0 1 0 -7 25 3 0 1 0 -7 25 4 0 1 0 -7 25 5 0 1 0 -7 25 6 0 1 0 -7 25 7 0 1 0 -7 25 8 0 1 0 -7 25 9 0 1 0 -7 25 10 0 1 0 -7 25 11 0 1 0 -7 25 12 0 1 0 -7 25 13 0 1 0 -7 25 14 0 1 0.13269 -7 25 15 0 1 0.279541 -7 25 16 0 1 0.38501 -7 25 17 0 1 0.482666 -7 25 18 0 1 0.576172 -7 25 19 0 1 0.664551 -7 25 20 0 1 0.744141 -7 25 21 0 1 0.816406 -7 25 22 0 1 0.878906 -7 25 23 0 1 0.930176 -7 25 24 0 1 0.972656 -7 25 25 0 0.99707 1 -7 25 26 0 0.963867 1 -7 25 27 0 0.924316 1 -7 25 28 0 0.880371 1 -7 25 29 0 0.834961 1 -7 25 30 0 0.789551 1 -7 25 31 0 0.745117 1 -7 26 0 0 1 0 -7 26 1 0 1 0 -7 26 2 0 1 0 -7 26 3 0 1 0 -7 26 4 0 1 0 -7 26 5 0 1 0 -7 26 6 0 1 0 -7 26 7 0 1 0 -7 26 8 0 1 0 -7 26 9 0 1 0 -7 26 10 0 1 0 -7 26 11 0 1 0 -7 26 12 0 1 0 -7 26 13 0 1 0 -7 26 14 0 1 0 -7 26 15 0 1 0.241943 -7 26 16 0 1 0.353271 -7 26 17 0 1 0.451172 -7 26 18 0 1 0.543457 -7 26 19 0 1 0.630859 -7 26 20 0 1 0.710938 -7 26 21 0 1 0.783691 -7 26 22 0 1 0.848633 -7 26 23 0 1 0.902832 -7 26 24 0 1 0.948242 -7 26 25 0 1 0.989258 -7 26 26 0 1 1 -7 26 27 0 0.976074 1 -7 26 28 0 0.93457 1 -7 26 29 0 0.889648 1 -7 26 30 0 0.842773 1 -7 26 31 0 0.796387 1 -7 27 0 0 1 0 -7 27 1 0 1 0 -7 27 2 0 1 0 -7 27 3 0 1 0 -7 27 4 0 1 0 -7 27 5 0 1 0 -7 27 6 0 1 0 -7 27 7 0 1 0 -7 27 8 0 1 0 -7 27 9 0 1 0 -7 27 10 0 1 0 -7 27 11 0 1 0 -7 27 12 0 1 0 -7 27 13 0 1 0 -7 27 14 0 1 0 -7 27 15 0 1 0.195557 -7 27 16 0 1 0.318604 -7 27 17 0 1 0.417725 -7 27 18 0 1 0.509277 -7 27 19 0 1 0.595215 -7 27 20 0 1 0.674805 -7 27 21 0 1 0.748047 -7 27 22 0 1 0.813965 -7 27 23 0 1 0.870605 -7 27 24 0 1 0.918457 -7 27 25 0 1 0.962891 -7 27 26 0 1 1 -7 27 27 0 1 1 -7 27 28 0 0.98584 1 -7 27 29 0 0.941895 1 -7 27 30 0 0.895508 1 -7 27 31 0 0.848145 1 -7 28 0 0 1 0 -7 28 1 0 1 0 -7 28 2 0 1 0 -7 28 3 0 1 0 -7 28 4 0 1 0 -7 28 5 0 1 0 -7 28 6 0 1 0 -7 28 7 0 1 0 -7 28 8 0 1 0 -7 28 9 0 1 0 -7 28 10 0 1 0 -7 28 11 0 1 0 -7 28 12 0 1 0 -7 28 13 0 1 0 -7 28 14 0 1 0 -7 28 15 0 1 0.126953 -7 28 16 0 1 0.280518 -7 28 17 0 1 0.382812 -7 28 18 0 1 0.473877 -7 28 19 0 1 0.558105 -7 28 20 0 1 0.63623 -7 28 21 0 1 0.709473 -7 28 22 0 1 0.775879 -7 28 23 0 1 0.833496 -7 28 24 0 1 0.883789 -7 28 25 0 1 0.931152 -7 28 26 0 1 0.974609 -7 28 27 0 1 1 -7 28 28 0 1 1 -7 28 29 0 0.991699 1 -7 28 30 0 0.947266 1 -7 28 31 0 0.899902 1 -7 29 0 0 1 0 -7 29 1 0 1 0 -7 29 2 0 1 0 -7 29 3 0 1 0 -7 29 4 0 1 0 -7 29 5 0 1 0 -7 29 6 0 1 0 -7 29 7 0 1 0 -7 29 8 0 1 0 -7 29 9 0 1 0 -7 29 10 0 1 0 -7 29 11 0 1 0 -7 29 12 0 1 0 -7 29 13 0 1 0 -7 29 14 0 1 0 -7 29 15 0 1 0 -7 29 16 0 1 0.236572 -7 29 17 0 1 0.345215 -7 29 18 0 1 0.436523 -7 29 19 0 1 0.519531 -7 29 20 0 1 0.596191 -7 29 21 0 1 0.667969 -7 29 22 0 1 0.733887 -7 29 23 0 1 0.79248 -7 29 24 0 1 0.84375 -7 29 25 0 1 0.893555 -7 29 26 0 1 0.94043 -7 29 27 0 1 0.98291 -7 29 28 0 1 1 -7 29 29 0 1 1 -7 29 30 0 0.996582 1 -7 29 31 0 0.951172 1 -7 30 0 0 1 0 -7 30 1 0 1 0 -7 30 2 0 1 0 -7 30 3 0 1 0 -7 30 4 0 1 0 -7 30 5 0 1 0 -7 30 6 0 1 0 -7 30 7 0 1 0 -7 30 8 0 1 0 -7 30 9 0 1 0 -7 30 10 0 1 0 -7 30 11 0 1 0 -7 30 12 0 1 0 -7 30 13 0 1 0 -7 30 14 0 1 0 -7 30 15 0 1 0 -7 30 16 0 1 0.182007 -7 30 17 0 1 0.304932 -7 30 18 0 1 0.397461 -7 30 19 0 1 0.479248 -7 30 20 0 1 0.554199 -7 30 21 0 1 0.624512 -7 30 22 0 1 0.689453 -7 30 23 0 1 0.747559 -7 30 24 0 1 0.799805 -7 30 25 0 1 0.851074 -7 30 26 0 1 0.899902 -7 30 27 0 1 0.946289 -7 30 28 0 1 0.988281 -7 30 29 0 1 1 -7 30 30 0 1 1 -7 30 31 0 1 1 -7 31 0 0 1 0 -7 31 1 0 1 0 -7 31 2 0 1 0 -7 31 3 0 1 0 -7 31 4 0 1 0 -7 31 5 0 1 0 -7 31 6 0 1 0 -7 31 7 0 1 0 -7 31 8 0 1 0 -7 31 9 0 1 0 -7 31 10 0 1 0 -7 31 11 0 1 0 -7 31 12 0 1 0 -7 31 13 0 1 0 -7 31 14 0 1 0 -7 31 15 0 1 0 -7 31 16 0 1 0.0875854 -7 31 17 0 1 0.260742 -7 31 18 0 1 0.356934 -7 31 19 0 1 0.438232 -7 31 20 0 1 0.51123 -7 31 21 0 1 0.57959 -7 31 22 0 1 0.643066 -7 31 23 0 1 0.700684 -7 31 24 0 1 0.752441 -7 31 25 0 1 0.804199 -7 31 26 0 1 0.855469 -7 31 27 0 1 0.904785 -7 31 28 0 1 0.951172 -7 31 29 0 1 0.992676 -7 31 30 0 1 1 -7 31 31 0 1 1 -8 0 0 0.168457 0 0.00870514 -8 0 1 0.168457 0 0.0085907 -8 0 2 0.168457 0 0.00837708 -8 0 3 0.168579 0 0.00814056 -8 0 4 0.168701 0 0.0214081 -8 0 5 0.167114 0 0.0551758 -8 0 6 0.162598 0 0.079895 -8 0 7 0.141357 0.0254211 0.0961914 -8 0 8 0.124023 0.0435486 0.112488 -8 0 9 0.115479 0.0482788 0.143311 -8 0 10 0.0993652 0.0559998 0.183228 -8 0 11 0.0453491 0.0675049 0.235107 -8 0 12 0 0.0820312 0.296387 -8 0 13 0 0.098999 0.365967 -8 0 14 0 0.118164 0.442383 -8 0 15 0 0.138916 0.523926 -8 0 16 0 0.160645 0.608398 -8 0 17 0 0.181641 0.689941 -8 0 18 0 0.20105 0.765137 -8 0 19 0 0.21814 0.831055 -8 0 20 0 0.227661 0.868164 -8 0 21 0 0.22937 0.875 -8 0 22 0 0.231323 0.882812 -8 0 23 0 0.233276 0.890137 -8 0 24 0 0.235229 0.897949 -8 0 25 0 0.237427 0.90625 -8 0 26 0 0.239868 0.916016 -8 0 27 0 0.242554 0.92627 -8 0 28 0 0.245605 0.937988 -8 0 29 0 0.248901 0.950684 -8 0 30 0 0.252441 0.963867 -8 0 31 0 0.255859 0.977539 -8 1 0 0.168213 0 0.00707245 -8 1 1 0.168091 0 0.00691605 -8 1 2 0.168091 0 0.00661469 -8 1 3 0.168213 0 0.0062561 -8 1 4 0.168457 0 0.0209351 -8 1 5 0.166992 0 0.0550232 -8 1 6 0.162598 0 0.079834 -8 1 7 0.141357 0.0281219 0.0962524 -8 1 8 0.123962 0.0444946 0.112427 -8 1 9 0.115417 0.0490723 0.143311 -8 1 10 0.0993042 0.0566406 0.183228 -8 1 11 0.0449829 0.0679932 0.235107 -8 1 12 0 0.0823975 0.296387 -8 1 13 0 0.0993042 0.365967 -8 1 14 0 0.118408 0.442383 -8 1 15 0 0.139038 0.523926 -8 1 16 0 0.160767 0.608398 -8 1 17 0 0.181763 0.689941 -8 1 18 0 0.20105 0.765137 -8 1 19 0 0.21814 0.831055 -8 1 20 0 0.227661 0.868164 -8 1 21 0 0.229492 0.875 -8 1 22 0 0.231323 0.882812 -8 1 23 0 0.233276 0.890137 -8 1 24 0 0.235229 0.897949 -8 1 25 0 0.237427 0.90625 -8 1 26 0 0.239868 0.916016 -8 1 27 0 0.242554 0.92627 -8 1 28 0 0.245728 0.937988 -8 1 29 0 0.248901 0.950684 -8 1 30 0 0.252441 0.963867 -8 1 31 0 0.255859 0.977539 -8 2 0 0.167603 0.01371 0 -8 2 1 0.167603 0.0147934 0 -8 2 2 0.167603 0.016449 0 -8 2 3 0.167725 0.0180511 0 -8 2 4 0.167969 0.0186615 0.0201111 -8 2 5 0.166748 0.00863647 0.0547485 -8 2 6 0.162476 0 0.0797119 -8 2 7 0.141602 0.032135 0.0963745 -8 2 8 0.12384 0.0461426 0.112427 -8 2 9 0.115295 0.0504761 0.143311 -8 2 10 0.0991211 0.0577698 0.183228 -8 2 11 0.044342 0.0689087 0.234985 -8 2 12 0 0.0830688 0.296387 -8 2 13 0 0.0997925 0.365967 -8 2 14 0 0.118774 0.442383 -8 2 15 0 0.139404 0.523926 -8 2 16 0 0.160889 0.608398 -8 2 17 0 0.181885 0.689941 -8 2 18 0 0.201172 0.765137 -8 2 19 0 0.218262 0.831055 -8 2 20 0 0.227783 0.868164 -8 2 21 0 0.229492 0.875 -8 2 22 0 0.231445 0.882812 -8 2 23 0 0.233276 0.890137 -8 2 24 0 0.235352 0.897949 -8 2 25 0 0.237427 0.90625 -8 2 26 0 0.239868 0.916016 -8 2 27 0 0.242676 0.92627 -8 2 28 0 0.245728 0.937988 -8 2 29 0 0.248901 0.950684 -8 2 30 0 0.252441 0.963867 -8 2 31 0 0.255859 0.977539 -8 3 0 0.166504 0.0328674 0 -8 3 1 0.166504 0.0331421 0 -8 3 2 0.166504 0.0335999 0 -8 3 3 0.166626 0.0341797 0 -8 3 4 0.166992 0.0343628 0.0186462 -8 3 5 0.166138 0.0316467 0.0542297 -8 3 6 0.162109 0.0277557 0.0794067 -8 3 7 0.141846 0.0379944 0.0966187 -8 3 8 0.123596 0.0489197 0.112427 -8 3 9 0.115051 0.0528564 0.143311 -8 3 10 0.0988159 0.0597229 0.183228 -8 3 11 0.0431213 0.0704956 0.234985 -8 3 12 0 0.0842896 0.296387 -8 3 13 0 0.100708 0.365967 -8 3 14 0 0.119446 0.442383 -8 3 15 0 0.139893 0.523926 -8 3 16 0 0.161377 0.608398 -8 3 17 0 0.182129 0.689941 -8 3 18 0 0.201416 0.765137 -8 3 19 0 0.218384 0.831055 -8 3 20 0 0.227905 0.868164 -8 3 21 0 0.229614 0.875 -8 3 22 0 0.231445 0.882812 -8 3 23 0 0.233398 0.890137 -8 3 24 0 0.235352 0.897949 -8 3 25 0 0.237549 0.906738 -8 3 26 0 0.23999 0.916016 -8 3 27 0 0.242676 0.92627 -8 3 28 0 0.245728 0.937988 -8 3 29 0 0.249023 0.950684 -8 3 30 0 0.252441 0.963867 -8 3 31 0 0.255859 0.977539 -8 4 0 0.164307 0.0476685 0 -8 4 1 0.164307 0.047821 0 -8 4 2 0.164307 0.0480652 0 -8 4 3 0.164429 0.0484009 0 -8 4 4 0.165039 0.048584 0.0161591 -8 4 5 0.164795 0.0470276 0.0533142 -8 4 6 0.161377 0.0444641 0.0788574 -8 4 7 0.142456 0.0464783 0.0971069 -8 4 8 0.123169 0.0535889 0.112366 -8 4 9 0.114563 0.0569458 0.143311 -8 4 10 0.0982056 0.0632324 0.183105 -8 4 11 0.0406494 0.0733032 0.234985 -8 4 12 0 0.0865479 0.296387 -8 4 13 0 0.102417 0.365967 -8 4 14 0 0.120728 0.442383 -8 4 15 0 0.140869 0.523926 -8 4 16 0 0.162109 0.608398 -8 4 17 0 0.182739 0.689941 -8 4 18 0 0.201904 0.765137 -8 4 19 0 0.21875 0.831055 -8 4 20 0 0.228271 0.868164 -8 4 21 0 0.229858 0.875 -8 4 22 0 0.231689 0.882812 -8 4 23 0 0.233521 0.890137 -8 4 24 0 0.235474 0.897949 -8 4 25 0 0.237671 0.906738 -8 4 26 0 0.240112 0.916016 -8 4 27 0 0.242798 0.92627 -8 4 28 0 0.24585 0.937988 -8 4 29 0 0.249023 0.950684 -8 4 30 0 0.252441 0.963867 -8 4 31 0 0.255859 0.977539 -8 5 0 0.15979 0.0633545 0 -8 5 1 0.15979 0.0634155 0 -8 5 2 0.15979 0.0635376 0 -8 5 3 0.15979 0.0637817 0 -8 5 4 0.160645 0.0640259 0.0139542 -8 5 5 0.161255 0.0634155 0.0516663 -8 5 6 0.15918 0.0616455 0.0775757 -8 5 7 0.143555 0.0588379 0.0979614 -8 5 8 0.122375 0.0610962 0.112244 -8 5 9 0.113708 0.0637817 0.143188 -8 5 10 0.0969849 0.0691528 0.183105 -8 5 11 0.0350342 0.0783691 0.234985 -8 5 12 0 0.0905762 0.296387 -8 5 13 0 0.105652 0.365967 -8 5 14 0 0.123169 0.442383 -8 5 15 0 0.1427 0.523926 -8 5 16 0 0.163452 0.608398 -8 5 17 0 0.183838 0.689941 -8 5 18 0 0.202759 0.765137 -8 5 19 0 0.219482 0.831055 -8 5 20 0 0.22876 0.868164 -8 5 21 0 0.230225 0.875 -8 5 22 0 0.232056 0.882812 -8 5 23 0 0.233887 0.890137 -8 5 24 0 0.235718 0.897949 -8 5 25 0 0.237915 0.906738 -8 5 26 0 0.240234 0.916016 -8 5 27 0 0.24292 0.92627 -8 5 28 0 0.245972 0.937988 -8 5 29 0 0.249146 0.950684 -8 5 30 0 0.252441 0.963867 -8 5 31 0 0.256104 0.977539 -8 6 0 0.150635 0.0793457 0 -8 6 1 0.150635 0.0793457 0 -8 6 2 0.150513 0.0794678 0 -8 6 3 0.150513 0.0795898 0 -8 6 4 0.151245 0.0799561 0.0209198 -8 6 5 0.152466 0.0802612 0.0498047 -8 6 6 0.153931 0.0804443 0.0748901 -8 6 7 0.145264 0.0767212 0.0993652 -8 6 8 0.120789 0.0723267 0.112061 -8 6 9 0.111938 0.0742188 0.143066 -8 6 10 0.0946655 0.0786743 0.182983 -8 6 11 0.0143204 0.086731 0.234863 -8 6 12 0 0.0976562 0.296387 -8 6 13 0 0.111328 0.365723 -8 6 14 0 0.127686 0.442383 -8 6 15 0 0.146118 0.523926 -8 6 16 0 0.166138 0.608398 -8 6 17 0 0.185791 0.689941 -8 6 18 0 0.204346 0.765137 -8 6 19 0 0.220703 0.831055 -8 6 20 0 0.229736 0.868164 -8 6 21 0 0.231079 0.875 -8 6 22 0 0.232666 0.882812 -8 6 23 0 0.234375 0.890137 -8 6 24 0 0.236206 0.897949 -8 6 25 0 0.238281 0.906738 -8 6 26 0 0.240601 0.916016 -8 6 27 0 0.243164 0.92627 -8 6 28 0 0.246216 0.938477 -8 6 29 0 0.24939 0.950684 -8 6 30 0 0.252686 0.963867 -8 6 31 0 0.256104 0.977539 -8 7 0 0.136353 0.0942383 0.0239868 -8 7 1 0.136353 0.0942383 0.0240326 -8 7 2 0.136353 0.0942993 0.0240936 -8 7 3 0.136353 0.0943604 0.024231 -8 7 4 0.13623 0.0944824 0.0359802 -8 7 5 0.135986 0.0947266 0.0514832 -8 7 6 0.136353 0.0956421 0.0699463 -8 7 7 0.139404 0.0983887 0.0964966 -8 7 8 0.117554 0.088501 0.111633 -8 7 9 0.108398 0.0897217 0.142822 -8 7 10 0.0899048 0.0932007 0.182739 -8 7 11 0 0.100098 0.234619 -8 7 12 0 0.109436 0.296143 -8 7 13 0 0.121216 0.365723 -8 7 14 0 0.13562 0.442383 -8 7 15 0 0.152466 0.523926 -8 7 16 0 0.171021 0.608887 -8 7 17 0 0.189697 0.69043 -8 7 18 0 0.207397 0.765137 -8 7 19 0 0.223145 0.831055 -8 7 20 0 0.231812 0.868164 -8 7 21 0 0.232666 0.875488 -8 7 22 0 0.234009 0.882812 -8 7 23 0 0.235474 0.890625 -8 7 24 0 0.237183 0.897949 -8 7 25 0 0.239014 0.906738 -8 7 26 0 0.241211 0.916016 -8 7 27 0 0.243774 0.92627 -8 7 28 0 0.246704 0.938477 -8 7 29 0 0.249756 0.950684 -8 7 30 0 0.253174 0.963867 -8 7 31 0 0.256592 0.977539 -8 8 0 0.129395 0.118774 0.0372925 -8 8 1 0.129395 0.118835 0.0372925 -8 8 2 0.129395 0.118835 0.0372925 -8 8 3 0.129395 0.118896 0.0372925 -8 8 4 0.129272 0.118896 0.040741 -8 8 5 0.12793 0.118347 0.0541992 -8 8 6 0.125488 0.117371 0.0701904 -8 8 7 0.120544 0.115234 0.0893555 -8 8 8 0.110718 0.110718 0.110718 -8 8 9 0.100891 0.111511 0.142334 -8 8 10 0.0791626 0.114197 0.182373 -8 8 11 0 0.120178 0.234253 -8 8 12 0 0.12793 0.295898 -8 8 13 0 0.137451 0.365723 -8 8 14 0 0.149414 0.442383 -8 8 15 0 0.163696 0.523926 -8 8 16 0 0.180054 0.608887 -8 8 17 0 0.196899 0.69043 -8 8 18 0 0.213135 0.765137 -8 8 19 0 0.227783 0.831055 -8 8 20 0 0.235596 0.868652 -8 8 21 0 0.235718 0.875488 -8 8 22 0 0.23645 0.882812 -8 8 23 0 0.237549 0.890625 -8 8 24 0 0.238892 0.898438 -8 8 25 0 0.240601 0.906738 -8 8 26 0 0.242554 0.916016 -8 8 27 0 0.244873 0.926758 -8 8 28 0 0.247681 0.938477 -8 8 29 0 0.250732 0.950684 -8 8 30 0 0.253906 0.963867 -8 8 31 0 0.25708 0.977539 -8 9 0 0.109558 0.144287 0.0350037 -8 9 1 0.109558 0.144287 0.0350037 -8 9 2 0.109558 0.144287 0.0350037 -8 9 3 0.109619 0.144409 0.0350037 -8 9 4 0.109619 0.144409 0.0350342 -8 9 5 0.108765 0.144043 0.0462341 -8 9 6 0.106567 0.143066 0.0637817 -8 9 7 0.102356 0.141235 0.0839844 -8 9 8 0.09552 0.139893 0.108948 -8 9 9 0.0831909 0.140625 0.141479 -8 9 10 0.0466309 0.142822 0.181885 -8 9 11 0 0.148193 0.233765 -8 9 12 0 0.154663 0.295654 -8 9 13 0 0.162231 0.365479 -8 9 14 0 0.171387 0.442139 -8 9 15 0 0.182495 0.523926 -8 9 16 0 0.195679 0.608887 -8 9 17 0 0.209717 0.69043 -8 9 18 0 0.223511 0.765625 -8 9 19 0 0.236328 0.831543 -8 9 20 0 0.242554 0.869141 -8 9 21 0 0.241333 0.875977 -8 9 22 0 0.241089 0.883301 -8 9 23 0 0.241455 0.891113 -8 9 24 0 0.24231 0.898438 -8 9 25 0 0.24353 0.907227 -8 9 26 0 0.245117 0.916504 -8 9 27 0 0.24707 0.926758 -8 9 28 0 0.249512 0.938477 -8 9 29 0 0.252197 0.951172 -8 9 30 0 0.255127 0.964355 -8 9 31 0 0.258301 0.977539 -8 10 0 0.0706787 0.17749 0.03302 -8 10 1 0.0706787 0.17749 0.03302 -8 10 2 0.0707397 0.177612 0.0330505 -8 10 3 0.0707397 0.177612 0.0330505 -8 10 4 0.0708618 0.177612 0.0330505 -8 10 5 0.0709839 0.177734 0.0331116 -8 10 6 0.0684204 0.177368 0.0555725 -8 10 7 0.0627441 0.17688 0.0790405 -8 10 8 0.0489502 0.17688 0.106445 -8 10 9 0 0.177612 0.140137 -8 10 10 0 0.179688 0.181396 -8 10 11 0 0.184448 0.233154 -8 10 12 0 0.190063 0.294922 -8 10 13 0 0.195923 0.36499 -8 10 14 0 0.202515 0.442139 -8 10 15 0 0.210327 0.523926 -8 10 16 0 0.219849 0.608887 -8 10 17 0 0.230103 0.69043 -8 10 18 0 0.240723 0.765625 -8 10 19 0 0.250732 0.831543 -8 10 20 0 0.254639 0.870117 -8 10 21 0 0.251221 0.876465 -8 10 22 0 0.249146 0.883789 -8 10 23 0 0.248291 0.891602 -8 10 24 0 0.248169 0.898926 -8 10 25 0 0.248657 0.907227 -8 10 26 0 0.249512 0.916504 -8 10 27 0 0.250977 0.927246 -8 10 28 0 0.252686 0.938965 -8 10 29 0 0.255127 0.951172 -8 10 30 0 0.257568 0.964355 -8 10 31 0 0.260498 0.978027 -8 11 0 0 0.224976 0.0315247 -8 11 1 0 0.224976 0.0315247 -8 11 2 0 0.224976 0.0315552 -8 11 3 0 0.224976 0.0315552 -8 11 4 0 0.225098 0.0315857 -8 11 5 0 0.225098 0.0316162 -8 11 6 0 0.22522 0.0383911 -8 11 7 0 0.224976 0.0717773 -8 11 8 0 0.224854 0.103088 -8 11 9 0 0.22522 0.138916 -8 11 10 0 0.226807 0.181274 -8 11 11 0 0.230103 0.232544 -8 11 12 0 0.234619 0.293945 -8 11 13 0 0.239258 0.364258 -8 11 14 0 0.243774 0.44165 -8 11 15 0 0.248535 0.523926 -8 11 16 0 0.25415 0.609375 -8 11 17 0 0.260498 0.690918 -8 11 18 0 0.266846 0.766113 -8 11 19 0 0.273193 0.832031 -8 11 20 0 0.273926 0.871582 -8 11 21 0 0.26709 0.87793 -8 11 22 0 0.262451 0.885254 -8 11 23 0 0.259766 0.892578 -8 11 24 0 0.258057 0.899902 -8 11 25 0 0.257324 0.908203 -8 11 26 0 0.25708 0.91748 -8 11 27 0 0.257324 0.927734 -8 11 28 0 0.258545 0.939453 -8 11 29 0 0.26001 0.95166 -8 11 30 0 0.261963 0.964844 -8 11 31 0 0.26416 0.978027 -8 12 0 0 0.28418 0.0284271 -8 12 1 0 0.28418 0.0284424 -8 12 2 0 0.28418 0.0284424 -8 12 3 0 0.28418 0.0284576 -8 12 4 0 0.28418 0.0284729 -8 12 5 0 0.28418 0.0285187 -8 12 6 0 0.284424 0.0286102 -8 12 7 0 0.284424 0.052887 -8 12 8 0 0.284424 0.0953369 -8 12 9 0 0.284424 0.13562 -8 12 10 0 0.284912 0.180054 -8 12 11 0 0.286621 0.231689 -8 12 12 0 0.289551 0.292725 -8 12 13 0 0.292725 0.363037 -8 12 14 0 0.295654 0.440918 -8 12 15 0 0.297852 0.523926 -8 12 16 0 0.300049 0.609375 -8 12 17 0 0.302002 0.691406 -8 12 18 0 0.303955 0.766602 -8 12 19 0 0.306152 0.833008 -8 12 20 0 0.302979 0.874023 -8 12 21 0 0.29126 0.879883 -8 12 22 0 0.283203 0.887207 -8 12 23 0 0.277832 0.894043 -8 12 24 0 0.273926 0.901367 -8 12 25 0 0.270996 0.909668 -8 12 26 0 0.269043 0.918457 -8 12 27 0 0.268066 0.928711 -8 12 28 0 0.267578 0.94043 -8 12 29 0 0.268066 0.952637 -8 12 30 0 0.268799 0.965332 -8 12 31 0 0.270264 0.978516 -8 13 0 0 0.351807 0.0202179 -8 13 1 0 0.351807 0.0202179 -8 13 2 0 0.351807 0.0202332 -8 13 3 0 0.351807 0.0202637 -8 13 4 0 0.351807 0.0202942 -8 13 5 0 0.351807 0.0203705 -8 13 6 0 0.351807 0.0205078 -8 13 7 0 0.352051 0.0207825 -8 13 8 0 0.352051 0.0756226 -8 13 9 0 0.352295 0.126343 -8 13 10 0 0.352539 0.175171 -8 13 11 0 0.353271 0.228882 -8 13 12 0 0.354736 0.290527 -8 13 13 0 0.356689 0.36084 -8 13 14 0 0.358154 0.439209 -8 13 15 0 0.358398 0.522949 -8 13 16 0 0.357666 0.609375 -8 13 17 0 0.355469 0.691895 -8 13 18 0 0.353027 0.767578 -8 13 19 0 0.350342 0.833984 -8 13 20 0 0.343262 0.877441 -8 13 21 0 0.325928 0.883789 -8 13 22 0 0.313232 0.890137 -8 13 23 0 0.304199 0.896973 -8 13 24 0 0.297363 0.903809 -8 13 25 0 0.291748 0.911621 -8 13 26 0 0.287354 0.920898 -8 13 27 0 0.28418 0.930664 -8 13 28 0 0.281982 0.941895 -8 13 29 0 0.280518 0.954102 -8 13 30 0 0.279785 0.966797 -8 13 31 0 0.279785 0.97998 -8 14 0 0 0.427002 0 -8 14 1 0 0.427002 0 -8 14 2 0 0.427002 0 -8 14 3 0 0.427002 0 -8 14 4 0 0.427002 0 -8 14 5 0 0.427002 0 -8 14 6 0 0.427002 0 -8 14 7 0 0.427246 0 -8 14 8 0 0.42749 0 -8 14 9 0 0.427734 0.106323 -8 14 10 0 0.427979 0.164307 -8 14 11 0 0.428711 0.222046 -8 14 12 0 0.429443 0.285645 -8 14 13 0 0.43042 0.356934 -8 14 14 0 0.430664 0.436035 -8 14 15 0 0.429443 0.520508 -8 14 16 0 0.426514 0.608398 -8 14 17 0 0.420898 0.691895 -8 14 18 0 0.414062 0.768555 -8 14 19 0 0.406982 0.835449 -8 14 20 0 0.39624 0.882812 -8 14 21 0 0.372314 0.88916 -8 14 22 0 0.354004 0.89502 -8 14 23 0 0.340576 0.901367 -8 14 24 0 0.330078 0.908203 -8 14 25 0 0.321289 0.915527 -8 14 26 0 0.313721 0.923828 -8 14 27 0 0.307373 0.933594 -8 14 28 0 0.302734 0.944336 -8 14 29 0 0.298828 0.956055 -8 14 30 0 0.296143 0.96875 -8 14 31 0 0.293945 0.981445 -8 15 0 0 0.507812 0 -8 15 1 0 0.507812 0 -8 15 2 0 0.507812 0 -8 15 3 0 0.507812 0 -8 15 4 0 0.507812 0 -8 15 5 0 0.507812 0 -8 15 6 0 0.507812 0 -8 15 7 0 0.507812 0 -8 15 8 0 0.508301 0 -8 15 9 0 0.508301 0.0488586 -8 15 10 0 0.508789 0.143555 -8 15 11 0 0.509766 0.208984 -8 15 12 0 0.510742 0.276123 -8 15 13 0 0.511719 0.349365 -8 15 14 0 0.511719 0.429932 -8 15 15 0 0.509766 0.516113 -8 15 16 0 0.505371 0.605469 -8 15 17 0 0.49707 0.690918 -8 15 18 0 0.486572 0.768555 -8 15 19 0 0.475098 0.836426 -8 15 20 0 0.46167 0.889648 -8 15 21 0 0.430908 0.896484 -8 15 22 0 0.406494 0.902832 -8 15 23 0 0.387695 0.908691 -8 15 24 0 0.373047 0.914551 -8 15 25 0 0.360107 0.921875 -8 15 26 0 0.348877 0.929199 -8 15 27 0 0.339111 0.938477 -8 15 28 0 0.331055 0.94873 -8 15 29 0 0.324463 0.959961 -8 15 30 0 0.318848 0.97168 -8 15 31 0 0.314209 0.983887 -8 16 0 0 0.592773 0 -8 16 1 0 0.592773 0 -8 16 2 0 0.592773 0 -8 16 3 0 0.592773 0 -8 16 4 0 0.592773 0 -8 16 5 0 0.592773 0 -8 16 6 0 0.592773 0 -8 16 7 0 0.592773 0 -8 16 8 0 0.593262 0 -8 16 9 0 0.593262 0 -8 16 10 0 0.59375 0.101929 -8 16 11 0 0.594727 0.187256 -8 16 12 0 0.596191 0.260742 -8 16 13 0 0.597168 0.336914 -8 16 14 0 0.597656 0.419434 -8 16 15 0 0.59668 0.507324 -8 16 16 0 0.591309 0.599121 -8 16 17 0 0.582031 0.687012 -8 16 18 0 0.568848 0.76709 -8 16 19 0 0.553711 0.836426 -8 16 20 0 0.537598 0.893555 -8 16 21 0 0.501953 0.90625 -8 16 22 0 0.471436 0.913574 -8 16 23 0 0.447021 0.919434 -8 16 24 0 0.427246 0.924805 -8 16 25 0 0.409912 0.931152 -8 16 26 0 0.394043 0.937988 -8 16 27 0 0.380127 0.945801 -8 16 28 0 0.368164 0.955078 -8 16 29 0 0.35791 0.965332 -8 16 30 0 0.348877 0.976562 -8 16 31 0 0.341309 0.988281 -8 17 0 0 0.676758 0 -8 17 1 0 0.676758 0 -8 17 2 0 0.676758 0 -8 17 3 0 0.676758 0 -8 17 4 0 0.676758 0 -8 17 5 0 0.676758 0 -8 17 6 0 0.676758 0 -8 17 7 0 0.676758 0 -8 17 8 0 0.676758 0 -8 17 9 0 0.676758 0 -8 17 10 0 0.677246 0 -8 17 11 0 0.678223 0.1521 -8 17 12 0 0.679688 0.238159 -8 17 13 0 0.681641 0.318848 -8 17 14 0 0.683594 0.403809 -8 17 15 0 0.683105 0.493652 -8 17 16 0 0.679199 0.587402 -8 17 17 0 0.669922 0.678711 -8 17 18 0 0.65625 0.761719 -8 17 19 0 0.638672 0.833984 -8 17 20 0 0.619141 0.893555 -8 17 21 0 0.58252 0.916504 -8 17 22 0 0.546875 0.927246 -8 17 23 0 0.516602 0.934082 -8 17 24 0 0.491943 0.939453 -8 17 25 0 0.469238 0.944824 -8 17 26 0 0.448486 0.950195 -8 17 27 0 0.429932 0.957031 -8 17 28 0 0.413574 0.964844 -8 17 29 0 0.398926 0.974121 -8 17 30 0 0.385986 0.983887 -8 17 31 0 0.374756 0.994141 -8 18 0 0 0.754883 0 -8 18 1 0 0.754883 0 -8 18 2 0 0.754883 0 -8 18 3 0 0.754883 0 -8 18 4 0 0.754883 0 -8 18 5 0 0.754883 0 -8 18 6 0 0.754883 0 -8 18 7 0 0.754883 0 -8 18 8 0 0.754883 0 -8 18 9 0 0.754883 0 -8 18 10 0 0.755371 0 -8 18 11 0 0.755859 0.0785522 -8 18 12 0 0.757812 0.206665 -8 18 13 0 0.760254 0.295166 -8 18 14 0 0.762695 0.382812 -8 18 15 0 0.76416 0.474609 -8 18 16 0 0.762207 0.570312 -8 18 17 0 0.754883 0.664551 -8 18 18 0 0.742188 0.751465 -8 18 19 0 0.724121 0.827637 -8 18 20 0 0.703125 0.889648 -8 18 21 0 0.667969 0.924316 -8 18 22 0 0.629395 0.941895 -8 18 23 0 0.594727 0.951172 -8 18 24 0 0.564941 0.95752 -8 18 25 0 0.537109 0.962402 -8 18 26 0 0.51123 0.967285 -8 18 27 0 0.487061 0.972168 -8 18 28 0 0.465576 0.978516 -8 18 29 0 0.446289 0.98584 -8 18 30 0 0.429199 0.993652 -8 18 31 0 0.413574 1 -8 19 0 0 0.824707 0 -8 19 1 0 0.824707 0 -8 19 2 0 0.824707 0 -8 19 3 0 0.824707 0 -8 19 4 0 0.824707 0 -8 19 5 0 0.824707 0 -8 19 6 0 0.824707 0 -8 19 7 0 0.824707 0 -8 19 8 0 0.824707 0 -8 19 9 0 0.825195 0 -8 19 10 0 0.825195 0 -8 19 11 0 0.825195 0 -8 19 12 0 0.827148 0.162598 -8 19 13 0 0.82959 0.266113 -8 19 14 0 0.833008 0.358154 -8 19 15 0 0.835938 0.45166 -8 19 16 0 0.836426 0.548828 -8 19 17 0 0.832031 0.64502 -8 19 18 0 0.821777 0.73584 -8 19 19 0 0.805176 0.81543 -8 19 20 0 0.783691 0.881348 -8 19 21 0 0.752441 0.927246 -8 19 22 0 0.714355 0.954102 -8 19 23 0 0.677246 0.96875 -8 19 24 0 0.643555 0.977051 -8 19 25 0 0.61084 0.982422 -8 19 26 0 0.579102 0.986816 -8 19 27 0 0.549805 0.990723 -8 19 28 0 0.522949 0.995117 -8 19 29 0 0.498779 1 -8 19 30 0 0.476562 1 -8 19 31 0 0.456787 1 -8 20 0 0 0.885254 0 -8 20 1 0 0.885254 0 -8 20 2 0 0.885254 0 -8 20 3 0 0.885254 0 -8 20 4 0 0.885254 0 -8 20 5 0 0.885254 0 -8 20 6 0 0.885254 0 -8 20 7 0 0.885254 0 -8 20 8 0 0.885254 0 -8 20 9 0 0.885742 0 -8 20 10 0 0.885742 0 -8 20 11 0 0.885742 0 -8 20 12 0 0.886719 0.0799561 -8 20 13 0 0.889648 0.232178 -8 20 14 0 0.893066 0.331055 -8 20 15 0 0.896973 0.42627 -8 20 16 0 0.899902 0.524414 -8 20 17 0 0.898438 0.62207 -8 20 18 0 0.891113 0.715332 -8 20 19 0 0.876953 0.79834 -8 20 20 0 0.856934 0.867676 -8 20 21 0 0.830078 0.922852 -8 20 22 0 0.795898 0.959961 -8 20 23 0 0.758789 0.981934 -8 20 24 0 0.722656 0.994141 -8 20 25 0 0.686035 1 -8 20 26 0 0.649902 1 -8 20 27 0 0.615723 1 -8 20 28 0 0.583496 1 -8 20 29 0 0.554199 1 -8 20 30 0 0.526855 1 -8 20 31 0 0.502441 1 -8 21 0 0 0.937012 0 -8 21 1 0 0.937012 0 -8 21 2 0 0.937012 0 -8 21 3 0 0.937012 0 -8 21 4 0 0.937012 0 -8 21 5 0 0.937012 0 -8 21 6 0 0.937012 0 -8 21 7 0 0.937012 0 -8 21 8 0 0.937012 0 -8 21 9 0 0.937012 0 -8 21 10 0 0.937012 0 -8 21 11 0 0.937012 0 -8 21 12 0 0.9375 0 -8 21 13 0 0.939941 0.189575 -8 21 14 0 0.943848 0.300537 -8 21 15 0 0.94873 0.398926 -8 21 16 0 0.953125 0.497559 -8 21 17 0 0.95459 0.596191 -8 21 18 0 0.950195 0.69043 -8 21 19 0 0.939453 0.775879 -8 21 20 0 0.922363 0.849609 -8 21 21 0 0.899414 0.910645 -8 21 22 0 0.870117 0.95752 -8 21 23 0 0.835449 0.987305 -8 21 24 0 0.799805 1 -8 21 25 0 0.76123 1 -8 21 26 0 0.722168 1 -8 21 27 0 0.683594 1 -8 21 28 0 0.646484 1 -8 21 29 0 0.611816 1 -8 21 30 0 0.580078 1 -8 21 31 0 0.550781 1 -8 22 0 0 0.979492 0 -8 22 1 0 0.979492 0 -8 22 2 0 0.979492 0 -8 22 3 0 0.979492 0 -8 22 4 0 0.979492 0 -8 22 5 0 0.979492 0 -8 22 6 0 0.979492 0 -8 22 7 0 0.979492 0 -8 22 8 0 0.979492 0 -8 22 9 0 0.979492 0 -8 22 10 0 0.97998 0 -8 22 11 0 0.97998 0 -8 22 12 0 0.97998 0 -8 22 13 0 0.981445 0.128662 -8 22 14 0 0.98584 0.267334 -8 22 15 0 0.991211 0.370117 -8 22 16 0 0.996582 0.469482 -8 22 17 0 1 0.567871 -8 22 18 0 0.999023 0.663086 -8 22 19 0 0.991699 0.750488 -8 22 20 0 0.978027 0.82666 -8 22 21 0 0.958008 0.891602 -8 22 22 0 0.933105 0.944824 -8 22 23 0 0.90332 0.983398 -8 22 24 0 0.870117 1 -8 22 25 0 0.83252 1 -8 22 26 0 0.791992 1 -8 22 27 0 0.750488 1 -8 22 28 0 0.709961 1 -8 22 29 0 0.670898 1 -8 22 30 0 0.634277 1 -8 22 31 0 0.600586 1 -8 23 0 0 1 0 -8 23 1 0 1 0 -8 23 2 0 1 0 -8 23 3 0 1 0 -8 23 4 0 1 0 -8 23 5 0 1 0 -8 23 6 0 1 0 -8 23 7 0 1 0 -8 23 8 0 1 0 -8 23 9 0 1 0 -8 23 10 0 1 0 -8 23 11 0 1 0 -8 23 12 0 1 0 -8 23 13 0 1 0 -8 23 14 0 1 0.231812 -8 23 15 0 1 0.341309 -8 23 16 0 1 0.44165 -8 23 17 0 1 0.540039 -8 23 18 0 1 0.634766 -8 23 19 0 1 0.723145 -8 23 20 0 1 0.80127 -8 23 21 0 1 0.869629 -8 23 22 0 0.984375 0.92627 -8 23 23 0 0.958984 0.971191 -8 23 24 0 0.930176 1 -8 23 25 0 0.89502 1 -8 23 26 0 0.855469 1 -8 23 27 0 0.812988 1 -8 23 28 0 0.769531 1 -8 23 29 0 0.727539 1 -8 23 30 0 0.687012 1 -8 23 31 0 0.648926 1 -8 24 0 0 1 0 -8 24 1 0 1 0 -8 24 2 0 1 0 -8 24 3 0 1 0 -8 24 4 0 1 0 -8 24 5 0 1 0 -8 24 6 0 1 0 -8 24 7 0 1 0 -8 24 8 0 1 0 -8 24 9 0 1 0 -8 24 10 0 1 0 -8 24 11 0 1 0 -8 24 12 0 1 0 -8 24 13 0 1 0 -8 24 14 0 1 0.191406 -8 24 15 0 1 0.312256 -8 24 16 0 1 0.414551 -8 24 17 0 1 0.512207 -8 24 18 0 1 0.606934 -8 24 19 0 1 0.695312 -8 24 20 0 1 0.774902 -8 24 21 0 1 0.845215 -8 24 22 0 1 0.904785 -8 24 23 0 1 0.953125 -8 24 24 0 0.979492 0.991699 -8 24 25 0 0.948242 1 -8 24 26 0 0.911133 1 -8 24 27 0 0.869141 1 -8 24 28 0 0.825195 1 -8 24 29 0 0.780762 1 -8 24 30 0 0.737305 1 -8 24 31 0 0.695801 1 -8 25 0 0 1 0 -8 25 1 0 1 0 -8 25 2 0 1 0 -8 25 3 0 1 0 -8 25 4 0 1 0 -8 25 5 0 1 0 -8 25 6 0 1 0 -8 25 7 0 1 0 -8 25 8 0 1 0 -8 25 9 0 1 0 -8 25 10 0 1 0 -8 25 11 0 1 0 -8 25 12 0 1 0 -8 25 13 0 1 0 -8 25 14 0 1 0.132812 -8 25 15 0 1 0.279541 -8 25 16 0 1 0.38501 -8 25 17 0 1 0.482666 -8 25 18 0 1 0.576172 -8 25 19 0 1 0.664551 -8 25 20 0 1 0.744141 -8 25 21 0 1 0.816406 -8 25 22 0 1 0.878906 -8 25 23 0 1 0.930176 -8 25 24 0 1 0.972656 -8 25 25 0 0.99707 1 -8 25 26 0 0.963867 1 -8 25 27 0 0.924316 1 -8 25 28 0 0.880859 1 -8 25 29 0 0.834961 1 -8 25 30 0 0.789551 1 -8 25 31 0 0.745117 1 -8 26 0 0 1 0 -8 26 1 0 1 0 -8 26 2 0 1 0 -8 26 3 0 1 0 -8 26 4 0 1 0 -8 26 5 0 1 0 -8 26 6 0 1 0 -8 26 7 0 1 0 -8 26 8 0 1 0 -8 26 9 0 1 0 -8 26 10 0 1 0 -8 26 11 0 1 0 -8 26 12 0 1 0 -8 26 13 0 1 0 -8 26 14 0 1 0 -8 26 15 0 1 0.241943 -8 26 16 0 1 0.353271 -8 26 17 0 1 0.451172 -8 26 18 0 1 0.543945 -8 26 19 0 1 0.630859 -8 26 20 0 1 0.710938 -8 26 21 0 1 0.78418 -8 26 22 0 1 0.848633 -8 26 23 0 1 0.902832 -8 26 24 0 1 0.948242 -8 26 25 0 1 0.989258 -8 26 26 0 1 1 -8 26 27 0 0.976074 1 -8 26 28 0 0.93457 1 -8 26 29 0 0.889648 1 -8 26 30 0 0.842773 1 -8 26 31 0 0.796387 1 -8 27 0 0 1 0 -8 27 1 0 1 0 -8 27 2 0 1 0 -8 27 3 0 1 0 -8 27 4 0 1 0 -8 27 5 0 1 0 -8 27 6 0 1 0 -8 27 7 0 1 0 -8 27 8 0 1 0 -8 27 9 0 1 0 -8 27 10 0 1 0 -8 27 11 0 1 0 -8 27 12 0 1 0 -8 27 13 0 1 0 -8 27 14 0 1 0 -8 27 15 0 1 0.195679 -8 27 16 0 1 0.318604 -8 27 17 0 1 0.417969 -8 27 18 0 1 0.509277 -8 27 19 0 1 0.595703 -8 27 20 0 1 0.674805 -8 27 21 0 1 0.748047 -8 27 22 0 1 0.813965 -8 27 23 0 1 0.870605 -8 27 24 0 1 0.918457 -8 27 25 0 1 0.962891 -8 27 26 0 1 1 -8 27 27 0 1 1 -8 27 28 0 0.98584 1 -8 27 29 0 0.941895 1 -8 27 30 0 0.895508 1 -8 27 31 0 0.848145 1 -8 28 0 0 1 0 -8 28 1 0 1 0 -8 28 2 0 1 0 -8 28 3 0 1 0 -8 28 4 0 1 0 -8 28 5 0 1 0 -8 28 6 0 1 0 -8 28 7 0 1 0 -8 28 8 0 1 0 -8 28 9 0 1 0 -8 28 10 0 1 0 -8 28 11 0 1 0 -8 28 12 0 1 0 -8 28 13 0 1 0 -8 28 14 0 1 0 -8 28 15 0 1 0.127075 -8 28 16 0 1 0.280518 -8 28 17 0 1 0.382812 -8 28 18 0 1 0.473877 -8 28 19 0 1 0.558594 -8 28 20 0 1 0.63623 -8 28 21 0 1 0.709473 -8 28 22 0 1 0.775879 -8 28 23 0 1 0.833496 -8 28 24 0 1 0.883789 -8 28 25 0 1 0.931152 -8 28 26 0 1 0.974609 -8 28 27 0 1 1 -8 28 28 0 1 1 -8 28 29 0 0.991699 1 -8 28 30 0 0.947266 1 -8 28 31 0 0.899902 1 -8 29 0 0 1 0 -8 29 1 0 1 0 -8 29 2 0 1 0 -8 29 3 0 1 0 -8 29 4 0 1 0 -8 29 5 0 1 0 -8 29 6 0 1 0 -8 29 7 0 1 0 -8 29 8 0 1 0 -8 29 9 0 1 0 -8 29 10 0 1 0 -8 29 11 0 1 0 -8 29 12 0 1 0 -8 29 13 0 1 0 -8 29 14 0 1 0 -8 29 15 0 1 0 -8 29 16 0 1 0.236694 -8 29 17 0 1 0.345215 -8 29 18 0 1 0.436523 -8 29 19 0 1 0.519531 -8 29 20 0 1 0.596191 -8 29 21 0 1 0.667969 -8 29 22 0 1 0.733887 -8 29 23 0 1 0.79248 -8 29 24 0 1 0.84375 -8 29 25 0 1 0.893555 -8 29 26 0 1 0.94043 -8 29 27 0 1 0.98291 -8 29 28 0 1 1 -8 29 29 0 1 1 -8 29 30 0 0.996582 1 -8 29 31 0 0.951172 1 -8 30 0 0 1 0 -8 30 1 0 1 0 -8 30 2 0 1 0 -8 30 3 0 1 0 -8 30 4 0 1 0 -8 30 5 0 1 0 -8 30 6 0 1 0 -8 30 7 0 1 0 -8 30 8 0 1 0 -8 30 9 0 1 0 -8 30 10 0 1 0 -8 30 11 0 1 0 -8 30 12 0 1 0 -8 30 13 0 1 0 -8 30 14 0 1 0 -8 30 15 0 1 0 -8 30 16 0 1 0.182007 -8 30 17 0 1 0.304932 -8 30 18 0 1 0.397461 -8 30 19 0 1 0.479248 -8 30 20 0 1 0.554199 -8 30 21 0 1 0.624512 -8 30 22 0 1 0.689453 -8 30 23 0 1 0.747559 -8 30 24 0 1 0.799805 -8 30 25 0 1 0.851074 -8 30 26 0 1 0.899902 -8 30 27 0 1 0.946289 -8 30 28 0 1 0.988281 -8 30 29 0 1 1 -8 30 30 0 1 1 -8 30 31 0 1 1 -8 31 0 0 1 0 -8 31 1 0 1 0 -8 31 2 0 1 0 -8 31 3 0 1 0 -8 31 4 0 1 0 -8 31 5 0 1 0 -8 31 6 0 1 0 -8 31 7 0 1 0 -8 31 8 0 1 0 -8 31 9 0 1 0 -8 31 10 0 1 0 -8 31 11 0 1 0 -8 31 12 0 1 0 -8 31 13 0 1 0 -8 31 14 0 1 0 -8 31 15 0 1 0 -8 31 16 0 1 0.0877075 -8 31 17 0 1 0.260742 -8 31 18 0 1 0.356934 -8 31 19 0 1 0.438232 -8 31 20 0 1 0.51123 -8 31 21 0 1 0.57959 -8 31 22 0 1 0.643066 -8 31 23 0 1 0.700684 -8 31 24 0 1 0.752441 -8 31 25 0 1 0.804199 -8 31 26 0 1 0.855469 -8 31 27 0 1 0.904785 -8 31 28 0 1 0.951172 -8 31 29 0 1 0.992676 -8 31 30 0 1 1 -8 31 31 0 1 1 -9 0 0 0.218384 0 0.0127182 -9 0 1 0.218384 0 0.0126495 -9 0 2 0.218384 0 0.0125351 -9 0 3 0.218384 0 0.0123291 -9 0 4 0.218506 0 0.0120316 -9 0 5 0.218628 0 0.0226898 -9 0 6 0.216187 0 0.0701904 -9 0 7 0.209717 0 0.1026 -9 0 8 0.180298 0.0296783 0.122925 -9 0 9 0.158569 0.0546265 0.143799 -9 0 10 0.150146 0.0612488 0.183594 -9 0 11 0.133301 0.0716553 0.234985 -9 0 12 0.0814209 0.0852051 0.296387 -9 0 13 0 0.10144 0.365967 -9 0 14 0 0.120056 0.442627 -9 0 15 0 0.140381 0.524414 -9 0 16 0 0.161743 0.608887 -9 0 17 0 0.182495 0.69043 -9 0 18 0 0.20166 0.765625 -9 0 19 0 0.218628 0.831055 -9 0 20 0 0.228271 0.868652 -9 0 21 0 0.229858 0.875488 -9 0 22 0 0.231689 0.883301 -9 0 23 0 0.233643 0.890625 -9 0 24 0 0.235474 0.898438 -9 0 25 0 0.237671 0.906738 -9 0 26 0 0.240112 0.916504 -9 0 27 0 0.242798 0.926758 -9 0 28 0 0.24585 0.938477 -9 0 29 0 0.249023 0.951172 -9 0 30 0 0.252441 0.964355 -9 0 31 0 0.256104 0.977539 -9 1 0 0.21814 0 0.0118942 -9 1 1 0.21814 0 0.0118256 -9 1 2 0.21814 0 0.0116959 -9 1 3 0.21814 0 0.0114594 -9 1 4 0.218262 0 0.0111313 -9 1 5 0.218506 0 0.0222626 -9 1 6 0.216064 0 0.0700684 -9 1 7 0.209595 0 0.102539 -9 1 8 0.180298 0.0317688 0.122925 -9 1 9 0.158569 0.0552979 0.143799 -9 1 10 0.150024 0.0617981 0.183594 -9 1 11 0.133301 0.0720825 0.234985 -9 1 12 0.0812988 0.0855713 0.296387 -9 1 13 0 0.101746 0.365967 -9 1 14 0 0.120239 0.442627 -9 1 15 0 0.140503 0.524414 -9 1 16 0 0.161865 0.608887 -9 1 17 0 0.182617 0.69043 -9 1 18 0 0.201782 0.765625 -9 1 19 0 0.21875 0.831543 -9 1 20 0 0.228271 0.868652 -9 1 21 0 0.229858 0.875488 -9 1 22 0 0.231689 0.883301 -9 1 23 0 0.233643 0.890625 -9 1 24 0 0.235596 0.898438 -9 1 25 0 0.237671 0.906738 -9 1 26 0 0.240112 0.916504 -9 1 27 0 0.242798 0.926758 -9 1 28 0 0.24585 0.938477 -9 1 29 0 0.249146 0.951172 -9 1 30 0 0.252441 0.964355 -9 1 31 0 0.256104 0.977539 -9 2 0 0.217773 0 0.0101624 -9 2 1 0.217773 0 0.0100708 -9 2 2 0.217773 0 0.00991058 -9 2 3 0.217773 0 0.00959778 -9 2 4 0.217773 0 0.00915527 -9 2 5 0.21814 0 0.0214691 -9 2 6 0.215942 0 0.0698853 -9 2 7 0.209473 0 0.102478 -9 2 8 0.18042 0.0350647 0.123047 -9 2 9 0.158447 0.056427 0.143677 -9 2 10 0.150024 0.0628052 0.183594 -9 2 11 0.133179 0.072876 0.234985 -9 2 12 0.0810547 0.0861816 0.296387 -9 2 13 0 0.102234 0.365967 -9 2 14 0 0.120605 0.442627 -9 2 15 0 0.140747 0.524414 -9 2 16 0 0.161987 0.608887 -9 2 17 0 0.182739 0.69043 -9 2 18 0 0.201904 0.765625 -9 2 19 0 0.218872 0.831543 -9 2 20 0 0.228394 0.868652 -9 2 21 0 0.22998 0.875488 -9 2 22 0 0.231812 0.883301 -9 2 23 0 0.233643 0.890625 -9 2 24 0 0.235596 0.898438 -9 2 25 0 0.237793 0.906738 -9 2 26 0 0.240112 0.916504 -9 2 27 0 0.242798 0.926758 -9 2 28 0 0.24585 0.938477 -9 2 29 0 0.249146 0.951172 -9 2 30 0 0.252441 0.964355 -9 2 31 0 0.256104 0.977539 -9 3 0 0.217041 0 0.00391388 -9 3 1 0.217041 0 0.00346756 -9 3 2 0.217041 0 0.00229454 -9 3 3 0.216919 0.0106506 0 -9 3 4 0.217041 0.0160522 0 -9 3 5 0.217529 0.0183105 0.0200043 -9 3 6 0.215454 0 0.069519 -9 3 7 0.209351 0 0.102295 -9 3 8 0.180664 0.0401001 0.12323 -9 3 9 0.158325 0.0584412 0.143677 -9 3 10 0.14978 0.0645142 0.183472 -9 3 11 0.132935 0.0743408 0.234985 -9 3 12 0.0805664 0.0873413 0.296387 -9 3 13 0 0.103088 0.365967 -9 3 14 0 0.121277 0.442627 -9 3 15 0 0.141235 0.524414 -9 3 16 0 0.162476 0.608887 -9 3 17 0 0.182983 0.69043 -9 3 18 0 0.202148 0.765625 -9 3 19 0 0.218994 0.831543 -9 3 20 0 0.228516 0.868652 -9 3 21 0 0.230103 0.875488 -9 3 22 0 0.231934 0.883301 -9 3 23 0 0.233765 0.890625 -9 3 24 0 0.235718 0.898438 -9 3 25 0 0.237793 0.906738 -9 3 26 0 0.240234 0.916504 -9 3 27 0 0.24292 0.926758 -9 3 28 0 0.24585 0.938477 -9 3 29 0 0.249146 0.951172 -9 3 30 0 0.252441 0.964355 -9 3 31 0 0.256104 0.977539 -9 4 0 0.215576 0.0397339 0 -9 4 1 0.215576 0.0399475 0 -9 4 2 0.215576 0.0403137 0 -9 4 3 0.215454 0.0409546 0 -9 4 4 0.215576 0.0418701 0 -9 4 5 0.216187 0.0423889 0.0170441 -9 4 6 0.214722 0.0385132 0.0688477 -9 4 7 0.208984 0.0328064 0.101929 -9 4 8 0.18103 0.0476379 0.123535 -9 4 9 0.158081 0.0619812 0.143677 -9 4 10 0.149536 0.067627 0.183472 -9 4 11 0.132568 0.0769653 0.234985 -9 4 12 0.0796509 0.0894775 0.296387 -9 4 13 0 0.104736 0.365967 -9 4 14 0 0.122559 0.442627 -9 4 15 0 0.142212 0.524414 -9 4 16 0 0.163208 0.608887 -9 4 17 0 0.183594 0.69043 -9 4 18 0 0.202515 0.765625 -9 4 19 0 0.21936 0.831543 -9 4 20 0 0.22876 0.868652 -9 4 21 0 0.230347 0.875488 -9 4 22 0 0.232056 0.883301 -9 4 23 0 0.233887 0.890625 -9 4 24 0 0.23584 0.898438 -9 4 25 0 0.237915 0.906738 -9 4 26 0 0.240234 0.916504 -9 4 27 0 0.24292 0.926758 -9 4 28 0 0.245972 0.938477 -9 4 29 0 0.249146 0.951172 -9 4 30 0 0.252686 0.964355 -9 4 31 0 0.256104 0.977539 -9 5 0 0.212524 0.0602417 0 -9 5 1 0.212524 0.0603333 0 -9 5 2 0.212524 0.0605164 0 -9 5 3 0.212402 0.0608521 0 -9 5 4 0.212524 0.0613403 0 -9 5 5 0.213379 0.061676 0.0101547 -9 5 6 0.212769 0.0595703 0.0675659 -9 5 7 0.207886 0.0559998 0.101196 -9 5 8 0.181763 0.0587463 0.124146 -9 5 9 0.157471 0.0680542 0.143677 -9 5 10 0.148926 0.072998 0.183472 -9 5 11 0.131836 0.081665 0.234985 -9 5 12 0.0778809 0.0933228 0.296387 -9 5 13 0 0.107849 0.365967 -9 5 14 0 0.124939 0.442627 -9 5 15 0 0.144043 0.524414 -9 5 16 0 0.164551 0.608887 -9 5 17 0 0.184692 0.69043 -9 5 18 0 0.203369 0.765625 -9 5 19 0 0.219971 0.831543 -9 5 20 0 0.22937 0.868652 -9 5 21 0 0.230713 0.875977 -9 5 22 0 0.232422 0.883301 -9 5 23 0 0.234131 0.890625 -9 5 24 0 0.236084 0.898438 -9 5 25 0 0.238159 0.906738 -9 5 26 0 0.240479 0.916504 -9 5 27 0 0.243042 0.926758 -9 5 28 0 0.246094 0.938477 -9 5 29 0 0.249268 0.951172 -9 5 30 0 0.252686 0.964355 -9 5 31 0 0.256104 0.977539 -9 6 0 0.206299 0.0808105 0 -9 6 1 0.206299 0.0808716 0 -9 6 2 0.206299 0.0809326 0 -9 6 3 0.206177 0.0811157 0 -9 6 4 0.206299 0.0814209 0 -9 6 5 0.207397 0.0818481 0 -9 6 6 0.208008 0.0809326 0.0653687 -9 6 7 0.204956 0.0784302 0.0994873 -9 6 8 0.18335 0.074646 0.125366 -9 6 9 0.156494 0.0776367 0.143433 -9 6 10 0.147705 0.0818481 0.18335 -9 6 11 0.130371 0.0895386 0.234863 -9 6 12 0.0742188 0.100098 0.296387 -9 6 13 0 0.113342 0.365967 -9 6 14 0 0.129272 0.442627 -9 6 15 0 0.147461 0.524414 -9 6 16 0 0.167114 0.608887 -9 6 17 0 0.186646 0.69043 -9 6 18 0 0.204956 0.765625 -9 6 19 0 0.221313 0.831543 -9 6 20 0 0.230347 0.868652 -9 6 21 0 0.231567 0.875977 -9 6 22 0 0.233032 0.883301 -9 6 23 0 0.234741 0.890625 -9 6 24 0 0.23645 0.898438 -9 6 25 0 0.238525 0.906738 -9 6 26 0 0.240845 0.916504 -9 6 27 0 0.243408 0.926758 -9 6 28 0 0.246338 0.938477 -9 6 29 0 0.249512 0.951172 -9 6 30 0 0.25293 0.964355 -9 6 31 0 0.256348 0.977539 -9 7 0 0.193726 0.101685 0 -9 7 1 0.193726 0.101685 0 -9 7 2 0.193726 0.101746 0 -9 7 3 0.193604 0.101807 0 -9 7 4 0.193604 0.10199 0 -9 7 5 0.194458 0.102478 0.0226593 -9 7 6 0.195923 0.102844 0.0628052 -9 7 7 0.197876 0.103027 0.0958862 -9 7 8 0.186035 0.0979614 0.127441 -9 7 9 0.154419 0.0922241 0.143311 -9 7 10 0.145508 0.0956421 0.183105 -9 7 11 0.127319 0.102356 0.234619 -9 7 12 0.0661621 0.11145 0.296143 -9 7 13 0 0.122986 0.365967 -9 7 14 0 0.137207 0.442627 -9 7 15 0 0.153687 0.524414 -9 7 16 0 0.171997 0.608887 -9 7 17 0 0.190552 0.69043 -9 7 18 0 0.208008 0.765625 -9 7 19 0 0.223755 0.831543 -9 7 20 0 0.2323 0.869141 -9 7 21 0 0.233154 0.875977 -9 7 22 0 0.234375 0.883301 -9 7 23 0 0.23584 0.891113 -9 7 24 0 0.237427 0.898438 -9 7 25 0 0.239258 0.907227 -9 7 26 0 0.241455 0.916504 -9 7 27 0 0.244019 0.926758 -9 7 28 0 0.246826 0.938477 -9 7 29 0 0.25 0.951172 -9 7 30 0 0.253174 0.964355 -9 7 31 0 0.256592 0.977539 -9 8 0 0.174438 0.120728 0.0310059 -9 8 1 0.174438 0.120728 0.0310364 -9 8 2 0.174438 0.120789 0.0310822 -9 8 3 0.174438 0.12085 0.0311584 -9 8 4 0.174438 0.120911 0.031311 -9 8 5 0.174194 0.121033 0.0450439 -9 8 6 0.173828 0.121277 0.0651245 -9 8 7 0.174194 0.122375 0.0891113 -9 8 8 0.178589 0.126343 0.123901 -9 8 9 0.150269 0.113342 0.142822 -9 8 10 0.140869 0.116028 0.182861 -9 8 11 0.121216 0.121826 0.234375 -9 8 12 0.0427551 0.129517 0.296143 -9 8 13 0 0.138916 0.365723 -9 8 14 0 0.150757 0.442627 -9 8 15 0 0.164917 0.524414 -9 8 16 0 0.18103 0.608887 -9 8 17 0 0.197632 0.69043 -9 8 18 0 0.213745 0.765625 -9 8 19 0 0.228394 0.831543 -9 8 20 0 0.236084 0.869141 -9 8 21 0 0.236084 0.875977 -9 8 22 0 0.236816 0.883789 -9 8 23 0 0.237915 0.891113 -9 8 24 0 0.239258 0.898926 -9 8 25 0 0.240845 0.907227 -9 8 26 0 0.242798 0.916504 -9 8 27 0 0.245117 0.926758 -9 8 28 0 0.247803 0.938477 -9 8 29 0 0.250732 0.951172 -9 8 30 0 0.253906 0.964355 -9 8 31 0 0.257324 0.977539 -9 9 0 0.166504 0.152832 0.0479736 -9 9 1 0.166504 0.152832 0.0479736 -9 9 2 0.166626 0.152954 0.0479736 -9 9 3 0.166626 0.152954 0.0480042 -9 9 4 0.166626 0.153076 0.0480042 -9 9 5 0.166382 0.153076 0.0514832 -9 9 6 0.164673 0.152222 0.0689697 -9 9 7 0.161133 0.150757 0.0899048 -9 9 8 0.154541 0.147705 0.114746 -9 9 9 0.141968 0.141968 0.141968 -9 9 10 0.131348 0.144287 0.182373 -9 9 11 0.107971 0.149414 0.233887 -9 9 12 0 0.155884 0.295654 -9 9 13 0 0.16333 0.365479 -9 9 14 0 0.172363 0.442383 -9 9 15 0 0.183472 0.524414 -9 9 16 0 0.196533 0.608887 -9 9 17 0 0.210327 0.690918 -9 9 18 0 0.224121 0.765625 -9 9 19 0 0.236816 0.831543 -9 9 20 0 0.243164 0.869629 -9 9 21 0 0.241821 0.876465 -9 9 22 0 0.241455 0.883789 -9 9 23 0 0.241821 0.891602 -9 9 24 0 0.242554 0.898926 -9 9 25 0 0.243774 0.907227 -9 9 26 0 0.245239 0.916504 -9 9 27 0 0.247192 0.927246 -9 9 28 0 0.249634 0.938965 -9 9 29 0 0.252441 0.951172 -9 9 30 0 0.255371 0.964355 -9 9 31 0 0.258545 0.978027 -9 10 0 0.143311 0.185303 0.0454407 -9 10 1 0.143311 0.185303 0.0454712 -9 10 2 0.143311 0.185303 0.0454712 -9 10 3 0.143311 0.185425 0.0454712 -9 10 4 0.143311 0.185425 0.0454712 -9 10 5 0.143311 0.185547 0.0455017 -9 10 6 0.142212 0.184937 0.0596008 -9 10 7 0.139038 0.18335 0.0825806 -9 10 8 0.133301 0.180542 0.108826 -9 10 9 0.124573 0.178711 0.140747 -9 10 10 0.110596 0.180786 0.181885 -9 10 11 0.0731812 0.185303 0.233276 -9 10 12 0 0.190796 0.294922 -9 10 13 0 0.196777 0.365234 -9 10 14 0 0.203369 0.442383 -9 10 15 0 0.211182 0.524414 -9 10 16 0 0.220581 0.609375 -9 10 17 0 0.230713 0.690918 -9 10 18 0 0.241211 0.766113 -9 10 19 0 0.251221 0.832031 -9 10 20 0 0.255127 0.870605 -9 10 21 0 0.251465 0.877441 -9 10 22 0 0.249512 0.884277 -9 10 23 0 0.248657 0.89209 -9 10 24 0 0.248535 0.899414 -9 10 25 0 0.248901 0.907715 -9 10 26 0 0.249756 0.916992 -9 10 27 0 0.250977 0.927246 -9 10 28 0 0.25293 0.938965 -9 10 29 0 0.255127 0.95166 -9 10 30 0 0.257812 0.964844 -9 10 31 0 0.260498 0.978027 -9 11 0 0.100159 0.227539 0.0434265 -9 11 1 0.100159 0.227539 0.0434265 -9 11 2 0.10022 0.227539 0.0434265 -9 11 3 0.10022 0.227539 0.0434265 -9 11 4 0.100281 0.227661 0.043457 -9 11 5 0.100342 0.227661 0.043457 -9 11 6 0.100586 0.227905 0.0435181 -9 11 7 0.09729 0.227173 0.0735474 -9 11 8 0.0905762 0.226318 0.104187 -9 11 9 0.0759277 0.226074 0.139404 -9 11 10 0 0.227539 0.181641 -9 11 11 0 0.230713 0.232788 -9 11 12 0 0.235107 0.294189 -9 11 13 0 0.239868 0.364502 -9 11 14 0 0.244385 0.441895 -9 11 15 0 0.249146 0.524414 -9 11 16 0 0.254883 0.609375 -9 11 17 0 0.260986 0.691406 -9 11 18 0 0.267334 0.766602 -9 11 19 0 0.273682 0.83252 -9 11 20 0 0.274414 0.87207 -9 11 21 0 0.267334 0.878418 -9 11 22 0 0.262939 0.885742 -9 11 23 0 0.26001 0.893066 -9 11 24 0 0.258301 0.900391 -9 11 25 0 0.257568 0.908691 -9 11 26 0 0.25708 0.917969 -9 11 27 0 0.257568 0.928223 -9 11 28 0 0.258545 0.939453 -9 11 29 0 0.26001 0.952148 -9 11 30 0 0.261963 0.964844 -9 11 31 0 0.26416 0.978516 -9 12 0 0 0.284912 0.041687 -9 12 1 0 0.284912 0.041687 -9 12 2 0 0.284912 0.0417175 -9 12 3 0 0.284912 0.0417175 -9 12 4 0 0.284912 0.0417175 -9 12 5 0 0.285156 0.041748 -9 12 6 0 0.285156 0.0418091 -9 12 7 0 0.285156 0.0551453 -9 12 8 0 0.284912 0.0962524 -9 12 9 0 0.284912 0.136108 -9 12 10 0 0.2854 0.18042 -9 12 11 0 0.287109 0.231934 -9 12 12 0 0.289795 0.292969 -9 12 13 0 0.293213 0.363037 -9 12 14 0 0.296143 0.441162 -9 12 15 0 0.29834 0.523926 -9 12 16 0 0.300537 0.609375 -9 12 17 0 0.30249 0.691895 -9 12 18 0 0.304443 0.76709 -9 12 19 0 0.306396 0.833008 -9 12 20 0 0.303467 0.874512 -9 12 21 0 0.291748 0.880859 -9 12 22 0 0.283691 0.887695 -9 12 23 0 0.278076 0.894531 -9 12 24 0 0.27417 0.901855 -9 12 25 0 0.27124 0.910156 -9 12 26 0 0.269287 0.918945 -9 12 27 0 0.268066 0.929199 -9 12 28 0 0.267822 0.94043 -9 12 29 0 0.268066 0.952637 -9 12 30 0 0.269043 0.96582 -9 12 31 0 0.270264 0.979004 -9 13 0 0 0.352051 0.0381165 -9 13 1 0 0.352051 0.0381165 -9 13 2 0 0.352051 0.0381165 -9 13 3 0 0.352051 0.038147 -9 13 4 0 0.352051 0.038147 -9 13 5 0 0.352295 0.0381775 -9 13 6 0 0.352295 0.0382385 -9 13 7 0 0.352295 0.0383301 -9 13 8 0 0.352539 0.0769043 -9 13 9 0 0.352539 0.126953 -9 13 10 0 0.352783 0.175537 -9 13 11 0 0.353516 0.229126 -9 13 12 0 0.35498 0.290771 -9 13 13 0 0.356934 0.361084 -9 13 14 0 0.358398 0.439453 -9 13 15 0 0.358643 0.522949 -9 13 16 0 0.35791 0.609375 -9 13 17 0 0.355957 0.692383 -9 13 18 0 0.353271 0.768066 -9 13 19 0 0.35083 0.834473 -9 13 20 0 0.34375 0.878418 -9 13 21 0 0.326416 0.884277 -9 13 22 0 0.313477 0.890625 -9 13 23 0 0.304443 0.897461 -9 13 24 0 0.297607 0.904297 -9 13 25 0 0.291992 0.912109 -9 13 26 0 0.287598 0.920898 -9 13 27 0 0.284424 0.930664 -9 13 28 0 0.281982 0.942383 -9 13 29 0 0.280762 0.954102 -9 13 30 0 0.280029 0.966797 -9 13 31 0 0.279785 0.97998 -9 14 0 0 0.427246 0.0302582 -9 14 1 0 0.427246 0.0302582 -9 14 2 0 0.427246 0.0302582 -9 14 3 0 0.427246 0.0302734 -9 14 4 0 0.427246 0.0302887 -9 14 5 0 0.42749 0.0303345 -9 14 6 0 0.42749 0.0304108 -9 14 7 0 0.42749 0.0305481 -9 14 8 0 0.427734 0.030838 -9 14 9 0 0.427979 0.107056 -9 14 10 0 0.428467 0.164673 -9 14 11 0 0.428955 0.22229 -9 14 12 0 0.429688 0.285889 -9 14 13 0 0.430664 0.357178 -9 14 14 0 0.430908 0.436035 -9 14 15 0 0.429932 0.520996 -9 14 16 0 0.426758 0.608398 -9 14 17 0 0.421143 0.692383 -9 14 18 0 0.414307 0.768555 -9 14 19 0 0.407227 0.835449 -9 14 20 0 0.396729 0.883789 -9 14 21 0 0.372559 0.889648 -9 14 22 0 0.354492 0.895508 -9 14 23 0 0.34082 0.901855 -9 14 24 0 0.330322 0.908691 -9 14 25 0 0.321289 0.916016 -9 14 26 0 0.313965 0.924316 -9 14 27 0 0.307617 0.933594 -9 14 28 0 0.302734 0.944824 -9 14 29 0 0.299072 0.956543 -9 14 30 0 0.296143 0.96875 -9 14 31 0 0.294189 0.981445 -9 15 0 0 0.508301 0 -9 15 1 0 0.508301 0 -9 15 2 0 0.508301 0 -9 15 3 0 0.508301 0 -9 15 4 0 0.508301 0 -9 15 5 0 0.508301 0 -9 15 6 0 0.508301 0 -9 15 7 0 0.508301 0 -9 15 8 0 0.508301 0 -9 15 9 0 0.508789 0.0513 -9 15 10 0 0.509277 0.144043 -9 15 11 0 0.510254 0.209229 -9 15 12 0 0.510742 0.276367 -9 15 13 0 0.511719 0.349609 -9 15 14 0 0.511719 0.429932 -9 15 15 0 0.509766 0.516113 -9 15 16 0 0.505371 0.605469 -9 15 17 0 0.497314 0.690918 -9 15 18 0 0.486816 0.769043 -9 15 19 0 0.475342 0.836914 -9 15 20 0 0.462158 0.890137 -9 15 21 0 0.431152 0.896973 -9 15 22 0 0.406738 0.90332 -9 15 23 0 0.387939 0.90918 -9 15 24 0 0.373291 0.915039 -9 15 25 0 0.360352 0.921875 -9 15 26 0 0.349121 0.929688 -9 15 27 0 0.339355 0.938477 -9 15 28 0 0.331299 0.94873 -9 15 29 0 0.324463 0.959961 -9 15 30 0 0.318848 0.97168 -9 15 31 0 0.314209 0.984375 -9 16 0 0 0.593262 0 -9 16 1 0 0.593262 0 -9 16 2 0 0.593262 0 -9 16 3 0 0.593262 0 -9 16 4 0 0.593262 0 -9 16 5 0 0.593262 0 -9 16 6 0 0.593262 0 -9 16 7 0 0.593262 0 -9 16 8 0 0.593262 0 -9 16 9 0 0.59375 0 -9 16 10 0 0.594238 0.102661 -9 16 11 0 0.595215 0.187622 -9 16 12 0 0.596191 0.260986 -9 16 13 0 0.597656 0.337158 -9 16 14 0 0.598145 0.419434 -9 16 15 0 0.59668 0.507812 -9 16 16 0 0.591797 0.599121 -9 16 17 0 0.582031 0.687012 -9 16 18 0 0.569336 0.76709 -9 16 19 0 0.554199 0.836914 -9 16 20 0 0.537598 0.894043 -9 16 21 0 0.502441 0.906738 -9 16 22 0 0.47168 0.914062 -9 16 23 0 0.447266 0.919922 -9 16 24 0 0.42749 0.925293 -9 16 25 0 0.409912 0.931152 -9 16 26 0 0.394287 0.937988 -9 16 27 0 0.380371 0.945801 -9 16 28 0 0.368408 0.955566 -9 16 29 0 0.35791 0.96582 -9 16 30 0 0.349121 0.976562 -9 16 31 0 0.341309 0.988281 -9 17 0 0 0.676758 0 -9 17 1 0 0.676758 0 -9 17 2 0 0.676758 0 -9 17 3 0 0.676758 0 -9 17 4 0 0.676758 0 -9 17 5 0 0.676758 0 -9 17 6 0 0.676758 0 -9 17 7 0 0.677246 0 -9 17 8 0 0.677246 0 -9 17 9 0 0.677246 0 -9 17 10 0 0.677246 0 -9 17 11 0 0.678711 0.152466 -9 17 12 0 0.680176 0.238403 -9 17 13 0 0.682129 0.319092 -9 17 14 0 0.683594 0.403809 -9 17 15 0 0.683105 0.493896 -9 17 16 0 0.679199 0.587402 -9 17 17 0 0.67041 0.678711 -9 17 18 0 0.65625 0.761719 -9 17 19 0 0.638672 0.834473 -9 17 20 0 0.619141 0.893555 -9 17 21 0 0.58252 0.916992 -9 17 22 0 0.546875 0.927246 -9 17 23 0 0.51709 0.934082 -9 17 24 0 0.492188 0.939453 -9 17 25 0 0.469482 0.944824 -9 17 26 0 0.44873 0.950684 -9 17 27 0 0.429932 0.957031 -9 17 28 0 0.413574 0.965332 -9 17 29 0 0.398926 0.974121 -9 17 30 0 0.38623 0.983887 -9 17 31 0 0.374756 0.994629 -9 18 0 0 0.754883 0 -9 18 1 0 0.754883 0 -9 18 2 0 0.754883 0 -9 18 3 0 0.754883 0 -9 18 4 0 0.754883 0 -9 18 5 0 0.754883 0 -9 18 6 0 0.754883 0 -9 18 7 0 0.754883 0 -9 18 8 0 0.755371 0 -9 18 9 0 0.755371 0 -9 18 10 0 0.755371 0 -9 18 11 0 0.755859 0.0795898 -9 18 12 0 0.757812 0.206909 -9 18 13 0 0.760254 0.295166 -9 18 14 0 0.762695 0.383057 -9 18 15 0 0.76416 0.474609 -9 18 16 0 0.762207 0.570312 -9 18 17 0 0.755371 0.664551 -9 18 18 0 0.742188 0.751465 -9 18 19 0 0.724609 0.827637 -9 18 20 0 0.703125 0.889648 -9 18 21 0 0.667969 0.924805 -9 18 22 0 0.629395 0.941895 -9 18 23 0 0.595215 0.95166 -9 18 24 0 0.56543 0.95752 -9 18 25 0 0.537109 0.962402 -9 18 26 0 0.51123 0.967285 -9 18 27 0 0.487305 0.972168 -9 18 28 0 0.46582 0.978516 -9 18 29 0 0.446533 0.98584 -9 18 30 0 0.429199 0.994141 -9 18 31 0 0.413818 1 -9 19 0 0 0.825195 0 -9 19 1 0 0.825195 0 -9 19 2 0 0.825195 0 -9 19 3 0 0.825195 0 -9 19 4 0 0.825195 0 -9 19 5 0 0.825195 0 -9 19 6 0 0.825195 0 -9 19 7 0 0.825195 0 -9 19 8 0 0.825195 0 -9 19 9 0 0.825195 0 -9 19 10 0 0.825195 0 -9 19 11 0 0.825684 0 -9 19 12 0 0.827148 0.162964 -9 19 13 0 0.830078 0.266357 -9 19 14 0 0.833008 0.358398 -9 19 15 0 0.835938 0.45166 -9 19 16 0 0.836426 0.548828 -9 19 17 0 0.83252 0.645508 -9 19 18 0 0.821777 0.73584 -9 19 19 0 0.805176 0.81543 -9 19 20 0 0.783691 0.881348 -9 19 21 0 0.752441 0.927246 -9 19 22 0 0.714355 0.954102 -9 19 23 0 0.677246 0.96875 -9 19 24 0 0.643555 0.977051 -9 19 25 0 0.61084 0.98291 -9 19 26 0 0.57959 0.986816 -9 19 27 0 0.549805 0.990723 -9 19 28 0 0.523438 0.995117 -9 19 29 0 0.498779 1 -9 19 30 0 0.476807 1 -9 19 31 0 0.456787 1 -9 20 0 0 0.885742 0 -9 20 1 0 0.885742 0 -9 20 2 0 0.885742 0 -9 20 3 0 0.885742 0 -9 20 4 0 0.885742 0 -9 20 5 0 0.885742 0 -9 20 6 0 0.885742 0 -9 20 7 0 0.885742 0 -9 20 8 0 0.885742 0 -9 20 9 0 0.885742 0 -9 20 10 0 0.885742 0 -9 20 11 0 0.88623 0 -9 20 12 0 0.886719 0.0807495 -9 20 13 0 0.889648 0.232422 -9 20 14 0 0.893555 0.331055 -9 20 15 0 0.897461 0.426514 -9 20 16 0 0.899902 0.524414 -9 20 17 0 0.898438 0.622559 -9 20 18 0 0.891113 0.715332 -9 20 19 0 0.876953 0.79834 -9 20 20 0 0.856934 0.868164 -9 20 21 0 0.830078 0.92334 -9 20 22 0 0.795898 0.959961 -9 20 23 0 0.758789 0.981934 -9 20 24 0 0.722656 0.994629 -9 20 25 0 0.686035 1 -9 20 26 0 0.650391 1 -9 20 27 0 0.615723 1 -9 20 28 0 0.583496 1 -9 20 29 0 0.554199 1 -9 20 30 0 0.526855 1 -9 20 31 0 0.502441 1 -9 21 0 0 0.937012 0 -9 21 1 0 0.937012 0 -9 21 2 0 0.937012 0 -9 21 3 0 0.937012 0 -9 21 4 0 0.937012 0 -9 21 5 0 0.937012 0 -9 21 6 0 0.937012 0 -9 21 7 0 0.937012 0 -9 21 8 0 0.937012 0 -9 21 9 0 0.937012 0 -9 21 10 0 0.9375 0 -9 21 11 0 0.9375 0 -9 21 12 0 0.9375 0 -9 21 13 0 0.939941 0.189819 -9 21 14 0 0.944336 0.300781 -9 21 15 0 0.949219 0.398926 -9 21 16 0 0.953125 0.497559 -9 21 17 0 0.95459 0.596191 -9 21 18 0 0.950684 0.69043 -9 21 19 0 0.939941 0.776367 -9 21 20 0 0.922363 0.849609 -9 21 21 0 0.899414 0.910645 -9 21 22 0 0.870117 0.95752 -9 21 23 0 0.835938 0.987793 -9 21 24 0 0.799805 1 -9 21 25 0 0.761719 1 -9 21 26 0 0.722168 1 -9 21 27 0 0.683594 1 -9 21 28 0 0.646484 1 -9 21 29 0 0.612305 1 -9 21 30 0 0.580078 1 -9 21 31 0 0.550781 1 -9 22 0 0 0.97998 0 -9 22 1 0 0.97998 0 -9 22 2 0 0.97998 0 -9 22 3 0 0.97998 0 -9 22 4 0 0.97998 0 -9 22 5 0 0.97998 0 -9 22 6 0 0.97998 0 -9 22 7 0 0.97998 0 -9 22 8 0 0.97998 0 -9 22 9 0 0.97998 0 -9 22 10 0 0.97998 0 -9 22 11 0 0.97998 0 -9 22 12 0 0.980469 0 -9 22 13 0 0.981445 0.129028 -9 22 14 0 0.98584 0.267578 -9 22 15 0 0.991211 0.370117 -9 22 16 0 0.996582 0.469482 -9 22 17 0 1 0.567871 -9 22 18 0 0.999023 0.663086 -9 22 19 0 0.992188 0.750488 -9 22 20 0 0.978027 0.82666 -9 22 21 0 0.958496 0.89209 -9 22 22 0 0.933105 0.944824 -9 22 23 0 0.903809 0.983887 -9 22 24 0 0.870605 1 -9 22 25 0 0.83252 1 -9 22 26 0 0.791992 1 -9 22 27 0 0.750488 1 -9 22 28 0 0.709961 1 -9 22 29 0 0.670898 1 -9 22 30 0 0.634277 1 -9 22 31 0 0.600586 1 -9 23 0 0 1 0 -9 23 1 0 1 0 -9 23 2 0 1 0 -9 23 3 0 1 0 -9 23 4 0 1 0 -9 23 5 0 1 0 -9 23 6 0 1 0 -9 23 7 0 1 0 -9 23 8 0 1 0 -9 23 9 0 1 0 -9 23 10 0 1 0 -9 23 11 0 1 0 -9 23 12 0 1 0 -9 23 13 0 1 0 -9 23 14 0 1 0.231934 -9 23 15 0 1 0.341309 -9 23 16 0 1 0.441895 -9 23 17 0 1 0.540039 -9 23 18 0 1 0.634766 -9 23 19 0 1 0.723145 -9 23 20 0 1 0.80127 -9 23 21 0 1 0.869629 -9 23 22 0 0.984375 0.92627 -9 23 23 0 0.958984 0.971191 -9 23 24 0 0.930176 1 -9 23 25 0 0.89502 1 -9 23 26 0 0.855469 1 -9 23 27 0 0.812988 1 -9 23 28 0 0.769531 1 -9 23 29 0 0.727539 1 -9 23 30 0 0.687012 1 -9 23 31 0 0.648926 1 -9 24 0 0 1 0 -9 24 1 0 1 0 -9 24 2 0 1 0 -9 24 3 0 1 0 -9 24 4 0 1 0 -9 24 5 0 1 0 -9 24 6 0 1 0 -9 24 7 0 1 0 -9 24 8 0 1 0 -9 24 9 0 1 0 -9 24 10 0 1 0 -9 24 11 0 1 0 -9 24 12 0 1 0 -9 24 13 0 1 0 -9 24 14 0 1 0.19165 -9 24 15 0 1 0.312256 -9 24 16 0 1 0.414551 -9 24 17 0 1 0.512207 -9 24 18 0 1 0.606934 -9 24 19 0 1 0.695312 -9 24 20 0 1 0.774902 -9 24 21 0 1 0.845215 -9 24 22 0 1 0.904785 -9 24 23 0 1 0.953125 -9 24 24 0 0.979492 0.991699 -9 24 25 0 0.948242 1 -9 24 26 0 0.911133 1 -9 24 27 0 0.869141 1 -9 24 28 0 0.825195 1 -9 24 29 0 0.780762 1 -9 24 30 0 0.737305 1 -9 24 31 0 0.695801 1 -9 25 0 0 1 0 -9 25 1 0 1 0 -9 25 2 0 1 0 -9 25 3 0 1 0 -9 25 4 0 1 0 -9 25 5 0 1 0 -9 25 6 0 1 0 -9 25 7 0 1 0 -9 25 8 0 1 0 -9 25 9 0 1 0 -9 25 10 0 1 0 -9 25 11 0 1 0 -9 25 12 0 1 0 -9 25 13 0 1 0 -9 25 14 0 1 0.133057 -9 25 15 0 1 0.279785 -9 25 16 0 1 0.38501 -9 25 17 0 1 0.482666 -9 25 18 0 1 0.576172 -9 25 19 0 1 0.664551 -9 25 20 0 1 0.744629 -9 25 21 0 1 0.816406 -9 25 22 0 1 0.878906 -9 25 23 0 1 0.930664 -9 25 24 0 1 0.972656 -9 25 25 0 0.99707 1 -9 25 26 0 0.963867 1 -9 25 27 0 0.924316 1 -9 25 28 0 0.880859 1 -9 25 29 0 0.834961 1 -9 25 30 0 0.789551 1 -9 25 31 0 0.745117 1 -9 26 0 0 1 0 -9 26 1 0 1 0 -9 26 2 0 1 0 -9 26 3 0 1 0 -9 26 4 0 1 0 -9 26 5 0 1 0 -9 26 6 0 1 0 -9 26 7 0 1 0 -9 26 8 0 1 0 -9 26 9 0 1 0 -9 26 10 0 1 0 -9 26 11 0 1 0 -9 26 12 0 1 0 -9 26 13 0 1 0 -9 26 14 0 1 0 -9 26 15 0 1 0.242065 -9 26 16 0 1 0.353271 -9 26 17 0 1 0.451172 -9 26 18 0 1 0.543945 -9 26 19 0 1 0.630859 -9 26 20 0 1 0.710938 -9 26 21 0 1 0.78418 -9 26 22 0 1 0.848633 -9 26 23 0 1 0.902832 -9 26 24 0 1 0.948242 -9 26 25 0 1 0.989258 -9 26 26 0 1 1 -9 26 27 0 0.976562 1 -9 26 28 0 0.93457 1 -9 26 29 0 0.889648 1 -9 26 30 0 0.842773 1 -9 26 31 0 0.796387 1 -9 27 0 0 1 0 -9 27 1 0 1 0 -9 27 2 0 1 0 -9 27 3 0 1 0 -9 27 4 0 1 0 -9 27 5 0 1 0 -9 27 6 0 1 0 -9 27 7 0 1 0 -9 27 8 0 1 0 -9 27 9 0 1 0 -9 27 10 0 1 0 -9 27 11 0 1 0 -9 27 12 0 1 0 -9 27 13 0 1 0 -9 27 14 0 1 0 -9 27 15 0 1 0.195801 -9 27 16 0 1 0.318848 -9 27 17 0 1 0.417969 -9 27 18 0 1 0.509766 -9 27 19 0 1 0.595703 -9 27 20 0 1 0.674805 -9 27 21 0 1 0.748047 -9 27 22 0 1 0.813965 -9 27 23 0 1 0.870605 -9 27 24 0 1 0.918457 -9 27 25 0 1 0.962891 -9 27 26 0 1 1 -9 27 27 0 1 1 -9 27 28 0 0.98584 1 -9 27 29 0 0.941895 1 -9 27 30 0 0.895508 1 -9 27 31 0 0.848145 1 -9 28 0 0 1 0 -9 28 1 0 1 0 -9 28 2 0 1 0 -9 28 3 0 1 0 -9 28 4 0 1 0 -9 28 5 0 1 0 -9 28 6 0 1 0 -9 28 7 0 1 0 -9 28 8 0 1 0 -9 28 9 0 1 0 -9 28 10 0 1 0 -9 28 11 0 1 0 -9 28 12 0 1 0 -9 28 13 0 1 0 -9 28 14 0 1 0 -9 28 15 0 1 0.127197 -9 28 16 0 1 0.280518 -9 28 17 0 1 0.382812 -9 28 18 0 1 0.473877 -9 28 19 0 1 0.558594 -9 28 20 0 1 0.63623 -9 28 21 0 1 0.709473 -9 28 22 0 1 0.775879 -9 28 23 0 1 0.833496 -9 28 24 0 1 0.883789 -9 28 25 0 1 0.931152 -9 28 26 0 1 0.974609 -9 28 27 0 1 1 -9 28 28 0 1 1 -9 28 29 0 0.991699 1 -9 28 30 0 0.947266 1 -9 28 31 0 0.899902 1 -9 29 0 0 1 0 -9 29 1 0 1 0 -9 29 2 0 1 0 -9 29 3 0 1 0 -9 29 4 0 1 0 -9 29 5 0 1 0 -9 29 6 0 1 0 -9 29 7 0 1 0 -9 29 8 0 1 0 -9 29 9 0 1 0 -9 29 10 0 1 0 -9 29 11 0 1 0 -9 29 12 0 1 0 -9 29 13 0 1 0 -9 29 14 0 1 0 -9 29 15 0 1 0 -9 29 16 0 1 0.236694 -9 29 17 0 1 0.345215 -9 29 18 0 1 0.436523 -9 29 19 0 1 0.519531 -9 29 20 0 1 0.596191 -9 29 21 0 1 0.667969 -9 29 22 0 1 0.733887 -9 29 23 0 1 0.79248 -9 29 24 0 1 0.84375 -9 29 25 0 1 0.893555 -9 29 26 0 1 0.94043 -9 29 27 0 1 0.98291 -9 29 28 0 1 1 -9 29 29 0 1 1 -9 29 30 0 0.996582 1 -9 29 31 0 0.95166 1 -9 30 0 0 1 0 -9 30 1 0 1 0 -9 30 2 0 1 0 -9 30 3 0 1 0 -9 30 4 0 1 0 -9 30 5 0 1 0 -9 30 6 0 1 0 -9 30 7 0 1 0 -9 30 8 0 1 0 -9 30 9 0 1 0 -9 30 10 0 1 0 -9 30 11 0 1 0 -9 30 12 0 1 0 -9 30 13 0 1 0 -9 30 14 0 1 0 -9 30 15 0 1 0 -9 30 16 0 1 0.182129 -9 30 17 0 1 0.304932 -9 30 18 0 1 0.397461 -9 30 19 0 1 0.479492 -9 30 20 0 1 0.554199 -9 30 21 0 1 0.624512 -9 30 22 0 1 0.689453 -9 30 23 0 1 0.748047 -9 30 24 0 1 0.799805 -9 30 25 0 1 0.851074 -9 30 26 0 1 0.899902 -9 30 27 0 1 0.946289 -9 30 28 0 1 0.988281 -9 30 29 0 1 1 -9 30 30 0 1 1 -9 30 31 0 1 1 -9 31 0 0 1 0 -9 31 1 0 1 0 -9 31 2 0 1 0 -9 31 3 0 1 0 -9 31 4 0 1 0 -9 31 5 0 1 0 -9 31 6 0 1 0 -9 31 7 0 1 0 -9 31 8 0 1 0 -9 31 9 0 1 0 -9 31 10 0 1 0 -9 31 11 0 1 0 -9 31 12 0 1 0 -9 31 13 0 1 0 -9 31 14 0 1 0 -9 31 15 0 1 0 -9 31 16 0 1 0.0878906 -9 31 17 0 1 0.260742 -9 31 18 0 1 0.356934 -9 31 19 0 1 0.438232 -9 31 20 0 1 0.51123 -9 31 21 0 1 0.57959 -9 31 22 0 1 0.643066 -9 31 23 0 1 0.700684 -9 31 24 0 1 0.752441 -9 31 25 0 1 0.804199 -9 31 26 0 1 0.855469 -9 31 27 0 1 0.904785 -9 31 28 0 1 0.951172 -9 31 29 0 1 0.992676 -9 31 30 0 1 1 -9 31 31 0 1 1 -10 0 0 0.283936 0 0.0173492 -10 0 1 0.283936 0 0.0173187 -10 0 2 0.283936 0 0.0172424 -10 0 3 0.283936 0 0.0171051 -10 0 4 0.283936 0 0.0168457 -10 0 5 0.283936 0 0.0164795 -10 0 6 0.28418 0 0.030838 -10 0 7 0.280518 0 0.0925903 -10 0 8 0.270752 0 0.134766 -10 0 9 0.229248 0.0401001 0.158325 -10 0 10 0.203857 0.069519 0.184814 -10 0 11 0.195679 0.0784302 0.235474 -10 0 12 0.175537 0.0905762 0.296631 -10 0 13 0.122986 0.105652 0.366211 -10 0 14 0 0.123291 0.442871 -10 0 15 0 0.142822 0.524414 -10 0 16 0 0.163696 0.609375 -10 0 17 0 0.184082 0.690918 -10 0 18 0 0.202881 0.766113 -10 0 19 0 0.219604 0.832031 -10 0 20 0 0.229248 0.870117 -10 0 21 0 0.230713 0.876953 -10 0 22 0 0.232422 0.884277 -10 0 23 0 0.234253 0.891602 -10 0 24 0 0.236084 0.899414 -10 0 25 0 0.238159 0.907715 -10 0 26 0 0.240479 0.916992 -10 0 27 0 0.243164 0.927246 -10 0 28 0 0.246094 0.938965 -10 0 29 0 0.24939 0.95166 -10 0 30 0 0.252686 0.964355 -10 0 31 0 0.256104 0.978027 -10 1 0 0.283936 0 0.0168457 -10 1 1 0.283936 0 0.0167999 -10 1 2 0.283691 0 0.0167236 -10 1 3 0.283691 0 0.016571 -10 1 4 0.283691 0 0.0163116 -10 1 5 0.283936 0 0.0159149 -10 1 6 0.28418 0 0.0305481 -10 1 7 0.280518 0 0.0925293 -10 1 8 0.270752 0 0.134766 -10 1 9 0.22937 0.0414124 0.158325 -10 1 10 0.203857 0.0700073 0.184814 -10 1 11 0.195679 0.0787964 0.235474 -10 1 12 0.175537 0.0908813 0.296631 -10 1 13 0.122925 0.105896 0.366211 -10 1 14 0 0.123474 0.442871 -10 1 15 0 0.142944 0.524414 -10 1 16 0 0.163818 0.609375 -10 1 17 0 0.184082 0.690918 -10 1 18 0 0.203003 0.766113 -10 1 19 0 0.219727 0.832031 -10 1 20 0 0.229248 0.870117 -10 1 21 0 0.230713 0.876953 -10 1 22 0 0.232422 0.884277 -10 1 23 0 0.234253 0.891602 -10 1 24 0 0.236084 0.899414 -10 1 25 0 0.238159 0.907715 -10 1 26 0 0.240479 0.916992 -10 1 27 0 0.243164 0.927246 -10 1 28 0 0.246216 0.938965 -10 1 29 0 0.24939 0.95166 -10 1 30 0 0.252686 0.964355 -10 1 31 0 0.256104 0.978027 -10 2 0 0.283447 0 0.0158539 -10 2 1 0.283447 0 0.0158081 -10 2 2 0.283447 0 0.0157318 -10 2 3 0.283447 0 0.0155716 -10 2 4 0.283447 0 0.015274 -10 2 5 0.283447 0 0.0148315 -10 2 6 0.283936 0 0.0300293 -10 2 7 0.280273 0 0.0924072 -10 2 8 0.270752 0 0.134766 -10 2 9 0.22937 0.0436401 0.158447 -10 2 10 0.203857 0.0708008 0.184814 -10 2 11 0.195557 0.0795288 0.235474 -10 2 12 0.175415 0.0914917 0.296631 -10 2 13 0.122803 0.106384 0.366211 -10 2 14 0 0.12384 0.442871 -10 2 15 0 0.143311 0.524414 -10 2 16 0 0.16394 0.609375 -10 2 17 0 0.184326 0.690918 -10 2 18 0 0.203125 0.766113 -10 2 19 0 0.219849 0.832031 -10 2 20 0 0.22937 0.870117 -10 2 21 0 0.230835 0.876953 -10 2 22 0 0.232544 0.884277 -10 2 23 0 0.234253 0.891602 -10 2 24 0 0.236084 0.899414 -10 2 25 0 0.238159 0.907715 -10 2 26 0 0.240601 0.916992 -10 2 27 0 0.243164 0.927246 -10 2 28 0 0.246216 0.938965 -10 2 29 0 0.24939 0.95166 -10 2 30 0 0.252686 0.964355 -10 2 31 0 0.256104 0.978027 -10 3 0 0.282959 0 0.0137711 -10 3 1 0.282959 0 0.0137177 -10 3 2 0.282959 0 0.0136108 -10 3 3 0.282959 0 0.0134125 -10 3 4 0.282959 0 0.013031 -10 3 5 0.282959 0 0.0124588 -10 3 6 0.283447 0 0.0290833 -10 3 7 0.280029 0 0.0921631 -10 3 8 0.270508 0 0.134644 -10 3 9 0.229492 0.0473022 0.158569 -10 3 10 0.203735 0.0722656 0.184814 -10 3 11 0.195435 0.0807495 0.235474 -10 3 12 0.175293 0.0925293 0.296631 -10 3 13 0.122559 0.107239 0.366211 -10 3 14 0 0.124512 0.442871 -10 3 15 0 0.143799 0.524414 -10 3 16 0 0.164429 0.609375 -10 3 17 0 0.18457 0.690918 -10 3 18 0 0.203369 0.766113 -10 3 19 0 0.219971 0.832031 -10 3 20 0 0.229492 0.870117 -10 3 21 0 0.230957 0.876953 -10 3 22 0 0.232544 0.884277 -10 3 23 0 0.234375 0.891602 -10 3 24 0 0.236206 0.899414 -10 3 25 0 0.238281 0.907715 -10 3 26 0 0.240601 0.916992 -10 3 27 0 0.243286 0.927246 -10 3 28 0 0.246216 0.938965 -10 3 29 0 0.24939 0.95166 -10 3 30 0 0.252686 0.964355 -10 3 31 0 0.256348 0.978027 -10 4 0 0.281982 0 0.00696945 -10 4 1 0.281982 0 0.00679779 -10 4 2 0.281982 0 0.00646591 -10 4 3 0.281982 0 0.0057869 -10 4 4 0.281982 0 0.00392532 -10 4 5 0.281982 0.0148926 0 -10 4 6 0.282471 0.0193176 0.0272675 -10 4 7 0.279541 0 0.0916748 -10 4 8 0.270508 0 0.134399 -10 4 9 0.229736 0.0532532 0.158691 -10 4 10 0.203491 0.0748901 0.184692 -10 4 11 0.195312 0.0830688 0.235474 -10 4 12 0.175049 0.0944824 0.296631 -10 4 13 0.12207 0.108765 0.366211 -10 4 14 0 0.125732 0.442871 -10 4 15 0 0.144653 0.524414 -10 4 16 0 0.165039 0.609375 -10 4 17 0 0.185181 0.690918 -10 4 18 0 0.203735 0.766113 -10 4 19 0 0.220337 0.832031 -10 4 20 0 0.229858 0.870117 -10 4 21 0 0.231201 0.876953 -10 4 22 0 0.232788 0.884277 -10 4 23 0 0.234497 0.891602 -10 4 24 0 0.236328 0.899414 -10 4 25 0 0.238403 0.907715 -10 4 26 0 0.240723 0.916992 -10 4 27 0 0.243286 0.927246 -10 4 28 0 0.246338 0.938965 -10 4 29 0 0.249512 0.95166 -10 4 30 0 0.25293 0.964355 -10 4 31 0 0.256348 0.978027 -10 5 0 0.280029 0.0509644 0 -10 5 1 0.280029 0.0511169 0 -10 5 2 0.280029 0.0513916 0 -10 5 3 0.280029 0.0518494 0 -10 5 4 0.279785 0.0527344 0 -10 5 5 0.280029 0.0539856 0 -10 5 6 0.280762 0.054657 0.0236053 -10 5 7 0.278564 0.0493469 0.0907593 -10 5 8 0.27002 0.0417786 0.134033 -10 5 9 0.230347 0.062561 0.15918 -10 5 10 0.203125 0.0795898 0.184692 -10 5 11 0.194824 0.0872803 0.235474 -10 5 12 0.174561 0.0980225 0.296631 -10 5 13 0.121155 0.111694 0.366211 -10 5 14 0 0.128052 0.442871 -10 5 15 0 0.146484 0.524414 -10 5 16 0 0.166504 0.609375 -10 5 17 0 0.186157 0.690918 -10 5 18 0 0.20459 0.766113 -10 5 19 0 0.221069 0.832031 -10 5 20 0 0.230347 0.870117 -10 5 21 0 0.231567 0.876953 -10 5 22 0 0.233154 0.884277 -10 5 23 0 0.234741 0.891602 -10 5 24 0 0.236572 0.899414 -10 5 25 0 0.238647 0.907715 -10 5 26 0 0.240845 0.916992 -10 5 27 0 0.243408 0.927246 -10 5 28 0 0.24646 0.938965 -10 5 29 0 0.249634 0.95166 -10 5 30 0 0.25293 0.964355 -10 5 31 0 0.256348 0.978027 -10 6 0 0.275879 0.0782471 0 -10 6 1 0.275879 0.0783691 0 -10 6 2 0.275879 0.0784912 0 -10 6 3 0.275879 0.0786743 0 -10 6 4 0.275635 0.0791016 0 -10 6 5 0.275879 0.0797729 0 -10 6 6 0.2771 0.0802612 0.0158539 -10 6 7 0.275879 0.0773315 0.0890503 -10 6 8 0.268555 0.0724487 0.133057 -10 6 9 0.231323 0.076416 0.160156 -10 6 10 0.202393 0.0875244 0.18457 -10 6 11 0.194092 0.0944824 0.235352 -10 6 12 0.173584 0.104309 0.296387 -10 6 13 0.119385 0.116882 0.366211 -10 6 14 0 0.132202 0.442871 -10 6 15 0 0.14978 0.524414 -10 6 16 0 0.169067 0.609375 -10 6 17 0 0.188232 0.690918 -10 6 18 0 0.206177 0.766113 -10 6 19 0 0.22229 0.832031 -10 6 20 0 0.231323 0.870117 -10 6 21 0 0.232422 0.876953 -10 6 22 0 0.233765 0.884277 -10 6 23 0 0.235352 0.891602 -10 6 24 0 0.237061 0.899414 -10 6 25 0 0.239014 0.907715 -10 6 26 0 0.241211 0.916992 -10 6 27 0 0.243774 0.927246 -10 6 28 0 0.246704 0.938965 -10 6 29 0 0.249756 0.95166 -10 6 30 0 0.253174 0.964355 -10 6 31 0 0.256592 0.978027 -10 7 0 0.26709 0.10553 0 -10 7 1 0.26709 0.105591 0 -10 7 2 0.26709 0.105652 0 -10 7 3 0.26709 0.105774 0 -10 7 4 0.26709 0.106018 0 -10 7 5 0.26709 0.106445 0 -10 7 6 0.268555 0.106995 0 -10 7 7 0.269287 0.105774 0.0860596 -10 7 8 0.264648 0.102234 0.130737 -10 7 9 0.233643 0.0967407 0.161987 -10 7 10 0.20105 0.100281 0.184448 -10 7 11 0.192505 0.106384 0.235229 -10 7 12 0.171631 0.11499 0.296387 -10 7 13 0.115845 0.126099 0.365967 -10 7 14 0 0.139771 0.442871 -10 7 15 0 0.155884 0.524414 -10 7 16 0 0.173828 0.609375 -10 7 17 0 0.192017 0.690918 -10 7 18 0 0.209229 0.766113 -10 7 19 0 0.224731 0.832031 -10 7 20 0 0.233398 0.870117 -10 7 21 0 0.234009 0.876953 -10 7 22 0 0.235107 0.884277 -10 7 23 0 0.23645 0.89209 -10 7 24 0 0.237915 0.899414 -10 7 25 0 0.239746 0.907715 -10 7 26 0 0.241943 0.916992 -10 7 27 0 0.244385 0.927246 -10 7 28 0 0.247192 0.938965 -10 7 29 0 0.250244 0.95166 -10 7 30 0 0.253418 0.964844 -10 7 31 0 0.256836 0.978027 -10 8 0 0.24939 0.13269 0 -10 8 1 0.24939 0.13269 0 -10 8 2 0.24939 0.13269 0 -10 8 3 0.249268 0.132812 0 -10 8 4 0.249268 0.132935 0 -10 8 5 0.249146 0.133057 0 -10 8 6 0.250244 0.133667 0.0313721 -10 8 7 0.252197 0.134155 0.0823975 -10 8 8 0.254883 0.134644 0.125732 -10 8 9 0.237915 0.127441 0.165405 -10 8 10 0.198364 0.11969 0.184082 -10 8 11 0.189331 0.124939 0.234985 -10 8 12 0.167847 0.132324 0.296143 -10 8 13 0.108337 0.141602 0.365967 -10 8 14 0 0.153076 0.442871 -10 8 15 0 0.16687 0.524902 -10 8 16 0 0.182739 0.609375 -10 8 17 0 0.199097 0.690918 -10 8 18 0 0.214844 0.766113 -10 8 19 0 0.22937 0.832031 -10 8 20 0 0.237061 0.870605 -10 8 21 0 0.236938 0.877441 -10 8 22 0 0.237549 0.884766 -10 8 23 0 0.238525 0.89209 -10 8 24 0 0.239746 0.899414 -10 8 25 0 0.241333 0.907715 -10 8 26 0 0.243164 0.916992 -10 8 27 0 0.245483 0.927734 -10 8 28 0 0.248169 0.939453 -10 8 29 0 0.250977 0.95166 -10 8 30 0 0.25415 0.964844 -10 8 31 0 0.257568 0.978027 -10 9 0 0.223755 0.156494 0.0422974 -10 9 1 0.223755 0.156616 0.0422974 -10 9 2 0.223755 0.156616 0.0423279 -10 9 3 0.223755 0.156616 0.0423889 -10 9 4 0.223755 0.156738 0.0424805 -10 9 5 0.223755 0.15686 0.0426636 -10 9 6 0.223267 0.15686 0.0591431 -10 9 7 0.222412 0.156982 0.0849609 -10 9 8 0.222656 0.158325 0.116089 -10 9 9 0.229126 0.164307 0.161255 -10 9 10 0.193115 0.147095 0.183716 -10 9 11 0.18335 0.151733 0.234497 -10 9 12 0.160034 0.157959 0.295898 -10 9 13 0.0909424 0.165283 0.365723 -10 9 14 0 0.174316 0.442871 -10 9 15 0 0.185181 0.524902 -10 9 16 0 0.197998 0.609375 -10 9 17 0 0.21167 0.691406 -10 9 18 0 0.22522 0.766113 -10 9 19 0 0.237793 0.832031 -10 9 20 0 0.244141 0.871094 -10 9 21 0 0.242554 0.877441 -10 9 22 0 0.242188 0.884766 -10 9 23 0 0.242432 0.89209 -10 9 24 0 0.243042 0.899902 -10 9 25 0 0.244141 0.908203 -10 9 26 0 0.245728 0.91748 -10 9 27 0 0.247559 0.927734 -10 9 28 0 0.25 0.939453 -10 9 29 0 0.252686 0.95166 -10 9 30 0 0.255615 0.964844 -10 9 31 0 0.258545 0.978027 -10 10 0 0.215576 0.197876 0.0621033 -10 10 1 0.215576 0.197876 0.0621033 -10 10 2 0.215576 0.197876 0.0621033 -10 10 3 0.215576 0.197876 0.0621033 -10 10 4 0.215576 0.197998 0.0621338 -10 10 5 0.215698 0.19812 0.0621338 -10 10 6 0.215332 0.19812 0.0667725 -10 10 7 0.212769 0.196899 0.0899658 -10 10 8 0.207886 0.19458 0.117493 -10 10 9 0.198853 0.19043 0.149414 -10 10 10 0.183105 0.183105 0.183105 -10 10 11 0.171509 0.187134 0.234009 -10 10 12 0.144165 0.192383 0.295166 -10 10 13 0 0.198242 0.365234 -10 10 14 0 0.204834 0.442627 -10 10 15 0 0.212524 0.524414 -10 10 16 0 0.221802 0.609863 -10 10 17 0 0.231934 0.691406 -10 10 18 0 0.242188 0.766602 -10 10 19 0 0.251953 0.83252 -10 10 20 0 0.256104 0.87207 -10 10 21 0 0.252441 0.878418 -10 10 22 0 0.250244 0.885742 -10 10 23 0 0.249268 0.893066 -10 10 24 0 0.249023 0.900391 -10 10 25 0 0.249268 0.908691 -10 10 26 0 0.25 0.917969 -10 10 27 0 0.251465 0.928223 -10 10 28 0 0.253174 0.939941 -10 10 29 0 0.255615 0.952148 -10 10 30 0 0.258057 0.964844 -10 10 31 0 0.260742 0.978516 -10 11 0 0.187988 0.238647 0.0592346 -10 11 1 0.18811 0.238647 0.0592346 -10 11 2 0.18811 0.238647 0.0592346 -10 11 3 0.18811 0.238647 0.0592651 -10 11 4 0.18811 0.238647 0.0592651 -10 11 5 0.18811 0.23877 0.0592651 -10 11 6 0.188232 0.238892 0.0592957 -10 11 7 0.186523 0.238037 0.0791016 -10 11 8 0.182129 0.235596 0.109253 -10 11 9 0.174194 0.231567 0.143066 -10 11 10 0.163208 0.229248 0.182739 -10 11 11 0.146851 0.232056 0.233398 -10 11 12 0.106445 0.236328 0.294434 -10 11 13 0 0.240845 0.364502 -10 11 14 0 0.245483 0.442139 -10 11 15 0 0.250244 0.524414 -10 11 16 0 0.255859 0.609863 -10 11 17 0 0.261963 0.691895 -10 11 18 0 0.268066 0.76709 -10 11 19 0 0.274414 0.833008 -10 11 20 0 0.275391 0.873535 -10 11 21 0 0.268311 0.879395 -10 11 22 0 0.263428 0.886719 -10 11 23 0 0.260742 0.894043 -10 11 24 0 0.259033 0.901367 -10 11 25 0 0.257812 0.90918 -10 11 26 0 0.257568 0.918457 -10 11 27 0 0.257812 0.928711 -10 11 28 0 0.258789 0.94043 -10 11 29 0 0.260498 0.952637 -10 11 30 0 0.262207 0.965332 -10 11 31 0 0.264404 0.978516 -10 12 0 0.138062 0.288574 0.0564575 -10 12 1 0.138062 0.288574 0.0564575 -10 12 2 0.138062 0.288574 0.0564575 -10 12 3 0.138062 0.288574 0.0564575 -10 12 4 0.138184 0.288574 0.0564575 -10 12 5 0.138184 0.288574 0.056488 -10 12 6 0.138306 0.288818 0.0565186 -10 12 7 0.138306 0.288818 0.0593567 -10 12 8 0.134155 0.287842 0.0985107 -10 12 9 0.125977 0.286621 0.137451 -10 12 10 0.110046 0.286377 0.18103 -10 12 11 0.0672607 0.287842 0.232422 -10 12 12 0 0.290771 0.293213 -10 12 13 0 0.293945 0.363281 -10 12 14 0 0.297119 0.441406 -10 12 15 0 0.299316 0.524414 -10 12 16 0 0.301514 0.609863 -10 12 17 0 0.303223 0.692383 -10 12 18 0 0.305176 0.767578 -10 12 19 0 0.307129 0.833496 -10 12 20 0 0.304199 0.875977 -10 12 21 0 0.29248 0.881836 -10 12 22 0 0.28418 0.888672 -10 12 23 0 0.278564 0.895508 -10 12 24 0 0.274658 0.902832 -10 12 25 0 0.271729 0.910645 -10 12 26 0 0.269775 0.919434 -10 12 27 0 0.268555 0.929688 -10 12 28 0 0.268066 0.940918 -10 12 29 0 0.268311 0.953125 -10 12 30 0 0.269287 0.966309 -10 12 31 0 0.270508 0.979492 -10 13 0 0 0.353271 0.0540161 -10 13 1 0 0.353271 0.0540161 -10 13 2 0 0.353271 0.0540161 -10 13 3 0 0.353271 0.0540466 -10 13 4 0 0.353271 0.0540466 -10 13 5 0 0.353271 0.0540466 -10 13 6 0 0.353271 0.0540771 -10 13 7 0 0.353516 0.0541382 -10 13 8 0 0.353516 0.0792236 -10 13 9 0 0.353271 0.128052 -10 13 10 0 0.353516 0.176147 -10 13 11 0 0.354248 0.229492 -10 13 12 0 0.355469 0.291016 -10 13 13 0 0.357666 0.361328 -10 13 14 0 0.359131 0.439697 -10 13 15 0 0.359375 0.523438 -10 13 16 0 0.358643 0.609863 -10 13 17 0 0.356689 0.692871 -10 13 18 0 0.354004 0.768555 -10 13 19 0 0.351318 0.834473 -10 13 20 0 0.344482 0.879395 -10 13 21 0 0.327148 0.885254 -10 13 22 0 0.314209 0.891602 -10 13 23 0 0.304932 0.898438 -10 13 24 0 0.298096 0.905273 -10 13 25 0 0.29248 0.913086 -10 13 26 0 0.288086 0.921875 -10 13 27 0 0.284668 0.931641 -10 13 28 0 0.282471 0.942871 -10 13 29 0 0.281006 0.95459 -10 13 30 0 0.280273 0.967285 -10 13 31 0 0.280029 0.980469 -10 14 0 0 0.427979 0.0498962 -10 14 1 0 0.427979 0.0498962 -10 14 2 0 0.427979 0.0498962 -10 14 3 0 0.427979 0.0498962 -10 14 4 0 0.427979 0.0499268 -10 14 5 0 0.427979 0.0499268 -10 14 6 0 0.427979 0.0499573 -10 14 7 0 0.428223 0.0500183 -10 14 8 0 0.428223 0.0501709 -10 14 9 0 0.428467 0.108459 -10 14 10 0 0.428711 0.165283 -10 14 11 0 0.429443 0.222656 -10 14 12 0 0.430176 0.286133 -10 14 13 0 0.431152 0.357178 -10 14 14 0 0.431396 0.436279 -10 14 15 0 0.43042 0.520996 -10 14 16 0 0.427246 0.608887 -10 14 17 0 0.421875 0.692871 -10 14 18 0 0.415039 0.769043 -10 14 19 0 0.407715 0.835938 -10 14 20 0 0.397461 0.884766 -10 14 21 0 0.373291 0.890625 -10 14 22 0 0.35498 0.896484 -10 14 23 0 0.341309 0.902832 -10 14 24 0 0.330811 0.90918 -10 14 25 0 0.321777 0.916504 -10 14 26 0 0.314209 0.924805 -10 14 27 0 0.307861 0.93457 -10 14 28 0 0.303223 0.945312 -10 14 29 0 0.299316 0.957031 -10 14 30 0 0.296387 0.969238 -10 14 31 0 0.294434 0.981934 -10 15 0 0 0.508789 0.0421143 -10 15 1 0 0.508789 0.0421143 -10 15 2 0 0.508789 0.0421143 -10 15 3 0 0.508789 0.0421448 -10 15 4 0 0.508789 0.0421448 -10 15 5 0 0.508789 0.0421753 -10 15 6 0 0.508789 0.0422058 -10 15 7 0 0.508789 0.0422974 -10 15 8 0 0.508789 0.04245 -10 15 9 0 0.509277 0.0553284 -10 15 10 0 0.509766 0.144897 -10 15 11 0 0.510254 0.209717 -10 15 12 0 0.51123 0.276611 -10 15 13 0 0.512207 0.349854 -10 15 14 0 0.512207 0.430176 -10 15 15 0 0.510254 0.516602 -10 15 16 0 0.505859 0.605957 -10 15 17 0 0.497803 0.691406 -10 15 18 0 0.487305 0.769043 -10 15 19 0 0.47583 0.836914 -10 15 20 0 0.462891 0.891113 -10 15 21 0 0.431885 0.897949 -10 15 22 0 0.407227 0.903809 -10 15 23 0 0.388428 0.909668 -10 15 24 0 0.373779 0.915527 -10 15 25 0 0.36084 0.922363 -10 15 26 0 0.349365 0.930176 -10 15 27 0 0.3396 0.938965 -10 15 28 0 0.331543 0.949219 -10 15 29 0 0.324707 0.960449 -10 15 30 0 0.319092 0.972168 -10 15 31 0 0.314453 0.984375 -10 16 0 0 0.59375 0.0237579 -10 16 1 0 0.59375 0.0237579 -10 16 2 0 0.59375 0.0237732 -10 16 3 0 0.59375 0.0237885 -10 16 4 0 0.59375 0.023819 -10 16 5 0 0.59375 0.0238647 -10 16 6 0 0.59375 0.0239716 -10 16 7 0 0.59375 0.0241699 -10 16 8 0 0.59375 0.0245514 -10 16 9 0 0.594238 0.0252686 -10 16 10 0 0.594727 0.104065 -10 16 11 0 0.595215 0.18811 -10 16 12 0 0.59668 0.26123 -10 16 13 0 0.597656 0.337402 -10 16 14 0 0.598145 0.419678 -10 16 15 0 0.597168 0.507812 -10 16 16 0 0.591797 0.599121 -10 16 17 0 0.58252 0.6875 -10 16 18 0 0.569336 0.767578 -10 16 19 0 0.554688 0.836914 -10 16 20 0 0.538086 0.894043 -10 16 21 0 0.50293 0.907227 -10 16 22 0 0.471924 0.914551 -10 16 23 0 0.44751 0.92041 -10 16 24 0 0.427979 0.925781 -10 16 25 0 0.4104 0.931641 -10 16 26 0 0.394531 0.938477 -10 16 27 0 0.380615 0.946289 -10 16 28 0 0.368652 0.955566 -10 16 29 0 0.358154 0.966309 -10 16 30 0 0.349121 0.977051 -10 16 31 0 0.341553 0.98877 -10 17 0 0 0.677246 0 -10 17 1 0 0.677246 0 -10 17 2 0 0.677246 0 -10 17 3 0 0.677246 0 -10 17 4 0 0.677246 0 -10 17 5 0 0.677246 0 -10 17 6 0 0.677246 0 -10 17 7 0 0.677734 0 -10 17 8 0 0.677734 0 -10 17 9 0 0.677734 0 -10 17 10 0 0.678223 0 -10 17 11 0 0.679199 0.153198 -10 17 12 0 0.680664 0.23877 -10 17 13 0 0.682617 0.319336 -10 17 14 0 0.684082 0.404053 -10 17 15 0 0.683594 0.493896 -10 17 16 0 0.679688 0.587402 -10 17 17 0 0.67041 0.678711 -10 17 18 0 0.656738 0.762207 -10 17 19 0 0.63916 0.834473 -10 17 20 0 0.619629 0.894043 -10 17 21 0 0.583008 0.91748 -10 17 22 0 0.547363 0.927734 -10 17 23 0 0.51709 0.93457 -10 17 24 0 0.492432 0.939941 -10 17 25 0 0.469727 0.945312 -10 17 26 0 0.448975 0.951172 -10 17 27 0 0.430176 0.95752 -10 17 28 0 0.413818 0.965332 -10 17 29 0 0.39917 0.974609 -10 17 30 0 0.38623 0.984375 -10 17 31 0 0.375 0.994629 -10 18 0 0 0.755371 0 -10 18 1 0 0.755371 0 -10 18 2 0 0.755371 0 -10 18 3 0 0.755371 0 -10 18 4 0 0.755371 0 -10 18 5 0 0.755371 0 -10 18 6 0 0.755371 0 -10 18 7 0 0.755371 0 -10 18 8 0 0.755859 0 -10 18 9 0 0.755859 0 -10 18 10 0 0.755859 0 -10 18 11 0 0.756348 0.0813599 -10 18 12 0 0.758301 0.207397 -10 18 13 0 0.760742 0.295654 -10 18 14 0 0.763184 0.383301 -10 18 15 0 0.764648 0.474854 -10 18 16 0 0.762695 0.570312 -10 18 17 0 0.755371 0.664551 -10 18 18 0 0.742676 0.751953 -10 18 19 0 0.724609 0.827637 -10 18 20 0 0.703613 0.890137 -10 18 21 0 0.668457 0.924805 -10 18 22 0 0.629883 0.942383 -10 18 23 0 0.595215 0.95166 -10 18 24 0 0.56543 0.95752 -10 18 25 0 0.537598 0.962891 -10 18 26 0 0.51123 0.967285 -10 18 27 0 0.487305 0.972656 -10 18 28 0 0.466064 0.979004 -10 18 29 0 0.446533 0.98584 -10 18 30 0 0.429443 0.994141 -10 18 31 0 0.413818 1 -10 19 0 0 0.825684 0 -10 19 1 0 0.825684 0 -10 19 2 0 0.825684 0 -10 19 3 0 0.825684 0 -10 19 4 0 0.825684 0 -10 19 5 0 0.825684 0 -10 19 6 0 0.825684 0 -10 19 7 0 0.825684 0 -10 19 8 0 0.825684 0 -10 19 9 0 0.825684 0 -10 19 10 0 0.825684 0 -10 19 11 0 0.826172 0 -10 19 12 0 0.827637 0.163574 -10 19 13 0 0.830078 0.266602 -10 19 14 0 0.833496 0.358643 -10 19 15 0 0.836426 0.451904 -10 19 16 0 0.836914 0.548828 -10 19 17 0 0.83252 0.645508 -10 19 18 0 0.822266 0.73584 -10 19 19 0 0.805664 0.81543 -10 19 20 0 0.78418 0.881836 -10 19 21 0 0.75293 0.927734 -10 19 22 0 0.714844 0.954102 -10 19 23 0 0.677734 0.96875 -10 19 24 0 0.644043 0.977051 -10 19 25 0 0.61084 0.98291 -10 19 26 0 0.57959 0.987305 -10 19 27 0 0.550293 0.991211 -10 19 28 0 0.523438 0.995605 -10 19 29 0 0.499023 1 -10 19 30 0 0.476807 1 -10 19 31 0 0.457031 1 -10 20 0 0 0.88623 0 -10 20 1 0 0.88623 0 -10 20 2 0 0.88623 0 -10 20 3 0 0.88623 0 -10 20 4 0 0.88623 0 -10 20 5 0 0.88623 0 -10 20 6 0 0.88623 0 -10 20 7 0 0.88623 0 -10 20 8 0 0.88623 0 -10 20 9 0 0.88623 0 -10 20 10 0 0.88623 0 -10 20 11 0 0.886719 0 -10 20 12 0 0.887207 0.0822144 -10 20 13 0 0.890137 0.232666 -10 20 14 0 0.894043 0.331299 -10 20 15 0 0.897461 0.426758 -10 20 16 0 0.900391 0.524414 -10 20 17 0 0.898926 0.622559 -10 20 18 0 0.891602 0.715332 -10 20 19 0 0.877441 0.79834 -10 20 20 0 0.857422 0.868164 -10 20 21 0 0.830566 0.92334 -10 20 22 0 0.795898 0.960449 -10 20 23 0 0.758789 0.981934 -10 20 24 0 0.723145 0.994629 -10 20 25 0 0.686523 1 -10 20 26 0 0.650391 1 -10 20 27 0 0.615723 1 -10 20 28 0 0.583984 1 -10 20 29 0 0.554199 1 -10 20 30 0 0.527344 1 -10 20 31 0 0.50293 1 -10 21 0 0 0.9375 0 -10 21 1 0 0.9375 0 -10 21 2 0 0.9375 0 -10 21 3 0 0.9375 0 -10 21 4 0 0.9375 0 -10 21 5 0 0.9375 0 -10 21 6 0 0.9375 0 -10 21 7 0 0.9375 0 -10 21 8 0 0.9375 0 -10 21 9 0 0.9375 0 -10 21 10 0 0.937988 0 -10 21 11 0 0.937988 0 -10 21 12 0 0.937988 0 -10 21 13 0 0.94043 0.190186 -10 21 14 0 0.944824 0.301025 -10 21 15 0 0.949219 0.39917 -10 21 16 0 0.953613 0.497803 -10 21 17 0 0.95459 0.596191 -10 21 18 0 0.950684 0.69043 -10 21 19 0 0.939941 0.776367 -10 21 20 0 0.922852 0.849609 -10 21 21 0 0.899902 0.911133 -10 21 22 0 0.870117 0.95752 -10 21 23 0 0.835938 0.987793 -10 21 24 0 0.800293 1 -10 21 25 0 0.761719 1 -10 21 26 0 0.722168 1 -10 21 27 0 0.683594 1 -10 21 28 0 0.646973 1 -10 21 29 0 0.612305 1 -10 21 30 0 0.580078 1 -10 21 31 0 0.55127 1 -10 22 0 0 0.980469 0 -10 22 1 0 0.980469 0 -10 22 2 0 0.980469 0 -10 22 3 0 0.980469 0 -10 22 4 0 0.980469 0 -10 22 5 0 0.980469 0 -10 22 6 0 0.980469 0 -10 22 7 0 0.980469 0 -10 22 8 0 0.980469 0 -10 22 9 0 0.980469 0 -10 22 10 0 0.980469 0 -10 22 11 0 0.980469 0 -10 22 12 0 0.980957 0 -10 22 13 0 0.981934 0.129639 -10 22 14 0 0.986328 0.267822 -10 22 15 0 0.991699 0.370361 -10 22 16 0 0.99707 0.469727 -10 22 17 0 1 0.567871 -10 22 18 0 0.999512 0.663086 -10 22 19 0 0.992188 0.750488 -10 22 20 0 0.978516 0.82666 -10 22 21 0 0.958496 0.89209 -10 22 22 0 0.933594 0.945312 -10 22 23 0 0.903809 0.983887 -10 22 24 0 0.870605 1 -10 22 25 0 0.833008 1 -10 22 26 0 0.79248 1 -10 22 27 0 0.750977 1 -10 22 28 0 0.709961 1 -10 22 29 0 0.670898 1 -10 22 30 0 0.634766 1 -10 22 31 0 0.600586 1 -10 23 0 0 1 0 -10 23 1 0 1 0 -10 23 2 0 1 0 -10 23 3 0 1 0 -10 23 4 0 1 0 -10 23 5 0 1 0 -10 23 6 0 1 0 -10 23 7 0 1 0 -10 23 8 0 1 0 -10 23 9 0 1 0 -10 23 10 0 1 0 -10 23 11 0 1 0 -10 23 12 0 1 0 -10 23 13 0 1 0 -10 23 14 0 1 0.232178 -10 23 15 0 1 0.341553 -10 23 16 0 1 0.441895 -10 23 17 0 1 0.540039 -10 23 18 0 1 0.635254 -10 23 19 0 1 0.723145 -10 23 20 0 1 0.801758 -10 23 21 0 1 0.869629 -10 23 22 0 0.984863 0.926758 -10 23 23 0 0.958984 0.971191 -10 23 24 0 0.930176 1 -10 23 25 0 0.89502 1 -10 23 26 0 0.855469 1 -10 23 27 0 0.812988 1 -10 23 28 0 0.77002 1 -10 23 29 0 0.727539 1 -10 23 30 0 0.687012 1 -10 23 31 0 0.648926 1 -10 24 0 0 1 0 -10 24 1 0 1 0 -10 24 2 0 1 0 -10 24 3 0 1 0 -10 24 4 0 1 0 -10 24 5 0 1 0 -10 24 6 0 1 0 -10 24 7 0 1 0 -10 24 8 0 1 0 -10 24 9 0 1 0 -10 24 10 0 1 0 -10 24 11 0 1 0 -10 24 12 0 1 0 -10 24 13 0 1 0 -10 24 14 0 1 0.191895 -10 24 15 0 1 0.3125 -10 24 16 0 1 0.414795 -10 24 17 0 1 0.512695 -10 24 18 0 1 0.606934 -10 24 19 0 1 0.695312 -10 24 20 0 1 0.774902 -10 24 21 0 1 0.845215 -10 24 22 0 1 0.904785 -10 24 23 0 1 0.953125 -10 24 24 0 0.979492 0.991699 -10 24 25 0 0.948242 1 -10 24 26 0 0.911133 1 -10 24 27 0 0.869141 1 -10 24 28 0 0.825195 1 -10 24 29 0 0.780762 1 -10 24 30 0 0.737305 1 -10 24 31 0 0.695801 1 -10 25 0 0 1 0 -10 25 1 0 1 0 -10 25 2 0 1 0 -10 25 3 0 1 0 -10 25 4 0 1 0 -10 25 5 0 1 0 -10 25 6 0 1 0 -10 25 7 0 1 0 -10 25 8 0 1 0 -10 25 9 0 1 0 -10 25 10 0 1 0 -10 25 11 0 1 0 -10 25 12 0 1 0 -10 25 13 0 1 0 -10 25 14 0 1 0.133423 -10 25 15 0 1 0.280029 -10 25 16 0 1 0.385254 -10 25 17 0 1 0.48291 -10 25 18 0 1 0.57666 -10 25 19 0 1 0.664551 -10 25 20 0 1 0.744629 -10 25 21 0 1 0.816406 -10 25 22 0 1 0.878906 -10 25 23 0 1 0.930664 -10 25 24 0 1 0.972656 -10 25 25 0 0.997559 1 -10 25 26 0 0.963867 1 -10 25 27 0 0.924316 1 -10 25 28 0 0.880859 1 -10 25 29 0 0.835449 1 -10 25 30 0 0.789551 1 -10 25 31 0 0.745605 1 -10 26 0 0 1 0 -10 26 1 0 1 0 -10 26 2 0 1 0 -10 26 3 0 1 0 -10 26 4 0 1 0 -10 26 5 0 1 0 -10 26 6 0 1 0 -10 26 7 0 1 0 -10 26 8 0 1 0 -10 26 9 0 1 0 -10 26 10 0 1 0 -10 26 11 0 1 0 -10 26 12 0 1 0 -10 26 13 0 1 0 -10 26 14 0 1 0 -10 26 15 0 1 0.24231 -10 26 16 0 1 0.353516 -10 26 17 0 1 0.451416 -10 26 18 0 1 0.543945 -10 26 19 0 1 0.631348 -10 26 20 0 1 0.710938 -10 26 21 0 1 0.78418 -10 26 22 0 1 0.848633 -10 26 23 0 1 0.902832 -10 26 24 0 1 0.948242 -10 26 25 0 1 0.989258 -10 26 26 0 1 1 -10 26 27 0 0.976562 1 -10 26 28 0 0.935059 1 -10 26 29 0 0.889648 1 -10 26 30 0 0.843262 1 -10 26 31 0 0.796387 1 -10 27 0 0 1 0 -10 27 1 0 1 0 -10 27 2 0 1 0 -10 27 3 0 1 0 -10 27 4 0 1 0 -10 27 5 0 1 0 -10 27 6 0 1 0 -10 27 7 0 1 0 -10 27 8 0 1 0 -10 27 9 0 1 0 -10 27 10 0 1 0 -10 27 11 0 1 0 -10 27 12 0 1 0 -10 27 13 0 1 0 -10 27 14 0 1 0 -10 27 15 0 1 0.195923 -10 27 16 0 1 0.318848 -10 27 17 0 1 0.417969 -10 27 18 0 1 0.509766 -10 27 19 0 1 0.595703 -10 27 20 0 1 0.674805 -10 27 21 0 1 0.748047 -10 27 22 0 1 0.813965 -10 27 23 0 1 0.870605 -10 27 24 0 1 0.918457 -10 27 25 0 1 0.962891 -10 27 26 0 1 1 -10 27 27 0 1 1 -10 27 28 0 0.98584 1 -10 27 29 0 0.942383 1 -10 27 30 0 0.895508 1 -10 27 31 0 0.848145 1 -10 28 0 0 1 0 -10 28 1 0 1 0 -10 28 2 0 1 0 -10 28 3 0 1 0 -10 28 4 0 1 0 -10 28 5 0 1 0 -10 28 6 0 1 0 -10 28 7 0 1 0 -10 28 8 0 1 0 -10 28 9 0 1 0 -10 28 10 0 1 0 -10 28 11 0 1 0 -10 28 12 0 1 0 -10 28 13 0 1 0 -10 28 14 0 1 0 -10 28 15 0 1 0.127563 -10 28 16 0 1 0.280762 -10 28 17 0 1 0.382812 -10 28 18 0 1 0.473877 -10 28 19 0 1 0.558594 -10 28 20 0 1 0.636719 -10 28 21 0 1 0.709473 -10 28 22 0 1 0.775879 -10 28 23 0 1 0.833496 -10 28 24 0 1 0.883789 -10 28 25 0 1 0.931152 -10 28 26 0 1 0.974609 -10 28 27 0 1 1 -10 28 28 0 1 1 -10 28 29 0 0.991699 1 -10 28 30 0 0.947266 1 -10 28 31 0 0.899902 1 -10 29 0 0 1 0 -10 29 1 0 1 0 -10 29 2 0 1 0 -10 29 3 0 1 0 -10 29 4 0 1 0 -10 29 5 0 1 0 -10 29 6 0 1 0 -10 29 7 0 1 0 -10 29 8 0 1 0 -10 29 9 0 1 0 -10 29 10 0 1 0 -10 29 11 0 1 0 -10 29 12 0 1 0 -10 29 13 0 1 0 -10 29 14 0 1 0 -10 29 15 0 1 0 -10 29 16 0 1 0.236816 -10 29 17 0 1 0.345459 -10 29 18 0 1 0.436523 -10 29 19 0 1 0.519531 -10 29 20 0 1 0.596191 -10 29 21 0 1 0.667969 -10 29 22 0 1 0.734375 -10 29 23 0 1 0.79248 -10 29 24 0 1 0.844238 -10 29 25 0 1 0.893555 -10 29 26 0 1 0.94043 -10 29 27 0 1 0.98291 -10 29 28 0 1 1 -10 29 29 0 1 1 -10 29 30 0 0.996582 1 -10 29 31 0 0.95166 1 -10 30 0 0 1 0 -10 30 1 0 1 0 -10 30 2 0 1 0 -10 30 3 0 1 0 -10 30 4 0 1 0 -10 30 5 0 1 0 -10 30 6 0 1 0 -10 30 7 0 1 0 -10 30 8 0 1 0 -10 30 9 0 1 0 -10 30 10 0 1 0 -10 30 11 0 1 0 -10 30 12 0 1 0 -10 30 13 0 1 0 -10 30 14 0 1 0 -10 30 15 0 1 0 -10 30 16 0 1 0.182251 -10 30 17 0 1 0.304932 -10 30 18 0 1 0.397461 -10 30 19 0 1 0.479492 -10 30 20 0 1 0.554199 -10 30 21 0 1 0.624512 -10 30 22 0 1 0.689453 -10 30 23 0 1 0.748047 -10 30 24 0 1 0.799805 -10 30 25 0 1 0.851074 -10 30 26 0 1 0.900391 -10 30 27 0 1 0.946289 -10 30 28 0 1 0.988281 -10 30 29 0 1 1 -10 30 30 0 1 1 -10 30 31 0 1 1 -10 31 0 0 1 0 -10 31 1 0 1 0 -10 31 2 0 1 0 -10 31 3 0 1 0 -10 31 4 0 1 0 -10 31 5 0 1 0 -10 31 6 0 1 0 -10 31 7 0 1 0 -10 31 8 0 1 0 -10 31 9 0 1 0 -10 31 10 0 1 0 -10 31 11 0 1 0 -10 31 12 0 1 0 -10 31 13 0 1 0 -10 31 14 0 1 0 -10 31 15 0 1 0 -10 31 16 0 1 0.0882568 -10 31 17 0 1 0.260742 -10 31 18 0 1 0.356934 -10 31 19 0 1 0.438232 -10 31 20 0 1 0.51123 -10 31 21 0 1 0.57959 -10 31 22 0 1 0.643066 -10 31 23 0 1 0.700684 -10 31 24 0 1 0.752441 -10 31 25 0 1 0.804688 -10 31 26 0 1 0.855469 -10 31 27 0 1 0.904785 -10 31 28 0 1 0.951172 -10 31 29 0 1 0.993164 -10 31 30 0 1 1 -10 31 31 0 1 1 -11 0 0 0.362061 0 0.0226288 -11 0 1 0.362061 0 0.0225983 -11 0 2 0.362061 0 0.0225525 -11 0 3 0.362061 0 0.0224609 -11 0 4 0.362061 0 0.0222931 -11 0 5 0.362061 0 0.0219574 -11 0 6 0.362061 0 0.0214996 -11 0 7 0.362305 0 0.0509033 -11 0 8 0.357178 0 0.123596 -11 0 9 0.34375 0 0.176636 -11 0 10 0.291016 0.0554504 0.203613 -11 0 11 0.261719 0.0887451 0.237183 -11 0 12 0.250488 0.098999 0.297119 -11 0 13 0.226074 0.112488 0.366455 -11 0 14 0.171631 0.128662 0.443359 -11 0 15 0 0.147095 0.525391 -11 0 16 0 0.166992 0.610352 -11 0 17 0 0.186646 0.691895 -11 0 18 0 0.205078 0.766602 -11 0 19 0 0.221436 0.83252 -11 0 20 0 0.231079 0.87207 -11 0 21 0 0.232178 0.878906 -11 0 22 0 0.233643 0.88623 -11 0 23 0 0.235229 0.893555 -11 0 24 0 0.237061 0.900879 -11 0 25 0 0.239014 0.90918 -11 0 26 0 0.241211 0.918457 -11 0 27 0 0.243774 0.928223 -11 0 28 0 0.246704 0.939941 -11 0 29 0 0.249878 0.952637 -11 0 30 0 0.253174 0.965332 -11 0 31 0 0.256592 0.978516 -11 1 0 0.362061 0 0.0222931 -11 1 1 0.362061 0 0.0222626 -11 1 2 0.362061 0 0.0222168 -11 1 3 0.362061 0 0.0221252 -11 1 4 0.361816 0 0.0219421 -11 1 5 0.361816 0 0.0215912 -11 1 6 0.362061 0 0.0211182 -11 1 7 0.362061 0 0.0507812 -11 1 8 0.357178 0 0.123535 -11 1 9 0.34375 0 0.176514 -11 1 10 0.291016 0.0562744 0.203613 -11 1 11 0.261719 0.0891113 0.237183 -11 1 12 0.250488 0.0993042 0.297119 -11 1 13 0.226074 0.112671 0.366455 -11 1 14 0.171509 0.128906 0.443359 -11 1 15 0 0.147217 0.525391 -11 1 16 0 0.167114 0.610352 -11 1 17 0 0.186768 0.691895 -11 1 18 0 0.205078 0.766602 -11 1 19 0 0.221436 0.83252 -11 1 20 0 0.231079 0.87207 -11 1 21 0 0.232178 0.878906 -11 1 22 0 0.233643 0.88623 -11 1 23 0 0.235352 0.893555 -11 1 24 0 0.237061 0.900879 -11 1 25 0 0.239014 0.90918 -11 1 26 0 0.241211 0.918457 -11 1 27 0 0.243774 0.928223 -11 1 28 0 0.246704 0.939941 -11 1 29 0 0.249878 0.952637 -11 1 30 0 0.253174 0.965332 -11 1 31 0 0.256592 0.978516 -11 2 0 0.361816 0 0.0216522 -11 2 1 0.361816 0 0.0216217 -11 2 2 0.361816 0 0.0215759 -11 2 3 0.361816 0 0.0214844 -11 2 4 0.361816 0 0.0213013 -11 2 5 0.361572 0 0.0209351 -11 2 6 0.361816 0 0.0204315 -11 2 7 0.362061 0 0.0505066 -11 2 8 0.357178 0 0.123474 -11 2 9 0.34375 0 0.176514 -11 2 10 0.291016 0.0576782 0.203735 -11 2 11 0.261719 0.0896606 0.237183 -11 2 12 0.250488 0.0997925 0.297119 -11 2 13 0.226074 0.113098 0.366455 -11 2 14 0.171509 0.129272 0.443359 -11 2 15 0 0.147461 0.525391 -11 2 16 0 0.167358 0.610352 -11 2 17 0 0.18689 0.691895 -11 2 18 0 0.2052 0.766602 -11 2 19 0 0.221558 0.83252 -11 2 20 0 0.231201 0.87207 -11 2 21 0 0.2323 0.878906 -11 2 22 0 0.233765 0.88623 -11 2 23 0 0.235352 0.893555 -11 2 24 0 0.237061 0.900879 -11 2 25 0 0.239014 0.90918 -11 2 26 0 0.241333 0.918457 -11 2 27 0 0.243774 0.928223 -11 2 28 0 0.246704 0.939941 -11 2 29 0 0.249878 0.952637 -11 2 30 0 0.253174 0.965332 -11 2 31 0 0.256592 0.978516 -11 3 0 0.361328 0 0.0204163 -11 3 1 0.361328 0 0.0203857 -11 3 2 0.361328 0 0.0203247 -11 3 3 0.361328 0 0.0202179 -11 3 4 0.361328 0 0.0200195 -11 3 5 0.361328 0 0.0196228 -11 3 6 0.361572 0 0.0190735 -11 3 7 0.361816 0 0.0500793 -11 3 8 0.356934 0 0.123291 -11 3 9 0.34375 0 0.176514 -11 3 10 0.291016 0.0601501 0.203735 -11 3 11 0.261475 0.0907593 0.237183 -11 3 12 0.250244 0.100708 0.297119 -11 3 13 0.225952 0.113892 0.366455 -11 3 14 0.171387 0.129883 0.443359 -11 3 15 0 0.147949 0.525391 -11 3 16 0 0.167725 0.610352 -11 3 17 0 0.187256 0.691895 -11 3 18 0 0.205444 0.766602 -11 3 19 0 0.221802 0.83252 -11 3 20 0 0.231323 0.87207 -11 3 21 0 0.232422 0.878906 -11 3 22 0 0.233887 0.88623 -11 3 23 0 0.235474 0.893555 -11 3 24 0 0.237183 0.900879 -11 3 25 0 0.239136 0.90918 -11 3 26 0 0.241333 0.918457 -11 3 27 0 0.243896 0.928223 -11 3 28 0 0.246826 0.939941 -11 3 29 0 0.249878 0.952637 -11 3 30 0 0.253174 0.965332 -11 3 31 0 0.256592 0.978516 -11 4 0 0.36084 0 0.0177002 -11 4 1 0.36084 0 0.0176544 -11 4 2 0.36084 0 0.0175781 -11 4 3 0.36084 0 0.0174561 -11 4 4 0.36084 0 0.0171967 -11 4 5 0.360596 0 0.0166779 -11 4 6 0.36084 0 0.0159607 -11 4 7 0.361084 0 0.0492249 -11 4 8 0.356689 0 0.122986 -11 4 9 0.34375 0 0.176392 -11 4 10 0.29126 0.0644531 0.203979 -11 4 11 0.261475 0.0927124 0.237183 -11 4 12 0.250244 0.102417 0.297119 -11 4 13 0.22583 0.115295 0.366455 -11 4 14 0.171021 0.130981 0.443359 -11 4 15 0 0.148926 0.525391 -11 4 16 0 0.168335 0.610352 -11 4 17 0 0.187744 0.691895 -11 4 18 0 0.205933 0.766602 -11 4 19 0 0.222046 0.83252 -11 4 20 0 0.231567 0.87207 -11 4 21 0 0.232666 0.878906 -11 4 22 0 0.234009 0.88623 -11 4 23 0 0.235596 0.893555 -11 4 24 0 0.237305 0.900879 -11 4 25 0 0.239258 0.90918 -11 4 26 0 0.241455 0.918457 -11 4 27 0 0.243896 0.928711 -11 4 28 0 0.246826 0.939941 -11 4 29 0 0.25 0.952637 -11 4 30 0 0.253174 0.965332 -11 4 31 0 0.256592 0.978516 -11 5 0 0.359375 0 0.00821686 -11 5 1 0.359375 0 0.00807953 -11 5 2 0.359375 0 0.00782776 -11 5 3 0.359375 0 0.00732422 -11 5 4 0.359375 0 0.00618362 -11 5 5 0.359375 0.007061 0 -11 5 6 0.359619 0.0234985 0 -11 5 7 0.360107 0.0258942 0.0476074 -11 5 8 0.356201 0 0.122437 -11 5 9 0.343506 0 0.176147 -11 5 10 0.291504 0.0716553 0.204224 -11 5 11 0.26123 0.0962524 0.237061 -11 5 12 0.249878 0.105591 0.297119 -11 5 13 0.225464 0.11792 0.366455 -11 5 14 0.170532 0.133179 0.443359 -11 5 15 0 0.150635 0.525391 -11 5 16 0 0.169678 0.610352 -11 5 17 0 0.188843 0.691895 -11 5 18 0 0.206665 0.766602 -11 5 19 0 0.222778 0.83252 -11 5 20 0 0.232178 0.872559 -11 5 21 0 0.233032 0.878906 -11 5 22 0 0.234375 0.88623 -11 5 23 0 0.23584 0.893555 -11 5 24 0 0.237549 0.900879 -11 5 25 0 0.23938 0.90918 -11 5 26 0 0.241577 0.918457 -11 5 27 0 0.244141 0.928711 -11 5 28 0 0.246948 0.939941 -11 5 29 0 0.25 0.952637 -11 5 30 0 0.253418 0.965332 -11 5 31 0 0.256836 0.978516 -11 6 0 0.356934 0.0668945 0 -11 6 1 0.356934 0.0670166 0 -11 6 2 0.356934 0.0671997 0 -11 6 3 0.356934 0.0675049 0 -11 6 4 0.356934 0.0681152 0 -11 6 5 0.356689 0.0692139 0 -11 6 6 0.356934 0.0707397 0 -11 6 7 0.35791 0.071106 0.0446472 -11 6 8 0.354736 0.0643311 0.121277 -11 6 9 0.343262 0.0556946 0.175781 -11 6 10 0.292236 0.0831299 0.204834 -11 6 11 0.260742 0.1026 0.237061 -11 6 12 0.249268 0.111206 0.297119 -11 6 13 0.224854 0.122742 0.366455 -11 6 14 0.169556 0.137085 0.443359 -11 6 15 0 0.153809 0.525391 -11 6 16 0 0.172241 0.610352 -11 6 17 0 0.190796 0.691895 -11 6 18 0 0.208252 0.76709 -11 6 19 0 0.223999 0.83252 -11 6 20 0 0.233154 0.872559 -11 6 21 0 0.233887 0.878906 -11 6 22 0 0.234985 0.88623 -11 6 23 0 0.23645 0.893555 -11 6 24 0 0.238037 0.900879 -11 6 25 0 0.239868 0.90918 -11 6 26 0 0.241943 0.918457 -11 6 27 0 0.244385 0.928711 -11 6 28 0 0.247192 0.939941 -11 6 29 0 0.250244 0.952637 -11 6 30 0 0.253418 0.965332 -11 6 31 0 0.256836 0.978516 -11 7 0 0.351562 0.102539 0 -11 7 1 0.351562 0.102539 0 -11 7 2 0.351562 0.102661 0 -11 7 3 0.351562 0.102783 0 -11 7 4 0.351318 0.103088 0 -11 7 5 0.351318 0.103638 0 -11 7 6 0.351562 0.104492 0 -11 7 7 0.353027 0.104797 0.0396423 -11 7 8 0.351562 0.101074 0.11908 -11 7 9 0.342041 0.0949707 0.174683 -11 7 10 0.293457 0.100647 0.206055 -11 7 11 0.259766 0.113342 0.236938 -11 7 12 0.248291 0.120972 0.296875 -11 7 13 0.223511 0.131348 0.366455 -11 7 14 0.167603 0.144287 0.443359 -11 7 15 0 0.159668 0.525391 -11 7 16 0 0.17688 0.610352 -11 7 17 0 0.194458 0.691895 -11 7 18 0 0.211304 0.76709 -11 7 19 0 0.22644 0.833008 -11 7 20 0 0.235107 0.872559 -11 7 21 0 0.235474 0.878906 -11 7 22 0 0.236328 0.88623 -11 7 23 0 0.237549 0.893555 -11 7 24 0 0.238892 0.900879 -11 7 25 0 0.240601 0.90918 -11 7 26 0 0.242676 0.918457 -11 7 27 0 0.244995 0.928711 -11 7 28 0 0.247681 0.939941 -11 7 29 0 0.250732 0.952637 -11 7 30 0 0.253906 0.965332 -11 7 31 0 0.257324 0.978516 -11 8 0 0.339844 0.138184 0 -11 8 1 0.339844 0.138184 0 -11 8 2 0.339844 0.138306 0 -11 8 3 0.339844 0.138306 0 -11 8 4 0.339844 0.13855 0 -11 8 5 0.339844 0.138794 0 -11 8 6 0.339844 0.139404 0 -11 8 7 0.341797 0.139893 0.0357666 -11 8 8 0.343018 0.13855 0.115112 -11 8 9 0.33667 0.134033 0.171631 -11 8 10 0.296631 0.127075 0.208618 -11 8 11 0.257812 0.130615 0.236694 -11 8 12 0.246094 0.137207 0.296875 -11 8 13 0.220947 0.145874 0.366211 -11 8 14 0.163574 0.156982 0.443359 -11 8 15 0 0.170288 0.525391 -11 8 16 0 0.185547 0.610352 -11 8 17 0 0.201416 0.691895 -11 8 18 0 0.216919 0.76709 -11 8 19 0 0.230957 0.833008 -11 8 20 0 0.238892 0.872559 -11 8 21 0 0.238403 0.879395 -11 8 22 0 0.23877 0.88623 -11 8 23 0 0.239502 0.893555 -11 8 24 0 0.240723 0.900879 -11 8 25 0 0.242188 0.90918 -11 8 26 0 0.243896 0.918457 -11 8 27 0 0.246094 0.928711 -11 8 28 0 0.248657 0.94043 -11 8 29 0 0.251465 0.952637 -11 8 30 0 0.254639 0.965332 -11 8 31 0 0.257812 0.978516 -11 9 0 0.316895 0.172729 0 -11 9 1 0.316895 0.172729 0 -11 9 2 0.316895 0.172729 0 -11 9 3 0.31665 0.172852 0 -11 9 4 0.31665 0.172852 0 -11 9 5 0.31665 0.172974 0 -11 9 6 0.316406 0.17334 0 -11 9 7 0.317871 0.174072 0.0506287 -11 9 8 0.320557 0.174927 0.110168 -11 9 9 0.324219 0.175903 0.165283 -11 9 10 0.302246 0.166504 0.213379 -11 9 11 0.25415 0.15625 0.236206 -11 9 12 0.241943 0.161621 0.296387 -11 9 13 0.216064 0.168823 0.365967 -11 9 14 0.155518 0.17749 0.443115 -11 9 15 0 0.18811 0.525391 -11 9 16 0 0.200562 0.610352 -11 9 17 0 0.213867 0.691895 -11 9 18 0 0.227051 0.76709 -11 9 19 0 0.23938 0.833008 -11 9 20 0 0.24585 0.873047 -11 9 21 0 0.244019 0.879395 -11 9 22 0 0.243408 0.886719 -11 9 23 0 0.243408 0.894043 -11 9 24 0 0.244019 0.901367 -11 9 25 0 0.244995 0.909668 -11 9 26 0 0.24646 0.918457 -11 9 27 0 0.248291 0.928711 -11 9 28 0 0.250488 0.94043 -11 9 29 0 0.253174 0.952637 -11 9 30 0 0.255859 0.96582 -11 9 31 0 0.259033 0.979004 -11 10 0 0.285889 0.202515 0.057251 -11 10 1 0.285889 0.202515 0.057251 -11 10 2 0.285889 0.202515 0.0572815 -11 10 3 0.285889 0.202637 0.057312 -11 10 4 0.285889 0.202637 0.057373 -11 10 5 0.285889 0.202759 0.0574951 -11 10 6 0.285889 0.202881 0.0577087 -11 10 7 0.285156 0.202881 0.0796509 -11 10 8 0.283936 0.203003 0.112854 -11 10 9 0.283691 0.204712 0.152588 -11 10 10 0.291504 0.212158 0.208618 -11 10 11 0.247314 0.190674 0.235596 -11 10 12 0.234253 0.19519 0.295898 -11 10 13 0.206543 0.200806 0.365723 -11 10 14 0.138794 0.207275 0.442871 -11 10 15 0 0.214966 0.525391 -11 10 16 0 0.223999 0.610352 -11 10 17 0 0.233887 0.692383 -11 10 18 0 0.243896 0.767578 -11 10 19 0 0.253418 0.833496 -11 10 20 0 0.257812 0.874023 -11 10 21 0 0.253662 0.880371 -11 10 22 0 0.251465 0.887207 -11 10 23 0 0.250244 0.894531 -11 10 24 0 0.249878 0.901855 -11 10 25 0 0.250244 0.910156 -11 10 26 0 0.250732 0.918945 -11 10 27 0 0.251953 0.929199 -11 10 28 0 0.253906 0.940918 -11 10 29 0 0.256104 0.953125 -11 10 30 0 0.258545 0.96582 -11 10 31 0 0.260986 0.979004 -11 11 0 0.276123 0.253418 0.0795288 -11 11 1 0.276123 0.253418 0.0795288 -11 11 2 0.276123 0.253418 0.0795288 -11 11 3 0.276123 0.253418 0.0795288 -11 11 4 0.276123 0.253418 0.0795288 -11 11 5 0.276123 0.253662 0.0795898 -11 11 6 0.276367 0.253662 0.0795898 -11 11 7 0.275635 0.253662 0.0877075 -11 11 8 0.272217 0.252197 0.118408 -11 11 9 0.265869 0.249146 0.154053 -11 11 10 0.254395 0.243896 0.193726 -11 11 11 0.234741 0.234741 0.234741 -11 11 12 0.219727 0.238403 0.295166 -11 11 13 0.187988 0.242798 0.36499 -11 11 14 0.0969849 0.247314 0.442627 -11 11 15 0 0.252197 0.524902 -11 11 16 0 0.257812 0.610352 -11 11 17 0 0.263672 0.692383 -11 11 18 0 0.269775 0.767578 -11 11 19 0 0.275635 0.833984 -11 11 20 0 0.276855 0.875488 -11 11 21 0 0.269531 0.881348 -11 11 22 0 0.264648 0.888184 -11 11 23 0 0.261719 0.895508 -11 11 24 0 0.259766 0.902832 -11 11 25 0 0.258789 0.910645 -11 11 26 0 0.258301 0.919922 -11 11 27 0 0.258545 0.929688 -11 11 28 0 0.259521 0.941406 -11 11 29 0 0.260742 0.953613 -11 11 30 0 0.262695 0.966309 -11 11 31 0 0.264648 0.979492 -11 12 0 0.242188 0.302002 0.0758057 -11 12 1 0.242188 0.302002 0.0758057 -11 12 2 0.242188 0.302002 0.0758057 -11 12 3 0.242188 0.302002 0.0758057 -11 12 4 0.242188 0.302002 0.0758057 -11 12 5 0.242188 0.302002 0.0758057 -11 12 6 0.24231 0.302246 0.0758667 -11 12 7 0.24231 0.30249 0.0758667 -11 12 8 0.239746 0.301025 0.105286 -11 12 9 0.233887 0.297852 0.143677 -11 12 10 0.223755 0.292969 0.185303 -11 12 11 0.210205 0.289795 0.233398 -11 12 12 0.19043 0.292236 0.293701 -11 12 13 0.146729 0.29541 0.36377 -11 12 14 0 0.29834 0.44165 -11 12 15 0 0.300781 0.524902 -11 12 16 0 0.302979 0.610352 -11 12 17 0 0.304688 0.692871 -11 12 18 0 0.306396 0.768555 -11 12 19 0 0.30835 0.834473 -11 12 20 0 0.305664 0.87793 -11 12 21 0 0.293701 0.883789 -11 12 22 0 0.2854 0.890137 -11 12 23 0 0.279541 0.896973 -11 12 24 0 0.275635 0.903809 -11 12 25 0 0.272461 0.912109 -11 12 26 0 0.270508 0.920898 -11 12 27 0 0.269043 0.930664 -11 12 28 0 0.268555 0.941895 -11 12 29 0 0.268799 0.954102 -11 12 30 0 0.269531 0.966797 -11 12 31 0 0.270752 0.97998 -11 13 0 0.184326 0.357422 0.0717163 -11 13 1 0.184326 0.357422 0.0717163 -11 13 2 0.184326 0.357422 0.0717163 -11 13 3 0.184326 0.357422 0.0717773 -11 13 4 0.184326 0.357422 0.0717773 -11 13 5 0.184326 0.357422 0.0717773 -11 13 6 0.184448 0.357422 0.0717773 -11 13 7 0.18457 0.357666 0.0718384 -11 13 8 0.184082 0.357666 0.0836792 -11 13 9 0.178955 0.356689 0.130615 -11 13 10 0.169556 0.355469 0.177734 -11 13 11 0.151978 0.355225 0.230225 -11 13 12 0.112366 0.356689 0.291504 -11 13 13 0 0.358643 0.361572 -11 13 14 0 0.360107 0.439941 -11 13 15 0 0.360596 0.523438 -11 13 16 0 0.359863 0.610352 -11 13 17 0 0.357666 0.693359 -11 13 18 0 0.35498 0.769043 -11 13 19 0 0.352295 0.835449 -11 13 20 0 0.345947 0.881348 -11 13 21 0 0.328125 0.886719 -11 13 22 0 0.315186 0.893066 -11 13 23 0 0.305908 0.899414 -11 13 24 0 0.298828 0.90625 -11 13 25 0 0.293213 0.914062 -11 13 26 0 0.288574 0.922852 -11 13 27 0 0.285156 0.932617 -11 13 28 0 0.282959 0.943359 -11 13 29 0 0.28125 0.955566 -11 13 30 0 0.280518 0.968262 -11 13 31 0 0.280273 0.980957 -11 14 0 0 0.429443 0.0686035 -11 14 1 0 0.429443 0.0686035 -11 14 2 0 0.429443 0.0686035 -11 14 3 0 0.429443 0.0686035 -11 14 4 0 0.429443 0.0686035 -11 14 5 0 0.429443 0.0686035 -11 14 6 0 0.429443 0.0686035 -11 14 7 0 0.429688 0.0686646 -11 14 8 0 0.429688 0.0687256 -11 14 9 0 0.429932 0.11084 -11 14 10 0 0.429932 0.166626 -11 14 11 0 0.430176 0.223389 -11 14 12 0 0.430908 0.286621 -11 14 13 0 0.431885 0.357666 -11 14 14 0 0.432129 0.436523 -11 14 15 0 0.431152 0.521484 -11 14 16 0 0.428223 0.609375 -11 14 17 0 0.422852 0.693359 -11 14 18 0 0.416016 0.77002 -11 14 19 0 0.408691 0.836914 -11 14 20 0 0.398682 0.886719 -11 14 21 0 0.374512 0.89209 -11 14 22 0 0.355957 0.897949 -11 14 23 0 0.342041 0.903809 -11 14 24 0 0.331543 0.910645 -11 14 25 0 0.32251 0.91748 -11 14 26 0 0.314941 0.925781 -11 14 27 0 0.308594 0.935059 -11 14 28 0 0.303711 0.946289 -11 14 29 0 0.299805 0.95752 -11 14 30 0 0.296875 0.969727 -11 14 31 0 0.294678 0.982422 -11 15 0 0 0.509766 0.0637817 -11 15 1 0 0.509766 0.0637817 -11 15 2 0 0.509766 0.0637817 -11 15 3 0 0.509766 0.0637817 -11 15 4 0 0.509766 0.0637817 -11 15 5 0 0.509766 0.0637817 -11 15 6 0 0.509766 0.0638428 -11 15 7 0 0.509766 0.0639038 -11 15 8 0 0.509766 0.0639648 -11 15 9 0 0.510254 0.0641479 -11 15 10 0 0.510742 0.146362 -11 15 11 0 0.51123 0.210571 -11 15 12 0 0.512207 0.277344 -11 15 13 0 0.512695 0.350098 -11 15 14 0 0.512695 0.43042 -11 15 15 0 0.510742 0.516602 -11 15 16 0 0.506348 0.605957 -11 15 17 0 0.498535 0.691895 -11 15 18 0 0.488037 0.77002 -11 15 19 0 0.476562 0.837891 -11 15 20 0 0.464111 0.892578 -11 15 21 0 0.432861 0.899414 -11 15 22 0 0.408203 0.905273 -11 15 23 0 0.38916 0.910645 -11 15 24 0 0.374512 0.916992 -11 15 25 0 0.361328 0.92334 -11 15 26 0 0.350098 0.931152 -11 15 27 0 0.340088 0.939941 -11 15 28 0 0.332031 0.950195 -11 15 29 0 0.325195 0.961426 -11 15 30 0 0.31958 0.973145 -11 15 31 0 0.314941 0.985352 -11 16 0 0 0.594238 0.0559082 -11 16 1 0 0.594238 0.0559082 -11 16 2 0 0.594238 0.0559082 -11 16 3 0 0.594238 0.0559082 -11 16 4 0 0.594238 0.0559082 -11 16 5 0 0.594238 0.0559387 -11 16 6 0 0.594727 0.0559692 -11 16 7 0 0.594727 0.0559998 -11 16 8 0 0.594727 0.0561218 -11 16 9 0 0.594727 0.0563049 -11 16 10 0 0.595215 0.106384 -11 16 11 0 0.596191 0.189087 -11 16 12 0 0.597168 0.261963 -11 16 13 0 0.598145 0.337891 -11 16 14 0 0.598633 0.419922 -11 16 15 0 0.597656 0.508301 -11 16 16 0 0.592773 0.599609 -11 16 17 0 0.583008 0.6875 -11 16 18 0 0.570312 0.768066 -11 16 19 0 0.555176 0.837891 -11 16 20 0 0.539062 0.89502 -11 16 21 0 0.503906 0.908691 -11 16 22 0 0.4729 0.915527 -11 16 23 0 0.448242 0.921387 -11 16 24 0 0.428467 0.926758 -11 16 25 0 0.410889 0.932617 -11 16 26 0 0.39502 0.939453 -11 16 27 0 0.381104 0.947266 -11 16 28 0 0.369141 0.956543 -11 16 29 0 0.358643 0.966797 -11 16 30 0 0.349609 0.977539 -11 16 31 0 0.341797 0.989258 -11 17 0 0 0.678223 0.0422668 -11 17 1 0 0.678223 0.0422668 -11 17 2 0 0.678223 0.0422668 -11 17 3 0 0.678223 0.0422668 -11 17 4 0 0.678223 0.0422668 -11 17 5 0 0.678223 0.0422974 -11 17 6 0 0.678223 0.0423279 -11 17 7 0 0.678223 0.0424194 -11 17 8 0 0.678223 0.042572 -11 17 9 0 0.678711 0.0428467 -11 17 10 0 0.678711 0.043335 -11 17 11 0 0.679688 0.154419 -11 17 12 0 0.681152 0.239502 -11 17 13 0 0.683105 0.319824 -11 17 14 0 0.68457 0.404541 -11 17 15 0 0.684082 0.494385 -11 17 16 0 0.680176 0.587891 -11 17 17 0 0.670898 0.679199 -11 17 18 0 0.657227 0.762695 -11 17 19 0 0.639648 0.834961 -11 17 20 0 0.620117 0.894531 -11 17 21 0 0.583984 0.917969 -11 17 22 0 0.547852 0.928711 -11 17 23 0 0.518066 0.935059 -11 17 24 0 0.49292 0.94043 -11 17 25 0 0.470215 0.945801 -11 17 26 0 0.449463 0.95166 -11 17 27 0 0.430664 0.958008 -11 17 28 0 0.414307 0.96582 -11 17 29 0 0.399658 0.975098 -11 17 30 0 0.386719 0.984863 -11 17 31 0 0.375244 0.995117 -11 18 0 0 0.756348 0 -11 18 1 0 0.756348 0 -11 18 2 0 0.756348 0 -11 18 3 0 0.756348 0 -11 18 4 0 0.756348 0 -11 18 5 0 0.756348 0 -11 18 6 0 0.756348 0 -11 18 7 0 0.756348 0 -11 18 8 0 0.756348 0 -11 18 9 0 0.756348 0 -11 18 10 0 0.756836 0 -11 18 11 0 0.757324 0.0843506 -11 18 12 0 0.758789 0.208252 -11 18 13 0 0.76123 0.296143 -11 18 14 0 0.763672 0.383545 -11 18 15 0 0.765137 0.475098 -11 18 16 0 0.763184 0.570801 -11 18 17 0 0.755859 0.665039 -11 18 18 0 0.743164 0.751953 -11 18 19 0 0.725098 0.828125 -11 18 20 0 0.704102 0.890625 -11 18 21 0 0.668945 0.925781 -11 18 22 0 0.630371 0.942871 -11 18 23 0 0.595703 0.952148 -11 18 24 0 0.565918 0.958008 -11 18 25 0 0.537598 0.963379 -11 18 26 0 0.511719 0.967773 -11 18 27 0 0.487793 0.973145 -11 18 28 0 0.466309 0.979492 -11 18 29 0 0.447021 0.986328 -11 18 30 0 0.429688 0.994629 -11 18 31 0 0.414062 1 -11 19 0 0 0.826172 0 -11 19 1 0 0.826172 0 -11 19 2 0 0.826172 0 -11 19 3 0 0.826172 0 -11 19 4 0 0.826172 0 -11 19 5 0 0.826172 0 -11 19 6 0 0.826172 0 -11 19 7 0 0.826172 0 -11 19 8 0 0.82666 0 -11 19 9 0 0.82666 0 -11 19 10 0 0.82666 0 -11 19 11 0 0.827148 0 -11 19 12 0 0.828125 0.164551 -11 19 13 0 0.831055 0.267334 -11 19 14 0 0.833984 0.358887 -11 19 15 0 0.836914 0.452148 -11 19 16 0 0.836914 0.549316 -11 19 17 0 0.833008 0.645508 -11 19 18 0 0.822754 0.736328 -11 19 19 0 0.806152 0.815918 -11 19 20 0 0.784668 0.881836 -11 19 21 0 0.753418 0.928223 -11 19 22 0 0.715332 0.95459 -11 19 23 0 0.678223 0.969238 -11 19 24 0 0.644043 0.977539 -11 19 25 0 0.611328 0.983398 -11 19 26 0 0.57959 0.987305 -11 19 27 0 0.550293 0.991211 -11 19 28 0 0.523438 0.995605 -11 19 29 0 0.499268 1 -11 19 30 0 0.477051 1 -11 19 31 0 0.457275 1 -11 20 0 0 0.886719 0 -11 20 1 0 0.886719 0 -11 20 2 0 0.886719 0 -11 20 3 0 0.886719 0 -11 20 4 0 0.886719 0 -11 20 5 0 0.886719 0 -11 20 6 0 0.886719 0 -11 20 7 0 0.886719 0 -11 20 8 0 0.886719 0 -11 20 9 0 0.887207 0 -11 20 10 0 0.887207 0 -11 20 11 0 0.887207 0 -11 20 12 0 0.887695 0.0847168 -11 20 13 0 0.890625 0.233276 -11 20 14 0 0.894531 0.331787 -11 20 15 0 0.897949 0.427002 -11 20 16 0 0.900391 0.524902 -11 20 17 0 0.899414 0.622559 -11 20 18 0 0.89209 0.71582 -11 20 19 0 0.87793 0.798828 -11 20 20 0 0.85791 0.868652 -11 20 21 0 0.831055 0.923828 -11 20 22 0 0.796387 0.960449 -11 20 23 0 0.759277 0.982422 -11 20 24 0 0.723145 0.994629 -11 20 25 0 0.686523 1 -11 20 26 0 0.650391 1 -11 20 27 0 0.616211 1 -11 20 28 0 0.583984 1 -11 20 29 0 0.554199 1 -11 20 30 0 0.527344 1 -11 20 31 0 0.50293 1 -11 21 0 0 0.938477 0 -11 21 1 0 0.938477 0 -11 21 2 0 0.938477 0 -11 21 3 0 0.938477 0 -11 21 4 0 0.938477 0 -11 21 5 0 0.938477 0 -11 21 6 0 0.938477 0 -11 21 7 0 0.938477 0 -11 21 8 0 0.938477 0 -11 21 9 0 0.938477 0 -11 21 10 0 0.938477 0 -11 21 11 0 0.938477 0 -11 21 12 0 0.938965 0 -11 21 13 0 0.941406 0.190918 -11 21 14 0 0.945312 0.301514 -11 21 15 0 0.949707 0.399658 -11 21 16 0 0.954102 0.498047 -11 21 17 0 0.955078 0.59668 -11 21 18 0 0.951172 0.690918 -11 21 19 0 0.94043 0.776367 -11 21 20 0 0.922852 0.849609 -11 21 21 0 0.899902 0.911133 -11 21 22 0 0.870605 0.958008 -11 21 23 0 0.836426 0.988281 -11 21 24 0 0.800293 1 -11 21 25 0 0.761719 1 -11 21 26 0 0.722656 1 -11 21 27 0 0.684082 1 -11 21 28 0 0.646973 1 -11 21 29 0 0.612305 1 -11 21 30 0 0.580566 1 -11 21 31 0 0.55127 1 -11 22 0 0 0.980957 0 -11 22 1 0 0.980957 0 -11 22 2 0 0.980957 0 -11 22 3 0 0.980957 0 -11 22 4 0 0.980957 0 -11 22 5 0 0.980957 0 -11 22 6 0 0.980957 0 -11 22 7 0 0.980957 0 -11 22 8 0 0.980957 0 -11 22 9 0 0.980957 0 -11 22 10 0 0.980957 0 -11 22 11 0 0.981445 0 -11 22 12 0 0.981445 0 -11 22 13 0 0.98291 0.130737 -11 22 14 0 0.986816 0.268311 -11 22 15 0 0.992188 0.370605 -11 22 16 0 0.997559 0.469971 -11 22 17 0 1 0.568359 -11 22 18 0 0.999512 0.663574 -11 22 19 0 0.992676 0.750977 -11 22 20 0 0.978516 0.827148 -11 22 21 0 0.958984 0.89209 -11 22 22 0 0.933594 0.945312 -11 22 23 0 0.904297 0.983887 -11 22 24 0 0.871094 1 -11 22 25 0 0.833008 1 -11 22 26 0 0.79248 1 -11 22 27 0 0.750977 1 -11 22 28 0 0.710449 1 -11 22 29 0 0.671387 1 -11 22 30 0 0.634766 1 -11 22 31 0 0.600586 1 -11 23 0 0 1 0 -11 23 1 0 1 0 -11 23 2 0 1 0 -11 23 3 0 1 0 -11 23 4 0 1 0 -11 23 5 0 1 0 -11 23 6 0 1 0 -11 23 7 0 1 0 -11 23 8 0 1 0 -11 23 9 0 1 0 -11 23 10 0 1 0 -11 23 11 0 1 0 -11 23 12 0 1 0 -11 23 13 0 1 0 -11 23 14 0 1 0.232666 -11 23 15 0 1 0.341797 -11 23 16 0 1 0.442139 -11 23 17 0 1 0.540527 -11 23 18 0 1 0.635254 -11 23 19 0 1 0.723633 -11 23 20 0 1 0.801758 -11 23 21 0 1 0.870117 -11 23 22 0 0.984863 0.926758 -11 23 23 0 0.959473 0.97168 -11 23 24 0 0.930664 1 -11 23 25 0 0.895508 1 -11 23 26 0 0.855469 1 -11 23 27 0 0.812988 1 -11 23 28 0 0.77002 1 -11 23 29 0 0.727539 1 -11 23 30 0 0.6875 1 -11 23 31 0 0.649414 1 -11 24 0 0 1 0 -11 24 1 0 1 0 -11 24 2 0 1 0 -11 24 3 0 1 0 -11 24 4 0 1 0 -11 24 5 0 1 0 -11 24 6 0 1 0 -11 24 7 0 1 0 -11 24 8 0 1 0 -11 24 9 0 1 0 -11 24 10 0 1 0 -11 24 11 0 1 0 -11 24 12 0 1 0 -11 24 13 0 1 0 -11 24 14 0 1 0.192383 -11 24 15 0 1 0.312744 -11 24 16 0 1 0.415039 -11 24 17 0 1 0.512695 -11 24 18 0 1 0.607422 -11 24 19 0 1 0.695801 -11 24 20 0 1 0.774902 -11 24 21 0 1 0.845215 -11 24 22 0 1 0.905273 -11 24 23 0 1 0.953613 -11 24 24 0 0.97998 0.992188 -11 24 25 0 0.94873 1 -11 24 26 0 0.911621 1 -11 24 27 0 0.869629 1 -11 24 28 0 0.825684 1 -11 24 29 0 0.780762 1 -11 24 30 0 0.737793 1 -11 24 31 0 0.696289 1 -11 25 0 0 1 0 -11 25 1 0 1 0 -11 25 2 0 1 0 -11 25 3 0 1 0 -11 25 4 0 1 0 -11 25 5 0 1 0 -11 25 6 0 1 0 -11 25 7 0 1 0 -11 25 8 0 1 0 -11 25 9 0 1 0 -11 25 10 0 1 0 -11 25 11 0 1 0 -11 25 12 0 1 0 -11 25 13 0 1 0 -11 25 14 0 1 0.134155 -11 25 15 0 1 0.280273 -11 25 16 0 1 0.385498 -11 25 17 0 1 0.483154 -11 25 18 0 1 0.57666 -11 25 19 0 1 0.664551 -11 25 20 0 1 0.744629 -11 25 21 0 1 0.816895 -11 25 22 0 1 0.879395 -11 25 23 0 1 0.930664 -11 25 24 0 1 0.973145 -11 25 25 0 0.997559 1 -11 25 26 0 0.964355 1 -11 25 27 0 0.924805 1 -11 25 28 0 0.880859 1 -11 25 29 0 0.835449 1 -11 25 30 0 0.790039 1 -11 25 31 0 0.745605 1 -11 26 0 0 1 0 -11 26 1 0 1 0 -11 26 2 0 1 0 -11 26 3 0 1 0 -11 26 4 0 1 0 -11 26 5 0 1 0 -11 26 6 0 1 0 -11 26 7 0 1 0 -11 26 8 0 1 0 -11 26 9 0 1 0 -11 26 10 0 1 0 -11 26 11 0 1 0 -11 26 12 0 1 0 -11 26 13 0 1 0 -11 26 14 0 1 0 -11 26 15 0 1 0.242676 -11 26 16 0 1 0.35376 -11 26 17 0 1 0.45166 -11 26 18 0 1 0.543945 -11 26 19 0 1 0.631348 -11 26 20 0 1 0.711426 -11 26 21 0 1 0.78418 -11 26 22 0 1 0.849121 -11 26 23 0 1 0.90332 -11 26 24 0 1 0.948242 -11 26 25 0 1 0.989258 -11 26 26 0 1 1 -11 26 27 0 0.976562 1 -11 26 28 0 0.935059 1 -11 26 29 0 0.889648 1 -11 26 30 0 0.843262 1 -11 26 31 0 0.796875 1 -11 27 0 0 1 0 -11 27 1 0 1 0 -11 27 2 0 1 0 -11 27 3 0 1 0 -11 27 4 0 1 0 -11 27 5 0 1 0 -11 27 6 0 1 0 -11 27 7 0 1 0 -11 27 8 0 1 0 -11 27 9 0 1 0 -11 27 10 0 1 0 -11 27 11 0 1 0 -11 27 12 0 1 0 -11 27 13 0 1 0 -11 27 14 0 1 0 -11 27 15 0 1 0.196289 -11 27 16 0 1 0.319092 -11 27 17 0 1 0.418213 -11 27 18 0 1 0.509766 -11 27 19 0 1 0.595703 -11 27 20 0 1 0.674805 -11 27 21 0 1 0.748535 -11 27 22 0 1 0.814453 -11 27 23 0 1 0.870605 -11 27 24 0 1 0.918945 -11 27 25 0 1 0.962891 -11 27 26 0 1 1 -11 27 27 0 1 1 -11 27 28 0 0.986328 1 -11 27 29 0 0.942383 1 -11 27 30 0 0.895996 1 -11 27 31 0 0.848145 1 -11 28 0 0 1 0 -11 28 1 0 1 0 -11 28 2 0 1 0 -11 28 3 0 1 0 -11 28 4 0 1 0 -11 28 5 0 1 0 -11 28 6 0 1 0 -11 28 7 0 1 0 -11 28 8 0 1 0 -11 28 9 0 1 0 -11 28 10 0 1 0 -11 28 11 0 1 0 -11 28 12 0 1 0 -11 28 13 0 1 0 -11 28 14 0 1 0 -11 28 15 0 1 0.128052 -11 28 16 0 1 0.281006 -11 28 17 0 1 0.383057 -11 28 18 0 1 0.474121 -11 28 19 0 1 0.558594 -11 28 20 0 1 0.636719 -11 28 21 0 1 0.709473 -11 28 22 0 1 0.775879 -11 28 23 0 1 0.833984 -11 28 24 0 1 0.883789 -11 28 25 0 1 0.931152 -11 28 26 0 1 0.975098 -11 28 27 0 1 1 -11 28 28 0 1 1 -11 28 29 0 0.992188 1 -11 28 30 0 0.947266 1 -11 28 31 0 0.900391 1 -11 29 0 0 1 0 -11 29 1 0 1 0 -11 29 2 0 1 0 -11 29 3 0 1 0 -11 29 4 0 1 0 -11 29 5 0 1 0 -11 29 6 0 1 0 -11 29 7 0 1 0 -11 29 8 0 1 0 -11 29 9 0 1 0 -11 29 10 0 1 0 -11 29 11 0 1 0 -11 29 12 0 1 0 -11 29 13 0 1 0 -11 29 14 0 1 0 -11 29 15 0 1 0 -11 29 16 0 1 0.237061 -11 29 17 0 1 0.345703 -11 29 18 0 1 0.436768 -11 29 19 0 1 0.52002 -11 29 20 0 1 0.596191 -11 29 21 0 1 0.667969 -11 29 22 0 1 0.734375 -11 29 23 0 1 0.79248 -11 29 24 0 1 0.844238 -11 29 25 0 1 0.893555 -11 29 26 0 1 0.94043 -11 29 27 0 1 0.98291 -11 29 28 0 1 1 -11 29 29 0 1 1 -11 29 30 0 0.99707 1 -11 29 31 0 0.95166 1 -11 30 0 0 1 0 -11 30 1 0 1 0 -11 30 2 0 1 0 -11 30 3 0 1 0 -11 30 4 0 1 0 -11 30 5 0 1 0 -11 30 6 0 1 0 -11 30 7 0 1 0 -11 30 8 0 1 0 -11 30 9 0 1 0 -11 30 10 0 1 0 -11 30 11 0 1 0 -11 30 12 0 1 0 -11 30 13 0 1 0 -11 30 14 0 1 0 -11 30 15 0 1 0 -11 30 16 0 1 0.182617 -11 30 17 0 1 0.305176 -11 30 18 0 1 0.397705 -11 30 19 0 1 0.479736 -11 30 20 0 1 0.554199 -11 30 21 0 1 0.624512 -11 30 22 0 1 0.689941 -11 30 23 0 1 0.748047 -11 30 24 0 1 0.800293 -11 30 25 0 1 0.851074 -11 30 26 0 1 0.900391 -11 30 27 0 1 0.946289 -11 30 28 0 1 0.988281 -11 30 29 0 1 1 -11 30 30 0 1 1 -11 30 31 0 1 1 -11 31 0 0 1 0 -11 31 1 0 1 0 -11 31 2 0 1 0 -11 31 3 0 1 0 -11 31 4 0 1 0 -11 31 5 0 1 0 -11 31 6 0 1 0 -11 31 7 0 1 0 -11 31 8 0 1 0 -11 31 9 0 1 0 -11 31 10 0 1 0 -11 31 11 0 1 0 -11 31 12 0 1 0 -11 31 13 0 1 0 -11 31 14 0 1 0 -11 31 15 0 1 0 -11 31 16 0 1 0.0888672 -11 31 17 0 1 0.260986 -11 31 18 0 1 0.357178 -11 31 19 0 1 0.438477 -11 31 20 0 1 0.51123 -11 31 21 0 1 0.57959 -11 31 22 0 1 0.643555 -11 31 23 0 1 0.700684 -11 31 24 0 1 0.75293 -11 31 25 0 1 0.804688 -11 31 26 0 1 0.855469 -11 31 27 0 1 0.905273 -11 31 28 0 1 0.951172 -11 31 29 0 1 0.993164 -11 31 30 0 1 1 -11 31 31 0 1 1 -12 0 0 0.438232 0 0.0275726 -12 0 1 0.438232 0 0.0275574 -12 0 2 0.438232 0 0.0275269 -12 0 3 0.438232 0 0.0274658 -12 0 4 0.438232 0 0.0273438 -12 0 5 0.438232 0 0.0271301 -12 0 6 0.438232 0 0.0266876 -12 0 7 0.440186 0 0.0262604 -12 0 8 0.445557 0 0.0808105 -12 0 9 0.445312 0 0.163696 -12 0 10 0.427734 0 0.226318 -12 0 11 0.362793 0.0745239 0.25708 -12 0 12 0.329346 0.11145 0.298584 -12 0 13 0.314453 0.122742 0.367188 -12 0 14 0.2854 0.137085 0.443848 -12 0 15 0.229004 0.153931 0.525879 -12 0 16 0 0.172485 0.611328 -12 0 17 0 0.19104 0.693359 -12 0 18 0 0.208618 0.768066 -12 0 19 0 0.224365 0.833984 -12 0 20 0 0.234131 0.875977 -12 0 21 0 0.234741 0.882324 -12 0 22 0 0.23584 0.88916 -12 0 23 0 0.237183 0.895996 -12 0 24 0 0.238647 0.90332 -12 0 25 0 0.240479 0.911621 -12 0 26 0 0.242554 0.92041 -12 0 27 0 0.244873 0.930176 -12 0 28 0 0.247681 0.941895 -12 0 29 0 0.250732 0.954102 -12 0 30 0 0.253906 0.966797 -12 0 31 0 0.25708 0.97998 -12 1 0 0.438232 0 0.0273438 -12 1 1 0.438232 0 0.0273285 -12 1 2 0.438232 0 0.027298 -12 1 3 0.438232 0 0.0272369 -12 1 4 0.438232 0 0.0271149 -12 1 5 0.438232 0 0.026886 -12 1 6 0.438232 0 0.0264435 -12 1 7 0.440186 0 0.0260162 -12 1 8 0.445557 0 0.0807495 -12 1 9 0.445068 0 0.163696 -12 1 10 0.427734 0 0.226318 -12 1 11 0.362793 0.0750732 0.25708 -12 1 12 0.329346 0.111633 0.298584 -12 1 13 0.314453 0.122986 0.367188 -12 1 14 0.2854 0.137329 0.443848 -12 1 15 0.228882 0.154053 0.525879 -12 1 16 0 0.172607 0.611328 -12 1 17 0 0.191162 0.693359 -12 1 18 0 0.208618 0.768066 -12 1 19 0 0.224365 0.833984 -12 1 20 0 0.234131 0.875977 -12 1 21 0 0.234741 0.882324 -12 1 22 0 0.23584 0.88916 -12 1 23 0 0.237183 0.895996 -12 1 24 0 0.238647 0.90332 -12 1 25 0 0.240479 0.911621 -12 1 26 0 0.242554 0.92041 -12 1 27 0 0.244873 0.930176 -12 1 28 0 0.247681 0.941895 -12 1 29 0 0.250732 0.954102 -12 1 30 0 0.253906 0.966797 -12 1 31 0 0.25708 0.97998 -12 2 0 0.438232 0 0.0269318 -12 2 1 0.438232 0 0.0269165 -12 2 2 0.438232 0 0.0268707 -12 2 3 0.438232 0 0.0268097 -12 2 4 0.438232 0 0.0266876 -12 2 5 0.438232 0 0.0264587 -12 2 6 0.438232 0 0.026001 -12 2 7 0.440186 0 0.0255585 -12 2 8 0.445557 0 0.0806885 -12 2 9 0.445068 0 0.163574 -12 2 10 0.427734 0 0.226318 -12 2 11 0.362793 0.0759888 0.25708 -12 2 12 0.329346 0.112061 0.298584 -12 2 13 0.314453 0.123352 0.367188 -12 2 14 0.2854 0.137573 0.443848 -12 2 15 0.228882 0.154297 0.525879 -12 2 16 0 0.172729 0.611328 -12 2 17 0 0.191284 0.693359 -12 2 18 0 0.20874 0.768066 -12 2 19 0 0.224487 0.833984 -12 2 20 0 0.234253 0.875977 -12 2 21 0 0.234863 0.882324 -12 2 22 0 0.23584 0.88916 -12 2 23 0 0.237183 0.895996 -12 2 24 0 0.238647 0.90332 -12 2 25 0 0.240479 0.911621 -12 2 26 0 0.242554 0.92041 -12 2 27 0 0.244873 0.930176 -12 2 28 0 0.247681 0.941895 -12 2 29 0 0.250732 0.954102 -12 2 30 0 0.253906 0.966797 -12 2 31 0 0.25708 0.97998 -12 3 0 0.438232 0 0.0261383 -12 3 1 0.438232 0 0.026123 -12 3 2 0.438232 0 0.0260925 -12 3 3 0.438232 0 0.0260162 -12 3 4 0.438232 0 0.0258942 -12 3 5 0.438232 0 0.02565 -12 3 6 0.437988 0 0.0251617 -12 3 7 0.439941 0 0.0246887 -12 3 8 0.445312 0 0.0804443 -12 3 9 0.445068 0 0.163452 -12 3 10 0.427734 0 0.226318 -12 3 11 0.363037 0.0775757 0.25708 -12 3 12 0.329346 0.112854 0.298584 -12 3 13 0.314453 0.124023 0.367188 -12 3 14 0.2854 0.138184 0.443848 -12 3 15 0.22876 0.154663 0.525879 -12 3 16 0 0.173096 0.611328 -12 3 17 0 0.191528 0.693359 -12 3 18 0 0.208984 0.768066 -12 3 19 0 0.224609 0.833984 -12 3 20 0 0.234375 0.875977 -12 3 21 0 0.234863 0.882324 -12 3 22 0 0.235962 0.88916 -12 3 23 0 0.237305 0.895996 -12 3 24 0 0.23877 0.90332 -12 3 25 0 0.240479 0.911621 -12 3 26 0 0.242554 0.92041 -12 3 27 0 0.244995 0.930176 -12 3 28 0 0.247681 0.941895 -12 3 29 0 0.250732 0.954102 -12 3 30 0 0.253906 0.966797 -12 3 31 0 0.257324 0.97998 -12 4 0 0.437988 0 0.0245361 -12 4 1 0.437988 0 0.0245209 -12 4 2 0.437988 0 0.0244751 -12 4 3 0.437988 0 0.0243988 -12 4 4 0.437988 0 0.0242615 -12 4 5 0.437988 0 0.0239868 -12 4 6 0.437988 0 0.0234528 -12 4 7 0.439941 0 0.0229034 -12 4 8 0.445312 0 0.0800781 -12 4 9 0.445068 0 0.16333 -12 4 10 0.427734 0 0.226318 -12 4 11 0.363037 0.0805054 0.257324 -12 4 12 0.329346 0.114258 0.298584 -12 4 13 0.314209 0.125244 0.367188 -12 4 14 0.285156 0.13916 0.443848 -12 4 15 0.228638 0.155518 0.525879 -12 4 16 0 0.173828 0.611328 -12 4 17 0 0.192139 0.693359 -12 4 18 0 0.209473 0.768066 -12 4 19 0 0.224976 0.833984 -12 4 20 0 0.234619 0.875977 -12 4 21 0 0.235107 0.882324 -12 4 22 0 0.236084 0.88916 -12 4 23 0 0.237427 0.895996 -12 4 24 0 0.238892 0.90332 -12 4 25 0 0.240601 0.911621 -12 4 26 0 0.242676 0.92041 -12 4 27 0 0.244995 0.930176 -12 4 28 0 0.247803 0.941895 -12 4 29 0 0.250732 0.954102 -12 4 30 0 0.253906 0.966797 -12 4 31 0 0.257324 0.97998 -12 5 0 0.4375 0 0.0208435 -12 5 1 0.4375 0 0.020813 -12 5 2 0.4375 0 0.0207672 -12 5 3 0.4375 0 0.0206604 -12 5 4 0.4375 0 0.0204926 -12 5 5 0.4375 0 0.0201263 -12 5 6 0.4375 0 0.0194092 -12 5 7 0.439453 0 0.0186157 -12 5 8 0.444824 0 0.0792847 -12 5 9 0.44458 0 0.162964 -12 5 10 0.427734 0 0.226196 -12 5 11 0.363281 0.0857544 0.257568 -12 5 12 0.329102 0.116943 0.298584 -12 5 13 0.313965 0.127563 0.366943 -12 5 14 0.284912 0.141113 0.443848 -12 5 15 0.228271 0.157104 0.525879 -12 5 16 0 0.175049 0.611328 -12 5 17 0 0.193115 0.693359 -12 5 18 0 0.210205 0.768066 -12 5 19 0 0.225708 0.833984 -12 5 20 0 0.235107 0.875977 -12 5 21 0 0.235596 0.882324 -12 5 22 0 0.23645 0.88916 -12 5 23 0 0.237671 0.895996 -12 5 24 0 0.239136 0.90332 -12 5 25 0 0.240845 0.911621 -12 5 26 0 0.24292 0.92041 -12 5 27 0 0.245239 0.930176 -12 5 28 0 0.247925 0.941895 -12 5 29 0 0.250977 0.954102 -12 5 30 0 0.25415 0.966797 -12 5 31 0 0.257324 0.97998 -12 6 0 0.436768 0.00949097 0 -12 6 1 0.436768 0.0113525 0 -12 6 2 0.436768 0.0138092 0 -12 6 3 0.436768 0.0170441 0 -12 6 4 0.436768 0.0213623 0 -12 6 5 0.436768 0.0270996 0 -12 6 6 0.436523 0.0345459 0 -12 6 7 0.438477 0.0409546 0 -12 6 8 0.444336 0.0390015 0.0778809 -12 6 9 0.444092 0 0.162231 -12 6 10 0.42749 0 0.226074 -12 6 11 0.363525 0.0946045 0.257812 -12 6 12 0.328613 0.121765 0.29834 -12 6 13 0.313721 0.131836 0.366943 -12 6 14 0.284668 0.144775 0.443848 -12 6 15 0.227661 0.160156 0.525879 -12 6 16 0 0.177368 0.611328 -12 6 17 0 0.194946 0.693359 -12 6 18 0 0.211792 0.768066 -12 6 19 0 0.226929 0.833984 -12 6 20 0 0.236206 0.875977 -12 6 21 0 0.236328 0.882324 -12 6 22 0 0.237183 0.88916 -12 6 23 0 0.238281 0.895996 -12 6 24 0 0.239624 0.90332 -12 6 25 0 0.241211 0.911621 -12 6 26 0 0.243164 0.92041 -12 6 27 0 0.245483 0.930176 -12 6 28 0 0.248169 0.941895 -12 6 29 0 0.251221 0.954102 -12 6 30 0 0.25415 0.966797 -12 6 31 0 0.257568 0.97998 -12 7 0 0.434814 0.0875854 0 -12 7 1 0.434814 0.0876465 0 -12 7 2 0.434814 0.0877686 0 -12 7 3 0.434814 0.0879517 0 -12 7 4 0.434814 0.0883179 0 -12 7 5 0.434814 0.0890503 0 -12 7 6 0.43457 0.0903931 0 -12 7 7 0.436523 0.0922241 0 -12 7 8 0.442627 0.0925903 0.0753174 -12 7 9 0.442627 0.085144 0.160889 -12 7 10 0.42749 0.0765381 0.225586 -12 7 11 0.364258 0.109009 0.258545 -12 7 12 0.327881 0.130371 0.29834 -12 7 13 0.312988 0.139526 0.366943 -12 7 14 0.283691 0.151367 0.443848 -12 7 15 0.226562 0.165649 0.525879 -12 7 16 0 0.181885 0.611328 -12 7 17 0 0.198608 0.693359 -12 7 18 0 0.2146 0.768066 -12 7 19 0 0.229248 0.833984 -12 7 20 0 0.238037 0.875977 -12 7 21 0 0.237915 0.882324 -12 7 22 0 0.238403 0.88916 -12 7 23 0 0.23938 0.896484 -12 7 24 0 0.240479 0.90332 -12 7 25 0 0.242065 0.911621 -12 7 26 0 0.243896 0.92041 -12 7 27 0 0.246094 0.930664 -12 7 28 0 0.248657 0.941895 -12 7 29 0 0.251465 0.954102 -12 7 30 0 0.254639 0.966797 -12 7 31 0 0.257812 0.97998 -12 8 0 0.430176 0.131958 0 -12 8 1 0.430176 0.131958 0 -12 8 2 0.430176 0.131958 0 -12 8 3 0.430176 0.13208 0 -12 8 4 0.430176 0.132324 0 -12 8 5 0.429932 0.13269 0 -12 8 6 0.429932 0.133301 0 -12 8 7 0.431641 0.134644 0 -12 8 8 0.437988 0.135864 0.071106 -12 8 9 0.438721 0.131958 0.158081 -12 8 10 0.426025 0.124878 0.224487 -12 8 11 0.365967 0.13147 0.260254 -12 8 12 0.32666 0.14502 0.298096 -12 8 13 0.311523 0.152954 0.366943 -12 8 14 0.281982 0.163208 0.443848 -12 8 15 0.224243 0.175781 0.525879 -12 8 16 0 0.190308 0.611328 -12 8 17 0 0.205444 0.693359 -12 8 18 0 0.220215 0.768555 -12 8 19 0 0.233765 0.834473 -12 8 20 0 0.241821 0.876465 -12 8 21 0 0.240845 0.882324 -12 8 22 0 0.240845 0.88916 -12 8 23 0 0.241333 0.896484 -12 8 24 0 0.24231 0.903809 -12 8 25 0 0.24353 0.911621 -12 8 26 0 0.245239 0.92041 -12 8 27 0 0.247192 0.930664 -12 8 28 0 0.249634 0.941895 -12 8 29 0 0.252441 0.954102 -12 8 30 0 0.255371 0.966797 -12 8 31 0 0.258545 0.97998 -12 9 0 0.418213 0.177002 0 -12 9 1 0.418213 0.177002 0 -12 9 2 0.418213 0.177124 0 -12 9 3 0.418213 0.177124 0 -12 9 4 0.418213 0.177246 0 -12 9 5 0.418213 0.177368 0 -12 9 6 0.417969 0.177734 0 -12 9 7 0.419189 0.178711 0 -12 9 8 0.425781 0.180908 0.067688 -12 9 9 0.42749 0.179443 0.152832 -12 9 10 0.419922 0.174072 0.220703 -12 9 11 0.369629 0.164795 0.263672 -12 9 12 0.323975 0.167969 0.297852 -12 9 13 0.308594 0.174438 0.366699 -12 9 14 0.278809 0.182739 0.443604 -12 9 15 0.219604 0.192749 0.525879 -12 9 16 0 0.204834 0.611328 -12 9 17 0 0.217529 0.693359 -12 9 18 0 0.230103 0.768555 -12 9 19 0 0.242065 0.834473 -12 9 20 0 0.248657 0.876953 -12 9 21 0 0.24646 0.882812 -12 9 22 0 0.245483 0.889648 -12 9 23 0 0.245239 0.896484 -12 9 24 0 0.245605 0.903809 -12 9 25 0 0.24646 0.911621 -12 9 26 0 0.247681 0.920898 -12 9 27 0 0.249268 0.930664 -12 9 28 0 0.251465 0.941895 -12 9 29 0 0.253906 0.954102 -12 9 30 0 0.256592 0.966797 -12 9 31 0 0.259521 0.97998 -12 10 0 0.392334 0.219238 0 -12 10 1 0.392334 0.219238 0 -12 10 2 0.392334 0.219238 0 -12 10 3 0.392334 0.21936 0 -12 10 4 0.392334 0.21936 0 -12 10 5 0.39209 0.219482 0 -12 10 6 0.39209 0.219604 0 -12 10 7 0.39209 0.220093 0 -12 10 8 0.395752 0.222046 0.0787354 -12 10 9 0.39917 0.223511 0.146362 -12 10 10 0.404297 0.224976 0.212769 -12 10 11 0.376709 0.213135 0.269775 -12 10 12 0.319336 0.200073 0.297363 -12 10 13 0.303467 0.205078 0.366211 -12 10 14 0.272705 0.211426 0.443359 -12 10 15 0.210815 0.21875 0.525879 -12 10 16 0 0.227661 0.611328 -12 10 17 0 0.237061 0.693359 -12 10 18 0 0.246704 0.768555 -12 10 19 0 0.256104 0.834473 -12 10 20 0 0.260498 0.877441 -12 10 21 0 0.256104 0.883789 -12 10 22 0 0.253418 0.890137 -12 10 23 0 0.251953 0.896973 -12 10 24 0 0.251465 0.904297 -12 10 25 0 0.251465 0.912109 -12 10 26 0 0.251953 0.920898 -12 10 27 0 0.253174 0.931152 -12 10 28 0 0.254883 0.942383 -12 10 29 0 0.256836 0.95459 -12 10 30 0 0.259033 0.967285 -12 10 31 0 0.261719 0.97998 -12 11 0 0.357178 0.255859 0.0759888 -12 11 1 0.357178 0.255859 0.0759888 -12 11 2 0.357178 0.255859 0.0760498 -12 11 3 0.357178 0.255859 0.0760498 -12 11 4 0.357178 0.255859 0.0761108 -12 11 5 0.357178 0.255859 0.0761719 -12 11 6 0.357178 0.256104 0.0762939 -12 11 7 0.357178 0.256348 0.0765381 -12 11 8 0.356689 0.256592 0.107056 -12 11 9 0.355469 0.257324 0.148315 -12 11 10 0.35498 0.259277 0.196777 -12 11 11 0.36377 0.268311 0.26416 -12 11 12 0.310547 0.242065 0.296387 -12 11 13 0.293945 0.245972 0.365479 -12 11 14 0.26123 0.250488 0.442871 -12 11 15 0.193726 0.255127 0.525879 -12 11 16 0 0.260742 0.611328 -12 11 17 0 0.266357 0.693848 -12 11 18 0 0.272217 0.769043 -12 11 19 0 0.278076 0.834961 -12 11 20 0 0.279541 0.878906 -12 11 21 0 0.271729 0.884766 -12 11 22 0 0.266602 0.891113 -12 11 23 0 0.263428 0.897949 -12 11 24 0 0.26123 0.905273 -12 11 25 0 0.26001 0.913086 -12 11 26 0 0.259521 0.921875 -12 11 27 0 0.259521 0.931641 -12 11 28 0 0.260498 0.942871 -12 11 29 0 0.261719 0.955078 -12 11 30 0 0.263428 0.967285 -12 11 31 0 0.265381 0.980469 -12 12 0 0.344238 0.315918 0.0991211 -12 12 1 0.344238 0.315918 0.0991211 -12 12 2 0.344238 0.315918 0.0991211 -12 12 3 0.344238 0.315918 0.0991211 -12 12 4 0.344238 0.315918 0.0991211 -12 12 5 0.344238 0.315918 0.0991211 -12 12 6 0.344238 0.316162 0.0991821 -12 12 7 0.344238 0.316162 0.0991821 -12 12 8 0.343262 0.316162 0.114197 -12 12 9 0.339355 0.314453 0.15332 -12 12 10 0.331787 0.311523 0.197144 -12 12 11 0.318115 0.30542 0.245239 -12 12 12 0.294922 0.294922 0.294922 -12 12 13 0.276123 0.297852 0.364258 -12 12 14 0.239868 0.300781 0.442139 -12 12 15 0.15686 0.303223 0.525391 -12 12 16 0 0.30542 0.611328 -12 12 17 0 0.307129 0.694336 -12 12 18 0 0.308594 0.769531 -12 12 19 0 0.310303 0.835938 -12 12 20 0 0.30835 0.881348 -12 12 21 0 0.295898 0.886719 -12 12 22 0 0.287109 0.893066 -12 12 23 0 0.28125 0.899414 -12 12 24 0 0.2771 0.90625 -12 12 25 0 0.273926 0.914062 -12 12 26 0 0.271484 0.922852 -12 12 27 0 0.27002 0.932617 -12 12 28 0 0.269531 0.943848 -12 12 29 0 0.269775 0.955566 -12 12 30 0 0.270264 0.968262 -12 12 31 0 0.271484 0.980957 -12 13 0 0.303223 0.370605 0.0942993 -12 13 1 0.303223 0.370605 0.0942993 -12 13 2 0.303223 0.370605 0.0942993 -12 13 3 0.303223 0.37085 0.0942993 -12 13 4 0.303223 0.37085 0.0942993 -12 13 5 0.303223 0.37085 0.0942993 -12 13 6 0.303223 0.37085 0.0942993 -12 13 7 0.303223 0.371094 0.0942993 -12 13 8 0.303467 0.371338 0.0943604 -12 13 9 0.299805 0.369629 0.137817 -12 13 10 0.293213 0.366699 0.184204 -12 13 11 0.281738 0.361816 0.234497 -12 13 12 0.265625 0.358398 0.29248 -12 13 13 0.242554 0.360352 0.362061 -12 13 14 0.195679 0.361816 0.440186 -12 13 15 0 0.362305 0.524414 -12 13 16 0 0.361816 0.61084 -12 13 17 0 0.359619 0.694336 -12 13 18 0 0.356934 0.77002 -12 13 19 0 0.354004 0.836914 -12 13 20 0 0.348389 0.884766 -12 13 21 0 0.330322 0.889648 -12 13 22 0 0.316895 0.895996 -12 13 23 0 0.307373 0.902344 -12 13 24 0 0.300293 0.908691 -12 13 25 0 0.294434 0.916016 -12 13 26 0 0.289795 0.924805 -12 13 27 0 0.286133 0.934082 -12 13 28 0 0.283691 0.945312 -12 13 29 0 0.282227 0.957031 -12 13 30 0 0.28125 0.969238 -12 13 31 0 0.281006 0.981934 -12 14 0 0.239868 0.434082 0.0894775 -12 14 1 0.239868 0.434082 0.0895386 -12 14 2 0.239868 0.434082 0.0895386 -12 14 3 0.239868 0.434082 0.0895386 -12 14 4 0.239868 0.434082 0.0895386 -12 14 5 0.239868 0.434082 0.0895386 -12 14 6 0.239868 0.434326 0.0895386 -12 14 7 0.23999 0.434326 0.0895386 -12 14 8 0.240234 0.43457 0.0895996 -12 14 9 0.238647 0.434326 0.115417 -12 14 10 0.232666 0.43335 0.169434 -12 14 11 0.221924 0.432373 0.225098 -12 14 12 0.202637 0.432129 0.287354 -12 14 13 0.16394 0.432861 0.358154 -12 14 14 0 0.43335 0.437012 -12 14 15 0 0.432617 0.521973 -12 14 16 0 0.429688 0.609863 -12 14 17 0 0.424316 0.694336 -12 14 18 0 0.41748 0.770996 -12 14 19 0 0.410156 0.837891 -12 14 20 0 0.400879 0.889648 -12 14 21 0 0.376221 0.894531 -12 14 22 0 0.357666 0.900391 -12 14 23 0 0.343506 0.90625 -12 14 24 0 0.332764 0.912598 -12 14 25 0 0.32373 0.919434 -12 14 26 0 0.315918 0.927734 -12 14 27 0 0.30957 0.937012 -12 14 28 0 0.304443 0.947754 -12 14 29 0 0.300537 0.958984 -12 14 30 0 0.297363 0.971191 -12 14 31 0 0.295166 0.983398 -12 15 0 0 0.511719 0.0854492 -12 15 1 0 0.511719 0.0854492 -12 15 2 0 0.511719 0.0854492 -12 15 3 0 0.511719 0.0854492 -12 15 4 0 0.511719 0.0854492 -12 15 5 0 0.511719 0.0854492 -12 15 6 0 0.511719 0.0854492 -12 15 7 0 0.511719 0.0854492 -12 15 8 0 0.511719 0.0855103 -12 15 9 0 0.512207 0.0856323 -12 15 10 0 0.512207 0.148926 -12 15 11 0 0.512207 0.211914 -12 15 12 0 0.512695 0.278076 -12 15 13 0 0.513672 0.350586 -12 15 14 0 0.513672 0.430908 -12 15 15 0 0.511719 0.51709 -12 15 16 0 0.507812 0.606445 -12 15 17 0 0.499756 0.692383 -12 15 18 0 0.489502 0.770508 -12 15 19 0 0.478027 0.838867 -12 15 20 0 0.46582 0.894531 -12 15 21 0 0.43457 0.901367 -12 15 22 0 0.409668 0.907227 -12 15 23 0 0.390625 0.912598 -12 15 24 0 0.375732 0.918457 -12 15 25 0 0.362549 0.925293 -12 15 26 0 0.351074 0.932617 -12 15 27 0 0.341064 0.941406 -12 15 28 0 0.332764 0.95166 -12 15 29 0 0.325928 0.962402 -12 15 30 0 0.320068 0.974121 -12 15 31 0 0.31543 0.986328 -12 16 0 0 0.595703 0.079895 -12 16 1 0 0.595703 0.079895 -12 16 2 0 0.595703 0.079895 -12 16 3 0 0.595703 0.079895 -12 16 4 0 0.595703 0.079895 -12 16 5 0 0.595703 0.079895 -12 16 6 0 0.595703 0.079895 -12 16 7 0 0.595703 0.0799561 -12 16 8 0 0.595703 0.0800171 -12 16 9 0 0.596191 0.0800781 -12 16 10 0 0.59668 0.110168 -12 16 11 0 0.597168 0.190796 -12 16 12 0 0.598145 0.262939 -12 16 13 0 0.599121 0.338379 -12 16 14 0 0.599609 0.42041 -12 16 15 0 0.598145 0.508301 -12 16 16 0 0.593262 0.600098 -12 16 17 0 0.584473 0.688477 -12 16 18 0 0.571289 0.768555 -12 16 19 0 0.556152 0.838379 -12 16 20 0 0.540039 0.895996 -12 16 21 0 0.505371 0.910645 -12 16 22 0 0.474121 0.916992 -12 16 23 0 0.449463 0.922852 -12 16 24 0 0.429688 0.928223 -12 16 25 0 0.411865 0.934082 -12 16 26 0 0.395996 0.940918 -12 16 27 0 0.381836 0.948242 -12 16 28 0 0.369873 0.95752 -12 16 29 0 0.359375 0.967773 -12 16 30 0 0.350098 0.978516 -12 16 31 0 0.342285 0.990234 -12 17 0 0 0.679688 0.0718994 -12 17 1 0 0.679688 0.0718994 -12 17 2 0 0.679688 0.0718994 -12 17 3 0 0.679688 0.0718994 -12 17 4 0 0.679688 0.0718994 -12 17 5 0 0.679688 0.0718994 -12 17 6 0 0.679688 0.0719604 -12 17 7 0 0.679688 0.0719604 -12 17 8 0 0.679688 0.0720215 -12 17 9 0 0.679688 0.0721436 -12 17 10 0 0.680176 0.0723877 -12 17 11 0 0.680664 0.156616 -12 17 12 0 0.682129 0.240601 -12 17 13 0 0.683594 0.320557 -12 17 14 0 0.685059 0.405029 -12 17 15 0 0.68457 0.494629 -12 17 16 0 0.680664 0.588379 -12 17 17 0 0.671875 0.679688 -12 17 18 0 0.657715 0.763184 -12 17 19 0 0.640625 0.835938 -12 17 20 0 0.621094 0.89502 -12 17 21 0 0.585449 0.919434 -12 17 22 0 0.548828 0.929688 -12 17 23 0 0.519043 0.936523 -12 17 24 0 0.493896 0.941406 -12 17 25 0 0.470947 0.946777 -12 17 26 0 0.450195 0.952637 -12 17 27 0 0.431396 0.958984 -12 17 28 0 0.414795 0.966797 -12 17 29 0 0.400146 0.976074 -12 17 30 0 0.387207 0.985352 -12 17 31 0 0.375732 0.996094 -12 18 0 0 0.757324 0.0604858 -12 18 1 0 0.757324 0.0604858 -12 18 2 0 0.757324 0.0604858 -12 18 3 0 0.757812 0.0604858 -12 18 4 0 0.757812 0.0604858 -12 18 5 0 0.757812 0.0604858 -12 18 6 0 0.757812 0.0605164 -12 18 7 0 0.757812 0.0605469 -12 18 8 0 0.757812 0.0606384 -12 18 9 0 0.757812 0.060791 -12 18 10 0 0.757812 0.0610352 -12 18 11 0 0.758301 0.0890503 -12 18 12 0 0.760254 0.209473 -12 18 13 0 0.762207 0.296875 -12 18 14 0 0.764648 0.384277 -12 18 15 0 0.765625 0.475586 -12 18 16 0 0.763672 0.571289 -12 18 17 0 0.756836 0.665527 -12 18 18 0 0.743652 0.752441 -12 18 19 0 0.726074 0.828613 -12 18 20 0 0.70459 0.891113 -12 18 21 0 0.669922 0.926758 -12 18 22 0 0.631348 0.943848 -12 18 23 0 0.59668 0.953125 -12 18 24 0 0.566406 0.958984 -12 18 25 0 0.538574 0.963867 -12 18 26 0 0.512207 0.96875 -12 18 27 0 0.488281 0.973633 -12 18 28 0 0.466797 0.97998 -12 18 29 0 0.44751 0.987305 -12 18 30 0 0.430176 0.995117 -12 18 31 0 0.414551 1 -12 19 0 0 0.827637 0.0426941 -12 19 1 0 0.827637 0.0426941 -12 19 2 0 0.827637 0.0426941 -12 19 3 0 0.827637 0.0426941 -12 19 4 0 0.827637 0.0427246 -12 19 5 0 0.827637 0.0427246 -12 19 6 0 0.827637 0.0427551 -12 19 7 0 0.827637 0.0428162 -12 19 8 0 0.827637 0.0429688 -12 19 9 0 0.827637 0.0431824 -12 19 10 0 0.828125 0.0436096 -12 19 11 0 0.828125 0.044342 -12 19 12 0 0.82959 0.166138 -12 19 13 0 0.832031 0.268311 -12 19 14 0 0.834961 0.359619 -12 19 15 0 0.837402 0.452637 -12 19 16 0 0.837891 0.549805 -12 19 17 0 0.833496 0.645996 -12 19 18 0 0.823242 0.736816 -12 19 19 0 0.806641 0.816406 -12 19 20 0 0.785156 0.882324 -12 19 21 0 0.753906 0.928711 -12 19 22 0 0.71582 0.955078 -12 19 23 0 0.678711 0.969727 -12 19 24 0 0.644531 0.978027 -12 19 25 0 0.611816 0.983887 -12 19 26 0 0.580078 0.987793 -12 19 27 0 0.550781 0.991699 -12 19 28 0 0.523926 0.996094 -12 19 29 0 0.499512 1 -12 19 30 0 0.477539 1 -12 19 31 0 0.45752 1 -12 20 0 0 0.888184 0 -12 20 1 0 0.888184 0 -12 20 2 0 0.888184 0 -12 20 3 0 0.888184 0 -12 20 4 0 0.888184 0 -12 20 5 0 0.888184 0 -12 20 6 0 0.888184 0 -12 20 7 0 0.888184 0 -12 20 8 0 0.888184 0 -12 20 9 0 0.888184 0 -12 20 10 0 0.888184 0 -12 20 11 0 0.888672 0 -12 20 12 0 0.88916 0.0886841 -12 20 13 0 0.891602 0.234375 -12 20 14 0 0.895508 0.33252 -12 20 15 0 0.898926 0.42749 -12 20 16 0 0.901367 0.525391 -12 20 17 0 0.899902 0.623047 -12 20 18 0 0.892578 0.71582 -12 20 19 0 0.878418 0.798828 -12 20 20 0 0.858398 0.868652 -12 20 21 0 0.831543 0.924316 -12 20 22 0 0.796875 0.960938 -12 20 23 0 0.759766 0.98291 -12 20 24 0 0.723633 0.995117 -12 20 25 0 0.687012 1 -12 20 26 0 0.650879 1 -12 20 27 0 0.616699 1 -12 20 28 0 0.584473 1 -12 20 29 0 0.554688 1 -12 20 30 0 0.527832 1 -12 20 31 0 0.503418 1 -12 21 0 0 0.939453 0 -12 21 1 0 0.939453 0 -12 21 2 0 0.939453 0 -12 21 3 0 0.939453 0 -12 21 4 0 0.939453 0 -12 21 5 0 0.939453 0 -12 21 6 0 0.939453 0 -12 21 7 0 0.939453 0 -12 21 8 0 0.939453 0 -12 21 9 0 0.939453 0 -12 21 10 0 0.939941 0 -12 21 11 0 0.939941 0 -12 21 12 0 0.939941 0 -12 21 13 0 0.942383 0.192017 -12 21 14 0 0.946289 0.302246 -12 21 15 0 0.950684 0.400146 -12 21 16 0 0.95459 0.498535 -12 21 17 0 0.955566 0.59668 -12 21 18 0 0.95166 0.691406 -12 21 19 0 0.940918 0.776855 -12 21 20 0 0.923828 0.850098 -12 21 21 0 0.900879 0.911621 -12 21 22 0 0.871094 0.958496 -12 21 23 0 0.836914 0.988281 -12 21 24 0 0.800781 1 -12 21 25 0 0.762207 1 -12 21 26 0 0.723145 1 -12 21 27 0 0.684082 1 -12 21 28 0 0.647461 1 -12 21 29 0 0.612793 1 -12 21 30 0 0.580566 1 -12 21 31 0 0.55127 1 -12 22 0 0 0.981934 0 -12 22 1 0 0.981934 0 -12 22 2 0 0.981934 0 -12 22 3 0 0.981934 0 -12 22 4 0 0.981934 0 -12 22 5 0 0.981934 0 -12 22 6 0 0.981934 0 -12 22 7 0 0.981934 0 -12 22 8 0 0.982422 0 -12 22 9 0 0.982422 0 -12 22 10 0 0.982422 0 -12 22 11 0 0.982422 0 -12 22 12 0 0.982422 0 -12 22 13 0 0.983887 0.132446 -12 22 14 0 0.987793 0.269043 -12 22 15 0 0.993164 0.371338 -12 22 16 0 0.998047 0.470459 -12 22 17 0 1 0.568848 -12 22 18 0 1 0.663574 -12 22 19 0 0.993164 0.750977 -12 22 20 0 0.979492 0.827148 -12 22 21 0 0.959473 0.892578 -12 22 22 0 0.934082 0.945801 -12 22 23 0 0.904785 0.984375 -12 22 24 0 0.871582 1 -12 22 25 0 0.833496 1 -12 22 26 0 0.792969 1 -12 22 27 0 0.751465 1 -12 22 28 0 0.710449 1 -12 22 29 0 0.671387 1 -12 22 30 0 0.634766 1 -12 22 31 0 0.601074 1 -12 23 0 0 1 0 -12 23 1 0 1 0 -12 23 2 0 1 0 -12 23 3 0 1 0 -12 23 4 0 1 0 -12 23 5 0 1 0 -12 23 6 0 1 0 -12 23 7 0 1 0 -12 23 8 0 1 0 -12 23 9 0 1 0 -12 23 10 0 1 0 -12 23 11 0 1 0 -12 23 12 0 1 0 -12 23 13 0 1 0 -12 23 14 0 1 0.233521 -12 23 15 0 1 0.342529 -12 23 16 0 1 0.442627 -12 23 17 0 1 0.540527 -12 23 18 0 1 0.635742 -12 23 19 0 1 0.724121 -12 23 20 0 1 0.802246 -12 23 21 0 1 0.870117 -12 23 22 0 0.985352 0.927246 -12 23 23 0 0.959961 0.97168 -12 23 24 0 0.931152 1 -12 23 25 0 0.895996 1 -12 23 26 0 0.855957 1 -12 23 27 0 0.813477 1 -12 23 28 0 0.770508 1 -12 23 29 0 0.728027 1 -12 23 30 0 0.6875 1 -12 23 31 0 0.649414 1 -12 24 0 0 1 0 -12 24 1 0 1 0 -12 24 2 0 1 0 -12 24 3 0 1 0 -12 24 4 0 1 0 -12 24 5 0 1 0 -12 24 6 0 1 0 -12 24 7 0 1 0 -12 24 8 0 1 0 -12 24 9 0 1 0 -12 24 10 0 1 0 -12 24 11 0 1 0 -12 24 12 0 1 0 -12 24 13 0 1 0 -12 24 14 0 1 0.193237 -12 24 15 0 1 0.313477 -12 24 16 0 1 0.415527 -12 24 17 0 1 0.513184 -12 24 18 0 1 0.607422 -12 24 19 0 1 0.695801 -12 24 20 0 1 0.775391 -12 24 21 0 1 0.845703 -12 24 22 0 1 0.905762 -12 24 23 0 1 0.953613 -12 24 24 0 0.980469 0.992676 -12 24 25 0 0.949219 1 -12 24 26 0 0.911621 1 -12 24 27 0 0.870117 1 -12 24 28 0 0.825684 1 -12 24 29 0 0.78125 1 -12 24 30 0 0.737793 1 -12 24 31 0 0.696289 1 -12 25 0 0 1 0 -12 25 1 0 1 0 -12 25 2 0 1 0 -12 25 3 0 1 0 -12 25 4 0 1 0 -12 25 5 0 1 0 -12 25 6 0 1 0 -12 25 7 0 1 0 -12 25 8 0 1 0 -12 25 9 0 1 0 -12 25 10 0 1 0 -12 25 11 0 1 0 -12 25 12 0 1 0 -12 25 13 0 1 0 -12 25 14 0 1 0.135498 -12 25 15 0 1 0.280762 -12 25 16 0 1 0.385986 -12 25 17 0 1 0.483398 -12 25 18 0 1 0.577148 -12 25 19 0 1 0.665039 -12 25 20 0 1 0.745117 -12 25 21 0 1 0.816895 -12 25 22 0 1 0.879395 -12 25 23 0 1 0.931152 -12 25 24 0 1 0.973145 -12 25 25 0 0.998047 1 -12 25 26 0 0.964355 1 -12 25 27 0 0.924805 1 -12 25 28 0 0.881348 1 -12 25 29 0 0.835938 1 -12 25 30 0 0.790039 1 -12 25 31 0 0.745605 1 -12 26 0 0 1 0 -12 26 1 0 1 0 -12 26 2 0 1 0 -12 26 3 0 1 0 -12 26 4 0 1 0 -12 26 5 0 1 0 -12 26 6 0 1 0 -12 26 7 0 1 0 -12 26 8 0 1 0 -12 26 9 0 1 0 -12 26 10 0 1 0 -12 26 11 0 1 0 -12 26 12 0 1 0 -12 26 13 0 1 0 -12 26 14 0 1 0 -12 26 15 0 1 0.243164 -12 26 16 0 1 0.354248 -12 26 17 0 1 0.451904 -12 26 18 0 1 0.544434 -12 26 19 0 1 0.631836 -12 26 20 0 1 0.711426 -12 26 21 0 1 0.784668 -12 26 22 0 1 0.849121 -12 26 23 0 1 0.90332 -12 26 24 0 1 0.94873 -12 26 25 0 1 0.989746 -12 26 26 0 1 1 -12 26 27 0 0.977051 1 -12 26 28 0 0.935547 1 -12 26 29 0 0.890137 1 -12 26 30 0 0.843262 1 -12 26 31 0 0.796875 1 -12 27 0 0 1 0 -12 27 1 0 1 0 -12 27 2 0 1 0 -12 27 3 0 1 0 -12 27 4 0 1 0 -12 27 5 0 1 0 -12 27 6 0 1 0 -12 27 7 0 1 0 -12 27 8 0 1 0 -12 27 9 0 1 0 -12 27 10 0 1 0 -12 27 11 0 1 0 -12 27 12 0 1 0 -12 27 13 0 1 0 -12 27 14 0 1 0 -12 27 15 0 1 0.196899 -12 27 16 0 1 0.31958 -12 27 17 0 1 0.418701 -12 27 18 0 1 0.510254 -12 27 19 0 1 0.596191 -12 27 20 0 1 0.675293 -12 27 21 0 1 0.748535 -12 27 22 0 1 0.814453 -12 27 23 0 1 0.871094 -12 27 24 0 1 0.918945 -12 27 25 0 1 0.963379 -12 27 26 0 1 1 -12 27 27 0 1 1 -12 27 28 0 0.986328 1 -12 27 29 0 0.942871 1 -12 27 30 0 0.895996 1 -12 27 31 0 0.848633 1 -12 28 0 0 1 0 -12 28 1 0 1 0 -12 28 2 0 1 0 -12 28 3 0 1 0 -12 28 4 0 1 0 -12 28 5 0 1 0 -12 28 6 0 1 0 -12 28 7 0 1 0 -12 28 8 0 1 0 -12 28 9 0 1 0 -12 28 10 0 1 0 -12 28 11 0 1 0 -12 28 12 0 1 0 -12 28 13 0 1 0 -12 28 14 0 1 0 -12 28 15 0 1 0.129028 -12 28 16 0 1 0.281494 -12 28 17 0 1 0.383545 -12 28 18 0 1 0.474365 -12 28 19 0 1 0.559082 -12 28 20 0 1 0.637207 -12 28 21 0 1 0.709961 -12 28 22 0 1 0.776367 -12 28 23 0 1 0.833984 -12 28 24 0 1 0.884277 -12 28 25 0 1 0.931641 -12 28 26 0 1 0.975098 -12 28 27 0 1 1 -12 28 28 0 1 1 -12 28 29 0 0.992188 1 -12 28 30 0 0.947754 1 -12 28 31 0 0.900391 1 -12 29 0 0 1 0 -12 29 1 0 1 0 -12 29 2 0 1 0 -12 29 3 0 1 0 -12 29 4 0 1 0 -12 29 5 0 1 0 -12 29 6 0 1 0 -12 29 7 0 1 0 -12 29 8 0 1 0 -12 29 9 0 1 0 -12 29 10 0 1 0 -12 29 11 0 1 0 -12 29 12 0 1 0 -12 29 13 0 1 0 -12 29 14 0 1 0 -12 29 15 0 1 0 -12 29 16 0 1 0.237549 -12 29 17 0 1 0.345947 -12 29 18 0 1 0.437012 -12 29 19 0 1 0.52002 -12 29 20 0 1 0.59668 -12 29 21 0 1 0.668457 -12 29 22 0 1 0.734375 -12 29 23 0 1 0.792969 -12 29 24 0 1 0.844238 -12 29 25 0 1 0.894043 -12 29 26 0 1 0.940918 -12 29 27 0 1 0.983398 -12 29 28 0 1 1 -12 29 29 0 1 1 -12 29 30 0 0.99707 1 -12 29 31 0 0.95166 1 -12 30 0 0 1 0 -12 30 1 0 1 0 -12 30 2 0 1 0 -12 30 3 0 1 0 -12 30 4 0 1 0 -12 30 5 0 1 0 -12 30 6 0 1 0 -12 30 7 0 1 0 -12 30 8 0 1 0 -12 30 9 0 1 0 -12 30 10 0 1 0 -12 30 11 0 1 0 -12 30 12 0 1 0 -12 30 13 0 1 0 -12 30 14 0 1 0 -12 30 15 0 1 0 -12 30 16 0 1 0.182983 -12 30 17 0 1 0.30542 -12 30 18 0 1 0.397949 -12 30 19 0 1 0.47998 -12 30 20 0 1 0.554688 -12 30 21 0 1 0.625 -12 30 22 0 1 0.689941 -12 30 23 0 1 0.748047 -12 30 24 0 1 0.800293 -12 30 25 0 1 0.851074 -12 30 26 0 1 0.900391 -12 30 27 0 1 0.946777 -12 30 28 0 1 0.98877 -12 30 29 0 1 1 -12 30 30 0 1 1 -12 30 31 0 1 1 -12 31 0 0 1 0 -12 31 1 0 1 0 -12 31 2 0 1 0 -12 31 3 0 1 0 -12 31 4 0 1 0 -12 31 5 0 1 0 -12 31 6 0 1 0 -12 31 7 0 1 0 -12 31 8 0 1 0 -12 31 9 0 1 0 -12 31 10 0 1 0 -12 31 11 0 1 0 -12 31 12 0 1 0 -12 31 13 0 1 0 -12 31 14 0 1 0 -12 31 15 0 1 0 -12 31 16 0 1 0.0899048 -12 31 17 0 1 0.26123 -12 31 18 0 1 0.357422 -12 31 19 0 1 0.438721 -12 31 20 0 1 0.511719 -12 31 21 0 1 0.580078 -12 31 22 0 1 0.643555 -12 31 23 0 1 0.701172 -12 31 24 0 1 0.75293 -12 31 25 0 1 0.804688 -12 31 26 0 1 0.855957 -12 31 27 0 1 0.905273 -12 31 28 0 1 0.951172 -12 31 29 0 1 0.993164 -12 31 30 0 1 1 -12 31 31 0 1 1 -13 0 0 0.491211 0 0.0305328 -13 0 1 0.491211 0 0.0305328 -13 0 2 0.491211 0 0.0305023 -13 0 3 0.491211 0 0.0304718 -13 0 4 0.491211 0 0.0303802 -13 0 5 0.491211 0 0.0302429 -13 0 6 0.491211 0 0.029953 -13 0 7 0.491211 0 0.0293732 -13 0 8 0.493408 0 0.0289307 -13 0 9 0.497803 0 0.112427 -13 0 10 0.499023 0 0.195312 -13 0 11 0.486816 0 0.266602 -13 0 12 0.432129 0.103699 0.310791 -13 0 13 0.406006 0.137085 0.36792 -13 0 14 0.386475 0.149292 0.444336 -13 0 15 0.352539 0.16394 0.526855 -13 0 16 0.293701 0.180786 0.612305 -13 0 17 0.171631 0.197876 0.694824 -13 0 18 0 0.214233 0.77002 -13 0 19 0 0.229004 0.836426 -13 0 20 0 0.238892 0.881348 -13 0 21 0 0.238647 0.887207 -13 0 22 0 0.239258 0.894043 -13 0 23 0 0.240112 0.900879 -13 0 24 0 0.241333 0.907715 -13 0 25 0 0.242798 0.915039 -13 0 26 0 0.244507 0.923828 -13 0 27 0 0.246704 0.933594 -13 0 28 0 0.249268 0.944336 -13 0 29 0 0.251953 0.956543 -13 0 30 0 0.255127 0.96875 -13 0 31 0 0.258301 0.981445 -13 1 0 0.491211 0 0.0303802 -13 1 1 0.491211 0 0.0303802 -13 1 2 0.491211 0 0.0303497 -13 1 3 0.491211 0 0.030304 -13 1 4 0.491211 0 0.0302277 -13 1 5 0.491211 0 0.0300751 -13 1 6 0.491211 0 0.0297852 -13 1 7 0.491211 0 0.0292053 -13 1 8 0.493408 0 0.0287628 -13 1 9 0.497803 0 0.112427 -13 1 10 0.499023 0 0.195312 -13 1 11 0.486816 0 0.266602 -13 1 12 0.432129 0.104004 0.310791 -13 1 13 0.406006 0.137329 0.36792 -13 1 14 0.386475 0.149414 0.444336 -13 1 15 0.352539 0.164062 0.526855 -13 1 16 0.293701 0.180908 0.612305 -13 1 17 0.171509 0.197998 0.694824 -13 1 18 0 0.214233 0.77002 -13 1 19 0 0.229004 0.836426 -13 1 20 0 0.238892 0.881348 -13 1 21 0 0.23877 0.887207 -13 1 22 0 0.239258 0.894043 -13 1 23 0 0.240112 0.900879 -13 1 24 0 0.241333 0.907715 -13 1 25 0 0.242798 0.915039 -13 1 26 0 0.244629 0.923828 -13 1 27 0 0.246704 0.933594 -13 1 28 0 0.249268 0.944336 -13 1 29 0 0.251953 0.956543 -13 1 30 0 0.255127 0.96875 -13 1 31 0 0.258301 0.981445 -13 2 0 0.491211 0 0.0301056 -13 2 1 0.491211 0 0.0300903 -13 2 2 0.491211 0 0.0300751 -13 2 3 0.491211 0 0.0300293 -13 2 4 0.491211 0 0.029953 -13 2 5 0.491211 0 0.0298004 -13 2 6 0.491211 0 0.0295105 -13 2 7 0.491211 0 0.0289154 -13 2 8 0.493408 0 0.0284576 -13 2 9 0.497803 0 0.112366 -13 2 10 0.499023 0 0.195312 -13 2 11 0.486816 0 0.266602 -13 2 12 0.432129 0.104492 0.310791 -13 2 13 0.406006 0.137573 0.36792 -13 2 14 0.386475 0.149658 0.444336 -13 2 15 0.352539 0.164307 0.526855 -13 2 16 0.293701 0.18103 0.612305 -13 2 17 0.171509 0.19812 0.694824 -13 2 18 0 0.214355 0.77002 -13 2 19 0 0.229126 0.836426 -13 2 20 0 0.239014 0.881348 -13 2 21 0 0.23877 0.887207 -13 2 22 0 0.23938 0.894043 -13 2 23 0 0.240234 0.900879 -13 2 24 0 0.241333 0.907715 -13 2 25 0 0.242798 0.915039 -13 2 26 0 0.244629 0.923828 -13 2 27 0 0.246704 0.933594 -13 2 28 0 0.249268 0.944336 -13 2 29 0 0.252197 0.956543 -13 2 30 0 0.255127 0.96875 -13 2 31 0 0.258301 0.981445 -13 3 0 0.490967 0 0.0295868 -13 3 1 0.490967 0 0.0295868 -13 3 2 0.490967 0 0.0295563 -13 3 3 0.490967 0 0.0295105 -13 3 4 0.490967 0 0.0294342 -13 3 5 0.490967 0 0.0292816 -13 3 6 0.490967 0 0.0289764 -13 3 7 0.490967 0 0.0283661 -13 3 8 0.493408 0 0.0278778 -13 3 9 0.497559 0 0.112244 -13 3 10 0.498779 0 0.195312 -13 3 11 0.486816 0 0.266602 -13 3 12 0.432373 0.105347 0.310791 -13 3 13 0.406006 0.138184 0.36792 -13 3 14 0.386475 0.150146 0.444336 -13 3 15 0.352539 0.164795 0.526855 -13 3 16 0.293701 0.181396 0.612305 -13 3 17 0.171387 0.198364 0.694824 -13 3 18 0 0.2146 0.77002 -13 3 19 0 0.22937 0.836426 -13 3 20 0 0.239136 0.881348 -13 3 21 0 0.238892 0.887207 -13 3 22 0 0.23938 0.894043 -13 3 23 0 0.240234 0.900879 -13 3 24 0 0.241455 0.907715 -13 3 25 0 0.24292 0.915039 -13 3 26 0 0.244629 0.923828 -13 3 27 0 0.246704 0.933594 -13 3 28 0 0.249268 0.944336 -13 3 29 0 0.252197 0.956543 -13 3 30 0 0.255127 0.96875 -13 3 31 0 0.258301 0.981445 -13 4 0 0.490967 0 0.0285797 -13 4 1 0.490967 0 0.0285645 -13 4 2 0.490967 0 0.0285339 -13 4 3 0.490967 0 0.0284882 -13 4 4 0.490967 0 0.0284119 -13 4 5 0.490967 0 0.028244 -13 4 6 0.490967 0 0.0279083 -13 4 7 0.490967 0 0.0272675 -13 4 8 0.493408 0 0.0267487 -13 4 9 0.497559 0 0.112122 -13 4 10 0.498779 0 0.19519 -13 4 11 0.487061 0 0.266602 -13 4 12 0.432373 0.107056 0.310791 -13 4 13 0.405762 0.13916 0.36792 -13 4 14 0.386475 0.151001 0.444336 -13 4 15 0.352295 0.165527 0.526855 -13 4 16 0.293457 0.182007 0.612305 -13 4 17 0.171143 0.198853 0.694824 -13 4 18 0 0.214966 0.77002 -13 4 19 0 0.229614 0.836426 -13 4 20 0 0.23938 0.881348 -13 4 21 0 0.239136 0.887207 -13 4 22 0 0.239624 0.894043 -13 4 23 0 0.240479 0.900879 -13 4 24 0 0.241577 0.907715 -13 4 25 0 0.24292 0.915039 -13 4 26 0 0.244751 0.923828 -13 4 27 0 0.246826 0.933594 -13 4 28 0 0.24939 0.944336 -13 4 29 0 0.252197 0.956543 -13 4 30 0 0.255127 0.96875 -13 4 31 0 0.258301 0.981445 -13 5 0 0.490723 0 0.0264282 -13 5 1 0.490723 0 0.026413 -13 5 2 0.490723 0 0.0263824 -13 5 3 0.490723 0 0.0263214 -13 5 4 0.490723 0 0.0262299 -13 5 5 0.490723 0 0.0260468 -13 5 6 0.490723 0 0.0256653 -13 5 7 0.490723 0 0.0249329 -13 5 8 0.493164 0 0.0243073 -13 5 9 0.497559 0 0.111816 -13 5 10 0.498535 0 0.195068 -13 5 11 0.487061 0 0.266602 -13 5 12 0.432373 0.110168 0.311035 -13 5 13 0.405762 0.141113 0.36792 -13 5 14 0.38623 0.15271 0.444336 -13 5 15 0.352295 0.166992 0.526855 -13 5 16 0.293213 0.183105 0.612305 -13 5 17 0.170654 0.199829 0.694824 -13 5 18 0 0.21582 0.77002 -13 5 19 0 0.230225 0.836426 -13 5 20 0 0.239868 0.881348 -13 5 21 0 0.239502 0.887207 -13 5 22 0 0.23999 0.894043 -13 5 23 0 0.240723 0.900879 -13 5 24 0 0.241821 0.907715 -13 5 25 0 0.243164 0.915039 -13 5 26 0 0.244873 0.923828 -13 5 27 0 0.246948 0.933594 -13 5 28 0 0.249512 0.944824 -13 5 29 0 0.252197 0.956543 -13 5 30 0 0.255371 0.96875 -13 5 31 0 0.258301 0.981445 -13 6 0 0.490479 0 0.0212708 -13 6 1 0.490479 0 0.0212402 -13 6 2 0.490479 0 0.0212097 -13 6 3 0.490479 0 0.0211334 -13 6 4 0.490479 0 0.0209961 -13 6 5 0.490479 0 0.0207214 -13 6 6 0.490479 0 0.0201874 -13 6 7 0.490479 0 0.0190735 -13 6 8 0.492676 0 0.0180359 -13 6 9 0.49707 0 0.111206 -13 6 10 0.498291 0 0.194824 -13 6 11 0.487305 0 0.266602 -13 6 12 0.432373 0.115784 0.311035 -13 6 13 0.405518 0.144775 0.36792 -13 6 14 0.385986 0.156006 0.444336 -13 6 15 0.352051 0.169678 0.526855 -13 6 16 0.292969 0.185425 0.612305 -13 6 17 0.1698 0.20166 0.694824 -13 6 18 0 0.217285 0.77002 -13 6 19 0 0.231445 0.836426 -13 6 20 0 0.240845 0.881348 -13 6 21 0 0.240356 0.887207 -13 6 22 0 0.240601 0.894043 -13 6 23 0 0.241211 0.900879 -13 6 24 0 0.24231 0.907715 -13 6 25 0 0.24353 0.915527 -13 6 26 0 0.245239 0.923828 -13 6 27 0 0.247314 0.933594 -13 6 28 0 0.249756 0.944824 -13 6 29 0 0.252441 0.956543 -13 6 30 0 0.255371 0.96875 -13 6 31 0 0.258545 0.981934 -13 7 0 0.489502 0.0518494 0 -13 7 1 0.489502 0.0519714 0 -13 7 2 0.489502 0.0521545 0 -13 7 3 0.489502 0.0525208 0 -13 7 4 0.489502 0.0532227 0 -13 7 5 0.489502 0.0544739 0 -13 7 6 0.489502 0.0567932 0 -13 7 7 0.489502 0.0608826 0 -13 7 8 0.491943 0.0645142 0 -13 7 9 0.496582 0.0597839 0.110107 -13 7 10 0.497803 0.0416565 0.194214 -13 7 11 0.487793 0.0405884 0.266602 -13 7 12 0.432617 0.12561 0.311523 -13 7 13 0.405029 0.151489 0.367676 -13 7 14 0.385498 0.161865 0.444336 -13 7 15 0.351318 0.174683 0.526855 -13 7 16 0.292236 0.189575 0.612793 -13 7 17 0.168213 0.205078 0.694824 -13 7 18 0 0.220093 0.77002 -13 7 19 0 0.233765 0.836426 -13 7 20 0 0.242798 0.881348 -13 7 21 0 0.241821 0.887207 -13 7 22 0 0.241821 0.894043 -13 7 23 0 0.24231 0.900879 -13 7 24 0 0.243164 0.907715 -13 7 25 0 0.244385 0.915527 -13 7 26 0 0.245972 0.923828 -13 7 27 0 0.247925 0.933594 -13 7 28 0 0.250244 0.944824 -13 7 29 0 0.25293 0.956543 -13 7 30 0 0.255859 0.96875 -13 7 31 0 0.258789 0.981934 -13 8 0 0.487793 0.109985 0 -13 8 1 0.487793 0.110046 0 -13 8 2 0.487793 0.110107 0 -13 8 3 0.487793 0.110229 0 -13 8 4 0.487793 0.110413 0 -13 8 5 0.487793 0.110779 0 -13 8 6 0.487793 0.111572 0 -13 8 7 0.487793 0.112976 0 -13 8 8 0.48999 0.114685 0 -13 8 9 0.494873 0.113464 0.108215 -13 8 10 0.497314 0.107666 0.192993 -13 8 11 0.488281 0.10437 0.266602 -13 8 12 0.432861 0.142212 0.312256 -13 8 13 0.404053 0.163452 0.367676 -13 8 14 0.384521 0.172607 0.444336 -13 8 15 0.350098 0.184082 0.526855 -13 8 16 0.290771 0.19751 0.612793 -13 8 17 0.164795 0.211548 0.694824 -13 8 18 0 0.225342 0.770508 -13 8 19 0 0.238159 0.836426 -13 8 20 0 0.24646 0.881836 -13 8 21 0 0.244873 0.887695 -13 8 22 0 0.244263 0.894043 -13 8 23 0 0.244385 0.900879 -13 8 24 0 0.244873 0.907715 -13 8 25 0 0.24585 0.915527 -13 8 26 0 0.247192 0.923828 -13 8 27 0 0.249023 0.933594 -13 8 28 0 0.251221 0.944824 -13 8 29 0 0.253662 0.956543 -13 8 30 0 0.256592 0.96875 -13 8 31 0 0.259521 0.981934 -13 9 0 0.483398 0.15918 0 -13 9 1 0.483398 0.15918 0 -13 9 2 0.483398 0.159302 0 -13 9 3 0.483398 0.159302 0 -13 9 4 0.483398 0.159424 0 -13 9 5 0.483398 0.159668 0 -13 9 6 0.483398 0.160034 0 -13 9 7 0.483154 0.160767 0 -13 9 8 0.485352 0.162109 0 -13 9 9 0.490479 0.162231 0.105774 -13 9 10 0.495117 0.159546 0.190796 -13 9 11 0.488281 0.155396 0.265869 -13 9 12 0.433838 0.168091 0.313477 -13 9 13 0.4021 0.182983 0.367432 -13 9 14 0.382568 0.190552 0.444092 -13 9 15 0.3479 0.200073 0.526855 -13 9 16 0.287842 0.211304 0.612793 -13 9 17 0.157959 0.223145 0.694824 -13 9 18 0 0.235107 0.770508 -13 9 19 0 0.246216 0.836426 -13 9 20 0 0.253174 0.882324 -13 9 21 0 0.250244 0.888184 -13 9 22 0 0.248779 0.894531 -13 9 23 0 0.248169 0.901367 -13 9 24 0 0.248169 0.908203 -13 9 25 0 0.248779 0.915527 -13 9 26 0 0.249634 0.924316 -13 9 27 0 0.251221 0.933594 -13 9 28 0 0.25293 0.944824 -13 9 29 0 0.255371 0.956543 -13 9 30 0 0.257812 0.969238 -13 9 31 0 0.260742 0.981934 -13 10 0 0.473145 0.209717 0 -13 10 1 0.473145 0.209717 0 -13 10 2 0.473145 0.209839 0 -13 10 3 0.473145 0.209839 0 -13 10 4 0.473145 0.209839 0 -13 10 5 0.473145 0.209961 0 -13 10 6 0.473145 0.210205 0 -13 10 7 0.473145 0.210693 0 -13 10 8 0.474609 0.211914 0 -13 10 9 0.479492 0.213013 0.105713 -13 10 10 0.486084 0.213379 0.186768 -13 10 11 0.483887 0.210449 0.263184 -13 10 12 0.436279 0.205322 0.316406 -13 10 13 0.398682 0.211792 0.366943 -13 10 14 0.378906 0.217651 0.443848 -13 10 15 0.343994 0.224731 0.526855 -13 10 16 0.282471 0.233154 0.612793 -13 10 17 0.144165 0.242188 0.695312 -13 10 18 0 0.251221 0.770508 -13 10 19 0 0.26001 0.836914 -13 10 20 0 0.264893 0.882812 -13 10 21 0 0.26001 0.888672 -13 10 22 0 0.256836 0.89502 -13 10 23 0 0.254883 0.901855 -13 10 24 0 0.25415 0.908203 -13 10 25 0 0.253662 0.916016 -13 10 26 0 0.25415 0.924316 -13 10 27 0 0.254883 0.934082 -13 10 28 0 0.256348 0.945312 -13 10 29 0 0.258057 0.957031 -13 10 30 0 0.260254 0.969238 -13 10 31 0 0.262695 0.981934 -13 11 0 0.453125 0.260254 0 -13 11 1 0.453125 0.260254 0 -13 11 2 0.453125 0.260254 0 -13 11 3 0.453125 0.260254 0 -13 11 4 0.453125 0.260254 0 -13 11 5 0.452881 0.260254 0 -13 11 6 0.452881 0.260498 0 -13 11 7 0.452881 0.260742 0 -13 11 8 0.453125 0.26123 0 -13 11 9 0.455811 0.262695 0.117371 -13 11 10 0.461182 0.265381 0.182983 -13 11 11 0.468262 0.268311 0.255615 -13 11 12 0.44043 0.257812 0.321045 -13 11 13 0.392578 0.250977 0.366211 -13 11 14 0.372314 0.255127 0.443359 -13 11 15 0.336426 0.26001 0.526367 -13 11 16 0.272705 0.265137 0.612793 -13 11 17 0.112976 0.270752 0.695312 -13 11 18 0 0.276123 0.770996 -13 11 19 0 0.281494 0.836914 -13 11 20 0 0.283691 0.884277 -13 11 21 0 0.275391 0.889648 -13 11 22 0 0.269775 0.895996 -13 11 23 0 0.266113 0.902344 -13 11 24 0 0.263916 0.90918 -13 11 25 0 0.262207 0.916504 -13 11 26 0 0.261475 0.925293 -13 11 27 0 0.26123 0.93457 -13 11 28 0 0.261963 0.945801 -13 11 29 0 0.262939 0.95752 -13 11 30 0 0.264404 0.969727 -13 11 31 0 0.266357 0.982422 -13 12 0 0.429199 0.311279 0.100647 -13 12 1 0.429199 0.311279 0.100647 -13 12 2 0.429199 0.311279 0.100647 -13 12 3 0.429199 0.311279 0.100647 -13 12 4 0.429199 0.311279 0.100647 -13 12 5 0.429199 0.311279 0.100708 -13 12 6 0.429199 0.311523 0.100769 -13 12 7 0.429199 0.311768 0.100891 -13 12 8 0.429199 0.312012 0.101135 -13 12 9 0.427734 0.312012 0.141968 -13 12 10 0.425049 0.312256 0.188477 -13 12 11 0.422607 0.313477 0.243042 -13 12 12 0.425293 0.319336 0.314941 -13 12 13 0.381836 0.301514 0.36499 -13 12 14 0.360596 0.304199 0.442383 -13 12 15 0.323242 0.306641 0.525879 -13 12 16 0.254639 0.309082 0.612305 -13 12 17 0 0.310547 0.695801 -13 12 18 0 0.312012 0.771484 -13 12 19 0 0.313477 0.837891 -13 12 20 0 0.312256 0.886719 -13 12 21 0 0.299316 0.891602 -13 12 22 0 0.290283 0.897461 -13 12 23 0 0.283936 0.903809 -13 12 24 0 0.279541 0.910156 -13 12 25 0 0.276123 0.917969 -13 12 26 0 0.273438 0.92627 -13 12 27 0 0.271729 0.935547 -13 12 28 0 0.270996 0.946289 -13 12 29 0 0.270996 0.958008 -13 12 30 0 0.271484 0.970215 -13 12 31 0 0.272461 0.98291 -13 13 0 0.416992 0.382812 0.120117 -13 13 1 0.416992 0.382812 0.120117 -13 13 2 0.416992 0.382812 0.120117 -13 13 3 0.416992 0.382812 0.120117 -13 13 4 0.416992 0.382812 0.120117 -13 13 5 0.416992 0.382812 0.120178 -13 13 6 0.417236 0.382812 0.120178 -13 13 7 0.417236 0.383057 0.120178 -13 13 8 0.417236 0.383301 0.120239 -13 13 9 0.415527 0.383057 0.146484 -13 13 10 0.411133 0.381592 0.193115 -13 13 11 0.402588 0.378418 0.245361 -13 13 12 0.387695 0.372559 0.302979 -13 13 13 0.362793 0.362793 0.362793 -13 13 14 0.339844 0.364258 0.440674 -13 13 15 0.298828 0.36499 0.524414 -13 13 16 0.219116 0.364502 0.611816 -13 13 17 0 0.362549 0.695801 -13 13 18 0 0.359863 0.771973 -13 13 19 0 0.356934 0.838379 -13 13 20 0 0.352051 0.889648 -13 13 21 0 0.333496 0.894531 -13 13 22 0 0.319824 0.899902 -13 13 23 0 0.310059 0.90625 -13 13 24 0 0.30249 0.912598 -13 13 25 0 0.296631 0.919434 -13 13 26 0 0.291748 0.927734 -13 13 27 0 0.287842 0.937012 -13 13 28 0 0.285156 0.947754 -13 13 29 0 0.283447 0.959473 -13 13 30 0 0.282471 0.971191 -13 13 31 0 0.281982 0.983887 -13 14 0 0.372559 0.447266 0.115112 -13 14 1 0.372559 0.447266 0.115112 -13 14 2 0.372559 0.447266 0.115112 -13 14 3 0.372559 0.447266 0.115112 -13 14 4 0.372559 0.447266 0.115112 -13 14 5 0.372559 0.447266 0.115112 -13 14 6 0.372559 0.447266 0.115112 -13 14 7 0.372559 0.447266 0.115112 -13 14 8 0.372559 0.44751 0.115173 -13 14 9 0.372314 0.447754 0.124268 -13 14 10 0.36792 0.446045 0.176758 -13 14 11 0.360107 0.443115 0.231689 -13 14 12 0.346924 0.438232 0.29126 -13 14 13 0.328369 0.43457 0.358643 -13 14 14 0.301514 0.435059 0.437256 -13 14 15 0.251953 0.434326 0.521973 -13 14 16 0.125854 0.431885 0.610352 -13 14 17 0 0.426758 0.695312 -13 14 18 0 0.419922 0.772461 -13 14 19 0 0.412598 0.839355 -13 14 20 0 0.404541 0.894531 -13 14 21 0 0.379395 0.898926 -13 14 22 0 0.360352 0.904297 -13 14 23 0 0.345947 0.910156 -13 14 24 0 0.334961 0.916016 -13 14 25 0 0.325684 0.922852 -13 14 26 0 0.317627 0.930664 -13 14 27 0 0.311035 0.939453 -13 14 28 0 0.305908 0.950195 -13 14 29 0 0.301758 0.961426 -13 14 30 0 0.298584 0.973145 -13 14 31 0 0.296143 0.985352 -13 15 0 0.303955 0.516602 0.109436 -13 15 1 0.303955 0.516602 0.109436 -13 15 2 0.303955 0.516602 0.109436 -13 15 3 0.303955 0.516602 0.109436 -13 15 4 0.303955 0.516602 0.109436 -13 15 5 0.303955 0.51709 0.109436 -13 15 6 0.303955 0.51709 0.109436 -13 15 7 0.303955 0.51709 0.109497 -13 15 8 0.304199 0.51709 0.109497 -13 15 9 0.304443 0.517578 0.109558 -13 15 10 0.301514 0.51709 0.153687 -13 15 11 0.294434 0.516113 0.215088 -13 15 12 0.282227 0.515137 0.279785 -13 15 13 0.26123 0.514648 0.351318 -13 15 14 0.222046 0.514648 0.431152 -13 15 15 0.121948 0.513184 0.51709 -13 15 16 0 0.509277 0.606934 -13 15 17 0 0.501465 0.693359 -13 15 18 0 0.491455 0.771973 -13 15 19 0 0.47998 0.840332 -13 15 20 0 0.467773 0.896484 -13 15 21 0 0.4375 0.905273 -13 15 22 0 0.412109 0.910645 -13 15 23 0 0.392822 0.916016 -13 15 24 0 0.377686 0.921387 -13 15 25 0 0.364258 0.928223 -13 15 26 0 0.352539 0.935547 -13 15 27 0 0.342529 0.943848 -13 15 28 0 0.334229 0.953613 -13 15 29 0 0.327148 0.964355 -13 15 30 0 0.321045 0.976074 -13 15 31 0 0.316162 0.987793 -13 16 0 0.153687 0.598145 0.104309 -13 16 1 0.153687 0.598145 0.104309 -13 16 2 0.153687 0.598145 0.104309 -13 16 3 0.153687 0.598145 0.104309 -13 16 4 0.153687 0.598145 0.104309 -13 16 5 0.153809 0.598145 0.104309 -13 16 6 0.153809 0.598145 0.104309 -13 16 7 0.154053 0.598145 0.10437 -13 16 8 0.154419 0.598145 0.10437 -13 16 9 0.155029 0.598633 0.104431 -13 16 10 0.154541 0.598633 0.116089 -13 16 11 0.135498 0.599121 0.193481 -13 16 12 0.0858154 0.599121 0.264404 -13 16 13 0 0.600098 0.339355 -13 16 14 0 0.600586 0.420898 -13 16 15 0 0.599121 0.508789 -13 16 16 0 0.594727 0.600098 -13 16 17 0 0.585449 0.688965 -13 16 18 0 0.572754 0.769531 -13 16 19 0 0.558105 0.839844 -13 16 20 0 0.541504 0.897461 -13 16 21 0 0.507812 0.913574 -13 16 22 0 0.476318 0.919922 -13 16 23 0 0.451416 0.925293 -13 16 24 0 0.431396 0.930664 -13 16 25 0 0.413574 0.936523 -13 16 26 0 0.397461 0.942871 -13 16 27 0 0.383301 0.950684 -13 16 28 0 0.371094 0.959473 -13 16 29 0 0.360352 0.969727 -13 16 30 0 0.351074 0.980469 -13 16 31 0 0.343262 0.991699 -13 17 0 0 0.681152 0.0979614 -13 17 1 0 0.681152 0.0979614 -13 17 2 0 0.681152 0.0979614 -13 17 3 0 0.681152 0.0979614 -13 17 4 0 0.681152 0.0979614 -13 17 5 0 0.681152 0.0979614 -13 17 6 0 0.681152 0.0979614 -13 17 7 0 0.681152 0.0980225 -13 17 8 0 0.681152 0.0980225 -13 17 9 0 0.681641 0.0980835 -13 17 10 0 0.681641 0.0982666 -13 17 11 0 0.682129 0.159912 -13 17 12 0 0.683594 0.24231 -13 17 13 0 0.685059 0.321777 -13 17 14 0 0.686035 0.405762 -13 17 15 0 0.685547 0.495117 -13 17 16 0 0.681641 0.588867 -13 17 17 0 0.672852 0.680176 -13 17 18 0 0.65918 0.763672 -13 17 19 0 0.64209 0.836914 -13 17 20 0 0.622559 0.896484 -13 17 21 0 0.587402 0.921875 -13 17 22 0 0.550781 0.931641 -13 17 23 0 0.520508 0.938477 -13 17 24 0 0.495361 0.943359 -13 17 25 0 0.472412 0.94873 -13 17 26 0 0.451416 0.954102 -13 17 27 0 0.432617 0.960938 -13 17 28 0 0.416016 0.96875 -13 17 29 0 0.401123 0.977539 -13 17 30 0 0.387939 0.986816 -13 17 31 0 0.376465 0.99707 -13 18 0 0 0.759277 0.0897827 -13 18 1 0 0.759277 0.0897827 -13 18 2 0 0.759277 0.0897827 -13 18 3 0 0.759277 0.0897827 -13 18 4 0 0.759277 0.0897827 -13 18 5 0 0.759277 0.0897827 -13 18 6 0 0.759277 0.0898438 -13 18 7 0 0.759277 0.0898438 -13 18 8 0 0.759277 0.0899048 -13 18 9 0 0.759277 0.0899658 -13 18 10 0 0.759766 0.0900879 -13 18 11 0 0.759766 0.0960083 -13 18 12 0 0.76123 0.211548 -13 18 13 0 0.763672 0.29834 -13 18 14 0 0.765625 0.385254 -13 18 15 0 0.766602 0.476318 -13 18 16 0 0.764648 0.571777 -13 18 17 0 0.757324 0.666016 -13 18 18 0 0.744629 0.75293 -13 18 19 0 0.727051 0.82959 -13 18 20 0 0.706055 0.89209 -13 18 21 0 0.671875 0.928223 -13 18 22 0 0.632812 0.944824 -13 18 23 0 0.597656 0.954102 -13 18 24 0 0.567871 0.959961 -13 18 25 0 0.539551 0.964844 -13 18 26 0 0.513184 0.969727 -13 18 27 0 0.489258 0.975098 -13 18 28 0 0.467773 0.980957 -13 18 29 0 0.448242 0.988281 -13 18 30 0 0.430908 0.996582 -13 18 31 0 0.415283 1 -13 19 0 0 0.829102 0.0797119 -13 19 1 0 0.829102 0.0797119 -13 19 2 0 0.829102 0.0797119 -13 19 3 0 0.829102 0.0797119 -13 19 4 0 0.829102 0.0797119 -13 19 5 0 0.829102 0.0797119 -13 19 6 0 0.829102 0.0797729 -13 19 7 0 0.829102 0.0797729 -13 19 8 0 0.82959 0.079834 -13 19 9 0 0.82959 0.079895 -13 19 10 0 0.82959 0.0800781 -13 19 11 0 0.82959 0.0803223 -13 19 12 0 0.831055 0.168823 -13 19 13 0 0.833496 0.269531 -13 19 14 0 0.835938 0.360596 -13 19 15 0 0.838379 0.453613 -13 19 16 0 0.838867 0.550293 -13 19 17 0 0.834473 0.646484 -13 19 18 0 0.824219 0.737305 -13 19 19 0 0.807617 0.816895 -13 19 20 0 0.786133 0.883301 -13 19 21 0 0.755371 0.929688 -13 19 22 0 0.716797 0.956055 -13 19 23 0 0.679688 0.970703 -13 19 24 0 0.645508 0.979004 -13 19 25 0 0.612305 0.984375 -13 19 26 0 0.581055 0.98877 -13 19 27 0 0.551758 0.992676 -13 19 28 0 0.524902 0.99707 -13 19 29 0 0.500488 1 -13 19 30 0 0.478271 1 -13 19 31 0 0.458252 1 -13 20 0 0 0.889648 0.0673828 -13 20 1 0 0.889648 0.0673828 -13 20 2 0 0.889648 0.0673828 -13 20 3 0 0.889648 0.0673828 -13 20 4 0 0.889648 0.0673828 -13 20 5 0 0.889648 0.0674438 -13 20 6 0 0.889648 0.0674438 -13 20 7 0 0.889648 0.0674438 -13 20 8 0 0.890137 0.0675049 -13 20 9 0 0.890137 0.067627 -13 20 10 0 0.890137 0.0678101 -13 20 11 0 0.890137 0.0681152 -13 20 12 0 0.890625 0.0946655 -13 20 13 0 0.893066 0.235962 -13 20 14 0 0.896484 0.333496 -13 20 15 0 0.899902 0.428467 -13 20 16 0 0.902344 0.525879 -13 20 17 0 0.900879 0.623535 -13 20 18 0 0.893066 0.716797 -13 20 19 0 0.879395 0.799805 -13 20 20 0 0.859375 0.869629 -13 20 21 0 0.83252 0.924805 -13 20 22 0 0.797852 0.961914 -13 20 23 0 0.760742 0.983398 -13 20 24 0 0.724609 0.995605 -13 20 25 0 0.6875 1 -13 20 26 0 0.651367 1 -13 20 27 0 0.617188 1 -13 20 28 0 0.584961 1 -13 20 29 0 0.555176 1 -13 20 30 0 0.52832 1 -13 20 31 0 0.503906 1 -13 21 0 0 0.941406 0.0505676 -13 21 1 0 0.941406 0.0505676 -13 21 2 0 0.941406 0.0505676 -13 21 3 0 0.941406 0.0505676 -13 21 4 0 0.941406 0.0505676 -13 21 5 0 0.941406 0.0505676 -13 21 6 0 0.941406 0.0505981 -13 21 7 0 0.941406 0.0506287 -13 21 8 0 0.941406 0.0507202 -13 21 9 0 0.941406 0.0508728 -13 21 10 0 0.941406 0.0511475 -13 21 11 0 0.941406 0.0516052 -13 21 12 0 0.941895 0.0523987 -13 21 13 0 0.943848 0.19397 -13 21 14 0 0.947754 0.303223 -13 21 15 0 0.952148 0.400879 -13 21 16 0 0.955566 0.499268 -13 21 17 0 0.956543 0.597656 -13 21 18 0 0.952637 0.691895 -13 21 19 0 0.941406 0.777344 -13 21 20 0 0.924316 0.850586 -13 21 21 0 0.901367 0.912598 -13 21 22 0 0.87207 0.958984 -13 21 23 0 0.837402 0.989258 -13 21 24 0 0.801758 1 -13 21 25 0 0.763184 1 -13 21 26 0 0.723633 1 -13 21 27 0 0.68457 1 -13 21 28 0 0.647949 1 -13 21 29 0 0.613281 1 -13 21 30 0 0.581055 1 -13 21 31 0 0.551758 1 -13 22 0 0 0.983887 0 -13 22 1 0 0.983887 0 -13 22 2 0 0.983887 0 -13 22 3 0 0.983887 0 -13 22 4 0 0.983887 0 -13 22 5 0 0.983887 0 -13 22 6 0 0.983887 0 -13 22 7 0 0.983887 0 -13 22 8 0 0.983887 0 -13 22 9 0 0.983887 0 -13 22 10 0 0.983887 0.00701904 -13 22 11 0 0.984375 0.0128708 -13 22 12 0 0.984375 0.0178986 -13 22 13 0 0.985352 0.135254 -13 22 14 0 0.989258 0.270264 -13 22 15 0 0.994141 0.37207 -13 22 16 0 0.999023 0.471191 -13 22 17 0 1 0.569336 -13 22 18 0 1 0.664062 -13 22 19 0 0.993652 0.751465 -13 22 20 0 0.97998 0.827637 -13 22 21 0 0.959961 0.893066 -13 22 22 0 0.935059 0.946289 -13 22 23 0 0.905273 0.985352 -13 22 24 0 0.87207 1 -13 22 25 0 0.833984 1 -13 22 26 0 0.793457 1 -13 22 27 0 0.751953 1 -13 22 28 0 0.710938 1 -13 22 29 0 0.671875 1 -13 22 30 0 0.635254 1 -13 22 31 0 0.601562 1 -13 23 0 0 1 0 -13 23 1 0 1 0 -13 23 2 0 1 0 -13 23 3 0 1 0 -13 23 4 0 1 0 -13 23 5 0 1 0 -13 23 6 0 1 0 -13 23 7 0 1 0 -13 23 8 0 1 0 -13 23 9 0 1 0 -13 23 10 0 1 0 -13 23 11 0 1 0 -13 23 12 0 1 0 -13 23 13 0 1 0 -13 23 14 0 1 0.234741 -13 23 15 0 1 0.343262 -13 23 16 0 1 0.443604 -13 23 17 0 1 0.541504 -13 23 18 0 1 0.63623 -13 23 19 0 1 0.724609 -13 23 20 0 1 0.802734 -13 23 21 0 1 0.870605 -13 23 22 0 0.986328 0.927734 -13 23 23 0 0.960449 0.972656 -13 23 24 0 0.931641 1 -13 23 25 0 0.896484 1 -13 23 26 0 0.856445 1 -13 23 27 0 0.813965 1 -13 23 28 0 0.770996 1 -13 23 29 0 0.728516 1 -13 23 30 0 0.687988 1 -13 23 31 0 0.649902 1 -13 24 0 0 1 0 -13 24 1 0 1 0 -13 24 2 0 1 0 -13 24 3 0 1 0 -13 24 4 0 1 0 -13 24 5 0 1 0 -13 24 6 0 1 0 -13 24 7 0 1 0 -13 24 8 0 1 0 -13 24 9 0 1 0 -13 24 10 0 1 0 -13 24 11 0 1 0 -13 24 12 0 1 0 -13 24 13 0 1 0 -13 24 14 0 1 0.194702 -13 24 15 0 1 0.314209 -13 24 16 0 1 0.41626 -13 24 17 0 1 0.513672 -13 24 18 0 1 0.608398 -13 24 19 0 1 0.696777 -13 24 20 0 1 0.775879 -13 24 21 0 1 0.846191 -13 24 22 0 1 0.90625 -13 24 23 0 1 0.95459 -13 24 24 0 0.980957 0.993164 -13 24 25 0 0.949707 1 -13 24 26 0 0.912598 1 -13 24 27 0 0.870605 1 -13 24 28 0 0.826172 1 -13 24 29 0 0.781738 1 -13 24 30 0 0.738281 1 -13 24 31 0 0.696777 1 -13 25 0 0 1 0 -13 25 1 0 1 0 -13 25 2 0 1 0 -13 25 3 0 1 0 -13 25 4 0 1 0 -13 25 5 0 1 0 -13 25 6 0 1 0 -13 25 7 0 1 0 -13 25 8 0 1 0 -13 25 9 0 1 0 -13 25 10 0 1 0 -13 25 11 0 1 0 -13 25 12 0 1 0 -13 25 13 0 1 0 -13 25 14 0 1 0.137451 -13 25 15 0 1 0.281738 -13 25 16 0 1 0.386719 -13 25 17 0 1 0.484131 -13 25 18 0 1 0.577637 -13 25 19 0 1 0.665527 -13 25 20 0 1 0.745605 -13 25 21 0 1 0.817383 -13 25 22 0 1 0.879883 -13 25 23 0 1 0.931641 -13 25 24 0 1 0.973633 -13 25 25 0 0.998535 1 -13 25 26 0 0.965332 1 -13 25 27 0 0.925293 1 -13 25 28 0 0.881836 1 -13 25 29 0 0.835938 1 -13 25 30 0 0.790527 1 -13 25 31 0 0.746094 1 -13 26 0 0 1 0 -13 26 1 0 1 0 -13 26 2 0 1 0 -13 26 3 0 1 0 -13 26 4 0 1 0 -13 26 5 0 1 0 -13 26 6 0 1 0 -13 26 7 0 1 0 -13 26 8 0 1 0 -13 26 9 0 1 0 -13 26 10 0 1 0 -13 26 11 0 1 0 -13 26 12 0 1 0 -13 26 13 0 1 0 -13 26 14 0 1 0 -13 26 15 0 1 0.244141 -13 26 16 0 1 0.354736 -13 26 17 0 1 0.452637 -13 26 18 0 1 0.544922 -13 26 19 0 1 0.632324 -13 26 20 0 1 0.711914 -13 26 21 0 1 0.785156 -13 26 22 0 1 0.849609 -13 26 23 0 1 0.903809 -13 26 24 0 1 0.949219 -13 26 25 0 1 0.990234 -13 26 26 0 1 1 -13 26 27 0 0.977539 1 -13 26 28 0 0.936035 1 -13 26 29 0 0.890625 1 -13 26 30 0 0.84375 1 -13 26 31 0 0.797363 1 -13 27 0 0 1 0 -13 27 1 0 1 0 -13 27 2 0 1 0 -13 27 3 0 1 0 -13 27 4 0 1 0 -13 27 5 0 1 0 -13 27 6 0 1 0 -13 27 7 0 1 0 -13 27 8 0 1 0 -13 27 9 0 1 0 -13 27 10 0 1 0 -13 27 11 0 1 0 -13 27 12 0 1 0 -13 27 13 0 1 0 -13 27 14 0 1 0 -13 27 15 0 1 0.197998 -13 27 16 0 1 0.320312 -13 27 17 0 1 0.419189 -13 27 18 0 1 0.510742 -13 27 19 0 1 0.59668 -13 27 20 0 1 0.675781 -13 27 21 0 1 0.749023 -13 27 22 0 1 0.814941 -13 27 23 0 1 0.871582 -13 27 24 0 1 0.919434 -13 27 25 0 1 0.963867 -13 27 26 0 1 1 -13 27 27 0 1 1 -13 27 28 0 0.986816 1 -13 27 29 0 0.943359 1 -13 27 30 0 0.896484 1 -13 27 31 0 0.849121 1 -13 28 0 0 1 0 -13 28 1 0 1 0 -13 28 2 0 1 0 -13 28 3 0 1 0 -13 28 4 0 1 0 -13 28 5 0 1 0 -13 28 6 0 1 0 -13 28 7 0 1 0 -13 28 8 0 1 0 -13 28 9 0 1 0 -13 28 10 0 1 0 -13 28 11 0 1 0 -13 28 12 0 1 0 -13 28 13 0 1 0 -13 28 14 0 1 0 -13 28 15 0 1 0.130493 -13 28 16 0 1 0.281982 -13 28 17 0 1 0.384033 -13 28 18 0 1 0.475098 -13 28 19 0 1 0.55957 -13 28 20 0 1 0.637207 -13 28 21 0 1 0.710449 -13 28 22 0 1 0.776367 -13 28 23 0 1 0.834473 -13 28 24 0 1 0.884277 -13 28 25 0 1 0.931641 -13 28 26 0 1 0.975586 -13 28 27 0 1 1 -13 28 28 0 1 1 -13 28 29 0 0.992676 1 -13 28 30 0 0.948242 1 -13 28 31 0 0.900879 1 -13 29 0 0 1 0 -13 29 1 0 1 0 -13 29 2 0 1 0 -13 29 3 0 1 0 -13 29 4 0 1 0 -13 29 5 0 1 0 -13 29 6 0 1 0 -13 29 7 0 1 0 -13 29 8 0 1 0 -13 29 9 0 1 0 -13 29 10 0 1 0 -13 29 11 0 1 0 -13 29 12 0 1 0 -13 29 13 0 1 0 -13 29 14 0 1 0 -13 29 15 0 1 0 -13 29 16 0 1 0.238159 -13 29 17 0 1 0.346436 -13 29 18 0 1 0.4375 -13 29 19 0 1 0.520508 -13 29 20 0 1 0.597168 -13 29 21 0 1 0.668945 -13 29 22 0 1 0.734863 -13 29 23 0 1 0.793457 -13 29 24 0 1 0.844727 -13 29 25 0 1 0.894043 -13 29 26 0 1 0.940918 -13 29 27 0 1 0.983398 -13 29 28 0 1 1 -13 29 29 0 1 1 -13 29 30 0 0.997559 1 -13 29 31 0 0.952148 1 -13 30 0 0 1 0 -13 30 1 0 1 0 -13 30 2 0 1 0 -13 30 3 0 1 0 -13 30 4 0 1 0 -13 30 5 0 1 0 -13 30 6 0 1 0 -13 30 7 0 1 0 -13 30 8 0 1 0 -13 30 9 0 1 0 -13 30 10 0 1 0 -13 30 11 0 1 0 -13 30 12 0 1 0 -13 30 13 0 1 0 -13 30 14 0 1 0 -13 30 15 0 1 0 -13 30 16 0 1 0.183838 -13 30 17 0 1 0.305908 -13 30 18 0 1 0.398438 -13 30 19 0 1 0.480225 -13 30 20 0 1 0.555176 -13 30 21 0 1 0.625488 -13 30 22 0 1 0.69043 -13 30 23 0 1 0.748535 -13 30 24 0 1 0.800781 -13 30 25 0 1 0.851562 -13 30 26 0 1 0.900879 -13 30 27 0 1 0.946777 -13 30 28 0 1 0.98877 -13 30 29 0 1 1 -13 30 30 0 1 1 -13 30 31 0 1 1 -13 31 0 0 1 0 -13 31 1 0 1 0 -13 31 2 0 1 0 -13 31 3 0 1 0 -13 31 4 0 1 0 -13 31 5 0 1 0 -13 31 6 0 1 0 -13 31 7 0 1 0 -13 31 8 0 1 0 -13 31 9 0 1 0 -13 31 10 0 1 0 -13 31 11 0 1 0 -13 31 12 0 1 0 -13 31 13 0 1 0 -13 31 14 0 1 0 -13 31 15 0 1 0 -13 31 16 0 1 0.0915527 -13 31 17 0 1 0.261719 -13 31 18 0 1 0.35791 -13 31 19 0 1 0.438965 -13 31 20 0 1 0.512207 -13 31 21 0 1 0.580566 -13 31 22 0 1 0.644043 -13 31 23 0 1 0.701172 -13 31 24 0 1 0.753418 -13 31 25 0 1 0.805176 -13 31 26 0 1 0.855957 -13 31 27 0 1 0.905273 -13 31 28 0 1 0.95166 -13 31 29 0 1 0.993652 -13 31 30 0 1 1 -13 31 31 0 1 1 -14 0 0 0.557617 0 0.0342712 -14 0 1 0.557617 0 0.0342712 -14 0 2 0.557617 0 0.0342407 -14 0 3 0.557617 0 0.0342102 -14 0 4 0.557617 0 0.0341492 -14 0 5 0.557617 0 0.0340576 -14 0 6 0.557617 0 0.033844 -14 0 7 0.557617 0 0.0334473 -14 0 8 0.557617 0 0.0326538 -14 0 9 0.560547 0 0.032196 -14 0 10 0.563477 0 0.148438 -14 0 11 0.564453 0 0.234253 -14 0 12 0.552246 0 0.312744 -14 0 13 0.512695 0.134277 0.373535 -14 0 14 0.490234 0.165405 0.444336 -14 0 15 0.466064 0.177979 0.526855 -14 0 16 0.426758 0.192627 0.613281 -14 0 17 0.366455 0.207764 0.696777 -14 0 18 0.270752 0.222534 0.772461 -14 0 19 0 0.236084 0.838867 -14 0 20 0 0.246094 0.88916 -14 0 21 0 0.244629 0.894043 -14 0 22 0 0.244263 0.899902 -14 0 23 0 0.244507 0.906738 -14 0 24 0 0.245361 0.913574 -14 0 25 0 0.24646 0.921387 -14 0 26 0 0.247803 0.929688 -14 0 27 0 0.249512 0.938477 -14 0 28 0 0.251709 0.949219 -14 0 29 0 0.25415 0.960449 -14 0 30 0 0.256836 0.972168 -14 0 31 0 0.259766 0.984863 -14 1 0 0.557617 0 0.0341492 -14 1 1 0.557617 0 0.0341492 -14 1 2 0.557617 0 0.0341492 -14 1 3 0.557617 0 0.0341187 -14 1 4 0.557617 0 0.0340576 -14 1 5 0.557617 0 0.0339355 -14 1 6 0.557617 0 0.0337524 -14 1 7 0.557617 0 0.0333557 -14 1 8 0.557617 0 0.0325623 -14 1 9 0.560547 0 0.032074 -14 1 10 0.563477 0 0.148438 -14 1 11 0.564453 0 0.234253 -14 1 12 0.552246 0 0.312744 -14 1 13 0.512695 0.134521 0.373535 -14 1 14 0.490234 0.165527 0.444336 -14 1 15 0.466064 0.178101 0.526855 -14 1 16 0.426758 0.192627 0.613281 -14 1 17 0.366455 0.207886 0.696777 -14 1 18 0.270752 0.222656 0.772461 -14 1 19 0 0.236084 0.838867 -14 1 20 0 0.246094 0.88916 -14 1 21 0 0.244629 0.894043 -14 1 22 0 0.244263 0.899902 -14 1 23 0 0.244629 0.906738 -14 1 24 0 0.245483 0.913574 -14 1 25 0 0.24646 0.921387 -14 1 26 0 0.247803 0.929688 -14 1 27 0 0.249634 0.938477 -14 1 28 0 0.251709 0.949219 -14 1 29 0 0.25415 0.960449 -14 1 30 0 0.25708 0.972168 -14 1 31 0 0.259766 0.984863 -14 2 0 0.557617 0 0.0339661 -14 2 1 0.557617 0 0.0339661 -14 2 2 0.557617 0 0.0339355 -14 2 3 0.557617 0 0.033905 -14 2 4 0.557617 0 0.0338745 -14 2 5 0.557617 0 0.0337524 -14 2 6 0.557617 0 0.0335388 -14 2 7 0.557617 0 0.0331421 -14 2 8 0.557617 0 0.0323486 -14 2 9 0.560547 0 0.0318604 -14 2 10 0.563477 0 0.148438 -14 2 11 0.564453 0 0.234253 -14 2 12 0.552246 0 0.312744 -14 2 13 0.512695 0.134766 0.373535 -14 2 14 0.490234 0.165771 0.444336 -14 2 15 0.466064 0.178223 0.526855 -14 2 16 0.426758 0.192871 0.613281 -14 2 17 0.366455 0.208008 0.696777 -14 2 18 0.270752 0.222656 0.772461 -14 2 19 0 0.236206 0.838867 -14 2 20 0 0.246216 0.88916 -14 2 21 0 0.244751 0.894043 -14 2 22 0 0.244263 0.899902 -14 2 23 0 0.244629 0.906738 -14 2 24 0 0.245483 0.914062 -14 2 25 0 0.246582 0.921387 -14 2 26 0 0.247925 0.929688 -14 2 27 0 0.249634 0.938477 -14 2 28 0 0.251709 0.949219 -14 2 29 0 0.25415 0.960449 -14 2 30 0 0.25708 0.972168 -14 2 31 0 0.259766 0.984863 -14 3 0 0.557617 0 0.0335999 -14 3 1 0.557617 0 0.0335999 -14 3 2 0.557617 0 0.0335999 -14 3 3 0.557617 0 0.0335693 -14 3 4 0.557617 0 0.0335083 -14 3 5 0.557617 0 0.0333862 -14 3 6 0.557617 0 0.0331726 -14 3 7 0.557617 0 0.0327759 -14 3 8 0.557617 0 0.0319519 -14 3 9 0.560547 0 0.0314636 -14 3 10 0.563477 0 0.148438 -14 3 11 0.564453 0 0.234253 -14 3 12 0.552246 0 0.312744 -14 3 13 0.512695 0.135376 0.373535 -14 3 14 0.490234 0.166138 0.444336 -14 3 15 0.46582 0.178589 0.526855 -14 3 16 0.426758 0.193115 0.613281 -14 3 17 0.366455 0.208252 0.696777 -14 3 18 0.270752 0.2229 0.772461 -14 3 19 0 0.236328 0.838867 -14 3 20 0 0.246338 0.88916 -14 3 21 0 0.244873 0.894043 -14 3 22 0 0.244385 0.899902 -14 3 23 0 0.244751 0.906738 -14 3 24 0 0.245483 0.914062 -14 3 25 0 0.246582 0.921387 -14 3 26 0 0.247925 0.929688 -14 3 27 0 0.249634 0.938477 -14 3 28 0 0.251709 0.949219 -14 3 29 0 0.254395 0.960449 -14 3 30 0 0.25708 0.972168 -14 3 31 0 0.259766 0.984863 -14 4 0 0.557617 0 0.0329285 -14 4 1 0.557617 0 0.0328979 -14 4 2 0.557617 0 0.0328979 -14 4 3 0.557617 0 0.0328674 -14 4 4 0.557617 0 0.0328064 -14 4 5 0.557617 0 0.0326843 -14 4 6 0.557617 0 0.0324707 -14 4 7 0.557617 0 0.0320435 -14 4 8 0.557617 0 0.0312042 -14 4 9 0.560547 0 0.0306702 -14 4 10 0.563477 0 0.148315 -14 4 11 0.563965 0 0.234131 -14 4 12 0.552246 0 0.312744 -14 4 13 0.512695 0.136475 0.373535 -14 4 14 0.490234 0.166992 0.444336 -14 4 15 0.46582 0.179321 0.526855 -14 4 16 0.426758 0.193726 0.613281 -14 4 17 0.366455 0.20874 0.696777 -14 4 18 0.270508 0.223267 0.772461 -14 4 19 0 0.236694 0.838867 -14 4 20 0 0.246582 0.88916 -14 4 21 0 0.244995 0.894043 -14 4 22 0 0.244507 0.899902 -14 4 23 0 0.244873 0.906738 -14 4 24 0 0.245605 0.914062 -14 4 25 0 0.246704 0.921387 -14 4 26 0 0.248047 0.929688 -14 4 27 0 0.249756 0.938477 -14 4 28 0 0.251953 0.949219 -14 4 29 0 0.254395 0.960449 -14 4 30 0 0.25708 0.972168 -14 4 31 0 0.26001 0.984863 -14 5 0 0.557617 0 0.0315247 -14 5 1 0.557617 0 0.0314941 -14 5 2 0.557617 0 0.0314941 -14 5 3 0.557617 0 0.0314636 -14 5 4 0.557617 0 0.0314026 -14 5 5 0.557617 0 0.0312805 -14 5 6 0.557617 0 0.0310364 -14 5 7 0.557617 0 0.0305786 -14 5 8 0.557617 0 0.0296631 -14 5 9 0.560059 0 0.0290833 -14 5 10 0.563477 0 0.148193 -14 5 11 0.563965 0 0.234131 -14 5 12 0.552246 0 0.312744 -14 5 13 0.512695 0.138428 0.373535 -14 5 14 0.48999 0.168457 0.444336 -14 5 15 0.46582 0.180542 0.526855 -14 5 16 0.426514 0.194824 0.613281 -14 5 17 0.366211 0.209595 0.696777 -14 5 18 0.270264 0.223999 0.772461 -14 5 19 0 0.237305 0.838867 -14 5 20 0 0.24707 0.88916 -14 5 21 0 0.245483 0.894043 -14 5 22 0 0.244873 0.899902 -14 5 23 0 0.245117 0.906738 -14 5 24 0 0.24585 0.914062 -14 5 25 0 0.246948 0.921387 -14 5 26 0 0.248169 0.929688 -14 5 27 0 0.249878 0.938477 -14 5 28 0 0.251953 0.949219 -14 5 29 0 0.254395 0.960449 -14 5 30 0 0.25708 0.972168 -14 5 31 0 0.26001 0.984863 -14 6 0 0.557129 0 0.0285034 -14 6 1 0.557129 0 0.0284882 -14 6 2 0.557129 0 0.0284729 -14 6 3 0.557129 0 0.0284271 -14 6 4 0.557129 0 0.0283508 -14 6 5 0.557129 0 0.0282135 -14 6 6 0.557129 0 0.0279388 -14 6 7 0.557129 0 0.0274048 -14 6 8 0.557129 0 0.0262909 -14 6 9 0.560059 0 0.0255737 -14 6 10 0.562988 0 0.147827 -14 6 11 0.563965 0 0.233887 -14 6 12 0.552246 0 0.312744 -14 6 13 0.512695 0.142212 0.373779 -14 6 14 0.48999 0.171143 0.444336 -14 6 15 0.465576 0.182861 0.526855 -14 6 16 0.426514 0.196777 0.613281 -14 6 17 0.365967 0.211304 0.696777 -14 6 18 0.27002 0.225464 0.772461 -14 6 19 0 0.238403 0.838867 -14 6 20 0 0.248047 0.88916 -14 6 21 0 0.246216 0.894043 -14 6 22 0 0.245483 0.899902 -14 6 23 0 0.245728 0.906738 -14 6 24 0 0.246338 0.914062 -14 6 25 0 0.247314 0.921387 -14 6 26 0 0.248535 0.929688 -14 6 27 0 0.250244 0.938477 -14 6 28 0 0.252197 0.949219 -14 6 29 0 0.254639 0.960449 -14 6 30 0 0.257324 0.972168 -14 6 31 0 0.260254 0.984863 -14 7 0 0.557129 0 0.0203857 -14 7 1 0.557129 0 0.0203705 -14 7 2 0.557129 0 0.02034 -14 7 3 0.557129 0 0.0202637 -14 7 4 0.557129 0 0.0201416 -14 7 5 0.557129 0 0.0198975 -14 7 6 0.557129 0 0.0194244 -14 7 7 0.557129 0 0.0184174 -14 7 8 0.557129 0 0.0161743 -14 7 9 0.55957 0 0.0144196 -14 7 10 0.562988 0 0.147339 -14 7 11 0.563477 0 0.233643 -14 7 12 0.552246 0 0.312744 -14 7 13 0.512207 0.149048 0.373779 -14 7 14 0.489502 0.17627 0.444092 -14 7 15 0.465332 0.187378 0.526855 -14 7 16 0.426025 0.200684 0.613281 -14 7 17 0.365479 0.214478 0.696777 -14 7 18 0.269287 0.228027 0.772461 -14 7 19 0 0.240601 0.838867 -14 7 20 0 0.249878 0.88916 -14 7 21 0 0.247681 0.894043 -14 7 22 0 0.246826 0.899902 -14 7 23 0 0.246704 0.906738 -14 7 24 0 0.247314 0.914062 -14 7 25 0 0.248047 0.921387 -14 7 26 0 0.249268 0.929688 -14 7 27 0 0.250732 0.938477 -14 7 28 0 0.252686 0.949219 -14 7 29 0 0.255127 0.960449 -14 7 30 0 0.257812 0.972168 -14 7 31 0 0.260498 0.984863 -14 8 0 0.556152 0.081665 0 -14 8 1 0.556152 0.0817261 0 -14 8 2 0.556152 0.0817871 0 -14 8 3 0.556152 0.0819092 0 -14 8 4 0.556152 0.0822144 0 -14 8 5 0.556152 0.0827637 0 -14 8 6 0.556152 0.0838013 0 -14 8 7 0.556152 0.0856934 0 -14 8 8 0.556152 0.0892944 0 -14 8 9 0.559082 0.0917358 0 -14 8 10 0.562012 0.085144 0.14624 -14 8 11 0.562988 0.0756836 0.233032 -14 8 12 0.552246 0.0888062 0.3125 -14 8 13 0.512207 0.161133 0.373779 -14 8 14 0.48877 0.185669 0.444092 -14 8 15 0.4646 0.195801 0.526855 -14 8 16 0.425293 0.207886 0.613281 -14 8 17 0.364502 0.220581 0.696777 -14 8 18 0.267822 0.233154 0.772461 -14 8 19 0 0.244873 0.839355 -14 8 20 0 0.253418 0.889648 -14 8 21 0 0.250732 0.894043 -14 8 22 0 0.249146 0.900391 -14 8 23 0 0.248779 0.907227 -14 8 24 0 0.249023 0.914062 -14 8 25 0 0.249634 0.921387 -14 8 26 0 0.250488 0.929688 -14 8 27 0 0.251953 0.938477 -14 8 28 0 0.253662 0.949219 -14 8 29 0 0.255859 0.960449 -14 8 30 0 0.258301 0.972656 -14 8 31 0 0.260986 0.984863 -14 9 0 0.554199 0.139526 0 -14 9 1 0.554199 0.139526 0 -14 9 2 0.554199 0.139648 0 -14 9 3 0.554199 0.139648 0 -14 9 4 0.554199 0.139771 0 -14 9 5 0.554199 0.140015 0 -14 9 6 0.554199 0.140503 0 -14 9 7 0.554199 0.141357 0 -14 9 8 0.554199 0.142944 0 -14 9 9 0.557129 0.144409 0 -14 9 10 0.560547 0.141479 0.144653 -14 9 11 0.561523 0.136963 0.231812 -14 9 12 0.552246 0.13855 0.312256 -14 9 13 0.511719 0.181274 0.374268 -14 9 14 0.487549 0.201782 0.444092 -14 9 15 0.463135 0.210327 0.526855 -14 9 16 0.423584 0.220703 0.613281 -14 9 17 0.362793 0.231567 0.696777 -14 9 18 0.265137 0.242432 0.772949 -14 9 19 0 0.252686 0.839355 -14 9 20 0 0.260254 0.889648 -14 9 21 0 0.256104 0.894531 -14 9 22 0 0.253662 0.900879 -14 9 23 0 0.252686 0.907227 -14 9 24 0 0.252441 0.914551 -14 9 25 0 0.252441 0.921875 -14 9 26 0 0.25293 0.929688 -14 9 27 0 0.253906 0.938965 -14 9 28 0 0.255615 0.949219 -14 9 29 0 0.257568 0.960449 -14 9 30 0 0.259766 0.972656 -14 9 31 0 0.262207 0.984863 -14 10 0 0.550781 0.193848 0 -14 10 1 0.550781 0.193848 0 -14 10 2 0.550781 0.193848 0 -14 10 3 0.550781 0.193848 0 -14 10 4 0.550781 0.19397 0 -14 10 5 0.550781 0.194092 0 -14 10 6 0.550781 0.194336 0 -14 10 7 0.550781 0.194824 0 -14 10 8 0.550781 0.195801 0 -14 10 9 0.553223 0.197021 0 -14 10 10 0.556641 0.195679 0.143188 -14 10 11 0.559082 0.192749 0.22937 -14 10 12 0.551758 0.190552 0.311279 -14 10 13 0.51123 0.210938 0.374756 -14 10 14 0.485107 0.226685 0.443604 -14 10 15 0.460449 0.233276 0.526855 -14 10 16 0.420898 0.241333 0.613281 -14 10 17 0.359375 0.249634 0.696777 -14 10 18 0.26001 0.257812 0.772949 -14 10 19 0 0.265869 0.839355 -14 10 20 0 0.271729 0.890625 -14 10 21 0 0.265381 0.895508 -14 10 22 0 0.261475 0.901367 -14 10 23 0 0.259277 0.908203 -14 10 24 0 0.258057 0.915039 -14 10 25 0 0.257324 0.921875 -14 10 26 0 0.257324 0.930176 -14 10 27 0 0.257812 0.938965 -14 10 28 0 0.258789 0.949707 -14 10 29 0 0.260254 0.960938 -14 10 30 0 0.262207 0.972656 -14 10 31 0 0.264404 0.984863 -14 11 0 0.54248 0.251221 0 -14 11 1 0.54248 0.251221 0 -14 11 2 0.54248 0.251221 0 -14 11 3 0.54248 0.251221 0 -14 11 4 0.54248 0.251221 0 -14 11 5 0.54248 0.251465 0 -14 11 6 0.54248 0.251465 0 -14 11 7 0.54248 0.251709 0 -14 11 8 0.54248 0.252441 0 -14 11 9 0.543945 0.253418 0 -14 11 10 0.546875 0.253418 0.145386 -14 11 11 0.550781 0.252686 0.226318 -14 11 12 0.547363 0.249878 0.30835 -14 11 13 0.510254 0.252197 0.375977 -14 11 14 0.480713 0.261963 0.443115 -14 11 15 0.456055 0.266602 0.526367 -14 11 16 0.416016 0.271973 0.613281 -14 11 17 0.353516 0.2771 0.696777 -14 11 18 0.250488 0.281982 0.772949 -14 11 19 0 0.286865 0.839844 -14 11 20 0 0.290039 0.891602 -14 11 21 0 0.280762 0.896484 -14 11 22 0 0.274658 0.902344 -14 11 23 0 0.270752 0.90918 -14 11 24 0 0.267822 0.915527 -14 11 25 0 0.265869 0.922852 -14 11 26 0 0.264648 0.930664 -14 11 27 0 0.26416 0.939453 -14 11 28 0 0.264404 0.950195 -14 11 29 0 0.265137 0.961426 -14 11 30 0 0.266357 0.973145 -14 11 31 0 0.268066 0.985352 -14 12 0 0.527344 0.311035 0 -14 12 1 0.527344 0.311035 0 -14 12 2 0.527344 0.311035 0 -14 12 3 0.527344 0.311035 0 -14 12 4 0.527344 0.311035 0 -14 12 5 0.527344 0.311035 0 -14 12 6 0.527344 0.311279 0 -14 12 7 0.527344 0.311279 0 -14 12 8 0.527344 0.311768 0 -14 12 9 0.527344 0.312256 0.0849609 -14 12 10 0.52832 0.312988 0.159058 -14 12 11 0.530273 0.314453 0.225952 -14 12 12 0.532715 0.314941 0.302246 -14 12 13 0.509277 0.308594 0.377686 -14 12 14 0.473145 0.309082 0.442139 -14 12 15 0.447998 0.311768 0.525879 -14 12 16 0.406982 0.314209 0.612793 -14 12 17 0.342773 0.315918 0.696777 -14 12 18 0.232544 0.317139 0.773438 -14 12 19 0 0.318115 0.840332 -14 12 20 0 0.318115 0.893555 -14 12 21 0 0.304688 0.898438 -14 12 22 0 0.295166 0.904785 -14 12 23 0 0.28833 0.910645 -14 12 24 0 0.283447 0.916504 -14 12 25 0 0.279541 0.923828 -14 12 26 0 0.276611 0.931641 -14 12 27 0 0.274658 0.94043 -14 12 28 0 0.273438 0.950684 -14 12 29 0 0.273193 0.961914 -14 12 30 0 0.273438 0.973633 -14 12 31 0 0.273926 0.98584 -14 13 0 0.511719 0.375732 0.126343 -14 13 1 0.511719 0.375732 0.126343 -14 13 2 0.511719 0.375732 0.126343 -14 13 3 0.511719 0.375732 0.126343 -14 13 4 0.511719 0.375732 0.126343 -14 13 5 0.511719 0.375732 0.126343 -14 13 6 0.511719 0.375977 0.126343 -14 13 7 0.511719 0.375977 0.126465 -14 13 8 0.512207 0.376221 0.126587 -14 13 9 0.511719 0.376709 0.134644 -14 13 10 0.509277 0.376221 0.182495 -14 13 11 0.504883 0.375732 0.235718 -14 13 12 0.498535 0.375244 0.296875 -14 13 13 0.493408 0.376465 0.37207 -14 13 14 0.459717 0.367432 0.44043 -14 13 15 0.434082 0.368408 0.524414 -14 13 16 0.391602 0.368408 0.612305 -14 13 17 0.32373 0.366699 0.696777 -14 13 18 0.197266 0.364014 0.773926 -14 13 19 0 0.36084 0.84082 -14 13 20 0 0.357422 0.896484 -14 13 21 0 0.338623 0.901367 -14 13 22 0 0.324463 0.906738 -14 13 23 0 0.313965 0.912598 -14 13 24 0 0.306396 0.918457 -14 13 25 0 0.299805 0.925293 -14 13 26 0 0.294678 0.933105 -14 13 27 0 0.290527 0.941895 -14 13 28 0 0.287598 0.952148 -14 13 29 0 0.2854 0.962891 -14 13 30 0 0.28418 0.974609 -14 13 31 0 0.283447 0.986816 -14 14 0 0.498535 0.45752 0.143555 -14 14 1 0.498535 0.45752 0.143555 -14 14 2 0.498535 0.45752 0.143555 -14 14 3 0.498535 0.45752 0.143555 -14 14 4 0.498535 0.45752 0.143555 -14 14 5 0.498535 0.45752 0.143555 -14 14 6 0.498535 0.45752 0.143555 -14 14 7 0.498535 0.457764 0.143677 -14 14 8 0.498535 0.458008 0.143677 -14 14 9 0.498779 0.458252 0.143677 -14 14 10 0.496094 0.457764 0.185059 -14 14 11 0.490723 0.456299 0.23999 -14 14 12 0.481201 0.453125 0.30127 -14 14 13 0.464355 0.447266 0.36792 -14 14 14 0.437012 0.437012 0.437012 -14 14 15 0.409912 0.436768 0.521973 -14 14 16 0.364746 0.43457 0.61084 -14 14 17 0.288574 0.429932 0.696289 -14 14 18 0.0928955 0.42334 0.773926 -14 14 19 0 0.416016 0.841797 -14 14 20 0 0.408203 0.897461 -14 14 21 0 0.384033 0.905273 -14 14 22 0 0.364502 0.910645 -14 14 23 0 0.349854 0.916016 -14 14 24 0 0.338379 0.921387 -14 14 25 0 0.328857 0.928223 -14 14 26 0 0.320557 0.935547 -14 14 27 0 0.313477 0.943848 -14 14 28 0 0.308105 0.954102 -14 14 29 0 0.303711 0.964844 -14 14 30 0 0.300293 0.976074 -14 14 31 0 0.297607 0.988281 -14 15 0 0.449707 0.529785 0.138062 -14 15 1 0.449707 0.529785 0.138062 -14 15 2 0.449707 0.529785 0.138062 -14 15 3 0.449707 0.529785 0.138062 -14 15 4 0.449707 0.529785 0.138062 -14 15 5 0.449707 0.529785 0.138184 -14 15 6 0.449707 0.529785 0.138184 -14 15 7 0.449951 0.529785 0.138184 -14 15 8 0.449951 0.529785 0.138184 -14 15 9 0.449951 0.530273 0.138184 -14 15 10 0.44873 0.529785 0.162598 -14 15 11 0.443604 0.52832 0.222534 -14 15 12 0.43457 0.525391 0.286377 -14 15 13 0.419189 0.52002 0.35498 -14 15 14 0.397949 0.515625 0.431152 -14 15 15 0.367676 0.514648 0.51709 -14 15 16 0.31543 0.51123 0.607422 -14 15 17 0.215088 0.503906 0.694336 -14 15 18 0 0.494141 0.773438 -14 15 19 0 0.48291 0.842285 -14 15 20 0 0.470703 0.898438 -14 15 21 0 0.44165 0.911133 -14 15 22 0 0.416016 0.916016 -14 15 23 0 0.39624 0.920898 -14 15 24 0 0.380859 0.92627 -14 15 25 0 0.367188 0.932617 -14 15 26 0 0.355225 0.939941 -14 15 27 0 0.344971 0.947754 -14 15 28 0 0.336182 0.95752 -14 15 29 0 0.328857 0.967773 -14 15 30 0 0.322754 0.979004 -14 15 31 0 0.317627 0.990234 -14 16 0 0.376221 0.604004 0.131348 -14 16 1 0.376221 0.604004 0.131348 -14 16 2 0.376221 0.604004 0.131348 -14 16 3 0.376221 0.604004 0.131348 -14 16 4 0.376221 0.604004 0.131348 -14 16 5 0.376221 0.604004 0.131348 -14 16 6 0.376221 0.604004 0.131348 -14 16 7 0.376221 0.604004 0.13147 -14 16 8 0.376221 0.604004 0.13147 -14 16 9 0.376465 0.604492 0.13147 -14 16 10 0.376709 0.604492 0.131592 -14 16 11 0.372314 0.604004 0.198364 -14 16 12 0.364014 0.603027 0.267578 -14 16 13 0.350098 0.602051 0.34082 -14 16 14 0.327393 0.601074 0.421143 -14 16 15 0.287598 0.600098 0.508789 -14 16 16 0.206543 0.595703 0.600586 -14 16 17 0 0.587402 0.689453 -14 16 18 0 0.575195 0.770508 -14 16 19 0 0.560547 0.841309 -14 16 20 0 0.544434 0.899414 -14 16 21 0 0.511719 0.917969 -14 16 22 0 0.479736 0.924316 -14 16 23 0 0.45459 0.929199 -14 16 24 0 0.434082 0.93457 -14 16 25 0 0.416016 0.939941 -14 16 26 0 0.399902 0.946777 -14 16 27 0 0.385498 0.954102 -14 16 28 0 0.373047 0.962891 -14 16 29 0 0.362061 0.972656 -14 16 30 0 0.352783 0.98291 -14 16 31 0 0.344482 0.994141 -14 17 0 0.250488 0.684082 0.125 -14 17 1 0.250488 0.684082 0.125 -14 17 2 0.250488 0.684082 0.125 -14 17 3 0.250488 0.684082 0.125 -14 17 4 0.250488 0.684082 0.125 -14 17 5 0.250488 0.684082 0.125 -14 17 6 0.250488 0.684082 0.125 -14 17 7 0.250488 0.684082 0.125122 -14 17 8 0.250732 0.684082 0.125122 -14 17 9 0.250977 0.684082 0.125122 -14 17 10 0.251465 0.68457 0.125244 -14 17 11 0.248291 0.685059 0.164917 -14 17 12 0.234741 0.685547 0.244995 -14 17 13 0.209229 0.686035 0.323242 -14 17 14 0.153198 0.686523 0.40625 -14 17 15 0 0.686035 0.495361 -14 17 16 0 0.682617 0.588867 -14 17 17 0 0.674316 0.680664 -14 17 18 0 0.661133 0.764648 -14 17 19 0 0.644043 0.837891 -14 17 20 0 0.625 0.897949 -14 17 21 0 0.590332 0.925293 -14 17 22 0 0.553711 0.935059 -14 17 23 0 0.522949 0.941406 -14 17 24 0 0.497559 0.946289 -14 17 25 0 0.474609 0.95166 -14 17 26 0 0.453369 0.957031 -14 17 27 0 0.434326 0.963379 -14 17 28 0 0.417725 0.971191 -14 17 29 0 0.402588 0.97998 -14 17 30 0 0.389404 0.989258 -14 17 31 0 0.377686 0.999512 -14 18 0 0 0.76123 0.117798 -14 18 1 0 0.76123 0.117798 -14 18 2 0 0.76123 0.117798 -14 18 3 0 0.76123 0.117798 -14 18 4 0 0.76123 0.117798 -14 18 5 0 0.76123 0.117859 -14 18 6 0 0.76123 0.117859 -14 18 7 0 0.76123 0.117859 -14 18 8 0 0.761719 0.117859 -14 18 9 0 0.761719 0.11792 -14 18 10 0 0.761719 0.117981 -14 18 11 0 0.762207 0.118164 -14 18 12 0 0.763184 0.2146 -14 18 13 0 0.764648 0.300049 -14 18 14 0 0.766602 0.38623 -14 18 15 0 0.767578 0.477051 -14 18 16 0 0.765137 0.572266 -14 18 17 0 0.758301 0.666016 -14 18 18 0 0.746094 0.753906 -14 18 19 0 0.729004 0.830566 -14 18 20 0 0.708008 0.893555 -14 18 21 0 0.674316 0.930664 -14 18 22 0 0.634766 0.947266 -14 18 23 0 0.599609 0.956055 -14 18 24 0 0.569336 0.961914 -14 18 25 0 0.541016 0.966797 -14 18 26 0 0.515137 0.97168 -14 18 27 0 0.490723 0.977051 -14 18 28 0 0.469238 0.98291 -14 18 29 0 0.449707 0.990234 -14 18 30 0 0.432129 0.998047 -14 18 31 0 0.416504 1 -14 19 0 0 0.831543 0.109558 -14 19 1 0 0.831543 0.109558 -14 19 2 0 0.831543 0.109558 -14 19 3 0 0.831543 0.109558 -14 19 4 0 0.831543 0.109558 -14 19 5 0 0.831543 0.109558 -14 19 6 0 0.831543 0.109558 -14 19 7 0 0.831543 0.109558 -14 19 8 0 0.831543 0.109619 -14 19 9 0 0.831543 0.10968 -14 19 10 0 0.831543 0.109741 -14 19 11 0 0.832031 0.109924 -14 19 12 0 0.833008 0.172852 -14 19 13 0 0.834961 0.271729 -14 19 14 0 0.837402 0.362061 -14 19 15 0 0.839355 0.454346 -14 19 16 0 0.839844 0.550781 -14 19 17 0 0.835449 0.646973 -14 19 18 0 0.825195 0.737793 -14 19 19 0 0.809082 0.817871 -14 19 20 0 0.788086 0.884277 -14 19 21 0 0.756836 0.931152 -14 19 22 0 0.71875 0.95752 -14 19 23 0 0.681152 0.97168 -14 19 24 0 0.646973 0.97998 -14 19 25 0 0.61377 0.98584 -14 19 26 0 0.58252 0.990234 -14 19 27 0 0.552734 0.994141 -14 19 28 0 0.525879 0.998535 -14 19 29 0 0.501465 1 -14 19 30 0 0.479248 1 -14 19 31 0 0.459229 1 -14 20 0 0 0.89209 0.100403 -14 20 1 0 0.89209 0.100403 -14 20 2 0 0.89209 0.100403 -14 20 3 0 0.89209 0.100403 -14 20 4 0 0.89209 0.100403 -14 20 5 0 0.89209 0.100403 -14 20 6 0 0.89209 0.100403 -14 20 7 0 0.89209 0.100403 -14 20 8 0 0.89209 0.100464 -14 20 9 0 0.89209 0.100464 -14 20 10 0 0.892578 0.100586 -14 20 11 0 0.892578 0.100769 -14 20 12 0 0.893066 0.103088 -14 20 13 0 0.89502 0.238281 -14 20 14 0 0.898438 0.335205 -14 20 15 0 0.901367 0.429443 -14 20 16 0 0.90332 0.526855 -14 20 17 0 0.901855 0.624512 -14 20 18 0 0.894531 0.717285 -14 20 19 0 0.880371 0.800293 -14 20 20 0 0.86084 0.870605 -14 20 21 0 0.833984 0.92627 -14 20 22 0 0.799316 0.962891 -14 20 23 0 0.761719 0.984375 -14 20 24 0 0.725586 0.996582 -14 20 25 0 0.688965 1 -14 20 26 0 0.652344 1 -14 20 27 0 0.618164 1 -14 20 28 0 0.585938 1 -14 20 29 0 0.556152 1 -14 20 30 0 0.529297 1 -14 20 31 0 0.504395 1 -14 21 0 0 0.943848 0.0899658 -14 21 1 0 0.943848 0.0899658 -14 21 2 0 0.943848 0.0899658 -14 21 3 0 0.943848 0.0899658 -14 21 4 0 0.943848 0.0899658 -14 21 5 0 0.943848 0.0899658 -14 21 6 0 0.943848 0.0900269 -14 21 7 0 0.943848 0.0900269 -14 21 8 0 0.943848 0.0900269 -14 21 9 0 0.943848 0.0900879 -14 21 10 0 0.943848 0.09021 -14 21 11 0 0.943848 0.0903931 -14 21 12 0 0.944336 0.0906982 -14 21 13 0 0.945801 0.196777 -14 21 14 0 0.949707 0.304932 -14 21 15 0 0.953613 0.402344 -14 21 16 0 0.957031 0.500488 -14 21 17 0 0.958008 0.598145 -14 21 18 0 0.953613 0.692383 -14 21 19 0 0.942871 0.777832 -14 21 20 0 0.925781 0.851562 -14 21 21 0 0.902832 0.913086 -14 21 22 0 0.873535 0.959961 -14 21 23 0 0.838867 0.990234 -14 21 24 0 0.802734 1 -14 21 25 0 0.76416 1 -14 21 26 0 0.724609 1 -14 21 27 0 0.685547 1 -14 21 28 0 0.648438 1 -14 21 29 0 0.61377 1 -14 21 30 0 0.582031 1 -14 21 31 0 0.552734 1 -14 22 0 0 0.986328 0.0782471 -14 22 1 0 0.986328 0.0782471 -14 22 2 0 0.986328 0.0782471 -14 22 3 0 0.986328 0.0783081 -14 22 4 0 0.986328 0.0783081 -14 22 5 0 0.986328 0.0783081 -14 22 6 0 0.986328 0.0783081 -14 22 7 0 0.986328 0.0783081 -14 22 8 0 0.986328 0.0783691 -14 22 9 0 0.986328 0.0784302 -14 22 10 0 0.986328 0.0785522 -14 22 11 0 0.986816 0.0787354 -14 22 12 0 0.986816 0.0791016 -14 22 13 0 0.987793 0.139526 -14 22 14 0 0.991211 0.271973 -14 22 15 0 0.996094 0.373535 -14 22 16 0 1 0.472412 -14 22 17 0 1 0.570312 -14 22 18 0 1 0.665039 -14 22 19 0 0.994629 0.752441 -14 22 20 0 0.980957 0.828613 -14 22 21 0 0.961426 0.894043 -14 22 22 0 0.936523 0.947266 -14 22 23 0 0.906738 0.986328 -14 22 24 0 0.873047 1 -14 22 25 0 0.834961 1 -14 22 26 0 0.794434 1 -14 22 27 0 0.752441 1 -14 22 28 0 0.711426 1 -14 22 29 0 0.672363 1 -14 22 30 0 0.635742 1 -14 22 31 0 0.602051 1 -14 23 0 0 1 0.0650024 -14 23 1 0 1 0.0650024 -14 23 2 0 1 0.0650024 -14 23 3 0 1 0.0650024 -14 23 4 0 1 0.0650024 -14 23 5 0 1 0.0650024 -14 23 6 0 1 0.0650024 -14 23 7 0 1 0.0650635 -14 23 8 0 1 0.0651245 -14 23 9 0 1 0.0651855 -14 23 10 0 1 0.0653076 -14 23 11 0 1 0.0656128 -14 23 12 0 1 0.06604 -14 23 13 0 1 0.0667114 -14 23 14 0 1 0.236694 -14 23 15 0 1 0.344727 -14 23 16 0 1 0.44458 -14 23 17 0 1 0.54248 -14 23 18 0 1 0.637207 -14 23 19 0 1 0.725098 -14 23 20 0 1 0.803223 -14 23 21 0 1 0.871582 -14 23 22 0 0.987305 0.928711 -14 23 23 0 0.961914 0.973145 -14 23 24 0 0.932617 1 -14 23 25 0 0.897461 1 -14 23 26 0 0.857422 1 -14 23 27 0 0.814941 1 -14 23 28 0 0.771484 1 -14 23 29 0 0.729004 1 -14 23 30 0 0.688477 1 -14 23 31 0 0.650391 1 -14 24 0 0 1 0.0481567 -14 24 1 0 1 0.0481567 -14 24 2 0 1 0.0481567 -14 24 3 0 1 0.0481567 -14 24 4 0 1 0.0481567 -14 24 5 0 1 0.0481567 -14 24 6 0 1 0.0481873 -14 24 7 0 1 0.0482178 -14 24 8 0 1 0.0482788 -14 24 9 0 1 0.0484009 -14 24 10 0 1 0.0486145 -14 24 11 0 1 0.0490112 -14 24 12 0 1 0.0496521 -14 24 13 0 1 0.0506592 -14 24 14 0 1 0.196899 -14 24 15 0 1 0.315674 -14 24 16 0 1 0.417236 -14 24 17 0 1 0.514648 -14 24 18 0 1 0.608887 -14 24 19 0 1 0.697266 -14 24 20 0 1 0.776367 -14 24 21 0 1 0.84668 -14 24 22 0 1 0.906738 -14 24 23 0 1 0.955078 -14 24 24 0 0.981934 0.993652 -14 24 25 0 0.950684 1 -14 24 26 0 0.913574 1 -14 24 27 0 0.871094 1 -14 24 28 0 0.827148 1 -14 24 29 0 0.782227 1 -14 24 30 0 0.73877 1 -14 24 31 0 0.697266 1 -14 25 0 0 1 0 -14 25 1 0 1 0 -14 25 2 0 1 0 -14 25 3 0 1 0 -14 25 4 0 1 0 -14 25 5 0 1 0 -14 25 6 0 1 0 -14 25 7 0 1 0 -14 25 8 0 1 0 -14 25 9 0 1 0 -14 25 10 0 1 0 -14 25 11 0 1 0 -14 25 12 0 1 0 -14 25 13 0 1 0 -14 25 14 0 1 0.140625 -14 25 15 0 1 0.282959 -14 25 16 0 1 0.387695 -14 25 17 0 1 0.485107 -14 25 18 0 1 0.578613 -14 25 19 0 1 0.666504 -14 25 20 0 1 0.746094 -14 25 21 0 1 0.818359 -14 25 22 0 1 0.880859 -14 25 23 0 1 0.932129 -14 25 24 0 1 0.974609 -14 25 25 0 0.999512 1 -14 25 26 0 0.966309 1 -14 25 27 0 0.92627 1 -14 25 28 0 0.882812 1 -14 25 29 0 0.836914 1 -14 25 30 0 0.791016 1 -14 25 31 0 0.746582 1 -14 26 0 0 1 0 -14 26 1 0 1 0 -14 26 2 0 1 0 -14 26 3 0 1 0 -14 26 4 0 1 0 -14 26 5 0 1 0 -14 26 6 0 1 0 -14 26 7 0 1 0 -14 26 8 0 1 0 -14 26 9 0 1 0 -14 26 10 0 1 0 -14 26 11 0 1 0 -14 26 12 0 1 0 -14 26 13 0 1 0 -14 26 14 0 1 0 -14 26 15 0 1 0.245483 -14 26 16 0 1 0.355957 -14 26 17 0 1 0.453613 -14 26 18 0 1 0.545898 -14 26 19 0 1 0.632812 -14 26 20 0 1 0.712891 -14 26 21 0 1 0.785645 -14 26 22 0 1 0.850098 -14 26 23 0 1 0.904297 -14 26 24 0 1 0.949707 -14 26 25 0 1 0.990723 -14 26 26 0 1 1 -14 26 27 0 0.978516 1 -14 26 28 0 0.937012 1 -14 26 29 0 0.891602 1 -14 26 30 0 0.844727 1 -14 26 31 0 0.797852 1 -14 27 0 0 1 0 -14 27 1 0 1 0 -14 27 2 0 1 0 -14 27 3 0 1 0 -14 27 4 0 1 0 -14 27 5 0 1 0 -14 27 6 0 1 0 -14 27 7 0 1 0 -14 27 8 0 1 0 -14 27 9 0 1 0 -14 27 10 0 1 0 -14 27 11 0 1 0 -14 27 12 0 1 0 -14 27 13 0 1 0 -14 27 14 0 1 0 -14 27 15 0 1 0.199585 -14 27 16 0 1 0.321289 -14 27 17 0 1 0.420166 -14 27 18 0 1 0.511719 -14 27 19 0 1 0.597168 -14 27 20 0 1 0.67627 -14 27 21 0 1 0.749512 -14 27 22 0 1 0.81543 -14 27 23 0 1 0.87207 -14 27 24 0 1 0.919922 -14 27 25 0 1 0.964355 -14 27 26 0 1 1 -14 27 27 0 1 1 -14 27 28 0 0.987793 1 -14 27 29 0 0.943848 1 -14 27 30 0 0.897461 1 -14 27 31 0 0.849609 1 -14 28 0 0 1 0 -14 28 1 0 1 0 -14 28 2 0 1 0 -14 28 3 0 1 0 -14 28 4 0 1 0 -14 28 5 0 1 0 -14 28 6 0 1 0 -14 28 7 0 1 0 -14 28 8 0 1 0 -14 28 9 0 1 0 -14 28 10 0 1 0 -14 28 11 0 1 0 -14 28 12 0 1 0 -14 28 13 0 1 0 -14 28 14 0 1 0 -14 28 15 0 1 0.132935 -14 28 16 0 1 0.282959 -14 28 17 0 1 0.384766 -14 28 18 0 1 0.47583 -14 28 19 0 1 0.560059 -14 28 20 0 1 0.638184 -14 28 21 0 1 0.710938 -14 28 22 0 1 0.777344 -14 28 23 0 1 0.834961 -14 28 24 0 1 0.885254 -14 28 25 0 1 0.932129 -14 28 26 0 1 0.976074 -14 28 27 0 1 1 -14 28 28 0 1 1 -14 28 29 0 0.993652 1 -14 28 30 0 0.94873 1 -14 28 31 0 0.901367 1 -14 29 0 0 1 0 -14 29 1 0 1 0 -14 29 2 0 1 0 -14 29 3 0 1 0 -14 29 4 0 1 0 -14 29 5 0 1 0 -14 29 6 0 1 0 -14 29 7 0 1 0 -14 29 8 0 1 0 -14 29 9 0 1 0 -14 29 10 0 1 0 -14 29 11 0 1 0 -14 29 12 0 1 0 -14 29 13 0 1 0 -14 29 14 0 1 0 -14 29 15 0 1 0 -14 29 16 0 1 0.239136 -14 29 17 0 1 0.347168 -14 29 18 0 1 0.438232 -14 29 19 0 1 0.521484 -14 29 20 0 1 0.597656 -14 29 21 0 1 0.669434 -14 29 22 0 1 0.735352 -14 29 23 0 1 0.793945 -14 29 24 0 1 0.845215 -14 29 25 0 1 0.894531 -14 29 26 0 1 0.941406 -14 29 27 0 1 0.983887 -14 29 28 0 1 1 -14 29 29 0 1 1 -14 29 30 0 0.998047 1 -14 29 31 0 0.952637 1 -14 30 0 0 1 0 -14 30 1 0 1 0 -14 30 2 0 1 0 -14 30 3 0 1 0 -14 30 4 0 1 0 -14 30 5 0 1 0 -14 30 6 0 1 0 -14 30 7 0 1 0 -14 30 8 0 1 0 -14 30 9 0 1 0 -14 30 10 0 1 0 -14 30 11 0 1 0 -14 30 12 0 1 0 -14 30 13 0 1 0 -14 30 14 0 1 0 -14 30 15 0 1 0 -14 30 16 0 1 0.184937 -14 30 17 0 1 0.306641 -14 30 18 0 1 0.39917 -14 30 19 0 1 0.480957 -14 30 20 0 1 0.555664 -14 30 21 0 1 0.625977 -14 30 22 0 1 0.690918 -14 30 23 0 1 0.749023 -14 30 24 0 1 0.80127 -14 30 25 0 1 0.852051 -14 30 26 0 1 0.901367 -14 30 27 0 1 0.947266 -14 30 28 0 1 0.989258 -14 30 29 0 1 1 -14 30 30 0 1 1 -14 30 31 0 1 1 -14 31 0 0 1 0 -14 31 1 0 1 0 -14 31 2 0 1 0 -14 31 3 0 1 0 -14 31 4 0 1 0 -14 31 5 0 1 0 -14 31 6 0 1 0 -14 31 7 0 1 0 -14 31 8 0 1 0 -14 31 9 0 1 0 -14 31 10 0 1 0 -14 31 11 0 1 0 -14 31 12 0 1 0 -14 31 13 0 1 0 -14 31 14 0 1 0 -14 31 15 0 1 0 -14 31 16 0 1 0.0941162 -14 31 17 0 1 0.262451 -14 31 18 0 1 0.358398 -14 31 19 0 1 0.439697 -14 31 20 0 1 0.512695 -14 31 21 0 1 0.581055 -14 31 22 0 1 0.644531 -14 31 23 0 1 0.70166 -14 31 24 0 1 0.753906 -14 31 25 0 1 0.805664 -14 31 26 0 1 0.856445 -14 31 27 0 1 0.905762 -14 31 28 0 1 0.952148 -14 31 29 0 1 0.993652 -14 31 30 0 1 1 -14 31 31 0 1 1 -15 0 0 0.635742 0 0.0386963 -15 0 1 0.635742 0 0.0386963 -15 0 2 0.635742 0 0.0386658 -15 0 3 0.635742 0 0.0386658 -15 0 4 0.635742 0 0.0386047 -15 0 5 0.635742 0 0.0385437 -15 0 6 0.635742 0 0.0383911 -15 0 7 0.635742 0 0.0381165 -15 0 8 0.635742 0 0.0375366 -15 0 9 0.63623 0 0.0366211 -15 0 10 0.638672 0 0.0359192 -15 0 11 0.641113 0 0.19104 -15 0 12 0.641113 0 0.282227 -15 0 13 0.630371 0 0.369141 -15 0 14 0.602051 0.166748 0.444824 -15 0 15 0.580078 0.195679 0.525879 -15 0 16 0.550293 0.20813 0.613281 -15 0 17 0.506348 0.221313 0.697754 -15 0 18 0.446045 0.234131 0.774902 -15 0 19 0.365967 0.245972 0.842285 -15 0 20 0.245972 0.256104 0.897461 -15 0 21 0 0.253418 0.90332 -15 0 22 0 0.251709 0.908203 -15 0 23 0 0.250732 0.914062 -15 0 24 0 0.250732 0.92041 -15 0 25 0 0.251221 0.927734 -15 0 26 0 0.252441 0.936035 -15 0 27 0 0.253906 0.945801 -15 0 28 0 0.255615 0.956055 -15 0 29 0 0.257568 0.966797 -15 0 30 0 0.259766 0.977539 -15 0 31 0 0.262451 0.989258 -15 1 0 0.635742 0 0.0386047 -15 1 1 0.635742 0 0.0386047 -15 1 2 0.635742 0 0.0386047 -15 1 3 0.635742 0 0.0385742 -15 1 4 0.635742 0 0.0385437 -15 1 5 0.635742 0 0.0384521 -15 1 6 0.635742 0 0.0382996 -15 1 7 0.635742 0 0.0380249 -15 1 8 0.635742 0 0.0374756 -15 1 9 0.63623 0 0.0365295 -15 1 10 0.638672 0 0.0358276 -15 1 11 0.641113 0 0.19104 -15 1 12 0.641113 0 0.282227 -15 1 13 0.630371 0 0.369141 -15 1 14 0.602051 0.16687 0.444824 -15 1 15 0.580078 0.195801 0.525879 -15 1 16 0.550293 0.208252 0.613281 -15 1 17 0.506348 0.221313 0.697754 -15 1 18 0.446045 0.234131 0.774902 -15 1 19 0.365723 0.246094 0.842285 -15 1 20 0.245972 0.256104 0.897461 -15 1 21 0 0.253418 0.90332 -15 1 22 0 0.251709 0.908203 -15 1 23 0 0.250977 0.914062 -15 1 24 0 0.250732 0.92041 -15 1 25 0 0.251221 0.927734 -15 1 26 0 0.252441 0.936035 -15 1 27 0 0.253906 0.945801 -15 1 28 0 0.255615 0.956055 -15 1 29 0 0.257568 0.966797 -15 1 30 0 0.259766 0.977539 -15 1 31 0 0.262451 0.989258 -15 2 0 0.635742 0 0.0384827 -15 2 1 0.635742 0 0.0384521 -15 2 2 0.635742 0 0.0384521 -15 2 3 0.635742 0 0.0384216 -15 2 4 0.635742 0 0.0383911 -15 2 5 0.635742 0 0.0383301 -15 2 6 0.635742 0 0.0381775 -15 2 7 0.635742 0 0.0379028 -15 2 8 0.635742 0 0.037323 -15 2 9 0.63623 0 0.036377 -15 2 10 0.638672 0 0.035675 -15 2 11 0.641113 0 0.19104 -15 2 12 0.641113 0 0.282227 -15 2 13 0.630371 0 0.369141 -15 2 14 0.602051 0.166992 0.444824 -15 2 15 0.580078 0.195923 0.525879 -15 2 16 0.550293 0.208374 0.613281 -15 2 17 0.506348 0.221436 0.697754 -15 2 18 0.446045 0.234253 0.774902 -15 2 19 0.365723 0.246094 0.842285 -15 2 20 0.245972 0.256104 0.897461 -15 2 21 0 0.253418 0.90332 -15 2 22 0 0.251709 0.908203 -15 2 23 0 0.250977 0.914062 -15 2 24 0 0.250732 0.92041 -15 2 25 0 0.251465 0.927734 -15 2 26 0 0.252441 0.936035 -15 2 27 0 0.253906 0.945801 -15 2 28 0 0.255615 0.956055 -15 2 29 0 0.257568 0.966797 -15 2 30 0 0.26001 0.977539 -15 2 31 0 0.262451 0.989258 -15 3 0 0.635742 0 0.038208 -15 3 1 0.635742 0 0.038208 -15 3 2 0.635742 0 0.038208 -15 3 3 0.635742 0 0.0381775 -15 3 4 0.635742 0 0.038147 -15 3 5 0.635742 0 0.0380554 -15 3 6 0.635742 0 0.0379028 -15 3 7 0.635742 0 0.0376282 -15 3 8 0.635742 0 0.0370483 -15 3 9 0.63623 0 0.0361023 -15 3 10 0.638672 0 0.0353699 -15 3 11 0.641113 0 0.190918 -15 3 12 0.641113 0 0.281982 -15 3 13 0.629883 0 0.369141 -15 3 14 0.602051 0.16748 0.444824 -15 3 15 0.580078 0.196167 0.525879 -15 3 16 0.550293 0.208618 0.613281 -15 3 17 0.506348 0.22168 0.697754 -15 3 18 0.446045 0.234497 0.774902 -15 3 19 0.365723 0.246338 0.842285 -15 3 20 0.245972 0.256348 0.897461 -15 3 21 0 0.253662 0.90332 -15 3 22 0 0.251709 0.908203 -15 3 23 0 0.250977 0.914062 -15 3 24 0 0.250977 0.92041 -15 3 25 0 0.251465 0.927734 -15 3 26 0 0.252441 0.936035 -15 3 27 0 0.253906 0.945801 -15 3 28 0 0.255615 0.956055 -15 3 29 0 0.257568 0.966797 -15 3 30 0 0.26001 0.977539 -15 3 31 0 0.262451 0.989258 -15 4 0 0.635742 0 0.0377197 -15 4 1 0.635742 0 0.0377197 -15 4 2 0.635742 0 0.0377197 -15 4 3 0.635742 0 0.0376892 -15 4 4 0.635742 0 0.0376587 -15 4 5 0.635742 0 0.0375671 -15 4 6 0.635742 0 0.0374146 -15 4 7 0.635742 0 0.0371094 -15 4 8 0.635742 0 0.0365295 -15 4 9 0.63623 0 0.035553 -15 4 10 0.638672 0 0.0348206 -15 4 11 0.641113 0 0.190918 -15 4 12 0.641113 0 0.281982 -15 4 13 0.629883 0 0.369141 -15 4 14 0.602051 0.168091 0.444824 -15 4 15 0.580078 0.196777 0.525879 -15 4 16 0.550293 0.209106 0.613281 -15 4 17 0.506348 0.222046 0.697754 -15 4 18 0.445801 0.234863 0.774902 -15 4 19 0.365723 0.246582 0.842285 -15 4 20 0.24585 0.256592 0.897461 -15 4 21 0 0.253662 0.90332 -15 4 22 0 0.251953 0.908203 -15 4 23 0 0.251221 0.914062 -15 4 24 0 0.250977 0.92041 -15 4 25 0 0.251465 0.927734 -15 4 26 0 0.252441 0.936035 -15 4 27 0 0.25415 0.945801 -15 4 28 0 0.255859 0.956055 -15 4 29 0 0.257812 0.966797 -15 4 30 0 0.26001 0.977539 -15 4 31 0 0.262451 0.989258 -15 5 0 0.635742 0 0.0367432 -15 5 1 0.635742 0 0.0367432 -15 5 2 0.635742 0 0.0367126 -15 5 3 0.635742 0 0.0367126 -15 5 4 0.635742 0 0.0366516 -15 5 5 0.635742 0 0.0365906 -15 5 6 0.635742 0 0.0364075 -15 5 7 0.635742 0 0.0361023 -15 5 8 0.635742 0 0.0354919 -15 5 9 0.63623 0 0.0344543 -15 5 10 0.638672 0 0.0337219 -15 5 11 0.640625 0 0.190796 -15 5 12 0.641113 0 0.281982 -15 5 13 0.629883 0 0.369141 -15 5 14 0.601562 0.169556 0.444824 -15 5 15 0.580078 0.197876 0.525879 -15 5 16 0.550293 0.210083 0.613281 -15 5 17 0.506348 0.2229 0.697754 -15 5 18 0.445801 0.235474 0.774902 -15 5 19 0.365723 0.247192 0.842285 -15 5 20 0.245605 0.25708 0.897461 -15 5 21 0 0.25415 0.90332 -15 5 22 0 0.252197 0.908203 -15 5 23 0 0.251465 0.914062 -15 5 24 0 0.251221 0.92041 -15 5 25 0 0.251709 0.927734 -15 5 26 0 0.252686 0.936035 -15 5 27 0 0.25415 0.945801 -15 5 28 0 0.255859 0.956055 -15 5 29 0 0.257812 0.966797 -15 5 30 0 0.26001 0.977539 -15 5 31 0 0.262451 0.989258 -15 6 0 0.635254 0 0.034729 -15 6 1 0.635254 0 0.034729 -15 6 2 0.635254 0 0.034729 -15 6 3 0.635254 0 0.0346985 -15 6 4 0.635742 0 0.0346375 -15 6 5 0.635742 0 0.0345764 -15 6 6 0.635742 0 0.0343933 -15 6 7 0.635742 0 0.0340576 -15 6 8 0.635742 0 0.0333862 -15 6 9 0.635742 0 0.0322266 -15 6 10 0.638672 0 0.0314026 -15 6 11 0.640625 0 0.190674 -15 6 12 0.641113 0 0.281982 -15 6 13 0.629883 0 0.368896 -15 6 14 0.601562 0.172119 0.444824 -15 6 15 0.580078 0.199951 0.525879 -15 6 16 0.550293 0.211792 0.612793 -15 6 17 0.505859 0.224487 0.697754 -15 6 18 0.445557 0.236816 0.774902 -15 6 19 0.365479 0.248291 0.842285 -15 6 20 0.245239 0.258057 0.897461 -15 6 21 0 0.254883 0.90332 -15 6 22 0 0.25293 0.908691 -15 6 23 0 0.251953 0.914062 -15 6 24 0 0.251709 0.92041 -15 6 25 0 0.252197 0.927734 -15 6 26 0 0.253174 0.936035 -15 6 27 0 0.254395 0.946289 -15 6 28 0 0.256104 0.956055 -15 6 29 0 0.258057 0.966797 -15 6 30 0 0.260254 0.977539 -15 6 31 0 0.262695 0.989258 -15 7 0 0.635254 0 0.0302124 -15 7 1 0.635254 0 0.0301971 -15 7 2 0.635254 0 0.0301819 -15 7 3 0.635254 0 0.0301514 -15 7 4 0.635254 0 0.0300903 -15 7 5 0.635254 0 0.0299835 -15 7 6 0.635254 0 0.0297699 -15 7 7 0.635254 0 0.0293274 -15 7 8 0.635254 0 0.0284576 -15 7 9 0.635742 0 0.026947 -15 7 10 0.638672 0 0.0258484 -15 7 11 0.640625 0 0.190308 -15 7 12 0.641113 0 0.281738 -15 7 13 0.629883 0.00761414 0.368896 -15 7 14 0.601562 0.177002 0.444824 -15 7 15 0.57959 0.203735 0.525879 -15 7 16 0.549805 0.21521 0.612793 -15 7 17 0.505859 0.227295 0.697754 -15 7 18 0.445312 0.239258 0.774902 -15 7 19 0.36499 0.250244 0.842285 -15 7 20 0.244629 0.259766 0.897461 -15 7 21 0 0.256348 0.90332 -15 7 22 0 0.25415 0.908691 -15 7 23 0 0.25293 0.914062 -15 7 24 0 0.252686 0.92041 -15 7 25 0 0.25293 0.927734 -15 7 26 0 0.253662 0.936523 -15 7 27 0 0.255127 0.946289 -15 7 28 0 0.256592 0.956055 -15 7 29 0 0.258545 0.966797 -15 7 30 0 0.260742 0.977539 -15 7 31 0 0.262939 0.989258 -15 8 0 0.634766 0 0.0141602 -15 8 1 0.634766 0 0.0141296 -15 8 2 0.634766 0 0.0140762 -15 8 3 0.634766 0 0.0139694 -15 8 4 0.634766 0 0.0137711 -15 8 5 0.634766 0 0.0133667 -15 8 6 0.634766 0 0.0125427 -15 8 7 0.635254 0 0.0106201 -15 8 8 0.635254 0.0114517 0 -15 8 9 0.635254 0.043396 0 -15 8 10 0.638184 0.0521851 0 -15 8 11 0.640137 0 0.189575 -15 8 12 0.640625 0 0.28125 -15 8 13 0.629883 0.0869141 0.368652 -15 8 14 0.601074 0.185913 0.444824 -15 8 15 0.579102 0.21106 0.525391 -15 8 16 0.549316 0.22168 0.612793 -15 8 17 0.505371 0.23291 0.697754 -15 8 18 0.444824 0.244019 0.774902 -15 8 19 0.364258 0.254395 0.842285 -15 8 20 0.243286 0.263184 0.897461 -15 8 21 0 0.259277 0.903809 -15 8 22 0 0.256348 0.908691 -15 8 23 0 0.254883 0.914551 -15 8 24 0 0.254395 0.92041 -15 8 25 0 0.254395 0.927734 -15 8 26 0 0.255127 0.936523 -15 8 27 0 0.256104 0.946289 -15 8 28 0 0.257568 0.956055 -15 8 29 0 0.259277 0.966797 -15 8 30 0 0.26123 0.978027 -15 8 31 0 0.263672 0.989258 -15 9 0 0.634277 0.115234 0 -15 9 1 0.634277 0.115234 0 -15 9 2 0.634277 0.115295 0 -15 9 3 0.634277 0.115356 0 -15 9 4 0.634277 0.115479 0 -15 9 5 0.634277 0.115784 0 -15 9 6 0.634277 0.116333 0 -15 9 7 0.634277 0.11731 0 -15 9 8 0.634277 0.119263 0 -15 9 9 0.634766 0.122498 0 -15 9 10 0.637207 0.124329 0 -15 9 11 0.639648 0.116028 0.188477 -15 9 12 0.639648 0.109741 0.280762 -15 9 13 0.629883 0.13147 0.368408 -15 9 14 0.600586 0.201416 0.444824 -15 9 15 0.578125 0.223877 0.525391 -15 9 16 0.54834 0.233276 0.612793 -15 9 17 0.503906 0.243042 0.697754 -15 9 18 0.443604 0.252686 0.774902 -15 9 19 0.362793 0.261719 0.842285 -15 9 20 0.240601 0.269531 0.897949 -15 9 21 0 0.264404 0.903809 -15 9 22 0 0.260742 0.90918 -15 9 23 0 0.258789 0.914551 -15 9 24 0 0.257568 0.920898 -15 9 25 0 0.257324 0.928223 -15 9 26 0 0.257568 0.937012 -15 9 27 0 0.258301 0.946777 -15 9 28 0 0.259277 0.956055 -15 9 29 0 0.260742 0.966797 -15 9 30 0 0.262695 0.978027 -15 9 31 0 0.264648 0.989746 -15 10 0 0.632812 0.175537 0 -15 10 1 0.632812 0.175537 0 -15 10 2 0.632812 0.175537 0 -15 10 3 0.632812 0.175537 0 -15 10 4 0.632812 0.175659 0 -15 10 5 0.632812 0.175781 0 -15 10 6 0.632812 0.176025 0 -15 10 7 0.632812 0.176636 0 -15 10 8 0.632812 0.177612 0 -15 10 9 0.632812 0.179443 0 -15 10 10 0.635742 0.180298 0 -15 10 11 0.637695 0.175903 0.187012 -15 10 12 0.637695 0.172729 0.279541 -15 10 13 0.628906 0.178833 0.367676 -15 10 14 0.599121 0.225586 0.444824 -15 10 15 0.576172 0.244751 0.525391 -15 10 16 0.546387 0.252197 0.612793 -15 10 17 0.501953 0.259766 0.697754 -15 10 18 0.441406 0.267334 0.774902 -15 10 19 0.359863 0.274414 0.842285 -15 10 20 0.235596 0.280518 0.897949 -15 10 21 0 0.273682 0.904785 -15 10 22 0 0.268555 0.909668 -15 10 23 0 0.265381 0.915039 -15 10 24 0 0.263428 0.921387 -15 10 25 0 0.262207 0.928711 -15 10 26 0 0.261963 0.9375 -15 10 27 0 0.261963 0.946777 -15 10 28 0 0.262695 0.956543 -15 10 29 0 0.263672 0.966797 -15 10 30 0 0.265137 0.978027 -15 10 31 0 0.266846 0.989746 -15 11 0 0.629395 0.235962 0 -15 11 1 0.629395 0.235962 0 -15 11 2 0.629395 0.236084 0 -15 11 3 0.629395 0.236084 0 -15 11 4 0.629395 0.236084 0 -15 11 5 0.629395 0.236206 0 -15 11 6 0.629395 0.236328 0 -15 11 7 0.629395 0.236694 0 -15 11 8 0.629395 0.237305 0 -15 11 9 0.629395 0.238525 0 -15 11 10 0.631836 0.239014 0.0408325 -15 11 11 0.633789 0.236694 0.186279 -15 11 12 0.635254 0.233398 0.276855 -15 11 13 0.627441 0.233398 0.366211 -15 11 14 0.597168 0.260254 0.444824 -15 11 15 0.573242 0.275635 0.524902 -15 11 16 0.543457 0.280762 0.612793 -15 11 17 0.498779 0.285645 0.697754 -15 11 18 0.4375 0.290283 0.774902 -15 11 19 0.35498 0.294678 0.842773 -15 11 20 0.226562 0.298096 0.898438 -15 11 21 0 0.288574 0.905762 -15 11 22 0 0.28125 0.910645 -15 11 23 0 0.276367 0.916016 -15 11 24 0 0.273193 0.922363 -15 11 25 0 0.270752 0.929688 -15 11 26 0 0.269287 0.938477 -15 11 27 0 0.268311 0.947266 -15 11 28 0 0.268066 0.957031 -15 11 29 0 0.268555 0.967285 -15 11 30 0 0.269287 0.978516 -15 11 31 0 0.270508 0.989746 -15 12 0 0.623047 0.301514 0 -15 12 1 0.623047 0.301514 0 -15 12 2 0.623047 0.301514 0 -15 12 3 0.623047 0.301514 0 -15 12 4 0.623047 0.301514 0 -15 12 5 0.623047 0.301514 0 -15 12 6 0.623047 0.301758 0 -15 12 7 0.623047 0.302002 0 -15 12 8 0.623047 0.302246 0 -15 12 9 0.623047 0.302979 0 -15 12 10 0.624023 0.303467 0.0870361 -15 12 11 0.625488 0.302734 0.190308 -15 12 12 0.626953 0.300781 0.274414 -15 12 13 0.62207 0.298096 0.363037 -15 12 14 0.59375 0.307129 0.44458 -15 12 15 0.567871 0.318115 0.524414 -15 12 16 0.537598 0.321045 0.612305 -15 12 17 0.492676 0.322998 0.697754 -15 12 18 0.430664 0.324219 0.775391 -15 12 19 0.346191 0.324951 0.843262 -15 12 20 0.209351 0.325195 0.898926 -15 12 21 0 0.312012 0.907227 -15 12 22 0 0.301514 0.912109 -15 12 23 0 0.293945 0.917969 -15 12 24 0 0.288574 0.924316 -15 12 25 0 0.284424 0.931641 -15 12 26 0 0.28125 0.939941 -15 12 27 0 0.278809 0.947754 -15 12 28 0 0.2771 0.95752 -15 12 29 0 0.276367 0.967773 -15 12 30 0 0.276123 0.979004 -15 12 31 0 0.276367 0.990234 -15 13 0 0.612305 0.37085 0.0724487 -15 13 1 0.612305 0.37085 0.0724487 -15 13 2 0.612305 0.37085 0.0724487 -15 13 3 0.612305 0.37085 0.0725098 -15 13 4 0.612305 0.37085 0.0725098 -15 13 5 0.612305 0.37085 0.0726318 -15 13 6 0.612305 0.37085 0.0727539 -15 13 7 0.612305 0.371094 0.072998 -15 13 8 0.612305 0.371338 0.0735474 -15 13 9 0.612793 0.371826 0.074585 -15 13 10 0.612305 0.37207 0.136475 -15 13 11 0.611328 0.372314 0.206177 -15 13 12 0.609863 0.37207 0.2771 -15 13 13 0.60791 0.37085 0.357666 -15 13 14 0.587891 0.367676 0.443848 -15 13 15 0.558105 0.372803 0.522949 -15 13 16 0.527832 0.373291 0.611328 -15 13 17 0.482422 0.372314 0.697266 -15 13 18 0.418945 0.369629 0.775391 -15 13 19 0.330811 0.366699 0.84375 -15 13 20 0.174683 0.363037 0.899414 -15 13 21 0 0.345459 0.910156 -15 13 22 0 0.330566 0.915039 -15 13 23 0 0.319824 0.920898 -15 13 24 0 0.311768 0.927246 -15 13 25 0 0.304932 0.934082 -15 13 26 0 0.299316 0.940918 -15 13 27 0 0.294678 0.94873 -15 13 28 0 0.29126 0.958496 -15 13 29 0 0.288574 0.96875 -15 13 30 0 0.286865 0.979492 -15 13 31 0 0.285889 0.991211 -15 14 0 0.602051 0.447754 0.153564 -15 14 1 0.602051 0.447754 0.153564 -15 14 2 0.602051 0.447754 0.153564 -15 14 3 0.602051 0.447754 0.153564 -15 14 4 0.602051 0.447998 0.153564 -15 14 5 0.602051 0.447998 0.153564 -15 14 6 0.602051 0.447998 0.153564 -15 14 7 0.602051 0.447998 0.153687 -15 14 8 0.602051 0.448242 0.153687 -15 14 9 0.602051 0.44873 0.153931 -15 14 10 0.601074 0.448975 0.174683 -15 14 11 0.597656 0.448242 0.229126 -15 14 12 0.591797 0.447021 0.290039 -15 14 13 0.582031 0.445068 0.358398 -15 14 14 0.570312 0.442627 0.437988 -15 14 15 0.54248 0.439209 0.520508 -15 14 16 0.511719 0.437988 0.609863 -15 14 17 0.465088 0.434082 0.696289 -15 14 18 0.398926 0.427979 0.775391 -15 14 19 0.303467 0.420898 0.84375 -15 14 20 0.0482788 0.413086 0.900391 -15 14 21 0 0.390869 0.914062 -15 14 22 0 0.37085 0.919434 -15 14 23 0 0.355713 0.924805 -15 14 24 0 0.34375 0.930176 -15 14 25 0 0.33374 0.936035 -15 14 26 0 0.324951 0.942871 -15 14 27 0 0.317627 0.950684 -15 14 28 0 0.311523 0.959961 -15 14 29 0 0.306641 0.970215 -15 14 30 0 0.302979 0.980957 -15 14 31 0 0.300049 0.992188 -15 15 0 0.585938 0.537598 0.168823 -15 15 1 0.585938 0.537598 0.168823 -15 15 2 0.585938 0.537598 0.168823 -15 15 3 0.585938 0.537598 0.168823 -15 15 4 0.585938 0.537598 0.168823 -15 15 5 0.585938 0.537598 0.168823 -15 15 6 0.585938 0.538086 0.168823 -15 15 7 0.585938 0.538086 0.168823 -15 15 8 0.585938 0.538086 0.168823 -15 15 9 0.585938 0.538574 0.168823 -15 15 10 0.585938 0.538574 0.172485 -15 15 11 0.58252 0.538086 0.230103 -15 15 12 0.576172 0.536621 0.293701 -15 15 13 0.564941 0.533203 0.36377 -15 15 14 0.546387 0.526855 0.438965 -15 15 15 0.516113 0.516113 0.516113 -15 15 16 0.484131 0.513184 0.605957 -15 15 17 0.435547 0.506836 0.693848 -15 15 18 0.364258 0.497803 0.774414 -15 15 19 0.250977 0.486816 0.844238 -15 15 20 0 0.474854 0.901367 -15 15 21 0 0.447998 0.918457 -15 15 22 0 0.421875 0.923828 -15 15 23 0 0.401611 0.928711 -15 15 24 0 0.385742 0.934082 -15 15 25 0 0.371826 0.939941 -15 15 26 0 0.359375 0.946289 -15 15 27 0 0.348633 0.954102 -15 15 28 0 0.3396 0.962891 -15 15 29 0 0.331787 0.973145 -15 15 30 0 0.325439 0.983398 -15 15 31 0 0.320068 0.994629 -15 16 0 0.532715 0.615723 0.162598 -15 16 1 0.532715 0.615723 0.162598 -15 16 2 0.532715 0.615723 0.162598 -15 16 3 0.532715 0.615723 0.162598 -15 16 4 0.532715 0.615723 0.162598 -15 16 5 0.532715 0.615723 0.162598 -15 16 6 0.532715 0.615723 0.162598 -15 16 7 0.532715 0.616211 0.162598 -15 16 8 0.532715 0.616211 0.162598 -15 16 9 0.532715 0.616211 0.16272 -15 16 10 0.532715 0.616699 0.16272 -15 16 11 0.530273 0.616211 0.207031 -15 16 12 0.524414 0.614746 0.274902 -15 16 13 0.51416 0.611328 0.346924 -15 16 14 0.496582 0.605469 0.424072 -15 16 15 0.472168 0.600098 0.507812 -15 16 16 0.438232 0.59668 0.599609 -15 16 17 0.384766 0.589355 0.688965 -15 16 18 0.299561 0.577637 0.771484 -15 16 19 0.0805054 0.563477 0.842773 -15 16 20 0 0.547852 0.901367 -15 16 21 0 0.51709 0.924316 -15 16 22 0 0.484619 0.930176 -15 16 23 0 0.459229 0.935547 -15 16 24 0 0.438477 0.94043 -15 16 25 0 0.420166 0.945801 -15 16 26 0 0.403564 0.952148 -15 16 27 0 0.388672 0.959473 -15 16 28 0 0.375977 0.967773 -15 16 29 0 0.364746 0.977051 -15 16 30 0 0.35498 0.987305 -15 16 31 0 0.34668 0.997559 -15 17 0 0.456055 0.689941 0.154663 -15 17 1 0.456055 0.689941 0.154663 -15 17 2 0.456055 0.689941 0.154663 -15 17 3 0.456055 0.689941 0.154663 -15 17 4 0.456055 0.689941 0.154663 -15 17 5 0.456055 0.689941 0.154663 -15 17 6 0.456055 0.689941 0.154663 -15 17 7 0.456055 0.689941 0.154663 -15 17 8 0.456055 0.689941 0.154663 -15 17 9 0.456055 0.689941 0.154663 -15 17 10 0.456299 0.69043 0.154785 -15 17 11 0.455811 0.69043 0.172729 -15 17 12 0.450195 0.69043 0.249756 -15 17 13 0.440674 0.689453 0.326172 -15 17 14 0.425293 0.6875 0.407471 -15 17 15 0.400635 0.686035 0.495117 -15 17 16 0.360107 0.683105 0.588379 -15 17 17 0.290283 0.675293 0.680176 -15 17 18 0.119263 0.662598 0.765137 -15 17 19 0 0.646484 0.838867 -15 17 20 0 0.62793 0.899902 -15 17 21 0 0.594727 0.929688 -15 17 22 0 0.557617 0.939453 -15 17 23 0 0.526855 0.945801 -15 17 24 0 0.500977 0.950684 -15 17 25 0 0.477783 0.956055 -15 17 26 0 0.456543 0.961426 -15 17 27 0 0.437256 0.967773 -15 17 28 0 0.42041 0.975098 -15 17 29 0 0.405029 0.983887 -15 17 30 0 0.391602 0.992676 -15 17 31 0 0.379639 1 -15 18 0 0.346191 0.764648 0.147095 -15 18 1 0.346191 0.764648 0.147095 -15 18 2 0.346191 0.764648 0.147095 -15 18 3 0.346191 0.764648 0.147095 -15 18 4 0.346191 0.764648 0.147095 -15 18 5 0.346191 0.764648 0.147095 -15 18 6 0.346191 0.764648 0.147095 -15 18 7 0.346191 0.764648 0.147095 -15 18 8 0.346191 0.764648 0.147095 -15 18 9 0.346436 0.764648 0.147095 -15 18 10 0.34668 0.764648 0.147217 -15 18 11 0.347168 0.765137 0.147339 -15 18 12 0.341553 0.765625 0.219238 -15 18 13 0.32959 0.766602 0.30249 -15 18 14 0.30835 0.76709 0.387451 -15 18 15 0.270264 0.767578 0.477051 -15 18 16 0.189941 0.765625 0.571777 -15 18 17 0 0.759277 0.666016 -15 18 18 0 0.747559 0.753906 -15 18 19 0 0.730469 0.831055 -15 18 20 0 0.709961 0.894531 -15 18 21 0 0.677246 0.933594 -15 18 22 0 0.637695 0.949707 -15 18 23 0 0.602539 0.958984 -15 18 24 0 0.572266 0.964844 -15 18 25 0 0.543945 0.969727 -15 18 26 0 0.517578 0.974609 -15 18 27 0 0.493164 0.97998 -15 18 28 0 0.471436 0.986328 -15 18 29 0 0.45166 0.993164 -15 18 30 0 0.434082 1 -15 18 31 0 0.418213 1 -15 19 0 0 0.833984 0.13916 -15 19 1 0 0.833984 0.13916 -15 19 2 0 0.833984 0.13916 -15 19 3 0 0.833984 0.13916 -15 19 4 0 0.833984 0.13916 -15 19 5 0 0.833984 0.13916 -15 19 6 0 0.833984 0.13916 -15 19 7 0 0.833984 0.13916 -15 19 8 0 0.833984 0.13916 -15 19 9 0 0.833984 0.139282 -15 19 10 0 0.833984 0.139282 -15 19 11 0 0.834473 0.139404 -15 19 12 0 0.834961 0.178589 -15 19 13 0 0.836426 0.274414 -15 19 14 0 0.838379 0.36377 -15 19 15 0 0.840332 0.455322 -15 19 16 0 0.840332 0.55127 -15 19 17 0 0.835938 0.647461 -15 19 18 0 0.826172 0.737793 -15 19 19 0 0.810547 0.818359 -15 19 20 0 0.789551 0.885254 -15 19 21 0 0.759277 0.933105 -15 19 22 0 0.720703 0.959473 -15 19 23 0 0.683105 0.973633 -15 19 24 0 0.648926 0.981445 -15 19 25 0 0.615723 0.987305 -15 19 26 0 0.583984 0.991699 -15 19 27 0 0.554688 0.996094 -15 19 28 0 0.527832 1 -15 19 29 0 0.50293 1 -15 19 30 0 0.480957 1 -15 19 31 0 0.460693 1 -15 20 0 0 0.894531 0.130859 -15 20 1 0 0.894531 0.130859 -15 20 2 0 0.894531 0.130859 -15 20 3 0 0.894531 0.130859 -15 20 4 0 0.894531 0.130859 -15 20 5 0 0.894531 0.130859 -15 20 6 0 0.894531 0.130859 -15 20 7 0 0.894531 0.130859 -15 20 8 0 0.894531 0.130859 -15 20 9 0 0.894531 0.130859 -15 20 10 0 0.89502 0.130981 -15 20 11 0 0.89502 0.131104 -15 20 12 0 0.895508 0.131226 -15 20 13 0 0.897461 0.241577 -15 20 14 0 0.899902 0.337158 -15 20 15 0 0.902832 0.430908 -15 20 16 0 0.904297 0.527832 -15 20 17 0 0.902344 0.625 -15 20 18 0 0.89502 0.717773 -15 20 19 0 0.881348 0.800781 -15 20 20 0 0.862305 0.871094 -15 20 21 0 0.835938 0.927246 -15 20 22 0 0.80127 0.964355 -15 20 23 0 0.763672 0.98584 -15 20 24 0 0.727051 0.998047 -15 20 25 0 0.689941 1 -15 20 26 0 0.653809 1 -15 20 27 0 0.619629 1 -15 20 28 0 0.587402 1 -15 20 29 0 0.557617 1 -15 20 30 0 0.530273 1 -15 20 31 0 0.505859 1 -15 21 0 0 0.946289 0.121765 -15 21 1 0 0.946289 0.121765 -15 21 2 0 0.946289 0.121765 -15 21 3 0 0.946289 0.121765 -15 21 4 0 0.946289 0.121765 -15 21 5 0 0.946289 0.121765 -15 21 6 0 0.946289 0.121765 -15 21 7 0 0.946289 0.121826 -15 21 8 0 0.946777 0.121826 -15 21 9 0 0.946777 0.121826 -15 21 10 0 0.946777 0.121887 -15 21 11 0 0.946777 0.122009 -15 21 12 0 0.947266 0.122192 -15 21 13 0 0.948242 0.200928 -15 21 14 0 0.95166 0.307373 -15 21 15 0 0.955078 0.403809 -15 21 16 0 0.958496 0.501465 -15 21 17 0 0.958984 0.599121 -15 21 18 0 0.95459 0.692871 -15 21 19 0 0.943848 0.778809 -15 21 20 0 0.926758 0.852051 -15 21 21 0 0.904297 0.914062 -15 21 22 0 0.875 0.961426 -15 21 23 0 0.840332 0.991211 -15 21 24 0 0.804199 1 -15 21 25 0 0.765137 1 -15 21 26 0 0.725586 1 -15 21 27 0 0.686523 1 -15 21 28 0 0.649414 1 -15 21 29 0 0.614746 1 -15 21 30 0 0.583008 1 -15 21 31 0 0.553711 1 -15 22 0 0 0.989258 0.112244 -15 22 1 0 0.989258 0.112244 -15 22 2 0 0.989258 0.112244 -15 22 3 0 0.989258 0.112244 -15 22 4 0 0.989258 0.112244 -15 22 5 0 0.989258 0.112244 -15 22 6 0 0.989258 0.112244 -15 22 7 0 0.989258 0.112244 -15 22 8 0 0.989258 0.112305 -15 22 9 0 0.989258 0.112305 -15 22 10 0 0.989258 0.112366 -15 22 11 0 0.989746 0.112488 -15 22 12 0 0.989746 0.112732 -15 22 13 0 0.990234 0.14563 -15 22 14 0 0.993652 0.274658 -15 22 15 0 0.998047 0.375244 -15 22 16 0 1 0.473633 -15 22 17 0 1 0.571289 -15 22 18 0 1 0.666016 -15 22 19 0 0.996094 0.75293 -15 22 20 0 0.982422 0.829102 -15 22 21 0 0.962402 0.89502 -15 22 22 0 0.937988 0.948242 -15 22 23 0 0.908203 0.987305 -15 22 24 0 0.874512 1 -15 22 25 0 0.836426 1 -15 22 26 0 0.79541 1 -15 22 27 0 0.753418 1 -15 22 28 0 0.712402 1 -15 22 29 0 0.67334 1 -15 22 30 0 0.636719 1 -15 22 31 0 0.603027 1 -15 23 0 0 1 0.1026 -15 23 1 0 1 0.1026 -15 23 2 0 1 0.1026 -15 23 3 0 1 0.1026 -15 23 4 0 1 0.1026 -15 23 5 0 1 0.1026 -15 23 6 0 1 0.1026 -15 23 7 0 1 0.1026 -15 23 8 0 1 0.102661 -15 23 9 0 1 0.102661 -15 23 10 0 1 0.102722 -15 23 11 0 1 0.102844 -15 23 12 0 1 0.103088 -15 23 13 0 1 0.103394 -15 23 14 0 1 0.239502 -15 23 15 0 1 0.346436 -15 23 16 0 1 0.446045 -15 23 17 0 1 0.543457 -15 23 18 0 1 0.638184 -15 23 19 0 1 0.726074 -15 23 20 0 1 0.804199 -15 23 21 0 1 0.872559 -15 23 22 0 0.98877 0.929688 -15 23 23 0 0.963379 0.974609 -15 23 24 0 0.93457 1 -15 23 25 0 0.898926 1 -15 23 26 0 0.858887 1 -15 23 27 0 0.815918 1 -15 23 28 0 0.772461 1 -15 23 29 0 0.72998 1 -15 23 30 0 0.689453 1 -15 23 31 0 0.651367 1 -15 24 0 0 1 0.0927124 -15 24 1 0 1 0.0927124 -15 24 2 0 1 0.0927124 -15 24 3 0 1 0.0927124 -15 24 4 0 1 0.0927124 -15 24 5 0 1 0.0927124 -15 24 6 0 1 0.0927124 -15 24 7 0 1 0.0927124 -15 24 8 0 1 0.0927734 -15 24 9 0 1 0.0927734 -15 24 10 0 1 0.0928955 -15 24 11 0 1 0.0930176 -15 24 12 0 1 0.0932007 -15 24 13 0 1 0.0935669 -15 24 14 0 1 0.200195 -15 24 15 0 1 0.317627 -15 24 16 0 1 0.418945 -15 24 17 0 1 0.516113 -15 24 18 0 1 0.609863 -15 24 19 0 1 0.698242 -15 24 20 0 1 0.777344 -15 24 21 0 1 0.847656 -15 24 22 0 1 0.907715 -15 24 23 0 1 0.956055 -15 24 24 0 0.983398 0.995117 -15 24 25 0 0.952148 1 -15 24 26 0 0.914551 1 -15 24 27 0 0.872559 1 -15 24 28 0 0.828125 1 -15 24 29 0 0.783203 1 -15 24 30 0 0.739746 1 -15 24 31 0 0.698242 1 -15 25 0 0 1 0.0812378 -15 25 1 0 1 0.0812378 -15 25 2 0 1 0.0812378 -15 25 3 0 1 0.0812378 -15 25 4 0 1 0.0812378 -15 25 5 0 1 0.0812988 -15 25 6 0 1 0.0812988 -15 25 7 0 1 0.0812988 -15 25 8 0 1 0.0812988 -15 25 9 0 1 0.0813599 -15 25 10 0 1 0.0814209 -15 25 11 0 1 0.081604 -15 25 12 0 1 0.0818481 -15 25 13 0 1 0.0822754 -15 25 14 0 1 0.145142 -15 25 15 0 1 0.285156 -15 25 16 0 1 0.389404 -15 25 17 0 1 0.486328 -15 25 18 0 1 0.57959 -15 25 19 0 1 0.66748 -15 25 20 0 1 0.74707 -15 25 21 0 1 0.818848 -15 25 22 0 1 0.881348 -15 25 23 0 1 0.933105 -15 25 24 0 1 0.975586 -15 25 25 0 1 1 -15 25 26 0 0.967285 1 -15 25 27 0 0.927734 1 -15 25 28 0 0.883789 1 -15 25 29 0 0.837891 1 -15 25 30 0 0.791992 1 -15 25 31 0 0.747559 1 -15 26 0 0 1 0.0673218 -15 26 1 0 1 0.0673218 -15 26 2 0 1 0.0673218 -15 26 3 0 1 0.0673218 -15 26 4 0 1 0.0673218 -15 26 5 0 1 0.0673218 -15 26 6 0 1 0.0673218 -15 26 7 0 1 0.0673218 -15 26 8 0 1 0.0673828 -15 26 9 0 1 0.0674438 -15 26 10 0 1 0.0675049 -15 26 11 0 1 0.067688 -15 26 12 0 1 0.0679932 -15 26 13 0 1 0.0684814 -15 26 14 0 1 0.0692749 -15 26 15 0 1 0.247559 -15 26 16 0 1 0.357422 -15 26 17 0 1 0.454834 -15 26 18 0 1 0.546875 -15 26 19 0 1 0.633789 -15 26 20 0 1 0.713379 -15 26 21 0 1 0.786621 -15 26 22 0 1 0.851074 -15 26 23 0 1 0.905273 -15 26 24 0 1 0.950684 -15 26 25 0 1 0.991699 -15 26 26 0 1 1 -15 26 27 0 0.979492 1 -15 26 28 0 0.937988 1 -15 26 29 0 0.892578 1 -15 26 30 0 0.845703 1 -15 26 31 0 0.798828 1 -15 27 0 0 1 0.047699 -15 27 1 0 1 0.047699 -15 27 2 0 1 0.047699 -15 27 3 0 1 0.047699 -15 27 4 0 1 0.047699 -15 27 5 0 1 0.047699 -15 27 6 0 1 0.047699 -15 27 7 0 1 0.0477295 -15 27 8 0 1 0.0477905 -15 27 9 0 1 0.0478821 -15 27 10 0 1 0.0480347 -15 27 11 0 1 0.0483093 -15 27 12 0 1 0.0487671 -15 27 13 0 1 0.04953 -15 27 14 0 1 0.0506897 -15 27 15 0 1 0.201904 -15 27 16 0 1 0.322754 -15 27 17 0 1 0.421387 -15 27 18 0 1 0.512695 -15 27 19 0 1 0.598145 -15 27 20 0 1 0.677246 -15 27 21 0 1 0.750488 -15 27 22 0 1 0.816406 -15 27 23 0 1 0.872559 -15 27 24 0 1 0.920898 -15 27 25 0 1 0.965332 -15 27 26 0 1 1 -15 27 27 0 1 1 -15 27 28 0 0.98877 1 -15 27 29 0 0.944824 1 -15 27 30 0 0.898438 1 -15 27 31 0 0.850586 1 -15 28 0 0 1 0 -15 28 1 0 1 0 -15 28 2 0 1 0 -15 28 3 0 1 0 -15 28 4 0 1 0 -15 28 5 0 1 0 -15 28 6 0 1 0 -15 28 7 0 1 0 -15 28 8 0 1 0 -15 28 9 0 1 0 -15 28 10 0 1 0 -15 28 11 0 1 0 -15 28 12 0 1 0 -15 28 13 0 1 0 -15 28 14 0 1 0 -15 28 15 0 1 0.136475 -15 28 16 0 1 0.284424 -15 28 17 0 1 0.385986 -15 28 18 0 1 0.476807 -15 28 19 0 1 0.561035 -15 28 20 0 1 0.63916 -15 28 21 0 1 0.711914 -15 28 22 0 1 0.777832 -15 28 23 0 1 0.835449 -15 28 24 0 1 0.885742 -15 28 25 0 1 0.933105 -15 28 26 0 1 0.976562 -15 28 27 0 1 1 -15 28 28 0 1 1 -15 28 29 0 0.994629 1 -15 28 30 0 0.949707 1 -15 28 31 0 0.902344 1 -15 29 0 0 1 0 -15 29 1 0 1 0 -15 29 2 0 1 0 -15 29 3 0 1 0 -15 29 4 0 1 0 -15 29 5 0 1 0 -15 29 6 0 1 0 -15 29 7 0 1 0 -15 29 8 0 1 0 -15 29 9 0 1 0 -15 29 10 0 1 0 -15 29 11 0 1 0 -15 29 12 0 1 0 -15 29 13 0 1 0 -15 29 14 0 1 0 -15 29 15 0 1 0 -15 29 16 0 1 0.240723 -15 29 17 0 1 0.348389 -15 29 18 0 1 0.439209 -15 29 19 0 1 0.522461 -15 29 20 0 1 0.598633 -15 29 21 0 1 0.67041 -15 29 22 0 1 0.736328 -15 29 23 0 1 0.794434 -15 29 24 0 1 0.845703 -15 29 25 0 1 0.895508 -15 29 26 0 1 0.942383 -15 29 27 0 1 0.984863 -15 29 28 0 1 1 -15 29 29 0 1 1 -15 29 30 0 0.999023 1 -15 29 31 0 0.953613 1 -15 30 0 0 1 0 -15 30 1 0 1 0 -15 30 2 0 1 0 -15 30 3 0 1 0 -15 30 4 0 1 0 -15 30 5 0 1 0 -15 30 6 0 1 0 -15 30 7 0 1 0 -15 30 8 0 1 0 -15 30 9 0 1 0 -15 30 10 0 1 0 -15 30 11 0 1 0 -15 30 12 0 1 0 -15 30 13 0 1 0 -15 30 14 0 1 0 -15 30 15 0 1 0 -15 30 16 0 1 0.186768 -15 30 17 0 1 0.307861 -15 30 18 0 1 0.400146 -15 30 19 0 1 0.481934 -15 30 20 0 1 0.556641 -15 30 21 0 1 0.626465 -15 30 22 0 1 0.691895 -15 30 23 0 1 0.75 -15 30 24 0 1 0.801758 -15 30 25 0 1 0.852539 -15 30 26 0 1 0.901855 -15 30 27 0 1 0.948242 -15 30 28 0 1 0.990234 -15 30 29 0 1 1 -15 30 30 0 1 1 -15 30 31 0 1 1 -15 31 0 0 1 0 -15 31 1 0 1 0 -15 31 2 0 1 0 -15 31 3 0 1 0 -15 31 4 0 1 0 -15 31 5 0 1 0 -15 31 6 0 1 0 -15 31 7 0 1 0 -15 31 8 0 1 0 -15 31 9 0 1 0 -15 31 10 0 1 0 -15 31 11 0 1 0 -15 31 12 0 1 0 -15 31 13 0 1 0 -15 31 14 0 1 0 -15 31 15 0 1 0 -15 31 16 0 1 0.0978394 -15 31 17 0 1 0.263672 -15 31 18 0 1 0.359375 -15 31 19 0 1 0.44043 -15 31 20 0 1 0.513184 -15 31 21 0 1 0.581543 -15 31 22 0 1 0.64502 -15 31 23 0 1 0.702637 -15 31 24 0 1 0.754395 -15 31 25 0 1 0.806152 -15 31 26 0 1 0.856934 -15 31 27 0 1 0.90625 -15 31 28 0 1 0.952637 -15 31 29 0 1 0.994629 -15 31 30 0 1 1 -15 31 31 0 1 1 -16 0 0 0.711914 0 0.0427856 -16 0 1 0.711914 0 0.0427551 -16 0 2 0.711914 0 0.0427551 -16 0 3 0.711914 0 0.0427551 -16 0 4 0.711914 0 0.0427246 -16 0 5 0.711914 0 0.0426636 -16 0 6 0.711914 0 0.0425415 -16 0 7 0.711914 0 0.0423584 -16 0 8 0.711914 0 0.0419312 -16 0 9 0.712402 0 0.0411377 -16 0 10 0.714844 0 0.0403442 -16 0 11 0.72168 0 0.118835 -16 0 12 0.727539 0 0.241211 -16 0 13 0.727539 0 0.338135 -16 0 14 0.718262 0 0.43457 -16 0 15 0.697266 0.200317 0.522461 -16 0 16 0.672852 0.226929 0.609863 -16 0 17 0.637695 0.238037 0.696289 -16 0 18 0.589844 0.249023 0.775391 -16 0 19 0.53125 0.259277 0.844238 -16 0 20 0.46167 0.267822 0.900879 -16 0 21 0.363281 0.265625 0.915527 -16 0 22 0.239258 0.262207 0.92041 -16 0 23 0 0.26001 0.925293 -16 0 24 0 0.258789 0.930176 -16 0 25 0 0.258301 0.936035 -16 0 26 0 0.258301 0.943359 -16 0 27 0 0.259033 0.952148 -16 0 28 0 0.260254 0.962402 -16 0 29 0 0.262207 0.973633 -16 0 30 0 0.26416 0.98584 -16 0 31 0 0.266113 0.996094 -16 1 0 0.711914 0 0.0427246 -16 1 1 0.711914 0 0.0427246 -16 1 2 0.711914 0 0.0426941 -16 1 3 0.711914 0 0.0426941 -16 1 4 0.711914 0 0.0426636 -16 1 5 0.711914 0 0.0426025 -16 1 6 0.711914 0 0.042511 -16 1 7 0.711914 0 0.0422974 -16 1 8 0.711914 0 0.0418701 -16 1 9 0.712402 0 0.0410767 -16 1 10 0.714844 0 0.0402832 -16 1 11 0.72168 0 0.118835 -16 1 12 0.727539 0 0.241211 -16 1 13 0.727539 0 0.338135 -16 1 14 0.718262 0 0.43457 -16 1 15 0.697266 0.200317 0.522461 -16 1 16 0.672852 0.226929 0.609863 -16 1 17 0.637695 0.238159 0.696289 -16 1 18 0.589844 0.249146 0.775391 -16 1 19 0.53125 0.259277 0.844238 -16 1 20 0.46167 0.267822 0.900879 -16 1 21 0.363281 0.265625 0.915527 -16 1 22 0.239258 0.262207 0.92041 -16 1 23 0 0.260254 0.925293 -16 1 24 0 0.258789 0.930176 -16 1 25 0 0.258301 0.936035 -16 1 26 0 0.258301 0.943359 -16 1 27 0 0.259033 0.952148 -16 1 28 0 0.260254 0.962402 -16 1 29 0 0.262207 0.973633 -16 1 30 0 0.26416 0.98584 -16 1 31 0 0.266113 0.996094 -16 2 0 0.711914 0 0.0426025 -16 2 1 0.711914 0 0.0426025 -16 2 2 0.711914 0 0.0426025 -16 2 3 0.711914 0 0.042572 -16 2 4 0.711914 0 0.042572 -16 2 5 0.711914 0 0.042511 -16 2 6 0.711914 0 0.0423889 -16 2 7 0.711914 0 0.0421753 -16 2 8 0.711914 0 0.0417786 -16 2 9 0.712402 0 0.0409546 -16 2 10 0.714844 0 0.0401611 -16 2 11 0.72168 0 0.118835 -16 2 12 0.727539 0 0.241211 -16 2 13 0.727539 0 0.338135 -16 2 14 0.718262 0 0.43457 -16 2 15 0.697266 0.200439 0.522461 -16 2 16 0.672852 0.227051 0.609863 -16 2 17 0.637695 0.238281 0.696289 -16 2 18 0.589844 0.249146 0.775391 -16 2 19 0.53125 0.259277 0.844238 -16 2 20 0.46167 0.267822 0.900879 -16 2 21 0.363281 0.265625 0.915527 -16 2 22 0.239258 0.262451 0.92041 -16 2 23 0 0.260254 0.925293 -16 2 24 0 0.259033 0.930176 -16 2 25 0 0.258301 0.936035 -16 2 26 0 0.258301 0.943359 -16 2 27 0 0.259033 0.952148 -16 2 28 0 0.260254 0.962402 -16 2 29 0 0.262207 0.973633 -16 2 30 0 0.26416 0.98584 -16 2 31 0 0.266113 0.996094 -16 3 0 0.711914 0 0.0424194 -16 3 1 0.711914 0 0.0424194 -16 3 2 0.711914 0 0.0424194 -16 3 3 0.711914 0 0.0423889 -16 3 4 0.711914 0 0.0423584 -16 3 5 0.711914 0 0.0423279 -16 3 6 0.711914 0 0.0422058 -16 3 7 0.711914 0 0.0419922 -16 3 8 0.711914 0 0.0415955 -16 3 9 0.712402 0 0.0407715 -16 3 10 0.714844 0 0.039978 -16 3 11 0.72168 0 0.118774 -16 3 12 0.727539 0 0.241211 -16 3 13 0.727539 0 0.338135 -16 3 14 0.718262 0 0.43457 -16 3 15 0.697266 0.200806 0.522461 -16 3 16 0.672852 0.227295 0.609863 -16 3 17 0.637695 0.238403 0.696289 -16 3 18 0.589844 0.24939 0.775391 -16 3 19 0.53125 0.259521 0.844238 -16 3 20 0.46167 0.268066 0.900879 -16 3 21 0.363281 0.265625 0.915527 -16 3 22 0.239258 0.262451 0.92041 -16 3 23 0 0.260254 0.925293 -16 3 24 0 0.259033 0.930176 -16 3 25 0 0.258301 0.936035 -16 3 26 0 0.258301 0.943359 -16 3 27 0 0.259033 0.952148 -16 3 28 0 0.260254 0.962402 -16 3 29 0 0.262207 0.973633 -16 3 30 0 0.26416 0.98584 -16 3 31 0 0.266113 0.996094 -16 4 0 0.711914 0 0.0420837 -16 4 1 0.711914 0 0.0420532 -16 4 2 0.711914 0 0.0420532 -16 4 3 0.711914 0 0.0420532 -16 4 4 0.711914 0 0.0420227 -16 4 5 0.711914 0 0.0419617 -16 4 6 0.711914 0 0.0418396 -16 4 7 0.711914 0 0.041626 -16 4 8 0.711914 0 0.0411987 -16 4 9 0.712402 0 0.0403748 -16 4 10 0.714844 0 0.0395813 -16 4 11 0.722168 0 0.118713 -16 4 12 0.727539 0 0.241089 -16 4 13 0.727539 0 0.338135 -16 4 14 0.718262 0 0.43457 -16 4 15 0.697266 0.201294 0.522461 -16 4 16 0.672852 0.227661 0.609863 -16 4 17 0.637695 0.23877 0.696289 -16 4 18 0.589844 0.249634 0.775391 -16 4 19 0.53125 0.259766 0.844238 -16 4 20 0.46167 0.268311 0.900879 -16 4 21 0.363037 0.265869 0.915527 -16 4 22 0.239136 0.262695 0.92041 -16 4 23 0 0.260498 0.925293 -16 4 24 0 0.259033 0.930176 -16 4 25 0 0.258545 0.936035 -16 4 26 0 0.258545 0.943359 -16 4 27 0 0.259033 0.952148 -16 4 28 0 0.260498 0.962402 -16 4 29 0 0.262207 0.973633 -16 4 30 0 0.264404 0.98584 -16 4 31 0 0.266113 0.996094 -16 5 0 0.711914 0 0.0413818 -16 5 1 0.711914 0 0.0413513 -16 5 2 0.711914 0 0.0413513 -16 5 3 0.711914 0 0.0413513 -16 5 4 0.711914 0 0.0413208 -16 5 5 0.711914 0 0.0412598 -16 5 6 0.711914 0 0.0411377 -16 5 7 0.711914 0 0.0409241 -16 5 8 0.712402 0 0.0404968 -16 5 9 0.712402 0 0.0396423 -16 5 10 0.714844 0 0.0387878 -16 5 11 0.722168 0 0.118652 -16 5 12 0.727539 0 0.241089 -16 5 13 0.727539 0 0.338135 -16 5 14 0.718262 0.020462 0.43457 -16 5 15 0.697266 0.202271 0.522461 -16 5 16 0.672852 0.228516 0.609863 -16 5 17 0.637695 0.239502 0.696289 -16 5 18 0.589844 0.250244 0.775391 -16 5 19 0.53125 0.260254 0.844238 -16 5 20 0.46167 0.268555 0.900879 -16 5 21 0.363037 0.266357 0.915527 -16 5 22 0.239014 0.262939 0.92041 -16 5 23 0 0.260742 0.925293 -16 5 24 0 0.259277 0.930176 -16 5 25 0 0.258789 0.936035 -16 5 26 0 0.258545 0.943359 -16 5 27 0 0.259277 0.952148 -16 5 28 0 0.260498 0.962402 -16 5 29 0 0.262451 0.973633 -16 5 30 0 0.264404 0.98584 -16 5 31 0 0.266357 0.996094 -16 6 0 0.712402 0 0.039978 -16 6 1 0.712402 0 0.0399475 -16 6 2 0.712402 0 0.0399475 -16 6 3 0.712402 0 0.0399475 -16 6 4 0.712402 0 0.039917 -16 6 5 0.712402 0 0.039856 -16 6 6 0.712402 0 0.0397339 -16 6 7 0.712402 0 0.0394897 -16 6 8 0.712402 0 0.039032 -16 6 9 0.712402 0 0.0381165 -16 6 10 0.714844 0 0.0372314 -16 6 11 0.722168 0 0.118469 -16 6 12 0.727539 0 0.240967 -16 6 13 0.727539 0 0.338135 -16 6 14 0.718262 0.0512695 0.434326 -16 6 15 0.696777 0.204102 0.522461 -16 6 16 0.672852 0.230103 0.609863 -16 6 17 0.637207 0.240845 0.696289 -16 6 18 0.589844 0.251465 0.775391 -16 6 19 0.53125 0.26123 0.844238 -16 6 20 0.461426 0.269531 0.900879 -16 6 21 0.363037 0.26709 0.915527 -16 6 22 0.23877 0.263428 0.92041 -16 6 23 0 0.26123 0.925293 -16 6 24 0 0.259766 0.930176 -16 6 25 0 0.259033 0.936523 -16 6 26 0 0.259033 0.943359 -16 6 27 0 0.259521 0.952148 -16 6 28 0 0.260742 0.962402 -16 6 29 0 0.262451 0.974121 -16 6 30 0 0.264648 0.98584 -16 6 31 0 0.266357 0.996094 -16 7 0 0.712402 0 0.0369873 -16 7 1 0.712402 0 0.0369873 -16 7 2 0.712402 0 0.0369568 -16 7 3 0.712402 0 0.0369568 -16 7 4 0.712402 0 0.0369263 -16 7 5 0.712402 0 0.0368347 -16 7 6 0.712402 0 0.0367126 -16 7 7 0.712402 0 0.036438 -16 7 8 0.712402 0 0.0359192 -16 7 9 0.712402 0 0.0348816 -16 7 10 0.714844 0 0.0338135 -16 7 11 0.722168 0 0.118164 -16 7 12 0.727539 0 0.240723 -16 7 13 0.727539 0 0.337891 -16 7 14 0.718262 0.0758667 0.434326 -16 7 15 0.696777 0.207642 0.522461 -16 7 16 0.672363 0.233032 0.609863 -16 7 17 0.637207 0.243408 0.696289 -16 7 18 0.589355 0.253662 0.775391 -16 7 19 0.530762 0.263184 0.844238 -16 7 20 0.461182 0.27124 0.900879 -16 7 21 0.362549 0.268311 0.915527 -16 7 22 0.238281 0.264648 0.920898 -16 7 23 0 0.262207 0.925293 -16 7 24 0 0.260742 0.930176 -16 7 25 0 0.259766 0.936523 -16 7 26 0 0.259766 0.943848 -16 7 27 0 0.26001 0.952148 -16 7 28 0 0.26123 0.962402 -16 7 29 0 0.262939 0.974121 -16 7 30 0 0.264893 0.98584 -16 7 31 0 0.266602 0.996094 -16 8 0 0.712891 0 0.0296173 -16 8 1 0.712891 0 0.0296021 -16 8 2 0.712891 0 0.0295868 -16 8 3 0.712891 0 0.0295563 -16 8 4 0.712891 0 0.0295105 -16 8 5 0.712891 0 0.0294037 -16 8 6 0.712891 0 0.0292206 -16 8 7 0.712891 0 0.0288239 -16 8 8 0.712891 0 0.0280609 -16 8 9 0.712891 0 0.0264587 -16 8 10 0.715332 0 0.0246582 -16 8 11 0.722168 0 0.117615 -16 8 12 0.727051 0 0.240234 -16 8 13 0.727051 0 0.337646 -16 8 14 0.717773 0.103699 0.434082 -16 8 15 0.696289 0.214355 0.522461 -16 8 16 0.672363 0.238525 0.609863 -16 8 17 0.636719 0.248413 0.696289 -16 8 18 0.589355 0.258057 0.775391 -16 8 19 0.530273 0.266846 0.844238 -16 8 20 0.460693 0.274414 0.901367 -16 8 21 0.362061 0.270996 0.915527 -16 8 22 0.237427 0.266846 0.920898 -16 8 23 0 0.26416 0.925293 -16 8 24 0 0.262207 0.930664 -16 8 25 0 0.26123 0.936523 -16 8 26 0 0.260986 0.943848 -16 8 27 0 0.26123 0.952148 -16 8 28 0 0.262207 0.962891 -16 8 29 0 0.263916 0.974121 -16 8 30 0 0.265625 0.98584 -16 8 31 0 0.267334 0.996094 -16 9 0 0.713379 0.0744019 0 -16 9 1 0.713379 0.0744629 0 -16 9 2 0.713379 0.0745239 0 -16 9 3 0.713379 0.074646 0 -16 9 4 0.713379 0.0748901 0 -16 9 5 0.713379 0.0753784 0 -16 9 6 0.713379 0.0762939 0 -16 9 7 0.713379 0.078064 0 -16 9 8 0.713379 0.0812988 0 -16 9 9 0.713379 0.0869141 0 -16 9 10 0.71582 0.0925293 0 -16 9 11 0.722656 0.0912476 0.116699 -16 9 12 0.726562 0.072876 0.23938 -16 9 13 0.726562 0.0591431 0.337158 -16 9 14 0.717285 0.137207 0.433838 -16 9 15 0.695801 0.226318 0.521973 -16 9 16 0.671387 0.248779 0.609863 -16 9 17 0.63623 0.257568 0.696289 -16 9 18 0.588379 0.265869 0.775391 -16 9 19 0.529785 0.273926 0.844238 -16 9 20 0.459961 0.280273 0.901367 -16 9 21 0.361084 0.276123 0.916016 -16 9 22 0.235596 0.27124 0.920898 -16 9 23 0 0.267822 0.925781 -16 9 24 0 0.265381 0.930664 -16 9 25 0 0.26416 0.936523 -16 9 26 0 0.263428 0.943848 -16 9 27 0 0.263428 0.952637 -16 9 28 0 0.26416 0.962891 -16 9 29 0 0.265381 0.974121 -16 9 30 0 0.26709 0.98584 -16 9 31 0 0.268555 0.996582 -16 10 0 0.713867 0.152222 0 -16 10 1 0.713867 0.152222 0 -16 10 2 0.713867 0.152344 0 -16 10 3 0.713867 0.152344 0 -16 10 4 0.713867 0.152466 0 -16 10 5 0.713867 0.152588 0 -16 10 6 0.713867 0.152832 0 -16 10 7 0.714355 0.153442 0 -16 10 8 0.714355 0.154541 0 -16 10 9 0.714355 0.156738 0 -16 10 10 0.716309 0.159302 0 -16 10 11 0.723145 0.159058 0.115845 -16 10 12 0.726074 0.151978 0.238159 -16 10 13 0.725586 0.147949 0.336182 -16 10 14 0.716797 0.177368 0.433105 -16 10 15 0.694824 0.245728 0.521973 -16 10 16 0.67041 0.265625 0.609375 -16 10 17 0.634766 0.272705 0.695801 -16 10 18 0.586914 0.279541 0.775391 -16 10 19 0.52832 0.285645 0.844727 -16 10 20 0.458252 0.290771 0.901367 -16 10 21 0.359131 0.284912 0.916504 -16 10 22 0.232178 0.278564 0.921387 -16 10 23 0 0.27417 0.92627 -16 10 24 0 0.27124 0.931152 -16 10 25 0 0.269043 0.937012 -16 10 26 0 0.267578 0.944336 -16 10 27 0 0.26709 0.953125 -16 10 28 0 0.267334 0.963379 -16 10 29 0 0.268311 0.974609 -16 10 30 0 0.269287 0.98584 -16 10 31 0 0.270508 0.996582 -16 11 0 0.714844 0.216797 0 -16 11 1 0.714844 0.216797 0 -16 11 2 0.714844 0.216797 0 -16 11 3 0.714844 0.216797 0 -16 11 4 0.714844 0.216919 0 -16 11 5 0.714844 0.216919 0 -16 11 6 0.714844 0.217163 0 -16 11 7 0.714844 0.217407 0 -16 11 8 0.714844 0.21814 0 -16 11 9 0.715332 0.21936 0 -16 11 10 0.716797 0.221191 0 -16 11 11 0.722656 0.221313 0.11676 -16 11 12 0.724121 0.216675 0.236694 -16 11 13 0.723633 0.214478 0.334961 -16 11 14 0.715332 0.225708 0.432129 -16 11 15 0.692871 0.274902 0.521484 -16 11 16 0.667969 0.291748 0.609375 -16 11 17 0.632324 0.296631 0.695801 -16 11 18 0.584473 0.301025 0.775391 -16 11 19 0.525879 0.304932 0.844727 -16 11 20 0.455322 0.307617 0.901855 -16 11 21 0.355713 0.299561 0.916992 -16 11 22 0.226074 0.291016 0.922363 -16 11 23 0 0.284912 0.926758 -16 11 24 0 0.280518 0.932129 -16 11 25 0 0.277344 0.937988 -16 11 26 0 0.274902 0.945312 -16 11 27 0 0.273438 0.954102 -16 11 28 0 0.272949 0.964355 -16 11 29 0 0.273193 0.975586 -16 11 30 0 0.273438 0.986328 -16 11 31 0 0.27417 0.996582 -16 12 0 0.715332 0.285156 0 -16 12 1 0.715332 0.285156 0 -16 12 2 0.715332 0.285156 0 -16 12 3 0.715332 0.285156 0 -16 12 4 0.715332 0.285156 0 -16 12 5 0.715332 0.285156 0 -16 12 6 0.715332 0.2854 0 -16 12 7 0.715332 0.285645 0 -16 12 8 0.715332 0.285889 0 -16 12 9 0.715332 0.286865 0 -16 12 10 0.716309 0.288086 0 -16 12 11 0.719238 0.288086 0.125122 -16 12 12 0.720215 0.285156 0.23645 -16 12 13 0.719727 0.281738 0.332275 -16 12 14 0.711914 0.28418 0.429688 -16 12 15 0.688965 0.31543 0.520996 -16 12 16 0.664062 0.329102 0.608887 -16 12 17 0.628418 0.331543 0.695801 -16 12 18 0.580566 0.333008 0.775391 -16 12 19 0.520996 0.33374 0.844727 -16 12 20 0.450195 0.33374 0.901855 -16 12 21 0.349609 0.322266 0.918457 -16 12 22 0.214844 0.310547 0.92334 -16 12 23 0 0.302002 0.928223 -16 12 24 0 0.295654 0.933105 -16 12 25 0 0.290771 0.939453 -16 12 26 0 0.286865 0.946777 -16 12 27 0 0.283936 0.955078 -16 12 28 0 0.282227 0.965332 -16 12 29 0 0.28125 0.976562 -16 12 30 0 0.280273 0.986816 -16 12 31 0 0.280029 0.99707 -16 13 0 0.712402 0.359375 0 -16 13 1 0.712402 0.359375 0 -16 13 2 0.712402 0.359375 0 -16 13 3 0.712402 0.359375 0 -16 13 4 0.712402 0.359375 0 -16 13 5 0.712402 0.359375 0 -16 13 6 0.712402 0.359375 0 -16 13 7 0.712402 0.359619 0 -16 13 8 0.712402 0.359863 0 -16 13 9 0.712402 0.360352 0 -16 13 10 0.712891 0.361328 0 -16 13 11 0.712891 0.36084 0.148804 -16 13 12 0.712891 0.359619 0.241943 -16 13 13 0.711914 0.356689 0.330322 -16 13 14 0.705566 0.354248 0.426025 -16 13 15 0.683105 0.368408 0.52002 -16 13 16 0.657227 0.378906 0.60791 -16 13 17 0.621582 0.378662 0.695312 -16 13 18 0.573242 0.376953 0.775391 -16 13 19 0.513672 0.374023 0.845215 -16 13 20 0.441406 0.370361 0.902344 -16 13 21 0.338867 0.35498 0.92041 -16 13 22 0.19397 0.339355 0.925781 -16 13 23 0 0.327393 0.930176 -16 13 24 0 0.318604 0.935547 -16 13 25 0 0.311035 0.941895 -16 13 26 0 0.304932 0.949219 -16 13 27 0 0.300049 0.95752 -16 13 28 0 0.296387 0.967773 -16 13 29 0 0.293457 0.977539 -16 13 30 0 0.291016 0.987305 -16 13 31 0 0.289551 0.997559 -16 14 0 0.705078 0.437988 0.112061 -16 14 1 0.705078 0.437988 0.112061 -16 14 2 0.705078 0.437988 0.112061 -16 14 3 0.705078 0.437988 0.112061 -16 14 4 0.705078 0.437988 0.112061 -16 14 5 0.705078 0.437988 0.112122 -16 14 6 0.705078 0.438232 0.112183 -16 14 7 0.705078 0.438232 0.112305 -16 14 8 0.705078 0.438477 0.112549 -16 14 9 0.705078 0.438721 0.113037 -16 14 10 0.705078 0.439453 0.113892 -16 14 11 0.703613 0.439453 0.187622 -16 14 12 0.701172 0.439209 0.259521 -16 14 13 0.697266 0.437988 0.335449 -16 14 14 0.690918 0.43457 0.421387 -16 14 15 0.67334 0.434082 0.516602 -16 14 16 0.645508 0.440918 0.605957 -16 14 17 0.610352 0.438232 0.694336 -16 14 18 0.561523 0.43335 0.774902 -16 14 19 0.500977 0.426758 0.845215 -16 14 20 0.426758 0.419189 0.90332 -16 14 21 0.320557 0.399414 0.92334 -16 14 22 0.149414 0.378662 0.928711 -16 14 23 0 0.362793 0.934082 -16 14 24 0 0.350586 0.939453 -16 14 25 0 0.340088 0.945312 -16 14 26 0 0.331055 0.952637 -16 14 27 0 0.323486 0.961426 -16 14 28 0 0.316895 0.969727 -16 14 29 0 0.311279 0.978516 -16 14 30 0 0.306885 0.988281 -16 14 31 0 0.303467 0.999023 -16 15 0 0.696289 0.524414 0.181885 -16 15 1 0.696289 0.524414 0.181885 -16 15 2 0.696289 0.524414 0.181885 -16 15 3 0.696289 0.524414 0.181885 -16 15 4 0.696289 0.524902 0.181885 -16 15 5 0.696289 0.524902 0.181885 -16 15 6 0.696289 0.524902 0.182007 -16 15 7 0.696289 0.524902 0.182007 -16 15 8 0.696289 0.524902 0.182007 -16 15 9 0.696289 0.525391 0.182129 -16 15 10 0.696289 0.525879 0.182373 -16 15 11 0.694824 0.525879 0.219849 -16 15 12 0.690918 0.525391 0.281982 -16 15 13 0.683105 0.523926 0.350586 -16 15 14 0.67041 0.520508 0.426025 -16 15 15 0.652832 0.514648 0.510254 -16 15 16 0.626953 0.51416 0.602539 -16 15 17 0.591309 0.509277 0.691895 -16 15 18 0.54248 0.501465 0.773438 -16 15 19 0.47998 0.491455 0.845215 -16 15 20 0.4021 0.47998 0.903809 -16 15 21 0.287842 0.455811 0.927246 -16 15 22 0 0.429688 0.933594 -16 15 23 0 0.409424 0.939453 -16 15 24 0 0.393066 0.945312 -16 15 25 0 0.378662 0.950684 -16 15 26 0 0.365723 0.956543 -16 15 27 0 0.354248 0.963379 -16 15 28 0 0.344482 0.97168 -16 15 29 0 0.336182 0.980957 -16 15 30 0 0.329102 0.990234 -16 15 31 0 0.323242 1 -16 16 0 0.675781 0.620117 0.194702 -16 16 1 0.675781 0.620117 0.194702 -16 16 2 0.675781 0.620117 0.194702 -16 16 3 0.675781 0.620117 0.194702 -16 16 4 0.675781 0.620117 0.194702 -16 16 5 0.675781 0.620117 0.194702 -16 16 6 0.675781 0.620117 0.194702 -16 16 7 0.675781 0.620605 0.194702 -16 16 8 0.675781 0.620605 0.194702 -16 16 9 0.675781 0.620605 0.194702 -16 16 10 0.675781 0.621094 0.194824 -16 16 11 0.675293 0.621094 0.215332 -16 16 12 0.671387 0.620605 0.281006 -16 16 13 0.664062 0.619141 0.352539 -16 16 14 0.651367 0.616211 0.430908 -16 16 15 0.629883 0.608887 0.513672 -16 16 16 0.596191 0.596191 0.596191 -16 16 17 0.560547 0.590332 0.687012 -16 16 18 0.510742 0.580078 0.770508 -16 16 19 0.445312 0.566895 0.843262 -16 16 20 0.359863 0.551758 0.90332 -16 16 21 0.220947 0.523926 0.931641 -16 16 22 0 0.491943 0.938965 -16 16 23 0 0.466064 0.944824 -16 16 24 0 0.445068 0.949707 -16 16 25 0 0.42627 0.955078 -16 16 26 0 0.40918 0.960938 -16 16 27 0 0.394043 0.967773 -16 16 28 0 0.380615 0.975586 -16 16 29 0 0.368896 0.984375 -16 16 30 0 0.358643 0.993652 -16 16 31 0 0.349854 1 -16 17 0 0.619141 0.699707 0.187744 -16 17 1 0.619141 0.699707 0.187744 -16 17 2 0.619141 0.699707 0.187744 -16 17 3 0.619141 0.699707 0.187744 -16 17 4 0.619141 0.699707 0.187744 -16 17 5 0.619141 0.699707 0.187744 -16 17 6 0.619141 0.699707 0.187744 -16 17 7 0.619141 0.699707 0.187744 -16 17 8 0.619141 0.699707 0.187744 -16 17 9 0.619141 0.699707 0.187744 -16 17 10 0.619141 0.700195 0.187744 -16 17 11 0.619629 0.700684 0.187866 -16 17 12 0.615723 0.700195 0.257568 -16 17 13 0.608887 0.69873 0.33252 -16 17 14 0.59668 0.695312 0.412598 -16 17 15 0.577148 0.688965 0.496582 -16 17 16 0.549805 0.681641 0.585938 -16 17 17 0.513184 0.675293 0.678223 -16 17 18 0.460449 0.664062 0.763672 -16 17 19 0.387939 0.648926 0.839355 -16 17 20 0.282227 0.630859 0.900879 -16 17 21 0 0.600586 0.935059 -16 17 22 0 0.562988 0.945312 -16 17 23 0 0.532227 0.952148 -16 17 24 0 0.506348 0.95752 -16 17 25 0 0.48291 0.962402 -16 17 26 0 0.461426 0.968262 -16 17 27 0 0.441895 0.974609 -16 17 28 0 0.424316 0.981445 -16 17 29 0 0.408936 0.989746 -16 17 30 0 0.39502 0.998535 -16 17 31 0 0.382568 1 -16 18 0 0.54248 0.77002 0.178711 -16 18 1 0.54248 0.77002 0.178711 -16 18 2 0.54248 0.77002 0.178711 -16 18 3 0.54248 0.77002 0.178711 -16 18 4 0.54248 0.77002 0.178711 -16 18 5 0.54248 0.77002 0.178711 -16 18 6 0.54248 0.77002 0.178711 -16 18 7 0.54248 0.77002 0.178711 -16 18 8 0.54248 0.77002 0.178711 -16 18 9 0.54248 0.77002 0.178711 -16 18 10 0.54248 0.770508 0.178833 -16 18 11 0.542969 0.770508 0.178833 -16 18 12 0.540527 0.770996 0.226074 -16 18 13 0.53418 0.770508 0.306885 -16 18 14 0.523438 0.769531 0.389893 -16 18 15 0.506348 0.76709 0.477295 -16 18 16 0.480225 0.76416 0.570312 -16 18 17 0.440186 0.758789 0.664551 -16 18 18 0.379395 0.748047 0.75293 -16 18 19 0.283691 0.732422 0.831055 -16 18 20 0 0.712402 0.895508 -16 18 21 0 0.681152 0.936035 -16 18 22 0 0.641602 0.953125 -16 18 23 0 0.606445 0.962402 -16 18 24 0 0.576172 0.96875 -16 18 25 0 0.547852 0.974121 -16 18 26 0 0.520996 0.979492 -16 18 27 0 0.496826 0.984863 -16 18 28 0 0.474854 0.990723 -16 18 29 0 0.454834 0.998047 -16 18 30 0 0.437012 1 -16 18 31 0 0.420898 1 -16 19 0 0.446289 0.836914 0.170166 -16 19 1 0.446289 0.836914 0.170166 -16 19 2 0.446289 0.836914 0.170166 -16 19 3 0.446289 0.836914 0.170166 -16 19 4 0.446289 0.836914 0.170166 -16 19 5 0.446289 0.836914 0.170166 -16 19 6 0.446289 0.836914 0.170166 -16 19 7 0.446289 0.836914 0.170166 -16 19 8 0.446289 0.836914 0.170166 -16 19 9 0.446533 0.836914 0.170166 -16 19 10 0.446533 0.837402 0.170288 -16 19 11 0.446777 0.837402 0.170288 -16 19 12 0.446533 0.837891 0.186401 -16 19 13 0.439453 0.838867 0.278564 -16 19 14 0.427734 0.839355 0.365723 -16 19 15 0.408203 0.839844 0.455811 -16 19 16 0.375732 0.839355 0.550781 -16 19 17 0.321533 0.835449 0.646484 -16 19 18 0.21875 0.82666 0.737305 -16 19 19 0 0.811523 0.818359 -16 19 20 0 0.791504 0.885742 -16 19 21 0 0.761719 0.93457 -16 19 22 0 0.723145 0.960938 -16 19 23 0 0.685547 0.975098 -16 19 24 0 0.651367 0.983887 -16 19 25 0 0.618164 0.989746 -16 19 26 0 0.586914 0.994629 -16 19 27 0 0.557617 0.999023 -16 19 28 0 0.530273 1 -16 19 29 0 0.505859 1 -16 19 30 0 0.483398 1 -16 19 31 0 0.463135 1 -16 20 0 0.303467 0.896973 0.161743 -16 20 1 0.303467 0.896973 0.161743 -16 20 2 0.303467 0.896973 0.161743 -16 20 3 0.303467 0.896973 0.161743 -16 20 4 0.303467 0.896973 0.161743 -16 20 5 0.303467 0.896973 0.161743 -16 20 6 0.303467 0.896973 0.161743 -16 20 7 0.303467 0.896973 0.161743 -16 20 8 0.303711 0.896973 0.161743 -16 20 9 0.303711 0.896973 0.161743 -16 20 10 0.304199 0.897461 0.161865 -16 20 11 0.304688 0.897461 0.161865 -16 20 12 0.30542 0.897949 0.161987 -16 20 13 0.296143 0.898926 0.246094 -16 20 14 0.275146 0.900879 0.3396 -16 20 15 0.236694 0.902832 0.431885 -16 20 16 0.145508 0.904297 0.527832 -16 20 17 0 0.902344 0.624512 -16 20 18 0 0.895508 0.717285 -16 20 19 0 0.882324 0.800781 -16 20 20 0 0.86377 0.871582 -16 20 21 0 0.837891 0.928223 -16 20 22 0 0.803223 0.965332 -16 20 23 0 0.765625 0.986816 -16 20 24 0 0.729004 0.999023 -16 20 25 0 0.691895 1 -16 20 26 0 0.655762 1 -16 20 27 0 0.621582 1 -16 20 28 0 0.589355 1 -16 20 29 0 0.55957 1 -16 20 30 0 0.532715 1 -16 20 31 0 0.507812 1 -16 21 0 0 0.949219 0.152954 -16 21 1 0 0.949219 0.152954 -16 21 2 0 0.949219 0.152954 -16 21 3 0 0.949219 0.152954 -16 21 4 0 0.949219 0.152954 -16 21 5 0 0.949219 0.152954 -16 21 6 0 0.949219 0.152954 -16 21 7 0 0.949219 0.152954 -16 21 8 0 0.949219 0.152954 -16 21 9 0 0.949219 0.152954 -16 21 10 0 0.949219 0.152954 -16 21 11 0 0.949707 0.153076 -16 21 12 0 0.949707 0.153198 -16 21 13 0 0.950684 0.206543 -16 21 14 0 0.953125 0.310303 -16 21 15 0 0.956543 0.405518 -16 21 16 0 0.958984 0.502441 -16 21 17 0 0.959473 0.599609 -16 21 18 0 0.955078 0.693359 -16 21 19 0 0.944336 0.778809 -16 21 20 0 0.928223 0.852539 -16 21 21 0 0.905762 0.915039 -16 21 22 0 0.876953 0.962402 -16 21 23 0 0.842285 0.992676 -16 21 24 0 0.805664 1 -16 21 25 0 0.766602 1 -16 21 26 0 0.727051 1 -16 21 27 0 0.687988 1 -16 21 28 0 0.651367 1 -16 21 29 0 0.616699 1 -16 21 30 0 0.584473 1 -16 21 31 0 0.555176 1 -16 22 0 0 0.992676 0.143799 -16 22 1 0 0.992676 0.143799 -16 22 2 0 0.992676 0.143799 -16 22 3 0 0.992676 0.143799 -16 22 4 0 0.992676 0.143799 -16 22 5 0 0.992676 0.143799 -16 22 6 0 0.992676 0.143799 -16 22 7 0 0.992676 0.143799 -16 22 8 0 0.992676 0.143921 -16 22 9 0 0.992676 0.143921 -16 22 10 0 0.992676 0.143921 -16 22 11 0 0.992676 0.144043 -16 22 12 0 0.993164 0.144165 -16 22 13 0 0.993164 0.153809 -16 22 14 0 0.996094 0.277832 -16 22 15 0 1 0.377441 -16 22 16 0 1 0.474854 -16 22 17 0 1 0.572266 -16 22 18 0 1 0.666504 -16 22 19 0 0.99707 0.753418 -16 22 20 0 0.983398 0.82959 -16 22 21 0 0.963867 0.895508 -16 22 22 0 0.939453 0.949707 -16 22 23 0 0.910156 0.98877 -16 22 24 0 0.876465 1 -16 22 25 0 0.838379 1 -16 22 26 0 0.796875 1 -16 22 27 0 0.754883 1 -16 22 28 0 0.713867 1 -16 22 29 0 0.674805 1 -16 22 30 0 0.638184 1 -16 22 31 0 0.604492 1 -16 23 0 0 1 0.134888 -16 23 1 0 1 0.134888 -16 23 2 0 1 0.134888 -16 23 3 0 1 0.134888 -16 23 4 0 1 0.134888 -16 23 5 0 1 0.134888 -16 23 6 0 1 0.134888 -16 23 7 0 1 0.134888 -16 23 8 0 1 0.134888 -16 23 9 0 1 0.134888 -16 23 10 0 1 0.13501 -16 23 11 0 1 0.13501 -16 23 12 0 1 0.135132 -16 23 13 0 1 0.135376 -16 23 14 0 1 0.243286 -16 23 15 0 1 0.348877 -16 23 16 0 1 0.447754 -16 23 17 0 1 0.544922 -16 23 18 0 1 0.638672 -16 23 19 0 1 0.726562 -16 23 20 0 1 0.804688 -16 23 21 0 1 0.873047 -16 23 22 0 0.990234 0.930176 -16 23 23 0 0.964844 0.975586 -16 23 24 0 0.936035 1 -16 23 25 0 0.900879 1 -16 23 26 0 0.860352 1 -16 23 27 0 0.817383 1 -16 23 28 0 0.773926 1 -16 23 29 0 0.730957 1 -16 23 30 0 0.69043 1 -16 23 31 0 0.652344 1 -16 24 0 0 1 0.125977 -16 24 1 0 1 0.125977 -16 24 2 0 1 0.125977 -16 24 3 0 1 0.125977 -16 24 4 0 1 0.125977 -16 24 5 0 1 0.125977 -16 24 6 0 1 0.125977 -16 24 7 0 1 0.126099 -16 24 8 0 1 0.126099 -16 24 9 0 1 0.126099 -16 24 10 0 1 0.126099 -16 24 11 0 1 0.126221 -16 24 12 0 1 0.126343 -16 24 13 0 1 0.126587 -16 24 14 0 1 0.204712 -16 24 15 0 1 0.320068 -16 24 16 0 1 0.420654 -16 24 17 0 1 0.517578 -16 24 18 0 1 0.611328 -16 24 19 0 1 0.699219 -16 24 20 0 1 0.77832 -16 24 21 0 1 0.848633 -16 24 22 0 1 0.908691 -16 24 23 0 1 0.957031 -16 24 24 0 0.985352 0.996094 -16 24 25 0 0.954102 1 -16 24 26 0 0.916504 1 -16 24 27 0 0.874023 1 -16 24 28 0 0.82959 1 -16 24 29 0 0.784668 1 -16 24 30 0 0.740723 1 -16 24 31 0 0.699219 1 -16 25 0 0 1 0.116394 -16 25 1 0 1 0.116394 -16 25 2 0 1 0.116394 -16 25 3 0 1 0.116394 -16 25 4 0 1 0.116394 -16 25 5 0 1 0.116394 -16 25 6 0 1 0.116394 -16 25 7 0 1 0.116394 -16 25 8 0 1 0.116394 -16 25 9 0 1 0.116455 -16 25 10 0 1 0.116455 -16 25 11 0 1 0.116577 -16 25 12 0 1 0.116699 -16 25 13 0 1 0.116943 -16 25 14 0 1 0.151489 -16 25 15 0 1 0.287842 -16 25 16 0 1 0.391357 -16 25 17 0 1 0.488037 -16 25 18 0 1 0.581055 -16 25 19 0 1 0.668457 -16 25 20 0 1 0.748047 -16 25 21 0 1 0.819824 -16 25 22 0 1 0.882324 -16 25 23 0 1 0.934082 -16 25 24 0 1 0.976562 -16 25 25 0 1 1 -16 25 26 0 0.969238 1 -16 25 27 0 0.929199 1 -16 25 28 0 0.885254 1 -16 25 29 0 0.839355 1 -16 25 30 0 0.793457 1 -16 25 31 0 0.748535 1 -16 26 0 0 1 0.105835 -16 26 1 0 1 0.105835 -16 26 2 0 1 0.105835 -16 26 3 0 1 0.105835 -16 26 4 0 1 0.105835 -16 26 5 0 1 0.105835 -16 26 6 0 1 0.105835 -16 26 7 0 1 0.105835 -16 26 8 0 1 0.105835 -16 26 9 0 1 0.105896 -16 26 10 0 1 0.105957 -16 26 11 0 1 0.106018 -16 26 12 0 1 0.10614 -16 26 13 0 1 0.106384 -16 26 14 0 1 0.10675 -16 26 15 0 1 0.250488 -16 26 16 0 1 0.359375 -16 26 17 0 1 0.456543 -16 26 18 0 1 0.54834 -16 26 19 0 1 0.635254 -16 26 20 0 1 0.714355 -16 26 21 0 1 0.787598 -16 26 22 0 1 0.852051 -16 26 23 0 1 0.90625 -16 26 24 0 1 0.95166 -16 26 25 0 1 0.993164 -16 26 26 0 1 1 -16 26 27 0 0.981445 1 -16 26 28 0 0.939453 1 -16 26 29 0 0.894043 1 -16 26 30 0 0.84668 1 -16 26 31 0 0.799805 1 -16 27 0 0 1 0.0941162 -16 27 1 0 1 0.0941162 -16 27 2 0 1 0.0941162 -16 27 3 0 1 0.0941162 -16 27 4 0 1 0.0941162 -16 27 5 0 1 0.0941162 -16 27 6 0 1 0.0941162 -16 27 7 0 1 0.0941162 -16 27 8 0 1 0.0941162 -16 27 9 0 1 0.0941772 -16 27 10 0 1 0.0942383 -16 27 11 0 1 0.0942993 -16 27 12 0 1 0.0944824 -16 27 13 0 1 0.0947266 -16 27 14 0 1 0.0951538 -16 27 15 0 1 0.2052 -16 27 16 0 1 0.324707 -16 27 17 0 1 0.423096 -16 27 18 0 1 0.51416 -16 27 19 0 1 0.599609 -16 27 20 0 1 0.678711 -16 27 21 0 1 0.751465 -16 27 22 0 1 0.817383 -16 27 23 0 1 0.873535 -16 27 24 0 1 0.921875 -16 27 25 0 1 0.966309 -16 27 26 0 1 1 -16 27 27 0 1 1 -16 27 28 0 0.990234 1 -16 27 29 0 0.946777 1 -16 27 30 0 0.899902 1 -16 27 31 0 0.852051 1 -16 28 0 0 1 0.0806885 -16 28 1 0 1 0.0806885 -16 28 2 0 1 0.0806885 -16 28 3 0 1 0.0806885 -16 28 4 0 1 0.0806885 -16 28 5 0 1 0.0806885 -16 28 6 0 1 0.0806885 -16 28 7 0 1 0.0806885 -16 28 8 0 1 0.0807495 -16 28 9 0 1 0.0807495 -16 28 10 0 1 0.0808105 -16 28 11 0 1 0.0809326 -16 28 12 0 1 0.0811157 -16 28 13 0 1 0.0814209 -16 28 14 0 1 0.0818481 -16 28 15 0 1 0.141357 -16 28 16 0 1 0.286621 -16 28 17 0 1 0.387695 -16 28 18 0 1 0.478271 -16 28 19 0 1 0.5625 -16 28 20 0 1 0.640137 -16 28 21 0 1 0.712891 -16 28 22 0 1 0.778809 -16 28 23 0 1 0.836426 -16 28 24 0 1 0.886719 -16 28 25 0 1 0.934082 -16 28 26 0 1 0.977539 -16 28 27 0 1 1 -16 28 28 0 1 1 -16 28 29 0 0.996094 1 -16 28 30 0 0.951172 1 -16 28 31 0 0.903809 1 -16 29 0 0 1 0.0641479 -16 29 1 0 1 0.0641479 -16 29 2 0 1 0.0641479 -16 29 3 0 1 0.064209 -16 29 4 0 1 0.064209 -16 29 5 0 1 0.064209 -16 29 6 0 1 0.064209 -16 29 7 0 1 0.064209 -16 29 8 0 1 0.064209 -16 29 9 0 1 0.06427 -16 29 10 0 1 0.0643311 -16 29 11 0 1 0.0644531 -16 29 12 0 1 0.0646973 -16 29 13 0 1 0.0650635 -16 29 14 0 1 0.0656128 -16 29 15 0 1 0.0665283 -16 29 16 0 1 0.24292 -16 29 17 0 1 0.350098 -16 29 18 0 1 0.440674 -16 29 19 0 1 0.523438 -16 29 20 0 1 0.599609 -16 29 21 0 1 0.671387 -16 29 22 0 1 0.737305 -16 29 23 0 1 0.79541 -16 29 24 0 1 0.84668 -16 29 25 0 1 0.896484 -16 29 26 0 1 0.943359 -16 29 27 0 1 0.98584 -16 29 28 0 1 1 -16 29 29 0 1 1 -16 29 30 0 1 1 -16 29 31 0 0.955078 1 -16 30 0 0 1 0.0390625 -16 30 1 0 1 0.0390625 -16 30 2 0 1 0.0390625 -16 30 3 0 1 0.0390625 -16 30 4 0 1 0.039093 -16 30 5 0 1 0.039093 -16 30 6 0 1 0.039093 -16 30 7 0 1 0.0391235 -16 30 8 0 1 0.0391541 -16 30 9 0 1 0.0392456 -16 30 10 0 1 0.0393982 -16 30 11 0 1 0.0396423 -16 30 12 0 1 0.0400696 -16 30 13 0 1 0.040741 -16 30 14 0 1 0.0417786 -16 30 15 0 1 0.0433044 -16 30 16 0 1 0.189209 -16 30 17 0 1 0.30957 -16 30 18 0 1 0.401367 -16 30 19 0 1 0.483154 -16 30 20 0 1 0.557617 -16 30 21 0 1 0.62793 -16 30 22 0 1 0.692871 -16 30 23 0 1 0.750488 -16 30 24 0 1 0.802734 -16 30 25 0 1 0.853516 -16 30 26 0 1 0.902832 -16 30 27 0 1 0.94873 -16 30 28 0 1 0.990723 -16 30 29 0 1 1 -16 30 30 0 1 1 -16 30 31 0 1 1 -16 31 0 0 1 0 -16 31 1 0 1 0 -16 31 2 0 1 0 -16 31 3 0 1 0 -16 31 4 0 1 0 -16 31 5 0 1 0 -16 31 6 0 1 0 -16 31 7 0 1 0 -16 31 8 0 1 0 -16 31 9 0 1 0 -16 31 10 0 1 0 -16 31 11 0 1 0 -16 31 12 0 1 0 -16 31 13 0 1 0 -16 31 14 0 1 0 -16 31 15 0 1 0 -16 31 16 0 1 0.103027 -16 31 17 0 1 0.265137 -16 31 18 0 1 0.360596 -16 31 19 0 1 0.44165 -16 31 20 0 1 0.514648 -16 31 21 0 1 0.58252 -16 31 22 0 1 0.645996 -16 31 23 0 1 0.703125 -16 31 24 0 1 0.755371 -16 31 25 0 1 0.806641 -16 31 26 0 1 0.85791 -16 31 27 0 1 0.907227 -16 31 28 0 1 0.953125 -16 31 29 0 1 0.995117 -16 31 30 0 1 1 -16 31 31 0 1 1 -17 0 0 0.764648 0 0.0446777 -17 0 1 0.764648 0 0.0446777 -17 0 2 0.764648 0 0.0446472 -17 0 3 0.764648 0 0.0446472 -17 0 4 0.764648 0 0.0446167 -17 0 5 0.764648 0 0.0445862 -17 0 6 0.764648 0 0.0444946 -17 0 7 0.764648 0 0.044342 -17 0 8 0.764648 0 0.0440369 -17 0 9 0.765137 0 0.0434265 -17 0 10 0.765137 0 0.0422974 -17 0 11 0.769043 0 0.0416565 -17 0 12 0.775879 0 0.176758 -17 0 13 0.786133 0 0.289307 -17 0 14 0.794434 0 0.392334 -17 0 15 0.796875 0.117798 0.499756 -17 0 16 0.788086 0.235596 0.600586 -17 0 17 0.761719 0.256836 0.69043 -17 0 18 0.722168 0.266357 0.772461 -17 0 19 0.67334 0.274902 0.84375 -17 0 20 0.616699 0.281982 0.902832 -17 0 21 0.539062 0.280762 0.927734 -17 0 22 0.455322 0.276367 0.936035 -17 0 23 0.37207 0.272949 0.940918 -17 0 24 0.279053 0.270264 0.944824 -17 0 25 0.0883789 0.268066 0.949219 -17 0 26 0 0.266846 0.955078 -17 0 27 0 0.266357 0.961914 -17 0 28 0 0.266357 0.970215 -17 0 29 0 0.267334 0.980469 -17 0 30 0 0.268799 0.991211 -17 0 31 0 0.270508 1 -17 1 0 0.764648 0 0.0446167 -17 1 1 0.764648 0 0.0446167 -17 1 2 0.764648 0 0.0446167 -17 1 3 0.764648 0 0.0446167 -17 1 4 0.764648 0 0.0445862 -17 1 5 0.764648 0 0.0445251 -17 1 6 0.764648 0 0.0444641 -17 1 7 0.764648 0 0.0443115 -17 1 8 0.764648 0 0.0440063 -17 1 9 0.765137 0 0.043396 -17 1 10 0.765137 0 0.0422668 -17 1 11 0.769043 0 0.041626 -17 1 12 0.775879 0 0.176758 -17 1 13 0.786133 0 0.289307 -17 1 14 0.794434 0 0.392334 -17 1 15 0.796875 0.117981 0.499756 -17 1 16 0.788086 0.235718 0.600586 -17 1 17 0.761719 0.256836 0.69043 -17 1 18 0.722168 0.266357 0.772461 -17 1 19 0.67334 0.274902 0.84375 -17 1 20 0.616699 0.281982 0.902832 -17 1 21 0.539062 0.280762 0.927734 -17 1 22 0.455322 0.276367 0.936035 -17 1 23 0.37207 0.272949 0.940918 -17 1 24 0.279053 0.270264 0.944824 -17 1 25 0.0883789 0.268066 0.949219 -17 1 26 0 0.266846 0.955078 -17 1 27 0 0.266357 0.961914 -17 1 28 0 0.266602 0.970215 -17 1 29 0 0.267334 0.980469 -17 1 30 0 0.268799 0.991211 -17 1 31 0 0.270508 1 -17 2 0 0.764648 0 0.0445557 -17 2 1 0.764648 0 0.0445557 -17 2 2 0.764648 0 0.0445251 -17 2 3 0.764648 0 0.0445251 -17 2 4 0.764648 0 0.0444946 -17 2 5 0.764648 0 0.0444641 -17 2 6 0.764648 0 0.0443726 -17 2 7 0.764648 0 0.04422 -17 2 8 0.764648 0 0.0439148 -17 2 9 0.765137 0 0.0433044 -17 2 10 0.765137 0 0.0421753 -17 2 11 0.769043 0 0.0415344 -17 2 12 0.775879 0 0.176758 -17 2 13 0.786133 0 0.289307 -17 2 14 0.794434 0 0.392334 -17 2 15 0.796875 0.118286 0.499756 -17 2 16 0.788086 0.23584 0.600586 -17 2 17 0.761719 0.25708 0.69043 -17 2 18 0.722168 0.266357 0.772461 -17 2 19 0.67334 0.275146 0.84375 -17 2 20 0.616699 0.282227 0.902832 -17 2 21 0.539062 0.280762 0.927734 -17 2 22 0.455322 0.276611 0.936035 -17 2 23 0.371826 0.272949 0.940918 -17 2 24 0.279053 0.270264 0.944824 -17 2 25 0.0883179 0.268311 0.949219 -17 2 26 0 0.266846 0.955078 -17 2 27 0 0.266357 0.961914 -17 2 28 0 0.266602 0.970215 -17 2 29 0 0.267334 0.980469 -17 2 30 0 0.268799 0.991211 -17 2 31 0 0.270508 1 -17 3 0 0.764648 0 0.0444031 -17 3 1 0.764648 0 0.0444031 -17 3 2 0.764648 0 0.0444031 -17 3 3 0.764648 0 0.0443726 -17 3 4 0.764648 0 0.0443726 -17 3 5 0.764648 0 0.0443115 -17 3 6 0.764648 0 0.0442505 -17 3 7 0.764648 0 0.0440979 -17 3 8 0.764648 0 0.0437622 -17 3 9 0.765137 0 0.0431519 -17 3 10 0.765137 0 0.0420227 -17 3 11 0.769043 0 0.0413818 -17 3 12 0.775879 0 0.176758 -17 3 13 0.786133 0 0.289307 -17 3 14 0.794434 0 0.392334 -17 3 15 0.796875 0.118896 0.499756 -17 3 16 0.788086 0.235962 0.600586 -17 3 17 0.761719 0.25708 0.69043 -17 3 18 0.722168 0.266602 0.772461 -17 3 19 0.67334 0.275146 0.84375 -17 3 20 0.616699 0.282227 0.902832 -17 3 21 0.539062 0.281006 0.927734 -17 3 22 0.455322 0.276611 0.936035 -17 3 23 0.371826 0.272949 0.940918 -17 3 24 0.279053 0.270264 0.944824 -17 3 25 0.0881958 0.268311 0.949219 -17 3 26 0 0.266846 0.955078 -17 3 27 0 0.266357 0.961914 -17 3 28 0 0.266602 0.970215 -17 3 29 0 0.267334 0.980469 -17 3 30 0 0.268799 0.991211 -17 3 31 0 0.270508 1 -17 4 0 0.764648 0 0.0441284 -17 4 1 0.764648 0 0.0441284 -17 4 2 0.764648 0 0.0441284 -17 4 3 0.764648 0 0.0441284 -17 4 4 0.764648 0 0.0440979 -17 4 5 0.764648 0 0.0440674 -17 4 6 0.764648 0 0.0439758 -17 4 7 0.764648 0 0.0438232 -17 4 8 0.764648 0 0.0434875 -17 4 9 0.765137 0 0.0428772 -17 4 10 0.765137 0 0.0417175 -17 4 11 0.769043 0 0.0410767 -17 4 12 0.775879 0 0.176758 -17 4 13 0.786133 0 0.289307 -17 4 14 0.794434 0 0.39209 -17 4 15 0.796875 0.119934 0.499756 -17 4 16 0.788086 0.236328 0.600586 -17 4 17 0.761719 0.257568 0.69043 -17 4 18 0.722168 0.266846 0.772461 -17 4 19 0.67334 0.275391 0.84375 -17 4 20 0.616699 0.282471 0.902832 -17 4 21 0.539062 0.281006 0.927734 -17 4 22 0.455322 0.276855 0.936035 -17 4 23 0.371826 0.273193 0.940918 -17 4 24 0.279053 0.270508 0.944824 -17 4 25 0.0879517 0.268311 0.949219 -17 4 26 0 0.26709 0.955078 -17 4 27 0 0.266357 0.961914 -17 4 28 0 0.266602 0.970215 -17 4 29 0 0.267334 0.980469 -17 4 30 0 0.268799 0.991211 -17 4 31 0 0.270508 1 -17 5 0 0.764648 0 0.0436096 -17 5 1 0.764648 0 0.0436096 -17 5 2 0.764648 0 0.0436096 -17 5 3 0.764648 0 0.0435791 -17 5 4 0.764648 0 0.0435791 -17 5 5 0.764648 0 0.0435181 -17 5 6 0.764648 0 0.0434265 -17 5 7 0.764648 0 0.0432739 -17 5 8 0.765137 0 0.0429688 -17 5 9 0.765137 0 0.0423279 -17 5 10 0.765137 0 0.0411377 -17 5 11 0.769043 0 0.0404663 -17 5 12 0.775879 0 0.176636 -17 5 13 0.786133 0 0.289307 -17 5 14 0.794434 0 0.39209 -17 5 15 0.796875 0.121948 0.499756 -17 5 16 0.788086 0.237061 0.600586 -17 5 17 0.761719 0.258057 0.69043 -17 5 18 0.722168 0.267334 0.772461 -17 5 19 0.67334 0.275879 0.84375 -17 5 20 0.616211 0.282959 0.902832 -17 5 21 0.539062 0.281494 0.928223 -17 5 22 0.455322 0.2771 0.936035 -17 5 23 0.371826 0.273438 0.940918 -17 5 24 0.279053 0.270508 0.944824 -17 5 25 0.0875244 0.268555 0.949219 -17 5 26 0 0.26709 0.955078 -17 5 27 0 0.266602 0.961914 -17 5 28 0 0.266846 0.970215 -17 5 29 0 0.267578 0.980469 -17 5 30 0 0.268799 0.991211 -17 5 31 0 0.270508 1 -17 6 0 0.765137 0 0.042572 -17 6 1 0.765137 0 0.042572 -17 6 2 0.765137 0 0.042572 -17 6 3 0.765137 0 0.0425415 -17 6 4 0.765137 0 0.0425415 -17 6 5 0.765137 0 0.0424805 -17 6 6 0.765137 0 0.0423889 -17 6 7 0.765137 0 0.0422363 -17 6 8 0.765137 0 0.0419006 -17 6 9 0.765137 0 0.0412292 -17 6 10 0.765137 0 0.0400085 -17 6 11 0.769043 0 0.0393066 -17 6 12 0.775879 0 0.176636 -17 6 13 0.786133 0 0.289307 -17 6 14 0.794434 0 0.39209 -17 6 15 0.796875 0.125732 0.499512 -17 6 16 0.788086 0.238403 0.600586 -17 6 17 0.761719 0.259277 0.69043 -17 6 18 0.722168 0.268555 0.772461 -17 6 19 0.67334 0.276855 0.84375 -17 6 20 0.616211 0.283691 0.902832 -17 6 21 0.539062 0.282227 0.928223 -17 6 22 0.455078 0.277588 0.936035 -17 6 23 0.371826 0.273926 0.940918 -17 6 24 0.278809 0.270996 0.944824 -17 6 25 0.086731 0.269043 0.949707 -17 6 26 0 0.267578 0.955078 -17 6 27 0 0.266846 0.961914 -17 6 28 0 0.26709 0.970215 -17 6 29 0 0.267822 0.980469 -17 6 30 0 0.269043 0.991211 -17 6 31 0 0.270752 1 -17 7 0 0.765137 0 0.0404358 -17 7 1 0.765137 0 0.0404358 -17 7 2 0.765137 0 0.0404053 -17 7 3 0.765137 0 0.0404053 -17 7 4 0.765137 0 0.0403748 -17 7 5 0.765137 0 0.0403442 -17 7 6 0.765137 0 0.0402222 -17 7 7 0.765137 0 0.0400391 -17 7 8 0.765137 0 0.0396729 -17 7 9 0.765137 0 0.0389709 -17 7 10 0.765625 0 0.0375977 -17 7 11 0.769043 0 0.0368042 -17 7 12 0.776367 0 0.176514 -17 7 13 0.786133 0 0.289062 -17 7 14 0.794434 0 0.39209 -17 7 15 0.796875 0.132568 0.499512 -17 7 16 0.787598 0.240967 0.600586 -17 7 17 0.761719 0.261475 0.69043 -17 7 18 0.722168 0.270508 0.772461 -17 7 19 0.672852 0.278564 0.84375 -17 7 20 0.616211 0.285156 0.902832 -17 7 21 0.538574 0.283447 0.928223 -17 7 22 0.455078 0.278809 0.936035 -17 7 23 0.371582 0.274902 0.940918 -17 7 24 0.278564 0.271973 0.944824 -17 7 25 0.085083 0.269775 0.949707 -17 7 26 0 0.268066 0.955078 -17 7 27 0 0.267334 0.961914 -17 7 28 0 0.267578 0.970703 -17 7 29 0 0.268311 0.980469 -17 7 30 0 0.269531 0.991211 -17 7 31 0 0.270996 1 -17 8 0 0.765625 0 0.0355835 -17 8 1 0.765625 0 0.0355835 -17 8 2 0.765625 0 0.0355835 -17 8 3 0.765625 0 0.035553 -17 8 4 0.765625 0 0.0355225 -17 8 5 0.765625 0 0.0354614 -17 8 6 0.765625 0 0.0353394 -17 8 7 0.765625 0 0.0351257 -17 8 8 0.765625 0 0.034668 -17 8 9 0.765625 0 0.0337524 -17 8 10 0.766113 0 0.0320129 -17 8 11 0.769531 0 0.0309448 -17 8 12 0.776367 0 0.176392 -17 8 13 0.786133 0 0.288818 -17 8 14 0.794434 0 0.391846 -17 8 15 0.796387 0.144409 0.499512 -17 8 16 0.787598 0.245972 0.600586 -17 8 17 0.76123 0.265869 0.69043 -17 8 18 0.72168 0.274414 0.772461 -17 8 19 0.672852 0.281982 0.844238 -17 8 20 0.615723 0.288086 0.902832 -17 8 21 0.538574 0.286133 0.928223 -17 8 22 0.45459 0.281006 0.936035 -17 8 23 0.371094 0.276611 0.940918 -17 8 24 0.278076 0.273438 0.945312 -17 8 25 0.0817871 0.270996 0.949707 -17 8 26 0 0.269287 0.955078 -17 8 27 0 0.268555 0.961914 -17 8 28 0 0.268311 0.970703 -17 8 29 0 0.269043 0.980469 -17 8 30 0 0.27002 0.991211 -17 8 31 0 0.271729 1 -17 9 0 0.766602 0 0.0205383 -17 9 1 0.766602 0 0.0205231 -17 9 2 0.766602 0 0.0205078 -17 9 3 0.766602 0 0.020462 -17 9 4 0.766602 0 0.0203857 -17 9 5 0.766602 0 0.0202484 -17 9 6 0.766602 0 0.0199432 -17 9 7 0.766602 0 0.0193634 -17 9 8 0.766602 0 0.0181274 -17 9 9 0.766602 0 0.0152817 -17 9 10 0.766602 0.0100403 0 -17 9 11 0.77002 0.0415649 0 -17 9 12 0.776855 0 0.176147 -17 9 13 0.786133 0 0.28833 -17 9 14 0.794434 0 0.391602 -17 9 15 0.795898 0.163696 0.499268 -17 9 16 0.787109 0.254883 0.600586 -17 9 17 0.760742 0.273682 0.69043 -17 9 18 0.721191 0.281494 0.772461 -17 9 19 0.672363 0.28833 0.844238 -17 9 20 0.615234 0.293701 0.902832 -17 9 21 0.538086 0.290771 0.928223 -17 9 22 0.454102 0.284912 0.936523 -17 9 23 0.370361 0.280273 0.941406 -17 9 24 0.2771 0.276611 0.945312 -17 9 25 0.074707 0.273682 0.949707 -17 9 26 0 0.271729 0.955566 -17 9 27 0 0.270508 0.962402 -17 9 28 0 0.270264 0.970703 -17 9 29 0 0.270508 0.980469 -17 9 30 0 0.271484 0.991699 -17 9 31 0 0.272949 1 -17 10 0 0.767578 0.122437 0 -17 10 1 0.767578 0.122437 0 -17 10 2 0.767578 0.122437 0 -17 10 3 0.768066 0.122498 0 -17 10 4 0.768066 0.12262 0 -17 10 5 0.768066 0.122803 0 -17 10 6 0.768066 0.123108 0 -17 10 7 0.768066 0.123779 0 -17 10 8 0.768066 0.125122 0 -17 10 9 0.768066 0.127563 0 -17 10 10 0.768066 0.131836 0 -17 10 11 0.771484 0.134399 0 -17 10 12 0.777344 0.12915 0.175903 -17 10 13 0.786621 0.121826 0.287598 -17 10 14 0.794434 0.122986 0.391357 -17 10 15 0.79541 0.191772 0.498779 -17 10 16 0.786133 0.270264 0.600098 -17 10 17 0.759766 0.287354 0.69043 -17 10 18 0.720215 0.293701 0.772461 -17 10 19 0.671387 0.299316 0.844238 -17 10 20 0.614258 0.303467 0.902832 -17 10 21 0.537109 0.299072 0.928711 -17 10 22 0.452881 0.292236 0.936523 -17 10 23 0.369141 0.286377 0.941406 -17 10 24 0.275146 0.281982 0.945312 -17 10 25 0.0579834 0.278564 0.950195 -17 10 26 0 0.275879 0.955566 -17 10 27 0 0.27417 0.962402 -17 10 28 0 0.273438 0.971191 -17 10 29 0 0.273438 0.980957 -17 10 30 0 0.273926 0.991699 -17 10 31 0 0.274902 1 -17 11 0 0.77002 0.190552 0 -17 11 1 0.77002 0.190552 0 -17 11 2 0.77002 0.190552 0 -17 11 3 0.77002 0.190552 0 -17 11 4 0.77002 0.190674 0 -17 11 5 0.77002 0.190796 0 -17 11 6 0.77002 0.190918 0 -17 11 7 0.77002 0.191284 0 -17 11 8 0.770508 0.191895 0 -17 11 9 0.770508 0.193237 0 -17 11 10 0.770508 0.195435 0 -17 11 11 0.773438 0.197144 0 -17 11 12 0.778809 0.194214 0.17627 -17 11 13 0.786621 0.189941 0.286621 -17 11 14 0.793945 0.190918 0.390625 -17 11 15 0.793945 0.229492 0.497803 -17 11 16 0.78418 0.293945 0.600098 -17 11 17 0.758301 0.309082 0.689941 -17 11 18 0.71875 0.313477 0.772461 -17 11 19 0.669434 0.316895 0.844238 -17 11 20 0.612793 0.319336 0.90332 -17 11 21 0.535156 0.312988 0.929199 -17 11 22 0.450928 0.303955 0.937012 -17 11 23 0.366699 0.296875 0.941895 -17 11 24 0.271729 0.29126 0.946289 -17 11 25 0 0.286621 0.950684 -17 11 26 0 0.282959 0.956055 -17 11 27 0 0.280518 0.963379 -17 11 28 0 0.278809 0.97168 -17 11 29 0 0.278076 0.981445 -17 11 30 0 0.278076 0.992676 -17 11 31 0 0.278564 1 -17 12 0 0.773926 0.258057 0 -17 12 1 0.773926 0.258057 0 -17 12 2 0.773926 0.258057 0 -17 12 3 0.773926 0.258057 0 -17 12 4 0.773926 0.258057 0 -17 12 5 0.773926 0.258301 0 -17 12 6 0.773926 0.258301 0 -17 12 7 0.773926 0.258545 0 -17 12 8 0.773926 0.259033 0 -17 12 9 0.773926 0.259766 0 -17 12 10 0.774414 0.26123 0 -17 12 11 0.776367 0.262451 0 -17 12 12 0.780762 0.260742 0.179077 -17 12 13 0.787109 0.257812 0.285889 -17 12 14 0.792969 0.258789 0.389893 -17 12 15 0.791504 0.278076 0.496338 -17 12 16 0.78125 0.328613 0.599121 -17 12 17 0.755371 0.341064 0.689941 -17 12 18 0.71582 0.343262 0.771973 -17 12 19 0.666504 0.344238 0.844238 -17 12 20 0.609375 0.343994 0.90332 -17 12 21 0.532227 0.334961 0.929688 -17 12 22 0.44751 0.322998 0.937988 -17 12 23 0.362549 0.313477 0.942871 -17 12 24 0.265625 0.305908 0.946777 -17 12 25 0 0.299805 0.95166 -17 12 26 0 0.294678 0.95752 -17 12 27 0 0.290527 0.964355 -17 12 28 0 0.287842 0.972656 -17 12 29 0 0.286133 0.98291 -17 12 30 0 0.284912 0.993652 -17 12 31 0 0.284668 1 -17 13 0 0.778809 0.332031 0 -17 13 1 0.778809 0.332031 0 -17 13 2 0.778809 0.332031 0 -17 13 3 0.778809 0.332031 0 -17 13 4 0.778809 0.332031 0 -17 13 5 0.778809 0.332031 0 -17 13 6 0.778809 0.332031 0 -17 13 7 0.778809 0.332275 0 -17 13 8 0.778809 0.33252 0 -17 13 9 0.778809 0.333008 0 -17 13 10 0.779297 0.333984 0 -17 13 11 0.780273 0.335205 0 -17 13 12 0.782715 0.333984 0.188721 -17 13 13 0.786621 0.332031 0.287842 -17 13 14 0.790527 0.331299 0.388184 -17 13 15 0.787598 0.338379 0.493408 -17 13 16 0.775879 0.374756 0.598145 -17 13 17 0.750488 0.385254 0.689453 -17 13 18 0.710938 0.384766 0.771973 -17 13 19 0.661621 0.382568 0.844238 -17 13 20 0.604492 0.37915 0.903809 -17 13 21 0.527344 0.366455 0.931152 -17 13 22 0.441895 0.35083 0.938965 -17 13 23 0.355469 0.338135 0.944336 -17 13 24 0.255371 0.328125 0.948242 -17 13 25 0 0.31958 0.953125 -17 13 26 0 0.312256 0.958984 -17 13 27 0 0.306396 0.96582 -17 13 28 0 0.301758 0.974609 -17 13 29 0 0.29834 0.984375 -17 13 30 0 0.295898 0.995117 -17 13 31 0 0.294189 1 -17 14 0 0.78418 0.414062 0 -17 14 1 0.78418 0.414062 0 -17 14 2 0.78418 0.414307 0 -17 14 3 0.78418 0.414307 0 -17 14 4 0.78418 0.414307 0 -17 14 5 0.78418 0.414307 0 -17 14 6 0.78418 0.414307 0 -17 14 7 0.78418 0.414307 0 -17 14 8 0.78418 0.414551 0 -17 14 9 0.78418 0.415039 0 -17 14 10 0.784668 0.415771 0 -17 14 11 0.784668 0.41626 0.105713 -17 14 12 0.784668 0.416016 0.211426 -17 14 13 0.785156 0.415283 0.297119 -17 14 14 0.784668 0.412842 0.387939 -17 14 15 0.779297 0.412109 0.489014 -17 14 16 0.766602 0.432861 0.595215 -17 14 17 0.741699 0.442139 0.687988 -17 14 18 0.702637 0.438721 0.771484 -17 14 19 0.65332 0.43335 0.844238 -17 14 20 0.595703 0.42627 0.904297 -17 14 21 0.519043 0.409668 0.933105 -17 14 22 0.432373 0.38916 0.940918 -17 14 23 0.34375 0.372559 0.946289 -17 14 24 0.237061 0.359375 0.950684 -17 14 25 0 0.3479 0.956055 -17 14 26 0 0.337891 0.961914 -17 14 27 0 0.329346 0.96875 -17 14 28 0 0.32251 0.977539 -17 14 29 0 0.31665 0.987305 -17 14 30 0 0.312256 0.997559 -17 14 31 0 0.30835 1 -17 15 0 0.788086 0.503906 0.157959 -17 15 1 0.788086 0.503906 0.157959 -17 15 2 0.788086 0.503906 0.157959 -17 15 3 0.788086 0.503906 0.157959 -17 15 4 0.788086 0.504395 0.157959 -17 15 5 0.788086 0.504395 0.157959 -17 15 6 0.788086 0.504395 0.157959 -17 15 7 0.788086 0.504395 0.158081 -17 15 8 0.788086 0.504395 0.158203 -17 15 9 0.788086 0.504883 0.158447 -17 15 10 0.788086 0.505371 0.158813 -17 15 11 0.788086 0.505859 0.175049 -17 15 12 0.786133 0.505859 0.245728 -17 15 13 0.782227 0.505371 0.318359 -17 15 14 0.775879 0.503418 0.397217 -17 15 15 0.765137 0.498047 0.485352 -17 15 16 0.75 0.500977 0.588379 -17 15 17 0.728027 0.510742 0.685547 -17 15 18 0.688965 0.504883 0.769531 -17 15 19 0.640137 0.496094 0.843262 -17 15 20 0.582031 0.485596 0.904297 -17 15 21 0.504883 0.4646 0.935059 -17 15 22 0.416748 0.438965 0.943848 -17 15 23 0.324219 0.417969 0.949707 -17 15 24 0.203003 0.400879 0.95459 -17 15 25 0 0.385986 0.960449 -17 15 26 0 0.372559 0.966309 -17 15 27 0 0.36084 0.973633 -17 15 28 0 0.35083 0.981934 -17 15 29 0 0.342285 0.991699 -17 15 30 0 0.334717 1 -17 15 31 0 0.328125 1 -17 16 0 0.786133 0.602539 0.21106 -17 16 1 0.786133 0.602539 0.21106 -17 16 2 0.786133 0.602539 0.21106 -17 16 3 0.786133 0.602539 0.21106 -17 16 4 0.786133 0.602539 0.21106 -17 16 5 0.786133 0.602539 0.21106 -17 16 6 0.786133 0.602539 0.21106 -17 16 7 0.786133 0.602539 0.21106 -17 16 8 0.786133 0.602539 0.211182 -17 16 9 0.786133 0.602539 0.211182 -17 16 10 0.786133 0.603027 0.211304 -17 16 11 0.786133 0.604004 0.211548 -17 16 12 0.783691 0.603516 0.270752 -17 16 13 0.77832 0.603027 0.3396 -17 16 14 0.769043 0.601074 0.415283 -17 16 15 0.751953 0.595703 0.49585 -17 16 16 0.725098 0.583984 0.57959 -17 16 17 0.706055 0.589355 0.681152 -17 16 18 0.66748 0.581055 0.766602 -17 16 19 0.618652 0.569824 0.841309 -17 16 20 0.560059 0.556152 0.90332 -17 16 21 0.48291 0.53125 0.9375 -17 16 22 0.391357 0.5 0.947754 -17 16 23 0.290283 0.474609 0.955078 -17 16 24 0.118469 0.453613 0.960938 -17 16 25 0 0.43457 0.967285 -17 16 26 0 0.417236 0.973633 -17 16 27 0 0.401367 0.97998 -17 16 28 0 0.387207 0.986816 -17 16 29 0 0.374756 0.994141 -17 16 30 0 0.36377 1 -17 16 31 0 0.354248 1 -17 17 0 0.761719 0.699219 0.219482 -17 17 1 0.761719 0.699219 0.219482 -17 17 2 0.761719 0.699219 0.219482 -17 17 3 0.761719 0.699219 0.219482 -17 17 4 0.761719 0.699219 0.219482 -17 17 5 0.761719 0.699219 0.219482 -17 17 6 0.761719 0.699219 0.219482 -17 17 7 0.761719 0.699219 0.219482 -17 17 8 0.761719 0.699219 0.219482 -17 17 9 0.761719 0.699707 0.219482 -17 17 10 0.761719 0.699707 0.219482 -17 17 11 0.762207 0.700195 0.219604 -17 17 12 0.760254 0.700195 0.263428 -17 17 13 0.755859 0.700195 0.336182 -17 17 14 0.747559 0.69873 0.415283 -17 17 15 0.73291 0.695312 0.500488 -17 17 16 0.708984 0.687012 0.588379 -17 17 17 0.672852 0.672852 0.672852 -17 17 18 0.634766 0.663574 0.759766 -17 17 19 0.585938 0.650391 0.836914 -17 17 20 0.525879 0.633789 0.900391 -17 17 21 0.447021 0.606445 0.938965 -17 17 22 0.349121 0.570312 0.952148 -17 17 23 0.225342 0.540039 0.960938 -17 17 24 0 0.51416 0.966797 -17 17 25 0 0.490479 0.972656 -17 17 26 0 0.468506 0.978516 -17 17 27 0 0.448486 0.984375 -17 17 28 0 0.43042 0.990723 -17 17 29 0 0.414307 0.998535 -17 17 30 0 0.399658 1 -17 17 31 0 0.386963 1 -17 18 0 0.704102 0.776367 0.211914 -17 18 1 0.704102 0.776367 0.211914 -17 18 2 0.704102 0.776367 0.211914 -17 18 3 0.704102 0.776367 0.211914 -17 18 4 0.704102 0.776367 0.211914 -17 18 5 0.704102 0.776367 0.211914 -17 18 6 0.704102 0.776367 0.211914 -17 18 7 0.704102 0.776367 0.211914 -17 18 8 0.704102 0.776367 0.211914 -17 18 9 0.704102 0.776855 0.212036 -17 18 10 0.704102 0.776855 0.212036 -17 18 11 0.704102 0.776855 0.212036 -17 18 12 0.703613 0.777344 0.235107 -17 18 13 0.69873 0.777344 0.313232 -17 18 14 0.690918 0.775879 0.394775 -17 18 15 0.677246 0.772461 0.480957 -17 18 16 0.655273 0.764648 0.570312 -17 18 17 0.625 0.755859 0.660156 -17 18 18 0.587402 0.746582 0.749512 -17 18 19 0.537598 0.73291 0.828613 -17 18 20 0.474365 0.714355 0.89502 -17 18 21 0.389648 0.685059 0.937988 -17 18 22 0.273682 0.645996 0.956055 -17 18 23 0 0.611328 0.967285 -17 18 24 0 0.581543 0.974609 -17 18 25 0 0.553223 0.980469 -17 18 26 0 0.526855 0.986328 -17 18 27 0 0.502441 0.991699 -17 18 28 0 0.47998 0.998047 -17 18 29 0 0.459717 1 -17 18 30 0 0.441162 1 -17 18 31 0 0.424805 1 -17 19 0 0.629883 0.841309 0.202393 -17 19 1 0.629883 0.841309 0.202393 -17 19 2 0.629883 0.841309 0.202393 -17 19 3 0.629883 0.841309 0.202393 -17 19 4 0.629883 0.841309 0.202393 -17 19 5 0.629883 0.841309 0.202393 -17 19 6 0.629883 0.841309 0.202393 -17 19 7 0.629883 0.841309 0.202393 -17 19 8 0.629883 0.841309 0.202393 -17 19 9 0.629883 0.841309 0.202393 -17 19 10 0.629883 0.841309 0.202393 -17 19 11 0.630371 0.841797 0.202393 -17 19 12 0.630371 0.842285 0.202515 -17 19 13 0.626465 0.842285 0.28418 -17 19 14 0.619141 0.842285 0.369141 -17 19 15 0.606934 0.84082 0.457275 -17 19 16 0.587891 0.837402 0.549316 -17 19 17 0.560547 0.83252 0.643555 -17 19 18 0.521484 0.824707 0.734375 -17 19 19 0.467773 0.811035 0.815918 -17 19 20 0.39624 0.79248 0.884766 -17 19 21 0.29126 0.763672 0.93457 -17 19 22 0 0.725586 0.961426 -17 19 23 0 0.688477 0.976562 -17 19 24 0 0.654785 0.98584 -17 19 25 0 0.62207 0.992676 -17 19 26 0 0.59082 0.998535 -17 19 27 0 0.561523 1 -17 19 28 0 0.53418 1 -17 19 29 0 0.509766 1 -17 19 30 0 0.487061 1 -17 19 31 0 0.466553 1 -17 20 0 0.544922 0.899414 0.193115 -17 20 1 0.544922 0.899414 0.193115 -17 20 2 0.544922 0.899414 0.193115 -17 20 3 0.544922 0.899414 0.193115 -17 20 4 0.544922 0.899414 0.193115 -17 20 5 0.544922 0.899414 0.193115 -17 20 6 0.544922 0.899414 0.193115 -17 20 7 0.544922 0.899414 0.193115 -17 20 8 0.544922 0.899414 0.193115 -17 20 9 0.544922 0.899414 0.193115 -17 20 10 0.54541 0.899414 0.193115 -17 20 11 0.54541 0.899902 0.193237 -17 20 12 0.54541 0.899902 0.193237 -17 20 13 0.542969 0.900879 0.251953 -17 20 14 0.535645 0.901855 0.342529 -17 20 15 0.523438 0.902344 0.433105 -17 20 16 0.503906 0.902344 0.527344 -17 20 17 0.474121 0.899902 0.622559 -17 20 18 0.429443 0.893555 0.715332 -17 20 19 0.36377 0.881836 0.798828 -17 20 20 0.259766 0.86377 0.870605 -17 20 21 0 0.838867 0.927734 -17 20 22 0 0.804688 0.965332 -17 20 23 0 0.76709 0.986816 -17 20 24 0 0.730957 0.999512 -17 20 25 0 0.694336 1 -17 20 26 0 0.658203 1 -17 20 27 0 0.624023 1 -17 20 28 0 0.592285 1 -17 20 29 0 0.5625 1 -17 20 30 0 0.535645 1 -17 20 31 0 0.510742 1 -17 21 0 0.438721 0.95166 0.18396 -17 21 1 0.438721 0.95166 0.18396 -17 21 2 0.438721 0.95166 0.18396 -17 21 3 0.438721 0.95166 0.18396 -17 21 4 0.438721 0.95166 0.18396 -17 21 5 0.438721 0.95166 0.18396 -17 21 6 0.438721 0.95166 0.18396 -17 21 7 0.438721 0.95166 0.18396 -17 21 8 0.438721 0.95166 0.18396 -17 21 9 0.438721 0.95166 0.184082 -17 21 10 0.438965 0.95166 0.184082 -17 21 11 0.439209 0.95166 0.184082 -17 21 12 0.439453 0.952148 0.184204 -17 21 13 0.438232 0.952637 0.213623 -17 21 14 0.428955 0.954102 0.313721 -17 21 15 0.413574 0.956055 0.407227 -17 21 16 0.388428 0.958008 0.502441 -17 21 17 0.347412 0.95752 0.598633 -17 21 18 0.277344 0.953613 0.691895 -17 21 19 0.092041 0.943848 0.777344 -17 21 20 0 0.928223 0.852051 -17 21 21 0 0.907227 0.915039 -17 21 22 0 0.878418 0.962891 -17 21 23 0 0.84375 0.992676 -17 21 24 0 0.807129 1 -17 21 25 0 0.768555 1 -17 21 26 0 0.729004 1 -17 21 27 0 0.689941 1 -17 21 28 0 0.65332 1 -17 21 29 0 0.618652 1 -17 21 30 0 0.586914 1 -17 21 31 0 0.557617 1 -17 22 0 0.275146 0.995117 0.174805 -17 22 1 0.275146 0.995117 0.174805 -17 22 2 0.275146 0.995117 0.174805 -17 22 3 0.275146 0.995605 0.174805 -17 22 4 0.275146 0.995605 0.174805 -17 22 5 0.275146 0.995605 0.174805 -17 22 6 0.275146 0.995605 0.174805 -17 22 7 0.275146 0.995605 0.174805 -17 22 8 0.275391 0.995605 0.174805 -17 22 9 0.275391 0.995605 0.174805 -17 22 10 0.275635 0.995605 0.174805 -17 22 11 0.276123 0.995605 0.174927 -17 22 12 0.2771 0.995605 0.174927 -17 22 13 0.27832 0.996094 0.175049 -17 22 14 0.260742 0.998047 0.281982 -17 22 15 0.226685 1 0.379639 -17 22 16 0.149414 1 0.476074 -17 22 17 0 1 0.572266 -17 22 18 0 1 0.666016 -17 22 19 0 0.996582 0.75293 -17 22 20 0 0.983398 0.829102 -17 22 21 0 0.964844 0.895508 -17 22 22 0 0.940918 0.950195 -17 22 23 0 0.912109 0.989746 -17 22 24 0 0.878418 1 -17 22 25 0 0.839844 1 -17 22 26 0 0.79834 1 -17 22 27 0 0.756348 1 -17 22 28 0 0.715332 1 -17 22 29 0 0.67627 1 -17 22 30 0 0.640137 1 -17 22 31 0 0.605957 1 -17 23 0 0 1 0.165771 -17 23 1 0 1 0.165771 -17 23 2 0 1 0.165771 -17 23 3 0 1 0.165771 -17 23 4 0 1 0.165771 -17 23 5 0 1 0.165771 -17 23 6 0 1 0.165771 -17 23 7 0 1 0.165771 -17 23 8 0 1 0.165771 -17 23 9 0 1 0.165771 -17 23 10 0 1 0.165771 -17 23 11 0 1 0.165771 -17 23 12 0 1 0.165894 -17 23 13 0 1 0.166016 -17 23 14 0 1 0.248169 -17 23 15 0 1 0.351562 -17 23 16 0 1 0.449219 -17 23 17 0 1 0.54541 -17 23 18 0 1 0.63916 -17 23 19 0 1 0.726562 -17 23 20 0 1 0.804688 -17 23 21 0 1 0.873047 -17 23 22 0 0.991211 0.930664 -17 23 23 0 0.966797 0.976562 -17 23 24 0 0.937988 1 -17 23 25 0 0.902832 1 -17 23 26 0 0.862305 1 -17 23 27 0 0.818848 1 -17 23 28 0 0.775391 1 -17 23 29 0 0.732422 1 -17 23 30 0 0.691895 1 -17 23 31 0 0.653809 1 -17 24 0 0 1 0.15686 -17 24 1 0 1 0.15686 -17 24 2 0 1 0.15686 -17 24 3 0 1 0.15686 -17 24 4 0 1 0.15686 -17 24 5 0 1 0.15686 -17 24 6 0 1 0.15686 -17 24 7 0 1 0.15686 -17 24 8 0 1 0.15686 -17 24 9 0 1 0.156982 -17 24 10 0 1 0.156982 -17 24 11 0 1 0.156982 -17 24 12 0 1 0.157104 -17 24 13 0 1 0.157227 -17 24 14 0 1 0.210449 -17 24 15 0 1 0.323242 -17 24 16 0 1 0.422607 -17 24 17 0 1 0.518555 -17 24 18 0 1 0.611816 -17 24 19 0 1 0.699219 -17 24 20 0 1 0.77832 -17 24 21 0 1 0.848633 -17 24 22 0 1 0.908691 -17 24 23 0 1 0.958008 -17 24 24 0 0.986816 0.99707 -17 24 25 0 0.956055 1 -17 24 26 0 0.918457 1 -17 24 27 0 0.875977 1 -17 24 28 0 0.831055 1 -17 24 29 0 0.786133 1 -17 24 30 0 0.742188 1 -17 24 31 0 0.700684 1 -17 25 0 0 1 0.147461 -17 25 1 0 1 0.147461 -17 25 2 0 1 0.147461 -17 25 3 0 1 0.147461 -17 25 4 0 1 0.147461 -17 25 5 0 1 0.147461 -17 25 6 0 1 0.147461 -17 25 7 0 1 0.147461 -17 25 8 0 1 0.147461 -17 25 9 0 1 0.147461 -17 25 10 0 1 0.147461 -17 25 11 0 1 0.147583 -17 25 12 0 1 0.147583 -17 25 13 0 1 0.147705 -17 25 14 0 1 0.159546 -17 25 15 0 1 0.29126 -17 25 16 0 1 0.393555 -17 25 17 0 1 0.489502 -17 25 18 0 1 0.582031 -17 25 19 0 1 0.668945 -17 25 20 0 1 0.748535 -17 25 21 0 1 0.820312 -17 25 22 0 1 0.882812 -17 25 23 0 1 0.93457 -17 25 24 0 1 0.977539 -17 25 25 0 1 1 -17 25 26 0 0.971191 1 -17 25 27 0 0.931152 1 -17 25 28 0 0.887207 1 -17 25 29 0 0.84082 1 -17 25 30 0 0.794922 1 -17 25 31 0 0.75 1 -17 26 0 0 1 0.137329 -17 26 1 0 1 0.137329 -17 26 2 0 1 0.137329 -17 26 3 0 1 0.137329 -17 26 4 0 1 0.137329 -17 26 5 0 1 0.137329 -17 26 6 0 1 0.137329 -17 26 7 0 1 0.137329 -17 26 8 0 1 0.137329 -17 26 9 0 1 0.137329 -17 26 10 0 1 0.137451 -17 26 11 0 1 0.137451 -17 26 12 0 1 0.137573 -17 26 13 0 1 0.137695 -17 26 14 0 1 0.137939 -17 26 15 0 1 0.25415 -17 26 16 0 1 0.361816 -17 26 17 0 1 0.458252 -17 26 18 0 1 0.549805 -17 26 19 0 1 0.63623 -17 26 20 0 1 0.715332 -17 26 21 0 1 0.788086 -17 26 22 0 1 0.852539 -17 26 23 0 1 0.906738 -17 26 24 0 1 0.952637 -17 26 25 0 1 0.994141 -17 26 26 0 1 1 -17 26 27 0 0.983398 1 -17 26 28 0 0.941406 1 -17 26 29 0 0.895508 1 -17 26 30 0 0.848633 1 -17 26 31 0 0.801758 1 -17 27 0 0 1 0.126587 -17 27 1 0 1 0.126587 -17 27 2 0 1 0.126587 -17 27 3 0 1 0.126587 -17 27 4 0 1 0.126587 -17 27 5 0 1 0.126587 -17 27 6 0 1 0.126587 -17 27 7 0 1 0.126587 -17 27 8 0 1 0.126709 -17 27 9 0 1 0.126709 -17 27 10 0 1 0.126709 -17 27 11 0 1 0.126709 -17 27 12 0 1 0.126831 -17 27 13 0 1 0.126953 -17 27 14 0 1 0.127197 -17 27 15 0 1 0.209595 -17 27 16 0 1 0.327393 -17 27 17 0 1 0.425049 -17 27 18 0 1 0.515625 -17 27 19 0 1 0.601074 -17 27 20 0 1 0.679688 -17 27 21 0 1 0.752441 -17 27 22 0 1 0.817871 -17 27 23 0 1 0.874512 -17 27 24 0 1 0.922363 -17 27 25 0 1 0.967285 -17 27 26 0 1 1 -17 27 27 0 1 1 -17 27 28 0 0.992188 1 -17 27 29 0 0.948242 1 -17 27 30 0 0.901367 1 -17 27 31 0 0.853516 1 -17 28 0 0 1 0.115173 -17 28 1 0 1 0.115173 -17 28 2 0 1 0.115173 -17 28 3 0 1 0.115173 -17 28 4 0 1 0.115173 -17 28 5 0 1 0.115173 -17 28 6 0 1 0.115173 -17 28 7 0 1 0.115173 -17 28 8 0 1 0.115173 -17 28 9 0 1 0.115173 -17 28 10 0 1 0.115234 -17 28 11 0 1 0.115295 -17 28 12 0 1 0.115417 -17 28 13 0 1 0.11554 -17 28 14 0 1 0.115784 -17 28 15 0 1 0.147705 -17 28 16 0 1 0.289307 -17 28 17 0 1 0.389893 -17 28 18 0 1 0.47998 -17 28 19 0 1 0.563965 -17 28 20 0 1 0.641602 -17 28 21 0 1 0.713867 -17 28 22 0 1 0.779785 -17 28 23 0 1 0.837402 -17 28 24 0 1 0.887695 -17 28 25 0 1 0.935059 -17 28 26 0 1 0.979004 -17 28 27 0 1 1 -17 28 28 0 1 1 -17 28 29 0 0.997559 1 -17 28 30 0 0.952637 1 -17 28 31 0 0.905273 1 -17 29 0 0 1 0.102722 -17 29 1 0 1 0.102722 -17 29 2 0 1 0.102722 -17 29 3 0 1 0.102722 -17 29 4 0 1 0.102722 -17 29 5 0 1 0.102722 -17 29 6 0 1 0.102722 -17 29 7 0 1 0.102722 -17 29 8 0 1 0.102722 -17 29 9 0 1 0.102722 -17 29 10 0 1 0.102783 -17 29 11 0 1 0.102844 -17 29 12 0 1 0.102966 -17 29 13 0 1 0.103088 -17 29 14 0 1 0.103394 -17 29 15 0 1 0.10376 -17 29 16 0 1 0.24585 -17 29 17 0 1 0.352051 -17 29 18 0 1 0.442383 -17 29 19 0 1 0.524902 -17 29 20 0 1 0.601074 -17 29 21 0 1 0.672363 -17 29 22 0 1 0.738281 -17 29 23 0 1 0.796387 -17 29 24 0 1 0.847656 -17 29 25 0 1 0.897461 -17 29 26 0 1 0.944336 -17 29 27 0 1 0.986816 -17 29 28 0 1 1 -17 29 29 0 1 1 -17 29 30 0 1 1 -17 29 31 0 0.956543 1 -17 30 0 0 1 0.0889282 -17 30 1 0 1 0.0889282 -17 30 2 0 1 0.0889282 -17 30 3 0 1 0.0889282 -17 30 4 0 1 0.0889282 -17 30 5 0 1 0.0889282 -17 30 6 0 1 0.0889282 -17 30 7 0 1 0.0889282 -17 30 8 0 1 0.0889282 -17 30 9 0 1 0.0889893 -17 30 10 0 1 0.0889893 -17 30 11 0 1 0.0890503 -17 30 12 0 1 0.0891724 -17 30 13 0 1 0.0893555 -17 30 14 0 1 0.0896606 -17 30 15 0 1 0.0900879 -17 30 16 0 1 0.192627 -17 30 17 0 1 0.311523 -17 30 18 0 1 0.403076 -17 30 19 0 1 0.484619 -17 30 20 0 1 0.559082 -17 30 21 0 1 0.628906 -17 30 22 0 1 0.693848 -17 30 23 0 1 0.751953 -17 30 24 0 1 0.803711 -17 30 25 0 1 0.854492 -17 30 26 0 1 0.903809 -17 30 27 0 1 0.949707 -17 30 28 0 1 0.991699 -17 30 29 0 1 1 -17 30 30 0 1 1 -17 30 31 0 1 1 -17 31 0 0 1 0.0730591 -17 31 1 0 1 0.0730591 -17 31 2 0 1 0.0730591 -17 31 3 0 1 0.0730591 -17 31 4 0 1 0.0730591 -17 31 5 0 1 0.0730591 -17 31 6 0 1 0.0730591 -17 31 7 0 1 0.0730591 -17 31 8 0 1 0.0730591 -17 31 9 0 1 0.0731201 -17 31 10 0 1 0.0731201 -17 31 11 0 1 0.0732422 -17 31 12 0 1 0.0733643 -17 31 13 0 1 0.0735474 -17 31 14 0 1 0.0739136 -17 31 15 0 1 0.0744629 -17 31 16 0 1 0.109558 -17 31 17 0 1 0.26709 -17 31 18 0 1 0.362305 -17 31 19 0 1 0.443115 -17 31 20 0 1 0.515625 -17 31 21 0 1 0.583984 -17 31 22 0 1 0.647461 -17 31 23 0 1 0.70459 -17 31 24 0 1 0.756348 -17 31 25 0 1 0.807617 -17 31 26 0 1 0.858887 -17 31 27 0 1 0.908203 -17 31 28 0 1 0.954102 -17 31 29 0 1 0.996094 -17 31 30 0 1 1 -17 31 31 0 1 1 -18 0 0 0.821289 0 0.0467834 -18 0 1 0.821289 0 0.0467834 -18 0 2 0.821289 0 0.0467529 -18 0 3 0.821289 0 0.0467529 -18 0 4 0.821289 0 0.0467529 -18 0 5 0.821289 0 0.0466919 -18 0 6 0.821289 0 0.0466309 -18 0 7 0.821289 0 0.0465088 -18 0 8 0.821289 0 0.0462646 -18 0 9 0.821289 0 0.0458069 -18 0 10 0.821777 0 0.0449524 -18 0 11 0.822266 0 0.0436707 -18 0 12 0.82666 0 0.0569153 -18 0 13 0.834473 0 0.233887 -18 0 14 0.846191 0 0.343018 -18 0 15 0.85791 0 0.45166 -18 0 16 0.873047 0.180298 0.569824 -18 0 17 0.873047 0.268311 0.677734 -18 0 18 0.843262 0.284424 0.76416 -18 0 19 0.80127 0.291748 0.839355 -18 0 20 0.751465 0.297852 0.900879 -18 0 21 0.685059 0.297852 0.9375 -18 0 22 0.610352 0.293457 0.953125 -18 0 23 0.539062 0.288818 0.960449 -18 0 24 0.470459 0.284912 0.964355 -18 0 25 0.395508 0.28125 0.967773 -18 0 26 0.305176 0.27832 0.971191 -18 0 27 0.153931 0.276123 0.976074 -18 0 28 0 0.274902 0.982422 -18 0 29 0 0.274414 0.990234 -18 0 30 0 0.274658 0.999023 -18 0 31 0 0.275391 1 -18 1 0 0.821289 0 0.0467529 -18 1 1 0.821289 0 0.0467224 -18 1 2 0.821289 0 0.0467224 -18 1 3 0.821289 0 0.0467224 -18 1 4 0.821289 0 0.0466919 -18 1 5 0.821289 0 0.0466614 -18 1 6 0.821289 0 0.0466003 -18 1 7 0.821289 0 0.0464783 -18 1 8 0.821289 0 0.0462341 -18 1 9 0.821289 0 0.0457764 -18 1 10 0.821777 0 0.0448914 -18 1 11 0.822266 0 0.0436401 -18 1 12 0.82666 0 0.0569153 -18 1 13 0.834473 0 0.233887 -18 1 14 0.846191 0 0.343018 -18 1 15 0.85791 0 0.45166 -18 1 16 0.873047 0.18042 0.569824 -18 1 17 0.873047 0.268311 0.677734 -18 1 18 0.843262 0.284424 0.76416 -18 1 19 0.80127 0.291992 0.839355 -18 1 20 0.751465 0.297852 0.900879 -18 1 21 0.685059 0.297852 0.9375 -18 1 22 0.610352 0.293457 0.953125 -18 1 23 0.539062 0.288818 0.960449 -18 1 24 0.470459 0.284912 0.964355 -18 1 25 0.395508 0.28125 0.967773 -18 1 26 0.305176 0.27832 0.97168 -18 1 27 0.153931 0.276123 0.976074 -18 1 28 0 0.274902 0.982422 -18 1 29 0 0.274414 0.990234 -18 1 30 0 0.274658 0.999023 -18 1 31 0 0.275391 1 -18 2 0 0.821289 0 0.0466919 -18 2 1 0.821289 0 0.0466614 -18 2 2 0.821289 0 0.0466614 -18 2 3 0.821289 0 0.0466614 -18 2 4 0.821289 0 0.0466309 -18 2 5 0.821289 0 0.0466003 -18 2 6 0.821289 0 0.0465393 -18 2 7 0.821289 0 0.0464172 -18 2 8 0.821289 0 0.0461731 -18 2 9 0.821289 0 0.0457153 -18 2 10 0.821777 0 0.0448303 -18 2 11 0.822266 0 0.0435791 -18 2 12 0.82666 0 0.0569458 -18 2 13 0.834473 0 0.233887 -18 2 14 0.846191 0 0.343018 -18 2 15 0.85791 0 0.45166 -18 2 16 0.873047 0.180542 0.569824 -18 2 17 0.873047 0.268555 0.677734 -18 2 18 0.843262 0.284424 0.76416 -18 2 19 0.80127 0.291992 0.839355 -18 2 20 0.751465 0.297852 0.900879 -18 2 21 0.685059 0.297852 0.9375 -18 2 22 0.610352 0.293701 0.953125 -18 2 23 0.539062 0.289062 0.960449 -18 2 24 0.470459 0.284912 0.964355 -18 2 25 0.395508 0.28125 0.967773 -18 2 26 0.305176 0.27832 0.97168 -18 2 27 0.153931 0.276123 0.976074 -18 2 28 0 0.274902 0.982422 -18 2 29 0 0.274414 0.990234 -18 2 30 0 0.274658 0.999023 -18 2 31 0 0.275391 1 -18 3 0 0.821289 0 0.0465698 -18 3 1 0.821289 0 0.0465698 -18 3 2 0.821289 0 0.0465698 -18 3 3 0.821289 0 0.0465393 -18 3 4 0.821289 0 0.0465393 -18 3 5 0.821289 0 0.0465088 -18 3 6 0.821289 0 0.0464478 -18 3 7 0.821289 0 0.0463257 -18 3 8 0.821289 0 0.0460815 -18 3 9 0.821289 0 0.0455933 -18 3 10 0.821777 0 0.0447083 -18 3 11 0.822754 0 0.043457 -18 3 12 0.82666 0 0.0569458 -18 3 13 0.834473 0 0.233887 -18 3 14 0.846191 0 0.343018 -18 3 15 0.85791 0 0.45166 -18 3 16 0.873047 0.180786 0.569824 -18 3 17 0.873047 0.268555 0.677734 -18 3 18 0.843262 0.284668 0.76416 -18 3 19 0.80127 0.291992 0.839355 -18 3 20 0.751465 0.297852 0.900879 -18 3 21 0.685059 0.297852 0.9375 -18 3 22 0.610352 0.293701 0.953125 -18 3 23 0.539062 0.289062 0.960449 -18 3 24 0.470459 0.284912 0.964355 -18 3 25 0.395508 0.281494 0.967773 -18 3 26 0.305176 0.27832 0.97168 -18 3 27 0.153931 0.276367 0.976074 -18 3 28 0 0.274902 0.982422 -18 3 29 0 0.274658 0.990234 -18 3 30 0 0.274658 0.999023 -18 3 31 0 0.275635 1 -18 4 0 0.821289 0 0.0463562 -18 4 1 0.821289 0 0.0463562 -18 4 2 0.821289 0 0.0463562 -18 4 3 0.821289 0 0.0463257 -18 4 4 0.821289 0 0.0463257 -18 4 5 0.821289 0 0.0462952 -18 4 6 0.821289 0 0.0462341 -18 4 7 0.821289 0 0.0461121 -18 4 8 0.821289 0 0.0458679 -18 4 9 0.821289 0 0.0453796 -18 4 10 0.821777 0 0.0444946 -18 4 11 0.822754 0 0.0432129 -18 4 12 0.82666 0 0.0569458 -18 4 13 0.834473 0 0.233887 -18 4 14 0.846191 0 0.343018 -18 4 15 0.85791 0 0.45166 -18 4 16 0.873047 0.181274 0.569824 -18 4 17 0.873047 0.269043 0.677734 -18 4 18 0.843262 0.284912 0.76416 -18 4 19 0.80127 0.292236 0.839355 -18 4 20 0.751465 0.298096 0.900879 -18 4 21 0.685059 0.298096 0.9375 -18 4 22 0.610352 0.293701 0.953125 -18 4 23 0.539062 0.289062 0.960449 -18 4 24 0.470459 0.285156 0.964355 -18 4 25 0.395508 0.281494 0.967773 -18 4 26 0.305176 0.278564 0.97168 -18 4 27 0.153809 0.276367 0.976074 -18 4 28 0 0.275146 0.982422 -18 4 29 0 0.274658 0.990234 -18 4 30 0 0.274902 0.999023 -18 4 31 0 0.275635 1 -18 5 0 0.821289 0 0.0459595 -18 5 1 0.821289 0 0.045929 -18 5 2 0.821289 0 0.045929 -18 5 3 0.821289 0 0.045929 -18 5 4 0.821289 0 0.0458984 -18 5 5 0.821289 0 0.0458679 -18 5 6 0.821289 0 0.0458069 -18 5 7 0.821289 0 0.0456848 -18 5 8 0.821289 0 0.0454407 -18 5 9 0.821777 0 0.0449524 -18 5 10 0.821777 0 0.0440674 -18 5 11 0.822754 0 0.0427551 -18 5 12 0.82666 0 0.0569763 -18 5 13 0.834473 0 0.233887 -18 5 14 0.846191 0 0.343018 -18 5 15 0.85791 0 0.45166 -18 5 16 0.873047 0.182251 0.569824 -18 5 17 0.873047 0.269531 0.677734 -18 5 18 0.843262 0.285156 0.76416 -18 5 19 0.80127 0.292725 0.839355 -18 5 20 0.751465 0.298584 0.900879 -18 5 21 0.685059 0.29834 0.9375 -18 5 22 0.610352 0.294189 0.953125 -18 5 23 0.538574 0.289307 0.960449 -18 5 24 0.470459 0.2854 0.964355 -18 5 25 0.395508 0.281738 0.967773 -18 5 26 0.305176 0.278809 0.97168 -18 5 27 0.153687 0.276367 0.976074 -18 5 28 0 0.275146 0.982422 -18 5 29 0 0.274658 0.990234 -18 5 30 0 0.274902 0.999023 -18 5 31 0 0.275635 1 -18 6 0 0.821289 0 0.0451355 -18 6 1 0.821289 0 0.0451355 -18 6 2 0.821289 0 0.0451355 -18 6 3 0.821289 0 0.0451355 -18 6 4 0.821289 0 0.045105 -18 6 5 0.821289 0 0.0450745 -18 6 6 0.821289 0 0.0450134 -18 6 7 0.821777 0 0.0448608 -18 6 8 0.821777 0 0.0446167 -18 6 9 0.821777 0 0.0441284 -18 6 10 0.821777 0 0.0431824 -18 6 11 0.822754 0 0.0418396 -18 6 12 0.827148 0 0.0570068 -18 6 13 0.834473 0 0.233887 -18 6 14 0.846191 0 0.343018 -18 6 15 0.85791 0 0.451416 -18 6 16 0.872559 0.18396 0.569824 -18 6 17 0.873047 0.270508 0.677734 -18 6 18 0.843262 0.286133 0.76416 -18 6 19 0.80127 0.293457 0.839355 -18 6 20 0.751465 0.299316 0.900879 -18 6 21 0.685059 0.299072 0.9375 -18 6 22 0.610352 0.294678 0.953125 -18 6 23 0.538574 0.289795 0.960449 -18 6 24 0.470215 0.285645 0.964355 -18 6 25 0.395264 0.281982 0.967773 -18 6 26 0.304932 0.279053 0.97168 -18 6 27 0.153442 0.276855 0.976074 -18 6 28 0 0.275391 0.982422 -18 6 29 0 0.274902 0.990234 -18 6 30 0 0.275146 0.999023 -18 6 31 0 0.275879 1 -18 7 0 0.821777 0 0.0435181 -18 7 1 0.821777 0 0.0435181 -18 7 2 0.821777 0 0.0434875 -18 7 3 0.821777 0 0.0434875 -18 7 4 0.821777 0 0.043457 -18 7 5 0.821777 0 0.0434265 -18 7 6 0.821777 0 0.0433655 -18 7 7 0.821777 0 0.0432129 -18 7 8 0.821777 0 0.0429382 -18 7 9 0.821777 0 0.0424194 -18 7 10 0.822266 0 0.0414124 -18 7 11 0.822754 0 0.039978 -18 7 12 0.827148 0 0.0570984 -18 7 13 0.834961 0 0.233765 -18 7 14 0.846191 0 0.343018 -18 7 15 0.85791 0 0.451416 -18 7 16 0.872559 0.187256 0.569336 -18 7 17 0.872559 0.272461 0.677734 -18 7 18 0.843262 0.287842 0.76416 -18 7 19 0.80127 0.295166 0.839355 -18 7 20 0.751465 0.300537 0.900879 -18 7 21 0.685059 0.300293 0.9375 -18 7 22 0.610352 0.295654 0.953125 -18 7 23 0.538574 0.290771 0.960449 -18 7 24 0.470215 0.286621 0.964355 -18 7 25 0.395264 0.282715 0.967773 -18 7 26 0.304688 0.279541 0.97168 -18 7 27 0.152954 0.277344 0.976074 -18 7 28 0 0.275879 0.982422 -18 7 29 0 0.275391 0.990234 -18 7 30 0 0.275391 0.999023 -18 7 31 0 0.276123 1 -18 8 0 0.822266 0 0.039978 -18 8 1 0.822266 0 0.039978 -18 8 2 0.822266 0 0.039978 -18 8 3 0.822266 0 0.0399475 -18 8 4 0.822266 0 0.0399475 -18 8 5 0.822266 0 0.0398865 -18 8 6 0.822266 0 0.0398254 -18 8 7 0.822266 0 0.0396423 -18 8 8 0.822266 0 0.0393372 -18 8 9 0.822266 0 0.0387268 -18 8 10 0.822754 0 0.0375671 -18 8 11 0.823242 0 0.0358276 -18 8 12 0.827637 0 0.057373 -18 8 13 0.834961 0 0.233643 -18 8 14 0.846191 0 0.343018 -18 8 15 0.85791 0 0.451172 -18 8 16 0.872559 0.193604 0.569336 -18 8 17 0.872559 0.276123 0.677734 -18 8 18 0.843262 0.29126 0.76416 -18 8 19 0.80127 0.298096 0.839355 -18 8 20 0.750977 0.303467 0.900879 -18 8 21 0.68457 0.302734 0.9375 -18 8 22 0.609863 0.297852 0.953125 -18 8 23 0.538574 0.29248 0.960449 -18 8 24 0.469971 0.288086 0.964355 -18 8 25 0.39502 0.28418 0.967773 -18 8 26 0.304443 0.280762 0.97168 -18 8 27 0.151978 0.27832 0.976074 -18 8 28 0 0.276855 0.982422 -18 8 29 0 0.276123 0.990234 -18 8 30 0 0.276123 0.999512 -18 8 31 0 0.276611 1 -18 9 0 0.822754 0 0.0312195 -18 9 1 0.822754 0 0.0312042 -18 9 2 0.822754 0 0.0312042 -18 9 3 0.822754 0 0.031189 -18 9 4 0.822754 0 0.0311584 -18 9 5 0.822754 0 0.0310822 -18 9 6 0.822754 0 0.0309601 -18 9 7 0.823242 0 0.0307312 -18 9 8 0.823242 0 0.0302429 -18 9 9 0.823242 0 0.0292816 -18 9 10 0.823242 0 0.0274048 -18 9 11 0.824219 0 0.024353 -18 9 12 0.828125 0 0.058136 -18 9 13 0.835449 0 0.233521 -18 9 14 0.84668 0 0.343018 -18 9 15 0.857422 0 0.450928 -18 9 16 0.87207 0.204712 0.569336 -18 9 17 0.87207 0.283203 0.677734 -18 9 18 0.842773 0.297607 0.76416 -18 9 19 0.800781 0.303711 0.839355 -18 9 20 0.750977 0.30835 0.900879 -18 9 21 0.68457 0.307129 0.9375 -18 9 22 0.609375 0.301514 0.953125 -18 9 23 0.538086 0.295898 0.960449 -18 9 24 0.469482 0.291016 0.964355 -18 9 25 0.394531 0.286621 0.967773 -18 9 26 0.303711 0.283203 0.97168 -18 9 27 0.150024 0.280273 0.976562 -18 9 28 0 0.278564 0.982422 -18 9 29 0 0.277588 0.990234 -18 9 30 0 0.277344 0.999512 -18 9 31 0 0.277832 1 -18 10 0 0.824219 0.0863037 0 -18 10 1 0.824219 0.0863647 0 -18 10 2 0.824219 0.0863647 0 -18 10 3 0.824219 0.0864868 0 -18 10 4 0.824219 0.0866089 0 -18 10 5 0.824219 0.086853 0 -18 10 6 0.824707 0.0874023 0 -18 10 7 0.824707 0.0883789 0 -18 10 8 0.824707 0.09021 0 -18 10 9 0.824707 0.0936279 0 -18 10 10 0.824707 0.0993652 0 -18 10 11 0.825684 0.10675 0 -18 10 12 0.829102 0.109558 0.0603943 -18 10 13 0.835938 0.0935059 0.233276 -18 10 14 0.847168 0.0948486 0.343262 -18 10 15 0.856934 0.119751 0.450439 -18 10 16 0.871094 0.2229 0.568848 -18 10 17 0.871094 0.295166 0.677246 -18 10 18 0.841797 0.308594 0.76416 -18 10 19 0.799805 0.313721 0.839355 -18 10 20 0.75 0.317383 0.900879 -18 10 21 0.683594 0.314941 0.937988 -18 10 22 0.608887 0.30835 0.953125 -18 10 23 0.537109 0.302002 0.960449 -18 10 24 0.46875 0.296387 0.964844 -18 10 25 0.393555 0.29126 0.968262 -18 10 26 0.30249 0.287109 0.97168 -18 10 27 0.146606 0.283936 0.976562 -18 10 28 0 0.281738 0.98291 -18 10 29 0 0.280273 0.990723 -18 10 30 0 0.279785 0.999512 -18 10 31 0 0.280029 1 -18 11 0 0.827148 0.166382 0 -18 11 1 0.827148 0.166382 0 -18 11 2 0.827148 0.166382 0 -18 11 3 0.827148 0.166382 0 -18 11 4 0.827148 0.166504 0 -18 11 5 0.827148 0.166504 0 -18 11 6 0.827148 0.166748 0 -18 11 7 0.827148 0.167114 0 -18 11 8 0.827148 0.167847 0 -18 11 9 0.827148 0.169067 0 -18 11 10 0.827637 0.171509 0 -18 11 11 0.828125 0.174805 0 -18 11 12 0.831055 0.175659 0.0664673 -18 11 13 0.836914 0.168701 0.233398 -18 11 14 0.847168 0.168823 0.342773 -18 11 15 0.856445 0.179077 0.449707 -18 11 16 0.869141 0.25 0.567871 -18 11 17 0.870117 0.314697 0.677246 -18 11 18 0.84082 0.326416 0.76416 -18 11 19 0.798828 0.330078 0.839355 -18 11 20 0.749023 0.332031 0.901367 -18 11 21 0.682617 0.328125 0.937988 -18 11 22 0.607422 0.319824 0.953125 -18 11 23 0.536133 0.312012 0.960449 -18 11 24 0.467285 0.305176 0.964844 -18 11 25 0.391846 0.299072 0.968262 -18 11 26 0.300293 0.293945 0.972168 -18 11 27 0.140015 0.290039 0.977051 -18 11 28 0 0.287109 0.983398 -18 11 29 0 0.285156 0.991211 -18 11 30 0 0.283936 1 -18 11 31 0 0.283447 1 -18 12 0 0.831543 0.234375 0 -18 12 1 0.831543 0.234375 0 -18 12 2 0.831543 0.234375 0 -18 12 3 0.831543 0.234375 0 -18 12 4 0.831543 0.234375 0 -18 12 5 0.831543 0.234497 0 -18 12 6 0.831543 0.234619 0 -18 12 7 0.831543 0.234741 0 -18 12 8 0.831543 0.235229 0 -18 12 9 0.831543 0.235962 0 -18 12 10 0.831543 0.237427 0 -18 12 11 0.832031 0.239624 0 -18 12 12 0.834473 0.239624 0.0802612 -18 12 13 0.839355 0.235352 0.234375 -18 12 14 0.847168 0.233765 0.341553 -18 12 15 0.85498 0.239746 0.448486 -18 12 16 0.866211 0.287598 0.565918 -18 12 17 0.867188 0.34375 0.676758 -18 12 18 0.838379 0.353516 0.76416 -18 12 19 0.796387 0.355225 0.839355 -18 12 20 0.746582 0.355225 0.901367 -18 12 21 0.680664 0.348633 0.938477 -18 12 22 0.605469 0.337891 0.953613 -18 12 23 0.533691 0.327881 0.960938 -18 12 24 0.464844 0.319336 0.965332 -18 12 25 0.388916 0.311768 0.96875 -18 12 26 0.296387 0.30542 0.972656 -18 12 27 0.127441 0.299805 0.977539 -18 12 28 0 0.295898 0.983887 -18 12 29 0 0.292725 0.992188 -18 12 30 0 0.290771 1 -18 12 31 0 0.289551 1 -18 13 0 0.838379 0.306396 0 -18 13 1 0.838379 0.306396 0 -18 13 2 0.838379 0.306396 0 -18 13 3 0.838379 0.306396 0 -18 13 4 0.838379 0.306396 0 -18 13 5 0.838379 0.306396 0 -18 13 6 0.838379 0.306396 0 -18 13 7 0.838379 0.306641 0 -18 13 8 0.838379 0.306885 0 -18 13 9 0.838379 0.307373 0 -18 13 10 0.838379 0.30835 0 -18 13 11 0.838867 0.310059 0 -18 13 12 0.840332 0.30957 0.10553 -18 13 13 0.842773 0.306641 0.23877 -18 13 14 0.847168 0.303955 0.341064 -18 13 15 0.853516 0.307129 0.447266 -18 13 16 0.86084 0.336426 0.562988 -18 13 17 0.863281 0.384277 0.675293 -18 13 18 0.834961 0.39209 0.763672 -18 13 19 0.792969 0.391113 0.838867 -18 13 20 0.743164 0.388428 0.901367 -18 13 21 0.677246 0.378906 0.938965 -18 13 22 0.601562 0.364746 0.954102 -18 13 23 0.529785 0.351807 0.961426 -18 13 24 0.460693 0.341064 0.96582 -18 13 25 0.384277 0.331055 0.969727 -18 13 26 0.289795 0.32251 0.974121 -18 13 27 0.100891 0.315186 0.979004 -18 13 28 0 0.309326 0.985352 -18 13 29 0 0.304932 0.993164 -18 13 30 0 0.301514 1 -18 13 31 0 0.298828 1 -18 14 0 0.848145 0.386963 0 -18 14 1 0.848145 0.386963 0 -18 14 2 0.848145 0.386963 0 -18 14 3 0.848145 0.386963 0 -18 14 4 0.848145 0.386963 0 -18 14 5 0.848145 0.386963 0 -18 14 6 0.848145 0.387207 0 -18 14 7 0.848145 0.387207 0 -18 14 8 0.848145 0.387451 0 -18 14 9 0.848633 0.387695 0 -18 14 10 0.848633 0.388428 0 -18 14 11 0.848633 0.389648 0 -18 14 12 0.849121 0.388916 0.143555 -18 14 13 0.849121 0.386963 0.250732 -18 14 14 0.849121 0.384033 0.344727 -18 14 15 0.850586 0.383789 0.446289 -18 14 16 0.852539 0.396973 0.558105 -18 14 17 0.855469 0.436768 0.67334 -18 14 18 0.828613 0.443115 0.763184 -18 14 19 0.786621 0.439453 0.838867 -18 14 20 0.737305 0.433594 0.901367 -18 14 21 0.671387 0.42041 0.939941 -18 14 22 0.595703 0.4021 0.955078 -18 14 23 0.523438 0.385498 0.962402 -18 14 24 0.453857 0.371582 0.967285 -18 14 25 0.376465 0.358887 0.971191 -18 14 26 0.278809 0.347412 0.975586 -18 14 27 0 0.337646 0.980957 -18 14 28 0 0.32959 0.987305 -18 14 29 0 0.322754 0.995605 -18 14 30 0 0.317383 1 -18 14 31 0 0.312988 1 -18 15 0 0.860352 0.476807 0.104919 -18 15 1 0.860352 0.476807 0.104919 -18 15 2 0.860352 0.476807 0.104919 -18 15 3 0.860352 0.476807 0.10498 -18 15 4 0.860352 0.476807 0.10498 -18 15 5 0.860352 0.476807 0.10498 -18 15 6 0.860352 0.477051 0.105042 -18 15 7 0.860352 0.477051 0.105164 -18 15 8 0.860352 0.477295 0.105408 -18 15 9 0.860352 0.477539 0.105774 -18 15 10 0.86084 0.478027 0.106567 -18 15 11 0.86084 0.47876 0.107849 -18 15 12 0.859863 0.47876 0.19104 -18 15 13 0.857422 0.477539 0.274902 -18 15 14 0.853027 0.474854 0.35791 -18 15 15 0.84668 0.470215 0.44751 -18 15 16 0.840332 0.470703 0.55127 -18 15 17 0.842773 0.499756 0.668945 -18 15 18 0.818359 0.506348 0.76123 -18 15 19 0.776855 0.499756 0.837891 -18 15 20 0.727539 0.490723 0.901367 -18 15 21 0.662109 0.473633 0.94043 -18 15 22 0.586426 0.450195 0.956055 -18 15 23 0.513672 0.429443 0.963867 -18 15 24 0.443359 0.411865 0.969238 -18 15 25 0.36377 0.395752 0.973633 -18 15 26 0.260254 0.381348 0.978516 -18 15 27 0 0.368408 0.983887 -18 15 28 0 0.357422 0.990723 -18 15 29 0 0.3479 0.999023 -18 15 30 0 0.339844 1 -18 15 31 0 0.333252 1 -18 16 0 0.870605 0.576172 0.196899 -18 16 1 0.870605 0.576172 0.196899 -18 16 2 0.870605 0.576172 0.196899 -18 16 3 0.870605 0.576172 0.196899 -18 16 4 0.870605 0.576172 0.196899 -18 16 5 0.870605 0.576172 0.197021 -18 16 6 0.870605 0.576172 0.197021 -18 16 7 0.870605 0.576172 0.197021 -18 16 8 0.870605 0.576172 0.197021 -18 16 9 0.870605 0.57666 0.197144 -18 16 10 0.871094 0.57666 0.197388 -18 16 11 0.871094 0.577637 0.197754 -18 16 12 0.870117 0.577637 0.236084 -18 16 13 0.866211 0.577148 0.306885 -18 16 14 0.859375 0.575684 0.382324 -18 16 15 0.847168 0.570801 0.462891 -18 16 16 0.827637 0.561035 0.549805 -18 16 17 0.819336 0.569824 0.658203 -18 16 18 0.802246 0.580078 0.758301 -18 16 19 0.76123 0.571289 0.835449 -18 16 20 0.711914 0.559082 0.899902 -18 16 21 0.647461 0.538086 0.940918 -18 16 22 0.571289 0.509766 0.957031 -18 16 23 0.498535 0.484375 0.96582 -18 16 24 0.426758 0.462891 0.972168 -18 16 25 0.343506 0.442871 0.977539 -18 16 26 0.227661 0.424805 0.98291 -18 16 27 0 0.408447 0.989258 -18 16 28 0 0.393799 0.996094 -18 16 29 0 0.381104 1 -18 16 30 0 0.370117 1 -18 16 31 0 0.360352 1 -18 17 0 0.868652 0.678223 0.237427 -18 17 1 0.868652 0.678223 0.237427 -18 17 2 0.868652 0.678223 0.237427 -18 17 3 0.868652 0.678223 0.237427 -18 17 4 0.868652 0.678223 0.237427 -18 17 5 0.868652 0.678223 0.237427 -18 17 6 0.868652 0.678223 0.237549 -18 17 7 0.868652 0.678223 0.237549 -18 17 8 0.868652 0.678223 0.237549 -18 17 9 0.868652 0.678223 0.237549 -18 17 10 0.868652 0.678711 0.237671 -18 17 11 0.868652 0.679199 0.237671 -18 17 12 0.868164 0.679688 0.256836 -18 17 13 0.864746 0.679688 0.325439 -18 17 14 0.858887 0.679199 0.401123 -18 17 15 0.847168 0.67627 0.482666 -18 17 16 0.826172 0.668457 0.567383 -18 17 17 0.791504 0.651855 0.647949 -18 17 18 0.777344 0.660645 0.751953 -18 17 19 0.737793 0.649902 0.831055 -18 17 20 0.688965 0.635254 0.896973 -18 17 21 0.625 0.61084 0.939941 -18 17 22 0.549316 0.577637 0.958008 -18 17 23 0.47583 0.54834 0.969238 -18 17 24 0.401367 0.522949 0.977051 -18 17 25 0.311279 0.499268 0.983887 -18 17 26 0.160767 0.477295 0.990234 -18 17 27 0 0.457031 0.99707 -18 17 28 0 0.438477 1 -18 17 29 0 0.421387 1 -18 17 30 0 0.40625 1 -18 17 31 0 0.392578 1 -18 18 0 0.840332 0.771484 0.242065 -18 18 1 0.840332 0.771484 0.242065 -18 18 2 0.840332 0.771484 0.242065 -18 18 3 0.840332 0.771484 0.242065 -18 18 4 0.840332 0.771484 0.242065 -18 18 5 0.840332 0.771484 0.242065 -18 18 6 0.840332 0.771484 0.242065 -18 18 7 0.840332 0.771484 0.242065 -18 18 8 0.840332 0.771484 0.242065 -18 18 9 0.840332 0.771484 0.242065 -18 18 10 0.840332 0.771484 0.242065 -18 18 11 0.840332 0.771973 0.242188 -18 18 12 0.840332 0.772461 0.242188 -18 18 13 0.837402 0.772949 0.315918 -18 18 14 0.83252 0.772949 0.395264 -18 18 15 0.822754 0.771484 0.480713 -18 18 16 0.806152 0.76709 0.570801 -18 18 17 0.779785 0.757812 0.660156 -18 18 18 0.742188 0.742188 0.742188 -18 18 19 0.703613 0.730469 0.822754 -18 18 20 0.655762 0.714355 0.890625 -18 18 21 0.592773 0.687012 0.936523 -18 18 22 0.518066 0.650879 0.959473 -18 18 23 0.442139 0.618164 0.973145 -18 18 24 0.362061 0.588867 0.982422 -18 18 25 0.255127 0.561035 0.990234 -18 18 26 0 0.534668 0.996582 -18 18 27 0 0.509766 1 -18 18 28 0 0.486816 1 -18 18 29 0 0.466064 1 -18 18 30 0 0.447021 1 -18 18 31 0 0.429932 1 -18 19 0 0.783203 0.843262 0.234253 -18 19 1 0.783203 0.843262 0.234253 -18 19 2 0.783203 0.843262 0.234253 -18 19 3 0.783203 0.843262 0.234253 -18 19 4 0.783203 0.843262 0.234253 -18 19 5 0.783203 0.843262 0.234253 -18 19 6 0.783203 0.843262 0.234253 -18 19 7 0.783203 0.843262 0.234253 -18 19 8 0.783203 0.843262 0.234253 -18 19 9 0.783203 0.84375 0.234253 -18 19 10 0.783203 0.84375 0.234253 -18 19 11 0.783203 0.84375 0.234253 -18 19 12 0.783203 0.844238 0.234375 -18 19 13 0.78125 0.844727 0.290527 -18 19 14 0.776367 0.844727 0.373291 -18 19 15 0.76709 0.84375 0.459961 -18 19 16 0.751465 0.839844 0.550781 -18 19 17 0.727051 0.831055 0.641113 -18 19 18 0.695312 0.819824 0.728516 -18 19 19 0.657227 0.808105 0.811035 -18 19 20 0.609863 0.791504 0.880859 -18 19 21 0.547852 0.763672 0.931152 -18 19 22 0.4729 0.727051 0.959961 -18 19 23 0.392334 0.691406 0.977539 -18 19 24 0.298828 0.658691 0.98877 -18 19 25 0.117737 0.626953 0.99707 -18 19 26 0 0.596191 1 -18 19 27 0 0.566895 1 -18 19 28 0 0.540039 1 -18 19 29 0 0.514648 1 -18 19 30 0 0.491943 1 -18 19 31 0 0.470947 1 -18 20 0 0.713379 0.900879 0.224365 -18 20 1 0.713379 0.900879 0.224365 -18 20 2 0.713379 0.900879 0.224365 -18 20 3 0.713379 0.900879 0.224365 -18 20 4 0.713379 0.900879 0.224365 -18 20 5 0.713379 0.900879 0.224365 -18 20 6 0.713379 0.900879 0.224365 -18 20 7 0.713379 0.900879 0.224365 -18 20 8 0.713379 0.900879 0.224365 -18 20 9 0.713379 0.900879 0.224365 -18 20 10 0.713379 0.900879 0.224365 -18 20 11 0.713379 0.901367 0.224365 -18 20 12 0.713379 0.901367 0.224365 -18 20 13 0.712402 0.901855 0.258789 -18 20 14 0.70752 0.902832 0.346436 -18 20 15 0.699219 0.902344 0.434814 -18 20 16 0.685547 0.900391 0.526855 -18 20 17 0.664551 0.895996 0.619629 -18 20 18 0.635742 0.88916 0.710449 -18 20 19 0.598145 0.878418 0.794434 -18 20 20 0.549805 0.862305 0.867188 -18 20 21 0.488281 0.838379 0.924805 -18 20 22 0.409912 0.804199 0.962402 -18 20 23 0.314697 0.767578 0.984863 -18 20 24 0.164673 0.732422 0.999023 -18 20 25 0 0.696777 1 -18 20 26 0 0.661621 1 -18 20 27 0 0.62793 1 -18 20 28 0 0.596191 1 -18 20 29 0 0.566406 1 -18 20 30 0 0.539551 1 -18 20 31 0 0.514648 1 -18 21 0 0.63623 0.953613 0.214844 -18 21 1 0.63623 0.953613 0.214844 -18 21 2 0.63623 0.953613 0.214844 -18 21 3 0.63623 0.953613 0.214844 -18 21 4 0.63623 0.953613 0.214844 -18 21 5 0.63623 0.953613 0.214844 -18 21 6 0.63623 0.953613 0.214844 -18 21 7 0.63623 0.953613 0.214844 -18 21 8 0.63623 0.953613 0.214844 -18 21 9 0.63623 0.953613 0.214844 -18 21 10 0.63623 0.953613 0.214844 -18 21 11 0.636719 0.953613 0.214966 -18 21 12 0.636719 0.954102 0.214966 -18 21 13 0.636719 0.95459 0.222168 -18 21 14 0.631348 0.955078 0.317871 -18 21 15 0.623047 0.955566 0.40918 -18 21 16 0.609863 0.955566 0.502441 -18 21 17 0.589355 0.953613 0.596191 -18 21 18 0.561035 0.949219 0.688477 -18 21 19 0.521484 0.94043 0.773926 -18 21 20 0.469238 0.92627 0.848633 -18 21 21 0.400635 0.90625 0.913086 -18 21 22 0.304199 0.878906 0.960938 -18 21 23 0.106018 0.844238 0.991211 -18 21 24 0 0.808105 1 -18 21 25 0 0.769531 1 -18 21 26 0 0.730469 1 -18 21 27 0 0.692383 1 -18 21 28 0 0.655762 1 -18 21 29 0 0.621582 1 -18 21 30 0 0.589844 1 -18 21 31 0 0.560547 1 -18 22 0 0.547852 0.997559 0.2052 -18 22 1 0.547852 0.997559 0.2052 -18 22 2 0.547852 0.997559 0.2052 -18 22 3 0.547852 0.997559 0.2052 -18 22 4 0.547852 0.997559 0.2052 -18 22 5 0.547852 0.997559 0.2052 -18 22 6 0.547852 0.997559 0.2052 -18 22 7 0.547852 0.997559 0.2052 -18 22 8 0.547852 0.997559 0.2052 -18 22 9 0.547852 0.997559 0.2052 -18 22 10 0.547852 0.997559 0.2052 -18 22 11 0.547852 0.998047 0.2052 -18 22 12 0.54834 0.998047 0.205322 -18 22 13 0.54834 0.998535 0.205322 -18 22 14 0.543945 0.999512 0.287109 -18 22 15 0.534668 1 0.38208 -18 22 16 0.52002 1 0.476562 -18 22 17 0.498047 1 0.571289 -18 22 18 0.465332 1 0.663574 -18 22 19 0.418701 0.993652 0.75 -18 22 20 0.352783 0.981445 0.82666 -18 22 21 0.246704 0.963867 0.893555 -18 22 22 0 0.941406 0.949219 -18 22 23 0 0.913086 0.989258 -18 22 24 0 0.879395 1 -18 22 25 0 0.84082 1 -18 22 26 0 0.799805 1 -18 22 27 0 0.757812 1 -18 22 28 0 0.717285 1 -18 22 29 0 0.678711 1 -18 22 30 0 0.64209 1 -18 22 31 0 0.608398 1 -18 23 0 0.443115 1 0.195679 -18 23 1 0.443115 1 0.195679 -18 23 2 0.443115 1 0.195679 -18 23 3 0.443115 1 0.195679 -18 23 4 0.443115 1 0.195679 -18 23 5 0.443115 1 0.195679 -18 23 6 0.443115 1 0.195679 -18 23 7 0.443115 1 0.195679 -18 23 8 0.443115 1 0.195679 -18 23 9 0.443115 1 0.195679 -18 23 10 0.443359 1 0.195679 -18 23 11 0.443359 1 0.195679 -18 23 12 0.443848 1 0.195801 -18 23 13 0.444336 1 0.195923 -18 23 14 0.440674 1 0.253906 -18 23 15 0.428955 1 0.354736 -18 23 16 0.410156 1 0.450439 -18 23 17 0.380615 1 0.54541 -18 23 18 0.334473 1 0.637695 -18 23 19 0.257324 1 0.725098 -18 23 20 0 1 0.802734 -18 23 21 0 1 0.871582 -18 23 22 0 0.991211 0.929688 -18 23 23 0 0.967773 0.976074 -18 23 24 0 0.939453 1 -18 23 25 0 0.904297 1 -18 23 26 0 0.86377 1 -18 23 27 0 0.820312 1 -18 23 28 0 0.776855 1 -18 23 29 0 0.734375 1 -18 23 30 0 0.693848 1 -18 23 31 0 0.655762 1 -18 24 0 0.297119 1 0.186401 -18 24 1 0.297119 1 0.186401 -18 24 2 0.297119 1 0.186401 -18 24 3 0.297119 1 0.186401 -18 24 4 0.297119 1 0.186401 -18 24 5 0.297119 1 0.186401 -18 24 6 0.297119 1 0.186401 -18 24 7 0.297363 1 0.186401 -18 24 8 0.297363 1 0.186523 -18 24 9 0.297363 1 0.186523 -18 24 10 0.297607 1 0.186523 -18 24 11 0.297852 1 0.186523 -18 24 12 0.298584 1 0.186523 -18 24 13 0.299561 1 0.186646 -18 24 14 0.297119 1 0.217285 -18 24 15 0.275879 1 0.32666 -18 24 16 0.237549 1 0.424561 -18 24 17 0.154541 1 0.519531 -18 24 18 0 1 0.611328 -18 24 19 0 1 0.69873 -18 24 20 0 1 0.777344 -18 24 21 0 1 0.847656 -18 24 22 0 1 0.908203 -18 24 23 0 1 0.95752 -18 24 24 0 0.988281 0.997559 -18 24 25 0 0.958008 1 -18 24 26 0 0.919922 1 -18 24 27 0 0.877441 1 -18 24 28 0 0.83252 1 -18 24 29 0 0.787598 1 -18 24 30 0 0.744141 1 -18 24 31 0 0.702148 1 -18 25 0 0 1 0.176636 -18 25 1 0 1 0.176636 -18 25 2 0 1 0.176636 -18 25 3 0 1 0.176636 -18 25 4 0 1 0.176636 -18 25 5 0 1 0.176636 -18 25 6 0 1 0.176636 -18 25 7 0 1 0.176636 -18 25 8 0 1 0.176636 -18 25 9 0 1 0.176636 -18 25 10 0 1 0.176758 -18 25 11 0 1 0.176758 -18 25 12 0 1 0.176758 -18 25 13 0 1 0.17688 -18 25 14 0 1 0.177002 -18 25 15 0 1 0.294922 -18 25 16 0 1 0.395752 -18 25 17 0 1 0.490723 -18 25 18 0 1 0.58252 -18 25 19 0 1 0.668945 -18 25 20 0 1 0.748047 -18 25 21 0 1 0.819824 -18 25 22 0 1 0.882324 -18 25 23 0 1 0.93457 -18 25 24 0 1 0.977539 -18 25 25 0 1 1 -18 25 26 0 0.973145 1 -18 25 27 0 0.933105 1 -18 25 28 0 0.888672 1 -18 25 29 0 0.842773 1 -18 25 30 0 0.796387 1 -18 25 31 0 0.751953 1 -18 26 0 0 1 0.166382 -18 26 1 0 1 0.166382 -18 26 2 0 1 0.166382 -18 26 3 0 1 0.166382 -18 26 4 0 1 0.166382 -18 26 5 0 1 0.166382 -18 26 6 0 1 0.166382 -18 26 7 0 1 0.166382 -18 26 8 0 1 0.166382 -18 26 9 0 1 0.166382 -18 26 10 0 1 0.166382 -18 26 11 0 1 0.166504 -18 26 12 0 1 0.166504 -18 26 13 0 1 0.166626 -18 26 14 0 1 0.166748 -18 26 15 0 1 0.258789 -18 26 16 0 1 0.364502 -18 26 17 0 1 0.459961 -18 26 18 0 1 0.550781 -18 26 19 0 1 0.636719 -18 26 20 0 1 0.71582 -18 26 21 0 1 0.788086 -18 26 22 0 1 0.852539 -18 26 23 0 1 0.907227 -18 26 24 0 1 0.952637 -18 26 25 0 1 0.994629 -18 26 26 0 1 1 -18 26 27 0 0.985352 1 -18 26 28 0 0.943359 1 -18 26 29 0 0.897461 1 -18 26 30 0 0.850586 1 -18 26 31 0 0.803223 1 -18 27 0 0 1 0.155518 -18 27 1 0 1 0.155518 -18 27 2 0 1 0.155518 -18 27 3 0 1 0.155518 -18 27 4 0 1 0.155518 -18 27 5 0 1 0.155518 -18 27 6 0 1 0.155518 -18 27 7 0 1 0.155518 -18 27 8 0 1 0.15564 -18 27 9 0 1 0.15564 -18 27 10 0 1 0.15564 -18 27 11 0 1 0.15564 -18 27 12 0 1 0.155762 -18 27 13 0 1 0.155762 -18 27 14 0 1 0.156006 -18 27 15 0 1 0.214844 -18 27 16 0 1 0.330322 -18 27 17 0 1 0.427002 -18 27 18 0 1 0.51709 -18 27 19 0 1 0.602051 -18 27 20 0 1 0.680176 -18 27 21 0 1 0.75293 -18 27 22 0 1 0.818359 -18 27 23 0 1 0.875 -18 27 24 0 1 0.922852 -18 27 25 0 1 0.967773 -18 27 26 0 1 1 -18 27 27 0 1 1 -18 27 28 0 0.994141 1 -18 27 29 0 0.950684 1 -18 27 30 0 0.903809 1 -18 27 31 0 0.855469 1 -18 28 0 0 1 0.144287 -18 28 1 0 1 0.144287 -18 28 2 0 1 0.144287 -18 28 3 0 1 0.144287 -18 28 4 0 1 0.144287 -18 28 5 0 1 0.144287 -18 28 6 0 1 0.144287 -18 28 7 0 1 0.144287 -18 28 8 0 1 0.144287 -18 28 9 0 1 0.144287 -18 28 10 0 1 0.144287 -18 28 11 0 1 0.144287 -18 28 12 0 1 0.144409 -18 28 13 0 1 0.144531 -18 28 14 0 1 0.144653 -18 28 15 0 1 0.155396 -18 28 16 0 1 0.29248 -18 28 17 0 1 0.39209 -18 28 18 0 1 0.481689 -18 28 19 0 1 0.56543 -18 28 20 0 1 0.642578 -18 28 21 0 1 0.714844 -18 28 22 0 1 0.780762 -18 28 23 0 1 0.837891 -18 28 24 0 1 0.888184 -18 28 25 0 1 0.935547 -18 28 26 0 1 0.979492 -18 28 27 0 1 1 -18 28 28 0 1 1 -18 28 29 0 0.999512 1 -18 28 30 0 0.95459 1 -18 28 31 0 0.907227 1 -18 29 0 0 1 0.132324 -18 29 1 0 1 0.132324 -18 29 2 0 1 0.132324 -18 29 3 0 1 0.132324 -18 29 4 0 1 0.132324 -18 29 5 0 1 0.132324 -18 29 6 0 1 0.132324 -18 29 7 0 1 0.132324 -18 29 8 0 1 0.132324 -18 29 9 0 1 0.132324 -18 29 10 0 1 0.132324 -18 29 11 0 1 0.132446 -18 29 12 0 1 0.132446 -18 29 13 0 1 0.132568 -18 29 14 0 1 0.13269 -18 29 15 0 1 0.132935 -18 29 16 0 1 0.249268 -18 29 17 0 1 0.354492 -18 29 18 0 1 0.444336 -18 29 19 0 1 0.526855 -18 29 20 0 1 0.602539 -18 29 21 0 1 0.673828 -18 29 22 0 1 0.739258 -18 29 23 0 1 0.797363 -18 29 24 0 1 0.848633 -18 29 25 0 1 0.897949 -18 29 26 0 1 0.944824 -18 29 27 0 1 0.987793 -18 29 28 0 1 1 -18 29 29 0 1 1 -18 29 30 0 1 1 -18 29 31 0 0.958496 1 -18 30 0 0 1 0.11969 -18 30 1 0 1 0.11969 -18 30 2 0 1 0.11969 -18 30 3 0 1 0.11969 -18 30 4 0 1 0.11969 -18 30 5 0 1 0.11969 -18 30 6 0 1 0.11969 -18 30 7 0 1 0.11969 -18 30 8 0 1 0.119751 -18 30 9 0 1 0.119751 -18 30 10 0 1 0.119751 -18 30 11 0 1 0.119812 -18 30 12 0 1 0.119873 -18 30 13 0 1 0.119995 -18 30 14 0 1 0.120117 -18 30 15 0 1 0.120422 -18 30 16 0 1 0.196899 -18 30 17 0 1 0.313965 -18 30 18 0 1 0.405273 -18 30 19 0 1 0.486328 -18 30 20 0 1 0.560547 -18 30 21 0 1 0.630371 -18 30 22 0 1 0.694824 -18 30 23 0 1 0.75293 -18 30 24 0 1 0.804688 -18 30 25 0 1 0.855469 -18 30 26 0 1 0.904785 -18 30 27 0 1 0.950684 -18 30 28 0 1 0.993164 -18 30 29 0 1 1 -18 30 30 0 1 1 -18 30 31 0 1 1 -18 31 0 0 1 0.106445 -18 31 1 0 1 0.106445 -18 31 2 0 1 0.106445 -18 31 3 0 1 0.106445 -18 31 4 0 1 0.106445 -18 31 5 0 1 0.106445 -18 31 6 0 1 0.106445 -18 31 7 0 1 0.106445 -18 31 8 0 1 0.106445 -18 31 9 0 1 0.106445 -18 31 10 0 1 0.106506 -18 31 11 0 1 0.106506 -18 31 12 0 1 0.106567 -18 31 13 0 1 0.106689 -18 31 14 0 1 0.106873 -18 31 15 0 1 0.107178 -18 31 16 0 1 0.11731 -18 31 17 0 1 0.269775 -18 31 18 0 1 0.364258 -18 31 19 0 1 0.444824 -18 31 20 0 1 0.517578 -18 31 21 0 1 0.585449 -18 31 22 0 1 0.648438 -18 31 23 0 1 0.705566 -18 31 24 0 1 0.757324 -18 31 25 0 1 0.808594 -18 31 26 0 1 0.859863 -18 31 27 0 1 0.90918 -18 31 28 0 1 0.955078 -18 31 29 0 1 0.99707 -18 31 30 0 1 1 -18 31 31 0 1 1 -19 0 0 0.87793 0 0.0489502 -19 0 1 0.87793 0 0.0489502 -19 0 2 0.87793 0 0.0489502 -19 0 3 0.87793 0 0.0489502 -19 0 4 0.87793 0 0.0489197 -19 0 5 0.87793 0 0.0488892 -19 0 6 0.87793 0 0.0488586 -19 0 7 0.87793 0 0.0487366 -19 0 8 0.87793 0 0.0485535 -19 0 9 0.87793 0 0.0481873 -19 0 10 0.878418 0 0.0474854 -19 0 11 0.878418 0 0.0462036 -19 0 12 0.880371 0 0.045166 -19 0 13 0.885254 0 0.171387 -19 0 14 0.895508 0 0.296143 -19 0 15 0.907227 0 0.404053 -19 0 16 0.92627 0 0.521484 -19 0 17 0.949219 0.231323 0.644531 -19 0 18 0.948242 0.297119 0.749512 -19 0 19 0.914551 0.30835 0.828613 -19 0 20 0.870605 0.313477 0.894043 -19 0 21 0.813965 0.314941 0.940918 -19 0 22 0.74707 0.312012 0.967285 -19 0 23 0.679688 0.307129 0.97998 -19 0 24 0.615234 0.302246 0.986328 -19 0 25 0.547852 0.297363 0.990234 -19 0 26 0.476807 0.292725 0.992676 -19 0 27 0.398193 0.288818 0.995117 -19 0 28 0.302979 0.285645 0.998535 -19 0 29 0.126465 0.283691 1 -19 0 30 0 0.282471 1 -19 0 31 0 0.281982 1 -19 1 0 0.87793 0 0.0489197 -19 1 1 0.87793 0 0.0489197 -19 1 2 0.87793 0 0.0489197 -19 1 3 0.87793 0 0.0489197 -19 1 4 0.87793 0 0.0488892 -19 1 5 0.87793 0 0.0488892 -19 1 6 0.87793 0 0.0488281 -19 1 7 0.87793 0 0.0487366 -19 1 8 0.87793 0 0.0485229 -19 1 9 0.87793 0 0.0481567 -19 1 10 0.878418 0 0.0474548 -19 1 11 0.878418 0 0.0461731 -19 1 12 0.880371 0 0.0451355 -19 1 13 0.885254 0 0.171387 -19 1 14 0.895508 0 0.296143 -19 1 15 0.907227 0 0.404053 -19 1 16 0.92627 0 0.521484 -19 1 17 0.949219 0.231445 0.644531 -19 1 18 0.948242 0.297119 0.749512 -19 1 19 0.914551 0.30835 0.828613 -19 1 20 0.870605 0.313477 0.894043 -19 1 21 0.813965 0.314941 0.940918 -19 1 22 0.74707 0.312012 0.967285 -19 1 23 0.679688 0.307373 0.97998 -19 1 24 0.615234 0.302246 0.986328 -19 1 25 0.547852 0.297363 0.990234 -19 1 26 0.476807 0.292725 0.992676 -19 1 27 0.398193 0.288818 0.995117 -19 1 28 0.302979 0.285889 0.998535 -19 1 29 0.126465 0.283691 1 -19 1 30 0 0.282471 1 -19 1 31 0 0.281982 1 -19 2 0 0.87793 0 0.0488892 -19 2 1 0.87793 0 0.0488892 -19 2 2 0.87793 0 0.0488586 -19 2 3 0.87793 0 0.0488586 -19 2 4 0.87793 0 0.0488586 -19 2 5 0.87793 0 0.0488281 -19 2 6 0.87793 0 0.0487671 -19 2 7 0.87793 0 0.0486755 -19 2 8 0.87793 0 0.0484924 -19 2 9 0.87793 0 0.0480957 -19 2 10 0.878418 0 0.0473938 -19 2 11 0.878418 0 0.0461121 -19 2 12 0.880371 0 0.0450745 -19 2 13 0.885254 0 0.171387 -19 2 14 0.895508 0 0.296143 -19 2 15 0.907227 0 0.404053 -19 2 16 0.92627 0 0.521484 -19 2 17 0.949219 0.231445 0.644531 -19 2 18 0.948242 0.297119 0.749512 -19 2 19 0.914551 0.30835 0.828613 -19 2 20 0.870605 0.313477 0.894043 -19 2 21 0.813965 0.314941 0.940918 -19 2 22 0.74707 0.312012 0.967285 -19 2 23 0.679688 0.307373 0.97998 -19 2 24 0.615234 0.302246 0.986328 -19 2 25 0.547852 0.297363 0.990234 -19 2 26 0.476807 0.292725 0.992676 -19 2 27 0.398193 0.288818 0.995117 -19 2 28 0.302734 0.285889 0.998535 -19 2 29 0.126465 0.283691 1 -19 2 30 0 0.282471 1 -19 2 31 0 0.281982 1 -19 3 0 0.87793 0 0.0487976 -19 3 1 0.87793 0 0.0487976 -19 3 2 0.87793 0 0.0487976 -19 3 3 0.87793 0 0.0487671 -19 3 4 0.87793 0 0.0487671 -19 3 5 0.87793 0 0.0487366 -19 3 6 0.87793 0 0.0486755 -19 3 7 0.87793 0 0.048584 -19 3 8 0.87793 0 0.0484009 -19 3 9 0.87793 0 0.0480042 -19 3 10 0.878418 0 0.0473022 -19 3 11 0.878418 0 0.0460205 -19 3 12 0.880371 0 0.0449829 -19 3 13 0.885254 0 0.171387 -19 3 14 0.895508 0 0.296143 -19 3 15 0.907227 0 0.404053 -19 3 16 0.92627 0 0.521484 -19 3 17 0.949219 0.231689 0.644531 -19 3 18 0.948242 0.297363 0.749512 -19 3 19 0.914551 0.30835 0.828613 -19 3 20 0.870605 0.313721 0.894043 -19 3 21 0.813965 0.315186 0.940918 -19 3 22 0.74707 0.312256 0.967285 -19 3 23 0.679688 0.307373 0.97998 -19 3 24 0.615234 0.302246 0.986328 -19 3 25 0.547852 0.297363 0.990234 -19 3 26 0.476807 0.292725 0.992676 -19 3 27 0.398193 0.288818 0.995117 -19 3 28 0.302734 0.285889 0.998535 -19 3 29 0.126465 0.283691 1 -19 3 30 0 0.282471 1 -19 3 31 0 0.281982 1 -19 4 0 0.87793 0 0.0486145 -19 4 1 0.87793 0 0.0486145 -19 4 2 0.87793 0 0.0486145 -19 4 3 0.87793 0 0.0486145 -19 4 4 0.87793 0 0.048584 -19 4 5 0.87793 0 0.0485535 -19 4 6 0.87793 0 0.0485229 -19 4 7 0.87793 0 0.0484009 -19 4 8 0.87793 0 0.0482178 -19 4 9 0.878418 0 0.047821 -19 4 10 0.878418 0 0.0471191 -19 4 11 0.878418 0 0.0458374 -19 4 12 0.880371 0 0.0447998 -19 4 13 0.885254 0 0.171387 -19 4 14 0.895508 0 0.296143 -19 4 15 0.907227 0 0.404053 -19 4 16 0.92627 0 0.521484 -19 4 17 0.949219 0.231934 0.644531 -19 4 18 0.948242 0.297363 0.749512 -19 4 19 0.914551 0.308594 0.828613 -19 4 20 0.870605 0.313965 0.894043 -19 4 21 0.813965 0.315186 0.940918 -19 4 22 0.74707 0.312256 0.967285 -19 4 23 0.679688 0.307373 0.97998 -19 4 24 0.615234 0.30249 0.986328 -19 4 25 0.547852 0.297363 0.990234 -19 4 26 0.476807 0.292725 0.992676 -19 4 27 0.398193 0.288818 0.995117 -19 4 28 0.302734 0.285889 0.998535 -19 4 29 0.126343 0.283691 1 -19 4 30 0 0.282471 1 -19 4 31 0 0.281982 1 -19 5 0 0.87793 0 0.0482788 -19 5 1 0.87793 0 0.0482788 -19 5 2 0.87793 0 0.0482788 -19 5 3 0.87793 0 0.0482788 -19 5 4 0.87793 0 0.0482483 -19 5 5 0.87793 0 0.0482178 -19 5 6 0.87793 0 0.0481873 -19 5 7 0.87793 0 0.0480652 -19 5 8 0.87793 0 0.0478821 -19 5 9 0.878418 0 0.0474854 -19 5 10 0.878418 0 0.0467834 -19 5 11 0.878906 0 0.0454712 -19 5 12 0.880371 0 0.0444031 -19 5 13 0.885254 0 0.171387 -19 5 14 0.895508 0 0.296143 -19 5 15 0.907227 0 0.404053 -19 5 16 0.92627 0 0.521484 -19 5 17 0.949219 0.232544 0.644531 -19 5 18 0.947754 0.297852 0.749512 -19 5 19 0.914551 0.309082 0.828613 -19 5 20 0.870605 0.314209 0.894043 -19 5 21 0.813965 0.315674 0.940918 -19 5 22 0.74707 0.3125 0.967285 -19 5 23 0.679688 0.307617 0.97998 -19 5 24 0.615234 0.302734 0.986328 -19 5 25 0.547852 0.297607 0.990234 -19 5 26 0.476807 0.292969 0.992676 -19 5 27 0.398193 0.289062 0.995117 -19 5 28 0.302734 0.285889 0.998535 -19 5 29 0.126221 0.283936 1 -19 5 30 0 0.282715 1 -19 5 31 0 0.282227 1 -19 6 0 0.87793 0 0.0476379 -19 6 1 0.87793 0 0.0476379 -19 6 2 0.87793 0 0.0476379 -19 6 3 0.87793 0 0.0476379 -19 6 4 0.87793 0 0.0476074 -19 6 5 0.87793 0 0.0475769 -19 6 6 0.878418 0 0.0475464 -19 6 7 0.878418 0 0.0474243 -19 6 8 0.878418 0 0.0472107 -19 6 9 0.878418 0 0.046814 -19 6 10 0.878418 0 0.0460815 -19 6 11 0.878906 0 0.0447693 -19 6 12 0.880371 0 0.0436707 -19 6 13 0.885742 0 0.171387 -19 6 14 0.895508 0 0.296143 -19 6 15 0.907227 0 0.404053 -19 6 16 0.92627 0.0246277 0.521484 -19 6 17 0.949219 0.233643 0.644531 -19 6 18 0.947754 0.298584 0.749512 -19 6 19 0.914551 0.309814 0.828613 -19 6 20 0.870605 0.314941 0.894043 -19 6 21 0.813965 0.316162 0.940918 -19 6 22 0.74707 0.312988 0.967285 -19 6 23 0.679688 0.308105 0.97998 -19 6 24 0.615234 0.302979 0.986328 -19 6 25 0.547852 0.298096 0.990234 -19 6 26 0.476807 0.293213 0.992676 -19 6 27 0.398193 0.289307 0.995117 -19 6 28 0.302734 0.286133 0.998535 -19 6 29 0.125977 0.28418 1 -19 6 30 0 0.282959 1 -19 6 31 0 0.282227 1 -19 7 0 0.878418 0 0.0463562 -19 7 1 0.878418 0 0.0463257 -19 7 2 0.878418 0 0.0463257 -19 7 3 0.878418 0 0.0463257 -19 7 4 0.878418 0 0.0463257 -19 7 5 0.878418 0 0.0462952 -19 7 6 0.878418 0 0.0462341 -19 7 7 0.878418 0 0.0461121 -19 7 8 0.878418 0 0.0458984 -19 7 9 0.878418 0 0.0455017 -19 7 10 0.878906 0 0.0447083 -19 7 11 0.878906 0 0.0433044 -19 7 12 0.880859 0 0.0421753 -19 7 13 0.885742 0 0.171509 -19 7 14 0.895508 0 0.296143 -19 7 15 0.907227 0 0.404053 -19 7 16 0.92627 0.0570984 0.520996 -19 7 17 0.949219 0.235718 0.644531 -19 7 18 0.947754 0.300293 0.749512 -19 7 19 0.914551 0.311035 0.828613 -19 7 20 0.870605 0.316162 0.894043 -19 7 21 0.813965 0.317383 0.940918 -19 7 22 0.74707 0.313965 0.967285 -19 7 23 0.679199 0.309082 0.97998 -19 7 24 0.615234 0.303711 0.986328 -19 7 25 0.547852 0.298584 0.990234 -19 7 26 0.476562 0.293945 0.992676 -19 7 27 0.397949 0.289795 0.995117 -19 7 28 0.30249 0.286621 0.998535 -19 7 29 0.125366 0.284424 1 -19 7 30 0 0.283203 1 -19 7 31 0 0.282715 1 -19 8 0 0.878906 0 0.0436096 -19 8 1 0.878906 0 0.0436096 -19 8 2 0.878906 0 0.0436096 -19 8 3 0.878906 0 0.0436096 -19 8 4 0.878906 0 0.0435791 -19 8 5 0.878906 0 0.0435486 -19 8 6 0.878906 0 0.0434875 -19 8 7 0.878906 0 0.0433655 -19 8 8 0.878906 0 0.0431213 -19 8 9 0.878906 0 0.0426636 -19 8 10 0.878906 0 0.0418091 -19 8 11 0.879395 0 0.0402222 -19 8 12 0.881348 0 0.0389404 -19 8 13 0.885742 0 0.171509 -19 8 14 0.895508 0 0.295898 -19 8 15 0.907227 0 0.404053 -19 8 16 0.925781 0.0841064 0.520996 -19 8 17 0.94873 0.239746 0.644043 -19 8 18 0.947754 0.303223 0.749512 -19 8 19 0.914062 0.313721 0.828613 -19 8 20 0.870605 0.318604 0.894043 -19 8 21 0.813965 0.31958 0.941406 -19 8 22 0.746582 0.315918 0.967285 -19 8 23 0.679199 0.310791 0.97998 -19 8 24 0.614746 0.30542 0.986328 -19 8 25 0.547852 0.300049 0.990234 -19 8 26 0.476562 0.295166 0.992676 -19 8 27 0.397949 0.290771 0.995117 -19 8 28 0.302246 0.287598 0.998535 -19 8 29 0.12439 0.2854 1 -19 8 30 0 0.283936 1 -19 8 31 0 0.283203 1 -19 9 0 0.879395 0 0.037384 -19 9 1 0.879395 0 0.037384 -19 9 2 0.879395 0 0.037384 -19 9 3 0.879395 0 0.037384 -19 9 4 0.879395 0 0.0373535 -19 9 5 0.879395 0 0.037323 -19 9 6 0.879395 0 0.0372314 -19 9 7 0.879395 0 0.0370789 -19 9 8 0.879395 0 0.0367737 -19 9 9 0.879883 0 0.0361633 -19 9 10 0.879883 0 0.0350342 -19 9 11 0.879883 0 0.0328979 -19 9 12 0.881836 0 0.0310669 -19 9 13 0.88623 0 0.171631 -19 9 14 0.895508 0 0.295898 -19 9 15 0.907227 0 0.404053 -19 9 16 0.925781 0.114258 0.520508 -19 9 17 0.948242 0.24707 0.644043 -19 9 18 0.947266 0.308838 0.749512 -19 9 19 0.914062 0.318848 0.828613 -19 9 20 0.870117 0.323242 0.894043 -19 9 21 0.813477 0.323486 0.941406 -19 9 22 0.746582 0.31958 0.967285 -19 9 23 0.678711 0.313965 0.980469 -19 9 24 0.614746 0.308105 0.986328 -19 9 25 0.547363 0.30249 0.990234 -19 9 26 0.476074 0.297363 0.992676 -19 9 27 0.397461 0.292725 0.995117 -19 9 28 0.301758 0.289307 0.998535 -19 9 29 0.122375 0.286865 1 -19 9 30 0 0.285156 1 -19 9 31 0 0.284424 1 -19 10 0 0.880859 0 0.0154266 -19 10 1 0.880859 0 0.0154114 -19 10 2 0.880859 0 0.0153809 -19 10 3 0.880859 0 0.0153351 -19 10 4 0.880859 0 0.0152435 -19 10 5 0.880859 0 0.0150681 -19 10 6 0.880859 0 0.0147171 -19 10 7 0.880859 0 0.0139999 -19 10 8 0.880859 0 0.0123978 -19 10 9 0.880859 0 0.00764084 -19 10 10 0.881348 0.0405273 0 -19 10 11 0.881348 0.0637817 0 -19 10 12 0.882812 0.0750122 0 -19 10 13 0.887207 0.0643311 0.171997 -19 10 14 0.895996 0 0.29541 -19 10 15 0.907715 0.0335388 0.404053 -19 10 16 0.924805 0.14917 0.52002 -19 10 17 0.947266 0.259766 0.643555 -19 10 18 0.946777 0.318359 0.749512 -19 10 19 0.913574 0.327637 0.828613 -19 10 20 0.869629 0.331299 0.894043 -19 10 21 0.812988 0.330811 0.941406 -19 10 22 0.745605 0.325928 0.967285 -19 10 23 0.678223 0.31958 0.980469 -19 10 24 0.61377 0.313232 0.986328 -19 10 25 0.546875 0.306885 0.990234 -19 10 26 0.475586 0.30127 0.992676 -19 10 27 0.396729 0.296143 0.995117 -19 10 28 0.300781 0.292236 0.999023 -19 10 29 0.11853 0.289307 1 -19 10 30 0 0.287354 1 -19 10 31 0 0.286377 1 -19 11 0 0.883301 0.142212 0 -19 11 1 0.883301 0.142212 0 -19 11 2 0.883301 0.142212 0 -19 11 3 0.883301 0.142212 0 -19 11 4 0.883301 0.142334 0 -19 11 5 0.883301 0.142334 0 -19 11 6 0.883301 0.142578 0 -19 11 7 0.883301 0.142944 0 -19 11 8 0.883301 0.143799 0 -19 11 9 0.883301 0.145264 0 -19 11 10 0.883789 0.147827 0 -19 11 11 0.883789 0.152222 0 -19 11 12 0.885254 0.155396 0 -19 11 13 0.88916 0.151733 0.172974 -19 11 14 0.896484 0.144043 0.295166 -19 11 15 0.908203 0.147705 0.404053 -19 11 16 0.923828 0.190186 0.519043 -19 11 17 0.945801 0.279541 0.642578 -19 11 18 0.945801 0.334229 0.749023 -19 11 19 0.912598 0.342529 0.828613 -19 11 20 0.868652 0.344727 0.894043 -19 11 21 0.812012 0.343018 0.941406 -19 11 22 0.744629 0.336914 0.967285 -19 11 23 0.677246 0.329102 0.980469 -19 11 24 0.612793 0.321777 0.986816 -19 11 25 0.545898 0.314453 0.990234 -19 11 26 0.474365 0.307861 0.992676 -19 11 27 0.395508 0.302246 0.995605 -19 11 28 0.299072 0.297607 0.999023 -19 11 29 0.111328 0.293945 1 -19 11 30 0 0.291504 1 -19 11 31 0 0.289795 1 -19 12 0 0.887207 0.213135 0 -19 12 1 0.887207 0.213135 0 -19 12 2 0.887207 0.213135 0 -19 12 3 0.887207 0.213135 0 -19 12 4 0.887207 0.213257 0 -19 12 5 0.887207 0.213257 0 -19 12 6 0.887207 0.213379 0 -19 12 7 0.887207 0.213623 0 -19 12 8 0.887695 0.213989 0 -19 12 9 0.887695 0.214844 0 -19 12 10 0.887695 0.216187 0 -19 12 11 0.888184 0.21875 0 -19 12 12 0.88916 0.220581 0 -19 12 13 0.89209 0.217773 0.175659 -19 12 14 0.897949 0.212891 0.295166 -19 12 15 0.908691 0.216797 0.404541 -19 12 16 0.921875 0.238892 0.517578 -19 12 17 0.943359 0.309082 0.641602 -19 12 18 0.943848 0.358887 0.749023 -19 12 19 0.910645 0.365479 0.828613 -19 12 20 0.867188 0.365967 0.894043 -19 12 21 0.810547 0.362305 0.941406 -19 12 22 0.743164 0.354248 0.967773 -19 12 23 0.675781 0.344727 0.980469 -19 12 24 0.611328 0.335693 0.986816 -19 12 25 0.543945 0.326904 0.990234 -19 12 26 0.472412 0.318848 0.993164 -19 12 27 0.393311 0.311768 0.995605 -19 12 28 0.296143 0.306152 0.999512 -19 12 29 0.0968018 0.301514 1 -19 12 30 0 0.298096 1 -19 12 31 0 0.295654 1 -19 13 0 0.894043 0.283936 0 -19 13 1 0.894043 0.283936 0 -19 13 2 0.894043 0.283936 0 -19 13 3 0.894043 0.283936 0 -19 13 4 0.894043 0.283936 0 -19 13 5 0.894043 0.283936 0 -19 13 6 0.894043 0.28418 0 -19 13 7 0.894043 0.28418 0 -19 13 8 0.894043 0.284424 0 -19 13 9 0.894531 0.284912 0 -19 13 10 0.894531 0.285889 0 -19 13 11 0.894531 0.287598 0 -19 13 12 0.89502 0.288818 0 -19 13 13 0.896973 0.286377 0.182495 -19 13 14 0.900391 0.282471 0.296631 -19 13 15 0.90918 0.28418 0.404053 -19 13 16 0.918457 0.296143 0.515137 -19 13 17 0.938477 0.349365 0.63916 -19 13 18 0.94043 0.394287 0.748535 -19 13 19 0.907715 0.398926 0.828613 -19 13 20 0.864258 0.397217 0.894043 -19 13 21 0.807617 0.391113 0.941895 -19 13 22 0.740234 0.379883 0.967773 -19 13 23 0.672852 0.36792 0.980469 -19 13 24 0.608398 0.356445 0.986816 -19 13 25 0.541016 0.345703 0.990723 -19 13 26 0.469238 0.335693 0.993652 -19 13 27 0.389648 0.326904 0.996582 -19 13 28 0.291016 0.319336 1 -19 13 29 0.0593567 0.313477 1 -19 13 30 0 0.308594 1 -19 13 31 0 0.304932 1 -19 14 0 0.904785 0.361816 0 -19 14 1 0.904785 0.361816 0 -19 14 2 0.904785 0.361816 0 -19 14 3 0.904785 0.361816 0 -19 14 4 0.904785 0.361816 0 -19 14 5 0.904785 0.361816 0 -19 14 6 0.904785 0.361816 0 -19 14 7 0.904785 0.362061 0 -19 14 8 0.904785 0.362061 0 -19 14 9 0.904785 0.362549 0 -19 14 10 0.904785 0.363281 0 -19 14 11 0.905273 0.364502 0 -19 14 12 0.905273 0.365234 0 -19 14 13 0.905273 0.363037 0.197632 -19 14 14 0.905762 0.359619 0.302246 -19 14 15 0.908691 0.357422 0.40332 -19 14 16 0.914551 0.363525 0.512695 -19 14 17 0.930176 0.400391 0.634766 -19 14 18 0.935059 0.441406 0.74707 -19 14 19 0.90332 0.444092 0.828125 -19 14 20 0.859863 0.439941 0.894043 -19 14 21 0.803223 0.430664 0.941895 -19 14 22 0.73584 0.416016 0.967773 -19 14 23 0.667969 0.400391 0.980469 -19 14 24 0.603516 0.38623 0.986816 -19 14 25 0.536133 0.372559 0.991211 -19 14 26 0.464355 0.359863 0.994141 -19 14 27 0.383789 0.348633 0.997559 -19 14 28 0.282715 0.339111 1 -19 14 29 0 0.331055 1 -19 14 30 0 0.324219 1 -19 14 31 0 0.318848 1 -19 15 0 0.919434 0.448975 0 -19 15 1 0.919434 0.448975 0 -19 15 2 0.919434 0.448975 0 -19 15 3 0.919434 0.448975 0 -19 15 4 0.919434 0.448975 0 -19 15 5 0.919434 0.448975 0 -19 15 6 0.919434 0.448975 0 -19 15 7 0.919434 0.449219 0 -19 15 8 0.919434 0.449219 0 -19 15 9 0.919434 0.449463 0 -19 15 10 0.919434 0.449951 0 -19 15 11 0.919922 0.450928 0 -19 15 12 0.919434 0.451416 0.0978394 -19 15 13 0.917969 0.449951 0.224976 -19 15 14 0.915039 0.447021 0.31665 -19 15 15 0.911133 0.442627 0.408203 -19 15 16 0.911133 0.443604 0.512207 -19 15 17 0.91748 0.462158 0.627441 -19 15 18 0.925781 0.5 0.744629 -19 15 19 0.895508 0.501465 0.827148 -19 15 20 0.852051 0.494629 0.893555 -19 15 21 0.795898 0.481689 0.941406 -19 15 22 0.728516 0.462891 0.967285 -19 15 23 0.660645 0.443359 0.980469 -19 15 24 0.596191 0.425781 0.987305 -19 15 25 0.528809 0.408691 0.991699 -19 15 26 0.456299 0.393066 0.995605 -19 15 27 0.374512 0.378662 0.999023 -19 15 28 0.268799 0.366211 1 -19 15 29 0 0.355469 1 -19 15 30 0 0.346436 1 -19 15 31 0 0.338623 1 -19 16 0 0.936035 0.546387 0.163452 -19 16 1 0.936035 0.546387 0.163452 -19 16 2 0.936035 0.546387 0.163452 -19 16 3 0.936035 0.546387 0.163452 -19 16 4 0.936035 0.546387 0.163452 -19 16 5 0.936035 0.546387 0.163452 -19 16 6 0.936035 0.546387 0.163452 -19 16 7 0.936035 0.546387 0.163452 -19 16 8 0.936035 0.546387 0.163574 -19 16 9 0.936035 0.546875 0.163818 -19 16 10 0.936035 0.546875 0.164062 -19 16 11 0.936523 0.547852 0.164673 -19 16 12 0.936523 0.54834 0.179565 -19 16 13 0.933594 0.547852 0.262695 -19 16 14 0.928711 0.545898 0.342285 -19 16 15 0.919922 0.541504 0.425049 -19 16 16 0.906738 0.53418 0.51416 -19 16 17 0.899414 0.535645 0.617676 -19 16 18 0.910156 0.568359 0.73877 -19 16 19 0.883301 0.570312 0.824707 -19 16 20 0.840332 0.560547 0.89209 -19 16 21 0.784668 0.543945 0.94043 -19 16 22 0.716797 0.520508 0.966309 -19 16 23 0.649414 0.496826 0.97998 -19 16 24 0.584961 0.475342 0.987793 -19 16 25 0.517578 0.45459 0.993164 -19 16 26 0.444092 0.435303 0.997559 -19 16 27 0.359863 0.417725 1 -19 16 28 0.245972 0.401855 1 -19 16 29 0 0.387939 1 -19 16 30 0 0.375977 1 -19 16 31 0 0.365234 1 -19 17 0 0.947266 0.648926 0.230591 -19 17 1 0.947266 0.648926 0.230591 -19 17 2 0.947266 0.648926 0.230591 -19 17 3 0.947266 0.648926 0.230591 -19 17 4 0.947266 0.648926 0.230591 -19 17 5 0.947266 0.648926 0.230591 -19 17 6 0.947266 0.648926 0.230591 -19 17 7 0.947266 0.648926 0.230713 -19 17 8 0.947266 0.648926 0.230713 -19 17 9 0.947266 0.649414 0.230713 -19 17 10 0.947266 0.649414 0.230835 -19 17 11 0.947266 0.649902 0.231079 -19 17 12 0.947754 0.650879 0.231445 -19 17 13 0.944824 0.650879 0.296875 -19 17 14 0.939941 0.649902 0.371094 -19 17 15 0.930176 0.647461 0.450195 -19 17 16 0.913086 0.640137 0.533203 -19 17 17 0.886719 0.626953 0.616699 -19 17 18 0.882324 0.638672 0.725586 -19 17 19 0.864258 0.646484 0.820312 -19 17 20 0.822754 0.634277 0.888672 -19 17 21 0.76709 0.614258 0.937988 -19 17 22 0.699707 0.585938 0.964355 -19 17 23 0.632812 0.558105 0.979004 -19 17 24 0.568848 0.533203 0.988281 -19 17 25 0.500977 0.508789 0.995117 -19 17 26 0.42627 0.48584 1 -19 17 27 0.337646 0.4646 1 -19 17 28 0.206299 0.445312 1 -19 17 29 0 0.427979 1 -19 17 30 0 0.412354 1 -19 17 31 0 0.398682 1 -19 18 0 0.94043 0.748047 0.260254 -19 18 1 0.94043 0.748047 0.260254 -19 18 2 0.94043 0.748047 0.260254 -19 18 3 0.94043 0.748047 0.260254 -19 18 4 0.94043 0.748047 0.260254 -19 18 5 0.94043 0.748047 0.260254 -19 18 6 0.94043 0.748047 0.260254 -19 18 7 0.94043 0.748047 0.260254 -19 18 8 0.94043 0.748047 0.260254 -19 18 9 0.94043 0.748047 0.260254 -19 18 10 0.94043 0.748535 0.260254 -19 18 11 0.94043 0.748535 0.260254 -19 18 12 0.94043 0.749512 0.260498 -19 18 13 0.938965 0.75 0.308594 -19 18 14 0.935059 0.75 0.383545 -19 18 15 0.927734 0.749512 0.465332 -19 18 16 0.914062 0.746094 0.552246 -19 18 17 0.890137 0.736816 0.637695 -19 18 18 0.851562 0.717285 0.713379 -19 18 19 0.837402 0.725098 0.812988 -19 18 20 0.796875 0.711914 0.882812 -19 18 21 0.741699 0.6875 0.932129 -19 18 22 0.675781 0.655762 0.960938 -19 18 23 0.61084 0.625 0.978516 -19 18 24 0.547363 0.597168 0.990234 -19 18 25 0.47876 0.569824 0.999512 -19 18 26 0.401123 0.543457 1 -19 18 27 0.303955 0.518555 1 -19 18 28 0.11438 0.495361 1 -19 18 29 0 0.474365 1 -19 18 30 0 0.45459 1 -19 18 31 0 0.436523 1 -19 19 0 0.907715 0.833008 0.261475 -19 19 1 0.907715 0.833008 0.261475 -19 19 2 0.907715 0.833008 0.261475 -19 19 3 0.907715 0.833008 0.261475 -19 19 4 0.907715 0.833008 0.261475 -19 19 5 0.907715 0.833008 0.261475 -19 19 6 0.907715 0.833008 0.261475 -19 19 7 0.907715 0.833008 0.261475 -19 19 8 0.907715 0.833008 0.261475 -19 19 9 0.907715 0.833008 0.261475 -19 19 10 0.907715 0.833008 0.261475 -19 19 11 0.907715 0.833496 0.261475 -19 19 12 0.907715 0.833496 0.261475 -19 19 13 0.906738 0.834473 0.293457 -19 19 14 0.90332 0.835449 0.372559 -19 19 15 0.897461 0.835449 0.457031 -19 19 16 0.88623 0.833984 0.547363 -19 19 17 0.867676 0.828613 0.638184 -19 19 18 0.839355 0.817871 0.725098 -19 19 19 0.801758 0.801758 0.801758 -19 19 20 0.762695 0.787598 0.873535 -19 19 21 0.708496 0.760742 0.923828 -19 19 22 0.645508 0.728027 0.95752 -19 19 23 0.582031 0.695312 0.979004 -19 19 24 0.518555 0.664551 0.993652 -19 19 25 0.447754 0.633789 1 -19 19 26 0.36377 0.604004 1 -19 19 27 0.248169 0.574707 1 -19 19 28 0 0.547363 1 -19 19 29 0 0.521973 1 -19 19 30 0 0.498535 1 -19 19 31 0 0.476807 1 -19 20 0 0.853027 0.898438 0.253662 -19 20 1 0.853027 0.898438 0.253662 -19 20 2 0.853027 0.898438 0.253662 -19 20 3 0.853027 0.898438 0.253662 -19 20 4 0.853027 0.898438 0.253662 -19 20 5 0.853027 0.898438 0.253662 -19 20 6 0.853027 0.898438 0.253662 -19 20 7 0.853027 0.898438 0.253662 -19 20 8 0.853027 0.898438 0.253662 -19 20 9 0.853027 0.898438 0.253662 -19 20 10 0.853027 0.898438 0.253662 -19 20 11 0.853027 0.898926 0.253662 -19 20 12 0.853027 0.898926 0.253662 -19 20 13 0.853027 0.899414 0.265869 -19 20 14 0.848633 0.899414 0.349365 -19 20 15 0.843262 0.899902 0.435791 -19 20 16 0.83252 0.898926 0.526855 -19 20 17 0.81543 0.894043 0.618164 -19 20 18 0.789062 0.884277 0.705566 -19 20 19 0.756348 0.871094 0.786621 -19 20 20 0.719238 0.857422 0.859863 -19 20 21 0.669922 0.833984 0.917969 -19 20 22 0.609375 0.80127 0.956055 -19 20 23 0.545898 0.766602 0.980957 -19 20 24 0.480469 0.733398 0.997559 -19 20 25 0.404785 0.699707 1 -19 20 26 0.30835 0.665527 1 -19 20 27 0.12262 0.632812 1 -19 20 28 0 0.601562 1 -19 20 29 0 0.572266 1 -19 20 30 0 0.544922 1 -19 20 31 0 0.519531 1 -19 21 0 0.790527 0.955566 0.244873 -19 21 1 0.790527 0.955566 0.244873 -19 21 2 0.790527 0.955566 0.244873 -19 21 3 0.790527 0.955566 0.244873 -19 21 4 0.790527 0.955566 0.244873 -19 21 5 0.790527 0.955566 0.244873 -19 21 6 0.790527 0.955566 0.244873 -19 21 7 0.790527 0.955566 0.244873 -19 21 8 0.790527 0.955566 0.244873 -19 21 9 0.790527 0.955566 0.244873 -19 21 10 0.790527 0.956055 0.244873 -19 21 11 0.791016 0.956055 0.244873 -19 21 12 0.791016 0.956055 0.244995 -19 21 13 0.791016 0.956543 0.244995 -19 21 14 0.787598 0.956543 0.323242 -19 21 15 0.780762 0.956543 0.411865 -19 21 16 0.77002 0.95459 0.50293 -19 21 17 0.753418 0.950684 0.594727 -19 21 18 0.72998 0.943359 0.683594 -19 21 19 0.700684 0.934082 0.767578 -19 21 20 0.664551 0.921387 0.842773 -19 21 21 0.619629 0.90332 0.907715 -19 21 22 0.563965 0.876465 0.956543 -19 21 23 0.499512 0.842285 0.986816 -19 21 24 0.429443 0.807129 1 -19 21 25 0.342285 0.77002 1 -19 21 26 0.207275 0.731934 1 -19 21 27 0 0.694824 1 -19 21 28 0 0.65918 1 -19 21 29 0 0.625488 1 -19 21 30 0 0.594238 1 -19 21 31 0 0.564941 1 -19 22 0 0.718262 0.999512 0.234619 -19 22 1 0.718262 0.999512 0.234619 -19 22 2 0.718262 0.999512 0.234619 -19 22 3 0.718262 0.999512 0.234619 -19 22 4 0.718262 0.999512 0.234619 -19 22 5 0.718262 0.999512 0.234619 -19 22 6 0.718262 0.999512 0.234619 -19 22 7 0.718262 0.999512 0.234619 -19 22 8 0.718262 0.999512 0.234619 -19 22 9 0.718262 1 0.234619 -19 22 10 0.718262 1 0.234619 -19 22 11 0.718262 1 0.234619 -19 22 12 0.718262 1 0.234619 -19 22 13 0.718262 1 0.234741 -19 22 14 0.71582 1 0.292969 -19 22 15 0.709961 1 0.385254 -19 22 16 0.699707 1 0.477539 -19 22 17 0.68457 0.999023 0.569824 -19 22 18 0.662598 0.994629 0.659668 -19 22 19 0.634277 0.987793 0.745117 -19 22 20 0.598633 0.977051 0.821777 -19 22 21 0.552734 0.960449 0.88916 -19 22 22 0.497559 0.939453 0.945801 -19 22 23 0.431641 0.912109 0.986328 -19 22 24 0.351074 0.878418 1 -19 22 25 0.227417 0.840332 1 -19 22 26 0 0.800293 1 -19 22 27 0 0.759277 1 -19 22 28 0 0.719238 1 -19 22 29 0 0.681152 1 -19 22 30 0 0.64502 1 -19 22 31 0 0.611816 1 -19 23 0 0.640625 1 0.224365 -19 23 1 0.640625 1 0.224365 -19 23 2 0.640625 1 0.224365 -19 23 3 0.640625 1 0.224365 -19 23 4 0.640625 1 0.224365 -19 23 5 0.640625 1 0.224365 -19 23 6 0.640625 1 0.224365 -19 23 7 0.640625 1 0.224365 -19 23 8 0.640625 1 0.224365 -19 23 9 0.640625 1 0.224365 -19 23 10 0.640625 1 0.224365 -19 23 11 0.641113 1 0.224487 -19 23 12 0.641113 1 0.224487 -19 23 13 0.641113 1 0.224487 -19 23 14 0.640137 1 0.260498 -19 23 15 0.633789 1 0.35791 -19 23 16 0.624023 1 0.451904 -19 23 17 0.608887 1 0.544434 -19 23 18 0.587402 1 0.635254 -19 23 19 0.558105 1 0.721191 -19 23 20 0.520508 1 0.798828 -19 23 21 0.470947 1 0.868164 -19 23 22 0.408203 0.989746 0.926758 -19 23 23 0.327148 0.966797 0.974121 -19 23 24 0.198975 0.939453 1 -19 23 25 0 0.904297 1 -19 23 26 0 0.86377 1 -19 23 27 0 0.821289 1 -19 23 28 0 0.777832 1 -19 23 29 0 0.73584 1 -19 23 30 0 0.695801 1 -19 23 31 0 0.658203 1 -19 24 0 0.557617 1 0.2146 -19 24 1 0.557617 1 0.2146 -19 24 2 0.557617 1 0.2146 -19 24 3 0.557617 1 0.2146 -19 24 4 0.557617 1 0.2146 -19 24 5 0.557617 1 0.2146 -19 24 6 0.557617 1 0.2146 -19 24 7 0.557617 1 0.2146 -19 24 8 0.557617 1 0.2146 -19 24 9 0.557617 1 0.2146 -19 24 10 0.557617 1 0.2146 -19 24 11 0.557617 1 0.2146 -19 24 12 0.558105 1 0.2146 -19 24 13 0.558105 1 0.214722 -19 24 14 0.558105 1 0.224976 -19 24 15 0.55127 1 0.330322 -19 24 16 0.540527 1 0.426025 -19 24 17 0.524414 1 0.519043 -19 24 18 0.500488 1 0.609863 -19 24 19 0.467773 1 0.695801 -19 24 20 0.42334 1 0.774414 -19 24 21 0.362061 1 0.844727 -19 24 22 0.270508 1 0.905762 -19 24 23 0 1 0.956055 -19 24 24 0 0.988281 0.996582 -19 24 25 0 0.958496 1 -19 24 26 0 0.920898 1 -19 24 27 0 0.878418 1 -19 24 28 0 0.833984 1 -19 24 29 0 0.789062 1 -19 24 30 0 0.745605 1 -19 24 31 0 0.70459 1 -19 25 0 0.452148 1 0.204224 -19 25 1 0.452148 1 0.204224 -19 25 2 0.452148 1 0.204224 -19 25 3 0.452148 1 0.204224 -19 25 4 0.452148 1 0.204224 -19 25 5 0.452148 1 0.204224 -19 25 6 0.452148 1 0.204224 -19 25 7 0.452148 1 0.204224 -19 25 8 0.452148 1 0.204224 -19 25 9 0.452148 1 0.204346 -19 25 10 0.452393 1 0.204346 -19 25 11 0.452393 1 0.204346 -19 25 12 0.452637 1 0.204346 -19 25 13 0.453125 1 0.204468 -19 25 14 0.453613 1 0.204468 -19 25 15 0.446533 1 0.299316 -19 25 16 0.432617 1 0.397949 -19 25 17 0.411621 1 0.491455 -19 25 18 0.380127 1 0.581543 -19 25 19 0.333008 1 0.66748 -19 25 20 0.259033 1 0.746094 -19 25 21 0 1 0.817871 -19 25 22 0 1 0.880859 -19 25 23 0 1 0.933105 -19 25 24 0 1 0.977051 -19 25 25 0 1 1 -19 25 26 0 0.974121 1 -19 25 27 0 0.93457 1 -19 25 28 0 0.890625 1 -19 25 29 0 0.844238 1 -19 25 30 0 0.79834 1 -19 25 31 0 0.753418 1 -19 26 0 0.287842 1 0.193481 -19 26 1 0.287842 1 0.193481 -19 26 2 0.287842 1 0.193481 -19 26 3 0.287842 1 0.193481 -19 26 4 0.287842 1 0.193481 -19 26 5 0.287842 1 0.193481 -19 26 6 0.287842 1 0.193481 -19 26 7 0.287842 1 0.193481 -19 26 8 0.287842 1 0.193481 -19 26 9 0.288086 1 0.193481 -19 26 10 0.288086 1 0.193481 -19 26 11 0.288574 1 0.193604 -19 26 12 0.289062 1 0.193604 -19 26 13 0.289795 1 0.193726 -19 26 14 0.291016 1 0.193726 -19 26 15 0.281738 1 0.263428 -19 26 16 0.253174 1 0.367188 -19 26 17 0.200562 1 0.461182 -19 26 18 0 1 0.55127 -19 26 19 0 1 0.63623 -19 26 20 0 1 0.714844 -19 26 21 0 1 0.787109 -19 26 22 0 1 0.851562 -19 26 23 0 1 0.90625 -19 26 24 0 1 0.952148 -19 26 25 0 1 0.994629 -19 26 26 0 1 1 -19 26 27 0 0.986816 1 -19 26 28 0 0.945312 1 -19 26 29 0 0.899414 1 -19 26 30 0 0.852539 1 -19 26 31 0 0.805176 1 -19 27 0 0 1 0.182251 -19 27 1 0 1 0.182251 -19 27 2 0 1 0.182251 -19 27 3 0 1 0.182251 -19 27 4 0 1 0.182251 -19 27 5 0 1 0.182251 -19 27 6 0 1 0.182251 -19 27 7 0 1 0.182251 -19 27 8 0 1 0.182251 -19 27 9 0 1 0.182251 -19 27 10 0 1 0.182373 -19 27 11 0 1 0.182373 -19 27 12 0 1 0.182373 -19 27 13 0 1 0.182495 -19 27 14 0 1 0.182495 -19 27 15 0 1 0.220825 -19 27 16 0 1 0.333252 -19 27 17 0 1 0.428955 -19 27 18 0 1 0.518066 -19 27 19 0 1 0.602539 -19 27 20 0 1 0.680176 -19 27 21 0 1 0.752441 -19 27 22 0 1 0.817871 -19 27 23 0 1 0.874023 -19 27 24 0 1 0.922363 -19 27 25 0 1 0.967773 -19 27 26 0 1 1 -19 27 27 0 1 1 -19 27 28 0 0.996094 1 -19 27 29 0 0.952637 1 -19 27 30 0 0.905762 1 -19 27 31 0 0.857422 1 -19 28 0 0 1 0.170654 -19 28 1 0 1 0.170654 -19 28 2 0 1 0.170654 -19 28 3 0 1 0.170654 -19 28 4 0 1 0.170654 -19 28 5 0 1 0.170654 -19 28 6 0 1 0.170654 -19 28 7 0 1 0.170654 -19 28 8 0 1 0.170654 -19 28 9 0 1 0.170654 -19 28 10 0 1 0.170654 -19 28 11 0 1 0.170654 -19 28 12 0 1 0.170776 -19 28 13 0 1 0.170776 -19 28 14 0 1 0.170898 -19 28 15 0 1 0.171021 -19 28 16 0 1 0.295898 -19 28 17 0 1 0.394287 -19 28 18 0 1 0.483154 -19 28 19 0 1 0.566406 -19 28 20 0 1 0.643066 -19 28 21 0 1 0.714844 -19 28 22 0 1 0.780762 -19 28 23 0 1 0.837891 -19 28 24 0 1 0.888184 -19 28 25 0 1 0.935547 -19 28 26 0 1 0.97998 -19 28 27 0 1 1 -19 28 28 0 1 1 -19 28 29 0 1 1 -19 28 30 0 0.957031 1 -19 28 31 0 0.90918 1 -19 29 0 0 1 0.158447 -19 29 1 0 1 0.158447 -19 29 2 0 1 0.158447 -19 29 3 0 1 0.158447 -19 29 4 0 1 0.158447 -19 29 5 0 1 0.158447 -19 29 6 0 1 0.158447 -19 29 7 0 1 0.158447 -19 29 8 0 1 0.158447 -19 29 9 0 1 0.158447 -19 29 10 0 1 0.158447 -19 29 11 0 1 0.158447 -19 29 12 0 1 0.158569 -19 29 13 0 1 0.158569 -19 29 14 0 1 0.158691 -19 29 15 0 1 0.158936 -19 29 16 0 1 0.253174 -19 29 17 0 1 0.356934 -19 29 18 0 1 0.446289 -19 29 19 0 1 0.527832 -19 29 20 0 1 0.603516 -19 29 21 0 1 0.674316 -19 29 22 0 1 0.739746 -19 29 23 0 1 0.797852 -19 29 24 0 1 0.848633 -19 29 25 0 1 0.898438 -19 29 26 0 1 0.945312 -19 29 27 0 1 0.988281 -19 29 28 0 1 1 -19 29 29 0 1 1 -19 29 30 0 1 1 -19 29 31 0 0.960449 1 -19 30 0 0 1 0.145752 -19 30 1 0 1 0.145752 -19 30 2 0 1 0.145752 -19 30 3 0 1 0.145752 -19 30 4 0 1 0.145752 -19 30 5 0 1 0.145752 -19 30 6 0 1 0.145752 -19 30 7 0 1 0.145752 -19 30 8 0 1 0.145752 -19 30 9 0 1 0.145752 -19 30 10 0 1 0.145752 -19 30 11 0 1 0.145874 -19 30 12 0 1 0.145874 -19 30 13 0 1 0.145996 -19 30 14 0 1 0.146118 -19 30 15 0 1 0.14624 -19 30 16 0 1 0.20166 -19 30 17 0 1 0.31665 -19 30 18 0 1 0.407227 -19 30 19 0 1 0.488037 -19 30 20 0 1 0.562012 -19 30 21 0 1 0.631348 -19 30 22 0 1 0.695801 -19 30 23 0 1 0.753418 -19 30 24 0 1 0.805176 -19 30 25 0 1 0.855957 -19 30 26 0 1 0.905273 -19 30 27 0 1 0.95166 -19 30 28 0 1 0.993652 -19 30 29 0 1 1 -19 30 30 0 1 1 -19 30 31 0 1 1 -19 31 0 0 1 0.132812 -19 31 1 0 1 0.132812 -19 31 2 0 1 0.132812 -19 31 3 0 1 0.132812 -19 31 4 0 1 0.132812 -19 31 5 0 1 0.132812 -19 31 6 0 1 0.132812 -19 31 7 0 1 0.132812 -19 31 8 0 1 0.132812 -19 31 9 0 1 0.132812 -19 31 10 0 1 0.132812 -19 31 11 0 1 0.132812 -19 31 12 0 1 0.132812 -19 31 13 0 1 0.132935 -19 31 14 0 1 0.133057 -19 31 15 0 1 0.133301 -19 31 16 0 1 0.133545 -19 31 17 0 1 0.272705 -19 31 18 0 1 0.366455 -19 31 19 0 1 0.446533 -19 31 20 0 1 0.519043 -19 31 21 0 1 0.586426 -19 31 22 0 1 0.649902 -19 31 23 0 1 0.706543 -19 31 24 0 1 0.758301 -19 31 25 0 1 0.80957 -19 31 26 0 1 0.860352 -19 31 27 0 1 0.909668 -19 31 28 0 1 0.956055 -19 31 29 0 1 0.998047 -19 31 30 0 1 1 -19 31 31 0 1 1 -20 0 0 0.946289 0 0.0526733 -20 0 1 0.946289 0 0.0526733 -20 0 2 0.946289 0 0.0526733 -20 0 3 0.946289 0 0.0526733 -20 0 4 0.946289 0 0.0526428 -20 0 5 0.946289 0 0.0526428 -20 0 6 0.946289 0 0.0525818 -20 0 7 0.946289 0 0.0525208 -20 0 8 0.946289 0 0.0523376 -20 0 9 0.946289 0 0.0520325 -20 0 10 0.946777 0 0.0514526 -20 0 11 0.946777 0 0.0504456 -20 0 12 0.946777 0 0.0488586 -20 0 13 0.944336 0 0.0471802 -20 0 14 0.943848 0 0.248535 -20 0 15 0.956543 0 0.365234 -20 0 16 0.969238 0 0.474609 -20 0 17 0.996094 0.154053 0.597168 -20 0 18 1 0.274414 0.717773 -20 0 19 1 0.320557 0.8125 -20 0 20 0.972656 0.327881 0.881348 -20 0 21 0.925781 0.330811 0.9375 -20 0 22 0.868164 0.329834 0.975098 -20 0 23 0.805176 0.325928 0.996094 -20 0 24 0.743164 0.320557 1 -20 0 25 0.677246 0.314941 1 -20 0 26 0.608887 0.308838 1 -20 0 27 0.537598 0.303467 1 -20 0 28 0.461914 0.298584 1 -20 0 29 0.377197 0.294678 1 -20 0 30 0.266602 0.291748 1 -20 0 31 0 0.290039 1 -20 1 0 0.946289 0 0.0526428 -20 1 1 0.946289 0 0.0526428 -20 1 2 0.946289 0 0.0526428 -20 1 3 0.946289 0 0.0526428 -20 1 4 0.946289 0 0.0526428 -20 1 5 0.946289 0 0.0526123 -20 1 6 0.946289 0 0.0525818 -20 1 7 0.946289 0 0.0524902 -20 1 8 0.946289 0 0.0523376 -20 1 9 0.946289 0 0.052002 -20 1 10 0.946777 0 0.0514526 -20 1 11 0.946777 0 0.050415 -20 1 12 0.946777 0 0.0488281 -20 1 13 0.944336 0 0.0471497 -20 1 14 0.943848 0 0.248535 -20 1 15 0.956543 0 0.365234 -20 1 16 0.969238 0 0.474609 -20 1 17 0.996094 0.154175 0.597168 -20 1 18 1 0.274414 0.717773 -20 1 19 1 0.320557 0.8125 -20 1 20 0.972656 0.327881 0.881348 -20 1 21 0.925781 0.330811 0.9375 -20 1 22 0.868164 0.329834 0.975098 -20 1 23 0.805176 0.325928 0.996094 -20 1 24 0.743164 0.320801 1 -20 1 25 0.677246 0.314941 1 -20 1 26 0.608887 0.308838 1 -20 1 27 0.537598 0.303467 1 -20 1 28 0.461914 0.298584 1 -20 1 29 0.377197 0.294678 1 -20 1 30 0.266602 0.291992 1 -20 1 31 0 0.290039 1 -20 2 0 0.946289 0 0.0526123 -20 2 1 0.946289 0 0.0526123 -20 2 2 0.946289 0 0.0526123 -20 2 3 0.946289 0 0.0526123 -20 2 4 0.946289 0 0.0525818 -20 2 5 0.946289 0 0.0525818 -20 2 6 0.946289 0 0.0525208 -20 2 7 0.946289 0 0.0524597 -20 2 8 0.946289 0 0.0522766 -20 2 9 0.946777 0 0.0519714 -20 2 10 0.946777 0 0.0513916 -20 2 11 0.946777 0 0.050354 -20 2 12 0.946777 0 0.0487671 -20 2 13 0.944336 0 0.0470886 -20 2 14 0.943848 0 0.248535 -20 2 15 0.956543 0 0.365234 -20 2 16 0.969238 0 0.474609 -20 2 17 0.996094 0.154297 0.597168 -20 2 18 1 0.274414 0.717773 -20 2 19 1 0.320557 0.8125 -20 2 20 0.972656 0.327881 0.881348 -20 2 21 0.925781 0.330811 0.9375 -20 2 22 0.868164 0.329834 0.975098 -20 2 23 0.805176 0.325928 0.996094 -20 2 24 0.743164 0.320801 1 -20 2 25 0.677246 0.314941 1 -20 2 26 0.608887 0.308838 1 -20 2 27 0.537598 0.303467 1 -20 2 28 0.461914 0.298584 1 -20 2 29 0.377197 0.294678 1 -20 2 30 0.266602 0.291992 1 -20 2 31 0 0.290039 1 -20 3 0 0.946289 0 0.0525513 -20 3 1 0.946289 0 0.0525513 -20 3 2 0.946289 0 0.0525513 -20 3 3 0.946289 0 0.0525208 -20 3 4 0.946289 0 0.0525208 -20 3 5 0.946289 0 0.0524902 -20 3 6 0.946289 0 0.0524597 -20 3 7 0.946289 0 0.0523682 -20 3 8 0.946289 0 0.0522156 -20 3 9 0.946777 0 0.0519104 -20 3 10 0.946777 0 0.0513306 -20 3 11 0.946777 0 0.050293 -20 3 12 0.946777 0 0.0486755 -20 3 13 0.944336 0 0.0469971 -20 3 14 0.943848 0 0.248535 -20 3 15 0.956543 0 0.365234 -20 3 16 0.969238 0 0.474609 -20 3 17 0.996094 0.154541 0.597168 -20 3 18 1 0.274658 0.717773 -20 3 19 1 0.320801 0.8125 -20 3 20 0.972656 0.328125 0.881348 -20 3 21 0.925781 0.330811 0.9375 -20 3 22 0.868164 0.329834 0.975098 -20 3 23 0.805176 0.325928 0.996094 -20 3 24 0.743164 0.320801 1 -20 3 25 0.677246 0.314941 1 -20 3 26 0.608887 0.309082 1 -20 3 27 0.537598 0.303467 1 -20 3 28 0.461914 0.298584 1 -20 3 29 0.377197 0.294678 1 -20 3 30 0.266602 0.291992 1 -20 3 31 0 0.290039 1 -20 4 0 0.946289 0 0.0523987 -20 4 1 0.946289 0 0.0523987 -20 4 2 0.946289 0 0.0523987 -20 4 3 0.946289 0 0.0523987 -20 4 4 0.946289 0 0.0523682 -20 4 5 0.946289 0 0.0523682 -20 4 6 0.946289 0 0.0523071 -20 4 7 0.946289 0 0.0522461 -20 4 8 0.946289 0 0.052063 -20 4 9 0.946777 0 0.0517578 -20 4 10 0.946777 0 0.051178 -20 4 11 0.946777 0 0.0501404 -20 4 12 0.946777 0 0.0485229 -20 4 13 0.944336 0 0.0468445 -20 4 14 0.943848 0 0.248535 -20 4 15 0.956543 0 0.365234 -20 4 16 0.969238 0 0.474609 -20 4 17 0.996094 0.155029 0.597168 -20 4 18 1 0.274658 0.717773 -20 4 19 1 0.320801 0.8125 -20 4 20 0.972656 0.328125 0.881348 -20 4 21 0.925781 0.331055 0.9375 -20 4 22 0.868164 0.330078 0.975098 -20 4 23 0.805176 0.325928 0.996094 -20 4 24 0.743164 0.320801 1 -20 4 25 0.677246 0.314941 1 -20 4 26 0.608887 0.309082 1 -20 4 27 0.537598 0.303467 1 -20 4 28 0.461914 0.298584 1 -20 4 29 0.376953 0.294922 1 -20 4 30 0.266602 0.291992 1 -20 4 31 0 0.290039 1 -20 5 0 0.946289 0 0.052124 -20 5 1 0.946289 0 0.052124 -20 5 2 0.946289 0 0.052124 -20 5 3 0.946289 0 0.052124 -20 5 4 0.946289 0 0.0520935 -20 5 5 0.946289 0 0.0520935 -20 5 6 0.946289 0 0.0520325 -20 5 7 0.946289 0 0.0519409 -20 5 8 0.946289 0 0.0517883 -20 5 9 0.946777 0 0.0514832 -20 5 10 0.946777 0 0.0509033 -20 5 11 0.946777 0 0.0498352 -20 5 12 0.946777 0 0.0482178 -20 5 13 0.944336 0 0.0465088 -20 5 14 0.943848 0 0.248535 -20 5 15 0.956543 0 0.365234 -20 5 16 0.969238 0 0.474609 -20 5 17 0.996094 0.156006 0.597168 -20 5 18 1 0.275146 0.717773 -20 5 19 1 0.321289 0.8125 -20 5 20 0.972656 0.328613 0.881348 -20 5 21 0.925781 0.331299 0.9375 -20 5 22 0.867676 0.330322 0.975098 -20 5 23 0.805176 0.326172 0.996094 -20 5 24 0.743164 0.321045 1 -20 5 25 0.677246 0.315186 1 -20 5 26 0.608887 0.309326 1 -20 5 27 0.537598 0.303711 1 -20 5 28 0.461914 0.298828 1 -20 5 29 0.376953 0.294922 1 -20 5 30 0.266602 0.291992 1 -20 5 31 0 0.290039 1 -20 6 0 0.946289 0 0.0516052 -20 6 1 0.946289 0 0.0516052 -20 6 2 0.946289 0 0.0516052 -20 6 3 0.946289 0 0.0515747 -20 6 4 0.946289 0 0.0515747 -20 6 5 0.946289 0 0.0515442 -20 6 6 0.946289 0 0.0515137 -20 6 7 0.946289 0 0.0514221 -20 6 8 0.946777 0 0.0512695 -20 6 9 0.946777 0 0.0509338 -20 6 10 0.946777 0 0.050354 -20 6 11 0.946777 0 0.0492859 -20 6 12 0.946777 0 0.0476074 -20 6 13 0.944336 0 0.0458984 -20 6 14 0.943848 0 0.248535 -20 6 15 0.957031 0 0.365234 -20 6 16 0.969238 0 0.474609 -20 6 17 0.996094 0.157715 0.597168 -20 6 18 1 0.275879 0.717773 -20 6 19 1 0.321777 0.8125 -20 6 20 0.972656 0.329102 0.881348 -20 6 21 0.925781 0.331787 0.9375 -20 6 22 0.867676 0.330811 0.975098 -20 6 23 0.805176 0.32666 0.996094 -20 6 24 0.743164 0.321533 1 -20 6 25 0.677246 0.31543 1 -20 6 26 0.608887 0.30957 1 -20 6 27 0.537598 0.303955 1 -20 6 28 0.461914 0.299072 1 -20 6 29 0.376953 0.295166 1 -20 6 30 0.266602 0.292236 1 -20 6 31 0 0.290283 1 -20 7 0 0.946777 0 0.0505371 -20 7 1 0.946777 0 0.0505371 -20 7 2 0.946777 0 0.0505371 -20 7 3 0.946777 0 0.0505371 -20 7 4 0.946777 0 0.0505066 -20 7 5 0.946777 0 0.0504761 -20 7 6 0.946777 0 0.0504456 -20 7 7 0.946777 0 0.050354 -20 7 8 0.946777 0 0.0501709 -20 7 9 0.946777 0 0.0498657 -20 7 10 0.946777 0 0.0492249 -20 7 11 0.946777 0 0.0481262 -20 7 12 0.946777 0 0.0464172 -20 7 13 0.944336 0 0.0446472 -20 7 14 0.943848 0 0.248413 -20 7 15 0.957031 0 0.365234 -20 7 16 0.969238 0 0.474365 -20 7 17 0.996094 0.161133 0.597168 -20 7 18 1 0.277344 0.717773 -20 7 19 1 0.322998 0.8125 -20 7 20 0.972656 0.330322 0.881348 -20 7 21 0.925781 0.332764 0.9375 -20 7 22 0.867676 0.331543 0.975098 -20 7 23 0.805176 0.327393 0.996094 -20 7 24 0.742676 0.322266 1 -20 7 25 0.677246 0.316162 1 -20 7 26 0.608398 0.310059 1 -20 7 27 0.537109 0.304443 1 -20 7 28 0.461914 0.299561 1 -20 7 29 0.376953 0.295654 1 -20 7 30 0.266357 0.29248 1 -20 7 31 0 0.290527 1 -20 8 0 0.946777 0 0.0483398 -20 8 1 0.946777 0 0.0483398 -20 8 2 0.946777 0 0.0483398 -20 8 3 0.946777 0 0.0483398 -20 8 4 0.946777 0 0.0483398 -20 8 5 0.946777 0 0.0483093 -20 8 6 0.946777 0 0.0482483 -20 8 7 0.946777 0 0.0481567 -20 8 8 0.946777 0 0.0479736 -20 8 9 0.946777 0 0.0476074 -20 8 10 0.946777 0 0.0469666 -20 8 11 0.947266 0 0.0457458 -20 8 12 0.946777 0 0.0438843 -20 8 13 0.944336 0 0.0419922 -20 8 14 0.944336 0 0.248413 -20 8 15 0.956543 0 0.365234 -20 8 16 0.969238 0 0.474365 -20 8 17 0.995605 0.167358 0.597168 -20 8 18 1 0.280273 0.717773 -20 8 19 1 0.325439 0.8125 -20 8 20 0.972656 0.332275 0.881348 -20 8 21 0.925781 0.334717 0.9375 -20 8 22 0.867676 0.333496 0.975098 -20 8 23 0.805176 0.329102 0.996094 -20 8 24 0.742676 0.32373 1 -20 8 25 0.676758 0.317383 1 -20 8 26 0.608398 0.311279 1 -20 8 27 0.537109 0.30542 1 -20 8 28 0.46167 0.300293 1 -20 8 29 0.376709 0.296387 1 -20 8 30 0.266113 0.293213 1 -20 8 31 0 0.291016 1 -20 9 0 0.947266 0 0.0436401 -20 9 1 0.947266 0 0.0436401 -20 9 2 0.947266 0 0.0436401 -20 9 3 0.947266 0 0.0436401 -20 9 4 0.947266 0 0.0436096 -20 9 5 0.947266 0 0.0435791 -20 9 6 0.947266 0 0.0435181 -20 9 7 0.947266 0 0.0434265 -20 9 8 0.947266 0 0.0431824 -20 9 9 0.947266 0 0.0427551 -20 9 10 0.947266 0 0.0419617 -20 9 11 0.947266 0 0.0405273 -20 9 12 0.947266 0 0.038208 -20 9 13 0.944824 0 0.0359802 -20 9 14 0.944336 0 0.248413 -20 9 15 0.956543 0 0.36499 -20 9 16 0.969238 0 0.474365 -20 9 17 0.995117 0.178467 0.59668 -20 9 18 1 0.285645 0.717285 -20 9 19 1 0.330078 0.812012 -20 9 20 0.972168 0.336426 0.881348 -20 9 21 0.925293 0.338623 0.9375 -20 9 22 0.867676 0.336914 0.975098 -20 9 23 0.804688 0.332031 0.996094 -20 9 24 0.742676 0.326416 1 -20 9 25 0.676758 0.319824 1 -20 9 26 0.608398 0.313232 1 -20 9 27 0.537109 0.307129 1 -20 9 28 0.461426 0.302002 1 -20 9 29 0.376465 0.297607 1 -20 9 30 0.265625 0.294434 1 -20 9 31 0 0.292236 1 -20 10 0 0.947754 0 0.0319214 -20 10 1 0.947754 0 0.0319214 -20 10 2 0.947754 0 0.0319214 -20 10 3 0.947754 0 0.0318909 -20 10 4 0.947754 0 0.0318604 -20 10 5 0.947754 0 0.0318298 -20 10 6 0.947754 0 0.0317383 -20 10 7 0.947754 0 0.0315552 -20 10 8 0.947754 0 0.0311737 -20 10 9 0.947754 0 0.0304413 -20 10 10 0.947754 0 0.0290375 -20 10 11 0.948242 0 0.0262604 -20 10 12 0.947754 0 0.0210571 -20 10 13 0.945312 0 0.0147095 -20 10 14 0.944336 0 0.248413 -20 10 15 0.956543 0 0.364502 -20 10 16 0.96875 0.0324097 0.473877 -20 10 17 0.994629 0.196167 0.596191 -20 10 18 1 0.295166 0.717285 -20 10 19 1 0.337891 0.812012 -20 10 20 0.972168 0.34375 0.881348 -20 10 21 0.924805 0.345215 0.9375 -20 10 22 0.867188 0.342773 0.975098 -20 10 23 0.804199 0.337646 0.996094 -20 10 24 0.742188 0.331299 1 -20 10 25 0.67627 0.324219 1 -20 10 26 0.60791 0.317139 1 -20 10 27 0.536621 0.310547 1 -20 10 28 0.460938 0.304932 1 -20 10 29 0.375732 0.300293 1 -20 10 30 0.264648 0.296631 1 -20 10 31 0 0.294189 1 -20 11 0 0.94873 0.112 0 -20 11 1 0.94873 0.112 0 -20 11 2 0.94873 0.112 0 -20 11 3 0.94873 0.112061 0 -20 11 4 0.94873 0.112122 0 -20 11 5 0.94873 0.112244 0 -20 11 6 0.94873 0.112549 0 -20 11 7 0.94873 0.113098 0 -20 11 8 0.94873 0.114075 0 -20 11 9 0.94873 0.116028 0 -20 11 10 0.94873 0.119385 0 -20 11 11 0.949219 0.124939 0 -20 11 12 0.949219 0.132446 0 -20 11 13 0.946289 0.136353 0.0213013 -20 11 14 0.945312 0.12439 0.248657 -20 11 15 0.956543 0.125854 0.36377 -20 11 16 0.96875 0.139038 0.473633 -20 11 17 0.993164 0.222168 0.595215 -20 11 18 1 0.310547 0.716797 -20 11 19 1 0.351074 0.812012 -20 11 20 0.971191 0.355957 0.881348 -20 11 21 0.924316 0.356445 0.9375 -20 11 22 0.866211 0.353027 0.975098 -20 11 23 0.803711 0.34668 0.996094 -20 11 24 0.741211 0.339355 1 -20 11 25 0.675293 0.331543 1 -20 11 26 0.606934 0.32373 1 -20 11 27 0.535645 0.316406 1 -20 11 28 0.459961 0.310059 1 -20 11 29 0.374756 0.304688 1 -20 11 30 0.262939 0.300537 1 -20 11 31 0 0.297607 1 -20 12 0 0.950684 0.193604 0 -20 12 1 0.950684 0.193604 0 -20 12 2 0.950684 0.193604 0 -20 12 3 0.950684 0.193604 0 -20 12 4 0.950684 0.193604 0 -20 12 5 0.950684 0.193726 0 -20 12 6 0.950684 0.193848 0 -20 12 7 0.950684 0.194092 0 -20 12 8 0.950684 0.194458 0 -20 12 9 0.950684 0.195312 0 -20 12 10 0.950684 0.196777 0 -20 12 11 0.951172 0.199463 0 -20 12 12 0.951172 0.203247 0 -20 12 13 0.947754 0.203735 0.0549011 -20 12 14 0.947266 0.196533 0.249512 -20 12 15 0.956543 0.195679 0.363037 -20 12 16 0.968262 0.203613 0.473145 -20 12 17 0.990723 0.257812 0.59375 -20 12 18 1 0.334229 0.71582 -20 12 19 1 0.371826 0.812012 -20 12 20 0.969727 0.375488 0.881348 -20 12 21 0.922852 0.374512 0.9375 -20 12 22 0.864746 0.369385 0.975098 -20 12 23 0.802246 0.361572 0.996094 -20 12 24 0.739746 0.352783 1 -20 12 25 0.673828 0.343506 1 -20 12 26 0.605469 0.334229 1 -20 12 27 0.53418 0.325928 1 -20 12 28 0.458496 0.318359 1 -20 12 29 0.372803 0.312256 1 -20 12 30 0.26001 0.307129 1 -20 12 31 0 0.303223 1 -20 13 0 0.954102 0.265381 0 -20 13 1 0.954102 0.265381 0 -20 13 2 0.954102 0.265381 0 -20 13 3 0.954102 0.265381 0 -20 13 4 0.954102 0.265381 0 -20 13 5 0.954102 0.265381 0 -20 13 6 0.954102 0.265625 0 -20 13 7 0.954102 0.265625 0 -20 13 8 0.95459 0.265869 0 -20 13 9 0.95459 0.266602 0 -20 13 10 0.95459 0.267334 0 -20 13 11 0.95459 0.269043 0 -20 13 12 0.955078 0.271484 0 -20 13 13 0.951172 0.270508 0.0842896 -20 13 14 0.950684 0.265137 0.252197 -20 13 15 0.95752 0.262939 0.362549 -20 13 16 0.968262 0.268799 0.472656 -20 13 17 0.986816 0.303711 0.591309 -20 13 18 1 0.36792 0.713867 -20 13 19 1 0.402588 0.811523 -20 13 20 0.967773 0.404541 0.881348 -20 13 21 0.920898 0.401367 0.9375 -20 13 22 0.862793 0.394043 0.975098 -20 13 23 0.799805 0.383789 0.996094 -20 13 24 0.737305 0.373047 1 -20 13 25 0.671875 0.361816 1 -20 13 26 0.603027 0.35083 1 -20 13 27 0.531738 0.340576 1 -20 13 28 0.456055 0.331299 1 -20 13 29 0.369873 0.32373 1 -20 13 30 0.255371 0.317383 1 -20 13 31 0 0.3125 1 -20 14 0 0.960938 0.341064 0 -20 14 1 0.960938 0.341064 0 -20 14 2 0.960938 0.341064 0 -20 14 3 0.960938 0.341064 0 -20 14 4 0.960938 0.341064 0 -20 14 5 0.960938 0.341064 0 -20 14 6 0.960938 0.341064 0 -20 14 7 0.960938 0.341309 0 -20 14 8 0.960938 0.341553 0 -20 14 9 0.960938 0.341797 0 -20 14 10 0.960938 0.342529 0 -20 14 11 0.961426 0.343506 0 -20 14 12 0.961426 0.345459 0 -20 14 13 0.95752 0.343262 0.119568 -20 14 14 0.957031 0.339355 0.259277 -20 14 15 0.959961 0.336182 0.364014 -20 14 16 0.969238 0.341064 0.473633 -20 14 17 0.980957 0.359863 0.587402 -20 14 18 1 0.412354 0.710938 -20 14 19 0.999512 0.44458 0.811035 -20 14 20 0.963867 0.44458 0.881348 -20 14 21 0.916992 0.438965 0.9375 -20 14 22 0.858887 0.428711 0.975098 -20 14 23 0.795898 0.415771 0.995605 -20 14 24 0.733398 0.4021 1 -20 14 25 0.667969 0.388184 1 -20 14 26 0.599609 0.374512 1 -20 14 27 0.527832 0.361816 1 -20 14 28 0.451904 0.350586 1 -20 14 29 0.36499 0.34082 1 -20 14 30 0.247314 0.332764 1 -20 14 31 0 0.325928 1 -20 15 0 0.97168 0.424561 0 -20 15 1 0.97168 0.424561 0 -20 15 2 0.97168 0.424561 0 -20 15 3 0.97168 0.424561 0 -20 15 4 0.97168 0.424561 0 -20 15 5 0.97168 0.424561 0 -20 15 6 0.97168 0.424561 0 -20 15 7 0.97168 0.424561 0 -20 15 8 0.97168 0.424805 0 -20 15 9 0.972168 0.425049 0 -20 15 10 0.972168 0.425537 0 -20 15 11 0.972168 0.42627 0 -20 15 12 0.972656 0.427734 0 -20 15 13 0.969727 0.425781 0.161743 -20 15 14 0.968262 0.422852 0.274414 -20 15 15 0.966309 0.418945 0.370605 -20 15 16 0.967285 0.41748 0.472412 -20 15 17 0.973145 0.427002 0.583008 -20 15 18 0.993652 0.467285 0.706055 -20 15 19 0.993164 0.498291 0.80957 -20 15 20 0.958008 0.496338 0.880371 -20 15 21 0.911133 0.488037 0.937012 -20 15 22 0.853027 0.474365 0.974609 -20 15 23 0.790039 0.457764 0.995117 -20 15 24 0.727539 0.440918 1 -20 15 25 0.662109 0.423584 1 -20 15 26 0.59375 0.406982 1 -20 15 27 0.521973 0.391357 1 -20 15 28 0.445557 0.377197 1 -20 15 29 0.357178 0.36499 1 -20 15 30 0.234009 0.354492 1 -20 15 31 0 0.345459 1 -20 16 0 0.988281 0.517578 0.111267 -20 16 1 0.988281 0.517578 0.111267 -20 16 2 0.988281 0.517578 0.111267 -20 16 3 0.988281 0.517578 0.111267 -20 16 4 0.988281 0.517578 0.111267 -20 16 5 0.988281 0.517578 0.111328 -20 16 6 0.988281 0.517578 0.111328 -20 16 7 0.988281 0.517578 0.11145 -20 16 8 0.988281 0.517578 0.111572 -20 16 9 0.988281 0.518066 0.111877 -20 16 10 0.98877 0.518066 0.112427 -20 16 11 0.98877 0.519043 0.113281 -20 16 12 0.989258 0.52002 0.114807 -20 16 13 0.987305 0.519531 0.209839 -20 16 14 0.983887 0.51709 0.300537 -20 16 15 0.978027 0.513184 0.387207 -20 16 16 0.969727 0.507812 0.478027 -20 16 17 0.967285 0.508789 0.581055 -20 16 18 0.976562 0.53125 0.696777 -20 16 19 0.981934 0.562988 0.806152 -20 16 20 0.948242 0.55957 0.878906 -20 16 21 0.901855 0.54834 0.936035 -20 16 22 0.84375 0.530762 0.973633 -20 16 23 0.780762 0.510254 0.994141 -20 16 24 0.718262 0.489502 1 -20 16 25 0.65332 0.46875 1 -20 16 26 0.584961 0.448486 1 -20 16 27 0.513184 0.429443 1 -20 16 28 0.435791 0.412109 1 -20 16 29 0.344971 0.396729 1 -20 16 30 0.211792 0.383301 1 -20 16 31 0 0.371582 1 -20 17 0 1 0.617676 0.207397 -20 17 1 1 0.617676 0.207397 -20 17 2 1 0.617676 0.207397 -20 17 3 1 0.617676 0.207397 -20 17 4 1 0.617676 0.207397 -20 17 5 1 0.617676 0.207397 -20 17 6 1 0.617676 0.207397 -20 17 7 1 0.617676 0.20752 -20 17 8 1 0.617676 0.20752 -20 17 9 1 0.618164 0.207642 -20 17 10 1 0.618164 0.207764 -20 17 11 1 0.618652 0.20813 -20 17 12 1 0.619629 0.208618 -20 17 13 1 0.619629 0.255615 -20 17 14 1 0.618652 0.333252 -20 17 15 0.993164 0.616211 0.41333 -20 17 16 0.980469 0.610352 0.496826 -20 17 17 0.961426 0.600098 0.583008 -20 17 18 0.953613 0.603027 0.684082 -20 17 19 0.963379 0.633301 0.799805 -20 17 20 0.934082 0.630859 0.875977 -20 17 21 0.888184 0.616699 0.933594 -20 17 22 0.82959 0.595215 0.970703 -20 17 23 0.766602 0.570312 0.991211 -20 17 24 0.705078 0.545898 1 -20 17 25 0.640625 0.521484 1 -20 17 26 0.572754 0.497559 1 -20 17 27 0.500488 0.475098 1 -20 17 28 0.421875 0.454346 1 -20 17 29 0.326904 0.435791 1 -20 17 30 0.171875 0.419189 1 -20 17 31 0 0.404297 1 -20 18 0 1 0.717773 0.258057 -20 18 1 1 0.717773 0.258057 -20 18 2 1 0.717773 0.258057 -20 18 3 1 0.717773 0.258057 -20 18 4 1 0.717773 0.258057 -20 18 5 1 0.717773 0.258057 -20 18 6 1 0.717773 0.258057 -20 18 7 1 0.717773 0.258057 -20 18 8 1 0.717773 0.258057 -20 18 9 1 0.717773 0.258057 -20 18 10 1 0.718262 0.258301 -20 18 11 1 0.718262 0.258301 -20 18 12 1 0.719238 0.258545 -20 18 13 1 0.719727 0.285156 -20 18 14 1 0.719727 0.358643 -20 18 15 1 0.719238 0.437256 -20 18 16 0.990234 0.71582 0.520508 -20 18 17 0.969238 0.707031 0.603516 -20 18 18 0.938477 0.690918 0.682129 -20 18 19 0.933594 0.702637 0.785645 -20 18 20 0.913086 0.706055 0.870117 -20 18 21 0.867676 0.688965 0.928223 -20 18 22 0.809082 0.663086 0.965332 -20 18 23 0.74707 0.634277 0.986816 -20 18 24 0.687012 0.606934 1 -20 18 25 0.623535 0.57959 1 -20 18 26 0.556152 0.552246 1 -20 18 27 0.483398 0.526855 1 -20 18 28 0.402344 0.50293 1 -20 18 29 0.300049 0.480713 1 -20 18 30 0.0489502 0.460693 1 -20 18 31 0 0.442383 1 -20 19 0 1 0.810547 0.279297 -20 19 1 1 0.810547 0.279297 -20 19 2 1 0.810547 0.279297 -20 19 3 1 0.810547 0.279297 -20 19 4 1 0.810547 0.279297 -20 19 5 1 0.810547 0.279297 -20 19 6 1 0.810547 0.279297 -20 19 7 1 0.810547 0.279297 -20 19 8 1 0.810547 0.279297 -20 19 9 1 0.810547 0.279297 -20 19 10 1 0.811035 0.279297 -20 19 11 1 0.811035 0.279297 -20 19 12 1 0.811523 0.279297 -20 19 13 1 0.812012 0.289795 -20 19 14 0.99707 0.812012 0.36377 -20 19 15 0.991211 0.811523 0.443848 -20 19 16 0.982422 0.810547 0.530273 -20 19 17 0.966797 0.806641 0.618652 -20 19 18 0.940918 0.796387 0.70166 -20 19 19 0.900879 0.775391 0.771973 -20 19 20 0.884766 0.780273 0.861328 -20 19 21 0.838867 0.759766 0.918945 -20 19 22 0.78125 0.730469 0.956543 -20 19 23 0.722168 0.700195 0.980957 -20 19 24 0.664062 0.670898 0.998047 -20 19 25 0.602051 0.641113 1 -20 19 26 0.535156 0.611328 1 -20 19 27 0.461426 0.583008 1 -20 19 28 0.375732 0.555664 1 -20 19 29 0.259521 0.529785 1 -20 19 30 0 0.506348 1 -20 19 31 0 0.484131 1 -20 20 0 0.970703 0.891113 0.279541 -20 20 1 0.970703 0.891113 0.279541 -20 20 2 0.970703 0.891113 0.279541 -20 20 3 0.970703 0.891113 0.279541 -20 20 4 0.970703 0.891113 0.279541 -20 20 5 0.970703 0.891113 0.279541 -20 20 6 0.970703 0.891113 0.279541 -20 20 7 0.970703 0.891113 0.279541 -20 20 8 0.970703 0.891113 0.279541 -20 20 9 0.970703 0.891113 0.279541 -20 20 10 0.970703 0.891113 0.279785 -20 20 11 0.970703 0.891602 0.279785 -20 20 12 0.970703 0.891602 0.279785 -20 20 13 0.970703 0.89209 0.279785 -20 20 14 0.967773 0.892578 0.351318 -20 20 15 0.962402 0.89209 0.434326 -20 20 16 0.953613 0.890625 0.522949 -20 20 17 0.938965 0.887207 0.613281 -20 20 18 0.917969 0.880371 0.701172 -20 20 19 0.888184 0.868164 0.781738 -20 20 20 0.849121 0.849121 0.849121 -20 20 21 0.803711 0.826172 0.90625 -20 20 22 0.75 0.797363 0.948242 -20 20 23 0.694336 0.766602 0.977539 -20 20 24 0.638184 0.736328 0.997559 -20 20 25 0.57666 0.70459 1 -20 20 26 0.508789 0.671875 1 -20 20 27 0.431396 0.639648 1 -20 20 28 0.337646 0.608887 1 -20 20 29 0.188721 0.579102 1 -20 20 30 0 0.551758 1 -20 20 31 0 0.525879 1 -20 21 0 0.919922 0.953613 0.272461 -20 21 1 0.919922 0.953613 0.272461 -20 21 2 0.919922 0.953613 0.272461 -20 21 3 0.919922 0.953613 0.272461 -20 21 4 0.919922 0.953613 0.272461 -20 21 5 0.919922 0.953613 0.272461 -20 21 6 0.919922 0.953613 0.272461 -20 21 7 0.919922 0.953613 0.272461 -20 21 8 0.919922 0.953613 0.272461 -20 21 9 0.919922 0.953613 0.272461 -20 21 10 0.919922 0.953613 0.272461 -20 21 11 0.919922 0.954102 0.272461 -20 21 12 0.919922 0.954102 0.272461 -20 21 13 0.919922 0.95459 0.272461 -20 21 14 0.917969 0.955078 0.328125 -20 21 15 0.912598 0.955078 0.414307 -20 21 16 0.904297 0.953613 0.503906 -20 21 17 0.890137 0.950195 0.594727 -20 21 18 0.869141 0.942383 0.682129 -20 21 19 0.839844 0.928711 0.761719 -20 21 20 0.805176 0.912598 0.833008 -20 21 21 0.768555 0.896973 0.899414 -20 21 22 0.71875 0.870117 0.947266 -20 21 23 0.663574 0.836914 0.978027 -20 21 24 0.607422 0.804199 1 -20 21 25 0.544434 0.769531 1 -20 21 26 0.473877 0.733887 1 -20 21 27 0.390625 0.698242 1 -20 21 28 0.281006 0.663574 1 -20 21 29 0 0.630371 1 -20 21 30 0 0.599121 1 -20 21 31 0 0.569824 1 -20 22 0 0.855957 0.999512 0.262207 -20 22 1 0.855957 0.999512 0.262207 -20 22 2 0.855957 0.999512 0.262207 -20 22 3 0.855957 0.999512 0.262207 -20 22 4 0.855957 0.999512 0.262207 -20 22 5 0.855957 0.999512 0.262207 -20 22 6 0.855957 0.999512 0.262207 -20 22 7 0.855957 0.999512 0.262207 -20 22 8 0.855957 0.999512 0.262207 -20 22 9 0.855957 1 0.262207 -20 22 10 0.855957 1 0.262207 -20 22 11 0.855957 1 0.262207 -20 22 12 0.855957 1 0.262207 -20 22 13 0.855957 1 0.262207 -20 22 14 0.854492 1 0.299072 -20 22 15 0.849609 1 0.388672 -20 22 16 0.841797 1 0.479248 -20 22 17 0.828613 0.997559 0.569824 -20 22 18 0.80957 0.990723 0.657227 -20 22 19 0.783203 0.980469 0.73877 -20 22 20 0.753418 0.96875 0.813965 -20 22 21 0.718262 0.954102 0.881836 -20 22 22 0.67627 0.935059 0.939453 -20 22 23 0.626465 0.908203 0.97998 -20 22 24 0.570312 0.875 1 -20 22 25 0.505371 0.838379 1 -20 22 26 0.429443 0.799316 1 -20 22 27 0.333984 0.760254 1 -20 22 28 0.174683 0.721191 1 -20 22 29 0 0.684082 1 -20 22 30 0 0.648926 1 -20 22 31 0 0.615723 1 -20 23 0 0.787598 1 0.251221 -20 23 1 0.787598 1 0.251221 -20 23 2 0.787598 1 0.251221 -20 23 3 0.787598 1 0.251221 -20 23 4 0.787598 1 0.251221 -20 23 5 0.787598 1 0.251221 -20 23 6 0.787598 1 0.251221 -20 23 7 0.787598 1 0.251221 -20 23 8 0.787598 1 0.251221 -20 23 9 0.787598 1 0.251221 -20 23 10 0.787598 1 0.251221 -20 23 11 0.787598 1 0.251465 -20 23 12 0.787598 1 0.251465 -20 23 13 0.787598 1 0.251465 -20 23 14 0.787109 1 0.267334 -20 23 15 0.782715 1 0.361572 -20 23 16 0.775391 1 0.453369 -20 23 17 0.763672 1 0.543945 -20 23 18 0.746582 1 0.632324 -20 23 19 0.723633 1 0.71582 -20 23 20 0.695801 1 0.791992 -20 23 21 0.661621 1 0.861816 -20 23 22 0.620117 0.984863 0.921387 -20 23 23 0.57373 0.963867 0.969727 -20 23 24 0.520508 0.9375 1 -20 23 25 0.453125 0.902832 1 -20 23 26 0.367676 0.862793 1 -20 23 27 0.241821 0.820801 1 -20 23 28 0 0.778809 1 -20 23 29 0 0.737793 1 -20 23 30 0 0.698242 1 -20 23 31 0 0.661133 1 -20 24 0 0.717773 1 0.240845 -20 24 1 0.717773 1 0.240845 -20 24 2 0.717773 1 0.240845 -20 24 3 0.717773 1 0.240845 -20 24 4 0.717773 1 0.240845 -20 24 5 0.717773 1 0.240845 -20 24 6 0.717773 1 0.240845 -20 24 7 0.717773 1 0.240845 -20 24 8 0.717773 1 0.240845 -20 24 9 0.717773 1 0.240845 -20 24 10 0.717773 1 0.240845 -20 24 11 0.717773 1 0.240845 -20 24 12 0.717773 1 0.240845 -20 24 13 0.717773 1 0.240967 -20 24 14 0.718262 1 0.240967 -20 24 15 0.713867 1 0.333984 -20 24 16 0.707031 1 0.427734 -20 24 17 0.696289 1 0.519043 -20 24 18 0.680176 1 0.607422 -20 24 19 0.658691 1 0.691406 -20 24 20 0.631836 1 0.769043 -20 24 21 0.597168 1 0.839355 -20 24 22 0.555664 1 0.900879 -20 24 23 0.507324 1 0.952148 -20 24 24 0.451904 0.986816 0.993652 -20 24 25 0.378174 0.95752 1 -20 24 26 0.267578 0.92041 1 -20 24 27 0 0.878418 1 -20 24 28 0 0.834473 1 -20 24 29 0 0.790039 1 -20 24 30 0 0.747559 1 -20 24 31 0 0.706543 1 -20 25 0 0.638184 1 0.22998 -20 25 1 0.638184 1 0.22998 -20 25 2 0.638184 1 0.22998 -20 25 3 0.638184 1 0.22998 -20 25 4 0.638184 1 0.22998 -20 25 5 0.638184 1 0.22998 -20 25 6 0.638184 1 0.22998 -20 25 7 0.638184 1 0.22998 -20 25 8 0.638184 1 0.22998 -20 25 9 0.638184 1 0.22998 -20 25 10 0.638184 1 0.22998 -20 25 11 0.638184 1 0.22998 -20 25 12 0.638184 1 0.22998 -20 25 13 0.638184 1 0.230103 -20 25 14 0.638672 1 0.230103 -20 25 15 0.635254 1 0.303467 -20 25 16 0.628418 1 0.399902 -20 25 17 0.617188 1 0.491455 -20 25 18 0.601562 1 0.580078 -20 25 19 0.57959 1 0.664551 -20 25 20 0.55127 1 0.742188 -20 25 21 0.515137 1 0.813965 -20 25 22 0.469482 1 0.876953 -20 25 23 0.414551 1 0.929688 -20 25 24 0.346191 1 0.974121 -20 25 25 0.236084 1 1 -20 25 26 0 0.974121 1 -20 25 27 0 0.935059 1 -20 25 28 0 0.891113 1 -20 25 29 0 0.845215 1 -20 25 30 0 0.799805 1 -20 25 31 0 0.755371 1 -20 26 0 0.542969 1 0.218628 -20 26 1 0.542969 1 0.218628 -20 26 2 0.542969 1 0.218628 -20 26 3 0.542969 1 0.218628 -20 26 4 0.542969 1 0.218628 -20 26 5 0.542969 1 0.218628 -20 26 6 0.542969 1 0.218628 -20 26 7 0.542969 1 0.218628 -20 26 8 0.542969 1 0.218628 -20 26 9 0.542969 1 0.218628 -20 26 10 0.542969 1 0.218628 -20 26 11 0.543457 1 0.218628 -20 26 12 0.543457 1 0.21875 -20 26 13 0.543457 1 0.21875 -20 26 14 0.543945 1 0.21875 -20 26 15 0.541504 1 0.268555 -20 26 16 0.533203 1 0.369629 -20 26 17 0.520996 1 0.462158 -20 26 18 0.50293 1 0.550293 -20 26 19 0.477783 1 0.634277 -20 26 20 0.44458 1 0.711914 -20 26 21 0.399902 1 0.78418 -20 26 22 0.339111 1 0.848633 -20 26 23 0.250977 1 0.90332 -20 26 24 0 1 0.950195 -20 26 25 0 1 0.992676 -20 26 26 0 1 1 -20 26 27 0 0.987793 1 -20 26 28 0 0.946289 1 -20 26 29 0 0.900879 1 -20 26 30 0 0.854004 1 -20 26 31 0 0.807129 1 -20 27 0 0.418457 1 0.206909 -20 27 1 0.418457 1 0.206909 -20 27 2 0.418457 1 0.206909 -20 27 3 0.418457 1 0.206909 -20 27 4 0.418457 1 0.206909 -20 27 5 0.418457 1 0.206909 -20 27 6 0.418457 1 0.206909 -20 27 7 0.418457 1 0.206909 -20 27 8 0.418457 1 0.206909 -20 27 9 0.418701 1 0.206909 -20 27 10 0.418701 1 0.206909 -20 27 11 0.418701 1 0.206909 -20 27 12 0.418945 1 0.206909 -20 27 13 0.419434 1 0.207031 -20 27 14 0.419922 1 0.207031 -20 27 15 0.419189 1 0.227051 -20 27 16 0.407715 1 0.336182 -20 27 17 0.389648 1 0.43042 -20 27 18 0.363037 1 0.518555 -20 27 19 0.324219 1 0.601562 -20 27 20 0.265137 1 0.678711 -20 27 21 0.145264 1 0.750488 -20 27 22 0 1 0.815918 -20 27 23 0 1 0.872559 -20 27 24 0 1 0.920898 -20 27 25 0 1 0.966309 -20 27 26 0 1 1 -20 27 27 0 1 1 -20 27 28 0 0.997559 1 -20 27 29 0 0.954102 1 -20 27 30 0 0.907715 1 -20 27 31 0 0.859375 1 -20 28 0 0.174561 1 0.194702 -20 28 1 0.174561 1 0.194702 -20 28 2 0.174561 1 0.194702 -20 28 3 0.174561 1 0.194702 -20 28 4 0.174561 1 0.194702 -20 28 5 0.174561 1 0.194702 -20 28 6 0.174683 1 0.194702 -20 28 7 0.174683 1 0.194702 -20 28 8 0.174805 1 0.194702 -20 28 9 0.174927 1 0.194702 -20 28 10 0.175171 1 0.194824 -20 28 11 0.175781 1 0.194824 -20 28 12 0.176636 1 0.194824 -20 28 13 0.178101 1 0.194824 -20 28 14 0.18042 1 0.194946 -20 28 15 0.183716 1 0.195068 -20 28 16 0.139893 1 0.299561 -20 28 17 0 1 0.39624 -20 28 18 0 1 0.484131 -20 28 19 0 1 0.566406 -20 28 20 0 1 0.642578 -20 28 21 0 1 0.713867 -20 28 22 0 1 0.779297 -20 28 23 0 1 0.836914 -20 28 24 0 1 0.887207 -20 28 25 0 1 0.935059 -20 28 26 0 1 0.979492 -20 28 27 0 1 1 -20 28 28 0 1 1 -20 28 29 0 1 1 -20 28 30 0 0.958496 1 -20 28 31 0 0.911133 1 -20 29 0 0 1 0.182129 -20 29 1 0 1 0.182129 -20 29 2 0 1 0.182129 -20 29 3 0 1 0.182129 -20 29 4 0 1 0.182129 -20 29 5 0 1 0.182129 -20 29 6 0 1 0.182129 -20 29 7 0 1 0.182129 -20 29 8 0 1 0.182129 -20 29 9 0 1 0.182129 -20 29 10 0 1 0.182129 -20 29 11 0 1 0.182129 -20 29 12 0 1 0.182129 -20 29 13 0 1 0.182251 -20 29 14 0 1 0.182251 -20 29 15 0 1 0.182373 -20 29 16 0 1 0.257324 -20 29 17 0 1 0.359375 -20 29 18 0 1 0.447754 -20 29 19 0 1 0.528809 -20 29 20 0 1 0.604004 -20 29 21 0 1 0.674316 -20 29 22 0 1 0.739258 -20 29 23 0 1 0.797363 -20 29 24 0 1 0.848145 -20 29 25 0 1 0.897949 -20 29 26 0 1 0.944824 -20 29 27 0 1 0.988281 -20 29 28 0 1 1 -20 29 29 0 1 1 -20 29 30 0 1 1 -20 29 31 0 0.961914 1 -20 30 0 0 1 0.168945 -20 30 1 0 1 0.168945 -20 30 2 0 1 0.168945 -20 30 3 0 1 0.168945 -20 30 4 0 1 0.169067 -20 30 5 0 1 0.169067 -20 30 6 0 1 0.169067 -20 30 7 0 1 0.169067 -20 30 8 0 1 0.169067 -20 30 9 0 1 0.169067 -20 30 10 0 1 0.169067 -20 30 11 0 1 0.169067 -20 30 12 0 1 0.169067 -20 30 13 0 1 0.169189 -20 30 14 0 1 0.169189 -20 30 15 0 1 0.169312 -20 30 16 0 1 0.206909 -20 30 17 0 1 0.31958 -20 30 18 0 1 0.40918 -20 30 19 0 1 0.489502 -20 30 20 0 1 0.562988 -20 30 21 0 1 0.631836 -20 30 22 0 1 0.696289 -20 30 23 0 1 0.753906 -20 30 24 0 1 0.805176 -20 30 25 0 1 0.855957 -20 30 26 0 1 0.905273 -20 30 27 0 1 0.95166 -20 30 28 0 1 0.994141 -20 30 29 0 1 1 -20 30 30 0 1 1 -20 30 31 0 1 1 -20 31 0 0 1 0.15564 -20 31 1 0 1 0.15564 -20 31 2 0 1 0.15564 -20 31 3 0 1 0.15564 -20 31 4 0 1 0.15564 -20 31 5 0 1 0.15564 -20 31 6 0 1 0.15564 -20 31 7 0 1 0.15564 -20 31 8 0 1 0.15564 -20 31 9 0 1 0.15564 -20 31 10 0 1 0.155762 -20 31 11 0 1 0.155762 -20 31 12 0 1 0.155762 -20 31 13 0 1 0.155762 -20 31 14 0 1 0.155884 -20 31 15 0 1 0.156006 -20 31 16 0 1 0.15625 -20 31 17 0 1 0.275879 -20 31 18 0 1 0.368652 -20 31 19 0 1 0.448242 -20 31 20 0 1 0.52002 -20 31 21 0 1 0.587891 -20 31 22 0 1 0.650391 -20 31 23 0 1 0.707031 -20 31 24 0 1 0.758789 -20 31 25 0 1 0.810059 -20 31 26 0 1 0.86084 -20 31 27 0 1 0.910156 -20 31 28 0 1 0.956543 -20 31 29 0 1 0.998535 -20 31 30 0 1 1 -20 31 31 0 1 1 -21 0 0 1 0 0.0576477 -21 0 1 1 0 0.0576477 -21 0 2 1 0 0.0576477 -21 0 3 1 0 0.0576477 -21 0 4 1 0 0.0576477 -21 0 5 1 0 0.0576172 -21 0 6 1 0 0.0575867 -21 0 7 1 0 0.0575256 -21 0 8 1 0 0.057373 -21 0 9 1 0 0.0571289 -21 0 10 1 0 0.0566711 -21 0 11 1 0 0.0558167 -21 0 12 1 0 0.0543213 -21 0 13 1 0 0.052948 -21 0 14 1 0 0.193604 -21 0 15 1 0 0.328613 -21 0 16 1 0 0.440918 -21 0 17 1 0 0.554199 -21 0 18 1 0.214844 0.674805 -21 0 19 1 0.306152 0.783203 -21 0 20 1 0.339111 0.86377 -21 0 21 1 0.343994 0.924805 -21 0 22 0.972656 0.344971 0.972656 -21 0 23 0.917969 0.342773 1 -21 0 24 0.859375 0.338623 1 -21 0 25 0.79541 0.332764 1 -21 0 26 0.727539 0.326172 1 -21 0 27 0.657227 0.319336 1 -21 0 28 0.584961 0.312988 1 -21 0 29 0.509766 0.307373 1 -21 0 30 0.428223 0.302979 1 -21 0 31 0.331055 0.299316 1 -21 1 0 1 0 0.0576477 -21 1 1 1 0 0.0576477 -21 1 2 1 0 0.0576172 -21 1 3 1 0 0.0576172 -21 1 4 1 0 0.0576172 -21 1 5 1 0 0.0575867 -21 1 6 1 0 0.0575562 -21 1 7 1 0 0.0574951 -21 1 8 1 0 0.057373 -21 1 9 1 0 0.0570984 -21 1 10 1 0 0.0566406 -21 1 11 1 0 0.0557861 -21 1 12 1 0 0.0543213 -21 1 13 1 0 0.0529175 -21 1 14 1 0 0.193604 -21 1 15 1 0 0.328613 -21 1 16 1 0 0.440674 -21 1 17 1 0 0.554199 -21 1 18 1 0.214966 0.674805 -21 1 19 1 0.306152 0.783203 -21 1 20 1 0.339111 0.86377 -21 1 21 1 0.343994 0.924805 -21 1 22 0.972656 0.344971 0.972656 -21 1 23 0.917969 0.343018 1 -21 1 24 0.859375 0.338623 1 -21 1 25 0.79541 0.332764 1 -21 1 26 0.727539 0.326172 1 -21 1 27 0.657227 0.319336 1 -21 1 28 0.584961 0.312988 1 -21 1 29 0.509766 0.307373 1 -21 1 30 0.428223 0.302979 1 -21 1 31 0.331055 0.299316 1 -21 2 0 1 0 0.0576172 -21 2 1 1 0 0.0575867 -21 2 2 1 0 0.0575867 -21 2 3 1 0 0.0575867 -21 2 4 1 0 0.0575867 -21 2 5 1 0 0.0575562 -21 2 6 1 0 0.0575256 -21 2 7 1 0 0.0574646 -21 2 8 1 0 0.0573425 -21 2 9 1 0 0.0570679 -21 2 10 1 0 0.0566101 -21 2 11 1 0 0.0557556 -21 2 12 1 0 0.0542603 -21 2 13 1 0 0.052887 -21 2 14 1 0 0.193604 -21 2 15 1 0 0.328613 -21 2 16 1 0 0.440674 -21 2 17 1 0 0.554199 -21 2 18 1 0.214966 0.674805 -21 2 19 1 0.306152 0.783203 -21 2 20 1 0.339111 0.86377 -21 2 21 1 0.343994 0.924805 -21 2 22 0.972656 0.344971 0.972656 -21 2 23 0.917969 0.343018 1 -21 2 24 0.859375 0.338623 1 -21 2 25 0.79541 0.332764 1 -21 2 26 0.727539 0.326172 1 -21 2 27 0.657227 0.319336 1 -21 2 28 0.584961 0.312988 1 -21 2 29 0.509766 0.307373 1 -21 2 30 0.428223 0.302979 1 -21 2 31 0.331055 0.299316 1 -21 3 0 1 0 0.0575256 -21 3 1 1 0 0.0575256 -21 3 2 1 0 0.0575256 -21 3 3 1 0 0.0575256 -21 3 4 1 0 0.0575256 -21 3 5 1 0 0.0574951 -21 3 6 1 0 0.0574646 -21 3 7 1 0 0.0574036 -21 3 8 1 0 0.0572815 -21 3 9 1 0 0.0570068 -21 3 10 1 0 0.0565491 -21 3 11 1 0 0.0556946 -21 3 12 1 0 0.0541992 -21 3 13 1 0 0.0528259 -21 3 14 1 0 0.193604 -21 3 15 1 0 0.328613 -21 3 16 1 0 0.440674 -21 3 17 1 0 0.554199 -21 3 18 1 0.21521 0.674805 -21 3 19 1 0.306396 0.783203 -21 3 20 1 0.339111 0.86377 -21 3 21 1 0.343994 0.924805 -21 3 22 0.972656 0.345215 0.972656 -21 3 23 0.917969 0.343018 1 -21 3 24 0.859375 0.338623 1 -21 3 25 0.79541 0.332764 1 -21 3 26 0.727539 0.326172 1 -21 3 27 0.657227 0.319336 1 -21 3 28 0.584961 0.312988 1 -21 3 29 0.509766 0.307617 1 -21 3 30 0.428223 0.302979 1 -21 3 31 0.331055 0.299316 1 -21 4 0 1 0 0.0574341 -21 4 1 1 0 0.0574341 -21 4 2 1 0 0.0574341 -21 4 3 1 0 0.0574036 -21 4 4 1 0 0.0574036 -21 4 5 1 0 0.057373 -21 4 6 1 0 0.0573425 -21 4 7 1 0 0.0572815 -21 4 8 1 0 0.0571594 -21 4 9 1 0 0.0568848 -21 4 10 1 0 0.056427 -21 4 11 1 0 0.0555725 -21 4 12 1 0 0.0540771 -21 4 13 1 0 0.0526733 -21 4 14 1 0 0.193604 -21 4 15 1 0 0.328613 -21 4 16 1 0 0.440674 -21 4 17 1 0 0.554199 -21 4 18 1 0.215454 0.674805 -21 4 19 1 0.306396 0.783203 -21 4 20 1 0.339355 0.86377 -21 4 21 1 0.344238 0.924805 -21 4 22 0.972656 0.345215 0.972656 -21 4 23 0.917969 0.343018 1 -21 4 24 0.859375 0.338867 1 -21 4 25 0.79541 0.332764 1 -21 4 26 0.727539 0.326172 1 -21 4 27 0.657227 0.319336 1 -21 4 28 0.584961 0.313232 1 -21 4 29 0.509766 0.307617 1 -21 4 30 0.428223 0.302979 1 -21 4 31 0.331055 0.299316 1 -21 5 0 1 0 0.0571899 -21 5 1 1 0 0.0571899 -21 5 2 1 0 0.0571899 -21 5 3 1 0 0.0571899 -21 5 4 1 0 0.0571899 -21 5 5 1 0 0.0571594 -21 5 6 1 0 0.0571289 -21 5 7 1 0 0.0570679 -21 5 8 1 0 0.0569153 -21 5 9 1 0 0.0566711 -21 5 10 1 0 0.0561829 -21 5 11 1 0 0.0553284 -21 5 12 1 0 0.053833 -21 5 13 1 0 0.0524292 -21 5 14 1 0 0.193604 -21 5 15 1 0 0.328613 -21 5 16 1 0 0.440674 -21 5 17 1 0 0.554199 -21 5 18 1 0.215942 0.674805 -21 5 19 1 0.306885 0.783203 -21 5 20 1 0.3396 0.86377 -21 5 21 1 0.344482 0.924805 -21 5 22 0.972656 0.345459 0.972656 -21 5 23 0.917969 0.343262 1 -21 5 24 0.859375 0.338867 1 -21 5 25 0.79541 0.333008 1 -21 5 26 0.727539 0.326416 1 -21 5 27 0.657227 0.31958 1 -21 5 28 0.584961 0.313232 1 -21 5 29 0.509766 0.307617 1 -21 5 30 0.428223 0.302979 1 -21 5 31 0.331055 0.299561 1 -21 6 0 1 0 0.0567627 -21 6 1 1 0 0.0567627 -21 6 2 1 0 0.0567627 -21 6 3 1 0 0.0567627 -21 6 4 1 0 0.0567322 -21 6 5 1 0 0.0567322 -21 6 6 1 0 0.0567017 -21 6 7 1 0 0.0566101 -21 6 8 1 0 0.056488 -21 6 9 1 0 0.0562134 -21 6 10 1 0 0.0557251 -21 6 11 1 0 0.0548706 -21 6 12 1 0 0.0533447 -21 6 13 1 0 0.0519409 -21 6 14 1 0 0.193604 -21 6 15 1 0 0.328613 -21 6 16 1 0 0.440674 -21 6 17 1 0 0.554199 -21 6 18 1 0.216919 0.674805 -21 6 19 1 0.307373 0.783203 -21 6 20 1 0.340088 0.86377 -21 6 21 1 0.344971 0.924805 -21 6 22 0.972656 0.345947 0.972656 -21 6 23 0.917969 0.34375 1 -21 6 24 0.859375 0.339355 1 -21 6 25 0.79541 0.333252 1 -21 6 26 0.727539 0.32666 1 -21 6 27 0.657227 0.319824 1 -21 6 28 0.584961 0.313477 1 -21 6 29 0.509766 0.307861 1 -21 6 30 0.428223 0.303223 1 -21 6 31 0.331055 0.299561 1 -21 7 0 1 0 0.0559082 -21 7 1 1 0 0.0559082 -21 7 2 1 0 0.0559082 -21 7 3 1 0 0.0558777 -21 7 4 1 0 0.0558777 -21 7 5 1 0 0.0558472 -21 7 6 1 0 0.0558167 -21 7 7 1 0 0.0557556 -21 7 8 1 0 0.055603 -21 7 9 1 0 0.0553589 -21 7 10 1 0 0.0548401 -21 7 11 1 0 0.0539551 -21 7 12 1 0 0.0523987 -21 7 13 1 0 0.0509338 -21 7 14 1 0 0.193604 -21 7 15 1 0 0.328369 -21 7 16 1 0 0.440674 -21 7 17 1 0 0.554199 -21 7 18 1 0.218872 0.674805 -21 7 19 1 0.308594 0.783203 -21 7 20 1 0.341064 0.86377 -21 7 21 1 0.345947 0.924805 -21 7 22 0.972656 0.34668 0.972656 -21 7 23 0.917969 0.344482 1 -21 7 24 0.859375 0.340088 1 -21 7 25 0.79541 0.333984 1 -21 7 26 0.727539 0.327148 1 -21 7 27 0.656738 0.320312 1 -21 7 28 0.584961 0.313965 1 -21 7 29 0.509277 0.30835 1 -21 7 30 0.427979 0.303467 1 -21 7 31 0.331055 0.300049 1 -21 8 0 1 0 0.0541382 -21 8 1 1 0 0.0541382 -21 8 2 1 0 0.0541382 -21 8 3 1 0 0.0541382 -21 8 4 1 0 0.0541382 -21 8 5 1 0 0.0541077 -21 8 6 1 0 0.0540771 -21 8 7 1 0 0.0539856 -21 8 8 1 0 0.053833 -21 8 9 1 0 0.0535583 -21 8 10 1 0 0.0530396 -21 8 11 1 0 0.0520935 -21 8 12 1 0 0.0504456 -21 8 13 1 0 0.0488892 -21 8 14 1 0 0.193604 -21 8 15 1 0 0.328369 -21 8 16 1 0 0.440674 -21 8 17 1 0 0.553711 -21 8 18 1 0.222534 0.674805 -21 8 19 1 0.310791 0.783203 -21 8 20 1 0.343018 0.86377 -21 8 21 1 0.347656 0.924805 -21 8 22 0.972656 0.348389 0.972656 -21 8 23 0.91748 0.345947 1 -21 8 24 0.859375 0.341309 1 -21 8 25 0.79541 0.335205 1 -21 8 26 0.727051 0.328369 1 -21 8 27 0.656738 0.321289 1 -21 8 28 0.584473 0.314697 1 -21 8 29 0.509277 0.309082 1 -21 8 30 0.427979 0.304199 1 -21 8 31 0.330811 0.300537 1 -21 9 0 1 0 0.0505066 -21 9 1 1 0 0.0504761 -21 9 2 1 0 0.0504761 -21 9 3 1 0 0.0504761 -21 9 4 1 0 0.0504761 -21 9 5 1 0 0.0504456 -21 9 6 1 0 0.050415 -21 9 7 1 0 0.0503235 -21 9 8 1 0 0.0501404 -21 9 9 1 0 0.0498352 -21 9 10 1 0 0.0492554 -21 9 11 1 0 0.0481873 -21 9 12 1 0 0.0462646 -21 9 13 1 0 0.0445557 -21 9 14 1 0 0.193726 -21 9 15 1 0 0.328125 -21 9 16 1 0 0.440674 -21 9 17 1 0 0.553711 -21 9 18 1 0.229248 0.674316 -21 9 19 1 0.315186 0.783203 -21 9 20 1 0.34668 0.86377 -21 9 21 1 0.351074 0.924805 -21 9 22 0.972168 0.351562 0.972656 -21 9 23 0.91748 0.348877 1 -21 9 24 0.858887 0.343994 1 -21 9 25 0.794922 0.337646 1 -21 9 26 0.727051 0.330322 1 -21 9 27 0.656738 0.322998 1 -21 9 28 0.584473 0.316406 1 -21 9 29 0.509277 0.310303 1 -21 9 30 0.427734 0.30542 1 -21 9 31 0.330566 0.301514 1 -21 10 0 1 0 0.04245 -21 10 1 1 0 0.04245 -21 10 2 1 0 0.04245 -21 10 3 1 0 0.04245 -21 10 4 1 0 0.0424194 -21 10 5 1 0 0.0423889 -21 10 6 1 0 0.0423279 -21 10 7 1 0 0.0422363 -21 10 8 1 0 0.0419922 -21 10 9 1 0 0.0415649 -21 10 10 1 0 0.0407715 -21 10 11 1 0 0.0393372 -21 10 12 1 0 0.0366211 -21 10 13 1 0 0.0341492 -21 10 14 1 0 0.19397 -21 10 15 1 0 0.327881 -21 10 16 1 0 0.440674 -21 10 17 1 0.102051 0.553223 -21 10 18 1 0.240723 0.673828 -21 10 19 1 0.32251 0.782715 -21 10 20 1 0.353271 0.863281 -21 10 21 1 0.357178 0.924805 -21 10 22 0.972168 0.357178 0.972656 -21 10 23 0.916992 0.354004 1 -21 10 24 0.858887 0.348633 1 -21 10 25 0.794434 0.341797 1 -21 10 26 0.726562 0.333984 1 -21 10 27 0.65625 0.326416 1 -21 10 28 0.583984 0.319092 1 -21 10 29 0.508789 0.312988 1 -21 10 30 0.427246 0.307617 1 -21 10 31 0.329834 0.303467 1 -21 11 0 1 0.0171204 0 -21 11 1 1 0.0173492 0 -21 11 2 1 0.0177307 0 -21 11 3 1 0.0184326 0 -21 11 4 1 0.0196381 0 -21 11 5 1 0.0216827 0 -21 11 6 1 0.0248871 0 -21 11 7 1 0.0297394 0 -21 11 8 1 0.0366821 0 -21 11 9 1 0.0460205 0 -21 11 10 1 0.0578308 0 -21 11 11 1 0.0722656 0 -21 11 12 1 0.0896606 0 -21 11 13 1 0.0997925 0 -21 11 14 1 0.0933838 0.194336 -21 11 15 1 0.0739746 0.327637 -21 11 16 1 0.0922241 0.440674 -21 11 17 1 0.155029 0.552246 -21 11 18 1 0.259033 0.67334 -21 11 19 1 0.335205 0.782715 -21 11 20 1 0.364502 0.863281 -21 11 21 1 0.367432 0.924805 -21 11 22 0.97168 0.366699 0.972656 -21 11 23 0.916504 0.362549 1 -21 11 24 0.85791 0.356445 1 -21 11 25 0.793945 0.348877 1 -21 11 26 0.726074 0.340332 1 -21 11 27 0.655762 0.332031 1 -21 11 28 0.583496 0.324219 1 -21 11 29 0.507812 0.317383 1 -21 11 30 0.426514 0.311523 1 -21 11 31 0.328857 0.306885 1 -21 12 0 1 0.170654 0 -21 12 1 1 0.170654 0 -21 12 2 1 0.170654 0 -21 12 3 1 0.170776 0 -21 12 4 1 0.170776 0 -21 12 5 1 0.170776 0 -21 12 6 1 0.171021 0 -21 12 7 1 0.171265 0 -21 12 8 1 0.171753 0 -21 12 9 1 0.172729 0 -21 12 10 1 0.174438 0 -21 12 11 1 0.177368 0 -21 12 12 1 0.182373 0 -21 12 13 1 0.185425 0 -21 12 14 1 0.181763 0.195679 -21 12 15 1 0.174316 0.327148 -21 12 16 1 0.181519 0.440918 -21 12 17 1 0.207764 0.55127 -21 12 18 1 0.285889 0.671875 -21 12 19 1 0.35498 0.782227 -21 12 20 1 0.38208 0.863281 -21 12 21 1 0.384033 0.924805 -21 12 22 0.970215 0.38208 0.972656 -21 12 23 0.915527 0.376709 1 -21 12 24 0.856934 0.369385 1 -21 12 25 0.792969 0.360352 1 -21 12 26 0.725098 0.35083 1 -21 12 27 0.654297 0.341309 1 -21 12 28 0.582031 0.332275 1 -21 12 29 0.506836 0.324463 1 -21 12 30 0.425049 0.317871 1 -21 12 31 0.327148 0.3125 1 -21 13 0 1 0.248657 0 -21 13 1 1 0.248657 0 -21 13 2 1 0.248657 0 -21 13 3 1 0.248779 0 -21 13 4 1 0.248779 0 -21 13 5 1 0.248779 0 -21 13 6 1 0.248901 0 -21 13 7 1 0.249023 0 -21 13 8 1 0.249268 0 -21 13 9 1 0.249878 0 -21 13 10 1 0.250732 0 -21 13 11 1 0.252441 0 -21 13 12 1 0.255371 0 -21 13 13 1 0.256836 0 -21 13 14 1 0.253418 0.198975 -21 13 15 1 0.247559 0.327393 -21 13 16 1 0.252441 0.441162 -21 13 17 1 0.264893 0.549316 -21 13 18 1 0.322754 0.669434 -21 13 19 1 0.383789 0.78125 -21 13 20 1 0.408691 0.863281 -21 13 21 1 0.408936 0.924805 -21 13 22 0.96875 0.405273 0.972656 -21 13 23 0.913574 0.398193 1 -21 13 24 0.85498 0.388916 1 -21 13 25 0.791016 0.378174 1 -21 13 26 0.723145 0.366699 1 -21 13 27 0.652344 0.355469 1 -21 13 28 0.580566 0.344971 1 -21 13 29 0.504883 0.335938 1 -21 13 30 0.422852 0.327881 1 -21 13 31 0.324219 0.321289 1 -21 14 0 1 0.325684 0 -21 14 1 1 0.325684 0 -21 14 2 1 0.325684 0 -21 14 3 1 0.325684 0 -21 14 4 1 0.325684 0 -21 14 5 1 0.325684 0 -21 14 6 1 0.325684 0 -21 14 7 1 0.325928 0 -21 14 8 1 0.325928 0 -21 14 9 1 0.326416 0 -21 14 10 1 0.327148 0 -21 14 11 1 0.328125 0 -21 14 12 1 0.330078 0 -21 14 13 1 0.330811 0 -21 14 14 1 0.327393 0.206909 -21 14 15 1 0.322021 0.329102 -21 14 16 1 0.321289 0.438965 -21 14 17 1 0.329102 0.546875 -21 14 18 1 0.370117 0.666016 -21 14 19 1 0.42334 0.779297 -21 14 20 1 0.445801 0.862793 -21 14 21 1 0.444092 0.924805 -21 14 22 0.96582 0.438232 0.972656 -21 14 23 0.910645 0.428711 1 -21 14 24 0.852051 0.417236 1 -21 14 25 0.787598 0.404053 1 -21 14 26 0.719727 0.390137 1 -21 14 27 0.649414 0.376709 1 -21 14 28 0.577148 0.364014 1 -21 14 29 0.501953 0.352783 1 -21 14 30 0.419434 0.343018 1 -21 14 31 0.31958 0.334717 1 -21 15 0 1 0.407715 0 -21 15 1 1 0.407715 0 -21 15 2 1 0.407715 0 -21 15 3 1 0.407715 0 -21 15 4 1 0.407715 0 -21 15 5 1 0.407715 0 -21 15 6 1 0.407715 0 -21 15 7 1 0.407959 0 -21 15 8 1 0.407959 0 -21 15 9 1 0.408203 0 -21 15 10 1 0.408691 0 -21 15 11 1 0.409668 0 -21 15 12 1 0.410889 0 -21 15 13 1 0.411377 0 -21 15 14 1 0.407715 0.223267 -21 15 15 1 0.402588 0.335449 -21 15 16 1 0.398193 0.438721 -21 15 17 1 0.402344 0.54541 -21 15 18 1 0.42749 0.660156 -21 15 19 1 0.473389 0.775879 -21 15 20 1 0.494385 0.861816 -21 15 21 1 0.490723 0.924316 -21 15 22 0.960938 0.482178 0.972656 -21 15 23 0.905762 0.469727 1 -21 15 24 0.847168 0.455322 1 -21 15 25 0.783203 0.438965 1 -21 15 26 0.715332 0.422119 1 -21 15 27 0.64502 0.405518 1 -21 15 28 0.572754 0.390137 1 -21 15 29 0.496826 0.376221 1 -21 15 30 0.413818 0.364258 1 -21 15 31 0.312012 0.35376 1 -21 16 0 1 0.497314 0 -21 16 1 1 0.497314 0 -21 16 2 1 0.497559 0 -21 16 3 1 0.497559 0 -21 16 4 1 0.497559 0 -21 16 5 1 0.497559 0 -21 16 6 1 0.497559 0 -21 16 7 1 0.497559 0 -21 16 8 1 0.497559 0 -21 16 9 1 0.497803 0 -21 16 10 1 0.498291 0 -21 16 11 1 0.498779 0 -21 16 12 1 0.499756 0 -21 16 13 1 0.5 0.104736 -21 16 14 1 0.497314 0.251465 -21 16 15 1 0.492676 0.350342 -21 16 16 1 0.486084 0.444824 -21 16 17 1 0.483887 0.544434 -21 16 18 1 0.495117 0.652344 -21 16 19 1 0.533203 0.77002 -21 16 20 1 0.554199 0.860352 -21 16 21 1 0.54834 0.92334 -21 16 22 0.953613 0.537109 0.97168 -21 16 23 0.898438 0.521484 1 -21 16 24 0.839355 0.503418 1 -21 16 25 0.775391 0.483398 1 -21 16 26 0.708008 0.462891 1 -21 16 27 0.637695 0.443115 1 -21 16 28 0.565918 0.424316 1 -21 16 29 0.489746 0.407471 1 -21 16 30 0.405518 0.392578 1 -21 16 31 0.300537 0.379395 1 -21 17 0 1 0.592773 0.159546 -21 17 1 1 0.592773 0.159546 -21 17 2 1 0.592773 0.159546 -21 17 3 1 0.592773 0.159546 -21 17 4 1 0.592773 0.159546 -21 17 5 1 0.592773 0.159546 -21 17 6 1 0.592773 0.159546 -21 17 7 1 0.592773 0.159668 -21 17 8 1 0.593262 0.159668 -21 17 9 1 0.593262 0.159912 -21 17 10 1 0.593262 0.160156 -21 17 11 1 0.59375 0.160645 -21 17 12 1 0.594727 0.161377 -21 17 13 1 0.595215 0.191895 -21 17 14 1 0.59375 0.28833 -21 17 15 1 0.590332 0.375 -21 17 16 1 0.583984 0.46167 -21 17 17 1 0.574707 0.549316 -21 17 18 1 0.575195 0.647949 -21 17 19 1 0.598633 0.759277 -21 17 20 1 0.621582 0.856445 -21 17 21 0.989746 0.614746 0.920898 -21 17 22 0.942871 0.600586 0.969727 -21 17 23 0.887207 0.581055 1 -21 17 24 0.828125 0.559082 1 -21 17 25 0.764648 0.535645 1 -21 17 26 0.697266 0.51123 1 -21 17 27 0.62793 0.487793 1 -21 17 28 0.555664 0.46582 1 -21 17 29 0.479248 0.445557 1 -21 17 30 0.393555 0.42749 1 -21 17 31 0.282959 0.411377 1 -21 18 0 1 0.69043 0.238403 -21 18 1 1 0.69043 0.238403 -21 18 2 1 0.69043 0.238403 -21 18 3 1 0.69043 0.238403 -21 18 4 1 0.69043 0.238403 -21 18 5 1 0.69043 0.238403 -21 18 6 1 0.69043 0.238403 -21 18 7 1 0.69043 0.238403 -21 18 8 1 0.69043 0.238403 -21 18 9 1 0.690918 0.238525 -21 18 10 1 0.690918 0.238647 -21 18 11 1 0.691406 0.23877 -21 18 12 1 0.691895 0.239136 -21 18 13 1 0.692871 0.245117 -21 18 14 1 0.691895 0.323486 -21 18 15 1 0.69043 0.40332 -21 18 16 1 0.686035 0.486084 -21 18 17 1 0.677246 0.568359 -21 18 18 1 0.665039 0.649902 -21 18 19 1 0.66748 0.745605 -21 18 20 1 0.691895 0.849121 -21 18 21 0.973145 0.685547 0.916992 -21 18 22 0.926758 0.668457 0.96582 -21 18 23 0.870605 0.64502 0.996094 -21 18 24 0.8125 0.619629 1 -21 18 25 0.749512 0.592285 1 -21 18 26 0.683594 0.564941 1 -21 18 27 0.614746 0.538086 1 -21 18 28 0.54248 0.512695 1 -21 18 29 0.465332 0.489258 1 -21 18 30 0.376953 0.468018 1 -21 18 31 0.256592 0.44873 1 -21 19 0 1 0.78418 0.281006 -21 19 1 1 0.78418 0.281006 -21 19 2 1 0.78418 0.281006 -21 19 3 1 0.78418 0.281006 -21 19 4 1 0.78418 0.281006 -21 19 5 1 0.78418 0.281006 -21 19 6 1 0.78418 0.281006 -21 19 7 1 0.78418 0.281006 -21 19 8 1 0.78418 0.281006 -21 19 9 1 0.78418 0.281006 -21 19 10 1 0.784668 0.281006 -21 19 11 1 0.784668 0.281006 -21 19 12 1 0.785156 0.28125 -21 19 13 1 0.786133 0.281494 -21 19 14 1 0.786133 0.344727 -21 19 15 1 0.785645 0.422607 -21 19 16 1 0.783691 0.505371 -21 19 17 1 0.77832 0.589844 -21 19 18 1 0.76709 0.669434 -21 19 19 0.984863 0.750488 0.742676 -21 19 20 0.975586 0.757812 0.835449 -21 19 21 0.950684 0.756348 0.910156 -21 19 22 0.904297 0.736328 0.958984 -21 19 23 0.848145 0.708984 0.988281 -21 19 24 0.791504 0.680664 1 -21 19 25 0.730469 0.650879 1 -21 19 26 0.665527 0.621094 1 -21 19 27 0.597656 0.591309 1 -21 19 28 0.525879 0.562988 1 -21 19 29 0.447266 0.536621 1 -21 19 30 0.354248 0.512207 1 -21 19 31 0.215698 0.48999 1 -21 20 0 1 0.868164 0.296631 -21 20 1 1 0.868164 0.296631 -21 20 2 1 0.868164 0.296631 -21 20 3 1 0.868164 0.296631 -21 20 4 1 0.868164 0.296631 -21 20 5 1 0.868164 0.296631 -21 20 6 1 0.868164 0.296631 -21 20 7 1 0.868164 0.296631 -21 20 8 1 0.868164 0.296631 -21 20 9 1 0.868164 0.296631 -21 20 10 1 0.868164 0.296631 -21 20 11 1 0.868652 0.296631 -21 20 12 1 0.868652 0.296631 -21 20 13 1 0.869141 0.296631 -21 20 14 1 0.870117 0.345459 -21 20 15 1 0.870117 0.425049 -21 20 16 1 0.869629 0.510254 -21 20 17 1 0.866699 0.597168 -21 20 18 1 0.859863 0.682129 -21 20 19 0.983398 0.84668 0.758789 -21 20 20 0.943848 0.825195 0.821777 -21 20 21 0.922363 0.824219 0.900391 -21 20 22 0.875 0.800293 0.947754 -21 20 23 0.820312 0.77002 0.978027 -21 20 24 0.766113 0.740723 0.999512 -21 20 25 0.708008 0.709961 1 -21 20 26 0.645508 0.678223 1 -21 20 27 0.578613 0.646973 1 -21 20 28 0.506348 0.616211 1 -21 20 29 0.424561 0.586914 1 -21 20 30 0.323975 0.559082 1 -21 20 31 0.138062 0.533203 1 -21 21 0 1 0.938965 0.294678 -21 21 1 1 0.938965 0.294678 -21 21 2 1 0.938965 0.294678 -21 21 3 1 0.938965 0.294678 -21 21 4 1 0.938965 0.294678 -21 21 5 1 0.938965 0.294678 -21 21 6 1 0.938965 0.294678 -21 21 7 1 0.938965 0.294678 -21 21 8 1 0.938965 0.294678 -21 21 9 1 0.939453 0.294678 -21 21 10 1 0.939453 0.294678 -21 21 11 1 0.939453 0.294678 -21 21 12 1 0.939453 0.294678 -21 21 13 1 0.939941 0.294678 -21 21 14 1 0.940918 0.328857 -21 21 15 1 0.941406 0.411865 -21 21 16 1 0.941406 0.499023 -21 21 17 1 0.939453 0.588379 -21 21 18 0.984863 0.934082 0.675781 -21 21 19 0.960449 0.924316 0.757324 -21 21 20 0.928223 0.90918 0.828125 -21 21 21 0.887207 0.887207 0.887207 -21 21 22 0.839844 0.860352 0.934082 -21 21 23 0.790039 0.832031 0.969238 -21 21 24 0.739258 0.802734 0.995117 -21 21 25 0.683594 0.771484 1 -21 21 26 0.62207 0.737793 1 -21 21 27 0.554688 0.703613 1 -21 21 28 0.480225 0.669922 1 -21 21 29 0.393555 0.637207 1 -21 21 30 0.279053 0.605957 1 -21 21 31 0 0.576172 1 -21 22 0 0.970703 0.992188 0.286377 -21 22 1 0.970703 0.992188 0.286377 -21 22 2 0.970703 0.992188 0.286377 -21 22 3 0.970703 0.992188 0.286377 -21 22 4 0.970703 0.992188 0.286377 -21 22 5 0.970703 0.992188 0.286377 -21 22 6 0.970703 0.992188 0.286377 -21 22 7 0.970703 0.992188 0.286377 -21 22 8 0.970703 0.992188 0.286377 -21 22 9 0.970703 0.992188 0.286377 -21 22 10 0.970703 0.992188 0.286377 -21 22 11 0.970703 0.992676 0.286377 -21 22 12 0.970703 0.992676 0.286377 -21 22 13 0.970703 0.992676 0.286377 -21 22 14 0.970215 0.993164 0.303467 -21 22 15 0.967285 0.994629 0.389648 -21 22 16 0.961426 0.994629 0.478516 -21 22 17 0.951172 0.993164 0.567871 -21 22 18 0.935059 0.988281 0.655762 -21 22 19 0.911621 0.978027 0.736328 -21 22 20 0.880859 0.962402 0.807129 -21 22 21 0.845703 0.944336 0.871094 -21 22 22 0.80957 0.927734 0.929688 -21 22 23 0.763184 0.900391 0.969727 -21 22 24 0.712402 0.868652 0.996094 -21 22 25 0.65625 0.834473 1 -21 22 26 0.59375 0.79834 1 -21 22 27 0.524902 0.76123 1 -21 22 28 0.447021 0.724121 1 -21 22 29 0.352295 0.687988 1 -21 22 30 0.206665 0.65332 1 -21 22 31 0 0.620605 1 -21 23 0 0.910156 1 0.276123 -21 23 1 0.910156 1 0.276123 -21 23 2 0.910156 1 0.276123 -21 23 3 0.910156 1 0.276123 -21 23 4 0.910156 1 0.276123 -21 23 5 0.910156 1 0.276123 -21 23 6 0.910156 1 0.276123 -21 23 7 0.910156 1 0.276123 -21 23 8 0.910156 1 0.276123 -21 23 9 0.910156 1 0.276123 -21 23 10 0.910156 1 0.276123 -21 23 11 0.910156 1 0.276123 -21 23 12 0.910156 1 0.276123 -21 23 13 0.910156 1 0.276123 -21 23 14 0.910156 1 0.276123 -21 23 15 0.907227 1 0.364258 -21 23 16 0.901855 1 0.454102 -21 23 17 0.89209 1 0.543457 -21 23 18 0.877441 1 0.630371 -21 23 19 0.856445 1 0.711914 -21 23 20 0.829102 1 0.784668 -21 23 21 0.798828 0.992676 0.852051 -21 23 22 0.765137 0.977051 0.912598 -21 23 23 0.726562 0.958496 0.962402 -21 23 24 0.681641 0.932617 0.998047 -21 23 25 0.626465 0.898438 1 -21 23 26 0.562988 0.859863 1 -21 23 27 0.490967 0.819824 1 -21 23 28 0.406738 0.779297 1 -21 23 29 0.296143 0.739746 1 -21 23 30 0 0.701172 1 -21 23 31 0 0.664551 1 -21 24 0 0.847168 1 0.265381 -21 24 1 0.847168 1 0.265381 -21 24 2 0.847168 1 0.265381 -21 24 3 0.847168 1 0.265381 -21 24 4 0.847168 1 0.265381 -21 24 5 0.847168 1 0.265381 -21 24 6 0.847168 1 0.265625 -21 24 7 0.847168 1 0.265625 -21 24 8 0.847168 1 0.265625 -21 24 9 0.847168 1 0.265625 -21 24 10 0.847168 1 0.265625 -21 24 11 0.847168 1 0.265625 -21 24 12 0.847168 1 0.265625 -21 24 13 0.847168 1 0.265625 -21 24 14 0.847168 1 0.265625 -21 24 15 0.844727 1 0.337646 -21 24 16 0.839844 1 0.428955 -21 24 17 0.831055 1 0.518555 -21 24 18 0.817871 1 0.605469 -21 24 19 0.798828 1 0.687012 -21 24 20 0.775391 1 0.762207 -21 24 21 0.748047 1 0.831543 -21 24 22 0.715332 1 0.893555 -21 24 23 0.678711 1 0.945312 -21 24 24 0.638184 0.98291 0.988281 -21 24 25 0.586914 0.95459 1 -21 24 26 0.523926 0.917969 1 -21 24 27 0.447754 0.876953 1 -21 24 28 0.352783 0.833984 1 -21 24 29 0.201782 0.791016 1 -21 24 30 0 0.749023 1 -21 24 31 0 0.708984 1 -21 25 0 0.776855 1 0.25415 -21 25 1 0.776855 1 0.25415 -21 25 2 0.776855 1 0.25415 -21 25 3 0.776855 1 0.25415 -21 25 4 0.776855 1 0.25415 -21 25 5 0.776855 1 0.25415 -21 25 6 0.776855 1 0.25415 -21 25 7 0.776855 1 0.25415 -21 25 8 0.776855 1 0.25415 -21 25 9 0.776855 1 0.25415 -21 25 10 0.776855 1 0.25415 -21 25 11 0.776855 1 0.25415 -21 25 12 0.776855 1 0.25415 -21 25 13 0.776855 1 0.25415 -21 25 14 0.777344 1 0.25415 -21 25 15 0.775391 1 0.307861 -21 25 16 0.770508 1 0.401611 -21 25 17 0.762207 1 0.491455 -21 25 18 0.750488 1 0.578613 -21 25 19 0.733398 1 0.660645 -21 25 20 0.712402 1 0.736816 -21 25 21 0.686035 1 0.807129 -21 25 22 0.654785 1 0.870605 -21 25 23 0.618652 1 0.924316 -21 25 24 0.578125 1 0.969238 -21 25 25 0.52832 1 1 -21 25 26 0.4646 0.972656 1 -21 25 27 0.380859 0.934082 1 -21 25 28 0.257812 0.890625 1 -21 25 29 0 0.845703 1 -21 25 30 0 0.800781 1 -21 25 31 0 0.757324 1 -21 26 0 0.697754 1 0.24231 -21 26 1 0.697754 1 0.24231 -21 26 2 0.697754 1 0.24231 -21 26 3 0.697754 1 0.24231 -21 26 4 0.697754 1 0.24231 -21 26 5 0.697754 1 0.24231 -21 26 6 0.697754 1 0.24231 -21 26 7 0.697754 1 0.24231 -21 26 8 0.697754 1 0.24231 -21 26 9 0.697754 1 0.24231 -21 26 10 0.697754 1 0.24231 -21 26 11 0.697754 1 0.24231 -21 26 12 0.697754 1 0.24231 -21 26 13 0.697754 1 0.24231 -21 26 14 0.698242 1 0.242432 -21 26 15 0.697266 1 0.273926 -21 26 16 0.692383 1 0.371826 -21 26 17 0.68457 1 0.462402 -21 26 18 0.672852 1 0.549316 -21 26 19 0.656738 1 0.631836 -21 26 20 0.63623 1 0.708008 -21 26 21 0.610352 1 0.779297 -21 26 22 0.578613 1 0.84375 -21 26 23 0.541504 1 0.898926 -21 26 24 0.498779 1 0.945801 -21 26 25 0.444336 1 0.989258 -21 26 26 0.371094 1 1 -21 26 27 0.256836 0.987305 1 -21 26 28 0 0.946289 1 -21 26 29 0 0.901367 1 -21 26 30 0 0.85498 1 -21 26 31 0 0.808594 1 -21 27 0 0.605957 1 0.22998 -21 27 1 0.605957 1 0.22998 -21 27 2 0.605957 1 0.22998 -21 27 3 0.605957 1 0.22998 -21 27 4 0.605957 1 0.22998 -21 27 5 0.605957 1 0.22998 -21 27 6 0.605957 1 0.22998 -21 27 7 0.605957 1 0.22998 -21 27 8 0.605957 1 0.22998 -21 27 9 0.605957 1 0.22998 -21 27 10 0.605957 1 0.22998 -21 27 11 0.605957 1 0.22998 -21 27 12 0.606445 1 0.230103 -21 27 13 0.606445 1 0.230103 -21 27 14 0.606445 1 0.230103 -21 27 15 0.606934 1 0.233521 -21 27 16 0.601074 1 0.339111 -21 27 17 0.592773 1 0.431396 -21 27 18 0.580566 1 0.518066 -21 27 19 0.563477 1 0.600098 -21 27 20 0.541504 1 0.675781 -21 27 21 0.513672 1 0.74707 -21 27 22 0.478027 1 0.8125 -21 27 23 0.435547 1 0.868652 -21 27 24 0.383545 1 0.91748 -21 27 25 0.309082 1 0.963379 -21 27 26 0.164429 1 1 -21 27 27 0 1 1 -21 27 28 0 0.997559 1 -21 27 29 0 0.955078 1 -21 27 30 0 0.908691 1 -21 27 31 0 0.861328 1 -21 28 0 0.493896 1 0.217285 -21 28 1 0.493896 1 0.217285 -21 28 2 0.493896 1 0.217285 -21 28 3 0.493896 1 0.217285 -21 28 4 0.493896 1 0.217285 -21 28 5 0.493896 1 0.217285 -21 28 6 0.493896 1 0.217285 -21 28 7 0.493896 1 0.217285 -21 28 8 0.493896 1 0.217285 -21 28 9 0.493896 1 0.217285 -21 28 10 0.493896 1 0.217285 -21 28 11 0.493896 1 0.217407 -21 28 12 0.494141 1 0.217407 -21 28 13 0.494385 1 0.217407 -21 28 14 0.494629 1 0.217407 -21 28 15 0.495117 1 0.217529 -21 28 16 0.489746 1 0.302979 -21 28 17 0.479004 1 0.397949 -21 28 18 0.463623 1 0.484619 -21 28 19 0.442139 1 0.565918 -21 28 20 0.413818 1 0.641113 -21 28 21 0.375977 1 0.711914 -21 28 22 0.323975 1 0.776855 -21 28 23 0.249512 1 0.834473 -21 28 24 0.0376892 1 0.884766 -21 28 25 0 1 0.932617 -21 28 26 0 1 0.977539 -21 28 27 0 1 1 -21 28 28 0 1 1 -21 28 29 0 1 1 -21 28 30 0 0.959961 1 -21 28 31 0 0.913086 1 -21 29 0 0.330566 1 0.204102 -21 29 1 0.330566 1 0.204102 -21 29 2 0.330566 1 0.204102 -21 29 3 0.330566 1 0.204102 -21 29 4 0.330566 1 0.204102 -21 29 5 0.330566 1 0.204102 -21 29 6 0.330566 1 0.204102 -21 29 7 0.330566 1 0.204102 -21 29 8 0.330566 1 0.204102 -21 29 9 0.330811 1 0.204102 -21 29 10 0.330811 1 0.204224 -21 29 11 0.331055 1 0.204224 -21 29 12 0.331299 1 0.204224 -21 29 13 0.331543 1 0.204224 -21 29 14 0.332275 1 0.204346 -21 29 15 0.333252 1 0.204346 -21 29 16 0.327393 1 0.261719 -21 29 17 0.307617 1 0.361572 -21 29 18 0.276855 1 0.44873 -21 29 19 0.228149 1 0.529297 -21 29 20 0.127441 1 0.603516 -21 29 21 0 1 0.67334 -21 29 22 0 1 0.738281 -21 29 23 0 1 0.79541 -21 29 24 0 1 0.84668 -21 29 25 0 1 0.896484 -21 29 26 0 1 0.943848 -21 29 27 0 1 0.987305 -21 29 28 0 1 1 -21 29 29 0 1 1 -21 29 30 0 1 1 -21 29 31 0 0.963867 1 -21 30 0 0 1 0.190552 -21 30 1 0 1 0.190552 -21 30 2 0 1 0.190552 -21 30 3 0 1 0.190552 -21 30 4 0 1 0.190552 -21 30 5 0 1 0.190552 -21 30 6 0 1 0.190552 -21 30 7 0 1 0.190552 -21 30 8 0 1 0.190552 -21 30 9 0 1 0.190552 -21 30 10 0 1 0.190552 -21 30 11 0 1 0.190552 -21 30 12 0 1 0.190552 -21 30 13 0 1 0.190674 -21 30 14 0 1 0.190674 -21 30 15 0 1 0.190796 -21 30 16 0 1 0.21228 -21 30 17 0 1 0.322266 -21 30 18 0 1 0.410645 -21 30 19 0 1 0.490234 -21 30 20 0 1 0.563477 -21 30 21 0 1 0.631836 -21 30 22 0 1 0.695801 -21 30 23 0 1 0.75293 -21 30 24 0 1 0.804199 -21 30 25 0 1 0.85498 -21 30 26 0 1 0.904297 -21 30 27 0 1 0.951172 -21 30 28 0 1 0.993652 -21 30 29 0 1 1 -21 30 30 0 1 1 -21 30 31 0 1 1 -21 31 0 0 1 0.176758 -21 31 1 0 1 0.176758 -21 31 2 0 1 0.176758 -21 31 3 0 1 0.176758 -21 31 4 0 1 0.176758 -21 31 5 0 1 0.176758 -21 31 6 0 1 0.176758 -21 31 7 0 1 0.176758 -21 31 8 0 1 0.176758 -21 31 9 0 1 0.176758 -21 31 10 0 1 0.176758 -21 31 11 0 1 0.176758 -21 31 12 0 1 0.17688 -21 31 13 0 1 0.17688 -21 31 14 0 1 0.17688 -21 31 15 0 1 0.177002 -21 31 16 0 1 0.177124 -21 31 17 0 1 0.279053 -21 31 18 0 1 0.370605 -21 31 19 0 1 0.449707 -21 31 20 0 1 0.520996 -21 31 21 0 1 0.588379 -21 31 22 0 1 0.650879 -21 31 23 0 1 0.707031 -21 31 24 0 1 0.758301 -21 31 25 0 1 0.80957 -21 31 26 0 1 0.860352 -21 31 27 0 1 0.909668 -21 31 28 0 1 0.956055 -21 31 29 0 1 0.999023 -21 31 30 0 1 1 -21 31 31 0 1 1 -22 0 0 1 0 0.061615 -22 0 1 1 0 0.061615 -22 0 2 1 0 0.061615 -22 0 3 1 0 0.061615 -22 0 4 1 0 0.061615 -22 0 5 1 0 0.0615845 -22 0 6 1 0 0.061554 -22 0 7 1 0 0.0615234 -22 0 8 1 0 0.0614014 -22 0 9 1 0 0.0611877 -22 0 10 1 0 0.060791 -22 0 11 1 0 0.0600891 -22 0 12 1 0 0.0588684 -22 0 13 1 0 0.0572815 -22 0 14 1 0 0.0748291 -22 0 15 1 0 0.287109 -22 0 16 1 0 0.411621 -22 0 17 1 0 0.520996 -22 0 18 1 0.0924683 0.635742 -22 0 19 1 0.257812 0.746094 -22 0 20 1 0.329834 0.836914 -22 0 21 1 0.35376 0.905762 -22 0 22 1 0.356689 0.958984 -22 0 23 1 0.356445 0.999023 -22 0 24 0.960938 0.354004 1 -22 0 25 0.901367 0.349121 1 -22 0 26 0.835449 0.342773 1 -22 0 27 0.765137 0.335449 1 -22 0 28 0.693359 0.328125 1 -22 0 29 0.619629 0.321289 1 -22 0 30 0.543457 0.315186 1 -22 0 31 0.462646 0.309814 1 -22 1 0 1 0 0.061615 -22 1 1 1 0 0.061615 -22 1 2 1 0 0.061615 -22 1 3 1 0 0.061615 -22 1 4 1 0 0.0615845 -22 1 5 1 0 0.0615845 -22 1 6 1 0 0.061554 -22 1 7 1 0 0.0614929 -22 1 8 1 0 0.0613708 -22 1 9 1 0 0.0611572 -22 1 10 1 0 0.0607605 -22 1 11 1 0 0.0600586 -22 1 12 1 0 0.0588379 -22 1 13 1 0 0.0572815 -22 1 14 1 0 0.0748291 -22 1 15 1 0 0.287109 -22 1 16 1 0 0.411621 -22 1 17 1 0 0.520996 -22 1 18 1 0.0926514 0.635742 -22 1 19 1 0.257812 0.746094 -22 1 20 1 0.329834 0.836914 -22 1 21 1 0.35376 0.905762 -22 1 22 1 0.356689 0.958984 -22 1 23 1 0.356445 0.999023 -22 1 24 0.960938 0.354004 1 -22 1 25 0.901367 0.349121 1 -22 1 26 0.835449 0.342773 1 -22 1 27 0.765137 0.335449 1 -22 1 28 0.693359 0.328125 1 -22 1 29 0.619629 0.321289 1 -22 1 30 0.543457 0.315186 1 -22 1 31 0.462646 0.309814 1 -22 2 0 1 0 0.0615845 -22 2 1 1 0 0.0615845 -22 2 2 1 0 0.0615845 -22 2 3 1 0 0.0615845 -22 2 4 1 0 0.061554 -22 2 5 1 0 0.061554 -22 2 6 1 0 0.0615234 -22 2 7 1 0 0.0614624 -22 2 8 1 0 0.0613403 -22 2 9 1 0 0.0611267 -22 2 10 1 0 0.06073 -22 2 11 1 0 0.0600586 -22 2 12 1 0 0.0588074 -22 2 13 1 0 0.057251 -22 2 14 1 0 0.0748901 -22 2 15 1 0 0.287109 -22 2 16 1 0 0.411621 -22 2 17 1 0 0.520996 -22 2 18 1 0.0929565 0.635742 -22 2 19 1 0.258057 0.746094 -22 2 20 1 0.329834 0.836914 -22 2 21 1 0.35376 0.905762 -22 2 22 1 0.356689 0.958984 -22 2 23 1 0.356445 0.999023 -22 2 24 0.960938 0.354004 1 -22 2 25 0.901367 0.349121 1 -22 2 26 0.835449 0.342773 1 -22 2 27 0.765137 0.335449 1 -22 2 28 0.693359 0.328125 1 -22 2 29 0.619629 0.321289 1 -22 2 30 0.543457 0.315186 1 -22 2 31 0.462646 0.309814 1 -22 3 0 1 0 0.0615234 -22 3 1 1 0 0.0615234 -22 3 2 1 0 0.0615234 -22 3 3 1 0 0.0615234 -22 3 4 1 0 0.0615234 -22 3 5 1 0 0.0614929 -22 3 6 1 0 0.0614624 -22 3 7 1 0 0.0614014 -22 3 8 1 0 0.0613098 -22 3 9 1 0 0.0610962 -22 3 10 1 0 0.0606995 -22 3 11 1 0 0.0599976 -22 3 12 1 0 0.0587463 -22 3 13 1 0 0.0571899 -22 3 14 1 0 0.0748901 -22 3 15 1 0 0.287109 -22 3 16 1 0 0.411621 -22 3 17 1 0 0.520996 -22 3 18 1 0.0934448 0.635742 -22 3 19 1 0.258057 0.746094 -22 3 20 1 0.329834 0.836914 -22 3 21 1 0.354004 0.905762 -22 3 22 1 0.356689 0.958984 -22 3 23 1 0.356689 0.999023 -22 3 24 0.960938 0.354004 1 -22 3 25 0.901367 0.349121 1 -22 3 26 0.835449 0.342773 1 -22 3 27 0.765137 0.335449 1 -22 3 28 0.693359 0.328125 1 -22 3 29 0.619629 0.321289 1 -22 3 30 0.543457 0.315186 1 -22 3 31 0.462646 0.310059 1 -22 4 0 1 0 0.0614319 -22 4 1 1 0 0.0614319 -22 4 2 1 0 0.0614319 -22 4 3 1 0 0.0614319 -22 4 4 1 0 0.0614319 -22 4 5 1 0 0.0614014 -22 4 6 1 0 0.0613708 -22 4 7 1 0 0.0613098 -22 4 8 1 0 0.0612183 -22 4 9 1 0 0.0609741 -22 4 10 1 0 0.0605774 -22 4 11 1 0 0.0598755 -22 4 12 1 0 0.0586548 -22 4 13 1 0 0.0570679 -22 4 14 1 0 0.0748901 -22 4 15 1 0 0.287109 -22 4 16 1 0 0.411621 -22 4 17 1 0 0.520996 -22 4 18 1 0.0943604 0.635742 -22 4 19 1 0.258301 0.746094 -22 4 20 1 0.330078 0.836914 -22 4 21 1 0.354004 0.905762 -22 4 22 1 0.356934 0.958984 -22 4 23 1 0.356689 0.999023 -22 4 24 0.960938 0.354004 1 -22 4 25 0.901367 0.349365 1 -22 4 26 0.835449 0.342773 1 -22 4 27 0.765137 0.335693 1 -22 4 28 0.693359 0.328125 1 -22 4 29 0.619629 0.321289 1 -22 4 30 0.543457 0.315186 1 -22 4 31 0.462646 0.310059 1 -22 5 0 1 0 0.0612488 -22 5 1 1 0 0.0612488 -22 5 2 1 0 0.0612488 -22 5 3 1 0 0.0612488 -22 5 4 1 0 0.0612183 -22 5 5 1 0 0.0612183 -22 5 6 1 0 0.0611877 -22 5 7 1 0 0.0611267 -22 5 8 1 0 0.0610046 -22 5 9 1 0 0.060791 -22 5 10 1 0 0.0603943 -22 5 11 1 0 0.0596924 -22 5 12 1 0 0.0584412 -22 5 13 1 0 0.0568542 -22 5 14 1 0 0.0748901 -22 5 15 1 0 0.287109 -22 5 16 1 0 0.411621 -22 5 17 1 0 0.520996 -22 5 18 1 0.0961914 0.635742 -22 5 19 1 0.258545 0.746094 -22 5 20 1 0.330322 0.836914 -22 5 21 1 0.354248 0.905762 -22 5 22 1 0.356934 0.958984 -22 5 23 1 0.356934 0.999023 -22 5 24 0.960938 0.354248 1 -22 5 25 0.901367 0.349365 1 -22 5 26 0.835449 0.343018 1 -22 5 27 0.765137 0.335693 1 -22 5 28 0.693359 0.328369 1 -22 5 29 0.619629 0.321533 1 -22 5 30 0.543457 0.315186 1 -22 5 31 0.462646 0.310059 1 -22 6 0 1 0 0.0608826 -22 6 1 1 0 0.0608826 -22 6 2 1 0 0.0608826 -22 6 3 1 0 0.0608826 -22 6 4 1 0 0.0608521 -22 6 5 1 0 0.0608521 -22 6 6 1 0 0.0608215 -22 6 7 1 0 0.0607605 -22 6 8 1 0 0.0606384 -22 6 9 1 0 0.0604248 -22 6 10 1 0 0.0600281 -22 6 11 1 0 0.0593262 -22 6 12 1 0 0.0580444 -22 6 13 1 0 0.0564575 -22 6 14 1 0 0.0749512 -22 6 15 1 0 0.286865 -22 6 16 1 0 0.411621 -22 6 17 1 0 0.520996 -22 6 18 1 0.0994263 0.635742 -22 6 19 1 0.259277 0.746094 -22 6 20 1 0.330811 0.836914 -22 6 21 1 0.354736 0.905762 -22 6 22 1 0.357422 0.958984 -22 6 23 1 0.357178 0.999023 -22 6 24 0.960938 0.354736 1 -22 6 25 0.901367 0.349854 1 -22 6 26 0.835449 0.343262 1 -22 6 27 0.765137 0.335938 1 -22 6 28 0.693359 0.328613 1 -22 6 29 0.619629 0.321533 1 -22 6 30 0.543457 0.31543 1 -22 6 31 0.462646 0.310303 1 -22 7 0 1 0 0.0601501 -22 7 1 1 0 0.0601501 -22 7 2 1 0 0.0601501 -22 7 3 1 0 0.0601501 -22 7 4 1 0 0.0601501 -22 7 5 1 0 0.0601196 -22 7 6 1 0 0.0600891 -22 7 7 1 0 0.0600281 -22 7 8 1 0 0.0599365 -22 7 9 1 0 0.0596924 -22 7 10 1 0 0.0592957 -22 7 11 1 0 0.0585632 -22 7 12 1 0 0.0572815 -22 7 13 1 0 0.0556335 -22 7 14 1 0 0.0750732 -22 7 15 1 0 0.286865 -22 7 16 1 0 0.411621 -22 7 17 1 0 0.520996 -22 7 18 1 0.105347 0.635254 -22 7 19 1 0.260742 0.746094 -22 7 20 1 0.331787 0.836914 -22 7 21 1 0.355469 0.905762 -22 7 22 1 0.358154 0.958984 -22 7 23 1 0.35791 0.999023 -22 7 24 0.960938 0.355225 1 -22 7 25 0.901367 0.350342 1 -22 7 26 0.835449 0.34375 1 -22 7 27 0.765137 0.336426 1 -22 7 28 0.693359 0.329102 1 -22 7 29 0.619629 0.322021 1 -22 7 30 0.543457 0.315674 1 -22 7 31 0.462646 0.310547 1 -22 8 0 1 0 0.0587158 -22 8 1 1 0 0.0587158 -22 8 2 1 0 0.0587158 -22 8 3 1 0 0.0587158 -22 8 4 1 0 0.0586853 -22 8 5 1 0 0.0586853 -22 8 6 1 0 0.0586548 -22 8 7 1 0 0.0585938 -22 8 8 1 0 0.0584717 -22 8 9 1 0 0.0582275 -22 8 10 1 0 0.0578003 -22 8 11 1 0 0.0570374 -22 8 12 1 0 0.0556946 -22 8 13 1 0 0.0539856 -22 8 14 1 0 0.0753174 -22 8 15 1 0 0.286865 -22 8 16 1 0 0.411621 -22 8 17 1 0 0.520996 -22 8 18 1 0.115601 0.635254 -22 8 19 1 0.263184 0.745605 -22 8 20 1 0.333496 0.836914 -22 8 21 1 0.357178 0.905762 -22 8 22 1 0.359619 0.958984 -22 8 23 1 0.359375 0.999023 -22 8 24 0.960938 0.356689 1 -22 8 25 0.901367 0.351562 1 -22 8 26 0.834961 0.344971 1 -22 8 27 0.765137 0.337402 1 -22 8 28 0.692871 0.329834 1 -22 8 29 0.619141 0.322754 1 -22 8 30 0.543457 0.316406 1 -22 8 31 0.462402 0.311035 1 -22 9 0 1 0 0.0557556 -22 9 1 1 0 0.0557556 -22 9 2 1 0 0.0557556 -22 9 3 1 0 0.0557556 -22 9 4 1 0 0.0557251 -22 9 5 1 0 0.0557251 -22 9 6 1 0 0.0556946 -22 9 7 1 0 0.055603 -22 9 8 1 0 0.055481 -22 9 9 1 0 0.0552368 -22 9 10 1 0 0.0547791 -22 9 11 1 0 0.0539246 -22 9 12 1 0 0.0524597 -22 9 13 1 0 0.0505676 -22 9 14 1 0 0.0758057 -22 9 15 1 0 0.286865 -22 9 16 1 0 0.411377 -22 9 17 1 0 0.520996 -22 9 18 1 0.131958 0.635254 -22 9 19 1 0.268066 0.745605 -22 9 20 1 0.336914 0.836914 -22 9 21 1 0.360352 0.905762 -22 9 22 1 0.362549 0.958984 -22 9 23 1 0.362061 0.999023 -22 9 24 0.960938 0.359131 1 -22 9 25 0.900879 0.35376 1 -22 9 26 0.834961 0.346924 1 -22 9 27 0.765137 0.339111 1 -22 9 28 0.692871 0.331299 1 -22 9 29 0.619141 0.323975 1 -22 9 30 0.543457 0.317627 1 -22 9 31 0.462402 0.312012 1 -22 10 0 1 0 0.0496216 -22 10 1 1 0 0.0496216 -22 10 2 1 0 0.0496216 -22 10 3 1 0 0.0495911 -22 10 4 1 0 0.0495911 -22 10 5 1 0 0.0495605 -22 10 6 1 0 0.04953 -22 10 7 1 0 0.0494385 -22 10 8 1 0 0.0492859 -22 10 9 1 0 0.0489807 -22 10 10 1 0 0.0484009 -22 10 11 1 0 0.0473938 -22 10 12 1 0 0.0455627 -22 10 13 1 0 0.0431824 -22 10 14 1 0 0.0769043 -22 10 15 1 0 0.286621 -22 10 16 1 0 0.410889 -22 10 17 1 0 0.520508 -22 10 18 1 0.155396 0.634766 -22 10 19 1 0.276611 0.745605 -22 10 20 1 0.343262 0.836914 -22 10 21 1 0.365723 0.905762 -22 10 22 1 0.367676 0.958984 -22 10 23 1 0.366699 0.999023 -22 10 24 0.960449 0.363281 1 -22 10 25 0.900879 0.357666 1 -22 10 26 0.834473 0.350342 1 -22 10 27 0.764648 0.342285 1 -22 10 28 0.692383 0.334229 1 -22 10 29 0.618652 0.326416 1 -22 10 30 0.542969 0.319824 1 -22 10 31 0.461914 0.313965 1 -22 11 0 1 0 0.0340271 -22 11 1 1 0 0.0340271 -22 11 2 1 0 0.0340271 -22 11 3 1 0 0.0339966 -22 11 4 1 0 0.0339966 -22 11 5 1 0 0.0339355 -22 11 6 1 0 0.0338745 -22 11 7 1 0 0.0337219 -22 11 8 1 0 0.0334167 -22 11 9 1 0 0.0328369 -22 11 10 1 0 0.0317383 -22 11 11 1 0 0.0296478 -22 11 12 1 0 0.0254059 -22 11 13 1 0 0.0179749 -22 11 14 1 0 0.0791626 -22 11 15 1 0 0.286621 -22 11 16 1 0 0.4104 -22 11 17 1 0 0.52002 -22 11 18 1 0.186646 0.634277 -22 11 19 1 0.290527 0.745117 -22 11 20 1 0.353516 0.836426 -22 11 21 1 0.375 0.905762 -22 11 22 1 0.376465 0.958984 -22 11 23 1 0.375 0.999023 -22 11 24 0.959961 0.37085 1 -22 11 25 0.900391 0.364502 1 -22 11 26 0.833984 0.356445 1 -22 11 27 0.76416 0.347656 1 -22 11 28 0.691895 0.339111 1 -22 11 29 0.618164 0.330811 1 -22 11 30 0.54248 0.323486 1 -22 11 31 0.461426 0.317383 1 -22 12 0 1 0.140625 0 -22 12 1 1 0.140625 0 -22 12 2 1 0.140625 0 -22 12 3 1 0.140625 0 -22 12 4 1 0.140747 0 -22 12 5 1 0.140869 0 -22 12 6 1 0.140991 0 -22 12 7 1 0.141357 0 -22 12 8 1 0.141968 0 -22 12 9 1 0.143188 0 -22 12 10 1 0.145386 0 -22 12 11 1 0.149048 0 -22 12 12 1 0.155029 0 -22 12 13 1 0.161621 0 -22 12 14 1 0.164429 0.0841064 -22 12 15 1 0.151733 0.286621 -22 12 16 1 0.151611 0.409424 -22 12 17 1 0.160645 0.519531 -22 12 18 1 0.226074 0.633301 -22 12 19 1 0.312012 0.744141 -22 12 20 1 0.370361 0.836426 -22 12 21 1 0.390137 0.905762 -22 12 22 1 0.390625 0.958984 -22 12 23 1 0.388184 0.999023 -22 12 24 0.958984 0.383057 1 -22 12 25 0.899414 0.375732 1 -22 12 26 0.833008 0.366699 1 -22 12 27 0.763184 0.356689 1 -22 12 28 0.690918 0.346924 1 -22 12 29 0.617188 0.337891 1 -22 12 30 0.541504 0.329834 1 -22 12 31 0.460449 0.322754 1 -22 13 0 1 0.228882 0 -22 13 1 1 0.228882 0 -22 13 2 1 0.228882 0 -22 13 3 1 0.229004 0 -22 13 4 1 0.229004 0 -22 13 5 1 0.229004 0 -22 13 6 1 0.229126 0 -22 13 7 1 0.229248 0 -22 13 8 1 0.229492 0 -22 13 9 1 0.230103 0 -22 13 10 1 0.231201 0 -22 13 11 1 0.23291 0 -22 13 12 1 0.235962 0 -22 13 13 1 0.23938 0 -22 13 14 1 0.239746 0.0942383 -22 13 15 1 0.2323 0.287109 -22 13 16 1 0.22998 0.408203 -22 13 17 1 0.235718 0.519043 -22 13 18 1 0.273926 0.631348 -22 13 19 1 0.342773 0.742676 -22 13 20 1 0.395264 0.835938 -22 13 21 1 0.413086 0.905762 -22 13 22 1 0.412354 0.958984 -22 13 23 1 0.408447 0.999023 -22 13 24 0.95752 0.401855 1 -22 13 25 0.897949 0.392822 1 -22 13 26 0.831543 0.38208 1 -22 13 27 0.761719 0.37085 1 -22 13 28 0.689453 0.359619 1 -22 13 29 0.615723 0.348877 1 -22 13 30 0.540039 0.3396 1 -22 13 31 0.45874 0.331543 1 -22 14 0 1 0.307861 0 -22 14 1 1 0.307861 0 -22 14 2 1 0.308105 0 -22 14 3 1 0.308105 0 -22 14 4 1 0.308105 0 -22 14 5 1 0.308105 0 -22 14 6 1 0.308105 0 -22 14 7 1 0.308105 0 -22 14 8 1 0.30835 0 -22 14 9 1 0.308838 0 -22 14 10 1 0.309326 0 -22 14 11 1 0.310547 0 -22 14 12 1 0.3125 0 -22 14 13 1 0.314697 0 -22 14 14 1 0.313721 0.112915 -22 14 15 1 0.30835 0.289307 -22 14 16 1 0.304688 0.407471 -22 14 17 1 0.309326 0.518555 -22 14 18 1 0.330566 0.628906 -22 14 19 1 0.384033 0.740723 -22 14 20 1 0.43042 0.834961 -22 14 21 1 0.446045 0.905273 -22 14 22 1 0.443359 0.958984 -22 14 23 1 0.4375 0.999512 -22 14 24 0.955078 0.429199 1 -22 14 25 0.895508 0.417969 1 -22 14 26 0.829102 0.405029 1 -22 14 27 0.759277 0.391357 1 -22 14 28 0.687012 0.378174 1 -22 14 29 0.613281 0.365479 1 -22 14 30 0.537598 0.354492 1 -22 14 31 0.455811 0.344727 1 -22 15 0 1 0.389404 0 -22 15 1 1 0.389404 0 -22 15 2 1 0.389404 0 -22 15 3 1 0.389404 0 -22 15 4 1 0.389404 0 -22 15 5 1 0.389404 0 -22 15 6 1 0.389404 0 -22 15 7 1 0.389648 0 -22 15 8 1 0.389648 0 -22 15 9 1 0.389893 0 -22 15 10 1 0.390381 0 -22 15 11 1 0.391113 0 -22 15 12 1 0.392578 0 -22 15 13 1 0.394287 0 -22 15 14 1 0.392578 0.142456 -22 15 15 1 0.388428 0.295654 -22 15 16 1 0.383789 0.408203 -22 15 17 1 0.38623 0.518555 -22 15 18 1 0.395996 0.625 -22 15 19 1 0.435547 0.736816 -22 15 20 1 0.476074 0.833008 -22 15 21 1 0.489746 0.904785 -22 15 22 1 0.485107 0.958984 -22 15 23 1 0.477051 0.999023 -22 15 24 0.95166 0.466064 1 -22 15 25 0.891602 0.452148 1 -22 15 26 0.825195 0.436523 1 -22 15 27 0.755371 0.419922 1 -22 15 28 0.683105 0.403809 1 -22 15 29 0.609375 0.388916 1 -22 15 30 0.533691 0.375244 1 -22 15 31 0.45166 0.363281 1 -22 16 0 1 0.476807 0 -22 16 1 1 0.476807 0 -22 16 2 1 0.476807 0 -22 16 3 1 0.476807 0 -22 16 4 1 0.476807 0 -22 16 5 1 0.476807 0 -22 16 6 1 0.476807 0 -22 16 7 1 0.476807 0 -22 16 8 1 0.477051 0 -22 16 9 1 0.477295 0 -22 16 10 1 0.477539 0 -22 16 11 1 0.478027 0 -22 16 12 1 0.479248 0 -22 16 13 1 0.480713 0 -22 16 14 1 0.47876 0.183105 -22 16 15 1 0.475342 0.30957 -22 16 16 1 0.470459 0.413818 -22 16 17 1 0.467041 0.516602 -22 16 18 1 0.47168 0.621582 -22 16 19 1 0.496826 0.730469 -22 16 20 1 0.532227 0.830078 -22 16 21 1 0.544434 0.903809 -22 16 22 1 0.537598 0.958008 -22 16 23 0.99707 0.527344 0.999023 -22 16 24 0.945312 0.513184 1 -22 16 25 0.885254 0.496094 1 -22 16 26 0.818848 0.476807 1 -22 16 27 0.749023 0.457031 1 -22 16 28 0.677246 0.437744 1 -22 16 29 0.604004 0.419678 1 -22 16 30 0.527832 0.40332 1 -22 16 31 0.445312 0.388672 1 -22 17 0 1 0.568359 0 -22 17 1 1 0.568359 0 -22 17 2 1 0.568359 0 -22 17 3 1 0.568359 0 -22 17 4 1 0.568359 0 -22 17 5 1 0.568359 0 -22 17 6 1 0.568359 0 -22 17 7 1 0.568848 0 -22 17 8 1 0.568848 0 -22 17 9 1 0.568848 0 -22 17 10 1 0.568848 0 -22 17 11 1 0.569336 0 -22 17 12 1 0.570312 0.0261383 -22 17 13 1 0.571777 0.0415039 -22 17 14 1 0.570312 0.230713 -22 17 15 1 0.568359 0.333496 -22 17 16 1 0.563477 0.427979 -22 17 17 1 0.557129 0.521484 -22 17 18 1 0.555664 0.619629 -22 17 19 1 0.56543 0.72168 -22 17 20 1 0.594727 0.824219 -22 17 21 1 0.607422 0.901367 -22 17 22 1 0.598633 0.956543 -22 17 23 0.988281 0.585449 0.997559 -22 17 24 0.936523 0.568848 1 -22 17 25 0.875977 0.547852 1 -22 17 26 0.810059 0.524902 1 -22 17 27 0.740723 0.501465 1 -22 17 28 0.668945 0.478516 1 -22 17 29 0.595703 0.457031 1 -22 17 30 0.519531 0.4375 1 -22 17 31 0.436279 0.419922 1 -22 18 0 1 0.662109 0.201904 -22 18 1 1 0.662109 0.201904 -22 18 2 1 0.662109 0.201904 -22 18 3 1 0.662109 0.201904 -22 18 4 1 0.662109 0.201904 -22 18 5 1 0.662109 0.201904 -22 18 6 1 0.662109 0.201904 -22 18 7 1 0.662109 0.201904 -22 18 8 1 0.662109 0.201904 -22 18 9 1 0.662598 0.202026 -22 18 10 1 0.662598 0.202271 -22 18 11 1 0.663086 0.202515 -22 18 12 1 0.663574 0.203003 -22 18 13 1 0.664551 0.203857 -22 18 14 1 0.664551 0.276855 -22 18 15 1 0.663086 0.36377 -22 18 16 1 0.660156 0.450195 -22 18 17 1 0.65332 0.536133 -22 18 18 1 0.644531 0.62207 -22 18 19 1 0.643066 0.714844 -22 18 20 1 0.660645 0.813965 -22 18 21 1 0.674805 0.896973 -22 18 22 1 0.665039 0.953613 -22 18 23 0.975586 0.649414 0.995117 -22 18 24 0.92334 0.628906 1 -22 18 25 0.863281 0.604492 1 -22 18 26 0.797852 0.578125 1 -22 18 27 0.729004 0.550781 1 -22 18 28 0.658203 0.524414 1 -22 18 29 0.584961 0.5 1 -22 18 30 0.508301 0.477295 1 -22 18 31 0.423828 0.456543 1 -22 19 0 1 0.753418 0.265137 -22 19 1 1 0.753418 0.265137 -22 19 2 1 0.753418 0.265137 -22 19 3 1 0.753418 0.265137 -22 19 4 1 0.753418 0.265137 -22 19 5 1 0.753418 0.265137 -22 19 6 1 0.753418 0.265137 -22 19 7 1 0.753418 0.265381 -22 19 8 1 0.753418 0.265381 -22 19 9 1 0.753418 0.265381 -22 19 10 1 0.753418 0.265381 -22 19 11 1 0.753906 0.265625 -22 19 12 1 0.754395 0.265869 -22 19 13 1 0.754883 0.266113 -22 19 14 1 0.755371 0.312012 -22 19 15 1 0.755371 0.390869 -22 19 16 1 0.753906 0.473145 -22 19 17 1 0.749512 0.556152 -22 19 18 1 0.740234 0.636719 -22 19 19 1 0.727539 0.714355 -22 19 20 1 0.727051 0.800293 -22 19 21 1 0.742188 0.889648 -22 19 22 1 0.732422 0.948242 -22 19 23 0.958008 0.714355 0.990234 -22 19 24 0.905762 0.690918 1 -22 19 25 0.846191 0.662598 1 -22 19 26 0.781738 0.632812 1 -22 19 27 0.713867 0.603027 1 -22 19 28 0.644531 0.57373 1 -22 19 29 0.571777 0.545898 1 -22 19 30 0.494629 0.520508 1 -22 19 31 0.407715 0.496582 1 -22 20 0 1 0.836914 0.29834 -22 20 1 1 0.836914 0.29834 -22 20 2 1 0.836914 0.29834 -22 20 3 1 0.836914 0.29834 -22 20 4 1 0.836914 0.29834 -22 20 5 1 0.836914 0.29834 -22 20 6 1 0.836914 0.29834 -22 20 7 1 0.836914 0.29834 -22 20 8 1 0.836914 0.29834 -22 20 9 1 0.836914 0.29834 -22 20 10 1 0.837402 0.29834 -22 20 11 1 0.837402 0.298584 -22 20 12 1 0.837891 0.298584 -22 20 13 1 0.838379 0.298828 -22 20 14 1 0.838867 0.328125 -22 20 15 1 0.839844 0.404785 -22 20 16 1 0.839355 0.486816 -22 20 17 1 0.836914 0.570801 -22 20 18 1 0.830566 0.652832 -22 20 19 1 0.818359 0.727539 -22 20 20 1 0.801758 0.794434 -22 20 21 1 0.803711 0.876465 -22 20 22 0.979492 0.797852 0.940918 -22 20 23 0.935059 0.776855 0.982422 -22 20 24 0.882812 0.75 1 -22 20 25 0.824707 0.719238 1 -22 20 26 0.762207 0.6875 1 -22 20 27 0.696777 0.655273 1 -22 20 28 0.62793 0.624023 1 -22 20 29 0.555664 0.59375 1 -22 20 30 0.477783 0.56543 1 -22 20 31 0.387451 0.538574 1 -22 21 0 1 0.911621 0.308838 -22 21 1 1 0.911621 0.308838 -22 21 2 1 0.911621 0.308838 -22 21 3 1 0.911621 0.308838 -22 21 4 1 0.911621 0.308838 -22 21 5 1 0.911621 0.308838 -22 21 6 1 0.911621 0.308838 -22 21 7 1 0.911621 0.308838 -22 21 8 1 0.911621 0.308838 -22 21 9 1 0.911621 0.308838 -22 21 10 1 0.911621 0.308838 -22 21 11 1 0.911621 0.308838 -22 21 12 1 0.912109 0.308838 -22 21 13 1 0.912598 0.309082 -22 21 14 1 0.913086 0.32373 -22 21 15 1 0.914551 0.4021 -22 21 16 1 0.915039 0.48584 -22 21 17 1 0.914062 0.571777 -22 21 18 1 0.910156 0.656738 -22 21 19 1 0.901855 0.73584 -22 21 20 1 0.886719 0.804688 -22 21 21 0.975586 0.865234 0.862305 -22 21 22 0.950684 0.859863 0.930176 -22 21 23 0.905273 0.835449 0.969727 -22 21 24 0.854492 0.806152 0.995605 -22 21 25 0.799316 0.774902 1 -22 21 26 0.740234 0.742676 1 -22 21 27 0.676758 0.709473 1 -22 21 28 0.609863 0.67627 1 -22 21 29 0.537109 0.644043 1 -22 21 30 0.457275 0.612793 1 -22 21 31 0.361328 0.583496 1 -22 22 0 1 0.973145 0.30542 -22 22 1 1 0.973145 0.30542 -22 22 2 1 0.973145 0.30542 -22 22 3 1 0.973145 0.30542 -22 22 4 1 0.973145 0.30542 -22 22 5 1 0.973145 0.30542 -22 22 6 1 0.973145 0.30542 -22 22 7 1 0.973145 0.30542 -22 22 8 1 0.973145 0.30542 -22 22 9 1 0.973145 0.30542 -22 22 10 1 0.973145 0.30542 -22 22 11 1 0.973145 0.30542 -22 22 12 1 0.973633 0.30542 -22 22 13 1 0.973633 0.30542 -22 22 14 1 0.974121 0.30542 -22 22 15 1 0.975586 0.386475 -22 22 16 1 0.977051 0.471924 -22 22 17 1 0.976562 0.55957 -22 22 18 1 0.974121 0.645996 -22 22 19 1 0.967285 0.727539 -22 22 20 0.989746 0.956055 0.800781 -22 22 21 0.956543 0.938965 0.864258 -22 22 22 0.916504 0.916504 0.916504 -22 22 23 0.871582 0.890137 0.955566 -22 22 24 0.825684 0.862305 0.986328 -22 22 25 0.773926 0.832031 1 -22 22 26 0.717285 0.799316 1 -22 22 27 0.655273 0.764648 1 -22 22 28 0.587891 0.729004 1 -22 22 29 0.51416 0.693848 1 -22 22 30 0.430176 0.659668 1 -22 22 31 0.325439 0.626465 1 -22 23 0 1 1 0.297119 -22 23 1 1 1 0.297119 -22 23 2 1 1 0.297119 -22 23 3 1 1 0.297119 -22 23 4 1 1 0.297119 -22 23 5 1 1 0.297119 -22 23 6 1 1 0.297119 -22 23 7 1 1 0.297119 -22 23 8 1 1 0.297119 -22 23 9 1 1 0.297119 -22 23 10 1 1 0.297119 -22 23 11 1 1 0.297119 -22 23 12 1 1 0.297119 -22 23 13 1 1 0.297119 -22 23 14 1 1 0.297119 -22 23 15 1 1 0.364746 -22 23 16 1 1 0.451904 -22 23 17 0.998535 1 0.540039 -22 23 18 0.986816 1 0.626465 -22 23 19 0.969238 1 0.70752 -22 23 20 0.944824 1 0.780762 -22 23 21 0.913086 0.985352 0.844238 -22 23 22 0.878418 0.966309 0.900879 -22 23 23 0.845215 0.950195 0.952148 -22 23 24 0.802246 0.923828 0.986816 -22 23 25 0.750488 0.891113 1 -22 23 26 0.693359 0.855469 1 -22 23 27 0.630859 0.818359 1 -22 23 28 0.5625 0.780273 1 -22 23 29 0.486328 0.742188 1 -22 23 30 0.397461 0.705078 1 -22 23 31 0.277588 0.668945 1 -22 24 0 0.955078 1 0.287354 -22 24 1 0.955078 1 0.287354 -22 24 2 0.955078 1 0.287354 -22 24 3 0.955078 1 0.287354 -22 24 4 0.955078 1 0.287354 -22 24 5 0.955078 1 0.287354 -22 24 6 0.955078 1 0.287354 -22 24 7 0.955078 1 0.287354 -22 24 8 0.955078 1 0.287354 -22 24 9 0.955078 1 0.287354 -22 24 10 0.955078 1 0.287354 -22 24 11 0.955078 1 0.287354 -22 24 12 0.955078 1 0.287354 -22 24 13 0.955078 1 0.287354 -22 24 14 0.955078 1 0.287354 -22 24 15 0.953613 1 0.340088 -22 24 16 0.950195 1 0.428955 -22 24 17 0.943359 1 0.51709 -22 24 18 0.932617 1 0.603027 -22 24 19 0.916504 1 0.683594 -22 24 20 0.894043 1 0.756836 -22 24 21 0.866699 1 0.822754 -22 24 22 0.836426 1 0.883301 -22 24 23 0.805176 0.994141 0.936035 -22 24 24 0.77002 0.976074 0.97998 -22 24 25 0.724609 0.949219 1 -22 24 26 0.668457 0.913086 1 -22 24 27 0.60498 0.873535 1 -22 24 28 0.534668 0.83252 1 -22 24 29 0.454346 0.791504 1 -22 24 30 0.356689 0.750977 1 -22 24 31 0.203369 0.711914 1 -22 25 0 0.891113 1 0.276123 -22 25 1 0.891113 1 0.276123 -22 25 2 0.891113 1 0.276123 -22 25 3 0.891113 1 0.276123 -22 25 4 0.891113 1 0.276123 -22 25 5 0.891113 1 0.276123 -22 25 6 0.891113 1 0.276123 -22 25 7 0.891113 1 0.276123 -22 25 8 0.891113 1 0.276123 -22 25 9 0.891113 1 0.276123 -22 25 10 0.891113 1 0.276123 -22 25 11 0.891113 1 0.276123 -22 25 12 0.891113 1 0.276123 -22 25 13 0.891113 1 0.276123 -22 25 14 0.891113 1 0.276123 -22 25 15 0.890137 1 0.311768 -22 25 16 0.886719 1 0.402832 -22 25 17 0.880371 1 0.490967 -22 25 18 0.870605 1 0.576172 -22 25 19 0.855957 1 0.657227 -22 25 20 0.836914 1 0.730957 -22 25 21 0.812988 1 0.799316 -22 25 22 0.786133 1 0.861816 -22 25 23 0.756348 1 0.916016 -22 25 24 0.723145 1 0.961914 -22 25 25 0.682617 0.999023 1 -22 25 26 0.631836 0.969238 1 -22 25 27 0.569336 0.931152 1 -22 25 28 0.496582 0.888672 1 -22 25 29 0.409668 0.845215 1 -22 25 30 0.294189 0.80127 1 -22 25 31 0 0.758789 1 -22 26 0 0.819336 1 0.26416 -22 26 1 0.819336 1 0.26416 -22 26 2 0.819336 1 0.26416 -22 26 3 0.819336 1 0.26416 -22 26 4 0.819336 1 0.26416 -22 26 5 0.819336 1 0.26416 -22 26 6 0.819336 1 0.26416 -22 26 7 0.819336 1 0.26416 -22 26 8 0.819336 1 0.26416 -22 26 9 0.819336 1 0.26416 -22 26 10 0.819336 1 0.26416 -22 26 11 0.819336 1 0.26416 -22 26 12 0.819336 1 0.26416 -22 26 13 0.819336 1 0.26416 -22 26 14 0.819336 1 0.26416 -22 26 15 0.818848 1 0.278809 -22 26 16 0.81543 1 0.373535 -22 26 17 0.80957 1 0.462402 -22 26 18 0.800781 1 0.547852 -22 26 19 0.788086 1 0.628418 -22 26 20 0.770996 1 0.703125 -22 26 21 0.75 1 0.772461 -22 26 22 0.725098 1 0.836426 -22 26 23 0.696777 1 0.891602 -22 26 24 0.664551 1 0.939453 -22 26 25 0.625 1 0.983887 -22 26 26 0.57666 1 1 -22 26 27 0.515625 0.985352 1 -22 26 28 0.439453 0.945312 1 -22 26 29 0.339111 0.900879 1 -22 26 30 0.156738 0.855469 1 -22 26 31 0 0.80957 1 -22 27 0 0.73877 1 0.251465 -22 27 1 0.73877 1 0.251465 -22 27 2 0.73877 1 0.251465 -22 27 3 0.73877 1 0.251465 -22 27 4 0.73877 1 0.251465 -22 27 5 0.73877 1 0.251465 -22 27 6 0.73877 1 0.251465 -22 27 7 0.73877 1 0.251465 -22 27 8 0.73877 1 0.251465 -22 27 9 0.73877 1 0.251465 -22 27 10 0.73877 1 0.251465 -22 27 11 0.73877 1 0.251465 -22 27 12 0.73877 1 0.251465 -22 27 13 0.73877 1 0.251465 -22 27 14 0.739258 1 0.251465 -22 27 15 0.739258 1 0.251465 -22 27 16 0.73584 1 0.341553 -22 27 17 0.730469 1 0.431885 -22 27 18 0.722168 1 0.51709 -22 27 19 0.709961 1 0.597656 -22 27 20 0.694336 1 0.672363 -22 27 21 0.674316 1 0.742188 -22 27 22 0.650391 1 0.806641 -22 27 23 0.622559 1 0.863281 -22 27 24 0.590332 1 0.912109 -22 27 25 0.550293 1 0.958496 -22 27 26 0.5 1 1 -22 27 27 0.435059 1 1 -22 27 28 0.346191 0.99707 1 -22 27 29 0.190186 0.955078 1 -22 27 30 0 0.909668 1 -22 27 31 0 0.862305 1 -22 28 0 0.647949 1 0.238159 -22 28 1 0.647949 1 0.238159 -22 28 2 0.647949 1 0.238159 -22 28 3 0.647949 1 0.238159 -22 28 4 0.647949 1 0.238159 -22 28 5 0.647949 1 0.238159 -22 28 6 0.647949 1 0.238159 -22 28 7 0.647949 1 0.238159 -22 28 8 0.647949 1 0.238159 -22 28 9 0.647949 1 0.238159 -22 28 10 0.647949 1 0.238159 -22 28 11 0.647949 1 0.238281 -22 28 12 0.647949 1 0.238281 -22 28 13 0.647949 1 0.238281 -22 28 14 0.647949 1 0.238281 -22 28 15 0.648438 1 0.238281 -22 28 16 0.645996 1 0.306152 -22 28 17 0.640137 1 0.398926 -22 28 18 0.631348 1 0.484375 -22 28 19 0.619141 1 0.564453 -22 28 20 0.603027 1 0.638672 -22 28 21 0.58252 1 0.708496 -22 28 22 0.557617 1 0.772949 -22 28 23 0.527832 1 0.830078 -22 28 24 0.493408 1 0.880371 -22 28 25 0.448975 1 0.928711 -22 28 26 0.38916 1 0.974121 -22 28 27 0.301758 1 1 -22 28 28 0.0841675 1 1 -22 28 29 0 1 1 -22 28 30 0 0.960938 1 -22 28 31 0 0.914062 1 -22 29 0 0.539062 1 0.224487 -22 29 1 0.539062 1 0.224487 -22 29 2 0.539062 1 0.224487 -22 29 3 0.539062 1 0.224487 -22 29 4 0.539062 1 0.224487 -22 29 5 0.539062 1 0.224487 -22 29 6 0.539062 1 0.224487 -22 29 7 0.539062 1 0.224487 -22 29 8 0.539062 1 0.224487 -22 29 9 0.539062 1 0.224487 -22 29 10 0.539062 1 0.224487 -22 29 11 0.539551 1 0.224487 -22 29 12 0.539551 1 0.224609 -22 29 13 0.539551 1 0.224609 -22 29 14 0.539551 1 0.224609 -22 29 15 0.540039 1 0.224609 -22 29 16 0.538574 1 0.265869 -22 29 17 0.53125 1 0.363281 -22 29 18 0.520508 1 0.449219 -22 29 19 0.506348 1 0.528809 -22 29 20 0.487549 1 0.602051 -22 29 21 0.463379 1 0.671387 -22 29 22 0.432617 1 0.735352 -22 29 23 0.39502 1 0.79248 -22 29 24 0.348145 1 0.84375 -22 29 25 0.27832 1 0.893555 -22 29 26 0.123718 1 0.940918 -22 29 27 0 1 0.984863 -22 29 28 0 1 1 -22 29 29 0 1 1 -22 29 30 0 1 1 -22 29 31 0 0.964844 1 -22 30 0 0.395264 1 0.210449 -22 30 1 0.395264 1 0.210449 -22 30 2 0.395264 1 0.210449 -22 30 3 0.395264 1 0.210449 -22 30 4 0.395264 1 0.210449 -22 30 5 0.395264 1 0.210449 -22 30 6 0.395264 1 0.210449 -22 30 7 0.395264 1 0.210449 -22 30 8 0.395264 1 0.210449 -22 30 9 0.395264 1 0.210449 -22 30 10 0.395264 1 0.210449 -22 30 11 0.395508 1 0.210449 -22 30 12 0.395508 1 0.210449 -22 30 13 0.395752 1 0.210449 -22 30 14 0.39624 1 0.210571 -22 30 15 0.396973 1 0.210571 -22 30 16 0.397217 1 0.217773 -22 30 17 0.385742 1 0.324707 -22 30 18 0.369141 1 0.411865 -22 30 19 0.345947 1 0.490479 -22 30 20 0.314209 1 0.562988 -22 30 21 0.268066 1 0.630859 -22 30 22 0.192505 1 0.694336 -22 30 23 0 1 0.750977 -22 30 24 0 1 0.802246 -22 30 25 0 1 0.853027 -22 30 26 0 1 0.902344 -22 30 27 0 1 0.949219 -22 30 28 0 1 0.992676 -22 30 29 0 1 1 -22 30 30 0 1 1 -22 30 31 0 1 1 -22 31 0 0 1 0.196167 -22 31 1 0 1 0.196167 -22 31 2 0 1 0.196167 -22 31 3 0 1 0.196167 -22 31 4 0 1 0.196167 -22 31 5 0 1 0.196167 -22 31 6 0 1 0.196167 -22 31 7 0 1 0.196167 -22 31 8 0 1 0.196167 -22 31 9 0 1 0.196167 -22 31 10 0 1 0.196167 -22 31 11 0 1 0.196289 -22 31 12 0 1 0.196289 -22 31 13 0 1 0.196289 -22 31 14 0 1 0.196289 -22 31 15 0 1 0.196411 -22 31 16 0 1 0.196533 -22 31 17 0 1 0.281982 -22 31 18 0 1 0.372314 -22 31 19 0 1 0.450684 -22 31 20 0 1 0.521484 -22 31 21 0 1 0.588379 -22 31 22 0 1 0.650391 -22 31 23 0 1 0.706543 -22 31 24 0 1 0.757324 -22 31 25 0 1 0.808594 -22 31 26 0 1 0.859375 -22 31 27 0 1 0.908691 -22 31 28 0 1 0.955566 -22 31 29 0 1 0.998047 -22 31 30 0 1 1 -22 31 31 0 1 1 -23 0 0 1 0 0.0647583 -23 0 1 1 0 0.0647583 -23 0 2 1 0 0.0646973 -23 0 3 1 0 0.0646973 -23 0 4 1 0 0.0646973 -23 0 5 1 0 0.0646973 -23 0 6 1 0 0.0646973 -23 0 7 1 0 0.0646362 -23 0 8 1 0 0.0645142 -23 0 9 1 0 0.0643311 -23 0 10 1 0 0.0640259 -23 0 11 1 0 0.0634155 -23 0 12 1 0 0.0623779 -23 0 13 1 0 0.0606079 -23 0 14 1 0 0.0593872 -23 0 15 1 0 0.237549 -23 0 16 1 0 0.375244 -23 0 17 1 0 0.489746 -23 0 18 1 0 0.600098 -23 0 19 1 0.180908 0.708496 -23 0 20 1 0.293701 0.804199 -23 0 21 1 0.349121 0.881348 -23 0 22 1 0.36499 0.939941 -23 0 23 1 0.366211 0.984863 -23 0 24 1 0.365479 1 -23 0 25 0.990723 0.362549 1 -23 0 26 0.928711 0.357178 1 -23 0 27 0.86084 0.350098 1 -23 0 28 0.789062 0.342529 1 -23 0 29 0.715332 0.334717 1 -23 0 30 0.640137 0.327393 1 -23 0 31 0.562988 0.320801 1 -23 1 0 1 0 0.0646973 -23 1 1 1 0 0.0646973 -23 1 2 1 0 0.0646973 -23 1 3 1 0 0.0646973 -23 1 4 1 0 0.0646973 -23 1 5 1 0 0.0646973 -23 1 6 1 0 0.0646362 -23 1 7 1 0 0.0646362 -23 1 8 1 0 0.0645142 -23 1 9 1 0 0.0643311 -23 1 10 1 0 0.0640259 -23 1 11 1 0 0.0634155 -23 1 12 1 0 0.0623779 -23 1 13 1 0 0.0606079 -23 1 14 1 0 0.0593872 -23 1 15 1 0 0.237549 -23 1 16 1 0 0.375244 -23 1 17 1 0 0.489746 -23 1 18 1 0 0.600098 -23 1 19 1 0.180908 0.708496 -23 1 20 1 0.293701 0.804199 -23 1 21 1 0.349121 0.881348 -23 1 22 1 0.36499 0.939941 -23 1 23 1 0.366211 0.984863 -23 1 24 1 0.365479 1 -23 1 25 0.990723 0.362549 1 -23 1 26 0.928711 0.357178 1 -23 1 27 0.86084 0.350098 1 -23 1 28 0.789062 0.342529 1 -23 1 29 0.715332 0.334717 1 -23 1 30 0.640137 0.327393 1 -23 1 31 0.562988 0.320801 1 -23 2 0 1 0 0.0646973 -23 2 1 1 0 0.0646973 -23 2 2 1 0 0.0646973 -23 2 3 1 0 0.0646973 -23 2 4 1 0 0.0646973 -23 2 5 1 0 0.0646362 -23 2 6 1 0 0.0646362 -23 2 7 1 0 0.0645752 -23 2 8 1 0 0.0645142 -23 2 9 1 0 0.0643311 -23 2 10 1 0 0.0639648 -23 2 11 1 0 0.0633545 -23 2 12 1 0 0.0623474 -23 2 13 1 0 0.0605774 -23 2 14 1 0 0.0593567 -23 2 15 1 0 0.237549 -23 2 16 1 0 0.375244 -23 2 17 1 0 0.489746 -23 2 18 1 0 0.600098 -23 2 19 1 0.18103 0.708496 -23 2 20 1 0.293701 0.804199 -23 2 21 1 0.349121 0.881348 -23 2 22 1 0.36499 0.939941 -23 2 23 1 0.366211 0.984863 -23 2 24 1 0.365479 1 -23 2 25 0.990723 0.362549 1 -23 2 26 0.928711 0.357178 1 -23 2 27 0.86084 0.350098 1 -23 2 28 0.789062 0.342529 1 -23 2 29 0.715332 0.334717 1 -23 2 30 0.640137 0.327393 1 -23 2 31 0.562988 0.320801 1 -23 3 0 1 0 0.0646362 -23 3 1 1 0 0.0646362 -23 3 2 1 0 0.0646362 -23 3 3 1 0 0.0646362 -23 3 4 1 0 0.0646362 -23 3 5 1 0 0.0646362 -23 3 6 1 0 0.0645752 -23 3 7 1 0 0.0645752 -23 3 8 1 0 0.0644531 -23 3 9 1 0 0.06427 -23 3 10 1 0 0.0639038 -23 3 11 1 0 0.0633545 -23 3 12 1 0 0.0622864 -23 3 13 1 0 0.0605164 -23 3 14 1 0 0.0592957 -23 3 15 1 0 0.237549 -23 3 16 1 0 0.375244 -23 3 17 1 0 0.489746 -23 3 18 1 0 0.600098 -23 3 19 1 0.181152 0.708496 -23 3 20 1 0.293701 0.804199 -23 3 21 1 0.349121 0.881348 -23 3 22 1 0.365234 0.939941 -23 3 23 1 0.366455 0.984863 -23 3 24 1 0.365723 1 -23 3 25 0.990723 0.362549 1 -23 3 26 0.928711 0.357178 1 -23 3 27 0.86084 0.350342 1 -23 3 28 0.789062 0.342529 1 -23 3 29 0.715332 0.334717 1 -23 3 30 0.640137 0.327393 1 -23 3 31 0.562988 0.320801 1 -23 4 0 1 0 0.0645752 -23 4 1 1 0 0.0645752 -23 4 2 1 0 0.0645752 -23 4 3 1 0 0.0645752 -23 4 4 1 0 0.0645752 -23 4 5 1 0 0.0645142 -23 4 6 1 0 0.0645142 -23 4 7 1 0 0.0644531 -23 4 8 1 0 0.0643921 -23 4 9 1 0 0.064209 -23 4 10 1 0 0.0638428 -23 4 11 1 0 0.0632324 -23 4 12 1 0 0.0621948 -23 4 13 1 0 0.0604248 -23 4 14 1 0 0.0592041 -23 4 15 1 0 0.237549 -23 4 16 1 0 0.375244 -23 4 17 1 0 0.489746 -23 4 18 1 0 0.600098 -23 4 19 1 0.181519 0.708496 -23 4 20 1 0.293945 0.804199 -23 4 21 1 0.349365 0.881348 -23 4 22 1 0.365234 0.939941 -23 4 23 1 0.366455 0.984863 -23 4 24 1 0.365723 1 -23 4 25 0.990723 0.362549 1 -23 4 26 0.928711 0.357178 1 -23 4 27 0.86084 0.350342 1 -23 4 28 0.789062 0.342529 1 -23 4 29 0.715332 0.334717 1 -23 4 30 0.640137 0.327393 1 -23 4 31 0.562988 0.321045 1 -23 5 0 1 0 0.0643921 -23 5 1 1 0 0.0643921 -23 5 2 1 0 0.0643921 -23 5 3 1 0 0.0643921 -23 5 4 1 0 0.0643921 -23 5 5 1 0 0.0643921 -23 5 6 1 0 0.0643311 -23 5 7 1 0 0.0643311 -23 5 8 1 0 0.064209 -23 5 9 1 0 0.0640259 -23 5 10 1 0 0.0636597 -23 5 11 1 0 0.0631104 -23 5 12 1 0 0.0620422 -23 5 13 1 0 0.0602417 -23 5 14 1 0 0.059021 -23 5 15 1 0 0.237549 -23 5 16 1 0 0.375244 -23 5 17 1 0 0.489746 -23 5 18 1 0 0.600098 -23 5 19 1 0.182129 0.708496 -23 5 20 1 0.294189 0.804199 -23 5 21 1 0.349365 0.881348 -23 5 22 1 0.365479 0.939941 -23 5 23 1 0.366699 0.984863 -23 5 24 1 0.365967 1 -23 5 25 0.990723 0.362793 1 -23 5 26 0.928711 0.357422 1 -23 5 27 0.86084 0.350342 1 -23 5 28 0.789062 0.342773 1 -23 5 29 0.715332 0.334961 1 -23 5 30 0.640137 0.327637 1 -23 5 31 0.562988 0.321045 1 -23 6 0 1 0 0.0640869 -23 6 1 1 0 0.0640869 -23 6 2 1 0 0.0640869 -23 6 3 1 0 0.0640869 -23 6 4 1 0 0.0640869 -23 6 5 1 0 0.0640869 -23 6 6 1 0 0.0640259 -23 6 7 1 0 0.0639648 -23 6 8 1 0 0.0639038 -23 6 9 1 0 0.0637207 -23 6 10 1 0 0.0633545 -23 6 11 1 0 0.0627441 -23 6 12 1 0 0.0617065 -23 6 13 1 0 0.059906 -23 6 14 1 0 0.0586853 -23 6 15 1 0 0.237549 -23 6 16 1 0 0.375244 -23 6 17 1 0 0.489746 -23 6 18 1 0 0.600098 -23 6 19 1 0.183228 0.708496 -23 6 20 1 0.294678 0.804199 -23 6 21 1 0.349854 0.881348 -23 6 22 1 0.365723 0.939941 -23 6 23 1 0.366943 0.984863 -23 6 24 1 0.366211 1 -23 6 25 0.990723 0.363037 1 -23 6 26 0.928711 0.357666 1 -23 6 27 0.86084 0.350586 1 -23 6 28 0.789062 0.343018 1 -23 6 29 0.715332 0.335205 1 -23 6 30 0.640137 0.327637 1 -23 6 31 0.562988 0.321045 1 -23 7 0 1 0 0.0634766 -23 7 1 1 0 0.0634766 -23 7 2 1 0 0.0634766 -23 7 3 1 0 0.0634766 -23 7 4 1 0 0.0634766 -23 7 5 1 0 0.0634766 -23 7 6 1 0 0.0634155 -23 7 7 1 0 0.0633545 -23 7 8 1 0 0.0632935 -23 7 9 1 0 0.0631104 -23 7 10 1 0 0.0627441 -23 7 11 1 0 0.0621338 -23 7 12 1 0 0.0610352 -23 7 13 1 0 0.0592041 -23 7 14 1 0 0.0579834 -23 7 15 1 0 0.237549 -23 7 16 1 0 0.375244 -23 7 17 1 0 0.489746 -23 7 18 1 0 0.599609 -23 7 19 1 0.185303 0.708496 -23 7 20 1 0.295654 0.804199 -23 7 21 1 0.350586 0.881348 -23 7 22 1 0.366455 0.939941 -23 7 23 1 0.367676 0.984863 -23 7 24 1 0.366699 1 -23 7 25 0.990723 0.363525 1 -23 7 26 0.928711 0.358154 1 -23 7 27 0.86084 0.351074 1 -23 7 28 0.789062 0.343262 1 -23 7 29 0.715332 0.335449 1 -23 7 30 0.640137 0.328125 1 -23 7 31 0.562988 0.321533 1 -23 8 0 1 0 0.0622559 -23 8 1 1 0 0.0622559 -23 8 2 1 0 0.0622559 -23 8 3 1 0 0.0622559 -23 8 4 1 0 0.0622253 -23 8 5 1 0 0.0622253 -23 8 6 1 0 0.0621948 -23 8 7 1 0 0.0621338 -23 8 8 1 0 0.0620422 -23 8 9 1 0 0.0618591 -23 8 10 1 0 0.0614929 -23 8 11 1 0 0.0608521 -23 8 12 1 0 0.0597534 -23 8 13 1 0 0.0578308 -23 8 14 1 0 0.0565491 -23 8 15 1 0 0.237549 -23 8 16 1 0 0.375 -23 8 17 1 0 0.489746 -23 8 18 1 0 0.599609 -23 8 19 1 0.189331 0.708008 -23 8 20 1 0.297607 0.804199 -23 8 21 1 0.352051 0.881348 -23 8 22 1 0.36792 0.939941 -23 8 23 1 0.368896 0.984863 -23 8 24 1 0.36792 1 -23 8 25 0.990723 0.364746 1 -23 8 26 0.928711 0.359131 1 -23 8 27 0.860352 0.352051 1 -23 8 28 0.789062 0.344238 1 -23 8 29 0.714844 0.336182 1 -23 8 30 0.640137 0.328613 1 -23 8 31 0.562988 0.322021 1 -23 9 0 1 0 0.0597839 -23 9 1 1 0 0.0597839 -23 9 2 1 0 0.0597839 -23 9 3 1 0 0.0597839 -23 9 4 1 0 0.0597534 -23 9 5 1 0 0.0597534 -23 9 6 1 0 0.0597229 -23 9 7 1 0 0.0596619 -23 9 8 1 0 0.0595703 -23 9 9 1 0 0.0593567 -23 9 10 1 0 0.05896 -23 9 11 1 0 0.0582886 -23 9 12 1 0 0.0570984 -23 9 13 1 0 0.0550232 -23 9 14 1 0 0.0536804 -23 9 15 1 0 0.237549 -23 9 16 1 0 0.375 -23 9 17 1 0 0.489746 -23 9 18 1 0 0.599609 -23 9 19 1 0.196777 0.708008 -23 9 20 1 0.30127 0.804199 -23 9 21 1 0.35498 0.881348 -23 9 22 1 0.370361 0.939941 -23 9 23 1 0.371338 0.984863 -23 9 24 1 0.370361 1 -23 9 25 0.990234 0.366943 1 -23 9 26 0.928711 0.361084 1 -23 9 27 0.860352 0.35376 1 -23 9 28 0.788574 0.345703 1 -23 9 29 0.714844 0.337402 1 -23 9 30 0.639648 0.329834 1 -23 9 31 0.5625 0.322998 1 -23 10 0 1 0 0.0548096 -23 10 1 1 0 0.0548096 -23 10 2 1 0 0.0548096 -23 10 3 1 0 0.0548096 -23 10 4 1 0 0.0548096 -23 10 5 1 0 0.0547791 -23 10 6 1 0 0.0547485 -23 10 7 1 0 0.0546875 -23 10 8 1 0 0.0545654 -23 10 9 1 0 0.0543213 -23 10 10 1 0 0.0538635 -23 10 11 1 0 0.0530701 -23 10 12 1 0 0.0516663 -23 10 13 1 0 0.0492249 -23 10 14 1 0 0.047699 -23 10 15 1 0 0.237427 -23 10 16 1 0 0.374756 -23 10 17 1 0 0.489746 -23 10 18 1 0 0.599609 -23 10 19 1 0.209106 0.708008 -23 10 20 1 0.307861 0.803711 -23 10 21 1 0.360107 0.881348 -23 10 22 1 0.375244 0.939941 -23 10 23 1 0.375732 0.984863 -23 10 24 1 0.374268 1 -23 10 25 0.990234 0.370605 1 -23 10 26 0.928223 0.364502 1 -23 10 27 0.860352 0.356689 1 -23 10 28 0.788574 0.348389 1 -23 10 29 0.714844 0.339844 1 -23 10 30 0.639648 0.332031 1 -23 10 31 0.5625 0.324951 1 -23 11 0 1 0 0.0436707 -23 11 1 1 0 0.0436707 -23 11 2 1 0 0.0436707 -23 11 3 1 0 0.0436707 -23 11 4 1 0 0.0436401 -23 11 5 1 0 0.0436401 -23 11 6 1 0 0.0435791 -23 11 7 1 0 0.0434875 -23 11 8 1 0 0.0433044 -23 11 9 1 0 0.0429688 -23 11 10 1 0 0.0422974 -23 11 11 1 0 0.0411072 -23 11 12 1 0 0.0389709 -23 11 13 1 0 0.0349121 -23 11 14 1 0 0.0323486 -23 11 15 1 0 0.237549 -23 11 16 1 0 0.374512 -23 11 17 1 0 0.489746 -23 11 18 1 0.072998 0.599121 -23 11 19 1 0.228394 0.70752 -23 11 20 1 0.318848 0.803711 -23 11 21 1 0.368896 0.881348 -23 11 22 1 0.383057 0.939941 -23 11 23 1 0.383301 0.984863 -23 11 24 1 0.381348 1 -23 11 25 0.989746 0.376953 1 -23 11 26 0.927734 0.370361 1 -23 11 27 0.859863 0.362061 1 -23 11 28 0.788086 0.353027 1 -23 11 29 0.714355 0.343994 1 -23 11 30 0.63916 0.335693 1 -23 11 31 0.562012 0.328125 1 -23 12 0 1 0.0981445 0 -23 12 1 1 0.0982056 0 -23 12 2 1 0.0982056 0 -23 12 3 1 0.0982666 0 -23 12 4 1 0.0983276 0 -23 12 5 1 0.0984497 0 -23 12 6 1 0.0987549 0 -23 12 7 1 0.0993042 0 -23 12 8 1 0.100342 0 -23 12 9 1 0.102234 0 -23 12 10 1 0.105652 0 -23 12 11 1 0.111206 0 -23 12 12 1 0.119751 0 -23 12 13 1 0.131958 0 -23 12 14 1 0.137207 0 -23 12 15 1 0.127563 0.237793 -23 12 16 1 0.113342 0.373779 -23 12 17 1 0.122864 0.489746 -23 12 18 1 0.163818 0.598145 -23 12 19 1 0.256348 0.706543 -23 12 20 1 0.336182 0.803223 -23 12 21 1 0.383057 0.880859 -23 12 22 1 0.39624 0.939941 -23 12 23 1 0.395508 0.984863 -23 12 24 1 0.392822 1 -23 12 25 0.989258 0.387695 1 -23 12 26 0.927246 0.380127 1 -23 12 27 0.858887 0.37085 1 -23 12 28 0.787109 0.36084 1 -23 12 29 0.713379 0.351074 1 -23 12 30 0.638184 0.341797 1 -23 12 31 0.561035 0.333496 1 -23 13 0 1 0.207275 0 -23 13 1 1 0.207275 0 -23 13 2 1 0.207275 0 -23 13 3 1 0.207275 0 -23 13 4 1 0.207397 0 -23 13 5 1 0.207397 0 -23 13 6 1 0.20752 0 -23 13 7 1 0.207642 0 -23 13 8 1 0.208008 0 -23 13 9 1 0.208618 0 -23 13 10 1 0.209717 0 -23 13 11 1 0.21167 0 -23 13 12 1 0.214844 0 -23 13 13 1 0.219971 0 -23 13 14 1 0.221802 0 -23 13 15 1 0.216675 0.23877 -23 13 16 1 0.209717 0.373291 -23 13 17 1 0.21582 0.489746 -23 13 18 1 0.231323 0.597168 -23 13 19 1 0.293945 0.705078 -23 13 20 1 0.361816 0.802246 -23 13 21 1 0.404785 0.880859 -23 13 22 1 0.41626 0.939941 -23 13 23 1 0.414551 0.984863 -23 13 24 1 0.410645 1 -23 13 25 0.987793 0.404297 1 -23 13 26 0.925781 0.395264 1 -23 13 27 0.857422 0.384521 1 -23 13 28 0.786133 0.373047 1 -23 13 29 0.711914 0.361816 1 -23 13 30 0.637207 0.351562 1 -23 13 31 0.560059 0.342041 1 -23 14 0 1 0.289551 0 -23 14 1 1 0.289551 0 -23 14 2 1 0.289551 0 -23 14 3 1 0.289551 0 -23 14 4 1 0.289551 0 -23 14 5 1 0.289551 0 -23 14 6 1 0.289551 0 -23 14 7 1 0.289795 0 -23 14 8 1 0.289795 0 -23 14 9 1 0.290283 0 -23 14 10 1 0.291016 0 -23 14 11 1 0.291992 0 -23 14 12 1 0.293945 0 -23 14 13 1 0.297363 0 -23 14 14 1 0.297852 0 -23 14 15 1 0.293945 0.241455 -23 14 16 1 0.288574 0.373291 -23 14 17 1 0.292236 0.489258 -23 14 18 1 0.299316 0.595703 -23 14 19 1 0.341309 0.703125 -23 14 20 1 0.397461 0.80127 -23 14 21 1 0.435547 0.880371 -23 14 22 1 0.445312 0.939941 -23 14 23 1 0.442139 0.984863 -23 14 24 1 0.436768 1 -23 14 25 0.98584 0.428467 1 -23 14 26 0.923828 0.41748 1 -23 14 27 0.855469 0.404785 1 -23 14 28 0.783691 0.391357 1 -23 14 29 0.709961 0.378174 1 -23 14 30 0.635254 0.365967 1 -23 14 31 0.557617 0.35498 1 -23 15 0 1 0.37085 0 -23 15 1 1 0.37085 0 -23 15 2 1 0.37085 0 -23 15 3 1 0.37085 0 -23 15 4 1 0.37085 0 -23 15 5 1 0.37085 0 -23 15 6 1 0.37085 0 -23 15 7 1 0.37085 0 -23 15 8 1 0.371094 0 -23 15 9 1 0.371338 0 -23 15 10 1 0.371826 0 -23 15 11 1 0.372559 0 -23 15 12 1 0.374023 0 -23 15 13 1 0.376221 0 -23 15 14 1 0.376465 0 -23 15 15 1 0.372803 0.248413 -23 15 16 1 0.368164 0.374512 -23 15 17 1 0.367432 0.487061 -23 15 18 1 0.372314 0.59375 -23 15 19 1 0.398438 0.699707 -23 15 20 1 0.443359 0.798828 -23 15 21 1 0.476807 0.879395 -23 15 22 1 0.484375 0.939453 -23 15 23 1 0.479492 0.984863 -23 15 24 1 0.472412 1 -23 15 25 0.98291 0.46167 1 -23 15 26 0.92041 0.448242 1 -23 15 27 0.852051 0.432861 1 -23 15 28 0.780762 0.416748 1 -23 15 29 0.707031 0.401123 1 -23 15 30 0.631836 0.386719 1 -23 15 31 0.554688 0.373535 1 -23 16 0 1 0.456299 0 -23 16 1 1 0.456299 0 -23 16 2 1 0.456299 0 -23 16 3 1 0.456299 0 -23 16 4 1 0.456543 0 -23 16 5 1 0.456543 0 -23 16 6 1 0.456543 0 -23 16 7 1 0.456543 0 -23 16 8 1 0.456543 0 -23 16 9 1 0.456787 0 -23 16 10 1 0.457031 0 -23 16 11 1 0.457764 0 -23 16 12 1 0.45874 0 -23 16 13 1 0.460205 0 -23 16 14 1 0.460205 0 -23 16 15 1 0.45752 0.263184 -23 16 16 1 0.453369 0.380127 -23 16 17 1 0.449951 0.486816 -23 16 18 1 0.453125 0.593262 -23 16 19 1 0.465332 0.695312 -23 16 20 1 0.499268 0.794922 -23 16 21 1 0.52832 0.87793 -23 16 22 1 0.53418 0.938965 -23 16 23 1 0.527344 0.984375 -23 16 24 1 0.518066 1 -23 16 25 0.978027 0.504883 1 -23 16 26 0.915527 0.488037 1 -23 16 27 0.847168 0.469482 1 -23 16 28 0.775391 0.450439 1 -23 16 29 0.702148 0.431641 1 -23 16 30 0.626953 0.414307 1 -23 16 31 0.549805 0.398438 1 -23 17 0 1 0.54541 0 -23 17 1 1 0.54541 0 -23 17 2 1 0.54541 0 -23 17 3 1 0.54541 0 -23 17 4 1 0.54541 0 -23 17 5 1 0.54541 0 -23 17 6 1 0.54541 0 -23 17 7 1 0.54541 0 -23 17 8 1 0.54541 0 -23 17 9 1 0.54541 0 -23 17 10 1 0.545898 0 -23 17 11 1 0.546387 0 -23 17 12 1 0.546875 0 -23 17 13 1 0.54834 0 -23 17 14 1 0.54834 0.146606 -23 17 15 1 0.546387 0.287842 -23 17 16 1 0.543457 0.392822 -23 17 17 1 0.538574 0.491455 -23 17 18 1 0.535645 0.59082 -23 17 19 1 0.540039 0.689941 -23 17 20 1 0.5625 0.788574 -23 17 21 1 0.587891 0.874512 -23 17 22 1 0.592773 0.937012 -23 17 23 1 0.583984 0.983398 -23 17 24 1 0.572266 1 -23 17 25 0.970703 0.556152 1 -23 17 26 0.908203 0.535645 1 -23 17 27 0.839844 0.513672 1 -23 17 28 0.768555 0.490967 1 -23 17 29 0.695312 0.468994 1 -23 17 30 0.620605 0.448242 1 -23 17 31 0.542969 0.429443 1 -23 18 0 1 0.635254 0.146362 -23 18 1 1 0.635254 0.146362 -23 18 2 1 0.635254 0.146362 -23 18 3 1 0.635254 0.146362 -23 18 4 1 0.635254 0.146362 -23 18 5 1 0.635254 0.146362 -23 18 6 1 0.635254 0.146484 -23 18 7 1 0.635254 0.146484 -23 18 8 1 0.635254 0.146606 -23 18 9 1 0.635742 0.146729 -23 18 10 1 0.635742 0.146973 -23 18 11 1 0.63623 0.147461 -23 18 12 1 0.636719 0.148315 -23 18 13 1 0.637695 0.149536 -23 18 14 1 0.638184 0.217651 -23 18 15 1 0.637207 0.320557 -23 18 16 1 0.635254 0.413574 -23 18 17 1 0.630859 0.503906 -23 18 18 1 0.624023 0.59375 -23 18 19 1 0.622559 0.687012 -23 18 20 1 0.629883 0.779297 -23 18 21 1 0.651367 0.868652 -23 18 22 1 0.65625 0.934082 -23 18 23 1 0.645996 0.981445 -23 18 24 1 0.631836 1 -23 18 25 0.959961 0.612305 1 -23 18 26 0.897949 0.588867 1 -23 18 27 0.82959 0.562988 1 -23 18 28 0.758789 0.536621 1 -23 18 29 0.686035 0.51123 1 -23 18 30 0.611328 0.487305 1 -23 18 31 0.533691 0.465332 1 -23 19 0 1 0.723145 0.237427 -23 19 1 1 0.723145 0.237427 -23 19 2 1 0.723145 0.237427 -23 19 3 1 0.723145 0.237427 -23 19 4 1 0.723145 0.237427 -23 19 5 1 0.723145 0.237427 -23 19 6 1 0.723145 0.237427 -23 19 7 1 0.723145 0.237427 -23 19 8 1 0.723145 0.237427 -23 19 9 1 0.723145 0.237549 -23 19 10 1 0.723633 0.237671 -23 19 11 1 0.723633 0.237793 -23 19 12 1 0.724121 0.238159 -23 19 13 1 0.725098 0.238647 -23 19 14 1 0.725586 0.268311 -23 19 15 1 0.726074 0.353271 -23 19 16 1 0.725098 0.437988 -23 19 17 1 0.72168 0.522461 -23 19 18 1 0.715332 0.605469 -23 19 19 1 0.706055 0.686523 -23 19 20 1 0.703125 0.770996 -23 19 21 1 0.714844 0.858887 -23 19 22 1 0.721191 0.929199 -23 19 23 1 0.709961 0.977539 -23 19 24 0.999512 0.693848 1 -23 19 25 0.945801 0.670898 1 -23 19 26 0.883789 0.644043 1 -23 19 27 0.816406 0.614746 1 -23 19 28 0.746582 0.584961 1 -23 19 29 0.674316 0.556152 1 -23 19 30 0.600586 0.529297 1 -23 19 31 0.522461 0.504395 1 -23 20 0 1 0.804688 0.286621 -23 20 1 1 0.804688 0.286621 -23 20 2 1 0.804688 0.286621 -23 20 3 1 0.804688 0.286621 -23 20 4 1 0.804688 0.286621 -23 20 5 1 0.804688 0.286621 -23 20 6 1 0.804688 0.286621 -23 20 7 1 0.804688 0.286621 -23 20 8 1 0.805176 0.286621 -23 20 9 1 0.805176 0.286621 -23 20 10 1 0.805176 0.286621 -23 20 11 1 0.805176 0.286865 -23 20 12 1 0.805664 0.286865 -23 20 13 1 0.806152 0.287109 -23 20 14 1 0.807129 0.299561 -23 20 15 1 0.807617 0.376465 -23 20 16 1 0.808105 0.45752 -23 20 17 1 0.806641 0.540039 -23 20 18 1 0.801758 0.621094 -23 20 19 1 0.791992 0.696777 -23 20 20 1 0.779297 0.767578 -23 20 21 1 0.775879 0.845703 -23 20 22 1 0.783691 0.921387 -23 20 23 1 0.772461 0.97168 -23 20 24 0.981445 0.754395 1 -23 20 25 0.927734 0.728516 1 -23 20 26 0.866211 0.697754 1 -23 20 27 0.800293 0.666016 1 -23 20 28 0.731445 0.633789 1 -23 20 29 0.660645 0.602539 1 -23 20 30 0.586914 0.573242 1 -23 20 31 0.508789 0.54541 1 -23 21 0 1 0.879883 0.311279 -23 21 1 1 0.879883 0.311279 -23 21 2 1 0.879883 0.311279 -23 21 3 1 0.879883 0.311279 -23 21 4 1 0.879883 0.311279 -23 21 5 1 0.879883 0.311279 -23 21 6 1 0.879883 0.311279 -23 21 7 1 0.879883 0.311279 -23 21 8 1 0.879883 0.311523 -23 21 9 1 0.879883 0.311523 -23 21 10 1 0.879883 0.311523 -23 21 11 1 0.879883 0.311523 -23 21 12 1 0.880371 0.311523 -23 21 13 1 0.880859 0.311523 -23 21 14 1 0.881348 0.311768 -23 21 15 1 0.882812 0.385254 -23 21 16 1 0.883789 0.465576 -23 21 17 1 0.883301 0.54834 -23 21 18 1 0.880371 0.630859 -23 21 19 1 0.873047 0.70752 -23 21 20 1 0.86084 0.775391 -23 21 21 1 0.84375 0.837402 -23 21 22 1 0.841309 0.908691 -23 21 23 0.999023 0.83252 0.963379 -23 21 24 0.958008 0.8125 0.999512 -23 21 25 0.904297 0.783203 1 -23 21 26 0.844238 0.750977 1 -23 21 27 0.780762 0.716797 1 -23 21 28 0.714355 0.683105 1 -23 21 29 0.644531 0.650391 1 -23 21 30 0.571777 0.618652 1 -23 21 31 0.492432 0.588379 1 -23 22 0 1 0.945312 0.317383 -23 22 1 1 0.945312 0.317383 -23 22 2 1 0.945312 0.317383 -23 22 3 1 0.945312 0.317383 -23 22 4 1 0.945312 0.317383 -23 22 5 1 0.945312 0.317383 -23 22 6 1 0.945312 0.317383 -23 22 7 1 0.945312 0.317383 -23 22 8 1 0.945312 0.317383 -23 22 9 1 0.945312 0.317383 -23 22 10 1 0.945312 0.317383 -23 22 11 1 0.945312 0.317383 -23 22 12 1 0.945801 0.317383 -23 22 13 1 0.945801 0.317627 -23 22 14 1 0.946289 0.317627 -23 22 15 1 0.947754 0.378418 -23 22 16 1 0.949219 0.460205 -23 22 17 1 0.950195 0.544434 -23 22 18 1 0.948242 0.628418 -23 22 19 1 0.943359 0.708008 -23 22 20 1 0.933594 0.779785 -23 22 21 1 0.917969 0.842285 -23 22 22 0.996582 0.896973 0.894531 -23 22 23 0.970703 0.88916 0.952148 -23 22 24 0.928711 0.865234 0.986816 -23 22 25 0.876465 0.834473 1 -23 22 26 0.819824 0.801758 1 -23 22 27 0.759766 0.768066 1 -23 22 28 0.695312 0.733398 1 -23 22 29 0.627441 0.699219 1 -23 22 30 0.554199 0.665527 1 -23 22 31 0.473145 0.632812 1 -23 23 0 1 0.997559 0.312988 -23 23 1 1 0.997559 0.312988 -23 23 2 1 0.997559 0.312988 -23 23 3 1 0.997559 0.312988 -23 23 4 1 0.997559 0.312988 -23 23 5 1 0.997559 0.312988 -23 23 6 1 0.997559 0.312988 -23 23 7 1 0.997559 0.312988 -23 23 8 1 0.997559 0.312988 -23 23 9 1 0.997559 0.312988 -23 23 10 1 0.997559 0.312988 -23 23 11 1 0.997559 0.312988 -23 23 12 1 0.997559 0.312988 -23 23 13 1 0.998047 0.312988 -23 23 14 1 0.998047 0.312988 -23 23 15 1 0.999512 0.361572 -23 23 16 1 1 0.445557 -23 23 17 1 1 0.530762 -23 23 18 1 1 0.615723 -23 23 19 1 0.998047 0.696777 -23 23 20 1 0.990234 0.770508 -23 23 21 1 0.977539 0.836914 -23 23 22 0.976562 0.960449 0.893555 -23 23 23 0.938965 0.938965 0.938965 -23 23 24 0.896973 0.913574 0.973145 -23 23 25 0.849609 0.884766 1 -23 23 26 0.796875 0.853027 1 -23 23 27 0.73877 0.818848 1 -23 23 28 0.675781 0.782715 1 -23 23 29 0.607422 0.746094 1 -23 23 30 0.533203 0.709961 1 -23 23 31 0.449219 0.674316 1 -23 24 0 1 1 0.305176 -23 24 1 1 1 0.305176 -23 24 2 1 1 0.305176 -23 24 3 1 1 0.305176 -23 24 4 1 1 0.305176 -23 24 5 1 1 0.305176 -23 24 6 1 1 0.305176 -23 24 7 1 1 0.305176 -23 24 8 1 1 0.305176 -23 24 9 1 1 0.305176 -23 24 10 1 1 0.305176 -23 24 11 1 1 0.305176 -23 24 12 1 1 0.305176 -23 24 13 1 1 0.304932 -23 24 14 1 1 0.304932 -23 24 15 1 1 0.340332 -23 24 16 1 1 0.426025 -23 24 17 1 1 0.512207 -23 24 18 1 1 0.59668 -23 24 19 1 1 0.677734 -23 24 20 0.993164 1 0.751465 -23 24 21 0.968262 1 0.817871 -23 24 22 0.936523 1 0.875 -23 24 23 0.903809 0.983398 0.924316 -23 24 24 0.872559 0.967285 0.969238 -23 24 25 0.828613 0.939941 1 -23 24 26 0.775391 0.905762 1 -23 24 27 0.717285 0.869141 1 -23 24 28 0.653809 0.831055 1 -23 24 29 0.584961 0.791992 1 -23 24 30 0.508789 0.753418 1 -23 24 31 0.421143 0.715332 1 -23 25 0 0.983398 1 0.294922 -23 25 1 0.983398 1 0.294922 -23 25 2 0.983398 1 0.294922 -23 25 3 0.983398 1 0.294922 -23 25 4 0.983398 1 0.294922 -23 25 5 0.983398 1 0.294922 -23 25 6 0.983398 1 0.294922 -23 25 7 0.983398 1 0.294922 -23 25 8 0.983398 1 0.294922 -23 25 9 0.983398 1 0.294922 -23 25 10 0.983398 1 0.294922 -23 25 11 0.983398 1 0.294922 -23 25 12 0.983398 1 0.294922 -23 25 13 0.983398 1 0.294922 -23 25 14 0.98291 1 0.294678 -23 25 15 0.982422 1 0.313965 -23 25 16 0.980469 1 0.4021 -23 25 17 0.976074 1 0.488525 -23 25 18 0.968262 1 0.572754 -23 25 19 0.956543 1 0.652832 -23 25 20 0.939453 1 0.726562 -23 25 21 0.916504 1 0.793457 -23 25 22 0.889648 1 0.852539 -23 25 23 0.861328 1 0.905762 -23 25 24 0.832031 1 0.952148 -23 25 25 0.796387 0.992188 0.995605 -23 25 26 0.749512 0.963379 1 -23 25 27 0.692383 0.92627 1 -23 25 28 0.628418 0.885742 1 -23 25 29 0.557617 0.84375 1 -23 25 30 0.478271 0.801758 1 -23 25 31 0.383301 0.760254 1 -23 26 0 0.91748 1 0.282959 -23 26 1 0.91748 1 0.282959 -23 26 2 0.91748 1 0.282959 -23 26 3 0.91748 1 0.282959 -23 26 4 0.91748 1 0.282959 -23 26 5 0.91748 1 0.282959 -23 26 6 0.91748 1 0.282959 -23 26 7 0.91748 1 0.282959 -23 26 8 0.91748 1 0.282959 -23 26 9 0.91748 1 0.282959 -23 26 10 0.91748 1 0.282959 -23 26 11 0.91748 1 0.282959 -23 26 12 0.91748 1 0.282959 -23 26 13 0.916992 1 0.282959 -23 26 14 0.916992 1 0.282959 -23 26 15 0.916992 1 0.282959 -23 26 16 0.915039 1 0.374512 -23 26 17 0.910645 1 0.461426 -23 26 18 0.903809 1 0.54541 -23 26 19 0.893066 1 0.625 -23 26 20 0.87793 1 0.698242 -23 26 21 0.858398 1 0.766113 -23 26 22 0.834961 1 0.828125 -23 26 23 0.810059 1 0.882812 -23 26 24 0.782715 1 0.931152 -23 26 25 0.748535 1 0.976074 -23 26 26 0.707031 1 1 -23 26 27 0.655273 0.981445 1 -23 26 28 0.592773 0.942383 1 -23 26 29 0.520508 0.899414 1 -23 26 30 0.435791 0.85498 1 -23 26 31 0.327148 0.810547 1 -23 27 0 0.843262 1 0.270264 -23 27 1 0.843262 1 0.270264 -23 27 2 0.843262 1 0.270264 -23 27 3 0.843262 1 0.270264 -23 27 4 0.843262 1 0.270264 -23 27 5 0.843262 1 0.270264 -23 27 6 0.843262 1 0.270264 -23 27 7 0.843262 1 0.270264 -23 27 8 0.843262 1 0.270264 -23 27 9 0.843262 1 0.270264 -23 27 10 0.843262 1 0.270264 -23 27 11 0.843262 1 0.270264 -23 27 12 0.843262 1 0.270264 -23 27 13 0.843262 1 0.270264 -23 27 14 0.843262 1 0.270264 -23 27 15 0.843262 1 0.270264 -23 27 16 0.841309 1 0.343506 -23 27 17 0.837402 1 0.431641 -23 27 18 0.831055 1 0.515625 -23 27 19 0.821777 1 0.594727 -23 27 20 0.808594 1 0.667969 -23 27 21 0.791504 1 0.736816 -23 27 22 0.770996 1 0.799805 -23 27 23 0.747559 1 0.855957 -23 27 24 0.72168 1 0.905273 -23 27 25 0.689453 1 0.952148 -23 27 26 0.649414 1 0.995605 -23 27 27 0.600586 1 1 -23 27 28 0.540039 0.994629 1 -23 27 29 0.465088 0.953613 1 -23 27 30 0.370605 0.90918 1 -23 27 31 0.223877 0.862793 1 -23 28 0 0.76123 1 0.256836 -23 28 1 0.76123 1 0.256836 -23 28 2 0.76123 1 0.256836 -23 28 3 0.76123 1 0.256836 -23 28 4 0.76123 1 0.256836 -23 28 5 0.76123 1 0.256836 -23 28 6 0.76123 1 0.256836 -23 28 7 0.76123 1 0.256836 -23 28 8 0.76123 1 0.256836 -23 28 9 0.76123 1 0.256836 -23 28 10 0.76123 1 0.256836 -23 28 11 0.76123 1 0.256836 -23 28 12 0.76123 1 0.256836 -23 28 13 0.76123 1 0.256836 -23 28 14 0.76123 1 0.256836 -23 28 15 0.761719 1 0.256836 -23 28 16 0.760254 1 0.308838 -23 28 17 0.756348 1 0.399658 -23 28 18 0.75 1 0.483398 -23 28 19 0.741211 1 0.562012 -23 28 20 0.729492 1 0.635254 -23 28 21 0.713867 1 0.704102 -23 28 22 0.694824 1 0.767578 -23 28 23 0.672363 1 0.824219 -23 28 24 0.647461 1 0.874512 -23 28 25 0.615723 1 0.92334 -23 28 26 0.575684 1 0.969238 -23 28 27 0.525879 1 1 -23 28 28 0.462402 1 1 -23 28 29 0.378906 1 1 -23 28 30 0.251709 0.960449 1 -23 28 31 0 0.914551 1 -23 29 0 0.668457 1 0.242676 -23 29 1 0.668457 1 0.242676 -23 29 2 0.668457 1 0.242676 -23 29 3 0.668457 1 0.242676 -23 29 4 0.668457 1 0.242676 -23 29 5 0.668457 1 0.242676 -23 29 6 0.668457 1 0.242676 -23 29 7 0.668457 1 0.242676 -23 29 8 0.668457 1 0.242676 -23 29 9 0.668457 1 0.242676 -23 29 10 0.668457 1 0.242676 -23 29 11 0.668457 1 0.242676 -23 29 12 0.668457 1 0.242676 -23 29 13 0.668457 1 0.242676 -23 29 14 0.668457 1 0.242798 -23 29 15 0.668945 1 0.242798 -23 29 16 0.667969 1 0.269531 -23 29 17 0.664062 1 0.364502 -23 29 18 0.657715 1 0.448975 -23 29 19 0.648438 1 0.527344 -23 29 20 0.636719 1 0.599609 -23 29 21 0.621094 1 0.667969 -23 29 22 0.602051 1 0.731445 -23 29 23 0.57959 1 0.788574 -23 29 24 0.553223 1 0.839355 -23 29 25 0.52002 1 0.88916 -23 29 26 0.477051 1 0.937012 -23 29 27 0.42041 1 0.981445 -23 29 28 0.342041 1 1 -23 29 29 0.207031 1 1 -23 29 30 0 1 1 -23 29 31 0 0.965332 1 -23 30 0 0.560059 1 0.228271 -23 30 1 0.560059 1 0.228271 -23 30 2 0.560059 1 0.228271 -23 30 3 0.560059 1 0.228271 -23 30 4 0.560059 1 0.228271 -23 30 5 0.560059 1 0.228271 -23 30 6 0.560059 1 0.228271 -23 30 7 0.560059 1 0.228271 -23 30 8 0.560059 1 0.228271 -23 30 9 0.560059 1 0.228271 -23 30 10 0.560059 1 0.228271 -23 30 11 0.560059 1 0.228271 -23 30 12 0.560059 1 0.228271 -23 30 13 0.560547 1 0.228271 -23 30 14 0.560547 1 0.228271 -23 30 15 0.561035 1 0.228394 -23 30 16 0.561035 1 0.228394 -23 30 17 0.556152 1 0.32666 -23 30 18 0.54834 1 0.412354 -23 30 19 0.537598 1 0.490234 -23 30 20 0.523926 1 0.561523 -23 30 21 0.506348 1 0.628906 -23 30 22 0.483887 1 0.691895 -23 30 23 0.45752 1 0.748535 -23 30 24 0.426025 1 0.799316 -23 30 25 0.384033 1 0.849609 -23 30 26 0.324219 1 0.899414 -23 30 27 0.224976 1 0.946289 -23 30 28 0 1 0.990234 -23 30 29 0 1 1 -23 30 30 0 1 1 -23 30 31 0 1 1 -23 31 0 0.421143 1 0.213623 -23 31 1 0.421143 1 0.213623 -23 31 2 0.421143 1 0.213623 -23 31 3 0.421143 1 0.213623 -23 31 4 0.421143 1 0.213623 -23 31 5 0.421143 1 0.213623 -23 31 6 0.421143 1 0.213623 -23 31 7 0.421387 1 0.213623 -23 31 8 0.421387 1 0.213623 -23 31 9 0.421387 1 0.213745 -23 31 10 0.421387 1 0.213745 -23 31 11 0.421387 1 0.213745 -23 31 12 0.421631 1 0.213745 -23 31 13 0.421631 1 0.213745 -23 31 14 0.422119 1 0.213745 -23 31 15 0.422607 1 0.213745 -23 31 16 0.423096 1 0.213867 -23 31 17 0.417725 1 0.284912 -23 31 18 0.405762 1 0.373779 -23 31 19 0.389648 1 0.451172 -23 31 20 0.368408 1 0.521484 -23 31 21 0.340332 1 0.587402 -23 31 22 0.30249 1 0.648926 -23 31 23 0.250488 1 0.705078 -23 31 24 0.16394 1 0.755859 -23 31 25 0 1 0.806641 -23 31 26 0 1 0.857422 -23 31 27 0 1 0.906738 -23 31 28 0 1 0.953613 -23 31 29 0 1 0.99707 -23 31 30 0 1 1 -23 31 31 0 1 1 -24 0 0 1 0 0.0671997 -24 0 1 1 0 0.0671997 -24 0 2 1 0 0.0671997 -24 0 3 1 0 0.0671997 -24 0 4 1 0 0.0671997 -24 0 5 1 0 0.0671997 -24 0 6 1 0 0.0671387 -24 0 7 1 0 0.0671387 -24 0 8 1 0 0.0670166 -24 0 9 1 0 0.0668945 -24 0 10 1 0 0.0665894 -24 0 11 1 0 0.06604 -24 0 12 1 0 0.0651855 -24 0 13 1 0 0.0636597 -24 0 14 1 0 0.0622864 -24 0 15 1 0 0.171753 -24 0 16 1 0 0.337158 -24 0 17 1 0 0.459473 -24 0 18 1 0 0.566406 -24 0 19 1 0 0.672363 -24 0 20 1 0.23645 0.769531 -24 0 21 1 0.322998 0.852051 -24 0 22 1 0.363525 0.916992 -24 0 23 1 0.373535 0.966309 -24 0 24 1 0.374023 1 -24 0 25 1 0.372559 1 -24 0 26 1 0.368896 1 -24 0 27 0.944336 0.362793 1 -24 0 28 0.874023 0.355469 1 -24 0 29 0.800781 0.347412 1 -24 0 30 0.725586 0.339355 1 -24 0 31 0.649414 0.331787 1 -24 1 0 1 0 0.0671997 -24 1 1 1 0 0.0671997 -24 1 2 1 0 0.0671997 -24 1 3 1 0 0.0671997 -24 1 4 1 0 0.0671997 -24 1 5 1 0 0.0671387 -24 1 6 1 0 0.0671387 -24 1 7 1 0 0.0670776 -24 1 8 1 0 0.0670166 -24 1 9 1 0 0.0668335 -24 1 10 1 0 0.0665894 -24 1 11 1 0 0.06604 -24 1 12 1 0 0.0651245 -24 1 13 1 0 0.0636597 -24 1 14 1 0 0.0622559 -24 1 15 1 0 0.171753 -24 1 16 1 0 0.337158 -24 1 17 1 0 0.459473 -24 1 18 1 0 0.566406 -24 1 19 1 0 0.672363 -24 1 20 1 0.23645 0.769531 -24 1 21 1 0.322998 0.852051 -24 1 22 1 0.363525 0.916992 -24 1 23 1 0.373535 0.966309 -24 1 24 1 0.374023 1 -24 1 25 1 0.372559 1 -24 1 26 1 0.368896 1 -24 1 27 0.944336 0.362793 1 -24 1 28 0.874023 0.355469 1 -24 1 29 0.800781 0.347412 1 -24 1 30 0.725586 0.339355 1 -24 1 31 0.649414 0.331787 1 -24 2 0 1 0 0.0671387 -24 2 1 1 0 0.0671387 -24 2 2 1 0 0.0671387 -24 2 3 1 0 0.0671387 -24 2 4 1 0 0.0671387 -24 2 5 1 0 0.0671387 -24 2 6 1 0 0.0671387 -24 2 7 1 0 0.0670776 -24 2 8 1 0 0.0670166 -24 2 9 1 0 0.0668335 -24 2 10 1 0 0.0665283 -24 2 11 1 0 0.06604 -24 2 12 1 0 0.0651245 -24 2 13 1 0 0.0635986 -24 2 14 1 0 0.0622559 -24 2 15 1 0 0.171753 -24 2 16 1 0 0.337158 -24 2 17 1 0 0.459473 -24 2 18 1 0 0.566406 -24 2 19 1 0 0.672363 -24 2 20 1 0.236572 0.769531 -24 2 21 1 0.322998 0.852051 -24 2 22 1 0.363525 0.916992 -24 2 23 1 0.373535 0.966309 -24 2 24 1 0.374023 1 -24 2 25 1 0.372559 1 -24 2 26 1 0.368896 1 -24 2 27 0.944336 0.362793 1 -24 2 28 0.874023 0.355469 1 -24 2 29 0.800781 0.347412 1 -24 2 30 0.725586 0.339355 1 -24 2 31 0.649414 0.331787 1 -24 3 0 1 0 0.0671387 -24 3 1 1 0 0.0671387 -24 3 2 1 0 0.0671387 -24 3 3 1 0 0.0671387 -24 3 4 1 0 0.0671387 -24 3 5 1 0 0.0670776 -24 3 6 1 0 0.0670776 -24 3 7 1 0 0.0670166 -24 3 8 1 0 0.0669556 -24 3 9 1 0 0.0667725 -24 3 10 1 0 0.0665283 -24 3 11 1 0 0.065979 -24 3 12 1 0 0.0650635 -24 3 13 1 0 0.0635986 -24 3 14 1 0 0.0621948 -24 3 15 1 0 0.171753 -24 3 16 1 0 0.337158 -24 3 17 1 0 0.459473 -24 3 18 1 0 0.566406 -24 3 19 1 0 0.672363 -24 3 20 1 0.236572 0.769531 -24 3 21 1 0.322998 0.852051 -24 3 22 1 0.36377 0.916992 -24 3 23 1 0.373535 0.966309 -24 3 24 1 0.374023 1 -24 3 25 1 0.372559 1 -24 3 26 1 0.368896 1 -24 3 27 0.944336 0.362793 1 -24 3 28 0.874023 0.355469 1 -24 3 29 0.800781 0.347412 1 -24 3 30 0.725586 0.339355 1 -24 3 31 0.649414 0.331787 1 -24 4 0 1 0 0.0670776 -24 4 1 1 0 0.0670776 -24 4 2 1 0 0.0670776 -24 4 3 1 0 0.0670776 -24 4 4 1 0 0.0670166 -24 4 5 1 0 0.0670166 -24 4 6 1 0 0.0670166 -24 4 7 1 0 0.0669556 -24 4 8 1 0 0.0668945 -24 4 9 1 0 0.0667114 -24 4 10 1 0 0.0664062 -24 4 11 1 0 0.065918 -24 4 12 1 0 0.0650024 -24 4 13 1 0 0.0634766 -24 4 14 1 0 0.0621033 -24 4 15 1 0 0.171753 -24 4 16 1 0 0.337158 -24 4 17 1 0 0.459473 -24 4 18 1 0 0.566406 -24 4 19 1 0 0.672363 -24 4 20 1 0.236816 0.769531 -24 4 21 1 0.323242 0.852051 -24 4 22 1 0.36377 0.916992 -24 4 23 1 0.373779 0.966309 -24 4 24 1 0.374023 1 -24 4 25 1 0.372803 1 -24 4 26 1 0.368896 1 -24 4 27 0.944336 0.363037 1 -24 4 28 0.874023 0.355469 1 -24 4 29 0.800781 0.347412 1 -24 4 30 0.725586 0.339355 1 -24 4 31 0.649414 0.331787 1 -24 5 0 1 0 0.0668945 -24 5 1 1 0 0.0668945 -24 5 2 1 0 0.0668945 -24 5 3 1 0 0.0668945 -24 5 4 1 0 0.0668945 -24 5 5 1 0 0.0668945 -24 5 6 1 0 0.0668945 -24 5 7 1 0 0.0668335 -24 5 8 1 0 0.0667725 -24 5 9 1 0 0.0665894 -24 5 10 1 0 0.0662842 -24 5 11 1 0 0.0657959 -24 5 12 1 0 0.0648804 -24 5 13 1 0 0.0633545 -24 5 14 1 0 0.0619507 -24 5 15 1 0 0.171753 -24 5 16 1 0 0.337158 -24 5 17 1 0 0.459473 -24 5 18 1 0 0.566406 -24 5 19 1 0 0.672363 -24 5 20 1 0.237183 0.769531 -24 5 21 1 0.323242 0.852051 -24 5 22 1 0.364014 0.916992 -24 5 23 1 0.374023 0.966309 -24 5 24 1 0.374268 1 -24 5 25 1 0.372803 1 -24 5 26 1 0.369141 1 -24 5 27 0.943848 0.363037 1 -24 5 28 0.874023 0.355713 1 -24 5 29 0.800781 0.347656 1 -24 5 30 0.725586 0.3396 1 -24 5 31 0.649414 0.331787 1 -24 6 0 1 0 0.0666504 -24 6 1 1 0 0.0666504 -24 6 2 1 0 0.0666504 -24 6 3 1 0 0.0666504 -24 6 4 1 0 0.0666504 -24 6 5 1 0 0.0666504 -24 6 6 1 0 0.0665894 -24 6 7 1 0 0.0665283 -24 6 8 1 0 0.0664673 -24 6 9 1 0 0.0662842 -24 6 10 1 0 0.06604 -24 6 11 1 0 0.0654907 -24 6 12 1 0 0.0645752 -24 6 13 1 0 0.0630493 -24 6 14 1 0 0.0616455 -24 6 15 1 0 0.171753 -24 6 16 1 0 0.337158 -24 6 17 1 0 0.459473 -24 6 18 1 0 0.566406 -24 6 19 1 0 0.672363 -24 6 20 1 0.237793 0.769531 -24 6 21 1 0.32373 0.852051 -24 6 22 1 0.364258 0.916992 -24 6 23 1 0.374268 0.966309 -24 6 24 1 0.374512 1 -24 6 25 1 0.373047 1 -24 6 26 1 0.369385 1 -24 6 27 0.943848 0.363281 1 -24 6 28 0.874023 0.355957 1 -24 6 29 0.800781 0.347656 1 -24 6 30 0.725586 0.3396 1 -24 6 31 0.649414 0.332031 1 -24 7 0 1 0 0.0661011 -24 7 1 1 0 0.0661011 -24 7 2 1 0 0.0661011 -24 7 3 1 0 0.0661011 -24 7 4 1 0 0.0661011 -24 7 5 1 0 0.0661011 -24 7 6 1 0 0.06604 -24 7 7 1 0 0.06604 -24 7 8 1 0 0.065918 -24 7 9 1 0 0.0657959 -24 7 10 1 0 0.0654907 -24 7 11 1 0 0.0649414 -24 7 12 1 0 0.0640259 -24 7 13 1 0 0.0624695 -24 7 14 1 0 0.0610657 -24 7 15 1 0 0.171753 -24 7 16 1 0 0.337158 -24 7 17 1 0 0.459473 -24 7 18 1 0 0.566406 -24 7 19 1 0 0.672363 -24 7 20 1 0.239136 0.769531 -24 7 21 1 0.324463 0.852051 -24 7 22 1 0.36499 0.916992 -24 7 23 1 0.374756 0.966309 -24 7 24 1 0.375 1 -24 7 25 1 0.373535 1 -24 7 26 1 0.369873 1 -24 7 27 0.943848 0.36377 1 -24 7 28 0.874023 0.356201 1 -24 7 29 0.800781 0.348145 1 -24 7 30 0.725586 0.340088 1 -24 7 31 0.648926 0.332275 1 -24 8 0 1 0 0.0650635 -24 8 1 1 0 0.0650635 -24 8 2 1 0 0.0650635 -24 8 3 1 0 0.0650635 -24 8 4 1 0 0.0650635 -24 8 5 1 0 0.0650635 -24 8 6 1 0 0.0650024 -24 8 7 1 0 0.0649414 -24 8 8 1 0 0.0648804 -24 8 9 1 0 0.0646973 -24 8 10 1 0 0.0643921 -24 8 11 1 0 0.0638428 -24 8 12 1 0 0.0629272 -24 8 13 1 0 0.0613098 -24 8 14 1 0 0.059845 -24 8 15 1 0 0.171753 -24 8 16 1 0 0.336914 -24 8 17 1 0 0.459473 -24 8 18 1 0 0.566406 -24 8 19 1 0 0.672363 -24 8 20 1 0.241577 0.769043 -24 8 21 1 0.326172 0.852051 -24 8 22 1 0.366211 0.916992 -24 8 23 1 0.375977 0.966309 -24 8 24 1 0.376221 1 -24 8 25 1 0.374756 1 -24 8 26 1 0.37085 1 -24 8 27 0.943848 0.364502 1 -24 8 28 0.874023 0.356934 1 -24 8 29 0.800781 0.348877 1 -24 8 30 0.725586 0.340576 1 -24 8 31 0.648926 0.332764 1 -24 9 0 1 0 0.0629272 -24 9 1 1 0 0.0629272 -24 9 2 1 0 0.0629272 -24 9 3 1 0 0.0629272 -24 9 4 1 0 0.0629272 -24 9 5 1 0 0.0629272 -24 9 6 1 0 0.0629272 -24 9 7 1 0 0.0628662 -24 9 8 1 0 0.0627441 -24 9 9 1 0 0.062561 -24 9 10 1 0 0.0622559 -24 9 11 1 0 0.061676 -24 9 12 1 0 0.0606689 -24 9 13 1 0 0.05896 -24 9 14 1 0 0.0574341 -24 9 15 1 0 0.171753 -24 9 16 1 0 0.336914 -24 9 17 1 0 0.459473 -24 9 18 1 0 0.566406 -24 9 19 1 0.0397644 0.672363 -24 9 20 1 0.246216 0.769043 -24 9 21 1 0.329102 0.852051 -24 9 22 1 0.368652 0.916992 -24 9 23 1 0.378174 0.966309 -24 9 24 1 0.378418 1 -24 9 25 1 0.376709 1 -24 9 26 1 0.372559 1 -24 9 27 0.943848 0.366211 1 -24 9 28 0.874023 0.358398 1 -24 9 29 0.800781 0.350098 1 -24 9 30 0.725586 0.341797 1 -24 9 31 0.648926 0.33374 1 -24 10 0 1 0 0.0588074 -24 10 1 1 0 0.0587769 -24 10 2 1 0 0.0587769 -24 10 3 1 0 0.0587769 -24 10 4 1 0 0.0587769 -24 10 5 1 0 0.0587769 -24 10 6 1 0 0.0587463 -24 10 7 1 0 0.0586853 -24 10 8 1 0 0.0585938 -24 10 9 1 0 0.0583801 -24 10 10 1 0 0.0580139 -24 10 11 1 0 0.057373 -24 10 12 1 0 0.0562439 -24 10 13 1 0 0.0542908 -24 10 14 1 0 0.0525513 -24 10 15 1 0 0.171875 -24 10 16 1 0 0.33667 -24 10 17 1 0 0.459473 -24 10 18 1 0 0.566406 -24 10 19 1 0.101379 0.671875 -24 10 20 1 0.254395 0.769043 -24 10 21 1 0.334229 0.852051 -24 10 22 1 0.373047 0.916992 -24 10 23 1 0.382324 0.966309 -24 10 24 1 0.38208 1 -24 10 25 1 0.380127 1 -24 10 26 1 0.375732 1 -24 10 27 0.943848 0.369141 1 -24 10 28 0.873535 0.361084 1 -24 10 29 0.800293 0.352539 1 -24 10 30 0.725098 0.34375 1 -24 10 31 0.648926 0.335693 1 -24 11 0 1 0 0.0500488 -24 11 1 1 0 0.0500488 -24 11 2 1 0 0.0500488 -24 11 3 1 0 0.0500488 -24 11 4 1 0 0.0500183 -24 11 5 1 0 0.0500183 -24 11 6 1 0 0.0499878 -24 11 7 1 0 0.0498962 -24 11 8 1 0 0.0497742 -24 11 9 1 0 0.0494995 -24 11 10 1 0 0.0490417 -24 11 11 1 0 0.0481873 -24 11 12 1 0 0.0466614 -24 11 13 1 0 0.0439758 -24 11 14 1 0 0.0415955 -24 11 15 1 0 0.172119 -24 11 16 1 0 0.33667 -24 11 17 1 0 0.459473 -24 11 18 1 0 0.565918 -24 11 19 1 0.146484 0.671387 -24 11 20 1 0.267578 0.768555 -24 11 21 1 0.343018 0.852051 -24 11 22 1 0.380371 0.916992 -24 11 23 1 0.38916 0.966309 -24 11 24 1 0.388672 1 -24 11 25 1 0.38623 1 -24 11 26 1 0.381348 1 -24 11 27 0.943359 0.374268 1 -24 11 28 0.873535 0.365723 1 -24 11 29 0.799805 0.356445 1 -24 11 30 0.725098 0.347412 1 -24 11 31 0.648438 0.338867 1 -24 12 0 1 0 0.0211792 -24 12 1 1 0 0.0211639 -24 12 2 1 0 0.0211639 -24 12 3 1 0 0.0211334 -24 12 4 1 0 0.0211029 -24 12 5 1 0 0.0210266 -24 12 6 1 0 0.0208893 -24 12 7 1 0 0.0205994 -24 12 8 1 0 0.0200348 -24 12 9 1 0 0.0188751 -24 12 10 1 0 0.0164032 -24 12 11 1 0 0.0092392 -24 12 12 1 0.0552368 0 -24 12 13 1 0.0840454 0 -24 12 14 1 0.0987549 0 -24 12 15 1 0.0988159 0.172729 -24 12 16 1 0.0563049 0.336182 -24 12 17 1 0.0758057 0.458496 -24 12 18 1 0.0889893 0.56543 -24 12 19 1 0.193115 0.670898 -24 12 20 1 0.28833 0.768066 -24 12 21 1 0.357422 0.851562 -24 12 22 1 0.392578 0.916992 -24 12 23 1 0.400635 0.966309 -24 12 24 1 0.399414 1 -24 12 25 1 0.396484 1 -24 12 26 1 0.390625 1 -24 12 27 0.942871 0.382812 1 -24 12 28 0.872559 0.373291 1 -24 12 29 0.799316 0.363281 1 -24 12 30 0.724121 0.353516 1 -24 12 31 0.647949 0.344238 1 -24 13 0 1 0.183716 0 -24 13 1 1 0.183716 0 -24 13 2 1 0.183716 0 -24 13 3 1 0.183716 0 -24 13 4 1 0.183716 0 -24 13 5 1 0.183838 0 -24 13 6 1 0.183838 0 -24 13 7 1 0.184082 0 -24 13 8 1 0.184448 0 -24 13 9 1 0.185059 0 -24 13 10 1 0.186401 0 -24 13 11 1 0.188477 0 -24 13 12 1 0.192017 0 -24 13 13 1 0.197754 0 -24 13 14 1 0.20166 0 -24 13 15 1 0.200562 0.174316 -24 13 16 1 0.190308 0.336182 -24 13 17 1 0.191528 0.45752 -24 13 18 1 0.196533 0.564941 -24 13 19 1 0.244507 0.669922 -24 13 20 1 0.317627 0.767578 -24 13 21 1 0.378906 0.851074 -24 13 22 1 0.411377 0.916992 -24 13 23 1 0.418213 0.966309 -24 13 24 1 0.41626 1 -24 13 25 1 0.412109 1 -24 13 26 1 0.405273 1 -24 13 27 0.941406 0.395996 1 -24 13 28 0.871582 0.385254 1 -24 13 29 0.79834 0.374023 1 -24 13 30 0.723145 0.363037 1 -24 13 31 0.646484 0.352539 1 -24 14 0 1 0.270508 0 -24 14 1 1 0.270508 0 -24 14 2 1 0.270508 0 -24 14 3 1 0.270508 0 -24 14 4 1 0.270508 0 -24 14 5 1 0.270508 0 -24 14 6 1 0.270508 0 -24 14 7 1 0.270752 0 -24 14 8 1 0.270996 0 -24 14 9 1 0.27124 0 -24 14 10 1 0.271973 0 -24 14 11 1 0.273193 0 -24 14 12 1 0.275146 0 -24 14 13 1 0.27832 0 -24 14 14 1 0.280518 0 -24 14 15 1 0.279053 0.178345 -24 14 16 1 0.272705 0.336426 -24 14 17 1 0.27124 0.456055 -24 14 18 1 0.275635 0.564453 -24 14 19 1 0.302246 0.668457 -24 14 20 1 0.356934 0.766113 -24 14 21 1 0.409668 0.850586 -24 14 22 1 0.438721 0.916504 -24 14 23 1 0.444092 0.966309 -24 14 24 1 0.440674 1 -24 14 25 1 0.435303 1 -24 14 26 1 0.426758 1 -24 14 27 0.939941 0.415771 1 -24 14 28 0.870117 0.403076 1 -24 14 29 0.796387 0.390137 1 -24 14 30 0.721191 0.377197 1 -24 14 31 0.64502 0.365234 1 -24 15 0 1 0.352051 0 -24 15 1 1 0.352051 0 -24 15 2 1 0.352051 0 -24 15 3 1 0.352051 0 -24 15 4 1 0.352295 0 -24 15 5 1 0.352295 0 -24 15 6 1 0.352295 0 -24 15 7 1 0.352295 0 -24 15 8 1 0.352539 0 -24 15 9 1 0.352783 0 -24 15 10 1 0.353027 0 -24 15 11 1 0.354004 0 -24 15 12 1 0.355225 0 -24 15 13 1 0.357422 0 -24 15 14 1 0.358887 0 -24 15 15 1 0.356934 0.187744 -24 15 16 1 0.352295 0.338135 -24 15 17 1 0.349609 0.455078 -24 15 18 1 0.354004 0.563965 -24 15 19 1 0.366943 0.666016 -24 15 20 1 0.40625 0.763672 -24 15 21 1 0.450439 0.849121 -24 15 22 1 0.47583 0.916504 -24 15 23 1 0.479492 0.966309 -24 15 24 1 0.474609 1 -24 15 25 1 0.467285 1 -24 15 26 1 0.456543 1 -24 15 27 0.937012 0.443115 1 -24 15 28 0.867188 0.428223 1 -24 15 29 0.793945 0.412598 1 -24 15 30 0.71875 0.397705 1 -24 15 31 0.64209 0.383545 1 -24 16 0 1 0.436279 0 -24 16 1 1 0.436279 0 -24 16 2 1 0.436279 0 -24 16 3 1 0.436523 0 -24 16 4 1 0.436523 0 -24 16 5 1 0.436523 0 -24 16 6 1 0.436523 0 -24 16 7 1 0.436523 0 -24 16 8 1 0.436523 0 -24 16 9 1 0.436768 0 -24 16 10 1 0.437012 0 -24 16 11 1 0.437744 0 -24 16 12 1 0.438721 0 -24 16 13 1 0.440186 0 -24 16 14 1 0.441162 0 -24 16 15 1 0.439453 0.205933 -24 16 16 1 0.436035 0.34375 -24 16 17 1 0.432373 0.455566 -24 16 18 1 0.434082 0.562988 -24 16 19 1 0.439697 0.662598 -24 16 20 1 0.465332 0.759766 -24 16 21 1 0.500977 0.84668 -24 16 22 1 0.522949 0.915039 -24 16 23 1 0.524902 0.96582 -24 16 24 1 0.518555 1 -24 16 25 1 0.508789 1 -24 16 26 0.997559 0.495605 1 -24 16 27 0.933105 0.479248 1 -24 16 28 0.862793 0.461426 1 -24 16 29 0.789551 0.442871 1 -24 16 30 0.714844 0.425049 1 -24 16 31 0.638184 0.408203 1 -24 17 0 1 0.522949 0 -24 17 1 1 0.522949 0 -24 17 2 1 0.522949 0 -24 17 3 1 0.522949 0 -24 17 4 1 0.522949 0 -24 17 5 1 0.522949 0 -24 17 6 1 0.522949 0 -24 17 7 1 0.522949 0 -24 17 8 1 0.522949 0 -24 17 9 1 0.523438 0 -24 17 10 1 0.523438 0 -24 17 11 1 0.523926 0 -24 17 12 1 0.524414 0 -24 17 13 1 0.525879 0 -24 17 14 1 0.526855 0 -24 17 15 1 0.525391 0.235229 -24 17 16 1 0.522949 0.355957 -24 17 17 1 0.519531 0.460205 -24 17 18 1 0.516602 0.561035 -24 17 19 1 0.519043 0.660156 -24 17 20 1 0.532227 0.754395 -24 17 21 1 0.55957 0.842773 -24 17 22 1 0.578613 0.913574 -24 17 23 1 0.579102 0.964844 -24 17 24 1 0.570801 1 -24 17 25 1 0.558594 1 -24 17 26 0.991699 0.54248 1 -24 17 27 0.926758 0.522949 1 -24 17 28 0.856934 0.501465 1 -24 17 29 0.783691 0.479736 1 -24 17 30 0.708984 0.45874 1 -24 17 31 0.632812 0.438965 1 -24 18 0 1 0.609863 0 -24 18 1 1 0.609863 0 -24 18 2 1 0.609863 0 -24 18 3 1 0.609863 0 -24 18 4 1 0.609863 0 -24 18 5 1 0.609863 0 -24 18 6 1 0.609863 0 -24 18 7 1 0.609863 0 -24 18 8 1 0.609863 0 -24 18 9 1 0.610352 0 -24 18 10 1 0.610352 0 -24 18 11 1 0.61084 0 -24 18 12 1 0.611328 0 -24 18 13 1 0.612305 0 -24 18 14 1 0.613281 0.122559 -24 18 15 1 0.612793 0.272705 -24 18 16 1 0.611328 0.376221 -24 18 17 1 0.608398 0.471436 -24 18 18 1 0.603516 0.564453 -24 18 19 1 0.601074 0.657715 -24 18 20 1 0.604492 0.747559 -24 18 21 1 0.62207 0.836426 -24 18 22 1 0.63916 0.909668 -24 18 23 1 0.638672 0.962402 -24 18 24 1 0.628418 1 -24 18 25 1 0.614258 1 -24 18 26 0.98291 0.595215 1 -24 18 27 0.918457 0.572266 1 -24 18 28 0.848633 0.547363 1 -24 18 29 0.775391 0.521973 1 -24 18 30 0.701172 0.497559 1 -24 18 31 0.625 0.474365 1 -24 19 0 1 0.694824 0.199097 -24 19 1 1 0.694824 0.199097 -24 19 2 1 0.694824 0.199097 -24 19 3 1 0.694824 0.199097 -24 19 4 1 0.694824 0.199097 -24 19 5 1 0.694824 0.199097 -24 19 6 1 0.694824 0.199097 -24 19 7 1 0.694824 0.199097 -24 19 8 1 0.694824 0.199097 -24 19 9 1 0.694824 0.199219 -24 19 10 1 0.695312 0.199341 -24 19 11 1 0.695312 0.199585 -24 19 12 1 0.695801 0.200073 -24 19 13 1 0.696289 0.200806 -24 19 14 1 0.697754 0.211426 -24 19 15 1 0.697754 0.311035 -24 19 16 1 0.697754 0.401367 -24 19 17 1 0.695801 0.489014 -24 19 18 1 0.690918 0.574707 -24 19 19 1 0.684082 0.658203 -24 19 20 1 0.681641 0.743164 -24 19 21 1 0.686523 0.827148 -24 19 22 1 0.700684 0.903809 -24 19 23 1 0.700195 0.958984 -24 19 24 1 0.688965 1 -24 19 25 1 0.672852 1 -24 19 26 0.97168 0.650391 1 -24 19 27 0.907227 0.624023 1 -24 19 28 0.837402 0.595703 1 -24 19 29 0.765137 0.566895 1 -24 19 30 0.691406 0.539062 1 -24 19 31 0.615723 0.513184 1 -24 20 0 1 0.774414 0.265137 -24 20 1 1 0.774414 0.265137 -24 20 2 1 0.774414 0.265137 -24 20 3 1 0.774414 0.265137 -24 20 4 1 0.774414 0.265137 -24 20 5 1 0.774414 0.265137 -24 20 6 1 0.774414 0.265137 -24 20 7 1 0.774414 0.265137 -24 20 8 1 0.774414 0.265137 -24 20 9 1 0.774414 0.265137 -24 20 10 1 0.774414 0.265137 -24 20 11 1 0.774414 0.265381 -24 20 12 1 0.774902 0.265625 -24 20 13 1 0.775391 0.265869 -24 20 14 1 0.776367 0.266357 -24 20 15 1 0.777344 0.342529 -24 20 16 1 0.777832 0.424805 -24 20 17 1 0.777344 0.507812 -24 20 18 1 0.773926 0.588867 -24 20 19 1 0.76709 0.666504 -24 20 20 1 0.757324 0.740723 -24 20 21 1 0.752441 0.817383 -24 20 22 1 0.759277 0.894531 -24 20 23 1 0.760742 0.953125 -24 20 24 1 0.748535 0.995605 -24 20 25 1 0.730469 1 -24 20 26 0.956543 0.705078 1 -24 20 27 0.892578 0.675293 1 -24 20 28 0.824219 0.644043 1 -24 20 29 0.75293 0.612305 1 -24 20 30 0.679688 0.582031 1 -24 20 31 0.604492 0.553223 1 -24 21 0 1 0.848145 0.303223 -24 21 1 1 0.848145 0.303223 -24 21 2 1 0.848145 0.303223 -24 21 3 1 0.848145 0.303223 -24 21 4 1 0.848145 0.303223 -24 21 5 1 0.848145 0.303223 -24 21 6 1 0.848145 0.303223 -24 21 7 1 0.848145 0.303223 -24 21 8 1 0.848145 0.303223 -24 21 9 1 0.848145 0.303223 -24 21 10 1 0.848145 0.303467 -24 21 11 1 0.848633 0.303467 -24 21 12 1 0.848633 0.303467 -24 21 13 1 0.849121 0.303711 -24 21 14 1 0.849609 0.303955 -24 21 15 1 0.851074 0.361328 -24 21 16 1 0.852051 0.440186 -24 21 17 1 0.852539 0.520996 -24 21 18 1 0.850586 0.601562 -24 21 19 1 0.845215 0.677734 -24 21 20 1 0.835449 0.746582 -24 21 21 1 0.822266 0.812012 -24 21 22 1 0.816406 0.881348 -24 21 23 1 0.818848 0.944824 -24 21 24 1 0.807129 0.989258 -24 21 25 0.993652 0.787109 1 -24 21 26 0.937988 0.758789 1 -24 21 27 0.874512 0.726074 1 -24 21 28 0.807617 0.692383 1 -24 21 29 0.737793 0.658691 1 -24 21 30 0.666016 0.625977 1 -24 21 31 0.591309 0.594727 1 -24 22 0 1 0.914551 0.320801 -24 22 1 1 0.914551 0.320801 -24 22 2 1 0.914551 0.320801 -24 22 3 1 0.914551 0.320801 -24 22 4 1 0.914551 0.320801 -24 22 5 1 0.914551 0.320801 -24 22 6 1 0.914551 0.320801 -24 22 7 1 0.914551 0.320801 -24 22 8 1 0.914551 0.320801 -24 22 9 1 0.914551 0.320801 -24 22 10 1 0.914551 0.321045 -24 22 11 1 0.914551 0.321045 -24 22 12 1 0.915039 0.321045 -24 22 13 1 0.915039 0.321045 -24 22 14 1 0.915527 0.321045 -24 22 15 1 0.916992 0.36499 -24 22 16 1 0.918945 0.443359 -24 22 17 1 0.919922 0.524414 -24 22 18 1 0.918945 0.605469 -24 22 19 1 0.915039 0.683105 -24 22 20 1 0.907227 0.753418 -24 22 21 1 0.894043 0.81543 -24 22 22 1 0.877441 0.871582 -24 22 23 1 0.87207 0.932617 -24 22 24 1 0.862305 0.97998 -24 22 25 0.970215 0.839844 1 -24 22 26 0.914551 0.809082 1 -24 22 27 0.853516 0.774902 1 -24 22 28 0.789062 0.739746 1 -24 22 29 0.721191 0.70459 1 -24 22 30 0.650879 0.67041 1 -24 22 31 0.576172 0.637207 1 -24 23 0 1 0.969727 0.323486 -24 23 1 1 0.969727 0.323486 -24 23 2 1 0.969727 0.323486 -24 23 3 1 0.969727 0.323486 -24 23 4 1 0.969727 0.323486 -24 23 5 1 0.969727 0.323486 -24 23 6 1 0.969727 0.323486 -24 23 7 1 0.969727 0.323486 -24 23 8 1 0.969727 0.323486 -24 23 9 1 0.969727 0.323486 -24 23 10 1 0.970215 0.323486 -24 23 11 1 0.970215 0.323486 -24 23 12 1 0.970215 0.323486 -24 23 13 1 0.970215 0.323486 -24 23 14 1 0.970703 0.323486 -24 23 15 1 0.972168 0.355469 -24 23 16 1 0.974121 0.435303 -24 23 17 1 0.976074 0.517578 -24 23 18 1 0.976074 0.599609 -24 23 19 1 0.973633 0.678711 -24 23 20 1 0.967773 0.751465 -24 23 21 1 0.957031 0.816895 -24 23 22 1 0.940918 0.873047 -24 23 23 1 0.921387 0.918945 -24 23 24 0.986328 0.912109 0.969238 -24 23 25 0.942383 0.886719 1 -24 23 26 0.888672 0.854492 1 -24 23 27 0.831055 0.820801 1 -24 23 28 0.769531 0.785645 1 -24 23 29 0.704102 0.75 1 -24 23 30 0.634766 0.714355 1 -24 23 31 0.560059 0.679688 1 -24 24 0 1 1 0.318359 -24 24 1 1 1 0.318359 -24 24 2 1 1 0.318359 -24 24 3 1 1 0.318359 -24 24 4 1 1 0.318359 -24 24 5 1 1 0.318359 -24 24 6 1 1 0.318359 -24 24 7 1 1 0.318359 -24 24 8 1 1 0.318359 -24 24 9 1 1 0.318359 -24 24 10 1 1 0.318359 -24 24 11 1 1 0.318359 -24 24 12 1 1 0.318359 -24 24 13 1 1 0.318359 -24 24 14 1 1 0.318359 -24 24 15 1 1 0.337891 -24 24 16 1 1 0.419922 -24 24 17 1 1 0.503418 -24 24 18 1 1 0.585938 -24 24 19 1 1 0.666016 -24 24 20 1 1 0.739258 -24 24 21 1 1 0.807129 -24 24 22 1 0.993164 0.866699 -24 24 23 0.991211 0.976562 0.916016 -24 24 24 0.956543 0.956543 0.956543 -24 24 25 0.913574 0.930176 0.990234 -24 24 26 0.864746 0.899902 1 -24 24 27 0.810059 0.866699 1 -24 24 28 0.750488 0.831543 1 -24 24 29 0.686035 0.794434 1 -24 24 30 0.616699 0.756836 1 -24 24 31 0.540527 0.719238 1 -24 25 0 1 1 0.309814 -24 25 1 1 1 0.309814 -24 25 2 1 1 0.309814 -24 25 3 1 1 0.309814 -24 25 4 1 1 0.309814 -24 25 5 1 1 0.309814 -24 25 6 1 1 0.309814 -24 25 7 1 1 0.309814 -24 25 8 1 1 0.309814 -24 25 9 1 1 0.309814 -24 25 10 1 1 0.309814 -24 25 11 1 1 0.309814 -24 25 12 1 1 0.309814 -24 25 13 1 1 0.309814 -24 25 14 1 1 0.309814 -24 25 15 1 1 0.314453 -24 25 16 1 1 0.39917 -24 25 17 1 1 0.483154 -24 25 18 1 1 0.565918 -24 25 19 1 1 0.645508 -24 25 20 1 1 0.719238 -24 25 21 1 1 0.786621 -24 25 22 0.97998 1 0.84668 -24 25 23 0.950684 1 0.896484 -24 25 24 0.92041 1 0.94043 -24 25 25 0.887695 0.983398 0.984863 -24 25 26 0.842285 0.95459 1 -24 25 27 0.788086 0.919434 1 -24 25 28 0.728516 0.881836 1 -24 25 29 0.664062 0.842285 1 -24 25 30 0.59375 0.802734 1 -24 25 31 0.516113 0.762695 1 -24 26 0 0.997559 1 0.299072 -24 26 1 0.997559 1 0.299072 -24 26 2 0.997559 1 0.299072 -24 26 3 0.997559 1 0.299072 -24 26 4 0.997559 1 0.299072 -24 26 5 0.997559 1 0.299072 -24 26 6 0.997559 1 0.299072 -24 26 7 0.997559 1 0.299072 -24 26 8 0.997559 1 0.299072 -24 26 9 0.997559 1 0.299072 -24 26 10 0.997559 1 0.299072 -24 26 11 0.997559 1 0.299072 -24 26 12 0.997559 1 0.299072 -24 26 13 0.99707 1 0.299072 -24 26 14 0.99707 1 0.299072 -24 26 15 0.99707 1 0.298828 -24 26 16 0.996094 1 0.373779 -24 26 17 0.993164 1 0.458496 -24 26 18 0.988281 1 0.541016 -24 26 19 0.979492 1 0.619629 -24 26 20 0.967285 1 0.692871 -24 26 21 0.949707 1 0.760254 -24 26 22 0.927246 1 0.820801 -24 26 23 0.902344 1 0.873535 -24 26 24 0.876465 1 0.920898 -24 26 25 0.845703 1 0.966797 -24 26 26 0.808105 1 1 -24 26 27 0.759766 0.975586 1 -24 26 28 0.702148 0.9375 1 -24 26 29 0.637207 0.896484 1 -24 26 30 0.56543 0.854004 1 -24 26 31 0.484619 0.811035 1 -24 27 0 0.929199 1 0.286621 -24 27 1 0.929199 1 0.286621 -24 27 2 0.929199 1 0.286621 -24 27 3 0.929199 1 0.286621 -24 27 4 0.929199 1 0.286621 -24 27 5 0.929199 1 0.286621 -24 27 6 0.929199 1 0.286621 -24 27 7 0.929199 1 0.286621 -24 27 8 0.929199 1 0.286621 -24 27 9 0.929199 1 0.286621 -24 27 10 0.929199 1 0.286621 -24 27 11 0.929199 1 0.286621 -24 27 12 0.929199 1 0.286621 -24 27 13 0.929199 1 0.286621 -24 27 14 0.928711 1 0.286621 -24 27 15 0.928711 1 0.286621 -24 27 16 0.927734 1 0.344238 -24 27 17 0.925293 1 0.430176 -24 27 18 0.92041 1 0.512695 -24 27 19 0.913086 1 0.59082 -24 27 20 0.901855 1 0.663086 -24 27 21 0.886719 1 0.730957 -24 27 22 0.867676 1 0.792969 -24 27 23 0.846191 1 0.847656 -24 27 24 0.822754 1 0.896484 -24 27 25 0.794434 1 0.943848 -24 27 26 0.758789 1 0.988281 -24 27 27 0.71582 1 1 -24 27 28 0.662598 0.990723 1 -24 27 29 0.599609 0.951172 1 -24 27 30 0.526367 0.907715 1 -24 27 31 0.440918 0.862793 1 -24 28 0 0.853027 1 0.273193 -24 28 1 0.853027 1 0.273193 -24 28 2 0.853027 1 0.273193 -24 28 3 0.853027 1 0.273193 -24 28 4 0.853027 1 0.273193 -24 28 5 0.853027 1 0.273193 -24 28 6 0.853027 1 0.273193 -24 28 7 0.853027 1 0.273193 -24 28 8 0.853027 1 0.273193 -24 28 9 0.853027 1 0.273193 -24 28 10 0.853027 1 0.273193 -24 28 11 0.853027 1 0.273193 -24 28 12 0.853027 1 0.273193 -24 28 13 0.853027 1 0.273193 -24 28 14 0.853027 1 0.273193 -24 28 15 0.853027 1 0.273193 -24 28 16 0.852051 1 0.311035 -24 28 17 0.849609 1 0.39917 -24 28 18 0.845215 1 0.481689 -24 28 19 0.838379 1 0.559082 -24 28 20 0.828613 1 0.631348 -24 28 21 0.81543 1 0.699219 -24 28 22 0.798828 1 0.761719 -24 28 23 0.779785 1 0.817383 -24 28 24 0.758301 1 0.867676 -24 28 25 0.731445 1 0.916016 -24 28 26 0.698242 1 0.962402 -24 28 27 0.656738 1 1 -24 28 28 0.606445 1 1 -24 28 29 0.544434 1 1 -24 28 30 0.469482 0.959473 1 -24 28 31 0.374756 0.914551 1 -24 29 0 0.768066 1 0.259033 -24 29 1 0.768066 1 0.259033 -24 29 2 0.768066 1 0.259033 -24 29 3 0.768066 1 0.259033 -24 29 4 0.768066 1 0.259033 -24 29 5 0.768066 1 0.259033 -24 29 6 0.768066 1 0.259033 -24 29 7 0.768066 1 0.259033 -24 29 8 0.768066 1 0.259033 -24 29 9 0.768066 1 0.259033 -24 29 10 0.768066 1 0.259033 -24 29 11 0.768066 1 0.259033 -24 29 12 0.768066 1 0.259033 -24 29 13 0.768066 1 0.259033 -24 29 14 0.768066 1 0.259033 -24 29 15 0.768066 1 0.259033 -24 29 16 0.768066 1 0.272705 -24 29 17 0.765137 1 0.365234 -24 29 18 0.76123 1 0.447998 -24 29 19 0.754883 1 0.524902 -24 29 20 0.745605 1 0.59668 -24 29 21 0.733887 1 0.664062 -24 29 22 0.71875 1 0.726562 -24 29 23 0.700684 1 0.783203 -24 29 24 0.680664 1 0.833496 -24 29 25 0.654785 1 0.883301 -24 29 26 0.62207 1 0.931641 -24 29 27 0.581543 1 0.976562 -24 29 28 0.530273 1 1 -24 29 29 0.466553 1 1 -24 29 30 0.383057 1 1 -24 29 31 0.256104 0.965332 1 -24 30 0 0.67334 1 0.244263 -24 30 1 0.67334 1 0.244263 -24 30 2 0.67334 1 0.244263 -24 30 3 0.67334 1 0.244263 -24 30 4 0.67334 1 0.244263 -24 30 5 0.67334 1 0.244263 -24 30 6 0.67334 1 0.244263 -24 30 7 0.67334 1 0.244263 -24 30 8 0.67334 1 0.244263 -24 30 9 0.67334 1 0.244263 -24 30 10 0.67334 1 0.244263 -24 30 11 0.673828 1 0.244385 -24 30 12 0.673828 1 0.244385 -24 30 13 0.673828 1 0.244385 -24 30 14 0.673828 1 0.244385 -24 30 15 0.673828 1 0.244385 -24 30 16 0.673828 1 0.244385 -24 30 17 0.671387 1 0.328125 -24 30 18 0.666504 1 0.412354 -24 30 19 0.659668 1 0.489014 -24 30 20 0.650391 1 0.55957 -24 30 21 0.638672 1 0.625977 -24 30 22 0.623535 1 0.688477 -24 30 23 0.605957 1 0.744141 -24 30 24 0.584961 1 0.794922 -24 30 25 0.559082 1 0.845703 -24 30 26 0.525391 1 0.89502 -24 30 27 0.481689 1 0.942871 -24 30 28 0.425049 1 0.986816 -24 30 29 0.346436 1 1 -24 30 30 0.213623 1 1 -24 30 31 0 1 1 -24 31 0 0.563965 1 0.229614 -24 31 1 0.563965 1 0.229614 -24 31 2 0.563965 1 0.229614 -24 31 3 0.563965 1 0.229614 -24 31 4 0.563965 1 0.229614 -24 31 5 0.563965 1 0.229614 -24 31 6 0.563965 1 0.229614 -24 31 7 0.563965 1 0.229614 -24 31 8 0.563965 1 0.229614 -24 31 9 0.563965 1 0.229614 -24 31 10 0.563965 1 0.229614 -24 31 11 0.563965 1 0.229614 -24 31 12 0.564453 1 0.229614 -24 31 13 0.564453 1 0.229614 -24 31 14 0.564453 1 0.229614 -24 31 15 0.564453 1 0.229614 -24 31 16 0.564941 1 0.229736 -24 31 17 0.5625 1 0.287598 -24 31 18 0.556152 1 0.374756 -24 31 19 0.547852 1 0.451172 -24 31 20 0.537109 1 0.520508 -24 31 21 0.522949 1 0.585938 -24 31 22 0.505859 1 0.646973 -24 31 23 0.485352 1 0.702637 -24 31 24 0.461426 1 0.75293 -24 31 25 0.430176 1 0.803711 -24 31 26 0.387939 1 0.854492 -24 31 27 0.328613 1 0.903809 -24 31 28 0.230713 1 0.951172 -24 31 29 0 1 0.994629 -24 31 30 0 1 1 -24 31 31 0 1 1 -25 0 0 1 0 0.0693359 -25 0 1 1 0 0.0693359 -25 0 2 1 0 0.0693359 -25 0 3 1 0 0.0693359 -25 0 4 1 0 0.0693359 -25 0 5 1 0 0.0693359 -25 0 6 1 0 0.0693359 -25 0 7 1 0 0.0692749 -25 0 8 1 0 0.0692139 -25 0 9 1 0 0.0690918 -25 0 10 1 0 0.0688477 -25 0 11 1 0 0.0683594 -25 0 12 1 0 0.067627 -25 0 13 1 0 0.0662842 -25 0 14 1 0 0.0646973 -25 0 15 1 0 0.0632324 -25 0 16 1 0 0.291748 -25 0 17 1 0 0.421875 -25 0 18 1 0 0.53125 -25 0 19 1 0 0.634277 -25 0 20 1 0.139038 0.730957 -25 0 21 1 0.273926 0.816895 -25 0 22 1 0.342529 0.888184 -25 0 23 1 0.373291 0.942871 -25 0 24 1 0.380859 0.985352 -25 0 25 1 0.380615 1 -25 0 26 1 0.378418 1 -25 0 27 1 0.374023 1 -25 0 28 0.956543 0.367676 1 -25 0 29 0.884766 0.359863 1 -25 0 30 0.810547 0.351562 1 -25 0 31 0.733887 0.343262 1 -25 1 0 1 0 0.0693359 -25 1 1 1 0 0.0693359 -25 1 2 1 0 0.0693359 -25 1 3 1 0 0.0693359 -25 1 4 1 0 0.0693359 -25 1 5 1 0 0.0693359 -25 1 6 1 0 0.0693359 -25 1 7 1 0 0.0692749 -25 1 8 1 0 0.0692139 -25 1 9 1 0 0.0690918 -25 1 10 1 0 0.0687866 -25 1 11 1 0 0.0683594 -25 1 12 1 0 0.0675659 -25 1 13 1 0 0.0662842 -25 1 14 1 0 0.0646973 -25 1 15 1 0 0.0632324 -25 1 16 1 0 0.291748 -25 1 17 1 0 0.421875 -25 1 18 1 0 0.53125 -25 1 19 1 0 0.634277 -25 1 20 1 0.139038 0.730957 -25 1 21 1 0.273926 0.816895 -25 1 22 1 0.342529 0.888184 -25 1 23 1 0.373291 0.942871 -25 1 24 1 0.380859 0.985352 -25 1 25 1 0.380615 1 -25 1 26 1 0.378418 1 -25 1 27 1 0.374023 1 -25 1 28 0.956543 0.367676 1 -25 1 29 0.884766 0.359863 1 -25 1 30 0.810547 0.351562 1 -25 1 31 0.733887 0.343262 1 -25 2 0 1 0 0.0693359 -25 2 1 1 0 0.0693359 -25 2 2 1 0 0.0693359 -25 2 3 1 0 0.0693359 -25 2 4 1 0 0.0693359 -25 2 5 1 0 0.0693359 -25 2 6 1 0 0.0692749 -25 2 7 1 0 0.0692749 -25 2 8 1 0 0.0691528 -25 2 9 1 0 0.0690308 -25 2 10 1 0 0.0687866 -25 2 11 1 0 0.0683594 -25 2 12 1 0 0.0675659 -25 2 13 1 0 0.0662842 -25 2 14 1 0 0.0646973 -25 2 15 1 0 0.0631714 -25 2 16 1 0 0.291748 -25 2 17 1 0 0.421875 -25 2 18 1 0 0.53125 -25 2 19 1 0 0.634277 -25 2 20 1 0.13916 0.730957 -25 2 21 1 0.273926 0.816895 -25 2 22 1 0.342529 0.888184 -25 2 23 1 0.373291 0.942871 -25 2 24 1 0.380859 0.985352 -25 2 25 1 0.380615 1 -25 2 26 1 0.378418 1 -25 2 27 1 0.374023 1 -25 2 28 0.956543 0.367676 1 -25 2 29 0.884766 0.359863 1 -25 2 30 0.810547 0.351562 1 -25 2 31 0.733887 0.343262 1 -25 3 0 1 0 0.0692749 -25 3 1 1 0 0.0692749 -25 3 2 1 0 0.0692749 -25 3 3 1 0 0.0692749 -25 3 4 1 0 0.0692749 -25 3 5 1 0 0.0692749 -25 3 6 1 0 0.0692749 -25 3 7 1 0 0.0692139 -25 3 8 1 0 0.0691528 -25 3 9 1 0 0.0690308 -25 3 10 1 0 0.0687866 -25 3 11 1 0 0.0682983 -25 3 12 1 0 0.0675659 -25 3 13 1 0 0.0662231 -25 3 14 1 0 0.0646362 -25 3 15 1 0 0.0631714 -25 3 16 1 0 0.291748 -25 3 17 1 0 0.421875 -25 3 18 1 0 0.53125 -25 3 19 1 0 0.634277 -25 3 20 1 0.139404 0.730957 -25 3 21 1 0.273926 0.816895 -25 3 22 1 0.342529 0.888184 -25 3 23 1 0.373535 0.942871 -25 3 24 1 0.380859 0.985352 -25 3 25 1 0.380615 1 -25 3 26 1 0.378662 1 -25 3 27 1 0.374023 1 -25 3 28 0.956543 0.367676 1 -25 3 29 0.884766 0.359863 1 -25 3 30 0.810547 0.351562 1 -25 3 31 0.733887 0.343262 1 -25 4 0 1 0 0.0692139 -25 4 1 1 0 0.0692139 -25 4 2 1 0 0.0692139 -25 4 3 1 0 0.0692139 -25 4 4 1 0 0.0692139 -25 4 5 1 0 0.0692139 -25 4 6 1 0 0.0692139 -25 4 7 1 0 0.0691528 -25 4 8 1 0 0.0690918 -25 4 9 1 0 0.0689697 -25 4 10 1 0 0.0686646 -25 4 11 1 0 0.0682373 -25 4 12 1 0 0.0674438 -25 4 13 1 0 0.0661621 -25 4 14 1 0 0.0645752 -25 4 15 1 0 0.0630493 -25 4 16 1 0 0.291748 -25 4 17 1 0 0.421875 -25 4 18 1 0 0.53125 -25 4 19 1 0 0.634277 -25 4 20 1 0.139771 0.730957 -25 4 21 1 0.27417 0.816895 -25 4 22 1 0.342529 0.888184 -25 4 23 1 0.373535 0.942871 -25 4 24 1 0.380859 0.985352 -25 4 25 1 0.380859 1 -25 4 26 1 0.378662 1 -25 4 27 1 0.374268 1 -25 4 28 0.956543 0.367676 1 -25 4 29 0.884766 0.359863 1 -25 4 30 0.810547 0.351562 1 -25 4 31 0.733887 0.343262 1 -25 5 0 1 0 0.0690918 -25 5 1 1 0 0.0690918 -25 5 2 1 0 0.0690918 -25 5 3 1 0 0.0690918 -25 5 4 1 0 0.0690918 -25 5 5 1 0 0.0690918 -25 5 6 1 0 0.0690918 -25 5 7 1 0 0.0690308 -25 5 8 1 0 0.0689697 -25 5 9 1 0 0.0688477 -25 5 10 1 0 0.0685425 -25 5 11 1 0 0.0681152 -25 5 12 1 0 0.0673218 -25 5 13 1 0 0.06604 -25 5 14 1 0 0.0644531 -25 5 15 1 0 0.0629272 -25 5 16 1 0 0.291748 -25 5 17 1 0 0.421875 -25 5 18 1 0 0.53125 -25 5 19 1 0 0.634277 -25 5 20 1 0.140503 0.730957 -25 5 21 1 0.274414 0.816895 -25 5 22 1 0.342773 0.888184 -25 5 23 1 0.373535 0.942871 -25 5 24 1 0.381104 0.985352 -25 5 25 1 0.380859 1 -25 5 26 1 0.378662 1 -25 5 27 1 0.374268 1 -25 5 28 0.956543 0.367676 1 -25 5 29 0.884766 0.359863 1 -25 5 30 0.810547 0.351562 1 -25 5 31 0.733887 0.343506 1 -25 6 0 1 0 0.0689087 -25 6 1 1 0 0.0688477 -25 6 2 1 0 0.0688477 -25 6 3 1 0 0.0688477 -25 6 4 1 0 0.0688477 -25 6 5 1 0 0.0688477 -25 6 6 1 0 0.0688477 -25 6 7 1 0 0.0687866 -25 6 8 1 0 0.0687256 -25 6 9 1 0 0.0686035 -25 6 10 1 0 0.0683594 -25 6 11 1 0 0.0678711 -25 6 12 1 0 0.0670776 -25 6 13 1 0 0.0657959 -25 6 14 1 0 0.0641479 -25 6 15 1 0 0.0626831 -25 6 16 1 0 0.291748 -25 6 17 1 0 0.421875 -25 6 18 1 0 0.53125 -25 6 19 1 0 0.634277 -25 6 20 1 0.141968 0.730957 -25 6 21 1 0.274902 0.816895 -25 6 22 1 0.343262 0.888184 -25 6 23 1 0.374023 0.942871 -25 6 24 1 0.381348 0.985352 -25 6 25 1 0.381104 1 -25 6 26 1 0.378906 1 -25 6 27 1 0.374512 1 -25 6 28 0.956543 0.36792 1 -25 6 29 0.884766 0.360107 1 -25 6 30 0.810547 0.351807 1 -25 6 31 0.733887 0.343506 1 -25 7 0 1 0 0.0684204 -25 7 1 1 0 0.0684204 -25 7 2 1 0 0.0684204 -25 7 3 1 0 0.0684204 -25 7 4 1 0 0.0684204 -25 7 5 1 0 0.0684204 -25 7 6 1 0 0.0683594 -25 7 7 1 0 0.0683594 -25 7 8 1 0 0.0682983 -25 7 9 1 0 0.0681152 -25 7 10 1 0 0.0678711 -25 7 11 1 0 0.0674438 -25 7 12 1 0 0.0666504 -25 7 13 1 0 0.0653076 -25 7 14 1 0 0.0636597 -25 7 15 1 0 0.0621338 -25 7 16 1 0 0.291748 -25 7 17 1 0 0.421631 -25 7 18 1 0 0.53125 -25 7 19 1 0 0.634277 -25 7 20 1 0.144653 0.730957 -25 7 21 1 0.275635 0.816895 -25 7 22 1 0.34375 0.887695 -25 7 23 1 0.374512 0.942871 -25 7 24 1 0.381836 0.985352 -25 7 25 1 0.381592 1 -25 7 26 1 0.379395 1 -25 7 27 1 0.375 1 -25 7 28 0.956543 0.368408 1 -25 7 29 0.884766 0.360596 1 -25 7 30 0.810547 0.352051 1 -25 7 31 0.733887 0.34375 1 -25 8 0 1 0 0.0675049 -25 8 1 1 0 0.0675049 -25 8 2 1 0 0.0675049 -25 8 3 1 0 0.0675049 -25 8 4 1 0 0.0675049 -25 8 5 1 0 0.0675049 -25 8 6 1 0 0.0674438 -25 8 7 1 0 0.0674438 -25 8 8 1 0 0.0673828 -25 8 9 1 0 0.0671997 -25 8 10 1 0 0.0669556 -25 8 11 1 0 0.0664673 -25 8 12 1 0 0.0656738 -25 8 13 1 0 0.0643311 -25 8 14 1 0 0.0626221 -25 8 15 1 0 0.0610962 -25 8 16 1 0 0.291748 -25 8 17 1 0 0.421631 -25 8 18 1 0 0.53125 -25 8 19 1 0 0.634277 -25 8 20 1 0.149658 0.730957 -25 8 21 1 0.277588 0.816895 -25 8 22 1 0.344971 0.887695 -25 8 23 1 0.375488 0.942871 -25 8 24 1 0.383057 0.985352 -25 8 25 1 0.382568 1 -25 8 26 1 0.380371 1 -25 8 27 1 0.375732 1 -25 8 28 0.956543 0.369141 1 -25 8 29 0.884766 0.361084 1 -25 8 30 0.810059 0.352783 1 -25 8 31 0.733887 0.344238 1 -25 9 0 1 0 0.0657349 -25 9 1 1 0 0.0657349 -25 9 2 1 0 0.0657349 -25 9 3 1 0 0.0656738 -25 9 4 1 0 0.0656738 -25 9 5 1 0 0.0656738 -25 9 6 1 0 0.0656738 -25 9 7 1 0 0.0656128 -25 9 8 1 0 0.0655518 -25 9 9 1 0 0.0653687 -25 9 10 1 0 0.0651245 -25 9 11 1 0 0.0646362 -25 9 12 1 0 0.0637817 -25 9 13 1 0 0.0623474 -25 9 14 1 0 0.0606079 -25 9 15 1 0 0.0589905 -25 9 16 1 0 0.291748 -25 9 17 1 0 0.421631 -25 9 18 1 0 0.53125 -25 9 19 1 0 0.634277 -25 9 20 1 0.158569 0.730957 -25 9 21 1 0.281006 0.816895 -25 9 22 1 0.347412 0.887695 -25 9 23 1 0.377686 0.942871 -25 9 24 1 0.38501 0.985352 -25 9 25 1 0.384521 1 -25 9 26 1 0.38208 1 -25 9 27 1 0.377197 1 -25 9 28 0.956543 0.370605 1 -25 9 29 0.884766 0.362305 1 -25 9 30 0.810059 0.35376 1 -25 9 31 0.733887 0.345215 1 -25 10 0 1 0 0.0622253 -25 10 1 1 0 0.0622253 -25 10 2 1 0 0.0621948 -25 10 3 1 0 0.0621948 -25 10 4 1 0 0.0621948 -25 10 5 1 0 0.0621948 -25 10 6 1 0 0.0621643 -25 10 7 1 0 0.0621338 -25 10 8 1 0 0.0620422 -25 10 9 1 0 0.0618591 -25 10 10 1 0 0.061554 -25 10 11 1 0 0.0610352 -25 10 12 1 0 0.0600891 -25 10 13 1 0 0.0585327 -25 10 14 1 0 0.0565796 -25 10 15 1 0 0.0548401 -25 10 16 1 0 0.291504 -25 10 17 1 0 0.421387 -25 10 18 1 0 0.53125 -25 10 19 1 0 0.634277 -25 10 20 1 0.173096 0.730469 -25 10 21 1 0.286865 0.816895 -25 10 22 1 0.351807 0.887695 -25 10 23 1 0.381348 0.942871 -25 10 24 1 0.388428 0.985352 -25 10 25 1 0.387695 1 -25 10 26 1 0.38501 1 -25 10 27 1 0.380127 1 -25 10 28 0.956055 0.373047 1 -25 10 29 0.884766 0.364746 1 -25 10 30 0.810059 0.355957 1 -25 10 31 0.733887 0.347168 1 -25 11 0 1 0 0.0551453 -25 11 1 1 0 0.0551453 -25 11 2 1 0 0.0551453 -25 11 3 1 0 0.0551453 -25 11 4 1 0 0.0551453 -25 11 5 1 0 0.0551147 -25 11 6 1 0 0.0550842 -25 11 7 1 0 0.0550537 -25 11 8 1 0 0.0549316 -25 11 9 1 0 0.0547485 -25 11 10 1 0 0.0543518 -25 11 11 1 0 0.0537109 -25 11 12 1 0 0.0525513 -25 11 13 1 0 0.0505676 -25 11 14 1 0 0.0480652 -25 11 15 1 0 0.045929 -25 11 16 1 0 0.291504 -25 11 17 1 0 0.421143 -25 11 18 1 0 0.53125 -25 11 19 1 0 0.633789 -25 11 20 1 0.194702 0.730469 -25 11 21 1 0.296875 0.816406 -25 11 22 1 0.359131 0.887695 -25 11 23 1 0.387939 0.942871 -25 11 24 1 0.394531 0.985352 -25 11 25 1 0.393311 1 -25 11 26 1 0.390381 1 -25 11 27 1 0.38501 1 -25 11 28 0.956055 0.377441 1 -25 11 29 0.884277 0.368652 1 -25 11 30 0.80957 0.359375 1 -25 11 31 0.733398 0.350098 1 -25 12 0 1 0 0.0375671 -25 12 1 1 0 0.0375671 -25 12 2 1 0 0.0375671 -25 12 3 1 0 0.0375671 -25 12 4 1 0 0.0375366 -25 12 5 1 0 0.0375061 -25 12 6 1 0 0.0374756 -25 12 7 1 0 0.037384 -25 12 8 1 0 0.0371704 -25 12 9 1 0 0.0368042 -25 12 10 1 0 0.0361023 -25 12 11 1 0 0.03479 -25 12 12 1 0 0.0323792 -25 12 13 1 0 0.0276489 -25 12 14 1 0 0.0195923 -25 12 15 1 0.0159607 0 -25 12 16 1 0 0.29126 -25 12 17 1 0 0.420654 -25 12 18 1 0 0.53125 -25 12 19 1 0.100952 0.633301 -25 12 20 1 0.224609 0.72998 -25 12 21 1 0.312988 0.816406 -25 12 22 1 0.371094 0.887695 -25 12 23 1 0.398438 0.942383 -25 12 24 1 0.404297 0.985352 -25 12 25 1 0.402832 1 -25 12 26 1 0.39917 1 -25 12 27 1 0.393066 1 -25 12 28 0.955566 0.384766 1 -25 12 29 0.883789 0.375244 1 -25 12 30 0.809082 0.365234 1 -25 12 31 0.73291 0.355469 1 -25 13 0 1 0.154053 0 -25 13 1 1 0.154053 0 -25 13 2 1 0.154053 0 -25 13 3 1 0.154175 0 -25 13 4 1 0.154175 0 -25 13 5 1 0.154175 0 -25 13 6 1 0.154297 0 -25 13 7 1 0.154541 0 -25 13 8 1 0.155029 0 -25 13 9 1 0.155762 0 -25 13 10 1 0.157227 0 -25 13 11 1 0.15979 0 -25 13 12 1 0.164062 0 -25 13 13 1 0.170532 0 -25 13 14 1 0.177734 0 -25 13 15 1 0.181641 0 -25 13 16 1 0.169067 0.291504 -25 13 17 1 0.161377 0.419922 -25 13 18 1 0.166992 0.53125 -25 13 19 1 0.192505 0.632812 -25 13 20 1 0.263184 0.729004 -25 13 21 1 0.33667 0.815918 -25 13 22 1 0.389648 0.887695 -25 13 23 1 0.415039 0.942383 -25 13 24 1 0.419922 0.985352 -25 13 25 1 0.41748 1 -25 13 26 1 0.412842 1 -25 13 27 1 0.405762 1 -25 13 28 0.95459 0.39624 1 -25 13 29 0.882812 0.385742 1 -25 13 30 0.808105 0.374512 1 -25 13 31 0.731934 0.36377 1 -25 14 0 1 0.249146 0 -25 14 1 1 0.249146 0 -25 14 2 1 0.249146 0 -25 14 3 1 0.249146 0 -25 14 4 1 0.249146 0 -25 14 5 1 0.249146 0 -25 14 6 1 0.249268 0 -25 14 7 1 0.24939 0 -25 14 8 1 0.249512 0 -25 14 9 1 0.249878 0 -25 14 10 1 0.250732 0 -25 14 11 1 0.251953 0 -25 14 12 1 0.253906 0 -25 14 13 1 0.257324 0 -25 14 14 1 0.260986 0 -25 14 15 1 0.262451 0 -25 14 16 1 0.255371 0.291992 -25 14 17 1 0.250488 0.419189 -25 14 18 1 0.255859 0.53125 -25 14 19 1 0.265625 0.631836 -25 14 20 1 0.310791 0.728027 -25 14 21 1 0.369873 0.814941 -25 14 22 1 0.416504 0.887207 -25 14 23 1 0.439209 0.942383 -25 14 24 1 0.442871 0.985352 -25 14 25 1 0.439209 1 -25 14 26 1 0.43335 1 -25 14 27 1 0.424561 1 -25 14 28 0.953125 0.413574 1 -25 14 29 0.881348 0.401367 1 -25 14 30 0.806641 0.388672 1 -25 14 31 0.730469 0.376221 1 -25 15 0 1 0.331787 0 -25 15 1 1 0.331787 0 -25 15 2 1 0.331787 0 -25 15 3 1 0.331787 0 -25 15 4 1 0.331787 0 -25 15 5 1 0.331787 0 -25 15 6 1 0.331787 0 -25 15 7 1 0.331787 0 -25 15 8 1 0.332031 0 -25 15 9 1 0.332275 0 -25 15 10 1 0.332764 0 -25 15 11 1 0.333496 0 -25 15 12 1 0.334717 0 -25 15 13 1 0.336914 0 -25 15 14 1 0.3396 0 -25 15 15 1 0.3396 0 -25 15 16 1 0.334961 0.294434 -25 15 17 1 0.330811 0.418701 -25 15 18 1 0.334229 0.530273 -25 15 19 1 0.338623 0.630371 -25 15 20 1 0.367188 0.725586 -25 15 21 1 0.412598 0.813477 -25 15 22 1 0.452637 0.88623 -25 15 23 1 0.472412 0.942383 -25 15 24 1 0.474609 0.985352 -25 15 25 1 0.469727 1 -25 15 26 1 0.461914 1 -25 15 27 1 0.451172 1 -25 15 28 0.950684 0.438232 1 -25 15 29 0.878906 0.423584 1 -25 15 30 0.804688 0.408691 1 -25 15 31 0.728027 0.394287 1 -25 16 0 1 0.414795 0 -25 16 1 1 0.414795 0 -25 16 2 1 0.414795 0 -25 16 3 1 0.414795 0 -25 16 4 1 0.414795 0 -25 16 5 1 0.414795 0 -25 16 6 1 0.414795 0 -25 16 7 1 0.414795 0 -25 16 8 1 0.415039 0 -25 16 9 1 0.415039 0 -25 16 10 1 0.415527 0 -25 16 11 1 0.416016 0 -25 16 12 1 0.416992 0 -25 16 13 1 0.418457 0 -25 16 14 1 0.42041 0 -25 16 15 1 0.419678 0.0967407 -25 16 16 1 0.416748 0.300293 -25 16 17 1 0.413086 0.419922 -25 16 18 1 0.412842 0.52832 -25 16 19 1 0.416504 0.628906 -25 16 20 1 0.431885 0.722656 -25 16 21 1 0.465332 0.811035 -25 16 22 1 0.498535 0.884766 -25 16 23 1 0.515625 0.941406 -25 16 24 1 0.516113 0.985352 -25 16 25 1 0.509277 1 -25 16 26 1 0.499756 1 -25 16 27 1 0.486572 1 -25 16 28 0.947266 0.470703 1 -25 16 29 0.875488 0.453369 1 -25 16 30 0.80127 0.435791 1 -25 16 31 0.725098 0.418457 1 -25 17 0 1 0.499268 0 -25 17 1 1 0.499268 0 -25 17 2 1 0.499268 0 -25 17 3 1 0.499268 0 -25 17 4 1 0.499268 0 -25 17 5 1 0.499268 0 -25 17 6 1 0.499268 0 -25 17 7 1 0.499268 0 -25 17 8 1 0.499268 0 -25 17 9 1 0.499512 0 -25 17 10 1 0.499756 0 -25 17 11 1 0.5 0 -25 17 12 1 0.500977 0 -25 17 13 1 0.501953 0 -25 17 14 1 0.503418 0 -25 17 15 1 0.50293 0.154907 -25 17 16 1 0.500977 0.312744 -25 17 17 1 0.498047 0.424805 -25 17 18 1 0.495361 0.527832 -25 17 19 1 0.498535 0.628418 -25 17 20 1 0.503418 0.71875 -25 17 21 1 0.525391 0.806641 -25 17 22 1 0.552246 0.882324 -25 17 23 1 0.566895 0.94043 -25 17 24 1 0.565918 0.984375 -25 17 25 1 0.557129 1 -25 17 26 1 0.54541 1 -25 17 27 1 0.529297 1 -25 17 28 0.942383 0.510254 1 -25 17 29 0.870605 0.48999 1 -25 17 30 0.796387 0.469238 1 -25 17 31 0.720215 0.448975 1 -25 18 0 1 0.583496 0 -25 18 1 1 0.583496 0 -25 18 2 1 0.583496 0 -25 18 3 1 0.583496 0 -25 18 4 1 0.583496 0 -25 18 5 1 0.583496 0 -25 18 6 1 0.583496 0 -25 18 7 1 0.583496 0 -25 18 8 1 0.583496 0 -25 18 9 1 0.583496 0 -25 18 10 1 0.583984 0 -25 18 11 1 0.583984 0 -25 18 12 1 0.584473 0 -25 18 13 1 0.585449 0 -25 18 14 1 0.586914 0 -25 18 15 1 0.586914 0.208496 -25 18 16 1 0.585938 0.333252 -25 18 17 1 0.583984 0.435303 -25 18 18 1 0.580566 0.53125 -25 18 19 1 0.578125 0.625 -25 18 20 1 0.580078 0.714844 -25 18 21 1 0.590332 0.800781 -25 18 22 1 0.61084 0.878418 -25 18 23 1 0.623535 0.937988 -25 18 24 1 0.621582 0.98291 -25 18 25 1 0.611328 1 -25 18 26 1 0.59668 1 -25 18 27 1 0.578125 1 -25 18 28 0.935547 0.555664 1 -25 18 29 0.86377 0.531738 1 -25 18 30 0.789551 0.507812 1 -25 18 31 0.713867 0.484375 1 -25 19 0 1 0.665527 0.137695 -25 19 1 1 0.665527 0.137695 -25 19 2 1 0.665527 0.137695 -25 19 3 1 0.665527 0.137695 -25 19 4 1 0.665527 0.137695 -25 19 5 1 0.665527 0.137695 -25 19 6 1 0.665527 0.137695 -25 19 7 1 0.665527 0.137695 -25 19 8 1 0.665527 0.137817 -25 19 9 1 0.665527 0.137939 -25 19 10 1 0.665527 0.138184 -25 19 11 1 0.666016 0.138672 -25 19 12 1 0.666504 0.139404 -25 19 13 1 0.666992 0.140625 -25 19 14 1 0.668457 0.142456 -25 19 15 1 0.668945 0.257812 -25 19 16 1 0.668945 0.359375 -25 19 17 1 0.667969 0.451904 -25 19 18 1 0.665039 0.540527 -25 19 19 1 0.660156 0.626465 -25 19 20 1 0.657227 0.711426 -25 19 21 1 0.658691 0.793457 -25 19 22 1 0.671387 0.871582 -25 19 23 1 0.682129 0.934082 -25 19 24 1 0.679688 0.97998 -25 19 25 1 0.66748 1 -25 19 26 1 0.651367 1 -25 19 27 0.992676 0.629395 1 -25 19 28 0.92627 0.604004 1 -25 19 29 0.85498 0.57666 1 -25 19 30 0.78125 0.549316 1 -25 19 31 0.705566 0.522461 1 -25 20 0 1 0.742676 0.232544 -25 20 1 1 0.742676 0.232544 -25 20 2 1 0.742676 0.232544 -25 20 3 1 0.742676 0.232544 -25 20 4 1 0.742676 0.232544 -25 20 5 1 0.742676 0.232544 -25 20 6 1 0.742676 0.232544 -25 20 7 1 0.742676 0.232544 -25 20 8 1 0.742676 0.232544 -25 20 9 1 0.742676 0.232666 -25 20 10 1 0.742676 0.232666 -25 20 11 1 0.743164 0.23291 -25 20 12 1 0.743164 0.233154 -25 20 13 1 0.743652 0.233643 -25 20 14 1 0.744629 0.234375 -25 20 15 1 0.745605 0.298584 -25 20 16 1 0.746582 0.38623 -25 20 17 1 0.746582 0.471191 -25 20 18 1 0.744629 0.554199 -25 20 19 1 0.739746 0.633789 -25 20 20 1 0.73291 0.709961 -25 20 21 1 0.729004 0.788086 -25 20 22 1 0.730957 0.862305 -25 20 23 1 0.739258 0.927734 -25 20 24 1 0.737305 0.976074 -25 20 25 1 0.724121 1 -25 20 26 1 0.706055 1 -25 20 27 0.980469 0.681152 1 -25 20 28 0.914551 0.652344 1 -25 20 29 0.84375 0.62207 1 -25 20 30 0.770996 0.591797 1 -25 20 31 0.695801 0.5625 1 -25 21 0 1 0.814941 0.284912 -25 21 1 1 0.814941 0.284912 -25 21 2 1 0.814941 0.284912 -25 21 3 1 0.814941 0.284912 -25 21 4 1 0.814941 0.284912 -25 21 5 1 0.814941 0.284912 -25 21 6 1 0.814941 0.284912 -25 21 7 1 0.814941 0.284912 -25 21 8 1 0.814941 0.284912 -25 21 9 1 0.814941 0.284912 -25 21 10 1 0.814941 0.284912 -25 21 11 1 0.81543 0.285156 -25 21 12 1 0.81543 0.285156 -25 21 13 1 0.815918 0.2854 -25 21 14 1 0.816406 0.285889 -25 21 15 1 0.817871 0.328125 -25 21 16 1 0.819336 0.407959 -25 21 17 1 0.819824 0.488281 -25 21 18 1 0.818848 0.567871 -25 21 19 1 0.81543 0.644043 -25 21 20 1 0.808105 0.714844 -25 21 21 1 0.79834 0.783203 -25 21 22 1 0.791992 0.852539 -25 21 23 1 0.794922 0.917969 -25 21 24 1 0.793945 0.969727 -25 21 25 1 0.780273 1 -25 21 26 1 0.759766 1 -25 21 27 0.965332 0.732422 1 -25 21 28 0.900391 0.701172 1 -25 21 29 0.830566 0.667969 1 -25 21 30 0.758301 0.634766 1 -25 21 31 0.684082 0.603027 1 -25 22 0 1 0.880859 0.314697 -25 22 1 1 0.880859 0.314697 -25 22 2 1 0.880859 0.314697 -25 22 3 1 0.880859 0.314697 -25 22 4 1 0.880859 0.314697 -25 22 5 1 0.880859 0.314697 -25 22 6 1 0.880859 0.314697 -25 22 7 1 0.880859 0.314697 -25 22 8 1 0.880859 0.314697 -25 22 9 1 0.880859 0.314941 -25 22 10 1 0.880859 0.314941 -25 22 11 1 0.880859 0.314941 -25 22 12 1 0.881348 0.314941 -25 22 13 1 0.881348 0.314941 -25 22 14 1 0.881836 0.315186 -25 22 15 1 0.883301 0.343018 -25 22 16 1 0.884766 0.419678 -25 22 17 1 0.88623 0.498291 -25 22 18 1 0.88623 0.577148 -25 22 19 1 0.883789 0.652832 -25 22 20 1 0.87793 0.722168 -25 22 21 1 0.867676 0.786133 -25 22 22 1 0.85498 0.845703 -25 22 23 1 0.847656 0.905273 -25 22 24 1 0.847168 0.960938 -25 22 25 1 0.833496 1 -25 22 26 1 0.812012 1 -25 22 27 0.946777 0.781738 1 -25 22 28 0.882812 0.748047 1 -25 22 29 0.814453 0.712891 1 -25 22 30 0.744141 0.677734 1 -25 22 31 0.671387 0.644043 1 -25 23 0 1 0.937012 0.327393 -25 23 1 1 0.937012 0.327393 -25 23 2 1 0.937012 0.327393 -25 23 3 1 0.937012 0.327393 -25 23 4 1 0.937012 0.327393 -25 23 5 1 0.937012 0.327393 -25 23 6 1 0.937012 0.327393 -25 23 7 1 0.937012 0.327393 -25 23 8 1 0.9375 0.327393 -25 23 9 1 0.9375 0.327393 -25 23 10 1 0.9375 0.327393 -25 23 11 1 0.9375 0.327393 -25 23 12 1 0.9375 0.327393 -25 23 13 1 0.937988 0.327393 -25 23 14 1 0.938477 0.327637 -25 23 15 1 0.938965 0.343506 -25 23 16 1 0.941406 0.419678 -25 23 17 1 0.943359 0.498535 -25 23 18 1 0.944336 0.577637 -25 23 19 1 0.942871 0.654297 -25 23 20 1 0.938477 0.725098 -25 23 21 1 0.929688 0.789551 -25 23 22 1 0.916504 0.846191 -25 23 23 1 0.901367 0.895996 -25 23 24 1 0.894043 0.94873 -25 23 25 1 0.882324 0.995605 -25 23 26 0.982422 0.858887 1 -25 23 27 0.925293 0.82666 1 -25 23 28 0.863281 0.791504 1 -25 23 29 0.797363 0.755371 1 -25 23 30 0.729004 0.719238 1 -25 23 31 0.657227 0.684082 1 -25 24 0 1 0.984863 0.328369 -25 24 1 1 0.984863 0.328369 -25 24 2 1 0.984863 0.328369 -25 24 3 1 0.984863 0.328369 -25 24 4 1 0.984863 0.328369 -25 24 5 1 0.984863 0.328369 -25 24 6 1 0.984863 0.328369 -25 24 7 1 0.984863 0.328369 -25 24 8 1 0.984863 0.328369 -25 24 9 1 0.984863 0.328369 -25 24 10 1 0.984863 0.328369 -25 24 11 1 0.984863 0.328369 -25 24 12 1 0.985352 0.328369 -25 24 13 1 0.985352 0.328369 -25 24 14 1 0.98584 0.328369 -25 24 15 1 0.986328 0.33252 -25 24 16 1 0.98877 0.4104 -25 24 17 1 0.991211 0.48999 -25 24 18 1 0.993164 0.569824 -25 24 19 1 0.992676 0.647461 -25 24 20 1 0.989258 0.719727 -25 24 21 1 0.982422 0.786133 -25 24 22 1 0.97168 0.845215 -25 24 23 1 0.956543 0.894531 -25 24 24 1 0.938477 0.936523 -25 24 25 1 0.927246 0.984863 -25 24 26 0.956543 0.900879 1 -25 24 27 0.901855 0.867676 1 -25 24 28 0.842773 0.833008 1 -25 24 29 0.780273 0.796875 1 -25 24 30 0.713379 0.760254 1 -25 24 31 0.642578 0.723633 1 -25 25 0 1 1 0.32251 -25 25 1 1 1 0.32251 -25 25 2 1 1 0.32251 -25 25 3 1 1 0.32251 -25 25 4 1 1 0.32251 -25 25 5 1 1 0.32251 -25 25 6 1 1 0.32251 -25 25 7 1 1 0.32251 -25 25 8 1 1 0.32251 -25 25 9 1 1 0.32251 -25 25 10 1 1 0.32251 -25 25 11 1 1 0.32251 -25 25 12 1 1 0.32251 -25 25 13 1 1 0.32251 -25 25 14 1 1 0.32251 -25 25 15 1 1 0.322266 -25 25 16 1 1 0.393311 -25 25 17 1 1 0.474121 -25 25 18 1 1 0.554688 -25 25 19 1 1 0.632324 -25 25 20 1 1 0.705078 -25 25 21 1 1 0.772949 -25 25 22 1 1 0.833984 -25 25 23 1 1 0.88623 -25 25 24 1 0.991699 0.930664 -25 25 25 0.971191 0.971191 0.971191 -25 25 26 0.927246 0.943848 1 -25 25 27 0.876953 0.913086 1 -25 25 28 0.821777 0.878906 1 -25 25 29 0.760742 0.842773 1 -25 25 30 0.694824 0.804688 1 -25 25 31 0.624023 0.766113 1 -25 26 0 1 1 0.313232 -25 26 1 1 1 0.313232 -25 26 2 1 1 0.313232 -25 26 3 1 1 0.313232 -25 26 4 1 1 0.313232 -25 26 5 1 1 0.313232 -25 26 6 1 1 0.313232 -25 26 7 1 1 0.313232 -25 26 8 1 1 0.313232 -25 26 9 1 1 0.313232 -25 26 10 1 1 0.313232 -25 26 11 1 1 0.313232 -25 26 12 1 1 0.313232 -25 26 13 1 1 0.313232 -25 26 14 1 1 0.312988 -25 26 15 1 1 0.312988 -25 26 16 1 1 0.37085 -25 26 17 1 1 0.452637 -25 26 18 1 1 0.533203 -25 26 19 1 1 0.61084 -25 26 20 1 1 0.683105 -25 26 21 1 1 0.750977 -25 26 22 1 1 0.8125 -25 26 23 0.991211 1 0.865234 -25 26 24 0.964355 1 0.910156 -25 26 25 0.933594 1 0.954102 -25 26 26 0.899414 0.996094 0.998047 -25 26 27 0.853027 0.966797 1 -25 26 28 0.797852 0.930664 1 -25 26 29 0.737305 0.892578 1 -25 26 30 0.671875 0.852539 1 -25 26 31 0.600098 0.811523 1 -25 27 0 1 1 0.301758 -25 27 1 1 1 0.301758 -25 27 2 1 1 0.301758 -25 27 3 1 1 0.301758 -25 27 4 1 1 0.301758 -25 27 5 1 1 0.301758 -25 27 6 1 1 0.301758 -25 27 7 1 1 0.301758 -25 27 8 1 1 0.301758 -25 27 9 1 1 0.301758 -25 27 10 1 1 0.301758 -25 27 11 1 1 0.301758 -25 27 12 1 1 0.301758 -25 27 13 1 1 0.301758 -25 27 14 1 1 0.301758 -25 27 15 1 1 0.301758 -25 27 16 1 1 0.343506 -25 27 17 1 1 0.427002 -25 27 18 1 1 0.507324 -25 27 19 0.996094 1 0.584473 -25 27 20 0.987305 1 0.65625 -25 27 21 0.974609 1 0.723633 -25 27 22 0.95752 1 0.785156 -25 27 23 0.937012 1 0.838867 -25 27 24 0.914062 1 0.885742 -25 27 25 0.887695 1 0.932617 -25 27 26 0.855469 1 0.978027 -25 27 27 0.816406 1 1 -25 27 28 0.76709 0.984863 1 -25 27 29 0.708984 0.946777 1 -25 27 30 0.643555 0.905273 1 -25 27 31 0.570801 0.861816 1 -25 28 0 0.936035 1 0.288818 -25 28 1 0.936035 1 0.288818 -25 28 2 0.936035 1 0.288818 -25 28 3 0.936035 1 0.288818 -25 28 4 0.936035 1 0.288818 -25 28 5 0.936035 1 0.288818 -25 28 6 0.936035 1 0.288818 -25 28 7 0.936035 1 0.288818 -25 28 8 0.936035 1 0.288818 -25 28 9 0.936035 1 0.288818 -25 28 10 0.936035 1 0.288818 -25 28 11 0.936035 1 0.288818 -25 28 12 0.936035 1 0.288818 -25 28 13 0.936035 1 0.288818 -25 28 14 0.936035 1 0.288818 -25 28 15 0.936035 1 0.288818 -25 28 16 0.935547 1 0.312012 -25 28 17 0.93457 1 0.397705 -25 28 18 0.931641 1 0.478271 -25 28 19 0.926758 1 0.554199 -25 28 20 0.918945 1 0.625488 -25 28 21 0.907715 1 0.692383 -25 28 22 0.893066 1 0.754395 -25 28 23 0.875977 1 0.809082 -25 28 24 0.855957 1 0.85791 -25 28 25 0.832031 1 0.906738 -25 28 26 0.802734 1 0.953613 -25 28 27 0.765625 1 0.99707 -25 28 28 0.721191 1 1 -25 28 29 0.666992 0.99707 1 -25 28 30 0.603516 0.957031 1 -25 28 31 0.529785 0.913086 1 -25 29 0 0.85791 1 0.274902 -25 29 1 0.85791 1 0.274902 -25 29 2 0.85791 1 0.274902 -25 29 3 0.85791 1 0.274902 -25 29 4 0.85791 1 0.274902 -25 29 5 0.85791 1 0.274902 -25 29 6 0.85791 1 0.274902 -25 29 7 0.85791 1 0.274902 -25 29 8 0.85791 1 0.274902 -25 29 9 0.85791 1 0.274902 -25 29 10 0.85791 1 0.274902 -25 29 11 0.85791 1 0.274902 -25 29 12 0.85791 1 0.274902 -25 29 13 0.85791 1 0.274902 -25 29 14 0.85791 1 0.274658 -25 29 15 0.85791 1 0.274658 -25 29 16 0.85791 1 0.275635 -25 29 17 0.856445 1 0.36499 -25 29 18 0.853516 1 0.446045 -25 29 19 0.849121 1 0.521484 -25 29 20 0.842285 1 0.591797 -25 29 21 0.83252 1 0.658691 -25 29 22 0.819824 1 0.720215 -25 29 23 0.804688 1 0.775879 -25 29 24 0.787109 1 0.825684 -25 29 25 0.765625 1 0.875488 -25 29 26 0.737793 1 0.923828 -25 29 27 0.703125 1 0.969727 -25 29 28 0.660645 1 1 -25 29 29 0.609375 1 1 -25 29 30 0.547363 1 1 -25 29 31 0.47168 0.963867 1 -25 30 0 0.772461 1 0.260254 -25 30 1 0.772461 1 0.260254 -25 30 2 0.772461 1 0.260254 -25 30 3 0.772461 1 0.260254 -25 30 4 0.772461 1 0.260254 -25 30 5 0.772461 1 0.260254 -25 30 6 0.772461 1 0.260254 -25 30 7 0.772461 1 0.260254 -25 30 8 0.772461 1 0.260254 -25 30 9 0.772461 1 0.260254 -25 30 10 0.772461 1 0.260254 -25 30 11 0.772461 1 0.260254 -25 30 12 0.772461 1 0.260254 -25 30 13 0.772461 1 0.260254 -25 30 14 0.772461 1 0.260254 -25 30 15 0.772461 1 0.260254 -25 30 16 0.772461 1 0.260254 -25 30 17 0.770996 1 0.329346 -25 30 18 0.767578 1 0.411621 -25 30 19 0.763184 1 0.486816 -25 30 20 0.756348 1 0.556152 -25 30 21 0.747559 1 0.62207 -25 30 22 0.73584 1 0.683594 -25 30 23 0.722168 1 0.73877 -25 30 24 0.706055 1 0.789062 -25 30 25 0.685547 1 0.839355 -25 30 26 0.65918 1 0.88916 -25 30 27 0.625977 1 0.937012 -25 30 28 0.584473 1 0.981934 -25 30 29 0.533203 1 1 -25 30 30 0.468994 1 1 -25 30 31 0.384766 1 1 -25 31 0 0.676758 1 0.245483 -25 31 1 0.676758 1 0.245483 -25 31 2 0.676758 1 0.245483 -25 31 3 0.676758 1 0.245483 -25 31 4 0.676758 1 0.245483 -25 31 5 0.676758 1 0.245483 -25 31 6 0.676758 1 0.245483 -25 31 7 0.676758 1 0.245483 -25 31 8 0.676758 1 0.245483 -25 31 9 0.676758 1 0.245483 -25 31 10 0.676758 1 0.245483 -25 31 11 0.676758 1 0.245483 -25 31 12 0.676758 1 0.245483 -25 31 13 0.676758 1 0.245483 -25 31 14 0.676758 1 0.245483 -25 31 15 0.677246 1 0.245605 -25 31 16 0.677246 1 0.245605 -25 31 17 0.675781 1 0.290039 -25 31 18 0.672363 1 0.375244 -25 31 19 0.666992 1 0.450439 -25 31 20 0.659668 1 0.519043 -25 31 21 0.650391 1 0.583496 -25 31 22 0.638672 1 0.644043 -25 31 23 0.625 1 0.69873 -25 31 24 0.608887 1 0.749023 -25 31 25 0.588379 1 0.799316 -25 31 26 0.562012 1 0.850098 -25 31 27 0.527832 1 0.899902 -25 31 28 0.484131 1 0.947266 -25 31 29 0.426758 1 0.991211 -25 31 30 0.3479 1 1 -25 31 31 0.214233 1 1 -26 0 0 1 0 0.071228 -26 0 1 1 0 0.071228 -26 0 2 1 0 0.071228 -26 0 3 1 0 0.071228 -26 0 4 1 0 0.071228 -26 0 5 1 0 0.071228 -26 0 6 1 0 0.071228 -26 0 7 1 0 0.071167 -26 0 8 1 0 0.071106 -26 0 9 1 0 0.0709839 -26 0 10 1 0 0.0708008 -26 0 11 1 0 0.0703735 -26 0 12 1 0 0.0697021 -26 0 13 1 0 0.0686035 -26 0 14 1 0 0.0667725 -26 0 15 1 0 0.0656738 -26 0 16 1 0 0.234131 -26 0 17 1 0 0.378662 -26 0 18 1 0 0.493896 -26 0 19 1 0 0.594238 -26 0 20 1 0 0.689453 -26 0 21 1 0.19519 0.776855 -26 0 22 1 0.298096 0.852539 -26 0 23 1 0.354004 0.912598 -26 0 24 1 0.380127 0.959961 -26 0 25 1 0.386963 1 -26 0 26 1 0.38623 1 -26 0 27 1 0.383301 1 -26 0 28 1 0.378174 1 -26 0 29 0.96582 0.371094 1 -26 0 30 0.893555 0.363281 1 -26 0 31 0.817871 0.354736 1 -26 1 0 1 0 0.071228 -26 1 1 1 0 0.071228 -26 1 2 1 0 0.071228 -26 1 3 1 0 0.071228 -26 1 4 1 0 0.071228 -26 1 5 1 0 0.071228 -26 1 6 1 0 0.071228 -26 1 7 1 0 0.071167 -26 1 8 1 0 0.071106 -26 1 9 1 0 0.0709839 -26 1 10 1 0 0.0708008 -26 1 11 1 0 0.0703735 -26 1 12 1 0 0.0697021 -26 1 13 1 0 0.0686035 -26 1 14 1 0 0.0667725 -26 1 15 1 0 0.0656738 -26 1 16 1 0 0.234131 -26 1 17 1 0 0.378662 -26 1 18 1 0 0.493896 -26 1 19 1 0 0.594238 -26 1 20 1 0 0.689453 -26 1 21 1 0.19519 0.776855 -26 1 22 1 0.298096 0.852539 -26 1 23 1 0.354004 0.912598 -26 1 24 1 0.380127 0.959961 -26 1 25 1 0.386963 1 -26 1 26 1 0.38623 1 -26 1 27 1 0.383301 1 -26 1 28 1 0.378174 1 -26 1 29 0.96582 0.371338 1 -26 1 30 0.893555 0.363281 1 -26 1 31 0.817871 0.354736 1 -26 2 0 1 0 0.071228 -26 2 1 1 0 0.071228 -26 2 2 1 0 0.071228 -26 2 3 1 0 0.071228 -26 2 4 1 0 0.071228 -26 2 5 1 0 0.071228 -26 2 6 1 0 0.071167 -26 2 7 1 0 0.071167 -26 2 8 1 0 0.071106 -26 2 9 1 0 0.0709839 -26 2 10 1 0 0.0707397 -26 2 11 1 0 0.0703735 -26 2 12 1 0 0.0697021 -26 2 13 1 0 0.0686035 -26 2 14 1 0 0.0667725 -26 2 15 1 0 0.0656738 -26 2 16 1 0 0.234131 -26 2 17 1 0 0.378662 -26 2 18 1 0 0.493896 -26 2 19 1 0 0.594238 -26 2 20 1 0 0.689453 -26 2 21 1 0.195312 0.776855 -26 2 22 1 0.298096 0.852539 -26 2 23 1 0.354004 0.912598 -26 2 24 1 0.380127 0.959961 -26 2 25 1 0.387207 1 -26 2 26 1 0.38623 1 -26 2 27 1 0.383301 1 -26 2 28 1 0.378174 1 -26 2 29 0.96582 0.371338 1 -26 2 30 0.893555 0.363281 1 -26 2 31 0.817871 0.354736 1 -26 3 0 1 0 0.071167 -26 3 1 1 0 0.071167 -26 3 2 1 0 0.071167 -26 3 3 1 0 0.071167 -26 3 4 1 0 0.071167 -26 3 5 1 0 0.071167 -26 3 6 1 0 0.071167 -26 3 7 1 0 0.071106 -26 3 8 1 0 0.0710449 -26 3 9 1 0 0.0709229 -26 3 10 1 0 0.0707397 -26 3 11 1 0 0.0703125 -26 3 12 1 0 0.0697021 -26 3 13 1 0 0.0685425 -26 3 14 1 0 0.0667114 -26 3 15 1 0 0.0656738 -26 3 16 1 0 0.234131 -26 3 17 1 0 0.378662 -26 3 18 1 0 0.493896 -26 3 19 1 0 0.594238 -26 3 20 1 0 0.689453 -26 3 21 1 0.195435 0.776855 -26 3 22 1 0.298096 0.852539 -26 3 23 1 0.354004 0.912598 -26 3 24 1 0.380127 0.959961 -26 3 25 1 0.387207 1 -26 3 26 1 0.38623 1 -26 3 27 1 0.383301 1 -26 3 28 1 0.378174 1 -26 3 29 0.96582 0.371338 1 -26 3 30 0.893555 0.363281 1 -26 3 31 0.817871 0.354736 1 -26 4 0 1 0 0.071106 -26 4 1 1 0 0.071106 -26 4 2 1 0 0.071106 -26 4 3 1 0 0.071106 -26 4 4 1 0 0.071106 -26 4 5 1 0 0.071106 -26 4 6 1 0 0.071106 -26 4 7 1 0 0.0710449 -26 4 8 1 0 0.0709839 -26 4 9 1 0 0.0708618 -26 4 10 1 0 0.0706787 -26 4 11 1 0 0.0703125 -26 4 12 1 0 0.0696411 -26 4 13 1 0 0.0684814 -26 4 14 1 0 0.0666504 -26 4 15 1 0 0.0656128 -26 4 16 1 0 0.234131 -26 4 17 1 0 0.378662 -26 4 18 1 0 0.493896 -26 4 19 1 0 0.594238 -26 4 20 1 0 0.689453 -26 4 21 1 0.195679 0.776855 -26 4 22 1 0.29834 0.852539 -26 4 23 1 0.354004 0.912598 -26 4 24 1 0.380127 0.959961 -26 4 25 1 0.387207 1 -26 4 26 1 0.38623 1 -26 4 27 1 0.383301 1 -26 4 28 1 0.378174 1 -26 4 29 0.96582 0.371338 1 -26 4 30 0.893555 0.363281 1 -26 4 31 0.817871 0.354736 1 -26 5 0 1 0 0.0710449 -26 5 1 1 0 0.0710449 -26 5 2 1 0 0.0710449 -26 5 3 1 0 0.0710449 -26 5 4 1 0 0.0710449 -26 5 5 1 0 0.0709839 -26 5 6 1 0 0.0709839 -26 5 7 1 0 0.0709839 -26 5 8 1 0 0.0709229 -26 5 9 1 0 0.0708008 -26 5 10 1 0 0.0705566 -26 5 11 1 0 0.0701904 -26 5 12 1 0 0.069519 -26 5 13 1 0 0.0684204 -26 5 14 1 0 0.0665283 -26 5 15 1 0 0.0654907 -26 5 16 1 0 0.234131 -26 5 17 1 0 0.378662 -26 5 18 1 0 0.493896 -26 5 19 1 0 0.594238 -26 5 20 1 0 0.689453 -26 5 21 1 0.196045 0.776855 -26 5 22 1 0.29834 0.852539 -26 5 23 1 0.354248 0.912598 -26 5 24 1 0.380371 0.959961 -26 5 25 1 0.387207 1 -26 5 26 1 0.386475 1 -26 5 27 1 0.383545 1 -26 5 28 1 0.378418 1 -26 5 29 0.96582 0.371338 1 -26 5 30 0.893555 0.363281 1 -26 5 31 0.817871 0.35498 1 -26 6 0 1 0 0.0708008 -26 6 1 1 0 0.0708008 -26 6 2 1 0 0.0708008 -26 6 3 1 0 0.0708008 -26 6 4 1 0 0.0708008 -26 6 5 1 0 0.0708008 -26 6 6 1 0 0.0708008 -26 6 7 1 0 0.0707397 -26 6 8 1 0 0.0706787 -26 6 9 1 0 0.0705566 -26 6 10 1 0 0.0703735 -26 6 11 1 0 0.0699463 -26 6 12 1 0 0.0692749 -26 6 13 1 0 0.0681763 -26 6 14 1 0 0.0663452 -26 6 15 1 0 0.0652466 -26 6 16 1 0 0.234131 -26 6 17 1 0 0.378662 -26 6 18 1 0 0.493896 -26 6 19 1 0 0.594238 -26 6 20 1 0 0.689453 -26 6 21 1 0.196777 0.776855 -26 6 22 1 0.298828 0.852539 -26 6 23 1 0.354492 0.912598 -26 6 24 1 0.380615 0.959961 -26 6 25 1 0.387451 1 -26 6 26 1 0.386719 1 -26 6 27 1 0.383789 1 -26 6 28 1 0.378662 1 -26 6 29 0.96582 0.371582 1 -26 6 30 0.893555 0.363525 1 -26 6 31 0.817871 0.35498 1 -26 7 0 1 0 0.0704346 -26 7 1 1 0 0.0704346 -26 7 2 1 0 0.0704346 -26 7 3 1 0 0.0704346 -26 7 4 1 0 0.0704346 -26 7 5 1 0 0.0704346 -26 7 6 1 0 0.0703735 -26 7 7 1 0 0.0703735 -26 7 8 1 0 0.0703125 -26 7 9 1 0 0.0701904 -26 7 10 1 0 0.0699463 -26 7 11 1 0 0.0695801 -26 7 12 1 0 0.0689087 -26 7 13 1 0 0.067749 -26 7 14 1 0 0.065918 -26 7 15 1 0 0.0648193 -26 7 16 1 0 0.234131 -26 7 17 1 0 0.378662 -26 7 18 1 0 0.493896 -26 7 19 1 0 0.594238 -26 7 20 1 0 0.689453 -26 7 21 1 0.198242 0.776855 -26 7 22 1 0.299561 0.852539 -26 7 23 1 0.35498 0.912598 -26 7 24 1 0.381104 0.959961 -26 7 25 1 0.387939 1 -26 7 26 1 0.386963 1 -26 7 27 1 0.384033 1 -26 7 28 1 0.378906 1 -26 7 29 0.96582 0.371826 1 -26 7 30 0.893555 0.36377 1 -26 7 31 0.817871 0.355225 1 -26 8 0 1 0 0.0696411 -26 8 1 1 0 0.0696411 -26 8 2 1 0 0.0696411 -26 8 3 1 0 0.0696411 -26 8 4 1 0 0.0696411 -26 8 5 1 0 0.0696411 -26 8 6 1 0 0.0696411 -26 8 7 1 0 0.0695801 -26 8 8 1 0 0.069519 -26 8 9 1 0 0.069397 -26 8 10 1 0 0.0691528 -26 8 11 1 0 0.0687866 -26 8 12 1 0 0.0681152 -26 8 13 1 0 0.0669556 -26 8 14 1 0 0.0650024 -26 8 15 1 0 0.0639038 -26 8 16 1 0 0.234131 -26 8 17 1 0 0.378662 -26 8 18 1 0 0.493896 -26 8 19 1 0 0.594238 -26 8 20 1 0 0.689453 -26 8 21 1 0.200928 0.776855 -26 8 22 1 0.301025 0.852539 -26 8 23 1 0.356201 0.912598 -26 8 24 1 0.38208 0.959961 -26 8 25 1 0.388916 1 -26 8 26 1 0.387939 1 -26 8 27 1 0.38501 1 -26 8 28 1 0.379639 1 -26 8 29 0.96582 0.372559 1 -26 8 30 0.893555 0.364258 1 -26 8 31 0.817871 0.355713 1 -26 9 0 1 0 0.0681152 -26 9 1 1 0 0.0681152 -26 9 2 1 0 0.0681152 -26 9 3 1 0 0.0681152 -26 9 4 1 0 0.0681152 -26 9 5 1 0 0.0681152 -26 9 6 1 0 0.0680542 -26 9 7 1 0 0.0680542 -26 9 8 1 0 0.0679932 -26 9 9 1 0 0.0678711 -26 9 10 1 0 0.067627 -26 9 11 1 0 0.0671997 -26 9 12 1 0 0.0664673 -26 9 13 1 0 0.0653076 -26 9 14 1 0 0.0632935 -26 9 15 1 0 0.0621338 -26 9 16 1 0 0.234131 -26 9 17 1 0 0.378662 -26 9 18 1 0 0.493896 -26 9 19 1 0 0.594238 -26 9 20 1 0 0.688965 -26 9 21 1 0.206055 0.776855 -26 9 22 1 0.303711 0.852051 -26 9 23 1 0.358154 0.912598 -26 9 24 1 0.383789 0.959961 -26 9 25 1 0.390625 1 -26 9 26 1 0.389404 1 -26 9 27 1 0.386475 1 -26 9 28 1 0.380859 1 -26 9 29 0.96582 0.373779 1 -26 9 30 0.893066 0.365479 1 -26 9 31 0.817871 0.356689 1 -26 10 0 1 0 0.0651855 -26 10 1 1 0 0.0651855 -26 10 2 1 0 0.0651855 -26 10 3 1 0 0.0651855 -26 10 4 1 0 0.0651245 -26 10 5 1 0 0.0651245 -26 10 6 1 0 0.0651245 -26 10 7 1 0 0.0650635 -26 10 8 1 0 0.0650024 -26 10 9 1 0 0.0648804 -26 10 10 1 0 0.0646362 -26 10 11 1 0 0.064209 -26 10 12 1 0 0.0634155 -26 10 13 1 0 0.0621033 -26 10 14 1 0 0.0599365 -26 10 15 1 0 0.0587158 -26 10 16 1 0 0.234131 -26 10 17 1 0 0.378418 -26 10 18 1 0 0.493896 -26 10 19 1 0 0.594238 -26 10 20 1 0 0.688965 -26 10 21 1 0.214966 0.776855 -26 10 22 1 0.30835 0.852051 -26 10 23 1 0.361816 0.912598 -26 10 24 1 0.386963 0.959961 -26 10 25 1 0.393555 1 -26 10 26 1 0.392334 1 -26 10 27 1 0.388916 1 -26 10 28 1 0.383301 1 -26 10 29 0.96582 0.375977 1 -26 10 30 0.893066 0.367432 1 -26 10 31 0.817383 0.358398 1 -26 11 0 1 0 0.0593872 -26 11 1 1 0 0.0593872 -26 11 2 1 0 0.0593872 -26 11 3 1 0 0.0593872 -26 11 4 1 0 0.0593567 -26 11 5 1 0 0.0593567 -26 11 6 1 0 0.0593262 -26 11 7 1 0 0.0592957 -26 11 8 1 0 0.0592041 -26 11 9 1 0 0.0590515 -26 11 10 1 0 0.0587463 -26 11 11 1 0 0.0582275 -26 11 12 1 0 0.057312 -26 11 13 1 0 0.0557861 -26 11 14 1 0 0.0531921 -26 11 15 1 0 0.0517578 -26 11 16 1 0 0.234009 -26 11 17 1 0 0.378174 -26 11 18 1 0 0.494141 -26 11 19 1 0 0.59375 -26 11 20 1 0 0.688965 -26 11 21 1 0.229126 0.776367 -26 11 22 1 0.316406 0.852051 -26 11 23 1 0.368164 0.912598 -26 11 24 1 0.392578 0.959961 -26 11 25 1 0.398926 1 -26 11 26 1 0.397217 1 -26 11 27 1 0.393555 1 -26 11 28 1 0.387451 1 -26 11 29 0.965332 0.379639 1 -26 11 30 0.893066 0.37085 1 -26 11 31 0.817383 0.361572 1 -26 12 0 1 0 0.0465393 -26 12 1 1 0 0.0465393 -26 12 2 1 0 0.0465393 -26 12 3 1 0 0.0465393 -26 12 4 1 0 0.0465393 -26 12 5 1 0 0.0465088 -26 12 6 1 0 0.0464783 -26 12 7 1 0 0.0464172 -26 12 8 1 0 0.0462952 -26 12 9 1 0 0.046051 -26 12 10 1 0 0.0456238 -26 12 11 1 0 0.0448303 -26 12 12 1 0 0.0434265 -26 12 13 1 0 0.0409546 -26 12 14 1 0 0.036438 -26 12 15 1 0 0.0339355 -26 12 16 1 0 0.234131 -26 12 17 1 0 0.37793 -26 12 18 1 0 0.494385 -26 12 19 1 0 0.59375 -26 12 20 1 0.133301 0.688477 -26 12 21 1 0.250732 0.776367 -26 12 22 1 0.32959 0.852051 -26 12 23 1 0.378418 0.912109 -26 12 24 1 0.401855 0.959961 -26 12 25 1 0.407471 1 -26 12 26 1 0.405273 1 -26 12 27 1 0.401123 1 -26 12 28 1 0.394531 1 -26 12 29 0.964844 0.385986 1 -26 12 30 0.892578 0.376465 1 -26 12 31 0.816895 0.366455 1 -26 13 0 1 0.112061 0 -26 13 1 1 0.112061 0 -26 13 2 1 0.112061 0 -26 13 3 1 0.112061 0 -26 13 4 1 0.112122 0 -26 13 5 1 0.112244 0 -26 13 6 1 0.112366 0 -26 13 7 1 0.112732 0 -26 13 8 1 0.113342 0 -26 13 9 1 0.114563 0 -26 13 10 1 0.11676 0 -26 13 11 1 0.120361 0 -26 13 12 1 0.126221 0 -26 13 13 1 0.13501 0 -26 13 14 1 0.147217 0 -26 13 15 1 0.151978 0 -26 13 16 1 0.144897 0.234375 -26 13 17 1 0.127197 0.377686 -26 13 18 1 0.136475 0.493652 -26 13 19 1 0.137451 0.593262 -26 13 20 1 0.199829 0.687988 -26 13 21 1 0.280762 0.775879 -26 13 22 1 0.349365 0.851562 -26 13 23 1 0.394531 0.912109 -26 13 24 1 0.41626 0.959961 -26 13 25 1 0.421143 1 -26 13 26 1 0.418213 1 -26 13 27 1 0.413086 1 -26 13 28 1 0.405518 1 -26 13 29 0.964355 0.395996 1 -26 13 30 0.891602 0.385498 1 -26 13 31 0.815918 0.374756 1 -26 14 0 1 0.224854 0 -26 14 1 1 0.224854 0 -26 14 2 1 0.224854 0 -26 14 3 1 0.224854 0 -26 14 4 1 0.224854 0 -26 14 5 1 0.224854 0 -26 14 6 1 0.224976 0 -26 14 7 1 0.225098 0 -26 14 8 1 0.22522 0 -26 14 9 1 0.225708 0 -26 14 10 1 0.22644 0 -26 14 11 1 0.227661 0 -26 14 12 1 0.229858 0 -26 14 13 1 0.233398 0 -26 14 14 1 0.238892 0 -26 14 15 1 0.240601 0 -26 14 16 1 0.236694 0.235474 -26 14 17 1 0.228882 0.377197 -26 14 18 1 0.230835 0.492432 -26 14 19 1 0.233398 0.592773 -26 14 20 1 0.262939 0.687012 -26 14 21 1 0.320068 0.774902 -26 14 22 1 0.377686 0.851074 -26 14 23 1 0.417969 0.912109 -26 14 24 1 0.437988 0.959961 -26 14 25 1 0.441406 1 -26 14 26 1 0.4375 1 -26 14 27 1 0.431152 1 -26 14 28 1 0.422119 1 -26 14 29 0.963379 0.411133 1 -26 14 30 0.890625 0.39917 1 -26 14 31 0.814941 0.386963 1 -26 15 0 1 0.309326 0 -26 15 1 1 0.309326 0 -26 15 2 1 0.309326 0 -26 15 3 1 0.309326 0 -26 15 4 1 0.309326 0 -26 15 5 1 0.30957 0 -26 15 6 1 0.30957 0 -26 15 7 1 0.30957 0 -26 15 8 1 0.30957 0 -26 15 9 1 0.309814 0 -26 15 10 1 0.310303 0 -26 15 11 1 0.311279 0 -26 15 12 1 0.3125 0 -26 15 13 1 0.314697 0 -26 15 14 1 0.318115 0 -26 15 15 1 0.318848 0 -26 15 16 1 0.315918 0.238403 -26 15 17 1 0.311035 0.377441 -26 15 18 1 0.310303 0.490967 -26 15 19 1 0.313965 0.592285 -26 15 20 1 0.329102 0.685059 -26 15 21 1 0.368652 0.773438 -26 15 22 1 0.415283 0.850098 -26 15 23 1 0.450439 0.911621 -26 15 24 1 0.467773 0.959473 -26 15 25 1 0.469971 1 -26 15 26 1 0.464355 1 -26 15 27 1 0.456543 1 -26 15 28 1 0.445801 1 -26 15 29 0.961426 0.432861 1 -26 15 30 0.888672 0.418945 1 -26 15 31 0.812988 0.404541 1 -26 16 0 1 0.391602 0 -26 16 1 1 0.391602 0 -26 16 2 1 0.391602 0 -26 16 3 1 0.391602 0 -26 16 4 1 0.391602 0 -26 16 5 1 0.391602 0 -26 16 6 1 0.391602 0 -26 16 7 1 0.391846 0 -26 16 8 1 0.391846 0 -26 16 9 1 0.39209 0 -26 16 10 1 0.392334 0 -26 16 11 1 0.392822 0 -26 16 12 1 0.393799 0 -26 16 13 1 0.395264 0 -26 16 14 1 0.397705 0 -26 16 15 1 0.398193 0 -26 16 16 1 0.395752 0.245483 -26 16 17 1 0.392334 0.37915 -26 16 18 1 0.390381 0.489746 -26 16 19 1 0.394775 0.592285 -26 16 20 1 0.400391 0.683105 -26 16 21 1 0.426025 0.770996 -26 16 22 1 0.462402 0.848633 -26 16 23 1 0.492188 0.910645 -26 16 24 1 0.506836 0.959473 -26 16 25 1 0.507324 1 -26 16 26 1 0.500488 1 -26 16 27 1 0.490479 1 -26 16 28 1 0.477295 1 -26 16 29 0.958496 0.461914 1 -26 16 30 0.88623 0.445312 1 -26 16 31 0.810547 0.428711 1 -26 17 0 1 0.474121 0 -26 17 1 1 0.474121 0 -26 17 2 1 0.474121 0 -26 17 3 1 0.474121 0 -26 17 4 1 0.474121 0 -26 17 5 1 0.474121 0 -26 17 6 1 0.474121 0 -26 17 7 1 0.474121 0 -26 17 8 1 0.474121 0 -26 17 9 1 0.474365 0 -26 17 10 1 0.474609 0 -26 17 11 1 0.475098 0 -26 17 12 1 0.475586 0 -26 17 13 1 0.476807 0 -26 17 14 1 0.478516 0 -26 17 15 1 0.47876 0 -26 17 16 1 0.477295 0.259277 -26 17 17 1 0.474854 0.384033 -26 17 18 1 0.472168 0.490234 -26 17 19 1 0.473145 0.589844 -26 17 20 1 0.476074 0.680664 -26 17 21 1 0.490479 0.767578 -26 17 22 1 0.51709 0.845703 -26 17 23 1 0.541504 0.90918 -26 17 24 1 0.554199 0.958496 -26 17 25 1 0.552734 1 -26 17 26 1 0.543945 1 -26 17 27 1 0.531738 1 -26 17 28 1 0.516113 1 -26 17 29 0.95459 0.498047 1 -26 17 30 0.881836 0.478516 1 -26 17 31 0.806641 0.45874 1 -26 18 0 1 0.555664 0 -26 18 1 1 0.555664 0 -26 18 2 1 0.555664 0 -26 18 3 1 0.556152 0 -26 18 4 1 0.556152 0 -26 18 5 1 0.556152 0 -26 18 6 1 0.556152 0 -26 18 7 1 0.556152 0 -26 18 8 1 0.556152 0 -26 18 9 1 0.556152 0 -26 18 10 1 0.556152 0 -26 18 11 1 0.556641 0 -26 18 12 1 0.557129 0 -26 18 13 1 0.558105 0 -26 18 14 1 0.55957 0 -26 18 15 1 0.55957 0.0662231 -26 18 16 1 0.559082 0.281494 -26 18 17 1 0.557617 0.394287 -26 18 18 1 0.555176 0.494141 -26 18 19 1 0.553223 0.588379 -26 18 20 1 0.555176 0.679199 -26 18 21 1 0.55957 0.762695 -26 18 22 1 0.57666 0.841309 -26 18 23 1 0.59668 0.90625 -26 18 24 1 0.606934 0.956543 -26 18 25 1 0.604492 1 -26 18 26 1 0.59375 1 -26 18 27 1 0.579102 1 -26 18 28 1 0.560547 1 -26 18 29 0.949219 0.539551 1 -26 18 30 0.876465 0.516602 1 -26 18 31 0.80127 0.493896 1 -26 19 0 1 0.635254 0 -26 19 1 1 0.635254 0 -26 19 2 1 0.635254 0 -26 19 3 1 0.635254 0 -26 19 4 1 0.635254 0 -26 19 5 1 0.635254 0 -26 19 6 1 0.635254 0 -26 19 7 1 0.635254 0 -26 19 8 1 0.635254 0 -26 19 9 1 0.635254 0 -26 19 10 1 0.635254 0 -26 19 11 1 0.635742 0 -26 19 12 1 0.63623 0 -26 19 13 1 0.636719 0 -26 19 14 1 0.637695 0 -26 19 15 1 0.638672 0.18042 -26 19 16 1 0.63916 0.310303 -26 19 17 1 0.638672 0.4104 -26 19 18 1 0.636719 0.50293 -26 19 19 1 0.633301 0.59082 -26 19 20 1 0.630859 0.675781 -26 19 21 1 0.631348 0.757812 -26 19 22 1 0.638672 0.834961 -26 19 23 1 0.65332 0.901367 -26 19 24 1 0.662109 0.953613 -26 19 25 1 0.658691 0.998047 -26 19 26 1 0.645996 1 -26 19 27 1 0.629395 1 -26 19 28 1 0.608398 1 -26 19 29 0.941895 0.583984 1 -26 19 30 0.869629 0.558105 1 -26 19 31 0.794434 0.531738 1 -26 20 0 1 0.709961 0.18457 -26 20 1 1 0.709961 0.18457 -26 20 2 1 0.709961 0.18457 -26 20 3 1 0.709961 0.18457 -26 20 4 1 0.709961 0.18457 -26 20 5 1 0.709961 0.18457 -26 20 6 1 0.709961 0.18457 -26 20 7 1 0.709961 0.184692 -26 20 8 1 0.709961 0.184692 -26 20 9 1 0.709961 0.184692 -26 20 10 1 0.709961 0.184937 -26 20 11 1 0.710449 0.185181 -26 20 12 1 0.710938 0.185547 -26 20 13 1 0.711426 0.186157 -26 20 14 1 0.711914 0.187256 -26 20 15 1 0.713379 0.240356 -26 20 16 1 0.714355 0.34082 -26 20 17 1 0.714844 0.43042 -26 20 18 1 0.713867 0.515625 -26 20 19 1 0.710449 0.597656 -26 20 20 1 0.705566 0.675781 -26 20 21 1 0.702148 0.753906 -26 20 22 1 0.70166 0.827637 -26 20 23 1 0.709473 0.89502 -26 20 24 1 0.716797 0.949219 -26 20 25 1 0.712891 0.994629 -26 20 26 1 0.699219 1 -26 20 27 1 0.680664 1 -26 20 28 1 0.656738 1 -26 20 29 0.932617 0.629395 1 -26 20 30 0.860352 0.600586 1 -26 20 31 0.785645 0.571289 1 -26 21 0 1 0.780273 0.255615 -26 21 1 1 0.780273 0.255615 -26 21 2 1 0.780273 0.255615 -26 21 3 1 0.780273 0.255615 -26 21 4 1 0.780273 0.255615 -26 21 5 1 0.780273 0.255615 -26 21 6 1 0.780273 0.255615 -26 21 7 1 0.780273 0.255615 -26 21 8 1 0.780273 0.255615 -26 21 9 1 0.780762 0.255615 -26 21 10 1 0.780762 0.255859 -26 21 11 1 0.780762 0.255859 -26 21 12 1 0.78125 0.256104 -26 21 13 1 0.78125 0.256348 -26 21 14 1 0.782227 0.256836 -26 21 15 1 0.783203 0.283203 -26 21 16 1 0.784668 0.368164 -26 21 17 1 0.786133 0.450439 -26 21 18 1 0.786133 0.530762 -26 21 19 1 0.783691 0.60791 -26 21 20 1 0.778809 0.680664 -26 21 21 1 0.771973 0.750977 -26 21 22 1 0.76709 0.821289 -26 21 23 1 0.766113 0.885742 -26 21 24 1 0.770508 0.942383 -26 21 25 1 0.76709 0.989746 -26 21 26 1 0.752441 1 -26 21 27 1 0.731934 1 -26 21 28 0.988281 0.705566 1 -26 21 29 0.920898 0.675293 1 -26 21 30 0.849609 0.643555 1 -26 21 31 0.775879 0.611816 1 -26 22 0 1 0.845215 0.298096 -26 22 1 1 0.845215 0.29834 -26 22 2 1 0.845215 0.29834 -26 22 3 1 0.845215 0.29834 -26 22 4 1 0.845215 0.29834 -26 22 5 1 0.845215 0.29834 -26 22 6 1 0.845215 0.29834 -26 22 7 1 0.845215 0.29834 -26 22 8 1 0.845215 0.29834 -26 22 9 1 0.845215 0.29834 -26 22 10 1 0.845215 0.29834 -26 22 11 1 0.845215 0.29834 -26 22 12 1 0.845215 0.29834 -26 22 13 1 0.845703 0.298584 -26 22 14 1 0.846191 0.298828 -26 22 15 1 0.847168 0.310303 -26 22 16 1 0.849121 0.387695 -26 22 17 1 0.851074 0.46582 -26 22 18 1 0.852051 0.543457 -26 22 19 1 0.850586 0.618164 -26 22 20 1 0.84668 0.687988 -26 22 21 1 0.839355 0.753418 -26 22 22 1 0.82959 0.815918 -26 22 23 1 0.822754 0.875977 -26 22 24 1 0.821777 0.933105 -26 22 25 1 0.818848 0.983398 -26 22 26 1 0.803711 1 -26 22 27 1 0.781738 1 -26 22 28 0.973145 0.75293 1 -26 22 29 0.907227 0.720215 1 -26 22 30 0.836914 0.686035 1 -26 22 31 0.763672 0.651855 1 -26 23 0 1 0.901367 0.321777 -26 23 1 1 0.901367 0.321777 -26 23 2 1 0.901367 0.321777 -26 23 3 1 0.901367 0.321777 -26 23 4 1 0.901367 0.321777 -26 23 5 1 0.901367 0.321777 -26 23 6 1 0.901367 0.321777 -26 23 7 1 0.901367 0.321777 -26 23 8 1 0.901367 0.321777 -26 23 9 1 0.901367 0.321777 -26 23 10 1 0.901367 0.321777 -26 23 11 1 0.901367 0.321777 -26 23 12 1 0.901855 0.322021 -26 23 13 1 0.901855 0.322021 -26 23 14 1 0.902344 0.322021 -26 23 15 1 0.902832 0.322266 -26 23 16 1 0.905273 0.396484 -26 23 17 1 0.907715 0.4729 -26 23 18 1 0.90918 0.549316 -26 23 19 1 0.908691 0.624023 -26 23 20 1 0.905762 0.692871 -26 23 21 1 0.899902 0.757324 -26 23 22 1 0.889648 0.815918 -26 23 23 1 0.87793 0.868652 -26 23 24 1 0.869629 0.921387 -26 23 25 1 0.866211 0.974609 -26 23 26 1 0.851074 1 -26 23 27 1 0.827637 1 -26 23 28 0.956543 0.796875 1 -26 23 29 0.891113 0.762207 1 -26 23 30 0.822754 0.726074 1 -26 23 31 0.750977 0.69043 1 -26 24 0 1 0.950195 0.331787 -26 24 1 1 0.950195 0.331787 -26 24 2 1 0.950195 0.331787 -26 24 3 1 0.950195 0.331787 -26 24 4 1 0.950195 0.331787 -26 24 5 1 0.950195 0.331787 -26 24 6 1 0.950195 0.331787 -26 24 7 1 0.950195 0.331787 -26 24 8 1 0.950195 0.331787 -26 24 9 1 0.950195 0.331787 -26 24 10 1 0.950195 0.331787 -26 24 11 1 0.950195 0.331787 -26 24 12 1 0.950195 0.331787 -26 24 13 1 0.950684 0.331787 -26 24 14 1 0.950684 0.331787 -26 24 15 1 0.951172 0.331787 -26 24 16 1 0.953613 0.395264 -26 24 17 1 0.956543 0.471436 -26 24 18 1 0.958496 0.547852 -26 24 19 1 0.958984 0.622559 -26 24 20 1 0.95752 0.692871 -26 24 21 1 0.952148 0.757812 -26 24 22 1 0.943359 0.816406 -26 24 23 1 0.931641 0.867188 -26 24 24 1 0.91748 0.912109 -26 24 25 1 0.908203 0.963379 -26 24 26 1 0.89502 1 -26 24 27 0.994141 0.870117 1 -26 24 28 0.937012 0.837402 1 -26 24 29 0.874023 0.801758 1 -26 24 30 0.807129 0.764648 1 -26 24 31 0.737305 0.728027 1 -26 25 0 1 0.995117 0.331787 -26 25 1 1 0.995117 0.331787 -26 25 2 1 0.995117 0.331787 -26 25 3 1 0.995117 0.331787 -26 25 4 1 0.995117 0.331787 -26 25 5 1 0.995117 0.331787 -26 25 6 1 0.995117 0.331787 -26 25 7 1 0.995117 0.331787 -26 25 8 1 0.995117 0.331787 -26 25 9 1 0.995117 0.331787 -26 25 10 1 0.995117 0.331787 -26 25 11 1 0.995117 0.331787 -26 25 12 1 0.995605 0.331787 -26 25 13 1 0.995605 0.331787 -26 25 14 1 0.995605 0.331787 -26 25 15 1 0.996094 0.331787 -26 25 16 1 0.998535 0.384277 -26 25 17 1 1 0.461182 -26 25 18 1 1 0.538574 -26 25 19 1 1 0.61377 -26 25 20 1 1 0.68457 -26 25 21 1 1 0.750977 -26 25 22 1 0.994629 0.811523 -26 25 23 1 0.983887 0.86377 -26 25 24 1 0.970215 0.908203 -26 25 25 1 0.952637 0.950195 -26 25 26 1 0.938965 0.997559 -26 25 27 0.96875 0.912109 1 -26 25 28 0.913086 0.878418 1 -26 25 29 0.853516 0.843262 1 -26 25 30 0.789551 0.806641 1 -26 25 31 0.72168 0.769043 1 -26 26 0 1 1 0.324951 -26 26 1 1 1 0.324951 -26 26 2 1 1 0.324951 -26 26 3 1 1 0.324951 -26 26 4 1 1 0.324951 -26 26 5 1 1 0.324951 -26 26 6 1 1 0.324951 -26 26 7 1 1 0.324951 -26 26 8 1 1 0.324951 -26 26 9 1 1 0.324951 -26 26 10 1 1 0.324951 -26 26 11 1 1 0.324951 -26 26 12 1 1 0.324951 -26 26 13 1 1 0.324951 -26 26 14 1 1 0.324951 -26 26 15 1 1 0.324951 -26 26 16 1 1 0.365234 -26 26 17 1 1 0.443604 -26 26 18 1 1 0.521484 -26 26 19 1 1 0.59668 -26 26 20 1 1 0.66748 -26 26 21 1 1 0.734863 -26 26 22 1 1 0.796387 -26 26 23 1 1 0.850586 -26 26 24 1 1 0.897461 -26 26 25 1 1 0.941895 -26 26 26 0.98291 0.98291 0.98291 -26 26 27 0.938477 0.955566 1 -26 26 28 0.887695 0.923828 1 -26 26 29 0.831055 0.88916 1 -26 26 30 0.769043 0.852051 1 -26 26 31 0.702148 0.812988 1 -26 27 0 1 1 0.315186 -26 27 1 1 1 0.315186 -26 27 2 1 1 0.315186 -26 27 3 1 1 0.315186 -26 27 4 1 1 0.315186 -26 27 5 1 1 0.315186 -26 27 6 1 1 0.315186 -26 27 7 1 1 0.315186 -26 27 8 1 1 0.315186 -26 27 9 1 1 0.315186 -26 27 10 1 1 0.315186 -26 27 11 1 1 0.315186 -26 27 12 1 1 0.315186 -26 27 13 1 1 0.315186 -26 27 14 1 1 0.315186 -26 27 15 1 1 0.315186 -26 27 16 1 1 0.341064 -26 27 17 1 1 0.420898 -26 27 18 1 1 0.498779 -26 27 19 1 1 0.57373 -26 27 20 1 1 0.644531 -26 27 21 1 1 0.711426 -26 27 22 1 1 0.772949 -26 27 23 1 1 0.827637 -26 27 24 1 1 0.875 -26 27 25 0.975098 1 0.92041 -26 27 26 0.943848 1 0.964355 -26 27 27 0.907715 1 1 -26 27 28 0.86084 0.975586 1 -26 27 29 0.805664 0.939941 1 -26 27 30 0.744629 0.901367 1 -26 27 31 0.678223 0.860352 1 -26 28 0 1 1 0.303223 -26 28 1 1 1 0.303223 -26 28 2 1 1 0.303223 -26 28 3 1 1 0.303223 -26 28 4 1 1 0.303223 -26 28 5 1 1 0.303223 -26 28 6 1 1 0.303223 -26 28 7 1 1 0.303223 -26 28 8 1 1 0.303223 -26 28 9 1 1 0.303223 -26 28 10 1 1 0.303223 -26 28 11 1 1 0.303223 -26 28 12 1 1 0.303223 -26 28 13 1 1 0.303223 -26 28 14 1 1 0.303223 -26 28 15 1 1 0.303223 -26 28 16 1 1 0.312012 -26 28 17 1 1 0.394043 -26 28 18 1 1 0.472168 -26 28 19 1 1 0.546875 -26 28 20 1 1 0.616699 -26 28 21 0.991699 1 0.683105 -26 28 22 0.97998 1 0.744629 -26 28 23 0.964355 1 0.798828 -26 28 24 0.946289 1 0.847168 -26 28 25 0.92334 1 0.894531 -26 28 26 0.895996 1 0.941406 -26 28 27 0.862793 1 0.98584 -26 28 28 0.821777 1 1 -26 28 29 0.771973 0.990723 1 -26 28 30 0.713379 0.952637 1 -26 28 31 0.647461 0.910645 1 -26 29 0 0.940918 1 0.290039 -26 29 1 0.940918 1 0.290039 -26 29 2 0.940918 1 0.290039 -26 29 3 0.940918 1 0.290039 -26 29 4 0.940918 1 0.290039 -26 29 5 0.940918 1 0.290039 -26 29 6 0.940918 1 0.290039 -26 29 7 0.940918 1 0.290039 -26 29 8 0.940918 1 0.290039 -26 29 9 0.940918 1 0.290039 -26 29 10 0.94043 1 0.290039 -26 29 11 0.94043 1 0.290039 -26 29 12 0.94043 1 0.290039 -26 29 13 0.94043 1 0.290039 -26 29 14 0.94043 1 0.290039 -26 29 15 0.94043 1 0.290039 -26 29 16 0.94043 1 0.290039 -26 29 17 0.939453 1 0.36377 -26 29 18 0.937988 1 0.442383 -26 29 19 0.93457 1 0.516113 -26 29 20 0.929688 1 0.585449 -26 29 21 0.921875 1 0.650879 -26 29 22 0.911133 1 0.711914 -26 29 23 0.898438 1 0.766602 -26 29 24 0.882812 1 0.815918 -26 29 25 0.863281 1 0.865234 -26 29 26 0.838379 1 0.913574 -26 29 27 0.807617 1 0.959961 -26 29 28 0.77002 1 1 -26 29 29 0.724609 1 1 -26 29 30 0.67041 1 1 -26 29 31 0.606445 0.961426 1 -26 30 0 0.862305 1 0.276123 -26 30 1 0.862305 1 0.276123 -26 30 2 0.862305 1 0.276123 -26 30 3 0.862305 1 0.276123 -26 30 4 0.862305 1 0.276123 -26 30 5 0.862305 1 0.276123 -26 30 6 0.862305 1 0.276123 -26 30 7 0.862305 1 0.276123 -26 30 8 0.862305 1 0.276123 -26 30 9 0.862305 1 0.276123 -26 30 10 0.862305 1 0.276123 -26 30 11 0.862305 1 0.276123 -26 30 12 0.862305 1 0.276123 -26 30 13 0.862305 1 0.276123 -26 30 14 0.862305 1 0.276123 -26 30 15 0.862305 1 0.276123 -26 30 16 0.861816 1 0.276123 -26 30 17 0.861328 1 0.330078 -26 30 18 0.859375 1 0.410156 -26 30 19 0.855957 1 0.483643 -26 30 20 0.851074 1 0.551758 -26 30 21 0.844238 1 0.616211 -26 30 22 0.834961 1 0.676758 -26 30 23 0.823242 1 0.731445 -26 30 24 0.80957 1 0.78125 -26 30 25 0.79248 1 0.831055 -26 30 26 0.77002 1 0.880859 -26 30 27 0.742188 1 0.929199 -26 30 28 0.707031 1 0.974609 -26 30 29 0.664062 1 1 -26 30 30 0.612305 1 1 -26 30 31 0.549805 1 1 -26 31 0 0.775879 1 0.261475 -26 31 1 0.775879 1 0.261475 -26 31 2 0.775879 1 0.261475 -26 31 3 0.775879 1 0.261475 -26 31 4 0.775879 1 0.261475 -26 31 5 0.775879 1 0.261475 -26 31 6 0.775879 1 0.261475 -26 31 7 0.775879 1 0.261475 -26 31 8 0.775879 1 0.261475 -26 31 9 0.775879 1 0.261475 -26 31 10 0.775879 1 0.261475 -26 31 11 0.775879 1 0.261475 -26 31 12 0.775879 1 0.261475 -26 31 13 0.775879 1 0.261475 -26 31 14 0.775879 1 0.261475 -26 31 15 0.775879 1 0.261475 -26 31 16 0.775879 1 0.261475 -26 31 17 0.775391 1 0.292236 -26 31 18 0.772949 1 0.375244 -26 31 19 0.769531 1 0.448975 -26 31 20 0.764648 1 0.516113 -26 31 21 0.757812 1 0.580078 -26 31 22 0.749023 1 0.639648 -26 31 23 0.738281 1 0.693359 -26 31 24 0.725586 1 0.743164 -26 31 25 0.709473 1 0.793457 -26 31 26 0.688965 1 0.84375 -26 31 27 0.662598 1 0.893555 -26 31 28 0.628906 1 0.941406 -26 31 29 0.587402 1 0.986328 -26 31 30 0.535645 1 1 -26 31 31 0.470459 1 1 -27 0 0 1 0 0.0733643 -27 0 1 1 0 0.0733643 -27 0 2 1 0 0.0733643 -27 0 3 1 0 0.0733643 -27 0 4 1 0 0.0733643 -27 0 5 1 0 0.0733643 -27 0 6 1 0 0.0733032 -27 0 7 1 0 0.0733032 -27 0 8 1 0 0.0732422 -27 0 9 1 0 0.0731201 -27 0 10 1 0 0.072937 -27 0 11 1 0 0.0726318 -27 0 12 1 0 0.0720825 -27 0 13 1 0 0.071106 -27 0 14 1 0 0.0695801 -27 0 15 1 0 0.0680542 -27 0 16 1 0 0.143799 -27 0 17 1 0 0.330322 -27 0 18 1 0 0.451172 -27 0 19 1 0 0.552246 -27 0 20 1 0 0.645508 -27 0 21 1 0 0.73291 -27 0 22 1 0.226562 0.811035 -27 0 23 1 0.310791 0.875488 -27 0 24 1 0.359619 0.927734 -27 0 25 1 0.385498 0.974121 -27 0 26 1 0.39209 1 -27 0 27 1 0.390625 1 -27 0 28 1 0.386719 1 -27 0 29 1 0.380859 1 -27 0 30 0.972656 0.373779 1 -27 0 31 0.898926 0.365479 1 -27 1 0 1 0 0.0733643 -27 1 1 1 0 0.0733643 -27 1 2 1 0 0.0733643 -27 1 3 1 0 0.0733643 -27 1 4 1 0 0.0733643 -27 1 5 1 0 0.0733643 -27 1 6 1 0 0.0733032 -27 1 7 1 0 0.0733032 -27 1 8 1 0 0.0732422 -27 1 9 1 0 0.0731201 -27 1 10 1 0 0.072937 -27 1 11 1 0 0.0726318 -27 1 12 1 0 0.0720825 -27 1 13 1 0 0.071106 -27 1 14 1 0 0.0695801 -27 1 15 1 0 0.0680542 -27 1 16 1 0 0.143799 -27 1 17 1 0 0.330322 -27 1 18 1 0 0.451172 -27 1 19 1 0 0.552246 -27 1 20 1 0 0.645508 -27 1 21 1 0 0.73291 -27 1 22 1 0.226562 0.811035 -27 1 23 1 0.310791 0.875488 -27 1 24 1 0.359619 0.927734 -27 1 25 1 0.385498 0.974121 -27 1 26 1 0.39209 1 -27 1 27 1 0.390625 1 -27 1 28 1 0.386719 1 -27 1 29 1 0.380859 1 -27 1 30 0.972656 0.373779 1 -27 1 31 0.898926 0.365479 1 -27 2 0 1 0 0.0733643 -27 2 1 1 0 0.0733643 -27 2 2 1 0 0.0733643 -27 2 3 1 0 0.0733643 -27 2 4 1 0 0.0733032 -27 2 5 1 0 0.0733032 -27 2 6 1 0 0.0733032 -27 2 7 1 0 0.0733032 -27 2 8 1 0 0.0732422 -27 2 9 1 0 0.0731201 -27 2 10 1 0 0.072937 -27 2 11 1 0 0.0726318 -27 2 12 1 0 0.0720215 -27 2 13 1 0 0.071106 -27 2 14 1 0 0.0695801 -27 2 15 1 0 0.0680542 -27 2 16 1 0 0.143799 -27 2 17 1 0 0.330322 -27 2 18 1 0 0.451172 -27 2 19 1 0 0.552246 -27 2 20 1 0 0.645508 -27 2 21 1 0 0.73291 -27 2 22 1 0.226562 0.811035 -27 2 23 1 0.310791 0.875488 -27 2 24 1 0.359619 0.927734 -27 2 25 1 0.385498 0.974121 -27 2 26 1 0.39209 1 -27 2 27 1 0.390625 1 -27 2 28 1 0.386719 1 -27 2 29 1 0.381104 1 -27 2 30 0.972656 0.373779 1 -27 2 31 0.898926 0.365479 1 -27 3 0 1 0 0.0733032 -27 3 1 1 0 0.0733032 -27 3 2 1 0 0.0733032 -27 3 3 1 0 0.0733032 -27 3 4 1 0 0.0733032 -27 3 5 1 0 0.0733032 -27 3 6 1 0 0.0733032 -27 3 7 1 0 0.0732422 -27 3 8 1 0 0.0731812 -27 3 9 1 0 0.0731201 -27 3 10 1 0 0.072937 -27 3 11 1 0 0.0725708 -27 3 12 1 0 0.0720215 -27 3 13 1 0 0.0710449 -27 3 14 1 0 0.069519 -27 3 15 1 0 0.0679932 -27 3 16 1 0 0.143799 -27 3 17 1 0 0.330322 -27 3 18 1 0 0.451172 -27 3 19 1 0 0.552246 -27 3 20 1 0 0.645508 -27 3 21 1 0 0.73291 -27 3 22 1 0.226685 0.811035 -27 3 23 1 0.310791 0.875488 -27 3 24 1 0.359619 0.927734 -27 3 25 1 0.385498 0.974121 -27 3 26 1 0.39209 1 -27 3 27 1 0.390625 1 -27 3 28 1 0.386963 1 -27 3 29 1 0.381104 1 -27 3 30 0.972656 0.373779 1 -27 3 31 0.898926 0.365479 1 -27 4 0 1 0 0.0732422 -27 4 1 1 0 0.0732422 -27 4 2 1 0 0.0732422 -27 4 3 1 0 0.0732422 -27 4 4 1 0 0.0732422 -27 4 5 1 0 0.0732422 -27 4 6 1 0 0.0732422 -27 4 7 1 0 0.0731812 -27 4 8 1 0 0.0731812 -27 4 9 1 0 0.0730591 -27 4 10 1 0 0.072876 -27 4 11 1 0 0.0725098 -27 4 12 1 0 0.0719604 -27 4 13 1 0 0.0710449 -27 4 14 1 0 0.069458 -27 4 15 1 0 0.0679932 -27 4 16 1 0 0.143799 -27 4 17 1 0 0.330322 -27 4 18 1 0 0.451172 -27 4 19 1 0 0.552246 -27 4 20 1 0 0.645508 -27 4 21 1 0 0.73291 -27 4 22 1 0.226807 0.811035 -27 4 23 1 0.310791 0.875488 -27 4 24 1 0.359619 0.927734 -27 4 25 1 0.385742 0.974121 -27 4 26 1 0.392334 1 -27 4 27 1 0.390625 1 -27 4 28 1 0.386963 1 -27 4 29 1 0.381104 1 -27 4 30 0.972656 0.373779 1 -27 4 31 0.898926 0.365479 1 -27 5 0 1 0 0.0731812 -27 5 1 1 0 0.0731812 -27 5 2 1 0 0.0731812 -27 5 3 1 0 0.0731812 -27 5 4 1 0 0.0731812 -27 5 5 1 0 0.0731812 -27 5 6 1 0 0.0731201 -27 5 7 1 0 0.0731201 -27 5 8 1 0 0.0730591 -27 5 9 1 0 0.072937 -27 5 10 1 0 0.0727539 -27 5 11 1 0 0.0724487 -27 5 12 1 0 0.0718994 -27 5 13 1 0 0.0709229 -27 5 14 1 0 0.069397 -27 5 15 1 0 0.0678711 -27 5 16 1 0 0.143799 -27 5 17 1 0 0.330322 -27 5 18 1 0 0.451172 -27 5 19 1 0 0.552246 -27 5 20 1 0 0.645508 -27 5 21 1 0 0.73291 -27 5 22 1 0.227051 0.811035 -27 5 23 1 0.311035 0.875488 -27 5 24 1 0.359863 0.927734 -27 5 25 1 0.385742 0.974121 -27 5 26 1 0.392334 1 -27 5 27 1 0.390625 1 -27 5 28 1 0.386963 1 -27 5 29 1 0.381104 1 -27 5 30 0.972656 0.373779 1 -27 5 31 0.898926 0.365723 1 -27 6 0 1 0 0.072998 -27 6 1 1 0 0.072998 -27 6 2 1 0 0.072998 -27 6 3 1 0 0.072998 -27 6 4 1 0 0.072998 -27 6 5 1 0 0.072998 -27 6 6 1 0 0.072998 -27 6 7 1 0 0.072937 -27 6 8 1 0 0.072876 -27 6 9 1 0 0.0728149 -27 6 10 1 0 0.0726318 -27 6 11 1 0 0.0722656 -27 6 12 1 0 0.0717163 -27 6 13 1 0 0.0707397 -27 6 14 1 0 0.0692139 -27 6 15 1 0 0.067688 -27 6 16 1 0 0.143799 -27 6 17 1 0 0.330322 -27 6 18 1 0 0.451172 -27 6 19 1 0 0.552246 -27 6 20 1 0 0.645508 -27 6 21 1 0 0.73291 -27 6 22 1 0.227539 0.811035 -27 6 23 1 0.311279 0.875488 -27 6 24 1 0.360107 0.927734 -27 6 25 1 0.385986 0.974121 -27 6 26 1 0.392578 1 -27 6 27 1 0.390869 1 -27 6 28 1 0.387207 1 -27 6 29 1 0.381348 1 -27 6 30 0.972656 0.374023 1 -27 6 31 0.898926 0.365723 1 -27 7 0 1 0 0.0726929 -27 7 1 1 0 0.0726929 -27 7 2 1 0 0.0726929 -27 7 3 1 0 0.0726929 -27 7 4 1 0 0.0726318 -27 7 5 1 0 0.0726318 -27 7 6 1 0 0.0726318 -27 7 7 1 0 0.0726318 -27 7 8 1 0 0.0725708 -27 7 9 1 0 0.0724487 -27 7 10 1 0 0.0722656 -27 7 11 1 0 0.0718994 -27 7 12 1 0 0.0713501 -27 7 13 1 0 0.0703735 -27 7 14 1 0 0.0687866 -27 7 15 1 0 0.0672607 -27 7 16 1 0 0.143799 -27 7 17 1 0 0.330322 -27 7 18 1 0 0.451172 -27 7 19 1 0 0.552246 -27 7 20 1 0 0.645508 -27 7 21 1 0 0.73291 -27 7 22 1 0.228638 0.811035 -27 7 23 1 0.312012 0.875488 -27 7 24 1 0.360596 0.927734 -27 7 25 1 0.386475 0.974121 -27 7 26 1 0.393066 1 -27 7 27 1 0.391357 1 -27 7 28 1 0.387451 1 -27 7 29 1 0.381592 1 -27 7 30 0.972656 0.374268 1 -27 7 31 0.898926 0.365967 1 -27 8 0 1 0 0.0720215 -27 8 1 1 0 0.0720215 -27 8 2 1 0 0.0720215 -27 8 3 1 0 0.0720215 -27 8 4 1 0 0.0719604 -27 8 5 1 0 0.0719604 -27 8 6 1 0 0.0719604 -27 8 7 1 0 0.0719604 -27 8 8 1 0 0.0718994 -27 8 9 1 0 0.0717773 -27 8 10 1 0 0.0715942 -27 8 11 1 0 0.071228 -27 8 12 1 0 0.0706787 -27 8 13 1 0 0.0697021 -27 8 14 1 0 0.0681152 -27 8 15 1 0 0.0665283 -27 8 16 1 0 0.143799 -27 8 17 1 0 0.330078 -27 8 18 1 0 0.451172 -27 8 19 1 0 0.552246 -27 8 20 1 0 0.64502 -27 8 21 1 0 0.73291 -27 8 22 1 0.230591 0.811035 -27 8 23 1 0.312988 0.875488 -27 8 24 1 0.361572 0.927734 -27 8 25 1 0.387207 0.974121 -27 8 26 1 0.393799 1 -27 8 27 1 0.39209 1 -27 8 28 1 0.388184 1 -27 8 29 1 0.38208 1 -27 8 30 0.972656 0.374756 1 -27 8 31 0.898926 0.366455 1 -27 9 0 1 0 0.0706787 -27 9 1 1 0 0.0706787 -27 9 2 1 0 0.0706787 -27 9 3 1 0 0.0706787 -27 9 4 1 0 0.0706787 -27 9 5 1 0 0.0706787 -27 9 6 1 0 0.0706787 -27 9 7 1 0 0.0706177 -27 9 8 1 0 0.0705566 -27 9 9 1 0 0.0704346 -27 9 10 1 0 0.0702515 -27 9 11 1 0 0.0698853 -27 9 12 1 0 0.0693359 -27 9 13 1 0 0.0682983 -27 9 14 1 0 0.0666504 -27 9 15 1 0 0.0650635 -27 9 16 1 0 0.143799 -27 9 17 1 0 0.330078 -27 9 18 1 0 0.450928 -27 9 19 1 0 0.552246 -27 9 20 1 0 0.64502 -27 9 21 1 0 0.73291 -27 9 22 1 0.234253 0.811035 -27 9 23 1 0.31543 0.875488 -27 9 24 1 0.363281 0.927734 -27 9 25 1 0.388672 0.974121 -27 9 26 1 0.395264 1 -27 9 27 1 0.393311 1 -27 9 28 1 0.389404 1 -27 9 29 1 0.383301 1 -27 9 30 0.972656 0.375732 1 -27 9 31 0.898926 0.367432 1 -27 10 0 1 0 0.0681763 -27 10 1 1 0 0.0681763 -27 10 2 1 0 0.0681763 -27 10 3 1 0 0.0681763 -27 10 4 1 0 0.0681763 -27 10 5 1 0 0.0681763 -27 10 6 1 0 0.0681763 -27 10 7 1 0 0.0681152 -27 10 8 1 0 0.0680542 -27 10 9 1 0 0.0679321 -27 10 10 1 0 0.067749 -27 10 11 1 0 0.0673828 -27 10 12 1 0 0.0667114 -27 10 13 1 0 0.0656738 -27 10 14 1 0 0.0639038 -27 10 15 1 0 0.0621948 -27 10 16 1 0 0.143799 -27 10 17 1 0 0.330078 -27 10 18 1 0 0.450928 -27 10 19 1 0 0.552246 -27 10 20 1 0 0.64502 -27 10 21 1 0.052063 0.73291 -27 10 22 1 0.240723 0.811035 -27 10 23 1 0.319336 0.875488 -27 10 24 1 0.366455 0.927734 -27 10 25 1 0.391602 0.974121 -27 10 26 1 0.397705 1 -27 10 27 1 0.395752 1 -27 10 28 1 0.391602 1 -27 10 29 1 0.385498 1 -27 10 30 0.972168 0.377686 1 -27 10 31 0.898926 0.369141 1 -27 11 0 1 0 0.0634155 -27 11 1 1 0 0.0634155 -27 11 2 1 0 0.0634155 -27 11 3 1 0 0.0634155 -27 11 4 1 0 0.0634155 -27 11 5 1 0 0.0634155 -27 11 6 1 0 0.0634155 -27 11 7 1 0 0.0633545 -27 11 8 1 0 0.0632935 -27 11 9 1 0 0.0631714 -27 11 10 1 0 0.0629272 -27 11 11 1 0 0.0625 -27 11 12 1 0 0.0617676 -27 11 13 1 0 0.0605469 -27 11 14 1 0 0.0585327 -27 11 15 1 0 0.0566101 -27 11 16 1 0 0.143921 -27 11 17 1 0 0.329834 -27 11 18 1 0 0.450684 -27 11 19 1 0 0.552246 -27 11 20 1 0 0.64502 -27 11 21 1 0.114136 0.732422 -27 11 22 1 0.251465 0.811035 -27 11 23 1 0.326172 0.875488 -27 11 24 1 0.371826 0.927734 -27 11 25 1 0.396484 0.974121 -27 11 26 1 0.402344 1 -27 11 27 1 0.399902 1 -27 11 28 1 0.395508 1 -27 11 29 1 0.388916 1 -27 11 30 0.972168 0.380859 1 -27 11 31 0.898438 0.37207 1 -27 12 0 1 0 0.0535889 -27 12 1 1 0 0.0535889 -27 12 2 1 0 0.0535583 -27 12 3 1 0 0.0535583 -27 12 4 1 0 0.0535583 -27 12 5 1 0 0.0535583 -27 12 6 1 0 0.0535278 -27 12 7 1 0 0.0534973 -27 12 8 1 0 0.0534058 -27 12 9 1 0 0.0532227 -27 12 10 1 0 0.0529175 -27 12 11 1 0 0.0523682 -27 12 12 1 0 0.0513916 -27 12 13 1 0 0.0497131 -27 12 14 1 0 0.046875 -27 12 15 1 0 0.0441589 -27 12 16 1 0 0.144165 -27 12 17 1 0 0.329834 -27 12 18 1 0 0.450195 -27 12 19 1 0 0.552246 -27 12 20 1 0 0.644531 -27 12 21 1 0.162109 0.732422 -27 12 22 1 0.268311 0.810547 -27 12 23 1 0.337402 0.875488 -27 12 24 1 0.380859 0.927734 -27 12 25 1 0.404541 0.974121 -27 12 26 1 0.409668 1 -27 12 27 1 0.406982 1 -27 12 28 1 0.4021 1 -27 12 29 1 0.39502 1 -27 12 30 0.97168 0.386475 1 -27 12 31 0.898438 0.376953 1 -27 13 0 1 0 0.0213928 -27 13 1 1 0 0.0213928 -27 13 2 1 0 0.0213776 -27 13 3 1 0 0.0213623 -27 13 4 1 0 0.0213318 -27 13 5 1 0 0.021286 -27 13 6 1 0 0.0211792 -27 13 7 1 0 0.0209808 -27 13 8 1 0 0.0205841 -27 13 9 1 0 0.0197601 -27 13 10 1 0 0.0181274 -27 13 11 1 0 0.0145035 -27 13 12 1 0.0312042 0 -27 13 13 1 0.0675659 0 -27 13 14 1 0.0942383 0 -27 13 15 1 0.109619 0 -27 13 16 1 0.115295 0.14502 -27 13 17 1 0.0792236 0.32959 -27 13 18 1 0.0563965 0.449707 -27 13 19 1 0.0674438 0.552246 -27 13 20 1 0.118958 0.644043 -27 13 21 1 0.21106 0.731934 -27 13 22 1 0.29248 0.810059 -27 13 23 1 0.354492 0.875 -27 13 24 1 0.39502 0.927734 -27 13 25 1 0.417236 0.974121 -27 13 26 1 0.421631 1 -27 13 27 1 0.418213 1 -27 13 28 1 0.412598 1 -27 13 29 1 0.404541 1 -27 13 30 0.971191 0.39502 1 -27 13 31 0.897461 0.384766 1 -27 14 0 1 0.196167 0 -27 14 1 1 0.196167 0 -27 14 2 1 0.196167 0 -27 14 3 1 0.196167 0 -27 14 4 1 0.196167 0 -27 14 5 1 0.196289 0 -27 14 6 1 0.196289 0 -27 14 7 1 0.196411 0 -27 14 8 1 0.196655 0 -27 14 9 1 0.197144 0 -27 14 10 1 0.197998 0 -27 14 11 1 0.199463 0 -27 14 12 1 0.201782 0 -27 14 13 1 0.205688 0 -27 14 14 1 0.211548 0 -27 14 15 1 0.216064 0 -27 14 16 1 0.216797 0.147339 -27 14 17 1 0.206421 0.32959 -27 14 18 1 0.201538 0.44873 -27 14 19 1 0.206787 0.552246 -27 14 20 1 0.216797 0.643555 -27 14 21 1 0.26416 0.730957 -27 14 22 1 0.325928 0.80957 -27 14 23 1 0.37915 0.875 -27 14 24 1 0.416016 0.927734 -27 14 25 1 0.436035 0.974121 -27 14 26 1 0.439453 1 -27 14 27 1 0.435059 1 -27 14 28 1 0.428223 1 -27 14 29 1 0.418945 1 -27 14 30 0.970215 0.408203 1 -27 14 31 0.896973 0.396484 1 -27 15 0 1 0.285156 0 -27 15 1 1 0.285156 0 -27 15 2 1 0.285156 0 -27 15 3 1 0.285156 0 -27 15 4 1 0.2854 0 -27 15 5 1 0.2854 0 -27 15 6 1 0.2854 0 -27 15 7 1 0.2854 0 -27 15 8 1 0.285645 0 -27 15 9 1 0.285889 0 -27 15 10 1 0.286133 0 -27 15 11 1 0.287109 0 -27 15 12 1 0.28833 0 -27 15 13 1 0.290527 0 -27 15 14 1 0.294189 0 -27 15 15 1 0.296631 0 -27 15 16 1 0.296143 0.15271 -27 15 17 1 0.290039 0.330078 -27 15 18 1 0.286621 0.447998 -27 15 19 1 0.292725 0.552734 -27 15 20 1 0.294922 0.642578 -27 15 21 1 0.322754 0.729492 -27 15 22 1 0.368164 0.808594 -27 15 23 1 0.412598 0.874023 -27 15 24 1 0.445068 0.927246 -27 15 25 1 0.462646 0.974121 -27 15 26 1 0.464844 1 -27 15 27 1 0.458984 1 -27 15 28 1 0.450684 1 -27 15 29 1 0.439697 1 -27 15 30 0.96875 0.427246 1 -27 15 31 0.895508 0.413818 1 -27 16 0 1 0.367188 0 -27 16 1 1 0.367188 0 -27 16 2 1 0.367188 0 -27 16 3 1 0.367432 0 -27 16 4 1 0.367432 0 -27 16 5 1 0.367432 0 -27 16 6 1 0.367432 0 -27 16 7 1 0.367432 0 -27 16 8 1 0.367432 0 -27 16 9 1 0.367676 0 -27 16 10 1 0.36792 0 -27 16 11 1 0.368408 0 -27 16 12 1 0.369385 0 -27 16 13 1 0.37085 0 -27 16 14 1 0.373291 0 -27 16 15 1 0.374756 0 -27 16 16 1 0.374023 0.164307 -27 16 17 1 0.370117 0.332275 -27 16 18 1 0.367188 0.447754 -27 16 19 1 0.369385 0.550781 -27 16 20 1 0.37207 0.641602 -27 16 21 1 0.387451 0.728027 -27 16 22 1 0.419678 0.806641 -27 16 23 1 0.455322 0.873047 -27 16 24 1 0.48291 0.926758 -27 16 25 1 0.498047 0.973633 -27 16 26 1 0.498291 1 -27 16 27 1 0.490967 1 -27 16 28 1 0.480713 1 -27 16 29 1 0.467773 1 -27 16 30 0.966797 0.453125 1 -27 16 31 0.893066 0.437256 1 -27 17 0 1 0.447998 0 -27 17 1 1 0.447998 0 -27 17 2 1 0.447998 0 -27 17 3 1 0.447998 0 -27 17 4 1 0.447998 0 -27 17 5 1 0.447998 0 -27 17 6 1 0.447998 0 -27 17 7 1 0.447998 0 -27 17 8 1 0.447998 0 -27 17 9 1 0.448242 0 -27 17 10 1 0.448486 0 -27 17 11 1 0.44873 0 -27 17 12 1 0.449463 0 -27 17 13 1 0.450684 0 -27 17 14 1 0.452393 0 -27 17 15 1 0.453613 0 -27 17 16 1 0.452637 0.184448 -27 17 17 1 0.450195 0.337646 -27 17 18 1 0.447754 0.44873 -27 17 19 1 0.447021 0.548828 -27 17 20 1 0.450684 0.641113 -27 17 21 1 0.456787 0.725098 -27 17 22 1 0.478027 0.804199 -27 17 23 1 0.505371 0.871094 -27 17 24 1 0.52832 0.925781 -27 17 25 1 0.541016 0.973145 -27 17 26 1 0.539551 1 -27 17 27 1 0.530762 1 -27 17 28 1 0.518066 1 -27 17 29 1 0.50293 1 -27 17 30 0.963379 0.485352 1 -27 17 31 0.890137 0.466797 1 -27 18 0 1 0.527344 0 -27 18 1 1 0.527344 0 -27 18 2 1 0.527344 0 -27 18 3 1 0.527344 0 -27 18 4 1 0.527344 0 -27 18 5 1 0.527344 0 -27 18 6 1 0.527344 0 -27 18 7 1 0.527344 0 -27 18 8 1 0.527344 0 -27 18 9 1 0.527832 0 -27 18 10 1 0.527832 0 -27 18 11 1 0.527832 0 -27 18 12 1 0.528809 0 -27 18 13 1 0.529297 0 -27 18 14 1 0.530762 0 -27 18 15 1 0.531738 0 -27 18 16 1 0.53125 0.213745 -27 18 17 1 0.530273 0.3479 -27 18 18 1 0.52832 0.452881 -27 18 19 1 0.526367 0.548828 -27 18 20 1 0.527344 0.63916 -27 18 21 1 0.529785 0.722168 -27 18 22 1 0.541016 0.800293 -27 18 23 1 0.561035 0.868164 -27 18 24 1 0.57959 0.923828 -27 18 25 1 0.589844 0.972168 -27 18 26 1 0.586914 1 -27 18 27 1 0.575684 1 -27 18 28 1 0.561035 1 -27 18 29 1 0.542969 1 -27 18 30 0.958984 0.522949 1 -27 18 31 0.885742 0.501465 1 -27 19 0 1 0.604004 0 -27 19 1 1 0.604004 0 -27 19 2 1 0.604004 0 -27 19 3 1 0.604004 0 -27 19 4 1 0.604004 0 -27 19 5 1 0.604004 0 -27 19 6 1 0.604004 0 -27 19 7 1 0.604004 0 -27 19 8 1 0.604004 0 -27 19 9 1 0.604004 0 -27 19 10 1 0.604004 0 -27 19 11 1 0.604492 0 -27 19 12 1 0.60498 0 -27 19 13 1 0.605469 0 -27 19 14 1 0.606445 0 -27 19 15 1 0.60791 0 -27 19 16 1 0.608398 0.249023 -27 19 17 1 0.60791 0.364258 -27 19 18 1 0.606934 0.461426 -27 19 19 1 0.604492 0.55127 -27 19 20 1 0.602539 0.636719 -27 19 21 1 0.604004 0.720215 -27 19 22 1 0.606445 0.79541 -27 19 23 1 0.618652 0.863281 -27 19 24 1 0.632812 0.92041 -27 19 25 1 0.641113 0.969727 -27 19 26 1 0.637207 1 -27 19 27 1 0.624512 1 -27 19 28 1 0.607422 1 -27 19 29 1 0.586914 1 -27 19 30 0.953125 0.563965 1 -27 19 31 0.879883 0.539551 1 -27 20 0 1 0.67627 0.0932617 -27 20 1 1 0.67627 0.0932617 -27 20 2 1 0.67627 0.0932617 -27 20 3 1 0.67627 0.0932617 -27 20 4 1 0.67627 0.0932617 -27 20 5 1 0.67627 0.0932617 -27 20 6 1 0.67627 0.0933228 -27 20 7 1 0.67627 0.0933838 -27 20 8 1 0.67627 0.0934448 -27 20 9 1 0.67627 0.093689 -27 20 10 1 0.676758 0.0940552 -27 20 11 1 0.676758 0.0947266 -27 20 12 1 0.677246 0.0958252 -27 20 13 1 0.677734 0.0975952 -27 20 14 1 0.678223 0.100281 -27 20 15 1 0.679688 0.144531 -27 20 16 1 0.680664 0.285645 -27 20 17 1 0.681641 0.384766 -27 20 18 1 0.681152 0.474121 -27 20 19 1 0.679199 0.558105 -27 20 20 1 0.67627 0.637695 -27 20 21 1 0.67334 0.71582 -27 20 22 1 0.672363 0.790527 -27 20 23 1 0.676758 0.857422 -27 20 24 1 0.686523 0.915527 -27 20 25 1 0.693359 0.966797 -27 20 26 1 0.687988 1 -27 20 27 1 0.673828 1 -27 20 28 1 0.654785 1 -27 20 29 1 0.631836 1 -27 20 30 0.946289 0.605957 1 -27 20 31 0.873047 0.578613 1 -27 21 0 1 0.744629 0.213257 -27 21 1 1 0.744629 0.213257 -27 21 2 1 0.744629 0.213257 -27 21 3 1 0.744629 0.213257 -27 21 4 1 0.744629 0.213257 -27 21 5 1 0.744629 0.213257 -27 21 6 1 0.744629 0.213257 -27 21 7 1 0.744629 0.213257 -27 21 8 1 0.744629 0.213257 -27 21 9 1 0.745117 0.213379 -27 21 10 1 0.745117 0.213379 -27 21 11 1 0.745117 0.213623 -27 21 12 1 0.745605 0.213867 -27 21 13 1 0.745605 0.214355 -27 21 14 1 0.746582 0.214966 -27 21 15 1 0.747559 0.219238 -27 21 16 1 0.749023 0.31958 -27 21 17 1 0.750488 0.407227 -27 21 18 1 0.750977 0.489746 -27 21 19 1 0.750488 0.568359 -27 21 20 1 0.74707 0.642578 -27 21 21 1 0.742188 0.714844 -27 21 22 1 0.738281 0.785645 -27 21 23 1 0.73584 0.850098 -27 21 24 1 0.739746 0.908691 -27 21 25 1 0.744629 0.961914 -27 21 26 1 0.739258 1 -27 21 27 1 0.723633 1 -27 21 28 1 0.703125 1 -27 21 29 1 0.677734 1 -27 21 30 0.937012 0.648926 1 -27 21 31 0.864746 0.618652 1 -27 22 0 1 0.807617 0.270752 -27 22 1 1 0.807617 0.270752 -27 22 2 1 0.807617 0.270752 -27 22 3 1 0.807617 0.270752 -27 22 4 1 0.807617 0.270752 -27 22 5 1 0.807617 0.270752 -27 22 6 1 0.807617 0.270752 -27 22 7 1 0.808105 0.270752 -27 22 8 1 0.808105 0.270752 -27 22 9 1 0.808105 0.270752 -27 22 10 1 0.808105 0.270752 -27 22 11 1 0.808105 0.270752 -27 22 12 1 0.808105 0.270996 -27 22 13 1 0.808594 0.27124 -27 22 14 1 0.809082 0.271729 -27 22 15 1 0.810059 0.272217 -27 22 16 1 0.812012 0.346924 -27 22 17 1 0.813965 0.426758 -27 22 18 1 0.81543 0.504395 -27 22 19 1 0.81543 0.57959 -27 22 20 1 0.812988 0.649902 -27 22 21 1 0.808105 0.717285 -27 22 22 1 0.80127 0.781738 -27 22 23 1 0.795898 0.843262 -27 22 24 1 0.79248 0.899902 -27 22 25 1 0.794434 0.955078 -27 22 26 1 0.789062 1 -27 22 27 1 0.772461 1 -27 22 28 1 0.75 1 -27 22 29 0.993652 0.722656 1 -27 22 30 0.92627 0.691406 1 -27 22 31 0.854492 0.658691 1 -27 23 0 1 0.863281 0.305664 -27 23 1 1 0.863281 0.305664 -27 23 2 1 0.863281 0.305664 -27 23 3 1 0.863281 0.305664 -27 23 4 1 0.863281 0.305664 -27 23 5 1 0.863281 0.305664 -27 23 6 1 0.863281 0.305664 -27 23 7 1 0.863281 0.305664 -27 23 8 1 0.863281 0.305664 -27 23 9 1 0.863281 0.305664 -27 23 10 1 0.863281 0.305664 -27 23 11 1 0.86377 0.305664 -27 23 12 1 0.86377 0.305908 -27 23 13 1 0.86377 0.305908 -27 23 14 1 0.864258 0.306152 -27 23 15 1 0.865234 0.306396 -27 23 16 1 0.867188 0.364502 -27 23 17 1 0.869629 0.440186 -27 23 18 1 0.871582 0.515137 -27 23 19 1 0.872559 0.588379 -27 23 20 1 0.871094 0.656738 -27 23 21 1 0.867188 0.72168 -27 23 22 1 0.859863 0.781738 -27 23 23 1 0.851074 0.837402 -27 23 24 1 0.84375 0.891113 -27 23 25 1 0.839844 0.945801 -27 23 26 1 0.834961 0.994629 -27 23 27 1 0.817871 1 -27 23 28 1 0.794434 1 -27 23 29 0.97998 0.764648 1 -27 23 30 0.913574 0.731934 1 -27 23 31 0.842773 0.697266 1 -27 24 0 1 0.912109 0.325439 -27 24 1 1 0.912109 0.325439 -27 24 2 1 0.912109 0.325439 -27 24 3 1 0.912109 0.325439 -27 24 4 1 0.912109 0.325439 -27 24 5 1 0.912109 0.325439 -27 24 6 1 0.912109 0.325439 -27 24 7 1 0.912109 0.325439 -27 24 8 1 0.912109 0.325439 -27 24 9 1 0.912109 0.325684 -27 24 10 1 0.912109 0.325684 -27 24 11 1 0.912109 0.325684 -27 24 12 1 0.912109 0.325684 -27 24 13 1 0.912598 0.325684 -27 24 14 1 0.913086 0.325684 -27 24 15 1 0.913574 0.325928 -27 24 16 1 0.915527 0.371826 -27 24 17 1 0.918457 0.445557 -27 24 18 1 0.920898 0.519531 -27 24 19 1 0.922363 0.591797 -27 24 20 1 0.921875 0.660156 -27 24 21 1 0.918945 0.724121 -27 24 22 1 0.912598 0.783203 -27 24 23 1 0.903809 0.835449 -27 24 24 1 0.892578 0.883789 -27 24 25 1 0.883301 0.935547 -27 24 26 1 0.876953 0.986328 -27 24 27 1 0.860352 1 -27 24 28 1 0.835449 1 -27 24 29 0.964844 0.804199 1 -27 24 30 0.899902 0.769531 1 -27 24 31 0.830078 0.733398 1 -27 25 0 1 0.958496 0.334473 -27 25 1 1 0.958496 0.334473 -27 25 2 1 0.958496 0.334473 -27 25 3 1 0.958496 0.334473 -27 25 4 1 0.958496 0.334473 -27 25 5 1 0.958496 0.334473 -27 25 6 1 0.958496 0.334473 -27 25 7 1 0.958496 0.334473 -27 25 8 1 0.958496 0.334473 -27 25 9 1 0.958496 0.334473 -27 25 10 1 0.958496 0.334473 -27 25 11 1 0.958496 0.334473 -27 25 12 1 0.958496 0.334473 -27 25 13 1 0.958496 0.334473 -27 25 14 1 0.958984 0.334473 -27 25 15 1 0.959473 0.334473 -27 25 16 1 0.960938 0.369629 -27 25 17 1 0.964355 0.442871 -27 25 18 1 0.967285 0.516602 -27 25 19 1 0.969727 0.588867 -27 25 20 1 0.970215 0.657227 -27 25 21 1 0.968262 0.722168 -27 25 22 1 0.963379 0.781738 -27 25 23 1 0.955078 0.833984 -27 25 24 1 0.944336 0.879395 -27 25 25 1 0.930664 0.925293 -27 25 26 1 0.919434 0.975098 -27 25 27 1 0.90332 1 -27 25 28 1 0.87793 1 -27 25 29 0.945801 0.845215 1 -27 25 30 0.882324 0.80957 1 -27 25 31 0.814941 0.771973 1 -27 26 0 1 1 0.333984 -27 26 1 1 1 0.333984 -27 26 2 1 1 0.333984 -27 26 3 1 1 0.333984 -27 26 4 1 1 0.333984 -27 26 5 1 1 0.333984 -27 26 6 1 1 0.333984 -27 26 7 1 1 0.333984 -27 26 8 1 1 0.333984 -27 26 9 1 1 0.333984 -27 26 10 1 1 0.333984 -27 26 11 1 1 0.33374 -27 26 12 1 1 0.33374 -27 26 13 1 1 0.33374 -27 26 14 1 1 0.33374 -27 26 15 1 1 0.33374 -27 26 16 1 1 0.357178 -27 26 17 1 1 0.431396 -27 26 18 1 1 0.505371 -27 26 19 1 1 0.577637 -27 26 20 1 1 0.646484 -27 26 21 1 1 0.711914 -27 26 22 1 1 0.772461 -27 26 23 1 1 0.826172 -27 26 24 1 0.994629 0.873535 -27 26 25 1 0.981445 0.918457 -27 26 26 1 0.963867 0.961426 -27 26 27 1 0.947266 1 -27 26 28 0.977539 0.92041 1 -27 26 29 0.922363 0.887207 1 -27 26 30 0.861816 0.851562 1 -27 26 31 0.796875 0.813965 1 -27 27 0 1 1 0.32666 -27 27 1 1 1 0.32666 -27 27 2 1 1 0.32666 -27 27 3 1 1 0.32666 -27 27 4 1 1 0.32666 -27 27 5 1 1 0.32666 -27 27 6 1 1 0.32666 -27 27 7 1 1 0.32666 -27 27 8 1 1 0.32666 -27 27 9 1 1 0.32666 -27 27 10 1 1 0.32666 -27 27 11 1 1 0.32666 -27 27 12 1 1 0.32666 -27 27 13 1 1 0.32666 -27 27 14 1 1 0.32666 -27 27 15 1 1 0.32666 -27 27 16 1 1 0.336914 -27 27 17 1 1 0.412354 -27 27 18 1 1 0.487061 -27 27 19 1 1 0.55957 -27 27 20 1 1 0.62793 -27 27 21 1 1 0.693359 -27 27 22 1 1 0.754395 -27 27 23 1 1 0.809082 -27 27 24 1 1 0.857422 -27 27 25 1 1 0.904297 -27 27 26 1 1 0.949219 -27 27 27 0.990723 0.990723 0.990723 -27 27 28 0.946777 0.963867 1 -27 27 29 0.895508 0.932129 1 -27 27 30 0.838867 0.897461 1 -27 27 31 0.775879 0.859375 1 -27 28 0 1 1 0.316406 -27 28 1 1 1 0.316406 -27 28 2 1 1 0.316406 -27 28 3 1 1 0.316406 -27 28 4 1 1 0.316406 -27 28 5 1 1 0.316406 -27 28 6 1 1 0.316406 -27 28 7 1 1 0.316406 -27 28 8 1 1 0.316406 -27 28 9 1 1 0.316406 -27 28 10 1 1 0.316406 -27 28 11 1 1 0.316406 -27 28 12 1 1 0.316406 -27 28 13 1 1 0.316406 -27 28 14 1 1 0.316406 -27 28 15 1 1 0.316406 -27 28 16 1 1 0.316406 -27 28 17 1 1 0.388916 -27 28 18 1 1 0.464111 -27 28 19 1 1 0.536133 -27 28 20 1 1 0.604004 -27 28 21 1 1 0.668945 -27 28 22 1 1 0.72998 -27 28 23 1 1 0.78418 -27 28 24 1 1 0.833008 -27 28 25 1 1 0.880859 -27 28 26 0.981934 1 0.926758 -27 28 27 0.950684 1 0.971191 -27 28 28 0.913086 1 1 -27 28 29 0.866211 0.981445 1 -27 28 30 0.811035 0.945801 1 -27 28 31 0.749512 0.907227 1 -27 29 0 1 1 0.304688 -27 29 1 1 1 0.304688 -27 29 2 1 1 0.304688 -27 29 3 1 1 0.304688 -27 29 4 1 1 0.304688 -27 29 5 1 1 0.304688 -27 29 6 1 1 0.304688 -27 29 7 1 1 0.304688 -27 29 8 1 1 0.304688 -27 29 9 1 1 0.304688 -27 29 10 1 1 0.304688 -27 29 11 1 1 0.304688 -27 29 12 1 1 0.304443 -27 29 13 1 1 0.304443 -27 29 14 1 1 0.304443 -27 29 15 1 1 0.304443 -27 29 16 1 1 0.304443 -27 29 17 1 1 0.361328 -27 29 18 1 1 0.437256 -27 29 19 1 1 0.508789 -27 29 20 1 1 0.576172 -27 29 21 1 1 0.640625 -27 29 22 0.994629 1 0.700684 -27 29 23 0.983398 1 0.754883 -27 29 24 0.969727 1 0.803711 -27 29 25 0.952148 1 0.852539 -27 29 26 0.929199 1 0.900391 -27 29 27 0.901367 1 0.947266 -27 29 28 0.867676 1 0.991211 -27 29 29 0.826172 1 1 -27 29 30 0.775879 0.995605 1 -27 29 31 0.716797 0.95752 1 -27 30 0 0.944824 1 0.29126 -27 30 1 0.944824 1 0.29126 -27 30 2 0.944824 1 0.29126 -27 30 3 0.944824 1 0.29126 -27 30 4 0.944824 1 0.29126 -27 30 5 0.944824 1 0.29126 -27 30 6 0.944824 1 0.29126 -27 30 7 0.944824 1 0.29126 -27 30 8 0.944824 1 0.29126 -27 30 9 0.944824 1 0.29126 -27 30 10 0.944824 1 0.29126 -27 30 11 0.944824 1 0.29126 -27 30 12 0.944824 1 0.29126 -27 30 13 0.944824 1 0.29126 -27 30 14 0.944824 1 0.29126 -27 30 15 0.944336 1 0.29126 -27 30 16 0.944336 1 0.29126 -27 30 17 0.943848 1 0.330078 -27 30 18 0.942871 1 0.407227 -27 30 19 0.940918 1 0.479004 -27 30 20 0.9375 1 0.54541 -27 30 21 0.932129 1 0.608887 -27 30 22 0.924316 1 0.668457 -27 30 23 0.915039 1 0.722168 -27 30 24 0.90332 1 0.771484 -27 30 25 0.887695 1 0.820801 -27 30 26 0.868164 1 0.870117 -27 30 27 0.843262 1 0.918457 -27 30 28 0.812012 1 0.964844 -27 30 29 0.773926 1 1 -27 30 30 0.728027 1 1 -27 30 31 0.67334 1 1 -27 31 0 0.865723 1 0.2771 -27 31 1 0.865723 1 0.2771 -27 31 2 0.865723 1 0.2771 -27 31 3 0.865723 1 0.2771 -27 31 4 0.865723 1 0.2771 -27 31 5 0.865723 1 0.2771 -27 31 6 0.865723 1 0.2771 -27 31 7 0.865723 1 0.2771 -27 31 8 0.865723 1 0.2771 -27 31 9 0.865723 1 0.2771 -27 31 10 0.865723 1 0.2771 -27 31 11 0.865723 1 0.2771 -27 31 12 0.865723 1 0.2771 -27 31 13 0.865723 1 0.2771 -27 31 14 0.865723 1 0.2771 -27 31 15 0.865723 1 0.2771 -27 31 16 0.865723 1 0.2771 -27 31 17 0.865234 1 0.294189 -27 31 18 0.86377 1 0.374268 -27 31 19 0.861816 1 0.446289 -27 31 20 0.858398 1 0.512207 -27 31 21 0.853027 1 0.574707 -27 31 22 0.846191 1 0.633301 -27 31 23 0.837891 1 0.686523 -27 31 24 0.827148 1 0.735352 -27 31 25 0.813965 1 0.785156 -27 31 26 0.796387 1 0.835449 -27 31 27 0.773926 1 0.885254 -27 31 28 0.745605 1 0.933594 -27 31 29 0.709961 1 0.979004 -27 31 30 0.666992 1 1 -27 31 31 0.614258 1 1 -28 0 0 1 0 0.0759888 -28 0 1 1 0 0.0759888 -28 0 2 1 0 0.0759888 -28 0 3 1 0 0.0759277 -28 0 4 1 0 0.0759277 -28 0 5 1 0 0.0759277 -28 0 6 1 0 0.0759277 -28 0 7 1 0 0.0759277 -28 0 8 1 0 0.0758667 -28 0 9 1 0 0.0758057 -28 0 10 1 0 0.0756226 -28 0 11 1 0 0.0753784 -28 0 12 1 0 0.0748901 -28 0 13 1 0 0.0740967 -28 0 14 1 0 0.0728149 -28 0 15 1 0 0.071167 -28 0 16 1 0 0.0697021 -28 0 17 1 0 0.271973 -28 0 18 1 0 0.403809 -28 0 19 1 0 0.509766 -28 0 20 1 0 0.599609 -28 0 21 1 0 0.686035 -28 0 22 1 0.0726929 0.765137 -28 0 23 1 0.240967 0.833008 -28 0 24 1 0.314941 0.88916 -28 0 25 1 0.364014 0.939941 -28 0 26 1 0.389648 0.985352 -28 0 27 1 0.395752 1 -28 0 28 1 0.393311 1 -28 0 29 1 0.388916 1 -28 0 30 1 0.383057 1 -28 0 31 0.977539 0.375488 1 -28 1 0 1 0 0.0759277 -28 1 1 1 0 0.0759277 -28 1 2 1 0 0.0759277 -28 1 3 1 0 0.0759277 -28 1 4 1 0 0.0759277 -28 1 5 1 0 0.0759277 -28 1 6 1 0 0.0759277 -28 1 7 1 0 0.0759277 -28 1 8 1 0 0.0758667 -28 1 9 1 0 0.0758057 -28 1 10 1 0 0.0756226 -28 1 11 1 0 0.0753174 -28 1 12 1 0 0.0748901 -28 1 13 1 0 0.0740967 -28 1 14 1 0 0.0727539 -28 1 15 1 0 0.071167 -28 1 16 1 0 0.0697021 -28 1 17 1 0 0.271973 -28 1 18 1 0 0.403809 -28 1 19 1 0 0.509766 -28 1 20 1 0 0.599609 -28 1 21 1 0 0.686035 -28 1 22 1 0.0728149 0.765137 -28 1 23 1 0.240967 0.833008 -28 1 24 1 0.314941 0.88916 -28 1 25 1 0.364014 0.939941 -28 1 26 1 0.389648 0.985352 -28 1 27 1 0.395752 1 -28 1 28 1 0.393311 1 -28 1 29 1 0.38916 1 -28 1 30 1 0.383057 1 -28 1 31 0.977539 0.375488 1 -28 2 0 1 0 0.0759277 -28 2 1 1 0 0.0759277 -28 2 2 1 0 0.0759277 -28 2 3 1 0 0.0759277 -28 2 4 1 0 0.0759277 -28 2 5 1 0 0.0759277 -28 2 6 1 0 0.0759277 -28 2 7 1 0 0.0758667 -28 2 8 1 0 0.0758667 -28 2 9 1 0 0.0757446 -28 2 10 1 0 0.0756226 -28 2 11 1 0 0.0753174 -28 2 12 1 0 0.0748291 -28 2 13 1 0 0.0740356 -28 2 14 1 0 0.0727539 -28 2 15 1 0 0.071167 -28 2 16 1 0 0.0696411 -28 2 17 1 0 0.271973 -28 2 18 1 0 0.403809 -28 2 19 1 0 0.509766 -28 2 20 1 0 0.599609 -28 2 21 1 0 0.686035 -28 2 22 1 0.0730591 0.765137 -28 2 23 1 0.240967 0.833008 -28 2 24 1 0.315186 0.88916 -28 2 25 1 0.364014 0.939941 -28 2 26 1 0.389648 0.985352 -28 2 27 1 0.395752 1 -28 2 28 1 0.393311 1 -28 2 29 1 0.38916 1 -28 2 30 1 0.383057 1 -28 2 31 0.977539 0.375488 1 -28 3 0 1 0 0.0759277 -28 3 1 1 0 0.0759277 -28 3 2 1 0 0.0759277 -28 3 3 1 0 0.0759277 -28 3 4 1 0 0.0759277 -28 3 5 1 0 0.0759277 -28 3 6 1 0 0.0759277 -28 3 7 1 0 0.0758667 -28 3 8 1 0 0.0758057 -28 3 9 1 0 0.0757446 -28 3 10 1 0 0.0755615 -28 3 11 1 0 0.0753174 -28 3 12 1 0 0.0748291 -28 3 13 1 0 0.0740356 -28 3 14 1 0 0.0727539 -28 3 15 1 0 0.071167 -28 3 16 1 0 0.0696411 -28 3 17 1 0 0.271973 -28 3 18 1 0 0.403809 -28 3 19 1 0 0.509766 -28 3 20 1 0 0.599609 -28 3 21 1 0 0.686035 -28 3 22 1 0.0734863 0.765137 -28 3 23 1 0.241089 0.833008 -28 3 24 1 0.315186 0.88916 -28 3 25 1 0.364014 0.939941 -28 3 26 1 0.389648 0.985352 -28 3 27 1 0.395996 1 -28 3 28 1 0.393555 1 -28 3 29 1 0.38916 1 -28 3 30 1 0.383057 1 -28 3 31 0.977539 0.375488 1 -28 4 0 1 0 0.0758667 -28 4 1 1 0 0.0758667 -28 4 2 1 0 0.0758667 -28 4 3 1 0 0.0758667 -28 4 4 1 0 0.0758667 -28 4 5 1 0 0.0758667 -28 4 6 1 0 0.0758667 -28 4 7 1 0 0.0758057 -28 4 8 1 0 0.0758057 -28 4 9 1 0 0.0756836 -28 4 10 1 0 0.0755615 -28 4 11 1 0 0.0752563 -28 4 12 1 0 0.0747681 -28 4 13 1 0 0.0739746 -28 4 14 1 0 0.0726929 -28 4 15 1 0 0.071106 -28 4 16 1 0 0.0695801 -28 4 17 1 0 0.271973 -28 4 18 1 0 0.403809 -28 4 19 1 0 0.509766 -28 4 20 1 0 0.599609 -28 4 21 1 0 0.686035 -28 4 22 1 0.0742798 0.765137 -28 4 23 1 0.241211 0.833008 -28 4 24 1 0.315186 0.88916 -28 4 25 1 0.364014 0.939941 -28 4 26 1 0.389648 0.985352 -28 4 27 1 0.395996 1 -28 4 28 1 0.393555 1 -28 4 29 1 0.38916 1 -28 4 30 1 0.383057 1 -28 4 31 0.977539 0.375488 1 -28 5 0 1 0 0.0758057 -28 5 1 1 0 0.0758057 -28 5 2 1 0 0.0758057 -28 5 3 1 0 0.0758057 -28 5 4 1 0 0.0758057 -28 5 5 1 0 0.0758057 -28 5 6 1 0 0.0758057 -28 5 7 1 0 0.0757446 -28 5 8 1 0 0.0757446 -28 5 9 1 0 0.0756226 -28 5 10 1 0 0.0755005 -28 5 11 1 0 0.0751953 -28 5 12 1 0 0.074707 -28 5 13 1 0 0.0739136 -28 5 14 1 0 0.0726318 -28 5 15 1 0 0.0710449 -28 5 16 1 0 0.069519 -28 5 17 1 0 0.271973 -28 5 18 1 0 0.403809 -28 5 19 1 0 0.509766 -28 5 20 1 0 0.599609 -28 5 21 1 0 0.686035 -28 5 22 1 0.0757446 0.765137 -28 5 23 1 0.241333 0.833008 -28 5 24 1 0.31543 0.88916 -28 5 25 1 0.364258 0.939941 -28 5 26 1 0.389893 0.985352 -28 5 27 1 0.395996 1 -28 5 28 1 0.393555 1 -28 5 29 1 0.38916 1 -28 5 30 1 0.383057 1 -28 5 31 0.977051 0.375732 1 -28 6 0 1 0 0.0756836 -28 6 1 1 0 0.0756836 -28 6 2 1 0 0.0756836 -28 6 3 1 0 0.0756836 -28 6 4 1 0 0.0756836 -28 6 5 1 0 0.0756226 -28 6 6 1 0 0.0756226 -28 6 7 1 0 0.0756226 -28 6 8 1 0 0.0755615 -28 6 9 1 0 0.0755005 -28 6 10 1 0 0.0753174 -28 6 11 1 0 0.0750732 -28 6 12 1 0 0.074585 -28 6 13 1 0 0.0737915 -28 6 14 1 0 0.0724487 -28 6 15 1 0 0.0708618 -28 6 16 1 0 0.0693359 -28 6 17 1 0 0.271973 -28 6 18 1 0 0.403809 -28 6 19 1 0 0.509766 -28 6 20 1 0 0.599609 -28 6 21 1 0 0.686035 -28 6 22 1 0.0784302 0.765137 -28 6 23 1 0.241821 0.833008 -28 6 24 1 0.315674 0.88916 -28 6 25 1 0.364502 0.939941 -28 6 26 1 0.390137 0.985352 -28 6 27 1 0.39624 1 -28 6 28 1 0.393799 1 -28 6 29 1 0.389404 1 -28 6 30 1 0.383301 1 -28 6 31 0.977051 0.375732 1 -28 7 0 1 0 0.0753784 -28 7 1 1 0 0.0753784 -28 7 2 1 0 0.0753784 -28 7 3 1 0 0.0753784 -28 7 4 1 0 0.0753784 -28 7 5 1 0 0.0753784 -28 7 6 1 0 0.0753784 -28 7 7 1 0 0.0753174 -28 7 8 1 0 0.0752563 -28 7 9 1 0 0.0751953 -28 7 10 1 0 0.0750122 -28 7 11 1 0 0.0747681 -28 7 12 1 0 0.0742798 -28 7 13 1 0 0.0734863 -28 7 14 1 0 0.0721436 -28 7 15 1 0 0.0705566 -28 7 16 1 0 0.0690308 -28 7 17 1 0 0.271973 -28 7 18 1 0 0.403564 -28 7 19 1 0 0.509766 -28 7 20 1 0 0.599609 -28 7 21 1 0 0.686035 -28 7 22 1 0.083313 0.765137 -28 7 23 1 0.242554 0.833008 -28 7 24 1 0.316162 0.88916 -28 7 25 1 0.364746 0.939941 -28 7 26 1 0.390381 0.985352 -28 7 27 1 0.396484 1 -28 7 28 1 0.394043 1 -28 7 29 1 0.389648 1 -28 7 30 1 0.383545 1 -28 7 31 0.977051 0.375977 1 -28 8 0 1 0 0.0748291 -28 8 1 1 0 0.0748291 -28 8 2 1 0 0.0748291 -28 8 3 1 0 0.0748291 -28 8 4 1 0 0.0748291 -28 8 5 1 0 0.0748291 -28 8 6 1 0 0.0747681 -28 8 7 1 0 0.0747681 -28 8 8 1 0 0.074707 -28 8 9 1 0 0.074646 -28 8 10 1 0 0.0744629 -28 8 11 1 0 0.0741577 -28 8 12 1 0 0.0736694 -28 8 13 1 0 0.072876 -28 8 14 1 0 0.0715332 -28 8 15 1 0 0.0698853 -28 8 16 1 0 0.0683594 -28 8 17 1 0 0.271973 -28 8 18 1 0 0.403564 -28 8 19 1 0 0.509766 -28 8 20 1 0 0.599609 -28 8 21 1 0 0.686035 -28 8 22 1 0.0916748 0.765137 -28 8 23 1 0.244141 0.833008 -28 8 24 1 0.317139 0.88916 -28 8 25 1 0.365723 0.939941 -28 8 26 1 0.391113 0.985352 -28 8 27 1 0.397217 1 -28 8 28 1 0.394531 1 -28 8 29 1 0.390137 1 -28 8 30 1 0.384033 1 -28 8 31 0.977051 0.376465 1 -28 9 0 1 0 0.0737305 -28 9 1 1 0 0.0737305 -28 9 2 1 0 0.0737305 -28 9 3 1 0 0.0737305 -28 9 4 1 0 0.0737305 -28 9 5 1 0 0.0737305 -28 9 6 1 0 0.0736694 -28 9 7 1 0 0.0736694 -28 9 8 1 0 0.0736084 -28 9 9 1 0 0.0735474 -28 9 10 1 0 0.0733643 -28 9 11 1 0 0.0730591 -28 9 12 1 0 0.0725708 -28 9 13 1 0 0.0717163 -28 9 14 1 0 0.0703735 -28 9 15 1 0 0.0686646 -28 9 16 1 0 0.0671387 -28 9 17 1 0 0.271973 -28 9 18 1 0 0.403564 -28 9 19 1 0 0.509766 -28 9 20 1 0 0.599609 -28 9 21 1 0 0.686035 -28 9 22 1 0.10498 0.765137 -28 9 23 1 0.247192 0.833008 -28 9 24 1 0.319092 0.88916 -28 9 25 1 0.367188 0.939941 -28 9 26 1 0.392334 0.985352 -28 9 27 1 0.398438 1 -28 9 28 1 0.395752 1 -28 9 29 1 0.391357 1 -28 9 30 1 0.38501 1 -28 9 31 0.977051 0.377441 1 -28 10 0 1 0 0.0716553 -28 10 1 1 0 0.0716553 -28 10 2 1 0 0.0716553 -28 10 3 1 0 0.0716553 -28 10 4 1 0 0.0716553 -28 10 5 1 0 0.0716553 -28 10 6 1 0 0.0716553 -28 10 7 1 0 0.0715942 -28 10 8 1 0 0.0715332 -28 10 9 1 0 0.0714722 -28 10 10 1 0 0.0712891 -28 10 11 1 0 0.0709839 -28 10 12 1 0 0.0704346 -28 10 13 1 0 0.0695801 -28 10 14 1 0 0.0681152 -28 10 15 1 0 0.0663452 -28 10 16 1 0 0.0647583 -28 10 17 1 0 0.271729 -28 10 18 1 0 0.403564 -28 10 19 1 0 0.509766 -28 10 20 1 0 0.599609 -28 10 21 1 0 0.686035 -28 10 22 1 0.123962 0.765137 -28 10 23 1 0.252441 0.833008 -28 10 24 1 0.32251 0.88916 -28 10 25 1 0.369873 0.939941 -28 10 26 1 0.394775 0.985352 -28 10 27 1 0.400635 1 -28 10 28 1 0.397949 1 -28 10 29 1 0.393066 1 -28 10 30 1 0.386719 1 -28 10 31 0.977051 0.378906 1 -28 11 0 1 0 0.067749 -28 11 1 1 0 0.067749 -28 11 2 1 0 0.067749 -28 11 3 1 0 0.067749 -28 11 4 1 0 0.067749 -28 11 5 1 0 0.067749 -28 11 6 1 0 0.067749 -28 11 7 1 0 0.067749 -28 11 8 1 0 0.067688 -28 11 9 1 0 0.0675659 -28 11 10 1 0 0.0673828 -28 11 11 1 0 0.0670166 -28 11 12 1 0 0.0664673 -28 11 13 1 0 0.0654907 -28 11 14 1 0 0.0639038 -28 11 15 1 0 0.0619202 -28 11 16 1 0 0.0601807 -28 11 17 1 0 0.271729 -28 11 18 1 0 0.40332 -28 11 19 1 0 0.509766 -28 11 20 1 0 0.599609 -28 11 21 1 0 0.685547 -28 11 22 1 0.14917 0.765137 -28 11 23 1 0.26123 0.83252 -28 11 24 1 0.328369 0.88916 -28 11 25 1 0.374512 0.939941 -28 11 26 1 0.398926 0.985352 -28 11 27 1 0.404541 1 -28 11 28 1 0.401611 1 -28 11 29 1 0.396484 1 -28 11 30 1 0.389893 1 -28 11 31 0.977051 0.381836 1 -28 12 0 1 0 0.0601501 -28 12 1 1 0 0.0601501 -28 12 2 1 0 0.0601501 -28 12 3 1 0 0.0601501 -28 12 4 1 0 0.0601501 -28 12 5 1 0 0.0601501 -28 12 6 1 0 0.0601196 -28 12 7 1 0 0.0600891 -28 12 8 1 0 0.0600281 -28 12 9 1 0 0.059906 -28 12 10 1 0 0.0596619 -28 12 11 1 0 0.0592651 -28 12 12 1 0 0.0585632 -28 12 13 1 0 0.057373 -28 12 14 1 0 0.0553894 -28 12 15 1 0 0.0528564 -28 12 16 1 0 0.0507202 -28 12 17 1 0 0.271484 -28 12 18 1 0 0.403076 -28 12 19 1 0 0.509766 -28 12 20 1 0 0.599609 -28 12 21 1 0 0.685547 -28 12 22 1 0.180908 0.764648 -28 12 23 1 0.275391 0.83252 -28 12 24 1 0.338135 0.88916 -28 12 25 1 0.382324 0.939941 -28 12 26 1 0.406006 0.985352 -28 12 27 1 0.410889 1 -28 12 28 1 0.407471 1 -28 12 29 1 0.4021 1 -28 12 30 1 0.39502 1 -28 12 31 0.976562 0.386475 1 -28 13 0 1 0 0.0423584 -28 13 1 1 0 0.0423584 -28 13 2 1 0 0.0423584 -28 13 3 1 0 0.0423279 -28 13 4 1 0 0.0423279 -28 13 5 1 0 0.0423279 -28 13 6 1 0 0.0422974 -28 13 7 1 0 0.0422363 -28 13 8 1 0 0.0421143 -28 13 9 1 0 0.0419006 -28 13 10 1 0 0.0414734 -28 13 11 1 0 0.040741 -28 13 12 1 0 0.0394287 -28 13 13 1 0 0.0371094 -28 13 14 1 0 0.0328369 -28 13 15 1 0 0.0261841 -28 13 16 1 0 0.0189056 -28 13 17 1 0 0.271484 -28 13 18 1 0 0.402588 -28 13 19 1 0 0.509277 -28 13 20 1 0 0.599121 -28 13 21 1 0.112061 0.685059 -28 13 22 1 0.21936 0.76416 -28 13 23 1 0.296143 0.83252 -28 13 24 1 0.353271 0.88916 -28 13 25 1 0.394775 0.939941 -28 13 26 1 0.416992 0.985352 -28 13 27 1 0.421387 1 -28 13 28 1 0.417236 1 -28 13 29 1 0.411133 1 -28 13 30 1 0.40332 1 -28 13 31 0.976074 0.393799 1 -28 14 0 1 0.156128 0 -28 14 1 1 0.156128 0 -28 14 2 1 0.156128 0 -28 14 3 1 0.156128 0 -28 14 4 1 0.15625 0 -28 14 5 1 0.15625 0 -28 14 6 1 0.156372 0 -28 14 7 1 0.156494 0 -28 14 8 1 0.156738 0 -28 14 9 1 0.157349 0 -28 14 10 1 0.158447 0 -28 14 11 1 0.160278 0 -28 14 12 1 0.16333 0 -28 14 13 1 0.168091 0 -28 14 14 1 0.175293 0 -28 14 15 1 0.183228 0 -28 14 16 1 0.187744 0 -28 14 17 1 0.179565 0.271484 -28 14 18 1 0.169067 0.4021 -28 14 19 1 0.174927 0.508301 -28 14 20 1 0.174927 0.599121 -28 14 21 1 0.205322 0.68457 -28 14 22 1 0.264648 0.763672 -28 14 23 1 0.325195 0.832031 -28 14 24 1 0.375244 0.888672 -28 14 25 1 0.41333 0.939941 -28 14 26 1 0.433594 0.985352 -28 14 27 1 0.436768 1 -28 14 28 1 0.431885 1 -28 14 29 1 0.424805 1 -28 14 30 1 0.415771 1 -28 14 31 0.975586 0.405273 1 -28 15 0 1 0.25708 0 -28 15 1 1 0.25708 0 -28 15 2 1 0.25708 0 -28 15 3 1 0.25708 0 -28 15 4 1 0.25708 0 -28 15 5 1 0.25708 0 -28 15 6 1 0.25708 0 -28 15 7 1 0.25708 0 -28 15 8 1 0.257324 0 -28 15 9 1 0.257568 0 -28 15 10 1 0.258057 0 -28 15 11 1 0.259033 0 -28 15 12 1 0.260254 0 -28 15 13 1 0.262695 0 -28 15 14 1 0.266357 0 -28 15 15 1 0.270508 0 -28 15 16 1 0.272217 0 -28 15 17 1 0.267578 0.272217 -28 15 18 1 0.261963 0.401611 -28 15 19 1 0.263184 0.507324 -28 15 20 1 0.265869 0.598633 -28 15 21 1 0.279297 0.683594 -28 15 22 1 0.31665 0.762695 -28 15 23 1 0.363037 0.831055 -28 15 24 1 0.405518 0.888184 -28 15 25 1 0.439209 0.939941 -28 15 26 1 0.457275 0.985352 -28 15 27 1 0.458984 1 -28 15 28 1 0.452881 1 -28 15 29 1 0.444336 1 -28 15 30 1 0.433838 1 -28 15 31 0.974121 0.421875 1 -28 16 0 1 0.341064 0 -28 16 1 1 0.341064 0 -28 16 2 1 0.341064 0 -28 16 3 1 0.341064 0 -28 16 4 1 0.341064 0 -28 16 5 1 0.341064 0 -28 16 6 1 0.341064 0 -28 16 7 1 0.341064 0 -28 16 8 1 0.341064 0 -28 16 9 1 0.341309 0 -28 16 10 1 0.341553 0 -28 16 11 1 0.342041 0 -28 16 12 1 0.343018 0 -28 16 13 1 0.344482 0 -28 16 14 1 0.346924 0 -28 16 15 1 0.349854 0 -28 16 16 1 0.350342 0 -28 16 17 1 0.347168 0.274902 -28 16 18 1 0.343262 0.401611 -28 16 19 1 0.342773 0.505859 -28 16 20 1 0.346924 0.598633 -28 16 21 1 0.352051 0.682617 -28 16 22 1 0.375244 0.76123 -28 16 23 1 0.409912 0.830078 -28 16 24 1 0.44458 0.887695 -28 16 25 1 0.473389 0.939453 -28 16 26 1 0.48877 0.984863 -28 16 27 1 0.489014 1 -28 16 28 1 0.481201 1 -28 16 29 1 0.470947 1 -28 16 30 1 0.458496 1 -28 16 31 0.972168 0.44458 1 -28 17 0 1 0.420898 0 -28 17 1 1 0.420898 0 -28 17 2 1 0.420898 0 -28 17 3 1 0.420898 0 -28 17 4 1 0.420898 0 -28 17 5 1 0.420898 0 -28 17 6 1 0.420898 0 -28 17 7 1 0.420898 0 -28 17 8 1 0.420898 0 -28 17 9 1 0.421143 0 -28 17 10 1 0.421387 0 -28 17 11 1 0.421631 0 -28 17 12 1 0.422363 0 -28 17 13 1 0.42334 0 -28 17 14 1 0.425049 0 -28 17 15 1 0.427246 0 -28 17 16 1 0.427246 0 -28 17 17 1 0.425049 0.280762 -28 17 18 1 0.422363 0.40332 -28 17 19 1 0.420654 0.504883 -28 17 20 1 0.424072 0.597656 -28 17 21 1 0.426025 0.680664 -28 17 22 1 0.439209 0.759277 -28 17 23 1 0.463379 0.828125 -28 17 24 1 0.490723 0.88623 -28 17 25 1 0.515137 0.938477 -28 17 26 1 0.527832 0.984863 -28 17 27 1 0.526367 1 -28 17 28 1 0.516602 1 -28 17 29 1 0.504395 1 -28 17 30 1 0.489746 1 -28 17 31 0.969727 0.473145 1 -28 18 0 1 0.498291 0 -28 18 1 1 0.498291 0 -28 18 2 1 0.498291 0 -28 18 3 1 0.498291 0 -28 18 4 1 0.498535 0 -28 18 5 1 0.498535 0 -28 18 6 1 0.498535 0 -28 18 7 1 0.498535 0 -28 18 8 1 0.498535 0 -28 18 9 1 0.498535 0 -28 18 10 1 0.498779 0 -28 18 11 1 0.499023 0 -28 18 12 1 0.499512 0 -28 18 13 1 0.500488 0 -28 18 14 1 0.501465 0 -28 18 15 1 0.503418 0 -28 18 16 1 0.503418 0 -28 18 17 1 0.501953 0.291992 -28 18 18 1 0.5 0.407715 -28 18 19 1 0.498291 0.505371 -28 18 20 1 0.498291 0.595215 -28 18 21 1 0.500977 0.679688 -28 18 22 1 0.506348 0.756348 -28 18 23 1 0.521973 0.825195 -28 18 24 1 0.54248 0.884277 -28 18 25 1 0.562012 0.9375 -28 18 26 1 0.572266 0.983887 -28 18 27 1 0.569336 1 -28 18 28 1 0.557617 1 -28 18 29 1 0.543457 1 -28 18 30 1 0.526367 1 -28 18 31 0.966309 0.506836 1 -28 19 0 1 0.572754 0 -28 19 1 1 0.572754 0 -28 19 2 1 0.572754 0 -28 19 3 1 0.572754 0 -28 19 4 1 0.572754 0 -28 19 5 1 0.572754 0 -28 19 6 1 0.572754 0 -28 19 7 1 0.572754 0 -28 19 8 1 0.572754 0 -28 19 9 1 0.572754 0 -28 19 10 1 0.572754 0 -28 19 11 1 0.573242 0 -28 19 12 1 0.57373 0 -28 19 13 1 0.574219 0 -28 19 14 1 0.575195 0 -28 19 15 1 0.57666 0 -28 19 16 1 0.577148 0.144165 -28 19 17 1 0.57666 0.309326 -28 19 18 1 0.575684 0.41626 -28 19 19 1 0.574219 0.508789 -28 19 20 1 0.572754 0.594727 -28 19 21 1 0.57373 0.677246 -28 19 22 1 0.574707 0.75293 -28 19 23 1 0.58252 0.820801 -28 19 24 1 0.59668 0.880859 -28 19 25 1 0.611816 0.935059 -28 19 26 1 0.620117 0.982422 -28 19 27 1 0.615723 1 -28 19 28 1 0.602051 1 -28 19 29 1 0.585449 1 -28 19 30 1 0.565918 1 -28 19 31 0.961426 0.543945 1 -28 20 0 1 0.64209 0 -28 20 1 1 0.64209 0 -28 20 2 1 0.64209 0 -28 20 3 1 0.64209 0 -28 20 4 1 0.64209 0 -28 20 5 1 0.64209 0 -28 20 6 1 0.64209 0 -28 20 7 1 0.64209 0 -28 20 8 1 0.64209 0 -28 20 9 1 0.642578 0 -28 20 10 1 0.642578 0 -28 20 11 1 0.642578 0 -28 20 12 1 0.643066 0 -28 20 13 1 0.643555 0 -28 20 14 1 0.644531 0 -28 20 15 1 0.645508 0 -28 20 16 1 0.646484 0.205078 -28 20 17 1 0.647461 0.331543 -28 20 18 1 0.647461 0.428955 -28 20 19 1 0.646484 0.515625 -28 20 20 1 0.644531 0.596191 -28 20 21 1 0.64209 0.674805 -28 20 22 1 0.642578 0.75 -28 20 23 1 0.643066 0.815918 -28 20 24 1 0.650879 0.875977 -28 20 25 1 0.662598 0.931641 -28 20 26 1 0.668457 0.97998 -28 20 27 1 0.662598 1 -28 20 28 1 0.647949 1 -28 20 29 1 0.629395 1 -28 20 30 1 0.607422 1 -28 20 31 0.955566 0.58252 1 -28 21 0 1 0.708496 0.130127 -28 21 1 1 0.708496 0.130127 -28 21 2 1 0.708496 0.130127 -28 21 3 1 0.708496 0.130127 -28 21 4 1 0.708496 0.130127 -28 21 5 1 0.708496 0.130127 -28 21 6 1 0.708496 0.130127 -28 21 7 1 0.708496 0.130127 -28 21 8 1 0.708496 0.130127 -28 21 9 1 0.708496 0.130249 -28 21 10 1 0.708496 0.130493 -28 21 11 1 0.708984 0.130859 -28 21 12 1 0.708984 0.131348 -28 21 13 1 0.709473 0.132324 -28 21 14 1 0.709961 0.133667 -28 21 15 1 0.710938 0.135742 -28 21 16 1 0.712891 0.253174 -28 21 17 1 0.714355 0.356201 -28 21 18 1 0.714844 0.444824 -28 21 19 1 0.714844 0.525391 -28 21 20 1 0.713379 0.601074 -28 21 21 1 0.709961 0.674805 -28 21 22 1 0.707031 0.745605 -28 21 23 1 0.705078 0.811035 -28 21 24 1 0.706543 0.870117 -28 21 25 1 0.712891 0.926758 -28 21 26 1 0.717285 0.976562 -28 21 27 1 0.710449 1 -28 21 28 1 0.694336 1 -28 21 29 1 0.673828 1 -28 21 30 1 0.649414 1 -28 21 31 0.948242 0.622559 1 -28 22 0 1 0.77002 0.223999 -28 22 1 1 0.77002 0.223999 -28 22 2 1 0.77002 0.223999 -28 22 3 1 0.77002 0.223999 -28 22 4 1 0.77002 0.223999 -28 22 5 1 0.77002 0.223999 -28 22 6 1 0.77002 0.223999 -28 22 7 1 0.77002 0.223999 -28 22 8 1 0.77002 0.223999 -28 22 9 1 0.77002 0.223999 -28 22 10 1 0.77002 0.224121 -28 22 11 1 0.77002 0.224243 -28 22 12 1 0.77002 0.224487 -28 22 13 1 0.770508 0.224731 -28 22 14 1 0.770996 0.225342 -28 22 15 1 0.771973 0.226074 -28 22 16 1 0.773438 0.29126 -28 22 17 1 0.775879 0.379639 -28 22 18 1 0.777344 0.461182 -28 22 19 1 0.77832 0.537109 -28 22 20 1 0.777344 0.608887 -28 22 21 1 0.774414 0.677246 -28 22 22 1 0.769531 0.743652 -28 22 23 1 0.765137 0.805664 -28 22 24 1 0.761719 0.862793 -28 22 25 1 0.762695 0.919922 -28 22 26 1 0.764648 0.97168 -28 22 27 1 0.757324 1 -28 22 28 1 0.740234 1 -28 22 29 1 0.717773 1 -28 22 30 1 0.691406 1 -28 22 31 0.939941 0.662109 1 -28 23 0 1 0.824219 0.273926 -28 23 1 1 0.824219 0.273926 -28 23 2 1 0.824219 0.273926 -28 23 3 1 0.824219 0.273926 -28 23 4 1 0.824219 0.273926 -28 23 5 1 0.824219 0.273926 -28 23 6 1 0.824219 0.273926 -28 23 7 1 0.824219 0.273926 -28 23 8 1 0.824219 0.273926 -28 23 9 1 0.824219 0.273926 -28 23 10 1 0.824219 0.273926 -28 23 11 1 0.824219 0.27417 -28 23 12 1 0.824219 0.27417 -28 23 13 1 0.824707 0.274414 -28 23 14 1 0.825195 0.274658 -28 23 15 1 0.825684 0.275146 -28 23 16 1 0.827637 0.318604 -28 23 17 1 0.830078 0.398438 -28 23 18 1 0.83252 0.475098 -28 23 19 1 0.833984 0.547852 -28 23 20 1 0.833984 0.616699 -28 23 21 1 0.832031 0.682129 -28 23 22 1 0.827148 0.744141 -28 23 23 1 0.820801 0.801758 -28 23 24 1 0.814941 0.856445 -28 23 25 1 0.80957 0.912109 -28 23 26 1 0.809082 0.965332 -28 23 27 1 0.80127 1 -28 23 28 1 0.783203 1 -28 23 29 1 0.759766 1 -28 23 30 0.997559 0.731445 1 -28 23 31 0.930176 0.700195 1 -28 24 0 1 0.87207 0.305664 -28 24 1 1 0.87207 0.305664 -28 24 2 1 0.87207 0.305664 -28 24 3 1 0.87207 0.305664 -28 24 4 1 0.87207 0.305664 -28 24 5 1 0.87207 0.305664 -28 24 6 1 0.87207 0.305664 -28 24 7 1 0.87207 0.305664 -28 24 8 1 0.87207 0.305664 -28 24 9 1 0.87207 0.305664 -28 24 10 1 0.87207 0.305664 -28 24 11 1 0.87207 0.305664 -28 24 12 1 0.87207 0.305664 -28 24 13 1 0.872559 0.305908 -28 24 14 1 0.872559 0.305908 -28 24 15 1 0.873047 0.306152 -28 24 16 1 0.875 0.336182 -28 24 17 1 0.87793 0.410645 -28 24 18 1 0.880859 0.484131 -28 24 19 1 0.883301 0.555664 -28 24 20 1 0.883789 0.622559 -28 24 21 1 0.882812 0.686523 -28 24 22 1 0.878906 0.746094 -28 24 23 1 0.872559 0.800293 -28 24 24 1 0.864258 0.850586 -28 24 25 1 0.855957 0.903809 -28 24 26 1 0.850098 0.957031 -28 24 27 1 0.842285 1 -28 24 28 1 0.82373 1 -28 24 29 1 0.799316 1 -28 24 30 0.98584 0.769531 1 -28 24 31 0.918945 0.736328 1 -28 25 0 1 0.917969 0.325928 -28 25 1 1 0.917969 0.325928 -28 25 2 1 0.917969 0.325928 -28 25 3 1 0.917969 0.325928 -28 25 4 1 0.917969 0.325928 -28 25 5 1 0.917969 0.325928 -28 25 6 1 0.918457 0.325928 -28 25 7 1 0.918457 0.325928 -28 25 8 1 0.918457 0.325928 -28 25 9 1 0.918457 0.325928 -28 25 10 1 0.918457 0.325928 -28 25 11 1 0.918457 0.325928 -28 25 12 1 0.918457 0.325928 -28 25 13 1 0.918457 0.325928 -28 25 14 1 0.918945 0.326172 -28 25 15 1 0.919434 0.326172 -28 25 16 1 0.92041 0.344727 -28 25 17 1 0.923828 0.41626 -28 25 18 1 0.927246 0.487793 -28 25 19 1 0.930176 0.558105 -28 25 20 1 0.931641 0.624512 -28 25 21 1 0.931152 0.687988 -28 25 22 1 0.928711 0.746582 -28 25 23 1 0.92334 0.799316 -28 25 24 1 0.915039 0.84668 -28 25 25 1 0.904297 0.89502 -28 25 26 1 0.893555 0.946289 -28 25 27 1 0.884277 0.995117 -28 25 28 1 0.865723 1 -28 25 29 1 0.840332 1 -28 25 30 0.970703 0.809082 1 -28 25 31 0.905273 0.774414 1 -28 26 0 1 0.962891 0.335449 -28 26 1 1 0.962891 0.335449 -28 26 2 1 0.962891 0.335449 -28 26 3 1 0.962891 0.335449 -28 26 4 1 0.962891 0.335449 -28 26 5 1 0.962891 0.335449 -28 26 6 1 0.962891 0.335449 -28 26 7 1 0.962891 0.335449 -28 26 8 1 0.962891 0.335449 -28 26 9 1 0.962891 0.335449 -28 26 10 1 0.963379 0.335449 -28 26 11 1 0.963379 0.335449 -28 26 12 1 0.963379 0.335449 -28 26 13 1 0.963379 0.335449 -28 26 14 1 0.963379 0.335449 -28 26 15 1 0.963867 0.335693 -28 26 16 1 0.964844 0.342773 -28 26 17 1 0.967773 0.41333 -28 26 18 1 0.97168 0.484131 -28 26 19 1 0.974609 0.553223 -28 26 20 1 0.976562 0.619629 -28 26 21 1 0.977051 0.683105 -28 26 22 1 0.975586 0.742188 -28 26 23 1 0.971191 0.79541 -28 26 24 1 0.964355 0.842773 -28 26 25 1 0.95459 0.888672 -28 26 26 1 0.94043 0.935059 -28 26 27 1 0.927246 0.983398 -28 26 28 1 0.90918 1 -28 26 29 1 0.882812 1 -28 26 30 0.95166 0.850586 1 -28 26 31 0.888184 0.814941 1 -28 27 0 1 1 0.335205 -28 27 1 1 1 0.335205 -28 27 2 1 1 0.335205 -28 27 3 1 1 0.335205 -28 27 4 1 1 0.335205 -28 27 5 1 1 0.335205 -28 27 6 1 1 0.335205 -28 27 7 1 1 0.335205 -28 27 8 1 1 0.335205 -28 27 9 1 1 0.335205 -28 27 10 1 1 0.335205 -28 27 11 1 1 0.335205 -28 27 12 1 1 0.335205 -28 27 13 1 1 0.335205 -28 27 14 1 1 0.335205 -28 27 15 1 1 0.335205 -28 27 16 1 1 0.334961 -28 27 17 1 1 0.401367 -28 27 18 1 1 0.472168 -28 27 19 1 1 0.541016 -28 27 20 1 1 0.606934 -28 27 21 1 1 0.67041 -28 27 22 1 1 0.72998 -28 27 23 1 1 0.783691 -28 27 24 1 1 0.832031 -28 27 25 1 1 0.879395 -28 27 26 1 0.988281 0.924805 -28 27 27 1 0.971191 0.96875 -28 27 28 1 0.953125 1 -28 27 29 0.983398 0.925781 1 -28 27 30 0.928223 0.893066 1 -28 27 31 0.867676 0.857422 1 -28 28 0 1 1 0.327881 -28 28 1 1 1 0.327881 -28 28 2 1 1 0.327881 -28 28 3 1 1 0.327881 -28 28 4 1 1 0.327881 -28 28 5 1 1 0.327881 -28 28 6 1 1 0.327881 -28 28 7 1 1 0.327881 -28 28 8 1 1 0.327881 -28 28 9 1 1 0.327881 -28 28 10 1 1 0.327881 -28 28 11 1 1 0.327881 -28 28 12 1 1 0.327881 -28 28 13 1 1 0.327881 -28 28 14 1 1 0.327881 -28 28 15 1 1 0.327881 -28 28 16 1 1 0.327637 -28 28 17 1 1 0.381836 -28 28 18 1 1 0.453369 -28 28 19 1 1 0.522461 -28 28 20 1 1 0.588379 -28 28 21 1 1 0.651367 -28 28 22 1 1 0.710938 -28 28 23 1 1 0.764648 -28 28 24 1 1 0.812988 -28 28 25 1 1 0.861816 -28 28 26 1 1 0.90918 -28 28 27 1 1 0.95459 -28 28 28 0.996582 0.996582 0.996582 -28 28 29 0.952148 0.969238 1 -28 28 30 0.900879 0.937988 1 -28 28 31 0.843262 0.902344 1 -28 29 0 1 1 0.317627 -28 29 1 1 1 0.317627 -28 29 2 1 1 0.317627 -28 29 3 1 1 0.317627 -28 29 4 1 1 0.317627 -28 29 5 1 1 0.317627 -28 29 6 1 1 0.317627 -28 29 7 1 1 0.317627 -28 29 8 1 1 0.317627 -28 29 9 1 1 0.317627 -28 29 10 1 1 0.317627 -28 29 11 1 1 0.317627 -28 29 12 1 1 0.317627 -28 29 13 1 1 0.317627 -28 29 14 1 1 0.317627 -28 29 15 1 1 0.317383 -28 29 16 1 1 0.317383 -28 29 17 1 1 0.357422 -28 29 18 1 1 0.430176 -28 29 19 1 1 0.499268 -28 29 20 1 1 0.564453 -28 29 21 1 1 0.626953 -28 29 22 1 1 0.686035 -28 29 23 1 1 0.739746 -28 29 24 1 1 0.788086 -28 29 25 1 1 0.836914 -28 29 26 1 1 0.885254 -28 29 27 0.986816 1 0.931641 -28 29 28 0.955566 1 0.976562 -28 29 29 0.91748 1 1 -28 29 30 0.870117 0.986328 1 -28 29 31 0.814941 0.950684 1 -28 30 0 1 1 0.305664 -28 30 1 1 1 0.305664 -28 30 2 1 1 0.305664 -28 30 3 1 1 0.305664 -28 30 4 1 1 0.305664 -28 30 5 1 1 0.305664 -28 30 6 1 1 0.305664 -28 30 7 1 1 0.305664 -28 30 8 1 1 0.305664 -28 30 9 1 1 0.305664 -28 30 10 1 1 0.305664 -28 30 11 1 1 0.305664 -28 30 12 1 1 0.305664 -28 30 13 1 1 0.305664 -28 30 14 1 1 0.305664 -28 30 15 1 1 0.305664 -28 30 16 1 1 0.30542 -28 30 17 1 1 0.328857 -28 30 18 1 1 0.403076 -28 30 19 1 1 0.472412 -28 30 20 1 1 0.537109 -28 30 21 1 1 0.599121 -28 30 22 1 1 0.657227 -28 30 23 0.997559 1 0.710449 -28 30 24 0.987793 1 0.758789 -28 30 25 0.974121 1 0.807617 -28 30 26 0.956543 1 0.856934 -28 30 27 0.934082 1 0.904785 -28 30 28 0.905762 1 0.95166 -28 30 29 0.871582 1 0.996094 -28 30 30 0.82959 1 1 -28 30 31 0.778809 0.999512 1 -28 31 0 0.947754 1 0.292236 -28 31 1 0.947754 1 0.292236 -28 31 2 0.947754 1 0.292236 -28 31 3 0.947754 1 0.292236 -28 31 4 0.947754 1 0.292236 -28 31 5 0.947754 1 0.292236 -28 31 6 0.947754 1 0.292236 -28 31 7 0.947754 1 0.292236 -28 31 8 0.947754 1 0.292236 -28 31 9 0.947754 1 0.292236 -28 31 10 0.947754 1 0.292236 -28 31 11 0.947754 1 0.292236 -28 31 12 0.947754 1 0.292236 -28 31 13 0.947754 1 0.292236 -28 31 14 0.947754 1 0.292236 -28 31 15 0.947266 1 0.292236 -28 31 16 0.947266 1 0.292236 -28 31 17 0.947266 1 0.29541 -28 31 18 0.946777 1 0.372559 -28 31 19 0.945312 1 0.442139 -28 31 20 0.943359 1 0.506348 -28 31 21 0.939453 1 0.567383 -28 31 22 0.934082 1 0.625 -28 31 23 0.927246 1 0.677734 -28 31 24 0.918457 1 0.725586 -28 31 25 0.906738 1 0.774902 -28 31 26 0.891602 1 0.824219 -28 31 27 0.871582 1 0.874023 -28 31 28 0.84668 1 0.922363 -28 31 29 0.81543 1 0.96875 -28 31 30 0.776855 1 1 -28 31 31 0.730469 1 1 -29 0 0 1 0 0.0778198 -29 0 1 1 0 0.0778198 -29 0 2 1 0 0.0778198 -29 0 3 1 0 0.0778198 -29 0 4 1 0 0.0778198 -29 0 5 1 0 0.0778198 -29 0 6 1 0 0.0777588 -29 0 7 1 0 0.0777588 -29 0 8 1 0 0.0777588 -29 0 9 1 0 0.0776367 -29 0 10 1 0 0.0775146 -29 0 11 1 0 0.0772705 -29 0 12 1 0 0.0769043 -29 0 13 1 0 0.0762329 -29 0 14 1 0 0.0751343 -29 0 15 1 0 0.0734253 -29 0 16 1 0 0.0723267 -29 0 17 1 0 0.189087 -29 0 18 1 0 0.350098 -29 0 19 1 0 0.46167 -29 0 20 1 0 0.554199 -29 0 21 1 0 0.638184 -29 0 22 1 0 0.716797 -29 0 23 1 0.0764771 0.785645 -29 0 24 1 0.235962 0.845215 -29 0 25 1 0.313477 0.899902 -29 0 26 1 0.364746 0.949219 -29 0 27 1 0.391846 0.992676 -29 0 28 1 0.398193 1 -29 0 29 1 0.395508 1 -29 0 30 1 0.390869 1 -29 0 31 1 0.384766 1 -29 1 0 1 0 0.0778198 -29 1 1 1 0 0.0778198 -29 1 2 1 0 0.0778198 -29 1 3 1 0 0.0778198 -29 1 4 1 0 0.0778198 -29 1 5 1 0 0.0778198 -29 1 6 1 0 0.0777588 -29 1 7 1 0 0.0777588 -29 1 8 1 0 0.0776978 -29 1 9 1 0 0.0776367 -29 1 10 1 0 0.0775146 -29 1 11 1 0 0.0772705 -29 1 12 1 0 0.0769043 -29 1 13 1 0 0.0762329 -29 1 14 1 0 0.0751343 -29 1 15 1 0 0.0734253 -29 1 16 1 0 0.0723267 -29 1 17 1 0 0.189087 -29 1 18 1 0 0.350098 -29 1 19 1 0 0.46167 -29 1 20 1 0 0.554199 -29 1 21 1 0 0.638184 -29 1 22 1 0 0.716797 -29 1 23 1 0.0765381 0.785645 -29 1 24 1 0.235962 0.845215 -29 1 25 1 0.313477 0.899902 -29 1 26 1 0.364746 0.949219 -29 1 27 1 0.39209 0.992676 -29 1 28 1 0.398193 1 -29 1 29 1 0.395508 1 -29 1 30 1 0.390869 1 -29 1 31 1 0.384766 1 -29 2 0 1 0 0.0778198 -29 2 1 1 0 0.0778198 -29 2 2 1 0 0.0778198 -29 2 3 1 0 0.0778198 -29 2 4 1 0 0.0777588 -29 2 5 1 0 0.0777588 -29 2 6 1 0 0.0777588 -29 2 7 1 0 0.0777588 -29 2 8 1 0 0.0776978 -29 2 9 1 0 0.0776367 -29 2 10 1 0 0.0775146 -29 2 11 1 0 0.0772705 -29 2 12 1 0 0.0769043 -29 2 13 1 0 0.0762329 -29 2 14 1 0 0.0751343 -29 2 15 1 0 0.0734253 -29 2 16 1 0 0.0723267 -29 2 17 1 0 0.189087 -29 2 18 1 0 0.350098 -29 2 19 1 0 0.46167 -29 2 20 1 0 0.554199 -29 2 21 1 0 0.638184 -29 2 22 1 0 0.716797 -29 2 23 1 0.0767212 0.785645 -29 2 24 1 0.235962 0.845215 -29 2 25 1 0.313721 0.899902 -29 2 26 1 0.364746 0.949219 -29 2 27 1 0.39209 0.992676 -29 2 28 1 0.398193 1 -29 2 29 1 0.395508 1 -29 2 30 1 0.390869 1 -29 2 31 1 0.384766 1 -29 3 0 1 0 0.0777588 -29 3 1 1 0 0.0777588 -29 3 2 1 0 0.0777588 -29 3 3 1 0 0.0777588 -29 3 4 1 0 0.0777588 -29 3 5 1 0 0.0777588 -29 3 6 1 0 0.0777588 -29 3 7 1 0 0.0777588 -29 3 8 1 0 0.0776978 -29 3 9 1 0 0.0776367 -29 3 10 1 0 0.0775146 -29 3 11 1 0 0.0772705 -29 3 12 1 0 0.0768433 -29 3 13 1 0 0.0761719 -29 3 14 1 0 0.0751343 -29 3 15 1 0 0.0734253 -29 3 16 1 0 0.0722656 -29 3 17 1 0 0.189087 -29 3 18 1 0 0.350098 -29 3 19 1 0 0.46167 -29 3 20 1 0 0.554199 -29 3 21 1 0 0.638184 -29 3 22 1 0 0.716797 -29 3 23 1 0.0770874 0.785645 -29 3 24 1 0.236084 0.845215 -29 3 25 1 0.313721 0.899902 -29 3 26 1 0.364746 0.949219 -29 3 27 1 0.39209 0.992676 -29 3 28 1 0.398193 1 -29 3 29 1 0.395508 1 -29 3 30 1 0.390869 1 -29 3 31 1 0.384766 1 -29 4 0 1 0 0.0777588 -29 4 1 1 0 0.0777588 -29 4 2 1 0 0.0777588 -29 4 3 1 0 0.0777588 -29 4 4 1 0 0.0777588 -29 4 5 1 0 0.0777588 -29 4 6 1 0 0.0776978 -29 4 7 1 0 0.0776978 -29 4 8 1 0 0.0776367 -29 4 9 1 0 0.0775757 -29 4 10 1 0 0.0774536 -29 4 11 1 0 0.0772095 -29 4 12 1 0 0.0768433 -29 4 13 1 0 0.0761719 -29 4 14 1 0 0.0750732 -29 4 15 1 0 0.0733643 -29 4 16 1 0 0.0722656 -29 4 17 1 0 0.189087 -29 4 18 1 0 0.350098 -29 4 19 1 0 0.46167 -29 4 20 1 0 0.554199 -29 4 21 1 0 0.638184 -29 4 22 1 0 0.716797 -29 4 23 1 0.0777588 0.785645 -29 4 24 1 0.236206 0.845215 -29 4 25 1 0.313721 0.899902 -29 4 26 1 0.36499 0.949219 -29 4 27 1 0.39209 0.992676 -29 4 28 1 0.398193 1 -29 4 29 1 0.395508 1 -29 4 30 1 0.391113 1 -29 4 31 1 0.384766 1 -29 5 0 1 0 0.0776978 -29 5 1 1 0 0.0776978 -29 5 2 1 0 0.0776978 -29 5 3 1 0 0.0776978 -29 5 4 1 0 0.0776978 -29 5 5 1 0 0.0776978 -29 5 6 1 0 0.0776367 -29 5 7 1 0 0.0776367 -29 5 8 1 0 0.0775757 -29 5 9 1 0 0.0775146 -29 5 10 1 0 0.0773926 -29 5 11 1 0 0.0771484 -29 5 12 1 0 0.0767822 -29 5 13 1 0 0.0761108 -29 5 14 1 0 0.0750122 -29 5 15 1 0 0.0733032 -29 5 16 1 0 0.0722046 -29 5 17 1 0 0.189087 -29 5 18 1 0 0.350098 -29 5 19 1 0 0.46167 -29 5 20 1 0 0.554199 -29 5 21 1 0 0.638184 -29 5 22 1 0 0.716797 -29 5 23 1 0.0789795 0.785645 -29 5 24 1 0.236328 0.845215 -29 5 25 1 0.313721 0.899902 -29 5 26 1 0.36499 0.949219 -29 5 27 1 0.39209 0.992676 -29 5 28 1 0.398438 1 -29 5 29 1 0.395752 1 -29 5 30 1 0.391113 1 -29 5 31 1 0.384766 1 -29 6 0 1 0 0.0775757 -29 6 1 1 0 0.0775757 -29 6 2 1 0 0.0775757 -29 6 3 1 0 0.0775757 -29 6 4 1 0 0.0775757 -29 6 5 1 0 0.0775757 -29 6 6 1 0 0.0775146 -29 6 7 1 0 0.0775146 -29 6 8 1 0 0.0774536 -29 6 9 1 0 0.0773926 -29 6 10 1 0 0.0772705 -29 6 11 1 0 0.0770264 -29 6 12 1 0 0.0766602 -29 6 13 1 0 0.0759888 -29 6 14 1 0 0.0748901 -29 6 15 1 0 0.0731812 -29 6 16 1 0 0.0720215 -29 6 17 1 0 0.189087 -29 6 18 1 0 0.350098 -29 6 19 1 0 0.46167 -29 6 20 1 0 0.554199 -29 6 21 1 0 0.638184 -29 6 22 1 0 0.716797 -29 6 23 1 0.0812378 0.785645 -29 6 24 1 0.236694 0.845215 -29 6 25 1 0.313965 0.899902 -29 6 26 1 0.365234 0.949219 -29 6 27 1 0.392334 0.992676 -29 6 28 1 0.398438 1 -29 6 29 1 0.395752 1 -29 6 30 1 0.391113 1 -29 6 31 1 0.38501 1 -29 7 0 1 0 0.0773315 -29 7 1 1 0 0.0773315 -29 7 2 1 0 0.0773315 -29 7 3 1 0 0.0773315 -29 7 4 1 0 0.0773315 -29 7 5 1 0 0.0773315 -29 7 6 1 0 0.0772705 -29 7 7 1 0 0.0772705 -29 7 8 1 0 0.0772095 -29 7 9 1 0 0.0771484 -29 7 10 1 0 0.0770264 -29 7 11 1 0 0.0767822 -29 7 12 1 0 0.076416 -29 7 13 1 0 0.0757446 -29 7 14 1 0 0.074646 -29 7 15 1 0 0.072937 -29 7 16 1 0 0.0717773 -29 7 17 1 0 0.189087 -29 7 18 1 0 0.349854 -29 7 19 1 0 0.461426 -29 7 20 1 0 0.554199 -29 7 21 1 0 0.638184 -29 7 22 1 0 0.716797 -29 7 23 1 0.0853271 0.785645 -29 7 24 1 0.237549 0.845215 -29 7 25 1 0.314453 0.899902 -29 7 26 1 0.365479 0.949219 -29 7 27 1 0.392578 0.992676 -29 7 28 1 0.398682 1 -29 7 29 1 0.395996 1 -29 7 30 1 0.391357 1 -29 7 31 1 0.38501 1 -29 8 0 1 0 0.0768433 -29 8 1 1 0 0.0768433 -29 8 2 1 0 0.0768433 -29 8 3 1 0 0.0768433 -29 8 4 1 0 0.0768433 -29 8 5 1 0 0.0768433 -29 8 6 1 0 0.0768433 -29 8 7 1 0 0.0767822 -29 8 8 1 0 0.0767822 -29 8 9 1 0 0.0767212 -29 8 10 1 0 0.0765381 -29 8 11 1 0 0.0762939 -29 8 12 1 0 0.0759277 -29 8 13 1 0 0.0752563 -29 8 14 1 0 0.0741577 -29 8 15 1 0 0.0723877 -29 8 16 1 0 0.071228 -29 8 17 1 0 0.189087 -29 8 18 1 0 0.349854 -29 8 19 1 0 0.461426 -29 8 20 1 0 0.554199 -29 8 21 1 0 0.638184 -29 8 22 1 0 0.716797 -29 8 23 1 0.0925903 0.785645 -29 8 24 1 0.238892 0.845215 -29 8 25 1 0.31543 0.899902 -29 8 26 1 0.366211 0.949219 -29 8 27 1 0.393311 0.992676 -29 8 28 1 0.399414 1 -29 8 29 1 0.396484 1 -29 8 30 1 0.391846 1 -29 8 31 1 0.385498 1 -29 9 0 1 0 0.0759277 -29 9 1 1 0 0.0759277 -29 9 2 1 0 0.0759277 -29 9 3 1 0 0.0759277 -29 9 4 1 0 0.0759277 -29 9 5 1 0 0.0759277 -29 9 6 1 0 0.0759277 -29 9 7 1 0 0.0758667 -29 9 8 1 0 0.0758667 -29 9 9 1 0 0.0757446 -29 9 10 1 0 0.0756226 -29 9 11 1 0 0.0753784 -29 9 12 1 0 0.0749512 -29 9 13 1 0 0.0742798 -29 9 14 1 0 0.0731812 -29 9 15 1 0 0.0714111 -29 9 16 1 0 0.0701904 -29 9 17 1 0 0.188965 -29 9 18 1 0 0.349854 -29 9 19 1 0 0.461426 -29 9 20 1 0 0.554199 -29 9 21 1 0 0.638184 -29 9 22 1 0 0.716797 -29 9 23 1 0.10437 0.785645 -29 9 24 1 0.241699 0.845215 -29 9 25 1 0.317139 0.899902 -29 9 26 1 0.367432 0.949219 -29 9 27 1 0.394287 0.992676 -29 9 28 1 0.400391 1 -29 9 29 1 0.397461 1 -29 9 30 1 0.392822 1 -29 9 31 1 0.386475 1 -29 10 0 1 0 0.0742188 -29 10 1 1 0 0.0742188 -29 10 2 1 0 0.0742188 -29 10 3 1 0 0.0742188 -29 10 4 1 0 0.0742188 -29 10 5 1 0 0.0742188 -29 10 6 1 0 0.0742188 -29 10 7 1 0 0.0741577 -29 10 8 1 0 0.0741577 -29 10 9 1 0 0.0740356 -29 10 10 1 0 0.0739136 -29 10 11 1 0 0.0736694 -29 10 12 1 0 0.0732422 -29 10 13 1 0 0.0725098 -29 10 14 1 0 0.0713501 -29 10 15 1 0 0.069458 -29 10 16 1 0 0.0682983 -29 10 17 1 0 0.188843 -29 10 18 1 0 0.349854 -29 10 19 1 0 0.461426 -29 10 20 1 0 0.554199 -29 10 21 1 0 0.638184 -29 10 22 1 0 0.716797 -29 10 23 1 0.121582 0.785645 -29 10 24 1 0.24646 0.845215 -29 10 25 1 0.320312 0.899902 -29 10 26 1 0.369873 0.949219 -29 10 27 1 0.396484 0.992676 -29 10 28 1 0.402344 1 -29 10 29 1 0.399414 1 -29 10 30 1 0.394531 1 -29 10 31 1 0.387939 1 -29 11 0 1 0 0.0710449 -29 11 1 1 0 0.0710449 -29 11 2 1 0 0.0710449 -29 11 3 1 0 0.0710449 -29 11 4 1 0 0.0710449 -29 11 5 1 0 0.0710449 -29 11 6 1 0 0.0709839 -29 11 7 1 0 0.0709839 -29 11 8 1 0 0.0709229 -29 11 9 1 0 0.0708618 -29 11 10 1 0 0.0706787 -29 11 11 1 0 0.0704346 -29 11 12 1 0 0.0699463 -29 11 13 1 0 0.0692139 -29 11 14 1 0 0.0679321 -29 11 15 1 0 0.065918 -29 11 16 1 0 0.0646362 -29 11 17 1 0 0.188721 -29 11 18 1 0 0.349609 -29 11 19 1 0 0.461182 -29 11 20 1 0 0.554199 -29 11 21 1 0 0.638184 -29 11 22 1 0 0.716797 -29 11 23 1 0.144775 0.785645 -29 11 24 1 0.254639 0.845215 -29 11 25 1 0.325439 0.899902 -29 11 26 1 0.374023 0.949219 -29 11 27 1 0.399902 0.992676 -29 11 28 1 0.405518 1 -29 11 29 1 0.402344 1 -29 11 30 1 0.397217 1 -29 11 31 1 0.390625 1 -29 12 0 1 0 0.0650024 -29 12 1 1 0 0.0650024 -29 12 2 1 0 0.0650024 -29 12 3 1 0 0.0650024 -29 12 4 1 0 0.0650024 -29 12 5 1 0 0.0650024 -29 12 6 1 0 0.0649414 -29 12 7 1 0 0.0649414 -29 12 8 1 0 0.0648804 -29 12 9 1 0 0.0647583 -29 12 10 1 0 0.0646362 -29 12 11 1 0 0.06427 -29 12 12 1 0 0.0637817 -29 12 13 1 0 0.0628662 -29 12 14 1 0 0.0613708 -29 12 15 1 0 0.05896 -29 12 16 1 0 0.0574951 -29 12 17 1 0 0.188599 -29 12 18 1 0 0.349365 -29 12 19 1 0 0.460938 -29 12 20 1 0 0.554199 -29 12 21 1 0 0.638184 -29 12 22 1 0 0.716309 -29 12 23 1 0.174561 0.785645 -29 12 24 1 0.267578 0.844727 -29 12 25 1 0.334229 0.899902 -29 12 26 1 0.380859 0.949219 -29 12 27 1 0.406006 0.992676 -29 12 28 1 0.411133 1 -29 12 29 1 0.407715 1 -29 12 30 1 0.4021 1 -29 12 31 1 0.39502 1 -29 13 0 1 0 0.0523987 -29 13 1 1 0 0.0523987 -29 13 2 1 0 0.0523987 -29 13 3 1 0 0.0523987 -29 13 4 1 0 0.0523987 -29 13 5 1 0 0.0523987 -29 13 6 1 0 0.0523682 -29 13 7 1 0 0.0523376 -29 13 8 1 0 0.0522766 -29 13 9 1 0 0.052124 -29 13 10 1 0 0.0518799 -29 13 11 1 0 0.0514221 -29 13 12 1 0 0.0506287 -29 13 13 1 0 0.0493164 -29 13 14 1 0 0.0470886 -29 13 15 1 0 0.0432739 -29 13 16 1 0 0.0409241 -29 13 17 1 0 0.188354 -29 13 18 1 0 0.349121 -29 13 19 1 0 0.460449 -29 13 20 1 0 0.554199 -29 13 21 1 0 0.637695 -29 13 22 1 0.0765991 0.71582 -29 13 23 1 0.210693 0.785156 -29 13 24 1 0.287109 0.844727 -29 13 25 1 0.347656 0.899902 -29 13 26 1 0.391602 0.949219 -29 13 27 1 0.415527 0.992676 -29 13 28 1 0.420166 1 -29 13 29 1 0.416016 1 -29 13 30 1 0.409912 1 -29 13 31 1 0.4021 1 -29 14 0 1 0.0916138 0 -29 14 1 1 0.0916748 0 -29 14 2 1 0.0916748 0 -29 14 3 1 0.0916748 0 -29 14 4 1 0.0917358 0 -29 14 5 1 0.0917969 0 -29 14 6 1 0.09198 0 -29 14 7 1 0.0922852 0 -29 14 8 1 0.0929565 0 -29 14 9 1 0.0941162 0 -29 14 10 1 0.0961914 0 -29 14 11 1 0.0996704 0 -29 14 12 1 0.105164 0 -29 14 13 1 0.113342 0 -29 14 14 1 0.124695 0 -29 14 15 1 0.139404 0 -29 14 16 1 0.145996 0 -29 14 17 1 0.146118 0.188354 -29 14 18 1 0.125488 0.348877 -29 14 19 1 0.11438 0.459717 -29 14 20 1 0.124207 0.554199 -29 14 21 1 0.12854 0.637207 -29 14 22 1 0.186157 0.715332 -29 14 23 1 0.253662 0.784668 -29 14 24 1 0.314209 0.844238 -29 14 25 1 0.367676 0.899902 -29 14 26 1 0.407959 0.949219 -29 14 27 1 0.429932 0.992676 -29 14 28 1 0.433594 1 -29 14 29 1 0.428711 1 -29 14 30 1 0.421631 1 -29 14 31 1 0.412842 1 -29 15 0 1 0.224487 0 -29 15 1 1 0.224487 0 -29 15 2 1 0.224487 0 -29 15 3 1 0.224487 0 -29 15 4 1 0.224487 0 -29 15 5 1 0.224487 0 -29 15 6 1 0.224609 0 -29 15 7 1 0.224609 0 -29 15 8 1 0.224854 0 -29 15 9 1 0.225098 0 -29 15 10 1 0.225586 0 -29 15 11 1 0.226562 0 -29 15 12 1 0.228027 0 -29 15 13 1 0.230591 0 -29 15 14 1 0.234497 0 -29 15 15 1 0.240234 0 -29 15 16 1 0.242798 0 -29 15 17 1 0.24231 0.189209 -29 15 18 1 0.234375 0.348389 -29 15 19 1 0.22998 0.458984 -29 15 20 1 0.237305 0.554199 -29 15 21 1 0.23584 0.636719 -29 15 22 1 0.260254 0.714844 -29 15 23 1 0.302734 0.783691 -29 15 24 1 0.349854 0.84375 -29 15 25 1 0.395264 0.899414 -29 15 26 1 0.431152 0.949219 -29 15 27 1 0.450684 0.992676 -29 15 28 1 0.453125 1 -29 15 29 1 0.447021 1 -29 15 30 1 0.438721 1 -29 15 31 1 0.428467 1 -29 16 0 1 0.311768 0 -29 16 1 1 0.311768 0 -29 16 2 1 0.311768 0 -29 16 3 1 0.311768 0 -29 16 4 1 0.311768 0 -29 16 5 1 0.311768 0 -29 16 6 1 0.311768 0 -29 16 7 1 0.311768 0 -29 16 8 1 0.312012 0 -29 16 9 1 0.312012 0 -29 16 10 1 0.3125 0 -29 16 11 1 0.312988 0 -29 16 12 1 0.313965 0 -29 16 13 1 0.31543 0 -29 16 14 1 0.317871 0 -29 16 15 1 0.321289 0 -29 16 16 1 0.322754 0 -29 16 17 1 0.322021 0.192139 -29 16 18 1 0.317627 0.348633 -29 16 19 1 0.314453 0.458008 -29 16 20 1 0.317383 0.552734 -29 16 21 1 0.318848 0.63623 -29 16 22 1 0.330811 0.713379 -29 16 23 1 0.358643 0.782715 -29 16 24 1 0.393799 0.843262 -29 16 25 1 0.431152 0.898926 -29 16 26 1 0.461914 0.94873 -29 16 27 1 0.47876 0.992676 -29 16 28 1 0.479492 1 -29 16 29 1 0.471924 1 -29 16 30 1 0.462158 1 -29 16 31 1 0.450195 1 -29 17 0 1 0.391113 0 -29 17 1 1 0.391113 0 -29 17 2 1 0.391113 0 -29 17 3 1 0.391113 0 -29 17 4 1 0.391113 0 -29 17 5 1 0.391113 0 -29 17 6 1 0.391113 0 -29 17 7 1 0.391357 0 -29 17 8 1 0.391357 0 -29 17 9 1 0.391357 0 -29 17 10 1 0.391602 0 -29 17 11 1 0.39209 0 -29 17 12 1 0.392578 0 -29 17 13 1 0.393799 0 -29 17 14 1 0.395508 0 -29 17 15 1 0.397949 0 -29 17 16 1 0.398926 0 -29 17 17 1 0.398193 0.199219 -29 17 18 1 0.395508 0.350342 -29 17 19 1 0.393311 0.457764 -29 17 20 1 0.393799 0.550781 -29 17 21 1 0.396973 0.635742 -29 17 22 1 0.401855 0.711914 -29 17 23 1 0.418945 0.780762 -29 17 24 1 0.444336 0.841797 -29 17 25 1 0.474121 0.897949 -29 17 26 1 0.5 0.94873 -29 17 27 1 0.513672 0.992188 -29 17 28 1 0.512695 1 -29 17 29 1 0.503418 1 -29 17 30 1 0.491943 1 -29 17 31 1 0.478027 1 -29 18 0 1 0.467041 0 -29 18 1 1 0.467041 0 -29 18 2 1 0.467041 0 -29 18 3 1 0.467041 0 -29 18 4 1 0.467041 0 -29 18 5 1 0.467041 0 -29 18 6 1 0.467041 0 -29 18 7 1 0.467041 0 -29 18 8 1 0.467285 0 -29 18 9 1 0.467285 0 -29 18 10 1 0.467529 0 -29 18 11 1 0.467773 0 -29 18 12 1 0.468262 0 -29 18 13 1 0.468994 0 -29 18 14 1 0.470215 0 -29 18 15 1 0.472168 0 -29 18 16 1 0.4729 0 -29 18 17 1 0.472412 0.212769 -29 18 18 1 0.471191 0.354492 -29 18 19 1 0.469482 0.458496 -29 18 20 1 0.46875 0.549316 -29 18 21 1 0.47168 0.634766 -29 18 22 1 0.4729 0.709961 -29 18 23 1 0.482178 0.77832 -29 18 24 1 0.499512 0.839355 -29 18 25 1 0.521973 0.896484 -29 18 26 1 0.543457 0.947754 -29 18 27 1 0.554199 0.991699 -29 18 28 1 0.55127 1 -29 18 29 1 0.540527 1 -29 18 30 1 0.526855 1 -29 18 31 1 0.510742 1 -29 19 0 1 0.539551 0 -29 19 1 1 0.539551 0 -29 19 2 1 0.539551 0 -29 19 3 1 0.539551 0 -29 19 4 1 0.539551 0 -29 19 5 1 0.539551 0 -29 19 6 1 0.539551 0 -29 19 7 1 0.539551 0 -29 19 8 1 0.539551 0 -29 19 9 1 0.539551 0 -29 19 10 1 0.539551 0 -29 19 11 1 0.540039 0 -29 19 12 1 0.540039 0 -29 19 13 1 0.541016 0 -29 19 14 1 0.541992 0 -29 19 15 1 0.543457 0 -29 19 16 1 0.543945 0 -29 19 17 1 0.544434 0.233398 -29 19 18 1 0.543945 0.362305 -29 19 19 1 0.542969 0.46167 -29 19 20 1 0.541504 0.549316 -29 19 21 1 0.541504 0.631836 -29 19 22 1 0.543457 0.708008 -29 19 23 1 0.546387 0.775391 -29 19 24 1 0.556641 0.836426 -29 19 25 1 0.573242 0.894043 -29 19 26 1 0.589844 0.946289 -29 19 27 1 0.598145 0.990723 -29 19 28 1 0.59375 1 -29 19 29 1 0.581055 1 -29 19 30 1 0.564941 1 -29 19 31 1 0.546387 1 -29 20 0 1 0.606934 0 -29 20 1 1 0.606934 0 -29 20 2 1 0.606934 0 -29 20 3 1 0.606934 0 -29 20 4 1 0.606934 0 -29 20 5 1 0.606934 0 -29 20 6 1 0.606934 0 -29 20 7 1 0.606934 0 -29 20 8 1 0.606934 0 -29 20 9 1 0.606934 0 -29 20 10 1 0.606934 0 -29 20 11 1 0.606934 0 -29 20 12 1 0.607422 0 -29 20 13 1 0.60791 0 -29 20 14 1 0.608887 0 -29 20 15 1 0.609863 0 -29 20 16 1 0.61084 0 -29 20 17 1 0.611816 0.259521 -29 20 18 1 0.612793 0.374512 -29 20 19 1 0.612305 0.467773 -29 20 20 1 0.611328 0.55127 -29 20 21 1 0.609863 0.630371 -29 20 22 1 0.609863 0.705566 -29 20 23 1 0.609863 0.771973 -29 20 24 1 0.61377 0.832031 -29 20 25 1 0.624512 0.890625 -29 20 26 1 0.636719 0.943848 -29 20 27 1 0.643066 0.989258 -29 20 28 1 0.637207 1 -29 20 29 1 0.622559 1 -29 20 30 1 0.60498 1 -29 20 31 1 0.583984 1 -29 21 0 1 0.67041 0 -29 21 1 1 0.67041 0 -29 21 2 1 0.67041 0 -29 21 3 1 0.67041 0 -29 21 4 1 0.67041 0 -29 21 5 1 0.67041 0 -29 21 6 1 0.67041 0 -29 21 7 1 0.67041 0 -29 21 8 1 0.67041 0 -29 21 9 1 0.67041 0 -29 21 10 1 0.670898 0 -29 21 11 1 0.670898 0 -29 21 12 1 0.670898 0 -29 21 13 1 0.671387 0 -29 21 14 1 0.671875 0 -29 21 15 1 0.672852 0 -29 21 16 1 0.674805 0.125366 -29 21 17 1 0.67627 0.288818 -29 21 18 1 0.677734 0.390381 -29 21 19 1 0.678711 0.477295 -29 21 20 1 0.677734 0.556152 -29 21 21 1 0.675781 0.630859 -29 21 22 1 0.67334 0.702148 -29 21 23 1 0.67334 0.769043 -29 21 24 1 0.671875 0.827148 -29 21 25 1 0.67627 0.88623 -29 21 26 1 0.68457 0.94043 -29 21 27 1 0.688477 0.986816 -29 21 28 1 0.681641 1 -29 21 29 1 0.665527 1 -29 21 30 1 0.645996 1 -29 21 31 1 0.623047 1 -29 22 0 1 0.72998 0.135254 -29 22 1 1 0.72998 0.135254 -29 22 2 1 0.72998 0.135254 -29 22 3 1 0.72998 0.135254 -29 22 4 1 0.72998 0.135254 -29 22 5 1 0.72998 0.135254 -29 22 6 1 0.72998 0.135254 -29 22 7 1 0.72998 0.135254 -29 22 8 1 0.72998 0.135376 -29 22 9 1 0.72998 0.135376 -29 22 10 1 0.72998 0.13562 -29 22 11 1 0.730469 0.135864 -29 22 12 1 0.730469 0.13623 -29 22 13 1 0.730957 0.137085 -29 22 14 1 0.731445 0.138184 -29 22 15 1 0.731934 0.139893 -29 22 16 1 0.733398 0.203735 -29 22 17 1 0.73584 0.317871 -29 22 18 1 0.738281 0.408203 -29 22 19 1 0.739746 0.489014 -29 22 20 1 0.739746 0.562988 -29 22 21 1 0.738281 0.633789 -29 22 22 1 0.735352 0.701172 -29 22 23 1 0.731934 0.76416 -29 22 24 1 0.729492 0.822266 -29 22 25 1 0.728027 0.880371 -29 22 26 1 0.731445 0.935547 -29 22 27 1 0.733398 0.983398 -29 22 28 1 0.725586 1 -29 22 29 1 0.708496 1 -29 22 30 1 0.687012 1 -29 22 31 1 0.662109 1 -29 23 0 1 0.782715 0.221313 -29 23 1 1 0.782715 0.221313 -29 23 2 1 0.782715 0.221313 -29 23 3 1 0.782715 0.221313 -29 23 4 1 0.782715 0.221313 -29 23 5 1 0.783203 0.221313 -29 23 6 1 0.783203 0.221313 -29 23 7 1 0.783203 0.221313 -29 23 8 1 0.783203 0.221313 -29 23 9 1 0.783203 0.221313 -29 23 10 1 0.783203 0.221436 -29 23 11 1 0.783203 0.221558 -29 23 12 1 0.783203 0.22168 -29 23 13 1 0.783691 0.222046 -29 23 14 1 0.78418 0.222412 -29 23 15 1 0.784668 0.223145 -29 23 16 1 0.786133 0.250488 -29 23 17 1 0.788574 0.343262 -29 23 18 1 0.791504 0.425049 -29 23 19 1 0.793945 0.500977 -29 23 20 1 0.794922 0.571289 -29 23 21 1 0.794434 0.638672 -29 23 22 1 0.791504 0.702148 -29 23 23 1 0.787109 0.76123 -29 23 24 1 0.782227 0.816895 -29 23 25 1 0.777832 0.873535 -29 23 26 1 0.776367 0.929688 -29 23 27 1 0.775879 0.978516 -29 23 28 1 0.76709 1 -29 23 29 1 0.749023 1 -29 23 30 1 0.726562 1 -29 23 31 1 0.699707 1 -29 24 0 1 0.830078 0.269287 -29 24 1 1 0.830078 0.269287 -29 24 2 1 0.830078 0.269287 -29 24 3 1 0.830078 0.269287 -29 24 4 1 0.830078 0.269287 -29 24 5 1 0.830078 0.269287 -29 24 6 1 0.830078 0.269287 -29 24 7 1 0.830078 0.269287 -29 24 8 1 0.830078 0.269287 -29 24 9 1 0.830078 0.269287 -29 24 10 1 0.830078 0.269287 -29 24 11 1 0.830566 0.269287 -29 24 12 1 0.830566 0.269531 -29 24 13 1 0.830566 0.269531 -29 24 14 1 0.831055 0.269775 -29 24 15 1 0.831543 0.270264 -29 24 16 1 0.83252 0.282471 -29 24 17 1 0.835449 0.363281 -29 24 18 1 0.838867 0.439209 -29 24 19 1 0.841797 0.51123 -29 24 20 1 0.84375 0.578613 -29 24 21 1 0.84375 0.643555 -29 24 22 1 0.841797 0.70459 -29 24 23 1 0.837891 0.760254 -29 24 24 1 0.832031 0.8125 -29 24 25 1 0.825684 0.867188 -29 24 26 1 0.819336 0.922363 -29 24 27 1 0.81543 0.973145 -29 24 28 1 0.806641 1 -29 24 29 1 0.787598 1 -29 24 30 1 0.76416 1 -29 24 31 1 0.735352 1 -29 25 0 1 0.876953 0.303223 -29 25 1 1 0.876953 0.303223 -29 25 2 1 0.876953 0.303223 -29 25 3 1 0.876953 0.303223 -29 25 4 1 0.876953 0.303223 -29 25 5 1 0.876953 0.303223 -29 25 6 1 0.876953 0.303223 -29 25 7 1 0.876953 0.303223 -29 25 8 1 0.876953 0.303223 -29 25 9 1 0.876953 0.303223 -29 25 10 1 0.876953 0.303223 -29 25 11 1 0.876953 0.303223 -29 25 12 1 0.876953 0.303467 -29 25 13 1 0.876953 0.303467 -29 25 14 1 0.877441 0.303711 -29 25 15 1 0.87793 0.303955 -29 25 16 1 0.878418 0.304932 -29 25 17 1 0.881836 0.378418 -29 25 18 1 0.885254 0.449707 -29 25 19 1 0.888184 0.519043 -29 25 20 1 0.890625 0.584473 -29 25 21 1 0.891602 0.646973 -29 25 22 1 0.890625 0.706543 -29 25 23 1 0.887695 0.760254 -29 25 24 1 0.882324 0.80957 -29 25 25 1 0.874512 0.860352 -29 25 26 1 0.865234 0.913574 -29 25 27 1 0.856934 0.964844 -29 25 28 1 0.847168 1 -29 25 29 1 0.828125 1 -29 25 30 1 0.803223 1 -29 25 31 0.990234 0.773438 1 -29 26 0 1 0.922852 0.325684 -29 26 1 1 0.922852 0.325684 -29 26 2 1 0.922852 0.325684 -29 26 3 1 0.922852 0.325684 -29 26 4 1 0.922852 0.325684 -29 26 5 1 0.922852 0.325684 -29 26 6 1 0.922852 0.325684 -29 26 7 1 0.922852 0.325684 -29 26 8 1 0.922852 0.325684 -29 26 9 1 0.922852 0.325684 -29 26 10 1 0.922852 0.325684 -29 26 11 1 0.922852 0.325684 -29 26 12 1 0.922852 0.325684 -29 26 13 1 0.922852 0.325684 -29 26 14 1 0.92334 0.325684 -29 26 15 1 0.92334 0.325928 -29 26 16 1 0.923828 0.326172 -29 26 17 1 0.926758 0.38623 -29 26 18 1 0.930176 0.454834 -29 26 19 1 0.933594 0.521973 -29 26 20 1 0.936035 0.585938 -29 26 21 1 0.9375 0.647461 -29 26 22 1 0.9375 0.705566 -29 26 23 1 0.935059 0.758301 -29 26 24 1 0.931152 0.806152 -29 26 25 1 0.923828 0.854492 -29 26 26 1 0.913086 0.903809 -29 26 27 1 0.900879 0.954102 -29 26 28 1 0.889648 1 -29 26 29 1 0.870117 1 -29 26 30 1 0.844727 1 -29 26 31 0.975098 0.812988 1 -29 27 0 1 0.967285 0.336182 -29 27 1 1 0.967285 0.336182 -29 27 2 1 0.967285 0.336182 -29 27 3 1 0.967285 0.336182 -29 27 4 1 0.967285 0.336182 -29 27 5 1 0.967285 0.336182 -29 27 6 1 0.967285 0.336182 -29 27 7 1 0.967285 0.336182 -29 27 8 1 0.967285 0.336182 -29 27 9 1 0.967285 0.336182 -29 27 10 1 0.967285 0.336182 -29 27 11 1 0.967285 0.336182 -29 27 12 1 0.967285 0.336182 -29 27 13 1 0.967285 0.336426 -29 27 14 1 0.967773 0.336426 -29 27 15 1 0.967773 0.336426 -29 27 16 1 0.968262 0.336426 -29 27 17 1 0.970703 0.384521 -29 27 18 1 0.974121 0.451904 -29 27 19 1 0.977539 0.518066 -29 27 20 1 0.97998 0.581055 -29 27 21 1 0.981934 0.64209 -29 27 22 1 0.981934 0.699707 -29 27 23 1 0.980469 0.752441 -29 27 24 1 0.976562 0.799805 -29 27 25 1 0.970703 0.847656 -29 27 26 1 0.960938 0.894531 -29 27 27 1 0.947266 0.941895 -29 27 28 1 0.932129 0.989258 -29 27 29 1 0.913574 1 -29 27 30 1 0.887207 1 -29 27 31 0.956543 0.85498 1 -29 28 0 1 1 0.336182 -29 28 1 1 1 0.336182 -29 28 2 1 1 0.336182 -29 28 3 1 1 0.336182 -29 28 4 1 1 0.336182 -29 28 5 1 1 0.336182 -29 28 6 1 1 0.336182 -29 28 7 1 1 0.336182 -29 28 8 1 1 0.336182 -29 28 9 1 1 0.336182 -29 28 10 1 1 0.336182 -29 28 11 1 1 0.336182 -29 28 12 1 1 0.336182 -29 28 13 1 1 0.336182 -29 28 14 1 1 0.336182 -29 28 15 1 1 0.336182 -29 28 16 1 1 0.336182 -29 28 17 1 1 0.372559 -29 28 18 1 1 0.440186 -29 28 19 1 1 0.505859 -29 28 20 1 1 0.568848 -29 28 21 1 1 0.629395 -29 28 22 1 1 0.687012 -29 28 23 1 1 0.739746 -29 28 24 1 1 0.787598 -29 28 25 1 1 0.835938 -29 28 26 1 1 0.883301 -29 28 27 1 0.993652 0.929688 -29 28 28 1 0.976562 0.974121 -29 28 29 1 0.95752 1 -29 28 30 0.988281 0.930176 1 -29 28 31 0.933105 0.897461 1 -29 29 0 1 1 0.328857 -29 29 1 1 1 0.328857 -29 29 2 1 1 0.328857 -29 29 3 1 1 0.328857 -29 29 4 1 1 0.328857 -29 29 5 1 1 0.328857 -29 29 6 1 1 0.328857 -29 29 7 1 1 0.328857 -29 29 8 1 1 0.328857 -29 29 9 1 1 0.328857 -29 29 10 1 1 0.328857 -29 29 11 1 1 0.328857 -29 29 12 1 1 0.328857 -29 29 13 1 1 0.328857 -29 29 14 1 1 0.328857 -29 29 15 1 1 0.328857 -29 29 16 1 1 0.328613 -29 29 17 1 1 0.352051 -29 29 18 1 1 0.420898 -29 29 19 1 1 0.487061 -29 29 20 1 1 0.549805 -29 29 21 1 1 0.610352 -29 29 22 1 1 0.66748 -29 29 23 1 1 0.719727 -29 29 24 1 1 0.768066 -29 29 25 1 1 0.816406 -29 29 26 1 1 0.865234 -29 29 27 1 1 0.913086 -29 29 28 1 1 0.958496 -29 29 29 1 1 1 -29 29 30 0.956543 0.974121 1 -29 29 31 0.905273 0.942383 1 -29 30 0 1 1 0.318359 -29 30 1 1 1 0.318359 -29 30 2 1 1 0.318359 -29 30 3 1 1 0.318359 -29 30 4 1 1 0.318359 -29 30 5 1 1 0.318359 -29 30 6 1 1 0.318359 -29 30 7 1 1 0.318359 -29 30 8 1 1 0.318359 -29 30 9 1 1 0.318359 -29 30 10 1 1 0.318359 -29 30 11 1 1 0.318359 -29 30 12 1 1 0.318359 -29 30 13 1 1 0.318359 -29 30 14 1 1 0.318359 -29 30 15 1 1 0.318359 -29 30 16 1 1 0.318359 -29 30 17 1 1 0.326416 -29 30 18 1 1 0.396973 -29 30 19 1 1 0.463623 -29 30 20 1 1 0.525879 -29 30 21 1 1 0.585938 -29 30 22 1 1 0.643066 -29 30 23 1 1 0.694824 -29 30 24 1 1 0.742676 -29 30 25 1 1 0.791504 -29 30 26 1 1 0.840332 -29 30 27 1 1 0.88916 -29 30 28 0.991699 1 0.936035 -29 30 29 0.959473 1 0.980469 -29 30 30 0.921387 1 1 -29 30 31 0.873535 0.990234 1 -29 31 0 1 1 0.306396 -29 31 1 1 1 0.306396 -29 31 2 1 1 0.306396 -29 31 3 1 1 0.306396 -29 31 4 1 1 0.306396 -29 31 5 1 1 0.306396 -29 31 6 1 1 0.306396 -29 31 7 1 1 0.306396 -29 31 8 1 1 0.306396 -29 31 9 1 1 0.306396 -29 31 10 1 1 0.306396 -29 31 11 1 1 0.306396 -29 31 12 1 1 0.306396 -29 31 13 1 1 0.306396 -29 31 14 1 1 0.306396 -29 31 15 1 1 0.306396 -29 31 16 1 1 0.306396 -29 31 17 1 1 0.306152 -29 31 18 1 1 0.369141 -29 31 19 1 1 0.436523 -29 31 20 1 1 0.498779 -29 31 21 1 1 0.558105 -29 31 22 1 1 0.614258 -29 31 23 1 1 0.665527 -29 31 24 1 1 0.713379 -29 31 25 0.991211 1 0.761719 -29 31 26 0.978027 1 0.811035 -29 31 27 0.960449 1 0.860352 -29 31 28 0.937988 1 0.908691 -29 31 29 0.90918 1 0.955566 -29 31 30 0.874512 1 0.999512 -29 31 31 0.832031 1 1 -30 0 0 1 0 0.0789795 -30 0 1 1 0 0.0789795 -30 0 2 1 0 0.0789795 -30 0 3 1 0 0.0789795 -30 0 4 1 0 0.0789795 -30 0 5 1 0 0.0789795 -30 0 6 1 0 0.0789795 -30 0 7 1 0 0.0789795 -30 0 8 1 0 0.0789185 -30 0 9 1 0 0.0788574 -30 0 10 1 0 0.0787354 -30 0 11 1 0 0.0785522 -30 0 12 1 0 0.0782471 -30 0 13 1 0 0.0776367 -30 0 14 1 0 0.0767822 -30 0 15 1 0 0.0753784 -30 0 16 1 0 0.0740356 -30 0 17 1 0 0.0726318 -30 0 18 1 0 0.286377 -30 0 19 1 0 0.406738 -30 0 20 1 0 0.504395 -30 0 21 1 0 0.586914 -30 0 22 1 0 0.664551 -30 0 23 1 0 0.733887 -30 0 24 1 0 0.794922 -30 0 25 1 0.22644 0.853027 -30 0 26 1 0.310303 0.906738 -30 0 27 1 0.364746 0.955078 -30 0 28 1 0.393555 0.997559 -30 0 29 1 0.400146 1 -30 0 30 1 0.397217 1 -30 0 31 1 0.392334 1 -30 1 0 1 0 0.0789795 -30 1 1 1 0 0.0789795 -30 1 2 1 0 0.0789795 -30 1 3 1 0 0.0789795 -30 1 4 1 0 0.0789795 -30 1 5 1 0 0.0789795 -30 1 6 1 0 0.0789795 -30 1 7 1 0 0.0789795 -30 1 8 1 0 0.0789185 -30 1 9 1 0 0.0788574 -30 1 10 1 0 0.0787354 -30 1 11 1 0 0.0785522 -30 1 12 1 0 0.0782471 -30 1 13 1 0 0.0776367 -30 1 14 1 0 0.0767822 -30 1 15 1 0 0.0753784 -30 1 16 1 0 0.0740356 -30 1 17 1 0 0.0726318 -30 1 18 1 0 0.286377 -30 1 19 1 0 0.406738 -30 1 20 1 0 0.504395 -30 1 21 1 0 0.586914 -30 1 22 1 0 0.664551 -30 1 23 1 0 0.733887 -30 1 24 1 0 0.794922 -30 1 25 1 0.226562 0.853027 -30 1 26 1 0.310303 0.906738 -30 1 27 1 0.364746 0.955078 -30 1 28 1 0.393555 0.997559 -30 1 29 1 0.400146 1 -30 1 30 1 0.397217 1 -30 1 31 1 0.392334 1 -30 2 0 1 0 0.0789795 -30 2 1 1 0 0.0789795 -30 2 2 1 0 0.0789795 -30 2 3 1 0 0.0789795 -30 2 4 1 0 0.0789795 -30 2 5 1 0 0.0789795 -30 2 6 1 0 0.0789795 -30 2 7 1 0 0.0789185 -30 2 8 1 0 0.0789185 -30 2 9 1 0 0.0788574 -30 2 10 1 0 0.0787354 -30 2 11 1 0 0.0785522 -30 2 12 1 0 0.078186 -30 2 13 1 0 0.0776367 -30 2 14 1 0 0.0767822 -30 2 15 1 0 0.0753174 -30 2 16 1 0 0.0740356 -30 2 17 1 0 0.0726318 -30 2 18 1 0 0.286377 -30 2 19 1 0 0.406738 -30 2 20 1 0 0.504395 -30 2 21 1 0 0.586914 -30 2 22 1 0 0.664551 -30 2 23 1 0 0.733887 -30 2 24 1 0 0.794922 -30 2 25 1 0.226562 0.853027 -30 2 26 1 0.310303 0.906738 -30 2 27 1 0.364746 0.955078 -30 2 28 1 0.393555 0.997559 -30 2 29 1 0.400146 1 -30 2 30 1 0.397217 1 -30 2 31 1 0.392334 1 -30 3 0 1 0 0.0789795 -30 3 1 1 0 0.0789795 -30 3 2 1 0 0.0789795 -30 3 3 1 0 0.0789795 -30 3 4 1 0 0.0789795 -30 3 5 1 0 0.0789795 -30 3 6 1 0 0.0789795 -30 3 7 1 0 0.0789185 -30 3 8 1 0 0.0789185 -30 3 9 1 0 0.0788574 -30 3 10 1 0 0.0787354 -30 3 11 1 0 0.0785522 -30 3 12 1 0 0.078186 -30 3 13 1 0 0.0776367 -30 3 14 1 0 0.0767212 -30 3 15 1 0 0.0753174 -30 3 16 1 0 0.0740356 -30 3 17 1 0 0.0725708 -30 3 18 1 0 0.286377 -30 3 19 1 0 0.406738 -30 3 20 1 0 0.504395 -30 3 21 1 0 0.586914 -30 3 22 1 0 0.664551 -30 3 23 1 0 0.733887 -30 3 24 1 0 0.794922 -30 3 25 1 0.226562 0.853027 -30 3 26 1 0.310303 0.906738 -30 3 27 1 0.364746 0.955078 -30 3 28 1 0.393555 0.997559 -30 3 29 1 0.400146 1 -30 3 30 1 0.397217 1 -30 3 31 1 0.392334 1 -30 4 0 1 0 0.0789185 -30 4 1 1 0 0.0789185 -30 4 2 1 0 0.0789185 -30 4 3 1 0 0.0789185 -30 4 4 1 0 0.0789185 -30 4 5 1 0 0.0789185 -30 4 6 1 0 0.0789185 -30 4 7 1 0 0.0789185 -30 4 8 1 0 0.0788574 -30 4 9 1 0 0.0787964 -30 4 10 1 0 0.0786743 -30 4 11 1 0 0.0784912 -30 4 12 1 0 0.078186 -30 4 13 1 0 0.0776367 -30 4 14 1 0 0.0767212 -30 4 15 1 0 0.0753174 -30 4 16 1 0 0.0739746 -30 4 17 1 0 0.0725708 -30 4 18 1 0 0.286377 -30 4 19 1 0 0.406738 -30 4 20 1 0 0.504395 -30 4 21 1 0 0.586914 -30 4 22 1 0 0.664551 -30 4 23 1 0 0.733887 -30 4 24 1 0 0.794922 -30 4 25 1 0.226685 0.853027 -30 4 26 1 0.310547 0.906738 -30 4 27 1 0.364746 0.955078 -30 4 28 1 0.393555 0.997559 -30 4 29 1 0.400146 1 -30 4 30 1 0.397217 1 -30 4 31 1 0.392578 1 -30 5 0 1 0 0.0788574 -30 5 1 1 0 0.0788574 -30 5 2 1 0 0.0788574 -30 5 3 1 0 0.0788574 -30 5 4 1 0 0.0788574 -30 5 5 1 0 0.0788574 -30 5 6 1 0 0.0788574 -30 5 7 1 0 0.0788574 -30 5 8 1 0 0.0787964 -30 5 9 1 0 0.0787354 -30 5 10 1 0 0.0786743 -30 5 11 1 0 0.0784302 -30 5 12 1 0 0.078125 -30 5 13 1 0 0.0775757 -30 5 14 1 0 0.0766602 -30 5 15 1 0 0.0752563 -30 5 16 1 0 0.0739136 -30 5 17 1 0 0.0725098 -30 5 18 1 0 0.286377 -30 5 19 1 0 0.406738 -30 5 20 1 0 0.504395 -30 5 21 1 0 0.586914 -30 5 22 1 0 0.664551 -30 5 23 1 0 0.733887 -30 5 24 1 0 0.794922 -30 5 25 1 0.226929 0.853027 -30 5 26 1 0.310547 0.906738 -30 5 27 1 0.36499 0.955078 -30 5 28 1 0.393799 0.997559 -30 5 29 1 0.400391 1 -30 5 30 1 0.397461 1 -30 5 31 1 0.392578 1 -30 6 0 1 0 0.0787964 -30 6 1 1 0 0.0787964 -30 6 2 1 0 0.0787964 -30 6 3 1 0 0.0787964 -30 6 4 1 0 0.0787964 -30 6 5 1 0 0.0787964 -30 6 6 1 0 0.0787354 -30 6 7 1 0 0.0787354 -30 6 8 1 0 0.0787354 -30 6 9 1 0 0.0786743 -30 6 10 1 0 0.0785522 -30 6 11 1 0 0.0783691 -30 6 12 1 0 0.0780029 -30 6 13 1 0 0.0774536 -30 6 14 1 0 0.0765381 -30 6 15 1 0 0.0751343 -30 6 16 1 0 0.0738525 -30 6 17 1 0 0.0723877 -30 6 18 1 0 0.286377 -30 6 19 1 0 0.406738 -30 6 20 1 0 0.504395 -30 6 21 1 0 0.586914 -30 6 22 1 0 0.664551 -30 6 23 1 0 0.733887 -30 6 24 1 0 0.794922 -30 6 25 1 0.227173 0.853027 -30 6 26 1 0.310791 0.906738 -30 6 27 1 0.36499 0.955078 -30 6 28 1 0.393799 0.997559 -30 6 29 1 0.400391 1 -30 6 30 1 0.397461 1 -30 6 31 1 0.392578 1 -30 7 0 1 0 0.0785522 -30 7 1 1 0 0.0785522 -30 7 2 1 0 0.0785522 -30 7 3 1 0 0.0785522 -30 7 4 1 0 0.0785522 -30 7 5 1 0 0.0785522 -30 7 6 1 0 0.0785522 -30 7 7 1 0 0.0785522 -30 7 8 1 0 0.0784912 -30 7 9 1 0 0.0784302 -30 7 10 1 0 0.0783691 -30 7 11 1 0 0.078125 -30 7 12 1 0 0.0778198 -30 7 13 1 0 0.0772705 -30 7 14 1 0 0.076355 -30 7 15 1 0 0.0748901 -30 7 16 1 0 0.0736084 -30 7 17 1 0 0.0721436 -30 7 18 1 0 0.286133 -30 7 19 1 0 0.406738 -30 7 20 1 0 0.503906 -30 7 21 1 0 0.586914 -30 7 22 1 0 0.664551 -30 7 23 1 0 0.733887 -30 7 24 1 0 0.794922 -30 7 25 1 0.227905 0.853027 -30 7 26 1 0.311279 0.906738 -30 7 27 1 0.365479 0.955078 -30 7 28 1 0.394043 0.997559 -30 7 29 1 0.400635 1 -30 7 30 1 0.397705 1 -30 7 31 1 0.392822 1 -30 8 0 1 0 0.078186 -30 8 1 1 0 0.078186 -30 8 2 1 0 0.078186 -30 8 3 1 0 0.078186 -30 8 4 1 0 0.078186 -30 8 5 1 0 0.078186 -30 8 6 1 0 0.078186 -30 8 7 1 0 0.078125 -30 8 8 1 0 0.078125 -30 8 9 1 0 0.078064 -30 8 10 1 0 0.0779419 -30 8 11 1 0 0.0777588 -30 8 12 1 0 0.0773926 -30 8 13 1 0 0.0768433 -30 8 14 1 0 0.0759277 -30 8 15 1 0 0.0744629 -30 8 16 1 0 0.0731812 -30 8 17 1 0 0.0717163 -30 8 18 1 0 0.286133 -30 8 19 1 0 0.406738 -30 8 20 1 0 0.503906 -30 8 21 1 0 0.586914 -30 8 22 1 0 0.664551 -30 8 23 1 0 0.733887 -30 8 24 1 0 0.794922 -30 8 25 1 0.229248 0.853027 -30 8 26 1 0.312012 0.906738 -30 8 27 1 0.365967 0.955078 -30 8 28 1 0.394531 0.997559 -30 8 29 1 0.401123 1 -30 8 30 1 0.398193 1 -30 8 31 1 0.393311 1 -30 9 0 1 0 0.0773926 -30 9 1 1 0 0.0773926 -30 9 2 1 0 0.0773926 -30 9 3 1 0 0.0773926 -30 9 4 1 0 0.0773926 -30 9 5 1 0 0.0773926 -30 9 6 1 0 0.0773926 -30 9 7 1 0 0.0773926 -30 9 8 1 0 0.0773315 -30 9 9 1 0 0.0772705 -30 9 10 1 0 0.0771484 -30 9 11 1 0 0.0769653 -30 9 12 1 0 0.0765991 -30 9 13 1 0 0.0760498 -30 9 14 1 0 0.0751343 -30 9 15 1 0 0.0736694 -30 9 16 1 0 0.0723267 -30 9 17 1 0 0.0708008 -30 9 18 1 0 0.286133 -30 9 19 1 0 0.406738 -30 9 20 1 0 0.503906 -30 9 21 1 0 0.586914 -30 9 22 1 0 0.664551 -30 9 23 1 0 0.733887 -30 9 24 1 0 0.794922 -30 9 25 1 0.231812 0.853027 -30 9 26 1 0.313477 0.906738 -30 9 27 1 0.367188 0.955078 -30 9 28 1 0.395508 0.997559 -30 9 29 1 0.4021 1 -30 9 30 1 0.398926 1 -30 9 31 1 0.394043 1 -30 10 0 1 0 0.0759888 -30 10 1 1 0 0.0759888 -30 10 2 1 0 0.0759888 -30 10 3 1 0 0.0759888 -30 10 4 1 0 0.0759888 -30 10 5 1 0 0.0759888 -30 10 6 1 0 0.0759888 -30 10 7 1 0 0.0759277 -30 10 8 1 0 0.0759277 -30 10 9 1 0 0.0758667 -30 10 10 1 0 0.0757446 -30 10 11 1 0 0.0755005 -30 10 12 1 0 0.0751953 -30 10 13 1 0 0.074585 -30 10 14 1 0 0.0736084 -30 10 15 1 0 0.0720825 -30 10 16 1 0 0.0707397 -30 10 17 1 0 0.0692139 -30 10 18 1 0 0.286133 -30 10 19 1 0 0.406494 -30 10 20 1 0 0.503906 -30 10 21 1 0 0.586914 -30 10 22 1 0 0.664551 -30 10 23 1 0 0.733887 -30 10 24 1 0.0721436 0.794922 -30 10 25 1 0.236328 0.853027 -30 10 26 1 0.316162 0.906738 -30 10 27 1 0.369141 0.955078 -30 10 28 1 0.397461 0.998047 -30 10 29 1 0.403564 1 -30 10 30 1 0.400391 1 -30 10 31 1 0.395508 1 -30 11 0 1 0 0.0733643 -30 11 1 1 0 0.0733643 -30 11 2 1 0 0.0733643 -30 11 3 1 0 0.0733643 -30 11 4 1 0 0.0733643 -30 11 5 1 0 0.0733643 -30 11 6 1 0 0.0733643 -30 11 7 1 0 0.0733032 -30 11 8 1 0 0.0733032 -30 11 9 1 0 0.0732422 -30 11 10 1 0 0.0731201 -30 11 11 1 0 0.072876 -30 11 12 1 0 0.0725098 -30 11 13 1 0 0.0718384 -30 11 14 1 0 0.0708618 -30 11 15 1 0 0.0692139 -30 11 16 1 0 0.067749 -30 11 17 1 0 0.0661621 -30 11 18 1 0 0.285889 -30 11 19 1 0 0.406494 -30 11 20 1 0 0.503906 -30 11 21 1 0 0.586914 -30 11 22 1 0 0.664551 -30 11 23 1 0 0.733887 -30 11 24 1 0.109436 0.794922 -30 11 25 1 0.243896 0.853027 -30 11 26 1 0.320801 0.906738 -30 11 27 1 0.372803 0.955078 -30 11 28 1 0.400391 0.998047 -30 11 29 1 0.406494 1 -30 11 30 1 0.403076 1 -30 11 31 1 0.397949 1 -30 12 0 1 0 0.0684814 -30 12 1 1 0 0.0684814 -30 12 2 1 0 0.0684814 -30 12 3 1 0 0.0684814 -30 12 4 1 0 0.0684814 -30 12 5 1 0 0.0684814 -30 12 6 1 0 0.0684814 -30 12 7 1 0 0.0684814 -30 12 8 1 0 0.0684204 -30 12 9 1 0 0.0683594 -30 12 10 1 0 0.0681763 -30 12 11 1 0 0.0679321 -30 12 12 1 0 0.0675049 -30 12 13 1 0 0.0668335 -30 12 14 1 0 0.0656738 -30 12 15 1 0 0.0638428 -30 12 16 1 0 0.0621643 -30 12 17 1 0 0.0603943 -30 12 18 1 0 0.285889 -30 12 19 1 0 0.40625 -30 12 20 1 0 0.503418 -30 12 21 1 0 0.586914 -30 12 22 1 0 0.664062 -30 12 23 1 0 0.733398 -30 12 24 1 0.146362 0.794922 -30 12 25 1 0.256104 0.853027 -30 12 26 1 0.328613 0.906738 -30 12 27 1 0.378662 0.955078 -30 12 28 1 0.405518 0.998047 -30 12 29 1 0.411133 1 -30 12 30 1 0.407471 1 -30 12 31 1 0.401855 1 -30 13 0 1 0 0.0589905 -30 13 1 1 0 0.0589905 -30 13 2 1 0 0.0589905 -30 13 3 1 0 0.0589905 -30 13 4 1 0 0.0589905 -30 13 5 1 0 0.0589905 -30 13 6 1 0 0.05896 -30 13 7 1 0 0.05896 -30 13 8 1 0 0.0588989 -30 13 9 1 0 0.0588074 -30 13 10 1 0 0.0586243 -30 13 11 1 0 0.0582886 -30 13 12 1 0 0.0577393 -30 13 13 1 0 0.0568237 -30 13 14 1 0 0.0553284 -30 13 15 1 0 0.052887 -30 13 16 1 0 0.0505981 -30 13 17 1 0 0.0482483 -30 13 18 1 0 0.2854 -30 13 19 1 0 0.406006 -30 13 20 1 0 0.50293 -30 13 21 1 0 0.586914 -30 13 22 1 0 0.664062 -30 13 23 1 0 0.733398 -30 13 24 1 0.186401 0.794434 -30 13 25 1 0.27417 0.853027 -30 13 26 1 0.340576 0.906738 -30 13 27 1 0.388184 0.955078 -30 13 28 1 0.413818 0.998047 -30 13 29 1 0.418945 1 -30 13 30 1 0.414795 1 -30 13 31 1 0.408691 1 -30 14 0 1 0 0.0341492 -30 14 1 1 0 0.0341492 -30 14 2 1 0 0.0341492 -30 14 3 1 0 0.0341492 -30 14 4 1 0 0.0341492 -30 14 5 1 0 0.0341187 -30 14 6 1 0 0.0340881 -30 14 7 1 0 0.0340271 -30 14 8 1 0 0.033905 -30 14 9 1 0 0.0336609 -30 14 10 1 0 0.0332031 -30 14 11 1 0 0.0324097 -30 14 12 1 0 0.0309601 -30 14 13 1 0 0.0283051 -30 14 14 1 0 0.0230103 -30 14 15 1 0.0296021 0 -30 14 16 1 0.0753784 0 -30 14 17 1 0.0944214 0 -30 14 18 1 0.0440674 0.285156 -30 14 19 1 0 0.405518 -30 14 20 1 0 0.502441 -30 14 21 1 0 0.586914 -30 14 22 1 0 0.663574 -30 14 23 1 0.152954 0.73291 -30 14 24 1 0.230835 0.794434 -30 14 25 1 0.299561 0.853027 -30 14 26 1 0.358398 0.906738 -30 14 27 1 0.402344 0.955078 -30 14 28 1 0.42627 0.998047 -30 14 29 1 0.430664 1 -30 14 30 1 0.425781 1 -30 14 31 1 0.418701 1 -30 15 0 1 0.186279 0 -30 15 1 1 0.186279 0 -30 15 2 1 0.186279 0 -30 15 3 1 0.186279 0 -30 15 4 1 0.186401 0 -30 15 5 1 0.186401 0 -30 15 6 1 0.186401 0 -30 15 7 1 0.186523 0 -30 15 8 1 0.186646 0 -30 15 9 1 0.187012 0 -30 15 10 1 0.187622 0 -30 15 11 1 0.188721 0 -30 15 12 1 0.19043 0 -30 15 13 1 0.193359 0 -30 15 14 1 0.197754 0 -30 15 15 1 0.204224 0 -30 15 16 1 0.209473 0 -30 15 17 1 0.213257 0 -30 15 18 1 0.204834 0.284912 -30 15 19 1 0.195557 0.404785 -30 15 20 1 0.194214 0.501465 -30 15 21 1 0.195435 0.586914 -30 15 22 1 0.201294 0.663086 -30 15 23 1 0.233765 0.732422 -30 15 24 1 0.280273 0.793945 -30 15 25 1 0.333008 0.852539 -30 15 26 1 0.383301 0.906738 -30 15 27 1 0.422852 0.955078 -30 15 28 1 0.44458 0.998047 -30 15 29 1 0.44751 1 -30 15 30 1 0.44165 1 -30 15 31 1 0.433594 1 -30 16 0 1 0.280029 0 -30 16 1 1 0.280029 0 -30 16 2 1 0.280029 0 -30 16 3 1 0.280029 0 -30 16 4 1 0.280029 0 -30 16 5 1 0.280029 0 -30 16 6 1 0.280029 0 -30 16 7 1 0.280029 0 -30 16 8 1 0.280029 0 -30 16 9 1 0.280273 0 -30 16 10 1 0.280518 0 -30 16 11 1 0.28125 0 -30 16 12 1 0.282227 0 -30 16 13 1 0.283691 0 -30 16 14 1 0.286133 0 -30 16 15 1 0.289795 0 -30 16 16 1 0.292725 0 -30 16 17 1 0.294434 0 -30 16 18 1 0.290039 0.285156 -30 16 19 1 0.285156 0.404297 -30 16 20 1 0.283936 0.500488 -30 16 21 1 0.288086 0.586914 -30 16 22 1 0.288574 0.662598 -30 16 23 1 0.305176 0.731445 -30 16 24 1 0.334961 0.792969 -30 16 25 1 0.374512 0.852051 -30 16 26 1 0.416016 0.90625 -30 16 27 1 0.450195 0.955078 -30 16 28 1 0.469238 0.998047 -30 16 29 1 0.470703 1 -30 16 30 1 0.463623 1 -30 16 31 1 0.454102 1 -30 17 0 1 0.359375 0 -30 17 1 1 0.359375 0 -30 17 2 1 0.359375 0 -30 17 3 1 0.359375 0 -30 17 4 1 0.359375 0 -30 17 5 1 0.359375 0 -30 17 6 1 0.359375 0 -30 17 7 1 0.359619 0 -30 17 8 1 0.359619 0 -30 17 9 1 0.359619 0 -30 17 10 1 0.359863 0 -30 17 11 1 0.360352 0 -30 17 12 1 0.36084 0 -30 17 13 1 0.362061 0 -30 17 14 1 0.36377 0 -30 17 15 1 0.366211 0 -30 17 16 1 0.368164 0 -30 17 17 1 0.369141 0 -30 17 18 1 0.366455 0.286621 -30 17 19 1 0.36377 0.404297 -30 17 20 1 0.362305 0.499268 -30 17 21 1 0.365723 0.585938 -30 17 22 1 0.366211 0.661621 -30 17 23 1 0.374512 0.730469 -30 17 24 1 0.393311 0.791992 -30 17 25 1 0.422363 0.851074 -30 17 26 1 0.455566 0.905762 -30 17 27 1 0.484375 0.95459 -30 17 28 1 0.500488 0.998047 -30 17 29 1 0.500488 1 -30 17 30 1 0.491699 1 -30 17 31 1 0.480469 1 -30 18 0 1 0.433838 0 -30 18 1 1 0.433838 0 -30 18 2 1 0.433838 0 -30 18 3 1 0.433838 0 -30 18 4 1 0.433838 0 -30 18 5 1 0.433838 0 -30 18 6 1 0.433838 0 -30 18 7 1 0.433838 0 -30 18 8 1 0.433838 0 -30 18 9 1 0.433838 0 -30 18 10 1 0.434082 0 -30 18 11 1 0.434326 0 -30 18 12 1 0.434814 0 -30 18 13 1 0.435547 0 -30 18 14 1 0.436768 0 -30 18 15 1 0.438721 0 -30 18 16 1 0.44043 0 -30 18 17 1 0.44043 0 -30 18 18 1 0.439453 0.290771 -30 18 19 1 0.437988 0.405273 -30 18 20 1 0.436768 0.498779 -30 18 21 1 0.437744 0.583984 -30 18 22 1 0.440186 0.661133 -30 18 23 1 0.443115 0.728516 -30 18 24 1 0.454346 0.790039 -30 18 25 1 0.474609 0.849609 -30 18 26 1 0.5 0.904785 -30 18 27 1 0.523926 0.954102 -30 18 28 1 0.537109 0.997559 -30 18 29 1 0.535156 1 -30 18 30 1 0.524902 1 -30 18 31 1 0.511719 1 -30 19 0 1 0.503906 0 -30 19 1 1 0.503906 0 -30 19 2 1 0.503906 0 -30 19 3 1 0.503906 0 -30 19 4 1 0.503906 0 -30 19 5 1 0.503906 0 -30 19 6 1 0.503906 0 -30 19 7 1 0.503906 0 -30 19 8 1 0.503906 0 -30 19 9 1 0.503906 0 -30 19 10 1 0.503906 0 -30 19 11 1 0.504395 0 -30 19 12 1 0.504883 0 -30 19 13 1 0.505371 0 -30 19 14 1 0.506348 0 -30 19 15 1 0.507812 0 -30 19 16 1 0.509277 0 -30 19 17 1 0.509277 0.0790405 -30 19 18 1 0.509277 0.298828 -30 19 19 1 0.508789 0.408447 -30 19 20 1 0.507812 0.499023 -30 19 21 1 0.507812 0.582031 -30 19 22 1 0.510254 0.659668 -30 19 23 1 0.510742 0.726562 -30 19 24 1 0.515625 0.787598 -30 19 25 1 0.528809 0.847656 -30 19 26 1 0.547852 0.90332 -30 19 27 1 0.566406 0.953125 -30 19 28 1 0.57666 0.99707 -30 19 29 1 0.573242 1 -30 19 30 1 0.561035 1 -30 19 31 1 0.545898 1 -30 20 0 1 0.569336 0 -30 20 1 1 0.569336 0 -30 20 2 1 0.569336 0 -30 20 3 1 0.569336 0 -30 20 4 1 0.569336 0 -30 20 5 1 0.569336 0 -30 20 6 1 0.569336 0 -30 20 7 1 0.569336 0 -30 20 8 1 0.569336 0 -30 20 9 1 0.569336 0 -30 20 10 1 0.569336 0 -30 20 11 1 0.569824 0 -30 20 12 1 0.569824 0 -30 20 13 1 0.570312 0 -30 20 14 1 0.571289 0 -30 20 15 1 0.572266 0 -30 20 16 1 0.57373 0 -30 20 17 1 0.574219 0.145752 -30 20 18 1 0.575195 0.311035 -30 20 19 1 0.575684 0.414307 -30 20 20 1 0.575195 0.501465 -30 20 21 1 0.574707 0.581543 -30 20 22 1 0.574219 0.656738 -30 20 23 1 0.575684 0.724609 -30 20 24 1 0.576172 0.784668 -30 20 25 1 0.583008 0.844238 -30 20 26 1 0.595703 0.900879 -30 20 27 1 0.610352 0.95166 -30 20 28 1 0.618164 0.995605 -30 20 29 1 0.613281 1 -30 20 30 1 0.599121 1 -30 20 31 1 0.58252 1 -30 21 0 1 0.630859 0 -30 21 1 1 0.630859 0 -30 21 2 1 0.630859 0 -30 21 3 1 0.630859 0 -30 21 4 1 0.630859 0 -30 21 5 1 0.630859 0 -30 21 6 1 0.630859 0 -30 21 7 1 0.630859 0 -30 21 8 1 0.630859 0 -30 21 9 1 0.630859 0 -30 21 10 1 0.630859 0 -30 21 11 1 0.631348 0 -30 21 12 1 0.631348 0 -30 21 13 1 0.631836 0 -30 21 14 1 0.632324 0 -30 21 15 1 0.633301 0 -30 21 16 1 0.634766 0 -30 21 17 1 0.63623 0.194702 -30 21 18 1 0.638184 0.327393 -30 21 19 1 0.63916 0.423096 -30 21 20 1 0.639648 0.505859 -30 21 21 1 0.638672 0.58252 -30 21 22 1 0.637695 0.654785 -30 21 23 1 0.637207 0.72168 -30 21 24 1 0.636719 0.78125 -30 21 25 1 0.637695 0.840332 -30 21 26 1 0.64502 0.897949 -30 21 27 1 0.654785 0.949219 -30 21 28 1 0.660156 0.994141 -30 21 29 1 0.653809 1 -30 21 30 1 0.638672 1 -30 21 31 1 0.620117 1 -30 22 0 1 0.688477 0 -30 22 1 1 0.688477 0 -30 22 2 1 0.688477 0 -30 22 3 1 0.688477 0 -30 22 4 1 0.688477 0 -30 22 5 1 0.688477 0 -30 22 6 1 0.688477 0 -30 22 7 1 0.688477 0 -30 22 8 1 0.688477 0 -30 22 9 1 0.688477 0 -30 22 10 1 0.688477 0 -30 22 11 1 0.688965 0 -30 22 12 1 0.688965 0 -30 22 13 1 0.689453 0 -30 22 14 1 0.689941 0 -30 22 15 1 0.69043 0 -30 22 16 1 0.691895 0 -30 22 17 1 0.693848 0.236816 -30 22 18 1 0.696289 0.346924 -30 22 19 1 0.698242 0.434814 -30 22 20 1 0.699707 0.512695 -30 22 21 1 0.699219 0.585449 -30 22 22 1 0.697754 0.654297 -30 22 23 1 0.695801 0.718262 -30 22 24 1 0.694336 0.777344 -30 22 25 1 0.691895 0.835938 -30 22 26 1 0.693359 0.893555 -30 22 27 1 0.699219 0.946289 -30 22 28 1 0.702148 0.991699 -30 22 29 1 0.694824 1 -30 22 30 1 0.678223 1 -30 22 31 1 0.657715 1 -30 23 0 1 0.740723 0.127075 -30 23 1 1 0.740723 0.127075 -30 23 2 1 0.740723 0.127075 -30 23 3 1 0.740723 0.127075 -30 23 4 1 0.740723 0.127075 -30 23 5 1 0.740723 0.127075 -30 23 6 1 0.740723 0.127075 -30 23 7 1 0.740723 0.127197 -30 23 8 1 0.740723 0.127197 -30 23 9 1 0.740723 0.127319 -30 23 10 1 0.740723 0.127441 -30 23 11 1 0.740723 0.127686 -30 23 12 1 0.741211 0.128052 -30 23 13 1 0.741211 0.128784 -30 23 14 1 0.741699 0.129883 -30 23 15 1 0.742188 0.131592 -30 23 16 1 0.743164 0.134033 -30 23 17 1 0.746094 0.272217 -30 23 18 1 0.748535 0.366699 -30 23 19 1 0.750977 0.44751 -30 23 20 1 0.75293 0.520996 -30 23 21 1 0.753418 0.590332 -30 23 22 1 0.752441 0.655762 -30 23 23 1 0.75 0.716309 -30 23 24 1 0.746582 0.772949 -30 23 25 1 0.743652 0.831055 -30 23 26 1 0.740234 0.888184 -30 23 27 1 0.741211 0.941895 -30 23 28 1 0.742188 0.988281 -30 23 29 1 0.733887 1 -30 23 30 1 0.716309 1 -30 23 31 1 0.694336 1 -30 24 0 1 0.787598 0.212646 -30 24 1 1 0.787598 0.212646 -30 24 2 1 0.787598 0.212646 -30 24 3 1 0.787598 0.212646 -30 24 4 1 0.787598 0.212646 -30 24 5 1 0.787598 0.212646 -30 24 6 1 0.787598 0.212646 -30 24 7 1 0.787598 0.212646 -30 24 8 1 0.787598 0.212646 -30 24 9 1 0.787598 0.212646 -30 24 10 1 0.787598 0.212769 -30 24 11 1 0.788086 0.212891 -30 24 12 1 0.788086 0.213013 -30 24 13 1 0.788086 0.213379 -30 24 14 1 0.788574 0.213745 -30 24 15 1 0.789062 0.214478 -30 24 16 1 0.790039 0.215454 -30 24 17 1 0.79248 0.301758 -30 24 18 1 0.79541 0.385254 -30 24 19 1 0.79834 0.460205 -30 24 20 1 0.800781 0.529785 -30 24 21 1 0.802246 0.595703 -30 24 22 1 0.801758 0.657715 -30 24 23 1 0.799805 0.715332 -30 24 24 1 0.795898 0.769531 -30 24 25 1 0.791016 0.825684 -30 24 26 1 0.785156 0.881836 -30 24 27 1 0.781738 0.936523 -30 24 28 1 0.779785 0.984375 -30 24 29 1 0.771484 1 -30 24 30 1 0.75293 1 -30 24 31 1 0.729492 1 -30 25 0 1 0.834473 0.264404 -30 25 1 1 0.834473 0.264404 -30 25 2 1 0.834473 0.264404 -30 25 3 1 0.834473 0.264404 -30 25 4 1 0.834473 0.264404 -30 25 5 1 0.834473 0.264404 -30 25 6 1 0.834473 0.264404 -30 25 7 1 0.834473 0.264404 -30 25 8 1 0.834473 0.264404 -30 25 9 1 0.834473 0.264404 -30 25 10 1 0.834473 0.264648 -30 25 11 1 0.834473 0.264648 -30 25 12 1 0.834961 0.264648 -30 25 13 1 0.834961 0.264893 -30 25 14 1 0.835449 0.265137 -30 25 15 1 0.835449 0.265625 -30 25 16 1 0.836426 0.266113 -30 25 17 1 0.838867 0.327148 -30 25 18 1 0.841797 0.402344 -30 25 19 1 0.845215 0.472656 -30 25 20 1 0.848145 0.538574 -30 25 21 1 0.849609 0.601074 -30 25 22 1 0.850098 0.661133 -30 25 23 1 0.848633 0.71582 -30 25 24 1 0.845215 0.76709 -30 25 25 1 0.839844 0.819824 -30 25 26 1 0.83252 0.875 -30 25 27 1 0.824707 0.929199 -30 25 28 1 0.819824 0.978516 -30 25 29 1 0.810547 1 -30 25 30 1 0.791016 1 -30 25 31 1 0.76709 1 -30 26 0 1 0.880859 0.30127 -30 26 1 1 0.880859 0.30127 -30 26 2 1 0.880859 0.30127 -30 26 3 1 0.880859 0.30127 -30 26 4 1 0.880859 0.30127 -30 26 5 1 0.880859 0.30127 -30 26 6 1 0.880859 0.30127 -30 26 7 1 0.880859 0.30127 -30 26 8 1 0.880859 0.30127 -30 26 9 1 0.880859 0.30127 -30 26 10 1 0.880859 0.30127 -30 26 11 1 0.880859 0.30127 -30 26 12 1 0.881348 0.30127 -30 26 13 1 0.881348 0.301514 -30 26 14 1 0.881348 0.301514 -30 26 15 1 0.881836 0.301758 -30 26 16 1 0.882324 0.302002 -30 26 17 1 0.884277 0.346436 -30 26 18 1 0.887695 0.415771 -30 26 19 1 0.891113 0.482422 -30 26 20 1 0.894043 0.54541 -30 26 21 1 0.896484 0.605957 -30 26 22 1 0.896973 0.663574 -30 26 23 1 0.896484 0.716309 -30 26 24 1 0.894043 0.765137 -30 26 25 1 0.88916 0.814941 -30 26 26 1 0.881348 0.866699 -30 26 27 1 0.871094 0.919922 -30 26 28 1 0.861328 0.970703 -30 26 29 1 0.851562 1 -30 26 30 1 0.831543 1 -30 26 31 1 0.806641 1 -30 27 0 1 0.92627 0.325195 -30 27 1 1 0.92627 0.325195 -30 27 2 1 0.92627 0.325195 -30 27 3 1 0.92627 0.325195 -30 27 4 1 0.92627 0.325195 -30 27 5 1 0.92627 0.325195 -30 27 6 1 0.92627 0.325195 -30 27 7 1 0.92627 0.325195 -30 27 8 1 0.926758 0.325195 -30 27 9 1 0.926758 0.325195 -30 27 10 1 0.926758 0.325195 -30 27 11 1 0.926758 0.325195 -30 27 12 1 0.926758 0.325439 -30 27 13 1 0.926758 0.325439 -30 27 14 1 0.926758 0.325439 -30 27 15 1 0.927246 0.325684 -30 27 16 1 0.927734 0.325684 -30 27 17 1 0.929199 0.356934 -30 27 18 1 0.932617 0.422852 -30 27 19 1 0.936035 0.487061 -30 27 20 1 0.938965 0.54834 -30 27 21 1 0.941406 0.607422 -30 27 22 1 0.942871 0.663574 -30 27 23 1 0.942383 0.714844 -30 27 24 1 0.94043 0.762207 -30 27 25 1 0.936523 0.810547 -30 27 26 1 0.929688 0.859375 -30 27 27 1 0.918945 0.90918 -30 27 28 1 0.905762 0.959961 -30 27 29 1 0.893555 1 -30 27 30 1 0.874023 1 -30 27 31 1 0.848145 1 -30 28 0 1 0.970215 0.336914 -30 28 1 1 0.970215 0.336914 -30 28 2 1 0.970215 0.336914 -30 28 3 1 0.970215 0.336914 -30 28 4 1 0.970215 0.336914 -30 28 5 1 0.970215 0.336914 -30 28 6 1 0.970215 0.336914 -30 28 7 1 0.970215 0.336914 -30 28 8 1 0.970215 0.336914 -30 28 9 1 0.970215 0.336914 -30 28 10 1 0.970703 0.336914 -30 28 11 1 0.970703 0.336914 -30 28 12 1 0.970703 0.336914 -30 28 13 1 0.970703 0.336914 -30 28 14 1 0.970703 0.336914 -30 28 15 1 0.971191 0.336914 -30 28 16 1 0.971191 0.336914 -30 28 17 1 0.972656 0.356445 -30 28 18 1 0.975586 0.420898 -30 28 19 1 0.979004 0.483887 -30 28 20 1 0.982422 0.543945 -30 28 21 1 0.984863 0.602539 -30 28 22 1 0.986328 0.657715 -30 28 23 1 0.986328 0.708984 -30 28 24 1 0.984863 0.755859 -30 28 25 1 0.981445 0.803711 -30 28 26 1 0.975586 0.851562 -30 28 27 1 0.966309 0.899414 -30 28 28 1 0.952637 0.946777 -30 28 29 1 0.936523 0.993652 -30 28 30 1 0.91748 1 -30 28 31 1 0.890625 1 -30 29 0 1 1 0.337158 -30 29 1 1 1 0.337158 -30 29 2 1 1 0.337158 -30 29 3 1 1 0.337158 -30 29 4 1 1 0.337158 -30 29 5 1 1 0.337158 -30 29 6 1 1 0.337158 -30 29 7 1 1 0.337158 -30 29 8 1 1 0.337158 -30 29 9 1 1 0.337158 -30 29 10 1 1 0.337158 -30 29 11 1 1 0.337158 -30 29 12 1 1 0.337158 -30 29 13 1 1 0.337158 -30 29 14 1 1 0.337158 -30 29 15 1 1 0.337158 -30 29 16 1 1 0.336914 -30 29 17 1 1 0.344238 -30 29 18 1 1 0.40918 -30 29 19 1 1 0.471924 -30 29 20 1 1 0.531738 -30 29 21 1 1 0.589844 -30 29 22 1 1 0.64502 -30 29 23 1 1 0.695801 -30 29 24 1 1 0.742676 -30 29 25 1 1 0.790527 -30 29 26 1 1 0.838867 -30 29 27 1 1 0.887207 -30 29 28 1 0.998047 0.934082 -30 29 29 1 0.980957 0.978516 -30 29 30 1 0.961426 1 -30 29 31 0.991699 0.934082 1 -30 30 0 1 1 0.32959 -30 30 1 1 1 0.32959 -30 30 2 1 1 0.32959 -30 30 3 1 1 0.32959 -30 30 4 1 1 0.32959 -30 30 5 1 1 0.32959 -30 30 6 1 1 0.32959 -30 30 7 1 1 0.32959 -30 30 8 1 1 0.32959 -30 30 9 1 1 0.32959 -30 30 10 1 1 0.32959 -30 30 11 1 1 0.32959 -30 30 12 1 1 0.32959 -30 30 13 1 1 0.32959 -30 30 14 1 1 0.329346 -30 30 15 1 1 0.329346 -30 30 16 1 1 0.329346 -30 30 17 1 1 0.329346 -30 30 18 1 1 0.38916 -30 30 19 1 1 0.452393 -30 30 20 1 1 0.512207 -30 30 21 1 1 0.569824 -30 30 22 1 1 0.625 -30 30 23 1 1 0.675781 -30 30 24 1 1 0.722656 -30 30 25 1 1 0.770508 -30 30 26 1 1 0.819336 -30 30 27 1 1 0.868164 -30 30 28 1 1 0.916016 -30 30 29 1 1 0.961914 -30 30 30 1 1 1 -30 30 31 0.959961 0.977539 1 -30 31 0 1 1 0.318848 -30 31 1 1 1 0.318848 -30 31 2 1 1 0.318848 -30 31 3 1 1 0.318848 -30 31 4 1 1 0.318848 -30 31 5 1 1 0.318848 -30 31 6 1 1 0.318848 -30 31 7 1 1 0.318848 -30 31 8 1 1 0.318848 -30 31 9 1 1 0.318848 -30 31 10 1 1 0.318848 -30 31 11 1 1 0.318848 -30 31 12 1 1 0.318848 -30 31 13 1 1 0.318848 -30 31 14 1 1 0.318848 -30 31 15 1 1 0.318848 -30 31 16 1 1 0.318848 -30 31 17 1 1 0.318848 -30 31 18 1 1 0.364502 -30 31 19 1 1 0.428711 -30 31 20 1 1 0.488525 -30 31 21 1 1 0.545898 -30 31 22 1 1 0.600586 -30 31 23 1 1 0.650391 -30 31 24 1 1 0.696777 -30 31 25 1 1 0.744629 -30 31 26 1 1 0.793457 -30 31 27 1 1 0.842773 -30 31 28 1 1 0.891602 -30 31 29 0.994629 1 0.938965 -30 31 30 0.962402 1 0.983398 -30 31 31 0.92334 1 1 -31 0 0 1 0 0.079895 -31 0 1 1 0 0.079895 -31 0 2 1 0 0.079895 -31 0 3 1 0 0.079895 -31 0 4 1 0 0.079895 -31 0 5 1 0 0.079895 -31 0 6 1 0 0.079895 -31 0 7 1 0 0.079834 -31 0 8 1 0 0.079834 -31 0 9 1 0 0.0797729 -31 0 10 1 0 0.0797119 -31 0 11 1 0 0.0795288 -31 0 12 1 0 0.0792236 -31 0 13 1 0 0.0787964 -31 0 14 1 0 0.0780029 -31 0 15 1 0 0.0768433 -31 0 16 1 0 0.0753174 -31 0 17 1 0 0.0742798 -31 0 18 1 0 0.203247 -31 0 19 1 0 0.346924 -31 0 20 1 0 0.447266 -31 0 21 1 0 0.533203 -31 0 22 1 0 0.608398 -31 0 23 1 0 0.677246 -31 0 24 1 0 0.739258 -31 0 25 1 0 0.799805 -31 0 26 1 0.217285 0.85791 -31 0 27 1 0.307129 0.911621 -31 0 28 1 0.364502 0.959473 -31 0 29 1 0.39502 1 -31 0 30 1 0.401611 1 -31 0 31 1 0.398438 1 -31 1 0 1 0 0.079895 -31 1 1 1 0 0.079895 -31 1 2 1 0 0.079895 -31 1 3 1 0 0.079895 -31 1 4 1 0 0.079895 -31 1 5 1 0 0.079895 -31 1 6 1 0 0.079895 -31 1 7 1 0 0.079834 -31 1 8 1 0 0.079834 -31 1 9 1 0 0.0797729 -31 1 10 1 0 0.0796509 -31 1 11 1 0 0.0795288 -31 1 12 1 0 0.0792236 -31 1 13 1 0 0.0787354 -31 1 14 1 0 0.0780029 -31 1 15 1 0 0.0768433 -31 1 16 1 0 0.0753174 -31 1 17 1 0 0.0742798 -31 1 18 1 0 0.203247 -31 1 19 1 0 0.346924 -31 1 20 1 0 0.447266 -31 1 21 1 0 0.533203 -31 1 22 1 0 0.608398 -31 1 23 1 0 0.677246 -31 1 24 1 0 0.739258 -31 1 25 1 0 0.799805 -31 1 26 1 0.217407 0.85791 -31 1 27 1 0.307129 0.911621 -31 1 28 1 0.364502 0.959473 -31 1 29 1 0.39502 1 -31 1 30 1 0.401611 1 -31 1 31 1 0.398438 1 -31 2 0 1 0 0.079895 -31 2 1 1 0 0.079895 -31 2 2 1 0 0.079895 -31 2 3 1 0 0.079895 -31 2 4 1 0 0.079895 -31 2 5 1 0 0.079895 -31 2 6 1 0 0.079834 -31 2 7 1 0 0.079834 -31 2 8 1 0 0.079834 -31 2 9 1 0 0.0797729 -31 2 10 1 0 0.0796509 -31 2 11 1 0 0.0795288 -31 2 12 1 0 0.0792236 -31 2 13 1 0 0.0787354 -31 2 14 1 0 0.0780029 -31 2 15 1 0 0.0768433 -31 2 16 1 0 0.0753174 -31 2 17 1 0 0.0742798 -31 2 18 1 0 0.203247 -31 2 19 1 0 0.346924 -31 2 20 1 0 0.447266 -31 2 21 1 0 0.533203 -31 2 22 1 0 0.608398 -31 2 23 1 0 0.677246 -31 2 24 1 0 0.739258 -31 2 25 1 0 0.799805 -31 2 26 1 0.217407 0.85791 -31 2 27 1 0.307129 0.911621 -31 2 28 1 0.364502 0.959473 -31 2 29 1 0.39502 1 -31 2 30 1 0.401611 1 -31 2 31 1 0.398438 1 -31 3 0 1 0 0.079834 -31 3 1 1 0 0.079834 -31 3 2 1 0 0.079834 -31 3 3 1 0 0.079834 -31 3 4 1 0 0.079834 -31 3 5 1 0 0.079834 -31 3 6 1 0 0.079834 -31 3 7 1 0 0.079834 -31 3 8 1 0 0.079834 -31 3 9 1 0 0.0797729 -31 3 10 1 0 0.0796509 -31 3 11 1 0 0.0794678 -31 3 12 1 0 0.0792236 -31 3 13 1 0 0.0787354 -31 3 14 1 0 0.0780029 -31 3 15 1 0 0.0768433 -31 3 16 1 0 0.0753174 -31 3 17 1 0 0.0742798 -31 3 18 1 0 0.203247 -31 3 19 1 0 0.346924 -31 3 20 1 0 0.447266 -31 3 21 1 0 0.533203 -31 3 22 1 0 0.608398 -31 3 23 1 0 0.677246 -31 3 24 1 0 0.739258 -31 3 25 1 0 0.799805 -31 3 26 1 0.217407 0.85791 -31 3 27 1 0.307129 0.911621 -31 3 28 1 0.364502 0.959473 -31 3 29 1 0.39502 1 -31 3 30 1 0.401611 1 -31 3 31 1 0.398438 1 -31 4 0 1 0 0.079834 -31 4 1 1 0 0.079834 -31 4 2 1 0 0.079834 -31 4 3 1 0 0.079834 -31 4 4 1 0 0.079834 -31 4 5 1 0 0.079834 -31 4 6 1 0 0.079834 -31 4 7 1 0 0.079834 -31 4 8 1 0 0.0797729 -31 4 9 1 0 0.0797119 -31 4 10 1 0 0.0796509 -31 4 11 1 0 0.0794678 -31 4 12 1 0 0.0791626 -31 4 13 1 0 0.0787354 -31 4 14 1 0 0.0779419 -31 4 15 1 0 0.0767822 -31 4 16 1 0 0.0752563 -31 4 17 1 0 0.0742188 -31 4 18 1 0 0.203247 -31 4 19 1 0 0.346924 -31 4 20 1 0 0.447266 -31 4 21 1 0 0.533203 -31 4 22 1 0 0.608398 -31 4 23 1 0 0.677246 -31 4 24 1 0 0.739258 -31 4 25 1 0 0.799805 -31 4 26 1 0.217529 0.85791 -31 4 27 1 0.307373 0.911621 -31 4 28 1 0.364502 0.959473 -31 4 29 1 0.39502 1 -31 4 30 1 0.401855 1 -31 4 31 1 0.398682 1 -31 5 0 1 0 0.0797729 -31 5 1 1 0 0.0797729 -31 5 2 1 0 0.0797729 -31 5 3 1 0 0.0797729 -31 5 4 1 0 0.0797729 -31 5 5 1 0 0.0797729 -31 5 6 1 0 0.0797729 -31 5 7 1 0 0.0797729 -31 5 8 1 0 0.0797119 -31 5 9 1 0 0.0797119 -31 5 10 1 0 0.0795898 -31 5 11 1 0 0.0794067 -31 5 12 1 0 0.0791626 -31 5 13 1 0 0.0786743 -31 5 14 1 0 0.0779419 -31 5 15 1 0 0.0767212 -31 5 16 1 0 0.0752563 -31 5 17 1 0 0.0742188 -31 5 18 1 0 0.203247 -31 5 19 1 0 0.346924 -31 5 20 1 0 0.447266 -31 5 21 1 0 0.533203 -31 5 22 1 0 0.608398 -31 5 23 1 0 0.677246 -31 5 24 1 0 0.739258 -31 5 25 1 0 0.799805 -31 5 26 1 0.217651 0.85791 -31 5 27 1 0.307373 0.911621 -31 5 28 1 0.364746 0.959473 -31 5 29 1 0.39502 1 -31 5 30 1 0.401855 1 -31 5 31 1 0.398682 1 -31 6 0 1 0 0.0797119 -31 6 1 1 0 0.0797119 -31 6 2 1 0 0.0797119 -31 6 3 1 0 0.0797119 -31 6 4 1 0 0.0797119 -31 6 5 1 0 0.0797119 -31 6 6 1 0 0.0797119 -31 6 7 1 0 0.0796509 -31 6 8 1 0 0.0796509 -31 6 9 1 0 0.0795898 -31 6 10 1 0 0.0795288 -31 6 11 1 0 0.0793457 -31 6 12 1 0 0.0790405 -31 6 13 1 0 0.0786133 -31 6 14 1 0 0.0778198 -31 6 15 1 0 0.0766602 -31 6 16 1 0 0.0751343 -31 6 17 1 0 0.0740967 -31 6 18 1 0 0.203247 -31 6 19 1 0 0.346924 -31 6 20 1 0 0.447266 -31 6 21 1 0 0.533203 -31 6 22 1 0 0.608398 -31 6 23 1 0 0.677246 -31 6 24 1 0 0.739258 -31 6 25 1 0 0.799805 -31 6 26 1 0.218018 0.85791 -31 6 27 1 0.307617 0.911621 -31 6 28 1 0.364746 0.959473 -31 6 29 1 0.39502 1 -31 6 30 1 0.401855 1 -31 6 31 1 0.398682 1 -31 7 0 1 0 0.0795288 -31 7 1 1 0 0.0795288 -31 7 2 1 0 0.0795288 -31 7 3 1 0 0.0795288 -31 7 4 1 0 0.0795288 -31 7 5 1 0 0.0795288 -31 7 6 1 0 0.0795288 -31 7 7 1 0 0.0795288 -31 7 8 1 0 0.0794678 -31 7 9 1 0 0.0794067 -31 7 10 1 0 0.0793457 -31 7 11 1 0 0.0791626 -31 7 12 1 0 0.0788574 -31 7 13 1 0 0.0784302 -31 7 14 1 0 0.0776367 -31 7 15 1 0 0.0764771 -31 7 16 1 0 0.0749512 -31 7 17 1 0 0.0739136 -31 7 18 1 0 0.203247 -31 7 19 1 0 0.346924 -31 7 20 1 0 0.447266 -31 7 21 1 0 0.533203 -31 7 22 1 0 0.608398 -31 7 23 1 0 0.677246 -31 7 24 1 0 0.739258 -31 7 25 1 0 0.799805 -31 7 26 1 0.218628 0.85791 -31 7 27 1 0.307861 0.911621 -31 7 28 1 0.36499 0.959473 -31 7 29 1 0.395264 1 -31 7 30 1 0.4021 1 -31 7 31 1 0.398926 1 -31 8 0 1 0 0.0792236 -31 8 1 1 0 0.0792236 -31 8 2 1 0 0.0792236 -31 8 3 1 0 0.0792236 -31 8 4 1 0 0.0792236 -31 8 5 1 0 0.0792236 -31 8 6 1 0 0.0791626 -31 8 7 1 0 0.0791626 -31 8 8 1 0 0.0791626 -31 8 9 1 0 0.0791016 -31 8 10 1 0 0.0789795 -31 8 11 1 0 0.0788574 -31 8 12 1 0 0.0785522 -31 8 13 1 0 0.078064 -31 8 14 1 0 0.0773315 -31 8 15 1 0 0.0761108 -31 8 16 1 0 0.074585 -31 8 17 1 0 0.0735474 -31 8 18 1 0 0.203125 -31 8 19 1 0 0.346924 -31 8 20 1 0 0.447266 -31 8 21 1 0 0.533203 -31 8 22 1 0 0.608398 -31 8 23 1 0 0.677246 -31 8 24 1 0 0.739258 -31 8 25 1 0 0.799805 -31 8 26 1 0.219849 0.85791 -31 8 27 1 0.308594 0.911621 -31 8 28 1 0.365479 0.959473 -31 8 29 1 0.395752 1 -31 8 30 1 0.402588 1 -31 8 31 1 0.399414 1 -31 9 0 1 0 0.0785522 -31 9 1 1 0 0.0785522 -31 9 2 1 0 0.0785522 -31 9 3 1 0 0.0785522 -31 9 4 1 0 0.0785522 -31 9 5 1 0 0.0785522 -31 9 6 1 0 0.0785522 -31 9 7 1 0 0.0785522 -31 9 8 1 0 0.0784912 -31 9 9 1 0 0.0784302 -31 9 10 1 0 0.0783691 -31 9 11 1 0 0.078186 -31 9 12 1 0 0.0778809 -31 9 13 1 0 0.0773926 -31 9 14 1 0 0.0766602 -31 9 15 1 0 0.0754395 -31 9 16 1 0 0.0738525 -31 9 17 1 0 0.0728149 -31 9 18 1 0 0.203125 -31 9 19 1 0 0.346924 -31 9 20 1 0 0.447021 -31 9 21 1 0 0.533203 -31 9 22 1 0 0.608398 -31 9 23 1 0 0.677246 -31 9 24 1 0 0.739258 -31 9 25 1 0 0.799805 -31 9 26 1 0.222168 0.85791 -31 9 27 1 0.309814 0.911621 -31 9 28 1 0.366455 0.959473 -31 9 29 1 0.396729 1 -31 9 30 1 0.40332 1 -31 9 31 1 0.399902 1 -31 10 0 1 0 0.0773926 -31 10 1 1 0 0.0773926 -31 10 2 1 0 0.0773926 -31 10 3 1 0 0.0773926 -31 10 4 1 0 0.0773926 -31 10 5 1 0 0.0773315 -31 10 6 1 0 0.0773315 -31 10 7 1 0 0.0773315 -31 10 8 1 0 0.0773315 -31 10 9 1 0 0.0772705 -31 10 10 1 0 0.0771484 -31 10 11 1 0 0.0769653 -31 10 12 1 0 0.0766602 -31 10 13 1 0 0.0761719 -31 10 14 1 0 0.0753784 -31 10 15 1 0 0.0741577 -31 10 16 1 0 0.0725708 -31 10 17 1 0 0.0714722 -31 10 18 1 0 0.203003 -31 10 19 1 0 0.34668 -31 10 20 1 0 0.447021 -31 10 21 1 0 0.533203 -31 10 22 1 0 0.608398 -31 10 23 1 0 0.677246 -31 10 24 1 0 0.739258 -31 10 25 1 0 0.799805 -31 10 26 1 0.226318 0.85791 -31 10 27 1 0.312256 0.911621 -31 10 28 1 0.368408 0.959473 -31 10 29 1 0.398193 1 -31 10 30 1 0.404785 1 -31 10 31 1 0.401367 1 -31 11 0 1 0 0.0751953 -31 11 1 1 0 0.0751953 -31 11 2 1 0 0.0751953 -31 11 3 1 0 0.0751953 -31 11 4 1 0 0.0751953 -31 11 5 1 0 0.0751953 -31 11 6 1 0 0.0751953 -31 11 7 1 0 0.0751953 -31 11 8 1 0 0.0751343 -31 11 9 1 0 0.0750732 -31 11 10 1 0 0.0749512 -31 11 11 1 0 0.0747681 -31 11 12 1 0 0.0744629 -31 11 13 1 0 0.0739746 -31 11 14 1 0 0.0731201 -31 11 15 1 0 0.0718384 -31 11 16 1 0 0.0701294 -31 11 17 1 0 0.0690308 -31 11 18 1 0 0.202759 -31 11 19 1 0 0.34668 -31 11 20 1 0 0.447021 -31 11 21 1 0 0.533203 -31 11 22 1 0 0.608398 -31 11 23 1 0 0.676758 -31 11 24 1 0 0.73877 -31 11 25 1 0.028244 0.799805 -31 11 26 1 0.233398 0.85791 -31 11 27 1 0.316406 0.911621 -31 11 28 1 0.371338 0.959473 -31 11 29 1 0.400635 1 -31 11 30 1 0.406982 1 -31 11 31 1 0.403564 1 -31 12 0 1 0 0.071228 -31 12 1 1 0 0.071228 -31 12 2 1 0 0.071228 -31 12 3 1 0 0.071228 -31 12 4 1 0 0.071228 -31 12 5 1 0 0.071228 -31 12 6 1 0 0.071228 -31 12 7 1 0 0.071228 -31 12 8 1 0 0.071167 -31 12 9 1 0 0.071106 -31 12 10 1 0 0.0709839 -31 12 11 1 0 0.0708008 -31 12 12 1 0 0.0704346 -31 12 13 1 0 0.0698853 -31 12 14 1 0 0.0689697 -31 12 15 1 0 0.0675049 -31 12 16 1 0 0.0656128 -31 12 17 1 0 0.0644531 -31 12 18 1 0 0.202515 -31 12 19 1 0 0.346436 -31 12 20 1 0 0.446777 -31 12 21 1 0 0.533203 -31 12 22 1 0 0.608398 -31 12 23 1 0 0.676758 -31 12 24 1 0 0.73877 -31 12 25 1 0.10968 0.799805 -31 12 26 1 0.244629 0.85791 -31 12 27 1 0.323242 0.911621 -31 12 28 1 0.376465 0.959473 -31 12 29 1 0.405273 1 -31 12 30 1 0.411133 1 -31 12 31 1 0.407471 1 -31 13 0 1 0 0.0637817 -31 13 1 1 0 0.0637817 -31 13 2 1 0 0.0637817 -31 13 3 1 0 0.0637817 -31 13 4 1 0 0.0637817 -31 13 5 1 0 0.0637817 -31 13 6 1 0 0.0637817 -31 13 7 1 0 0.0637817 -31 13 8 1 0 0.0637207 -31 13 9 1 0 0.0636597 -31 13 10 1 0 0.0635376 -31 13 11 1 0 0.0632935 -31 13 12 1 0 0.0628662 -31 13 13 1 0 0.0621948 -31 13 14 1 0 0.0610657 -31 13 15 1 0 0.0592957 -31 13 16 1 0 0.0569458 -31 13 17 1 0 0.0555115 -31 13 18 1 0 0.202148 -31 13 19 1 0 0.346191 -31 13 20 1 0 0.446289 -31 13 21 1 0 0.533203 -31 13 22 1 0 0.608398 -31 13 23 1 0 0.676758 -31 13 24 1 0 0.73877 -31 13 25 1 0.158325 0.799805 -31 13 26 1 0.261475 0.85791 -31 13 27 1 0.33374 0.911621 -31 13 28 1 0.384766 0.959961 -31 13 29 1 0.412354 1 -31 13 30 1 0.417725 1 -31 13 31 1 0.413574 1 -31 14 0 1 0 0.04776 -31 14 1 1 0 0.04776 -31 14 2 1 0 0.0477295 -31 14 3 1 0 0.0477295 -31 14 4 1 0 0.0477295 -31 14 5 1 0 0.0477295 -31 14 6 1 0 0.047699 -31 14 7 1 0 0.0476685 -31 14 8 1 0 0.0476074 -31 14 9 1 0 0.0474854 -31 14 10 1 0 0.0472717 -31 14 11 1 0 0.0469055 -31 14 12 1 0 0.0462341 -31 14 13 1 0 0.0450745 -31 14 14 1 0 0.0431824 -31 14 15 1 0 0.039978 -31 14 16 1 0 0.0351868 -31 14 17 1 0 0.0322266 -31 14 18 1 0 0.201538 -31 14 19 1 0 0.345703 -31 14 20 1 0 0.445801 -31 14 21 1 0 0.533203 -31 14 22 1 0 0.608398 -31 14 23 1 0 0.67627 -31 14 24 1 0.0910034 0.738281 -31 14 25 1 0.205933 0.799316 -31 14 26 1 0.285156 0.85791 -31 14 27 1 0.349609 0.911621 -31 14 28 1 0.397217 0.959961 -31 14 29 1 0.423096 1 -31 14 30 1 0.427734 1 -31 14 31 1 0.422852 1 -31 15 0 1 0.137695 0 -31 15 1 1 0.137695 0 -31 15 2 1 0.137695 0 -31 15 3 1 0.137695 0 -31 15 4 1 0.137695 0 -31 15 5 1 0.137695 0 -31 15 6 1 0.137817 0 -31 15 7 1 0.137939 0 -31 15 8 1 0.138184 0 -31 15 9 1 0.138672 0 -31 15 10 1 0.139526 0 -31 15 11 1 0.140991 0 -31 15 12 1 0.143311 0 -31 15 13 1 0.147217 0 -31 15 14 1 0.152954 0 -31 15 15 1 0.161255 0 -31 15 16 1 0.170898 0 -31 15 17 1 0.174927 0 -31 15 18 1 0.173218 0.201172 -31 15 19 1 0.158691 0.345215 -31 15 20 1 0.147705 0.445312 -31 15 21 1 0.151733 0.532715 -31 15 22 1 0.142822 0.60791 -31 15 23 1 0.157471 0.67627 -31 15 24 1 0.199463 0.737793 -31 15 25 1 0.255859 0.799316 -31 15 26 1 0.316162 0.857422 -31 15 27 1 0.37207 0.911621 -31 15 28 1 0.415039 0.959961 -31 15 29 1 0.438965 1 -31 15 30 1 0.442383 1 -31 15 31 1 0.436768 1 -31 16 0 1 0.246216 0 -31 16 1 1 0.246216 0 -31 16 2 1 0.246216 0 -31 16 3 1 0.246216 0 -31 16 4 1 0.246216 0 -31 16 5 1 0.246216 0 -31 16 6 1 0.246216 0 -31 16 7 1 0.246216 0 -31 16 8 1 0.246338 0 -31 16 9 1 0.246582 0 -31 16 10 1 0.246826 0 -31 16 11 1 0.247437 0 -31 16 12 1 0.248535 0 -31 16 13 1 0.25 0 -31 16 14 1 0.252686 0 -31 16 15 1 0.256592 0 -31 16 16 1 0.261475 0 -31 16 17 1 0.262939 0 -31 16 18 1 0.261963 0.201172 -31 16 19 1 0.255371 0.344727 -31 16 20 1 0.250732 0.444336 -31 16 21 1 0.251465 0.53125 -31 16 22 1 0.251465 0.60791 -31 16 23 1 0.255371 0.675293 -31 16 24 1 0.274658 0.737305 -31 16 25 1 0.309814 0.79834 -31 16 26 1 0.35498 0.857422 -31 16 27 1 0.401611 0.911621 -31 16 28 1 0.439453 0.959961 -31 16 29 1 0.460693 1 -31 16 30 1 0.462891 1 -31 16 31 1 0.456055 1 -31 17 0 1 0.326904 0 -31 17 1 1 0.326904 0 -31 17 2 1 0.326904 0 -31 17 3 1 0.326904 0 -31 17 4 1 0.326904 0 -31 17 5 1 0.326904 0 -31 17 6 1 0.327148 0 -31 17 7 1 0.327148 0 -31 17 8 1 0.327148 0 -31 17 9 1 0.327148 0 -31 17 10 1 0.327393 0 -31 17 11 1 0.327881 0 -31 17 12 1 0.328369 0 -31 17 13 1 0.32959 0 -31 17 14 1 0.331299 0 -31 17 15 1 0.33374 0 -31 17 16 1 0.337158 0 -31 17 17 1 0.337891 0 -31 17 18 1 0.336914 0.202881 -31 17 19 1 0.333496 0.344727 -31 17 20 1 0.330566 0.443604 -31 17 21 1 0.330322 0.530273 -31 17 22 1 0.333496 0.60791 -31 17 23 1 0.33374 0.674805 -31 17 24 1 0.343994 0.736328 -31 17 25 1 0.366455 0.797363 -31 17 26 1 0.399902 0.856445 -31 17 27 1 0.437744 0.911133 -31 17 28 1 0.469971 0.959473 -31 17 29 1 0.488281 1 -31 17 30 1 0.489014 1 -31 17 31 1 0.480713 1 -31 18 0 1 0.399902 0 -31 18 1 1 0.399902 0 -31 18 2 1 0.399902 0 -31 18 3 1 0.399902 0 -31 18 4 1 0.399902 0 -31 18 5 1 0.399902 0 -31 18 6 1 0.400146 0 -31 18 7 1 0.400146 0 -31 18 8 1 0.400146 0 -31 18 9 1 0.400146 0 -31 18 10 1 0.400391 0 -31 18 11 1 0.400635 0 -31 18 12 1 0.401123 0 -31 18 13 1 0.401855 0 -31 18 14 1 0.403076 0 -31 18 15 1 0.404785 0 -31 18 16 1 0.407471 0 -31 18 17 1 0.407959 0 -31 18 18 1 0.407227 0.207764 -31 18 19 1 0.405518 0.345947 -31 18 20 1 0.403564 0.443359 -31 18 21 1 0.403076 0.528809 -31 18 22 1 0.406006 0.606934 -31 18 23 1 0.40625 0.673828 -31 18 24 1 0.410889 0.734863 -31 18 25 1 0.424805 0.796387 -31 18 26 1 0.448975 0.855469 -31 18 27 1 0.478516 0.910645 -31 18 28 1 0.505859 0.959473 -31 18 29 1 0.520996 1 -31 18 30 1 0.52002 1 -31 18 31 1 0.510254 1 -31 19 0 1 0.468018 0 -31 19 1 1 0.468018 0 -31 19 2 1 0.468018 0 -31 19 3 1 0.468018 0 -31 19 4 1 0.468018 0 -31 19 5 1 0.468018 0 -31 19 6 1 0.468018 0 -31 19 7 1 0.468018 0 -31 19 8 1 0.468262 0 -31 19 9 1 0.468262 0 -31 19 10 1 0.468262 0 -31 19 11 1 0.468506 0 -31 19 12 1 0.468994 0 -31 19 13 1 0.469482 0 -31 19 14 1 0.470459 0 -31 19 15 1 0.471924 0 -31 19 16 1 0.473877 0 -31 19 17 1 0.474121 0 -31 19 18 1 0.474121 0.217041 -31 19 19 1 0.473389 0.348877 -31 19 20 1 0.472412 0.444092 -31 19 21 1 0.471924 0.527832 -31 19 22 1 0.472656 0.604492 -31 19 23 1 0.474854 0.672852 -31 19 24 1 0.47583 0.733398 -31 19 25 1 0.483398 0.794434 -31 19 26 1 0.499756 0.854004 -31 19 27 1 0.522461 0.909668 -31 19 28 1 0.544434 0.958496 -31 19 29 1 0.557129 1 -31 19 30 1 0.554199 1 -31 19 31 1 0.542969 1 -31 20 0 1 0.53125 0 -31 20 1 1 0.53125 0 -31 20 2 1 0.53125 0 -31 20 3 1 0.53125 0 -31 20 4 1 0.53125 0 -31 20 5 1 0.53125 0 -31 20 6 1 0.53125 0 -31 20 7 1 0.53125 0 -31 20 8 1 0.53125 0 -31 20 9 1 0.531738 0 -31 20 10 1 0.531738 0 -31 20 11 1 0.531738 0 -31 20 12 1 0.532227 0 -31 20 13 1 0.532715 0 -31 20 14 1 0.533203 0 -31 20 15 1 0.534668 0 -31 20 16 1 0.536133 0 -31 20 17 1 0.536621 0 -31 20 18 1 0.537109 0.231445 -31 20 19 1 0.537109 0.354492 -31 20 20 1 0.537109 0.446533 -31 20 21 1 0.536621 0.527832 -31 20 22 1 0.536133 0.603027 -31 20 23 1 0.537598 0.671387 -31 20 24 1 0.538086 0.731445 -31 20 25 1 0.541016 0.791992 -31 20 26 1 0.550781 0.851562 -31 20 27 1 0.567383 0.907715 -31 20 28 1 0.584961 0.95752 -31 20 29 1 0.594727 1 -31 20 30 1 0.590332 1 -31 20 31 1 0.577637 1 -31 21 0 1 0.591309 0 -31 21 1 1 0.591309 0 -31 21 2 1 0.591309 0 -31 21 3 1 0.591309 0 -31 21 4 1 0.591309 0 -31 21 5 1 0.591309 0 -31 21 6 1 0.591309 0 -31 21 7 1 0.591309 0 -31 21 8 1 0.591309 0 -31 21 9 1 0.591309 0 -31 21 10 1 0.591309 0 -31 21 11 1 0.591797 0 -31 21 12 1 0.591797 0 -31 21 13 1 0.592285 0 -31 21 14 1 0.592773 0 -31 21 15 1 0.59375 0 -31 21 16 1 0.595215 0 -31 21 17 1 0.595703 0 -31 21 18 1 0.597168 0.250977 -31 21 19 1 0.598145 0.363281 -31 21 20 1 0.598633 0.450928 -31 21 21 1 0.598633 0.529297 -31 21 22 1 0.598145 0.602051 -31 21 23 1 0.597656 0.668457 -31 21 24 1 0.599121 0.72998 -31 21 25 1 0.598145 0.789062 -31 21 26 1 0.602539 0.848633 -31 21 27 1 0.612793 0.905762 -31 21 28 1 0.625977 0.956055 -31 21 29 1 0.633789 1 -31 21 30 1 0.62793 1 -31 21 31 1 0.613281 1 -31 22 0 1 0.646973 0 -31 22 1 1 0.646973 0 -31 22 2 1 0.646973 0 -31 22 3 1 0.646973 0 -31 22 4 1 0.646973 0 -31 22 5 1 0.646973 0 -31 22 6 1 0.646973 0 -31 22 7 1 0.646973 0 -31 22 8 1 0.646973 0 -31 22 9 1 0.646973 0 -31 22 10 1 0.647461 0 -31 22 11 1 0.647461 0 -31 22 12 1 0.647461 0 -31 22 13 1 0.647949 0 -31 22 14 1 0.648438 0 -31 22 15 1 0.649414 0 -31 22 16 1 0.650391 0 -31 22 17 1 0.651855 0.0343323 -31 22 18 1 0.653809 0.273682 -31 22 19 1 0.655273 0.375244 -31 22 20 1 0.656738 0.457764 -31 22 21 1 0.657227 0.532715 -31 22 22 1 0.656738 0.602539 -31 22 23 1 0.655273 0.666504 -31 22 24 1 0.654297 0.726074 -31 22 25 1 0.653809 0.785645 -31 22 26 1 0.65332 0.845215 -31 22 27 1 0.658691 0.902344 -31 22 28 1 0.66748 0.953613 -31 22 29 1 0.672363 0.998047 -31 22 30 1 0.666016 1 -31 22 31 1 0.649902 1 -31 23 0 1 0.697754 0 -31 23 1 1 0.697754 0 -31 23 2 1 0.697754 0 -31 23 3 1 0.697754 0 -31 23 4 1 0.697754 0 -31 23 5 1 0.697754 0 -31 23 6 1 0.697754 0 -31 23 7 1 0.697754 0 -31 23 8 1 0.697754 0 -31 23 9 1 0.697754 0 -31 23 10 1 0.698242 0 -31 23 11 1 0.698242 0 -31 23 12 1 0.698242 0 -31 23 13 1 0.69873 0 -31 23 14 1 0.699219 0 -31 23 15 1 0.699707 0 -31 23 16 1 0.700684 0 -31 23 17 1 0.702637 0.162354 -31 23 18 1 0.705078 0.297607 -31 23 19 1 0.707031 0.388916 -31 23 20 1 0.708984 0.466309 -31 23 21 1 0.709961 0.537598 -31 23 22 1 0.709961 0.604004 -31 23 23 1 0.708496 0.665527 -31 23 24 1 0.706543 0.722656 -31 23 25 1 0.70459 0.782227 -31 23 26 1 0.70166 0.84082 -31 23 27 1 0.702148 0.898438 -31 23 28 1 0.707031 0.950684 -31 23 29 1 0.709961 0.995605 -31 23 30 1 0.702148 1 -31 23 31 1 0.685059 1 -31 24 0 1 0.744629 0.1026 -31 24 1 1 0.744629 0.1026 -31 24 2 1 0.744629 0.1026 -31 24 3 1 0.744629 0.1026 -31 24 4 1 0.744629 0.1026 -31 24 5 1 0.744629 0.1026 -31 24 6 1 0.744629 0.102661 -31 24 7 1 0.744629 0.102661 -31 24 8 1 0.744629 0.102722 -31 24 9 1 0.744629 0.102783 -31 24 10 1 0.744629 0.102966 -31 24 11 1 0.744629 0.103271 -31 24 12 1 0.744629 0.103821 -31 24 13 1 0.745117 0.104675 -31 24 14 1 0.745605 0.106018 -31 24 15 1 0.746094 0.108032 -31 24 16 1 0.746582 0.11084 -31 24 17 1 0.748535 0.214844 -31 24 18 1 0.751465 0.320801 -31 24 19 1 0.753906 0.403564 -31 24 20 1 0.756348 0.476074 -31 24 21 1 0.757812 0.543457 -31 24 22 1 0.758301 0.607422 -31 24 23 1 0.757324 0.666016 -31 24 24 1 0.755371 0.720703 -31 24 25 1 0.751953 0.777832 -31 24 26 1 0.748535 0.836426 -31 24 27 1 0.744141 0.893555 -31 24 28 1 0.744629 0.946777 -31 24 29 1 0.745605 0.992676 -31 24 30 1 0.737305 1 -31 24 31 1 0.719238 1 -31 25 0 1 0.791016 0.204102 -31 25 1 1 0.791016 0.204102 -31 25 2 1 0.791016 0.204102 -31 25 3 1 0.791016 0.204102 -31 25 4 1 0.791016 0.204102 -31 25 5 1 0.791016 0.204102 -31 25 6 1 0.791016 0.204102 -31 25 7 1 0.791016 0.204102 -31 25 8 1 0.791016 0.204102 -31 25 9 1 0.791016 0.204224 -31 25 10 1 0.791504 0.204224 -31 25 11 1 0.791504 0.204346 -31 25 12 1 0.791504 0.204468 -31 25 13 1 0.791504 0.204712 -31 25 14 1 0.791992 0.2052 -31 25 15 1 0.79248 0.205811 -31 25 16 1 0.792969 0.206787 -31 25 17 1 0.794922 0.256348 -31 25 18 1 0.797852 0.343994 -31 25 19 1 0.800781 0.419189 -31 25 20 1 0.803711 0.487061 -31 25 21 1 0.805664 0.55127 -31 25 22 1 0.806641 0.611816 -31 25 23 1 0.806152 0.66748 -31 25 24 1 0.804199 0.719727 -31 25 25 1 0.800781 0.773926 -31 25 26 1 0.79541 0.830566 -31 25 27 1 0.789551 0.887207 -31 25 28 1 0.785156 0.941406 -31 25 29 1 0.783203 0.98877 -31 25 30 1 0.774414 1 -31 25 31 1 0.755371 1 -31 26 0 1 0.837891 0.260254 -31 26 1 1 0.837891 0.260254 -31 26 2 1 0.837891 0.260254 -31 26 3 1 0.837891 0.260254 -31 26 4 1 0.837891 0.260254 -31 26 5 1 0.837891 0.260254 -31 26 6 1 0.837891 0.260254 -31 26 7 1 0.837891 0.260254 -31 26 8 1 0.837891 0.260254 -31 26 9 1 0.837891 0.260254 -31 26 10 1 0.837891 0.260254 -31 26 11 1 0.837891 0.260254 -31 26 12 1 0.838379 0.260254 -31 26 13 1 0.838379 0.260498 -31 26 14 1 0.838379 0.260742 -31 26 15 1 0.838867 0.260986 -31 26 16 1 0.839355 0.261719 -31 26 17 1 0.84082 0.289551 -31 26 18 1 0.844238 0.365479 -31 26 19 1 0.847168 0.434326 -31 26 20 1 0.850586 0.498291 -31 26 21 1 0.853027 0.559082 -31 26 22 1 0.854492 0.616699 -31 26 23 1 0.854492 0.669922 -31 26 24 1 0.853516 0.719238 -31 26 25 1 0.850098 0.770508 -31 26 26 1 0.844727 0.824219 -31 26 27 1 0.837402 0.879883 -31 26 28 1 0.828613 0.934082 -31 26 29 1 0.823242 0.98291 -31 26 30 1 0.813477 1 -31 26 31 1 0.793457 1 -31 27 0 1 0.884277 0.299316 -31 27 1 1 0.884277 0.299316 -31 27 2 1 0.884277 0.299316 -31 27 3 1 0.884277 0.299316 -31 27 4 1 0.884277 0.299316 -31 27 5 1 0.884277 0.299316 -31 27 6 1 0.884277 0.299316 -31 27 7 1 0.884277 0.299316 -31 27 8 1 0.884277 0.299316 -31 27 9 1 0.884277 0.299316 -31 27 10 1 0.884277 0.299316 -31 27 11 1 0.884277 0.299316 -31 27 12 1 0.884277 0.299316 -31 27 13 1 0.884766 0.299561 -31 27 14 1 0.884766 0.299561 -31 27 15 1 0.885254 0.299805 -31 27 16 1 0.885254 0.300049 -31 27 17 1 0.886719 0.314209 -31 27 18 1 0.889648 0.382324 -31 27 19 1 0.893066 0.446777 -31 27 20 1 0.896484 0.507324 -31 27 21 1 0.898926 0.56543 -31 27 22 1 0.900879 0.621094 -31 27 23 1 0.901855 0.671875 -31 27 24 1 0.900879 0.719727 -31 27 25 1 0.898926 0.768555 -31 27 26 1 0.894043 0.818848 -31 27 27 1 0.88623 0.871094 -31 27 28 1 0.875488 0.924805 -31 27 29 1 0.865234 0.975098 -31 27 30 1 0.854492 1 -31 27 31 1 0.834473 1 -31 28 0 1 0.929199 0.324707 -31 28 1 1 0.929199 0.324707 -31 28 2 1 0.929199 0.324707 -31 28 3 1 0.929199 0.324707 -31 28 4 1 0.929199 0.324707 -31 28 5 1 0.929199 0.324707 -31 28 6 1 0.929199 0.324707 -31 28 7 1 0.929199 0.324707 -31 28 8 1 0.929199 0.324707 -31 28 9 1 0.929199 0.324707 -31 28 10 1 0.929199 0.324707 -31 28 11 1 0.929199 0.324951 -31 28 12 1 0.929688 0.324951 -31 28 13 1 0.929688 0.324951 -31 28 14 1 0.929688 0.324951 -31 28 15 1 0.930176 0.324951 -31 28 16 1 0.930176 0.325195 -31 28 17 1 0.930664 0.327881 -31 28 18 1 0.934082 0.391602 -31 28 19 1 0.9375 0.453125 -31 28 20 1 0.94043 0.51123 -31 28 21 1 0.943359 0.567871 -31 28 22 1 0.945312 0.62207 -31 28 23 1 0.946777 0.671875 -31 28 24 1 0.946289 0.717773 -31 28 25 1 0.944824 0.765137 -31 28 26 1 0.940918 0.813965 -31 28 27 1 0.934082 0.863281 -31 28 28 1 0.92334 0.913574 -31 28 29 1 0.909668 0.963867 -31 28 30 1 0.896973 1 -31 28 31 1 0.876465 1 -31 29 0 1 0.972656 0.337158 -31 29 1 1 0.972656 0.337158 -31 29 2 1 0.972656 0.337158 -31 29 3 1 0.972656 0.337158 -31 29 4 1 0.972656 0.337158 -31 29 5 1 0.972656 0.337158 -31 29 6 1 0.972656 0.337158 -31 29 7 1 0.972656 0.337158 -31 29 8 1 0.972656 0.337158 -31 29 9 1 0.972656 0.337158 -31 29 10 1 0.972656 0.337158 -31 29 11 1 0.972656 0.337158 -31 29 12 1 0.972656 0.337158 -31 29 13 1 0.972656 0.337158 -31 29 14 1 0.973145 0.337158 -31 29 15 1 0.973145 0.337158 -31 29 16 1 0.973633 0.337402 -31 29 17 1 0.973633 0.337402 -31 29 18 1 0.976562 0.390869 -31 29 19 1 0.97998 0.450684 -31 29 20 1 0.983398 0.507812 -31 29 21 1 0.98584 0.563477 -31 29 22 1 0.988281 0.616699 -31 29 23 1 0.989258 0.666016 -31 29 24 1 0.989746 0.711426 -31 29 25 1 0.988281 0.758301 -31 29 26 1 0.985352 0.806641 -31 29 27 1 0.979492 0.85498 -31 29 28 1 0.970215 0.902832 -31 29 29 1 0.956543 0.950684 -31 29 30 1 0.939941 0.99707 -31 29 31 1 0.919922 1 -31 30 0 1 1 0.337646 -31 30 1 1 1 0.337646 -31 30 2 1 1 0.337646 -31 30 3 1 1 0.337646 -31 30 4 1 1 0.337646 -31 30 5 1 1 0.337646 -31 30 6 1 1 0.337646 -31 30 7 1 1 0.337646 -31 30 8 1 1 0.337646 -31 30 9 1 1 0.337646 -31 30 10 1 1 0.337646 -31 30 11 1 1 0.337646 -31 30 12 1 1 0.337646 -31 30 13 1 1 0.337646 -31 30 14 1 1 0.337646 -31 30 15 1 1 0.337402 -31 30 16 1 1 0.337402 -31 30 17 1 1 0.337402 -31 30 18 1 1 0.378906 -31 30 19 1 1 0.438721 -31 30 20 1 1 0.495605 -31 30 21 1 1 0.550781 -31 30 22 1 1 0.603516 -31 30 23 1 1 0.652344 -31 30 24 1 1 0.697754 -31 30 25 1 1 0.744629 -31 30 26 1 1 0.792969 -31 30 27 1 1 0.841309 -31 30 28 1 1 0.889648 -31 30 29 1 1 0.937012 -31 30 30 1 0.984375 0.981934 -31 30 31 1 0.963379 1 -31 31 0 1 1 0.329834 -31 31 1 1 1 0.329834 -31 31 2 1 1 0.329834 -31 31 3 1 1 0.329834 -31 31 4 1 1 0.329834 -31 31 5 1 1 0.329834 -31 31 6 1 1 0.329834 -31 31 7 1 1 0.329834 -31 31 8 1 1 0.329834 -31 31 9 1 1 0.329834 -31 31 10 1 1 0.329834 -31 31 11 1 1 0.329834 -31 31 12 1 1 0.329834 -31 31 13 1 1 0.329834 -31 31 14 1 1 0.329834 -31 31 15 1 1 0.329834 -31 31 16 1 1 0.329834 -31 31 17 1 1 0.329834 -31 31 18 1 1 0.358398 -31 31 19 1 1 0.419189 -31 31 20 1 1 0.476074 -31 31 21 1 1 0.53125 -31 31 22 1 1 0.583496 -31 31 23 1 1 0.631836 -31 31 24 1 1 0.677246 -31 31 25 1 1 0.723633 -31 31 26 1 1 0.771973 -31 31 27 1 1 0.820801 -31 31 28 1 1 0.869629 -31 31 29 1 1 0.917969 -31 31 30 1 1 0.963867 -31 31 31 1 1 1 diff --git a/release/datafiles/colormanagement/luts/slog.py b/release/datafiles/colormanagement/luts/slog.py deleted file mode 100644 index 86546e06e3f..00000000000 --- a/release/datafiles/colormanagement/luts/slog.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python - -import math - -# IT's annoying that the 1023,4 and 4095,16 almost, but dont exactly, cancel. UGH -# The intent is clearly to have the same mapping, but it's not done very well. -# Sony engineers and/or the Academy should pick one of these mappings for both. - -def SLog10_to_lin(x): - return (math.pow(10.0,(((((x*1023.0)/4.0-16.0)/219.0)-0.616596-0.03)/0.432699))-0.037584)*0.9 - -def SLog12_to_lin(x): - return (math.pow(10.0,(((((x*4095.0)/16.0-16.0)/219.0)-0.616596-0.03)/0.432699))-0.037584)*0.9 - - -def WriteSPI1D(filename, fromMin, fromMax, data): - f = file(filename,'w') - f.write("Version 1\n") - f.write("From %s %s\n" % (fromMin, fromMax)) - f.write("Length %d\n" % len(data)) - f.write("Components 1\n") - f.write("{\n") - for value in data: - f.write(" %s\n" % value) - f.write("}\n") - f.close() - -def Fit(value, fromMin, fromMax, toMin, toMax): - if fromMin == fromMax: - raise ValueError("fromMin == fromMax") - return (value - fromMin) / (fromMax - fromMin) * (toMax - toMin) + toMin - -# -# NOTE: The ctl matrix order is transposed compared to what OCIO expects -#const float SGAMUT_TO_ACES_MTX[3][3] = { -# { 0.754338638, 0.021198141, -0.009756991 }, -# #{ 0.133697046, 1.005410934, 0.004508563 }, -# { 0.111968437, -0.026610548, 1.005253201 } - -NUM_SAMPLES = 2**11 -RANGE = (-0.125, 1.125) -data = [] -for i in xrange(NUM_SAMPLES): - x = i/(NUM_SAMPLES-1.0) - x = Fit(x, 0.0, 1.0, RANGE[0], RANGE[1]) - data.append(SLog10_to_lin(x)) -WriteSPI1D('slog10.spi1d', RANGE[0], RANGE[1], data) - -""" -NUM_SAMPLES = 2**13 -RANGE = (-0.125, 1.125) -data = [] -for i in xrange(NUM_SAMPLES): - x = i/(NUM_SAMPLES-1.0) - x = Fit(x, 0.0, 1.0, RANGE[0], RANGE[1]) - data.append(SLog12_to_lin(x)) -WriteSPI1D('slog12.spi1d', RANGE[0], RANGE[1], data) -""" diff --git a/release/datafiles/colormanagement/luts/slog.spi1d b/release/datafiles/colormanagement/luts/slog.spi1d deleted file mode 100644 index 4ef5b11408a..00000000000 --- a/release/datafiles/colormanagement/luts/slog.spi1d +++ /dev/null @@ -1,4102 +0,0 @@ -Version 1 -From -0.125 1.125 -Length 4096 -Components 1 -{ - -0.0248367707262 - -0.0248197031226 - -0.0248026031117 - -0.0247854706321 - -0.0247683056221 - -0.0247511080199 - -0.0247338777637 - -0.0247166147913 - -0.0246993190408 - -0.0246819904498 - -0.0246646289561 - -0.0246472344971 - -0.0246298070102 - -0.0246123464328 - -0.024594852702 - -0.0245773257548 - -0.0245597655282 - -0.024542171959 - -0.0245245449839 - -0.0245068845395 - -0.0244891905621 - -0.0244714629882 - -0.024453701754 - -0.0244359067954 - -0.0244180780486 - -0.0244002154493 - -0.0243823189333 - -0.0243643884361 - -0.0243464238933 - -0.0243284252401 - -0.0243103924119 - -0.0242923253438 - -0.0242742239706 - -0.0242560882274 - -0.0242379180487 - -0.0242197133693 - -0.0242014741237 - -0.0241832002462 - -0.024164891671 - -0.0241465483322 - -0.0241281701639 - -0.0241097571 - -0.0240913090741 - -0.0240728260199 - -0.0240543078708 - -0.0240357545603 - -0.0240171660216 - -0.0239985421877 - -0.0239798829917 - -0.0239611883664 - -0.0239424582446 - -0.0239236925588 - -0.0239048912415 - -0.0238860542251 - -0.0238671814418 - -0.0238482728236 - -0.0238293283026 - -0.0238103478105 - -0.0237913312791 - -0.0237722786399 - -0.0237531898244 - -0.0237340647639 - -0.0237149033895 - -0.0236957056323 - -0.0236764714232 - -0.0236572006931 - -0.0236378933725 - -0.023618549392 - -0.0235991686819 - -0.0235797511726 - -0.0235602967942 - -0.0235408054766 - -0.0235212771498 - -0.0235017117434 - -0.0234821091871 - -0.0234624694102 - -0.0234427923422 - -0.0234230779122 - -0.0234033260494 - -0.0233835366825 - -0.0233637097404 - -0.0233438451518 - -0.0233239428451 - -0.0233040027488 - -0.0232840247911 - -0.0232640089001 - -0.0232439550038 - -0.02322386303 - -0.0232037329064 - -0.0231835645606 - -0.02316335792 - -0.023143112912 - -0.0231228294635 - -0.0231025075018 - -0.0230821469535 - -0.0230617477455 - -0.0230413098044 - -0.0230208330566 - -0.0230003174284 - -0.0229797628461 - -0.0229591692355 - -0.0229385365227 - -0.0229178646334 - -0.0228971534932 - -0.0228764030276 - -0.0228556131619 - -0.0228347838212 - -0.0228139149308 - -0.0227930064153 - -0.0227720581997 - -0.0227510702085 - -0.0227300423662 - -0.0227089745971 - -0.0226878668254 - -0.0226667189753 - -0.0226455309705 - -0.0226243027348 - -0.0226030341918 - -0.0225817252651 - -0.0225603758778 - -0.0225389859533 - -0.0225175554145 - -0.0224960841843 - -0.0224745721855 - -0.0224530193406 - -0.0224314255721 - -0.0224097908023 - -0.0223881149533 - -0.0223663979471 - -0.0223446397056 - -0.0223228401505 - -0.0223009992033 - -0.0222791167854 - -0.0222571928182 - -0.0222352272227 - -0.0222132199198 - -0.0221911708305 - -0.0221690798752 - -0.0221469469746 - -0.022124772049 - -0.0221025550186 - -0.0220802958035 - -0.0220579943235 - -0.0220356504984 - -0.0220132642479 - -0.0219908354912 - -0.0219683641479 - -0.0219458501368 - -0.0219232933772 - -0.0219006937877 - -0.0218780512871 - -0.0218553657939 - -0.0218326372265 - -0.021809865503 - -0.0217870505416 - -0.0217641922601 - -0.0217412905762 - -0.0217183454077 - -0.0216953566718 - -0.0216723242859 - -0.0216492481671 - -0.0216261282323 - -0.0216029643984 - -0.021579756582 - -0.0215565046996 - -0.0215332086676 - -0.021509868402 - -0.0214864838189 - -0.0214630548342 - -0.0214395813635 - -0.0214160633224 - -0.0213925006263 - -0.0213688931903 - -0.0213452409296 - -0.0213215437589 - -0.0212978015931 - -0.0212740143466 - -0.021250181934 - -0.0212263042694 - -0.0212023812669 - -0.0211784128404 - -0.0211543989037 - -0.0211303393704 - -0.0211062341539 - -0.0210820831674 - -0.0210578863241 - -0.0210336435368 - -0.0210093547184 - -0.0209850197814 - -0.0209606386383 - -0.0209362112013 - -0.0209117373825 - -0.0208872170939 - -0.0208626502472 - -0.020838036754 - -0.0208133765258 - -0.0207886694739 - -0.0207639155092 - -0.0207391145427 - -0.0207142664853 - -0.0206893712474 - -0.0206644287395 - -0.0206394388719 - -0.0206144015545 - -0.0205893166974 - -0.0205641842102 - -0.0205390040025 - -0.0205137759838 - -0.0204885000631 - -0.0204631761496 - -0.0204378041522 - -0.0204123839795 - -0.0203869155401 - -0.0203613987422 - -0.0203358334942 - -0.020310219704 - -0.0202845572794 - -0.0202588461281 - -0.0202330861576 - -0.0202072772752 - -0.0201814193879 - -0.0201555124028 - -0.0201295562266 - -0.020103550766 - -0.0200774959273 - -0.0200513916168 - -0.0200252377405 - -0.0199990342044 - -0.0199727809141 - -0.0199464777752 - -0.0199201246931 - -0.0198937215728 - -0.0198672683194 - -0.0198407648378 - -0.0198142110324 - -0.0197876068078 - -0.0197609520683 - -0.0197342467179 - -0.0197074906605 - -0.0196806837998 - -0.0196538260395 - -0.0196269172827 - -0.0195999574328 - -0.0195729463927 - -0.0195458840651 - -0.0195187703528 - -0.0194916051581 - -0.0194643883834 - -0.0194371199305 - -0.0194097997015 - -0.0193824275981 - -0.0193550035216 - -0.0193275273735 - -0.0192999990549 - -0.0192724184666 - -0.0192447855096 - -0.0192171000842 - -0.019189362091 - -0.01916157143 - -0.0191337280013 - -0.0191058317047 - -0.0190778824399 - -0.0190498801061 - -0.0190218246028 - -0.0189937158288 - -0.0189655536831 - -0.0189373380644 - -0.018909068871 - -0.0188807460013 - -0.0188523693533 - -0.018823938825 - -0.018795454314 - -0.0187669157179 - -0.0187383229338 - -0.0187096758591 - -0.0186809743905 - -0.0186522184247 - -0.0186234078584 - -0.0185945425878 - -0.0185656225091 - -0.0185366475182 - -0.0185076175108 - -0.0184785323824 - -0.0184493920285 - -0.0184201963441 - -0.0183909452242 - -0.0183616385636 - -0.0183322762567 - -0.0183028581979 - -0.0182733842813 - -0.018243854401 - -0.0182142684506 - -0.0181846263236 - -0.0181549279135 - -0.0181251731132 - -0.0180953618159 - -0.0180654939141 - -0.0180355693005 - -0.0180055878672 - -0.0179755495065 - -0.0179454541103 - -0.0179153015702 - -0.0178850917777 - -0.0178548246242 - -0.0178245000008 - -0.0177941177982 - -0.0177636779072 - -0.0177331802182 - -0.0177026246216 - -0.0176720110073 - -0.0176413392651 - -0.0176106092848 - -0.0175798209557 - -0.0175489741671 - -0.0175180688079 - -0.0174871047669 - -0.0174560819327 - -0.0174250001937 - -0.017393859438 - -0.0173626595536 - -0.0173314004282 - -0.0173000819493 - -0.0172687040042 - -0.0172372664801 - -0.0172057692637 - -0.0171742122417 - -0.0171425953006 - -0.0171109183266 - -0.0170791812058 - -0.0170473838238 - -0.0170155260664 - -0.0169836078188 - -0.0169516289662 - -0.0169195893935 - -0.0168874889855 - -0.0168553276266 - -0.0168231052011 - -0.016790821593 - -0.0167584766862 - -0.0167260703643 - -0.0166936025106 - -0.0166610730084 - -0.0166284817405 - -0.0165958285897 - -0.0165631134386 - -0.0165303361693 - -0.0164974966639 - -0.0164645948043 - -0.0164316304721 - -0.0163986035486 - -0.016365513915 - -0.0163323614522 - -0.0162991460409 - -0.0162658675616 - -0.0162325258946 - -0.0161991209199 - -0.0161656525172 - -0.0161321205662 - -0.0160985249461 - -0.0160648655361 - -0.016031142215 - -0.0159973548616 - -0.0159635033542 - -0.015929587571 - -0.0158956073899 - -0.0158615626888 - -0.015827453345 - -0.0157932792359 - -0.0157590402384 - -0.0157247362294 - -0.0156903670854 - -0.0156559326828 - -0.0156214328976 - -0.0155868676057 - -0.0155522366826 - -0.0155175400039 - -0.0154827774446 - -0.0154479488797 - -0.0154130541837 - -0.0153780932312 - -0.0153430658964 - -0.0153079720532 - -0.0152728115752 - -0.0152375843361 - -0.015202290209 - -0.0151669290669 - -0.0151315007826 - -0.0150960052286 - -0.0150604422771 - -0.0150248118002 - -0.0149891136698 - -0.0149533477572 - -0.0149175139339 - -0.0148816120708 - -0.0148456420388 - -0.0148096037085 - -0.0147734969501 - -0.0147373216338 - -0.0147010776293 - -0.0146647648062 - -0.014628383034 - -0.0145919321815 - -0.0145554121178 - -0.0145188227113 - -0.0144821638305 - -0.0144454353433 - -0.0144086371176 - -0.0143717690211 - -0.014334830921 - -0.0142978226844 - -0.0142607441782 - -0.0142235952688 - -0.0141863758228 - -0.014149085706 - -0.0141117247844 - -0.0140742929234 - -0.0140367899885 - -0.0139992158445 - -0.0139615703564 - -0.0139238533887 - -0.0138860648056 - -0.0138482044711 - -0.0138102722491 - -0.013772268003 - -0.0137341915961 - -0.0136960428913 - -0.0136578217514 - -0.0136195280388 - -0.0135811616158 - -0.0135427223442 - -0.0135042100858 - -0.013465624702 - -0.0134269660539 - -0.0133882340025 - -0.0133494284083 - -0.0133105491316 - -0.0132715960327 - -0.0132325689713 - -0.013193467807 - -0.0131542923991 - -0.0131150426065 - -0.0130757182882 - -0.0130363193025 - -0.0129968455078 - -0.0129572967618 - -0.0129176729225 - -0.012877973847 - -0.0128381993927 - -0.0127983494163 - -0.0127584237746 - -0.0127184223237 - -0.0126783449198 - -0.0126381914186 - -0.0125979616757 - -0.0125576555462 - -0.0125172728852 - -0.0124768135474 - -0.0124362773871 - -0.0123956642584 - -0.0123549740153 - -0.0123142065114 - -0.0122733615998 - -0.0122324391336 - -0.0121914389657 - -0.0121503609484 - -0.0121092049339 - -0.0120679707741 - -0.0120266583206 - -0.0119852674249 - -0.0119437979379 - -0.0119022497104 - -0.0118606225929 - -0.0118189164356 - -0.0117771310885 - -0.0117352664011 - -0.0116933222229 - -0.0116512984029 - -0.0116091947898 - -0.0115670112322 - -0.0115247475783 - -0.0114824036759 - -0.0114399793728 - -0.0113974745162 - -0.0113548889532 - -0.0113122225306 - -0.0112694750948 - -0.011226646492 - -0.0111837365681 - -0.0111407451687 - -0.011097672139 - -0.0110545173242 - -0.0110112805688 - -0.0109679617173 - -0.0109245606138 - -0.0108810771022 - -0.010837511026 - -0.0107938622283 - -0.0107501305522 - -0.0107063158403 - -0.0106624179348 - -0.0106184366779 - -0.0105743719113 - -0.0105302234764 - -0.0104859912143 - -0.010441674966 - -0.0103972745718 - -0.010352789872 - -0.0103082207066 - -0.0102635669152 - -0.0102188283371 - -0.0101740048113 - -0.0101290961765 - -0.0100841022711 - -0.0100390229333 - -0.00999385800066 - -0.00994860731083 - -0.00990327070093 - -0.00985784800781 - -0.00981233906804 - -0.00976674371784 - -0.00972106179315 - -0.00967529312957 - -0.00962943756242 - -0.00958349492669 - -0.00953746505704 - -0.00949134778786 - -0.00944514295318 - -0.00939885038674 - -0.00935246992197 - -0.00930600139195 - -0.00925944462949 - -0.00921279946703 - -0.00916606573675 - -0.00911924327046 - -0.00907233189968 - -0.0090253314556 - -0.00897824176909 - -0.00893106267071 - -0.00888379399067 - -0.0088364355589 - -0.00878898720496 - -0.00874144875812 - -0.00869382004732 - -0.00864610090117 - -0.00859829114794 - -0.00855039061561 - -0.0085023991318 - -0.00845431652382 - -0.00840614261864 - -0.00835787724292 - -0.00830952022298 - -0.00826107138479 - -0.00821253055403 - -0.00816389755603 - -0.00811517221577 - -0.00806635435792 - -0.00801744380682 - -0.00796844038646 - -0.00791934392051 - -0.0078701542323 - -0.00782087114481 - -0.00777149448071 - -0.00772202406232 - -0.00767245971162 - -0.00762280125025 - -0.00757304849953 - -0.00752320128042 - -0.00747325941354 - -0.00742322271919 - -0.00737309101731 - -0.00732286412751 - -0.00727254186904 - -0.00722212406082 - -0.00717161052143 - -0.0071210010691 - -0.00707029552171 - -0.0070194936968 - -0.00696859541156 - -0.00691760048284 - -0.00686650872714 - -0.00681531996061 - -0.00676403399903 - -0.00671265065788 - -0.00666116975224 - -0.00660959109686 - -0.00655791450614 - -0.00650613979413 - -0.00645426677452 - -0.00640229526064 - -0.00635022506548 - -0.00629805600166 - -0.00624578788146 - -0.0061934205168 - -0.00614095371923 - -0.00608838729996 - -0.00603572106982 - -0.0059829548393 - -0.00593008841853 - -0.00587712161726 - -0.0058240542449 - -0.0057708861105 - -0.00571761702271 - -0.00566424678987 - -0.00561077521992 - -0.00555720212044 - -0.00550352729866 - -0.00544975056143 - -0.00539587171524 - -0.00534189056621 - -0.00528780692008 - -0.00523362058224 - -0.00517933135771 - -0.00512493905113 - -0.00507044346677 - -0.00501584440853 - -0.00496114167994 - -0.00490633508415 - -0.00485142442395 - -0.00479640950175 - -0.00474129011956 - -0.00468606607906 - -0.00463073718152 - -0.00457530322784 - -0.00451976401855 - -0.00446411935378 - -0.00440836903331 - -0.00435251285653 - -0.00429655062243 - -0.00424048212964 - -0.0041843071764 - -0.00412802556057 - -0.00407163707962 - -0.00401514153064 - -0.00395853871033 - -0.00390182841502 - -0.00384501044063 - -0.0037880845827 - -0.0037310506364 - -0.00367390839648 - -0.00361665765733 - -0.00355929821294 - -0.00350182985688 - -0.00344425238238 - -0.00338656558224 - -0.00332876924887 - -0.00327086317431 - -0.00321284715018 - -0.0031547209677 - -0.00309648441772 - -0.00303813729068 - -0.00297967937662 - -0.00292111046517 - -0.00286243034559 - -0.00280363880671 - -0.00274473563698 - -0.00268572062444 - -0.00262659355672 - -0.00256735422106 - -0.00250800240429 - -0.00244853789283 - -0.00238896047271 - -0.00232926992954 - -0.00226946604853 - -0.00220954861447 - -0.00214951741176 - -0.00208937222437 - -0.00202911283588 - -0.00196873902944 - -0.00190825058782 - -0.00184764729333 - -0.0017869289279 - -0.00172609527305 - -0.00166514610986 - -0.00160408121902 - -0.00154290038077 - -0.00148160337498 - -0.00142018998106 - -0.00135865997802 - -0.00129701314444 - -0.00123524925851 - -0.00117336809795 - -0.00111136944011 - -0.00104925306186 - -0.000987018739706 - -0.000924666249687 - -0.000862195367433 - -0.000799605868146 - -0.000736897526602 - -0.000674070117148 - -0.000611123413703 - -0.000548057189756 - -0.000484871218368 - -0.000421565272166 - -0.000358139123348 - -0.000294592543679 - -0.000230925304488 - -0.000167137176674 - -0.000103227930699 - -3.91973365867e-05 - 2.49548360717e-05 - 8.92288181248e-05 - 0.000153624840859 - 0.000218143136 - 0.000282783935713 - 0.000347547472605 - 0.000412433979724 - 0.000477443690561 - 0.000542576839049 - 0.000607833659566 - 0.000673214386936 - 0.000738719256428 - 0.000804348503757 - 0.000870102365087 - 0.000935981077029 - 0.00100198487664 - 0.00106811400144 - 0.00113436868939 - 0.0012007491789 - 0.00126725570883 - 0.00133388851852 - 0.00140064784772 - 0.00146753393668 - 0.00153454702607 - 0.00160168735704 - 0.0016689551712 - 0.0017363507106 - 0.00180387421775 - 0.00187152593565 - 0.00193930610773 - 0.00200721497789 - 0.0020752527905 - 0.0021434197904 - 0.00221171622287 - 0.00228014233368 - 0.00234869836905 - 0.00241738457569 - 0.00248620120074 - 0.00255514849186 - 0.00262422669714 - 0.00269343606514 - 0.00276277684493 - 0.00283224928602 - 0.0029018536384 - 0.00297159015255 - 0.00304145907939 - 0.00311146067036 - 0.00318159517734 - 0.00325186285272 - 0.00332226394935 - 0.00339279872056 - 0.00346346742018 - 0.00353427030248 - 0.00360520762227 - 0.0036762796348 - 0.00374748659581 - 0.00381882876155 - 0.00389030638874 - 0.00396191973458 - 0.00403366905677 - 0.0041055546135 - 0.00417757666344 - 0.00424973546576 - 0.00432203128012 - 0.00439446436667 - 0.00446703498606 - 0.00453974339943 - 0.00461258986842 - 0.00468557465516 - 0.00475869802228 - 0.00483196023292 - 0.0049053615507 - 0.00497890223976 - 0.00505258256472 - 0.00512640279073 - 0.00520036318342 - 0.00527446400892 - 0.0053487055339 - 0.0054230880255 - 0.00549761175139 - 0.00557227697973 - 0.00564708397921 - 0.00572203301901 - 0.00579712436884 - 0.00587235829889 - 0.00594773507991 - 0.00602325498313 - 0.0060989182803 - 0.0061747252437 - 0.00625067614611 - 0.00632677126084 - 0.0064030108617 - 0.00647939522305 - 0.00655592461975 - 0.00663259932719 - 0.00670941962128 - 0.00678638577844 - 0.00686349807565 - 0.00694075679038 - 0.00701816220064 - 0.00709571458498 - 0.00717341422246 - 0.00725126139267 - 0.00732925637576 - 0.00740739945238 - 0.00748569090372 - 0.00756413101151 - 0.00764272005802 - 0.00772145832603 - 0.0078003460989 - 0.00787938366048 - 0.0079585712952 - 0.008037909288 - 0.00811739792438 - 0.00819703749037 - 0.00827682827256 - 0.00835677055807 - 0.00843686463455 - 0.00851711079024 - 0.00859750931389 - 0.0086780604948 - 0.00875876462285 - 0.00883962198843 - 0.00892063288251 - 0.0090017975966 - 0.00908311642277 - 0.00916458965364 - 0.00924621758239 - 0.00932800050275 - 0.00940993870901 - 0.00949203249603 - 0.0095742821592 - 0.00965668799451 - 0.00973925029849 - 0.00982196936823 - 0.00990484550139 - 0.00998787899621 - 0.0100710701515 - 0.0101544192665 - 0.0102379266413 - 0.0103215925763 - 0.0104054173726 - 0.0104894013318 - 0.0105735447561 - 0.0106578479484 - 0.010742311212 - 0.0108269348508 - 0.0109117191693 - 0.0109966644727 - 0.0110817710665 - 0.0111670392571 - 0.0112524693513 - 0.0113380616565 - 0.0114238164807 - 0.0115097341325 - 0.011595814921 - 0.0116820591561 - 0.0117684671479 - 0.0118550392076 - 0.0119417756466 - 0.0120286767771 - 0.0121157429116 - 0.0122029743636 - 0.012290371447 - 0.0123779344762 - 0.0124656637663 - 0.012553559633 - 0.0126416223927 - 0.0127298523621 - 0.0128182498588 - 0.0129068152009 - 0.012995548707 - 0.0130844506966 - 0.0131735214894 - 0.013262761406 - 0.0133521707675 - 0.0134417498958 - 0.013531499113 - 0.0136214187421 - 0.0137115091069 - 0.0138017705313 - 0.0138922033403 - 0.0139828078592 - 0.0140735844141 - 0.0141645333316 - 0.014255654939 - 0.0143469495642 - 0.0144384175357 - 0.0145300591827 - 0.0146218748349 - 0.0147138648228 - 0.0148060294773 - 0.0148983691301 - 0.0149908841134 - 0.0150835747603 - 0.0151764414041 - 0.0152694843792 - 0.0153627040203 - 0.0154561006628 - 0.0155496746429 - 0.0156434262973 - 0.0157373559632 - 0.0158314639788 - 0.0159257506827 - 0.0160202164141 - 0.0161148615129 - 0.0162096863199 - 0.0163046911761 - 0.0163998764235 - 0.0164952424045 - 0.0165907894623 - 0.0166865179409 - 0.0167824281845 - 0.0168785205384 - 0.0169747953484 - 0.0170712529608 - 0.0171678937228 - 0.0172647179821 - 0.0173617260872 - 0.0174589183872 - 0.0175562952317 - 0.0176538569711 - 0.0177516039567 - 0.01784953654 - 0.0179476550735 - 0.0180459599102 - 0.018144451404 - 0.0182431299092 - 0.0183419957809 - 0.0184410493749 - 0.0185402910476 - 0.0186397211561 - 0.0187393400583 - 0.0188391481126 - 0.0189391456781 - 0.0190393331147 - 0.0191397107829 - 0.0192402790439 - 0.0193410382597 - 0.0194419887927 - 0.0195431310062 - 0.0196444652643 - 0.0197459919315 - 0.0198477113731 - 0.0199496239553 - 0.0200517300448 - 0.0201540300089 - 0.0202565242157 - 0.0203592130342 - 0.0204620968338 - 0.0205651759848 - 0.020668450858 - 0.0207719218252 - 0.0208755892585 - 0.0209794535312 - 0.0210835150168 - 0.02118777409 - 0.0212922311258 - 0.0213968865002 - 0.0215017405897 - 0.0216067937716 - 0.021712046424 - 0.0218174989257 - 0.021923151656 - 0.0220290049952 - 0.0221350593242 - 0.0222413150246 - 0.0223477724788 - 0.0224544320698 - 0.0225612941815 - 0.0226683591983 - 0.0227756275057 - 0.0228830994895 - 0.0229907755365 - 0.0230986560341 - 0.0232067413706 - 0.023315031935 - 0.0234235281168 - 0.0235322303065 - 0.0236411388952 - 0.0237502542749 - 0.0238595768382 - 0.0239691069785 - 0.02407884509 - 0.0241887915675 - 0.0242989468066 - 0.0244093112038 - 0.0245198851561 - 0.0246306690615 - 0.0247416633187 - 0.024852868327 - 0.0249642844866 - 0.0250759121984 - 0.0251877518642 - 0.0252998038863 - 0.0254120686679 - 0.0255245466132 - 0.0256372381267 - 0.025750143614 - 0.0258632634815 - 0.0259765981361 - 0.0260901479857 - 0.0262039134388 - 0.0263178949049 - 0.0264320927942 - 0.0265465075175 - 0.0266611394866 - 0.0267759891139 - 0.0268910568128 - 0.0270063429973 - 0.0271218480823 - 0.0272375724833 - 0.0273535166169 - 0.0274696809003 - 0.0275860657514 - 0.0277026715891 - 0.0278194988329 - 0.0279365479033 - 0.0280538192214 - 0.0281713132094 - 0.0282890302898 - 0.0284069708864 - 0.0285251354235 - 0.0286435243264 - 0.0287621380211 - 0.0288809769344 - 0.0290000414939 - 0.0291193321281 - 0.0292388492662 - 0.0293585933383 - 0.0294785647754 - 0.0295987640091 - 0.0297191914719 - 0.0298398475972 - 0.0299607328192 - 0.0300818475729 - 0.0302031922941 - 0.0303247674194 - 0.0304465733864 - 0.0305686106333 - 0.0306908795993 - 0.0308133807244 - 0.0309361144493 - 0.0310590812158 - 0.0311822814663 - 0.0313057156442 - 0.0314293841936 - 0.0315532875595 - 0.0316774261879 - 0.0318018005253 - 0.0319264110194 - 0.0320512581186 - 0.0321763422721 - 0.03230166393 - 0.0324272235433 - 0.0325530215638 - 0.0326790584441 - 0.032805334638 - 0.0329318505996 - 0.0330586067843 - 0.0331856036483 - 0.0333128416484 - 0.0334403212426 - 0.0335680428896 - 0.0336960070489 - 0.0338242141811 - 0.0339526647476 - 0.0340813592104 - 0.0342102980328 - 0.0343394816787 - 0.034468910613 - 0.0345985853013 - 0.0347285062104 - 0.0348586738078 - 0.0349890885618 - 0.0351197509417 - 0.0352506614178 - 0.0353818204611 - 0.0355132285435 - 0.035644886138 - 0.0357767937183 - 0.035908951759 - 0.0360413607358 - 0.036174021125 - 0.0363069334041 - 0.0364400980513 - 0.0365735155459 - 0.0367071863679 - 0.0368411109983 - 0.036975289919 - 0.0371097236129 - 0.0372444125638 - 0.0373793572562 - 0.0375145581759 - 0.0376500158093 - 0.0377857306438 - 0.0379217031678 - 0.0380579338706 - 0.0381944232425 - 0.0383311717745 - 0.0384681799587 - 0.0386054482882 - 0.038742977257 - 0.0388807673598 - 0.0390188190926 - 0.0391571329521 - 0.039295709436 - 0.039434549043 - 0.0395736522727 - 0.0397130196257 - 0.0398526516034 - 0.0399925487083 - 0.0401327114438 - 0.0402731403143 - 0.0404138358252 - 0.0405547984826 - 0.0406960287939 - 0.0408375272673 - 0.0409792944119 - 0.0411213307379 - 0.0412636367563 - 0.0414062129793 - 0.04154905992 - 0.0416921780923 - 0.0418355680112 - 0.0419792301928 - 0.0421231651539 - 0.0422673734126 - 0.0424118554877 - 0.0425566118993 - 0.042701643168 - 0.042846949816 - 0.0429925323659 - 0.0431383913418 - 0.0432845272684 - 0.0434309406717 - 0.0435776320785 - 0.0437246020166 - 0.0438718510149 - 0.0440193796033 - 0.0441671883127 - 0.0443152776749 - 0.0444636482229 - 0.0446123004905 - 0.0447612350126 - 0.0449104523252 - 0.0450599529653 - 0.0452097374707 - 0.0453598063806 - 0.0455101602348 - 0.0456607995746 - 0.0458117249418 - 0.0459629368796 - 0.0461144359322 - 0.0462662226447 - 0.0464182975633 - 0.0465706612353 - 0.0467233142088 - 0.0468762570333 - 0.047029490259 - 0.0471830144374 - 0.047336830121 - 0.0474909378631 - 0.0476453382185 - 0.0478000317426 - 0.0479550189921 - 0.0481103005248 - 0.0482658768994 - 0.0484217486758 - 0.0485779164148 - 0.0487343806784 - 0.0488911420297 - 0.0490482010326 - 0.0492055582525 - 0.0493632142555 - 0.049521169609 - 0.0496794248813 - 0.049837980642 - 0.0499968374615 - 0.0501559959116 - 0.0503154565649 - 0.0504752199952 - 0.0506352867775 - 0.0507956574877 - 0.050956332703 - 0.0511173130015 - 0.0512785989624 - 0.0514401911662 - 0.0516020901944 - 0.0517642966295 - 0.0519268110553 - 0.0520896340564 - 0.0522527662189 - 0.0524162081297 - 0.0525799603771 - 0.0527440235502 - 0.0529083982394 - 0.0530730850362 - 0.0532380845332 - 0.0534033973242 - 0.0535690240041 - 0.0537349651688 - 0.0539012214154 - 0.0540677933423 - 0.0542346815488 - 0.0544018866355 - 0.054569409204 - 0.0547372498573 - 0.0549054091991 - 0.0550738878347 - 0.0552426863703 - 0.0554118054133 - 0.0555812455723 - 0.055751007457 - 0.0559210916784 - 0.0560914988483 - 0.05626222958 - 0.056433284488 - 0.0566046641877 - 0.0567763692958 - 0.0569484004302 - 0.0571207582099 - 0.0572934432552 - 0.0574664561875 - 0.0576397976293 - 0.0578134682044 - 0.0579874685377 - 0.0581617992554 - 0.0583364609848 - 0.0585114543544 - 0.0586867799939 - 0.0588624385343 - 0.0590384306075 - 0.0592147568469 - 0.059391417887 - 0.0595684143636 - 0.0597457469134 - 0.0599234161747 - 0.0601014227868 - 0.0602797673902 - 0.0604584506267 - 0.0606374731392 - 0.060816835572 - 0.0609965385705 - 0.0611765827814 - 0.0613569688525 - 0.0615376974329 - 0.061718769173 - 0.0619001847244 - 0.0620819447398 - 0.0622640498734 - 0.0624465007803 - 0.0626292981173 - 0.062812442542 - 0.0629959347134 - 0.0631797752919 - 0.0633639649391 - 0.0635485043176 - 0.0637333940916 - 0.0639186349264 - 0.0641042274885 - 0.0642901724458 - 0.0644764704675 - 0.0646631222238 - 0.0648501283865 - 0.0650374896285 - 0.0652252066239 - 0.0654132800484 - 0.0656017105786 - 0.0657904988926 - 0.0659796456697 - 0.0661691515907 - 0.0663590173374 - 0.066549243593 - 0.066739831042 - 0.0669307803704 - 0.0671220922651 - 0.0673137674147 - 0.0675058065088 - 0.0676982102385 - 0.0678909792962 - 0.0680841143755 - 0.0682776161714 - 0.0684714853802 - 0.0686657226995 - 0.0688603288283 - 0.069055304467 - 0.069250650317 - 0.0694463670813 - 0.0696424554642 - 0.0698389161713 - 0.0700357499096 - 0.0702329573874 - 0.0704305393143 - 0.0706284964012 - 0.0708268293606 - 0.0710255389061 - 0.0712246257528 - 0.071424090617 - 0.0716239342166 - 0.0718241572706 - 0.0720247604996 - 0.0722257446254 - 0.0724271103712 - 0.0726288584617 - 0.0728309896228 - 0.0730335045818 - 0.0732364040676 - 0.0734396888103 - 0.0736433595413 - 0.0738474169935 - 0.0740518619013 - 0.0742566950003 - 0.0744619170276 - 0.0746675287217 - 0.0748735308225 - 0.0750799240712 - 0.0752867092106 - 0.0754938869847 - 0.0757014581391 - 0.0759094234207 - 0.0761177835779 - 0.0763265393604 - 0.0765356915194 - 0.0767452408076 - 0.076955187979 - 0.077165533789 - 0.0773762789947 - 0.0775874243544 - 0.0777989706277 - 0.0780109185761 - 0.0782232689622 - 0.0784360225501 - 0.0786491801053 - 0.078862742395 - 0.0790767101876 - 0.0792910842531 - 0.0795058653628 - 0.0797210542898 - 0.0799366518082 - 0.0801526586939 - 0.0803690757243 - 0.080585903678 - 0.0808031433354 - 0.0810207954781 - 0.0812388608894 - 0.0814573403539 - 0.0816762346578 - 0.0818955445889 - 0.0821152709363 - 0.0823354144906 - 0.0825559760441 - 0.0827769563904 - 0.0829983563247 - 0.0832201766437 - 0.0834424181456 - 0.0836650816302 - 0.0838881678986 - 0.0841116777536 - 0.0843356119996 - 0.0845599714424 - 0.0847847568892 - 0.085009969149 - 0.0852356090322 - 0.0854616773507 - 0.085688174918 - 0.0859151025493 - 0.0861424610609 - 0.0863702512712 - 0.0865984739997 - 0.0868271300678 - 0.0870562202982 - 0.0872857455153 - 0.0875157065451 - 0.087746104215 - 0.0879769393541 - 0.0882082127931 - 0.0884399253642 - 0.0886720779011 - 0.0889046712394 - 0.0891377062159 - 0.0893711836692 - 0.0896051044395 - 0.0898394693686 - 0.0900742792997 - 0.0903095350778 - 0.0905452375496 - 0.090781387563 - 0.091017985968 - 0.0912550336159 - 0.0914925313597 - 0.0917304800541 - 0.0919688805552 - 0.092207733721 - 0.0924470404109 - 0.0926868014861 - 0.0929270178093 - 0.093167690245 - 0.0934088196592 - 0.0936504069196 - 0.0938924528955 - 0.094134958458 - 0.0943779244796 - 0.0946213518347 - 0.0948652413992 - 0.0951095940507 - 0.0953544106686 - 0.0955996921338 - 0.0958454393289 - 0.0960916531382 - 0.0963383344478 - 0.0965854841453 - 0.09683310312 - 0.097081192263 - 0.097329752467 - 0.0975787846265 - 0.0978282896376 - 0.0980782683981 - 0.0983287218075 - 0.0985796507671 - 0.0988310561799 - 0.0990829389505 - 0.0993352999853 - 0.0995881401924 - 0.0998414604817 - 0.100095261765 - 0.100349544955 - 0.100604310967 - 0.100859560717 - 0.101115295125 - 0.101371515111 - 0.101628221596 - 0.101885415504 - 0.102143097762 - 0.102401269295 - 0.102659931033 - 0.102919083907 - 0.103178728849 - 0.103438866794 - 0.103699498678 - 0.103960625439 - 0.104222248015 - 0.10448436735 - 0.104746984385 - 0.105010100067 - 0.105273715341 - 0.105537831156 - 0.105802448464 - 0.106067568215 - 0.106333191364 - 0.106599318868 - 0.106865951682 - 0.107133090768 - 0.107400737086 - 0.107668891599 - 0.107937555273 - 0.108206729073 - 0.10847641397 - 0.108746610932 - 0.109017320933 - 0.109288544946 - 0.109560283948 - 0.109832538916 - 0.110105310831 - 0.110378600672 - 0.110652409425 - 0.110926738075 - 0.111201587607 - 0.111476959013 - 0.111752853281 - 0.112029271406 - 0.112306214382 - 0.112583683205 - 0.112861678874 - 0.11314020239 - 0.113419254753 - 0.11369883697 - 0.113978950045 - 0.114259594987 - 0.114540772806 - 0.114822484513 - 0.115104731122 - 0.115387513648 - 0.115670833111 - 0.115954690527 - 0.116239086921 - 0.116524023314 - 0.116809500732 - 0.117095520202 - 0.117382082754 - 0.117669189418 - 0.117956841228 - 0.118245039219 - 0.118533784429 - 0.118823077895 - 0.119112920659 - 0.119403313764 - 0.119694258255 - 0.119985755179 - 0.120277805585 - 0.120570410524 - 0.120863571049 - 0.121157288214 - 0.121451563076 - 0.121746396696 - 0.122041790132 - 0.122337744449 - 0.122634260712 - 0.122931339986 - 0.123228983342 - 0.123527191851 - 0.123825966585 - 0.12412530862 - 0.124425219032 - 0.124725698902 - 0.12502674931 - 0.125328371339 - 0.125630566076 - 0.125933334606 - 0.126236678021 - 0.126540597411 - 0.126845093871 - 0.127150168495 - 0.127455822382 - 0.127762056631 - 0.128068872345 - 0.128376270627 - 0.128684252584 - 0.128992819324 - 0.129301971957 - 0.129611711596 - 0.129922039355 - 0.130232956351 - 0.130544463704 - 0.130856562533 - 0.131169253961 - 0.131482539115 - 0.131796419122 - 0.13211089511 - 0.132425968212 - 0.132741639561 - 0.133057910293 - 0.133374781547 - 0.133692254462 - 0.134010330181 - 0.134329009849 - 0.134648294611 - 0.134968185619 - 0.135288684021 - 0.135609790972 - 0.135931507627 - 0.136253835144 - 0.136576774683 - 0.136900327405 - 0.137224494476 - 0.137549277061 - 0.137874676329 - 0.138200693451 - 0.138527329601 - 0.138854585954 - 0.139182463686 - 0.139510963979 - 0.139840088015 - 0.140169836976 - 0.140500212051 - 0.140831214429 - 0.141162845299 - 0.141495105855 - 0.141827997294 - 0.142161520813 - 0.142495677612 - 0.142830468893 - 0.143165895862 - 0.143501959725 - 0.143838661692 - 0.144176002974 - 0.144513984785 - 0.144852608342 - 0.145191874862 - 0.145531785568 - 0.145872341681 - 0.146213544427 - 0.146555395035 - 0.146897894734 - 0.147241044756 - 0.147584846337 - 0.147929300714 - 0.148274409126 - 0.148620172815 - 0.148966593026 - 0.149313671004 - 0.149661407999 - 0.150009805262 - 0.150358864047 - 0.15070858561 - 0.151058971209 - 0.151410022105 - 0.151761739561 - 0.152114124844 - 0.152467179221 - 0.152820903962 - 0.153175300341 - 0.153530369632 - 0.153886113113 - 0.154242532065 - 0.15459962777 - 0.154957401513 - 0.155315854582 - 0.155674988266 - 0.156034803857 - 0.156395302651 - 0.156756485944 - 0.157118355037 - 0.157480911232 - 0.157844155832 - 0.158208090146 - 0.158572715483 - 0.158938033154 - 0.159304044476 - 0.159670750763 - 0.160038153337 - 0.16040625352 - 0.160775052635 - 0.16114455201 - 0.161514752974 - 0.16188565686 - 0.162257265003 - 0.162629578739 - 0.163002599409 - 0.163376328354 - 0.16375076692 - 0.164125916454 - 0.164501778305 - 0.164878353827 - 0.165255644374 - 0.165633651305 - 0.166012375979 - 0.166391819759 - 0.16677198401 - 0.167152870101 - 0.167534479403 - 0.167916813287 - 0.168299873131 - 0.168683660313 - 0.169068176213 - 0.169453422215 - 0.169839399706 - 0.170226110075 - 0.170613554713 - 0.171001735013 - 0.171390652374 - 0.171780308195 - 0.172170703877 - 0.172561840826 - 0.172953720449 - 0.173346344157 - 0.173739713361 - 0.174133829478 - 0.174528693925 - 0.174924308125 - 0.175320673499 - 0.175717791476 - 0.176115663482 - 0.176514290951 - 0.176913675317 - 0.177313818017 - 0.17771472049 - 0.17811638418 - 0.178518810532 - 0.178922000994 - 0.179325957016 - 0.179730680053 - 0.180136171561 - 0.180542432998 - 0.180949465827 - 0.181357271513 - 0.181765851523 - 0.182175207326 - 0.182585340398 - 0.182996252212 - 0.183407944248 - 0.183820417987 - 0.184233674913 - 0.184647716514 - 0.18506254428 - 0.185478159703 - 0.185894564278 - 0.186311759505 - 0.186729746884 - 0.187148527919 - 0.187568104118 - 0.187988476991 - 0.188409648049 - 0.188831618809 - 0.189254390788 - 0.18967796551 - 0.190102344496 - 0.190527529276 - 0.190953521377 - 0.191380322335 - 0.191807933684 - 0.192236356962 - 0.192665593713 - 0.19309564548 - 0.193526513811 - 0.193958200256 - 0.194390706369 - 0.194824033706 - 0.195258183826 - 0.195693158292 - 0.196128958669 - 0.196565586525 - 0.197003043431 - 0.197441330961 - 0.197880450693 - 0.198320404207 - 0.198761193086 - 0.199202818915 - 0.199645283285 - 0.200088587787 - 0.200532734017 - 0.200977723573 - 0.201423558056 - 0.20187023907 - 0.202317768223 - 0.202766147125 - 0.203215377389 - 0.203665460633 - 0.204116398476 - 0.20456819254 - 0.205020844451 - 0.205474355838 - 0.205928728334 - 0.206383963572 - 0.206840063191 - 0.207297028833 - 0.207754862142 - 0.208213564765 - 0.208673138352 - 0.209133584559 - 0.20959490504 - 0.210057101458 - 0.210520175474 - 0.210984128755 - 0.211448962971 - 0.211914679794 - 0.2123812809 - 0.212848767969 - 0.213317142682 - 0.213786406724 - 0.214256561785 - 0.214727609557 - 0.215199551733 - 0.215672390014 - 0.216146126099 - 0.216620761694 - 0.217096298507 - 0.217572738248 - 0.218050082633 - 0.218528333379 - 0.219007492207 - 0.219487560842 - 0.21996854101 - 0.220450434442 - 0.220933242874 - 0.221416968041 - 0.221901611684 - 0.222387175549 - 0.222873661381 - 0.223361070931 - 0.223849405954 - 0.224338668207 - 0.22482885945 - 0.225319981446 - 0.225812035965 - 0.226305024775 - 0.226798949651 - 0.227293812371 - 0.227789614714 - 0.228286358466 - 0.228784045414 - 0.229282677348 - 0.229782256064 - 0.230282783358 - 0.230784261031 - 0.231286690889 - 0.231790074739 - 0.232294414393 - 0.232799711666 - 0.233305968375 - 0.233813186343 - 0.234321367394 - 0.234830513358 - 0.235340626067 - 0.235851707355 - 0.236363759063 - 0.236876783033 - 0.23739078111 - 0.237905755145 - 0.238421706991 - 0.238938638504 - 0.239456551544 - 0.239975447975 - 0.240495329665 - 0.241016198484 - 0.241538056306 - 0.242060905009 - 0.242584746475 - 0.243109582589 - 0.243635415239 - 0.244162246317 - 0.24469007772 - 0.245218911347 - 0.2457487491 - 0.246279592886 - 0.246811444616 - 0.247344306203 - 0.247878179564 - 0.248413066622 - 0.2489489693 - 0.249485889527 - 0.250023829235 - 0.250562790361 - 0.251102774842 - 0.251643784623 - 0.25218582165 - 0.252728887873 - 0.253272985248 - 0.253818115731 - 0.254364281285 - 0.254911483874 - 0.255459725468 - 0.25600900804 - 0.256559333566 - 0.257110704027 - 0.257663121406 - 0.258216587691 - 0.258771104875 - 0.259326674952 - 0.259883299921 - 0.260440981787 - 0.260999722554 - 0.261559524235 - 0.262120388843 - 0.262682318397 - 0.263245314919 - 0.263809380434 - 0.264374516973 - 0.264940726568 - 0.265508011258 - 0.266076373084 - 0.266645814091 - 0.267216336329 - 0.267787941849 - 0.26836063271 - 0.268934410971 - 0.269509278698 - 0.270085237959 - 0.270662290827 - 0.271240439378 - 0.271819685692 - 0.272400031855 - 0.272981479954 - 0.273564032082 - 0.274147690335 - 0.274732456813 - 0.275318333621 - 0.275905322866 - 0.276493426662 - 0.277082647124 - 0.277672986372 - 0.278264446531 - 0.278857029729 - 0.279450738099 - 0.280045573777 - 0.280641538903 - 0.281238635623 - 0.281836866084 - 0.282436232439 - 0.283036736846 - 0.283638381464 - 0.28424116846 - 0.284845100002 - 0.285450178263 - 0.28605640542 - 0.286663783656 - 0.287272315155 - 0.287882002108 - 0.288492846709 - 0.289104851155 - 0.289718017649 - 0.290332348397 - 0.29094784561 - 0.291564511502 - 0.292182348294 - 0.292801358207 - 0.29342154347 - 0.294042906314 - 0.294665448975 - 0.295289173694 - 0.295914082714 - 0.296540178285 - 0.297167462659 - 0.297795938094 - 0.298425606851 - 0.299056471196 - 0.299688533399 - 0.300321795735 - 0.300956260482 - 0.301591929924 - 0.302228806347 - 0.302866892044 - 0.303506189311 - 0.304146700448 - 0.304788427761 - 0.305431373557 - 0.306075540152 - 0.306720929862 - 0.307367545011 - 0.308015387925 - 0.308664460935 - 0.309314766377 - 0.309966306591 - 0.310619083922 - 0.311273100718 - 0.311928359334 - 0.312584862126 - 0.313242611458 - 0.313901609696 - 0.314561859212 - 0.315223362381 - 0.315886121584 - 0.316550139206 - 0.317215417636 - 0.317881959268 - 0.318549766501 - 0.319218841737 - 0.319889187385 - 0.320560805856 - 0.321233699568 - 0.321907870942 - 0.322583322403 - 0.323260056382 - 0.323938075315 - 0.324617381642 - 0.325297977806 - 0.325979866256 - 0.326663049448 - 0.327347529838 - 0.32803330989 - 0.328720392072 - 0.329408778857 - 0.33009847272 - 0.330789476145 - 0.331481791617 - 0.332175421628 - 0.332870368675 - 0.333566635256 - 0.334264223879 - 0.334963137054 - 0.335663377294 - 0.336364947121 - 0.337067849059 - 0.337772085636 - 0.338477659388 - 0.339184572853 - 0.339892828575 - 0.340602429103 - 0.34131337699 - 0.342025674794 - 0.342739325078 - 0.343454330411 - 0.344170693366 - 0.34488841652 - 0.345607502455 - 0.346327953761 - 0.347049773028 - 0.347772962855 - 0.348497525844 - 0.349223464601 - 0.349950781741 - 0.350679479878 - 0.351409561637 - 0.352141029644 - 0.35287388653 - 0.353608134934 - 0.354343777497 - 0.355080816867 - 0.355819255696 - 0.35655909664 - 0.357300342363 - 0.358042995531 - 0.358787058818 - 0.359532534899 - 0.360279426459 - 0.361027736185 - 0.361777466769 - 0.362528620909 - 0.363281201308 - 0.364035210675 - 0.364790651723 - 0.365547527169 - 0.366305839739 - 0.367065592159 - 0.367826787165 - 0.368589427496 - 0.369353515895 - 0.370119055112 - 0.370886047903 - 0.371654497026 - 0.372424405248 - 0.373195775338 - 0.373968610073 - 0.374742912234 - 0.375518684606 - 0.376295929981 - 0.377074651157 - 0.377854850935 - 0.378636532123 - 0.379419697533 - 0.380204349985 - 0.380990492301 - 0.38177812731 - 0.382567257847 - 0.383357886751 - 0.384150016867 - 0.384943651046 - 0.385738792144 - 0.386535443021 - 0.387333606545 - 0.388133285588 - 0.388934483027 - 0.389737201745 - 0.390541444631 - 0.391347214579 - 0.392154514489 - 0.392963347264 - 0.393773715817 - 0.394585623063 - 0.395399071924 - 0.396214065326 - 0.397030606203 - 0.397848697493 - 0.398668342139 - 0.399489543092 - 0.400312303306 - 0.401136625741 - 0.401962513365 - 0.402789969148 - 0.40361899607 - 0.404449597111 - 0.405281775263 - 0.406115533519 - 0.406950874879 - 0.40778780235 - 0.408626318942 - 0.409466427674 - 0.410308131568 - 0.411151433654 - 0.411996336965 - 0.412842844543 - 0.413690959433 - 0.414540684687 - 0.415392023363 - 0.416244978524 - 0.41709955324 - 0.417955750586 - 0.418813573643 - 0.419673025497 - 0.420534109242 - 0.421396827975 - 0.422261184802 - 0.423127182833 - 0.423994825183 - 0.424864114976 - 0.425735055339 - 0.426607649406 - 0.427481900317 - 0.428357811218 - 0.429235385261 - 0.430114625605 - 0.430995535412 - 0.431878117853 - 0.432762376104 - 0.433648313346 - 0.434535932768 - 0.435425237564 - 0.436316230933 - 0.437208916083 - 0.438103296224 - 0.438999374577 - 0.439897154364 - 0.440796638818 - 0.441697831173 - 0.442600734675 - 0.44350535257 - 0.444411688116 - 0.445319744572 - 0.446229525207 - 0.447141033295 - 0.448054272115 - 0.448969244954 - 0.449885955104 - 0.450804405864 - 0.451724600538 - 0.452646542439 - 0.453570234884 - 0.454495681197 - 0.455422884707 - 0.456351848751 - 0.457282576673 - 0.45821507182 - 0.45914933755 - 0.460085377223 - 0.461023194208 - 0.46196279188 - 0.46290417362 - 0.463847342815 - 0.464792302859 - 0.465739057153 - 0.466687609103 - 0.467637962123 - 0.468590119633 - 0.469544085059 - 0.470499861833 - 0.471457453395 - 0.472416863191 - 0.473378094673 - 0.4743411513 - 0.475306036538 - 0.476272753858 - 0.47724130674 - 0.478211698669 - 0.479183933136 - 0.48015801364 - 0.481133943687 - 0.482111726788 - 0.483091366461 - 0.484072866232 - 0.485056229633 - 0.486041460202 - 0.487028561485 - 0.488017537033 - 0.489008390406 - 0.490001125168 - 0.490995744893 - 0.491992253159 - 0.492990653552 - 0.493990949665 - 0.494993145097 - 0.495997243455 - 0.497003248352 - 0.498011163408 - 0.49902099225 - 0.500032738512 - 0.501046405834 - 0.502061997864 - 0.503079518257 - 0.504098970673 - 0.505120358782 - 0.50614368626 - 0.507168956787 - 0.508196174054 - 0.509225341758 - 0.510256463601 - 0.511289543294 - 0.512324584554 - 0.513361591106 - 0.514400566682 - 0.51544151502 - 0.516484439866 - 0.517529344973 - 0.518576234101 - 0.519625111017 - 0.520675979496 - 0.521728843319 - 0.522783706274 - 0.523840572158 - 0.524899444774 - 0.525960327932 - 0.527023225449 - 0.52808814115 - 0.529155078868 - 0.530224042441 - 0.531295035716 - 0.532368062547 - 0.533443126796 - 0.534520232331 - 0.535599383027 - 0.536680582769 - 0.537763835446 - 0.538849144957 - 0.539936515207 - 0.541025950109 - 0.542117453584 - 0.543211029558 - 0.544306681968 - 0.545404414755 - 0.546504231871 - 0.547606137272 - 0.548710134923 - 0.549816228798 - 0.550924422877 - 0.552034721147 - 0.553147127604 - 0.55426164625 - 0.555378281097 - 0.556497036162 - 0.557617915471 - 0.558740923058 - 0.559866062964 - 0.560993339237 - 0.562122755933 - 0.563254317118 - 0.564388026863 - 0.565523889247 - 0.566661908357 - 0.56780208829 - 0.568944433148 - 0.570088947041 - 0.571235634087 - 0.572384498414 - 0.573535544156 - 0.574688775453 - 0.575844196457 - 0.577001811325 - 0.578161624222 - 0.579323639322 - 0.580487860807 - 0.581654292865 - 0.582822939694 - 0.583993805501 - 0.585166894496 - 0.586342210903 - 0.587519758951 - 0.588699542876 - 0.589881566924 - 0.591065835349 - 0.592252352411 - 0.593441122382 - 0.594632149538 - 0.595825438165 - 0.597020992558 - 0.598218817018 - 0.599418915856 - 0.60062129339 - 0.601825953947 - 0.603032901861 - 0.604242141477 - 0.605453677145 - 0.606667513225 - 0.607883654085 - 0.609102104101 - 0.610322867657 - 0.611545949147 - 0.612771352972 - 0.613999083541 - 0.615229145272 - 0.616461542592 - 0.617696279935 - 0.618933361744 - 0.620172792471 - 0.621414576576 - 0.622658718528 - 0.623905222802 - 0.625154093886 - 0.626405336273 - 0.627658954465 - 0.628914952973 - 0.630173336317 - 0.631434109026 - 0.632697275636 - 0.633962840693 - 0.63523080875 - 0.636501184371 - 0.637773972126 - 0.639049176596 - 0.64032680237 - 0.641606854045 - 0.642889336227 - 0.644174253531 - 0.645461610581 - 0.64675141201 - 0.648043662458 - 0.649338366576 - 0.650635529022 - 0.651935154465 - 0.653237247581 - 0.654541813056 - 0.655848855583 - 0.657158379867 - 0.65847039062 - 0.659784892562 - 0.661101890424 - 0.662421388945 - 0.663743392873 - 0.665067906966 - 0.66639493599 - 0.667724484719 - 0.669056557938 - 0.670391160441 - 0.67172829703 - 0.673067972516 - 0.674410191721 - 0.675754959474 - 0.677102280614 - 0.67845215999 - 0.679804602459 - 0.681159612888 - 0.682517196153 - 0.683877357138 - 0.685240100739 - 0.686605431859 - 0.687973355411 - 0.689343876318 - 0.690716999511 - 0.692092729931 - 0.69347107253 - 0.694852032266 - 0.696235614109 - 0.697621823038 - 0.699010664042 - 0.700402142117 - 0.701796262271 - 0.70319302952 - 0.704592448892 - 0.70599452542 - 0.707399264152 - 0.708806670141 - 0.710216748453 - 0.71162950416 - 0.713044942348 - 0.714463068109 - 0.715883886546 - 0.717307402772 - 0.71873362191 - 0.720162549092 - 0.72159418946 - 0.723028548164 - 0.724465630368 - 0.725905441242 - 0.727347985966 - 0.728793269733 - 0.730241297743 - 0.731692075206 - 0.733145607343 - 0.734601899385 - 0.736060956572 - 0.737522784154 - 0.738987387391 - 0.740454771554 - 0.741924941924 - 0.743397903789 - 0.744873662452 - 0.746352223222 - 0.747833591419 - 0.749317772376 - 0.750804771431 - 0.752294593936 - 0.753787245253 - 0.755282730751 - 0.756781055814 - 0.758282225832 - 0.759786246207 - 0.761293122351 - 0.762802859687 - 0.764315463648 - 0.765830939677 - 0.767349293226 - 0.76887052976 - 0.770394654752 - 0.771921673688 - 0.773451592062 - 0.774984415379 - 0.776520149156 - 0.778058798917 - 0.779600370202 - 0.781144868555 - 0.782692299536 - 0.784242668712 - 0.785795981663 - 0.787352243978 - 0.788911461257 - 0.790473639111 - 0.792038783161 - 0.79360689904 - 0.79517799239 - 0.796752068865 - 0.798329134128 - 0.799909193855 - 0.801492253732 - 0.803078319456 - 0.804667396733 - 0.806259491281 - 0.807854608831 - 0.809452755121 - 0.811053935903 - 0.812658156938 - 0.814265424 - 0.815875742871 - 0.817489119347 - 0.819105559233 - 0.820725068345 - 0.822347652512 - 0.823973317573 - 0.825602069376 - 0.827233913783 - 0.828868856667 - 0.83050690391 - 0.832148061407 - 0.833792335063 - 0.835439730796 - 0.837090254533 - 0.838743912214 - 0.840400709789 - 0.84206065322 - 0.843723748481 - 0.845390001556 - 0.84705941844 - 0.848732005142 - 0.85040776768 - 0.852086712083 - 0.853768844395 - 0.855454170667 - 0.857142696964 - 0.858834429363 - 0.86052937395 - 0.862227536826 - 0.863928924101 - 0.865633541896 - 0.867341396347 - 0.869052493599 - 0.870766839809 - 0.872484441146 - 0.874205303791 - 0.875929433935 - 0.877656837785 - 0.879387521554 - 0.881121491472 - 0.882858753778 - 0.884599314722 - 0.886343180569 - 0.888090357594 - 0.889840852084 - 0.891594670338 - 0.893351818666 - 0.895112303392 - 0.896876130852 - 0.898643307391 - 0.900413839369 - 0.902187733157 - 0.903964995139 - 0.90574563171 - 0.907529649277 - 0.90931705426 - 0.911107853092 - 0.912902052215 - 0.914699658086 - 0.916500677175 - 0.918305115961 - 0.920112980938 - 0.921924278612 - 0.9237390155 - 0.925557198133 - 0.927378833053 - 0.929203926815 - 0.931032485987 - 0.932864517149 - 0.934700026893 - 0.936539021824 - 0.93838150856 - 0.940227493731 - 0.942076983979 - 0.94392998596 - 0.945786506342 - 0.947646551804 - 0.949510129042 - 0.95137724476 - 0.953247905677 - 0.955122118526 - 0.956999890049 - 0.958881227004 - 0.960766136161 - 0.962654624303 - 0.964546698225 - 0.966442364736 - 0.968341630657 - 0.970244502823 - 0.972150988081 - 0.974061093291 - 0.975974825327 - 0.977892191076 - 0.979813197437 - 0.981737851322 - 0.983666159657 - 0.985598129381 - 0.987533767447 - 0.989473080819 - 0.991416076477 - 0.993362761411 - 0.995313142627 - 0.997267227143 - 0.999225021991 - 1.00118653422 - 1.00315177088 - 1.00512073904 - 1.0070934458 - 1.00906989826 - 1.01105010351 - 1.01303406869 - 1.01502180094 - 1.01701330741 - 1.01900859527 - 1.0210076717 - 1.02301054389 - 1.02501721904 - 1.02702770438 - 1.02904200715 - 1.03106013459 - 1.03308209396 - 1.03510789254 - 1.03713753762 - 1.03917103651 - 1.04120839651 - 1.04324962497 - 1.04529472922 - 1.04734371663 - 1.04939659457 - 1.05145337043 - 1.0535140516 - 1.05557864551 - 1.05764715957 - 1.05971960125 - 1.06179597799 - 1.06387629726 - 1.06596056656 - 1.06804879337 - 1.07014098522 - 1.07223714964 - 1.07433729416 - 1.07644142635 - 1.07854955377 - 1.08066168401 - 1.08277782468 - 1.08489798339 - 1.08702216776 - 1.08915038544 - 1.09128264409 - 1.09341895138 - 1.095559315 - 1.09770374265 - 1.09985224204 - 1.10200482092 - 1.10416148702 - 1.1063222481 - 1.10848711195 - 1.11065608635 - 1.1128291791 - 1.11500639803 - 1.11718775096 - 1.11937324576 - 1.12156289028 - 1.12375669241 - 1.12595466003 - 1.12815680105 - 1.13036312341 - 1.13257363504 - 1.1347883439 - 1.13700725794 - 1.13923038517 - 1.14145773358 - 1.14368931118 - 1.145925126 - 1.14816518609 - 1.15040949951 - 1.15265807434 - 1.15491091867 - 1.1571680406 - 1.15942944825 - 1.16169514977 - 1.16396515331 - 1.16623946703 - 1.16851809913 - 1.17080105779 - 1.17308835123 - 1.17537998769 - 1.17767597541 - 1.17997632266 - 1.1822810377 - 1.18459012884 - 1.18690360438 - 1.18922147265 - 1.19154374199 - 1.19387042075 - 1.19620151732 - 1.19853704006 - 1.2008769974 - 1.20322139775 - 1.20557024955 - 1.20792356124 - 1.21028134131 - 1.21264359822 - 1.21501034049 - 1.21738157662 - 1.21975731516 - 1.22213756465 - 1.22452233365 - 1.22691163075 - 1.22930546454 - 1.23170384365 - 1.23410677669 - 1.23651427232 - 1.2389263392 - 1.24134298601 - 1.24376422144 - 1.24619005421 - 1.24862049305 - 1.2510555467 - 1.25349522393 - 1.25593953351 - 1.25838848424 - 1.26084208494 - 1.26330034443 - 1.26576327155 - 1.26823087517 - 1.27070316418 - 1.27318014746 - 1.27566183393 - 1.27814823252 - 1.28063935218 - 1.28313520187 - 1.28563579057 - 1.28814112728 - 1.29065122102 - 1.29316608081 - 1.29568571572 - 1.29821013479 - 1.30073934713 - 1.30327336183 - 1.305812188 - 1.30835583479 - 1.31090431135 - 1.31345762685 - 1.31601579047 - 1.31857881142 - 1.32114669893 - 1.32371946223 - 1.32629711058 - 1.32887965327 - 1.33146709957 - 1.33405945881 - 1.3366567403 - 1.33925895341 - 1.34186610748 - 1.34447821191 - 1.34709527608 - 1.34971730943 - 1.35234432138 - 1.35497632139 - 1.35761331893 - 1.36025532349 - 1.36290234457 - 1.3655543917 - 1.36821147442 - 1.3708736023 - 1.37354078492 - 1.37621303186 - 1.37889035276 - 1.38157275723 - 1.38426025494 - 1.38695285556 - 1.38965056877 - 1.39235340428 - 1.39506137182 - 1.39777448113 - 1.40049274198 - 1.40321616415 - 1.40594475743 - 1.40867853165 - 1.41141749664 - 1.41416166226 - 1.41691103839 - 1.41966563491 - 1.42242546175 - 1.42519052882 - 1.42796084608 - 1.43073642351 - 1.43351727108 - 1.43630339881 - 1.43909481671 - 1.44189153484 - 1.44469356326 - 1.44750091205 - 1.45031359131 - 1.45313161117 - 1.45595498177 - 1.45878371326 - 1.46161781582 - 1.46445729965 - 1.46730217498 - 1.47015245203 - 1.47300814107 - 1.47586925236 - 1.47873579622 - 1.48160778294 - 1.48448522287 - 1.48736812635 - 1.49025650377 - 1.49315036552 - 1.49604972201 - 1.49895458367 - 1.50186496096 - 1.50478086435 - 1.50770230433 - 1.51062929142 - 1.51356183614 - 1.51649994905 - 1.51944364073 - 1.52239292176 - 1.52534780276 - 1.52830829437 - 1.53127440722 - 1.53424615201 - 1.53722353941 - 1.54020658015 - 1.54319528496 - 1.5461896646 - 1.54918972984 - 1.55219549147 - 1.55520696031 - 1.5582241472 - 1.56124706299 - 1.56427571857 - 1.56731012483 - 1.57035029269 - 1.57339623309 - 1.57644795699 - 1.57950547537 - 1.58256879924 - 1.58563793962 - 1.58871290755 - 1.59179371409 - 1.59488037034 - 1.5979728874 - 1.6010712764 - 1.60417554849 - 1.60728571483 - 1.61040178663 - 1.61352377509 - 1.61665169144 - 1.61978554695 - 1.62292535289 - 1.62607112056 - 1.62922286128 - 1.63238058639 - 1.63554430725 - 1.63871403525 - 1.6418897818 - 1.64507155831 - 1.64825937625 - 1.65145324707 - 1.65465318229 - 1.6578591934 - 1.66107129195 - 1.66428948949 - 1.66751379761 - 1.6707442279 - 1.673980792 - 1.67722350155 - 1.68047236822 - 1.68372740369 - 1.68698861969 - 1.69025602794 - 1.69352964021 - 1.69680946828 - 1.70009552394 - 1.70338781902 - 1.70668636537 - 1.70999117486 - 1.71330225938 - 1.71661963084 - 1.71994330119 - 1.72327328238 - 1.7266095864 - 1.72995222524 - 1.73330121095 - 1.73665655556 - 1.74001827117 - 1.74338636985 - 1.74676086373 - 1.75014176496 - 1.7535290857 - 1.75692283814 - 1.76032303448 - 1.76372968698 - 1.76714280788 - 1.77056240947 - 1.77398850406 - 1.77742110396 - 1.78086022154 - 1.78430586916 - 1.78775805924 - 1.79121680418 - 1.79468211644 - 1.79815400849 - 1.80163249282 - 1.80511758194 - 1.80860928841 - 1.81210762477 - 1.81561260363 - 1.81912423759 - 1.82264253929 - 1.82616752139 - 1.82969919657 - 1.83323757755 - 1.83678267705 - 1.84033450784 - 1.84389308269 - 1.84745841441 - 1.85103051583 - 1.8546093998 - 1.85819507921 - 1.86178756695 - 1.86538687594 - 1.86899301916 - 1.87260600956 - 1.87622586016 - 1.87985258397 - 1.88348619405 - 1.88712670347 - 1.89077412534 - 1.89442847277 - 1.89808975892 - 1.90175799697 - 1.90543320011 - 1.90911538156 - 1.91280455459 - 1.91650073246 - 1.92020392847 - 1.92391415595 - 1.92763142825 - 1.93135575876 - 1.93508716085 - 1.93882564798 - 1.94257123359 - 1.94632393115 - 1.95008375417 - 1.95385071618 - 1.95762483075 - 1.96140611143 - 1.96519457185 - 1.96899022564 - 1.97279308645 - 1.97660316797 - 1.98042048391 - 1.98424504801 - 1.98807687402 - 1.99191597574 - 1.99576236699 - 1.99961606159 - 2.00347707343 - 2.00734541639 - 2.01122110439 - 2.01510415138 - 2.01899457134 - 2.02289237826 - 2.02679758616 - 2.03071020911 - 2.03463026118 - 2.03855775648 - 2.04249270914 - 2.04643513331 - 2.05038504319 - 2.05434245299 - 2.05830737695 - 2.06227982934 - 2.06625982445 - 2.07024737661 - 2.07424250016 - 2.07824520947 - 2.08225551896 - 2.08627344306 - 2.09029899621 - 2.09433219292 - 2.09837304768 - 2.10242157505 - 2.10647778958 - 2.11054170589 - 2.11461333858 - 2.11869270231 - 2.12277981177 - 2.12687468165 - 2.1309773267 - 2.13508776167 - 2.13920600136 - 2.14333206059 - 2.1474659542 - 2.15160769707 - 2.15575730411 - 2.15991479024 - 2.16408017043 - 2.16825345966 - 2.17243467296 - 2.17662382536 - 2.18082093195 - 2.18502600783 - 2.18923906812 - 2.19346012799 - 2.19768920262 - 2.20192630725 - 2.2061714571 - 2.21042466746 - 2.21468595364 - 2.21895533097 - 2.2232328148 - 2.22751842054 - 2.2318121636 - 2.23611405944 - 2.24042412353 - 2.24474237139 - 2.24906881855 - 2.25340348059 - 2.25774637309 - 2.2620975117 - 2.26645691205 - 2.27082458985 - 2.27520056081 - 2.27958484068 - 2.28397744523 - 2.28837839027 - 2.29278769163 - 2.29720536519 - 2.30163142683 - 2.30606589249 - 2.31050877813 - 2.31496009972 - 2.3194198733 - 2.3238881149 - 2.3283648406 - 2.33285006652 - 2.3373438088 - 2.3418460836 - 2.34635690713 - 2.35087629561 - 2.35540426532 - 2.35994083254 - 2.3644860136 - 2.36903982485 - 2.37360228269 - 2.37817340353 - 2.38275320381 - 2.38734170002 - 2.39193890868 - 2.39654484631 - 2.4011595295 - 2.40578297486 - 2.41041519901 - 2.41505621864 - 2.41970605043 - 2.42436471112 - 2.42903221748 - 2.4337085863 - 2.43839383441 - 2.44308797866 - 2.44779103596 - 2.45250302322 - 2.4572239574 - 2.46195385549 - 2.4666927345 - 2.4714406115 - 2.47619750355 - 2.4809634278 - 2.48573840137 - 2.49052244146 - 2.49531556528 - 2.50011779008 - 2.50492913314 - 2.50974961177 - 2.51457924331 - 2.51941804516 - 2.52426603471 - 2.52912322942 - 2.53398964676 - 2.53886530425 - 2.54375021942 - 2.54864440986 - 2.55354789319 - 2.55846068703 - 2.56338280908 - 2.56831427704 - 2.57325510866 - 2.57820532172 - 2.58316493404 - 2.58813396345 - 2.59311242784 - 2.59810034513 - 2.60309773326 - 2.60810461022 - 2.61312099402 - 2.61814690271 - 2.62318235439 - 2.62822736716 - 2.63328195919 - 2.63834614866 - 2.6434199538 - 2.64850339286 - 2.65359648414 - 2.65869924596 - 2.66381169668 - 2.66893385471 - 2.67406573847 - 2.67920736643 - 2.6843587571 - 2.689519929 - 2.69469090072 - 2.69987169086 - 2.70506231806 - 2.71026280099 - 2.71547315839 - 2.72069340898 - 2.72592357157 - 2.73116366496 - 2.73641370802 - 2.74167371963 - 2.74694371873 - 2.75222372427 - 2.75751375527 - 2.76281383075 - 2.76812396978 - 2.77344419148 - 2.77877451499 - 2.78411495949 - 2.78946554419 - 2.79482628836 - 2.80019721127 - 2.80557833227 - 2.8109696707 - 2.81637124598 - 2.82178307754 - 2.82720518485 - 2.83263758743 - 2.83808030482 - 2.84353335661 - 2.84899676242 - 2.85447054191 - 2.85995471478 - 2.86544930076 - 2.87095431962 - 2.87646979118 - 2.88199573528 - 2.8875321718 - 2.89307912067 - 2.89863660186 - 2.90420463534 - 2.90978324118 - 2.91537243943 - 2.9209722502 - 2.92658269366 - 2.93220378999 - 2.93783555942 - 2.94347802221 - 2.94913119866 - 2.95479510913 - 2.96046977398 - 2.96615521365 - 2.97185144858 - 2.97755849928 - 2.98327638628 - 2.98900513016 - 2.99474475154 - 3.00049527106 - 3.00625670942 - 3.01202908736 - 3.01781242564 - 3.02360674507 - 3.02941206651 - 3.03522841084 - 3.041055799 - 3.04689425195 - 3.05274379071 - 3.05860443632 - 3.06447620987 - 3.0703591325 - 3.07625322537 - 3.08215850968 - 3.0880750067 - 3.09400273771 - 3.09994172404 - 3.10589198706 - 3.11185354819 - 3.11782642887 - 3.12381065061 - 3.12980623492 - 3.1358132034 - 3.14183157765 - 3.14786137933 - 3.15390263014 - 3.15995535182 - 3.16601956614 - 3.17209529494 - 3.17818256007 - 3.18428138344 - 3.19039178699 - 3.19651379271 - 3.20264742264 - 3.20879269884 - 3.21494964342 - 3.22111827855 - 3.22729862642 - 3.23349070927 - 3.23969454938 - 3.24591016907 - 3.25213759072 - 3.25837683673 - 3.26462792955 - 3.27089089168 - 3.27716574565 - 3.28345251405 - 3.28975121949 - 3.29606188464 - 3.30238453222 - 3.30871918496 - 3.31506586568 - 3.3214245972 - 3.3277954024 - 3.33417830422 - 3.34057332562 - 3.34698048961 - 3.35339981925 - 3.35983133763 - 3.36627506791 - 3.37273103327 - 3.37919925693 - 3.38567976218 - 3.39217257234 - 3.39867771077 - 3.40519520087 - 3.41172506611 - 3.41826732997 - 3.42482201601 - 3.4313891478 - 3.43796874898 - 3.44456084322 - 3.45116545425 - 3.45778260583 - 3.46441232178 - 3.47105462594 - 3.47770954223 - 3.48437709459 - 3.49105730701 - 3.49775020353 - 3.50445580824 - 3.51117414526 - 3.51790523877 - 3.52464911299 - 3.53140579219 - 3.53817530069 - 3.54495766284 - 3.55175290304 - 3.55856104576 - 3.56538211548 - 3.57221613676 - 3.57906313419 - 3.5859231324 - 3.59279615609 - 3.59968222997 - 3.60658137884 - 3.61349362751 - 3.62041900087 - 3.62735752383 - 3.63430922136 - 3.64127411847 - 3.64825224023 - 3.65524361175 - 3.66224825819 - 3.66926620475 - 3.67629747668 - 3.6833420993 - 3.69040009794 - 3.697471498 - 3.70455632494 - 3.71165460424 - 3.71876636145 - 3.72589162216 - 3.73303041201 - 3.74018275669 - 3.74734868193 - 3.75452821352 - 3.76172137731 - 3.76892819916 - 3.77614870501 - 3.78338292086 - 3.79063087272 - 3.79789258668 - 3.80516808888 - 3.81245740548 - 3.81976056273 - 3.8270775869 - 3.83440850432 - 3.84175334137 - 3.84911212448 - 3.85648488014 - 3.86387163487 - 3.87127241525 - 3.87868724791 - 3.88611615955 - 3.89355917688 - 3.90101632669 - 3.90848763582 - 3.91597313115 - 3.92347283962 - 3.93098678821 - 3.93851500397 - 3.94605751398 - 3.95361434538 - 3.96118552537 - 3.9687710812 - 3.97637104015 - 3.98398542958 - 3.99161427688 - 3.99925760951 - 4.00691545498 - 4.01458784083 - 4.02227479468 - 4.02997634419 - 4.03769251707 - 4.04542334109 - 4.05316884407 - 4.06092905387 - 4.06870399843 - 4.07649370572 - 4.08429820377 - 4.09211752067 - 4.09995168455 - 4.10780072361 - 4.11566466609 - 4.12354354028 - 4.13143737454 - 4.13934619727 - 4.14727003694 - 4.15520892206 - 4.16316288119 - 4.17113194295 - 4.17911613603 - 4.18711548916 - 4.19513003111 - 4.20315979073 - 4.21120479691 - 4.21926507861 - 4.22734066482 - 4.23543158461 - 4.24353786709 - 4.25165954144 - 4.25979663687 - 4.26794918266 - 4.27611720817 - 4.28430074277 - 4.29249981591 - 4.3007144571 - 4.3089446959 - 4.31719056193 - 4.32545208485 - 4.3337292944 - 4.34202222036 - 4.35033089257 - 4.35865534093 - 4.36699559539 - 4.37535168598 - 4.38372364275 - 4.39211149583 - 4.40051527541 - 4.40893501173 - 4.41737073507 - 4.42582247581 - 4.43429026436 - 4.44277413117 - 4.45127410679 - 4.4597902218 - 4.46832250684 - 4.47687099262 - 4.4854357099 - 4.49401668949 - 4.50261396228 - 4.51122755921 - 4.51985751126 - 4.52850384949 - 4.53716660503 - 4.54584580903 - 4.55454149273 - 4.56325368742 - 4.57198242445 - 4.58072773524 - 4.58948965125 - 4.598268204 - 4.6070634251 - 4.61587534618 - 4.62470399897 - 4.63354941522 - 4.64241162677 - 4.6512906655 - 4.66018656337 - 4.6690993524 - 4.67802906464 - 4.68697573224 - 4.69593938739 - 4.70492006234 - 4.71391778941 - 4.72293260098 - 4.73196452949 - 4.74101360744 - 4.75007986738 - 4.75916334196 - 4.76826406384 - 4.77738206579 - 4.78651738061 - 4.79567004117 - 4.80484008041 - 4.81402753133 - 4.82323242698 - 4.8324548005 - 4.84169468506 - 4.85095211392 - 4.86022712039 - 4.86951973785 - 4.87882999973 - 4.88815793953 - 4.89750359083 - 4.90686698725 - 4.91624816248 - 4.92564715029 - 4.93506398449 - 4.94449869897 - 4.95395132769 - 4.96342190465 - 4.97291046393 - 4.98241703969 - 4.99194166612 - 5.00148437751 - 5.01104520819 - 5.02062419256 - 5.0302213651 - 5.03983676033 - 5.04947041287 - 5.05912235738 - 5.06879262858 - 5.07848126128 - 5.08818829034 - 5.09791375068 - 5.10765767732 - 5.11742010531 - 5.12720106977 - 5.13700060592 - 5.146818749 - 5.15665553435 - 5.16651099736 - 5.17638517351 - 5.18627809832 - 5.19618980739 - 5.20612033639 - 5.21606972105 - 5.22603799718 - 5.23602520064 - 5.24603136738 - 5.25605653339 - 5.26610073476 - 5.27616400763 - 5.28624638822 - 5.29634791279 - 5.3064686177 - 5.31660853938 - 5.3267677143 - 5.33694617903 - 5.34714397019 - 5.35736112448 - 5.36759767867 - 5.37785366959 - 5.38812913414 - 5.3984241093 - 5.40873863212 - 5.41907273971 - 5.42942646927 - 5.43979985804 - 5.45019294336 - 5.46060576262 - 5.47103835329 - 5.48149075293 - 5.49196299913 - 5.50245512958 - 5.51296718204 - 5.52349919434 - 5.53405120437 - 5.5446232501 - 5.55521536958 - 5.56582760092 - 5.57645998231 - 5.58711255201 - 5.59778534836 - 5.60847840975 - 5.61919177467 - 5.62992548166 - 5.64067956936 - 5.65145407646 - 5.66224904174 - 5.67306450402 - 5.68390050225 - 5.6947570754 - 5.70563426255 - 5.71653210284 - 5.72745063548 - 5.73838989976 - 5.74934993504 - 5.76033078077 - 5.77133247646 - 5.7823550617 - 5.79339857615 - 5.80446305955 - 5.81554855172 - 5.82665509255 - 5.83778272199 - 5.84893148011 - 5.86010140701 - 5.87129254288 - 5.88250492801 - 5.89373860273 - 5.90499360747 - 5.91626998273 - 5.92756776909 - 5.93888700721 - 5.9502277378 - 5.96159000169 - 5.97297383976 - 5.98437929297 - 5.99580640237 - 6.00725520907 - 6.01872575428 - 6.03021807927 - 6.04173222538 - 6.05326823407 - 6.06482614684 - 6.07640600527 - 6.08800785104 - 6.0996317259 - 6.11127767168 - 6.12294573028 - 6.13463594368 - 6.14634835397 - 6.15808300327 - 6.16983993383 - 6.18161918794 - 6.19342080799 - 6.20524483645 - 6.21709131587 - 6.22896028888 - 6.24085179819 - 6.25276588658 - 6.26470259694 - 6.2766619722 - 6.28864405542 - 6.3006488897 - 6.31267651825 - 6.32472698434 - 6.33680033134 - 6.34889660269 - 6.36101584193 - 6.37315809266 - 6.38532339857 - 6.39751180344 - 6.40972335114 - 6.42195808559 - 6.43421605084 - 6.44649729098 - 6.45880185022 - 6.47112977283 - 6.48348110317 - 6.49585588568 - 6.5082541649 - 6.52067598544 - 6.533121392 - 6.54559042937 - 6.55808314241 - 6.57059957608 - 6.58313977541 - 6.59570378554 - 6.60829165167 - 6.6209034191 - 6.63353913322 - 6.64619883948 - 6.65888258346 - 6.67159041078 - 6.68432236718 - 6.69707849848 - 6.70985885057 - 6.72266346944 - 6.73549240118 - 6.74834569194 - 6.76122338797 - 6.77412553563 - 6.78705218133 - 6.80000337159 - 6.81297915301 - 6.8259795723 - 6.83900467622 - 6.85205451165 - 6.86512912555 - 6.87822856496 - 6.89135287703 - 6.90450210898 - 6.91767630812 - 6.93087552188 - 6.94409979773 - 6.95734918327 - 6.97062372617 - 6.98392347421 - 6.99724847524 - 7.01059877721 - 7.02397442816 - 7.03737547623 - 7.05080196963 - 7.06425395668 - 7.07773148578 - 7.09123460544 - 7.10476336425 - 7.11831781088 - 7.13189799411 - 7.14550396281 - 7.15913576595 - 7.17279345256 - 7.18647707181 - 7.20018667293 - 7.21392230524 - 7.22768401819 - 7.24147186129 - 7.25528588416 - 7.26912613649 - 7.28299266811 - 7.2968855289 - 7.31080476886 - 7.32475043808 - 7.33872258673 - 7.3527212651 - 7.36674652356 - 7.38079841258 - 7.39487698273 - 7.40898228466 - 7.42311436913 - 7.437273287 - 7.45145908922 - 7.46567182683 - 7.47991155097 - 7.49417831289 - 7.50847216393 - 7.52279315552 - 7.5371413392 - 7.55151676659 - 7.56591948942 - 7.58034955953 - 7.59480702884 - 7.60929194937 - 7.62380437324 - 7.63834435268 - 7.65291194002 - 7.66750718766 - 7.68213014813 - 7.69678087406 - 7.71145941815 - 7.72616583324 - 7.74090017223 - 7.75566248816 - 7.77045283414 - 7.78527126339 - 7.80011782924 - 7.81499258511 - 7.82989558454 - 7.84482688113 - 7.85978652864 - 7.87477458088 - 7.88979109179 - 7.90483611541 - 7.91990970588 - 7.93501191743 - 7.95014280441 - 7.96530242128 - 7.98049082257 - 7.99570806295 - 8.01095419717 - 8.0262292801 - 8.0415333667 - 8.05686651205 - 8.07222877131 - 8.08762019978 - 8.10304085282 - 8.11849078594 - 8.13397005474 - 8.1494787149 - 8.16501682224 - 8.18058443268 - 8.19618160223 - 8.21180838701 - 8.22746484326 - 8.24315102732 - 8.25886699563 - 8.27461280475 - 8.29038851134 - 8.30619417217 - 8.3220298441 - 8.33789558413 - 8.35379144934 - 8.36971749695 - 8.38567378424 - 8.40166036866 - 8.41767730771 - 8.43372465904 - 8.4498024804 - 8.46591082963 - 8.4820497647 - 8.4982193437 - 8.51441962479 - 8.53065066629 - 8.54691252659 - 8.56320526421 - 8.57952893778 - 8.59588360605 - 8.61226932786 - 8.62868616218 - 8.64513416807 - 8.66161340474 - 8.67812393147 - 8.69466580768 - 8.7112390929 - 8.72784384676 - 8.74448012902 - 8.76114799953 - 8.77784751829 - 8.79457874537 - 8.81134174099 - 8.82813656547 - 8.84496327924 - 8.86182194285 - 8.87871261697 - 8.89563536238 - 8.91259023997 - 8.92957731075 - 8.94659663586 - 8.96364827653 - 8.98073229413 - 8.99784875013 - 9.01499770612 - 9.03217922381 - 9.04939336503 - 9.06664019172 - 9.08391976595 - 9.10123214989 - 9.11857740585 - 9.13595559623 - 9.15336678358 - 9.17081103054 - 9.18828839989 - 9.20579895452 - 9.22334275744 - 9.24091987178 - 9.2585303608 - 9.27617428785 - 9.29385171644 - 9.31156271016 - 9.32930733277 - 9.3470856481 - 9.36489772014 - 9.38274361297 - 9.40062339082 - 9.41853711803 - 9.43648485905 - 9.45446667848 - 9.47248264101 - 9.49053281148 - 9.50861725484 - 9.52673603616 - 9.54488922065 - 9.56307687363 - 9.58129906055 - 9.59955584697 - 9.61784729859 - 9.63617348124 - 9.65453446086 - 9.67293030352 - 9.69136107541 - 9.70982684287 - 9.72832767233 - 9.74686363037 - 9.7654347837 - 9.78404119914 - 9.80268294364 - 9.82136008428 - 9.84007268828 - 9.85882082297 - 9.87760455582 - 9.89642395441 - 9.91527908646 - 9.93417001984 - 9.9530968225 - 9.97205956257 - 9.99105830828 - 10.010093128 - 10.0291640902 - 10.0482712635 - 10.0674147168 - 10.0865945187 - 10.1058107385 - 10.1250634452 - 10.1443527081 - 10.1636785967 - 10.1830411804 - 10.2024405289 - 10.2218767122 - 10.2413497999 - 10.2608598624 - 10.2804069697 - 10.2999911923 - 10.3196126005 - 10.339271265 - 10.3589672566 - 10.378700646 - 10.3984715044 - 10.4182799028 - 10.4381259125 - 10.4580096051 - 10.4779310519 - 10.4978903247 - 10.5178874953 - 10.5379226357 - 10.5579958179 - 10.5781071142 - 10.5982565971 - 10.6184443388 - 10.6386704122 - 10.65893489 - 10.6792378452 - 10.6995793507 - 10.7199594798 - 10.7403783058 - 10.7608359022 - 10.7813323426 - 10.8018677007 - 10.8224420505 - 10.843055466 - 10.8637080214 - 10.884399791 - 10.9051308492 - 10.9259012707 - 10.9467111301 - 10.9675605024 - 10.9884494626 - 11.0093780859 - 11.0303464475 - 11.051354623 - 11.0724026879 - 11.0934907179 - 11.114618789 - 11.1357869772 - 11.1569953586 - 11.1782440096 - 11.1995330066 - 11.2208624263 - 11.2422323453 - 11.2636428407 - 11.2850939893 - 11.3065858685 - 11.3281185555 - 11.3496921279 - 11.3713066632 - 11.3929622393 - 11.4146589341 - 11.4363968257 - 11.4581759922 - 11.479996512 - 11.5018584638 - 11.523761926 - 11.5457069776 - 11.5676936976 - 11.589722165 - 11.6117924591 - 11.6339046593 - 11.6560588452 - 11.6782550965 - 11.7004934932 - 11.7227741151 - 11.7450970425 - 11.7674623558 - 11.7898701353 - 11.8123204618 - 11.834813416 - 11.8573490789 - 11.8799275315 - 11.9025488551 - 11.9252131311 - 11.947920441 - 11.9706708666 - 11.9934644898 - 12.0163013925 - 12.0391816569 - 12.0621053654 - 12.0850726005 - 12.1080834448 - 12.131137981 - 12.1542362922 - 12.1773784616 - 12.2005645722 - 12.2237947077 - 12.2470689515 - 12.2703873875 - 12.2937500996 - 12.3171571717 - 12.3406086882 - 12.3641047334 - 12.3876453919 - 12.4112307484 - 12.4348608878 - 12.4585358951 - 12.4822558554 - 12.5060208542 - 12.529830977 - 12.5536863094 - 12.5775869372 - 12.6015329466 - 12.6255244236 - 12.6495614546 - 12.6736441261 - 12.6977725247 - 12.7219467374 - 12.7461668509 - 12.7704329526 - 12.7947451297 - 12.8191034697 - 12.8435080603 - 12.8679589893 - 12.8924563447 - 12.9170002146 - 12.9415906873 - 12.9662278514 - 12.9909117955 - 13.0156426083 - 13.040420379 - 13.0652451967 - 13.0901171507 - 13.1150363304 - 13.1400028256 - 13.1650167262 - 13.190078122 - 13.2151871034 - 13.2403437606 - 13.2655481842 - 13.2908004649 - 13.3161006935 - 13.3414489611 - 13.366845359 - 13.3922899784 - 13.4177829109 - 13.4433242484 - 13.4689140826 - 13.4945525058 - 13.52023961 - 13.5459754879 - 13.5717602319 - 13.5975939349 - 13.6234766898 - 13.6494085898 - 13.6753897281 - 13.7014201984 - 13.7275000941 - 13.7536295093 - 13.7798085379 - 13.8060372741 - 13.8323158123 - 13.858644247 - 13.8850226731 - 13.9114511853 - 13.9379298789 - 13.9644588492 - 13.9910381914 - 14.0176680014 - 14.044348375 - 14.0710794081 - 14.0978611969 - 14.1246938378 - 14.1515774274 - 14.1785120625 - 14.2054978398 - 14.2325348566 - 14.2596232101 - 14.2867629978 - 14.3139543174 - 14.3411972667 - 14.3684919437 - 14.3958384467 - 14.4232368741 - 14.4506873244 - 14.4781898965 - 14.5057446892 - 14.5333518019 - 14.5610113337 - 14.5887233843 - 14.6164880533 - 14.6443054406 - 14.6721756465 - 14.7000987711 - 14.7280749149 - 14.7561041786 - 14.7841866631 - 14.8123224694 - 14.8405116988 - 14.8687544527 - 14.8970508327 - 14.9254009406 - 14.9538048785 - 14.9822627486 - 15.0107746533 - 15.0393406952 - 15.067960977 - 15.0966356018 - 15.1253646728 - 15.1541482933 - 15.1829865669 - 15.2118795973 - 15.2408274886 - 15.269830345 - 15.2988882707 - 15.3280013703 - 15.3571697487 - 15.3863935107 - 15.4156727616 - 15.4450076066 - 15.4743981514 - 15.5038445017 - 15.5333467634 - 15.5629050428 - 15.5925194462 - 15.6221900801 - 15.6519170514 - 15.6817004669 - 15.711540434 - 15.7414370598 - 15.7713904522 - 15.8014007187 - 15.8314679674 - 15.8615923066 - 15.8917738445 - 15.9220126899 - 15.9523089514 - 15.9826627383 - 16.0130741596 - 16.0435433248 - 16.0740703435 - 16.1046553256 - 16.1352983812 - 16.1659996205 - 16.196759154 - 16.2275770924 - 16.2584535466 - 16.2893886276 - 16.3203824469 - 16.3514351159 - 16.3825467463 - 16.4137174502 - 16.4449473397 - 16.4762365272 - 16.5075851252 - 16.5389932466 - 16.5704610044 - 16.6019885119 - 16.6335758824 - 16.6652232296 - 16.6969306675 - 16.7286983101 - 16.7605262718 - 16.792414667 - 16.8243636105 - 16.8563732173 - 16.8884436026 - 16.9205748818 - 16.9527671704 - 16.9850205844 - 17.0173352398 - 17.0497112529 - 17.0821487401 - 17.1146478183 - 17.1472086043 - 17.1798312154 - 17.2125157688 - 17.2452623823 - 17.2780711737 - 17.3109422609 - 17.3438757624 - 17.3768717966 - 17.4099304823 - 17.4430519384 - 17.4762362841 - 17.5094836388 - 17.5427941221 - 17.576167854 - 17.6096049545 - 17.6431055439 - 17.6766697428 - 17.7102976719 - 17.7439894523 - 17.7777452053 - 17.8115650522 - 17.8454491148 - 17.8793975149 - 17.9134103749 - 17.947487817 - 17.9816299639 - 18.0158369385 - 18.0501088637 - 18.0844458631 - 18.11884806 - 18.1533155784 - 18.1878485423 - 18.2224470758 - 18.2571113035 - 18.2918413502 - 18.3266373409 - 18.3614994006 - 18.396427655 - 18.4314222296 - 18.4664832504 - 18.5016108436 - 18.5368051355 - 18.5720662529 - 18.6073943225 - 18.6427894716 - 18.6782518275 - 18.7137815177 - 18.7493786703 - 18.7850434131 - 18.8207758747 - 18.8565761835 - 18.8924444684 - 18.9283808585 - 18.964385483 - 19.0004584716 - 19.036599954 - 19.0728100604 - 19.1090889209 - 19.1454366662 - 19.181853427 - 19.2183393344 - 19.2548945196 - 19.2915191143 - 19.3282132502 - 19.3649770594 - 19.401810674 - 19.4387142268 - 19.4756878505 - 19.5127316781 - 19.5498458429 - 19.5870304785 - 19.6242857187 - 19.6616116976 - 19.6990085494 - 19.7364764088 - 19.7740154105 - 19.8116256897 - 19.8493073816 - 19.887060622 - 19.9248855466 - 19.9627822915 - 20.0007509931 - 20.0387917881 - 20.0769048133 - 20.1150902059 - 20.1533481033 - 20.1916786431 - 20.2300819633 - 20.2685582021 - 20.3071074979 - 20.3457299895 - 20.3844258158 - 20.4231951161 - 20.4620380298 - 20.5009546968 - 20.5399452572 - 20.5790098511 - 20.6181486192 - 20.6573617023 - 20.6966492416 - 20.7360113783 - 20.7754482542 - 20.8149600111 - 20.8545467912 - 20.894208737 - 20.9339459913 - 20.9737586969 - 21.0136469972 - 21.0536110357 - 21.0936509561 - 21.1337669027 - 21.1739590197 - 21.2142274518 -} diff --git a/release/datafiles/colormanagement/luts/slog10.spi1d b/release/datafiles/colormanagement/luts/slog10.spi1d deleted file mode 100644 index 7230f745c4f..00000000000 --- a/release/datafiles/colormanagement/luts/slog10.spi1d +++ /dev/null @@ -1,2054 +0,0 @@ -Version 1 -From -0.125 1.125 -Length 2048 -Components 1 -{ - -0.0248367707262 - -0.0248025947501 - -0.0247682888353 - -0.0247338524877 - -0.0246992852114 - -0.0246645865086 - -0.0246297558796 - -0.0245947928228 - -0.0245596968347 - -0.0245244674099 - -0.0244891040412 - -0.0244536062191 - -0.0244179734325 - -0.0243822051683 - -0.0243463009114 - -0.0243102601447 - -0.0242740823493 - -0.024237767004 - -0.024201313586 - -0.0241647215703 - -0.0241279904299 - -0.0240911196359 - -0.0240541086574 - -0.0240169569612 - -0.0239796640124 - -0.023942229274 - -0.0239046522069 - -0.0238669322698 - -0.0238290689197 - -0.0237910616113 - -0.0237529097972 - -0.023714612928 - -0.0236761704521 - -0.0236375818161 - -0.0235988464642 - -0.0235599638385 - -0.0235209333792 - -0.0234817545241 - -0.023442426709 - -0.0234029493676 - -0.0233633219315 - -0.0233235438298 - -0.0232836144898 - -0.0232435333365 - -0.0232032997926 - -0.0231629132788 - -0.0231223732135 - -0.0230816790128 - -0.0230408300908 - -0.0229998258591 - -0.0229586657273 - -0.0229173491026 - -0.0228758753901 - -0.0228342439924 - -0.0227924543101 - -0.0227505057414 - -0.0227083976821 - -0.0226661295258 - -0.022623700664 - -0.0225811104854 - -0.0225383583769 - -0.0224954437228 - -0.022452365905 - -0.0224091243032 - -0.0223657182947 - -0.0223221472544 - -0.0222784105548 - -0.0222345075662 - -0.0221904376561 - -0.0221462001901 - -0.022101794531 - -0.0220572200394 - -0.0220124760734 - -0.0219675619886 - -0.0219224771382 - -0.021877220873 - -0.0218317925411 - -0.0217861914886 - -0.0217404170585 - -0.0216944685918 - -0.0216483454267 - -0.0216020468991 - -0.0215555723421 - -0.0215089210866 - -0.0214620924607 - -0.02141508579 - -0.0213679003976 - -0.021320535604 - -0.0212729907271 - -0.0212252650822 - -0.021177357982 - -0.0211292687367 - -0.0210809966537 - -0.0210325410378 - -0.0209839011912 - -0.0209350764135 - -0.0208860660016 - -0.0208368692497 - -0.0207874854492 - -0.0207379138891 - -0.0206881538555 - -0.0206382046317 - -0.0205880654985 - -0.0205377357339 - -0.0204872146129 - -0.0204365014082 - -0.0203855953893 - -0.0203344958232 - -0.020283201974 - -0.020231713103 - -0.0201800284688 - -0.020128147327 - -0.0200760689306 - -0.0200237925295 - -0.0199713173709 - -0.0199186426992 - -0.0198657677557 - -0.0198126917791 - -0.019759414005 - -0.0197059336661 - -0.0196522499923 - -0.0195983622105 - -0.0195442695447 - -0.0194899712159 - -0.0194354664422 - -0.0193807544385 - -0.0193258344172 - -0.0192707055871 - -0.0192153671545 - -0.0191598183225 - -0.019104058291 - -0.0190480862571 - -0.0189919014147 - -0.0189355029548 - -0.0188788900651 - -0.0188220619304 - -0.0187650177323 - -0.0187077566494 - -0.0186502778569 - -0.0185925805272 - -0.0185346638294 - -0.0184765269295 - -0.0184181689901 - -0.018359589171 - -0.0183007866284 - -0.0182417605157 - -0.0181825099828 - -0.0181230341764 - -0.01806333224 - -0.0180034033139 - -0.017943246535 - -0.0178828610371 - -0.0178222459505 - -0.0177614004023 - -0.0177003235163 - -0.0176390144129 - -0.0175774722093 - -0.0175156960192 - -0.017453684953 - -0.0173914381175 - -0.0173289546165 - -0.0172662335502 - -0.0172032740152 - -0.0171400751049 - -0.0170766359092 - -0.0170129555146 - -0.0169490330039 - -0.0168848674567 - -0.0168204579488 - -0.0167558035528 - -0.0166909033376 - -0.0166257563685 - -0.0165603617074 - -0.0164947184126 - -0.0164288255387 - -0.0163626821368 - -0.0162962872543 - -0.0162296399353 - -0.0161627392198 - -0.0160955841445 - -0.0160281737422 - -0.0159605070423 - -0.0158925830701 - -0.0158244008477 - -0.0157559593931 - -0.0156872577206 - -0.015618294841 - -0.015549069761 - -0.0154795814839 - -0.0154098290089 - -0.0153398113315 - -0.0152695274434 - -0.0151989763324 - -0.0151281569827 - -0.0150570683742 - -0.0149857094833 - -0.0149140792824 - -0.0148421767399 - -0.0147700008203 - -0.0146975504843 - -0.0146248246885 - -0.0145518223857 - -0.0144785425244 - -0.0144049840495 - -0.0143311459015 - -0.0142570270173 - -0.0141826263294 - -0.0141079427664 - -0.0140329752527 - -0.0139577227088 - -0.013882184051 - -0.0138063581915 - -0.0137302440383 - -0.0136538404953 - -0.0135771464622 - -0.0135001608346 - -0.0134228825038 - -0.013345310357 - -0.013267443277 - -0.0131892801424 - -0.0131108198278 - -0.0130320612031 - -0.0129530031342 - -0.0128736444826 - -0.0127939841055 - -0.0127140208557 - -0.0126337535816 - -0.0125531811273 - -0.0124723023325 - -0.0123911160326 - -0.0123096210583 - -0.012227816236 - -0.0121457003878 - -0.012063272331 - -0.0119805308786 - -0.0118974748392 - -0.0118141030165 - -0.01173041421 - -0.0116464072145 - -0.0115620808202 - -0.0114774338128 - -0.0113924649732 - -0.0113071730779 - -0.0112215568986 - -0.0111356152023 - -0.0110493467514 - -0.0109627503035 - -0.0108758246117 - -0.010788568424 - -0.010700980484 - -0.0106130595303 - -0.0105248042967 - -0.0104362135123 - -0.0103472859014 - -0.0102580201833 - -0.0101684150724 - -0.0100784692785 - -0.00998818150621 - -0.0098975504553 - -0.00980657482063 - -0.00971525329208 - -0.00962358455452 - -0.00953156728787 - -0.009439200167 - -0.00934648186173 - -0.00925341103686 - -0.00915998635208 - -0.009066206462 - -0.00897207001611 - -0.00887757565878 - -0.00878272202919 - -0.00868750776139 - -0.00859193148421 - -0.00849599182126 - -0.00839968739095 - -0.0083030168064 - -0.00820597867548 - -0.00810857160076 - -0.00801079417949 - -0.0079126450036 - -0.00781412265967 - -0.00771522572888 - -0.00761595278705 - -0.00751630240454 - -0.00741627314633 - -0.0073158635719 - -0.00721507223528 - -0.00711389768498 - -0.00701233846401 - -0.00691039310982 - -0.00680806015433 - -0.00670533812385 - -0.0066022255391 - -0.00649872091518 - -0.00639482276152 - -0.00629052958192 - -0.00618583987446 - -0.00608075213152 - -0.00597526483976 - -0.00586937648007 - -0.00576308552757 - -0.00565639045157 - -0.0055492897156 - -0.00544178177729 - -0.00533386508846 - -0.005225538095 - -0.00511679923693 - -0.00500764694831 - -0.00489807965726 - -0.00478809578592 - -0.00467769375043 - -0.00456687196091 - -0.00445562882143 - -0.00434396273001 - -0.00423187207854 - -0.00411935525285 - -0.00400641063258 - -0.00389303659125 - -0.00377923149618 - -0.00366499370847 - -0.00355032158302 - -0.00343521346843 - -0.00331966770707 - -0.00320368263498 - -0.00308725658187 - -0.00297038787112 - -0.00285307481972 - -0.00273531573825 - -0.00261710893091 - -0.0024984526954 - -0.00237934532298 - -0.0022597850984 - -0.00213977029991 - -0.00201929919918 - -0.00189837006133 - -0.00177698114489 - -0.00165513070174 - -0.00153281697715 - -0.0014100382097 - -0.00128679263126 - -0.00116307846701 - -0.00103889393534 - -0.000914237247911 - -0.000789106609554 - -0.000663500218286 - -0.000537416265269 - -0.000410852934791 - -0.000283808404235 - -0.000156280844053 - -2.82684177441e-05 - 0.000100230718178 - 0.000229218414207 - 0.000358696527872 - 0.000488666923767 - 0.000619131473572 - 0.000750092056085 - 0.000881550557248 - 0.00101350887017 - 0.00114596889517 - 0.00127893253976 - 0.00141240171875 - 0.0015463783542 - 0.00168086437548 - 0.0018158617193 - 0.00195137232974 - 0.00208739815826 - 0.00222394116375 - 0.00236100331253 - 0.00249858657843 - 0.00263669294275 - 0.00277532439433 - 0.00291448292959 - 0.00305417055252 - 0.00319438927474 - 0.00333514111552 - 0.0034764281018 - 0.00361825226823 - 0.00376061565719 - 0.00390352031885 - 0.00404696831113 - 0.00419096169982 - 0.00433550255853 - 0.00448059296878 - 0.00462623501999 - 0.00477243080952 - 0.00491918244271 - 0.00506649203292 - 0.00521436170151 - 0.00536279357794 - 0.00551178979975 - 0.0056613525126 - 0.00581148387033 - 0.00596218603495 - 0.0061134611767 - 0.00626531147406 - 0.0064177391138 - 0.00657074629101 - 0.00672433520913 - 0.00687850807995 - 0.00703326712369 - 0.00718861456901 - 0.00734455265306 - 0.00750108362145 - 0.00765820972837 - 0.00781593323657 - 0.00797425641739 - 0.00813318155082 - 0.00829271092551 - 0.00845284683882 - 0.00861359159684 - 0.00877494751443 - 0.00893691691524 - 0.00909950213177 - 0.00926270550538 - 0.00942652938634 - 0.00959097613384 - 0.00975604811606 - 0.00992174771016 - 0.0100880773024 - 0.0102550392879 - 0.0104226360713 - 0.010590870066 - 0.0107597436947 - 0.0109292593893 - 0.011099419591 - 0.0112702267503 - 0.0114416833269 - 0.0116137917899 - 0.0117865546179 - 0.0119599742987 - 0.0121340533298 - 0.012308794218 - 0.0124841994798 - 0.0126602716411 - 0.0128370132375 - 0.0130144268143 - 0.0131925149263 - 0.0133712801381 - 0.0135507250242 - 0.0137308521687 - 0.0139116641655 - 0.0140931636186 - 0.0142753531416 - 0.0144582353582 - 0.0146418129021 - 0.014826088417 - 0.0150110645565 - 0.0151967439845 - 0.015383129375 - 0.0155702234119 - 0.0157580287897 - 0.0159465482129 - 0.0161357843963 - 0.0163257400651 - 0.0165164179548 - 0.0167078208114 - 0.0168999513911 - 0.0170928124608 - 0.0172864067979 - 0.0174807371903 - 0.0176758064365 - 0.0178716173458 - 0.0180681727378 - 0.0182654754432 - 0.0184635283033 - 0.0186623341702 - 0.0188618959069 - 0.0190622163873 - 0.0192632984961 - 0.0194651451291 - 0.019667759193 - 0.0198711436057 - 0.020075301296 - 0.0202802352041 - 0.020485948281 - 0.0206924434893 - 0.0208997238026 - 0.021107792206 - 0.0213166516959 - 0.0215263052798 - 0.0217367559772 - 0.0219480068186 - 0.0221600608461 - 0.0223729211137 - 0.0225865906866 - 0.0228010726418 - 0.023016370068 - 0.0232324860658 - 0.0234494237474 - 0.0236671862368 - 0.0238857766701 - 0.024105198195 - 0.0243254539715 - 0.0245465471715 - 0.0247684809787 - 0.0249912585894 - 0.0252148832116 - 0.0254393580657 - 0.0256646863844 - 0.0258908714126 - 0.0261179164075 - 0.0263458246387 - 0.0265745993884 - 0.0268042439511 - 0.0270347616338 - 0.0272661557563 - 0.0274984296507 - 0.027731586662 - 0.0279656301478 - 0.0282005634786 - 0.0284363900377 - 0.028673113221 - 0.0289107364377 - 0.0291492631096 - 0.0293886966718 - 0.0296290405724 - 0.0298702982724 - 0.0301124732462 - 0.0303555689812 - 0.0305995889784 - 0.0308445367517 - 0.0310904158287 - 0.0313372297501 - 0.0315849820703 - 0.0318336763572 - 0.0320833161921 - 0.0323339051701 - 0.0325854468999 - 0.0328379450038 - 0.0330914031181 - 0.0333458248927 - 0.0336012139916 - 0.0338575740925 - 0.0341149088873 - 0.0343732220818 - 0.0346325173959 - 0.0348927985637 - 0.0351540693334 - 0.0354163334676 - 0.0356795947431 - 0.035943856951 - 0.036209123897 - 0.0364753994012 - 0.036742687298 - 0.0370109914367 - 0.0372803156811 - 0.0375506639097 - 0.0378220400157 - 0.0380944479072 - 0.038367891507 - 0.0386423747529 - 0.0389179015979 - 0.0391944760096 - 0.0394721019709 - 0.03975078348 - 0.04003052455 - 0.0403113292096 - 0.0405932015023 - 0.0408761454876 - 0.04116016524 - 0.0414452648496 - 0.0417314484221 - 0.0420187200788 - 0.0423070839566 - 0.0425965442082 - 0.0428871050021 - 0.0431787705226 - 0.0434715449699 - 0.0437654325602 - 0.0440604375258 - 0.0443565641149 - 0.044653816592 - 0.0449521992378 - 0.0452517163493 - 0.0455523722398 - 0.0458541712389 - 0.0461571176928 - 0.0464612159642 - 0.0467664704324 - 0.0470728854932 - 0.0473804655594 - 0.0476892150602 - 0.047999138442 - 0.0483102401679 - 0.0486225247181 - 0.0489359965896 - 0.0492506602969 - 0.0495665203711 - 0.0498835813611 - 0.0502018478328 - 0.0505213243694 - 0.0508420155716 - 0.0511639260578 - 0.0514870604637 - 0.0518114234427 - 0.0521370196658 - 0.052463853822 - 0.0527919306179 - 0.053121254778 - 0.0534518310451 - 0.0537836641795 - 0.0541167589601 - 0.0544511201835 - 0.054786752665 - 0.0551236612378 - 0.0554618507538 - 0.0558013260832 - 0.0561420921146 - 0.0564841537555 - 0.0568275159317 - 0.057172183588 - 0.0575181616879 - 0.0578654552137 - 0.0582140691668 - 0.0585640085675 - 0.0589152784552 - 0.0592678838885 - 0.0596218299451 - 0.0599771217223 - 0.0603337643365 - 0.0606917629237 - 0.0610511226393 - 0.0614118486584 - 0.0617739461758 - 0.0621374204059 - 0.0625022765832 - 0.0628685199618 - 0.0632361558159 - 0.0636051894399 - 0.063975626148 - 0.0643474712749 - 0.0647207301755 - 0.065095408225 - 0.0654715108191 - 0.065849043374 - 0.0662280113264 - 0.0666084201338 - 0.0669902752745 - 0.0673735822473 - 0.0677583465724 - 0.0681445737905 - 0.0685322694638 - 0.0689214391753 - 0.0693120885294 - 0.0697042231517 - 0.0700978486894 - 0.070492970811 - 0.0708895952066 - 0.0712877275878 - 0.0716873736881 - 0.0720885392628 - 0.072491230089 - 0.0728954519657 - 0.0733012107141 - 0.0737085121775 - 0.0741173622213 - 0.0745277667332 - 0.0749397316236 - 0.075353262825 - 0.0757683662925 - 0.0761850480041 - 0.0766033139603 - 0.0770231701844 - 0.0774446227228 - 0.0778676776448 - 0.0782923410425 - 0.0787186190317 - 0.079146517751 - 0.0795760433624 - 0.0800072020517 - 0.0804400000277 - 0.0808744435231 - 0.0813105387943 - 0.0817482921215 - 0.0821877098085 - 0.0826287981835 - 0.0830715635984 - 0.0835160124294 - 0.083962151077 - 0.084409985966 - 0.0848595235455 - 0.0853107702892 - 0.0857637326954 - 0.0862184172873 - 0.0866748306126 - 0.0871329792441 - 0.0875928697794 - 0.0880545088415 - 0.0885179030782 - 0.0889830591629 - 0.0894499837942 - 0.0899186836961 - 0.0903891656183 - 0.0908614363363 - 0.091335502651 - 0.0918113713894 - 0.0922890494044 - 0.092768543575 - 0.0932498608063 - 0.0937330080296 - 0.0942179922028 - 0.0947048203098 - 0.0951934993616 - 0.0956840363954 - 0.0961764384754 - 0.0966707126927 - 0.0971668661651 - 0.0976649060376 - 0.0981648394826 - 0.0986666736993 - 0.0991704159148 - 0.0996760733831 - 0.100183653386 - 0.100693163234 - 0.101204610263 - 0.10171800184 - 0.102233345357 - 0.102750648235 - 0.103269917925 - 0.103791161904 - 0.104314387678 - 0.104839602783 - 0.105366814782 - 0.105896031267 - 0.10642725986 - 0.10696050821 - 0.107495783997 - 0.108033094929 - 0.108572448744 - 0.109113853209 - 0.10965731612 - 0.110202845305 - 0.110750448619 - 0.111300133947 - 0.111851909207 - 0.112405782344 - 0.112961761334 - 0.113519854183 - 0.11408006893 - 0.114642413641 - 0.115206896414 - 0.115773525379 - 0.116342308696 - 0.116913254555 - 0.117486371178 - 0.11806166682 - 0.118639149764 - 0.119218828327 - 0.119800710856 - 0.120384805732 - 0.120971121366 - 0.121559666201 - 0.122150448713 - 0.122743477409 - 0.12333876083 - 0.123936307548 - 0.124536126168 - 0.125138225329 - 0.1257426137 - 0.126349299986 - 0.126958292924 - 0.127569601283 - 0.128183233867 - 0.128799199513 - 0.12941750709 - 0.130038165504 - 0.130661183692 - 0.131286570626 - 0.131914335312 - 0.132544486791 - 0.133177034137 - 0.133811986459 - 0.134449352902 - 0.135089142644 - 0.135731364898 - 0.136376028913 - 0.137023143973 - 0.137672719396 - 0.138324764538 - 0.138979288787 - 0.139636301571 - 0.140295812349 - 0.140957830621 - 0.141622365919 - 0.142289427813 - 0.142959025909 - 0.143631169851 - 0.144305869318 - 0.144983134025 - 0.145662973727 - 0.146345398213 - 0.14703041731 - 0.147718040885 - 0.148408278838 - 0.149101141111 - 0.14979663768 - 0.150494778562 - 0.151195573811 - 0.151899033517 - 0.152605167813 - 0.153313986866 - 0.154025500884 - 0.154739720115 - 0.155456654842 - 0.156176315391 - 0.156898712125 - 0.157623855447 - 0.1583517558 - 0.159082423667 - 0.159815869569 - 0.160552104069 - 0.161291137769 - 0.162032981312 - 0.162777645381 - 0.1635251407 - 0.164275478034 - 0.165028668187 - 0.165784722006 - 0.16654365038 - 0.167305464238 - 0.168070174549 - 0.168837792327 - 0.169608328626 - 0.170381794543 - 0.171158201215 - 0.171937559824 - 0.172719881594 - 0.173505177789 - 0.17429345972 - 0.175084738738 - 0.175879026238 - 0.176676333659 - 0.177476672482 - 0.178280054233 - 0.179086490482 - 0.179895992841 - 0.180708572969 - 0.181524242566 - 0.18234301338 - 0.183164897201 - 0.183989905866 - 0.184818051255 - 0.185649345293 - 0.186483799953 - 0.187321427251 - 0.188162239249 - 0.189006248057 - 0.189853465828 - 0.190703904763 - 0.191557577109 - 0.19241449516 - 0.193274671257 - 0.194138117785 - 0.19500484718 - 0.195874871923 - 0.196748204544 - 0.197624857619 - 0.198504843772 - 0.199388175677 - 0.200274866053 - 0.20116492767 - 0.202058373346 - 0.202955215947 - 0.203855468388 - 0.204759143633 - 0.205666254697 - 0.206576814642 - 0.207490836581 - 0.208408333677 - 0.209329319143 - 0.210253806241 - 0.211181808285 - 0.21211333864 - 0.213048410719 - 0.213987037988 - 0.214929233965 - 0.215875012218 - 0.216824386367 - 0.217777370084 - 0.218733977092 - 0.219694221168 - 0.220658116139 - 0.221625675887 - 0.222596914346 - 0.223571845501 - 0.224550483393 - 0.225532842115 - 0.226518935813 - 0.227508778689 - 0.228502384997 - 0.229499769046 - 0.230500945198 - 0.231505927872 - 0.23251473154 - 0.233527370729 - 0.234543860023 - 0.23556421406 - 0.236588447534 - 0.237616575195 - 0.238648611848 - 0.239684572355 - 0.240724471636 - 0.241768324666 - 0.242816146477 - 0.243867952159 - 0.244923756858 - 0.245983575779 - 0.247047424184 - 0.248115317394 - 0.249187270788 - 0.250263299801 - 0.25134341993 - 0.252427646729 - 0.253515995813 - 0.254608482854 - 0.255705123585 - 0.256805933799 - 0.257910929348 - 0.259020126145 - 0.260133540163 - 0.261251187437 - 0.262373084062 - 0.263499246193 - 0.264629690048 - 0.265764431908 - 0.266903488112 - 0.268046875065 - 0.269194609232 - 0.270346707141 - 0.271503185384 - 0.272664060614 - 0.27382934955 - 0.274999068973 - 0.276173235727 - 0.277351866721 - 0.278534978929 - 0.279722589388 - 0.280914715202 - 0.282111373537 - 0.283312581627 - 0.284518356769 - 0.285728716329 - 0.286943677736 - 0.288163258486 - 0.289387476144 - 0.290616348337 - 0.291849892764 - 0.293088127188 - 0.294331069442 - 0.295578737423 - 0.2968311491 - 0.298088322509 - 0.299350275753 - 0.300617027006 - 0.301888594511 - 0.303164996579 - 0.30444625159 - 0.305732377998 - 0.307023394321 - 0.308319319153 - 0.309620171156 - 0.310925969062 - 0.312236731677 - 0.313552477877 - 0.31487322661 - 0.316198996895 - 0.317529807824 - 0.318865678563 - 0.320206628348 - 0.321552676492 - 0.322903842377 - 0.324260145463 - 0.32562160528 - 0.326988241435 - 0.328360073609 - 0.329737121557 - 0.33111940511 - 0.332506944173 - 0.333899758729 - 0.335297868836 - 0.336701294626 - 0.338110056311 - 0.339524174179 - 0.340943668592 - 0.342368559994 - 0.343798868904 - 0.34523461592 - 0.346675821717 - 0.348122507051 - 0.349574692754 - 0.351032399739 - 0.352495648999 - 0.353964461605 - 0.35543885871 - 0.356918861546 - 0.358404491426 - 0.359895769745 - 0.361392717979 - 0.362895357684 - 0.3644037105 - 0.365917798148 - 0.367437642433 - 0.368963265242 - 0.370494688544 - 0.372031934394 - 0.373575024929 - 0.375123982371 - 0.376678829026 - 0.378239587286 - 0.379806279626 - 0.381378928609 - 0.382957556881 - 0.384542187176 - 0.386132842315 - 0.387729545203 - 0.389332318835 - 0.390941186293 - 0.392556170744 - 0.394177295447 - 0.395804583746 - 0.397438059077 - 0.399077744962 - 0.400723665014 - 0.402375842936 - 0.404034302521 - 0.405699067652 - 0.407370162303 - 0.409047610538 - 0.410731436515 - 0.412421664483 - 0.414118318781 - 0.415821423843 - 0.417531004195 - 0.419247084457 - 0.420969689341 - 0.422698843655 - 0.4244345723 - 0.426176900271 - 0.42792585266 - 0.429681454653 - 0.431443731531 - 0.433212708675 - 0.434988411557 - 0.43677086575 - 0.438560096923 - 0.440356130841 - 0.44215899337 - 0.443968710472 - 0.445785308208 - 0.447608812739 - 0.449439250326 - 0.451276647326 - 0.453121030202 - 0.454972425513 - 0.456830859922 - 0.45869636019 - 0.460568953183 - 0.462448665868 - 0.464335525314 - 0.466229558693 - 0.468130793282 - 0.470039256459 - 0.471954975708 - 0.473877978617 - 0.475808292878 - 0.477745946291 - 0.479690966758 - 0.481643382289 - 0.483603221002 - 0.485570511119 - 0.487545280971 - 0.489527558996 - 0.49151737374 - 0.49351475386 - 0.495519728118 - 0.497532325387 - 0.499552574652 - 0.501580505005 - 0.50361614565 - 0.505659525902 - 0.507710675187 - 0.509769623044 - 0.511836399123 - 0.513911033188 - 0.515993555114 - 0.518083994893 - 0.520182382627 - 0.522288748536 - 0.524403122953 - 0.526525536327 - 0.528656019222 - 0.530794602319 - 0.532941316415 - 0.535096192425 - 0.537259261381 - 0.539430554432 - 0.541610102848 - 0.543797938015 - 0.545994091441 - 0.548198594751 - 0.550411479692 - 0.552632778132 - 0.554862522059 - 0.557100743583 - 0.559347474937 - 0.561602748475 - 0.563866596676 - 0.56613905214 - 0.568420147592 - 0.570709915883 - 0.573008389987 - 0.575315603004 - 0.57763158816 - 0.579956378806 - 0.582290008422 - 0.584632510614 - 0.586983919115 - 0.589344267789 - 0.591713590626 - 0.594091921746 - 0.5964792954 - 0.598875745966 - 0.601281307958 - 0.603696016015 - 0.606119904913 - 0.608553009556 - 0.610995364985 - 0.61344700637 - 0.615907969018 - 0.618378288369 - 0.620857999996 - 0.62334713961 - 0.625845743057 - 0.628353846319 - 0.630871485514 - 0.633398696898 - 0.635935516866 - 0.63848198195 - 0.64103812882 - 0.643603994288 - 0.646179615305 - 0.64876502896 - 0.651360272487 - 0.653965383258 - 0.656580398791 - 0.659205356742 - 0.661840294915 - 0.664485251253 - 0.667140263847 - 0.669805370931 - 0.672480610884 - 0.675166022233 - 0.67786164365 - 0.680567513953 - 0.68328367211 - 0.686010157235 - 0.688747008592 - 0.691494265594 - 0.694251967804 - 0.697020154935 - 0.699798866851 - 0.702588143568 - 0.705388025254 - 0.70819855223 - 0.711019764968 - 0.713851704098 - 0.716694410402 - 0.719547924816 - 0.722412288434 - 0.725287542504 - 0.728173728434 - 0.731070887787 - 0.733979062283 - 0.736898293803 - 0.739828624387 - 0.742770096234 - 0.745722751702 - 0.748686633314 - 0.751661783751 - 0.754648245858 - 0.757646062643 - 0.760655277276 - 0.763675933093 - 0.766708073593 - 0.769751742443 - 0.772806983472 - 0.775873840681 - 0.778952358233 - 0.782042580461 - 0.785144551869 - 0.788258317126 - 0.791383921073 - 0.794521408722 - 0.797670825256 - 0.800832216027 - 0.804005626564 - 0.807191102565 - 0.810388689904 - 0.81359843463 - 0.816820382965 - 0.820054581307 - 0.823301076233 - 0.826559914494 - 0.82983114302 - 0.833114808919 - 0.83641095948 - 0.839719642169 - 0.843040904634 - 0.846374794704 - 0.84972136039 - 0.853080649886 - 0.856452711567 - 0.859837593994 - 0.863235345913 - 0.866646016254 - 0.870069654133 - 0.873506308853 - 0.876956029906 - 0.880418866969 - 0.883894869912 - 0.88738408879 - 0.890886573853 - 0.894402375537 - 0.897931544475 - 0.901474131488 - 0.905030187594 - 0.908599764002 - 0.912182912117 - 0.915779683539 - 0.919390130065 - 0.923014303688 - 0.9266522566 - 0.93030404119 - 0.933969710046 - 0.937649315958 - 0.941342911914 - 0.945050551106 - 0.948772286927 - 0.952508172972 - 0.956258263042 - 0.960022611141 - 0.963801271479 - 0.967594298471 - 0.971401746741 - 0.975223671118 - 0.979060126642 - 0.98291116856 - 0.986776852332 - 0.990657233625 - 0.994552368322 - 0.998462312514 - 1.00238712251 - 1.00632685483 - 1.0102815662 - 1.01425131359 - 1.01823615415 - 1.02223614527 - 1.02625134456 - 1.03028180984 - 1.03432759914 - 1.03838877074 - 1.04246538312 - 1.04655749498 - 1.05066516525 - 1.05478845308 - 1.05892741787 - 1.0630821192 - 1.06725261691 - 1.07143897107 - 1.07564124195 - 1.07985949007 - 1.08409377618 - 1.08834416126 - 1.09261070652 - 1.09689347339 - 1.10119252355 - 1.10550791892 - 1.10983972164 - 1.11418799408 - 1.11855279887 - 1.12293419887 - 1.12733225717 - 1.1317470371 - 1.13617860225 - 1.14062701643 - 1.1450923437 - 1.14957464837 - 1.15407399498 - 1.15859044833 - 1.16312407346 - 1.16767493567 - 1.17224310047 - 1.17682863367 - 1.18143160129 - 1.18605206962 - 1.1906901052 - 1.19534577482 - 1.20001914554 - 1.20471028464 - 1.20941925968 - 1.21414613848 - 1.21889098911 - 1.2236538799 - 1.22843487944 - 1.23323405657 - 1.23805148041 - 1.24288722034 - 1.247741346 - 1.25261392728 - 1.25750503435 - 1.26241473766 - 1.26734310791 - 1.27229021606 - 1.27725613337 - 1.28224093134 - 1.28724468176 - 1.29226745668 - 1.29730932845 - 1.30237036967 - 1.30745065321 - 1.31255025225 - 1.31766924022 - 1.32280769083 - 1.32796567809 - 1.33314327627 - 1.33834055993 - 1.34355760393 - 1.34879448339 - 1.35405127373 - 1.35932805064 - 1.36462489012 - 1.36994186845 - 1.3752790622 - 1.38063654822 - 1.38601440367 - 1.39141270599 - 1.39683153293 - 1.40227096252 - 1.40773107309 - 1.41321194327 - 1.41871365199 - 1.42423627848 - 1.42977990228 - 1.4353446032 - 1.4409304614 - 1.44653755731 - 1.45216597167 - 1.45781578555 - 1.4634870803 - 1.46917993759 - 1.47489443941 - 1.48063066805 - 1.48638870612 - 1.49216863654 - 1.49797054253 - 1.50379450767 - 1.5096406158 - 1.51550895114 - 1.52139959817 - 1.52731264174 - 1.53324816699 - 1.53920625941 - 1.54518700479 - 1.55119048926 - 1.55721679928 - 1.56326602163 - 1.56933824342 - 1.5754335521 - 1.58155203545 - 1.58769378158 - 1.59385887893 - 1.60004741629 - 1.60625948277 - 1.61249516784 - 1.6187545613 - 1.62503775328 - 1.63134483427 - 1.63767589509 - 1.64403102692 - 1.65041032129 - 1.65681387004 - 1.66324176541 - 1.66969409995 - 1.67617096659 - 1.6826724586 - 1.68919866961 - 1.69574969359 - 1.70232562489 - 1.70892655822 - 1.71555258862 - 1.72220381151 - 1.72888032269 - 1.73558221829 - 1.74230959484 - 1.7490625492 - 1.75584117863 - 1.76264558075 - 1.76947585355 - 1.77633209538 - 1.78321440498 - 1.79012288147 - 1.79705762433 - 1.80401873342 - 1.811006309 - 1.81802045169 - 1.8250612625 - 1.83212884282 - 1.83922329444 - 1.84634471951 - 1.85349322059 - 1.86066890063 - 1.86787186296 - 1.87510221132 - 1.88236004982 - 1.88964548298 - 1.89695861572 - 1.90429955335 - 1.9116684016 - 1.91906526657 - 1.92649025479 - 1.93394347319 - 1.94142502909 - 1.94893503024 - 1.95647358479 - 1.9640408013 - 1.97163678874 - 1.9792616565 - 1.98691551439 - 1.99459847263 - 2.00231064186 - 2.01005213314 - 2.01782305795 - 2.02562352821 - 2.03345365624 - 2.04131355481 - 2.0492033371 - 2.05712311674 - 2.06507300778 - 2.07305312469 - 2.08106358241 - 2.08910449629 - 2.09717598212 - 2.10527815614 - 2.11341113503 - 2.12157503591 - 2.12976997635 - 2.13799607436 - 2.1462534484 - 2.15454221739 - 2.1628625007 - 2.17121441813 - 2.17959808997 - 2.18801363694 - 2.19646118025 - 2.20494084153 - 2.21345274291 - 2.22199700696 - 2.23057375673 - 2.23918311572 - 2.24782520793 - 2.2565001578 - 2.26520809027 - 2.27394913072 - 2.28272340505 - 2.2915310396 - 2.30037216122 - 2.30924689722 - 2.31815537541 - 2.32709772408 - 2.336074072 - 2.34508454845 - 2.35412928317 - 2.36320840642 - 2.37232204896 - 2.38147034201 - 2.39065341733 - 2.39987140716 - 2.40912444425 - 2.41841266184 - 2.4277361937 - 2.43709517409 - 2.44648973779 - 2.45592002008 - 2.46538615678 - 2.47488828421 - 2.48442653919 - 2.49400105909 - 2.5036119818 - 2.51325944571 - 2.52294358976 - 2.5326645534 - 2.54242247664 - 2.55221749998 - 2.56204976449 - 2.57191941175 - 2.58182658391 - 2.59177142363 - 2.60175407412 - 2.61177467915 - 2.62183338302 - 2.63193033058 - 2.64206566723 - 2.65223953894 - 2.66245209222 - 2.67270347413 - 2.68299383231 - 2.69332331494 - 2.70369207077 - 2.71410024914 - 2.72454799991 - 2.73503547355 - 2.74556282109 - 2.75613019413 - 2.76673774484 - 2.77738562599 - 2.78807399092 - 2.79880299354 - 2.80957278836 - 2.82038353048 - 2.83123537557 - 2.84212847993 - 2.8530630004 - 2.86403909447 - 2.87505692019 - 2.88611663623 - 2.89721840187 - 2.90836237697 - 2.91954872202 - 2.9307775981 - 2.94204916694 - 2.95336359084 - 2.96472103274 - 2.9761216562 - 2.9875656254 - 2.99905310513 - 3.01058426084 - 3.02215925858 - 3.03377826503 - 3.04544144752 - 3.05714897401 - 3.0689010131 - 3.08069773403 - 3.09253930668 - 3.10442590157 - 3.1163576899 - 3.12833484347 - 3.14035753478 - 3.15242593696 - 3.1645402238 - 3.17670056976 - 3.18890714997 - 3.2011601402 - 3.21345971691 - 3.22580605722 - 3.23819933893 - 3.25063974051 - 3.26312744112 - 3.27566262059 - 3.28824545944 - 3.30087613886 - 3.31355484076 - 3.32628174771 - 3.33905704299 - 3.35188091058 - 3.36475353516 - 3.37767510209 - 3.39064579747 - 3.40366580807 - 3.4167353214 - 3.42985452567 - 3.44302360981 - 3.45624276346 - 3.46951217699 - 3.4828320415 - 3.49620254878 - 3.50962389141 - 3.52309626264 - 3.5366198565 - 3.55019486774 - 3.56382149185 - 3.57749992505 - 3.59123036434 - 3.60501300745 - 3.61884805285 - 3.63273569978 - 3.64667614823 - 3.66066959897 - 3.6747162535 - 3.6888163141 - 3.70296998384 - 3.71717746654 - 3.73143896679 - 3.74575468998 - 3.76012484226 - 3.77454963057 - 3.78902926264 - 3.803563947 - 3.81815389294 - 3.83279931059 - 3.84750041085 - 3.86225740542 - 3.87707050681 - 3.89193992836 - 3.90686588419 - 3.92184858924 - 3.93688825928 - 3.9519851109 - 3.96713936149 - 3.9823512293 - 3.99762093339 - 4.01294869366 - 4.02833473083 - 4.04377926648 - 4.05928252302 - 4.07484472372 - 4.09046609267 - 4.10614685485 - 4.12188723607 - 4.137687463 - 4.15354776317 - 4.169468365 - 4.18544949775 - 4.20149139156 - 4.21759427744 - 4.2337583873 - 4.24998395392 - 4.26627121094 - 4.28262039292 - 4.29903173531 - 4.31550547443 - 4.33204184754 - 4.34864109275 - 4.36530344912 - 4.3820291566 - 4.39881845605 - 4.41567158926 - 4.43258879891 - 4.44957032863 - 4.46661642298 - 4.48372732743 - 4.50090328838 - 4.5181445532 - 4.53545137016 - 4.55282398849 - 4.57026265839 - 4.58776763098 - 4.60533915835 - 4.62297749353 - 4.64068289055 - 4.65845560436 - 4.67629589092 - 4.69420400713 - 4.71218021089 - 4.73022476107 - 4.74833791754 - 4.76651994112 - 4.78477109366 - 4.80309163799 - 4.82148183794 - 4.83994195834 - 4.85847226505 - 4.8770730249 - 4.89574450576 - 4.91448697652 - 4.93330070709 - 4.9521859684 - 4.97114303241 - 4.99017217213 - 5.00927366157 - 5.02844777584 - 5.04769479103 - 5.06701498434 - 5.08640863398 - 5.10587601925 - 5.12541742048 - 5.14503311909 - 5.16472339756 - 5.18448853945 - 5.20432882939 - 5.2242445531 - 5.24423599739 - 5.26430345014 - 5.28444720034 - 5.30466753809 - 5.32496475456 - 5.34533914206 - 5.365790994 - 5.38632060489 - 5.40692827039 - 5.42761428725 - 5.44837895338 - 5.46922256781 - 5.49014543069 - 5.51114784334 - 5.5322301082 - 5.55339252889 - 5.57463541015 - 5.5959590579 - 5.61736377923 - 5.63884988236 - 5.66041767673 - 5.68206747293 - 5.70379958273 - 5.72561431909 - 5.74751199617 - 5.7694929293 - 5.79155743504 - 5.81370583112 - 5.83593843651 - 5.85825557136 - 5.88065755708 - 5.90314471626 - 5.92571737273 - 5.94837585157 - 5.97112047908 - 5.99395158278 - 6.01686949148 - 6.03987453521 - 6.06296704526 - 6.08614735419 - 6.1094157958 - 6.13277270518 - 6.15621841869 - 6.17975327397 - 6.20337760995 - 6.22709176682 - 6.2508960861 - 6.27479091058 - 6.29877658438 - 6.3228534529 - 6.34702186287 - 6.37128216234 - 6.39563470067 - 6.42007982857 - 6.44461789805 - 6.4692492625 - 6.49397427663 - 6.51879329648 - 6.54370667949 - 6.56871478441 - 6.5938179714 - 6.61901660195 - 6.64431103894 - 6.66970164665 - 6.69518879071 - 6.72077283815 - 6.74645415742 - 6.77223311835 - 6.79811009216 - 6.82408545152 - 6.85015957048 - 6.87633282454 - 6.90260559062 - 6.92897824706 - 6.95545117365 - 6.98202475162 - 7.00869936366 - 7.0354753939 - 7.06235322794 - 7.08933325285 - 7.11641585715 - 7.14360143085 - 7.17089036547 - 7.19828305396 - 7.22577989083 - 7.25338127203 - 7.28108759506 - 7.30889925891 - 7.33681666409 - 7.36484021263 - 7.39297030809 - 7.42120735558 - 7.44955176173 - 7.47800393472 - 7.50656428428 - 7.53523322172 - 7.56401115988 - 7.5928985132 - 7.62189569767 - 7.65100313087 - 7.68022123199 - 7.70955042178 - 7.73899112261 - 7.76854375845 - 7.79820875488 - 7.8279865391 - 7.85787753993 - 7.88788218784 - 7.91800091492 - 7.94823415489 - 7.97858234315 - 8.00904591672 - 8.03962531432 - 8.07032097631 - 8.10113334474 - 8.13206286332 - 8.16310997747 - 8.19427513429 - 8.22555878258 - 8.25696137287 - 8.28848335737 - 8.32012519001 - 8.35188732648 - 8.38377022418 - 8.41577434223 - 8.44790014154 - 8.48014808473 - 8.51251863621 - 8.54501226213 - 8.57762943044 - 8.61037061084 - 8.64323627484 - 8.67622689573 - 8.7093429486 - 8.74258491035 - 8.77595325969 - 8.80944847715 - 8.8430710451 - 8.87682144773 - 8.91070017106 - 8.94470770299 - 8.97884453324 - 9.01311115343 - 9.047508057 - 9.08203573932 - 9.1166946976 - 9.15148543096 - 9.18640844042 - 9.2214642289 - 9.25665330124 - 9.29197616417 - 9.32743332639 - 9.36302529851 - 9.39875259307 - 9.43461572458 - 9.4706152095 - 9.50675156626 - 9.54302531524 - 9.57943697882 - 9.61598708136 - 9.6526761492 - 9.68950471071 - 9.72647329623 - 9.76358243816 - 9.80083267089 - 9.83822453086 - 9.87575855655 - 9.91343528846 - 9.95125526919 - 9.98921904336 - 10.0273271577 - 10.065580161 - 10.1039786041 - 10.1425230399 - 10.1812140237 - 10.2200521125 - 10.2590378656 - 10.2981718446 - 10.3374546128 - 10.3768867361 - 10.4164687823 - 10.4562013214 - 10.4960849255 - 10.5361201692 - 10.5763076288 - 10.6166478831 - 10.6571415131 - 10.6977891019 - 10.7385912348 - 10.7795484995 - 10.8206614858 - 10.8619307856 - 10.9033569934 - 10.9449407057 - 10.9866825213 - 11.0285830414 - 11.0706428694 - 11.1128626109 - 11.1552428739 - 11.1977842689 - 11.2404874083 - 11.2833529072 - 11.3263813829 - 11.3695734549 - 11.4129297454 - 11.4564508786 - 11.5001374814 - 11.5439901828 - 11.5880096143 - 11.6321964099 - 11.676551206 - 11.7210746411 - 11.7657673566 - 11.810629996 - 11.8556632053 - 11.9008676332 - 11.9462439306 - 11.9917927509 - 12.0375147501 - 12.0834105866 - 12.1294809213 - 12.1757264178 - 12.2221477419 - 12.2687455622 - 12.3155205498 - 12.3624733782 - 12.4096047235 - 12.4569152646 - 12.5044056827 - 12.5520766618 - 12.5999288883 - 12.6479630513 - 12.6961798426 - 12.7445799565 - 12.7931640901 - 12.841932943 - 12.8908872175 - 12.9400276186 - 12.9893548539 - 13.0388696338 - 13.0885726714 - 13.1384646824 - 13.1885463853 - 13.2388185013 - 13.2892817545 - 13.3399368714 - 13.3907845816 - 13.4418256173 - 13.4930607136 - 13.5444906082 - 13.5961160419 - 13.647937758 - 13.6999565029 - 13.7521730257 - 13.8045880782 - 13.8572024154 - 13.9100167949 - 13.9630319774 - 14.0162487261 - 14.0696678076 - 14.1232899912 - 14.1771160489 - 14.231146756 - 14.2853828905 - 14.3398252335 - 14.3944745689 - 14.4493316839 - 14.5043973684 - 14.5596724153 - 14.6151576207 - 14.6708537836 - 14.7267617061 - 14.7828821933 - 14.8392160534 - 14.8957640976 - 14.9525271403 - 15.009505999 - 15.066701494 - 15.1241144492 - 15.1817456913 - 15.2395960503 - 15.2976663591 - 15.3559574542 - 15.414470175 - 15.473205364 - 15.5321638671 - 15.5913465334 - 15.6507542151 - 15.7103877678 - 15.7702480502 - 15.8303359244 - 15.8906522557 - 15.9511979127 - 16.0119737672 - 16.0729806946 - 16.1342195734 - 16.1956912854 - 16.2573967159 - 16.3193367536 - 16.3815122903 - 16.4439242216 - 16.5065734461 - 16.5694608661 - 16.6325873871 - 16.6959539184 - 16.7595613723 - 16.823410665 - 16.8875027158 - 16.9518384478 - 17.0164187875 - 17.0812446648 - 17.1463170134 - 17.2116367702 - 17.277204876 - 17.343022275 - 17.409089915 - 17.4754087475 - 17.5419797275 - 17.6088038137 - 17.6758819683 - 17.7432151575 - 17.8108043508 - 17.8786505215 - 17.9467546468 - 18.0151177073 - 18.0837406876 - 18.1526245759 - 18.2217703642 - 18.2911790481 - 18.3608516274 - 18.4307891052 - 18.5009924889 - 18.5714627893 - 18.6422010212 - 18.7132082035 - 18.7844853586 - 18.856033513 - 18.927853697 - 18.9999469449 - 19.072314295 - 19.1449567893 - 19.217875474 - 19.2910713991 - 19.3645456188 - 19.4382991912 - 19.5123331783 - 19.5866486463 - 19.6612466654 - 19.7361283099 - 19.8112946581 - 19.8867467925 - 19.9624857997 - 20.0385127703 - 20.1148287993 - 20.1914349856 - 20.2683324325 - 20.3455222473 - 20.4230055415 - 20.5007834312 - 20.5788570362 - 20.657227481 - 20.735895894 - 20.8148634084 - 20.8941311611 - 20.9737002937 - 21.0535719522 - 21.1337472867 - 21.2142274518 -} diff --git a/release/datafiles/colormanagement/luts/slog2.py b/release/datafiles/colormanagement/luts/slog2.py deleted file mode 100644 index 656827df049..00000000000 --- a/release/datafiles/colormanagement/luts/slog2.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python - -import math - -# IT's annoying that the 1023,4 and 4095,16 almost, but dont exactly, cancel. UGH -# The intent is clearly to have the same mapping, but it's not done very well. -# Sony engineers and/or the Academy should pick one of these mappings for both. - -def SLog_to_lin(x): - return (math.pow(10.0,(((((x*1023.0)/4.0-16.0)/219.0)-0.616596-0.03)/0.432699))-0.037584)*0.9 - -def SLog2_to_lin(x): - if x < 0.030001222851889303: - return (x-0.030001222851889303 ) * 0.28258064516129 - return (219.0*(math.pow(10.0, ((x-0.616596-0.03)/0.432699)) - 0.037584) /155.0) - -steps = 21 -for i in xrange(steps): - x = i/(steps-1.0) - print x, SLog_to_lin(x), SLog2_to_lin(x) - -def WriteSPI1D(filename, fromMin, fromMax, data): - f = file(filename,'w') - f.write("Version 1\n") - f.write("From %s %s\n" % (fromMin, fromMax)) - f.write("Length %d\n" % len(data)) - f.write("Components 1\n") - f.write("{\n") - for value in data: - f.write(" %s\n" % value) - f.write("}\n") - f.close() - -def Fit(value, fromMin, fromMax, toMin, toMax): - if fromMin == fromMax: - raise ValueError("fromMin == fromMax") - return (value - fromMin) / (fromMax - fromMin) * (toMax - toMin) + toMin - -""" -5500K: - -ACESR = 0.8764457030 * Rraw + 0.0145411681 * Graw + 0.1090131290 * Braw; -ACESG = 0.0774075345 * Rraw + 0.9529571767 * Graw + -0.0303647111 * Braw; -ACESB = 0.0573564351 * Rraw + -0.1151066335 * Graw + 1.0577501984 * Braw; - -3200K: - -ACESR = 1.0110238740 * Rraw + -0.1362526051 * Graw + 0.1252287310 * Braw; -ACESG = 0.1011994504 * Rraw + 0.9562196265 * Graw + -0.0574190769 * Braw; -ACESB = 0.0600766530 * Rraw + -0.1010185315 * Graw + 1.0409418785 * Braw; -""" - -""" -NUM_SAMPLES = 2**11 -RANGE = (-0.125, 1.125) -data = [] -for i in xrange(NUM_SAMPLES): - x = i/(NUM_SAMPLES-1.0) - x = Fit(x, 0.0, 1.0, RANGE[0], RANGE[1]) - data.append(SLog10_to_lin(x)) -WriteSPI1D('slog2.spi1d', RANGE[0], RANGE[1], data) -""" diff --git a/release/datafiles/colormanagement/luts/slogf35_to_aces.spimtx b/release/datafiles/colormanagement/luts/slogf35_to_aces.spimtx deleted file mode 100644 index 299861faf09..00000000000 --- a/release/datafiles/colormanagement/luts/slogf35_to_aces.spimtx +++ /dev/null @@ -1,4 +0,0 @@ -0.754338638 0.133697046 0.111968437 0 -0.021198141 1.005410934 -0.026610548 0 --0.009756991 0.004508563 1.005253201 0 - diff --git a/release/datafiles/colormanagement/luts/slogf65_to_aces_3200.spimtx b/release/datafiles/colormanagement/luts/slogf65_to_aces_3200.spimtx deleted file mode 100644 index ea7eca4aebb..00000000000 --- a/release/datafiles/colormanagement/luts/slogf65_to_aces_3200.spimtx +++ /dev/null @@ -1,4 +0,0 @@ -1.0110238740 -0.1362526051 0.1252287310 0 -0.1011994504 0.9562196265 -0.0574190769 0 -0.0600766530 -0.1010185315 1.0409418785 0 - diff --git a/release/datafiles/colormanagement/luts/slogf65_to_aces_5500.spimtx b/release/datafiles/colormanagement/luts/slogf65_to_aces_5500.spimtx deleted file mode 100644 index bac5d333844..00000000000 --- a/release/datafiles/colormanagement/luts/slogf65_to_aces_5500.spimtx +++ /dev/null @@ -1,4 +0,0 @@ -0.8764457030 0.0145411681 0.1090131290 0 -0.0774075345 0.9529571767 -0.0303647111 0 -0.0573564351 -0.1151066335 1.0577501984 0 - diff --git a/release/datafiles/colormanagement/luts/ten_bit_scale.spimtx b/release/datafiles/colormanagement/luts/ten_bit_scale.spimtx deleted file mode 100644 index 6b3f9f3cbbd..00000000000 --- a/release/datafiles/colormanagement/luts/ten_bit_scale.spimtx +++ /dev/null @@ -1,3 +0,0 @@ -1023 0.0 0.0 0 -0.0 1023 0.0 0 -0.000 0.0 1023 0 From 8dff07ef9a4a6d57529977c0cfb80fc6367184c1 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 4 Sep 2012 12:32:32 +0000 Subject: [PATCH 105/160] Color Management: fix for color sample information line - Color managed RGB values wouldn't be displayed anymore for byte images (which are currently unsupported to be managed). - Color rectangle would now be color managed - Sequencer was passing non-linear float to information line, now it'll pass linear float. --- .../blender/editors/space_image/image_draw.c | 6 +- .../blender/editors/space_image/image_ops.c | 8 +- source/blender/editors/space_node/node_view.c | 8 +- .../editors/space_sequencer/sequencer_view.c | 13 +- source/blender/imbuf/IMB_colormanagement.h | 17 +- source/blender/imbuf/intern/colormanagement.c | 179 ++++++++++++------ 6 files changed, 158 insertions(+), 73 deletions(-) diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 1fd29c0163d..3078abaa946 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -222,8 +222,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int channel dx += BLF_width(blf_mono_font, str); } - /* OCIO_TODO: make it fit better to overall color interaction */ - if (fp && channels == 4) { + if (color_manage && channels == 4) { float pixel[4]; IMB_display_buffer_pixel(pixel, fp, &scene->view_settings, &scene->display_settings); @@ -276,11 +275,12 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int channel } if (color_manage) { - linearrgb_to_srgb_v4(finalcol, col); + IMB_display_buffer_pixel(finalcol, col, &scene->view_settings, &scene->display_settings); } else { copy_v4_v4(finalcol, col); } + glDisable(GL_BLEND); glColor3fv(finalcol); dx += 5; diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 43e4db16b7d..bc518645e43 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1986,6 +1986,7 @@ typedef struct ImageSampleInfo { float *zfp; int draw; + int color_manage; } ImageSampleInfo; static void image_sample_draw(const bContext *C, ARegion *ar, void *arg_info) @@ -1994,8 +1995,7 @@ static void image_sample_draw(const bContext *C, ARegion *ar, void *arg_info) if (info->draw) { Scene *scene = CTX_data_scene(C); - /* no color management needed for images (color_manage=0) */ - ED_image_draw_info(scene, ar, 0, info->channels, info->x, info->y, info->colp, info->colfp, info->zp, info->zfp); + ED_image_draw_info(scene, ar, info->color_manage, info->channels, info->x, info->y, info->colp, info->colfp, info->zp, info->zfp); } } @@ -2094,6 +2094,8 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->colf[2] = (float)cp[2] / 255.0f; info->colf[3] = (float)cp[3] / 255.0f; info->colfp = info->colf; + + info->color_manage = FALSE; } if (ibuf->rect_float) { fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x)); @@ -2103,6 +2105,8 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->colf[2] = fp[2]; info->colf[3] = fp[3]; info->colfp = info->colf; + + info->color_manage = TRUE; } if (ibuf->zbuf) { diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index dfceb832b65..e86d2b4eb5f 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -327,12 +327,12 @@ typedef struct ImageSampleInfo { void *draw_handle; int x, y; int channels; - int color_manage; unsigned char col[4]; float colf[4]; int draw; + int color_manage; } ImageSampleInfo; static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) @@ -341,7 +341,7 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) ImageSampleInfo *info = arg_info; if (info->draw) { - ED_image_draw_info(scene, ar, (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT), info->channels, + ED_image_draw_info(scene, ar, info->color_manage, info->channels, info->x, info->y, info->col, info->colf, NULL, NULL /* zbuf - unused for nodes */ ); @@ -457,6 +457,8 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->colf[1] = (float)cp[1] / 255.0f; info->colf[2] = (float)cp[2] / 255.0f; info->colf[3] = (float)cp[3] / 255.0f; + + info->color_manage = FALSE; } if (ibuf->rect_float) { fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x)); @@ -465,6 +467,8 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->colf[1] = fp[1]; info->colf[2] = fp[2]; info->colf[3] = fp[3]; + + info->color_manage = TRUE; } ED_node_sample_set(info->colf); diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index f83a903c358..7dc82593a29 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -49,6 +49,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "IMB_colormanagement.h" #include "UI_view2d.h" @@ -70,6 +71,7 @@ typedef struct ImageSampleInfo { float *colfp; int draw; +int color_manage; } ImageSampleInfo; static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) @@ -78,8 +80,8 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) ImageSampleInfo *info = arg_info; if (info->draw) { - ED_image_draw_info(scene, ar, (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT), info->channels, - info->x, info->y, info->col, info->colf, NULL, NULL); + ED_image_draw_info(scene, ar, info->color_manage, info->channels, + info->x, info->y, info->colp, info->colfp, NULL, NULL); } } @@ -131,6 +133,8 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->colf[2] = (float)cp[2] / 255.0f; info->colf[3] = (float)cp[3] / 255.0f; info->colfp = info->colf; + + info->color_manage = FALSE; } if (ibuf->rect_float) { fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x)); @@ -140,6 +144,11 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->colf[2] = fp[2]; info->colf[3] = fp[3]; info->colfp = info->colf; + + /* sequencer's image buffers are in non-linear space, need to make them linear */ + IMB_colormanagement_pixel_from_sequencer_space(info->colf); + + info->color_manage = TRUE; } } else { diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 551251565de..d6a9a1d8ffe 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -54,15 +54,15 @@ void IMB_colormanagement_exit(void); void IMB_colormanagement_colorspace_transform(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace); +void IMB_colormanagement_pixel_to_role(float pixel[4], int role); +void IMB_colormanagement_pixel_from_role(float pixel[4], int role); + void IMB_colormanagement_imbuf_to_role(struct ImBuf *ibuf, int role); void IMB_colormanagement_imbuf_from_role(struct ImBuf *ibuf, int role); void IMB_colormanagement_imbuf_make_scene_linear(struct ImBuf *ibuf, struct ColorManagedColorspaceSettings *colorspace_settings); -void IMB_colormanagement_imbuf_to_sequencer_space(struct ImBuf *ibuf, int make_float); -void IMB_colormanagement_imbuf_from_sequencer_space(struct ImBuf *ibuf); - /* ** Public display buffers interfaces ** */ void IMB_colormanage_cache_free(struct ImBuf *ibuf); @@ -109,6 +109,17 @@ void IMB_partial_display_buffer_update(struct ImBuf *ibuf, const float *linear_b int stride, int offset_x, int offset_y, int xmin, int ymin, int xmax, int ymax); +/* ** Area-specific functions ** */ + +/* Sequencer */ + +void IMB_colormanagement_imbuf_to_sequencer_space(struct ImBuf *ibuf, int make_float); +void IMB_colormanagement_imbuf_from_sequencer_space(struct ImBuf *ibuf); + +void IMB_colormanagement_pixel_from_sequencer_space(float pixel[4]); + + +/* Roles */ enum { COLOR_ROLE_SCENE_LINEAR = 0, COLOR_ROLE_COLOR_PICKING, diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 1bedfb58754..2ba1beccf99 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1019,6 +1019,46 @@ void IMB_colormanagement_imbuf_from_role(ImBuf *ibuf, int role) #endif } +void IMB_colormanagement_pixel_to_role(float pixel[4], int role) +{ +#ifdef WITH_OCIO + ConstProcessorRcPtr *processor; + const char *from_colorspace = global_role_scene_linear; + const char *to_colorspace = role_colorspace_name_get(role); + + processor = create_colorspace_transform_processor(from_colorspace, to_colorspace); + + if (processor) { + OCIO_processorApplyRGBA(processor, pixel); + + OCIO_processorRelease(processor); + } +#else + (void) pixel; + (void) role; +#endif +} + +void IMB_colormanagement_pixel_from_role(float pixel[4], int role) +{ +#ifdef WITH_OCIO + ConstProcessorRcPtr *processor; + const char *from_colorspace = role_colorspace_name_get(role); + const char *to_colorspace = global_role_scene_linear; + + processor = create_colorspace_transform_processor(from_colorspace, to_colorspace); + + if (processor) { + OCIO_processorApplyRGBA(processor, pixel); + + OCIO_processorRelease(processor); + } +#else + (void) pixel; + (void) role; +#endif +} + void IMB_colormanagement_imbuf_make_scene_linear(ImBuf *ibuf, ColorManagedColorspaceSettings *colorspace_settings) { #ifdef WITH_OCIO @@ -1035,67 +1075,6 @@ void IMB_colormanagement_imbuf_make_scene_linear(ImBuf *ibuf, ColorManagedColors #endif } -void IMB_colormanagement_imbuf_to_sequencer_space(ImBuf *ibuf, int make_float) -{ - (void) make_float; - - if (!ibuf->rect_float) { - if (make_float && ibuf->rect) { - /* when converting byte buffer to float in sequencer we need to make float - * buffer be in sequencer's working space, which is currently only doable - * from linear space. - * - */ - - /* - * OCIO_TODO: would be nice to support direct single transform from byte to sequencer's - */ - - ibuf->profile = IB_PROFILE_SRGB; - IMB_float_from_rect(ibuf); - } - else { - /* if there's only byte buffer in image it's already in compositor's working space, - * nothing to do here - */ - - return; - } - } - -#ifdef WITH_OCIO - if (global_role_sequencer[0]) { - IMB_colormanagement_imbuf_to_role(ibuf, COLOR_ROLE_SEQUENCER); - - ibuf->profile = IB_PROFILE_NONE; - } - else -#endif - { - /* if no sequencer's working space defined fallback to legacy sRGB space */ - IMB_convert_profile(ibuf, IB_PROFILE_NONE); - } -} - -void IMB_colormanagement_imbuf_from_sequencer_space(ImBuf *ibuf) -{ - if (!ibuf->rect_float) - return; - -#ifdef WITH_OCIO - if (global_role_sequencer[0]) { - IMB_colormanagement_imbuf_from_role(ibuf, COLOR_ROLE_SEQUENCER); - ibuf->profile = IB_PROFILE_LINEAR_RGB; - } - else -#endif - { - /* if no sequencer's working space defined fallback to legacy sRGB space */ - - IMB_convert_profile(ibuf, IB_PROFILE_LINEAR_RGB); - } -} - #ifdef WITH_OCIO static void colormanage_flags_allocate(ImBuf *ibuf) { @@ -1958,3 +1937,81 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, (void) display_buffer_flags; #endif } + +/*********************** Area-specific functions *************************/ + +/* ** Sequencer ** */ + +void IMB_colormanagement_imbuf_to_sequencer_space(ImBuf *ibuf, int make_float) +{ + (void) make_float; + + if (!ibuf->rect_float) { + if (make_float && ibuf->rect) { + /* when converting byte buffer to float in sequencer we need to make float + * buffer be in sequencer's working space, which is currently only doable + * from linear space. + * + */ + + /* + * OCIO_TODO: would be nice to support direct single transform from byte to sequencer's + */ + + ibuf->profile = IB_PROFILE_SRGB; + IMB_float_from_rect(ibuf); + } + else { + /* if there's only byte buffer in image it's already in compositor's working space, + * nothing to do here + */ + + return; + } + } + +#ifdef WITH_OCIO + if (global_role_sequencer[0]) { + IMB_colormanagement_imbuf_to_role(ibuf, COLOR_ROLE_SEQUENCER); + + ibuf->profile = IB_PROFILE_NONE; + } + else +#endif + { + /* if no sequencer's working space defined fallback to legacy sRGB space */ + IMB_convert_profile(ibuf, IB_PROFILE_NONE); + } +} + +void IMB_colormanagement_imbuf_from_sequencer_space(ImBuf *ibuf) +{ + if (!ibuf->rect_float) + return; + +#ifdef WITH_OCIO + if (global_role_sequencer[0]) { + IMB_colormanagement_imbuf_from_role(ibuf, COLOR_ROLE_SEQUENCER); + ibuf->profile = IB_PROFILE_LINEAR_RGB; + } + else +#endif + { + /* if no sequencer's working space defined fallback to legacy sRGB space */ + + IMB_convert_profile(ibuf, IB_PROFILE_LINEAR_RGB); + } +} + +void IMB_colormanagement_pixel_from_sequencer_space(float pixel[4]) +{ +#ifdef WITH_OCIO + if (global_role_sequencer[0]) { + IMB_colormanagement_pixel_from_role(pixel, COLOR_ROLE_SEQUENCER); + } + else +#endif + { + srgb_to_linearrgb_v4(pixel, pixel); + } +} From 3963425006ea738c93ca30b50cc0332dd522f0d9 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 5 Sep 2012 11:42:20 +0000 Subject: [PATCH 106/160] Merging r50374 through r50412 from trunk into soc-2011-tomato --- extern/bullet2/CMakeLists.txt | 2 + intern/cycles/app/cycles_test.cpp | 12 +- intern/cycles/blender/addon/properties.py | 2 +- intern/cycles/blender/addon/ui.py | 2 + intern/cycles/blender/blender_object.cpp | 3 +- intern/cycles/blender/blender_particles.cpp | 3 +- intern/cycles/blender/blender_session.h | 3 +- intern/cycles/blender/blender_sync.cpp | 5 +- intern/cycles/blender/blender_sync.h | 14 -- intern/cycles/blender/blender_util.h | 11 +- intern/cycles/kernel/kernel_displace.h | 2 + intern/cycles/kernel/kernel_path.h | 30 +++- intern/cycles/kernel/kernel_shader.h | 17 ++ intern/cycles/kernel/osl/nodes/CMakeLists.txt | 1 + .../kernel/osl/nodes/node_brick_texture.osl | 94 +++++++++++ .../osl/nodes/node_gradient_texture.osl | 37 ++--- .../cycles/kernel/osl/nodes/node_holdout.osl | 8 +- .../osl/nodes/node_musgrave_texture.osl | 25 +-- .../kernel/osl/nodes/node_noise_texture.osl | 19 +-- .../kernel/osl/nodes/node_wave_texture.osl | 12 +- intern/cycles/kernel/osl/osl_shader.cpp | 24 +-- intern/cycles/kernel/osl/osl_shader.h | 3 +- intern/cycles/render/camera.cpp | 14 +- intern/cycles/render/camera.h | 2 +- intern/cycles/render/nodes.cpp | 4 +- intern/cycles/render/osl.cpp | 10 +- release/scripts/modules/addon_utils.py | 2 +- release/scripts/startup/bl_operators/wm.py | 2 +- .../scripts/startup/bl_ui/space_sequencer.py | 10 +- release/scripts/templates/operator_modal.py | 3 +- .../scripts/templates/operator_modal_draw.py | 3 +- .../scripts/templates/operator_modal_timer.py | 2 +- .../templates/operator_modal_view3d.py | 3 +- source/blender/blenkernel/BKE_armature.h | 2 - source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/BKE_deform.h | 3 +- source/blender/blenkernel/BKE_object_deform.h | 38 +++++ source/blender/blenkernel/BKE_sequencer.h | 2 +- source/blender/blenkernel/CMakeLists.txt | 2 + .../blender/blenkernel/intern/DerivedMesh.c | 28 ++-- source/blender/blenkernel/intern/armature.c | 30 ---- source/blender/blenkernel/intern/deform.c | 56 ++++++- source/blender/blenkernel/intern/image.c | 4 +- .../blender/blenkernel/intern/object_deform.c | 156 ++++++++++++++++++ .../blender/blenkernel/intern/seqmodifier.c | 36 +--- source/blender/blenkernel/intern/sequencer.c | 36 +--- source/blender/blenlib/CMakeLists.txt | 1 + source/blender/blenloader/intern/readfile.c | 54 ++++-- source/blender/blenloader/intern/writefile.c | 3 - source/blender/compositor/COM_compositor.h | 7 + source/blender/compositor/intern/COM_Device.h | 7 + source/blender/compositor/intern/COM_Node.cpp | 15 ++ source/blender/compositor/intern/COM_Node.h | 7 + .../blender/compositor/intern/COM_NodeBase.h | 3 +- source/blender/compositor/intern/COM_Socket.h | 8 + .../compositor/intern/COM_WorkScheduler.cpp | 29 +++- .../compositor/intern/COM_compositor.cpp | 20 ++- .../compositor/nodes/COM_GroupNode.cpp | 11 +- .../compositor/nodes/COM_ImageNode.cpp | 9 + .../operations/COM_CompositorOperation.h | 3 + source/blender/editors/include/UI_interface.h | 4 +- source/blender/editors/interface/interface.c | 10 +- .../editors/interface/interface_layout.c | 4 +- .../blender/editors/interface/interface_ops.c | 16 +- .../editors/interface/interface_templates.c | 18 +- source/blender/editors/io/io_collada.c | 4 +- source/blender/editors/mesh/editmesh_knife.c | 11 +- source/blender/editors/object/object_vgroup.c | 40 +++-- .../editors/sculpt_paint/paint_vertex.c | 99 +---------- .../blender/editors/space_clip/clip_toolbar.c | 2 +- .../editors/space_logic/logic_window.c | 26 +-- source/blender/editors/space_node/drawnode.c | 66 ++++---- .../blender/editors/space_node/node_buttons.c | 4 +- .../editors/space_node/node_templates.c | 4 +- .../blender/editors/space_view3d/drawmesh.c | 2 +- .../editors/space_view3d/view3d_toolbar.c | 2 +- source/blender/editors/util/CMakeLists.txt | 1 + source/blender/imbuf/intern/moviecache.c | 9 +- source/blender/makesdna/DNA_sequence_types.h | 7 +- source/blender/makesrna/intern/rna_render.c | 2 +- .../blender/makesrna/intern/rna_sequencer.c | 103 ++---------- .../makesrna/rna_cleanup/rna_cleaner.py | 2 +- source/blender/nodes/NOD_shader.h | 1 + .../nodes/composite/node_composite_tree.c | 8 +- source/blender/python/intern/bpy_interface.c | 9 + .../render/intern/source/external_engine.c | 10 +- .../blender/render/intern/source/pipeline.c | 19 ++- .../render/intern/source/render_result.c | 74 +++++---- .../render/intern/source/render_texture.c | 6 +- .../windowmanager/intern/wm_event_system.c | 5 +- .../windowmanager/intern/wm_operators.c | 2 +- source/tests/pep8.py | 2 +- 92 files changed, 901 insertions(+), 627 deletions(-) create mode 100644 intern/cycles/kernel/osl/nodes/node_brick_texture.osl create mode 100644 source/blender/blenkernel/BKE_object_deform.h create mode 100644 source/blender/blenkernel/intern/object_deform.c diff --git a/extern/bullet2/CMakeLists.txt b/extern/bullet2/CMakeLists.txt index 4bf26ab3794..c57474f99f2 100644 --- a/extern/bullet2/CMakeLists.txt +++ b/extern/bullet2/CMakeLists.txt @@ -314,6 +314,7 @@ set(SRC src/BulletDynamics/Character/btKinematicCharacterController.h src/BulletSoftBody/btSoftBody.h + src/BulletSoftBody/btSoftBodyInternals.h src/BulletSoftBody/btSoftBodyData.h src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h src/BulletSoftBody/btSoftBodyHelpers.h @@ -355,6 +356,7 @@ set(SRC src/btBulletCollisionCommon.h src/btBulletDynamicsCommon.h + src/Bullet-C-Api.h ) if(CMAKE_COMPILER_IS_GNUCXX) diff --git a/intern/cycles/app/cycles_test.cpp b/intern/cycles/app/cycles_test.cpp index 75f76efc8e1..5ee351260c5 100644 --- a/intern/cycles/app/cycles_test.cpp +++ b/intern/cycles/app/cycles_test.cpp @@ -66,12 +66,13 @@ static void session_print(const string& str) static void session_print_status() { - int sample; + int sample, tile; double total_time, sample_time; string status, substatus; /* get status */ - options.session->progress.get_sample(sample, total_time, sample_time); + sample = options.session->progress.get_sample(); + options.session->progress.get_tile(tile, total_time, sample_time); options.session->progress.get_status(status, substatus); if(substatus != "") @@ -111,7 +112,7 @@ static void session_init() static void scene_init(int width, int height) { - options.scene = new Scene(options.scene_params); + options.scene = new Scene(options.scene_params, options.session_params.device); xml_read_file(options.scene, options.filepath.c_str()); if (width == 0 || height == 0) { @@ -147,11 +148,12 @@ static void display_info(Progress& progress) latency = (elapsed - last); last = elapsed; - int sample; + int sample, tile; double total_time, sample_time; string status, substatus; - progress.get_sample(sample, total_time, sample_time); + sample = progress.get_sample(); + progress.get_tile(tile, total_time, sample_time); progress.get_status(status, substatus); if(substatus != "") diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index c23f0196c2d..7f3eca471e6 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -244,7 +244,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): cls.resolution_divider = IntProperty( name="Resolution Divider", - description="Start viewport rendering with lower resolution which would be real resolution divided by two in power of this value", + description="For viewport render, the number of lower resolutions to render before the full resolution", min=1, max=512, default=4, ) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 885b488a3ea..bf44a558b1a 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -213,6 +213,8 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel): sub.prop(cscene, "debug_use_spatial_splits") sub.prop(cscene, "use_cache") + sub = col.column(align=True) + sub.label(text="Viewport:") sub.prop(cscene, "resolution_divider") diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index fd9f836eec0..eb9deb0de2d 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -305,8 +305,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) for(; b_sce && !cancel; b_sce = b_sce.background_set()) { for(b_sce.objects.begin(b_ob); b_ob != b_sce.objects.end() && !cancel; ++b_ob) { bool hide = (render_layer.use_viewport_visibility)? b_ob->hide(): b_ob->hide_render(); - uint ob_layer = get_layer(b_ob->layers(), b_ob->layers_local_view(), object_is_light(*b_ob)); - CYCLES_LOCAL_LAYER_HACK(render_layer.use_localview, ob_layer); + uint ob_layer = get_layer(b_ob->layers(), b_ob->layers_local_view(), render_layer.use_localview, object_is_light(*b_ob)); hide = hide || !(ob_layer & scene_layer); if(!hide) { diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp index 177912cd8f0..f309960fc55 100644 --- a/intern/cycles/blender/blender_particles.cpp +++ b/intern/cycles/blender/blender_particles.cpp @@ -199,8 +199,7 @@ void BlenderSync::sync_particle_systems() for(; b_sce; b_sce = b_sce.background_set()) { for(b_sce.objects.begin(b_ob); b_ob != b_sce.objects.end(); ++b_ob) { bool hide = (render_layer.use_viewport_visibility)? b_ob->hide(): b_ob->hide_render(); - uint ob_layer = get_layer(b_ob->layers(), b_ob->layers_local_view(), object_is_light(*b_ob)); - CYCLES_LOCAL_LAYER_HACK(render_layer.use_localview, ob_layer); + uint ob_layer = get_layer(b_ob->layers(), b_ob->layers_local_view(), render_layer.use_localview, object_is_light(*b_ob)); hide = hide || !(ob_layer & scene_layer); if(!hide) { diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index 4666b5982e1..d52e0103bbf 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -53,8 +53,7 @@ public: void write_render_tile(RenderTile& rtile); /* update functions are used to update display buffer only after sample was rendered - * only needed for better visual feedback - */ + * only needed for better visual feedback */ void update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile); void update_render_tile(RenderTile& rtile); diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index cb83309cc00..907573cf072 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -231,8 +231,7 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer) } else { render_layer.use_localview = (b_v3d.local_view() ? true : false); - render_layer.scene_layer = get_layer(b_v3d.layers(), b_v3d.layers_local_view()); - CYCLES_LOCAL_LAYER_HACK(render_layer.use_localview, render_layer.scene_layer); + render_layer.scene_layer = get_layer(b_v3d.layers(), b_v3d.layers_local_view(), render_layer.use_localview); render_layer.layer = render_layer.scene_layer; render_layer.holdout_layer = 0; render_layer.material_override = PointerRNA_NULL; @@ -354,8 +353,6 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use /* tiles */ if(params.device.type != DEVICE_CPU && !background) { - printf("%d\n", get_int(cscene, "debug_tile_size")); - /* currently GPU could be much slower than CPU when using tiles, * still need to be investigated, but meanwhile make it possible * to work in viewport smoothly diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index ac4cc37b74a..27f6b6ee4ee 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -137,20 +137,6 @@ private: Progress &progress; }; -/* we don't have spare bits for localview (normally 20-28) - * because PATH_RAY_LAYER_SHIFT uses 20-32. - * So - check if we have localview and if so, shift local - * view bits down to 1-8, since this is done for the view - * port only - it should be OK and not conflict with - * render layers. - Campbell. - * - * ... as an alternative we could use uint64_t - */ -#define CYCLES_LOCAL_LAYER_HACK(use_localview, layer) \ - if (use_localview) { \ - layer >>= 20; \ - } (void)0 - CCL_NAMESPACE_END #endif /* __BLENDER_SYNC_H__ */ diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index b0febcc23d4..d0fca9a9fb9 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -170,7 +170,7 @@ static inline uint get_layer(BL::Array array) return layer; } -static inline uint get_layer(BL::Array array, BL::Array local_array, bool is_light = false) +static inline uint get_layer(BL::Array array, BL::Array local_array, bool use_local, bool is_light = false) { uint layer = 0; @@ -188,7 +188,14 @@ static inline uint get_layer(BL::Array array, BL::Array local_a if(local_array[i]) layer |= (1 << (20+i)); } - + + /* we don't have spare bits for localview (normally 20-28) because + * PATH_RAY_LAYER_SHIFT uses 20-32. So - check if we have localview and if + * so, shift local view bits down to 1-8, since this is done for the view + * port only - it should be OK and not conflict with render layers. */ + if(use_local) + layer >>= 20; + return layer; } diff --git a/intern/cycles/kernel/kernel_displace.h b/intern/cycles/kernel/kernel_displace.h index f4b33605f5b..6461a1eea38 100644 --- a/intern/cycles/kernel/kernel_displace.h +++ b/intern/cycles/kernel/kernel_displace.h @@ -63,6 +63,8 @@ __device void kernel_shader_evaluate(KernelGlobals *kg, uint4 *input, float4 *ou out = shader_eval_background(kg, &sd, flag); } + 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_path.h b/intern/cycles/kernel/kernel_path.h index 6c81fa4cfca..d606c3d634a 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -209,6 +209,8 @@ __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++; } } @@ -294,8 +296,10 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, L_transparent += average(holdout_weight*throughput); } - if(sd.flag & SD_HOLDOUT_MASK) + if(sd.flag & SD_HOLDOUT_MASK) { + shader_release(kg, &sd); break; + } } #endif @@ -313,8 +317,10 @@ __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) + if(terminate >= probability) { + shader_release(kg, &sd); break; + } throughput /= probability; @@ -380,8 +386,10 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, #endif /* no BSDF? we can stop here */ - if(!(sd.flag & SD_BSDF)) + if(!(sd.flag & SD_BSDF)) { + shader_release(kg, &sd); break; + } /* sample BSDF */ float bsdf_pdf; @@ -486,8 +494,10 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray float probability = path_state_terminate_probability(kg, &state, throughput); float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE); - if(terminate >= probability) + if(terminate >= probability) { + shader_release(kg, &sd); break; + } throughput /= probability; @@ -554,8 +564,10 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray #endif /* no BSDF? we can stop here */ - if(!(sd.flag & SD_BSDF)) + if(!(sd.flag & SD_BSDF)) { + shader_release(kg, &sd); break; + } /* sample BSDF */ float bsdf_pdf; @@ -661,8 +673,10 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam L_transparent += average(holdout_weight*throughput); } - if(sd.flag & SD_HOLDOUT_MASK) + if(sd.flag & SD_HOLDOUT_MASK) { + shader_release(kg, &sd); break; + } } #endif @@ -682,8 +696,10 @@ __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) + if(terminate >= probability) { + shader_release(kg, &sd); break; + } throughput /= probability; } diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 5ab3c2c2545..b57e27bc8ed 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -46,6 +46,11 @@ CCL_NAMESPACE_BEGIN __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray) { +#ifdef __OSL__ + if (kernel_osl_use(kg)) + OSLShader::init(kg, sd); +#endif + /* fetch triangle data */ int prim = kernel_tex_fetch(__prim_index, isect->prim); float4 Ns = kernel_tex_fetch(__tri_normal, prim); @@ -129,6 +134,11 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, const float3 P, const float3 Ng, const float3 I, int shader, int object, int prim, float u, float v, float t, float time) { +#ifdef __OSL__ + if (kernel_osl_use(kg)) + OSLShader::init(kg, sd); +#endif + /* vectors */ sd->P = P; sd->N = Ng; @@ -233,6 +243,8 @@ __device void shader_setup_from_sample(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; @@ -251,6 +263,11 @@ __device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd, __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData *sd, const Ray *ray) { +#ifdef __OSL__ + if (kernel_osl_use(kg)) + OSLShader::init(kg, sd); +#endif + /* vectors */ sd->P = ray->D; sd->N = -sd->P; diff --git a/intern/cycles/kernel/osl/nodes/CMakeLists.txt b/intern/cycles/kernel/osl/nodes/CMakeLists.txt index 2d2b5b10ce6..08e9b9ee726 100644 --- a/intern/cycles/kernel/osl/nodes/CMakeLists.txt +++ b/intern/cycles/kernel/osl/nodes/CMakeLists.txt @@ -5,6 +5,7 @@ set(SRC_OSL node_add_closure.osl node_attribute.osl node_background.osl + node_brick_texture.osl node_bump.osl node_camera.osl node_checker_texture.osl diff --git a/intern/cycles/kernel/osl/nodes/node_brick_texture.osl b/intern/cycles/kernel/osl/nodes/node_brick_texture.osl new file mode 100644 index 00000000000..4daceb4018e --- /dev/null +++ b/intern/cycles/kernel/osl/nodes/node_brick_texture.osl @@ -0,0 +1,94 @@ +/* + * Copyright 2012, 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" +#include "node_texture.h" + +/* Brick */ + +float brick_noise(int n) /* fast integer noise */ +{ + int nn; + n = (n >> 13) ^ n; + nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 2147483647; + return 0.5 * ((float)nn / 1073741824.0); +} + +float brick(point p, float mortar_size, float bias, + float BrickWidth, float row_height, float offset_amount, int offset_frequency, + float squash_amount, int squash_frequency, float tint) +{ + int bricknum, rownum; + float offset = 0.0; + float brick_width = BrickWidth; + float x, y; + + rownum = (int)floor(p[1] / row_height); + + if(offset_frequency && squash_frequency) { + brick_width *= ((int)(rownum) % squash_frequency ) ? 1.0 : squash_amount; /* squash */ + offset = ((int)(rownum) % offset_frequency ) ? 0 : (brick_width*offset_amount); /* offset */ + } + + bricknum = (int)floor((p[0]+offset) / brick_width); + + x = (p[0]+offset) - brick_width*bricknum; + y = p[1] - row_height*rownum; + + tint = clamp((brick_noise((rownum << 16) + (bricknum & 65535)) + bias), 0.0, 1.0); + + return (x < mortar_size || y < mortar_size || + x > (brick_width - mortar_size) || + y > (row_height - mortar_size)) ? 1.0 : 0.0; +} + +shader node_brick_texture( + float Offset = 0.5, + int OffsetFrequency = 2, + float Squash = 1.0, + int SquashFrequency = 1, + point Vector = P, + color Color1 = color(0.2, 0.2, 0.2), + color Color2 = color(0.8, 0.8, 0.8), + color Mortar = color(0.0, 0.0, 0.0), + float Scale = 5.0, + float MortarSize = 0.02, + float Bias = 0.0, + float BrickWidth = 0.5, + float RowHeight = 0.25, + output float Fac = 0.0, + output color Color = color(0.2, 0.2, 0.2)) +{ + float tint = 0.0; + color Col = Color1; + + Fac = brick(Vector*Scale, MortarSize, Bias, BrickWidth, RowHeight, + Offset, OffsetFrequency, Squash, SquashFrequency, tint); + + if(Fac != 1.0) { + float facm = 1.0 - tint; + + Col[0] = facm * (Color1[0]) + tint * Color2[0]; + Col[1] = facm * (Color1[1]) + tint * Color2[1]; + Col[2] = facm * (Color1[2]) + tint * Color2[2]; + } + + Color = (Fac == 1.0) ? Mortar: Col; + +} + diff --git a/intern/cycles/kernel/osl/nodes/node_gradient_texture.osl b/intern/cycles/kernel/osl/nodes/node_gradient_texture.osl index e6fa014324c..a8dd65ae23b 100644 --- a/intern/cycles/kernel/osl/nodes/node_gradient_texture.osl +++ b/intern/cycles/kernel/osl/nodes/node_gradient_texture.osl @@ -21,46 +21,40 @@ /* Gradient */ -float gradient(point p, string progression, string axis) +float gradient(point p, string type) { float x, y; - - if(axis == "Vertical") { - x= p[1]; - y= p[0]; - } - else { - x= p[0]; - y= p[1]; - } + + x = p[0]; + y = p[1]; float result = 0.0; - if(progression == "Linear") { + if(type == "Linear") { result = (1.0 + x)/2.0; } - else if(progression == "Quadratic") { + else if(type == "Quadratic") { float r = max((1.0 + x)/2.0, 0.0); result = r*r; } - else if(progression == "Easing") { + else if(type == "Easing") { float r = min(max((1.0 + x)/2.0, 0.0), 1.0); float t = r*r; result = (3.0*t - 2.0*t*r); } - else if(progression == "Diagonal") { + else if(type == "Diagonal") { result = (2.0 + x + y)/4.0; } - else if(progression == "Radial") { + else if(type == "Radial") { result = atan2(y, x)/(2*M_PI) + 0.5; } else { float r = max(1.0 - sqrt(x*x + y*y + p[2]*p[2]), 0.0); - if(progression == "Quadratic Sphere") + if(type == "Quadratic Sphere") result = r*r; - else if(progression == "Spherical") + else if(type == "Spherical") result = r; } @@ -68,11 +62,12 @@ float gradient(point p, string progression, string axis) } shader node_gradient_texture( - string Progression = "Linear", - string Axis = "Horizontal", + string Type = "Linear", point Vector = P, - output float Fac = 0.0) + output float Fac = 0.0, + output color Color = color(0.0, 0.0, 0.0)) { - Fac = gradient(Vector, Progression, Axis); + Fac = gradient(Vector, Type); + Color = color(Fac, Fac, Fac); } diff --git a/intern/cycles/kernel/osl/nodes/node_holdout.osl b/intern/cycles/kernel/osl/nodes/node_holdout.osl index 69f8d85a82e..aede50c7ca0 100644 --- a/intern/cycles/kernel/osl/nodes/node_holdout.osl +++ b/intern/cycles/kernel/osl/nodes/node_holdout.osl @@ -18,11 +18,9 @@ #include "stdosl.h" -shader node_background( - color Color = color(0.8, 0.8, 0.8), - float Strength = 1.0, - output closure color Background = background()) +shader node_holdout( + output closure color Holdout = holdout()) { - Background = Color*Strength*background(); + } diff --git a/intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl b/intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl index 3ab345279f1..3e1a6862660 100644 --- a/intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl +++ b/intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl @@ -186,32 +186,35 @@ float noise_musgrave_ridged_multi_fractal(point p, string basis, float H, float shader node_musgrave_texture( string Type = "fBM", - string Basis = "Perlin", float Dimension = 2.0, float Lacunarity = 1.0, - float Octaves = 2.0, + float Detail = 2.0, float Offset = 0.0, - float Intensity = 1.0, float Gain = 1.0, float Scale = 5.0, point Vector = P, - output float Fac = 0.0) + output float Fac = 0.0, + output color Color = color(0.0, 0.0, 0.0)) { - float dimension = max(Dimension, 0.0); - float octaves = max(Octaves, 0.0); + float dimension = max(Dimension, 1e-5); + float octaves = clamp(Detail, 0.0, 16.0); float lacunarity = max(Lacunarity, 1e-5); + string Basis = "Perlin"; + float intensity = 1.0; point p = Vector*Scale; if(Type == "Multifractal") - Fac = Intensity*noise_musgrave_multi_fractal(p, Basis, dimension, lacunarity, octaves); + Fac = intensity*noise_musgrave_multi_fractal(p, Basis, dimension, lacunarity, octaves); else if(Type == "fBM") - Fac = Intensity*noise_musgrave_fBm(p, Basis, dimension, lacunarity, octaves); + Fac = intensity*noise_musgrave_fBm(p, Basis, dimension, lacunarity, octaves); else if(Type == "Hybrid Multifractal") - Fac = Intensity*noise_musgrave_hybrid_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain); + Fac = intensity*noise_musgrave_hybrid_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain); else if(Type == "Ridged Multifractal") - Fac = Intensity*noise_musgrave_ridged_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain); + Fac = intensity*noise_musgrave_ridged_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain); else if(Type == "Hetero Terrain") - Fac = Intensity*noise_musgrave_hetero_terrain(p, Basis, dimension, lacunarity, octaves, Offset); + Fac = intensity*noise_musgrave_hetero_terrain(p, Basis, dimension, lacunarity, octaves, Offset); + + Color = color(Fac, Fac, Fac); } diff --git a/intern/cycles/kernel/osl/nodes/node_noise_texture.osl b/intern/cycles/kernel/osl/nodes/node_noise_texture.osl index 7738902f529..1ddb4d8a08b 100644 --- a/intern/cycles/kernel/osl/nodes/node_noise_texture.osl +++ b/intern/cycles/kernel/osl/nodes/node_noise_texture.osl @@ -21,11 +21,10 @@ /* Noise */ -float noise(point p, string basis, float distortion, float detail) +float noise(point p, string basis, float distortion, float detail, float fac, color Color) { point r; int hard = 0; - float fac = 0.0; if(distortion != 0.0) { r[0] = noise_basis(p + point(13.5), basis) * distortion; @@ -37,23 +36,21 @@ float noise(point p, string basis, float distortion, float detail) fac = noise_turbulence(p, basis, detail, hard); + Color = color(fac, noise_turbulence(point(p[1], p[0], p[2]), basis, detail, hard), + noise_turbulence(point(p[1], p[2], p[0]), basis, detail, hard)); + return fac; - - /* - Color[0] = Fac; - Color[1] = noise_turbulence(point(p[1], p[0], p[2]), basis, detail, hard); - Color[2] = noise_turbulence(point(p[1], p[2], p[0]), basis, detail, hard); - */ } shader node_noise_texture( - string Basis = "Perlin", float Distortion = 0.0, float Scale = 5.0, float Detail = 2.0, point Vector = P, - output float Fac = 0.0) + output float Fac = 0.0, + output color Color = color(0.2, 0.2, 0.2)) { - Fac = noise(Vector*Scale, Basis, Distortion, Detail); + string Basis = "Perlin"; + Fac = noise(Vector*Scale, Basis, Distortion, Detail, Fac, Color); } diff --git a/intern/cycles/kernel/osl/nodes/node_wave_texture.osl b/intern/cycles/kernel/osl/nodes/node_wave_texture.osl index 693f09ae24c..db53faaf94b 100644 --- a/intern/cycles/kernel/osl/nodes/node_wave_texture.osl +++ b/intern/cycles/kernel/osl/nodes/node_wave_texture.osl @@ -48,12 +48,14 @@ float wave(point p, float scale, string type, float detail, float distortion, fl shader node_wave_texture( string Type = "Bands", float Scale = 5.0, - float distortion = 0.0, - float detail = 2.0, - float dscale = 1.0, + float Distortion = 0.0, + float Detail = 2.0, + float DetailScale = 1.0, point Vector = P, - output float Fac = 0.0) + output float Fac = 0.0, + output color Color = color (0.0, 0.0, 0.0)) { - Fac = wave(Vector, Scale, Type, detail, distortion, dscale); + Fac = wave(Vector, Scale, Type, Detail, Distortion, DetailScale); + Color = color(Fac, Fac, Fac); } diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index 345614c2868..98ede0e4f60 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -204,10 +204,9 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int OSL::ShadingSystem *ss = kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); OSL::ShaderGlobals *globals = &tdata->globals; - OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info); + OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; /* setup shader globals from shader data */ - sd->osl_ctx = ctx; shaderdata_to_shaderglobals(kg, sd, path_flag, globals); /* execute shader for this point */ @@ -262,10 +261,9 @@ float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_fl OSL::ShadingSystem *ss = kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); OSL::ShaderGlobals *globals = &tdata->globals; - OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info); + OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; /* setup shader globals from shader data */ - sd->osl_ctx = ctx; shaderdata_to_shaderglobals(kg, sd, path_flag, globals); /* execute shader for this point */ @@ -339,10 +337,9 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int OSL::ShadingSystem *ss = kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); OSL::ShaderGlobals *globals = &tdata->globals; - OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info); + OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; /* setup shader globals from shader data */ - sd->osl_ctx = ctx; shaderdata_to_shaderglobals(kg, sd, path_flag, globals); /* execute shader */ @@ -363,10 +360,9 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) OSL::ShadingSystem *ss = kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); OSL::ShaderGlobals *globals = &tdata->globals; - OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info); + OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; /* setup shader globals from shader data */ - sd->osl_ctx = ctx; shaderdata_to_shaderglobals(kg, sd, 0, globals); /* execute shader */ @@ -379,13 +375,19 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) sd->P = TO_FLOAT3(globals->P); } -void OSLShader::release(KernelGlobals *kg, const ShaderData *sd) +void OSLShader::init(KernelGlobals *kg, ShaderData *sd) { OSL::ShadingSystem *ss = kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); - OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info); + + sd->osl_ctx = ss->get_context(tdata->thread_info); +} - ss->release_context(ctx); +void OSLShader::release(KernelGlobals *kg, ShaderData *sd) +{ + OSL::ShadingSystem *ss = kg->osl.ss; + + ss->release_context((OSL::ShadingContext *)sd->osl_ctx); } /* BSDF Closure */ diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h index 815557ed203..e55f98d4d02 100644 --- a/intern/cycles/kernel/osl/osl_shader.h +++ b/intern/cycles/kernel/osl/osl_shader.h @@ -79,7 +79,8 @@ public: const float3 omega_in, const float3 omega_out); /* release */ - static void release(KernelGlobals *kg, const ShaderData *sd); + static void init(KernelGlobals *kg, ShaderData *sd); + static void release(KernelGlobals *kg, ShaderData *sd); }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 272ddb89b0c..e44caa90f12 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -75,7 +75,7 @@ Camera::Camera() need_update = true; need_device_update = true; - previous_motion = -1; + previous_need_motion = -1; } Camera::~Camera() @@ -145,12 +145,10 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) update(); - if (previous_motion != need_motion) { - /* scene's motion model could have been changed since - * previous device camera update - * this could happen for example in case when one render - * layer has got motion pass and another not - */ + if (previous_need_motion != need_motion) { + /* scene's motion model could have been changed since previous device + * camera update this could happen for example in case when one render + * layer has got motion pass and another not */ need_device_update = true; } @@ -237,7 +235,7 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) kcam->cliplength = (farclip == FLT_MAX)? FLT_MAX: farclip - nearclip; need_device_update = false; - previous_motion = need_motion; + previous_need_motion = need_motion; } void Camera::device_free(Device *device, DeviceScene *dscene) diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index a539510029f..82852bde5e0 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -91,7 +91,7 @@ public: /* update */ bool need_update; bool need_device_update; - int previous_motion; + int previous_need_motion; /* functions */ Camera(); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index da511b2d2f4..1f03ab4e347 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -984,9 +984,9 @@ void BrickTextureNode::compile(SVMCompiler& compiler) void BrickTextureNode::compile(OSLCompiler& compiler) { compiler.parameter("Offset", offset); - compiler.parameter("Offset Frequency", offset_frequency); + compiler.parameter("OffsetFrequency", offset_frequency); compiler.parameter("Squash", squash); - compiler.parameter("Squash Frequency", squash_frequency); + compiler.parameter("SquashFrequency", squash_frequency); compiler.add(this, "node_brick_texture"); } diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index d4c93c07e2f..dbd6b0ac9d9 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -200,19 +200,19 @@ void OSLCompiler::add(ShaderNode *node, const char *name) switch(input->type) { case SHADER_SOCKET_COLOR: - parameter_color(input->name, input->value); + parameter_color(compatible_name(input->name).c_str(), input->value); break; case SHADER_SOCKET_POINT: - parameter_point(input->name, input->value); + parameter_point(compatible_name(input->name).c_str(), input->value); break; case SHADER_SOCKET_VECTOR: - parameter_vector(input->name, input->value); + parameter_vector(compatible_name(input->name).c_str(), input->value); break; case SHADER_SOCKET_NORMAL: - parameter_normal(input->name, input->value); + parameter_normal(compatible_name(input->name).c_str(), input->value); break; case SHADER_SOCKET_FLOAT: - parameter(input->name, input->value.x); + parameter(compatible_name(input->name).c_str(), input->value.x); break; case SHADER_SOCKET_CLOSURE: break; diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py index 433d9024e0a..485b4829b71 100644 --- a/release/scripts/modules/addon_utils.py +++ b/release/scripts/modules/addon_utils.py @@ -148,7 +148,7 @@ def modules(module_cache): for path in path_list: # force all contrib addons to be 'TESTING' - if path.endswith("addons_contrib") or path.endswith("addons_extern"): + if path.endswith(("addons_contrib", "addons_extern")): force_support = 'TESTING' else: force_support = None diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index ed4d5dd55f5..513277a2099 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -735,7 +735,7 @@ class WM_OT_context_modal_mouse(Operator): if not self._values: self.report({'WARNING'}, "Nothing to operate on: %s[ ].%s" % - (self.data_path_iter, self.data_path_item)) + (self.data_path_iter, self.data_path_item)) return {'CANCELLED'} else: diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index d92325a8b3d..2ab90301bdb 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -449,7 +449,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): return strip.type in {'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER', 'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP', 'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', 'SPEED', - 'MULTICAM', 'ADJUSTMENT'} + 'MULTICAM'} def draw(self, context): layout = self.layout @@ -463,10 +463,6 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): if strip.input_count > 1: col.prop(strip, "input_2") - if strip.is_supports_mask: - col = layout.column() - col.prop_search(strip, "input_mask_strip", sequencer, "sequences", text="Mask") - if strip.type == 'COLOR': layout.prop(strip, "color") @@ -793,10 +789,6 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel): col.prop(strip, "use_premultiply") col.prop(strip, "use_float") - layout.prop(strip, "use_color_balance") - if strip.use_color_balance and strip.color_balance: # TODO - need to add this somehow - draw_color_balance(layout, strip.color_balance) - class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel): bl_label = "Proxy / Timecode" diff --git a/release/scripts/templates/operator_modal.py b/release/scripts/templates/operator_modal.py index d8115bc95bf..88e5ee80590 100644 --- a/release/scripts/templates/operator_modal.py +++ b/release/scripts/templates/operator_modal.py @@ -26,9 +26,10 @@ class ModalOperator(bpy.types.Operator): def invoke(self, context, event): if context.object: - context.window_manager.modal_handler_add(self) self.first_mouse_x = event.mouse_x self.first_value = context.object.location.x + + context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'} else: self.report({'WARNING'}, "No active object, could not finish") diff --git a/release/scripts/templates/operator_modal_draw.py b/release/scripts/templates/operator_modal_draw.py index f2d5ad8982b..f1c4e113b0a 100644 --- a/release/scripts/templates/operator_modal_draw.py +++ b/release/scripts/templates/operator_modal_draw.py @@ -53,14 +53,13 @@ class ModalDrawOperator(bpy.types.Operator): def invoke(self, context, event): if context.area.type == 'VIEW_3D': - context.window_manager.modal_handler_add(self) - # Add the region OpenGL drawing callback # draw in view space with 'POST_VIEW' and 'PRE_VIEW' self._handle = context.region.callback_add(draw_callback_px, (self, context), 'POST_PIXEL') self.mouse_path = [] + context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'} else: self.report({'WARNING'}, "View3D not found, cannot run operator") diff --git a/release/scripts/templates/operator_modal_timer.py b/release/scripts/templates/operator_modal_timer.py index 6d2ec95aedb..72c153df9d2 100644 --- a/release/scripts/templates/operator_modal_timer.py +++ b/release/scripts/templates/operator_modal_timer.py @@ -21,8 +21,8 @@ class ModalTimerOperator(bpy.types.Operator): return {'PASS_THROUGH'} def execute(self, context): - context.window_manager.modal_handler_add(self) self._timer = context.window_manager.event_timer_add(0.1, context.window) + context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'} def cancel(self, context): diff --git a/release/scripts/templates/operator_modal_view3d.py b/release/scripts/templates/operator_modal_view3d.py index 0babf169610..c870bbffdcf 100644 --- a/release/scripts/templates/operator_modal_view3d.py +++ b/release/scripts/templates/operator_modal_view3d.py @@ -45,14 +45,13 @@ class ViewOperator(bpy.types.Operator): v3d = context.space_data rv3d = v3d.region_3d - context.window_manager.modal_handler_add(self) - if rv3d.view_perspective == 'CAMERA': rv3d.view_perspective = 'PERSP' self._initial_mouse = Vector((event.mouse_x, event.mouse_y, 0.0)) self._initial_location = rv3d.view_location.copy() + context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'} else: self.report({'WARNING'}, "Active space must be a View3d") diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 44e47e779e7..d750e88ac04 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -101,8 +101,6 @@ void get_objectspace_bone_matrix(struct Bone *bone, float M_accumulatedMatrix[][ void vec_roll_to_mat3(const float vec[3], const float roll, float mat[][3]); void mat3_to_vec_roll(float mat[][3], float *vec, float *roll); -int get_selected_defgroups(struct Object *ob, char *defbase_sel, int defbase_len); - /* Common Conversions Between Co-ordinate Spaces */ void BKE_armature_mat_world_to_pose(struct Object *ob, float inmat[][4], float outmat[][4]); void BKE_armature_loc_world_to_pose(struct Object *ob, const float inloc[3], float outloc[3]); diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index dec4d3cb8cb..0e7bdbbb4dd 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 263 -#define BLENDER_SUBVERSION 17 +#define BLENDER_SUBVERSION 18 /* 262 was the last editmesh release but its has compatibility code for bmesh data, * so set the minversion to 2.61 */ diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index 25677165fc2..52a143ddf55 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -67,7 +67,8 @@ void defvert_remap(struct MDeformVert *dvert, int *map, const int map_len); void defvert_flip(struct MDeformVert *dvert, const int *flip_map, const int flip_map_len); void defvert_flip_merged(struct MDeformVert *dvert, const int *flip_map, const int flip_map_len); void defvert_normalize(struct MDeformVert *dvert); -void defvert_normalize_lock(struct MDeformVert *dvert, const int def_nr_lock); +void defvert_normalize_lock_single(struct MDeformVert *dvert, const int def_nr_lock); +void defvert_normalize_lock_map(struct MDeformVert *dvert, const char *lock_flags, const int defbase_tot); /* utility function, note that MAX_VGROUP_NAME chars is the maximum string length since its only * used with defgroups currently */ diff --git a/source/blender/blenkernel/BKE_object_deform.h b/source/blender/blenkernel/BKE_object_deform.h new file mode 100644 index 00000000000..35a4e19a5bc --- /dev/null +++ b/source/blender/blenkernel/BKE_object_deform.h @@ -0,0 +1,38 @@ +/* + * ***** 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. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BKE_OBJECT_DEFORM_H__ +#define __BKE_OBJECT_DEFORM_H__ + +/** \file BKE_object_vgroup.h + * \ingroup bke + * \brief Functions for dealing with objects and deform verts, + * used by painting and tools. + */ + +struct Object; + +char *BKE_objdef_lock_flags_get(struct Object *ob, const int defbase_tot); +char *BKE_objdef_validmap_get(struct Object *ob, const int defbase_tot); +char *BKE_objdef_selected_get(struct Object *ob, int defbase_tot, int *r_dg_flags_sel_tot); + +#endif /* __BKE_OBJECT_DEFORM_H__ */ diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 0468d3fad9c..5bef0b2a771 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -380,7 +380,7 @@ typedef struct SequenceModifierTypeInfo { void (*copy_data) (struct SequenceModifierData *smd, struct SequenceModifierData *target); /* apply modifier on a given image buffer */ - struct ImBuf *(*apply) (struct SequenceModifierData *smd, struct ImBuf *ibuf, struct ImBuf *mask); + void (*apply) (struct SequenceModifierData *smd, struct ImBuf *ibuf, struct ImBuf *mask); } SequenceModifierTypeInfo; struct SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index afa3998fb49..576b79f899c 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -115,6 +115,7 @@ set(SRC intern/nla.c intern/node.c intern/object.c + intern/object_deform.c intern/ocean.c intern/packedFile.c intern/paint.c @@ -203,6 +204,7 @@ set(SRC BKE_nla.h BKE_node.h BKE_object.h + BKE_object_deform.h BKE_ocean.h BKE_packedFile.h BKE_paint.h diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 1aa54307841..a7f8e1bb161 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -59,6 +59,7 @@ #include "BKE_modifier.h" #include "BKE_mesh.h" #include "BKE_object.h" +#include "BKE_object_deform.h" #include "BKE_paint.h" #include "BKE_texture.h" #include "BKE_multires.h" @@ -1015,14 +1016,14 @@ static void calc_weightpaint_vert_color( unsigned char r_col[4], MDeformVert *dv, ColorBand *coba, const int defbase_tot, const int defbase_act, - const char *dg_flags, - const int selected, const int draw_flag) + const char *defbase_sel, const int defbase_sel_tot, + const int draw_flag) { float input = 0.0f; int make_black = FALSE; - if ((selected > 1) && (draw_flag & CALC_WP_MULTIPAINT)) { + if ((defbase_sel_tot > 1) && (draw_flag & CALC_WP_MULTIPAINT)) { int was_a_nonzero = FALSE; unsigned int i; @@ -1031,7 +1032,7 @@ static void calc_weightpaint_vert_color( /* in multipaint, get the average if auto normalize is inactive * get the sum if it is active */ if (dw->def_nr < defbase_tot) { - if (dg_flags[dw->def_nr]) { + if (defbase_sel[dw->def_nr]) { if (dw->weight) { input += dw->weight; was_a_nonzero = TRUE; @@ -1045,7 +1046,7 @@ static void calc_weightpaint_vert_color( make_black = TRUE; } else if ((draw_flag & CALC_WP_AUTO_NORMALIZE) == FALSE) { - input /= selected; /* get the average */ + input /= defbase_sel_tot; /* get the average */ } } else { @@ -1090,14 +1091,21 @@ static unsigned char *calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, i /* variables for multipaint */ const int defbase_tot = BLI_countlist(&ob->defbase); const int defbase_act = ob->actdef - 1; - char *dg_flags = MEM_mallocN(defbase_tot * sizeof(char), __func__); - const int selected = get_selected_defgroups(ob, dg_flags, defbase_tot); - for (i = numVerts; i != 0; i--, wc += 4, dv++) { - calc_weightpaint_vert_color(wc, dv, coba, defbase_tot, defbase_act, dg_flags, selected, draw_flag); + int defbase_sel_tot = 0; + char *defbase_sel = NULL; + + if (draw_flag & CALC_WP_MULTIPAINT) { + defbase_sel = BKE_objdef_selected_get(ob, defbase_tot, &defbase_sel_tot); } - MEM_freeN(dg_flags); + for (i = numVerts; i != 0; i--, wc += 4, dv++) { + calc_weightpaint_vert_color(wc, dv, coba, defbase_tot, defbase_act, defbase_sel, defbase_sel_tot, draw_flag); + } + + if (defbase_sel) { + MEM_freeN(defbase_sel); + } } else { int col_i; diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index aa834ff131b..b87342f85fa 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -2517,36 +2517,6 @@ void BKE_pose_where_is(Scene *scene, Object *ob) } } - -/* Returns total selected vgroups, - * wpi.defbase_sel is assumed malloc'd, all values are set */ -int get_selected_defgroups(Object *ob, char *dg_selection, int defbase_tot) -{ - bDeformGroup *defgroup; - unsigned int i; - Object *armob = BKE_object_pose_armature_get(ob); - int dg_flags_sel_tot = 0; - - if (armob) { - bPose *pose = armob->pose; - for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) { - bPoseChannel *pchan = BKE_pose_channel_find_name(pose, defgroup->name); - if (pchan && (pchan->bone->flag & BONE_SELECTED)) { - dg_selection[i] = TRUE; - dg_flags_sel_tot++; - } - else { - dg_selection[i] = FALSE; - } - } - } - else { - memset(dg_selection, FALSE, sizeof(char) * defbase_tot); - } - - return dg_flags_sel_tot; -} - /************** Bounding box ********************/ static int minmax_armature(Object *ob, float r_min[3], float r_max[3]) { diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 547a64a70d4..4110d4565b2 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "MEM_guardedalloc.h" @@ -41,7 +42,10 @@ #include "BKE_deform.h" -#include "BLI_blenlib.h" +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_path_util.h" +#include "BLI_string.h" #include "BLI_utildefines.h" @@ -204,13 +208,15 @@ void defvert_normalize(MDeformVert *dvert) } } -void defvert_normalize_lock(MDeformVert *dvert, const int def_nr_lock) +void defvert_normalize_lock_single(MDeformVert *dvert, const int def_nr_lock) { if (dvert->totweight <= 0) { /* nothing */ } else if (dvert->totweight == 1) { - dvert->dw[0].weight = 1.0f; + if (def_nr_lock != 0) { + dvert->dw[0].weight = 1.0f; + } } else { MDeformWeight *dw_lock = NULL; @@ -246,6 +252,50 @@ void defvert_normalize_lock(MDeformVert *dvert, const int def_nr_lock) } } +void defvert_normalize_lock_map(MDeformVert *dvert, const char *lock_flags, const int defbase_tot) +{ + if (dvert->totweight <= 0) { + /* nothing */ + } + else if (dvert->totweight == 1) { + if (LIKELY(defbase_tot >= 1) && lock_flags[0]) { + dvert->dw[0].weight = 1.0f; + } + } + else { + MDeformWeight *dw; + unsigned int i; + float tot_weight = 0.0f; + float lock_iweight = 0.0f; + + for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { + if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) { + tot_weight += dw->weight; + } + else { + /* invert after */ + lock_iweight += dw->weight; + } + } + + lock_iweight = maxf(0.0f, 1.0f - lock_iweight); + + if (tot_weight > 0.0f) { + /* paranoid, should be 1.0 but in case of float error clamp anyway */ + + float scalar = (1.0f / tot_weight) * lock_iweight; + for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { + if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) { + dw->weight *= scalar; + + /* in case of division errors with very low weights */ + CLAMP(dw->weight, 0.0f, 1.0f); + } + } + } + } +} + void defvert_flip(MDeformVert *dvert, const int *flip_map, const int flip_map_len) { MDeformWeight *dw; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 987963273bb..a0839a502b7 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2548,7 +2548,9 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ dither = iuser->scene->r.dither_intensity; /* combined layer gets added as first layer */ - if (rres.have_combined && layer == 0) ; + if (rres.have_combined && layer == 0) { + /* pass */ + } else if (rres.layers.first) { RenderLayer *rl = BLI_findlink(&rres.layers, layer - (rres.have_combined ? 1 : 0)); if (rl) { diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c new file mode 100644 index 00000000000..7f9578250f2 --- /dev/null +++ b/source/blender/blenkernel/intern/object_deform.c @@ -0,0 +1,156 @@ +/* + * ***** 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. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/object_deform.c + * \ingroup bke + */ + +#include +#include + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_ghash.h" + +#include "BKE_action.h" +#include "BKE_object_deform.h" /* own include */ +#include "BKE_object.h" +#include "BKE_modifier.h" + +#include "DNA_armature_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" + +/* --- functions for getting vgroup aligned maps --- */ + +/** + * gets the status of "flag" for each bDeformGroup + * in ob->defbase and returns an array containing them + */ +char *BKE_objdef_lock_flags_get(Object *ob, const int defbase_tot) +{ + char is_locked = FALSE; + int i; + //int defbase_tot = BLI_countlist(&ob->defbase); + char *lock_flags = MEM_mallocN(defbase_tot * sizeof(char), "defflags"); + bDeformGroup *defgroup; + + for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) { + lock_flags[i] = ((defgroup->flag & DG_LOCK_WEIGHT) != 0); + is_locked |= lock_flags[i]; + } + if (is_locked) { + return lock_flags; + } + + MEM_freeN(lock_flags); + return NULL; +} + +char *BKE_objdef_validmap_get(Object *ob, const int defbase_tot) +{ + bDeformGroup *dg; + ModifierData *md; + char *vgroup_validmap; + GHash *gh; + int i, step1 = 1; + //int defbase_tot = BLI_countlist(&ob->defbase); + + if (ob->defbase.first == NULL) { + return NULL; + } + + gh = BLI_ghash_str_new("BKE_objdef_validmap_get gh"); + + /* add all names to a hash table */ + for (dg = ob->defbase.first; dg; dg = dg->next) { + BLI_ghash_insert(gh, dg->name, NULL); + } + + BLI_assert(BLI_ghash_size(gh) == defbase_tot); + + /* now loop through the armature modifiers and identify deform bones */ + for (md = ob->modifiers.first; md; md = !md->next && step1 ? (step1 = 0), modifiers_getVirtualModifierList(ob) : md->next) { + if (!(md->mode & (eModifierMode_Realtime | eModifierMode_Virtual))) + continue; + + if (md->type == eModifierType_Armature) { + ArmatureModifierData *amd = (ArmatureModifierData *) md; + + if (amd->object && amd->object->pose) { + bPose *pose = amd->object->pose; + bPoseChannel *chan; + + for (chan = pose->chanbase.first; chan; chan = chan->next) { + if (chan->bone->flag & BONE_NO_DEFORM) + continue; + + if (BLI_ghash_remove(gh, chan->name, NULL, NULL)) { + BLI_ghash_insert(gh, chan->name, SET_INT_IN_POINTER(1)); + } + } + } + } + } + + vgroup_validmap = MEM_mallocN(defbase_tot, "wpaint valid map"); + + /* add all names to a hash table */ + for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) { + vgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != NULL); + } + + BLI_assert(i == BLI_ghash_size(gh)); + + BLI_ghash_free(gh, NULL, NULL); + + return vgroup_validmap; +} + +/* Returns total selected vgroups, + * wpi.defbase_sel is assumed malloc'd, all values are set */ +char *BKE_objdef_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot) +{ + char *dg_selection = MEM_mallocN(defbase_tot * sizeof(char), __func__); + bDeformGroup *defgroup; + unsigned int i; + Object *armob = BKE_object_pose_armature_get(ob); + (*r_dg_flags_sel_tot) = 0; + + if (armob) { + bPose *pose = armob->pose; + for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) { + bPoseChannel *pchan = BKE_pose_channel_find_name(pose, defgroup->name); + if (pchan && (pchan->bone->flag & BONE_SELECTED)) { + dg_selection[i] = TRUE; + (*r_dg_flags_sel_tot) += 1; + } + else { + dg_selection[i] = FALSE; + } + } + } + else { + memset(dg_selection, FALSE, sizeof(char) * defbase_tot); + } + + return dg_selection; +} diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c index 0a195210e38..6028b40756d 100644 --- a/source/blender/blenkernel/intern/seqmodifier.c +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -154,14 +154,11 @@ void colorBalance_init_data(SequenceModifierData *smd) } } -ImBuf *colorBalance_apply(SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) +void colorBalance_apply(SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) { ColorBalanceModifierData *cbmd = (ColorBalanceModifierData *) smd; - ImBuf *ibuf_new = IMB_dupImBuf(ibuf); - BKE_sequencer_color_balance_apply(&cbmd->color_balance, ibuf_new, cbmd->color_multiply, FALSE, mask); - - return ibuf_new; + BKE_sequencer_color_balance_apply(&cbmd->color_balance, ibuf, cbmd->color_multiply, FALSE, mask); } static SequenceModifierTypeInfo seqModifier_ColorBalance = { @@ -252,10 +249,9 @@ void curves_apply_threaded(int width, int height, unsigned char *rect, float *re } } -ImBuf *curves_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) +void curves_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) { CurvesModifierData *cmd = (CurvesModifierData *) smd; - ImBuf *ibuf_new = IMB_dupImBuf(ibuf); float black[3] = {0.0f, 0.0f, 0.0f}; float white[3] = {1.0f, 1.0f, 1.0f}; @@ -265,11 +261,9 @@ ImBuf *curves_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) curvemapping_premultiply(&cmd->curve_mapping, 0); curvemapping_set_black_white(&cmd->curve_mapping, black, white); - modifier_apply_threaded(ibuf_new, mask, curves_apply_threaded, &cmd->curve_mapping); + modifier_apply_threaded(ibuf, mask, curves_apply_threaded, &cmd->curve_mapping); curvemapping_premultiply(&cmd->curve_mapping, 1); - - return ibuf_new; } static SequenceModifierTypeInfo seqModifier_Curves = { @@ -371,16 +365,13 @@ void hue_correct_apply_threaded(int width, int height, unsigned char *rect, floa } } -ImBuf *hue_correct_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) +void hue_correct_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) { HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd; - ImBuf *ibuf_new = IMB_dupImBuf(ibuf); curvemapping_initialize(&hcmd->curve_mapping); - modifier_apply_threaded(ibuf_new, mask, hue_correct_apply_threaded, &hcmd->curve_mapping); - - return ibuf_new; + modifier_apply_threaded(ibuf, mask, hue_correct_apply_threaded, &hcmd->curve_mapping); } static SequenceModifierTypeInfo seqModifier_HueCorrect = { @@ -469,18 +460,15 @@ void brightcontrast_apply_threaded(int width, int height, unsigned char *rect, f } } -ImBuf *brightcontrast_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) +void brightcontrast_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) { BrightContrastModifierData *bcmd = (BrightContrastModifierData *) smd; BrightContrastThreadData data; - ImBuf *ibuf_new = IMB_dupImBuf(ibuf); data.bright = bcmd->bright; data.contrast = bcmd->contrast; - modifier_apply_threaded(ibuf_new, mask, brightcontrast_apply_threaded, &data); - - return ibuf_new; + modifier_apply_threaded(ibuf, mask, brightcontrast_apply_threaded, &data); } static SequenceModifierTypeInfo seqModifier_BrightContrast = { @@ -595,7 +583,6 @@ ImBuf *BKE_sequence_modifier_apply_stack(SeqRenderData context, Sequence *seq, I for (smd = seq->modifiers.first; smd; smd = smd->next) { SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); - ImBuf *ibuf_new; /* could happen if modifier is being removed or not exists in current version of blender */ if (!smti) @@ -611,12 +598,7 @@ ImBuf *BKE_sequence_modifier_apply_stack(SeqRenderData context, Sequence *seq, I if (processed_ibuf == ibuf) processed_ibuf = IMB_dupImBuf(ibuf); - ibuf_new = smti->apply(smd, processed_ibuf, mask); - - if (ibuf_new != processed_ibuf) { - IMB_freeImBuf(processed_ibuf); - processed_ibuf = ibuf_new; - } + smti->apply(smd, processed_ibuf, mask); if (mask) IMB_freeImBuf(mask); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 9aaa9fd79e8..0ac0db50fb5 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -166,9 +166,6 @@ static void seq_free_strip(Strip *strip) if (strip->transform) { MEM_freeN(strip->transform); } - if (strip->color_balance) { - MEM_freeN(strip->color_balance); - } MEM_freeN(strip); } @@ -1671,26 +1668,6 @@ void BKE_sequencer_color_balance_apply(StripColorBalance *cb, ImBuf *ibuf, float imb_freerectImBuf(ibuf); } -static void sequence_color_balance(SeqRenderData context, Sequence *seq, ImBuf *ibuf, float mul, int cfra) -{ - StripColorBalance *cb = seq->strip->color_balance; - ImBuf *mask_input = NULL; - short make_float = seq->flag & SEQ_MAKE_FLOAT; - - if (seq->mask_sequence) { - if (seq->mask_sequence != seq && !BKE_sequence_check_depend(seq, seq->mask_sequence)) { - int make_float = ibuf->rect_float != NULL; - - mask_input = BKE_sequencer_render_mask_input(context, SEQUENCE_MASK_INPUT_STRIP, seq->mask_sequence, NULL, cfra, make_float); - } - } - - BKE_sequencer_color_balance_apply(cb, ibuf, mul, make_float, mask_input); - - if (mask_input) - IMB_freeImBuf(mask_input); -} - /* * input preprocessing for SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_MOVIECLIP and SEQ_TYPE_SCENE * @@ -1713,9 +1690,7 @@ int BKE_sequencer_input_have_to_preprocess(SeqRenderData UNUSED(context), Sequen { float mul; - if (seq->flag & (SEQ_FILTERY | SEQ_USE_CROP | SEQ_USE_TRANSFORM | SEQ_FLIPX | - SEQ_FLIPY | SEQ_USE_COLOR_BALANCE | SEQ_MAKE_PREMUL | SEQ_MAKE_FLOAT)) - { + if (seq->flag & (SEQ_FILTERY | SEQ_USE_CROP | SEQ_USE_TRANSFORM | SEQ_FLIPX | SEQ_FLIPY | SEQ_MAKE_PREMUL | SEQ_MAKE_FLOAT)) { return TRUE; } @@ -1834,11 +1809,6 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, mul *= seq->blend_opacity / 100.0f; } - if (seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) { - sequence_color_balance(context, seq, ibuf, mul, cfra); - mul = 1.0; - } - if (seq->flag & SEQ_MAKE_FLOAT) { if (!ibuf->rect_float) { IMB_colormanagement_imbuf_to_sequencer_space(ibuf, TRUE); @@ -4020,10 +3990,6 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup seqn->strip->proxy->anim = NULL; } - if (seq->strip->color_balance) { - seqn->strip->color_balance = MEM_dupallocN(seq->strip->color_balance); - } - if (seqn->modifiers.first) { seqn->modifiers.first = seqn->modifiers.last = NULL; diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index fd755943e70..2836174be73 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -147,6 +147,7 @@ set(SRC BLI_utildefines.h BLI_uvproject.h BLI_vfontdata.h + BLI_voronoi.h BLI_voxel.h BLI_winstuff.h PIL_time.h diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 1021d2a794d..04c9d96ea0f 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4959,7 +4959,6 @@ static void direct_link_scene(FileData *fd, Scene *sce) seq->seq1= newdataadr(fd, seq->seq1); seq->seq2= newdataadr(fd, seq->seq2); seq->seq3= newdataadr(fd, seq->seq3); - seq->mask_sequence= newdataadr(fd, seq->mask_sequence); /* a patch: after introduction of effects with 3 input strips */ if (seq->seq3 == NULL) seq->seq3 = seq->seq2; @@ -5005,16 +5004,9 @@ static void direct_link_scene(FileData *fd, Scene *sce) else { seq->strip->proxy = NULL; } - if (seq->flag & SEQ_USE_COLOR_BALANCE) { - seq->strip->color_balance = newdataadr( - fd, seq->strip->color_balance); - } - else { - seq->strip->color_balance = NULL; - } - if (seq->strip->color_balance) { - // seq->strip->color_balance->gui = 0; // XXX - peter, is this relevant in 2.5? - } + + /* need to load color balance to it could be converted to modifier */ + seq->strip->color_balance = newdataadr(fd, seq->strip->color_balance); } direct_link_sequence_modifiers(fd, &seq->modifiers); @@ -7888,6 +7880,42 @@ static void do_versions(FileData *fd, Library *lib, Main *main) ntreetype->foreach_nodetree(main, NULL, do_version_ntree_mask_264); } + if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 18)) { + Scene *scene; + + for (scene = main->scene.first; scene; scene = scene->id.next) { + if (scene->ed) { + Sequence *seq; + + SEQ_BEGIN (scene->ed, seq) + { + Strip *strip = seq->strip; + + if (strip && strip->color_balance) { + SequenceModifierData *smd; + ColorBalanceModifierData *cbmd; + + smd = BKE_sequence_modifier_new(seq, NULL, seqModifierType_ColorBalance); + cbmd = (ColorBalanceModifierData *) smd; + + cbmd->color_balance = *strip->color_balance; + + /* multiplication with color balance used is handled differently, + * so we need to move multiplication to modifier so files would be + * compatible + */ + cbmd->color_multiply = seq->mul; + seq->mul = 1.0f; + + MEM_freeN(strip->color_balance); + strip->color_balance = NULL; + } + } + SEQ_END + } + } + } + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */ @@ -9443,9 +9471,9 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) cleanup_path(G.main->name, mainptr->curlib->filepath); fd = blo_openblenderfile(mainptr->curlib->filepath, basefd->reports); - fd->mainlist = mainlist; - + if (fd) { + fd->mainlist = mainlist; printf("found: '%s', party on macuno!\n", mainptr->curlib->filepath); } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index f8b3a548345..109a844352f 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2214,9 +2214,6 @@ static void write_scenes(WriteData *wd, ListBase *scebase) if (seq->flag & SEQ_USE_PROXY && strip->proxy) { writestruct(wd, DATA, "StripProxy", 1, strip->proxy); } - if (seq->flag & SEQ_USE_COLOR_BALANCE && strip->color_balance) { - writestruct(wd, DATA, "StripColorBalance", 1, strip->color_balance); - } if (seq->type==SEQ_TYPE_IMAGE) writestruct(wd, DATA, "StripElem", MEM_allocN_len(strip->stripdata) / sizeof(struct StripElem), strip->stripdata); else if (seq->type==SEQ_TYPE_MOVIE || seq->type==SEQ_TYPE_SOUND_RAM || seq->type == SEQ_TYPE_SOUND_HD) diff --git a/source/blender/compositor/COM_compositor.h b/source/blender/compositor/COM_compositor.h index d9cfae8edb9..e6efd77f8b2 100644 --- a/source/blender/compositor/COM_compositor.h +++ b/source/blender/compositor/COM_compositor.h @@ -301,9 +301,16 @@ void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering); /** * @brief Deinitialize the compositor caches and allocated memory. + * Use COM_clearCaches to only free the caches. */ void COM_deinitialize(void); +/** + * @brief Clear all compositor caches. (Compositor system will still remain available). + * To deinitialize the compositor use the COM_deinitialize method. + */ +void COM_clearCaches(void); + /** * @brief Return a list of highlighted bnodes pointers. * @return diff --git a/source/blender/compositor/intern/COM_Device.h b/source/blender/compositor/intern/COM_Device.h index e33a2a4288f..dc39b2baca7 100644 --- a/source/blender/compositor/intern/COM_Device.h +++ b/source/blender/compositor/intern/COM_Device.h @@ -31,7 +31,14 @@ * work are packaged as a WorkPackage instance. */ class Device { + public: + /** + * @brief Declaration of the virtual destructor + * @note resolve warning gcc 4.7 + */ + virtual ~Device() {} + /** * @brief initialize the device */ diff --git a/source/blender/compositor/intern/COM_Node.cpp b/source/blender/compositor/intern/COM_Node.cpp index 320baacb669..50393d14f35 100644 --- a/source/blender/compositor/intern/COM_Node.cpp +++ b/source/blender/compositor/intern/COM_Node.cpp @@ -137,6 +137,21 @@ void Node::addSetVectorOperation(ExecutionSystem *graph, InputSocket *inputsocke graph->addOperation(operation); } +/* when a node has no valid data (missing image or group pointer) */ +void Node::convertToOperations_invalid(ExecutionSystem *graph, CompositorContext *context) +{ + /* this is a really bad situation - bring on the pink! - so artists know this is bad */ + const float warning_color[4] = {1.0f, 0.0f, 1.0f, 1.0f}; + int index; + vector &outputsockets = this->getOutputSockets(); + for (index = 0; index < outputsockets.size(); index++) { + SetColorOperation *operation = new SetColorOperation(); + this->getOutputSocket(index)->relinkConnections(operation->getOutputSocket()); + operation->setChannels(warning_color); + graph->addOperation(operation); + } +} + bNodeSocket *Node::getEditorInputSocket(int editorNodeInputSocketIndex) { bNodeSocket *bSock = (bNodeSocket *)this->getbNode()->inputs.first; diff --git a/source/blender/compositor/intern/COM_Node.h b/source/blender/compositor/intern/COM_Node.h index e19b1d774c9..7ce40e3cb34 100644 --- a/source/blender/compositor/intern/COM_Node.h +++ b/source/blender/compositor/intern/COM_Node.h @@ -99,6 +99,13 @@ public: */ void addSetVectorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex); + /** + * when a node has no valid data (missing image or a group nodes ID pointer is NULL) + * call this function from #convertToOperations, this way the node sockets are converted + * into valid outputs, without this the compositor system gets confused and crashes, see [#32490] + */ + void convertToOperations_invalid(ExecutionSystem *graph, CompositorContext *context); + /** * Creates a new link between an outputSocket and inputSocket and registrates the link to the graph * @return the new created link diff --git a/source/blender/compositor/intern/COM_NodeBase.h b/source/blender/compositor/intern/COM_NodeBase.h index 3c390f6bcdb..b55e444be80 100644 --- a/source/blender/compositor/intern/COM_NodeBase.h +++ b/source/blender/compositor/intern/COM_NodeBase.h @@ -71,13 +71,14 @@ protected: inline vector& getOutputSockets() { return this->m_outputsockets; } -public: +protected: /** * @brief destructor * clean up memory related to this NodeBase. */ virtual ~NodeBase(); +public: /** * @brief get the reference to the SDNA bNode struct */ diff --git a/source/blender/compositor/intern/COM_Socket.h b/source/blender/compositor/intern/COM_Socket.h index 2aebe262594..bad112d20c7 100644 --- a/source/blender/compositor/intern/COM_Socket.h +++ b/source/blender/compositor/intern/COM_Socket.h @@ -62,6 +62,14 @@ private: DataType m_datatype; bNodeSocket *m_editorSocket; + +protected: + /** + * @brief Declaration of the virtual destructor + * @note resolve warning gcc 4.7 + */ + virtual ~Socket() {} + public: Socket(DataType datatype); diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp index f9af23faea8..78e198ac9c2 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.cpp +++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp @@ -103,7 +103,13 @@ void **g_highlightedNodesRead; void COM_startReadHighlights() { - if (g_highlightedNodesRead) { + if (!g_highlightInitialized) + { + return; + } + + if (g_highlightedNodesRead) + { MEM_freeN(g_highlightedNodesRead); } @@ -114,11 +120,15 @@ void COM_startReadHighlights() int COM_isHighlightedbNode(bNode *bnode) { + if (!g_highlightInitialized) { + return false; + } + if (!g_highlightedNodesRead) { return false; } - for (int i = 0 ; i < MAX_HIGHLIGHT; i++) { + for (int i = 0; i < MAX_HIGHLIGHT; i++) { void *p = g_highlightedNodesRead[i]; if (!p) return false; if (p == bnode) return true; @@ -397,13 +407,16 @@ void WorkScheduler::deinitialize() /* deinitialize highlighting */ if (g_highlightInitialized) { - if (g_highlightedNodes) - MEM_freeN(g_highlightedNodes); - - if (g_highlightedNodesRead) - MEM_freeN(g_highlightedNodesRead); - g_highlightInitialized = false; + if (g_highlightedNodes) { + MEM_freeN(g_highlightedNodes); + g_highlightedNodes = NULL; + } + + if (g_highlightedNodesRead) { + MEM_freeN(g_highlightedNodesRead); + g_highlightedNodesRead = NULL; + } } } diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp index daf48d65caf..cb9166c929d 100644 --- a/source/blender/compositor/intern/COM_compositor.cpp +++ b/source/blender/compositor/intern/COM_compositor.cpp @@ -37,6 +37,11 @@ extern "C" { static ThreadMutex s_compositorMutex; static char is_compositorMutex_init = FALSE; +void intern_freeCompositorCaches() +{ + deintializeDistortionCache(); +} + void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering) { /* initialize mutex, TODO this mutex init is actually not thread safe and @@ -63,7 +68,7 @@ void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering) /* set progress bar to 0% and status to init compositing */ editingtree->progress(editingtree->prh, 0.0); - bool twopass = (editingtree->flag&NTREE_TWO_PASS) > 0 && !rendering; + bool twopass = (editingtree->flag & NTREE_TWO_PASS) > 0 && !rendering; /* initialize execution system */ if (twopass) { ExecutionSystem *system = new ExecutionSystem(rd, editingtree, rendering, twopass); @@ -86,14 +91,21 @@ void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering) BLI_mutex_unlock(&s_compositorMutex); } +void COM_freeCaches() +{ + if (is_compositorMutex_init) { + BLI_mutex_lock(&s_compositorMutex); + intern_freeCompositorCaches(); + BLI_mutex_unlock(&s_compositorMutex); + } +} + void COM_deinitialize() { if (is_compositorMutex_init) { BLI_mutex_lock(&s_compositorMutex); - - deintializeDistortionCache(); + intern_freeCompositorCaches(); WorkScheduler::deinitialize(); - is_compositorMutex_init = FALSE; BLI_mutex_unlock(&s_compositorMutex); BLI_mutex_end(&s_compositorMutex); diff --git a/source/blender/compositor/nodes/COM_GroupNode.cpp b/source/blender/compositor/nodes/COM_GroupNode.cpp index b1bc0966687..e10d7dbad2e 100644 --- a/source/blender/compositor/nodes/COM_GroupNode.cpp +++ b/source/blender/compositor/nodes/COM_GroupNode.cpp @@ -33,16 +33,7 @@ GroupNode::GroupNode(bNode *editorNode) : Node(editorNode) void GroupNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) { if (this->getbNode()->id == NULL) { - /* this is a really bad situation - bring on the pink! - so artists know this is bad */ - const float warning_color[4] = {1.0f, 0.0f, 1.0f, 1.0f}; - int index; - vector &outputsockets = this->getOutputSockets(); - for (index = 0; index < outputsockets.size(); index++) { - SetColorOperation *operation = new SetColorOperation(); - this->getOutputSocket(index)->relinkConnections(operation->getOutputSocket()); - operation->setChannels(warning_color); - graph->addOperation(operation); - } + convertToOperations_invalid(graph, context); } } diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp index addde140b9f..2d13ffb82b6 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.cpp +++ b/source/blender/compositor/nodes/COM_ImageNode.cpp @@ -72,12 +72,16 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c /* force a load, we assume iuser index will be set OK anyway */ if (image && image->type == IMA_TYPE_MULTILAYER) { + bool is_multilayer_ok = false; BKE_image_get_ibuf(image, imageuser); if (image->rr) { RenderLayer *rl = (RenderLayer *)BLI_findlink(&image->rr->layers, imageuser->layer); if (rl) { OutputSocket *socket; int index; + + is_multilayer_ok = true; + for (index = 0; index < numberOfOutputs; index++) { socket = this->getOutputSocket(index); if (socket->isConnected() || index == 0) { @@ -114,6 +118,11 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c } } } + + /* without this, multilayer that fail to load will crash blender [#32490] */ + if (is_multilayer_ok == false) { + convertToOperations_invalid(graph, context); + } } else { if (numberOfOutputs > 0) { diff --git a/source/blender/compositor/operations/COM_CompositorOperation.h b/source/blender/compositor/operations/COM_CompositorOperation.h index ae94e974db0..c1d91c16a3c 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.h +++ b/source/blender/compositor/operations/COM_CompositorOperation.h @@ -31,6 +31,9 @@ */ class CompositorOperation : public NodeOperation { private: + /** + * @brief Scene name, used for getting the render output, includes 'SC' prefix. + */ char m_sceneName[MAX_ID_NAME]; /** diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 2dbaa2998e3..12ab4166bc8 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -745,7 +745,9 @@ void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv); void uiLayoutSetContextPointer(uiLayout *layout, const char *name, struct PointerRNA *ptr); void uiLayoutContextCopy(uiLayout *layout, struct bContextStore *context); const char *uiLayoutIntrospect(uiLayout *layout); // XXX - testing -void uiLayoutOperatorButs(const struct bContext *C, struct uiLayout *layout, struct wmOperator *op, int (*check_prop)(struct PointerRNA *, struct PropertyRNA *), const char label_align, const short flag); +void uiLayoutOperatorButs(const struct bContext *C, struct uiLayout *layout, struct wmOperator *op, + int (*check_prop)(struct PointerRNA *, struct PropertyRNA *), + const char label_align, const short flag); struct MenuType *uiButGetMenuType(uiBut *but); void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index ffce2b618a3..f97b9864539 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -3722,8 +3722,14 @@ void uiButGetStrInfo(bContext *C, uiBut *but, int nbr, ...) if (type == BUT_GET_LABEL) { if (but->str) { - /* Menu labels can have some complex formating stuff marked by pipes, we don't want those here! */ - char *tc = strchr(but->str, '|'); + /* Menu labels can have some complex formating stuff marked by pipes or %t, we don't want those here! */ + const char *tc; + + if (but->type == MENU) + tc = strstr(but->str, "%t"); + else + tc = strchr(but->str, '|'); + if (tc) tmp = BLI_strdupn(but->str, tc - but->str); else diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index b68e14898d0..803fd928085 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -2837,7 +2837,9 @@ static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), void *op_pt, } /* this function does not initialize the layout, functions can be called on the layout before and after */ -void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op, int (*check_prop)(struct PointerRNA *, struct PropertyRNA *), const char label_align, const short flag) +void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op, + int (*check_prop)(struct PointerRNA *, struct PropertyRNA *), + const char label_align, const short flag) { if (!op->properties) { IDPropertyTemplate val = {0}; diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 67c0d04a79f..e8b8959fd43 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -908,19 +908,19 @@ static void UI_OT_editsource(wmOperatorType *ot) void edittranslation_find_po_file(const char *root, const char *uilng, char *path, const size_t maxlen) { - char t[32]; /* Should be more than enough! */ + char tstr[32]; /* Should be more than enough! */ /* First, full lang code. */ - sprintf(t, "%s.po", uilng); + BLI_snprintf(tstr, sizeof(tstr), "%s.po", uilng); BLI_join_dirfile(path, maxlen, root, uilng); - BLI_join_dirfile(path, maxlen, path, t); + BLI_join_dirfile(path, maxlen, path, tstr); if (BLI_is_file(path)) return; /* Now try without the second iso code part (_ES in es_ES). */ - strncpy(t, uilng, 2); - strcpy(t + 2, uilng + 5); /* Because of some codes like sr_SR@latin... */ - BLI_join_dirfile(path, maxlen, root, t); - sprintf(t, "%s.po", t); - BLI_join_dirfile(path, maxlen, path, t); + strncpy(tstr, uilng, 2); + BLI_strncpy(tstr + 2, uilng + 5, sizeof(tstr) - 2); /* Because of some codes like sr_SR@latin... */ + BLI_join_dirfile(path, maxlen, root, tstr); + strcat(tstr, ".po"); + BLI_join_dirfile(path, maxlen, path, tstr); if (BLI_is_file(path)) return; path[0] = '\0'; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 9aaafe28377..543ac18801c 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1024,7 +1024,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, xco + 10, yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); if (con->flag & CONSTRAINT_DISABLE) - uiLayoutSetRedAlert(row, 1); + uiLayoutSetRedAlert(row, TRUE); if (proxy_protected == 0) { uiItemR(row, &ptr, "name", 0, "", ICON_NONE); @@ -1032,7 +1032,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) else uiItemL(row, con->name, ICON_NONE); - uiLayoutSetRedAlert(row, 0); + uiLayoutSetRedAlert(row, FALSE); /* proxy-protected constraints cannot be edited, so hide up/down + close buttons */ if (proxy_protected) { @@ -1200,7 +1200,7 @@ void uiTemplatePreview(uiLayout *layout, ID *id, int show_buttons, ID *parent, M block = uiLayoutGetBlock(layout); row = uiLayoutRow(layout, FALSE); col = uiLayoutColumn(row, FALSE); - uiLayoutSetKeepAspect(col, 1); + uiLayoutSetKeepAspect(col, TRUE); /* add preview */ uiDefBut(block, BUT_EXTRA, 0, "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, pid, 0.0, 0.0, 0, 0, ""); @@ -1894,7 +1894,7 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe } if (cmp) { - uiLayoutColumn(layout, TRUE); + uiLayoutRow(layout, TRUE); uiBlockSetNFunc(block, curvemap_buttons_update, NULL, cumap); uiDefButF(block, NUM, 0, "X", 0, 2 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, &cmp->x, 0.0f, 1.0f, 1, 5, ""); uiDefButF(block, NUM, 0, "Y", 0, 1 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, &cmp->y, 0.0f, 1.0f, 1, 5, ""); @@ -2205,7 +2205,7 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe row = uiLayoutRow(split, TRUE); if (i == 0 || (key->type != KEY_RELATIVE)) uiItemL(row, "", ICON_NONE); else uiItemR(row, itemptr, "value", 0, "", ICON_NONE); - uiItemR(row, itemptr, "mute", 0, "", 0); + uiItemR(row, itemptr, "mute", 0, "", ICON_NONE); if ((kb->flag & KEYBLOCK_MUTE) || (ob->mode == OB_MODE_EDIT && !((ob->shapeflag & OB_SHAPE_EDIT_MODE) && ob->type == OB_MESH))) @@ -2274,9 +2274,9 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe uiBlockSetEmboss(block, UI_EMBOSSN); row = uiLayoutRow(split, TRUE); uiItemR(row, itemptr, "alpha", 0, "", ICON_NONE); - uiItemR(row, itemptr, "hide", 0, "", 0); - uiItemR(row, itemptr, "hide_select", 0, "", 0); - uiItemR(row, itemptr, "hide_render", 0, "", 0); + uiItemR(row, itemptr, "hide", 0, "", ICON_NONE); + uiItemR(row, itemptr, "hide_select", 0, "", ICON_NONE); + uiItemR(row, itemptr, "hide_render", 0, "", ICON_NONE); uiBlockSetEmboss(block, UI_EMBOSS); } @@ -2321,7 +2321,7 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe while (id < prop_names_end) { if ((id_next = strchr(id, ':'))) *id_next++ = '\0'; else id_next = prop_names_end; - uiItemR(row, itemptr, id, 0, NULL, 0); + uiItemR(row, itemptr, id, 0, NULL, ICON_NONE); id = id_next; } MEM_freeN(prop_names); diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index d0ce3f0cace..0e6b8f77528 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -152,10 +152,10 @@ void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) /* Export Options: */ box = uiLayoutBox(layout); - row = uiLayoutRow(box, 0); + row = uiLayoutRow(box, FALSE); uiItemL(row, IFACE_("Export Data Options:"), ICON_MESH_DATA); - row = uiLayoutRow(box, 0); + row = uiLayoutRow(box, FALSE); split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT); col = uiLayoutColumn(split, FALSE); uiItemR(col, imfptr, "apply_modifiers", 0, NULL, ICON_NONE); diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 8f08c3afc36..7ecfb712c18 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -555,7 +555,7 @@ static int verge_linehit(const void *vlh1, const void *vlh2) } /* If there's a linehit connected (same face) as testi in range [firsti, lasti], return the first such, else -1. - * If testi is out of range, look for connection to f instead, if f is non-NULL */ + * If testi is out of range, look for connection to f instead, if f is non-NULL */ static int find_connected_linehit(KnifeTool_OpData *kcd, int testi, BMFace *f, int firsti, int lasti) { int i; @@ -563,9 +563,10 @@ static int find_connected_linehit(KnifeTool_OpData *kcd, int testi, BMFace *f, i for (i = firsti; i <= lasti; i++) { if (testi >= 0 && testi < kcd->totlinehit) { if (knife_find_common_face(&kcd->linehits[testi].kfe->faces, - &kcd->linehits[i].kfe->faces)) + &kcd->linehits[i].kfe->faces)) return i; - } else if (f) { + } + else if (f) { if (find_ref(&kcd->linehits[i].kfe->faces, f)) return i; } @@ -582,9 +583,9 @@ static void knife_sort_linehits(KnifeTool_OpData *kcd) /* for ranges of equal "l", swap if neccesary to make predecessor and * successor faces connected to the linehits at either end of the range */ - for (i = 0; i < kcd->totlinehit -1; i = nexti) { + for (i = 0; i < kcd->totlinehit - 1; i = nexti) { for (j = i + 1; j < kcd->totlinehit; j++) { - if (fabsf(kcd->linehits[j].l - kcd->linehits[i].l) > 80*FLT_EPSILON) + if (fabsf(kcd->linehits[j].l - kcd->linehits[i].l) > 80 * FLT_EPSILON) break; } nexti = j; diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index b13a299c4c7..c8ba9240db3 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -62,6 +62,7 @@ #include "BKE_tessmesh.h" #include "BKE_report.h" #include "BKE_DerivedMesh.h" +#include "BKE_object_deform.h" #include "RNA_access.h" #include "RNA_define.h" @@ -1136,7 +1137,6 @@ static void vgroup_levels(Object *ob, float offset, float gain) } } -/* TODO - select between groups */ static void vgroup_normalize_all(Object *ob, int lock_active) { MDeformVert *dv, **dvert_array = NULL; @@ -1152,27 +1152,33 @@ static void vgroup_normalize_all(Object *ob, int lock_active) ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, use_vert_sel); if (dvert_array) { - if (lock_active) { + const int defbase_tot = BLI_countlist(&ob->defbase); + char *lock_flags = BKE_objdef_lock_flags_get(ob, defbase_tot); - for (i = 0; i < dvert_tot; i++) { - /* in case its not selected */ - if (!(dv = dvert_array[i])) { - continue; + if ((lock_active == TRUE) && + (lock_flags != NULL) && + (def_nr < defbase_tot)) + { + lock_flags[def_nr] = TRUE; + } + + for (i = 0; i < dvert_tot; i++) { + /* in case its not selected */ + if ((dv = dvert_array[i])) { + if (lock_flags) { + defvert_normalize_lock_map(dv, lock_flags, defbase_tot); + } + else if (lock_active) { + defvert_normalize_lock_single(dv, def_nr); + } + else { + defvert_normalize(dv); } - - defvert_normalize_lock(dv, def_nr); } } - else { - for (i = 0; i < dvert_tot; i++) { - /* in case its not selected */ - if (!(dv = dvert_array[i])) { - continue; - } - - defvert_normalize(dv); - } + if (lock_flags) { + MEM_freeN(lock_flags); } MEM_freeN(dvert_array); diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 3c389f97b34..bf948bf9dd8 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -72,6 +72,7 @@ #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_object.h" +#include "BKE_object_deform.h" #include "BKE_paint.h" #include "BKE_report.h" @@ -1308,29 +1309,6 @@ static char has_locked_group(MDeformVert *dvert, const int defbase_tot, } return FALSE; } -/* - * gen_lck_flags gets the status of "flag" for each bDeformGroup - * in ob->defbase and returns an array containing them - */ -static char *gen_lock_flags(Object *ob, int defbase_tot) -{ - char is_locked = FALSE; - int i; - //int defbase_tot = BLI_countlist(&ob->defbase); - char *lock_flags = MEM_mallocN(defbase_tot * sizeof(char), "defflags"); - bDeformGroup *defgroup; - - for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) { - lock_flags[i] = ((defgroup->flag & DG_LOCK_WEIGHT) != 0); - is_locked |= lock_flags[i]; - } - if (is_locked) { - return lock_flags; - } - - MEM_freeN(lock_flags); - return NULL; -} static int has_locked_group_selected(int defbase_tot, const char *defbase_sel, const char *lock_flags) { @@ -1722,10 +1700,6 @@ static int get_first_selected_nonzero_weight(MDeformVert *dvert, const int defba return -1; } - -static char *wpaint_make_validmap(Object *ob); - - static void do_weight_paint_vertex( /* vars which remain the same for every vert */ VPaint *wp, Object *ob, const WeightPaintInfo *wpi, @@ -2067,63 +2041,6 @@ struct WPaintData { int defbase_tot; }; -static char *wpaint_make_validmap(Object *ob) -{ - bDeformGroup *dg; - ModifierData *md; - char *vgroup_validmap; - GHash *gh; - int i, step1 = 1; - - if (ob->defbase.first == NULL) { - return NULL; - } - - gh = BLI_ghash_str_new("wpaint_make_validmap gh"); - - /* add all names to a hash table */ - for (dg = ob->defbase.first; dg; dg = dg->next) { - BLI_ghash_insert(gh, dg->name, NULL); - } - - /* now loop through the armature modifiers and identify deform bones */ - for (md = ob->modifiers.first; md; md = !md->next && step1 ? (step1 = 0), modifiers_getVirtualModifierList(ob) : md->next) { - if (!(md->mode & (eModifierMode_Realtime | eModifierMode_Virtual))) - continue; - - if (md->type == eModifierType_Armature) { - ArmatureModifierData *amd = (ArmatureModifierData *) md; - - if (amd->object && amd->object->pose) { - bPose *pose = amd->object->pose; - bPoseChannel *chan; - - for (chan = pose->chanbase.first; chan; chan = chan->next) { - if (chan->bone->flag & BONE_NO_DEFORM) - continue; - - if (BLI_ghash_remove(gh, chan->name, NULL, NULL)) { - BLI_ghash_insert(gh, chan->name, SET_INT_IN_POINTER(1)); - } - } - } - } - } - - vgroup_validmap = MEM_mallocN(BLI_ghash_size(gh), "wpaint valid map"); - - /* add all names to a hash table */ - for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) { - vgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != NULL); - } - - BLI_assert(i == BLI_ghash_size(gh)); - - BLI_ghash_free(gh, NULL, NULL); - - return vgroup_validmap; -} - static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNUSED(mouse[2])) { Scene *scene = CTX_data_scene(C); @@ -2202,9 +2119,9 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNU /* set up auto-normalize, and generate map for detecting which * vgroups affect deform bones */ wpd->defbase_tot = BLI_countlist(&ob->defbase); - wpd->lock_flags = gen_lock_flags(ob, wpd->defbase_tot); + wpd->lock_flags = BKE_objdef_lock_flags_get(ob, wpd->defbase_tot); if (ts->auto_normalize || ts->multipaint || wpd->lock_flags) { - wpd->vgroup_validmap = wpaint_make_validmap(ob); + wpd->vgroup_validmap = BKE_objdef_validmap_get(ob, wpd->defbase_tot); } /* painting on subsurfs should give correct points too, this returns me->totvert amount */ @@ -2243,7 +2160,6 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P float alpha; float mval[2]; int use_vert_sel; - char *defbase_sel; const float pressure = RNA_float_get(itemptr, "pressure"); const float brush_size_pressure = BKE_brush_size_get(scene, brush) * (BKE_brush_use_size_pressure(scene, brush) ? pressure : 1.0f); @@ -2277,12 +2193,13 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P + /* *** setup WeightPaintInfo - pass onto do_weight_paint_vertex *** */ wpi.defbase_tot = wpd->defbase_tot; - defbase_sel = MEM_mallocN(wpi.defbase_tot * sizeof(char), "wpi.defbase_sel"); - wpi.defbase_tot_sel = get_selected_defgroups(ob, defbase_sel, wpi.defbase_tot); - wpi.defbase_sel = defbase_sel; /* so we can stay const */ - if (wpi.defbase_tot_sel == 0 && ob->actdef > 0) wpi.defbase_tot_sel = 1; + wpi.defbase_sel = BKE_objdef_selected_get(ob, wpi.defbase_tot, &wpi.defbase_tot_sel); + if (wpi.defbase_tot_sel == 0 && ob->actdef > 0) { + wpi.defbase_tot_sel = 1; + } wpi.defbase_tot_unsel = wpi.defbase_tot - wpi.defbase_tot_sel; wpi.vgroup_active = wpd->vgroup_active; diff --git a/source/blender/editors/space_clip/clip_toolbar.c b/source/blender/editors/space_clip/clip_toolbar.c index d8c7bf3f809..1bdf5214192 100644 --- a/source/blender/editors/space_clip/clip_toolbar.c +++ b/source/blender/editors/space_clip/clip_toolbar.c @@ -230,7 +230,7 @@ static void clip_panel_operator_redo(const bContext *C, Panel *pa) block = uiLayoutGetBlock(pa->layout); if (!WM_operator_check_ui_enabled(C, op->type->name)) - uiLayoutSetEnabled(pa->layout, 0); + uiLayoutSetEnabled(pa->layout, FALSE); /* note, blockfunc is a default but->func, use Handle func to allow button callbacks too */ uiBlockSetHandleFunc(block, ED_undo_operator_repeat_cb_evt, op); diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index 08e0934e8ae..12823de60d2 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -4352,38 +4352,38 @@ static void draw_actuator_steering(uiLayout *layout, PointerRNA *ptr) uiLayout *row; uiLayout *col; - uiItemR(layout, ptr, "mode", 0, NULL, 0); - uiItemR(layout, ptr, "target", 0, NULL, 0); - uiItemR(layout, ptr, "navmesh", 0, NULL, 0); + uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "target", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "navmesh", 0, NULL, ICON_NONE); row = uiLayoutRow(layout, FALSE); - uiItemR(row, ptr, "distance", 0, NULL, 0); - uiItemR(row, ptr, "velocity", 0, NULL, 0); + uiItemR(row, ptr, "distance", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "velocity", 0, NULL, ICON_NONE); row = uiLayoutRow(layout, FALSE); - uiItemR(row, ptr, "acceleration", 0, NULL, 0); - uiItemR(row, ptr, "turn_speed", 0, NULL, 0); + uiItemR(row, ptr, "acceleration", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "turn_speed", 0, NULL, ICON_NONE); row = uiLayoutRow(layout, FALSE); col = uiLayoutColumn(row, FALSE); - uiItemR(col, ptr, "facing", 0, NULL, 0); + uiItemR(col, ptr, "facing", 0, NULL, ICON_NONE); col = uiLayoutColumn(row, FALSE); - uiItemR(col, ptr, "facing_axis", 0, NULL, 0); + uiItemR(col, ptr, "facing_axis", 0, NULL, ICON_NONE); if (!RNA_boolean_get(ptr, "facing")) { uiLayoutSetActive(col, FALSE); } col = uiLayoutColumn(row, FALSE); - uiItemR(col, ptr, "normal_up", 0, NULL, 0); + uiItemR(col, ptr, "normal_up", 0, NULL, ICON_NONE); if (!RNA_pointer_get(ptr, "navmesh").data) { uiLayoutSetActive(col, FALSE); } row = uiLayoutRow(layout, FALSE); - uiItemR(row, ptr, "self_terminated", 0, NULL, 0); + uiItemR(row, ptr, "self_terminated", 0, NULL, ICON_NONE); if (RNA_enum_get(ptr, "mode")==ACT_STEERING_PATHFOLLOWING) { - uiItemR(row, ptr, "update_period", 0, NULL, 0); + uiItemR(row, ptr, "update_period", 0, NULL, ICON_NONE); row = uiLayoutRow(layout, FALSE); } - uiItemR(row, ptr, "show_visualization", 0, NULL, 0); + uiItemR(row, ptr, "show_visualization", 0, NULL, ICON_NONE); } static void draw_brick_actuator(uiLayout *layout, PointerRNA *ptr, bContext *C) diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 1981d085583..3455e0b219c 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -901,7 +901,7 @@ void node_uifunc_group(uiLayout *layout, bContext *C, PointerRNA *ptr) static void node_common_buts_whileloop(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "max_iterations", 0, NULL, 0); + uiItemR(layout, ptr, "max_iterations", 0, NULL, ICON_NONE); } /* XXX Does a bounding box update by iterating over all children. @@ -1555,9 +1555,9 @@ static void node_composit_buts_blur(uiLayout *layout, bContext *UNUSED(C), Point uiItemR(col, ptr, "use_relative", 0, NULL, ICON_NONE); if (RNA_boolean_get(ptr, "use_relative")) { - uiItemL(col, IFACE_("Aspect Correction"), 0); + uiItemL(col, IFACE_("Aspect Correction"), ICON_NONE); row = uiLayoutRow(layout, TRUE); - uiItemR(row, ptr, "aspect_correction", UI_ITEM_R_EXPAND, NULL, 0); + uiItemR(row, ptr, "aspect_correction", UI_ITEM_R_EXPAND, NULL, ICON_NONE); col = uiLayoutColumn(layout, TRUE); uiItemR(col, ptr, "factor_x", 0, IFACE_("X"), ICON_NONE); @@ -1981,7 +1981,7 @@ static void node_draw_input_file_output(const bContext *C, uiBlock *block, NodeImageMultiFileSocket *input = sock->storage; RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotLayer, input, &inputptr); - uiItemL(row, input->layer, 0); + uiItemL(row, input->layer, ICON_NONE); } else { NodeImageMultiFileSocket *input = sock->storage; @@ -1989,7 +1989,7 @@ static void node_draw_input_file_output(const bContext *C, uiBlock *block, const char *imtype_name; RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotFile, input, &inputptr); - uiItemL(row, input->path, 0); + uiItemL(row, input->path, ICON_NONE); if (!RNA_boolean_get(&inputptr, "use_node_format")) imfptr = RNA_pointer_get(&inputptr, "format"); @@ -1998,7 +1998,7 @@ static void node_draw_input_file_output(const bContext *C, uiBlock *block, RNA_property_enum_name((bContext *)C, &imfptr, imtype_prop, RNA_property_enum_get(&imfptr, imtype_prop), &imtype_name); uiBlockSetEmboss(block, UI_EMBOSSP); - uiItemL(row, imtype_name, 0); + uiItemL(row, imtype_name, ICON_NONE); uiBlockSetEmboss(block, UI_EMBOSSN); } @@ -2010,9 +2010,9 @@ static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C) int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER); if (multilayer) - uiItemL(layout, IFACE_("Path:"), 0); + uiItemL(layout, IFACE_("Path:"), ICON_NONE); else - uiItemL(layout, IFACE_("Base Path:"), 0); + uiItemL(layout, IFACE_("Base Path:"), ICON_NONE); uiItemR(layout, ptr, "base_path", 0, "", ICON_NONE); } static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -2058,9 +2058,9 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C uiLayout *row, *col; col = uiLayoutColumn(layout, TRUE); - uiItemL(col, IFACE_("Layer:"), 0); + uiItemL(col, IFACE_("Layer:"), ICON_NONE); row = uiLayoutRow(col, FALSE); - uiItemR(row, &active_input_ptr, "name", 0, "", 0); + uiItemR(row, &active_input_ptr, "name", 0, "", ICON_NONE); uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "", ICON_X, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY); } @@ -2068,9 +2068,9 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C uiLayout *row, *col; col = uiLayoutColumn(layout, TRUE); - uiItemL(col, IFACE_("File Path:"), 0); + uiItemL(col, IFACE_("File Path:"), ICON_NONE); row = uiLayoutRow(col, FALSE); - uiItemR(row, &active_input_ptr, "path", 0, "", 0); + uiItemR(row, &active_input_ptr, "path", 0, "", ICON_NONE); uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "", ICON_X, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY); @@ -2078,8 +2078,8 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C imfptr = RNA_pointer_get(&active_input_ptr, "format"); col = uiLayoutColumn(layout, TRUE); - uiItemL(col, IFACE_("Format:"), 0); - uiItemR(col, &active_input_ptr, "use_node_format", 0, NULL, 0); + uiItemL(col, IFACE_("Format:"), ICON_NONE); + uiItemR(col, &active_input_ptr, "use_node_format", 0, NULL, ICON_NONE); col = uiLayoutColumn(layout, FALSE); uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format") == FALSE); @@ -2233,12 +2233,12 @@ static void node_composit_buts_stabilize2d(uiLayout *layout, bContext *C, Pointe if (!node->id) return; - uiItemR(layout, ptr, "filter_type", 0, "", 0); + uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE); } static void node_composit_buts_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "filter_type", 0, "", 0); + uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE); } static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -2250,7 +2250,7 @@ static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, Po if (!node->id) return; - uiItemR(layout, ptr, "distortion_type", 0, "", 0); + uiItemR(layout, ptr, "distortion_type", 0, "", ICON_NONE); } static void node_composit_buts_colorcorrection(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -2263,15 +2263,15 @@ static void node_composit_buts_colorcorrection(uiLayout *layout, bContext *UNUSE uiItemR(row, ptr, "blue", 0, NULL, ICON_NONE); row = uiLayoutRow(layout, FALSE); - uiItemL(row, "", 0); - uiItemL(row, IFACE_("Saturation"), 0); - uiItemL(row, IFACE_("Contrast"), 0); - uiItemL(row, IFACE_("Gamma"), 0); - uiItemL(row, IFACE_("Gain"), 0); - uiItemL(row, IFACE_("Lift"), 0); + uiItemL(row, "", ICON_NONE); + uiItemL(row, IFACE_("Saturation"), ICON_NONE); + uiItemL(row, IFACE_("Contrast"), ICON_NONE); + uiItemL(row, IFACE_("Gamma"), ICON_NONE); + uiItemL(row, IFACE_("Gain"), ICON_NONE); + uiItemL(row, IFACE_("Lift"), ICON_NONE); row = uiLayoutRow(layout, FALSE); - uiItemL(row, IFACE_("Master"), 0); + uiItemL(row, IFACE_("Master"), ICON_NONE); uiItemR(row, ptr, "master_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE); uiItemR(row, ptr, "master_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE); uiItemR(row, ptr, "master_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE); @@ -2279,7 +2279,7 @@ static void node_composit_buts_colorcorrection(uiLayout *layout, bContext *UNUSE uiItemR(row, ptr, "master_lift", UI_ITEM_R_SLIDER, "", ICON_NONE); row = uiLayoutRow(layout, FALSE); - uiItemL(row, IFACE_("Highlights"), 0); + uiItemL(row, IFACE_("Highlights"), ICON_NONE); uiItemR(row, ptr, "highlights_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE); uiItemR(row, ptr, "highlights_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE); uiItemR(row, ptr, "highlights_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE); @@ -2287,7 +2287,7 @@ static void node_composit_buts_colorcorrection(uiLayout *layout, bContext *UNUSE uiItemR(row, ptr, "highlights_lift", UI_ITEM_R_SLIDER, "", ICON_NONE); row = uiLayoutRow(layout, FALSE); - uiItemL(row, IFACE_("Midtones"), 0); + uiItemL(row, IFACE_("Midtones"), ICON_NONE); uiItemR(row, ptr, "midtones_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE); uiItemR(row, ptr, "midtones_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE); uiItemR(row, ptr, "midtones_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE); @@ -2295,7 +2295,7 @@ static void node_composit_buts_colorcorrection(uiLayout *layout, bContext *UNUSE uiItemR(row, ptr, "midtones_lift", UI_ITEM_R_SLIDER, "", ICON_NONE); row = uiLayoutRow(layout, FALSE); - uiItemL(row, IFACE_("Shadows"), 0); + uiItemL(row, IFACE_("Shadows"), ICON_NONE); uiItemR(row, ptr, "shadows_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE); uiItemR(row, ptr, "shadows_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE); uiItemR(row, ptr, "shadows_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE); @@ -2316,31 +2316,31 @@ static void node_composit_buts_colorcorrection_but(uiLayout *layout, bContext *U uiItemR(row, ptr, "green", 0, NULL, ICON_NONE); uiItemR(row, ptr, "blue", 0, NULL, ICON_NONE); row = layout; - uiItemL(row, IFACE_("Saturation"), 0); + uiItemL(row, IFACE_("Saturation"), ICON_NONE); uiItemR(row, ptr, "master_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemR(row, ptr, "highlights_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemR(row, ptr, "midtones_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemR(row, ptr, "shadows_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemL(row, IFACE_("Contrast"), 0); + uiItemL(row, IFACE_("Contrast"), ICON_NONE); uiItemR(row, ptr, "master_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemR(row, ptr, "highlights_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemR(row, ptr, "midtones_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemR(row, ptr, "shadows_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemL(row, IFACE_("Gamma"), 0); + uiItemL(row, IFACE_("Gamma"), ICON_NONE); uiItemR(row, ptr, "master_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemR(row, ptr, "highlights_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemR(row, ptr, "midtones_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemR(row, ptr, "shadows_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemL(row, IFACE_("Gain"), 0); + uiItemL(row, IFACE_("Gain"), ICON_NONE); uiItemR(row, ptr, "master_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemR(row, ptr, "highlights_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemR(row, ptr, "midtones_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemR(row, ptr, "shadows_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemL(row, IFACE_("Lift"), 0); + uiItemL(row, IFACE_("Lift"), ICON_NONE); uiItemR(row, ptr, "master_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemR(row, ptr, "highlights_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemR(row, ptr, "midtones_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE); @@ -2591,7 +2591,7 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN RNA_pointer_create(&clip->id, &RNA_MovieTracking, tracking, &tracking_ptr); - col = uiLayoutColumn(layout, 0); + col = uiLayoutColumn(layout, FALSE); uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA); object = BKE_tracking_object_get_named(tracking, data->tracking_object); diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c index e50b1dc4ba6..da077d93641 100644 --- a/source/blender/editors/space_node/node_buttons.c +++ b/source/blender/editors/space_node/node_buttons.c @@ -110,8 +110,8 @@ static void active_node_panel(const bContext *C, Panel *pa) uiItemR(col, &ptr, "use_custom_color", UI_ITEM_R_ICON_ONLY, NULL, ICON_NONE); sub = uiLayoutRow(col, FALSE); if (!(node->flag & NODE_CUSTOM_COLOR)) - uiLayoutSetEnabled(sub, 0); - uiItemR(sub, &ptr, "color", 0, "", 0); + uiLayoutSetEnabled(sub, FALSE); + uiItemR(sub, &ptr, "color", 0, "", ICON_NONE); col = uiLayoutColumn(row, TRUE); uiItemO(col, "", ICON_ZOOMIN, "node.node_color_preset_add"); diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c index 989b3999018..7881014ed54 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.c @@ -627,11 +627,11 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, row = uiLayoutRow(split, FALSE); col = uiLayoutColumn(row, FALSE); - uiItemR(col, &inputptr, "default_value", 0, "", 0); + uiItemR(col, &inputptr, "default_value", 0, "", ICON_NONE); } else { row = uiLayoutRow(split, TRUE); - uiItemR(row, &inputptr, "default_value", 0, "", 0); + uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE); } } else diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index d2b3bcf6825..da93e07748a 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -1030,7 +1030,7 @@ void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d, if (draw_flags & DRAW_FACE_SELECT) facemask = wpaint__setSolidDrawOptions_facemask; - if (ob && ob->mode & OB_MODE_WEIGHT_PAINT) { + if (ob->mode & OB_MODE_WEIGHT_PAINT) { if (do_light) { const float spec[4] = {0.47f, 0.47f, 0.47f, 0.47f}; diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c index ee1ead76f7c..b40e880591a 100644 --- a/source/blender/editors/space_view3d/view3d_toolbar.c +++ b/source/blender/editors/space_view3d/view3d_toolbar.c @@ -111,7 +111,7 @@ static void view3d_panel_operator_redo(const bContext *C, Panel *pa) block = uiLayoutGetBlock(pa->layout); if (!WM_operator_check_ui_enabled(C, op->type->name)) - uiLayoutSetEnabled(pa->layout, 0); + uiLayoutSetEnabled(pa->layout, FALSE); /* note, blockfunc is a default but->func, use Handle func to allow button callbacks too */ uiBlockSetHandleFunc(block, ED_undo_operator_repeat_cb_evt, op); diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index c13e6c16413..e0991c48fa6 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -62,6 +62,7 @@ set(SRC ../include/ED_lattice.h ../include/ED_logic.h ../include/ED_markers.h + ../include/ED_mask.h ../include/ED_mball.h ../include/ED_mesh.h ../include/ED_node.h diff --git a/source/blender/imbuf/intern/moviecache.c b/source/blender/imbuf/intern/moviecache.c index dd6ccbb1dab..78a989ad48f 100644 --- a/source/blender/imbuf/intern/moviecache.c +++ b/source/blender/imbuf/intern/moviecache.c @@ -174,12 +174,13 @@ static int compare_int(const void *av, const void *bv) static void IMB_moviecache_destructor(void *p) { - MovieCacheItem *item = (MovieCacheItem *) p; - MovieCache *cache = item->cache_owner; - - PRINT("%s: cache '%s' destroy item %p buffer %p\n", __func__, cache->name, item, item->ibuf); + MovieCacheItem *item = (MovieCacheItem *)p; if (item && item->ibuf) { + MovieCache *cache = item->cache_owner; + + PRINT("%s: cache '%s' destroy item %p buffer %p\n", __func__, cache->name, item, item->ibuf); + IMB_freeImBuf(item->ibuf); item->ibuf = NULL; diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index c83bddbfc64..c34ff009405 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -99,7 +99,7 @@ typedef struct Strip { StripProxy *proxy; StripCrop *crop; StripTransform *transform; - StripColorBalance *color_balance; + StripColorBalance *color_balance DNA_DEPRECATED; } Strip; /** @@ -150,9 +150,6 @@ typedef struct Sequence { /* pointers for effects: */ struct Sequence *seq1, *seq2, *seq3; - /* maks input for effects */ - struct Sequence *mask_sequence; - ListBase seqbase; /* list of strips for metastrips */ struct bSound *sound; /* the linked "bSound" object */ @@ -315,7 +312,7 @@ typedef struct BrightContrastModifierData { #define SEQ_USE_PROXY (1 << 15) #define SEQ_USE_TRANSFORM (1 << 16) #define SEQ_USE_CROP (1 << 17) -#define SEQ_USE_COLOR_BALANCE (1 << 18) +/* #define SEQ_USE_COLOR_BALANCE (1 << 18) */ /* DEPRECATED */ #define SEQ_USE_PROXY_CUSTOM_DIR (1 << 19) #define SEQ_USE_PROXY_CUSTOM_FILE (1 << 21) diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index a755e130bb7..5a3efb645a5 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -317,7 +317,7 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_REQUIRED); prop = RNA_def_int(func, "h", 0, 0, INT_MAX, "Height", "", 0, INT_MAX); RNA_def_property_flag(prop, PROP_REQUIRED); - prop = RNA_def_string(func, "layer", "", 0, "Layer", "Single layer to get render result for"); + RNA_def_string(func, "layer", "", 0, "Layer", "Single layer to get render result for"); /* NULL ok here */ prop = RNA_def_pointer(func, "result", "RenderResult", "Result", ""); RNA_def_function_return(func, prop); diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 88952e6ceca..e3e467a9abb 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -56,7 +56,6 @@ typedef struct EffectInfo { const char *ui_desc; void (*func)(StructRNA *); int inputs; - int supports_mask; } EffectInfo; EnumPropertyItem sequence_modifier_type_items[] = { @@ -244,28 +243,6 @@ static void rna_Sequence_channel_set(PointerRNA *ptr, int value) BKE_sequencer_sort(scene); } -/* properties that need to allocate structs */ -static void rna_Sequence_use_color_balance_set(PointerRNA *ptr, int value) -{ - Sequence *seq = (Sequence *)ptr->data; - int c; - - if (value) { - seq->flag |= SEQ_USE_COLOR_BALANCE; - if (seq->strip->color_balance == NULL) { - seq->strip->color_balance = MEM_callocN(sizeof(struct StripColorBalance), "StripColorBalance"); - for (c = 0; c < 3; c++) { - seq->strip->color_balance->lift[c] = 1.0f; - seq->strip->color_balance->gamma[c] = 1.0f; - seq->strip->color_balance->gain[c] = 1.0f; - } - } - } - else { - seq->flag ^= SEQ_USE_COLOR_BALANCE; - } -} - static void rna_Sequence_use_proxy_set(PointerRNA *ptr, int value) { Sequence *seq = (Sequence *)ptr->data; @@ -608,13 +585,6 @@ static int rna_Sequence_input_count_get(PointerRNA *ptr) return BKE_sequence_effect_get_num_inputs(seq->type); } -static int rna_Sequence_supports_mask_get(PointerRNA *ptr) -{ - Sequence *seq = (Sequence *)(ptr->data); - - return BKE_sequence_effect_get_supports_mask(seq->type); -} - #if 0 static void rna_SoundSequence_filename_set(PointerRNA *ptr, const char *value) { @@ -642,20 +612,6 @@ static void rna_Sequence_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Point } } -static int rna_Sequence_otherSequence_poll(PointerRNA *ptr, PointerRNA value) -{ - Sequence *seq = (Sequence *) ptr->data; - Sequence *cur = (Sequence *) value.data; - - if (seq == cur) - return FALSE; - - if (BKE_sequence_check_depend(seq, cur)) - return FALSE; - - return TRUE; -} - static void rna_Sequence_update_reopen_files(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Scene *scene = (Scene *) ptr->id.data; @@ -1631,16 +1587,6 @@ static void rna_def_filter_video(StructRNA *srna) RNA_def_property_ui_text(prop, "Strobe", "Only display every nth frame"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); - prop = RNA_def_property(srna, "use_color_balance", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_COLOR_BALANCE); - RNA_def_property_ui_text(prop, "Use Color Balance", "(3-Way color correction) on input"); - RNA_def_property_boolean_funcs(prop, NULL, "rna_Sequence_use_color_balance_set"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); - - prop = RNA_def_property(srna, "color_balance", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "strip->color_balance"); - RNA_def_property_ui_text(prop, "Color Balance", ""); - prop = RNA_def_property(srna, "use_translation", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_TRANSFORM); RNA_def_property_ui_text(prop, "Use Translation", "Translate image before processing"); @@ -1706,7 +1652,7 @@ static void rna_def_input(StructRNA *srna) RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); } -static void rna_def_effect_inputs(StructRNA *srna, int count, int supports_mask) +static void rna_def_effect_inputs(StructRNA *srna, int count) { PropertyRNA *prop; @@ -1714,10 +1660,6 @@ static void rna_def_effect_inputs(StructRNA *srna, int count, int supports_mask) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_int_funcs(prop, "rna_Sequence_input_count_get", NULL, NULL); - prop = RNA_def_property(srna, "is_supports_mask", PROP_INT, PROP_UNSIGNED); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_int_funcs(prop, "rna_Sequence_supports_mask_get", NULL, NULL); - if (count >= 1) { prop = RNA_def_property(srna, "input_1", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "seq1"); @@ -1740,15 +1682,6 @@ static void rna_def_effect_inputs(StructRNA *srna, int count, int supports_mask) RNA_def_property_ui_text(prop, "Input 3", "Third input for the effect strip"); } */ - - if (supports_mask) { - prop = RNA_def_property(srna, "input_mask_strip", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "mask_sequence"); - RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Sequence_otherSequence_poll"); - RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Mask", "Mask input for the effect strip"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); - } } static void rna_def_image(BlenderRNA *brna) @@ -2189,28 +2122,28 @@ static void rna_def_speed_control(StructRNA *srna) } static EffectInfo def_effects[] = { - {"AddSequence", "Add Sequence", "Add Sequence", NULL, 2, FALSE}, + {"AddSequence", "Add Sequence", "Add Sequence", NULL, 2}, {"AdjustmentSequence", "Adjustment Layer Sequence", - "Sequence strip to perform filter adjustments to layers below", rna_def_input, 0, TRUE}, - {"AlphaOverSequence", "Alpha Over Sequence", "Alpha Over Sequence", NULL, 2, FALSE}, - {"AlphaUnderSequence", "Alpha Under Sequence", "Alpha Under Sequence", NULL, 2, FALSE}, + "Sequence strip to perform filter adjustments to layers below", rna_def_input, 0}, + {"AlphaOverSequence", "Alpha Over Sequence", "Alpha Over Sequence", NULL, 2}, + {"AlphaUnderSequence", "Alpha Under Sequence", "Alpha Under Sequence", NULL, 2}, {"ColorSequence", "Color Sequence", - "Sequence strip creating an image filled with a single color", rna_def_solid_color, 0, FALSE}, - {"CrossSequence", "Cross Sequence", "Cross Sequence", NULL, 2, FALSE}, - {"GammaCrossSequence", "Gamma Cross Sequence", "Gamma Cross Sequence", NULL, 2, FALSE}, - {"GlowSequence", "Glow Sequence", "Sequence strip creating a glow effect", rna_def_glow, 1, FALSE}, + "Sequence strip creating an image filled with a single color", rna_def_solid_color, 0}, + {"CrossSequence", "Cross Sequence", "Cross Sequence", NULL, 2}, + {"GammaCrossSequence", "Gamma Cross Sequence", "Gamma Cross Sequence", NULL, 2}, + {"GlowSequence", "Glow Sequence", "Sequence strip creating a glow effect", rna_def_glow, 1}, {"MulticamSequence", "Multicam Select Sequence", "Sequence strip to perform multicam editing", - rna_def_multicam, 0, FALSE}, - {"MultiplySequence", "Multiply Sequence", "Multiply Sequence", NULL, 2, FALSE}, - {"OverDropSequence", "Over Drop Sequence", "Over Drop Sequence", NULL, 2, FALSE}, + rna_def_multicam, 0}, + {"MultiplySequence", "Multiply Sequence", "Multiply Sequence", NULL, 2}, + {"OverDropSequence", "Over Drop Sequence", "Over Drop Sequence", NULL, 2}, {"SpeedControlSequence", "SpeedControl Sequence", - "Sequence strip to control the speed of other strips", rna_def_speed_control, 1, FALSE}, - {"SubtractSequence", "Subtract Sequence", "Subtract Sequence", NULL, 2, FALSE}, + "Sequence strip to control the speed of other strips", rna_def_speed_control, 1}, + {"SubtractSequence", "Subtract Sequence", "Subtract Sequence", NULL, 2}, {"TransformSequence", "Transform Sequence", - "Sequence strip applying affine transformations to other strips", rna_def_transform, 1, FALSE}, + "Sequence strip applying affine transformations to other strips", rna_def_transform, 1}, {"WipeSequence", "Wipe Sequence", "Sequence strip creating a wipe transition", - rna_def_wipe, 1, FALSE}, - {"", "", "", NULL, 0, FALSE} + rna_def_wipe, 1}, + {"", "", "", NULL, 0} }; static void rna_def_effects(BlenderRNA *brna) @@ -2223,7 +2156,7 @@ static void rna_def_effects(BlenderRNA *brna) RNA_def_struct_ui_text(srna, effect->ui_name, effect->ui_desc); RNA_def_struct_sdna(srna, "Sequence"); - rna_def_effect_inputs(srna, effect->inputs, effect->supports_mask); + rna_def_effect_inputs(srna, effect->inputs); if (effect->func) effect->func(srna); diff --git a/source/blender/makesrna/rna_cleanup/rna_cleaner.py b/source/blender/makesrna/rna_cleanup/rna_cleaner.py index b75d177d809..e3359fbae59 100755 --- a/source/blender/makesrna/rna_cleanup/rna_cleaner.py +++ b/source/blender/makesrna/rna_cleanup/rna_cleaner.py @@ -60,7 +60,7 @@ def check_commandline(): usage() if sys.argv[1] == '-h': help() - elif not (sys.argv[1].endswith(".txt") or sys.argv[1].endswith(".py")): + elif not sys.argv[1].endswith((".txt", ".py")): print ('\nBad input file extension... exiting.') usage() else: diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 360b343daa9..eae636d3510 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -69,6 +69,7 @@ void register_node_type_sh_invert(struct bNodeTreeType *ttype); void register_node_type_sh_seprgb(struct bNodeTreeType *ttype); void register_node_type_sh_combrgb(struct bNodeTreeType *ttype); void register_node_type_sh_hue_sat(struct bNodeTreeType *ttype); +void register_node_type_sh_tex_brick(struct bNodeTreeType *ttype); void register_node_type_sh_attribute(struct bNodeTreeType *ttype); void register_node_type_sh_geometry(struct bNodeTreeType *ttype); diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index 55750ca1bab..07db1ce1a18 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -606,11 +606,9 @@ static void ntreeCompositExecTreeOld(bNodeTree *ntree, RenderData *rd, int do_pr bNode *node; ListBase threads; ThreadData thdata; - int totnode, curnode, rendering= 1, n; - bNodeTreeExec *exec= ntree->execdata; - - if (ntree == NULL) return; - + int totnode, curnode, rendering = TRUE, n; + bNodeTreeExec *exec = ntree->execdata; + if (do_preview) ntreeInitPreview(ntree, 0, 0); diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index aa9d81389da..1c63ab512f2 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -254,6 +254,15 @@ void BPY_python_start(int argc, const char **argv) Py_Initialize(); +#ifdef WIN32 + /* this is disappointing, its likely a bug in python? + * for some reason 'PYTHONIOENCODING' is ignored in windows + * see: [#31555] for details. */ + PyRun_SimpleString("import sys, io\n" + "sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='surrogateescape', line_buffering=True)\n" + "sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='surrogateescape', line_buffering=True)\n"); +#endif /* WIN32 */ + // PySys_SetArgv(argc, argv); // broken in py3, not a huge deal /* sigh, why do python guys not have a (char **) version anymore? */ { diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 57993874c7a..636b3205b23 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -205,17 +205,19 @@ void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel Render *re = engine->re; RenderPart *pa; - if (!result) + if (!result) { return; + } /* merge. on break, don't merge in result for preview renders, looks nicer */ if (!cancel) { /* for exr tile render, detect tiles that are done */ for (pa = re->parts.first; pa; pa = pa->next) { if (result->tilerect.xmin == pa->disprect.xmin && - result->tilerect.ymin == pa->disprect.ymin && - result->tilerect.xmax == pa->disprect.xmax && - result->tilerect.ymax == pa->disprect.ymax) { + result->tilerect.ymin == pa->disprect.ymin && + result->tilerect.xmax == pa->disprect.xmax && + result->tilerect.ymax == pa->disprect.ymax) + { pa->ready = 1; } } diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 984efdbb563..7b0629063a6 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -195,14 +195,12 @@ float *RE_RenderLayerGetPass(RenderLayer *rl, int passtype) RenderLayer *RE_GetRenderLayer(RenderResult *rr, const char *name) { - RenderLayer *rl; - - if (rr == NULL) return NULL; - - for (rl = rr->layers.first; rl; rl = rl->next) - if (strncmp(rl->name, name, RE_MAXNAME) == 0) - return rl; - return NULL; + if (rr == NULL) { + return NULL; + } + else { + return BLI_findstring(&rr->layers, name, offsetof(RenderLayer, name)); + } } RenderResult *RE_MultilayerConvert(void *exrhandle, int rectx, int recty) @@ -1109,7 +1107,10 @@ static void merge_renderresult_fields(RenderResult *rr, RenderResult *rr1, Rende /* passes are allocated in sync */ rpass1 = rl1->passes.first; rpass2 = rl2->passes.first; - for (rpass = rl->passes.first; rpass && rpass1 && rpass2; rpass = rpass->next, rpass1 = rpass1->next, rpass2 = rpass2->next) { + for (rpass = rl->passes.first; + rpass && rpass1 && rpass2; + rpass = rpass->next, rpass1 = rpass1->next, rpass2 = rpass2->next) + { interleave_rect(rr, rpass->rect, rpass1->rect, rpass2->rect, rpass->channels); } } diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 603e49766b1..509266bdc33 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -30,6 +30,7 @@ */ #include +#include #include #include "MEM_guardedalloc.h" @@ -554,8 +555,9 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.B", 0, 0, NULL); IMB_exr_add_channel(rl->exrhandle, rl->name, "Combined.A", 0, 0, NULL); } - else + else { rl->rectf = MEM_mapallocN(rectx * recty * sizeof(float) * 4, "Combined rgba"); + } /* note, this has to be in sync with scene.c */ rl->lay = (1 << 20) - 1; @@ -691,16 +693,18 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart) RenderPass *rpass, *rpassp; for (rl = rr->layers.first; rl; rl = rl->next) { - for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) { - if (strcmp(rlp->name, rl->name) == 0) { - /* combined */ - if (rl->rectf && rlp->rectf) - do_merge_tile(rr, rrpart, rl->rectf, rlp->rectf, 4); - - /* passes are allocated in sync */ - for (rpass = rl->passes.first, rpassp = rlp->passes.first; rpass && rpassp; rpass = rpass->next, rpassp = rpassp->next) { - do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels); - } + rlp = RE_GetRenderLayer(rrpart, rl->name); + if (rlp) { + /* combined */ + if (rl->rectf && rlp->rectf) + do_merge_tile(rr, rrpart, rl->rectf, rlp->rectf, 4); + + /* passes are allocated in sync */ + for (rpass = rl->passes.first, rpassp = rlp->passes.first; + rpass && rpassp; + rpass = rpass->next, rpassp = rpassp->next) + { + do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels); } } } @@ -746,21 +750,24 @@ int RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *file /* combined */ if (rl->rectf) { int a, xstride = 4; - for (a = 0; a < xstride; a++) - IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), + for (a = 0; a < xstride; a++) { + IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), xstride, xstride * rr->rectx, rl->rectf + a); + } } /* passes are allocated in sync */ for (rpass = rl->passes.first; rpass; rpass = rpass->next) { int a, xstride = rpass->channels; for (a = 0; a < xstride; a++) { - if (rpass->passtype) - IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), + if (rpass->passtype) { + IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), xstride, xstride * rr->rectx, rpass->rect + a); - else - IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), + } + else { + IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), xstride, xstride * rr->rectx, rpass->rect + a); + } } } } @@ -818,8 +825,9 @@ void render_result_single_layer_end(Render *re) /* reconstruct render result layers */ for (nr = 0, srl = re->scene->r.layers.first; srl; srl = srl->next, nr++) { - if (nr == re->r.actlay) + if (nr == re->r.actlay) { BLI_addtail(&re->result->layers, rl); + } else { rlpush = RE_GetRenderLayer(re->pushedresult, srl->name); if (rlpush) { @@ -845,10 +853,14 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart) BLI_lock_thread(LOCK_IMAGE); for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) { - for (rl = rr->layers.first; rl; rl = rl->next) - if (strcmp(rl->name, rlp->name) == 0) - break; - + rl = RE_GetRenderLayer(rr, rlp->name); + + /* should never happen but prevents crash if it does */ + BLI_assert(rl); + if (UNLIKELY(rl == NULL)) { + continue; + } + if (rrpart->crop) { /* filters add pixel extra */ offs = (rrpart->crop + rrpart->crop * rrpart->rectx); } @@ -859,17 +871,19 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart) /* combined */ if (rlp->rectf) { int a, xstride = 4; - for (a = 0; a < xstride; a++) + for (a = 0; a < xstride; a++) { IMB_exr_set_channel(rl->exrhandle, rlp->name, get_pass_name(SCE_PASS_COMBINED, a), xstride, xstride * rrpart->rectx, rlp->rectf + a + xstride * offs); + } } /* passes are allocated in sync */ for (rpassp = rlp->passes.first; rpassp; rpassp = rpassp->next) { int a, xstride = rpassp->channels; - for (a = 0; a < xstride; a++) + for (a = 0; a < xstride; a++) { IMB_exr_set_channel(rl->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a), xstride, xstride * rrpart->rectx, rpassp->rect + a + xstride * offs); + } } } @@ -878,10 +892,14 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart) partx = rrpart->tilerect.xmin + rrpart->crop; for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) { - for (rl = rr->layers.first; rl; rl = rl->next) - if (strcmp(rl->name, rlp->name) == 0) - break; - + rl = RE_GetRenderLayer(rr, rlp->name); + + /* should never happen but prevents crash if it does */ + BLI_assert(rl); + if (UNLIKELY(rl == NULL)) { + continue; + } + IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0); } diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index 14c178c10f9..cbe8cc81451 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -93,13 +93,9 @@ extern struct Render R; static void init_render_texture(Render *re, Tex *tex) { - int cfra= re->scene->r.cfra; - - if (re) cfra= re->r.cfra; - /* imap test */ if (tex->ima && ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { - BKE_image_user_frame_calc(&tex->iuser, cfra, re?re->flag & R_SEC_FIELD:0); + BKE_image_user_frame_calc(&tex->iuser, re->r.cfra, re?re->flag & R_SEC_FIELD:0); } else if (tex->type==TEX_ENVMAP) { diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 60c61dbe88c..dee9d036891 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1444,14 +1444,15 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand } else { - printf("%s: error - missing modal\n", __func__); + printf("%s: error '%s' missing modal\n", __func__, op->idname); } } else { wmOperatorType *ot = WM_operatortype_find(event->keymap_idname, 0); - if (ot) + if (ot) { retval = wm_operator_invoke(C, ot, event, properties, NULL, FALSE); + } } /* Finished and pass through flag as handled */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 67cd202591d..0259146a9d3 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1002,7 +1002,7 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, width, UI_UNIT_Y, style); if (!WM_operator_check_ui_enabled(C, op->type->name)) - uiLayoutSetEnabled(layout, 0); + uiLayoutSetEnabled(layout, FALSE); if (op->type->flag & OPTYPE_MACRO) { for (op = op->macro.first; op; op = op->next) { diff --git a/source/tests/pep8.py b/source/tests/pep8.py index d12397ea81d..ccaaeb7c0cd 100644 --- a/source/tests/pep8.py +++ b/source/tests/pep8.py @@ -43,7 +43,7 @@ FORCE_PEP8_ALL = False def file_list_py(path): for dirpath, dirnames, filenames in os.walk(path): for filename in filenames: - if filename.endswith(".py") or filename.endswith(".cfg"): + if filename.endswith((".py", ".cfg")): yield os.path.join(dirpath, filename) From f4817e316e79992a870690b6984e952de0bff18a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 5 Sep 2012 11:42:57 +0000 Subject: [PATCH 107/160] Color Management: sequencer's scopes now works in display space Added utility function to apply display transformation on image buffer's float array which is currently only used by sequencer's scopes. This function is multithreaded, but scopes should be improved further since currently they're being recalculated from scratch on every draw. --- .../editors/space_sequencer/sequencer_draw.c | 50 +++++++----- source/blender/imbuf/IMB_colormanagement.h | 20 +++-- source/blender/imbuf/intern/colormanagement.c | 76 +++++++++++++++---- 3 files changed, 104 insertions(+), 42 deletions(-) diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 991ae873c59..42843b65e1d 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -912,27 +912,35 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq if (ibuf->rect == NULL && ibuf->rect_float == NULL) return; - - switch (sseq->mainb) { - case SEQ_DRAW_IMG_IMBUF: - if (sseq->zebra != 0) { - scope = make_zebra_view_from_ibuf(ibuf, sseq->zebra); - } - break; - case SEQ_DRAW_IMG_WAVEFORM: - if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) { - scope = make_sep_waveform_view_from_ibuf(ibuf); - } - else { - scope = make_waveform_view_from_ibuf(ibuf); - } - break; - case SEQ_DRAW_IMG_VECTORSCOPE: - scope = make_vectorscope_view_from_ibuf(ibuf); - break; - case SEQ_DRAW_IMG_HISTOGRAM: - scope = make_histogram_view_from_ibuf(ibuf); - break; + + if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { + if (sseq->zebra != 0) { + scope = make_zebra_view_from_ibuf(ibuf, sseq->zebra); + } + } + else { + ImBuf *display_ibuf = IMB_dupImBuf(ibuf); + + IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings, &scene->display_settings); + + switch (sseq->mainb) { + case SEQ_DRAW_IMG_WAVEFORM: + if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) { + scope = make_sep_waveform_view_from_ibuf(display_ibuf); + } + else { + scope = make_waveform_view_from_ibuf(display_ibuf); + } + break; + case SEQ_DRAW_IMG_VECTORSCOPE: + scope = make_vectorscope_view_from_ibuf(display_ibuf); + break; + case SEQ_DRAW_IMG_HISTOGRAM: + scope = make_histogram_view_from_ibuf(display_ibuf); + break; + } + + IMB_freeImBuf(display_ibuf); } if (scope) { diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index d6a9a1d8ffe..106ed2f6ea1 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -50,6 +50,13 @@ struct Scene; void IMB_colormanagement_init(void); void IMB_colormanagement_exit(void); +/* ** Generic functions ** */ + +void IMB_colormanagement_check_file_config(struct Main *bmain); + +void IMB_colormanagement_validate_settings(struct ColorManagedDisplaySettings *display_settings, + struct ColorManagedViewSettings *view_settings); + /* ** Color space transformation functions ** */ void IMB_colormanagement_colorspace_transform(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace); @@ -60,8 +67,10 @@ void IMB_colormanagement_pixel_from_role(float pixel[4], int role); void IMB_colormanagement_imbuf_to_role(struct ImBuf *ibuf, int role); void IMB_colormanagement_imbuf_from_role(struct ImBuf *ibuf, int role); -void IMB_colormanagement_imbuf_make_scene_linear(struct ImBuf *ibuf, - struct ColorManagedColorspaceSettings *colorspace_settings); +void IMB_colormanagement_imbuf_make_scene_linear(struct ImBuf *ibuf, struct ColorManagedColorspaceSettings *colorspace_settings); + +void IMB_colormanagement_imbuf_make_display_space(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings); /* ** Public display buffers interfaces ** */ @@ -81,11 +90,6 @@ void IMB_display_buffer_release(void *cache_handle); void IMB_display_buffer_invalidate(struct ImBuf *ibuf); -void IMB_colormanagement_check_file_config(struct Main *bmain); - -void IMB_colormanagement_validate_settings(struct ColorManagedDisplaySettings *display_settings, - struct ColorManagedViewSettings *view_settings); - /* ** Display funcrions ** */ int IMB_colormanagement_display_get_named_index(const char *name); const char *IMB_colormanagement_display_get_indexed_name(int index); @@ -104,7 +108,7 @@ void IMB_colormanagement_display_items_add(struct EnumPropertyItem **items, int void IMB_colormanagement_view_items_add(struct EnumPropertyItem **items, int *totitem, const char *display_name); void IMB_colormanagement_colorspace_items_add(struct EnumPropertyItem **items, int *totitem); -/* Tile-based buffer management */ +/* ** Tile-based buffer management ** */ void IMB_partial_display_buffer_update(struct ImBuf *ibuf, const float *linear_buffer, int stride, int offset_x, int offset_y, int xmin, int ymin, int xmax, int ymax); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 2ba1beccf99..5e446d8cb81 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -599,7 +599,9 @@ typedef struct DisplayBufferThread { float *buffer; unsigned char *byte_buffer; - unsigned char *display_buffer; + + float *display_buffer; + unsigned char *display_buffer_byte; int width; int start_line; @@ -617,7 +619,10 @@ typedef struct DisplayBufferInitData { void *processor; float *buffer; unsigned char *byte_buffer; - unsigned char *display_buffer; + + float *display_buffer; + unsigned char *display_buffer_byte; + int width; } DisplayBufferInitData; @@ -643,7 +648,11 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l if (init_data->byte_buffer) handle->byte_buffer = init_data->byte_buffer + offset; - handle->display_buffer = init_data->display_buffer + offset; + if (init_data->display_buffer) + handle->display_buffer = init_data->display_buffer + offset; + + if (init_data->display_buffer_byte) + handle->display_buffer_byte = init_data->display_buffer_byte + offset; handle->width = ibuf->x; @@ -658,7 +667,7 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l } static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned char *byte_buffer, - unsigned char *display_buffer, + float *display_buffer, unsigned char *display_buffer_byte, void *processor, void *(do_thread) (void *)) { DisplayBufferInitData init_data; @@ -668,6 +677,7 @@ static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned c init_data.buffer = buffer; init_data.byte_buffer = byte_buffer; init_data.display_buffer = display_buffer; + init_data.display_buffer_byte = display_buffer_byte; IMB_processor_apply_threaded(ibuf->y, sizeof(DisplayBufferThread), &init_data, display_buffer_init_handle, do_thread); @@ -735,7 +745,8 @@ static void *do_display_buffer_apply_thread(void *handle_v) ConstProcessorRcPtr *processor = (ConstProcessorRcPtr *) handle->processor; PackedImageDesc *img; float *buffer = handle->buffer; - unsigned char *display_buffer = handle->display_buffer; + float *display_buffer = handle->display_buffer; + unsigned char *display_buffer_byte = handle->display_buffer_byte; int channels = handle->channels; int width = handle->width; int height = handle->tot_line; @@ -751,10 +762,16 @@ static void *do_display_buffer_apply_thread(void *handle_v) OCIO_packedImageDescRelease(img); - /* do conversion */ - IMB_buffer_byte_from_float(display_buffer, linear_buffer, - channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, - predivide, width, height, width, width); + if (display_buffer_byte) { + /* do conversion */ + IMB_buffer_byte_from_float(display_buffer_byte, linear_buffer, + channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, + predivide, width, height, width, width); + } + + if (display_buffer) { + memcpy(display_buffer, linear_buffer, width * height * channels * sizeof(float)); + } if (linear_buffer != buffer) MEM_freeN(linear_buffer); @@ -811,9 +828,9 @@ static ConstProcessorRcPtr *create_display_buffer_processor(const char *view_tra return processor; } -static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *display_buffer, - const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) +static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_buffer, unsigned char *display_buffer_byte, + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) { ConstProcessorRcPtr *processor; const float gamma = view_settings->gamma; @@ -825,12 +842,20 @@ static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *displ if (processor) { display_buffer_apply_threaded(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect, - display_buffer, processor, do_display_buffer_apply_thread); + display_buffer, display_buffer_byte, processor, + do_display_buffer_apply_thread); } OCIO_processorRelease(processor); } +static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *display_buffer, + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) +{ + colormanage_display_buffer_process_ex(ibuf, NULL, display_buffer, view_settings, display_settings); +} + /*********************** Threaded color space transform routines *************************/ typedef struct ColorspaceTransformThread { @@ -1075,6 +1100,30 @@ void IMB_colormanagement_imbuf_make_scene_linear(ImBuf *ibuf, ColorManagedColors #endif } +void IMB_colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) +{ +#ifdef WITH_OCIO + /* OCIO_TODO: byte buffer management is not supported here yet */ + if (!ibuf->rect_float) + return; + + if (global_tot_display == 0 || global_tot_view == 0) { + IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float, ibuf->channels, IB_PROFILE_LINEAR_RGB, ibuf->profile, + ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x); + } + else { + colormanage_display_buffer_process_ex(ibuf, ibuf->rect_float, NULL, view_settings, display_settings); + } +#else + (void) view_settings; + (void) display_settings; + + IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float, ibuf->channels, IB_PROFILE_LINEAR_RGB, ibuf->profile, + ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x); +#endif +} + #ifdef WITH_OCIO static void colormanage_flags_allocate(ImBuf *ibuf) { @@ -1265,6 +1314,7 @@ void IMB_display_buffer_pixel(float result[4], const float pixel[4], const Colo #endif } +/* covert float buffer to display space and store it in image buffer's byte array */ void IMB_display_buffer_to_imbuf_rect(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { From 54cf098492dab220b23e0e5ff93b52a267a02762 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 5 Sep 2012 11:43:05 +0000 Subject: [PATCH 108/160] Sequencer: cache currently displaying scopes This avoids calculation of scopes on every redraw, so such tools as panning and zoom wouldn't imply re-calculating scopes. Implemented as a structure inside of SpaceSeq, juts like it's done for clip and image spaces. Also fixed zebra display to work in display space. --- source/blender/blenloader/intern/readfile.c | 7 ++ .../editors/space_sequencer/sequencer_draw.c | 86 ++++++++++++++++--- .../editors/space_sequencer/space_sequencer.c | 52 ++++++++++- source/blender/makesdna/DNA_movieclip_types.h | 1 + source/blender/makesdna/DNA_sequence_types.h | 12 +++ source/blender/makesdna/DNA_space_types.h | 2 + source/blender/makesrna/intern/rna_color.c | 17 +++- 7 files changed, 156 insertions(+), 21 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 04c9d96ea0f..33693cf994b 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5294,6 +5294,13 @@ static void lib_link_screen(FileData *fd, Main *main) * so fingers crossed this works fine! */ sseq->gpd = newlibadr_us(fd, sc->id.lib, sseq->gpd); + + sseq->scopes.reference_ibuf = NULL; + sseq->scopes.zebra_ibuf = NULL; + sseq->scopes.waveform_ibuf = NULL; + sseq->scopes.sep_waveform_ibuf = NULL; + sseq->scopes.vector_ibuf = NULL; + sseq->scopes.histogram_ibuf = NULL; } else if (sl->spacetype == SPACE_NLA) { SpaceNla *snla= (SpaceNla *)sl; diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 42843b65e1d..d1e2066cfba 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -850,6 +850,50 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int return ibuf; } +static void sequencer_check_scopes(SequencerScopes *scopes, ImBuf *ibuf) +{ + if (scopes->reference_ibuf != ibuf) { + if (scopes->zebra_ibuf) { + IMB_freeImBuf(scopes->zebra_ibuf); + scopes->zebra_ibuf = NULL; + } + + if (scopes->waveform_ibuf) { + IMB_freeImBuf(scopes->waveform_ibuf); + scopes->waveform_ibuf = NULL; + } + + if (scopes->sep_waveform_ibuf) { + IMB_freeImBuf(scopes->sep_waveform_ibuf); + scopes->sep_waveform_ibuf = NULL; + } + + if (scopes->vector_ibuf) { + IMB_freeImBuf(scopes->vector_ibuf); + scopes->vector_ibuf = NULL; + } + + if (scopes->histogram_ibuf) { + IMB_freeImBuf(scopes->histogram_ibuf); + scopes->histogram_ibuf = NULL; + } + } +} + +static ImBuf *sequencer_make_scope(Scene *scene, ImBuf *ibuf, ImBuf *(*make_scope_cb) (ImBuf *ibuf)) +{ + ImBuf *display_ibuf = IMB_dupImBuf(ibuf); + ImBuf *scope; + + IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings, &scene->display_settings); + + scope = make_scope_cb(display_ibuf); + + IMB_freeImBuf(display_ibuf); + + return scope; +} + void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, int draw_overlay) { struct Main *bmain = CTX_data_main(C); @@ -913,34 +957,47 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq if (ibuf->rect == NULL && ibuf->rect_float == NULL) return; - if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { - if (sseq->zebra != 0) { - scope = make_zebra_view_from_ibuf(ibuf, sseq->zebra); - } - } - else { - ImBuf *display_ibuf = IMB_dupImBuf(ibuf); + if (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0) { + SequencerScopes *scopes = &sseq->scopes; - IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings, &scene->display_settings); + sequencer_check_scopes(scopes, ibuf); switch (sseq->mainb) { + case SEQ_DRAW_IMG_IMBUF: + if (!scopes->zebra_ibuf) { + ImBuf *display_ibuf = IMB_dupImBuf(ibuf); + + IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings, &scene->display_settings); + scopes->zebra_ibuf = make_zebra_view_from_ibuf(display_ibuf, sseq->zebra); + IMB_freeImBuf(display_ibuf); + } + scope = scopes->zebra_ibuf; + break; case SEQ_DRAW_IMG_WAVEFORM: if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) { - scope = make_sep_waveform_view_from_ibuf(display_ibuf); + if (!scopes->sep_waveform_ibuf) + scopes->sep_waveform_ibuf = sequencer_make_scope(scene, ibuf, make_sep_waveform_view_from_ibuf); + scope = scopes->sep_waveform_ibuf; } else { - scope = make_waveform_view_from_ibuf(display_ibuf); + if (!scopes->waveform_ibuf) + scopes->waveform_ibuf = sequencer_make_scope(scene, ibuf, make_waveform_view_from_ibuf); + scope = scopes->waveform_ibuf; } break; case SEQ_DRAW_IMG_VECTORSCOPE: - scope = make_vectorscope_view_from_ibuf(display_ibuf); + if (!scopes->vector_ibuf) + scopes->vector_ibuf = sequencer_make_scope(scene, ibuf, make_vectorscope_view_from_ibuf); + scope = scopes->vector_ibuf; break; case SEQ_DRAW_IMG_HISTOGRAM: - scope = make_histogram_view_from_ibuf(display_ibuf); + if (!scopes->histogram_ibuf) + scopes->histogram_ibuf = sequencer_make_scope(scene, ibuf, make_histogram_view_from_ibuf); + scope = scopes->histogram_ibuf; break; } - IMB_freeImBuf(display_ibuf); + scopes->reference_ibuf = ibuf; } if (scope) { @@ -1049,7 +1106,8 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq /* draw grease-pencil (image aligned) */ draw_gpencil_2dimage(C); - IMB_freeImBuf(ibuf); + if (!scope) + IMB_freeImBuf(ibuf); /* ortho at pixel level */ UI_view2d_view_restore(C); diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index f7362aab7aa..8ac50a57b10 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -57,8 +57,19 @@ #include "UI_resources.h" #include "UI_view2d.h" +#include "IMB_imbuf.h" + #include "sequencer_intern.h" // own include +/**************************** common state *****************************/ + +static void sequencer_scopes_tag_refresh(ScrArea *sa) +{ + SpaceSeq *sseq = (SpaceSeq *)sa->spacedata.first; + + sseq->scopes.reference_ibuf = NULL; +} + /* ******************** manage regions ********************* */ ARegion *sequencer_has_buttons_region(ScrArea *sa) @@ -183,12 +194,27 @@ static SpaceLink *sequencer_new(const bContext *C) } /* not spacelink itself */ -static void sequencer_free(SpaceLink *UNUSED(sl)) +static void sequencer_free(SpaceLink *sl) { -// SpaceSeq *sseq= (SpaceSequencer*) sl; - + SpaceSeq *sseq= (SpaceSeq *) sl; + SequencerScopes *scopes = &sseq->scopes; + // XXX if (sseq->gpd) BKE_gpencil_free(sseq->gpd); + if (scopes->zebra_ibuf) + IMB_freeImBuf(scopes->zebra_ibuf); + + if (scopes->waveform_ibuf) + IMB_freeImBuf(scopes->waveform_ibuf); + + if (scopes->sep_waveform_ibuf) + IMB_freeImBuf(scopes->sep_waveform_ibuf); + + if (scopes->vector_ibuf) + IMB_freeImBuf(scopes->vector_ibuf); + + if (scopes->histogram_ibuf) + IMB_freeImBuf(scopes->histogram_ibuf); } @@ -290,7 +316,24 @@ static SpaceLink *sequencer_duplicate(SpaceLink *sl) return (SpaceLink *)sseqn; } - +static void sequencer_listener(ScrArea *sa, wmNotifier *wmn) +{ + /* context changes */ + switch (wmn->category) { + case NC_SCENE: + switch (wmn->data) { + case ND_FRAME: + case ND_SEQUENCER: + sequencer_scopes_tag_refresh(sa); + break; + } + break; + case NC_SPACE: + if (wmn->data == ND_SPACE_SEQUENCER) + sequencer_scopes_tag_refresh(sa); + break; + } +} /* *********************** sequencer (main) region ************************ */ /* add handlers, stuff you only do once or on area/region changes */ @@ -610,6 +653,7 @@ void ED_spacetype_sequencer(void) st->context = sequencer_context; st->dropboxes = sequencer_dropboxes; st->refresh = sequencer_refresh; + st->listener = sequencer_listener; /* regions: main window */ art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region"); diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h index cda51779528..53e8556f786 100644 --- a/source/blender/makesdna/DNA_movieclip_types.h +++ b/source/blender/makesdna/DNA_movieclip_types.h @@ -38,6 +38,7 @@ #include "DNA_ID.h" #include "DNA_tracking_types.h" #include "DNA_color_types.h" /* for color management */ +#include "DNA_sequence_types.h" struct anim; struct AnimData; diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index c34ff009405..ebe13508eb8 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -275,6 +275,18 @@ typedef struct BrightContrastModifierData { float contrast; } BrightContrastModifierData; +/* ***************** Scopes ****************** */ + +typedef struct SequencerScopes { + struct ImBuf *reference_ibuf; + + struct ImBuf *zebra_ibuf; + struct ImBuf *waveform_ibuf; + struct ImBuf *sep_waveform_ibuf; + struct ImBuf *vector_ibuf; + struct ImBuf *histogram_ibuf; +} SequencerScopes; + #define MAXSEQ 32 #define SELECT 1 diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index b828247c816..e70d80fd6f5 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -473,6 +473,8 @@ typedef struct SpaceSeq { int overlay_type; struct bGPdata *gpd; /* grease-pencil data */ + + struct SequencerScopes scopes; /* different scoped displayed in space */ } SpaceSeq; diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 5f1669cd3c8..45d6ea2951e 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -386,6 +386,8 @@ static void rna_ColorManagedDisplaySettings_display_device_update(Main *UNUSED(b Scene *scene = (Scene *) id; IMB_colormanagement_validate_settings(&scene->display_settings, &scene->view_settings); + + WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); } } @@ -470,6 +472,15 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *UNUSED(bmain) } } +static void rna_ColorManagement_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + ID *id = ptr->id.data; + + if (GS(id->name) == ID_SCE) { + WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); + } +} + /* this function only exists because #curvemap_evaluateF uses a 'const' qualifier */ float rna_CurveMap_evaluateF(struct CurveMap *cuma, float value) { @@ -852,21 +863,21 @@ static void rna_def_colormanage(BlenderRNA *brna) "rna_ColorManagedViewSettings_view_transform_set", "rna_ColorManagedViewSettings_view_transform_itemf"); RNA_def_property_ui_text(prop, "View Transform", "View used "); - RNA_def_property_update(prop, NC_WINDOW, NULL); + RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update"); prop = RNA_def_property(srna, "exposure", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "exposure"); RNA_def_property_range(prop, -10.0f, 10.0f); RNA_def_property_float_default(prop, 0.0f); RNA_def_property_ui_text(prop, "Exposure", "Exposure (stops) applied on displaying image buffers"); - RNA_def_property_update(prop, NC_WINDOW, NULL); + RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update"); prop = RNA_def_property(srna, "gamma", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "gamma"); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0.0f, 5.0f); RNA_def_property_ui_text(prop, "Gamma", "Amount f gamma modification for displaying image buffers"); - RNA_def_property_update(prop, NC_WINDOW, NULL); + RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update"); /* ** Colorspace ** */ srna = RNA_def_struct(brna, "ColorManagedColorspaceSettings", NULL); From c6599979c738c3f528b93a25373c377cebf3a401 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 5 Sep 2012 11:43:11 +0000 Subject: [PATCH 109/160] Sequencer: multi-threaded histogram calculation This gives some percentage of speedup, which compensates slowdown caused by converting image buffer into display space. Used OpenMP for this. Still feel skeptic about this, discussed with Brecht and we decided this approach actually could be used since seems all the platforms has got OpenMP issues solved. Waveform and vector scopes are still single-threaded since they're a bit tricker to be done multi-threaded and probably not so commonly used. --- .../space_sequencer/sequencer_scopes.c | 50 +++++++++++++++---- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c index 1655b3ec7bc..d09d6a29c10 100644 --- a/source/blender/editors/space_sequencer/sequencer_scopes.c +++ b/source/blender/editors/space_sequencer/sequencer_scopes.c @@ -460,12 +460,28 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf) memset(bins, 0, sizeof(bins)); + #pragma omp parallel for shared(bins, src, ibuf) private(x, y) if (ibuf->y >= 256) for (y = 0; y < ibuf->y; y++) { + unsigned int cur_bins[3][512]; + + memset(cur_bins, 0, sizeof(cur_bins)); + for (x = 0; x < ibuf->x; x++) { - bins[0][*src++]++; - bins[1][*src++]++; - bins[2][*src++]++; - src++; + unsigned char *pixel = src + (y * ibuf->x + x) * 4; + + cur_bins[0][pixel[0]]++; + cur_bins[1][pixel[1]]++; + cur_bins[2][pixel[2]]++; + } + + #pragma omp critical + { + int i; + for (i = 0; i < 512; i++) { + bins[0][i] += cur_bins[0][i]; + bins[1][i] += cur_bins[1][i]; + bins[2][i] += cur_bins[2][i]; + } } } @@ -490,7 +506,7 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf) return rval; } -static int get_bin_float(float f) +BLI_INLINE int get_bin_float(float f) { if (f < -0.25f) { return 0; @@ -512,12 +528,28 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf) memset(bins, 0, sizeof(bins)); + #pragma omp parallel for shared(bins, src, ibuf) private(x, y) if (ibuf->y >= 256) for (y = 0; y < ibuf->y; y++) { + unsigned int cur_bins[3][512]; + + memset(cur_bins, 0, sizeof(cur_bins)); + for (x = 0; x < ibuf->x; x++) { - bins[0][get_bin_float(*src++)]++; - bins[1][get_bin_float(*src++)]++; - bins[2][get_bin_float(*src++)]++; - src++; + float *pixel = src + (y * ibuf->x + x) * 4; + + cur_bins[0][get_bin_float(pixel[0])]++; + cur_bins[1][get_bin_float(pixel[1])]++; + cur_bins[2][get_bin_float(pixel[2])]++; + } + + #pragma omp critical + { + int i; + for (i = 0; i < 512; i++) { + bins[0][i] += cur_bins[0][i]; + bins[1][i] += cur_bins[1][i]; + bins[2][i] += cur_bins[2][i]; + } } } From 201583592f950e2de8068ee7637d9a8226b66592 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 5 Sep 2012 12:00:08 +0000 Subject: [PATCH 110/160] Code cleanup -- remove unneeded changes, synchronize some areas with trunk --- release/scripts/startup/bl_ui/space_info.py | 2 -- release/scripts/startup/bl_ui/space_sequencer.py | 5 ----- source/blender/editors/screen/screen_ops.c | 3 +-- source/blender/editors/space_clip/space_clip.c | 1 - source/blender/editors/space_node/space_node.c | 3 +-- source/blender/imbuf/intern/IMB_filter.h | 3 --- source/blender/makesdna/DNA_movieclip_types.h | 1 - source/blender/makesdna/DNA_space_types.h | 1 + source/blender/makesrna/intern/rna_render.c | 1 + source/blender/makesrna/intern/rna_space.c | 3 +-- source/blender/makesrna/intern/rna_wm.c | 2 -- source/blender/nodes/NOD_shader.h | 1 - source/blender/windowmanager/intern/wm_window.c | 3 +-- 13 files changed, 6 insertions(+), 23 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py index d2d8dc22aea..04ea6b818ac 100644 --- a/release/scripts/startup/bl_ui/space_info.py +++ b/release/scripts/startup/bl_ui/space_info.py @@ -356,8 +356,6 @@ class INFO_MT_window(Menu): def draw(self, context): import sys - window = context.window - layout = self.layout layout.operator("wm.window_duplicate") diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 2ab90301bdb..dd13b8a9b51 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -874,11 +874,6 @@ class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel): col.prop(st, "show_separate_color") col.prop(st, "proxy_render_size") - #col = layout.column() - #col.separator() - #col.label(text="Color Management:") - #col.template_colormanaged_view_settings(st, "view_settings", True) - class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel): bl_label = "Modifiers" diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 4b26ed89f53..823037a7903 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -49,7 +49,6 @@ #include "DNA_mask_types.h" #include "DNA_userdef_types.h" -#include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_global.h" @@ -852,7 +851,7 @@ static int area_dupli_invoke(bContext *C, wmOperator *op, wmEvent *event) rect = sa->totrct; BLI_rcti_translate(&rect, win->posx, win->posy); newwin = WM_window_open(C, &rect); - + /* allocs new screen and adds to newly created window, using window size */ newsc = ED_screen_add(newwin, CTX_data_scene(C), sc->id.name + 2); newwin->screen = newsc; diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 803a9dd2d1d..bb06104d442 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -43,7 +43,6 @@ #include "BLI_utildefines.h" #include "BLI_math.h" -#include "BKE_colortools.h" #include "BKE_main.h" #include "BKE_context.h" #include "BKE_screen.h" diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index a8e43563649..1522528a8ac 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -40,7 +40,6 @@ #include "BLI_blenlib.h" #include "BLI_math.h" -#include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_screen.h" #include "BKE_node.h" @@ -307,7 +306,7 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa) static SpaceLink *node_duplicate(SpaceLink *sl) { SpaceNode *snoden = MEM_dupallocN(sl); - + /* clear or remove stuff from old */ snoden->nodetree = NULL; snoden->linkdrag.first = snoden->linkdrag.last = NULL; diff --git a/source/blender/imbuf/intern/IMB_filter.h b/source/blender/imbuf/intern/IMB_filter.h index 20e1e120705..eaedb160c94 100644 --- a/source/blender/imbuf/intern/IMB_filter.h +++ b/source/blender/imbuf/intern/IMB_filter.h @@ -43,8 +43,5 @@ void IMB_premultiply_rect_float(float *rect_float, char planes, int w, int h); void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1); -/* tonecurves corrections */ -void IMB_ratio_preserving_odt_tonecurve(float rgbOut[3], const float rgbIn[3]); - #endif diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h index 53e8556f786..cda51779528 100644 --- a/source/blender/makesdna/DNA_movieclip_types.h +++ b/source/blender/makesdna/DNA_movieclip_types.h @@ -38,7 +38,6 @@ #include "DNA_ID.h" #include "DNA_tracking_types.h" #include "DNA_color_types.h" /* for color management */ -#include "DNA_sequence_types.h" struct anim; struct AnimData; diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index e70d80fd6f5..7196b6b7059 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -40,6 +40,7 @@ #include "DNA_outliner_types.h" /* for TreeStoreElem */ #include "DNA_image_types.h" /* ImageUser */ #include "DNA_movieclip_types.h" /* MovieClipUser */ +#include "DNA_sequence_types.h" /* SequencerScopes */ /* Hum ... Not really nice... but needed for spacebuts. */ #include "DNA_view2d_types.h" diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 5a3efb645a5..d2e4e8edbfb 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -327,6 +327,7 @@ static void rna_def_render_engine(BlenderRNA *brna) func = RNA_def_function(srna, "end_result", "RE_engine_end_result"); prop = RNA_def_pointer(func, "result", "RenderResult", "Result", ""); + RNA_def_property_flag(prop, PROP_REQUIRED); prop = RNA_def_boolean(func, "cancel", 0, "Cancel", "Don't merge back results"); RNA_def_property_flag(prop, PROP_REQUIRED); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 385e82cab35..c4a60dba025 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -152,7 +152,6 @@ EnumPropertyItem clip_editor_mode_items[] = { #include "ED_sequencer.h" #include "ED_clip.h" -#include "IMB_colormanagement.h" #include "IMB_imbuf_types.h" static StructRNA *rna_Space_refine(struct PointerRNA *ptr) @@ -1904,7 +1903,7 @@ static void rna_def_space_buttons(BlenderRNA *brna) {SB_TEXC_MAT_OR_LAMP, "MATERIAL", ICON_MATERIAL, "Material", "Material"}, {0, NULL, 0, NULL, NULL} }; /*actually populated dynamically trough a function */ - + srna = RNA_def_struct(brna, "SpaceProperties", "Space"); RNA_def_struct_sdna(srna, "SpaceButs"); RNA_def_struct_ui_text(srna, "Properties Space", "Properties space data"); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index cd6517b8d40..61c75e306cb 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -440,8 +440,6 @@ EnumPropertyItem wm_report_items[] = { #include "MEM_guardedalloc.h" -#include "IMB_colormanagement.h" - static wmOperator *rna_OperatorProperties_find_operator(PointerRNA *ptr) { wmWindowManager *wm = ptr->id.data; diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index eae636d3510..49428c06e5f 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -109,7 +109,6 @@ void register_node_type_sh_tex_wave(struct bNodeTreeType *ttype); void register_node_type_sh_tex_musgrave(struct bNodeTreeType *ttype); void register_node_type_sh_tex_noise(struct bNodeTreeType *ttype); void register_node_type_sh_tex_checker(struct bNodeTreeType *ttype); -void register_node_type_sh_tex_brick(struct bNodeTreeType *ttype); #endif diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 363d04b8433..b83b93454e6 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -49,7 +49,6 @@ #include "BLF_translation.h" #include "BKE_blender.h" -#include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_library.h" #include "BKE_global.h" @@ -244,7 +243,7 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *winorig) win->drawmethod = -1; win->drawdata = NULL; - + return win; } From ade9acca416d96021a017a471ab7985f6376ccce Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 5 Sep 2012 12:14:09 +0000 Subject: [PATCH 111/160] Color Management: fix for tiled image draw and remove unused code --- source/blender/editors/space_clip/clip_draw.c | 16 ----- .../blender/editors/space_image/image_draw.c | 66 +++++-------------- 2 files changed, 18 insertions(+), 64 deletions(-) diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 507e8591c6b..d486caeacc2 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -247,19 +247,6 @@ static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar) ED_region_info_draw(ar, str, block, 0.6f); } -/* OCIO_TODO: after finishing proper color management pipeline integration - * this wouldn't be needed -- color managed display buffer - * would be used unstead - */ -#if 0 -static void verify_buffer_float(ImBuf *ibuf) -{ - if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID))) { - IMB_rect_from_float(ibuf); - } -} -#endif - static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, ImBuf *ibuf, int width, int height, float zoomx, float zoomy) { @@ -277,9 +264,6 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, unsigned char *display_buffer; void *cache_handle; - /* OCIO_TODO: finally get rid of this stuff */ - /* verify_buffer_float(ibuf); */ - display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); if (display_buffer) { diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 3078abaa946..512921262f0 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -80,36 +80,6 @@ #define HEADER_HEIGHT 18 -/* OCIO_TODO: after finishing proper color management pipeline integration - * this wouldn't be needed -- color managed display buffer - * would be used unstead - */ -static void image_verify_buffer_float(Image *ima, ImBuf *ibuf, int color_manage) -{ - /* detect if we need to redo the curve map. - * ibuf->rect is zero for compositor and render results after change - * convert to 32 bits always... drawing float rects isn't supported well (atis) - * - * NOTE: if float buffer changes, we have to manually remove the rect - */ - - if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID)) ) { - if (color_manage) { - if (ima && ima->source == IMA_SRC_VIEWER) - ibuf->profile = IB_PROFILE_LINEAR_RGB; - } - else - ibuf->profile = IB_PROFILE_NONE; - - /* OCIO_TODO: currently only get rid of old-style color managed byte - * buffer calculation to save some time on buffer display, - * but still need to set image buffer's profile to prevent - * comatibility breackage - */ - /* IMB_rect_from_float(ibuf); */ - } -} - static void draw_render_info(Scene *scene, Image *ima, ARegion *ar) { RenderResult *rr; @@ -442,10 +412,9 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rec MEM_freeN(rectf); } -static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy) +static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, Scene *scene, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy) { int x, y; - int color_manage = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT; /* set zoom */ glPixelZoom(zoomx, zoomy); @@ -479,10 +448,6 @@ static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - /* we don't draw floats buffers directly but - * convert them, and optionally apply curves */ - image_verify_buffer_float(ima, ibuf, color_manage); - display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); if (display_buffer) @@ -502,14 +467,14 @@ static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, glPixelZoom(1.0f, 1.0f); } -static unsigned int *get_part_from_ibuf(ImBuf *ibuf, short startx, short starty, short endx, short endy) +static unsigned int *get_part_from_buffer(unsigned int *buffer, int width, short startx, short starty, short endx, short endy) { unsigned int *rt, *rp, *rectmain; short y, heigth, len; /* the right offset in rectot */ - rt = ibuf->rect + (starty * ibuf->x + startx); + rt = buffer + (starty * width + startx); len = (endx - startx); heigth = (endy - starty); @@ -518,7 +483,7 @@ static unsigned int *get_part_from_ibuf(ImBuf *ibuf, short startx, short starty, for (y = 0; y < heigth; y++) { memcpy(rp, rt, len * 4); - rt += ibuf->x; + rt += width; rp += len; } return rectmain; @@ -526,28 +491,31 @@ static unsigned int *get_part_from_ibuf(ImBuf *ibuf, short startx, short starty, static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy) { - unsigned int *rect; + unsigned int *display_buffer, *rect; int dx, dy, sx, sy, x, y; - int color_manage = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT; + void *cache_handle; /* verify valid values, just leave this a while */ if (ima->xrep < 1) return; if (ima->yrep < 1) return; - + + display_buffer = (unsigned int *) IMB_display_buffer_acquire(ibuf, &scene->view_settings, + &scene->display_settings, &cache_handle); + + if (!display_buffer) + return; + glPixelZoom(zoomx, zoomy); if (sima->curtile >= ima->xrep * ima->yrep) sima->curtile = ima->xrep * ima->yrep - 1; - /* create char buffer from float if needed */ - image_verify_buffer_float(ima, ibuf, color_manage); - /* retrieve part of image buffer */ dx = ibuf->x / ima->xrep; dy = ibuf->y / ima->yrep; sx = (sima->curtile % ima->xrep) * dx; sy = (sima->curtile / ima->xrep) * dy; - rect = get_part_from_ibuf(ibuf, sx, sy, sx + dx, sy + dy); + rect = get_part_from_buffer(display_buffer, ibuf->x, sx, sy, sx + dx, sy + dy); /* draw repeated */ for (sy = 0; sy + dy <= ibuf->y; sy += dy) { @@ -560,6 +528,8 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene, glPixelZoom(1.0f, 1.0f); + IMB_display_buffer_release(cache_handle); + MEM_freeN(rect); } @@ -580,7 +550,7 @@ static void draw_image_buffer_repeated(const bContext *C, SpaceImage *sima, AReg if (ima && (ima->tpageflag & IMA_TILES)) draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, x, y, zoomx, zoomy); else - draw_image_buffer(C, sima, ar, scene, ima, ibuf, x, y, zoomx, zoomy); + draw_image_buffer(C, sima, ar, scene, ibuf, x, y, zoomx, zoomy); /* only draw until running out of time */ if ((PIL_check_seconds_timer() - time_current) > 0.25) @@ -798,7 +768,7 @@ void draw_image_main(const bContext *C, ARegion *ar) else if (ima && (ima->tpageflag & IMA_TILES)) draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, 0.0f, 0.0, zoomx, zoomy); else - draw_image_buffer(C, sima, ar, scene, ima, ibuf, 0.0f, 0.0f, zoomx, zoomy); + draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy); /* paint helpers */ if (sima->mode == SI_MODE_PAINT) From 196028a99fd87efdf2e73c2c0a9020687088e3fc Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 5 Sep 2012 13:58:01 +0000 Subject: [PATCH 112/160] Color Management: made OpenColorIO transformations aware of color unpremultiply Mainly behaves in the same way as legacy color transformation, but it'll give different result on over and under exposured areas. Not sure if it's indeed issue -- seems this behaves crappy in both of current stable release and OCIO branch. --- intern/opencolorio/ocio_capi.cpp | 51 +++++++++++++++++++ intern/opencolorio/ocio_capi.h | 2 + .../blender/editors/space_image/space_image.c | 1 + source/blender/imbuf/IMB_colormanagement.h | 3 +- source/blender/imbuf/intern/colormanagement.c | 49 +++++++++++++----- 5 files changed, 92 insertions(+), 14 deletions(-) diff --git a/intern/opencolorio/ocio_capi.cpp b/intern/opencolorio/ocio_capi.cpp index 15ef0dd25e9..6fec1185bd5 100644 --- a/intern/opencolorio/ocio_capi.cpp +++ b/intern/opencolorio/ocio_capi.cpp @@ -304,6 +304,34 @@ void OCIO_processorApply(ConstProcessorRcPtr *processor, PackedImageDesc *img) } } +void OCIO_processorApply_predivide(ConstProcessorRcPtr *processor, PackedImageDesc *img) +{ + try { + int channels = img->getNumChannels(); + + if (channels == 4) { + float *pixels = img->getData(); + + int width = img->getWidth(); + int height = img->getHeight(); + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + float *pixel = pixels + 4 * (y * width + x); + + OCIO_processorApplyRGBA_predivide(processor, pixel); + } + } + } + else { + (*processor)->apply(*img); + } + } + catch (Exception &exception) { + OCIO_reportException(exception); + } +} + void OCIO_processorApplyRGB(ConstProcessorRcPtr *processor, float *pixel) { (*processor)->applyRGB(pixel); @@ -314,6 +342,29 @@ void OCIO_processorApplyRGBA(ConstProcessorRcPtr *processor, float *pixel) (*processor)->applyRGBA(pixel); } +void OCIO_processorApplyRGBA_predivide(ConstProcessorRcPtr *processor, float *pixel) +{ + if (pixel[3] == 1.0f || pixel[3] == 0.0f) { + (*processor)->applyRGBA(pixel); + } + else { + float alpha, inv_alpha; + + alpha = pixel[3]; + inv_alpha = 1.0f / alpha; + + pixel[0] *= inv_alpha; + pixel[1] *= inv_alpha; + pixel[2] *= inv_alpha; + + (*processor)->applyRGBA(pixel); + + pixel[0] *= alpha; + pixel[1] *= alpha; + pixel[2] *= alpha; + } +} + void OCIO_processorRelease(ConstProcessorRcPtr *p) { delete p; diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index 1af77ad41ea..c3830f3fc72 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -83,8 +83,10 @@ ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(ConstConfigRcPtr *config, ConstProcessorRcPtr *OCIO_configGetProcessor(ConstConfigRcPtr *config, ConstTransformRcPtr *transform); void OCIO_processorApply(ConstProcessorRcPtr *processor, PackedImageDesc *img); +void OCIO_processorApply_predivide(ConstProcessorRcPtr *processor, PackedImageDesc *img); void OCIO_processorApplyRGB(ConstProcessorRcPtr *processor, float *pixel); void OCIO_processorApplyRGBA(ConstProcessorRcPtr *processor, float *pixel); +void OCIO_processorApplyRGBA_predivide(ConstProcessorRcPtr *processor, float *pixel); void OCIO_processorRelease(ConstProcessorRcPtr *p); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index cff1f987da6..439f6a49c7f 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -443,6 +443,7 @@ static void image_listener(ScrArea *sa, wmNotifier *wmn) break; case ND_MODE: case ND_RENDER_RESULT: + case ND_RENDER_OPTIONS: case ND_COMPO_RESULT: if (ED_space_image_show_render(sima)) image_scopes_tag_refresh(sa); diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 106ed2f6ea1..2df67b6912c 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -59,7 +59,8 @@ void IMB_colormanagement_validate_settings(struct ColorManagedDisplaySettings *d /* ** Color space transformation functions ** */ void IMB_colormanagement_colorspace_transform(float *buffer, int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace); + const char *from_colorspace, const char *to_colorspace, + int predivide); void IMB_colormanagement_pixel_to_role(float pixel[4], int role); void IMB_colormanagement_pixel_from_role(float pixel[4], int role); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 5e446d8cb81..f0b6a1bda1d 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -176,6 +176,7 @@ typedef struct ColormanageCacheKey { typedef struct ColormnaageCacheData { float exposure; /* exposure value cached buffer is calculated with */ float gamma; /* gamma value cached buffer is calculated with */ + int predivide; /* predivide flag of cached buffer */ } ColormnaageCacheData; typedef struct ColormanageCache { @@ -308,6 +309,7 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV ColormanageCacheKey key; ImBuf *cache_ibuf; int view_flag = 1 << (view_settings->view - 1); + int predivide = ibuf->flags & IB_cm_predivide; colormanage_settings_to_key(&key, view_settings, display_settings); @@ -335,7 +337,8 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV cache_data = colormanage_cachedata_get(cache_ibuf); if (cache_data->exposure != view_settings->exposure || - cache_data->gamma != view_settings->gamma) + cache_data->gamma != view_settings->gamma || + cache_data->predivide != predivide) { *cache_handle = NULL; @@ -358,6 +361,7 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting ImBuf *cache_ibuf; ColormnaageCacheData *cache_data; int view_flag = 1 << (view_settings->view - 1); + int predivide = ibuf->flags & IB_cm_predivide; struct MovieCache *moviecache = colormanage_moviecache_ensure(ibuf); colormanage_settings_to_key(&key, view_settings, display_settings); @@ -376,6 +380,7 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting cache_data = MEM_callocN(sizeof(ColormnaageCacheData), "color manage cache imbuf data"); cache_data->exposure = view_settings->exposure; cache_data->gamma = view_settings->gamma; + cache_data->predivide = predivide; colormanage_cachedata_set(cache_ibuf, cache_data); @@ -693,7 +698,6 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) int buffer_size = channels * width * height; - /* TODO: do we actually need to handle alpha premultiply in some way here? */ int predivide = handle->predivide; linear_buffer = MEM_callocN(buffer_size * sizeof(float), "color conversion linear buffer"); @@ -721,7 +725,7 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float)); IMB_colormanagement_colorspace_transform(linear_buffer, width, height, channels, - from_colorspace, to_colorspace); + from_colorspace, to_colorspace, predivide); } else { /* some processors would want to modify float original buffer @@ -758,7 +762,10 @@ static void *do_display_buffer_apply_thread(void *handle_v) img = OCIO_createPackedImageDesc(linear_buffer, width, height, channels, sizeof(float), channels * sizeof(float), channels * sizeof(float) * width); - OCIO_processorApply(processor, img); + if (predivide) + OCIO_processorApply_predivide(processor, img); + else + OCIO_processorApply(processor, img); OCIO_packedImageDescRelease(img); @@ -865,6 +872,7 @@ typedef struct ColorspaceTransformThread { int start_line; int tot_line; int channels; + int predivide; } ColorspaceTransformThread; typedef struct ColorspaceTransformInit { @@ -873,6 +881,7 @@ typedef struct ColorspaceTransformInit { int width; int height; int channels; + int predivide; } ColorspaceTransformInitData; static void colorspace_transform_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v) @@ -882,6 +891,7 @@ static void colorspace_transform_init_handle(void *handle_v, int start_line, int int channels = init_data->channels; int width = init_data->width; + int predivide = init_data->predivide; int offset = channels * start_line * width; @@ -897,10 +907,11 @@ static void colorspace_transform_init_handle(void *handle_v, int start_line, int handle->tot_line = tot_line; handle->channels = channels; + handle->predivide = predivide; } static void colorspace_transform_apply_threaded(float *buffer, int width, int height, int channels, - void *processor, void *(do_thread) (void *)) + void *processor, int predivide, void *(do_thread) (void *)) { ColorspaceTransformInitData init_data; @@ -909,6 +920,7 @@ static void colorspace_transform_apply_threaded(float *buffer, int width, int he init_data.width = width; init_data.height = height; init_data.channels = channels; + init_data.predivide = predivide; IMB_processor_apply_threaded(height, sizeof(ColorspaceTransformThread), &init_data, colorspace_transform_init_handle, do_thread); @@ -923,11 +935,15 @@ static void *do_color_space_transform_thread(void *handle_v) int channels = handle->channels; int width = handle->width; int height = handle->tot_line; + int predivide = handle->predivide; img = OCIO_createPackedImageDesc(buffer, width, height, channels, sizeof(float), channels * sizeof(float), channels * sizeof(float) * width); - OCIO_processorApply(processor, img); + if (predivide) + OCIO_processorApply_predivide(processor, img); + else + OCIO_processorApply(processor, img); OCIO_packedImageDescRelease(img); @@ -947,7 +963,8 @@ static ConstProcessorRcPtr *create_colorspace_transform_processor(const char *fr #endif void IMB_colormanagement_colorspace_transform(float *buffer, int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace) + const char *from_colorspace, const char *to_colorspace, + int predivide) { #ifdef WITH_OCIO ConstProcessorRcPtr *processor; @@ -966,8 +983,8 @@ void IMB_colormanagement_colorspace_transform(float *buffer, int width, int heig processor = create_colorspace_transform_processor(from_colorspace, to_colorspace); if (processor) { - colorspace_transform_apply_threaded(buffer, width, height, channels, - processor, do_color_space_transform_thread); + colorspace_transform_apply_threaded(buffer, width, height, channels, processor, predivide, + do_color_space_transform_thread); OCIO_processorRelease(processor); } @@ -1012,12 +1029,13 @@ void IMB_colormanagement_imbuf_to_role(ImBuf *ibuf, int role) if (ibuf->rect_float) { const char *from_colorspace = global_role_scene_linear; const char *to_colorspace = role_colorspace_name_get(role); + int predivide = ibuf->flags & IB_cm_predivide; if (ibuf->rect) imb_freerectImBuf(ibuf); IMB_colormanagement_colorspace_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace); + from_colorspace, to_colorspace, predivide); } #else (void) ibuf; @@ -1031,12 +1049,13 @@ void IMB_colormanagement_imbuf_from_role(ImBuf *ibuf, int role) if (ibuf->rect_float) { const char *from_colorspace = role_colorspace_name_get(role); const char *to_colorspace = global_role_scene_linear; + int predivide = ibuf->flags & IB_cm_predivide; if (ibuf->rect) imb_freerectImBuf(ibuf); IMB_colormanagement_colorspace_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace); + from_colorspace, to_colorspace, predivide); } #else (void) ibuf; @@ -1090,9 +1109,10 @@ void IMB_colormanagement_imbuf_make_scene_linear(ImBuf *ibuf, ColorManagedColors if (ibuf->rect_float) { const char *from_colorspace = colorspace_settings->name; const char *to_colorspace = global_role_scene_linear; + int predivide = ibuf->flags & IB_cm_predivide; IMB_colormanagement_colorspace_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace); + from_colorspace, to_colorspace, predivide); } #else (void) ibuf; @@ -1879,7 +1899,10 @@ static void partial_buffer_update_rect(unsigned char *display_buffer, const floa copy_v4_v4(pixel, (float *) linear_buffer + linear_index); - OCIO_processorApplyRGBA(processor, pixel); + if (predivide) + OCIO_processorApplyRGBA_predivide(processor, pixel); + else + OCIO_processorApplyRGBA(processor, pixel); rgba_float_to_uchar(display_buffer + display_index, pixel); } From 16a126622eea530003defc89deb7d425cd23cea9 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 5 Sep 2012 14:19:40 +0000 Subject: [PATCH 113/160] Merging r50413 through r50422 from trunk into soc-2011-tomato --- intern/cycles/render/attribute.cpp | 2 ++ source/blender/compositor/intern/COM_WorkScheduler.cpp | 6 ++++-- source/blender/editors/space_sequencer/sequencer_view.c | 4 ++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index 5c7966d6d96..7296f8bebba 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -102,6 +102,8 @@ ustring Attribute::standard_name(AttributeStandard std) return ustring("motion_pre"); else if(std == ATTR_STD_MOTION_POST) return ustring("motion_post"); + else if(std == ATTR_STD_PARTICLE) + return ustring("particle"); return ustring(); } diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp index 78e198ac9c2..f732a40e768 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.cpp +++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp @@ -93,8 +93,10 @@ void **g_highlightedNodesRead; if (node->original) { \ node = node->original; \ } \ - if (g_highlightIndex < MAX_HIGHLIGHT) { \ - g_highlightedNodes[g_highlightIndex++] = node; \ + if (g_highlightInitialized && g_highlightedNodes) { \ + if (g_highlightIndex < MAX_HIGHLIGHT) { \ + g_highlightedNodes[g_highlightIndex++] = node; \ + } \ } \ } \ } \ diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index 7dc82593a29..bb8242866bb 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -171,8 +171,12 @@ static void sample_exit(bContext *C, wmOperator *op) static int sample_invoke(bContext *C, wmOperator *op, wmEvent *event) { ARegion *ar = CTX_wm_region(C); + SpaceSeq *sseq = CTX_wm_space_seq(C); ImageSampleInfo *info; + if (sseq->mainb != SEQ_DRAW_IMG_IMBUF) + return OPERATOR_CANCELLED; + info = MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo"); info->art = ar->type; info->draw_handle = ED_region_draw_cb_activate(ar->type, sample_draw, info, REGION_DRAW_POST_PIXEL); From 7d980ca9694f1a19fe0e408939a34ed7b0b33f12 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 5 Sep 2012 14:29:15 +0000 Subject: [PATCH 114/160] Color Management: don't show input color space for byte images --- source/blender/editors/space_image/image_buttons.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index e33291e460f..799ecc3075e 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -731,8 +731,11 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char } if (ima->source != IMA_SRC_GENERATED) { - col = uiLayoutColumn(layout, FALSE); - uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings"); + /* OCIO_TODO: color space transformation for byte images is not implemented yet */ + if (ibuf && ibuf->rect_float) { + col = uiLayoutColumn(layout, FALSE); + uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings"); + } if (compact == 0) { /* background image view doesnt need these */ uiItemS(layout); From ee5bf889e9e00c93e5790a38cfe90af39b7b2423 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 5 Sep 2012 16:08:36 +0000 Subject: [PATCH 115/160] Color Management: RGB curves transform as a part of display transform This replaces per-image editor curve mapping which didn't behave properly (it was possible to open the same image in two image editors and setup different curves in this editors, but only last changed curve was applied on image) After discussion with Brecht decided to have something which works reliable and predictable and ended up with adding RGB curves as a part of display transform, which is applied before OCIO processor (to match old behavior). Setting white/black values from image editor (Ctrl/Shift + LMB) would affect on scene settings. This could break compatibility, but there's no reliable way to convert old semi-working settings into new one. --- source/blender/blenkernel/BKE_colortools.h | 1 + source/blender/blenkernel/intern/colortools.c | 11 +++ source/blender/blenkernel/intern/scene.c | 2 + source/blender/blenloader/intern/readfile.c | 10 +++ source/blender/blenloader/intern/writefile.c | 11 ++- .../editors/interface/interface_templates.c | 5 ++ .../editors/space_image/image_buttons.c | 49 ----------- .../blender/editors/space_image/image_ops.c | 18 ++-- .../blender/editors/space_image/space_image.c | 6 +- source/blender/imbuf/intern/colormanagement.c | 86 +++++++++++++++++-- source/blender/makesdna/DNA_color_types.h | 8 +- source/blender/makesdna/DNA_scene_types.h | 2 +- source/blender/makesdna/DNA_space_types.h | 7 +- source/blender/makesrna/intern/rna_color.c | 31 ++++++- source/blender/makesrna/intern/rna_space.c | 19 ---- 15 files changed, 170 insertions(+), 96 deletions(-) diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index 51d5b45cd5d..7c2c9bb62ce 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -104,6 +104,7 @@ void BKE_color_managed_display_settings_copy(struct ColorManagedDisplaySettings void BKE_color_managed_view_settings_init(struct ColorManagedViewSettings *settings); void BKE_color_managed_view_settings_copy(struct ColorManagedViewSettings *new_settings, const struct ColorManagedViewSettings *settings); +void BKE_color_managed_view_settings_free(struct ColorManagedViewSettings *settings); void BKE_color_managed_colorspace_settings_init(struct ColorManagedColorspaceSettings *colorspace_settings); void BKE_color_managed_colorspace_settings_copy(struct ColorManagedColorspaceSettings *colorspace_settings, diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 252add2c423..65bffe42a1e 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -175,6 +175,7 @@ void curvemapping_set_black_white(CurveMapping *cumap, const float black[3], con } curvemapping_set_black_white_ex(cumap->black, cumap->white, cumap->bwmul); + cumap->changed_timestamp++; } /* ***************** operations on single curve ************* */ @@ -1289,8 +1290,18 @@ void BKE_color_managed_view_settings_copy(ColorManagedViewSettings *new_settings { BLI_strncpy(new_settings->view_transform, settings->view_transform, sizeof(new_settings->view_transform)); + new_settings->flag = settings->flag; new_settings->exposure = settings->exposure; new_settings->gamma = settings->gamma; + + if (settings->curve_mapping) + new_settings->curve_mapping = curvemapping_copy(settings->curve_mapping); +} + +void BKE_color_managed_view_settings_free(ColorManagedViewSettings *settings) +{ + if (settings->curve_mapping) + curvemapping_free(settings->curve_mapping); } void BKE_color_managed_colorspace_settings_init(ColorManagedColorspaceSettings *colorspace_settings) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index e74413c3198..1bd8f3dfcd2 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -342,6 +342,8 @@ void BKE_scene_free(Scene *sce) MEM_freeN(sce->fps_info); sound_destroy_scene(sce); + + BKE_color_managed_view_settings_free(&sce->view_settings); } Scene *BKE_scene_add(const char *name) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 33693cf994b..4dc1ad1e5c9 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4904,6 +4904,14 @@ static void direct_link_sequence_modifiers(FileData *fd, ListBase *lb) } } +static void direct_link_view_settings(FileData *fd, ColorManagedViewSettings *view_settings) +{ + view_settings->curve_mapping = newdataadr(fd, view_settings->curve_mapping); + + if (view_settings->curve_mapping) + direct_link_curvemapping(fd, view_settings->curve_mapping); +} + static void direct_link_scene(FileData *fd, Scene *sce) { Editing *ed; @@ -5081,6 +5089,8 @@ static void direct_link_scene(FileData *fd, Scene *sce) sce->nodetree = newdataadr(fd, sce->nodetree); if (sce->nodetree) direct_link_nodetree(fd, sce->nodetree); + + direct_link_view_settings(fd, &sce->view_settings); } /* ************ READ WM ***************** */ diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 109a844352f..b8d63b3c5d5 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2119,6 +2119,13 @@ static void write_sequence_modifiers(WriteData *wd, ListBase *modbase) } } +static void write_view_settings(WriteData *wd, ColorManagedViewSettings *view_settings) +{ + if (view_settings->curve_mapping) { + write_curvemapping(wd, view_settings->curve_mapping); + } +} + static void write_scenes(WriteData *wd, ListBase *scebase) { Scene *sce; @@ -2261,7 +2268,9 @@ static void write_scenes(WriteData *wd, ListBase *scebase) writestruct(wd, DATA, "bNodeTree", 1, sce->nodetree); write_nodetree(wd, sce->nodetree); } - + + write_view_settings(wd, &sce->view_settings); + sce= sce->id.next; } /* flush helps the compression for undo-save */ diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 543ac18801c..79b9d313775 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2848,4 +2848,9 @@ void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *UNUSED(C), P col = uiLayoutColumn(layout, FALSE); uiItemR(col, &view_transform_ptr, "exposure", 0, NULL, ICON_NONE); uiItemR(col, &view_transform_ptr, "gamma", 0, NULL, ICON_NONE); + + col = uiLayoutColumn(layout, FALSE); + uiItemR(col, &view_transform_ptr, "use_curve_mapping", 0, NULL, ICON_NONE); + if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) + uiTemplateCurveMapping(col, &view_transform_ptr, "curve_mapping", 'c', TRUE, 0); } diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 799ecc3075e..90c6a5ef509 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -169,47 +169,6 @@ struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree) /* ************ panel stuff ************* */ -/* is used for both read and write... */ - -static int image_panel_poll(const bContext *C, PanelType *UNUSED(pt)) -{ - SpaceImage *sima = CTX_wm_space_image(C); - ImBuf *ibuf; - void *lock; - int result; - - ibuf = ED_space_image_acquire_buffer(sima, &lock); - result = ibuf && ibuf->rect_float; - ED_space_image_release_buffer(sima, lock); - - return result; -} - -static void image_panel_curves(const bContext *C, Panel *pa) -{ - bScreen *sc = CTX_wm_screen(C); - SpaceImage *sima = CTX_wm_space_image(C); - ImBuf *ibuf; - PointerRNA simaptr; - int levels; - void *lock; - - ibuf = ED_space_image_acquire_buffer(sima, &lock); - - if (ibuf) { - if (sima->cumap == NULL) - sima->cumap = curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); - - /* curvemap black/white levels only works for RGBA */ - levels = (ibuf->channels == 4); - - RNA_pointer_create(&sc->id, &RNA_SpaceImageEditor, sima, &simaptr); - uiTemplateCurveMapping(pa->layout, &simaptr, "curve", 'c', levels, 0); - } - - ED_space_image_release_buffer(sima, lock); -} - #if 0 /* 0: disable preview * otherwise refresh preview @@ -913,14 +872,6 @@ void image_buttons_register(ARegionType *art) { PanelType *pt; - pt = MEM_callocN(sizeof(PanelType), "spacetype image panel curves"); - strcpy(pt->idname, "IMAGE_PT_curves"); - strcpy(pt->label, "Curves"); - pt->draw = image_panel_curves; - pt->poll = image_panel_poll; - pt->flag |= PNL_DEFAULT_CLOSED; - BLI_addtail(&art->paneltypes, pt); - pt = MEM_callocN(sizeof(PanelType), "spacetype image panel gpencil"); strcpy(pt->idname, "IMAGE_PT_gpencil"); strcpy(pt->label, "Grease Pencil"); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index bc518645e43..44cb3ae578f 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -2053,7 +2053,9 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock); ImageSampleInfo *info = op->customdata; float fx, fy; - + Scene *scene = CTX_data_scene(C); + CurveMapping *curve_mapping = scene->view_settings.curve_mapping; + if (ibuf == NULL) { ED_space_image_release_buffer(sima, lock); info->draw = 0; @@ -2117,25 +2119,21 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->zf = ibuf->zbuf_float[y * ibuf->x + x]; info->zfp = &info->zf; } - - if (sima->cumap && ibuf->channels == 4) { + + if (curve_mapping && ibuf->channels == 4) { /* we reuse this callback for set curves point operators */ if (RNA_struct_find_property(op->ptr, "point")) { int point = RNA_enum_get(op->ptr, "point"); if (point == 1) { - curvemapping_set_black_white(sima->cumap, NULL, info->colfp); - if (ibuf->rect_float) - curvemapping_do_ibuf(sima->cumap, ibuf); + curvemapping_set_black_white(curve_mapping, NULL, info->colfp); } else if (point == 0) { - curvemapping_set_black_white(sima->cumap, info->colfp, NULL); - if (ibuf->rect_float) - curvemapping_do_ibuf(sima->cumap, ibuf); + curvemapping_set_black_white(curve_mapping, info->colfp, NULL); } } } - + // XXX node curve integration .. #if 0 { diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 439f6a49c7f..970f9d6d35d 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -195,9 +195,7 @@ static SpaceLink *image_new(const bContext *UNUSED(C)) static void image_free(SpaceLink *sl) { SpaceImage *simage = (SpaceImage *) sl; - - if (simage->cumap) - curvemapping_free(simage->cumap); + scopes_free(&simage->scopes); } @@ -217,8 +215,6 @@ static SpaceLink *image_duplicate(SpaceLink *sl) SpaceImage *simagen = MEM_dupallocN(sl); /* clear or remove stuff from old */ - if (simagen->cumap) - simagen->cumap = curvemapping_copy(simagen->cumap); scopes_new(&simagen->scopes); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index f0b6a1bda1d..3fff419895e 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -56,6 +56,7 @@ #include "BLI_string.h" #include "BLI_threads.h" +#include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_utildefines.h" #include "BKE_main.h" @@ -159,9 +160,11 @@ static int global_tot_view = 0; * to color management cache system and keeps calls small and nice. */ typedef struct ColormanageCacheViewSettings { + int flag; int view; float exposure; float gamma; + CurveMapping *curve_mapping; } ColormanageCacheViewSettings; typedef struct ColormanageCacheDisplaySettings { @@ -174,9 +177,12 @@ typedef struct ColormanageCacheKey { } ColormanageCacheKey; typedef struct ColormnaageCacheData { + int flag; /* view flags of cached buffer */ float exposure; /* exposure value cached buffer is calculated with */ float gamma; /* gamma value cached buffer is calculated with */ int predivide; /* predivide flag of cached buffer */ + CurveMapping *curve_mapping; /* curve mapping used for cached buffer */ + int curve_mapping_timestamp; /* time stamp of curve mapping used for cached buffer */ } ColormnaageCacheData; typedef struct ColormanageCache { @@ -264,6 +270,8 @@ static void colormanage_view_settings_to_cache(ColormanageCacheViewSettings *cac cache_view_settings->view = view; cache_view_settings->exposure = view_settings->exposure; cache_view_settings->gamma = view_settings->gamma; + cache_view_settings->flag = view_settings->flag; + cache_view_settings->curve_mapping = view_settings->curve_mapping; } static void colormanage_display_settings_to_cache(ColormanageCacheDisplaySettings *cache_display_settings, @@ -338,7 +346,10 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV if (cache_data->exposure != view_settings->exposure || cache_data->gamma != view_settings->gamma || - cache_data->predivide != predivide) + cache_data->predivide != predivide || + cache_data->flag != view_settings->flag || + cache_data->curve_mapping != view_settings->curve_mapping || + cache_data->curve_mapping_timestamp != view_settings->curve_mapping->changed_timestamp) { *cache_handle = NULL; @@ -381,6 +392,9 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting cache_data->exposure = view_settings->exposure; cache_data->gamma = view_settings->gamma; cache_data->predivide = predivide; + cache_data->flag = view_settings->flag; + cache_data->curve_mapping = view_settings->curve_mapping; + cache_data->curve_mapping_timestamp = view_settings->curve_mapping->changed_timestamp; colormanage_cachedata_set(cache_ibuf, cache_data); @@ -600,6 +614,7 @@ void IMB_colormanagement_exit(void) #ifdef WITH_OCIO typedef struct DisplayBufferThread { + CurveMapping *curve_mapping; void *processor; float *buffer; @@ -621,6 +636,7 @@ typedef struct DisplayBufferThread { typedef struct DisplayBufferInitData { ImBuf *ibuf; + CurveMapping *curve_mapping; void *processor; float *buffer; unsigned char *byte_buffer; @@ -636,6 +652,7 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l DisplayBufferThread *handle = (DisplayBufferThread *) handle_v; DisplayBufferInitData *init_data = (DisplayBufferInitData *) init_data_v; ImBuf *ibuf = init_data->ibuf; + CurveMapping *curve_mapping = init_data->curve_mapping; int predivide = ibuf->flags & IB_cm_predivide; int channels = ibuf->channels; @@ -667,17 +684,19 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l handle->channels = channels; handle->dither = dither; handle->predivide = predivide; + handle->curve_mapping = curve_mapping; handle->nolinear_float = ibuf->colormanage_flags & IMB_COLORMANAGE_NOLINEAR_FLOAT; } static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned char *byte_buffer, float *display_buffer, unsigned char *display_buffer_byte, - void *processor, void *(do_thread) (void *)) + CurveMapping *curve_mapping, void *processor, void *(do_thread) (void *)) { DisplayBufferInitData init_data; init_data.ibuf = ibuf; + init_data.curve_mapping = curve_mapping; init_data.processor = processor; init_data.buffer = buffer; init_data.byte_buffer = byte_buffer; @@ -746,6 +765,7 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) static void *do_display_buffer_apply_thread(void *handle_v) { DisplayBufferThread *handle = (DisplayBufferThread *) handle_v; + CurveMapping *curve_mapping = handle->curve_mapping; ConstProcessorRcPtr *processor = (ConstProcessorRcPtr *) handle->processor; PackedImageDesc *img; float *buffer = handle->buffer; @@ -759,6 +779,27 @@ static void *do_display_buffer_apply_thread(void *handle_v) float *linear_buffer = display_buffer_apply_get_linear_buffer(handle); + if (curve_mapping) { + int x, y; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + float *pixel = linear_buffer + channels * (y * width + x); + + if (channels == 1) { + pixel[0] = curvemap_evaluateF(curve_mapping->cm, pixel[0]); + } + else if (channels == 2) { + pixel[0] = curvemap_evaluateF(curve_mapping->cm, pixel[0]); + pixel[1] = curvemap_evaluateF(curve_mapping->cm, pixel[1]); + } + else { + curvemapping_evaluate_premulRGBF(curve_mapping, pixel, pixel); + } + } + } + } + img = OCIO_createPackedImageDesc(linear_buffer, width, height, channels, sizeof(float), channels * sizeof(float), channels * sizeof(float) * width); @@ -848,9 +889,20 @@ static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_bu processor = create_display_buffer_processor(view_transform, display, exposure, gamma); if (processor) { + CurveMapping *curve_mapping = NULL; + + if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) { + curve_mapping = view_settings->curve_mapping; + + curvemapping_premultiply(curve_mapping, FALSE); + } + display_buffer_apply_threaded(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect, - display_buffer, display_buffer_byte, processor, + display_buffer, display_buffer_byte, curve_mapping, processor, do_display_buffer_apply_thread); + + if (curve_mapping) + curvemapping_premultiply(curve_mapping, TRUE); } OCIO_processorRelease(processor); @@ -1324,8 +1376,32 @@ void IMB_display_buffer_pixel(float result[4], const float pixel[4], const Colo processor = create_display_buffer_processor(view_transform, display, exposure, gamma); - if (processor) - OCIO_processorApplyRGBA(processor, result); + if (processor) { + + if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) { + CurveMapping *curve_mapping = NULL; + + /* curve mapping could be used meanwhile to compute display buffer, + * so need to lock here to be sure we're not changing curve mapping + * from separated threads + */ + BLI_lock_thread(LOCK_COLORMANAGE); + + curve_mapping = view_settings->curve_mapping; + + curvemapping_premultiply(curve_mapping, FALSE); + + curvemapping_evaluate_premulRGBF(curve_mapping, result, result); + OCIO_processorApplyRGBA(processor, result); + + curvemapping_premultiply(curve_mapping, TRUE); + + BLI_unlock_thread(LOCK_COLORMANAGE); + } + else { + OCIO_processorApplyRGBA(processor, result); + } + } #else (void) view_settings; (void) display_settings; diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h index 5ccc2579179..560caa40cff 100644 --- a/source/blender/makesdna/DNA_color_types.h +++ b/source/blender/makesdna/DNA_color_types.h @@ -161,9 +161,11 @@ typedef struct Scopes { #define SCOPES_WAVEFRM_YCC_JPEG 4 typedef struct ColorManagedViewSettings { + int flag, pad; char view_transform[64]; /* view transform which is being applied when displaying buffer on the screen */ float exposure; /* fstop exposure */ float gamma; /* post-display gamma transform */ + struct CurveMapping *curve_mapping; /* pre-display RGB curves transform */ } ColorManagedViewSettings; typedef struct ColorManagedDisplaySettings { @@ -174,5 +176,9 @@ typedef struct ColorManagedColorspaceSettings { char name[64]; } ColorManagedColorspaceSettings; -#endif +/* ColorManagedViewSettings->flag */ +enum { + COLORMANAGE_VIEW_USE_CURVES = (1 << 0) +}; +#endif diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index ed0e27917ad..51186c9bb6e 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -41,7 +41,7 @@ extern "C" { #endif -#include "DNA_color_types.h" // color management +#include "DNA_color_types.h" /* color management */ #include "DNA_vec_types.h" #include "DNA_listBase.h" #include "DNA_ID.h" diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 7196b6b7059..6cc4541f19e 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -40,7 +40,7 @@ #include "DNA_outliner_types.h" /* for TreeStoreElem */ #include "DNA_image_types.h" /* ImageUser */ #include "DNA_movieclip_types.h" /* MovieClipUser */ -#include "DNA_sequence_types.h" /* SequencerScopes */ +#include "DNA_sequence_types.h" /* SequencerScopes */ /* Hum ... Not really nice... but needed for spacebuts. */ #include "DNA_view2d_types.h" @@ -688,8 +688,9 @@ typedef struct SpaceImage { struct Image *image; struct ImageUser iuser; - struct CurveMapping *cumap; - + + struct CurveMapping *cumap DNA_DEPRECATED; /* was switched to scene's color management settings */ + struct Scopes scopes; /* histogram waveform and vectorscope */ struct Histogram sample_line_hist; /* sample line histogram */ diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 45d6ea2951e..facadf4258b 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -423,6 +423,22 @@ static EnumPropertyItem* rna_ColorManagedViewSettings_view_transform_itemf(bCont return items; } +static void rna_ColorManagedViewSettings_use_curves_set(PointerRNA *ptr, int value) +{ + ColorManagedViewSettings *view_settings = (ColorManagedViewSettings *) ptr->data; + + if (value) { + view_settings->flag |= COLORMANAGE_VIEW_USE_CURVES; + + if (view_settings->curve_mapping == NULL) { + view_settings->curve_mapping = curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); + } + } + else { + view_settings->flag &= ~COLORMANAGE_VIEW_USE_CURVES; + } +} + static int rna_ColorManagedColorspaceSettings_colorspace_get(struct PointerRNA *ptr) { ColorManagedColorspaceSettings *colorspace = (ColorManagedColorspaceSettings *) ptr->data; @@ -869,14 +885,25 @@ static void rna_def_colormanage(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "exposure"); RNA_def_property_range(prop, -10.0f, 10.0f); RNA_def_property_float_default(prop, 0.0f); - RNA_def_property_ui_text(prop, "Exposure", "Exposure (stops) applied on displaying image buffers"); + RNA_def_property_ui_text(prop, "Exposure", "Exposure (stops) applied after display transform"); RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update"); prop = RNA_def_property(srna, "gamma", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "gamma"); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_range(prop, 0.0f, 5.0f); - RNA_def_property_ui_text(prop, "Gamma", "Amount f gamma modification for displaying image buffers"); + RNA_def_property_ui_text(prop, "Gamma", "Amount of gamma modification applied after display transform"); + RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update"); + + prop = RNA_def_property(srna, "curve_mapping", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "curve_mapping"); + RNA_def_property_ui_text(prop, "Curve", "Color curve mapping applied before display transform"); + RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update"); + + prop = RNA_def_property(srna, "use_curve_mapping", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", COLORMANAGE_VIEW_USE_CURVES); + RNA_def_property_boolean_funcs(prop, NULL, "rna_ColorManagedViewSettings_use_curves_set"); + RNA_def_property_ui_text(prop, "Use Curves", "Use RGB curved for pre-display transformation"); RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update"); /* ** Colorspace ** */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index c4a60dba025..80860dbdf26 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -658,20 +658,6 @@ static void rna_SpaceImageEditor_cursor_location_set(PointerRNA *ptr, const floa } } -static void rna_SpaceImageEditor_curves_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) -{ - SpaceImage *sima = (SpaceImage *)ptr->data; - ImBuf *ibuf; - void *lock; - - ibuf = ED_space_image_acquire_buffer(sima, &lock); - if (ibuf->rect_float) - curvemapping_do_ibuf(sima->cumap, ibuf); - ED_space_image_release_buffer(sima, lock); - - WM_main_add_notifier(NC_IMAGE, sima->image); -} - static void rna_SpaceImageEditor_scopes_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) { SpaceImage *sima = (SpaceImage *)ptr->data; @@ -1980,11 +1966,6 @@ static void rna_def_space_image(BlenderRNA *brna) "Parameters defining which layer, pass and frame of the image is displayed"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); - prop = RNA_def_property(srna, "curve", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "cumap"); - RNA_def_property_ui_text(prop, "Curve", "Color curve mapping to use for displaying the image"); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, "rna_SpaceImageEditor_curves_update"); - prop = RNA_def_property(srna, "scopes", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "scopes"); RNA_def_property_struct_type(prop, "Scopes"); From 4d152140a3a76b61e4a234dce536694f9fdfe7dc Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 5 Sep 2012 16:24:33 +0000 Subject: [PATCH 116/160] Color Management: exposure is in fact pre-display transfrom --- source/blender/makesrna/intern/rna_color.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index facadf4258b..2ebac408b77 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -885,7 +885,7 @@ static void rna_def_colormanage(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "exposure"); RNA_def_property_range(prop, -10.0f, 10.0f); RNA_def_property_float_default(prop, 0.0f); - RNA_def_property_ui_text(prop, "Exposure", "Exposure (stops) applied after display transform"); + RNA_def_property_ui_text(prop, "Exposure", "Exposure (stops) applied before display transform"); RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update"); prop = RNA_def_property(srna, "gamma", PROP_FLOAT, PROP_FACTOR); From bac6f03e16ea410cce78e10f783c3b27865d6237 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 5 Sep 2012 16:29:16 +0000 Subject: [PATCH 117/160] Color Management: fix for dereferencing NULL pointer --- source/blender/imbuf/intern/colormanagement.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 3fff419895e..f394f845769 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -318,6 +318,8 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV ImBuf *cache_ibuf; int view_flag = 1 << (view_settings->view - 1); int predivide = ibuf->flags & IB_cm_predivide; + CurveMapping *curve_mapping = view_settings->curve_mapping; + int curve_mapping_timestamp = curve_mapping ? curve_mapping->changed_timestamp : 0; colormanage_settings_to_key(&key, view_settings, display_settings); @@ -348,8 +350,8 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV cache_data->gamma != view_settings->gamma || cache_data->predivide != predivide || cache_data->flag != view_settings->flag || - cache_data->curve_mapping != view_settings->curve_mapping || - cache_data->curve_mapping_timestamp != view_settings->curve_mapping->changed_timestamp) + cache_data->curve_mapping != curve_mapping || + cache_data->curve_mapping_timestamp != curve_mapping_timestamp) { *cache_handle = NULL; @@ -374,6 +376,8 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting int view_flag = 1 << (view_settings->view - 1); int predivide = ibuf->flags & IB_cm_predivide; struct MovieCache *moviecache = colormanage_moviecache_ensure(ibuf); + CurveMapping *curve_mapping = view_settings->curve_mapping; + int curve_mapping_timestamp = curve_mapping ? curve_mapping->changed_timestamp : 0; colormanage_settings_to_key(&key, view_settings, display_settings); @@ -393,8 +397,8 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting cache_data->gamma = view_settings->gamma; cache_data->predivide = predivide; cache_data->flag = view_settings->flag; - cache_data->curve_mapping = view_settings->curve_mapping; - cache_data->curve_mapping_timestamp = view_settings->curve_mapping->changed_timestamp; + cache_data->curve_mapping = curve_mapping; + cache_data->curve_mapping_timestamp = curve_mapping_timestamp; colormanage_cachedata_set(cache_ibuf, cache_data); From 0b778a902691b4421067f7826bb6e0b6a4d8cec5 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 6 Sep 2012 09:44:32 +0000 Subject: [PATCH 118/160] Merging r50423 through r50449 from trunk into soc-2011-tomato --- .../audaspace/intern/AUD_ReferenceHandler.cpp | 2 +- intern/cycles/kernel/kernel_accumulate.h | 2 +- intern/cycles/kernel/kernel_triangle.h | 40 ++- intern/cycles/kernel/kernel_types.h | 26 ++ intern/cycles/kernel/osl/CMakeLists.txt | 1 + intern/cycles/kernel/osl/bsdf_phong.cpp | 277 ++++++++++++++++++ intern/cycles/kernel/osl/osl_closures.cpp | 2 + intern/cycles/kernel/osl/osl_closures.h | 6 + intern/cycles/kernel/osl/osl_services.h | 6 +- intern/cycles/kernel/osl/osl_shader.h | 8 +- intern/cycles/render/attribute.cpp | 26 +- intern/cycles/render/attribute.h | 1 - intern/cycles/render/mesh.cpp | 2 +- intern/ghost/GHOST_IEvent.h | 16 +- intern/ghost/GHOST_IEventConsumer.h | 12 +- intern/ghost/GHOST_ISystem.h | 133 ++++----- intern/ghost/GHOST_ISystemPaths.h | 12 +- intern/ghost/GHOST_ITimerTask.h | 16 +- intern/ghost/GHOST_IWindow.h | 104 +++---- intern/ghost/GHOST_Path-api.h | 10 +- intern/ghost/GHOST_Rect.h | 68 ++--- intern/ghost/GHOST_Types.h | 4 +- intern/ghost/intern/GHOST_Buttons.h | 12 +- .../intern/GHOST_CallbackEventConsumer.cpp | 4 +- .../intern/GHOST_CallbackEventConsumer.h | 12 +- intern/ghost/intern/GHOST_DisplayManager.cpp | 4 +- intern/ghost/intern/GHOST_DisplayManager.h | 46 +-- .../intern/GHOST_DisplayManagerCarbon.cpp | 4 +- .../ghost/intern/GHOST_DisplayManagerCarbon.h | 42 +-- .../ghost/intern/GHOST_DisplayManagerCocoa.h | 36 +-- .../ghost/intern/GHOST_DisplayManagerCocoa.mm | 4 +- .../ghost/intern/GHOST_DisplayManagerWin32.h | 34 +-- intern/ghost/intern/GHOST_DisplayManagerX11.h | 34 +-- intern/ghost/intern/GHOST_DropTargetWin32.h | 30 +- intern/ghost/intern/GHOST_DropTargetX11.h | 28 +- intern/ghost/intern/GHOST_Event.h | 18 +- intern/ghost/intern/GHOST_EventButton.h | 14 +- intern/ghost/intern/GHOST_EventCursor.h | 12 +- intern/ghost/intern/GHOST_EventDragnDrop.h | 14 +- intern/ghost/intern/GHOST_EventKey.h | 18 +- intern/ghost/intern/GHOST_EventManager.cpp | 4 +- intern/ghost/intern/GHOST_EventManager.h | 32 +- intern/ghost/intern/GHOST_EventPrinter.h | 8 +- intern/ghost/intern/GHOST_EventString.h | 12 +- intern/ghost/intern/GHOST_EventTrackpad.h | 10 +- intern/ghost/intern/GHOST_EventWheel.h | 10 +- intern/ghost/intern/GHOST_ISystem.cpp | 4 +- intern/ghost/intern/GHOST_ISystemPaths.cpp | 4 +- intern/ghost/intern/GHOST_ModifierKeys.cpp | 4 +- intern/ghost/intern/GHOST_ModifierKeys.h | 20 +- intern/ghost/intern/GHOST_System.h | 104 +++---- intern/ghost/intern/GHOST_SystemCarbon.cpp | 6 +- intern/ghost/intern/GHOST_SystemCarbon.h | 94 +++--- intern/ghost/intern/GHOST_SystemCocoa.h | 104 +++---- intern/ghost/intern/GHOST_SystemCocoa.mm | 77 +++-- intern/ghost/intern/GHOST_SystemPaths.h | 6 +- intern/ghost/intern/GHOST_SystemPathsCarbon.h | 12 +- intern/ghost/intern/GHOST_SystemPathsCocoa.h | 6 +- intern/ghost/intern/GHOST_SystemPathsWin32.h | 12 +- intern/ghost/intern/GHOST_SystemPathsX11.h | 6 +- intern/ghost/intern/GHOST_SystemWin32.h | 163 ++++++----- intern/ghost/intern/GHOST_SystemX11.cpp | 24 +- intern/ghost/intern/GHOST_SystemX11.h | 74 ++--- intern/ghost/intern/GHOST_TimerManager.cpp | 4 +- intern/ghost/intern/GHOST_TimerManager.h | 28 +- intern/ghost/intern/GHOST_TimerTask.h | 36 +-- intern/ghost/intern/GHOST_Window.cpp | 4 +- intern/ghost/intern/GHOST_Window.h | 72 ++--- intern/ghost/intern/GHOST_WindowCarbon.cpp | 4 +- intern/ghost/intern/GHOST_WindowCarbon.h | 88 +++--- intern/ghost/intern/GHOST_WindowCocoa.h | 108 +++---- intern/ghost/intern/GHOST_WindowCocoa.mm | 261 ++++++++--------- intern/ghost/intern/GHOST_WindowManager.cpp | 4 +- intern/ghost/intern/GHOST_WindowManager.h | 40 +-- intern/ghost/intern/GHOST_WindowWin32.cpp | 4 +- intern/ghost/intern/GHOST_WindowWin32.h | 92 +++--- intern/ghost/intern/GHOST_WindowX11.cpp | 6 +- intern/ghost/intern/GHOST_WindowX11.h | 34 +-- intern/ghost/test/gears/GHOST_C-Test.c | 4 +- intern/ghost/test/gears/GHOST_Test.cpp | 4 +- source/blender/blenfont/intern/blf_lang.c | 3 +- source/blender/blenkernel/BKE_customdata.h | 2 - source/blender/blenkernel/BKE_mask.h | 3 - source/blender/blenkernel/BKE_object_deform.h | 2 +- source/blender/blenkernel/BKE_script.h | 2 - source/blender/blenkernel/BKE_shrinkwrap.h | 6 +- source/blender/blenkernel/intern/library.c | 2 +- source/blender/blenkernel/intern/mball.c | 33 ++- source/blender/blenkernel/intern/sequencer.c | 41 ++- source/blender/blenkernel/intern/shrinkwrap.c | 4 +- .../blender/blenkernel/intern/writeffmpeg.c | 18 +- source/blender/blenlib/BLI_math_vector.h | 1 + source/blender/blenlib/BLI_path_util.h | 1 - .../blenlib/intern/math_vector_inline.c | 7 + source/blender/blenloader/intern/readfile.c | 12 +- source/blender/bmesh/bmesh.h | 5 + source/blender/bmesh/intern/bmesh_core.c | 1 + source/blender/bmesh/intern/bmesh_polygon.c | 47 +-- source/blender/bmesh/operators/bmo_connect.c | 58 ++-- .../blender/bmesh/operators/bmo_subdivide.c | 140 +++++---- source/blender/compositor/COM_compositor.h | 5 +- .../compositor/intern/COM_Converter.cpp | 6 +- .../intern/COM_ExecutionSystemHelper.h | 2 +- .../operations/COM_RenderLayersImageProg.h | 2 +- .../blender/editors/animation/anim_filter.c | 4 +- source/blender/editors/armature/reeb.c | 2 +- source/blender/editors/armature/reeb.h | 4 +- source/blender/editors/curve/editcurve.c | 14 +- source/blender/editors/include/ED_mesh.h | 3 - source/blender/editors/include/ED_render.h | 8 +- source/blender/editors/io/io_collada.h | 2 +- source/blender/editors/io/io_ops.h | 2 +- source/blender/editors/mesh/editmesh_slide.c | 54 +++- source/blender/editors/screen/glutil.c | 6 +- .../editors/space_sequencer/sequencer_draw.c | 6 +- .../space_sequencer/sequencer_intern.h | 2 - source/blender/editors/uvedit/uvedit_intern.h | 4 - source/blender/ikplugin/BIK_api.h | 6 +- source/blender/imbuf/intern/imbuf_cocoa.m | 2 +- source/blender/makesdna/DNA_meshdata_types.h | 1 - source/blender/makesdna/DNA_scene_types.h | 5 +- source/blender/makesdna/DNA_screen_types.h | 9 - source/blender/makesdna/DNA_sequence_types.h | 5 - source/blender/makesdna/DNA_userdef_types.h | 1 - source/blender/makesrna/intern/rna_scene.c | 4 +- source/blender/makesrna/intern/rna_userdef.c | 3 +- .../modifiers/intern/MOD_weightvgproximity.c | 2 +- .../render/intern/include/render_types.h | 1 - source/blender/render/intern/include/sunsky.h | 4 +- .../render/intern/include/volumetric.h | 3 - .../BlenderRoutines/BL_KetsjiEmbedStart.cpp | 96 +++--- .../gameengine/Expressions/PyObjectPlus.cpp | 4 +- .../GameLogic/Joystick/SCA_Joystick.cpp | 10 +- .../GameLogic/Joystick/SCA_JoystickDefines.h | 6 +- .../gameengine/GamePlayer/ghost/GPG_ghost.cpp | 19 +- source/gameengine/Ketsji/KX_PythonMain.cpp | 2 +- 136 files changed, 1898 insertions(+), 1528 deletions(-) create mode 100644 intern/cycles/kernel/osl/bsdf_phong.cpp diff --git a/intern/audaspace/intern/AUD_ReferenceHandler.cpp b/intern/audaspace/intern/AUD_ReferenceHandler.cpp index 3e9f6707262..6aa4f87ea96 100644 --- a/intern/audaspace/intern/AUD_ReferenceHandler.cpp +++ b/intern/audaspace/intern/AUD_ReferenceHandler.cpp @@ -22,7 +22,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file audaspace/intern/AUD_Reference.cpp +/** \file audaspace/intern/AUD_ReferenceHandler.cpp * \ingroup audaspaceintern */ diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index e73b2ba70b8..2f2314c9a8b 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -301,7 +301,7 @@ __device_inline float3 path_radiance_sum(KernelGlobals *kg, PathRadiance *L) __device_inline void path_radiance_clamp(PathRadiance *L, float3 *L_sum, float clamp) { - #ifdef WITH_OSL + #ifdef __OSL__ using std::isfinite; #endif diff --git a/intern/cycles/kernel/kernel_triangle.h b/intern/cycles/kernel/kernel_triangle.h index 492800e8aab..901034cfac6 100644 --- a/intern/cycles/kernel/kernel_triangle.h +++ b/intern/cycles/kernel/kernel_triangle.h @@ -15,7 +15,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - + #include "kernel_projection.h" CCL_NAMESPACE_BEGIN @@ -183,17 +183,39 @@ __device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData *s /* motion */ +/* note: declared in kernel.h, have to add it here because kernel.h is not available */ +bool kernel_osl_use(KernelGlobals *kg); + __device int triangle_find_attribute(KernelGlobals *kg, ShaderData *sd, uint id) { - /* find attribute by unique id */ - uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride; - uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset); - while(attr_map.x != id) - attr_map = kernel_tex_fetch(__attributes_map, ++attr_offset); - - /* return result */ - return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : attr_map.z; +#ifdef __OSL__ + if (kernel_osl_use(kg)) { + /* for OSL, a hash map is used to lookup the attribute by name. */ + OSLGlobals::AttributeMap &attr_map = kg->osl.attribute_map[sd->object]; + ustring stdname = ustring(std::string("std::") + attribute_standard_name((AttributeStandard)id).c_str()); + OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname); + if (it != attr_map.end()) { + const OSLGlobals::Attribute &osl_attr = it->second; + /* return result */ + return (osl_attr.elem == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : osl_attr.offset; + } + else + return (int)ATTR_STD_NOT_FOUND; + } + else +#endif + { + /* for SVM, find attribute by unique id */ + uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride; + uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset); + + while(attr_map.x != id) + attr_map = kernel_tex_fetch(__attributes_map, ++attr_offset); + + /* return result */ + return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : attr_map.z; + } } __device float4 triangle_motion_vector(KernelGlobals *kg, ShaderData *sd) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 39e088583c4..7faa1323258 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -22,6 +22,8 @@ #include "kernel_math.h" #include "svm/svm_types.h" +#include "util_string.h" + #ifndef __KERNEL_GPU__ #define __KERNEL_CPU__ #endif @@ -368,6 +370,30 @@ typedef enum AttributeStandard { ATTR_STD_NOT_FOUND = ~0 } AttributeStandard; +__device string attribute_standard_name(AttributeStandard std) +{ + if(std == ATTR_STD_VERTEX_NORMAL) + return string("N"); + else if(std == ATTR_STD_FACE_NORMAL) + return string("Ng"); + else if(std == ATTR_STD_UV) + return string("uv"); + else if(std == ATTR_STD_GENERATED) + return string("generated"); + else if(std == ATTR_STD_POSITION_UNDEFORMED) + return string("undeformed"); + else if(std == ATTR_STD_POSITION_UNDISPLACED) + return string("undisplaced"); + else if(std == ATTR_STD_MOTION_PRE) + return string("motion_pre"); + else if(std == ATTR_STD_MOTION_POST) + return string("motion_post"); + else if(std == ATTR_STD_PARTICLE) + return string("particle"); + + return string(); +} + /* Closure data */ #define MAX_CLOSURE 8 diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt index ce82d901c44..ea675456e6d 100644 --- a/intern/cycles/kernel/osl/CMakeLists.txt +++ b/intern/cycles/kernel/osl/CMakeLists.txt @@ -13,6 +13,7 @@ set(SRC bsdf_ashikhmin_velvet.cpp bsdf_diffuse.cpp bsdf_oren_nayar.cpp + bsdf_phong.cpp bsdf_microfacet.cpp bsdf_reflection.cpp bsdf_refraction.cpp diff --git a/intern/cycles/kernel/osl/bsdf_phong.cpp b/intern/cycles/kernel/osl/bsdf_phong.cpp new file mode 100644 index 00000000000..57745079d33 --- /dev/null +++ b/intern/cycles/kernel/osl/bsdf_phong.cpp @@ -0,0 +1,277 @@ +/* + * Adapted from Open Shading Language with this license: + * + * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. + * All Rights Reserved. + * + * Modifications Copyright 2012, 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 + +#include +#include "osl_closures.h" +#include "util_math.h" + +CCL_NAMESPACE_BEGIN + +using namespace OSL; + +// vanilla phong - leaks energy at grazing angles +// see Global Illumination Compendium entry (66) +class PhongClosure : public BSDFClosure { +public: + Vec3 m_N; + float m_exponent; + PhongClosure() : BSDFClosure(Labels::GLOSSY) { } + + void setup() {}; + + bool mergeable (const ClosurePrimitive *other) const { + const PhongClosure *comp = (const PhongClosure *)other; + return m_N == comp->m_N && m_exponent == comp->m_exponent && + BSDFClosure::mergeable(other); + } + + size_t memsize () const { return sizeof(*this); } + + const char *name () const { return "phong"; } + + void print_on (std::ostream &out) const { + out << name() << " (("; + out << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; + out << m_exponent << ")"; + } + + float albedo (const Vec3 &omega_out) const + { + return 1.0f; + } + + Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + float cosNI = m_N.dot(omega_in); + float cosNO = m_N.dot(omega_out); + if (cosNI > 0 && cosNO > 0) { + // reflect the view vector + Vec3 R = (2 * cosNO) * m_N - omega_out; + float cosRI = R.dot(omega_in); + if (cosRI > 0) { + float common = 0.5f * (float) M_1_PI * powf(cosRI, m_exponent); + float out = cosNI * (m_exponent + 2) * common; + pdf = (m_exponent + 1) * common; + return Color3 (out, out, out); + } + } + return Color3 (0, 0, 0); + } + + Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + return Color3 (0, 0, 0); + } + + ustring sample (const Vec3 &Ng, + const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, + float randu, float randv, + Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, + float &pdf, Color3 &eval) const + { + float cosNO = m_N.dot(omega_out); + if (cosNO > 0) { + // reflect the view vector + Vec3 R = (2 * cosNO) * m_N - omega_out; + domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; + domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; + Vec3 T, B; + make_orthonormals (R, T, B); + float phi = 2 * (float) M_PI * randu; + float cosTheta = powf(randv, 1 / (m_exponent + 1)); + float sinTheta2 = 1 - cosTheta * cosTheta; + float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; + omega_in = (cosf(phi) * sinTheta) * T + + (sinf(phi) * sinTheta) * B + + ( cosTheta) * R; + if (Ng.dot(omega_in) > 0) + { + // common terms for pdf and eval + float cosNI = m_N.dot(omega_in); + // make sure the direction we chose is still in the right hemisphere + if (cosNI > 0) + { + float common = 0.5f * (float) M_1_PI * powf(cosTheta, m_exponent); + pdf = (m_exponent + 1) * common; + float out = cosNI * (m_exponent + 2) * common; + eval.setValue(out, out, out); + // Since there is some blur to this reflection, make the + // derivatives a bit bigger. In theory this varies with the + // exponent but the exact relationship is complex and + // requires more ops than are practical. + domega_in_dx *= 10; + domega_in_dy *= 10; + } + } + } + return Labels::REFLECT; + } +}; + + +class PhongRampClosure : public BSDFClosure { +public: + static const int MAXCOLORS = 8; + Vec3 m_N; + float m_exponent; + Color3 m_colors[MAXCOLORS]; + PhongRampClosure() : BSDFClosure(Labels::GLOSSY) { } + + void setup() {}; + + bool mergeable (const ClosurePrimitive *other) const { + const PhongRampClosure *comp = (const PhongRampClosure *)other; + if (! (m_N == comp->m_N && m_exponent == comp->m_exponent && + BSDFClosure::mergeable(other))) + return false; + for (int i = 0; i < MAXCOLORS; ++i) + if (m_colors[i] != comp->m_colors[i]) + return false; + return true; + } + + size_t memsize () const { return sizeof(*this); } + + const char *name () const { return "phong_ramp"; } + + void print_on (std::ostream &out) const { + out << name() << " (("; + out << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; + out << m_exponent << ")"; + } + + Color3 get_color (float pos) const + { + float npos = pos * (float)(MAXCOLORS - 1); + int ipos = (int)npos; + if (ipos >= (MAXCOLORS - 1)) + return m_colors[MAXCOLORS - 1]; + float offset = npos - (float)ipos; + return m_colors[ipos] * (1.0f - offset) + m_colors[ipos+1] * offset; + } + + float albedo (const Vec3 &omega_out) const + { + return 1.0f; + } + + Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + float cosNI = m_N.dot(omega_in); + float cosNO = m_N.dot(omega_out); + if (cosNI > 0 && cosNO > 0) { + // reflect the view vector + Vec3 R = (2 * cosNO) * m_N - omega_out; + float cosRI = R.dot(omega_in); + if (cosRI > 0) { + float cosp = powf(cosRI, m_exponent); + float common = 0.5f * (float) M_1_PI * cosp; + float out = cosNI * (m_exponent + 2) * common; + pdf = (m_exponent + 1) * common; + return get_color(cosp) * out; + } + } + return Color3 (0, 0, 0); + } + + Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const + { + return Color3 (0, 0, 0); + } + + ustring sample (const Vec3 &Ng, + const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, + float randu, float randv, + Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, + float &pdf, Color3 &eval) const + { + float cosNO = m_N.dot(omega_out); + if (cosNO > 0) { + // reflect the view vector + Vec3 R = (2 * cosNO) * m_N - omega_out; + domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; + domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; + Vec3 T, B; + make_orthonormals (R, T, B); + float phi = 2 * (float) M_PI * randu; + float cosTheta = powf(randv, 1 / (m_exponent + 1)); + float sinTheta2 = 1 - cosTheta * cosTheta; + float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; + omega_in = (cosf(phi) * sinTheta) * T + + (sinf(phi) * sinTheta) * B + + ( cosTheta) * R; + if (Ng.dot(omega_in) > 0) + { + // common terms for pdf and eval + float cosNI = m_N.dot(omega_in); + // make sure the direction we chose is still in the right hemisphere + if (cosNI > 0) + { + float cosp = powf(cosTheta, m_exponent); + float common = 0.5f * (float) M_1_PI * cosp; + pdf = (m_exponent + 1) * common; + float out = cosNI * (m_exponent + 2) * common; + eval = get_color(cosp) * out; + // Since there is some blur to this reflection, make the + // derivatives a bit bigger. In theory this varies with the + // exponent but the exact relationship is complex and + // requires more ops than are practical. + domega_in_dx *= 10; + domega_in_dy *= 10; + } + } + } + return Labels::REFLECT; + } +}; + + + +ClosureParam bsdf_phong_params[] = { + CLOSURE_VECTOR_PARAM(PhongClosure, m_N), + CLOSURE_FLOAT_PARAM (PhongClosure, m_exponent), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(PhongClosure) }; + +ClosureParam bsdf_phong_ramp_params[] = { + CLOSURE_VECTOR_PARAM (PhongRampClosure, m_N), + CLOSURE_FLOAT_PARAM (PhongRampClosure, m_exponent), + CLOSURE_COLOR_ARRAY_PARAM(PhongRampClosure, m_colors, PhongRampClosure::MAXCOLORS), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM (PhongRampClosure) }; + +CLOSURE_PREPARE(bsdf_phong_prepare, PhongClosure) +CLOSURE_PREPARE(bsdf_phong_ramp_prepare, PhongRampClosure) + +CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index 0793b29d1ac..a1a108a1b1d 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -75,6 +75,8 @@ void OSLShader::register_closures(OSL::ShadingSystem *ss) register_closure(ss, "microfacet_beckmann", OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_ID, bsdf_microfacet_beckmann_params, bsdf_microfacet_beckmann_prepare); register_closure(ss, "microfacet_beckmann_refraction", OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID, bsdf_microfacet_beckmann_refraction_params, bsdf_microfacet_beckmann_refraction_prepare); register_closure(ss, "ward", OSL_CLOSURE_BSDF_WARD_ID, bsdf_ward_params, bsdf_ward_prepare); + register_closure(ss, "phong", OSL_CLOSURE_BSDF_PHONG_ID, bsdf_phong_params, bsdf_phong_prepare); + register_closure(ss, "phong_ramp", OSL_CLOSURE_BSDF_PHONG_RAMP_ID, bsdf_phong_ramp_params, bsdf_phong_ramp_prepare); register_closure(ss, "ashikhmin_velvet", OSL_CLOSURE_BSDF_ASHIKHMIN_VELVET_ID, bsdf_ashikhmin_velvet_params, bsdf_ashikhmin_velvet_prepare); register_closure(ss, "westin_backscatter", OSL_CLOSURE_BSDF_WESTIN_BACKSCATTER_ID, bsdf_westin_backscatter_params, bsdf_westin_backscatter_prepare); register_closure(ss, "westin_sheen", OSL_CLOSURE_BSDF_WESTIN_SHEEN_ID, bsdf_westin_sheen_params, bsdf_westin_sheen_prepare); diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h index 1b4288b8601..00794183ca5 100644 --- a/intern/cycles/kernel/osl/osl_closures.h +++ b/intern/cycles/kernel/osl/osl_closures.h @@ -51,6 +51,8 @@ enum { OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_ID, OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID, OSL_CLOSURE_BSDF_WARD_ID, + OSL_CLOSURE_BSDF_PHONG_ID, + OSL_CLOSURE_BSDF_PHONG_RAMP_ID, OSL_CLOSURE_BSDF_ASHIKHMIN_VELVET_ID, OSL_CLOSURE_BSDF_WESTIN_BACKSCATTER_ID, OSL_CLOSURE_BSDF_WESTIN_SHEEN_ID, @@ -73,6 +75,8 @@ extern OSL::ClosureParam bsdf_microfacet_ggx_refraction_params[]; extern OSL::ClosureParam bsdf_microfacet_beckmann_params[]; extern OSL::ClosureParam bsdf_microfacet_beckmann_refraction_params[]; extern OSL::ClosureParam bsdf_ward_params[]; +extern OSL::ClosureParam bsdf_phong_params[]; +extern OSL::ClosureParam bsdf_phong_ramp_params[]; extern OSL::ClosureParam bsdf_ashikhmin_velvet_params[]; extern OSL::ClosureParam bsdf_westin_backscatter_params[]; extern OSL::ClosureParam bsdf_westin_sheen_params[]; @@ -94,6 +98,8 @@ void bsdf_microfacet_ggx_refraction_prepare(OSL::RendererServices *, int id, voi void bsdf_microfacet_beckmann_prepare(OSL::RendererServices *, int id, void *data); void bsdf_microfacet_beckmann_refraction_prepare(OSL::RendererServices *, int id, void *data); void bsdf_ward_prepare(OSL::RendererServices *, int id, void *data); +void bsdf_phong_prepare(OSL::RendererServices *, int id, void *data); +void bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data); void bsdf_ashikhmin_velvet_prepare(OSL::RendererServices *, int id, void *data); void bsdf_westin_backscatter_prepare(OSL::RendererServices *, int id, void *data); void bsdf_westin_sheen_prepare(OSL::RendererServices *, int id, void *data); diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h index 60ff463f033..5ec8a8edf9e 100644 --- a/intern/cycles/kernel/osl/osl_services.h +++ b/intern/cycles/kernel/osl/osl_services.h @@ -35,9 +35,9 @@ CCL_NAMESPACE_BEGIN class Object; class Scene; class Shader; -class ShaderData; -class float3; -class KernelGlobals; +struct ShaderData; +struct float3; +struct KernelGlobals; class OSLRenderServices : public OSL::RendererServices { diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h index e55f98d4d02..e2f4d1e94b8 100644 --- a/intern/cycles/kernel/osl/osl_shader.h +++ b/intern/cycles/kernel/osl/osl_shader.h @@ -46,10 +46,10 @@ namespace OSL = ::OSL; class OSLRenderServices; class Scene; -class ShaderClosure; -class ShaderData; -class differential3; -class KernelGlobals; +struct ShaderClosure; +struct ShaderData; +struct differential3; +struct KernelGlobals; class OSLShader { public: diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index 7296f8bebba..5122c1af410 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -84,30 +84,6 @@ bool Attribute::same_storage(TypeDesc a, TypeDesc b) return false; } -ustring Attribute::standard_name(AttributeStandard std) -{ - if(std == ATTR_STD_VERTEX_NORMAL) - return ustring("N"); - else if(std == ATTR_STD_FACE_NORMAL) - return ustring("Ng"); - else if(std == ATTR_STD_UV) - return ustring("uv"); - else if(std == ATTR_STD_GENERATED) - return ustring("generated"); - else if(std == ATTR_STD_POSITION_UNDEFORMED) - return ustring("undeformed"); - else if(std == ATTR_STD_POSITION_UNDISPLACED) - return ustring("undisplaced"); - else if(std == ATTR_STD_MOTION_PRE) - return ustring("motion_pre"); - else if(std == ATTR_STD_MOTION_POST) - return ustring("motion_post"); - else if(std == ATTR_STD_PARTICLE) - return ustring("particle"); - - return ustring(); -} - /* Attribute Set */ AttributeSet::AttributeSet() @@ -178,7 +154,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) Attribute *attr = NULL; if(name == ustring()) - name = Attribute::standard_name(std); + name = attribute_standard_name(std); if(std == ATTR_STD_VERTEX_NORMAL) attr = add(name, TypeDesc::TypeNormal, Attribute::VERTEX); diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h index 707d558fc79..e95bf42f6ae 100644 --- a/intern/cycles/render/attribute.h +++ b/intern/cycles/render/attribute.h @@ -71,7 +71,6 @@ public: const float *data_float() const { return (float*)data(); } static bool same_storage(TypeDesc a, TypeDesc b); - static ustring standard_name(AttributeStandard std); }; /* Attribute Set diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 8f5f2647ebf..1d9683f25cc 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -366,7 +366,7 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vectorattribute_map[i][stdname] = osl_attr; } else if(req.name != ustring()) { diff --git a/intern/ghost/GHOST_IEvent.h b/intern/ghost/GHOST_IEvent.h index ef63c57caa5..ba5d9ee33b9 100644 --- a/intern/ghost/GHOST_IEvent.h +++ b/intern/ghost/GHOST_IEvent.h @@ -45,10 +45,10 @@ class GHOST_IWindow; * Use the getType() method to retrieve the type of event and the getData() * method to get the event data out. Using the event type you can cast the * event data to the correct event dat structure. - * @see GHOST_IEventConsumer#processEvent - * @see GHOST_TEventType - * @author Maarten Gribnau - * @date May 31, 2001 + * \see GHOST_IEventConsumer#processEvent + * \see GHOST_TEventType + * \author Maarten Gribnau + * \date May 31, 2001 */ class GHOST_IEvent { @@ -62,26 +62,26 @@ public: /** * Returns the event type. - * @return The event type. + * \return The event type. */ virtual GHOST_TEventType getType() = 0; /** * Returns the time this event was generated. - * @return The event generation time. + * \return The event generation time. */ virtual GHOST_TUns64 getTime() = 0; /** * Returns the window this event was generated on, * or NULL if it is a 'system' event. - * @return The generating window. + * \return The generating window. */ virtual GHOST_IWindow *getWindow() = 0; /** * Returns the event data. - * @return The event data. + * \return The event data. */ virtual GHOST_TEventDataPtr getData() = 0; diff --git a/intern/ghost/GHOST_IEventConsumer.h b/intern/ghost/GHOST_IEventConsumer.h index cfc4fae7978..5682d04d434 100644 --- a/intern/ghost/GHOST_IEventConsumer.h +++ b/intern/ghost/GHOST_IEventConsumer.h @@ -41,9 +41,9 @@ * processEvent() method. They should then be registered with the system that * they want to receive events. The system will call the processEvent() method * for every installed event consumer to pass events. - * @see GHOST_ISystem#addEventConsumer - * @author Maarten Gribnau - * @date May 14, 2001 + * \see GHOST_ISystem#addEventConsumer + * \author Maarten Gribnau + * \date May 14, 2001 */ class GHOST_IEventConsumer { @@ -57,9 +57,9 @@ public: /** * This method is called by the system when it has events to dispatch. - * @see GHOST_ISystem#dispatchEvents - * @param event The event that can be handled or ignored. - * @return Indication as to whether the event was handled. + * \see GHOST_ISystem#dispatchEvents + * \param event The event that can be handled or ignored. + * \return Indication as to whether the event was handled. */ virtual bool processEvent(GHOST_IEvent *event) = 0; diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 474e3e97c45..8aef81bb762 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -136,27 +136,27 @@ class GHOST_IEventConsumer; * -# Access to the state of the mouse buttons and the keyboard. * -# Menus for windows with events generated when they are accessed (this is * work in progress). - * @author Maarten Gribnau - * @date May 30, 2001 + * \author Maarten Gribnau + * \date May 30, 2001 */ class GHOST_ISystem { public: /** * Creates the one and only system. - * @return An indication of success. + * \return An indication of success. */ static GHOST_TSuccess createSystem(); /** * Disposes the one and only system. - * @return An indication of success. + * \return An indication of success. */ static GHOST_TSuccess disposeSystem(); /** * Returns a pointer to the one and only system (nil if it hasn't been created). - * @return A pointer to the system. + * \return A pointer to the system. */ static GHOST_ISystem *getSystem(); @@ -184,7 +184,7 @@ public: * Returns the system time. * Returns the number of milliseconds since the start of the system process. * Based on ANSI clock() routine. - * @return The number of milliseconds. + * \return The number of milliseconds. */ virtual GHOST_TUns64 getMilliSeconds() const = 0; @@ -192,11 +192,11 @@ public: * Installs a timer. * Note that, on most operating systems, messages need to be processed in order * for the timer callbacks to be invoked. - * @param delay The time to wait for the first call to the timerProc (in milliseconds) - * @param interval The interval between calls to the timerProc (in milliseconds) - * @param timerProc The callback invoked when the interval expires, - * @param userData Placeholder for user data. - * @return A timer task (0 if timer task installation failed). + * \param delay The time to wait for the first call to the timerProc (in milliseconds) + * \param interval The interval between calls to the timerProc (in milliseconds) + * \param timerProc The callback invoked when the interval expires, + * \param userData Placeholder for user data. + * \return A timer task (0 if timer task installation failed). */ virtual GHOST_ITimerTask *installTimer(GHOST_TUns64 delay, GHOST_TUns64 interval, @@ -205,8 +205,8 @@ public: /** * Removes a timer. - * @param timerTask Timer task to be removed. - * @return Indication of success. + * \param timerTask Timer task to be removed. + * \return Indication of success. */ virtual GHOST_TSuccess removeTimer(GHOST_ITimerTask *timerTask) = 0; @@ -216,13 +216,13 @@ public: /** * Returns the number of displays on this system. - * @return The number of displays. + * \return The number of displays. */ virtual GHOST_TUns8 getNumDisplays() const = 0; /** * Returns the dimensions of the main display on this system. - * @return The dimension of the main display. + * \return The dimension of the main display. */ virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const = 0; @@ -230,17 +230,17 @@ public: * Create a new window. * The new window is added to the list of windows managed. * Never explicitly delete the window, use disposeWindow() instead. - * @param title The name of the window (displayed in the title bar of the window if the OS supports it). - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state of the window when opened. - * @param type The type of drawing context installed in this window. - * @param stereoVisual Create a stereo visual for quad buffered stereo. - * @param numOfAASamples Number of samples used for AA (zero if no AA) - * @param parentWindow Parent (embedder) window - * @return The new window (or 0 if creation failed). + * \param title The name of the window (displayed in the title bar of the window if the OS supports it). + * \param left The coordinate of the left edge of the window. + * \param top The coordinate of the top edge of the window. + * \param width The width the window. + * \param height The height the window. + * \param state The state of the window when opened. + * \param type The type of drawing context installed in this window. + * \param stereoVisual Create a stereo visual for quad buffered stereo. + * \param numOfAASamples Number of samples used for AA (zero if no AA) + * \param parentWindow Parent (embedder) window + * \return The new window (or 0 if creation failed). */ virtual GHOST_IWindow *createWindow( const STR_String& title, @@ -252,46 +252,46 @@ public: /** * Dispose a window. - * @param window Pointer to the window to be disposed. - * @return Indication of success. + * \param window Pointer to the window to be disposed. + * \return Indication of success. */ virtual GHOST_TSuccess disposeWindow(GHOST_IWindow *window) = 0; /** * Returns whether a window is valid. - * @param window Pointer to the window to be checked. - * @return Indication of validity. + * \param window Pointer to the window to be checked. + * \return Indication of validity. */ virtual bool validWindow(GHOST_IWindow *window) = 0; /** * Begins full screen mode. - * @param setting The new setting of the display. - * @param window Window displayed in full screen. + * \param setting The new setting of the display. + * \param window Window displayed in full screen. * This window is invalid after full screen has been ended. - * @return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window, const bool stereoVisual, const GHOST_TUns16 numOfAASamples = 0) = 0; /** * Updates the resolution while in fullscreen mode. - * @param setting The new setting of the display. - * @param window Window displayed in full screen. + * \param setting The new setting of the display. + * \param window Window displayed in full screen. * - * @return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window) = 0; /** * Ends full screen mode. - * @return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess endFullScreen(void) = 0; /** * Returns current full screen mode status. - * @return The current status. + * \return The current status. */ virtual bool getFullScreen(void) = 0; @@ -301,28 +301,28 @@ public: /** * Retrieves events from the system and stores them in the queue. - * @param waitForEvent Flag to wait for an event (or return immediately). - * @return Indication of the presence of events. + * \param waitForEvent Flag to wait for an event (or return immediately). + * \return Indication of the presence of events. */ virtual bool processEvents(bool waitForEvent) = 0; /** * Retrieves events from the queue and send them to the event consumers. - * @return Indication of the presence of events. + * \return Indication of the presence of events. */ virtual bool dispatchEvents() = 0; /** * Adds the given event consumer to our list. - * @param consumer The event consumer to add. - * @return Indication of success. + * \param consumer The event consumer to add. + * \return Indication of success. */ virtual GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer *consumer) = 0; /** * Removes the given event consumer to our list. - * @param consumer The event consumer to remove. - * @return Indication of success. + * \param consumer The event consumer to remove. + * \return Indication of success. */ virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer *consumer) = 0; @@ -332,18 +332,18 @@ public: /** * Returns the current location of the cursor (location in screen coordinates) - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. + * \param x The x-coordinate of the cursor. + * \param y The y-coordinate of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const = 0; /** * Updates the location of the cursor (location in screen coordinates). * Not all operating systems allow the cursor to be moved (without the input device being moved). - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. + * \param x The x-coordinate of the cursor. + * \param y The y-coordinate of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) = 0; @@ -353,28 +353,29 @@ public: /** * Returns the state of a modifier key (ouside the message queue). - * @param mask The modifier key state to retrieve. - * @param isDown The state of a modifier key (true == pressed). - * @return Indication of success. + * \param mask The modifier key state to retrieve. + * \param isDown The state of a modifier key (true == pressed). + * \return Indication of success. */ virtual GHOST_TSuccess getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const = 0; /** * Returns the state of a mouse button (ouside the message queue). - * @param mask The button state to retrieve. - * @param isDown Button state. - * @return Indication of success. + * \param mask The button state to retrieve. + * \param isDown Button state. + * \return Indication of success. */ virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const = 0; /** * Toggles console - * @action 0 - Hides - * 1 - Shows - * 2 - Toggles - * 3 - Hides if it runs not from command line - * * - Does nothing - * @return current status (1 -visible, 0 - hidden) + * \param action + * - 0: Hides + * - 1: Shows + * - 2: Toggles + * - 3: Hides if it runs not from command line + * - *: Does nothing + * \return current status (1 -visible, 0 - hidden) */ virtual int toggleConsole(int action) = 0; @@ -384,7 +385,7 @@ public: /** * Returns the selection buffer - * @return Returns "unsinged char" from X11 XA_CUT_BUFFER0 buffer + * \return Returns "unsinged char" from X11 XA_CUT_BUFFER0 buffer * */ virtual GHOST_TUns8 *getClipboard(bool selection) const = 0; @@ -402,13 +403,13 @@ public: protected: /** * Initialize the system. - * @return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess init() = 0; /** * Shut the system down. - * @return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess exit() = 0; diff --git a/intern/ghost/GHOST_ISystemPaths.h b/intern/ghost/GHOST_ISystemPaths.h index 1ba4ceaaaba..8f81a226f94 100644 --- a/intern/ghost/GHOST_ISystemPaths.h +++ b/intern/ghost/GHOST_ISystemPaths.h @@ -38,19 +38,19 @@ class GHOST_ISystemPaths public: /** * Creates the one and only system. - * @return An indication of success. + * \return An indication of success. */ static GHOST_TSuccess create(); /** * Disposes the one and only system. - * @return An indication of success. + * \return An indication of success. */ static GHOST_TSuccess dispose(); /** * Returns a pointer to the one and only system (nil if it hasn't been created). - * @return A pointer to the system. + * \return A pointer to the system. */ static GHOST_ISystemPaths *get(); @@ -73,20 +73,20 @@ public: /** * Determine the base dir in which shared resources are located. It will first try to use * "unpack and run" path, then look for properly installed path, including versioning. - * @return Unsigned char string pointing to system dir (eg /usr/share/blender/). + * \return Unsigned char string pointing to system dir (eg /usr/share/blender/). */ virtual const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const = 0; /** * Determine the base dir in which user configuration is stored, including versioning. * If needed, it will create the base directory. - * @return Unsigned char string pointing to user dir (eg ~/.blender/). + * \return Unsigned char string pointing to user dir (eg ~/.blender/). */ virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const = 0; /** * Determine the directory of the current binary - * @return Unsigned char string pointing to the binary dir + * \return Unsigned char string pointing to the binary dir */ virtual const GHOST_TUns8 *getBinaryDir() const = 0; diff --git a/intern/ghost/GHOST_ITimerTask.h b/intern/ghost/GHOST_ITimerTask.h index 08c4890939f..fcd42db59da 100644 --- a/intern/ghost/GHOST_ITimerTask.h +++ b/intern/ghost/GHOST_ITimerTask.h @@ -45,10 +45,10 @@ *
* Note that GHOST processes timers in the UI thread. You should ask GHOST * process messages in order for the timer-callbacks to be called. - * @see GHOST_ISystem#installTimer - * @see GHOST_TimerProcPtr - * @author Maarten Gribnau - * @date May 31, 2001 + * \see GHOST_ISystem#installTimer + * \see GHOST_TimerProcPtr + * \author Maarten Gribnau + * \date May 31, 2001 */ class GHOST_ITimerTask { @@ -62,25 +62,25 @@ public: /** * Returns the timer callback. - * @return The timer callback. + * \return The timer callback. */ virtual GHOST_TimerProcPtr getTimerProc() const = 0; /** * Changes the timer callback. - * @param timerProc The timer callback. + * \param timerProc The timer callback. */ virtual void setTimerProc(const GHOST_TimerProcPtr timerProc) = 0; /** * Returns the timer user data. - * @return The timer user data. + * \return The timer user data. */ virtual GHOST_TUserDataPtr getUserData() const = 0; /** * Changes the time user data. - * @param data The timer user data. + * \param data The timer user data. */ virtual void setUserData(const GHOST_TUserDataPtr userData) = 0; diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index b606294e97d..a1a1acfca75 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -43,7 +43,7 @@ * * You can create a window with the system's GHOST_ISystem::createWindow * method. - * @see GHOST_ISystem#createWindow + * \see GHOST_ISystem#createWindow * * There are two coordinate systems: *
    @@ -53,8 +53,8 @@ * is the area that is drawable by the application (excluding title bars etc.). * *
- * @author Maarten Gribnau - * @date May 31, 2001 + * \author Maarten Gribnau + * \date May 31, 2001 */ class GHOST_IWindow { @@ -68,89 +68,89 @@ public: /** * Returns indication as to whether the window is valid. - * @return The validity of the window. + * \return The validity of the window. */ virtual bool getValid() const = 0; /** * Returns the associated OS object/handle - * @return The associated OS object/handle + * \return The associated OS object/handle */ virtual void *getOSWindow() const = 0; /** * Returns the type of drawing context used in this window. - * @return The current type of drawing context. + * \return The current type of drawing context. */ virtual GHOST_TDrawingContextType getDrawingContextType() = 0; /** * Tries to install a rendering context in this window. - * @param type The type of rendering context installed. - * @return Indication as to whether installation has succeeded. + * \param type The type of rendering context installed. + * \return Indication as to whether installation has succeeded. */ virtual GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type) = 0; /** * Sets the title displayed in the title bar. - * @param title The title to display in the title bar. + * \param title The title to display in the title bar. */ virtual void setTitle(const STR_String& title) = 0; /** * Returns the title displayed in the title bar. - * @param title The title displayed in the title bar. + * \param title The title displayed in the title bar. */ virtual void getTitle(STR_String& title) const = 0; /** * Returns the window rectangle dimensions. * These are screen coordinates. - * @param bounds The bounding rectangle of the window. + * \param bounds The bounding rectangle of the window. */ virtual void getWindowBounds(GHOST_Rect& bounds) const = 0; /** * Returns the client rectangle dimensions. * The left and top members of the rectangle are always zero. - * @param bounds The bounding rectangle of the client area of the window. + * \param bounds The bounding rectangle of the client area of the window. */ virtual void getClientBounds(GHOST_Rect& bounds) const = 0; /** * Resizes client rectangle width. - * @param width The new width of the client area of the window. + * \param width The new width of the client area of the window. */ virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0; /** * Resizes client rectangle height. - * @param height The new height of the client area of the window. + * \param height The new height of the client area of the window. */ virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height) = 0; /** * Resizes client rectangle. - * @param width The new width of the client area of the window. - * @param height The new height of the client area of the window. + * \param width The new width of the client area of the window. + * \param height The new height of the client area of the window. */ virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) = 0; /** * Converts a point in screen coordinates to client rectangle coordinates - * @param inX The x-coordinate on the screen. - * @param inY The y-coordinate on the screen. - * @param outX The x-coordinate in the client rectangle. - * @param outY The y-coordinate in the client rectangle. + * \param inX The x-coordinate on the screen. + * \param inY The y-coordinate on the screen. + * \param outX The x-coordinate in the client rectangle. + * \param outY The y-coordinate in the client rectangle. */ virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0; /** * Converts a point in screen coordinates to client rectangle coordinates - * @param inX The x-coordinate in the client rectangle. - * @param inY The y-coordinate in the client rectangle. - * @param outX The x-coordinate on the screen. - * @param outY The y-coordinate on the screen. + * \param inX The x-coordinate in the client rectangle. + * \param inY The y-coordinate in the client rectangle. + * \param outX The x-coordinate on the screen. + * \param outY The y-coordinate on the screen. */ virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0; @@ -167,70 +167,70 @@ public: /** * Returns the state of the window (normal, minimized, maximized). - * @return The state of the window. + * \return The state of the window. */ virtual GHOST_TWindowState getState() const = 0; /** * Sets the state of the window (normal, minimized, maximized). - * @param state The state of the window. - * @return Indication of success. + * \param state The state of the window. + * \return Indication of success. */ virtual GHOST_TSuccess setState(GHOST_TWindowState state) = 0; /** * Sets the window "modified" status, indicating unsaved changes - * @param isUnsavedChanges Unsaved changes or not - * @return Indication of success. + * \param isUnsavedChanges Unsaved changes or not + * \return Indication of success. */ virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges) = 0; /** * Gets the window "modified" status, indicating unsaved changes - * @return True if there are unsaved changes + * \return True if there are unsaved changes */ virtual bool getModifiedState() = 0; /** * Sets the order of the window (bottom, top). - * @param order The order of the window. - * @return Indication of success. + * \param order The order of the window. + * \return Indication of success. */ virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order) = 0; /** * Swaps front and back buffers of a window. - * @return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess swapBuffers() = 0; /** * Activates the drawing context of this window. - * @return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess activateDrawingContext() = 0; /** * Invalidates the contents of this window. - * @return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess invalidate() = 0; /** * Returns the window user data. - * @return The window user data. + * \return The window user data. */ virtual GHOST_TUserDataPtr getUserData() const = 0; /** * Changes the window user data. - * @param data The window user data. + * \param data The window user data. */ virtual void setUserData(const GHOST_TUserDataPtr userData) = 0; /** * Returns the tablet data (pressure etc). - * @return The tablet data (pressure etc). + * \return The tablet data (pressure etc). */ virtual const GHOST_TabletData *GetTabletData() = 0; @@ -240,7 +240,7 @@ public: /** * Sets the progress bar value displayed in the window/application icon - * @param progress The progress % + * \param progress The progress % */ virtual GHOST_TSuccess setProgressBar(float progress) = 0; @@ -255,24 +255,24 @@ public: /** * Returns the current cursor shape. - * @return The current cursor shape. + * \return The current cursor shape. */ virtual GHOST_TStandardCursor getCursorShape() const = 0; /** * Set the shape of the cursor. - * @param cursor The new cursor shape type id. - * @return Indication of success. + * \param cursor The new cursor shape type id. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape) = 0; /** * Set the shape of the cursor to a custom cursor. - * @param bitmap The bitmap data for the cursor. - * @param mask The mask data for the cursor. - * @param hotX The X coordinate of the cursor hotspot. - * @param hotY The Y coordinate of the cursor hotspot. - * @return Indication of success. + * \param bitmap The bitmap data for the cursor. + * \param mask The mask data for the cursor. + * \param hotX The X coordinate of the cursor hotspot. + * \param hotY The Y coordinate of the cursor hotspot. + * \return Indication of success. */ virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], @@ -287,21 +287,21 @@ public: /** * Returns the visibility state of the cursor. - * @return The visibility state of the cursor. + * \return The visibility state of the cursor. */ virtual bool getCursorVisibility() const = 0; /** * Shows or hides the cursor. - * @param visible The new visibility state of the cursor. - * @return Indication of success. + * \param visible The new visibility state of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorVisibility(bool visible) = 0; /** * Grabs the cursor for a modal operation. - * @param grab The new grab state of the cursor. - * @return Indication of success. + * \param grab The new grab state of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds) { return GHOST_kSuccess; } diff --git a/intern/ghost/GHOST_Path-api.h b/intern/ghost/GHOST_Path-api.h index a037f2e3760..5af3adaa570 100644 --- a/intern/ghost/GHOST_Path-api.h +++ b/intern/ghost/GHOST_Path-api.h @@ -43,33 +43,33 @@ GHOST_DECLARE_HANDLE(GHOST_SystemPathsHandle); /** * Creates the one and only instance of the system path access. - * @return An indication of success. + * \return An indication of success. */ extern GHOST_TSuccess GHOST_CreateSystemPaths(void); /** * Disposes the one and only system. - * @return An indication of success. + * \return An indication of success. */ extern GHOST_TSuccess GHOST_DisposeSystemPaths(void); /** * Determine the base dir in which shared resources are located. It will first try to use * "unpack and run" path, then look for properly installed path, including versioning. - * @return Unsigned char string pointing to system dir (eg /usr/share/blender/). + * \return Unsigned char string pointing to system dir (eg /usr/share/blender/). */ extern const GHOST_TUns8 *GHOST_getSystemDir(int version, const char *versionstr); /** * Determine the base dir in which user configuration is stored, including versioning. - * @return Unsigned char string pointing to user dir (eg ~). + * \return Unsigned char string pointing to user dir (eg ~). */ extern const GHOST_TUns8 *GHOST_getUserDir(int version, const char *versionstr); /** * Determine the dir in which the binary file is found. - * @return Unsigned char string pointing to binary dir (eg ~/usr/local/bin/). + * \return Unsigned char string pointing to binary dir (eg ~/usr/local/bin/). */ extern const GHOST_TUns8 *GHOST_getBinaryDir(void); diff --git a/intern/ghost/GHOST_Rect.h b/intern/ghost/GHOST_Rect.h index 745e402cdc8..e52d6a7e6a0 100644 --- a/intern/ghost/GHOST_Rect.h +++ b/intern/ghost/GHOST_Rect.h @@ -41,8 +41,8 @@ * The four extreme coordinates are stored as left, top, right and bottom. * To be valid, a rectangle should have a left coordinate smaller than or equal to right. * To be valid, a rectangle should have a top coordinate smaller than or equal to bottom. - * @author Maarten Gribnau - * @date May 10, 2001 + * \author Maarten Gribnau + * \date May 10, 2001 */ class GHOST_Rect { @@ -50,10 +50,10 @@ public: /** * Constructs a rectangle with the given values. - * @param l requested left coordinate of the rectangle - * @param t requested top coordinate of the rectangle - * @param r requested right coordinate of the rectangle - * @param b requested bottom coordinate of the rectangle + * \param l requested left coordinate of the rectangle + * \param t requested top coordinate of the rectangle + * \param r requested right coordinate of the rectangle + * \param b requested bottom coordinate of the rectangle */ GHOST_Rect(GHOST_TInt32 l = 0, GHOST_TInt32 t = 0, GHOST_TInt32 r = 0, GHOST_TInt32 b = 0) : m_l(l), m_t(t), m_r(r), m_b(b) @@ -61,7 +61,7 @@ public: /** * Copy constructor. - * @param r rectangle to copy + * \param r rectangle to copy */ GHOST_Rect(const GHOST_Rect& r) : m_l(r.m_l), m_t(r.m_t), m_r(r.m_r), m_b(r.m_b) @@ -75,88 +75,88 @@ public: /** * Access to rectangle width. - * @return width of the rectangle + * \return width of the rectangle */ virtual inline GHOST_TInt32 getWidth() const; /** * Access to rectangle height. - * @return height of the rectangle + * \return height of the rectangle */ virtual inline GHOST_TInt32 getHeight() const; /** * Sets all members of the rectangle. - * @param l requested left coordinate of the rectangle - * @param t requested top coordinate of the rectangle - * @param r requested right coordinate of the rectangle - * @param b requested bottom coordinate of the rectangle + * \param l requested left coordinate of the rectangle + * \param t requested top coordinate of the rectangle + * \param r requested right coordinate of the rectangle + * \param b requested bottom coordinate of the rectangle */ virtual inline void set(GHOST_TInt32 l, GHOST_TInt32 t, GHOST_TInt32 r, GHOST_TInt32 b); /** * Returns whether this rectangle is empty. * Empty rectangles are rectangles that have width==0 and/or height==0. - * @return boolean value (true==empty rectangle) + * \return boolean value (true==empty rectangle) */ virtual inline bool isEmpty() const; /** * Returns whether this rectangle is valid. * Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b. Thus, emapty rectangles are valid. - * @return boolean value (true==valid rectangle) + * \return boolean value (true==valid rectangle) */ virtual inline bool isValid() const; /** * Grows (or shrinks the rectangle). * The method avoids negative insets making the rectangle invalid - * @param i The amount of offset given to each extreme (negative values shrink the rectangle). + * \param i The amount of offset given to each extreme (negative values shrink the rectangle). */ virtual void inset(GHOST_TInt32 i); /** * Does a union of the rectangle given and this rectangle. * The result is stored in this rectangle. - * @param r The rectangle that is input for the union operation. + * \param r The rectangle that is input for the union operation. */ virtual inline void unionRect(const GHOST_Rect& r); /** * Grows the rectangle to included a point. - * @param x The x-coordinate of the point. - * @param y The y-coordinate of the point. + * \param x The x-coordinate of the point. + * \param y The y-coordinate of the point. */ virtual inline void unionPoint(GHOST_TInt32 x, GHOST_TInt32 y); /** * Grows the rectangle to included a point. - * @param x The x-coordinate of the point. - * @param y The y-coordinate of the point. + * \param x The x-coordinate of the point. + * \param y The y-coordinate of the point. */ virtual inline void wrapPoint(GHOST_TInt32 &x, GHOST_TInt32 &y, GHOST_TInt32 ofs); /** * Returns whether the point is inside this rectangle. * Point on the boundary is considered inside. - * @param x x-coordinate of point to test. - * @param y y-coordinate of point to test. - * @return boolean value (true if point is inside). + * \param x x-coordinate of point to test. + * \param y y-coordinate of point to test. + * \return boolean value (true if point is inside). */ virtual inline bool isInside(GHOST_TInt32 x, GHOST_TInt32 y) const; /** * Returns whether the rectangle is inside this rectangle. - * @param r rectangle to test. - * @return visibility (not, partially or fully visible). + * \param r rectangle to test. + * \return visibility (not, partially or fully visible). */ virtual GHOST_TVisibility getVisibility(GHOST_Rect& r) const; /** * Sets rectangle members. * Sets rectangle members such that it is centered at the given location. - * @param cx requested center x-coordinate of the rectangle - * @param cy requested center y-coordinate of the rectangle + * \param cx requested center x-coordinate of the rectangle + * \param cy requested center y-coordinate of the rectangle */ virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy); @@ -164,10 +164,10 @@ public: * Sets rectangle members. * Sets rectangle members such that it is centered at the given location, * with the width requested. - * @param cx requested center x-coordinate of the rectangle - * @param cy requested center y-coordinate of the rectangle - * @param w requested width of the rectangle - * @param h requested height of the rectangle + * \param cx requested center x-coordinate of the rectangle + * \param cy requested center y-coordinate of the rectangle + * \param w requested width of the rectangle + * \param h requested height of the rectangle */ virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy, GHOST_TInt32 w, GHOST_TInt32 h); @@ -175,8 +175,8 @@ public: * Clips a rectangle. * Updates the rectangle given such that it will fit within this one. * This can result in an empty rectangle. - * @param r the rectangle to clip - * @return whether clipping has occurred + * \param r the rectangle to clip + * \return whether clipping has occurred */ virtual bool clip(GHOST_Rect& r) const; diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 4921acde670..c6d364c361c 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -507,8 +507,8 @@ typedef int GHOST_TEmbedderWindowID; /** * A timer task callback routine. - * @param task The timer task object. - * @param time The current time. + * \param task The timer task object. + * \param time The current time. */ #ifdef __cplusplus class GHOST_ITimerTask; diff --git a/intern/ghost/intern/GHOST_Buttons.h b/intern/ghost/intern/GHOST_Buttons.h index edcf0102201..6b0d74e7eb9 100644 --- a/intern/ghost/intern/GHOST_Buttons.h +++ b/intern/ghost/intern/GHOST_Buttons.h @@ -39,8 +39,8 @@ /** * This struct stores the state of the mouse buttons. * Buttons can be set using button masks. - * @author Maarten Gribnau - * @date May 15, 2001 + * \author Maarten Gribnau + * \date May 15, 2001 */ struct GHOST_Buttons { /** @@ -52,15 +52,15 @@ struct GHOST_Buttons { /** * Returns the state of a single button. - * @param mask Key button to return. - * @return The state of the button (pressed == true). + * \param mask Key button to return. + * \return The state of the button (pressed == true). */ virtual bool get(GHOST_TButtonMask mask) const; /** * Updates the state of a single button. - * @param mask Button state to update. - * @param down The new state of the button. + * \param mask Button state to update. + * \param down The new state of the button. */ virtual void set(GHOST_TButtonMask mask, bool down); diff --git a/intern/ghost/intern/GHOST_CallbackEventConsumer.cpp b/intern/ghost/intern/GHOST_CallbackEventConsumer.cpp index 47121562604..9d20a62d70c 100644 --- a/intern/ghost/intern/GHOST_CallbackEventConsumer.cpp +++ b/intern/ghost/intern/GHOST_CallbackEventConsumer.cpp @@ -32,8 +32,8 @@ /** * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date October 25, 2001 + * \author Maarten Gribnau + * \date October 25, 2001 */ #include "GHOST_Debug.h" diff --git a/intern/ghost/intern/GHOST_CallbackEventConsumer.h b/intern/ghost/intern/GHOST_CallbackEventConsumer.h index e13a56c38f4..770ebdc8b78 100644 --- a/intern/ghost/intern/GHOST_CallbackEventConsumer.h +++ b/intern/ghost/intern/GHOST_CallbackEventConsumer.h @@ -39,16 +39,16 @@ /** * Event consumer that will forward events to a call-back routine. * Especially useful for the C-API. - * @author Maarten Gribnau - * @date October 25, 2001 + * \author Maarten Gribnau + * \date October 25, 2001 */ class GHOST_CallbackEventConsumer : public GHOST_IEventConsumer { public: /** * Constructor. - * @param eventCallback The call-back routine invoked. - * @param userData The data passed back though the call-back routine. + * \param eventCallback The call-back routine invoked. + * \param userData The data passed back though the call-back routine. */ GHOST_CallbackEventConsumer( GHOST_EventCallbackProcPtr eventCallback, @@ -63,8 +63,8 @@ public: /** * This method is called by an event producer when an event is available. - * @param event The event that can be handled or ignored. - * @return Indication as to whether the event was handled. + * \param event The event that can be handled or ignored. + * \return Indication as to whether the event was handled. */ virtual bool processEvent(GHOST_IEvent *event); diff --git a/intern/ghost/intern/GHOST_DisplayManager.cpp b/intern/ghost/intern/GHOST_DisplayManager.cpp index 380fb817ab0..7ca4c8182b9 100644 --- a/intern/ghost/intern/GHOST_DisplayManager.cpp +++ b/intern/ghost/intern/GHOST_DisplayManager.cpp @@ -32,8 +32,8 @@ /** * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date September 21, 2001 + * \author Maarten Gribnau + * \date September 21, 2001 */ #include "GHOST_DisplayManager.h" diff --git a/intern/ghost/intern/GHOST_DisplayManager.h b/intern/ghost/intern/GHOST_DisplayManager.h index 7893f0936b3..7dc0cf2ca04 100644 --- a/intern/ghost/intern/GHOST_DisplayManager.h +++ b/intern/ghost/intern/GHOST_DisplayManager.h @@ -39,8 +39,8 @@ /** * Manages system displays (platform independent implementation). - * @author Maarten Gribnau - * @date September 21, 2001 + * \author Maarten Gribnau + * \date September 21, 2001 */ class GHOST_DisplayManager { @@ -58,32 +58,32 @@ public: /** * Initializes the list with devices and settings. - * @return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess initialize(void); /** * Returns the number of display devices on this system. - * @param numDisplays The number of displays on this system. - * @return Indication of success. + * \param numDisplays The number of displays on this system. + * \return Indication of success. */ virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const; /** * Returns the number of display settings for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param numSettings The number of settings of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param numSettings The number of settings of the display device with this index. + * \return Indication of success. */ virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const; /** * Returns the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param index The setting index to be returned. - * @param setting The setting of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param index The setting index to be returned. + * \param setting The setting of the display device with this index. + * \return Indication of success. */ virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, @@ -91,9 +91,9 @@ public: /** * Returns the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The current setting of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting The current setting of the display device with this index. + * \return Indication of success. */ virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const; @@ -102,9 +102,9 @@ public: * Changes the current setting for this display device. * The setting given to this method is matched againts the available diplay settings. * The best match is activated (@see findMatch()). - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The setting of the display device to be matched and activated. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting The setting of the display device to be matched and activated. + * \return Indication of success. */ virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting); @@ -114,10 +114,10 @@ protected: /** * Finds the best display settings match. - * @param display The index of the display device. - * @param setting The setting to match. - * @param match The optimal display setting. - * @return Indication of success. + * \param display The index of the display device. + * \param setting The setting to match. + * \param match The optimal display setting. + * \return Indication of success. */ GHOST_TSuccess findMatch(GHOST_TUns8 display, const GHOST_DisplaySetting& setting, @@ -125,7 +125,7 @@ protected: /** * Retrieves settings for each display device and stores them. - * @return Indication of success. + * \return Indication of success. */ GHOST_TSuccess initializeSettings(void); diff --git a/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp b/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp index 21798ed2d0a..3f7d2102dac 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp +++ b/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp @@ -32,8 +32,8 @@ /** * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date September 21, 2001 + * \author Maarten Gribnau + * \date September 21, 2001 */ #include "GHOST_DisplayManagerCarbon.h" diff --git a/intern/ghost/intern/GHOST_DisplayManagerCarbon.h b/intern/ghost/intern/GHOST_DisplayManagerCarbon.h index d9af12ba13f..1ac6540b7bd 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerCarbon.h +++ b/intern/ghost/intern/GHOST_DisplayManagerCarbon.h @@ -44,9 +44,9 @@ /** * Manages system displays (Mac OSX/Carbon implementation). - * @see GHOST_DisplayManager - * @author Maarten Gribnau - * @date September 21, 2001 + * \see GHOST_DisplayManager + * \author Maarten Gribnau + * \date September 21, 2001 */ class GHOST_DisplayManagerCarbon : public GHOST_DisplayManager { @@ -58,50 +58,50 @@ public: /** * Returns the number of display devices on this system. - * @param numDisplays The number of displays on this system. - * @return Indication of success. + * \param numDisplays The number of displays on this system. + * \return Indication of success. */ virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const; /** * Returns the number of display settings for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The number of settings of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting The number of settings of the display device with this index. + * \return Indication of success. */ virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const; /** * Returns the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param index The setting index to be returned. - * @param setting The setting of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param index The setting index to be returned. + * \param setting The setting of the display device with this index. + * \return Indication of success. */ virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const; /** * Returns the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The current setting of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting The current setting of the display device with this index. + * \return Indication of success. */ virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const; /** * Changes the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The current setting of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting The current setting of the display device with this index. + * \return Indication of success. */ virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting); protected: /** * Returns a value from a dictionary. - * @param values Dictionary to return value from. - * @param key Key to return value for. - * @return The value for this key. + * \param values Dictionary to return value from. + * \param key Key to return value for. + * \return The value for this key. */ long getValue(CFDictionaryRef values, CFStringRef key) const; diff --git a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h index bf194ad0492..1f17b4dd976 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerCocoa.h +++ b/intern/ghost/intern/GHOST_DisplayManagerCocoa.h @@ -41,9 +41,9 @@ /** * Manages system displays (Mac OSX/Cocoa implementation). - * @see GHOST_DisplayManager - * @author Maarten Gribnau - * @date September 21, 2001 + * \see GHOST_DisplayManager + * \author Maarten Gribnau + * \date September 21, 2001 */ class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager { @@ -55,41 +55,41 @@ public: /** * Returns the number of display devices on this system. - * @param numDisplays The number of displays on this system. - * @return Indication of success. + * \param numDisplays The number of displays on this system. + * \return Indication of success. */ virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const; /** * Returns the number of display settings for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The number of settings of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting The number of settings of the display device with this index. + * \return Indication of success. */ virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const; /** * Returns the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param index The setting index to be returned. - * @param setting The setting of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param index The setting index to be returned. + * \param setting The setting of the display device with this index. + * \return Indication of success. */ virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const; /** * Returns the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The current setting of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting The current setting of the display device with this index. + * \return Indication of success. */ virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const; /** * Changes the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The current setting of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting The current setting of the display device with this index. + * \return Indication of success. */ virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting); diff --git a/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm b/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm index 9050c3f946f..c5a2fecd3b8 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm @@ -101,7 +101,7 @@ GHOST_TSuccess GHOST_DisplayManagerCocoa::getCurrentDisplaySetting(GHOST_TUns8 d NSScreen *askedDisplay; GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::getCurrentDisplaySetting(): only main display is supported"); - + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; if (display == kMainDisplay) //Screen #0 may not be the main one @@ -162,6 +162,6 @@ GHOST_TSuccess GHOST_DisplayManagerCocoa::setCurrentDisplaySetting(GHOST_TUns8 d #endif // GHOST_DEBUG //CGDisplayErr err = ::CGDisplaySwitchToMode(m_displayIDs[display], displayModeValues); - + return /*err == CGDisplayNoErr ?*/ GHOST_kSuccess /*: GHOST_kFailure*/; } diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.h b/intern/ghost/intern/GHOST_DisplayManagerWin32.h index 534274ec878..ced4ceac044 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerWin32.h +++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.h @@ -42,8 +42,8 @@ /** * Manages system displays (WIN32 implementation). - * @author Maarten Gribnau - * @date September 21, 2001 + * \author Maarten Gribnau + * \date September 21, 2001 */ class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager { @@ -55,41 +55,41 @@ public: /** * Returns the number of display devices on this system. - * @param numDisplays The number of displays on this system. - * @return Indication of success. + * \param numDisplays The number of displays on this system. + * \return Indication of success. */ virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const; /** * Returns the number of display settings for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The number of settings of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting The number of settings of the display device with this index. + * \return Indication of success. */ virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const; /** * Returns the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param index The setting index to be returned. - * @param setting The setting of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param index The setting index to be returned. + * \param setting The setting of the display device with this index. + * \return Indication of success. */ virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const; /** * Returns the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The current setting of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting The current setting of the display device with this index. + * \return Indication of success. */ virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const; /** * Changes the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The current setting of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting The current setting of the display device with this index. + * \return Indication of success. */ virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting); diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.h b/intern/ghost/intern/GHOST_DisplayManagerX11.h index 61b4578cac3..66fd1e5c15e 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerX11.h +++ b/intern/ghost/intern/GHOST_DisplayManagerX11.h @@ -40,8 +40,8 @@ class GHOST_SystemX11; /** * Manages system displays (X11 implementation). - * @author Laurence Bourn - * @date October 26, 2001 + * \author Laurence Bourn + * \date October 26, 2001 */ class GHOST_DisplayManagerX11 : public GHOST_DisplayManager { @@ -55,8 +55,8 @@ public: /** * Returns the number of display devices on this system. - * @param numDisplays The number of displays on this system. - * @return Indication of success. + * \param numDisplays The number of displays on this system. + * \return Indication of success. */ GHOST_TSuccess getNumDisplays( @@ -65,9 +65,9 @@ public: /** * Returns the number of display settings for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The number of settings of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting The number of settings of the display device with this index. + * \return Indication of success. */ GHOST_TSuccess getNumDisplaySettings( @@ -77,10 +77,10 @@ public: /** * Returns the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param index The setting index to be returned. - * @param setting The setting of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param index The setting index to be returned. + * \param setting The setting of the display device with this index. + * \return Indication of success. */ GHOST_TSuccess getDisplaySetting( @@ -91,9 +91,9 @@ public: /** * Returns the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The current setting of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting The current setting of the display device with this index. + * \return Indication of success. */ GHOST_TSuccess getCurrentDisplaySetting( @@ -103,9 +103,9 @@ public: /** * Changes the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The current setting of the display device with this index. - * @return Indication of success. + * \param display The index of the display to query with 0 <= display < getNumDisplays(). + * \param setting The current setting of the display device with this index. + * \return Indication of success. */ GHOST_TSuccess setCurrentDisplaySetting( diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.h b/intern/ghost/intern/GHOST_DropTargetWin32.h index 88a4032ac23..f746a50d469 100644 --- a/intern/ghost/intern/GHOST_DropTargetWin32.h +++ b/intern/ghost/intern/GHOST_DropTargetWin32.h @@ -80,8 +80,8 @@ public: * With the modifier keys, we want to distinguish left and right keys. * Sometimes this is not possible (Windows ME for instance). Then, we want * events generated for both keys. - * @param window The window to register as drop target. - * @param system The associated system. + * \param window The window to register as drop target. + * \param system The associated system. */ GHOST_DropTargetWin32(GHOST_WindowWin32 *window, GHOST_SystemWin32 *system); @@ -97,37 +97,37 @@ private: /** * Base the effect on those allowed by the dropsource. - * @param dwAllowed Drop sources allowed drop effect. - * @return The allowed drop effect. + * \param dwAllowed Drop sources allowed drop effect. + * \return The allowed drop effect. */ DWORD allowedDropEffect(DWORD dwAllowed); /** * Query DataObject for the data types it supports. - * @param pDataObject Pointer to the DataObject. - * @return GHOST data type. + * \param pDataObject Pointer to the DataObject. + * \return GHOST data type. */ GHOST_TDragnDropTypes getGhostType(IDataObject *pDataObject); /** * Get data to pass in event. * It checks the type and calls specific functions for each type. - * @param pDataObject Pointer to the DataObject. - * @return Pointer to data. + * \param pDataObject Pointer to the DataObject. + * \return Pointer to data. */ void *getGhostData(IDataObject *pDataObject); /** * Allocate data as file array to pass in event. - * @param pDataObject Pointer to the DataObject. - * @return Pointer to data. + * \param pDataObject Pointer to the DataObject. + * \return Pointer to data. */ void *getDropDataAsFilenames(IDataObject *pDataObject); /** * Allocate data as string to pass in event. - * @param pDataObject Pointer to the DataObject. - * @return Pointer to data. + * \param pDataObject Pointer to the DataObject. + * \return Pointer to data. */ void *getDropDataAsString(IDataObject *pDataObject); @@ -135,9 +135,9 @@ private: * Convert Unicode to ANSI, replacing unconvertable chars with '?'. * The ANSI codepage is the system default codepage, * and can change from system to system. - * @param in LPCWSTR. - * @param out char *. Is set to NULL on failure. - * @return 0 on failure. Else the size of the string including '\0'. + * \param in LPCWSTR. + * \param out char *. Is set to NULL on failure. + * \return 0 on failure. Else the size of the string including '\0'. */ int WideCharToANSI(LPCWSTR in, char * &out); diff --git a/intern/ghost/intern/GHOST_DropTargetX11.h b/intern/ghost/intern/GHOST_DropTargetX11.h index 10d76bbb165..3fed5798611 100644 --- a/intern/ghost/intern/GHOST_DropTargetX11.h +++ b/intern/ghost/intern/GHOST_DropTargetX11.h @@ -44,8 +44,8 @@ public: /** * Constructor * - * @param window The window to register as drop target. - * @param system The associated system. + * \param window The window to register as drop target. + * \param system The associated system. */ GHOST_DropTargetX11(GHOST_WindowX11 *window, GHOST_SystemX11 *system); @@ -62,10 +62,10 @@ public: /** * Get data to pass in event. * It checks the type and calls specific functions for each type. - * @param dropType - type of dropped entity. - * @param dropBuffer - buffer returned from source application - * @param dropBufferSize - size of returned buffer - * @return Pointer to data. + * \param dropType - type of dropped entity. + * \param dropBuffer - buffer returned from source application + * \param dropBufferSize - size of returned buffer + * \return Pointer to data. */ void *getGhostData(Atom dropType, unsigned char *dropBuffer, int dropBufferSize); @@ -84,24 +84,24 @@ private: /** * Get data to be passed to event from text/uri-list mime type - * @param dropBuffer - buffer returned from source application - * @param dropBufferSize - size of dropped buffer - * @return pointer to newly created GHOST data + * \param dropBuffer - buffer returned from source application + * \param dropBufferSize - size of dropped buffer + * \return pointer to newly created GHOST data */ void *getURIListGhostData(unsigned char *dropBuffer, int dropBufferSize); /** * Decode URL (i.e. converts "file:///a%20b/test" to "file:///a b/test") - * @param decodedOut - buffer for decoded URL - * @param bufferSize - size of output buffer - * @param encodedIn - input encoded buffer to be decoded + * \param decodedOut - buffer for decoded URL + * \param bufferSize - size of output buffer + * \param encodedIn - input encoded buffer to be decoded */ void UrlDecode(char *decodedOut, int bufferSize, const char *encodedIn); /** * Fully decode file URL (i.e. converts "file:///a%20b/test" to "/a b/test") - * @param fileUrl - file path URL to be fully decoded - * @return decoded file path (resutl shold be free-d) + * \param fileUrl - file path URL to be fully decoded + * \return decoded file path (resutl shold be free-d) */ char *FileUrlDecode(char *fileUrl); diff --git a/intern/ghost/intern/GHOST_Event.h b/intern/ghost/intern/GHOST_Event.h index 6e12a34d149..c9a51f29559 100644 --- a/intern/ghost/intern/GHOST_Event.h +++ b/intern/ghost/intern/GHOST_Event.h @@ -38,17 +38,17 @@ /** * Base class for events received the operating system. - * @author Maarten Gribnau - * @date May 11, 2001 + * \author Maarten Gribnau + * \date May 11, 2001 */ class GHOST_Event : public GHOST_IEvent { public: /** * Constructor. - * @param msec The time this event was generated. - * @param type The type of this event. - * @param window The generating window (or NULL if system event). + * \param msec The time this event was generated. + * \param type The type of this event. + * \param window The generating window (or NULL if system event). */ GHOST_Event(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow *window) : m_type(type), m_time(msec), m_window(window), m_data(0) @@ -57,7 +57,7 @@ public: /** * Returns the event type. - * @return The event type. + * \return The event type. */ virtual GHOST_TEventType getType() { @@ -66,7 +66,7 @@ public: /** * Returns the time this event was generated. - * @return The event generation time. + * \return The event generation time. */ virtual GHOST_TUns64 getTime() { @@ -76,7 +76,7 @@ public: /** * Returns the window this event was generated on, * or NULL if it is a 'system' event. - * @return The generating window. + * \return The generating window. */ virtual GHOST_IWindow *getWindow() { @@ -85,7 +85,7 @@ public: /** * Returns the event data. - * @return The event data. + * \return The event data. */ virtual GHOST_TEventDataPtr getData() { diff --git a/intern/ghost/intern/GHOST_EventButton.h b/intern/ghost/intern/GHOST_EventButton.h index 7ad840bb964..f88fe6e201d 100644 --- a/intern/ghost/intern/GHOST_EventButton.h +++ b/intern/ghost/intern/GHOST_EventButton.h @@ -37,19 +37,19 @@ /** * Mouse button event. - * @author Maarten Gribnau - * @date May 11, 2001 + * \author Maarten Gribnau + * \date May 11, 2001 */ class GHOST_EventButton : public GHOST_Event { public: /** * Constructor. - * @param time The time this event was generated. - * @param type The type of this event. - * @param x The x-coordinate of the location the cursor was at at the time of the event. - * @param y The y-coordinate of the location the cursor was at at the time of the event. - * @param buttons The state of the buttons was at at the time of the event. + * \param time The time this event was generated. + * \param type The type of this event. + * \param x The x-coordinate of the location the cursor was at at the time of the event. + * \param y The y-coordinate of the location the cursor was at at the time of the event. + * \param buttons The state of the buttons was at at the time of the event. */ GHOST_EventButton(GHOST_TUns64 time, GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask button) : GHOST_Event(time, type, window) diff --git a/intern/ghost/intern/GHOST_EventCursor.h b/intern/ghost/intern/GHOST_EventCursor.h index 0ff703ba254..1c6f762cd9e 100644 --- a/intern/ghost/intern/GHOST_EventCursor.h +++ b/intern/ghost/intern/GHOST_EventCursor.h @@ -37,18 +37,18 @@ /** * Cursor event. - * @author Maarten Gribnau - * @date May 11, 2001 + * \author Maarten Gribnau + * \date May 11, 2001 */ class GHOST_EventCursor : public GHOST_Event { public: /** * Constructor. - * @param msec The time this event was generated. - * @param type The type of this event. - * @param x The x-coordinate of the location the cursor was at at the time of the event. - * @param y The y-coordinate of the location the cursor was at at the time of the event. + * \param msec The time this event was generated. + * \param type The type of this event. + * \param x The x-coordinate of the location the cursor was at at the time of the event. + * \param y The y-coordinate of the location the cursor was at at the time of the event. */ GHOST_EventCursor(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow *window, GHOST_TInt32 x, GHOST_TInt32 y) : GHOST_Event(msec, type, window) diff --git a/intern/ghost/intern/GHOST_EventDragnDrop.h b/intern/ghost/intern/GHOST_EventDragnDrop.h index 1a05a4b9b68..cef9bb0a34a 100644 --- a/intern/ghost/intern/GHOST_EventDragnDrop.h +++ b/intern/ghost/intern/GHOST_EventDragnDrop.h @@ -72,13 +72,13 @@ class GHOST_EventDragnDrop : public GHOST_Event public: /** * Constructor. - * @param time The time this event was generated. - * @param type The type of this event. - * @param dataType The type of the drop candidate object - * @param window The window where the event occurred - * @param x The x-coordinate of the location the cursor was at at the time of the event. - * @param y The y-coordinate of the location the cursor was at at the time of the event. - * @param data The "content" dropped in the window + * \param time The time this event was generated. + * \param type The type of this event. + * \param dataType The type of the drop candidate object + * \param window The window where the event occurred + * \param x The x-coordinate of the location the cursor was at at the time of the event. + * \param y The y-coordinate of the location the cursor was at at the time of the event. + * \param data The "content" dropped in the window */ GHOST_EventDragnDrop(GHOST_TUns64 time, GHOST_TEventType type, diff --git a/intern/ghost/intern/GHOST_EventKey.h b/intern/ghost/intern/GHOST_EventKey.h index 66817576f0f..54e38c00d05 100644 --- a/intern/ghost/intern/GHOST_EventKey.h +++ b/intern/ghost/intern/GHOST_EventKey.h @@ -37,17 +37,17 @@ /** * Key event. - * @author Maarten Gribnau - * @date May 11, 2001 + * \author Maarten Gribnau + * \date May 11, 2001 */ class GHOST_EventKey : public GHOST_Event { public: /** * Constructor. - * @param msec The time this event was generated. - * @param type The type of key event. - * @param key The key code of the key. + * \param msec The time this event was generated. + * \param type The type of key event. + * \param key The key code of the key. */ GHOST_EventKey(GHOST_TUns64 msec, GHOST_TEventType type, @@ -63,10 +63,10 @@ public: /** * Constructor. - * @param msec The time this event was generated. - * @param type The type of key event. - * @param key The key code of the key. - * @param ascii The ascii code for the key event. + * \param msec The time this event was generated. + * \param type The type of key event. + * \param key The key code of the key. + * \param ascii The ascii code for the key event. */ GHOST_EventKey(GHOST_TUns64 msec, GHOST_TEventType type, diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp index 33e0afb797a..b8660b3038e 100644 --- a/intern/ghost/intern/GHOST_EventManager.cpp +++ b/intern/ghost/intern/GHOST_EventManager.cpp @@ -32,8 +32,8 @@ /** * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date May 14, 2001 + * \author Maarten Gribnau + * \date May 14, 2001 */ #include "GHOST_EventManager.h" diff --git a/intern/ghost/intern/GHOST_EventManager.h b/intern/ghost/intern/GHOST_EventManager.h index eec00789800..fea8214c7f2 100644 --- a/intern/ghost/intern/GHOST_EventManager.h +++ b/intern/ghost/intern/GHOST_EventManager.h @@ -62,21 +62,21 @@ public: /** * Returns the number of events currently on the stack. - * @return The number of events on the stack. + * \return The number of events on the stack. */ virtual GHOST_TUns32 getNumEvents(); /** * Returns the number of events of a certain type currently on the stack. - * @param type The type of events to be counted. - * @return The number of events on the stack of this type. + * \param type The type of events to be counted. + * \return The number of events on the stack of this type. */ virtual GHOST_TUns32 getNumEvents(GHOST_TEventType type); /** * Return the event at the top of the stack without removal. * Do not delete the event! - * @return The event at the top of the stack. + * \return The event at the top of the stack. */ virtual GHOST_IEvent *peekEvent(); @@ -84,47 +84,47 @@ public: * Pushes an event on the stack. * To dispatch it, call dispatchEvent() or dispatchEvents(). * Do not delete the event! - * @param event The event to push on the stack. + * \param event The event to push on the stack. */ virtual GHOST_TSuccess pushEvent(GHOST_IEvent *event); /** * Dispatches the given event directly, bypassing the event stack. - * @return Indication as to whether any of the consumers handled the event. + * \return Indication as to whether any of the consumers handled the event. */ virtual bool dispatchEvent(GHOST_IEvent *event); /** * Dispatches the event at the back of the stack. * The event will be removed from the stack. - * @return Indication as to whether any of the consumers handled the event. + * \return Indication as to whether any of the consumers handled the event. */ virtual bool dispatchEvent(); /** * Dispatches all the events on the stack. * The event stack will be empty afterwards. - * @return Indication as to whether any of the consumers handled the events. + * \return Indication as to whether any of the consumers handled the events. */ virtual bool dispatchEvents(); /** * Adds a consumer to the list of event consumers. - * @param consumer The consumer added to the list. - * @return Indication as to whether addition has succeeded. + * \param consumer The consumer added to the list. + * \return Indication as to whether addition has succeeded. */ virtual GHOST_TSuccess addConsumer(GHOST_IEventConsumer *consumer); /** * Removes a consumer from the list of event consumers. - * @param consumer The consumer removed from the list. - * @return Indication as to whether removal has succeeded. + * \param consumer The consumer removed from the list. + * \return Indication as to whether removal has succeeded. */ virtual GHOST_TSuccess removeConsumer(GHOST_IEventConsumer *consumer); /** * Removes all events for a window from the stack. - * @param window The window to remove events for. + * \param window The window to remove events for. */ virtual void removeWindowEvents( @@ -135,8 +135,8 @@ public: * Removes all events of a certain type from the stack. * The window parameter is optional. If non-null, the routine will remove * events only associated with that window. - * @param type The type of events to be removed. - * @param window The window to remove the events for. + * \param type The type of events to be removed. + * \param window The window to remove the events for. */ virtual void removeTypeEvents( @@ -148,7 +148,7 @@ protected: /** * Returns the event at the top of the stack and removes it. * Delete the event after use! - * @return The event at the top of the stack. + * \return The event at the top of the stack. */ virtual GHOST_IEvent *popEvent(); diff --git a/intern/ghost/intern/GHOST_EventPrinter.h b/intern/ghost/intern/GHOST_EventPrinter.h index f5fe303f9bc..280d4208413 100644 --- a/intern/ghost/intern/GHOST_EventPrinter.h +++ b/intern/ghost/intern/GHOST_EventPrinter.h @@ -46,16 +46,16 @@ class GHOST_EventPrinter : public GHOST_IEventConsumer public: /** * Prints all the events received to std out. - * @param event The event that can be handled or not. - * @return Indication as to whether the event was handled. + * \param event The event that can be handled or not. + * \return Indication as to whether the event was handled. */ virtual bool processEvent(GHOST_IEvent *event); protected: /** * Converts GHOST key code to a readable string. - * @param key The GHOST key code to convert. - * @param str The GHOST key code converted to a readable string. + * \param key The GHOST key code to convert. + * \param str The GHOST key code converted to a readable string. */ void getKeyString(GHOST_TKey key, char str[32]) const; }; diff --git a/intern/ghost/intern/GHOST_EventString.h b/intern/ghost/intern/GHOST_EventString.h index 8611944197d..391af0f8e2d 100644 --- a/intern/ghost/intern/GHOST_EventString.h +++ b/intern/ghost/intern/GHOST_EventString.h @@ -38,18 +38,18 @@ /** * Generic class for events with string data - * @author Damien Plisson - * @date Feb 1, 2010 + * \author Damien Plisson + * \date Feb 1, 2010 */ class GHOST_EventString : public GHOST_Event { public: /** * Constructor. - * @param msec The time this event was generated. - * @param type The type of this event. - * @param window The generating window (or NULL if system event). - * @param data_ptr Pointer to the (unformatted) data associated with the event + * \param msec The time this event was generated. + * \param type The type of this event. + * \param window The generating window (or NULL if system event). + * \param data_ptr Pointer to the (unformatted) data associated with the event */ GHOST_EventString(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow *window, GHOST_TEventDataPtr data_ptr) : GHOST_Event(msec, type, window) diff --git a/intern/ghost/intern/GHOST_EventTrackpad.h b/intern/ghost/intern/GHOST_EventTrackpad.h index ab576fb9ec3..dc8b1649754 100644 --- a/intern/ghost/intern/GHOST_EventTrackpad.h +++ b/intern/ghost/intern/GHOST_EventTrackpad.h @@ -44,11 +44,11 @@ class GHOST_EventTrackpad : public GHOST_Event public: /** * Constructor. - * @param msec The time this event was generated. - * @param type The type of this event. - * @param subtype The subtype of the event. - * @param x The x-delta of the pan event. - * @param y The y-delta of the pan event. + * \param msec The time this event was generated. + * \param type The type of this event. + * \param subtype The subtype of the event. + * \param x The x-delta of the pan event. + * \param y The y-delta of the pan event. */ GHOST_EventTrackpad(GHOST_TUns64 msec, GHOST_IWindow *window, diff --git a/intern/ghost/intern/GHOST_EventWheel.h b/intern/ghost/intern/GHOST_EventWheel.h index 7d6137af575..216f13fda4e 100644 --- a/intern/ghost/intern/GHOST_EventWheel.h +++ b/intern/ghost/intern/GHOST_EventWheel.h @@ -39,17 +39,17 @@ * Mouse wheel event. * The displacement of the mouse wheel is counted in ticks. * A positive value means the wheel is turned away from the user. - * @author Maarten Gribnau - * @date May 11, 2001 + * \author Maarten Gribnau + * \date May 11, 2001 */ class GHOST_EventWheel : public GHOST_Event { public: /** * Constructor. - * @param msec The time this event was generated. - * @param type The type of this event. - * @param z The displacement of the mouse wheel. + * \param msec The time this event was generated. + * \param type The type of this event. + * \param z The displacement of the mouse wheel. */ GHOST_EventWheel(GHOST_TUns64 msec, GHOST_IWindow *window, GHOST_TInt32 z) : GHOST_Event(msec, GHOST_kEventWheel, window) diff --git a/intern/ghost/intern/GHOST_ISystem.cpp b/intern/ghost/intern/GHOST_ISystem.cpp index fe1132e7996..f6973caad03 100644 --- a/intern/ghost/intern/GHOST_ISystem.cpp +++ b/intern/ghost/intern/GHOST_ISystem.cpp @@ -32,8 +32,8 @@ /** * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date May 7, 2001 + * \author Maarten Gribnau + * \date May 7, 2001 */ #include "GHOST_ISystem.h" diff --git a/intern/ghost/intern/GHOST_ISystemPaths.cpp b/intern/ghost/intern/GHOST_ISystemPaths.cpp index f84c50770f0..ae9a8e49057 100644 --- a/intern/ghost/intern/GHOST_ISystemPaths.cpp +++ b/intern/ghost/intern/GHOST_ISystemPaths.cpp @@ -32,8 +32,8 @@ /** * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date May 7, 2001 + * \author Maarten Gribnau + * \date May 7, 2001 */ #include "GHOST_ISystemPaths.h" diff --git a/intern/ghost/intern/GHOST_ModifierKeys.cpp b/intern/ghost/intern/GHOST_ModifierKeys.cpp index ffc7a09e4dd..d25d0beb34c 100644 --- a/intern/ghost/intern/GHOST_ModifierKeys.cpp +++ b/intern/ghost/intern/GHOST_ModifierKeys.cpp @@ -32,8 +32,8 @@ /** * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date May 31, 2001 + * \author Maarten Gribnau + * \date May 31, 2001 */ #include "GHOST_ModifierKeys.h" diff --git a/intern/ghost/intern/GHOST_ModifierKeys.h b/intern/ghost/intern/GHOST_ModifierKeys.h index 064af8d2e6c..8189006f602 100644 --- a/intern/ghost/intern/GHOST_ModifierKeys.h +++ b/intern/ghost/intern/GHOST_ModifierKeys.h @@ -38,8 +38,8 @@ /** * Stores the state of modifier keys. * Discriminates between left and right modifier keys. - * @author Maarten Gribnau - * @date May 17, 2001 + * \author Maarten Gribnau + * \date May 17, 2001 */ struct GHOST_ModifierKeys { /** @@ -51,23 +51,23 @@ struct GHOST_ModifierKeys { /** * Returns the modifier key's key code from a modifier key mask. - * @param mask The mask of the modifier key. - * @return The modifier key's key code. + * \param mask The mask of the modifier key. + * \return The modifier key's key code. */ static GHOST_TKey getModifierKeyCode(GHOST_TModifierKeyMask mask); /** * Returns the state of a single modifier key. - * @param mask. Key state to return. - * @return The state of the key (pressed == true). + * \param mask. Key state to return. + * \return The state of the key (pressed == true). */ virtual bool get(GHOST_TModifierKeyMask mask) const; /** * Updates the state of a single modifier key. - * @param mask. Key state to update. - * @param down. The new state of the key. + * \param mask. Key state to update. + * \param down. The new state of the key. */ virtual void set(GHOST_TModifierKeyMask mask, bool down); @@ -78,8 +78,8 @@ struct GHOST_ModifierKeys { /** * Determines whether to modifier key states are equal. - * @param keys. The modifier key state to compare to. - * @return Indication of equality. + * \param keys. The modifier key state to compare to. + * \return Indication of equality. */ virtual bool equals(const GHOST_ModifierKeys& keys) const; diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index de475c79f43..070bf914dda 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -55,9 +55,9 @@ class GHOST_NDOFManager; * interface. * GHOST_System is an abstract class because not all methods of GHOST_ISystem * are implemented. - * @see GHOST_ISystem. - * @author Maarten Gribnau - * @date May 7, 2001 + * \see GHOST_ISystem. + * \author Maarten Gribnau + * \date May 7, 2001 */ class GHOST_System : public GHOST_ISystem { @@ -83,7 +83,7 @@ public: * Returns the system time. * Returns the number of milliseconds since the start of the system process. * Based on ANSI clock() routine. - * @return The number of milliseconds. + * \return The number of milliseconds. */ virtual GHOST_TUns64 getMilliSeconds() const; @@ -91,11 +91,11 @@ public: * Installs a timer. * Note that, on most operating systems, messages need to be processed in order * for the timer callbacks to be invoked. - * @param delay The time to wait for the first call to the timerProc (in milliseconds) - * @param interval The interval between calls to the timerProc - * @param timerProc The callback invoked when the interval expires, - * @param userData Placeholder for user data. - * @return A timer task (0 if timer task installation failed). + * \param delay The time to wait for the first call to the timerProc (in milliseconds) + * \param interval The interval between calls to the timerProc + * \param timerProc The callback invoked when the interval expires, + * \param userData Placeholder for user data. + * \return A timer task (0 if timer task installation failed). */ virtual GHOST_ITimerTask *installTimer(GHOST_TUns64 delay, GHOST_TUns64 interval, @@ -104,8 +104,8 @@ public: /** * Removes a timer. - * @param timerTask Timer task to be removed. - * @return Indication of success. + * \param timerTask Timer task to be removed. + * \return Indication of success. */ virtual GHOST_TSuccess removeTimer(GHOST_ITimerTask *timerTask); @@ -123,47 +123,47 @@ public: /** * Dispose a window. - * @param window Pointer to the window to be disposed. - * @return Indication of success. + * \param window Pointer to the window to be disposed. + * \return Indication of success. */ virtual GHOST_TSuccess disposeWindow(GHOST_IWindow *window); /** * Returns whether a window is valid. - * @param window Pointer to the window to be checked. - * @return Indication of validity. + * \param window Pointer to the window to be checked. + * \return Indication of validity. */ virtual bool validWindow(GHOST_IWindow *window); /** * Begins full screen mode. - * @param setting The new setting of the display. - * @param window Window displayed in full screen. - * @param stereoVisual Stereo visual for quad buffered stereo. + * \param setting The new setting of the display. + * \param window Window displayed in full screen. + * \param stereoVisual Stereo visual for quad buffered stereo. * This window is invalid after full screen has been ended. - * @return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window, const bool stereoVisual, const GHOST_TUns16 numOfAASamples = 0); /** * Updates the resolution while in fullscreen mode. - * @param setting The new setting of the display. - * @param window Window displayed in full screen. + * \param setting The new setting of the display. + * \param window Window displayed in full screen. * - * @return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window); /** * Ends full screen mode. - * @return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess endFullScreen(void); /** * Returns current full screen mode status. - * @return The current status. + * \return The current status. */ virtual bool getFullScreen(void); @@ -183,21 +183,21 @@ public: /** * Dispatches all the events on the stack. * The event stack will be empty afterwards. - * @return Indication as to whether any of the consumers handled the events. + * \return Indication as to whether any of the consumers handled the events. */ virtual bool dispatchEvents(); /** * Adds the given event consumer to our list. - * @param consumer The event consumer to add. - * @return Indication of success. + * \param consumer The event consumer to add. + * \return Indication of success. */ virtual GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer *consumer); /** * Remove the given event consumer to our list. - * @param consumer The event consumer to remove. - * @return Indication of success. + * \param consumer The event consumer to remove. + * \return Indication of success. */ virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer *consumer); @@ -216,17 +216,17 @@ public: /** * Returns the state of a modifier key (ouside the message queue). - * @param mask The modifier key state to retrieve. - * @param isDown The state of a modifier key (true == pressed). - * @return Indication of success. + * \param mask The modifier key state to retrieve. + * \param isDown The state of a modifier key (true == pressed). + * \return Indication of success. */ virtual GHOST_TSuccess getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const; /** * Returns the state of a mouse button (ouside the message queue). - * @param mask The button state to retrieve. - * @param isDown Button state. - * @return Indication of success. + * \param mask The button state to retrieve. + * \param isDown Button state. + * \return Indication of success. */ virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const; @@ -238,62 +238,62 @@ public: * Pushes an event on the stack. * To dispatch it, call dispatchEvent() or dispatchEvents(). * Do not delete the event! - * @param event The event to push on the stack. + * \param event The event to push on the stack. */ virtual GHOST_TSuccess pushEvent(GHOST_IEvent *event); /** * Returns the timer manager. - * @return The timer manager. + * \return The timer manager. */ inline virtual GHOST_TimerManager *getTimerManager() const; /** * Returns a pointer to our event manager. - * @return A pointer to our event manager. + * \return A pointer to our event manager. */ virtual inline GHOST_EventManager *getEventManager() const; /** * Returns a pointer to our window manager. - * @return A pointer to our window manager. + * \return A pointer to our window manager. */ virtual inline GHOST_WindowManager *getWindowManager() const; #ifdef WITH_INPUT_NDOF /** * Returns a pointer to our n-degree of freedeom manager. - * @return A pointer to our n-degree of freedeom manager. + * \return A pointer to our n-degree of freedeom manager. */ virtual inline GHOST_NDOFManager *getNDOFManager() const; #endif /** * Returns the state of all modifier keys. - * @param keys The state of all modifier keys (true == pressed). - * @return Indication of success. + * \param keys The state of all modifier keys (true == pressed). + * \return Indication of success. */ virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const = 0; /** * Returns the state of the mouse buttons (ouside the message queue). - * @param buttons The state of the buttons. - * @return Indication of success. + * \param buttons The state of the buttons. + * \return Indication of success. */ virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const = 0; /** * Returns the selection buffer - * @param selection Only used on X11 - * @return Returns the clipboard data + * \param selection Only used on X11 + * \return Returns the clipboard data * */ virtual GHOST_TUns8 *getClipboard(bool selection) const = 0; /** * Put data to the Clipboard - * @param buffer The buffer to copy to the clipboard - * @param selection The clipboard to copy too only used on X11 + * \param buffer The buffer to copy to the clipboard + * \param selection The clipboard to copy too only used on X11 */ virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const = 0; @@ -308,20 +308,20 @@ public: protected: /** * Initialize the system. - * @return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess init(); /** * Shut the system down. - * @return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess exit(); /** * Creates a fullscreen window. - * @param window The window created. - * @return Indication of success. + * \param window The window created. + * \return Indication of success. */ virtual GHOST_TSuccess createFullScreenWindow(GHOST_Window **window, const bool stereoVisual, const GHOST_TUns16 numOfAASamples = 0); diff --git a/intern/ghost/intern/GHOST_SystemCarbon.cpp b/intern/ghost/intern/GHOST_SystemCarbon.cpp index ffb8388543b..bb68ce8889c 100644 --- a/intern/ghost/intern/GHOST_SystemCarbon.cpp +++ b/intern/ghost/intern/GHOST_SystemCarbon.cpp @@ -32,8 +32,8 @@ /** * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date May 7, 2001 + * \author Maarten Gribnau + * \date May 7, 2001 */ #include @@ -990,7 +990,7 @@ bool GHOST_SystemCarbon::handleMouseDown(EventRef event) /* * The DragWindow() routine creates a lot of kEventWindowBoundsChanged * events. By setting m_ignoreWindowSizedMessages these are suppressed. - * @see GHOST_SystemCarbon::handleWindowEvent(EventRef event) + * \see GHOST_SystemCarbon::handleWindowEvent(EventRef event) */ /* even worse: scale window also generates a load of events, and nothing * is handled (read: client's event proc called) until you release mouse (ton) */ diff --git a/intern/ghost/intern/GHOST_SystemCarbon.h b/intern/ghost/intern/GHOST_SystemCarbon.h index 2415c57e094..61e5a086a0f 100644 --- a/intern/ghost/intern/GHOST_SystemCarbon.h +++ b/intern/ghost/intern/GHOST_SystemCarbon.h @@ -48,9 +48,9 @@ class GHOST_EventWindow; /** * OSX/Carbon Implementation of GHOST_System class. - * @see GHOST_System. - * @author Maarten Gribnau - * @date May 21, 2001 + * \see GHOST_System. + * \author Maarten Gribnau + * \date May 21, 2001 */ class GHOST_SystemCarbon : public GHOST_System { public: @@ -72,7 +72,7 @@ public: * Returns the system time. * Returns the number of milliseconds since the start of the system process. * Based on ANSI clock() routine. - * @return The number of milliseconds. + * \return The number of milliseconds. */ virtual GHOST_TUns64 getMilliSeconds() const; @@ -82,13 +82,13 @@ public: /** * Returns the number of displays on this system. - * @return The number of displays. + * \return The number of displays. */ virtual GHOST_TUns8 getNumDisplays() const; /** * Returns the dimensions of the main display on this system. - * @return The dimension of the main display. + * \return The dimension of the main display. */ virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const; @@ -96,15 +96,15 @@ public: * Create a new window. * The new window is added to the list of windows managed. * Never explicitly delete the window, use disposeWindow() instead. - * @param title The name of the window (displayed in the title bar of the window if the OS supports it). - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state of the window when opened. - * @param type The type of drawing context installed in this window. - * @param parentWindow Parent (embedder) window - * @return The new window (or 0 if creation failed). + * \param title The name of the window (displayed in the title bar of the window if the OS supports it). + * \param left The coordinate of the left edge of the window. + * \param top The coordinate of the top edge of the window. + * \param width The width the window. + * \param height The height the window. + * \param state The state of the window when opened. + * \param type The type of drawing context installed in this window. + * \param parentWindow Parent (embedder) window + * \return The new window (or 0 if creation failed). */ virtual GHOST_IWindow *createWindow( const STR_String& title, @@ -133,8 +133,8 @@ public: /** * Gets events from the system and stores them in the queue. - * @param waitForEvent Flag to wait for an event (or return immediately). - * @return Indication of the presence of events. + * \param waitForEvent Flag to wait for an event (or return immediately). + * \return Indication of the presence of events. */ virtual bool processEvents(bool waitForEvent); @@ -144,17 +144,17 @@ public: /** * Returns the current location of the cursor (location in screen coordinates) - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. + * \param x The x-coordinate of the cursor. + * \param y The y-coordinate of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const; /** * Updates the location of the cursor (location in screen coordinates). - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. + * \param x The x-coordinate of the cursor. + * \param y The y-coordinate of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); @@ -164,34 +164,34 @@ public: /** * Returns the state of all modifier keys. - * @param keys The state of all modifier keys (true == pressed). - * @return Indication of success. + * \param keys The state of all modifier keys (true == pressed). + * \return Indication of success. */ virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const; /** * Returns the state of the mouse buttons (ouside the message queue). - * @param buttons The state of the buttons. - * @return Indication of success. + * \param buttons The state of the buttons. + * \return Indication of success. */ virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const; /** * Returns Clipboard data - * @param selection Indicate which buffer to return - * @return Returns the selected buffer + * \param selection Indicate which buffer to return + * \return Returns the selected buffer */ virtual GHOST_TUns8 *getClipboard(bool selection) const; /** * Puts buffer to system clipboard - * @param buffer The buffer to be copied - * @param selection Indicates which buffer to copy too, only used on X11 + * \param buffer The buffer to be copied + * \param selection Indicates which buffer to copy too, only used on X11 */ virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const; /** - * @see GHOST_ISystem + * \see GHOST_ISystem */ int toggleConsole(int action) { return 0; @@ -201,55 +201,55 @@ protected: /** * Initializes the system. * For now, it justs registers the window class (WNDCLASS). - * @return A success value. + * \return A success value. */ virtual GHOST_TSuccess init(); /** * Closes the system down. - * @return A success value. + * \return A success value. */ virtual GHOST_TSuccess exit(); /** * Handles a tablet event. - * @param event A Mac event. - * @return Indication whether the event was handled. + * \param event A Mac event. + * \return Indication whether the event was handled. */ OSStatus handleTabletEvent(EventRef event); /** * Handles a mouse event. - * @param event A Mac event. - * @return Indication whether the event was handled. + * \param event A Mac event. + * \return Indication whether the event was handled. */ OSStatus handleMouseEvent(EventRef event); /** * Handles a key event. - * @param event A Mac event. - * @return Indication whether the event was handled. + * \param event A Mac event. + * \return Indication whether the event was handled. */ OSStatus handleKeyEvent(EventRef event); /** * Handles a window event. - * @param event A Mac event. - * @return Indication whether the event was handled. + * \param event A Mac event. + * \return Indication whether the event was handled. */ OSStatus handleWindowEvent(EventRef event); /** * Handles all basic Mac application stuff for a mouse down event. - * @param event A Mac event. - * @return Indication whether the event was handled. + * \param event A Mac event. + * \return Indication whether the event was handled. */ bool handleMouseDown(EventRef event); /** * Handles a Mac menu command. - * @param menuResult A Mac menu/item identifier. - * @return Indication whether the event was handled. + * \param menuResult A Mac menu/item identifier. + * \return Indication whether the event was handled. */ bool handleMenuCommand(GHOST_TInt32 menuResult); @@ -270,7 +270,7 @@ protected: /** * Callback for Mac Timer tasks that expire. - * @param tmTask Pointer to the timer task that expired. + * \param tmTask Pointer to the timer task that expired. */ //static void s_timerCallback(TMTaskPtr tmTask); diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index cb4e9fe3c99..08f982ffd3f 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -69,7 +69,7 @@ public: * Returns the system time. * Returns the number of milliseconds since the start of the system process. * Based on ANSI clock() routine. - * @return The number of milliseconds. + * \return The number of milliseconds. */ virtual GHOST_TUns64 getMilliSeconds() const; @@ -79,13 +79,13 @@ public: /** * Returns the number of displays on this system. - * @return The number of displays. + * \return The number of displays. */ virtual GHOST_TUns8 getNumDisplays() const; /** * Returns the dimensions of the main display on this system. - * @return The dimension of the main display. + * \return The dimension of the main display. */ virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const; @@ -93,17 +93,17 @@ public: * Create a new window. * The new window is added to the list of windows managed. * Never explicitly delete the window, use disposeWindow() instead. - * @param title The name of the window (displayed in the title bar of the window if the OS supports it). - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state of the window when opened. - * @param type The type of drawing context installed in this window. - * @param stereoVisual Stereo visual for quad buffered stereo. - * @param numOfAASamples Number of samples used for AA (zero if no AA) - * @param parentWindow Parent (embedder) window - * @return The new window (or 0 if creation failed). + * \param title The name of the window (displayed in the title bar of the window if the OS supports it). + * \param left The coordinate of the left edge of the window. + * \param top The coordinate of the top edge of the window. + * \param width The width the window. + * \param height The height the window. + * \param state The state of the window when opened. + * \param type The type of drawing context installed in this window. + * \param stereoVisual Stereo visual for quad buffered stereo. + * \param numOfAASamples Number of samples used for AA (zero if no AA) + * \param parentWindow Parent (embedder) window + * \return The new window (or 0 if creation failed). */ virtual GHOST_IWindow *createWindow( const STR_String& title, @@ -124,8 +124,8 @@ public: /** * Gets events from the system and stores them in the queue. - * @param waitForEvent Flag to wait for an event (or return immediately). - * @return Indication of the presence of events. + * \param waitForEvent Flag to wait for an event (or return immediately). + * \return Indication of the presence of events. */ virtual bool processEvents(bool waitForEvent); @@ -143,12 +143,12 @@ public: /** * Handles a drag'n'drop destination event. Called by GHOST_WindowCocoa window subclass - * @param eventType The type of drag'n'drop event - * @param draggedObjectType The type object concerned (currently array of file names, string, TIFF image) - * @param mouseX x mouse coordinate (in cocoa base window coordinates) - * @param mouseY y mouse coordinate - * @param window The window on which the event occurred - * @return Indication whether the event was handled. + * \param eventType The type of drag'n'drop event + * \param draggedObjectType The type object concerned (currently array of file names, string, TIFF image) + * \param mouseX x mouse coordinate (in cocoa base window coordinates) + * \param mouseY y mouse coordinate + * \param window The window on which the event occurred + * \return Indication whether the event was handled. */ GHOST_TSuccess handleDraggingEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType, GHOST_WindowCocoa *window, int mouseX, int mouseY, void *data); @@ -159,17 +159,17 @@ public: /** * Returns the current location of the cursor (location in screen coordinates) - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. + * \param x The x-coordinate of the cursor. + * \param y The y-coordinate of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const; /** * Updates the location of the cursor (location in screen coordinates). - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. + * \param x The x-coordinate of the cursor. + * \param y The y-coordinate of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); @@ -179,43 +179,43 @@ public: /** * Returns the state of all modifier keys. - * @param keys The state of all modifier keys (true == pressed). - * @return Indication of success. + * \param keys The state of all modifier keys (true == pressed). + * \return Indication of success. */ virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const; /** * Returns the state of the mouse buttons (ouside the message queue). - * @param buttons The state of the buttons. - * @return Indication of success. + * \param buttons The state of the buttons. + * \return Indication of success. */ virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const; /** * Returns Clipboard data - * @param selection Indicate which buffer to return - * @return Returns the selected buffer + * \param selection Indicate which buffer to return + * \return Returns the selected buffer */ virtual GHOST_TUns8 *getClipboard(bool selection) const; /** * Puts buffer to system clipboard - * @param buffer The buffer to be copied - * @param selection Indicates which buffer to copy too, only used on X11 + * \param buffer The buffer to be copied + * \param selection Indicates which buffer to copy too, only used on X11 */ virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const; /** * Handles a window event. Called by GHOST_WindowCocoa window delegate - * @param eventType The type of window event - * @param window The window on which the event occurred - * @return Indication whether the event was handled. + * \param eventType The type of window event + * \param window The window on which the event occurred + * \return Indication whether the event was handled. */ GHOST_TSuccess handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa *window); /** * Handles the Cocoa event telling the application has become active (again) - * @return Indication whether the event was handled. + * \return Indication whether the event was handled. */ GHOST_TSuccess handleApplicationBecomeActiveEvent(); @@ -225,7 +225,7 @@ public: void notifyExternalEventProcessed(); /** - * @see GHOST_ISystem + * \see GHOST_ISystem */ int toggleConsole(int action) { return 0; @@ -236,40 +236,40 @@ protected: /** * Initializes the system. * For now, it justs registers the window class (WNDCLASS). - * @return A success value. + * \return A success value. */ virtual GHOST_TSuccess init(); /** * Handles a tablet event. - * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) - * @param eventType The type of the event. + * \param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) + * \param eventType The type of the event. * It needs to be passed separately as it can be either directly in the event type, * or as a subtype if combined with a mouse button event. - * @return Indication whether the event was handled. + * \return Indication whether the event was handled. */ GHOST_TSuccess handleTabletEvent(void *eventPtr, short eventType); bool handleTabletEvent(void *eventPtr); /** * Handles a mouse event. - * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) - * @return Indication whether the event was handled. + * \param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) + * \return Indication whether the event was handled. */ GHOST_TSuccess handleMouseEvent(void *eventPtr); /** * Handles a key event. - * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) - * @return Indication whether the event was handled. + * \param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) + * \return Indication whether the event was handled. */ GHOST_TSuccess handleKeyEvent(void *eventPtr); /** * Performs the actual cursor position update (location in screen coordinates). - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. + * \param x The x-coordinate of the cursor. + * \param y The y-coordinate of the cursor. + * \return Indication of success. */ GHOST_TSuccess setMouseCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 1bffbc8eb85..7bc40287dc3 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -228,9 +228,9 @@ static GHOST_TButtonMask convertButton(int button) /** * Converts Mac rawkey codes (same for Cocoa & Carbon) * into GHOST key codes - * @param rawCode The raw physical key code - * @param recvChar the character ignoring modifiers (except for shift) - * @return Ghost key code + * \param rawCode The raw physical key code + * \param recvChar the character ignoring modifiers (except for shift) + * \return Ghost key code */ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) { @@ -594,9 +594,8 @@ GHOST_SystemCocoa::~GHOST_SystemCocoa() GHOST_TSuccess GHOST_SystemCocoa::init() { - - GHOST_TSuccess success = GHOST_System::init(); - if (success) { + GHOST_TSuccess success = GHOST_System::init(); + if (success) { #ifdef WITH_INPUT_NDOF m_ndofManager = new GHOST_NDOFManagerCocoa(*this); @@ -676,8 +675,8 @@ GHOST_TSuccess GHOST_SystemCocoa::init() [NSApp finishLaunching]; [pool drain]; - } - return success; + } + return success; } @@ -739,7 +738,7 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow( const GHOST_TEmbedderWindowID parentWindow ) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_IWindow* window = 0; //Get the available rect for including window contents @@ -755,45 +754,44 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow( window = new GHOST_WindowCocoa (this, title, left, bottom, width, height, state, type, stereoVisual, numOfAASamples); - if (window) { - if (window->getValid()) { - // Store the pointer to the window - GHOST_ASSERT(m_windowManager, "m_windowManager not initialized"); - m_windowManager->addWindow(window); - m_windowManager->setActiveWindow(window); + if (window) { + if (window->getValid()) { + // Store the pointer to the window + GHOST_ASSERT(m_windowManager, "m_windowManager not initialized"); + m_windowManager->addWindow(window); + m_windowManager->setActiveWindow(window); //Need to tell window manager the new window is the active one (Cocoa does not send the event activate upon window creation) - pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window)); + pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window)); pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window)); - - } - else { + } + else { GHOST_PRINT("GHOST_SystemCocoa::createWindow(): window invalid\n"); - delete window; - window = 0; - } - } + delete window; + window = 0; + } + } else { GHOST_PRINT("GHOST_SystemCocoa::createWindow(): could not create window\n"); } [pool drain]; - return window; + return window; } /** - * @note : returns coordinates in Cocoa screen coordinates + * \note : returns coordinates in Cocoa screen coordinates */ GHOST_TSuccess GHOST_SystemCocoa::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const { - NSPoint mouseLoc = [NSEvent mouseLocation]; + NSPoint mouseLoc = [NSEvent mouseLocation]; - // Returns the mouse location in screen coordinates - x = (GHOST_TInt32)mouseLoc.x; - y = (GHOST_TInt32)mouseLoc.y; - return GHOST_kSuccess; + // Returns the mouse location in screen coordinates + x = (GHOST_TInt32)mouseLoc.x; + y = (GHOST_TInt32)mouseLoc.y; + return GHOST_kSuccess; } /** - * @note : expect Cocoa screen coordinates + * \note : expect Cocoa screen coordinates */ GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) { @@ -833,7 +831,7 @@ GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(GHOST_TInt32 x, GHOST_T CGDisplayMoveCursorToPoint((CGDirectDisplayID)[[[windowScreen deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue], CGPointMake(xf, yf)); [pool drain]; - return GHOST_kSuccess; + return GHOST_kSuccess; } @@ -844,18 +842,18 @@ GHOST_TSuccess GHOST_SystemCocoa::getModifierKeys(GHOST_ModifierKeys& keys) cons keys.set(GHOST_kModifierKeyLeftShift, (m_modifierMask & NSShiftKeyMask) ? true : false); keys.set(GHOST_kModifierKeyLeftControl, (m_modifierMask & NSControlKeyMask) ? true : false); - return GHOST_kSuccess; + return GHOST_kSuccess; } GHOST_TSuccess GHOST_SystemCocoa::getButtons(GHOST_Buttons& buttons) const { buttons.clear(); - buttons.set(GHOST_kButtonMaskLeft, m_pressedMouseButtons & GHOST_kButtonMaskLeft); + buttons.set(GHOST_kButtonMaskLeft, m_pressedMouseButtons & GHOST_kButtonMaskLeft); buttons.set(GHOST_kButtonMaskRight, m_pressedMouseButtons & GHOST_kButtonMaskRight); buttons.set(GHOST_kButtonMaskMiddle, m_pressedMouseButtons & GHOST_kButtonMaskMiddle); buttons.set(GHOST_kButtonMaskButton4, m_pressedMouseButtons & GHOST_kButtonMaskButton4); buttons.set(GHOST_kButtonMaskButton5, m_pressedMouseButtons & GHOST_kButtonMaskButton5); - return GHOST_kSuccess; + return GHOST_kSuccess; } @@ -976,7 +974,7 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) m_ignoreWindowSizedMessages = false; - return anyProcessed; + return anyProcessed; } //Note: called from NSApplication delegate @@ -1442,7 +1440,7 @@ bool GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) { NSEvent *event = (NSEvent *)eventPtr; - GHOST_WindowCocoa* window; + GHOST_WindowCocoa* window; window = (GHOST_WindowCocoa*)m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]); if (!window) { @@ -1450,8 +1448,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) return GHOST_kFailure; } - switch ([event type]) - { + switch ([event type]) { case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown: @@ -1459,7 +1456,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) //Handle tablet events combined with mouse events handleTabletEvent(event); break; - + case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: diff --git a/intern/ghost/intern/GHOST_SystemPaths.h b/intern/ghost/intern/GHOST_SystemPaths.h index fe0fae71955..53cad347293 100644 --- a/intern/ghost/intern/GHOST_SystemPaths.h +++ b/intern/ghost/intern/GHOST_SystemPaths.h @@ -53,20 +53,20 @@ public: /** * Determine the base dir in which shared resources are located. It will first try to use * "unpack and run" path, then look for properly installed path, including versioning. - * @return Unsigned char string pointing to system dir (eg /usr/share/blender/). + * \return Unsigned char string pointing to system dir (eg /usr/share/blender/). */ virtual const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const = 0; /** * Determine the base dir in which user configuration is stored, including versioning. * If needed, it will create the base directory. - * @return Unsigned char string pointing to user dir (eg ~/.blender/). + * \return Unsigned char string pointing to user dir (eg ~/.blender/). */ virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const = 0; /** * Determine the directory of the current binary - * @return Unsigned char string pointing to the binary dir + * \return Unsigned char string pointing to the binary dir */ virtual const GHOST_TUns8 *getBinaryDir() const = 0; diff --git a/intern/ghost/intern/GHOST_SystemPathsCarbon.h b/intern/ghost/intern/GHOST_SystemPathsCarbon.h index 6a94c1d6606..9d9a3a22564 100644 --- a/intern/ghost/intern/GHOST_SystemPathsCarbon.h +++ b/intern/ghost/intern/GHOST_SystemPathsCarbon.h @@ -42,9 +42,9 @@ /** * OSX/Carbon Implementation of GHOST_SystemPaths class. - * @see GHOST_System. - * @author Andrea Weikert - * @date Aug 1, 2010 + * \see GHOST_System. + * \author Andrea Weikert + * \date Aug 1, 2010 */ class GHOST_SystemPathsCarbon : public GHOST_SystemPaths { public: @@ -61,20 +61,20 @@ public: /** * Determine the base dir in which shared resources are located. It will first try to use * "unpack and run" path, then look for properly installed path, including versioning. - * @return Unsigned char string pointing to system dir (eg /usr/share/blender/). + * \return Unsigned char string pointing to system dir (eg /usr/share/blender/). */ virtual const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const; /** * Determine the base dir in which user configuration is stored, including versioning. * If needed, it will create the base directory. - * @return Unsigned char string pointing to user dir (eg ~/.blender/). + * \return Unsigned char string pointing to user dir (eg ~/.blender/). */ virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const; /** * Determine the directory of the current binary - * @return Unsigned char string pointing to the binary dir + * \return Unsigned char string pointing to the binary dir */ virtual const GHOST_TUns8 *getBinaryDir() const; diff --git a/intern/ghost/intern/GHOST_SystemPathsCocoa.h b/intern/ghost/intern/GHOST_SystemPathsCocoa.h index ad44396c3ff..cd8d161ff9c 100644 --- a/intern/ghost/intern/GHOST_SystemPathsCocoa.h +++ b/intern/ghost/intern/GHOST_SystemPathsCocoa.h @@ -55,20 +55,20 @@ public: /** * Determine the base dir in which shared resources are located. It will first try to use * "unpack and run" path, then look for properly installed path, including versioning. - * @return Unsigned char string pointing to system dir (eg /usr/share/blender/). + * \return Unsigned char string pointing to system dir (eg /usr/share/blender/). */ virtual const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const; /** * Determine the base dir in which user configuration is stored, including versioning. * If needed, it will create the base directory. - * @return Unsigned char string pointing to user dir (eg ~/.blender/). + * \return Unsigned char string pointing to user dir (eg ~/.blender/). */ virtual const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const; /** * Determine the directory of the current binary - * @return Unsigned char string pointing to the binary dir + * \return Unsigned char string pointing to the binary dir */ virtual const GHOST_TUns8 *getBinaryDir() const; diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.h b/intern/ghost/intern/GHOST_SystemPathsWin32.h index 3a243f8be16..c074a7902b8 100644 --- a/intern/ghost/intern/GHOST_SystemPathsWin32.h +++ b/intern/ghost/intern/GHOST_SystemPathsWin32.h @@ -46,9 +46,9 @@ /** * WIN32 Implementation of GHOST_SystemPaths class. - * @see GHOST_SystemPaths. - * @author Andrea Weikert - * @date August 1, 2010 + * \see GHOST_SystemPaths. + * \author Andrea Weikert + * \date August 1, 2010 */ class GHOST_SystemPathsWin32 : public GHOST_SystemPaths { public: @@ -65,20 +65,20 @@ public: /** * Determine the base dir in which shared resources are located. It will first try to use * "unpack and run" path, then look for properly installed path, including versioning. - * @return Unsigned char string pointing to system dir (eg /usr/share/). + * \return Unsigned char string pointing to system dir (eg /usr/share/). */ const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const; /** * Determine the base dir in which user configuration is stored, including versioning. * If needed, it will create the base directory. - * @return Unsigned char string pointing to user dir (eg ~/). + * \return Unsigned char string pointing to user dir (eg ~/). */ const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const; /** * Determine the directory of the current binary - * @return Unsigned char string pointing to the binary dir + * \return Unsigned char string pointing to the binary dir */ const GHOST_TUns8 *getBinaryDir() const; diff --git a/intern/ghost/intern/GHOST_SystemPathsX11.h b/intern/ghost/intern/GHOST_SystemPathsX11.h index db6d5a6c6ea..1b5710e0f57 100644 --- a/intern/ghost/intern/GHOST_SystemPathsX11.h +++ b/intern/ghost/intern/GHOST_SystemPathsX11.h @@ -53,20 +53,20 @@ public: /** * Determine the base dir in which shared resources are located. It will first try to use * "unpack and run" path, then look for properly installed path, including versioning. - * @return Unsigned char string pointing to system dir (eg /usr/share/blender/). + * \return Unsigned char string pointing to system dir (eg /usr/share/blender/). */ const GHOST_TUns8 *getSystemDir(int version, const char *versionstr) const; /** * Determine the base dir in which user configuration is stored, including versioning. * If needed, it will create the base directory. - * @return Unsigned char string pointing to user dir (eg ~/.blender/). + * \return Unsigned char string pointing to user dir (eg ~/.blender/). */ const GHOST_TUns8 *getUserDir(int version, const char *versionstr) const; /** * Determine the directory of the current binary - * @return Unsigned char string pointing to the binary dir + * \return Unsigned char string pointing to the binary dir */ const GHOST_TUns8 *getBinaryDir() const; diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index f63ad38d0cc..6a756d35872 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -57,9 +57,9 @@ class GHOST_EventDragnDrop; /** * WIN32 Implementation of GHOST_System class. - * @see GHOST_System. - * @author Maarten Gribnau - * @date May 10, 2001 + * \see GHOST_System. + * \author Maarten Gribnau + * \date May 10, 2001 */ class GHOST_SystemWin32 : public GHOST_System { public: @@ -81,7 +81,7 @@ public: * Returns the system time. * Returns the number of milliseconds since the start of the system process. * This overloaded method uses the high frequency timer if available. - * @return The number of milliseconds. + * \return The number of milliseconds. */ virtual GHOST_TUns64 getMilliSeconds() const; @@ -91,13 +91,13 @@ public: /** * Returns the number of displays on this system. - * @return The number of displays. + * \return The number of displays. */ virtual GHOST_TUns8 getNumDisplays() const; /** * Returns the dimensions of the main display on this system. - * @return The dimension of the main display. + * \return The dimension of the main display. */ virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const; @@ -105,17 +105,17 @@ public: * Create a new window. * The new window is added to the list of windows managed. * Never explicitly delete the window, use disposeWindow() instead. - * @param title The name of the window (displayed in the title bar of the window if the OS supports it). - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state of the window when opened. - * @param type The type of drawing context installed in this window. - * @param stereoVisual Stereo visual for quad buffered stereo. - * @param numOfAASamples Number of samples used for AA (zero if no AA) - * @param parentWindow Parent (embedder) window - * @return The new window (or 0 if creation failed). + * \param title The name of the window (displayed in the title bar of the window if the OS supports it). + * \param left The coordinate of the left edge of the window. + * \param top The coordinate of the top edge of the window. + * \param width The width the window. + * \param height The height the window. + * \param state The state of the window when opened. + * \param type The type of drawing context installed in this window. + * \param stereoVisual Stereo visual for quad buffered stereo. + * \param numOfAASamples Number of samples used for AA (zero if no AA) + * \param parentWindow Parent (embedder) window + * \return The new window (or 0 if creation failed). */ virtual GHOST_IWindow *createWindow( const STR_String& title, @@ -131,8 +131,8 @@ public: /** * Gets events from the system and stores them in the queue. - * @param waitForEvent Flag to wait for an event (or return immediately). - * @return Indication of the presence of events. + * \param waitForEvent Flag to wait for an event (or return immediately). + * \return Indication of the presence of events. */ virtual bool processEvents(bool waitForEvent); @@ -143,17 +143,17 @@ public: /** * Returns the current location of the cursor (location in screen coordinates) - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. + * \param x The x-coordinate of the cursor. + * \param y The y-coordinate of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const; /** * Updates the location of the cursor (location in screen coordinates). - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. + * \param x The x-coordinate of the cursor. + * \param y The y-coordinate of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); @@ -163,41 +163,41 @@ public: /** * Returns the state of all modifier keys. - * @param keys The state of all modifier keys (true == pressed). - * @return Indication of success. + * \param keys The state of all modifier keys (true == pressed). + * \return Indication of success. */ virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const; /** * Returns the state of the mouse buttons (ouside the message queue). - * @param buttons The state of the buttons. - * @return Indication of success. + * \param buttons The state of the buttons. + * \return Indication of success. */ virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const; /** * Returns unsinged char from CUT_BUFFER0 - * @param selection Used by X11 only - * @return Returns the Clipboard + * \param selection Used by X11 only + * \return Returns the Clipboard */ virtual GHOST_TUns8 *getClipboard(bool selection) const; /** * Puts buffer to system clipboard - * @param selection Used by X11 only - * @return No return + * \param selection Used by X11 only + * \return No return */ virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const; /** * Creates a drag'n'drop event and pushes it immediately onto the event queue. * Called by GHOST_DropTargetWin32 class. - * @param eventType The type of drag'n'drop event - * @param draggedObjectType The type object concerned (currently array of file names, string, ?bitmap) - * @param mouseX x mouse coordinate (in window coordinates) - * @param mouseY y mouse coordinate - * @param window The window on which the event occurred - * @return Indication whether the event was handled. + * \param eventType The type of drag'n'drop event + * \param draggedObjectType The type object concerned (currently array of file names, string, ?bitmap) + * \param mouseX x mouse coordinate (in window coordinates) + * \param mouseY y mouse coordinate + * \param window The window on which the event occurred + * \return Indication whether the event was handled. */ static GHOST_TSuccess pushDragDropEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType, GHOST_IWindow *window, int mouseX, int mouseY, void *data); @@ -211,33 +211,33 @@ protected: /** * Initializes the system. * For now, it justs registers the window class (WNDCLASS). - * @return A success value. + * \return A success value. */ virtual GHOST_TSuccess init(); /** * Closes the system down. - * @return A success value. + * \return A success value. */ virtual GHOST_TSuccess exit(); /** * Converts raw WIN32 key codes from the wndproc to GHOST keys. - * @param window-> The window for this handling - * @param vKey The virtual key from hardKey - * @param ScanCode The ScanCode of pressed key (simular to PS/2 Set 1) - * @param extend Flag if key is not primerly (left or right) - * @return The GHOST key (GHOST_kKeyUnknown if no match). + * \param window-> The window for this handling + * \param vKey The virtual key from hardKey + * \param ScanCode The ScanCode of pressed key (simular to PS/2 Set 1) + * \param extend Flag if key is not primerly (left or right) + * \return The GHOST key (GHOST_kKeyUnknown if no match). */ virtual GHOST_TKey convertKey(GHOST_IWindow *window, short vKey, short ScanCode, short extend) const; /** * Catches raw WIN32 key codes from WM_INPUT in the wndproc. - * @param window The window for this handling - * @param raw RawInput structure with detailed info about the key event - * @param keyDown Pointer flag that specify if a key is down - * @param vk Pointer to virtual key - * @return The GHOST key (GHOST_kKeyUnknown if no match). + * \param window The window for this handling + * \param raw RawInput structure with detailed info about the key event + * \param keyDown Pointer flag that specify if a key is down + * \param vk Pointer to virtual key + * \return The GHOST key (GHOST_kKeyUnknown if no match). */ virtual GHOST_TKey hardKey(GHOST_IWindow *window, RAWINPUT const& raw, int *keyDown, char *vk); @@ -246,32 +246,32 @@ protected: * With the modifier keys, we want to distinguish left and right keys. * Sometimes this is not possible (Windows ME for instance). Then, we want * events generated for both keys. - * @param window The window receiving the event (the active window). + * \param window The window receiving the event (the active window). */ GHOST_EventKey *processModifierKeys(GHOST_IWindow *window); /** * Creates mouse button event. - * @param type The type of event to create. - * @param window The window receiving the event (the active window). - * @param mask The button mask of this event. - * @return The event created. + * \param type The type of event to create. + * \param window The window receiving the event (the active window). + * \param mask The button mask of this event. + * \return The event created. */ static GHOST_EventButton *processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask); /** * Creates cursor event. - * @param type The type of event to create. - * @param window The window receiving the event (the active window). - * @return The event created. + * \param type The type of event to create. + * \param window The window receiving the event (the active window). + * \return The event created. */ static GHOST_EventCursor *processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow); /** * Creates a mouse wheel event. - * @param window The window receiving the event (the active window). - * @param wParam The wParam from the wndproc - * @param lParam The lParam from the wndproc + * \param window The window receiving the event (the active window). + * \param wParam The wParam from the wndproc + * \param lParam The lParam from the wndproc */ static GHOST_EventWheel *processWheelEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam); @@ -279,31 +279,31 @@ protected: * Creates a key event and updates the key data stored locally (m_modifierKeys). * In most cases this is a straightforward conversion of key codes. * For the modifier keys however, we want to distinguish left and right keys. - * @param window The window receiving the event (the active window). - * @param raw RawInput structure with detailed info about the key event + * \param window The window receiving the event (the active window). + * \param raw RawInput structure with detailed info about the key event */ static GHOST_EventKey *processKeyEvent(GHOST_IWindow *window, RAWINPUT const& raw); /** * Process special keys (VK_OEM_*), to see if current key layout * gives us anything special, like ! on french AZERTY. - * @param window The window receiving the event (the active window). - * @param vKey The virtual key from hardKey - * @param ScanCode The ScanCode of pressed key (simular to PS/2 Set 1) + * \param window The window receiving the event (the active window). + * \param vKey The virtual key from hardKey + * \param ScanCode The ScanCode of pressed key (simular to PS/2 Set 1) */ virtual GHOST_TKey processSpecialKey(GHOST_IWindow *window, short vKey, short scanCode) const; /** * Creates a window event. - * @param type The type of event to create. - * @param window The window receiving the event (the active window). - * @return The event created. + * \param type The type of event to create. + * \param window The window receiving the event (the active window). + * \return The event created. */ static GHOST_Event *processWindowEvent(GHOST_TEventType type, GHOST_IWindow *window); /** * Handles minimum window size. - * @param minmax The MINMAXINFO structure. + * \param minmax The MINMAXINFO structure. */ static void processMinMaxInfo(MINMAXINFO *minmax); @@ -312,22 +312,22 @@ protected: * Handles Motion and Button events from a SpaceNavigator or related device. * Instead of returning an event object, this function communicates directly * with the GHOST_NDOFManager. - * @param raw RawInput structure with detailed info about the NDOF event - * @return Whether an event was generated and sent. + * \param raw RawInput structure with detailed info about the NDOF event + * \return Whether an event was generated and sent. */ bool processNDOF(RAWINPUT const& raw); #endif /** * Returns the local state of the modifier keys (from the message queue). - * @param keys The state of the keys. + * \param keys The state of the keys. */ inline virtual void retrieveModifierKeys(GHOST_ModifierKeys& keys) const; /** * Stores the state of the modifier keys locally. * For internal use only! - * @param keys The new state of the modifier keys. + * param keys The new state of the modifier keys. */ inline virtual void storeModifierKeys(const GHOST_ModifierKeys& keys); @@ -343,12 +343,13 @@ protected: /** * Toggles console - * @action 0 - Hides - * 1 - Shows - * 2 - Toggles - * 3 - Hides if it runs not from command line - * * - Does nothing - * @return current status (1 -visible, 0 - hidden) + * \param action + * - 0 - Hides + * - 1 - Shows + * - 2 - Toggles + * - 3 - Hides if it runs not from command line + * - * - Does nothing + * \return current status (1 -visible, 0 - hidden) */ int toggleConsole(int action); diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 7ac9b0c3c24..e75ecfb641e 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -203,7 +203,7 @@ getNumDisplays() const /** * Returns the dimensions of the main display on this system. - * @return The dimension of the main display. + * \return The dimension of the main display. */ void GHOST_SystemX11:: @@ -221,17 +221,17 @@ getMainDisplayDimensions( * Create a new window. * The new window is added to the list of windows managed. * Never explicitly delete the window, use disposeWindow() instead. - * @param title The name of the window (displayed in the title bar of the window if the OS supports it). - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state of the window when opened. - * @param type The type of drawing context installed in this window. - * @param stereoVisual Stereo visual for quad buffered stereo. - * @param numOfAASamples Number of samples used for AA (zero if no AA) - * @param parentWindow Parent (embedder) window - * @return The new window (or 0 if creation failed). + * \param title The name of the window (displayed in the title bar of the window if the OS supports it). + * \param left The coordinate of the left edge of the window. + * \param top The coordinate of the top edge of the window. + * \param width The width the window. + * \param height The height the window. + * \param state The state of the window when opened. + * \param type The type of drawing context installed in this window. + * \param stereoVisual Stereo visual for quad buffered stereo. + * \param numOfAASamples Number of samples used for AA (zero if no AA) + * \param parentWindow Parent (embedder) window + * \return The new window (or 0 if creation failed). */ GHOST_IWindow * GHOST_SystemX11:: diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index d86790e262f..92bffe46357 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -49,9 +49,9 @@ class GHOST_WindowX11; /** * X11 Implementation of GHOST_System class. - * @see GHOST_System. - * @author Laurence Bourn - * @date October 26, 2001 + * \see GHOST_System. + * \author Laurence Bourn + * \date October 26, 2001 */ class GHOST_SystemX11 : public GHOST_System { @@ -77,13 +77,13 @@ public: /** - * @section Interface Inherited from GHOST_ISystem + * \section Interface Inherited from GHOST_ISystem */ /** * Returns the system time. * Returns the number of milliseconds since the start of the system process. - * @return The number of milliseconds. + * \return The number of milliseconds. */ GHOST_TUns64 getMilliSeconds( @@ -92,7 +92,7 @@ public: /** * Returns the number of displays on this system. - * @return The number of displays. + * \return The number of displays. */ GHOST_TUns8 getNumDisplays( @@ -100,7 +100,7 @@ public: /** * Returns the dimensions of the main display on this system. - * @return The dimension of the main display. + * \return The dimension of the main display. */ void getMainDisplayDimensions( @@ -112,16 +112,16 @@ public: * Create a new window. * The new window is added to the list of windows managed. * Never explicitly delete the window, use disposeWindow() instead. - * @param title The name of the window (displayed in the title bar of the window if the OS supports it). - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state of the window when opened. - * @param type The type of drawing context installed in this window. - * @param stereoVisual Create a stereo visual for quad buffered stereo. - * @param parentWindow Parent (embedder) window - * @return The new window (or 0 if creation failed). + * \param title The name of the window (displayed in the title bar of the window if the OS supports it). + * \param left The coordinate of the left edge of the window. + * \param top The coordinate of the top edge of the window. + * \param width The width the window. + * \param height The height the window. + * \param state The state of the window when opened. + * \param type The type of drawing context installed in this window. + * \param stereoVisual Create a stereo visual for quad buffered stereo. + * \param parentWindow Parent (embedder) window + * \return The new window (or 0 if creation failed). */ GHOST_IWindow * createWindow( @@ -138,13 +138,13 @@ public: ); /** - * @section Interface Inherited from GHOST_ISystem + * \section Interface Inherited from GHOST_ISystem */ /** * Retrieves events from the system and stores them in the queue. - * @param waitForEvent Flag to wait for an event (or return immediately). - * @return Indication of the presence of events. + * \param waitForEvent Flag to wait for an event (or return immediately). + * \return Indication of the presence of events. */ bool processEvents( @@ -152,7 +152,7 @@ public: ); /** - * @section Interface Inherited from GHOST_System + * \section Interface Inherited from GHOST_System */ GHOST_TSuccess getCursorPosition( @@ -168,8 +168,8 @@ public: /** * Returns the state of all modifier keys. - * @param keys The state of all modifier keys (true == pressed). - * @return Indication of success. + * \param keys The state of all modifier keys (true == pressed). + * \return Indication of success. */ GHOST_TSuccess getModifierKeys( @@ -178,8 +178,8 @@ public: /** * Returns the state of the mouse buttons (ouside the message queue). - * @param buttons The state of the buttons. - * @return Indication of success. + * \param buttons The state of the buttons. + * \return Indication of success. */ GHOST_TSuccess getButtons( @@ -187,7 +187,7 @@ public: ) const; /** - * @section Interface Dirty + * \section Interface Dirty * Flag a window as dirty. This will * generate a GHOST window update event on a call to processEvents() */ @@ -223,15 +223,15 @@ public: /** * Returns unsinged char from CUT_BUFFER0 - * @param selection Get selection, X11 only feature - * @return Returns the Clipboard indicated by Flag + * \param selection Get selection, X11 only feature + * \return Returns the Clipboard indicated by Flag */ GHOST_TUns8 *getClipboard(bool selection) const; /** * Puts buffer to system clipboard - * @param buffer The buffer to copy to the clipboard - * @param selection Set the selection into the clipboard, X11 only feature + * \param buffer The buffer to copy to the clipboard + * \param selection Set the selection into the clipboard, X11 only feature */ void putClipboard(GHOST_TInt8 *buffer, bool selection) const; @@ -239,18 +239,18 @@ public: /** * Creates a drag'n'drop event and pushes it immediately onto the event queue. * Called by GHOST_DropTargetX11 class. - * @param eventType The type of drag'n'drop event - * @param draggedObjectType The type object concerned (currently array of file names, string, ?bitmap) - * @param mouseX x mouse coordinate (in window coordinates) - * @param mouseY y mouse coordinate - * @param window The window on which the event occurred - * @return Indication whether the event was handled. + * \param eventType The type of drag'n'drop event + * \param draggedObjectType The type object concerned (currently array of file names, string, ?bitmap) + * \param mouseX x mouse coordinate (in window coordinates) + * \param mouseY y mouse coordinate + * \param window The window on which the event occurred + * \return Indication whether the event was handled. */ static GHOST_TSuccess pushDragDropEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType, GHOST_IWindow *window, int mouseX, int mouseY, void *data); #endif /** - * @see GHOST_ISystem + * \see GHOST_ISystem */ int toggleConsole(int action) { return 0; diff --git a/intern/ghost/intern/GHOST_TimerManager.cpp b/intern/ghost/intern/GHOST_TimerManager.cpp index 4ad28d6633d..b1186507028 100644 --- a/intern/ghost/intern/GHOST_TimerManager.cpp +++ b/intern/ghost/intern/GHOST_TimerManager.cpp @@ -32,8 +32,8 @@ /** * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date May 31, 2001 + * \author Maarten Gribnau + * \date May 31, 2001 */ #include "GHOST_TimerManager.h" diff --git a/intern/ghost/intern/GHOST_TimerManager.h b/intern/ghost/intern/GHOST_TimerManager.h index 88d27088c1d..5a24c56ef10 100644 --- a/intern/ghost/intern/GHOST_TimerManager.h +++ b/intern/ghost/intern/GHOST_TimerManager.h @@ -44,8 +44,8 @@ class GHOST_TimerTask; * Manages a list of timer tasks. * Timer tasks added are owned by the manager. * Don't delete timer task objects. - * @author Maarten Gribnau - * @date May 31, 2001 + * \author Maarten Gribnau + * \date May 31, 2001 */ class GHOST_TimerManager { @@ -62,51 +62,51 @@ public: /** * Returns the number of timer tasks. - * @return The number of events on the stack. + * \return The number of events on the stack. */ virtual GHOST_TUns32 getNumTimers(); /** * Returns whther this timer task ins in our list. - * @return Indication of presence. + * \return Indication of presence. */ virtual bool getTimerFound(GHOST_TimerTask *timer); /** * Adds a timer task to the list. * It is only added when it not already present in the list. - * @param timer The timer task added to the list. - * @return Indication as to whether addition has succeeded. + * \param timer The timer task added to the list. + * \return Indication as to whether addition has succeeded. */ virtual GHOST_TSuccess addTimer(GHOST_TimerTask *timer); /** * Removes a timer task from the list. * It is only removed when it is found in the list. - * @param timer The timer task to be removed from the list. - * @return Indication as to whether removal has succeeded. + * \param timer The timer task to be removed from the list. + * \return Indication as to whether removal has succeeded. */ virtual GHOST_TSuccess removeTimer(GHOST_TimerTask *timer); /** * Finds the soonest time the next timer would fire. - * @return The soonest time the next timer would fire, + * \return The soonest time the next timer would fire, * or GHOST_kFireTimeNever if no timers exist. */ virtual GHOST_TUns64 nextFireTime(); /** * Checks all timer tasks to see if they are expired and fires them if needed. - * @param time The current time. - * @return True if any timers were fired. + * \param time The current time. + * \return True if any timers were fired. */ virtual bool fireTimers(GHOST_TUns64 time); /** * Checks this timer task to see if they are expired and fires them if needed. - * @param time The current time. - * @param task The timer task to check and optionally fire. - * @return True if the timer fired. + * \param time The current time. + * \param task The timer task to check and optionally fire. + * \return True if the timer fired. */ virtual bool fireTimer(GHOST_TUns64 time, GHOST_TimerTask *task); diff --git a/intern/ghost/intern/GHOST_TimerTask.h b/intern/ghost/intern/GHOST_TimerTask.h index d74d705d511..0731bc066af 100644 --- a/intern/ghost/intern/GHOST_TimerTask.h +++ b/intern/ghost/intern/GHOST_TimerTask.h @@ -38,18 +38,18 @@ /** * Implementation of a timer task. - * @author Maarten Gribnau - * @date May 28, 2001 + * \author Maarten Gribnau + * \date May 28, 2001 */ class GHOST_TimerTask : public GHOST_ITimerTask { public: /** * Constructor. - * @param start The timer start time. - * @param interval The interval between calls to the timerProc - * @param timerProc The callbak invoked when the interval expires. - * @param data The timer user data. + * \param start The timer start time. + * \param interval The interval between calls to the timerProc + * \param timerProc The callbak invoked when the interval expires. + * \param data The timer user data. */ GHOST_TimerTask(GHOST_TUns64 start, GHOST_TUns64 interval, @@ -66,7 +66,7 @@ public: /** * Returns the timer start time. - * @return The timer start time. + * \return The timer start time. */ inline virtual GHOST_TUns64 getStart() const { @@ -75,7 +75,7 @@ public: /** * Changes the timer start time. - * @param start The timer start time. + * \param start The timer start time. */ virtual void setStart(GHOST_TUns64 start) { @@ -84,7 +84,7 @@ public: /** * Returns the timer interval. - * @return The timer interval. + * \return The timer interval. */ inline virtual GHOST_TUns64 getInterval() const { @@ -93,7 +93,7 @@ public: /** * Changes the timer interval. - * @param interval The timer interval. + * \param interval The timer interval. */ virtual void setInterval(GHOST_TUns64 interval) { @@ -102,7 +102,7 @@ public: /** * Returns the time the timerProc will be called. - * @return The time the timerProc will be called. + * \return The time the timerProc will be called. */ inline virtual GHOST_TUns64 getNext() const { @@ -111,7 +111,7 @@ public: /** * Changes the time the timerProc will be called. - * @param next The time the timerProc will be called. + * \param next The time the timerProc will be called. */ virtual void setNext(GHOST_TUns64 next) { @@ -120,7 +120,7 @@ public: /** * Returns the timer callback. - * @return the timer callback. + * \return the timer callback. */ inline virtual GHOST_TimerProcPtr getTimerProc() const { @@ -129,7 +129,7 @@ public: /** * Changes the timer callback. - * @param The timer callback. + * \param The timer callback. */ inline virtual void setTimerProc(const GHOST_TimerProcPtr timerProc) { @@ -138,7 +138,7 @@ public: /** * Returns the timer user data. - * @return The timer user data. + * \return The timer user data. */ inline virtual GHOST_TUserDataPtr getUserData() const { @@ -147,7 +147,7 @@ public: /** * Changes the time user data. - * @param data The timer user data. + * \param data The timer user data. */ virtual void setUserData(const GHOST_TUserDataPtr userData) { @@ -156,7 +156,7 @@ public: /** * Returns the auxiliary storage room. - * @return The auxiliary storage room. + * \return The auxiliary storage room. */ inline virtual GHOST_TUns32 getAuxData() const { @@ -165,7 +165,7 @@ public: /** * Changes the auxiliary storage room. - * @param auxData The auxiliary storage room. + * \param auxData The auxiliary storage room. */ virtual void setAuxData(GHOST_TUns32 auxData) { diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp index c3244d1594d..eb80a073b44 100644 --- a/intern/ghost/intern/GHOST_Window.cpp +++ b/intern/ghost/intern/GHOST_Window.cpp @@ -32,8 +32,8 @@ /** * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date May 10, 2001 + * \author Maarten Gribnau + * \date May 10, 2001 */ #include "GHOST_Window.h" diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index 10a6a57b9fe..3043b107aa1 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -43,14 +43,14 @@ class STR_String; * upper-left corner of the screen. * Implements part of the GHOST_IWindow interface and adds some methods to * be implemented by childs of this class. - * @author Maarten Gribnau - * @date May 7, 2001 + * \author Maarten Gribnau + * \date May 7, 2001 */ class GHOST_Window : public GHOST_IWindow { public: /** - * @section Interface inherited from GHOST_IWindow left for derived class + * \section Interface inherited from GHOST_IWindow left for derived class * implementation. * virtual bool getValid() const = 0; * virtual void setTitle(const STR_String& title) = 0; @@ -75,12 +75,12 @@ public: * Constructor. * Creates a new window and opens it. * To check if the window was created properly, use the getValid() method. - * @param width The width the window. - * @param heigh The height the window. - * @param state The state the window is initially opened with. - * @param type The type of drawing context installed in this window. - * @param stereoVisual Stereo visual for quad buffered stereo. - * @param numOfAASamples Number of samples used for AA (zero if no AA) + * \param width The width the window. + * \param heigh The height the window. + * \param state The state the window is initially opened with. + * \param type The type of drawing context installed in this window. + * \param stereoVisual Stereo visual for quad buffered stereo. + * \param numOfAASamples Number of samples used for AA (zero if no AA) */ GHOST_Window( GHOST_TUns32 width, @@ -91,7 +91,7 @@ public: const GHOST_TUns16 numOfAASamples = 0); /** - * @section Interface inherited from GHOST_IWindow left for derived class + * \section Interface inherited from GHOST_IWindow left for derived class * implementation. * virtual bool getValid() const = 0; * virtual void setTitle(const STR_String& title) = 0; @@ -119,30 +119,30 @@ public: /** * Returns the associated OS object/handle - * @return The associated OS object/handle + * \return The associated OS object/handle */ virtual void *getOSWindow() const; /** * Returns the current cursor shape. - * @return The current cursor shape. + * \return The current cursor shape. */ inline virtual GHOST_TStandardCursor getCursorShape() const; /** * Set the shape of the cursor. - * @param cursor The new cursor shape type id. - * @return Indication of success. + * \param cursor The new cursor shape type id. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape); /** * Set the shape of the cursor to a custom cursor. - * @param bitmap The bitmap data for the cursor. - * @param mask The mask data for the cursor. - * @param hotX The X coordinate of the cursor hotspot. - * @param hotY The Y coordinate of the cursor hotspot. - * @return Indication of success. + * \param bitmap The bitmap data for the cursor. + * \param mask The mask data for the cursor. + * \param hotX The X coordinate of the cursor hotspot. + * \param hotY The Y coordinate of the cursor hotspot. + * \return Indication of success. */ virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], @@ -157,7 +157,7 @@ public: /** * Returns the visibility state of the cursor. - * @return The visibility state of the cursor. + * \return The visibility state of the cursor. */ inline virtual bool getCursorVisibility() const; inline virtual GHOST_TGrabCursorMode getCursorGrabMode() const; @@ -168,15 +168,15 @@ public: /** * Shows or hides the cursor. - * @param visible The new visibility state of the cursor. - * @return Indication of success. + * \param visible The new visibility state of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorVisibility(bool visible); /** * Sets the cursor grab. - * @param mode The new grab state of the cursor. - * @return Indication of success. + * \param mode The new grab state of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds); @@ -188,7 +188,7 @@ public: /** * Sets the progress bar value displayed in the window/application icon - * @param progress The progress % (0.0 to 1.0) + * \param progress The progress % (0.0 to 1.0) */ virtual GHOST_TSuccess setProgressBar(float progress) { return GHOST_kFailure; @@ -214,20 +214,20 @@ public: /** * Sets the window "modified" status, indicating unsaved changes - * @param isUnsavedChanges Unsaved changes or not - * @return Indication of success. + * \param isUnsavedChanges Unsaved changes or not + * \return Indication of success. */ virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges); /** * Gets the window "modified" status, indicating unsaved changes - * @return True if there are unsaved changes + * \return True if there are unsaved changes */ virtual bool getModifiedState(); /** * Returns the type of drawing context used in this window. - * @return The current type of drawing context. + * \return The current type of drawing context. */ inline virtual GHOST_TDrawingContextType getDrawingContextType(); @@ -235,14 +235,14 @@ public: * Tries to install a rendering context in this window. * Child classes do not need to overload this method. * They should overload the installDrawingContext and removeDrawingContext instead. - * @param type The type of rendering context installed. - * @return Indication as to whether installation has succeeded. + * \param type The type of rendering context installed. + * \return Indication as to whether installation has succeeded. */ virtual GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type); /** * Returns the window user data. - * @return The window user data. + * \return The window user data. */ inline virtual GHOST_TUserDataPtr getUserData() const { @@ -251,7 +251,7 @@ public: /** * Changes the window user data. - * @param data The window user data. + * \param data The window user data. */ virtual void setUserData(const GHOST_TUserDataPtr userData) { @@ -261,14 +261,14 @@ public: protected: /** * Tries to install a rendering context in this window. - * @param type The type of rendering context installed. - * @return Indication as to whether installation has succeeded. + * \param type The type of rendering context installed. + * \return Indication as to whether installation has succeeded. */ virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type) = 0; /** * Removes the current drawing context. - * @return Indication as to whether removal has succeeded. + * \return Indication as to whether removal has succeeded. */ virtual GHOST_TSuccess removeDrawingContext() = 0; diff --git a/intern/ghost/intern/GHOST_WindowCarbon.cpp b/intern/ghost/intern/GHOST_WindowCarbon.cpp index ca3366004d3..c7be02cc7af 100644 --- a/intern/ghost/intern/GHOST_WindowCarbon.cpp +++ b/intern/ghost/intern/GHOST_WindowCarbon.cpp @@ -32,8 +32,8 @@ /** * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date May 10, 2001 + * \author Maarten Gribnau + * \date May 10, 2001 */ #include "GHOST_WindowCarbon.h" diff --git a/intern/ghost/intern/GHOST_WindowCarbon.h b/intern/ghost/intern/GHOST_WindowCarbon.h index 1291fb1a2c4..d25d57156f6 100644 --- a/intern/ghost/intern/GHOST_WindowCarbon.h +++ b/intern/ghost/intern/GHOST_WindowCarbon.h @@ -54,8 +54,8 @@ * which is called the gutter. * When OpenGL contexts are active, GHOST will use AGL_BUFFER_RECT to prevent * OpenGL drawing outside the reduced client rectangle. - * @author Maarten Gribnau - * @date May 23, 2001 + * \author Maarten Gribnau + * \date May 23, 2001 */ class GHOST_WindowCarbon : public GHOST_Window { public: @@ -63,14 +63,14 @@ public: * Constructor. * Creates a new window and opens it. * To check if the window was created properly, use the getValid() method. - * @param title The text shown in the title bar of the window. - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state the window is initially opened with. - * @param type The type of drawing context installed in this window. - * @param stereoVisual Stereo visual for quad buffered stereo. + * \param title The text shown in the title bar of the window. + * \param left The coordinate of the left edge of the window. + * \param top The coordinate of the top edge of the window. + * \param width The width the window. + * \param height The height the window. + * \param state The state the window is initially opened with. + * \param type The type of drawing context installed in this window. + * \param stereoVisual Stereo visual for quad buffered stereo. */ GHOST_WindowCarbon( const STR_String& title, @@ -92,109 +92,109 @@ public: /** * Returns indication as to whether the window is valid. - * @return The validity of the window. + * \return The validity of the window. */ virtual bool getValid() const; /** * Sets the title displayed in the title bar. - * @param title The title to display in the title bar. + * \param title The title to display in the title bar. */ virtual void setTitle(const STR_String& title); /** * Returns the title displayed in the title bar. - * @param title The title displayed in the title bar. + * \param title The title displayed in the title bar. */ virtual void getTitle(STR_String& title) const; /** * Returns the window rectangle dimensions. * The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen. - * @param bounds The bounding rectangle of the window. + * \param bounds The bounding rectangle of the window. */ virtual void getWindowBounds(GHOST_Rect& bounds) const; /** * Returns the client rectangle dimensions. * The left and top members of the rectangle are always zero. - * @param bounds The bounding rectangle of the cleient area of the window. + * \param bounds The bounding rectangle of the cleient area of the window. */ virtual void getClientBounds(GHOST_Rect& bounds) const; /** * Resizes client rectangle width. - * @param width The new width of the client area of the window. + * \param width The new width of the client area of the window. */ virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width); /** * Resizes client rectangle height. - * @param height The new height of the client area of the window. + * \param height The new height of the client area of the window. */ virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height); /** * Resizes client rectangle. - * @param width The new width of the client area of the window. - * @param height The new height of the client area of the window. + * \param width The new width of the client area of the window. + * \param height The new height of the client area of the window. */ virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height); /** * Returns the state of the window (normal, minimized, maximized). - * @return The state of the window. + * \return The state of the window. */ virtual GHOST_TWindowState getState() const; /** * Converts a point in screen coordinates to client rectangle coordinates - * @param inX The x-coordinate on the screen. - * @param inY The y-coordinate on the screen. - * @param outX The x-coordinate in the client rectangle. - * @param outY The y-coordinate in the client rectangle. + * \param inX The x-coordinate on the screen. + * \param inY The y-coordinate on the screen. + * \param outX The x-coordinate in the client rectangle. + * \param outY The y-coordinate in the client rectangle. */ virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; /** * Converts a point in screen coordinates to client rectangle coordinates - * @param inX The x-coordinate in the client rectangle. - * @param inY The y-coordinate in the client rectangle. - * @param outX The x-coordinate on the screen. - * @param outY The y-coordinate on the screen. + * \param inX The x-coordinate in the client rectangle. + * \param inY The y-coordinate in the client rectangle. + * \param outX The x-coordinate on the screen. + * \param outY The y-coordinate on the screen. */ virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; /** * Sets the state of the window (normal, minimized, maximized). - * @param state The state of the window. - * @return Indication of success. + * \param state The state of the window. + * \return Indication of success. */ virtual GHOST_TSuccess setState(GHOST_TWindowState state); /** * Sets the order of the window (bottom, top). - * @param order The order of the window. - * @return Indication of success. + * \param order The order of the window. + * \return Indication of success. */ virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order); /** * Swaps front and back buffers of a window. - * @return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess swapBuffers(); /** * Updates the drawing context of this window. Needed * whenever the window is changed. - * @return Indication of success. + * \return Indication of success. */ GHOST_TSuccess updateDrawingContext(); /** * Activates the drawing context of this window. - * @return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess activateDrawingContext(); @@ -202,7 +202,7 @@ public: /** * Returns the dirty state of the window when in full-screen mode. - * @return Whether it is dirty. + * \return Whether it is dirty. */ virtual bool getFullScreenDirty(); @@ -223,20 +223,20 @@ public: protected: /** * Tries to install a rendering context in this window. - * @param type The type of rendering context installed. - * @return Indication as to whether installation has succeeded. + * \param type The type of rendering context installed. + * \return Indication as to whether installation has succeeded. */ virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type); /** * Removes the current drawing context. - * @return Indication as to whether removal has succeeded. + * \return Indication as to whether removal has succeeded. */ virtual GHOST_TSuccess removeDrawingContext(); /** * Invalidates the contents of this window. - * @return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess invalidate(); @@ -263,15 +263,15 @@ protected: /** * Converts a string object to a Mac Pascal string. - * @param in The string object to be converted. - * @param out The converted string. + * \param in The string object to be converted. + * \param out The converted string. */ virtual void gen2mac(const STR_String& in, Str255 out) const; /** * Converts a Mac Pascal string to a string object. - * @param in The string to be converted. - * @param out The converted string object. + * \param in The string to be converted. + * \param out The converted string object. */ virtual void mac2gen(const Str255 in, STR_String& out) const; diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h index d53dfa71d95..3e5c675d4a7 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.h +++ b/intern/ghost/intern/GHOST_WindowCocoa.h @@ -53,8 +53,8 @@ class GHOST_SystemCocoa; * which is called the gutter. * When OpenGL contexts are active, GHOST will use AGL_BUFFER_RECT to prevent * OpenGL drawing outside the reduced client rectangle. - * @author Maarten Gribnau - * @date May 23, 2001 + * \author Maarten Gribnau + * \date May 23, 2001 */ class GHOST_WindowCocoa : public GHOST_Window { public: @@ -62,16 +62,16 @@ public: * Constructor. * Creates a new window and opens it. * To check if the window was created properly, use the getValid() method. - * @param systemCocoa The associated system class to forward events to - * @param title The text shown in the title bar of the window. - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state the window is initially opened with. - * @param type The type of drawing context installed in this window. - * @param stereoVisual Stereo visual for quad buffered stereo. - * @param numOfAASamples Number of samples used for AA (zero if no AA) + * \param systemCocoa The associated system class to forward events to + * \param title The text shown in the title bar of the window. + * \param left The coordinate of the left edge of the window. + * \param top The coordinate of the top edge of the window. + * \param width The width the window. + * \param height The height the window. + * \param state The state the window is initially opened with. + * \param type The type of drawing context installed in this window. + * \param stereoVisual Stereo visual for quad buffered stereo. + * \param numOfAASamples Number of samples used for AA (zero if no AA) */ GHOST_WindowCocoa( GHOST_SystemCocoa *systemCocoa, @@ -94,148 +94,148 @@ public: /** * Returns indication as to whether the window is valid. - * @return The validity of the window. + * \return The validity of the window. */ virtual bool getValid() const; /** * Returns the associated NSWindow object - * @return The associated NSWindow object + * \return The associated NSWindow object */ virtual void *getOSWindow() const; /** * Sets the title displayed in the title bar. - * @param title The title to display in the title bar. + * \param title The title to display in the title bar. */ virtual void setTitle(const STR_String& title); /** * Returns the title displayed in the title bar. - * @param title The title displayed in the title bar. + * \param title The title displayed in the title bar. */ virtual void getTitle(STR_String& title) const; /** * Returns the window rectangle dimensions. * The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen. - * @param bounds The bounding rectangle of the window. + * \param bounds The bounding rectangle of the window. */ virtual void getWindowBounds(GHOST_Rect& bounds) const; /** * Returns the client rectangle dimensions. * The left and top members of the rectangle are always zero. - * @param bounds The bounding rectangle of the cleient area of the window. + * \param bounds The bounding rectangle of the cleient area of the window. */ virtual void getClientBounds(GHOST_Rect& bounds) const; /** * Resizes client rectangle width. - * @param width The new width of the client area of the window. + * \param width The new width of the client area of the window. */ virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width); /** * Resizes client rectangle height. - * @param height The new height of the client area of the window. + * \param height The new height of the client area of the window. */ virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height); /** * Resizes client rectangle. - * @param width The new width of the client area of the window. - * @param height The new height of the client area of the window. + * \param width The new width of the client area of the window. + * \param height The new height of the client area of the window. */ virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height); /** * Returns the state of the window (normal, minimized, maximized). - * @return The state of the window. + * \return The state of the window. */ virtual GHOST_TWindowState getState() const; /** * Sets the window "modified" status, indicating unsaved changes - * @param isUnsavedChanges Unsaved changes or not - * @return Indication of success. + * \param isUnsavedChanges Unsaved changes or not + * \return Indication of success. */ virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges); /** * Converts a point in screen coordinates to client rectangle coordinates - * @param inX The x-coordinate on the screen. - * @param inY The y-coordinate on the screen. - * @param outX The x-coordinate in the client rectangle. - * @param outY The y-coordinate in the client rectangle. + * \param inX The x-coordinate on the screen. + * \param inY The y-coordinate on the screen. + * \param outX The x-coordinate in the client rectangle. + * \param outY The y-coordinate in the client rectangle. */ virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; /** * Converts a point in screen coordinates to client rectangle coordinates - * @param inX The x-coordinate in the client rectangle. - * @param inY The y-coordinate in the client rectangle. - * @param outX The x-coordinate on the screen. - * @param outY The y-coordinate on the screen. + * \param inX The x-coordinate in the client rectangle. + * \param inY The y-coordinate in the client rectangle. + * \param outX The x-coordinate on the screen. + * \param outY The y-coordinate on the screen. */ virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; /** * Converts a point in screen coordinates to client rectangle coordinates * but without the y coordinate conversion needed for ghost compatibility. - * @param inX The x-coordinate in the client rectangle. - * @param inY The y-coordinate in the client rectangle. - * @param outX The x-coordinate on the screen. - * @param outY The y-coordinate on the screen. + * \param inX The x-coordinate in the client rectangle. + * \param inY The y-coordinate in the client rectangle. + * \param outX The x-coordinate on the screen. + * \param outY The y-coordinate on the screen. */ void clientToScreenIntern(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; /** * Converts a point in screen coordinates to client rectangle coordinates, * but without the y coordinate conversion needed for ghost compatibility. - * @param inX The x-coordinate in the client rectangle. - * @param inY The y-coordinate in the client rectangle. - * @param outX The x-coordinate on the screen. - * @param outY The y-coordinate on the screen. + * \param inX The x-coordinate in the client rectangle. + * \param inY The y-coordinate in the client rectangle. + * \param outX The x-coordinate on the screen. + * \param outY The y-coordinate on the screen. */ void screenToClientIntern(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; /** * Gets the screen the window is displayed in - * @return The NSScreen object + * \return The NSScreen object */ NSScreen *getScreen(); /** * Sets the state of the window (normal, minimized, maximized). - * @param state The state of the window. - * @return Indication of success. + * \param state The state of the window. + * \return Indication of success. */ virtual GHOST_TSuccess setState(GHOST_TWindowState state); /** * Sets the order of the window (bottom, top). - * @param order The order of the window. - * @return Indication of success. + * \param order The order of the window. + * \return Indication of success. */ virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order); /** * Swaps front and back buffers of a window. - * @return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess swapBuffers(); /** * Updates the drawing context of this window. Needed * whenever the window is changed. - * @return Indication of success. + * \return Indication of success. */ GHOST_TSuccess updateDrawingContext(); /** * Activates the drawing context of this window. - * @return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess activateDrawingContext(); @@ -254,7 +254,7 @@ public: /** * Sets the progress bar value displayed in the window/application icon - * @param progress The progress % (0.0 to 1.0) + * \param progress The progress % (0.0 to 1.0) */ virtual GHOST_TSuccess setProgressBar(float progress); @@ -265,20 +265,20 @@ public: protected: /** * Tries to install a rendering context in this window. - * @param type The type of rendering context installed. - * @return Indication as to whether installation has succeeded. + * \param type The type of rendering context installed. + * \return Indication as to whether installation has succeeded. */ virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type); /** * Removes the current drawing context. - * @return Indication as to whether removal has succeeded. + * \return Indication as to whether removal has succeeded. */ virtual GHOST_TSuccess removeDrawingContext(); /** * Invalidates the contents of this window. - * @return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess invalidate(); diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 294766cba24..31589003131 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -213,7 +213,7 @@ extern "C" { switch (m_draggedObjectType) { case GHOST_kDragnDropTypeBitmap: - if([NSImage canInitWithPasteboard:draggingPBoard]) { + if ([NSImage canInitWithPasteboard:draggingPBoard]) { droppedImg = [[NSImage alloc]initWithPasteboard:draggingPBoard]; data = droppedImg; //[draggingPBoard dataForType:NSTIFFPboardType]; } @@ -244,8 +244,8 @@ extern "C" { GHOST_SystemCocoa *systemCocoa; GHOST_WindowCocoa *associatedWindow; - bool composing; - NSString *composing_text; + bool composing; + NSString *composing_text; } - (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa; @end @@ -256,34 +256,35 @@ extern "C" { systemCocoa = sysCocoa; associatedWindow = winCocoa; - composing = false; - composing_text = nil; + composing = false; + composing_text = nil; } - (BOOL)acceptsFirstResponder { - return YES; + return YES; } // The trick to prevent Cocoa from complaining (beeping) - (void)keyDown:(NSEvent *)event { - // Start or continue composing? - if([[event characters] length] == 0 || - [[event charactersIgnoringModifiers] length] == 0 || - composing) { - composing = YES; - - // interpret event to call insertText - NSMutableArray *events; - events = [[NSMutableArray alloc] initWithCapacity:1]; - [events addObject:event]; - [self interpretKeyEvents:events]; // calls insertText - [events removeObject:event]; - [events release]; + /* Start or continue composing? */ + if ([[event characters] length] == 0 || + [[event charactersIgnoringModifiers] length] == 0 || + composing) + { + composing = YES; - return; - } + // interpret event to call insertText + NSMutableArray *events; + events = [[NSMutableArray alloc] initWithCapacity:1]; + [events addObject:event]; + [self interpretKeyEvents:events]; // calls insertText + [events removeObject:event]; + [events release]; + + return; + } } #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 @@ -314,62 +315,60 @@ extern "C" { - (BOOL)isOpaque { - return YES; + return YES; } - (void) drawRect:(NSRect)rect { - if ([self inLiveResize]) - { - //Don't redraw while in live resize - } - else - { - [super drawRect:rect]; - systemCocoa->handleWindowEvent(GHOST_kEventWindowUpdate, associatedWindow); - } + if ([self inLiveResize]) { + /* Don't redraw while in live resize */ + } + else { + [super drawRect:rect]; + systemCocoa->handleWindowEvent(GHOST_kEventWindowUpdate, associatedWindow); + } } // Text input - (void)composing_free { - composing = NO; + composing = NO; - if(composing_text) { - [composing_text release]; - composing_text = nil; - } + if (composing_text) { + [composing_text release]; + composing_text = nil; + } } - (void)insertText:(id)chars { - [self composing_free]; + [self composing_free]; } - (void)setMarkedText:(id)chars selectedRange:(NSRange)range { - [self composing_free]; - if([chars length] == 0) - return; - - // start composing - composing = YES; - composing_text = [chars copy]; + [self composing_free]; + if ([chars length] == 0) + return; - // if empty, cancel - if([composing_text length] == 0) - [self composing_free]; + // start composing + composing = YES; + composing_text = [chars copy]; + + // if empty, cancel + if ([composing_text length] == 0) + [self composing_free]; } - (void)unmarkText { - [self composing_free]; + [self composing_free]; } - (BOOL)hasMarkedText { - return (composing)? YES: NO; + return (composing)? YES: NO; } - (void)doCommandBySelector:(SEL)selector @@ -378,48 +377,48 @@ extern "C" { - (BOOL)isComposing { - return composing; + return composing; } - (NSInteger)conversationIdentifier { - return (NSInteger)self; + return (NSInteger)self; } - (NSAttributedString *)attributedSubstringFromRange:(NSRange)range { - return [NSAttributedString new]; // XXX does this leak? + return [NSAttributedString new]; // XXX does this leak? } - (NSRange)markedRange { - unsigned int length = (composing_text)? [composing_text length]: 0; + unsigned int length = (composing_text)? [composing_text length]: 0; - if(composing) - return NSMakeRange(0, length); + if (composing) + return NSMakeRange(0, length); - return NSMakeRange(NSNotFound, 0); + return NSMakeRange(NSNotFound, 0); } - (NSRange)selectedRange { - unsigned int length = (composing_text)? [composing_text length]: 0; - return NSMakeRange(0, length); + unsigned int length = (composing_text)? [composing_text length]: 0; + return NSMakeRange(0, length); } - (NSRect)firstRectForCharacterRange:(NSRange)range { - return NSZeroRect; + return NSZeroRect; } - (NSUInteger)characterIndexForPoint:(NSPoint)point { - return NSNotFound; + return NSNotFound; } - (NSArray*)validAttributesForMarkedText { - return [NSArray array]; // XXX does this leak? + return [NSArray array]; // XXX does this leak? } @end @@ -487,7 +486,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( pixelFormatAttrsWindow[i++] = NSOpenGLPFABackingStore; // Force software OpenGL, for debugging - if(getenv("BLENDER_SOFTWAREGL")) { + if (getenv("BLENDER_SOFTWAREGL")) { pixelFormatAttrsWindow[i++] = NSOpenGLPFARendererID; pixelFormatAttrsWindow[i++] = kCGLRendererGenericID; } @@ -530,7 +529,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( pixelFormatAttrsWindow[i++] = NSOpenGLPFABackingStore; // Force software OpenGL, for debugging - if(getenv("BLENDER_SOFTWAREGL")) { + if (getenv("BLENDER_SOFTWAREGL")) { pixelFormatAttrsWindow[i++] = NSOpenGLPFARendererID; pixelFormatAttrsWindow[i++] = kCGLRendererGenericID; } @@ -600,7 +599,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( GHOST_WindowCocoa::~GHOST_WindowCocoa() { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; if (m_customCursor) { [m_customCursor release]; @@ -638,14 +637,13 @@ void* GHOST_WindowCocoa::getOSWindow() const void GHOST_WindowCocoa::setTitle(const STR_String& title) { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid") NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *windowTitle = [[NSString alloc] initWithCString:title encoding:NSUTF8StringEncoding]; //Set associated file if applicable - if (windowTitle && [windowTitle hasPrefix:@"Blender"]) - { + if (windowTitle && [windowTitle hasPrefix:@"Blender"]) { NSRange fileStrRange; NSString *associatedFileName; int len; @@ -653,8 +651,7 @@ void GHOST_WindowCocoa::setTitle(const STR_String& title) fileStrRange.location = [windowTitle rangeOfString:@"["].location+1; len = [windowTitle rangeOfString:@"]"].location - fileStrRange.location; - if (len > 0) - { + if (len > 0) { fileStrRange.length = len; associatedFileName = [windowTitle substringWithRange:fileStrRange]; [m_window setTitle:[associatedFileName lastPathComponent]]; @@ -686,14 +683,14 @@ void GHOST_WindowCocoa::setTitle(const STR_String& title) void GHOST_WindowCocoa::getTitle(STR_String& title) const { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid") NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *windowTitle = [m_window title]; if (windowTitle != nil) { - title = [windowTitle UTF8String]; + title = [windowTitle UTF8String]; } [pool drain]; @@ -727,8 +724,7 @@ void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - if (!m_fullScreen) - { + if (!m_fullScreen) { NSRect screenSize = [[m_window screen] visibleFrame]; //Max window contents as screen size (excluding title bar...) @@ -794,8 +790,9 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); - if ((((GHOST_TUns32)cBnds.getWidth()) != width) || - (((GHOST_TUns32)cBnds.getHeight()) != height)) { + if ((((GHOST_TUns32)cBnds.getWidth()) != width) || + (((GHOST_TUns32)cBnds.getHeight()) != height)) + { NSSize size; size.width=width; size.height=height; @@ -889,35 +886,36 @@ NSScreen* GHOST_WindowCocoa::getScreen() /** - * @note Fullscreen switch is not actual fullscreen with display capture. As this capture removes all OS X window manager features. + * \note Fullscreen switch is not actual fullscreen with display capture. + * As this capture removes all OS X window manager features. + * * Instead, the menu bar and the dock are hidden, and the window is made borderless and enlarged. * Thus, process switch, exposé, spaces, ... still work in fullscreen mode */ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setState(): window invalid") - switch (state) { + switch (state) { case GHOST_kWindowStateMinimized: - [m_window miniaturize:nil]; - break; + [m_window miniaturize:nil]; + break; case GHOST_kWindowStateMaximized: [m_window zoom:nil]; break; case GHOST_kWindowStateFullScreen: - if (!m_fullScreen) - { + if (!m_fullScreen) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - //This status change needs to be done before Cocoa call to enter fullscreen mode - //to give window delegate hint not to forward its deactivation to ghost wm that doesn't know view/window difference + /* This status change needs to be done before Cocoa call to enter fullscreen mode + * to give window delegate hint not to forward its deactivation to ghost wm that + * doesn't know view/window difference. */ m_fullScreen = true; #ifdef MAC_OS_X_VERSION_10_6 //10.6 provides Cocoa functions to autoshow menu bar, and to change a window style //Hide menu & dock if needed - if ([[m_window screen] isEqual:[[NSScreen screens] objectAtIndex:0]]) - { + if ([[m_window screen] isEqual:[[NSScreen screens] objectAtIndex:0]]) { [NSApp setPresentationOptions:(NSApplicationPresentationHideDock | NSApplicationPresentationAutoHideMenuBar)]; } //Make window borderless and enlarge it @@ -927,8 +925,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) #else //With 10.5, we need to create a new window to change its style to borderless //Hide menu & dock if needed - if ([[m_window screen] isEqual:[[NSScreen screens] objectAtIndex:0]]) - { + if ([[m_window screen] isEqual:[[NSScreen screens] objectAtIndex:0]]) { //Cocoa function in 10.5 does not allow to set the menu bar in auto-show mode [NSMenu setMenuBarVisible:NO]; //One of the very few 64bit compatible Carbon function SetSystemUIMode(kUIModeAllHidden,kUIOptionAutoShowMenuBar); @@ -947,7 +944,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) [tmpWindow setDelegate:[m_window delegate]]; [tmpWindow setSystemAndWindowCocoa:[m_window systemCocoa] windowCocoa:this]; [tmpWindow registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, - NSStringPboardType, NSTIFFPboardType, nil]]; + NSStringPboardType, NSTIFFPboardType, nil]]; //Assign the openGL view to the new window [tmpWindow setContentView:m_openGLView]; @@ -968,17 +965,15 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) } break; case GHOST_kWindowStateNormal: - default: + default: NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - if (m_fullScreen) - { + if (m_fullScreen) { m_fullScreen = false; //Exit fullscreen #ifdef MAC_OS_X_VERSION_10_6 //Show again menu & dock if needed - if ([[m_window screen] isEqual:[NSScreen mainScreen]]) - { + if ([[m_window screen] isEqual:[NSScreen mainScreen]]) { [NSApp setPresentationOptions:NSApplicationPresentationDefault]; } //Make window normal and resize it @@ -989,8 +984,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) #else //With 10.5, we need to create a new window to change its style to borderless //Show menu & dock if needed - if ([[m_window screen] isEqual:[NSScreen mainScreen]]) - { + if ([[m_window screen] isEqual:[NSScreen mainScreen]]) { //Cocoa function in 10.5 does not allow to set the menu bar in auto-show mode [NSMenu setMenuBarVisible:YES]; SetSystemUIMode(kUIModeNormal, 0); //One of the very few 64bit compatible Carbon function } @@ -1027,15 +1021,15 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) //Tell WM of view new size m_systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, this); } - else if ([m_window isMiniaturized]) + else if ([m_window isMiniaturized]) [m_window deminiaturize:nil]; else if ([m_window isZoomed]) [m_window zoom:nil]; [pool drain]; - break; - } + break; + } - return GHOST_kSuccess; + return GHOST_kSuccess; } GHOST_TSuccess GHOST_WindowCocoa::setModifiedState(bool isUnsavedChanges) @@ -1055,10 +1049,10 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order) NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setOrder(): window invalid") - if (order == GHOST_kWindowOrderTop) { + if (order == GHOST_kWindowOrderTop) { [m_window makeKeyAndOrderFront:nil]; - } - else { + } + else { NSArray *windowsList; [m_window orderBack:nil]; @@ -1068,10 +1062,10 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order) if ([windowsList count]) { [[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil]; } - } + } [pool drain]; - return GHOST_kSuccess; + return GHOST_kSuccess; } #pragma mark Drawing context @@ -1080,15 +1074,15 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order) GHOST_TSuccess GHOST_WindowCocoa::swapBuffers() { - if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { - if (m_openGLContext != nil) { + if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { + if (m_openGLContext != nil) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [m_openGLContext flushBuffer]; [pool drain]; - return GHOST_kSuccess; - } - } - return GHOST_kFailure; + return GHOST_kSuccess; + } + } + return GHOST_kFailure; } GHOST_TSuccess GHOST_WindowCocoa::updateDrawingContext() @@ -1184,8 +1178,7 @@ GHOST_TSuccess GHOST_WindowCocoa::removeDrawingContext() NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; switch (m_drawingContextType) { case GHOST_kDrawingContextTypeOpenGL: - if (m_openGLContext) - { + if (m_openGLContext) { [m_openGLView clearGLContext]; if (s_firstOpenGLcontext == m_openGLContext) s_firstOpenGLcontext = nil; m_openGLContext = nil; @@ -1222,24 +1215,24 @@ GHOST_TSuccess GHOST_WindowCocoa::setProgressBar(float progress) NSImage* dockIcon = [[NSImage alloc] initWithSize:NSMakeSize(128,128)]; [dockIcon lockFocus]; - NSRect progressBox = {{4, 4}, {120, 16}}; + NSRect progressBox = {{4, 4}, {120, 16}}; - [[NSImage imageNamed:@"NSApplicationIcon"] dissolveToPoint:NSZeroPoint fraction:1.0]; - - // Track & Outline - [[NSColor blackColor] setFill]; - NSRectFill(progressBox); - - [[NSColor whiteColor] set]; - NSFrameRect(progressBox); - - // Progress fill - progressBox = NSInsetRect(progressBox, 1, 1); - - progressBox.size.width = progressBox.size.width * progress; - NSGradient *gradient = [[NSGradient alloc] initWithStartingColor:[NSColor darkGrayColor] endingColor:[NSColor lightGrayColor]]; - [gradient drawInRect:progressBox angle:90]; - [gradient release]; + [[NSImage imageNamed:@"NSApplicationIcon"] dissolveToPoint:NSZeroPoint fraction:1.0]; + + // Track & Outline + [[NSColor blackColor] setFill]; + NSRectFill(progressBox); + + [[NSColor whiteColor] set]; + NSFrameRect(progressBox); + + // Progress fill + progressBox = NSInsetRect(progressBox, 1, 1); + + progressBox.size.width = progressBox.size.width * progress; + NSGradient *gradient = [[NSGradient alloc] initWithStartingColor:[NSColor darkGrayColor] endingColor:[NSColor lightGrayColor]]; + [gradient drawInRect:progressBox angle:90]; + [gradient release]; [dockIcon unlockFocus]; @@ -1364,10 +1357,9 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode { GHOST_TSuccess err = GHOST_kSuccess; - if (mode != GHOST_kGrabDisable) - { + if (mode != GHOST_kGrabDisable) { //No need to perform grab without warp as it is always on in OS X - if(mode != GHOST_kGrabNormal) { + if (mode != GHOST_kGrabNormal) { GHOST_TInt32 x_old,y_old; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -1376,7 +1368,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode //Warp position is stored in client (window base) coordinates setCursorGrabAccum(0, 0); - if(mode == GHOST_kGrabHide) { + if (mode == GHOST_kGrabHide) { setWindowCursorVisibility(false); } @@ -1390,8 +1382,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode } } else { - if(m_cursorGrab==GHOST_kGrabHide) - { + if (m_cursorGrab==GHOST_kGrabHide) { //No need to set again cursor position, as it has not changed for Cocoa setWindowCursorVisibility(true); } diff --git a/intern/ghost/intern/GHOST_WindowManager.cpp b/intern/ghost/intern/GHOST_WindowManager.cpp index 2b7fb6686f2..1816c57a150 100644 --- a/intern/ghost/intern/GHOST_WindowManager.cpp +++ b/intern/ghost/intern/GHOST_WindowManager.cpp @@ -32,8 +32,8 @@ /** * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date May 11, 2001 + * \author Maarten Gribnau + * \date May 11, 2001 */ #include "GHOST_WindowManager.h" diff --git a/intern/ghost/intern/GHOST_WindowManager.h b/intern/ghost/intern/GHOST_WindowManager.h index e754595e881..ecf0cb30860 100644 --- a/intern/ghost/intern/GHOST_WindowManager.h +++ b/intern/ghost/intern/GHOST_WindowManager.h @@ -41,8 +41,8 @@ /** * Manages system windows (platform independent implementation). - * @author Maarten Gribnau - * @date May 11, 2001 + * \author Maarten Gribnau + * \date May 11, 2001 */ class GHOST_WindowManager { @@ -60,68 +60,68 @@ public: /** * Add a window to our list. * It is only added if it is not already in the list. - * @param window Pointer to the window to be added. - * @return Indication of success. + * \param window Pointer to the window to be added. + * \return Indication of success. */ virtual GHOST_TSuccess addWindow(GHOST_IWindow *window); /** * Remove a window from our list. - * @param window Pointer to the window to be removed. - * @return Indication of success. + * \param window Pointer to the window to be removed. + * \return Indication of success. */ virtual GHOST_TSuccess removeWindow(const GHOST_IWindow *window); /** * Returns whether the window is in our list. - * @param window Pointer to the window to query. - * @return A boolean indicator. + * \param window Pointer to the window to query. + * \return A boolean indicator. */ virtual bool getWindowFound(const GHOST_IWindow *window) const; /** * Returns whether one of the windows is fullscreen. - * @return A boolean indicator. + * \return A boolean indicator. */ virtual bool getFullScreen(void) const; /** * Returns pointer to the full-screen window. - * @return The fll-screen window (0 if not in full-screen). + * \return The fll-screen window (0 if not in full-screen). */ virtual GHOST_IWindow *getFullScreenWindow(void) const; /** * Activates fullscreen mode for a window. - * @param window The window displayed fullscreen. - * @return Indication of success. + * \param window The window displayed fullscreen. + * \return Indication of success. */ virtual GHOST_TSuccess beginFullScreen(GHOST_IWindow *window, const bool stereoVisual); /** * Closes fullscreen mode down. - * @return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess endFullScreen(void); /** * Sets new window as active window (the window receiving events). * There can be only one window active which should be in the current window list. - * @param window The new active window. + * \param window The new active window. */ virtual GHOST_TSuccess setActiveWindow(GHOST_IWindow *window); /** * Returns the active window (the window receiving events). * There can be only one window active which should be in the current window list. - * @return window The active window (or NULL if there is none). + * \return window The active window (or NULL if there is none). */ virtual GHOST_IWindow *getActiveWindow(void) const; /** * Set this window to be inactive (not receiving events). - * @param window The window to decativate. + * \param window The window to decativate. */ virtual void setWindowInactive(const GHOST_IWindow *window); @@ -129,7 +129,7 @@ public: /** * Return a vector of the windows currently managed by this * class. - * @warning It is very dangerous to mess with the contents of + * \warning It is very dangerous to mess with the contents of * this vector. Please do not destroy or add windows use the * interface above for this, */ @@ -137,14 +137,14 @@ public: /** * Finds the window associated with an OS window object/handle - * @param osWindow The OS window object/handle - * @return The associated window, null if none corresponds + * \param osWindow The OS window object/handle + * \return The associated window, null if none corresponds */ virtual GHOST_IWindow *getWindowAssociatedWithOSWindow(void *osWindow); /** * Return true if any windows has a modified status - * @return True if any window has unsaved changes + * \return True if any window has unsaved changes */ bool getAnyModifiedState(); diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 71a9db349ee..0e8ff438998 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -32,8 +32,8 @@ /** * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date May 10, 2001 + * \author Maarten Gribnau + * \date May 10, 2001 */ #include diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index cf5a7fe808d..3f52f9e22b0 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -61,8 +61,8 @@ typedef BOOL (API * GHOST_WIN32_WTPacket)(HCTX, UINT, LPVOID); /** * GHOST window on M$ Windows OSs. - * @author Maarten Gribnau - * @date May 10, 2001 + * \author Maarten Gribnau + * \date May 10, 2001 */ class GHOST_WindowWin32 : public GHOST_Window { public: @@ -70,15 +70,15 @@ public: * Constructor. * Creates a new window and opens it. * To check if the window was created properly, use the getValid() method. - * @param title The text shown in the title bar of the window. - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state the window is initially opened with. - * @param type The type of drawing context installed in this window. - * @param stereoVisual Stereo visual for quad buffered stereo. - * @param numOfAASamples Number of samples used for AA (zero if no AA) + * \param title The text shown in the title bar of the window. + * \param left The coordinate of the left edge of the window. + * \param top The coordinate of the top edge of the window. + * \param width The width the window. + * \param height The height the window. + * \param state The state the window is initially opened with. + * \param type The type of drawing context installed in this window. + * \param stereoVisual Stereo visual for quad buffered stereo. + * \param numOfAASamples Number of samples used for AA (zero if no AA) */ GHOST_WindowWin32( GHOST_SystemWin32 *system, @@ -104,115 +104,115 @@ public: /** * Returns the window to replace this one if it's getting replaced - * @return The window replacing this one. + * \return The window replacing this one. */ GHOST_Window *getNextWindow(); /** * Returns indication as to whether the window is valid. - * @return The validity of the window. + * \return The validity of the window. */ virtual bool getValid() const; /** * Access to the handle of the window. - * @return The handle of the window. + * \return The handle of the window. */ virtual HWND getHWND() const; /** * Sets the title displayed in the title bar. - * @param title The title to display in the title bar. + * \param title The title to display in the title bar. */ virtual void setTitle(const STR_String& title); /** * Returns the title displayed in the title bar. - * @param title The title displayed in the title bar. + * \param title The title displayed in the title bar. */ virtual void getTitle(STR_String& title) const; /** * Returns the window rectangle dimensions. * The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen. - * @param bounds The bounding rectangle of the window. + * \param bounds The bounding rectangle of the window. */ virtual void getWindowBounds(GHOST_Rect& bounds) const; /** * Returns the client rectangle dimensions. * The left and top members of the rectangle are always zero. - * @param bounds The bounding rectangle of the cleient area of the window. + * \param bounds The bounding rectangle of the cleient area of the window. */ virtual void getClientBounds(GHOST_Rect& bounds) const; /** * Resizes client rectangle width. - * @param width The new width of the client area of the window. + * \param width The new width of the client area of the window. */ virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width); /** * Resizes client rectangle height. - * @param height The new height of the client area of the window. + * \param height The new height of the client area of the window. */ virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height); /** * Resizes client rectangle. - * @param width The new width of the client area of the window. - * @param height The new height of the client area of the window. + * \param width The new width of the client area of the window. + * \param height The new height of the client area of the window. */ virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height); /** * Returns the state of the window (normal, minimized, maximized). - * @return The state of the window. + * \return The state of the window. */ virtual GHOST_TWindowState getState() const; /** * Converts a point in screen coordinates to client rectangle coordinates - * @param inX The x-coordinate on the screen. - * @param inY The y-coordinate on the screen. - * @param outX The x-coordinate in the client rectangle. - * @param outY The y-coordinate in the client rectangle. + * \param inX The x-coordinate on the screen. + * \param inY The y-coordinate on the screen. + * \param outX The x-coordinate in the client rectangle. + * \param outY The y-coordinate in the client rectangle. */ virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; /** * Converts a point in screen coordinates to client rectangle coordinates - * @param inX The x-coordinate in the client rectangle. - * @param inY The y-coordinate in the client rectangle. - * @param outX The x-coordinate on the screen. - * @param outY The y-coordinate on the screen. + * \param inX The x-coordinate in the client rectangle. + * \param inY The y-coordinate in the client rectangle. + * \param outX The x-coordinate on the screen. + * \param outY The y-coordinate on the screen. */ virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; /** * Sets the state of the window (normal, minimized, maximized). - * @param state The state of the window. - * @return Indication of success. + * \param state The state of the window. + * \return Indication of success. */ virtual GHOST_TSuccess setState(GHOST_TWindowState state); /** * Sets the order of the window (bottom, top). - * @param order The order of the window. - * @return Indication of success. + * \param order The order of the window. + * \return Indication of success. */ virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order); /** * Swaps front and back buffers of a window. - * @return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess swapBuffers(); /** * Activates the drawing context of this window. - * @return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess activateDrawingContext(); @@ -223,7 +223,7 @@ public: /** * Sets the progress bar value displayed in the window/application icon - * @param progress The progress % + * \param progress The progress % */ virtual GHOST_TSuccess setProgressBar(float progress); @@ -234,7 +234,7 @@ public: /** * Returns the name of the window class. - * @return The name of the window class. + * \return The name of the window class. */ static wchar_t *getWindowClassName() { return s_windowClassName; @@ -245,7 +245,7 @@ public: * for any real button press, controls mouse * capturing). * - * @param press + * \param press * 0 - mouse pressed * 1 - mouse released * 2 - operator grab @@ -261,8 +261,8 @@ public: /** * Loads the windows equivalent of a standard GHOST cursor. - * @param visible Flag for cursor visibility. - * @param cursorShape The cursor shape. + * \param visible Flag for cursor visibility. + * \param cursorShape The cursor shape. */ void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const; @@ -279,14 +279,14 @@ protected: /** * Tries to install a rendering context in this window. - * @param type The type of rendering context installed. - * @return Indication of success. + * \param type The type of rendering context installed. + * \return Indication of success. */ virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type); /** * Removes the current drawing context. - * @return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess removeDrawingContext(); @@ -299,7 +299,7 @@ protected: /** * Sets the cursor grab on the window using native window system calls. * Using registerMouseClickEvent. - * @param mode GHOST_TGrabCursorMode. + * \param mode GHOST_TGrabCursorMode. */ virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode); diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 17efecb4a82..4ad95fcab53 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -1376,8 +1376,8 @@ GHOST_WindowX11:: /** * Tries to install a rendering context in this window. - * @param type The type of rendering context installed. - * @return Indication as to whether installation has succeeded. + * \param type The type of rendering context installed. + * \return Indication as to whether installation has succeeded. */ GHOST_TSuccess GHOST_WindowX11:: @@ -1418,7 +1418,7 @@ installDrawingContext( /** * Removes the current drawing context. - * @return Indication as to whether removal has succeeded. + * \return Indication as to whether removal has succeeded. */ GHOST_TSuccess GHOST_WindowX11:: diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index 753d8960a18..5b2ffced29c 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -53,8 +53,8 @@ class GHOST_DropTargetX11; /** * X11 implementation of GHOST_IWindow. * Dimensions are given in screen coordinates that are relative to the upper-left corner of the screen. - * @author Laurence Bourn - * @date October 26, 2001 + * \author Laurence Bourn + * \date October 26, 2001 */ class GHOST_WindowX11 : public GHOST_Window @@ -64,16 +64,16 @@ public: * Constructor. * Creates a new window and opens it. * To check if the window was created properly, use the getValid() method. - * @param title The text shown in the title bar of the window. - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state the window is initially opened with. - * @param parentWindow Parent (embedder) window - * @param type The type of drawing context installed in this window. - * @param stereoVisual Stereo visual for quad buffered stereo. - * @param numOfAASamples Number of samples used for AA (zero if no AA) + * \param title The text shown in the title bar of the window. + * \param left The coordinate of the left edge of the window. + * \param top The coordinate of the top edge of the window. + * \param width The width the window. + * \param height The height the window. + * \param state The state the window is initially opened with. + * \param parentWindow Parent (embedder) window + * \param type The type of drawing context installed in this window. + * \param stereoVisual Stereo visual for quad buffered stereo. + * \param numOfAASamples Number of samples used for AA (zero if no AA) */ GHOST_WindowX11( GHOST_SystemX11 *system, @@ -176,7 +176,7 @@ public: ~GHOST_WindowX11(); /** - * @section x11specific X11 system specific calls + * \section x11specific X11 system specific calls */ /** @@ -256,8 +256,8 @@ public: protected: /** * Tries to install a rendering context in this window. - * @param type The type of rendering context installed. - * @return Indication as to whether installation has succeeded. + * \param type The type of rendering context installed. + * \return Indication as to whether installation has succeeded. */ GHOST_TSuccess installDrawingContext( @@ -266,7 +266,7 @@ protected: /** * Removes the current drawing context. - * @return Indication as to whether removal has succeeded. + * \return Indication as to whether removal has succeeded. */ GHOST_TSuccess removeDrawingContext( @@ -284,7 +284,7 @@ protected: /** * Sets the cursor grab on the window using * native window system calls. - * @param warp Only used when grab is enabled, hides the mouse and allows gragging outside the screen. + * \param warp Only used when grab is enabled, hides the mouse and allows gragging outside the screen. */ GHOST_TSuccess setWindowCursorGrab( diff --git a/intern/ghost/test/gears/GHOST_C-Test.c b/intern/ghost/test/gears/GHOST_C-Test.c index 98e2b9c2497..00ae4bb25b4 100644 --- a/intern/ghost/test/gears/GHOST_C-Test.c +++ b/intern/ghost/test/gears/GHOST_C-Test.c @@ -31,8 +31,8 @@ * Simple test file for the GHOST library. * The OpenGL gear code is taken from the Qt sample code which, * in turn, is probably taken from somewhere as well. - * @author Maarten Gribnau - * @date May 31, 2001 + * \author Maarten Gribnau + * \date May 31, 2001 */ #include diff --git a/intern/ghost/test/gears/GHOST_Test.cpp b/intern/ghost/test/gears/GHOST_Test.cpp index c02272094f4..1e641a8643c 100644 --- a/intern/ghost/test/gears/GHOST_Test.cpp +++ b/intern/ghost/test/gears/GHOST_Test.cpp @@ -30,8 +30,8 @@ * Simple test file for the GHOST library. * The OpenGL gear code is taken from the Qt sample code which, * in turn, is probably taken from somewhere as well. - * @author Maarten Gribnau - * @date May 31, 2001 + * \author Maarten Gribnau + * \date May 31, 2001 * Stereo code by Raymond de Vries, januari 2002 */ diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c index b37180d499c..55a65f07759 100644 --- a/source/blender/blenfont/intern/blf_lang.c +++ b/source/blender/blenfont/intern/blf_lang.c @@ -82,7 +82,7 @@ static const char *locales[] = { "spanish", "es", "catalan", "ca_AD", "czech", "cs_CZ", - "portuguese", "pt", + "portuguese", "pt_PT", #if defined(_WIN32) && !defined(FREE_WINDOWS) "Chinese (Simplified)_China.1252", "zh_CN", "Chinese (Traditional)_China.1252", "zh_TW", @@ -107,6 +107,7 @@ static const char *locales[] = { "kyrgyz", "ky_KG", "turkish", "tr_TR", "hungarian", "hu_HU", + "brazilian portuguese", "pt_BR", }; void BLF_lang_init(void) diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 8d486218d21..19dd67b88f8 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -124,8 +124,6 @@ void CustomData_free_temporary(struct CustomData *data, int totelem); /* adds a data layer of the given type to the CustomData object, optionally * backed by an external data array. the different allocation types are * defined above. returns the data of the layer. - * - * in editmode, use EDBM_data_layer_add instead of this function */ void *CustomData_add_layer(struct CustomData *data, int type, int alloctype, void *layer, int totelem); diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 9cf5a7f31a5..48615e638e8 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -127,7 +127,6 @@ void BKE_mask_get_handle_point_adjacent(struct MaskSpline *spline, struct MaskSp void BKE_mask_layer_calc_handles(struct MaskLayer *masklay); void BKE_mask_layer_calc_handles_deform(struct MaskLayer *masklay); void BKE_mask_calc_handles(struct Mask *mask); -void BKE_mask_calc_handles_deform(struct Mask *mask); void BKE_mask_spline_ensure_deform(struct MaskSpline *spline); /* animation */ @@ -153,8 +152,6 @@ int BKE_mask_layer_shape_spline_from_index(struct MaskLayer *masklay, int index, struct MaskSpline **r_masklay_shape, int *r_index); int BKE_mask_layer_shape_spline_to_index(struct MaskLayer *masklay, struct MaskSpline *spline); -int BKE_mask_layer_shape_spline_index(struct MaskLayer *masklay, int index, - struct MaskSpline **r_masklay_shape, int *r_index); void BKE_mask_layer_shape_changed_add(struct MaskLayer *masklay, int index, int do_init, int do_init_interpolate); diff --git a/source/blender/blenkernel/BKE_object_deform.h b/source/blender/blenkernel/BKE_object_deform.h index 35a4e19a5bc..ecc521a77fb 100644 --- a/source/blender/blenkernel/BKE_object_deform.h +++ b/source/blender/blenkernel/BKE_object_deform.h @@ -23,7 +23,7 @@ #ifndef __BKE_OBJECT_DEFORM_H__ #define __BKE_OBJECT_DEFORM_H__ -/** \file BKE_object_vgroup.h +/** \file BKE_object_deform.h * \ingroup bke * \brief Functions for dealing with objects and deform verts, * used by painting and tools. diff --git a/source/blender/blenkernel/BKE_script.h b/source/blender/blenkernel/BKE_script.h index 9976009c4c2..c3789733a04 100644 --- a/source/blender/blenkernel/BKE_script.h +++ b/source/blender/blenkernel/BKE_script.h @@ -40,8 +40,6 @@ extern "C" { struct Script; -void free_script(struct Script *script); - #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h index a7b03cef933..d1332ba937e 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.h +++ b/source/blender/blenkernel/BKE_shrinkwrap.h @@ -52,7 +52,7 @@ struct DerivedMesh *object_get_derived_final(struct Object *ob); * the matrix calculation. * * A SpaceTransform is initialized using: - * space_transform_setup( &data, ob1, ob2 ) + * SPACE_TRANSFORM_SETUP( &data, ob1, ob2 ) * * After that the following calls can be used: * space_transform_apply (&data, co); //converts a coordinate in ob1 coords space to the corresponding ob2 coords @@ -75,7 +75,7 @@ void space_transform_from_matrixs(struct SpaceTransform *data, float local[4][4] void space_transform_apply(const struct SpaceTransform *data, float co[3]); void space_transform_invert(const struct SpaceTransform *data, float co[3]); -#define space_transform_setup(data, local, target) space_transform_from_matrixs(data, (local)->obmat, (target)->obmat) +#define SPACE_TRANSFORM_SETUP(data, local, target) space_transform_from_matrixs(data, (local)->obmat, (target)->obmat) /* Shrinkwrap stuff */ #include "BKE_bvhutils.h" @@ -126,7 +126,7 @@ void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object /* * This function casts a ray in the given BVHTree.. but it takes into consideration the space_transform, that is: * - * if transf was configured with "space_transform_setup( &transf, ob1, ob2 )" + * if transf was configured with "SPACE_TRANSFORM_SETUP( &transf, ob1, ob2 )" * then the input (vert, dir, BVHTreeRayHit) must be defined in ob1 coordinates space * and the BVHTree must be built in ob2 coordinate space. * diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index f099a79b520..f8c1a35776a 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -862,7 +862,7 @@ void BKE_libblock_free(ListBase *lb, void *idv) BKE_text_free((Text *)id); break; case ID_SCRIPT: - //XXX free_script((Script *)id); + /* deprecated */ break; case ID_SPK: BKE_speaker_free((Speaker *)id); diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index a4fec1c0de4..3925c3cc858 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -640,21 +640,6 @@ static float densfunc(MetaElem *ball, float x, float y, float z) case MB_BALL: /* do nothing */ break; - case MB_TUBEX: - if (dvec[0] > ball->len) dvec[0] -= ball->len; - else if (dvec[0] < -ball->len) dvec[0] += ball->len; - else dvec[0] = 0.0; - break; - case MB_TUBEY: - if (dvec[1] > ball->len) dvec[1] -= ball->len; - else if (dvec[1] < -ball->len) dvec[1] += ball->len; - else dvec[1] = 0.0; - break; - case MB_TUBEZ: - if (dvec[2] > ball->len) dvec[2] -= ball->len; - else if (dvec[2] < -ball->len) dvec[2] += ball->len; - else dvec[2] = 0.0; - break; case MB_TUBE: if (dvec[0] > ball->expx) dvec[0] -= ball->expx; else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; @@ -686,6 +671,24 @@ static float densfunc(MetaElem *ball, float x, float y, float z) else if (dvec[2] < -ball->expz) dvec[2] += ball->expz; else dvec[2] = 0.0; break; + + /* *** deprecated, could be removed?, do-versioned at least *** */ + case MB_TUBEX: + if (dvec[0] > ball->len) dvec[0] -= ball->len; + else if (dvec[0] < -ball->len) dvec[0] += ball->len; + else dvec[0] = 0.0; + break; + case MB_TUBEY: + if (dvec[1] > ball->len) dvec[1] -= ball->len; + else if (dvec[1] < -ball->len) dvec[1] += ball->len; + else dvec[1] = 0.0; + break; + case MB_TUBEZ: + if (dvec[2] > ball->len) dvec[2] -= ball->len; + else if (dvec[2] < -ball->len) dvec[2] += ball->len; + else dvec[2] = 0.0; + break; + /* *** end deprecated *** */ } dist2 = 1.0f - (len_v3(dvec) / ball->rad2); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 0ac0db50fb5..611b175c9ef 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -170,7 +170,8 @@ static void seq_free_strip(Strip *strip) MEM_freeN(strip); } -void BKE_sequence_free(Scene *scene, Sequence *seq) +/* only give option to skip cache locally (static func) */ +static void BKE_sequence_free_ex(Scene *scene, Sequence *seq, const int do_cache) { if (seq->strip) seq_free_strip(seq->strip); @@ -206,21 +207,37 @@ void BKE_sequence_free(Scene *scene, Sequence *seq) /* free cached data used by this strip, * also invalidate cache for all dependent sequences + * + * be _very_ careful here, invalidating cache loops over the scene sequences and + * assumes the listbase is valid for all strips, this may not be the case if lists are being freed. + * this is optional BKE_sequence_invalidate_cache */ - BKE_sequence_invalidate_cache(scene, seq); + if (do_cache) { + if (scene) { + BKE_sequence_invalidate_cache(scene, seq); + } + } MEM_freeN(seq); } +void BKE_sequence_free(Scene *scene, Sequence *seq) +{ + BKE_sequence_free_ex(scene, seq, TRUE); +} + +/* cache must be freed before calling this function + * since it leaves the seqbase in an invalid state */ static void seq_free_sequence_recurse(Scene *scene, Sequence *seq) { - Sequence *iseq; + Sequence *iseq, *iseq_next; - for (iseq = seq->seqbase.first; iseq; iseq = iseq->next) { + for (iseq = seq->seqbase.first; iseq; iseq = iseq_next) { + iseq_next = iseq->next; seq_free_sequence_recurse(scene, iseq); } - BKE_sequence_free(scene, seq); + BKE_sequence_free_ex(scene, seq, FALSE); } @@ -241,7 +258,7 @@ static void seq_free_clipboard_recursive(Sequence *seq_parent) seq_free_clipboard_recursive(seq); } - BKE_sequence_free(NULL, seq_parent); + BKE_sequence_free_ex(NULL, seq_parent, FALSE); } void BKE_sequencer_free_clipboard(void) @@ -270,22 +287,22 @@ Editing *BKE_sequencer_editing_ensure(Scene *scene) void BKE_sequencer_editing_free(Scene *scene) { Editing *ed = scene->ed; - MetaStack *ms; Sequence *seq; if (ed == NULL) return; + /* this may not be the active scene!, could be smarter about this */ + BKE_sequencer_cache_cleanup(); + SEQ_BEGIN (ed, seq) { - BKE_sequence_free(scene, seq); + /* handle cache freeing above */ + BKE_sequence_free_ex(scene, seq, FALSE); } SEQ_END - while ((ms = ed->metastack.first)) { - BLI_remlink(&ed->metastack, ms); - MEM_freeN(ms); - } + BLI_freelistN(&ed->metastack); MEM_freeN(ed); diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index f9399946570..9a8bcaabe0c 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -313,7 +313,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) auxMesh = object_get_derived_final(calc->smd->auxTarget); if (!auxMesh) return; - space_transform_setup(&local2aux, calc->ob, calc->smd->auxTarget); + SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->smd->auxTarget); } //After sucessufuly build the trees, start projection vertexs @@ -500,7 +500,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM //TODO there might be several "bugs" on non-uniform scales matrixs //because it will no longer be nearest surface, not sphere projection //because space has been deformed - space_transform_setup(&calc.local2target, ob, smd->target); + SPACE_TRANSFORM_SETUP(&calc.local2target, ob, smd->target); //TODO: smd->keepDist is in global units.. must change to local calc.keepDist = smd->keepDist; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 3526058e12b..cd07ac3b9ed 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -946,6 +946,7 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, } void BKE_ffmpeg_end(void); +static void end_ffmpeg_impl(int is_autosplit); #ifdef WITH_AUDASPACE static void write_audio_frames(double to_pts) @@ -978,7 +979,7 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i if (ffmpeg_autosplit) { if (avio_tell(outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) { - BKE_ffmpeg_end(); + end_ffmpeg_impl(TRUE); ffmpeg_autosplit_count++; success &= start_ffmpeg_impl(rd, rectx, recty, reports); } @@ -991,7 +992,7 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i return success; } -void BKE_ffmpeg_end(void) +static void end_ffmpeg_impl(int is_autosplit) { unsigned int i; @@ -1004,9 +1005,11 @@ void BKE_ffmpeg_end(void) #endif #ifdef WITH_AUDASPACE - if (audio_mixdown_device) { - AUD_closeReadDevice(audio_mixdown_device); - audio_mixdown_device = 0; + if (is_autosplit == FALSE) { + if (audio_mixdown_device) { + AUD_closeReadDevice(audio_mixdown_device); + audio_mixdown_device = 0; + } } #endif @@ -1069,6 +1072,11 @@ void BKE_ffmpeg_end(void) } } +void BKE_ffmpeg_end(void) +{ + end_ffmpeg_impl(FALSE); +} + /* properties */ void BKE_ffmpeg_property_del(RenderData *rd, void *type, void *prop_) diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index eef8c9daaef..6c81ca3f0a9 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -81,6 +81,7 @@ MINLINE void copy_v4db_v4fl(double r[4], const float a[4]); /********************************* Arithmetic ********************************/ +MINLINE void add_v2_fl(float r[2], float f); MINLINE void add_v3_fl(float r[3], float f); MINLINE void add_v4_fl(float r[4], float f); MINLINE void add_v2_v2(float r[2], const float a[2]); diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 4bd21139545..5e47adf25ef 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -97,7 +97,6 @@ typedef enum bli_rebase_state { } bli_rebase_state; int BLI_rebase_path(char *abs, size_t abs_len, char *rel, size_t rel_len, const char *base_dir, const char *src_dir, const char *dest_dir); -#define BKE_rebase_path BLI_rebase_path /* remove after a 2012 */ char *BLI_last_slash(const char *string); int BLI_add_slash(char *string); diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index 177c099d647..0a8f57214d7 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -231,6 +231,13 @@ MINLINE void swap_v4_v4(float a[4], float b[4]) /********************************* Arithmetic ********************************/ +MINLINE void add_v2_fl(float r[2], float f) +{ + r[0] += f; + r[1] += f; +} + + MINLINE void add_v3_fl(float r[3], float f) { r[0] += f; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 4dc1ad1e5c9..65d29c1144b 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5763,7 +5763,6 @@ static void direct_link_screen(FileData *fd, bScreen *sc) ScrArea *sa; ScrVert *sv; ScrEdge *se; - int a; link_list(fd, &(sc->vertbase)); link_list(fd, &(sc->edgebase)); @@ -5773,16 +5772,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc) sc->mainwin = sc->subwinactive= 0; /* indices */ sc->swap = 0; - - /* hacky patch... but people have been saving files with the verse-blender, - * causing the handler to keep running for ever, with no means to disable it */ - for (a = 0; a < SCREEN_MAXHANDLER; a+=2) { - if (sc->handler[a] == SCREEN_HANDLER_VERSE) { - sc->handler[a] = 0; - break; - } - } - + /* edges */ for (se = sc->edgebase.first; se; se = se->next) { se->v1 = newdataadr(fd, se->v1); diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h index ac002070484..955b1a729c5 100644 --- a/source/blender/bmesh/bmesh.h +++ b/source/blender/bmesh/bmesh.h @@ -196,6 +196,11 @@ * * There may be a better place for this section, but adding here for now. * + * \subsection bm_todo_api API + * + * - make crease and bevel weight optional, they come for free in meshes but are allocated layers + * in the bmesh data structure. + * * * \subsection bm_todo_tools Tools * diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 94d94cbec3e..c449dec1b6c 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -1483,6 +1483,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) * and collapses the edge on that vertex. * * \par Examples: + * *
  *     Before:         OE      KE
  *                   ------- -------
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index 1d056dbfae7..eb2b7721bdc 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -285,7 +285,7 @@ void calc_poly_plane(float (*verts)[3], const int nverts)
  * the list that bridges a concave region of the face or intersects
  * any of the faces's edges.
  */
-static void shrink_edgef(float v1[3], float v2[3], const float fac)
+static void scale_edge_v3f(float v1[3], float v2[3], const float fac)
 {
 	float mid[3];
 
@@ -502,7 +502,7 @@ void BM_face_normal_flip(BMesh *bm, BMFace *f)
 
 /* detects if two line segments cross each other (intersects).
  * note, there could be more winding cases then there needs to be. */
-static int linecrossesf(const float v1[2], const float v2[2], const float v3[2], const float v4[2])
+static int line_crosses_v2f(const float v1[2], const float v2[2], const float v3[2], const float v4[2])
 {
 
 #define GETMIN2_AXIS(a, b, ma, mb, axis)   \
@@ -612,7 +612,7 @@ int BM_face_point_inside_test(BMFace *f, const float co[3])
 		v2[0] = (l_iter->v->co[ax] - cent[0]) * onepluseps + cent[0];
 		v2[1] = (l_iter->v->co[ay] - cent[1]) * onepluseps + cent[1];
 		
-		crosses += linecrossesf(v1, v2, co2, out) != 0;
+		crosses += line_crosses_v2f(v1, v2, co2, out) != 0;
 	} while ((l_iter = l_iter->next) != l_first);
 	
 	return crosses % 2 != 0;
@@ -959,7 +959,7 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len)
 	BMIter iter;
 	BMLoop *l;
 	float v1[3], v2[3], v3[3] /*, v4[3 */, no[3], mid[3], *p1, *p2, *p3, *p4;
-	float out[3] = {-234324.0f, -234324.0f, 0.0f};
+	float out[3] = {-FLT_MAX, -FLT_MAX, 0.0f};
 	float (*projverts)[3];
 	float (*edgeverts)[3];
 	float fac1 = 1.0000001f, fac2 = 0.9f; //9999f; //0.999f;
@@ -980,7 +980,7 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len)
 		copy_v3_v3(v1, loops[i][0]->v->co);
 		copy_v3_v3(v2, loops[i][1]->v->co);
 
-		shrink_edgef(v1, v2, fac2);
+		scale_edge_v3f(v1, v2, fac2);
 		
 		copy_v3_v3(edgeverts[a], v1);
 		a++;
@@ -994,14 +994,16 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len)
 
 	for (i = 0, l = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l = l->next) {
 		p1 = projverts[i];
-		out[0] = maxf(out[0], p1[0]) + 0.01f;
-		out[1] = maxf(out[1], p1[1]) + 0.01f;
-		out[2] = 0.0f;
-		p1[2] = 0.0f;
+		out[0] = maxf(out[0], p1[0]);
+		out[1] = maxf(out[1], p1[1]);
+		/* out[2] = 0.0f; */ /* keep at zero */
 
-		//copy_v3_v3(l->v->co, p1);
+		p1[2] = 0.0f;
 	}
 	
+	/* ensure we are well outside the face bounds (value is arbitrary) */
+	add_v2_fl(out, 1.0f);
+
 	for (i = 0; i < len; i++) {
 		edgeverts[i * 2][2] = 0.0f;
 		edgeverts[i * 2 + 1][2] = 0.0f;
@@ -1019,19 +1021,26 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len)
 			p1 = projverts[j];
 			p2 = projverts[(j + 1) % f->len];
 			
+#if 0
 			copy_v3_v3(v1, p1);
 			copy_v3_v3(v2, p2);
 
-			shrink_edgef(v1, v2, fac1);
-
-			if (linecrossesf(p1, p2, mid, out)) clen++;
+			scale_edge_v3f(v1, v2, fac1);
+			if (line_crosses_v2f(v1, v2, mid, out)) {
+				clen++;
+			}
+#else
+			if (line_crosses_v2f(p1, p2, mid, out)) {
+				clen++;
+			}
+#endif
 		}
-		
+
 		if (clen % 2 == 0) {
 			loops[i][0] = NULL;
 		}
 	}
-	
+
 	/* do line crossing test */
 	for (i = 0; i < f->len; i++) {
 		p1 = projverts[i];
@@ -1040,7 +1049,7 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len)
 		copy_v3_v3(v1, p1);
 		copy_v3_v3(v2, p2);
 
-		shrink_edgef(v1, v2, fac1);
+		scale_edge_v3f(v1, v2, fac1);
 
 		for (j = 0; j < len; j++) {
 			if (!loops[j][0]) {
@@ -1050,7 +1059,7 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len)
 			p3 = edgeverts[j * 2];
 			p4 = edgeverts[j * 2 + 1];
 
-			if (linecrossesf(v1, v2, p3, p4)) {
+			if (line_crosses_v2f(v1, v2, p3, p4)) {
 				loops[j][0] = NULL;
 			}
 		}
@@ -1067,9 +1076,9 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len)
 				copy_v3_v3(v1, p1);
 				copy_v3_v3(v2, p2);
 
-				shrink_edgef(v1, v2, fac1);
+				scale_edge_v3f(v1, v2, fac1);
 
-				if (linecrossesf(v1, v2, p3, p4)) {
+				if (line_crosses_v2f(v1, v2, p3, p4)) {
 					loops[i][0] = NULL;
 				}
 			}
diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c
index 6943dcb3e5d..3758ba739d1 100644
--- a/source/blender/bmesh/operators/bmo_connect.c
+++ b/source/blender/bmesh/operators/bmo_connect.c
@@ -45,18 +45,18 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)
 {
 	BMIter iter, liter;
 	BMFace *f, *nf;
-	BMLoop **loops = NULL, *lastl = NULL;
-	BLI_array_declare(loops);
-	BMLoop *l, *nl;
-	BMVert **verts = NULL;
-	BLI_array_declare(verts);
+	BMLoop *(*loops_split)[2] = NULL;
+	BLI_array_declare(loops_split);
+	BMLoop *l, *nl, *lastl = NULL;
+	BMVert *(*verts_pair)[2] = NULL;
+	BLI_array_declare(verts_pair);
 	int i;
 	
 	BMO_slot_buffer_flag_enable(bm, op, "verts", BM_VERT, VERT_INPUT);
 
 	for (f = BM_iter_new(&iter, bm, BM_FACES_OF_MESH, NULL); f; f = BM_iter_step(&iter)) {
-		BLI_array_empty(loops);
-		BLI_array_empty(verts);
+		BLI_array_empty(loops_split);
+		BLI_array_empty(verts_pair);
 		
 		if (BMO_elem_flag_test(bm, f, FACE_NEW)) {
 			continue;
@@ -72,50 +72,44 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)
 				}
 
 				if (lastl != l->prev && lastl != l->next) {
-					BLI_array_grow_one(loops);
-					loops[BLI_array_count(loops) - 1] = lastl;
-
-					BLI_array_grow_one(loops);
-					loops[BLI_array_count(loops) - 1] = l;
+					BLI_array_grow_one(loops_split);
+					loops_split[BLI_array_count(loops_split) - 1][0] = lastl;
+					loops_split[BLI_array_count(loops_split) - 1][1] = l;
 
 				}
 				lastl = l;
 			}
 		}
 
-		if (BLI_array_count(loops) == 0) {
+		if (BLI_array_count(loops_split) == 0) {
 			continue;
 		}
 		
-		if (BLI_array_count(loops) > 2) {
-			BLI_array_grow_one(loops);
-			loops[BLI_array_count(loops) - 1] = loops[BLI_array_count(loops) - 2];
-
-			BLI_array_grow_one(loops);
-			loops[BLI_array_count(loops) - 1] = loops[0];
+		if (BLI_array_count(loops_split) > 1) {
+			BLI_array_grow_one(loops_split);
+			loops_split[BLI_array_count(loops_split) - 1][0] = loops_split[BLI_array_count(loops_split) - 2][1];
+			loops_split[BLI_array_count(loops_split) - 1][1] = loops_split[0][0];
 		}
 
-		BM_face_legal_splits(bm, f, (BMLoop *(*)[2])loops, BLI_array_count(loops) / 2);
+		BM_face_legal_splits(bm, f, loops_split, BLI_array_count(loops_split));
 		
-		for (i = 0; i < BLI_array_count(loops) / 2; i++) {
-			if (loops[i * 2] == NULL) {
+		for (i = 0; i < BLI_array_count(loops_split); i++) {
+			if (loops_split[i][0] == NULL) {
 				continue;
 			}
 
-			BLI_array_grow_one(verts);
-			verts[BLI_array_count(verts) - 1] = loops[i * 2]->v;
-
-			BLI_array_grow_one(verts);
-			verts[BLI_array_count(verts) - 1] = loops[i * 2 + 1]->v;
+			BLI_array_grow_one(verts_pair);
+			verts_pair[BLI_array_count(verts_pair) - 1][0] = loops_split[i][0]->v;
+			verts_pair[BLI_array_count(verts_pair) - 1][1] = loops_split[i][1]->v;
 		}
 
-		for (i = 0; i < BLI_array_count(verts) / 2; i++) {
-			nf = BM_face_split(bm, f, verts[i * 2], verts[i * 2 + 1], &nl, NULL, FALSE);
+		for (i = 0; i < BLI_array_count(verts_pair); i++) {
+			nf = BM_face_split(bm, f, verts_pair[i][0], verts_pair[i][1], &nl, NULL, FALSE);
 			f = nf;
 			
 			if (!nl || !nf) {
 				BMO_error_raise(bm, op, BMERR_CONNECTVERT_FAILED, NULL);
-				BLI_array_free(loops);
+				BLI_array_free(loops_split);
 				return;
 			}
 			BMO_elem_flag_enable(bm, nf, FACE_NEW);
@@ -125,8 +119,8 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)
 
 	BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EDGE_OUT);
 
-	BLI_array_free(loops);
-	BLI_array_free(verts);
+	BLI_array_free(loops_split);
+	BLI_array_free(verts_pair);
 }
 
 static BMVert *get_outer_vert(BMesh *bm, BMEdge *e)
diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c
index 2af764060fb..23526d7498b 100644
--- a/source/blender/bmesh/operators/bmo_subdivide.c
+++ b/source/blender/bmesh/operators/bmo_subdivide.c
@@ -308,7 +308,7 @@ static void quad_1edge_split(BMesh *bm, BMFace *UNUSED(face),
 	}
 }
 
-static SubDPattern quad_1edge = {
+static const SubDPattern quad_1edge = {
 	{1, 0, 0, 0},
 	quad_1edge_split,
 	4,
@@ -337,7 +337,7 @@ static void quad_2edge_split_path(BMesh *bm, BMFace *UNUSED(face), BMVert **vert
 	connect_smallest_face(bm, verts[numcuts * 2 + 3], verts[numcuts * 2 + 1], &nf);
 }
 
-static SubDPattern quad_2edge_path = {
+static const SubDPattern quad_2edge_path = {
 	{1, 1, 0, 0},
 	quad_2edge_split_path,
 	4,
@@ -379,7 +379,7 @@ static void quad_2edge_split_innervert(BMesh *bm, BMFace *UNUSED(face), BMVert *
 	connect_smallest_face(bm, lastv, verts[numcuts * 2 + 2], &nf);
 }
 
-static SubDPattern quad_2edge_innervert = {
+static const SubDPattern quad_2edge_innervert = {
 	{1, 1, 0, 0},
 	quad_2edge_split_innervert,
 	4,
@@ -410,7 +410,7 @@ static void quad_2edge_split_fan(BMesh *bm, BMFace *UNUSED(face), BMVert **verts
 	}
 }
 
-static SubDPattern quad_2edge_fan = {
+static const SubDPattern quad_2edge_fan = {
 	{1, 1, 0, 0},
 	quad_2edge_split_fan,
 	4,
@@ -449,7 +449,7 @@ static void quad_3edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
 	}
 }
 
-static SubDPattern quad_3edge = {
+static const SubDPattern quad_3edge = {
 	{1, 1, 1, 0},
 	quad_3edge_split,
 	4,
@@ -559,7 +559,7 @@ static void tri_1edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
 	}
 }
 
-static SubDPattern tri_1edge = {
+static const SubDPattern tri_1edge = {
 	{1, 0, 0},
 	tri_1edge_split,
 	3,
@@ -660,51 +660,55 @@ cleanup:
 	MEM_freeN(lines);
 }
 
-static SubDPattern tri_3edge = {
+static const SubDPattern tri_3edge = {
 	{1, 1, 1},
 	tri_3edge_subdivide,
 	3,
 };
 
 
-static SubDPattern quad_4edge = {
+static const SubDPattern quad_4edge = {
 	{1, 1, 1, 1},
 	quad_4edge_subdivide,
 	4,
 };
 
-static SubDPattern *patterns[] = {
-	NULL, //quad single edge pattern is inserted here
-	NULL, //quad corner vert pattern is inserted here
-	NULL, //tri single edge pattern is inserted here
+static const SubDPattern *patterns[] = {
+	NULL,  /* quad single edge pattern is inserted here */
+	NULL,  /* quad corner vert pattern is inserted here */
+	NULL,  /* tri single edge pattern is inserted here */
 	NULL,
 	&quad_3edge,
 	NULL,
 };
 
-#define PLEN  (sizeof(patterns) / sizeof(void *))
+#define PATTERNS_TOT  (sizeof(patterns) / sizeof(void *))
 
 typedef struct SubDFaceData {
-	BMVert *start; SubDPattern *pat;
-	int totedgesel; //only used if pat was NULL, e.g. no pattern was found
+	BMVert *start;
+	const SubDPattern *pat;
+	int totedgesel;  /* only used if pat was NULL, e.g. no pattern was found */
 	BMFace *face;
 } SubDFaceData;
 
 void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
 {
 	BMOpSlot *einput;
-	SubDPattern *pat;
+	const SubDPattern *pat;
 	SubDParams params;
 	SubDFaceData *facedata = NULL;
+	BLI_array_declare(facedata);
 	BMIter viter, fiter, liter;
 	BMVert *v, **verts = NULL;
-	BMEdge *edge, **edges = NULL;
-	BMLoop *nl, *l, **splits = NULL, **loops = NULL;
-	BMFace *face;
-	BLI_array_declare(splits);
-	BLI_array_declare(loops);
-	BLI_array_declare(facedata);
+	BMEdge *edge;
+	BMEdge **edges = NULL;
 	BLI_array_declare(edges);
+	BMLoop *(*loops_split)[2] = NULL;
+	BLI_array_declare(loops_split);
+	BMLoop **loops = NULL;
+	BLI_array_declare(loops);
+	BMLoop *nl, *l;
+	BMFace *face;
 	BLI_array_declare(verts);
 	float smooth, fractal, along_normal;
 	int use_sphere, cornertype, use_singleedge, use_gridfill;
@@ -726,7 +730,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
 	BLI_srandom(seed);
 	
 	patterns[1] = NULL;
-	//straight cut is patterns[1] == NULL
+	/* straight cut is patterns[1] == NULL */
 	switch (cornertype) {
 		case SUBD_PATH:
 			patterns[1] = &quad_2edge_path;
@@ -861,7 +865,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
 			continue;
 		}
 
-		for (i = 0; i < PLEN; i++) {
+		for (i = 0; i < PATTERNS_TOT; i++) {
 			pat = patterns[i];
 			if (!pat) {
 				continue;
@@ -935,12 +939,12 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
 			
 			/* ok, no pattern.  we still may be able to do something */
 			BLI_array_empty(loops);
-			BLI_array_empty(splits);
+			BLI_array_empty(loops_split);
 
 			/* for case of two edges, connecting them shouldn't be too hard */
-			BM_ITER_ELEM (l, &liter, face, BM_LOOPS_OF_FACE) {
-				BLI_array_grow_one(loops);
-				loops[BLI_array_count(loops) - 1] = l;
+			BLI_array_grow_items(loops, face->len);
+			BM_ITER_ELEM_INDEX (l, &liter, face, BM_LOOPS_OF_FACE, a) {
+				loops[a] = l;
 			}
 			
 			vlen = BLI_array_count(loops);
@@ -971,23 +975,65 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
 			
 			b += numcuts - 1;
 
+			BLI_array_grow_items(loops_split, numcuts);
 			for (j = 0; j < numcuts; j++) {
-				BLI_array_grow_one(splits);
-				splits[BLI_array_count(splits) - 1] = loops[a];
-				
-				BLI_array_grow_one(splits);
-				splits[BLI_array_count(splits) - 1] = loops[b];
+				int ok = TRUE;
+
+				/* Check for special case: [#32500]
+				 * This edge pair could be used by more then one face,
+				 * in this case it used to (2.63), split both faces along the same verts
+				 * while it could be calculated which face should do the split,
+				 * its ambigious, so in this case we're better off to skip them as exceptional cases
+				 * and not try to be clever guessing which face to cut up.
+				 *
+				 * To avoid this case we need to check:
+				 * Do the verts of each share a face besides the one we are subdividing,
+				 *  (but not connect to make an edge of that face).
+				 */
+				{
+					BMLoop *other_loop;
+					BMIter other_fiter;
+					BM_ITER_ELEM (other_loop, &other_fiter, loops[a]->v, BM_LOOPS_OF_VERT) {
+						if (other_loop->f != face) {
+							if (BM_vert_in_face(other_loop->f, loops[a]->v)) {
+								/* we assume that these verts are not making an edge in the face */
+								BLI_assert(other_loop->prev->v != loops[a]->v);
+								BLI_assert(other_loop->next->v != loops[a]->v);
+
+								ok = FALSE;
+								break;
+							}
+						}
+					}
+				}
+
+
+				if (ok == TRUE) {
+					loops_split[j][0] = loops[a];
+					loops_split[j][1] = loops[b];
+				}
+				else {
+					loops_split[j][0] = NULL;
+					loops_split[j][1] = NULL;
+				}
 
 				b = (b - 1) % vlen;
 				a = (a + 1) % vlen;
 			}
 			
-			//BM_face_legal_splits(bmesh, face, splits, BLI_array_count(splits) / 2);
+			/* Since these are newly created vertices, we don't need to worry about them being legal,
+			 * ... though there are some cases we _should_ check for
+			 * - concave corner of an ngon.
+			 * - 2 edges being used in 2+ ngons.
+			 */
+//			BM_face_legal_splits(bm, face, loops_split, BLI_array_count(loops_split));
+
+			for (j = 0; j < BLI_array_count(loops_split); j++) {
+				if (loops_split[j][0]) {
+					BLI_assert(BM_edge_exists(loops_split[j][0]->v, loops_split[j][1]->v) == FALSE);
 
-			for (j = 0; j < BLI_array_count(splits) / 2; j++) {
-				if (splits[j * 2]) {
 					/* BMFace *nf = */ /* UNUSED */
-					BM_face_split(bm, face, splits[j * 2]->v, splits[j * 2 + 1]->v, &nl, NULL, FALSE);
+					BM_face_split(bm, face, loops_split[j][0]->v, loops_split[j][1]->v, &nl, NULL, FALSE);
 				}
 			}
 
@@ -997,27 +1043,19 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
 			continue;
 		}
 
-		j = a = 0;
-		for (nl = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, face);
-		     nl;
-		     nl = BM_iter_step(&liter))
-		{
+		a = 0;
+		BM_ITER_ELEM_INDEX (nl, &liter, face, BM_LOOPS_OF_FACE, j) {
 			if (nl->v == facedata[i].start) {
 				a = j + 1;
 				break;
 			}
-			j++;
 		}
 
-		for (j = 0; j < face->len; j++) {
-			BLI_array_grow_one(verts);
-		}
-		
-		j = 0;
-		for (nl = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, face); nl; nl = BM_iter_step(&liter)) {
+		BLI_array_grow_items(verts, face->len);
+
+		BM_ITER_ELEM_INDEX (nl, &liter, face, BM_LOOPS_OF_FACE, j) {
 			b = (j - a + face->len) % face->len;
 			verts[b] = nl->v;
-			j += 1;
 		}
 
 		BM_CHECK_ELEMENT(face);
@@ -1035,7 +1073,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
 	if (facedata) BLI_array_free(facedata);
 	if (edges) BLI_array_free(edges);
 	if (verts) BLI_array_free(verts);
-	BLI_array_free(splits);
+	BLI_array_free(loops_split);
 	BLI_array_free(loops);
 
 	BMO_slot_buffer_from_enabled_flag(bm, op, "outinner", BM_ALL, ELE_INNER);
diff --git a/source/blender/compositor/COM_compositor.h b/source/blender/compositor/COM_compositor.h
index e6efd77f8b2..f35bf71392c 100644
--- a/source/blender/compositor/COM_compositor.h
+++ b/source/blender/compositor/COM_compositor.h
@@ -277,6 +277,9 @@ extern "C" {
  * It can be executed during editing (blenkernel/node.c) or rendering
  * (renderer/pipeline.c)
  *
+ * @param rd [struct RenderData]
+ *   Render data for this composite, this won't always belong to a scene.
+ *
  * @param editingtree [struct bNodeTree]
  *   reference to the compositor editing tree
  *
@@ -309,7 +312,7 @@ void COM_deinitialize(void);
  * @brief Clear all compositor caches. (Compositor system will still remain available). 
  * To deinitialize the compositor use the COM_deinitialize method.
  */
-void COM_clearCaches(void);
+// void COM_clearCaches(void); // NOT YET WRITTEN
 
 /**
  * @brief Return a list of highlighted bnodes pointers.
diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp
index d4fad80ed07..71067ac8f15 100644
--- a/source/blender/compositor/intern/COM_Converter.cpp
+++ b/source/blender/compositor/intern/COM_Converter.cpp
@@ -500,7 +500,8 @@ void Converter::convertResolution(SocketConnection *connection, ExecutionSystem
 			system->addOperation(sxop);
 			system->addOperation(syop);
 
-			unsigned int resolution[2] = {fromWidth, fromHeight};
+			unsigned int resolution[2] = {fromOperation->getWidth(),
+			                              fromOperation->getHeight()};
 			scaleOperation->setResolution(resolution);
 			sxop->setResolution(resolution);
 			syop->setResolution(resolution);
@@ -522,7 +523,8 @@ void Converter::convertResolution(SocketConnection *connection, ExecutionSystem
 		system->addOperation(xop);
 		system->addOperation(yop);
 
-		unsigned int resolution[2] = {toWidth, toHeight};
+		unsigned int resolution[2] = {toOperation->getWidth(),
+		                              toOperation->getHeight()};
 		translateOperation->setResolution(resolution);
 		xop->setResolution(resolution);
 		yop->setResolution(resolution);
diff --git a/source/blender/compositor/intern/COM_ExecutionSystemHelper.h b/source/blender/compositor/intern/COM_ExecutionSystemHelper.h
index bd34fe8ab02..307e082ea80 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystemHelper.h
+++ b/source/blender/compositor/intern/COM_ExecutionSystemHelper.h
@@ -55,7 +55,7 @@ public:
 	 * this node is converted to a Node instance.
 	 * and the converted node is returned
 	 *
-	 * @param bNode node to add
+	 * @param b_node node to add
 	 * @return Node that represents the bNode or null when not able to convert.
 	 */
 	static Node *addNode(vector& nodes, bNode *b_node, bool isInActiveGroup, bool fast);
diff --git a/source/blender/compositor/operations/COM_RenderLayersImageProg.h b/source/blender/compositor/operations/COM_RenderLayersImageProg.h
index 2d63bad235b..5fa74c8b21f 100644
--- a/source/blender/compositor/operations/COM_RenderLayersImageProg.h
+++ b/source/blender/compositor/operations/COM_RenderLayersImageProg.h
@@ -25,7 +25,7 @@
 
 #include "COM_RenderLayersBaseProg.h"
 
-/// @TODO rename to image operation
+/// @todo rename to image operation
 class RenderLayersColorProg : public RenderLayersBaseProg {
 public:
 	RenderLayersColorProg();
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index c92b7ce2761..209414550e3 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -1394,13 +1394,13 @@ static size_t animdata_filter_mask_data(ListBase *anim_data, Mask *mask, const i
 		/* only if selected */
 		if (ANIMCHANNEL_SELOK(SEL_MASKLAY(masklay)) ) {
 			/* only if editable */
-//			if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
+			if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_MASK(masklay)) {
 				/* active... */
 				if (!(filter_mode & ANIMFILTER_ACTIVE) || (masklay_act == masklay)) {
 					/* add to list */
 					ANIMCHANNEL_NEW_CHANNEL(masklay, ANIMTYPE_MASKLAYER, mask);
 				}
-//			}
+			}
 		}
 	}
 
diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c
index ce4e1db23b5..00f88a69fb6 100644
--- a/source/blender/editors/armature/reeb.c
+++ b/source/blender/editors/armature/reeb.c
@@ -3272,7 +3272,7 @@ ReebGraph *BIF_ReebGraphFromEditMesh(void)
 	freeEdgeIndex(&indexed_edges);
 	
 #ifdef DEBUG_REEB
-	weightToVCol(em, 1);
+//	weightToVCol(em, 1);
 #endif
 	
 	rg = generateReebGraph(em, G.scene->toolsettings->skgen_resolution);
diff --git a/source/blender/editors/armature/reeb.h b/source/blender/editors/armature/reeb.h
index d71e80ca0ca..bb8b3003baf 100644
--- a/source/blender/editors/armature/reeb.h
+++ b/source/blender/editors/armature/reeb.h
@@ -146,9 +146,9 @@ struct EdgeIndex;
 int weightToHarmonic(struct EditMesh *em, struct EdgeIndex *indexed_edges);
 int weightFromDistance(struct EditMesh *em, struct EdgeIndex *indexed_edges);
 int weightFromLoc(struct EditMesh *me, int axis);
-void weightToVCol(struct EditMesh *em, int index);
+//void weightToVCol(struct EditMesh *em, int index);
 void arcToVCol(struct ReebGraph *rg, struct EditMesh *em, int index);
-void angleToVCol(struct EditMesh *em, int index);
+//void angleToVCol(struct EditMesh *em, int index);
 void renormalizeWeight(struct EditMesh *em, float newmax);
 
 ReebGraph *generateReebGraph(struct EditMesh *me, int subdivisions);
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index e2d15897233..d780429784f 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -107,7 +107,7 @@ void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatu
 static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short selstatus);
 
 /* still need to eradicate a few :( */
-#define callocstructN(x, y, name) (x *)MEM_callocN((y) * sizeof(x), name)
+#define CALLOC_STRUCT_N(x, y, name) (x *)MEM_callocN((y) * sizeof(x), name)
 
 static float nurbcircle[8][2] = {
 	{0.0, -1.0}, {-1.0, -1.0}, {-1.0, 0.0}, {-1.0,  1.0},
@@ -6265,7 +6265,7 @@ Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newob)
 				nu->pntsu = 4;
 				nu->pntsv = 1;
 				nu->orderu = 4;
-				nu->bp = callocstructN(BPoint, 4, "addNurbprim3");
+				nu->bp = CALLOC_STRUCT_N(BPoint, 4, "addNurbprim3");
 
 				bp = nu->bp;
 				for (a = 0; a < 4; a++, bp++) {
@@ -6301,7 +6301,7 @@ Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newob)
 			nu->orderu = 5;
 			nu->flagu = CU_NURB_ENDPOINT; /* endpoint */
 			nu->resolu = cu->resolu;
-			nu->bp = callocstructN(BPoint, 5, "addNurbprim3");
+			nu->bp = CALLOC_STRUCT_N(BPoint, 5, "addNurbprim3");
 
 			bp = nu->bp;
 			for (a = 0; a < 5; a++, bp++) {
@@ -6334,7 +6334,7 @@ Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newob)
 			if (cutype == CU_BEZIER) {
 				if (!force_3d) nu->flag |= CU_2D;
 				nu->pntsu = 4;
-				nu->bezt = callocstructN(BezTriple, 4, "addNurbprim1");
+				nu->bezt = CALLOC_STRUCT_N(BezTriple, 4, "addNurbprim1");
 				nu->flagu = CU_NURB_CYCLIC;
 				bezt = nu->bezt;
 
@@ -6371,7 +6371,7 @@ Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newob)
 				nu->pntsu = 8;
 				nu->pntsv = 1;
 				nu->orderu = 4;
-				nu->bp = callocstructN(BPoint, 8, "addNurbprim6");
+				nu->bp = CALLOC_STRUCT_N(BPoint, 8, "addNurbprim6");
 				nu->flagu = CU_NURB_CYCLIC;
 				bp = nu->bp;
 
@@ -6404,7 +6404,7 @@ Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newob)
 				nu->orderu = 4;
 				nu->orderv = 4;
 				nu->flag = CU_SMOOTH;
-				nu->bp = callocstructN(BPoint, 4 * 4, "addNurbprim6");
+				nu->bp = CALLOC_STRUCT_N(BPoint, 4 * 4, "addNurbprim6");
 				nu->flagu = 0;
 				nu->flagv = 0;
 				bp = nu->bp;
@@ -6471,7 +6471,7 @@ Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newob)
 				nu->resolu = cu->resolu;
 				nu->resolv = cu->resolv;
 				nu->flag = CU_SMOOTH;
-				nu->bp = callocstructN(BPoint, 5, "addNurbprim6");
+				nu->bp = CALLOC_STRUCT_N(BPoint, 5, "addNurbprim6");
 				nu->flagu = 0;
 				bp = nu->bp;
 
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index da440063552..c25401d570f 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -141,9 +141,6 @@ void              EDBM_uv_vert_map_free(struct UvVertMap *vmap);
 struct UvMapVert *EDBM_uv_vert_map_at_index(struct UvVertMap *vmap, unsigned int v);
 struct UvVertMap *EDBM_uv_vert_map_create(struct BMEditMesh *em, int selected, int do_face_idx_array, const float limit[2]);
 
-void EDBM_data_layer_add(struct BMEditMesh *em, struct CustomData *data, int type, const char *name);
-void EDBM_data_layer_free(struct BMEditMesh *em, struct CustomData *data, int type);
-
 void EDBM_select_toggle_all(struct BMEditMesh *em);
 void EDBM_select_swap(struct BMEditMesh *em); /* exported for UV */
 int  EDBM_select_interior_faces(struct BMEditMesh *em);
diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h
index 7891315be9f..39e2c28a61a 100644
--- a/source/blender/editors/include/ED_render.h
+++ b/source/blender/editors/include/ED_render.h
@@ -56,18 +56,12 @@ void ED_render_scene_update(struct Main *bmain, struct Scene *scene, int updated
 typedef struct RenderInfo {
 	int pr_rectx;
 	int pr_recty;
-	short curtile, tottile, status;
+	short curtile, tottile;
 	rcti disprect;          /* storage for view3d preview rect */
 	unsigned int *rect;
 	struct Render *re;      /* persistent render */
 } RenderInfo;
 
-/* ri->status */
-#define PR_DBASE            1
-#define PR_DISPRECT         2
-#define PR_PROJECTED        4
-#define PR_ROTATED          8
-
 /* Render the preview
  *
  * pr_method:
diff --git a/source/blender/editors/io/io_collada.h b/source/blender/editors/io/io_collada.h
index 5cb255e1b7c..4bb1475a3b2 100644
--- a/source/blender/editors/io/io_collada.h
+++ b/source/blender/editors/io/io_collada.h
@@ -24,7 +24,7 @@
  * ***** END GPL LICENSE BLOCK *****
  */
 
-/** \file blender/editor/io/io_collada.h
+/** \file blender/editors/io/io_collada.h
  *  \ingroup editor/io
  */
 
diff --git a/source/blender/editors/io/io_ops.h b/source/blender/editors/io/io_ops.h
index 4c04b349655..4fffca4607c 100644
--- a/source/blender/editors/io/io_ops.h
+++ b/source/blender/editors/io/io_ops.h
@@ -24,7 +24,7 @@
  * ***** END GPL LICENSE BLOCK *****
  */
 
-/** \file blender/editor/io/io_ops.h
+/** \file blender/editors/io/io_ops.h
  *  \ingroup editor/io
  */
 
diff --git a/source/blender/editors/mesh/editmesh_slide.c b/source/blender/editors/mesh/editmesh_slide.c
index f08c229d38a..397f224ef2e 100644
--- a/source/blender/editors/mesh/editmesh_slide.c
+++ b/source/blender/editors/mesh/editmesh_slide.c
@@ -27,6 +27,7 @@
 /* Takes heavily from editmesh_loopcut.c */
 
 #include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
 
 #include "MEM_guardedalloc.h"
 
@@ -99,7 +100,7 @@ typedef struct VertexSlideOp {
 } VertexSlideOp;
 
 static void vtx_slide_draw(const bContext *C, ARegion *ar, void *arg);
-static int edbm_vertex_slide_exec(bContext *C, wmOperator *op);
+static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_update);
 static void vtx_slide_exit(const bContext *C, wmOperator *op);
 static int vtx_slide_set_frame(VertexSlideOp *vso);
 
@@ -195,16 +196,38 @@ static void vtx_slide_confirm(bContext *C, wmOperator *op)
 	VertexSlideOp *vso = op->customdata;
 	BMEditMesh *em = BMEdit_FromObject(vso->obj);
 	BMesh *bm = em->bm;
+	BMVert *other = NULL;
+
+	BMVert *mirr_vtx = NULL;
+	BMVert *mirr_vtx_other = NULL;
 
 	/* Select new edge */
 	BM_edge_select_set(bm, vso->sel_edge, TRUE);
 
-	/* Invoke operator */
-	edbm_vertex_slide_exec(C, op);
+	if (vso->snap_n_merge) {
+		other = BM_edge_other_vert(vso->sel_edge, vso->start_vtx);
+	}
+
+	if (em->me->editflag & ME_EDIT_MIRROR_X) {
+		EDBM_verts_mirror_cache_begin(em, TRUE);
+
+		mirr_vtx = EDBM_verts_mirror_get(em, vso->start_vtx);
+		if (vso->snap_n_merge) {
+			mirr_vtx_other = EDBM_verts_mirror_get(em, other);
+		}
+	}
+
+	/* Invoke operator - warning */
+	edbm_vertex_slide_exec_ex(C, op, FALSE);
+
+	if (mirr_vtx) {
+		mirr_vtx->co[0] = -vso->start_vtx->co[0];
+		mirr_vtx->co[1] =  vso->start_vtx->co[1];
+		mirr_vtx->co[2] =  vso->start_vtx->co[2];
+	}
 
 	if (vso->snap_n_merge) {
 		float other_d;
-		BMVert *other = BM_edge_other_vert(vso->sel_edge, vso->start_vtx);
 		other_d = len_v3v3(vso->interp, other->co);
 
 		/* Only snap if within threshold */
@@ -213,6 +236,13 @@ static void vtx_slide_confirm(bContext *C, wmOperator *op)
 			BM_vert_select_set(bm, vso->start_vtx, TRUE);
 			EDBM_op_callf(em, op, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, other->co);
 			EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+
+			if (mirr_vtx_other) {
+				BM_vert_select_set(bm, mirr_vtx, TRUE);
+				BM_vert_select_set(bm, mirr_vtx_other, TRUE);
+				EDBM_op_callf(em, op, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, mirr_vtx_other->co);
+				EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+			}
 		}
 		else {
 			/* Store in historty if not merging */
@@ -225,6 +255,10 @@ static void vtx_slide_confirm(bContext *C, wmOperator *op)
 		BM_select_history_store(em->bm, vso->start_vtx);
 	}
 
+	if (em->me->editflag & ME_EDIT_MIRROR_X) {
+		EDBM_verts_mirror_cache_end(em);
+	}
+
 	EDBM_selectmode_flush(em);
 	
 	/* NC_GEOM | ND_DATA & Retess */
@@ -644,7 +678,7 @@ static int edbm_vertex_slide_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED
 }
 
 /* Vertex Slide */
-static int edbm_vertex_slide_exec(bContext *C, wmOperator *op)
+static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_update)
 {
 	Object *obedit = CTX_data_edit_object(C);
 	BMEditMesh *em = BMEdit_FromObject(obedit);
@@ -708,11 +742,17 @@ static int edbm_vertex_slide_exec(bContext *C, wmOperator *op)
 		return OPERATOR_CANCELLED;
 	}
 
-	/* Update Geometry */
-	EDBM_update_generic(C, em, TRUE);
+	if (do_update) {
+		/* Update Geometry */
+		EDBM_update_generic(C, em, TRUE);
+	}
 
 	return OPERATOR_FINISHED;
 }
+static int edbm_vertex_slide_exec(bContext *C, wmOperator *op)
+{
+	return edbm_vertex_slide_exec_ex(C, op, TRUE);
+}
 
 void MESH_OT_vert_slide(wmOperatorType *ot)
 {
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 967c6e85590..c93f4156eeb 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -298,13 +298,13 @@ void setlinestyle(int nr)
 
 /* Invert line handling */
 	
-#define gl_toggle(mode, onoff)  (((onoff) ? glEnable : glDisable)(mode))
+#define GL_TOGGLE(mode, onoff)  (((onoff) ? glEnable : glDisable)(mode))
 
 void set_inverted_drawing(int enable) 
 {
 	glLogicOp(enable ? GL_INVERT : GL_COPY);
-	gl_toggle(GL_COLOR_LOGIC_OP, enable);
-	gl_toggle(GL_DITHER, !enable);
+	GL_TOGGLE(GL_COLOR_LOGIC_OP, enable);
+	GL_TOGGLE(GL_DITHER, !enable);
 }
 
 void sdrawXORline(int x0, int y0, int x1, int y1)
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index d1e2066cfba..7c5a1cca756 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -900,7 +900,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
 	struct ImBuf *ibuf = NULL;
 	struct ImBuf *scope = NULL;
 	struct View2D *v2d = &ar->v2d;
-	int rectx, recty;
+	/* int rectx, recty; */ /* UNUSED */
 	float viewrectx, viewrecty;
 	float render_size = 0.0;
 	float proxy_size = 100.0;
@@ -924,8 +924,8 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
 	viewrectx = (render_size * (float)scene->r.xsch) / 100.0f;
 	viewrecty = (render_size * (float)scene->r.ysch) / 100.0f;
 
-	rectx = viewrectx + 0.5f;
-	recty = viewrecty + 0.5f;
+	/* rectx = viewrectx + 0.5f; */ /* UNUSED */
+	/* recty = viewrecty + 0.5f; */ /* UNUSED */
 
 	if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
 		viewrectx *= scene->r.xasp / scene->r.yasp;
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index f5c3a4c4d89..935bd13fcfc 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -118,8 +118,6 @@ void SEQUENCER_OT_paste(struct wmOperatorType *ot);
 
 void SEQUENCER_OT_rebuild_proxy(struct wmOperatorType *ot);
 
-void SEQUENCER_OT_update_strip_length(struct wmOperatorType *ot);
-
 /* preview specific operators */
 void SEQUENCER_OT_view_all_preview(struct wmOperatorType *ot);
 
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index d258d271833..f0ff79ae25e 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -46,10 +46,6 @@ struct BMLoop;
 struct BMEdge;
 struct BMVert;
 
-/* id can be from 0 to 3 */
-#define TF_PIN_MASK(id) (TF_PIN1 << id)
-#define TF_SEL_MASK(id) (TF_SEL1 << id)
-
 /* visibility and selection */
 int uvedit_face_visible_nolocal(struct Scene *scene, struct BMFace *efa);
 
diff --git a/source/blender/ikplugin/BIK_api.h b/source/blender/ikplugin/BIK_api.h
index cbc6485cb54..e1d5f50edfb 100644
--- a/source/blender/ikplugin/BIK_api.h
+++ b/source/blender/ikplugin/BIK_api.h
@@ -70,9 +70,9 @@ void BIK_clear_cache(struct bPose *pose);
 void BIK_update_param(struct bPose *pose);
 void BIK_test_constraint(struct Object *ob, struct bConstraint *cons);
 // not yet implemented
-int BIK_get_constraint_param(struct bPose *pose, struct bConstraint *cons, int id, BIK_ParamValue *value);
-int BIK_get_channel_param(struct bPose *pose, struct bPoseChannel *pchan, int id, BIK_ParamValue *value);
-int BIK_get_solver_param(struct bPose *pose, struct bPoseChannel *pchan, int id, BIK_ParamValue *value);
+// int BIK_get_constraint_param(struct bPose *pose, struct bConstraint *cons, int id, BIK_ParamValue *value);
+// int BIK_get_channel_param(struct bPose *pose, struct bPoseChannel *pchan, int id, BIK_ParamValue *value);
+// int BIK_get_solver_param(struct bPose *pose, struct bPoseChannel *pchan, int id, BIK_ParamValue *value);
 
 // number of solver available
 // 0 = iksolver
diff --git a/source/blender/imbuf/intern/imbuf_cocoa.m b/source/blender/imbuf/intern/imbuf_cocoa.m
index 10381e9d1c3..d099c8af236 100644
--- a/source/blender/imbuf/intern/imbuf_cocoa.m
+++ b/source/blender/imbuf/intern/imbuf_cocoa.m
@@ -20,7 +20,7 @@
  * ***** END GPL LICENSE BLOCK *****
  */
 
-/** \file blender/imbuf/intern/imbuf_coca.m
+/** \file blender/imbuf/intern/imbuf_cocoa.m
  *  \ingroup imbuf
  *
  * Provides image file loading and saving for Blender, via Cocoa.
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index 2f5ef9c2aaa..0b826070fe4 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -326,7 +326,6 @@ typedef struct MVertSkin {
 #define TF_SEL2		8
 #define TF_SEL3		16
 #define TF_SEL4		32
-#define TF_HIDE		64 /* unused, same as TF_SELECT */
 
 /* mtface->mode */
 #define TF_DYNAMIC		1
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 51186c9bb6e..639c1cd5fb2 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1159,7 +1159,7 @@ typedef struct Scene {
 #define R_EDGE			0x0020
 #define R_FIELDS		0x0040
 #define R_FIELDSTILL	0x0080
-#define R_RADIO			0x0100
+/*#define R_RADIO			0x0100 */ /* deprecated */
 #define R_BORDER		0x0200
 #define R_PANORAMA		0x0400	/* deprecated as scene option, still used in renderer */
 #define R_CROP			0x0800
@@ -1357,9 +1357,6 @@ typedef struct Scene {
 #define TIME2FRA(a)           ((((double) scene->r.frs_sec) * (double)(a)) / (double)scene->r.frs_sec_base)
 #define FPS                     (((double) scene->r.frs_sec) / (double)scene->r.frs_sec_base)
 
-#define RAD_PHASE_PATCHES	1
-#define RAD_PHASE_FACES		2
-
 /* base->flag is in DNA_object_types.h */
 
 /* toolsettings->snap_flag */
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index 34fb7ce60be..b1cd54950e6 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -77,8 +77,6 @@ typedef struct bScreen {
 	
 	struct wmTimer *animtimer;			/* if set, screen has timer handler added in window */
 	void *context;						/* context callback */
-	
-	short handler[8];					/* similar to space handler */
 } bScreen;
 
 typedef struct ScrVert {
@@ -214,13 +212,6 @@ typedef struct ARegion {
 #define PNL_DEFAULT_CLOSED		1
 #define PNL_NO_HEADER			2
 
-/* screen handlers */
-#define SCREEN_MAXHANDLER		8
-
-#define SCREEN_HANDLER_ANIM		1
-#define SCREEN_HANDLER_PYTHON   2
-#define SCREEN_HANDLER_VERSE	3
-
 /* regiontype, first two are the default set */
 /* Do NOT change order, append on end. Types are hardcoded needed */
 enum {
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index ebe13508eb8..913f416e6ea 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -393,11 +393,6 @@ enum {
 	SEQ_TYPE_EFFECT_MAX  = 31
 };
 
-#define STRIPELEM_FAILED       0
-#define STRIPELEM_OK           1
-
-#define STRIPELEM_PREVIEW_DONE  1
-
 #define SEQ_MOVIECLIP_RENDER_UNDISTORTED (1 << 0)
 #define SEQ_MOVIECLIP_RENDER_STABILIZED  (1 << 1)
 
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 3f9f4d3980e..218027209a8 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -47,7 +47,6 @@ struct ColorBand;
 /* ************************ style definitions ******************** */
 
 #define MAX_STYLE_NAME	64
-#define MAX_FONT_NAME	256
 
 /* default uifont_id offered by Blender */
 #define UIFONT_DEFAULT	0
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 90fe09246fc..c58271bb4bc 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -3564,11 +3564,13 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
 	RNA_def_property_boolean_sdna(prop, NULL, "mode", R_ENVMAP);
 	RNA_def_property_ui_text(prop, "Environment Maps", "Calculate environment maps while rendering");
 	RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-	
+
+#if 0
 	prop = RNA_def_property(srna, "use_radiosity", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "mode", R_RADIO);
 	RNA_def_property_ui_text(prop, "Radiosity", "Calculate radiosity in a pre-process before rendering");
 	RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+#endif
 	
 	prop = RNA_def_property(srna, "use_sss", PROP_BOOLEAN, PROP_NONE);
 	RNA_def_property_boolean_sdna(prop, NULL, "mode", R_SSS);
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 7cebbe5a895..f753ff680fd 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -2982,11 +2982,12 @@ static void rna_def_userdef_system(BlenderRNA *brna)
 	/* locale according to http://www.roseindia.net/tutorials/I18N/locales-list.shtml */
 	/* if you edit here, please also edit the source/blender/blenfont/intern/blf_lang.c 's locales */
 	/* Note: As this list is in alphabetical order, and not defined order,
-	 *       here is the highest define currently in use: 31 (Hungarian). */
+	 *       here is the highest define currently in use: 32 (Brazilian Portuguese). */
 	static EnumPropertyItem language_items[] = {
 		{ 0, "", 0, N_("Nearly done"), ""},
 		{ 0, "DEFAULT", 0, "Default (Default)", ""},
 		{21, "ARABIC", 0, "Arabic (ﺔﻴﺑﺮﻌﻟﺍ)", "ar_EG"},
+		{32, "BRAZILIANPORTUGUESE", 0, "Brazilian Portuguese (Português do Brasil)", "pt_BR"},
 		{ 1, "ENGLISH", 0, "English (English)", "en_US"},
 		{ 8, "FRENCH", 0, "French (Français)", "fr_FR"},
 		{ 4, "ITALIAN", 0, "Italian (Italiano)", "it_IT"},
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index d5deb50e1f9..22b1e33e2a6 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -474,7 +474,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
 				float *dists_e = use_trgt_edges ? MEM_mallocN(sizeof(float) * numIdx, "dists_e") : NULL;
 				float *dists_f = use_trgt_faces ? MEM_mallocN(sizeof(float) * numIdx, "dists_f") : NULL;
 
-				space_transform_setup(&loc2trgt, ob, obr);
+				SPACE_TRANSFORM_SETUP(&loc2trgt, ob, obr);
 				get_vert2geom_distance(numIdx, v_cos, dists_v, dists_e, dists_f,
 				                       target_dm, &loc2trgt);
 				for (i = 0; i < numIdx; i++) {
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index e5af51cf2d7..85dbd9356f4 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -63,7 +63,6 @@ struct ReportList;
 struct Main;
 
 #define TABLEINITSIZE 1024
-#define LAMPINITSIZE 256
 
 typedef struct SampleTables {
 	float centLut[16];
diff --git a/source/blender/render/intern/include/sunsky.h b/source/blender/render/intern/include/sunsky.h
index 4bb7d99ba16..74e42109be5 100644
--- a/source/blender/render/intern/include/sunsky.h
+++ b/source/blender/render/intern/include/sunsky.h
@@ -27,9 +27,7 @@
 #ifndef __SUNSKY_H__
 #define __SUNSKY_H__
 
-#define SPECTRUM_MAX_COMPONENTS     100
-#define SPECTRUM_START              350.0
-#define SPECTRUM_END                800.0
+// #define SPECTRUM_MAX_COMPONENTS     100
 
 typedef struct SunSky {
 	short effect_type, skyblendtype, sky_colorspace;
diff --git a/source/blender/render/intern/include/volumetric.h b/source/blender/render/intern/include/volumetric.h
index 7f63bcbbecc..3805478fed0 100644
--- a/source/blender/render/intern/include/volumetric.h
+++ b/source/blender/render/intern/include/volumetric.h
@@ -41,9 +41,6 @@ void shade_volume_outside(ShadeInput *shi, ShadeResult *shr);
 void shade_volume_inside(ShadeInput *shi, ShadeResult *shr);
 void shade_volume_shadow(struct ShadeInput *shi, struct ShadeResult *shr, struct Isect *last_is);
 
-#define STEPSIZE_VIEW	0
-#define STEPSIZE_SHADE	1
-
 #define VOL_IS_BACKFACE			1
 #define VOL_IS_SAMEMATERIAL		2
 
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
index ed8a6cc7220..3a06fe979e1 100644
--- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -125,68 +125,66 @@ static BlendFileData *load_game_data(char *filename)
 	return bfd;
 }
 
-int BL_KetsjiNextFrame(struct KX_KetsjiEngine* ketsjiengine, struct bContext *C, struct wmWindow* win, struct Scene* scene, struct ARegion *ar,
-                    KX_BlenderKeyboardDevice* keyboarddevice, KX_BlenderMouseDevice* mousedevice, int draw_letterbox)
+int BL_KetsjiNextFrame(KX_KetsjiEngine *ketsjiengine, bContext *C, wmWindow *win, Scene *scene, ARegion *ar,
+                       KX_BlenderKeyboardDevice* keyboarddevice, KX_BlenderMouseDevice* mousedevice, int draw_letterbox)
 {
-    int exitrequested;
+	int exitrequested;
 
-    // first check if we want to exit
-    exitrequested = ketsjiengine->GetExitCode();
+	// first check if we want to exit
+	exitrequested = ketsjiengine->GetExitCode();
 
-    // kick the engine
-    bool render = ketsjiengine->NextFrame();
+	// kick the engine
+	bool render = ketsjiengine->NextFrame();
 
-    if (render)
-    {
-        if(draw_letterbox) {
-            // Clear screen to border color
-            // We do this here since we set the canvas to be within the frames. This means the engine
-            // itself is unaware of the extra space, so we clear the whole region for it.
-            glClearColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 1.0f);
-            glViewport(ar->winrct.xmin, ar->winrct.ymin,
+	if (render) {
+		if (draw_letterbox) {
+			// Clear screen to border color
+			// We do this here since we set the canvas to be within the frames. This means the engine
+			// itself is unaware of the extra space, so we clear the whole region for it.
+			glClearColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 1.0f);
+			glViewport(ar->winrct.xmin, ar->winrct.ymin,
 			           BLI_RCT_SIZE_X(&ar->winrct), BLI_RCT_SIZE_Y(&ar->winrct));
-            glClear(GL_COLOR_BUFFER_BIT);
-        }
+			glClear(GL_COLOR_BUFFER_BIT);
+		}
 
-        // render the frame
-        ketsjiengine->Render();
-    }
+		// render the frame
+		ketsjiengine->Render();
+	}
 
-    wm_window_process_events_nosleep();
+	wm_window_process_events_nosleep();
 
-    // test for the ESC key
-    //XXX while (qtest())
-    while(wmEvent *event= (wmEvent *)win->queue.first)
-    {
-        short val = 0;
-        //unsigned short event = 0; //XXX extern_qread(&val);
+	// test for the ESC key
+	//XXX while (qtest())
+	while (wmEvent *event= (wmEvent *)win->queue.first) {
+		short val = 0;
+		//unsigned short event = 0; //XXX extern_qread(&val);
 
-        if (keyboarddevice->ConvertBlenderEvent(event->type,event->val))
-            exitrequested = KX_EXIT_REQUEST_BLENDER_ESC;
+		if (keyboarddevice->ConvertBlenderEvent(event->type,event->val))
+			exitrequested = KX_EXIT_REQUEST_BLENDER_ESC;
 
-            /* Coordinate conversion... where
-            * should this really be?
-        */
-        if (event->type==MOUSEMOVE) {
-            /* Note, not nice! XXX 2.5 event hack */
-            val = event->x - ar->winrct.xmin;
-            mousedevice->ConvertBlenderEvent(MOUSEX, val);
+		/* Coordinate conversion... where
+		 * should this really be?
+		 */
+		if (event->type == MOUSEMOVE) {
+			/* Note, not nice! XXX 2.5 event hack */
+			val = event->x - ar->winrct.xmin;
+			mousedevice->ConvertBlenderEvent(MOUSEX, val);
 
-            val = ar->winy - (event->y - ar->winrct.ymin) - 1;
-            mousedevice->ConvertBlenderEvent(MOUSEY, val);
-        }
-        else {
-            mousedevice->ConvertBlenderEvent(event->type,event->val);
-        }
+			val = ar->winy - (event->y - ar->winrct.ymin) - 1;
+			mousedevice->ConvertBlenderEvent(MOUSEY, val);
+		}
+		else {
+			mousedevice->ConvertBlenderEvent(event->type,event->val);
+		}
 
-        BLI_remlink(&win->queue, event);
-        wm_event_free(event);
-    }
+		BLI_remlink(&win->queue, event);
+		wm_event_free(event);
+	}
 
-    if(win != CTX_wm_window(C)) {
-        exitrequested= KX_EXIT_REQUEST_OUTSIDE; /* window closed while bge runs */
-    }
-    return exitrequested;
+	if (win != CTX_wm_window(C)) {
+		exitrequested= KX_EXIT_REQUEST_OUTSIDE; /* window closed while bge runs */
+	}
+	return exitrequested;
 }
 
 struct BL_KetsjiNextFrameState {
diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp
index 5347aaafc65..a35cb4f9f69 100644
--- a/source/gameengine/Expressions/PyObjectPlus.cpp
+++ b/source/gameengine/Expressions/PyObjectPlus.cpp
@@ -262,7 +262,7 @@ PyMethodDef PyObjectPlus::Methods[] = {
   {NULL, NULL}		/* Sentinel */
 };
 
-#define attr_invalid (&(PyObjectPlus::Attributes[0]))
+#define BGE_PY_ATTR_INVALID (&(PyObjectPlus::Attributes[0]))
 PyAttributeDef PyObjectPlus::Attributes[] = {
 	KX_PYATTRIBUTE_RO_FUNCTION("invalid",		PyObjectPlus, pyattr_get_invalid),
 	{NULL} //Sentinel
@@ -281,7 +281,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *
 	PyObjectPlus *ref= (BGE_PROXY_REF(self_py));
 	char* ptr = (attrdef->m_usePtr) ? (char*)BGE_PROXY_PTR(self_py) : (char*)ref;
 	if (ptr == NULL || (BGE_PROXY_PYREF(self_py) && (ref==NULL || !ref->py_is_valid()))) {
-		if (attrdef == attr_invalid)
+		if (attrdef == BGE_PY_ATTR_INVALID)
 			Py_RETURN_TRUE; // don't bother running the function
 
 		PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
index ea4ac1e150b..48fa3257d20 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
+++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
@@ -81,7 +81,7 @@ SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex )
 	return NULL;
 #else  /* WITH_SDL */
 	if (joyindex < 0 || joyindex >= JOYINDEX_MAX) {
-		echo("Error-invalid joystick index: " << joyindex);
+		ECHO("Error-invalid joystick index: " << joyindex);
 		return NULL;
 	}
 
@@ -96,7 +96,7 @@ SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex )
 #  else
 		if (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO) == -1 ) {
 #  endif
-			echo("Error-Initializing-SDL: " << SDL_GetError());
+			ECHO("Error-Initializing-SDL: " << SDL_GetError());
 			return NULL;
 		}
 		
@@ -242,7 +242,7 @@ bool SCA_Joystick::CreateJoystickDevice(void)
 	if (m_isinit == false) {
 		if (m_joyindex>=m_joynum) {
 			// don't print a message, because this is done anyway
-			//echo("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)");
+			//ECHO("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)");
 			
 			// Need this so python args can return empty lists
 			m_axismax = m_buttonmax = m_hatmax = 0;
@@ -253,7 +253,7 @@ bool SCA_Joystick::CreateJoystickDevice(void)
 		SDL_JoystickEventState(SDL_ENABLE);
 		m_isinit = true;
 		
-		echo("Joystick " << m_joyindex << " initialized");
+		ECHO("Joystick " << m_joyindex << " initialized");
 		
 		/* must run after being initialized */
 		m_axismax =		SDL_JoystickNumAxes(m_private->m_joystick);
@@ -279,7 +279,7 @@ void SCA_Joystick::DestroyJoystickDevice(void)
 #ifdef WITH_SDL
 	if (m_isinit) {
 		if (SDL_JoystickOpened(m_joyindex)) {
-			echo("Closing-joystick " << m_joyindex);
+			ECHO("Closing-joystick " << m_joyindex);
 			SDL_JoystickClose(m_private->m_joystick);
 		}
 		m_isinit = false;
diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h
index 45766eb9057..148bdd0962e 100644
--- a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h
+++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h
@@ -37,10 +37,10 @@
 #endif
 
 #ifndef _DEBUG
-#define echo(x)
+#  define ECHO(x)
 #else
-#include 
-#define echo(x) std::cout << x << std::endl;
+#  include 
+#  define ECHO(x) std::cout << x << std::endl;
 #endif
 
 #define JOYINDEX_MAX			8
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
index 6e1e8f5a8ec..d8b07fd50d9 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -334,17 +334,16 @@ static BlendFileData *load_game_data(const char *progname, char *filename = NULL
 
 bool GPG_NextFrame(GHOST_ISystem* system, GPG_Application *app, int &exitcode, STR_String &exitstring, GlobalSettings *gs)
 {
-    bool run = true;
-    system->processEvents(false);
-    system->dispatchEvents();
+	bool run = true;
+	system->processEvents(false);
+	system->dispatchEvents();
 	app->EngineNextFrame();
-    if ((exitcode = app->getExitRequested()))
-    {
-        run = false;
-        exitstring = app->getExitString();
-        *gs = *app->getGlobalSettings();
-    }
-    return run;
+	if ((exitcode = app->getExitRequested())) {
+		run = false;
+		exitstring = app->getExitString();
+		*gs = *app->getGlobalSettings();
+	}
+	return run;
 }
 
 struct GPG_NextFrameState {
diff --git a/source/gameengine/Ketsji/KX_PythonMain.cpp b/source/gameengine/Ketsji/KX_PythonMain.cpp
index d5550ce4380..d926dff0bf5 100644
--- a/source/gameengine/Ketsji/KX_PythonMain.cpp
+++ b/source/gameengine/Ketsji/KX_PythonMain.cpp
@@ -26,7 +26,7 @@
  *
  * ***** END GPL LICENSE BLOCK *****
  */
-/** \file gameengine/Ketsji/KX_KetsjiPythonMain.cpp
+/** \file gameengine/Ketsji/KX_PythonMain.cpp
  *  \ingroup ketsji
  */
 

From 8cc17be2746f74ea10a0bf9d3e7091ef6bb3c30c Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Thu, 6 Sep 2012 16:06:55 +0000
Subject: [PATCH 119/160] Merging r50450 through r50454 from trunk into
 soc-2011-tomato

---
 source/blender/bmesh/operators/bmo_subdivide.c    | 2 +-
 source/blender/editors/space_view3d/view3d_draw.c | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c
index 23526d7498b..b239be1c83b 100644
--- a/source/blender/bmesh/operators/bmo_subdivide.c
+++ b/source/blender/bmesh/operators/bmo_subdivide.c
@@ -995,7 +995,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
 					BMIter other_fiter;
 					BM_ITER_ELEM (other_loop, &other_fiter, loops[a]->v, BM_LOOPS_OF_VERT) {
 						if (other_loop->f != face) {
-							if (BM_vert_in_face(other_loop->f, loops[a]->v)) {
+							if (BM_vert_in_face(other_loop->f, loops[b]->v)) {
 								/* we assume that these verts are not making an edge in the face */
 								BLI_assert(other_loop->prev->v != loops[a]->v);
 								BLI_assert(other_loop->next->v != loops[a]->v);
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 97130390c14..85d8b386f52 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -2836,8 +2836,8 @@ static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar, int draw
 
 		engine = RE_engine_create(type);
 
-		engine->tile_x = scene->r.xparts;
-		engine->tile_y = scene->r.yparts;
+		engine->tile_x = ceil(ar->winx/(float)scene->r.xparts);
+		engine->tile_y = ceil(ar->winy/(float)scene->r.yparts);
 
 		type->view_update(engine, C);
 

From 0325c727993887643032536484592057fc970b4f Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Thu, 6 Sep 2012 16:44:27 +0000
Subject: [PATCH 120/160] Merging r50455 through r50456 from trunk into
 soc-2011-tomato

---
 intern/cycles/kernel/kernel_types.h | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 7faa1323258..06babe78493 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -19,11 +19,11 @@
 #ifndef __KERNEL_TYPES_H__
 #define __KERNEL_TYPES_H__
 
+#include 
+
 #include "kernel_math.h"
 #include "svm/svm_types.h"
 
-#include "util_string.h"
-
 #ifndef __KERNEL_GPU__
 #define __KERNEL_CPU__
 #endif
@@ -370,28 +370,28 @@ typedef enum AttributeStandard {
 	ATTR_STD_NOT_FOUND = ~0
 } AttributeStandard;
 
-__device string attribute_standard_name(AttributeStandard std)
+__device std::string attribute_standard_name(AttributeStandard std)
 {
 	if(std == ATTR_STD_VERTEX_NORMAL)
-		return string("N");
+		return std::string("N");
 	else if(std == ATTR_STD_FACE_NORMAL)
-		return string("Ng");
+		return std::string("Ng");
 	else if(std == ATTR_STD_UV)
-		return string("uv");
+		return std::string("uv");
 	else if(std == ATTR_STD_GENERATED)
-		return string("generated");
+		return std::string("generated");
 	else if(std == ATTR_STD_POSITION_UNDEFORMED)
-		return string("undeformed");
+		return std::string("undeformed");
 	else if(std == ATTR_STD_POSITION_UNDISPLACED)
-		return string("undisplaced");
+		return std::string("undisplaced");
 	else if(std == ATTR_STD_MOTION_PRE)
-		return string("motion_pre");
+		return std::string("motion_pre");
 	else if(std == ATTR_STD_MOTION_POST)
-		return string("motion_post");
+		return std::string("motion_post");
 	else if(std == ATTR_STD_PARTICLE)
-		return string("particle");
+		return std::string("particle");
 	
-	return string();
+	return std::string();
 }
 
 /* Closure data */

From a913101b4bd2369d757d623b70ab7477874d8849 Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Fri, 7 Sep 2012 09:44:22 +0000
Subject: [PATCH 121/160] Tomato: alignment issue fix

There were alignment issues on 32bit systems caused by 64bit integer
used in Scene.
---
 source/blender/makesdna/DNA_color_types.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h
index 560caa40cff..dfba83618dc 100644
--- a/source/blender/makesdna/DNA_color_types.h
+++ b/source/blender/makesdna/DNA_color_types.h
@@ -166,6 +166,7 @@ typedef struct ColorManagedViewSettings {
 	float exposure;            /* fstop exposure */
 	float gamma;               /* post-display gamma transform */
 	struct CurveMapping *curve_mapping;  /* pre-display RGB curves transform */
+	void *pad2;
 } ColorManagedViewSettings;
 
 typedef struct ColorManagedDisplaySettings {

From 62076905a3e732e331a9c6a157f861a09b4ebbec Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Fri, 7 Sep 2012 12:53:41 +0000
Subject: [PATCH 122/160] Merging r50457 through r50469 from trunk into
 soc-2011-tomato

---
 intern/cycles/kernel/CMakeLists.txt           |   1 +
 intern/cycles/kernel/kernel_attribute.h       |  68 ++++++++
 intern/cycles/kernel/kernel_triangle.h        |  42 +----
 intern/cycles/kernel/kernel_types.h           |  42 -----
 intern/cycles/render/attribute.h              |   1 +
 intern/cycles/render/mesh.cpp                 |   2 +-
 intern/cycles/render/scene.h                  |   1 +
 intern/cycles/util/CMakeLists.txt             |   2 +
 intern/cycles/util/util_attribute.cpp         |  47 ++++++
 intern/cycles/util/util_attribute.h           |  31 ++++
 intern/cycles/util/util_types.h               |  16 ++
 .../startup/bl_ui/space_view3d_toolbar.py     |   1 +
 source/blender/editors/armature/poseobject.c  |   8 +-
 source/blender/editors/include/ED_mesh.h      | 144 ++++++++--------
 source/blender/editors/include/ED_screen.h    |   1 +
 source/blender/editors/mesh/editface.c        |  41 +----
 source/blender/editors/mesh/editmesh_bvh.c    |   9 +-
 source/blender/editors/mesh/editmesh_rip.c    |  52 ++++--
 source/blender/editors/mesh/editmesh_select.c |   2 +-
 source/blender/editors/mesh/editmesh_slide.c  |   3 +
 source/blender/editors/mesh/editmesh_tools.c  |   6 +-
 source/blender/editors/mesh/editmesh_utils.c  |   2 +-
 source/blender/editors/mesh/mesh_intern.h     |   2 -
 source/blender/editors/mesh/meshtools.c       | 125 +++++++++++++-
 .../editors/object/object_constraint.c        |  12 +-
 .../blender/editors/physics/particle_edit.c   |   4 +-
 source/blender/editors/screen/screen_ops.c    |  23 +++
 .../editors/sculpt_paint/paint_utils.c        |   4 +-
 .../editors/sculpt_paint/paint_vertex.c       | 157 +++++++++---------
 source/blender/editors/sculpt_paint/sculpt.c  |   6 +-
 .../editors/space_view3d/view3d_draw.c        |   9 +-
 .../editors/space_view3d/view3d_edit.c        |   4 +-
 .../editors/space_view3d/view3d_select.c      |  40 +----
 .../editors/space_view3d/view3d_view.c        |   3 +-
 source/blender/editors/transform/transform.c  |   4 +-
 35 files changed, 560 insertions(+), 355 deletions(-)
 create mode 100644 intern/cycles/kernel/kernel_attribute.h
 create mode 100644 intern/cycles/util/util_attribute.cpp
 create mode 100644 intern/cycles/util/util_attribute.h

diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index c26954e23b6..b43aca24496 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -16,6 +16,7 @@ set(SRC
 set(SRC_HEADERS
 	kernel.h
 	kernel_accumulate.h
+	kernel_attribute.h
 	kernel_bvh.h
 	kernel_camera.h
 	kernel_compat_cpu.h
diff --git a/intern/cycles/kernel/kernel_attribute.h b/intern/cycles/kernel/kernel_attribute.h
new file mode 100644
index 00000000000..115de2fdbdb
--- /dev/null
+++ b/intern/cycles/kernel/kernel_attribute.h
@@ -0,0 +1,68 @@
+/*
+ * 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 __KERNEL_ATTRIBUTE_CL__
+#define __KERNEL_ATTRIBUTE_CL__
+
+#include "util_types.h"
+
+#ifdef __OSL__
+#include 
+#include "util_attribute.h"
+#endif
+
+CCL_NAMESPACE_BEGIN
+
+/* note: declared in kernel.h, have to add it here because kernel.h is not available */
+bool kernel_osl_use(KernelGlobals *kg);
+
+__device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id)
+{
+
+#ifdef __OSL__
+	if (kernel_osl_use(kg)) {
+		/* for OSL, a hash map is used to lookup the attribute by name. */
+		OSLGlobals::AttributeMap &attr_map = kg->osl.attribute_map[sd->object];
+		ustring stdname(std::string("std::") + std::string(attribute_standard_name((AttributeStandard)id)));
+		OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname);
+		if (it != attr_map.end()) {
+			const OSLGlobals::Attribute &osl_attr = it->second;
+			/* return result */
+			return (osl_attr.elem == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : osl_attr.offset;
+		}
+		else
+			return (int)ATTR_STD_NOT_FOUND;
+	}
+	else
+#endif
+	{
+		/* for SVM, find attribute by unique id */
+		uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
+		uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
+		
+		while(attr_map.x != id)
+			attr_map = kernel_tex_fetch(__attributes_map, ++attr_offset);
+		
+		/* return result */
+		return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : attr_map.z;
+	}
+}
+
+CCL_NAMESPACE_END
+
+#endif /* __KERNEL_ATTRIBUTE_CL__ */
diff --git a/intern/cycles/kernel/kernel_triangle.h b/intern/cycles/kernel/kernel_triangle.h
index 901034cfac6..f57c59a45eb 100644
--- a/intern/cycles/kernel/kernel_triangle.h
+++ b/intern/cycles/kernel/kernel_triangle.h
@@ -16,6 +16,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
+#include "kernel_attribute.h"
 #include "kernel_projection.h"
 
 CCL_NAMESPACE_BEGIN
@@ -183,48 +184,13 @@ __device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData *s
 
 /* motion */
 
-/* note: declared in kernel.h, have to add it here because kernel.h is not available */
-bool kernel_osl_use(KernelGlobals *kg);
-
-__device int triangle_find_attribute(KernelGlobals *kg, ShaderData *sd, uint id)
-{
-
-#ifdef __OSL__
-	if (kernel_osl_use(kg)) {
-		/* for OSL, a hash map is used to lookup the attribute by name. */
-		OSLGlobals::AttributeMap &attr_map = kg->osl.attribute_map[sd->object];
-		ustring stdname = ustring(std::string("std::") + attribute_standard_name((AttributeStandard)id).c_str());
-		OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname);
-		if (it != attr_map.end()) {
-			const OSLGlobals::Attribute &osl_attr = it->second;
-			/* return result */
-			return (osl_attr.elem == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : osl_attr.offset;
-		}
-		else
-			return (int)ATTR_STD_NOT_FOUND;
-	}
-	else
-#endif
-	{
-		/* for SVM, find attribute by unique id */
-		uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
-		uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
-		
-		while(attr_map.x != id)
-			attr_map = kernel_tex_fetch(__attributes_map, ++attr_offset);
-		
-		/* return result */
-		return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : attr_map.z;
-	}
-}
-
 __device float4 triangle_motion_vector(KernelGlobals *kg, ShaderData *sd)
 {
 	float3 motion_pre = sd->P, motion_post = sd->P;
 
 	/* deformation motion */
-	int offset_pre = triangle_find_attribute(kg, sd, ATTR_STD_MOTION_PRE);
-	int offset_post = triangle_find_attribute(kg, sd, ATTR_STD_MOTION_POST);
+	int offset_pre = find_attribute(kg, sd, ATTR_STD_MOTION_PRE);
+	int offset_post = find_attribute(kg, sd, ATTR_STD_MOTION_POST);
 
 	if(offset_pre != ATTR_STD_NOT_FOUND)
 		motion_pre = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_pre, NULL, NULL);
@@ -283,7 +249,7 @@ __device float4 triangle_motion_vector(KernelGlobals *kg, ShaderData *sd)
 
 __device float3 triangle_uv(KernelGlobals *kg, ShaderData *sd)
 {
-	int offset_uv = triangle_find_attribute(kg, sd, ATTR_STD_UV);
+	int offset_uv = find_attribute(kg, sd, ATTR_STD_UV);
 
 	if(offset_uv == ATTR_STD_NOT_FOUND)
 		return make_float3(0.0f, 0.0f, 0.0f);
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 06babe78493..ce21ab994f0 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -19,8 +19,6 @@
 #ifndef __KERNEL_TYPES_H__
 #define __KERNEL_TYPES_H__
 
-#include 
-
 #include "kernel_math.h"
 #include "svm/svm_types.h"
 
@@ -354,46 +352,6 @@ typedef enum AttributeElement {
 	ATTR_ELEMENT_NONE
 } AttributeElement;
 
-typedef enum AttributeStandard {
-	ATTR_STD_NONE = 0,
-	ATTR_STD_VERTEX_NORMAL,
-	ATTR_STD_FACE_NORMAL,
-	ATTR_STD_UV,
-	ATTR_STD_GENERATED,
-	ATTR_STD_POSITION_UNDEFORMED,
-	ATTR_STD_POSITION_UNDISPLACED,
-	ATTR_STD_MOTION_PRE,
-	ATTR_STD_MOTION_POST,
-	ATTR_STD_PARTICLE,
-	ATTR_STD_NUM,
-
-	ATTR_STD_NOT_FOUND = ~0
-} AttributeStandard;
-
-__device std::string attribute_standard_name(AttributeStandard std)
-{
-	if(std == ATTR_STD_VERTEX_NORMAL)
-		return std::string("N");
-	else if(std == ATTR_STD_FACE_NORMAL)
-		return std::string("Ng");
-	else if(std == ATTR_STD_UV)
-		return std::string("uv");
-	else if(std == ATTR_STD_GENERATED)
-		return std::string("generated");
-	else if(std == ATTR_STD_POSITION_UNDEFORMED)
-		return std::string("undeformed");
-	else if(std == ATTR_STD_POSITION_UNDISPLACED)
-		return std::string("undisplaced");
-	else if(std == ATTR_STD_MOTION_PRE)
-		return std::string("motion_pre");
-	else if(std == ATTR_STD_MOTION_POST)
-		return std::string("motion_post");
-	else if(std == ATTR_STD_PARTICLE)
-		return std::string("particle");
-	
-	return std::string();
-}
-
 /* Closure data */
 
 #define MAX_CLOSURE 8
diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h
index e95bf42f6ae..d05952edfd7 100644
--- a/intern/cycles/render/attribute.h
+++ b/intern/cycles/render/attribute.h
@@ -21,6 +21,7 @@
 
 #include "kernel_types.h"
 
+#include "util_attribute.h"
 #include "util_list.h"
 #include "util_param.h"
 #include "util_types.h"
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index 1d9683f25cc..7037e36f313 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -366,7 +366,7 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vectorattribute_map[i][stdname] = osl_attr;
 			}
 			else if(req.name != ustring()) {
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index f6c1ef44146..09087fb2970 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -25,6 +25,7 @@
 
 #include "kernel_types.h"
 
+#include "util_attribute.h"
 #include "util_param.h"
 #include "util_string.h"
 #include "util_thread.h"
diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt
index 87bd84b4e0f..ae8403a14a8 100644
--- a/intern/cycles/util/CMakeLists.txt
+++ b/intern/cycles/util/CMakeLists.txt
@@ -6,6 +6,7 @@ set(INC
 )
 
 set(SRC
+	util_attribute.cpp
 	util_cache.cpp
 	util_cuda.cpp
 	util_dynlib.cpp
@@ -29,6 +30,7 @@ endif()
 set(SRC_HEADERS
 	util_algorithm.h
 	util_args.h
+	util_attribute.h
 	util_boundbox.h
 	util_cache.h
 	util_cuda.h
diff --git a/intern/cycles/util/util_attribute.cpp b/intern/cycles/util/util_attribute.cpp
new file mode 100644
index 00000000000..3a1c2b6f332
--- /dev/null
+++ b/intern/cycles/util/util_attribute.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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 "util_attribute.h"
+
+CCL_NAMESPACE_BEGIN
+
+const char *attribute_standard_name(AttributeStandard std)
+{
+	if(std == ATTR_STD_VERTEX_NORMAL)
+		return "N";
+	else if(std == ATTR_STD_FACE_NORMAL)
+		return "Ng";
+	else if(std == ATTR_STD_UV)
+		return "uv";
+	else if(std == ATTR_STD_GENERATED)
+		return "generated";
+	else if(std == ATTR_STD_POSITION_UNDEFORMED)
+		return "undeformed";
+	else if(std == ATTR_STD_POSITION_UNDISPLACED)
+		return "undisplaced";
+	else if(std == ATTR_STD_MOTION_PRE)
+		return "motion_pre";
+	else if(std == ATTR_STD_MOTION_POST)
+		return "motion_post";
+	else if(std == ATTR_STD_PARTICLE)
+		return "particle";
+	
+	return "";
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_attribute.h b/intern/cycles/util/util_attribute.h
new file mode 100644
index 00000000000..334864c7f44
--- /dev/null
+++ b/intern/cycles/util/util_attribute.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 __UTIL_ATTRIBUTE_H__
+#define __UTIL_ATTRIBUTE_H__
+
+#include "util_types.h"
+
+CCL_NAMESPACE_BEGIN
+
+const char *attribute_standard_name(AttributeStandard std);
+
+CCL_NAMESPACE_END
+
+#endif /* __UTIL_ATTRIBUTE_H__ */
+
diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h
index 0451d877c45..5c6b9d5bb78 100644
--- a/intern/cycles/util/util_types.h
+++ b/intern/cycles/util/util_types.h
@@ -444,6 +444,22 @@ __device_inline int4 make_int4(const float3& f)
 
 #endif
 
+typedef enum AttributeStandard {
+	ATTR_STD_NONE = 0,
+	ATTR_STD_VERTEX_NORMAL,
+	ATTR_STD_FACE_NORMAL,
+	ATTR_STD_UV,
+	ATTR_STD_GENERATED,
+	ATTR_STD_POSITION_UNDEFORMED,
+	ATTR_STD_POSITION_UNDISPLACED,
+	ATTR_STD_MOTION_PRE,
+	ATTR_STD_MOTION_POST,
+	ATTR_STD_PARTICLE,
+	ATTR_STD_NUM,
+
+	ATTR_STD_NOT_FOUND = ~0
+} AttributeStandard;
+
 CCL_NAMESPACE_END
 
 #endif /* __UTIL_TYPES_H__ */
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 2c1e963dcfe..1b67b30d17a 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -980,6 +980,7 @@ class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
 
         col = layout.column()
 
+        col.prop(wpaint, "use_all_faces")
         col.prop(wpaint, "use_normal")
         col.prop(wpaint, "use_spray")
         col.prop(wpaint, "use_group_restrict")
diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c
index cd2ca16fec5..e4f1e6d3e8b 100644
--- a/source/blender/editors/armature/poseobject.c
+++ b/source/blender/editors/armature/poseobject.c
@@ -274,7 +274,7 @@ void POSE_OT_paths_calculate(wmOperatorType *ot)
 	/* api callbacks */
 	ot->invoke = pose_calculate_paths_invoke;
 	ot->exec = pose_calculate_paths_exec;
-	ot->poll = ED_operator_posemode;
+	ot->poll = ED_operator_posemode_exclusive;
 	
 	/* flags */
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -319,7 +319,7 @@ void POSE_OT_paths_update(wmOperatorType *ot)
 	
 	/* api callbakcs */
 	ot->exec = pose_update_paths_exec;
-	ot->poll = ED_operator_posemode; /* TODO: this should probably check for active bone and/or existing paths */
+	ot->poll = ED_operator_posemode_exclusive; /* TODO: this should probably check for active bone and/or existing paths */
 	
 	/* flags */
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -380,7 +380,7 @@ void POSE_OT_paths_clear(wmOperatorType *ot)
 	
 	/* api callbacks */
 	ot->exec = pose_clear_paths_exec;
-	ot->poll = ED_operator_posemode;
+	ot->poll = ED_operator_posemode_exclusive;
 	
 	/* flags */
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -2192,7 +2192,7 @@ void POSE_OT_bone_layers(wmOperatorType *ot)
 	/* callbacks */
 	ot->invoke = pose_bone_layers_invoke;
 	ot->exec = pose_bone_layers_exec;
-	ot->poll = ED_operator_posemode;
+	ot->poll = ED_operator_posemode_exclusive;
 	
 	/* flags */
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index c25401d570f..1d4fbe81e02 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -71,14 +71,8 @@ struct Material;
 struct Object;
 struct rcti;
 
-intptr_t    mesh_octree_table(struct Object *ob, struct BMEditMesh *em, const float co[3], char mode);
-int         mesh_mirrtopo_table(struct Object *ob, char mode);
 
 /* editmesh_utils.c */
-
-/* retrieves mirrored cache vert, or NULL if there isn't one.
- * note: calling this without ensuring the mirror cache state
- * is bad.*/
 void           EDBM_verts_mirror_cache_begin(struct BMEditMesh *em, const short use_select); /* note, replaces EM_cache_x_mirror_vert in trunk */
 void           EDBM_verts_mirror_apply(struct BMEditMesh *em, const int sel_from, const int sel_to);
 struct BMVert *EDBM_verts_mirror_get(struct BMEditMesh *em, struct BMVert *v);
@@ -86,7 +80,9 @@ void           EDBM_verts_mirror_cache_clear(struct BMEditMesh *em, struct BMVer
 void           EDBM_verts_mirror_cache_end(struct BMEditMesh *em);
 
 void EDBM_mesh_normals_update(struct BMEditMesh *em);
+void EDBM_mesh_clear(struct BMEditMesh *em);
 
+void EDBM_selectmode_to_scene(struct bContext *C);
 void EDBM_mesh_make(struct ToolSettings *ts, struct Scene *scene, struct Object *ob);
 void EDBM_mesh_free(struct BMEditMesh *tm);
 void EDBM_mesh_load(struct Object *ob);
@@ -110,27 +106,15 @@ void EDBM_selectmode_flush(struct BMEditMesh *em);
 void EDBM_deselect_flush(struct BMEditMesh *em);
 void EDBM_select_flush(struct BMEditMesh *em);
 
-void EDBM_selectmode_set(struct BMEditMesh *em);
-void EDBM_selectmode_convert(struct BMEditMesh *em, short oldmode, const short selectmode);
 void undo_push_mesh(struct bContext *C, const char *name);
 
 int  EDBM_vert_color_check(struct BMEditMesh *em);
 
-
 void EDBM_mesh_hide(struct BMEditMesh *em, int swap);
 void EDBM_mesh_reveal(struct BMEditMesh *em);
 
 void EDBM_update_generic(struct bContext *C, struct BMEditMesh *em, const short do_tessface);
 
-int  EDBM_backbuf_check(unsigned int index);
-int EDBM_backbuf_border_mask_init(struct ViewContext *vc, int mcords[][2], short tot,
-                                  short xmin, short ymin, short xmax, short ymax);
-void EDBM_backbuf_free(void);
-int  EDBM_backbuf_border_init(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
-int  EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads);
-
-void EDBM_deselect_by_material(struct BMEditMesh *em, const short index, const short select);
-
 struct UvElementMap *EDBM_uv_element_map_create(struct BMEditMesh *em, int selected, int doIslands);
 void                 EDBM_uv_element_map_free(struct UvElementMap *vmap);
 
@@ -141,60 +125,86 @@ void              EDBM_uv_vert_map_free(struct UvVertMap *vmap);
 struct UvMapVert *EDBM_uv_vert_map_at_index(struct UvVertMap *vmap, unsigned int v);
 struct UvVertMap *EDBM_uv_vert_map_create(struct BMEditMesh *em, int selected, int do_face_idx_array, const float limit[2]);
 
-void EDBM_select_toggle_all(struct BMEditMesh *em);
-void EDBM_select_swap(struct BMEditMesh *em); /* exported for UV */
-int  EDBM_select_interior_faces(struct BMEditMesh *em);
-
 void EDBM_flag_enable_all(struct BMEditMesh *em, const char hflag);
 void EDBM_flag_disable_all(struct BMEditMesh *em, const char hflag);
+
+
+/* editmesh_select.c */
 void EDBM_select_mirrored(struct Object *obedit, struct BMEditMesh *em, int extend);
 void EDBM_automerge(struct Scene *scene, struct Object *ob, int update);
 
-/* editmesh_mods.c */
+int  EDBM_backbuf_border_init(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
+int  EDBM_backbuf_check(unsigned int index);
+void EDBM_backbuf_free(void);
+
+int  EDBM_backbuf_border_mask_init(struct ViewContext *vc, int mcords[][2], short tot,
+                                   short xmin, short ymin, short xmax, short ymax);
+int  EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads);
+
+struct BMVert *EDBM_vert_find_nearest(struct ViewContext *vc, int *dist, short sel, short strict);
+struct BMEdge *EDBM_edge_find_nearest(struct ViewContext *vc, int *dist);
+struct BMFace *EDBM_face_find_nearest(struct ViewContext *vc, int *dist);
+
+int  EDBM_select_pick(struct bContext *C, const int mval[2], short extend, short deselect, short toggle);
+
+void EDBM_selectmode_set(struct BMEditMesh *em);
+void EDBM_selectmode_convert(struct BMEditMesh *em, short oldmode, const short selectmode);
+
+void EDBM_deselect_by_material(struct BMEditMesh *em, const short index, const short select);
+
+void EDBM_select_toggle_all(struct BMEditMesh *em);
+
+void EDBM_select_swap(struct BMEditMesh *em); /* exported for UV */
+int  EDBM_select_interior_faces(struct BMEditMesh *em);
+void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc);  /* rename? */
+
 extern unsigned int bm_vertoffs, bm_solidoffs, bm_wireoffs;
 
-int         mouse_mesh(struct bContext *C, const int mval[2], short extend, short deselect, short toggle);
-
-struct BMVert *editbmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh *em, struct BMVert *eve, const float co[3], int index);
-int            mesh_get_x_mirror_vert(struct Object *ob, int index);
-int           *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em);
-
-int         join_mesh_exec(struct bContext *C, struct wmOperator *op);
-int         join_mesh_shapes_exec(struct bContext *C, struct wmOperator *op);
 
 /* mesh_ops.c */
 void        ED_operatortypes_mesh(void);
 void        ED_operatormacros_mesh(void);
 void        ED_keymap_mesh(struct wmKeyConfig *keyconf);
-
-
-/* editmesh.c */
-
-void        ED_spacetypes_init(void);
 void        ED_keymap_mesh(struct wmKeyConfig *keyconf);
 
-/* bmesh_mods.c */
-extern unsigned int bm_vertoffs, bm_solidoffs, bm_wireoffs;
 
-/* bmesh_tools.c (could be moved) */
+/* spacetypes.c */
+void        ED_spacetypes_init(void);
+
+
+/* editmesh_tools.c (could be moved) */
 void EMBM_project_snap_verts(struct bContext *C, struct ARegion *ar, struct Object *obedit, struct BMEditMesh *em);
 
+
 /* editface.c */
 void paintface_flush_flags(struct Object *ob);
-int paintface_mouse_select(struct bContext *C, struct Object *ob, const int mval[2], int extend, int deselect, int toggle);
-int do_paintface_box_select(struct ViewContext *vc, struct rcti *rect, int select, int extend);
+int  paintface_mouse_select(struct bContext *C, struct Object *ob, const int mval[2], int extend, int deselect, int toggle);
+int  do_paintface_box_select(struct ViewContext *vc, struct rcti *rect, int select, int extend);
 void paintface_deselect_all_visible(struct Object *ob, int action, short flush_flags);
 void paintface_select_linked(struct bContext *C, struct Object *ob, int mval[2], int mode);
-int paintface_minmax(struct Object *ob, float r_min[3], float r_max[3]);
+int  paintface_minmax(struct Object *ob, float r_min[3], float r_max[3]);
 
 void paintface_hide(struct Object *ob, const int unselected);
 void paintface_reveal(struct Object *ob);
 
 void paintvert_deselect_all_visible(struct Object *ob, int action, short flush_flags);
-void        paintvert_flush_flags(struct Object *ob);
+void paintvert_flush_flags(struct Object *ob);
+
+/* mirrtopo */
+typedef struct MirrTopoStore_t {
+	intptr_t *index_lookup;
+	int prev_vert_tot;
+	int prev_edge_tot;
+	int prev_ob_mode;
+} MirrTopoStore_t;
+
+int  ED_mesh_mirrtopo_recalc_check(struct Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store);
+void ED_mesh_mirrtopo_init(struct Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store,
+                           const short skip_em_vert_array_init);
+void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store);
+
 
 /* object_vgroup.c */
-
 #define WEIGHT_REPLACE 1
 #define WEIGHT_ADD 2
 #define WEIGHT_SUBTRACT 3
@@ -215,9 +225,6 @@ void                 ED_vgroup_vert_add(struct Object *ob, struct bDeformGroup *
 void                 ED_vgroup_vert_remove(struct Object *ob, struct bDeformGroup *dg, int vertnum);
 float                ED_vgroup_vert_weight(struct Object *ob, struct bDeformGroup *dg, int vertnum);
 
-struct BMVert *EDBM_vert_find_nearest(struct ViewContext *vc, int *dist, short sel, short strict);
-struct BMEdge *EDBM_edge_find_nearest(struct ViewContext *vc, int *dist);
-struct BMFace *EDBM_face_find_nearest(struct ViewContext *vc, int *dist);
 
 /* mesh_data.c */
 // void ED_mesh_geometry_add(struct Mesh *mesh, struct ReportList *reports, int verts, int edges, int faces);
@@ -245,25 +252,6 @@ int ED_mesh_color_add(struct bContext *C, struct Scene *scene, struct Object *ob
 int ED_mesh_color_remove(struct bContext *C, struct Object *ob, struct Mesh *me);
 int ED_mesh_color_remove_named(struct bContext *C, struct Object *ob, struct Mesh *me, const char *name);
 
-void EDBM_selectmode_to_scene(struct bContext *C);
-void EDBM_mesh_clear(struct BMEditMesh *em);
-
-#include "../mesh/editmesh_bvh.h"
-
-
-/* mirrtopo */
-typedef struct MirrTopoStore_t {
-	intptr_t *index_lookup;
-	int prev_vert_tot;
-	int prev_edge_tot;
-	int prev_ob_mode;
-} MirrTopoStore_t;
-
-int  ED_mesh_mirrtopo_recalc_check(struct Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store);
-void ED_mesh_mirrtopo_init(struct Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store,
-                           const short skip_em_vert_array_init);
-void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store);
-
 /* mesh backup */
 typedef struct BMBackup {
 	struct BMesh *bmcopy;
@@ -276,6 +264,30 @@ void EDBM_redo_state_restore(struct BMBackup, struct BMEditMesh *em, int recalct
 /* delete the backup, optionally flushing it to an editmesh */
 void EDBM_redo_state_free(struct BMBackup *, struct BMEditMesh *em, int recalctess);
 
+
+/* meshtools.c */
+int         join_mesh_exec(struct bContext *C, struct wmOperator *op);
+int         join_mesh_shapes_exec(struct bContext *C, struct wmOperator *op);
+
+intptr_t    mesh_octree_table(struct Object *ob, struct BMEditMesh *em, const float co[3], char mode);
+int         mesh_mirrtopo_table(struct Object *ob, char mode);
+
+/* retrieves mirrored cache vert, or NULL if there isn't one.
+ * note: calling this without ensuring the mirror cache state
+ * is bad.*/
+int            mesh_get_x_mirror_vert(struct Object *ob, int index);
+struct BMVert *editbmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh *em, struct BMVert *eve, const float co[3], int index);
+int           *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em);
+
+int ED_mesh_pick_vert(struct bContext *C, struct Mesh *me, const int mval[2], unsigned int *index, int size);
+int ED_mesh_pick_face(struct bContext *C, struct Mesh *me, const int mval[2], unsigned int *index, int size);
+int ED_mesh_pick_face_vert(struct bContext *C, struct Mesh *me, struct Object *ob, const int mval[2], unsigned int *index, int size);
+
+#define ED_MESH_PICK_DEFAULT_VERT_SIZE 50
+#define ED_MESH_PICK_DEFAULT_FACE_SIZE 3
+
+#include "../mesh/editmesh_bvh.h"
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 4faf82eec36..fc20bdfb9c5 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -169,6 +169,7 @@ int     ED_operator_editlattice(struct bContext *C);
 int     ED_operator_editmball(struct bContext *C);
 int     ED_operator_uvedit(struct bContext *C);
 int     ED_operator_uvmap(struct bContext *C);
+int     ED_operator_posemode_exclusive(struct bContext *C);
 int     ED_operator_posemode(struct bContext *C);
 int     ED_operator_mask(struct bContext *C);
 
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 3431bea18ea..4e30cff5fde 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -123,43 +123,6 @@ void paintface_flush_flags(Object *ob)
 	}
 }
 
-/* returns 0 if not found, otherwise 1 */
-static int facesel_face_pick(struct bContext *C, Mesh *me, Object *ob, const int mval[2], unsigned int *index, short rect)
-{
-	Scene *scene = CTX_data_scene(C);
-	ViewContext vc;
-	view3d_set_viewcontext(C, &vc);
-
-	if (!me || me->totpoly == 0)
-		return 0;
-
-	makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH, 0);
-
-	// XXX  if (v3d->flag & V3D_INVALID_BACKBUF) {
-// XXX drawview.c!		check_backbuf();
-// XXX		persp(PERSP_VIEW);
-// XXX  }
-
-	if (rect) {
-		/* sample rect to increase changes of selecting, so that when clicking
-		 * on an edge in the backbuf, we can still select a face */
-
-		int dist;
-		*index = view3d_sample_backbuf_rect(&vc, mval, 3, 1, me->totpoly + 1, &dist, 0, NULL, NULL);
-	}
-	else {
-		/* sample only on the exact position */
-		*index = view3d_sample_backbuf(&vc, mval[0], mval[1]);
-	}
-
-	if ((*index) <= 0 || (*index) > (unsigned int)me->totpoly)
-		return 0;
-
-	(*index)--;
-	
-	return 1;
-}
-
 void paintface_hide(Object *ob, const int unselected)
 {
 	Mesh *me;
@@ -331,7 +294,7 @@ void paintface_select_linked(bContext *UNUSED(C), Object *ob, int UNUSED(mval[2]
 	if (mode == 0 || mode == 1) {
 		/* XXX - Causes glitches, not sure why */
 #if 0
-		if (!facesel_face_pick(C, me, mval, &index, 1))
+		if (!ED_mesh_pick_face(C, me, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE))
 			return;
 #endif
 	}
@@ -518,7 +481,7 @@ int paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], in
 	/* Get the face under the cursor */
 	me = BKE_mesh_from_object(ob);
 
-	if (!facesel_face_pick(C, me, ob, mval, &index, 1))
+	if (!ED_mesh_pick_face(C, me, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE))
 		return 0;
 	
 	if (index >= me->totpoly)
diff --git a/source/blender/editors/mesh/editmesh_bvh.c b/source/blender/editors/mesh/editmesh_bvh.c
index 549032f7286..580592c02f6 100644
--- a/source/blender/editors/mesh/editmesh_bvh.c
+++ b/source/blender/editors/mesh/editmesh_bvh.c
@@ -49,6 +49,7 @@
 #include "ED_mesh.h"
 #include "ED_view3d.h"
 
+#include "editmesh_bvh.h"  /* own include */
 
 typedef struct BMBVHTree {
 	BMEditMesh *em;
@@ -394,15 +395,15 @@ int BMBVH_EdgeVisible(BMBVHTree *tree, BMEdge *e, ARegion *ar, View3D *v3d, Obje
 	float co1[3], co2[3], co3[3], dir1[4], dir2[4], dir3[4];
 	float origin[3], invmat[4][4];
 	float epsilon = 0.01f; 
-	float mval_f[2], end[3];
+	float end[3];
+	const float mval_f[2] = {ar->winx / 2.0f,
+	                         ar->winy / 2.0f};
 	
 	if (!ar) {
 		printf("error in BMBVH_EdgeVisible!\n");
 		return 0;
 	}
-	
-	mval_f[0] = ar->winx / 2.0f;
-	mval_f[1] = ar->winy / 2.0f;
+
 	ED_view3d_win_to_segment_clip(ar, v3d, mval_f, origin, end);
 	
 	invert_m4_m4(invmat, obedit->obmat);
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index 8325e0a50d4..d2806233fa9 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -380,6 +380,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event)
 	float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]};
 	float dist = FLT_MAX;
 	float d;
+	int is_wire;
 
 	BMEditSelection ese;
 	int totboundary_edge = 0;
@@ -403,6 +404,8 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event)
 	if (!v)
 		return OPERATOR_CANCELLED;
 
+	is_wire = BM_vert_is_wire(v);
+
 	e2 = NULL;
 
 	if (v->e) {
@@ -430,8 +433,11 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event)
 	 * - we cant find an edge - this means we are ripping a faces vert that is connected to other
 	 *   geometry only at the vertex.
 	 * - the boundary edge total is greater then 2,
-	 *   in this case edge split _can_ work but we get far nicer results if we use this special case. */
-	if (totboundary_edge > 2) {
+	 *   in this case edge split _can_ work but we get far nicer results if we use this special case.
+	 * - there are only 2 edges but we are a wire vert. */
+	if ((is_wire == FALSE && totboundary_edge > 2) ||
+	    (is_wire == TRUE  && totboundary_edge > 1))
+	{
 		BMVert **vout;
 		int vout_len;
 
@@ -459,20 +465,40 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event)
 			dist = FLT_MAX;
 
 			for (i = 0; i < vout_len; i++) {
-				BM_ITER_ELEM (l, &iter, vout[i], BM_LOOPS_OF_VERT) {
-					if (!BM_elem_flag_test(l->f, BM_ELEM_HIDDEN)) {
-						float l_mid_co[3];
-						BM_loop_calc_face_tangent(l, l_mid_co);
 
-						/* scale to average of surrounding edge size, only needs to be approx */
-						mul_v3_fl(l_mid_co, (BM_edge_calc_length(l->e) + BM_edge_calc_length(l->prev->e)) / 2.0f);
-						add_v3_v3(l_mid_co, v->co);
+				if (BM_vert_is_wire(vout[i]) == FALSE) {
+					/* find the best face corner */
+					BM_ITER_ELEM (l, &iter, vout[i], BM_LOOPS_OF_VERT) {
+						if (!BM_elem_flag_test(l->f, BM_ELEM_HIDDEN)) {
+							float l_mid_co[3];
+							BM_loop_calc_face_tangent(l, l_mid_co);
 
-						d = edbm_rip_rip_edgedist(ar, projectMat, v->co, l_mid_co, fmval);
+							/* scale to average of surrounding edge size, only needs to be approx */
+							mul_v3_fl(l_mid_co, (BM_edge_calc_length(l->e) + BM_edge_calc_length(l->prev->e)) / 2.0f);
+							add_v3_v3(l_mid_co, v->co);
 
-						if (d < dist) {
-							dist = d;
-							vi_best = i;
+							d = edbm_rip_rip_edgedist(ar, projectMat, v->co, l_mid_co, fmval);
+
+							if (d < dist) {
+								dist = d;
+								vi_best = i;
+							}
+						}
+					}
+				}
+				else {
+					/* a wire vert, find the best edge */
+					BM_ITER_ELEM (e, &iter, vout[i], BM_EDGES_OF_VERT) {
+						if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+							float e_mid_co[3];
+							mid_v3_v3v3(e_mid_co, e->v1->co, e->v2->co);
+
+							d = edbm_rip_rip_edgedist(ar, projectMat, v->co, e_mid_co, fmval);
+
+							if (d < dist) {
+								dist = d;
+								vi_best = i;
+							}
 						}
 					}
 				}
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index a9e8c253c82..c8b86354cb8 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -1494,7 +1494,7 @@ void MESH_OT_select_shortest_path(wmOperatorType *ot)
 /* ************************************************** */
 /* here actual select happens */
 /* gets called via generic mouse select operator */
-int mouse_mesh(bContext *C, const int mval[2], short extend, short deselect, short toggle)
+int EDBM_select_pick(bContext *C, const int mval[2], short extend, short deselect, short toggle)
 {
 	ViewContext vc;
 	BMVert *eve = NULL;
diff --git a/source/blender/editors/mesh/editmesh_slide.c b/source/blender/editors/mesh/editmesh_slide.c
index 397f224ef2e..40c1ea7eff2 100644
--- a/source/blender/editors/mesh/editmesh_slide.c
+++ b/source/blender/editors/mesh/editmesh_slide.c
@@ -749,10 +749,13 @@ static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_u
 
 	return OPERATOR_FINISHED;
 }
+
+#if 0
 static int edbm_vertex_slide_exec(bContext *C, wmOperator *op)
 {
 	return edbm_vertex_slide_exec_ex(C, op, TRUE);
 }
+#endif
 
 void MESH_OT_vert_slide(wmOperatorType *ot)
 {
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 92cc3366b3e..546b28bfb25 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -751,10 +751,8 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent
 		float nor[3] = {0.0, 0.0, 0.0};
 
 		/* 2D normal calc */
-		float mval_f[2];
-
-		mval_f[0] = (float)event->mval[0];
-		mval_f[1] = (float)event->mval[1];
+		const float mval_f[2] = {(float)event->mval[0],
+		                         (float)event->mval[1]};
 
 		/* check for edges that are half selected, use for rotation */
 		done = FALSE;
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index a111c2ffafb..290ef3baba3 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -1063,7 +1063,7 @@ void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const short use_select)
 	int li, topo = 0;
 
 	/* one or the other is used depending if topo is enabled */
-	BMBVHTree *tree = NULL;
+	struct BMBVHTree *tree = NULL;
 	MirrTopoStore_t mesh_topo_store = {NULL, -1, -1, -1};
 
 	if (me && (me->editflag & ME_EDIT_MIRROR_TOPO)) {
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index cf17fce2971..41666740730 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -85,8 +85,6 @@ float labda_PdistVL2Dfl(const float v1[3], const float v2[3], const float v3[3])
 
 /* ******************** editface.c */
 
-void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc);
-
 void MESH_OT_separate(struct wmOperatorType *ot);
 
 /* ******************* editmesh_add.c */
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index 2e75a779fed..06dcac0505a 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -42,6 +42,7 @@
 #include "MEM_guardedalloc.h"
 
 #include "DNA_mesh_types.h"
+#include "DNA_view3d_types.h"
 #include "DNA_key_types.h"
 #include "DNA_material_types.h"
 #include "DNA_meshdata_types.h"
@@ -877,7 +878,7 @@ intptr_t mesh_octree_table(Object *ob, BMEditMesh *em, const float co[3], char m
 	return 0;
 }
 
-MirrTopoStore_t mesh_topo_store = {NULL, -1. - 1, -1};
+static MirrTopoStore_t mesh_topo_store = {NULL, -1. - 1, -1};
 
 /* mode is 's' start, or 'e' end, or 'u' use */
 /* if end, ob can be NULL */
@@ -1146,3 +1147,125 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em)
 	
 	return mirrorfaces;
 }
+
+/* selection, vertex and face */
+/* returns 0 if not found, otherwise 1 */
+
+/**
+ * Face selection in object mode,
+ * currently only weight-paint and vertex-paint use this.
+ *
+ * \return boolean TRUE == Found
+ */
+int ED_mesh_pick_face(bContext *C, Mesh *me, const int mval[2], unsigned int *index, int size)
+{
+	ViewContext vc;
+
+	if (!me || me->totpoly == 0)
+		return 0;
+
+	view3d_set_viewcontext(C, &vc);
+
+	if (size) {
+		/* sample rect to increase chances of selecting, so that when clicking
+		 * on an edge in the backbuf, we can still select a face */
+
+		int dummy_dist;
+		*index = view3d_sample_backbuf_rect(&vc, mval, size, 1, me->totpoly + 1, &dummy_dist, 0, NULL, NULL);
+	}
+	else {
+		/* sample only on the exact position */
+		*index = view3d_sample_backbuf(&vc, mval[0], mval[1]);
+	}
+
+	if ((*index) <= 0 || (*index) > (unsigned int)me->totpoly)
+		return 0;
+
+	(*index)--;
+
+	return 1;
+}
+/**
+ * Use when the back buffer stores face index values. but we want a vert.
+ * This gets the face then finds the closest vertex to mval.
+ */
+int ED_mesh_pick_face_vert(bContext *C, Mesh *me, Object *ob, const int mval[2], unsigned int *index, int size)
+{
+	unsigned int poly_index;
+
+	if (ED_mesh_pick_face(C, me, mval, &poly_index, size)) {
+		Scene *scene = CTX_data_scene(C);
+		struct ARegion *ar = CTX_wm_region(C);
+
+		/* derived mesh to find deformed locations */
+		DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+		int v_idx_best = -1;
+
+		if (dm->getVertCo) {
+			/* find the vert closest to 'mval' */
+			const float mval_f[2] = {(float)mval[0],
+			                         (float)mval[1]};
+			MPoly *mp = &me->mpoly[poly_index];
+			int fidx;
+			float len_best = FLT_MAX;
+
+			fidx = mp->totloop - 1;
+			do {
+				float co[3], sco[2], len;
+				const int v_idx = me->mloop[mp->loopstart + fidx].v;
+				dm->getVertCo(dm, v_idx, co);
+				mul_m4_v3(ob->obmat, co);
+				project_float_noclip(ar, co, sco);
+				len = len_squared_v2v2(mval_f, sco);
+				if (len < len_best) {
+					len_best = len;
+					v_idx_best = v_idx;
+				}
+			} while (fidx--);
+		}
+
+		dm->release(dm);
+
+		if (v_idx_best != -1) {
+			*index = v_idx_best;
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * Vertex selection in object mode,
+ * currently only weight paint uses this.
+ *
+ * \return boolean TRUE == Found
+ */
+int ED_mesh_pick_vert(bContext *C, Mesh *me, const int mval[2], unsigned int *index, int size)
+{
+	ViewContext vc;
+
+	if (!me || me->totvert == 0)
+		return 0;
+
+	view3d_set_viewcontext(C, &vc);
+
+	if (size > 0) {
+		/* sample rect to increase chances of selecting, so that when clicking
+		 * on an face in the backbuf, we can still select a vert */
+
+		int dummy_dist;
+		*index = view3d_sample_backbuf_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist, 0, NULL, NULL);
+	}
+	else {
+		/* sample only on the exact position */
+		*index = view3d_sample_backbuf(&vc, mval[0], mval[1]);
+	}
+
+	if ((*index) <= 0 || (*index) > (unsigned int)me->totvert)
+		return 0;
+
+	(*index)--;
+
+	return 1;
+}
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index be25c79ba25..08ba6a1e682 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -1185,7 +1185,7 @@ void POSE_OT_constraints_clear(wmOperatorType *ot)
 	
 	/* callbacks */
 	ot->exec = pose_constraints_clear_exec;
-	ot->poll = ED_operator_posemode; // XXX - do we want to ensure there are selected bones too?
+	ot->poll = ED_operator_posemode_exclusive; // XXX - do we want to ensure there are selected bones too?
 }
 
 
@@ -1266,7 +1266,7 @@ void POSE_OT_constraints_copy(wmOperatorType *ot)
 	
 	/* api callbacks */
 	ot->exec = pose_constraint_copy_exec;
-	ot->poll = ED_operator_posemode;
+	ot->poll = ED_operator_posemode_exclusive;
 
 	/* flags */
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1661,7 +1661,7 @@ void POSE_OT_constraint_add(wmOperatorType *ot)
 	/* api callbacks */
 	ot->invoke = WM_menu_invoke;
 	ot->exec = pose_constraint_add_exec;
-	ot->poll = ED_operator_posemode;
+	ot->poll = ED_operator_posemode_exclusive;
 	
 	/* flags */
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1680,7 +1680,7 @@ void POSE_OT_constraint_add_with_targets(wmOperatorType *ot)
 	/* api callbacks */
 	ot->invoke = WM_menu_invoke;
 	ot->exec = pose_constraint_add_exec;
-	ot->poll = ED_operator_posemode;
+	ot->poll = ED_operator_posemode_exclusive;
 	
 	/* flags */
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1766,7 +1766,7 @@ void POSE_OT_ik_add(wmOperatorType *ot)
 	/* api callbacks */
 	ot->invoke = pose_ik_add_invoke;
 	ot->exec = pose_ik_add_exec;
-	ot->poll = ED_operator_posemode;
+	ot->poll = ED_operator_posemode_exclusive;
 	
 	/* flags */
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1816,7 +1816,7 @@ void POSE_OT_ik_clear(wmOperatorType *ot)
 	
 	/* api callbacks */
 	ot->exec = pose_ik_clear_exec;
-	ot->poll = ED_operator_posemode;
+	ot->poll = ED_operator_posemode_exclusive;
 	
 	/* flags */
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 72d2d67e081..3ed31abca94 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -3540,7 +3540,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
 			switch (pset->brushtype) {
 				case PE_BRUSH_COMB:
 				{
-					float mval_f[2];
+					const float mval_f[2] = {dx, dy};
 					data.mval= mval;
 					data.rad= (float)brush->size;
 
@@ -3552,8 +3552,6 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
 
 					invert_m4_m4(ob->imat, ob->obmat);
 
-					mval_f[0]= dx;
-					mval_f[1]= dy;
 					ED_view3d_win_to_delta(ar, mval_f, vec);
 					data.dvec= vec;
 
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 823037a7903..9f9d0bab15c 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -349,6 +349,29 @@ int ED_operator_editarmature(bContext *C)
 	return 0;
 }
 
+/**
+ * \brief check for pose mode (no mixed modes)
+ *
+ * We wan't to enable most pose operations in weight paint mode,
+ * when it comes to transforming bones, but managing bomes layers/groups
+ * can be left for pose mode only. (not weight paint mode)
+ */
+int ED_operator_posemode_exclusive(bContext *C)
+{
+	Object *obact = CTX_data_active_object(C);
+
+	if (obact && !(obact->mode & OB_MODE_EDIT)) {
+		Object *obpose;
+		if ((obpose = BKE_object_pose_armature_get(obact))) {
+			if (obact == obpose) {
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+}
+
 int ED_operator_posemode(bContext *C)
 {
 	Object *obact = CTX_data_active_object(C);
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 99bc192042c..df64e1c9d90 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -159,14 +159,12 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3],
 {
 	Object *ob = vc->obact;
 	float delta[3], scale, loc[3];
-	float mval_f[2];
+	const float mval_f[2] = {pixel_radius, 0.0f};
 
 	mul_v3_m4v3(loc, ob->obmat, center);
 
 	initgrabz(vc->rv3d, loc[0], loc[1], loc[2]);
 
-	mval_f[0] = pixel_radius;
-	mval_f[1] = 0.0f;
 	ED_view3d_win_to_delta(vc->ar, mval_f, delta);
 
 	scale = fabsf(mat4_to_scale(ob->obmat));
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index bf948bf9dd8..c52bae215ec 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -1009,52 +1009,34 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, wmEvent *event)
 	me = BKE_mesh_from_object(vc.obact);
 
 	if (me && me->dvert && vc.v3d && vc.rv3d) {
-		int index;
+		const int use_vert_sel = (me->editflag & ME_EDIT_VERT_SEL) != 0;
+		int v_idx_best = -1;
+		unsigned int index;
 
 		view3d_operator_needs_opengl(C);
 
-		index = view3d_sample_backbuf(&vc, event->mval[0], event->mval[1]);
-
-		if (index && index <= me->totpoly) {
-			DerivedMesh *dm = mesh_get_derived_final(vc.scene, vc.obact, CD_MASK_BAREMESH);
-
-			if (dm->getVertCo == NULL) {
+		if (use_vert_sel) {
+			if (ED_mesh_pick_vert(C, me, event->mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE)) {
+				v_idx_best = index;
+			}
+		}
+		else {
+			if (ED_mesh_pick_face_vert(C, me, vc.obact, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
+				v_idx_best = index;
+			}
+			else if (ED_mesh_pick_face(C, me, event->mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
+				/* this relies on knowning the internal worksings of ED_mesh_pick_face_vert() */
 				BKE_report(op->reports, RPT_WARNING, "The modifier used does not support deformed locations");
 			}
-			else {
-				MPoly *mp = ((MPoly *)me->mpoly) + (index - 1);
-				const int vgroup_active = vc.obact->actdef - 1;
-				Scene *scene = vc.scene;
-				ToolSettings *ts = vc.scene->toolsettings;
-				Brush *brush = paint_brush(&ts->wpaint->paint);
-				float mval_f[2];
-				int v_idx_best = -1;
-				int fidx;
-				float len_best = FLT_MAX;
+		}
 
-				mval_f[0] = (float)event->mval[0];
-				mval_f[1] = (float)event->mval[1];
-
-				fidx = mp->totloop - 1;
-				do {
-					float co[3], sco[3], len;
-					const int v_idx = me->mloop[mp->loopstart + fidx].v;
-					dm->getVertCo(dm, v_idx, co);
-					project_float_noclip(vc.ar, co, sco);
-					len = len_squared_v2v2(mval_f, sco);
-					if (len < len_best) {
-						len_best = len;
-						v_idx_best = v_idx;
-					}
-				} while (fidx--);
-
-				if (v_idx_best != -1) { /* should always be valid */
-					float vgroup_weight = defvert_find_weight(&me->dvert[v_idx_best], vgroup_active);
-					BKE_brush_weight_set(scene, brush, vgroup_weight);
-					change = TRUE;
-				}
-			}
-			dm->release(dm);
+		if (v_idx_best != -1) { /* should always be valid */
+			ToolSettings *ts = vc.scene->toolsettings;
+			Brush *brush = paint_brush(&ts->wpaint->paint);
+			const int vgroup_active = vc.obact->actdef - 1;
+			float vgroup_weight = defvert_find_weight(&me->dvert[v_idx_best], vgroup_active);
+			BKE_brush_weight_set(vc.scene, brush, vgroup_weight);
+			change = TRUE;
 		}
 	}
 
@@ -1085,6 +1067,20 @@ void PAINT_OT_weight_sample(wmOperatorType *ot)
 }
 
 /* samples cursor location, and gives menu with vertex groups to activate */
+static int weight_paint_sample_enum_itemf__helper(const MDeformVert *dvert, const int defbase_tot, int *groups)
+{
+	/* this func fills in used vgroup's */
+	int found = FALSE;
+	int i = dvert->totweight;
+	MDeformWeight *dw;
+	for (dw = dvert->dw; i > 0; dw++, i--) {
+		if (dw->def_nr < defbase_tot) {
+			groups[dw->def_nr] = TRUE;
+			found = TRUE;
+		}
+	}
+	return found;
+}
 static EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
 {
 	if (C) {
@@ -1096,56 +1092,57 @@ static EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, PointerRNA
 			view3d_set_viewcontext(C, &vc);
 			me = BKE_mesh_from_object(vc.obact);
 
-			if (me && me->dvert && vc.v3d && vc.rv3d) {
-				int index;
+			if (me && me->dvert && vc.v3d && vc.rv3d && vc.obact->defbase.first) {
+				const int defbase_tot = BLI_countlist(&vc.obact->defbase);
+				const int use_vert_sel = (me->editflag & ME_EDIT_VERT_SEL) != 0;
+				int *groups = MEM_callocN(defbase_tot * sizeof(int), "groups");
+				int found = FALSE;
+				unsigned int index;
+
+				int mval[2] = {win->eventstate->x - vc.ar->winrct.xmin,
+				               win->eventstate->y - vc.ar->winrct.ymin};
 
 				view3d_operator_needs_opengl(C);
 
-				index = view3d_sample_backbuf(&vc, win->eventstate->x - vc.ar->winrct.xmin, win->eventstate->y - vc.ar->winrct.ymin);
-
-				if (index && index <= me->totpoly) {
-					const int defbase_tot = BLI_countlist(&vc.obact->defbase);
-					if (defbase_tot) {
-						MPoly *mp = ((MPoly *)me->mpoly) + (index - 1);
+				if (use_vert_sel) {
+					if (ED_mesh_pick_vert(C, me, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE)) {
+						MDeformVert *dvert = &me->dvert[index];
+						found |= weight_paint_sample_enum_itemf__helper(dvert, defbase_tot, groups);
+					}
+				}
+				else {
+					if (ED_mesh_pick_face(C, me, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
+						MPoly *mp = &me->mpoly[index];
 						unsigned int fidx = mp->totloop - 1;
-						int *groups = MEM_callocN(defbase_tot * sizeof(int), "groups");
-						int found = FALSE;
 
 						do {
-							MDeformVert *dvert = me->dvert + me->mloop[mp->loopstart + fidx].v;
-							int i = dvert->totweight;
-							MDeformWeight *dw;
-							for (dw = dvert->dw; i > 0; dw++, i--) {
-								if (dw->def_nr < defbase_tot) {
-									groups[dw->def_nr] = TRUE;
-									found = TRUE;
-								}
-							}
+							MDeformVert *dvert = &me->dvert[me->mloop[mp->loopstart + fidx].v];
+							found |= weight_paint_sample_enum_itemf__helper(dvert, defbase_tot, groups);
 						} while (fidx--);
+					}
+				}
 
-						if (found == FALSE) {
-							MEM_freeN(groups);
-						}
-						else {
-							EnumPropertyItem *item = NULL, item_tmp = {0};
-							int totitem = 0;
-							int i = 0;
-							bDeformGroup *dg;
-							for (dg = vc.obact->defbase.first; dg && i < defbase_tot; i++, dg = dg->next) {
-								if (groups[i]) {
-									item_tmp.identifier = item_tmp.name = dg->name;
-									item_tmp.value = i;
-									RNA_enum_item_add(&item, &totitem, &item_tmp);
-								}
-							}
-
-							RNA_enum_item_end(&item, &totitem);
-							*free = 1;
-
-							MEM_freeN(groups);
-							return item;
+				if (found == FALSE) {
+					MEM_freeN(groups);
+				}
+				else {
+					EnumPropertyItem *item = NULL, item_tmp = {0};
+					int totitem = 0;
+					int i = 0;
+					bDeformGroup *dg;
+					for (dg = vc.obact->defbase.first; dg && i < defbase_tot; i++, dg = dg->next) {
+						if (groups[i]) {
+							item_tmp.identifier = item_tmp.name = dg->name;
+							item_tmp.value = i;
+							RNA_enum_item_add(&item, &totitem, &item_tmp);
 						}
 					}
+
+					RNA_enum_item_end(&item, &totitem);
+					*free = 1;
+
+					MEM_freeN(groups);
+					return item;
 				}
 			}
 		}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index e2289bc9cfc..210477e3e5a 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -3074,12 +3074,12 @@ void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, int need_
 	/* BMESH ONLY --- at some point we should move sculpt code to use polygons only - but for now it needs tessfaces */
 	BKE_mesh_tessface_ensure(me);
 
-	/* needs to be called after we ensure tessface */
-	dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
-
 	if (!mmd) ss->kb = ob_get_keyblock(ob);
 	else ss->kb = NULL;
 
+	/* needs to be called after we ensure tessface */
+	dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+
 	if (mmd) {
 		ss->multires = mmd;
 		ss->totvert = dm->getNumVerts(dm);
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 85d8b386f52..3f8a69fcc93 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -1389,14 +1389,17 @@ unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y)
 {
 	unsigned int col;
 	
-	if (x >= vc->ar->winx || y >= vc->ar->winy) return 0;
+	if (x >= vc->ar->winx || y >= vc->ar->winy) {
+		return 0;
+	}
+
 	x += vc->ar->winrct.xmin;
 	y += vc->ar->winrct.ymin;
 	
 	view3d_validate_backbuf(vc);
 
-	glReadPixels(x,  y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,  &col);
-	glReadBuffer(GL_BACK);	
+	glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
+	glReadBuffer(GL_BACK);
 	
 	if (ENDIAN_ORDER == B_ENDIAN) {
 		BLI_endian_switch_uint32(&col);
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 5169d823bd8..17f1081f5c4 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -475,8 +475,8 @@ static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event)
 
 	{
 		/* for dolly */
-		float mval_f[2];
-		VECCOPY2D(mval_f, event->mval);
+		const float mval_f[2] = {(float)event->mval[0],
+		                         (float)event->mval[1]};
 		ED_view3d_win_to_vector(vod->ar, mval_f, vod->mousevec);
 	}
 
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index d8e394ab68c..fa431e89d80 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -119,8 +119,8 @@ int view3d_get_view_aligned_coordinate(ViewContext *vc, float fp[3], const int m
 	initgrabz(vc->rv3d, fp[0], fp[1], fp[2]);
 
 	if (mval_cpy[0] != IS_CLIPPED) {
-		float mval_f[2];
-		VECSUB2D(mval_f, mval_cpy, mval);
+		const float mval_f[2] = {(float)(mval_cpy[0] - mval[0]),
+		                         (float)(mval_cpy[1] - mval[1])};
 		ED_view3d_win_to_delta(vc->ar, mval_f, dvec);
 		sub_v3_v3(fp, dvec);
 
@@ -2027,36 +2027,6 @@ void VIEW3D_OT_select_border(wmOperatorType *ot)
 	WM_operator_properties_gesture_border(ot, TRUE);
 }
 
-/* much like facesel_face_pick()*/
-/* returns 0 if not found, otherwise 1 */
-static int vertsel_vert_pick(struct bContext *C, Mesh *me, const int mval[2], unsigned int *index, int size)
-{
-	ViewContext vc;
-	view3d_set_viewcontext(C, &vc);
-
-	if (!me || me->totvert == 0)
-		return 0;
-
-	if (size > 0) {
-		/* sample rect to increase changes of selecting, so that when clicking
-		 * on an face in the backbuf, we can still select a vert */
-
-		int dist;
-		*index = view3d_sample_backbuf_rect(&vc, mval, size, 1, me->totvert + 1, &dist, 0, NULL, NULL);
-	}
-	else {
-		/* sample only on the exact position */
-		*index = view3d_sample_backbuf(&vc, mval[0], mval[1]);
-	}
-
-	if ((*index) <= 0 || (*index) > (unsigned int)me->totvert)
-		return 0;
-
-	(*index)--;
-	
-	return 1;
-}
-
 /* mouse selection in weight paint */
 /* gets called via generic mouse select operator */
 static int mouse_weight_paint_vertex_select(bContext *C, const int mval[2], short extend, short deselect, short toggle, Object *obact)
@@ -2065,8 +2035,8 @@ static int mouse_weight_paint_vertex_select(bContext *C, const int mval[2], shor
 	unsigned int index = 0;
 	MVert *mv;
 
-	if (vertsel_vert_pick(C, me, mval, &index, 50)) {
-		mv = me->mvert + index;
+	if (ED_mesh_pick_vert(C, me, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE)) {
+		mv = &me->mvert[index];
 		if (extend) {
 			mv->flag |= SELECT;
 		}
@@ -2116,7 +2086,7 @@ static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
 
 	if (obedit && object == FALSE) {
 		if (obedit->type == OB_MESH)
-			retval = mouse_mesh(C, event->mval, extend, deselect, toggle);
+			retval = EDBM_select_pick(C, event->mval, extend, deselect, toggle);
 		else if (obedit->type == OB_ARMATURE)
 			retval = mouse_armature(C, event->mval, extend, deselect, toggle);
 		else if (obedit->type == OB_LATTICE)
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index fbbf23beca4..1d40ae280b7 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -87,8 +87,9 @@ void view3d_operator_needs_opengl(const bContext *C)
 void view3d_region_operator_needs_opengl(wmWindow *win, ARegion *ar)
 {
 	/* for debugging purpose, context should always be OK */
-	if ((ar == NULL) || (ar->regiontype != RGN_TYPE_WINDOW))
+	if ((ar == NULL) || (ar->regiontype != RGN_TYPE_WINDOW)) {
 		printf("view3d_region_operator_needs_opengl error, wrong region\n");
+	}
 	else {
 		RegionView3D *rv3d = ar->regiondata;
 		
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index fa7964b31ca..68cc1c8e9b6 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -164,9 +164,7 @@ static void convertViewVec2D_mask(View2D *v2d, float r_vec[3], int dx, int dy)
 void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy)
 {
 	if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) {
-		float mval_f[2];
-		mval_f[0] = dx;
-		mval_f[1] = dy;
+		const float mval_f[2] = {(float)dx, (float)dy};
 		ED_view3d_win_to_delta(t->ar, mval_f, r_vec);
 	}
 	else if (t->spacetype == SPACE_IMAGE) {

From 37a70492d145971e9b9800ac89e4a9b72d621d93 Mon Sep 17 00:00:00 2001
From: Sergey Sharybin 
Date: Sat, 8 Sep 2012 10:17:42 +0000
Subject: [PATCH 123/160] Merging r50470 through r50477 from trunk into
 soc-2011-tomato

---
 intern/ghost/intern/GHOST_C-api.cpp           |   5 +-
 intern/ghost/test/multitest/EventToBuf.c      |  45 ++---
 intern/ghost/test/multitest/MultiTest.c       |  24 ++-
 intern/utfconv/utf_winfunc.c                  |  22 ++-
 release/datafiles/fonts/droidsans.ttf.gz      | Bin 2334749 -> 2347305 bytes
 source/blender/blenfont/intern/blf_lang.c     |   1 +
 source/blender/blenkernel/intern/implicit.c   |   4 +-
 source/blender/blenkernel/intern/text.c       |   3 +-
 .../blender/blenkernel/intern/writeffmpeg.c   |  39 +++--
 source/blender/blenlib/BLI_math_base.h        |   5 +-
 source/blender/blenlib/BLI_utildefines.h      |   5 +-
 source/blender/bmesh/intern/bmesh_core.c      |  15 +-
 source/blender/bmesh/intern/bmesh_operators.c |  12 +-
 .../compositor/intern/COM_OpenCLDevice.cpp    |  10 +-
 .../editors/interface/interface_handlers.c    |  44 +++--
 .../editors/interface/interface_utils.c       |   6 +-
 source/blender/editors/mesh/editmesh_rip.c    |   5 +-
 .../blender/editors/space_info/info_stats.c   |   9 +-
 source/blender/editors/space_node/drawnode.c  |   3 +-
 source/blender/editors/space_node/node_edit.c |   9 +-
 .../editors/space_node/node_relationships.c   |   3 +-
 source/blender/editors/transform/transform.c  |  12 +-
 source/blender/imbuf/intern/anim_movie.c      |  28 +++
 source/blender/imbuf/intern/indexer.c         | 162 +++++++++++-------
 source/blender/makesrna/intern/makesrna.c     | 129 +++++++++-----
 source/blender/makesrna/intern/rna_access.c   |  57 ++++--
 source/blender/makesrna/intern/rna_define.c   | 126 +++++++++-----
 .../blender/makesrna/intern/rna_object_api.c  |   6 +-
 source/blender/makesrna/intern/rna_userdef.c  |   3 +-
 .../nodes/node_composite_channelMatte.c       |   9 +-
 source/blender/python/generic/bgl.c           |   2 +-
 .../windowmanager/intern/wm_event_system.c    |  28 +--
 .../blender/windowmanager/intern/wm_window.c  |   9 +-
 source/darwin/blender.app/Contents/Info.plist |   2 +
 .../blenderplayer.app/Contents/Info.plist     |  12 +-
 35 files changed, 559 insertions(+), 295 deletions(-)

diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index bb6c90cd431..0a4325930d5 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -529,7 +529,10 @@ char *GHOST_GetTitle(GHOST_WindowHandle windowhandle)
 
 	char *ctitle = (char *) malloc(title.Length() + 1);
 
-	if (ctitle == NULL) return NULL;
+	if (ctitle == NULL) {
+		return NULL;
+	}
+
 	strcpy(ctitle, title.Ptr());
 
 	return ctitle;
diff --git a/intern/ghost/test/multitest/EventToBuf.c b/intern/ghost/test/multitest/EventToBuf.c
index 034fbe04447..0eb37a58be2 100644
--- a/intern/ghost/test/multitest/EventToBuf.c
+++ b/intern/ghost/test/multitest/EventToBuf.c
@@ -203,33 +203,36 @@ void event_to_buf(GHOST_EventHandle evt, char buf[128])
 	void *data= GHOST_GetEventData(evt);
 	char *pos= buf;
 
-	pos+= sprintf(pos, "event: %6.2f, %16s", time, eventtype_to_string(type));
+	pos += sprintf(pos, "event: %6.2f, %16s", time, eventtype_to_string(type));
 	if (win) {
 		char *s= GHOST_GetTitle(win);
-		pos+= sprintf(pos, " - win: %s", s);
+		pos += sprintf(pos, " - win: %s", s);
 		free(s);
 	} else {
 		pos+= sprintf(pos, " - sys evt");
 	}
 	switch (type) {
-	case GHOST_kEventCursorMove: {
-		GHOST_TEventCursorData *cd= data;
-		pos+= sprintf(pos, " - pos: (%d, %d)", cd->x, cd->y);
-		break;
-	}
-	case GHOST_kEventButtonDown:
-	case GHOST_kEventButtonUp: {
-		GHOST_TEventButtonData *bd= data;
-		pos+= sprintf(pos, " - but: %d", bd->button);
-		break;
-	}
-	
-	case GHOST_kEventKeyDown:
-	case GHOST_kEventKeyUp: {
-		GHOST_TEventKeyData *kd= data;
-		pos+= sprintf(pos, " - key: %s (%d)", keytype_to_string(kd->key), kd->key);
-		if (kd->ascii) pos+= sprintf(pos, " ascii: '%c' (%d)", kd->ascii, kd->ascii);
-		break;
-	}
+		case GHOST_kEventCursorMove:
+		{
+			GHOST_TEventCursorData *cd= data;
+			pos += sprintf(pos, " - pos: (%d, %d)", cd->x, cd->y);
+			break;
+		}
+		case GHOST_kEventButtonDown:
+		case GHOST_kEventButtonUp:
+		{
+			GHOST_TEventButtonData *bd= data;
+			pos += sprintf(pos, " - but: %d", bd->button);
+			break;
+		}
+
+		case GHOST_kEventKeyDown:
+		case GHOST_kEventKeyUp:
+		{
+			GHOST_TEventKeyData *kd= data;
+			pos += sprintf(pos, " - key: %s (%d)", keytype_to_string(kd->key), kd->key);
+			if (kd->ascii) pos+= sprintf(pos, " ascii: '%c' (%d)", kd->ascii, kd->ascii);
+			break;
+		}
 	}
 }
diff --git a/intern/ghost/test/multitest/MultiTest.c b/intern/ghost/test/multitest/MultiTest.c
index da1c56d0a3a..5d207dafaaf 100644
--- a/intern/ghost/test/multitest/MultiTest.c
+++ b/intern/ghost/test/multitest/MultiTest.c
@@ -267,7 +267,8 @@ static void mainwindow_handle(void *priv, GHOST_EventHandle evt)
 	mainwindow_log(mw, buf);
 	
 	switch (type) {
-		case GHOST_kEventCursorMove: {
+		case GHOST_kEventCursorMove:
+		{
 			GHOST_TEventCursorData *cd = GHOST_GetEventData(evt);
 			int x, y;
 			GHOST_ScreenToClient(mw->win, cd->x, cd->y, &x, &y);
@@ -275,13 +276,15 @@ static void mainwindow_handle(void *priv, GHOST_EventHandle evt)
 			break;
 		}
 		case GHOST_kEventButtonDown:
-		case GHOST_kEventButtonUp: {
+		case GHOST_kEventButtonUp:
+		{
 			GHOST_TEventButtonData *bd = GHOST_GetEventData(evt);
 			mainwindow_do_button(mw, bd->button, (type == GHOST_kEventButtonDown));
 			break;
 		}
 		case GHOST_kEventKeyDown:
-		case GHOST_kEventKeyUp: {
+		case GHOST_kEventKeyUp:
+		{
 			GHOST_TEventKeyData *kd = GHOST_GetEventData(evt);
 			mainwindow_do_key(mw, kd->key, (type == GHOST_kEventKeyDown));
 			break;
@@ -541,7 +544,8 @@ static void loggerwindow_handle(void *priv, GHOST_EventHandle evt)
 	GHOST_TEventType type = GHOST_GetEventType(evt);
 	
 	switch (type) {
-		case GHOST_kEventCursorMove: {
+		case GHOST_kEventCursorMove:
+		{
 			GHOST_TEventCursorData *cd = GHOST_GetEventData(evt);
 			int x, y;
 			GHOST_ScreenToClient(lw->win, cd->x, cd->y, &x, &y);
@@ -549,13 +553,15 @@ static void loggerwindow_handle(void *priv, GHOST_EventHandle evt)
 			break;
 		}
 		case GHOST_kEventButtonDown:
-		case GHOST_kEventButtonUp: {
+		case GHOST_kEventButtonUp:
+		{
 			GHOST_TEventButtonData *bd = GHOST_GetEventData(evt);
 			loggerwindow_do_button(lw, bd->button, (type == GHOST_kEventButtonDown));
 			break;
 		}
 		case GHOST_kEventKeyDown:
-		case GHOST_kEventKeyUp: {
+		case GHOST_kEventKeyUp:
+		{
 			GHOST_TEventKeyData *kd = GHOST_GetEventData(evt);
 			loggerwindow_do_key(lw, kd->key, (type == GHOST_kEventKeyDown));
 			break;
@@ -743,13 +749,15 @@ static void extrawindow_handle(void *priv, GHOST_EventHandle evt)
 	
 	switch (type) {
 		case GHOST_kEventKeyDown:
-		case GHOST_kEventKeyUp: {
+		case GHOST_kEventKeyUp:
+		{
 			GHOST_TEventKeyData *kd = GHOST_GetEventData(evt);
 			extrawindow_do_key(ew, kd->key, (type == GHOST_kEventKeyDown));
 			break;
 		}
 
-		case GHOST_kEventCursorMove: {
+		case GHOST_kEventCursorMove:
+		{
 			extrawindow_spin_cursor(ew, GHOST_GetEventTime(evt));
 			break;
 		}
diff --git a/intern/utfconv/utf_winfunc.c b/intern/utfconv/utf_winfunc.c
index 3840dc25648..18f0e808562 100644
--- a/intern/utfconv/utf_winfunc.c
+++ b/intern/utfconv/utf_winfunc.c
@@ -37,7 +37,7 @@ FILE * ufopen(const char * filename, const char * mode)
 {
 	FILE *f = NULL;
 	UTF16_ENCODE(filename);
-	UTF16_ENCODE (mode);
+	UTF16_ENCODE(mode);
 
 	if (filename_16 && mode_16) {
 		f = _wfopen(filename_16, mode_16);
@@ -79,9 +79,11 @@ int urename(const char *oldname, const char *newname )
 {
 	int r = -1;
 	UTF16_ENCODE(oldname);
-	UTF16_ENCODE (newname);
+	UTF16_ENCODE(newname);
 
-	if (oldname_16 && newname_16) r = _wrename(oldname_16, newname_16);
+	if (oldname_16 && newname_16) {
+		r = _wrename(oldname_16, newname_16);
+	}
 	
 	UTF16_UN_ENCODE(newname);
 	UTF16_UN_ENCODE(oldname);
@@ -94,7 +96,9 @@ int umkdir(const char *pathname)
 	BOOL r = 0;
 	UTF16_ENCODE(pathname);
 	
-	if (pathname_16) r = CreateDirectoryW(pathname_16, NULL);
+	if (pathname_16) {
+		r = CreateDirectoryW(pathname_16, NULL);
+	}
 
 	UTF16_UN_ENCODE(pathname);
 
@@ -123,7 +127,10 @@ int uput_getenv(const char *varname, char * value, size_t buffsize)
 {
 	int r = 0;
 	wchar_t * str;
-	if (!buffsize) return r;
+
+	if (!buffsize) {
+		return r;
+	}
 
 	UTF16_ENCODE(varname);
 	if (varname_16) {
@@ -133,7 +140,9 @@ int uput_getenv(const char *varname, char * value, size_t buffsize)
 	}
 	UTF16_UN_ENCODE(varname);
 
-	if (!r) value[0] = 0;
+	if (!r) {
+		value[0] = 0;
+	}
 
 	return r;
 }
@@ -143,6 +152,7 @@ int uputenv(const char *name, const char *value)
 	int r = -1;
 	UTF16_ENCODE(name);
 	UTF16_ENCODE(value);
+
 	if (name_16 && value_16) {
 		r = (SetEnvironmentVariableW(name_16,value_16)!= 0) ? 0 : -1;
 	}
diff --git a/release/datafiles/fonts/droidsans.ttf.gz b/release/datafiles/fonts/droidsans.ttf.gz
index b2eb31af4b97d05d7fb18f5ca7868cd3806c9ee9..439515e5bb4a639c2779a106cd31738123586cca 100644
GIT binary patch
literal 2347305
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�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%0DKE_EVESFg-9-Pbdtq
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%0A(LMrk6$6%UqSP)fPWJ*x(S>&!T(L<
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

FRZN?FrZ@X!a)NgBF`NBWZ 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

@Ia|ZwUy8hQue=+|5K7x-s(eM8`(nSyZ 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Ⓢ+4! zy5W62Z0*|u($_Pq$ko@?ujA<4Vl1SbTcE5X;Ssu}yFrRYo0g%VCJ9>gm}_Vv3L>mT zZ8MUntG9WeU6nOKUd`$Jx%~(>iM4M_a6T7dls1q$|ZVIcA?OD+n{NuR$F;D2% zQO}<37M||q4=jCfBXo?*F66b9SP{~6;CUmHDMwckhdVAr;wWinp_A)-aQ9NfoY+q= ztj{jC+r&W89llIepHo0&yWnDNM9OMZ5UjxKe0b~JaF^-+3(ikMPQ}*Vaa}guSU_!J zOgol{XfTKR6g8ed_0P8Iy40NhAu`9rC~mQ?`kKRV{FZvURjU)T`Sk<^7V!DAh&+}k z<^EDqg>o`swro|EyJC8GzSwI;vS@L=Y7hVZjo((SW`M0a05;2}fZ!ou<_Q!*+-ho2 z)Lp3f=8gZrKJ4+sVMcRTS-PQ*Gs|LHBWwD&L5X*_aqdVdsC*D+XG^^AQ%mL~CcSOD zT^*z8O#6WF-j9F`nw+JTST@lBlkpIo3%&9E0q7%d$%j=*$W_4835Pyne@SSs6_P2V z;7$5X?@@K7x3TPZI@t;=cj=7&w$sB;4P8|$(p3>d--2@NGYRQEBOZy|IM(4FRpIrf z=l*=BFXh(qvtqk4Y5^wPJXc!EWRtV}@5_-QZ)z5W@RO9=r(;7WV~tNY1?pDzH_VQz zN4xaoM;~7vZMeSP_%zrZ3|;ZJ7GP*?8g2I%F>o^smDJ;W)&mlC;j4i;Lesu(KRNA^ z@VIAnVfQ_JRA-&i5rtgdrfyI78`P?1<%^?zZ*SnGQt=@?)65sYO693YRAvm{)K|(i zw&+FU3Mrj@3&p&OT(VrVNG;_bvTVv^g)MI=2bj89otUz+d>S7oHCiPouK7Vd z>R6MJn;S_=Az@^LY`0pviYO_4g??%X6<YXwd=7!?A?we$IRZ zS%35^rHHN@47b}~zp1_1Fzvg;a;uhG)452yzfXiq8%&_SvHeQLPB!nRK1zh}x_x5u zaloY-8M79h()YB2pZ9J?-qB%?hK>`}K0EAawwYs9sQ*!#68oLh@|wBfqv*S2LNKWc zkpL_u8JuU6PE`Zu>YDu(0c3UeC|*ExvI^sfl-^%>6yxk%ZccofKAq?dBT-Sh{D7on zJUcKEIxKjd)R$JjkQzZF4;uF)- zG!+tN;uzsne%5~t~HoFS9#(pfp`!yaO3t9f_pKrk+Gyw#+{nRV_9YU*s3f*(`p0Ro`Po@_ztV zK&ZcF=AWhO5w4;P$|UpI6LaYXMC)A})|>E}*jj&Fm{?n9;I)XgLAuxohkv){9;P$d zTj4Hn-omznOcJL>I@o(0$p!mRjQt{TB#z^!>WB(0&2@^cR%ly>5n7fL*)`KpUB%?; zVIl`X>Xv~#`aV3P>0{X7Ll-v_*C4BstH2QWW73SG806OR1FIIPK~M~Xz`@2pY574N zd2|q0^m6G;vlE*pZ6ra1U@$9PZ*Y>Fq;~R$eLBbJ!>d}~brKVb(zP^y(XJoBtQHyeEqR*+$S+(Az>mVC-Jc;HfUacO40{HBDwTi;iH8uu^(zTPaZyKWHibAa8 zd`Hpe1^DlfeTz_*BS%4R;Mrl4x0orfZg&WInu3PRAlgcFuH30=UaUhsnwm75PGXD7 zCRKOJ4TH5qs8*89hMd$5Rkv89Qw)IlwD)MnG%gyZ92=x96*)8cg!1d?#?;e(| zCP@kDO+L-jz|Kq17}L%9%o2h7@+ziC^d&P@U7X}0Cj_ezAf-bgH3>LXP((m^;1TI{ z-gInB<10a@6yyYru7_q&HLFovH|n9^a5WI9Gd0voc-jmTXdi-iwgn9L;9n(?WKnjd z*wifKCiSM_nsuagDoLqa1?3RnY~RrKjmV0MdSC=49V{A>J-1`pHeE~%B&8S%uh)X{ z65U6}OKlrAFh`f(OHN66|J{ApOZfWx(|n&FXTDXC>A^gaXT0wB8C!GySsn@A*$iiu zbi;)6+h9EEPWPu$ZKD|Db0HCY8w3qoV7#9XC}#s1Mbo!Hd>yR~2$V$g$i`=6Um3O< z$37BIS8~)D-p&PWiY|wd3^ur3b}X?d8H|L=;H82{*Am`uWa}(4?D=q-bM-&6_V(5| z<5mA~{U?1`lI#ia(R81vzwPk{+dFM^=}*a?`+qt^-c#KA(>@;hefux`talynl>xl{ z!2cxIf8MJrTYGYUx{qTjcsj7yGWK>;K604?T2t+~H(e z?=Sk=l0Jt-FCM)y>uZ~=Ns+;(?;*4LE7UqcwEexgxcw`eEiJ)wwTQf@pJPU_EUzL} zJPq7npAjv~FUwU=?cj~WDoNErYRefBzBTk!*4X;SKV)9w!`m>!T$1WJe;kg`1_up5u|+h^Y`NGF_8^wpqD4U zKU?XZMis6~*SdGN!a6dRMrku$(YJPFVWS&G=po; z%LX(_fh7-R*+fdIQ%51Rw;OP6i#S8Z#Hm4QH&jd8cu{DGmx{7+r4m%jh*#@zpy;-# zTSnV6pu8ZuK{2Sdt#YSXX6*p{R~&QcxM17;1mINaJ9gLU$zZvj0p7sYt{@rtg~_d? zozcP?p4v+dE1JUDdhGHd2Bw57DZ;5EAtJE?yd)TYhjazSYT|crzNe&yZYUUf;(?87 za*qYV$zZ<_k`KxTK85vI41L%1PB<)JFF1xq6%3QX;U-pBuAgQT25VWn` zYe)hvDLqb170t|N5EPA0jgFyu$P1O&k>o^`6%dmaSxN`5Pymo@BiXVIhgdOqabicK zW2p?17&t}Wiv6-Gfro^2)$>HoS0u?Vx*(CV-0^JC+)j=>#xM;4=yno0Ob{et0%$dI zeJA2eW?;u)pgri%#5Pd`z@pi4lX4yLNTho4T^sY}3u%14n_HC5efiW(mTR^~9iyH} zvP$r3w=7chA2O$Z1`+?xHsBL<5wu!NVK3)hT$SR3Gs`Q z!w#UU2q#t0ai@W8wubQ(Dg#$EFK~6o=&~e&2T;1H`-w-#kQVg@K)gPmaRd-Z8Rr(ciDGCKvtls_@UNs|s*oAGZh1 zO>|Sb=hxTP4T=-mHl$ zS56(^_Y1ow_?i6!)GWs@>>b#*boB*Wtoi0Des2>7P3@YU|Kvgey^T8f`2Noc)CVT> z3tyhzGq-ZlMSr)t`gg0p`IYdiRrsIwYu0~wTjegV`jhuly4P?HKix_@^m)6NuYC)2 z?ltu1F+a23W`Ld0(P_W_&hD{g%*`%$yN#p&S5HPs`nlXC_7Z9_{Rn8?q4d1Pj9+Nj@LbZ(1|tew>bea-1M<bUD@6?&*!?fObz4K;rX0EaiX(?}#~wXU7~jAAJZ*7dZumg>_K&>a z1%=W1$Jb|e9X$W~=g9N>M;5Mn&hLNX+M9OlnSI-B$B}i5fAzNJUVG_*Rdh(vF2?Qt z^yV-4UjW~)!aF$vzt=NYEL&~2UO2owmu*H*+B7k~Hiy6BFG~~SvuKVPpGr%vZQY%_ zZlLtc&%NermC_sD@Q0saljr{7tKbX|2fzB6HGCoZDZ1nm zC{jv`GmkCKwS!0Qx}*6I=&t0W4?q0)$I*KhcHjEk_q^q@=Y96|?@+&_|K4ZO`OEv> z)44sm?z+c6PQU(4looHNf052h(Ap|4Q8)~ui3i4SC-JW@`?J@4?c4auBVYW_sOvoRqC0=x z=-fg-^zcKEfBei(iLTtD4d+aEyMK*@an9*#JZm&p*hV+-avE*}QDLIwC*7`xuKwT~ zwz~S%50h8*NPpf<$xq($7Ur?Eqm!#sBKtb`%w->=Z`u-z+irtDBKGy~pfXy^=!e#JHh=I*n7v~%`g4hw=Yp&em`l;%Rc+UJKyjI_rJpHH&3qqy77w- zm|KGDzW(q2F6BJnk4MoGx-0j+(WTtC0e|FkpF@MmpHnD#jQs?Yf9Jj6_&%TJcGxt3q zefDzh+bAJ*JVFoB^YHicHh-SG4C>}`PZBJ68QAMzk?-kwVCTX24f4I5&i%mmd&&3o z{4Rr{m~W8p74rSc&A(!P!o7Kvdm=r18GPp4cgf%XJNdp0GN( z`= z*3T^mJbIK0d)K4h^<}u7mmZf zb*gZD{hT_M(`R6sD7><3RvSaN?FG~G;l1b&_M+GCMK{8?tp}ud{j$wz(nm|Uk4Rsp zXIoyDe0Z@=sv3}H%nM<$g}P{=UH7@TEenK=z23LLvNMY z{1WtkIySxzWw_ku2GghHP%dQ%l=&Vguh->%3T3{Lmf5wfCc=Y{ZvqE$KZi2k%IbP7 zqbDVr)J0#pH4aJJ2B}A=U0MNsFNYq;q5E=ZCD*Mw?UPidllzEFFFo;pvbKiVvxm@7 z*4FMgS;FIll=;EtUyw4RXf!L+9Xm^S?2s~#Py#ik4I+95&7d5-75e311Niq7(x&fa zZE8XJDQzcG_91E?+K29hxAd0oJv!kPrsIiT|DD}0Yrv}~Nty3w&;3N!FYvgm%v+QD zawaKLO?4K%PJIck1E|Wqf?WSWcKslA0Ow5Ka;U7fOob;>sW_qPeg9VzoS+1M??*!{1Kx2}#_ z!a9o3aVmR0^hoynN3ooeasBmFccApFJ2IxY1L>H8>nG^kmfj@SE9rHV>O;ama{UKc z`OAo2H1HVa-b@v!tF$SK9T*%O;n*B12*Ownq0teJ%M~siK+gaH7(hoUETu;&8XcjI z9a}rLatv$9LKY@o8=b=6Kx>Yrs}PTjZLH;o={%bM=ZC&@6Z*!3yQdzX8ocO^7o(T_ zV{V1MA-SsazWWjV^Pjx*kq7Te<|#bijse3P^Pi%4k^}b)ZO_QaM1H{A$s=vJu;X6l zK89wzofO57Qp1G-uvy1`wpv)50n3F})@J^8b#>+>d|y!x71mOtJhyllus5E~F09?E zKXk*b$q;(yv#wkELo}TndW`$=4_NN3b-vENlQ}iI^v=_`PwwZL zm8UAyoHj`#MKA&=_kp( zzt?wfTK9-C;*5AB!3aBo>;B6Vd!~m6w$}}`|7aWS41;(79{oIn@A%G%*)Fx~q^=*) z*Y?rLAdn(T&<3FJ8-}{1b=&l#ZFHq&v*-THiHR;HWbA{__D=S*eY~ID{CjHW7ics! zIhv)6#x!>z6CwvZ* zxY@@nsz>8zQW}N){ds17^O-%GK9kb4b)7tWh`YN-LmuJNWH1dc;tS`{aCeV}v|LKV zPfiqO&Z2?8iCclXHc8nWdy4Qh#{igl<%#nZW@4+aaL|{OZKq}F*QI?0g@0dK7~uQ+ z3hN_MwsTHdVc*h@!ERZ2FYP!lIt;Uf&*zg<1KItrIy^b$p) z9Kw(v!~ZD)NQLvz5_18->ijYu*;AuaYZL71#Q6Na^}}=7?|k+fwSV!ln_u?32Y>J3 z6W>A)p|=}{W?%8jcRZ{=^uy16Z%Mi1?~@hFvd|yF+r^f3`}b~t_2Szv{NCr#9XFx5 zKYzy!?|RW!{x$i^9nrmaW&ghU;=As8G1Zml+${5N&`*Dx$}>IGlYMr2n_H&Pr zvOmqrZjBRWX75;Gt1Pt!%I{sc|8xJG^*`QuWUn?zqml8Iae5pJ!beW*80Yg_BR9P- z_c|gsr?UHQ?%lV0WjDPW?n^o+#&!!k`tRF(T{2Gp1Mcg0{37jZ^gxfcTNlq`$NJiV z%ic(6Yi4!4EtBDI3DX?v$#DA2yL->fqX)Bcw@vTMo``J@87tgds3qzOZB7*SEG0AN&@cij^swN8K%w(5{OTU%;DG?w|8)GPs%Nx*|CEg#1?Ta;}+QEm2-Ht#g4gi zsbXTxhR+;rU-Wd;p*sl|&LNWc_@qzsCiqtuP^NbN1=LdRz`mi0iG54(Gc5?p-rdu? zc1`A)r3=^tmt#j}d}MBJbQ0tZLkU9jaUgp1=;-!d#$*eBeNy;7CO)H;-PW(awfpIL z4ZZFA7nPG&U4sU3C*OMu?&S9Co?Z^v-22g8H^2R=Rg)91bz8vE7wWyNy^ zf})8Wyp6PX7j=;~J2}jQQs#H(#&$h9hz9ec!;|dT!%ZO#3Mo4A}{a;O9ecj#kKb_klJ%T^|Cuh#>7A!l2&fKdAoePwq$+@wGT?-3? zgBih#v-9)(WS)>qsNFj-FvoB8$+6>@6@WSo77IR#^3U7LoHFf%g(qhNe=q)^~?u~S1sJi~B!6krQ;tY4N^&XRv& zZhjw41gC(nNz-U8_xY5Xgnr*&oVxK-SH9!TcOvuARPOHq+{pj^zkmM=N%ALuj&$ai zDTaRq_%sJW$8+ojguX+758eaxjZlkPfnpeh3VB}04YT|J#Spv-%0c)(#;8O$;HA+8 zj$-D=E@3v-a<4;TvigbStJR-8a^+{g@-_P#QN$d*FnK7s6Rp1CSD$F#vA*>8pfdpBurYf% zHAT(B7}`TigQI)*veb?l<~A0wBG043$T+`ekfu@Eqqs8M5Upv z*0+A}%g!SD1rpH6MGtAogUJ{5u<(bMn8IEM(=N)ihthUj*k%Xb9bdACp)8UElG}MZAh^l=JhD|&O#UK z;WokdQ6jguBo=!${Z{CU8EwbT!NIW{wS%2Rq=(VU${Oigvd`1uBa4@yi-Fp4Eq%_q^Vu-jL7%i z_PNwXV&92kDNzFtnad$?X47GS2&T+Le-2A~vP#4}v#r=a0r}pqjpcUkM2P3Hgb(GZ z!Qt!yYpZ<{-Wx<)_6I-m-dnC(0mXqI+<8k^U6FXkqx?PK|8VadPx+pFpT3kiC2;SY z?0tWde8($&nB+^jUm*)r^C&e#ty7Msu1M#fzp!hXqeo#pObiVjzHZlTyXajD2rVy2 zdk-xhJh*s>*}rT5J}Q?R8KddZ!I6<&`=$mdkh7Dk*oGD|_q+hGdIcDa8G?<^@zvFI z3?0qH6Zi1?21eY#^0n10EphS4`e8gzGlik`GF&2kPm&ea$ac*aqvUJOi(kGdJhK#k z{T**IX3=ZStFCUu$JY+OviQ=43vRZq-B{+{`1Th+$URdJAGr5DSI!)mF`jYR#?SBh z&Lww!`|?A_R&RanwYRQcbTdVh_Urj+ilO#WS80plz{JGPJqTTwyDdlOb_(G6?;Oa_ zAZBuAcye-hh8Y{n?Vwfw-H^5kKYOA;+6SG58@NKO6|{?4oY;wedjpzepB?oqlK<+; zd-a)fXiWP^hdwHRMmS8}sjVKIJ^%dq8Ic{`na`u~ojcdAo4IXBNrWRoYP{QhYNO%|3v;rq+j-d*YOPM zBiaoIjt+?8B+W3BlY95#-dQ<+O`(n=?R<3Xd~|f@`HFJ>&Z9Z$$kK(g(#ioUT^A5s~G)GCG1&;Ml-_KT0rkp7d3;qOAq}ZT=^(5CU9ny$ltye+zvaEeO?dcmkxh%Vge)*yVp5OsK?vD>bUp9o%IDk{b?Ti)5+Wb9 z;K$Dic<-<{sgv9zd>`eJ`u0%NBD8IOZr}1e2k+d({3U2@ZuJP6;F?>V%zL3>B&Dh> z$kn7|7$F}7$gs@FGLaDko@q83rWwaLc{lE(iPiD5(J)FMN~%~|P9Hk8c7#-s_uyek zY+8|NC286bRE2cIVD-3!A6tqo16PvL-6VA9;Y*&GW0uF}@}3`^F(SXtYDm@b z!U-J}w|G+}WufTC*xXp&tDi2{{U{elIX^K`QBNvJCC|0Vb9u}U%)|KtJXlYnM24S8 z&r>$?6PI>-?Xz%Mysa`Wy_WZ$qIBq=8vIx~U8lXoL1Z&Qn({WwCV1^+m8D!Z?B*ybQK5D2)L_w#Hq9AEzyrt_oiuE(z zruUJ9rgK!=Lm_H-i5Ngd#iW@u@Y%9tF&G2Y3wfIhvc3CBo__bZvAm6!&2&`qu3-7# z1T2PLdLIS%MbP&{l#ppAtVb8SXO+c@WEcih>NIHajE>(qLsAR_KLYC;R^Tbl#q)Fs zz{Aq~K75u;_rvpV|MA&(-ecxA;C8?yF>bRa5NYv)OE%#btoe29NK?nY_SbgwIl; z7WZL0G2j2bzKSRA*ZSXi3hU-R#SA+8EVT`PYNbluNPmHS2sSNRrvi$DdZsvh=pC)` zl5R+1Ah^Xa#C+E`C7P$2SoYaGUd~JNZcuXSu3Zc4a%yMd%_eP7A=XoiBs{yeO5^4k znqim}jeMxbpo{SLVJM!JV6qwwL)Q&4trp*9b{c8rboyL!-^kW|g>5z9f9YLeT9*j- z)ESrfoYdm_;Y;XsoT8D&lqbfA={;yFdjcxTzNG1fExDHKDuFD6&emI^X5kIBHO0g` zYg?YC2&MGdgdWC$-o;~lo>?2~(jwuVH!&?O+HF^HY0MXAQ=71z~w@vLK+ET`bzAas$aoZPf5q9{9OBl!XUi`-D&1 zo7k7;p{!%%1LJuDC)|zaCnhIoLs1;V0 z8|&RC;;fg+?1>z%VI9T3uc)?zpX%7EQg-19Ugex8!!u2IW|6^r%u(!OVR0f~m;yZ( zBcom~m*`U2b2_nmR=JJB@;X~!ky)?f-8FTWHXN_q(MzB!LDe!2l-osCCgDSZnfWpD zT3_3M*Vr0EUK1>QrOR?$R!pS`uc)XLW7Sk+)lk47#!^g+Wpk4v2Psl!*+6{K!Y`v- zhTbi1wwM@XXquWQXNvb=d4B51#u}HOnqMX}7KbrLC;30)XqmXPtH`u$$FWN_Rdgh) z=-Y1S12h7TsVb5ho^Cj(;gBtgUAwN?z8%|+>xQ8Tx=>N|L~H7fuBUdXj$B4!ie%K} zH>UDa`Q`jFUL?Ovt722A2exfFL0xEwOtGoELRqWTw6fsp&Gh~T6)_@RA@%|16{ag6 z=1~>ENV91oA48u;Ru=h;h*BK6J~z>z75KB+eNF(+X%anw))9DGj7YZj)KEDLmxO(fRK4cD-NG{aC;m#;gn1f(S)|Z5c3h zH#av0Zk=lK$3{7pC2^6*p@ScS?@Ku{7YtV)?aha7p4c(S(7pN4ea&)#$M-+bYt@B6^JUltG= zg!VsB&E#L;xp}HbW8Q@C{1%Pyy-OocXdM0`g@D97my!td{T0x6kkB_k?t3%b_Y?Tu zy>DP!+j51zwrvWXCo>ub(>gm(qKBxcckkeDsq;(RtB}qQ!F@Z(eINkn-{5=qz8&Pg z9giVum`!g==Qn4$w^6^~*Wtb)^8E?8?>+Fnd*2Yb56|gQ`JGH}PJXjY@-}W9U3v$} z|6z9`fV|XhZ4ix&&W_$T%8WweUVb7kJP(QiR;6A}E^068~UZ zjt0lFgu0}79?N`YkY|AU*(1mc{v?d^pv$%&jhC}uc zpS1+vl-{!~Zv%>S?-{X19v)#v(BMQNYgKv=^$Lp0eUE($&?k_4So#(s*9=|S{EHLQ zdzis(ISkxuN!he5EOV$g2I8%BlOA7h!eul1S#(1tgIn1qJ^qt&zt>kTeP&;($yWU& z*CDMxN9xb=Qa*oT`9OcZ3q02(bLFqg=E`sG&6WSRadCUT3z3199t~;P?78g|d*=G` zU2f@oE%!Z=AMg{BGr}>Sf9mg3-fzn>;Apzr&tulu!(+@CJgakJdLqp>=uGL=Fk>iOl{a>$9P*ZhGAbd12>Vs+&?ikaC$!;Jm)HT(u_&S-D3@xu2e0 z?(JJWkJ7x6+#LA$7ibeB9D~r{;3x$HdSD0~{{beKPv`b*EZsf-H zqVDX+8vQ9ddF(RuqG0TS8|QYt<=XZqBKqnNe&k)9zkbdeqgTC(>gKoPUPtIUmC^Ns zu6>wTnRs}DnE=^*{fViuG*6`~n`ur7bBdaz4r&tsba(7vM@L0=vQQWw7-GS)50Os6 zy@FQy=6P8RTb4Jv3Hja08q|LLvk$p9+;sQNFMY&$fy6y>^w5*Py5o)7gRjr+PUmg9 zc`St1Uu3j?EVY%d+%uh~u~6N)=z+(8wpHpL?MOjUhQ;&GpO}^9-NO^RcTWs6%>4Xe zpm2HLzQeoDJMZAif${N!lOrtr>{&cGum^1L5Kb4tQ|wvDyRg=st6A<W1mQtsmtO z+DESo{qxr8EaA3aS!P7~66WYRGNFC{eRx9qjW4|K(Kp_4-=p{5f*Fwf_|q3A{{v5Y zC*x@9-_Ym}{vxS8`c-r#qbHZ%c^~~T{LWn3dG~Ej^cwu{o@9vXju-Y6w0{?MwI;K> zcF{vqQv>CJ>Htj-&;w(XAPBTT4KhrDotzor5faDKbRL|~1D!@@a=VkETg^+i8`$2Y zZcE0|N=iPwk{@H@A2}MOBz6gH&tf7o`nV^6z6I)q+8VpCKo3dMz}W8HLNtKr0YMm` znW?Fz%_T%Fp_I(oUGwvkn9{jD(;2BLt%WYRc*bFc^vUu5PC2AJ9o6S_L_hgis=?DY zBAY`@Tawy-kTqggewo@8&hFV2^z0LtUcoH%+bi}IDf{=CZF_ysUcGPs1!!!$z2crA zW&a^7dta~Y+}Z{bdpUnJq2W`Y9~Y^El&Kw9D$LIh&rVLBHw-__%*+bN`rhg3eX?AT z##nY_w={767&o#d=G|P9RU+nRC;1TRe>&kFos$X^+gK^gA(HAdCvB7KZ=qMBA7(i| z-+JSX2~E>`K1IJT`SavkXN&efBszMc(|SKi@_FdNWQe&aMpvMFsVrxP#qAsht)pqP zBY;R52JJY86J)p{K9@riJXaVRLc_hx1U#+ZZ61;7R1d9@+ypEb&5ez)eKXUZx$MKWZfBVGJ zJ~~B3G>!#x4+40`JiAVld(0AXhiXG3Is#R0(mUW*?QtY zDzrWOf>TcZ6L!7xJHMS!u~2iKEF zKT?UlXT4_S?N>bUCum2{9y8w{_*Ky+>EYqrKyH8r zOiT<8?i?N6AUTPA!b#z*O#sr@!*}XTSgN|F8Gl@unxHkE6AR(Y}Yi z_37We2hnZo;wCycaouNM^f!0i6`l72bWQP%?|SnOlUKdw0R7D5sW1F@bbRAhvYrO_ zEzv3ep5gGDQp~qwd49IAP4_V0Amv)y%e`r45{+#um-``GhH_73LRa%w*acGPJgMO`0=!kj1wyHe73ZzsLi7d@}zKc~OH zSI%m|({|0%cTX>e9Bhq9T|n8|x&VE%uyDbwcix^|v(&6KOYfZBIhz|FR|fLA1Jl#H z_AM{&6LHH#1`ShVLqn5Yb91cQfHmRd(d|(4IL7n1RV#(ekZ(&L?{gLRvFlmJ6;_Hk z18(EU2K&zT>poju`_SwwpHKh%(HGx2w+n#gRc}iE)zV*mTtBu~UAg<>#n-HLkRyO+FWPq z|7W?*S8_8w`+~mIjazn8EU8|K$ZCzDgKzko6)3Z zkiyxm*f!&t()lAm+SUZgUBTTuFGmBlDq@a58@;&Az1RHGUFd6H`p~C7a-a9<*S__= zuPFZ?bT~QPc*)7N=)spYt((y_y6>x>{@|Zizwmu*GrtA>d?(Pm6ST_(+LTBGaTGN( zD2ytj^yoyM8}2jJeXy?IP6L6|{Bj>v7owHR(cq7OsN}o<{GRvx@qhoweQ*9$)FtI# zlm8uk@8J*r`CtDT*<3iqnTtRJ))vpucF)kcorB|t#!+q@l=Cpyo!wJ;PT1KaWNST1 zcMuiMrUx@@v5%s0#Ag(};5opiw}0uwpZp{5zE4Fj{dP*zOTT+KioW)l55p#yUOB24sXi-b9})Q>ackxjHQ0?Z z7MOv7@nL2M$MS;E*ArVydgjvUF}y`=Px)Q`qR?<5(wuw~+pWCgVGb?S*fzTx4wygjP?k6&X^7)nlqButm1=+F=T@g;A+;eBtq@c;Zz z5Q>Mp0)e{u;nZGA)n=&CshLsu$%~={6b%eajO3&}YPm zddC!zH5gKX9ZybmenaLr?|$BCbQe9i zy?t@a8NBWZsGghu?Npx)H*!Bpez8gY>leSh_QAa`KmHVYF+GW!aTPS9b29)A^vCe_ z;D7%``LpkQ#{=$NuSFw>?=`4>stY{&bMX7-lP*53P>b3Ojf7!s*ci5kz2WL`b2vXt zqZbdIyVg3*+3%lcg8OA{9PS^{MvM__#2cxOG)M9yXHPx#)>~hSUU4WW@;v%9cso!bTX{_+GUAgb#or1!BQxo`ID`(|fnZ=3z>Y;Km^H$J{&N8f$7 z;QI0dz50gH-N`1kPZP-etTKAt=xw79k8*gH_A4hwN4M2^3$BygJDc5mSNGn@*-2&c zy2;xnAD-kU;oh&En4H{RZ>J6I9PiaTLjN$;$yblg4-anXWGDyi8t>JSmLu~Pe{*7T zc?X-#Tab1TEOCK0!O%HG!w)r>r)ZkbQNtM30-8t%%F0^bD8c8EBD|+5Isatt7WBQO z^*G|yA3yf}&vXt%c%Qj{%DwH(?Zqe3IWfZLaj*!NY0~h{k)Z)FNjrxGVQ43l%Z(52 z+&NgFMz$}y%rICtK-?Fw?_YEYWPsVoJp%A6|H#oZaYhI#Jl0)ciD_Y9P3&}{y%8BB88ZFW)5CVEW0wTz#CiY zH1XMzv;Yn!c=MbEWz*a#e6|5IKSo~ZPN!pQ40%l;_{u_MVp26iGpQMYu}L9OPZ~&p z&q&5^RJ(~JEvYkJQX&bu_~j$rPd_DwpOlaedWJSOeKzIEt7Y)oDBssD z)9^bY3cZr!;W5EPOfhE>c_Px3vt%a|B7*Z7At|$U_&d%gTcZjBnqPuz&~I8Iqi0t@GZ zTgVa1-CS>4K|EW{Mctg~LS~Sd51LKA%gm2% ze)@wyBN)f6q?i;pNzO5%@xDqiR0BG8ZoY7MgIxwU62@54w2&7vLAls)k&^OJ1v)D* zwtx!2sOS>3EzOqBqlr1T(sqzlbv!2u?Q)}B_iK2NM#ybcT*vd>Vm0}wdc@S)3bd+j>zxQ_)`8{{@N5QW8&7W0h&QBRfEhXPNjJ6qvYEWrbpJnylAhXcg$fI%|yDLvrzRslHqn7PqulPg{-UdIT=#LZq~+ z^#*9FTDe?LtcL5jPIZ&=13$2f3}39rb$n`zAJoH2C2Xj6Y{S2JlX9!B>pP}zoXwXx z;J7q4pAIPye8QJ~s4v%%j&uu^dVE2k!jiI$csGt+;7cgdM%=76pf5^EB{33{E=Nw6 zE9b7`>Kna>k6?^rg$MjXP?l+A7yV!$EN>GjD`eoNLT{EyNMJK9TrjS&7Fb90R)~254K{hWSr_}W2wUXp? z=xykADIF6yvo-w)?|7(eWwwsx>Q*_38|5MlHcfYu$|eQU;KN9fYV~q62@?m^@F}Cn zuLMQi(A~f?D*_7QN~zjX5=-Mvvs?xjR7)Jto7JRb`X&mHjeOLEOK~G<(tt`L*F!4k z7#nm<2s(zWdzi!M46O|y25&ddu%KQ_#R{#(w3Zk}MG(M3hwn?~6uT0&JMf?7p@-0B?=38m-)2(28<^71777vV+6oC#I6*84~49+Pyq)rz-j?bXn;zxL1yEm)dc?X ztrp-2A0Nk;c&vEF2Oxoe#LP~BuBxV30>{_Wz3mHgy+Kgw=rl+uJ~^|~>MK7$>{?cy zZkD@+aZ!pKnv75c?YE%)(_}RkH`m92u80-pawg3;6U>GHy5DJ3^eU(+V7Q0`KTKkV z?!qK$TNU9iddBn@vgLU17wfu!(#xui;2z)Mdl895kh17F!1|mXdY*k+Yvme%$U3o=SoT4Yd7E#ItV8t zfgD=Ux6u}M>M9M1BG`#eu@kc3M%T zVi9_=_e3q?W4D+symM zVvF6yNXtu$*a2L~R14P7xk=0?i3U%pT+!8}Tr1*A>P@{?Dn>3XMR*BhQdVNaaV=GG z^lA`Q%?J#KW0gyOwSwg%%;?XjV+)^Nl(Wj6R<7D<0gfqV>(w{|$`o)5$1yj1yZ&wz zIIOzrP*D{cQm%mAX&WtQsnlZPwhp?p#FX&bYNFdq>Dn&f&KjDW8e^-KPNm$bRFJF4 zW(wNdQV<}C#2kEz%H#2c2k6?^=+u#oF}O9g2k?Y3d>kJWRqDDZ%9TnIlv}baOHFW1 zDs>S)!o%=UXtg5az?dldam8svEp6Wc6da}c%gb~v(JkOX3}BN3L)fV&c4Ag(K2fRw z{T+Oaso!zw7G3U?X{}@8^?*G+P2qc>^8x=;D6D~l)@j!0D&1&%oeH1_pVS4)os&}@ zU>|^>#yL(t6EkMJoRiuyV+T2}7@YA^9|`)Db<(~;U7hW~^Hg$rNSSMerxog4ABe6o zVg--n)CWRz0KQ};eGZ$Q3Puyx4UeLjt%gtWM4$1r40@?dFb(dc0l0*U1RlX7XqgGy zHU>FleQ8qW`AwbpZ}3E(|MwQpCuN`by}4R0;v_=%{L=FJ+T>I&@FrM$yYGFQH1m$>OK^{m7Z##mfR>;f$p>qc&MWVG#AJyn;Y$egm@Bb zagNl%w%S!5ytq=a24q)})Tkk$U8QYcNs*=!--vXiU|56H1Po;mMVVYyK@KK}{9^60 zxHWx@4>@4{#4F+Dz@@6^%C_yA$iwHXGG#}y%CQuPmTMDChiZw)$w224wTkyiLKFEk z^0b@=%U6jqBx?+D2%QAWprWz9uoN@j=l^kXS!+~P*)q&ZsSJ3d+H4}x@*THcvveEu zu#aD16?~qsUbl0)Bbr`V;Z;MH!=PLW!>T4bjv>WXTosd|<6>Y4$PlkbgX=gp0UTu; z(0}7te--knKiap&JS~Edxy?qU1c*K=fov&3v0UvabUAS2dZ&`wN4CTXpr0nr@__)= z6xa#iY0g&ha!GirBrQ}%Ry#l@8)0_=u6F98+tx+EJE^@ W;`Z`bzcp$zrl$KuPm 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�J48YZz^ibht*17`b(^-*7yg}+H_+U~C{ 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ⅆ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 z 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 VPcoCqZ}34aambLZ9{Qdj+Qn-uY^*>jJ({H>t^ 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

sQy3qDv56&q1A7x?FNU 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%0Aeb8t`6T^5Zy9}afEKNCh>W@;c2VA*Po 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%0A`w*rrsS+U;wwo+4P!|Ik%Fnkt1`EVzE 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

!+javgmag$QyTedJ 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�y3!)tt6Pm=^36icZtEeQ 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ཪ~2JIx}$z_JP9HDj(ZSeGUB) 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ðaX0aHvnP>fUAc_b2w9oaq4qgL-0d_0*t2& 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�$pz!S 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ℑSL}+itVd{ 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℞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�oH{n$0w>8X5C<}ns)rjX?pvgUV5ID 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%0Ahd$|ra-+f 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

PS`b*u&y3 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�odcioBNRFjv&=< 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

$aV0=Q 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 OlO@r5k;Tp@7c6Z%3D7jGF_&u3HY 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%0D40)d*ikS!1&r$Xv4u4v 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≷WYDOWW3$J>@JZx$6^HxBr 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%0AVOI~XZnojLueZ;9YxM|xPK*gKNZ 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�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⁢P4&jI?cA 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

SOn&Ws%Nk6R$HBfc>#G;(fdk%dy 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

    e!eW= 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�_H_7hW+&c)XaTJv<=D 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

    4plY_a3^`4l_Q1wDm(*ojNvi?n<`wd5g(JH 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

  1. The C-API. For programs written in C.
  2. *
  3. The C++-API. For programs written in C++.
  4. * - * GHOST itself is writtem in C++ and the C-API is a wrapper around the C++ + * GHOST itself is writtem in C++ and the C-API is a wrapper around the C++ * API. * * \subsection cplusplus_api The C++ API consists of the following files: @@ -113,7 +113,7 @@ class GHOST_IEventConsumer; * program in the ?/ghost/test/gears/ directory. * * \subsection c_api The C-API - * To use GHOST in programs written in C, include the file GHOST_C-API.h in + * To use GHOST in programs written in C, include the file GHOST_C-API.h in * your program. This file includes the GHOST_Types.h file for all GHOST types * and defines functions that give you access to the same functionality present * in the C++ API.
    @@ -123,7 +123,7 @@ class GHOST_IEventConsumer; * \section work Work in progress * \todo write WIP section */ - + /** \interface GHOST_ISystem * Interface for classes that provide access to the operating system. * There should be only one system class in an application. @@ -136,8 +136,8 @@ class GHOST_IEventConsumer; * -# Access to the state of the mouse buttons and the keyboard. * -# Menus for windows with events generated when they are accessed (this is * work in progress). - * \author Maarten Gribnau - * \date May 30, 2001 + * \author Maarten Gribnau + * \date May 30, 2001 */ class GHOST_ISystem { @@ -190,12 +190,12 @@ public: /** * Installs a timer. - * Note that, on most operating systems, messages need to be processed in order + * Note that, on most operating systems, messages need to be processed in order * for the timer callbacks to be invoked. - * \param delay The time to wait for the first call to the timerProc (in milliseconds) - * \param interval The interval between calls to the timerProc (in milliseconds) - * \param timerProc The callback invoked when the interval expires, - * \param userData Placeholder for user data. + * \param delay The time to wait for the first call to the timerProc (in milliseconds) + * \param interval The interval between calls to the timerProc (in milliseconds) + * \param timerProc The callback invoked when the interval expires, + * \param userData Placeholder for user data. * \return A timer task (0 if timer task installation failed). */ virtual GHOST_ITimerTask *installTimer(GHOST_TUns64 delay, @@ -225,22 +225,22 @@ public: * \return The dimension of the main display. */ virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const = 0; - + /** * Create a new window. - * The new window is added to the list of windows managed. + * The new window is added to the list of windows managed. * Never explicitly delete the window, use disposeWindow() instead. - * \param title The name of the window (displayed in the title bar of the window if the OS supports it). - * \param left The coordinate of the left edge of the window. - * \param top The coordinate of the top edge of the window. - * \param width The width the window. - * \param height The height the window. - * \param state The state of the window when opened. - * \param type The type of drawing context installed in this window. - * \param stereoVisual Create a stereo visual for quad buffered stereo. - * \param numOfAASamples Number of samples used for AA (zero if no AA) - * \param parentWindow Parent (embedder) window - * \return The new window (or 0 if creation failed). + * \param title The name of the window (displayed in the title bar of the window if the OS supports it). + * \param left The coordinate of the left edge of the window. + * \param top The coordinate of the top edge of the window. + * \param width The width the window. + * \param height The height the window. + * \param state The state of the window when opened. + * \param type The type of drawing context installed in this window. + * \param stereoVisual Create a stereo visual for quad buffered stereo. + * \param numOfAASamples Number of samples used for AA (zero if no AA) + * \param parentWindow Parent (embedder) window + * \return The new window (or 0 if creation failed). */ virtual GHOST_IWindow *createWindow( const STR_String& title, @@ -252,40 +252,40 @@ public: /** * Dispose a window. - * \param window Pointer to the window to be disposed. - * \return Indication of success. + * \param window Pointer to the window to be disposed. + * \return Indication of success. */ virtual GHOST_TSuccess disposeWindow(GHOST_IWindow *window) = 0; /** * Returns whether a window is valid. - * \param window Pointer to the window to be checked. - * \return Indication of validity. + * \param window Pointer to the window to be checked. + * \return Indication of validity. */ virtual bool validWindow(GHOST_IWindow *window) = 0; /** * Begins full screen mode. - * \param setting The new setting of the display. - * \param window Window displayed in full screen. - * This window is invalid after full screen has been ended. - * \return Indication of success. + * \param setting The new setting of the display. + * \param window Window displayed in full screen. + * This window is invalid after full screen has been ended. + * \return Indication of success. */ virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window, const bool stereoVisual, const GHOST_TUns16 numOfAASamples = 0) = 0; - + /** * Updates the resolution while in fullscreen mode. - * \param setting The new setting of the display. - * \param window Window displayed in full screen. + * \param setting The new setting of the display. + * \param window Window displayed in full screen. * - * \return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window) = 0; /** * Ends full screen mode. - * \return Indication of success. + * \return Indication of success. */ virtual GHOST_TSuccess endFullScreen(void) = 0; @@ -305,7 +305,7 @@ public: * \return Indication of the presence of events. */ virtual bool processEvents(bool waitForEvent) = 0; - + /** * Retrieves events from the queue and send them to the event consumers. * \return Indication of the presence of events. @@ -332,18 +332,18 @@ public: /** * Returns the current location of the cursor (location in screen coordinates) - * \param x The x-coordinate of the cursor. - * \param y The y-coordinate of the cursor. - * \return Indication of success. + * \param x The x-coordinate of the cursor. + * \param y The y-coordinate of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const = 0; /** * Updates the location of the cursor (location in screen coordinates). * Not all operating systems allow the cursor to be moved (without the input device being moved). - * \param x The x-coordinate of the cursor. - * \param y The y-coordinate of the cursor. - * \return Indication of success. + * \param x The x-coordinate of the cursor. + * \param y The y-coordinate of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) = 0; @@ -353,17 +353,17 @@ public: /** * Returns the state of a modifier key (ouside the message queue). - * \param mask The modifier key state to retrieve. - * \param isDown The state of a modifier key (true == pressed). - * \return Indication of success. + * \param mask The modifier key state to retrieve. + * \param isDown The state of a modifier key (true == pressed). + * \return Indication of success. */ virtual GHOST_TSuccess getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const = 0; /** * Returns the state of a mouse button (ouside the message queue). - * \param mask The button state to retrieve. - * \param isDown Button state. - * \return Indication of success. + * \param mask The button state to retrieve. + * \param isDown Button state. + * \return Indication of success. */ virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const = 0; @@ -378,11 +378,11 @@ public: * \return current status (1 -visible, 0 - hidden) */ virtual int toggleConsole(int action) = 0; - + /*************************************************************************************** * Access to clipboard. ***************************************************************************************/ - + /** * Returns the selection buffer * \return Returns "unsinged char" from X11 XA_CUT_BUFFER0 buffer diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index a1a1acfca75..88f130aabe8 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -41,20 +41,20 @@ /** * Interface for GHOST windows. * - * You can create a window with the system's GHOST_ISystem::createWindow + * You can create a window with the system's GHOST_ISystem::createWindow * method. * \see GHOST_ISystem#createWindow * * There are two coordinate systems: *
      *
    • The screen coordinate system. The origin of the screen is located in the - * upper left corner of the screen.
    • + * upper left corner of the screen. *
    • The client rectangle coordinate system. The client rectangle of a window * is the area that is drawable by the application (excluding title bars etc.). - *
    • + * *
    - * \author Maarten Gribnau - * \date May 31, 2001 + * \author Maarten Gribnau + * \date May 31, 2001 */ class GHOST_IWindow { @@ -86,20 +86,20 @@ public: /** * Tries to install a rendering context in this window. - * \param type The type of rendering context installed. + * \param type The type of rendering context installed. * \return Indication as to whether installation has succeeded. */ virtual GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type) = 0; /** * Sets the title displayed in the title bar. - * \param title The title to display in the title bar. + * \param title The title to display in the title bar. */ virtual void setTitle(const STR_String& title) = 0; /** * Returns the title displayed in the title bar. - * \param title The title displayed in the title bar. + * \param title The title displayed in the title bar. */ virtual void getTitle(STR_String& title) const = 0; @@ -109,7 +109,7 @@ public: * \param bounds The bounding rectangle of the window. */ virtual void getWindowBounds(GHOST_Rect& bounds) const = 0; - + /** * Returns the client rectangle dimensions. * The left and top members of the rectangle are always zero. @@ -131,26 +131,26 @@ public: /** * Resizes client rectangle. - * \param width The new width of the client area of the window. - * \param height The new height of the client area of the window. + * \param width The new width of the client area of the window. + * \param height The new height of the client area of the window. */ virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) = 0; /** * Converts a point in screen coordinates to client rectangle coordinates - * \param inX The x-coordinate on the screen. - * \param inY The y-coordinate on the screen. - * \param outX The x-coordinate in the client rectangle. - * \param outY The y-coordinate in the client rectangle. + * \param inX The x-coordinate on the screen. + * \param inY The y-coordinate on the screen. + * \param outX The x-coordinate in the client rectangle. + * \param outY The y-coordinate in the client rectangle. */ virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0; /** * Converts a point in screen coordinates to client rectangle coordinates - * \param inX The x-coordinate in the client rectangle. - * \param inY The y-coordinate in the client rectangle. - * \param outX The x-coordinate on the screen. - * \param outY The y-coordinate on the screen. + * \param inX The x-coordinate in the client rectangle. + * \param inY The y-coordinate in the client rectangle. + * \param outX The x-coordinate on the screen. + * \param outY The y-coordinate on the screen. */ virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0; @@ -158,13 +158,13 @@ public: * Tells if the ongoing drag'n'drop object can be accepted upon mouse drop */ virtual void setAcceptDragOperation(bool canAccept) = 0; - + /** * Returns acceptance of the dropped object * Usually called by the "object dropped" event handling function */ virtual bool canAcceptDragOperation() const = 0; - + /** * Returns the state of the window (normal, minimized, maximized). * \return The state of the window. @@ -184,13 +184,13 @@ public: * \return Indication of success. */ virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges) = 0; - + /** * Gets the window "modified" status, indicating unsaved changes * \return True if there are unsaved changes */ virtual bool getModifiedState() = 0; - + /** * Sets the order of the window (bottom, top). * \param order The order of the window. @@ -200,13 +200,13 @@ public: /** * Swaps front and back buffers of a window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess swapBuffers() = 0; /** * Activates the drawing context of this window. - * \return A boolean success indicator. + * \return A boolean success indicator. */ virtual GHOST_TSuccess activateDrawingContext() = 0; @@ -215,71 +215,71 @@ public: * \return Indication of success. */ virtual GHOST_TSuccess invalidate() = 0; - + /** * Returns the window user data. * \return The window user data. */ virtual GHOST_TUserDataPtr getUserData() const = 0; - + /** * Changes the window user data. * \param data The window user data. */ virtual void setUserData(const GHOST_TUserDataPtr userData) = 0; - + /** * Returns the tablet data (pressure etc). * \return The tablet data (pressure etc). */ virtual const GHOST_TabletData *GetTabletData() = 0; - + /*************************************************************************************** * Progress bar functionality ***************************************************************************************/ - + /** * Sets the progress bar value displayed in the window/application icon * \param progress The progress % */ virtual GHOST_TSuccess setProgressBar(float progress) = 0; - + /** * Hides the progress bar in the icon */ virtual GHOST_TSuccess endProgressBar() = 0; - + /*************************************************************************************** * Cursor management functionality ***************************************************************************************/ /** * Returns the current cursor shape. - * \return The current cursor shape. + * \return The current cursor shape. */ virtual GHOST_TStandardCursor getCursorShape() const = 0; /** * Set the shape of the cursor. - * \param cursor The new cursor shape type id. - * \return Indication of success. + * \param cursor The new cursor shape type id. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape) = 0; /** * Set the shape of the cursor to a custom cursor. - * \param bitmap The bitmap data for the cursor. - * \param mask The mask data for the cursor. - * \param hotX The X coordinate of the cursor hotspot. - * \param hotY The Y coordinate of the cursor hotspot. - * \return Indication of success. + * \param bitmap The bitmap data for the cursor. + * \param mask The mask data for the cursor. + * \param hotX The X coordinate of the cursor hotspot. + * \param hotY The Y coordinate of the cursor hotspot. + * \return Indication of success. */ - virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 bitmap[16][2], + virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY) = 0; - virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap, + virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, int sizex, int sizey, int hotX, int hotY, @@ -287,23 +287,23 @@ public: /** * Returns the visibility state of the cursor. - * \return The visibility state of the cursor. + * \return The visibility state of the cursor. */ virtual bool getCursorVisibility() const = 0; /** * Shows or hides the cursor. - * \param visible The new visibility state of the cursor. - * \return Indication of success. + * \param visible The new visibility state of the cursor. + * \return Indication of success. */ virtual GHOST_TSuccess setCursorVisibility(bool visible) = 0; /** * Grabs the cursor for a modal operation. - * \param grab The new grab state of the cursor. - * \return Indication of success. + * \param grab The new grab state of the cursor. + * \return Indication of success. */ - virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds) { return GHOST_kSuccess; } + virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds, GHOST_TInt32 mouse_ungrab_xy[2]) { return GHOST_kSuccess; } #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IWindow") diff --git a/intern/ghost/GHOST_Rect.h b/intern/ghost/GHOST_Rect.h index e52d6a7e6a0..a055b6f7f0d 100644 --- a/intern/ghost/GHOST_Rect.h +++ b/intern/ghost/GHOST_Rect.h @@ -41,8 +41,8 @@ * The four extreme coordinates are stored as left, top, right and bottom. * To be valid, a rectangle should have a left coordinate smaller than or equal to right. * To be valid, a rectangle should have a top coordinate smaller than or equal to bottom. - * \author Maarten Gribnau - * \date May 10, 2001 + * \author Maarten Gribnau + * \date May 10, 2001 */ class GHOST_Rect { @@ -50,10 +50,10 @@ public: /** * Constructs a rectangle with the given values. - * \param l requested left coordinate of the rectangle - * \param t requested top coordinate of the rectangle - * \param r requested right coordinate of the rectangle - * \param b requested bottom coordinate of the rectangle + * \param l requested left coordinate of the rectangle + * \param t requested top coordinate of the rectangle + * \param r requested right coordinate of the rectangle + * \param b requested bottom coordinate of the rectangle */ GHOST_Rect(GHOST_TInt32 l = 0, GHOST_TInt32 t = 0, GHOST_TInt32 r = 0, GHOST_TInt32 b = 0) : m_l(l), m_t(t), m_r(r), m_b(b) @@ -61,85 +61,84 @@ public: /** * Copy constructor. - * \param r rectangle to copy + * \param r rectangle to copy */ GHOST_Rect(const GHOST_Rect& r) : m_l(r.m_l), m_t(r.m_t), m_r(r.m_r), m_b(r.m_b) {} - + /** * Destructor. */ - virtual ~GHOST_Rect() - {}; + virtual ~GHOST_Rect() {} /** * Access to rectangle width. - * \return width of the rectangle + * \return width of the rectangle */ virtual inline GHOST_TInt32 getWidth() const; /** * Access to rectangle height. - * \return height of the rectangle + * \return height of the rectangle */ virtual inline GHOST_TInt32 getHeight() const; /** * Sets all members of the rectangle. - * \param l requested left coordinate of the rectangle - * \param t requested top coordinate of the rectangle - * \param r requested right coordinate of the rectangle - * \param b requested bottom coordinate of the rectangle + * \param l requested left coordinate of the rectangle + * \param t requested top coordinate of the rectangle + * \param r requested right coordinate of the rectangle + * \param b requested bottom coordinate of the rectangle */ virtual inline void set(GHOST_TInt32 l, GHOST_TInt32 t, GHOST_TInt32 r, GHOST_TInt32 b); /** * Returns whether this rectangle is empty. * Empty rectangles are rectangles that have width==0 and/or height==0. - * \return boolean value (true==empty rectangle) + * \return boolean value (true==empty rectangle) */ virtual inline bool isEmpty() const; /** * Returns whether this rectangle is valid. * Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b. Thus, emapty rectangles are valid. - * \return boolean value (true==valid rectangle) + * \return boolean value (true==valid rectangle) */ virtual inline bool isValid() const; /** * Grows (or shrinks the rectangle). * The method avoids negative insets making the rectangle invalid - * \param i The amount of offset given to each extreme (negative values shrink the rectangle). + * \param i The amount of offset given to each extreme (negative values shrink the rectangle). */ virtual void inset(GHOST_TInt32 i); /** * Does a union of the rectangle given and this rectangle. * The result is stored in this rectangle. - * \param r The rectangle that is input for the union operation. + * \param r The rectangle that is input for the union operation. */ virtual inline void unionRect(const GHOST_Rect& r); /** * Grows the rectangle to included a point. - * \param x The x-coordinate of the point. - * \param y The y-coordinate of the point. + * \param x The x-coordinate of the point. + * \param y The y-coordinate of the point. */ virtual inline void unionPoint(GHOST_TInt32 x, GHOST_TInt32 y); /** * Grows the rectangle to included a point. - * \param x The x-coordinate of the point. - * \param y The y-coordinate of the point. + * \param x The x-coordinate of the point. + * \param y The y-coordinate of the point. */ virtual inline void wrapPoint(GHOST_TInt32 &x, GHOST_TInt32 &y, GHOST_TInt32 ofs); /** * Returns whether the point is inside this rectangle. * Point on the boundary is considered inside. - * \param x x-coordinate of point to test. + * \param x x-coordinate of point to test. * \param y y-coordinate of point to test. * \return boolean value (true if point is inside). */ @@ -147,16 +146,16 @@ public: /** * Returns whether the rectangle is inside this rectangle. - * \param r rectangle to test. - * \return visibility (not, partially or fully visible). + * \param r rectangle to test. + * \return visibility (not, partially or fully visible). */ virtual GHOST_TVisibility getVisibility(GHOST_Rect& r) const; /** * Sets rectangle members. * Sets rectangle members such that it is centered at the given location. - * \param cx requested center x-coordinate of the rectangle - * \param cy requested center y-coordinate of the rectangle + * \param cx requested center x-coordinate of the rectangle + * \param cy requested center y-coordinate of the rectangle */ virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy); @@ -164,10 +163,10 @@ public: * Sets rectangle members. * Sets rectangle members such that it is centered at the given location, * with the width requested. - * \param cx requested center x-coordinate of the rectangle - * \param cy requested center y-coordinate of the rectangle - * \param w requested width of the rectangle - * \param h requested height of the rectangle + * \param cx requested center x-coordinate of the rectangle + * \param cy requested center y-coordinate of the rectangle + * \param w requested width of the rectangle + * \param h requested height of the rectangle */ virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy, GHOST_TInt32 w, GHOST_TInt32 h); @@ -175,8 +174,8 @@ public: * Clips a rectangle. * Updates the rectangle given such that it will fit within this one. * This can result in an empty rectangle. - * \param r the rectangle to clip - * \return whether clipping has occurred + * \param r the rectangle to clip + * \return whether clipping has occurred */ virtual bool clip(GHOST_Rect& r) const; diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index c6d364c361c..868d787b5f9 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -50,7 +50,7 @@ typedef unsigned short GHOST_TUns16; typedef int GHOST_TInt32; typedef unsigned int GHOST_TUns32; -#if defined(WIN32) && !defined(FREE_WINDOWS) +#ifdef _MSC_VER typedef __int64 GHOST_TInt64; typedef unsigned __int64 GHOST_TUns64; #else @@ -388,7 +388,7 @@ typedef struct { typedef struct { /** Displacement of a mouse wheel. */ - GHOST_TInt32 z; + GHOST_TInt32 z; } GHOST_TEventWheelData; typedef enum { diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 0a4325930d5..88d02c46f61 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -355,10 +355,11 @@ GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle, GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle, GHOST_TGrabCursorMode mode, - int *bounds) + int bounds[4], int mouse_ungrab_xy[2]) { GHOST_IWindow *window = (GHOST_IWindow *) windowhandle; GHOST_Rect bounds_rect, bounds_win; + GHOST_TInt32 mouse_ungrab_xy_global[2]; if (bounds) { /* if this is X11 specific we need a function that converts */ @@ -368,7 +369,16 @@ GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle, } - return window->setCursorGrab(mode, bounds ? &bounds_rect : NULL); + if (mouse_ungrab_xy) { + if (bounds == NULL) + window->getClientBounds(bounds_win); + window->clientToScreen(mouse_ungrab_xy[0], bounds_win.getHeight() - mouse_ungrab_xy[1], + mouse_ungrab_xy_global[0], mouse_ungrab_xy_global[1]); + } + + return window->setCursorGrab(mode, + bounds ? &bounds_rect : NULL, + mouse_ungrab_xy ? mouse_ungrab_xy_global : NULL); } diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h index c364f1d26a4..f0db1b3de8d 100644 --- a/intern/ghost/intern/GHOST_Debug.h +++ b/intern/ghost/intern/GHOST_Debug.h @@ -33,12 +33,12 @@ #ifndef __GHOST_DEBUG_H__ #define __GHOST_DEBUG_H__ -#if defined(WIN32) && !defined(FREE_WINDOWS) +#ifdef _MSC_VER # ifdef DEBUG # pragma warning (disable:4786) // suppress stl-MSVC debug info warning // #define GHOST_DEBUG # endif // DEBUG -#endif // WIN32 +#endif // _MSC_VER #ifdef WITH_GHOST_DEBUG # define GHOST_DEBUG // spit ghost events to stdout diff --git a/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm b/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm index c5a2fecd3b8..555f883cbf2 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_DisplayManagerCocoa.mm @@ -102,7 +102,7 @@ GHOST_TSuccess GHOST_DisplayManagerCocoa::getCurrentDisplaySetting(GHOST_TUns8 d GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::getCurrentDisplaySetting(): only main display is supported"); - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; if (display == kMainDisplay) //Screen #0 may not be the main one askedDisplay = [NSScreen mainScreen]; diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp index 0bd90854a31..754218191a5 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp +++ b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp @@ -88,8 +88,8 @@ getNumDisplaySettings( #else /* We only have one X11 setting at the moment. */ - GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n"); - numSettings = GHOST_TInt32(1); + GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n"); + numSettings = 1; #endif return GHOST_kSuccess; @@ -130,8 +130,8 @@ getDisplaySetting( setting.bpp = DefaultDepth(dpy, DefaultScreen(dpy)); #else - GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n"); - GHOST_ASSERT(index < 1, "Requested setting outside of valid range.\n"); + GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n"); + GHOST_ASSERT(index < 1, "Requested setting outside of valid range.\n"); Display *x_display = m_system->getXDisplay(); @@ -160,7 +160,7 @@ getCurrentDisplaySetting( /* According to the xf86vidmodegetallmodelines man page, * "The first element of the array corresponds to the current video mode." */ - return getDisplaySetting(display, GHOST_TInt32(0), setting); + return getDisplaySetting(display, 0, setting); } diff --git a/intern/ghost/intern/GHOST_EventDragnDrop.h b/intern/ghost/intern/GHOST_EventDragnDrop.h index cef9bb0a34a..c51f9568087 100644 --- a/intern/ghost/intern/GHOST_EventDragnDrop.h +++ b/intern/ghost/intern/GHOST_EventDragnDrop.h @@ -72,13 +72,13 @@ class GHOST_EventDragnDrop : public GHOST_Event public: /** * Constructor. - * \param time The time this event was generated. - * \param type The type of this event. - * \param dataType The type of the drop candidate object - * \param window The window where the event occurred - * \param x The x-coordinate of the location the cursor was at at the time of the event. - * \param y The y-coordinate of the location the cursor was at at the time of the event. - * \param data The "content" dropped in the window + * \param time The time this event was generated. + * \param type The type of this event. + * \param dataType The type of the drop candidate object + * \param window The window where the event occurred + * \param x The x-coordinate of the location the cursor was at at the time of the event. + * \param y The y-coordinate of the location the cursor was at at the time of the event. + * \param data The "content" dropped in the window */ GHOST_EventDragnDrop(GHOST_TUns64 time, GHOST_TEventType type, diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp index b8660b3038e..014eef85aa8 100644 --- a/intern/ghost/intern/GHOST_EventManager.cpp +++ b/intern/ghost/intern/GHOST_EventManager.cpp @@ -70,7 +70,7 @@ GHOST_TUns32 GHOST_EventManager::getNumEvents(GHOST_TEventType type) { GHOST_TUns32 numEvents = 0; TEventStack::iterator p; - for (p = m_events.begin(); p != m_events.end(); p++) { + for (p = m_events.begin(); p != m_events.end(); ++p) { if ((*p)->getType() == type) { numEvents++; } @@ -82,7 +82,7 @@ GHOST_TUns32 GHOST_EventManager::getNumEvents(GHOST_TEventType type) GHOST_IEvent *GHOST_EventManager::peekEvent() { GHOST_IEvent *event = 0; - if (m_events.size() > 0) { + if (m_events.empty() == false) { event = m_events.back(); } return event; @@ -110,7 +110,7 @@ bool GHOST_EventManager::dispatchEvent(GHOST_IEvent *event) if (event) { handled = true; TConsumerVector::iterator iter; - for (iter = m_consumers.begin(); iter != m_consumers.end(); iter++) { + for (iter = m_consumers.begin(); iter != m_consumers.end(); ++iter) { if ((*iter)->processEvent(event)) { handled = false; } @@ -212,7 +212,7 @@ void GHOST_EventManager::removeWindowEvents(GHOST_IWindow *window) iter = m_events.begin(); } else { - iter++; + ++iter; } } } @@ -236,7 +236,7 @@ void GHOST_EventManager::removeTypeEvents(GHOST_TEventType type, GHOST_IWindow * iter = m_events.begin(); } else { - iter++; + ++iter; } } } @@ -254,7 +254,7 @@ GHOST_IEvent *GHOST_EventManager::popEvent() void GHOST_EventManager::disposeEvents() { - while (m_events.size() > 0) { + while (m_events.empty() == false) { GHOST_ASSERT(m_events[0], "invalid event"); delete m_events[0]; m_events.pop_front(); diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 2baf0f6fa42..2c213752f94 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -107,7 +107,7 @@ class GHOST_NDOFManager public: GHOST_NDOFManager(GHOST_System&); - virtual ~GHOST_NDOFManager() {}; + virtual ~GHOST_NDOFManager() {} // whether multi-axis functionality is available (via the OS or driver) // does not imply that a device is plugged in or being used diff --git a/intern/ghost/intern/GHOST_Rect.cpp b/intern/ghost/intern/GHOST_Rect.cpp index dc30b3eb220..9af4f30ebc1 100644 --- a/intern/ghost/intern/GHOST_Rect.cpp +++ b/intern/ghost/intern/GHOST_Rect.cpp @@ -75,7 +75,7 @@ GHOST_TVisibility GHOST_Rect::getVisibility(GHOST_Rect& r) const GHOST_TVisibility v; if (lt && rt && lb && rb) { // All points inside, rectangle is inside this - v = GHOST_kFullyVisible; + v = GHOST_kFullyVisible; } else if (!(lt || rt || lb || rb)) { // None of the points inside diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index 070bf914dda..d2e3377f6ce 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -206,7 +206,7 @@ public: ***************************************************************************************/ /** Inherited from GHOST_ISystem but left pure virtual - * GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const = 0; + * GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const = 0; * GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) */ diff --git a/intern/ghost/intern/GHOST_SystemCarbon.cpp b/intern/ghost/intern/GHOST_SystemCarbon.cpp index bb68ce8889c..f5784c7d451 100644 --- a/intern/ghost/intern/GHOST_SystemCarbon.cpp +++ b/intern/ghost/intern/GHOST_SystemCarbon.cpp @@ -126,7 +126,7 @@ static GHOST_TKey convertKey(int rawCode) */ static UInt32 dummy = 0; Handle transData = (Handle) GetScriptManagerVariable(smKCHRCache); - unsigned char vk = KeyTranslate(transData, rawCode, &dummy); + unsigned char vk = KeyTranslate(transData, rawCode, &dummy); /* Map numpad based on rawcodes first, otherwise they * look like non-numpad events. * Added too: mapping the number keys, for french keyboards etc (ton) diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 7bc40287dc3..27720a01a3f 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -355,16 +355,18 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) /* alphanumerical or punctuation key that is remappable in int'l keyboards */ if ((recvChar >= 'A') && (recvChar <= 'Z')) { return (GHOST_TKey) (recvChar - 'A' + GHOST_kKeyA); - } else if ((recvChar >= 'a') && (recvChar <= 'z')) { + } + else if ((recvChar >= 'a') && (recvChar <= 'z')) { return (GHOST_TKey) (recvChar - 'a' + GHOST_kKeyA); - } else { + } + else { #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 KeyboardLayoutRef keyLayout; UCKeyboardLayout *uchrData; KLGetCurrentKeyboardLayout(&keyLayout); KLGetKeyboardLayoutProperty(keyLayout, kKLuchrData, (const void **) - &uchrData); + &uchrData); /*get actual character value of the "remappable" keys in int'l keyboards, if keyboard layout is not correctly reported (e.g. some non Apple keyboards in Tiger), then fallback on using the received charactersIgnoringModifiers */ @@ -457,7 +459,8 @@ extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) strncpy(buf, g_firstFileBuf, FIRSTFILEBUFLG - 1); buf[FIRSTFILEBUFLG - 1] = '\0'; return 1; - } else { + } + else { return 0; } } @@ -870,29 +873,30 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) // SetMouseCoalescingEnabled(false, NULL); //TODO : implement timer ?? - - /*do { +#if 0 + do { GHOST_TimerManager* timerMgr = getTimerManager(); if (waitForEvent) { - GHOST_TUns64 next = timerMgr->nextFireTime(); - double timeOut; + GHOST_TUns64 next = timerMgr->nextFireTime(); + double timeOut; - if (next == GHOST_kFireTimeNever) { - timeOut = kEventDurationForever; - } else { - timeOut = (double)(next - getMilliSeconds())/1000.0; - if (timeOut < 0.0) - timeOut = 0.0; - } + if (next == GHOST_kFireTimeNever) { + timeOut = kEventDurationForever; + } + else { + timeOut = (double)(next - getMilliSeconds())/1000.0; + if (timeOut < 0.0) + timeOut = 0.0; + } - ::ReceiveNextEvent(0, NULL, timeOut, false, &event); + ::ReceiveNextEvent(0, NULL, timeOut, false, &event); } if (timerMgr->fireTimers(getMilliSeconds())) { - anyProcessed = true; + anyProcessed = true; } - */ +#endif do { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -962,8 +966,10 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) //Resend event to NSApp to ensure Mac wide events are handled [NSApp sendEvent:event]; [pool drain]; - } while (event!= nil); - //} while (waitForEvent && !anyProcessed); Needed only for timer implementation + } while (event != nil); +#if 0 + } while (waitForEvent && !anyProcessed); // Needed only for timer implementation +#endif if (m_needDelayedApplicationBecomeActiveEventProcessing) handleApplicationBecomeActiveEvent(); @@ -994,16 +1000,16 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent() modifiers = [[[NSApplication sharedApplication] currentEvent] modifierFlags]; if ((modifiers & NSShiftKeyMask) != (m_modifierMask & NSShiftKeyMask)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) ); + pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSShiftKeyMask) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift)); } if ((modifiers & NSControlKeyMask) != (m_modifierMask & NSControlKeyMask)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSControlKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) ); + pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSControlKeyMask) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl)); } if ((modifiers & NSAlternateKeyMask) != (m_modifierMask & NSAlternateKeyMask)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSAlternateKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) ); + pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSAlternateKeyMask) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt)); } if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyOS) ); + pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSCommandKeyMask) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, GHOST_kKeyOS)); } m_modifierMask = modifiers; @@ -1046,7 +1052,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, case GHOST_kEventWindowSize: if (!m_ignoreWindowSizedMessages) { - //Enforce only one resize message per event loop (coalescing all the live resize messages) + //Enforce only one resize message per event loop (coalescing all the live resize messages) window->updateDrawingContext(); pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) ); //Mouse up event is trapped by the resizing event loop, so send it anyway to the window manager @@ -1083,7 +1089,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType GHOST_TUns8 * temp_buff; GHOST_TStringArray *strArray; NSArray *droppedArray; - size_t pastedTextSize; + size_t pastedTextSize; NSString *droppedStr; GHOST_TEventDataPtr eventData; int i; @@ -1120,7 +1126,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType strArray->strings[i] = temp_buff; } - eventData = (GHOST_TEventDataPtr) strArray; + eventData = (GHOST_TEventDataPtr) strArray; break; case GHOST_kDragnDropTypeString: @@ -1153,7 +1159,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType NSEnumerator *enumerator; NSImageRep *representation; - ibuf = IMB_allocImBuf (imgSize.width , imgSize.height, 32, IB_rect); + ibuf = IMB_allocImBuf (imgSize.width, imgSize.height, 32, IB_rect); if (!ibuf) { [droppedImg release]; return GHOST_kFailure; @@ -1285,12 +1291,13 @@ GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest() if (m_windowManager->getAnyModifiedState()) { int shouldQuit = NSRunAlertPanel(@"Exit Blender", @"Some changes have not been saved.\nDo you really want to quit ?", - @"Cancel", @"Quit Anyway", nil); + @"Cancel", @"Quit Anyway", nil); if (shouldQuit == NSAlertAlternateReturn) { pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL) ); return GHOST_kExitNow; - } else { + } + else { //Give back focus to the blender window if user selected cancel quit NSArray *windowsList = [NSApp orderedWindows]; if ([windowsList count]) { @@ -1319,7 +1326,7 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr) int confirmOpen = NSAlertAlternateReturn; NSArray *windowsList; char * temp_buff; - size_t filenameTextSize; + size_t filenameTextSize; GHOST_Window* window= (GHOST_Window*)m_windowManager->getActiveWindow(); if (!window) { @@ -1405,7 +1412,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr, short eventT ct.Active = GHOST_kTabletModeNone; break; } - } else { + } + else { // pointer is leaving - return to mouse ct.Active = GHOST_kTabletModeNone; } @@ -1452,7 +1460,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown: - pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonDown, window, convertButton([event buttonNumber]))); + pushEvent(new GHOST_EventButton([event timestamp] * 1000, GHOST_kEventButtonDown, window, convertButton([event buttonNumber]))); //Handle tablet events combined with mouse events handleTabletEvent(event); break; @@ -1460,14 +1468,14 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: - pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonUp, window, convertButton([event buttonNumber]))); + pushEvent(new GHOST_EventButton([event timestamp] * 1000, GHOST_kEventButtonUp, window, convertButton([event buttonNumber]))); //Handle tablet events combined with mouse events handleTabletEvent(event); break; case NSLeftMouseDragged: case NSRightMouseDragged: - case NSOtherMouseDragged: + case NSOtherMouseDragged: //Handle tablet events combined with mouse events handleTabletEvent(event); @@ -1495,7 +1503,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) window->setCursorGrabAccum(x_accum, y_accum); window->clientToScreenIntern(x_warp+x_accum, y_warp+y_accum, x, y); - pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x, y)); + pushEvent(new GHOST_EventCursor([event timestamp] * 1000, GHOST_kEventCursorMove, window, x, y)); } break; case GHOST_kGrabWrap: //Wrap cursor at area/window boundaries @@ -1540,7 +1548,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) //Post event window->getCursorGrabInitPos(x_cur, y_cur); window->clientToScreenIntern(x_cur + x_accum, y_cur + y_accum, x, y); - pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x, y)); + pushEvent(new GHOST_EventCursor([event timestamp] * 1000, GHOST_kEventCursorMove, window, x, y)); } break; default: @@ -1550,7 +1558,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) GHOST_TInt32 x, y; window->clientToScreenIntern(mousePos.x, mousePos.y, x, y); - pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x, y)); + pushEvent(new GHOST_EventCursor([event timestamp] * 1000, GHOST_kEventCursorMove, window, x, y)); m_cursorDelta_x=0; m_cursorDelta_y=0; //Mouse motion occurred between two cursor warps, so we can reset the delta counter @@ -1572,7 +1580,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) if (deltaF == 0.0) break; //discard trackpad delta=0 events delta = deltaF > 0.0 ? 1 : -1; - pushEvent(new GHOST_EventWheel([event timestamp]*1000, window, delta)); + pushEvent(new GHOST_EventWheel([event timestamp] * 1000, window, delta)); } else { NSPoint mousePos = [event locationInWindow]; @@ -1596,7 +1604,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) window->clientToScreenIntern(mousePos.x, mousePos.y, x, y); dy = -dy; - pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventScroll, x, y, dx, dy)); + pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000, window, GHOST_kTrackpadEventScroll, x, y, dx, dy)); } } break; @@ -1606,8 +1614,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) NSPoint mousePos = [event locationInWindow]; GHOST_TInt32 x, y; window->clientToScreenIntern(mousePos.x, mousePos.y, x, y); - pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventMagnify, x, y, - [event magnification]*125.0 + 0.1, 0)); + pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000, window, GHOST_kTrackpadEventMagnify, x, y, + [event magnification] * 125.0 + 0.1, 0)); } break; @@ -1616,8 +1624,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) NSPoint mousePos = [event locationInWindow]; GHOST_TInt32 x, y; window->clientToScreenIntern(mousePos.x, mousePos.y, x, y); - pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventRotate, x, y, - -[event rotation] * 5.0, 0)); + pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000, window, GHOST_kTrackpadEventRotate, x, y, + -[event rotation] * 5.0, 0)); } case NSEventTypeBeginGesture: m_isGestureInProgress = true; @@ -1692,10 +1700,11 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) break; //Cmd-Q is directly handled by Cocoa if ([event type] == NSKeyDown) { - pushEvent( new GHOST_EventKey([event timestamp]*1000, GHOST_kEventKeyDown, window, keyCode, ascii, utf8_buf) ); + pushEvent( new GHOST_EventKey([event timestamp] * 1000, GHOST_kEventKeyDown, window, keyCode, ascii, utf8_buf) ); //printf("Key down rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c utf8=%s\n",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii, utf8_buf); - } else { - pushEvent( new GHOST_EventKey([event timestamp]*1000, GHOST_kEventKeyUp, window, keyCode, 0, '\0') ); + } + else { + pushEvent( new GHOST_EventKey([event timestamp] * 1000, GHOST_kEventKeyUp, window, keyCode, 0, '\0') ); //printf("Key up rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c utf8=%s\n",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii, utf8_buf); } break; @@ -1704,16 +1713,16 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) modifiers = [event modifierFlags]; if ((modifiers & NSShiftKeyMask) != (m_modifierMask & NSShiftKeyMask)) { - pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) ); + pushEvent(new GHOST_EventKey([event timestamp] * 1000, (modifiers & NSShiftKeyMask) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift)); } if ((modifiers & NSControlKeyMask) != (m_modifierMask & NSControlKeyMask)) { - pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSControlKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) ); + pushEvent(new GHOST_EventKey([event timestamp] * 1000, (modifiers & NSControlKeyMask) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl)); } if ((modifiers & NSAlternateKeyMask) != (m_modifierMask & NSAlternateKeyMask)) { - pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSAlternateKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) ); + pushEvent(new GHOST_EventKey([event timestamp] * 1000, (modifiers & NSAlternateKeyMask) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt)); } if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) { - pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyOS) ); + pushEvent(new GHOST_EventKey([event timestamp] * 1000, (modifiers & NSCommandKeyMask) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, GHOST_kKeyOS)); } m_modifierMask = modifiers; @@ -1734,7 +1743,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const { GHOST_TUns8 * temp_buff; - size_t pastedTextSize; + size_t pastedTextSize; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -1780,7 +1789,8 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const if(temp_buff) { return temp_buff; - } else { + } + else { return NULL; } } diff --git a/intern/ghost/intern/GHOST_SystemPaths.h b/intern/ghost/intern/GHOST_SystemPaths.h index 53cad347293..22879c71e1e 100644 --- a/intern/ghost/intern/GHOST_SystemPaths.h +++ b/intern/ghost/intern/GHOST_SystemPaths.h @@ -40,13 +40,13 @@ protected: * Constructor. * Protected default constructor to force use of static createSystem member. */ - GHOST_SystemPaths() {}; + GHOST_SystemPaths() {} /** * Destructor. * Protected default constructor to force use of static dispose member. */ - virtual ~GHOST_SystemPaths() {}; + virtual ~GHOST_SystemPaths() {} public: diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 52ebaf02404..46c71f57c6f 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -742,8 +742,6 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINP ascii = utf8_char[0] & 0x80 ? '?' : utf8_char[0]; } - if (0x80 & state[VK_MENU]) utf8_char[0] = '\0'; - event = new GHOST_EventKey(system->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown : GHOST_kEventKeyUp, window, key, ascii, utf8_char); #ifdef GHOST_DEBUG diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index e75ecfb641e..c9953c80a52 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -858,7 +858,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) } case DestroyNotify: - ::exit(-1); + ::exit(-1); /* We're not interested in the following things.(yet...) */ case NoExpose: case GraphicsExpose: @@ -983,8 +983,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) default: { #ifdef WITH_X11_XINPUT - if (xe->type == window->GetXTablet().MotionEvent) - { + if (xe->type == window->GetXTablet().MotionEvent) { XDeviceMotionEvent *data = (XDeviceMotionEvent *)xe; /* stroke might begin without leading ProxyIn event, @@ -993,23 +992,23 @@ GHOST_SystemX11::processEvent(XEvent *xe) setTabletMode(window, data->deviceid); window->GetXTablet().CommonData.Pressure = - data->axis_data[2] / ((float)window->GetXTablet().PressureLevels); - + data->axis_data[2] / ((float)window->GetXTablet().PressureLevels); + /* the (short) cast and the &0xffff is bizarre and unexplained anywhere, * but I got garbage data without it. Found it in the xidump.c source --matt */ window->GetXTablet().CommonData.Xtilt = - (short)(data->axis_data[3] & 0xffff) / ((float)window->GetXTablet().XtiltLevels); + (short)(data->axis_data[3] & 0xffff) / ((float)window->GetXTablet().XtiltLevels); window->GetXTablet().CommonData.Ytilt = - (short)(data->axis_data[4] & 0xffff) / ((float)window->GetXTablet().YtiltLevels); + (short)(data->axis_data[4] & 0xffff) / ((float)window->GetXTablet().YtiltLevels); } - else if (xe->type == window->GetXTablet().ProxInEvent) - { + else if (xe->type == window->GetXTablet().ProxInEvent) { XProximityNotifyEvent *data = (XProximityNotifyEvent *)xe; setTabletMode(window, data->deviceid); } - else if (xe->type == window->GetXTablet().ProxOutEvent) + else if (xe->type == window->GetXTablet().ProxOutEvent) { window->GetXTablet().CommonData.Active = GHOST_kTabletModeNone; + } #endif // WITH_X11_XINPUT break; } @@ -1172,7 +1171,7 @@ generateWindowExposeEvents() *w_start ); - (*w_start)->validate(); + (*w_start)->validate(); if (g_event) { pushEvent(g_event); @@ -1457,7 +1456,7 @@ void GHOST_SystemX11::getClipboard_xcout(XEvent evt, /* check size and format of the property */ XGetWindowProperty(m_display, win, m_xclip_out, 0, 0, False, AnyPropertyType, &pty_type, &pty_format, - &pty_items, &pty_size, (unsigned char **) &buffer); + &pty_items, &pty_size, &buffer); if (pty_format != 8) { /* property does not contain text, delete it @@ -1485,7 +1484,7 @@ void GHOST_SystemX11::getClipboard_xcout(XEvent evt, * text, we know the size. */ XGetWindowProperty(m_display, win, m_xclip_out, 0, (long) pty_size, False, AnyPropertyType, &pty_type, &pty_format, - &pty_items, &pty_size, (unsigned char **) &buffer); + &pty_items, &pty_size, &buffer); /* allocate memory to accommodate data in *txt */ if (*len == 0) { @@ -1539,12 +1538,12 @@ GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const if (sseln == m_clipboard) { sel_buf = (unsigned char *)malloc(strlen(txt_cut_buffer) + 1); strcpy((char *)sel_buf, txt_cut_buffer); - return((GHOST_TUns8 *)sel_buf); + return sel_buf; } else { sel_buf = (unsigned char *)malloc(strlen(txt_select_buffer) + 1); strcpy((char *)sel_buf, txt_select_buffer); - return((GHOST_TUns8 *)sel_buf); + return sel_buf; } } else if (owner == None) @@ -1595,7 +1594,7 @@ GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const else free(sel_buf); - return (GHOST_TUns8 *)tmp_data; + return tmp_data; } return(NULL); } @@ -1604,7 +1603,7 @@ void GHOST_SystemX11::putClipboard(GHOST_TInt8 *buffer, bool selection) const { Window m_window, owner; - vector & win_vec = m_windowManager->getWindows(); + vector & win_vec = m_windowManager->getWindows(); vector::iterator win_it = win_vec.begin(); GHOST_WindowX11 *window = static_cast(*win_it); m_window = window->getXWindow(); diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index 92bffe46357..02c0109085a 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -210,8 +210,8 @@ public: #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING) XIM - getX11_XIM( - ) { + getX11_XIM() + { return m_xim; } #endif @@ -230,12 +230,12 @@ public: /** * Puts buffer to system clipboard - * \param buffer The buffer to copy to the clipboard + * \param buffer The buffer to copy to the clipboard * \param selection Set the selection into the clipboard, X11 only feature */ void putClipboard(GHOST_TInt8 *buffer, bool selection) const; -#if WITH_XDND +#ifdef WITH_XDND /** * Creates a drag'n'drop event and pushes it immediately onto the event queue. * Called by GHOST_DropTargetX11 class. diff --git a/intern/ghost/intern/GHOST_TimerManager.cpp b/intern/ghost/intern/GHOST_TimerManager.cpp index b1186507028..601359984de 100644 --- a/intern/ghost/intern/GHOST_TimerManager.cpp +++ b/intern/ghost/intern/GHOST_TimerManager.cpp @@ -104,7 +104,7 @@ GHOST_TUns64 GHOST_TimerManager::nextFireTime() GHOST_TUns64 smallest = GHOST_kFireTimeNever; TTimerVector::iterator iter; - for (iter = m_timers.begin(); iter != m_timers.end(); iter++) { + for (iter = m_timers.begin(); iter != m_timers.end(); ++iter) { GHOST_TUns64 next = (*iter)->getNext(); if (next < smallest) @@ -119,7 +119,7 @@ bool GHOST_TimerManager::fireTimers(GHOST_TUns64 time) TTimerVector::iterator iter; bool anyProcessed = false; - for (iter = m_timers.begin(); iter != m_timers.end(); iter++) { + for (iter = m_timers.begin(); iter != m_timers.end(); ++iter) { if (fireTimer(time, *iter)) anyProcessed = true; } @@ -156,7 +156,7 @@ bool GHOST_TimerManager::fireTimer(GHOST_TUns64 time, GHOST_TimerTask *task) void GHOST_TimerManager::disposeTimers() { - while (m_timers.size() > 0) { + while (m_timers.empty() == false) { delete m_timers[0]; m_timers.erase(m_timers.begin()); } diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp index eb80a073b44..fd3ff4f85f0 100644 --- a/intern/ghost/intern/GHOST_Window.cpp +++ b/intern/ghost/intern/GHOST_Window.cpp @@ -38,6 +38,7 @@ #include "GHOST_Window.h" +#include GHOST_Window::GHOST_Window( GHOST_TUns32 width, GHOST_TUns32 height, @@ -105,11 +106,18 @@ GHOST_TSuccess GHOST_Window::setCursorVisibility(bool visible) } } -GHOST_TSuccess GHOST_Window::setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds) +GHOST_TSuccess GHOST_Window::setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds, GHOST_TInt32 mouse_ungrab_xy[2]) { if (m_cursorGrab == mode) return GHOST_kSuccess; + /* override with new location */ + if (mouse_ungrab_xy) { + assert(mode == GHOST_kGrabDisable); + m_cursorGrabInitPos[0] = mouse_ungrab_xy[0]; + m_cursorGrabInitPos[1] = mouse_ungrab_xy[1]; + } + if (setWindowCursorGrab(mode)) { if (mode == GHOST_kGrabDisable) diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index 3043b107aa1..fd870327fd4 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -178,7 +178,7 @@ public: * \param mode The new grab state of the cursor. * \return Indication of success. */ - virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds); + virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds, GHOST_TInt32 mouse_ungrab_xy[2]); /** * Gets the cursor grab region, if unset the window is used. @@ -192,14 +192,14 @@ public: */ virtual GHOST_TSuccess setProgressBar(float progress) { return GHOST_kFailure; - }; + } /** * Hides the progress bar in the icon */ virtual GHOST_TSuccess endProgressBar() { return GHOST_kFailure; - }; + } /** * Tells if the ongoing drag'n'drop object can be accepted upon mouse drop @@ -284,7 +284,7 @@ protected: */ virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode) { return GHOST_kSuccess; - }; + } /** * Sets the cursor shape on the window using diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 31589003131..23eefe17959 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -187,7 +187,7 @@ extern "C" { NSPoint mouseLocation = [sender draggingLocation]; systemCocoa->handleDraggingEvent(GHOST_kEventDraggingUpdated, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, nil); - return associatedWindow->canAcceptDragOperation()?NSDragOperationCopy:NSDragOperationNone; + return associatedWindow->canAcceptDragOperation() ? NSDragOperationCopy : NSDragOperationNone; } - (void)draggingExited:(id < NSDraggingInfo >)sender @@ -368,7 +368,7 @@ extern "C" { - (BOOL)hasMarkedText { - return (composing)? YES: NO; + return (composing) ? YES : NO; } - (void)doCommandBySelector:(SEL)selector @@ -392,7 +392,7 @@ extern "C" { - (NSRange)markedRange { - unsigned int length = (composing_text)? [composing_text length]: 0; + unsigned int length = (composing_text) ? [composing_text length] : 0; if (composing) return NSMakeRange(0, length); @@ -402,7 +402,7 @@ extern "C" { - (NSRange)selectedRange { - unsigned int length = (composing_text)? [composing_text length]: 0; + unsigned int length = (composing_text) ? [composing_text length] : 0; return NSMakeRange(0, length); } @@ -637,7 +637,7 @@ void* GHOST_WindowCocoa::getOSWindow() const void GHOST_WindowCocoa::setTitle(const STR_String& title) { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *windowTitle = [[NSString alloc] initWithCString:title encoding:NSUTF8StringEncoding]; @@ -670,7 +670,8 @@ void GHOST_WindowCocoa::setTitle(const STR_String& title) [m_window setRepresentedFilename:@""]; } - } else { + } + else { [m_window setTitle:windowTitle]; [m_window setRepresentedFilename:@""]; } @@ -683,7 +684,7 @@ void GHOST_WindowCocoa::setTitle(const STR_String& title) void GHOST_WindowCocoa::getTitle(STR_String& title) const { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -700,7 +701,7 @@ void GHOST_WindowCocoa::getTitle(STR_String& title) const void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect& bounds) const { NSRect rect; - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -720,7 +721,7 @@ void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect& bounds) const void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const { NSRect rect; - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getClientBounds(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getClientBounds(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -752,7 +753,7 @@ void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width) { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientWidth(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientWidth(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); @@ -769,7 +770,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width) GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height) { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); @@ -786,7 +787,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height) GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); @@ -805,7 +806,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 GHOST_TWindowState GHOST_WindowCocoa::getState() const { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getState(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getState(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_TWindowState state; if (m_fullScreen) { @@ -827,7 +828,7 @@ GHOST_TWindowState GHOST_WindowCocoa::getState() const void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::screenToClient(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::screenToClient(): window invalid"); screenToClientIntern(inX, inY, outX, outY); @@ -840,7 +841,7 @@ void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST void GHOST_WindowCocoa::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::clientToScreen(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::clientToScreen(): window invalid"); /* switch y to match ghost convention */ GHOST_Rect cBnds; @@ -894,7 +895,7 @@ NSScreen* GHOST_WindowCocoa::getScreen() */ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setState(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setState(): window invalid"); switch (state) { case GHOST_kWindowStateMinimized: [m_window miniaturize:nil]; @@ -1048,7 +1049,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setOrder(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setOrder(): window invalid"); if (order == GHOST_kWindowOrderTop) { [m_window makeKeyAndOrderFront:nil]; } @@ -1198,7 +1199,7 @@ GHOST_TSuccess GHOST_WindowCocoa::removeDrawingContext() GHOST_TSuccess GHOST_WindowCocoa::invalidate() { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::invalidate(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::invalidate(): window invalid"); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [m_openGLView setNeedsDisplay:YES]; [pool drain]; @@ -1288,7 +1289,8 @@ void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) c if (cursor == GHOST_kStandardCursorCustom && m_customCursor) { tmpCursor = m_customCursor; - } else { + } + else { switch (cursor) { case GHOST_kStandardCursorDestroy: tmpCursor = [NSCursor disappearingItemCursor]; diff --git a/intern/ghost/intern/GHOST_WindowManager.cpp b/intern/ghost/intern/GHOST_WindowManager.cpp index 1816c57a150..daf1c2f2d22 100644 --- a/intern/ghost/intern/GHOST_WindowManager.cpp +++ b/intern/ghost/intern/GHOST_WindowManager.cpp @@ -195,7 +195,7 @@ GHOST_IWindow *GHOST_WindowManager::getWindowAssociatedWithOSWindow(void *osWind { std::vector::iterator iter; - for (iter = m_windows.begin(); iter != m_windows.end(); iter++) { + for (iter = m_windows.begin(); iter != m_windows.end(); ++iter) { if ((*iter)->getOSWindow() == osWindow) return *iter; } @@ -208,7 +208,7 @@ bool GHOST_WindowManager::getAnyModifiedState() bool isAnyModified = false; std::vector::iterator iter; - for (iter = m_windows.begin(); iter != m_windows.end(); iter++) { + for (iter = m_windows.begin(); iter != m_windows.end(); ++iter) { if ((*iter)->getModifiedState()) isAnyModified = true; } diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index c9c902fca8b..dded7dc256d 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -720,7 +720,7 @@ GHOST_TSuccess GHOST_WindowWin32::initMultisample(PIXELFORMATDESCRIPTOR pfd) }; // Get the function - PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); + PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); if (!wglChoosePixelFormatARB) { diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 4ad95fcab53..dd1930a241b 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -76,7 +76,7 @@ typedef struct { */ #define _NET_WM_STATE_REMOVE 0 #define _NET_WM_STATE_ADD 1 -#define _NET_WM_STATE_TOGGLE 2 +// #define _NET_WM_STATE_TOGGLE 2 // UNUSED /* import bpy @@ -1326,7 +1326,7 @@ GHOST_WindowX11:: c_owner = XGetSelectionOwner(m_display, Clipboard_atom); std::map::iterator it = m_standard_cursors.begin(); - for (; it != m_standard_cursors.end(); it++) { + for (; it != m_standard_cursors.end(); ++it) { XFreeCursor(m_display, it->second); } diff --git a/intern/ghost/test/multitest/EventToBuf.c b/intern/ghost/test/multitest/EventToBuf.c index 0eb37a58be2..49255de5e64 100644 --- a/intern/ghost/test/multitest/EventToBuf.c +++ b/intern/ghost/test/multitest/EventToBuf.c @@ -197,31 +197,32 @@ static char *keytype_to_string(GHOST_TKey key) void event_to_buf(GHOST_EventHandle evt, char buf[128]) { - GHOST_TEventType type= GHOST_GetEventType(evt); - double time= (double) ((GHOST_TInt64) GHOST_GetEventTime(evt))/1000; - GHOST_WindowHandle win= GHOST_GetEventWindow(evt); - void *data= GHOST_GetEventData(evt); - char *pos= buf; + GHOST_TEventType type = GHOST_GetEventType(evt); + double time = (double) ((GHOST_TInt64) GHOST_GetEventTime(evt))/1000; + GHOST_WindowHandle win = GHOST_GetEventWindow(evt); + void *data = GHOST_GetEventData(evt); + char *pos = buf; pos += sprintf(pos, "event: %6.2f, %16s", time, eventtype_to_string(type)); if (win) { - char *s= GHOST_GetTitle(win); + char *s = GHOST_GetTitle(win); pos += sprintf(pos, " - win: %s", s); free(s); - } else { + } + else { pos+= sprintf(pos, " - sys evt"); } switch (type) { case GHOST_kEventCursorMove: { - GHOST_TEventCursorData *cd= data; + GHOST_TEventCursorData *cd = data; pos += sprintf(pos, " - pos: (%d, %d)", cd->x, cd->y); break; } case GHOST_kEventButtonDown: case GHOST_kEventButtonUp: { - GHOST_TEventButtonData *bd= data; + GHOST_TEventButtonData *bd = data; pos += sprintf(pos, " - but: %d", bd->button); break; } @@ -229,7 +230,7 @@ void event_to_buf(GHOST_EventHandle evt, char buf[128]) case GHOST_kEventKeyDown: case GHOST_kEventKeyUp: { - GHOST_TEventKeyData *kd= data; + GHOST_TEventKeyData *kd = data; pos += sprintf(pos, " - key: %s (%d)", keytype_to_string(kd->key), kd->key); if (kd->ascii) pos+= sprintf(pos, " ascii: '%c' (%d)", kd->ascii, kd->ascii); break; diff --git a/intern/ghost/test/multitest/MultiTest.c b/intern/ghost/test/multitest/MultiTest.c index 5d207dafaaf..2d0afcf671c 100644 --- a/intern/ghost/test/multitest/MultiTest.c +++ b/intern/ghost/test/multitest/MultiTest.c @@ -26,9 +26,8 @@ */ #define FALSE 0 -#ifdef WIN32 - -#pragma warning(disable: 4244 4305) +#ifdef _MSC_VER +# pragma warning(disable: 4244 4305) #endif #include diff --git a/intern/guardedalloc/test/simpletest/memtest.c b/intern/guardedalloc/test/simpletest/memtest.c index 7c6a0a2d546..749e2500dd1 100644 --- a/intern/guardedalloc/test/simpletest/memtest.c +++ b/intern/guardedalloc/test/simpletest/memtest.c @@ -94,7 +94,8 @@ int main (int argc, char *argv[]) if (verbose) { if (error_status) { fprintf(stderr, "|--* Memory test FAILED\n|\n"); - } else { + } + else { fprintf(stderr, "|--* Memory tested as good (as it should be)\n|\n"); } } @@ -130,7 +131,8 @@ int main (int argc, char *argv[]) if (verbose) { if (retval) { fprintf(stderr, "|--* Memory test failed (as it should be)\n"); - } else { + } + else { fprintf(stderr, "|--* Memory test FAILED to find corrupted blocks \n"); } } @@ -147,7 +149,8 @@ int main (int argc, char *argv[]) if (verbose) { if (error_status) { fprintf(stderr,"|\n|--* Errors were detected\n"); - } else { + } + else { fprintf(stderr,"|\n|--* Test exited succesfully\n"); } diff --git a/intern/iksolver/intern/IK_QJacobianSolver.h b/intern/iksolver/intern/IK_QJacobianSolver.h index ead2b150b40..646f952b9ff 100644 --- a/intern/iksolver/intern/IK_QJacobianSolver.h +++ b/intern/iksolver/intern/IK_QJacobianSolver.h @@ -53,12 +53,12 @@ class IK_QJacobianSolver { public: IK_QJacobianSolver(); - ~IK_QJacobianSolver() {}; + ~IK_QJacobianSolver() {} // setup pole vector constraint void SetPoleVectorConstraint(IK_QSegment *tip, MT_Vector3& goal, MT_Vector3& polegoal, float poleangle, bool getangle); - float GetPoleAngle() { return m_poleangle; }; + float GetPoleAngle() { return m_poleangle; } // call setup once before solving, if it fails don't solve bool Setup(IK_QSegment *root, std::list& tasks); diff --git a/intern/iksolver/intern/IK_QSegment.h b/intern/iksolver/intern/IK_QSegment.h index 25a8fbc0804..b40bf3739ff 100644 --- a/intern/iksolver/intern/IK_QSegment.h +++ b/intern/iksolver/intern/IK_QSegment.h @@ -158,10 +158,10 @@ public: virtual void UpdateAngleApply()=0; // set joint limits - virtual void SetLimit(int, MT_Scalar, MT_Scalar) {}; + virtual void SetLimit(int, MT_Scalar, MT_Scalar) {} // set joint weights (per axis) - virtual void SetWeight(int, MT_Scalar) {}; + virtual void SetWeight(int, MT_Scalar) {} virtual void SetBasis(const MT_Matrix3x3& basis) { m_basis = basis; } diff --git a/intern/iksolver/intern/IK_QTask.h b/intern/iksolver/intern/IK_QTask.h index 45b1e59e606..baf1c346d62 100644 --- a/intern/iksolver/intern/IK_QTask.h +++ b/intern/iksolver/intern/IK_QTask.h @@ -49,7 +49,7 @@ public: bool active, const IK_QSegment *segment ); - virtual ~IK_QTask() {}; + virtual ~IK_QTask() {} int Id() const { return m_size; } @@ -119,7 +119,7 @@ public: const MT_Matrix3x3& goal ); - MT_Scalar Distance() const { return m_distance; }; + MT_Scalar Distance() const { return m_distance; } void ComputeJacobian(IK_QJacobian& jacobian); private: diff --git a/intern/iksolver/intern/IK_Solver.cpp b/intern/iksolver/intern/IK_Solver.cpp index 6c2e30932bb..c1a4ffcb1e8 100644 --- a/intern/iksolver/intern/IK_Solver.cpp +++ b/intern/iksolver/intern/IK_Solver.cpp @@ -43,7 +43,7 @@ using namespace std; class IK_QSolver { public: IK_QSolver() : root(NULL) { - }; + } IK_QJacobianSolver solver; IK_QSegment *root; @@ -51,7 +51,7 @@ public: }; // FIXME: locks still result in small "residual" changes to the locked axes... -IK_QSegment *CreateSegment(int flag, bool translate) +static IK_QSegment *CreateSegment(int flag, bool translate) { int ndof = 0; ndof += (flag & IK_XDOF) ? 1 : 0; @@ -348,7 +348,7 @@ float IK_SolverGetPoleAngle(IK_Solver *solver) return qsolver->solver.GetPoleAngle(); } -void IK_SolverAddCenterOfMass(IK_Solver *solver, IK_Segment *root, float goal[3], float weight) +static void IK_SolverAddCenterOfMass(IK_Solver *solver, IK_Segment *root, float goal[3], float weight) { if (solver == NULL || root == NULL) return; diff --git a/intern/iksolver/intern/MT_ExpMap.h b/intern/iksolver/intern/MT_ExpMap.h index 9485428dc9f..65bbe4d4ad5 100644 --- a/intern/iksolver/intern/MT_ExpMap.h +++ b/intern/iksolver/intern/MT_ExpMap.h @@ -103,7 +103,7 @@ public: const MT_Quaternion &q ) { setRotation(q); - }; + } /** * Accessors @@ -118,7 +118,7 @@ public: vector( ) const { return m_v; - }; + } /** * Set the exponential map from a quaternion diff --git a/intern/iksolver/intern/TNT/cmat.h b/intern/iksolver/intern/TNT/cmat.h index 146afdc79d7..fd3a1851262 100644 --- a/intern/iksolver/intern/TNT/cmat.h +++ b/intern/iksolver/intern/TNT/cmat.h @@ -182,7 +182,7 @@ class Matrix // constructors - Matrix() : m_(0), n_(0), mn_(0), v_(0), row_(0), vm1_(0), rowm1_(0) {}; + Matrix() : m_(0), n_(0), mn_(0), v_(0), row_(0), vm1_(0), rowm1_(0) {} Matrix(const Matrix &A) { diff --git a/intern/iksolver/intern/TNT/vec.h b/intern/iksolver/intern/TNT/vec.h index ff1b5c0ea0e..5d4ef14bf73 100644 --- a/intern/iksolver/intern/TNT/vec.h +++ b/intern/iksolver/intern/TNT/vec.h @@ -164,7 +164,7 @@ class Vector // constructors - Vector() : v_(0), vm1_(0), n_(0) {}; + Vector() : v_(0), vm1_(0), n_(0) {} Vector(const Vector &A) : v_(0), vm1_(0), n_(0) { diff --git a/intern/itasc/CMakeLists.txt b/intern/itasc/CMakeLists.txt index f4bc0326ea1..99c64d956cb 100644 --- a/intern/itasc/CMakeLists.txt +++ b/intern/itasc/CMakeLists.txt @@ -24,11 +24,11 @@ # ***** END GPL LICENSE BLOCK ***** set(INC - ../../extern/Eigen3 + ) set(INC_SYS - + ../../extern/Eigen3 ) set(SRC @@ -121,201 +121,235 @@ set(SRC kdl/framevel.inl # until we have another user... - ../../extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h - ../../extern/Eigen3/Eigen/src/plugins/CommonCwiseUnaryOps.h - ../../extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h - ../../extern/Eigen3/Eigen/src/plugins/BlockMethods.h - ../../extern/Eigen3/Eigen/src/plugins/ArrayCwiseUnaryOps.h - ../../extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h - ../../extern/Eigen3/Eigen/src/plugins/CommonCwiseBinaryOps.h - ../../extern/Eigen3/Eigen/src/misc/Kernel.h - ../../extern/Eigen3/Eigen/src/misc/Image.h - ../../extern/Eigen3/Eigen/src/misc/Solve.h - ../../extern/Eigen3/Eigen/src/QR/HouseholderQR.h - ../../extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h - ../../extern/Eigen3/Eigen/src/QR/FullPivHouseholderQR.h - ../../extern/Eigen3/Eigen/src/StlSupport/details.h - ../../extern/Eigen3/Eigen/src/StlSupport/StdList.h - ../../extern/Eigen3/Eigen/src/StlSupport/StdDeque.h - ../../extern/Eigen3/Eigen/src/StlSupport/StdVector.h - ../../extern/Eigen3/Eigen/src/SVD/UpperBidiagonalization.h - ../../extern/Eigen3/Eigen/src/SVD/JacobiSVD.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/Tridiagonalization.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/EigenvaluesCommon.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h - ../../extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h - ../../extern/Eigen3/Eigen/src/Jacobi/Jacobi.h - ../../extern/Eigen3/Eigen/src/Householder/Householder.h - ../../extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h - ../../extern/Eigen3/Eigen/src/Householder/HouseholderSequence.h - ../../extern/Eigen3/Eigen/src/Geometry/RotationBase.h - ../../extern/Eigen3/Eigen/src/Geometry/Rotation2D.h - ../../extern/Eigen3/Eigen/src/Geometry/Homogeneous.h - ../../extern/Eigen3/Eigen/src/Geometry/Hyperplane.h - ../../extern/Eigen3/Eigen/src/Geometry/EulerAngles.h - ../../extern/Eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h - ../../extern/Eigen3/Eigen/src/Geometry/ParametrizedLine.h - ../../extern/Eigen3/Eigen/src/Geometry/OrthoMethods.h - ../../extern/Eigen3/Eigen/src/Geometry/AngleAxis.h - ../../extern/Eigen3/Eigen/src/Geometry/Umeyama.h - ../../extern/Eigen3/Eigen/src/Geometry/Scaling.h - ../../extern/Eigen3/Eigen/src/Geometry/Translation.h - ../../extern/Eigen3/Eigen/src/Geometry/AlignedBox.h - ../../extern/Eigen3/Eigen/src/Geometry/Transform.h - ../../extern/Eigen3/Eigen/src/Geometry/Quaternion.h - ../../extern/Eigen3/Eigen/src/LU/PartialPivLU.h - ../../extern/Eigen3/Eigen/src/LU/Determinant.h - ../../extern/Eigen3/Eigen/src/LU/arch/Inverse_SSE.h - ../../extern/Eigen3/Eigen/src/LU/FullPivLU.h - ../../extern/Eigen3/Eigen/src/LU/Inverse.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseMatrixBase.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseSelfAdjointView.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseVector.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseDiagonalProduct.h - ../../extern/Eigen3/Eigen/src/Sparse/TriangularSolver.h - ../../extern/Eigen3/Eigen/src/Sparse/AmbiVector.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseDenseProduct.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseBlock.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseTriangularView.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseCwiseBinaryOp.h - ../../extern/Eigen3/Eigen/src/Sparse/CoreIterators.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseMatrix.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseAssign.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseSparseProduct.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseDot.h - ../../extern/Eigen3/Eigen/src/Sparse/DynamicSparseMatrix.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseRedux.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseFuzzy.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseCwiseUnaryOp.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseView.h - ../../extern/Eigen3/Eigen/src/Sparse/MappedSparseMatrix.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseUtil.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseTranspose.h - ../../extern/Eigen3/Eigen/src/Sparse/SparseProduct.h - ../../extern/Eigen3/Eigen/src/Sparse/CompressedStorage.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Cwise.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/TriangularSolver.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/QR.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Lazy.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Memory.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/SVD.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/CwiseOperators.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/VectorBlock.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Meta.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Macros.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/LeastSquares.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/LU.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Block.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/RotationBase.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Rotation2D.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Hyperplane.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AngleAxis.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Scaling.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/All.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Translation.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AlignedBox.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Transform.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Quaternion.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/Minor.h - ../../extern/Eigen3/Eigen/src/Eigen2Support/MathFunctions.h - ../../extern/Eigen3/Eigen/src/Core/SelfAdjointView.h - ../../extern/Eigen3/Eigen/src/Core/MatrixBase.h - ../../extern/Eigen3/Eigen/src/Core/Swap.h - ../../extern/Eigen3/Eigen/src/Core/DenseCoeffsBase.h - ../../extern/Eigen3/Eigen/src/Core/DenseBase.h - ../../extern/Eigen3/Eigen/src/Core/GlobalFunctions.h - ../../extern/Eigen3/Eigen/src/Core/ProductBase.h - ../../extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h - ../../extern/Eigen3/Eigen/src/Core/Stride.h - ../../extern/Eigen3/Eigen/src/Core/Matrix.h - ../../extern/Eigen3/Eigen/src/Core/Visitor.h - ../../extern/Eigen3/Eigen/src/Core/Array.h - ../../extern/Eigen3/Eigen/src/Core/ReturnByValue.h - ../../extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h - ../../extern/Eigen3/Eigen/src/Core/EigenBase.h - ../../extern/Eigen3/Eigen/src/Core/Random.h - ../../extern/Eigen3/Eigen/src/Core/Redux.h - ../../extern/Eigen3/Eigen/src/Core/arch/Default/Settings.h - ../../extern/Eigen3/Eigen/src/Core/arch/AltiVec/PacketMath.h - ../../extern/Eigen3/Eigen/src/Core/arch/AltiVec/Complex.h - ../../extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h - ../../extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h - ../../extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h - ../../extern/Eigen3/Eigen/src/Core/arch/SSE/Complex.h - ../../extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h - ../../extern/Eigen3/Eigen/src/Core/BooleanRedux.h - ../../extern/Eigen3/Eigen/src/Core/util/ReenableStupidWarnings.h - ../../extern/Eigen3/Eigen/src/Core/util/BlasUtil.h - ../../extern/Eigen3/Eigen/src/Core/util/Memory.h - ../../extern/Eigen3/Eigen/src/Core/util/Meta.h - ../../extern/Eigen3/Eigen/src/Core/util/Constants.h - ../../extern/Eigen3/Eigen/src/Core/util/Macros.h - ../../extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h - ../../extern/Eigen3/Eigen/src/Core/util/StaticAssert.h - ../../extern/Eigen3/Eigen/src/Core/util/DisableStupidWarnings.h - ../../extern/Eigen3/Eigen/src/Core/util/XprHelper.h - ../../extern/Eigen3/Eigen/src/Core/VectorBlock.h - ../../extern/Eigen3/Eigen/src/Core/Transpositions.h - ../../extern/Eigen3/Eigen/src/Core/Select.h - ../../extern/Eigen3/Eigen/src/Core/BandMatrix.h - ../../extern/Eigen3/Eigen/src/Core/CwiseUnaryView.h - ../../extern/Eigen3/Eigen/src/Core/Dot.h - ../../extern/Eigen3/Eigen/src/Core/GenericPacketMath.h - ../../extern/Eigen3/Eigen/src/Core/Product.h - ../../extern/Eigen3/Eigen/src/Core/Transpose.h - ../../extern/Eigen3/Eigen/src/Core/Block.h - ../../extern/Eigen3/Eigen/src/Core/ArrayWrapper.h - ../../extern/Eigen3/Eigen/src/Core/MapBase.h - ../../extern/Eigen3/Eigen/src/Core/NoAlias.h - ../../extern/Eigen3/Eigen/src/Core/ForceAlignedAccess.h - ../../extern/Eigen3/Eigen/src/Core/PlainObjectBase.h - ../../extern/Eigen3/Eigen/src/Core/IO.h - ../../extern/Eigen3/Eigen/src/Core/DiagonalMatrix.h - ../../extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h - ../../extern/Eigen3/Eigen/src/Core/Reverse.h - ../../extern/Eigen3/Eigen/src/Core/Fuzzy.h - ../../extern/Eigen3/Eigen/src/Core/DenseStorage.h - ../../extern/Eigen3/Eigen/src/Core/StableNorm.h - ../../extern/Eigen3/Eigen/src/Core/NumTraits.h - ../../extern/Eigen3/Eigen/src/Core/Map.h - ../../extern/Eigen3/Eigen/src/Core/Functors.h - ../../extern/Eigen3/Eigen/src/Core/PermutationMatrix.h - ../../extern/Eigen3/Eigen/src/Core/ArrayBase.h - ../../extern/Eigen3/Eigen/src/Core/CwiseNullaryOp.h - ../../extern/Eigen3/Eigen/src/Core/SolveTriangular.h - ../../extern/Eigen3/Eigen/src/Core/NestByValue.h - ../../extern/Eigen3/Eigen/src/Core/DiagonalProduct.h - ../../extern/Eigen3/Eigen/src/Core/CommaInitializer.h - ../../extern/Eigen3/Eigen/src/Core/MathFunctions.h - ../../extern/Eigen3/Eigen/src/Core/Diagonal.h - ../../extern/Eigen3/Eigen/src/Core/Replicate.h - ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix.h - ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointProduct.h - ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector.h - ../../extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h - ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector.h - ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointRank2Update.h - ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h - ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h - ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix.h - ../../extern/Eigen3/Eigen/src/Core/products/Parallelizer.h - ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix.h - ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverVector.h - ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector.h - ../../extern/Eigen3/Eigen/src/Core/products/GeneralBlockPanelKernel.h - ../../extern/Eigen3/Eigen/src/Core/TriangularMatrix.h - ../../extern/Eigen3/Eigen/src/Core/VectorwiseOp.h - ../../extern/Eigen3/Eigen/src/Core/Assign.h - ../../extern/Eigen3/Eigen/src/Core/Flagged.h ../../extern/Eigen3/Eigen/src/Cholesky/LDLT.h ../../extern/Eigen3/Eigen/src/Cholesky/LLT.h + ../../extern/Eigen3/Eigen/src/Cholesky/LLT_MKL.h + ../../extern/Eigen3/Eigen/src/CholmodSupport/CholmodSupport.h + ../../extern/Eigen3/Eigen/src/Core/Array.h + ../../extern/Eigen3/Eigen/src/Core/ArrayBase.h + ../../extern/Eigen3/Eigen/src/Core/ArrayWrapper.h + ../../extern/Eigen3/Eigen/src/Core/Assign.h + ../../extern/Eigen3/Eigen/src/Core/Assign_MKL.h + ../../extern/Eigen3/Eigen/src/Core/BandMatrix.h + ../../extern/Eigen3/Eigen/src/Core/Block.h + ../../extern/Eigen3/Eigen/src/Core/BooleanRedux.h + ../../extern/Eigen3/Eigen/src/Core/CommaInitializer.h + ../../extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h + ../../extern/Eigen3/Eigen/src/Core/CwiseNullaryOp.h + ../../extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h + ../../extern/Eigen3/Eigen/src/Core/CwiseUnaryView.h + ../../extern/Eigen3/Eigen/src/Core/DenseBase.h + ../../extern/Eigen3/Eigen/src/Core/DenseCoeffsBase.h + ../../extern/Eigen3/Eigen/src/Core/DenseStorage.h + ../../extern/Eigen3/Eigen/src/Core/Diagonal.h + ../../extern/Eigen3/Eigen/src/Core/DiagonalMatrix.h + ../../extern/Eigen3/Eigen/src/Core/DiagonalProduct.h + ../../extern/Eigen3/Eigen/src/Core/Dot.h + ../../extern/Eigen3/Eigen/src/Core/EigenBase.h + ../../extern/Eigen3/Eigen/src/Core/Flagged.h + ../../extern/Eigen3/Eigen/src/Core/ForceAlignedAccess.h + ../../extern/Eigen3/Eigen/src/Core/Functors.h + ../../extern/Eigen3/Eigen/src/Core/Fuzzy.h + ../../extern/Eigen3/Eigen/src/Core/GeneralProduct.h + ../../extern/Eigen3/Eigen/src/Core/GenericPacketMath.h + ../../extern/Eigen3/Eigen/src/Core/GlobalFunctions.h + ../../extern/Eigen3/Eigen/src/Core/IO.h + ../../extern/Eigen3/Eigen/src/Core/Map.h + ../../extern/Eigen3/Eigen/src/Core/MapBase.h + ../../extern/Eigen3/Eigen/src/Core/MathFunctions.h + ../../extern/Eigen3/Eigen/src/Core/Matrix.h + ../../extern/Eigen3/Eigen/src/Core/MatrixBase.h + ../../extern/Eigen3/Eigen/src/Core/NestByValue.h + ../../extern/Eigen3/Eigen/src/Core/NoAlias.h + ../../extern/Eigen3/Eigen/src/Core/NumTraits.h + ../../extern/Eigen3/Eigen/src/Core/PermutationMatrix.h + ../../extern/Eigen3/Eigen/src/Core/PlainObjectBase.h + ../../extern/Eigen3/Eigen/src/Core/Product.h + ../../extern/Eigen3/Eigen/src/Core/ProductBase.h + ../../extern/Eigen3/Eigen/src/Core/Random.h + ../../extern/Eigen3/Eigen/src/Core/Redux.h + ../../extern/Eigen3/Eigen/src/Core/Replicate.h + ../../extern/Eigen3/Eigen/src/Core/ReturnByValue.h + ../../extern/Eigen3/Eigen/src/Core/Reverse.h + ../../extern/Eigen3/Eigen/src/Core/Select.h + ../../extern/Eigen3/Eigen/src/Core/SelfAdjointView.h + ../../extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h + ../../extern/Eigen3/Eigen/src/Core/SolveTriangular.h + ../../extern/Eigen3/Eigen/src/Core/StableNorm.h + ../../extern/Eigen3/Eigen/src/Core/Stride.h + ../../extern/Eigen3/Eigen/src/Core/Swap.h + ../../extern/Eigen3/Eigen/src/Core/Transpose.h + ../../extern/Eigen3/Eigen/src/Core/Transpositions.h + ../../extern/Eigen3/Eigen/src/Core/TriangularMatrix.h + ../../extern/Eigen3/Eigen/src/Core/VectorBlock.h + ../../extern/Eigen3/Eigen/src/Core/VectorwiseOp.h + ../../extern/Eigen3/Eigen/src/Core/Visitor.h + ../../extern/Eigen3/Eigen/src/Core/arch/AltiVec/Complex.h + ../../extern/Eigen3/Eigen/src/Core/arch/AltiVec/PacketMath.h + ../../extern/Eigen3/Eigen/src/Core/arch/Default/Settings.h + ../../extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h + ../../extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h + ../../extern/Eigen3/Eigen/src/Core/arch/SSE/Complex.h + ../../extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h + ../../extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h + ../../extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralBlockPanelKernel.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector.h + ../../extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/Parallelizer.h + ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix.h + ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector.h + ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointProduct.h + ../../extern/Eigen3/Eigen/src/Core/products/SelfadjointRank2Update.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix_MKL.h + ../../extern/Eigen3/Eigen/src/Core/products/TriangularSolverVector.h + ../../extern/Eigen3/Eigen/src/Core/util/BlasUtil.h + ../../extern/Eigen3/Eigen/src/Core/util/Constants.h + ../../extern/Eigen3/Eigen/src/Core/util/DisableStupidWarnings.h + ../../extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h + ../../extern/Eigen3/Eigen/src/Core/util/Macros.h + ../../extern/Eigen3/Eigen/src/Core/util/Memory.h + ../../extern/Eigen3/Eigen/src/Core/util/Meta.h + ../../extern/Eigen3/Eigen/src/Core/util/MKL_support.h + ../../extern/Eigen3/Eigen/src/Core/util/NonMPL2.h + ../../extern/Eigen3/Eigen/src/Core/util/ReenableStupidWarnings.h + ../../extern/Eigen3/Eigen/src/Core/util/StaticAssert.h + ../../extern/Eigen3/Eigen/src/Core/util/XprHelper.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Block.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Cwise.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/CwiseOperators.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Lazy.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/LeastSquares.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/LU.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Macros.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/MathFunctions.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Memory.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Meta.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Minor.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/QR.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/SVD.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/TriangularSolver.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/VectorBlock.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AlignedBox.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/All.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AngleAxis.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Hyperplane.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Quaternion.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Rotation2D.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/RotationBase.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Scaling.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Transform.h + ../../extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Translation.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur_MKL.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/RealSchur_MKL.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h + ../../extern/Eigen3/Eigen/src/Eigenvalues/Tridiagonalization.h + ../../extern/Eigen3/Eigen/src/Geometry/AlignedBox.h + ../../extern/Eigen3/Eigen/src/Geometry/AngleAxis.h + ../../extern/Eigen3/Eigen/src/Geometry/EulerAngles.h + ../../extern/Eigen3/Eigen/src/Geometry/Homogeneous.h + ../../extern/Eigen3/Eigen/src/Geometry/Hyperplane.h + ../../extern/Eigen3/Eigen/src/Geometry/OrthoMethods.h + ../../extern/Eigen3/Eigen/src/Geometry/ParametrizedLine.h + ../../extern/Eigen3/Eigen/src/Geometry/Quaternion.h + ../../extern/Eigen3/Eigen/src/Geometry/Rotation2D.h + ../../extern/Eigen3/Eigen/src/Geometry/RotationBase.h + ../../extern/Eigen3/Eigen/src/Geometry/Scaling.h + ../../extern/Eigen3/Eigen/src/Geometry/Transform.h + ../../extern/Eigen3/Eigen/src/Geometry/Translation.h + ../../extern/Eigen3/Eigen/src/Geometry/Umeyama.h + ../../extern/Eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h + ../../extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h + ../../extern/Eigen3/Eigen/src/Householder/Householder.h + ../../extern/Eigen3/Eigen/src/Householder/HouseholderSequence.h + ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h + ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h + ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h + ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h + ../../extern/Eigen3/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h + ../../extern/Eigen3/Eigen/src/Jacobi/Jacobi.h + ../../extern/Eigen3/Eigen/src/LU/Determinant.h + ../../extern/Eigen3/Eigen/src/LU/FullPivLU.h + ../../extern/Eigen3/Eigen/src/LU/Inverse.h + ../../extern/Eigen3/Eigen/src/LU/PartialPivLU.h + ../../extern/Eigen3/Eigen/src/LU/PartialPivLU_MKL.h + ../../extern/Eigen3/Eigen/src/LU/arch/Inverse_SSE.h + ../../extern/Eigen3/Eigen/src/misc/blas.h + ../../extern/Eigen3/Eigen/src/misc/Image.h + ../../extern/Eigen3/Eigen/src/misc/Kernel.h + ../../extern/Eigen3/Eigen/src/misc/Solve.h + ../../extern/Eigen3/Eigen/src/misc/SparseSolve.h + ../../extern/Eigen3/Eigen/src/OrderingMethods/Amd.h + ../../extern/Eigen3/Eigen/src/PardisoSupport/PardisoSupport.h + ../../extern/Eigen3/Eigen/src/PaStiXSupport/PaStiXSupport.h + ../../extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h + ../../extern/Eigen3/Eigen/src/plugins/ArrayCwiseUnaryOps.h + ../../extern/Eigen3/Eigen/src/plugins/BlockMethods.h + ../../extern/Eigen3/Eigen/src/plugins/CommonCwiseBinaryOps.h + ../../extern/Eigen3/Eigen/src/plugins/CommonCwiseUnaryOps.h + ../../extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h + ../../extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h + ../../extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h + ../../extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR_MKL.h + ../../extern/Eigen3/Eigen/src/QR/FullPivHouseholderQR.h + ../../extern/Eigen3/Eigen/src/QR/HouseholderQR.h + ../../extern/Eigen3/Eigen/src/QR/HouseholderQR_MKL.h + ../../extern/Eigen3/Eigen/src/SparseCholesky/SimplicialCholesky.h + ../../extern/Eigen3/Eigen/src/SparseCore/AmbiVector.h + ../../extern/Eigen3/Eigen/src/SparseCore/CompressedStorage.h + ../../extern/Eigen3/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h + ../../extern/Eigen3/Eigen/src/SparseCore/CoreIterators.h + ../../extern/Eigen3/Eigen/src/SparseCore/MappedSparseMatrix.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseAssign.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseBlock.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseCwiseBinaryOp.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseCwiseUnaryOp.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseDenseProduct.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseDiagonalProduct.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseDot.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseFuzzy.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseMatrix.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseMatrixBase.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparsePermutation.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseProduct.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseRedux.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseSelfAdjointView.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseSparseProductWithPruning.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseTranspose.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseTriangularView.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseUtil.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseVector.h + ../../extern/Eigen3/Eigen/src/SparseCore/SparseView.h + ../../extern/Eigen3/Eigen/src/SparseCore/TriangularSolver.h + ../../extern/Eigen3/Eigen/src/StlSupport/details.h + ../../extern/Eigen3/Eigen/src/StlSupport/StdDeque.h + ../../extern/Eigen3/Eigen/src/StlSupport/StdList.h + ../../extern/Eigen3/Eigen/src/StlSupport/StdVector.h + ../../extern/Eigen3/Eigen/src/SuperLUSupport/SuperLUSupport.h + ../../extern/Eigen3/Eigen/src/SVD/JacobiSVD.h + ../../extern/Eigen3/Eigen/src/SVD/JacobiSVD_MKL.h + ../../extern/Eigen3/Eigen/src/SVD/UpperBidiagonalization.h + ../../extern/Eigen3/Eigen/src/UmfPackSupport/UmfPackSupport.h ) diff --git a/intern/itasc/Scene.cpp b/intern/itasc/Scene.cpp index 7a83f821bf0..7ed8fc4e63c 100644 --- a/intern/itasc/Scene.cpp +++ b/intern/itasc/Scene.cpp @@ -40,7 +40,7 @@ public: { q_nr += m_qrange.start; project(m_scene->m_Wq, Range(q_nr, ndof), m_qrange).setZero(); - // update the ouput vector so that the movement of this joint will be + // update the output vector so that the movement of this joint will be // taken into account and we can put the joint back in its initial position // which means that the jacobian doesn't need to be changed for (unsigned int i=0 ;itouch(this); } - void set_priority(int priority) { - this->priority = priority; - } - - int get_priority(void) { - return this->priority; - } - private: friend class MEM_CacheLimiter; T * data; int refcount; - int priority; typename std::list *, MEM_Allocator *> >::iterator me; MEM_CacheLimiter * parent; }; @@ -171,7 +162,6 @@ public: } void enforce_limits() { - MEM_CachePriorityQueue priority_queue; size_t max = MEM_CacheLimiter_get_maximum(); size_t mem_in_use, cur_size; @@ -179,9 +169,10 @@ public: return; } - if(getDataSize) { + if (getDataSize) { mem_in_use = total_size(); - } else { + } + else { mem_in_use = MEM_get_memory_in_use(); } @@ -189,23 +180,24 @@ public: return; } - priority_queue = get_priority_queue(); + while (!queue.empty() && mem_in_use > max) { + MEM_CacheElementPtr elem = get_least_priority_destroyable_element(); - while (!priority_queue.empty() && mem_in_use > max) { - MEM_CacheElementPtr elem = priority_queue.top(); + if (!elem) + break; - priority_queue.pop(); - - if(getDataSize) { + if (getDataSize) { cur_size = getDataSize(elem->get()->get_data()); - } else { + } + else { cur_size = mem_in_use; } if (elem->destroy_if_possible()) { if (getDataSize) { mem_in_use -= cur_size; - } else { + } + else { mem_in_use -= cur_size - MEM_get_memory_in_use(); } } @@ -229,14 +221,6 @@ private: typedef std::list > MEM_CacheQueue; typedef typename MEM_CacheQueue::iterator iterator; - struct compare_element_priority : public std::binary_function { - bool operator()(const MEM_CacheElementPtr left_elem, const MEM_CacheElementPtr right_elem) const { - return left_elem->get_priority() > right_elem->get_priority(); - } - }; - - typedef std::priority_queue, compare_element_priority > MEM_CachePriorityQueue; - size_t total_size() { size_t size = 0; for (iterator it = queue.begin(); it != queue.end(); it++) { @@ -245,28 +229,35 @@ private: return size; } - MEM_CachePriorityQueue get_priority_queue(void) { - MEM_CachePriorityQueue priority_queue; + MEM_CacheElementPtr get_least_priority_destroyable_element(void) { + if (queue.empty()) + return NULL; + + if (!getItemPriority) + return *queue.begin(); + + MEM_CacheElementPtr best_match_elem = NULL; + int best_match_priority = 0; iterator it; int i; for (it = queue.begin(), i = 0; it != queue.end(); it++, i++) { MEM_CacheElementPtr elem = *it; - int priority; + + if (!elem->can_destroy()) + continue; /* by default 0 means higherst priority element */ - priority = -(queue.size() - i - 1); + int priority = -(queue.size() - i - 1); + priority = getItemPriority(elem->get()->get_data(), priority); - if (getItemPriority) { - priority = getItemPriority(elem->get()->get_data(), priority); + if (priority < best_match_priority || best_match_elem == NULL) { + best_match_priority = priority; + best_match_elem = elem; } - - elem->set_priority(priority); - - priority_queue.push(elem); } - return priority_queue; + return best_match_elem; } MEM_CacheQueue queue; diff --git a/intern/memutil/MEM_CacheLimiterC-Api.h b/intern/memutil/MEM_CacheLimiterC-Api.h index 1ae5e9df1c6..c05c9d61ea2 100644 --- a/intern/memutil/MEM_CacheLimiterC-Api.h +++ b/intern/memutil/MEM_CacheLimiterC-Api.h @@ -80,7 +80,7 @@ void delete_MEM_CacheLimiter(MEM_CacheLimiterC *This); * @return CacheLimiterHandle to ref, unref, touch the managed object */ -MEM_CacheLimiterHandleC *MEM_CacheLimiter_insert(MEM_CacheLimiterC * This, void * data); +MEM_CacheLimiterHandleC *MEM_CacheLimiter_insert(MEM_CacheLimiterC *This, void *data); /** * Free objects until memory constraints are satisfied @@ -140,7 +140,7 @@ int MEM_CacheLimiter_get_refcount(MEM_CacheLimiterHandleC *handle); * @param handle of object */ -void * MEM_CacheLimiter_get(MEM_CacheLimiterHandleC *handle); +void *MEM_CacheLimiter_get(MEM_CacheLimiterHandleC *handle); void MEM_CacheLimiter_ItemPriority_Func_set(MEM_CacheLimiterC *This, MEM_CacheLimiter_ItemPriority_Func item_priority_func); diff --git a/intern/memutil/MEM_SmartPtr.h b/intern/memutil/MEM_SmartPtr.h index 722a0a8fd3b..09cf5c95854 100644 --- a/intern/memutil/MEM_SmartPtr.h +++ b/intern/memutil/MEM_SmartPtr.h @@ -86,7 +86,7 @@ * private : * MEM_SmartPtr m_foo; * } - * + * * You may also safely construct vectors of MEM_SmartPtrs and * have the vector own stuff you put into it. * @@ -167,7 +167,7 @@ public : Ref( ) const { return *m_val; - } + } /** * Assignment operator - ownership is transfered from rhs to lhs. @@ -207,7 +207,7 @@ public : Release( ) const { T* temp = m_val; - (const_cast(this))->m_val = NULL; + (const_cast(this))->m_val = NULL; return temp; } diff --git a/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp b/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp index 81a1ce670ae..7a19543b2db 100644 --- a/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp +++ b/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp @@ -59,9 +59,9 @@ public: } ~MEM_CacheLimiterCClass(); - handle_t * insert(void * data); + handle_t * insert(void *data); - void destruct(void * data, list_t::iterator it); + void destruct(void *data, list_t::iterator it); cache_t * get_cache() { return &cache; @@ -76,7 +76,7 @@ private: class MEM_CacheLimiterHandleCClass { public: - MEM_CacheLimiterHandleCClass(void * data_, MEM_CacheLimiterCClass * parent_) : + MEM_CacheLimiterHandleCClass(void *data_, MEM_CacheLimiterCClass *parent_) : data(data_), parent(parent_) { } @@ -87,7 +87,7 @@ public: it = it_; } - void set_data(void * data_) { + void set_data(void *data_) { data = data_; } @@ -101,7 +101,7 @@ private: list_t::iterator it; }; -handle_t *MEM_CacheLimiterCClass::insert(void * data) +handle_t *MEM_CacheLimiterCClass::insert(void *data) { cclass_list.push_back(new MEM_CacheLimiterHandleCClass(data, this)); list_t::iterator it = cclass_list.end(); @@ -111,7 +111,7 @@ handle_t *MEM_CacheLimiterCClass::insert(void * data) return cache.insert(cclass_list.back()); } -void MEM_CacheLimiterCClass::destruct(void * data, list_t::iterator it) +void MEM_CacheLimiterCClass::destruct(void *data, list_t::iterator it) { data_destructor(data); cclass_list.erase(it); diff --git a/intern/mikktspace/mikktspace.c b/intern/mikktspace/mikktspace.c index a1ae6bd81c0..a6597986c0a 100644 --- a/intern/mikktspace/mikktspace.c +++ b/intern/mikktspace/mikktspace.c @@ -1063,6 +1063,7 @@ static int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupT const int iNrMaxGroups = iNrTrianglesIn*3; int iNrActiveGroups = 0; int iOffset = 0, f=0, i=0; + (void)iNrMaxGroups; /* quiet warnings in non debug mode */ for (f=0; f=0) // neighbor { @@ -1104,6 +1106,7 @@ static int Build4RuleGroups(STriInfo pTriInfos[], SGroup pGroups[], int piGroupT const tbool bOrPre2 = (pTriInfos[neigh_indexR].iFlag&ORIENT_PRESERVING)!=0 ? TTRUE : TFALSE; const tbool bDiff = bOrPre!=bOrPre2 ? TTRUE : TFALSE; assert(bAnswer || bDiff); + (void)bAnswer, (void)bDiff; /* quiet warnings in non debug mode */ } // update offset diff --git a/intern/opencolorio/CMakeLists.txt b/intern/opencolorio/CMakeLists.txt index 479bbd3ab0a..aeb10669d57 100644 --- a/intern/opencolorio/CMakeLists.txt +++ b/intern/opencolorio/CMakeLists.txt @@ -23,40 +23,43 @@ # # ***** END GPL LICENSE BLOCK ***** -if(WITH_OPENCOLORIO) set(INC . + ../guardedalloc + ../../source/blender/blenlib +) + +set(INC_SYS + + ) + + set(SRC + ocio_capi.cc + fallback_impl.cc + + ocio_capi.h + ocio_impl.h + ) + +if(WITH_OPENCOLORIO) + add_definitions( + -DWITH_OCIO + ) + + list(APPEND INC_SYS ${OPENCOLORIO_INCLUDE_DIRS} ) - set(SRC - ocio_capi.cpp - ocio_capi.h - ) + list(APPEND SRC + ocio_impl.cc +) if(WIN32 AND NOT MINGW) - list(APPEND INC + list(APPEND INC_SYS ${BOOST_INCLUDE_DIR} - ) +) endif() -else() - set(INC - . - ../../source/blender/blenlib - ) - - set(SRC - ocio_capi_stub.cpp - ocio_capi.h - ) endif() -set(INC_SYS - ../guardedalloc -) - -add_definitions( -) blender_add_lib(bf_intern_opencolorio "${SRC}" "${INC}" "${INC_SYS}") - diff --git a/intern/opencolorio/SConscript b/intern/opencolorio/SConscript index fec07662735..a4d21f3e440 100644 --- a/intern/opencolorio/SConscript +++ b/intern/opencolorio/SConscript @@ -2,18 +2,18 @@ Import('env') -sources = env.Glob('*.cpp') +sources = env.Glob('*.cc') incs = '. ../guardedalloc ../../source/blender/blenlib' +defs = [] if env['WITH_BF_OCIO']: - sources.remove('ocio_capi_stub.cpp') - + defs.append('WITH_OCIO') incs += ' ' + env['BF_OCIO_INC'] if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): incs += ' ' + env['BF_BOOST_INC'] else: - sources.remove('ocio_capi.cpp') + sources.remove('ocio_impl.cc') -env.BlenderLib( 'bf_intern_opencolorio', sources, Split(incs), [], libtype=['extern','player'], priority=[10, 185]) +env.BlenderLib( 'bf_intern_opencolorio', sources, Split(incs), defs, libtype=['extern','player'], priority=[10, 185]) diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index f0edd25ac14..0ce5f8a1456 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -28,96 +28,94 @@ #ifndef __OCIO_CAPI_H__ #define __OCIO_CAPI_H__ - - #ifdef __cplusplus -using namespace OCIO_NAMESPACE; extern "C" { #endif #define OCIO_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name +#define OCIO_ROLE_SCENE_LINEAR "scene_linear" +#define OCIO_ROLE_COLOR_PICKING "color_picking" +#define OCIO_ROLE_TEXTURE_PAINT "texture_paint" +#define OCIO_ROLE_DEFAULT_BYTE "default_byte" +#define OCIO_ROLE_DEFAULT_FLOAT "default_float" +#define OCIO_ROLE_DEFAULT_SEQUENCER "default_sequencer" -#ifndef OCIO_CAPI_IMPLEMENTATION - #define OCIO_ROLE_SCENE_LINEAR "scene_linear" - #define OCIO_ROLE_COLOR_PICKING "color_picking" - #define OCIO_ROLE_TEXTURE_PAINT "texture_paint" - #define OCIO_ROLE_DEFAULT_BYTE "default_byte" - #define OCIO_ROLE_DEFAULT_FLOAT "default_float" - #define OCIO_ROLE_DEFAULT_SEQUENCER "default_sequencer" +OCIO_DECLARE_HANDLE(OCIO_ConstConfigRcPtr); +OCIO_DECLARE_HANDLE(OCIO_ConstColorSpaceRcPtr); +OCIO_DECLARE_HANDLE(OCIO_ConstProcessorRcPtr); +OCIO_DECLARE_HANDLE(OCIO_ConstContextRcPtr); +OCIO_DECLARE_HANDLE(OCIO_PackedImageDesc); +OCIO_DECLARE_HANDLE(OCIO_DisplayTransformRcPtr); +OCIO_DECLARE_HANDLE(OCIO_ConstTransformRcPtr); +OCIO_DECLARE_HANDLE(OCIO_ExponentTransformRcPtr); +OCIO_DECLARE_HANDLE(OCIO_MatrixTransformRcPtr); - OCIO_DECLARE_HANDLE(ConstConfigRcPtr); - OCIO_DECLARE_HANDLE(ConstColorSpaceRcPtr); - OCIO_DECLARE_HANDLE(ConstProcessorRcPtr); - OCIO_DECLARE_HANDLE(ConstContextRcPtr); - OCIO_DECLARE_HANDLE(PackedImageDesc); - OCIO_DECLARE_HANDLE(DisplayTransformRcPtr); - OCIO_DECLARE_HANDLE(ConstTransformRcPtr); - OCIO_DECLARE_HANDLE(ExponentTransformRcPtr); - OCIO_DECLARE_HANDLE(MatrixTransformRcPtr); -#endif +void OCIO_init(void); +void OCIO_exit(void); +OCIO_ConstConfigRcPtr *OCIO_getCurrentConfig(void); +void OCIO_setCurrentConfig(const OCIO_ConstConfigRcPtr *config); -ConstConfigRcPtr *OCIO_getCurrentConfig(void); -void OCIO_setCurrentConfig(const ConstConfigRcPtr *config); +OCIO_ConstConfigRcPtr *OCIO_configCreateFromEnv(void); +OCIO_ConstConfigRcPtr *OCIO_configCreateFromFile(const char* filename); +OCIO_ConstConfigRcPtr *OCIO_configCreateFallback(void); -ConstConfigRcPtr *OCIO_configCreateFromEnv(void); -ConstConfigRcPtr *OCIO_configCreateFromFile(const char* filename); +void OCIO_configRelease(OCIO_ConstConfigRcPtr *config); -void OCIO_configRelease(ConstConfigRcPtr *config); +int OCIO_configGetNumColorSpaces(OCIO_ConstConfigRcPtr *config); +const char *OCIO_configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr *config, int index); +OCIO_ConstColorSpaceRcPtr *OCIO_configGetColorSpace(OCIO_ConstConfigRcPtr *config, const char *name); +int OCIO_configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, const char *name); -int OCIO_configGetNumColorSpaces(ConstConfigRcPtr *config); -const char *OCIO_configGetColorSpaceNameByIndex(ConstConfigRcPtr *config, int index); -ConstColorSpaceRcPtr *OCIO_configGetColorSpace(ConstConfigRcPtr *config, const char *name); -int OCIO_configGetIndexForColorSpace(ConstConfigRcPtr *config, const char *name); +int OCIO_colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs); +int OCIO_colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs); -int OCIO_colorSpaceIsInvertible(ConstColorSpaceRcPtr *cs); +void OCIO_colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs); -void OCIO_colorSpaceRelease(ConstColorSpaceRcPtr *cs); +const char *OCIO_configGetDefaultDisplay(OCIO_ConstConfigRcPtr *config); +int OCIO_configGetNumDisplays(OCIO_ConstConfigRcPtr *config); +const char *OCIO_configGetDisplay(OCIO_ConstConfigRcPtr *config, int index); +const char *OCIO_configGetDefaultView(OCIO_ConstConfigRcPtr *config, const char *display); +int OCIO_configGetNumViews(OCIO_ConstConfigRcPtr *config, const char *display); +const char *OCIO_configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index); +const char *OCIO_configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view); -const char *OCIO_configGetDefaultDisplay(ConstConfigRcPtr *config); -int OCIO_configGetNumDisplays(ConstConfigRcPtr *config); -const char *OCIO_configGetDisplay(ConstConfigRcPtr *config, int index); -const char *OCIO_configGetDefaultView(ConstConfigRcPtr *config, const char *display); -int OCIO_configGetNumViews(ConstConfigRcPtr *config, const char *display); -const char *OCIO_configGetView(ConstConfigRcPtr *config, const char *display, int index); -const char *OCIO_configGetDisplayColorSpaceName(ConstConfigRcPtr *config, const char *display, const char *view); +OCIO_ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, const char *srcName, const char *dstName); +OCIO_ConstProcessorRcPtr *OCIO_configGetProcessor(OCIO_ConstConfigRcPtr *config, OCIO_ConstTransformRcPtr *transform); -ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(ConstConfigRcPtr *config, const char *srcName, const char *dstName); -ConstProcessorRcPtr *OCIO_configGetProcessor(ConstConfigRcPtr *config, ConstTransformRcPtr *transform); +void OCIO_processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img); +void OCIO_processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img); +void OCIO_processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel); +void OCIO_processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel); +void OCIO_processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel); -void OCIO_processorApply(ConstProcessorRcPtr *processor, PackedImageDesc *img); -void OCIO_processorApply_predivide(ConstProcessorRcPtr *processor, PackedImageDesc *img); -void OCIO_processorApplyRGB(ConstProcessorRcPtr *processor, float *pixel); -void OCIO_processorApplyRGBA(ConstProcessorRcPtr *processor, float *pixel); -void OCIO_processorApplyRGBA_predivide(ConstProcessorRcPtr *processor, float *pixel); +void OCIO_processorRelease(OCIO_ConstProcessorRcPtr *p); -void OCIO_processorRelease(ConstProcessorRcPtr *p); +const char *OCIO_colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs); +const char *OCIO_colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs); +const char *OCIO_colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs); -const char *OCIO_colorSpaceGetName(ConstColorSpaceRcPtr *cs); -const char *OCIO_colorSpaceGetDescription(ConstColorSpaceRcPtr *cs); -const char *OCIO_colorSpaceGetFamily(ConstColorSpaceRcPtr *cs); +OCIO_DisplayTransformRcPtr *OCIO_createDisplayTransform(void); +void OCIO_displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name); +void OCIO_displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name); +void OCIO_displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name); +void OCIO_displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et); +void OCIO_displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et); +void OCIO_displayTransformRelease(OCIO_DisplayTransformRcPtr *dt); -DisplayTransformRcPtr *OCIO_createDisplayTransform(void); -void OCIO_displayTransformSetInputColorSpaceName(DisplayTransformRcPtr *dt, const char *name); -void OCIO_displayTransformSetDisplay(DisplayTransformRcPtr *dt, const char *name); -void OCIO_displayTransformSetView(DisplayTransformRcPtr *dt, const char *name); -void OCIO_displayTransformSetDisplayCC(DisplayTransformRcPtr *dt, ConstTransformRcPtr *et); -void OCIO_displayTransformSetLinearCC(DisplayTransformRcPtr *dt, ConstTransformRcPtr *et); -void OCIO_displayTransformRelease(DisplayTransformRcPtr *dt); - -PackedImageDesc *OCIO_createPackedImageDesc(float *data, long width, long height, long numChannels, +OCIO_PackedImageDesc *OCIO_createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels, long chanStrideBytes, long xStrideBytes, long yStrideBytes); -void OCIO_packedImageDescRelease(PackedImageDesc *p); +void OCIO_OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p); -ExponentTransformRcPtr *OCIO_createExponentTransform(void); -void OCIO_exponentTransformSetValue(ExponentTransformRcPtr *et, const float *exponent); -void OCIO_exponentTransformRelease(ExponentTransformRcPtr *et); +OCIO_ExponentTransformRcPtr *OCIO_createExponentTransform(void); +void OCIO_exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent); +void OCIO_exponentTransformRelease(OCIO_ExponentTransformRcPtr *et); -MatrixTransformRcPtr *OCIO_createMatrixTransform(void); -void OCIO_matrixTransformSetValue(MatrixTransformRcPtr *et, const float *m44, const float *offset4); -void OCIO_matrixTransformRelease(MatrixTransformRcPtr *mt); +OCIO_MatrixTransformRcPtr *OCIO_createMatrixTransform(void); +void OCIO_matrixTransformSetValue(OCIO_MatrixTransformRcPtr *et, const float *m44, const float *offset4); +void OCIO_matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt); void OCIO_matrixTransformScale(float * m44, float * offset4, const float * scale4); @@ -125,4 +123,4 @@ void OCIO_matrixTransformScale(float * m44, float * offset4, const float * scale } #endif -#endif //OCIO_CAPI_H +#endif /* OCIO_CAPI_H */ diff --git a/intern/opennl/CMakeLists.txt b/intern/opennl/CMakeLists.txt index 322428386b1..b7a24839e38 100644 --- a/intern/opennl/CMakeLists.txt +++ b/intern/opennl/CMakeLists.txt @@ -40,11 +40,10 @@ add_definitions( set(INC extern superlu - ../../extern/colamd/Include ) set(INC_SYS - + ../../extern/colamd/Include ) set(SRC diff --git a/intern/opennl/SConscript b/intern/opennl/SConscript index 711955cbfeb..a0f02735748 100644 --- a/intern/opennl/SConscript +++ b/intern/opennl/SConscript @@ -5,8 +5,5 @@ sources = env.Glob('intern/*.c') + env.Glob('superlu/*.c') incs = 'extern superlu ../../extern/colamd/Include' -if (env['OURPLATFORM'] in ('win32-mingw', 'win64-mingw')): - env.BlenderLib ('bf_intern_opennl', sources, Split(incs), [], libtype=['core','intern'], priority=[1,80] ) -else: - env.BlenderLib ('bf_intern_opennl', sources, Split(incs), [], libtype=['core'], priority=[55] ) +env.BlenderLib ('bf_intern_opennl', sources, Split(incs), [], libtype=['intern','player'], priority=[100,90] ) diff --git a/intern/opennl/intern/opennl.c b/intern/opennl/intern/opennl.c index 71809cc7480..f9c63e9ecf6 100644 --- a/intern/opennl/intern/opennl.c +++ b/intern/opennl/intern/opennl.c @@ -137,14 +137,14 @@ static void __nl_should_not_have_reached(char* file, int line) { /************************************************************************************/ /* memory management */ -#define __NL_NEW(T) (T*)(calloc(1, sizeof(T))) -#define __NL_NEW_ARRAY(T,NB) (T*)(calloc((NB),sizeof(T))) +#define __NL_NEW(T) (T*)(calloc(1, sizeof(T))) +#define __NL_NEW_ARRAY(T,NB) (T*)(calloc(MAX(NB, 1),sizeof(T))) #define __NL_RENEW_ARRAY(T,x,NB) (T*)(realloc(x,(NB)*sizeof(T))) -#define __NL_DELETE(x) free(x); x = NULL -#define __NL_DELETE_ARRAY(x) free(x); x = NULL +#define __NL_DELETE(x) if(x) free(x); x = NULL +#define __NL_DELETE_ARRAY(x) if(x) free(x); x = NULL -#define __NL_CLEAR(T, x) memset(x, 0, sizeof(T)) -#define __NL_CLEAR_ARRAY(T,x,NB) memset(x, 0, (NB)*sizeof(T)) +#define __NL_CLEAR(T, x) memset(x, 0, sizeof(T)) +#define __NL_CLEAR_ARRAY(T,x,NB) if(NB) memset(x, 0, (NB)*sizeof(T)) /************************************************************************************/ /* Dynamic arrays for sparse row/columns */ @@ -1042,6 +1042,9 @@ static NLboolean __nlFactorize_SUPERLU(__NLContext *context, NLint *permutation) NLuint n = context->n; NLuint nnz = __nlSparseMatrixNNZ(M); /* number of non-zero coeffs */ + /*if(n > 10) + n = 10;*/ + /* Compressed Row Storage matrix representation */ NLint *xa = __NL_NEW_ARRAY(NLint, n+1); NLfloat *rhs = __NL_NEW_ARRAY(NLfloat, n); diff --git a/intern/opennl/superlu/get_perm_c.c b/intern/opennl/superlu/get_perm_c.c index 320fe3471f4..59889645988 100644 --- a/intern/opennl/superlu/get_perm_c.c +++ b/intern/opennl/superlu/get_perm_c.c @@ -173,17 +173,19 @@ getata( /* Flag the diagonal so it's not included in the B matrix */ marker[j] = j; - for (i = colptr[j]; i < colptr[j+1]; ++i) { - /* A_kj is nonzero, add pattern of column T_*k to B_*j */ - k = rowind[i]; - for (ti = t_colptr[k]; ti < t_colptr[k+1]; ++ti) { - trow = t_rowind[ti]; - if ( marker[trow] != j ) { - marker[trow] = j; - b_rowind[num_nz++] = trow; + if ( *atanz ) { + for (i = colptr[j]; i < colptr[j+1]; ++i) { + /* A_kj is nonzero, add pattern of column T_*k to B_*j */ + k = rowind[i]; + for (ti = t_colptr[k]; ti < t_colptr[k+1]; ++ti) { + trow = t_rowind[ti]; + if ( marker[trow] != j ) { + marker[trow] = j; + b_rowind[num_nz++] = trow; + } + } + } } - } - } } b_colptr[n] = num_nz; @@ -305,21 +307,23 @@ at_plus_a( marker[j] = j; /* Add pattern of column A_*k to B_*j */ - for (i = colptr[j]; i < colptr[j+1]; ++i) { - k = rowind[i]; - if ( marker[k] != j ) { - marker[k] = j; - (*b_rowind)[num_nz++] = k; - } - } + if (*bnz) { + for (i = colptr[j]; i < colptr[j+1]; ++i) { + k = rowind[i]; + if ( marker[k] != j ) { + marker[k] = j; + (*b_rowind)[num_nz++] = k; + } + } - /* Add pattern of column T_*k to B_*j */ - for (i = t_colptr[j]; i < t_colptr[j+1]; ++i) { - k = t_rowind[i]; - if ( marker[k] != j ) { - marker[k] = j; - (*b_rowind)[num_nz++] = k; - } + /* Add pattern of column T_*k to B_*j */ + for (i = t_colptr[j]; i < t_colptr[j+1]; ++i) { + k = t_rowind[i]; + if ( marker[k] != j ) { + marker[k] = j; + (*b_rowind)[num_nz++] = k; + } + } } } (*b_colptr)[n] = num_nz; diff --git a/intern/raskter/CMakeLists.txt b/intern/raskter/CMakeLists.txt index de6d2c33b7f..3e1368d8eb0 100644 --- a/intern/raskter/CMakeLists.txt +++ b/intern/raskter/CMakeLists.txt @@ -33,11 +33,8 @@ set(INC_SYS set(SRC raskter.c - raskter_mt.c - raskter_kdtree.c raskter.h - raskter_kdtree.h ) blender_add_lib(bf_intern_raskter "${SRC}" "${INC}" "${INC_SYS}") diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index 875dfc8a63b..21153082324 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -24,28 +24,49 @@ * * ***** END GPL LICENSE BLOCK ***** */ + /** \file raskter.c * \ingroup RASKTER */ #include #include "raskter.h" -//#define __PLX__FAKE_AA__ -//#define __PLX_KD_TREE__ -#ifdef __PLX_KD_TREE__ -#include "kdtree.h" -#endif +/* from BLI_utildefines.h */ +#define MIN2(x, y) ( (x) < (y) ? (x) : (y) ) +#define MAX2(x, y) ( (x) > (y) ? (x) : (y) ) -// this is needed for inlining behavior -#if defined _MSC_VER -# define DO_INLINE __inline -#elif defined (__sun) || defined (__sun__) -# define DO_INLINE -#else -# define DO_INLINE static inline -#endif +struct PolyVert { + int x; + int y; +}; +struct e_Status { + int x; + int ybeg; + int xshift; + int xdir; + int drift; + int drift_inc; + int drift_dec; + int num; + struct e_Status *e_next; +}; + +struct r_BufferStats { + float *buf; + int sizex; + int sizey; + int ymin; + int ymax; + int xmin; + int xmax; +}; + +struct r_FillContext { + struct e_Status *all_edges, *possible_edges; + struct r_BufferStats rb; +}; /* * Sort all the edges of the input polygon by Y, then by X, of the "first" vertex encountered. @@ -55,113 +76,121 @@ * just the poly. Since the DEM code could end up being coupled with this, we'll keep it separate * for now. */ -void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts, struct e_status *open_edge) { - int i; - int xbeg; - int ybeg; - int xend; - int yend; - int dx; - int dy; - int temp_pos; - int xdist; - struct e_status *e_new; - struct e_status *next_edge; - struct e_status **next_edge_ref; - struct poly_vert *v; - /* set up pointers */ - v = verts; - ctx->all_edges = NULL; - /* initialize some boundaries */ - ctx->rb.xmax = v[0].x; - ctx->rb.xmin = v[0].x; - ctx->rb.ymax = v[0].y; - ctx->rb.ymin = v[0].y; - /* loop all verts */ - for(i = 0; i < num_verts; i++) { - /* determine beginnings and endings of edges, linking last vertex to first vertex */ - xbeg = v[i].x; - ybeg = v[i].y; - /* keep track of our x and y bounds */ - if(xbeg >= ctx->rb.xmax) { - ctx->rb.xmax = xbeg; - } else if(xbeg <= ctx->rb.xmin) { - ctx->rb.xmin = xbeg; - } - if(ybeg >= ctx->rb.ymax) { - ctx->rb.ymax= ybeg; - } else if(ybeg <= ctx->rb.ymin) { - ctx->rb.ymin=ybeg; - } - if(i) { - /* we're not at the last vert, so end of the edge is the previous vertex */ - xend = v[i - 1].x; - yend = v[i - 1].y; - } else { - /* we're at the first vertex, so the "end" of this edge is the last vertex */ - xend = v[num_verts - 1].x; - yend = v[num_verts - 1].y; - } - /* make sure our edges are facing the correct direction */ - if(ybeg > yend) { - /* flip the Xs */ - temp_pos = xbeg; - xbeg = xend; - xend = temp_pos; - /* flip the Ys */ - temp_pos = ybeg; - ybeg = yend; - yend = temp_pos; - } +static void preprocess_all_edges(struct r_FillContext *ctx, + struct PolyVert *verts, int num_verts, struct e_Status *open_edge) +{ + int i; + int xbeg; + int ybeg; + int xend; + int yend; + int dx; + int dy; + int temp_pos; + int xdist; + struct e_Status *e_new; + struct e_Status *next_edge; + struct e_Status **next_edge_ref; + struct PolyVert *v; + /* set up pointers */ + v = verts; + ctx->all_edges = NULL; + /* initialize some boundaries */ + ctx->rb.xmax = v[0].x; + ctx->rb.xmin = v[0].x; + ctx->rb.ymax = v[0].y; + ctx->rb.ymin = v[0].y; + /* loop all verts */ + for (i = 0; i < num_verts; i++) { + /* determine beginnings and endings of edges, linking last vertex to first vertex */ + xbeg = v[i].x; + ybeg = v[i].y; + /* keep track of our x and y bounds */ + if (xbeg >= ctx->rb.xmax) { + ctx->rb.xmax = xbeg; + } + else if (xbeg <= ctx->rb.xmin) { + ctx->rb.xmin = xbeg; + } + if (ybeg >= ctx->rb.ymax) { + ctx->rb.ymax = ybeg; + } + else if (ybeg <= ctx->rb.ymin) { + ctx->rb.ymin=ybeg; + } + if (i) { + /* we're not at the last vert, so end of the edge is the previous vertex */ + xend = v[i - 1].x; + yend = v[i - 1].y; + } + else { + /* we're at the first vertex, so the "end" of this edge is the last vertex */ + xend = v[num_verts - 1].x; + yend = v[num_verts - 1].y; + } + /* make sure our edges are facing the correct direction */ + if (ybeg > yend) { + /* flip the Xs */ + temp_pos = xbeg; + xbeg = xend; + xend = temp_pos; + /* flip the Ys */ + temp_pos = ybeg; + ybeg = yend; + yend = temp_pos; + } - /* calculate y delta */ - dy = yend - ybeg; - /* dont draw horizontal lines directly, they are scanned as part of the edges they connect, so skip em. :) */ - if(dy) { - /* create the edge and determine it's slope (for incremental line drawing) */ - e_new = open_edge++; + /* calculate y delta */ + dy = yend - ybeg; + /* dont draw horizontal lines directly, they are scanned as part of the edges they connect, so skip em. :) */ + if (dy) { + /* create the edge and determine it's slope (for incremental line drawing) */ + e_new = open_edge++; - /* calculate x delta */ - dx = xend - xbeg; - if(dx > 0) { - e_new->xdir = 1; - xdist = dx; - } else { - e_new->xdir = -1; - xdist = -dx; - } + /* calculate x delta */ + dx = xend - xbeg; + if (dx > 0) { + e_new->xdir = 1; + xdist = dx; + } + else { + e_new->xdir = -1; + xdist = -dx; + } - e_new->x = xbeg; - e_new->ybeg = ybeg; - e_new->num = dy; - e_new->drift_dec = dy; + e_new->x = xbeg; + e_new->ybeg = ybeg; + e_new->num = dy; + e_new->drift_dec = dy; - /* calculate deltas for incremental drawing */ - if(dx >= 0) { - e_new->drift = 0; - } else { - e_new->drift = -dy + 1; - } - if(dy >= xdist) { - e_new->drift_inc = xdist; - e_new->xshift = 0; - } else { - e_new->drift_inc = xdist % dy; - e_new->xshift = (xdist / dy) * e_new->xdir; - } - next_edge_ref = &ctx->all_edges; - /* link in all the edges, in sorted order */ - for(;;) { - next_edge = *next_edge_ref; - if(!next_edge || (next_edge->ybeg > ybeg) || ((next_edge->ybeg == ybeg) && (next_edge->x >= xbeg))) { - e_new->e_next = next_edge; - *next_edge_ref = e_new; - break; - } - next_edge_ref = &next_edge->e_next; - } - } - } + /* calculate deltas for incremental drawing */ + if (dx >= 0) { + e_new->drift = 0; + } + else { + e_new->drift = -dy + 1; + } + if (dy >= xdist) { + e_new->drift_inc = xdist; + e_new->xshift = 0; + } + else { + e_new->drift_inc = xdist % dy; + e_new->xshift = (xdist / dy) * e_new->xdir; + } + next_edge_ref = &ctx->all_edges; + /* link in all the edges, in sorted order */ + for (;;) { + next_edge = *next_edge_ref; + if (!next_edge || (next_edge->ybeg > ybeg) || ((next_edge->ybeg == ybeg) && (next_edge->x >= xbeg))) { + e_new->e_next = next_edge; + *next_edge_ref = e_new; + break; + } + next_edge_ref = &next_edge->e_next; + } + } + } } /* @@ -169,1364 +198,261 @@ void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *verts, i * for speed, but waiting on final design choices for curve-data before eliminating data the DEM code will need * if it ends up being coupled with this function. */ -static int rast_scan_fill(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts, float intensity) { - int x_curr; /* current pixel position in X */ - int y_curr; /* current scan line being drawn */ - int yp; /* y-pixel's position in frame buffer */ - int swixd = 0; /* whether or not edges switched position in X */ - float *cpxl; /* pixel pointers... */ - float *mpxl; - float *spxl; - struct e_status *e_curr; /* edge pointers... */ - struct e_status *e_temp; - struct e_status *edgbuf; - struct e_status **edgec; +static int rast_scan_fill(struct r_FillContext *ctx, struct PolyVert *verts, int num_verts, float intensity) +{ + int x_curr; /* current pixel position in X */ + int y_curr; /* current scan line being drawn */ + int yp; /* y-pixel's position in frame buffer */ + int swixd = 0; /* whether or not edges switched position in X */ + float *cpxl; /* pixel pointers... */ + float *mpxl; + float *spxl; + struct e_Status *e_curr; /* edge pointers... */ + struct e_Status *e_temp; + struct e_Status *edgbuf; + struct e_Status **edgec; - /* - * If the number of verts specified to render as a polygon is less than 3, - * return immediately. Obviously we cant render a poly with sides < 3. The - * return for this we set to 1, simply so it can be distinguished from the - * next place we could return, /home/guest/blender-svn/soc-2011-tomato/intern/raskter/raskter. - * which is a failure to allocate memory. - */ - if(num_verts < 3) { - return(1); - } + /* + * If the number of verts specified to render as a polygon is less than 3, + * return immediately. Obviously we cant render a poly with sides < 3. The + * return for this we set to 1, simply so it can be distinguished from the + * next place we could return, /home/guest/blender-svn/soc-2011-tomato/intern/raskter/raskter. + * which is a failure to allocate memory. + */ + if (num_verts < 3) { + return(1); + } - /* - * Try to allocate an edge buffer in memory. needs to be the size of the edge tracking data - * multiplied by the number of edges, which is always equal to the number of verts in - * a 2D polygon. Here we return 0 to indicate a memory allocation failure, as opposed to a 1 for - * the preceeding error, which was a rasterization request on a 2D poly with less than - * 3 sides. - */ - if((edgbuf = (struct e_status *)(malloc(sizeof(struct e_status) * num_verts))) == NULL) { - return(0); - } + /* + * Try to allocate an edge buffer in memory. needs to be the size of the edge tracking data + * multiplied by the number of edges, which is always equal to the number of verts in + * a 2D polygon. Here we return 0 to indicate a memory allocation failure, as opposed to a 1 for + * the preceeding error, which was a rasterization request on a 2D poly with less than + * 3 sides. + */ + if ((edgbuf = (struct e_Status *)(malloc(sizeof(struct e_Status) * num_verts))) == NULL) { + return(0); + } - /* - * Do some preprocessing on all edges. This constructs a table structure in memory of all - * the edge properties and can "flip" some edges so sorting works correctly. - */ - preprocess_all_edges(ctx, verts, num_verts, edgbuf); + /* + * Do some preprocessing on all edges. This constructs a table structure in memory of all + * the edge properties and can "flip" some edges so sorting works correctly. + */ + preprocess_all_edges(ctx, verts, num_verts, edgbuf); - /* can happen with a zero area mask */ - if (ctx->all_edges == NULL) { - free(edgbuf); - return(1); - } - /* - * Set the pointer for tracking the edges currently in processing to NULL to make sure - * we don't get some crazy value after initialization. - */ - ctx->possible_edges = NULL; + /* can happen with a zero area mask */ + if (ctx->all_edges == NULL) { + free(edgbuf); + return(1); + } + /* + * Set the pointer for tracking the edges currently in processing to NULL to make sure + * we don't get some crazy value after initialization. + */ + ctx->possible_edges = NULL; - /* - * Loop through all scan lines to be drawn. Since we sorted by Y values during - * preprocess_all_edges(), we can already exact values for the lowest and - * highest Y values we could possibly need by induction. The preprocessing sorted - * out edges by Y position, we can cycle the current edge being processed once - * it runs out of Y pixels. When we have no more edges, meaning the current edge - * is NULL after setting the "current" edge to be the previous current edge's - * "next" edge in the Y sorted edge connection chain, we can stop looping Y values, - * since we can't possibly have more scan lines if we ran out of edges. :) - * - * TODO: This clips Y to the frame buffer, which should be done in the preprocessor, but for now is done here. - * Will get changed once DEM code gets in. - */ - for(y_curr = ctx->all_edges->ybeg; (ctx->all_edges || ctx->possible_edges); y_curr++) { + /* + * Loop through all scan lines to be drawn. Since we sorted by Y values during + * preprocess_all_edges(), we can already exact values for the lowest and + * highest Y values we could possibly need by induction. The preprocessing sorted + * out edges by Y position, we can cycle the current edge being processed once + * it runs out of Y pixels. When we have no more edges, meaning the current edge + * is NULL after setting the "current" edge to be the previous current edge's + * "next" edge in the Y sorted edge connection chain, we can stop looping Y values, + * since we can't possibly have more scan lines if we ran out of edges. :) + * + * TODO: This clips Y to the frame buffer, which should be done in the preprocessor, but for now is done here. + * Will get changed once DEM code gets in. + */ + for (y_curr = ctx->all_edges->ybeg; (ctx->all_edges || ctx->possible_edges); y_curr++) { - /* - * Link any edges that start on the current scan line into the list of - * edges currently needed to draw at least this, if not several, scan lines. - */ + /* + * Link any edges that start on the current scan line into the list of + * edges currently needed to draw at least this, if not several, scan lines. + */ - /* - * Set the current edge to the beginning of the list of edges to be rasterized - * into this scan line. - * - * We could have lots of edge here, so iterate over all the edges needed. The - * preprocess_all_edges() function sorted edges by X within each chunk of Y sorting - * so we safely cycle edges to thier own "next" edges in order. - * - * At each iteration, make sure we still have a non-NULL edge. - */ - for(edgec = &ctx->possible_edges; ctx->all_edges && (ctx->all_edges->ybeg == y_curr);) { - x_curr = ctx->all_edges->x; /* Set current X position. */ - for(;;) { /* Start looping edges. Will break when edges run out. */ - e_curr = *edgec; /* Set up a current edge pointer. */ - if(!e_curr || (e_curr->x >= x_curr)) { /* If we have an no edge, or we need to skip some X-span, */ - e_temp = ctx->all_edges->e_next; /* set a temp "next" edge to test. */ - *edgec = ctx->all_edges; /* Add this edge to the list to be scanned. */ - ctx->all_edges->e_next = e_curr; /* Set up the next edge. */ - edgec = &ctx->all_edges->e_next; /* Set our list to the next edge's location in memory. */ - ctx->all_edges = e_temp; /* Skip the NULL or bad X edge, set pointer to next edge. */ - break; /* Stop looping edges (since we ran out or hit empty X span. */ - } else { - edgec = &e_curr->e_next; /* Set the pointer to the edge list the "next" edge. */ - } - } - } + /* + * Set the current edge to the beginning of the list of edges to be rasterized + * into this scan line. + * + * We could have lots of edge here, so iterate over all the edges needed. The + * preprocess_all_edges() function sorted edges by X within each chunk of Y sorting + * so we safely cycle edges to thier own "next" edges in order. + * + * At each iteration, make sure we still have a non-NULL edge. + */ + for (edgec = &ctx->possible_edges; ctx->all_edges && (ctx->all_edges->ybeg == y_curr);) { + x_curr = ctx->all_edges->x; /* Set current X position. */ + for (;;) { /* Start looping edges. Will break when edges run out. */ + e_curr = *edgec; /* Set up a current edge pointer. */ + if (!e_curr || (e_curr->x >= x_curr)) { /* If we have an no edge, or we need to skip some X-span, */ + e_temp = ctx->all_edges->e_next; /* set a temp "next" edge to test. */ + *edgec = ctx->all_edges; /* Add this edge to the list to be scanned. */ + ctx->all_edges->e_next = e_curr; /* Set up the next edge. */ + edgec = &ctx->all_edges->e_next; /* Set our list to the next edge's location in memory. */ + ctx->all_edges = e_temp; /* Skip the NULL or bad X edge, set pointer to next edge. */ + break; /* Stop looping edges (since we ran out or hit empty X span. */ + } + else { + edgec = &e_curr->e_next; /* Set the pointer to the edge list the "next" edge. */ + } + } + } - /* - * Determine the current scan line's offset in the pixel buffer based on its Y position. - * Basically we just multiply the current scan line's Y value by the number of pixels in each line. - */ - yp = y_curr * ctx->rb.sizex; - /* - * Set a "scan line pointer" in memory. The location of the buffer plus the row offset. - */ - spxl = ctx->rb.buf + (yp); - /* - * Set up the current edge to the first (in X) edge. The edges which could possibly be in this - * list were determined in the preceeding edge loop above. They were already sorted in X by the - * initial processing function. - * - * At each iteration, test for a NULL edge. Since we'll keep cycling edge's to their own "next" edge - * we will eventually hit a NULL when the list runs out. - */ - for(e_curr = ctx->possible_edges; e_curr; e_curr = e_curr->e_next) { - /* - * Calculate a span of pixels to fill on the current scan line. - * - * Set the current pixel pointer by adding the X offset to the scan line's start offset. - * Cycle the current edge the next edge. - * Set the max X value to draw to be one less than the next edge's first pixel. This way we are - * sure not to ever get into a situation where we have overdraw. (drawing the same pixel more than - * one time because it's on a vertex connecting two edges) - * - * Then blast through all the pixels in the span, advancing the pointer and setting the color to white. - * - * TODO: Here we clip to the scan line, this is not efficient, and should be done in the preprocessor, - * but for now it is done here until the DEM code comes in. - */ + /* + * Determine the current scan line's offset in the pixel buffer based on its Y position. + * Basically we just multiply the current scan line's Y value by the number of pixels in each line. + */ + yp = y_curr * ctx->rb.sizex; + /* + * Set a "scan line pointer" in memory. The location of the buffer plus the row offset. + */ + spxl = ctx->rb.buf + (yp); + /* + * Set up the current edge to the first (in X) edge. The edges which could possibly be in this + * list were determined in the preceeding edge loop above. They were already sorted in X by the + * initial processing function. + * + * At each iteration, test for a NULL edge. Since we'll keep cycling edge's to their own "next" edge + * we will eventually hit a NULL when the list runs out. + */ + for (e_curr = ctx->possible_edges; e_curr; e_curr = e_curr->e_next) { + /* + * Calculate a span of pixels to fill on the current scan line. + * + * Set the current pixel pointer by adding the X offset to the scan line's start offset. + * Cycle the current edge the next edge. + * Set the max X value to draw to be one less than the next edge's first pixel. This way we are + * sure not to ever get into a situation where we have overdraw. (drawing the same pixel more than + * one time because it's on a vertex connecting two edges) + * + * Then blast through all the pixels in the span, advancing the pointer and setting the color to white. + * + * TODO: Here we clip to the scan line, this is not efficient, and should be done in the preprocessor, + * but for now it is done here until the DEM code comes in. + */ - /* set up xmin and xmax bounds on this scan line */ - cpxl = spxl + MAX2(e_curr->x, 0); - e_curr = e_curr->e_next; - mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1; + /* set up xmin and xmax bounds on this scan line */ + cpxl = spxl + MAX2(e_curr->x, 0); + e_curr = e_curr->e_next; + mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1; - if((y_curr >= 0) && (y_curr < ctx->rb.sizey)) { - /* draw the pixels. */ - for(; cpxl <= mpxl; *cpxl++ += intensity); - } - } + if ((y_curr >= 0) && (y_curr < ctx->rb.sizey)) { + /* draw the pixels. */ + for (; cpxl <= mpxl; *cpxl++ += intensity) {} + } + } - /* - * Loop through all edges of polygon that could be hit by this scan line, - * and figure out their x-intersections with the next scan line. - * - * Either A.) we wont have any more edges to test, or B.) we just add on the - * slope delta computed in preprocessing step. Since this draws non-antialiased - * polygons, we dont have fractional positions, so we only move in x-direction - * when needed to get all the way to the next pixel over... - */ - for(edgec = &ctx->possible_edges; (e_curr = *edgec);) { - if(!(--(e_curr->num))) { - *edgec = e_curr->e_next; - } else { - e_curr->x += e_curr->xshift; - if((e_curr->drift += e_curr->drift_inc) > 0) { - e_curr->x += e_curr->xdir; - e_curr->drift -= e_curr->drift_dec; - } - edgec = &e_curr->e_next; - } - } - /* - * It's possible that some edges may have crossed during the last step, so we'll be sure - * that we ALWAYS intersect scan lines in order by shuffling if needed to make all edges - * sorted by x-intersection coordinate. We'll always scan through at least once to see if - * edges crossed, and if so, we set the 'swixd' flag. If 'swixd' gets set on the initial - * pass, then we know we need to sort by x, so then cycle through edges again and perform - * the sort.- - */ - if(ctx->possible_edges) { - for(edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { - /* if the current edge hits scan line at greater X than the next edge, we need to exchange the edges */ - if(e_curr->x > e_curr->e_next->x) { - *edgec = e_curr->e_next; - /* exchange the pointers */ - e_temp = e_curr->e_next->e_next; - e_curr->e_next->e_next = e_curr; - e_curr->e_next = e_temp; - /* set flag that we had at least one switch */ - swixd = 1; - } - } - /* if we did have a switch, look for more (there will more if there was one) */ - for(;;) { - /* reset exchange flag so it's only set if we encounter another one */ - swixd = 0; - for(edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { - /* again, if current edge hits scan line at higher X than next edge, exchange the edges and set flag */ - if(e_curr->x > e_curr->e_next->x) { - *edgec = e_curr->e_next; - /* exchange the pointers */ - e_temp = e_curr->e_next->e_next; - e_curr->e_next->e_next = e_curr; - e_curr->e_next = e_temp; - /* flip the exchanged flag */ - swixd = 1; - } - } - /* if we had no exchanges, we're done reshuffling the pointers */ - if(!swixd) { - break; - } - } - } - } + /* + * Loop through all edges of polygon that could be hit by this scan line, + * and figure out their x-intersections with the next scan line. + * + * Either A.) we wont have any more edges to test, or B.) we just add on the + * slope delta computed in preprocessing step. Since this draws non-antialiased + * polygons, we dont have fractional positions, so we only move in x-direction + * when needed to get all the way to the next pixel over... + */ + for (edgec = &ctx->possible_edges; (e_curr = *edgec);) { + if (!(--(e_curr->num))) { + *edgec = e_curr->e_next; + } + else { + e_curr->x += e_curr->xshift; + if ((e_curr->drift += e_curr->drift_inc) > 0) { + e_curr->x += e_curr->xdir; + e_curr->drift -= e_curr->drift_dec; + } + edgec = &e_curr->e_next; + } + } + /* + * It's possible that some edges may have crossed during the last step, so we'll be sure + * that we ALWAYS intersect scan lines in order by shuffling if needed to make all edges + * sorted by x-intersection coordinate. We'll always scan through at least once to see if + * edges crossed, and if so, we set the 'swixd' flag. If 'swixd' gets set on the initial + * pass, then we know we need to sort by x, so then cycle through edges again and perform + * the sort.- + */ + if (ctx->possible_edges) { + for (edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { + /* if the current edge hits scan line at greater X than the next edge, we need to exchange the edges */ + if (e_curr->x > e_curr->e_next->x) { + *edgec = e_curr->e_next; + /* exchange the pointers */ + e_temp = e_curr->e_next->e_next; + e_curr->e_next->e_next = e_curr; + e_curr->e_next = e_temp; + /* set flag that we had at least one switch */ + swixd = 1; + } + } + /* if we did have a switch, look for more (there will more if there was one) */ + for (;;) { + /* reset exchange flag so it's only set if we encounter another one */ + swixd = 0; + for (edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { + /* again, if current edge hits scan line at higher X than next edge, exchange the edges and set flag */ + if (e_curr->x > e_curr->e_next->x) { + *edgec = e_curr->e_next; + /* exchange the pointers */ + e_temp = e_curr->e_next->e_next; + e_curr->e_next->e_next = e_curr; + e_curr->e_next = e_temp; + /* flip the exchanged flag */ + swixd = 1; + } + } + /* if we had no exchanges, we're done reshuffling the pointers */ + if (!swixd) { + break; + } + } + } + } - free(edgbuf); - return 1; + free(edgbuf); + return 1; } int PLX_raskterize(float(*base_verts)[2], int num_base_verts, - float *buf, int buf_x, int buf_y, int do_mask_AA) { - int subdiv_AA = (do_mask_AA != 0)? 0:0; - int i; /* i: Loop counter. */ - int sAx; - int sAy; - struct poly_vert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */ - struct r_fill_context ctx = {0}; - const float buf_x_f = (float)(buf_x); - const float buf_y_f = (float)(buf_y); - float div_offset=(1.0f / (float)(subdiv_AA)); - float div_offset_static = 0.5f * (float)(subdiv_AA) * div_offset; - /* - * Allocate enough memory for our poly_vert list. It'll be the size of the poly_vert - * data structure multiplied by the number of base_verts. - * - * In the event of a failure to allocate the memory, return 0, so this error can - * be distinguished as a memory allocation error. - */ - if((ply = (struct poly_vert *)(malloc(sizeof(struct poly_vert) * num_base_verts))) == NULL) { - return(0); - } + float *buf, int buf_x, int buf_y) +{ + int i; /* i: Loop counter. */ + struct PolyVert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */ + struct r_FillContext ctx = {0}; + const float buf_x_f = (float)(buf_x); + const float buf_y_f = (float)(buf_y); + /* + * Allocate enough memory for our PolyVert list. It'll be the size of the PolyVert + * data structure multiplied by the number of base_verts. + * + * In the event of a failure to allocate the memory, return 0, so this error can + * be distinguished as a memory allocation error. + */ + if ((ply = (struct PolyVert *)(malloc(sizeof(struct PolyVert) * num_base_verts))) == NULL) { + return(0); + } - ctx.rb.buf = buf; /* Set the output buffer pointer. */ - ctx.rb.sizex = buf_x; /* Set the output buffer size in X. (width) */ - ctx.rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */ - /* - * Loop over all verts passed in to be rasterized. Each vertex's X and Y coordinates are - * then converted from normalized screen space (0.0 <= POS <= 1.0) to integer coordinates - * in the buffer-space coordinates passed in inside buf_x and buf_y. - * - * It's worth noting that this function ONLY outputs fully white pixels in a mask. Every pixel - * drawn will be 1.0f in value, there is no anti-aliasing. - */ + ctx.rb.buf = buf; /* Set the output buffer pointer. */ + ctx.rb.sizex = buf_x; /* Set the output buffer size in X. (width) */ + ctx.rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */ + /* + * Loop over all verts passed in to be rasterized. Each vertex's X and Y coordinates are + * then converted from normalized screen space (0.0 <= POS <= 1.0) to integer coordinates + * in the buffer-space coordinates passed in inside buf_x and buf_y. + * + * It's worth noting that this function ONLY outputs fully white pixels in a mask. Every pixel + * drawn will be 1.0f in value, there is no anti-aliasing. + */ - if(!subdiv_AA) { - for(i = 0; i < num_base_verts; i++) { /* Loop over all base_verts. */ - ply[i].x = (int)((base_verts[i][0] * buf_x_f) + 0.5f); /* Range expand normalized X to integer buffer-space X. */ - ply[i].y = (int)((base_verts[i][1] * buf_y_f) + 0.5f); /* Range expand normalized Y to integer buffer-space Y. */ - } + for (i = 0; i < num_base_verts; i++) { /* Loop over all base_verts. */ + ply[i].x = (int)((base_verts[i][0] * buf_x_f) + 0.5f); /* Range expand normalized X to integer buffer-space X. */ + ply[i].y = (int)((base_verts[i][1] * buf_y_f) + 0.5f); /* Range expand normalized Y to integer buffer-space Y. */ + } - i = rast_scan_fill(&ctx, ply, num_base_verts,1.0f); /* Call our rasterizer, passing in the integer coords for each vert. */ - } else { - for(sAx=0; sAx < subdiv_AA; sAx++) { - for(sAy=0; sAy < subdiv_AA; sAy++) { - for(i=0; i < num_base_verts; i++) { - ply[i].x = (int)((base_verts[i][0]*buf_x_f)+0.5f - div_offset_static + (div_offset*(float)(sAx))); - ply[i].y = (int)((base_verts[i][1]*buf_y_f)+0.5f - div_offset_static + (div_offset*(float)(sAy))); - } - i = rast_scan_fill(&ctx, ply, num_base_verts,(1.0f / (float)(subdiv_AA*subdiv_AA))); - } - } - } - free(ply); /* Free the memory allocated for the integer coordinate table. */ - return(i); /* Return the value returned by the rasterizer. */ + i = rast_scan_fill(&ctx, ply, num_base_verts,1.0f); /* Call our rasterizer, passing in the integer coords for each vert. */ + + free(ply); /* Free the memory allocated for the integer coordinate table. */ + return(i); /* Return the value returned by the rasterizer. */ } - -/* - * This function clips drawing to the frame buffer. That clipping will likely be moved into the preprocessor - * for speed, but waiting on final design choices for curve-data before eliminating data the DEM code will need - * if it ends up being coupled with this function. - */ -static int rast_scan_feather(struct r_fill_context *ctx, - float(*base_verts_f)[2], int num_base_verts, - struct poly_vert *feather_verts, float(*feather_verts_f)[2], int num_feather_verts) { - int x_curr; /* current pixel position in X */ - int y_curr; /* current scan line being drawn */ - int yp; /* y-pixel's position in frame buffer */ - int swixd = 0; /* whether or not edges switched position in X */ - float *cpxl; /* pixel pointers... */ - float *mpxl; - float *spxl; - struct e_status *e_curr; /* edge pointers... */ - struct e_status *e_temp; - struct e_status *edgbuf; - struct e_status **edgec; - - /* from dem */ - int a; // a = temporary pixel index buffer loop counter - float fsz; // size of the frame - unsigned int rsl; // long used for finding fast 1.0/sqrt - float rsf; // float used for finding fast 1.0/sqrt - const float rsopf = 1.5f; // constant float used for finding fast 1.0/sqrt - - //unsigned int gradientFillOffset; - float t; - float ud; // ud = unscaled edge distance - float dmin; // dmin = minimum edge distance - float odist; // odist = current outer edge distance - float idist; // idist = current inner edge distance - float dx; // dx = X-delta (used for distance proportion calculation) - float dy; // dy = Y-delta (used for distance proportion calculation) - float xpxw = (1.0f / (float)(ctx->rb.sizex)); // xpxw = normalized pixel width - float ypxh = (1.0f / (float)(ctx->rb.sizey)); // ypxh = normalized pixel height -#ifdef __PLX_KD_TREE__ - void *res_kdi; - void *res_kdo; - float clup[2]; -#endif - - /* - * If the number of verts specified to render as a polygon is less than 3, - * return immediately. Obviously we cant render a poly with sides < 3. The - * return for this we set to 1, simply so it can be distinguished from the - * next place we could return, - * which is a failure to allocate memory. - */ - if(num_feather_verts < 3) { - return(1); - } - - /* - * Try to allocate an edge buffer in memory. needs to be the size of the edge tracking data - * multiplied by the number of edges, which is always equal to the number of verts in - * a 2D polygon. Here we return 0 to indicate a memory allocation failure, as opposed to a 1 for - * the preceeding error, which was a rasterization request on a 2D poly with less than - * 3 sides. - */ - if((edgbuf = (struct e_status *)(malloc(sizeof(struct e_status) * num_feather_verts))) == NULL) { - return(0); - } - - /* - * Do some preprocessing on all edges. This constructs a table structure in memory of all - * the edge properties and can "flip" some edges so sorting works correctly. - */ - preprocess_all_edges(ctx, feather_verts, num_feather_verts, edgbuf); - - /* can happen with a zero area mask */ - if (ctx->all_edges == NULL) { - free(edgbuf); - return(1); - } - - /* - * Set the pointer for tracking the edges currently in processing to NULL to make sure - * we don't get some crazy value after initialization. - */ - ctx->possible_edges = NULL; - - /* - * Loop through all scan lines to be drawn. Since we sorted by Y values during - * preprocess_all_edges(), we can already exact values for the lowest and - * highest Y values we could possibly need by induction. The preprocessing sorted - * out edges by Y position, we can cycle the current edge being processed once - * it runs out of Y pixels. When we have no more edges, meaning the current edge - * is NULL after setting the "current" edge to be the previous current edge's - * "next" edge in the Y sorted edge connection chain, we can stop looping Y values, - * since we can't possibly have more scan lines if we ran out of edges. :) - * - * TODO: This clips Y to the frame buffer, which should be done in the preprocessor, but for now is done here. - * Will get changed once DEM code gets in. - */ - for(y_curr = ctx->all_edges->ybeg; (ctx->all_edges || ctx->possible_edges); y_curr++) { - - /* - * Link any edges that start on the current scan line into the list of - * edges currently needed to draw at least this, if not several, scan lines. - */ - - /* - * Set the current edge to the beginning of the list of edges to be rasterized - * into this scan line. - * - * We could have lots of edge here, so iterate over all the edges needed. The - * preprocess_all_edges() function sorted edges by X within each chunk of Y sorting - * so we safely cycle edges to thier own "next" edges in order. - * - * At each iteration, make sure we still have a non-NULL edge. - */ - for(edgec = &ctx->possible_edges; ctx->all_edges && (ctx->all_edges->ybeg == y_curr);) { - x_curr = ctx->all_edges->x; /* Set current X position. */ - for(;;) { /* Start looping edges. Will break when edges run out. */ - e_curr = *edgec; /* Set up a current edge pointer. */ - if(!e_curr || (e_curr->x >= x_curr)) { /* If we have an no edge, or we need to skip some X-span, */ - e_temp = ctx->all_edges->e_next; /* set a temp "next" edge to test. */ - *edgec = ctx->all_edges; /* Add this edge to the list to be scanned. */ - ctx->all_edges->e_next = e_curr; /* Set up the next edge. */ - edgec = &ctx->all_edges->e_next; /* Set our list to the next edge's location in memory. */ - ctx->all_edges = e_temp; /* Skip the NULL or bad X edge, set pointer to next edge. */ - break; /* Stop looping edges (since we ran out or hit empty X span. */ - } else { - edgec = &e_curr->e_next; /* Set the pointer to the edge list the "next" edge. */ - } - } - } - - /* - * Determine the current scan line's offset in the pixel buffer based on its Y position. - * Basically we just multiply the current scan line's Y value by the number of pixels in each line. - */ - yp = y_curr * ctx->rb.sizex; - /* - * Set a "scan line pointer" in memory. The location of the buffer plus the row offset. - */ - spxl = ctx->rb.buf + (yp); - /* - * Set up the current edge to the first (in X) edge. The edges which could possibly be in this - * list were determined in the preceeding edge loop above. They were already sorted in X by the - * initial processing function. - * - * At each iteration, test for a NULL edge. Since we'll keep cycling edge's to their own "next" edge - * we will eventually hit a NULL when the list runs out. - */ - for(e_curr = ctx->possible_edges; e_curr; e_curr = e_curr->e_next) { - /* - * Calculate a span of pixels to fill on the current scan line. - * - * Set the current pixel pointer by adding the X offset to the scan line's start offset. - * Cycle the current edge the next edge. - * Set the max X value to draw to be one less than the next edge's first pixel. This way we are - * sure not to ever get into a situation where we have overdraw. (drawing the same pixel more than - * one time because it's on a vertex connecting two edges) - * - * Then blast through all the pixels in the span, advancing the pointer and setting the color to white. - * - * TODO: Here we clip to the scan line, this is not efficient, and should be done in the preprocessor, - * but for now it is done here until the DEM code comes in. - */ - - /* set up xmin and xmax bounds on this scan line */ - cpxl = spxl + MAX2(e_curr->x, 0); - e_curr = e_curr->e_next; - mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1; - - if((y_curr >= 0) && (y_curr < ctx->rb.sizey)) { - t = ((float)((cpxl - spxl) % ctx->rb.sizex) + 0.5f) * xpxw; - fsz = ((float)(y_curr) + 0.5f) * ypxh; - /* draw the pixels. */ - for(; cpxl <= mpxl; cpxl++, t += xpxw) { - //do feather check - // first check that pixel isn't already full, and only operate if it is not - if(*cpxl < 0.9999f) { -#ifndef __PLX_KD_TREE__ - dmin = 2.0f; // reset min distance to edge pixel - for(a = 0; a < num_feather_verts; a++) { // loop through all outer edge buffer pixels - dx = t - feather_verts_f[a][0]; // set dx to gradient pixel column - outer edge pixel row - dy = fsz - feather_verts_f[a][1]; // set dy to gradient pixel row - outer edge pixel column - ud = dx * dx + dy * dy; // compute sum of squares - if(ud < dmin) { // if our new sum of squares is less than the current minimum - dmin = ud; // set a new minimum equal to the new lower value - } - } - odist = dmin; // cast outer min to a float - rsf = odist * 0.5f; // - rsl = *(unsigned int *)&odist; // use some peculiar properties of the way bits are stored - rsl = 0x5f3759df - (rsl >> 1); // in floats vs. unsigned ints to compute an approximate - odist = *(float *)&rsl; // reciprocal square root - odist = odist * (rsopf - (rsf * odist * odist)); // -- ** this line can be iterated for more accuracy ** -- - odist = odist * (rsopf - (rsf * odist * odist)); - dmin = 2.0f; // reset min distance to edge pixel - for(a = 0; a < num_base_verts; a++) { // loop through all inside edge pixels - dx = t - base_verts_f[a][0]; // compute delta in Y from gradient pixel to inside edge pixel - dy = fsz - base_verts_f[a][1]; // compute delta in X from gradient pixel to inside edge pixel - ud = dx * dx + dy * dy; // compute sum of squares - if(ud < dmin) { // if our new sum of squares is less than the current minimum we've found - dmin = ud; // set a new minimum equal to the new lower value - } - } - idist = dmin; // cast inner min to a float - rsf = idist * 0.5f; // - rsl = *(unsigned int *)&idist; // - rsl = 0x5f3759df - (rsl >> 1); // see notes above - idist = *(float *)&rsl; // - idist = idist * (rsopf - (rsf * idist * idist)); // - idist = idist * (rsopf - (rsf * idist * idist)); - /* - * Note once again that since we are using reciprocals of distance values our - * proportion is already the correct intensity, and does not need to be - * subtracted from 1.0 like it would have if we used real distances. - */ -#else - clup[0]=t; - clup[1]=fsz; - res_kdi=kd_nearestf(ctx->kdi,clup); - res_kdo=kd_nearestf(ctx->kdo,clup); - kd_res_itemf(res_kdi,clup); - dx=t-clup[0]; - dy=fsz-clup[1]; - idist=dx*dx+dy*dy; - rsf = idist * 0.5f; // - rsl = *(unsigned int *)&idist; // - rsl = 0x5f3759df - (rsl >> 1); // see notes above - idist = *(float *)&rsl; // - idist = idist * (rsopf - (rsf * idist * idist)); // - idist = idist * (rsopf - (rsf * idist * idist)); - kd_res_itemf(res_kdo,clup); - dx=t-clup[0]; - dy=fsz-clup[1]; - odist=dx*dx+dy*dy; - rsf = odist * 0.5f; // - rsl = *(unsigned int *)&odist; // use some peculiar properties of the way bits are stored - rsl = 0x5f3759df - (rsl >> 1); // in floats vs. unsigned ints to compute an approximate - odist = *(float *)&rsl; // reciprocal square root - odist = odist * (rsopf - (rsf * odist * odist)); // -- ** this line can be iterated for more accuracy ** -- - odist = odist * (rsopf - (rsf * odist * odist)); - -#endif - /* set intensity, do the += so overlapping gradients are additive */ - *cpxl = (idist / (idist+odist)); - } - } - } - } - - /* - * Loop through all edges of polygon that could be hit by this scan line, - * and figure out their x-intersections with the next scan line. - * - * Either A.) we wont have any more edges to test, or B.) we just add on the - * slope delta computed in preprocessing step. Since this draws non-antialiased - * polygons, we dont have fractional positions, so we only move in x-direction - * when needed to get all the way to the next pixel over... - */ - for(edgec = &ctx->possible_edges; (e_curr = *edgec);) { - if(!(--(e_curr->num))) { - *edgec = e_curr->e_next; - } else { - e_curr->x += e_curr->xshift; - if((e_curr->drift += e_curr->drift_inc) > 0) { - e_curr->x += e_curr->xdir; - e_curr->drift -= e_curr->drift_dec; - } - edgec = &e_curr->e_next; - } - } - /* - * It's possible that some edges may have crossed during the last step, so we'll be sure - * that we ALWAYS intersect scan lines in order by shuffling if needed to make all edges - * sorted by x-intersection coordinate. We'll always scan through at least once to see if - * edges crossed, and if so, we set the 'swixd' flag. If 'swixd' gets set on the initial - * pass, then we know we need to sort by x, so then cycle through edges again and perform - * the sort.- - */ - if(ctx->possible_edges) { - for(edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { - /* if the current edge hits scan line at greater X than the next edge, we need to exchange the edges */ - if(e_curr->x > e_curr->e_next->x) { - *edgec = e_curr->e_next; - /* exchange the pointers */ - e_temp = e_curr->e_next->e_next; - e_curr->e_next->e_next = e_curr; - e_curr->e_next = e_temp; - /* set flag that we had at least one switch */ - swixd = 1; - } - } - /* if we did have a switch, look for more (there will more if there was one) */ - for(;;) { - /* reset exchange flag so it's only set if we encounter another one */ - swixd = 0; - for(edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { - /* again, if current edge hits scan line at higher X than next edge, - * exchange the edges and set flag */ - if(e_curr->x > e_curr->e_next->x) { - *edgec = e_curr->e_next; - /* exchange the pointers */ - e_temp = e_curr->e_next->e_next; - e_curr->e_next->e_next = e_curr; - e_curr->e_next = e_temp; - /* flip the exchanged flag */ - swixd = 1; - } - } - /* if we had no exchanges, we're done reshuffling the pointers */ - if(!swixd) { - break; - } - } - } - } - - free(edgbuf); - return 1; -} - -int PLX_raskterize_feather(float(*base_verts)[2], int num_base_verts, float(*feather_verts)[2], int num_feather_verts, - float *buf, int buf_x, int buf_y) { - //void plx_floatsort(float(*f)[2], unsigned int n, int sortby); - int i; /* i: Loop counter. */ - struct poly_vert *fe; /* fe: Pointer to a list of integer buffer-space feather vertex coords. */ - struct r_fill_context ctx = {0}; - - /* for faster multiply */ - const float buf_x_f = (float)buf_x; - const float buf_y_f = (float)buf_y; -#ifdef __PLX_KD_TREE__ - ctx.kdi = kd_create(2); - ctx.kdo = kd_create(2); -#endif - /* - * Allocate enough memory for our poly_vert list. It'll be the size of the poly_vert - * data structure multiplied by the number of verts. - * - * In the event of a failure to allocate the memory, return 0, so this error can - * be distinguished as a memory allocation error. - */ - if((fe = (struct poly_vert *)(malloc(sizeof(struct poly_vert) * num_feather_verts))) == NULL) { - return(0); - } - - /* - * Loop over all verts passed in to be rasterized. Each vertex's X and Y coordinates are - * then converted from normalized screen space (0.0 <= POS <= 1.0) to integer coordinates - * in the buffer-space coordinates passed in inside buf_x and buf_y. - * - * It's worth noting that this function ONLY outputs fully white pixels in a mask. Every pixel - * drawn will be 1.0f in value, there is no anti-aliasing. - */ - for(i = 0; i < num_feather_verts; i++) { /* Loop over all verts. */ - fe[i].x = (int)((feather_verts[i][0] * buf_x_f) + 0.5f); /* Range expand normalized X to integer buffer-space X. */ - fe[i].y = (int)((feather_verts[i][1] * buf_y_f) + 0.5f); /* Range expand normalized Y to integer buffer-space Y. */ -#ifdef __PLX_KD_TREE__ - kd_insertf(ctx.kdo,feather_verts[i],NULL); - } - for(i=0;i= buf_x || pos_y < 0 || pos_y >= buf_y) { - return 0.0f; - } - return buf[(pos_y * buf_x) + pos_x]; -} - -DO_INLINE float get_pixel_intensity_bilinear(float *buf, int buf_x, int buf_y, float u, float v) { - int a; - int b; - int a_plus_1; - int b_plus_1; - float prop_u; - float prop_v; - float inv_prop_u; - float inv_prop_v; - if(u<0.0f || u>1.0f || v<0.0f || v>1.0f) { - return 0.0f; - } - u = u * (float)(buf_x) - 0.5f; - v = v * (float)(buf_y) - 0.5f; - a = (int)(u); - b = (int)(v); - prop_u = u - (float)(a); - prop_v = v - (float)(b); - inv_prop_u = 1.0f - prop_u; - inv_prop_v = 1.0f - prop_v; - a_plus_1 = MIN2((buf_x-1),a+1); - b_plus_1 = MIN2((buf_y-1),b+1); - return (buf[(b * buf_x) + a] * inv_prop_u + buf[(b*buf_x)+(a_plus_1)] * prop_u)*inv_prop_v+(buf[((b_plus_1) * buf_x)+a] * inv_prop_u + buf[((b_plus_1)*buf_x)+(a_plus_1)] * prop_u) * prop_v; - -} - -DO_INLINE void set_pixel_intensity(float *buf, int buf_x, int buf_y, int pos_x, int pos_y, float intensity) { - if(pos_x < 0 || pos_x >= buf_x || pos_y < 0 || pos_y >= buf_y) { - return; - } - buf[(pos_y * buf_x) + pos_x] = intensity; -} -#endif - -int PLX_antialias_buffer(float *buf, int buf_x, int buf_y) { -#ifdef __PLX__FAKE_AA__ -#ifdef __PLX_GREY_AA__ - int i=0; - int sz = buf_x * buf_y; - for(i=0; i= ude ? 1:0; - tg0 = spP * 2.0f + spX; - - if(!lrsp) { - pui = pli; - pdi = pri; - } else { - sdst = 1.0f / (float)(buf_y); - } - tg1 = (tg0 * (1.0f/12.0f)) - pci; - - ugrad = pui - pci; - dgrad = pdi - pci; - uui = pui + pci; - ddi = pdi + pci; - revpp = (ABS(ugrad)) >= (ABS(dgrad)) ? 1:0; - grad = MAX2(ABS(ugrad), ABS(dgrad)); - if(revpp) { - sdst = -sdst; - } - tg2 = MAX2(MIN2(ABS(tg1) * inv_r,1.0f),0.0f); - - fpsqx = fpcx; - fpsqy = fpcy; - offset_dgx = (!lrsp) ? 0.0f:(1.0f / (float)(buf_x)); - offset_dgy = (lrsp) ? 0.0f:(1.0f / (float)(buf_y)); - if(!lrsp) { - fpsqx += sdst * 0.5f; - } else { - fpsqy += sdst * 0.5f; - } - - fprevx = fpsqx - offset_dgx * jump01; - fprevy = fpsqy - offset_dgy * jump01; - fpfowx = fpsqx + offset_dgx * jump01; - fpfowy = fpsqy + offset_dgy * jump01; - tg3 = ((-2.0f)*tg2) + 3.0f; - eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy); - tg4 = tg2 * tg2; - efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy); - - if(!revpp) { - uui = ddi; - } - gradexp = grad * 1.0f/4.0f; - cci =pci - uui * 0.5f; - tg5 = tg3 * tg4; - ltz = cci < 0.0f ? 1:0; - - eri -= uui * 0.5f; - efi -= uui * 0.5f; - revdone = (ABS(eri)) >= gradexp ? 1:0; - fowdone = (ABS(efi)) >= gradexp ? 1:0; - if(!revdone) { - fprevx -= offset_dgx * jump02; - fprevy -= offset_dgy * jump02; - } - tug_of_war = (!revdone) || (!fowdone) ? 1:0; - if(!fowdone) { - fpfowx += offset_dgx * jump02; - fpfowy += offset_dgy * jump02; - } - - if(tug_of_war) { - if(!revdone) { - eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fprevx,fprevy); - } - if(!fowdone) { - efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx, fpfowy); - } - if(!revdone) { - eri = eri - uui * 0.5; - } - if(!fowdone) { - efi = efi - uui * 0.5; - } - revdone = (ABS(eri)) >= gradexp ? 1:0; - fowdone = (ABS(efi)) >= gradexp ? 1:0; - if(!revdone) { - fprevx -= offset_dgx * jump03; - fprevy -= offset_dgy * jump03; - } - tug_of_war = (!revdone) || (!fowdone) ? 1:0; - if(!fowdone) { - fpfowx += offset_dgx * jump03; - fpfowy += offset_dgy * jump03; - } - if(tug_of_war) { - if(!revdone) { - eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy); - } - if(!fowdone) { - efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy); - } - if(!revdone) { - eri = eri - uui * 0.5; - } - if(!fowdone) { - efi = efi - uui * 0.5; - } - revdone = (ABS(eri)) >= gradexp ? 1:0; - fowdone = (ABS(efi)) >= gradexp ? 1:0; - if(!revdone) { - fprevx -= offset_dgx * jump04; - fprevy -= offset_dgy * jump04; - } - tug_of_war = (!revdone) || (!fowdone) ? 1:0; - if(!fowdone) { - fpfowx += offset_dgx * jump04; - fpfowy += offset_dgy * jump04; - } - if(tug_of_war) { - if(!revdone) { - eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy); - } - if(!fowdone) { - efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy); - } - if(!revdone) { - eri = eri - uui * 0.5; - } - if(!fowdone) { - efi = efi - uui * 0.5; - } - revdone = (ABS(eri)) >= gradexp ? 1:0; - fowdone = (ABS(efi)) >= gradexp ? 1:0; - if(!revdone) { - fprevx -= offset_dgx * jump05; - fprevy -= offset_dgy * jump05; - } - tug_of_war = (!revdone) || (!fowdone) ? 1:0; - if(!fowdone) { - fpfowx += offset_dgx * jump05; - fpfowy += offset_dgy * jump05; - } - if(tug_of_war) { - if(!revdone) { - eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy); - } - if(!fowdone) { - efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy); - } - if(!revdone) { - eri = eri - uui * 0.5; - } - if(!fowdone) { - efi = efi - uui * 0.5; - } - revdone = (ABS(eri)) >= gradexp ? 1:0; - fowdone = (ABS(efi)) >= gradexp ? 1:0; - if(!revdone) { - fprevx -= offset_dgx * jump06; - fprevy -= offset_dgy * jump06; - } - tug_of_war = (!revdone) || (!fowdone) ? 1:0; - if(!fowdone) { - fpfowx += offset_dgx * jump06; - fpfowy += offset_dgy * jump06; - } - if(tug_of_war) { - if(!revdone) { - eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy); - } - if(!fowdone) { - efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy); - } - if(!revdone) { - eri = eri - uui * 0.5; - } - if(!fowdone) { - efi = efi - uui * 0.5; - } - revdone = (ABS(eri)) >= gradexp ? 1:0; - fowdone = (ABS(efi)) >= gradexp ? 1:0; - if(!revdone) { - fprevx -= offset_dgx * jump07; - fprevy -= offset_dgy * jump07; - } - tug_of_war = (!revdone) || (!fowdone) ? 1:0; - if(!fowdone) { - fpfowx += offset_dgx * jump07; - fpfowy += offset_dgy * jump07; - } - if(tug_of_war) { - if(!revdone) { - eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy); - } - if(!fowdone) { - efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy); - } - if(!revdone) { - eri = eri - uui * 0.5; - } - if(!fowdone) { - efi = efi - uui * 0.5; - } - revdone = (ABS(eri)) >= gradexp ? 1:0; - fowdone = (ABS(efi)) >= gradexp ? 1:0; - if(!revdone) { - fprevx -= offset_dgx * jump08; - fprevy -= offset_dgy * jump08; - } - tug_of_war = (!revdone) || (!fowdone) ? 1:0; - if(!fowdone) { - fpfowx += offset_dgx * jump08; - fpfowy += offset_dgy * jump08; - } - if(tug_of_war) { - if(!revdone) { - eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy); - } - if(!fowdone) { - efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy); - } - if(!revdone) { - eri = eri - uui * 0.5; - } - if(!fowdone) { - efi = efi - uui * 0.5; - } - revdone = (ABS(eri)) >= gradexp ? 1:0; - fowdone = (ABS(efi)) >= gradexp ? 1:0; - if(!revdone) { - fprevx -= offset_dgx * jump09; - fprevy -= offset_dgy * jump09; - } - tug_of_war = (!revdone) || (!fowdone) ? 1:0; - if(!fowdone) { - fpfowx += offset_dgx * jump09; - fpfowy += offset_dgy * jump09; - } - if(tug_of_war) { - if(!revdone) { - eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy); - } - if(!fowdone) { - efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy); - } - if(!revdone) { - eri = eri - uui * 0.5; - } - if(!fowdone) { - efi = efi - uui * 0.5; - } - revdone = (ABS(eri)) >= gradexp ? 1:0; - fowdone = (ABS(efi)) >= gradexp ? 1:0; - if(!revdone) { - fprevx -= offset_dgx * jump10; - fprevy -= offset_dgy * jump10; - } - tug_of_war = (!revdone) || (!fowdone) ? 1:0; - if(!fowdone) { - fpfowx += offset_dgx * jump10; - fpfowy += offset_dgy * jump10; - } - if(tug_of_war) { - if(!revdone) { - eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy); - } - if(!fowdone) { - efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy); - } - if(!revdone) { - eri = eri - uui * 0.5; - } - if(!fowdone) { - efi = efi - uui * 0.5; - } - revdone = (ABS(eri)) >= gradexp ? 1:0; - fowdone = (ABS(efi)) >= gradexp ? 1:0; - if(!revdone) { - fprevx -= offset_dgx * jump11; - fprevy -= offset_dgy * jump11; - } - tug_of_war = (!revdone) || (!fowdone) ? 1:0; - if(!fowdone) { - fpfowx += offset_dgx * jump11; - fpfowy += offset_dgy * jump11; - } - if(tug_of_war) { - if(!revdone) { - eri = get_pixel_intensity_bilinear(buf, buf_x, buf_y,fprevx,fprevy); - } - if(!fowdone) { - efi = get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpfowx,fpfowy); - } - if(!revdone) { - eri = eri - uui * 0.5; - } - if(!fowdone) { - efi = efi - uui * 0.5; - } - revdone = (ABS(eri)) >= gradexp ? 1:0; - fowdone = (ABS(efi)) >= gradexp ? 1:0; - if(!revdone) { - fprevx -= offset_dgx * jump12; - fprevy -= offset_dgy * jump12; - } - tug_of_war = (!revdone) || (!fowdone) ? 1:0; - if(!fowdone) { - fpfowx += offset_dgx * jump12; - fpfowy += offset_dgy * jump12; - } - } - } - } - } - } - } - } - } - } - } - revdst = fpcx - fprevx; - fowdst = fpfowx - fpcx; - if(!lrsp) { - revdst = fpcy - fprevy; - fowdst = fpfowy - fpcy; - } - - revsph = ((eri < 0.0f) ? 1:0) != ltz ? 1:0; - dsts = (fowdst + revdst); - fowsph = ((efi < 0.0f) ? 1:0) != ltz ? 1:0; - inv_dsts = 1.0f/dsts; - - uls = revdst < fowdst ? 1:0; - dst = MIN2(revdst, fowdst); - sph = (uls==1) ? revsph:fowsph; - tg6 = tg5 * tg5; - pxOff = (dst * (-inv_dsts)) + 0.5f; - tg7 = tg6 * quality_subpix; - - gpxOff = (sph==1) ? pxOff : 0.0f; - tgpxOff = MAX2(gpxOff, tg7); - if(!lrsp) { - fpcx += tgpxOff * sdst; - } else { - fpcy += tgpxOff * sdst; - } - set_pixel_intensity(buf,buf_x,buf_y,curr_x,curr_y,get_pixel_intensity_bilinear(buf, buf_x, buf_y, fpcx,fpcy)); - } - } - } - return 1; - -#endif -} - -#define SWAP_POLYVERT(a,b) point_temp[0]=(a)[0]; point_temp[1]=(a)[1]; (a)[0]=(b)[0]; (a)[1]=(b)[1]; (b)[0]=point_temp[0]; (b)[1]=point_temp[1]; -#define __PLX_SMALL_COUNT__ 13 -static void plx_floatsort(float(*f)[2], unsigned int n, int sortby) { - unsigned int a; - unsigned int b; - unsigned int c; - unsigned int d=1; - unsigned int hold; - unsigned int index_list[50]; - int index_offset=0; - float t[2]; - float point_temp[2]; - - hold=n; - for(;;) { - if(hold-d < __PLX_SMALL_COUNT__) { - for(b=d+1; b<=hold; b++) { - t[1]=f[b][1]; - t[0]=f[b][0]; - for(a=b-1; a>=d; a--) { - if(f[a][sortby] <= t[sortby]) { - break; - } - f[a+1][1]=f[a][1]; - f[a+1][0]=f[a][0]; - } - f[a+1][1]=t[1]; - f[a+1][0]=t[0]; - } - if(index_offset < 0) { - break; - } - hold=index_list[index_offset--]; - d=index_list[index_offset--]; - } else { - c=(d+hold) >> 1; - SWAP_POLYVERT(f[c],f[d+1]) - if(f[d][sortby] > f[hold][sortby]) { - SWAP_POLYVERT(f[d],f[hold]) - } - if(f[d+1][sortby] > f[hold][sortby]) { - SWAP_POLYVERT(f[d+1],f[hold]) - } - if(f[d][sortby] > f[d+1][sortby]) { - SWAP_POLYVERT(f[d],f[d+1]) - } - a=d+1; - b=hold; - t[0]=f[d+1][0]; - t[1]=f[d+1][1]; - for(;;) { - do a++; - while(f[a][sortby] < t[sortby]); - do b--; - while(f[b][sortby] > t[sortby]); - if(b < a) { - break; - } - SWAP_POLYVERT(f[a],f[b]) - } - f[d+1][0]=f[b][0]; - f[d+1][1]=f[b][1]; - f[b][0]=t[0]; - f[b][1]=t[1]; - index_offset+=2; - if(index_offset > __PLX_SMALL_COUNT__) { - return; - } - if(hold-a+1 >= b-d) { - index_list[index_offset]=hold; - index_list[index_offset-1]=a; - hold=b-1; - } else { - index_list[index_offset]=b-1; - index_list[index_offset-1]=d; - d=a; - } - } - } -} - -static int plx_find_lower_bound(float v, float(*a)[2], int num_feather_verts) { - int x; - int l; - int r; - l=1; - r=num_feather_verts; - for(;;) { - // interpolation style search - //x=l+(v-a[l][1])*(r-l) / (a[r][1]-a[l][1]); - - // binary search - x=(l+r) / 2; - if(va[x-1][1] && v <= a[x][1]) || l>r) { - break; - } - } - if(v>a[x-1][1] && v <= a[x][1]) { - return x; - } else { - return num_feather_verts; - } -} - -static int plx_find_upper_bound(float v, float(*a)[2], int num_feather_verts) { - int x; - int l; - int r; - l=1; - r=num_feather_verts; - for(;;) { - // interpolation style search - //x=l+(v-a[l][1])*(r-l) / (a[r][1]-a[l][1]); - - // binary search - x=(l+r) / 2; - if(v=a[x-1][1] && v < a[x][1]) || l>r) { - break; - } - } - if(v>=a[x-1][1] && v < a[x][1]) { - return x-1; - } else { - return num_feather_verts; - } -} - diff --git a/intern/raskter/raskter.h b/intern/raskter/raskter.h index cf679dd37c0..cf691a9784b 100644 --- a/intern/raskter/raskter.h +++ b/intern/raskter/raskter.h @@ -27,80 +27,14 @@ /** \file raskter.h * \ingroup RASKTER */ -/* from BLI_utildefines.h */ -#define MIN2(x, y) ( (x) < (y) ? (x) : (y) ) -#define MAX2(x, y) ( (x) > (y) ? (x) : (y) ) -#define ABS(a) ( (a) < 0 ? (-(a)) : (a) ) - -struct poly_vert { - int x; - int y; -}; - -struct scan_line { - int xstart; - int xend; -}; - -struct scan_line_batch { - int num; - int ystart; - struct scan_line *slines; -}; - -struct e_status { - int x; - int ybeg; - int xshift; - int xdir; - int drift; - int drift_inc; - int drift_dec; - int num; - struct e_status *e_next; -}; - -struct r_buffer_stats { - float *buf; - int sizex; - int sizey; - int ymin; - int ymax; - int xmin; - int xmax; -}; - -struct r_fill_context { - struct e_status *all_edges, *possible_edges; - struct r_buffer_stats rb; - struct scan_line *bounds; - void *kdo; //only used with kd tree - void *kdi; //only used with kd tree - int *bound_indexes; - int bounds_length; -}; - -struct layer_init_data { - struct poly_vert *imask; - struct poly_vert *omask; - struct scan_line *bounds; - int *bound_indexes; - int bounds_length; -}; #ifdef __cplusplus extern "C" { #endif -void preprocess_all_edges(struct r_fill_context *ctx, struct poly_vert *verts, int num_verts, struct e_status *open_edge); -int PLX_init_base_data(struct layer_init_data *mlayer_data, float(*base_verts)[2], int num_base_verts, - float *buf, int buf_x, int buf_y); int PLX_raskterize(float (*base_verts)[2], int num_base_verts, - float *buf, int buf_x, int buf_y, int do_mask_AA); -int PLX_raskterize_feather(float (*base_verts)[2], int num_base_verts, - float (*feather_verts)[2], int num_feather_verts, - float *buf, int buf_x, int buf_y); -int PLX_antialias_buffer(float *buf, int buf_x, int buf_y); + float *buf, int buf_x, int buf_y); + #ifdef __cplusplus } #endif diff --git a/intern/raskter/raskter_kdtree.c b/intern/raskter/raskter_kdtree.c deleted file mode 100644 index 06fbc5dccd0..00000000000 --- a/intern/raskter/raskter_kdtree.c +++ /dev/null @@ -1,836 +0,0 @@ -/* -This file is part of ``kdtree'', a library for working with kd-trees. -Copyright (C) 2007-2011 John Tsiombikas - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. 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. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. -*/ -/* single nearest neighbor search written by Tamas Nepusz */ -#include -#include -#include -#include -#include "raskter_kdtree.h" - -#if defined(WIN32) || defined(__WIN32__) -#include -#endif - -#ifdef USE_LIST_NODE_ALLOCATOR - -#ifndef NO_PTHREADS -#include -#else - -#ifndef I_WANT_THREAD_BUGS -#error "You are compiling with the fast list node allocator, with pthreads disabled! This WILL break if used from multiple threads." -#endif /* I want thread bugs */ - -#endif /* pthread support */ -#endif /* use list node allocator */ - -struct kdhyperrect { - int dim; - double *min, *max; /* minimum/maximum coords */ -}; - -struct kdnode { - double *pos; - int dir; - void *data; - - struct kdnode *left, *right; /* negative/positive side */ -}; - -struct res_node { - struct kdnode *item; - double dist_sq; - struct res_node *next; -}; - -struct kdtree { - int dim; - struct kdnode *root; - struct kdhyperrect *rect; - void (*destr)(void*); -}; - -struct kdres { - struct kdtree *tree; - struct res_node *rlist, *riter; - int size; -}; - -#define SQ(x) ((x) * (x)) - - -static void clear_rec(struct kdnode *node, void (*destr)(void*)); -static int insert_rec(struct kdnode **node, const double *pos, void *data, int dir, int dim); -static int rlist_insert(struct res_node *list, struct kdnode *item, double dist_sq); -static void clear_results(struct kdres *set); - -static struct kdhyperrect* hyperrect_create(int dim, const double *min, const double *max); -static void hyperrect_free(struct kdhyperrect *rect); -static struct kdhyperrect* hyperrect_duplicate(const struct kdhyperrect *rect); -static void hyperrect_extend(struct kdhyperrect *rect, const double *pos); -static double hyperrect_dist_sq(struct kdhyperrect *rect, const double *pos); - -#ifdef USE_LIST_NODE_ALLOCATOR -static struct res_node *alloc_resnode(void); -static void free_resnode(struct res_node*); -#else -#define alloc_resnode() malloc(sizeof(struct res_node)) -#define free_resnode(n) free(n) -#endif - - - -struct kdtree *kd_create(int k) -{ - struct kdtree *tree; - - if(!(tree = malloc(sizeof *tree))) { - return 0; - } - - tree->dim = k; - tree->root = 0; - tree->destr = 0; - tree->rect = 0; - - return tree; -} - -void kd_free(struct kdtree *tree) -{ - if(tree) { - kd_clear(tree); - free(tree); - } -} - -static void clear_rec(struct kdnode *node, void (*destr)(void*)) -{ - if(!node) return; - - clear_rec(node->left, destr); - clear_rec(node->right, destr); - - if(destr) { - destr(node->data); - } - free(node->pos); - free(node); -} - -void kd_clear(struct kdtree *tree) -{ - clear_rec(tree->root, tree->destr); - tree->root = 0; - - if (tree->rect) { - hyperrect_free(tree->rect); - tree->rect = 0; - } -} - -void kd_data_destructor(struct kdtree *tree, void (*destr)(void*)) -{ - tree->destr = destr; -} - - -static int insert_rec(struct kdnode **nptr, const double *pos, void *data, int dir, int dim) -{ - int new_dir; - struct kdnode *node; - - if(!*nptr) { - if(!(node = malloc(sizeof *node))) { - return -1; - } - if(!(node->pos = malloc(dim * sizeof *node->pos))) { - free(node); - return -1; - } - memcpy(node->pos, pos, dim * sizeof *node->pos); - node->data = data; - node->dir = dir; - node->left = node->right = 0; - *nptr = node; - return 0; - } - - node = *nptr; - new_dir = (node->dir + 1) % dim; - if(pos[node->dir] < node->pos[node->dir]) { - return insert_rec(&(*nptr)->left, pos, data, new_dir, dim); - } - return insert_rec(&(*nptr)->right, pos, data, new_dir, dim); -} - -int kd_insert(struct kdtree *tree, const double *pos, void *data) -{ - if (insert_rec(&tree->root, pos, data, 0, tree->dim)) { - return -1; - } - - if (tree->rect == 0) { - tree->rect = hyperrect_create(tree->dim, pos, pos); - } else { - hyperrect_extend(tree->rect, pos); - } - - return 0; -} - -int kd_insertf(struct kdtree *tree, const float *pos, void *data) -{ - static double sbuf[16]; - double *bptr, *buf = 0; - int res, dim = tree->dim; - - if(dim > 16) { -#ifndef NO_ALLOCA - if(dim <= 256) - bptr = buf = alloca(dim * sizeof *bptr); - else -#endif - if(!(bptr = buf = malloc(dim * sizeof *bptr))) { - return -1; - } - } else { - bptr = buf = sbuf; - } - - while(dim-- > 0) { - *bptr++ = *pos++; - } - - res = kd_insert(tree, buf, data); -#ifndef NO_ALLOCA - if(tree->dim > 256) -#else - if(tree->dim > 16) -#endif - free(buf); - return res; -} - -int kd_insert3(struct kdtree *tree, double x, double y, double z, void *data) -{ - double buf[3]; - buf[0] = x; - buf[1] = y; - buf[2] = z; - return kd_insert(tree, buf, data); -} - -int kd_insert3f(struct kdtree *tree, float x, float y, float z, void *data) -{ - double buf[3]; - buf[0] = x; - buf[1] = y; - buf[2] = z; - return kd_insert(tree, buf, data); -} - -static int find_nearest(struct kdnode *node, const double *pos, double range, struct res_node *list, int ordered, int dim) -{ - double dist_sq, dx; - int i, ret, added_res = 0; - - if(!node) return 0; - - dist_sq = 0; - for(i=0; ipos[i] - pos[i]); - } - if(dist_sq <= SQ(range)) { - if(rlist_insert(list, node, ordered ? dist_sq : -1.0) == -1) { - return -1; - } - added_res = 1; - } - - dx = pos[node->dir] - node->pos[node->dir]; - - ret = find_nearest(dx <= 0.0 ? node->left : node->right, pos, range, list, ordered, dim); - if(ret >= 0 && fabs(dx) < range) { - added_res += ret; - ret = find_nearest(dx <= 0.0 ? node->right : node->left, pos, range, list, ordered, dim); - } - if(ret == -1) { - return -1; - } - added_res += ret; - - return added_res; -} - -#if 0 -static int find_nearest_n(struct kdnode *node, const double *pos, double range, int num, struct rheap *heap, int dim) -{ - double dist_sq, dx; - int i, ret, added_res = 0; - - if(!node) return 0; - - /* if the photon is close enough, add it to the result heap */ - dist_sq = 0; - for(i=0; ipos[i] - pos[i]); - } - if(dist_sq <= range_sq) { - if(heap->size >= num) { - /* get furthest element */ - struct res_node *maxelem = rheap_get_max(heap); - - /* and check if the new one is closer than that */ - if(maxelem->dist_sq > dist_sq) { - rheap_remove_max(heap); - - if(rheap_insert(heap, node, dist_sq) == -1) { - return -1; - } - added_res = 1; - - range_sq = dist_sq; - } - } else { - if(rheap_insert(heap, node, dist_sq) == -1) { - return =1; - } - added_res = 1; - } - } - - - /* find signed distance from the splitting plane */ - dx = pos[node->dir] - node->pos[node->dir]; - - ret = find_nearest_n(dx <= 0.0 ? node->left : node->right, pos, range, num, heap, dim); - if(ret >= 0 && fabs(dx) < range) { - added_res += ret; - ret = find_nearest_n(dx <= 0.0 ? node->right : node->left, pos, range, num, heap, dim); - } - -} -#endif - -static void kd_nearest_i(struct kdnode *node, const double *pos, struct kdnode **result, double *result_dist_sq, struct kdhyperrect* rect) -{ - int dir = node->dir; - int i; - double dummy, dist_sq; - struct kdnode *nearer_subtree, *farther_subtree; - double *nearer_hyperrect_coord, *farther_hyperrect_coord; - - /* Decide whether to go left or right in the tree */ - dummy = pos[dir] - node->pos[dir]; - if (dummy <= 0) { - nearer_subtree = node->left; - farther_subtree = node->right; - nearer_hyperrect_coord = rect->max + dir; - farther_hyperrect_coord = rect->min + dir; - } else { - nearer_subtree = node->right; - farther_subtree = node->left; - nearer_hyperrect_coord = rect->min + dir; - farther_hyperrect_coord = rect->max + dir; - } - - if (nearer_subtree) { - /* Slice the hyperrect to get the hyperrect of the nearer subtree */ - dummy = *nearer_hyperrect_coord; - *nearer_hyperrect_coord = node->pos[dir]; - /* Recurse down into nearer subtree */ - kd_nearest_i(nearer_subtree, pos, result, result_dist_sq, rect); - /* Undo the slice */ - *nearer_hyperrect_coord = dummy; - } - - /* Check the distance of the point at the current node, compare it - * with our best so far */ - dist_sq = 0; - for(i=0; i < rect->dim; i++) { - dist_sq += SQ(node->pos[i] - pos[i]); - } - if (dist_sq < *result_dist_sq) { - *result = node; - *result_dist_sq = dist_sq; - } - - if (farther_subtree) { - /* Get the hyperrect of the farther subtree */ - dummy = *farther_hyperrect_coord; - *farther_hyperrect_coord = node->pos[dir]; - /* Check if we have to recurse down by calculating the closest - * point of the hyperrect and see if it's closer than our - * minimum distance in result_dist_sq. */ - if (hyperrect_dist_sq(rect, pos) < *result_dist_sq) { - /* Recurse down into farther subtree */ - kd_nearest_i(farther_subtree, pos, result, result_dist_sq, rect); - } - /* Undo the slice on the hyperrect */ - *farther_hyperrect_coord = dummy; - } -} - -struct kdres *kd_nearest(struct kdtree *kd, const double *pos) -{ - struct kdhyperrect *rect; - struct kdnode *result; - struct kdres *rset; - double dist_sq; - int i; - - if (!kd) return 0; - if (!kd->rect) return 0; - - /* Allocate result set */ - if(!(rset = malloc(sizeof *rset))) { - return 0; - } - if(!(rset->rlist = alloc_resnode())) { - free(rset); - return 0; - } - rset->rlist->next = 0; - rset->tree = kd; - - /* Duplicate the bounding hyperrectangle, we will work on the copy */ - if (!(rect = hyperrect_duplicate(kd->rect))) { - kd_res_free(rset); - return 0; - } - - /* Our first guesstimate is the root node */ - result = kd->root; - dist_sq = 0; - for (i = 0; i < kd->dim; i++) - dist_sq += SQ(result->pos[i] - pos[i]); - - /* Search for the nearest neighbour recursively */ - kd_nearest_i(kd->root, pos, &result, &dist_sq, rect); - - /* Free the copy of the hyperrect */ - hyperrect_free(rect); - - /* Store the result */ - if (result) { - if (rlist_insert(rset->rlist, result, -1.0) == -1) { - kd_res_free(rset); - return 0; - } - rset->size = 1; - kd_res_rewind(rset); - return rset; - } else { - kd_res_free(rset); - return 0; - } -} - -struct kdres *kd_nearestf(struct kdtree *tree, const float *pos) -{ - static double sbuf[16]; - double *bptr, *buf = 0; - int dim = tree->dim; - struct kdres *res; - - if(dim > 16) { -#ifndef NO_ALLOCA - if(dim <= 256) - bptr = buf = alloca(dim * sizeof *bptr); - else -#endif - if(!(bptr = buf = malloc(dim * sizeof *bptr))) { - return 0; - } - } else { - bptr = buf = sbuf; - } - - while(dim-- > 0) { - *bptr++ = *pos++; - } - - res = kd_nearest(tree, buf); -#ifndef NO_ALLOCA - if(tree->dim > 256) -#else - if(tree->dim > 16) -#endif - free(buf); - return res; -} - -struct kdres *kd_nearest3(struct kdtree *tree, double x, double y, double z) -{ - double pos[3]; - pos[0] = x; - pos[1] = y; - pos[2] = z; - return kd_nearest(tree, pos); -} - -struct kdres *kd_nearest3f(struct kdtree *tree, float x, float y, float z) -{ - double pos[3]; - pos[0] = x; - pos[1] = y; - pos[2] = z; - return kd_nearest(tree, pos); -} - -/* ---- nearest N search ---- */ -/* -static kdres *kd_nearest_n(struct kdtree *kd, const double *pos, int num) -{ - int ret; - struct kdres *rset; - - if(!(rset = malloc(sizeof *rset))) { - return 0; - } - if(!(rset->rlist = alloc_resnode())) { - free(rset); - return 0; - } - rset->rlist->next = 0; - rset->tree = kd; - - if((ret = find_nearest_n(kd->root, pos, range, num, rset->rlist, kd->dim)) == -1) { - kd_res_free(rset); - return 0; - } - rset->size = ret; - kd_res_rewind(rset); - return rset; -}*/ - -struct kdres *kd_nearest_range(struct kdtree *kd, const double *pos, double range) -{ - int ret; - struct kdres *rset; - - if(!(rset = malloc(sizeof *rset))) { - return 0; - } - if(!(rset->rlist = alloc_resnode())) { - free(rset); - return 0; - } - rset->rlist->next = 0; - rset->tree = kd; - - if((ret = find_nearest(kd->root, pos, range, rset->rlist, 0, kd->dim)) == -1) { - kd_res_free(rset); - return 0; - } - rset->size = ret; - kd_res_rewind(rset); - return rset; -} - -struct kdres *kd_nearest_rangef(struct kdtree *kd, const float *pos, float range) -{ - static double sbuf[16]; - double *bptr, *buf = 0; - int dim = kd->dim; - struct kdres *res; - - if(dim > 16) { -#ifndef NO_ALLOCA - if(dim <= 256) - bptr = buf = alloca(dim * sizeof *bptr); - else -#endif - if(!(bptr = buf = malloc(dim * sizeof *bptr))) { - return 0; - } - } else { - bptr = buf = sbuf; - } - - while(dim-- > 0) { - *bptr++ = *pos++; - } - - res = kd_nearest_range(kd, buf, range); -#ifndef NO_ALLOCA - if(kd->dim > 256) -#else - if(kd->dim > 16) -#endif - free(buf); - return res; -} - -struct kdres *kd_nearest_range3(struct kdtree *tree, double x, double y, double z, double range) -{ - double buf[3]; - buf[0] = x; - buf[1] = y; - buf[2] = z; - return kd_nearest_range(tree, buf, range); -} - -struct kdres *kd_nearest_range3f(struct kdtree *tree, float x, float y, float z, float range) -{ - double buf[3]; - buf[0] = x; - buf[1] = y; - buf[2] = z; - return kd_nearest_range(tree, buf, range); -} - -void kd_res_free(struct kdres *rset) -{ - clear_results(rset); - free_resnode(rset->rlist); - free(rset); -} - -int kd_res_size(struct kdres *set) -{ - return (set->size); -} - -void kd_res_rewind(struct kdres *rset) -{ - rset->riter = rset->rlist->next; -} - -int kd_res_end(struct kdres *rset) -{ - return rset->riter == 0; -} - -int kd_res_next(struct kdres *rset) -{ - rset->riter = rset->riter->next; - return rset->riter != 0; -} - -void *kd_res_item(struct kdres *rset, double *pos) -{ - if(rset->riter) { - if(pos) { - memcpy(pos, rset->riter->item->pos, rset->tree->dim * sizeof *pos); - } - return rset->riter->item->data; - } - return 0; -} - -void *kd_res_itemf(struct kdres *rset, float *pos) -{ - if(rset->riter) { - if(pos) { - int i; - for(i=0; itree->dim; i++) { - pos[i] = rset->riter->item->pos[i]; - } - } - return rset->riter->item->data; - } - return 0; -} - -void *kd_res_item3(struct kdres *rset, double *x, double *y, double *z) -{ - if(rset->riter) { - if(*x) *x = rset->riter->item->pos[0]; - if(*y) *y = rset->riter->item->pos[1]; - if(*z) *z = rset->riter->item->pos[2]; - } - return 0; -} - -void *kd_res_item3f(struct kdres *rset, float *x, float *y, float *z) -{ - if(rset->riter) { - if(*x) *x = rset->riter->item->pos[0]; - if(*y) *y = rset->riter->item->pos[1]; - if(*z) *z = rset->riter->item->pos[2]; - } - return 0; -} - -void *kd_res_item_data(struct kdres *set) -{ - return kd_res_item(set, 0); -} - -/* ---- hyperrectangle helpers ---- */ -static struct kdhyperrect* hyperrect_create(int dim, const double *min, const double *max) -{ - size_t size = dim * sizeof(double); - struct kdhyperrect* rect = 0; - - if (!(rect = malloc(sizeof(struct kdhyperrect)))) { - return 0; - } - - rect->dim = dim; - if (!(rect->min = malloc(size))) { - free(rect); - return 0; - } - if (!(rect->max = malloc(size))) { - free(rect->min); - free(rect); - return 0; - } - memcpy(rect->min, min, size); - memcpy(rect->max, max, size); - - return rect; -} - -static void hyperrect_free(struct kdhyperrect *rect) -{ - free(rect->min); - free(rect->max); - free(rect); -} - -static struct kdhyperrect* hyperrect_duplicate(const struct kdhyperrect *rect) -{ - return hyperrect_create(rect->dim, rect->min, rect->max); -} - -static void hyperrect_extend(struct kdhyperrect *rect, const double *pos) -{ - int i; - - for (i=0; i < rect->dim; i++) { - if (pos[i] < rect->min[i]) { - rect->min[i] = pos[i]; - } - if (pos[i] > rect->max[i]) { - rect->max[i] = pos[i]; - } - } -} - -static double hyperrect_dist_sq(struct kdhyperrect *rect, const double *pos) -{ - int i; - double result = 0; - - for (i=0; i < rect->dim; i++) { - if (pos[i] < rect->min[i]) { - result += SQ(rect->min[i] - pos[i]); - } else if (pos[i] > rect->max[i]) { - result += SQ(rect->max[i] - pos[i]); - } - } - - return result; -} - -/* ---- static helpers ---- */ - -#ifdef USE_LIST_NODE_ALLOCATOR -/* special list node allocators. */ -static struct res_node *free_nodes; - -#ifndef NO_PTHREADS -static pthread_mutex_t alloc_mutex = PTHREAD_MUTEX_INITIALIZER; -#endif - -static struct res_node *alloc_resnode(void) -{ - struct res_node *node; - -#ifndef NO_PTHREADS - pthread_mutex_lock(&alloc_mutex); -#endif - - if(!free_nodes) { - node = malloc(sizeof *node); - } else { - node = free_nodes; - free_nodes = free_nodes->next; - node->next = 0; - } - -#ifndef NO_PTHREADS - pthread_mutex_unlock(&alloc_mutex); -#endif - - return node; -} - -static void free_resnode(struct res_node *node) -{ -#ifndef NO_PTHREADS - pthread_mutex_lock(&alloc_mutex); -#endif - - node->next = free_nodes; - free_nodes = node; - -#ifndef NO_PTHREADS - pthread_mutex_unlock(&alloc_mutex); -#endif -} -#endif /* list node allocator or not */ - - -/* inserts the item. if dist_sq is >= 0, then do an ordered insert */ -/* TODO make the ordering code use heapsort */ -static int rlist_insert(struct res_node *list, struct kdnode *item, double dist_sq) -{ - struct res_node *rnode; - - if(!(rnode = alloc_resnode())) { - return -1; - } - rnode->item = item; - rnode->dist_sq = dist_sq; - - if(dist_sq >= 0.0) { - while(list->next && list->next->dist_sq < dist_sq) { - list = list->next; - } - } - rnode->next = list->next; - list->next = rnode; - return 0; -} - -static void clear_results(struct kdres *rset) -{ - struct res_node *tmp, *node = rset->rlist->next; - - while(node) { - tmp = node; - node = node->next; - free_resnode(tmp); - } - - rset->rlist->next = 0; -} diff --git a/intern/raskter/raskter_kdtree.h b/intern/raskter/raskter_kdtree.h deleted file mode 100644 index da80e422a80..00000000000 --- a/intern/raskter/raskter_kdtree.h +++ /dev/null @@ -1,129 +0,0 @@ -/* -This file is part of ``kdtree'', a library for working with kd-trees. -Copyright (C) 2007-2011 John Tsiombikas - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. 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. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 _KDTREE_H_ -#define _KDTREE_H_ -#define USE_LIST_NODE_ALLOCATOR -#ifdef __cplusplus -extern "C" { -#endif - -struct kdtree; -struct kdres; - - -/* create a kd-tree for "k"-dimensional data */ -struct kdtree *kd_create(int k); - -/* free the struct kdtree */ -void kd_free(struct kdtree *tree); - -/* remove all the elements from the tree */ -void kd_clear(struct kdtree *tree); - -/* if called with non-null 2nd argument, the function provided - * will be called on data pointers (see kd_insert) when nodes - * are to be removed from the tree. - */ -void kd_data_destructor(struct kdtree *tree, void (*destr)(void*)); - -/* insert a node, specifying its position, and optional data */ -int kd_insert(struct kdtree *tree, const double *pos, void *data); -int kd_insertf(struct kdtree *tree, const float *pos, void *data); -int kd_insert3(struct kdtree *tree, double x, double y, double z, void *data); -int kd_insert3f(struct kdtree *tree, float x, float y, float z, void *data); - -/* Find the nearest node from a given point. - * - * This function returns a pointer to a result set with at most one element. - */ -struct kdres *kd_nearest(struct kdtree *tree, const double *pos); -struct kdres *kd_nearestf(struct kdtree *tree, const float *pos); -struct kdres *kd_nearest3(struct kdtree *tree, double x, double y, double z); -struct kdres *kd_nearest3f(struct kdtree *tree, float x, float y, float z); - -/* Find the N nearest nodes from a given point. - * - * This function returns a pointer to a result set, with at most N elements, - * which can be manipulated with the kd_res_* functions. - * The returned pointer can be null as an indication of an error. Otherwise - * a valid result set is always returned which may contain 0 or more elements. - * The result set must be deallocated with kd_res_free after use. - */ -/* -struct kdres *kd_nearest_n(struct kdtree *tree, const double *pos, int num); -struct kdres *kd_nearest_nf(struct kdtree *tree, const float *pos, int num); -struct kdres *kd_nearest_n3(struct kdtree *tree, double x, double y, double z); -struct kdres *kd_nearest_n3f(struct kdtree *tree, float x, float y, float z); -*/ - -/* Find any nearest nodes from a given point within a range. - * - * This function returns a pointer to a result set, which can be manipulated - * by the kd_res_* functions. - * The returned pointer can be null as an indication of an error. Otherwise - * a valid result set is always returned which may contain 0 or more elements. - * The result set must be deallocated with kd_res_free after use. - */ -struct kdres *kd_nearest_range(struct kdtree *tree, const double *pos, double range); -struct kdres *kd_nearest_rangef(struct kdtree *tree, const float *pos, float range); -struct kdres *kd_nearest_range3(struct kdtree *tree, double x, double y, double z, double range); -struct kdres *kd_nearest_range3f(struct kdtree *tree, float x, float y, float z, float range); - -/* frees a result set returned by kd_nearest_range() */ -void kd_res_free(struct kdres *set); - -/* returns the size of the result set (in elements) */ -int kd_res_size(struct kdres *set); - -/* rewinds the result set iterator */ -void kd_res_rewind(struct kdres *set); - -/* returns non-zero if the set iterator reached the end after the last element */ -int kd_res_end(struct kdres *set); - -/* advances the result set iterator, returns non-zero on success, zero if - * there are no more elements in the result set. - */ -int kd_res_next(struct kdres *set); - -/* returns the data pointer (can be null) of the current result set item - * and optionally sets its position to the pointers(s) if not null. - */ -void *kd_res_item(struct kdres *set, double *pos); -void *kd_res_itemf(struct kdres *set, float *pos); -void *kd_res_item3(struct kdres *set, double *x, double *y, double *z); -void *kd_res_item3f(struct kdres *set, float *x, float *y, float *z); - -/* equivalent to kd_res_item(set, 0) */ -void *kd_res_item_data(struct kdres *set); - - -#ifdef __cplusplus -} -#endif - -#endif /* _KDTREE_H_ */ diff --git a/intern/raskter/raskter_mt.c b/intern/raskter/raskter_mt.c deleted file mode 100644 index feda624d668..00000000000 --- a/intern/raskter/raskter_mt.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2012 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Peter Larabell. - * - * ***** END GPL LICENSE BLOCK ***** - */ -/** \file raskter_mt.c - * \ingroup RASKTER - */ -#include - -#include "raskter.h" -static int rast_scan_init(struct layer_init_data *mlayer_data, struct r_fill_context *ctx, struct poly_vert *verts, int num_verts) { - int x_curr; /* current pixel position in X */ - int y_curr; /* current scan line being drawn */ - int yp; /* y-pixel's position in frame buffer */ - int swixd = 0; /* whether or not edges switched position in X */ - int i=0; /* counter */ - float *cpxl; /* pixel pointers... */ - float *mpxl; - float *spxl; - struct e_status *e_curr; /* edge pointers... */ - struct e_status *e_temp; - struct e_status *edgbuf; - struct e_status **edgec; - - - if(num_verts < 3) { - return(1); - } - - if((edgbuf = (struct e_status *)(malloc(sizeof(struct e_status) * num_verts))) == NULL) { - return(0); - } - - /* set initial bounds length to 0 */ - mlayer_data->bounds_length=0; - - /* round 1, count up all the possible spans in the base buffer */ - preprocess_all_edges(ctx, verts, num_verts, edgbuf); - - /* can happen with a zero area mask */ - if (ctx->all_edges == NULL) { - free(edgbuf); - return(1); - } - ctx->possible_edges = NULL; - - for(y_curr = ctx->all_edges->ybeg; (ctx->all_edges || ctx->possible_edges); y_curr++) { - - for(edgec = &ctx->possible_edges; ctx->all_edges && (ctx->all_edges->ybeg == y_curr);) { - x_curr = ctx->all_edges->x; /* Set current X position. */ - for(;;) { /* Start looping edges. Will break when edges run out. */ - e_curr = *edgec; /* Set up a current edge pointer. */ - if(!e_curr || (e_curr->x >= x_curr)) { /* If we have an no edge, or we need to skip some X-span, */ - e_temp = ctx->all_edges->e_next; /* set a temp "next" edge to test. */ - *edgec = ctx->all_edges; /* Add this edge to the list to be scanned. */ - ctx->all_edges->e_next = e_curr; /* Set up the next edge. */ - edgec = &ctx->all_edges->e_next; /* Set our list to the next edge's location in memory. */ - ctx->all_edges = e_temp; /* Skip the NULL or bad X edge, set pointer to next edge. */ - break; /* Stop looping edges (since we ran out or hit empty X span. */ - } else { - edgec = &e_curr->e_next; /* Set the pointer to the edge list the "next" edge. */ - } - } - } - - yp = y_curr * ctx->rb.sizex; - spxl = ctx->rb.buf + (yp); - - for(e_curr = ctx->possible_edges; e_curr; e_curr = e_curr->e_next) { - - /* set up xmin and xmax bounds on this scan line */ - cpxl = spxl + MAX2(e_curr->x, 0); - e_curr = e_curr->e_next; - mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1; - - if((y_curr >= 0) && (y_curr < ctx->rb.sizey)) { - mlayer_data->bounds_length++; - } - } - - for(edgec = &ctx->possible_edges; (e_curr = *edgec);) { - if(!(--(e_curr->num))) { - *edgec = e_curr->e_next; - } else { - e_curr->x += e_curr->xshift; - if((e_curr->drift += e_curr->drift_inc) > 0) { - e_curr->x += e_curr->xdir; - e_curr->drift -= e_curr->drift_dec; - } - edgec = &e_curr->e_next; - } - } - if(ctx->possible_edges) { - for(edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { - /* if the current edge hits scan line at greater X than the next edge, we need to exchange the edges */ - if(e_curr->x > e_curr->e_next->x) { - *edgec = e_curr->e_next; - /* exchange the pointers */ - e_temp = e_curr->e_next->e_next; - e_curr->e_next->e_next = e_curr; - e_curr->e_next = e_temp; - /* set flag that we had at least one switch */ - swixd = 1; - } - } - /* if we did have a switch, look for more (there will more if there was one) */ - for(;;) { - /* reset exchange flag so it's only set if we encounter another one */ - swixd = 0; - for(edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { - /* again, if current edge hits scan line at higher X than next edge, exchange the edges and set flag */ - if(e_curr->x > e_curr->e_next->x) { - *edgec = e_curr->e_next; - /* exchange the pointers */ - e_temp = e_curr->e_next->e_next; - e_curr->e_next->e_next = e_curr; - e_curr->e_next = e_temp; - /* flip the exchanged flag */ - swixd = 1; - } - } - /* if we had no exchanges, we're done reshuffling the pointers */ - if(!swixd) { - break; - } - } - } - } - - -/*initialize index buffer and bounds buffers*/ - //gets the +1 for dummy at the end - if((mlayer_data->bound_indexes = (int *)(malloc(sizeof(int) * ctx->rb.sizey+1)))==NULL) { - return(0); - } - //gets the +1 for dummy at the start - if((mlayer_data->bounds = (struct scan_line *)(malloc(sizeof(struct scan_line) * mlayer_data->bounds_length+1)))==NULL){ - return(0); - } - //init all the indexes to zero (are they already zeroed from malloc???) - for(i=0;irb.sizey+1;i++){ - mlayer_data->bound_indexes[i]=0; - } - /* round 2, fill in the full list of bounds, and create indexes to the list... */ - preprocess_all_edges(ctx, verts, num_verts, edgbuf); - - /* can happen with a zero area mask */ - if (ctx->all_edges == NULL) { - free(edgbuf); - return(1); - } - ctx->possible_edges = NULL; - - /* restart i as a counter for total span placement in buffer */ - i=1; - for(y_curr = ctx->all_edges->ybeg; (ctx->all_edges || ctx->possible_edges); y_curr++) { - - for(edgec = &ctx->possible_edges; ctx->all_edges && (ctx->all_edges->ybeg == y_curr);) { - x_curr = ctx->all_edges->x; /* Set current X position. */ - for(;;) { /* Start looping edges. Will break when edges run out. */ - e_curr = *edgec; /* Set up a current edge pointer. */ - if(!e_curr || (e_curr->x >= x_curr)) { /* If we have an no edge, or we need to skip some X-span, */ - e_temp = ctx->all_edges->e_next; /* set a temp "next" edge to test. */ - *edgec = ctx->all_edges; /* Add this edge to the list to be scanned. */ - ctx->all_edges->e_next = e_curr; /* Set up the next edge. */ - edgec = &ctx->all_edges->e_next; /* Set our list to the next edge's location in memory. */ - ctx->all_edges = e_temp; /* Skip the NULL or bad X edge, set pointer to next edge. */ - break; /* Stop looping edges (since we ran out or hit empty X span. */ - } else { - edgec = &e_curr->e_next; /* Set the pointer to the edge list the "next" edge. */ - } - } - } - - yp = y_curr * ctx->rb.sizex; - spxl = ctx->rb.buf + (yp); - if((y_curr >=0) && (y_curr < ctx->rb.sizey)){ - ctx->bound_indexes[y_curr]=i; - } - for(e_curr = ctx->possible_edges; e_curr; e_curr = e_curr->e_next) { - - /* set up xmin and xmax bounds on this scan line */ - cpxl = spxl + MAX2(e_curr->x, 0); - e_curr = e_curr->e_next; - mpxl = spxl + MIN2(e_curr->x, ctx->rb.sizex) - 1; - - if((y_curr >= 0) && (y_curr < ctx->rb.sizey)) { - mlayer_data->bounds[i].xstart=cpxl-spxl; - mlayer_data->bounds[i].xend=mpxl-spxl; - i++; - } - } - - for(edgec = &ctx->possible_edges; (e_curr = *edgec);) { - if(!(--(e_curr->num))) { - *edgec = e_curr->e_next; - } else { - e_curr->x += e_curr->xshift; - if((e_curr->drift += e_curr->drift_inc) > 0) { - e_curr->x += e_curr->xdir; - e_curr->drift -= e_curr->drift_dec; - } - edgec = &e_curr->e_next; - } - } - if(ctx->possible_edges) { - for(edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { - /* if the current edge hits scan line at greater X than the next edge, we need to exchange the edges */ - if(e_curr->x > e_curr->e_next->x) { - *edgec = e_curr->e_next; - /* exchange the pointers */ - e_temp = e_curr->e_next->e_next; - e_curr->e_next->e_next = e_curr; - e_curr->e_next = e_temp; - /* set flag that we had at least one switch */ - swixd = 1; - } - } - /* if we did have a switch, look for more (there will more if there was one) */ - for(;;) { - /* reset exchange flag so it's only set if we encounter another one */ - swixd = 0; - for(edgec = &ctx->possible_edges; (e_curr = *edgec)->e_next; edgec = &(*edgec)->e_next) { - /* again, if current edge hits scan line at higher X than next edge, exchange the edges and set flag */ - if(e_curr->x > e_curr->e_next->x) { - *edgec = e_curr->e_next; - /* exchange the pointers */ - e_temp = e_curr->e_next->e_next; - e_curr->e_next->e_next = e_curr; - e_curr->e_next = e_temp; - /* flip the exchanged flag */ - swixd = 1; - } - } - /* if we had no exchanges, we're done reshuffling the pointers */ - if(!swixd) { - break; - } - } - } - } - - free(edgbuf); - return 1; -} - -/* static */ int PLX_init_base_data(struct layer_init_data *mlayer_data, float(*base_verts)[2], int num_base_verts, - float *buf, int buf_x, int buf_y) { - int i; /* i: Loop counter. */ - struct poly_vert *ply; /* ply: Pointer to a list of integer buffer-space vertex coordinates. */ - struct r_fill_context ctx = {0}; - const float buf_x_f = (float)(buf_x); - const float buf_y_f = (float)(buf_y); - if((ply = (struct poly_vert *)(malloc(sizeof(struct poly_vert) * num_base_verts))) == NULL) { - return(0); - } - ctx.rb.buf = buf; /* Set the output buffer pointer. */ - ctx.rb.sizex = buf_x; /* Set the output buffer size in X. (width) */ - ctx.rb.sizey = buf_y; /* Set the output buffer size in Y. (height) */ - for(i = 0; i < num_base_verts; i++) { /* Loop over all base_verts. */ - ply[i].x = (int)((base_verts[i][0] * buf_x_f) + 0.5f); /* Range expand normalized X to integer buffer-space X. */ - ply[i].y = (int)((base_verts[i][1] * buf_y_f) + 0.5f); /* Range expand normalized Y to integer buffer-space Y. */ - } - i = rast_scan_init(mlayer_data, &ctx, ply, num_base_verts); /* Call our rasterizer, passing in the integer coords for each vert. */ - free(ply); /* Free the memory allocated for the integer coordinate table. */ - return(i); /* Return the value returned by the rasterizer. */ -} - diff --git a/intern/smoke/CMakeLists.txt b/intern/smoke/CMakeLists.txt index 9524f7b2935..3b8a4c06e69 100644 --- a/intern/smoke/CMakeLists.txt +++ b/intern/smoke/CMakeLists.txt @@ -26,10 +26,10 @@ set(INC intern ../memutil - ../../extern/bullet2/src ) set(INC_SYS + ../../extern/bullet2/src ${PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIRS} ) @@ -40,6 +40,7 @@ set(SRC intern/FLUID_3D_SOLVERS.cpp intern/FLUID_3D_STATIC.cpp intern/LU_HELPER.cpp + intern/spectrum.cpp intern/SPHERE.cpp intern/WTURBULENCE.cpp intern/smoke_API.cpp @@ -53,6 +54,7 @@ set(SRC intern/LU_HELPER.h intern/MERSENNETWISTER.h intern/OBSTACLE.h + intern/spectrum.h intern/SPHERE.h intern/VEC3.h intern/WAVELET_NOISE.h diff --git a/intern/smoke/extern/smoke_API.h b/intern/smoke/extern/smoke_API.h index a0eb1bf38e0..98c63f08fbd 100644 --- a/intern/smoke/extern/smoke_API.h +++ b/intern/smoke/extern/smoke_API.h @@ -37,17 +37,23 @@ extern "C" { struct FLUID_3D; -// export -void smoke_export(struct FLUID_3D *fluid, float *dt, float *dx, float **dens, float **densold, float **heat, float **heatold, float **vx, float **vy, float **vz, float **vxold, float **vyold, float **vzold, unsigned char **obstacles); - // low res -struct FLUID_3D *smoke_init(int *res, float *p0, float dtdef); +struct FLUID_3D *smoke_init(int *res, float dx, float dtdef, int use_heat, int use_fire, int use_colors); void smoke_free(struct FLUID_3D *fluid); -void smoke_initBlenderRNA(struct FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli); -void smoke_step(struct FLUID_3D *fluid, float dtSubdiv); +void smoke_initBlenderRNA(struct FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli, float *burning_rate, + float *flame_smoke, float *flame_smoke_color, float *flame_vorticity, float *flame_ignition_temp, float *flame_max_temp); +void smoke_step(struct FLUID_3D *fluid, float gravity[3], float dtSubdiv); float *smoke_get_density(struct FLUID_3D *fluid); +float *smoke_get_flame(struct FLUID_3D *fluid); +float *smoke_get_fuel(struct FLUID_3D *fluid); +float *smoke_get_react(struct FLUID_3D *fluid); +float *smoke_get_color_r(struct FLUID_3D *fluid); +float *smoke_get_color_g(struct FLUID_3D *fluid); +float *smoke_get_color_b(struct FLUID_3D *fluid); +void smoke_get_rgba(struct FLUID_3D *fluid, float *data, int sequential); +void smoke_get_rgba_from_density(struct FLUID_3D *fluid, float color[3], float *data, int sequential); float *smoke_get_heat(struct FLUID_3D *fluid); float *smoke_get_velocity_x(struct FLUID_3D *fluid); float *smoke_get_velocity_y(struct FLUID_3D *fluid); @@ -68,19 +74,44 @@ size_t smoke_get_index2d(int x, int max_x, int y); void smoke_dissolve(struct FLUID_3D *fluid, int speed, int log); // wavelet turbulence functions -struct WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype); +struct WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype, int use_fire, int use_colors); void smoke_turbulence_free(struct WTURBULENCE *wt); void smoke_turbulence_step(struct WTURBULENCE *wt, struct FLUID_3D *fluid); float *smoke_turbulence_get_density(struct WTURBULENCE *wt); +float *smoke_turbulence_get_color_r(struct WTURBULENCE *wt); +float *smoke_turbulence_get_color_g(struct WTURBULENCE *wt); +float *smoke_turbulence_get_color_b(struct WTURBULENCE *wt); +void smoke_turbulence_get_rgba(struct WTURBULENCE *wt, float *data, int sequential); +void smoke_turbulence_get_rgba_from_density(struct WTURBULENCE *wt, float color[3], float *data, int sequential); +float *smoke_turbulence_get_flame(struct WTURBULENCE *wt); +float *smoke_turbulence_get_fuel(struct WTURBULENCE *wt); +float *smoke_turbulence_get_react(struct WTURBULENCE *wt); void smoke_turbulence_get_res(struct WTURBULENCE *wt, int *res); +int smoke_turbulence_get_cells(struct WTURBULENCE *wt); void smoke_turbulence_set_noise(struct WTURBULENCE *wt, int type); void smoke_initWaveletBlenderRNA(struct WTURBULENCE *wt, float *strength); - void smoke_dissolve_wavelet(struct WTURBULENCE *wt, int speed, int log); -// export -void smoke_turbulence_export(struct WTURBULENCE *wt, float **dens, float **densold, float **tcu, float **tcv, float **tcw); +/* export */ +void smoke_export(struct FLUID_3D *fluid, float *dt, float *dx, float **dens, float **react, float **flame, float **fuel, float **heat, float **heatold, + float **vx, float **vy, float **vz, float **r, float **g, float **b, unsigned char **obstacles); +void smoke_turbulence_export(struct WTURBULENCE *wt, float **dens, float **react, float **flame, float **fuel, + float **r, float **g, float **b, float **tcu, float **tcv, float **tcw); + +/* flame spectrum */ +void flame_get_spectrum(unsigned char *spec, int width, float t1, float t2); + +/* data fields */ +int smoke_has_heat(struct FLUID_3D *fluid); +int smoke_has_fuel(struct FLUID_3D *fluid); +int smoke_has_colors(struct FLUID_3D *fluid); +int smoke_turbulence_has_fuel(struct WTURBULENCE *wt); +int smoke_turbulence_has_colors(struct WTURBULENCE *wt); + +void smoke_ensure_heat(struct FLUID_3D *fluid); +void smoke_ensure_fire(struct FLUID_3D *fluid, struct WTURBULENCE *wt); +void smoke_ensure_colors(struct FLUID_3D *fluid, struct WTURBULENCE *wt, float init_r, float init_g, float init_b); #ifdef __cplusplus } diff --git a/intern/smoke/intern/FLUID_3D.cpp b/intern/smoke/intern/FLUID_3D.cpp index e006132ea8f..4eb11a46f5b 100644 --- a/intern/smoke/intern/FLUID_3D.cpp +++ b/intern/smoke/intern/FLUID_3D.cpp @@ -44,16 +44,11 @@ // Construction/Destruction ////////////////////////////////////////////////////////////////////// -FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) : +FLUID_3D::FLUID_3D(int *res, float dx, float dtdef, int init_heat, int init_fire, int init_colors) : _xRes(res[0]), _yRes(res[1]), _zRes(res[2]), _res(0.0f) { // set simulation consts _dt = dtdef; // just in case. set in step from a RNA factor - - // start point of array - _p0[0] = p0[0]; - _p0[1] = p0[1]; - _p0[2] = p0[2]; _iterations = 100; _tempAmb = 0; @@ -72,7 +67,10 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) : */ // scale the constants according to the refinement of the grid - _dx = 1.0f / (float)_maxRes; + if (!dx) + _dx = 1.0f / (float)_maxRes; + else + _dx = dx; _constantScaling = 64.0f / _maxRes; _constantScaling = (_constantScaling < 1.0f) ? 1.0f : _constantScaling; _vorticityEps = 2.0f / _constantScaling; // Just in case set a default value @@ -94,8 +92,6 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) : _zForce = new float[_totalCells]; _density = new float[_totalCells]; _densityOld = new float[_totalCells]; - _heat = new float[_totalCells]; - _heatOld = new float[_totalCells]; _obstacles = new unsigned char[_totalCells]; // set 0 at end of step // For threaded version: @@ -103,7 +99,6 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) : _yVelocityTemp = new float[_totalCells]; _zVelocityTemp = new float[_totalCells]; _densityTemp = new float[_totalCells]; - _heatTemp = new float[_totalCells]; // DG TODO: check if alloc went fine @@ -111,8 +106,6 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) : { _density[x] = 0.0f; _densityOld[x] = 0.0f; - _heat[x] = 0.0f; - _heatOld[x] = 0.0f; _xVelocity[x] = 0.0f; _yVelocity[x] = 0.0f; _zVelocity[x] = 0.0f; @@ -128,6 +121,25 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) : _obstacles[x] = false; } + /* heat */ + _heat = _heatOld = _heatTemp = NULL; + if (init_heat) { + initHeat(); + } + // Fire simulation + _flame = _fuel = _fuelTemp = _fuelOld = NULL; + _react = _reactTemp = _reactOld = NULL; + if (init_fire) { + initFire(); + } + // Smoke color + _color_r = _color_rOld = _color_rTemp = NULL; + _color_g = _color_gOld = _color_gTemp = NULL; + _color_b = _color_bOld = _color_bTemp = NULL; + if (init_colors) { + initColors(0.0f, 0.0f, 0.0f); + } + // boundary conditions of the fluid domain // set default values -> vertically non-colliding _domainBcFront = true; @@ -138,9 +150,70 @@ FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) : _domainBcRight = _domainBcLeft; _colloPrev = 1; // default value +} - setBorderObstacles(); // walls +void FLUID_3D::initHeat() +{ + if (!_heat) { + _heat = new float[_totalCells]; + _heatOld = new float[_totalCells]; + _heatTemp = new float[_totalCells]; + for (int x = 0; x < _totalCells; x++) + { + _heat[x] = 0.0f; + _heatOld[x] = 0.0f; + } + } +} + +void FLUID_3D::initFire() +{ + if (!_flame) { + _flame = new float[_totalCells]; + _fuel = new float[_totalCells]; + _fuelTemp = new float[_totalCells]; + _fuelOld = new float[_totalCells]; + _react = new float[_totalCells]; + _reactTemp = new float[_totalCells]; + _reactOld = new float[_totalCells]; + + for (int x = 0; x < _totalCells; x++) + { + _flame[x] = 0.0f; + _fuel[x] = 0.0f; + _fuelTemp[x] = 0.0f; + _fuelOld[x] = 0.0f; + _react[x] = 0.0f; + _reactTemp[x] = 0.0f; + _reactOld[x] = 0.0f; + } + } +} + +void FLUID_3D::initColors(float init_r, float init_g, float init_b) +{ + if (!_color_r) { + _color_r = new float[_totalCells]; + _color_rOld = new float[_totalCells]; + _color_rTemp = new float[_totalCells]; + _color_g = new float[_totalCells]; + _color_gOld = new float[_totalCells]; + _color_gTemp = new float[_totalCells]; + _color_b = new float[_totalCells]; + _color_bOld = new float[_totalCells]; + _color_bTemp = new float[_totalCells]; + + for (int x = 0; x < _totalCells; x++) + { + _color_r[x] = _density[x] * init_r; + _color_rOld[x] = 0.0f; + _color_g[x] = _density[x] * init_g; + _color_gOld[x] = 0.0f; + _color_b[x] = _density[x] * init_b; + _color_bOld[x] = 0.0f; + } + } } void FLUID_3D::setBorderObstacles() @@ -204,7 +277,6 @@ FLUID_3D::~FLUID_3D() if (_heat) delete[] _heat; if (_heatOld) delete[] _heatOld; if (_obstacles) delete[] _obstacles; - // if (_wTurbulence) delete _wTurbulence; if (_xVelocityTemp) delete[] _xVelocityTemp; if (_yVelocityTemp) delete[] _yVelocityTemp; @@ -212,23 +284,48 @@ FLUID_3D::~FLUID_3D() if (_densityTemp) delete[] _densityTemp; if (_heatTemp) delete[] _heatTemp; + if (_flame) delete[] _flame; + if (_fuel) delete[] _fuel; + if (_fuelTemp) delete[] _fuelTemp; + if (_fuelOld) delete[] _fuelOld; + if (_react) delete[] _react; + if (_reactTemp) delete[] _reactTemp; + if (_reactOld) delete[] _reactOld; + + if (_color_r) delete[] _color_r; + if (_color_rOld) delete[] _color_rOld; + if (_color_rTemp) delete[] _color_rTemp; + if (_color_g) delete[] _color_g; + if (_color_gOld) delete[] _color_gOld; + if (_color_gTemp) delete[] _color_gTemp; + if (_color_b) delete[] _color_b; + if (_color_bOld) delete[] _color_bOld; + if (_color_bTemp) delete[] _color_bTemp; + // printf("deleted fluid\n"); } // init direct access functions from blender -void FLUID_3D::initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *borderCollision) +void FLUID_3D::initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *borderCollision, float *burning_rate, + float *flame_smoke, float *flame_smoke_color, float *flame_vorticity, float *flame_ignition_temp, float *flame_max_temp) { _alpha = alpha; _beta = beta; _dtFactor = dt_factor; _vorticityRNA = vorticity; _borderColli = borderCollision; + _burning_rate = burning_rate; + _flame_smoke = flame_smoke; + _flame_smoke_color = flame_smoke_color; + _flame_vorticity = flame_vorticity; + _ignition_temp = flame_ignition_temp; + _max_temp = flame_max_temp; } ////////////////////////////////////////////////////////////////////// // step simulation once ////////////////////////////////////////////////////////////////////// -void FLUID_3D::step(float dt) +void FLUID_3D::step(float dt, float gravity[3]) { #if 0 // If border rules have been changed @@ -281,7 +378,7 @@ void FLUID_3D::step(float dt) wipeBoundariesSL(zBegin, zEnd); addVorticity(zBegin, zEnd); - addBuoyancy(_heat, _density, zBegin, zEnd); + addBuoyancy(_heat, _density, gravity, zBegin, zEnd); addForce(zBegin, zEnd); #if PARALLEL==1 @@ -312,13 +409,15 @@ void FLUID_3D::step(float dt) if (i==0) { #endif - project(); + project(); #if PARALLEL==1 } - else + else if (i==1) { #endif - diffuseHeat(); + if (_heat) { + diffuseHeat(); + } #if PARALLEL==1 } } @@ -338,6 +437,13 @@ void FLUID_3D::step(float dt) SWAP_POINTERS(_density, _densityOld); SWAP_POINTERS(_heat, _heatOld); + SWAP_POINTERS(_fuel, _fuelOld); + SWAP_POINTERS(_react, _reactOld); + + SWAP_POINTERS(_color_r, _color_rOld); + SWAP_POINTERS(_color_g, _color_gOld); + SWAP_POINTERS(_color_b, _color_bOld); + advectMacCormackBegin(0, _zRes); #if PARALLEL==1 @@ -398,11 +504,8 @@ void FLUID_3D::step(float dt) SWAP_POINTERS(_yVelocity, _yForce); SWAP_POINTERS(_zVelocity, _zForce); - - - _totalTime += _dt; - _totalSteps++; + _totalSteps++; for (int i = 0; i < _totalCells; i++) { @@ -643,6 +746,15 @@ void FLUID_3D::wipeBoundaries(int zBegin, int zEnd) setZeroBorder(_yVelocity, _res, zBegin, zEnd); setZeroBorder(_zVelocity, _res, zBegin, zEnd); setZeroBorder(_density, _res, zBegin, zEnd); + if (_fuel) { + setZeroBorder(_fuel, _res, zBegin, zEnd); + setZeroBorder(_react, _res, zBegin, zEnd); + } + if (_color_r) { + setZeroBorder(_color_r, _res, zBegin, zEnd); + setZeroBorder(_color_g, _res, zBegin, zEnd); + setZeroBorder(_color_b, _res, zBegin, zEnd); + } } void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd) @@ -668,6 +780,15 @@ void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd) _yVelocity[index] = 0.0f; _zVelocity[index] = 0.0f; _density[index] = 0.0f; + if (_fuel) { + _fuel[index] = 0.0f; + _react[index] = 0.0f; + } + if (_color_r) { + _color_r[index] = 0.0f; + _color_g[index] = 0.0f; + _color_b[index] = 0.0f; + } // right slab index += _xRes - 1; @@ -675,6 +796,15 @@ void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd) _yVelocity[index] = 0.0f; _zVelocity[index] = 0.0f; _density[index] = 0.0f; + if (_fuel) { + _fuel[index] = 0.0f; + _react[index] = 0.0f; + } + if (_color_r) { + _color_r[index] = 0.0f; + _color_g[index] = 0.0f; + _color_b[index] = 0.0f; + } } ///////////////////////////////////// @@ -690,6 +820,15 @@ void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd) _yVelocity[index] = 0.0f; _zVelocity[index] = 0.0f; _density[index] = 0.0f; + if (_fuel) { + _fuel[index] = 0.0f; + _react[index] = 0.0f; + } + if (_color_r) { + _color_r[index] = 0.0f; + _color_g[index] = 0.0f; + _color_b[index] = 0.0f; + } // top slab index += slabSize - _xRes; @@ -697,6 +836,15 @@ void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd) _yVelocity[index] = 0.0f; _zVelocity[index] = 0.0f; _density[index] = 0.0f; + if (_fuel) { + _fuel[index] = 0.0f; + _react[index] = 0.0f; + } + if (_color_r) { + _color_r[index] = 0.0f; + _color_g[index] = 0.0f; + _color_b[index] = 0.0f; + } } @@ -717,6 +865,15 @@ void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd) _yVelocity[index] = 0.0f; _zVelocity[index] = 0.0f; _density[index] = 0.0f; + if (_fuel) { + _fuel[index] = 0.0f; + _react[index] = 0.0f; + } + if (_color_r) { + _color_r[index] = 0.0f; + _color_g[index] = 0.0f; + _color_b[index] = 0.0f; + } } if (zEnd == _zRes) @@ -735,6 +892,15 @@ void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd) _yVelocity[indexx] = 0.0f; _zVelocity[indexx] = 0.0f; _density[indexx] = 0.0f; + if (_fuel) { + _fuel[index] = 0.0f; + _react[index] = 0.0f; + } + if (_color_r) { + _color_r[index] = 0.0f; + _color_g[index] = 0.0f; + _color_b[index] = 0.0f; + } } } @@ -781,35 +947,6 @@ void FLUID_3D::project() if(!_domainBcTop) setNeumannZ(_zVelocity, _res, 0, _zRes); else setZeroZ(_zVelocity, _res, 0, _zRes); - /* - { - float maxx = 0, maxy = 0, maxz = 0; - for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++) - { - if(_xVelocity[i] > maxx) - maxx = _xVelocity[i]; - if(_yVelocity[i] > maxy) - maxy = _yVelocity[i]; - if(_zVelocity[i] > maxz) - maxz = _zVelocity[i]; - } - printf("Max velx: %f, vely: %f, velz: %f\n", maxx, maxy, maxz); - } - */ - - /* - { - float maxvalue = 0; - for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++) - { - if(_heat[i] > maxvalue) - maxvalue = _heat[i]; - - } - printf("Max heat: %f\n", maxvalue); - } - */ - // calculate divergence index = _slabSize + _xRes + 1; for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes) @@ -910,21 +1047,52 @@ void FLUID_3D::project() setObstaclePressure(_pressure, 0, _zRes); // project out solution + // New idea for code from NVIDIA graphic gems 3 - DG float invDx = 1.0f / _dx; index = _slabSize + _xRes + 1; for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes) for (y = 1; y < _yRes - 1; y++, index += 2) for (x = 1; x < _xRes - 1; x++, index++) { + float vMask[3] = {1.0f, 1.0f, 1.0f}, vObst[3] = {0, 0, 0}; + float vR = 0.0f, vL = 0.0f, vT = 0.0f, vB = 0.0f, vD = 0.0f, vU = 0.0f; + + float pC = _pressure[index]; // center + float pR = _pressure[index + 1]; // right + float pL = _pressure[index - 1]; // left + float pU = _pressure[index + _xRes]; // Up + float pD = _pressure[index - _xRes]; // Down + float pT = _pressure[index + _slabSize]; // top + float pB = _pressure[index - _slabSize]; // bottom + if(!_obstacles[index]) { - _xVelocity[index] -= 0.5f * (_pressure[index + 1] - _pressure[index - 1]) * invDx; - _yVelocity[index] -= 0.5f * (_pressure[index + _xRes] - _pressure[index - _xRes]) * invDx; - _zVelocity[index] -= 0.5f * (_pressure[index + _slabSize] - _pressure[index - _slabSize]) * invDx; + // DG TODO: What if obstacle is left + right and one of them is moving? + if(_obstacles[index+1]) { pR = pC; vObst[0] = _xVelocityOb[index + 1]; vMask[0] = 0; } + if(_obstacles[index-1]) { pL = pC; vObst[0] = _xVelocityOb[index - 1]; vMask[0] = 0; } + if(_obstacles[index+_xRes]) { pU = pC; vObst[1] = _yVelocityOb[index + _xRes]; vMask[1] = 0; } + if(_obstacles[index-_xRes]) { pD = pC; vObst[1] = _yVelocityOb[index - _xRes]; vMask[1] = 0; } + if(_obstacles[index+_slabSize]) { pT = pC; vObst[2] = _zVelocityOb[index + _slabSize]; vMask[2] = 0; } + if(_obstacles[index-_slabSize]) { pB = pC; vObst[2] = _zVelocityOb[index - _slabSize]; vMask[2] = 0; } + + _xVelocity[index] -= 0.5f * (pR - pL) * invDx; + _yVelocity[index] -= 0.5f * (pU - pD) * invDx; + _zVelocity[index] -= 0.5f * (pT - pB) * invDx; + + _xVelocity[index] = (vMask[0] * _xVelocity[index]) + vObst[0]; + _yVelocity[index] = (vMask[1] * _yVelocity[index]) + vObst[1]; + _zVelocity[index] = (vMask[2] * _zVelocity[index]) + vObst[2]; + } + else + { + _xVelocity[index] = _xVelocityOb[index]; + _yVelocity[index] = _yVelocityOb[index]; + _zVelocity[index] = _zVelocityOb[index]; } } - setObstacleVelocity(0, _zRes); + // DG: was enabled in original code but now we do this later + // setObstacleVelocity(0, _zRes); if (_pressure) delete[] _pressure; if (_divergence) delete[] _divergence; @@ -1007,7 +1175,6 @@ void FLUID_3D::diffuseHeat() for (int x = 0; x < _totalCells; x++) if (_obstacles[x]) _heat[x] = 0.0f; - } ////////////////////////////////////////////////////////////////////// @@ -1175,7 +1342,7 @@ void FLUID_3D::setObstacleBoundaries(float *_pressure, int zBegin, int zEnd) ////////////////////////////////////////////////////////////////////// // add buoyancy forces ////////////////////////////////////////////////////////////////////// -void FLUID_3D::addBuoyancy(float *heat, float *density, int zBegin, int zEnd) +void FLUID_3D::addBuoyancy(float *heat, float *density, float gravity[3], int zBegin, int zEnd) { int index = zBegin*_slabSize; @@ -1183,17 +1350,26 @@ void FLUID_3D::addBuoyancy(float *heat, float *density, int zBegin, int zEnd) for (int y = 0; y < _yRes; y++) for (int x = 0; x < _xRes; x++, index++) { - _zForce[index] += *_alpha * density[index] + (*_beta * (heat[index] - _tempAmb)); // DG: was _yForce, changed for Blender + float buoyancy = *_alpha * density[index] + (*_beta * (((heat) ? heat[index] : 0.0f) - _tempAmb)); + _xForce[index] -= gravity[0] * buoyancy; + _yForce[index] -= gravity[1] * buoyancy; + _zForce[index] -= gravity[2] * buoyancy; } } + ////////////////////////////////////////////////////////////////////// // add vorticity to the force field ////////////////////////////////////////////////////////////////////// +#define VORT_VEL(i, j) \ + ((_obstacles[obpos[(i)]] & 8) ? ((abs(objvelocity[(j)][obpos[(i)]]) > FLT_EPSILON) ? objvelocity[(j)][obpos[(i)]] : velocity[(j)][index]) : velocity[(j)][obpos[(i)]]) + void FLUID_3D::addVorticity(int zBegin, int zEnd) { + // set flame vorticity from RNA value + float flame_vorticity = (*_flame_vorticity)/_constantScaling; //int x,y,z,index; - if(_vorticityEps<=0.) return; + if(_vorticityEps+flame_vorticity<=0.) return; int _blockSize=zEnd-zBegin; int _blockTotalCells = _slabSize * (_blockSize+2); @@ -1225,9 +1401,18 @@ void FLUID_3D::addVorticity(int zBegin, int zEnd) float gridSize = 0.5f / _dx; //index = _slabSize + _xRes + 1; + float *velocity[3]; + float *objvelocity[3]; + + velocity[0] = _xVelocity; + velocity[1] = _yVelocity; + velocity[2] = _zVelocity; + + objvelocity[0] = _xVelocityOb; + objvelocity[1] = _yVelocityOb; + objvelocity[2] = _zVelocityOb; size_t vIndex=_xRes + 1; - for (int z = zBegin + bb1; z < (zEnd - bt1); z++) { size_t index = index_ +(z-1)*_slabSize; @@ -1237,25 +1422,47 @@ void FLUID_3D::addVorticity(int zBegin, int zEnd) { for (int x = 1; x < _xRes - 1; x++, index++) { + if (!_obstacles[index]) + { + int obpos[6]; - int up = _obstacles[index + _xRes] ? index : index + _xRes; - int down = _obstacles[index - _xRes] ? index : index - _xRes; - float dy = (up == index || down == index) ? 1.0f / _dx : gridSize; - int out = _obstacles[index + _slabSize] ? index : index + _slabSize; - int in = _obstacles[index - _slabSize] ? index : index - _slabSize; - float dz = (out == index || in == index) ? 1.0f / _dx : gridSize; - int right = _obstacles[index + 1] ? index : index + 1; - int left = _obstacles[index - 1] ? index : index - 1; - float dx = (right == index || left == index) ? 1.0f / _dx : gridSize; + obpos[0] = (_obstacles[index + _xRes] == 1) ? index : index + _xRes; // up + obpos[1] = (_obstacles[index - _xRes] == 1) ? index : index - _xRes; // down + float dy = (obpos[0] == index || obpos[1] == index) ? 1.0f / _dx : gridSize; - _xVorticity[vIndex] = (_zVelocity[up] - _zVelocity[down]) * dy + (-_yVelocity[out] + _yVelocity[in]) * dz; - _yVorticity[vIndex] = (_xVelocity[out] - _xVelocity[in]) * dz + (-_zVelocity[right] + _zVelocity[left]) * dx; - _zVorticity[vIndex] = (_yVelocity[right] - _yVelocity[left]) * dx + (-_xVelocity[up] + _xVelocity[down])* dy; + obpos[2] = (_obstacles[index + _slabSize] == 1) ? index : index + _slabSize; // out + obpos[3] = (_obstacles[index - _slabSize] == 1) ? index : index - _slabSize; // in + float dz = (obpos[2] == index || obpos[3] == index) ? 1.0f / _dx : gridSize; - _vorticity[vIndex] = sqrtf(_xVorticity[vIndex] * _xVorticity[vIndex] + + obpos[4] = (_obstacles[index + 1] == 1) ? index : index + 1; // right + obpos[5] = (_obstacles[index - 1] == 1) ? index : index - 1; // left + float dx = (obpos[4] == index || obpos[5] == index) ? 1.0f / _dx : gridSize; + + float xV[2], yV[2], zV[2]; + + zV[1] = VORT_VEL(0, 2); + zV[0] = VORT_VEL(1, 2); + yV[1] = VORT_VEL(2, 1); + yV[0] = VORT_VEL(3, 1); + _xVorticity[vIndex] = (zV[1] - zV[0]) * dy + (-yV[1] + yV[0]) * dz; + + xV[1] = VORT_VEL(2, 0); + xV[0] = VORT_VEL(3, 0); + zV[1] = VORT_VEL(4, 2); + zV[0] = VORT_VEL(5, 2); + _yVorticity[vIndex] = (xV[1] - xV[0]) * dz + (-zV[1] + zV[0]) * dx; + + yV[1] = VORT_VEL(4, 1); + yV[0] = VORT_VEL(5, 1); + xV[1] = VORT_VEL(0, 0); + xV[0] = VORT_VEL(1, 0); + _zVorticity[vIndex] = (yV[1] - yV[0]) * dx + (-xV[1] + xV[0])* dy; + + _vorticity[vIndex] = sqrtf(_xVorticity[vIndex] * _xVorticity[vIndex] + _yVorticity[vIndex] * _yVorticity[vIndex] + _zVorticity[vIndex] * _zVorticity[vIndex]); + } vIndex++; } vIndex+=2; @@ -1284,15 +1491,18 @@ void FLUID_3D::addVorticity(int zBegin, int zEnd) { float N[3]; - int up = _obstacles[index + _xRes] ? vIndex : vIndex + _xRes; - int down = _obstacles[index - _xRes] ? vIndex : vIndex - _xRes; + int up = (_obstacles[index + _xRes] == 1) ? vIndex : vIndex + _xRes; + int down = (_obstacles[index - _xRes] == 1) ? vIndex : vIndex - _xRes; float dy = (up == vIndex || down == vIndex) ? 1.0f / _dx : gridSize; - int out = _obstacles[index + _slabSize] ? vIndex : vIndex + _slabSize; - int in = _obstacles[index - _slabSize] ? vIndex : vIndex - _slabSize; + + int out = (_obstacles[index + _slabSize] == 1) ? vIndex : vIndex + _slabSize; + int in = (_obstacles[index - _slabSize] == 1) ? vIndex : vIndex - _slabSize; float dz = (out == vIndex || in == vIndex) ? 1.0f / _dx : gridSize; - int right = _obstacles[index + 1] ? vIndex : vIndex + 1; - int left = _obstacles[index - 1] ? vIndex : vIndex - 1; + + int right = (_obstacles[index + 1] == 1) ? vIndex : vIndex + 1; + int left = (_obstacles[index - 1] == 1) ? vIndex : vIndex - 1; float dx = (right == vIndex || left == vIndex) ? 1.0f / _dx : gridSize; + N[0] = (_vorticity[right] - _vorticity[left]) * dx; N[1] = (_vorticity[up] - _vorticity[down]) * dy; N[2] = (_vorticity[out] - _vorticity[in]) * dz; @@ -1300,14 +1510,15 @@ void FLUID_3D::addVorticity(int zBegin, int zEnd) float magnitude = sqrtf(N[0] * N[0] + N[1] * N[1] + N[2] * N[2]); if (magnitude > FLT_EPSILON) { + float flame_vort = (_fuel) ? _fuel[index]*flame_vorticity : 0.0f; magnitude = 1.0f / magnitude; N[0] *= magnitude; N[1] *= magnitude; N[2] *= magnitude; - _xForce[index] += (N[1] * _zVorticity[vIndex] - N[2] * _yVorticity[vIndex]) * _dx * eps; - _yForce[index] += (N[2] * _xVorticity[vIndex] - N[0] * _zVorticity[vIndex]) * _dx * eps; - _zForce[index] += (N[0] * _yVorticity[vIndex] - N[1] * _xVorticity[vIndex]) * _dx * eps; + _xForce[index] += (N[1] * _zVorticity[vIndex] - N[2] * _yVorticity[vIndex]) * _dx * (eps + flame_vort); + _yForce[index] += (N[2] * _xVorticity[vIndex] - N[0] * _zVorticity[vIndex]) * _dx * (eps + flame_vort); + _zForce[index] += (N[0] * _yVorticity[vIndex] - N[1] * _xVorticity[vIndex]) * _dx * (eps + flame_vort); } } // if vIndex++; @@ -1328,14 +1539,9 @@ void FLUID_3D::advectMacCormackBegin(int zBegin, int zEnd) { Vec3Int res = Vec3Int(_xRes,_yRes,_zRes); - if(!_domainBcLeft) copyBorderX(_xVelocityOld, res, zBegin, zEnd); - else setZeroX(_xVelocityOld, res, zBegin, zEnd); - - if(!_domainBcFront) copyBorderY(_yVelocityOld, res, zBegin, zEnd); - else setZeroY(_yVelocityOld, res, zBegin, zEnd); - - if(!_domainBcTop) copyBorderZ(_zVelocityOld, res, zBegin, zEnd); - else setZeroZ(_zVelocityOld, res, zBegin, zEnd); + setZeroX(_xVelocityOld, res, zBegin, zEnd); + setZeroY(_yVelocityOld, res, zBegin, zEnd); + setZeroZ(_zVelocityOld, res, zBegin, zEnd); } ////////////////////////////////////////////////////////////////////// @@ -1355,7 +1561,18 @@ void FLUID_3D::advectMacCormackEnd1(int zBegin, int zEnd) // advectFieldMacCormack1(dt, xVelocity, yVelocity, zVelocity, oldField, newField, res) advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _densityTemp, res, zBegin, zEnd); - advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heatTemp, res, zBegin, zEnd); + if (_heat) { + advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heatTemp, res, zBegin, zEnd); + } + if (_fuel) { + advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _fuelOld, _fuelTemp, res, zBegin, zEnd); + advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _reactOld, _reactTemp, res, zBegin, zEnd); + } + if (_color_r) { + advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_rOld, _color_rTemp, res, zBegin, zEnd); + advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_gOld, _color_gTemp, res, zBegin, zEnd); + advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_bOld, _color_bTemp, res, zBegin, zEnd); + } advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocity, res, zBegin, zEnd); advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocity, res, zBegin, zEnd); advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocity, res, zBegin, zEnd); @@ -1371,17 +1588,30 @@ void FLUID_3D::advectMacCormackEnd2(int zBegin, int zEnd) const float dt0 = _dt / _dx; Vec3Int res = Vec3Int(_xRes,_yRes,_zRes); - // use force array as temp arrays + // use force array as temp array float* t1 = _xForce; // advectFieldMacCormack2(dt, xVelocity, yVelocity, zVelocity, oldField, newField, tempfield, temp, res, obstacles) + /* finish advection */ advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _density, _densityTemp, t1, res, _obstacles, zBegin, zEnd); - advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heat, _heatTemp, t1, res, _obstacles, zBegin, zEnd); + if (_heat) { + advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heat, _heatTemp, t1, res, _obstacles, zBegin, zEnd); + } + if (_fuel) { + advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _fuelOld, _fuel, _fuelTemp, t1, res, _obstacles, zBegin, zEnd); + advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _reactOld, _react, _reactTemp, t1, res, _obstacles, zBegin, zEnd); + } + if (_color_r) { + advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_rOld, _color_r, _color_rTemp, t1, res, _obstacles, zBegin, zEnd); + advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_gOld, _color_g, _color_gTemp, t1, res, _obstacles, zBegin, zEnd); + advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _color_bOld, _color_b, _color_bTemp, t1, res, _obstacles, zBegin, zEnd); + } advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocityTemp, _xVelocity, t1, res, _obstacles, zBegin, zEnd); advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocityTemp, _yVelocity, t1, res, _obstacles, zBegin, zEnd); advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocityTemp, _zVelocity, t1, res, _obstacles, zBegin, zEnd); + /* set boundary conditions for velocity */ if(!_domainBcLeft) copyBorderX(_xVelocityTemp, res, zBegin, zEnd); else setZeroX(_xVelocityTemp, res, zBegin, zEnd); @@ -1391,40 +1621,71 @@ void FLUID_3D::advectMacCormackEnd2(int zBegin, int zEnd) if(!_domainBcTop) copyBorderZ(_zVelocityTemp, res, zBegin, zEnd); else setZeroZ(_zVelocityTemp, res, zBegin, zEnd); + /* clear data boundaries */ setZeroBorder(_density, res, zBegin, zEnd); - setZeroBorder(_heat, res, zBegin, zEnd); -#if 0 - { - const size_t index_ = _slabSize + _xRes + 1; - int bb=0; - int bt=0; + if (_fuel) { + setZeroBorder(_fuel, res, zBegin, zEnd); + setZeroBorder(_react, res, zBegin, zEnd); + } + if (_color_r) { + setZeroBorder(_color_r, res, zBegin, zEnd); + setZeroBorder(_color_g, res, zBegin, zEnd); + setZeroBorder(_color_b, res, zBegin, zEnd); + } +} - if (zBegin == 0) {bb = 1;} - if (zEnd == _zRes) {bt = 1;} - - for (int z = zBegin + bb; z < zEnd - bt; z++) - { - size_t index = index_ +(z-1)*_slabSize; - for (int y = 1; y < _yRes - 1; y++, index += 2) - { - for (int x = 1; x < _xRes - 1; x++, index++) - { - // clean custom velocities from moving obstacles again - if (_obstacles[index]) - { - _xVelocity[index] = - _yVelocity[index] = - _zVelocity[index] = 0.0f; - } - } +void FLUID_3D::processBurn(float *fuel, float *smoke, float *react, float *flame, float *heat, + float *r, float *g, float *b, int total_cells, float dt) +{ + float burning_rate = *_burning_rate; + float flame_smoke = *_flame_smoke; + float ignition_point = *_ignition_temp; + float temp_max = *_max_temp; + + for (int index = 0; index < total_cells; index++) + { + float orig_fuel = fuel[index]; + float orig_smoke = smoke[index]; + float smoke_emit = 0.0f; + float react_coord = 0.0f; + + /* process fuel */ + fuel[index] -= burning_rate * dt; + if (fuel[index] < 0.0f) fuel[index] = 0.0f; + /* process reaction coordinate */ + if (orig_fuel) { + react[index] *= fuel[index]/orig_fuel; + react_coord = react[index]; + } + else { + react[index] = 0.0f; + } + + /* emit smoke based on fuel burn rate and "flame_smoke" factor */ + smoke_emit = (orig_fuel < 1.0f) ? (1.0f - orig_fuel)*0.5f : 0.0f; + smoke_emit = (smoke_emit + 0.5f) * (orig_fuel-fuel[index]) * 0.1f * flame_smoke; + smoke[index] += smoke_emit; + CLAMP(smoke[index], 0.0f, 1.0f); + + /* model flame temperature curve from the reaction coordinate (fuel) */ + if (react_coord>0.0f) { + /* do a smooth falloff for rest of the values */ + flame[index] = pow(react_coord, 0.5f); + } + else + flame[index] = 0.0f; + + /* set fluid temperature from the flame temperature profile */ + if (heat && flame[index]) + heat[index] = (1.0f-flame[index])*ignition_point + flame[index]*temp_max; + + /* mix new color */ + if (r && smoke_emit) { + float smoke_factor = smoke[index]/(orig_smoke+smoke_emit); + r[index] = (r[index] + _flame_smoke_color[0] * smoke_emit) * smoke_factor; + g[index] = (g[index] + _flame_smoke_color[1] * smoke_emit) * smoke_factor; + b[index] = (b[index] + _flame_smoke_color[2] * smoke_emit) * smoke_factor; } } - } -#endif - - /*int begin=zBegin * _slabSize; - int end=begin + (zEnd - zBegin) * _slabSize; - for (int x = begin; x < end; x++) - _xForce[x] = _yForce[x] = 0.0f;*/ } diff --git a/intern/smoke/intern/FLUID_3D.h b/intern/smoke/intern/FLUID_3D.h index ac77148ce84..8cadf3bc989 100644 --- a/intern/smoke/intern/FLUID_3D.h +++ b/intern/smoke/intern/FLUID_3D.h @@ -46,11 +46,16 @@ class WTURBULENCE; class FLUID_3D { public: - FLUID_3D(int *res, /* int amplify, */ float *p0, float dtdef); + FLUID_3D(int *res, float dx, float dtdef, int init_heat, int init_fire, int init_colors); FLUID_3D() {}; virtual ~FLUID_3D(); - void initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli); + void initHeat(); + void initFire(); + void initColors(float init_r, float init_g, float init_b); + + void initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli, float *burning_rate, + float *flame_smoke, float *flame_smoke_color, float *flame_vorticity, float *ignition_temp, float *max_temp); // create & allocate vector noise advection void initVectorNoise(int amplify); @@ -58,7 +63,7 @@ class FLUID_3D void addSmokeColumn(); static void addSmokeTestCase(float* field, Vec3Int res); - void step(float dt); + void step(float dt, float gravity[3]); void addObstacle(OBSTACLE* obstacle); const float* xVelocity() { return _xVelocity; }; @@ -115,6 +120,27 @@ class FLUID_3D float* _heatTemp; float* _densityTemp; + // fire simulation + float *_flame; + float *_fuel; + float *_fuelTemp; + float *_fuelOld; + float *_react; + float *_reactTemp; + float *_reactOld; + + // smoke color + float *_color_r; + float *_color_rOld; + float *_color_rTemp; + float *_color_g; + float *_color_gOld; + float *_color_gTemp; + float *_color_b; + float *_color_bOld; + float *_color_bTemp; + + // CG fields int _iterations; @@ -153,14 +179,16 @@ class FLUID_3D void wipeBoundariesSL(int zBegin, int zEnd); void addForce(int zBegin, int zEnd); void addVorticity(int zBegin, int zEnd); - void addBuoyancy(float *heat, float *density, int zBegin, int zEnd); + void addBuoyancy(float *heat, float *density, float gravity[3], int zBegin, int zEnd); // solver stuff void project(); void diffuseHeat(); + void diffuseColor(); void solvePressure(float* field, float* b, unsigned char* skip); void solvePressurePre(float* field, float* b, unsigned char* skip); void solveHeat(float* field, float* b, unsigned char* skip); + void solveDiffusion(float* field, float* b, float* factor); // handle obstacle boundaries @@ -174,6 +202,16 @@ class FLUID_3D void advectMacCormackEnd1(int zBegin, int zEnd); void advectMacCormackEnd2(int zBegin, int zEnd); + /* burning */ + float *_burning_rate; // RNA pointer + float *_flame_smoke; // RNA pointer + float *_flame_smoke_color; // RNA pointer + float *_flame_vorticity; // RNA pointer + float *_ignition_temp; // RNA pointer + float *_max_temp; // RNA pointer + void processBurn(float *fuel, float *smoke, float *react, float *flame, float *heat, + float *r, float *g, float *b, int total_cells, float dt); + // boundary setting functions static void copyBorderX(float* field, Vec3Int res, int zBegin, int zEnd); static void copyBorderY(float* field, Vec3Int res, int zBegin, int zEnd); diff --git a/intern/smoke/intern/FLUID_3D_SOLVERS.cpp b/intern/smoke/intern/FLUID_3D_SOLVERS.cpp index 3cf94eb00a9..42a8b2d6923 100644 --- a/intern/smoke/intern/FLUID_3D_SOLVERS.cpp +++ b/intern/smoke/intern/FLUID_3D_SOLVERS.cpp @@ -165,7 +165,6 @@ void FLUID_3D::solveHeat(float* field, float* b, unsigned char* skip) if (_Acenter) delete[] _Acenter; } - void FLUID_3D::solvePressurePre(float* field, float* b, unsigned char* skip) { int x, y, z; diff --git a/intern/smoke/intern/FLUID_3D_STATIC.cpp b/intern/smoke/intern/FLUID_3D_STATIC.cpp index c7a0ddcd04c..ac485ad983a 100644 --- a/intern/smoke/intern/FLUID_3D_STATIC.cpp +++ b/intern/smoke/intern/FLUID_3D_STATIC.cpp @@ -92,18 +92,10 @@ void FLUID_3D::setNeumannX(float* field, Vec3Int res, int zBegin, int zEnd) // left slab index = y * res[0] + z * slabSize; field[index] = field[index + 2]; - /* only allow outwards flux */ - if(field[index]>0.) field[index] = 0.; - index += 1; - if(field[index]>0.) field[index] = 0.; // right slab index = y * res[0] + z * slabSize + res[0] - 1; field[index] = field[index - 2]; - /* only allow outwards flux */ - if(field[index]<0.) field[index] = 0.; - index -= 1; - if(field[index]<0.) field[index] = 0.; } } @@ -120,18 +112,10 @@ void FLUID_3D::setNeumannY(float* field, Vec3Int res, int zBegin, int zEnd) // front slab index = x + z * slabSize; field[index] = field[index + 2 * res[0]]; - /* only allow outwards flux */ - if(field[index]>0.) field[index] = 0.; - index += res[0]; - if(field[index]>0.) field[index] = 0.; // back slab index = x + z * slabSize + slabSize - res[0]; field[index] = field[index - 2 * res[0]]; - /* only allow outwards flux */ - if(field[index]<0.) field[index] = 0.; - index -= res[0]; - if(field[index]<0.) field[index] = 0.; } } @@ -152,14 +136,6 @@ void FLUID_3D::setNeumannZ(float* field, Vec3Int res, int zBegin, int zEnd) // front slab index = x + y * res[0]; field[index] = field[index + 2 * slabSize]; - /* only allow outwards flux */ - - // DG: Disable this for z-axis. - // The problem is that smoke somehow gets sucked in again - // from the TOP slab when this is enabled - // if(field[index]>0.) field[index] = 0.; - // index += slabSize; - // if(field[index]>0.) field[index] = 0.; } } @@ -170,10 +146,6 @@ void FLUID_3D::setNeumannZ(float* field, Vec3Int res, int zBegin, int zEnd) // back slab index = x + y * res[0] + cellsslab; field[index] = field[index - 2 * slabSize]; - /* only allow outwards flux */ - if(field[index]<0.) field[index] = 0.; - index -= slabSize; - if(field[index]<0.) field[index] = 0.; } } diff --git a/intern/smoke/intern/WTURBULENCE.cpp b/intern/smoke/intern/WTURBULENCE.cpp index 671198065e8..1c89f5d681b 100644 --- a/intern/smoke/intern/WTURBULENCE.cpp +++ b/intern/smoke/intern/WTURBULENCE.cpp @@ -51,7 +51,7 @@ static const float persistence = 0.56123f; ////////////////////////////////////////////////////////////////////// // constructor ////////////////////////////////////////////////////////////////////// -WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype) +WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype, int init_fire, int init_colors) { // if noise magnitude is below this threshold, its contribution // is negilgible, so stop evaluating new octaves @@ -87,12 +87,26 @@ WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int no // allocate high resolution density field _totalStepsBig = 0; _densityBig = new float[_totalCellsBig]; - _densityBigOld = new float[_totalCellsBig]; + _densityBigOld = new float[_totalCellsBig]; for(int i = 0; i < _totalCellsBig; i++) { _densityBig[i] = _densityBigOld[i] = 0.; } + + /* fire */ + _flameBig = _fuelBig = _fuelBigOld = NULL; + _reactBig = _reactBigOld = NULL; + if (init_fire) { + initFire(); + } + /* colors */ + _color_rBig = _color_rBigOld = NULL; + _color_gBig = _color_gBigOld = NULL; + _color_bBig = _color_bBigOld = NULL; + if (init_colors) { + initColors(0.0f, 0.0f, 0.0f); + } // allocate & init texture coordinates _tcU = new float[_totalCellsSm]; @@ -128,12 +142,64 @@ WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int no */ } +void WTURBULENCE::initFire() +{ + if (!_fuelBig) { + _flameBig = new float[_totalCellsBig]; + _fuelBig = new float[_totalCellsBig]; + _fuelBigOld = new float[_totalCellsBig]; + _reactBig = new float[_totalCellsBig]; + _reactBigOld = new float[_totalCellsBig]; + + for(int i = 0; i < _totalCellsBig; i++) { + _flameBig[i] = + _fuelBig[i] = + _fuelBigOld[i] = 0.; + _reactBig[i] = + _reactBigOld[i] = 0.; + } + } +} + +void WTURBULENCE::initColors(float init_r, float init_g, float init_b) +{ + if (!_color_rBig) { + _color_rBig = new float[_totalCellsBig]; + _color_rBigOld = new float[_totalCellsBig]; + _color_gBig = new float[_totalCellsBig]; + _color_gBigOld = new float[_totalCellsBig]; + _color_bBig = new float[_totalCellsBig]; + _color_bBigOld = new float[_totalCellsBig]; + + for(int i = 0; i < _totalCellsBig; i++) { + _color_rBig[i] = _densityBig[i] * init_r; + _color_rBigOld[i] = 0.0f; + _color_gBig[i] = _densityBig[i] * init_g; + _color_gBigOld[i] = 0.0f; + _color_bBig[i] = _densityBig[i] * init_b; + _color_bBigOld[i] = 0.0f; + } + } +} + ////////////////////////////////////////////////////////////////////// // destructor ////////////////////////////////////////////////////////////////////// WTURBULENCE::~WTURBULENCE() { delete[] _densityBig; delete[] _densityBigOld; + if (_flameBig) delete[] _flameBig; + if (_fuelBig) delete[] _fuelBig; + if (_fuelBigOld) delete[] _fuelBigOld; + if (_reactBig) delete[] _reactBig; + if (_reactBigOld) delete[] _reactBigOld; + + if (_color_rBig) delete[] _color_rBig; + if (_color_rBigOld) delete[] _color_rBigOld; + if (_color_gBig) delete[] _color_gBig; + if (_color_gBigOld) delete[] _color_gBigOld; + if (_color_bBig) delete[] _color_bBig; + if (_color_bBigOld) delete[] _color_bBigOld; delete[] _tcU; delete[] _tcV; @@ -757,8 +823,10 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa // enlarge timestep to match grid const float dt = dtOrg * _amplify; const float invAmp = 1.0f / _amplify; - float *tempBig1 = (float *)calloc(_totalCellsBig, sizeof(float)); - float *tempBig2 = (float *)calloc(_totalCellsBig, sizeof(float)); + float *tempFuelBig = NULL, *tempReactBig = NULL; + float *tempColor_rBig = NULL, *tempColor_gBig = NULL, *tempColor_bBig = NULL; + float *tempDensityBig = (float *)calloc(_totalCellsBig, sizeof(float)); + float *tempBig = (float *)calloc(_totalCellsBig, sizeof(float)); float *bigUx = (float *)calloc(_totalCellsBig, sizeof(float)); float *bigUy = (float *)calloc(_totalCellsBig, sizeof(float)); float *bigUz = (float *)calloc(_totalCellsBig, sizeof(float)); @@ -767,11 +835,21 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa float *eigMin = (float *)calloc(_totalCellsSm, sizeof(float)); float *eigMax = (float *)calloc(_totalCellsSm, sizeof(float)); + if (_fuelBig) { + tempFuelBig = (float *)calloc(_totalCellsBig, sizeof(float)); + tempReactBig = (float *)calloc(_totalCellsBig, sizeof(float)); + } + if (_color_rBig) { + tempColor_rBig = (float *)calloc(_totalCellsBig, sizeof(float)); + tempColor_gBig = (float *)calloc(_totalCellsBig, sizeof(float)); + tempColor_bBig = (float *)calloc(_totalCellsBig, sizeof(float)); + } + memset(_tcTemp, 0, sizeof(float)*_totalCellsSm); // prepare textures - advectTextureCoordinates(dtOrg, xvel,yvel,zvel, tempBig1, tempBig2); + advectTextureCoordinates(dtOrg, xvel,yvel,zvel, tempDensityBig, tempBig); // do wavelet decomposition of energy computeEnergy(_energy, xvel, yvel, zvel, obstacles); @@ -972,6 +1050,11 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa // prepare density for an advection SWAP_POINTERS(_densityBig, _densityBigOld); + SWAP_POINTERS(_fuelBig, _fuelBigOld); + SWAP_POINTERS(_reactBig, _reactBigOld); + SWAP_POINTERS(_color_rBig, _color_rBigOld); + SWAP_POINTERS(_color_gBig, _color_gBigOld); + SWAP_POINTERS(_color_bBig, _color_bBigOld); // based on the maximum velocity present, see if we need to substep, // but cap the maximum number of substeps to 5 @@ -1017,7 +1100,21 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa int zEnd = (int)((float)(i+1)*partSize + 0.5f); #endif FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz, - _densityBigOld, tempBig1, _resBig, zBegin, zEnd); + _densityBigOld, tempDensityBig, _resBig, zBegin, zEnd); + if (_fuelBig) { + FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz, + _fuelBigOld, tempFuelBig, _resBig, zBegin, zEnd); + FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz, + _reactBigOld, tempReactBig, _resBig, zBegin, zEnd); + } + if (_color_rBig) { + FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz, + _color_rBigOld, tempColor_rBig, _resBig, zBegin, zEnd); + FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz, + _color_gBigOld, tempColor_gBig, _resBig, zBegin, zEnd); + FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz, + _color_bBigOld, tempColor_bBig, _resBig, zBegin, zEnd); + } #if PARALLEL==1 } @@ -1030,18 +1127,43 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa int zEnd = (int)((float)(i+1)*partSize + 0.5f); #endif FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz, - _densityBigOld, _densityBig, tempBig1, tempBig2, _resBig, NULL, zBegin, zEnd); + _densityBigOld, _densityBig, tempDensityBig, tempBig, _resBig, NULL, zBegin, zEnd); + if (_fuelBig) { + FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz, + _fuelBigOld, _fuelBig, tempFuelBig, tempBig, _resBig, NULL, zBegin, zEnd); + FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz, + _reactBigOld, _reactBig, tempReactBig, tempBig, _resBig, NULL, zBegin, zEnd); + } + if (_color_rBig) { + FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz, + _color_rBigOld, _color_rBig, tempColor_rBig, tempBig, _resBig, NULL, zBegin, zEnd); + FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz, + _color_gBigOld, _color_gBig, tempColor_gBig, tempBig, _resBig, NULL, zBegin, zEnd); + FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz, + _color_bBigOld, _color_bBig, tempColor_bBig, tempBig, _resBig, NULL, zBegin, zEnd); + } #if PARALLEL==1 } } #endif - if (substep < totalSubsteps - 1) + if (substep < totalSubsteps - 1) { SWAP_POINTERS(_densityBig, _densityBigOld); + SWAP_POINTERS(_fuelBig, _fuelBigOld); + SWAP_POINTERS(_reactBig, _reactBigOld); + SWAP_POINTERS(_color_rBig, _color_rBigOld); + SWAP_POINTERS(_color_gBig, _color_gBigOld); + SWAP_POINTERS(_color_bBig, _color_bBigOld); + } } // substep - free(tempBig1); - free(tempBig2); + free(tempDensityBig); + if (tempFuelBig) free(tempFuelBig); + if (tempReactBig) free(tempReactBig); + if (tempColor_rBig) free(tempColor_rBig); + if (tempColor_gBig) free(tempColor_gBig); + if (tempColor_bBig) free(tempColor_bBig); + free(tempBig); free(bigUx); free(bigUy); free(bigUz); @@ -1050,6 +1172,15 @@ void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, floa // wipe the density borders FLUID_3D::setZeroBorder(_densityBig, _resBig, 0 , _resBig[2]); + if (_fuelBig) { + FLUID_3D::setZeroBorder(_fuelBig, _resBig, 0 , _resBig[2]); + FLUID_3D::setZeroBorder(_reactBig, _resBig, 0 , _resBig[2]); + } + if (_color_rBig) { + FLUID_3D::setZeroBorder(_color_rBig, _resBig, 0 , _resBig[2]); + FLUID_3D::setZeroBorder(_color_gBig, _resBig, 0 , _resBig[2]); + FLUID_3D::setZeroBorder(_color_bBig, _resBig, 0 , _resBig[2]); + } // reset texture coordinates now in preparation for next timestep // Shouldn't do this before generating the noise because then the diff --git a/intern/smoke/intern/WTURBULENCE.h b/intern/smoke/intern/WTURBULENCE.h index f31ca100fdf..1655bd95d32 100644 --- a/intern/smoke/intern/WTURBULENCE.h +++ b/intern/smoke/intern/WTURBULENCE.h @@ -36,10 +36,13 @@ class WTURBULENCE { public: // both config files can be NULL, altCfg might override values from noiseCfg - WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype); + WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype, int init_fire, int init_colors); /// destructor virtual ~WTURBULENCE(); + + void initFire(); + void initColors(float init_r, float init_g, float init_b); void setNoise(int type); void initBlenderRNA(float *strength); @@ -63,6 +66,8 @@ class WTURBULENCE // access functions inline float* getDensityBig() { return _densityBig; } + inline float* getFlameBig() { return _flameBig; } + inline float* getFuelBig() { return _fuelBig; } inline float* getArrayTcU() { return _tcU; } inline float* getArrayTcV() { return _tcV; } inline float* getArrayTcW() { return _tcW; } @@ -111,6 +116,18 @@ class WTURBULENCE float* _densityBig; float* _densityBigOld; + float* _flameBig; + float* _fuelBig; + float* _fuelBigOld; + float* _reactBig; + float* _reactBigOld; + + float* _color_rBig; + float* _color_rBigOld; + float* _color_gBig; + float* _color_gBigOld; + float* _color_bBig; + float* _color_bBigOld; // texture coordinates for noise float* _tcU; diff --git a/intern/smoke/intern/smoke_API.cpp b/intern/smoke/intern/smoke_API.cpp index b45fef26504..6011de0bddb 100644 --- a/intern/smoke/intern/smoke_API.cpp +++ b/intern/smoke/intern/smoke_API.cpp @@ -28,30 +28,26 @@ * \ingroup smoke */ - #include "FLUID_3D.h" #include "WTURBULENCE.h" +#include "spectrum.h" #include #include #include -// y in smoke is z in blender -extern "C" FLUID_3D *smoke_init(int *res, float *p0, float dtdef) +#include "../extern/smoke_API.h" /* to ensure valid prototypes */ + +extern "C" FLUID_3D *smoke_init(int *res, float dx, float dtdef, int use_heat, int use_fire, int use_colors) { - // smoke lib uses y as top-bottom/vertical axis where blender uses z - FLUID_3D *fluid = new FLUID_3D(res, p0, dtdef); - - // printf("xres: %d, yres: %d, zres: %d\n", res[0], res[1], res[2]); - + FLUID_3D *fluid = new FLUID_3D(res, dx, dtdef, use_heat, use_fire, use_colors); return fluid; } -extern "C" WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype) +extern "C" WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype, int use_fire, int use_colors) { - // initialize wavelet turbulence - if(amplify) - return new WTURBULENCE(res[0],res[1],res[2], amplify, noisetype); + if (amplify) + return new WTURBULENCE(res[0],res[1],res[2], amplify, noisetype, use_fire, use_colors); else return NULL; } @@ -70,7 +66,6 @@ extern "C" void smoke_turbulence_free(WTURBULENCE *wt) extern "C" size_t smoke_get_index(int x, int max_x, int y, int max_y, int z /*, int max_z */) { - // // const int index = x + y * smd->res[0] + z * smd->res[0]*smd->res[1]; return x + y * max_x + z * max_x*max_y; } @@ -79,100 +74,28 @@ extern "C" size_t smoke_get_index2d(int x, int max_x, int y /*, int max_y, int z return x + y * max_x; } -extern "C" void smoke_step(FLUID_3D *fluid, float dtSubdiv) +extern "C" void smoke_step(FLUID_3D *fluid, float gravity[3], float dtSubdiv) { - fluid->step(dtSubdiv); + if (fluid->_fuel) { + fluid->processBurn(fluid->_fuel, fluid->_density, fluid->_react, fluid->_flame, fluid->_heat, + fluid->_color_r, fluid->_color_g, fluid->_color_b, fluid->_totalCells, (*fluid->_dtFactor)*dtSubdiv); + } + fluid->step(dtSubdiv, gravity); } extern "C" void smoke_turbulence_step(WTURBULENCE *wt, FLUID_3D *fluid) { + if (wt->_fuelBig) { + fluid->processBurn(wt->_fuelBig, wt->_densityBig, wt->_reactBig, wt->_flameBig, 0, + wt->_color_rBig, wt->_color_gBig, wt->_color_bBig, wt->_totalCellsBig, fluid->_dt); + } wt->stepTurbulenceFull(fluid->_dt/fluid->_dx, fluid->_xVelocity, fluid->_yVelocity, fluid->_zVelocity, fluid->_obstacles); } -extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli) +extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli, float *burning_rate, + float *flame_smoke, float *flame_smoke_color, float *flame_vorticity, float *flame_ignition_temp, float *flame_max_temp) { - fluid->initBlenderRNA(alpha, beta, dt_factor, vorticity, border_colli); -} - -extern "C" void smoke_dissolve(FLUID_3D *fluid, int speed, int log) -{ - float *density = fluid->_density; - //float *densityOld = fluid->_densityOld; - float *heat = fluid->_heat; - - if(log) - { - /* max density/speed = dydx */ - float dydx = 1.0 / (float)speed; - size_t size= fluid->_xRes * fluid->_yRes * fluid->_zRes; - - for(size_t i = 0; i < size; i++) - { - density[i] *= (1.0 - dydx); - - if(density[i] < 0.0f) - density[i] = 0.0f; - - heat[i] *= (1.0 - dydx); - - /*if(heat[i] < 0.0f) - heat[i] = 0.0f;*/ - } - } - else // linear falloff - { - /* max density/speed = dydx */ - float dydx = 1.0 / (float)speed; - size_t size= fluid->_xRes * fluid->_yRes * fluid->_zRes; - - for(size_t i = 0; i < size; i++) - { - density[i] -= dydx; - - if(density[i] < 0.0f) - density[i] = 0.0f; - - if(abs(heat[i]) < dydx) heat[i] = 0.0f; - else if (heat[i]>0.0f) heat[i] -= dydx; - else if (heat[i]<0.0f) heat[i] += dydx; - - } - } -} - -extern "C" void smoke_dissolve_wavelet(WTURBULENCE *wt, int speed, int log) -{ - float *density = wt->getDensityBig(); - Vec3Int r = wt->getResBig(); - - if(log) - { - /* max density/speed = dydx */ - float dydx = 1.0 / (float)speed; - size_t size= r[0] * r[1] * r[2]; - - for(size_t i = 0; i < size; i++) - { - density[i] *= (1.0 - dydx); - - if(density[i] < 0.0f) - density[i] = 0.0f; - } - } - else // linear falloff - { - /* max density/speed = dydx */ - float dydx = 1.0 / (float)speed; - size_t size= r[0] * r[1] * r[2]; - - for(size_t i = 0; i < size; i++) - { - density[i] -= dydx; - - if(density[i] < 0.0f) - density[i] = 0.0f; - } - } + fluid->initBlenderRNA(alpha, beta, dt_factor, vorticity, border_colli, burning_rate, flame_smoke, flame_smoke_color, flame_vorticity, flame_ignition_temp, flame_max_temp); } extern "C" void smoke_initWaveletBlenderRNA(WTURBULENCE *wt, float *strength) @@ -180,36 +103,104 @@ extern "C" void smoke_initWaveletBlenderRNA(WTURBULENCE *wt, float *strength) wt->initBlenderRNA(strength); } -template < class T > inline T ABS( T a ) +static void data_dissolve(float *density, float *heat, float *r, float *g, float *b, int total_cells, int speed, int log) { - return (0 < a) ? a : -a ; + if (log) { + /* max density/speed = dydx */ + float fac = 1.0f - (1.0f / (float)speed); + + for(size_t i = 0; i < total_cells; i++) + { + /* density */ + density[i] *= fac; + + /* heat */ + if (heat) { + heat[i] *= fac; + } + + /* color */ + if (r) { + r[i] *= fac; + g[i] *= fac; + b[i] *= fac; + } + } + } + else // linear falloff + { + /* max density/speed = dydx */ + float dydx = 1.0f / (float)speed; + + for(size_t i = 0; i < total_cells; i++) + { + float d = density[i]; + /* density */ + density[i] -= dydx; + if (density[i] < 0.0f) + density[i] = 0.0f; + + /* heat */ + if (heat) { + if (abs(heat[i]) < dydx) heat[i] = 0.0f; + else if (heat[i] > 0.0f) heat[i] -= dydx; + else if (heat[i] < 0.0f) heat[i] += dydx; + } + + /* color */ + if (r && d) { + r[i] *= (density[i]/d); + g[i] *= (density[i]/d); + b[i] *= (density[i]/d); + } + + } + } } -extern "C" void smoke_export(FLUID_3D *fluid, float *dt, float *dx, float **dens, float **densold, float **heat, float **heatold, float **vx, float **vy, float **vz, float **vxold, float **vyold, float **vzold, unsigned char **obstacles) +extern "C" void smoke_dissolve(FLUID_3D *fluid, int speed, int log) +{ + data_dissolve(fluid->_density, fluid->_heat, fluid->_color_r, fluid->_color_g, fluid->_color_b, fluid->_totalCells, speed, log); +} + +extern "C" void smoke_dissolve_wavelet(WTURBULENCE *wt, int speed, int log) +{ + data_dissolve(wt->_densityBig, 0, wt->_color_rBig, wt->_color_gBig, wt->_color_bBig, wt->_totalCellsBig, speed, log); +} + +extern "C" void smoke_export(FLUID_3D *fluid, float *dt, float *dx, float **dens, float **react, float **flame, float **fuel, float **heat, + float **heatold, float **vx, float **vy, float **vz, float **r, float **g, float **b, unsigned char **obstacles) { *dens = fluid->_density; - *densold = fluid->_densityOld; + *fuel = fluid->_fuel; + *react = fluid->_react; + *flame = fluid->_flame; *heat = fluid->_heat; *heatold = fluid->_heatOld; *vx = fluid->_xVelocity; *vy = fluid->_yVelocity; *vz = fluid->_zVelocity; - *vxold = fluid->_xVelocityOld; - *vyold = fluid->_yVelocityOld; - *vzold = fluid->_zVelocityOld; + *r = fluid->_color_r; + *g = fluid->_color_g; + *b = fluid->_color_b; *obstacles = fluid->_obstacles; *dt = fluid->_dt; *dx = fluid->_dx; - } -extern "C" void smoke_turbulence_export(WTURBULENCE *wt, float **dens, float **densold, float **tcu, float **tcv, float **tcw) +extern "C" void smoke_turbulence_export(WTURBULENCE *wt, float **dens, float **react, float **flame, float **fuel, + float **r, float **g, float **b , float **tcu, float **tcv, float **tcw) { - if(!wt) + if (!wt) return; *dens = wt->_densityBig; - *densold = wt->_densityBigOld; + *fuel = wt->_fuelBig; + *react = wt->_reactBig; + *flame = wt->_flameBig; + *r = wt->_color_rBig; + *g = wt->_color_gBig; + *b = wt->_color_bBig; *tcu = wt->_tcU; *tcv = wt->_tcV; *tcw = wt->_tcW; @@ -220,6 +211,16 @@ extern "C" float *smoke_get_density(FLUID_3D *fluid) return fluid->_density; } +extern "C" float *smoke_get_fuel(FLUID_3D *fluid) +{ + return fluid->_fuel; +} + +extern "C" float *smoke_get_react(FLUID_3D *fluid) +{ + return fluid->_react; +} + extern "C" float *smoke_get_heat(FLUID_3D *fluid) { return fluid->_heat; @@ -255,15 +256,137 @@ extern "C" float *smoke_get_force_z(FLUID_3D *fluid) return fluid->_zForce; } +extern "C" float *smoke_get_flame(FLUID_3D *fluid) +{ + return fluid->_flame; +} + +extern "C" float *smoke_get_color_r(FLUID_3D *fluid) +{ + return fluid->_color_r; +} + +extern "C" float *smoke_get_color_g(FLUID_3D *fluid) +{ + return fluid->_color_g; +} + +extern "C" float *smoke_get_color_b(FLUID_3D *fluid) +{ + return fluid->_color_b; +} + +static void get_rgba(float *r, float *g, float *b, float *a, int total_cells, float *data, int sequential) +{ + int i; + int m = 4, i_g = 1, i_b = 2, i_a = 3; + /* sequential data */ + if (sequential) { + m = 1; + i_g *= total_cells; + i_b *= total_cells; + i_a *= total_cells; + } + + for (i=0; i_color_r, fluid->_color_g, fluid->_color_b, fluid->_density, fluid->_totalCells, data, sequential); +} + +extern "C" void smoke_turbulence_get_rgba(WTURBULENCE *wt, float *data, int sequential) +{ + get_rgba(wt->_color_rBig, wt->_color_gBig, wt->_color_bBig, wt->_densityBig, wt->_totalCellsBig, data, sequential); +} + +/* get a single color premultiplied voxel grid */ +static void get_rgba_from_density(float color[3], float *a, int total_cells, float *data, int sequential) +{ + int i; + int m = 4, i_g = 1, i_b = 2, i_a = 3; + /* sequential data */ + if (sequential) { + m = 1; + i_g *= total_cells; + i_b *= total_cells; + i_a *= total_cells; + } + + for (i=0; i_density, fluid->_totalCells, data, sequential); +} + +extern "C" void smoke_turbulence_get_rgba_from_density(WTURBULENCE *wt, float color[3], float *data, int sequential) +{ + get_rgba_from_density(color, wt->_densityBig, wt->_totalCellsBig, data, sequential); +} + extern "C" float *smoke_turbulence_get_density(WTURBULENCE *wt) { return wt ? wt->getDensityBig() : NULL; } +extern "C" float *smoke_turbulence_get_fuel(WTURBULENCE *wt) +{ + return wt ? wt->getFuelBig() : NULL; +} + +extern "C" float *smoke_turbulence_get_react(WTURBULENCE *wt) +{ + return wt ? wt->_reactBig : NULL; +} + +extern "C" float *smoke_turbulence_get_color_r(WTURBULENCE *wt) +{ + return wt ? wt->_color_rBig : NULL; +} + +extern "C" float *smoke_turbulence_get_color_g(WTURBULENCE *wt) +{ + return wt ? wt->_color_gBig : NULL; +} + +extern "C" float *smoke_turbulence_get_color_b(WTURBULENCE *wt) +{ + return wt ? wt->_color_bBig : NULL; +} + +extern "C" float *smoke_turbulence_get_flame(WTURBULENCE *wt) +{ + return wt ? wt->getFlameBig() : NULL; +} + extern "C" void smoke_turbulence_get_res(WTURBULENCE *wt, int *res) { - if(wt) - { + if (wt) { Vec3Int r = wt->getResBig(); res[0] = r[0]; res[1] = r[1]; @@ -271,6 +394,15 @@ extern "C" void smoke_turbulence_get_res(WTURBULENCE *wt, int *res) } } +extern "C" int smoke_turbulence_get_cells(WTURBULENCE *wt) +{ + if (wt) { + Vec3Int r = wt->getResBig(); + return r[0] * r[1] * r[2]; + } + return 0; +} + extern "C" unsigned char *smoke_get_obstacle(FLUID_3D *fluid) { return fluid->_obstacles; @@ -283,12 +415,72 @@ extern "C" void smoke_get_ob_velocity(FLUID_3D *fluid, float **x, float **y, flo *z = fluid->_zVelocityOb; } +#if 0 extern "C" unsigned char *smoke_get_obstacle_anim(FLUID_3D *fluid) { return fluid->_obstaclesAnim; } +#endif extern "C" void smoke_turbulence_set_noise(WTURBULENCE *wt, int type) { wt->setNoise(type); } + +extern "C" void flame_get_spectrum(unsigned char *spec, int width, float t1, float t2) +{ + spectrum(t1, t2, width, spec); +} + +extern "C" int smoke_has_heat(FLUID_3D *fluid) +{ + return (fluid->_heat) ? 1 : 0; +} + +extern "C" int smoke_has_fuel(FLUID_3D *fluid) +{ + return (fluid->_fuel) ? 1 : 0; +} + +extern "C" int smoke_has_colors(FLUID_3D *fluid) +{ + return (fluid->_color_r && fluid->_color_g && fluid->_color_b) ? 1 : 0; +} + +extern "C" int smoke_turbulence_has_fuel(WTURBULENCE *wt) +{ + return (wt->_fuelBig) ? 1 : 0; +} + +extern "C" int smoke_turbulence_has_colors(WTURBULENCE *wt) +{ + return (wt->_color_rBig && wt->_color_gBig && wt->_color_bBig) ? 1 : 0; +} + +/* additional field initialization */ +extern "C" void smoke_ensure_heat(FLUID_3D *fluid) +{ + if (fluid) { + fluid->initHeat(); + } +} + +extern "C" void smoke_ensure_fire(FLUID_3D *fluid, WTURBULENCE *wt) +{ + if (fluid) { + fluid->initFire(); + } + if (wt) { + wt->initFire(); + } +} + +extern "C" void smoke_ensure_colors(FLUID_3D *fluid, WTURBULENCE *wt, float init_r, float init_g, float init_b) +{ + if (fluid) { + fluid->initColors(init_r, init_g, init_b); + } + if (wt) { + wt->initColors(init_r, init_g, init_b); + } +} diff --git a/intern/smoke/intern/spectrum.cpp b/intern/smoke/intern/spectrum.cpp new file mode 100644 index 00000000000..30433451ac2 --- /dev/null +++ b/intern/smoke/intern/spectrum.cpp @@ -0,0 +1,426 @@ +/* + Colour Rendering of Spectra + + by John Walker + http://www.fourmilab.ch/ + + Last updated: March 9, 2003 + + This program is in the public domain. + + For complete information about the techniques employed in + this program, see the World-Wide Web document: + + http://www.fourmilab.ch/documents/specrend/ + + The xyz_to_rgb() function, which was wrong in the original + version of this program, was corrected by: + + Andrew J. S. Hamilton 21 May 1999 + Andrew.Hamilton@Colorado.EDU + http://casa.colorado.edu/~ajsh/ + + who also added the gamma correction facilities and + modified constrain_rgb() to work by desaturating the + colour by adding white. + + A program which uses these functions to plot CIE + "tongue" diagrams called "ppmcie" is included in + the Netpbm graphics toolkit: + http://netpbm.sourceforge.net/ + (The program was called cietoppm in earlier + versions of Netpbm.) + +*/ + +#include +#include +#include "spectrum.h" + +/* A colour system is defined by the CIE x and y coordinates of + its three primary illuminants and the x and y coordinates of + the white point. */ + +struct colourSystem { + const char *name; /* Colour system name */ + double xRed, yRed, /* Red x, y */ + xGreen, yGreen, /* Green x, y */ + xBlue, yBlue, /* Blue x, y */ + xWhite, yWhite, /* White point x, y */ + gamma; /* Gamma correction for system */ +}; + +/* White point chromaticities. */ + +#define IlluminantC 0.3101, 0.3162 /* For NTSC television */ +#define IlluminantD65 0.3127, 0.3291 /* For EBU and SMPTE */ +#define IlluminantE 0.33333333, 0.33333333 /* CIE equal-energy illuminant */ + +/* Gamma of nonlinear correction. + + See Charles Poynton's ColorFAQ Item 45 and GammaFAQ Item 6 at: + + http://www.poynton.com/ColorFAQ.html + http://www.poynton.com/GammaFAQ.html + +*/ + +#define GAMMA_REC709 0 /* Rec. 709 */ + +static struct colourSystem + /* Name xRed yRed xGreen yGreen xBlue yBlue White point Gamma */ +#if 0 /* UNUSED */ + NTSCsystem = { "NTSC", 0.67, 0.33, 0.21, 0.71, 0.14, 0.08, IlluminantC, GAMMA_REC709 }, + EBUsystem = { "EBU (PAL/SECAM)", 0.64, 0.33, 0.29, 0.60, 0.15, 0.06, IlluminantD65, GAMMA_REC709 }, + SMPTEsystem = { "SMPTE", 0.630, 0.340, 0.310, 0.595, 0.155, 0.070, IlluminantD65, GAMMA_REC709 }, + HDTVsystem = { "HDTV", 0.670, 0.330, 0.210, 0.710, 0.150, 0.060, IlluminantD65, GAMMA_REC709 }, +#endif + + CIEsystem = { "CIE", 0.7355, 0.2645, 0.2658, 0.7243, 0.1669, 0.0085, IlluminantE, GAMMA_REC709 }; + +#if 0 /* UNUSED */ + Rec709system = { "CIE REC 709", 0.64, 0.33, 0.30, 0.60, 0.15, 0.06, IlluminantD65, GAMMA_REC709 }; +#endif + +/* UPVP_TO_XY + + Given 1976 coordinates u', v', determine 1931 chromaticities x, y + +*/ + +#if 0 /* UNUSED */ +static void upvp_to_xy(double up, double vp, double *xc, double *yc) +{ + *xc = (9 * up) / ((6 * up) - (16 * vp) + 12); + *yc = (4 * vp) / ((6 * up) - (16 * vp) + 12); +} +#endif + +/* XY_TO_UPVP + + Given 1931 chromaticities x, y, determine 1976 coordinates u', v' + +*/ + +#if 0 /* UNUSED */ +static void xy_to_upvp(double xc, double yc, double *up, double *vp) +{ + *up = (4 * xc) / ((-2 * xc) + (12 * yc) + 3); + *vp = (9 * yc) / ((-2 * xc) + (12 * yc) + 3); +} +#endif + +/* XYZ_TO_RGB + + Given an additive tricolour system CS, defined by the CIE x + and y chromaticities of its three primaries (z is derived + trivially as 1-(x+y)), and a desired chromaticity (XC, YC, + ZC) in CIE space, determine the contribution of each + primary in a linear combination which sums to the desired + chromaticity. If the requested chromaticity falls outside + the Maxwell triangle (colour gamut) formed by the three + primaries, one of the r, g, or b weights will be negative. + + Caller can use constrain_rgb() to desaturate an + outside-gamut colour to the closest representation within + the available gamut and/or norm_rgb to normalise the RGB + components so the largest nonzero component has value 1. + +*/ + +static void xyz_to_rgb(struct colourSystem *cs, + double xc, double yc, double zc, + double *r, double *g, double *b) +{ + double xr, yr, zr, xg, yg, zg, xb, yb, zb; + double xw, yw, zw; + double rx, ry, rz, gx, gy, gz, bx, by, bz; + double rw, gw, bw; + + xr = cs->xRed; yr = cs->yRed; zr = 1 - (xr + yr); + xg = cs->xGreen; yg = cs->yGreen; zg = 1 - (xg + yg); + xb = cs->xBlue; yb = cs->yBlue; zb = 1 - (xb + yb); + + xw = cs->xWhite; yw = cs->yWhite; zw = 1 - (xw + yw); + + /* xyz -> rgb matrix, before scaling to white. */ + + rx = (yg * zb) - (yb * zg); ry = (xb * zg) - (xg * zb); rz = (xg * yb) - (xb * yg); + gx = (yb * zr) - (yr * zb); gy = (xr * zb) - (xb * zr); gz = (xb * yr) - (xr * yb); + bx = (yr * zg) - (yg * zr); by = (xg * zr) - (xr * zg); bz = (xr * yg) - (xg * yr); + + /* White scaling factors. + Dividing by yw scales the white luminance to unity, as conventional. */ + + rw = ((rx * xw) + (ry * yw) + (rz * zw)) / yw; + gw = ((gx * xw) + (gy * yw) + (gz * zw)) / yw; + bw = ((bx * xw) + (by * yw) + (bz * zw)) / yw; + + /* xyz -> rgb matrix, correctly scaled to white. */ + + rx = rx / rw; ry = ry / rw; rz = rz / rw; + gx = gx / gw; gy = gy / gw; gz = gz / gw; + bx = bx / bw; by = by / bw; bz = bz / bw; + + /* rgb of the desired point */ + + *r = (rx * xc) + (ry * yc) + (rz * zc); + *g = (gx * xc) + (gy * yc) + (gz * zc); + *b = (bx * xc) + (by * yc) + (bz * zc); +} + +/* INSIDE_GAMUT + + Test whether a requested colour is within the gamut + achievable with the primaries of the current colour + system. This amounts simply to testing whether all the + primary weights are non-negative. */ + +#if 0 /* UNUSED */ +static int inside_gamut(double r, double g, double b) +{ + return (r >= 0) && (g >= 0) && (b >= 0); +} +#endif + +/* CONSTRAIN_RGB + + If the requested RGB shade contains a negative weight for + one of the primaries, it lies outside the colour gamut + accessible from the given triple of primaries. Desaturate + it by adding white, equal quantities of R, G, and B, enough + to make RGB all positive. The function returns 1 if the + components were modified, zero otherwise. + +*/ + +static int constrain_rgb(double *r, double *g, double *b) +{ + double w; + + /* Amount of white needed is w = - min(0, *r, *g, *b) */ + + w = (0 < *r) ? 0 : *r; + w = (w < *g) ? w : *g; + w = (w < *b) ? w : *b; + w = -w; + + /* Add just enough white to make r, g, b all positive. */ + + if (w > 0) { + *r += w; *g += w; *b += w; + return 1; /* Colour modified to fit RGB gamut */ + } + + return 0; /* Colour within RGB gamut */ +} + +/* GAMMA_CORRECT_RGB + + Transform linear RGB values to nonlinear RGB values. Rec. + 709 is ITU-R Recommendation BT. 709 (1990) ``Basic + Parameter Values for the HDTV Standard for the Studio and + for International Programme Exchange'', formerly CCIR Rec. + 709. For details see + + http://www.poynton.com/ColorFAQ.html + http://www.poynton.com/GammaFAQ.html +*/ + +#if 0 /* UNUSED */ +static void gamma_correct(const struct colourSystem *cs, double *c) +{ + double gamma; + + gamma = cs->gamma; + + if (gamma == GAMMA_REC709) { + /* Rec. 709 gamma correction. */ + double cc = 0.018; + + if (*c < cc) { + *c *= ((1.099 * pow(cc, 0.45)) - 0.099) / cc; + } else { + *c = (1.099 * pow(*c, 0.45)) - 0.099; + } + } else { + /* Nonlinear colour = (Linear colour)^(1/gamma) */ + *c = pow(*c, 1.0 / gamma); + } +} + +static void gamma_correct_rgb(const struct colourSystem *cs, double *r, double *g, double *b) +{ + gamma_correct(cs, r); + gamma_correct(cs, g); + gamma_correct(cs, b); +} +#endif + +/* NORM_RGB + + Normalise RGB components so the most intense (unless all + are zero) has a value of 1. + +*/ + +static void norm_rgb(double *r, double *g, double *b) +{ +#define Max(a, b) (((a) > (b)) ? (a) : (b)) + double greatest = Max(*r, Max(*g, *b)); + + if (greatest > 0) { + *r /= greatest; + *g /= greatest; + *b /= greatest; + } +#undef Max +} + +/* SPECTRUM_TO_XYZ + + Calculate the CIE X, Y, and Z coordinates corresponding to + a light source with spectral distribution given by the + function SPEC_INTENS, which is called with a series of + wavelengths between 380 and 780 nm (the argument is + expressed in meters), which returns emittance at that + wavelength in arbitrary units. The chromaticity + coordinates of the spectrum are returned in the x, y, and z + arguments which respect the identity: + + x + y + z = 1. +*/ + +static void spectrum_to_xyz(double (*spec_intens)(double wavelength), + double *x, double *y, double *z) +{ + int i; + double lambda, X = 0, Y = 0, Z = 0, XYZ; + + /* CIE colour matching functions xBar, yBar, and zBar for + wavelengths from 380 through 780 nanometers, every 5 + nanometers. For a wavelength lambda in this range: + + cie_colour_match[(lambda - 380) / 5][0] = xBar + cie_colour_match[(lambda - 380) / 5][1] = yBar + cie_colour_match[(lambda - 380) / 5][2] = zBar + + To save memory, this table can be declared as floats + rather than doubles; (IEEE) float has enough + significant bits to represent the values. It's declared + as a double here to avoid warnings about "conversion + between floating-point types" from certain persnickety + compilers. */ + + static double cie_colour_match[81][3] = { + {0.0014,0.0000,0.0065}, {0.0022,0.0001,0.0105}, {0.0042,0.0001,0.0201}, + {0.0076,0.0002,0.0362}, {0.0143,0.0004,0.0679}, {0.0232,0.0006,0.1102}, + {0.0435,0.0012,0.2074}, {0.0776,0.0022,0.3713}, {0.1344,0.0040,0.6456}, + {0.2148,0.0073,1.0391}, {0.2839,0.0116,1.3856}, {0.3285,0.0168,1.6230}, + {0.3483,0.0230,1.7471}, {0.3481,0.0298,1.7826}, {0.3362,0.0380,1.7721}, + {0.3187,0.0480,1.7441}, {0.2908,0.0600,1.6692}, {0.2511,0.0739,1.5281}, + {0.1954,0.0910,1.2876}, {0.1421,0.1126,1.0419}, {0.0956,0.1390,0.8130}, + {0.0580,0.1693,0.6162}, {0.0320,0.2080,0.4652}, {0.0147,0.2586,0.3533}, + {0.0049,0.3230,0.2720}, {0.0024,0.4073,0.2123}, {0.0093,0.5030,0.1582}, + {0.0291,0.6082,0.1117}, {0.0633,0.7100,0.0782}, {0.1096,0.7932,0.0573}, + {0.1655,0.8620,0.0422}, {0.2257,0.9149,0.0298}, {0.2904,0.9540,0.0203}, + {0.3597,0.9803,0.0134}, {0.4334,0.9950,0.0087}, {0.5121,1.0000,0.0057}, + {0.5945,0.9950,0.0039}, {0.6784,0.9786,0.0027}, {0.7621,0.9520,0.0021}, + {0.8425,0.9154,0.0018}, {0.9163,0.8700,0.0017}, {0.9786,0.8163,0.0014}, + {1.0263,0.7570,0.0011}, {1.0567,0.6949,0.0010}, {1.0622,0.6310,0.0008}, + {1.0456,0.5668,0.0006}, {1.0026,0.5030,0.0003}, {0.9384,0.4412,0.0002}, + {0.8544,0.3810,0.0002}, {0.7514,0.3210,0.0001}, {0.6424,0.2650,0.0000}, + {0.5419,0.2170,0.0000}, {0.4479,0.1750,0.0000}, {0.3608,0.1382,0.0000}, + {0.2835,0.1070,0.0000}, {0.2187,0.0816,0.0000}, {0.1649,0.0610,0.0000}, + {0.1212,0.0446,0.0000}, {0.0874,0.0320,0.0000}, {0.0636,0.0232,0.0000}, + {0.0468,0.0170,0.0000}, {0.0329,0.0119,0.0000}, {0.0227,0.0082,0.0000}, + {0.0158,0.0057,0.0000}, {0.0114,0.0041,0.0000}, {0.0081,0.0029,0.0000}, + {0.0058,0.0021,0.0000}, {0.0041,0.0015,0.0000}, {0.0029,0.0010,0.0000}, + {0.0020,0.0007,0.0000}, {0.0014,0.0005,0.0000}, {0.0010,0.0004,0.0000}, + {0.0007,0.0002,0.0000}, {0.0005,0.0002,0.0000}, {0.0003,0.0001,0.0000}, + {0.0002,0.0001,0.0000}, {0.0002,0.0001,0.0000}, {0.0001,0.0000,0.0000}, + {0.0001,0.0000,0.0000}, {0.0001,0.0000,0.0000}, {0.0000,0.0000,0.0000} + }; + + for (i = 0, lambda = 380; lambda < 780.1; i++, lambda += 5) { + double Me; + + Me = (*spec_intens)(lambda); + X += Me * cie_colour_match[i][0]; + Y += Me * cie_colour_match[i][1]; + Z += Me * cie_colour_match[i][2]; + } + XYZ = (X + Y + Z); + *x = X / XYZ; + *y = Y / XYZ; + *z = Z / XYZ; +} + +/* BB_SPECTRUM + + Calculate, by Planck's radiation law, the emittance of a black body + of temperature bbTemp at the given wavelength (in metres). */ + +double bbTemp = 5000; /* Hidden temperature argument + to BB_SPECTRUM. */ +static double bb_spectrum(double wavelength) +{ + double wlm = wavelength * 1e-9; /* Wavelength in meters */ + + return (3.74183e-16 * pow(wlm, -5.0)) / + (exp(1.4388e-2 / (wlm * bbTemp)) - 1.0); +} + +static void xyz_to_lms(double x, double y, double z, double* l, double* m, double* s) +{ + *l = 0.3897*x + 0.6890*y - 0.0787*z; + *m = -0.2298*x + 1.1834*y + 0.0464*z; + *s = z; +} + +static void lms_to_xyz(double l, double m, double s, double* x, double *y, double* z) +{ + *x = 1.9102*l - 1.1121*m + 0.2019*s; + *y = 0.3709*l + 0.6290*m + 0.0000*s; + *z = s; +} + +void spectrum(double t1, double t2, int N, unsigned char *d) +{ + int i,j,dj; + double X,Y,Z,R,G,B,L,M,S, Lw, Mw, Sw; + struct colourSystem *cs = &CIEsystem; + + j = 0; dj = 1; + if (t10.1)? B*255 : 0; + j += dj; + } +} diff --git a/intern/smoke/intern/spectrum.h b/intern/smoke/intern/spectrum.h new file mode 100644 index 00000000000..3ffd41f9517 --- /dev/null +++ b/intern/smoke/intern/spectrum.h @@ -0,0 +1,6 @@ +#ifndef __SPECTRUM_H +#define __SPECTRUM_H + +void spectrum(double t1, double t2, int n, unsigned char *d); + +#endif diff --git a/intern/string/STR_String.h b/intern/string/STR_String.h index 6e9f6007e0b..a3d367a6fef 100644 --- a/intern/string/STR_String.h +++ b/intern/string/STR_String.h @@ -88,8 +88,16 @@ public: inline ~STR_String() { delete[] this->m_data; } // Operations - STR_String& Format(const char *fmt, ...); // Set formatted text to string - STR_String& FormatAdd(const char *fmt, ...); // Add formatted text to string + STR_String& Format(const char *fmt, ...) // Set formatted text to string +#ifdef __GNUC__ + __attribute__ ((format(printf, 2, 3))) +#endif + ; + STR_String& FormatAdd(const char *fmt, ...) // Add formatted text to string +#ifdef __GNUC__ + __attribute__ ((format(printf, 2, 3))) +#endif + ; inline void Clear() { this->m_len = this->m_data[0] = 0; } inline const STR_String & Reverse() { @@ -208,12 +216,10 @@ protected: #endif }; -inline STR_String operator+(rcSTR_String lhs, rcSTR_String rhs) { return STR_String(lhs.ReadPtr(), lhs.Length(), rhs.ReadPtr(), rhs.Length()); } -inline STR_String operator+(rcSTR_String lhs, char rhs) { return STR_String(lhs.ReadPtr(), lhs.Length(), &rhs, 1); } -inline STR_String operator+(char lhs, rcSTR_String rhs) { return STR_String(&lhs, 1, rhs.ReadPtr(), rhs.Length()); } -inline STR_String operator+(rcSTR_String lhs, const char *rhs) { return STR_String(lhs.ReadPtr(), lhs.Length(), rhs, strlen(rhs)); } -inline STR_String operator+(const char *lhs, rcSTR_String rhs) { return STR_String(lhs, strlen(lhs), rhs.ReadPtr(), rhs.Length()); } - +inline STR_String operator+(rcSTR_String lhs, rcSTR_String rhs) { return STR_String(lhs.ReadPtr(), lhs.Length(), rhs.ReadPtr(), rhs.Length()); } +inline STR_String operator+(rcSTR_String lhs, char rhs) { return STR_String(lhs.ReadPtr(), lhs.Length(), &rhs, 1); } +inline STR_String operator+(char lhs, rcSTR_String rhs) { return STR_String(&lhs, 1, rhs.ReadPtr(), rhs.Length()); } +inline STR_String operator+(rcSTR_String lhs, const char *rhs) { return STR_String(lhs.ReadPtr(), lhs.Length(), rhs, strlen(rhs)); } +inline STR_String operator+(const char *lhs, rcSTR_String rhs) { return STR_String(lhs, strlen(lhs), rhs.ReadPtr(), rhs.Length()); } #endif //__STR_STRING_H__ - diff --git a/intern/string/intern/STR_String.cpp b/intern/string/intern/STR_String.cpp index 4b2261e89f9..283b44380ee 100644 --- a/intern/string/intern/STR_String.cpp +++ b/intern/string/intern/STR_String.cpp @@ -738,4 +738,3 @@ int STR_String::Serialize(pCStream stream) return this->m_len + sizeof(this->m_len); } #endif - diff --git a/intern/utfconv/utfconv.h b/intern/utfconv/utfconv.h index 3bfd2772991..cf0e69170a2 100644 --- a/intern/utfconv/utfconv.h +++ b/intern/utfconv/utfconv.h @@ -95,7 +95,7 @@ wchar_t *alloc_utf16_from_8(const char *in8, size_t add); wchar_t *in8str ## _16 = alloc_utf16_from_8((char *)in8str, 0) #define UTF16_UN_ENCODE(in8str) \ - free(in8str ## _16); } (void)0 + free(in8str ## _16); } (void)0 #ifdef __cplusplus } diff --git a/release/datafiles/blender_icons.png b/release/datafiles/blender_icons.png index a0d460b0153b68d4fff7eaaa3bdcfd3a3f6b62e4..55a83964a8be84cb7435e49cc6bbcc7ff9907f8b 100644 GIT binary patch literal 228428 zcmZsC1yoc~+wRaQ-3?OG(%nc(iF8YMcXy*8AT1yz-Q6uM-6h=(Qg{3PvF=^#>I}mg z&Y3y0_Zv^V6RE5y{R)`~83KX4l9iEEg+QRS!94&G9y}xYJevoBAoE#DNGK~?*t^&} zTi82L$Vy01I5^pxS=yLFATk4)$?j@ub9mw7ZSGzf0MP?ZA2BM(;uGyf{8xdn@cr-MN z(h1rC7V6APvlZH5YJwv`5#c5Kht|GN;NCX~W_k@DArmHk1TT&JXO{Z$sBc6mOlAZ$ zX6^K1n8T5LMqgeDKQLA2eOo9NtdHp9E3EmjV0?mmUavqY-5XI6fx^+0!GyVnRrM~4 zEs1fHXLDW+jROXPBWr{2pczTUjrlf`9P1C&<~C$q2Fbv2S%Yca1f@5{NmhP*!xGfEd}{gZnM+w(0iVL z^flo{{=UOh{uC21?aCnPcZ@)fj7c&1(5Ls3XWxFuM&akV!H^j3{Bp|kWZsp(NfVrY z#y3VoA2Nn@!GV9 zKa{vK*uTR^DBw-do5b3cF>sLj#E~%2vBW(m%!&vYf`8_C6%qa=<44L2FBc7-(6c~I z3-b$K?Lt%tDz3yTg(L1k1@9LqvHsBkx)pvb6lI;%fo2&(9xAYYdB%0eEr=`nx3wJJ^``IHTzEnEuGx858OR45B!hdMlqedv~RS0n4q@)RRZB(*~lyOk% z;Oodf2K{_T`p)&cmkN){ry{LsX->kjh*{~S?`;#9d$2Be%@}%tcH#|rthx4ibQ2YC z2~c0<#a4BD7*oBK{Z{u4YeZOqc!$IcgCj1r$GGZ3)3=m#mVCGuxiWN~;Yj63>j=XQ z`T<_Lw|ITT;iQqC1U)6bq?5EOv+LCcts{!Zn^xLY_|tgvE$6fRyLUc3&-{MS9ipFU zEwGOeDMP5cX~k)Bk{rIA1)L?wQ2)d%iwu-xaeQ5s;1T1I%KOeoK7n%oi>}NhHKirO zKE^)DKFdB$s=_RlKtkRi^aYv|$365t=6x)zRJTmGd=PV$Snj)A31gYfCTe}v55Hxd z>P*T_LjNEQ9VT$7dc0wNga4*r+N+qTI8pVrs`GCg%MX_R`)d1G`>%g%{3tZ3WY=c5 zW4B3#P7P+qH|c+aD3!S>ZluEffe4(4t%mwB{Xpt{F5ZWZJTzrAO;g8Zk zIbX}w@?FF%-=!8D6=nR;E%$lnsU4bYT+#jUjRs%I#a9-2_uRq>#{IS{t&dV4l|JTJ zwH*W;1f|t$7iqU^r!Pvl2JuS>>9^^&N&BixNcAYaR?3sw%A(az%trYd6MGTMADcyNO(0Ep%6`J}Y+-DaVEo&{ zX-%zvdWmzbcInEULx>|;D|Ug|xw@(49{!T$5`XwA#WDHVz-=JNc*DGECU;;nI6sMI zt$N03QLcw!_UEish?prXn;bz(+2rilEODulR!3b`E#^E)!~N*&1oy&C#PPJ#@pi^` z?C`+x^wBrBYqz``mj}%Un43JbpJ)o<@Zke-2XQt7v;(qqdWF=5d5Yti?=$Ylj>j%p zxLFQ$$C{|h$;ze5VeHuLa_na8;+JQZv6pq0&4ri*XT35mCB6T8oLrEct6ms;a(Rz> z>3CLLo?KJj!#=1z2;R(GZa=s^bos6NwLFoPPUv>&OzxvUwmrH(h@eiOX=0y!qM&7? zsH8oU{cNeMuWZ0Z!%KT7b9RWa`}z0hhaCQ#?ujh6p~}6=oyvQMxwGoCNyM!PSIjvo zT&kuodMfipl|=Neyvdf?T8a0xj7*1;^)B43Eh5sa=H6o_<=!U^)+*Lo*4`It zm)zU2WzO0f9c0?%4ejQ^f5U=aVG|2+ldVe5e{J0_^htcIe$+_s;c>^O$F*T1Slg`1 z&sWaAaE-p`<$q3LhzK2Oq`&mv~Wr|;9% zE-#8BimPKAdT1?ZDY7Zs$+4$5ODightgH}x&Cn(aievMbCYs=m31Y&FlD>6@|-sr zAFf!O^^=d;yZH)rL!m2G$=rE-EK^>D$60ve(L+gL{0RjU-|iaz22J;>$>ToZAs@w8 z(bt@HNl)0dZ|B!gNlZ!R98-nsmCjYei^=(ihk$L-0oRg4J)Tl~7jzbKL5@FcF3$yr zqw)={c6u#sn>XtYduN$n_P$IC90`1I|8UaYnBr-_@!XHFhaiQXPo^%Y>N9;-b24t5 zmz-BPpgZuF96_XAWQ@rFM!ui*lny!TbGDkoPX%tJ)c2WbZrSbUF56R)=KJG#X2||Y z&viFVW0&N9&W~mO+{SL3a4&s@Yx4TPIs~t*7D}?30-B^NJ{Yi$;J1D8cfMoZvR!LA zb5BIkI;}co6xs9Jd)~V|?<$;D%6^7}`F8o(+`Bgguq3>(ytE|b<=_ABZH0;886*c8 zEoT5br~lodPQNtcf+rDNWZz36EF%+RA-&mCJvf6vC?K+uVrm|XM|$QSI5W^f90E)3 zHTy_!FcL&5zJ@5{D0_v|GXw?5R8dj&6$V8`xFk^(1>F5WLgc3SF8TvD0g@xD^cgk* z<>t+!aI6>Du^Jl?7z#p@S z7DtQh_1m{!DmUn!4ft%g0=Ml)D!HlRxVQ`Te7Nz1WfT;s6A}{QVD_fI-L4Xhubk); zhu#WHst5BDGp_J(nSa`*@gD1!xsA*6#um=&M>fy!L zr!X;yrtkrIt{>HWt-t{>9TH2XDF5Em4}1AxjYhGlwRb!JrKQy*h4z6v_rrA2SdEbR zC*7XpysF<8AJ)7-?c^7D+>nrUhOYDSDaIvk{rUHBX)t^r4?83U^?!xKe+Ni-2X03F zX;@eot!(~p^|5D-Vzt|om6o~q=FmpqSN@e=` zaPE^uTG)b3*pNxJ-@&!l6*#SnbU!#a_=AU_{%}~vC+>9T=%^?%S4SD50Q#Ui36AQu zOkZevHlo-}Jx459Ow;k*km#qAgsG*a2PP?%jkv}P-$G0NmLETU>}KD`JdYxxp(*Cj z|LoeYsjQr^{ELc&)FhfhRESh-Hr(#6De=0F zd@^|_yk%6;xkaX8Vqza=tm^O}JzM7l>6K6r1=ay-ESA++*1_c?h6HuTa);i(qwLm9MLK5}k@m88^j6_@9jy>#nds0{p z$o_0^!_0{Gdcj}C6ZT@Y|f9D>bM4FB`Tq-N5>WvI#He3K$n+-Um~Pjccm z7g6klRUNO>p9p!ysN8N8WaJ=NXefd(sP|Kb1O;Pe@q2p~!6l;HlN^6}UYniAJ&CPi zVJdLO_TE_>k}nt>!+&BA=1!gXTZc6JR8>{QGDX+Jh8gXCbbJ1_rnFRHs@`@9db)XZ zEJVHWT^>^P*&Mbcwe0Ky8kt~3Z?B~LEt#TDLUpaUU-Wa!{VEgO_eFZg)Y1DgWN=dgZOfvL@( z$wEg-8Cd0mjvXlp-J)%0aX4GXaXjukr@M`d6Vo*M1c98cy{T!Z5I$HK@)`+uFM&X? zB4I;pxfYR3*a_iZ5y9ptN0jTe1dZig{aEcsVl_U@Q7g$qIooH#l4|Kr0UseAPbo2dS-`U4Hrn1J*;)@@E>_P zxalDm>G>mezJ>T=V`Im|h#DDfRCafZLqyformsgvM(RsE#0&?QeAA9cfC*li`(QK2oJuZ7pqh1#of*VY%taH?~v{_h@k~%@b!6+A( zmn+E3-shhTiZ!c@;bu#Ii zEVv_?0z7sL)u!_EhrGz)uce2#7eClw&%_e*WN@i0v_o{0ldA(nOA@b*LONVuf*$1# zQEY5e)ISfI5L|2wknu@*wUPDp^{JCjdT1Sp8vy z5j1NnK4ouddV`UP;NjFTTZ}|tpPzZUvLLRu+c>>a$xJe+VU~M~_$?tu1O`DAR!l4! z5rrVEV?c!{IdoaH4sd;$`Z+vne$n3?4}m=KiyU!_cyw#2s~32>h^}p!#rj=_AYnVj zkqI%JQofEAcXQ{AO(8IIHV=mOx#Wa0N<)eWNC8PNFjL z?X!)Z&oa~m!ajE}eA@8AP~uSJCZcS#<@{0AM6uU!&P)ObyU|f^O9mi=)P2ea*JOP5 zobTtbwQ!`2M!vmO=jp0nL)PUa{rm8colnoOyh9k7mzx_P^7k5p^F5=lkB=V&;}@F( zFN9So3lm{rf67n9c2{i$-CRp6mG3Lk+O)yGTzS3xU6@`F*2?<`Pd!Ld3WsCkQ_~VG-+0K z#%}S6ztT3>sx;+W34ZFbG*qMlJXt)f7)Fc$OK_JV^If50=0WvZRN+%GDm;u#RJivj zl@YCy=C~~+gddUy!r5+_NMB%iN7_<9@p%`e$-H+D?8n; z=nbI?EWso4ag*LkkbwM&?5!_(eaL0i)$A!$C6sY^Z+@KVdB71+l7C&*l(smh7ruCW zEp`F-eS|iimoTh&PL0>{H#Jb@NGb8i$?b=w8ol}2_cfLf#@qSaJd2Zut8Np8$NfSN z*E*0P9%}j3!qI)_{xPJQuJ?^IzK<9$O{`whkU!a`hhxU^OM9y%-Os*E^gp5eesE?oPvq#go z9<*3eq`kauUlI11aT6Wz>A;GKp3sC#vIO_apG;pn(bQ@dM)>aAEL6jRhMP#IWamK6 zTrz?6nU|U$I_vY#*VXh<(DCEaIfAg%+33Iiq{^#*{0JA7%VxhSX#Hwc-Gu8;mR=w= z;_M1moz={N2&|YS#G+WWSQ4bp;rO-&{;y7((p_;rXM@v}MAvFqzt!}mdRuGP>L03a z1Qw^CIA~?VsfPVRD5O;CEEh)iWOSsh|LwTG4qddA#04ht?AAd1*5m!CLyxM&=Awy%O}6Ere8{9g%!AQy(@V^K z^1G?A0k0~pMK^5bpXt!(S}RGVVglr4S1JXKY*3q@{$5|s6Mm8=RmG`@tNiRWMETJ} zj4EXb1+80;a%?ujHgpzTgO~~qx7{)#G44drIpFe+&HZ?UBLVd=jRXF=1 zmw$Ka|55@^vE1g}(3?qbJQXYOrEmArda9c4c5FJcx>s+&L+Q65v3d}NA$L0E7nuWI zE#oQzsxJ}p9)JWmXe66>=*Dp<@DQscIf}HtYRVE&9t#OmEbOVXo)g?Y_b?vW(If8% za7`2gw*6>$IuL(IOQ#DJ3~N$;@h8baZgyOLwpF+qIJdah(Rc%>D03juZhV(xLof7-y;; zVoWJwR=dWLZ8#W1+Z1qUD3@LtHfvZqIem5?KYj$5Q?td583!58g+EhA@g^VemG5IE zUDq^27*SIbR%el)5-hCB$J7GbnR(Ahq z)S^tiZ(oMDsf4qYVCWG#)zs8H*4n&NX07U&mqVRjo}U`sj)}ak4?ddn(a+-6Wv;9w zUJY@l2&7@IrhdM}0n})9brryS%~}ggKw&^_gRFyISf|+j>z^9)LX@*zzU(qtx>t=f zX~MoOEh)*lXKYr}G#KkJ4Bn`rb2ilBc8E>kOL~g!Ggv{mxaC*oC<-lGoav+Y%sTZh z2j6%>LbM(#*0L~8PGch3>yA1%yHO!DSdL2l^||$%+8yP#U0l9CKj*_BA<<1vOFLLA z)8X-7`UHSFp0Rrx+1MN(zzp}VrQ=+_?PyK@q43>lk-sz_%fOt^I*nPQCExa@&^@K5 zrv6+nIQF}J(t>G2l@h>}=WB6!5J>>Mre-{*93CtK%3L1n3-d0oYIiNL27qdn(-rWU zbZF^aJyBD7Uz*KfA>e3qr~tYApcYeCA__!eA>TBGf~@zLh1=WPLXBVhz@jKxa6y)h zdtb;ckSG7MNT4cN=ziA4`CkQ#^A+NB9En3nSPU(J2l<@h&i|ur4D83H6OYdKLdX1< z+VLOJW6Ym?R|HFU>feR`M+%d`4&2OLXN5t3^-X1slpyRJZr!GfS4a#4_qIzGf}zRn zmiziO1O@^F;FNb9`d|?B8d^;1S}Y}^@cS*}XuMHYj9xY&$Y9W?r6JRVK>lE1)n0u4 z616wzhfy_l&O^a4;T^E?P?`aYb~N%(N1M4JFyXXV+D=W6OtJ|ZCp)`FMq0y69l5!= z)-dHl+AJxzTbK9okbp@Gg^vtL(oje6hRx&Nst^Jg!`AIvH+dr!-)tX85KL>A_dW$+ zaRnd%eP^>1#Y(!mUeiNThz6xE?jMs@fDGch*&A5_Rciag{0)`t?;Oz_%jRw02qq}V zDJbE8?U(AADMds&UPD5{!ws_7jJiYjrwUWvqJEIV2~qENmQG|vndquc;7@JyMNT@U6h`3akI26?kT3lL6+i|Qu&hQRFzGe_-1W^UN2PK zF?nDsw53@|`el+cQ%_ZOlPTl+r0s3Dr$|P5_fWDlMELsl*1xf|^hgVGs-~eaaOoj< zcYoiOH+SfNdvo&)`XIxrPE^RUS1}1MCmwi@yGiheRAJx0y0r^RolpGk zFr<81s6CvY2xwvJ5_M;n2*Qx6NVX0s3z-B2T09*b&e($}u5Nr_#rA->mSSpd&SOsS zZYPRE#C;_i;Rd}(?c=hc8ZOVb3ZCmSKhM840^+#>_E$)!l{bsA>BIzK3l5yGt$Q9> z{Z`NZT+JLly~fhF6ZH{B<8_BMSqrpwUKg`YG}y@W7db!d8eTJzHL z57G)z-wY-Vs1F{3T;eV)hT#*cm#4Nf`FtdQ`ZTfx_LhKTv!7D zmC**VkZ!{THyf{XbY#SYljs#T9-cb4)iizHf{oeD>DoA`NfW*gH(Xznli2}4HPcl? zZu04MbZR7*j;25yG-3C7IBrl(*{Xb6&6Pq?s#xG+XTP``N~EKqr1V#aD4RRnI6RED zoGL&f_dcqc4Msp0cHJGz6o!m7Z+J7Xv7Oa;Uhcq&09<}{Tfwo<{Vtv?RweHp5<3US zz(3A^1WG7!lH9fnM5K`_Nrw8hgoMOgwxB0FJv}|5ii*k~9s9N!ep=dhSY%|1K%Ybh zyygQ?hPK)n85q3!4B3v(*H=TIpPx@#FMcsX&CJXc07PM0^$;q)(M=}g zXZu%1dWH|1yH_O^JEu~Jl8?4CH2<2cR>zU* z8WN3cDz$%Jt|GHi2cmagmRYMUXDe{&`r@o5sMF^P$z-B&#kB*IWF zXDbXkKDvpQtSYM(t2I9Z%SH@fFD)&t!SV3{V*A#~i~>s_DsKP))98K6QV&$ut6prS zQg@14l2=NZ{6My?Z*On^GeGXI3)q!#!;!x~NS^WQlNEuzP<(wuumcTRWEoR;wa1C3 zmOH^T=XwnSbhA7DY^YPH0dW)&atIl)kW-*fj?eD9WGZC|-aovK7sP^ECriHrTWMON zUWTlwpfGZ@*5SYV?=Y4(Z?wAE6e8beGc(eGX85l~sQxaD=S%*H|7hO-xQsWdqpml? zz+*7VA{N^pLiaGoVz}D&3B~8;SXLqZp5-N6Pe=M`OtgThv3X6(N0^>hQ8WEp=kDcO zn|U@2SQUF_CE@J&t1FkQ(=~D*Ve)a2msaTvAm0G3Y1S3T_WnpJ82kNa8;yCOI)A3# zccHZPR&?LSB39JUt$%4kDKs5=9WRw!m|+8Yk2rvrjvL)@DY?Uu?WNAAxVX6304uA` zmg^lNK!9pC3wP=%NM^U(2-T(^k1l-IsjR2>1f3GkJ67<=C0`2i{}&72q9zXdjb#cn z^!(EqKw$1>=F6w(1MLP0a^$b`D?w5K6MyhR^FlZC6X{d^iwodglXAf2V&ajV$Fs^p zW>%U#$)i800}%|{f~6&wj|B$@7ZDNBc{wgZ-s*O|IHy26MaNz)>Nq-e^XEG3T%AkX-CnUhCdVkk8iYY{vtM(;3uyoTgDAxg z7nlMY+WNR&=%k}BLe}SbkQ-;$rh*El>S$$h0k@I-yrirwG~sOYNXej?5{(vW(@>~G zye4dpqs_hYWxBM2GL*I@`)vPbKC`h5tz9C#DzU~b7rgd}WM&mzH8t~Wy6E5Oqh@FK zJ~qpZn30i@GIDZG_k18eKT{8RU}Xz=-vAO?8FmjuGc?b+GM!zPZvgF0G&!3~b@)Af zPDls>onjvqUIGsiL-00tbg|Al6l_RvM~8?A56`W&1L+?=&bL5}zR7F=8Vk)0RX^U* z3(%XH^_n>+)o~V{&GhI5Fz32vzf|L@jKO|gd6>Pq!wMH4cKYONt4C3P=1NzsJ56%f zxwPbcm#8FciOZ*5Hp@_{`K9l94D9t>xgH#Vi#@}?ehHt8_EK_k;^gP&H~QSOQ&CYF zauPY7t&6FB{1`aCD?x$LY3Q)vP7I8r9$*yBx&rwR*Cy8P;pW(o06s7|;Ng`{JNw#$_1**^87_8YP>)g7ga`2KZyS!%F9 zH1Ij^R{DW%*n+d#F)dGx0TTlQ!|2e44?DQHxL6443=fb^cx4k} zc;G?-o|hzN3git2zspgc_n;N7YmGJS$XH#r*IFAXDLFahFf>xD z(L?CK?{Sygaf!L~sHFV0Sv}52^KZjX5(Va?sJtEj$OL?$-ggUhogHp1gj{BV?%>g+8#gk-36t~pe`Wy`fNz2U>xeBX2mwmNW4U@sUY$0xzTds6 zc*Wd6+x4u@sa2h}qJ^Uc`@A(KvBl0v>Lr>OhHR;X>8T*!-{bE##-v54^7_YSbenRB zL4$?_W+64sP?upY1GL2)iNgcoVBSB(J0)cG!@6yk5U#@)~ z&a}tQ2WfO#+{&cmW+O0PFC%L#;lVFC=ruZYQJ#jqB3|w@3>_YJ%TpY52QX0BY?bMqfitjU4q{vJ84>+I(d6SRonwoc6AK-d+(NAVd@IjP^M@2>TK(MlWZx(VuJ*NXZTiOQ7 zh!v!dJ=F&2x=Vju_kZ_UcZVSH`aRykL$sAnwenSGFf{?_Eh;V!RG{VXBrx}ReA|tI z+M}5r+c#>QjV_^rBk*%FbudVQR;SVRP(AXA0oorTo^Pu{X`y*Lnm7)sE<5t^&ymuri#1nI3t?*G zEiG*K{ZQS{2Uvj&EAmI&pc8c?5bi*5Q6|Z;?z=R<^Nu)4LxZxgUv0e)8$Au|2}fT8 zGsIl-tT;ruGcZG zQLXZBQ~VB8he}Sh1l$!hd9b9hoPr)_->-RO6Xt6z6Qy(afIG+{P`boL+FaMau+?$5 ziNc2Z$+cQ0p%-{-6j+g!9_PjYt|8z^HQDml;<7QXsV=F}%-OS=riP#nJm8+Na&13 zL@bt8J8r!L{v#2cVn*X>K@S=!zm1Zd+(o3+Iu zm8sb9E0Y&=J49q;aZAfL7IaUAvI!x;$5kzcU3Ou2zv>1N3;zD^Mu2K(J#=H1r9k^B z6ai8sE+L^4-Dmvg&mTzL>j!vnkzWne)%#oTHlyhX!#oMg%?IWRfBcYy4v?f8f(-zd z`w0*f(n4j1Bz7gib4kP=HW^vjNE}31)Qotm>63+;-JcB&w{d`h#L6ouwEnL8G$4~C z_px-+f>XOJdE?vz+Q7izJVzqjPf1CMyhxee?dab*9J}vn6Sqrd4w8>J>TtC{k^!8z zu&@AVLeoi_D<3E6yj)V-rE$mjhcBj#sNg#PIH55s@!3jEg7d3@y5$u&3j_$DD7M{Z z4fxh--u`rmB~NS9*QYyzh*oY`Yi1!xsr(C|HpPSb_ugdO=QBv=fWpv61!ZTG_s5gR z1171HPC@+38#rv!z~vGsmk37#GPz1qe0=yOGya@)Ml`z>Xecgu)tvf?%`MlUogOBR*=@iu&FO;z&@`;Wzc`tPq9PXK?ng%@A|jXaWs3gbYxM zqqBpO3VlD22Sb&WY->POIR3|u)Jrv0oDZgp1AT;F#sGxCgA~ys2D$ZGvZwmJS5(Z( z`1Va^rOg{(N=i!o%SSb}kokGdABBbKuizz|U^Z*2Ivr=##X-Fkz}B=e{q;dnM}-qW zReqLaQHsvnHUHDfWrxod2g@zTBnI{!Pi~}>+`z*v>`QIAGx7Y%9X3Pix<{Sef=s95 zc5&}BlFl>!NgCz)!2*~*r){9x19qTJc{noZgr99zbAJtnAlQ&YH#ZIr4$PgMog2Uo zgoEm#%MV7v6nnQ{$6>$c5SiJA#(ZRK$R`mZ8Bc0F;}Y7F7v|+pvxPp*KhN>UjIxfu?qB+2gb|Y@!dMh zDR|(Xon2o`DJx?DQXdGwRGPfJ{2a_32HK+X%E!A`@G$*xq$p_xRba5dqxyUGD^&R4 zKqyhozs|+XHS$|PX@NMeMG(A?aE&D3lh@k(#rmw$$XC6PUG_kMQ@TB`a zMo6;JH{&{OA(NYpZ_)pTCR&2M04 z$TPCf7!1*TO-kxAWcybnfhjWI>}n0T^nJi^oc}AE&_E82VVE!5(=!VV_SrprKZ$-> zvT_S%F8%tLACZ~dKlv5&71P|oxhhU*yvXxBzh%j5x_@&E!~46t8rF&O`QI&xUcZa+ zz|be^bV(;%OKH8|Nk;+Dd^W={jte>Rpj}-J?^9V*7p2E4-ES zRi(;6_X$&=B`#7g*O^WPv(cEdEfaj!wvK;t2e&Y`?8o9>g%C zO1l;Qo!K&-H7(szom*^KKR-VW9@|BnM^NdzEjTxU=@puiGB*QqROwArJPBWQ6Bzv% z&o3;rhdWyWu)9Iqimk!O zk*d&5>lm-z`}9t6mJ}U2p6egO(C=Ha;$w{n80lI(DXN#_Flw0sx84@gO$h+S8F&qh z6$r0Ih=1bULd~0V64^sr^hGkFk)$bGfXsBU-L%#?bZJI+lEo1eMM>f8m+d%Gfo2X=7=VpFG}y2C6;qO!)p*JQJ(pASFFPS> z*c(8cIh0$-ut&@;zfKh@>G<=UNe!`~<^lI$dWfhY~o@?^E; zaTfn{c_yB;iTfG=jj&kF6>Xm3i&f06f#3jhfzaCrQYSx+ zO}W!AfpWI2K1SlO>Pks;A}J;H&%*&-uCKhC5EnNz%&EEMc5qN8{PyG>27jA-;*g6$ zM)~FxE+^4@DMQ2WswFcQ041!Mu+LPH(_qO)zRTNSM@K+Ir>cG4;f-G0rXfOU1{oq` zURM|ueVQ_$FUzpErLQRO<25}aqjzH!A0Q>fZMo{& z+KYKeCvArvNmICh*pj)u?rn_e2@DRWXrlk$*>?*fj3QFLb;MVM@7d0T%QHtDoia%1 z28RAU>~_RWk@E1QRYk%P4BWqr55b6n2@G*2JZ#nCuj`xtJvEeijtaE)EYLCM(b;g3+&1K%`dDWkjT?u|}if(#*UnSnMdzocraD7xZYju+8VSFcpcteE#4kRZ_(GAuR91+avI!5qUt=xQWx2JU z`8m@(SX4w0Kk-)K_)&s3Pt0NaV*4wI<%-j_ju(xMjg2lJ;kCiIzhISv%5)m)cdD`f zxt));qTlNuFqT3i#ExCa6(m-TNXSGjhP1zzDZjJfBF=fc|E>6^pl%9}v=Y2W92Au- z8KDLDRA_B7+j(pPK|)S1K&KMI5;@4ppNDGm%ps|FR@Y`2OnPmTe~0(enNxR0%iT) zOgMMwC39u1VLL#>@xBFas^H~T6)xaC*2WjZ^4qLgJ|%RJgmC7*sG`A_nGv7?N^JOHqMN+IH$9Idvrjk(R-} zd4uARIGp^?|2->=C{=%MkJ8f4%rfVk?1PNpRl$9?qqF1a!6A(8zt)}R%AGK_DAn{e zluH@j7TLNiL{5?GHag&A-x=za&D_Btp~^sKBeWmQxw8nl}AC;4{`Eh2oRfu!((6xQSt6+E|_-Keql zeg{1ENB4FQ#KX7Cy81cnBljGmQAtd++M26vFN+Ul+U&i8 zzdByxdHyq$2z)A0Fe_WD&CJfuPJt(25Ss_JZ!tKj$CI)qs8Owu6n)D~nAIZ!W1Gff z{~Y{pG|J4Z9l_8UTi^QM2&70G7-IL#ROEpXrNw_D;pN5AvX!FRc&7Ai;qGwYi~byS z_nn>$5t_mi=gtR;J_IWKM z;(p~wVtdPv_-JY&(2J0XaNE;J>qY_YS=Y#~U%x5@F|~Hbvj=)3vE_jpKk_c-RyI!~ z1KyTBfSa&uf|iZ*RS7I zGWd>qQn8YsDtS3wY=$A?lzJ*EV#!HKIUq^_Ug32+BG}y8n&jOt5^1u3+IGM3^(!k$ z>-{wL8#BBkWzhKY1DK;~c0YZd1Z^>0!NT=;(e*wOo9+?VI|yLdm?gimvhvn9qKq39 zmOC*fJnyD`b_WB`4(WI@#<6S>fAxyF@joFH;T;MlNO0aFo-f-D{`Pz-x~gbRYOw7A z=sBW@IWn-q1`sl-K9k}=+3+y@AyVeK)+_rsm-qsA%~ofU?K#EpVO)gD!@RY# z$x7m@O)|bK^Krd_9KDVlf)1m*k}|fFHbt0xGbUAfoL$m$MA)EpF#i2=bY$}avhf~# znf2bF&8x1cx>}XbxEGNK0^|^}wV}2=vMUpEeq#v#=ySX8e8!J4sCLTSrm>U2fvw~F z&1lxu!QtUVo3(aQLPElbxVU~`=rX>$v6(x}v3U8oiuFtf@OhXTgA^dS8BKP~Kra6F zE2ZgzaQR9%X{tYW#qpuS9siwU;<lgFYJvM-3G-^Q(Wk z35Es?!GJsx#FmI?$9k^3kCu)u9N0i*79(f>s#>&C2JeRV-b79pP-Wh{LM28(i>0jf zz^Zb1*leH+Z-_#qL?S~9ltGg_dR4WIPL;}fN5$8Po!clLo`8(&@)!O(4im})czhhd zZE2kbJa7#$NCtt8=w-P{K*+iFKi{|#1(E^zL-1FzT?d{*#B^HRsWdD#7O&kzp4E;sI}J2(BC90?s##3_%8yeJG6mY@`<(e3|jc* z(fMe(2^#=f-Ym}@!mnSy-i2+D!PlZA9t-&TW&>&~UaSUW>a8@r#srlm!sj~hU5tB6 zP9h*Rd{pMgMg}@!T+KeOfXm**hMKl^np)nZA*iI^MEu()4cU|-H@v(&FrB+a z9aqVD4h#?ln29odq7Mx6SzZTkwt$>-2Uv1nyYB<^yI3MuN)8T=u6`joH#*eQyx{=p zb4$!1N+Tnq`FdNObx^cE06_<2gRb@_Z+cMTclw|A`6V5f9L^_V)HvYi&O-V#88VO7 z#W`86B%)xi+W=Lq;Hi$4GwKXxs8*_!VS~M;hKf^w;L-g3{lN@2Frr<7s&bH(oUHzR z?r;t=kNEvJW-%l4MFXBTaLZAxq>K1M7IniyJ{#>lmt>SORd6#A)LqG#mTyD?jSFjB zkQ?*CFKKgntc`#-2Lq;1a^n_zY{en3%Iz%ue?~h4x(ox<82V<2Q;aT{H-sK6t@Sl^ z2!FfbZFU~$wpGvbY8V8blG0yRfN4aoh2JC*K%LFf0^bmM3ur5t(ED!C;pgG`tEQ2N zJgQ-rRsEkVMDBM-sm3tFK-YCSd3ZhBX9vDp!n*P;JsqY0TGi?-38`0@y$g#>Ro!U=Xn&H>r8xqyrZL=Wl8iVs^8W1?MOum^m?9De)C`G%T`fACus| z?2nXZ`dI5N(SfkZCvLXiNC(f%d@-@^a#ajB5bgL{B%m(5a`#g%_2(FTZMt*x7c1| zV3Yn}jtfBqKggFcFJT>{5%c(=SD-2LQQJ~~E+MtyN=f3(Q7FBZpmXDxh;jypJN*OD zmXEcxg?rTZbIBSj@{<-oj+q{ zfwVm-yj>NY^x3#h~zMU;6p>PAcDmf$}LLM+p_*WNJ6soVbX%O|M<<9R+~>OKTM+T*=CMCZwgH*RPT!LbddSmd2)JUKqKac3LBQU>yU^axz^g7VMk#mK6cc& zf6)=s4+#?yhKiU>t@r7B(@B)?d!obJ4!S*AD=QYH!74M8rt#mT3Q#~sPA-Mo74!3s7_7wP#Ka+x%`u6KPvr;clPl`hi-c_p%-c>`ziVvF zgg;>~7nvv>z7D-+Li{TGy|*B(Z<+@1SUx~)H{_L+p3F7-qvR{ase>eJ3zH%8p%_g% zDy)yu#cT$ZB>iuZ#;j;6`)xr%4{R~*%Wl1T6ffc_inSulXm^VxG{;!=ji}jMuc7vE zJQX04KVz`yl&*t~OO{!S8*&qOVJYS$qaKTW9)r!cQTV7q9ri!>S zArH~a>m6oeqaiiE=c}c~{|GF<9S)_NZP~d4LVBePh|Qy|nTC4|!ouWGk9CxcnYKO0 zQ)Fh<$EAGp?(iuwDvtT@ppSKEp)$;YzFnmbHdvXkGbV2DN|DdL*w963*j*`|(swUG zWgAuxcFMyh_*)&vSxD4N!X~4+_HR)y)hH_}G$Yx3{2`u(uHh@#UXX(SN`eeN_cQHO z`|lHXDXN^PG3dS^WJw56gW4Vk2O)5KGq4a0B|A4|h{4rW7i^J=lmdPQWVc;M?95Kp zF!k{RDb=8Vgt)k@@|Gka{>=Ncuk>>L)DQLmae9s6FbS_C4O|1iMBo;J<8J3Xfb|Tp|Hqlvh+xumGlQ8)OVZ z1g)f4nZsa%n}l_`2rC8NS4(vbjlr9~!4$V{O*nMEymxKRGN8z*(f{S@LckN9rRuZMq> zzEn{1Y)mKj4K$-eMRW}@J7iM{ety%nq*3^p{$+AcTAaKne` zyt6=%_$ZOZYiAkXu`vfXx5 z*z)I_?w1?WjlyLPA4D=-ug*S=;K2#}(};mg7_EbWg#~?NLul5kb#{$-_FOvY$_TW8db0$<^zDvm(dGMB4D<%xf4%0a$vo^ zZlkf7l;Ah$VdnIBqnjjWGD5@8XFv3Q2sZrZ zy>7=N*1)ty%9SZ6lEL~S+*v_oQ6WW@$#OLAzD-RSh)RiSZY6-xN)g1M%=ZdMXk=vI z8X6ix2fg+s)B*6FPLc)7H`LZs%+`1iL2sNee$4C^3O@Zc zRHUI}l@py?#3O8eI6SsL{GC~UzZ=&b$btjV#~D9<{CF=)G6e{<5x7WRfWNk7JZnCU zop3Z|T{#FyyIAa50DCD?wFR7&oBII+_Ddz>meswS{Tbq2Bb3VzZFQ#a+QLk}D%^Xi zbCCH>Ed!eHH-MR9U}9lCxzOrJxKgJ<@6esMj3&!*ypIR=u#?Z~qW;#X0?LenrY%Nt zsI4Gg<=?NzIaxL@{qfah0ToG&5tj4EzYHJHxfv`>?aJ0d{Jf`nnKiw+o$p7m+Kq6@ zRk%WBmZz4}jb0>})}rVFX76(vUO~whlB-t4{!`BRBUOg*GZ`SofVcw9vdKkq z;U;olXoKw!d1ACX3M2hCdFNZ>4=0;L*L?$MZLPrPU zZaYCLK72H~IIIYZl4@GIxJc;ejlX(C13@vTgx~RN;b&)y&}3Ld#0STjuR?rqI{<{; zbBBw|abdnr62C(tJ1Z-8ZEdXyp*Y*mPeMX+8ya~OknDDz>@Pi($ed*q5Ed3jn&AUj zR2HFNqP!o_nA_NR!IF7TbXL*nI#HbPDh9zv6qJ+XZq3in9|vHKE?Cf<=bC$0x<8Yf z64Fr7CQCuWU$lPa!B7|p_n{3gx=gF%2MvvUIja~Ki6I_zmQt)oboky%@9JdHLZiP= z#!)kW-;`vQ}73d3=Rp-2GW7LQMYj zNmpb??j;wBsy!>|bIq~1tIr<7BWM#tdVl?;-}T=xR1DJdQQp6Z_r_Lw=0I$_N&I4= zdMm{I0ZZ5B7l}BcWIudZ0YE~+uRAqnx7ju%pWr+tZ_#sl5|uk%e~#rnsme%(n>)Nd z@JXjw&1G6O;l=)9XKH5*#S^&r zM*aY$Ub4W{v;K5;98`e9`c6bH2s(k9)TgDS9A5`zNu@@hDd!xR?9P4yPfYE0e&iGv zHVPW$#eqRozK;f#HuR%_KYSe77~E?NeUSk*LC$!?^JmB=5=dVpxta*P;(1zR&$1^R zeZGI;(p-U@3sxZVaOW5Uj57xZxopm^#~XI`*grL0_HFg;*gPK=S7E>jqw`6idMQmT zdnx@gh{=?Ni5wl3lZgpk{!O0Vj>2v9b%rPg9UNK$;|H=q(x~eb|F*5YR?eBlH(4Dk z8c-a6ol6}2QujTs5?z&SIS{wK5|WZF&2Qu5`b{Mn5=xb;=Rt{XBdPoyy~35qYNa^d z0lM%U16m!$z4{CF1LJrCAVQ=}-+Z!&MD-GsR9^*O$0-Jz9!Oo5y zwsRLCAwh&9MBCaN=;kxFo_{;3n^iSSY-G$)n3!CnJ$_6W8pCO)x-Cqm6I+13X0ydQ^eUvwg3D$#=f5# z$)O6HFPH?#6adhN(+Sl6>RDpB&{BBs%?ICQo$qqeT-iVF?!U}KqI;^@5(XOme+ebLCHQaP-A+XK5D1D%Qei~C zv&|rGEeamA3X*3*Rc8G8Dd3rp-DGY{327@_yP2uIKJnegF%ZA$+5SppbR7Ob0EVde zw{OFN#sLk8Ids^V;j;UppV%_AuZEKv)N{euaRJ+mH~3b1KudFpFb5BZLZxj#q4r1Z zckB;#!+ubqXH*M^$>v&&oNvCIqnzg8!-(%x#R<-6AQrnFnUT zM3wW*B+2Tp4&Pdg>3W}l_s<{SV8`2C3{bb2&DEn07f={$V|QN6>Nat}Kj81Y*P1+s zu{lU-V14`asC`0AzlLl7Z7Ky;?SA{!jTVdbX5U-frucR@m-AiHDz)wPMO@cs7v{9d z!kYLmujQX8c3K?IUe4PHedUw4NIA%_H6trM{ewm(RTtW>c{{`G^YBxG6|=o_HpeYO zEySqKk;6CI)|X$GEG#cu-;@U>J8Z&_ORvaI$XLZQW5B9w z)baio&S&IG03?hk?alVy1m5ZrqW^T&CE#sxvhaH-5sghk;rc`Mumo(&Be_E#!y}Ov z@1qG@vvJT56en{VF|o0+CFT_=BYyn&Ar03d19j~fd!g}dR@TgO082Q!ySq^m5)$^{ zpCLQJIPM()U}>RV1$2eqbx|Jfz@kT1`_|E`ewLZCxs>R|C>^*1l{yUip;WfcZ{N8; zxff-DZYL>wvHbWcJ_5mi+eJ9D6JZKOn9;#X#xtJnp@N?Gz@sO^oa7e*!px@7g0Tm} zJ)I#K379wJm^}NzbG&! zC0k&}&?S*@hCxkR=JL~gLg|114k>gI6s&8pHrK&uXG^U_SlzJyK7qG1k3;K&e1m|z zM#k{3vMcn*?Wj|?-xftg}iRhS9`cTHiFNU1EBK?iH=SJA{w6T?~Et1UFO{z%p zleoHyH?DI*A&vg#v$!!*j8u~ib4lswcuMGjA7IvZyv(8y#QJ03y?&ggm<6Eh=}S#` z+<}l7R$*bU(wrQ#F0f8_#@$_n-v1eraIe?=SmNetmxLA9g{#Sczz!15NYK)MSz;;V z7W063V*)$7nI*No7#nXJlb#6Ym0)O+Wj;)^zRC$M0c;&L{ec zDE5D5po4<_g4oS-C-p4nRl5M~%$0M(*FSOdf99Df5|*DnIRLlGFklvcj}HzyKxf1c z%3Nx7e2w2-r|~9woNwv4xwvS!NTWBXKNNjACc|!hib_aCq-1JJr=BfgFNAV^anOIH z+Un^l{3dQU_Nr2(W52A@+vHBi)KXQgfS-Tgx*y$srbHn@q4q}d+r6WbD5xeWU$NR% zVMZy)!Utt9D!x5Os4=?qB2N2Vd~}Z13s4w;wp}@uTyT*xA?G$iM@RP)@IU*f2&zkB zzvG$blb7ema~`r*6QMQl-&@I+M%*JE7!JBpmz10kOVD_K#gwmnsSvwUk)2+)7G^(J zVEO6#q%Xj3gAsAtO|F@Nv`eeFY(3>4O=&mHbG=-S(|i%95)FJhr>H!hzDS)|hYqr% zy*jnlMwK)yF3YuLCGTe3qp^v_w$RAC<^~73%=aDCScm1L2GCVV>yKwX)-YP4f7L=< zVFgLcs1!s!s$+Wv@*&%rXLDDkpg&KK;XHHgFi_9adFLnFBYoOD8a&kC6lzt^jb`0t zg!yB3eHweH1>5#vxxSwu3yVC;d?#Ccb`sb+>3>*NY!>+*W#7phM0g>_3E%ZT!7i-y z3-mHr6n&wdowRzv=30Xw-dr3#B*I=Dj)p1-=QO0(9fFkD`n&)0iMPraOXHCxZD2c2 zK<4V7|M@Za)K~a=nB?B>dFLH>c%1)yy^>D7y&@qwR{ZKtSJnw$*QNc!g_7(E+a+%b z3I4{pk3ii08#TPxJ*zk3TG*$-o@iuQUPrGs?1Tu)EAnVE4Se}wy&q9@!g4meK^Uy| z#Nqp{!};aN2C0!otAu64KbFNSLHDbra9xlQUj^%PIX@r{Gbq(HgK#lwl+3_y*B4^! z>}#C>$VHqh^UDxJ2Ti7651BHO)Us3q&i}+^LsFmE^is!sp+6ZPd_i~E!pD?gSMue{ zms;6ebCpE&$CtFSJ-7!R*4E25w%zd7^PHZY`MCGrKo5pq@g=CCcM$U{D_*)hDd#xh zvY-)!4?Dqh_{*W$K&$r<`_q@eGV%MZEoDT#o~h|<46lF?vc#5gTVkRFuyK6vmT1-6(|>jF*D zo6@*B%!hJZ0!lk-zJY4L&w5;Gz{$) zUXF<=f-g-^-^lLZy&6|IoEco9n_b1=I zdzZrHS{reov4ngYwNhR2PJ>6&^oxF^3l}kNR|ny`z>e0KHF}q0C}Ra0`~i1a5`amSegi|u9so=TD%4aYy!BiQf6K4yJZb*@%(R?; zqO`hsBNZ`=Ht@TXft_pJ?KJM`x14xB26?8z>%;A-u}x_0Vkn55p-`m+=Te+; zt7ON(Z&eEe=~Rz*i_Kmi&w@P_E+VBhw8!D)qJhRzKN+Kg&+B;lS^i)YR9#e?i@qPU z#sxxHN*ol*tLnEFM=p-(gw(+m=cPV8HlYiR6pQ{wz*)n5*4kY{V31nRU)af$<*w}PZE0Q__032Q)X0Nn6#m z14|cl5clZ#OL7s4d1o1M36P6GsC^{>k6EXndYY8pW=U-DyAY)9>kyB3mvkCxp#+%Gc zu7<$tW-b<%Z$Itt)QE_jg{7)ZT>F5FM+>Z_va}*D(vagp1df`9xmVi&6fcQv{FwwR zo7zPAlgKU5{8qqXkYON}aGM5cfuucn#3}&p>4rX)u&?NGMjVTZp!4)NM_&T7lKN!5 zd*K!w&K1Da84M>CCsC31wTP^0Sqzd=$0}xudE&CDw2zJb2Mh$ITe8dFKi#1OWsd$% zBnD)NEq@Ea9gWt_PE2UIA=|Z@}3)8*Bkg5)w3-tzWdH!;`|gzr|1bjo11KhG=uP{w$K3{X!UcM|Qj@9KR>x zqUQ0XbW5(31ruqs3*3B>oahb5c>0tqI?W0En&FZpO7UU4r*m}r+*NW|HRMvm1}6mt zAJJ7%@wH|=NYV8tzrDHk;tnjov3@HtD~ooGJyv8uFg8A(I5>1FLP1GsH#RPgLg?9S zCXkFk;=o6yG$fY^XIi9QK~1>@O`6^%c$=OeXex}#%O(jQNZ#H0chiIZo*hcSA3?Ko5x*ng+at#IB*S~G99`u$0&R2fT1mud^3lS2$d+}74sHuzfG!3Q#n*cHyvIMM!IEl7jZO)HOw!1ulzF&1Bv%-73_8-?yjhhtUwAwtfXtcBGX)J)0)w&WnE( ztA1i(qi^r%T|MGS`GO#3AdhKcQ%nEt4L+auwidn^M8G<&;aXB^T1Y zj5!^09GD?`SA<_H94|#+9y777%EvQkr;j$30F$e!xJ2qv<+qQuW<)zDrxd$r%AX3$ z-vYb`ITup}($JBPpP#sgQtw04b7m?XnTbS10S|;e2xUj>wz>-`?3}ZiKNjWVwK?Gg z346@WQkN^))3f}Bk5z>fE^#N|cKqNIMtWv}`#foa^;h)iQwY!>a3nv){`U2;XO0ER zIn%>Q^ft|pdjnx{`C>J`qeP!HnQM6JViUP8ot4(RE4aiw*1#%QA{#mdhJnZIVbbhD zuZv`drI;G)3#+R%@X~%~M-^xFI!GC@p>^nr2ZOW+!KKf~6`I$m>R0yXMxhZs^zN&D zv<`KmJ$!7h97{0)awP15=>N05^W7GTXER@K!UaOe5QBR$zGr#w=qMs5C&v>H504q7 zgwz@kF(3uzQ!%Ui{RX@SmEV$=Fu4(kS4ORQ7e`&R-7h;$32Ga)V`9O2v5;?@4K?AXdA?)38x(}l*454X^a+F=Tm z0ELEC3N-sFNG#%tkItI{I#Oo2j7$RbBTCD8@AQ4ocqV>)_zC>UEnh)z_}r)`u@t-P zror@zG-bS6x?tKB7;g+jFE1}08t((-3a(52{RP<*^f2=o%q|BrICmUh#m4$Ga;zVJ zYVfbLp`1Oxg?{GSKG&5mmPLuGcejG3MhWo)`2>wnC_SGdWTepheDKR)9~Aaqy|y>B zr=3Ja9jMtR>;C<@iu5(34RaS`3*!!{!~}21_~CG}Sm^}8vWL)|gS(Bb?UU2L%kyGR zHJ@bxiPeX=tPY=#qv8Vu(m}l(Xo&J&QyJoKU%Ymf`m~ZsiV+W|a?$6VBERrtlRnI# zc)WQ*@_wQADiPEB z=W~gQP)OFwtk34UbLR;hKZ>kzw@}gWJbVH%ESDBtShVp`f_CmbWPnsTz$ICYTDZlV zjk+9evIl28j-s;-_%?m_eqMv|tDzb3T!{?SL>6M^<$YL;-N>{O0B+ zSs@g*2L}hyV9R?`owqw0So&2>C?|IJn9gjcyi+1 zc+e+~jGqN#`)PdV!@}XVxw$#cnytnlb%M(uvV(o%%6=YaUq@wfOaF+}HWAdDry8ygf-@^JIEiPJZ|ROju{h>SYVO0sZW`b+ZOM4a&Zuhw5><_32u zsgxzXauwQ|E*_IRR&R16R0>}1tg<;{m|uU?>{xxh$nzg;c<=If4(X{7@mM2D#@pa}h759~x;eLd{0Oc1F8 z8D=A!hbo?~0{9xpx@)u01ZSp;+q~TOc5o3ZX>atL#E0Gccc1Ygk}XOHNq?_TbP8xV5#96_ZPLWVtW!0CcCrV|-Gat)SVO$eslJg;b%%cP^DTY$R~keDtwy29Zaf@iTv z0;;Rx!0W3&z$QflP_;1iti{v)8*FP8&vF!xvhJFvKD97tnz%N3L{y|G0%_Dcuy5`_ z(I#td&HxHG#-wiORdn+cs-3)Pn=%YbbyKpkwn6me1?Lqb6BDXH8a^bh0H2L6!yqbp zYbse)(d)a=D>|uh3lVF92|U0Sgj5-1q@;*7Sxn#? zufY=t5*$bacsFP_zrJoCdksh&ALQ!*gL4z=au3SqZyyu@K#+d^e9j*WoMgz#j_SE{ zK0DGG4mg_v$Wf+eW@uM5o<9BbpKqe4rw6{@fZI7!#PD=EkqX^eK3{3&KleCL>Qn&c z?fv@)qUTz-u`Yv1^70L*5C+1@#v88aGBi~)W1cz7w!ff0XaMUt&n{Tij)3WQDvp8s z9CUYzuz~W_HqG^2|8^RD856_ImB50K_gWuX9)tLwGaqkn{bvDt^C*BC&BIPvZ_`WF z54AQkJNu7Gv^seErr>1PMJaNswN_4)|6Ux1+wH12o>}$U#UHg@V$$*K**}j_ZD_ zb)L;a%Hwy`R5ZolWA(l~SJ>ZSx!H;uB(i{kkOXk|kJ`9ts)`_Ey=(&DQ4xN*+r^(g z{Qw`6#nyPataH>|F|kPtV^}odUz#~N437V+1vtY6v3QlkAQLt!_%Go-baXj;kj~J4 z|JU|!hq;=ABYd)jLINTeEB`(z6P(c?Ma&>KTW-T6bUt+aU(E&H_WpQbHGkXdx5GvL zO`ugiut>L6`WB30{$6dMsA`na1e!dDmWwZ)P1iH8rRx0eU?9Gl9gR@_qd8yhOTP3g ziYff5MzMM40M;CmxhK7GW4|4bcOK|E{YGzon_sE>@j5*k{g7dIX$$S#U2sayJZ%fX zV6h!c?6zXSMit8% zXnIazvG`3T>gg!HP30}72VsC`A!%svrZ{DmS)HzXh=HdGqGg-J8)dH+(}a1eM`!6k`R! zjfFP}Ss1N=SyVZU5kevVzuDdNHa@k?<0 z#WKqAsJ(q~8~og5kXcscI5EU%3-Ih91P@WILsnO59yY>_=Tpfw2^G}_>FVG^qO$ez z{sC%AZF^OrCcX)?4kmTBV{aLmLzBU(6FESX>=u1N(A9;((XLa*iY1gFZ21%G>S^%D8Fa!V{B;E zAukEp1j0ptS`0cZxMqlf`p=k|)&{>cv>UK5$(Uq?gBD(HP=vZi%~jeG!IlHJx5bP& zmEzarx6w>55ihO;Au|#uh#0}r9m0Ygzp5oo95mhEHBvK`@Wii)aPPC=Vs+p(G(IlL z04n3|?Cgwg!xa_c0uS6R@T&E>RFDVKpkrb}qR@X%S=fyy*IX~ z+m$-7hn2Z3$R4zZkGQkv<>$lyYdF$kmVDx*6|hn!Xo&@-&ybkJ9rhQLi~8g`=`* z-YiOym0?;OgyIN=`r8K>V0Z?n?gCWs;B}=G^I*pgDeEKlM2To@Y@BsQ%VB!Ta=!h1-+kp(j(VXS_{%@2rdhIcaFC$2;_)_`g9L#b;<7EE-a&z8 zYorJRP#IEGGQR!y}|ruPXz-`9@C+Z#nPF4LlYwpTd6^{#fnYZ>FFt`Adp9%UO!#1 zervmGhIGa&z6|_#=%|@>nc;1vl9{Ao5Yk3DTgkTQb5xQ&%SzU6!W69fN7tzvwKZME zmV(5*&IJ<#V*%*t4oDd&b6b7@g2K(MRnP}p0xn1?;a%3_y2|B^gM)+A7Odt3z6J>y z>=a13GEh8_uH*J{*vlKlqGM%JuBZbe5*5pS_8!bMA`JxS*v2P2rBr!)bK>d^zmRhy zs1`iFr!QC0YpN9|b)18wfB97@Jai0ph)8ODe3>0c)b3?2R6fsQh@$6aa;)pE*G>ro zciJYb``5^=0xSg)fP5N}DOAIoo&cUKx%|N*DR5wNA%>6KU+0Z3*QL$|6J>^5>0u(S9Kiy2@Mr_G&#vLD(F9yPV$! zdEHvZZdyiLE2p>$_XbMT(0}R6#E6!*SxQpKlZ_7@OEe0(;rg)~lV*CKv5(fbPdlgJ zmmMq|e(8@xiyb%TbaO6Ue05Eecbduv?m`d-uI4>OQmC~WiXQBNZda?DSd*kAJ1Ze*fTb< zWNvh2kdTxZ{NSmTDba|7$xM(hL$KsfuG}w$a?rHIch@FUH08s+G=m46Z*Rm>zrc2$ z8=fF2gw)9@+1&qVjDYrThb!)Z=tq^dw_i^Ka;{1RGLT-sdKK2t&`@Yt>P6=H9I=mx zc=rJ<;8swaa^jo!A3jJ44)ff;je+2q+(j|qG8CgFD_Bn5-|%fYe$_fk49M{>A6jR` zW6d|wDK@_neiw^Ses`8z3yD*YeNCmOI5RU-965LNtRpU`88_4z;El2nq(UM# zl=zry9%3N+5(INGSe7}YoNMwL8pHu?o%Pw|_Sl}h2?kQ6$aApDUh7x75FTK8au8b2 zY&t3&2c0P7=o8Z;QVxoQ*<|8{(5Y*i_zw+IM1g?Leauc*VddHaDUSP)gC^`@6;(-x zF;OqvSabWO^@KC|9LMF$n|GW`^vjvRQxgil{HWrdJnOiwKF{z<3-VDa>g{K~2@ma{ zQbq!e%8N; zks4xXBcO@VH3Q%4y<(w*IMmy$g>nA1ldWrG`hSP6bPO1RdOBvKC>S}tys&kQLG_ioOooI#Jd3`m-Khu{=|({yi3>mbm~eQ*q1rL zs{>XxH>V2f>bw(fl&k;f>oX;zqcdH4Z~8?EGD>@ZL+S?I*)G~%b^R8~JbMuDCg;QH zf!qfL;f2qc|5#_aQ4%LeVE}x5EXlGPT;_7O zF6D?6=6pxiLuFE#ns%NR40F97&$;AE)!+UFbXe?8BBXBy zmupw`xf%Mr;9|Q#{vDMawVlb-GqDe9Xw0x?OL)(`!=5j{BgX0?Evs z%aJn?xU=6D4fOf-hWMK*4oXl;fcWDJ%Q=cqS@(~*8hSVndZYOmdv7LSAWHOksn4Ce zo^Hzi#o*FEVx6qr!QM4}VK>T+uG6V_@vPyN!+mcoxZ7OW`EHfHixsRgq}6`FO?MBr zemKm4g^B=J8Vn0`MA0Rf>8tKQKAb_Bb+ni+-pC8))EaSTs zJFxceaq*|&`JGrvf~{`dnAq7Fqj{Lmp)lH{TEw{{Q8A7vD=jN?F_IkH9TKGNDm`C8 z&&B~_9*keHNyoc$krR%i`94`CDNY34MNcqG)rh`MihUZ9EBI6sviAFSTmg-%Wj;?% zNyHmQz*yCxqVE4*U97k7sC+XW(>JK}XQ00vSiEl=S>oHK4dPGV zJalaV>k=H?kT)Q=9b3F#dy_B6|L7Ln=8@2HfsE8)ZM>WrhBt))ERIxQK|1id%j8+_ z%-58NrB%YE0B7>Qc*eT!u~xEPkqY^sEp_|rCxx$phv$h3Z5ne(-yzEX^D z2*pYKx4Kwwbwj%_cKngxAauY0G?oQi`fR>OHA*81shBIb8JU8$dEn@ov-K=rs>qDW?We^vqhD}NC#f$o$7ym8?Y1#FXWw=Q5 zOY+c<4=RZNP+a^t?aLk6yNw8nNAN<8%)JUyRyxvM0^{cH)5J=RUkiZsnG~FRV8;Wu0JLRAqLPxdObOUv=MgL{C@{Et)^dIMELFF7 z`w&7?2vCTZWDQ+k@9($_p)`Ls&A#j6CGwf4Pt<)yFiMMsba49TE|92pf=EvY+(0$W zf^PNGoE4cQhOfz4ZsH>2)1soIVTu_*4s!k$+@mW?Z+BB{FH>$9Iq%4>y%AIo&>)oK zkN`SM+#Y@zc&*DNaQ`erPPGk~VtRb=8QSQ|-yD7#GPYxU*yc1ICE~*L`ELZ4riZPI z(4iP&9)xPB8`LkYDcfgeh!`2UNr;QkmfjykRf4NEfPmln*|PN%M8$F5yWPE zieag*Rc>cA!LvssvU1e96$4)SIf#2YAH{w-hSEBVLK}VrzsjuHrUw+F8|(Upcg5J) zuppjP1m>fdg9WUg4)Bd_umy<1Ip_=l3aTpLdjZMC0AwT*A$tuH!(@-&>$$r312&5! z9Y*s7Um1VpHNB9+6#CS<_S#fg%$qz(Tm>cco3#`VS2JTmRMgJ?fM>Mrq2XteK}qQq z$kp4avG{CaL!}wvIPCuY)h!4GK#9P=6@pw=P!a=((FVO9%(IAvckb)A7xO31+8;S( zNLhYzKFl3<;13*KRO)-~uoUR0aJbf5-b1j06fi+Nntn&(A$x#9;PcWT7LH8EOG^8D#NCDRpt2Yy9llvqAXsc>+tC z&2Z4~`6{eF{#h#l(M^O|Xwn@=2%%^Ls=nM#VnebK&wj9s;CW0E(5+a;HB%UYFLMmiyKn}5o;O&AS zC&&%!>;+<>jEnK@iw?C}Y^SLgp%!Zqqo-b*@sp!m6bi{Re{m2k+2e7Y&#F6C=y@$? zZodnC&OeFC-ugd^+w!x9xleNiT7(BtrC;zjs=h0|Y$#p+c@&trH|P_Uw8;W$Ze;(! z!GXiu^p6y3uLST=K;X+05M4kBD#6eE`Y(+!$GR;91BP|e6c zu#Ny3$`A~e={AcvCJ_-z$d>>%vH5g>3u`Kk5aP-2U!6R$0D1APo(f#O#a_|xIil|0 z?XkR#C}Y28!VA1N2^ZyE_V@mmVpRKVefD2$e^xkVG4-TbqtkFJbCTh@ZjN$unKn|w z`s}AG^z;5(ed=vJS5fkI?#mCVC!fNmcsHtRQA%I}%5$X-WKYT)GYuzS2q?LvNgU&v#8{d^dH(2 zg#-=m?I~CL*8k+J`0n==?R-VuMe(0iwv_+mb3ig>ZU0^Z1uEE6!9#TJO7I$n4Czks z-NEgtSk?8rn4RY~BGN#&Xg$^PeQaPcmnEZ$Q_f+}%bkbrm8DLXKkgF73r-tJWNwqw zwuy%&scH@2S|F7ar0U&)6P1dHR_xzjkR=S3KT#5V`WqW8QOHDYkOn~P+r$jQ)II+7 z`HlMl&kTp2M}A|m_=a5iCATN(Yt*$)d=5UEx^TFAtu`u>KpJz6iOv5^TnMVQ@x7uze^|j?CI+HQqWy% z4k;-*L^kJUa*r&K78{%$eA{3Q7KwRth*V{^@xA&!@(RXBPA{ekjan~eE^Yem8zc** zK*$Lg@{vgbo+sbDDoI$8#t{AF?VYEMPBcq8E`uo94&NYG>NPY2h0S^EMI?cmnMZ#k zEmFl4lJDM3$j49tzuF%+(dO$bUzmB)K-%bM!nlHZf;y7K2dcgg`<+ve?)Q2##4z`< zi%CbkKj@8i%+iFS2A{;K2k#=5Z;QAXevU0(f2nh5vb)MAg~4F{t5BRSlT#=n?$o2} z(%+p;@Z)Y8NPih&hL*^dWAm_JmJV2TGK;N~tqrWKtN>v7#je3lwnVMj#=>P&QOCPl=cOy7rVPXWOpw5ani{chlgqwuPMm?UUe`dvjivvHDfsKwUO^oh|O z_||AW;#)(k4HBY$o*X`vi98e26gHdp-ntuQ1|t_6k0u>P|5jPZnQb)(U@nRMk-g55 zVvxuXnOQ&!dOnx4Ki+Ob{oE)fx#_s|COtRs#2{3h{_2SbM+#KB08~Umv?y3gpnM;j zcai!maduZU=lg)Sfh7l68Lr;0mJ_J2PK3 zvYsy85yEdTn(z`ojckNKm0h{*IfbD{Yp>sPRM!?=r%X*^8?bdPTXr0&<|lfg{gIyr zAyST!++^0TH3`=%;L%sNI>1I2z&khr(O^p`g5w#1gILt$lCSq9ILbBj$}!3sgJqh` z3=PG~M(eL#LtYw<^(~*walP1aUFBCBu7@7Mz1!`HK$;t^$(JU@RBq>1ycizDNK(tg zti|8!9@fBwzBhhlR9@-&>~|3f=oU+S39I|XabeHs6o?^KJP&si!P(l4Hdwp=rc% zO75UOl6$l5`d>*dQkk10rmi&Iwf`o#sJb3?w&dskPu;t!g=d?&U?7zScso1>5uJoF z)^2|1fBuC05*{}l1mpha;age;m`=2bm%M)oyK)nZ{9H{MP&b zUzqFlBKKU)*<0C>%-9;&#FhD*|NDjxv)1TODGt%4qv@l!_N+|bM%;Nib4-g!>n*2h z)kHj}iHNXPAPugz)XZI4aC%3lizs4Mp@dcwf?oLusc1g5(I}W z?CjT&>sJYUlmKL;({r=45B%+1rVrLf;3UsQBVJ1|(Su%K<;U`03({zoun+dKFq8|T zU7rZ51wQ?FY~0CiW;T}s+~kOaxVShkxGlsH4Tx7nI5=rEaJQx>B)Aqr0N5_6jM?E`xRuNbjG0Q5U}5Y$Sa1mPh% zAGN)(5MbfuhnYEJu!T5-q9cU?yC8<-rY6~8Vq9E5U-}2}N-n&Yc|0lbOTa`RGc>y> z?;CjG?PCD=bEyq)qrl8YQ_zDe*`;5h2IZn;I$M^X2t9h#--a2QD~W)~ZVsTr>B7hC zpdfEMwUxtWcx`Qfi$F(hD*}&T>>1PMn%P01K~!k-<(5J=uCx&P;pk#81@(zsGp1b=@1&m8+Yf4KDoD3 z8P;i$>>ZeaWDo4x4Je3stqjNkSnz3T9yvW&JqKk&VKE3!cbS&&K>nEi(V!CjsTP?+ zs_KU#XlT5$p}Wg~qhK-}dS3UN`dp_G$8=hO zpHB&;uqM$v3NuQYzh9Dc` z8A&JflnjtYKvF|Da^=o;FOoq-4*`UuB8A$VK-N4qG{l8G3{WKS;mZNv3gUkl(_Vup zLV=|KYSa-CrD3E6{-2K|aB+~8@w=lVzaH>Fo}f#J)y^Tmd2{AEG~cWpClA&@1L9kt zf;#m>-J<1_z&MT)8akTBJO|72*VdAlQkV$!9I04{HHV-8>D)O3tSJaSVVZyNqNLhevIKp_EMgQ=i_jgK!6nlM~ET$k%3r+7>> zsq+(NA{cBnrEYyqTnGWc*-kwv4JmZ@Ute<@Vdf9o(Ygsy#fnhV6Lm)4II-Ecd=C0d zNyIdbixlCw+jlhfO2>UfpOTVN;Rncq0DB6UCG{df;L_QjagR3uuszzdqwN@&6$K#% zg?S$WN0SIwZy={*3JFJ?HpK!f&H`)Kj2dEsj+?iI;UINmGG zSHsxkeCEGyV24vo)q1JK@eoqu9VuYGRMkNQ(NBfa)~Lp|s78yU%?QM36HyE|?KPteaUt?ENzh30K@Y5u3AEOl`y82pF~?b}7Y?ps1579& zk7L1JoCj$f7Gkg1bGqk93SsH%>s%>H-&(QdlCg?PMd{bx_x~~V6;M%jQM*GaB}zz1 zi6}@ZDIy&L0+J%#jdV8x(k0#9A>9ok5)vW^7<4z%`S1De{nx!~4a!0phI!9>&fd>{ z;;4B9)u*9>2j)N#%{IX_L1+k81)}jH;85fsl?stQJ~P*XG&Bg{+#Hz#(}N)-n-`^F zac#{tlZq+K*~8-^5$Wy>*BlGM2=ih?5Z=j;amtQx%7QFbG%Y^<5l50tKOpUW0Q*mE z0^`9wgtAjFR0{mAasTb@70F?Vf=wT=HQ`k4Boc4c)G^0`Qy$_H$X0>)3I5MO5bV@_ zItyLENYR_8k4tomi+$#|DP5FAWXQ-!=!md&>~&dOw>D1y`Qc7YHPl;>3?6iUp`JGV zTzh>*()3%CZYU9-jyP23+>b>qqk@^qNKNI{ozK%?2w??;#XaO)7GC!12;8h!oU%&r zD3Ht8E*V?%2R*S!R#cB55s1p^2!K|a4YNRJ@ToQgjcpDz;tPZX1hg}Nlzvbw(p+QC z02n~KJP;NMv?5mK6 zURH{#@h15D3$oSGrnuD?!E`ERD&<9?;1h0d6G@^&1kq0i8JhgVvo;$Oy5EeS8gmSC zhEHnLgW0}NG+k3%92S55JF-%F29;~F4=^XigoqM)z~?KNrGZL70qdm5eGRl@u$Mt7 z78Jx;X?(8xjo?DrfF%`e_fhgd3Fs30zP`ThL;G;W;hW$A6H5>zJ>!AKI4Cmm84RTJ zVV*z0=XOx|4*Y2hP+G1edYz{^wJZ>2G10%phzH8&o_y)cp5CK`l5q_|6scesjN-zz zM_BwAMH#`zoUO|&e1{*Z#f6ykbnT(4O$@{@6rvvzU!LNE6580QT*yNXMJE3hr~&4I z(kdw}-Q5#vcFXgbj+3)9_5AWOvG5ot%SnW&HJh=4#?^ZmsDc3V8$u6wa;MGuVeG(Ur`<;6D#nSq|mz3y!Dn(a%gYi-e zBSzS7gt)Bpn`CMAJ*%fRAZYeezifu#EWRqItY00Egnf4~@E>N4>8^xF&=Mu07uAEs zXj8c?h~ed%$0F6UYMxbKg!;Os_m6cWO)Vns}v6?UlBqUxb7sQSyd!K=dS*;qR{j#>(H9all zb5X8+^qAvZe##fMwtqNLPRnM}9DPp_fZ)J4YndBEK@p-lVn4%kA;GY|oZ49N*~2g`_N zw^pwNruXlD6prSDVTLT&4dC>sNsgO47QihU&IjQ{I<@Lsc8!C5eN%^^YP z2=@1&n5)5%iWUZ94kR`4Km{NiZ8(w>|2FL-)-9|fzwJ%(8f?tKp|Ae?1WOqPqs2L8 zJ73gtDS{qaiimX4!g6^;N5@=cGFo-P`RlKVefyPdC`$ryvLWdWFr@-k7g9eC!&u>H zI@Neb<0CTZJLt&7wG3!Likczhsq?fQ4jV9k>Y67J{oU@Z;{eC?4iM>XsJWGdp()LZ zuJF7!Y6e0t2m_uM@G{?;i~I4z{9~S?dH^ny-lt;p5*3km+`_oT{;wAt&Zc|`)n0~< zfDao;X@Ld9d0B80=RF0AkRd?PQ_>TTZ8Ug*SJZNKwvh->&o>y6=pcKT-Rn&)XBVPz z5`K?<+p|hKbGa&;c_b zdPKxcj;8O?FK3hGV+p4PnN0?pKL&x9hn>nn9+{gZ=H}3pB7dTxc9O1k~^3ecO6q3i``l1`8A>_y!yUredC`I;CCH}8~NLtqp_%$<4Ednm{|T1*Qxmz zh0`F`^QWwu@jI&KqChw$=auZk@U~Oq%7de=7wgb>(%rttJ$N4aq|NjYlG+^J7AgNi ziB;!lLPkiCK=GG?EMcEAF%8HTj6H{KAEK)ZAlQ*mz3d3x2i=`~V{`Mj6%0*UK+J8^ zs0lkI@KUmYik%8cQ}v&Qv4C)>Rtp)jN>DeiuguSX7iJ(jL(K&HIh;j1SAEZEwX%$y zLSM*m(Ip`vfqLIJyU;h_FB+{tlH;?RjjO7VLyRs zKA23Pycdcx8ITTAWo|nIzv((jS=ps0nhh1UA|k%hP-p&v<^zI}A-IDb6oh85%X`68 zCVDw9LA$BWc}M%9d7roVozF{fh-E&KO(qrB;IcJhZ1Cy74;nuAvbq2m%ie=hd~1P* zKtzevuTJEKr|a{=eRg>xBOlEh@3n7J<@u@7iM)2=ZqVEgp9YR(XE+=?0+8ahE~i}Z z^DQe8M!2?)(dhi13(&uPg=iY~a(4`)=^h(k-(>1VZokOvgcER36H4WI2j8Y-4w*zXj_eDf3VQk&(7e=TAH1`vk$JTVPI1_2W`O4w}FA?kp3U+ z`S?Gq5hr~#VxG8{zts>p7VbI^Fj48{(o69vC7;QpNdv!zn-lDD+cGnCgHB%xWKfT{ zxc>VIm1`}c1K&O9E_Tns&zoTW{>mG9{`>1yGDX*>G zR-@d%P_M>iV6S|67lmffi=O-{j1$6?2Z)nYD>;o-o=X1;A&+8CtDNXnt2Xt-n0<&y z0Gjed8w?PcU`V{i9McE&l@A!w!0ph`(4Y&|e?MH<+WhlO;~TCBc~>_#?eO5>Jy0Dn zA%FjdUF1+1uWU*Q@YHtHFMP*hLGYKUKMpbbfo`b zBna8AfFgtps_lZlv>h80(=-L*FLV-Is$&mGZd`Y_HXqI9L<-P?zN*sw*y=|d-{DNh z>L?>Gulf&CV=p;kMaGL;_mIm?Is8*ibZ|CPOnC9jw|F;0vNvjC^=iy(250YN9Fy`a zjVS4VThqF0P0`2P9#x=;IeWX1Vfl({*)0&yDjkujqR<9WZgZNfZxM*suU}L0@$qpB z0JR_`&w>|vXjaHgeF7|KPPQjcc8GnXmp}OW`K^FTwwW-p_rZFD1Oh3xE>{UBf|R^%n?Oy@ga}8YJwvr#GnYMHI}U3t^DIGcFZ574+eMOhO)&o+T_>W8P6w zb@fp6b!mbF@1GeEoe6S+HC+e`qb!vYK$_(tt*;gm*OB=ekcSB<++@4Aclv#456k%QTQiowm17feH5e6xs`IYnDMLSqh2;LJ;fC;+()Jmix~%jVU* zq99Xd8SrR`Uj&t(J~)OV2{%Ab_XouZ8FKNB!CSmPocg?*S*%v^-4^7yNS-AHUf|HskngKJedtva?BT0RFd*w(vI{QwAtl3x z$*3e9<@)MFAYvlZYKFlg^^Um2Gwz@qB0}KVO^jRffQ zaOX$Sm|=IQsWqZZfvk1%7_bPhQJKmp0O>@zOAs1D!9roBVsV+rn zuZNzxUu%W$_($j^Zo+;gyY{E~_zVDvH^3}{*z=94lDAJVWXA@9ZOez8T=oFkun3!* z=@e|vdobvDLW}8J_u1^?2@?woC6s^H_U#w@p`j432Yt9mmXAmlqWh_hqocTj0zNV> z7)00Z1HLvKD`1dTe4kn_-OXdmw{ZwXHf4T}^6mj6h6`@+7Z%MiY;JYDRK|1ckTJacwdJu1 zq2+PVDE>48MTS3YpJ3pxOO*QM{0te`ya=lfrU4c}?9kC_^ElN3c5ylk3#d_ao1VjT z@xwE#-!`zAIf{O6R6-ykd3OxpIG{>I3+x^*R9>IZujJ|J?iL+XcHVZ2UKzU`_ZU}( za)vAaO06PYv6E_uR>8qRZhUpL0N0mcO8(J=>GyiSF$TiXmC26-39-fYk%CnhgP+JlG#Z>;N%A zT6Z0ZIZ|`~Ggtxk(i68>1Ggu5oa8J}N{ejF?V>$CwP-l~C{8rcp7 zrNx-d3Qby(n(jB|GrshZbV;9zfmBjFlxT9)%F9#s372Eh--*RiVSrosGaH6VTQ0JQQdPQzJ&6>?K3OmW@BE#ZpT{G zi%Yh7ijUDzQ2;}W5*a%)(x@XM6`P0|!hV8Y0s9#%47BuRk~y*RmA2na*I+^XJE8$y zxD>J5U2WCFJ`a8t_S!(FdE z>~!^jTLd}))$6qI;K9HRn3;vG1}A%|*G9-(#=Yu+NZ|bJY~S}wYO}YOmY3PV z!A-{4_z}P63kbyHK|Nqm{JF%-$#b-sN&(iL7 z2@R>c!5Z0nKJx3=ITEm~OG(kF1CQYQRFTK{2yM##-{fLQk0J?)-UX4Y3h29ud3kxM zR_q#evX8`yYwfVneV@R1E26offv5>S++1BLNiflG&At1o5v*YPm=q1uccc|khEm{O zZ?A-fc@MHF>&JED3~?ujF-qyJFP{B6{lU}S)ur#WIVn7x#33;OyQ2iq(mrlYR{G)L z;Di=EDTs`e(*;;A2h>Gt@MaA_%(5&sG4at?W{!&(9w$_xiq128(hdP--u818nwKRn zIRaL@1rZ0;c3YN92XDivzL9zqN1#Y@pHfDwU+KvCj?qFmo@WNz`*Pi!y_z^OIJeQa6Y=NuQ^J-}5l3>(O#7DJ*%E-|YNEUw=k^Hmsv`UQj^b1&^ z+ek`&ZG=8Z)5h63k}z0IdQZ;yo%_xyvK(>(zjcgpIAVUqJ7M3t#jgQbNHBk8zSq%l z9k`OV{^KLbA>MbfsEoKIWBho=w{WxoMuX2DH7ij#dWxu>bAsS}|86Dh%^^sbwzenD7V%)$YV=#2JymQOKLbeXKpk8H?K@z7kp zRZwu3{`1C8@lKVT_xcnJdYzqj%5+GgNzJ%{62V#7B4H;SZ! zJ$Xfe=kPHu4o))zK``_3jRm_#1z^`Uzweins=GFPu9kI3jp|M);GQb-L*SdF)~~65 zr|<05Q%eSD41IA?C3Z=9WKYA6l`Dcx-N;inTR+=XrIwDkZO&E|_S)GHeEg42;E!@IRHZ~0CQFJkV`p`V=O!gE0MJGd`;tF!e6+9S; zw{*tpSOTSkdc9DZz_f z(N>eDx&kT${kLOhd;BN7ha0%{RMyNI#ZpY^a5}w)BNM*6p{dC!jmOL5W^}LViAV20 z*hz=VtzQ(#B+ZwM7i(vkse>Vd|MFo2FAwVrc#6Q?_tGQ?xY*ct(3_s8YhN8JfB0W6 z07r|->Oh&O5Pce?p?LmNcIrv_$GZ6X+ozGbUIR(hQ)*OtFxDf4p_(3;P0roKz(CGD zij-eb^SRJ~$Wy;TmHBT>a&i+&oh&+u&3ZvO3PMYQ1y^Xva1{HWC4Vn7jNNaI)4v=N zHNwV_ZjGR^>V4I6`ZqxnL0CdAhuVJKLVOwMt!>HQ>2tmj5l4FRH$i1Z!GpzrWR%lj zoIozx|0?o4EDtLHM?MLy^u|L*dWSmItMK?#)Ut@GM4R~G1)?jbz~aiCRg$bRg*Z>9 z44ifO;*FxIY7=|7bCKCTZNH%W?gie+wHc4~Ui+>$>pof`FXml*@dJ(@=4bP+9RfnO_Y;|e$r5Ce(~U>Ts{O$r2nM1 z>#uZ6+mo7bj?7j^JU+aec%Q6R2bO$9Gsjm2znh>W9=A}ulb0W%2YpmGF^l?V z`o8{HdoVMGa~{+sNI9uD)K=YiRD40;6zX`iKhxw`A|)i`gN?XR>&QJrZ2J2K0-6uU zeOF0}@p>z*cb30*V*Yx?#vL*u@M>*GIlKAmyt2o)s9C3r+S{JA8Oh5>eRpVu=|-)V z2OO`cgKxjS0@XR zC}4d+3Qj~>Toe9`aKffbeKa~V(=z>tKDRl)=^unoXmhZ-18!at<8@H((%OC1n7kY_ zN7z_NhLWqxNhNt`U+Zm<7%#uo3&cp_;!6X0trF+%x!HIsYB5{^YKC`0B`7NWTbM!v4)krnQNGW9X=sT<6b^ z$L4LC$C{WdKxT@ETWMTO1?YBc^!amzsdw<9N2Fss)_uAabN@tl&_}?VLL>oT4pTSb!T&?=~>2m0=%bsGS~f%ky&XJ@+bQ9FDjJf28_cc zTU9W!&kQ54zZj-47hu#_G2fba94BAo5Y+Zh(v?qQTlUrW(2180__iT-_^ZsAeF+=s zp$5*d(bfWJKu%kdndwtnSm>itk_Wk~!U{xSGt`#?<|Ku{31Y}uuKaAa+nnqK)36S> zg)P9)ZF~?`OaF5Uyj;b#X)v*AdZJz<`9inD#{n_*Rr&1fgHRDAxi{WLysh9^gv{WnnipS3zxY z=VRhfN8r1BZLwd8$lIT_lXNgMd#Za{d$Vd--I6{M?J`yFrQJhXq1DZz_&!4$Tic?V zD6`rVFa+BJ-B94pulgO%^OovV<`uz;T=8^ai}*FM<8hCg*Gbew;%lRv9XAKssDQ)< zzxF|ZTu652m^rod0J&mhN~p`|j{Bp=R$dqJorl%E6a@@E`HmxNh>(f*`GBTI_Hs!` zjA0%e_e4(_=xWOiZhQJ&@$&u2>g~wW`8^=dZ1UkU=0nhvMRrYmPICT!u9_P@nt3_3 zVL1huhz7bnKJlM*kbYDAs0!xjYmJa~FNh!o`o?Q0{6gUa2X=JmKU%!tT&F*mGarE4EfA}n_4m{5MWa+P2hrc-jHTy5jcI_Hl`lD-+?@stjQB*|2z`rNimtsV> z8k!cfa&rg$^hmpCTvQMzD7A*iEB{X4p!O&ufSlllMfxCYK5TeJL(^KIMTO)fUj#=c z@6CYBJ6j$KQqP=qz}gFWoup^&WY!lZcS4HB&5=+#3^;)H%1{b-f zBOA3g#4#r}%Gc(!CEv62DtYN8|JzQ#I^t+)@v$a`W;`6l!hgtKD=4KcjCDVcmVS`h z;(MdcOtsmza>~|w^uEx<1}DC5NAo42_>3gB{C_A)Y%AN_R6n2S%VzjWltxaB`Bazq zAM8vLQVQxswznmBA|CEWoqcQ-P{S>V@Uz+LR^Z%SZRAn8c{5N1==N_I<3M2ok8uo? zNQtoPRV6tp9YmUnUk+R7#v*6F4e5^wGK%y}zQ+uvEC~ZJF+6eX4jVo$PhP}D{9NGv z8X$LVMJW{x+3+In(`j*WOXVshZ*IIdCh~&WwFT_7arqmT?H&D+0_y0Z9K4hm zA^9br<$`6lyiY#Y8b9jMAZ>Tp_|e})no9b{k;0w(TUyiV`Ob%ju|G|^9|&NEQV3u_ z`0L8ASvE>BAB9_1Qhb|^H1XWD(nUn_aomQB2wSR0%B(g<&x#FC0(C6o30)vg^niq7 z@T+4AN-MxALTUi{gNp#RJ_kVGvun^y7fk4Va0Bl;c4&Bb{3G2>T+zA1ufhKEbjuc8 z2i$Tnp48@&0LWqvI#Hp7X zWNfA*GzvmOdDK@K_a03RuB~+-jLd}8+-^xvfFq&5u&}Tbf9Q>yE+vi46pd~)*U7S) zIXeDB!&txHl*ioRaV=~fJXs)Ms#C3~z%o`}OcH4jra9vDP{CqlMUcuk_y-U9zAi7j zUxkF#OdXU85_chLq$cD4OsqdCm`DI-pt zm!qJf$hS(jk#krx>$Q1etN)`=!2v3a6I7J4u{ECZmVIn42r6V36r`@&$7V%1^W8LN zNs=MvfV8DuIQ@2|qWxtai2@7~5^5?qdJ-vcIQZ?`Xme1bxj;rB%zk)1IwY5ND`W1- zrneeO|2>txXIa$ENigC8XzQ>4>JVTwl5!Y_$u0zvhX<(Dy-S+rYm(0yeF{-2qe%Jz zkW_NU#~!O*W8 zD6JiYL9^TA4aHOjtv%wA9X>@B`UPVuPKvW`E*K&bYeE|iK=7pDi3@bvT)iLWajmrL z&uTSOruGSUgTd2%sKM6!UYO5fnSTpf#_ROIKN+gLf~OqLeL5==@PK@sXM!kQpjFqYNOKniVxBpg%l+rv-_lOG0Cs6iK}Hx~Fq8qU?%L zFgCIgL=CSj%(ul=r5g}8ArLwYtZRTfz69uC5j=cuiG3>+{kNhd=rZUK0h3&)Cam*6 za$KG`S1C{rKf;U<0%mSU7?6OWsuAALTB_i zDW_}>yb}2$E(}!lg*;A|NForQUsiG% z^~drSJZHmKql9-dxV-HQd&cXWr4|~4p)_~1X*TL%Ca#j3xQW>665i&)<+(Bf<>&XL zNfwD1h9Z)93W|@j5nnMMV<1wVSw{c!XN~ySErB95vopagSb;h7lckQ7_F(Ms*q<<3 zi|+NFXIjC&hcRuE-;*ZL5ZgmMBbVWM<#z?5%Z+xb>2JOls@N@Wzp?`)i)C+jPE=lb z>F%g`Enxg0;C>F!JlMhtebT5OvIR0F4j1{i-r+M_Ai-LJEchu9bot*wejOjUuXK&q z`iz)yAxQHJ3xk|&q8DAyPE3}UNdneu$VXx)it8Kiw{|B$>1|#Go&e!ybhEo_Gi4hi zS$^k$?sGxSJ@}Nj{MS6L_a=$}7#_T|updfacx&~{F8SpHyfgiQBdAS}A?zz`+QrY; zH&(Goc?^WG*i?~k&HBEt5y7Te1LBDMHzg`}k9fC2d-T7U-mOM=&&G45ScSJ)EspGJ zAS$W_e6^)uBMbp71sS}>_1VkCg$Me=YQ(UDz7{d_)v&xf6^s4FiNRpT(>=2)fALUa ztXuJ=ZD4m8pjhNkEnj*Yw~?DUxD-SUJNl$wsD++|WIwSyzv|VVSPu;gEA8yNLl;OF zjExd`>OMBHCHR&}XYJxID*7kydgDd{Asze558nA?Mf05VIlff5 z(bAF=07AUiHTKe|GwhX2{))u7@NI* zSia#wE}r5#jd}CtP12qO{w>b%x|&Ia2}(!R9y7@udD()V&z}z<9&`?VUu@H?h zkU%zddF3AQk*mq`Yn|sAM*a)bGt8Oa-)_{r$$CQ)7O{i)3f!4kfU@i1@{Bjhd3jwO zft|HE?M51ynFw-oABlnNt2Ltkn|RCWK{?0ouA8iBxVj(iic(QdD4ZQRTf|d8CDeF< zXfcqDJ958d*}T|$kz<{3vOJ!e)BQ%50}D*Zz=|dAm683Ax%M8{g)g_f4IFaWn!xRNA6Tvz z;i=}e)A@y>(6`FT$Q%?ftXGOtCSw~Y4^^vLeiHYyCKHB@5$|4=?%rTGpJLUKRNjW~ z=-!_Qtp)(-x1Ry>XHLsROY1ugQ@Y1R%IZSVi^45RueyBUTd)BI%G1G zD%It?GoC9I!~DrxJrzW*RiqDjAnH&(=VsX)@S0rSDFoIz>j0SPGNjAqP_8W!O4qkR zoQ;Epz?F*r$zu3?1O^tY;6+HdXm`4^1Ae-(K|z?_@8l9!4Vj&-d-=c2D~*??*oABI zF3o=(J+UGF!7l7z$xsnfjzFC7z0Rub%Q@wHt;gbZ?$q||4z3TzX3RI=p6c_f>l()G zZor6{R|w~b$RX>sa^?SGzT^cD!@OVm6C3EE$jgNi1JZM4FaOj29#V)@Vaj7J^T@KP zGnuiLJ~>mM{|J4c5BV(g|NV9Coa$(svMor}F<~P1jz7+ac%rob|NS$wiDxGsWfc-5 zMn2g^Mt7Tk9y2q|Y}xZnwgDU7ga;cV7b{zL9?;VA9L35>$3*?4xt!?vC|D@+={&xT z+uBp>S+#{hXmqZ9sfYaG4U04e2h}h(xR(ki& zQ>$I#@gvr;q)XC21mKiKIVX$AMcnXn7N)^Bs}x=DA-t%gHr<` zxFfB)=4`&V0gaIotn>{qH#p*?Zyi@ub~~frxj};|#OR|@m~PY};PQwE1a9P`ocu$* zy(>tD*^FfLg#hGX9h)8T0(JO4raoWyQ;n^YR9!jnB`FljQ*^!8Mgr>E4DSt>bVDt< z)ywm40~71RXIkUs8WuSG*rSl)nM*Z3@IgW4OvqP{6c&;XI61os0@cEwuCE!mon`T7 zUp!L!?1w^Fh=&)c^8ji3-P?5}s`bkzN1! zP6np-Zg+(wLb5-hPFCu6qFSU`6ZxnG+;gK3?0)_i#sT?25qki|jt`I^Ga&%=@D!X# zzcYk@28b1REPWC|i;POVx?AT(H5xDLT^MP-EWNQTk! z@RHs|^0quF;p!aa-c&=@e8q^dd?(gg4^hNtN(>+VBek>ur$xIrqXR2)7E_mbPk#@N z&Y9z3h$rJwDBcV)M%*YqqjGc#rZU+v7a~9eqDw|20!!)1${Oo;doA>OFgS%Qwz+nF zYhc=Z3i34uDKD=!14wiC7r76UbRO{9gBabCSfrlio_ZNKrBG#fY8D!A9e=yysmR+u zc{vP!E^&D1(AshclS6uV&YU=ogBofs6L1!@5O(Xd&7SAn5@jm40V7@OTG;atvyxra zwCW8M7n3*7s?YBIAs}$sp7t9@Nd=a%7KyicNz-@$hiKw`#=KM{`ax;COYDmj8h{aIr%GOLWAPU#tmJ_Fu8x~Apo|SFIlu(RA1Fu@VgQ;{=`}Nhip_`jqJN>)SY4baTu1@jZ%Ru}Yg9&I$xIO#21Ft;Mn?o~A(`3+v zAx)wmCJb0Um#~YeH(n6YI0MOF`WOFJ$Ae8NMLjbnn5GLM&}Q$l=eWJ^KQ?L9O#fIA zPlvLqfRjSU$Y_25D`|$k@_Su)SQuxyZon4`3ez5gpb-fsq1{ z?V=yP^^teZF%ylrRl{3M&98NCJ&l$+UM>UcnKg^t8- z&!7cW{S8LQK8HeL%KMg0y=ILbpPGlpZ~D6q4GlDcRf{d>;_LXeQzTw2H_$joq**E2K{{!oMvu2avK_>q=(g6C*25$XGVe1*F1AlHjuR^0|R;?jU)S@rxwvO-rW%CCoeBvP*HTmwl z3Etn234)7D<%!peJ7HIYP7%$Q21%n?`N!e~Jf^X~PR97?!uzKeWSXqbsX%8Z2^MQ4 z62Ht^^P=hXTxZ6Qyc>F-?LnbEh()RR0`G6T}l^;+VO241OynENWGY#KL!M z^EYG%lDx>zQo!)}hS%ZvTRo_FF2ATA&D;q-QmxSpQH}^2c0frGeJ@QgYlnD>&i-9V zo|TC|wC2*RPOXZzsclyzW$DFF8G7%ax0%YHy0+To=K72LPGi$~F?}1cqp&3Nb`X_^ zDGR>34RIm^G@put%L)RVSTyP=j(|4guHEb;3lbxhHaM|0Yt_^6W+TC)E*{7pcbRqC zTEOz(G8ZH6G0TwjY<)pNg7>rnnp zd^bNR!4aIfvL#Wh&Y}iWxDwc%P$9fg3{~httJUVq7o6}b)$ehu)6-}l^2|Nj?&C{5 zA-b|6Qgh_`J~h?I&@8{aFh|$r{wH7yJGqVM9!Oq;aQg(C6wvUUD&&f|eFO z#408Y3lozxWKONH6E+bb2EZDC!j~oy7#|Po06XdW_U#soU%`3}qJQBNFrsg8SR;TV zV6#acRGT(VPB&!7ZY}3BgiJ!_`~tXaQWzK*c!D$aeg$;$Z$WM2H1q41hUev(W2&Gx z70jAfzvqR@rh;iD@W^3?AzdS5GI2l3=@7DdHAwf%lnB6`El+G73$FV zBKc|s!*QeFD&F5}>gtT~l5`x1#ql>J!gpqEcxL~df?qxe(>iWad-#CI*#mGJgKgjo z$Q$b>Gr{ z#FxLHoS0hmBrEJ1Y<$$qUfS7J@t^+?LYBmUg3FCL@cGo?b{~N1n1S(Bvl{zIbVJqdI~9#~P$^l z<&(F+il(OK7PkMF7q;ilTAO9!x~hTOk0$Qlz)BcG)Agz zzV@?xK7AmV#qi`(!Y9eMMpezPTr9?U+Qr@Fm9qK`PPEK`NjFAQq~z&79BaEk^~?qU zk`WftKB$-;BUW&YKEV|fC-=vKjA!f`bxX@OoUMZJd!9~H%Ujv!&j>5Ik1$`|#a>s= zvU`fi$-drDuVfEI8B3HPh~nM%uohGdMhu8nf!W&U=AAYst`KGf1M5%QyXKSy78bW1 zR__M;$DCIj%i#I8QVelAGS{w!5#L?5)Nb_}SU1AS$I8dE5f_u767xW1#p45iAX(?F z?@1eqMVxpYv#>TL^S)yvoS##?CKp$TPiOaM{R%ZL#p z9Dtmc^S7@L%dSxqT>9SB1~Ff!Z~aPBt8;CZ%p1*=DZ0_y{Y%pjrGu$8`TP{0*5oPT zyV10!1uYK3UqmkhgnDmMNQTFf3Y_ok7urkpICS-S2DQJD2|c0c50$!Ab%-8oOm8XR z!n1usqVuF&{_6n#Z^^KbeRgK;DjDZFk&7ZSB>^{Ac*~>})^PC<&M*afb_Ocrzwf=j z^CdoTUi|uT3br*?oLje8+)sAzLs9_eR18vWxjOfGm;7V@s=(B`*oC=2|lKQ~gDwrn)t_Y`AC;)mT-<4ylzu*=~Pj zNVe{6PRz34{83U_wVUH){g{M!R<&n(yuN zSLjpqhIjXPajDL-BLmO-R&Oc1wta?WXae>A6EsSl?cl|f;7rFKUcV#De#KNviTxWH zQK1fO|9xX%fzjs4-0fK6CC|VE&vWX5yVzl-D+^m*cD(@%eWP>)YHDjdH3nQcW5v=6 z{Lus3^~P*v_{y=wLQ1cN#Tdn$@Dvx(f^$3ajGV|ZUy|*X1Whs6TSeSTbMYcvCJo3qTWF&H4V@XxNIv^)` zHoeo3uHf^7{V-z!Gc+_5?9}iXz{u5FQj&6MeN8lFou8O-?7nD@VA`v^eeRQY08xdi zh|=O)+-s{T@T8Lh0yI#mT7Ux!Od&sTZ-?_@c77feOkRMB%a|n|%`LI^)V!7#ywed# zM`KC4Vs&WO!10SFVc>F?)AAVLrRK|5sYR-^n6y?<%vG-sJcHS;T0FDnEh5eFQVmTd z3^N5OaKstTSGv=rZw-_N672b$#b*3@1TF)qA_uBhEcJ@!L_wJeCQT*g5 zArhYZv-qo=WO<>irMgxkASt`BaCHRIr-Sb@srZ*D7waGrlNo+Ntm|zg$;%xix;vXw z)%$?qvm?C9y64$jcP4{Vk7O?%X-N;e5_ar7O6k7gWa?>k9^E+9WM5hMb)f6*N|h1f zoxltj>Hrox@`mq+b8P>>vV>a+&MRe2s6$E;ww-gZhE&KgUVo0-+GPUYuRZIOm0phYIT_zA6uu*0snFJxl%m^dqv%MPPnF#>;4ftpTVzp{(zQfg;GL7@jKgcn0Nf49@=y)^}A4uxpnZ%TuAWX8g(>YO-z%P#Y)d=`C_HYWXo?>mU~fTN7XW#$qf9Se zXh0GH*Ag_t*k;KBh>rNIA5T8zt$0MPpW02!-g~j%_4T+n`1|Y69V{$lI_U#>+wrC^ zNlPt==hoKxfXQP53adIB2Zzrfn%!F+eGnTLC(PoWdz|@d$^Q!9g^vom+98vHaYn_0 z7*P+P#%;4?Zey`hVl7j}As4|Kuy+jO4(8=_40x9BOoO{d*>nNArh3>aGc2V_AyloI zGOtXWZ6a_iS$x2wl|S{%oOBLh%c-YnF-yz zL9HoSIY!2CFNhBI;Q9Qr8DP0}z=;Rl8mPbo!`7%bN6UHBwpSiX#}7_J6`iO@iiz&a zn8gLDkPzZ>IrS*ZXz=7Uhg3wwnR*T$%a%cpjx@pDyIjfnYxTPEU7e+xwLfmZbGu2* zeL(;As{0!UHgnhK=r<1=zD|D*O-NZ>tb;4=q3Gy|jc#?e@`Cc-SOrZjY0w z`KASTJ3qeI`OCiqe9>c3cTG@nKk?&zTv}Ro+z&kbr*(WO3s&;CdXGObjcvRs=N2<; z9aw3<`~A0|(NLiEt*zgKBveWDdmD*astxCsJnpu;-w`Gr6_d_|oH8yt)3>arge@7X zrok}8VHJcg{7}^}H38Yo9Ml8gbF@$DBldzvR$S#gX`xqBwT?wyY#&4Q>RYfU_iu zk3_BQ?x`a-{eRR|^McX+*B4vQu$`f_%oIk5zX z4fg)TWVe6J+&&rk^XFSa;CpJ<2AzvHPEoUcwPEpU(axXD)kD^|O0jfIOjht=YVU{- zsRaQ3eg~qqD*)7yhz8xU%Afw;12jwfe8Bp z$mplJG9h8$J;V^)r{;I_hbbB3iaCT%)6vt9fwfqpNR~}~*_Ovr+}rQa?HQ21Y(}eI z6^Y4a+27yig&lbeK_QckC;L2njnWu}2Ftf0Ix$go6l9$sQu?}N2h>5K@}CQk(IF`* z88yb~IqmCGHUSY+WC-y0B6<==#n0;jsc+*V-+^g6x4mseLXSXtp^O82Ti`hx+g>OL z#u|o_xuho{ltrFMd?KMbH}~@)TudhLd^nQ2zPfA#fzT~YEiK?y{uf+E1|GgPN1JN= z-B0iJ_xHEe{L>Z@&5*Sqrm=WTRvLT#^OxE37=|czAejpLWcP&oUxpgkyMRSjiR7ue z*1%p=YNNsHv<#dTBH=qvkoDFV_np>fuOR~d1uyUNxg(DUG!a_pOYTO5@DKaTk*4*42;#L! z!}EQf-|O}Fy6?N2xLnuu`JCr@9Pi^j^hxzsb05k9eg~uNhY0_PH^s3x4e1ext+bM| z9XMD`zns5>VW!cjP_f&Km%5hEXYxi-Zzoh7C$0ZI6jUNbvAadJrDAJohST47X|sBH zWTg5-^_=v!{lBI$+x?$dM z+y!q-7(dwFQ`ZQGv{yFEE^$~2^)xF9PTk@Ij6;&BbmX-iM!U<|UyCY5()GEjK z<{jVjSF;x26JL2r^CdSYM;4}Z8$jVbde_4A8twYja|)Z%m&>#9KDc-KG>S8b`CMHF zqd75wZ{tUBg9j9>P;YB(Z4%rV)&~O}$fU;bU0qLPK;3>(`D*^x``$k<=rCwY!A~?- znaS?+eRn@fXUgfei|Xi@EAk&<={X_bFhZ1w&F;JzyI(~U8_K#m_JyHGFaTQ(2@&f| zqNSW~viWTU5%Wf5l}?Td*&&{;`(nk9Eo%nm$uOiIc-PK#o7}zfjEp5mb}iAiDon{bN%{-f0c39=v=eVU<%+e?VoTTs7qRg;bD zQR9dq+zdRgvm=q+T9;2=aY%KPNo-C@WBBSK6jy2MaEyX=Yf=!3kLY4DoW3+)9BasY zTK)w1y{9K2!A>>oQvilcyW6A+U#Bj2_mTTw+I*w)daY&XoY-E?Tha|626RR_!}OwbUt&+HFLoR zvD>l)vEjGVCsj*~Nc6W@uWU;m(pxKj3=Rec*wovW{!;mzC?6vtMZ9Y>R7nUYluLJYh9$r1!37BA32&?+z8x5EGz?@*!*Z z-kC@a`>`5pr=mHOUsG>h6{urM*G`6XyJTt0MgwL5ME&Z#NClYmed^)~6Bp;Z%Ix*} znx~Z;#qt?EZK%95xcot1(#y$tZM`-xHH)4f$Zzz%983x5?n?N;_<*<6wuC1J6>^l*q_E?uQTmSSu-M>Fn)$ zqotUWA{^Y_O%-a*iBh?oxutH5pm|*!VwhCkyLYdL^9S)nfYC&aonaZ`{zArXc0_S| z&s=cq;7fhUhQX&lTc=YnWpfoo`H%`!_>*u;H2222i%`Du1t3f?3#UX$*< z!Y9l+&o4YrE6>~D`2gHE2BgMh_80YQ^%jFvth~g&yeAu(I6c7lhZ+_ zZpHA093K%r!aY}oHqC;VKir;i{RO4k;=+P2sJKAtjt)kF?xMb#IV&qArKO2Yz;SlQ zHALPOP?PQ9L?FH)FHD-ggKzBxDPwUly$mF4ZPbC5C<*A6_!7Sc+CRs~2Lbr5n7}E0 zLxHBYHZC8telv5kFrWs4($@_F#e4eurJp=O0t~knW<;1&V&1cl;dCR!@gbQ+oIBUd zBEcy3d;$2Cc(>77Um}9$TYEJu^z~)+b(kAz^s>XsSP3qH@Gxr%n}=mbsQz1?@xznd+3yOg1Dx*@kf+WB>%)~D>OHTj zse>NW$~-%d%3WN=zUp!2qFh+UW=-U^`Tg&{(d-XA3>qVX0!HfoL|lgnB9#lx2O{_q z3|P!PGG(Tz$|LS`aPgg_aKA*3O^Wu1UE^*HpRU*h$}So9QAEf1 zFWYOS4Bfk0l!?OOaXKvDIi9DfHqXyf13I&a*ke37s*5f_es_m_MS_N)7%CD|kmC#_ zA`lWn6^{2scCHWpe8%?Bdi!V9+_ATaHdcOdVEO%@WR;f?s8$MOZZJz*+}(`;OFKuzTVTaLJ;DWNfBwei2?YVK*~o(fX&VfUwuIV3lqdh!P+-qix1kE;b|O?QQ&vS zRpIbBjCu82M&*n*y!B4sM32+QtZ&^9DgGIHdg+zw6xiKZiuV|oxF8pQ&oIYEgi6y6 zqe8XBU!vog+m=)HJ(J#$h1gK9-fh1HJbZ8)-S*R;fuO$``j_o!`OKgD_H}J!^GSfL z>4U^;CLN})`Us3)qyGlbhA8O!yY}OgUG*W=#{;%_zyT2Aowb$+ZuNe^ys44qo7pCUcEPKKw`@`btQfz^rbXlJj4$(u=U8sew+k7z1< zBScZ2GS{Nwu6K|y9FJ@K4Ha;%RXMe+-jX8>GjaXoxT?#GW59JtaVln3RypV4*gUtd zotn`vo=?hUt~2nWIW)LMV4_K`Ho=9Zc9f8s)3UoL*8Hdg6`u=77^{72)J}SIMCQJt zucHGFz6e-*;8g@0`iHQvb|~@T#<7WsPEMu(+h`choumu6Dw4EpR&%#Z326&n9_|+v zlJV}|n|RxG=unes2cb>(VD9xE49ZT=&#&~AR~kO?LO44EIghoe>+ugBvlj%c5z52P zR*8W+wkDH4YdXgZeqK4t%gY*w6Zt;7H_l90NY%H=xYt6#S@a&rM1DZKguOdg7eAb( zL>>y;RwxK5gQ5NRb_V{(JVFX7$KgA#1P1IPEvm-kuVu~)n}BAG#MpN$qSFMWI3Rd? z%`$Ptv1Yc4o|*R{dPy#7SNCXo@esm}21(zx1u1=zASREuUm|p33JTIr_L7j`v18&&x$C@SjU^iA)l^^xJb&*SG$&n>L&g zRWP!$dV2m%h%UEJT zF%b2T#gw3epH(Ufzv&WvA!JJ8gB?5gr|h}aPY9;i)B5fp8j<(P(azqi&(@TALF`#B zq~0~yQNvO-;iWzSZS8eT7>_2Zd|L|esc;v`hO zRAnZT!IiC*M#`FCwTOSAA=9qio^Q5)7&=O_AtqgpH2!(GZg(ljEB1*wthu@QQMn=( zn8c56CGuKLmA0;ADzMtx+EzaZy3J*ag^Bs(p=J{{qOxbYwioEmli?-BYX9Q`$OQ*4 zH!nuN%yeh)R0`sTI|}ap-XJiR4Hf3GIsT6_Gk9rE$hvG4F%-}&#&Mb ze^t*lGBH7UFX0F7dkavdxm{ffSSHEXar^U{6xMY~-I508sV5YDVx;Y8Lb);9<@bul0zf+JI?>-&z% zZs4SAaENn?2o2RYmMHL11NhK_K%yGrc@T&j7z#cYVne92Kd&_v0wkUU)Cj~r=j++F z{w;d}t&5RRQ+uK>%*=}r=oX-Z6!yrD^7*1=%e(pd)ppe6&oZ8eHc|m|{&3#>=;&Cn z^7O1{qoH}J3>tuQ>w{B(yC*w_hY5gZ_d$iZ`LNY^nTQzuaW#XKvxj!Vhs=if#KgQ& z>k5GMEM67KNB90Q2eWHAN(u^yLX`sMqvW5})dzfh@q(ZwYr2_`z~&wU_p>WNqVM6Z z{jHRn$nscG1~;h8=|=#jzYpL6=s}G~7%b18r-RqB;7oaL_V)L?N)rg3E57Q=jvKos zs+Eg2#4`IMB?|$1pADCqYP!Lr%5s0H z{W)w_0+`LydRsnCV86bqY7hMgG&U23;WDAGUcPj6f(z0A{Q2|8PRp{pV7`(HVFFuN z&EJr7!Ffpxh^ggjW<1z;(}pekV3jp-3kufC$k>1(!;KVw81z|LARnIQfB`5D8F$WK zIJ?Feb}9^5!EtAOC{6MVT%=GDZg1bFK>-2rhVUEkz%&CaxNaC>FJHfYJ$iU}XdOnZ zaG#2NvMzgTGKKD*6^f`OT~JZo-7oE{_fM^aKk8AzzGyi|(=04N<7A7b>gB=e=eFhB z{9?qU>P}Sby(cezU2K19WbhG22v=9X@~?QGlOH;Wz7_ubf(dU|i7M%AwQu`G==-!u z#sfaD!>vW{fc)~hN28lRW4(Xg#`ygAPkiAO-^+KASyo$Df8vveA|oyCAl!`~x^E&n zTm1Zx6AZ#tvQ&Z;i<&NvBM~WL2|W4RF^tco$Qv(CpHw+wds#~4j9B-GXa+6meZ>_|!be;P>k0Q2mIInbrLpvyD zpaG4(rn-7rP)KOi+|=|wkn_NFQK!y@6~^RXs8@I!M`_e;J`wS?GSb9!Fpfe=t&sy9 z1XDILe4>WkLtBjS1qB5BP*tZ;-K`G39BbVC>*Dt!Z`>MUsv&|~#_}Ce6%>nQ0ABI! z07qvCws$ZP1wqpzDsk&>!C*iw65gj0)Ml|fS_^t{PCr3w(ebKu`5J_cP)I^^dX0sl5khh@S# zdgoQe`RL2mz?WbmR}JljIFXoY1wwfq#%qI1?V*ny7Q`o~ruuV~mb+V9e{TXA_&3mS z_KuHb;NZ1DRvkZZC^H zK|x`8nP?FE=5z;xX?z$w6ql7r!T^Ycg$0<#SczGMiqUjonk!h}%&nXKkVM&-3~&d< zZ4-&Lh|Oh{l_W*5X|}d0#WCh4>CpSk&oBaL>$}Hk7T05OQq;H}GjEt1XpQyrr({_! z`IE15ZRATAS5=`)uf_Sa|2s`X*?LGju=aPRF-zI@i-HxWvHojqlBaR3NZEKnxORU5 zKE`~euD-S?8Cb7-xLrjupz+r@5}hBe>RlFu#Xw503fdBq`0dFPpqu`SH}s^DAMEpOp0v8_R>TVux-#h9T$3oo1A>M_%h!LR~)GB)6Wpp#?xnUg|R@zSWHBH){;gNE-g=JY$2)l9MG)I70=ZqJSiNG98 zFjnJ1fP|nHw#qzvO-D~} zF5-1QmR|c%RP@)_&Y5wphWku!FLO3rJ!+`CAxdER2uhN5Nc}T`5>}_umK6FGsKD(? zhmFgoKnM*TDUd$hfK$3Y#JR8!H&(C|a+K^X;!rb)iVs2VW*qYGHS=ptCm@Kvo$@6x zvJ)*{5-A`sApn~u^)|8eFugUckRiHg1S(sEN(qk4@J!HyPVg8zjge>bjXdE?B>v1~ zuOmvlAWuPoR-{w&DK#2~k+8^v8-0AVX&jm)c~W9@D8dywaVhaB2;a^2^~H-j{&s6D z+>V4u$iLX3Asi0Pz6B(F_FLh-t-)T8+hq!-{|@}tjo&Z_p&W9%q-+jrrb0H(Zs6=Y z+P@{7n|WuhP?Qmg z_*^BkR~2Wnn$Gr}Q_ra)d~0H&3%NGdVG<1N0optHvlBMAUL+&17chl8Y))0!R3`IxHB?xhNf2;m1BZppnP;OqZIlj(D^r+8 z2+B`6SL{@zYCgQTasKm}<0bM1KuHSVkE^VaCh&-vdGj1*T3U=-iTd&sO&X^IUT6ph z4aXKHMv}79(#W{DKCVpH6|9nbHL8Dbz@oh=r6qFy)qoSvW0) z_-`P-CESrPA4uR@z3m(3b6i0O4-6eI0aQ#+!BWv0(be63<_Ja8MMng6grWDDnU$X2 zG^xhCW?d%~Nsi}-R*;6aZ-Y=_(%o%8+WfhClXsDQbCdvaVGc=ST)ff->OY5#F-G9@ z-_k6H{D6sbIEgACqmdkFz9V;=AKr191E9zD##~m9+iK(%FjCk@)?d$A^e4XY1Yn{R zP6cm{mp=mP9-4ro0%J_OG3yP`S`9s#F)*_NVdpwVb=U!-dlB%Hz2F3k-2!UV$E3$5 zGGt1lKCv}d-f-axk&%)2&W~)MZa@bLNj!7`hR!Z7R}djV1@C8u8E1kvKpR3LZhPW5 zqtok|U|f~J2r5b(w3|ekmKG!+N5PQ~NjsQ8kbyuGReHS_VT{J_8$y(Ajo6|QGBi}8 zp+TAQm=D?|oSX;~>!$qD8BERS{L^zBo^gi-;D#$H7Fy8U`6`!>2%WJQap@*6PicPn z%(hXy)^YapW2Qv2O}bzOG}2wPUQg zG!P-fvc?vab{lN8I;qpnNH|HF)ez3$g+dE^PBzyXcTE*B?r#x{Y$tf?j4k_V&GK^n=xF2vV1@i+7VireP+@ ztG|lZHwzob`V+1Ym~^zZk0P-oba1-=x<>@RGryeIgb#rJAw+oRE}x6&e>{rPOU zvke}TXah#J%4J+aN_5%3B8D{*#1`%Q-iogoE&9TB5%Yuu5#xxj7G-lD$7_DTL!c0K z^(p;DlRE`YZETtkCi$Y6c%_3uha0-$FXYpAS@3ph7e;3~Pau@8KAyP`k$`_-$4 z%>EQ}cDwy6&f8Z?T6%hV>q*XPw+|8^F6~#h#Z+E50GF@;TP?Y@j_+rHmVaPpzDbM( z5yx(L6_}nA3Zf;0mQugg#aWi;uFy2R+Ph#X5&Pr~7V+KSYrazpNUaf^p0dz^AzzCT z{aBesFz%j$e8^!T(`NtHFC}r86D^ zxI>sJCn+47zMuG3us$d&D$;@4rLwYeV0^n?JvX_*te1EIZq;GXcqn8i30?NSqIti|Dn~v&%KI(TK@?PhJj0R|nH1Gn8Y5gZ?Y!)LWZ6IG#CC}+ZGR$uKT z%(QXVA6fVFkb)N*mv?1tK2zX|FNf80c9Vv_0zaND<>yoBhDJO2h*tIf50BESsDfrW z90Z7F=L|S@d#8G&=ldQzTdny*wsW$Wt6u6oYS*)(4M(@T3v#G20sY1;U4+YJ3W6it z$A_;q_4R*4wQV&1_34_X@1t1apYK-x{7KU&ib_gK^3QmnoFa_Lt0cCq+KMETdRJSr zX*|<6Jz|^2#`M*nEDc!)zQc#y?oO{<>90oiyRO9Pzs6|>_43(H4mm-C`W%cA7%3ss z07hSsd1Pc^fu1q^0gNYL%SV69t(4li8+3c^9cKggKx1Ie-#03=-hly8As|Pv=#^u1Mo^!iIF!X**aJA!2OQxq(^IYF zw+pH*uaB_tC5&k3yZYVzgYYCHlaf5D=+7W`O&3hMAsUn!7&>SWEDEawES_(0HHHmW zlS+-ugw(`DJxH=_(Vh{?NV|*IXef$;;pZ=aT_d1d4LaS@va%wLEVp7Ujy>>1m$|IH1^m()Hdqeg`SI_2Bhs zrkU~pvZo%Cg#nP>bBoDtUJYbDu@FAC-DX_!_RY^5x9ppTT9^S*p)-P5%czSQ$c%6M zL4Pw1@G3ei{oQUr)a8Pgb2`@hVt6-7scU$Qu@p`trp)9c{I$ z^l09?bZTn~w1j4Mlf_5@k$1sit<*D+O2Em~0xH3$FhNy?JU5=3M3};zbD(GOdjj1B z2~?aeu!|Ab*49d7kJ2zQVuEuT0~T=f2YY%14Wc>QzV?&4Y>o^!472~xcip1O8Qa*p z-(~cG`2negGR45h5O=S-ulH?ql(^p{ZlzVRQ_ql4-yP0t@KG^~njk=?!X{{t_7wSYgsuWX2qPEknxZdo_FkL^9@2-Km zf~Kk}g6%6MwgW3Gt2AQo^33@|s11*G%%HG1En7w}G8QL)&QDpkG{k*T0Tey2*ugL# z!K9vh-<2u|7Le9p{z%fFD(2G;%4Y4uojH&9;`enloQmISCVvo9Dtph`_m5otCo-AZ zA)Q#J7yhEftLn-}7^PO|AXDS6bxq|#vk({U|^u1}$ z&d%Mit}ydbe`L!m`H3$8#^m88KTUqX!s$1Q=`AtvqE`BtQdDjN&5jPndgI6r1;O+| zt?SFXyQxv1K1l#H*9EGaE@*?hU@Po~UQ`iEk!Oe;n{<$|B6}RJr49Bl-dDpUrDLHD znXM<088E1obJ-P^5#UazOsjUiVlzM3bBAc6=-RgxRt^Fa@l_eHm0&vy8BBv@gcAOG1-tVAV`=ZIG``^`5 zOP3`F{-3^ij|kYFz3>?{FH=EUGidd!&C$qf0s8ZuO!c#1_#q?F)Lr#>uPT^6cDB^* z5?q)!7*iykggYK!3L7tuWU4&pq4YwI5aiya+#IS`dF@Z^_f*6Fx%*}8s-=d=q>CK_ zrRJE2=4T`Qb249hJG8+#-va%3Hs;{rYA5j~Z{`#vY~-2= zmvFtknLog{v<;;(QzAA)4w**j5Oq{W`dZqk++@qQifX))G2nr9_tKd6)l4*a5@V%9 zu7(K;6KNS44dP=iW9x%L_Zn;}OZ{x(Wi+Hz_y)*{T;<{}v9Y@;^$O!)okl@G;-~m{ z?O);zJf^?^pc57S($>-O32Li%*RMQGoJ9XPoyFmaT@C?n_Ge>+7fhZEmo_)^FQ9z_ z0`1c-NF(S5o`W3Jj6A^RX|>LKo4A6*kgYuf6#M zU99P@0k4OtnY*SHp>O|hhm~@>IroR?r={G5&rmkjE#|g^Qy&~TeY@LsZJcrRYw;3^ zWKm4|@2=A`q4;}Q89W~>DW&&WHU=vCve!g*J?_NHzkwGcPzW$eFeELpBkBaL-F5Z# zuhX^i4Wa4}$kWK9RukUvEaa&%_+F$}*toR39P?*w?Q^<%?y)9*H>dO{+FcT+`cJ!` zgK+=zT6XV!_6^jTu0XFw_@YLtfBID+>vMGg? z#xAp;mdp2^CEngu#S9d?AAL>K--OMsCT+6J$?`U$N%!>22@Q*gNW)Y2bC2z$J$?a! zw__JXW1B~=02>N6qUZM1zSuM}uChf#3%tf9GHSE&9BxOo;g=~MkfKd9h_9E(<4tV8 z=c=LF@vNeM^*Z`QD9lYb?Mf({6|>#0e8aXJI8`?vSGU;ejb5}}Atkrf4Oc~*eYDI> z8%#X>mZNlfi2R?I_L2TSe_RXnt1~4D9qHB#R&2DN82aT}Sa6dn$wUvE-u&@*Ub(Py z*x2a5A32Hg8TKFl-{(2xybNE`H|VZ>^753#kDl$-x5C+>3-eob(bV}<00RmD!Kfaf z#MHX1j)Qla0d+)>_^Qje#2w@P4`PHW=R<|UMF)Q9vxg%4%}?+#LU_csM!$bgOnFEsm#o9$ zjSvTGcM0HQ+<}z&e0o97ge|RZ7aD{VWWK>m$h3OU(z%k2MS%T1 z{kZop&Kg?J&W}4CKkWRzeF+;E;o>TraH_ea>?fdB;+7uON>dGhp+q^D;f3N$e2_?! zMf$3dKOPK#hg7CI!Dp&=lUxlZ5Vgwz$B7n^3Eu!)KX6w{L7)w|CIMD+Tn+1g@4!)+ z{Q5=C!i{3+I*}{%=Je>JkAQLV1enD~WE@5ag^b~Q5Mg1PlAN3c*?wv;bz@8&q-F#M zkK>)WO@mnTXme_ezP^~kGtVbtxf;aWR;rJR)VR<~-KH%~va@h2!^o!<%e3TW948C1 zh@`_nrodZQW%v5Kc_$eR>H{HUrD`918*V}1Dgu!)+=UM9;1qOg0Ei|a6h-``vPaFZ zZXp*>*&>GG*Jx;Ik>Ok=xcRY?!a_R?-@v}Y7C6_MoA**P#|%=WYVstNb3NeiPlVJS zh^97O!6s?f-``ITTHN1&g`q;dC$6VQmJ%P|d3=1V1(p&`K`lmmTwGkt5T>VY#hnw9ShS?2iSY!t# zH1Z*I)zeM*mp^0|NwN?>faVoiAOu9BW+R%@7_i_Ih-~Req^N+V?P2O52v`x#jKe6Y zgHK&tc#~67a^VN{kJg5N$0}!E+y~zK=bDNCyG+)~(l3^&r7C_~zG1-}k4@os&4zxg zLWAk(2Cr1eR9}SB{WZj*hW7q>*ZZdwJQe78?%^!Kj7#mGPG8~wxB$R5k%yeWc?(n1 z*&^BpLgWdU1=8l85x>i(%UDvle9N#cKgIVf4c%hG?0>QTR4)3i@>1@_NX}+a=?GAH zPhiTXX+@6^m-_j_q-+pudc4NQZKaJ6N zX#e>L)KiNhIm=dcplN&bUP@9(I!l)nPLyi)mS zlk#ET$l}4j_)|4kG<~X)-}k(E**v_y^SEV+P%i*Tg-l z%vL`bSk`hxZ`(hRUEZ&*Loz+yoeK?7QRJ-HcQ>}S&N~4Jud4jjyl5G4vdZl=&uH%T zDULBWQ6;4_fRXH1*nScKqnrPfn7DEKepF54|F$a)!Emh#NlN%0hPT2m;%|rskQkf| zUJ&YU9y|@l7ZYnb7|zDBIALSydxqsU%a(fDv(dR8 zQ{MULWJ$2EsbaILlfvuH-yeZ1o*U6Ll4$wfLXMxx?dN*v`UyWmqnUb>v+Drh*%A=o zg?&H5NSO$(utth937)uii_2XrFgbc&5Brfd7(!zC;xxRVo(Iq5Q$T=ll$DhJ-SRC7 zsplxG1}=D%k&lxy}k)O<`3EuO41C`oOI9FWgEqV45R_>I*~( zyw95-{(E*JM_1&g4{FMkpL%+W@Fs1O0=(r6+OAG86jiV6gQY(U0ms{kmI$NPTAsrpOfLKSaJSjBx8N&g zW3#CsgAyb!A5PzA^}niyybN4uWP>YM5FG#@dzfbv^uIxxir_b@_{|c}>cbF~|(+<9%kXY}b zRIGbB`2Am@_MdvK|2olEn-w$frj^X>G#WmsA|npVEF#HKBqY!C2s|?G!dd)l|lF;XBrP$pco?Q)8d4Ay^?tf*YQi%R#v1Y z_V!oxw&`Z0S9ZxW;pZJcxQZnykKW#B-6Yc7DnPs12!p|x7e!ThEyvqnuQv)7KHdPd z{-W6#(CS^TBWE@FUa)n#Fg9J(-$$f^D8JUH=%&@XO+0h$sP4zl__PQ&oGlV*D|~2T z@gaSZ7RtBLj8lp3LcX|-%_1JBVx237^ny);g<_p(tHhn2-}|C3zo`1)-9n}k$M{A_ zgFx1zEF?&6xAw??HUHi@kvC-p_b|837R3K`b#H$&-rc=M?rSBwdA)1>k+2G_U_SqXQraS=DmCVHkR2XwjAKKiddK7K+ihf{3+n3F zdIiHhweMkZ-7+?jccyV|eDnQNB89#o9mw!DhxsY5X(Y|+01X#*_br&W4@28}9Hz?f z5qYSPSC2Mo%}<9V9P0PoWoZ^-F>qaV1ZP9%sn<~GD?qe#muYFF{Kp{_aD)TMhB`(G zyz)~r)vf9k>6uf1$t#`txUe*eAtkMsv<7le3MUz4z;!`{SL48=QkH-HbZ^QUy!0%Mb3G0 zGrjrJRPP-Dcf>0?GV;FlTrE#hd*1McR6JCk8NiA-0$jO+_a2U$r>$sPTB`WH3Z&z7 z?t%Qj3fstn-VQ`QjwY&3L;mO?_9}Ob&$!dNO10&6@Fw#HRE z|H@spiTq`6*TVdvxb5u6_Dl5D)m3@X;c;21+o2zYg-X>je!-Qe)c2c8NA&5|zFyA( z%vGP)a>!`O!+qVb0a}Bp2x_s)H%?A^s*?Tky$>_hr|bYN=7JD;o+-E|x-W(JB z!+{I5s7qtWS`k1D)i_&F`A)oH+r?PCBXNmI(||#ff=R=waP>;9^pG~-HRDN@ba!Ru z{DoHfaQ>x>StaB3S;{pthhBr~tXBR{At8sQHca*7S8oIP7iX;OHtq_GGzKlVOMmM7 z5VX9Q)o!YX-TQ9w_MT*a1PKkuqUhjB(nE=|44V74pFgWqfj56^LF3Nj1jRTfI3o%1 z@gu?MSUcvIfm4m}AAnfsz&S*pKDrRC8O;~S4q1c}A2Kt|jHTV-m`e!2PgiA-&rh6$ zUhfF_b_Xy%QHhZ^vl4_muIMvJlwJV+cj}PoF&|$97g^XcOmo_LdYDT3`Y9~9$-3d) zVD8t~^n*0WT2JuQsR8|C+m9c#nTqEj@OP^n9UX+=zobsZ%EF=!ym4tXoO_Yajz0s- z?AuL>Ft=9?BWgln;kFbrbN+w+g&RtBkg9Z6efm6>CUDJ_1NxqqD1~PlVR=}4Yz$gb7I;k*;bJ`cSLti zIK?%g?sGKiUeqbPR$a>_(yO&fP`g6;G7h~QwF)QBB>e!jwAHl;29jO@63 zISPEPuiloFl(dbGa;5g0M_jNc6tI223>cbA9rdbjBi-$`eG77_%w5PYge5&Tomlwf zpWvq-TcO_!cjGjFJpckH{ngc#DbPH|=M-XuhFmR1v!1R$@&724#4ECad&v4&hsc*5 zN@sf9~sC9>N$2zu|=nh)|W!kGB;N1-S|}8f4uE$H!NP0K2)u z=r(QwcHlpNwrY-P{oVbb!Su#{&rVjJ;uzUs6e|IDn=9kZ@a5Md}8^m?~2aq z#QMO|*{tO&+FnuaFcvN@J&X>)>^}f#4pCcMwxvGT-Wi}^Nduf3OWZW%Gk_B`0r(Jf z1NmYa8icv(%tRqX(6aRO&;ruWs?I=^hOpIS(ljtNrBllvzne&!sh)5EOcV9r8Y;OO zfz(1Sicc|UAmOoXc2*eGclyVVrN!Vok6s7h-^l+H?LQ4Ov9Qnqk=Nr9UgkQ?&AdB( z6MXg3RB!FhHyPS+lgYWcx#h}f!2JI`(6>}?z9J@4Sg zom_ZWxQgFWrFAQ3GfL3N0VHE7Xg-alJM@{{3v2!;^pj#tKsq=Pi~<# z-)Fsxp@Y8^KFm8UKPm2EF0NyI0+@R7SVu?J8gvvgDaua)m6C(N$r&4<8urm;v@bfW z%r|&w!(v?r0=fzG9yg0X^_OLooxvw>cVU4VtH8L<-~HD%>AFVIVfKEe8TxzSQF({6 zkqrUKsZU<`%=`B3vh`;2)uKj+?f7?9QS$SQ%q|ZH*}lfUT9oYk7}Rpo4fLq)^YPxU za<-#`^)UOEWs3+To?(_y@%wHtt-S37gi+|dkZFlSP3E6!L|krd$nw^?+}D3@+ZBuJ zQ->?cYNu9|&nzbTZ;?RaS3O-fv#^{ipZ)XxxOnLE^j^Q_mQz-y2hBAtD5OitT@yYNvAnCU>PbUm52ZVbx7 z&891DeH7pTnL{hFD8Bk+svPeD#15G$x4I(?;PN{N6^{h$n-Dx|Vfw7xc(y`bYB$5n z3GrT@FqEx>?ul^Xe$p46Yf?4k%KeW*BVE{bMj7(yf-#cAJT~@ z4&N>QJp;!&;LgFz7B@Dg1zU+ukVg;zSIRL^mM#Q!sA#$_fhk-T{Fks{98CgAf%yrU znSUPKAWyzv?v6vsDOC)d@($?UX#`W0S@1EM&C8g_fB%JWrXysaL=M5Te|xkumqdQ& zjz5$^Ye(*l`S~_FFc2>TYO*5`ZU6%P%S)ZLtPPn*_wm2l#u7`b4Ow!-Q=_+mdQusf zG%tY-e1MCCvpm=2Lk%mBgDlJwrfJ3S;5?8Q!p_dkO$22HM+H{l>jwDZOE5&egdr_= zRY?gZU^|{Set)e1oSlNd!4bsL;uU5wMcqb#;R`4mVqoR~eVJdD)x9togt&~k%w$IK z-Uqc-(Jj@SQA_)IkG=AjUQdNWXpi!{t%3VX2>E{@Dj69WsPNnh0MG?(0tsB6Z65Ot z@4si4;ox(f3?b1&+_w<{?RnMhAsm}%!eeOPW$89fjeAQFt=0 z`uBR@+0n5Cgtap6?t&0emZrfJi>RGAPb-^K^Q9<9)nPXJMl3$4`!3$GKW2cviGfu1cd%0k0gDjTTgAQD(k@sArtocJQ#I@Bh$kAdN3Fl=mHpR zQxR%QfS>0SJr46Y#T3E2;GOcWrba;K<2|*MDO!T&eQF8Gs$H0gwROpaxkos>dCqOM zHslBpT_;FkA^%YA#_<*M%7;2TI(7=|G{+(DCJQFB8TDCg^zFMY zLG|&i25zfo;I1x&II_vtMfaB`kO)AuJq*3&>jvC|kmhFbw{nR&rn!~w^P{7qJ5b?Z z!UaG4RbdkkK=lJ=W^6dxI{<(JV-yUU$x6E)k$)=VfY zRrwlzw^sIRZbdYC=^%B$2gxUGY`XkJIz_EU?8_1=AGGblwAO$8aZ-bMD^Lc2$^pqR zLKZE?CEkU~*#$4%LGB|gESv)iD<9woCZ>NWa9n{c*fTgXD$l`M`kQ6~X-GOKt2j(L zaE2ixw$IMaZXc+AH)DLz5P*6Ie-2X8M+i zwE$T4bSz3fX9o`fCUbyYnHgyB*_^D2Sy3@D0Zxkhg(|ip2lgur@7>zr|&R^OHsePY-(z5{;qZLa%Xz! zuaXTGaM6U}-pd?a|0UB5W@(~x&k%!WZWg4qf_K|;g0%9FPDe9z5vcN;$RP)fe+B1f zi%vMGXa^DHR7Q?NCApNVmO71Ox0KTSglNW3E@=^{Ysp9({?6<;#C8`dD-Y@DfFKU| zYjfSG_`t8H?l!8HXq2;x!=8_}7zn-o_4Cck_E_Hpe?ytum|M}^LsAv!*XNe3s_HY` zZ5pAS``-S(DgD=1S5$pkPyNL4F~2@fQH=ZO<1yd(@2GD(REZcz8lip5MuE%r-`M=@ zh@!@`vOnP7#r~_t`RPLDaghYjvW^1u}NrHFX)hB4kUQS=P#Eky}~rHoMXe}SPYtTt<QU!omv1 zY>#&5=Rbn4;oCXz*`kES_9Y$az0A~`BmCwSfK_VB8+b*b`@cJx!EUyQ-qiIFhD&o0 zNYr?BZleTyj0NH`f(TeeXQE(mT?GPObi}E~n_bOi=^ir5XCu~ijk)Ie2I`q6mJKH5 zKmhl;8+-U|q(ROPA@gC9sBMeW9GjbeD)+1PutH{f5Dkn80EpGff1i6tGd>Zy#sD{0 zBLqUkfa(eZGj*<;udu~q!#`=Nr*)R4r)#Tl-`$Sk#v9a%=gu|DB6xN#{ z)>O=&EWKJ6dwfa#M+cU=EW|JxzwujxDV^gBX<7o{xas2(60xXJNm2@+D-1Qq;$=>S#|S zrFxSP`-e#xv$s-JC?~x{_r-zx8 z|jXM5eRmfk=L`c>dB6;EFm)9o% zsd}nJN8<$puh0AQ}j5xc}^#h(lFS)`sy3YXZ(TMiYM5Q!q=#>0e9gfL;EiF%Q#m}d0iuU2=MTY6Dxm_|0&3;3o zc5D5OwYNB&({PpsfY@&_#kGg{mh09eK>$7&(tuJ>CLucdZ|&WcO3U%QyWllPKu+#~ ziwG)xThI;-Vk7u&6oY$(Uwr(}$7A?QnY^qc_^L#2N@;#-x_!_4`(fO7T0{@J&nzY% zt^Ipy)k(x}F_rCvH22NrNU;coJm|8sB@i1|sSnGsu(2P*0X7F{z+ZuIa`T@7z*u7t4jAMb zYy^dH1k&fq=0`jY&06o2$UorWR`UN{?T*PBCc|}=8UI3E)NRjKV|nz~FRGh|hl5Jx z?e&$HdXzb6Oe^jcoL*zSM~2!7M36KvP}8=bE|)VD5aH#G!=V(^0C#c0M&5n($H^8Y zI$wWoMu8;;;QgIDuT%QiJZC@CP`(yS;iVU)DSU23&X=N`t)!$7icaiY;Sd4MuiX`> z4POJVa*(w=Kw=SvD&i^R6g>GT^FU5Tg>UsPvEHS2!Tl4k>7$E^qOCDdj&&Y^9%7k} zu-pH-b|_r{Pj&fyFQ#>nw`2!aZZf&A-0cq(NKp^mI4y9thNI4|^n%ebe%?loa!pD0 zT*7q_@ecbb)X3ppSqzeWoK|6CY4rpgub?IwACJ}rq{yAG_jcW9H>o{A&wI093~~Pp zc*fKY1Z*jI1F#ErE^*N?nn~UxmQ$)JyfREqUVHC)H9i}uG~viCL}hk|r>N_RJibR*sHp}V^!rIALuJEiMAet++OE!J`tTxaIa+n){0_?G)LO`jp`=pM|N*ShvyHlUB<4j8;qu~z<}gvDIFamps->F!PWmjRlwY< zsE9ul0>u0YVBGrT`+TjQ1;{emk7Hc@A>k1yYLZfeK16s6fTey@HIMa>s};uqEN?r& zttJAx^sO=#x-$?aU57>EAK>VF7EK17j>s3tH38(;L0f;$Vol}AJ@)Mv> zLxGn(bYxPBVov?y0IrYkzynS}MMEPL{LL85-@raBoF^H@Y`wq?=4k}LjsuU&R_B{^ z0Rdz^_w6qA&h~bWc9X3JKqS|bfo{bYv_;b3Z8fZ}uD*aIqrl|kcOV*lA5h(HR48gK zXUHKcI{|}tGexD*Yvmn{OI;P*XBIW8_wJ_q)ep!}xG(nSULDmAG7FC`{wnmr;<4*$4k`C=;J1OW=F1~9_C2DF28V83phAd%Rhg<}ow89u;|12@zT7W7XvT&EIt8Mr&U_Es-`*MZ334}+jGFueGd{8lL^31mih%g?vn`! z`#b^FZ6qIHInPN`VgZcH6K&*;Xx1B*#OaElexooTR6St^FY*VR-;4@k&M+s?FsXe^ z9y!{XD&>}^jt8DqVn`EhC%7UB@>P zPl_o_m#73zfCa?HMZEgt!hN9qgyo2a%wm&^`RbH9gvAFjk`g{fWMZ;g{xn4=EQUB2 zj%O4&BrHNu5g5Rfpa7Qi7&yiLsrs)F+k(=a9ME}w@Cj^rrcAadt|tW z0&eBMV0KXeRzt7^iQC&VgL;t+B%BsOW~>BPU8t013#|7M5T+eZO|?ry=@Wz3$C#qu zzD?Sf(v_*Ye<^`)iU<#XVA7~2)h|#|ee;iL{1&7C9n{SI<>Q~AI+2e_6Fp-?k9gd7 z#LKPefiXfv=m>mBfT+oA)Q3o~+lm9&fd4#j8;l3h0kmQ@17JdtS(bv0S&-YX2_R`a zc5_U?;0Xi_!ec%kUPF1&pM!6m8Z8l@6&OHYvZ~zzqRA;J-aGB??HL2WA0JXUFJ&@Y zq;I*_+3^bGB~0P{Mv9=c6$Z*_cz-Fhb$XAixKgk|3V~B~r~n?1zX5#L3T)eEG|Of= zK~ZcgnWus@Ej_G&M%Q<(&5a3om<2F(-a&(kxHkyp9pyiVh0}!^80c>h z;HR(;h&5}M8**0JGF%_Rc|R-8v=j;2&E04VR8}0EX-#+yj}prh&uz`_YVb2Czw{^!4*+qyxZW`v#<@ zTMDoMoR9|aCn&#>!MvO##0^NE4Mh;_Nqv(LdNa+`6Q8`ceC^(kkP4y{Cf&~%Z4<-KG|LKd(|bx$1jPB zj-D&b&)>gva*~xUP*Mlp_szg&ScL9*EzpgWPpgUY&r=K)gAD;&QIU$Dod<%bFM-HV z2^Uh>o&WNJV34yFosnPm9=3evC7+S(C-~YtU76akSCyYX3R$qd*nj(7?Z7(%$te~w zu`CFf_$2r2?eA>G$gs7%>sOv-NYWZ1PJRte_8$qE#EFE@H4+%*Fc_?qeuY*r(N5n; zVtQuu`z^1R=C=tWdg>!T6x|r;J)am0!}P}S$;Hv8*Zg-!N%xn|%Qo@GrW(&$f$Rw; z9uU&{51dYB)FlV3wQWFNqGVu*%Ha3-0nFe92&!!~)!pub8?a2)?%Vmuqz2#2W~u*L z7nTqSop9>UJK8@!&TzZj{tQA3L>cwkKY{Q35~3lX?|R-%5{P#eyD9+l`SIpkzWS{i zC7T5{(&TByb>` z7e^!mh$T6s790z#Wmu8W(K$Ku&&v;zL2)hm`1jz-0oYG@%>}v@f4`bQ79Go>zcV9* zWRAr6U$XD=aO;Cq`87Zt)dj?&NCP}m1b-xR4R5yA<=(ppfENCfuDZa$qmlv>FiKE` zQxXlvfrqicc=8AC_;?bU@Tz(@VRbIO!2#h|NyJuquCoqXF-=2GIg$o}TKwcDcXZ$2 zU_4k0tV~!nsmn1mw1TGl`>B3|9V3-AE%A35EWL}9(_`=SwDQ5>p=TMd9DpuA$;-B<)PP1U3AA#+7NFJ^$Y80#3Jvhm0RYz#fO}IF z^7BYr3Qc@ry4TFaOW5sFwfh%BgtxK&86BH=1+n<2K7{S1My}81%7&?=OQ(Km-hWzY z7H4$K-|lfSc*dT*6dB__3`Fm5TP{C7yMi&sr)c6OG10Wdi1I3EU$Q^Yp4z>dnF}Bz zh~_g8D}gB98a0z3RhoK1lUm^NQv~b7}^MYf1(OyCcSY?!R^XKYsEP3j5~0 z;}+)qmbqJtFG$pofUbYW;{h{F9OM$HX=ECeHPAjj{T4L&;rN++yoKZlgbqE;shfYdSLdbtEgV76ZS*8pp7mATRx(~-|X?Vx`_}c zq0{0R1PrZ;gIA^IZe)O8?jtaKEHK&l8H7-Zq+!WmwwZ0Rm;F2B34{ABRv6_W_*(L- zt7BnX+v4A%im}2%|DeK*wGr;=5~h|dvDiPal57x_0aFIhdExgP)u;i|pBqY+pEHHC zgTsCA%8Ks6>8YN?v8o(MziYW>>Vncnfela*%+_~7$>J0f({|2o?(R65{5D}xBut9w zO^F-P07@&i(%HiYL&V86E6)cx7Z2hp7wm-zFI#J#p@{IJ)oyZdi?XPIrYPJ|KB3V$E(A6IH z+}AIF&#M4*VWlxNWu>G~163@Gr(I=V#Ah9>uO8E^FRY&2T4GvTdzfNYuAl6lTeAcV^(8HB%5ma7X zW9IZbHq7w+of5G@xvEq(-!{Ah?42yHtrHj`ycx&4e##N@SlG`0pD5az)x0Is1N@ZnY&Xn4*Sen4>Y$)9l(Fjor5^ zg3%T$T0=_Rd!3N4%_1Ffmc?8}fynS9*?wDbjlbS?B|UV`YiG?>wD6I>(0Xz7m^ z^(TFyeiX@@YKL1F^|_J*U0Du`SI;PHz)Wor2AS667k0;-eB8k_>s!U^41M30#Ei#l z9MmOflf9(%S)};M8e>e*7gd7@@_)t-V3=7zU|{CgqVrPP)#Z1Ul9CdlRpH9zub<`n zatG57C7n;IO-7`#o+JL*m;`W10-Lbpe~35!<8$jR%fY6gvPmG z(EFOZ4jq(6Q$IUMwGbQTx@Vn%wrK)cfUy_WMEwy?)!`Dfh=AXu6(_b6H57iF4 zPC1-M_aq;b)YpMgPVoW}Ha~=-U)I(2{ploRvJ<7n_XZI|iMg|UJlyZp!2Daq ziDYXVt=`x#rk4%hj0ba{%7&)fhIf2C(VQux-$cKWj;W~Bf&rJI1B(S!1dx6yJqt$^JW z)w(uonA$73T>_mNm1*6tzS?6ayDtnsmKZ!uy{N*2^>mxJJ>22OD-e?1NMa0!WAv?$ z0Pgl(x;1!q4vA_?87z5R)4tfEuJ;vyO(tBgICXWi}NZ;E$BBEYH%dJy^+Rf;q=?^ z?~ORag|7DOPsub(XXcVW>ouksdnEItBl(6xpfX{)u!; zs<^#&jqMO{a%>=UyhYA_dg*85Q=k73`ZZi4Z&j=Mu3zxEEMLFN6V9vA8(G$(w=b!? z<$7H`iAX^3s{wX#6zn6pk|8I-#dJ7J)0g`T8f%}@f47*}+YI`5>NMFexsth5;Cs`1 zJPDkR`*;BHuO`LtZufS2)lDbgf{@lvtk1~^c@p|9Pr#AE5^M7suU98mV3V9e=}Ll0 zukUL6Z7^uZ1eZYB^A)l`RcAKx&k#d%YoBt-Z@=hE2kVWgnBzy=ndOlx)jIWCzqV9g zhwfsBm>kWL3C|RZu?7&5=>&8o0t$_Uk6Tp-^W95wWlrJAh#tmRY4lw@Tx;rZChB&D>_N?ZILye%be+(w)~jR@ zy!eq2LGS(CE3*7~Z~bg<;wq(1y3^-A;jH27qqQoH8}MX6=ePekL*;X^wU^y9CJPfp zj)t=gRZl0xB9ao~40*q^E86Hx0KW_`cnsNwzRN7NnRhqRydQs>{Z=^!{XK7s)!}4Y zt=LhC7#Zct_uOLf+t9J@_i)D_hI{@d;nlqWA9I3e>_}XmpKEN-Hd{@Ed%9hoXlPsz zj-9*iQLTBmH6HmqhkVg%X^=WYa2qH2;)UnZZ^VhOb>DFIG;p*vz(3@CkVD71KHl+2 zEcE&mF>xlf)>fpz&CO}Gl3V8YD6)kdDK}Q}Mhh1O#VlrbJ>u=TYm<~>2^7J1I7X5& zgBt$qx^f?F`Q=gOO+#;9{^iWrtioECg8!|BvlN7?G+k%K%H~l1IzPp99MK`&BG98* zyl?J3O6Md|LOx^Dtj~S7?kgx3MijBKE92ULhpD{E{}u0<`Mi@%n9X?iS1SCcDrBK^ z>u5440=JXHa5K<11f94QBS%CuLh1u&)yor`p=6exklCvDX@}dMHH3MXj;eR>4`^_Q zELsos()7JKUzNJztguK5-mVCG9cv^5#D$cCt?02dO5cUsN9|J5BFr|Qlc{k@HeJH| z<(aCi(Pf)R>-YOE4n!Mmc2QH?H=gKt!x60>bwUOWlb*cp>*f^6e+>IE<{#0|=8D;5 z*%XdO72XndI||1@yaLabhCWWFNYTH3@adbC{hs)+S*{5|pWnc6zI3e<)A6)uAeYHw z^72Q)!^H`8Vh~?}@n`z5$>B{)wbu?NG?__MmMMa{zE z%DWmrqCh$ZkkMz(y*a~Oe|vEz$Ue8T^6!#icR8HtFFi&Wd5F@Peo@q#I=PTxbWUaY zk4kQhp~o!Vs|z_tEw}$1@nez~JMsN+`F)g5|5X7N0Xi$0Z%bChb65Vqq?22_ByR$jfB}uo7hIi81km@&TI>B2ze{)Y$IqXyLvu?tN=MUQp^y z7$W;KTjtmceRGLR|29vR7y@$9JXVe@i-(%14*kYv|V1Chhu-ICH^3l?0f(C=%R^D1G1F^AB8M&JIhel-zd*q zGHFqxWVo*YfOXPzXuU_YMdt!)!{vO}YRId<-z~yw)0+T`>or$QANg!+V`Dr@-{HAu zS5qWPyTN)^V7#2LbVQb0t@mpT4^K3V>@={5Gtk5Z{=%kp_y-3u2}ES8^xR9+(}et4 zn6l}2Mt_16f9pQR!1>)B)aEVm2d;m%9~sPe2>2;hH2$go{+PThT%*)<1xRNir%t2vCO2xy{>lubUcj z^u(5Fvayb_^X&-hUai^>LZwh#XoJ9-|G9d*%-ss-n07!}gY5#b&ueT{A*%(nyueiD zL4S(CiGVz)^%07&bDKjoZDN5%#^8bv@nJbCHo>Jsh(ReKckF0b%CmTE-6#}~o&h_E z)ZX?ec@JJjPX>1W|HZ1C2lfojrMRUPrn8`8gF2(4_6$`6LKWlzY+MZR;G^X#A;oli zjzr1UCq61rTr)qOfip?08zlz71LUyNR$R#S~?08e{sa1C;nssYAL=tLeVfp9C_Bfv@*XZ@1 zzL`JA1+quIN$XWl#8^x3s`ejzXQ%8Ary+1VXw3<9D&6MnKTTN4*aTen?~>c*U2KJ=b9-)Z+UoGz zkY(Ioyy!blBvtHWoha=@Eq#3dUhi8&u$d`d+TT+`SKGtUCco*V-96trkI#j4M~da2 zgf;WY;VnDh*0Lvl?kBoo#uvhq<&UGa^Q^Db#IKo+QDZ+5jMSJ7?%^%9!93JEi6`T- ze)51{_QMSE@#<`{CwkT+<}z}>e**`xYaDT>BQ#%M;VilP`h9?9!ohkAtk`ctO^Q};mwE3d+$o`Y%%xM%SA_WZuEej-ZA`d zY`6vc%?~5-_wv>+%>n}$m!iQ+5g$fQyH_$}vYEabPp?weUnUy5XG^;Kgt}d?YLVEH z0&ypo_gyFzd5!f>`Pa60GUDyXcJz3`-xjUmWtH*x%&v^$RB9aW&fmz~dB1Rz#Bf!2 z3Ji89^M0S(Gg_C)v^gvL-!|9aRZoXLLHFz`tG<8TnxJS*(>*;VCV1RG52yH9Lg8x> zIg22HRtG-xpsD`?jBMJ&rtPxgbm1(`Y({^q6873;Zq{lT2Ce6H>A?Kv7Bb(7<~i{| zOmbVf-t65{UI?oe9rem;3JB)=5P%_+5n}kgm*pU8z8K^N3FZ$C>o~64-S5X!iGGdi zcc;*^i5;f=v4%a9)+kFT10UrraJ1cHHwTkqj;0>e&6++2hF2h%&jVvv@Jc3Xh=EmD z)5Je$huQI1{MXnJA2!qsvwp;@xDn^Uh$Q%ht6cZZBeHySL z2>S+94mk9r?g*jsdlir?%eKz z7)ba8Po83M@-$@J6ljvLM4dmvKHgq28|Gk;P`;ZXEl$zxcCbBEIncyh!KkmmDGZw zLovNlvhHXQ*{P(nnMI7v5nm7T+Mgj&ZXGy@fqg^ML4kD%5)MVpkxL_Q19Q8P+!IoB zEyhih(pQ#sC>SL(@c(P#ho!(25L8!p;VxyYX@G-p+AdW$YIj`(L^LVou)*YtR9sxW zRG|f?tj(LOtt!Px?yqlcv4t?<+{Ar)D_EHoWf30~^lMaf_gErgTke@#%f8=;RWgOW zGzwxlGvB2bad0&|(2ysP`Ssl4&H7!x=-lX*IhVc=GK8RQk!*L)uG#CBWGN`PS91fc z#h=O}tm|E~m%EF~t_gA$t`-RiNdz@WAX}K8#s=Oo?iqS5t1#ax6GPCu_P z!!kMB!wf>%Rdq$|=VKk;(IQfKc^N)V;ndqveb*Z7F)<;-{EcW%9rCGr{bvP#f+c%{ zqjDtTvu6l-)h85nFS4}zW>H3)V5LmB5}tnAxs*8dVv*ZPgQr>ZzP9^S`t%?inPFHmO z6m_?EybdVKgjB`ghst!yVm_`z;nMRUxgoUemvs?ay}|iyyi!8pmHoy6Ooe4Yf?*Ik zF)#h;ObIra$pDwAp$$TQ*zp3pC}L8`Jd<^j3yg@uwzKyu$UiG4g6JY znrh2KG3{DLbqr$)mmXtIe z2h-liFn@U7`JIbs?YFwzsQYycn0@wWuMA(%37nxBpeA06=+869HUph#`{HJDj8;G~7_ds8hC-X7~o8hVg){c_;hLA;E=@ zCTN?0^n|g$Soe-L3sbTVN)iRZxPV8Cnhk+%L+o&o1dc@rL0DghV&1Cin#p{+a=J%; z)#nI=_GJcEk};8y=+P zw9nL3zz$Xqi{XD4LfEhN_ua6f{;V~s)XfW?`_MmAeU>xxzif-i3d*vkf5IMDG`)Q#?GR~Dv#v@nF;^_0&m{wL%+FN{W}FjGbObv)e4!9*mofX6Tqyd^a3xDM}D6k==dH7AmF%=FX!g706UxhotxGVG!m3ImQQN1LJvuDySJ+&Cx zwU5IwoeK+{1z{KK{aMR=$U#d_Cp>&6L`3*_8JZJC zILB13QD7c5l*aSw<=tsQJ`8=DZ20ouduE5-kDN7M|Do9mbzDdI8dUY$N-T&J13Sf( zcMTRXXE7_nBd%maj1B(&l}-(YaJxSFZE)*zletP~Zz$Ry-u!%Z`E&CF6=II7A=&Ey z8wd&fh^;f%=ImbbVUbEU&2tDd-jH=j9C}HS+C=9h2pTE|AxR86&@TloqClabC3(hsBf?R=F+5H*9M%D zK-CE&(s)G098MVjmd=VI4da0tD;{oNcP2_Kq)#wfIl`p&>nMH97Q?|PAJM0k5yr5g z*e80Vmo)MeZ>6M{8z7BtGNwiv%I%zA8QZn$flh^Dva=+B*P8>)w60(#&qEvTgZ9^S zNDhp@)tq}HPU4|Jj@K2sd?2nutY_PtYI!+}kg`?2g=n*-KK>mf^o@ck_BLdF3KEkG z6%KC5ipDH@+z}?C!4H4|USXnnqc-!a!A+~3+lGZ6jyZj#kPTTv$sQ*vUuKQbRJJt_ zpsSULXZBT`aXb5z5&&L7M8D|WlcC;BZd1K}01u2#n*2!B3xdSb(|d@P0|-? z0Y-0K+&Z`+lh~iEDjKnasFRUtK+T^|8pn0Z zvodD^(h(++yA((sg@ik=@bn~w+XoFl%opNZni0tpyxf<-Te>Nx5>_C=x|+cr*X27# zC#Il4qXfho4O-9nUucny__$~(`6*ZVgZi$HoFRfWh5R3T<%WAFD@mAB2FR)w{L{Oh zb=2cMf&n8%nyy_vv6mO`qesKSw^H#qrIE$|wZhVbSVR?%Mf)E&!&h;?5%F%W>>=m?dIGZnMXFX4zt!yZ_P;PG#as_UYFY`NP7Mw#IHh9g2_K z@TN_`PU!3^cJ8lc>yy&A#y4;-?48d)iY8WYjDht!Z`wv`CJz70cLX<8b*9Y24~^AT z7FHWI8ua}jr28#K{onx<17)wT(7j=uo|t+|<*Rj8k|``vKel+C>55(^t1Y4B#nBYB z!}0YW7BX}>!B3+z!g)>ICL8Ot??|^+HI;|I55XLkx2V>7BY;^cqB4>An9+110AlIu>R8@VU({U}_9wtI~oz-NsGBT7{ z4lbLewfmmltopQ)skdQezcI@OQ}gdq7UuPRs6dK{zX-*^u3m???|Iz&M!O-u1i{_u z#Ps6_mz(^IZBZNx?&Hr^po_sHR$vT279iyHsdbU3QW$*o?JAVy# zptyJRv6e0$m#nY!n-jD@6XwscF>D+-uuw;uqPSm|7iAo8ngzt4YO`B^4r)3a3ZKHe zxX6`AoCxd4wms7N-=HkZU|2bO&Z8d0j1Hq1igi1{(nE1KE?@NtTnN^f`V3!b4LTf0 zG4Q#fBO{*z8Zf=oXJ7QnXWt&^Xq|@Lho>jlhQ5xSVwOB9q6}^eEyan|j<2@1B*BrR zs3%QruIUq5yi4)lcM_kT#9eIoL6|UMnan$+ofRl{WA_BbBI)A!$n*Bmzi}Uv7<}1Z zDq4Q->M_J>kCIYRAYd>ObC?XQ@hkmsu&PZ|S)9%P3eoTb&Y_JP8yhen8&a(BODeRe z{}o?hd_aO#$Z&@S2B8L1Npj_?t7nUuSyr79tLv%ISNIL3qt9EXE6qq%*3H%Q`MuL2 zQ%@!@DZ;1Y)8tDX!B2vD99Ub%OH>1cU!Y^X>~H4>p}KRXWh1!#=s9+Mx2?qVeX1n> zpzFGabn0Wo>p9{1&z`7Knvkf@cqw^rQ`01b~TTDR|F&c8a zzCDG993;SP1RV)q{ClgrcJ9nYLqh?X#!bEcU;!%#PRly;ZDamrY|aNEUx%Ot%jp^_ zqq8EhYvzHuivI(su~cVs<#H2Av~lH+sw6GsP6I(clf!*X+l|XSVU!+hfb*PDd$DQF zq!xN6E6eZ27S;78eY^YZKbiVB(1Q=k-4vo5Ts5hg8p%VY*SV?ctsS6aZhi8;j=Ano zOMag$#zvieLYP!hXi+FM;^-aCK~qcp{Ek<3nMFfj1P!j?$@P8rb7*KN31IW~Ksf)i z#^@i~D|sj8Yq55_*WvdfpwLMqWnkE%@=fkfQx?16Sb9@z+UPMG_WDQpKtKBW9wwt2p(l9b~t;u?xa_>j`Y7&9)8z8#w_?rCd&fB<&V(v z;p(`<->N0;ag7`Mt+k92Gr@q6(Kfq%yQIE^SNH`rP|K(>o$VSX|Ky2BLnhbRN7fVD4L_gl`l}h~ z+it1XGS64LZX-^HZ;PHaInbryzxaQ@`af>L)9cm~jj=Qb0_4x+|5|PE8X@+swp0it6Gs);O34s6 z$Rt=~Z3@i9IEvdR3=?^@oMDje+2!v#RW^t|*13&82{GxEx?nFJ`wFDL9M6AYEf;(z zt*h;~H}#)Y+GxeKwLARhtU<(7Z8r55`MtHbdNv3za2_}fAULQVsQhyw;(qYCGZoj| zXGvtq%V}=yq)v7m4-=dkr;EQePp1!PJo0XW94Bt59M9z5y=8-~|(DTWjPO&_*Brx5>uA%)eze>(ytd6G4s|qCfivO_ zl1eAUYElzB^y&b7B|mlb`Hi=5e#YCHgfP>9)h3WXyK?!_N7I?e0146Sd!EPoUdi6w(zMA%94?%p7rp z-ha8h-?F3cbRJHA76KU^y{hKZ+=WCt1J%K8#G&!`OsgwX{?w6zcfn(SLwTDXz2=6l zr*~DCp4&F;ZKnQ{co%G#0i?XsXnbna9Pd{v~j3XQ_|DDSHd|T%oH8=(9ih&!tY$0+oUu*ChB)X z?gDE(pWi%;)Q=pUYEVJ?j0Sc=1u}w-&09i z&J-Nc2X97PQ?qKX3c2xElEzFF{d{!&irO8tSK}{p`)uyh!P~q1Ock@RA8`xCY;Ii!g{;QNUGs^|C@>g0<>RF9$W8Bd03%a zDwj5ylZL~8FphS(KGVTL$aKZ_WOSh$pO^%+jkvlh+0Si1#Z<=`>!%7g+05cSKVIJ} zAP`llr*B+P0y}ndk!g108jZi;Qnr{dR?nNu^;5|4`GUJOUm6lO^39Ah+VI#XKoF|e zD`Knp@9+8{+gH(;Il#x!r%t2sHd`iSgWl`Bt#Ka@M$A~|6*@bktA+UI;-A%ZWw^v6 z<3s$l?0UM-&s(z*Wdr>3J`7hGeRP;J!n(Q>6;P#)6^636n4$c+;wZsu`z7V9(x=Nb z|LgXAn{pl=l&I&8ltvfS4OiuBjq{-TAHmv`(Lda5O>+9NDXL~>r&Fcz3a5^y+cRIs zJ(rMBg#PS19{kOUNIf8Ko|$nL$SqF!8F1{z&hyz}4mVYY(GH}!@Bz;{J$}1Y{+9^A zd>5~kPbI%QXPKJPw zJAuEDgn4R#>&R*v?*vD_jFjm?7Wbz>e$@SAsSXyeZ@uHPGF>7ho~nDlHtYLQpmigw zP|<9HjlH6(a?TKP3T{TGV|<<^DQ&b36i1iiqUF_RAs;r!eg@5$8qI#dZHP=N6=*LuDEq3VT6^W5kIu zJ=oyf?n#K4vU~oF;pH~hakhFj#_{Rg&U1|~j3{*G(pi`EVhAeHQASa6XXn{|kou>X zmU*NNH8Y*XI~f~F`0pY-q~1Bi{qdhCo}YZ=No0FQu{1QG8@=sRN}tez3qN2+uU9lt z8w=kFGnj3#mY;3!12g*PQ%hzijXIA#CD|HFi%Xb2sl(0omeyt1vfG{<5#A!9$gI}A zJ`UJMB*;kO;=vw6Z&v&~pqA*Ha!E}tNkubewm~MWWlbxFl<1GIe+N>1*Uy6GQdghs z#Dz+OWX&j+P6EQz$LN_IuMTpvGV*aAig=5yP{%jv8)G zv!Y5@hI9*t-}o|LLHBPV4NoA*B1+9}QXvE9h}md`6udUfpG|)8ru(%6mMmq+)3$Ik zz1Z_fOgPqr9Ii@DQxqXR)3YRdmCOD0nrCSY)K{(WE+nYEBV%Je+xz?b7f%z~rHfT& z@@<)X?^*m#f@P;=B_mQPwl4$+u);#u?9TD{nsCWBWg}L%Ur_|K_+D^wsS;=hydQe3 zFKSoj?H!Nm`E5RD9c^*J@r7uo{rE2@ScBHhhFF@Vy#%Lsh&Bz&kv`d$g&_Ip61z5= z>y}9BeENOMHMTG;gWHMF=I$wJz-ph-aWm50#o+t5l{cdMQMl!LZH+3=`}u$J{{9@T zCOdn%WTxWcWzhD^>1@RR0y-&Nb2N6XhLeEVqo;n0l3!=OuPa=3gMG|Gj;I~t*~Ho> zdNfKg-B7O4<6cre;oJWT|NA99TT984Z{!Fp7}E2an|LxLnad-qk<8C zR9gfbHbLc0Lhp0daeD_+OzvzaMAk@P^hkarR{SLk>|PmTc&^~m6Z8dkg)@L-{sMeO zTY<-YJ_sg=p0z8aCz~YHsNTW&q*{}^`Y3=;;9ygfSs?_uZ4!7wS+YSYqu;-PAC;TW z(=%5cv!3vG%tU;thVJqD_*ag37ggTYbC-3|)p9iR%G&^kX5!~p5e}tMn=wQ6QTY`f>zOkGc3fUTV zy(fiLNXFgz?zRdog~$sFcl+jcU+UAnEvd)7M_Mxii{Zm^^O0I|fu5aOiORp+2O#co zczyBN-rMU1wwe`FGaql#bwLR>C?zf)N=%$>{Tt*jN2D~V| zAPFi~@*+k_KUdDm^q6ka&>>iS6We2J#9jJFC>1^wYrx;D2||`5%xQVGMtIKO**fMa@|gDy0-LBmQ!(INQrrzmF$| zCm%WWXFpOdbw6BTIh%}Gw|yd1YFyI@xRB`gQtsK6`*Rf^J#Y30A|hM)EC&8Id7qoO z3>wSTc#SYRdL_e96jdoLj{tTFWQ?EEUJ22lUco(|HF1pxJw?DSZ2HNqD4R|Z3Fe!I zvW*9bPWp+2O?^IQT4(W;?)0#?T^#Jwa)AQUR`}{YQT{unfd{g_{KX5luIKiP^h!%f(pP1YDtT?-V3WbFx(oLs!Xs8@I50wI^!w^iz<=G`?C5lb z!~89pa3vg_-_$ppEthYes(vBA{)7oqSFSx}ifJuthsxK8Bm z4C6E9%)ZmK`A1tQs}rS7I@9;<_^4IL-|=r01C?v_&%0?8f`*sjQR|4`G=_x9w-eu^ zI;R;~uiUsq!_9osX*VyCe}t9NBW5Yy6GX;Tswd5hv%_BN6w`ZmOUw&Z-p?&`$l8)K z7R6_WW@eBMQRrrnwSDqi;5$2~4S$X4y7iPfL!z7soWzpeC&r1@gA*6w4G#^64u@8f z5DE9kc>^T^^!D`-XeBJfz}UdQSvtelzD-w;6i7-+jQ;w5hwWK=StGWmt4(cnI|AAF zqoeGQSPzbe8VCEWxrs^?R8(6V`4*w*gm7ZB=2j2iH_PP(>b_xd4$f6kGktsubq8g- z{Ikon(Le-*HYHT8e^l1b7hkqJT6r8CMhDXR4 z)YM|i5F38Q*RZCiSHqQzSLHl8c{#)PCwyyTRxz+Ljwt>gFKmI+JeFu|TG1ZpBVUjq zRyQ?OCi31zx`m@b{JnH(`Z;3UhG#v)jPCh^Ld)5@!>Vd*mA z;E=IZc-h!JKMr(|C~Vx8UQhrLTOhV5Jf^4~3@N=nqmL=u#@FEEk{w`7ZlWzd~A-MvajspvvCpfz)F-;joUekaik3YJUFqR+yD;YnF%%O7EGf zcm8fdYo`|@;bCw_WHDaA9HWUm9)_E!azzyfVIn6Q`rCOQs3@2{4c>j01iZQU+==-# zgX>FcN}XEkpx*Grwa)jxk*emG@4dAhu=N*g7_Y?9aeMu%8_R#xYa2q&Sz9y!Rd~5} znIIU-8UAClPNDFduCpHPh~&S^4Y$_l8_mTHODZ3v_lU|_;N#IGBhYHx@+KR6l$}wn zP&0erGpE8m(Y`}<=lu-Wa#RW(Ga~KV<<5zsY1auncX=y9x!q#~_m>(M{8tM&&*E#W zKxabDwUygO7A9H8eD1BAYPzwKv0&mZ62#G8zutRa4%x=(d=>eUh6{&G(S6+)@Kq>u z*PH$8P_zKTw3mxTvfi}M+^;RSlRtjzgHSNRpN#A>#5XgqWE$W&h9@@b&8L3y0+XL> zAb5EKAqHyljLByK>J;*dHOe_lN$oi4`#a-7SLqg)@X zNQl1cWp6B8Cv?_GY!3ax9xRa3iDuI3V%tpDLQmo|QtNzi)ey^WdEXwjbL6_Aq~iT8 zX{(KW-dsT2gO+&R0iRp?ZnAWHIDdaSN>4GxQ>QOZH^Zm_E;R_Ax<~_!P-dO{ZTB!1 zZ8%EmN}KEET*VQQJx@G@zWmakwLmrq-N@HM{FBmyZA}d#x^*bSkvgA;yGNdr`lC}G z@yb#C!sC^vxL(Amuf-UK4bc<-JWJ#WA0}R;DPcl57NTsbxwZ^CR|%R0o&NHKjC1j6 zu)g!_IdL#*s^9uu(2kGZS@fd?9q8{ugLJ^pIXdHwS#q{7$cP{Sz+T9*=aMeU&csRqqDidj5xA>^#IjN zFMpQsOWy4&hiv+_$DVITTR(D(Lc!PVR-Kq=6vKP;7i_aCT)aq5S{K}mrxM313Rkp! zg(jD-u<6caax4d)UDK#1<<eTg+!xP&3>&|$H!EjjP1NCo9JXV3Eiy!FK33+% zW0t;B>KU2`cLCldW#l<}Ij0k$ig{wFBF{w`2;Xshe19@S&aY9J&n4sz3B(N$A>}~z zd2A~>zJ1oEPZ1@pwk21KMGl2vih?pQp2I2AtlX8tHD4lbC1w&yRMW(S6+dvEG;_#~ zsuz6*F-If~GaNFt>6}np|ItvmCoqyUmz>E@IMZ|?{(L8@i4aUSh6k5VQ za_I@ST<7NPoGsr!j&O!eD)+-QmUr!w`hHZR8HdWA6dkMN1VQCx*N9LPSbd--62|(43Q(lR0h^qL-;cL*zlThbcFR;hO8|chTLdJP zZje+`I;Fe2Q@T~UrMtUZx}>|iLAvhpocEmbedCThhI_u+4QG-+b}^?N??CdTXVW>b?Lj}hd@*FB z*Y_=pT45%y2mcPA-_Va6veyi+?`wS1Q&ddxy7KE*nl8z7T|;E9^`al}q}lO?>46mI z>3IE2$Bte5R%K5A@961^E$`Yu2A%L#2R{orWaA)Ku-a=Km*Um)U5&%VJne*KJBZ#i+D=@EdB!NS@{_nxe- zJGfa7hKSO`ftXd)VSRVox23UKnJ#otMq=`q7Plc|L0yid+MFbBv_v-E3IzlsMHb zKZI&-zPfp8A>2_2Y`x_7Fo&!DY_M2yv1XWFP&sE>4J#k-O6qwwJhc2Mz8XchV@u7B z1R(Ssgu-INCA3z}-aAP%CESbfLhURle^F>gicAz8#^kPQ^ST*n=*Wt}-zRl-qr?4MeJQ-E zb?VZvtrS&fR+aKPwdE$O)J5_W6HGRMT1U#ZhD`a{JR)~7#Uh=-ozZNaWVuLbVQ_9Q znJpQP7RC=c2eZfQ)y4GW=tJ#exrc?4SkYI9?|0M`rL0bl*zXAZVj1KUEv?a98)V`Q zsmuqii)KD%MNicy7yGNW2Yhb#?eFXy84TIj*kUQsS4A9Idt=&SW5b0dR>yx85^ z^q}@=Jj?D@PPv=ET(<#;@`kw-$C&x8DacKeG++ zxpsyt)uibroc?uW(0ztdd9E+cw}5i%0o11AghTz-+bpG4`&jLzuR0jcD+idyGCZUW zgX>XUb>nTROt8G@*&|-{$%Wk^!pYd;*H$C!1Q9FBE7L@H+hpK~%5cWIIH-xoSl^$w z;iIMJVs@;}2A=!<5RNwVcC{)!I%}d->C~&ktKdJClv>+Liy9p^4YgmIoIAQcA!Y^i zEXoQ@MjagebU7Fv=X3v)?CQ&e!o5!+J=9eciD8QLK|$+xAM!YqJaspho{0rtPrZDfb770--*zl;w-(GHK3q1X z7c6X6iUs{EoL$<(_Uw=DkJz|VIY%lK2=Zpn6VT2NmKi5&`WV&B9388n=dWHSW105fqk0u=wTC3Ey1m*{%8W$$#3R~gLXt7+c8)h)&ud~5%yUsIaRi1A`}2LqQf zxwmb(=OQ6FWw$uT@g5SZU%$jI{x2LF68 z>fE_N1IT!lS8Q&R7uSKyogWtDR@Q3JBVOF!e^|~DIG#$s+{3-GITs{ynSEiU<+w@~ z-7drl2~I_FM^TG(-Ay2^vx<7YD{9aSi1Yo}-V<=KWApgys3rg-^0<@EUzT$jXhOU| zX?T|yL3OWyi-Y?6&5^?xH)k4Ds@9MVw)hOd^-J?M&L^3)^+b`9-DjTvLlCKTFll0gUduxv`uX zND9B#4NQz?|}i7 z#HSk12#+kSAKzjYU4A!h++4yC+9St^^~H)|(?)=x0kON- z|7LggriW*~lKwug|E_h?peLJ#9Lom$A;YrKt-)-fWyC5Idt6RGOH1!Z#(paeTu&F* z`hodsJintAPY5J|*Z4J+v(Pc=xnf?dC@{Kwh;3f9O8odxIH+bX+PHi8K0`D!P*g=zEv*IglYGZ~`8o-rtSB!)|fgv%j_#@I@uGN}^hMFnw4V zXZtFV;j*MSr;Pl0yky^Oo!(dHHa81`s2T^St9IIh&Kw1QbTMeOkc=YF{K{S!7>t?x) z32D$+txzPS#Lv_AYzXtbckd|r5)P?t)|Em?znm|i#}Hwqhy*)jbW zx^o-D{_Ps`Z9olNgV=#uL)rqfMpqpj!l)i=HU{B)0?j~}st@s6UUsfrC>1u>!kodk zHZiBGWNTUW3LKNGUSjm@INVuiZdtG3qhFCcmCiPr3os-9;dCo{akgg$I~C{qZQnY& zcsP@o)1&xxe3#FlE~hjhhfu{YRH!JB$bwD`MxaI_g@z)9gM$MHe~5^PFH|hykcfyW z5erWcs(M1B<4JY)#Jf)2X5PK?K;UJq{hF2hS`{6^hz=!s4&FyUUkbpO+w!ESqW2uQ z9YMy*KmKTbmFs($v>P#1NF_LPg#fbTm$*`4QAGp1k-? z`Ey@)&PBd=`9$i@<@P7$hAsIzo-)&;L;TQORY-D?{owYI`^G?n{tKSF_Nk@3i&-QV zEyDLsw58fyK{a&zE2b=k-ZjP=hFX_=8r5d^aaqY6*b;0+Us}c}tA{l(jtO>5P~O$n*5Cga5~w3^SqT!p!YIm zm84wl{8i~gtiqe#o6c3gV%|qT8Gog|{SFb?6a@n*Oe<>}8UlYsCv7R&Kec{CYPY)A zeO!3bJ>J>SW=-qWrA!v4KdTAu?{laIGnu*zx%4Z6xGV|e$I;{a0`ch26`vi} zfNM3ZwOlhR>`j9l!@Zzj)oH|PhbRdf_#p07LvF(v?%IJM+=2Bq!2C*o?oiI=TX-xp z>gy?j;v183_ToFc%q+!jn68*@kro!Wd{6419iiET?yUPUr}fmyC<~5W8%{vc6T7su z6lh<0i_y|{EG*m)!lB^6$|kcPo#~|Wl3<*)U6b@0z2@bFV-QZF!Z9|?^g+Hrjk*m6b_DK zb55U>Ub;Vz{D!g~-n=9^Bf0L~ zV&O;7Icay_zPY(U0P5<8E(GjxAB@E09Q|A?5eL3ki+JNzc4!y640D zeuqYGPNL8&_vjYINIaI2D8St00P#uOBM8zF?y_uCEB+BJ@Z{k!w<%ZVSshkq<7jo$ zN&8ZcWrOjupzqg3JqR*xY`&eY(yVpK4F&Z`n918y;?QXjj5DicjBD7g$?%`YP|-{p z?GCfQ`1X4~pV-;{HmitnOIAMKM|ptZpv|89#(jE&#B)TRoG2%!rGiPj71jBA-~66_ zaJ_vmS+!*YTE_YrRSya`!w*;Y;hU2VQdsuQ?8DDohGs4zBu-SAtN=JcTD~-@=zhM} zuZ3UX;q7kh>~H`l4=eu!FY1tCIu+wtsc?$WQohK}U8l5F02-#_9jdLJ9hPRj%?Ch} zTfhApk0ri7Wpb3gS0%=3F$Mv{i!PMlcje`JeRiPAd$LCom`<-c<2IFB%;{04>=gl9&jy3?VBh*;Ov`0*EzJ8O%!(79a5wkL{A(Y~dao^_ zI8T1hIvKfB#zQGPBP4J2D1PA^w=DbvWv_sOs`yOLQQwDq=cfetRr96^@*(y=h-Wlx zqc}Ld^7YN3BZ4IHYt3m!Vw&aFTjQ$X@!UHupDJp@U6EFLO(m*?)4wj% zy(6f4RTsf998ru+Jqmx>+rm;CAMFRr6#}?v(b4VM(SG4da>9s_#={-c)`lV({E2Ciz;9erVN{v^##e|$wQ^<`n27%W}2!(GTC|3`Wx6(>_-xm2r3~sp938FrIf~eLW>~CCjc3 ztv<11A28c4ugDpuH9o=iQHcxEv%Ybk*p4WCB9}PQ7{uYXVzgMvWc>jIL16*FiIbD_ zXJf8#pzd-atLbn1nrEPu*gRc?Fm1gUiqrCI?Qn|aorbDEyQNQ~S83mnO50cf;|01` zn`IPvy7MvD3tSme3h$IBR|#nZp~GkO-iSY2RVaz zD<|HW>4-NW^j=(-)tFD+F;pti;at`e_h^o7QewmSFba5W39o)QGRLIWa3DmsZi6q& z+Z3o?06fw+Kwx<&T|mGEq<8!QcM~E4BwNSdP*E*^FrCpWm&Sk)m6+bXyJ7jz%A2%B zv*yRZr($MM4HAxj#0WuvP)$YXKt-r3?h8e0TP8u+_bW7u0*;cjoTL29bB&4(SoSbY_bX4TSdDiNHWW{bMA3%we z$*bbx=5_sY;L79x=VK-ln6?4 zGc4yZ1A|!B?t^{x)6jit@F(xR7XEC_=;scb&svY+HD6r0oVsX=r13>6h4J%e$l-)n zQA_`1{WC4{S#teZSFme4_-+IF2i9@#a*Jb&n$Aaem%FLkcT0Xv(6+YQ`vy|*!gn{e z)*Jm=LB#5CO)R5Y5QxJ*^o8t-XN>Cd!8f+#-*gj7aeWvfTA<>_=D9URD7Jw0YYuB{ zOE?YvvxcF_w{)0w{VY|#%2OS*GRdx+@17(v=}q*K?T|nM4#~6B+~NnPnj5Q7`1b{c zzjKB7>n3&1xT2(0Os%iXGKEo{=lpH6scw)Jbe9L5kH;ZZo#K5m*31T zAtRc?&v?%#?Vo(sU`Qo7!g%}BJ5F6~5kXLBct0S8KZ|N8(sC@n;B4Jfx=_fxfORyZ zEBLmePPX_YubQ%r`ohvozhpYr&9yUAA_+YpZ2H)H(Sp;sXXJOACHpKQN+&c+>mn?j zIgELgZw;oZg^2pnw%hF#pW?ZV_C{T+S8KyqPtRYVh>f#zP;|6Hjab;|4$rBJEa^Td z%E->i>FDoA@~>$(fJ&-6iE#gPZF_vpLspE&9F#PAP63v4ne=ssz#k%3Ok)g7syar} z^g^bOvqsMT%SQS@)bsB8IE{q(e)kV+hr%qwMunhyA6uUvr8}jqM(Lk|F&(S~o zzZsYGDgeSo>7I-uVJJYeRfOH`kH&)rhc!uzEBsO2`;;bBU15Boz<@w@-?>hqJcZav z2cV$lH~=J!5264&0f49!ynvoQ;Oi)5D;FsoP6gK!wFUOZP{xT@Gjlt)??R&`TRl|GGBma6o{Q|( zcLv6;*`r`QvaNy3{B7M2(wM24BEFr7E#t^>Z*)Ga9@Bu_)CVzjWK}(xlC>=>hFuKL514O&<+L3-XY%SLCt#Z(+cMqb^|S~ zsv@r-Q_Sm=9`vY))~jj4k~a*VE?i#+IuthK&_0p_LYBs zfh5XFXiIR=s$C%)O~{c!C4R1S$vrgiQF?qYf_%8Ekwt|fa)`BS!@accVadEJmqV(5 zTxaQgbakIz*zC8kr`}?VG>+dsOOrGX#PqwROHkc?Bf&7cW~)tSyZT(~3{$F9;ZlA? zy=$^oX@Gbg+60t)(L}%3jR$Oe0(QX;Q;Pjn=|uRTkMEp`5ASW9QvCDhoPkzr6{f{Z zDGx5|4vv!=B$Q~(;PgBSXj)CNEiIh zO;mdkF9cD`k-sBgtF){EV*W40=ZI~@TT9@PtAbnox|c$dHK5l5efif z_l=Hz2})7d*4O2aS~ci#BKi&NaFGLmNDPov{wOUSAYb6G$rz-ZRk_UDmOj%gEO5hy z_#yQt&Z<5BsSA+^$%6Wvld?r+Bij6!`6*=zUvVCot=zJjrt3bd`o(y-Hu>#`+KLt=c@=Ha{qdT%lO4tOzt#{Z{b!-F$|~$Hn5vb z<}bHBKk*n(=F2q#UDzU7k&2IwNi*I=v0-j{FooT1ZIQ{;gLJAhNg5Yhvz-9Y%XLXzk$mkO?TQ^N!}5YiL8HmY}^L&~i@ zOB!hUk*E1Ace9ocpL-q1CcnqfSud#zxR;`-WpR3! zIax0HBW^aMWr@Iqqj}@631Xmrrz0MOHnFAFBdgl-db zd*{}P?R$?e0j>q7F7sNYGi&<8i-*-GBWaxFMbdS?F6O^xw8hhAtI8eYp;D+U-CpnC z!KLuH-Vs*ix{w!+5*OI;h+^#_NNYF?i@6cVzdU)?qw$J~PV0VrLrv$Y{%DkXdY{MJDaReih!+-x4ztb-FoLlM6voUm@(%2;ynd+ps)Od2c z%qYJZi}&+)a>jIGhb|uMUH?x7+>PJ9)(lkA{WN6#nu)nXbS|Izvrt(06TL8njJ@03 z_;!@=OB9S(@NfG6Y;^d4(_${usi`IN@-n<1d6zSDt-<%8TN@WCU}OkII2b2-3puan zOD`~5!N00|sq#I#%xBpEP=N#H^k9Mp1Hy_>zV6q2tqOa2eqm?x`0$>xTeETC1^w^A zm!k^`V$dOyvTqR)7Eq^IqZLNnK=s*Jq3w|9BudQ~Bt2eIW1pv6Xi!OUH-Zwi~9(p2u=mT0WMKGk%2=dlwM z)k+5iVT`}OQA$fTe1|7B#hP)r2&AG@{<4^uSy%v42^Jt-DpbS&g6-SY+rn-iZOl9r zyHz@LTg-zTb`c5`;Ylh4@D=u_OdM3}J_!6FV8-7;w|-N{NSs_6Pi;}KSD{FQT>-&r zyFYG<0~m@T0g$5GOckKlM1X*#6T}B_ub2TfA*(~@BUqv#LTtoj5J9GR#)Vp4(TkzO z#SFBhx&Y(H+EXNpAgmgE4$>_$u4CTyQX69-oZxCdna}2>fcO9@22XyGJ*j%>mYf+|l}vSO z;x%~(?XQ+;DBJeR+;%%@@7X6!6HacQ0h!YXO;J2Lzm}gyNmL_X^XV&uQtu zNO?U>Zohr-TjKDzrD|RBfMpIr^fx>+!g$8imNw%ZThY)wSnVkuWNB>^5YJ2vCzIv$jM5hmIf377xaZ6rUUICw`=H``LPgMLx>a zeWH$>)9Y%{z_mSVzg|gV>#^6)4SzJ7!JyD2FBMIL=*~$)1XZ0B{+v+f)f{jjffEP~ z8s<#==Jwq+XcBSv{ngPR1qFq((=}mUw?BxW8}H_FW|AN_s+97`q7z0Yea*Vn(W86U zx%<*jh_j>S%i3|f@Iw|WpYG-fusbSccX)= zyR&Q=&@vM}hh8&giG$H?QB6I<~6(!WNTu*2Kg z1XooJ2PhTMmS9TMKsCUL))T(;lkANmfBR$=+G7y9YLftS_uwzdW^TGZ~UQ= zp!fTa=c}sL2Z6jhtstW;r`3dxC3M>cUh+Zp2%~7*o56(QHe?|SwT)g>&q6C5!w`d^ zK9)P`17sY+?~(YfN-AzJ1-uobGczULw~GOLd!lurVG+1c2KcCfxXZslk7y4N&?N?q zq6DC6`U{XL_6I;e5fKqpK*Ayg$L1bz*s7N%my+RYr}Z}rnA&XU2MRpd`U3aXMil*< zX?|49JCPP|I9^9J=fzW7d4+VD0p2kODty-?=!M9Pr~|ou70^5i3T+?I2-)!fBXdP^#wIfr6jl|syU3L<1@06w%B6EHa}+TRV) zK!y#O)qeW<`31lDouHcl^cVEO$|QJN?eHT&qe}KN4H_4ypGeaqrh8`#>;89jLJM}x z$vQ$J`FHt^XDbd&5A-Bcj0axFlNRl<(^VbAw-#Qke7h$@X}?KWP<3RwyMqq&vG#Ke zXT|n4q__gtrzIL3Omtj~7vrft?0)-WgK_rzS+gf~o*c$bR!#%# zsk~?WkloFY>y6A)LtU-u!_2RnCt8100Z=PtsmZy?VSh4Y_HnXhyY& zb1Snp!S>$p0)q~Yxz`KGL`S^}-bhr$W7$U}vgZ2UqmqjFS;4478*gUoa@M;|xB zi0Oz>$Mrr-s>Ri~mkNuDDR!widb0S_n_*5r*@yL5&@}O*LQwsG26yQ)+NurWPf04~ z;=#-KuXV_E!oa{27``v~B%>S%sdsYAF-GW>egC{bcpmFD6&F#26xwIbLbHhB<3oNSlk(ZE zw*$WGB#Pvw?QI$jVM20^`qu5+y01^aj zAEU~-s~hjzEvbT4xb{dW$+y_ZTTDJVK|bfsdSKc<&?(Juqp)5m3;bmDw=Y{ z_4iU#Q`t$1(PmFOtVI(~)a;*RT#asFeV#vc3ZNDJ`@{bA8y9WA^f!7kdcO*R8hdc* zGT&_zIq;VNp^RptS8T-cS)%{?LBKh3J}Z72J28M4|NDnqm<-yyEX^=%>i_zW&opI$ znu^#<$QT&ZuO6lUc~jde>9J^9xPkOr4fsQ}5kV^nX5xDTvAENtXV3GI z$C6WNNH7klihqB{_0lNp-}e)6E*m&vA@kqikRSHu+1fCHijDZseF?de-(@*G6u&h* zc`W$v1!{OX9?}1IXVW^C8Djrja*HXD;GeG=(}oBidrict0+Win=V=pZ_P>FB<{I9w z9$iZpzwJAvJ~gIzh(y6u6Lp0??*m=ioU zjelP)AGhFr>rGYNT1=%OqGH zwwwL?pZ9oUf?N9M)}JfZGXFckuab)MhH!@e`!Kj@hr!0?I_hiBcH{g18t75%hbVaZ zoG;q{zt8tWKN0+ADi%geRek=?Q$M#Gv;FU2Qh3M_OwoE<|8Gc(G6W>D)VEG1|GO51 zXoQuoGtqAxxaO?y0RJlRidGtFe*w8G^cb{T!QTJf^ME@cKgT6{gx>#F zV+3kj013`NBi8off79JHE!^yJG*ivN$o~Jk^y8(b6$Tv)T>kS8#QB47|19$@niJcb zP3Hg2@G%QM1k3+EC9Yh>D~$imHj1vEpXX^XJ7#1L6fGDda{t<^{=Iz&1O!Pq1O#{XIy$R7SD~MBe$PBUK4QSb!e%?} zj%Cz?OywEi^(>QPg)}Z)JQ|^;q%Q8Jeu1R<2CF{;RCt(|YBprPPn05vGh_o2AxZW-Bc|Mr``J*Z zm=G&8R?>?aQpWG;t(4mLYrmrp07vP;$54&g49N1VD(ed0?^F;23TM*a8X zghtVr%m&TDxq#g`4#;+e;D{n*+=LR)=L|rPp9B+A*^<+7lRIE=KY{jgwE&?H0H8Go zh*mobrnOq`MjEx?38WVH1D$wt4e7!BR7Cvk{4oE;P_o`YXR?)`DXOkT|IiU3kFgRU z8BIGuGzUDbBf#OX0Ac1|K+z!}y`e$$sAbbETuxV^G!zv@K)sqDzH?5s_&q;GP2Yg2|vGJ&HiU%R>=>0AE9;G=LCx(m34{2Tn(d z4Q_3|LSI}|ON#^v8JWWIVET=#tE>MDA*%=r=@Aa7{$`I*5h8v;s{8YgxZ1{HWl^%< zgMxbHdHJaIMFV)MLEGj2?5wJ^o?fOANCqXP@wuA;<`yd;Tup$ITN!=!WHu0_Pk@Qs zqpVY_HEVL_(p>ZY{d-Cfn#YK~rJZnavbEhi*x$eV4k$$0kP*lWSk7u2v33Lo0#?YPU+sr15@Yx0r2rb9F5#-GkfR*sx~@cs5#YZtneG5rlF$ zVQ&U3*u@ivxAOs?Fkd(bUG(v4!CHvIM;l3T|tA-jZNV1w6NHN-8Qwpm2Z! zXs)=dW|Jn%Kkr(JBg0)=V$TouO8N?;gj?OSj?CS~9Z4^&_@d}uHg`92q&DmuC!rs4 zSC~%~Is$CtMn!`>7)BnRSE7qemBJiw)?s+q5Rd~pKSHVorEcqihRZ%8c{YI3 zazi!-rblU6)I5(CWn=(Rq?Y#w+^YItv+xtsjj2M|E|AxjO6g;hvr?5hcu$vR;e@2VIZR;n4csVgGN#^TpM} z<6*{@$NRs&$dJDHmse<3eaNgn+L{KspHg_M_LCRtti^{@c{mCQjM=wfIr&WzE_(oz$6#&{1oRuWyoPUZ;-<0UOPQJ%s}L`a=O-4;{W0|uy7Bd z-GC2t2doz(kU&SlM(+6va7=K$kwj`^d9GQu17&%2+|1jT%GQ&1#I=pi$)xRxdzu}d%lSecoW9fi}hzQGL0_hW-v8J9c5(Yq@l z)?KQ#0bea>s#7Wif0$jEgp6d|7?cp`)Ped!U&!4C*aR!MWuOA+Y*8(13?IkQEAxA84uwDpQ^Hd$tu*6rbQJ;N=HDt#^uE3U{(A z#>(1X;rgT~9^JGfL@nNn1z>v&5a^-_umimUjB9|bhIMv!u5WDYoSJ$C$fOcEShTUo zfb|73&2Ub~i?p5PYBO zrNu>x8;_?K5J|{k>6#I}M!n5iN_V%&9!T(<%^9cb0@LgQ1YR&8vz4RGJIBW)BWpIb z(7Omf%gV~E%gh{thSK;J#z3OpzrMbnT%}A4?fzyXDt2#g54cZ0Wo1kckB=GSCZFZy zzmf|Fa`JF-DNQy<%^JkY_f>FN@wg-qEDunCCKq~#d4B4zXO1_I59x)x)kG-B+-Nts$(WU`4G0X9u9~Py)R= z(3awzOdIM=kF(%9Jfz@l0DEw7cedg+ULd~G_n#sZbM?+ATAwT|=n2>@@OZ$P-}e=d z3u&0d+#6>|InGwkNW%M#L9j3ew(J_z@+Mr-2v`w;AKEuE(yAQNFBKdaNd=y6e}6yt zTijnZu%#u@$SOT&D^IC{>O#elhTipM(^tB)w~V@u<_*jJLnX$#-~LeKlqeU?0Gg#L z$RvJ?jSX4I z!6#K+_;?h=H>;;bDf9N5`EprTMn*fw&?>Y$24^0=@V0ll>P%Uce$%L6yg+I!?If+n%hZ)sy7=tdsDs#T-qkB0^;o z5n3DtAX=&1jv^)MHD9HuiVRr^=zc^D4GyAMfcFF20)YS@FJR6hP`)H^8onF{2Rv&6 zSAGX}!PVVJAWm%4uoxrZ)K{n56?hH|^E^ZozT5+>$OIl|M$o6$=A3{^ca_Go7rBdq z$9#Q1eui^yYGgzOtQc8z|5sLmVf(LNnw%^dqWjAMKKMs$>=cqu&guASE>FEu*Xr(%dUC1zz-DxW~?$xJPKW-(c!HCJ$>=6 zmedeoGLh2~;$smQ`vLv%NkxGXBed&9R7TW?ssVB{z53Jem{c-84=;vGB!f8 zN`l3EcO*Pncmy)y!GDRuU~>EzPGUPy$dTtNkeKLl9huR<4}44MPs2(Op-k}|4-Og% z95IXfzgQ?bRrB|gQaz=;*Koj2#nD2wbhsFl2P0548W48Nfza zui`KgkH3~0y+U+@4v8G^ejqBTqJjt>^?N53zlCvk-PY#uOU1C00GLjQP7Sl#pH>Nw zcacpjemja^a{hVA2MQ*kkR-hJ2Q*DJclKMyJ{sNhJJP{Qr6)HTnUS-DnKIeGbBu{P zuUfPid?+9v_cge~sN;NNL-kcI68*GD%<1psZCv(-6%tT$7e>F*6sJ z>jeOfF4%LXm;yz&8hALkf+3@-5;>c9J4K?}D9h>WJvkqP5IhNPoec0+KRA83dyN)a z$esHoVDXeZRS3}R*v39gm%pvPw!X1g_O`2`6eEi$ieuF}AQuzb; za|97$3MKvPb`6gatu_4K@m7tK_}!3hwfBWZ-yl}haYF}T$?IOrD@g`rRvd^CPM|JRi9T1Wz>e@Mr#dxlT1&Osc6hprX z{M?$SGfnmFZl}NGiWuKCgwm{H`1<-bgB8C4AyKD~)4o1hpaxxHb!ec`!5c-;4?Lj= zpq;>$B)>MEB`yF2LL5dwfaMELSx5ew-^I$0GpnGGeRaXQtp~tW=K$+74JZ|l_mX-O z?H?U|Nk~q<&qtms2eANw_w%E3hI&aWw9fROy$NdI(8z$DmL_O@T`xe9_LbE_?Qm@G z#)qP*uex~oQ)UXHdL`M-V)E2^6Pk=F-9GKU`tDUqk&Uv|BT1*({mhFY-M&E$x3nzF zt))7n6YjJiM;)uUE&4>RcxSQ7+vEoUr-0{!Nu9-zV#sHMN=EI*qi^iKwjxQQKEf*c zj-piNu9?MbJUkkyX=&&!T4e>Bb)}Yz^>U;*IDsI7eoaI3SB_r{%qR(xUxL&1Yz9m4 zWLM9#O~>`QrPq&(n?~PZp`kkAWA}u5)DVs%7Sx?<%ntIE%}a_9l^+XB)GbTq)hjX` z*J-8$Q0l&h{-i;qAbU+lNls2l-hcb(``HY?qqgm&?#Por-2V2?FDZ7k%>)qB=k%|B~hU_(?07gv|vg!W~8uGb75o6Mf4XDOL1he1k9`C*( zL=j8vAKHL^2{q)slj{5e7Z(A-_A4%5v5*VYCU9IG&bg4 z-T-YXK{M-7=C4z8gwu7e_v*1`zX=blw)I$*ZZk9`&cJ{2-wz@exco-bBPp7CCed3@ z1P5?hpUf&QIav92r|b>+OWZC@T$|;MjUlKd&HU3?s2GZeecWiP?hu)p@AC@_-psD& zo9Bmz7C%6$37wQ*YP*eNZgQq~>TqK}+ZN=2*VoA+OkQ_;K;pW+q`V$(&cgensoSpi z-B%XcyxZ636Es@wr+wGtE*#H5A3Ht*U6jU?FV+>W6MQn@Qz zG_*7{WMGGV1NIg_WJrO{(YR>*tW?C0HdC3eYw@3~Iy1#&A8*EThddrZW8(azg zR%mZMqk1h$8=Dpq7WNvr5R~uVf0shuleLmM5SF>Ve&gQAK}C39L-E+;{2Fx3GK7SN zQb@+pzvtoPjQJUf#{kTaJ(&982rovBsy38pl{`Lu>K|28Q`3NfhUNz%pglJr8+5fl zH+wL#JpDlJX#p$y*wYztVTiAB(^*)_1ub9eU2ecDX)Uu=`=8;*IGbI3vmlF&8d zzyA|(^djwM4^2sw5j&GD9ZzuZ@wpC@ty}R?f4+u9CMRpiXlbS0frQFF?sr+`p+BJx2Bx(@hRwre0tHS3hGfCUQ&pyAgY00D%uLXS`lGp-_eWfuSR@gb5WK^&AiBr9 zABUdSc(;0j2*1bGf7;gK^r~rS3^L3)?j9a`$mC5Z`8ecT3C6qXU@tE56kxE%4wSV{h-JKSk&ol+6LwtEF>Hg85$|ipR zl8_sIlhs^*da_N^%se!clO2>y>15rFaR8jC>X+>^5Pneq(#Gs`I2!~?)LiRzyWoW- zB#;xi9SZ|Tcf7SUR>WNv3O-#a2wjy@7#xWE7vsyK%bv*gmA>*HvXJacA!E)8keZSS z{xxL%7VJuRlfg55YB)$Gg+t%cg(fAKsVAPt#GnBdep9w>vB z?>6tQ5yc$`5`GUCkdvKS?(Z*nq#KP5^79j(2Oh?xdWo_$q8wp_n4_ja*Tm#h?B_qt?Abx z2rLZP)MWcW4BQ8zwqQlt;nLxeW#vD^>z7p_Kus-krP3cl7AhU~X{~N;bL7ucc94(f zBU&W2g{5U1kK3PoE|Ad{5f_gJSNQ?XEU>&)aKBKK(6te!^IuRQNjh?WX_m+dRVkV} z1Cc}639u(1pOeZ?!tG$PoWy1xcv-tG@HT==q>mZ~DRC*5H+9+%Y;7kq1ACh>UlL2c zWQ~6V=M;8pop9@it3Q!z^+tC)#jhFJ%WEb_(y)}fhpnIWf2Yk0dnNIX&347r)TlSX z_@)WNrU|(R983nTy;2nlb0<|*RbFyRe&FMi9B#(YX+Rpd@0W#Cu>$7cR+?C1d$vCEc6IqA0kb` zcB{(4!66Rm>+gRnEhVKGLBdCnk&&U==JhD1*j@SHO>r_?p?_?@J@mayt?Cyqh!Juj zSSTnckG)Z(0?E01;{aXY3rdXP06v|`hd6&0c}3?`?Ol!e=2sSa#T7J;cdV>`Qop|z zCjfPm28soW)b!bdz-Fnc-3BSrI<|U0KhY;j{gRNB^pnXGHZv>4e zTmFA&`U?Far$#xc67rKYKp0 zI5Jl-Tv7;nC@{qJpd)H8t=Dtkwb^h7buAzvNZIwUNy9s$dzJ*lGERvlFd4&);&MfT zHB~=e8ljf&leq53_bvz3*i9$Q=E#wcL4B^Epb#)JqGI&W#J_M%g&-!cVoErD#LvT8 zKscO?Ak080ylMKQV&2beR7As*uz6&U2{1aRL{SNqTa6XQbMx_?5lblAA>77)Selxu zVx;Y=ejIaAp=hjTRxA7&5fLE)t3)`U2tiX_LH*##Kczund7P~&g-LM zKaf{K2L@;O0y>^O(1QHvu5Y7O(}5`Hhsrs!hPhc;Q)m!6PtX`vR(RKllq!3=d8}L8 z2+!m(vZ3Mq&t%}0~C~$a$nf>?VKDP89R53EB)H<_Zm~{{TY!X;VEPG zpPNC4i;DWs+T9R>p^(c0kQ1b$op64Se2!sy|SK5@0v; zTYws7YHaM-*B;4!SkQmGJosPVD_Jrr&bGjl^WXnA-0D5Ny<0wh{K$24c`#rCi9gGd z5fAbeq;#~CsaUm-+u9!q#2=tHL|4fb^$BhLsoGLV+LcDg7e@_ub(ss$J~o1CfZ()> z)M6H>K9b;1BrukN8F7dnV1UW&v{UMqlk}o^QADmI2mZfYQa&d}*v;p!f%A4H+v5>+ zll8|-sVjRP2MYfjw-Ev3gU#;IWl3G9uUw+kZS#T`lV5s$0Me<%j8}U8v%7K`tQ}_qMIL|nNjB6 z&64$B4Wso+ll8vV-~!Tgg~wFxc{B84l`dAg1rFee5~GSnmVY)~W>Gtg z2Kqa_#!E-UgX4cICKj%9h)Rq5NUI#{p&qmOPdb|q%6fes1(U0H6;&iUUK8a}uGKkQ zO^-JpZ3S1^uUm-D27UkjeTFW$5g1wi`h;CPY`{ZkgM(Gf0(NME3qx7G^~uPkhuXh1 zl?36J|J~fQ>=FLc@lNT^Wa+Wz{?O_GuT-GXU&m6Sl`g~L#>@167e#&Vbu)7TD-9HJ zQs*H<-urLfeQu*B*6I!T-{0ZDy8R~tt>kz zrs107<-M@AXVM)0C$OB*Yc>-uFd5W?rEC$Y zSmVm*U?qW*@r|@uzvX0$?wBHtOrFNV*4li$PxjTbiV4~HkDZ}R+52G=7LE2J)|(6R zmt8t>$t5RCwgJLeA4xxS2u)DDF-LI3#_5mejgmpI+Vf1xAJJ&QMAA9Ak#3N)krSANc$8%$NH z&t?3W8qrU6)_Ef~QXPmGv|j90zLMgxP4;8?+h8 zP|a!}=GND(hNfK5AJ?_okS0#|b&d02AYOZ)9~O68G_E7tTz&5Pts~}_m=v4w#7q=U z(z%^?pG$s>cF#`tjvZr0;MOK#x$KN!J?q3HRQKQ6jdU1@5$H<1-d#XbD^M%?l#*f> zO_J?3r-X&*c(h>@y}Fje-dwsiS;M}yzK#`^@d+d=jP&$5)0bxlA_4P?j`>t{aZ2ke zMU_<{{*PEvpGhJkWEgC1-B%o&0sF~q61h4Yj@t|;tKmZsoQZy+bK5>U`y%?^#pjb? zKIcdX_Y7-lYJlZv_3ToFd?27h z%tS?2)mw&_h$`E-Vaic7G>YQ%c{`o@}p$DQv16e5NM#QFkgo_1wV> zORX9A{Rf&gk*tm@*F>h0X2tdUO&MA3*X{MS&!Zxmu#?|}0tmYR9rZ1aGUI>aJ6(|7 zp1>O()b(!iMf}6#1tB|%&q=*(%*-!=9)dEsZDDT?&|{#QhJf$+J>!f1>Mi<5nb05d za>Fi;wyxq9313c9Dy7G!N(fTS7N5l3te{s-$gWnJ58y!OB&nc)56GaozKY7>1jJFr zIgj}^)al$f(ORuA<5H2^nX`*5y8b(SY6tF9cL=HWINPW55Tt@K`rqazHV6Z()_!Nt zfBN*;hu60mb9_ogkZ zWXt_;{Qmp&Ni;>!Q%wA!Vjvk!e$Zz*MD@+?*4?NnMm)TG&Bnq=f80cep{V|Pi!p(c ztvgEO`qeGpZ)ixHewOj}*TAS51CoZFogFGx$XgE&4}7X9DZo2HIwP_Mqf_tmI?&t~ z@e@4TtQY`|E)5K}Y}t3NazsM{#^uQ~Vd0b!v?4VbAhx>!VtfDU@h@!T!u9z|07%MwGZy)ZqOslA< zIQ|*^Xt5)l%;aQyIvBOkuSr)oNia0*<7fx+s&;Tt;Y(AKP?i$o52L4$u$ex-L0d_v6_XVUd@KAD zn@(*2bj2Ca0F_o%g;Z5Nhlvz{aL5?KII&kUGAO1m6uMu6`VNe5n$XKc?8L>!zDQR9 zMGXQVtb0OUm7BD31H};oR1R(@2Lg^4$F}IvuY$o2N+IBeohzT($=-7L7OZm=B7PJQ z7KK2Fh=@RYHTZ(%v&1Aye{W1R_Q1ixK=sca=dTciPg1270r}_#eSfQD_*#8rgsBm) zve?)NK>TRDw6tXS<2^wL`B<^<&UXAW;k{h>i$Y91{}LduL*O_3r@|bsr+fI>L&PVp zk$ysh?OTt~6F5SFjT`QL{TfMfj^X(yA54yslQSKIV}PZS&U|2w&FRAT-zx*!4+5!U zMc)zrx@1IAW5sKWn`$<6k6Rq&d!jB*tgUZ!p()Nsl+D!eDUE z1Ee|Iu#975jh`O{0pm?B6%W6R${71kz{QmgGfhgD#qIcbORL)E0~{@P(9mY8;ca$0 z^Ksy%z;|xqzpM68aYxwqe2~X}Cb*`C2SE7Ne-3^Jb53;*j*fvK3)z`z;sd+V8cy=| zffxIG#t-vv6E`~jTLdy*10NY9P10-jELe>8&`Zc7p;!Z%iGfKb@@uyVXW4`eY#?L6 zHQ+r!iR(c{PI@`I<^m`2?c)hCe15yOeN%_P zeM%t=XvFgNo*}p8fy(qJTnRu{!rabV-N4E~YFzh{Qzra8fDndvtQ?%RhvMY|i}WN+ z40JeG%|CxW9o*pIRQ}7Egz92@bWTet;8N>w(Vv_K00oTkF-+cV4eZHoy{Z>ZMC-jS zPY9qLNJW1T@YYI>v+?(^Jjg57UWkdkZNL2`%u+oy;tm+aDI3yyXt^^#{}zrq+JlJ- z`G|n(7w$SXZsVXCyIp4!1F8O2mqigIJkp{_$zP5w#l?RVg9hNO+_0{p&EWTcJIJ%S z%_4XNv$h`)95?~@TW!sLJT=(eIkp2e`? zoc#0qPmLaLZf1eTK2(-IC^nV^at~l4`b&_GBGLJW>lapE z0+0PAP(iLt2R;%}sjeuYm$67umQHZ%j7m6gO$h-GJI4{jXcW8ATrY2>r9vB4)IIzaI2 z_RWLTDGwN$#!;Z^n4+WyQiSs1UF28s9Fmq%1mY4jppWS3(TF8z>F7GLhOJJXInVbg zpy`-PiEp0I1>wzX{La2B+bW8PzL7veK>(I1nbB>sKEJbrhdM~mx`+1R=g3F{{DAIo zHxRh4D)1ogKd%}_Ouv2mHf_{uZ}ngMDcbwOWVn$NZ|ktli8>P4@ZEo_j4RMt-cuVx z(cbbaQMH8hjJo6F-ydYt_@t(ej+Y>9ORTh=B!!69&B3#x8a;ShA4T<`_Po9OK`oQd z|N8PQ^7fPiB_SrTP)zBnXR^aw7_|6UA-sS$zbF_=DjC-{;Y`#h38tdG1G`m+jSRN( z_i=LWk32}BSK^VW2>i=&w!!RdGC$C4xdBj00g631nc;0+fb3l$mEmzqHj1SOh|-9H z@ZD3>axLWV>8Yuy6uo>( z$;b;$p#|?uxF5Y5Nl%-DGV=Hk%?6Uhx724hRS_C1rB=MG3@MwAM!!)RhtuM#jRl4` zADi88nrn2}Y9QI+$cb;=C6SCxCl3}Cq)Li{BogX!iv%>e;j|}MAW}Cfy9c~k2T+qL zk^GPW#7;;*90cVCbg1BL6jda)Na%#iVo@JO5z%T^c8F*-Qv4#hGuB|&y|8Cc{O68> zy|zH|b^(Yu<8D3Q4cG*sjpWbOVY~eUCM%Bou+NEeZP3 z#So1~FB2e1m_~pj`{nfXF%_>vYnug^5iDCzw$?HJCo6X483l#Do=E z=3#iHV$ek2cf4&<7&0Y!h^Gxzg+)!K1**O$Uqr>?x^bH`%`!{#Z_Y9g=8V?N`rXA1 z4Js^T5%f952m0ooh+pFyZ6(f1t)g~egpr=3+K94p&U@e0VESDD4`wg~7^Ea1uE)58 zj1eLR^u&eg?JgAeV$}vHtEiTo>HK-N1o(c#E9mO?8UDvk3G6?f< z2@wmtyz~KeF6=K0t_KKF7Z)zS4{~aj(^9#kW-BGW{x(}ywWA*Ti%~XGQc^IjDHDoY z*tS|lr1YOLp>I5;otGMxaonx=7W~Q8(W<;KYu(!JMPJiT@0})dTVrFCiiwY)o`FW} zp^y+|Sy|bGIx)P6m$RGSg0r7HTz@#7bW|JAURt03@8I&xIUeM`iHV7diYk>~(37gr zoRB_=8JwwWSIbg@2=p%~>to|mXKQoH#1U=?8b()l`FcQHoI$t;B5jq^%eCQ-*gY-j zw8Xfmfxj@uk{3ej?f_Bi`L?&0Gz!U-b)jOcF5knc9Aax(CkGOq-<8ZHfN!eSb%QiT z#6Qw{yqM8OJj4ClD1V`&5ANZx$IdkQYsWeru;A{ZpJ}EZh_`z1%tK=XShO zy$W|J@AZ5j;azJ=D}ZZq_4vrRMb_GaKA5FdwHY`(i;dGRvCjuK5z%WuG&`+H~e;T*4xR?fqI7k4*;2i=@?)$fwm#G``Uf560CMJ|~ z)@L#vLbp z+0RqStB`q5UKe`X?JIx$ zFa5r;dCA^rfs^f4h~!Gv4|JBE6*JKfYujy+nUWvB_T{YEmAHxiCxu7dsZJUzIT+)N zLm?AexAC>r{T3k@4jD60`C+XZyO>`!W|%!5nq%qtx9p^AyrUnZ%9*OR*$rMveKW!^58!)vRnPpR28IDU1E zj&^}Qwg2zm1Xr+=xfp9seBo~0R-YO1N=NBOH!-XB@c!|Bf>_SIh|S>rkVhZ+AFVis z4Y`#Z^x5naW_i*-tu8X1l5QcC1%_P3l44>w#?5WUmLw92bOy+?_c;u92P90J+CSgS z>Q9B<5-Tr~Y*aQgj3fUa2g868F8b`2X$d#{UeaUmf9aNh7j#U<72g&F(jL0xa;yIR zG=0ZD!^ZgD|EQV!{Wn;-_$~U!X7CzkHyxVPC$o+`#-_4rsy1UcWcO;A{>Se8?+e_x z)HV`oj#48Yd@YT+<#Vp{G47&-<0}LQmtpYzpf}-4#J@~eqREsRPwG8x-*X%5B`|ND zqYlv-QBq0xFm%52eRyKR6CJ_C&TfwuAiMnOa_0q8>@kc#fXZ#ukKZ;7YV+hTM(%OJJstDo0L~qS~ozSRt z9T^#EZjq29M?WlEr$eRNfd8Nm4S`!%D;~|DeK~|qoU2kJlRj(}V}pBfKXt+9=qkTZ zxnsSCYV7c~0Uy`uXb53PE0^sHy;CJCf8pdDT2k*V;PAU*`@^`c`u5y}7fw9ayRe*) zksrDZdf#sHoy~DtnN}Q-pHxhc6VqiO@PU3Q(^x~!-0Kz-y+TV;Lc#y}??6aaGLr}u zpIdGvZo@@WhsF>y?KIaJkPP?FL#uZXH{ouar>s^aTA<{Q>@ccRXMd-yDPOwpKRTQF z1Pct04WMk+MQNTzYrThv)gC!P;(gD9$6F23r@J7UWiL{jL`DGm@gFGDQG?ocm&o^j zBW8ea7t&-=lNZB~z^KbpD_}?P-kFo*q|@j&DIZnJcbWQ+PDT&pa_Df1-Mmp$9Fm6& zqMpHk2d@54eSiQyapa|d#!gKh0k=?X-uQ-`Q=N}sKrYTA5z^{o((uU-9rFgCyGJ%v zeLJPBs`$qYIDR12Vu~J!a7h(fCPex?AG<=tT;9*RVSacQfpNEwik=Q#1+#=y&e~qK zt>RrZ>D?l|Y2A0&lz-z;5$F5LFWGeZg{~RgyZje_MvsGmY0HJ5(yaGu89P0_S%Gx6 zmeLAd=pValvc!HY#xPU_XT`*0@4fl_+4dhBDF6LuS2#qkUu&7eyF)(6Izjj-!Sj*H z&pd)4^_##Td&(4Z&ME>Sv*`F$8X5IC87KjMUCNk?Kh`Ehe|+YW^QT3IN% z+`$KS2&;7`3sO0cSis zzJ-wyiG53nkbDHeIaWiItO0t68JJztwF=1Je?<50X=rk0O+p9UQU@>{0ir=Mx^d{Y zz|8f-Xp0?CF&hqpl<+TDm7o&@=2}@+R<;35-2-3+AVMTrw(eP4+S>Yh0PqLJi8~oM zxG1131B^HE0T~(3EfmZQr?h1IzL#x`21|;Kv2g`I7nce@@DF-MMn+|T0l0!lwF_{G zejNw^pJa-)iq|T-CLkSAsI0Dzgn`oAUoifulX=K=I3xnzOWo+SB)tGl?l7qLPY|sj z>PH56D<4qN$R4A>#sk_y{d3p*xX%?9BzQdE0VE~>DH#x|bo=9P1O%fc<@R&N+dK?yx3uJXFpUVvStA25^Mg~JAYtnfPcjV*xzGm#ckLv6@%i0*CLW%eXCMRqo{^E!2o1C?$VD})yie>Jpz8r!jp0nA=ltg8<^;I% zc@DjNi&BdI`!AzUh79j+>??{t57Ti9>6AP!DkXFKUvfC?dcTsZo3wQQ@vDJd@5iMS zi*31dx`ob0o$Yqi_Dd<1_l1Ll9D=XkuyuQMp6@O`)#5F6S8i5JjdMKuRo1E7fP)_3 z7ESPvOqjxc{9?nmgYM?j23FO7?UtCCL$fm-OQP`;vcF=b@tiI5?;`H;Q8c|`@ta%U zAisDF^Ld>UwvRQZQGYS>F`Ud+z9!{zrdPk(jHk7|IR1V4M}w$ug(wOM~ z|FOk%{qxv_gfOVf5dlj1KVVs+LS?>tU%+isu1;r$QdCFC$2K`R*`MO6QSb(+)@%xk zilX5UP;8s(o{fM8_K?F0sr^n3v(w66Vc!k;F5KMQECM;}ZPR08q~O;m91y-J%mx*rDip4NK(_ThENnl8 z*KvNYx3@Q+Ke>2@4t!R*x}X$3l$DnL4n&qB*b=Ft(6zO-fx~DY7>Lqp^eA)q`HA*B zpY!tO?~Nl{7G9|$Q_hJZYw#xbKsqY^(4@QcqsHQ5+ z{qA|5=G{%PVhE ztgA$n$QKuXkL*k{GM74y67_kIGIKo({f;jcY^2KB>jj z$FuH|HDxeoRi#x^ne{lXIGilCrQXfApWo$sL=AfygV-n($Mxmuw+8K+@e$6R6Z_BIe38tXtRD@ zD3QY@3x=^ln3ZXxLYz@Fn*WFxYZw?WN-ANW_qDaWfVi~x_v2FFqQl7xH5!0R2x#oU zad8)PzV1RYqCU~DVw}$QO`~9+O*Q+HL$?Ud2sDJC_c1nTs5+o6bU4}8{rKQHlT7B& zDbnDmB;Y~L>^ildDB+gN8M4p-Ts8?v9^==qKWOBuI6<=~m8~=c$sFxQWwlyGU!1Qm zJ*(Rc@}9jgTk_-w&=?fb1c0al<$4d;%b?IubchcOh8t&oZ=nn3QH#PF-w=@6-P?QZ zyE_+%7uQo%xS^rRjt5kl$N3?nUZV$+zP>(q=C{{?^7Ppt2it-jD(nPYa21L{+Y0zD zZS*SxYisQzsFKJ*#T@_)YGYwxZ@w@AF<8f!K`ep`5YDZ!Nje)@ZWw?}_{w>N`;3f? z&5hh1B(;JHy5`OS6@u z`c${FnS&JeMxlQUvD{u?)KE@#1R-LZ?%QL2HAF%c2CY<-{t7%t0JqlxIixE}Y1h+s z>dLEL_F^?NpVixCtDkAe!UTRjR*7GZU!fspX8IOk)>c#v>4(L*Vm)sEqtW6Y6=crt zS_b7csj0IO&=&LlG~s;pm=I8&d)R1zOqFi72BIv%&o%~1L!h+)K?D}#=bgDDenr!d zq=?=Je?AU3#-&om*;kg&3pyg1&MS*=x~%s$spa-hQ;8TYc12FtM~SZP4=wTW#lJvv zktt@BEXZf~!l8aXzZJ{ej!*g^a+Rnn#)v@1+_)$Dj{CY&wZU;IOBH{Y@zOcU0vew7 z+)UM^gHDqZHr!~AF(hZ&?2n2OwJZsK167U-P5Vg{Jn0&}@nl4g061`;(W@<8Ts=Eb z<)KL}(0lr-;lutGL= zcr~%o|G}fUnA`1Ts5FnaXEap0QgTlvpF4KG@2I|zPhOYfP1+6@z8YbA{P+%d!oexi z7P&R)%Ercqr$a=vQ>~K!Mf=x;-Swr|=Wg+)CI`dWEb{@crS7E&M5_c-pVi71Weqd` z`QCU0c_M4o!NqWHGOoFa>}Tn0wKFHazLh;aH>;V;!J3{gx}5Zn9UzaL8}tWgCrzM8 z3X!0rJDgH2s23a^C6+5>(AMD`VygVTK-xzK!=<>aWbpYW#*0OwR%KqLgmj{ zjFOe1bKRnL8DI)qCUsw8l>JQX0B*EGRu#P#%0*#eDv){JZqn47$@w7I6SZzz55U(F z3>ULHoAF5T`_s!Pu)^9GjBh})Xeihh0|!=udX}yw?|`QorpY4TdPYHVyZk8mO-(tj z{f{KjMfETV0Ys^30jqEH0(voUX;XnM0v$m5k5ochx4wxk3obuRa)zibV^lP>YIFn$ zSxCc=esp$rf;{K7iLr5ek>T3wHlwojBQ3x^7nhdOO?$p5FflXL!tw-Vl~}ft>IXG- zb#;p>*HAx*gk&m&EZZybhXkqZ|K_f*E--I@n}a)H z6}T4xd@=m{_c5!qa3D(oXv;uRgn)p+;ri%Z_ZArcY3D#$yA~1x&Gnlam-om8YQ0UXG26vp=`*TNY6^K@zQMbzk3%rizTCu8Tl1TM3)}KoK-!pX-^MsA zg`oEsS99;0(4slj%ia)=fe>nW_e-btlidD}DI-Q1*B(}9Q%}F9i^+amx{%Q5gx;W7 zR~ZlQiZhih=?YZqRG2Ki%l5l|5viOT;;a@DF^h{eZ8iV;O$X}wpdvFONZpU>9gtoP z_jj1STQ9qzQew&&ngxmGECf~8`*8ayF86i!-(A(uJT zzpYD5b}`;{=4iM5b8k2YN7(P2>j96Qj;l~bRaFP158`~16O zkVWT~(&Rb39TdwPS7kTe?>x}#>jSwOh*t2wU5yp#Zj5qraQOF0QE$D`D$ha`fLzX8 zD)yl?P%`c^-9SXCLB)h>hD4ECW?mi!@B&codTbQcco2Rt`IK!AG^h$|T#s#o>xS9M z>QLsa>P3^wni3oz_d`33G>I)*AmTw>LgF7>vyj`+38iqE`2bZCuOl+tuYbx-?*b3| z4m#U$&q!#X`8hZ_%ZJZ#_KYM$BK+F0IEciLXp8FKYhaYriwa=L=7Do0?ca- zl%uGlT{e*H1wJgs%JOn8U{QJBK0Gt^N_9s8|Ao= zRGUw1mnK1np4Is>Du;LRn$Mo%QXjP#2jUwXt#5PocF(wV{Y-z^U2U8Aw?E~1#LiL+ zK5{p2t*3v$Ok0Xd!7@wR?S~?v8t0vu++H1>Hodq0THsLySuN(-gVWRJQc>GQZRtvm zi-T;7%gYZT<^ig)3`iBB0aRfVJaJ9{Fj2OCKIczOz8ciY;lAHXA6X{e&6>=&a^NK#8sVPj~n=T-Z_C=)!E z2%(qoFaVlE^?M$nSJMpP5aIt*aYP{405N`fzUU(L2$x=D+py{e#ENE zHcQEJ6jcpufgcK`y+Kw7!rFAT0!1YyBPju7=V0M15zL? z62L6n1;G^7OJ0zpQIW`Fk5*+nIkpYQ1S;fdxNgq2hydUTG>oF2UL=e=N{15QQ_m7F z5H#tjsj2O-CwrlE9oQfk&r0aR2iyzR^sPSY$rDk~B>{^CYUTAI&C;40>d|sj8SY!( zb2?o58r3%O5a$+&dl*X5U#!T#)Ql3Zf|E`NjAOB@!8R)?#d-M0S9^Rz$pEn$;mSX11rwlU}#ORS`R<$-p8 z%jcI}J1^2&F6S3WiQY{lRaPlEZYe-(XhQ?VbcHE_!dlgw31k37z#$ zBTRLK%c-?MogAR*eJd4MY|h!9;#=5(VOc75xpj_jdAZ| zllYI4EAI}IK`aW&2K4DY+$^>LhUdF{NdrnQbGQn!uMaY43JSm0JfvT1a;T_0{eZ?maucfie zAjaHb@h5=`XjZH=r6FhuHhR8_Z>cop|JMR!6c%EGj;I~r;eQ(&cQw9VK4)cRErt}Y zEhhGPSg|g*32^<;sOwM>5tk68R8*sD&dklT#=~A3Nw9?^G!skzv z3r6+GK8U~3D&hv*+TQbJf6b6Zuw>>7P=CSObRE^Sfg6=!)nZ;@3~ZU8vMg#4nwh9kmDEp+X62L*;Q;;mX>HCn{ON>vE~2| zTx6t#kUU4njsm>E$EJhmeMaLI2L3rhkPLs=&mx?fEi4=mbesOJmX^IfC+!MvCK@iQ z$A2XcyR1t%-d`Buz10eS$iqVhha3rG?5}ZVCML6q9^d&N633^}`chH%d7gT~V5we6 z2z59(FN+!PYD%NmL0$Ss-;faPS7&<>>1$y6C#5xGsr8}K%?;&Pd+3!%=*i9DFPR1X zt-+QXn)5#&Ue-GO`%x9!Gs{nOa@609655ErHobWnorm9(7?@IA!(+qLMuZ*sipdnQ zI|Z`l=ADuJq)0K^SyTf|+H^#t2Xb2|IwZy^dn^UTAk{hqpAtCYD>mZXz)oH%uV$u~^U%=i!sCZ&ho&kcP8zA!0e?d!13&~5aliZ3nvb~d6 zQ52dVBN`UP(8@vYrqk?m-zUuI`d6oN9H}RAk(PggaACQH z;*qBQCW#hgZlo7!9kr$8zpT^odzr7|299?`JIAP4K@MHtJVB zKp;i__APiSbF?)%UXYWopE)!KfLSXT!(S*8mzS4oeC|G!K^e(_N<9Z1#E9^>%6n$k>+#Un=9g?K-7M$`LwIB~TiA*( zvbs+$-XCquf6a49jaf{TC>|2FIE*^m=)SzsSkn)^@#1pa+`PYo85Gn$${^2xdSot~ zE!d=!#ya+hp#)>1PK}U)qPTg#3#Xe*zsSm(Bf&jIIFo+_qv@>Xz+JLfhn4Ty-ci3% zd@nU!2M<2+Vgy0i*51OG0|(b5(F(J^)`dOdvP=ZG%3<}8Z;V*7Ym%ZZuH~M-S z4bLx<&&@_8l5)by@!$6^QrpBfM7p&;^88MRBfn4ehYQ)U?PJ$URxOaX14CljVh_h>y zik|+pE}?z?oCNMzNoeZe)P?2$QSuR7mbdjW*tmuzGxt=CmCa$m`1i@l$&zDt$V0QM zhICtFFE9RSxRS`cQKd+#?Pv9D^LwDx0)|Eu1EjwI(?TGogzIJn{XBS`pS~RCg0zSr zD5$^onH6ePg&{ed`Hv>_nH_9{B+<_SXiSknQHR+qT}_e1zIPx(0qra*geihVJf8~V zF#|)~Z?2{aVLcd55#@KeC#7Gfb1mv!T>ef?^Y!xwIFL~|*y8V>3c7h;lQIp`xmhHu z!-M$b*{gw9AH!l-b|TnMeLKjWF(?1?Rg&yLTh#AyXkT49aYu8&!@00@%pJ(Xby=HF zDLt8MOI_}ZkLI#o)}E0ZwzYJ)`xF%ci{D8o_F0Jr-y=r5vzo?-wiAmY*Lfn1FXZ;V zFT8j_F{VAioh4NezEbo3wVjxShB-FXAqyelXT`jyfZG6A#&wU4_UgP@9Yf;n6R{;l z!H2%4^NB*nMk$Z>_R!<6E~--|&kok71)~)V%Imcle-)zam|2DVyAF_iLNIFYSA@O! zfZ+b}#jhXT#qIARX`~`ISKPM$B$YZFHxyCGvnwr;)A0)xJ&O5LBsOqAygZfjqU&Qd zQbXz=G;vhcz` zoxCtHMASqTv*_DRxKPpt8C&B$E)NHAJ{eVj14IFsi6`vr{-QQ8^;DTaQE`6@6SM7D zPrgB%E9xZfZV>~;5&eIpT$~|hHG}2D84|->IDpcCXn6c$4y@y!x=mD_f8Z21R%oyk zn1SuX76RJ!KwS*kVHRVB_o4Zz+R-4<2Z!J7;%EYRViaRV9b#~91|W`6(8t&JA6N`w zMYm5+Q-aS9P(A=xi;pMyJa!H0I*iV~5$s8V>ebrW&8-DXeQlMT5*}4n= zZ8%wzj;?M5*nY;q^uM<=Ro9+tS+95`tw;~2 zyH$uuNDObTuj=>r_uDKCI>51$3O*qD7h9Yv5&PeMG{9^?rF?PN*&Pr!PlO~mBvxSN z5&9x%7C%JFtwK-c!vLPOYK(|qaE~G4RkP-z7i&AtzvwcPL4%XkjPFNVh(8ac$59Z) zPTgMvQRu;4Iw3v}Z+O3C=eDvdayXm;y z?#wUX&8_s24>a%2=TT!xANf$H>pW&i`pWJ^^8PVr)u@*UGD!Sgkvh3f=i)gn8?9TA z9yy%;M7nJByo!%{BxP?i%9yl%en_UQU1c}=T|qHxMbRj6qL~C*PKHQ-aGWivJ$J3PlKeUi9qBMwn|8E;eZ>)MqsT}-&wKNOA zc}xi6xEh>(M-Ywo4ytBZdYPxALXY+l=0g(|%h|)Z z>>g_!Wa_DcuF~s(eh2LMR-)Z&STi-dJeNPpDlfrt0E~LGVCyCekZgh65rR?^DrC+0q zuP$)xk`w-;(t5UIsJj#+oefy;dp0>i_jlpi*Q_P_vt-3~mxi;=5h9zDkdb;sHj=_*Qc2k$^$9m_tQB{%3d9gj0bpNx4uDJ4MEt` z;u{cR@c+EGtW`JkhXNr?xA;akDLg>Q*KRvL%f6+Gi=3zbLSV4yuYJw3fOpn=K9Bs@HP99iQdKk}c^z+iy1{s7Fq139$C8?ae| z;WcT3=fHb%>rt>>=!`g*j*c}j*NkG0{YCZ;m$Kd!V!8TRda$7NzYCB+LQZsCoOyUu zR0+p}hy^5ynjrRk@EX7;5fQ=WI2oAnSil(ojx7A%yEd?|azTpjKEPeo&S}^8zf#i*Rl<;ub9{cr`y{FUZ}OOu-m!f zdq+o)q#^6V2KtkN4jEN)$W7VZ-+v1j;{3t_w0k97%R6cxtUI0|>#r};Ztg`3U~kqMt$wA=&ByxOxA$+=WW!VL#4)P=o3OYde*CXUI`v+e zd850IQY$r+lQZ=vt25-eQ8#Z>dF)4tBJGd&_rW;(Wm)3)?_WRt zufnFW#hh&SE_M$6^>f+JtVR>w1@mYmZi}Vhn!96I#=ChYYTUU6B zHWbu{OQb5<8{M_>Uc3V2V+?hatOj45!!bQ)JdSM|>?+J}_9nwfid=mBPUI1hQi?1X z(R&_(v2Sxq{ts1e0ajJGb>VKh1(XsA0SS@r21%tml@w{|P5}`C2@y~_q`N_+qy$7j zq`O4AyYA$i|J?gr9US!3Le*&HJu-B zZ&Lw*m;RGz(r7fdPv3Q^XmSF$4nz09T!MwYRH+T?)Kw@B=2FaYz|YUutWUD-GFf77G^+ zJ|T7A^ipYe>@_6gwH{ee5s#|^pi_k|%dj>p)F+ILj7h`RhtiaO_O6cde6L;xSyJt ztYzi$?9kif@6XSgFuj7CvI=x`-F5WKEAEkr4tK4x#5|dSpfHpINr4~Bd-u?T=3gwk zn4C&Ee0}oZ!z%V0Q)BZpVvtiY!fA8|_O&*D((=C2D1R<2T(^Kp5IgkBCU5Y$1u(`7 z@9F8O(JLMa`5=G&Zm6wo5j(Bl{)%*(4jS-ce$bxg1lK8s($LA(`L-imX>CBU3bT6= zY>+fm2wvTH;PSHCg{!4!dU~3M0MnR*%wc_m6;{YN3IT_7+J_HUQwJ?KP}1wLM)%cZ z7w{b*Zf*uH{7Eo#{S$GRllTl55!f@KDK4M=9f$^w8)KYpuxR2zD7Xy5;)-rYT+nQW-~iqwSn;) zRn*ZAGU=A@h&5A3b>VzzUl6wpqUpU$5RY=9f@lM_%EL0-2bhE(H8d}<<6SY*Z6loD zN$f;S^_Pw^M<%&%{#D9NM5$r!b?$qd-Q3))pRLYY`Ih@A$=+7>jU<=-c*P9yOXqE{ zx8OibOa$+&U+<^w>B$15oKfz3>g*Qbt3%n&BSoI9bxQZr!0-;PC>mUJ6bL+bycpxO zvDViwFf8>idFUE-`S)Iufdj|V%*>LeWZ?SJ@l4Y13av+@tx_SF&!0VmWgrZ!wWd(u zu0bW@k0=sNHt@f0yo}+tkY(4akftCeMgy6_$ApAM7)1y;|BWz*@>3{9ng5OXc#yw| z!I_RS<<&6N)zMU_C4yS#m48^LGrCxJii#bor-w%oe^Ouj3oa$}=wp1A-1|a8Uhnmb zw`4J2!%21u!;V_D{+=XRfm6g+h+cAab#vRYE7$%0D0lWZq;=j+>T}Egeb#;zwf+l( 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�g8aa5btFTqSt8% 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%0AZf2u>QUsm8+u|AB0#`=#6_uPFq`*Kv!n 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 z zM|ebpbiwEns5Ier#K7J6%;GLqAw&oMBR=*m6acUAs-|89BkIC+FTt(o8h#3|YtXx9 zfrSCPG29Wb)R%sKu8%tf1Y90`bt=x_t9PiWZ@vvO^?+zPT=bZLwqziTA{(M0KQ`{T<7~AOT_3Be}9ys z`EA0RZoUgWbOncKIaF{vAlZXz2Lmt_D>wvw+|wU_%yQPBw*(cmBox(gpg!}lpbZB~ zrW*`i;<_}IoKnZ=hQ9Q$F;-`5TeH4hc`4UVT!OT2zT-a_^QE#yXO7Ge8W<*3Yml)1 zw)7P8a$X?Wv|=yL_1wePEN3=Xt27jT*4tNS=D#{NTiO1dm>=hLEhg^1WR2w%LBr-6 zn)Ujx#o?}gOcI*Atzv4KsUb;44`biG`G~yb5(&JVHCbIE#NnSQz7ej<#bP<-GTpSf zN?V#>#NRWx#C`n_6KCkK5LvHYAySmO;)zPwE5XiXe;%awC@trIMYrKDz6}%e7FbP7 zHx>=G&U3dBWPG;RFqw*?c;MXH-;V`eQr0l5#Rmyu=>y>KEO6C5ubx7MxGvP-E8vi! z2D`INwZ~M^X?qW(4C)n(?m@yzKMoEp%UzrX#}F5n8;=#UQvJ`CLybGleg%=)tA^E) zc+|N0y`e9RamXSgN0QbBbF1VWffUWcCb(izdz*hi%Fd&K8@Rm}2MR%8J@^WE|6vwn zGa%dBxv4$(;W+&_VV*cLQQrJ-vk*e9ACAF0)&;}x#I!W@%#S0$=);I;k5W$MxPv&I z9(!&@YLt4j%^O{oLLs{v<0+>h&H3bgh-2SMypf5aELsu;4la8@{9yt{sit_1y8iY? zw;eH*Uw!^7@ed4pSNCXGiVd*;&^FSmxyb{k>7Fv331`8Sx zB6bU~vP+?^gzLkg{;#_pmmPS&TtavJc}V=k_{-cq$$scAZQvfCgyHOGIAd*L!^J&Y zXdZ}+jGQl~%ZcBdC=Y@-0vakQtp}fUGIN2=X#c(Pk9Mk!6`Rn`zCkdt5)^jib{{otud?+A|! zV~Jx(@csjbRR4-!_~^ny&_h+#msfyt$-y^r-^Rpjz@&k83*No#x_RHYlwRv6W2FjZ zr~X%CaC)1HfQ89lI0e6h@S_i|lC>vP3D1e8N*u=XY0S(P++kq${^k_`<6wsx!*TeD z+9!Be(bNyP`Z|t`oB~?$(y!^yi zkdiA|>+ZOrn-cbp^%g>*J`A`M4%jP%RLrwgZDwPsR69*NKdGHY& zsDEILr;i9@AEmoSZG)san(S-j;4Vu=H5C<{r>dhwh?~Jlg8s*B*R}6=Gijn5Q!c;2 zmnD7nt#^UydaBA~KFt3VEF8tGYd@jNJmzuA?Ns3=a9{FCPI5Xz8 znR}lSk+hev#JI|(oqZy7`0e3PHMIyARYjz32VI{ViSFOAF$Qr+?o5QCr0|m;3_Cz@ zowXv1l(gw1g5hTLA~fK-2w4!KdqW-JWNZ6z)9m_Rn)7t^lPh4j5>7kS7Kf5trM!6~ zkw-qk)&=yFowsWgf`I`dW5_GUoIwX_Rz{%OvKp+_Pxb;(U`UVC9+K6RBX>`YR zA8KaJ3OGf*iAi|@L-A85z-zw3%<39y-d7P35kMV+xf=*5U^*ZG*PRm_!^RhF=+xSG zlW#0D;>&cm+!+)FZw;s0OnpO@=D(GPKtKk1!iyKbJh!Kbp<{0Yad`!ht9Fp?dDhyd zjM1r~B#8z;^(5|$w?CwH66#9&JtNX~$F97zr`TI-!|icU7|elo3SGE7*zk&r{lUF4 zj9KlCacr^$nHJ3JDZux{Oj+Y~;o}e$&_(){`W>aj=L>lMR_@Dm>qGtJUWDEv=lq61 zl6j42^ZVn4nZ9@Lrym6w8cx5mliEvTHgx>r5Q2Qr<*g}X0Ea#|$B@x&Zf*imYd5*KG&I+Zk{8s7! zC5q(wE8M}{Cz*pTQRQM(>+X>jY^(V!n{!+yU(|uE=KL4_*@k$J9AZNUVrfN_5X@HI z^Cd+xAhkYta2-{|9>0pqGAA5FHwnHJ-GD<*m8!GU3IHbJ1A{tay2Ms%-i`0J2W2o? za)scWJu@x?A;D)K5r9Kyf!2u|;TB4BA@o)b9~HD~RAS!2a1!y|yrl%K1GG*2n*v|wxuah!P)I6l>K6q2CO!Zhx6Jj7w zKtLV{V1y`&l!nI0P44}Wg_(~2*pY}f_6NF@0&~YZnn#OQV}4-jsQEO2X`YIFc;D5 zTb2bOA036GAGZ#x?&go@SD(OmR%ceThR>f;se{L-}@nDIJ!zWrQDG!ssS1p}Q z@U&tC>P@5U@bCs~52CLXhDwV3R9 zOyuWVT+hOXDtVv!Lq#r<+s2d|MxfZ;06{A zLF*5;zwC`)cu0c@f@`=Ww}c$?sEv{PD?8Y-L>MrZ&7Wd&M)CQhbJzzEW7WIsMd&`Y zGN-irzrS%JbX#u1>mR-j|7I?E3Lu9;Dy6Pl45e;XO8`B20Boz(mlPwvwc5(=t45)C zYDK|QrQB4H68X9Gq`Ltqg+!bNmErFGL+DbIoW^H0XC22+Wb{asbehqI2&Kq+316&Z z$zHZj8=@c{ZQioty2|;;IfJm)NvlU2u8b+S&W*7^-4Hn_e4X?ZclH}gUeqI&3zc76 z?5sOq6w3rNzpqJ)hDdI1O8xgS?}nu1<}P3+G0@j@XRqL<#!L6`Jg!yxKpvh{wA|gh zadB;{UB!LEKbs@+3+cnV3W-$8D%NKE%({e~cR^}_-7Qb5)?|SMh#>J!e{;wGWN;g) z#p%rVrEY%aGl7g|&$LFy#W5)+k@Icz^0R%Zm9dDK1bkoR%Phuzl{o@~=Bq1(w0n|V zdw|^j6iBsEKAt!~Q0oms#}N^MCt=K7dzFZh*uPo@!ydD^E&?#Z8oe7C!_C2Aj7C$% z<##n@PqjQ&; zHrH_Wx4@P@QL?9CCyK2>i0BaWOi^WRS1Nt*MIkO9KR7-(IDbJCJp%rmI^xL#wpRM7 zb6^X4%8D?NJAtE)67<0v&>LufNQwOT1oY25H)m%7G~jX5zx-zn-+w8z9+oY->s!Fl1eDOP=pkR>U+ypCufQ(U3+#SHN-uv6K&vV{dp zC-cDHl-Hy$OLAv*(Ddr|t&02J&+Prmuc;noC(!+SSSL3gL-^zCtZ`>#M2NyDelkNR zD$;$$c4dxluT-*j&z3rVB$#=>Rdu@T01F@{P;PS00IMkoX3LAKt7s`o#IG_lr*C{+ z2&<~9B!4*6P;9zw=3-^xth5*%$~XO~7CrjNef9b7($Ha(j`{bZ{<~=-NK$lt3oX@^ zj>Iw?BeyQp zy%?RDInRQbW5}#Th-zrDF<@c1PGiMm4@7dD)zOw$tLhd4{dA#P5@LT9KpLLZ0zstE zw0c}b4%l`;aWfBHDKEh9c6$4N?f{w?9`JDQ_Gj}pWDflb1n7DM+SU&ON_x~1TqL+S zH7T)li4&Lb-c>&vZ&L^#UqN({UKVJbgap_PX09Ktlrty#9;m&~zAXAFPKmA}|57um zmv27#4pI3|#){vymB8H=_mNEEd$a`2V>RxMfgc%&X#)ukUpTjy2Oa)1x;1Pz$6>&@ zlG-zUI_>z|riL#1ozxvv76gNI-lTQ=>fXwT&z7$Lm!OuzDpE5KWhWTOnJ{9stCdgS zJ?#DVV+h$0{N=+q`bo&KBXQLp){;_Sb06EC?2z8i|6$3-$eINGIH(7z@Ozq z5uDY`p2}xWbad5qyvj78QY~8D1yCOPm&`{ovY{{=L*-EjV1tN?ysZg4{l!`7?-lJ zkdD`1kZpH_&QaK8P+6?wz3D#py!X2JRNLsp9?#_xJ@m()E{?@3t9TRBlR{jteYBX; z&I2_*N|(7z6(-az_Tzm!B-$!77(PSNwxT`NL|Mam#+>AbmD-S`ny7v{leE%JNmmlp zi+ZOc*p@7+hj*0!g)N`Vk?(Ad*xk~x*o5OhiLv4B3&x7f2n^KFVQ94lV5Yv!T2J-; z(3`U*zYl*7`i4`;Qy0X?Kz;jWktnXK+}p=zHLhz}uQ)@MptYS<>m!5M$*eo`c6%SK z!yCW94J&|$H{3RtMzd)W8}tP$qBt;qpa*bI5av`CHHLeeCFP+OWMCGTK41$Y$e;bt z(MTu>-u7CZLc76K>zt-|H(}mc2|yVE6jY|r8&fas?Bw1CU;GOOP))VWK+Qt|Us{4c z*Uai&XgzMI-|&?>dX$*Rpw3z zzco1z7VLM17fk+Bc~u-r$j*8W1G`5lr!|gIlNCINwT86j24cBcagufep-(2bULjD+ zzlH*yvgDypCi6nRaQ(aVVj?|$&nm&M#@f>m8jQp38Pe_q>Jvz??iqp3IN|-1e;%Iu zxk>j$aO$Ovj3o7Kc# zYd+w9kbxQv><1|0o#f?jF%V!rNC`PygKW*jZY2!99%<=q*_Pr-+bAYxS7@x&YPi0#IP7jN#gu#Eg2X4tFzB;=V zZ2lsM-7*O|VOjbEA6=yep(aD>A)hvF^)HEw8uxB5QqtkOulVu9mcESg&^`*HoTvPu zO;EM-&(OZ~(nOJ4ZWQAki@rWd&|qdnVZ9K8TRRUIZp{7r>bqz7i46KBM~T7#df_C9 z_XP!3Fk^@X!PSnUk`np)$H~QdWbn}>1DRv~?VYo&@|NMxRtj|m1rT-d3XZ_*ddCT_ zTrjQ#pk_?pK1TN4JTQPRTw$894>?4@AMCy1t8Rlo1$V|{CcREu)&LJE~(5 zmrHMgcVkDybMsIhz;y25iS1^TlvvKhM?dS}?ff8LL#Gk*863H=;H-yR1!nlsv9WaF zG8SrjZ>DBu{1*GUTOI?JMgp^v8{qyi69^}7TvBTwo}u|xm>-`pn2k~2H*ZDEgOCPX z1p@#Sc>nRE3|E>JNT5Su%FvXak+Jb<*a1|V$y*$iLU3o@fdWSB?EG8-#YMrs#s_9f z2jFM&;~Y@Gmw9P$ZsejPz*S)^qqViw9`WfmX9b7j`AN%l4inLBsOO;8SEd9mJ%ggJ z`&a{8bJmG_s%lQ1e?waOa?63H5&teRf&dM*X#su7$gJxy2%g}Cfv`3JYq`=^ z;C=NfnX@9h1#t1V^Mf^E+0+0g6xz17T|A6d*x1EHhEVwA0$f6!BHXdF(6X@C@Pf~O z?DC#mn>Fv!+4}W7+cCs>dH6%XXC6yzKUTYrDm~U$hO6_&w>!;7eKLA?)>nq<-c&lL z(AU2EGd`t`=ultIPr(tBr{+wpslg~GjdXktmjeq%0P#H|Ho;$yV?omX&q&&OZm|!b?Wy2&RYoEzT|D~592TNf3 z?}HF`omeC|N%3FZM&;R_)>*E(tM|i>@mpu`#gU$OoNOKjvREVL7ZIQ{!7Bl((1R?n zhB*ejpc6b}cif^Lmg(YcjpTRtLc@+886Ga?CJq$7WG0n9y^=9!G*3dPa9)5F?h5du zxm&>U0h~~Qvf^k+^bXh`U+iEnNx;GcE(a{!$=at`JD{q24o5OJ(kpee?(RW4N4Nv>``L`wd9iEwK8Ist=zn9=2@~1A5UcuKj zOc%;-7(bK2WcA#cm@W%PjB4oqBa*l-H~`$DIsU`aL#0aSE_=ja{Fq+mp$w=(sdQUd0G%|u$6CDYE%i2<1tA60z9op*hVw7J}jnr_z6io{c@zF=2L^`1AEg z3kUV6NEIohf2F9UXI~_mFgC~v`ggp?kL&-fAc++Hh=A`rQki>)`(F3}i?l?zmh)4o}DoQm+FdKhkr)^_z_J;0SS61`)}s=Wlr&Qttsa8$qlWtKNejRI zFalITf>~ufbKk%B_4P4gyt}G#oVY=SvG4Mtf&&w~h!;l&rC`>;80K=fI#HLdW-~R| zI3w`Y6=kKhoiP!CZ+=xjH+6QMhEt2VGW%L2uAD8fO54- z9Rz-JqJHx}zVn67esk)xmQZS|C}aY(%yX7I%L9IAy7Ppjh7yA-;RQ8TknQ_lq7d_i z`yfU9x1X??n>EgTP1d3&~~P1e`C!NrAVKIl3C>=wGE@xwdX zS8+o_+09OSAo$A$`($tL>;*&b$ZM>--C#9PHRT1a2udBIE-$w}eZ^WAD}1L`a{uPg z8suGfi5a6;=8UuA9V{j2?y@ik46(cKJ#-IL@gxztM<#cD?Ya>c!w(3av2 z!xS_YHHfSU0QjwJTS=^ATYmb`;#ZID5&h-Gnfk5FJLJY87BtfoOK)Yck4Y7(-||$t zZBcCD8uAUL8vUDM;1s#yTs;ygc6z^c`dP7hz z1Tqk*3-UM1&*ngC0lqa_zHtSCIIuwe$pimLN9n_l#KBE|p?lD$w*k7$3c$U6rk9Hn z0|5~0An)PgbR{7K&Wa!6B`@Sx=0SlcfPj0y2&}I`>?JOZztwkd3;yGI^MpPB-=Y^Y zPJ-P9@84H|-6F_+EI&&@o%MJbWcl(|z5LH*WROdBw+!^&m=uiWOn&vLDuZhG1|9&x z@oi@rv&O98-y^Z5D5wb+t$}%%TBMc>kjFU39EZNPd?0fblWi2J7 zTyi)GBayK$p~V)m4cQNs?CTl(I58aLy}fhIHUG>t|IG7y?&n@U-|t<;d;|#;GZet0 z!?K8v0lUiJT?DtoSC@bk0UR2g)eA+#_IuL;&hFk`ZhsBH1EQhUjE15)8Y~c_!7S|I z;lmnOnt>1DVPP6jBk~clL5mjxxr}H#jKW0PVRAAWe48T0-YqEG-WN9PC&Dfv(*BH* zXVperBIT0)Yi$_myXQ#rZ!A%p9Z`7lQ=90zO=9wr)7beo_H+N$2b$Kr)aKjNNbOD0 zLu$Ir#PfzaN-CZ?@y(=+p!nQ~QaaU5orrQpM`8bD`&Os?F;nIG%O{ODgcpm1WQ-LHoJC|aypkn5?kw8-UP*G4Mmo!c^rBV8!ZrCRwd1! zZq;H0*^x;da~5KA$8c{=57k%#U`uYC|2$EEHJKWyhQ+!zL$>;UWxU?z0(cx-7#a02 z3+|Iqntp!tQmE43z)!rPS5X^zam8WWy}R5vxFsNabbdW(NJkRumq7{S0@TOGEE+4xLCkVOJKRgF6 z2s^AoPS6&g@5%K1y;{4bkf5FO6B!B8p5RM3T!||{p0KwW=eZ&d9Z5Ch_r>F`=H`Fb zLsSn2;MTql!m@2mAa#oKGYt6694bN(qoZLd7&h=2l6G#A-c4(tvG|c!&6Xs$=RjK1 z>;3SnX`I)Jr*@&t#t?f{IkHC{{eF+HjzQ9qorpMkh5C0kZjI%8bEsYY(oBPX+9uyG zB<03Qg&Fs2=aPbE+PHo#ed9*>ZY>jmc4q=oi~y_c$DY4+ZeJsnD6fDGd4Ho|RMMc} z1DzCubDho(y3BmRUOW2k6?}i$)C7iYY;xCLqMx`=%;vK1S6g4p^pDlPjOM>7y2s<2 z!&8RGCP$_eM~GVfe5IqNRXvj55NxR6G^2g<)p_LRDHgiDJ(OANC*rQ0WKLi`J~_HN z#wHMl@bT%(iac(n&t9ySSs^5TG2!$@;IX82(z@pdmAYMX`a@tz!Tu&RZ%Tl^@&WQt zs3buly;}!V(zjtm{T1DxA<6%C_%7l2AJNK+sH7*#I9uM-%N z>*iiPau%dwqg5V5g%9`$_bzZc0&*S?wtwVDi>>|d<`x!=4}(9p^ya4x$rlpQZm%rC zmuVk3j?3nb(lm&6J7x7-BepPjz%_sQqNI@a6~>9@; zWAg#k$)f?tiHp$8Vur`<70i0FuEai~g_qf{UDW7>gjdgS(YxQotJ!^$=o0M*15~E; z^>W56f6Hq4$29vNW3{{-+;tO7<;x*lE81STG&yFwu3BW*b2=s$sgg{6(&nZbtM(_W zP6#W64JcWSoCwG(aA0{=D^kF<`=5XQ(L#jX?JBY?%Di}}7Tao~XLxY#iClfkYtAL4 z=$mmFZKOexgN`;E^AX4i9>qLXjd!i!sgtSo zlNS`KKgLH;yF{L(OLf$@1b8P5;ONxg?r z1{iotogm6sHR}#qE7@O7qTWF*8%fGbNi~9GZ3DdZW8Mgvh4KTrw|u0$%Pj0{GA&SB zyNyF!J3%E7M%axMi4GC$ds#5PAP0kGeyCJ^MgD)lX)qvJ)dyD=+GRvmV=IEp5^cW; z!;n76CXElBK_{S#04)PR^I-aq1jl_-IBk+1)%PE#yT6AnJiX_70UkDSxGc{VipwFdmE zLO_F{tC7`f%6Ak#H$v2hSFOGrX@u4V0UxU#iBO3wzwE6W z=_#noCG@u}Q{G21W>)fnG%;M6t<28p`=WhQgN>?UtaH$-!aYBw}C=KT&v?3 zK{)Z|mXqJN!WrA(QJ2c0d~Qdg0L1@8D625u&D(ZN$Go+jSam7}baGA5jS#s|`;m54 zt_tkyQ%WsePsLnF@7~^7$hvjX=5Sg7U_g_3_GHGj3t&);f)iHp9V@-KcHB#tjERi`%Li9!g)lq2NzGJeFzI?XWAYpQD87s56%`dhG9#10Q9Y@D zqaOmmGWhkBw^MgGIZ923ORx^FCa+6etapycdM?7qi*%aF)ADu0^I($FljEvBdsl`= zZ09w;wg`7o6ly3)ph)(8%)VKEt>g7+6{NXKWTB3>2tqb&W0)y3=xeurUbsrdWU;-@zz%DBTBHDJK{F`<7sAs$%za?+Ygd$Ps{)}~oIi+vLl2i_zS$44V-njvNrq_UlxkDEuDKYt9 zcf!%4<5{Susl3h1XMSj9YmH90yiJcrgoORZ1ys;;sreHR+4DHiSZyR;>*|!xkxw^G z$!?X4f!fJG)bov;hW^h-h?2z)O)zwJ!Wue=2C4gB!4_m1j+hw26n$~w!1yCASGmu^ zXt#gCeWAG3)fM0IqrKiaz8tc4KL+lbQa9F_AaLGiH=Hy9Al@4KWtaG0E#PogkxSfyI zU&0?Q?TnB8f6UOR6y!c5cYnFmoJ#mqE_I z?yQP8Sw*u_u#2YmGRRU4{`y_lp}rPF!I5j~JaVxmDhNzbvU|1Lxuqp{BV)=Z<(52Q zftSFCOx>+&?4eQn4Q-9GC8vggP5{{Ahbnweshj>r{ zr>iYDH_Lx&neyur6w0EhDy^6vDxFxFM=QZ(q9TKhe~DGM?n>ZDvPAo|SeXEIfoyt9 z-t6e?ZymoHRs6+rf$@D_Lkd>4E3ZF!5MP~UWb9v)G#n|iP`Ndp)wWk0TXuHPl%J^M zDV|9NYo1+n6EXVkK_b(dyB^zLbQCJB@r%GqQm8jKrP9aCn#~i5GNy#*?z!XCcPn2| zf`ST4AM#jdXWNmvnath;;Ae+yA%E?z7`N z2r~@tyyu>K&M(e{DauQtAmSlHAP^L3DKTXT1X>&1{Se^5BVtdp`49-Ag1M-uqN16t zldYqftsRN9s3?h@gRP0Vl`#b3wwS46s;Y8;&40amA@VWQ@7qUPWh?{|WswL!%s5IK z(%0xRp`^JBSV~=Q#KmFpf8~V2L`VBYVkyxfha=9zZj^RVMNaMp2~34xO8nE{JEN^Y z-=hJMO0DK=qTm+y*Fm7Shu6?xAfg_Ven*SRVF+!QCdAO~o{G!j&xW>sJ_3Q{#9@J} zJ%4l?L#-Gae*;>jqV;sV2vG8Wg!6N8Aty^?+eV;M=Eqpr_Rl52;^UjZP#yV1QWqk~!}oekRiK_7I4^7zKmsP>tXK0?4);f0`;`{EIFex=uKPu2;)lNDl@a zfg%*W-6H5Bh(>+{4hA2}0z{~TN2>^F3>be45wdkEnFS}T|dzc{IYi)Sw&EE-6@y2nv$HP)sGVk8$i$%*x@aBx+KG|M(rC zxkGd%n&WtXL0AGFf?Fk-zxh`y@&87y6K(pzi5Do5hcsd2#GDp`os&M{P>aVO$&tG^ zQEG;^7$YD$z|^^q1JBxP#l+CxBl44r?sdYK;h$t>$ff;wRqAChEn$~m#(%oPV)%=9 zzUF{+6(KPs5|+}G)s&x?`awcK!S-hHHRo%XK&5UfvVG|l%gY_ z#fW*!i0&CG+RI6S5hlt))f5XY{qwu(6vmXql#Md^0bOxAn-m^-!r-EjWi>qaH#!p9 zUqRcM+dbQ?+xXk0|8x*DKMUD^zfswwRvxmD!QDaMVcUT-PGJ#N%TH5Y`H`#ohCN1G zq&&A?xl$?Q$6Ge%H15%_*wP;h%JUMZ@yyxxsEB3p<%9f3Qb%EZZhl(LtKmTIe}NmEbbg%vl1m?)D- znTSurs9Ic7Sh8Azq;{@0tQu3Sui{-Hp~kARRs8yQQmI-=rs9zbzKUrv?~jlY(;v2~ zg5Q0#9>d_YdSrVPM87NL{QR`l+E0S?1-HhHj?@yRG}zgny_fRm=z^CEO-srnVM_#m zNpUW>D60&sMve0MHxohltrYv43@7>5d(=hA=RV=9n5Q2$Kj0U#$u=spp1B`0Z? zN|h>=N*=XwR2&y&7Pg7EXx;mx3J=Io=~79W#*Dqn+*4UlSt&v+!j|LbxvXF)u`IyP zZ4qL8gFPLLS56>tnaKc=B&GZ)cPMv~rYzS~ z_@R(jmRELQbYwJdbT*Yeou7G*WiNd%eJ*{i!9d$ho38#xeWS5-^|p4Q)=7P#S+k}+RcG~s^~DXiRXg)=OBMCj_1=c2pWm4_ z^i}knB(x=XH+x4t^24KqETEPWY7_c6);eJFsPn9*jb)q&diPx<9Wa_|j-!vyvu@SD z9sba3o~e>PEou7Bw8`=7d1yq~$ADpmWC4bB{Qi|+ZQC+Vm-c!a9#fZ@={4!y$3K=T zPdHA@PePWnN7%AIWNEQFPW1c|U02$f6hz8SWU^c<^HC60@Heg7BWL`=7^hJ_SJhD9 zT5@f8`cB|Vz#)4}V2h7)m1R}y(+Fp0!>@*6g&y0iPeE&ycSJey0!jU;m!dSvF0p$TZUFD=^zy8FQlV0zojKz(aqXsGZ z?9WcX8}1rL^!OlC1%(7@1Peyng=*qWGAFaUPA-c&u8G}=C5f%3n=&hKSJKO{(+HF> zSnw@!HnTMg_A{7hjm&6fYD!yuB;aPCso=1&YF~ReJ`dT<+(g>)e3!!bOV7?dcdYv& zs0h250fUYwNk}$Sp6lCRVRV`w*pcu5y>)#bjp*J@*lkM2ILR>?IxnhALnQxCibl>O z{!d&hyE{c6YXRL(Qy^7wY^yAa>`FRM7IvBoi8Tv9PaE^s__$bmkrGn5gnH9M(_Isn z;WFc(>Zd-Nhz3TYMEF6=n%J^eTJ(tZB8B^^+SGG2@YSZq8YUg1VME+WrCGG2$0IdE zOR=08r`gZP7~L2f@%074A2sL+HFw*}EV!%r?A@0Tx3FH(2CKuB@im6m(^$_alpbp& zSNOD1ddOM&>vs(Wbk#vw9wDhA?gV)sEzce6DQGfkt<@Rc1!v+5V1OoT3BG6R72BVgC7ssmM}fii zB{e8Dxfzog<9q4*nrp#|u#$tDqeo8)$4?%M~~uh*`LPp7A$A()LT&YgV zTNPSAT?icuFNm&$%n0f{Ezh4W`&x9m=A2J1OJ2hTeI0*_yNp2-eHD`$GaQT(e3Zo{ zz|FlW=6ZY) zg!}waQVjC^@-L^YC;>e3+D=N#5rEN|mpc^ytmYYb5Z*~zP8@z27UvBL?}XTy1q4C@ zkroqHbzA(S=jw*p2jkt+Fn8*3z>gj;MDi_A5i?f*Ro)K-XfkoSQ0g4&AE8nj2Q(x! za>7+mP#@wjq@V*S`Gqm0$d8pP8&=kc2Q!n0>xA+Ioz||8U0pp}Y)wr~P1ah?AxPMC znpFl}0k8hAZ=NkEC@EP`xV&;&GU{})pIyf&TU`s^aNqxS@VST$tQmi%ExPr=@8qo_ zJ^1l+bDAbY_De`jF&929@xp7WY1r|{{1A!^@252`>*<*ER+LRARylUI|M?|iHe&AA zROdP7gIzVx2+yR7a@5t!5+WkdhJ6YT9S+(9UsF4ndlo~vR_8M~&K5Lps7XovrDSFK zpmG$xta^Uob4~ZO#$3He*FxE}Dsx))&kHF^}9cia8hVIU>o3@;OCIJ9%aplkkxMXR_kD=WsC2 zshl~D!Aq$5`7b`xPT;R&^}ub;hBNw@M8|c%TL>H0X$PL%jMwaZ2Fmu6hCN4>yNSVD zzI$J`jHp3#{QiEc6Z0WE4oXv)?z_q@ulcO|=PzD7o1U>IA0$uAR03<5xmUpJ>;yV% zp6C4Ud|!uhZ{jzZ1W33Tq$xLYn1HtsBsvdkc40R=`)!Z2t4)y3erWeS2jk<~&iiz> zg@!koc@oZ9*4+48c(Vjii4y5|tN5&p?0q$+XAlP1;X#M$3_7a+{P(Oi=KEfX1M&Y$ z3OY?bRlE6id<=|uYU~Idp1V)Qs;e!or}}~%h|k0A#qKvGptUc;*#F~MfeO|d~t@rQW^FNK5 zUVM@;Ffd>dS3;4`4hjlFoi??z`zsz#A&Mt7m}}0nwc6&%pNS9${sQWcC0^2iBe=2uv-?o3=LHznJ0z#ltWk~P%TDP9lBTXb6eH624{!a<%maGJ2F1K)tSB#j!e zXmMo9hk)lAkBsPv*~})kAMdX}`aE80NJn7PcW#|^ZrFiCD4v2kygNTeK&DDM7F3yM z+}wg0i<+&it<=TSTxfqkQRK)iVGcOYVQ>DcTi zzMiE=DdS)BkCcT*??fTdF#GATv3Af9L?omTY;0_32pKuKt&x#YEwg3T;_ip6NwY`} zPPNpPJbxH?p7IU+%R3L~-mIkRIo%DZPLQdQMErOVf_A4ePR?3K zq8KJPYAo2uM48A~JiB~rDyxwXT`M%NKnNld3e7{vB6>Cq9`7!3SWS?*2%>eoX2+?? z$Ugf@NCYzqqc1L+Qh>B#$)DV}WJ&eH{|9oJX{vU`X`gzu`8;EJgN~L~g^GeA0~-NW z2L=WP>EFM9x`^~TXJ2%RHGh77HCv$<;q!Rcge70Djub#rWxv($@l3DVShaeoYli{( z6&o8nhf2gp%}RWb4BG$KQW>2F`vKp3?Dzvi?uLGpmh;1L29tN34gdkq$r%jG~ z^`Gjk7UH=bcUv2r4wP4yn;gF+)9cjtdJ%eVRPC8@>v;|>i#ea~%1O$p&N4!Z3JO5g z*fjDcII&#lAgS#B2dy*L^qvCab+Fe%v5tJ4e37WV{m(vQySk>~57@8c*lJ)LcD%g4 zsRutMKfxvs_ib788c>hJ5C@(!pU)EF;9TEbupocYFi7o4Pgh*V(&iYa*2tgy#mdS$ z<1`wf*UJ>iDU3c-$DmQwGQQst8Q4f2apcth#n1S;W{5V)^xy2A0tE8N!+*#k*x2(S zd3c5&{(|37`KUgUSWw`8{^u7m*KP|1vs68unqPU;h&-8N<(_i~PN?VbF#|2cl1MTI z$_=LDL}fY+s33uH_}rKRzJC4bd2Pdl{B`b=FCkgnuRr=VuVX;BZ*Y!*FYRv=Mm`z5D)>CkW&b@B& zUjTPjVib~iU&?|vgd*=VwG&T624`B~Q5a|dOdc0z5$Ogiwy)&VP`$mq$CWU#OfDk> z+1``AQ<9MBKw8#j)w+4UYNIJ*V~tzgs3nim%hcokWc^JOn-ZO zTLgtb?7kfbheTh~x#`fP+2rsZq^RZXnqICk8{QGZ51j^^nWm)jD#uByp&Sz@QbJr@ zb8aeXY6NhK9CJK2IZ#N?ROIOxikhiNG1XpRa^aUlOwfD{jD`GR6jLfEtEXB#lWMQxbsILP^a5Qv1 z+E$hSDrEA^n0H{g-m4s3dcPQ}4&V3pv zluH+i|NdSc?Dtaj^4QGG<8Kk58NGCJ&4GNaUKV7Sgu%ccKd9wQOm@?)X1$r>cFZ~k z#afQL=XvEpa3rJfob#%y9X__W9NXlcU?MQwQiqq2SB;Qaj;66Yi^X*r*p-qQFyS1& z&KeiEFB_wRTds)_7uMZ`3RGQSv84cZQQ| zqOk#l1u1nrRq(NrL9hAuCfx#$HtK3ikEM8Ght_wfiN&{KSGp`ZP$q4*FWcLy$8bqk zOVaF7kGj?6Rki>&T8@q5#+~Gn5Lu$oCTZV~HY%u``ibnVq#31yDzNDv28$?b3@E=?^tg(6OJ{Lz%t1dOrblo-Z50uXO%eW}DpHyO* zxfr_4T8&9NQA|0((IiSVdS0X8_L;EkA93rz3JV>Q21(KQ{}Mf%xOAYb z9g&Z_EvRumQkN=FmQ7iu|GIElX0}6ocTi7?KIYG+Bn9D7$m4fM?GO1w_a5KHi<#cVx!Kbdc;gh zfF=@~Ms=<^G<$>pZT{jbnU$Da z7{9;qimcg_JbGXkYUNm=^rTD2tx7vU8DC7OhAn(E?HZkGVWEY^OiT)m$z)Blc`{K! zKXY8dWsTwaPAyMpNO~13LU-;bMN@}G5Lha*tV>>xt$n^X4lk}WUu*srvVPpK=F$?A zl=_wu+I_^jx6%W<`4pL2<`xE1oHS=iaUzBfDNzb>$jHg_x1p96Zgovf*M=RFjCQlgJwD@s!qtzvXw zuzG3V<Aj=ksS5feS4zJc3BfQ>#~n!$(3BK{N$i0jCz!d%u!YDMuE3y;Z>i+xUECTjidpcYUU2HsCHPZKyySdG{G5&iv+@B$ zgTH?LHO1+N_oMPt=4j!Ov}>5#Sldy9bgmXKYF~}F{L{G8z116qhFEJO+n^WeGH3{{ zR!UX}@7kOI7)(g@ks1@Du4AQoSSlViq^EdJcVEh?X3uz?eEtCejy_;BE_(u@!x&iC;ci!^J=h0CuMGn?VA24w)Sp$bu|Wv z+0ktISFqjHOPvSJeGcrn2!1$}+JBM8xan4{CE$bW(tYDrnjjf#f0*O-vRMS!Yau5H|)kinn*i7{N&$&DemerjRx7OG*>Rtzi%g1%k z>l6Nyeb7LDjDVZ^ZUL7Cl6;m#e%Q%me#l45kV10=SZIJDo`@M>grO-8+k2sj@FA!n z(0Vn$Lxzb1;@#GveHkLbl z1uH&vMC-SC%xIww{R!6|KRJ=VW8+L-N`JE&7wh8fFZ{Pq{d-)Yuu1 z1OcDl8(cM!+?yg}W8;;DZ+$?eQa59V{Q2DbOl*cYIrKlOm6>j=73TjDvDi=$en%2i zg#<@Z;5S~srI^PQ&`M)3e&l6+ML?8>Trb+)Rf{DNN z|D3;03y-6aiKpRw5ui$;cAKrUc~nJTyi$dC|Qmslxn zG=fPQ*`hv8K?|GToeAVcy!4g?1|7&A!3 z9=X#7(tqDdh3hv7>7RLeYOk;Q(X7y}sh}{P-Kfi;0-}oo@$&Xoz(F(~X z0I2_I^WtE72f0TT12)&SUqx|!rM;2K(n9I%auR}$xor3@MD!odu2_b^3(hsmY_u|izS%W+G_;tPtK%Nty871&6dzhz+M~@-AZaj}?gX`Y zv&oqzCM7LqT8L046aeVG!H|4AZN|3CjaNXMFgRwbhTU+N@@K@5;NChtwdHls&*xZ1 zWl5!T1fX&8&mSv^$~jh#wk*K*P|pvFvMr2Rv?%>hQO5}PbEuRgSnt! z2OoqVA6*{ec2(Z6O4AHZGhL*R{Zak?b)){CO%6X*gkcIvuwj4_>!5L4lwr#H;+NKy z?QcfL#_UMQ$hs2ffn!NABnWy22J6*jWo0JFJyIF=yE|pR2c1t)SVRBPBdZ@M&yRQ8 z)hcCueI)Hvi{$hTkLUC{+%3s_nDAo?Ol>lrcWm*qv)Vnr+PXc^qJ)maLk+*~93C!J zELLSf?qQ-#2%9{*j8rc*R;9tpSENokJhb>IP+3-1>xG7ZV3)Gi*47pQ)TGR6(V}Us zA+$u9z8|VI62+?896=&ofq{YBJg@io9l6ZYOd=)7^XHD}Tk)a_#|mdGaLd()14BYu z2<2V5*zr)_Vq>eXhfWU+6iI=CzERumtD}E@nv;{$9c} z9dgNNwiH=P6A*q`FE7582HQ{G=H?$*&8H~(r3+$5CF!Ul?(J(40{q0ty3hn4*6p}a zk50jUb-hm0BO@b|&){*E!6bN?3!De&Zgq9_g=Rd5QDvF2yZv3C2B_&6W<3L`-Spw{ zQ81g+R)5`boFD$v8c%}Fm)}2>aJU^P7|F@MjLeqn43vH9XjjZtl!gCW!>Sx7#YRR! zVboKsQUncd=(xDj?dM~><$3w};)aHX+ijlLe~&6Vf};s}uLkn+@-!|z9*H%hWioM7LB zsrT6@D=p7uGZwsZnLO;KgYoalK=*|aQdLt+WYnw@YVf!`bX}^q<|U!0KgJC`qAk6!5l~?YXDPHpIJ{Yt!bgPB#r>u!`}PCVU(5A;|?rxSa@Aq0{;lcdYcNXeX>oBn}=rcCj5JZSi zT~YFE68$W6Zm-9gd9Y#gtV6oSkG~B(vtB4mYxUVKO&=h@lVIx@xuXQ4R8>2-t5}kI zCJV3oqDyF@5Lw)V)7^!6T*vdLYXC=-^z=}IMEt=XadUGsxIS6QgMxv3P}S2T)WbKA z=F(UJoqNKJEnvK1O+1W3y0^D?z3qCnCzez+;O_FMVMxMk2498-JAyMq&{sf+4x5~n z^{u`EVqab;-@sGa=jO&K%II zhdh_(5X-p=?_7|{P%4G8hRVvy^>YGTA!p_*RHgN)Xmw$y!K2*F>d#+6je%$fkkI@A z@);jI8WG>e(is;X=fmIGG5lAWTz;Ory?X}-AGGQ$)C@#KL?pnL<3%Cjb5oa=9>fSX zlqtKj(&945OAZL&{UalvE^y}-9({e4e(spYX{qG?p=QL1z7%%Gf;{WwQ;nZ{1M2A6 zEm{$ib^rZxwyQP%Efq{y-uj{s)!A*10k@&~XK0{x0VpnvF4k7Z*QCoZH8nNS;p=PH zq}zJ48DV3uj2YDR6<%jnsdl#p3k8);I9|>WDLfBo7Ck|=*4%oDA9w9|wyK}T)wnE^ z`5bhNnug6$sl=7`0c~Q?Z{1gQ;+{x$K51)h^%8M%a{Bku3L!!a$vW7rdv;un?&p+1 z>=d}$C-+uUo5AED{+S^+cpw`A+2?mXS!NhcqSu)Mdor`QxR@6qK*|V*vg?5xJahH( z42$Vl#xFHXiF;&vljhvs? z6cZEs&Aongyu@X<4xyo;nP_q}%_($j(Ch8%^TvGpmNkV!Iv-Gzf{)1)#VS+}e|yl( zR$I9N?qp$MLC43B092}TZH@Ts?5w|}q$C00u7Q))w)?nzyWrs9G2fj;jhk1mUR{8T zl854YwSIZM=Ii?pBq}t6ZlhvqR+dk{|1XDuL6*h#Z?cpL>gDQ3wc6$W6ob65!uzt6 zDz)TqKX3MiDFGNgZ8DM)r$<|DlUE4C2kA6pv%o?WR|A`)XCRvJeh(DFLb(hs`)hD2 zOvvy0z!y;UYa^D=xK3d??d%pK<-0`y_!7_f4dFETt7eEeSoe>uu@n6{eS~=K00DT#v+Y<4DGcyO?{{zo=-h zswmrMk<5V&FG}1XRXpj|RYC%;+3BGB{NjRuGI?0gQM8wof&vz-N~6OLBFHkpTkZBI zNLAI<1BQ132DXGNT^C*PnVFeI0d83}25nng#KL3!Xe0z=?eE!rQgV zTZcYrB}^jUhcge<@w2Ug<7R~l1Nv~QzBqm;iTLlsuVzPWviN@*A0IA-a%zkc4ZQZ=%i96;!N?)3uJSYah@doDP2vViexoxH%m!VquEsYEZfb8EQU5>0Otrd z824mf7s7*Ys8)0^(Y!EGkZ;W3wSuKxkuzz=0|yJsg{d|BqIJD_^9D32Lj1ca1XR>u z{mKC##G(KrlIWDtJ9nC!GonJTCCU5l;y@m(>ebUu@+TSa!r+h2nZeop>Eb_QpgeXBf~ z(L{niUh-O63&;=;f$WZYg=~S9g!uUOd~*+H(YGbm%QT5H2tgvQh4Jf2iHXh-NSN3r z%(}uyM2*s;P{U05B2doaAVSC7y6_oK668Luo}9xy&CeOh$?y832tNwU=EDnCd>QB> zE}Op+4Xu=Yhr5aNb-hqzQzId1U2NVTsnt;q4`J#ca6Mb9(#w5OI9L6WU2zp1gUL7r$f87o8`Fu z@Oz;DXX-@Hg1xVYsBwf1cVws6>Nd%63Nlu&zi7~?`|0tXo@^!(P2gr7OCX!r?ccUE zCN{Q6v8qU}Vh(t99EG$#4IN#pBPcFK3(Gy5wobLRpg6RFjjh}gomgJ8J>t%SRHiMw zZHsOD<3K&(F*SY9+LXJ0+3;`O@?2686YeV$VJSh%A|X;4&;xGhud>%Mn*wslBZi>gSKkbnDlP;MX-ZnqK}fJNfu|d z20&ZKSSGJ0Ae=;0@)`38LR%;Nw24DJ(4{3Mh%+-Yu~HNgoLi9*9TGSJhB(7D#m+S& z;~}}!LwqHZalZn@$g~=*mpI~%NnQaT0u&?QpO4(H!>kV2${qB^!4<|)KxJkX8`Nz!1@7elk;qcvVCtRi>x$_Z46L1F<-(s8Y1Ki<~ z{x}l-jW=Mz>kqzdD^z&iUvME`X3Mllq%mkUDqyAKZ$K|y!A_lp-W{W2&o-`x2~ z3?~dg;SHtp3;^bAPE{59=bty#>ZR7TA^Rl<=zhC^#@K2-5^-70SJ6vG6TFs}k?Brl zH3bzv#`$P=g_edU4R&41+`M@BNCI?4;J!;qOGEj+g%rxBbG%5gnjJoE7@fk5jFpc- zt~$Yd_ijKzMy7WKn_J_S87?0`e_J$J|7pJD93)HWa1g`CCRKxXed;0aM zv;J6Gz6tq#Dd)}Z-*VdGf89UTXDc!gc4U`NJlMyB^%+YI-8iECabhW98Q8@`BS`+b~U5P{iGIF z(=l!QEn*NVZ}*ZNPfMo&L<>m39{`}g=5swEP_NJ(oVKVN1;vVPuI}9@V2<|g5@5@1 zm~h{=^cMPJ8LmX`ZBJjhX&%??(vu=|8|-Cic(BzUFW~~61euIM(TB=crr$#e#YQtq5^`X`(PE}WTgc%3fY^DSYkm1}(Gesq( zE-1TRIn*pMvJHrkxcDnY*59?xPEKrN*@7|E)z#Th$Uv(T-UG7Gna|Az{LJrS6<-b< zWSb8tX@$-b`OE1Th5hZo@TeVO1`R=Z&!{6>2aC8gi~>#J%|UAMpwfCem2>S}9Ad z7HePUOGI@KCQzNW98`JVU#(G5QhMmOxS#-5Nd4i1zj~>-zJ6AZy8mLe?k})XzK-09 zPp)&M{BqRip`S?+ocVAF0o&xxlKy+HqOK56)2O4Ndmw_KR^ebJpKGw6JgV}d2 zH;5k#1;zJ7MQSk@7Y;?%YTI>SCX6Kx?~Ht8Y;y`XOwm~Pa`DmwmJTc=R4fk}0$M4n zs;cU5d&Iua%;&#V6kf3+e+8x?0#VFB=h+X5(JX$?3U?2W6HPFfFb|ZMQbHc5P(_-= zK8rf-@<}rs)R3O@t1E0G0k50!+S*!wmQ<^Om)CGRtWsb|XUP;;82S{>l9hsGL+&A= zrA7MulWRb&h9RQxYm>6^QS1DPqlS?d($}64G~P_nVLf?EB{s`hx-z|%`mFpqx3kZX zPIzLkbr)j#8c(&xS$JXFZ!@oXA?Uk*+3Ci==1~JkSEWzod{oHKnSOH^Sku^ugDKuM zFaW>RAJwzo^_5;O7GE+51AYfxb*5!?iwgZ44{`vmu7${~T1fg_DRKn=S$UWa+ z5T*{C_#i*Z%6{M9-o63_N1Fm;QY1H)ftnf&!AKB6E)Hit!skqwM2T3+rx~V{MB#HX z-~bSGO~mg}>w8=`SJ8Sg_0h=8?1!tfbKOgw-l0`5`yl|}7vQX(t{`?u5LMtpFKq$P z-$C{My_}4cRL;Nia}WljH(FpzhlYg-gFY@@IY-4#B7l!XXDatTka^Ep5_(uS)ggIW z8#4-zy(BuKZ|m&uw1VIQJ?Ee8Ql4uY{((8L5IT~zfRK$F+V9c`jPfO>iyVQl$Bt(P zP3yWiH0h3j=d2}>F7M5N_p{~+uzrqmF`dY4T>cJ?fE?vCJ`f>{jaU})!M+>c+upVU zb9XU-ZSXkP0>0??qSK|B_*6WDZsjeV2jGJ9>=>DJ_1J8z4_qBrMr!Kq$QK|(tbks; z@rIaq+s)^foQ#lQWZZv-4K^$KnLt7*0?i8q zKd_;J6KHXEU>fJoO3R$8wstdA=RnnT@L@@J<=hdo$q3E_TNI#&J(;f(%X8+AE|DR5 z^@7PIE-vOTf(ztCLQKpJBBZR0;h%O}w_Loz`qD3p;i1aYY z{*)=eV*y4kTF1k`;h&(28MkeL>yJ*P)$rl-xY++3Ktgau4pc8<*%T(j3oy^XA1Fc! zE(xg67asheOujID(CXDnXAWcL|J;msYU6M@)GecHq3UIVO16-hUy_?q|G8(SsXRk1 zd}MlRKAk1ce@B~NAAl7gQ)^RN*X|;PG!J2zq0%ZUjOtw8QG^~0=7~sGi%~hJ(thGOW zDUWcz_aPe`7}#6f9ZiSvz1?{S=s}rQ4IB{>(Hs!#mkX!`KwOeQ!nejICDo&J62HL0 zMerV9o12@j!8CgOng3Z1%&YX+tgLqY&OSKIc5KsOv)Z+({mwy$eyu*HNS}Y(gSJsb z{C7te7Z;MCRD6a4BKDC3u(-xg7VC~o$`f`%<-~zGzzA~OVx=aAll;qP~*X40ZLaSECN|peqx$bRov^dVa@0$Q zA0HpF@S=iCXDpf|@_$A@Qe%Y4{I+0Ech{_PL(jd8-6F6^N;ac2WBk26+VEjK5(%kYI%YV%J zDX|Uc_MQc);31?KVFhJG>JophlkX_16#rf z6Z_1D$NEu5#zTwx0C>l?`mPYh#W$kJhw>PUJRBS@z7`fGwg8jz zxSq7;H8#%2O|WpV`K@B;<3kwX++S0AvzB(aMnF|=48Bucpo)iMBPcxp##Q0Uq;s3CO(^$X?hzt?9m!`Y($tMCWm($ z{9z`$I|vNRTt8q8R+PyV(VyAa4bml8d!%YbDUZ9lzdfQ!EIEFJ6{EwB`1OiMc~ zRWG#%!^z(g6CWov<4))|=yjeQmRnY`vQVF|z6!;%$K=laX=}VGT;yfkX=%86xOvnW zzFyYWulPNF%gY6@%qLD4F(Lgur*@#)C}Cd=fgR87_-23P3zFFY=empD%Vz6V+F zmz_-vVEWYbG$|&JepEixf!VL0dJRcyJfEs%Q@^4?rOf}itrR{o8BKen!w5414jVCK zekyPdZ?0UYfgMa`HUnE@4K}t*LJ(NyPtsiY&NzQgPvJYH7+Sq4M3bK{9;Pel2_gEb z0z=QV)%@%b2;P8B^gw`)9&6Et8zr%k!R;suP8AO( z-2EaWkq2LXmdIDyC*F7L%I9We%xm}|Hbqd`Vpk=AgovmdMaZkZk}DcgjND@Y1~}Y+ zyW{$FwPgDSNVW^0cPPoGvb+MdnspgV3k<4s2EKkP6DhG3DG_-cmam>6{EK`%py#dD ztTMS2hHf0PVGMta2DUFeg&W^jq%?Q!`CQNewnomO!J^27(4;dzS zd~X`m>Db|yQBScH*#v6dN(&Pw0{2lSp=Zxn}l!Q zFfs7(?xa=p%YafdtdPZb;0T7l!4480glMlRq=5bI(+1FqJEWi80i6oiS#6Qyd&JG- zRX+{Rm~vtKG}Xvc1ol0=DG%`)xe|5|1uCAt=oVN*oG8yL|Mc;#!aA@%nk4SD}^LM&5Oo~Rd*D9 z7a_|z!GJ~0DIC{u>&ed&+FAL?bTE?xi(%&`5{pS}+%Oe;b|j)|v@+hkfz~M-A8kpW8 zdRa6)bo8n`=AP?c`k(X`=VWs_W5kDkK@^F2aN*ci@t)faNuhWfxb`q z%5OxF6{n(7p6M?kuI-Q?4)wN&*R>6$Oii8OtOLbN96ZJCWiSeURtk$TV*AY|(x2s~ zw+aHc6j`1p+#m*SA)7>SwdY6&yxyYO%wPJ2aurGV`5&9*8sinGai1=?24e1kc&n;Axtk>HNA2%%P=T9!@TSPYs|F{H77`C^u@$n+y{jC4n z8P;sHBLx)KZoLxFG=K z%*;P^EG#Vi<%@KX4Bq-7dVU|P{Uu6Yi}Cg??(ay&8l*(&=$rN2{i~L5Wz?lpj5tjf zX5!IL#g*-Mh~xasQ1?FXwl2onaJbshVW=cG#}lGk#Bq?>zpjBH3S>AKKor0M#Mp|J zR_J`!*L%0@boID>N=(-vpDMNMET+DFPyu68&<_{W3M1iI zw4v_jySc5c1VB;lp-sphsB1)T<@Nn(1tuGAfC7`NN~6Jzkd-W7R72;Ip1kLA(4Ub( zz%-Vu{IwyF>LUJclAY8hH!76x*RZa$S8bhPxM8=JuH9m+IM=^P#Ar%LFg{vfez0z4 z9NW*e4cJCBoU*Jk9ya;ItqPU-fU57whv+ZQ6(vDF-Rh2CYgGwDzP>T9NB{YrV!gj^ z=~v}%a)x^Eh{1$UfkGsmU{dC%(I5tOqKxZYP)&05_tH-~v|g8ebE_?}KFqF1?^=9P zuTH*IDxC7+@Y;Ei!pVkHaO%?dVs}E<2iz!r?g27pFHPc$u>8_Dn5`GtD%xZ|+S@Y& zM?5P75a|>!{ep28HJ|m(WL&!V3*wfQf4L-{9V(g{n%~<5lSdbn)(7Y}p}PbD>5@=N0i{7o5J_o}mhSG7P7xIaBt@jVq`N^x zN~EPhK&0zG=X<|*uf5m$T|5gOVrK5SuQ<=6t}DTtcVkhoZ}i?y2u1|szD&3L!ZZnB z&XoTDFa^d|^Ca&Z7AgMuHRBHb3^hKCz``#HC07~)oZ(AJ39Cw);35UxXsp*&G2{Cy zf015PFToRU!v1H{Z=PCr(LVQ{))EQZ{f(q~zeBSf42`MT^iqOK1UiQJ4SISNzkj2T z-;4P^0M4+D#4Gc~{Mx<$fIs9$#fAlrYs^XwT3U|P)M!DnK<;=gLBA;udSc+Yx=!{- zqz5tTXl@u=@$wUd7%%XUw(55Vw_s7+3vfGkk^6aO^MR=&o#F4{g3;`LTV&akg3%s( zFxk(3sf!v5DsrwXsyuZSB!u%4i?B6CEg(=gP`NXed6>FkuH){rJhSC9cZPbY3y&ol zLVB?%SjHRqojJu5xZQfK@84RWCywtqlXDD%R;=L|ykPkrW6pna;+vu_gZ<;90(A)Jsl zno&9&8^B))0S=ChaZrbyR(toAke_Pf6#MWP;>L*6CT-q+^}0M0hex6Xfs;INyRkFa zuuyB5y8#x5CeX2AfOLe`I7oR2Q`*pr%FsaI$x3egYNBa?Sed@Mp`k);lwF=yzQ%9x zkG1<8{^^@ZJ)_;jPpWLkzF-iDTy*R&J+_uASry#H;mcHc8;NB4t?RJXUxR@eOLuH&EKnaTCk&OPef zaV&eQO2=Py`#K;)Q32u8Bo8YqCeYM9gOf&G33zgh!m9Y|H#6Pu5Q~x+tG?uD!D}+) z^7ri7*F|hx| zw_-UqV|L+fKCXpjWNXH;g-c#ZX;vBA&tU-X<|w@Dt*?eqQn=dblw$*aCqCvz*1b~V z83}+sn_gXveZ4$7-U1m=)Zq7{6DyYZeWyDSvPv}S&1NKyGqBwb8RON(3-i0z6p3lq1$pInSWIIte~sGw}}2p6nqJe)sY`)iC4Oea^n9Ly}w zr6G(E_FtwP^~J=vCTIGz!;LP{z{iAk7Zz`tVHF_ddOTPZOyP*6B6R6iAE zq=T*odW_E_K3Jenz;`9>8hn^%w)Hb1OSBS2D#PLxx=hyQpWBF6GcsHjrq+|Q5Ktn(Yf+nEqRPSg4m&u|K0yfRgNRme25G+9M5D{36L1S-^ zlA6`mJ!P5hZQ*2W%&@Vw6$4vjtNHy$h2tTgt@ln@V{-ifY!mW%R_8nr%0dvqKB=x} zqP|>gJ+$N~Cud<{anTx#rg8;kL_kM4fi%dX>Qy8zt6BgTHTE}FQ%gLC_H1}%bye=i zpUusn%0ggPU=R;76~@@#{+}MmZR1Ar$QrYl7%hmDIERLZJ;pgbjhPsW`&u9gC6gIoX5~WRaJHGJy$Zwb*kaLuX&t6*R?%e*~0hX z=|HH#aGL^8(~ZxQTh2(4(8&n{8yiJqkYMMLFN$NrRK3J~ zF*xW&gom?26*?=y%S*hRek;7{*tCuMD{AtS&XetPS42>4kGpg42G?RD%Khd=xc~ti z1QPTNrRZK>$f8PghovEw`XS+tSvDj2->hOzRQvl24u*_>2l!ver8M{R_J(VchH!H#C)tXNM{K==@5^TPFYHiK!izv8_1J`mbN#0PY5u z7HCL#@zDq)(85hPt7$=WQB=ff(CqhN8WaU=_#J~L17#6Z#nMtzuVMXMrKh2Z1#|EU z_?;iry8faIH%TAt@0SAB%n-r+XYD=MDqcf3+X64h(K+D{ zO8R5)l$?{D<|@F+cz0hwpb5sFU~MgBrH4CuALHK8KWg3=5AyUMckv=(!DMn5IE=#Q zSs2EDp$%yMAnJV|jEljr!<)bsMJetl*nD}U@71TWoMcpLvK@itBv9B*X+yseLrYKe za`nKAH}{tOl)|jwQC|C~29Y^P<5U8!3{|Wt=?r(cyJMu6TIs8s9;FqB7*w{BEH~OlMu?Jmj7nV90g!~vJN@*Dp{U{NWOTH%MA9;tf{4auR=hWMON3=Mx-utiyDFJn=X{N*puFa+xF{* z9*|1!pFhTH?F5N=LSbRyU7!%z>*m`U-NE&$j4UivILVhmm5XHKq71lq;XjJ3}~2dR@qJxf@~Lf=11P%LdqH91PE*b z0$J!J9p)OLK7Dg1OzPgPR-WtCNav}?ik##U$L)ALC(r@^gC~BPH}=6|Bz=dTj0_!; zB=D*Dzcd0|EV6L*ngcay+hKpV?YlWyq;CSzquqVRbzvq1OGN8Rhs&O#eu3fp`?(ds zqG7&f8Ey1-T?T%_wTDhJidVwxsBm+RU;F8C$=KWwoz&oOHp zW;Z3E>zV~9R@zK9RGvi-1RS@F!0BIA#ShC^NoU_bLdY0Lyys$jD=uPkJ?WQ2=rI9nX4xef|3N_?KID>ZciT_dvta07a@fY#yAKp?-dT z(W@gFBY-D&Pfpgh5~K(h`bLC?rqu!Ct)*hb-s4Zw=BGKEbXxG0t&+8cnsl^d=HzG9 zhF-I*%{fyH7tq8J~eR+CUez806{p66zI*S;lFDf#rrKx(2T)%hT}x%Zlc81azCDIS-AfXk@D97o9eFUxe937Rf^?R|ZD z+y@k6A5iGMzze7C3*oLMA$m@GoamGl6)WFz#B@oyxVrWM)B|xRy#yM-2}X_;0toxi zarUb$w9@k69QW0k znL#^ox2#fF;i2wP#nu10`Y>w6Sr>5W(;Cg39Am+ga_dd3=yWAdnDK7K)5fX5C%Sfn z?9a^2KMjSz>*WGq!k+fc?+>ivvmS#EasHOOrlZwMyDLm{CC`%wjz)HHC~H+D&nX@l zA7p1C5TDmEV`tbxUSlk{l^|~FEu%dCq=fpSl+dobXO1+v%xbq|mn-x~YUNY=A1IOO z6=!~^P60)8RydU3TIi21>oOcbX9U$b3tY8nm54N%fDjixPG*oPsvQZQ*FiOAOuRjR zQ3sh6RtH)2X~=fpz<>y{FU14prw3k?j1&$!stzYP?Bg+AA%Fk6ASrdYNi`pWh`f9> zPz$bqbUy^cOR7RWK*_y*eUG5%=Qe7#%pl9wLmwdAOVL9!n(<4fc?TSdf&#nB6R1HFBg7+#2XPq`5Xs zBbhKPZd&mOAW+nLo@O|4Zd-Zb;@#=&k`|~m9LSA|h9>bGa(2!@SAHKFxM$;;k6w*)%IHb$Z6t$YwD}$o3xRug>=6iq_hFz9a4x;9f=r1 zdtrZVJbZ?)R;O9^oaVDr*w}N@y)j-6*PB#5eeiTNY;09m%~l|^l!FEBPfu4@?xpPg zWSd(o^fOHI%?+Bb{u!nk>ng`EOqY`fR~(B71pQNKpN8ZNS{wobO@!A9$EUSW5a>r} z+3Loywca8yz8l1a(31#u`r6;4X+^{KKTnhP?abE{sx-fnRwsDQ|9$G7J{+#&N8^b) zJ?SnX^vi-m%JE6dzmcB~=zBI|&nX3+`qTdNjilwGw@DQaRqkd9*MrV^SDnt+c}`bc zZPzcal83M{-TlQrbkO6RQ-nI5b}p*m5{YMAm&mhh+CE6tM+=fcYZ;HaH_GkC?m2WI=)q6{WqbY?!vcJlagWPlk#bA6I8Z$@*EdO4`RY)nhzn zGTfdM*m=S8C^e>8_!u-%9%0_Dva(&rC9hA<&J1DH9++h0vExF_)(S|5W)Vi`w6?=wN?bpH8{P*( zDzg>WUOWVNq4VnM>S7e#{f!rd^EJ*YfK+@&)-`3s96I%I^%%5_z9OWUOo>)6AU3RU zqHd=Bw9c7`kTAUnw0=uP%zqM`#N(W<6ojs?qzYj%(g&XDn*jqc0s-QO1`r6TqyWRs z6y$w)(eepU-ULNu<%H&GD3UFt!jt>-EsApxB$$ODbPWj=zs(|a5B z&&_yNaujl`a78S3IxC8NdQ&C)V_fu*Jy=T6qhy$frCNDoJH*astoXCxnYw?Tq;F6* zzt85Fi3p3DR`*%7nTtrEW&@Y%00;r6^7U$Ld*NL$0bKX$k5VD#^d;MMc=nIRNefLRq;8Bi~o4ZaiBBhw!nKMZ7BLWHk4Jr}}G zdK@cvUgnU8><5+!LN0SNH6ae}|Ggj$+xLGEk=Xe77r`c!{@_isb=m_sWMO1z%pS2tJ+VPel z&yL-9Zy}hIpZ`a;Cbl#=hN2~K;@D?w3}j>s&&lZXJ9~FU0o5j+?uJhRO$Bq zvGEoOzSTiu$~1^(&0#cPB=q=h*CkL1*jxZ^W)7mHBmvtA{35k1R(ho|tEsXq#WZGU z?^;0DJ`KS83+RWca@q9R#@W&WU4{cgWfjf&shl@|aD3w@fLq=8xBspnWEfpUk+L04 zc2pe3X`168j3)Lp!V9iMXL zG=7u}>IBsbUP@5;r8%ohWjW#Btw0!qa0nX*=aH)FtDT(hoOy-Nw?a?d1|>k^`}dLH zTGKAH!azlVDix_PY#SKB1CNO@MnEy@osiE@S;Hq*+sapRP(G>Cy^}lq>+L$#ka&SP z^g>7Uc&vOUq^?fT z1TLFBOBGu@16J!1+<(|o^5`ABmk^xRw>e&z{87}~g+J&e;a&1<`_dnL(ke!eYAG;> zyHsYD8xH^Uwm$njgiz(l>WU_a`H=O;Te+Ed&d*k8h&zTx@p@G8}oy zJQXnk7R2Q3&AioF^w_Yz`V-rdyHa-3U(|9~K~&d)hPXPPzcz(9yS;-0WXOmrJ8*7a zYCOMB{Y7w6i+F6~Q9pF}haLpwnkkTjd&kESd3kIyOo=jv5;8@Vw6VDZWIZtr4L*pd6Xnfg z_`qKBB$vC(A6^8H-E>74DFT`?5GR_&H0W@KtFjl>jFWwg7X*~-vK`=MQIrMX*?ItD zT-@5SRaAL5@KN+E$@PjabOJhzTuCc^u%@KI=DIIWpO<#R7ynn^@$emfEh{PHArivO4}n(t5~EticE9avJx z9(s_~<^UZya?chg5-zx*fmdC3Zc(bQpi5B(p)`5y{*FeID(KiVolCc!>B zUlSG)@eC=PL~88mHMO+p+|t%M^(XktyYSG~P!Wdj6;(afk_g>SQFqVu4GTKE!40&( z&o=^qPGWSl3(ida!l>w{+}T!OrFnt&`PGp82<-WXFeU$j@7k}&il5tswF3A#PuAPF zWwS@ET6yu2`FEnYlmF#l5|~{$N-VgSbF7HMQXW{wDyXK#>C`S!0ND_yJpq z<?p=m><#;t_%{`RQOEJmulli$xe9Y0 z)NNVv1|bqmH&_KfBOSC4hJ%8FY<7v1#svM(_-}}(V9mFx7U>-rC5PjgnVK3ZKRGMj zbeOE-2tV}0e1u|%y?0pjge|;%T>pde3^T$F@Ngs0wKqigN4$!=JL7Fpe1iEB<@r}P zXO2HdX+_m>H|_0wDy}=4OO@M&!fv)}wdux5GY}h}t5DliTTCX8&H9!0eR%se?6%^& zpq;Ae23){JOdwHHc`KJ{S5g}h?2(6$kn!-vkX36DtVH=jiAT!tKKKm zpJ{BRI@UhV&zCtI!tFCN=iz9D z!#A4@B`74b4#{jw@)Q*nKY%p#JN09t@L&Y(^~a$1Q#v$+q`_F3Gef4}#R>onu5Zq9 zAb5A8oC+hFZSi3Aau8)u*cCDRo9WH=6z0mb`8WPB@xO?{bSJVApD4!fg^$Lna$egn zHv+I413E4ofg4jde?1=eOjA`9d~VY@z4P})1oNwE7rlrDhU5X~ixcM=u@SLj8gOdE zo?@`1!A{1)!;|o{&Y2k#F8zzU}>77tE0VR&5s6a*g_ zSXTBxuV)66?>&%L%;Y=}a~c$cNS$)oL;cGCj~P!|Kf`!5k)u!#Bcl2Z^9w~3!lJ=` zH443E-Zv(Be9BVTV5YXY*>U?tm)G_3!_j>KAsZ6s7U%ou54q{(epZ_qbK-O2qcD>5 zS}+{0pRS%BAGBl3zun?OIEVHBnl$=xqjm1t?eLq!OT%jiSz{Yzkf->o(VG-1v`{dp zfTaY`r#;ZB7z5)H85`@CvK#v9)Asgue3Q>%He|*Cz)T1+m@!?bur1-o;;29(Xl z0G?-0ZY9|)n^P7@x$;~cAvdcg-elt*bzHT$&Xnb3(Y$RjK3`%)J8`OY@O#du`{xJZ zscPDS)1nFr3T?5s_>9YS*ikZwq_Ejjx{)FbpK%)`NidY1ZOlsrRvx4&zYX%N&ZcpS z&Dlv-zCRWe6BA?h5~V|iBmu6o1hh7oxj69% z2oC>DmeOAii|l5?-<Pn^SITB=25c*<#^~94_EYoIDqj3ByIPkn6 zZi5bVbjaQT+!|nAsg|2)UUWZl0H4cqEv|;RtF_pc+)k!jN0oK|4PgweF>j`>~irmQBXH$!N#P#T%w-u24&p=ByZ6#tgS_W4D098Fmf@5 z)=4Ra{}HHPMMXu^R@FcX+XHzd2qPmSNI#k3bSM(kI~#AeLBCPZX6E`ebyq+L0u;l* zPvYh6{fIkxrfzGgNH%8b-ve2-^PRaUo#^bNnO)n4k+aGX0MfoffH(KXXim>NfR%@; z_s6^Wz=^&N*vIXoW08}LpImyNZ+j!~nk=Xr;Hj$>KnnsOimE1+UfeGdz!)#UQ2fEH zX$V>%X(y+$Vk{?sJ|2MH>kGQ-n8N@VBP=ug$sZQw(B3OA$0j1G74imm80^+BQ(&*l zsJ0-M0*UBo<|8!g=UUi^$O&>Y&ld4a4oTNjrcfqa{sbvD^$_XH^B`2?lS3MVvUUSZ z-gWEuL>~o~2$y8Xlas2gps$3!sjgqaDka>28_+rIPwE_SZ>vG%OaukUFJpiO++bh4 z1X&oeTJiIU9;~WEc!6)6F0Ggj{+Mt_K7dEFg!C7(Sn+G2v=TtjI-RwRl;naXhW0jT8j# z#DbLnPO-iGq-puW&pxBn`RhaFe^*?o=!i^_`i7sGYwt^Is@J#f);Sdnx@DEzA6Yxt z2YWWdy?Z2}pS%ydR3zxk7a&wKu(M#LXwB;WhvsyC>+e5kMLep~L_E2N^s3-0*`tv{ zKX8dbwjOM;??EK7T+?QJ@^xYngyWj56Et>I%8&E;Bo4O^pMHAx+M|SW)|BDa*^^H^ z*eE85aD-126`w`pkZW#{<*ZQL-DDoAJ2$0sHQL&BBq>qLRfC8m-X}n3!(3qf3}85H z3@JZ=O4q;V;(=t_mV#6F3gCO~5`#yes6dKffFR>{oTCBc8k+{V4;P?p2j~M^06J@g zEZriFe2v^YZ*6XaM7tl<>Ux&u=0#vBbK1SWSd(a^5*KdNVxLUBGr_$Fx0yvyT4BSlvY#P` zEfGAnkln~?l_Cd?vYpm@kOZ0n$P96T+&xXej!^O%Bf#Ya!PeD`(hrp0KDiCTzA{KS zud*6#=dc6<=o|2LHX9sopV()E%ZulW-8GO{tK@5mF+}B8>m%Q&DK%`KjyLh5Hae|F z)N^-zT)CLPzKVePq(9r|(XY$=1ory<`D@`C^NDXv@teUq6f^oq;x$fDq@<+DKm6uy zWn3OojZoV}R!Y@|6Ly*IUt|PcO_zek37`N-J*~Ot4(mBY9{PSP;34_17U1{~k_7{R z1~NaP#{x1R@h!gwGmSXpL-ZYrtPH8JUR2(vYKNv}g!@pW!UBT@R$F^t%MSU;`+Sg? zCz&Ba5RGYto9Ts6BK<~&ab|Fz9rxAw`PUf_5!cw#F_gKFa*eCIfTOl+4kOnfFR!T@ zPz`HWTIq6zmIlrq?ih<}cC*zkN=F6532Iolj z$h~mm8?Rp6r7vY*BrNs`Vm4ac{&90bx=@99+2*qd)q`QK-fn98`0h^vqsFo{yUM<= zUjJ2>*0p}kOwz-PKPbn?FHEcPByLDpsMf1_6% zE|(L0c?I>TIb7SZ0M$^X)>yqX4d7hNtlQPJJv;}dFS8wdSKbK-B>#>cfBREk7*7GM z96`>@V1Y@#RhEn=!1k1tkCPmeh+bUAM~~`fwLQ+qIebQ=pbrlnGRM7I8OR{9NR=!O z5~P6H#;lgQ^R`6Xbv3pHUM93ptjcLt@XnEg!HK8EZVI|}aM}B6mh}Y<#FQh=|H5?`M7Le~l5OW2H?&Vm#%9 ziG{Tc(Y^15Tv?(2!3Df4_0kW#dEnO|c!^2iBJ!sQg9ivipq7w{-{2a-50(sqxg~nO zT?uuAThv&9mkP@b%}Vid)Niw*6>EO(8fe=h4Y$bH)2*$>cQ$^v*^~9 zvQj~>?p~NQ201%VUc?ncNW=k0^iO(vdIMcve(@#G$lP1+w1-cBRCHIg>NBr! z0O23R;&OwX&=l~rdM;w@6bcH8n3(8jNXyWm54><@MOXv$mlIDf5f81P9mxI>9+Rti zV74k&{jpuM?i%$HVq zj$wPA)QYv*;{SA|KFfPFm^6KAKFYrK!tAV@+*sCNQx5IO@e-Tk zamK^(7aV*kFmUiy3#v}o7aIza=oe9g@WkfRqUzp1Li`?pALZ?`t`RNl2ZL2FnRbAc10;HV9VC8~dEQ1e;2 zv9UilVc;OhC@dDnCoQA5G-&Xb%NX4{9_Q&jj^oOK@uu0~==*TF)zT4_oH@10*@|U`%8vKqE^};GZiT~^24oIEG9V*2 zHz82)(6WYr2ym%|zADk0=kS-3YL5dKId9qBPBiwbosAu#h}SVWVBEt$6{?A}s7*H`{Jo>ELPxXcIKS%ZecVKB%TUW9iA0IjX9H)LOE4O_u zx)of4j)QQhH|zU8`qpr3xbY<+Ps}&TNxTg1FL(M$En~aOCQo4l^UtHL34BNoLLD^5 z(1Io@V`JVAP*G>8YZj+|aBe!o&QUYcy{;heYQk0$5`qf(@>1+YRNdn4n`9uiiQ{5=3$j_U z)$^6Aqrcd9FQDN7$b^ABhVku_!YIyio$Y^J&NU4AGEDXC$pijVThOyYh({wNM9eUg zGZDD*dYjF?5hs-%wKQc%H2PQ@joxiCDsj2`RewUKwyJx>L@Gsu2@eq|&qICiDB{jm zd-uWnh7;N<+i?`}k=1PLNmUK;f&?;n zHRZ7M{M();1qd=w#(aECGy|D!>j=(s3gk&CMvyzU+k9RE=Rq8zy;{~vxsT48LqheD z&PG#{>Q_T~WxCk(o$}F2eb=WMSFHDUEhRMrj?23+gN7i)E_JIeV8rf0PsLVqeUK%f zi?EZZ?)-j6SQ*n9-qsTno)86S%9mfnymWANtaJ_5X|_-8usxQGcf0!s zdWdiUe!EP)KQ%c&ygEW%jp1o-1zF$zA73fxMZ{_~v)Dx(dCm@^L z3o}h15Rg$BT247elO#c;C#~7gQ6LXeG3PSTGEC>YF4Bu2L}7vOBNyb7iV8T5J*GNj zry_?xWZN+@Ffa^48V5{qov&^jAj!QVA|(G=$Wi4puPw!LR@~9ASA#I_f5VZWQ#FNO zfCtAs0q+G#VbF`d|`}dS^a7>CPgfk43nREaJ#cSLe)DL3AA=JGOc&1xX zLfw^NgX7f+1|-Su5ax&xCx_PTuJx`kZTnl+C7%2kKVV*VZ?SAgO~c;t8Cv4K?l->= zp?MCn<)l17;NF9W6M=;=!O8mIUf{^Am&&7br zo5H1P?XGGq;H7Rn9|0vlBgl}UKL+JVjnbVm3f%<8y8D1m@IlxagmluGmQRKH6a{t> zW6D+D5-ujcvnK7JOwF6qhaO&@X&d2W(BeVhVtDT=v@CxU8f$QhK&VMCsPJ0SWX4gy z6k#|@K_ZsKyMYyPEJ7MD>egfTu37V%=%b#eJwN5pX->_@E&FKC!{3@vUd&TF8XH^P zmh&VG6}~1kp9{|PV?vI+I_LQn*(e+Y{)Whn9euH{qB^B(1!v}#@kTNx&gnDG+J)oQ zdL_TgtfuFL9$X50Y)1m6vV&&bU>VH$1fHK=d4x;V&ihqn87`IS0=VFQUKv`iIE z{BY6-YlQ)c-Y_}K%E2jg)9Yh-L~wQm09%{5wuujj9Jh5}pGs)iDTtnY;}{a$e{l={ z_8x#OgC~HcnQnZ~9Rp_mEf0{zRREFB#G`bIFul96`()^JwZi;Y@W)8ByGwT*yqI)7 zF}0tSq9Nd97`z_>WCOf!A|fQDr1cqi<*~YD*GRM>jw;Q@w12dJ;7B_5kmSM9xsNlV zh7n55<0+|_o7CclQlVi2lCr^Axlls1Cyn;OoL*P#j#Bk;YzH>s)m5#K64=O`0Z zpY`cKrq!*a%QG<_^KT0YG&6qb61%w&_vzB|URDknZ{+N%S;rE^Ps+s6S^9eJqXNAF zf%{)Y*0&oRdS=B31qPn__rLP@X}&t!dJotZCJ|jMa$JGO3J{GhxCw07|K#qI%rV=0mOn#!hCTI{139y7+!oeXd|U&7D+T-d7mGe0nwFv#;Y~d* zF4ER(Am#6sz6(}|_lwWY~!29V_^AY71?~~98 zyM5tN8ngBwkQY#XY)reX#F|t{xHm31-TuIJ^(jPQp&zVG?rf?lGGF}=f}Orl^9T}^ zh9GA4bb5Mvyz}klY9>=b_lDggb-IKIz~qrxW3XTXQSMyzDnraNy=ltlD3^Hq`MapK zhPbYsXLk=B_=(5ct;=;P=DhtKzC|A@dKXQZ%Kq9Y)zo==!gcoVj~QPj8yj0Ht&X={ z8hQJtfRvM6!+HB(Y{W4^u6-hEx?28%3XT`{cdEaPx$+u_|54X9?fM5ad^rfug_-Le zW`*<8N}{alOXuqq zC@YzPQAtcnB4sDWmeb(VwyuWy$}UTlJ>9(<$jhgf5%dAc}nd+;}r4%H;m`(Z`7s9p~CwgX!x8JaN4Q zr;3j<0NemT0O#s0LL7yxni>i0U&v+-7-fw6ABqgU`M2VT_7?vhOG?_%W6+{<=s02)fppWKKz!)OBX$T!{#Irp-3W2t34<M0EZ;DFuOfJ4O+SE7=bkRil#$79&r7X7pOnx3 z5fbx-wCuQY9XZV7bT96t_5w_%wVf_7adR}u8B$DJU_;!0-ggX%r>QuM4n*hW1o5L* zp<4P9cX1h6ZZ9SgVcAc)sYbp_{>ZL(=b{FXqHAlDK<^^xIV!!BnFaJA&aKHAV4lKSny?GM%^D@Y(k;zlYdJRrQEK)QV8p;V6A#4wutECfhv{^k* z3cCA(1DbHemD&VXZJ5@J7b}|KCO^G>eJja1W~$-x0N#shxMjvmIn{Nquy~+TxM%Wk ziByUcs+x5ecRt5|?5V}e=eI*~AQpl^O8%kevi%xmX-F#Jo*nZXoDh%$9@X4ZD`DHt z4D!633lqxET8S%9WPkt9h#{&shzG_Vs=3yW3o9GAym+n2Us6JyDG(xYJi}MBCC&!a zKR|c9LlyqVFs|)35p~b> zpQS!M422rC=ObifWcYL-4q?j&QW_vGaiZhpSeASKv}KyiK2}-+R2fHup^;w zfwOpTw3(Ad{J;~~ViagMHgW%+R2_Oia7(T$F~yz)`CU6&NfSH=;hpb(x|tqLasj>Bz>-RPLdp2A2S`^(JQ; zXWOyfprp7%?=>6@Ae4~JZfM^`eDtt`ms~s}Lv^Ie$DqgST<$_)(b{QZkREA8u`{YF zt!IrsG%K`WTWTD}P#Cvy4}ilxyRN=ohI}68FLL+&4oIDu2#KZl(zR3~mUK@OxpP4$ zB?_Ww3YC#))9Z=8s_M66Yi&Zv=Xxj#=7H2VPhQXj`S>1;T#uxjsxXPFDBAtdvP0p_ zw^XGE8WI1C^B-+3)$*;M^|aTiT_X}3q7PDsgn;aHA8;|d|G_2gd1<}edohPr>Vpw9 z&7>AZgQXuEZn=dF0&Dz}AsZT?1DG8L4?HZQ{zQ3+`ToxDU< z-M@S{bJ+Xwc$)72Po^uXiPHT)V&eY@d)Fiq4jgeD)?cB)qkv$fHJDWIKcC?nY2TJW zMfATvz~TDeUqHiBwn8r2|NX&#zfi@%MI7zUJDxKb!;wy1xAFe>4;PO+=k;Qy9>@Qm zKNw?D!Q^MF`JbmlKF!n;Q}=%#MP|YXcbro%ZQ;L9eUWIo#Zw>~>0T+Z`hT8u?>%Z^ ziP(Q%GFk*1OWo9bOX|0!X1n44=jzD)xN-jbJT!FFM_QcG|JMboD4VOr$Jaa3y8QQg zL~lEh|DOwu=t0Byzuua~{AjKSHrrGor$K_hXM^H`|L+?aKX&W*-o@cJidF^0Wzo4_ z*klss!^5}#6-9$sdbmZz=J}U5uHkD7_bS)@l$3*ySScKOss_weXG$tsF=28Nfn`-fJu0t&HtczF^%Cc0AI|684T~WP% zRTLDWB4c8xKfQtp^*7+RL`RTurB|(FL@~+o9Nqpq}M8OtXqt zn8{mt5QBkT4_O!(jBz@6v)nCGWWKM!yUGO)N{iF8tJ++;OrI zv|iV)DWA~{P6NTy4vA)S=Q&Ff-W4S&^&%V!H!v9T(pSzmoHtoX5%RBDWR)hAhK&Oy zxJzl5T7*AuOJno;zhb+rle!D44{H#!AkmK=wos%Sv~;o-5_An(pri5ttdZxd!f7{n zu_?fk+=Bwg(LpMq8uG*LypNaZY?aoY1b+0Z9n zk~K+yp3frobvFAPNDPHR?4}{?cd{1+&dc|**g{HbZ`!-$YxWNgW~!l}j0BLw1jISm zjF8ESCj!gLs|4{gD=lm54R(aJ1B(HK=6zj;gOF`_0VN0kIRliE5W$577NfcmIB#NZ z!ls%>2P3?2eRXH2>7b$B^<_iL*`0adc0-AwSPr&)V7LCze!8L-f|svW*qg59LB`?( zn+q+#&JoecDz`YCekRwB>;y=7=m@5UNGR5f?>D{PLj)O0n_Q_XwG9L5NDFzhC>PH z1f7h%0Q9qL@e~wtI>B0E3D92(o}J{VGG;50Lk081IwcKFn)!oN=_0LF%YozIo^jmS_YwPzwzPlk{3|N z%`=74!*)gUamJbZl(w9HOLwDH4DIk8K!F zbZ`U}#GF5dlREw*3EG3?0G#uq&1t9Z!PZafYIg2h)1QaRhj4J{K1UD%+zO&8 z1Ol`->)-3{U4IWJFdQa1mYT!%G9<);5QH7x5WBPmJ;OZmzaKw-Ou!u0p(7*XALC}U5%(GVlfnxKrzv1v zQGikvu0!L5Tp?CroKomgTOGiFjS09qwNwP~Bo{_gzc^H$Yf$WBvxe@`IO{R)K?IO1 z=#3uByc45(U>6Bzq5GbmoNQw-6mg|#fi$Xb7%AoG7#kx+3N^6NK`bE!@-N)K2m1@d zwBIn%nooY4slXD^@#w`hc3y4m@$iu1JFho1BH>09JmI5ORRr~5X-SKVdAW4r?AKr% z909+hjJUy;rhU$2}6l8t^ z@^`-c$vCX)IQ=2WMXp#KXA)p*29e=0pymmKr7wy+O6C-lcQ-SHT*Gx_KMyQIAqQu_ zs}_#e1ztD10mj!v&TT;H4r=i-u;Hn|xnqqq@NZwFXI5wVm;&K4TSY8puWag1m*k!# zGNoDe=kLVZbc~6z0u)iNvAfnqM+W<^x5rUtQ%6{(_$1lBMZ+6Yvx1A5kU8-gAQ&xEC&7p z%}I@c*bU(3j$X(c>Eq+wtGy<|$M1w0CpuGQ&8H4OMRyv7P1cB3i!uWoMWeu=7QkD; zjCcbFdH2C_;U!QJznQlCjQkSZrAct&)(aR@E3jS|O!)3LJsb^QDC;?al< z_U<{$*zsnJWc=yWyMLJ~*t#aOSOqVH0Btu#_ zKsyUr#IVvpbMEd4g22x(rP~0d@Rx=o*C5oGL;KEK#pf%0RB@oCf?)#5FOXOuvka^1 zp1bhJ7l4K2vL-1=K)5~+6j-_~mZEGb6ZfLd1Fqh!rL2i@>YpT&PoLd_@W=fxS55J3im6>MW@MU)7F$o!67(h!HBvKQi z!MvrI->_Qy&qOaoLiwb)lO2!${S#$Q9;odQ7CjfFBnt~>)*BUinGzCfCA)?nz4VUi zq#-k$ygVX=_=X~Ol+x3u2BwqEl|AYdTxR8=ucmBp^Pd=t)r=0cY2|Wkzy0+5w_PP3 z1bhPN|60`c{_5IV4jjcwA8?Yj_DLaWZn&@S!!`?XHWA z+S;(Dwwak3bu~3cm_(v6UD+A@*00w=1h|VDq)lxNXZ2-*zHLI-4MN*mjg2UgY}X4#~-WoZ>dL?bUb9;XGLsl$9YoMfal zwyvkwfBdt|345p;4ej<8&M32@<1meeW)LK zO{DtSGW@l{bt z?EU?|@AG^T5ys3?E{CYUbGko_N~3`gE6Oy2>2(sgpUvdYpPwsW3lkXO`d-xiqzKBO z2x=L!Sqxck@$b@j7Z!#i=DLFbXBtprMUC4_R-mTvzel9_1>R7|bwG<$aEvhi`62;CC>D*^suo_Blg()1_y7QfVn2t%1_jgEw8{*3+m@ zg_xgRo#kc7Z?ymB3Wzp_Go<8x>;#Xf_|m>I5O9+0hKAUFCHQQQZ>1$sY!v3aHUF*18CU0gxDd6J}m2??tNa8d*a#H1^tz9E!W6V zH<|=Q+aOJ4B~aP^zf(})Kf(14QTAG0+YOJN* zs;-8TQ%)37N5tfhY22&-F7<_k zR1r1=u?FuOV3CGCQCw!oJ#SSKOswKt%=B*i@cws6cGSv#z?QTGbx`*(&n=Z+u@%D8 z$y^J4W+l&FM-Xz}LP0@^0g8XJlh$X#6~|14I2AR zTF;$#7Z7D?d!H3;2|o#*v^TWO})Nb#=RVS#=DbB~Yl6AeuU-j4|KX!z^4M&HSO={?I2s=}Vl+-F8 zXKtFf&WG2PI2`^hh>yTj8XE~*(|a$zr~=>FAiTo43riB?WbY~Yacmn7$)LW?-Vu^w zv|%HA2ml&2UYip_6=ml4^kz1=nFVlTkzrrv=o2S}GQH(pOGRUEOl$Lj$e)F6#7S>F z5(0JSbb`;PMZXH?CDk&QYms1ToJtN?f021MByRF>ZO)Ub^2NWaY{+nSA^d78H0|>= zd}N;?>CD|!RI;n^=*sd|n)>9Gdn0SbhXj#t89jtkf0>=SVpJ%>Eb-(TB=@rSkA+qcyvT_!PiA{F4YG_$N4f2EMMOW~{G zg1WxCI(8MO{rna@$Nv4xNQf^l4;w(#1-On&l)Q)_p>Jc~w()dn0hm)P4>vbwvha3# z1UtObszqAYdTDlA1*=i(xOcMF_4zKbS?* zWHQM0GxhW5tuoKky;3lz-G&wPts6|=dP8Mbr1EOy;QmeqyH|N;QPQ_^as#R1Xy&y3 zCIfA$Q_rg^ARq{06@PHEuo=VUQ>f9JS?HUciK?nCVR1Dzl&+(2_{K792-RVRX@<56% zf->DoK=l%lA|2<`{etNI503T9Vx$TxUsX%112W7xVBzb#gBP@ET5SC9*&ld2gE;RvN{^KDrr#H z(qel0`0;prTAI%d%_rS|`_pMKXFLiBZ&r^unjt(5w0$BoSuQU2`=fgBO=wh7&mk16 z!3mbrL11RCzq$dN!D%^F@74pmlmx2XZ|awk3cO~pxuos6)~klM#~fd87`o_?jFOA< z{!5rL#*miQAmNvM!dI4F_Ctq=xP>P20p&-XSK)?36#QkkfCecedLpMZ^q2Gw<{g1A zidYzA)!ThN+XQdB$~Rg$frRNh-mLk~Yuo2xyOwyq)t~~!wjQS8@$ocOCYM{iIQ)xT zWOh8UdS|>^!S#(J?BX~Pg=!cG?2p%>XTcwmj45QtQ17zEkN?0iwJ~hrWqe}BJ~_{> zTiJ-R!{o~b2VH?AWW#MESt`hM{g99l42v3cWeEuj8-o!m4E#029sklTG2IZVAXYR8 z4-MTN1E-`5%$BQQYPP9|Czu3$x~e4da3><&AkuKzJe{`_dJC%_-Nxo-NqSNx3Q!82 z1XMyhv!HVbgqOYWUUz9vdpiagdQ@S^qAq9&v%fgL8!UR0S}3}NBTh!2HBgxqLsJhg z^C=EZw*M!UwoVoF)K-+>5++McR?Vu=o7w8CyZZwJsndAaGtVg`X()@xwkMlj&=&&+ zfG=Q+A4a#+u`=MAH@Nx*ex}cSJA_Y1UVxsQ5sJ5oxXl0bkfRi7>9#^2q@rY4_#fE*^0ek9j^Y5ILmyERrz4m+hVL<@(5k|rZ( zA^#dZh(P<#z(8gl_pS%eNA+1QokaB(qFe{p+PJ4AhM(VP2-kZGsgf9GW#hHQwPm{p zpQJ1|-}iq{RM5Y{zV5}C#V7HwjIfzjRlTQey(dzu$Uqz+mHoxj&)>i8n?W%G0ZX1< z?f35`9?(aJ<=9yXW56bSIae+RD+51LQd0gQIFre6aBz~m;0+cKqlwC!r9weKvKc=S zPTlIe}s#R`wE<4 z%1Q4TK+td)5*1~8I%bw;{TIG&@;oXFed0fdr> zo=r?LAMiCcK21JL(XoZ^xe4;u?d_Usn`n&JnMZv<2{K9a zY(Wwxg`zwvCY!KSc;kOPhNy0^5NNQ%?XB1j@e>pPFMuKn?(=qtrFJ;bohzt#Q+R1V zdFGcA;UqK`n(>j$pVbXDHeM=yxcT$L3>&lua&MJ?evGF-n;SOpig)c^LalP&{1(Ty z@8l_g%D|95KtM`~%MnI5GhM~@$jr?1e7(f&jD44jgipy4y0@J#5lVxJ@Y{b!NnyhF zqsR7>b}O$g*FKd2oDr$T0Q7UIFEtz}s9B_U8ukoi6yFS-T!%0(^-Ds6dWA_>Olx{N zT^|e`hCg2JepwUBRZ7Nu`0ybVyxjyfZX3Aj>~?0PL4Ae-Ih%bwo_Nrr4*4=n>j0UA zK{kee_aYJ3D$@f+uDl2i>74tdpAkBNNnTm(_A(^YhT2^3VmwAS2T&mJm??YI6zS-MV=8 zgq_?Gedg+-(8eC|AGD>GVr46U0>9zQt0h~DZTX)ct{*!(IaN->uj)|pqUkdh9i>#n z?lKHS|6QtmaQELsqDchllIJUCEtz}Y2`$4!`1YHNPEx^ckptOftuTW!LuTO(X+pfT z{{G(XZhh<6(xH?Wih?VS)`ZYoMZr`7BBzgaZ#O9cq0NOv4_;88h(nhnL#{=VFi;Ae z(7MDX2`K3sINKt@*dgQ&fi)QD(!ZC4ZuXahYtFT#<|Ze|MxD$o+Oh=K!+#)mwo4G6E0*n&fHGzTq2D{|Xi{ zVko~_eJkMt#eQL1(@oozo~I5nSp&#U4sLAaHn&S?`Wmr!a{2*zki&2TZnNuGZC)$zan6?+F-8@9-3X{V1t#Ayg2iWyH;R7NeT^b{CA z*oiu=&>`a@8dO;r&3cnGk@;{08b`*wo1(#V*q)R5B!hK!=~`Au?NwpnQ=mAoc6X0K zZf?(xi}W0-(2ChS4pu<8^O5))MEy!aKWeSx zGJYZ)-rmrag$V{}D&*nKi!N=S&QAnwdIrM_$x}(6V;c!84H_W8+C~9d zqKMoH-6n5wsL?~%-SE@FpUKsp413)S$`iAu<0+3Pa7VQl))W^PLpE!maxMTggp@h=sl17Kk@1=Qc?mSRjiJFT6A!(&OeJ(C^qvMSj8tLAtOX%?;UbJX$LHarH- z!F`KZ(ys?-+-5>poq>#)k?aYb(Oueo5qM|R` z?8LN{t&9r2UL!4>U;C1dwZTjO3qEx>Wc~a*SSFp<{$z*y+rttnO$+T9)eub@0~Yt} zNGjoSL+4HC8xXqKteF-$hUbRf7w5VVgy|qLn1^S56(sk9cj^w%r4~TK77vSALm%>7 zf+x=rckxEJ((E5NqL$$9N`QPXR`Nw}lSFun0#Q=chE)p2KZK?YTk>aVu->jU=!2q} z2i%gl7cF2@V&dif*!AH}; z+WHuD@FHdZgtgdqO0rvH1e;(!ToPibgpE5W^QZ` zusMXYpiE;Nysxj2k-?+DvpE>T{VK3p6caHu&Jet~5P5AP`hwET+}ykeVl7u8RptpC zjwen4eE)$xZ7?Gv<3ZKp!O;;uPD?Tg^10>3j6h#4l59fx z8}6{|@&fV0ZqZJG*6Rezmxk+*I<@?Z|6ut6+~qBO+lIISxbh=F=RiUeMIN<>x1Dj;?|`^z zHRIXc-oB_0sLC|VS6oAY_D%Knawszrc?CD|zWV3h_un)$2w_@zT19%3{55KjPCRYj4m#$-h z^7LF>Utd3C-$Z_b=6}8@YCuY&DFEM@Pvu6!H@-`8y_7jfle*+VU92q~SqoH(4ix0q z7rN=$gyO1weX7*dvwhD_OBxRRC;{843uE~5V)QG`cS`|JLYlZQxPb>pj`*}N)>9R= zKX5>!lODEcetsl8EzHMv5c7zUC;3i9_o70z`M@00ueLZEDzBKCbBz&6zZM<1L`A=QB3!^F_0+~@OWew>b&a0d zx9Q5ZBashXr=pnY0NXDHB>)|zw``#)bzs^Waj#dya4HLB2oFsHCGWks-wMBohBBfq zODwSMW^8U+bVUL?E?Eib(_kF7D@TryP-RcfTkXE~C=@PnkJ|y~gSVu#g1Cg5*Kz?h znq_2-dkdlizaBmvtsX*~iCsM^R-Tj3B~WtN9P(IoSsQA#0M*+Uh#i6%x}w7Iye#Ws z4TD=mQh!YoG}Ql^7_WAOM^S<@a?d&`2LtRc=6X>Tsh58SgLD1`9-i8uG~*N{Af$Z@ zE)zBVMS|;x`6v!jD^$PoZ>ROKd-y!}JX+}CQFGf8{*A@ zO(($#TmTk22DAV{q3v^%0JvEhPs+iY=JOd1VJ`V5L-H4Mczkm4y4cGMN#FcDu?G&& zn!)nv`#SbqwNKQsc+_{!6$o{om zW$n~*R zt~acZL2OEAiD>&Pc6)I z(AnGu3oqw;7ev^tliufJuAL@7m`(edWIv$*L`Uzu<&uu?OSjc1@|vM3&O(n zc;7(MGcL3>A8q>Hcj*XYM~LdL@b^s71T_42Ol{YXl5ZGIt^XNoZf@qf%fNuisaF}I z60>-J8Srno+9Br%DJ#8#aS99Qe+2Twf3w)+b^cZy%*OW+2i9BWb)3zm_y{U$YO4iD zmon|iMz8#Q)}DThu}-+ntJB)xDB_Xxq;@+hKKvn9W3KDWTEYksd}~M2DhwltuZM)q{g82m=dk! z*|f4Y32^%#EdYHbm}V$F+}*W^bm4tsVPo@$g%mnL9>x3sU*`#kj&HBb&pWn;8UMg* zxQ9El^9vTj0@$k5L9712ps}=aKP2!yLdxMZ8#IUNKv}YaPSL0};KmnzYbg1Mc#x}C z^i`)38t1Ek;j|d5g(zUp1D@sSiif-eEaOFodoEK4- z*h^~`6Y2Q*gDlb-pEq{XKE3(4$mgHqd{0_05EanVf#c7t@6EdEA0<@!4bN`MrTD!; z7sBy#d_6vzxeetQZ2~qEI`Sp}%YFbB7u--z@Uer31gv7NK*!U>Cnw*r_${_1bm*=9 z48}NWZmSXYUeWFPk7`ZcUblnW-a(=LBnHX6AF6m}Kbki&KQ1BKip{R!IoHKOORlp|pno)5M z)>ZF3ks?h}o152`b$Se;qJS->8Q6rT4{P)#py-Y!}UswT$abdXIE1? zB4&&%VVLr2zgL^?hxut`xp8uM#Jd}${s{M;7VkSu_3r-8naDpUB#**Z6sU!(T1mzy zFJ0gzQ7o*Nq~M!I5Z^2xgbOUE$c$@G6674t*D zH}h_AX#CYoC59NM?%|Q?4{MI;~zz)#A^U<|D23L%e3yPtot11dbo~xdA2LRefbJQ11lVUBy`0&ngg!QKdXjo@YqtZus9pCxQ2@VDxIVtV%*h za3(BkOPz!@O+0IYlrx2*A|4>u%U;QAppdyBI3rR_;EX}U-0{c zlWP&vPGlh2Cx?Rg(7$tbLfj_`!|3m%R0mufXTT>k|92}aAA0Duw1Vd5UWUjmV)BCU zi0}tGf_SXp69(=+JU3+ea8dnIdW()&sidr!GuzI<{rNMlrE?yK;!ee9(BJNuh06Wu z+j+tA){a)(M#4$tCRID5#GR3fn4hdQ=J_0bH`Fy4l1F)8_R5$sAG-C~Iw*3(M z#W2VA{q?Lvo|%;mnX{^`h!NsUyS?O9JXLg;P%a4JY_~I?Bu|jIqkyLJBD`^Y4F0P{ zhftXeUvPA4uokgnyNbO$SbpKQbAoElZ%GxYYj8K0K2Uag>HW+OdbSHHnzm!DK{R8i ztW~bc-

    xcM%gI`fSvEo1OfOieO{CVQp~?jeD0Gta0jGzwufLAcxu+!fsn#YxxQP z38QizqKKBTj#PjTS46K!t8dW(lmbQS@{EdmAeUNwI9NHhr{uqekmyBuS265mTIhOf zIJ}5FUOEXQT)Vye5a&5@K;Sf~Oo1abQoXte${VyiWLUQykX7R=$BhMX4+<bI%pJlDHzQTWzLI%NK@?y{Ygd0b9(g;&41 zMW*(79xKp?lJbE$1*Xrz^G}b9B!1H0*3(y`eZm;sYI>7nT1w_&#ae6d3FW~t_aF9&NPzFQ$>ylL;LfuUZJ($kF9P! zu$z%8Yig22L1@1+yyoxNQ#MxIqt-< zMm@u^v{k;m<~y;jWq^#HZ3;_ADM zojr<_ZRXtwC$dTrCDIS_Y9y`!IB@5-f(Q-87ch#2OW2&wqH|WsfM;dI&aA8H7$gd1 zj54O6QH-GmlxTef)<^g{{4x?*8NxHo&G{_D2Pf)8Ldh>1UFz3GY1y|Q4;LJ0)wzHe^bf3N(Nv*fjv4^yfEtfDkZ~V@=L1sP1P@fuIab2LuD|;97 zX4{nE13KsS(MWl+>})l4jlahv@Sc>y06k`Hl5P_r#99;7k11tSadq4yJ5e}_ol}JMpKO%*r zgzf1ch}WN{RGGZ$Yd>5s%x@DS`t39cx7RR;Cmw^%jN-w|0L}SeIJ1>Uy zV|ZBem91@m8mzp$^3<01?Z}IY9&OV>v5OoiNaXeJ5#3;`)+y!oXVqI6u58s!co>fP zYi|#?L9BjVI(KkYQg5YFFM^gAn{DJFim&t==QJ_5J#Pg6R1dPn)eh9n%0P4ZAW1zN zaILmLi2*RL4m;=!-`qxu@;X&*ja!~^8~tMcyUMpHc;9YP94$S&G96Z%Dm}uKy<%!n zcS2c-Qyj63kLytd@%Lr)pGc<gLvvxl89JN^f?pO`Pj27*hD+)yVXvaR-)YAgYbL zxLy*bqJs`?Q37LmfQ<15ERQs>FT_N5nSf3ULUVpV-s3ieBWP=Dg9AK(hR5VlA*e%r zhTFA}n_-zwy$8}131ojumIWo;omkj@v%4736eUJOe(#?8cwfuChi!HnuAV55@SEzm zXYssv)T0f&^XZAA`fp(uS{@q_L6`m5`8fMhJoTuL(i)>h? z1VTpVAILX4F@4IA$07U*WW@%x>JW~w-GkKkeqam@2taRIW7oulbka>&IFsxl)OlQi zS}Pom3h1qZxD1TP*)dgbpk3F!l`krOv1dmw^{C(hG1&z+A-;mkyQZ5@@Is&-ry7e+ zAfyOFt%ikqLqGhq6bA{n=YFpsGTAQ=vY8#X#2*buoVUXMuV_({BiZZp~*w=I{yv7$L9tiY;?asD50o?Q(t&@p^I2m z-rrsu!_oD3KC%f~b-khA2)Q3Jz!_5{{k$;cZBlSTtHwjSNV8Q%NJUk76 zgq?vC=ynx*UVHCJK^&A|{sA%D8ax=WV{4UMWZ}2{HG8Pugo-TKr{96+QQq|AeoKom zB&U6Z44&Jd%4&xI?XMx1rKQ{{;Qd2+p7o=SUFV`x)r*GX*_(f4`^*uZNj*?ZEHBe= zuizX`P&h3NdP&wXy^3!-GFX9nRrGeyF52&RnJeAUO|||qzY*FVSyS+&9UjH75bu0y z8nGQedy>7k*tZ=iHPeB7-4ITKr1~cwNgr^O(IjZk-2#7}!PhpQQFJK@Z()Y6eYM>b zg+~nIl)&!5*Va?2W{0atPI%8P2CA*~|LBE5D<5Cw%i2KmMpmzyxM$nf_X;e0 zDCLqZ#<4|3MJawHaBT9uujcc}DimHT^?Q~!l@X&1l=>zzc;k(!3~ZU^PzEfm z%uGyYY9xmfnfQ@`4}LA{7V?c|PSr%vVfz^e-_$L2T{Nb=uY39B4}Z(diA@_5l$xv` zQSh0o-upmGL!%6U^me5jL)Tr!z0XCPc{>9#ae|Mc8QrpElbPrg_c}JzvNYf%i1{n> z&8Po+qP$Db6JEsD^G1rjE^Xvr#fWjV_$<-_E39xIOmt~%5S%+c$=C3s!_L$Ait`Rx zZU^GjuxrXlOdzNsmmARYk}BF%g{*;IogFW};O^0Z${<)r?^@UPne}{T2jH`Ti?g;@?ZkdI}F^epRvQY~jnQla4qe(4qR-P9HkSWFp_Q;VFAt+)PZ9jE6 zq=TwoXJ&4WM}g_%<<-DLS|uDXario5osJ*n<;e+@I8JAO4DZ%Z%UOTQp@Laf_4csb z`TUhj;IgS%amA3}6Te^Tl`lgz%F^K{5{G}m8F{#l@h&s()yuL^+)s1fylDWl0+dew zR#8MlAOVbu3SO45m(MEitz_>SylwPqSu=cBZGm z)Nf@i+U)KN8pMuUiszG$5BJ?tE-WvOtUYb%C=j@R*^*%>KEAwutvM07Xd+%hML|BooX zoEz<$z|_Cv>E)I|P$$-MlZ_!Hi!J|Em*5``tjF&nP(He7e9f~-aB%3R#-AEO^NvHZ znt03$R)BR;A(16XFZI${i;mtZh1V(2l*4WTVlDw+^(;XQD76+-`No%z>ql{e+b7uY zPY-qM#H3b!isMgay3ibjCnQFtx7!t?tXyZlf#U@WY;|jM{`n~4LO7iflTve+*i=b1AsH2P5 zye}?y%1Xsj+fl!C6xW1CnVK4ke^*&~`7m9&ASx%r0dsj=29bVOF-B=~V}sG5w%#{q zwUdQ5jq~e0<{LB5usqH`qrCTvza4l_H(PIw>KAbxnRp5BR|AvNH%UU@HbY*|e{ad& z|6}2hE|MXC!tZ`Q(=2@}wTVi+wPkb=ML3Y>_)z~MB~^yAIxS8wuV8HpAl8kFmD+Y=-~mnw(L@*{_SQ%#bh zZ?E2}%*%_5@bNo7q)(y|^~rq(ds}Rv2OTs4z*i#$Dm!l?uungYS-1o)R_n3XtGd1w z5wmu(aBWfum@&MY6!1^BD*)|BNU6Z}I``6iBYN8{;~ld>X8}iy2tvOsouPV*EX7-1 z-#-+|u1n9Y;zf(S5sO)(se02Vg0Qw4_~jNg=iAduEdqsz^iTD8B15Fe`EQuv0YBtsUO537;G`we>+c~y5 zENj$=qWfWWm`3NosIX6Z-bLvdO8YG;MAf$o!kZyl$QT;ue5Np#RkRs4g5>1Xis zZ_G#>41U%@q48Cq!p}WzN_++mDwu=pfNmQ=R#5E&DMtj&$*nLr>QRfkJ59kyZv#!G zHb6uV2n!2`kzY|UhYTRrR-E@x*%~X3tk+yinY>vij z^uuj*oV%zK4XvF~lyvwvEfDvpqO~5)KAKQN{IyOVwve*o)V|&D=4z;edK$02h@GSO zwOVwpWea^(x;ds%dZBd*Z@80?&x@Ne2q8wP7<3^MjxO^<|GsVrBSU_MI`f4U4osdP<~0!h0Lks}|k{ zs52)+3N(@fAfU*Eq@W#G!QMeAP912l84*|<`s_b$KhDl9e#9PM@}g!d7*eDMWM-#V zb1mC$Ao}|Hk|ByH1mwO<=Wh0}Y;XTfwrw2C2Cj4hi03T$*`(|6u>Xc%eGXbCIKUuN zvjt{SD~P@+c?LVA`14YEtB=p0F8tNGii3+8AL!2mo}Mlc21%=FwAaka4)Os+49P0@ z6Q7#)O2pi5;J+hLS!?@FYR34{U;Vb!%lC3R6F;V=BoIU88r0I8{R3-#bBCyH+|~$JN)Gib zPYvv|Wk!_dNt0T8;Wn3d-nF^jq8%YMzH}i4Rd42Q>+B59A>nl@P*~8m?pQx338X!B z+Bp~ZaPhkHSx9C)5Z$9-@hrd!hO)m>~xkQDh~eR*fez-6^G^m7YS0OuwLk*cr4 z+tIK!4toJyd`Qd&aJ&XY4dIIpwQHc{ItHCW3Rvm}fu6%0&41Rp3btAz$d4+ZWeu*< zo5S;Jn!KK?Db}^PHnAlc>JqeLd>Dl5=D_q@_mSstD>1$dCs}pL{BJ9tJ#`Kxg8cXU z@Szg{DM||Rj5x@%SAJw~_^oVLB_+2cyyUL7g^>UEp|*vL-Un{OivB+-4V%0lcwN@L zRxVO_Hr?NSBh&)tjVN1tTE$xW`rI4Op_p(&AFLI=aRtad95|~vDnOjc%gOOA*$FYD zQ01*sgvu?Msn|O^%j@V+Ks?MhWC)WDgAuE}C7ejfTiiEL1r>f6{P*v>$J3{H*nWAg z=GqU)u+W>qmjIUEIS49f@_=5bqT;)E>{=t_t=@InmkV8(7T1$@iccFE{@I_sUEFIK zEGo~S7D)Q*siCHjV$2U<;iL)CA=?JLC}Z33RR0_A>qM81_LT4uN$94|R?okXV^D(} zddUKfukDCRP#WkE>Y55~Zf>H1rS|u4by-+PlLT$?^P)AV&EVaaf}p*-h@ku9eLQ%B zT`Nrw;P3mNuZ}O_UBZCTBYj0aHI03_DXIdKV@{D!E@hxLx)7oH z#g4^@ro-c8p&;WkVa-B=@UVGgb&nc|D_22KSPnv9N?%Fva^HbyOubStg9HA+ z{}Dd9ht{SdS*$6~9^!@4@_T2pSoG^*#}IL!E6^XBz4s*Z)pRu&X_U$rZR9EB)b0Ne zg~{pH=aR-+P-OxPToJS--7p`_xp@PzytN)MINCmX`byCw)9abb0(k+qu{Fc{j^%3` zLS24-(EOIs@xEBw+@fpkq^A1qY%kENk4wKm{4F6V98>x*cg>T$O+l^~0&20p0E+&T5D*yg08U;diO<5p8ssSia9V0WNPlyCIJugJMgSn^dbBH_rHbV2q$P?*qFwP!=8{}A(H7;|1xxX9AXB;4k+yX&<@Vc0s zghXy7@J4X=A`VoPJ2&ETXH!vfA*kA$koJ^D=Pe-3WF z@j8E5aAYp+-4_(6c1N4jkXw_xHi5TQf1hrS*sgrucsHqcd_AFm3M@(Xh_l6o1+aw0 zqI?5fU;Ta<&+?Esxvz_p6JP$YWjEMTXXoe9Y;A2p!#WQ<=Lw|!+XI^k{SzPxYs>LJ z1ndh50>Jt9Swl5?dtq&fQ`Bc` zsv6}~I&77AbFFl!@(i~?3=NJspuSc0^k^zq=jQg*1L84ohaK6j3Buc0+fpHwUKZtP zO*t31Tj8}Z2elw1-P%Fu6GX=#tKI;QMh9XYR(xw~25LwVZ-C_341hzBxg-*8(Z-OPOLP+3pnbo)?DvTVkAy@?ABpv>_SP7(+t%NhIBu}$ z2PBn=nG4?dA1y$8w=Z&Z0e{pz?ayi^x0@b3z%0|;<*pJk(J?+}xF_*^%Z68>5=#k9 z1n0LJo{0lSjE!NOtlSU1VX6$Hu}ocJG-6&w6LJf?r5S}BI_4rt_2c)R5)4*Sj$6(_APL5NRNbRK`QdqCA+A(m_(H|7E~jnIe=OVLn~wY?bQo zk7mM?2-pNm!7W|yRQ+n9?@n!6AJmH!LS-=Ce^1DV$E@Z%-@)NMx%WnhFN*wQ@p5Fy zMnM|@5DWOYJ_p}bF=Jj(Bi|zVb0ha?ZemkL@5i$0=ckX;t3=a<_WOd+n%b$a-TTUU zY70rEoqw>fakR|cds4N#yR58|c5tc>t!kI}i+wW)J0Ae)+u&fYp!Ugir)ie2c4_tPoVYk`!e`AFVp<;d@HD#>F_7Ci?%V|IZ%1Z!7=CBlhS7 ztsO&HlEHeraoHgNwN>BMqc(NCQQ*(w3N=v_ZSL&MQCx&p7OTSIBhKXMr1nZZRjm{( z=ldA9?vsxRJ^FwPj?s&eGKiAx$Bff8CxG^lcjV5HN!SqFcKgd2j$5Zjos846)f!LSWysJt% z9UYxVKNt595ad5kOhn|7XgTg1G&Y%=R+2TOO1SsPv=s|wOdG$Wj+_I1O&`ESP5R2Gv|CH)^O6HT`s^AVvO$HbCU`sI%L^^8}IwA2H7pLgrHX9w6|CjqDRg zycTqnyWJb-i*sK$5X`t_4QF`i@i&w@cNsj~4AhBT6zdQq=gCGCPEG3-k%8;xcf9yO zRs7G#OAlT1_rhWgXgEd#g%%5x#T92kb2L`THOiStiAKi+GR!m6i`fyP&;>gP=RrY` zG2n5~6E%NQJ@K2*k>woz2B?DkixDaU!#u+4I-qL~sdMubwO3V5y!L0esaas8; z$WK&BG!@^7gJ&IPdfjThN?37d&+^(HL%4{&H_iF*-xvUq`|xj-=Zz%2hL$a(m!ax+ zF1e)K@M|Q_rn&d^txd;1LV#%s&)znxYX>KVx|l|o-Ry`-*Per;c-8Ae&s^~vQX}&k zDP!cCnOS_>zNQXyDjVS#D8lM5`*mExrMlylQ0-=_$uJTLnz;`I7CL{XovxsJ9RwvL zcjjBG?WZ0y6aDl|37hxG{323R&!&ESZz%rgS##VgF1^tv$8Ho9Y47yg9Oe@KQ8{jQ z+b8D#y(A8hn0mKc`01E?L!}A=Yl=;fU>4^qesZ8su6yx?21Ndefx*F8&vbM?JvT6z z_&GI21JB^@Ns_$w?^ePbF6aZ>d7_6kf`!ah)Cd(mc zKSK>d>MPZTGRk=C=^M~8RJMO_0nyb2wXOY69bd|`kc@AzSlYdnY4nx%XXV`2zOl9CvS}707qnvBRnDeZDE^x!1)E zQJtWBv$M1FZDy zBB+uZ&B*T3EreY~yZ@P_e6P#YIe92JhN-42a^!NKHSV)BSh1vCOWVmdEsUjkai?3O z(S9?VXwSHXR%$mIYAP_qlPZW~yYdBdlN;1W892f0 zwg`5*eNvqE2Z&GsJIe6FcwU95kQa5rdUAUhI!E2~5t7M@)XE78>3gM_y1;7?!x7IK z!?=5}`iz8(i~;bwx$j`81N#vWpc+rI|2!EH*ntK9u%f(N2G&cxb;)B@8p9Q%%0g#Y zktuu&f)*1K6AzJ)cz)#Xn9#^4unS#*R9SHRa33*B|J*A$c{6quMTuge=VIjzcTl24o>VH|v}H$`Qd)pg8t zhX#jKhVB0S8!#?Hi%*agofL%CR@+R5L0=OxNUM~qaM%_SlMLMf;}iv>n-(;@$z-S^ zTg8wG_t+3B8_!dk}U%9Ba3@$JX=ivrmu10C-yL&Ay zEv>c5ru9!wa#F|8(7E#5%rcH&Fv$B9pXnf4(AqgLV7~)(9Vt*Ydje^32koEsdenfkAvXoNIE2EK0=GfbnDpIZ4!BD_+44!7)*^i>OLO>HAD zq{!xA`?;>eCp(BVWUKKc_VfeZs9!LA1?jD1SrfEzw%y`#fH@|Ii|}!vebeZ+h?&Yz z$HDq&&6@4a{c&oRR&oolo0xq~a{YMXcrEGf0kO|A|1J!8cG(#UzE;WISNZ&%cizV` zj;K7Q{`}Fu)a$2{e`@yM@Vu)Wdiaf~rn)}$ep!_bGm2-$l{tHw-P^Xv&@{U5Izd_Y z&XZc7LzedZHn9wd6*Tb%kP5$%CCBT=e;gS&GL zz%w|Yw(Jr9`7f-efPkh*vVJx=f2;T3Y^U&GUg~bm(=5UQdARSLcjwx>UUfw14uI=g z1d5a!p~;pO($S)5#9QI983Gmhm_x0n1L&~cblGe1!ETm)CW3uwXKb~Sg?lsbK=Fw_ zT4}PR&s8VFhA}v&{=F zr8V2!-a(7udw6`au9aN7x@@n^O*^`%_p_SQLo%EO(`pZ|RYh-@3C1eCZ!f8-NHj=1 zYJ0(#^mruQA&uRA=Kkven^BSaOX6vJW_-!Zzf10W`};onFfyLD5l9AfEjl~{viYUn zv^}qoEhbjP_dV`QG@Sya|OCptF$8OB`FPQ`G$g91E8Kh5;^m)z* zTbqv;E4kHCK8IQ?KQ?(L9^%(BCwrP!=eS}v3X5f3pJI#{_KbvL41p4wVZ?7*=7?59Eb{(pR&_&n?s~o`gge{hYJSPwiMvo(Dv59hwydu;Nm$ zdO6JAY=~kZ4pWYo*;=62fzcH#rf1X6*5xVJkChXcoTX=YDVFiSj%2=O{7tdMOu{T) z{ad-sc`F94rr+RYbV9TAtFESARmc`v1`H+RiIGfmO->uTATe-ET1tlN{;!0*7(9Hs&OyOl!8()z#0h zbYCe4c(EH1JM|}5S<#3U>w|0VgAcofzuld0;TbU@=4*czBXnM>+h8H)Z`^pzlE%D~ z!2wFM+Apx7ynyPDE38yya^3JF%twqd+33=hsLgk==b(^xiYQh2m|czS9jL&kQBG*# z`|_iU0ox?ms#D!yfAi`JFwCEgDQFQ?G*QQlY;5aLJ)?i$)0^l8>)XOZsv&b)DlhIY<;N^e4j+>ATNsF=gZ5m?9CgzYP~rr+nB}=+G8CLuv?FP z#AK>I9F5pfmi{lIz5*)Bwp)7$X%Q(AL_!4wq`O2)qy(h98>G7wq(KmA5D<`-E@_Ys z2`P~->F)YB=RIfrEY|m}ml%hc=ehUZ*S-Ri@}(xLG?Kpd!C@nLy@Fd#vBAG$jdadp zs>g)){*FH;X>lb-s!R9jd@knp{p*ma)!+P<)3>c!0r~+-eCmCRRPHM&F4NDQH{w(D z8~78yQ4xnaAtc7->E7`6V4!b^ii#>>fVI1{CNIcN z$sonTlzc2=VDPndCDmsuIwmFtOnO|}Rid2O=j5NKNL1h;sy*k*of+ou zObIyUyp`=~S)nD@Ya_-cW(;F3$MqyZd-L&wv=(gmVN0csa&bYyD`pbN`wXk_N)|7dp(-9vkW6oESE;|o zW!f#f87PKQAM*f$R6>F@Z^ z@)dsCIRGn?M!Om07}%{1Zk3@O{%4wo{^_wBVl89sGimIssi|od)0NbF{$`>K zNlf9~cTLS?nw4$UvR`(LuVLy*Wq9^%%0|><4Q%F$>g*N*YEx3k!KfbCfWY#*$#9G7 zil)62C6$#OBehgi8RTGUy24atGlfq^^BL@|cJ}vM;h?;!Om7vnw2}d;e^c<}bGM@a zyqb*en-@P2EEheeJ*Zi7FALOZVpefc^ga-W-V0X&TZIxpoJJ>hmqN+5}Q;40kO7QJUITtZI#w0nrjgNToDfqKQ!)BM?aNw8VH8q>WFr@E zYtYVUxo#f}`t&r{D7}|>AvF3r>{Q?c?Usnh5T#3|`tt%F+<%-92%pN_c=Gaag=mf6IL8nZxs=WxQYNw0UfF+;Equl@=sdVz2=Y z1|`z1Yp{Q41_#f9wvLV&MDe7e@iy9v7bw(19~sC5OwZe4J93p;zmFR_Z!viyIC;*5 zjV=9BiH|GDK$US^o-tV4&~x+IpqQZn2TkR;fl?T$<;EGQ2Xl$4yl|V8se0l;>7}O+ z!dsFKJAUl*srHx_wyEis;Bf!n{bV$V{x~y37CvqdBdIiQ4bmT8?tph9whp_m@vh4| z?r4o3pj`a9kAo(JC{`<&hYr)6E`baW5s@hK&AVd21feznI&U{Pb3One>f7s7+L-&31m3={VKfH(C{w-9_0`uuB+tmmlD0vU zeos1G9z&!vsfGmZ$EeiQj}Uq$c|%?nwGIPLoK=E;m068 z;I{t5F%6tvKJcpf>APHnOwfejN)jxF6&XdH>+bx!W<4I9*&Tk@gf)w|ZyVLJ6bsRd z*Jtd7;rg2cY6GA3c=6lzR5VW23?E(Lc zXera5Eax9uy6X!`7*`v(tS2id1k8NJ%%6xxjRxJ@ecEp-N4`$jclYn_Rr>%Fp~eJV z&Az6l@0+zwoAgoYosn*)$Hq!Wg+H&k>^9`i{xk0&X+4^z| zJzV<$jH7VgR}f{W4nx;@DUu zf{u^bfUn$GKDC6GoJ0>IQhpiJ6>R{NlUWkdHq#3L1&m4pG!P!a6myw2BZW9|J`9NWY*xj36 zW!Zc*^*Z-kVPT;uIMH4(Yu6ZnAC@b9Oo+?Y(34Ogu%Ar+`QzTetK|QiCUqt-AfW#y znLGoA2SAK5z|s`94{E@a*Fe_Okv%nHA=w0%3gLHnISx40WxomTsJc@X#m_p)F+rXf z6(QCsUG5gA%giKLssteKv}-Lb#W0?p-WsrQ0&E2z;pxDMNmU8X5h#d%jz75Hx&o-C zBqxUpN7%R(7dmH^rDw)dqLKqf+_y*np3cxjeA%<64sA^;j9Db@dlem`c6RLPrNK@T zW({N<_ZB@CXXN6-Y!hjOG%9lQEoSB-v2=OY+}}A>xfwL7bc8w@rAA%Npa8^aaNYfC z3516<=tQ;&Lfgi6oNIq-%p}3~Qgi!n&2TBq%bJLt>A}l>)B$9ZzRq2p{@VJ~)Kmhv zn&Easq&awTfDSti9B??#mXqFALyLct>JH&o*nZ8v0G{tccFmMLbrepXvXJ_a7rW49 z!OFeij#t$9j^o}`NH1-&C<`M)8~h}C-2HJ@o0qzdMpX8Dcpcm$u8pb}?Lsg+Z1U~S z&2e$8un!&{P`K?o3!WD@P471R8e|q;2L`s9p{28U`Cn=-31^*Nkdp{3l>HiK zt9bx?`2j-0x)GDgd;)hJywXpk?z}>nkV1ZmGNanAdVi45ZXOjA7xx=tc7VX>_FnrP z(Qix%FInk^nyNMp10{rRsi>&H?d>m-ffU&K0#Ytu{{f_KYrw}fmL7wk!=Qx3pyVXQ ztpBo_Y+KoYZ+l~NhX0b|w6Tz^;@^V_r_KYq+zKx{BcsPQ({;f>b_O%Zi#Kx1Q$t+p zE=Zj)Z*I6AwJ5uJm%Jj4%QH=qp~3jz9B>&Jv4r#RcbsDWh&f^_HgPg>S!oev=K{Q- z8j}Uw*mN2^gW*^q0!1YEjd8R}sy5?(IpHDiA*%wy5ar>OzX{B1DNqcD0VsGkdSxGxqa?Dbkh>#gbYajKBSP7lGgsbq=(kKAqbv`WOhL{WOGc}>MmCM9@UG(3^+nt#0euF6fO_3u?{!|u?^_O->;xbN zN2hRpen|B?x<9PPB4ARYwg`#|7*USyycR=S@P?v;;&JazwHoVy{&d+VWH~bt#lH+< zFQ-310qX7V-+HB}_=$;^*G=xli{=2*y%QEj#@>E#41k0PNh#)^2dyHD#4)I><8&g} zw0DAi)9aIBW52(+q<~?(j83DsED<3gB{TC!K5*u_hFc~U z4)o6%84E6OJd4BfbD=jkk&#nIf;hCo;^Ji2&j--3^T38f+^4GA)cc2rf|CUaA1}Yh z$c`ba?cS@dZ1+4IQJs#Bjg9BAqXygZAQf5Z)7MO=tQ zZGoLSBvc!MOM>w&NG*pE5pLCvYPh$Y6myllO%gx82GTCxP=l9;C!|p%&iGt=vG~G> zpSlgFQH&_S2*eNsmpKVuthC5#s)3i=GbM&y54vG$ft7HN$M0b?yTXD3xf{Cb%??8% z;=w96xH(5dH0u;nyfP&(56^`y80xhvk1#4hw0y|}h|4Sm(ul_WLg0AK0twHlkmn~cwq?ijdQ2!yV#E=1!YCz+K_{~s3slFmWt zDFpt6pQWBa(rD+$&``_Rs3?VuL4zHCLy`9$(h*Z~?*@&U(8IGZc1oLvGqwB$U%gl8 zdG~t=%bM?&dS0|)yAd*H)z~~{2M*5aBOzz$4_3+?Zg$62(r5GU?GU!t^9|vZD(|

    oxENBPoG&XG1J`^5EE^4s2Ox;~L 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 diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio index 121c5b2055c..d73561338ba 100644 --- a/release/datafiles/colormanagement/config.ocio +++ b/release/datafiles/colormanagement/config.ocio @@ -11,7 +11,7 @@ luma: [0.2126, 0.7152, 0.0722] description: RRT version ut33 roles: - reference: Linear ACES + reference: Linear # Internal scene linear space scene_linear: Linear @@ -51,17 +51,19 @@ displays: - ! {name: Raw, colorspace: Raw} - ! {name: Log, colorspace: adx10} None: - - ! {name: Default, colorspace: raw} + - ! {name: Default, colorspace: Raw} active_displays: [sRGB, DCIP3, Rec709, XYZ, None] active_views: [Default, RRT, Raw, Log] colorspaces: - ! - name: Linear ACES + name: Linear family: aces equalitygroup: bitdepth: 32f + description: | + Rec. 709 (Full Range), Blender native linear space isdata: false allocation: lg2 allocationvars: [-8.5, 5] @@ -93,18 +95,19 @@ colorspaces: - ! {src: adx_cid_to_rle.spi1d, interpolation: linear} - ! {base: 10, direction: inverse} - ! {src: adx_exp_to_aces.spimtx} + - ! {src: rec709_to_aces.spimtx, interpolation: linear, direction: inverse} - ! - name: Linear + name: Linear ACES family: equalitygroup: bitdepth: 32f description: | - Rec. 709 (Full Range), Blender native linear space + ACES linear space isdata: false allocation: uniform - allocationvars: [-0.125, 1.125] - to_reference: ! {src: rec709_to_aces.spimtx, interpolation: nearest} + allocationvars: [-8.5, 5] + to_reference: ! {src: rec709_to_aces.spimtx, interpolation: linear, direction: inverse} - ! name: rrt_srgb @@ -116,6 +119,7 @@ colorspaces: allocationvars: [0, 1] from_reference: ! children: + - ! {src: rec709_to_aces.spimtx, interpolation: nearest} - ! {allocation: lg2, vars: [-8.5, 5]} - ! {src: rrt_ut33_sRGB.spi3d, interpolation: tetrahedral} @@ -132,7 +136,6 @@ colorspaces: to_reference: ! children: - ! {src: rec709.spi1d, interpolation: linear} - - ! {src: rec709_to_aces.spimtx, interpolation: nearest} - ! name: rrt_rec709 @@ -144,6 +147,7 @@ colorspaces: allocationvars: [0, 1] from_reference: ! children: + - ! {src: rec709_to_aces.spimtx, interpolation: nearest} - ! {allocation: lg2, vars: [-8.5, 5]} - ! {src: rrt_ut33_rec709.spi3d, interpolation: tetrahedral} @@ -157,6 +161,7 @@ colorspaces: allocationvars: [0, 1] from_reference: ! children: + - ! {src: rec709_to_aces.spimtx, interpolation: nearest} - ! {allocation: lg2, vars: [-8.5, 5]} - ! {src: rrt_ut33_p3dci.spi3d, interpolation: tetrahedral} @@ -170,6 +175,7 @@ colorspaces: allocationvars: [0, 1] from_reference: ! children: + - ! {src: rec709_to_aces.spimtx, interpolation: nearest} - ! {src: aces_to_xyz.spimtx, interpolation: linear} - ! @@ -182,6 +188,7 @@ colorspaces: allocationvars: [0, 1] from_reference: ! children: + - ! {src: rec709_to_aces.spimtx, interpolation: nearest} - ! {allocation: lg2, vars: [-8.5, 5]} - ! {src: rrt_ut33_dcdm.spi3d, interpolation: tetrahedral} @@ -197,7 +204,6 @@ colorspaces: allocationvars: [0, 1] from_reference: ! children: - - ! {src: rec709_to_aces.spimtx, interpolation: linear, direction: inverse} - ! {src: srgb_to_xyz.spimtx, interpolation: linear} - ! {src: dci_xyz.spi1d, interpolation: linear} @@ -213,7 +219,6 @@ colorspaces: to_reference: ! children: - ! {src: lg10.spi1d, interpolation: nearest} - - ! {src: rec709_to_aces.spimtx, interpolation: nearest} - ! name: srgb8 @@ -226,7 +231,7 @@ colorspaces: allocation: uniform from_reference: ! children: - - ! {src: Linear ACES, dst: lg10} + - ! {src: Linear, dst: lg10} - ! {src: spi_ocio_srgb_test.spi3d, interpolation: linear} - ! @@ -242,7 +247,6 @@ colorspaces: to_reference: ! children: - ! {src: srgb.spi1d, interpolation: linear} - - ! {src: rec709_to_aces.spimtx, interpolation: nearest} - ! name: VD16 @@ -256,7 +260,6 @@ colorspaces: to_reference: ! children: - ! {src: vd16.spi1d, interpolation: nearest} - - ! {src: rec709_to_aces.spimtx, interpolation: linear} - ! name: Non-Color @@ -280,5 +283,5 @@ colorspaces: allocation: uniform from_reference: ! children: - - ! {src: Linear ACES, dst: lg10} + - ! {src: Linear, dst: lg10} - ! {src: colorworks_filmlg_to_p3.3dl, interpolation: linear} diff --git a/release/datafiles/prvicons.png b/release/datafiles/prvicons.png index 364d9678f0bcb7427e1a163c4ba6047873eee610..dc31964b33f05a5a6504143027419366e7e5281d 100644 GIT binary patch literal 14130 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

    H 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 E3y102M*si- literal 12311 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 diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png index ca209835c89b3ee14a109584cf19823c1ffde5f7..7f40ead3911a72ea22362d50239e169107df00ce 100644 GIT binary patch delta 211368 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%0AR0Qan^PI6Y%49)20 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%0A70P4SA8JHGMzYSlS0svaba`XVZ!dmko6 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�`$l<|90!ND>I7o2S)F6gq?ka2hX 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≤ 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 Y|j}(tan>y|WSP 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 delta 108017 zcmX_{Wl$Ym)28sXAZH->IIS zzPnfTT34^(XQb9;n5qB-`1emAPgZ+jY-|JqApnK<1@zfmuW8`Zr|+M{g?=i!ET6Qy zrx~fJ?Z0}?tGk~&$SB>Cs=$#P{zjwoT}5+5CHG}MZwpQIVSI>IX=8{f3j2Fp3WFy) zwSai=JuE9G_(y026BH&6zmFlm4;CtuCdul|AxV@*?C+M+qqN%l7VdLGi_D{$_@lEU zNk_n0>2zb?p+zRs;cnTYy#4;EeBb(TGFvbRITd%}VV+#e{V+mw{H*zUovUR@b)#wx zr&(J2~sZk;@%TMinLl zj@SS4+)m%0HVft1n2u2j{_m|?V1L{$?C_lyF^GzfuIIVpX}<8cfR5*q@f%#w1%^g=Hz{DOyd9S#EQm zc|dA%#4Ji=tMi2I1i|8SJ;>R^?r+AL;A}_K`rX7qtIk!@SkAK>#yHt>~!oyxhD+_$JM|j*Jhm!a@lh+|t%M zKo7u`xH+-W;};XY&NtsBtOV~AGH&8y6o^XME+nEmpAmrehJ>DlJa|nxw zx@*}XNq6G90M9LM=&O9GR&C@v>&NmoPVBXmYY0)c2xK zT6@DKSC1k|)R^Nz*FM1Ojvt~r3pqx8ms%D|TN>ASnX1@3Y)GJ|PEhwrlGXm#zAMkC z`}eKHV%}$st1^_pSmv`*4FUC20VG>u+t}dM$u-t*zMA2|d1mF17m!^uKIvUfSt-j8 zWV%qRFfTsAnt&!^K`=qSj;z`FgjQFs_q8`n)3+wf2Zjqe&?B&|7t#6Y!FV&(o7x-E z+rhimrxLQ&XT|3p0^s0*#pgU(Z8m5)!u&3=<|2e7j`@>tZfqQe+|hHc6iLInBM^{z z2Nh3rFZ;t`$LfG}P5i4ryMO9neH=#^@Fw)dW_ae;++7{97?1YGuAN0@oQyh%?-aQX zpO^<;21@rz*nkrrX$MCZ+ximiFKzrncaDt{oCzWXGRE&7ae_z;klgStu_YZaE*Zfd znFec*cI&a(?`cAKTsW_FsyPeoAh zjk{CABTYCy%~#|~M~NZkqM9tl#)Lv=GF9iPjwLB5HR3`&LaXap$uetMMIuls$rQ|Ce4(h%r1~RU(dZ5v%w$_K#(GxQ;k8fy_ zddgiN0ssxw_!;5|{GI0PnH>B)uRG3*lIB+w%vhe6akXLEW%~TCERQ8PM{N!j%q-L( zX!mFRr6zNi>uuy#RKbYAZ}u)Nm!<{X@wE@<1Yr|*lVy#zj_8tQ)6Wp|mfV|b2qteI z^8NE7W3!`o=dU@G;J>ef;s=QkgrCN(_{_c8AOS#Hxe>rWh*rAX_{0tQa7N7R%64&i z=ZI*FV#{ay$%R>s<(+DiQNiGWN$Hgg^eFFq$i`-D{0D%Ij^buTAR;T#jx@)xJ~uXj zlsvkkLX*+?GYjDblW1IJ7p0?Db+hjO*=&{AEf3eQMh0F!Ww98g!oUp442l!x=moG^ z1~#Z42`{0(m|h00zSP>xICq%aQjv)ZSwm$&N|mm14OTfKDbXf+)-A>yE`hI1L61Zr z*V15*pF)9P`_|w#Wg$AE(oXWKE{%v<6o{80jBEhfB`3H|QONphw7W1#@L%6x4>_SX z5g{)bAp&QA_ggvel?TW*Jb0A^+!*>7&;}I?@3Mj(B{zpo1ND4qyXx1ps+%u&$$2U^ zjxi^Y8FS#obO*PfXFK*KKbG2{t#ZZz1yeD|kUHgDJ4l;7{xO56;nvt{#cV}H`EB-T5Q3{@>O5*ee9^;mMg_N0?v_3OHprATptGY2aHu+K2pB|UqU*nZqR9&lIXU;v*b}j^K zmEpy^;lc(@+u`g$&q+Xd>s7#_Yn>npKspZkVSu$JRKDq*kD9|D_92FjYD?}Ry@Yc z+wPTaaW`9f>+Jfx%KKd+8Rn0doeE#SS)12WS%m9+USH_QDe$q$o(|1RfdmY^6EZHoFVkkm)hMY^$4EK3;bz^`3%zu@iI-B zRB3j_PIoA;|__^$+JOvQJu)6c83freTD)R!KaO*f@>0ig;W zh)3;-EosD9FRk*D366jrEwi$7K8aL|@JQK>fVKKJd@;XCLmUa!lZZnbBw_xd3cBT#d{`PM$HQ`7I5CGw(ua^GSj+QWP6 ztqhp{oYMaoje-H3@g2dwoxf8}xUH$oTgJw~pC1{aZB;keIZE2jH04`a)QBe~7(2)C zoMt*;>u0W8wpmHkbVU2*qgATTpIaz8HU^jN?%p3^!g;ooi*Hn@>fsfdx2+_Co;r%( z(ud2OWYgUUBX=Iolic3f!19^fChtQZ!WDlA=dsxA00gbn)ISx`I!n7QbjxgGbn4E7i!>WX3&7QuiGdpgd0PF`eAc8l|K6 z9ZTGTOInqhb!x*rbgD)pc-I=W3eDOUr0efP=R@os>p3wWnv3rTW4X3c3)g|7(`ODt zuIKy4`{l1S<*%$YY;PJeF*<%ble?1e54YAFz(*7s$~{I#%iJZzJ`)mGRFUxa$;b7$ z*fHbL^>rQ^o1@3HyuCHPW`^D1L*bDj!++_EIz3S4C$=9CXtH_R$~WlnIOp|xxZfCg z&F#`Hh-^&AsftssQU^0$s1Uv*%wv1K226~iJsVAcy)Ms*==d2^LwE+fGdP`db)PO}aAEG&lhO2Ed{C|ApTE-OZtmb{?d*~TynX_&*xAW?qQ!-r+H5s^T4(eN*5}S7q+`-mo+tc*WJpK|l-ivev!uEakl*hp0`%E)~ z{tc<|H`Z{`hDsYq?cx#}h__6G_!A{yE=q7YLju{%eHbJAJuTRyMgy4*E8`(NvBRF> z*b7chULFJbGa+~$LB{{`7x1rvegm^*X;~<*VnIia;q0BW{te=%xn)s^+MEodoiq9@ zThpLsz$k%ct@b4r;ns-G8j6O=QYR`uSXoy$z`+=AM4A~FmCWJNXsgyBIWfYyeQbg9xzuJSm$?|ix_Yr%((d<{X>0+tpK#v&3(t-)F>9A9v<+yQjkO>XF@U(y$Z|@s)n)iZQcx# z99;L>5PVrHJoEp_7u1XcIgiFTx)8l`kG$mhj#?>DlaTtp7vTqGI}R8f9DG7m$7~Z2 zi$az&tAMVs&i`wmbSZ2+hO#z%247y;ce4E}sFKNYDA&F_}*wW$g(`&=AK}bWYrj#5D zMHRBmQ8laW74C~qI>n;J?=(68EFy@aL6smsDQ$>gz#kv}8KC zS9Yj+hBM$UXh^s}#fZ31n7OSgIwGut;_BuL{%axI6WFrx_R0c!j5q3RC3GRbkWqSN z+2pIwd`~Lr&=%r#PumAT7dguA*9PD#`ZfEe%ge>VbM{6)3*K$2AiJdzPsPY0K|h2% zY*aZh0UjBkb75?e?7O4q%3K1M^}E`?UK{lMZ2d5C0mXjuZVB;j-kkAG%YcE4a zGo!8=u!}X{$@l~OTsKxasdT^m5uCu^VVsLCY$*ZF3S#>$LEu8?pxr{eo%ukp7p(2+ zad#)uA1p*G^~UZ}o}1jla~1TCI+YwfM_#+(%Lv*6IVA@>;H|qxm9*{4jIZ)4a|@7s z9Jf>ZLc7W2le^qOC7Tam?}#&eXLQ_ zi{O1@|NfuH1r^7A>p$sFpC~1tc3`oZUqG-6&OEkkv#?n>=B>ou{`%f;FDbL7U!xc5 z%U2Ku|*&=Mdvr_xQ6IxWq5h*A=_1y!Uk2?nT2dT0Y?SY>05xNpLrYkd* z=0D*hxRYcsU%z6Rc}UBt>Pz*-+53!{cG?~no;^viIed$o#q{5BJ^F()$OjhBvI$ZY z`K2TxC(hYh_6qiVBzO#o1e&#ebof$Ggo3)^ZeaR&2nSAA{46&^V85yRUsj@ zbxKT}6aL^OTbamOr%#pjU}*^e@v=B8djC06Eraci{Zg%_cLfTi{Hp12Bi)o^)LAx~ zGcC^z27eq+)BaFc*k-_^?kEvR{6<}*BoG=lXb^ad3L?!GQbHvamR%E5SvA4mIaoih zY`?;7b7e|mbOEy9dkO4_swNY-b>?~Y#!j3qG2R*z~n&h zpLP4d@$0R&@dfvHr}CN0ionTtdz|cZD|kD~_o9d*k84%mC@1L~H2-_)b`WgCK|Upb=a zGm!=_G~`dOE9%Tn$yS`zqL`;(hhGhTP%%`!MM#3;ls$O#QJIg6j`pXtD5Vi(3+q4f zV%WZ`Gej&?T|xr}LNE?}6E8S#1v&yjLGw`um=XBK`~Y z^?L$&s_z}584kVa7Hy04&QI#)#=5Rai!3IKo(yZ9r&i1JJMq&Cy)Kcz!#C<7vUSM7 zDCwiu!G9OLQDi-DYLo~#Ut3dUtGSZDX_${&w zl42vwh|kgXA#P`mmc!^|6z{O1GxxESkZk=)<-n)1yseAwjC9QjeQcvG>0*e_R~w~l zWXM>EA3+b;g)Yr%vk%957N3eUTWuPKei1=-{Mvd(5pz~N5RP{g=d?!kZ@a~jd%ZXO z*b`5kPZylcS0_@KHs07FsRZ0oygn;!E}{2hUJQ~m%qL!4NV&XE(uN!pHf*y=4Mk#` z)T&MM%Nyz0`LqxyBw!jXL4wNI!&HCulRWm*Z!80t)@tYMIZs;J7tJD-?+qqD?)W5s zMCLGOX6dvEYrkaYeyxhie7fL$^(*Z3=WGuTK(&P_i>J|t^rJ<++u?gj7327m_R2o0 zmgsx@^C~asOz3_cVJ9eyLf3eh+;sb79XmfqsMlub{^f9g;TPvdfA8_1^PNTRjmo{r z)#G!(W+ZIAF7#SwEoLu;JuT!fuaf5%*xp;G;-g#Yc+-#KV=#|IV+R z&$k$1kddbFCb#>mEz#aIp2Pd&=wYRm)Xo#wnI6=+87bI|*Z)#sYjw2H=fZ7l$J_&_ zsDuK_4*87vvro5=1lQg3BL&iCKkqK1Y{0j@G^xKAM|PyMd5s*yKiMNQ6aSOwj&Y8p zz<`#=$b$FWobi9Q(Th=*34>JW89k|qM>7SdJn33OZ$XBMRC0Dhzq(k8EfD-kZyEy< zoM>UG6QzUC$ZA^L)Z_W&uFto#te!9}Jm^=uvWOz6E0 zmn3l5lC+}iq(Uxp#I}$_+p!zlwv7f*xrMjvt?9=oc`?Ko_0c-7_a@eP&W!EQqn_Z! zy|dK)b-FP2rw$M~Cd2AYqBF+KA3{#RFvIK7rD_yW7)N59las*iqwWqZ)V+smcla1( zTCIk<0H3j}JE&QY%4h7(K(%iHue|QfSGi@KL%4w&vvo;yTIrq0%s?Ftv9fNou?!5d8 zaB`DQunSRHbaP(Qt-o@~>#XHCp3-XT+>R1%tzN3YzX;fM&CJ3x**1r!LW9(rd6lS1 z%toO#eq%HC2EK8u=uJLbumcylS8dMYnZB+q#qm-$>e`*p>>;mYHJtC}5fuX+)jaRv z7GCA{A@kH4XdVCH9PF%~R~&iPnSvMZqpzzvK`ulb3aik&Zb#4Fl~L*2Z>mBOyO(dK zn;L(WHZowibLQC7zJ#fxb(VU1LOq<5n>kEw{gyaL)b@yvJM0X>LW+K6ySZ1dnc+?zZPP$;3HR)(5UEHm#(mOnlU?B z5W?rxLVqn#Qufnu-T_W0^|U@5()6e}JboP@4bADow5D8hS_@Odqt)+|uips3fQ$7e zVG+7q>@&D~8Cj=yu3d_Lx}-hoyr_CidT=No^NMfmt0#|dtL7*D0T@C^X)OgdgRlVYr9vwA zuvCyZw4Y#X&cKG(f=Ne5ZR%LWtZdrq#&tTTGtUjS$CFo-3F>WhUfq{`s7v;x$oOZm zCrXJ&Nr7`^*F#vW7RmYlp$^-jJ*?N*uZO99@bdz4oB~KL=W^06=a<>t>LXcv{N9{U zLNqXf67W;N%?p>!+B4glrBj~QmG~Rv#P5@CJ;J&hW3=a#DtZ0X|8Ukx)6JD+2DOnJ z7Tq%rc?jI5;P-(j{2fI(>6;P)CO}JTd>R1tT!0%H=k%s7OQ~;Sm#n6hRV}n08{vqL>X?l3}T%f z!g>02|5o^q#2v$O5jtEthwM={BNgOOewLVFX6_g|y3Z@3YJRIH>f=BC7Dj8ks5wfy zv~g%6T9uyL=+ zBEvEGj93zl3fa4bI%!D_n?_49?AwEBgst)Y@Gsw+;huyeX(P=*} zMX~N{1{JcAh?AN1;EICL6aYhJ0+8>-oxM^Y+`RFvy99?*dlhs^$N@U#Rq0y#y!d}4 zu&UsLC-#&awQ`}qwV~qbdu!Wtot)s6_}*uDO;j66X68VVZYg9{d=uG8xm-jSK}uze zTyuC%*Wroo(6rqm#%E1#y8BN5$wuQ zGGyx*q}yrT?1B=m1V@)iH58!l1!79d!Ela6AtkB?b^`)6c|~HokIo*KXLPLX#JB$| z64h^-E>qBns)IL!}_23E6*35*1y^c?0l1#AQ6WPbwDOY7G~5JBU)J} zg~uHQo_qD5*c#6}j+2J&qp>m?jV!<3YwU~hPY0L8FxQWp{$NgG^Lr$OSt1v!Pysn0 zC{s5u>Yq2ATij>!&>uzC z4WJI8M3v|N+zr zX?nzzxot|Sp?!1HlBhNY_d6+I%cp;b&LV|`SLMt8ZZ(1gUFuO-KIo@H&Lzt{r)DYO z8_5XPw=MV{jrwCK_J;86VS9m7;9RU-Flfx@n$WI;T_uf)Ae=B$KIQP%9Z^JT$AJ5n zl5np0aS~d$yJCC^O;vzJslKp>7Sn->X_%@3BOfGHO9 zt-y^i*JQ@X?^X4S%?a-xw_8BhxE9inB+(BIj@@X#sm9vySiw4f7_GjQqV|rHH#W0R zzv{u&wC_toZ#R|5YY+=1gZ3%PB9go(!f|hNs5RK{7m;>j5&AcSFPHWE>TZ}f#hW4o4l~9iHD2-Su zSp-bEhulM_8M$UYSTs^}6nGt0Q|;eXB3UAawFrv=p{e;q6LM0I+*i^Lcp4hID0y&S z*|applptINA_0#m9B|mNxx;nT@}@iUAj|gieA)e6@SDhVi|HWrgv?MU$%ivJC5Ae5 zj}FBDjNI>en@}F=MRjh9=*`3uMG?tF6jx(rIqe|Okp^O{#$YVXOZ90;mY5y(CWK#aS12r8s0N*R)jJ6rM*U&CV4vORXi6@h5X|63TDcr-4Arr5fRh1LRQ465g`g zW|@9fnLCd8oQa^iVhIikmtAOw(HndR2TYBIo8)hbmK&VCs|h#_qjxxpqyca-aoQ8n zsPbYD1(-$Uz|U~h82O;Srn?7haiVR(EP}aNX+POeTu5vWxUiIz7Hg{^%F+l=1@zdT z45q&QTi|CDJY79KF&<=pGEh4NviR5B1e&YL*EWI)I}|<4tPr325nB;PY~qxk6x?xx(xP* zj-AXW;7iZCJCF1Dc`tiEM>fS54P)vC8^S896(kd@OoI{4NQVX__WM<<8#iRR3y}PL zJDM*!S$~i}O7yaOTjXrG2|J#`f@4CJP#1d&1`b=sGVDRJ2IBMhzQW4ePpXX1?tHP*M3%STF z(l_4vrc7%gbu2lz-?K&4TN_3)@pB*YM6UChPYZ~!eoh>{VpIGHjRQ-|m*fmzekvh> z2Ifv+vv#FL2tp05dd$4uIIq@8^1R5j4rG38G@%?ycw&AJ44h=9h=O=XlZfqq&1mi9 zjHJdF-kZcYM3HE)O4mEq%xqpF&@gsy>XG{xx3Th+Fey&ee4EBhAd$HFtnZs=s)&1T z_FGCUnv5g`wMa1Gq&*VbfRUH6LexLb7HG($dd4=WMh-==jNXaJ_0bhgf(pRax4JMu zNx~$pF=*E&cZd8AW;dbGB)cx6L~L8i<^EGdtw|D1;~Iort^aFCSVBLTkJFeFg?Rq9yp_z_jse&$i50HDTbK^GXkX$ ziWo7*@|o;S+2 zw)rd9Gr0B-zIjrhPaJjX=K6plx*OYxo>~U_`@Tz$@kh#^gz-V-l9v(Cjcz?p9>ng( z^>g@Yko`O2bOmN~^yY%dm(19N8fdUS)Jy+f4wdwY5DZT$4)({RiWe8?_A&o@T2>$I zsA|_27fhrZCLEhZc|W2mxpd4}?y7@OW`x7jN`=!{A^OR< zHqi#^hmOPZ9c}}c+PJ#aA%M}pYjYbFbUCTSN(PNKk6Xs1h(KwyM4exDWqB0%dc7ls zFukk?oyM}eO$@WIep^Ffq{pZnj9WdviQtFb|26Ocl9!d_Gh^T`k~m~Zr~_%qw1oe1 z#)Q6Q2m-T9-LS;7DdaR98ZEBXJjuwiR^l99E<(4cev}i)N@-El9)L??FYEWmj>#0L2bcxGA1?O+S+QD8=mFF}gCDT1IoI*G}-uC9rFJr*$oiJ1!)L&h-tp zVuOY;p+O^}Wg4>-0?_!-E%yio?GPh4l3B97XG3Pj56wAv`$x4$G=3*2mYZm_~8{!6no5sE#DW$1tD&*xM+q zj=o9;Zpg0zURfv_Ea}@|djk`aQ)Yj59wjV8EP#}eV>_w{)Q%Ry#aN9L!zIBj!&N8v zQMq!|8;=l7$(=YdKyG@0x`T@qS?}UGV(dFVnZ{IzKNbo%YjG9lWu( zg9^$qW*XW}6GyMF3^`h{Sf-kFlu##^J?-;43(Kc+Q#DYY=PhG5K~V0d0Dq4;J(?cK z9c-AHUwpv3R3uySHrXIFGXM{X1*36Og-2NAOo<+Bpt zW`XKntIg@uW8hrvSij_I_v%`Ajh-Nl{|i`Yp-H|2h6w`fB+XayblufjEC#;le-C3J zcj4%^a47k@AXTUKD&>m`v11$;GL%G`dcO-nCY_hWFqY(1*|SxXi@)?Jg%mtC9*m;U zK3$+xAE;;W9U{c(x+{j3ACnX3}TB_*+_)YR~f}{_>ap7MVBiIJA2J~a1zQudQG z;Qb4%*+tz~Ftp>&iF=D#cm%bdeP)4=Z-|5$?Hi(}44@9iRc~$X<_H1{q2cP6*2|Rv zc9LGul=vRF^26|!^IXM_>{ocr;VvN7oOF-elOGF#lM`ug>89=|8}YJmzpC`B2DTJK zD1Xs2hke~YoM0KXPS2&l@0|)3>Z?aq&o(plh{ewj%U(F%dP;Cr^L~Wu#xFUDs>j(G zT4Xll6OlBcHD~g{t+onwABWs9-WS9Ka>#HueqoRb$dsm>ZZMMPGpZrzcxmq=lz4S7 z#vuug|E#p?xX<5E4XPGcoAsZRGO|)A$r;TKl$H+T*hvc(j`-0$EpZsjz{<#R#@qN! z&i-#+@UNB{rHOrMadb#tsIpr2V|%^SkShUuiqxVsxe41w>xwU{BF$poXfr&B0d7T; z7KODT^J7EwM{}=pOCOeqB=D`rn9IW_hZW-@W2)hrzGdGe@BkdsYqGKtkFjQCvF1<4 zzvj=(5Fty)UMvwDg(Dfo%L7HF@?uWvk}0T+aRC;!R{;sTNLhUtX1;}32IDXXG)8+D z-jT&hc6@C%j3NU&V)#d-a~%z6Kqsakcu&lqJ$lFiglQ5tlu{Y-QMg6a!%d z+kDrUqndb}s{uKnoILs2LUTRoyP|MFFcDP$GV3T^G%@1xsKXM_OAw1tifC~x<~f7< zB!V;J=IFg*x^VaqnaMtnQ>LzuK*O!NBkJ>(5FE#%r1me5B*kh-!?@uGfJ?vKUbvA; zbO)ZIFe(Y=on{^j9XBXU8CBt=BP9*M`-iEYppRaTt|wVmVu+@&jCU9s`B@q?r#YEN zg-DZtF(4#PZC@VTJs3#FT#le^UxTG0&pud$lbd3&r&fd-n?3n9meHQkJIy+6ydxBm$vYd|y@)0XPgDb(a~HsxWI8+1DJ{>c z?yHMdwc%jT34R^;6W7r9(V~7WR*{LaZ<##}^4KU@PRGEWaeHnA8cc`-MIcK+-J5fb zIEUZ+lLXt!%vi7zN)jcbo{ZyoK)HB7Dqp?CnFAqV{X-U9^blh{hIFK-ldP7>R+`M( zrvvarGio6U(w4^6-TV;5eNna;gtC_stZNop?Z{GPa$tv+uG%I_UN&oq(?Wj*kHDMA zj~knYzmL59Hg?x{PBise61GJtEF~gTq&%FrglfAx4L}!dFx9ft#=DMbT3kJ z^_h4AI**HZ-_9v;Hbq%_Ukz5Bf*jPO`3NEzwu^>i1|nAkNF}oL(##=rm;JfWi?5`b zftm$ZWR29tjPRkQ?HWim@BMEUe(>k+N%JgQbos z(hFlF!cqMtrltK`|xiU4>*TSw2l|>_oda;hq(!hui zSW+g&_z%f@e3BV4s%x-o+cY>fh`yd~mmvN=zH@~AGZ?by98(SQiMnE( z&LFSfwFwgxvSYPSFB>bl&nwSck5E!n5BeF)#%Q(Igx4}C9z83I#a0%VwHLNmCjK*L ze(Hy)x>R!Gvir8`kQWPD2NybgyF#_I{G&)z$%6V1oiV%dxIR6@^LCV9NJ#UTABhK) z)#iO;i4pLtMXna00*6PegqhWld2)AbG>YpX{87#S7_5=7TwY%NqFiH05Sz1WThn3| zELm)T7{+2{zNFbiYA)ml4k4v<-YzmOCoK@#feaDaE6Jbj`Y}Y1s2a)~Oc^~peSC|v zfWTNfMUJ_HJZ7CVcLrYiXJe^d#X<@2&YiyOKS89}w?7O$XZc|F#z4_il|N}Qg4x{} zQo4g}Yi7^1I>O@NH49nI3)<;JhvnG?*O;5YDxOl(P(yQ2p24$@pA3s7vj0xaOc9J( zpO5E-tcpe0d^_Ym7Qfn{h_EGh5F|Q+LyX4e-lHM0!e%v)FwuCfiV;W{7DNIRg}X4I z$vBwt)JR>-;dpvO`_+jyYp+u&c%Se9THStH(lfa)eHh~9gU(?byI->MhO1Y|_Agc9 z4$zOf)w6ML#Im~=q#G9439CaG8H3ip3<}Ci-TdM8OXkJZ z(`17s{Y|?6yRkVXRkdm!)qoDTK{t@OHxKU?i?FBAil(j!K{ZJIp=|HSWo2-kFa5=m zgzE%{e=erw>5x3KmmEHHdCa)u-9FSr1$+3%f^CDi)1eV`!K@LgXV;Wj-k{&TI6gpG0Ft)uH1a14j{3Um`5kj+#ZbSU!L3 zCGh8Rn2lV#_EN6O9U~vCkg`UIz{2xYO7$9jrATr(Qu zVfsu2dyEJN%kl+Q=`3M~amva6%@&+#xL+$%Bq7cxf}94k$Cv`BWy?HW$b47bCV zr~nq9dmnM(skDA+^;V}IRlj;#PbNL1hbO)qnY)Fyn{Cqgw6d@*c zLq3 zgfz%*a&YS&$K#D_5LdFWQ|2JqU`@T`{tiYtwYlKUcC+m3$S$o*M-Fk~A+upuI(7E< zg0bX{73PM*MJpcjH>NCu45%jD@r*_6jUycr9q{r`#(>ZU8tAEyAkni&IJMk>SRT>Kl^MBt0jC5G8vlWcTJ8)oM@kZelM$Pf zCY6^)UPCFfaS!5oX1iZ(qq8fMnIfqF^euHecnk5nOk&5BvVUTx)VDl~EjVFgsLrKd zI?xzwMCE3Du;fJj8D^!h(_s9`emY$fuc-X)t0SP4yel*3U|SH-imwefqF!3VjAV@1 zV0~(L$Kg57=^p6S*%$fkto5Ae&g=FQ>>Yhg(_)l9T|0BLs8a3HAg*9>Gy5+zIO(oG zXt@2zJo5+xBuCZq_qb2(F|`wP#ZQ5-gr?YEcB(%(PIM*87ygB}!}^ncpmOG$sh)HB<{F9rU{_LL-)fc00Recbj3H?CpZVU_DGqy!tv$< zm1{?*4bc_&vqUX#GeKa;>uai0oyDj#^^&}MNQBzx-(gM);_nsk6tOK|yXM(8=ECd2 z?)Oa+vK#N?tu(}^)wd6xXhzoTn;!k;apvptygxHJe??*B<0E;{{KtOShoR4~{c--4 zMR7$&TVmCVfR6h`8`2S*h`1ZGnM#*2BJAH5KV!}jhudpR`3lXvFG^qma;e+dsvB8Y zxPX_I*8OcEm{09AZB((OROg02#W#l@BY@P@qOt#1ANb>T5KA#*V2O#iH1Y_g8#4ah z;$etTTY}-+#c#^yOk7AR3A0iuUsk|9KsL0(aKENZEorf+oaF(PVSu1+3X$CeUalB) zm*1yfbV<3gU}Z)*g0KMdJs?!Duf=RIHFNAUK$VfT|Wb@D18OLVP-)f83j z9&tmgVo8z(C#V(n080C6!f=01U$-!dhA{zl;FG4=0g9WV60)=9QC$fqgf&mhU@}#; zmGSQo({YaW~ojbg${F zp%(StBty2DJ>de&&u_-Y)M*Z`)fhzL!-v0EOq@pKe``ESIkYU2Mgx@A+$y^0XxUY( zJ5MxjvZ|VC7`25V((^KP)0$G8j3x$F6=+z3{&5MjTOs}q5!xJGz*kZSu<6te0s4cy zKWqxf@$cK`00)eQzgy;bb+P2qrV#s@cRjKkW>LYYIfJ+hWbmP<#wIm#(RdA5Mq?S7 z;ox8j{$V|DKedsi{oCYpCdK%C3fi6J>n=!Q0uS40SOWGgA4oy-a}W#rLSY?`rksA6 z#&iyz+JaE&-Vi1h@UbhHX8uCt#ta=3SQdawsxMzslT|Dj@xZ_X<=h7$bzG4piACP* zT8C|7E|)X|a`viWg8-wNGbm?Y(FAsFyF}+jHz#vQs9a6<2sR@(@3LD~^(ED?dC(A& zCZV`WNCAqJA@@6U)np}Zmq412pEY?SLu1;~{KT~NyGPCEdvQg4#MCPe& z|N3%g+4MPpV?3fy!YB=vSPhvd*%3rrpI%l%w z$NAcpt15X3w7Tj|2uDkMURKEQufYOD$O>^7{qGa&Kq|Aila{Mjr^8wM`6DWbwX3SO%WwQF@uj*omv~I=myoJ0zqlPicO7q4s@g=3wB~&#WJ|uy7;GVS&_xp_8 z{^kjuC=x^{IEWA^->;+mLdFj_FK-hUgg?xr;G(Crunc%T_0~B3>1IoI6i=lRV1N=KYxB$5=f;zT1qGb8#ZQnGm3+h-*fo)LjR~W`Qic|=m zf%;*Av*o)O^k(<1c)**EJ%ae@SHL_0-TLvDx1j4}Lql1gd2nY)f&o zgFxQQiC33J+dqinfnw;hwExf@)&6os+lP$8qz;*p>`ONhsncIRQBVO&+QBxTUXK~g zfCre#_d5Ki((oEu2{nY&FRPga9g*RTRbnSu;RCs)7t=cNdPqNiOeGf9~5#>`O+F6mm)aY0D2F&S$+F<%vf z2Uj^D^-8h4?iZ}vYVoQO=<95$lf}`L^uDCU(;w12P7nQtOSLj~-#Mua(2QHg1sv6@ zo(D!E&mJy%HO|gulMn?7mLgP;jL;QO-xvk z&v<&Hk0{)^@Zzs*&XEtx?0Av0`7w%= zu336CBT@{@->j_bYR|Zazs~hVA=WEv8YtPNMKon!tk{VHf!E~I44(0O|Ltn5%5^^(kXH|Db9Tj#vP1UrOB;&7hqJ|vYh z3yXWt*3QJY(SfjHrT?yq!zu?=4|9EjcOJnFIF0-JxWWoxUrWfq4<~ zJX{HpERz>oFPmJtmeEf=I1^$=p?O;2;_Bk#-pF$+V#UOPMaBi4Eb5D7^&&@V{||CNjlbxKbuyeV&!)l~@c;lI07*naR5O+uB01dJH1xwFP=-R9 zB35-M1N+U6<9uXU&vID@+_7Izs$HM%9H#?It$nl)i_gKn&l`Rs%Fj+mo|!RfB8yUT zq2z)h%(irfemKajbgR|aW(9wJ){qycv;6(+JKnm^-Ni{LyVls+g5ea5oj00SCQlqC zb1#WIN!*Dtt5W&nM)Y5W#!Qm4**W`1N*)?ZYqZ&7n(^$87a!eoJk1D+-S(Q@xF_e* zvE07od*9vcQbskCG*j!${p|^nnIZ3b;qeKb`kQVP^G(t4=5*)36>@*@+Xe6M|5`5K zyvm3W?fYIi1G=;BzvTS2^Kqv3xk%_;kbJ?<&u2Azu{oIB`DPoj9M$Zsn-ho{E_c-s_;{|aSOq2%9 z!0f{0uyuG#5?6Voxu1W@O4f`ZzsFwNks!L^sKoesZeinEGAv6xX6gT1J7*+JU+z!$ z;VrL%Sb#VPb6ZF`lT)HvOfbyCASSx17>$B(oKO6xq>OnRU48eQUtgwXEmj^9qj!}O zCOW-}h@vD`16gvvIK%7R+&_Mu_ltRhb8VF^h6^|?Oi?iQUa5annkP=893*k;nHQS4 zCozkDs`30+W6J7iHa1tz=1MS`nXA&8arffD-HRi4cN49`X4tdcTruPkO~Id7JK*1* za(y}Op`p6Sq*O55;GLwoe!LdZtKY<)e!ZWwKem27Cu{M_9=CUV+Pl95BoUGjdQke; zDGt>nVZs%Rd?-_K^KQ@;2WqqM@~#fmoW)^rXR-L6{f_Sbb$Y#C{Wr@b2+B}; za+$$ybH(-cnt7SHJv^u6%y!%{&l9`N4%Nam&5)Jq@Saynaz-=Wk;XfHXRhL;uAfeF z>Bd(>v?!F;`=gi&hIWt^5{mYJpBj0oUdf)o$41{n<4d-F1#e zmFUoCuiSrG=7l7lN#;%x2T|IZ%l=gxv9D(MD&(XzPNeNj-e>Z#rB-7)p16N`;@Jl; zIi6-p-g3RaVLR^5Qo&CG?LU0Q<$to%FRq)9zd~PVO55*q`}tGe);F$iuh(Pvtgp%M z>b#|QbxG)-5)NPjMTM*|2ozCDf-FMO_)JOq--&-u)i@Ayck)USzxy18*vV4n7eY(3 z@Z?^aQ{9-FbF7WS;@mgm*x+E!;jg9f!#45AqZ@a?dp4z?C2exf4Ue@(5Ya-d zBVB*07H)D%gqz*Cux~TJn!qe#NJF!pLdRVjNrWMd5s!+~+CoCk4s7C~Z8vYE)FWG4 zc)Jf}U>Jr-db3DFt6i(EA}q}?dZ5ZW0p zGtDZ#O4UNFcP8kyZuuHJ_tl!#KK35T0#|=7Y+S+wMb_y^CmgyXw7yz07L*y|F^zXT zaYyC3XP!ysnI`U0mVW`CS&3MiA z_7R)1`IA)N|B|cSp91jn7u{KYk^9*2rB%|HInF1J z^MRy^Q8%b$j`NX|z%RxfFGcugTljwwiGS-0e`%E`?qpfV>OFY6%h|kxxcUR27aokq zImfJS4X#?_c(}!qFys_0aqD2FL11(DF1cG1&E(83cNc040BwCgKh@YnH)||)rn#Xh zA+F3mhoc;qvn=&)7!}OIJ0BNpo>+9DPeht%SC@Va7k%7 zclUzCbJR_BF0Z8^?m#0;V%MDF^lMs3;uM0oSUlDs87Fznk{XT4m5IiY#M@NvNIbX9 zhh#pG#4U+gF5vz;oPWRfXCASqt(-V{Wy~9L+Tx4z(Tk7x&3hkkdv_#h;cEAYtL-&8 zmGfHdPsMKkv`%-Q74Y*{9h85*@UhMtayzf!0kgC?l?ai2K z<+M~zHFK=SU2WXXjTejY;naAx81K)<3yU4Ge1U-e$#$%cArzdq8l-=v@l&6u!v@?L z^2n(kaB;?A%d%9==YU%ek8;U^N@J5VSGy~kJ3m<_ezpkzwr6yGp1z%@0PI=hAlYc?f_;U zCN>d!I#ZWQ*3|dpon?Ps8$-%$%1E__^*nXyUB3XBpjlbw<$Uov&QKz{76}4hvliEN z>V0ntpK!-;^GJm2z$ApP{2J$xBpA@m8`kA+o&M2*T^UiX+$kbapb8X;_rQQtTo^d9%>nA8rs&930>qOrXmsdfN|cl+S)w!PBYIs&?ny`; zbWCw{_k6Pm~&eFT`i&xqjsoKZy z>*#%5iMWu(c{J?!)-dqQCt6)lU&0ez`w(A*?Xc~dbq9&DcbK&hp6edBAgbrFdr5`4 z&S3@HjcmrU2@@M)oc=HYZk^)L3y*NIi{!QY(>*u4Yrg&T+f4Pui`$oBe4?pK*1Y?< z2gx9%6w`kQ!X~!)C7~GR|KKt!bY6ETkp{0+D{UOJ_CKaCC=zkz^xs8 zB8pfuXL94-ja!TtR36iKo65T+-uKLJC_E#GcJdj){qsJDw37=hO<0+c1Y_BvD5u*a z&py26?(Rr)XTQ1TX8(k7*nH)h&Oc;qpZSV?yorByg`adAy0WfcQ&*_ZdK>*dmX=*lsYMH-H-S5D-}9lD)yCW z9rNk~rmH>J+Xs1W4QN<*ydDPKxJU9*EkezLRb_6OsTsGk@p4{xq{5?=cr-6u=f>4! z{BnOXp7%IL`GQ|d?>M9wd*EAQe4om9wDMFMSKfFo&Tp0zFRVdZVw{^YwY6|JgYy)_ zBAbd$-s0An<|8?en1wEUx7l)9W`5k9pR4fqB>r1*{s){t^WZSF2RruOdtO!)U9YXH z=Q^-2$}lAAp<%U#-?_$odZ~?^GO8)Y+Gl?oRUvEXzUnb;DG9dYmaK*2;lyc~z@2Ip z=?n9vE=7ZZafnl*5;6C(Xc|;l17(DnVxxWXM7+Y`5xH980mA8Kk zp3`{YnU^R}S@;$Uzwv?hC_IzI^1yybzVLIXPum7zkpq<@DM=Jzi}C!~3tm3I4;?qk z&F&F5`zPnM$eS=Veih*JR~2mEl)~W?Z_EGqEzj!+=n2?%Aiq+$%EDDvc1hV~VXMln z1fXxSvdJCL@i>^0ut{P1QBpdO)B}IS713Z=M;F$iLN401XuQL9%n|Ug+oUIOtvzBw zapfZN5kM{^Cl`s}j9xGdC4NuI!lpVqHLew|fopAC3G7taYhxpgpPd>XS&X5-sMlsK zruH~bXuKjkjp$Xc)EeZpd6@v%4tsxw5-jq= z@eZ4eai}CsJlb8ev_`E4`r#R!w|K~zG{wJj z15rmU#3mxZ@z+|by#QM{3;Br&QRS0eniG=8PRhZ4Ktp%iWpN2d8i^B8LnDbqYM#Z?o> zdO|I3_iA@T(i~wiG?FGtDGWYxT2B0Jo%jufpETpYPr`RQs7HSyS`<;KgS_+*mQ~Nb zH6u?G<`o@>h+f4hz4$USYKy4UShEZlsglQ(A?3v5M~^8b^PBg7O|5e`9Er)!+BLh% zZy6E@;TY#;EX_XdP;{xu!{hnJDQ;L;uLtYK>xCf@h#g7x5b z_Y3fYkRA3duC0IEpSLVR5g0YNCmV_J`v(+>*b9GLD_p5?JqTAhvCE0wpzKR# z+ehu&l-Oov%+k9H7!=lCKqWep2`F9hb{|`J!F7_|q<}gy_Y&D=60;&>=c> zpgFw@H`ID3sR>bKMW61_c^S)R@7=vqTa5mPZaR_@48_l~J5>W3?bP_N+2?B8`6{3% zoIS=ngh_wQBN`hT#aj5PdkexDP%Xx>-?qwsHE#HuT(~>jF)tIx`9QOZIE=%VoJ-_F z*M&MCFmtZL2EMt`f?$&QJVGDd&jtK(s9D`A|Ys_`0Xbl%$a?_g1_ zou!!lXZ?DLxJ*A^>)x-0k}_^_8`t|A#yrGM-u-MIl9P7PTKqSCTra9<_dp1#rBclT zp!z;NsRqv5I#n`8U}r{I-RV|&rznFcg9fp1kXUzR^bG##e9?H9ZYt^_+jH@d{8?jY zjjew*ZmjVfxy-$8}PUbpm4CpEQL}x`xS6ZL3nDuK$><;s0)K+}^#! z47>$+WzB4dZH(TJchpu<31VAL!9ss;4Qh`|m31870XK`X+wKsf^A94ky_AvcnbSNW z_<5hcve>N`4&HO@SN5H;%KcVAdLR#0KS#a}20Me|L5>UOzTle_Rf^I(bk2SbsjCYf zg0EvF38jZ>FO*4WYp66*TNtS9ta44`ip0K8eBSoPFBtd*ndjv5zWt9qnpS_mh}IfS zW+X32a<2D}QBj_M^o*Au-f_GS8KM&r!PmPd-0UBp6Z<}o_td94zrTcnAiqff_;oBA zUZ>~Id&NHjR{}Q)Zjx|aVqd;bF=pQn$~I^ALt-}+wk5I2i7_iBuWoLu_BQr=@wJ{0 z&H#DCn|HEWfI8hl?DA%k-jRR%WhK5^jP*N9h+^D#m;%7)pU|Im!<*4S#|2YPV|437c{S32EI+{1C)lLG8o%@hSmO5h|9_#D1bLOx5<(eDHh>CEk zN17RVPVBZ@Zmu3hJZyhmq61IqOaKJ$CN_SKv-J-2c)gToeQIE4=sIx{Lp8Ipn1RNjF$)=biai`MFy!&qR>kZUi1Bc$9?eEL@f7%J*5jG%c|kGTV~b zbTBVjy9tbR(~zECHL877J*xfC0%#RQ;9FBC3DAsUosq?_gxNvJ#2 z#;n4I1C&P zN0t_Lu-=?QJ4S(EhDdnGuNwDe-M`>t%V3dk)ij~zD6*m+O7BLI8Nrq8c@7KAK{CXFPx2bl(( zT@)pzG3V)%TqX-5h$&(VnaW^|tvh=vI|@6DYm7(U_$dP)Ne(W-X8?2;W7Y|g1s!43 zf=Z@N3(uZ?#Qp6=Yu{@X_uG<7@G@j55gq8b=lDh=GHAY>t&jbbM|hP z2XR`fOsJ0&17IU-`qClwP?i?vBiww+}$Gp~4yQ)O7(mHA2-Kp~LJoBH@!Y}V`nXHDiY_ki#fMyn(ah$o$ zW14;<$M)s3+XY=?i5V-xYqaHpiWc>tv-;zr7ek_w`FE*Qr$;_eaRvU;t{!{>NSNsG=o_4PscxW}_O zbg9(c;qF0!)i_Q^-v8)BcDpdeX>`rIT6eu`ea#aqfL2@ga@S4(v{%aL3&^HEb=rTl z%IIOLR75Bmu8CPLgt#^TKqZRkHQIGG%UQqH%UBCHK~hXaq))9>6>V{ih$zx3YL&qj zwp6whMvN_uof|)~kq;zudJr@F`>x}hGpfqGOqk5bVC38)#6%LfbANZwi)S%z_kJoQS8cRE3($Y(HyO;o8MS}@xAkggey#9W;Yk)A4a#*=_C?rd ziM@GA>`P|IsgIqb`_;})cQ?WY+b=A1?E}eXV0L!fa(Ap%tSw++3A)}Xk%yH%=OUn) z;a2h9g{73qWkA!KXRWlwu`1nLyU}XHmP*P2Kq)DjbCBnRa1Tqplj+^LyG4KShZ$ZS zYV2suTkHc<0QnmCDSbbmMR=lcbm!Kb@6DOtOqJs?oW%4q0QxnJ?^5|b3vWy1iBuj* zWiJtXy3!6z9)LNqORp}>nz6J)($G6&$J>H06K^k#zw!l2$pQz7NkK6?11CMl>n+hXW^@IGs-C19dZO(3ChF@2OUM zVps31Rq@lIZ*L4l$f-~Xxt>{=-&Cu?u}jKs+_D*VSZz$F1(oQ41*3mSqxup6Z6S?Q z(b&}^!4L3?pA{TEu%>tOMUi4D7zwO(%YC5Lrz^wyAoca^YGSpHqmP{FK19~&&cp1bfaWu&PDz;Okja0{4O$q=cvie*1{IV< z>Z3oAU@pf*woeeuV!v;!&NML*NW^*}r2uw)Xs#k$N#bb-^>??0?@S9H&5f7MKNX-W z&J&D(#mx6*;T>tbrIn{zxxy}iDm|0CNf6_zz~T{Yy7UA!*EndaW?ITvO)*|?##4iT zYs$V9{>d9JPxpU}DUl_iDSY64wUQA*C1bYWZk*}~6R_sg7Grx6r&^=U75B=RN3O>` zziJEr>wH9V;lCjySqmZkYb%FiHCoXWyW&(r4dF&kL&U~fC83luU}h|JW}25?Xh;CX z-E*2*CovXUwKK5R{xMgt0pnVPp^x2HK+kK3E<~73@9cH$(7U?h z49v2=qu~7Gb)uygCq-F(`&X_Bj-;5LB`SkCI}g*PXPVi!i5qXct-?=p<~@W{Z5Jkg zf!Zc!nVElE+_yz08VgGk1}og%o_P7}o|i8U)TK`@#BmE}!^c-|alO4Jt&yp3z{e-@ zn109O%-=+Kel;G;mpNuX6X1Gh{v-vMKg!Z|=5UpBkl_YlQxap2@t>v`udfF~SX%b6 zWGA+*2cL9?yKpgo@s7Fy)P`A&j(8ox`)VR0XNP|`vq;5q4~Z*UDqoaiKbe)nL) z4Z>RnZ&%~pZQ;FR<^I(8L(Znw_vi0Y`3n}luM6MO%D1KRmNs@>4}Yc~tX(>=Xmsgw zC!v4Eh_<5bz-$wXBo-1&Kjd4VGF&zI;ndh<;r~_TxiuDB7;Na%m&SJ3aGDp!GGdmP zmMDHIGe{V(hy-KaamKPavz)6nraJK}f&T+&t@0y{f&S7b3$;I>k`lSQx~-ESYmKEY zoa_`#_?0=`wd+d_@O^ys7*z?w7k8Azyv%={v(d$nJ%$#KVls@3IR6>0a*^3?asl6~ z?KQP6%*%wJY|0}jS!yQwd`gPR(=vSGY^!<~B1KlWz zJ&7XSc;>u2=S-5zs-(5B#xF9xuE}4^>Tpo(62DGrS!K2T%8pf(JL$}sh}UESW`uu} zI43H{q|7OCS{Cjx>S$=1aD$l{r-k>r7>iE9ymw`*J9gVWX%T!e4lnL`@$A6;Vd|a{ z^vGRjQ?@+5ddhx#6+8}qbBtyF(2@No?$p2OoWEY(`M-2Kt6|Kw!qY4~UBSEv*C{&l zZ5FOdItQ$jyxOo{(y*HM5&CL*>#=_`rvu_TzB?Z_y?5}{kJX)4BNW4GfHr3W6&=(a z+R9Fj4oV7mPRNkSId*bF0_zeqiygZbr8Q8mSX=o5Le@;tLP@3PZU@V{H%fi<7e*=T z_q<&m14+)KcS)Uz-!I$vGRYxY}~is z?NM;vRTI*|@3Zh<$inxu@~$qttBt49*vVyo&MSL#^RUpZzUI!$#X0Xx_L56609d!` z6JTTT=L_s|;m67OpeT|GbvcCFF2sM8tR1#Q=A`z%dWm=|Ky>y1VSXjM6B(YD4eX0!2x|HogkPClc@0xV)cCh{W zIqz^+VG$wbRC*wmhzj5I=De<8dK2mtz8V3>XRC$p`rZiA7 z=5~)sVo3`^!!-k;G}&#hBR`(VWN6F4%a<>C`TWQ{2ge}*J?_|U*z@@MDZ9=7Y#{Y@ z`}mVO%6+pde{&w&+MR#z1Rf`Nt0+$f<#Cp;AOX1r>8vglYrYD15sk3%yl zVLGpfg--ltOuR$kgT?vwcHtLy3x^&UBEM(kUU2@Lg};)8@1~h=Yva4J@Rk_Esw8`r zZ_r=c?rz)3QXR`ZVr*I((XxZQfmEP%|Mz7ETfl|ZeZ#*~ogK>0O5r_$TaV`sfiV}L zv2{S%q7wT2-FDaS*Gz4d+7@yul(EpLOiS$AH)Vh9W;3k^<`l*>#{Rwxc#WbW z31m$q9T>~N)za8M0Q2*w2zfQ&>F;b=yYUAFqI9Le86Y0~f20=1HBy0>=6v9dUwGr^ zlK8PCer5~LwD4RK$K+HA1%=957<%^%2o=GYGRaro03^+rJ0)etvf=LbmY4S@ZeJd` zzdg`wEuep*XkLSZZm!l~md_4?ubzdkcD}zayZv>W2z)M%a&L0C{H8M5{}3=2!pikV z;b{&)e>@~^vT{=*Xl0*-ZBd4vl%~4IcXl>*~0y^Z4}u=%-`K~TJ>TKtSJO$*zI_06A>G>d#P#>sL%MEOw zAj5x#L}FV8cAG7p5{JVbcOU)+KZQ&yfLFOO<%g4Tot%GE<<6ZU4UEHUo(q@5}H?{UJ>o$D(mGwa0tL89#|X^HV1o!oiP8~^OiKbi55b>@HP zZafp^nBdTiV_l+yUvul%KpH|Bk_4qjNCJ?*iCQbi4e0)5$+D_x#fo0$=1u{sz#$UV#3I7lgpI z#Hc;MTzFiR>zugG5+t~!j45_>nj(Ly)Vfyu;_7xu!CJ{Rz8Z9_|7{k`@m6u#nPlec z&QhYfPf0IHSiN`fp1LOf&;g`Z0!3j+kQFNhGzO9G2_qqzW7H@?Y&-8+=Y_h&h&G9$ zc_8N@$Z`5`G~Eeu*2|dY7eIHrfaN*A+exOe|MZIq4(qfc+GSEwu9Ne2gLi*6g?Glp zdm?<~zuln^IDf{%k68GDE*}H*HJoF8N`#LGZLCk1_RU5*gS|o8uv|T1vwITqs9}I{ zq)MWx!dy5?!bB(%bhz5PyusmnO&GQCpR@CUExbIQz#1iuY|7ZPs{`z&<;2oE)*vnR z{BbSJRj8{3P77lmNt=OR>B4_6s&Lz8j?08=*PkcBJqVeCP*TD@z&k=u!U)wmyL@#b zT;_;v?dd-e$K59=)#`bqpFCd6W{uQ+$6c(u#RU^S;#y<6Ali!rhvR%=t~1yBYo6S^ zbq->2oVrZ?amR|HbuK_oDNK#TkR;e_9H$fe?T+oZrPd{geYub%itT@=`wfqpurWui zfwex#>V;7UYkN4n>ENUEupABM{hb-V_QpTA#@}1z?^@%Rnm8aFyLLaJXqRy&1QDb3 z*SEHXq@~}Q^=U^uUpW_&2%GJWlrx9ZJxWXK&T~X!Ht&q$p);v7BI$p@R?%?_Nz!VBbDl!1 zWB+q*H5umzH2$^D{8?J~ zj#R!QzYXZ}>JI+5zP@;=2QxnM(e~EZ;z-V1KY5Eb47~T=FS)yWK|LKv(_OsQdA*TX zaJFs?^DP&yn(}|kWc=70bqF9j9`Cq6-6InF?OH>UFeSP7x#{0&{H~ z-9Qs_Qx>lzSF8ooeKYifzN-#YHDr>#(43ZutQk#-Ru`IArujsz^(+%>ZXA~rDk&sz zX3TA2vN;M!iTpIPidpR3hdh8Qhv|;f>2wYXl8{yO0=9o~Iv#l`FM6iC#e_!k*#xLr z1m3jPLdMpMzS^6I@wpVO6+u&z>iJkE0 zG7fi`7E=QO&6!e4C&lTdJNL62`Pt0IY-R6X zdg2xEtp(FR|41L*|_^^Q2@Rm&E(0Mpef|I-pnnjZXYP zEAM|wWT4+jNV~M(4S8i}`ujfg%%A8+I}UpP5msl~u;YF?v52tTzkt(3sS7(QmV^bN z;?y;(9;kgxx;6L<7p~LD&ysR$VV|;&wilmJjnT4b_!p>VYF(Ip27w_L#xj5ib8Xl% zN5?H1ajFk=;i`s^yG*Ow_*(e*OD@cFbi{uo=`L;YxW}?#9H#KJXRY-bRT|WlL}ur- zHFGEDfszYt9kDlKx7ks0;raawT5B=(C+?s2Dyz1JwU|OlpFo+%d#1Gj?`_$}{p-b{ ziuTo1W9Yy0w47+IvKcoF)o5-^3b!h3)Y*uI2L7Bz06|6UyL3Mb*f`PnwG02~jsJf* zFZ`WVe(uIh=+QN0c6nr%3PT$SB9ig*zc~m+Fi35HXn1``>GS-e#`&k za|HSPbqBq#^E4ow$3mj^)*!q!CLVteiAN=KHD2<~$L>lMU1~dLyswdw*1Ar+kJzRA zNSnu)GN#hOGWHshw3XPllC1q9Be##yb56)mqGN7Bv_rb2s2k2Cjrh!QObkOIvn2Jt9DMy8is*V3MH2dDMkd>6y0q9y$?OW*QYvoe@=h1iun@x z+3RuI9qvRG$>|L4Yq}h*p%^=Xw>E{Ro6OB1T#Ivb!zA&&-l6|ME8o_IZ)@dRg7N%m z0DV2w*TggHz>^U0g*rW_&bKVL%G~wOZec$t3f7>DM30z)zbC+Lmp##&^!HhZpk zdB)1XG$v+iq!tsi+ON0eEOCo*^$gsl#CzWO`+4GTz43E_xv$2uWX5$Bk_y|+hM~Ld zrG8&aj(zyboR4W0A&6{7PEIa`{dPpJHkc`mLi@;g@8>_`_QioZHNrSAJp7+1d@I3Q zrQqW=A8c=!%Z8--##{Tdq}#j5)Zp!+JRTE|#>~x-xGsr(36q(u zK~b^3FJ3KM=`8jY(CxfG*FGBKfgU$p*Q_oV9ry!RSAV$Q(NiE+V#i1>rQ`~7>3L+Z2E3DwCkF3 z#H~JfPUQ^dYyPUAgJ#S_4}ES2JD`iNAlj4LrQ6SXbnBse7c{}+G4u9z;L(`4Nyf3l zwL3r3nIFi)JF@VuRvu#v4*>jk0s5;XC_x^0%dh$5Jr(U7Z5pq85+ftbC`mMcTq37? z?nWmCVRoppcJF^s-Kip|!&8(Ww&*&i-JaG#(}8I^F^RC$Id<1%Hrp*j9?&ctP6t|B zf{fUk@TJY+*M{2Qz{1&xrPc7LUzG)Jl%apH+wBrI-S{dp<;CMEtM2|p1y;Rs)kkIy3j zCV$;J*f$-}Kk2qsN4O^m-Y&w^-kskJiR&Q@WVR(SNQ~OOg^`F`jMu%7BF|25tpj`C zm9G`Gw-`%CC*Mcg*3MC<9|xONE(Dq-y7RFxltO=zL~=nbWJD?TylYi*&I~0nl*}*` zawqM%Ipp5WyVDG6gH{Qa`qJ>)-QV00i=lBTnPD7*w3K7_s@>CkHRGV~A6?~~szukx zySFeDd62Ii!53YsXBLa})wGv80}0}Vj`jx0RJ zC~|)R<5z)Pe#d0SU;SEms7}X-F~0QfI}z;a5CTRqxF8G?9r`S=5ZT;I?*^CtcM?P( zjKkY9uu;oc&pHk6raT4U!)264J2n z_;)un6^1;pbOPNp&&MlD!tXWqnIPce0na7zn4x-#Uroe=T|g-xg0r3ci?kp?0gaHPI%+E;VLEEjB$UA z;GM(q(3Jq*z3(OLn$t*5Lam|jP@yN^#oC~@1+#eXl#;o*y5{EkFZsc@p7Pd?)7=ND;Y5=HrXetcT~K>j*{?AHy@&pz3Gcm6cP+gW)! zCLV19(672r`$mP5*B!WZpY^^kZ|#4~Xg`nN&1toFYdEN3th zmtdo3C6!DbG9@Pl5lW9;RquuyC3PuJ2@o!clGE9ORRCRg*IfeNR>Dwgw54J5O3pLH zTL<(w%r-;lnpaSll+Nwzs=b!g^Swu4#)_fE&a{6W79_+Gy>@)6h&8lDY%71YcDa^5 z0O9BWOA?-L3vcZP-Y&vsn)rdjV{N=c<*{CL=nqM8zpGpKj{*9F?Z3#y2J~#)ad8z} z)6h)lsbBGDCBS@jDw`$r^0Nyw!LSY;yqrP3dUW(USLQbHb5$zNcGyK{yUd^w$blP@ z(>W-mS)*Eu(3lj?YDtum%K3k~k2p{{%f;5%(xol|M*W&7sr0`Wg=xu|TEmNAsS8Hu zL1-eSaGDD_T*iE1sgV#ax&nN6lH=kpzZrL!Ra#rXJBuA-o=-e`{*3+AKKAylo8I)i zbt5KQ>+x+gR1zhJ^PZU@qLhA}*Sc^#oj~C~i=!BmJEJ$=r}9AxJ^6n#ZyaOZM#HiH zpS?Hxu_Vv#`#$HlM8v(h*48x(XCWz)l0jLP{oof1uw@9gVZnc-0YB-Tdhv^8c!2=R zh9y9xhQnDnGu_i&TV~!RB7U15&WX4;tE-1Yi4wb;Q;kGcWmje1ycsvn@0|1fe!ec! z+iNO@jz(SC_Q3}(hb@0YzhRyx(xmBobDHtqGxP(X&l^-~o#|sl`ktJ@NzunBp5S#N zvmS1}zK*VMwmiAs@FW#(-n?V_^I!1x?OS}FfQBb=A&%!w4?Ydy7rtY*&-I(a{%aKV zuVWGax)b1j-LF-xJKtI)>hl0kqi`E7fTasu^^Q$YTadS#U9Eprt!Aaz?%NQp)|J;P zR@6|DOR@2L)!i_QGQ6ES!o|UT9tyLFhQvEUAL#l(-)R6$1f-e(%!;ZLr{lk%MLmRo z_xjkKT+3UC6mICxzFPlxR8YZr3*(;dk_XM~odl1|$T;kfY-5F*?I%wzgu~ z7Da!_nNqTtl9igLf(|Nvi(QzCc+iB*7 zz_nDar4oe|(Bs}K<{#?NA5BI?DSueuUXFfZhb{eiIV0!knxI;@9&Eh6yzfNOpvh3Q zQG`J>d?mHUu{CzBan~BNI0l42@B>izg>!_^bDSP5lC^(Z>1>;ROUg5)7VYGV3h)&5 zssS)v?8qf6P{welixb1Spi1&ujFZqTidDPmE<`Bx47Oqi!L^_(45j6|7T(h0%3VJX zB3XR!i;ym*$-p#~A@+zw#_32diE%oxx!4e5Ahl`zsiZP%mc6ZQ+`?2}S??;o)6kc! zd*&vqFm-=M__)DXl%M}P!XC$59Hmug9xo7^*z;UhF=DNCE#hU$%uGzXnQY-iDNnfI z^w1R?!!Xdt4%O{df`cv&q$D`1t#cp*M_i{}7Utx=9v;0gZMM9+7Y!GD^c$2#(sbQn_x}*b-!*CReoPME#}Xn<4J&< zPHf!n*>=JZ9KoZuvIcEorx$%+n~sauPPY_ey@)pPCYEakf^myC_AF6LyL1Jzv=zQ$ z`PkkOVxa2+Ll@{npz}spZ?Qn+SNPlb#qnaoA8>VNS`cXZF4Nj$G6FuyaWqrvtPBC*F#=j^(}cgcx-a zRx5LBd_sc|a53WM5myT$0UG8V*Mv3^A?Lz)I3h)m$uW&1^E`2o11T#m*}Gr|ClJ^4 zFmh3-myOM))2SYX=mXyMxK{1ZSc!i@*9Fn*^ALPckdr-cO@uiH((_y9K9a64+5YV3 z^mp%wrLd8S8^MH^IwAVRcNBj8!u~}n^Iz-!`4wZx|CJNvepArDWCa} zPokx%^^VKv+1ThhxRc+!+6`jagV(xH)-o+uO0sUWIa*U-i0-P@IO900F7JPtqs0p@ zdSt{1H z9N8&_t~sdAD+%}F(AnjK|3e<-Ja)Zq)A=8 z_$6FN&Jdw)k@8ti_p-mW_s+VfYH42q*dP=fZ=~^aC;UlE{4gE(xXk3Cqj`PgwKeV$ zdN2I#q2s%0;%zSEZctkv&~-h|Ii=0jOe#sQ!KQ5R-~zd3N~ugT(S?7G(kiuOax;OP z??^f6{@Uv`D$c$?J19gE6X>PY!BDY~9dV>Qsx{389i5kX%`K=Wtf5ARu6y=H*k(F~ zs^0i&{_|~rsUvz9G+woxj$=zOjFYO90_UJWDv2r0I6T26TIg^tSWr>mqQBDk+LEa? zGv}G@=8~ZwNM*)XztVsEJB!jyIWdo!bku9ti(_u{%9@xiBy6o@G)EEPxSKiN zALuq6VenjDbX;FHHl1ow#H%VaIIoBGsIM<)U?A`Gz9XVe6!DJo@E=(>MM?4ox3Hfmqg&$KfE-_qe$^!brhs)omyOAhbXBAe&J{>=l^>sQEePe7AA7lyZ-snpK{Ti(AK7T8TY zV|q(1__VXVx?9KYk5aVPseC)_pyd=9+eDS`;yib?@&A9f%Kw4z0}8v6*tLT1dbY90 zi(1Tv(BlTjLl^l$Nj&qOzxC_|zYLML={ADXbZ4q z5i9EVdIkdm8~^&Xqt9dFkTb_=*2265^q57hmZU*2qCrH{Jg>oQ-d((6J2XZdV(~L*B z@SbNw$IGr~>pXQX?B~pGKl6Gwv$@=Gb#=kTHkf~lq$38W?h%`)Ig257&bn=<0?Z~3 zwgc_=E*Q64ra$TEKK+C)&veq*G{-a4T~S1MCz19mM)7}Lg6Q`d@qZnKK77@S>u(Ma zkAHQ`?z|J8MYs)c?cuV6>rU8oo<4X&aO*`^turs_)ODV2a2gR=Ofjwy4lTOQJ8Drp zq*{MqEyD2(xv3{}M+lC7h+3dURuc81Vpo!w?GnY~e8h!icdi9qpL)0A(-nA9pjA@I zql5Ds^Y71-T;Bdd^?$g)I_wS$<4ZV=ZK^%{2 z@1r4mqiTSv{T&qqI(z<_ob>LW+rckMdFuzA?b+oKF1`WH1%BFf{L?h?&!)uAM+WbS zE^zIG3B($6n(1R;*mP`$Eg;-YN8YxXYdR{0>+JLoJ{{BI|;BK)-<~5wN-Bv3V*Yx11ZU(fQti_(S zwg$a411>eQDVCaWVq!dLU_Z9HmMYXt2oz~^Q3-t=MA<~ zaX#Rk9ui7U>dkKr*POBz1m-l+TG4;(bQ2!VQ|9f%0E<9$zmEBE#CuQI2WoAkIa5-l zivz(2QkqzXZ7vs{isR|!1t0Z2&xekiF4B9i;=raO5l9~Z03ZNKL_t(u_^}q=j)gb# zo@vaKtAWks2DwrJqBsLdd3_5jj~=|m5!a&kl>VZF&9@o5$o`Kb=@&nvncd}0_)GYz6}zu{ruo0?*A$?4@GJ-~I>)nKxCxC**SHLD5rs`B z#2^+JAuAEBWbMH923A%9Tr)gnnhPbX3SFEM-@G@iwyP@^c9pZ+9$GtURV;U1N8d*} zZ>d+S2*~4Y#|DBAdH@K)6Jw+^F+ zrXvaD$@v|v!8p%MDQjUhKER@AuhMKhtj|HM zmA)Go`hi*tQ%cmDm0agc_$5Mr7dzdXixwLvQ72u_>9t?;N-=Ba;y7`{&=YN{;Oe3V zchs6`Of1^HIUT7*18X|p5&ND}3j6&%IVXm00CCKRdjwAxI-=|Fc)W|uIhkr-uTzaB z)gQWF)>1A|svf*cGk8tc)5VSoicsb&7 z;aT+Dl!+Hz?*#e~xFPVZS~-lBhje6j$h+(YLHlok!KVRT6-Z$-hMXXpxLKk#*Z6kkK;BnTeFZtABg19c20zL*}2*kLM z*A{=g7SvjjS?4mPCUVOZ(WE$WO(8cJSxlO#uQ)qtP^zZLNonL<@hMZgg71tz>vW7Q&QnTb|K@?+XRoN^ zUX}myxJy4Dy|30ng!_2S>){0lKhV6#0~ax}xp@Nfk@4f1&Gd%w`7qb@vkA_wyU&Gl zDu3Um89#82|9PH&`G0F;J9KPZpbODF+G5j@MfDtP$D4V0c*Dct9`6EIalnfswVCF$ zYrNaN#fQM{)h$;SSBmSs^Sru$!>rLiyxmbtqKlqdK_#f3f{px3A*ICA5co(MH=*&ocWh;|UIC?OisHgAz@|M* zQlB%u#}g5MZZjPB6K}`F{c+;WdQczGqW1yN7p3Qp%Z@bhpyw*5}`#C9?4DMNaQ+uihd2nREOv()brt zwp~YbPBErY<786KxDaqvMOofEQp(JEVm}{$C{#9GPY7{MG{eC-9~kE&^;k)1=36g+ zi)zMlR9xr-eb+PQ#NFYJMrGT7 zZAeCDtj)&tw&rj?sOKF$ECdvHn`)-y!eQL&VZtdt-#Jg7GWWZC(s;l*7>15<&Xii| zd_-Kp6Pf3R%oE?5M}9jBS6=9Fw4Ah9+H>G+<*j{Zps{I z;j;|aHT@K2QNLcedPWx__db$-{weM_;^#zPCZ367FM&HB z_^SW8AIDbUNhf^NYj=LzJ8q&zq;6azx;3O!Uw932DNszkZTrPi zmYnm2Tdx1VQ4|#bX#F zTu1kUxB9}sGS>YK$wFIt4q-gS#9v&*LX`!rjHqxAJU|mF9uVSEP-T9Jm-Q0?? z9rrWuK6%CQ^{0?@gzMkympKi85!TV&K3wp2c!q?I%U0=~upN3f;t11$`R*0|@P@99 zi+Szw82?NutO72#dgYoGG(A8HuSNJLH2&{gx$Fk|7|6A(obWkm+MS#U^QJU&7?1iK z0z({dB8>BqR<%2u#*tKKg76+1=@=TdBL$6^eOU8K&K?|oLkQazeGtRs?hhMsH7Z|4l&VzFiXR)ib zX^}3X-E$L%G(CJSo&#^n`w$#m7eFikNpvy*@a*cvTC|%*jRqHV1t5;j$CaoUTwux* z%?`Px78U3P1?Y^&BjaIzWS);i?+_oDQ(~U8dcM6-=84*bzQXtV$lvY*8&kL!dwn`F zMDBV3Z@6~ux@c=8^3uJ#bqc3^i6<4Vjx!IRy<@lE^Y+Ol)9n>EHy8Mu3;Md`$qPfL zp-kQjr3h)(=kDs;x76vkxeJlj0|U)=NDGc!z!IJWp7F6LW0vHcrEJLEvc+Pl_eLt zh$^Q`RlAvp!$(xn?!9)|UAOMRwHvk(x5ENVOb}Xj-LC!TG;RgoNm_i9yZ=tO8PlNNU$h(1tTwaJz0VUk%+^^jM| zIdT7R$9$L-e&mHF8n80Y*}7@vvCng1TQa}bIlkY2cl1s#C?|qzHhEj}4QMD0pq?GZ z+gjMyMUBz*-q(F}t*|{Fc(E_s?~c6NO}yKW6X75BmRb>Ij^Jea`3#^1fKMs z>*%?E^upE)oq%81)UB?GDOH!lX1S`XCw)=6>$0>#UPy9j4Qk=cm#eUu1_6S;0<}1M z6}H6~EuK+3T0_RE9m}gA&Ra(mf;Sij_U2Ec&e~RsO_~#V*8J_9vVuB-ejS`gDoAdG zT=5k`6NKde;q?IG93ozASysGSQ{{O>i+5drVq{xYv@9rAQyO@uDqhqc)j91d$b~FW z45yi^!b}j&clWWwhd^~Y@)f6@6E2#oUnr$<*d2NJ^i$Hq+tb+nY~237>iy(97rK^l zEzvjh_lF0@v}1bpGZ^3E+e9#Itz%)8>vQ0j5vz&xENaWFUN)$=!|wkH{86sZ4?Mkp zzEq`tF2vw%f2=>Fr4UI|K~->`hS%|R$8e`I_)Ahv- zK?37+W4mV^IZIR9m$U*c+kjVp3qf-yWaU!Sf(vQ~bHV(l>T3;#S=B6Zu@~71mZEBC z9V2R2u7M$n@N~*+FO{4M^PHH+nbE9jDe3-PT-2gk9W4Q5BxgcxDgm<2Q^ackOmnA5 z*G1sd7BpzJ_{_2*NUJ5LX+)|{6A*AkGuayrqGevwD6N>q$Ra`whZ(wmfDgfZ%-OUD zr)fbof!;LEJiL0%^!7Ebq{Tq6cGAmD^z#>w7TGk{=vpR<@FOq$QH4(tp5I;*hrn@~w8IP?r4;6pOe`5Ft!TH~P@lQz zA+Sh2L4BITHP3E7s<@GVj@|JMop?G4BvZ=QX12J#=Xh~sOo?fpNNGlzFmyeamsiB7 zUGjc^Bt%US^WtoR^aMdT9*@lPj1L`s=QtdXIwdei$bxsRtun+7!Fi7Lpgj579#QaU7YZ#GER*s`xAhAueF|){v$+&xJteY_}&C@*$=;s_jI?QD*yT#9kIB zKrJ*;|7?g#tV8SoG|wcb>R~Nhl`@T_@jyu0>vgsG%r&?Cj5>D~{Nhd;ZgV3#{ry71u`lCA z7@gyP$MG-c#Ab*%UzyXSAwfZN%*QmX#j#odi<*s2x`qV^6GAXimt!m=yZxRpRj#Wi zO^Kf!XL8Z6z3iA@@>1Pi+AgP;T6~DhmPyp8*Xo}xV*Zg>pJF? z2qCZ=cbY!tbj;nwNGT^?Lu+NtKyP;4>vTXz`-nLr&;S=_OytrsT?p&0eNGci3fqfI zYHj!sX*f#B^sz(4aU2hfN$GXod-|?F{oKv|SxX^V+_8)L)0}f+oJV!5q(Yu_?V*Ib zYL+v9WyQx3X~7dyE{2Y0w_BdvZgCFAxiF_fj3~wKx4(sd z^A_1X;Ob1Rfm{NkIA$5hXWjbyb;)0~&iu4L zhmSU%k2aB~gXcPks@sFmi2_hcDHOApQHs%}tWYkbEgQo(3t`DAuNmjwH6%KsS7DN? z)rx}px5WT5J_J=Zdj+NLF_8bT0awDG%r{$^_YJZGk9VmwTL z9FG&nX=a)WxuTu7-86&V9@jCS^FepFk4AoH60_FUa#+{g8AV_&F`l()TM~Sr>pgv^ z`+pV7DH^p|XiP4JoM-ZMprj+-LFfj$ey~hwEeNF)O42>O3fxspRhx22r*Y!=?vA?O z;ajyX{Y-KEUSrPtfJ`|F=;W-}JKo2C$+nX}{VXAGJp^#_)}Mg#x+eMK5cp?vBZ=_r za!^Ekb9k?+@o}EWIj`%ES_{!fx)3yWlx9<-qP*{_U0R$oFH+?XXZW@RzTHRmG4N04 z${&})l$92z5vzKAsKB$a*=!iPp8a7@o-(;58;@)7$-}!n<6&m^?t#sApxbnR_~@1E zFIw#Ij_vk>)*8p-$ZI*@^iBhC;#RZayA7qG ziDy}_iAp1vnQ=biyrb(n6P@Z$sf!(6G={cReI1rs80U#nD!I%m1Wdx+-97U>s|Vfa zcwRi6AE;Hx)$^3f?=$g-EpzFAi(L)Pv>URnc)Ym^94A1GtREMf=$&x5PEJ#vlknB9 z!zPaopQi(`l#Ztw5-;muQic74PB;hH%YF1MY+uS!*(T&<)SNZi6Wk-ML0^}t?NEGhL^LDoL_Zc{&oKU`-gxpQ*r;=rnG&3)eHJ!SG$hz zd~m$H2s|AEH&J)zgH$4_;>}B#h^4A69`q#|t+bPDMT?mg(3B`i+1EAb@mzusE%d<< zZz_{9<*hfArxqt0xtW@L=`2?MwX{_X=M9VLfiCJuG&oa>XUL_IQem1Vj{76~w8w zYg)~AE>VnZ=M?*SJW$h!51ud#^!B2ea1Y5gncrCRg;p^$Ebk(1h4UJ&2A6em6S)i`e*`O<_Z^!`dlY*V7*TS#xK9+S<80<4COUZ8EX4^xNZW zvdMD&p7QDC5gWlKDmJ;Q4*FWSx_`&B!=8V0f5%V9=lo=vxxKyMa)=C_>N2KMs0Gq? zOaA`%xjr7ayt^~IXy93yn7n7_J^TmsuYb`Y;LA|p!`Ho_f7NVi%k8xnxQW6?8{x%9 z_vg30WJDElg`wd&^>}YAAFfWrMk(H|nhWVCRM4y@sU( z?JAuGVJ!P|QEv~33CK(^hb$4LCxLnJvKDqP5ThnH>1fe9=3JPj#PK+>J5C%9iMaqS zniWpi43W#BV;j7Zr@UMDeoIJ@d@Rti#TvoJiTm;(i&IJBFd>Vl&Wp z9;A^=!?{KX3&G1XripPpQ1VFE2Zrs2Zs-|eN9Q}db>XFEQr09e-F1c)qN7y0!hH8Y z8}}O1dN!_nznFjM&tLTMwW!PIV^`$^c=xsJ%Mvc4YHlZ_8gW( zv53=u!3uiHOK!ZUv`k8)6u-z z3M7v-9t$|Co?UnCy~ARAPu{tBD;Bse28?R1@v={2@2{i57$+m9b3BGLW4A(%k32l9<>pTS5IQj@p+W`(Sjq z7lZJ8qs9Cxz@@KrB2cU0N*4-THSt@2HHEQK;1s43w7?oCyNRe;T-0W^3frq?j~DB3 zgLVs{8OqdN%+3ieI1_`#v%+qw@?|G%YWLv9ytUf>NAK1c#@3uAaOt#RPD%IZQzBQv z1&u`Qqo?;mA3fWs8O`hNd>MV3?QRtXHtop8iu>~U=bXrvu2yPAe5Bi4FmyeCLl4_N zG7KHTi+0zoP+eI?emT#~tf@h6$6%+t8 z?hefN?~pv7+14H_h|hHu@_~ZBtZ0zW<74Fm9s464Tx$lJ;cSL)ZUuyU@A&6c_zcI* z?KPWC$23ips?Vc{W7Bnn&{0Z%UJ9Qt!c;4tid{2(WoH?%QV;c&&fvB zYJof@wawGacs!CzWxw0=_KgZykZeTNP=xgPFifd}kI-Log z<8hA@$FRAew8m~4dAECD|K@0#iN(VoOpM3+JOv+URV?*TOJP|Bo0^ywyoxf0cx2UzV@Eyg0TF zo^|li#_?_rWT^M*z{UmVg=w5g)2OP%;54bq z3*I%RX=c2;ryO?#C7Zu5O_Iv*IfpBHN0`*-{rUH<8YC#x#}SbfTW>Ky+vSKOxK z@@k{ctI_?Oc=fkSpj9Zf609TEm5v6o%q_!M_?ovf3F_(nE%b z(8WmfL0tiVvW(cxRZEU0?Z~2+xC~latVLDcp+?(^&yE5m;VsO{j1N{``c`tm_3r`18b$f)tHGEUC)tahS zRpm}uIOvLX)!0vq)O1=%Vjqpprfl&h4e^Rj6`ZoV1%bGwI%1Hf+JQwFxO_aJ0mWC?@ zY9Tlw^c}uiM!H98^|aXVz2HN{Rka&U$B~?WX7dFtV8W^<001BWNklrdd1G7y@(6_%ZPhlH-5uFL)U}3E@CvW+~`RJM@Nj>_9@(zY_X? zmVqq75F_6Yf#;inpC69=;C|1?^UPsNYzHBT0$SP`R{=YKXw0eZq!&Wo3Nf-LX=&`F zz}>5R(ww+{cA<8*T$$>m7+ZtD=yR$9wz}9vsdO>YPy(EotHUI^$Ri2dhbE7hVX^VZSh36jZ2544*i`HE8!(Xh{_YLW zesbW?_B;Ok+uzaShd8`CjK@zH}9RIVTW3zKew5X&FVV z7W;cP1{86Yq@@(C5S0y$7u~U=DOOA9ijE#F|6G;=Z##4E=$sJzDN5D5K;Lx+oAC;K zF`FIB{x$^qVL*H&ieuXchAt9+y$S8k3tbbUXwJ)rHppZ`_@UI)R z&M^#HxO2^TFZBI}+B~Hea>*;VzvN2rddp53wsYgZDxQD5*>dYWM=Rbl!fb_oUOIFu z=-J*E(T^1?PDO;=)PXR>z;9n)^K!G{$GZbR-0yf>tGzB%RF-q1R27tUUB{f09{wz7 zsMNB4&!y>WM?{D*lB;Ha9_-%kaL)1M`3=6)k88)PK{eicJ2$9RGx}b+?beNJX1F)e zsuJi@&TALn7D$l@+kRjiC&uH*bex#RM4nX4s;^c1iPna9@KhY%kjA&8<3$v%9CTz{ zf!PTaAyi#sWFR#m3e2t9=-u8#$ML~d9=+!^wJs7TABExLTT#J5L1 zyoTRkN_ly2`euLf!0kBlhd=)j&vrY0c>HZX{q{?)uD4tafr}x+cEkMpzk~S5)enA3 zewaDdiG2;+`L70P?pN9G{-YQ5zv;X4f1h6txC-!cfR|g(ZRfZSu=OgI^Gyr+GFGmw zYGKZWR&_Vql5*OA>#T%0y@D$(>W!s&6`C!bL@l!>Od;UZnijjL`O{roN9L=l-D%jz zLXPumw{9dk>(s>w(L3wV7owD+Ieqk&A1y}QvPRLVSAEkhH`_+<9DQ`_p+QV-YhWtf z(S@L(np`v$?W~A7aTKTVsHv%SCiqC~I*nb8o}us9YzO*(p{MIRRchz53I~@_W3v@U ztA%O-8YRu7k|?vru1alWX`~j2C_S#^s=9{tkYNXo);J!HYkR7i(pjr&IS_8xL=GY=;d` zU)+#NT5Xz3VRr7sK+p+*Gr^`eh|xmS!`uMPsC7brsg+zZDZzBe+`YYHzdMk#YGj=A z1RwRaQZkn!JRdwC1epd!?||z7FE?7ypZ1RHAZ$HEsko{TnPsF{EYzg7LQPdW-lCml$vPrb-njZdYtBec z>&9PjR_(?N66i+B=9t!Y!Tv6P_z#m4>x1#5#Ll=@)cTv6~?2}GuKXsJ14q=dU$(af4`^9Cg?N% zx(|U?8$pCC4==mGH@t8w&{2@4BkhR=<*K{!<+*c!Z>DZNvnWmQ{O>foy?7Qtl0JY{IM>dKrL8%ty_PgE>D0?FPew%;UB@wOk*-&m)I8$z zh$}PBQuve;0nhjMbbt0Id~$f;-TYnl@)7Pv*bWh1+>rV}?guXacrgf1dKJZOJw$XLtd=bMeX(va*Ha)%ZaPx0 zYG*kuP<5u&awU&5vkSNySU{LQC?v)?9iw+$q_+`$@ZLVfNi^f!GICe-dJN|RIJXvb zK?PsIu@-x08R_0F_PV7-*T?D1v%A{3%vR%_DecXcN7Vw~Tsw`|ZQQzl3cc(mT${$T zdhh5%N9=k+r{8DStD-(cwXi8dvzoV`(_=Iba%qrTH4lBJ6p@NuoVw~wUSDK+{7CRNsrJR}5Oew|2yZRialsP=?Y4dnSbNk}L{zZFq z`QUXWoNJLEEA2kSrF*0$18Mjw?7Z+NK2kP4FP>a7^p4UhKIt_Pf}`b`J_eO7F1Emgn zEABTJeCPI>&-N3a9VXr$M|R`Hl#;5;+u8TN*dav)=!-7HIZq6cQ6{D-@#?d;TwZMP zy^7=Tnn34WK%A)f%_cL8FtKFa)%)NH5}3!tyVv);eRan)YPy{U|ELu*O64*N-{`fV z-^M_HS1WZYq+B>h1fQ>M+L_>S>5h4irLT97- z*o5d#J9&S0skyW3uq|2Za{5_1gu2{YS~ZKD(D}eNMsA#Ab9KY<>V`MFYwq_q+#T-e z4)3@)ydmVH)E=+1Ach62rbIO7o$bYg?wMmCMsKl@mal!*;W?*%b5(C^7ahIFM-5|H7|_~( zjcEModh-##Ow892s1vUp?s8!+UA~2jES~pPPF*>*sd9hWPcNN$GmL9a3w8YI_}~4G_{ek;bFm%pQs347uRgB2LvHkwWmd|6unHPm1UBoaj?z>ra3Vm z3vXWC@%HsQ$d%x0W87Z;brl8Gg8*M!kU?j>@$|Ad$i>tVGC42J{mM?YpKo^`1P&_k2^7Il^5!p3yu&Y(d(F9$L7IsuloC? zgAE3Bkw-Vuc1rRx!Q85`au`rX>@hZtvuwHxXz2dTiISo?LrXg6D9eDZan`N3Q_E5H z-?!y^ZzqTaPS#+WoC_&`&y+NSRNa^NJ;SiE4m~2P1TF?&2I1s6QRY#*F_$?Wj!IQC=zehe+;t(~5b`wBa$1%A!ecD#`_#8D8oj^Y zww~i*+ZS~7=Za)ar<2nr-L9b-_@M+o3q9MR(>(5?heGev5*A~B#5-Xck9w^*7$1)O z?r!G4jT^oZf)#O7xtnEeDdvxCYBY+C;LEZ%V2@xFiQ(%Tu!e;s+t7aZhlr&G^9K@*GIF+EDPF1mOf-LFl2#$;P5{`Si{R5Xd<7;K? zE;-icxc$fYIcO?b=FfjZ_lut+&!3UL^^)W5EmL$HuY24fa+@cPsWJWvE&N}^ zeg9P-`|B$7@B7}vm#v_F-HQ40D+0F>UT%aJozo883mXA{o)EU|(yLiXnkw8eEUcc` zDE?w*{;m!j>#Mtfj`YTP-&1w@> z!wP48Vm%#3bfEq?BgFk%_TH>Vk|aqJ`$SaL%-!S2tgNe#Sq=vrfCFL)a9Y>f0G-h6o=f= zwDKOE=>)wBViqSYX%S1aQw32pNLUJ%B}085%l`Zn$*|3|S?-z)E|^|^wm=FHu8`uW z9e^KyYYMwKjLoOkZzuHpAZJ})Q{BMsmUyRaHw&D>_;nbO$Ap_*LSTFC0^5!iYPKOc zXNa#Hj>icC9=J$VnUAUJJWl&6Zo=AqUSVbMiut_HVsbRxI5a z=Axid+MUX6RfaU%N@M z7Q)M`fL30`#=n5jvB$fz-qvHZ*>@96BG_^v$p0#tf&*kyLbB;xU_1GNs&@cTz$j#Y z1zyRf_I5?n%4{cpy{P`}UNd-hy)KW)%M(7F-r@1P-vFE-ehv<>Cgj8;Cf?y7oeLuq z2nBIIf{Wtz@dNPT1IjP|3X~Xy8S}un9U@)`p$K950SfSsCEz9gRM7wJY{Ng~N&Y0l zAor2+$zZmxdsbt_)}mgjq^jO>W=LUwu&~9d3Ir4^>5RGzV|DLt4iRxkNNGTd5h+&l zmkJ?Q)_Md7Pg~>F@4IHEZxWb%Zyp#9irUVzh#-=#No=`*Oj~)rdF49lnkuh9TkRFruhff}I1kApnAm zQf8#YI86oPhZFu!3HZ;u9SSjjre3<%JH_cLTU$Doc3IoNEjQU0#eE9eTErbyX;ML5 ze^G(0RkHuK9!pr8w_5!ITS_1~zd{3}P=HXdX*a5+5mJH_#UdG?0YkjUQVQOk&R8H= zl<=5=X?enOo-h#Oi)F^`@q|~BaJyveF=5!F8M_db)%B1RqPg)k6a*oE-I%rDq8Yoc zY3vjE3`%R+@3fv3Rb5WxflUs_S0fog-v9R)l;-M??9b2XJ5lA(B+7{oFJT_oB)atFba{SKS^$gR^QkX?1xcN?2adV^6Rf~ zKOgam15P30p(NyRhY#3)V{Yt&KV2RBQx*I8Q$fG}IR0oXcK|PHLEjNx4TRgMZYpDX z*HS}R#4mL5#sanA+s6cMXc4GQ)vH;UC2PeL+KxOqnT@$4vbhAO5!dQX?J=9iWRFJf za!9j&ZSaagECAWGn`xD^k+L(5*vxCd5Cm%yyqSPI*r{{}@rL|=v^A-yWTx4Z)p9n| znvf#KWU@3P`c*%8cW?6t-MZ&uP`eZ{E`qNz42Cc5RZa~`YFpPTugsBv0nL%!J0+{K@G@YSRp6Srh2u1$;wkGZQ7M}@ zD!6W7gI2(|1w#RU2uB=uukcUl7H=Zq=3v_W*-?-=XTUxCWmynHFq4>v2mJk1@L$Ip zC^Jr~m{7gk*MdHG|Gl8oo-4Jt1?xHhl?UR5y=y&uFn7qkMSOM*8TA>%D@1Qo;>zQw zlY1cZRG=7qQV$@HXbmBNG@vAbu-#WTDT0MjMgfjzl=+B%V^$o`j{p>7++nv&80QI* z3y4h+uC%sd4f5wM3b?IB?70wZrF-jNYOnF;&RK`@wnFNgevsQMvkTFf8mX-*X6mHx zvW(JA`pyt(UI9f3g>3I${Fl8IK##Js1urNUG{^ONdi4euq>1KU>w!biM z`jHfa3WA7#Tg}=)!MepVGytJ2*gd{OS!P542M}&3U`iR^ju9u0f7TlJLl*e>Q!)Pm ze>VX4!Hi`-+Yvq)7`KtIciY#R6K#9l($dAqC28UWtgMd9_kC zLQ{=Dt#+*H@-0?&7|bBs)L>dG=z*!hTJRf(xaKE+tED%&9$eKK`D6zmynv%Y?=|Ns zK*dFMf=z5#zgw>3D}~Tl_@Y3d0%gy zo%arZT?ECjYF#HX~!`|$-9qCdOS+z&yzi$4|f zALcQ&f<6MD4TP5o4RR0Fo4giucbclCIGZACp|Sm?)YFZ+W2>>X3ET$~sVB5a!Q!SG z0wW7Kthg;HAwbiVo zw>DLP>@f5taLq@r2TyW_dS&8Amk|+(J9yz4SXqrROtIz9uc(LKWaOnZQ<$8M=`3O{ zbxSr2*t{&xu+Fx65O=VP0PS`NhdttMXN^!GjLV2Too$~T13;!v7cEX6y2fIE(&yCqCfK?h8!g9U>EMI3V7=KzSIUuaAH(&9<`+Up;evJDqbkr6sPltd9v4Xx3VNz-n`qW9+wmbB7mtG}n zM4hTZpM%cqpUFK0Pr8yDyJ;SO9k;{jU+p&z{sJ`4h$@%_K|Md*_1vK>2>FaL&lsiw zLkM=?E;D4FK$0!((737KP**4FYXdYbc})X0e|7)eX)WHxi=#R_ycYWP^XdB3&a{%> z;G7qwHTSssH#FNq=ic~*Q9ngnkzcQsj$qTKXlYean+Cm^Jo?8AER>~x+WU^qmq>o! z2dLfR9S^|lo`Zq?1c1%Lw>0gEjR>oG&Gqy4^6kr}nE~ADj9=tOe47q<8-^c6t@)#` zd;gL%&VPu=Rfk=QPmbB)I=h)Fq04G_ z^>26hJg`IaM&z2rX0YYnDvgGuTxxIqgIW1 zSts(cEXYf431c;)Q&h2(+#)@txO*2HLZPB4V$9?$8M-XS1oj+%Tan`XN<%EN2y*rv z{t8aunihp z(X3QIFkydxz-~+sa*JVQq~uU12TXIpH^2E7|J!lG|8jGKClyRWmf-*OW zq|(}0+x@n_-5wXMyLai3vr3+;tB^Ly!>X{fpU+*<*Ny{!qV4sqPJrT%eejkt*6F)@ z4MTnLK^<*U*QUrvhfCiAy(r>!kKf0;*3U~M_)L!YayjCW(~n|W|6>>S_?KSLe+bC^ zmVqxvvVuMk?wGJAqmaR^U)Al)YGEcgUgc?PB^T3Wy97jOC3bDtufZn7GzP@csEK&g;Lw?x7b&YIwdFdnfE+3|9Nyx0sNo_iL+~)9h{Fmx)P%WzDqAC+5Fq{Qmojj zLW+GnSNPps(<(dBWV+gOeT42Gsh}l+cOd|;Te=)RMMQxFn+5~cKKK)m&0DwS$zix!2c0F)lFh^^!N&)8uLDob(XLmHY zUT}(M`|Axrgd!j#Ith^po@=nilh#<%zQT0M%+1@<6>#kfxP$Z=ivR#107*naRIWw8 zR{=;Rpmmn34Rs-ccq6PXQCmIzxm{SR2@Eys*5*n_f3=XWUJ|vy*R-_0$hQnPs(jZz zR#hFjTMN2a#vO_RgWB84uSX^`xuNbFt&cnsA?tc4NR=>NG6!Y+*>CXxZmw5zKSJJQd`n8mSN{L=2w17Gi9vWmF-3 z6+qbwdvHkErgby1sgg3dwp-f{E*KZbq4~AwuN}X%u|-{L)%I#l?#9iFn`2+x?a)*h zH7+$?gPa@tk?dKsJAU$r-v#SV-5M zF0)N)GmvEg?1^cD}p4(0wO4mYD8!|EhUc5{+|uYUI) ze~-U?gTIeA_;i=>RI*9dNNjhm>^|=5gg8cK+7xt~Qnit{j5RH*Tc3(ebF`YNP?bg1 zoi`LL&hPO1f&F(UX2djt)6R>!Uvu*ecDvD7O^_T4j+^Pc78SIQ2PcWvl~ZldxUB|y zmicyf-kUrMZQ*nA-El4E=m=)g#ieRZeHNOMAsH;Dhbvo~8?<>O{>|{M^*F=@C ztvYqRXgsv7NcsXUopeL!av}_6COXj!SwbUO9DeJ=03F(VSzwMktH}=fAuS8 z5R?OQ2mmos2pGm4LX0>)JV2g4V9;Vk8?}(z!5?UqM=@xH)**<@2;(hicQ6D>fxwJ3 z3@8dr?+N?kgh8zV3mtUce?m&AzE7JxFf^JedhmPWoYq6ZAE8IIOHsSmq59UFZ#!+E zc6G?y-14e9Or=e7gU_29ygd;1iF}o@fjjA1E81SveLr8J|GL9(vO_Yad(nP(-Z2>5 zc~M;9AU;_aXZjcE6b>p77=g~*&x|x2I(5gI-`=4hFiD`OAu^&DfA^A4 z?eGB{WWg`;1Abd>@g|Nxn7r-JF~!H93i=<9ariRAjAcf~T>=ga4AlqOqMcU#bxj;= znJrG>ayL2c_oL1%p+MjiKq(@O$$ZRHG^tf7SmuoBxFDY`sui%*u#oI?t)P#l=}rML zP-D|G!>nUt7pqEUe=gGw4);e_#nwMrwLyHg>lbIhKPRqKFKGLjiV(yS*#eu7bTBu( zQ29PBM_x=GGUM8qJg7wL#f1Br|d+yNq34(=3l(ff? zl0{>R7_0c<0dHP^jq~fT5Ol&SWcxUI2z1R@)M7#xEqFIXq?;XX_XEzeJzpu3lkXVc zef1hIK4kn~pZ^VBz5ERS?fpBPa={^bbgB{-Vq{1&EGgB@gn4s4GY3pzK!_2C{Q>tc zUgG}#1+*x>f5xxz{^=2{GX~C&Zll)E7EWw2|~wb}WWe}0|PrLHw@x=2e(Y}2_q7~etj z>NdU6XK?ONnSR>lzA0+b#fsiNhv03ULtP{G{Iz5PJ}XCjS)TAA3~pchALCE_ODO0+ z^y48Iv;Fgt@ae#Kkr=l@F?7VAdWVtJBFG(EM%#ob;_#L>E`b~41?>r2aLmj!QJL;8Ycf5b6>MWHGznA=v*p=mzvaxE^ZU9 zbBh;IlGO>NhO(Ki)M-6rQ&(a}3_wbR6xm?T`i*2|Fe|Nc7VVxhsoaCCEtsV0SL>2a zyXP5D5F3-Wh&53ld%kwV4h-NN&p4k?$kQ3+e|!Sv2|;@jkDCFVPe4T!Qo=Cok#+}! zVFyuQo+oHto)-Y^X2tl0}lH=b|T>E1S}ICUjG*P^d2EUIttLg8uXlE ze}M{6n=|d_9%I7e-3`({;%1)^lKHwvCIn)p)@jYaT0)=a+4qI{^5gCO zL{}TBOOh6Ce$w_e(Q0waYo>U+aXNDte|S+RX1gC**By6vCDh`su9~4v3sK{lwW0%{ zHi4VFANii&wdXZWPu12fy2j+T5T16n0RuQsYnk5(vJEV2661k{yE<;Y0a@MxRZ zOS=oVuMsYguvHbaeLdM5l2J2$zC7T!@doe1u9N@%`<~e2f7D|Br+h581bi_7f1eGE zmjmN2684^UCY|9$lk8AvvK{dqqb0Lp6RcHXaAUX>UV?;<1Ly8!ZMXegse3h-$3tI#L+eBO^qiR^QPBmNjadUTh5?gO^#?Cfo zEC{3+0%34p`XL&mz3%s|@U9oHe=+%sdI2v2$%L&QAKnCA&1xf#T) z@v`gj(mRFGMuDp!Er=?X1XeP1o>1l^WI2JC2e3>l&z^pQpCSIA(S``}7kOJm_ z{eF+b%TJ-Xpd6p@;lo?VZ2EspCmiyGLm&*@o;#>R?=VSdtlD$37~H4}k}QY-_QQz# zmoE`H;`HVl9G@PMj~{TDe;+XFV)m}U#y0@pGmUdM-CaJz1iI=qur2Jg@$>IF|JuJc zwXmaub2@1noY#U*qSg~mmHOBB5~S$~ZCe3oa~rJaitq3K2$pEBwB0#(H~TZ_-p6@l|^ls*mW?`@+5{?v+q^f65?pOH=csi6Ps|0sY1nGXH)!2()t6JZ|%B0CIKs2O0`!l;!;qle%XK6})tZM$1RfHI8G+e+-BUzr6S-N!#^yF>v8mQ%*iBhe z$*j4s8~g7b93JfBuGp%!*uB#&gDokK2!#TkKKTTA^%A57PmdGQ5FuF*#~q&L z3H;^}|8rq*IpLHSgV*QDjCD{WRNWm;#jHZL&Z*p?5&(SHU8Xap;}i092J!;r43-6B z$rxF%3(?ZQe^gugR}l4GxaHR`VTYL`1caT;81jU0d;`sQIFmxkg7drA$nzPgoH3}m z0HPyM`4HF%GOw&hbltVf)mQ5Z^iEr3H7PrN2 zR$Iur?$Pdh!*}Z1Y-(#_+qz3%n6Ri7^gyl{5VZRne@={Vh9}cUuYRi~e?^|X9BCnG$nP!`UyR)@4B{yav1G}k)zSIH} zg9o*Ee{f5T2E)ey3gqOofWS2l)ppP=vs~AtG+XVeP23K9nzbZW4S6$$aGThUbX3Vq z@Bj`bZ3%AB0#f^4fg^})!&zJ%AX!jU8|hA!P)ZGvS&L*dFLAqF`}XbuP@iWv_c4i} zsS1j-_j3WJCF4BL9#UfaS;-5^oPk9eeOEgDe>;=O2suU!yB)^;!T1gSoX^XG^XY^# zpBsZ0+nMaj41HnM={v^#^bRyVdR(R;XhwvX8o?RZ*Y>=Z;eCy#*oadB48js3-oAK& z;l%-a6inv{@83Kj#)vTqj!y-DyZ;ow7++(4{D1{BmQp}vF;9CHbBb&GRuAW32Bi9o zf4c`i0K$U#;VtHew}1$On$>L-L4sloK%!uI-9DWMs2ReLDIJI-&ch8R9sy?T_cs`% zK;QlrbbJdrf57nrIsc&;F-}WY(Dmv*{Mz68ysg*z^(pc4MWt(K$+K+;cThQX`tmDn zLpPasjEKg#ZzR`l&(2h%l-G3+Z91Awe>(lT)9(v9%mijt2KZ|MG&7}Y+CwO2V_bLb z&Lt5?bVN;6Q0;qr+kOF%v{LNWpViy?UryrskyU8>_4N95-iHP;fKT%gpXM`;{{}Of z%UbxSEb^CAd;E`3(5rC&PdTA8fI9|WMZ(KSxDUXA8Oh0A6<%6-D%|O)SA)#zf80iv zmf>6}Zh7J4u4-C2R9?i{J)EmCOyGbRYfuYW@eTnoxZb-X$&{iN7ujI4^>Nnk*WRaU z?sLqZ3(o%Y7@@_uV3iwbEw|L1wWyL}cqOjXiMmvNfs&I26(u{e!7!#jxTSdY(*?0> z;EO?kQuEe}v}qrnl`UfFV&iikOGH_N-^)I8b1Oalo)U zAdP!)h&CZHA**6uCP4DW&1yw8F6Ot(L)KZ)AY;7W*! zMGcG~gs1%hZ|-if-w(JQ3DYUy#Vs%`g5SM;!Z?rkyU%_BdHoj0oUv%tfAG&JW!c!j z*62>NHk0P)XR<|U!5&eT#y(Fqwvz~vE$u5ZVL;937B`D=LYxZ9aD%kF!95r^hg;m< zzQp-v*k*(}uHfF`Hki9XewI>hg@a zfBm~DeNAHQ1dtt42KSGsf4&mU=bfq#pr*yX&ON-h%J06~<@}x;9r)t+`tJ z{?!hKynsWs?b$1*rJy_iI(N8rYL^Y+t{DV%nZuW}(eL9reU#wX4etk8@bl#f-=rJN z9R4VTxywTPr^;aeX!Pp8$Lah}`M3xcTJT8(K1qbTNH{QI4C>Bae|?``i?2XQnp6d1 zUgkzz_Nh0lGek`nBce7Tqus3jakdwbTy_>>aMO(y?ksM?<(znjim{A$&q`+khO{d!$P2Liwm!o|!b#8RNl5NaldW|v_9N)gif3nP`7FcE!S&Zqf?1#U$ zFpw6n>46r0Fe|4gaj)Zv1Jm}f^N=!Bn6>l3>S~A6JQ5rM zT)C783S@2fF;UH~*JEX)hUg6&ZKI9OMRGe$mzic9 zh=DL9!swaoRj*#n90=SpyVVPL3t%J9Bk!!u)#&vACu=wa&|E;i5&!`d$uk^R4UN`- z6fy)~f7YhIN$jMQW@I7__V*lhCX2iTV<{G?TJk#4$t=jz30P)BC!}n+0@YxI0)b*e z8g>|VHlY(!Gt0?RaGFk7mh-yH>*1YeQ%2Y*pjWLeR~zwmd^Iy(m1lu4bTvwHyQ3vH zD%TJY5U`|#cXziayM)Jw6Xp|PnlqMJ@c!Y1f9coXV)yIs@VG3PP#^;2ykODn#5kDK zUSG^a)>J=lW`i2i!@~i??gm3l7>5xtpP}!*!5{@Gu;q(;F^>xOW7n42Ro&ubc>o>+ zc|PJ%1^M_MTuumDYU+CXe{}LFzEY$aTb4R~-#P==JO=87|9qiNS80p1LT;P)Qn!Iw ze+ziK`iQ!()lI|NHt2m}uW`!Ns+m?!%;sm;Z`}-FnqbuZAiQvQP&PH^9BFpU)Tb)a z>J?!;3w88TIOqNp`(<3Y*N?XQ{1c1fnIryg@C(q#+UOW-ozaW z(RD=T2SAtqY(@PqO``Vu{u~H+6-}3Zf6IgsMjA1G*-Fv^t#XbPZu6r%_`ljwW|%kb z73}aCGp*5yov8?QJJJR)ikj_1H?3IML_qL@%hGGN%{eXvYHnzeZE{U)v6Lw&LR6$+ zKToPBx2(u0l##E8>ge(h;>PWsnUkP7TMrh3x zy9A98AsBg&-Qf;H8n6oy`(cMtW@G>Z2@(u?A5?v+2Lhz6bGXYa3zDJdcaZaYa~`AB z#8kVu8dWqylWQmje`IR^SV7+s;6DC2*C=w-G243{#rpd6#JCQ%@x;Sbe{a4{=nF@j z;{e2D9tLGX@~>I1FY1yIpBME$)ehY%PIa}Z3D@B7nvB<>Ar+z1>eo)@xgpgos*A!c zUfgG_x$2t*I-#4ab+h8QjHUh9gs%9wD&f)yDnjtH{D5D{CwLzch99{Z&A+Lr|5VVo ze?|bG1mHy^+^}LtgeZ1Ne;29yLw7zS(^@xsLvrJ2*J47qesSDQt4wQdIy1K;tFw*j z4penZR5Sj7lTttoW+S_C-Jgrt{!`5cGzOUQ3mZAk9ONu@Do{3uHx`88+So?UA~b@t zqGPevo1a`;UX399CXy-*G8tN_U>|wokRpUes4&EL+$tS$i9738f0eect8*DS1717E zYXF-(FA#>r*zFT&2v`bOB^3AR%|nGb_#z2eac1KuU}>jxH6n?D?Vv zSp`#Gu*_#@$yXr2mDjKZdc%d*xyyoAgK=2(**@5KlWYXU%jsO#&urE-N?k&p;^~VQ zn1A^NPmLKwUSHsf{arq;%6}jHj#rO;-tT-0ilzRJ9h2#I2YUf2}b6%n={b0l5DZ_b)#M zG2!&~HRi{+*yRc11=_b2HPSOYTRUjGnKZ%uCh7*QCh4he?)TQzSA${oX&u@MdnGMu zfA4xDF{`+vo;T&)*iYQOeewK%tf+T=z(%%b5SXs(yNliWeL3T^a>BbfY|XX)M78V( z4|MrUbASMy`ukl| ztI|QaMwU|{NI|Dh^+F5oj6KjgZw>Z%NzBXwUeHMket>C#n=)K;9Mxa5p18Hfx@0dWLI8NlUWQnvGi>G6boIvPSytl;vnLmEeO zjf0r>f44_W2^4I(l1o9Bg7Y+CnI_*U^L8JP4qm18kYA^%?S$Sw?#X8Uo(`)z7gE18!0TQo_5pPY}JujTZc;x9{;e2b35s!gqRV ztBrzsz0o$LrW(blsWqz3JVBB21bX-mdVG)Lhp$0p!7fi2h>#$N3M3_GyI1?ydN|9P zjSjh(!gRB1U7N~n_y^(pS?-t6I(_8+C!(vBe`F;;_AK{4{`C4!CSKnTqp3Q zf88aqO+dUrZxq0w89$pp;2+2P@1630?2vr?si6Pie+B?AS#eLmffOTAXG&5JR5II9 zC$QBb!_JImu59*ND5*=Ms>HZ0nWZwtrIOn^GnZ0#PcHXTt$E}&L4vb6K?yJygI75) z4*NZBnUF$23g+s@FoYqpB86%lYx{aAe>LeCyKaqx5q88UC#gB{;$3?i8rPMC)b_Zy z;qZ)SRRtCSb3shprUZpU?Mlv5ySUq{i=2by%nVh_L^r#4#ga45^BGwR7AVdtKp-5( z0e8Cr2?-@c1Q5;+f4#bY zNo(RdfmI*DO1-+BUEWg(Pj%MEPhaB0FF(im!x{Ts!rkqF zfBMZ^ynFkI7jNI-=MN{ualj1Iq?ctv5$zfUS_x9sSVk?$EkMl`PL24Md;%Y2!Jsq3 zqE^g_5XmGs5d`*fj($S#$XL44e@weqzboyubvtYmJw1n9uQA;9>JI!8VyEVgxOqQa z^50iu7;3ONZ^>?z@6i?h%5tw0xnL!~!D01<7!r559e21*15zM_7%<%5V~i2salnV~ z6qp`xLvp>`bp}lRw7vp}okqMX;OLYf3?PU_*G2%M#hN}547w(?Su^M)e>t~{t&+Ch z1S->Za&E404p_ymu*=2k^lWOUehv5W$-aLd1Nd|~;^i{qZA=J%<~sMUE%5QjUd(?i zkE=@9UNCUO#(p2j+1%mMt!XunsS`V~daS51wi#@buh6rLtnR8rbdxexC$M@GX7KCIlZ=9K%2p@^rqNjn%?aU$>Z*~o8F)7h+?MqV;9DNfUjX_>Js1;T_Zg429Lri^(vLdHFAVnTE{f15)9MMWC-7{>#a zBABN$mVkK__yX^QFr6pxE+T}87cUMt|HE(b#aFMf6U7`Nq!i4{3AyBM zC#>u5;42SuQe;p;e_{(U8o-Fe7>N*BF;sRtkxAJ+SDQIN;vOX(kjcoHdzmqw--G1b zByyLNcb~|m7yIG%+-=*YkCNi_%J+P}Vz{v5-4y)i^g1K0aW{=~2d7uWrVC$T?#?=P z9u0hI=k_>-1DFFw2&fe3d4f;?LO==uFK%yfI=;Z$`3#l`e>=W-ZWJFW^tzeW8;f1m ziM&qmYeQgxI;>rRSDV12SQ=Y^AXYa=`1#Ng-{ct)M4PvJ^X93@IX#yZZbEW!y^vq~ zm9Jd`w`IoX%M;$mm)3aynd{!arm)8!b20xhJ+>Vg-6l;X7d)(|2hN#9+W+TRN079@sgDC5 zM64bMS)}`0r}cFLuM;Eto>U2-VhxTmt?o|V1xT?ye>!`hOveTGJ-lG4Z1^UZvAERA z_|G|;nT!ZB6w8vW;UUZ3T9yJ`%(ZG+COn)9$}nK$fHF@gbM`E4wut+@KqMoj08Rtg zrGp?t1VoGho(oxIt24mso|K+Jx+{6DO<^7WOPzxl(Q_+Ph(4n^t+u26*+tub2?(X& zd~<`Ze-Af!ds-kR4xi2o3P%(rEX#~}nc8xvj~rboa&|ogQbZ7v z5(Z)q3(C+%$?|WB z)vI4f!OBQ%h)9{vm>)kNh=5W;DOOBxh7oV#h~qS46zQI_l~7pGt$GjD6`D3#+FIbH zgUPiEWPz@*JgFdv-B+wu;Di4wS||23XsIXXRaCFI{=J6AYzU2A_thzApH1DW*Qav& ze;%@2y$*sFe7Zc~H{%^1Id(?Qf8P4{FN$9MX*&PIru17PyiCP&lbDI1C-2F`|WEl4Gk zF@s_;6z7C(TuJM`-Nt(%0eXAq-%0uU76?)La^i(;7< zmk1hC^YZwF|KWH>0$~D>rC^$lkg{|Q!ZyXM!LXj9HV|Q8#^A1SgPOzQ05_U}iTLWj z-~l?`VI1}dS_~c8-vE*^DXps+e?0R)Gg4$b-r2b(of`o4oRzLQa>s_0=awVwgf#&{w%y2#l4xzb)`ht6mLc*vOWV?7E8~A+oJ2%JBi< zVAojAh_WCsVF9728UGkjQo0DzxT_APqISsnK~(5eN9)++eabwYet^WK94TKW(atZk9d(!cpUHl zB!sy?_S7DKD&&9QlF1V8Y!HF{S_t0Vzi8#sLWt zkzzZ1;YCb}GtXH&s7~$s%PLz_*h1Sf-a8jR4xj*YbR%QGOSQgqf6`fsI}9mdnP=ql zf@PkK4^Xn%*bwzQ2kT4KqAVnm_Kvv9?A2yM6wHx){E0G!g#t^W7^$Gy+ z^iTf?KE7>A3A#ds>WeihneO5ke`f1SePi;>q<2%)@sUZdC&ekP=N3~ZJp-QY)i?X~ z`rq6a_4T#w3wqxK5E(fac>!aO;pP^HpZ^u|e8%~kuThrSe^x@%2`mPUmkPO8V~36u zsNKX|9o^dWTnl{%n^z=Gt6_{6{WVV71`}%j?F34eZ_jxFFB90UfvYm3zfQ&d;hPVJ z;#m_}rLFuu1sosSo%fyI6{({Tu-64I^ATT<_fX=i)B2yo>-`Vix5u9f`tP68?*s73 zK)4?mHv?l#e``c2wK2*LVB+9<@zRKE+8Hmvv(t+RP^3c;4LYtQlFBqz&x{UL1*!}Y zJ4~1Zh8Pjjh%^l5{1yYo6tPbMyCGp10){kT9LzE{1Y;O8iRYO+yItM5Qv#G3p;=M% zNSQ)fyX=L05#*AQv)QXE6m!XVcRJzShbL&B!9&C(e+jbKlNN`;r`eq`=)+2XAze8G zhF};$PqKxwtdo}&G!;P+LCMxAgyoReZ zB&W+nhj|h-l3hNboEUSA*nRm0h8Oo(-oC-~@E(#EXjwpILGWg<=AKhWj9dAp(r)se z`7XVpr8&gaV(tYUt7J{v_YpfiI0A>yar@aXQ8?iJ`?pw*A3*2#;OPR3JOH|~V-HZg%o9dga1QAsY6tq0+Q0rwVEOn{LI3{lZY1DE zBD@#_ZW3dc3^J>$FzGJ|w!@YyWTiDhtQP9EsEfl^wTP({sAQ-VD^lW#WTZ&Z9o|B; z;-U=7W(vU}VQ|g#5CdXl3^8CAEp|1=e~9GJcL?NiHG|yEXwG+iYhtyzywM8R**kQF zE8S_zVD|-ivA`4&BkeuS6CR$9kmZa$nMPSNu!xg=RB$3fi~&PR4GOGY@mxKw)yQ$G zwTO1eM>VskzV3d=MH@2EmOtG^;q+5mE%ww+ZdF@A6`ozO!scM> z7Q3>UX}3fqfdT`B07 z)~^>cwqBky*LJHHh5a%cU9U9*c-8_m!LW!fp8^B~ z$ym;hIOYk<|1)8@xra<=lsrMQ5k+HOFluh@a9h-{y1ePC6{tvJm8xl%f8JOb>=mJE z4M16^^>$&JsZ}0cAm0BBcXyxSG@TIQ2p;c{!w3y~;QR(u^5#|4?wS=f=$&B&{(=p; zX?VVGmwpYsB6^O^ug|mMrkrt8yr}=4y7jNwd;gHIeEg}PfBa7Xa1(%+JI3um*e4)G zm$Wc7sA{!6bRvyU;ubDqfBPhKgN>r2)(diO4nU z>_s~vrHJH3J%)f3$l_I_Tg$RZtRkzyrGda4tl%{(%GDd(Kn3xgnQs%^7P27^S&>Ud zSu%qF6I60nlyTKpRBH-fXZ>0CdF#HjUSHK$Uz&Hu>L1H(B9}&ALgz2*eyf5)dYm>Hk!BEJ09ukq@`6ACf1DzX;j`Gism(8cL?&Y}*x6At4I z?hh}p3lUthSqppOnt8qpDm#P4ER(6*d$&g`@S|IwPszHKrd=zpj4S%3E2OBaXV6E8 zROoiR*FSd+7TTn%)3wj)q1$aX`^JyGGm5c&Z&!%@|5XjPe`YO^MKHhn9p;C3zEdYG zr9hVnV_A?Y3fNmM$|@_nEc99v53BSH9fw8DHPL>Dg3<_ZU2b|siFg1FHyDYqynl=7 zd;~9xon3Lne3O8Xz)!DH%Cvcw>Y!BWYu}OME*rDUwaLdc>)N3J{XYNNHNpT!Ex5}Q z-o^bNELi_@e-`&2O;P``N4G{e?4B6=#26B-dDyZtK-H6$R7<;p%!gcE>Sfw(=^(8N zag~yxrC9MV*>_cFiC@eN;)LLP^Asb3XJNP8^kCMiku6r0BOwO+xD|0LO76okBBe<#@(xh=?~K*$U>I7Gw{P{UiB z^HsHl_tdsE?V`Jh*;CkDN)up-bXkF17R>Wvu5Q`X0OnP1yYXc@wJh|+0XK&mXel_I zj*v2gQH)^7HOoFCr7B^w)H{v?IE6JL76L4aJQw77_O$}7hm)@TNmCK%szp}xnD$!g zcyl0We|K=zV@FUu)>injx&qY0%h3WJugBY*k?tq(r_zEw7{hh(? zjyx@8!LpnU(sp^>W@1*mmJYicytw@YyOa*h-D(^H0FewSmXIg@1%tTnUw7u%MOoIuBeG$-ubT9-I>Pz+W|MhY9pkDrt(nWL z4W(Vc35UZS?(XjJ^zZ@5vl$Di`F$ucmhm1UKsbH}k$EE|Y_R!-VGu50c-C#9uaBW% ze=BvnHnU&q+WU7TEx0cyMBHO(?28{~alia|@uz}*{f_`RM8b=Ka7ZT2;ZFJ?zB^KJ zhc625Bkm0F;?sNaziY|W zu=uV&0D%=Tl;#f~$c;fLnv4dq8Q(Nwe@-!{yUNCwvJz;-ch;zEZ2ui{E|xgwdhMLE zg`zCkI(MoBqM8s#NFiZ}Rw%W>sx?M-^`2hc!^Be8w1aFb3!e-X$$7zPI%8TER|CKq z>uaC~|I=CeWW1b-d_Vv0!Ph;iH_#K9Q*F(3{JWnSQ`e{7^7 znj}o+D%1xj7xuPhHEe@u>-$Ya*9%rJ)}@mczs_@P6H(@!wVdTTReSo1HBt@ ze*b8i+z;>Z=svbu8?vv^ z>VJo=mpgTncweMcpcGa{H+uV0zEW*kj_LMMX|>Zu%L35OHcfgLx5ifY$J&rX$9gK_ z*nLeiimB_J8kl4~8KiUglTPjyL&DvQSNQxt{g3$epMQmirw0UPB>y#%e}hf)?haCB z(D8NiaJYox3;F;li~6nbxz@to!}cE`&^35oKWcK4EdN=0lz3-rP_K5Zhsk z2L&+%f88RIW zB5v$ufMW2#mJxAC2r;g4xKP`#7eUYr0$VKUe17g7-Vxw>3l!b>#?o^J)&=S9vd~qo zw;it33cEWNdqWkm4EH#vTg>AKeYMBkr#Erum@0(Q5zINZNP z_~t7cWE>A*uO-JRfI|Ro6JZ|-Bb%8*QPYSQDPGXI`Fpn_F2&(tfRx+5 z)M6^dzJ4hve`SG`(!w~1tT@NWh-1Py4j9LTVHlkN=Ma1F!dFe<{UD)czTq+vFVxi} z#cv^4EGzq7zkVLvL`AXW1?Te_dCrz`oecU%DGtT^KHK~touyuoixu>Fnyg__G~*Ou z*yI+BxVLdeqxBkDGvxg)c9R_`WknCF7Fh{O1*H^_e-wZUQnDnnq6`XvW_!(`1+px* z8t^rQNWpTNp!w`dfNJM!<~uP(4C4-Q+<~K^CMw2#5G?>jETSk`F)wF)czVLJOf7Un z`@^{T6YxgEtPMxLOzFBfBsU72)i|X1q-*eJ{kIl$MoxD)4tLn!e**pa7dYM=@czRY zkMB?TfBfwe{^~fRs3K$aB*z4LH`vTO?1oXz}%xGjOIX^a+gc!Mk;6-0I>v=`}=7{idv zTYMZaq~t}F!JctmHL_CoT5ccPAZ{;?T*+3!nBU}%R&_$JdhfdT&$-|{TR~r@2~-4Q zN)|Ff)~r<6fmD4$_gGXZ$hlydGxD<7fAc`(vN+f6v#k_NmaA> z3u}gK1)vRvFRIoY)j}K01y75cwyGT>%mE12ct}y(>x(rbqUx}}DH=EggmJ*IKVaA& z5Qo8{RcrHBtRX9!jqH~T-p@0>eg7WIGGXYp;9C+8wU|on;=tB|-)WTnwWTYCf2RSd z-Y82)lq>a+<%lKS;c0k*@%|-#{=fbg{Q8S~ygB{`Z@+zy@$0wv>vue~o?*Y3>>OjcSRjs|8-;mHWNH%6M#(G(nrWOf{ZT z+E57%1?*A?ON%qDCMx2M`nuuX$kR5G3E!PxBgWwN|eLr-09APPyB%tN|msy*L@bWgW@k=b>G#4t{3e;M8_^$+6ELrf7F7TGJD1b z|6U~N$1=S~{PgG9pG3f21a2Z>7Zi~i2(>+2RUm5cb|c4m#csgP}oj|2v5EyCPVRv(b-OW9Q-3}o}dmdftMs^k&lrMtEdBLyVf4;|ux36(u@(?tQQTFDgbYwa1J>hlBsoX&C-D*Ovys~s+x~y{-YwRaE4vOG zbFEcXd!NT8o89b|x?BB_S`SN+)RLoz6WEXuSu!jm_DA541P=V+01g5qANdWC{N^Xg zXMz|B3?x6!e@_x8uww*}4a1QvL2z4YbvK*c>}Hd^m%JqJ^E~#hT5HaH%(+&rs$I3u zxh;~WL|x+IUfy%g-uvuRwZ@!djycBr0q*Y$sQ+>5%9rlnZKI0!(?ICFRg&W^Xdxnc z<1*U~$ZA(AX;3Ry&xML(9w10&Y65tRJ9TF53G&(@fBK-JIOkOCWR$n=sGHYvUb%AB zW>bQh!c1ZO+j^fRsjm zcIR|m&*%3~v<31blpRF$ZysRClKO ze|hYhPyve?I-?Nq5sv8;5OhXq*C0zEA5lBrST!S+jzA zwD4{Rrc}f%WV;ux1bj% zr7&=!{_1In*zfnayuQZn@)Eo^k8cJdB4UVO=i$pCYlQ_@-FmW_o~S*mvm`p*f9(c* z5VXOeZ3EiIqwyGZ0a^7+S)3$g&X{7tFsPUMFz60{rsh-12bzQT8#w0?LI>vwLvlzl z0p#HuRU+%x=anh}Qg7>rN)y8oLf2w*dW!B;DR=S#>w^Uv!fc;)E@zIp#G zTwFZCSu>S-2~7h<#1LL27hLuye;C;>P$o?(FU*z|#3z)Z)1OK2Jg&MsNZUJbK48NU zo6z9u%{TG#xBeAgeefzimptz50HgtNxCBeoBfwVvB*n@e2loCDy0AqPS~yN>$YT+> z1Q5kk3rf3Uf8;VkW_Cgo z8%tD#u*gA9_}HCSM&aLge=dtt{$hngGf=M_QEI3pNgAVC7i}dCt%^6ueSUFv!vt^{ zIB=;PKeqz)`esM1`j)EbM;Qf)%m9%v+mD}8;d~2S5|BXgQuQBc3%C|c4#`As12ad}QIiv$<$~c;s^~bgZ*{iY z3)oEBw#hjIhf(p_P{M>-#UGso>To2EhA651vevER72t)erkR=ohInME@ro9nCgwVMF@*Q?jyLX8|;sN{pHDWa598O5AG8-Zt6Et0m?(_^Ncb-Gr zZ9pM_oL8r|yo$)JDjj4vBA6s%3Ks9jhZXp#E{Jif8^wjj#*-~oC6tYbQch| zCph`h9{_?teZPm?e+v)qy^7>FV?MkH2;)XcRYez|8GZC+fwrgb<6N35@F$(QU1N11 z3rzsMO58Ki+W|qJt%b{K+SJ-N)90wu&@w2?IO#5;wF9cX?zE*6YgVQu@hO4;03ZNK zL_t(A^Qc~#f?K{$mw(dFAUCXvEdV4*gc~lvsYj#^i97}(Bx7#6w1?w8gcu2A!84;* z!+aK=yKzUO<6IWHl}PAkn5WBpA~K`pTS?e*Uy3360D%3EDyj>A3h0;V1F)lICvAzI2t1&vp_~y z*(__^xOrh#qZa`r7)YBFRZ40Q6Jx~gdWXxaYg}LLF$_w(I@V%B97?8g-m9hR#$s0b zELWD9RS*KCacH&;HXGoiBWzoT;Fa<4LBU@uXVwjYOr_DtTrlfsAjOCj6Qb?c3RLJv z;=r((I}6YV8h--Pz(CS{eV;=n;s749h%c7I&O1WWb=aPs;q>e|blX#l(p7%|A}UUK zWSb6;_XEEE*1Pz|y}NjFaiQ*XMxLM&>&Sc-Yv7!NdW0~wkh5rBnRJ6y3R$H-W)Y2= z<%BB=czW_N_&cA%*~uv=4H!}cbHe5I74|9OPE6P))qiIUoWOB69uy>INRo=n*+{zw zG`>ZEz_D5j`$TX7@Iq!DGz#g+#9Sf_*KOdttrnB@_!d?2SkofB@Nv-91zfgM<_H4Y zD$^J~;>!G-4(8l6i=d^IX}B!Lv{VjuvmNm|IZf|ZHwAC_F~})zZa7!`-({i_=Mh}% z?pvm7V}Enu8W%Af7f>I;nL%Fh|?p768%G{$m3QK~*KQ}N!qahh5>tgr|;`n~4Y?^&>k>Y*RW{jtEY zKNZSVN2nuUYXZ5>0WDRtniA(Yx=<&mRbphe`F{|~+#530(AFZJoaN#DXhcIKNJ)Xt zSr$72%v?t4PH%^M;_>x(az#*UNQ`lUE)X`gJCOywF?i4}eYe};`g(_cAB)%yg2Dzk z_M;%l+D2wotg@hlr3ewo+i0P2XigfOowR6u0?|+%E_sbkN~hyo4wTU~9?C33Vx%}| z7JoV?q-enEly(OZQc8$JuLaf6BklJ{!yd#DXj(X*lxp5zBlZK*eoz%Z)V{shwm7+S zj+4{p&~#mi#&pg>oYS9;S*1GX@FX(6_Ra%*w4v6xD$v7=c+GQrmE5bUj0?A^dY=3?a zW`CHsN+|n9khkn~8o`%S@qmD7I;a{Q)az(d%;iduTl(}#ruk&%Ej(Utg4s}F+VLIQ z{oHOHY>A4WgC;LL2SGg#2%1@umF#Tub!V$-ljo!5$FH9!i{~oui6?Bl+Fh2Tr6_D|_gs}`8b8We zl|BZc=*=&qck$dYp*jGW)fSZ<;F!R~2tlPt&JlcYI$LM9cvG0L%z-U^#W@G@l`1$t z1xxuHvRQaa1BQOUe%E8z>F7Y53igO}MGZs~OW3j>UAs%wH!wLM5d0?KYMu zV~9N@5n>htN(0|`cn<{)vN>ZCupgr_#bO;}PJ>If8Iu&4;tTis&xj&`DQTl4 z?8&Qh7x&<(Op3140o}I4`Pm(up58&XRdue~qWZ!VltYpn9_=GudhiG@-F*X3FP~0( zajFhDN3;GfGbJ@$JbJdaTIUc~9iDV#8dI3UH|C`v|3 z0+!x<6)Z$3UI9GJPBh8W-XdgDM>q$Mk#={a+7I<`HwxZbTvnskM6v6=6PMyfm{Fu+g{*&9kY5SBy*1>HnW&4zD!lYH=Tn+W=eKc z5vh5kQ_h-U=JTvAV2tiNIUbhpusJzg`kklz@0PO1W~b? zBY`*pQB*oP@py394em@S4m<3fb0(6p+fis#(F5wd<{Z3tmK3G{q@L=8XcV5lu6##$ zo4b#dxU&kj2yw_M%gT%xBZgr>-}l(>HG4VFQH$?+>McNHTz|JH8Eujk|M}z9nur5j z3%EvOOJm<74LuSF0|oft(Mk)poz&LrTM?s*pF9i1LFeaoki`@+3=!lT2zdU)@EZ@Zp4an)b4(I20aC&xzZnHrMK?P`}Ej;;PE>>z| z`*_#mTkk%?OMiFo;_;J*=E_ymiy0WkgNZ6ilT9sNcJND=k@ttWlmH1bIhg7OuBe|0 z7=#eJQ?#2CHRG_63X6;^fraiA)1K4=_Oq=u!Z|D@UsI0Eau^K9P7~G~!HFB!*0N=9 zUVob$o(b{#0_ov>gzY(;&HmZCRRMs0kN%yvz;Tc3%YO?X?m(Ol^aFM7SxKtPif*En zzN?a(ThE^@c&F3yDxEuz1gv=fzMh8aGy=)4(a{lK_~P1`0D%|Q;T9bqE1*6 zpUnZ<&41SRycHBa18-hkn|&S6<|{d#m1m+ksRf2J=HQrFP5qi%j_5d6z8dnc6{~J~ z{_s%+^obC`4(5$lzxR!EYQyT3(k7=nr>?erbc7IEa0etf2<;L3q#d!*(UcDq)~lCH zb*H=RDs*G$N|#c1qN$z%2u|Q7L6SqV{bp~Jr+=@8@?|PU*;%R5%9;wEY(AcMy$3Uy ziBYL+%AF96wzA%4`JTx3Kh0T+>~$w81}Q~No7LPLF{FrL--CywU0ncL?+{r)Ng&=b zo|ASh#ANTarn+S%{179C#Av+J-1cD)iOGig2}0iNE|uHo$VFI{Di9>|bniABoZUIc z>3`WBbX}+BGEHL}0_wz89Qgn|-4A%_{=4|*y*Kgr>EnsOsT@qXw=CNSuJ{r$$nu}7 zF01Smld%Vy^u^W6^j)NaG$lnC+;iCxX zOTRn;TW_|o4Qa$`7BIma*^G&nWOTM8geK_GLJrR9PPHTknLVbs0J33GrgS-_@hEbz z$APYXH3aXq&r6&T_X6hyU8gfnXMb~FrR`7@xX$LjA-l=t)HD!~EJ`&+q@hRO_efEX zNmmY1QuQ)NfEm7NOrU3gmDRtf= z0X*4jHzzssA$Q~u<6a-n`7u7y-pk-UkP-$_p%qo~AxD4@9^H0>^YiC$dVl8*+GeBH zuU;uuRy{62gnk&ngWzdO_~yG0@Xfn#;PJ&1dmnJ)zADL>IH5C8Z@bE3rW<2UywJG9 z!Uu}qarRo9XyhU)@qi)j;aRC&?S`ee1r{n-1W1E+!;#V zwKgVp03};38&Q(&?yA-8(-o{0K$j^^z68*7@a9{H$$)jW`_k+@KY!oi{CXvy-c`jL z5p2X$kEjlBJ()2FdEE^K*q6r+jGJv^C)gl@hSTai{e!Z9y)7jlK8k?8^!+phoCaX) zm4=^Cb2);NoYG~I_ty2Zf)7A&cC$O}P?O%2WM(Wm$&7jQ-gE}$K9J>~Yd6G6Ops=? zXY1Uv51IBF~jl~4|4K-#WFce=s$$b&B7e-?+^|Q# z?-5$4-+t6xa~bUd?F3Fh+QD%@lLS{(zop)J>(a@nP?w8Zu&rVWAP(gUGqGG5H{^M* zjZebx6d0~BP=CPQ`O=vZM|kehAR&C8;-h+wUQfuSnw3u+6Y3j>{c& zwr>XI;3O-meb9g(@2gc#^LmG^bk^i9c{mcVBc<(gK~Pu(8lB>3WL)Z5u*~+&W!jq` zRi|U6lV&+i$uD;8atNk^<1wbUsDnp`xC+Q!UF6cTnty%b7*{2?WvX9RI{Vf4N0t}| zK_k%;@Q!=He;9I3!bi0;KX@Yu*f>IK6ppVhN6q`zR4F2-b3_`OAQ6G{1P8CRKQnsn z&ABXT0bt(gc{9cbLfdLru6x_6PTwW_8qtrnjYAW3{Ys-vldWy&{M!?u@eaXhhpueE z2oe*YXMc_c?3{Pf6yVDawyK0})Q*_xKK{cB%gF^B zwtJ%{JcJy2Grt+43iA*dO-S$_NRp6vK#F@)hyxsTy$mLLBWMR6e53ZSsn-I`Mw-q$ zv|WdjlQW#0-$B!~N*6o8w*lS<#MrBaB?J3m4}XEfQz5+k=qbMa)|eh3nl{H&T#brD7Gvu4B{*D4au9^rqwjav0~%_RVo9R|N2R%i!D#@cUb}QU zEK17Q1-b^Q_QO@2C)9980h}vi7n=E!(ZnGwzg&+2!~>cnMdeRm9U}p^+W)N`&<;g# zhkrTgGD}*kHsq^7_Ax7=7(u!E->s{+aT>gWviBbF8uF9HbI2>57#GAK6=NoI+B|PP zWN>s~6NlDZ*rGivrX4$Eono(nZ%)hKxZ1S>c1OE-D;AcDFTM%bXTmt5L#lp>K0oN# ztLLJH_kl27m0KGjNI4b-ffJkv65Z?p|9?TIvMm)6;iCrV2lEj7A$QKYbXVV;Dx7ju zC6bwF4xFPexg5F?5CYIO4#5(_ zqOk5{3lKaIyhrOjLI(Vl*NI>qh!i(2k#V)A%)XNz{v-sSdeZ^~G);phr>O}|Xn#)T zoWHC-*N#|K(Gc}$=RsB1Or?Mk@o=uO$X68lHKvHG{SJuuz>(8}K zJ6vB~V4oO)2+qJ)eGz2^W zj%jCE1bIc2_iP>ce7qr;CfC&~>|>Ws6KhtQ{d{sM0~$e`3iUqvlVwAuI)7y^ckbk? zJ@$GZ-@rTv5V5gNIgDjKw#uWKNuW{PjmyMN=Ad&vHaC}N1m&ClTzw3=;q%rkT4$h6 zGe9r&{6e>0Uk8PvHyXZH)nkQen7n3Lqu~V&M+9L+mAw9u=<)X(*uzH|(Cdq-b3o?_ zjUxohGIrjKQbfa2AOvAu*?-C6Gr+vnSxji-%r(uGwGdw-JuUpjlUdISVj?64VjQhq zed7=shqiU_UMcTE0EpN0Gg5lI4Z%8i^+hLvDf8Xv!EI?+lFeHr=SMNfv2|%i?UO^( zXi8iY+;|8xspw2hS)NU2MEC2-n*n`{NJBofTvfN}i4zQx0plII@Dw z9qdevF{y=0w*s+_DCU@TG`fzez%FCDnv6j$Qi{#DJ z#|-4=z|Skimf&`~?GwRW{U=SG;j)oT4erMZzYOLuF`lF8*Dcw?@(LcvOb8Gpl|uNv z6t%q{;<@lqq1%srf1ZGiCu|&{F&eEXSnIHeYWA4BCMurE3V@yf3Lc?pATe5ow}qED zl$D4StvY8a=6@i7u7icfp=ota7o$Kp0`Qu2<{f-+Xo4zrrP#HSCBtP8bsl$IC991q zlLkj=uU%i zNavYCWM24c60%Q%*B(B>*WP>^Z@lv^cKd5ptkZJGC~Ndzc9ff`Z^;C4lWv^_>}-0N zH3ow6_X7Mh9{y4l10sNzgj2af91{A}sHZyAq=yVqoXUrsBedQ_dB!_;Rzt(vJR%EBKjC9 zGJpCZVu+e|Ue8l?l|3Ld9hwldFu}OG=c-Or2}=i|R8A1)gfv9N$mT7trLqIT`GBr# z(S(4Z*KtIQ1NME7%d1Na5!i%IGq;&R40r^1uN^mWfD>T9yG9x!f}ps*DHu6;6Dl^1 z!{+1!C#PpI7NtMxYjH;Y!(jqSd9aWDh;}eVqH2}7vbo)N_NaV)ISsCC&g@dTTHJ@D0 zK-m>=m$J6D1njQv!7DFKDyBr!`S=1V>9-7_r5r%zoi&&#ckk#k|)7pIB)$J#mI>c8Hc5!oEHU% z)6ey`RZ~KOKE&W2KFWZe-`3UO$tl{dLlYVWd!kWIoJCJ2-n;4teCwTu_`}yphqfq zDypeKDWbW|tP^1bWfBW`v406UEN@iZ#h54IXPj* zLRcY9PW=WFSzfx(cuyql)Kg5lMw;0ER2@l5QO8D^L96`)u$BdWNPm0tF%|bM=iY1c z?_+kbYjpojo&B1K4>)dOGqo>X7UE$dj+63thnwwU7w7#l7w_pRD&8Y7em}weBklc8 zrBf$#-l26y6}#LCs%o6F?S~^!$}_|##X# z&~}X)FGNO?pnSckLw~aK&dhL(;$~fSqikA})yfu_P&y4}3@M_IJ<>3!g4_}jI0=LT znr@5DW{Z&N`yv?1AR}XzxUj{RT6&q;xDJCUcWn^sz0T(yfPTNn&N+2N6HQ#}`(E8> zow{yu9N>IHpiXxPM9pP}bdBq)9a2A7$2GDjP0%D22C&^U*nezJ&@`=X2AG1s%p;S4 zoaT2!fCm>B_~u*p@y$2y;_<~(4I!bMS8vv4g7qQiDlE+wr(%IRDpJg#KmN&*-P|%H z*O}oRDqB9#h*a^;$@nbo)IAZH zOxRLZkxH{(zOH1AP3DYaYH7|+cAnr{Lc49zw5`(oL&6aA-YmhBN8>%(*1?e-4wCoC z$;?7@-7?DswTe$aI|)*X9|6L%orz}ZY2%qk8f3#S;DWhZo&%ZH@p z%xA$=0e=|EKH-cs>~N71hBzR!jK<}R^aS5+aC&kM5aIgjNm*5cy51wji2bg|es`^J zT&9U7DHq@zf+tW2IN6?}YdiDt=W#|Us`!U784%#%ZjW!=e+MtW@ft36SF3%(8hv=M zMnnsF&6GDH>KQQ=d7Qx8TwPfeXW$`)A|CBgU4OMER(!x`Ks`U;+{(4S)P0YBYc!d$ zy9Lx;16Ha-Ru1TNI^K)R`g0un)Owd+Xt`LZ^$k;h1v4g+?C$4^feF|I{chU#=kOgC z0onEhF@uv=I^TR8*qF2wjbe|L#XlpZ|<6T1-yY<<*YH|LF2_6dgU68NqGCSho-;599r(mAA0_fwFb2h7fhFLj_haFncfxR-7FH_X zJKTD&fIWQFfE8zkMPY05AeNrAK-d-jl-;}o6S39fvTJAzUEPj6@XgcporeGeGf=C2!vd* z19dbzT`>aunCgWpjjv8Bt0&2`2HH+Lw*a$~ndL%ZgtlvxSoQ&JI7QcP(Dws&SC>HSLEd55 zM_juBEn&>4F9)5O2 zj~-%(v3NwUuB;uo*=1JkbG3gi)#2*$9Gy%RPNp3<6BmY4@s+bFcz=#xogf#_a>VNM^Ce-k409T&zb5YIbmjIb?e64LM_~n=*-4gA6(|nz7C=OQx zSui!DAz6PvmL6bgXe00+(9ZdI{>VoU)ZYt{pMtukPN`vsl8|hcm{i|ZM#C3_7j>V3 zcR(VCBrXSr+iUY+7i}JI&RkB7XT14II~QygM{3yO0yf(Q-hVTk^njVU43QCIwuH_8 z-lY4lEQo`4fx&D1hB$SNOL4#ulN!P#>$ahtBMHMvf+r6j0=)O|IZBdfvOWVDU9iAX z6zFgo=}IoE03$z>`0rpI2M?pdz zyDCUXLbO&AK&R$NaJCb-3!fURv=x_WtG;$01FJ`ybL@A8Danp3OK> zn@vgtaet06=CuMiLroCC)Ji5Ws3ED63LY`Qa?oStKQa)KrV{U(A(6IwV3_HjVk_h>>3 zAyUI0*WmueHU8lB*KzmVw>3=1;W*_k%QN&vT2ZFmN*zg=g>X9OM_Kb54=V*4F9N3Q zWq)t;!n!b+0arO_L=K`Pr$8wO)9m@7NGsjYyi2dYpe`b6U_a=l3k52ee-$0+w`%Hi z75rzc#Pl#0I1?q#_t{5X-xw7lJgVOX1fP_Ba>B(;kMfoa*mBb6MWBrHbf{w@i>|Cm z265AOPuou zviszy_M)1vyM=K9R%rjjJa}1*fPKH4*6*iV|6>X2@8uevhorw%x!(AgNb@SAPOH zX-7`5H7W6Bced{n_IoWPf_GrA7oDo^?EsQGD$$anT|m>e=vv(&55bqQ0y&+XXN%js zj+a9#5?QRNXxK^!Dl~$3fJ9IffEdYpP}d=BHt^no(+FB==yB0ABrzJ~v{c=J=Qtqk zcg51yJHe(s!O8hKHYew*suzLtT7MjQ3&`*S_>F^u$K~Y(p6+|xy?lyqzjGgt9zWDV z&8>F@bK3W4S0U@67PaVTOl-?xHlr9$LAZ>h`t{()CwQzvvLSkI?=G+{s+-P~KOXRDUaEs7ZO~ zE_G^ofMXp;<&6&YtZ-$W6EfPmBCn2$74+r4%c^#x+pWMB19VtE`h;ee+bPzpi#GiO1FYB4Do2nT6qmLUiUns*B4oW z%20=keJ|d(nffuTdlqmHAAeOaKREQVFLN3{AT|^gVKXG5%4X8s+RQ~J|D8ldYmQm> z8i^1Zb!g*gR4cp&tEB7=?-0D8@g9L99BUFA5`o2!D{W55n^*g?{u??<=6=HwLZW{YmC zPH_d4Y-LX@1H5Y*q)529xWb!Hp5VI=ALI2$k8pLZ4sk^5K)wXltBPJZoSkz8<_`0Z zOIa~YCdzW+ipyM9w||p)l8-@tGTHE^a^g=7S?7OWqrd&i^}ocj&mo!)dgCd;6VXA? z%3+Ec79e(Z zu@$HTQVRNs8=R@wv*&y1#3ju{aHHAGG+ad1g=GuZCuBWRb$RYcn z;A#UaWZa{;)EuhjjJX-*o+`?S)(z6AujEaiYo$0xd4YvfyH9)jM$pLq z=v|8@Xu?}?2IwXjAW%^uvyAn5cCT~J>87=?K1Yd~WJ_+-F+kfkIB6Wf5&baeJX;7U z3V-4dEo3Hv(_o+ucyegl6P(_84rk}jq3JdzDg;7kO2?#y5+Mx(`h5?HJ+5{=zWeYY zzWd-I9$#Hsr?s-if}0IG4k9fVZv5gBD2Inz@d0-k#B>2V@33>ud^X@`J9)CFUpDh~ zmCM{5EM>7PU!JNSGjlmMhQK1|9!GTV967m-9Y6`rc@?pm#c%#$v7toqaWB7X0i2AKy^UUKKli11G%rxmw*}~> z>vW0kUR1WvzfO+trLSpG7`I@=j?DGf3jvu~b>qgXo)+E%I%4^Jpz4<~D?sXK-G4u# zUF`b_?BSye=JmxR<{E_2Le;3y+<^)Ra6u_SvGmCtLn;L4y!ySGCwt;p+~&yE*_`u8 z#9*jcD-fBrt7VZ701ta4CJZrZ%&4_%;t14wbX`D01nF&`T@)0!tn8>e7A1A2i!lSg z9!gEyV6$m75XPIyOy;H?%z_ngWPfCBR_TIOUf}X9c#IsK^ijefN$}32aSlEu48x#Z zy6EE#gXN-&?z)pC-K`G+C#R=4fBpq*@7zH!ceoIABf&d;y#l9Gk0GJIxrQsmaXTjE5J|=q#55X@8upVr9xX zC%HK?Fef^g8PkGz4vV0D9MJ3F6q$AP%WG_hzO$iQw?L6-bwQ^tCAcypoAnABl! zRJV2eUb|NUfr5vS9@rjSEMCRt=*$U;fs~ca`P=n`5CR(KfhZXE41Y-k=NmL#3krnD zJw&1^(OE@kQf*;0O~9sWv1tN=cLgNj6yV8G35)UMOBhBHja%gc-ZG`3O+bgdf1M(T z7%oPnYXRb*hCXmgowJ7CI5zKWNAOL+=Ik8j&%JMG@b<+eUVZc!_kW&VpdVuK0}#1IXD(A<$5KZ=JFO1DooAsCG_#DYbYCohFTg%_ z=S2u)z~M42n`gg^lRzvG*78hU_*z^k-J)Z!yWG4%wyIJu8RoNpKk~B~59Co@?-u8+ zGD$F-gFejwJTSxL^o%zy_+0e$f~tLyO?ps$Gp=WcThH>STWnKqkl z=EDH&A8Jr9l@NIgByWLWzsUnGpm?6f9vJoj_dv4V>4rBr&qI?P%t-)o0peS@rUTk7 z$a}S1l>x##5PwIb@bWIN6wu9GsuP9>flX?i#dS_}pIw~VQ@UA6s=KWtm2250fCnfz zG>+iKs6gk@ZX0x)4NkTjkQZFIE7|eE z<${S#b*+FcalDh&MmFmYl%-&35s_8gk{I#w8nPpFB!3|C>bk}DUO0d~03YCkN4weL zimsc1PSMjztSL8>9F}Qh0 zIDahKHMB~JR&Hm&n7N+2@a$KeXLXbl+n}D)nJ{)l2ZZzV|K+f=uB_Q*wVPk>_Lu1P z>F3hIzke-#jf@%Q!0KEcs7+|3qD-ai{7+79S_Y~)A5hcS$6V}0rey);&~?;XBzaw~ zZVZ%iA5{;tpFfVzY~@IFsjPJ5c$N+xH@l|Y1nO8BOC4iZ4#JOceB};D-Y=2k*W$5O zT~@B+C3a-#F|<&3qsh_IaOnf4;2R)xKzpLUU911*0}vCCdZ6in za0T?&0QG>xao{<3#jd;r1&l;&w77@34rtGSlNYdg;YDh4oa_k<2A*EbHo6{oTbE^sX*3E>pVQ~lateL-30=9O(knxi!PjjngH5p zXn#r9HfRHZc~HX^5moRfSR|`Lg>M2jZ9o&$V8#az7rX+y%i{qx#X+SHa6~2DthjaM z^f3D*UGGz~4Ry?Gv_Khj2S0{Tx!l1*as;kz(6$}gO^2@AV!J&>2rUu-?>v|VeeA(e zBV!!_ZP*}+!-GBJyYD{2>yIAcV&ALi(0?5sc&i799FLP+OLF4s5Rj^(k62dCbGBZs zhQVwttD`D_!amorGC{=yzTVlc%rt05A5g^%(5z!0Y3VxstrFlZ%;|5U+w0L4RVQb5 zZX?iv(imCMezd)szTWAF4-YV!0ELYAb>$f@v#yzNB)(I|??+b%^XH`TbT>v%CV%fj z)|O0xiEsq0Z!mpXqM><(O_7x`QvEnA$2)3X8B0xF_}1t3w<#EwzIHm&lEwD{N3O+V zKTp)PAFZ<-z;u(Pej>48rex7V|E=H|MtCT5Q{MoNiCyU0W0%4nQ0R?DtoQyMHUVJ}T{A ziUUI9!sw5lf!u3XK6=#a9z193*(zgNgw+O@bhl0Y+|7!WrL6Ig04}K2tV@HA9K3^T zHYOfSU_^*GxTZn7*`V8Q(KW3y22G;@3`Q30hX_Z6)(3bZblnzk4eq`3059Kv7k3{# z#6I@r{aU2QZwcruN4&6Qx_`blr!tvP3bNp5cCnVBo}+qQj#;(YtQg8>;hdgyY&7%e z`|Zk%e(L;ocsR?!jQoHwl^GWLU#kwz6HK z;!%x9Xnx=xfJhcH%2tb2V0Db9ws;PLX;#ZftpS?nfB*l$<>SW+uz#G!IeTq*uD*}uN==+FAR)Gdv}qwHXTbJF4CgOm-@Jg&|IAP0 zm6zW{I(-wV*~0f1AnE~1kl4cwdq{r?>7PQ_!qd%sLd{$}obzaWP;Yrw`_|a^i-$lq z9&yfuVIYur1i!_m*&?{66g&h*iaoBcF3|6ug5zEj%y`^xR(~~lix3*iHuq)&Yu1*; zc0;HeorbHZQAh-oy>paZ(l_J1vl+(F&>G?L!Kg$AK%^&4Y>qXuXiwA}{VlN0#R zz>M&~_TD(}k+|2LVc)?!r)zPc!*?D$!tcNK8s2{J4pK_9z>?!DEm#u-$#L49j|gZO zy2l^$_+~=aRevCw74DEpq-Unurz-cn3oE6w=B)XbG3D=Y$9$soJ`fSrT`MhgK{PuI z=W}x0V%A=H?JRbbgQW1s*a7>=I{H2;SwNa zHtLx)Te666?`QWOKD2hX%Fn5!d-hX83oTt)$ZPCc_Q^yca71*dHItOhhbJ08}Vm0uvA2W9>KTp zE~uDJNN3;B;-KGMA?|jz2`ok6=A34ld*|RnK=1+1>E11hkj!aRs%SusFc)DK0Z568 za1UJ1C-r!B&g=iXJYUZ&h1$o$2UDyAu#~p#>3_Kv8a`MDnvBxtZ1trq4HK?+J$B>~ zL3r)SyZF}Y-@}7P?~XqF$0~EIi{j?sz1rEx;oNP0_?2k~%?=2f(V>RtCF_~gZQL2i zKuDx1^wUmysl8j)P%o`cEzRcZvS}G$#z6pg-%cwZimR5jJ(5a|-IuIOG1HDEIog!-osV=iEvFnht1A@wv}`9)I(% z{tEubfA~AN|Kw6B@3=<-@SDH)HNZ8%_J4V_U5B6e{14zqKl4dEe|~~j?!JrP{>E## z-t{=!w)i)`@F{%u#pm(DofG`QcizPBzWfG;#Au&C!>51n1$^FK+{4}gqJL6)36ni41d-R zfdU|#;z$=$EaN%?;Jk-#ydKiIn2fAsOVgO(*hzBaJ}~jTI44b$w{i zbz7XCoB|B=`yCjm(9yvM1m7UCfPbU;+9$z->nptW&bxTy!F}}mU5N?33D9vw+#^er z;(}A$8htwd_d!OnoGj3HeuXy8w0f?xTnT`Y>E6113RfUrDB&!sn*sXLL3m6Y2izc_ zn+cB&S%7JWkK1&0w>XZ+%=SYXRSw{G8Kl?80Y@NwNqkr6&fBcp;YJgfMSoDgg_<2J zUG}Y9+txlVx9iY>+s72Ie}8hk`+f$mcs%1Zc67(T*3L{AIXwp*9VQpl-T1SD_*y6b zCt{|){39~Od$Yk8e)#kF*zb-}yfXpg}Bd;R5%^e_Y@VEc^pTo)K1pmuF`6_<= zhc@^x{?=c`Klt5m({=FCs%v?qMZ(mrGPx$Gd`x2h}*crb4^;glJ{UCn%H+~iW z;vf7Y>>u2-uGA})9D>eWSZB~gY~Zc7s*cp66%df~7=|5E%uE6UL4Uhxja1{(84p8` zWF|M9A~+5}iXh&@@c>_4(ZLZy@MuDV#w)PGk%F=SUW|G-WMN{6I18E(T^+NTzdoPt zm6OfWGZnAAxjF7xx*NF$2N@~-$WPU$h;i5IWv9oxw5R-j+Li2qwdCQx;E48BUR0% zbI-A%W9FFy6?Zy<3NN!WnpDMr%X#iptB?(zfC7BD;@fro`1g$2p*-IkGxLYqN@ki z_tcMXlgQE6wf4A6g~7AX?8knwtZx|P*D^SdcOc)PIe!7YJHeN}_!;~sf903)H~!myfH&_y!JGG=;upU3 zgZMkY_GP^M=6^%{r7wRT|M~y?n|Sl>r})3$ehGi>$3Km~{i{EN&wl(IpZvr*{^9@r z+xXtszl)#zsn6m07tWDhdJW8i&9=o){LB~e^{;#jn@xl3r{C+!HHbbc+C*fgXbjx>SI1&_uNT66wRrlst!P|zlY%75xg2WNbVo|hQlBUQx z4Y?tKkb-yyIkesIpaS&?Od9OHItL`f9bb63s_06C{F=fKa!X4nK^B;|GF4xTE1 zbJ5G}pu-rgW0zZ*<2mJr9ebVFb}-7I<#JpWka2x(o;}`Wp*voRdOdtvo>TNI-{0Za ztjuR_15gV^1Fy`a`N$j?H-xh+K876ckZ;^Wmw)4rPgoY>$&s1);pfZp$ZO%+y2)J* zE7bqm&xUaG4m~fhZji$rbpeok0DBK{4*pqqCJ~LOUZCgSmn;*a4;Iv)?VB)zb!H$9 zxOe{@I0yXvk9`im|IOEdj^H<^_=z9>EdK4E{WI`Qheua?Ja^h*+XNs4fCazz?YHos z{(pwYPkr_UeB$gxspO#O@Xx>T2LAGwzW_&sANtgD_}HgEj{R%*@$~66-o5{*@-hcb z&bGMo{5jsf`wkx7e}Li9+n|g4@bLY%4UD)Xk82&-5vtLiAPE; zVjPfSG^Z+ct%D>WMZgX{^;9!z($sZq&wu5;LkM00wQWn6PR3c+2fiem-GbqWbZ$No zB8km+jdrZovdE!0&pGEoKA`D3bWLkr93wcho`r*V9(}(@KkU)^#kAgA7-G7F` zoa_E-PF&Wpa+jVv?yL@`3iM4uPc`6Unuk6gFVwf-+QCOF-TWL(>uAfHX6sl146K0h znzDcGXHFukb9gy|+oNVyZawSgwPI3^cc6TP5rW*DmL@mQy=C@_EKs>Jr05%<7w zjaR<&8vfZ=UdG@0)i2|xfAog{*C92h_|C(G9XtHxpZg--cyNJ7S3Q3HXTMj`Ju z4qt!cA%63#uLC6bvtRn8wP1|%ZHw35eTu*L&%TEL_p7hrSN{B;!Qc1~|9>LB_u74Y z<#)cRp6HISyWZpB+mG?3pZq+oFL&5KzJT;sK>rlzFG0h#QsF7WLo>#mQ$rVL!7$Df zd{Fl}LiUD^5Q)0C?f~Bebej&F%?54PAvD3_MJa=Hf(-0Xc>c@eAi^zEW;S+rQ-aWkZhN|0n0njrgc9Upmu{)B(ILW2? zH!oD{YlmxXdl{vA%mwO|XIa^Gb~e|$@3ya7yVQ+Vv{Jn`ExM9v9MbH2=CyyZ})%8pPrunS05@culoRk&dhy49|bSH@c=*b8F1PfB&C<9l!mJ*KyJY z{PK@}8gE}*VY}_{>tFsN{-@vk1AP7ExA6bHd=JAg;P3pkU&5>3dk25ted%>P_pwv_ z^w0k&-hAU7eCunkx(1KaHno)^*tpTFD+|GWJ)7aDy975Be2@Rb0aHMn*<$Zs0T2zoa zw#Af;?pM|ONMf2u%Z-10t(d315OiK1JbV-2n?_ytoE9HBeNLE>VnRxSrrE&xfPRSj z7zsKzPmGutmx=Jb$4~IeTlaDQ;REdZzPyKm_4)atfd!V=Q;zMR*VO0I+S=N@RAwFD z)&Zvu2)1NFG@T+*)f!TDiRU-D1eDU@ZBQ@cQu+MDLyD@f(-MC`bmOQ(CM~+GWKd1b zXO*o8ugeAmsMm@3?_&SnTiQW&z%fPIX7lk=oI3&eA1vc(i#APd4Y~`uJhO z$%V)J+xatSI z@$OT+a_<3#t84u9mwo_0@#&A@;l(vxed__f_1fDIBD8IbU-+@l;1eHv4o~)sS04{} z<=zFp__-JHZ~n-qz(c~H|Kf}IwO{;E{PsWnD!%ete~5n{{*fQV?&=EnUcHMuXAOSr zCq9iJ1KxV+5ApUN{vPDwEd;(czw@MYt3+E3oAy5}sw~%$yVL3EB$HV!LrK&pT|Wnq z7!ilPrnU`(Qt&ipO*!Wj)SG~&?X(#1-l%t1K({v5h(kg@BnWFVnkTi1g?Yc1F27_z z>!03fA>x0XcKpr-O=Xj)8woa576DQcgl2=&)8{axh~3pCoL6_2eH?Jr@A2UB8gF0i z@bK~iyZz4WKr29hMlqbM%+(h&sTWkP-w&YY`sWh?_;jn_uKxKW4ekoK>-+04HP6VO zb zavICwm^xF#TCI(MObOy)nW8iqaatURUX?{atO&HiygIAybEZ#l+7~cC{9q&0E z|Nei1I@u94CRHpi!mi!XwWcn z)P=4X+PwI=&*8uP4}KN@^lPu<|N6aG5cUK9{h$9L{-eM43;4VL-T#Jk?;e6&!O0#z zUc(PNP`U<&C-CtSAzmZ+1kVh@pvE&urL=!0Gb4B84Y;Gx;C3X6OrlZ2qJp`ouiKLf zGbBaqch?wpJ*YU2iN&cZ9p1DpLeuJAyouw~LC=jh9E19xc}ra9$bH1 zU>AD`%XC!@w+v*#5ykK==jXg|5MV8K^2plH$2{g-Fztk z1Z9P${y0G&GhZ@wf#6VUC#H{w15iH%^JVa!+R4@(x|?tfH*#+WGwWM&b}JL|`mvV5 z{3d?j#QPd7ahN;-nQ zg^Qe~D{E7Td*J$sW|4;u7%q@p^;lU{_y3dk=FzfT*LmM>pQ`HVPH!GCJrI90Cy)dO zk>X&ARAgJ0EGMz$#F8!BkrK&qvX-Ky<=K|xcqy?XJBpVbc`33LS#lzUmLgfAMv@jO zkpRI7BnS`$frs~ihc~}>haPJTD-p+18bu;0NunY5KHQkR@<6mmX1SLW$7){)SCJ? zxJE#((<5)wY(`6px{S4IlQqx#6dFOlJg{yGsB{G_Ut60u<(YU@?@JZ!u1gq!?B7E# zAojd!ZRS_mSS2Msy}6NQ-~TZhsgH>S$})qErUZ z(*S{mJ!{d9Rm3^F8GB5AhnLTsNwdQB3==-5p- zE5T2}I&Dle8ZjOi&$_M&_^v@jw3U@jaGmp7qs3anY7KD|lW0S?KcG8UBZ(76lPQrl zjE!)4XO~OE5yQ!lIF6x2^0Q4{v#CD0L~B+w#1-lJCRTr-nwGSmA~c53#gM5@qoQEL zTFB~h8FoQnMni6{J)LJKGtZvwu+L^Zs_@>~y7Zj2k@C^7Vn$uLmZkd=lgroJtb1j? z>y*^Xi?n{(cTu&isjzmf%f6eyr>Qy9w4kordZE{XaSfB8Yd)9IruJJ3Q8ggRe4K3Ij9~JGL0AME2$+P?Xpf)%)sJ%L9k;Q* zw#MFM!j(&x*|~U$qq7;3Bp5C1Gm5@we0;|qM0S6!+a!1qE#>`A1o0m*blAlLUrGT^QXA9ZbG-EfJtXSACC*`TcfdWXq#@^{Z=L&6$5T4t^~H%(_gu38302s5OpunbiV^ruWMQ zR5fLWi-3awN)bpJx8zfgd;p5|hz#cgv4S=C$g%;v9bk zz4vs9NGbTh?r$=k@zqmjEO;d`CZ2)OocDYTYs9L9mI3>S7)VHvgy?t-%#g%5B{dIG zo;B`}0P#1F?k1+!M^x7un|Og8Lb9u^b5pagSH@t7Aaagx;RL(@<9QH|(VF6HSyj!5k#t)!rifZCX658r#Zr-0Nsi zOuP5bKeqtO7-4D*v71gHQ~%Cp>r1woOU_{|>8w-8y60t+tiHU-H?|e6H&uTj8!whT zOr~zHsb?F@GH1xE*e$rXFF9YRPOhU;xXOZDE+FGv0Ze73Ck1_|gTL$Wj zZg;VI?Vb;vK6E!=u!-tyBAtJMm3*D292y-@Er2EwDzz=uPQ=CY5Y=J7m#I&=pOhH{axlM4u=mj=VP-2+{u|wF2^1$obEZXaH(N2>yGZB%* z95iDF(U8Ch%8T)m1XSd@qCAi;_-m-{7Si8`-`hY1T|B>w=LaNCW|e=r3zwi$1@L5M z0evPQ&&SLZiMHmb=)?(aC`-AgUwmR42DP?wv^GYv^0Y?l%&qGL6tu>~f>y>d z0%CR05-sQ`vF0>5LmE%nSWE1AjuJDsloj8~<3_WHSZgNXnBD1&E0Zz1lQB_b`wo=Q z79Q#sQ`0;iQzz|Or~7~2HhU}5?gs1Nl%NRW2qBg3oMJ*FWwAF~G0^BL|3#2rCRo2{iH5357o_aUSW;6}JT}vZ3 z1ei3`%&B=z8~V8wlhl&lU;evk3<{b`Vr_vJs+&=1=oP3tFS>t4si9VC*HmA_i6|n! zWA7vL%JA>2X6^os19W#6iv>me9`x4PICz{t^}+XX^vGfBa-;0BlEg8edHMxD^W?MW z>6q{Mrbqb7$(MNg>1VCtn|R!H;tt+;|K0rhqfaAVz`Ni4AZvp@AOF%RCgBW3@ut@t z=QYQ+_~_@p#_oUagm*lAHzy7s;MX62hVgg`!0YZl#@p^c&aZ#^8LnI%^3c6^@V+

      ~x?!Mhhg6ag5L?{v_ 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 diff --git a/release/datafiles/startup.blend b/release/datafiles/startup.blend index 6f6c6646e3193e10273a2763ff5f9a9edc5d9a82..5056246e7439390550e6274262563d01421b1e4d 100644 GIT binary patch literal 408072 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 z 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 literal 400648 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%0D8nWbFd@AwJ>)* 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 +# # Write out messages.txt from Blender. # XXX: This script is meant to be used from inside Blender! @@ -33,8 +33,7 @@ from bl_i18n_utils import settings SOURCE_DIR = settings.SOURCE_DIR -CUSTOM_PY_UI_FILES = [os.path.abspath(os.path.join(SOURCE_DIR, p)) - for p in settings.CUSTOM_PY_UI_FILES] +CUSTOM_PY_UI_FILES = [os.path.abspath(os.path.join(SOURCE_DIR, p)) for p in settings.CUSTOM_PY_UI_FILES] FILE_NAME_MESSAGES = settings.FILE_NAME_MESSAGES COMMENT_PREFIX = settings.COMMENT_PREFIX CONTEXT_PREFIX = settings.CONTEXT_PREFIX @@ -43,6 +42,7 @@ UNDOC_OPS_STR = settings.UNDOC_OPS_STR NC_ALLOWED = settings.WARN_MSGID_NOT_CAPITALIZED_ALLOWED + def check(check_ctxt, messages, key, msgsrc): if check_ctxt is None: return @@ -63,8 +63,7 @@ def check(check_ctxt, messages, key, msgsrc): if key in py_in_rna[1]: py_in_rna[0].add(key) if not_capitalized is not None: - if(key[1] not in NC_ALLOWED and key[1][0].isalpha() and - not key[1][0].isupper()): + if(key[1] not in NC_ALLOWED and key[1][0].isalpha() and not key[1][0].isupper()): not_capitalized.add(key) if end_point is not None: if key[1].strip().endswith('.'): @@ -78,12 +77,11 @@ def dump_messages_rna(messages, check_ctxt): import bpy def classBlackList(): - blacklist_rna_class = [# core classes - "Context", "Event", "Function", "UILayout", - "BlendData", + blacklist_rna_class = [ + # core classes + "Context", "Event", "Function", "UILayout", "BlendData", # registerable classes - "Panel", "Menu", "Header", "RenderEngine", - "Operator", "OperatorMacro", "Macro", + "Panel", "Menu", "Header", "RenderEngine", "Operator", "OperatorMacro", "Macro", "KeyingSetInfo", "UnknownType", # window classes "Window", @@ -95,28 +93,22 @@ def dump_messages_rna(messages, check_ctxt): # extend with all internal operators # note that this uses internal api introspection functions # all possible operator names - op_ids = set(cls.bl_rna.identifier for cls in - bpy.types.OperatorProperties.__subclasses__()) | \ - set(cls.bl_rna.identifier for cls in - bpy.types.Operator.__subclasses__()) | \ - set(cls.bl_rna.identifier for cls in - bpy.types.OperatorMacro.__subclasses__()) + op_ids = set(cls.bl_rna.identifier for cls in bpy.types.OperatorProperties.__subclasses__()) | \ + set(cls.bl_rna.identifier for cls in bpy.types.Operator.__subclasses__()) | \ + set(cls.bl_rna.identifier for cls in bpy.types.OperatorMacro.__subclasses__()) get_instance = __import__("_bpy").ops.get_instance path_resolve = type(bpy.context).__base__.path_resolve for idname in op_ids: op = get_instance(idname) - # XXX Do not skip INTERNAL's anymore, some of those ops - # show up in UI now! + # XXX Do not skip INTERNAL's anymore, some of those ops show up in UI now! # if 'INTERNAL' in path_resolve(op, "bl_options"): # blacklist_rna_class.append(idname) # --------------------------------------------------------------------- # Collect builtin classes we don't need to doc blacklist_rna_class.append("Property") - blacklist_rna_class.extend( - [cls.__name__ for cls in - bpy.types.Property.__subclasses__()]) + blacklist_rna_class.extend([cls.__name__ for cls in bpy.types.Property.__subclasses__()]) # --------------------------------------------------------------------- # Collect classes which are attached to collections, these are api @@ -250,6 +242,12 @@ def dump_messages_rna(messages, check_ctxt): cls_list.sort(key=full_class_id) processed = 0 for cls in cls_list: + # XXX translation_context of Operator sub-classes are not "good"! + # So ignore those Operator sub-classes (anyway, will get the same from OperatorProperties + # sub-classes!)... + if issubclass(cls, bpy.types.Operator): + continue + walkClass(cls) # classes.add(cls) # Recursively process subclasses. @@ -296,7 +294,7 @@ def dump_messages_pytext(messages, check_ctxt): # check it has a 'text' argument for (arg_pos, (arg_kw, arg)) in enumerate(func.parameters.items()): if ((arg_kw in translate_kw) and - (arg.is_output == False) and + (arg.is_output is False) and (arg.type == 'STRING')): func_translate_args.setdefault(func_id, []).append((arg_kw, @@ -387,6 +385,7 @@ def dump_messages_pytext(messages, check_ctxt): def dump_messages(do_messages, do_checks): import collections + import re def enable_addons(): """For now, enable all official addons, before extracting msgids.""" @@ -417,21 +416,8 @@ def dump_messages(do_messages, do_checks): getattr(cat, op).get_rna() # check for strings like ": %d" - ignore = ("%d", "%f", "%s", "%r", # string formatting - "*", ".", "(", ")", "-", "/", "\\", "+", ":", "#", "%" - "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", - "x", # used on its own eg: 100x200 - "X", "Y", "Z", "W", # used alone. no need to include - ) - - def filter_message(msg): - msg_tmp = msg - for ign in ignore: - msg_tmp = msg_tmp.replace(ign, "") - if not msg_tmp.strip(): - return True - # we could filter out different strings here - return False + ignore_reg = re.compile(r"^(?:[-*.()/\\+:%xWXYZ0-9]|%d|%f|%s|%r|\s)*$") + filter_message = ignore_reg.match messages = getattr(collections, 'OrderedDict', dict)() @@ -501,7 +487,7 @@ def dump_messages(do_messages, do_checks): message_file.write(key.replace("\n", "") + "\n") num_written += 1 - print("Written {} messages to: {} ({} were filtered out)." \ + print("Written {} messages to: {} ({} were filtered out)." "".format(num_written, FILE_NAME_MESSAGES, num_filtered)) @@ -514,17 +500,13 @@ def main(): import sys back_argv = sys.argv + # Get rid of Blender args! sys.argv = sys.argv[sys.argv.index("--") + 1:] import argparse - parser = argparse.ArgumentParser(description="Process UI messages " \ - "from inside Blender.") - parser.add_argument('-c', '--no_checks', default=True, - action="store_false", - help="No checks over UI messages.") - parser.add_argument('-m', '--no_messages', default=True, - action="store_false", - help="No export of UI messages.") + parser = argparse.ArgumentParser(description="Process UI messages from inside Blender.") + parser.add_argument('-c', '--no_checks', default=True, action="store_false", help="No checks over UI messages.") + parser.add_argument('-m', '--no_messages', default=True, action="store_false", help="No export of UI messages.") parser.add_argument('-o', '--output', help="Output messages file path.") args = parser.parse_args() diff --git a/release/scripts/modules/bl_i18n_utils/check_po.py b/release/scripts/modules/bl_i18n_utils/check_po.py index 03a933887c6..2e82047bb95 100755 --- a/release/scripts/modules/bl_i18n_utils/check_po.py +++ b/release/scripts/modules/bl_i18n_utils/check_po.py @@ -162,9 +162,9 @@ def main(): " {} specific context{} present:\n {}\n" "".format(glob_stats["nbr"], glob_stats["lvl"] / glob_stats["nbr"], glob_stats["lvl_ttips"] / glob_stats["nbr"], - glob_stats["lvl_trans_ttips"]/glob_stats["nbr"], - glob_stats["lvl_ttips_in_trans"]/glob_stats["nbr"], - glob_stats["lvl_comm"]/glob_stats["nbr"], glob_stats["nbr_signs"], + glob_stats["lvl_trans_ttips"] / glob_stats["nbr"], + glob_stats["lvl_ttips_in_trans"] / glob_stats["nbr"], + glob_stats["lvl_comm"] / glob_stats["nbr"], glob_stats["nbr_signs"], glob_stats["nbr_trans_signs"], nbr_contexts, _ctx_txt, "\n ".join(glob_stats["contexts"]-{""}))) diff --git a/release/scripts/modules/bl_i18n_utils/import_po_from_branches.py b/release/scripts/modules/bl_i18n_utils/import_po_from_branches.py index a15bea9ef0d..533dded3c57 100755 --- a/release/scripts/modules/bl_i18n_utils/import_po_from_branches.py +++ b/release/scripts/modules/bl_i18n_utils/import_po_from_branches.py @@ -39,6 +39,8 @@ except: TRUNK_PO_DIR = settings.TRUNK_PO_DIR BRANCHES_DIR = settings.BRANCHES_DIR +IMPORT_LANGUAGES_SKIP = settings.IMPORT_LANGUAGES_SKIP + RTL_PREPROCESS_FILE = settings.RTL_PREPROCESS_FILE PY3 = settings.PYTHON3_EXEC @@ -63,7 +65,7 @@ def main(): threshold = float(args.threshold) / 100.0 for lang in os.listdir(BRANCHES_DIR): - if args.langs and lang not in args.langs: + if (args.langs and lang not in args.langs) or lang in IMPORT_LANGUAGES_SKIP: continue po = os.path.join(BRANCHES_DIR, lang, ".".join((lang, "po"))) if os.path.exists(po): diff --git a/release/scripts/modules/bl_i18n_utils/rtl_preprocess.py b/release/scripts/modules/bl_i18n_utils/rtl_preprocess.py index 5ee5c71be8b..d28f87cf042 100755 --- a/release/scripts/modules/bl_i18n_utils/rtl_preprocess.py +++ b/release/scripts/modules/bl_i18n_utils/rtl_preprocess.py @@ -34,6 +34,7 @@ import sys import ctypes +import re try: import settings @@ -87,44 +88,64 @@ FRIBIDI_FLAGS_ARABIC = FRIBIDI_FLAG_SHAPE_ARAB_PRES | \ FRIBIDI_FLAG_SHAPE_ARAB_LIGA +MENU_DETECT_REGEX = re.compile("%x\\d+\\|") + + ##### Kernel processing funcs. ##### def protect_format_seq(msg): """ Find some specific escaping/formating sequences (like \", %s, etc., and protect them from any modification! """ +# LRM = "\u200E" +# RLM = "\u200F" LRE = "\u202A" + RLE = "\u202B" PDF = "\u202C" + LRO = "\u202D" + RLO = "\u202E" + uctrl = {LRE, RLE, PDF, LRO, RLO} # Most likely incomplete, but seems to cover current needs. format_codes = set("tslfd") digits = set(".0123456789") + if not msg: + return msg + elif MENU_DETECT_REGEX.search(msg): + # An ugly "menu" message, just force it whole LRE if not yet done. + if msg[0] not in {LRE, LRO}: + msg = LRE + msg + idx = 0 ret = [] ln = len(msg) while idx < ln: dlt = 1 +# # If we find a control char, skip any additional protection! +# if msg[idx] in uctrl: +# ret.append(msg[idx:]) +# break # \" or \' if idx < (ln - 1) and msg[idx] == '\\' and msg[idx + 1] in "\"\'": dlt = 2 - # %x12 - elif idx < (ln - 2) and msg[idx] == '%' and msg[idx + 1] in "x" and \ - msg[idx + 2] in digits: + # %x12| + elif idx < (ln - 2) and msg[idx] == '%' and msg[idx + 1] in "x" and msg[idx + 2] in digits: dlt = 2 - while (idx + dlt + 1) < ln and msg[idx + dlt + 1] in digits: + while (idx + dlt) < ln and msg[idx + dlt] in digits: + dlt += 1 + if (idx + dlt) < ln and msg[idx + dlt] is '|': dlt += 1 # %.4f elif idx < (ln - 3) and msg[idx] == '%' and msg[idx + 1] in digits: dlt = 2 - while (idx + dlt + 1) < ln and msg[idx + dlt + 1] in digits: + while (idx + dlt) < ln and msg[idx + dlt] in digits: dlt += 1 - if (idx + dlt + 1) < ln and msg[idx + dlt + 1] in format_codes: + if (idx + dlt) < ln and msg[idx + dlt] in format_codes: dlt += 1 else: dlt = 1 # %s - elif idx < (ln - 1) and msg[idx] == '%' and \ - msg[idx + 1] in format_codes: + elif idx < (ln - 1) and msg[idx] == '%' and msg[idx + 1] in format_codes: dlt = 2 if dlt > 1: diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py index d323dd37979..0db3f85f1ff 100644 --- a/release/scripts/modules/bl_i18n_utils/settings.py +++ b/release/scripts/modules/bl_i18n_utils/settings.py @@ -31,10 +31,67 @@ import os.path # MISC ############################################################################### +# The languages defined in Blender. +LANGUAGES_CATEGORIES = ( + # Min completeness level, UI english label. + ( 0.95, "Complete"), + ( 0.33, "In Progress"), + ( -1.0, "Starting"), +) +LANGUAGES = ( + # ID, UI english label, ISO code. + ( 0, "Default (Default)", "DEFAULT", ""), + ( 1, "English (English)", "en_US", "english"), + ( 2, "Japanese (日本語)", "ja_JP", "japanese"), + ( 3, "Dutch (Nederlandse taal)", "nl_NL", "dutch"), + ( 4, "Italian (Italiano)", "it_IT", "italian"), + ( 5, "German (Deutsch)", "de_DE", "german"), + ( 6, "Finnish (Suomi)", "fi_FI", "finnish"), + ( 7, "Swedish (Svenska)", "sv_SE", "swedish"), + ( 8, "French (Français)", "fr_FR", "french"), + ( 9, "Spanish (Español)", "es", "spanish"), + (10, "Catalan (Català)", "ca_AD", "catalan"), + (11, "Czech (Český)", "cs_CZ", "czech"), + (12, "Portuguese (Português)", "pt_PT", "portuguese_portugal"), + (13, "Simplified Chinese (简体中文)", "zh_CN", "Chinese (Simplified)_China.1252"), + (14, "Traditional Chinese (繁體中文)", "zh_TW", "Chinese (Traditional)_China.1252"), + (15, "Russian (Русский)", "ru_RU", "russian"), + (16, "Croatian (Hrvatski)", "hr_HR", "croatian"), + (17, "Serbian (Српски)", "sr_RS", "serbian"), + (18, "Ukrainian (Український)", "uk_UA", "ukrainian"), + (19, "Polish (Polski)", "pl_PL", "polish"), + (20, "Romanian (Român)", "ro_RO", "romanian"), + # Using the utf8 flipped form of Arabic (العربية). + (21, "Arabic (ﺔﻴﺑﺮﻌﻟﺍ)", "ar_EG", "arabic"), + (22, "Bulgarian (Български)", "bg_BG", "bulgarian"), + (23, "Greek (Ελληνικά)", "el_GR", "greek"), + (24, "Korean (한국 언어)", "ko_KR", "korean"), + (25, "Nepali (नेपाली)", "ne_NP", "nepali"), + # Using the utf8 flipped form of Persian (فارسی). + (26, "Persian (ﯽﺳﺭﺎﻓ)", "fa_IR", "farsi"), + (27, "Indonesian (Bahasa indonesia)", "id_ID", "indonesian"), + (28, "Serbian Latin (Srpski latinica)", "sr_RS@latin", "serbian (latin)"), + (29, "Kyrgyz (Кыргыз тили)", "ky_KG", "kyrgyz"), + (30, "Turkish (Türkçe)", "tr_TR", "turkish"), + (31, "Hungarian (Magyar)", "hu_HU", "hungarian"), + (32, "Brazilian Portuguese (Português do Brasil)", "pt_BR", "protuguese_brazil"), + # Using the utf8 flipped form of Hebrew (עִבְרִית)). + (33, "Hebrew (תירִבְעִ)", "he_IL", "hebrew"), + (34, "Estonian (Eestlane)", "et_EE", "estonian"), + (35, "Esperanto (Esperanto)", "eo", "esperanto"), + (36, "Spanish from Spain (Español de España)", "es_ES", "spanish_spain"), +) + +# Name of language file used by Blender to generate translations' menu. +LANGUAGES_FILE = "languages" + # The min level of completeness for a po file to be imported from /branches # into /trunk, as a percentage. -1 means "import everything". IMPORT_MIN_LEVEL = -1 +# Languages in /branches we do not want to import in /trunk currently... +IMPORT_LANGUAGES_SKIP = {'bg', 'ca', 'fi', 'el', 'ko', 'ne', 'pl', 'ro'} + # The comment prefix used in generated messages.txt file. COMMENT_PREFIX = "#~ " @@ -97,12 +154,22 @@ _msg_re = r"(?P" + _str_whole_re.format(_="_msg") + r")" PYGETTEXT_KEYWORDS = (() + tuple((r"{}\(\s*" + _msg_re + r"\s*\)").format(it) for it in ("IFACE_", "TIP_", "N_")) + + tuple((r"{}\(\s*" + _ctxt_re + r"\s*,\s*" + _msg_re + r"\s*\)").format(it) - for it in ("CTX_IFACE_", "CTX_TIP_", "CTX_N_")) + for it in ("CTX_IFACE_", "CTX_TIP_", "CTX_N_")) + + + tuple(("{}\\((?:[^\"',]+,){{1,2}}\\s*" + _msg_re + r"\s*(?:\)|,)").format(it) + for it in ("BKE_report", "BKE_reportf", "BKE_reports_prepend", "BKE_reports_prependf")) + + + tuple(("{}\\((?:[^\"',]+,){{3}}\\s*" + _msg_re + r"\s*,").format(it) + for it in ("BMO_error_raise",)) + + + tuple(("{}\\((?:[^\"',]+,)\\s*" + _msg_re + r"\s*(?:\)|,)").format(it) + for it in ("modifier_setError",)) ) ESCAPE_RE = ( - ('((? + +# Update "languages" text file used by Blender at runtime to build translations menu. + +import os +import sys +import shutil + +try: + import settings + import utils +except: + from . import (settings, utils) + +TRUNK_PO_DIR = settings.TRUNK_PO_DIR +TRUNK_MO_DIR = settings.TRUNK_MO_DIR + +LANGUAGES_CATEGORIES = settings.LANGUAGES_CATEGORIES +LANGUAGES = settings.LANGUAGES +LANGUAGES_FILE = settings.LANGUAGES_FILE + +OK = 0 +MISSING = 1 +TOOLOW = 2 +FORBIDDEN = 3 +FLAG_MESSAGES = { + OK: "", + MISSING: "No translation yet!", + TOOLOW: "Not enough advanced to be included...", + FORBIDDEN: "Explicitly forbidden!", +} + +def find_matching_po(languages, stats, forbidden): + """Match languages defined in LANGUAGES setting to relevant po, if possible!""" + ret = [] + for uid, label, org_key, long_loc in languages: + key = org_key + if key not in stats: + # Try to simplify the key (eg from es_ES to es). + if '_' in org_key: + key = org_key[0:org_key.index('_')] + # For stuff like sr_SR@latin -> sr@latin... + if '@' in org_key: + key = key + org_key[org_key.index('@'):] + if key in stats: + if key in forbidden: + ret.append((stats[key], uid, label, org_key, long_loc, FORBIDDEN)) + else: + ret.append((stats[key], uid, label, org_key, long_loc, OK)) + else: + ret.append((0.0, uid, label, org_key, long_loc, MISSING)) + return ret + +def main(): + import argparse + parser = argparse.ArgumentParser(description="" + "Update 'languages' text file used by Blender at runtime to build translations menu.") + parser.add_argument('-m', '--min_translation', type=int, default=-100, + help="Minimum level of translation, as a percentage " + "(translations below this are commented out in menu).") + parser.add_argument('langs', metavar='ISO_code', nargs='*', + help="Unconditionally exclude those languages from the menu.") + args = parser.parse_args() + + ret = 0 + min_trans = args.min_translation / 100.0 + forbidden = set(args.langs) + # 'DEFAULT' and en_US are always valid, fully-translated "languages"! + stats = {"DEFAULT": 1.0, "en_US": 1.0} + + # Get the "done level" of each po in trunk... + for po in os.listdir(TRUNK_PO_DIR): + if po.endswith(".po") and not po.endswith("_raw.po"): + lang = os.path.basename(po)[:-3] + u1, u2, _stats = utils.parse_messages(os.path.join(TRUNK_PO_DIR, po)) + stats[lang] = _stats["trans_msg"] / _stats["tot_msg"] + + # Generate languages file used by Blender's i18n system. + # First, match all entries in LANGUAGES to a lang in stats, if possible! + stats = find_matching_po(LANGUAGES, stats, forbidden) + limits = sorted(LANGUAGES_CATEGORIES, key=lambda it: it[0], reverse=True) + idx = 0 + stats = sorted(stats, key=lambda it: it[0], reverse=True) + langs_cats = [[] for i in range(len(limits))] + highest_uid = 0 + for prop, uid, label, key, long_loc, flag in stats: + if prop < limits[idx][0]: + # Sub-sort languages by iso-codes. + langs_cats[idx].sort(key=lambda it: it[2]) + idx += 1 + if prop < min_trans and flag == OK: + flag = TOOLOW + langs_cats[idx].append((uid, label, key, long_loc, flag)) + if abs(uid) > highest_uid: + highest_uid = abs(uid) + # Sub-sort last group of languages by iso-codes! + langs_cats[idx].sort(key=lambda it: it[2]) + with open(os.path.join(TRUNK_MO_DIR, LANGUAGES_FILE), 'w', encoding="utf-8") as f: + f.write("# File used by Blender to know which languages (translations) are available, \n") + f.write("# and to generate translation menu.\n") + f.write("#\n") + f.write("# File format:\n") + f.write("# ID:MENULABEL:ISOCODE:WINCODE\n") + f.write("# ID must be unique, except for 0 value (marks categories for menu).\n") + f.write("# Line starting with a # are comments!\n") + f.write("#\n") + f.write("# Automatically generated by bl_i18n_utils/update_languages_menu.py script.\n") + f.write("# Highest ID currently in use: {}\n".format(highest_uid)) + for cat, langs_cat in zip(limits, langs_cats): + f.write("#\n") + # Write "category menu label"... + if langs_cat: + f.write("0:{}::\n".format(cat[1])) + else: + # Do not write the category if it has no language! + f.write("# Void category! #0:{}:\n".format(cat[1])) + # ...and all matching language entries! + for uid, label, key, long_loc, flag in langs_cat: + if flag == OK: + f.write("{}:{}:{}:{}\n".format(uid, label, key, long_loc)) + else: + # Non-existing, commented entry! + f.write("# {} #{}:{}:{}:{}\n".format(FLAG_MESSAGES[flag], uid, label, key, long_loc)) + + +if __name__ == "__main__": + print("\n\n *** Running {} *** \n".format(__file__)) + sys.exit(main()) diff --git a/release/scripts/modules/bl_i18n_utils/update_mo.py b/release/scripts/modules/bl_i18n_utils/update_mo.py index 4a68f19fab0..7f68736593c 100755 --- a/release/scripts/modules/bl_i18n_utils/update_mo.py +++ b/release/scripts/modules/bl_i18n_utils/update_mo.py @@ -69,9 +69,9 @@ def main(): "under {}.".format(TRUNK_MO_DIR)) parser.add_argument('langs', metavar='ISO_code', nargs='*', help="Restrict processed languages to those.") - parser.add_argument('po', help="Only process that po file (implies --mo).", + parser.add_argument('--po', help="Only process that po file (implies --mo).", nargs='?') - parser.add_argument('mo', help="Mo file to generate (implies --po).", + parser.add_argument('--mo', help="Mo file to generate (implies --po).", nargs='?') args = parser.parse_args() @@ -97,6 +97,7 @@ def main(): t = process_po(po, lang) if t: ret = t + return ret diff --git a/release/scripts/modules/bl_i18n_utils/update_pot.py b/release/scripts/modules/bl_i18n_utils/update_pot.py index f98fc5d7705..51197b86678 100755 --- a/release/scripts/modules/bl_i18n_utils/update_pot.py +++ b/release/scripts/modules/bl_i18n_utils/update_pot.py @@ -38,6 +38,9 @@ except: from . import (settings, utils) +LANGUAGES_CATEGORIES = settings.LANGUAGES_CATEGORIES +LANGUAGES = settings.LANGUAGES + COMMENT_PREFIX = settings.COMMENT_PREFIX COMMENT_PREFIX_SOURCE = settings.COMMENT_PREFIX_SOURCE CONTEXT_PREFIX = settings.CONTEXT_PREFIX @@ -117,28 +120,30 @@ def check_file(path, rel_path, messages): def py_xgettext(messages): + forbidden = set() + forced = set() with open(SRC_POTFILES) as src: - forbidden = set() - forced = set() for l in src: if l[0] == '-': forbidden.add(l[1:].rstrip('\n')) elif l[0] != '#': forced.add(l.rstrip('\n')) - for root, dirs, files in os.walk(POTFILES_DIR): - if "/.svn" in root: + for root, dirs, files in os.walk(POTFILES_DIR): + if "/.svn" in root: + continue + for fname in files: + if os.path.splitext(fname)[1] not in PYGETTEXT_ALLOWED_EXTS: continue - for fname in files: - if os.path.splitext(fname)[1] not in PYGETTEXT_ALLOWED_EXTS: - continue - path = os.path.join(root, fname) - rel_path = os.path.relpath(path, SOURCE_DIR) - if rel_path in forbidden | forced: - continue - check_file(path, rel_path, messages) - for path in forced: - if os.path.exists(path): - check_file(os.path.join(SOURCE_DIR, path), path, messages) + path = os.path.join(root, fname) + rel_path = os.path.relpath(path, SOURCE_DIR) + if rel_path in forbidden: + continue + elif rel_path in forced: + forced.remove(rel_path) + check_file(path, rel_path, messages) + for path in forced: + if os.path.exists(path): + check_file(os.path.join(SOURCE_DIR, path), path, messages) # Spell checking! @@ -187,7 +192,7 @@ def get_svnrev(): def gen_empty_pot(): - blender_rev = get_svnrev() + blender_rev = get_svnrev().decode() utctime = time.gmtime() time_str = time.strftime("%Y-%m-%d %H:%M+0000", utctime) year_str = time.strftime("%Y", utctime) @@ -231,8 +236,8 @@ def merge_messages(msgs, states, messages, do_checks, spell_cache): def main(): - parser = argparse.ArgumentParser(description="Update blender.pot file " \ - "from messages.txt") + parser = argparse.ArgumentParser(description="Update blender.pot file from messages.txt and source code parsing, " + "and performs some checks over msgids.") parser.add_argument('-w', '--warning', action="store_true", help="Show warnings.") parser.add_argument('-i', '--input', metavar="File", @@ -250,7 +255,7 @@ def main(): print("Running fake py gettext…") # Not using any more xgettext, simpler to do it ourself! - messages = {} + messages = utils.new_messages() py_xgettext(messages) print("Finished, found {} messages.".format(len(messages))) @@ -259,7 +264,6 @@ def main(): spell_cache = pickle.load(f) else: spell_cache = set() - print(len(spell_cache)) print("Generating POT file {}…".format(FILE_NAME_POT)) msgs, states = gen_empty_pot() @@ -268,7 +272,7 @@ def main(): # add messages collected automatically from RNA print("\tMerging RNA messages from {}…".format(FILE_NAME_MESSAGES)) - messages = {} + messages = utils.new_messages() with open(FILE_NAME_MESSAGES, encoding="utf-8") as f: srcs = [] context = "" @@ -290,11 +294,22 @@ def main(): print("\tMerged {} messages ({} were already present)." "".format(num_added, num_present)) + print("\tAdding languages labels...") + messages = {(CONTEXT_DEFAULT, lng[1]): + ("Languages’ labels from bl_i18n_utils/settings.py",) + for lng in LANGUAGES} + messages.update({(CONTEXT_DEFAULT, cat[1]): + ("Language categories’ labels from bl_i18n_utils/settings.py",) + for cat in LANGUAGES_CATEGORIES}) + num_added, num_present = merge_messages(msgs, states, messages, + True, spell_cache) + tot_messages += num_added + print("\tAdded {} language messages.".format(num_added)) + # Write back all messages into blender.pot. utils.write_messages(FILE_NAME_POT, msgs, states["comm_msg"], states["fuzzy_msg"]) - print(len(spell_cache)) if SPELL_CACHE and spell_cache: with open(SPELL_CACHE, 'wb') as f: pickle.dump(spell_cache, f) diff --git a/release/scripts/modules/bl_i18n_utils/update_trunk.py b/release/scripts/modules/bl_i18n_utils/update_trunk.py index b7f8f375744..9b904ec861a 100755 --- a/release/scripts/modules/bl_i18n_utils/update_trunk.py +++ b/release/scripts/modules/bl_i18n_utils/update_trunk.py @@ -35,34 +35,55 @@ import shutil try: import settings + import utils except: - from . import settings + from . import (settings, utils) +BRANCHES_DIR = settings.BRANCHES_DIR TRUNK_PO_DIR = settings.TRUNK_PO_DIR TRUNK_MO_DIR = settings.TRUNK_MO_DIR +LANGUAGES_CATEGORIES = settings.LANGUAGES_CATEGORIES +LANGUAGES = settings.LANGUAGES +LANGUAGES_FILE = settings.LANGUAGES_FILE + PY3 = settings.PYTHON3_EXEC +def find_matching_po(languages, stats): + """Match languages defined in LANGUAGES setting to relevant po, if possible!""" + ret = [] + for uid, label, org_key in languages: + key = org_key + if key not in stats: + # Try to simplify the key (eg from es_ES to es). + if '_' in org_key: + key = org_key[0:org_key.index('_')] + if '@' in org_key: + key = key + org_key[org_key.index('@'):] + if key in stats: + ret.append((stats[key], uid, label, org_key)) + else: + # Mark invalid entries, so that we can put them in the languages file, + # but commented! + ret.append((0.0, -uid, label, org_key)) + return ret + def main(): import argparse - parser = argparse.ArgumentParser(description="" \ - "Update trunk from branches:\n" \ - "* Remove po’s in trunk.\n" \ - "* Copy po’s from branches advanced enough.\n" \ - "* Clean po’s in trunk.\n" \ - "* Compile po’s in trunk in mo’s, keeping " \ - "track of those failing.\n" \ - "* Remove po’s and mo’s (and their dir’s) that " \ - "failed to compile or are no more present in trunk.") - parser.add_argument('-t', '--threshold', type=int, - help="Import threshold, as a percentage.") - parser.add_argument('-p', '--po', action="store_false", - help="Do not remove failing po’s.") - parser.add_argument('-m', '--mo', action="store_false", - help="Do not remove failing mo’s.") - parser.add_argument('langs', metavar='ISO_code', nargs='*', - help="Restrict processed languages to those.") + parser = argparse.ArgumentParser(description="" + "Update trunk from branches:\n" + "* Remove po’s in trunk.\n" + "* Copy po’s from branches advanced enough.\n" + "* Clean po’s in trunk.\n" + "* Compile po’s in trunk in mo’s, keeping track of those failing.\n" + "* Remove po’s and mo’s (and their dir’s) that " + "failed to compile or are no more present in trunk." + "* Generate languages file used by Blender's i18n.") + parser.add_argument('-t', '--threshold', type=int, help="Import threshold, as a percentage.") + parser.add_argument('-p', '--po', action="store_true", help="Remove failing po’s.") + parser.add_argument('-m', '--mo', action="store_true", help="Remove failing mo’s.") + parser.add_argument('langs', metavar='ISO_code', nargs='*', help="Restrict processed languages to those.") args = parser.parse_args() ret = 0 @@ -89,7 +110,7 @@ def main(): # Add in failed all mo’s no more having relevant po’s in trunk. for lang in os.listdir(TRUNK_MO_DIR): - if lang == ".svn": + if lang in {".svn", LANGUAGES_FILE}: continue # !!! if not os.path.exists(os.path.join(TRUNK_PO_DIR, ".".join((lang, "po")))): failed.add(lang) @@ -115,6 +136,13 @@ def main(): if t: ret = t failed.add(lang) + continue + + # Generate languages file used by Blender's i18n system. + cmd = [PY3, "./update_languages_menu.py"] + t = subprocess.call(cmd) + if t: + ret = t # Remove failing po’s, mo’s and related dir’s. for lang in failed: diff --git a/release/scripts/modules/bl_i18n_utils/utils.py b/release/scripts/modules/bl_i18n_utils/utils.py index 3e5394d85a4..9481f750092 100644 --- a/release/scripts/modules/bl_i18n_utils/utils.py +++ b/release/scripts/modules/bl_i18n_utils/utils.py @@ -41,6 +41,10 @@ def is_tooltip(msgid): return len(msgid) > 30 +def new_messages(): + return getattr(collections, 'OrderedDict', dict)() + + def parse_messages(fname): """ Returns a tupple (messages, states, stats). @@ -78,7 +82,7 @@ def parse_messages(fname): msgctxt_lines = [] comment_lines = [] - messages = getattr(collections, 'OrderedDict', dict)() + messages = new_messages() translated_messages = set() fuzzy_messages = set() commented_messages = set() @@ -95,7 +99,6 @@ def parse_messages(fname): msgctxt_lines = [] comment_lines = [] - def finalize_message(): nonlocal reading_msgid, reading_msgstr, reading_msgctxt, \ reading_comment, is_fuzzy, is_translated, is_commented, \ @@ -225,7 +228,6 @@ def parse_messages(fname): if reading_msgstr: finalize_message() - return (messages, {"trans_msg": translated_messages, "fuzzy_msg": fuzzy_messages, @@ -284,7 +286,7 @@ def gen_empty_messages(blender_rev, time_str, year_str): """Generate an empty messages & state data (only header if present!).""" header_key = ("", "") - messages = getattr(collections, 'OrderedDict', dict)() + messages = new_messages() messages[header_key] = { "msgid_lines": [""], "msgctxt_lines": [], diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py index 41fe052c434..d32b69b501c 100644 --- a/release/scripts/modules/bpy/path.py +++ b/release/scripts/modules/bpy/path.py @@ -264,8 +264,8 @@ def module_names(path, recursive=False): if recursive: for mod_name, mod_path in module_names(directory, True): modules.append(("%s.%s" % (filename, mod_name), - mod_path, - )) + mod_path, + )) return modules diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py index e24b61a757d..573694ff08e 100644 --- a/release/scripts/modules/bpy/utils.py +++ b/release/scripts/modules/bpy/utils.py @@ -59,6 +59,7 @@ import addon_utils as _addon_utils _script_module_dirs = "startup", "modules" + def _test_import(module_name, loaded_modules): use_time = _bpy.app.debug_python @@ -615,12 +616,15 @@ def _blender_default_map(): # hooks for doc lookups _manual_map = [_blender_default_map] + def register_manual_map(manual_hook): _manual_map.append(manual_hook) + def unregister_manual_map(manual_hook): _manual_map.remove(manual_hook) + def manual_map(): # reverse so default is called last for cb in reversed(_manual_map): @@ -633,4 +637,3 @@ def manual_map(): continue yield prefix, url_manual_mapping - diff --git a/release/scripts/modules/bpy_extras/mesh_utils.py b/release/scripts/modules/bpy_extras/mesh_utils.py index ad0fe06b68b..ad3cf8c08ec 100644 --- a/release/scripts/modules/bpy_extras/mesh_utils.py +++ b/release/scripts/modules/bpy_extras/mesh_utils.py @@ -232,7 +232,7 @@ def edge_loops_from_tessfaces(mesh, tessfaces=None, seams=()): ed_adj = edges[context_loop[-1]] if len(ed_adj) != 2: # the original edge had 2 other edges - if other_dir and flipped == False: + if other_dir and flipped is False: flipped = True # only flip the list once context_loop.reverse() ed_adj[:] = [] diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py index b1de1fd47a4..46731b807f7 100644 --- a/release/scripts/modules/bpy_extras/object_utils.py +++ b/release/scripts/modules/bpy_extras/object_utils.py @@ -187,3 +187,16 @@ class AddObjectHelper: name="Rotation", subtype='EULER', ) + + +def object_add_grid_scale(context): + """ + Return scale which should be applied on object data to align it to grid scale + """ + + space_data = context.space_data + + if space_data and space_data.type == 'VIEW_3D': + return space_data.grid_scale_unit + + return 1.0 diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index 9ad9a7affc3..4cd823d9184 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -689,10 +689,10 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta): files = [] for directory in searchpaths: files.extend([(f, os.path.join(directory, f)) - for f in os.listdir(directory) - if (not f.startswith(".")) - if ((filter_ext is None) or - (filter_ext(os.path.splitext(f)[1]))) + for f in os.listdir(directory) + if (not f.startswith(".")) + if ((filter_ext is None) or + (filter_ext(os.path.splitext(f)[1]))) ]) files.sort() diff --git a/release/scripts/modules/bpyml.py b/release/scripts/modules/bpyml.py index 42d2bf94fba..e942006010b 100644 --- a/release/scripts/modules/bpyml.py +++ b/release/scripts/modules/bpyml.py @@ -160,7 +160,7 @@ if __name__ == "__main__": from bpyml_test import * draw = [ - ui()[ + ui()[ split()[ column()[ prop(data='context.scene.render', property='use_stamp_time', text='Time'), diff --git a/release/scripts/modules/console_python.py b/release/scripts/modules/console_python.py index 6e8fee07c0f..60dfa2b6344 100644 --- a/release/scripts/modules/console_python.py +++ b/release/scripts/modules/console_python.py @@ -30,7 +30,7 @@ _BPY_MAIN_OWN = True def add_scrollback(text, text_type): for l in text.split("\n"): bpy.ops.console.scrollback_append(text=l.replace("\t", " "), - type=text_type) + type=text_type) def replace_help(namespace): @@ -195,7 +195,7 @@ def execute(context): # insert a new blank line bpy.ops.console.history_append(text="", current_character=0, - remove_duplicates=True) + remove_duplicates=True) # Insert the output into the editor # not quite correct because the order might have changed, @@ -294,8 +294,8 @@ def copy_as_script(context): sc = context.space_data lines = [ "import bpy", - "import bpy.context as C", - "import bpy.data as D", + "from bpy import data as D", + "from bpy import context as C", "from mathutils import *", "from math import *", "", @@ -304,7 +304,7 @@ def copy_as_script(context): for line in sc.scrollback: text = line.body type = line.type - + if type == 'INFO': # ignore autocomp. continue if type == 'INPUT': diff --git a/release/scripts/modules/console_shell.py b/release/scripts/modules/console_shell.py index 8beff24eedb..42348f453cd 100644 --- a/release/scripts/modules/console_shell.py +++ b/release/scripts/modules/console_shell.py @@ -26,7 +26,7 @@ language_id = "shell" def add_scrollback(text, text_type): for l in text.split("\n"): bpy.ops.console.scrollback_append(text=l.replace("\t", " "), - type=text_type) + type=text_type) def shell_run(text): @@ -57,7 +57,7 @@ def execute(context): # insert a new blank line bpy.ops.console.history_append(text="", current_character=0, - remove_duplicates=True) + remove_duplicates=True) sc.prompt = os.getcwd() + PROMPT return {'FINISHED'} diff --git a/release/scripts/modules/rna_info.py b/release/scripts/modules/rna_info.py index 0ef2ac5164d..6f4b63fc99a 100644 --- a/release/scripts/modules/rna_info.py +++ b/release/scripts/modules/rna_info.py @@ -249,7 +249,7 @@ class InfoPropertyRNA: def get_arg_default(self, force=True): default = self.default_str - if default and (force or self.is_required == False): + if default and (force or self.is_required is False): return "%s=%s" % (self.identifier, default) return self.identifier @@ -493,7 +493,7 @@ def BuildRNAInfo(): # Arrange so classes are always defined in the correct order deps_ok = False - while deps_ok == False: + while deps_ok is False: deps_ok = True rna_done = set() diff --git a/release/scripts/modules/rna_xml.py b/release/scripts/modules/rna_xml.py index a259a4ec396..fc8e3125228 100644 --- a/release/scripts/modules/rna_xml.py +++ b/release/scripts/modules/rna_xml.py @@ -250,14 +250,17 @@ def xml2rna(root_xml, if value_xml.startswith("#"): # read hexidecimal value as float array value_xml_split = value_xml[1:] - value_xml_coerce = [int(value_xml_split[i:i + 2], 16) / 255 for i in range(0, len(value_xml_split), 2)] + value_xml_coerce = [int(value_xml_split[i:i + 2], 16) / 255 for i in range(0, len(value_xml_split), 2)] del value_xml_split else: value_xml_split = value_xml.split() try: value_xml_coerce = [int(v) for v in value_xml_split] except ValueError: - value_xml_coerce = [float(v) for v in value_xml_split] + try: + value_xml_coerce = [float(v) for v in value_xml_split] + except ValueError: # bool vector property + value_xml_coerce = [{'TRUE': True, 'FALSE': False}[v] for v in value_xml_split] del value_xml_split tp_name = 'ARRAY' diff --git a/release/scripts/presets/interface_theme/back_to_black.xml b/release/scripts/presets/interface_theme/back_to_black.xml index 24f135e8548..805aa9bd184 100644 --- a/release/scripts/presets/interface_theme/back_to_black.xml +++ b/release/scripts/presets/interface_theme/back_to_black.xml @@ -9,6 +9,7 @@ handle_auto="#909000" handle_sel_auto="#f0ff40" bone_pose="#50c8ff" + bone_pose_active="#8cffff" bone_solid="#c8c8c8" bundle_solid="#c8c8c8" camera="#000000" diff --git a/release/scripts/presets/interface_theme/blender_24x.xml b/release/scripts/presets/interface_theme/blender_24x.xml index 79d1ed4ecf4..232276e300e 100644 --- a/release/scripts/presets/interface_theme/blender_24x.xml +++ b/release/scripts/presets/interface_theme/blender_24x.xml @@ -9,6 +9,7 @@ handle_auto="#909000" handle_sel_auto="#f0ff40" bone_pose="#50c8ff" + bone_pose_active="#8cffff" bone_solid="#c8c8c8" bundle_solid="#c8c8c8" camera="#000000" diff --git a/release/scripts/presets/interface_theme/elsyiun.xml b/release/scripts/presets/interface_theme/elsyiun.xml index bfeb3a0175e..581f5ce82d6 100644 --- a/release/scripts/presets/interface_theme/elsyiun.xml +++ b/release/scripts/presets/interface_theme/elsyiun.xml @@ -9,6 +9,7 @@ handle_auto="#909000" handle_sel_auto="#f0ff40" bone_pose="#50c8ff" + bone_pose_active="#8cffff" bone_solid="#c8c8c8" bundle_solid="#c8c8c8" camera="#000000" @@ -282,7 +283,7 @@ - + wire="#93237f"> @@ -70,7 +71,7 @@ - @@ -108,14 +109,14 @@ - + + view_sliders="#9c9c9c"> + list_text="#e2e2e2" + list_text_hi="#f47421" + list_title="#ffffff"> @@ -174,8 +175,8 @@ selected_file="#6b395a" tiles="#3c3b37"> - + list_text="#e2e2e2" + list_text_hi="#f47421" + list_title="#ffffff"> @@ -264,7 +265,7 @@ vertex_size="3"> + back="#29001b"> @@ -332,7 +333,7 @@ view_sliders="#969696"> - + syntax_numbers="#972144" + syntax_string="#6e00ff"> @@ -531,13 +532,13 @@ + text="#dddddd" + text_sel="#dddddd"> @@ -573,7 +574,7 @@ shadetop="20" show_shaded="TRUE" text="#dfdbcf" - text_sel="#fffbed"> + text_sel="#f47421"> @@ -614,7 +615,7 @@ shadetop="25" show_shaded="FALSE" text="#dddddd" - text_sel="#fff7fb"> + text_sel="#ffffff"> @@ -626,7 +627,7 @@ shadetop="5" show_shaded="TRUE" text="#dfdbcf" - text_sel="#ffffff"> + text_sel="#dfdbcf"> @@ -638,16 +639,16 @@ shadetop="21" show_shaded="TRUE" text="#dfdfdf" - text_sel="#ffffff"> + text_sel="#dfdfdf"> - @@ -684,7 +685,7 @@ shadetop="-10" show_shaded="TRUE" text="#dfdbcf" - text_sel="#fffaec"> + text_sel="#ffffff"> @@ -720,7 +721,7 @@ shadetop="25" show_shaded="FALSE" text="#ffffff" - text_sel="#ffffff"> + text_sel="#ff5d0d"> diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py index fe011a51e22..b5df519cf59 100644 --- a/release/scripts/presets/keyconfig/maya.py +++ b/release/scripts/presets/keyconfig/maya.py @@ -133,42 +133,42 @@ kmi = km.keymap_items.new('wm.context_toggle_enum', 'Z', 'PRESS', alt=True) kmi.properties.data_path = 'space_data.viewport_shade' kmi.properties.value_1 = 'TEXTURED' kmi.properties.value_2 = 'SOLID' -kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'PRESS') +kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE') kmi.properties.extend = False kmi.properties.center = False kmi.properties.object = False kmi.properties.enumerate = False -kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True) +kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', shift=True) kmi.properties.extend = True kmi.properties.center = False kmi.properties.object = False kmi.properties.enumerate = False -kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'PRESS', ctrl=True) +kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', ctrl=True) kmi.properties.extend = False kmi.properties.center = True kmi.properties.object = False kmi.properties.enumerate = False -kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'PRESS', alt=True) +kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', alt=True) kmi.properties.extend = False kmi.properties.center = False kmi.properties.object = False kmi.properties.enumerate = True -kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True) +kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', shift=True, ctrl=True) kmi.properties.extend = True kmi.properties.center = True kmi.properties.object = False kmi.properties.enumerate = False -kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True) +kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', ctrl=True, alt=True) kmi.properties.extend = False kmi.properties.center = True kmi.properties.object = False kmi.properties.enumerate = True -kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True, alt=True) +kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', shift=True, alt=True) kmi.properties.extend = True kmi.properties.center = False kmi.properties.object = False kmi.properties.enumerate = True -kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True) +kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'RELEASE', shift=True, ctrl=True, alt=True) kmi.properties.extend = True kmi.properties.center = True kmi.properties.object = False diff --git a/release/scripts/presets/tracking_settings/blurry_footage.py b/release/scripts/presets/tracking_settings/blurry_footage.py index 0423f7662a2..de6f085f53d 100644 --- a/release/scripts/presets/tracking_settings/blurry_footage.py +++ b/release/scripts/presets/tracking_settings/blurry_footage.py @@ -14,4 +14,4 @@ settings.default_margin = 0 settings.use_default_red_channel = True settings.use_default_green_channel = True settings.use_default_blue_channel = True -settings.default_correlation_min = 0.6 \ No newline at end of file +settings.default_correlation_min = 0.6 diff --git a/release/scripts/presets/tracking_settings/default.py b/release/scripts/presets/tracking_settings/default.py index 0aef22195e7..3c61ea7cd7f 100644 --- a/release/scripts/presets/tracking_settings/default.py +++ b/release/scripts/presets/tracking_settings/default.py @@ -14,4 +14,4 @@ settings.default_margin = 0 settings.use_default_red_channel = True settings.use_default_green_channel = True settings.use_default_blue_channel = True -settings.default_correlation_min = 0.75 \ No newline at end of file +settings.default_correlation_min = 0.75 diff --git a/release/scripts/presets/tracking_settings/fast_motion.py b/release/scripts/presets/tracking_settings/fast_motion.py index f7f6b37db74..6051f235b0c 100644 --- a/release/scripts/presets/tracking_settings/fast_motion.py +++ b/release/scripts/presets/tracking_settings/fast_motion.py @@ -14,4 +14,4 @@ settings.default_margin = 0 settings.use_default_red_channel = True settings.use_default_green_channel = True settings.use_default_blue_channel = True -settings.default_correlation_min = 0.6 \ No newline at end of file +settings.default_correlation_min = 0.6 diff --git a/release/scripts/presets/tracking_settings/planar.py b/release/scripts/presets/tracking_settings/planar.py index b25df1fc466..49a64046002 100644 --- a/release/scripts/presets/tracking_settings/planar.py +++ b/release/scripts/presets/tracking_settings/planar.py @@ -14,4 +14,4 @@ settings.default_margin = 0 settings.use_default_red_channel = True settings.use_default_green_channel = True settings.use_default_blue_channel = True -settings.default_correlation_min = 0.75 \ No newline at end of file +settings.default_correlation_min = 0.75 diff --git a/release/scripts/startup/bl_operators/add_mesh_torus.py b/release/scripts/startup/bl_operators/add_mesh_torus.py index 6c48ae72e4b..552247f0940 100644 --- a/release/scripts/startup/bl_operators/add_mesh_torus.py +++ b/release/scripts/startup/bl_operators/add_mesh_torus.py @@ -49,9 +49,9 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg): angle = 2 * pi * minor_index / minor_seg vec = quat * Vector((major_rad + (cos(angle) * minor_rad), - 0.0, - (sin(angle) * minor_rad), - )) + 0.0, + (sin(angle) * minor_rad), + )) verts.extend(vec[:]) @@ -133,13 +133,15 @@ class AddTorus(Operator, object_utils.AddObjectHelper): ) def execute(self, context): - if self.use_abso == True: + grid_scale = object_utils.object_add_grid_scale(context) + + if self.use_abso is True: extra_helper = (self.abso_major_rad - self.abso_minor_rad) * 0.5 self.major_radius = self.abso_minor_rad + extra_helper self.minor_radius = extra_helper - verts_loc, faces = add_torus(self.major_radius, - self.minor_radius, + verts_loc, faces = add_torus(self.major_radius * grid_scale, + self.minor_radius * grid_scale, self.major_segments, self.minor_segments) diff --git a/release/scripts/startup/bl_operators/anim.py b/release/scripts/startup/bl_operators/anim.py index 98bad276109..902c7007fb9 100644 --- a/release/scripts/startup/bl_operators/anim.py +++ b/release/scripts/startup/bl_operators/anim.py @@ -189,7 +189,7 @@ class BakeAction(Operator): name="Only Selected", default=True, ) - clear_consraints = BoolProperty( + clear_constraints = BoolProperty( name="Clear Constraints", default=False, ) @@ -212,9 +212,9 @@ class BakeAction(Operator): self.only_selected, 'POSE' in self.bake_types, 'OBJECT' in self.bake_types, - self.clear_consraints, + self.clear_constraints, True, - ) + ) if action is None: self.report({'INFO'}, "Nothing to bake") @@ -252,8 +252,8 @@ class ClearUselessActions(Operator): for action in bpy.data.actions: # if only user is "fake" user... - if ((self.only_unused is False) or - (action.use_fake_user and action.users == 1)): + if ((self.only_unused is False) or + (action.use_fake_user and action.users == 1)): # if it has F-Curves, then it's a "action library" # (i.e. walk, wave, jump, etc.) diff --git a/release/scripts/startup/bl_operators/clip.py b/release/scripts/startup/bl_operators/clip.py index c45d2f2e702..70967a01d1c 100644 --- a/release/scripts/startup/bl_operators/clip.py +++ b/release/scripts/startup/bl_operators/clip.py @@ -57,7 +57,7 @@ def CLIP_set_viewport_background(context, all_screens, clip, clip_user): space_v3d.show_background_images = True CLIP_spaces_walk(context, all_screens, 'VIEW_3D', 'VIEW_3D', - set_background, clip, clip_user) + set_background, clip, clip_user) def CLIP_camera_for_clip(context, clip): @@ -329,7 +329,7 @@ object's movement caused by this constraint""" if not con: self.report({'ERROR'}, - "Motion Tracking constraint to be converted not found") + "Motion Tracking constraint to be converted not found") return {'CANCELLED'} @@ -341,7 +341,7 @@ object's movement caused by this constraint""" if not clip: self.report({'ERROR'}, - "Movie clip to use tracking data from isn't set") + "Movie clip to use tracking data from isn't set") return {'CANCELLED'} @@ -461,9 +461,9 @@ class CLIP_OT_setup_tracking_scene(Operator): scene.camera = camob camob.matrix_local = (Matrix.Translation((7.481, -6.508, 5.344)) * - Matrix.Rotation(0.815, 4, 'Z') * - Matrix.Rotation(0.011, 4, 'Y') * - Matrix.Rotation(1.109, 4, 'X')) + Matrix.Rotation(0.815, 4, 'Z') * + Matrix.Rotation(0.011, 4, 'Y') * + Matrix.Rotation(1.109, 4, 'X')) return camob @@ -629,7 +629,7 @@ class CLIP_OT_setup_tracking_scene(Operator): if need_stabilization: tree.links.new(distortion.outputs["Image"], - stabilize.inputs["Image"]) + stabilize.inputs["Image"]) tree.links.new(stabilize.outputs["Image"], scale.inputs["Image"]) else: tree.links.new(distortion.outputs["Image"], scale.inputs["Image"]) diff --git a/release/scripts/startup/bl_operators/console.py b/release/scripts/startup/bl_operators/console.py index fd95da02b28..307165a4d18 100644 --- a/release/scripts/startup/bl_operators/console.py +++ b/release/scripts/startup/bl_operators/console.py @@ -129,6 +129,6 @@ class ConsoleLanguage(Operator): # insert a new blank line bpy.ops.console.history_append(text="", current_character=0, - remove_duplicates=True) + remove_duplicates=True) return {'FINISHED'} diff --git a/release/scripts/startup/bl_operators/mesh.py b/release/scripts/startup/bl_operators/mesh.py index 3dc25d84aca..df21349da47 100644 --- a/release/scripts/startup/bl_operators/mesh.py +++ b/release/scripts/startup/bl_operators/mesh.py @@ -92,7 +92,7 @@ class MeshMirrorUV(Operator): puvs[i] = tuple(uv.uv for uv in uv_loops[lstart:lend]) puvs_cpy[i] = tuple(uv.copy() for uv in puvs[i]) puvsel[i] = (False not in - (uv.select for uv in uv_loops[lstart:lend])) + (uv.select for uv in uv_loops[lstart:lend])) # Vert idx of the poly. vidxs[i] = tuple(l.vertex_index for l in loops[lstart:lend]) # As we have no poly.center yet... diff --git a/release/scripts/startup/bl_operators/node.py b/release/scripts/startup/bl_operators/node.py index ee005fcb8bb..fb264cb3429 100644 --- a/release/scripts/startup/bl_operators/node.py +++ b/release/scripts/startup/bl_operators/node.py @@ -22,12 +22,16 @@ import bpy from bpy.types import Operator from bpy.props import EnumProperty -# XXX These node item lists should actually be generated by a callback at operator execution time (see node_type_items below), -# using the active node tree from the context. Due to a difficult bug in bpy this is not possible (item list memory gets freed too early), +# XXX These node item lists should actually be generated by a callback at +# operator execution time (see node_type_items below), +# using the active node tree from the context. +# Due to a difficult bug in bpy this is not possible +# (item list memory gets freed too early), # so for now just copy the static item lists to these global variables. # -# In the custom_nodes branch, the static per-tree-type node items are replaced by a single independent type list anyway (with a poll function -# to limit node types to the respective trees). So this workaround is only temporary. +# In the custom_nodes branch, the static per-tree-type node items are replaced +# by a single independent type list anyway (with a poll function to limit node +# types to the respective trees). So this workaround is only temporary. # lazy init node_type_items_dict = {} @@ -39,18 +43,21 @@ node_group_prefix = 'GROUP_' # Generate a list of enum items for a given node class # Copy existing type enum, adding a prefix to distinguish from node groups -# Skip the base node group type, node groups will be added below for all existing group trees +# Skip the base node group type, +# node groups will be added below for all existing group trees def node_type_items(node_class): return [(node_type_prefix + item.identifier, item.name, item.description) - for item in node_class.bl_rna.properties['type'].enum_items if item.identifier != 'GROUP'] + for item in node_class.bl_rna.properties['type'].enum_items + if item.identifier != 'GROUP'] # Generate items for node group types # Filter by the given tree_type -# Node group trees don't have a description property yet (could add this as a custom property though) +# Node group trees don't have a description property yet +# (could add this as a custom property though) def node_group_items(tree_type): return [(node_group_prefix + group.name, group.name, '') - for group in bpy.data.node_groups if group.type == tree_type] + for group in bpy.data.node_groups if group.type == tree_type] # Returns the enum item list for the edited tree in the context @@ -71,7 +78,11 @@ def node_type_items_cb(self, context): }) # XXX Does not work correctly, see comment above - #return [(item.identifier, item.name, item.description, item.value) for item in tree.nodes.bl_rna.functions['new'].parameters['type'].enum_items] + ''' + return [(item.identifier, item.name, item.description, item.value) + for item in + tree.nodes.bl_rna.functions['new'].parameters['type'].enum_items] + ''' if tree.type in node_type_items_dict: return node_type_items_dict[tree.type] + node_group_items(tree.type) @@ -85,7 +96,8 @@ class NODE_OT_add_search(Operator): bl_label = "Search and Add Node" bl_options = {'REGISTER', 'UNDO'} - # XXX this should be called 'node_type' but the operator search property is hardcoded to 'type' by a hack in bpy_operator_wrap.c ... + # XXX this should be called 'node_type' but the operator search + # property is hardcoded to 'type' by a hack in bpy_operator_wrap.c ... type = EnumProperty( name="Node Type", description="Node type", @@ -98,14 +110,17 @@ class NODE_OT_add_search(Operator): space = context.space_data tree = space.edit_tree - # Enum item identifier has an additional prefix to distinguish base node types from node groups + # Enum item identifier has an additional prefix to + # distinguish base node types from node groups item = self.type if item.startswith(node_type_prefix): # item means base node type node = tree.nodes.new(type=item[len(node_type_prefix):]) elif item.startswith(node_group_prefix): # item means node group type - node = tree.nodes.new(type='GROUP', group=bpy.data.node_groups[item[len(node_group_prefix):]]) + node = tree.nodes.new( + type='GROUP', + group=bpy.data.node_groups[item[len(node_group_prefix):]]) else: return None @@ -133,7 +148,8 @@ class NODE_OT_add_search(Operator): v2d = context.region.view2d # convert mouse position to the View2D for later node placement - space.cursor_location = v2d.region_to_view(event.mouse_region_x, event.mouse_region_y) + space.cursor_location = v2d.region_to_view(event.mouse_region_x, + event.mouse_region_y) context.window_manager.invoke_search_popup(self) return {'CANCELLED'} diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py index 5000d718182..4e90f2e8585 100644 --- a/release/scripts/startup/bl_operators/object.py +++ b/release/scripts/startup/bl_operators/object.py @@ -408,13 +408,13 @@ class ShapeTransfer(Operator): n2loc_to = v2_to + target_normals[i2] * edlen_to pt = barycentric_transform(orig_shape_coords[i1], - v2, v1, n1loc, - v2_to, v1_to, n1loc_to) + v2, v1, n1loc, + v2_to, v1_to, n1loc_to) median_coords[i1].append(pt) pt = barycentric_transform(orig_shape_coords[i2], - v1, v2, n2loc, - v1_to, v2_to, n2loc_to) + v1, v2, n2loc, + v1_to, v2_to, n2loc_to) median_coords[i2].append(pt) # apply the offsets to the new shape @@ -507,7 +507,7 @@ class JoinUVs(Operator): if obj_other != obj and obj_other.type == 'MESH': mesh_other = obj_other.data if mesh_other != mesh: - if mesh_other.tag == False: + if mesh_other.tag is False: mesh_other.tag = True if len(mesh_other.loops) != nbr_loops: @@ -520,7 +520,7 @@ class JoinUVs(Operator): len(mesh_other.polygons), nbr_loops, ), - ) + ) else: uv_other = mesh_other.uv_layers.active if not uv_other: diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py index 35b496b6dd0..cd0b63a6b78 100644 --- a/release/scripts/startup/bl_operators/object_quick_effects.py +++ b/release/scripts/startup/bl_operators/object_quick_effects.py @@ -299,7 +299,6 @@ class QuickSmoke(Operator): style = EnumProperty( name="Smoke Style", items=(('STREAM', "Stream", ""), - ('PUFF', "Puff", ""), ('FIRE', "Fire", ""), ), default='STREAM', @@ -328,20 +327,9 @@ class QuickSmoke(Operator): bpy.ops.object.modifier_add(fake_context, type='SMOKE') obj.modifiers[-1].smoke_type = 'FLOW' - psys = obj.particle_systems[-1] - if self.style == 'PUFF': - psys.settings.frame_end = psys.settings.frame_start - psys.settings.emit_from = 'VOLUME' - psys.settings.distribution = 'RAND' - elif self.style == 'FIRE': - psys.settings.effector_weights.gravity = -1 - psys.settings.lifetime = 5 - psys.settings.count = 100000 + if self.style == 'FIRE': + obj.modifiers[-1].flow_settings.smoke_flow_type = 'FIRE' - obj.modifiers[-2].flow_settings.initial_velocity = True - obj.modifiers[-2].flow_settings.temperature = 2 - - psys.settings.use_render_emitter = self.show_flows if not self.show_flows: obj.draw_type = 'WIRE' @@ -361,8 +349,6 @@ class QuickSmoke(Operator): bpy.ops.object.modifier_add(type='SMOKE') obj.modifiers[-1].smoke_type = 'DOMAIN' if self.style == 'FIRE': - obj.modifiers[-1].domain_settings.use_dissolve_smoke = True - obj.modifiers[-1].domain_settings.dissolve_speed = 20 obj.modifiers[-1].domain_settings.use_high_resolution = True # create a volume material with a voxel data texture for the domain @@ -373,6 +359,7 @@ class QuickSmoke(Operator): mat.type = 'VOLUME' mat.volume.density = 0 mat.volume.density_scale = 5 + mat.volume.step_size = 0.1 tex = bpy.data.textures.new("Smoke Density", 'VOXEL_DATA') tex.voxel_data.domain_object = obj @@ -381,29 +368,35 @@ class QuickSmoke(Operator): tex_slot.texture = tex tex_slot.use_map_color_emission = False tex_slot.use_map_density = True + tex_slot.use_map_color_reflection = True - # for fire add a second texture for emission and emission color - if self.style == 'FIRE': - mat.volume.emission = 5 - tex = bpy.data.textures.new("Smoke Heat", 'VOXEL_DATA') - tex.voxel_data.domain_object = obj - tex.use_color_ramp = True + # for fire add a second texture for flame emission + mat.volume.emission_color = Vector((0.0, 0.0, 0.0)) + tex = bpy.data.textures.new("Flame", 'VOXEL_DATA') + tex.voxel_data.domain_object = obj + tex.voxel_data.smoke_data_type = 'SMOKEFLAME' + tex.use_color_ramp = True - tex_slot = mat.texture_slots.add() - tex_slot.texture = tex + tex_slot = mat.texture_slots.add() + tex_slot.texture = tex - ramp = tex.color_ramp + # add color ramp for flame color + ramp = tex.color_ramp + # dark orange + elem = ramp.elements.new(0.333) + elem.color[0] = 0.2 + elem.color[1] = 0.03 + elem.color[2] = 0 + elem.color[3] = 1 + # yellow glow + elem = ramp.elements.new(0.666) + elem.color[0] = elem.color[3] = 1 + elem.color[1] = 0.65 + elem.color[2] = 0.25 - elem = ramp.elements.new(0.333) - elem.color[0] = elem.color[3] = 1 - elem.color[1] = elem.color[2] = 0 - - elem = ramp.elements.new(0.666) - elem.color[0] = elem.color[1] = elem.color[3] = 1 - elem.color[2] = 0 - - mat.texture_slots[1].use_map_emission = True - mat.texture_slots[1].blend_type = 'MULTIPLY' + mat.texture_slots[1].use_map_density = True + mat.texture_slots[1].use_map_emission = True + mat.texture_slots[1].emission_factor = 5 return {'FINISHED'} diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py index db492450e28..b7adf53dbf1 100644 --- a/release/scripts/startup/bl_operators/presets.py +++ b/release/scripts/startup/bl_operators/presets.py @@ -185,10 +185,12 @@ class ExecutePreset(Operator): filepath = StringProperty( subtype='FILE_PATH', + options={'SKIP_SAVE'}, ) menu_idname = StringProperty( name="Menu ID Name", description="ID name of the menu this was called from", + options={'SKIP_SAVE'}, ) def execute(self, context): @@ -436,19 +438,19 @@ class AddPresetTrackingSettings(AddPresetBase, Operator): ] preset_values = [ - "default_correlation_min", - "default_pattern_size", - "default_search_size", - "default_frames_limit", - "default_pattern_match", - "default_margin", - "default_motion_model", - "use_default_brute", - "use_default_normalization", - "use_default_mask", - "use_default_red_channel", - "use_default_green_channel", - "use_default_blue_channel" + "settings.default_correlation_min", + "settings.default_pattern_size", + "settings.default_search_size", + "settings.default_frames_limit", + "settings.default_pattern_match", + "settings.default_margin", + "settings.default_motion_model", + "settings.use_default_brute", + "settings.use_default_normalization", + "settings.use_default_mask", + "settings.use_default_red_channel", + "settings.use_default_green_channel", + "settings.use_default_blue_channel" ] preset_subdir = "tracking_settings" @@ -504,7 +506,7 @@ class AddPresetKeyconfig(AddPresetBase, Operator): class AddPresetOperator(AddPresetBase, Operator): - """Add an Application Interaction Preset""" + """Add an Operator Preset""" bl_idname = "wm.operator_preset_add" bl_label = "Operator Preset" preset_menu = "WM_MT_operator_presets" @@ -512,7 +514,7 @@ class AddPresetOperator(AddPresetBase, Operator): operator = StringProperty( name="Operator", maxlen=64, - options={'HIDDEN'}, + options={'HIDDEN', 'SKIP_SAVE'}, ) preset_defines = [ diff --git a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py index 32658d353d9..694412e51d7 100644 --- a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py +++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py @@ -89,7 +89,7 @@ class PlayRenderedAnim(Operator): if player_path == "": player_path = guess_player_path(preset) - if is_movie == False and preset in {'FRAMECYCLER', 'RV', 'MPLAYER'}: + if is_movie is False and preset in {'FRAMECYCLER', 'RV', 'MPLAYER'}: # replace the number with '#' file_a = rd.frame_path(frame=0) diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index 07d4096632f..2bff11a686d 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -608,9 +608,9 @@ class WM_OT_context_collection_boolean_set(Operator): except: continue - if value_orig == True: + if value_orig is True: is_set = True - elif value_orig == False: + elif value_orig is False: pass else: self.report({'WARNING'}, "Non boolean value found: %s[ ].%s" % @@ -1028,7 +1028,7 @@ class WM_OT_properties_edit(Operator): min = rna_min max = rna_max description = StringProperty( - name="Tip", + name="Tooltip", ) def execute(self, context): @@ -1124,9 +1124,15 @@ class WM_OT_properties_add(Operator): return prop_new - property = unique_name(item.keys()) + prop = unique_name(item.keys()) + + item[prop] = 1.0 + + # not essential, but without this we get [#31661] + prop_ui = rna_idprop_ui_prop_get(item, prop) + prop_ui["soft_min"] = prop_ui["min"] = 0.0 + prop_ui["soft_max"] = prop_ui["max"] = 1.0 - item[property] = 1.0 return {'FINISHED'} @@ -1284,7 +1290,7 @@ class WM_OT_blenderplayer_start(Operator): return {'CANCELLED'} filepath = os.path.join(bpy.app.tempdir, "game.blend") - bpy.ops.wm.save_as_mainfile(filepath=filepath, check_existing=False, copy=True) + bpy.ops.wm.save_as_mainfile('EXEC_DEFAULT', filepath=filepath, copy=True) subprocess.call([player_path, filepath]) return {'FINISHED'} @@ -1583,7 +1589,7 @@ class WM_OT_addon_enable(Operator): "version %d.%d.%d and might not " "function (correctly), " "though it is enabled") % - info_ver) + info_ver) return {'FINISHED'} else: return {'CANCELLED'} @@ -1668,7 +1674,7 @@ class WM_OT_theme_install(Operator): class WM_OT_addon_install(Operator): "Install an addon" bl_idname = "wm.addon_install" - bl_label = "Install Addon..." + bl_label = "Install from File..." overwrite = BoolProperty( name="Overwrite", @@ -1773,12 +1779,6 @@ class WM_OT_addon_install(Operator): try: # extract the file to "addons" file_to_extract.extractall(path_addons) - - # zip files can create this dir with metadata, don't need it - macosx_dir = os.path.join(path_addons, '__MACOSX') - if os.path.isdir(macosx_dir): - shutil.rmtree(macosx_dir) - except: traceback.print_exc() return {'CANCELLED'} @@ -1822,8 +1822,11 @@ class WM_OT_addon_install(Operator): # in case a new module path was created to install this addon. bpy.utils.refresh_script_paths() - # TODO, should not be a warning. - #~ self.report({'WARNING'}, "File installed to '%s'\n" % path_dest) + # print message + msg = "Modules Installed from %r into %r (%s)" % (pyfile, path_addons, ", ".join(sorted(addons_new))) + print(msg) + self.report({'INFO'}, msg) + return {'FINISHED'} def invoke(self, context, event): diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py index 847807029fa..e4be84d5396 100644 --- a/release/scripts/startup/bl_ui/__init__.py +++ b/release/scripts/startup/bl_ui/__init__.py @@ -92,10 +92,11 @@ def register(): def addon_filter_items(self, context): import addon_utils - items = [('All', "All", ""), - ('Enabled', "Enabled", ""), - ('Disabled', "Disabled", ""), - ] + items = [('All', "All", "All Addons"), + ('User', "User", "All Addons Installed by User"), + ('Enabled', "Enabled", "All Enabled Addons"), + ('Disabled', "Disabled", "All Disabled Addons"), + ] items_unique = set() @@ -119,8 +120,8 @@ def register(): WindowManager.addon_support = EnumProperty( items=[('OFFICIAL', "Official", "Officially supported"), ('COMMUNITY', "Community", "Maintained by community developers"), - ('TESTING', "Testing", "Newly contributed scripts (excluded from release builds)"), - ], + ('TESTING', "Testing", "Newly contributed scripts (excluded from release builds)") + ], name="Support", description="Display support level", default={'OFFICIAL', 'COMMUNITY'}, diff --git a/release/scripts/startup/bl_ui/properties_animviz.py b/release/scripts/startup/bl_ui/properties_animviz.py index 2d15c534e9f..8308c7fc425 100644 --- a/release/scripts/startup/bl_ui/properties_animviz.py +++ b/release/scripts/startup/bl_ui/properties_animviz.py @@ -65,10 +65,13 @@ class MotionPathButtonsPanel(): sub.prop(mpath, "frame_start", text="From") sub.prop(mpath, "frame_end", text="To") + sub = col.row(align=True) if bones: - col.operator("pose.paths_update", text="Update Paths", icon='BONE_DATA') + sub.operator("pose.paths_update", text="Update Paths", icon='BONE_DATA') + sub.operator("pose.paths_clear", text="", icon='X') else: - col.operator("object.paths_update", text="Update Paths", icon='OBJECT_DATA') + sub.operator("object.paths_update", text="Update Paths", icon='OBJECT_DATA') + sub.operator("object.paths_clear", text="", icon='X') else: sub = col.column(align=True) sub.label(text="Nothing to show yet...", icon='ERROR') diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py index e194d7a1370..50c34be1414 100644 --- a/release/scripts/startup/bl_ui/properties_data_armature.py +++ b/release/scripts/startup/bl_ui/properties_data_armature.py @@ -285,10 +285,9 @@ class DATA_PT_iksolver_itasc(ArmatureButtonsPanel, Panel): row.prop(itasc, "damping_max", text="Damp", slider=True) row.prop(itasc, "damping_epsilon", text="Eps", slider=True) -from bl_ui.properties_animviz import ( - MotionPathButtonsPanel, - OnionSkinButtonsPanel, - ) +from bl_ui.properties_animviz import (MotionPathButtonsPanel, + OnionSkinButtonsPanel, + ) class DATA_PT_motion_paths(MotionPathButtonsPanel, Panel): diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py index e6d9affee93..1441c642d51 100644 --- a/release/scripts/startup/bl_ui/properties_data_bone.py +++ b/release/scripts/startup/bl_ui/properties_data_bone.py @@ -246,72 +246,74 @@ class BONE_PT_inverse_kinematics(BoneButtonsPanel, Panel): row = layout.row() row.prop(ob.pose, "ik_solver") + active = pchan.is_in_ik_chain + split = layout.split(percentage=0.25) split.prop(pchan, "lock_ik_x", icon='LOCKED' if pchan.lock_ik_x else 'UNLOCKED', text="X") - split.active = pchan.is_in_ik_chain + split.active = active row = split.row() row.prop(pchan, "ik_stiffness_x", text="Stiffness", slider=True) - row.active = pchan.lock_ik_x == False and pchan.is_in_ik_chain + row.active = pchan.lock_ik_x is False and active split = layout.split(percentage=0.25) sub = split.row() sub.prop(pchan, "use_ik_limit_x", text="Limit") - sub.active = pchan.lock_ik_x == False and pchan.is_in_ik_chain + sub.active = pchan.lock_ik_x is False and active sub = split.row(align=True) sub.prop(pchan, "ik_min_x", text="") sub.prop(pchan, "ik_max_x", text="") - sub.active = pchan.lock_ik_x == False and pchan.use_ik_limit_x and pchan.is_in_ik_chain + sub.active = pchan.lock_ik_x is False and pchan.use_ik_limit_x and active split = layout.split(percentage=0.25) split.prop(pchan, "lock_ik_y", icon='LOCKED' if pchan.lock_ik_y else 'UNLOCKED', text="Y") - split.active = pchan.is_in_ik_chain + split.active = active row = split.row() row.prop(pchan, "ik_stiffness_y", text="Stiffness", slider=True) - row.active = pchan.lock_ik_y == False and pchan.is_in_ik_chain + row.active = pchan.lock_ik_y is False and active split = layout.split(percentage=0.25) sub = split.row() sub.prop(pchan, "use_ik_limit_y", text="Limit") - sub.active = pchan.lock_ik_y == False and pchan.is_in_ik_chain + sub.active = pchan.lock_ik_y is False and active sub = split.row(align=True) sub.prop(pchan, "ik_min_y", text="") sub.prop(pchan, "ik_max_y", text="") - sub.active = pchan.lock_ik_y == False and pchan.use_ik_limit_y and pchan.is_in_ik_chain + sub.active = pchan.lock_ik_y is False and pchan.use_ik_limit_y and active split = layout.split(percentage=0.25) split.prop(pchan, "lock_ik_z", icon='LOCKED' if pchan.lock_ik_z else 'UNLOCKED', text="Z") - split.active = pchan.is_in_ik_chain + split.active = active sub = split.row() sub.prop(pchan, "ik_stiffness_z", text="Stiffness", slider=True) - sub.active = pchan.lock_ik_z == False and pchan.is_in_ik_chain + sub.active = pchan.lock_ik_z is False and active split = layout.split(percentage=0.25) sub = split.row() sub.prop(pchan, "use_ik_limit_z", text="Limit") - sub.active = pchan.lock_ik_z == False and pchan.is_in_ik_chain + sub.active = pchan.lock_ik_z is False and active sub = split.row(align=True) sub.prop(pchan, "ik_min_z", text="") sub.prop(pchan, "ik_max_z", text="") - sub.active = pchan.lock_ik_z == False and pchan.use_ik_limit_z and pchan.is_in_ik_chain + sub.active = pchan.lock_ik_z is False and pchan.use_ik_limit_z and active split = layout.split(percentage=0.25) split.label(text="Stretch:") sub = split.row() sub.prop(pchan, "ik_stretch", text="", slider=True) - sub.active = pchan.is_in_ik_chain + sub.active = active if ob.pose.ik_solver == 'ITASC': split = layout.split() col = split.column() col.prop(pchan, "use_ik_rotation_control", text="Control Rotation") - col.active = pchan.is_in_ik_chain + col.active = active col = split.column() col.prop(pchan, "ik_rotation_weight", text="Weight", slider=True) - col.active = pchan.is_in_ik_chain + col.active = active # not supported yet #row = layout.row() #row.prop(pchan, "use_ik_linear_control", text="Joint Size") diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py index 49457b8e569..5f6036c8945 100644 --- a/release/scripts/startup/bl_ui/properties_data_camera.py +++ b/release/scripts/startup/bl_ui/properties_data_camera.py @@ -88,7 +88,8 @@ class DATA_PT_lens(CameraButtonsPanel, Panel): col.prop(cam, "ortho_scale") elif cam.type == 'PANO': - if context.scene.render.engine == 'CYCLES': + engine = context.scene.render.engine + if engine == 'CYCLES': ccam = cam.cycles col.prop(ccam, "panorama_type", text="Type") if ccam.panorama_type == 'FISHEYE_EQUIDISTANT': @@ -97,6 +98,13 @@ class DATA_PT_lens(CameraButtonsPanel, Panel): row = layout.row() row.prop(ccam, "fisheye_lens", text="Lens") row.prop(ccam, "fisheye_fov") + elif engine == 'BLENDER_RENDER': + row = col.row() + if cam.lens_unit == 'MILLIMETERS': + row.prop(cam, "lens") + elif cam.lens_unit == 'DEGREES': + row.prop(cam, "angle") + row.prop(cam, "lens_unit", text="") split = layout.split() @@ -175,7 +183,7 @@ class DATA_PT_camera_display(CameraButtonsPanel, Panel): col = split.column() col.prop(cam, "show_limits", text="Limits") col.prop(cam, "show_mist", text="Mist") - col.prop(cam, "show_title_safe", text="Title Safe") + col.prop(cam, "show_title_safe", text="Safe Areas") col.prop(cam, "show_sensor", text="Sensor") col.prop(cam, "show_name", text="Name") diff --git a/release/scripts/startup/bl_ui/properties_data_lamp.py b/release/scripts/startup/bl_ui/properties_data_lamp.py index 769715ef1b9..71fdc1d7b67 100644 --- a/release/scripts/startup/bl_ui/properties_data_lamp.py +++ b/release/scripts/startup/bl_ui/properties_data_lamp.py @@ -118,7 +118,7 @@ class DATA_PT_lamp(DataButtonsPanel, Panel): class DATA_PT_sunsky(DataButtonsPanel, Panel): bl_label = "Sky & Atmosphere" - COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} + COMPAT_ENGINES = {'BLENDER_RENDER'} @classmethod def poll(cls, context): diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py index 5f21f78a375..6125540d491 100644 --- a/release/scripts/startup/bl_ui/properties_data_mesh.py +++ b/release/scripts/startup/bl_ui/properties_data_mesh.py @@ -316,10 +316,31 @@ class DATA_PT_vertex_colors(MeshButtonsPanel, Panel): layout.prop(lay, "name") +class DATA_PT_customdata(MeshButtonsPanel, Panel): + bl_label = "Geometry Data" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} + + def draw(self, context): + layout = self.layout + + # me = context.mesh + col = layout.column() + # sticky has no UI access since 2.49 - we may remove + ''' + row = col.row(align=True) + row.operator("mesh.customdata_create_sticky") + row.operator("mesh.customdata_clear_sticky", icon='X') + ''' + col.operator("mesh.customdata_clear_mask", icon='X') + col.operator("mesh.customdata_clear_skin", icon='X') + + class DATA_PT_custom_props_mesh(MeshButtonsPanel, PropertyPanel, Panel): COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} _context_path = "object.data" _property_type = bpy.types.Mesh + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index ae0c4d4161c..902358813df 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -211,12 +211,27 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): layout.row().prop(md, "deform_axis", expand=True) def DECIMATE(self, layout, ob, md): - layout.prop(md, "ratio") + row = layout.row() + row.prop(md, "decimate_type", expand=True) + decimate_type = md.decimate_type + + if decimate_type == 'COLLAPSE': + layout.prop(md, "ratio") + row = layout.row() + row.prop_search(md, "vertex_group", ob, "vertex_groups", text="") + row.prop(md, "invert_vertex_group") + layout.prop(md, "use_collapse_triangulate") + elif decimate_type == 'UNSUBDIV': + layout.prop(md, "iterations") + else: # decimate_type == 'DISSOLVE': + layout.prop(md, "angle_limit") + layout.prop(md, "use_dissolve_boundaries") + layout.label(text="Face Count" + ": %d" % md.face_count) def DISPLACE(self, layout, ob, md): has_texture = (md.texture is not None) - + split = layout.split() col = split.column() @@ -316,6 +331,28 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): row.operator("object.hook_select", text="Select") row.operator("object.hook_assign", text="Assign") + def LAPLACIANSMOOTH(self, layout, ob, md): + layout.prop(md, "iterations") + + split = layout.split(percentage=0.25) + + col = split.column() + col.label(text="Axis:") + col.prop(md, "use_x") + col.prop(md, "use_y") + col.prop(md, "use_z") + + col = split.column() + col.label(text="Lambda:") + col.prop(md, "lambda_factor", text="Factor") + col.prop(md, "lambda_border", text="Border") + + col.separator() + col.prop(md, "use_volume_preserve") + + layout.label(text="Vertex Group:") + layout.prop_search(md, "vertex_group", ob, "vertex_groups", text="") + def LATTICE(self, layout, ob, md): split = layout.split() @@ -397,7 +434,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col = layout.column() - if md.use_mirror_merge == True: + if md.use_mirror_merge is True: col.prop(md, "merge_threshold") col.label(text="Mirror Object:") col.prop(md, "mirror_object", text="") @@ -559,7 +596,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col = split.column() row = col.row() - row.active = (md.object is None or md.use_object_screw_offset == False) + row.active = (md.object is None or md.use_object_screw_offset is False) row.prop(md, "screw_offset") row = col.row() row.active = (md.object is not None) diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py index 5ff49a7d369..bf0c9eb762a 100644 --- a/release/scripts/startup/bl_ui/properties_game.py +++ b/release/scripts/startup/bl_ui/properties_game.py @@ -190,6 +190,14 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel): layout.operator("mesh.navmesh_reset") layout.operator("mesh.navmesh_clear") + if physics_type not in {'NO_COLLISION', 'OCCLUDE'}: + layout.separator() + split = layout.split() + + col = split.column() + col.prop(game, "collision_group") + col = split.column() + col.prop(game, "collision_mask") class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel, Panel): bl_label = "Collision Bounds" diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py index dfc75168d2b..951644db752 100644 --- a/release/scripts/startup/bl_ui/properties_material.py +++ b/release/scripts/startup/bl_ui/properties_material.py @@ -753,6 +753,7 @@ class MATERIAL_PT_options(MaterialButtonsPanel, Panel): row = sub.row() row.active = bool(mat.light_group) row.prop(mat, "use_light_group_exclusive", text="Exclusive") + row.prop(mat, "use_light_group_local", text="Local") col = split.column() col.prop(mat, "use_face_texture") @@ -763,6 +764,7 @@ class MATERIAL_PT_options(MaterialButtonsPanel, Panel): col.prop(mat, "use_vertex_color_paint") col.prop(mat, "use_vertex_color_light") col.prop(mat, "use_object_color") + col.prop(mat, "use_uv_project") if simple_material(base_mat): col.prop(mat, "pass_index") diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py index 275cb8fab65..8a668b5d95b 100644 --- a/release/scripts/startup/bl_ui/properties_object.py +++ b/release/scripts/startup/bl_ui/properties_object.py @@ -185,7 +185,7 @@ class OBJECT_PT_groups(ObjectButtonsPanel, Panel): split = col.box().split() col = split.column() - col.prop(group, "layers", text="Dupli") + col.prop(group, "layers", text="Dupli Visibility") col = split.column() col.prop(group, "dupli_offset", text="") @@ -290,10 +290,8 @@ class OBJECT_PT_relations_extras(ObjectButtonsPanel, Panel): row.prop(ob, "slow_parent_offset", text="Offset") -from bl_ui.properties_animviz import ( - MotionPathButtonsPanel, - OnionSkinButtonsPanel, - ) +from bl_ui.properties_animviz import (MotionPathButtonsPanel, + OnionSkinButtonsPanel) class OBJECT_PT_motion_paths(MotionPathButtonsPanel, Panel): diff --git a/release/scripts/startup/bl_ui/properties_object_constraint.py b/release/scripts/startup/bl_ui/properties_object_constraint.py index 3d671a0d1b7..3fa63bac13c 100644 --- a/release/scripts/startup/bl_ui/properties_object_constraint.py +++ b/release/scripts/startup/bl_ui/properties_object_constraint.py @@ -88,7 +88,6 @@ class ConstraintButtonsPanel(): col = split.column() col.prop(con, "chain_count") - col.prop(con, "use_target") def CHILD_OF(self, context, layout, con): self.target_template(layout, con) @@ -162,7 +161,6 @@ class ConstraintButtonsPanel(): col.prop(con, "use_tail") col.prop(con, "use_stretch") col.separator() - col.prop(con, "use_target") col.prop(con, "use_rotation") def IK_COPY_POSE(self, context, layout, con): @@ -212,6 +210,7 @@ class ConstraintButtonsPanel(): def FOLLOW_PATH(self, context, layout, con): self.target_template(layout, con) + layout.operator("constraint.followpath_path_animate", text="Animate Path", icon='ANIM_DATA') split = layout.split() @@ -484,6 +483,8 @@ class ConstraintButtonsPanel(): row.prop(con, "use_transform_limit") row.label() + self.space_template(layout, con) + def STRETCH_TO(self, context, layout, con): self.target_template(layout, con) diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py index aa0ea1d2d9e..6fcd56fb99e 100644 --- a/release/scripts/startup/bl_ui/properties_particle.py +++ b/release/scripts/startup/bl_ui/properties_particle.py @@ -21,12 +21,11 @@ import bpy from bpy.types import Panel from rna_prop_ui import PropertyPanel -from bl_ui.properties_physics_common import ( - point_cache_ui, - effector_weights_ui, - basic_force_field_settings_ui, - basic_force_field_falloff_ui, - ) +from bl_ui.properties_physics_common import (point_cache_ui, + effector_weights_ui, + basic_force_field_settings_ui, + basic_force_field_falloff_ui, + ) def particle_panel_enabled(context, psys): @@ -52,7 +51,7 @@ def particle_panel_poll(cls, context): if not settings: return False - return settings.is_fluid == False and (engine in cls.COMPAT_ENGINES) + return settings.is_fluid is False and (engine in cls.COMPAT_ENGINES) def particle_get_settings(context): @@ -133,13 +132,13 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel): split = layout.split(percentage=0.32) col = split.column() col.label(text="Name:") - if part.is_fluid == False: + if part.is_fluid is False: col.label(text="Settings:") col.label(text="Type:") col = split.column() col.prop(psys, "name", text="") - if part.is_fluid == False: + if part.is_fluid is False: row = col.row() row.enabled = particle_panel_enabled(context, psys) row.template_ID(psys, "settings", new="particle.new") @@ -279,7 +278,7 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel): cloth = psys.cloth.settings - layout.enabled = psys.use_hair_dynamics and psys.point_cache.is_baked == False + layout.enabled = psys.use_hair_dynamics and psys.point_cache.is_baked is False split = layout.split() @@ -813,7 +812,7 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel): sub.active = (part.use_strand_primitive is False) sub.prop(part, "use_render_adaptive") sub = col.column() - sub.active = part.use_render_adaptive or part.use_strand_primitive == True + sub.active = part.use_render_adaptive or part.use_strand_primitive is True sub.prop(part, "adaptive_angle") sub = col.column() sub.active = (part.use_render_adaptive is True and part.use_strand_primitive is False) @@ -831,9 +830,9 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel): row = layout.row() col = row.column() - if part.type == 'HAIR' and part.use_strand_primitive == True and part.child_type == 'INTERPOLATED': + if part.type == 'HAIR' and part.use_strand_primitive is True and part.child_type == 'INTERPOLATED': layout.prop(part, "use_simplify") - if part.use_simplify == True: + if part.use_simplify is True: row = layout.row() row.prop(part, "simplify_refsize") row.prop(part, "simplify_rate") @@ -841,7 +840,7 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel): row = layout.row() row.prop(part, "use_simplify_viewport") sub = row.row() - sub.active = part.use_simplify_viewport == True + sub.active = part.use_simplify_viewport is True sub.prop(part, "simplify_viewport") elif part.render_type == 'OBJECT': @@ -988,11 +987,11 @@ class PARTICLE_PT_draw(ParticleButtonsPanel, Panel): if part.draw_percentage != 100 and psys is not None: if part.type == 'HAIR': - if psys.use_hair_dynamics and psys.point_cache.is_baked == False: + if psys.use_hair_dynamics and psys.point_cache.is_baked is False: layout.row().label(text="Display percentage makes dynamics inaccurate without baking!") else: phystype = part.physics_type - if phystype != 'NO' and phystype != 'KEYED' and psys.point_cache.is_baked == False: + if phystype != 'NO' and phystype != 'KEYED' and psys.point_cache.is_baked is False: layout.row().label(text="Display percentage makes dynamics inaccurate without baking!") row = layout.row() @@ -1125,7 +1124,7 @@ class PARTICLE_PT_field_weights(ParticleButtonsPanel, Panel): def draw(self, context): part = particle_get_settings(context) - effector_weights_ui(self, context, part.effector_weights) + effector_weights_ui(self, context, part.effector_weights, 'PSYS') if part.type == 'HAIR': row = self.layout.row() diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py index 33b977b5f04..5a44294f0e0 100644 --- a/release/scripts/startup/bl_ui/properties_physics_cloth.py +++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py @@ -20,10 +20,8 @@ import bpy from bpy.types import Menu, Panel -from bl_ui.properties_physics_common import ( - point_cache_ui, - effector_weights_ui, - ) +from bl_ui.properties_physics_common import (point_cache_ui, + effector_weights_ui) def cloth_panel_enabled(md): @@ -178,7 +176,7 @@ class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, Panel): ob = context.object cloth = context.cloth.settings - layout.active = cloth.use_stiffness_scale and cloth_panel_enabled(md) + layout.active = (cloth.use_stiffness_scale and cloth_panel_enabled(md)) split = layout.split() @@ -199,7 +197,7 @@ class PHYSICS_PT_cloth_field_weights(PhysicButtonsPanel, Panel): def draw(self, context): cloth = context.cloth.settings - effector_weights_ui(self, context, cloth.effector_weights) + effector_weights_ui(self, context, cloth.effector_weights, 'CLOTH') if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py index 7f824d94431..405e877d1e2 100644 --- a/release/scripts/startup/bl_ui/properties_physics_common.py +++ b/release/scripts/startup/bl_ui/properties_physics_common.py @@ -133,7 +133,7 @@ def point_cache_ui(self, context, cache, enabled, cachetype): row.prop(cache, "frame_end") if cachetype not in {'SMOKE', 'CLOTH', 'DYNAMIC_PAINT'}: row.prop(cache, "frame_step") - row.prop(cache, "use_quick_cache") + if cachetype != 'SMOKE': layout.label(text=cache.info) @@ -160,7 +160,7 @@ def point_cache_ui(self, context, cache, enabled, cachetype): col = split.column() - if cache.is_baked == True: + if cache.is_baked is True: col.operator("ptcache.free_bake", text="Free Bake") else: col.operator("ptcache.bake", text="Bake").bake = True @@ -179,7 +179,7 @@ def point_cache_ui(self, context, cache, enabled, cachetype): col.operator("ptcache.bake_all", text="Update All To Frame").bake = False -def effector_weights_ui(self, context, weights): +def effector_weights_ui(self, context, weights, weight_type): layout = self.layout layout.prop(weights, "group") @@ -200,6 +200,8 @@ def effector_weights_ui(self, context, weights): col.prop(weights, "wind", slider=True) col.prop(weights, "curve_guide", slider=True) col.prop(weights, "texture", slider=True) + if weight_type != 'SMOKE': + col.prop(weights, "smokeflow", slider=True) col = split.column() col.prop(weights, "harmonic", slider=True) diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py index db0794d8a8a..1df2936b2d4 100644 --- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py +++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py @@ -20,10 +20,9 @@ import bpy from bpy.types import Panel -from bl_ui.properties_physics_common import ( - point_cache_ui, - effector_weights_ui, - ) +from bl_ui.properties_physics_common import (point_cache_ui, + effector_weights_ui, + ) class PhysicButtonsPanel(): @@ -350,7 +349,7 @@ class PHYSICS_PT_dp_effects(PhysicButtonsPanel, Panel): col = layout.column() col.active = surface.use_drip - effector_weights_ui(self, context, surface.effector_weights) + effector_weights_ui(self, context, surface.effector_weights, 'DYNAMIC_PAINT') layout.label(text="Surface Movement:") row = layout.row() diff --git a/release/scripts/startup/bl_ui/properties_physics_field.py b/release/scripts/startup/bl_ui/properties_physics_field.py index 569037cb0da..933a9aa12a3 100644 --- a/release/scripts/startup/bl_ui/properties_physics_field.py +++ b/release/scripts/startup/bl_ui/properties_physics_field.py @@ -20,10 +20,9 @@ import bpy from bpy.types import Panel -from bl_ui.properties_physics_common import ( - basic_force_field_settings_ui, - basic_force_field_falloff_ui, - ) +from bl_ui.properties_physics_common import (basic_force_field_settings_ui, + basic_force_field_falloff_ui, + ) class PhysicButtonsPanel(): @@ -113,6 +112,14 @@ class PHYSICS_PT_field(PhysicButtonsPanel, Panel): col = split.column() col.prop(field, "use_object_coords") col.prop(field, "use_2d_force") + elif field.type == 'SMOKE_FLOW': + col = split.column() + col.prop(field, "strength") + col.prop(field, "flow") + col = split.column() + col.label(text="Domain Object:") + col.prop(field, "source_object", "") + col.prop(field, "use_smoke_density") else: basic_force_field_settings_ui(self, context, field) diff --git a/release/scripts/startup/bl_ui/properties_physics_smoke.py b/release/scripts/startup/bl_ui/properties_physics_smoke.py index 1b333f1e505..ce5053f0ecf 100644 --- a/release/scripts/startup/bl_ui/properties_physics_smoke.py +++ b/release/scripts/startup/bl_ui/properties_physics_smoke.py @@ -20,10 +20,8 @@ import bpy from bpy.types import Panel -from bl_ui.properties_physics_common import ( - point_cache_ui, - effector_weights_ui, - ) +from bl_ui.properties_physics_common import (point_cache_ui, + effector_weights_ui) class PhysicButtonsPanel(): @@ -78,28 +76,40 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel): elif md.smoke_type == 'FLOW': flow = md.flow_settings + + layout.prop(flow, "smoke_flow_type", expand=False) - split = layout.split() + if flow.smoke_flow_type != "OUTFLOW": + split = layout.split() + col = split.column() + col.label(text="Flow Source:") + col.prop(flow, "smoke_flow_source", expand=False, text="") + if flow.smoke_flow_source == "PARTICLES": + col.label(text="Particle System:") + col.prop_search(flow, "particle_system", ob, "particle_systems", text="") + else: + col.prop(flow, "surface_distance") + col.prop(flow, "volume_density") - col = split.column() - col.prop(flow, "use_outflow") - col.label(text="Particle System:") - col.prop_search(flow, "particle_system", ob, "particle_systems", text="") + sub = col.column(align=True) - sub = col.column() - sub.active = not md.flow_settings.use_outflow + sub.prop(flow, "initial_velocity") + sub = sub.column() + sub.active = flow.initial_velocity + sub.prop(flow, "velocity_factor") + if flow.smoke_flow_source == "MESH": + sub.prop(flow, "velocity_normal") + #sub.prop(flow, "velocity_random") - sub.prop(flow, "initial_velocity", text="Initial Velocity") - sub = sub.column() - sub.active = flow.initial_velocity - sub.prop(flow, "velocity_factor", text="Multiplier") - - sub = split.column() - sub.active = not md.flow_settings.use_outflow - sub.label(text="Initial Values:") - sub.prop(flow, "use_absolute") - sub.prop(flow, "density") - sub.prop(flow, "temperature") + sub = split.column() + sub.label(text="Initial Values:") + sub.prop(flow, "use_absolute") + if flow.smoke_flow_type in {'SMOKE', 'BOTH'}: + sub.prop(flow, "density") + sub.prop(flow, "temperature") + sub.prop(flow, "smoke_color") + if flow.smoke_flow_type in {'FIRE', 'BOTH'}: + sub.prop(flow, "fuel_amount") elif md.smoke_type == 'COLLISION': coll = md.coll_settings @@ -108,36 +118,99 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel): col = split.column() col.prop(coll, "collision_type") - - -class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, Panel): - bl_label = "Smoke Groups" + +class PHYSICS_PT_smoke_flow_advanced(PhysicButtonsPanel, Panel): + bl_label = "Smoke Flow Advanced" bl_options = {'DEFAULT_CLOSED'} @classmethod def poll(cls, context): md = context.smoke - rd = context.scene.render - return md and (md.smoke_type == 'DOMAIN') and (not rd.use_game_engine) + return md and (md.smoke_type == 'FLOW') and (md.flow_settings.smoke_flow_source == "MESH") + + def draw(self, context): + layout = self.layout + ob = context.object + flow = context.smoke.flow_settings + + split = layout.split() + col = split.column() + + col.prop(flow, "use_texture") + sub = col.column() + sub.active = flow.use_texture + sub.prop(flow, "noise_texture", text="") + sub.label(text="Mapping:") + sub.prop(flow, "texture_map_type", expand=False, text="") + if flow.texture_map_type == "UV": + sub.prop_search(flow, "uv_layer", ob.data, "uv_textures", text="") + if flow.texture_map_type == "AUTO": + sub.prop(flow, "texture_size") + sub.prop(flow, "texture_offset") + + col = split.column() + col.label(text="Vertex Group:") + col.prop_search(flow, "density_vertex_group", ob, "vertex_groups", text="") + +class PHYSICS_PT_smoke_fire(PhysicButtonsPanel, Panel): + bl_label = "Smoke Flames" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + md = context.smoke + return md and (md.smoke_type == 'DOMAIN') + + def draw(self, context): + layout = self.layout + domain = context.smoke.domain_settings + + split = layout.split() + split.enabled = not domain.point_cache.is_baked + + col = split.column(align=True) + col.label(text="Reaction:") + col.prop(domain, "burning_rate") + col.prop(domain, "flame_smoke") + col.prop(domain, "flame_vorticity") + + col = split.column(align=True) + col.label(text="Temperatures:") + col.prop(domain, "flame_ignition") + col.prop(domain, "flame_max_temp") + col.prop(domain, "flame_smoke_color") + +class PHYSICS_PT_smoke_adaptive_domain(PhysicButtonsPanel, Panel): + bl_label = "Smoke Adaptive Domain" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + md = context.smoke + return md and (md.smoke_type == 'DOMAIN') + + def draw_header(self, context): + md = context.smoke.domain_settings + + self.layout.prop(md, "use_adaptive_domain", text="") def draw(self, context): layout = self.layout - group = context.smoke.domain_settings - + domain = context.smoke.domain_settings + layout.active = domain.use_adaptive_domain + split = layout.split() + split.enabled = not domain.point_cache.is_baked + + col = split.column(align=True) + col.label(text="Resolution:") + col.prop(domain, "additional_res") + col.prop(domain, "adapt_margin") - col = split.column() - col.label(text="Flow Group:") - col.prop(group, "fluid_group", text="") - - #col.label(text="Effector Group:") - #col.prop(group, "effector_group", text="") - - col = split.column() - col.label(text="Collision Group:") - col.prop(group, "collision_group", text="") - + col = split.column(align=True) + col.label(text="Advanced:") + col.prop(domain, "adapt_threshold") class PHYSICS_PT_smoke_highres(PhysicButtonsPanel, Panel): bl_label = "Smoke High Resolution" @@ -176,6 +249,32 @@ class PHYSICS_PT_smoke_highres(PhysicButtonsPanel, Panel): layout.prop(md, "show_high_resolution") +class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, Panel): + bl_label = "Smoke Groups" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + md = context.smoke + rd = context.scene.render + return md and (md.smoke_type == 'DOMAIN') and (not rd.use_game_engine) + + def draw(self, context): + layout = self.layout + domain = context.smoke.domain_settings + + split = layout.split() + + col = split.column() + col.label(text="Flow Group:") + col.prop(domain, "fluid_group", text="") + + #col.label(text="Effector Group:") + #col.prop(domain, "effector_group", text="") + + col = split.column() + col.label(text="Collision Group:") + col.prop(domain, "collision_group", text="") class PHYSICS_PT_smoke_cache(PhysicButtonsPanel, Panel): bl_label = "Smoke Cache" @@ -211,7 +310,7 @@ class PHYSICS_PT_smoke_field_weights(PhysicButtonsPanel, Panel): def draw(self, context): domain = context.smoke.domain_settings - effector_weights_ui(self, context, domain.effector_weights) + effector_weights_ui(self, context, domain.effector_weights, 'SMOKE') if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/properties_physics_softbody.py b/release/scripts/startup/bl_ui/properties_physics_softbody.py index b043c1f9b68..79d676533a5 100644 --- a/release/scripts/startup/bl_ui/properties_physics_softbody.py +++ b/release/scripts/startup/bl_ui/properties_physics_softbody.py @@ -20,10 +20,8 @@ import bpy from bpy.types import Panel -from bl_ui.properties_physics_common import ( - point_cache_ui, - effector_weights_ui, - ) +from bl_ui.properties_physics_common import (point_cache_ui, + effector_weights_ui) def softbody_panel_enabled(md): @@ -233,7 +231,7 @@ class PHYSICS_PT_softbody_field_weights(PhysicButtonsPanel, Panel): md = context.soft_body softbody = md.settings - effector_weights_ui(self, context, softbody.effector_weights) + effector_weights_ui(self, context, softbody.effector_weights, 'SOFTBODY') if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index b777fcddcf2..9814dd7e902 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -63,10 +63,10 @@ class RENDER_PT_render(RenderButtonsPanel, Panel): rd = context.scene.render - row = layout.row() - row.operator("render.render", text="Image", icon='RENDER_STILL') + row = layout.row(align=True) + row.operator("render.render", text="Render", icon='RENDER_STILL') row.operator("render.render", text="Animation", icon='RENDER_ANIMATION').animation = True - row.operator("render.play_rendered_anim", text="Play", icon='RENDER_ANIMATION') + row.operator("render.play_rendered_anim", text="Play", icon='PLAY') layout.prop(rd, "display_mode", text="Display") @@ -225,7 +225,7 @@ class RENDER_PT_dimensions(RenderButtonsPanel, Panel): # TODO: Change the following to iterate over existing presets custom_framerate = (fps_rate not in {23.98, 24, 25, 29.97, 30, 50, 59.94, 60}) - if custom_framerate == True: + if custom_framerate is True: fps_label_text = "Custom (" + str(fps_rate) + " fps)" else: fps_label_text = str(fps_rate) + " fps" @@ -316,7 +316,6 @@ class RENDER_PT_shading(RenderButtonsPanel, Panel): col = split.column() col.prop(rd, "use_raytrace", text="Ray Tracing") - col.prop(rd, "use_color_unpremultiply") col.prop(rd, "alpha_mode", text="Alpha") @@ -333,15 +332,17 @@ class RENDER_PT_performance(RenderButtonsPanel, Panel): split = layout.split() col = split.column() - col.label(text="Threads:") - col.row().prop(rd, "threads_mode", expand=True) - sub = col.column() - sub.enabled = rd.threads_mode == 'FIXED' - sub.prop(rd, "threads") sub = col.column(align=True) - sub.label(text="Tiles:") - sub.prop(rd, "parts_x", text="X") - sub.prop(rd, "parts_y", text="Y") + sub.label(text="Threads:") + sub.row().prop(rd, "threads_mode", expand=True) + subsub = sub.column() + subsub.enabled = rd.threads_mode == 'FIXED' + subsub.prop(rd, "threads") + + sub = col.column(align=True) + sub.label(text="Tile Size:") + sub.prop(rd, "tile_x", text="X") + sub.prop(rd, "tile_y", text="Y") col = split.column() col.label(text="Memory:") diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py index 2ccdb9cee26..518b253d0b0 100644 --- a/release/scripts/startup/bl_ui/properties_scene.py +++ b/release/scripts/startup/bl_ui/properties_scene.py @@ -241,6 +241,7 @@ class SCENE_PT_color_management(Panel): layout = self.layout scene = context.scene + rd = scene.render col = layout.column() col.label(text="Display:") @@ -250,6 +251,7 @@ class SCENE_PT_color_management(Panel): col.separator() col.label(text="Render:") col.template_colormanaged_view_settings(scene, "view_settings") + col.prop(rd, "use_color_unpremultiply") col = layout.column() col.separator() diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py index 46a17675c91..e623d034b48 100644 --- a/release/scripts/startup/bl_ui/properties_texture.py +++ b/release/scripts/startup/bl_ui/properties_texture.py @@ -111,8 +111,14 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel, Panel): engine = context.scene.render.engine if not (hasattr(context, "texture_slot") or hasattr(context, "texture_node")): return False - return ((context.material or context.world or context.lamp or context.brush or context.texture or context.particle_system or isinstance(context.space_data.pin_id, ParticleSettings)) - and (engine in cls.COMPAT_ENGINES)) + return ((context.material or + context.world or + context.lamp or + context.brush or + context.texture or + context.particle_system or + isinstance(context.space_data.pin_id, ParticleSettings)) and + (engine in cls.COMPAT_ENGINES)) def draw(self, context): layout = self.layout @@ -143,20 +149,15 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel, Panel): col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN' col.menu("TEXTURE_MT_specials", icon='DOWNARROW_HLT', text="") - split = layout.split(percentage=0.65) - col = split.column() - if tex_collection: - col.template_ID(idblock, "active_texture", new="texture.new") + layout.template_ID(idblock, "active_texture", new="texture.new") elif node: - col.template_ID(node, "texture", new="texture.new") + layout.template_ID(node, "texture", new="texture.new") elif idblock: - col.template_ID(idblock, "texture", new="texture.new") + layout.template_ID(idblock, "texture", new="texture.new") if pin_id: - col.template_ID(space, "pin_id") - - col = split.column() + layout.template_ID(space, "pin_id") if tex: split = layout.split(percentage=0.2) @@ -881,8 +882,12 @@ class TEXTURE_PT_mapping(TextureSlotPanel, Panel): col = split.column() if tex.texture_coords in {'ORCO', 'UV'}: col.prop(tex, "use_from_dupli") + if (idblock.type == 'VOLUME' and tex.texture_coords == 'ORCO'): + col.prop(tex, "use_map_to_bounds") elif tex.texture_coords == 'OBJECT': col.prop(tex, "use_from_original") + if (idblock.type == 'VOLUME'): + col.prop(tex, "use_map_to_bounds") else: col.label() diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index efac7a66086..cb88226b55a 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -311,8 +311,8 @@ class CLIP_PT_tools_solve(CLIP_PT_tracking_panel, Panel): col = layout.column(align=True) col.active = not settings.use_tripod_solver - col.prop(settings, "keyframe_a") - col.prop(settings, "keyframe_b") + col.prop(tracking_object, "keyframe_a") + col.prop(tracking_object, "keyframe_b") col = layout.column(align=True) col.active = (tracking_object.is_camera and @@ -320,6 +320,13 @@ class CLIP_PT_tools_solve(CLIP_PT_tracking_panel, Panel): col.label(text="Refine:") col.prop(settings, "refine_intrinsics", text="") + col = layout.column(align=True) + col.active = not settings.use_tripod_solver + col.prop(settings, "use_fallback_reconstruction", text="Allow Fallback") + sub = col.column() + sub.active = settings.use_fallback_reconstruction + sub.prop(settings, "reconstruction_success_threshold") + class CLIP_PT_tools_cleanup(CLIP_PT_tracking_panel, Panel): bl_space_type = 'CLIP_EDITOR' @@ -790,42 +797,45 @@ class CLIP_PT_proxy(CLIP_PT_clip_view_panel, Panel): sc = context.space_data clip = sc.clip - layout.active = clip.use_proxy + col = layout.column() + col.active = clip.use_proxy - layout.label(text="Build Original:") + col.label(text="Build Original:") - row = layout.row(align=True) + row = col.row(align=True) row.prop(clip.proxy, "build_25", toggle=True) row.prop(clip.proxy, "build_50", toggle=True) row.prop(clip.proxy, "build_75", toggle=True) row.prop(clip.proxy, "build_100", toggle=True) - layout.label(text="Build Undistorted:") + col.label(text="Build Undistorted:") - row = layout.row(align=True) + row = col.row(align=True) row.prop(clip.proxy, "build_undistorted_25", toggle=True) row.prop(clip.proxy, "build_undistorted_50", toggle=True) row.prop(clip.proxy, "build_undistorted_75", toggle=True) row.prop(clip.proxy, "build_undistorted_100", toggle=True) - layout.prop(clip.proxy, "quality") + col.prop(clip.proxy, "quality") - layout.prop(clip, "use_proxy_custom_directory") + col.prop(clip, "use_proxy_custom_directory") if clip.use_proxy_custom_directory: - layout.prop(clip.proxy, "directory") + col.prop(clip.proxy, "directory") - layout.operator("clip.rebuild_proxy", text="Build Proxy") + col.operator("clip.rebuild_proxy", text="Build Proxy") if clip.source == 'MOVIE': - col = layout.column() + col2 = col.column() - col.label(text="Use timecode index:") - col.prop(clip.proxy, "timecode", text="") + col2.label(text="Use timecode index:") + col2.prop(clip.proxy, "timecode", text="") - col = layout.column() - col.label(text="Proxy render size:") + col2 = col.column() + col2.label(text="Proxy render size:") col.prop(sc.clip_user, "proxy_render_size", text="") + + col = layout.column() col.prop(sc.clip_user, "use_render_undistorted") @@ -888,6 +898,12 @@ class CLIP_MT_view(Menu): layout.operator("clip.view_zoom_ratio", text=text).ratio = a / b else: + if sc.view == 'GRAPH': + layout.operator_context = 'INVOKE_REGION_PREVIEW' + layout.operator("clip.graph_center_current_frame") + layout.operator("clip.graph_view_all") + layout.operator_context = 'INVOKE_DEFAULT' + layout.prop(sc, "show_seconds") layout.separator() @@ -939,7 +955,7 @@ class CLIP_MT_track(Menu): props.action = 'UPTO' props = layout.operator("clip.clear_track_path", - text="Clear Track Path") + text="Clear Track Path") props.action = 'ALL' layout.separator() @@ -954,7 +970,7 @@ class CLIP_MT_track(Menu): layout.separator() props = layout.operator("clip.track_markers", - text="Track Frame Backwards") + text="Track Frame Backwards") props.backwards = True props = layout.operator("clip.track_markers", text="Track Backwards") diff --git a/release/scripts/startup/bl_ui/space_console.py b/release/scripts/startup/bl_ui/space_console.py index 7ded4954f80..5ff179902a3 100644 --- a/release/scripts/startup/bl_ui/space_console.py +++ b/release/scripts/startup/bl_ui/space_console.py @@ -86,7 +86,7 @@ class CONSOLE_MT_language(Menu): def add_scrollback(text, text_type): for l in text.split("\n"): bpy.ops.console.scrollback_append(text=l.replace('\t', ' '), - type=text_type) + type=text_type) if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index 8e955338480..a81553a8257 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -29,6 +29,7 @@ from bpy.types import Header, Menu def dopesheet_filter(layout, context, genericFiltersOnly=False): dopesheet = context.space_data.dopesheet is_nla = context.area.type == 'NLA_EDITOR' + is_drivers = (context.area.type == 'GRAPH_EDITOR' and context.space_data.mode == 'DRIVERS') row = layout.row(align=True) row.prop(dopesheet, "show_only_selected", text="") @@ -37,6 +38,9 @@ def dopesheet_filter(layout, context, genericFiltersOnly=False): if is_nla: row.prop(dopesheet, "show_missing_nla", text="") + if is_drivers: + row.prop(dopesheet, "show_only_errors", text="") + if not genericFiltersOnly: if bpy.data.groups: row = layout.row(align=True) @@ -161,7 +165,6 @@ class DOPESHEET_MT_view(Menu): layout.operator("action.previewrange_set") layout.separator() - layout.operator("action.frame_jump") layout.operator("action.view_all") layout.operator("action.view_selected") @@ -271,6 +274,9 @@ class DOPESHEET_MT_key(Menu): layout.separator() layout.operator("action.keyframe_insert") + layout.separator() + layout.operator("action.frame_jump") + layout.separator() layout.operator("action.duplicate_move") layout.operator("action.delete") diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py index 435b968f243..256545bab70 100644 --- a/release/scripts/startup/bl_ui/space_filebrowser.py +++ b/release/scripts/startup/bl_ui/space_filebrowser.py @@ -67,6 +67,7 @@ class FILEBROWSER_HT_header(Header): row.label(params.filter_glob) else: row.prop(params, "use_filter_blender", text="") + row.prop(params, "use_filter_backup", text="") row.prop(params, "use_filter_image", text="") row.prop(params, "use_filter_movie", text="") row.prop(params, "use_filter_script", text="") diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index 972b4ebe721..e89bd78a84f 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -96,7 +96,6 @@ class GRAPH_MT_view(Menu): layout.operator("graph.previewrange_set") layout.separator() - layout.operator("graph.frame_jump") layout.operator("graph.view_all") layout.operator("graph.view_selected") @@ -198,6 +197,9 @@ class GRAPH_MT_key(Menu): layout.operator("graph.fmodifier_add") layout.operator("graph.sound_bake") + layout.separator() + layout.operator("graph.frame_jump") + layout.separator() layout.operator("graph.duplicate_move") layout.operator("graph.delete") diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py index 04ea6b818ac..c0f2d3c361b 100644 --- a/release/scripts/startup/bl_ui/space_info.py +++ b/release/scripts/startup/bl_ui/space_info.py @@ -112,8 +112,9 @@ class INFO_MT_file(Menu): layout.separator() - layout.operator_context = 'INVOKE_AREA' - layout.operator("wm.save_mainfile", text="Save", icon='FILE_TICK').check_existing = False + layout.operator_context = 'EXEC_AREA' if context.blend_data.is_saved else 'INVOKE_AREA' + layout.operator("wm.save_mainfile", text="Save", icon='FILE_TICK') + layout.operator_context = 'INVOKE_AREA' layout.operator("wm.save_as_mainfile", text="Save As...", icon='SAVE_AS') layout.operator_context = 'INVOKE_AREA' @@ -192,7 +193,7 @@ class INFO_MT_mesh_add(Menu): def draw(self, context): layout = self.layout - layout.operator_context = 'INVOKE_REGION_WIN' + layout.operator_context = 'EXEC_REGION_WIN' layout.operator("mesh.primitive_plane_add", icon='MESH_PLANE', text="Plane") layout.operator("mesh.primitive_cube_add", icon='MESH_CUBE', text="Cube") layout.operator("mesh.primitive_circle_add", icon='MESH_CIRCLE', text="Circle") @@ -203,7 +204,7 @@ class INFO_MT_mesh_add(Menu): layout.separator() layout.operator("mesh.primitive_grid_add", icon='MESH_GRID', text="Grid") layout.operator("mesh.primitive_monkey_add", icon='MESH_MONKEY', text="Monkey") - layout.operator("mesh.primitive_torus_add", text="Torus", icon='MESH_TORUS') + layout.operator("mesh.primitive_torus_add", icon='MESH_TORUS', text="Torus") class INFO_MT_curve_add(Menu): @@ -213,7 +214,7 @@ class INFO_MT_curve_add(Menu): def draw(self, context): layout = self.layout - layout.operator_context = 'INVOKE_REGION_WIN' + layout.operator_context = 'EXEC_REGION_WIN' layout.operator("curve.primitive_bezier_curve_add", icon='CURVE_BEZCURVE', text="Bezier") layout.operator("curve.primitive_bezier_circle_add", icon='CURVE_BEZCIRCLE', text="Circle") layout.operator("curve.primitive_nurbs_curve_add", icon='CURVE_NCURVE', text="Nurbs Curve") @@ -221,6 +222,22 @@ class INFO_MT_curve_add(Menu): layout.operator("curve.primitive_nurbs_path_add", icon='CURVE_PATH', text="Path") +class INFO_MT_surface_add(Menu): + bl_idname = "INFO_MT_surface_add" + bl_label = "Surface" + + def draw(self, context): + layout = self.layout + + layout.operator_context = 'EXEC_REGION_WIN' + layout.operator("surface.primitive_nurbs_surface_curve_add", icon='SURFACE_NCURVE', text="NURBS Curve") + layout.operator("surface.primitive_nurbs_surface_circle_add", icon='SURFACE_NCIRCLE', text="NURBS Circle") + layout.operator("surface.primitive_nurbs_surface_surface_add", icon='SURFACE_NSURFACE', text="NURBS Surface") + layout.operator("surface.primitive_nurbs_surface_cylinder_add", icon='SURFACE_NCYLINDER', text="NURBS Cylinder") + layout.operator("surface.primitive_nurbs_surface_sphere_add", icon='SURFACE_NSPHERE', text="NURBS Sphere") + layout.operator("surface.primitive_nurbs_surface_torus_add", icon='SURFACE_NTORUS', text="NURBS Torus") + + class INFO_MT_edit_curve_add(Menu): bl_idname = "INFO_MT_edit_curve_add" bl_label = "Add" @@ -229,7 +246,7 @@ class INFO_MT_edit_curve_add(Menu): is_surf = context.active_object.type == 'SURFACE' layout = self.layout - layout.operator_context = 'INVOKE_REGION_WIN' + layout.operator_context = 'EXEC_REGION_WIN' if is_surf: INFO_MT_surface_add.draw(self, context) @@ -237,22 +254,6 @@ class INFO_MT_edit_curve_add(Menu): INFO_MT_curve_add.draw(self, context) -class INFO_MT_surface_add(Menu): - bl_idname = "INFO_MT_surface_add" - bl_label = "Surface" - - def draw(self, context): - layout = self.layout - - layout.operator_context = 'INVOKE_REGION_WIN' - layout.operator("surface.primitive_nurbs_surface_curve_add", icon='SURFACE_NCURVE', text="NURBS Curve") - layout.operator("surface.primitive_nurbs_surface_circle_add", icon='SURFACE_NCIRCLE', text="NURBS Circle") - layout.operator("surface.primitive_nurbs_surface_surface_add", icon='SURFACE_NSURFACE', text="NURBS Surface") - layout.operator("surface.primitive_nurbs_surface_cylinder_add", icon='SURFACE_NCYLINDER', text="NURBS Cylinder") - layout.operator("surface.primitive_nurbs_surface_sphere_add", icon='SURFACE_NSPHERE', text="NURBS Sphere") - layout.operator("surface.primitive_nurbs_surface_torus_add", icon='SURFACE_NTORUS', text="NURBS Torus") - - class INFO_MT_armature_add(Menu): bl_idname = "INFO_MT_armature_add" bl_label = "Armature" @@ -260,7 +261,7 @@ class INFO_MT_armature_add(Menu): def draw(self, context): layout = self.layout - layout.operator_context = 'INVOKE_REGION_WIN' + layout.operator_context = 'EXEC_REGION_WIN' layout.operator("object.armature_add", text="Single Bone", icon='BONE_DATA') @@ -272,7 +273,9 @@ class INFO_MT_add(Menu): # note, don't use 'EXEC_SCREEN' or operators wont get the 'v3d' context. - layout.operator_context = 'EXEC_AREA' + # Note: was EXEC_AREA, but this context does not have the 'rv3d', which prevents + # "align_view" to work on first call (see [#32719]). + layout.operator_context = 'EXEC_REGION_WIN' #layout.operator_menu_enum("object.mesh_add", "type", text="Mesh", icon='OUTLINER_OB_MESH') layout.menu("INFO_MT_mesh_add", icon='OUTLINER_OB_MESH') @@ -282,20 +285,18 @@ class INFO_MT_add(Menu): #layout.operator_menu_enum("object.surface_add", "type", text="Surface", icon='OUTLINER_OB_SURFACE') layout.menu("INFO_MT_surface_add", icon='OUTLINER_OB_SURFACE') layout.operator_menu_enum("object.metaball_add", "type", text="Metaball", icon='OUTLINER_OB_META') - layout.operator_context = 'INVOKE_REGION_WIN' layout.operator("object.text_add", text="Text", icon='OUTLINER_OB_FONT') layout.separator() layout.menu("INFO_MT_armature_add", icon='OUTLINER_OB_ARMATURE') layout.operator("object.add", text="Lattice", icon='OUTLINER_OB_LATTICE').type = 'LATTICE' - layout.operator("object.add", text="Empty", icon='OUTLINER_OB_EMPTY').type = 'EMPTY' + layout.operator_menu_enum("object.empty_add", "type", text="Empty", icon='OUTLINER_OB_EMPTY') layout.separator() layout.operator("object.speaker_add", text="Speaker", icon='OUTLINER_OB_SPEAKER') layout.separator() layout.operator("object.camera_add", text="Camera", icon='OUTLINER_OB_CAMERA') - layout.operator_context = 'EXEC_AREA' layout.operator_menu_enum("object.lamp_add", "type", text="Lamp", icon='OUTLINER_OB_LAMP') layout.separator() @@ -303,7 +304,7 @@ class INFO_MT_add(Menu): layout.separator() if(len(bpy.data.groups) > 10): - layout.operator_context = 'INVOKE_DEFAULT' + layout.operator_context = 'INVOKE_REGION_WIN' layout.operator("object.group_instance_add", text="Group Instance...", icon='OUTLINER_OB_EMPTY') else: layout.operator_menu_enum("object.group_instance_add", "group", text="Group Instance", icon='OUTLINER_OB_EMPTY') diff --git a/release/scripts/startup/bl_ui/space_logic.py b/release/scripts/startup/bl_ui/space_logic.py index 846169b3339..730398171d6 100644 --- a/release/scripts/startup/bl_ui/space_logic.py +++ b/release/scripts/startup/bl_ui/space_logic.py @@ -107,5 +107,10 @@ class LOGIC_MT_view(Menu): layout.operator("logic.properties", icon='MENU_PANEL') + layout.separator() + + layout.operator("screen.area_dupli") + layout.operator("screen.screen_full_area") + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index 5b7ecbfb618..c46b1c20738 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -166,11 +166,19 @@ class NODE_MT_node(Menu): layout.operator("node.delete_reconnect") layout.separator() + + layout.operator("node.join", text="Join in new Frame") + layout.operator("node.detach", text="Remove from Frame") + + layout.separator() + layout.operator("node.link_make") layout.operator("node.link_make", text="Make and Replace Links").replace = True layout.operator("node.links_cut") + layout.operator("node.links_detach") layout.separator() + layout.operator("node.group_edit") layout.operator("node.group_ungroup") layout.operator("node.group_make") diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 39c892930f4..14fbc7c34be 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -83,11 +83,11 @@ class SEQUENCER_HT_header(Header): layout.separator() layout.operator("sequencer.refresh_all") - elif st.view_type == 'SEQUENCER_PREVIEW': - layout.separator() - layout.operator("sequencer.refresh_all") - layout.prop(st, "display_channel", text="Channel") else: + if st.view_type == 'SEQUENCER_PREVIEW': + layout.separator() + layout.operator("sequencer.refresh_all") + layout.prop(st, "display_channel", text="Channel") ed = context.scene.sequence_editor @@ -101,12 +101,12 @@ class SEQUENCER_HT_header(Header): row = layout.row() row.prop(st, "overlay_type", text="") - row = layout.row(align=True) - props = row.operator("render.opengl", text="", icon='RENDER_STILL') - props.sequencer = True - props = row.operator("render.opengl", text="", icon='RENDER_ANIMATION') - props.animation = True - props.sequencer = True + row = layout.row(align=True) + props = row.operator("render.opengl", text="", icon='RENDER_STILL') + props.sequencer = True + props = row.operator("render.opengl", text="", icon='RENDER_ANIMATION') + props.animation = True + props.sequencer = True layout.template_running_jobs() @@ -130,12 +130,19 @@ class SEQUENCER_MT_view(Menu): st = context.space_data + if st.view_type in {'PREVIEW'}: + # Specifying the REGION_PREVIEW context is needed in preview-only + # mode, else the lookup for the shortcut will fail in + # wm_keymap_item_find_props() (see #32595). + layout.operator_context = 'INVOKE_REGION_PREVIEW' layout.operator("sequencer.properties", icon='MENU_PANEL') + layout.operator_context = 'INVOKE_DEFAULT' layout.separator() if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}: layout.operator("sequencer.view_all", text="View all Sequences") + layout.operator("sequencer.view_selected") if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}: layout.operator_context = 'INVOKE_REGION_PREVIEW' layout.operator("sequencer.view_all_preview", text="Fit preview in window") @@ -145,19 +152,21 @@ class SEQUENCER_MT_view(Menu): # # XXX, invokes in the header view # layout.operator("sequencer.view_ghost_border", text="Overlay Border") - layout.operator("sequencer.view_selected") + if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}: + layout.prop(st, "show_seconds") + layout.prop(st, "show_frame_indicator") - layout.prop(st, "show_seconds") - - layout.prop(st, "show_frame_indicator") - if st.display_mode == 'IMAGE': - layout.prop(st, "show_safe_margin") - if st.display_mode == 'WAVEFORM': - layout.prop(st, "show_separate_color") + if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}: + if st.display_mode == 'IMAGE': + layout.prop(st, "show_safe_margin") + elif st.display_mode == 'WAVEFORM': + layout.prop(st, "show_separate_color") layout.separator() - layout.prop(st, "use_marker_sync") - layout.separator() + + if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}: + layout.prop(st, "use_marker_sync") + layout.separator() layout.operator("screen.area_dupli") layout.operator("screen.screen_full_area") @@ -851,7 +860,6 @@ class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, Panel): render = context.scene.render col = layout.column() - col.active = False # Currently only opengl preview works! col.prop(render, "use_sequencer_gl_preview", text="Open GL Preview") col = layout.column() #col.active = render.use_sequencer_gl_preview diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py index eca9bc22db9..a64f8aa4aed 100644 --- a/release/scripts/startup/bl_ui/space_text.py +++ b/release/scripts/startup/bl_ui/space_text.py @@ -56,12 +56,17 @@ class TEXT_HT_header(Header): row.prop(st, "show_syntax_highlight", text="") if text: - row = layout.row() - row.operator("text.run_script") + osl = text.name.endswith(".osl") or text.name.endswith(".oso") - row = layout.row() - row.active = text.name.endswith(".py") - row.prop(text, "use_module") + if osl: + row = layout.row() + row.operator("node.shader_script_update") + else: + row = layout.row() + row.operator("text.run_script") + + row = layout.row() + row.prop(text, "use_module") row = layout.row() if text.filepath: @@ -149,12 +154,7 @@ class TEXT_MT_view(Menu): layout = self.layout layout.operator("text.properties", icon='MENU_PANEL') - - layout.separator() - - layout.operator("screen.area_dupli") - layout.operator("screen.screen_full_area") - + layout.separator() layout.operator("text.move", @@ -164,6 +164,11 @@ class TEXT_MT_view(Menu): text="Bottom of File", ).type = 'FILE_BOTTOM' + layout.separator() + + layout.operator("screen.area_dupli") + layout.operator("screen.screen_full_area") + class TEXT_MT_text(Menu): bl_label = "Text" diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py index ed1d2a0ae24..cb9e2444793 100644 --- a/release/scripts/startup/bl_ui/space_time.py +++ b/release/scripts/startup/bl_ui/space_time.py @@ -127,6 +127,11 @@ class TIME_MT_view(Menu): layout.operator("marker.camera_bind") + layout.separator() + + layout.operator("screen.area_dupli") + layout.operator("screen.screen_full_area") + class TIME_MT_cache(Menu): bl_label = "Cache" diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index b0b587056b1..455bf210ac2 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -20,7 +20,6 @@ import bpy from bpy.types import Header, Menu, Panel import os -import addon_utils def ui_items_general(col, context): @@ -93,7 +92,7 @@ class USERPREF_HT_header(Header): layout.operator("wm.keyconfig_import") layout.operator("wm.keyconfig_export") elif userpref.active_section == 'ADDONS': - layout.operator("wm.addon_install") + layout.operator("wm.addon_install", icon="FILESEL") layout.menu("USERPREF_MT_addons_dev_guides") elif userpref.active_section == 'THEMES': layout.operator("ui.reset_default_theme") @@ -249,7 +248,7 @@ class USERPREF_PT_interface(Panel): col.prop(view, "show_splash") if os.name == "nt": - col.prop(view, "quit_dialog") + col.prop(view, "use_quit_dialog") class USERPREF_PT_edit(Panel): @@ -300,9 +299,9 @@ class USERPREF_PT_edit(Panel): col.label(text="Grease Pencil:") col.prop(edit, "grease_pencil_manhattan_distance", text="Manhattan Distance") col.prop(edit, "grease_pencil_euclidean_distance", text="Euclidean Distance") - #~ col.prop(edit, "use_grease_pencil_simplify_stroke", text="Simplify Stroke") col.prop(edit, "grease_pencil_eraser_radius", text="Eraser Radius") col.prop(edit, "use_grease_pencil_smooth_stroke", text="Smooth Stroke") + col.prop(edit, "use_grease_pencil_simplify_stroke", text="Simplify Stroke") col.separator() col.separator() col.separator() @@ -325,6 +324,7 @@ class USERPREF_PT_edit(Panel): col.separator() col.prop(edit, "use_auto_keying", text="Auto Keyframing:") + col.prop(edit, "use_auto_keying_warning") sub = col.column() @@ -823,6 +823,7 @@ class USERPREF_PT_file(Panel): col.prop(paths, "use_filter_files") col.prop(paths, "show_hidden_files_datablocks") col.prop(paths, "hide_recent_locations") + col.prop(paths, "hide_system_bookmarks") col.prop(paths, "show_thumbnails") col.separator() @@ -866,7 +867,7 @@ class USERPREF_MT_ndof_settings(Menu): layout.separator() layout.label(text="Orbit options") - layout.prop(input_prefs, "ndof_turntable") + layout.row().prop(input_prefs, "ndof_view_rotate_method", text="") layout.prop(input_prefs, "ndof_roll_invert_axis") layout.prop(input_prefs, "ndof_tilt_invert_axis") layout.prop(input_prefs, "ndof_rotate_invert_axis") @@ -953,6 +954,8 @@ class USERPREF_PT_input(Panel, InputKeyMapPanel): sub = col.column() sub.label(text="NDOF Device:") sub.prop(inputs, "ndof_sensitivity", text="NDOF Sensitivity") + sub.prop(inputs, "ndof_orbit_sensitivity", text="NDOF Orbit Sensitivity") + sub.row().prop(inputs, "ndof_view_rotate_method", expand=True) row.separator() @@ -1031,11 +1034,16 @@ class USERPREF_PT_addons(Panel): box.label(l) def draw(self, context): + import addon_utils + layout = self.layout userpref = context.user_preferences used_ext = {ext.module for ext in userpref.addons} + userpref_addons_folder = os.path.join(userpref.filepaths.script_directory, "addons") + scripts_addons_folder = bpy.utils.user_resource('SCRIPTS', "addons") + # collect the categories that can be filtered on addons = [(mod, addon_utils.module_bl_info(mod)) for mod in addon_utils.modules(addon_utils.addons_fake_modules)] @@ -1081,10 +1089,12 @@ class USERPREF_PT_addons(Panel): continue # check if addon should be visible with current filters - if ((filter == "All") or - (filter == info["category"]) or - (filter == "Enabled" and is_enabled) or - (filter == "Disabled" and not is_enabled)): + if ((filter == "All") or + (filter == info["category"]) or + (filter == "Enabled" and is_enabled) or + (filter == "Disabled" and not is_enabled) or + (filter == "User" and (mod.__file__.startswith((scripts_addons_folder, userpref_addons_folder)))) + ): if search and search not in info["name"].lower(): if info["author"]: diff --git a/release/scripts/startup/bl_ui/space_userpref_keymap.py b/release/scripts/startup/bl_ui/space_userpref_keymap.py index 6646da4a91a..81d67aa662c 100644 --- a/release/scripts/startup/bl_ui/space_userpref_keymap.py +++ b/release/scripts/startup/bl_ui/space_userpref_keymap.py @@ -186,10 +186,10 @@ class InputKeyMapPanel: sub = split.column() subrow = sub.row(align=True) - if map_type in {'KEYBOARD', 'NDOF'}: + if map_type == 'KEYBOARD': subrow.prop(kmi, "type", text="", event=True) subrow.prop(kmi, "value", text="") - elif map_type == 'MOUSE': + elif map_type in {'MOUSE', 'NDOF'}: subrow.prop(kmi, "type", text="") subrow.prop(kmi, "value", text="") @@ -218,8 +218,8 @@ class InputKeyMapPanel: layout.context_pointer_set("keymap", km) filtered_items = [kmi for kmi in km.keymap_items - if filter_text in kmi.idname.lower() or - filter_text in kmi.name.lower()] + if (filter_text in kmi.idname.lower() or + filter_text in kmi.name.lower())] if filtered_items: col = layout.column() diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 5db103466a9..6361a0dfc27 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -223,8 +223,8 @@ class VIEW3D_MT_transform_armature(VIEW3D_MT_transform_base): layout.separator() obj = context.object - if (obj.type == 'ARMATURE' and obj.mode in {'EDIT', 'POSE'} and - obj.data.draw_type in {'BBONE', 'ENVELOPE'}): + if (obj.type == 'ARMATURE' and obj.mode in {'EDIT', 'POSE'} and + obj.data.draw_type in {'BBONE', 'ENVELOPE'}): layout.operator("transform.transform", text="Scale Envelope/BBone").mode = 'BONE_SIZE' if context.edit_object and context.edit_object.type == 'ARMATURE': @@ -571,7 +571,7 @@ class VIEW3D_MT_select_edit_mesh(Menu): layout.separator() layout.operator("mesh.select_random", text="Random") - layout.operator("mesh.select_nth", text="Every N Number of Verts") + layout.operator("mesh.select_nth") layout.operator("mesh.edges_select_sharp", text="Sharp Edges") layout.operator("mesh.faces_select_linked_flat", text="Linked Flat Faces") layout.operator("mesh.select_interior_faces", text="Interior Faces") @@ -579,11 +579,11 @@ class VIEW3D_MT_select_edit_mesh(Menu): layout.separator() - layout.operator("mesh.select_by_number_vertices", text="By Number of Verts") - if context.scene.tool_settings.mesh_select_mode[2] == False: + layout.operator("mesh.select_face_by_sides") + if context.scene.tool_settings.mesh_select_mode[2] is False: layout.operator("mesh.select_non_manifold", text="Non Manifold") layout.operator("mesh.select_loose_verts", text="Loose Verts/Edges") - layout.operator("mesh.select_similar", text="Similar") + layout.operator_menu_enum("mesh.select_similar", "type", text="Similar") layout.separator() @@ -722,6 +722,7 @@ class VIEW3D_MT_select_edit_armature(Menu): props.extend = True props.direction = 'CHILD' + layout.operator_menu_enum("armature.select_similar", "type", text="Similar") layout.operator("object.select_pattern", text="Select Pattern...") @@ -806,7 +807,8 @@ class VIEW3D_MT_object_animation(Menu): layout = self.layout layout.operator("anim.keyframe_insert_menu", text="Insert Keyframe...") - layout.operator("anim.keyframe_delete_v3d", text="Delete Keyframe...") + layout.operator("anim.keyframe_delete_v3d", text="Delete Keyframes...") + layout.operator("anim.keyframe_clear_v3d", text="Clear Keyframes...") layout.operator("anim.keying_set_active_set", text="Change Keying Set...") layout.separator() @@ -966,8 +968,9 @@ class VIEW3D_MT_object_parent(Menu): def draw(self, context): layout = self.layout - layout.operator_menu_enum("object.parent_set", "type", text="Set") - layout.operator_menu_enum("object.parent_clear", "type", text="Clear") + layout.operator_enum("object.parent_set", "type") + layout.separator() + layout.operator_enum("object.parent_clear", "type") class VIEW3D_MT_object_track(Menu): @@ -976,8 +979,9 @@ class VIEW3D_MT_object_track(Menu): def draw(self, context): layout = self.layout - layout.operator_menu_enum("object.track_set", "type", text="Set") - layout.operator_menu_enum("object.track_clear", "type", text="Clear") + layout.operator_enum("object.track_set", "type") + layout.separator() + layout.operator_enum("object.track_clear", "type") class VIEW3D_MT_object_group(Menu): @@ -1245,6 +1249,8 @@ class VIEW3D_MT_paint_weight(Menu): layout.operator("object.vertex_group_clean", text="Clean") layout.operator("object.vertex_group_levels", text="Levels") layout.operator("object.vertex_group_blend", text="Blend") + layout.operator("object.vertex_group_transfer_weight", text="Transfer Weights") + layout.operator("object.vertex_group_limit_total", text="Limit Total") layout.operator("object.vertex_group_fix", text="Fix Deforms") layout.separator() @@ -1281,6 +1287,7 @@ class VIEW3D_MT_sculpt(Menu): layout.prop(sculpt, "show_low_resolution") layout.prop(sculpt, "show_brush") layout.prop(sculpt, "use_deform_only") + layout.prop(sculpt, "show_diffuse_color") class VIEW3D_MT_hide_mask(Menu): @@ -1526,13 +1533,20 @@ class VIEW3D_MT_pose_group(Menu): def draw(self, context): layout = self.layout - layout.operator("pose.group_add") - layout.operator("pose.group_remove") + + pose = context.active_object.pose - layout.separator() + layout.operator_context = 'EXEC_AREA' + layout.operator("pose.group_assign", text="Assign to New Group").type = 0 + if pose.bone_groups: + active_group = pose.bone_groups.active_index + 1 + layout.operator("pose.group_assign", text="Assign to Group").type = active_group - layout.operator("pose.group_assign") - layout.operator("pose.group_unassign") + layout.separator() + + #layout.operator_context = 'INVOKE_AREA' + layout.operator("pose.group_unassign") + layout.operator("pose.group_remove") class VIEW3D_MT_pose_ik(Menu): @@ -1657,7 +1671,7 @@ class VIEW3D_MT_edit_mesh(Menu): layout.menu("VIEW3D_MT_uv_map", text="UV Unwrap...") layout.separator() - + layout.operator("mesh.symmetrize") layout.operator("view3d.edit_mesh_extrude_move_normal", text="Extrude Region") layout.operator("view3d.edit_mesh_extrude_individual_move", text="Extrude Individual") layout.operator("mesh.duplicate_move") @@ -1699,6 +1713,7 @@ class VIEW3D_MT_edit_mesh_specials(Menu): layout.operator("mesh.select_all", text="Select Inverse").action = 'INVERT' layout.operator("mesh.flip_normals") layout.operator("mesh.vertices_smooth", text="Smooth") + layout.operator("mesh.vertices_smooth_laplacian", text="Laplacian Smooth") layout.operator("mesh.inset") layout.operator("mesh.bevel", text="Bevel") layout.operator("mesh.bridge_edge_loops") @@ -1708,6 +1723,7 @@ class VIEW3D_MT_edit_mesh_specials(Menu): layout.operator("mesh.shape_propagate_to_all") layout.operator("mesh.select_vertex_path") layout.operator("mesh.sort_elements") + layout.operator("mesh.symmetrize") class VIEW3D_MT_edit_mesh_select_mode(Menu): @@ -1774,6 +1790,7 @@ class VIEW3D_MT_edit_mesh_vertices(Menu): layout.operator("mesh.merge") layout.operator("mesh.rip_move") + layout.operator("mesh.rip_move_fill") layout.operator("mesh.split") layout.operator_menu_enum("mesh.separate", "type") layout.operator("mesh.vert_connect") @@ -1808,6 +1825,7 @@ class VIEW3D_MT_edit_mesh_edges(Menu): layout.operator("mesh.edge_face_add") layout.operator("mesh.subdivide") + layout.operator("mesh.unsubdivide") layout.separator() @@ -1925,10 +1943,6 @@ class VIEW3D_MT_edit_mesh_dissolve(Menu): layout.separator() - layout.operator_enum("mesh.dissolve", "type") - - layout.separator() - layout.operator("mesh.dissolve_limited") @@ -2143,6 +2157,7 @@ class VIEW3D_MT_edit_lattice(Menu): layout.menu("VIEW3D_MT_transform") layout.menu("VIEW3D_MT_mirror") layout.menu("VIEW3D_MT_snap") + layout.operator_menu_enum("lattice.flip", "axis") layout.separator() @@ -2280,7 +2295,7 @@ class VIEW3D_PT_view3d_properties(Panel): if lock_object.type == 'ARMATURE': col.prop_search(view, "lock_bone", lock_object.data, "edit_bones" if lock_object.mode == 'EDIT' - else "bones", + else "bones", text="") else: col.prop(view, "lock_cursor", text="Lock to Cursor") @@ -2298,6 +2313,9 @@ class VIEW3D_PT_view3d_properties(Panel): subcol.label(text="Local Camera:") subcol.prop(view, "camera", text="") + col = layout.column(align=True) + col.prop(view, "use_render_border") + class VIEW3D_PT_view3d_cursor(Panel): bl_space_type = 'VIEW_3D' diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 1b67b30d17a..49355de4006 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -520,8 +520,8 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel): row = col.row(align=True) ups = toolsettings.unified_paint_settings - if ((ups.use_unified_size and ups.use_locked_size) or - ((not ups.use_unified_size) and brush.use_locked_size)): + if ((ups.use_unified_size and ups.use_locked_size) or + ((not ups.use_unified_size) and brush.use_locked_size)): self.prop_unified_size(row, context, brush, "use_locked_size", icon='LOCKED') self.prop_unified_size(row, context, brush, "unprojected_radius", slider=True, text="Radius") else: @@ -707,8 +707,8 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel): @classmethod def poll(cls, context): settings = cls.paint_settings(context) - return (settings and settings.brush and (context.sculpt_object or - context.image_paint_object)) + return (settings and settings.brush and + (context.sculpt_object or context.image_paint_object)) def draw(self, context): layout = self.layout @@ -747,10 +747,12 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel): @classmethod def poll(cls, context): settings = cls.paint_settings(context) - return (settings and settings.brush and (context.sculpt_object or - context.vertex_paint_object or - context.weight_paint_object or - context.image_paint_object)) + return (settings and + settings.brush and + (context.sculpt_object or + context.vertex_paint_object or + context.weight_paint_object or + context.image_paint_object)) def draw(self, context): layout = self.layout @@ -876,6 +878,7 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel): layout.prop(sculpt, "show_low_resolution") layout.prop(sculpt, "show_brush") layout.prop(sculpt, "use_deform_only") + layout.prop(sculpt, "show_diffuse_color") layout.prop(sculpt, "input_samples") @@ -965,6 +968,8 @@ class VIEW3D_PT_tools_weightpaint(View3DPanel, Panel): col.operator("object.vertex_group_clean", text="Clean") col.operator("object.vertex_group_levels", text="Levels") col.operator("object.vertex_group_blend", text="Blend") + col.operator("object.vertex_group_transfer_weight", text="Transfer Weights") + col.operator("object.vertex_group_limit_total", text="Limit Total") col.operator("object.vertex_group_fix", text="Fix Deforms") diff --git a/release/scripts/startup/keyingsets_builtins.py b/release/scripts/startup/keyingsets_builtins.py index b7693880f9c..6ad87375738 100644 --- a/release/scripts/startup/keyingsets_builtins.py +++ b/release/scripts/startup/keyingsets_builtins.py @@ -360,10 +360,10 @@ class BUILTIN_KSI_WholeCharacter(KeyingSetInfo): # add rotation properties if they will if bone.lock_rotations_4d: # can check individually - if (bone.lock_rotation == (False, False, False)) and (bone.lock_rotation_w == False): + if (bone.lock_rotation == (False, False, False)) and (bone.lock_rotation_w is False): ksi.addProp(ks, bone, prop) else: - if bone.lock_rotation_w == False: + if bone.lock_rotation_w is False: ksi.addProp(ks, bone, prop, 0) # w = 0 for i in range(3): diff --git a/release/scripts/templates/addon_add_object.py b/release/scripts/templates/addon_add_object.py index d7fc23f9242..a4df5fb7436 100644 --- a/release/scripts/templates/addon_add_object.py +++ b/release/scripts/templates/addon_add_object.py @@ -39,10 +39,9 @@ def add_object(self, context): class OBJECT_OT_add_object(Operator, AddObjectHelper): - """Add a Mesh Object""" + """Create a new Mesh Object""" bl_idname = "mesh.add_object" bl_label = "Add Mesh Object" - bl_description = "Create a new Mesh Object" bl_options = {'REGISTER', 'UNDO'} scale = FloatVectorProperty( @@ -82,6 +81,7 @@ def register(): bpy.utils.register_manual_map(add_object_manual_map) bpy.types.INFO_MT_mesh_add.append(add_object_button) + def unregister(): bpy.utils.unregister_class(OBJECT_OT_add_object) bpy.utils.unregister_manual_map(add_object_manual_map) diff --git a/release/scripts/templates/script_stub.py b/release/scripts/templates/script_stub.py new file mode 100644 index 00000000000..3b3212892d5 --- /dev/null +++ b/release/scripts/templates/script_stub.py @@ -0,0 +1,11 @@ +# This stub runs a python script relative to the currently open +# blend file, useful when editing scripts externally. + +import bpy +import os + +# Use your own script name here: +filename = "my_script.py" + +filepath = os.path.join(os.path.dirname(bpy.data.filepath), filename) +exec(compile(open(filepath).read(), filepath, 'exec')) diff --git a/release/scripts/templates/ui_panel.py b/release/scripts/templates/ui_panel.py index 095fa105efa..cacdb83e815 100644 --- a/release/scripts/templates/ui_panel.py +++ b/release/scripts/templates/ui_panel.py @@ -12,36 +12,53 @@ class LayoutDemoPanel(bpy.types.Panel): def draw(self, context): layout = self.layout - sc = context.scene - - #Create a simple row. + scene = context.scene + + # Create a simple row. layout.label(text=" Simple Row:") - + row = layout.row() - row.prop(sc, "frame_start") - row.prop(sc, "frame_end") - - #Create an row where the buttons are aligned to each other. - layout.label(text=" Aligned Row") - + row.prop(scene, "frame_start") + row.prop(scene, "frame_end") + + # Create an row where the buttons are aligned to each other. + layout.label(text=" Aligned Row:") + row = layout.row(align=True) - row.prop(sc, "frame_start") - row.prop(sc, "frame_end") - - #Create two columns, by using a split layout. + row.prop(scene, "frame_start") + row.prop(scene, "frame_end") + + # Create two columns, by using a split layout. split = layout.split() - + # First column col = split.column() col.label(text="Column One:") - col.prop(sc, "frame_end") - col.prop(sc, "frame_start") - + col.prop(scene, "frame_end") + col.prop(scene, "frame_start") + # Second column, aligned col = split.column(align=True) - col.label(text="Column Two") - col.prop(sc, "frame_start") - col.prop(sc, "frame_end") + col.label(text="Column Two:") + col.prop(scene, "frame_start") + col.prop(scene, "frame_end") + + # Big render button + layout.label(text="Big Button:") + row = layout.row() + row.scale_y = 3.0 + row.operator("render.render") + + # Different sizes in a row + layout.label(text="Different button sizes:") + row = layout.row(align=True) + row.operator("render.render") + + sub = row.row() + sub.scale_x = 2.0 + sub.operator("render.render") + + row.operator("render.render") def register(): diff --git a/release/scripts/templates/ui_panel_simple.py b/release/scripts/templates/ui_panel_simple.py index 3fab7d92675..9bcc750560f 100644 --- a/release/scripts/templates/ui_panel_simple.py +++ b/release/scripts/templates/ui_panel_simple.py @@ -22,6 +22,9 @@ class HelloWorldPanel(bpy.types.Panel): row = layout.row() row.prop(obj, "name") + row = layout.row() + row.operator("mesh.primitive_cube_add") + def register(): bpy.utils.register_class(HelloWorldPanel) diff --git a/release/text/readme.html b/release/text/readme.html index 512ba32bac0..40ea9035835 100644 --- a/release/text/readme.html +++ b/release/text/readme.html @@ -20,7 +20,7 @@


      2.64

      -

      The Blender Foundation and online developer community is proud to present Blender 2.64. This release is the fifth official stable release of the Blender 2.6 series, in which we will refine the 2.5 series and add exciting new features. More information about this release.

      +

      The Blender Foundation and online developer community is proud to present Blender 2.64. This release is the fifth official stable release of the Blender 2.6 series, in which we will refine the 2.5 series and add exciting new features. More information about this release.


      Bugs

      Although Blender 2.64 is considered a stable release, you may encounter a bug. If you do, please help us by posting it in the bug tracker or using Help → Report a Bug from inside Blender. If it wasn’t reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.

      diff --git a/release/windows/contrib/vfapi/vfapi-plugin.c b/release/windows/contrib/vfapi/vfapi-plugin.c index 81547b8bb1a..99ca6c64e80 100644 --- a/release/windows/contrib/vfapi/vfapi-plugin.c +++ b/release/windows/contrib/vfapi/vfapi-plugin.c @@ -15,7 +15,6 @@ * */ - #include #include #include @@ -83,16 +82,16 @@ typedef struct { } VF_ReadData_Audio,*LPVF_ReadData_Audio; typedef struct { - DWORD dwSize; - HRESULT (__stdcall *OpenFile)( - char *lpFileName, LPVF_FileHandle lpFileHandle ); + DWORD dwSize; + HRESULT (__stdcall *OpenFile)( + char *lpFileName, LPVF_FileHandle lpFileHandle ); HRESULT (__stdcall *CloseFile)( VF_FileHandle hFileHandle ); HRESULT (__stdcall *GetFileInfo)( VF_FileHandle hFileHandle, - LPVF_FileInfo lpFileInfo ); + LPVF_FileInfo lpFileInfo ); HRESULT (__stdcall *GetStreamInfo)( VF_FileHandle hFileHandle, - DWORD dwStream,void *lpStreamInfo ); + DWORD dwStream,void *lpStreamInfo ); HRESULT (__stdcall *ReadData)( VF_FileHandle hFileHandle, - DWORD dwStream,void *lpData ); + DWORD dwStream,void *lpData ); } VF_PluginFunc,*LPVF_PluginFunc; __declspec(dllexport) HRESULT vfGetPluginInfo( @@ -117,8 +116,9 @@ static unsigned long getipaddress(const char * ipaddr) struct hostent *host; unsigned long ip; - if (((ip = inet_addr(ipaddr)) == INADDR_NONE) - && strcmp(ipaddr, "255.255.255.255") != 0) { + if (((ip = inet_addr(ipaddr)) == INADDR_NONE) && + strcmp(ipaddr, "255.255.255.255") != 0) + { if ((host = gethostbyname(ipaddr)) != NULL) { memcpy(&ip, host->h_addr, sizeof(ip)); } @@ -157,7 +157,8 @@ static int my_gets(SOCKET sock, char * line, int maxlen) line++; *line = 0; break; - } else { + } + else { line++; maxlen--; } @@ -187,7 +188,7 @@ HRESULT __stdcall VF_OpenFileFunc_Blen( SOCKET s_in; char buf[256]; struct sockaddr_in addr; - FILE* fp; + FILE *fp; p = lpFileName; while (*p && *p != '.') p++; @@ -228,7 +229,7 @@ HRESULT __stdcall VF_OpenFileFunc_Blen( return VF_ERROR; } - rval = (conndesc*) malloc(sizeof(conndesc)); + rval = (conndesc *) malloc(sizeof(conndesc)); rval->addr = addr; @@ -251,15 +252,20 @@ HRESULT __stdcall VF_OpenFileFunc_Blen( if (strcmp(key, "width") == 0) { rval->width = atoi(val); - } else if (strcmp(key, "height") == 0) { + } + else if (strcmp(key, "height") == 0) { rval->height = atoi(val); - } else if (strcmp(key, "start") == 0) { + } + else if (strcmp(key, "start") == 0) { rval->start = atoi(val); - } else if (strcmp(key, "end") == 0) { + } + else if (strcmp(key, "end") == 0) { rval->end = atoi(val); - } else if (strcmp(key, "rate") == 0) { + } + else if (strcmp(key, "rate") == 0) { rval->rate = atoi(val); - } else if (strcmp(key, "ratescale") == 0) { + } + else if (strcmp(key, "ratescale") == 0) { rval->ratescale = atoi(val); } } @@ -275,7 +281,7 @@ HRESULT __stdcall VF_OpenFileFunc_Blen( HRESULT __stdcall VF_CloseFileFunc_Blen( VF_FileHandle hFileHandle ) { - free((conndesc*) hFileHandle); + free((conndesc *) hFileHandle); return VF_OK; } @@ -284,7 +290,7 @@ HRESULT __stdcall VF_GetFileInfoFunc_Blen( VF_FileHandle hFileHandle, LPVF_FileInfo lpFileInfo ) { - conndesc * c = (conndesc*) hFileHandle; + conndesc *c = (conndesc *) hFileHandle; if (c == 0) { return VF_ERROR; } @@ -376,13 +382,13 @@ HRESULT __stdcall VF_ReadDataFunc_Blen( my_gets(s_in, buf, 256); /* 255 */ - framebuf = (unsigned char*) v->lpData; + framebuf = (unsigned char *) v->lpData; for (y = 0; y < height; y++) { - unsigned char * p = framebuf + v->lPitch * y; - unsigned char * e = p + width * 3; + unsigned char *p = framebuf + v->lPitch * y; + unsigned char *e = p + width * 3; - my_recv(s_in, (char*) p, width * 3); + my_recv(s_in, (char *)p, width * 3); while (p != e) { unsigned char tmp = p[2]; p[2] = p[0]; @@ -413,6 +419,3 @@ __declspec(dllexport) HRESULT vfGetPluginFunc( return VF_OK; } - - - diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt index 92785804b01..ae3f3dce396 100644 --- a/source/blender/CMakeLists.txt +++ b/source/blender/CMakeLists.txt @@ -101,7 +101,6 @@ add_subdirectory(blenloader) add_subdirectory(ikplugin) add_subdirectory(gpu) add_subdirectory(imbuf) -add_subdirectory(avi) add_subdirectory(nodes) add_subdirectory(modifiers) add_subdirectory(makesdna) @@ -124,6 +123,10 @@ if(WITH_IMAGE_CINEON) add_subdirectory(imbuf/intern/cineon) endif() +if(WITH_CODEC_AVI) + add_subdirectory(avi) +endif() + if(WITH_CODEC_QUICKTIME) add_subdirectory(quicktime) endif() diff --git a/source/blender/avi/AVI_avi.h b/source/blender/avi/AVI_avi.h index bdfdbc117ed..4dc52970119 100644 --- a/source/blender/avi/AVI_avi.h +++ b/source/blender/avi/AVI_avi.h @@ -178,7 +178,7 @@ typedef struct _AviStreamRec { } AviStreamRec; typedef struct _AviMovie { - FILE *fp; + FILE *fp; int type; #define AVI_MOVIE_READ 0 diff --git a/source/blender/avi/CMakeLists.txt b/source/blender/avi/CMakeLists.txt index 79422dff917..292206d8cb9 100644 --- a/source/blender/avi/CMakeLists.txt +++ b/source/blender/avi/CMakeLists.txt @@ -35,19 +35,19 @@ set(INC_SYS set(SRC intern/avi.c - intern/avirgb.c - intern/codecs.c - intern/endian.c - intern/mjpeg.c - intern/options.c - intern/rgb32.c + intern/avi_rgb.c + intern/avi_codecs.c + intern/avi_endian.c + intern/avi_mjpeg.c + intern/avi_options.c + intern/avi_rgb32.c AVI_avi.h intern/avi_intern.h - intern/avirgb.h - intern/endian.h - intern/mjpeg.h - intern/rgb32.h + intern/avi_rgb.h + intern/avi_endian.h + intern/avi_mjpeg.h + intern/avi_rgb32.h ) blender_add_lib(bf_avi "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/avi/intern/avi.c b/source/blender/avi/intern/avi.c index 2845b2f95c9..e1732b0caae 100644 --- a/source/blender/avi/intern/avi.c +++ b/source/blender/avi/intern/avi.c @@ -32,7 +32,6 @@ * This is external code. */ - #include #include #include @@ -49,7 +48,7 @@ #include "AVI_avi.h" #include "avi_intern.h" -#include "endian.h" +#include "avi_endian.h" static int AVI_DEBUG = 0; static char DEBUG_FCC[4]; @@ -95,7 +94,7 @@ char *fcc_to_char(unsigned int fcc) DEBUG_FCC[2] = (fcc >> 16) & 127; DEBUG_FCC[3] = (fcc >> 24) & 127; - return DEBUG_FCC; + return DEBUG_FCC; } char *tcc_to_char(unsigned int tcc) @@ -105,7 +104,7 @@ char *tcc_to_char(unsigned int tcc) DEBUG_FCC[2] = 0; DEBUG_FCC[3] = 0; - return DEBUG_FCC; + return DEBUG_FCC; } int AVI_get_stream(AviMovie *movie, int avist_type, int stream_num) @@ -303,7 +302,7 @@ int AVI_is_avi(const char *name) MEM_freeN(movie.streams); fclose(movie.fp); - return 0; + return 0; } movie.streams[temp].sh.Type = GET_FCC(movie.fp); @@ -402,12 +401,12 @@ int AVI_is_avi(const char *name) } } - } + } if (j > 0) fseek(movie.fp, j, SEEK_CUR); } else fseek(movie.fp, movie.streams[temp].sf_size, SEEK_CUR); - /* Walk to the next LIST */ + /* Walk to the next LIST */ while (GET_FCC(movie.fp) != FCC("LIST")) { temp = GET_FCC(movie.fp); if (temp < 0 || ftell(movie.fp) > movie.size) { @@ -415,9 +414,9 @@ int AVI_is_avi(const char *name) MEM_freeN(movie.streams); fclose(movie.fp); - return 0; + return 0; } - fseek(movie.fp, temp, SEEK_CUR); + fseek(movie.fp, temp, SEEK_CUR); } fseek(movie.fp, -4L, SEEK_CUR); @@ -593,12 +592,12 @@ AviError AVI_open_movie(const char *name, AviMovie *movie) } } - } + } if (j > 0) fseek(movie->fp, j, SEEK_CUR); } else fseek(movie->fp, movie->streams[temp].sf_size, SEEK_CUR); - /* Walk to the next LIST */ + /* Walk to the next LIST */ while (GET_FCC(movie->fp) != FCC("LIST")) { temp = GET_FCC(movie->fp); if (temp < 0 || ftell(movie->fp) > movie->size) { @@ -828,7 +827,7 @@ AviError AVI_open_compress(char *name, AviMovie *movie, int streams, ...) movie->streams[i].sh.right = 0; movie->streams[i].sh.bottom = 0; - if (movie->streams[i].sh.Type == FCC("vids")) { + if (movie->streams[i].sh.Type == FCC("vids")) { #if 0 if (movie->streams[i].format == AVI_FORMAT_MJPEG) { movie->streams[i].sf = MEM_mallocN(sizeof(AviBitmapInfoHeader) + diff --git a/source/blender/avi/intern/codecs.c b/source/blender/avi/intern/avi_codecs.c similarity index 96% rename from source/blender/avi/intern/codecs.c rename to source/blender/avi/intern/avi_codecs.c index 01e228d570e..e43826064a6 100644 --- a/source/blender/avi/intern/codecs.c +++ b/source/blender/avi/intern/avi_codecs.c @@ -25,7 +25,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/avi/intern/codecs.c +/** \file blender/avi/intern/avi_codecs.c * \ingroup avi * * This is external code. Identify and convert different avi-files. @@ -35,9 +35,9 @@ #include "AVI_avi.h" #include "avi_intern.h" -#include "avirgb.h" -#include "mjpeg.h" -#include "rgb32.h" +#include "avi_rgb.h" +#include "avi_mjpeg.h" +#include "avi_rgb32.h" void *avi_format_convert(AviMovie *movie, int stream, void *buffer, AviFormat from, AviFormat to, int *size) { diff --git a/source/blender/avi/intern/endian.c b/source/blender/avi/intern/avi_endian.c similarity index 91% rename from source/blender/avi/intern/endian.c rename to source/blender/avi/intern/avi_endian.c index c9b95d25810..70add8bd90f 100644 --- a/source/blender/avi/intern/endian.c +++ b/source/blender/avi/intern/avi_endian.c @@ -26,7 +26,7 @@ * */ -/** \file blender/avi/intern/endian.c +/** \file blender/avi/intern/avi_endian.c * \ingroup avi * * This is external code. Streams bytes to output depending on the @@ -36,9 +36,10 @@ #include #include -#include +#include + #include "AVI_avi.h" -#include "endian.h" +#include "avi_endian.h" #include "avi_intern.h" #ifdef __BIG_ENDIAN__ @@ -46,31 +47,22 @@ #endif #ifdef __BIG_ENDIAN__ + +/* copied from BLI_endian_switch_inline.h */ static void invert(int *num) { - int new = 0, i, j; - - for (j = 0; j < 4; j++) { - for (i = 0; i < 8; i++) { - new |= ((*num >> (j * 8 + i)) & 1) << ((3 - j) * 8 + i); - } - } - - *num = new; + int tval = *val; + *val = ((tval >> 24)) | + ((tval << 8) & 0x00ff0000) | + ((tval >> 8) & 0x0000ff00) | + ((tval << 24)); } -static void sinvert(short int *num) +static void sinvert(short int *val) { - short int new = 0; - int i, j; - - for (j = 0; j < 2; j++) { - for (i = 0; i < 8; i++) { - new |= ((*num >> (j * 8 + i)) & 1) << ((1 - j) * 8 + i); - } - } - - *num = new; + short tval = *val; + *val = (tval >> 8) | + (tval << 8); } static void Ichunk(AviChunk *chunk) diff --git a/source/blender/avi/intern/endian.h b/source/blender/avi/intern/avi_endian.h similarity index 90% rename from source/blender/avi/intern/endian.h rename to source/blender/avi/intern/avi_endian.h index 7ef49cb1699..8cea283a553 100644 --- a/source/blender/avi/intern/endian.h +++ b/source/blender/avi/intern/avi_endian.h @@ -25,17 +25,14 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/avi/intern/endian.h +/** \file blender/avi/intern/avi_endian.h * \ingroup avi * * This is external code. */ -#ifndef __ENDIAN_H__ -#define __ENDIAN_H__ - -#include -#include "AVI_avi.h" +#ifndef __AVI_ENDIAN_H__ +#define __AVI_ENDIAN_H__ #define AVI_RAW 0 #define AVI_CHUNK 1 @@ -48,5 +45,4 @@ void awrite(AviMovie *movie, void *datain, int block, int size, FILE *fp, int type); -#endif - +#endif /* __AVI_ENDIAN_H__ */ diff --git a/source/blender/avi/intern/mjpeg.c b/source/blender/avi/intern/avi_mjpeg.c similarity index 99% rename from source/blender/avi/intern/mjpeg.c rename to source/blender/avi/intern/avi_mjpeg.c index a700284bf68..396f1199cd9 100644 --- a/source/blender/avi/intern/mjpeg.c +++ b/source/blender/avi/intern/avi_mjpeg.c @@ -26,21 +26,23 @@ * */ -/** \file blender/avi/intern/mjpeg.c +/** \file blender/avi/intern/avi_mjpeg.c * \ingroup avi * * This is external code. Converts between avi and mpeg/jpeg. */ - -#include "AVI_avi.h" #include #include -#include "jpeglib.h" -#include "jerror.h" + +#include "AVI_avi.h" + #include "MEM_guardedalloc.h" -#include "mjpeg.h" +#include "jpeglib.h" +#include "jerror.h" + +#include "avi_mjpeg.h" #define PADUP(num, amt) ((num + (amt - 1)) & ~(amt - 1)) @@ -71,7 +73,7 @@ static void std_huff_tables(j_decompress_ptr dinfo) 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; static const UINT8 val_dc_luminance[] = - { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; @@ -80,7 +82,7 @@ static void std_huff_tables(j_decompress_ptr dinfo) 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; static const UINT8 val_dc_chrominance[] = - { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; @@ -89,7 +91,7 @@ static void std_huff_tables(j_decompress_ptr dinfo) 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; static const UINT8 val_ac_luminance[] = - { + { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, @@ -117,7 +119,7 @@ static void std_huff_tables(j_decompress_ptr dinfo) 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; static const UINT8 val_ac_chrominance[] = - { + { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, @@ -391,7 +393,7 @@ void *avi_converter_to_mjpeg(AviMovie *movie, int stream, unsigned char *buffer, numbytes = 0; check_and_compress_jpeg(movie->streams[stream].sh.Quality / 100, buf + *size, buffer + (movie->header->Height / 2) * movie->header->Width * 3, movie->header->Width, movie->header->Height / 2, bufsize / 2); } - *size += numbytes; + *size += numbytes; MEM_freeN(buffer); return buf; diff --git a/source/blender/avi/intern/mjpeg.h b/source/blender/avi/intern/avi_mjpeg.h similarity index 91% rename from source/blender/avi/intern/mjpeg.h rename to source/blender/avi/intern/avi_mjpeg.h index 75649891f2b..6ae0e56ffa4 100644 --- a/source/blender/avi/intern/mjpeg.h +++ b/source/blender/avi/intern/avi_mjpeg.h @@ -25,11 +25,14 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/avi/intern/mjpeg.h +/** \file blender/avi/intern/avi_mjpeg.h * \ingroup avi */ +#ifndef __AVI_MJPEG_H__ +#define __AVI_MJPEG_H__ void *avi_converter_from_mjpeg (AviMovie *movie, int stream, unsigned char *buffer, int *size); void *avi_converter_to_mjpeg (AviMovie *movie, int stream, unsigned char *buffer, int *size); +#endif /* __AVI_MJPEG_H__ */ diff --git a/source/blender/avi/intern/options.c b/source/blender/avi/intern/avi_options.c similarity index 98% rename from source/blender/avi/intern/options.c rename to source/blender/avi/intern/avi_options.c index 7de91318ecf..f7759a1099f 100644 --- a/source/blender/avi/intern/options.c +++ b/source/blender/avi/intern/avi_options.c @@ -26,7 +26,7 @@ * */ -/** \file blender/avi/intern/options.c +/** \file blender/avi/intern/avi_options.c * \ingroup avi * * This is external code. Sets some compression related options @@ -35,7 +35,7 @@ #include "AVI_avi.h" #include "avi_intern.h" -#include "endian.h" +#include "avi_endian.h" #ifdef WIN32 # include "BLI_winstuff.h" diff --git a/source/blender/avi/intern/avirgb.c b/source/blender/avi/intern/avi_rgb.c similarity index 98% rename from source/blender/avi/intern/avirgb.c rename to source/blender/avi/intern/avi_rgb.c index 7a95972845a..11d9bdf8612 100644 --- a/source/blender/avi/intern/avirgb.c +++ b/source/blender/avi/intern/avi_rgb.c @@ -26,19 +26,19 @@ * */ -/** \file blender/avi/intern/avirgb.c +/** \file blender/avi/intern/avi_rgb.c * \ingroup avi * * This is external code. Converts rgb-type avi-s. */ - -#include "AVI_avi.h" #include #include #include "MEM_guardedalloc.h" -#include "avirgb.h" + +#include "AVI_avi.h" +#include "avi_rgb.h" /* implementation */ @@ -86,7 +86,7 @@ void *avi_converter_from_avi_rgb(AviMovie *movie, int stream, unsigned char *buf *(to++) = ((*pxl >> 10) & 0x1f) * 8; *(to++) = ((*pxl >> 5) & 0x1f) * 8; *(to++) = (*pxl & 0x1f) * 8; - pxl++; + pxl++; } } diff --git a/source/blender/avi/intern/avirgb.h b/source/blender/avi/intern/avi_rgb.h similarity index 76% rename from source/blender/avi/intern/avirgb.h rename to source/blender/avi/intern/avi_rgb.h index 20211d6ab2d..773166e9fab 100644 --- a/source/blender/avi/intern/avirgb.h +++ b/source/blender/avi/intern/avi_rgb.h @@ -25,11 +25,14 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/avi/intern/avirgb.h +/** \file blender/avi/intern/avi_rgb.h * \ingroup avi */ +#ifndef __AVI_RGB_H__ +#define __AVI_RGB_H__ -void *avi_converter_from_avi_rgb (AviMovie *movie, int stream, unsigned char *buffer, int *size); -void *avi_converter_to_avi_rgb (AviMovie *movie, int stream, unsigned char *buffer, int *size); +void *avi_converter_from_avi_rgb(AviMovie *movie, int stream, unsigned char *buffer, int *size); +void *avi_converter_to_avi_rgb(AviMovie *movie, int stream, unsigned char *buffer, int *size); +#endif /* __AVI_RGB_H__ */ diff --git a/source/blender/avi/intern/rgb32.c b/source/blender/avi/intern/avi_rgb32.c similarity index 97% rename from source/blender/avi/intern/rgb32.c rename to source/blender/avi/intern/avi_rgb32.c index 84630f09fe5..5c7a4889d97 100644 --- a/source/blender/avi/intern/rgb32.c +++ b/source/blender/avi/intern/avi_rgb32.c @@ -26,18 +26,19 @@ * */ -/** \file blender/avi/intern/rgb32.c +/** \file blender/avi/intern/avi_rgb32.c * \ingroup avi * * This is external code. Converts between rgb32 and avi. */ - -#include "AVI_avi.h" #include #include + #include "MEM_guardedalloc.h" -#include "rgb32.h" + +#include "AVI_avi.h" +#include "avi_rgb32.h" void *avi_converter_from_rgb32(AviMovie *movie, int stream, unsigned char *buffer, int *size) { diff --git a/source/blender/avi/intern/rgb32.h b/source/blender/avi/intern/avi_rgb32.h similarity index 76% rename from source/blender/avi/intern/rgb32.h rename to source/blender/avi/intern/avi_rgb32.h index 55f9771a4df..523f9e795fd 100644 --- a/source/blender/avi/intern/rgb32.h +++ b/source/blender/avi/intern/avi_rgb32.h @@ -25,11 +25,14 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/avi/intern/rgb32.h +/** \file blender/avi/intern/avi_rgb32.h * \ingroup avi */ +#ifndef __AVI_RGB32_H__ +#define __AVI_RGB32_H__ -void *avi_converter_from_rgb32 (AviMovie *movie, int stream, unsigned char *buffer, int *size); -void *avi_converter_to_rgb32 (AviMovie *movie, int stream, unsigned char *buffer, int *size); +void *avi_converter_from_rgb32(AviMovie *movie, int stream, unsigned char *buffer, int *size); +void *avi_converter_to_rgb32(AviMovie *movie, int stream, unsigned char *buffer, int *size); +#endif /* __AVI_RGB32_H__ */ diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index ce10951d6ff..6f348ccc267 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -109,6 +109,7 @@ float BLF_fixed_width(int fontid); * of the string, using the default font and both value * are multiplied by the aspect of the font. */ +void BLF_width_and_height_default(const char *str, float *width, float *height); float BLF_width_default(const char *str); float BLF_height_default(const char *str); diff --git a/source/blender/blenfont/BLF_translation.h b/source/blender/blenfont/BLF_translation.h index 56eabf4bb43..b01ce93cb65 100644 --- a/source/blender/blenfont/BLF_translation.h +++ b/source/blender/blenfont/BLF_translation.h @@ -49,9 +49,13 @@ const char *BLF_pgettext(const char *context, const char *message); /* Search the path directory to the locale files, this try all * the case for Linux, Win and Mac. + * Also dynamically builds locales and locales' menu from "languages" text file. */ void BLF_lang_init(void); +/* Free languages and locales_menu arrays created by BLF_lang_init. */ +void BLF_lang_free(void); + /* Set the current locale. */ void BLF_lang_set(const char *); /* Get the current locale (short code, e.g. es_ES). */ @@ -60,6 +64,9 @@ const char *BLF_lang_get(void); /* Set the current encoding name. */ void BLF_lang_encoding(const char *str); +/* Get EnumPropertyItem's for translations menu. */ +struct EnumPropertyItem *BLF_RNA_lang_enum_properties(void); + /* translation */ int BLF_translate_iface(void); int BLF_translate_tooltips(void); @@ -97,6 +104,8 @@ const char *BLF_translate_do_tooltip(const char *contex, const char *msgid); /* Default context for operator names/labels. */ #define BLF_I18NCONTEXT_OPERATOR_DEFAULT "Operator" +/* Audio disambiguation context. */ +#define BLF_I18NCONTEXT_AUDIO "Audio" #endif /* __BLF_TRANSLATION_H__ */ diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt index da60710a137..022dfd282b0 100644 --- a/source/blender/blenfont/CMakeLists.txt +++ b/source/blender/blenfont/CMakeLists.txt @@ -25,8 +25,10 @@ set(INC . ../blenkernel ../blenlib + ../blenloader ../editors/include ../makesdna + ../makesrna ../imbuf ../../../intern/guardedalloc ) diff --git a/source/blender/blenfont/SConscript b/source/blender/blenfont/SConscript index d3c7b1c2fcc..075da58b116 100644 --- a/source/blender/blenfont/SConscript +++ b/source/blender/blenfont/SConscript @@ -4,7 +4,8 @@ Import ('env') sources = env.Glob('intern/*.c') -incs = '. intern #/intern/guardedalloc ../blenkernel ../blenlib ../makesdna ../imbuf ../editors/include' +incs = '. intern #/intern/guardedalloc ../blenkernel ../blenlib ../blenloader' +incs += ' ../makesdna ../makesrna ../imbuf ../editors/include' incs += ' #/extern/glew/include' incs += ' ' + env['BF_FREETYPE_INC'] incs += ' ' + env['BF_GETTEXT_INC'] diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index 92fcb576e7d..f3cc92e7a27 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -69,7 +69,7 @@ static int global_font_dpi = 72; int blf_mono_font = -1; int blf_mono_font_render = -1; -static FontBLF *BLF_get(int fontid) +static FontBLF *blf_get(int fontid) { if (fontid >= 0 && fontid < BLF_MAX_FONT) return global_font[fontid]; @@ -141,6 +141,21 @@ static int blf_search_available(void) return -1; } +static int blf_global_font_init(void) +{ + if (global_font_default == -1) { + global_font_default = blf_search("default"); + } + + if (global_font_default == -1) { + printf("Warning: Can't find default font!\n"); + return 0; + } + else { + return 1; + } +} + int BLF_load(const char *name) { FontBLF *font; @@ -219,7 +234,7 @@ int BLF_load_unique(const char *name) void BLF_metrics_attach(int fontid, unsigned char *mem, int mem_size) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font) { blf_font_attach_from_mem(font, mem, mem_size); @@ -311,7 +326,7 @@ void BLF_unload(const char *name) void BLF_enable(int fontid, int option) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font) { font->flags |= option; @@ -320,7 +335,7 @@ void BLF_enable(int fontid, int option) void BLF_disable(int fontid, int option) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font) { font->flags &= ~option; @@ -329,7 +344,7 @@ void BLF_disable(int fontid, int option) void BLF_enable_default(int option) { - FontBLF *font = BLF_get(global_font_default); + FontBLF *font = blf_get(global_font_default); if (font) { font->flags |= option; @@ -338,7 +353,7 @@ void BLF_enable_default(int option) void BLF_disable_default(int option) { - FontBLF *font = BLF_get(global_font_default); + FontBLF *font = blf_get(global_font_default); if (font) { font->flags &= ~option; @@ -347,7 +362,7 @@ void BLF_disable_default(int option) void BLF_aspect(int fontid, float x, float y, float z) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font) { font->aspect[0] = x; @@ -358,7 +373,7 @@ void BLF_aspect(int fontid, float x, float y, float z) void BLF_matrix(int fontid, const double m[16]) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font) { memcpy(font->m, m, sizeof(font->m)); @@ -367,7 +382,7 @@ void BLF_matrix(int fontid, const double m[16]) void BLF_position(int fontid, float x, float y, float z) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font) { float xa, ya, za; @@ -416,7 +431,7 @@ void BLF_position(int fontid, float x, float y, float z) void BLF_size(int fontid, int size, int dpi) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font) { blf_font_size(font, size, dpi); @@ -425,7 +440,7 @@ void BLF_size(int fontid, int size, int dpi) void BLF_blur(int fontid, int size) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font) { font->blur = size; @@ -437,13 +452,8 @@ void BLF_draw_default(float x, float y, float z, const char *str, size_t len) if (!str) return; - if (global_font_default == -1) - global_font_default = blf_search("default"); - - if (global_font_default == -1) { - printf("Warning: Can't found default font!!\n"); + if (!blf_global_font_init()) return; - } BLF_size(global_font_default, global_font_points, global_font_dpi); BLF_position(global_font_default, x, y, z); @@ -456,13 +466,8 @@ void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t l if (!str) return; - if (global_font_default == -1) - global_font_default = blf_search("default"); - - if (global_font_default == -1) { - printf("Warning: Can't found default font!!\n"); + if (!blf_global_font_init()) return; - } BLF_size(global_font_default, global_font_points, global_font_dpi); BLF_position(global_font_default, x, y, z); @@ -471,7 +476,7 @@ void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t l void BLF_rotation_default(float angle) { - FontBLF *font = BLF_get(global_font_default); + FontBLF *font = blf_get(global_font_default); if (font) { font->angle = angle; @@ -543,7 +548,7 @@ static void blf_draw__end(GLint mode, GLint param) void BLF_draw(int fontid, const char *str, size_t len) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); GLint mode, param; if (font && font->glyph_cache) { @@ -555,7 +560,7 @@ void BLF_draw(int fontid, const char *str, size_t len) void BLF_draw_ascii(int fontid, const char *str, size_t len) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); GLint mode, param; if (font && font->glyph_cache) { @@ -567,7 +572,7 @@ void BLF_draw_ascii(int fontid, const char *str, size_t len) void BLF_boundbox(int fontid, const char *str, rctf *box) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font) { blf_font_boundbox(font, str, box); @@ -576,16 +581,29 @@ void BLF_boundbox(int fontid, const char *str, rctf *box) void BLF_width_and_height(int fontid, const char *str, float *width, float *height) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font && font->glyph_cache) { blf_font_width_and_height(font, str, width, height); } + else { + *width = *height = 0.0f; + } +} + +void BLF_width_and_height_default(const char *str, float *width, float *height) +{ + if (!blf_global_font_init()) { + *width = *height = 0.0f; + return; + } + + BLF_width_and_height(global_font_default, str, width, height); } float BLF_width(int fontid, const char *str) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font && font->glyph_cache) { return blf_font_width(font, str); @@ -596,7 +614,7 @@ float BLF_width(int fontid, const char *str) float BLF_fixed_width(int fontid) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font && font->glyph_cache) { return blf_font_fixed_width(font); @@ -607,13 +625,8 @@ float BLF_fixed_width(int fontid) float BLF_width_default(const char *str) { - if (global_font_default == -1) - global_font_default = blf_search("default"); - - if (global_font_default == -1) { - printf("Error: Can't found default font!!\n"); + if (!blf_global_font_init()) return 0.0f; - } BLF_size(global_font_default, global_font_points, global_font_dpi); return BLF_width(global_font_default, str); @@ -621,7 +634,7 @@ float BLF_width_default(const char *str) float BLF_height(int fontid, const char *str) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font && font->glyph_cache) { return blf_font_height(font, str); @@ -632,7 +645,7 @@ float BLF_height(int fontid, const char *str) float BLF_height_max(int fontid) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font && font->glyph_cache) { return font->glyph_cache->max_glyph_height; @@ -643,7 +656,7 @@ float BLF_height_max(int fontid) float BLF_width_max(int fontid) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font && font->glyph_cache) { return font->glyph_cache->max_glyph_width; @@ -654,7 +667,7 @@ float BLF_width_max(int fontid) float BLF_descender(int fontid) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font && font->glyph_cache) { return font->glyph_cache->descender; @@ -665,7 +678,7 @@ float BLF_descender(int fontid) float BLF_ascender(int fontid) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font && font->glyph_cache) { return font->glyph_cache->ascender; @@ -676,13 +689,8 @@ float BLF_ascender(int fontid) float BLF_height_default(const char *str) { - if (global_font_default == -1) - global_font_default = blf_search("default"); - - if (global_font_default == -1) { - printf("Error: Can't found default font!!\n"); + if (!blf_global_font_init()) return 0.0f; - } BLF_size(global_font_default, global_font_points, global_font_dpi); @@ -691,7 +699,7 @@ float BLF_height_default(const char *str) void BLF_rotation(int fontid, float angle) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font) { font->angle = angle; @@ -700,7 +708,7 @@ void BLF_rotation(int fontid, float angle) void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font) { font->clip_rec.xmin = xmin; @@ -712,7 +720,7 @@ void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax) void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax) { - FontBLF *font = BLF_get(global_font_default); + FontBLF *font = blf_get(global_font_default); if (font) { font->clip_rec.xmin = xmin; @@ -724,7 +732,7 @@ void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax) void BLF_shadow(int fontid, int level, float r, float g, float b, float a) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font) { font->shadow = level; @@ -737,7 +745,7 @@ void BLF_shadow(int fontid, int level, float r, float g, float b, float a) void BLF_shadow_offset(int fontid, int x, int y) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font) { font->shadow_x = x; @@ -747,7 +755,7 @@ void BLF_shadow_offset(int fontid, int x, int y) void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int nch, struct ColorManagedDisplay *display) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font) { font->buf_info.fbuf = fbuf; @@ -761,7 +769,7 @@ void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int void BLF_buffer_col(int fontid, float r, float g, float b, float a) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font) { font->buf_info.col[0] = r; @@ -773,7 +781,7 @@ void BLF_buffer_col(int fontid, float r, float g, float b, float a) void BLF_draw_buffer(int fontid, const char *str) { - FontBLF *font = BLF_get(fontid); + FontBLF *font = blf_get(fontid); if (font && font->glyph_cache && (font->buf_info.fbuf || font->buf_info.cbuf)) { blf_font_buffer(font, str); diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index 02b66993c0a..1900efa2dbc 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -174,7 +174,7 @@ void blf_font_draw(FontBLF *font, const char *str, size_t len) blf_font_ensure_ascii_table(font); - while (str[i] && i < len) { + while ((i < len) && str[i]) { BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table); if (c == BLI_UTF8_ERR) @@ -430,8 +430,8 @@ void blf_font_width_and_height(FontBLF *font, const char *str, float *width, flo } blf_font_boundbox(font, str, &box); - *width = (BLI_RCT_SIZE_X(&box) * xa); - *height = (BLI_RCT_SIZE_Y(&box) * ya); + *width = (BLI_rctf_size_x(&box) * xa); + *height = (BLI_rctf_size_y(&box) * ya); } float blf_font_width(FontBLF *font, const char *str) @@ -445,7 +445,7 @@ float blf_font_width(FontBLF *font, const char *str) xa = 1.0f; blf_font_boundbox(font, str, &box); - return BLI_RCT_SIZE_X(&box) * xa; + return BLI_rctf_size_x(&box) * xa; } float blf_font_height(FontBLF *font, const char *str) @@ -459,7 +459,7 @@ float blf_font_height(FontBLF *font, const char *str) ya = 1.0f; blf_font_boundbox(font, str, &box); - return BLI_RCT_SIZE_Y(&box) * ya; + return BLI_rctf_size_y(&box) * ya; } float blf_font_fixed_width(FontBLF *font) diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index 63225651e5b..91ecded88be 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -415,7 +415,7 @@ int blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y) g->uv[1][1] = ((float)(g->yoff + g->height)) / ((float)gc->p2_height); /* update the x offset for the next glyph. */ - gc->x_offs += (int)(BLI_RCT_SIZE_X(&g->box) + gc->pad); + gc->x_offs += (int)(BLI_rctf_size_x(&g->box) + gc->pad); gc->rem_glyphs--; g->build_tex = 1; diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c index d0b77222114..501f8cd2958 100644 --- a/source/blender/blenfont/intern/blf_lang.c +++ b/source/blender/blenfont/intern/blf_lang.c @@ -35,100 +35,196 @@ #include "BKE_global.h" #include "BLF_api.h" - #include "BLF_translation.h" /* own include */ #ifdef WITH_INTERNATIONAL #include -#if defined(_WIN32) -#include -#endif - #include "libintl.h" #include "DNA_userdef_types.h" -#include "DNA_listBase.h" -#include "DNA_vec_types.h" +#include "RNA_types.h" #include "MEM_guardedalloc.h" -#include "BLI_linklist.h" /* linknode */ #include "BLI_string.h" #include "BLI_utildefines.h" #include "BLI_path_util.h" +#include "BLI_fileops.h" +#include "BLI_linklist.h" +#include "BLI_string.h" #define SYSTEM_ENCODING_DEFAULT "UTF-8" #define FONT_SIZE_DEFAULT 12 -/* locale options. */ +/* Locale options. */ static char global_messagepath[1024]; static char global_language[32]; static char global_encoding_name[32]; -/* map from the rna_userdef.c:rna_def_userdef_system(BlenderRNA *brna):language_items */ -static const char *locales[] = { - "", "", - "english", "en_US", - "japanese", "ja_JP", - "dutch", "nl_NL", - "italian", "it_IT", - "german", "de_DE", - "finnish", "fi_FI", - "swedish", "sv_SE", - "french", "fr_FR", - "spanish", "es", - "catalan", "ca_AD", - "czech", "cs_CZ", - "portuguese", "pt_PT", -#if defined(_WIN32) && !defined(FREE_WINDOWS) - "Chinese (Simplified)_China.1252", "zh_CN", - "Chinese (Traditional)_China.1252", "zh_TW", -#else - "chs", "zh_CN", - "cht", "zh_TW", -#endif - "russian", "ru_RU", - "croatian", "hr_HR", - "serbian", "sr_RS", - "ukrainian", "uk_UA", - "polish", "pl_PL", - "romanian", "ro_RO", - "arabic", "ar_EG", - "bulgarian", "bg_BG", - "greek", "el_GR", - "korean", "ko_KR", - "nepali", "ne_NP", - "persian", "fa_IR", - "indonesian", "id_ID", - "serbian (latin)", "sr_RS@latin", - "kyrgyz", "ky_KG", - "turkish", "tr_TR", - "hungarian", "hu_HU", - "brazilian portuguese", "pt_BR", - "hebrew", "he_IL", -}; +static const char **locales = NULL; +static char **long_locales = NULL; /* XXX Temp fix until we get a final solution with modern intl lib under windows! */ +static int num_locales = 0; +static EnumPropertyItem *locales_menu = NULL; +static int num_locales_menu = 0; + +#define ULANGUAGE ((U.language >= 0 && U.language < num_locales) ? U.language : 0) +#define LOCALE(_id) (locales ? locales[_id] : "") +#define LONG_LOCALE(_id) (long_locales ? long_locales[_id] : "") + +static void free_locales(void) +{ + if (locales) { + int idx = num_locales_menu - 1; /* Last item does not need to be freed! */ + while (idx--) { + MEM_freeN((void*)locales_menu[idx].identifier); + MEM_freeN((void*)locales_menu[idx].name); + MEM_freeN((void*)locales_menu[idx].description); /* Also frees locales's relevant value! */ + } + + idx = num_locales; + while (idx--) { + if (long_locales[idx]) { + MEM_freeN(long_locales[idx]); + } + } + + MEM_freeN(locales); + locales = NULL; + MEM_freeN(long_locales); + long_locales = NULL; + } + if (locales_menu) { + MEM_freeN(locales_menu); + locales_menu = NULL; + } + num_locales = num_locales_menu = 0; +} + +static void fill_locales(void) +{ + char *languages_path = BLI_get_folder(BLENDER_DATAFILES, "locale"); + LinkNode *lines = NULL, *line; + char *str; + int idx = 0; + + free_locales(); + + BLI_join_dirfile(languages_path, FILE_MAX, languages_path, "languages"); + line = lines = BLI_file_read_as_lines(languages_path); + + /* This whole "parsing" code is a bit weak, in that it expects strictly formated input file... + * Should not be a problem, though, as this file is script-generated! */ + + /* First loop to find highest locale ID */ + while (line) { + int t; + str = (char*) line->link; + if (str[0] == '#' || str[0] == '\0') { + line = line->next; + continue; /* Comment or void... */ + } + t = atoi(str); + if (t >= num_locales) + num_locales = t + 1; + num_locales_menu++; + line = line->next; + } + num_locales_menu++; /* The "closing" void item... */ + + /* And now, buil locales and locale_menu! */ + locales_menu = MEM_callocN(num_locales_menu * sizeof(EnumPropertyItem), __func__); + line = lines; + /* Do not allocate locales with zero-sized mem, as LOCALE macro uses NULL locales as invalid marker! */ + if (num_locales > 0) { + locales = MEM_callocN(num_locales * sizeof(char*), __func__); + long_locales = MEM_callocN(num_locales * sizeof(char*), __func__); + while (line) { + int id; + char *loc, *sep1, *sep2, *sep3; + + str = (char*) line->link; + if (str[0] == '#' || str[0] == '\0') { + line = line->next; + continue; + } + + id = atoi(str); + sep1 = strchr(str, ':'); + if (sep1) { + sep1++; + sep2 = strchr(sep1, ':'); + if (sep2) { + locales_menu[idx].value = id; + locales_menu[idx].icon = 0; + locales_menu[idx].name = BLI_strdupn(sep1, sep2 - sep1); + + sep2++; + sep3 = strchr(sep2, ':'); + if (sep3) { + locales_menu[idx].identifier = loc = BLI_strdupn(sep2, sep3 - sep2); + + if (id == 0) { + /* The DEFAULT item... */ + if (BLI_strnlen(loc, 2)) { + locales[id] = locales_menu[idx].description = BLI_strdup(""); + long_locales[id] = BLI_strdup(""); + } + /* Menu "label", not to be stored in locales! */ + else { + locales_menu[idx].description = BLI_strdup(""); + } + } + else { + locales[id] = locales_menu[idx].description = BLI_strdup(loc); + long_locales[id] = BLI_strdup(sep3 + 1); + } + idx++; + } + } + } + + line = line->next; + } + } + + /* Add closing item to menu! */ + locales_menu[idx].identifier = NULL; + locales_menu[idx].value = locales_menu[idx].icon = 0; + locales_menu[idx].name = locales_menu[idx].description = ""; + + BLI_file_free_lines(lines); +} + +EnumPropertyItem *BLF_RNA_lang_enum_properties(void) +{ + return locales_menu; +} void BLF_lang_init(void) { char *messagepath = BLI_get_folder(BLENDER_DATAFILES, "locale"); -/* printf("%s\n", messagepath);*/ BLI_strncpy(global_encoding_name, SYSTEM_ENCODING_DEFAULT, sizeof(global_encoding_name)); - + if (messagepath) { BLI_strncpy(global_messagepath, messagepath, sizeof(global_messagepath)); + fill_locales(); } else { printf("%s: 'locale' data path for translations not found, continuing\n", __func__); global_messagepath[0] = '\0'; } - } -/* get LANG/LANGUAGE environment variable */ +void BLF_lang_free(void) +{ + free_locales(); +} + +/* Get LANG/LANGUAGE environment variable. */ static void get_language_variable(const char *varname, char *var, const size_t maxlen) { char *env = getenv(varname); @@ -136,18 +232,18 @@ static void get_language_variable(const char *varname, char *var, const size_t m if (env) { char *s; - /* store defaul locale */ + /* Store defaul locale. */ BLI_strncpy(var, env, maxlen); - /* use first language as default */ + /* Use first language as default. */ s = strchr(var, ':'); if (s) s[0] = 0; } } -/* get language to be used based on locale(which might be empty when using default language) and - * LANG environment variable +/* Get language to be used based on locale (which might be empty when using default language) and + * LANG environment variable. */ static void get_language(const char *locale, const char *lang, char *language, const size_t maxlen) { @@ -165,45 +261,43 @@ static void get_language(const char *locale, const char *lang, char *language, c } } -/* XXX WARNING!!! IN osx somehow the previous function call jumps in this one??? (ton, ppc) */ +/* XXX WARNING!!! In osx somehow the previous function call jumps in this one??? (ton, ppc) */ void BLF_lang_set(const char *str) { char *locreturn; - const char *short_locale; - int ok = 1; - const char *long_locale = locales[2 * U.language]; + int ok = TRUE; + int ulang = ULANGUAGE; if ((U.transopts & USER_DOTRANSLATE) == 0) return; - if (str) - short_locale = str; - else - short_locale = locales[2 * U.language + 1]; - #if defined(_WIN32) && !defined(FREE_WINDOWS) - if (short_locale) { - char *envStr; + { + const char *long_locale = str ? str : LONG_LOCALE(ulang); + if (long_locale) { + char *envStr; - if (U.language == 0) /* use system setting */ - envStr = BLI_sprintfN("LANG=%s", getenv("LANG")); - else - envStr = BLI_sprintfN("LANG=%s", short_locale); + if (ulang) + envStr = BLI_sprintfN("LANG=%s", long_locale); + else /* Use system setting. */ + envStr = BLI_sprintfN("LANG=%s", getenv("LANG")); - gettext_putenv(envStr); - MEM_freeN(envStr); - } + gettext_putenv(envStr); + MEM_freeN(envStr); + } - locreturn = setlocale(LC_ALL, long_locale); + locreturn = setlocale(LC_ALL, long_locale); - if (locreturn == NULL) { - if (G.debug & G_DEBUG) - printf("Could not change locale to %s\n", long_locale); + if (locreturn == NULL) { + if (G.debug & G_DEBUG) + printf("Could not change locale to %s\n", long_locale); - ok = 0; + ok = FALSE; + } } #else { + const char *short_locale = str ? str : LOCALE(ulang); static char default_lang[64] = "\0"; static char default_language[64] = "\0"; @@ -214,11 +308,33 @@ void BLF_lang_set(const char *str) get_language_variable("LANGUAGE", default_language, sizeof(default_language)); if (short_locale[0]) { - if (G.debug & G_DEBUG) - printf("Setting LANG= and LANGUAGE to %s\n", short_locale); + char *short_locale_utf8 = BLI_sprintfN("%s.UTF-8", short_locale); - BLI_setenv("LANG", short_locale); - BLI_setenv("LANGUAGE", short_locale); + if (G.debug & G_DEBUG) + printf("Setting LANG and LANGUAGE to %s\n", short_locale_utf8); + + locreturn = setlocale(LC_ALL, short_locale_utf8); + + if (locreturn != NULL) { + BLI_setenv("LANG", short_locale_utf8); + BLI_setenv("LANGUAGE", short_locale_utf8); + } + else { + if (G.debug & G_DEBUG) + printf("Setting LANG and LANGUAGE to %s\n", short_locale); + + locreturn = setlocale(LC_ALL, short_locale); + + if (locreturn != NULL) { + BLI_setenv("LANG", short_locale); + BLI_setenv("LANGUAGE", short_locale); + } + } + + if (G.debug & G_DEBUG && locreturn == NULL) + printf("Could not change locale to %s nor %s\n", short_locale, short_locale_utf8); + + MEM_freeN(short_locale_utf8); } else { if (G.debug & G_DEBUG) @@ -226,43 +342,27 @@ void BLF_lang_set(const char *str) BLI_setenv("LANG", default_lang); BLI_setenv("LANGUAGE", default_language); + locreturn = setlocale(LC_ALL, ""); + + if (G.debug & G_DEBUG && locreturn == NULL) + printf("Could not reset locale\n"); } - locreturn = setlocale(LC_ALL, short_locale); - if (locreturn == NULL) { - char *short_locale_utf8 = NULL; + char language[65]; - if (short_locale[0]) { - short_locale_utf8 = BLI_sprintfN("%s.UTF-8", short_locale); - locreturn = setlocale(LC_ALL, short_locale_utf8); - } + get_language(short_locale, default_lang, language, sizeof(language)); - if (locreturn == NULL) { - char language[65]; + if (G.debug & G_DEBUG) + printf("Fallback to LANG=%s and LANGUAGE=%s\n", default_lang, language); - get_language(long_locale, default_lang, language, sizeof(language)); + /* Fallback to default settings. */ + BLI_setenv("LANG", default_lang); + BLI_setenv("LANGUAGE", language); - if (G.debug & G_DEBUG) { - if (short_locale[0]) - printf("Could not change locale to %s nor %s\n", short_locale, short_locale_utf8); - else - printf("Could not reset locale\n"); + locreturn = setlocale(LC_ALL, ""); - printf("Fallback to LANG=%s and LANGUAGE=%s\n", default_lang, language); - } - - /* fallback to default settings */ - BLI_setenv("LANG", default_lang); - BLI_setenv("LANGUAGE", language); - - locreturn = setlocale(LC_ALL, ""); - - ok = 0; - } - - if (short_locale_utf8) - MEM_freeN(short_locale_utf8); + ok = FALSE; } } #endif @@ -281,7 +381,8 @@ void BLF_lang_set(const char *str) const char *BLF_lang_get(void) { - return locales[2 * U.language + 1]; + int uilang = ULANGUAGE; + return LOCALE(uilang); } void BLF_lang_encoding(const char *str) @@ -290,6 +391,9 @@ void BLF_lang_encoding(const char *str) /* bind_textdomain_codeset(TEXT_DOMAIN_NAME, encoding_name); */ } +#undef LOCALE +#undef ULANGUAGE + #else /* ! WITH_INTERNATIONAL */ void BLF_lang_init(void) @@ -297,6 +401,11 @@ void BLF_lang_init(void) return; } +void BLF_lang_free(void) +{ + return; +} + void BLF_lang_encoding(const char *str) { (void)str; diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index fa9223ba6e2..c6c54cc6e8a 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -148,6 +148,11 @@ typedef enum DMDrawFlag { typedef enum DMDirtyFlag { /* dm has valid tessellated faces, but tessellated CDDATA need to be updated. */ DM_DIRTY_TESS_CDLAYERS = 1 << 0, + /* One of the MCOL layers have been updated, force updating of GPUDrawObject's colors buffer. + * This is necessary with modern, VBO draw code, as e.g. in vpaint mode me->mcol may be updated + * without actually rebuilding dm (hence by defautl keeping same GPUDrawObject, and same colors + * buffer, which prevents update during a stroke!). */ + DM_DIRTY_MCOL_UPDATE_DRAW = 1 << 1, } DMDirtyFlag; typedef struct DerivedMesh DerivedMesh; @@ -223,6 +228,7 @@ struct DerivedMesh { void *(*getVertData)(DerivedMesh * dm, int index, int type); void *(*getEdgeData)(DerivedMesh * dm, int index, int type); void *(*getTessFaceData)(DerivedMesh * dm, int index, int type); + void *(*getPolyData)(DerivedMesh * dm, int index, int type); /** Return a pointer to the entire array of vert/edge/face custom data * from the derived mesh (this gives a pointer to the actual data, not @@ -231,7 +237,8 @@ struct DerivedMesh { void *(*getVertDataArray)(DerivedMesh * dm, int type); void *(*getEdgeDataArray)(DerivedMesh * dm, int type); void *(*getTessFaceDataArray)(DerivedMesh * dm, int type); - + void *(*getPolyDataArray)(DerivedMesh * dm, int type); + /** Retrieves the base CustomData structures for * verts/edges/tessfaces/loops/facdes*/ CustomData *(*getVertDataLayout)(DerivedMesh * dm); @@ -493,6 +500,7 @@ void DM_add_poly_layer(struct DerivedMesh *dm, int type, int alloctype, void *DM_get_vert_data(struct DerivedMesh *dm, int index, int type); void *DM_get_edge_data(struct DerivedMesh *dm, int index, int type); void *DM_get_tessface_data(struct DerivedMesh *dm, int index, int type); +void *DM_get_poly_data(struct DerivedMesh *dm, int index, int type); /* custom data layer access functions * return pointer to first data layer which matches type (a flat array) @@ -701,4 +709,10 @@ void DM_debug_print(DerivedMesh *dm); void DM_debug_print_cdlayers(CustomData *cdata); #endif +BLI_INLINE int DM_origindex_mface_mpoly(const int *index_mf_to_mpoly, const int *index_mp_to_orig, const int i) +{ + const int j = index_mf_to_mpoly[i]; + return (j != ORIGINDEX_NONE) ? index_mp_to_orig[j] : ORIGINDEX_NONE; +} + #endif diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 7df491c0fef..2d7030b2d42 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -203,7 +203,7 @@ void BKE_pose_ikparam_init(struct bPose *pose); void BKE_pose_itasc_init(struct bItasc *itasc); /* clears BONE_UNKEYED flags for frame changing */ -// XXX to be depreceated for a more general solution in animsys... +// XXX to be deprecated for a more general solution in animsys... void framechange_poses_clear_unkeyed(void); /* Bone Groups API --------------------- */ diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h index f506c67a36c..11537964e32 100644 --- a/source/blender/blenkernel/BKE_anim.h +++ b/source/blender/blenkernel/BKE_anim.h @@ -65,8 +65,8 @@ int where_on_path(struct Object *ob, float ctime, float vec[4], float dir[3], fl /* ---------------------------------------------------- */ /* Dupli-Geometry */ -struct ListBase *object_duplilist_ex(struct Scene *sce, struct Object *ob, int update); -struct ListBase *object_duplilist(struct Scene *sce, struct Object *ob); +struct ListBase *object_duplilist_ex(struct Scene *sce, struct Object *ob, int update, int for_render); +struct ListBase *object_duplilist(struct Scene *sce, struct Object *ob, int for_render); void free_object_duplilist(struct ListBase *lb); int count_duplilist(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index d750e88ac04..b0f372e0bac 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -99,7 +99,7 @@ void BKE_pose_where_is_bone_tail(struct bPoseChannel *pchan); /* get_objectspace_bone_matrix has to be removed still */ void get_objectspace_bone_matrix(struct Bone *bone, float M_accumulatedMatrix[][4], int root, int posed); void vec_roll_to_mat3(const float vec[3], const float roll, float mat[][3]); -void mat3_to_vec_roll(float mat[][3], float *vec, float *roll); +void mat3_to_vec_roll(float mat[][3], float r_vec[3], float *r_roll); /* Common Conversions Between Co-ordinate Spaces */ void BKE_armature_mat_world_to_pose(struct Object *ob, float inmat[][4], float outmat[][4]); @@ -131,7 +131,14 @@ typedef struct Mat4 { Mat4 *b_bone_spline_setup(struct bPoseChannel *pchan, int rest); /* like EBONE_VISIBLE */ -#define PBONE_VISIBLE(arm, bone) (((bone)->layer & (arm)->layer) && !((bone)->flag & BONE_HIDDEN_P)) +#define PBONE_VISIBLE(arm, bone) ( \ + CHECK_TYPE_INLINE(arm, bArmature), \ + CHECK_TYPE_INLINE(bone, Bone), \ + (((bone)->layer & (arm)->layer) && !((bone)->flag & BONE_HIDDEN_P)) \ + ) + +#define PBONE_SELECTABLE(arm, bone) \ + (PBONE_VISIBLE(arm, bone) && !((bone)->flag & BONE_UNSELECTABLE)) #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 1e67027ae8c..87e87904fe7 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -41,19 +41,18 @@ extern "C" { /* these lines are grep'd, watch out for our not-so-awesome regex * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ -#define BLENDER_VERSION 263 -#define BLENDER_SUBVERSION 18 +#define BLENDER_VERSION 264 +#define BLENDER_SUBVERSION 7 -/* 262 was the last editmesh release but its has compatibility code for bmesh data, - * so set the minversion to 2.61 */ -#define BLENDER_MINVERSION 261 +/* 262 was the last editmesh release but it has compatibility code for bmesh data */ +#define BLENDER_MINVERSION 262 #define BLENDER_MINSUBVERSION 0 /* used by packaging tools */ /* can be left blank, otherwise a,b,c... etc with no quotes */ #define BLENDER_VERSION_CHAR a /* alpha/beta/rc/release, docs use this */ -#define BLENDER_VERSION_CYCLE beta +#define BLENDER_VERSION_CYCLE alpha extern char versionstr[]; /* from blender.c */ diff --git a/source/blender/blenkernel/BKE_bmesh.h b/source/blender/blenkernel/BKE_bmesh.h index 67b21eb764c..8bfee836c0d 100644 --- a/source/blender/blenkernel/BKE_bmesh.h +++ b/source/blender/blenkernel/BKE_bmesh.h @@ -99,7 +99,7 @@ typedef struct BME_Glob { /* stored in Global G for Transform() purposes */ struct BME_TransData *BME_get_transdata(struct BME_TransData_Head *td, struct BMVert *v); void BME_free_transdata(struct BME_TransData_Head *td); -struct BMesh *BME_bevel(struct BMEditMesh *em, float value, int res, int options, int defgrp_index, float angle, - BME_TransData_Head **rtd, int do_tessface); +struct BMesh *BME_bevel(struct BMesh *bm, float value, int res, int options, int defgrp_index, float angle, + BME_TransData_Head **rtd); #endif diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h index d7882d8e7ec..2b2497f3f50 100644 --- a/source/blender/blenkernel/BKE_cdderivedmesh.h +++ b/source/blender/blenkernel/BKE_cdderivedmesh.h @@ -55,8 +55,10 @@ int CDDM_Check(struct DerivedMesh *dm); * data to not overwrite the original */ struct DerivedMesh *CDDM_from_mesh(struct Mesh *mesh, struct Object *ob); +struct DerivedMesh *CDDM_from_bmesh(struct BMesh *bm, int use_mdisps); + /* creates a CDDerivedMesh from the given BMEditMesh */ -DerivedMesh *CDDM_from_BMEditMesh(struct BMEditMesh *em, struct Mesh *me, int use_mdisps, int use_tessface); +DerivedMesh *CDDM_from_editbmesh(struct BMEditMesh *em, int use_mdisps, int use_tessface); /* merge verts */ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap); diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index cd67059ea8c..96e05aa87b9 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -61,10 +61,10 @@ void curvemapping_set_black_white(struct CurveMapping *cumap, con #define CURVEMAP_SLOPE_NEGATIVE 0 #define CURVEMAP_SLOPE_POSITIVE 1 -void curvemap_reset(struct CurveMap *cuma, struct rctf *clipr, int preset, int slope); +void curvemap_reset(struct CurveMap *cuma, const struct rctf *clipr, int preset, int slope); void curvemap_remove(struct CurveMap *cuma, const short flag); -void curvemap_remove_point(struct CurveMap *cuma, struct CurveMapPoint *cmp); -struct CurveMapPoint *curvemap_insert(struct CurveMap *cuma, float x, float y); +int curvemap_remove_point(struct CurveMap *cuma, struct CurveMapPoint *cmp); +struct CurveMapPoint *curvemap_insert(struct CurveMap *cuma, float x, float y); void curvemap_sethandle(struct CurveMap *cuma, int type); void curvemapping_changed(struct CurveMapping *cumap, int rem_doubles); @@ -88,7 +88,6 @@ int curvemapping_RGBA_does_something(const struct CurveMapping * void curvemapping_table_RGBA(const struct CurveMapping *cumap, float **array, int *size); /* non-const, these modify the curve */ -void curvemapping_do_ibuf(struct CurveMapping *cumap, struct ImBuf *ibuf); void curvemapping_premultiply(struct CurveMapping *cumap, int restore); diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index a845ac10c9d..536bbecb79b 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -93,6 +93,8 @@ void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float /* ** Nurbs ** */ +int BKE_nurbList_index_get_co(struct ListBase *editnurb, const int index, float r_co[3]); + int BKE_nurbList_verts_count(struct ListBase *nurb); int BKE_nurbList_verts_count_without_handles(struct ListBase *nurb); @@ -106,7 +108,7 @@ void BKE_nurb_free(struct Nurb *nu); struct Nurb *BKE_nurb_duplicate(struct Nurb *nu); void BKE_nurb_test2D(struct Nurb *nu); -void BKE_nurb_minmax(struct Nurb *nu, float *min, float *max); +void BKE_nurb_minmax(struct Nurb *nu, float min[3], float max[3]); void BKE_nurb_makeFaces(struct Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv); void BKE_nurb_makeCurve(struct Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, float *weight_array, int resolu, int stride); diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 33361b9921c..4736e7b7312 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -80,6 +80,13 @@ void customData_mask_layers__print(CustomDataMask mask); * the below operations. */ int CustomData_layer_has_math(struct CustomData *data, int layer_n); +int CustomData_layer_has_interp(struct CustomData *data, int layer_n); + +/** + * Checks if any of the customdata layers has math. + */ +int CustomData_has_math(struct CustomData *data); +int CustomData_has_interp(struct CustomData *data); /* copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to * another, while not overwriting anything else (e.g. flags). probably only @@ -115,7 +122,10 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, void CustomData_bmesh_merge(struct CustomData *source, struct CustomData *dest, CustomDataMask mask, int alloctype, struct BMesh *bm, const char htype); -/* frees data associated with a CustomData object (doesn't free the object +/** NULL's all members and resets the typemap. */ +void CustomData_reset(struct CustomData *data); + +/** frees data associated with a CustomData object (doesn't free the object * itself, though) */ void CustomData_free(struct CustomData *data, int totelem); @@ -205,8 +215,8 @@ void CustomData_free_elem(struct CustomData *data, int index, int count); void CustomData_interp(const struct CustomData *source, struct CustomData *dest, int *src_indices, float *weights, float *sub_weights, int count, int dest_index); -void CustomData_bmesh_interp(struct CustomData *data, void **src_blocks, - float *weights, float *sub_weights, int count, +void CustomData_bmesh_interp(struct CustomData *data, void **src_blocks, + const float *weights, const float *sub_weights, int count, void *dest_block); diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index 52a143ddf55..8306da71432 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -54,6 +54,7 @@ struct MDeformWeight *defvert_verify_index(struct MDeformVert *dv, const int void defvert_add_index_notest(struct MDeformVert *dv, int defgroup, const float weight); void defvert_remove_group(struct MDeformVert *dvert, struct MDeformWeight *dw); void defvert_clear(struct MDeformVert *dvert); +int defvert_find_shared(const struct MDeformVert *dvert_a, const struct MDeformVert *dvert_b); float defvert_find_weight(const struct MDeformVert *dvert, const int defgroup); float defvert_array_find_weight_safe(const struct MDeformVert *dvert, const int index, const int defgroup); diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 2656495a918..f7af534c2c2 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -130,8 +130,9 @@ enum { G_DEBUG_FFMPEG = (1 << 1), G_DEBUG_PYTHON = (1 << 2), /* extra python info */ G_DEBUG_EVENTS = (1 << 3), /* input/window/screen events */ - G_DEBUG_WM = (1 << 4), /* operator, undo */ - G_DEBUG_JOBS = (1 << 5) /* jobs time profiling */ + G_DEBUG_HANDLERS = (1 << 4), /* events handling */ + G_DEBUG_WM = (1 << 5), /* operator, undo */ + G_DEBUG_JOBS = (1 << 6) /* jobs time profiling */ }; #define G_DEBUG_ALL (G_DEBUG | G_DEBUG_FFMPEG | G_DEBUG_PYTHON | G_DEBUG_EVENTS | G_DEBUG_WM | G_DEBUG_JOBS) @@ -145,17 +146,17 @@ enum { #define G_FILE_ENABLE_ALL_FRAMES (1 << 3) /* deprecated */ #define G_FILE_SHOW_DEBUG_PROPS (1 << 4) /* deprecated */ #define G_FILE_SHOW_FRAMERATE (1 << 5) /* deprecated */ -/* #define G_FILE_SHOW_PROFILE (1 << 6) */ /* deprecated */ +/* #define G_FILE_SHOW_PROFILE (1 << 6) */ /* deprecated */ #define G_FILE_LOCK (1 << 7) #define G_FILE_SIGN (1 << 8) -/* #define G_FILE_PUBLISH (1 << 9) */ /* deprecated */ +/* #define G_FILE_PUBLISH (1 << 9) */ /* deprecated */ #define G_FILE_NO_UI (1 << 10) -/* #define G_FILE_GAME_TO_IPO (1 << 11) */ /* deprecated */ +/* #define G_FILE_GAME_TO_IPO (1 << 11) */ /* deprecated */ #define G_FILE_GAME_MAT (1 << 12) /* deprecated */ -/* #define G_FILE_DISPLAY_LISTS (1 << 13) */ /* deprecated */ +/* #define G_FILE_DISPLAY_LISTS (1 << 13) */ /* deprecated */ #define G_FILE_SHOW_PHYSICS (1 << 14) /* deprecated */ #define G_FILE_GAME_MAT_GLSL (1 << 15) /* deprecated */ -/* #define G_FILE_GLSL_NO_LIGHTS (1 << 16) */ /* deprecated */ +/* #define G_FILE_GLSL_NO_LIGHTS (1 << 16) */ /* deprecated */ #define G_FILE_GLSL_NO_SHADERS (1 << 17) /* deprecated */ #define G_FILE_GLSL_NO_SHADOWS (1 << 18) /* deprecated */ #define G_FILE_GLSL_NO_RAMPS (1 << 19) /* deprecated */ diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index f3223fb4af1..3cb20ead39e 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -44,7 +44,7 @@ void free_gpencil_layers(struct ListBase *list); void BKE_gpencil_free(struct bGPdata *gpd); struct bGPDframe *gpencil_frame_addnew(struct bGPDlayer *gpl, int cframe); -struct bGPDlayer *gpencil_layer_addnew(struct bGPdata *gpd); +struct bGPDlayer *gpencil_layer_addnew(struct bGPdata *gpd, const char *name, int setactive); struct bGPdata *gpencil_data_addnew(const char name[]); struct bGPDframe *gpencil_frame_duplicate(struct bGPDframe *src); @@ -62,6 +62,6 @@ struct bGPDframe *gpencil_layer_getframe(struct bGPDlayer *gpl, int cframe, shor void gpencil_layer_delframe(struct bGPDlayer *gpl, struct bGPDframe *gpf); struct bGPDlayer *gpencil_layer_getactive(struct bGPdata *gpd); void gpencil_layer_setactive(struct bGPdata *gpd, struct bGPDlayer *active); -void gpencil_layer_delactive(struct bGPdata *gpd); +void gpencil_layer_delete(struct bGPdata *gpd, struct bGPDlayer *gpl); #endif /* __BKE_GPENCIL_H__ */ diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h index 67cdee9fa07..3e9803a908b 100644 --- a/source/blender/blenkernel/BKE_group.h +++ b/source/blender/blenkernel/BKE_group.h @@ -52,10 +52,6 @@ int group_is_animated(struct Object *parent, struct Group *group); void group_tag_recalc(struct Group *group); void group_handle_recalc_and_update(struct Scene *scene, struct Object *parent, struct Group *group); -#if 0 /* UNUSED */ -struct Object *group_get_member_with_action(struct Group *group, struct bAction *act); -void group_relink_nla_objects(struct Object *ob); -#endif #endif diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index 3cf4a2c5cdc..a9f6a61a655 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -154,6 +154,12 @@ __attribute__((nonnull)) #endif ; +void IDP_MergeGroup(IDProperty *dest, IDProperty *src, const int do_overwrite) +#ifdef __GNUC__ +__attribute__((nonnull)) +#endif +; + /** * This function has a sanity check to make sure ID properties with the same name don't * get added to the group. @@ -260,6 +266,12 @@ __attribute__((nonnull)) #endif ; +int IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const int is_strict) +#ifdef __GNUC__ +__attribute__((warn_unused_result)) +#endif +; + int IDP_EqualsProperties(struct IDProperty *prop1, struct IDProperty *prop2) #ifdef __GNUC__ __attribute__((warn_unused_result)) @@ -306,11 +318,16 @@ void IDP_FreeProperty(struct IDProperty *prop); /** Unlinks any struct IDProperty<->ID linkage that might be going on.*/ void IDP_UnlinkProperty(struct IDProperty *prop); -#define IDP_Int(prop) ((prop)->data.val) -#define IDP_Float(prop) (*(float *)&(prop)->data.val) -#define IDP_String(prop) ((char *)(prop)->data.pointer) -#define IDP_Array(prop) ((prop)->data.pointer) -#define IDP_IDPArray(prop) ((IDProperty *)(prop)->data.pointer) -#define IDP_Double(prop) (*(double *)&(prop)->data.val) +#define IDP_Int(prop) ((prop)->data.val) +#define IDP_Float(prop) (*(float *)&(prop)->data.val) +#define IDP_Double(prop) (*(double *)&(prop)->data.val) +#define IDP_String(prop) ((char *) (prop)->data.pointer) +#define IDP_Array(prop) ((prop)->data.pointer) +#define IDP_IDPArray(prop) ((IDProperty *) (prop)->data.pointer) + +#ifdef DEBUG +/* for printout only */ +void IDP_spit(IDProperty *prop); +#endif #endif /* __BKE_IDPROP_H__ */ diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index ac324b2af00..1875fd66628 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -66,7 +66,7 @@ int BKE_imtype_is_movie(const char imtype); int BKE_imtype_supports_zbuf(const char imtype); int BKE_imtype_supports_compress(const char imtype); int BKE_imtype_supports_quality(const char imtype); -int BKE_imtype_supports_float(const char imtype); +int BKE_imtype_requires_linear_float(const char imtype); char BKE_imtype_valid_channels(const char imtype); char BKE_imtype_valid_depths(const char imtype); @@ -127,6 +127,7 @@ enum { #define IMA_SIGNAL_SRC_CHANGE 5 /* image-user gets a new image, check settings */ #define IMA_SIGNAL_USER_NEW_IMAGE 6 +#define IMA_SIGNAL_COLORMANAGE 7 #define IMA_CHAN_FLAG_BW 1 #define IMA_CHAN_FLAG_RGB 2 diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index 1ad451b0937..d7d75b4c4c9 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -47,13 +47,13 @@ struct Mesh; extern "C" { #endif -void BKE_key_free(struct Key *sc); -void free_key_nolib(struct Key *key); -struct Key *add_key(struct ID *id); +void BKE_key_free(struct Key *sc); +void BKE_key_free_nolib(struct Key *key); +struct Key *BKE_key_add(struct ID *id); struct Key *BKE_key_copy(struct Key *key); -struct Key *copy_key_nolib(struct Key *key); -void BKE_key_make_local(struct Key *key); -void sort_keys(struct Key *key); +struct Key *BKE_key_copy_nolib(struct Key *key); +void BKE_key_make_local(struct Key *key); +void BKE_key_sort(struct Key *key); void key_curve_position_weights(float t, float data[4], int type); void key_curve_tangent_weights(float t, float data[4], int type); @@ -61,27 +61,29 @@ void key_curve_normal_weights(float t, float data[4], int type); float *do_ob_key(struct Scene *scene, struct Object *ob); -struct Key *ob_get_key(struct Object *ob); -struct KeyBlock *add_keyblock(struct Key *key, const char *name); -struct KeyBlock *add_keyblock_ctime(struct Key *key, const char *name, const short do_force); -struct KeyBlock *ob_get_keyblock(struct Object *ob); -struct KeyBlock *ob_get_reference_keyblock(struct Object *ob); -struct KeyBlock *key_get_keyblock(struct Key *key, int index); -struct KeyBlock *key_get_named_keyblock(struct Key *key, const char name[]); -char *key_get_curValue_rnaPath(struct Key *key, struct KeyBlock *kb); +struct Key *BKE_key_from_object(struct Object *ob); +struct KeyBlock *BKE_keyblock_from_object(struct Object *ob); +struct KeyBlock *BKE_keyblock_from_object_reference(struct Object *ob); + +struct KeyBlock *BKE_keyblock_add(struct Key *key, const char *name); +struct KeyBlock *BKE_keyblock_add_ctime(struct Key *key, const char *name, const short do_force); +struct KeyBlock *BKE_keyblock_from_key(struct Key *key, int index); +struct KeyBlock *BKE_keyblock_find_name(struct Key *key, const char name[]); +void BKE_keyblock_copy_settings(struct KeyBlock *kb_dst, const struct KeyBlock *kb_src); +char *BKE_keyblock_curval_rnapath_get(struct Key *key, struct KeyBlock *kb); // needed for the GE -void do_rel_key(const int start, int end, const int tot, char *basispoin, struct Key *key, struct KeyBlock *actkb, const int mode); +void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, struct Key *key, struct KeyBlock *actkb, const int mode); /* conversion functions */ -void key_to_mesh(struct KeyBlock *kb, struct Mesh *me); -void mesh_to_key(struct Mesh *me, struct KeyBlock *kb); -void key_to_latt(struct KeyBlock *kb, struct Lattice *lt); -void latt_to_key(struct Lattice *lt, struct KeyBlock *kb); -void key_to_curve(struct KeyBlock *kb, struct Curve *cu, struct ListBase *nurb); -void curve_to_key(struct Curve *cu, struct KeyBlock *kb, struct ListBase *nurb); -float (*key_to_vertcos(struct Object *ob, struct KeyBlock *kb))[3]; -void vertcos_to_key(struct Object *ob, struct KeyBlock *kb, float (*vertCos)[3]); -void offset_to_key(struct Object *ob, struct KeyBlock *kb, float (*ofs)[3]); +void BKE_key_convert_to_mesh(struct KeyBlock *kb, struct Mesh *me); +void BKE_key_convert_from_mesh(struct Mesh *me, struct KeyBlock *kb); +void BKE_key_convert_to_lattice(struct KeyBlock *kb, struct Lattice *lt); +void BKE_key_convert_from_lattice(struct Lattice *lt, struct KeyBlock *kb); +void BKE_key_convert_to_curve(struct KeyBlock *kb, struct Curve *cu, struct ListBase *nurb); +void BKE_key_convert_from_curve(struct Curve *cu, struct KeyBlock *kb, struct ListBase *nurb); +float (*BKE_key_convert_to_vertcos(struct Object *ob, struct KeyBlock *kb))[3]; +void BKE_key_convert_from_vertcos(struct Object *ob, struct KeyBlock *kb, float (*vertCos)[3]); +void BKE_key_convert_from_offset(struct Object *ob, struct KeyBlock *kb, float (*ofs)[3]); /* key.c */ extern int slurph_opt; @@ -90,4 +92,4 @@ extern int slurph_opt; }; #endif -#endif // __BKE_KEY_H__ +#endif /* __BKE_KEY_H__ */ diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h index 31626ef4a58..34baa48dbe2 100644 --- a/source/blender/blenkernel/BKE_lattice.h +++ b/source/blender/blenkernel/BKE_lattice.h @@ -46,7 +46,7 @@ struct Lattice *BKE_lattice_add(const char *name); struct Lattice *BKE_lattice_copy(struct Lattice *lt); void BKE_lattice_free(struct Lattice *lt); void BKE_lattice_make_local(struct Lattice *lt); -void calc_lat_fudu(int flag, int res, float *fu, float *du); +void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du); void init_latt_deform(struct Object *oblatt, struct Object *ob); void calc_latt_deform(struct Object *, float co[3], float weight); diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 91756448297..bc081b7f308 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -81,6 +81,7 @@ int set_listbasepointers(struct Main *main, struct ListBase **lb); void BKE_libblock_free(struct ListBase *lb, void *idv); void BKE_libblock_free_us(struct ListBase *lb, void *idv); +void BKE_libblock_free_data(struct ID *id); void free_main(struct Main *mainvar); void tag_main_idcode(struct Main *mainvar, const short type, const short tag); diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index 3074e1c0e63..cfdcf1436bf 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -68,7 +68,7 @@ typedef struct Main { ListBase latt; ListBase lamp; ListBase camera; - ListBase ipo; // XXX depreceated + ListBase ipo; // XXX deprecated ListBase key; ListBase world; ListBase screen; diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index 913e8653b9b..7a0eea1b009 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -59,8 +59,12 @@ void BKE_mball_properties_copy(struct Scene *scene, struct Object *active_object int BKE_mball_minmax(struct MetaBall *mb, float min[3], float max[3]); int BKE_mball_center_median(struct MetaBall *mb, float r_cent[3]); int BKE_mball_center_bounds(struct MetaBall *mb, float r_cent[3]); -void BKE_mball_translate(struct MetaBall *mb, float offset[3]); +void BKE_mball_translate(struct MetaBall *mb, const float offset[3]); struct MetaElem *BKE_mball_element_add(struct MetaBall *mb, const int type); +void BKE_mball_select_all(struct MetaBall *mb); +void BKE_mball_deselect_all(struct MetaBall *mb); +void BKE_mball_select_swap(struct MetaBall *mb); + #endif diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 954fb47806b..2f889084d0e 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -88,8 +88,8 @@ int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata, int totface, int totloop, int totpoly); /*calculates a face normal.*/ -void mesh_calc_poly_normal(struct MPoly *mpoly, struct MLoop *loopstart, - struct MVert *mvarray, float no[3]); +void BKE_mesh_calc_poly_normal(struct MPoly *mpoly, struct MLoop *loopstart, + struct MVert *mvarray, float no[3]); void BKE_mesh_calc_poly_normal_coords(struct MPoly *mpoly, struct MLoop *loopstart, const float (*vertex_coords)[3], float no[3]); @@ -98,7 +98,7 @@ void BKE_mesh_calc_poly_center(struct MPoly *mpoly, struct MLoop *loopstart, struct MVert *mvarray, float cent[3]); float BKE_mesh_calc_poly_area(struct MPoly *mpoly, struct MLoop *loopstart, - struct MVert *mvarray, float polynormal[3]); + struct MVert *mvarray, const float polynormal[3]); /* Find the index of the loop in 'poly' which references vertex, * returns -1 if not found */ @@ -130,7 +130,7 @@ struct Mesh *BKE_mesh_copy(struct Mesh *me); void mesh_update_customdata_pointers(struct Mesh *me, const short do_ensure_tess_cd); void BKE_mesh_make_local(struct Mesh *me); -void BKE_mesh_boundbox_calc(struct Mesh *me, float *loc, float *size); +void BKE_mesh_boundbox_calc(struct Mesh *me, float r_loc[3], float r_size[3]); void BKE_mesh_texspace_calc(struct Mesh *me); float *BKE_mesh_orco_verts_get(struct Object *ob); void BKE_mesh_orco_verts_transform(struct Mesh *me, float (*orco)[3], int totvert, int invert); @@ -292,6 +292,7 @@ void create_vert_edge_map(MeshElemMap **map, int **mem, int BKE_mesh_minmax(struct Mesh *me, float r_min[3], float r_max[3]); int BKE_mesh_center_median(struct Mesh *me, float cent[3]); int BKE_mesh_center_bounds(struct Mesh *me, float cent[3]); +int BKE_mesh_center_centroid(struct Mesh *me, float cent[3]); void BKE_mesh_translate(struct Mesh *me, float offset[3], int do_keys); /* mesh_validate.c */ diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 3b675f3b620..7ee1c85d0de 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -352,6 +352,7 @@ int modifiers_isParticleEnabled(struct Object *ob); struct Object *modifiers_isDeformedByArmature(struct Object *ob); struct Object *modifiers_isDeformedByLattice(struct Object *ob); +struct Object *modifiers_isDeformedByCurve(struct Object *ob); int modifiers_usesArmature(struct Object *ob, struct bArmature *arm); int modifiers_isCorrectableDeformed(struct Object *ob); void modifier_freeTemporaryData(struct ModifierData *md); diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 82a791348dd..8fa20eb2cc2 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -116,5 +116,4 @@ void multires_topology_changed(struct Mesh *me); void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v); int mdisp_rot_face_to_crn(const int corners, const int face_side, const float u, const float v, float *x, float *y); -#endif // __BKE_MULTIRES_H__ - +#endif /* __BKE_MULTIRES_H__ */ diff --git a/source/blender/blenkernel/BKE_navmesh_conversion.h b/source/blender/blenkernel/BKE_navmesh_conversion.h index aab359b307a..cc9c18c764d 100644 --- a/source/blender/blenkernel/BKE_navmesh_conversion.h +++ b/source/blender/blenkernel/BKE_navmesh_conversion.h @@ -60,4 +60,4 @@ int polyFindVertex(const unsigned short *p, const int vertsPerPoly, unsigned sho float distPointToSegmentSq(const float *point, const float *a, const float *b); -#endif //NAVMESH_CONVERSION_H +#endif /* NAVMESH_CONVERSION_H */ diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 6ad2ad924e2..29e03f66bcc 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -193,10 +193,8 @@ typedef struct bNodeType { struct bNodeTree *(*group_edit_set)(struct bNode *node, int edit); void (*group_edit_clear)(struct bNode *node); - /* Generate a temporary list of internal links (bNodeLink), for muting and disconnect operators. - * Result must be freed by caller! - */ - ListBase (*internal_connect)(struct bNodeTree *, struct bNode *node); + /* Update the internal links list, for muting and disconnect operators. */ + void (*update_internal_links)(struct bNodeTree *, struct bNode *node); /* **** execution callbacks **** */ void *(*initexecfunc)(struct bNode *node); @@ -247,6 +245,7 @@ typedef struct bNodeType { #define NODE_CLASS_PARTICLES 25 #define NODE_CLASS_TRANSFORM 30 #define NODE_CLASS_COMBINE 31 +#define NODE_CLASS_SCRIPT 32 #define NODE_CLASS_SHADER 40 #define NODE_CLASS_LAYOUT 100 @@ -293,7 +292,7 @@ typedef struct bNodeTreeType { int (*validate_link)(struct bNodeTree *ntree, struct bNodeLink *link); /* Default internal linking. */ - ListBase (*internal_connect)(struct bNodeTree *, struct bNode *node); + void (*update_internal_links)(struct bNodeTree *, struct bNode *node); } bNodeTreeType; /* ************** GENERIC API, TREES *************** */ @@ -349,7 +348,7 @@ struct bNodeSocket *nodeInsertSocket(struct bNodeTree *ntree, struct bNode *node void nodeRemoveSocket(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock); void nodeRemoveAllSockets(struct bNodeTree *ntree, struct bNode *node); -void nodeAddToPreview(struct bNode *node, float col[4], int x, int y, int do_manage); +void nodeAddToPreview(struct bNode *node, const float col[4], int x, int y, int do_manage); struct bNode *nodeAddNode(struct bNodeTree *ntree, struct bNodeTemplate *ntemp); void nodeUnlinkNode(struct bNodeTree *ntree, struct bNode *node); @@ -389,6 +388,7 @@ struct bNode *nodeGetActiveTexture(struct bNodeTree *ntree); void nodeUpdate(struct bNodeTree *ntree, struct bNode *node); int nodeUpdateID(struct bNodeTree *ntree, struct ID *id); +void nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *node); void nodeFreePreview(struct bNode *node); @@ -445,7 +445,7 @@ void node_type_exec_new(struct bNodeType *ntype, void (*freeexecfunc)(struct bNode *node, void *nodedata), void (*newexecfunc)(void *data, int thread, struct bNode *, void *nodedata, struct bNodeStack **, struct bNodeStack **)); -void node_type_internal_connect(struct bNodeType *ntype, ListBase (*internal_connect)(struct bNodeTree *, struct bNode *)); +void node_type_internal_links(struct bNodeType *ntype, void (*update_internal_links)(struct bNodeTree *, struct bNode *)); void node_type_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out)); void node_type_gpu_ext(struct bNodeType *ntype, int (*gpuextfunc)(struct GPUMaterial *mat, struct bNode *node, @@ -456,8 +456,8 @@ void node_type_compatibility(struct bNodeType *ntype, short compatibi /* ************** COMMON NODES *************** */ #define NODE_GROUP 2 -#define NODE_FORLOOP 3 -#define NODE_WHILELOOP 4 +#define __NODE_FORLOOP 3 /* deprecated */ +#define __NODE_WHILELOOP 4 /* deprecated */ #define NODE_FRAME 5 #define NODE_REROUTE 6 @@ -475,6 +475,8 @@ struct bNodeSocket *node_group_add_extern_socket(struct bNodeTree *ntree, ListBa void register_node_type_frame(struct bNodeTreeType *ttype); void register_node_type_reroute(struct bNodeTreeType *ttype); +void BKE_node_tree_unlink_id_cb(void *calldata, struct ID *owner_id, struct bNodeTree *ntree); + /* ************** SHADER NODES *************** */ struct ShadeInput; @@ -549,6 +551,8 @@ struct ShadeResult; #define SH_NODE_OBJECT_INFO 167 #define SH_NODE_PARTICLE_INFO 168 #define SH_NODE_TEX_BRICK 169 +#define SH_NODE_BUMP 170 +#define SH_NODE_SCRIPT 171 /* custom defines options for Material node */ #define SH_NODE_MAT_DIFF 1 @@ -696,6 +700,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria #define CMP_NODE_BOKEHIMAGE 315 #define CMP_NODE_BOKEHBLUR 316 #define CMP_NODE_SWITCH 317 +#define CMP_NODE_PIXELATE 318 /* channel toggles */ #define CMP_CHAN_RGB 1 @@ -782,7 +787,9 @@ void ntreeTexCheckCyclics(struct bNodeTree *ntree); struct bNodeTreeExec *ntreeTexBeginExecTree(struct bNodeTree *ntree, int use_tree_data); void ntreeTexEndExecTree(struct bNodeTreeExec *exec, int use_tree_data); -int ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target, float *coord, float *dxt, float *dyt, int osatex, short thread, struct Tex *tex, short which_output, int cfra, int preview, struct ShadeInput *shi, struct MTex *mtex); +int ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target, + float coord[3], float dxt[3], float dyt[3], int osatex, const short thread, + struct Tex *tex, short which_output, int cfra, int preview, struct ShadeInput *shi, struct MTex *mtex); /*************************************************/ diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 31642dad60d..ec0703248fd 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -54,7 +54,7 @@ void BKE_object_workob_clear(struct Object *workob); void BKE_object_workob_calc_parent(struct Scene *scene, struct Object *ob, struct Object *workob); void BKE_object_transform_copy(struct Object *ob_tar, const struct Object *ob_src); -struct SoftBody *copy_softbody(struct SoftBody *sb); +struct SoftBody *copy_softbody(struct SoftBody *sb, int copy_caches); struct BulletSoftBody *copy_bulletsoftbody(struct BulletSoftBody *sb); void BKE_object_copy_particlesystems(struct Object *obn, struct Object *ob); void BKE_object_copy_softbody(struct Object *obn, struct Object *ob); @@ -82,6 +82,7 @@ struct Object *BKE_object_add(struct Scene *scene, int type); void *BKE_object_obdata_add_from_type(int type); struct Object *BKE_object_copy(struct Object *ob); +struct Object *BKE_object_copy_with_caches(struct Object *ob); void BKE_object_make_local(struct Object *ob); int BKE_object_is_libdata(struct Object *ob); int BKE_object_obdata_is_libdata(struct Object *ob); @@ -93,6 +94,7 @@ void BKE_object_to_mat3(struct Object *ob, float mat[][3]); void BKE_object_to_mat4(struct Object *ob, float mat[][4]); void BKE_object_apply_mat4(struct Object *ob, float mat[][4], const short use_compat, const short use_parent); +int BKE_object_pose_context_check(struct Object *ob); struct Object *BKE_object_pose_armature_get(struct Object *ob); void BKE_object_where_is_calc(struct Scene *scene, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index a93e542fe15..c452c177143 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -94,6 +94,7 @@ typedef struct SculptSession { /* PBVH acceleration structure */ struct PBVH *pbvh; + int show_diffuse_color; /* Paiting on deformed mesh */ int modifiers_active; /* object is deformed with some modifiers */ diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index b3e650b2aa5..ec03f53dbdb 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -257,7 +257,9 @@ void psys_interpolate_mcol(const struct MCol *mcol, int quad, const float w[4], void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int time); -void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); +void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache, + float fuv[4], float foffset, float vec[3], float nor[3], + float utan[3], float vtan[3], float orco[3], float ornor[3]); struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct ParticleSystem *psys); struct ModifierData *object_add_particle_system(struct Scene *scene, struct Object *ob, const char *name); @@ -282,8 +284,11 @@ void psys_get_particle_on_path(struct ParticleSimulationData *sim, int pa_num, s int psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, int always); /* for anim.c */ -void psys_get_dupli_texture(struct ParticleSystem *psys, struct ParticleSettings *part, struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa, float *uv, float *orco); -void psys_get_dupli_path_transform(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ChildParticle *cpa, struct ParticleCacheKey *cache, float mat[][4], float *scale); +void psys_get_dupli_texture(struct ParticleSystem *psys, struct ParticleSettings *part, + struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa, + float uv[2], float orco[3]); +void psys_get_dupli_path_transform(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ChildParticle *cpa, + struct ParticleCacheKey *cache, float mat[][4], float *scale); ParticleThread *psys_threads_create(struct ParticleSimulationData *sim); void psys_threads_free(ParticleThread *threads); @@ -327,13 +332,17 @@ void psys_free_pdd(struct ParticleSystem *psys); float *psys_cache_vgroup(struct DerivedMesh *dm, struct ParticleSystem *psys, int vgroup); void psys_get_texture(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleTexture *ptex, int event, float cfra); -void psys_interpolate_face(struct MVert *mvert, struct MFace *mface, struct MTFace *tface, float (*orcodata)[3], float *uv, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); +void psys_interpolate_face(struct MVert *mvert, struct MFace *mface, struct MTFace *tface, + float (*orcodata)[3], float w[4], float vec[3], float nor[3], float utan[3], float vtan[3], + float orco[3], float ornor[3]); float psys_particle_value_from_verts(struct DerivedMesh *dm, short from, struct ParticleData *pa, float *values); -void psys_get_from_key(struct ParticleKey *key, float *loc, float *vel, float *rot, float *time); +void psys_get_from_key(struct ParticleKey *key, float loc[3], float vel[3], float rot[4], float *time); /* BLI_bvhtree_ray_cast callback */ void BKE_psys_collision_neartest_cb(void *userdata, int index, const struct BVHTreeRay *ray, struct BVHTreeRayHit *hit); -void psys_particle_on_dm(struct DerivedMesh *dm, int from, int index, int index_dmcache, const float fw[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3], float orco[3], float ornor[3]); +void psys_particle_on_dm(struct DerivedMesh *dm, int from, int index, int index_dmcache, + const float fw[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3], + float orco[3], float ornor[3]); /* particle_system.c */ void initialize_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, int p); diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index d6ab9a35697..77b35e1a25c 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -303,7 +303,7 @@ struct PointCache *BKE_ptcache_add(struct ListBase *ptcaches); void BKE_ptcache_free_mem(struct ListBase *mem_cache); void BKE_ptcache_free(struct PointCache *cache); void BKE_ptcache_free_list(struct ListBase *ptcaches); -struct PointCache *BKE_ptcache_copy_list(struct ListBase *ptcaches_new, struct ListBase *ptcaches_old); +struct PointCache *BKE_ptcache_copy_list(struct ListBase *ptcaches_new, struct ListBase *ptcaches_old, int copy_data); /********************** Baking *********************/ diff --git a/source/blender/blenkernel/BKE_property.h b/source/blender/blenkernel/BKE_property.h index a29dc0e7be4..e0eb8c04b60 100644 --- a/source/blender/blenkernel/BKE_property.h +++ b/source/blender/blenkernel/BKE_property.h @@ -35,19 +35,18 @@ struct bProperty; struct ListBase; struct Object; -void free_property(struct bProperty *prop); -void free_properties(struct ListBase *lb); -struct bProperty *copy_property(struct bProperty *prop); -void copy_properties(struct ListBase *lbn, struct ListBase *lbo); -void init_property(struct bProperty *prop); -struct bProperty *new_property(int type); -void unique_property(struct bProperty *first, struct bProperty *prop, int force); -struct bProperty *get_ob_property(struct Object *ob, const char *name); -void set_ob_property(struct Object *ob, struct bProperty *propc); -int compare_property(struct bProperty *prop, const char *str); -void set_property(struct bProperty *prop, const char *str); -void add_property(struct bProperty *prop, const char *str); -void set_property_valstr(struct bProperty *prop, char *str); -void cp_property(struct bProperty *prop1, struct bProperty *prop2); +void BKE_bproperty_free(struct bProperty *prop); +void BKE_bproperty_free_list(struct ListBase *lb); +struct bProperty *BKE_bproperty_copy(struct bProperty *prop); +void BKE_bproperty_copy_list(struct ListBase *lbn, struct ListBase *lbo); +void BKE_bproperty_init(struct bProperty *prop); +struct bProperty *BKE_bproperty_new(int type); +void BKE_bproperty_unique(struct bProperty *first, struct bProperty *prop, int force); +struct bProperty *BKE_bproperty_object_get(struct Object *ob, const char *name); +void BKE_bproperty_object_set(struct Object *ob, struct bProperty *propc); +// int BKE_bproperty_cmp(struct bProperty *prop, const char *str); +void BKE_bproperty_set(struct bProperty *prop, const char *str); +void BKE_bproperty_add(struct bProperty *prop, const char *str); +void BKE_bproperty_set_valstr(struct bProperty *prop, char *str); #endif diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h index 22b44511195..d598a26fdf9 100644 --- a/source/blender/blenkernel/BKE_sca.h +++ b/source/blender/blenkernel/BKE_sca.h @@ -74,5 +74,7 @@ void sca_move_sensor(struct bSensor *sens_to_move, struct Object *ob, int move_u void sca_move_controller(struct bController *cont_to_move, struct Object *ob, int move_up); void sca_move_actuator(struct bActuator *act_to_move, struct Object *ob, int move_up); +const char *sca_state_name_get(Object *ob, short bit); + #endif diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 023b7e85c40..9927c7a42ed 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -55,7 +55,12 @@ struct Text; #define SCE_COPY_LINK_DATA 3 #define SCE_COPY_FULL 4 -#define SETLOOPER(_sce_basis, _sce_iter, _base) _sce_iter = _sce_basis, _base = _setlooper_base_step(&_sce_iter, NULL); _base; _base = _setlooper_base_step(&_sce_iter, _base) +/* Use as the contents of a 'for' loop: for (SETLOOPER(...)) { ... */ +#define SETLOOPER(_sce_basis, _sce_iter, _base) \ + _sce_iter = _sce_basis, _base = _setlooper_base_step(&_sce_iter, NULL); \ + _base; \ + _base = _setlooper_base_step(&_sce_iter, _base) + struct Base *_setlooper_base_step(struct Scene **sce_iter, struct Base *base); void free_avicodecdata(struct AviCodecData *acd); @@ -109,6 +114,7 @@ float get_render_aosss_error(struct RenderData *r, float error); int BKE_scene_use_new_shading_nodes(struct Scene *scene); void BKE_scene_disable_color_management(struct Scene *scene); +int BKE_scene_check_color_management_enabled(const struct Scene *scene); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 0c571f62f0e..1667c119790 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -64,29 +64,31 @@ typedef struct SeqIterator { int valid; } SeqIterator; -void BKE_seqence_iterator_begin(struct Editing *ed, SeqIterator *iter, int use_pointer); -void BKE_seqence_iterator_next(SeqIterator *iter); -void BKE_seqence_iterator_end(SeqIterator *iter); +void BKE_sequence_iterator_begin(struct Editing *ed, SeqIterator *iter, int use_pointer); +void BKE_sequence_iterator_next(SeqIterator *iter); +void BKE_sequence_iterator_end(SeqIterator *iter); -#define SEQP_BEGIN(ed, _seq) \ +#define SEQP_BEGIN(_ed, _seq) \ { \ - SeqIterator iter; \ - for (BKE_seqence_iterator_begin(ed, &iter, 1); \ - iter.valid; \ - BKE_seqence_iterator_next(&iter)) { \ - _seq = iter.seq; - + SeqIterator iter_macro; \ + for (BKE_sequence_iterator_begin(_ed, &iter_macro, 1); \ + iter_macro.valid; \ + BKE_sequence_iterator_next(&iter_macro)) \ + { \ + _seq = iter_macro.seq; + #define SEQ_BEGIN(ed, _seq) \ { \ - SeqIterator iter; \ - for (BKE_seqence_iterator_begin(ed, &iter, 0); \ - iter.valid; \ - BKE_seqence_iterator_next(&iter)) { \ - _seq = iter.seq; + SeqIterator iter_macro; \ + for (BKE_sequence_iterator_begin(ed, &iter_macro, 0); \ + iter_macro.valid; \ + BKE_sequence_iterator_next(&iter_macro)) \ + { \ + _seq = iter_macro.seq; #define SEQ_END \ } \ - BKE_seqence_iterator_end(&iter); \ + BKE_sequence_iterator_end(&iter_macro); \ } typedef struct SeqRenderData { @@ -307,7 +309,7 @@ int BKE_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char int BKE_sequence_check_depend(struct Sequence *seq, struct Sequence *cur); void BKE_sequence_invalidate_cache(struct Scene *scene, struct Sequence *seq); -void BKE_sequence_invalidate_deendent(struct Scene *scene, struct Sequence *seq); +void BKE_sequence_invalidate_dependent(struct Scene *scene, struct Sequence *seq); void BKE_sequence_invalidate_cache_for_modifier(struct Scene *scene, struct Sequence *seq); void BKE_sequencer_update_sound_bounds_all(struct Scene *scene); @@ -315,9 +317,9 @@ void BKE_sequencer_update_sound_bounds(struct Scene *scene, struct Sequence *seq void BKE_sequencer_update_muting(struct Editing *ed); void BKE_sequencer_update_sound(struct Scene *scene, struct bSound *sound); -void BKE_seqence_base_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq); +void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq); void BKE_sequence_base_dupli_recursive(struct Scene *scene, struct Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, int dupe_flag); -int BKE_seqence_is_valid_check(struct Sequence *seq); +int BKE_sequence_is_valid_check(struct Sequence *seq); void BKE_sequencer_clear_scene_in_allseqs(struct Main *bmain, struct Scene *sce); diff --git a/source/blender/blenkernel/BKE_smoke.h b/source/blender/blenkernel/BKE_smoke.h index 1f824ccbafc..3a9d2b86b41 100644 --- a/source/blender/blenkernel/BKE_smoke.h +++ b/source/blender/blenkernel/BKE_smoke.h @@ -35,8 +35,10 @@ typedef float (*bresenham_callback)(float *result, float *input, int res[3], int *pixel, float *tRay, float correct); -void smokeModifier_do(struct SmokeModifierData *smd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm); +struct DerivedMesh *smokeModifier_do(struct SmokeModifierData *smd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm); +void smoke_reallocate_fluid(struct SmokeDomainSettings *sds, float dx, int res[3], int free_old); +void smoke_reallocate_highres_fluid(struct SmokeDomainSettings *sds, float dx, int res[3], int free_old); void smokeModifier_free(struct SmokeModifierData *smd); void smokeModifier_reset(struct SmokeModifierData *smd); void smokeModifier_reset_turbulence(struct SmokeModifierData *smd); @@ -44,5 +46,7 @@ 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); #endif /* __BKE_SMOKE_H__ */ diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h index 3b8d0eafd4d..653f2a42675 100644 --- a/source/blender/blenkernel/BKE_subsurf.h +++ b/source/blender/blenkernel/BKE_subsurf.h @@ -64,10 +64,10 @@ typedef enum { } SubsurfFlags; struct DerivedMesh *subsurf_make_derived_from_derived( - struct DerivedMesh *dm, - struct SubsurfModifierData *smd, - float (*vertCos)[3], - SubsurfFlags flags); + struct DerivedMesh *dm, + struct SubsurfModifierData *smd, + float (*vertCos)[3], + SubsurfFlags flags); void subsurf_calculate_limit_positions(struct Mesh *me, float (*positions_r)[3]); diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index c14476a3b59..eb7004b1ced 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -80,7 +80,7 @@ int BKE_tracking_track_has_marker_at_frame(struct MovieTrackingTrack *track, int int BKE_tracking_track_has_enabled_marker_at_frame(struct MovieTrackingTrack *track, int framenr); void BKE_tracking_track_path_clear(struct MovieTrackingTrack *track, int ref_frame, int action); -void BKE_tracking_tracks_join(struct MovieTrackingTrack *dst_track, struct MovieTrackingTrack *src_track); +void BKE_tracking_tracks_join(struct MovieTracking *tracking, struct MovieTrackingTrack *dst_track, struct MovieTrackingTrack *src_track); struct MovieTrackingTrack *BKE_tracking_track_get_named(struct MovieTracking *tracking, struct MovieTrackingObject *object, @@ -114,7 +114,7 @@ void BKE_tracking_marker_get_subframe_position(struct MovieTrackingTrack *track, /* **** Object **** */ struct MovieTrackingObject *BKE_tracking_object_add(struct MovieTracking *tracking, const char *name); -void BKE_tracking_object_delete(struct MovieTracking *tracking, struct MovieTrackingObject *object); +int BKE_tracking_object_delete(struct MovieTracking *tracking, struct MovieTrackingObject *object); void BKE_tracking_object_unique_name(struct MovieTracking *tracking, struct MovieTrackingObject *object); diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index 63f5ec59a0b..06f8b89ec05 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -38,4 +38,4 @@ extern "C" { } #endif -#endif // __BKE_UTILDEFINES_H__ +#endif /* __BKE_UTILDEFINES_H__ */ diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index efdb80433c6..c5dc7da8edf 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -25,7 +25,6 @@ set(INC . - ../avi ../blenfont ../blenlib ../blenloader @@ -194,8 +193,8 @@ set(SRC BKE_lamp.h BKE_lattice.h BKE_library.h - BKE_mask.h BKE_main.h + BKE_mask.h BKE_material.h BKE_mball.h BKE_mesh.h @@ -250,7 +249,7 @@ if(WITH_AUDASPACE) endif() if(WITH_BULLET) - list(APPEND INC + list(APPEND INC_SYS ../../../extern/bullet2/src ) add_definitions(-DUSE_BULLET) @@ -292,6 +291,13 @@ if(WITH_IMAGE_HDR) add_definitions(-DWITH_HDR) endif() +if(WITH_CODEC_AVI) + list(APPEND INC + ../avi + ) + add_definitions(-DWITH_AVI) +endif() + if(WITH_CODEC_QUICKTIME) list(APPEND INC ../quicktime @@ -350,12 +356,6 @@ if(WITH_MOD_OCEANSIM) add_definitions(-DWITH_OCEANSIM) endif() -if(WITH_MOD_DECIMATE) - list(APPEND INC - ../../../intern/decimation/extern - ) -endif() - if(WITH_MOD_BOOLEAN) list(APPEND INC ../../../intern/bsp/extern diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index d1a35b122e8..f7b8f59fa57 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -10,7 +10,7 @@ sources_mask = env.Glob('intern/mask*.c') incs = '. #/intern/guardedalloc #/intern/memutil' incs += ' ../blenlib ../blenfont ../makesdna ../windowmanager' -incs += ' ../render/extern/include #/intern/decimation/extern ../makesrna' +incs += ' ../render/extern/include ../makesrna' incs += ' ../imbuf ../ikplugin ../avi #/intern/elbeem/extern ../nodes ../modifiers' incs += ' #/intern/iksolver/extern ../blenloader' incs += ' #/extern/bullet2/src' diff --git a/source/blender/blenkernel/depsgraph_private.h b/source/blender/blenkernel/depsgraph_private.h index 512b799aeed..12c111f5f16 100644 --- a/source/blender/blenkernel/depsgraph_private.h +++ b/source/blender/blenkernel/depsgraph_private.h @@ -61,7 +61,7 @@ typedef struct DagAdjList { typedef struct DagNode { int color; short type; - float x, y, k; + float x, y, k; void *ob; void *first_ancestor; int ancestor_count; diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index 387d4775ad4..cc20470b4d5 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -868,7 +868,7 @@ CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, int subdivLevels, CCGAllocatorIFC *a ss->oldVMap = ss->oldEMap = ss->oldFMap = NULL; ss->lenTempArrays = 0; ss->tempVerts = NULL; - ss->tempEdges = NULL; + ss->tempEdges = NULL; return ss; } @@ -1397,7 +1397,7 @@ CCGError ccgSubSurf_processSync(CCGSubSurf *ss) return eCCGError_None; } -#define VERT_getNo(e, lvl) _vert_getNo(e, lvl, vertDataSize, normalDataOffset) +#define VERT_getNo(e, lvl) _vert_getNo(v, lvl, vertDataSize, normalDataOffset) #define EDGE_getNo(e, lvl, x) _edge_getNo(e, lvl, x, vertDataSize, normalDataOffset) #define FACE_getIFNo(f, lvl, S, x, y) _face_getIFNo(f, lvl, S, x, y, subdivLevels, vertDataSize, normalDataOffset) #define FACE_calcIFNo(f, lvl, S, x, y, no) _face_calcIFNo(f, lvl, S, x, y, no, subdivLevels, vertDataSize) @@ -1491,7 +1491,7 @@ static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss, /* XXX can I reduce the number of normalisations here? */ for (ptrIdx = 0; ptrIdx < numEffectedV; ptrIdx++) { CCGVert *v = (CCGVert *) effectedV[ptrIdx]; - float length, *no = _vert_getNo(v, lvl, vertDataSize, normalDataOffset); + float length, *no = VERT_getNo(v, lvl); NormZero(no); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 07d14513bd0..fd92b7b5d69 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -51,8 +51,6 @@ #include "BLI_utildefines.h" #include "BLI_linklist.h" -#include "BLF_translation.h" - #include "BKE_cdderivedmesh.h" #include "BKE_displist.h" #include "BKE_key.h" @@ -267,9 +265,11 @@ void DM_init_funcs(DerivedMesh *dm) dm->getVertData = DM_get_vert_data; dm->getEdgeData = DM_get_edge_data; dm->getTessFaceData = DM_get_tessface_data; + dm->getPolyData = DM_get_poly_data; dm->getVertDataArray = DM_get_vert_data_layer; dm->getEdgeDataArray = DM_get_edge_data_layer; dm->getTessFaceDataArray = DM_get_tessface_data_layer; + dm->getPolyDataArray = DM_get_poly_data_layer; bvhcache_init(&dm->bvhCache); } @@ -289,6 +289,13 @@ void DM_init(DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges, dm->needsFree = 1; dm->auto_bump_scale = -1.0f; dm->dirty = 0; + + /* don't use CustomData_reset(...); because we dont want to touch customdata */ + fill_vn_i(dm->vertData.typemap, CD_NUMTYPES, -1); + fill_vn_i(dm->edgeData.typemap, CD_NUMTYPES, -1); + fill_vn_i(dm->faceData.typemap, CD_NUMTYPES, -1); + fill_vn_i(dm->loopData.typemap, CD_NUMTYPES, -1); + fill_vn_i(dm->polyData.typemap, CD_NUMTYPES, -1); } void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type, @@ -385,7 +392,7 @@ void DM_ensure_tessface(DerivedMesh *dm) } else if (dm->dirty & DM_DIRTY_TESS_CDLAYERS) { - BLI_assert(CustomData_has_layer(&dm->faceData, CD_POLYINDEX)); + BLI_assert(CustomData_has_layer(&dm->faceData, CD_ORIGINDEX)); DM_update_tessface_data(dm); } @@ -409,7 +416,7 @@ void DM_update_tessface_data(DerivedMesh *dm) const int hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL); const int hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP); - int *polyindex = CustomData_get_layer(fdata, CD_POLYINDEX); + int *polyindex = CustomData_get_layer(fdata, CD_ORIGINDEX); int mf_idx, totface = dm->getNumTessFaces(dm), @@ -466,11 +473,11 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob) int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly; int did_shapekeys = 0; - memset(&tmp.vdata, 0, sizeof(tmp.vdata)); - memset(&tmp.edata, 0, sizeof(tmp.edata)); - memset(&tmp.fdata, 0, sizeof(tmp.fdata)); - memset(&tmp.ldata, 0, sizeof(tmp.ldata)); - memset(&tmp.pdata, 0, sizeof(tmp.pdata)); + CustomData_reset(&tmp.vdata); + CustomData_reset(&tmp.edata); + CustomData_reset(&tmp.fdata); + CustomData_reset(&tmp.ldata); + CustomData_reset(&tmp.pdata); totvert = tmp.totvert = dm->getNumVerts(dm); totedge = tmp.totedge = dm->getNumEdges(dm); @@ -578,6 +585,13 @@ void DM_set_only_copy(DerivedMesh *dm, CustomDataMask mask) CustomData_set_only_copy(&dm->vertData, mask); CustomData_set_only_copy(&dm->edgeData, mask); CustomData_set_only_copy(&dm->faceData, mask); + /* this wasn't in 2.63 and is disabled for 2.64 because it gives problems with + * weight paint mode when there are modifiers applied, needs further investigation, + * see replies to r50969, Campbell */ +#if 0 + CustomData_set_only_copy(&dm->loopData, mask); + CustomData_set_only_copy(&dm->polyData, mask); +#endif } void DM_add_vert_layer(DerivedMesh *dm, int type, int alloctype, void *layer) @@ -620,6 +634,12 @@ void *DM_get_tessface_data(DerivedMesh *dm, int index, int type) return CustomData_get(&dm->faceData, index, type); } +void *DM_get_poly_data(DerivedMesh *dm, int index, int type) +{ + return CustomData_get(&dm->polyData, index, type); +} + + void *DM_get_vert_data_layer(DerivedMesh *dm, int type) { if (type == CD_MVERT) @@ -808,7 +828,7 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, if (mti->isDisabled && mti->isDisabled(md, 0)) return NULL; if (build_shapekey_layers && me->key && (kb = BLI_findlink(&me->key->block, ob->shapenr - 1))) { - key_to_mesh(kb, me); + BKE_key_convert_to_mesh(kb, me); } if (mti->type == eModifierTypeType_OnlyDeform) { @@ -878,7 +898,7 @@ static void *get_orco_coords_dm(Object *ob, BMEditMesh *em, int layer, int *free * by a more flexible customdata system, but not simple */ if (!em) { ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - KeyBlock *kb = key_get_keyblock(ob_get_key(ob), clmd->sim_parms->shapekey_rest); + KeyBlock *kb = BKE_keyblock_from_key(BKE_key_from_object(ob), clmd->sim_parms->shapekey_rest); if (kb->data) return kb->data; @@ -896,7 +916,7 @@ static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, BMEditMesh *em, int lay float (*orco)[3]; int free; - if (em) dm = CDDM_from_BMEditMesh(em, me, FALSE, FALSE); + if (em) dm = CDDM_from_editbmesh(em, FALSE, FALSE); else dm = CDDM_from_mesh(me, ob); orco = get_orco_coords_dm(ob, em, layer, &free); @@ -1263,7 +1283,7 @@ static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape int i, j, tot; if (!me->key) - return; + return; tot = CustomData_number_of_layers(&dm->vertData, CD_SHAPEKEY); for (i = 0; i < tot; i++) { @@ -1276,7 +1296,7 @@ static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape } if (!kb) { - kb = add_keyblock(me->key, layer->name); + kb = BKE_keyblock_add(me->key, layer->name); kb->uid = layer->uid; } @@ -1368,7 +1388,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos ModifierData *firstmd, *md, *previewmd = NULL; CDMaskLink *datamasks, *curr; /* XXX Always copying POLYINDEX, else tessellated data are no more valid! */ - CustomDataMask mask, nextmask, append_mask = CD_MASK_POLYINDEX; + CustomDataMask mask, nextmask, append_mask = CD_MASK_ORIGINDEX; float (*deformedVerts)[3] = NULL; DerivedMesh *dm = NULL, *orcodm, *clothorcodm, *finaldm; int numVerts = me->totvert; @@ -1500,7 +1520,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos if (!modifier_isEnabled(scene, md, required_mode)) continue; if (mti->type == eModifierTypeType_OnlyDeform && !useDeform) continue; if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) { - modifier_setError(md, "%s", TIP_("Modifier requires original data, bad stack position.")); + modifier_setError(md, "Modifier requires original data, bad stack position"); continue; } if (sculpt_mode && (!has_multires || multires_applied)) { @@ -1513,7 +1533,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos unsupported |= multires_applied; if (unsupported) { - modifier_setError(md, "%s", TIP_("Not supported in sculpt mode.")); + modifier_setError(md, "Not supported in sculpt mode"); continue; } } @@ -1796,7 +1816,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos #if 0 if (num_tessface == 0 && finaldm->getNumTessFaces(finaldm) == 0) #else - if (finaldm->getNumTessFaces(finaldm) == 0) /* || !CustomData_has_layer(&finaldm->faceData, CD_POLYINDEX)) */ + if (finaldm->getNumTessFaces(finaldm) == 0) /* || !CustomData_has_layer(&finaldm->faceData, CD_ORIGINDEX)) */ #endif { finaldm->recalcTessellation(finaldm); @@ -1804,8 +1824,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos /* Even if tessellation is not needed, some modifiers might have modified CD layers * (like mloopcol or mloopuv), hence we have to update those. */ else if (finaldm->dirty & DM_DIRTY_TESS_CDLAYERS) { - /* A tessellation already exists, it should always have a CD_POLYINDEX. */ - BLI_assert(CustomData_has_layer(&finaldm->faceData, CD_POLYINDEX)); + /* A tessellation already exists, it should always have a CD_ORIGINDEX. */ + BLI_assert(CustomData_has_layer(&finaldm->faceData, CD_ORIGINDEX)); DM_update_tessface_data(finaldm); } /* Need to watch this, it can cause issues, see bug [#29338] */ @@ -1874,7 +1894,7 @@ int editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *d if (!modifier_isEnabled(scene, md, required_mode)) return 0; if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) { - modifier_setError(md, "%s", TIP_("Modifier requires original data, bad stack position.")); + modifier_setError(md, "Modifier requires original data, bad stack position"); return 0; } @@ -1969,7 +1989,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D } else { - dm = CDDM_from_BMEditMesh(em, ob->data, FALSE, FALSE); + dm = CDDM_from_editbmesh(em, FALSE, FALSE); if (deformedVerts) { CDDM_apply_vert_coords(dm, deformedVerts); @@ -2060,12 +2080,18 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D } else if (dm) { *final_r = dm; - (*final_r)->calcNormals(*final_r); /* BMESH_ONLY - BMESH_TODO. check if this is needed */ + + /* once we support skipping normal calculation with modifiers we may want to add this back */ +#if 0 // was added for bmesh but is not needed + (*final_r)->calcNormals(*final_r); +#endif } else if (!deformedVerts && cage_r && *cage_r) { /* cage should already have up to date normals */ *final_r = *cage_r; - (*final_r)->calcNormals(*final_r); /* BMESH_ONLY - BMESH_TODO. check if this is needed */ +#if 0 // was added for bmesh but is not needed + (*final_r)->calcNormals(*final_r); +#endif } else { /* this is just a copy of the editmesh, no need to calc normals */ @@ -2242,8 +2268,16 @@ DerivedMesh *mesh_create_derived_view(Scene *scene, Object *ob, CustomDataMask d { DerivedMesh *final; + /* XXX hack + * psys modifier updates particle state when called during dupli-list generation, + * which can lead to wrong transforms. This disables particle system modifier execution. + */ + ob->transflag |= OB_NO_PSYS_UPDATE; + mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 0, 1, 0, dataMask, -1, 0, 0); + ob->transflag &= ~OB_NO_PSYS_UPDATE; + return final; } @@ -2413,7 +2447,7 @@ static int GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_ static void GetPosition(const SMikkTSpaceContext *pContext, float fPos[], const int face_num, const int vert_index) { - //assert(vert_index>=0 && vert_index<4); + //assert(vert_index >= 0 && vert_index < 4); SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; const float *co = pMesh->mvert[(&pMesh->mface[face_num].v1)[vert_index]].co; copy_v3_v3(fPos, co); @@ -2421,7 +2455,7 @@ static void GetPosition(const SMikkTSpaceContext *pContext, float fPos[], const static void GetTextureCoordinate(const SMikkTSpaceContext *pContext, float fUV[], const int face_num, const int vert_index) { - //assert(vert_index>=0 && vert_index<4); + //assert(vert_index >= 0 && vert_index < 4); SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; if (pMesh->mtface != NULL) { @@ -2436,7 +2470,7 @@ static void GetTextureCoordinate(const SMikkTSpaceContext *pContext, float fUV[] static void GetNormal(const SMikkTSpaceContext *pContext, float fNorm[], const int face_num, const int vert_index) { - //assert(vert_index>=0 && vert_index<4); + //assert(vert_index >= 0 && vert_index < 4); SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; const int smoothnormal = (pMesh->mface[face_num].flag & ME_SMOOTH); @@ -2466,7 +2500,7 @@ static void GetNormal(const SMikkTSpaceContext *pContext, float fNorm[], const i } static void SetTSpace(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int face_num, const int iVert) { - //assert(vert_index>=0 && vert_index<4); + //assert(vert_index >= 0 && vert_index < 4); SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; float *pRes = pMesh->tangent[4 * face_num + iVert]; copy_v3_v3(pRes, fvTangent); @@ -2477,15 +2511,11 @@ static void SetTSpace(const SMikkTSpaceContext *pContext, const float fvTangent[ void DM_add_tangent_layer(DerivedMesh *dm) { /* mesh vars */ - MTFace *mtface, *tf; - MFace *mface, *mf; - MVert *mvert, *v1, *v2, *v3, *v4; - MemArena *arena = NULL; - VertexTangent **vtangents = NULL; + MVert *mvert; + MTFace *mtface; + MFace *mface; float (*orco)[3] = NULL, (*tangent)[4]; - float *uv1, *uv2, *uv3, *uv4, *vtang; - float fno[3], tang[3], uv[4][2]; - int i, j, len, mf_vi[4], totvert, totface, iCalcNewMethod; + int /* totvert, */ totface; float *nors; if (CustomData_get_layer_index(&dm->faceData, CD_TANGENT) != -1) @@ -2494,7 +2524,7 @@ void DM_add_tangent_layer(DerivedMesh *dm) nors = dm->getTessFaceDataArray(dm, CD_NORMAL); /* check we have all the needed layers */ - totvert = dm->getNumVerts(dm); + /* totvert = dm->getNumVerts(dm); */ /* UNUSED */ totface = dm->getNumTessFaces(dm); mvert = dm->getVertArray(dm); @@ -2511,14 +2541,8 @@ void DM_add_tangent_layer(DerivedMesh *dm) DM_add_tessface_layer(dm, CD_TANGENT, CD_CALLOC, NULL); tangent = DM_get_tessface_data_layer(dm, CD_TANGENT); - /* allocate some space */ - arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "tangent layer arena"); - BLI_memarena_use_calloc(arena); - vtangents = MEM_callocN(sizeof(VertexTangent *) * totvert, "VertexTangent"); - /* new computation method */ - iCalcNewMethod = 1; - if (iCalcNewMethod != 0) { + { SGLSLMeshToTangent mesh2tangent = {0}; SMikkTSpaceContext sContext = {0}; SMikkTSpaceInterface sInterface = {0}; @@ -2541,87 +2565,13 @@ void DM_add_tangent_layer(DerivedMesh *dm) sInterface.m_setTSpaceBasic = SetTSpace; /* 0 if failed */ - iCalcNewMethod = genTangSpaceDefault(&sContext); + genTangSpaceDefault(&sContext); } - - if (!iCalcNewMethod) { - /* sum tangents at connected vertices */ - for (i = 0, tf = mtface, mf = mface; i < totface; mf++, tf++, i++) { - v1 = &mvert[mf->v1]; - v2 = &mvert[mf->v2]; - v3 = &mvert[mf->v3]; - - if (mf->v4) { - v4 = &mvert[mf->v4]; - normal_quad_v3(fno, v4->co, v3->co, v2->co, v1->co); - } - else { - v4 = NULL; - normal_tri_v3(fno, v3->co, v2->co, v1->co); - } - - if (mtface) { - uv1 = tf->uv[0]; - uv2 = tf->uv[1]; - uv3 = tf->uv[2]; - uv4 = tf->uv[3]; - } - else { - uv1 = uv[0]; uv2 = uv[1]; uv3 = uv[2]; uv4 = uv[3]; - map_to_sphere(&uv[0][0], &uv[0][1], orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2]); - map_to_sphere(&uv[1][0], &uv[1][1], orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2]); - map_to_sphere(&uv[2][0], &uv[2][1], orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2]); - if (v4) - map_to_sphere(&uv[3][0], &uv[3][1], orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2]); - } - - tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, fno, tang); - sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1); - sum_or_add_vertex_tangent(arena, &vtangents[mf->v2], tang, uv2); - sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3); - - if (mf->v4) { - v4 = &mvert[mf->v4]; - - tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, fno, tang); - sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1); - sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3); - sum_or_add_vertex_tangent(arena, &vtangents[mf->v4], tang, uv4); - } - } - - /* write tangent to layer */ - for (i = 0, tf = mtface, mf = mface; i < totface; mf++, tf++, i++, tangent += 4) { - len = (mf->v4) ? 4 : 3; - - if (mtface == NULL) { - map_to_sphere(&uv[0][0], &uv[0][1], orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2]); - map_to_sphere(&uv[1][0], &uv[1][1], orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2]); - map_to_sphere(&uv[2][0], &uv[2][1], orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2]); - if (len == 4) - map_to_sphere(&uv[3][0], &uv[3][1], orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2]); - } - - mf_vi[0] = mf->v1; - mf_vi[1] = mf->v2; - mf_vi[2] = mf->v3; - mf_vi[3] = mf->v4; - - for (j = 0; j < len; j++) { - vtang = find_vertex_tangent(vtangents[mf_vi[j]], mtface ? tf->uv[j] : uv[j]); - normalize_v3_v3(tangent[j], vtang); - ((float *) tangent[j])[3] = 1.0f; - } - } - } - - BLI_memarena_free(arena); - MEM_freeN(vtangents); } void DM_calc_auto_bump_scale(DerivedMesh *dm) { - /* int totvert= dm->getNumVerts(dm); */ /* UNUSED */ + /* int totvert = dm->getNumVerts(dm); */ /* UNUSED */ int totface = dm->getNumTessFaces(dm); MVert *mvert = dm->getVertArray(dm); diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 06bf5211abb..e95451252d0 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -224,7 +224,7 @@ bActionGroup *get_active_actiongroup(bAction *act) { bActionGroup *agrp = NULL; - if (act && act->groups.first) { + if (act && act->groups.first) { for (agrp = act->groups.first; agrp; agrp = agrp->next) { if (agrp->flag & AGRP_ACTIVE) break; @@ -301,7 +301,7 @@ bActionGroup *action_groups_add_new(bAction *act, const char name[]) /* add to action, and validate */ BLI_addtail(&act->groups, agrp); - BLI_uniquename(&act->groups, agrp, "Group", '.', offsetof(bActionGroup, name), sizeof(agrp->name)); + BLI_uniquename(&act->groups, agrp, "Group", '.', offsetof(bActionGroup, name), sizeof(agrp->name)); /* return the new group */ return agrp; @@ -380,7 +380,7 @@ void action_groups_add_channel(bAction *act, bActionGroup *agrp, FCurve *fcurve) void action_groups_remove_channel(bAction *act, FCurve *fcu) { /* sanity checks */ - if (ELEM(NULL, act, fcu)) + if (ELEM(NULL, act, fcu)) return; /* check if any group used this directly */ @@ -539,6 +539,7 @@ void BKE_pose_copy_data(bPose **dst, bPose *src, int copycon) outPose->iksolver = src->iksolver; outPose->ikdata = NULL; outPose->ikparam = MEM_dupallocN(src->ikparam); + outPose->avs = src->avs; for (pchan = outPose->chanbase.first; pchan; pchan = pchan->next) { /* TODO: rename this argument... */ @@ -905,8 +906,8 @@ void calc_action_range(const bAction *act, float *start, float *end, short incl_ calc_fcurve_range(fcu, &nmin, &nmax, FALSE, TRUE); /* compare to the running tally */ - min = MIN2(min, nmin); - max = MAX2(max, nmax); + min = min_ff(min, nmin); + max = max_ff(max, nmax); foundvert = 1; } @@ -924,10 +925,10 @@ void calc_action_range(const bAction *act, float *start, float *end, short incl_ FMod_Limits *fmd = (FMod_Limits *)fcm->data; if (fmd->flag & FCM_LIMIT_XMIN) { - min = MIN2(min, fmd->rect.xmin); + min = min_ff(min, fmd->rect.xmin); } if (fmd->flag & FCM_LIMIT_XMAX) { - max = MAX2(max, fmd->rect.xmax); + max = max_ff(max, fmd->rect.xmax); } } break; @@ -954,7 +955,7 @@ void calc_action_range(const bAction *act, float *start, float *end, short incl_ foundmod = 1; } } - } + } if (foundvert || foundmod) { if (min == max) max += 1.0f; @@ -1214,475 +1215,3 @@ void what_does_obaction(Object *ob, Object *workob, bPose *pose, bAction *act, c } } -/* ********** NLA with non-poses works with ipo channels ********** */ - -#if 0 // XXX OLD ANIMATION SYSTEM (TO BE REMOVED) - -/* ************************ Blending with NLA *************** */ - -static void blend_pose_strides(bPose *dst, bPose *src, float srcweight, short mode) -{ - float dstweight; - - switch (mode) { - case ACTSTRIPMODE_BLEND: - dstweight = 1.0F - srcweight; - break; - case ACTSTRIPMODE_ADD: - dstweight = 1.0F; - break; - default: - dstweight = 1.0F; - } - - interp_v3_v3v3(dst->stride_offset, dst->stride_offset, src->stride_offset, srcweight); -} - - -/* - * bone matching diagram, strips A and B - * - * .------------------------. - * | A | - * '------------------------' - * . . b2 - * . .-------------v----------. - * . | B . | - * . '------------------------' - * . . . - * . . . - * offset: . 0 . A-B . A-b2+B - * . . . - * - * */ - - -static void blend_pose_offset_bone(bActionStrip *strip, bPose *dst, bPose *src, float srcweight, short mode) -{ - /* matching offset bones */ - /* take dst offset, and put src on on that location */ - - if (strip->offs_bone[0] == 0) - return; - - /* are we also blending with matching bones? */ - if (strip->prev && strip->start >= strip->prev->start) { - bPoseChannel *dpchan = BKE_pose_channel_find_name(dst, strip->offs_bone); - if (dpchan) { - bPoseChannel *spchan = BKE_pose_channel_find_name(src, strip->offs_bone); - if (spchan) { - float vec[3]; - - /* dst->ctime has the internal strip->prev action time */ - /* map this time to nla time */ - - float ctime = get_actionstrip_frame(strip, src->ctime, 1); - - if (ctime > strip->prev->end) { - bActionChannel *achan; - - /* add src to dest, minus the position of src on strip->prev->end */ - - ctime = get_actionstrip_frame(strip, strip->prev->end, 0); - - achan = get_action_channel(strip->act, strip->offs_bone); - if (achan && achan->ipo) { - bPoseChannel pchan; - /* Evaluates and sets the internal ipo value */ - calc_ipo(achan->ipo, ctime); - /* This call also sets the pchan flags */ - execute_action_ipo(achan, &pchan); - - /* store offset that moves src to location of pchan */ - sub_v3_v3v3(vec, dpchan->loc, pchan.loc); - - mul_mat3_m4_v3(dpchan->bone->arm_mat, vec); - } - } - else { - /* store offset that moves src to location of dst */ - - sub_v3_v3v3(vec, dpchan->loc, spchan->loc); - mul_mat3_m4_v3(dpchan->bone->arm_mat, vec); - } - - /* if blending, we only add with factor scrweight */ - mul_v3_fl(vec, srcweight); - - add_v3_v3(dst->cyclic_offset, vec); - } - } - } - - add_v3_v3(dst->cyclic_offset, src->cyclic_offset); -} - -/* added "sizecorr" here, to allow armatures to be scaled and still have striding. - * Only works for uniform scaling. In general I'd advise against scaling armatures ever though! (ton) - */ -static float stridechannel_frame(Object *ob, float sizecorr, bActionStrip *strip, Path *path, float pathdist, float *stride_offset) -{ - bAction *act = strip->act; - const char *name = strip->stridechannel; - bActionChannel *achan = get_action_channel(act, name); - int stride_axis = strip->stride_axis; - - if (achan && achan->ipo) { - IpoCurve *icu = NULL; - float minx = 0.0f, maxx = 0.0f, miny = 0.0f, maxy = 0.0f; - int foundvert = 0; - - if (stride_axis == 0) stride_axis = AC_LOC_X; - else if (stride_axis == 1) stride_axis = AC_LOC_Y; - else stride_axis = AC_LOC_Z; - - /* calculate the min/max */ - for (icu = achan->ipo->curve.first; icu; icu = icu->next) { - if (icu->adrcode == stride_axis) { - if (icu->totvert > 1) { - foundvert = 1; - minx = icu->bezt[0].vec[1][0]; - maxx = icu->bezt[icu->totvert - 1].vec[1][0]; - - miny = icu->bezt[0].vec[1][1]; - maxy = icu->bezt[icu->totvert - 1].vec[1][1]; - } - break; - } - } - - if (foundvert && miny != maxy) { - float stridelen = sizecorr * fabs(maxy - miny), striptime; - float actiondist, pdist, pdistNewNormalized, offs; - float vec1[4], vec2[4], dir[3]; - - /* internal cycling, actoffs is in frames */ - offs = stridelen * strip->actoffs / (maxx - minx); - - /* amount path moves object */ - pdist = (float)fmod(pathdist + offs, stridelen); - striptime = pdist / stridelen; - - /* amount stride bone moves */ - actiondist = sizecorr * eval_icu(icu, minx + striptime * (maxx - minx)) - miny; - - pdist = fabs(actiondist) - pdist; - pdistNewNormalized = (pathdist + pdist) / path->totdist; - - /* now we need to go pdist further (or less) on cu path */ - where_on_path(ob, (pathdist) / path->totdist, vec1, dir); /* vec needs size 4 */ - if (pdistNewNormalized <= 1) { - /* search for correction in positive path-direction */ - where_on_path(ob, pdistNewNormalized, vec2, dir); /* vec needs size 4 */ - sub_v3_v3v3(stride_offset, vec2, vec1); - } - else { - /* we reached the end of the path, search backwards instead */ - where_on_path(ob, (pathdist - pdist) / path->totdist, vec2, dir); /* vec needs size 4 */ - sub_v3_v3v3(stride_offset, vec1, vec2); - } - mul_mat3_m4_v3(ob->obmat, stride_offset); - return striptime; - } - } - return 0.0f; -} - -static void cyclic_offs_bone(Object *ob, bPose *pose, bActionStrip *strip, float time) -{ - /* only called when strip has cyclic, so >= 1.0f works... */ - if (time >= 1.0f) { - bActionChannel *achan = get_action_channel(strip->act, strip->offs_bone); - - if (achan && achan->ipo) { - IpoCurve *icu = NULL; - Bone *bone; - float min[3] = {0.0f, 0.0f, 0.0f}, max[3] = {0.0f, 0.0f, 0.0f}; - int index = 0, foundvert = 0; - - /* calculate the min/max */ - for (icu = achan->ipo->curve.first; icu; icu = icu->next) { - if (icu->totvert > 1) { - - if (icu->adrcode == AC_LOC_X) - index = 0; - else if (icu->adrcode == AC_LOC_Y) - index = 1; - else if (icu->adrcode == AC_LOC_Z) - index = 2; - else - continue; - - foundvert = 1; - min[index] = icu->bezt[0].vec[1][1]; - max[index] = icu->bezt[icu->totvert - 1].vec[1][1]; - } - } - if (foundvert) { - /* bring it into armature space */ - sub_v3_v3v3(min, max, min); - bone = BKE_armature_find_bone_name(ob->data, strip->offs_bone); /* weak */ - if (bone) { - mul_mat3_m4_v3(bone->arm_mat, min); - - /* dominant motion, cyclic_offset was cleared in BKE_pose_rest */ - if (strip->flag & (ACTSTRIP_CYCLIC_USEX | ACTSTRIP_CYCLIC_USEY | ACTSTRIP_CYCLIC_USEZ)) { - if (strip->flag & ACTSTRIP_CYCLIC_USEX) pose->cyclic_offset[0] = time * min[0]; - if (strip->flag & ACTSTRIP_CYCLIC_USEY) pose->cyclic_offset[1] = time * min[1]; - if (strip->flag & ACTSTRIP_CYCLIC_USEZ) pose->cyclic_offset[2] = time * min[2]; - } - else { - if (fabsf(min[0]) >= fabsf(min[1]) && fabsf(min[0]) >= fabsf(min[2])) - pose->cyclic_offset[0] = time * min[0]; - else if (fabsf(min[1]) >= fabsf(min[0]) && fabsf(min[1]) >= fabsf(min[2])) - pose->cyclic_offset[1] = time * min[1]; - else - pose->cyclic_offset[2] = time * min[2]; - } - } - } - } - } -} - -/* simple case for now; only the curve path with constraint value > 0.5 */ -/* blending we might do later... */ -static Object *get_parent_path(Object *ob) -{ - bConstraint *con; - - if (ob->parent && ob->parent->type == OB_CURVE) - return ob->parent; - - for (con = ob->constraints.first; con; con = con->next) { - if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) { - if (con->enforce > 0.5f) { - bFollowPathConstraint *data = con->data; - return data->tar; - } - } - } - return NULL; -} - -/* ************** do the action ************ */ - -/* ----- nla, etc. --------- */ - -static void do_nla(Scene *scene, Object *ob, int blocktype) -{ - bPose *tpose = NULL; - Key *key = NULL; - ListBase tchanbase = {NULL, NULL}, chanbase = {NULL, NULL}; - bActionStrip *strip, *striplast = NULL, *stripfirst = NULL; - float striptime, frametime, length, actlength; - float blendfac, stripframe; - float scene_cfra = BKE_scene_frame_get(scene); - int doit, dostride; - - if (blocktype == ID_AR) { - BKE_pose_copy_data(&tpose, ob->pose, 1); - BKE_pose_rest(ob->pose); // potentially destroying current not-keyed pose - } - else { - key = ob_get_key(ob); - } - - /* check on extend to left or right, when no strip is hit by 'cfra' */ - for (strip = ob->nlastrips.first; strip; strip = strip->next) { - /* escape loop on a hit */ - if (scene_cfra >= strip->start && scene_cfra <= strip->end + 0.1f) /* note 0.1 comes back below */ - break; - if (scene_cfra < strip->start) { - if (stripfirst == NULL) - stripfirst = strip; - else if (stripfirst->start > strip->start) - stripfirst = strip; - } - else if (scene_cfra > strip->end) { - if (striplast == NULL) - striplast = strip; - else if (striplast->end < strip->end) - striplast = strip; - } - } - if (strip == NULL) { /* extend */ - if (striplast) - scene_cfra = striplast->end; - else if (stripfirst) - scene_cfra = stripfirst->start; - } - - /* and now go over all strips */ - for (strip = ob->nlastrips.first; strip; strip = strip->next) { - doit = dostride = 0; - - if (strip->act && !(strip->flag & ACTSTRIP_MUTE)) { /* so theres an action */ - - /* Determine if the current frame is within the strip's range */ - length = strip->end - strip->start; - actlength = strip->actend - strip->actstart; - striptime = (scene_cfra - strip->start) / length; - stripframe = (scene_cfra - strip->start); - - if (striptime >= 0.0) { - - if (blocktype == ID_AR) - BKE_pose_rest(tpose); - - /* To handle repeat, we add 0.1 frame extra to make sure the last frame is included */ - if (striptime < 1.0f + 0.1f / length) { - - /* Handle path */ - if ((strip->flag & ACTSTRIP_USESTRIDE) && (blocktype == ID_AR) && (ob->ipoflag & OB_DISABLE_PATH) == 0) { - Object *parent = get_parent_path(ob); - - if (parent) { - Curve *cu = parent->data; - float ctime, pdist; - - if (cu->flag & CU_PATH) { - /* Ensure we have a valid path */ - if (cu->path == NULL || cu->path->data == NULL) makeDispListCurveTypes(scene, parent, 0); - if (cu->path) { - - /* Find the position on the path */ - ctime = bsystem_time(scene, ob, scene_cfra, 0.0); - - if (calc_ipo_spec(cu->ipo, CU_SPEED, &ctime) == 0) { - /* correct for actions not starting on zero */ - ctime = (ctime - strip->actstart) / cu->pathlen; - CLAMP(ctime, 0.0, 1.0); - } - pdist = ctime * cu->path->totdist; - - if (tpose && strip->stridechannel[0]) { - striptime = stridechannel_frame(parent, ob->size[0], strip, cu->path, pdist, tpose->stride_offset); - } - else { - if (strip->stridelen) { - striptime = pdist / strip->stridelen; - striptime = (float)fmod(striptime + strip->actoffs, 1.0); - } - else - striptime = 0; - } - - frametime = (striptime * actlength) + strip->actstart; - frametime = bsystem_time(scene, ob, frametime, 0.0); - - if (blocktype == ID_AR) { - extract_pose_from_action(tpose, strip->act, frametime); - } - else if (blocktype == ID_OB) { - extract_ipochannels_from_action(&tchanbase, &ob->id, strip->act, "Object", frametime); - if (key) - extract_ipochannels_from_action(&tchanbase, &key->id, strip->act, "Shape", frametime); - } - doit = dostride = 1; - } - } - } - } - /* To handle repeat, we add 0.1 frame extra to make sure the last frame is included */ - else { - - /* Mod to repeat */ - if (strip->repeat != 1.0f) { - float cycle = striptime * strip->repeat; - - striptime = (float)fmod(cycle, 1.0f + 0.1f / length); - cycle -= striptime; - - if (blocktype == ID_AR) - cyclic_offs_bone(ob, tpose, strip, cycle); - } - - frametime = (striptime * actlength) + strip->actstart; - frametime = nla_time(scene, frametime, (float)strip->repeat); - - if (blocktype == ID_AR) { - extract_pose_from_action(tpose, strip->act, frametime); - } - else if (blocktype == ID_OB) { - extract_ipochannels_from_action(&tchanbase, &ob->id, strip->act, "Object", frametime); - if (key) - extract_ipochannels_from_action(&tchanbase, &key->id, strip->act, "Shape", frametime); - } - - doit = 1; - } - } - /* Handle extend */ - else { - if (strip->flag & ACTSTRIP_HOLDLASTFRAME) { - /* we want the strip to hold on the exact fraction of the repeat value */ - - frametime = actlength * (strip->repeat - (int)strip->repeat); - if (frametime <= 0.000001f) frametime = actlength; /* rounding errors... */ - frametime = bsystem_time(scene, ob, frametime + strip->actstart, 0.0); - - if (blocktype == ID_AR) - extract_pose_from_action(tpose, strip->act, frametime); - else if (blocktype == ID_OB) { - extract_ipochannels_from_action(&tchanbase, &ob->id, strip->act, "Object", frametime); - if (key) - extract_ipochannels_from_action(&tchanbase, &key->id, strip->act, "Shape", frametime); - } - - /* handle cycle hold */ - if (strip->repeat != 1.0f) { - if (blocktype == ID_AR) - cyclic_offs_bone(ob, tpose, strip, strip->repeat - 1.0f); - } - - doit = 1; - } - } - - /* Handle blendin & blendout */ - if (doit) { - /* Handle blendin */ - - if (strip->blendin > 0.0 && stripframe <= strip->blendin && scene_cfra >= strip->start) { - blendfac = stripframe / strip->blendin; - } - else if (strip->blendout > 0.0 && stripframe >= (length - strip->blendout) && scene_cfra <= strip->end) { - blendfac = (length - stripframe) / (strip->blendout); - } - else - blendfac = 1; - - if (blocktype == ID_AR) { /* Blend this pose with the accumulated pose */ - /* offset bone, for matching cycles */ - blend_pose_offset_bone(strip, ob->pose, tpose, blendfac, strip->mode); - - blend_poses(ob->pose, tpose, blendfac, strip->mode); - if (dostride) - blend_pose_strides(ob->pose, tpose, blendfac, strip->mode); - } - else { - blend_ipochannels(&chanbase, &tchanbase, blendfac, strip->mode); - BLI_freelistN(&tchanbase); - } - } - } - } - } - - if (blocktype == ID_OB) { - execute_ipochannels(&chanbase); - } - else if (blocktype == ID_AR) { - /* apply stride offset to object */ - add_v3_v3(ob->obmat[3], ob->pose->stride_offset); - } - - /* free */ - if (tpose) - BKE_pose_free(tpose); - if (chanbase.first) - BLI_freelistN(&chanbase); -} - -#endif // XXX OLD ANIMATION SYSTEM (TO BE REMOVED) diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 1b301ba43b3..dffe26bd782 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -40,6 +40,8 @@ #include "BLI_rand.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_group_types.h" @@ -75,7 +77,7 @@ /* forward declarations */ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, - int level, short animated, short update); + int level, short flag); /* ******************************************************************** */ /* Animation Visualization */ @@ -174,10 +176,10 @@ bMotionPath *animviz_verify_motionpaths(ReportList *reports, Scene *scene, Objec /* avoid 0 size allocs */ if (avs->path_sf >= avs->path_ef) { BKE_reportf(reports, RPT_ERROR, - "Motion Path frame extents invalid for %s (%d to %d).%s\n", + "Motion path frame extents invalid for %s (%d to %d)%s", (pchan) ? pchan->name : ob->id.name, avs->path_sf, avs->path_ef, - (avs->path_sf == avs->path_ef) ? " Cannot have single-frame paths." : ""); + (avs->path_sf == avs->path_ef) ? TIP_(", cannot have single-frame paths") : ""); return NULL; } @@ -700,7 +702,11 @@ int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float qua /* ******************************************************************** */ /* Dupli-Geometry */ -static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index, int par_index, int type, short animated) +#define DUPLILIST_DO_UPDATE 1 +#define DUPLILIST_FOR_RENDER 2 +#define DUPLILIST_ANIMATED 4 + +static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index, int par_index, int type, short flag) { DupliObject *dob = MEM_callocN(sizeof(DupliObject), "dupliobject"); @@ -712,14 +718,14 @@ static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], i dob->index = index; dob->particle_index = par_index; dob->type = type; - dob->animated = (type == OB_DUPLIGROUP) && animated; + dob->animated = (type == OB_DUPLIGROUP) && (flag & DUPLILIST_ANIMATED); ob->lay = lay; return dob; } static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, - int level, short animated, short update) + int level, short flag) { DupliObject *dob; Group *group; @@ -735,13 +741,14 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde /* handles animated groups, and */ /* we need to check update for objects that are not in scene... */ - if (update) { + 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); } - animated = animated || group_is_animated(ob, group); + if (group_is_animated(ob, group)) + flag |= DUPLILIST_ANIMATED; for (go = group->gobject.first; go; go = go->next) { /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */ @@ -757,7 +764,7 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde mult_m4_m4m4(mat, ob->obmat, go->ob->obmat); } - dob = new_dupli_object(lb, go->ob, mat, ob->lay, 0, par_index, OB_DUPLIGROUP, animated); + dob = new_dupli_object(lb, go->ob, mat, ob->lay, 0, par_index, OB_DUPLIGROUP, flag); /* check the group instance and object layers match, also that the object visible flags are ok. */ if ((dob->origlay & group->layer) == 0 || @@ -772,14 +779,14 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde if (go->ob->transflag & OB_DUPLI) { copy_m4_m4(dob->ob->obmat, dob->mat); - object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, par_index, level + 1, animated, update); + object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, par_index, level + 1, flag); copy_m4_m4(dob->ob->obmat, dob->omat); } } } } -static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, short animated) +static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, short flag) { extern int enable_cu_speed; /* object.c */ Object copyob; @@ -817,7 +824,7 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_ind ok = (ok < ob->dupon); } - if (ok) { + if (ok) { DupliObject *dob; /* WARNING: doing animation updates in this way is not terribly accurate, as the dependencies @@ -827,7 +834,7 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_ind BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */ BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra); - dob = new_dupli_object(lb, ob, ob->obmat, ob->lay, scene->r.cfra, par_index, OB_DUPLIFRAMES, animated); + dob = new_dupli_object(lb, ob, ob->obmat, ob->lay, scene->r.cfra, par_index, OB_DUPLIFRAMES, flag); copy_m4_m4(dob->omat, copyob.obmat); } } @@ -851,8 +858,7 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_ind typedef struct VertexDupliData { ID *id; /* scene or group, for recursive loops */ int level; - short animated; - short update; + short flag; ListBase *lb; float pmat[4][4]; float obmat[4][4]; /* Only used for dupliverts inside dupligroups, where the ob->obmat is modified */ @@ -896,7 +902,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], origlay = vdd->ob->lay; - dob = new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, vdd->par_index, OB_DUPLIVERTS, vdd->animated); + dob = new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, vdd->par_index, OB_DUPLIVERTS, vdd->flag); /* restore the original layer so that each dupli will have proper dob->origlay */ vdd->ob->lay = origlay; @@ -908,13 +914,13 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], float tmpmat[4][4]; copy_m4_m4(tmpmat, vdd->ob->obmat); copy_m4_m4(vdd->ob->obmat, obmat); /* pretend we are really this mat */ - object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->par_index, vdd->level + 1, vdd->animated, vdd->update); + object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->par_index, vdd->level + 1, vdd->flag); copy_m4_m4(vdd->ob->obmat, tmpmat); } } static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, - int level, short animated, short update) + int level, short flag) { Object *ob, *ob_iter; Mesh *me = par->data; @@ -942,7 +948,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl else dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH); - if (G.is_rendering) { + 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); } @@ -964,7 +970,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl } /* Start looping on Scene OR Group objects */ - while (base || go) { + while (base || go) { if (sce) { ob_iter = base->object; oblay = base->lay; @@ -992,8 +998,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl vdd.id = id; vdd.level = level; - vdd.animated = animated; - vdd.update = update; + vdd.flag = flag; vdd.lb = lb; vdd.ob = ob; vdd.scene = scene; @@ -1039,7 +1044,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl } static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, - int level, short animated, short update) + int level, short flag) { Object *ob, *ob_iter; Base *base = NULL; @@ -1076,8 +1081,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa mloop = dm->getLoopArray(dm); mvert = dm->getVertArray(dm); - if (G.is_rendering) { - + 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; @@ -1100,7 +1104,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa } /* Start looping on Scene OR Group objects */ - while (base || go) { + while (base || go) { if (sce) { ob_iter = base->object; oblay = base->lay; @@ -1140,21 +1144,17 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa float *v3; /* float *v4; */ /* UNUSED */ float cent[3], quat[4], mat[3][3], mat3[3][3], tmat[4][4], obmat[4][4]; + float f_no[3]; MLoop *loopstart = mloop + mp->loopstart; - if (mp->totloop < 3) { - /* highly unlikely but to be safe */ + if (UNLIKELY(mp->totloop < 3)) { continue; } else { + BKE_mesh_calc_poly_normal(mp, mloop + mp->loopstart, mvert, f_no); v1 = mvert[(mv1 = loopstart[0].v)].co; v2 = mvert[(mv2 = loopstart[1].v)].co; v3 = mvert[(mv3 = loopstart[2].v)].co; -#if 0 - if (mp->totloop > 3) { - v4 = mvert[(mv4 = loopstart[3].v)].co; - } -#endif } /* translation */ @@ -1170,12 +1170,12 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa copy_v3_v3(obmat[3], cent); /* rotation */ - tri_to_quat(quat, v1, v2, v3); + tri_to_quat_ex(quat, v1, v2, v3, f_no); quat_to_mat3(mat, quat); /* scale */ if (par->transflag & OB_DUPLIFACES_SCALE) { - float size = BKE_mesh_calc_poly_area(mp, loopstart, mvert, NULL); + float size = BKE_mesh_calc_poly_area(mp, loopstart, mvert, f_no); size = sqrtf(size) * par->dupfacesca; mul_m3_fl(mat, size); } @@ -1186,8 +1186,8 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa copy_m4_m4(tmat, obmat); mul_m4_m4m3(obmat, tmat, mat); - dob = new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIFACES, animated); - if (G.is_rendering) { + dob = new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIFACES, (flag & DUPLILIST_ANIMATED)); + if (flag & DUPLILIST_FOR_RENDER) { w = 1.0f / (float)mp->totloop; if (orco) { @@ -1209,7 +1209,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa float tmpmat[4][4]; copy_m4_m4(tmpmat, ob->obmat); copy_m4_m4(ob->obmat, obmat); /* pretend we are really this mat */ - object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, par_index, level + 1, animated, update); + object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, par_index, level + 1, flag); copy_m4_m4(ob->obmat, tmpmat); } } @@ -1230,7 +1230,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa } static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int UNUSED(par_index), ParticleSystem *psys, - int level, short animated, short update) + int level, short flag) { GroupObject *go; Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL; @@ -1313,7 +1313,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 (update) { + if (flag & DUPLILIST_DO_UPDATE) { group_handle_recalc_and_update(scene, par, part->dup_group); } @@ -1456,9 +1456,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p else copy_m4_m4(mat, tmat); - dob = new_dupli_object(lb, go->ob, mat, par->lay, counter, index, OB_DUPLIPARTS, animated); + dob = new_dupli_object(lb, go->ob, mat, par->lay, counter, index, OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED)); copy_m4_m4(dob->omat, obcopylist[b].obmat); - if (G.is_rendering) + if (flag & DUPLILIST_FOR_RENDER) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } @@ -1516,9 +1516,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p if (part->draw & PART_DRAW_GLOBAL_OB) add_v3_v3v3(mat[3], mat[3], vec); - dob = new_dupli_object(lb, ob, mat, ob->lay, counter, index, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, animated); + dob = new_dupli_object(lb, ob, mat, ob->lay, counter, index, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED)); copy_m4_m4(dob->omat, oldobmat); - if (G.is_rendering) + if (flag & DUPLILIST_FOR_RENDER) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } @@ -1570,7 +1570,7 @@ static Object *find_family_object(Object **obar, char *family, char ch) } -static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_index, int level, short animated) +static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_index, int level, short flag) { Object *ob, *obar[256] = {NULL}; Curve *cu; @@ -1609,7 +1609,7 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_inde copy_m4_m4(obmat, par->obmat); copy_v3_v3(obmat[3], vec); - new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIVERTS, animated); + new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIVERTS, flag); } } @@ -1619,7 +1619,7 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_inde /* ------------- */ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, - int level, short animated, short update) + int level, short flag) { if ((ob->transflag & OB_DUPLI) == 0) return; @@ -1639,31 +1639,31 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas if (ob->transflag & OB_DUPLIPARTS) { ParticleSystem *psys = ob->particlesystem.first; for (; psys; psys = psys->next) - new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, psys, level + 1, animated, update); + new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, psys, level + 1, flag); } else if (ob->transflag & OB_DUPLIVERTS) { if (ob->type == OB_MESH) { - vertex_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated, update); + vertex_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, flag); } else if (ob->type == OB_FONT) { if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */ - font_duplilist(duplilist, scene, ob, par_index, level + 1, animated); + font_duplilist(duplilist, scene, ob, par_index, level + 1, flag); } } } else if (ob->transflag & OB_DUPLIFACES) { if (ob->type == OB_MESH) - face_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated, update); + face_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, flag); } else if (ob->transflag & OB_DUPLIFRAMES) { if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */ - frames_duplilist(duplilist, scene, ob, par_index, level + 1, animated); + frames_duplilist(duplilist, scene, ob, par_index, level + 1, flag); } } else if (ob->transflag & OB_DUPLIGROUP) { DupliObject *dob; - group_duplilist(duplilist, scene, ob, par_index, level + 1, animated, update); /* now recursive */ + group_duplilist(duplilist, scene, ob, par_index, level + 1, flag); /* now recursive */ if (level == 0) { for (dob = duplilist->first; dob; dob = dob->next) @@ -1675,19 +1675,24 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas /* Returns a list of DupliObject * note; group dupli's already set transform matrix. see note in group_duplilist() */ -ListBase *object_duplilist_ex(Scene *sce, Object *ob, int update) +ListBase *object_duplilist_ex(Scene *sce, Object *ob, int update, int for_render) { ListBase *duplilist = MEM_mallocN(sizeof(ListBase), "duplilist"); + int flag = 0; + + if (update) flag |= DUPLILIST_DO_UPDATE; + if (for_render) flag |= DUPLILIST_FOR_RENDER; + duplilist->first = duplilist->last = NULL; - object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0, 0, update); + object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0, flag); return duplilist; } /* note: previously updating was always done, this is why it defaults to be on * but there are likely places it can be called without updating */ -ListBase *object_duplilist(Scene *sce, Object *ob) +ListBase *object_duplilist(Scene *sce, Object *ob, int for_render) { - return object_duplilist_ex(sce, ob, TRUE); + return object_duplilist_ex(sce, ob, TRUE, for_render); } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 6a3dae93639..66ed31c5b72 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -188,9 +188,9 @@ short BKE_animdata_set_action(ReportList *reports, ID *id, bAction *act) else { /* cannot set */ BKE_reportf(reports, RPT_ERROR, - "Couldn't set Action '%s' onto ID '%s', as it doesn't have suitably rooted paths for this purpose", - act->id.name + 2, id->name); - //ok = 0; + "Could not set action '%s' onto ID '%s', as it does not have suitably rooted paths " + "for this purpose", act->id.name + 2, id->name); + /* ok = 0; */ } } else { @@ -419,7 +419,7 @@ void action_move_fcurves_by_basepath(bAction *srcAct, bAction *dstAct, const cha /* should F-Curve be moved over? * - we only need the start of the path to match basepath */ - if (animpath_matches_basepath(fcu->rna_path, basepath)) { + if (animpath_matches_basepath(fcu->rna_path, basepath)) { bActionGroup *agrp = NULL; /* if grouped... */ @@ -574,7 +574,7 @@ static char *rna_path_rename_fix(ID *owner_id, const char *prefix, const char *o */ if ( (prefixPtr && oldNamePtr) && (prefixPtr + prefixLen == oldNamePtr) ) { /* if we haven't aren't able to resolve the path now, try again after fixing it */ - if (!verify_paths || check_rna_path_is_valid(owner_id, oldpath) == 0) { + if (!verify_paths || check_rna_path_is_valid(owner_id, oldpath) == 0) { DynStr *ds = BLI_dynstr_new(); char *postfixPtr = oldNamePtr + oldNameLen; char *newPath = NULL; @@ -639,7 +639,7 @@ static void fcurves_path_rename_fix(ID *owner_id, const char *prefix, const char if (fcu->rna_path != old_path) { bActionGroup *agrp = fcu->grp; - if ((agrp) && strcmp(oldName, agrp->name)==0) { + if ((agrp) && strcmp(oldName, agrp->name) == 0) { BLI_strncpy(agrp->name, newName, sizeof(agrp->name)); } } @@ -724,7 +724,7 @@ void BKE_animdata_fix_paths_rename(ID *owner_id, AnimData *adt, ID *ref_id, cons /* pad the names with [" "] so that only exact matches are made */ oldN = BLI_sprintfN("[\"%s\"]", oldName); newN = BLI_sprintfN("[\"%s\"]", newName); - } + } else { oldN = BLI_sprintfN("[%d]", oldSubscript); newN = BLI_sprintfN("[%d]", newSubscript); @@ -1239,7 +1239,7 @@ static short animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_in if (new_ptr.type == &RNA_PoseBone) { /* bone transforms - update pose (i.e. tag depsgraph) */ skip_updates_hack = 1; - } + } if (skip_updates_hack == 0) RNA_property_update_cache_add(&new_ptr, prop); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index b87342f85fa..b3cbc1f2b16 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -534,10 +534,12 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest) mul_m4_v3(imat, h2); /* if next bone is B-bone too, use average handle direction */ - if (next->bone->segments > 1) - ; - else + if (next->bone->segments > 1) { + /* pass */ + } + else { h2[1] -= length; + } normalize_v3(h2); /* find the next roll to interpolate as well */ @@ -945,7 +947,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float } } - if (use_dverts || armature_def_nr >= 0) { + if (use_dverts || armature_def_nr != -1) { if (dm) dvert = dm->getVertData(dm, i, CD_MDEFORMVERT); else if (dverts && i < target_totvert) @@ -956,7 +958,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float else dvert = NULL; - if (armature_def_nr >= 0 && dvert) { + if (armature_def_nr != -1 && dvert) { armature_weight = defvert_find_weight(dvert, armature_def_nr); if (invert_vgroup) @@ -1423,19 +1425,20 @@ void BKE_rotMode_change_values(float quat[4], float eul[3], float axis[3], float * *************************************************************************** */ /* Computes vector and roll based on a rotation. * "mat" must contain only a rotation, and no scaling. */ -void mat3_to_vec_roll(float mat[][3], float vec[3], float *roll) +void mat3_to_vec_roll(float mat[][3], float r_vec[3], float *r_roll) { - if (vec) - copy_v3_v3(vec, mat[1]); + if (r_vec) { + copy_v3_v3(r_vec, mat[1]); + } - if (roll) { + if (r_roll) { float vecmat[3][3], vecmatinv[3][3], rollmat[3][3]; vec_roll_to_mat3(mat[1], 0.0f, vecmat); invert_m3_m3(vecmatinv, vecmat); mul_m3_m3m3(rollmat, vecmatinv, mat); - *roll = (float)atan2(rollmat[2][0], rollmat[2][2]); + *r_roll = atan2f(rollmat[2][0], rollmat[2][2]); } } @@ -1459,7 +1462,7 @@ void vec_roll_to_mat3(const float vec[3], const float roll, float mat[][3]) * so a value inbetween these is needed. * * was 0.000001, causes bug [#30438] (which is same as [#27675, imho). - * Reseting it to org value seems to cause no more [#23954]... + * Resetting it to org value seems to cause no more [#23954]... * * was 0.0000000000001, caused bug [#31333], smaller values give unstable * roll when toggling editmode again... @@ -1590,7 +1593,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected if (UNLIKELY(pchanp == NULL)) { /* happens for proxies that become invalid because of a missing link - * for regulat cases it shouldn't happen at all */ + * for regular cases it shouldn't happen at all */ } else if (pchan->bone->layer & layer_protected) { ListBase proxylocal_constraints = {NULL, NULL}; diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 99b788e80ce..e1e868b234e 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -119,7 +119,7 @@ void free_blender(void) BKE_sequencer_cache_destruct(); IMB_moviecache_destruct(); - free_nodesystem(); + free_nodesystem(); } void initglobals(void) @@ -237,7 +237,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath /* free G.main Main database */ // CTX_wm_manager_set(C, NULL); - clear_global(); + clear_global(); /* clear old property update cache, in case some old references are left dangling */ RNA_property_update_cache_free(); @@ -338,7 +338,7 @@ static int handle_subversion_warning(Main *main, ReportList *reports) (main->minversionfile == BLENDER_VERSION && main->minsubversionfile > BLENDER_SUBVERSION)) { - BKE_reportf(reports, RPT_ERROR, "File written by newer Blender binary: %d.%d, expect loss of data!", + BKE_reportf(reports, RPT_ERROR, "File written by newer Blender binary (%d.%d), expect loss of data!", main->minversionfile, main->minsubversionfile); } @@ -407,9 +407,9 @@ int BKE_read_file(bContext *C, const char *filepath, ReportList *reports) } else setup_app_data(C, bfd, filepath); // frees BFD - } + } else - BKE_reports_prependf(reports, "Loading %s failed: ", filepath); + BKE_reports_prependf(reports, "Loading '%s' failed: ", filepath); return (bfd ? retval : BKE_READ_FILE_FAIL); } @@ -485,7 +485,7 @@ static int read_undosave(bContext *C, UndoElem *uel) int success = 0, fileflags; /* This is needed so undoing/redoing doesn't crash with threaded previews going */ - WM_jobs_stop_all(CTX_wm_manager(C)); + WM_jobs_kill_all_except(CTX_wm_manager(C), CTX_wm_screen(C)); BLI_strncpy(mainstr, G.main->name, sizeof(mainstr)); /* temporal store */ @@ -612,7 +612,7 @@ void BKE_write_undo(bContext *C, const char *name) } } -/* 1= an undo, -1 is a redo. we have to make sure 'curundo' remains at current situation */ +/* 1 = an undo, -1 is a redo. we have to make sure 'curundo' remains at current situation */ void BKE_undo_step(bContext *C, int step) { @@ -621,7 +621,9 @@ void BKE_undo_step(bContext *C, int step) } else if (step == 1) { /* curundo should never be NULL, after restart or load file it should call undo_save */ - if (curundo == NULL || curundo->prev == NULL) ; // XXX error("No undo available"); + if (curundo == NULL || curundo->prev == NULL) { + // XXX error("No undo available"); + } else { if (G.debug & G_DEBUG) printf("undo %s\n", curundo->name); curundo = curundo->prev; @@ -631,7 +633,9 @@ void BKE_undo_step(bContext *C, int step) else { /* curundo has to remain current situation! */ - if (curundo == NULL || curundo->next == NULL) ; // XXX error("No redo available"); + if (curundo == NULL || curundo->next == NULL) { + // XXX error("No redo available"); + } else { read_undosave(C, curundo->next); curundo = curundo->next; diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c index 18161bc6fcb..df7fb2c1807 100644 --- a/source/blender/blenkernel/intern/bmfont.c +++ b/source/blender/blenkernel/intern/bmfont.c @@ -96,13 +96,13 @@ void readBitmapFontVersion0(ImBuf * ibuf, unsigned char * rect, int step) ysize = (bytes + (ibuf->x - 1)) / ibuf->x; if (ysize < ibuf->y) { - /* we're first going to copy all data into a liniar buffer. + /* we're first going to copy all data into a linear buffer. * step can be 4 or 1 bytes, and the data is not sequential because * the bitmap was flipped vertically. */ buffer = MEM_mallocN(bytes, "readBitmapFontVersion0:buffer"); - index = 0; + index = 0; for (i = 0; i < bytes; i++) { buffer[i] = rect[index]; index += step; diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index 79d5e092a10..b6f1b88c912 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -101,13 +101,15 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, break; } } - else if (rule->type == eBoidRuleType_Goal && eob == bpa->ground) - ; /* skip current object */ + else if (rule->type == eBoidRuleType_Goal && eob == bpa->ground) { + /* skip current object */ + } else if (pd->forcefield == PFIELD_BOID && mul * pd->f_strength > 0.0f && get_effector_data(cur, &cur_efd, &epoint, 0)) { float temp = mul * pd->f_strength * effector_falloff(cur, &cur_efd, &epoint, bbd->part->effector_weights); - if (temp == 0.0f) - ; /* do nothing */ + if (temp == 0.0f) { + /* do nothing */ + } else if (temp > priority) { priority = temp; eff = cur; @@ -954,7 +956,8 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa) // } //} - bbd->wanted_co[0]=bbd->wanted_co[1]=bbd->wanted_co[2]=bbd->wanted_speed=0.0f; + zero_v3(bbd->wanted_co); + bbd->wanted_speed = 0.0f; /* create random seed for every particle & frame */ rand = (int)(PSYS_FRAND(psys->seed + p) * 1000); @@ -988,7 +991,8 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa) add_v3_v3(wanted_co, bbd->wanted_co); wanted_speed += bbd->wanted_speed; n++; - bbd->wanted_co[0]=bbd->wanted_co[1]=bbd->wanted_co[2]=bbd->wanted_speed=0.0f; + zero_v3(bbd->wanted_co); + bbd->wanted_speed = 0.0f; } } @@ -1168,7 +1172,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) /* constrain direction with maximum angular velocity */ angle = saacos(dot_v3v3(old_dir, wanted_dir)); - angle = minf(angle, val.max_ave); + angle = min_ff(angle, val.max_ave); cross_v3_v3v3(nor, old_dir, wanted_dir); axis_angle_to_quat(q, nor, angle); @@ -1264,9 +1268,9 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) { float grav[3]; - grav[0]= 0.0f; - grav[1]= 0.0f; - grav[2]= bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f; + grav[0] = 0.0f; + grav[1] = 0.0f; + grav[2] = bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f; /* don't take forward acceleration into account (better banking) */ if (dot_v3v3(bpa->data.acc, pa->state.vel) > 0.0f) { @@ -1307,9 +1311,9 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) { float grav[3]; - grav[0]= 0.0f; - grav[1]= 0.0f; - grav[2]= bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f; + grav[0] = 0.0f; + grav[1] = 0.0f; + grav[2] = bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f; /* gather apparent gravity */ diff --git a/source/blender/blenkernel/intern/booleanops_mesh.c b/source/blender/blenkernel/intern/booleanops_mesh.c index be79077bb58..461b945282f 100644 --- a/source/blender/blenkernel/intern/booleanops_mesh.c +++ b/source/blender/blenkernel/intern/booleanops_mesh.c @@ -142,7 +142,7 @@ CSG_AddMeshToBlender( /* Create a new blender mesh object - using 'base' as * a template for the new object. */ - ob_new= AddNewBlenderMesh(mesh->base); + ob_new = AddNewBlenderMesh(mesh->base); me_new = ob_new->data; @@ -180,7 +180,7 @@ CSG_PerformOp( if ((mesh1 == NULL) || (mesh2 == NULL) || (output == NULL)) { return 0; - } + } if ((int_op_type < 1) || (int_op_type > 3)) return 0; switch (int_op_type) { @@ -203,8 +203,8 @@ CSG_PerformOp( mesh1->m_face_iterator, mesh1->m_vertex_iterator, mesh2->m_face_iterator, - mesh2->m_vertex_iterator, - InterpFaceVertexData + mesh2->m_vertex_iterator, + InterpFaceVertexData ); } else { @@ -215,8 +215,8 @@ CSG_PerformOp( mesh1->m_face_iterator, mesh1->m_vertex_iterator, mesh2->m_face_iterator, - mesh2->m_vertex_iterator, - InterpNoUserData + mesh2->m_vertex_iterator, + InterpNoUserData ); } diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index fde95e0767e..98b206712d6 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -529,7 +529,7 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf unsigned char *dst, crgb[3]; const float alpha = BKE_brush_alpha_get(scene, brush); float brush_rgb[3]; - + imbflag = (flt) ? IB_rectfloat : IB_rect; xoff = -bufsize / 2.0f + 0.5f; yoff = -bufsize / 2.0f + 0.5f; @@ -563,7 +563,7 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf else { BKE_brush_sample_tex(scene, brush, xy, rgba, 0); mul_v3_v3v3(dstf, rgba, brush_rgb); - dstf[3] = rgba[3] *alpha *BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); + dstf[3] = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); } } } @@ -594,7 +594,7 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf else if (texfall == 2) { BKE_brush_sample_tex(scene, brush, xy, rgba, 0); mul_v3_v3(rgba, brush->rgb); - alpha_f = rgba[3] *alpha *BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); + alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); rgb_float_to_uchar(dst, rgba); @@ -602,7 +602,7 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf } else { BKE_brush_sample_tex(scene, brush, xy, rgba, 0); - alpha_f = rgba[3] *alpha *BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); + alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); dst[0] = crgb[0]; dst[1] = crgb[1]; @@ -618,18 +618,18 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf /* Unified Size and Strength */ -// XXX: be careful about setting size and unprojected radius -// because they depend on one another -// these functions do not set the other corresponding value -// this can lead to odd behavior if size and unprojected -// radius become inconsistent. -// the biggest problem is that it isn't possible to change -// unprojected radius because a view context is not -// available. my ussual solution to this is to use the -// ratio of change of the size to change the unprojected -// radius. Not completely convinced that is correct. -// In anycase, a better solution is needed to prevent -// inconsistency. +/* XXX: be careful about setting size and unprojected radius + * because they depend on one another + * these functions do not set the other corresponding value + * this can lead to odd behavior if size and unprojected + * radius become inconsistent. + * the biggest problem is that it isn't possible to change + * unprojected radius because a view context is not + * available. my ussual solution to this is to use the + * ratio of change of the size to change the unprojected + * radius. Not completely convinced that is correct. + * In anycase, a better solution is needed to prevent + * inconsistency. */ void BKE_brush_size_set(Scene *scene, Brush *brush, int size) { @@ -741,7 +741,7 @@ void BKE_brush_scale_unprojected_radius(float *unprojected_radius, } /* scale brush size to reflect a change in the brush's unprojected radius */ -void BKE_brush_scale_size(int *BKE_brush_size_get, +void BKE_brush_scale_size(int *r_brush_size, float new_unprojected_radius, float old_unprojected_radius) { @@ -749,7 +749,7 @@ void BKE_brush_scale_size(int *BKE_brush_size_get, /* avoid division by zero */ if (old_unprojected_radius != 0) scale /= new_unprojected_radius; - (*BKE_brush_size_get) = (int)((float)(*BKE_brush_size_get) * scale); + (*r_brush_size) = (int)((float)(*r_brush_size) * scale); } /* Brush Painting */ @@ -876,8 +876,8 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, /* not sure if it's actually needed or it's a mistake in coords/sizes * calculation in brush_painter_fixed_tex_partial_update(), but without this * limitation memory gets corrupted at fast strokes with quite big spacing (sergey) */ - w = MIN2(w, ibuf->x); - h = MIN2(h, ibuf->y); + w = min_ii(w, ibuf->x); + h = min_ii(h, ibuf->y); if (painter->cache.flt) { for (; y < h; y++) { @@ -1052,13 +1052,13 @@ void BKE_brush_painter_break_stroke(BrushPainter *painter) static void brush_pressure_apply(BrushPainter *painter, Brush *brush, float pressure) { if (BKE_brush_use_alpha_pressure(painter->scene, brush)) - brush_alpha_set(painter->scene, brush, maxf(0.0f, painter->startalpha * pressure)); + brush_alpha_set(painter->scene, brush, max_ff(0.0f, painter->startalpha * pressure)); if (BKE_brush_use_size_pressure(painter->scene, brush)) - BKE_brush_size_set(painter->scene, brush, maxf(1.0f, painter->startsize * pressure)); + BKE_brush_size_set(painter->scene, brush, max_ff(1.0f, painter->startsize * pressure)); if (brush->flag & BRUSH_JITTER_PRESSURE) - brush->jitter = maxf(0.0f, painter->startjitter * pressure); + brush->jitter = max_ff(0.0f, painter->startjitter * pressure); if (brush->flag & BRUSH_SPACING_PRESSURE) - brush->spacing = maxf(1.0f, painter->startspacing * (1.5f - pressure)); + brush->spacing = max_ff(1.0f, painter->startspacing * (1.5f - pressure)); } void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2], float jitterpos[2]) @@ -1158,7 +1158,7 @@ int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float p /* compute brush spacing adapted to brush radius, spacing may depend * on pressure, so update it */ brush_pressure_apply(painter, brush, painter->lastpressure); - spacing = maxf(1.0f, radius) * brush->spacing * 0.01f; + spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f; /* setup starting distance, direction vector and accumulated distance */ startdistance = painter->accumdistance; @@ -1176,7 +1176,7 @@ int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float p t = step / len; press = (1.0f - t) * painter->lastpressure + t * pressure; brush_pressure_apply(painter, brush, press); - spacing = maxf(1.0f, radius) * brush->spacing * 0.01f; + spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f; BKE_brush_jitter_pos(scene, brush, paintpos, finalpos); diff --git a/source/blender/blenkernel/intern/bullet.c b/source/blender/blenkernel/intern/bullet.c index 7defa7e1be3..088031e16a7 100644 --- a/source/blender/blenkernel/intern/bullet.c +++ b/source/blender/blenkernel/intern/bullet.c @@ -54,7 +54,7 @@ BulletSoftBody *bsbNew(void) bsb->viterations = 0; - bsb->piterations = 2; + bsb->piterations = 2; bsb->diterations = 0; bsb->citerations = 4; diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index 32ae6d04934..ad828a70dd8 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -358,8 +358,8 @@ float nearest_point_in_tri_surface(const float v0[3], const float v1[3], const f * BVH from meshs callbacks */ -// Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_faces. -// userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. +/* Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_faces. + * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */ static void mesh_faces_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest) { const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata; @@ -395,8 +395,8 @@ static void mesh_faces_nearest_point(void *userdata, int index, const float co[3 } while (t2); } -// Callback to bvh tree raycast. The tree must bust have been built using bvhtree_from_mesh_faces. -// userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. +/* Callback to bvh tree raycast. The tree must bust have been built using bvhtree_from_mesh_faces. + * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */ static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) { const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata; @@ -435,8 +435,8 @@ static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *r } while (t2); } -// Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_edges. -// userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. +/* Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_edges. + * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */ static void mesh_edges_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest) { const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata; @@ -463,12 +463,12 @@ static void mesh_edges_nearest_point(void *userdata, int index, const float co[3 /* * BVH builders */ -// Builds a bvh tree.. where nodes are the vertexs of the given mesh +/* Builds a bvh tree.. where nodes are the vertexs of the given mesh */ BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis) { BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_VERTICES); - //Not in cache + /* Not in cache */ if (tree == NULL) { int i; int numVerts = mesh->getNumVerts(mesh); @@ -484,7 +484,7 @@ BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float BLI_bvhtree_balance(tree); - //Save on cache for later use + /* Save on cache for later use */ // printf("BVHTree built and saved on cache\n"); bvhcache_insert(&mesh->bvhCache, tree, BVHTREE_FROM_VERTICES); } @@ -495,15 +495,15 @@ BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float } - //Setup BVHTreeFromMesh + /* Setup BVHTreeFromMesh */ memset(data, 0, sizeof(*data)); data->tree = tree; if (data->tree) { data->cached = TRUE; - //a NULL nearest callback works fine - //remeber the min distance to point is the same as the min distance to BV of point + /* a NULL nearest callback works fine + * remeber the min distance to point is the same as the min distance to BV of point */ data->nearest_callback = NULL; data->raycast_callback = NULL; @@ -517,12 +517,12 @@ BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float return data->tree; } -// Builds a bvh tree.. where nodes are the faces of the given mesh. +/* Builds a bvh tree.. where nodes are the faces of the given mesh. */ BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis) { BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_FACES); - //Not in cache + /* Not in cache */ if (tree == NULL) { int i; int numFaces = mesh->getNumTessFaces(mesh); @@ -616,7 +616,7 @@ BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float } BLI_bvhtree_balance(tree); - //Save on cache for later use + /* Save on cache for later use */ // printf("BVHTree built and saved on cache\n"); bvhcache_insert(&mesh->bvhCache, tree, BVHTREE_FROM_FACES); } @@ -627,7 +627,7 @@ BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float } - //Setup BVHTreeFromMesh + /* Setup BVHTreeFromMesh */ memset(data, 0, sizeof(*data)); data->tree = tree; @@ -647,12 +647,12 @@ BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float } -// Builds a bvh tree.. where nodes are the faces of the given mesh. +/* Builds a bvh tree.. where nodes are the faces of the given mesh. */ BVHTree *bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis) { BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_EDGES); - //Not in cache + /* Not in cache */ if (tree == NULL) { int i; int numEdges = mesh->getNumEdges(mesh); @@ -672,7 +672,7 @@ BVHTree *bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *mesh, float } BLI_bvhtree_balance(tree); - //Save on cache for later use + /* Save on cache for later use */ // printf("BVHTree built and saved on cache\n"); bvhcache_insert(&mesh->bvhCache, tree, BVHTREE_FROM_EDGES); } @@ -683,7 +683,7 @@ BVHTree *bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *mesh, float } - //Setup BVHTreeFromMesh + /* Setup BVHTreeFromMesh */ memset(data, 0, sizeof(*data)); data->tree = tree; @@ -703,7 +703,7 @@ BVHTree *bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *mesh, float } -// Frees data allocated by a call to bvhtree_from_mesh_*. +/* Frees data allocated by a call to bvhtree_from_mesh_*. */ void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data) { if (data->tree) { @@ -728,7 +728,7 @@ static void bvhcacheitem_set_if_match(void *_cached, void *_search) BVHCacheItem *search = (BVHCacheItem *)_search; if (search->type == cached->type) { - search->tree = cached->tree; + search->tree = cached->tree; } } diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index ed7ac0e1a32..9118baeae6f 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -151,7 +151,7 @@ float BKE_camera_object_dof_distance(Object *ob) Camera *cam = (Camera *)ob->data; if (ob->type != OB_CAMERA) return 0.0f; - if (cam->dof_ob) { + if (cam->dof_ob) { /* too simple, better to return the distance on the view axis only * return len_v3v3(ob->obmat[3], cam->dof_ob->obmat[3]); */ float mat[4][4], imat[4][4], obmat[4][4]; @@ -262,11 +262,12 @@ void BKE_camera_params_from_view3d(CameraParams *params, View3D *v3d, RegionView } else if (rv3d->persp == RV3D_ORTHO) { /* orthographic view */ + int sensor_size = BKE_camera_sensor_size(params->sensor_fit, params->sensor_x, params->sensor_y); params->clipend *= 0.5f; // otherwise too extreme low zbuffer quality params->clipsta = -params->clipend; params->is_ortho = TRUE; - params->ortho_scale = rv3d->dist; + params->ortho_scale = rv3d->dist * sensor_size / v3d->lens; params->zoom = 2.0f; } else { diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index b176ed429f8..2e0b3a3c64a 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -273,6 +273,8 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm) cddm->pbvh = BLI_pbvh_new(); cddm->pbvh_draw = can_pbvh_draw(ob, dm); + pbvh_show_diffuse_color_set(cddm->pbvh, ob->sculpt->show_diffuse_color); + BKE_mesh_tessface_ensure(me); BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert, @@ -379,7 +381,7 @@ static void cdDM_drawUVEdges(DerivedMesh *dm) for (i = 0; i < dm->numTessFaceData; i++, mf++) { if (!(mf->flag & ME_HIDE)) { draw = 1; - } + } else { draw = 0; } @@ -438,7 +440,7 @@ static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int drawAllEdges (drawLooseEdges || !(medge->flag & ME_LOOSEEDGE))) { draw = TRUE; - } + } else { draw = FALSE; } @@ -486,7 +488,7 @@ static void cdDM_drawLooseEdges(DerivedMesh *dm) for (i = 0; i < dm->numEdgeData; i++, medge++) { if (medge->flag & ME_LOOSEEDGE) { draw = 1; - } + } else { draw = 0; } @@ -552,7 +554,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, glShadeModel(shademodel = new_shademodel); glBegin(glmode = new_glmode); - } + } if (drawCurrentMat) { if (shademodel == GL_FLAT) { @@ -612,14 +614,29 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, CDDerivedMesh *cddm = (CDDerivedMesh *) dm; MVert *mv = cddm->mvert; MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE); - MCol *realcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_MCOL); float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL); MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); - int i, j, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX); - int startFace = 0 /*, lastFlag = 0xdeadbeef */ /* UNUSED */; - MCol *mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL); - if (!mcol) - mcol = dm->getTessFaceDataArray(dm, CD_MCOL); + MCol *mcol; + int i, orig; + int colType, startFace = 0; + + /* double lookup */ + const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); + if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { + index_mf_to_mpoly = index_mp_to_orig = NULL; + } + + colType = CD_TEXTURE_MCOL; + mcol = dm->getTessFaceDataArray(dm, colType); + if (!mcol) { + colType = CD_PREVIEW_MCOL; + mcol = dm->getTessFaceDataArray(dm, colType); + } + if (!mcol) { + colType = CD_MCOL; + mcol = dm->getTessFaceDataArray(dm, colType); + } cdDM_update_normals_from_pbvh(dm); @@ -634,8 +651,8 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, draw_option = drawParams(tf ? &tf[i] : NULL, (mcol != NULL), mf->mat_nr); } else { - if (index) { - orig = *index++; + if (index_mf_to_mpoly) { + orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i); if (orig == ORIGINDEX_NONE) { if (nors) nors += 3; continue; } if (drawParamsMapped) { draw_option = drawParamsMapped(userData, orig); } else { if (nors) nors += 3; continue; } @@ -697,42 +714,11 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, } } else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */ - MCol *col = realcol; - if (!col) - col = mcol; - GPU_vertex_setup(dm); GPU_normal_setup(dm); GPU_uv_setup(dm); - if (col != NULL) { -#if 0 - if (realcol && dm->drawObject->colType == CD_TEXTURE_MCOL) { - col = 0; - } - else if (mcol && dm->drawObject->colType == CD_MCOL) { - col = 0; - } - - if (col != 0) -#endif - { - unsigned char *colors = MEM_mallocN(dm->getNumTessFaces(dm) * 4 * 3 * sizeof(unsigned char), "cdDM_drawFacesTex_common"); - for (i = 0; i < dm->getNumTessFaces(dm); i++) { - for (j = 0; j < 4; j++) { - /* bgr -> rgb is intentional (and stupid), but how its stored internally */ - colors[i * 12 + j * 3] = col[i * 4 + j].b; - colors[i * 12 + j * 3 + 1] = col[i * 4 + j].g; - colors[i * 12 + j * 3 + 2] = col[i * 4 + j].r; - } - } - GPU_color3_upload(dm, colors); - MEM_freeN(colors); - if (realcol) - dm->drawObject->colType = CD_TEXTURE_MCOL; - else if (mcol) - dm->drawObject->colType = CD_MCOL; - } - GPU_color_setup(dm); + if (mcol) { + GPU_color_setup(dm, colType); } if (!GPU_buffer_legacy(dm)) { @@ -753,15 +739,18 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, draw_option = drawParams(tf ? &tf[actualFace] : NULL, (mcol != NULL), mf[actualFace].mat_nr); } else { - if (index) { - orig = index[actualFace]; - if (orig == ORIGINDEX_NONE) continue; - if (drawParamsMapped) + if (index_mf_to_mpoly) { + orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace); + if (orig == ORIGINDEX_NONE) { + continue; + } + if (drawParamsMapped) { draw_option = drawParamsMapped(userData, orig); + } } - else - if (drawParamsMapped) + else if (drawParamsMapped) { draw_option = drawParamsMapped(userData, actualFace); + } } /* flush buffer if current triangle isn't drawable or it's last triangle */ @@ -779,7 +768,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, int count = (i - startFace + (draw_option != DM_DRAW_OPTION_SKIP ? 1 : 0)) * 3; if (count) { - if (col) + if (mcol && draw_option != DM_DRAW_OPTION_NO_MCOL) GPU_color_switch(1); else GPU_color_switch(0); @@ -814,16 +803,32 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, CDDerivedMesh *cddm = (CDDerivedMesh *) dm; MVert *mv = cddm->mvert; MFace *mf = cddm->mface; - MCol *mc; + MCol *mcol; float *nors = DM_get_tessface_data_layer(dm, CD_NORMAL); - int useColors = flag & DM_DRAW_USE_COLORS; - int i, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX); + int colType, useColors = flag & DM_DRAW_USE_COLORS; + int i, orig; - mc = DM_get_tessface_data_layer(dm, CD_ID_MCOL); - if (!mc) - mc = DM_get_tessface_data_layer(dm, CD_PREVIEW_MCOL); - if (!mc) - mc = DM_get_tessface_data_layer(dm, CD_MCOL); + + /* double lookup */ + const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); + if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { + index_mf_to_mpoly = index_mp_to_orig = NULL; + } + + + colType = CD_ID_MCOL; + mcol = DM_get_tessface_data_layer(dm, colType); + if (!mcol) { + colType = CD_PREVIEW_MCOL; + mcol = DM_get_tessface_data_layer(dm, colType); + } + if (!mcol) { + colType = CD_MCOL; + mcol = DM_get_tessface_data_layer(dm, colType); + } + + printf("%s: %p(%d/%d)\n", __func__, mcol, CD_ID_MCOL, colType); cdDM_update_normals_from_pbvh(dm); @@ -835,7 +840,7 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int drawSmooth = (flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : (mf->flag & ME_SMOOTH); DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL; - orig = (index == NULL) ? i : *index++; + orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i; if (orig == ORIGINDEX_NONE) draw_option = setMaterial(mf->mat_nr + 1, NULL); @@ -845,8 +850,8 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, if (draw_option != DM_DRAW_OPTION_SKIP) { unsigned char *cp = NULL; - if (useColors && mc) - cp = (unsigned char *)&mc[i * 4]; + if (useColors && mcol) + cp = (unsigned char *)&mcol[i * 4]; /* no need to set shading mode to flat because * normals are already used to change shading */ @@ -906,8 +911,9 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int prevstart = 0; GPU_vertex_setup(dm); GPU_normal_setup(dm); - if (useColors && mc) - GPU_color_setup(dm); + if (useColors && mcol) { + GPU_color_setup(dm, colType); + } if (!GPU_buffer_legacy(dm)) { int tottri = dm->drawObject->tot_triangle_point / 3; glShadeModel(GL_SMOOTH); @@ -934,7 +940,7 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, if (i != tottri - 1) next_actualFace = dm->drawObject->triangle_to_mface[i + 1]; - orig = (index == NULL) ? actualFace : index[actualFace]; + orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace) : actualFace; if (orig == ORIGINDEX_NONE) draw_option = setMaterial(mface->mat_nr + 1, NULL); @@ -1039,7 +1045,14 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, /* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */ float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL); int a, b, do_draw, matnr, new_matnr; - int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + int orig; + + /* double lookup */ + const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); + if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { + index_mf_to_mpoly = index_mp_to_orig = NULL; + } cdDM_update_normals_from_pbvh(dm); @@ -1072,7 +1085,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, continue; } else if (setDrawOptions) { - orig = (index) ? index[a] : a; + orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a; if (orig == ORIGINDEX_NONE) { /* since the material is set by setMaterial(), faces with no @@ -1176,13 +1189,13 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, datatypes[numdata].size = 2; datatypes[numdata].type = GL_FLOAT; numdata++; - } + } for (b = 0; b < attribs.totmcol; b++) { datatypes[numdata].index = attribs.mcol[b].gl_index; datatypes[numdata].size = 4; datatypes[numdata].type = GL_UNSIGNED_BYTE; numdata++; - } + } if (attribs.tottang) { datatypes[numdata].index = attribs.tang.gl_index; datatypes[numdata].size = 4; @@ -1242,7 +1255,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a; copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize * 2], (char *)col); offset += sizeof(unsigned char) * 4; - } + } if (attribs.tottang) { float *tang = attribs.tang.array[a * 4 + 0]; copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset], tang); @@ -1283,7 +1296,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a; copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize * 2], (char *)col); offset += sizeof(unsigned char) * 4; - } + } if (attribs.tottang) { float *tang = attribs.tang.array[a * 4 + 2]; copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset], tang); @@ -1333,7 +1346,14 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm, MFace *mf = cddm->mface; float (*nors)[3] = dm->getTessFaceDataArray(dm, CD_NORMAL); int a, matnr, new_matnr; - int orig, *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + int orig; + + /* double lookup */ + const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); + if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { + index_mf_to_mpoly = index_mp_to_orig = NULL; + } cdDM_update_normals_from_pbvh(dm); @@ -1362,7 +1382,7 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm, /* skipping faces */ if (setFace) { - orig = (index) ? index[a] : a; + orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a; if (orig != ORIGINDEX_NONE && !setFace(userData, orig)) continue; @@ -1525,11 +1545,6 @@ void CDDM_recalc_tessellation_ex(DerivedMesh *dm, const int do_face_nor_cpy) dm->numTessFaceData, dm->numLoopData, dm->numPolyData, do_face_nor_cpy); - if (!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX)) { - int *polyIndex = CustomData_get_layer(&dm->faceData, CD_POLYINDEX); - CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_REFERENCE, polyIndex, dm->numTessFaceData); - } - cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); /* Tessellation recreated faceData, and the active layer indices need to get re-propagated @@ -1641,7 +1656,6 @@ DerivedMesh *CDDM_new(int numVerts, int numEdges, int numTessFaces, int numLoops CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts); CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numTessFaces); - CustomData_add_layer(&dm->faceData, CD_POLYINDEX, CD_CALLOC, NULL, numTessFaces); CustomData_add_layer(&dm->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, numPolys); CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts); @@ -1665,7 +1679,6 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob)) DerivedMesh *dm = &cddm->dm; CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS); int alloctype; - int *polyindex = NULL; /* this does a referenced copy, with an exception for fluidsim */ @@ -1680,7 +1693,7 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob)) mesh->totvert); CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype, mesh->totedge); - CustomData_merge(&mesh->fdata, &dm->faceData, mask | CD_MASK_POLYINDEX, alloctype, + CustomData_merge(&mesh->fdata, &dm->faceData, mask | CD_MASK_ORIGINDEX, alloctype, mesh->totface); CustomData_merge(&mesh->ldata, &dm->loopData, mask, alloctype, mesh->totloop); @@ -1693,17 +1706,12 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob)) cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE); - /* commented since even when CD_POLYINDEX was first added this line fails + /* commented since even when CD_ORIGINDEX was first added this line fails * on the default cube, (after editmode toggle too) - campbell */ #if 0 - BLI_assert(CustomData_has_layer(&cddm->dm.faceData, CD_POLYINDEX)); + BLI_assert(CustomData_has_layer(&cddm->dm.faceData, CD_ORIGINDEX)); #endif - polyindex = CustomData_get_layer(&dm->faceData, CD_POLYINDEX); - if (!CustomData_has_layer(&cddm->dm.faceData, CD_ORIGINDEX)) { - CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_REFERENCE, polyindex, mesh->totface); - } - return dm; } @@ -1789,10 +1797,10 @@ DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase, int **orco } static void loops_to_customdata_corners(BMesh *bm, CustomData *facedata, - int cdindex, BMLoop *l3[3], + int cdindex, const BMLoop *l3[3], int numCol, int numTex) { - BMLoop *l; + const BMLoop *l; BMFace *f = l3[0]->f; MTFace *texface; MTexPoly *texpoly; @@ -1835,13 +1843,16 @@ static void loops_to_customdata_corners(BMesh *bm, CustomData *facedata, } } -DerivedMesh *CDDM_from_BMEditMesh(BMEditMesh *em, Mesh *UNUSED(me), int use_mdisps, int use_tessface) +/* used for both editbmesh and bmesh */ +static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, int use_mdisps, + /* EditBMesh vars for use_tessface */ + int use_tessface, + const int em_tottri, const BMLoop *(*em_looptris)[3] + ) { - BMesh *bm = em->bm; - DerivedMesh *dm = CDDM_new(bm->totvert, bm->totedge, - use_tessface ? em->tottri : 0, + use_tessface ? em_tottri : 0, bm->totloop, bm->totface); @@ -1887,7 +1898,7 @@ DerivedMesh *CDDM_from_BMEditMesh(BMEditMesh *em, Mesh *UNUSED(me), int use_mdis /* add tessellation mface layers */ if (use_tessface) { - CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, em->tottri); + CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, em_tottri); } index = dm->getVertDataArray(dm, CD_ORIGINDEX); @@ -1949,11 +1960,10 @@ DerivedMesh *CDDM_from_BMEditMesh(BMEditMesh *em, Mesh *UNUSED(me), int use_mdis BM_mesh_elem_index_ensure(bm, BM_FACE); - polyindex = dm->getTessFaceDataArray(dm, CD_POLYINDEX); index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); for (i = 0; i < dm->numTessFaceData; i++, index++, polyindex++) { MFace *mf = &mface[i]; - BMLoop **l = em->looptris[i]; + const BMLoop **l = em_looptris[i]; efa = l[0]->f; mf->v1 = BM_elem_index_get(l[0]->v); @@ -1963,8 +1973,8 @@ DerivedMesh *CDDM_from_BMEditMesh(BMEditMesh *em, Mesh *UNUSED(me), int use_mdis mf->mat_nr = efa->mat_nr; mf->flag = BM_face_flag_to_mflag(efa); - *index = add_orig ? BM_elem_index_get(efa) : *(int *)CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_ORIGINDEX); - *polyindex = BM_elem_index_get(efa); + /* map mfaces to polygons in the same cddm intentionally */ + *index = BM_elem_index_get(efa); loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numTex); test_index_face(mf, &dm->faceData, i, 3); @@ -2003,6 +2013,20 @@ DerivedMesh *CDDM_from_BMEditMesh(BMEditMesh *em, Mesh *UNUSED(me), int use_mdis return dm; } +struct DerivedMesh *CDDM_from_bmesh(struct BMesh *bm, int use_mdisps) +{ + return cddm_from_bmesh_ex(bm, use_mdisps, FALSE, + /* these vars are for editmesh only */ + 0, NULL); +} + +DerivedMesh *CDDM_from_editbmesh(BMEditMesh *em, int use_mdisps, int use_tessface) +{ + return cddm_from_bmesh_ex(em->bm, use_mdisps, + /* editmesh */ + use_tessface, em->tottri, (const BMLoop *(*)[3])em->looptris); +} + static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces) { CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm"); @@ -2017,6 +2041,7 @@ static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces) source->getVertDataArray(source, CD_ORIGINDEX); source->getEdgeDataArray(source, CD_ORIGINDEX); source->getTessFaceDataArray(source, CD_ORIGINDEX); + source->getPolyDataArray(source, CD_ORIGINDEX); /* this initializes dm, and copies all non mvert/medge/mface layers */ DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces, @@ -2071,6 +2096,7 @@ DerivedMesh *CDDM_from_template(DerivedMesh *source, source->getVertDataArray(source, CD_ORIGINDEX); source->getEdgeDataArray(source, CD_ORIGINDEX); source->getTessFaceDataArray(source, CD_ORIGINDEX); + source->getPolyDataArray(source, CD_ORIGINDEX); /* this does a copy of all non mvert/medge/mface layers */ DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces, numLoops, numPolys); @@ -2088,8 +2114,6 @@ DerivedMesh *CDDM_from_template(DerivedMesh *source, CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); if (!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX)) CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numTessFaces); - if (!CustomData_get_layer(&dm->faceData, CD_POLYINDEX)) - CustomData_add_layer(&dm->faceData, CD_POLYINDEX, CD_CALLOC, NULL, numTessFaces); cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); @@ -2154,8 +2178,8 @@ void CDDM_calc_normals_mapping_ex(DerivedMesh *dm, const short only_face_normals CDDM_recalc_tessellation_ex(dm, FALSE); } else { - /* A tessellation already exists, it should always have a CD_POLYINDEX */ - BLI_assert(CustomData_has_layer(&dm->faceData, CD_POLYINDEX)); + /* A tessellation already exists, it should always have a CD_ORIGINDEX */ + BLI_assert(CustomData_has_layer(&dm->faceData, CD_ORIGINDEX)); CustomData_free_layers(&dm->faceData, CD_NORMAL, dm->numTessFaceData); } @@ -2165,7 +2189,7 @@ void CDDM_calc_normals_mapping_ex(DerivedMesh *dm, const short only_face_normals /* calculate face normals */ BKE_mesh_calc_normals_mapping_ex(cddm->mvert, dm->numVertData, CDDM_get_loops(dm), CDDM_get_polys(dm), dm->numLoopData, dm->numPolyData, NULL, cddm->mface, dm->numTessFaceData, - CustomData_get_layer(&dm->faceData, CD_POLYINDEX), face_nors, + CustomData_get_layer(&dm->faceData, CD_ORIGINDEX), face_nors, only_face_normals); CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_ASSIGN, @@ -2339,7 +2363,7 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) BLI_array_append(oldp, i); } - /*create new cddm*/ + /*create new cddm*/ cddm2 = (CDDerivedMesh *) CDDM_from_template((DerivedMesh *)cddm, BLI_array_count(mvert), BLI_array_count(medge), 0, BLI_array_count(mloop), BLI_array_count(mpoly)); /*update edge indices and copy customdata*/ @@ -2364,7 +2388,7 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) CustomData_copy_data(&dm->loopData, &cddm2->dm.loopData, oldl[i], i, 1); } - /*copy vertex customdata*/ + /*copy vertex customdata*/ mv = mvert; for (i = 0; i < cddm2->dm.numVertData; i++, mv++) { CustomData_copy_data(&dm->vertData, &cddm2->dm.vertData, oldv[i], i, 1); @@ -2439,7 +2463,7 @@ void CDDM_calc_edges_tessface(DerivedMesh *dm) numEdges = BLI_edgehash_size(eh); /* write new edges into a temporary CustomData */ - memset(&edgeData, 0, sizeof(edgeData)); + CustomData_reset(&edgeData); CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); @@ -2504,7 +2528,7 @@ void CDDM_calc_edges(DerivedMesh *dm) numEdges = BLI_edgehash_size(eh); /* write new edges into a temporary CustomData */ - memset(&edgeData, 0, sizeof(edgeData)); + CustomData_reset(&edgeData); CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 4241756a109..f1d73c7777a 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -41,8 +41,6 @@ #include "BLI_utildefines.h" #include "BLI_linklist.h" -#include "BLF_translation.h" - #include "BKE_cdderivedmesh.h" #include "BKE_cloth.h" #include "BKE_effect.h" @@ -331,7 +329,7 @@ static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul cache= clmd->point_cache; /* initialize simulation data if it didn't exist already */ - if (clmd->clothObject == NULL) { + if (clmd->clothObject == NULL) { if (!cloth_from_object(ob, clmd, result, framenr, 1)) { BKE_ptcache_invalidate(cache); return 0; @@ -773,11 +771,13 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) else verts->goal= 0.0f; + /* Reset vertex flags */ + verts->flags &= ~CLOTH_VERT_FLAG_PINNED; + verts->flags &= ~CLOTH_VERT_FLAG_NOSELFCOLL; + dvert = dm->getVertData ( dm, i, CD_MDEFORMVERT ); if ( dvert ) { - for ( j = 0; j < dvert->totweight; j++ ) { - verts->flags &= ~CLOTH_VERT_FLAG_PINNED; if (( dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_mass-1)) && (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )) { verts->goal = dvert->dw [j].weight; @@ -789,7 +789,7 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) */ verts->goal = powf(verts->goal, 4.0f); - if ( verts->goal >=SOFTGOALSNAP ) + if ( verts->goal >= SOFTGOALSNAP ) verts->flags |= CLOTH_VERT_FLAG_PINNED; } @@ -804,7 +804,6 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) } } - verts->flags &= ~CLOTH_VERT_FLAG_NOSELFCOLL; if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF ) { if ( dvert->dw[j].def_nr == (clmd->coll_parms->vgroup_selfcol-1)) { if (dvert->dw [j].weight > 0.0f) { @@ -823,7 +822,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d int i = 0; MVert *mvert = NULL; ClothVertex *verts = NULL; - float (*shapekey_rest)[3]= NULL; + float (*shapekey_rest)[3] = NULL; float tnull[3] = {0, 0, 0}; Cloth *cloth = NULL; float maxdist = 0; @@ -844,7 +843,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d clmd->clothObject->edgehash = NULL; } else if (!clmd->clothObject) { - modifier_setError(&(clmd->modifier), "%s", TIP_("Out of memory on allocating clmd->clothObject.")); + modifier_setError(&(clmd->modifier), "Out of memory on allocating clmd->clothObject"); return 0; } @@ -906,7 +905,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d if ( !cloth_build_springs ( clmd, dm ) ) { cloth_free_modifier ( clmd ); - modifier_setError(&(clmd->modifier), "%s", TIP_("Can't build springs.")); + modifier_setError(&(clmd->modifier), "Cannot build springs"); printf("cloth_free_modifier cloth_build_springs\n"); return 0; } @@ -948,7 +947,7 @@ static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm ) clmd->clothObject->verts = MEM_callocN ( sizeof ( ClothVertex ) * clmd->clothObject->numverts, "clothVertex" ); if ( clmd->clothObject->verts == NULL ) { cloth_free_modifier ( clmd ); - modifier_setError(&(clmd->modifier), "%s", TIP_("Out of memory on allocating clmd->clothObject->verts.")); + modifier_setError(&(clmd->modifier), "Out of memory on allocating clmd->clothObject->verts"); printf("cloth_free_modifier clmd->clothObject->verts\n"); return; } @@ -958,7 +957,7 @@ static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm ) clmd->clothObject->mfaces = MEM_callocN ( sizeof ( MFace ) * clmd->clothObject->numfaces, "clothMFaces" ); if ( clmd->clothObject->mfaces == NULL ) { cloth_free_modifier ( clmd ); - modifier_setError(&(clmd->modifier), "%s", TIP_("Out of memory on allocating clmd->clothObject->mfaces.")); + modifier_setError(&(clmd->modifier), "Out of memory on allocating clmd->clothObject->mfaces"); printf("cloth_free_modifier clmd->clothObject->mfaces\n"); return; } @@ -1049,29 +1048,25 @@ static void cloth_update_springs( ClothModifierData *clmd ) spring->stiffness = 0.0f; - if(spring->type == CLOTH_SPRING_TYPE_STRUCTURAL) - { + if (spring->type == CLOTH_SPRING_TYPE_STRUCTURAL) { spring->stiffness = (cloth->verts[spring->kl].struct_stiff + cloth->verts[spring->ij].struct_stiff) / 2.0f; } - else if(spring->type == CLOTH_SPRING_TYPE_SHEAR) - { + else if (spring->type == CLOTH_SPRING_TYPE_SHEAR) { spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0f; } - else if(spring->type == CLOTH_SPRING_TYPE_BENDING) - { + else if (spring->type == CLOTH_SPRING_TYPE_BENDING) { spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f; } - else if(spring->type == CLOTH_SPRING_TYPE_GOAL) - { + else if (spring->type == CLOTH_SPRING_TYPE_GOAL) { /* Warning: Appending NEW goal springs does not work because implicit solver would need reset! */ /* Activate / Deactivate existing springs */ - if ((!(cloth->verts[spring->ij].flags & CLOTH_VERT_FLAG_PINNED)) && (cloth->verts[spring->ij].goal > ALMOST_ZERO)) + if ((!(cloth->verts[spring->ij].flags & CLOTH_VERT_FLAG_PINNED)) && + (cloth->verts[spring->ij].goal > ALMOST_ZERO)) { spring->flags &= ~CLOTH_SPRING_FLAG_DEACTIVATE; } - else - { + else { spring->flags |= CLOTH_SPRING_FLAG_DEACTIVATE; } } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index af9bb971d05..b488e683947 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -161,8 +161,6 @@ void bvhtree_update_from_mvert(BVHTree * bvhtree, MFace *faces, int numfaces, MV /*********************************** Collision modifier code end ***********************************/ -#define mySWAP(a, b) do { double tmp = b ; b = a ; a = tmp ; } while (0) - // w3 is not perfect static void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3 ) @@ -200,6 +198,9 @@ static void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3 w3[0] = 1.0f - w1[0] - w2[0]; } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdouble-promotion" + DO_INLINE void collision_interpolateOnTriangle ( float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3 ) { zero_v3(to); @@ -274,7 +275,7 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM /* Decrease in magnitude of relative tangential velocity due to coulomb friction * in original formula "magrelVel" should be the "change of relative velocity in normal direction" */ - magtangent = minf(clmd->coll_parms->friction * 0.01f * magrelVel, sqrtf(dot_v3v3(vrel_t_pre, vrel_t_pre))); + magtangent = min_ff(clmd->coll_parms->friction * 0.01f * magrelVel, sqrtf(dot_v3v3(vrel_t_pre, vrel_t_pre))); /* Apply friction impulse. */ if ( magtangent > ALMOST_ZERO ) { @@ -314,8 +315,8 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM /* stay on the safe side and clamp repulse */ if ( impulse > ALMOST_ZERO ) - repulse = MIN2 ( repulse, 5.0*impulse ); - repulse = MAX2 ( impulse, repulse ); + repulse = min_ff( repulse, 5.0*impulse ); + repulse = max_ff(impulse, repulse); impulse = repulse / ( 1.0f + w1*w1 + w2*w2 + w3*w3 ); /* original 2.0 / 0.25 */ VECADDMUL ( i1, collpair->normal, impulse ); @@ -333,12 +334,12 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM * We don't use dt!! */ float spf = (float)clmd->sim_parms->stepsPerFrame / clmd->sim_parms->timescale; - float d = clmd->coll_parms->epsilon*8.0f/9.0f + epsilon2*8.0f/9.0f - collpair->distance; + float d = clmd->coll_parms->epsilon*8.0f/9.0f + epsilon2*8.0f/9.0f - (float)collpair->distance; if ( d > ALMOST_ZERO) { /* stay on the safe side and clamp repulse */ float repulse = d*1.0f/spf; - float impulse = repulse / ( 3.0 * ( 1.0f + w1*w1 + w2*w2 + w3*w3 )); /* original 2.0 / 0.25 */ + float impulse = repulse / ( 3.0f * ( 1.0f + w1*w1 + w2*w2 + w3*w3 )); /* original 2.0 / 0.25 */ VECADDMUL ( i1, collpair->normal, impulse ); VECADDMUL ( i2, collpair->normal, impulse ); @@ -370,6 +371,8 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM return result; } +#pragma GCC diagnostic pop + //Determines collisions on overlap, collisions are written to collpair[i] and collision+number_collision_found is returned static CollPair* cloth_collision(ModifierData *md1, ModifierData *md2, BVHTreeOverlap *overlap, CollPair *collpair, float UNUSED(dt)) @@ -460,7 +463,8 @@ static CollPair* cloth_collision(ModifierData *md1, ModifierData *md2, distance = 2.0 * (double)( epsilon1 + epsilon2 + ALMOST_ZERO ); #endif - if (distance <= (epsilon1 + epsilon2 + ALMOST_ZERO)) { + // distance -1 means no collision result + if (distance != -1.0 && (distance <= (double)(epsilon1 + epsilon2 + ALMOST_ZERO))) { normalize_v3_v3(collpair->normal, collpair->vector); collpair->distance = distance; @@ -516,7 +520,7 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned if (((modifier_type == eModifierType_Collision) && ob->pd && ob->pd->deflect) || (modifier_type != eModifierType_Collision)) cmd= (CollisionModifierData *)modifiers_findByType(ob, modifier_type); - if (cmd) { + if (cmd) { /* extend array */ if (*numobj >= *maxobj) { *maxobj *= 2; @@ -535,7 +539,7 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned /* add objects */ for (go= group->gobject.first; go; go= go->next) add_collision_object(objs, numobj, maxobj, go->ob, self, level+1, modifier_type); - } + } } // return all collision objects in scene @@ -581,7 +585,7 @@ static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self, if (ob->pd && ob->pd->deflect) cmd =(CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision); - if (cmd && cmd->bvhtree) { + if (cmd && cmd->bvhtree) { if (*objs == NULL) *objs = MEM_callocN(sizeof(ListBase), "ColliderCache array"); @@ -739,8 +743,7 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData * clmd, float step, flo collision_move_object ( collmd, step + dt, step ); } - do - { + do { CollPair **collisions, **collisions_index; ret2 = 0; @@ -871,7 +874,7 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData * clmd, float step, flo VECADD ( verts[i].tx, verts[i].tx, temp ); } else { - mul_v3_fl(temp, correction * -0.5); + mul_v3_fl(temp, correction * -0.5f); VECADD ( verts[j].tx, verts[j].tx, temp ); sub_v3_v3v3(verts[i].tx, verts[i].tx, temp); diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 19c8c2cd632..75276adf518 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -65,10 +65,10 @@ void curvemapping_set_defaults(CurveMapping *cumap, int tot, float minx, float m cumap->flag = CUMA_DO_CLIP; if (tot == 4) cumap->cur = 3; /* rhms, hack for 'col' curve? */ - clipminx = minf(minx, maxx); - clipminy = minf(miny, maxy); - clipmaxx = maxf(minx, maxx); - clipmaxy = maxf(miny, maxy); + clipminx = min_ff(minx, maxx); + clipminy = min_ff(miny, maxy); + clipmaxx = max_ff(minx, maxx); + clipmaxy = max_ff(miny, maxy); BLI_rctf_init(&cumap->curr, clipminx, clipmaxx, clipminy, clipmaxy); cumap->clipr = cumap->curr; @@ -85,7 +85,7 @@ void curvemapping_set_defaults(CurveMapping *cumap, int tot, float minx, float m cumap->cm[a].curve[0].y = miny; cumap->cm[a].curve[1].x = maxx; cumap->cm[a].curve[1].y = maxy; - } + } cumap->changed_timestamp = 0; } @@ -160,7 +160,7 @@ void curvemapping_set_black_white_ex(const float black[3], const float white[3], int a; for (a = 0; a < 3; a++) { - const float delta = maxf(white[a] - black[a], 1e-5f); + const float delta = max_ff(white[a] - black[a], 1e-5f); r_bwmul[a] = 1.0f / delta; } } @@ -182,14 +182,14 @@ void curvemapping_set_black_white(CurveMapping *cumap, const float black[3], con /* ********** NOTE: requires curvemapping_changed() call after ******** */ /* remove specified point */ -void curvemap_remove_point(CurveMap *cuma, CurveMapPoint *point) +int curvemap_remove_point(CurveMap *cuma, CurveMapPoint *point) { CurveMapPoint *cmp; int a, b, removed = 0; /* must have 2 points minimum */ if (cuma->totpoint <= 2) - return; + return FALSE; cmp = MEM_mallocN((cuma->totpoint) * sizeof(CurveMapPoint), "curve points"); @@ -205,6 +205,7 @@ void curvemap_remove_point(CurveMap *cuma, CurveMapPoint *point) MEM_freeN(cuma->curve); cuma->curve = cmp; cuma->totpoint -= removed; + return (removed != 0); } /* removes with flag set */ @@ -262,7 +263,7 @@ CurveMapPoint *curvemap_insert(CurveMap *cuma, float x, float y) return newcmp; } -void curvemap_reset(CurveMap *cuma, rctf *clipr, int preset, int slope) +void curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope) { if (cuma->curve) MEM_freeN(cuma->curve); @@ -481,7 +482,7 @@ static float curvemap_calc_extend(const CurveMap *cuma, float x, const float fir } /* only creates a table for a single channel in CurveMapping */ -static void curvemap_make_table(CurveMap *cuma, rctf *clipr) +static void curvemap_make_table(CurveMap *cuma, const rctf *clipr) { CurveMapPoint *cmp = cuma->curve; BezTriple *bezt; @@ -498,8 +499,8 @@ static void curvemap_make_table(CurveMap *cuma, rctf *clipr) bezt = MEM_callocN(cuma->totpoint * sizeof(BezTriple), "beztarr"); for (a = 0; a < cuma->totpoint; a++) { - cuma->mintable = minf(cuma->mintable, cmp[a].x); - cuma->maxtable = maxf(cuma->maxtable, cmp[a].x); + cuma->mintable = min_ff(cuma->mintable, cmp[a].x); + cuma->maxtable = max_ff(cuma->maxtable, cmp[a].x); bezt[a].vec[1][0] = cmp[a].x; bezt[a].vec[1][1] = cmp[a].y; if (cmp[a].flag & CUMA_VECTOR) @@ -555,7 +556,7 @@ static void curvemap_make_table(CurveMap *cuma, rctf *clipr) sub_v3_v3v3(bezt[a].vec[2], bezt[a].vec[1], vec); } } - } + } /* make the bezier curve */ if (cuma->table) MEM_freeN(cuma->table); @@ -679,7 +680,7 @@ void curvemapping_changed(CurveMapping *cumap, int rem_doubles) CurveMap *cuma = cumap->cm + cumap->cur; CurveMapPoint *cmp = cuma->curve; rctf *clipr = &cumap->clipr; - float thresh = 0.01f * BLI_RCT_SIZE_X(clipr); + float thresh = 0.01f * BLI_rctf_size_x(clipr); float dx = 0.0f, dy = 0.0f; int a; @@ -690,13 +691,13 @@ void curvemapping_changed(CurveMapping *cumap, int rem_doubles) for (a = 0; a < cuma->totpoint; a++) { if (cmp[a].flag & CUMA_SELECT) { if (cmp[a].x < clipr->xmin) - dx = minf(dx, cmp[a].x - clipr->xmin); + dx = min_ff(dx, cmp[a].x - clipr->xmin); else if (cmp[a].x > clipr->xmax) - dx = maxf(dx, cmp[a].x - clipr->xmax); + dx = max_ff(dx, cmp[a].x - clipr->xmax); if (cmp[a].y < clipr->ymin) - dy = minf(dy, cmp[a].y - clipr->ymin); + dy = min_ff(dy, cmp[a].y - clipr->ymin); else if (cmp[a].y > clipr->ymax) - dy = maxf(dy, cmp[a].y - clipr->ymax); + dy = max_ff(dy, cmp[a].y - clipr->ymax); } } for (a = 0; a < cuma->totpoint; a++) { @@ -731,7 +732,7 @@ void curvemapping_changed(CurveMapping *cumap, int rem_doubles) } if (a != cuma->totpoint - 1) curvemap_remove(cuma, 2); - } + } curvemap_make_table(cuma, clipr); } @@ -835,64 +836,6 @@ void curvemapping_evaluate_premulRGB(const CurveMapping *cumap, unsigned char ve vecout_byte[2] = FTOCHAR(vecout[2]); } - -/* only used for image editor curves */ -void curvemapping_do_ibuf(CurveMapping *cumap, ImBuf *ibuf) -{ - ImBuf *tmpbuf; - int pixel; - float *pix_in; - float col[3]; - int stride = 4; - float *pix_out; - - if (ibuf == NULL) - return; - if (ibuf->rect_float == NULL) - IMB_float_from_rect(ibuf); - else if (ibuf->rect == NULL) - imb_addrectImBuf(ibuf); - - if (!ibuf->rect || !ibuf->rect_float) - return; - - /* work on a temp buffer, so can color manage afterwards. - * No worse off memory wise than comp nodes */ - tmpbuf = IMB_dupImBuf(ibuf); - - curvemapping_premultiply(cumap, 0); - - pix_in = ibuf->rect_float; - pix_out = tmpbuf->rect_float; - - if (ibuf->channels) - stride = ibuf->channels; - - for (pixel = ibuf->x * ibuf->y; pixel > 0; pixel--, pix_in += stride, pix_out += stride) { - if (stride < 3) { - col[0] = curvemap_evaluateF(cumap->cm, *pix_in); - - pix_out[1] = pix_out[2] = pix_out[3] = pix_out[0] = col[0]; - } - else { - curvemapping_evaluate_premulRGBF(cumap, col, pix_in); - pix_out[0] = col[0]; - pix_out[1] = col[1]; - pix_out[2] = col[2]; - if (stride > 3) - pix_out[3] = pix_in[3]; - else - pix_out[3] = 1.f; - } - } - - IMB_rect_from_float(tmpbuf); - SWAP(unsigned int *, tmpbuf->rect, ibuf->rect); - IMB_freeImBuf(tmpbuf); - - curvemapping_premultiply(cumap, 1); -} - int curvemapping_RGBA_does_something(const CurveMapping *cumap) { int a; @@ -1289,9 +1232,9 @@ void BKE_color_managed_display_settings_copy(ColorManagedDisplaySettings *new_se void BKE_color_managed_view_settings_init(ColorManagedViewSettings *settings) { /* OCIO_TODO: use default view transform here when OCIO is completely integrated - * and proper versioning stuff is added. - * for now use NONE to be compatible with all current files - */ + * and proper versioning stuff is added. + * for now use NONE to be compatible with all current files + */ BLI_strncpy(settings->view_transform, "Default", sizeof(settings->view_transform)); settings->gamma = 1.0f; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 6b9e0921c3b..e300b5e0f19 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -221,51 +221,6 @@ void constraints_clear_evalob(bConstraintOb *cob) /* -------------- Space-Conversion API -------------- */ -#if 0 /* XXX Old code, does the same as one in armature.c, will remove it later. */ -static void constraint_pchan_diff_mat(bPoseChannel *pchan, float diff_mat[4][4]) -{ - if (pchan->parent) { - float offs_bone[4][4]; - - /* construct offs_bone the same way it is done in armature.c */ - copy_m4_m3(offs_bone, pchan->bone->bone_mat); - copy_v3_v3(offs_bone[3], pchan->bone->head); - offs_bone[3][1] += pchan->bone->parent->length; - - if (pchan->bone->flag & BONE_HINGE) { - /* pose_mat = par_pose-space_location * chan_mat */ - float tmat[4][4]; - - /* the rotation of the parent restposition */ - copy_m4_m4(tmat, pchan->bone->parent->arm_mat); - - /* the location of actual parent transform */ - copy_v3_v3(tmat[3], offs_bone[3]); - zero_v3(offs_bone[3]); - mul_m4_v3(pchan->parent->pose_mat, tmat[3]); - - mult_m4_m4m4(diff_mat, tmat, offs_bone); - } - else { - /* pose_mat = par_pose_mat * bone_mat * chan_mat */ - if (pchan->bone->flag & BONE_NO_SCALE) { - float tmat[4][4]; - copy_m4_m4(tmat, pchan->parent->pose_mat); - normalize_m4(tmat); - mult_m4_m4m4(diff_mat, tmat, offs_bone); - } - else { - mult_m4_m4m4(diff_mat, pchan->parent->pose_mat, offs_bone); - } - } - } - else { - /* pose_mat = chan_mat * arm_mat */ - copy_m4_m4(diff_mat, pchan->bone->arm_mat); - } -} -#endif - /* This function is responsible for the correct transformations/conversions * of a matrix from one space to another for constraint evaluation. * For now, this is only implemented for Objects and PoseChannels. @@ -307,18 +262,6 @@ void constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[][4] else if (to == CONSTRAINT_SPACE_LOCAL) { if (pchan->bone) { BKE_armature_mat_pose_to_bone(pchan, mat, mat); -#if 0 /* XXX Old code, will remove it later. */ - constraint_pchan_diff_mat(pchan, diff_mat); - - invert_m4_m4(imat, diff_mat); - mult_m4_m4m4(mat, imat, mat); - - /* override with local location */ - if ((pchan->parent) && (pchan->bone->flag & BONE_NO_LOCAL_LOCATION)) { - BKE_armature_mat_pose_to_bone_ex(ob, pchan, pchan->pose_mat, tempmat); - copy_v3_v3(mat[3], tempmat[3]); - } -#endif } } /* pose to local with parent */ @@ -336,24 +279,19 @@ void constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[][4] if (pchan->bone) { /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */ BKE_armature_mat_bone_to_pose(pchan, mat, mat); -#if 0 - constraint_pchan_diff_mat(pchan, diff_mat); - - mult_m4_m4m4(mat, diff_mat, mat); -#endif } /* use pose-space as stepping stone for other spaces */ if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL)) { /* call self with slightly different values */ constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); - } + } } break; case CONSTRAINT_SPACE_PARLOCAL: /* -------------- FROM LOCAL WITH PARENT ---------- */ { /* local + parent to pose */ - if (pchan->bone) { + if (pchan->bone) { copy_m4_m4(diff_mat, pchan->bone->arm_mat); mult_m4_m4m4(mat, mat, diff_mat); } @@ -432,7 +370,7 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[ /* get DerivedMesh */ if (em) { /* target is in editmode, so get a special derived mesh */ - dm = CDDM_from_BMEditMesh(em, ob->data, FALSE, FALSE); + dm = CDDM_from_editbmesh(em, FALSE, FALSE); freeDM = 1; } else { @@ -604,15 +542,15 @@ static void constraint_target_to_mat4(Object *ob, const char *substring, float m float tempmat[4][4], loc[3]; /* interpolate along length of bone */ - interp_v3_v3v3(loc, pchan->pose_head, pchan->pose_tail, headtail); + interp_v3_v3v3(loc, pchan->pose_head, pchan->pose_tail, headtail); /* use interpolated distance for subtarget */ - copy_m4_m4(tempmat, pchan->pose_mat); + copy_m4_m4(tempmat, pchan->pose_mat); copy_v3_v3(tempmat[3], loc); mult_m4_m4m4(mat, ob->obmat, tempmat); } - } + } else copy_m4_m4(mat, ob->obmat); @@ -976,11 +914,11 @@ static void vectomat(const float vec[3], const float target_up[3], short axis, s else negate_v3(n); /* n specifies the transformation of the track axis */ - if (flags & TARGET_Z_UP) { + if (flags & TARGET_Z_UP) { /* target Z axis is the global up axis */ copy_v3_v3(u, target_up); } - else { + else { /* world Z axis is the global up axis */ u[0] = 0; u[1] = 0; @@ -1030,12 +968,11 @@ static void trackto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar if (VALID_CONS_TARGET(ct)) { float size[3], vec[3]; float totmat[3][3]; - float tmat[4][4]; /* Get size property, since ob->size is only the object's own relative size, not its global one */ mat4_to_size(size, cob->matrix); - /* Clear the object's rotation */ + /* Clear the object's rotation */ cob->matrix[0][0] = size[0]; cob->matrix[0][1] = 0; cob->matrix[0][2] = 0; @@ -1053,9 +990,8 @@ static void trackto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar vectomat(vec, ct->matrix[2], (short)data->reserved1, (short)data->reserved2, data->flags, totmat); - - copy_m4_m4(tmat, cob->matrix); - mul_m4_m3m4(cob->matrix, totmat, tmat); + + mul_m4_m3m4(cob->matrix, totmat, cob->matrix); } } @@ -1470,7 +1406,7 @@ static void sizelimit_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *U if (data->flag & LIMIT_XMIN) { if (size[0] < data->xmin) - size[0] = data->xmin; + size[0] = data->xmin; } if (data->flag & LIMIT_XMAX) { if (size[0] > data->xmax) @@ -1478,7 +1414,7 @@ static void sizelimit_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *U } if (data->flag & LIMIT_YMIN) { if (size[1] < data->ymin) - size[1] = data->ymin; + size[1] = data->ymin; } if (data->flag & LIMIT_YMAX) { if (size[1] > data->ymax) @@ -1486,7 +1422,7 @@ static void sizelimit_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *U } if (data->flag & LIMIT_ZMIN) { if (size[2] < data->zmin) - size[2] = data->zmin; + size[2] = data->zmin; } if (data->flag & LIMIT_ZMAX) { if (size[2] > data->zmax) @@ -2004,7 +1940,7 @@ static void pycon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTa /* this check is to make sure curve objects get updated on file load correctly.*/ if (cu->path == NULL || cu->path->data == NULL) /* only happens on reload file, but violates depsgraph still... fix! */ - BKE_displist_make_curveTypes(cob->scene, ct->tar, 0); + BKE_displist_make_curveTypes(cob->scene, ct->tar, 0); } /* firstly calculate the matrix the normal way, then let the py-function override @@ -2281,7 +2217,6 @@ static void locktrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t float totmat[3][3]; float tmpmat[3][3]; float invmat[3][3]; - float tmat[4][4]; float mdet; /* Vector object -> target */ @@ -2509,8 +2444,6 @@ static void locktrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t totmat[1][0] = tmpmat[1][0]; totmat[1][1] = tmpmat[1][1]; totmat[1][2] = tmpmat[1][2]; totmat[2][0] = tmpmat[2][0]; totmat[2][1] = tmpmat[2][1]; totmat[2][2] = tmpmat[2][2]; - copy_m4_m4(tmat, cob->matrix); - mdet = determinant_m3(totmat[0][0], totmat[0][1], totmat[0][2], totmat[1][0], totmat[1][1], totmat[1][2], totmat[2][0], totmat[2][1], totmat[2][2]); @@ -2519,7 +2452,7 @@ static void locktrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t } /* apply out transformaton to the object */ - mul_m4_m3m4(cob->matrix, totmat, tmat); + mul_m4_m3m4(cob->matrix, totmat, cob->matrix); } } @@ -2717,7 +2650,6 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t if (VALID_CONS_TARGET(ct)) { float size[3], scale[3], vec[3], xx[3], zz[3], orth[3]; float totmat[3][3]; - float tmat[4][4]; float dist; /* store scaling before destroying obmat */ @@ -2770,7 +2702,7 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t default: /* should not happen, but in case*/ return; } /* switch (data->volmode) */ - + /* Clear the object's rotation and scale */ cob->matrix[0][0] = size[0] * scale[0]; cob->matrix[0][1] = 0; @@ -2793,10 +2725,10 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t /* othogonal to "new Y" "old X! plane */ cross_v3_v3v3(orth, vec, xx); normalize_v3(orth); - + /* new Z*/ copy_v3_v3(totmat[2], orth); - + /* we decided to keep X plane*/ cross_v3_v3v3(xx, orth, vec); normalize_v3_v3(totmat[0], xx); @@ -2806,18 +2738,17 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t /* othogonal to "new Y" "old Z! plane */ cross_v3_v3v3(orth, vec, zz); normalize_v3(orth); - + /* new X */ negate_v3_v3(totmat[0], orth); - + /* we decided to keep Z */ cross_v3_v3v3(zz, orth, vec); normalize_v3_v3(totmat[2], zz); break; } /* switch (data->plane) */ - copy_m4_m4(tmat, cob->matrix); - mul_m4_m3m4(cob->matrix, totmat, tmat); + mul_m4_m3m4(cob->matrix, totmat, cob->matrix); } } @@ -2944,7 +2875,7 @@ static void minmax_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targ if (data->flag & MINMAX_STICKY) { if (data->flag & MINMAX_STUCK) { copy_v3_v3(obmat[3], data->cache); - } + } else { copy_v3_v3(data->cache, obmat[3]); data->flag |= MINMAX_STUCK; @@ -2954,11 +2885,11 @@ static void minmax_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targ /* get out of localspace */ mult_m4_m4m4(tmat, ct->matrix, obmat); copy_m4_m4(cob->matrix, tmat); - } - else { + } + else { copy_v3_v3(cob->matrix[3], obmat[3]); } - } + } else { data->flag &= ~MINMAX_STUCK; } @@ -3298,7 +3229,7 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t /* extract components of owner's matrix */ copy_v3_v3(loc, cob->matrix[3]); mat4_to_eulO(eul, cob->rotOrder, cob->matrix); - mat4_to_size(size, cob->matrix); + mat4_to_size(size, cob->matrix); /* determine where in range current transforms lie */ if (data->expo) { @@ -3622,7 +3553,7 @@ static void damptrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t cross_v3_v3v3(raxis, obvec, tarvec); rangle = dot_v3v3(obvec, tarvec); - rangle = acos(maxf(-1.0f, minf(1.0f, rangle))); + rangle = acos(max_ff(-1.0f, min_ff(1.0f, rangle))); /* construct rotation matrix from the axis-angle rotation found above * - this call takes care to make sure that the axis provided is a unit vector first @@ -4061,32 +3992,36 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase copy_v3_v3(cob->matrix[3], disp); } - if (data->depth_ob && data->depth_ob->derivedFinal) { + if (data->depth_ob) { Object *depth_ob = data->depth_ob; - BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh; - BVHTreeRayHit hit; - float ray_start[3], ray_end[3], ray_nor[3], imat[4][4]; - int result; + DerivedMesh *target = object_get_derived_final(depth_ob); + if (target) { + BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh; + BVHTreeRayHit hit; + float ray_start[3], ray_end[3], ray_nor[3], imat[4][4]; + int result; - invert_m4_m4(imat, depth_ob->obmat); + invert_m4_m4(imat, depth_ob->obmat); - mul_v3_m4v3(ray_start, imat, camob->obmat[3]); - mul_v3_m4v3(ray_end, imat, cob->matrix[3]); + mul_v3_m4v3(ray_start, imat, camob->obmat[3]); + mul_v3_m4v3(ray_end, imat, cob->matrix[3]); - sub_v3_v3v3(ray_nor, ray_end, ray_start); + sub_v3_v3v3(ray_nor, ray_end, ray_start); - bvhtree_from_mesh_faces(&treeData, depth_ob->derivedFinal, 0.0f, 4, 6); + bvhtree_from_mesh_faces(&treeData, target, 0.0f, 4, 6); - hit.dist = FLT_MAX; - hit.index = -1; + hit.dist = FLT_MAX; + hit.index = -1; - result = BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_nor, 0.0f, &hit, treeData.raycast_callback, &treeData); + result = BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_nor, 0.0f, &hit, treeData.raycast_callback, &treeData); - if (result != -1) { - mul_v3_m4v3(cob->matrix[3], depth_ob->obmat, hit.co); + if (result != -1) { + mul_v3_m4v3(cob->matrix[3], depth_ob->obmat, hit.co); + } + + free_bvhtree_from_mesh(&treeData); + target->release(target); } - - free_bvhtree_from_mesh(&treeData); } } } @@ -4666,7 +4601,7 @@ short proxylocked_constraints_owner(Object *ob, bPoseChannel *pchan) else { /* FIXME: constraints on object-level are not handled well yet */ return 1; - } + } } return 0; @@ -4706,7 +4641,7 @@ void get_constraint_target_matrix(struct Scene *scene, bConstraint *con, int n, unit_m4(cob->matrix); unit_m4(cob->startmat); } - } + } break; case CONSTRAINT_OBTYPE_BONE: /* this may occur in some cases */ { @@ -4842,7 +4777,7 @@ void solve_constraints(ListBase *conlist, bConstraintOb *cob, float ctime) * since some constraints may not convert the solution back to the input space before blending * but all are guaranteed to end up in good "worldspace" result */ - /* Note: all kind of stuff here before (caused trouble), much easier to just interpolate, or did I miss something? -jahka */ + /* Note: all kind of stuff here before (caused trouble), much easier to just interpolate, or did I miss something? -jahka (r.32105) */ if (enf < 1.0f) { float solution[4][4]; copy_m4_m4(solution, cob->matrix); diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index be81c70f261..719ae7357b4 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -234,9 +234,8 @@ struct bContextDataResult { static void *ctx_wm_python_context_get(const bContext *C, const char *member, void *fall_through) { #ifdef WITH_PYTHON - bContextDataResult result; - - if (C && CTX_py_dict_get(C)) { + if (UNLIKELY(C && CTX_py_dict_get(C))) { + bContextDataResult result; memset(&result, 0, sizeof(bContextDataResult)); BPY_context_member_get((bContext *)C, member, &result); if (result.ptr.data) diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index a2f88781cbb..67aaaceaa38 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -429,6 +429,33 @@ void BKE_curve_texspace_calc(Curve *cu) } } +int BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3]) +{ + Nurb *nu; + int tot = 0; + + for (nu = nurb->first; nu; nu = nu->next) { + int tot_nu; + if (nu->type == CU_BEZIER) { + tot_nu = nu->pntsu; + if (index - tot < tot_nu) { + copy_v3_v3(r_co, nu->bezt[index - tot].vec[1]); + return TRUE; + } + } + else { + tot_nu = nu->pntsu * nu->pntsv; + if (index - tot < tot_nu) { + copy_v3_v3(r_co, nu->bp[index - tot].vec); + return TRUE; + } + } + tot += tot_nu; + } + + return FALSE; +} + int BKE_nurbList_verts_count(ListBase *nurb) { Nurb *nu; @@ -793,8 +820,8 @@ static void basisNurb(float t, short order, short pnts, float *knots, float *bas /* this is for float inaccuracy */ if (t < knots[0]) t = knots[0]; - else - if (t > knots[opp2]) t = knots[opp2]; + else if (t > knots[opp2]) + t = knots[opp2]; /* this part is order '1' */ o2 = order + 1; @@ -1023,10 +1050,13 @@ void BKE_nurb_makeFaces(Nurb *nu, float *coord_array, int rowstride, int resolu, MEM_freeN(jend); } +/** + * \param coord_array Has to be 3 * 4 * pntsu * resolu in size and zero-ed + * \param tilt_array set when non-NULL + * \param radius_array set when non-NULL + */ void BKE_nurb_makeCurve(Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, float *weight_array, int resolu, int stride) -/* coord_array has to be 3*4*pntsu*resolu in size and zero-ed - * tilt_array and radius_array will be written to if valid */ { BPoint *bp; float u, ustart, uend, ustep, sumdiv; @@ -1449,7 +1479,7 @@ void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp, int forRende } } else if (cu->ext1 == 0.0f && cu->ext2 == 0.0f) { - ; + /* pass */ } else if (cu->ext2 == 0.0f) { dl = MEM_callocN(sizeof(DispList), "makebevelcurve2"); @@ -1918,7 +1948,7 @@ static void bevel_list_smooth(BevList *bl, int smooth_iter) if (bl->poly == -1) { /* check its not cyclic */ /* skip the first point */ - /* bevp0= bevp1; */ + /* bevp0 = bevp1; */ bevp1 = bevp2; bevp2++; nr--; @@ -1947,7 +1977,7 @@ static void bevel_list_smooth(BevList *bl, int smooth_iter) interp_qt_qtqt(bevp1->quat, bevp1->quat, q, 0.5); normalize_qt(bevp1->quat); - /* bevp0= bevp1; */ /* UNUSED */ + /* bevp0 = bevp1; */ /* UNUSED */ bevp1 = bevp2; bevp2++; } @@ -2082,7 +2112,7 @@ static void make_bevel_list_3D_tangent(BevList *bl) BevPoint *bevp2, *bevp1, *bevp0; /* standard for all make_bevel_list_3D_* funcs */ int nr; - float bevp0_tan[3], cross_tmp[3]; + float bevp0_tan[3]; bevel_list_calc_bisect(bl); if (bl->poly == -1) /* check its not cyclic */ @@ -2096,6 +2126,7 @@ static void make_bevel_list_3D_tangent(BevList *bl) nr = bl->nr; while (nr--) { + float cross_tmp[3]; cross_v3_v3v3(cross_tmp, bevp1->tan, bevp1->dir); cross_v3_v3v3(bevp1->tan, cross_tmp, bevp1->dir); normalize_v3(bevp1->tan); @@ -2123,7 +2154,7 @@ static void make_bevel_list_3D_tangent(BevList *bl) normalize_v3(cross_tmp); tri_to_quat(bevp1->quat, zero, cross_tmp, bevp1->tan); /* XXX - could be faster */ - /* bevp0= bevp1; */ /* UNUSED */ + /* bevp0 = bevp1; */ /* UNUSED */ bevp1 = bevp2; bevp2++; } @@ -2741,7 +2772,7 @@ static void calchandleNurb_intern(BezTriple *bezt, BezTriple *prev, BezTriple *n if (skip_align) { /* handles need to be updated during animation and applying stuff like hooks, - * but in such situatios it's quite difficult to distinguish in which order + * but in such situations it's quite difficult to distinguish in which order * align handles should be aligned so skip them for now */ return; } diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 342ee5bba41..93c776ae30e 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -65,11 +65,20 @@ /* number of layers to add when growing a CustomData object */ #define CUSTOMDATA_GROW 5 +/* ensure typemap size is ok */ +BLI_STATIC_ASSERT(sizeof(((CustomData *)NULL)->typemap) / + sizeof(((CustomData *)NULL)->typemap[0]) == CD_NUMTYPES, + "size mismatch"); + + /********************* Layer type information **********************/ typedef struct LayerTypeInfo { int size; /* the memory size of one element of this layer's data */ - const char *structname; /* name of the struct used, for file writing */ - int structnum; /* number of structs per element, for file writing */ + + /** name of the struct used, for file writing */ + const char *structname; + /** number of structs per element, for file writing */ + int structnum; /** * default layer name. @@ -271,28 +280,6 @@ static void layerInterp_mdeformvert(void **sources, const float *weights, BLI_linklist_free(dest_dw, linklist_free_simple); } - -static void layerInterp_msticky(void **sources, const float *weights, - const float *UNUSED(sub_weights), int count, void *dest) -{ - float co[2], w; - MSticky *mst; - int i; - - co[0] = co[1] = 0.0f; - for (i = 0; i < count; i++) { - w = weights ? weights[i] : 1.0f; - mst = (MSticky *)sources[i]; - - madd_v2_v2fl(co, mst->co, w); - } - - /* delay writing to the destination incase dest is in sources */ - mst = (MSticky *)dest; - copy_v2_v2(mst->co, co); -} - - static void layerCopy_tface(const void *source, void *dest, int count) { const MTFace *source_tf = (const MTFace *)source; @@ -1055,8 +1042,8 @@ static void layerInterp_mvert_skin(void **sources, const float *weights, static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 0: CD_MVERT */ {sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL}, - /* 1: CD_MSTICKY */ - {sizeof(MSticky), "MSticky", 1, NULL, NULL, NULL, layerInterp_msticky, NULL, + /* 1: CD_MSTICKY */ /* DEPRECATED */ + {sizeof(float) * 2, "", 1, NULL, NULL, NULL, NULL, NULL, NULL}, /* 2: CD_MDEFORMVERT */ {sizeof(MDeformVert), "MDeformVert", 1, NULL, layerCopy_mdeformvert, @@ -1077,8 +1064,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 8: CD_NORMAL */ /* 3 floats per normal vector */ {sizeof(float) * 3, "vec3f", 1, NULL, NULL, NULL, NULL, NULL, NULL}, - /* 9: CD_POLYINDEX */ - {sizeof(int), "MIntProperty", 1, NULL, NULL, NULL, NULL, NULL, NULL}, + /* 9: CD_POLYINDEX (deprecated) */ + {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, /* 10: CD_PROP_FLT */ {sizeof(MFloatProperty), "MFloatProperty", 1, "Float", layerCopy_propFloat, NULL, NULL, NULL}, /* 11: CD_PROP_INT */ @@ -1098,7 +1085,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { layerEqual_mloopuv, layerMultiply_mloopuv, layerInitMinMax_mloopuv, layerAdd_mloopuv, layerDoMinMax_mloopuv, layerCopyValue_mloopuv}, /* 17: CD_MLOOPCOL */ - {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, + {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol, layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol}, /* 18: CD_TANGENT */ @@ -1155,7 +1142,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(GridPaintMask), "GridPaintMask", 1, NULL, layerCopy_grid_paint_mask, layerFree_grid_paint_mask, NULL, NULL, NULL}, /* 36: CD_SKIN_NODE */ - {sizeof(MVertSkin), "MVertSkin", 1, "Skin", NULL, NULL, + {sizeof(MVertSkin), "MVertSkin", 1, NULL, NULL, NULL, layerInterp_mvert_skin, NULL, layerDefault_mvert_skin} }; @@ -1196,7 +1183,7 @@ const CustomDataMask CD_MASK_DERIVEDMESH = CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORIGSPACE_MLOOP | CD_MASK_ORCO | CD_MASK_TANGENT | CD_MASK_PREVIEW_MCOL | CD_MASK_NORMAL | CD_MASK_SHAPEKEY | CD_MASK_RECAST | - CD_MASK_ORIGINDEX | CD_MASK_POLYINDEX | CD_MASK_MVERT_SKIN; + CD_MASK_ORIGINDEX | CD_MASK_MVERT_SKIN; const CustomDataMask CD_MASK_BMESH = CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | @@ -1243,9 +1230,6 @@ void CustomData_update_typemap(CustomData *data) { int i, lasttype = -1; - /* since we cant do in a pre-processor do here as an assert */ - BLI_assert(sizeof(data->typemap) / sizeof(int) >= CD_NUMTYPES); - for (i = 0; i < CD_NUMTYPES; i++) { data->typemap[i] = -1; } @@ -1258,6 +1242,13 @@ void CustomData_update_typemap(CustomData *data) } } +static int customdata_typemap_is_valid(const CustomData *data) +{ + CustomData data_copy = *data; + CustomData_update_typemap(&data_copy); + return (memcmp(data->typemap, data_copy.typemap, sizeof(data->typemap)) == 0); +} + void CustomData_merge(const struct CustomData *source, struct CustomData *dest, CustomDataMask mask, int alloctype, int totelem) { @@ -1323,7 +1314,7 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, void CustomData_copy(const struct CustomData *source, struct CustomData *dest, CustomDataMask mask, int alloctype, int totelem) { - memset(dest, 0, sizeof(*dest)); + CustomData_reset(dest); if (source->external) dest->external = MEM_dupallocN(source->external); @@ -1354,6 +1345,12 @@ static void CustomData_external_free(CustomData *data) } } +void CustomData_reset(CustomData *data) +{ + memset(data, 0, sizeof(*data)); + fill_vn_i(data->typemap, CD_NUMTYPES, -1); +} + void CustomData_free(CustomData *data, int totelem) { int i; @@ -1365,8 +1362,7 @@ void CustomData_free(CustomData *data, int totelem) MEM_freeN(data->layers); CustomData_external_free(data); - - memset(data, 0, sizeof(*data)); + CustomData_reset(data); } static void customData_update_offsets(CustomData *data) @@ -1385,9 +1381,10 @@ static void customData_update_offsets(CustomData *data) CustomData_update_typemap(data); } -int CustomData_get_layer_index(const CustomData *data, int type) +/* to use when we're in the middle of modifying layers */ +static int CustomData_get_layer_index__notypemap(const CustomData *data, int type) { - int i; + int i; for (i = 0; i < data->totlayer; ++i) if (data->layers[i].type == type) @@ -1396,11 +1393,21 @@ int CustomData_get_layer_index(const CustomData *data, int type) return -1; } +/* -------------------------------------------------------------------- */ +/* index values to access the layers (offset from the layer start) */ + +int CustomData_get_layer_index(const CustomData *data, int type) +{ + BLI_assert(customdata_typemap_is_valid(data)); + return data->typemap[type]; +} + int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n) { int i = CustomData_get_layer_index(data, type); if (i != -1) { + BLI_assert(i + n < data->totlayer); i = (data->layers[i + n].type == type) ? (i + n) : (-1); } @@ -1420,91 +1427,62 @@ int CustomData_get_named_layer_index(const CustomData *data, int type, const cha int CustomData_get_active_layer_index(const CustomData *data, int type) { - if (!data->totlayer) - return -1; - - if (data->typemap[type] != -1) { - return data->typemap[type] + data->layers[data->typemap[type]].active; - } - - return -1; + const int layer_index = data->typemap[type]; + BLI_assert(customdata_typemap_is_valid(data)); + return (layer_index != -1) ? layer_index + data->layers[layer_index].active: -1; } int CustomData_get_render_layer_index(const CustomData *data, int type) { - int i; - - for (i = 0; i < data->totlayer; ++i) - if (data->layers[i].type == type) - return i + data->layers[i].active_rnd; - - return -1; + const int layer_index = data->typemap[type]; + BLI_assert(customdata_typemap_is_valid(data)); + return (layer_index != -1) ? layer_index + data->layers[layer_index].active_rnd : -1; } int CustomData_get_clone_layer_index(const CustomData *data, int type) { - int i; - - for (i = 0; i < data->totlayer; ++i) - if (data->layers[i].type == type) - return i + data->layers[i].active_clone; - - return -1; + const int layer_index = data->typemap[type]; + BLI_assert(customdata_typemap_is_valid(data)); + return (layer_index != -1) ? layer_index + data->layers[layer_index].active_clone : -1; } int CustomData_get_stencil_layer_index(const CustomData *data, int type) { - int i; - - for (i = 0; i < data->totlayer; ++i) - if (data->layers[i].type == type) - return i + data->layers[i].active_mask; - - return -1; + const int layer_index = data->typemap[type]; + BLI_assert(customdata_typemap_is_valid(data)); + return (layer_index != -1) ? layer_index + data->layers[layer_index].active_mask : -1; } + +/* -------------------------------------------------------------------- */ +/* index values per layer type */ + int CustomData_get_active_layer(const CustomData *data, int type) { - int i; - - for (i = 0; i < data->totlayer; ++i) - if (data->layers[i].type == type) - return data->layers[i].active; - - return -1; + const int layer_index = data->typemap[type]; + BLI_assert(customdata_typemap_is_valid(data)); + return (layer_index != -1) ? data->layers[layer_index].active : -1; } int CustomData_get_render_layer(const CustomData *data, int type) { - int i; - - for (i = 0; i < data->totlayer; ++i) - if (data->layers[i].type == type) - return data->layers[i].active_rnd; - - return -1; + const int layer_index = data->typemap[type]; + BLI_assert(customdata_typemap_is_valid(data)); + return (layer_index != -1) ? data->layers[layer_index].active_rnd : -1; } int CustomData_get_clone_layer(const CustomData *data, int type) { - int i; - - for (i = 0; i < data->totlayer; ++i) - if (data->layers[i].type == type) - return data->layers[i].active_clone; - - return -1; + const int layer_index = data->typemap[type]; + BLI_assert(customdata_typemap_is_valid(data)); + return (layer_index != -1) ? data->layers[layer_index].active_clone : -1; } int CustomData_get_stencil_layer(const CustomData *data, int type) { - int i; - - for (i = 0; i < data->totlayer; ++i) - if (data->layers[i].type == type) - return data->layers[i].active_mask; - - return -1; + const int layer_index = data->typemap[type]; + BLI_assert(customdata_typemap_is_valid(data)); + return (layer_index != -1) ? data->layers[layer_index].active_mask : -1; } void CustomData_set_layer_active(CustomData *data, int type, int n) @@ -1735,7 +1713,7 @@ int CustomData_free_layer(CustomData *data, int type, int totelem, int index) /* if layer was last of type in array, set new active layer */ if ((index >= data->totlayer) || (data->layers[index].type != type)) { - i = CustomData_get_layer_index(data, type); + i = CustomData_get_layer_index__notypemap(data, type); if (i >= 0) for (; i < data->totlayer && data->layers[i].type == type; i++) { @@ -1750,7 +1728,6 @@ int CustomData_free_layer(CustomData *data, int type, int totelem, int index) customData_resize(data, -CUSTOMDATA_GROW); customData_update_offsets(data); - CustomData_update_typemap(data); return 1; } @@ -2021,7 +1998,7 @@ void CustomData_interp(const CustomData *source, CustomData *dest, } /* if there are no more dest layers, we're done */ - if (dest_i >= dest->totlayer) return; + if (dest_i >= dest->totlayer) break; /* if we found a matching layer, copy the data */ if (dest->layers[dest_i].type == source->layers[src_i].type) { @@ -2380,7 +2357,9 @@ void CustomData_bmesh_free_block(CustomData *data, void **block) const LayerTypeInfo *typeInfo; int i; - if (!*block) return; + if (*block == NULL) + return; + for (i = 0; i < data->totlayer; ++i) { if (!(data->layers[i].flag & CD_FLAG_NOFREE)) { typeInfo = layerType_getInfo(data->layers[i].type); @@ -2416,7 +2395,7 @@ void CustomData_bmesh_copy_data(const CustomData *source, CustomData *dest, const LayerTypeInfo *typeInfo; int dest_i, src_i; - if (!*dest_block) { + if (*dest_block == NULL) { CustomData_bmesh_alloc_block(dest, dest_block); if (*dest_block) memset(*dest_block, 0, dest->totsize); @@ -2497,10 +2476,49 @@ int CustomData_layer_has_math(struct CustomData *data, int layer_n) if (typeInfo->equal && typeInfo->add && typeInfo->multiply && typeInfo->initminmax && typeInfo->dominmax) { - return 1; + return TRUE; } - return 0; + return FALSE; +} + +int CustomData_layer_has_interp(struct CustomData *data, int layer_n) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[layer_n].type); + + if (typeInfo->interp) { + return TRUE; + } + + return FALSE; +} + +int CustomData_has_math(struct CustomData *data) +{ + int i; + + /* interpolates a layer at a time */ + for (i = 0; i < data->totlayer; ++i) { + if (CustomData_layer_has_math(data, i)) { + return TRUE; + } + } + + return FALSE; +} + +int CustomData_has_interp(struct CustomData *data) +{ + int i; + + /* interpolates a layer at a time */ + for (i = 0; i < data->totlayer; ++i) { + if (CustomData_layer_has_interp(data, i)) { + return TRUE; + } + } + + return FALSE; } /* copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to @@ -2600,8 +2618,8 @@ void CustomData_bmesh_set_layer_n(CustomData *data, void *block, int n, void *so memcpy(dest, source, typeInfo->size); } -void CustomData_bmesh_interp(CustomData *data, void **src_blocks, float *weights, - float *sub_weights, int count, void *dest_block) +void CustomData_bmesh_interp(CustomData *data, void **src_blocks, const float *weights, + const float *sub_weights, int count, void *dest_block) { int i, j; void *source_buf[SOURCE_BUF_SIZE]; @@ -2636,7 +2654,7 @@ void CustomData_bmesh_set_default(CustomData *data, void **block) const LayerTypeInfo *typeInfo; int i; - if (!*block) + if (*block == NULL) CustomData_bmesh_alloc_block(data, block); for (i = 0; i < data->totlayer; ++i) { @@ -2656,7 +2674,7 @@ void CustomData_to_bmesh_block(const CustomData *source, CustomData *dest, const LayerTypeInfo *typeInfo; int dest_i, src_i, src_offset; - if (!*dest_block) + if (*dest_block == NULL) CustomData_bmesh_alloc_block(dest, dest_block); /* copies a layer at a time */ @@ -2888,7 +2906,9 @@ void CustomData_external_reload(CustomData *data, ID *UNUSED(id), CustomDataMask layer = &data->layers[i]; typeInfo = layerType_getInfo(layer->type); - if (!(mask & CD_TYPE_AS_MASK(layer->type))) ; + if (!(mask & CD_TYPE_AS_MASK(layer->type))) { + /* pass */ + } else if ((layer->flag & CD_FLAG_EXTERNAL) && (layer->flag & CD_FLAG_IN_MEMORY)) { if (typeInfo->free) typeInfo->free(layer->data, totelem, typeInfo->size); @@ -2914,10 +2934,15 @@ void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int layer = &data->layers[i]; typeInfo = layerType_getInfo(layer->type); - if (!(mask & CD_TYPE_AS_MASK(layer->type))) ; - else if (layer->flag & CD_FLAG_IN_MEMORY) ; - else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) + if (!(mask & CD_TYPE_AS_MASK(layer->type))) { + /* pass */ + } + else if (layer->flag & CD_FLAG_IN_MEMORY) { + /* pass */ + } + else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) { update = 1; + } } if (!update) @@ -2935,15 +2960,23 @@ void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int layer = &data->layers[i]; typeInfo = layerType_getInfo(layer->type); - if (!(mask & CD_TYPE_AS_MASK(layer->type))) ; - else if (layer->flag & CD_FLAG_IN_MEMORY) ; + if (!(mask & CD_TYPE_AS_MASK(layer->type))) { + /* pass */ + } + else if (layer->flag & CD_FLAG_IN_MEMORY) { + /* pass */ + } else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) { blay = cdf_layer_find(cdf, layer->type, layer->name); if (blay) { if (cdf_read_layer(cdf, blay)) { - if (typeInfo->read(cdf, layer->data, totelem)) ; - else break; + if (typeInfo->read(cdf, layer->data, totelem)) { + /* pass */ + } + else { + break; + } layer->flag |= CD_FLAG_IN_MEMORY; } else @@ -2974,9 +3007,12 @@ void CustomData_external_write(CustomData *data, ID *id, CustomDataMask mask, in layer = &data->layers[i]; typeInfo = layerType_getInfo(layer->type); - if (!(mask & CD_TYPE_AS_MASK(layer->type))) ; - else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) + if (!(mask & CD_TYPE_AS_MASK(layer->type))) { + /* pass */ + } + else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) { update = 1; + } } if (!update) @@ -3017,11 +3053,16 @@ void CustomData_external_write(CustomData *data, ID *id, CustomDataMask mask, in blay = cdf_layer_find(cdf, layer->type, layer->name); if (cdf_write_layer(cdf, blay)) { - if (typeInfo->write(cdf, layer->data, totelem)) ; - else break; + if (typeInfo->write(cdf, layer->data, totelem)) { + /* pass */ + } + else { + break; + } } - else + else { break; + } } } diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 4110d4565b2..7c13ca388e0 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -278,7 +278,7 @@ void defvert_normalize_lock_map(MDeformVert *dvert, const char *lock_flags, cons } } - lock_iweight = maxf(0.0f, 1.0f - lock_iweight); + lock_iweight = max_ff(0.0f, 1.0f - lock_iweight); if (tot_weight > 0.0f) { /* paranoid, should be 1.0 but in case of float error clamp anyway */ @@ -431,7 +431,7 @@ int *defgroup_flip_map_single(Object *ob, int *flip_map_len, int use_default, in if (strcmp(name, dg->name)) { flip_num = defgroup_name_index(ob, name); - if (flip_num >= 0) { + if (flip_num != -1) { map[defgroup] = flip_num; map[flip_num] = defgroup; } @@ -790,3 +790,23 @@ void defvert_clear(MDeformVert *dvert) dvert->totweight = 0; } + +/** + * \return The first group index shared by both deform verts + * or -1 if none are found. + */ +int defvert_find_shared(const MDeformVert *dvert_a, const MDeformVert *dvert_b) +{ + if (dvert_a->totweight && dvert_b->totweight) { + MDeformWeight *dw = dvert_a->dw; + unsigned int i; + + for (i = dvert_a->totweight; i != 0; i--, dw++) { + if (dw->weight > 0.0f && defvert_find_weight(dvert_b, dw->def_nr) > 0.0f) { + return dw->def_nr; + } + } + } + + return -1; +} diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index b8d5294eabc..950a0ca3d60 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -150,8 +150,8 @@ void queue_delete(DagNodeQueue *queue) MEM_freeN(temp); } - MEM_freeN(queue->freenodes); - MEM_freeN(queue); + MEM_freeN(queue->freenodes); + MEM_freeN(queue); } /* insert in queue, remove in front */ @@ -190,8 +190,8 @@ void push_queue(DagNodeQueue *queue, DagNode *node) } queue->freenodes->count = DAGQUEUEALLOC; - elem = queue->freenodes->first; - queue->freenodes->first = elem->next; + elem = queue->freenodes->first; + queue->freenodes->first = elem->next; } elem->next = NULL; elem->node = node; @@ -211,7 +211,7 @@ void push_stack(DagNodeQueue *queue, DagNode *node) DagNodeQueueElem *elem; int i; - elem = queue->freenodes->first; + elem = queue->freenodes->first; if (elem != NULL) { queue->freenodes->first = elem->next; if (queue->freenodes->last == elem) { @@ -235,8 +235,8 @@ void push_stack(DagNodeQueue *queue, DagNode *node) } queue->freenodes->count = DAGQUEUEALLOC; - elem = queue->freenodes->first; - queue->freenodes->first = elem->next; + elem = queue->freenodes->first; + queue->freenodes->first = elem->next; } elem->next = queue->first; elem->node = node; @@ -302,7 +302,7 @@ DagForest *dag_init(void) } /* isdata = object data... */ -// XXX this needs to be extended to be more flexible (so that not only objects are evaluated via depsgraph)... +/* XXX this needs to be extended to be more flexible (so that not only objects are evaluated via depsgraph)... */ static void dag_add_driver_relation(AnimData *adt, DagForest *dag, DagNode *node, int isdata) { FCurve *fcu; @@ -400,8 +400,7 @@ static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Mat } } -static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node) -{ +static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node, int skip_forcefield){ Base *base; DagNode *node2; @@ -411,7 +410,9 @@ static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Objec if ((base->lay & ob->lay) && base->object->pd) { Object *ob1 = base->object; if ((ob1->pd->deflect || ob1->pd->forcefield) && (ob1 != ob)) { - node2 = dag_get_node(dag, ob1); + if (skip_forcefield && ob1->pd->forcefield == skip_forcefield) + continue; + node2 = dag_get_node(dag, ob1); dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Field Collision"); } } @@ -443,7 +444,6 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O if (ob->type == OB_ARMATURE) { if (ob->pose) { bPoseChannel *pchan; - bConstraint *con; for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { for (con = pchan->constraints.first; con; con = con->next) { @@ -464,7 +464,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O if (ct->tar->type == OB_MESH) node3->customdata_mask |= CD_MASK_MDEFORMVERT; } - else if (ELEM3(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) + else if (ELEM3(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) dag_add_relation(dag, node3, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, cti->name); else dag_add_relation(dag, node3, node, DAG_RL_OB_DATA, cti->name); @@ -501,7 +501,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O if (ob->adt) dag_add_driver_relation(ob->adt, dag, node, (ob->type == OB_ARMATURE)); // XXX isdata arg here doesn't give an accurate picture of situation - key = ob_get_key(ob); + key = BKE_key_from_object(ob); if (key && key->adt) dag_add_driver_relation(key->adt, dag, node, 1); @@ -570,12 +570,14 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O /* softbody collision */ if ((ob->type == OB_MESH) || (ob->type == OB_CURVE) || (ob->type == OB_LATTICE)) { if (ob->particlesystem.first || - modifiers_isModifierEnabled(ob, eModifierType_Softbody) || - modifiers_isModifierEnabled(ob, eModifierType_Cloth) || - modifiers_isModifierEnabled(ob, eModifierType_Smoke) || - modifiers_isModifierEnabled(ob, eModifierType_DynamicPaint)) + modifiers_isModifierEnabled(ob, eModifierType_Softbody) || + modifiers_isModifierEnabled(ob, eModifierType_Cloth) || + modifiers_isModifierEnabled(ob, eModifierType_DynamicPaint)) { - dag_add_collision_field_relation(dag, scene, ob, node); /* TODO: use effectorweight->group */ + dag_add_collision_field_relation(dag, scene, ob, node, 0); /* TODO: use effectorweight->group */ + } + else if (modifiers_isModifierEnabled(ob, eModifierType_Smoke)) { + dag_add_collision_field_relation(dag, scene, ob, node, PFIELD_SMOKEFLOW); } } @@ -604,7 +606,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O if (mom != ob) { node2 = dag_get_node(dag, mom); - dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Metaball"); // mom depends on children! + dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Metaball"); /* mom depends on children! */ } } break; @@ -816,7 +818,7 @@ DagForest *build_dag(Main *bmain, Scene *sce, short mask) tag_main_idcode(bmain, ID_MA, FALSE); /* add base node for scene. scene is always the first node in DAG */ - scenenode = dag_add_node(dag, sce); + scenenode = dag_add_node(dag, sce); /* add current scene objects */ for (base = sce->base.first; base; base = base->next) { @@ -870,7 +872,7 @@ DagForest *build_dag(Main *bmain, Scene *sce, short mask) } /* cycle detection and solving */ - // solve_cycles(dag); + // solve_cycles(dag); return dag; } @@ -879,23 +881,23 @@ DagForest *build_dag(Main *bmain, Scene *sce, short mask) void free_forest(DagForest *Dag) { /* remove all nodes and deps */ DagNode *tempN; - DagAdjList *tempA; + DagAdjList *tempA; DagAdjList *itA; DagNode *itN = Dag->DagNode.first; while (itN) { - itA = itN->child; + itA = itN->child; while (itA) { tempA = itA; itA = itA->next; - MEM_freeN(tempA); + MEM_freeN(tempA); } - itA = itN->parent; + itA = itN->parent; while (itA) { tempA = itA; itA = itA->next; - MEM_freeN(tempA); + MEM_freeN(tempA); } tempN = itN; @@ -919,8 +921,8 @@ DagNode *dag_find_node(DagForest *forest, void *fob) return NULL; } -static int ugly_hack_sorry = 1; // prevent type check -static int dag_print_dependencies = 0; // debugging +static int ugly_hack_sorry = 1; /* prevent type check */ +static int dag_print_dependencies = 0; /* debugging */ /* no checking of existence, use dag_find_node first or dag_get_node */ DagNode *dag_add_node(DagForest *forest, void *fob) @@ -932,7 +934,7 @@ DagNode *dag_add_node(DagForest *forest, void *fob) node->ob = fob; node->color = DAG_WHITE; - if (ugly_hack_sorry) node->type = GS(((ID *) fob)->name); // sorry, done for pose sorting + if (ugly_hack_sorry) node->type = GS(((ID *) fob)->name); /* sorry, done for pose sorting */ if (forest->numNodes) { ((DagNode *) forest->DagNode.last)->next = node; forest->DagNode.last = node; @@ -1151,7 +1153,7 @@ static void dag_check_cycle(DagForest *dag) for (node = dag->DagNode.first; node; node = node->next) { while (node->parent) { itA = node->parent->next; - MEM_freeN(node->parent); + MEM_freeN(node->parent); node->parent = itA; } } @@ -1240,7 +1242,7 @@ void graph_bfs(void) itA = itA->next; } if (pos[node->BFS_dist] > node->k) { - pos[node->BFS_dist] += 1; + pos[node->BFS_dist] += 1; node->k = (float) pos[node->BFS_dist]; } else { @@ -1301,7 +1303,7 @@ int pre_and_post_source_BFS(DagForest *dag, short mask, DagNode *source, graph_a pre_func(node->ob, data); } - else { // back or cross edge + else { /* back or cross edge */ retval = 1; } itA = itA->next; @@ -1332,7 +1334,7 @@ DagNodeQueue *graph_dfs(void) /* int is_cycle = 0; */ /* UNUSED */ /* *fprintf(stderr, "starting DFS\n ------------\n"); - */ + */ nqueue = queue_create(DAGQUEUEALLOC); retqueue = queue_create(MainDag->numNodes); for (i = 0; i < 50; i++) @@ -1384,7 +1386,7 @@ DagNodeQueue *graph_dfs(void) break; } else { - if (itA->node->color == DAG_GRAY) { // back edge + if (itA->node->color == DAG_GRAY) { /* back edge */ fprintf(stderr, "dfs back edge :%15s %15s\n", ((ID *) node->ob)->name, ((ID *) itA->node->ob)->name); /* is_cycle = 1; */ /* UNUSED */ } @@ -1462,7 +1464,7 @@ int pre_and_post_source_DFS(DagForest *dag, short mask, DagNode *source, graph_a int retval = 0; /* * fprintf(stderr, "starting DFS\n ------------\n"); - */ + */ nqueue = queue_create(DAGQUEUEALLOC); /* Init @@ -1516,7 +1518,7 @@ int pre_and_post_source_DFS(DagForest *dag, short mask, DagNode *source, graph_a // } } itA = itA->next; - } + } if (!skip) { node = pop_queue(nqueue); @@ -1535,7 +1537,7 @@ int pre_and_post_source_DFS(DagForest *dag, short mask, DagNode *source, graph_a } -// used to get the obs owning a datablock +/* used to get the obs owning a datablock */ DagNodeQueue *get_obparents(struct DagForest *dag, void *ob) { DagNode *node, *node1; @@ -1546,7 +1548,7 @@ DagNodeQueue *get_obparents(struct DagForest *dag, void *ob) if (node == NULL) { return NULL; } - else if (node->ancestor_count == 1) { // simple case + else if (node->ancestor_count == 1) { /* simple case */ nqueue = queue_create(1); push_queue(nqueue, node); } @@ -1555,7 +1557,7 @@ DagNodeQueue *get_obparents(struct DagForest *dag, void *ob) node1 = dag->DagNode.first; do { - if (node1->DFS_fntm > node->DFS_fntm) { // a parent is finished after child. must check adj list + if (node1->DFS_fntm > node->DFS_fntm) { /* a parent is finished after child. must check adj list */ itA = node->child; while (itA != NULL) { if ((itA->node == node) && (itA->type == DAG_RL_DATA)) { @@ -1583,7 +1585,7 @@ DagNodeQueue *get_first_ancestors(struct DagForest *dag, void *ob) node1 = dag->DagNode.first; do { - if (node1->DFS_fntm > node->DFS_fntm) { + if (node1->DFS_fntm > node->DFS_fntm) { itA = node->child; while (itA != NULL) { if (itA->node == node) { @@ -1595,10 +1597,10 @@ DagNodeQueue *get_first_ancestors(struct DagForest *dag, void *ob) node1 = node1->next; } while (node1); - return nqueue; + return nqueue; } -// standard DFS list +/* standard DFS list */ DagNodeQueue *get_all_childs(struct DagForest *dag, void *ob) { DagNode *node; @@ -1609,7 +1611,7 @@ DagNodeQueue *get_all_childs(struct DagForest *dag, void *ob) int skip = 0; nqueue = queue_create(DAGQUEUEALLOC); - retqueue = queue_create(dag->numNodes); // was MainDag... why? (ton) + retqueue = queue_create(dag->numNodes); /* was MainDag... why? (ton) */ node = dag->DagNode.first; while (node) { @@ -1619,8 +1621,8 @@ DagNodeQueue *get_all_childs(struct DagForest *dag, void *ob) time = 1; - node = dag_find_node(dag, ob); // could be done in loop above (ton) - if (node) { // can be null for newly added objects + node = dag_find_node(dag, ob); /* could be done in loop above (ton) */ + if (node) { /* can be null for newly added objects */ node->color = DAG_GRAY; time++; @@ -1641,9 +1643,9 @@ DagNodeQueue *get_all_childs(struct DagForest *dag, void *ob) push_stack(nqueue, itA->node); skip = 1; break; - } + } itA = itA->next; - } + } if (!skip) { node = pop_queue(nqueue); @@ -1671,7 +1673,7 @@ short are_obs_related(struct DagForest *dag, void *ob1, void *ob2) while (itA != NULL) { if (itA->node->ob == ob2) { return itA->node->type; - } + } itA = itA->next; } return DAG_NO_RELATION; @@ -1699,7 +1701,7 @@ void graph_print_queue(DagNodeQueue *nqueue) queueElem = nqueue->first; while (queueElem) { fprintf(stderr, "** %s %i %i-%i ", ((ID *) queueElem->node->ob)->name, queueElem->node->color, queueElem->node->DFS_dvtm, queueElem->node->DFS_fntm); - queueElem = queueElem->next; + queueElem = queueElem->next; } fprintf(stderr, "\n"); } @@ -1719,7 +1721,7 @@ void graph_print_queue_dist(DagNodeQueue *nqueue) fputc('|', stderr); fputc('\n', stderr); count = 0; - queueElem = queueElem->next; + queueElem = queueElem->next; } fprintf(stderr, "\n"); } @@ -1857,14 +1859,14 @@ void DAG_scene_sort(Main *bmain, Scene *sce) push_stack(nqueue, itA->node); skip = 1; break; - } + } itA = itA->next; - } + } if (!skip) { if (node) { node = pop_queue(nqueue); - if (node->ob == sce) // we are done + if (node->ob == sce) /* we are done */ break; node->color = DAG_BLACK; @@ -1876,7 +1878,7 @@ void DAG_scene_sort(Main *bmain, Scene *sce) BLI_remlink(&sce->base, base); BLI_addhead(&tempbase, base); } - } + } } } @@ -2021,7 +2023,7 @@ static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime) for (itA = node->child; itA; itA = itA->next) { if (itA->node->type == ID_OB) { if (itA->node->lasttime != curtime) { - itA->lay = flush_layer_node(sce, itA->node, curtime); // lay is only set once for each relation + itA->lay = flush_layer_node(sce, itA->node, curtime); /* lay is only set once for each relation */ } else itA->lay = itA->node->lay; @@ -2069,12 +2071,12 @@ static void dag_scene_flush_layers(Scene *sce, int lay) Base *base; int lasttime; - firstnode = sce->theDag->DagNode.first; // always scene node + firstnode = sce->theDag->DagNode.first; /* always scene node */ for (itA = firstnode->child; itA; itA = itA->next) itA->lay = 0; - sce->theDag->time++; // so we know which nodes were accessed + sce->theDag->time++; /* so we know which nodes were accessed */ lasttime = sce->theDag->time; /* update layer flags in nodes */ @@ -2146,13 +2148,13 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const sho DAG_scene_sort(bmain, sce); } - firstnode = sce->theDag->DagNode.first; // always scene node + firstnode = sce->theDag->DagNode.first; /* always scene node */ /* first we flush the layer flags */ dag_scene_flush_layers(sce, lay); /* then we use the relationships + layer info to flush update events */ - sce->theDag->time++; // so we know which nodes were accessed + sce->theDag->time++; /* so we know which nodes were accessed */ lasttime = sce->theDag->time; for (itA = firstnode->child; itA; itA = itA->next) if (itA->node->lasttime != lasttime && itA->node->type == ID_OB) @@ -2160,7 +2162,7 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const sho /* if update is not due to time change, do pointcache clears */ if (!time) { - sce->theDag->time++; // so we know which nodes were accessed + sce->theDag->time++; /* so we know which nodes were accessed */ lasttime = sce->theDag->time; for (itA = firstnode->child; itA; itA = itA->next) { if (itA->node->lasttime != lasttime && itA->node->type == ID_OB) { @@ -2378,7 +2380,7 @@ static void dag_object_time_update_flags(Object *ob) } } } - } + } if (ob->recalc & OB_RECALC_OB) lib_id_recalc_tag(G.main, &ob->id); @@ -2650,7 +2652,7 @@ static void dag_id_flush_update(Scene *sce, ID *id) /* set flags based on ShapeKey */ if (idtype == ID_KE) { for (obt = bmain->object.first; obt; obt = obt->id.next) { - Key *key = ob_get_key(obt); + Key *key = BKE_key_from_object(obt); if (!(ob && obt == ob) && ((ID *)key == id)) { obt->flag |= (OB_RECALC_OB | OB_RECALC_DATA); lib_id_recalc_tag(bmain, &obt->id); @@ -2928,9 +2930,9 @@ void DAG_pose_sort(Object *ob) int skip = 0; dag = dag_init(); - ugly_hack_sorry = 0; // no ID structs + ugly_hack_sorry = 0; /* no ID structs */ - rootnode = dag_add_node(dag, NULL); // node->ob becomes NULL + rootnode = dag_add_node(dag, NULL); /* node->ob becomes NULL */ /* we add the hierarchy and the constraints */ for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { @@ -2975,7 +2977,7 @@ void DAG_pose_sort(Object *ob) dag_add_relation(dag, node2, node3, 0, "IK Constraint"); segcount++; - if (segcount == data->rootbone || segcount > 255) break; // 255 is weak + if (segcount == data->rootbone || segcount > 255) break; /* 255 is weak */ parchan = parchan->parent; } } @@ -3018,21 +3020,21 @@ void DAG_pose_sort(Object *ob) push_stack(nqueue, itA->node); skip = 1; break; - } + } itA = itA->next; - } + } if (!skip) { if (node) { node = pop_queue(nqueue); - if (node->ob == NULL) // we are done + if (node->ob == NULL) /* we are done */ break; node->color = DAG_BLACK; /* put node in new list */ BLI_remlink(&pose->chanbase, node->ob); BLI_addhead(&tempbase, node->ob); - } + } } } diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 64959fd3aa1..e13d05d0a2f 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -299,7 +299,9 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase, i else resolu = nu->resolu; - if (!BKE_nurb_check_valid_u(nu)) ; + if (!BKE_nurb_check_valid_u(nu)) { + /* pass */ + } else if (nu->type == CU_BEZIER) { /* count */ len = 0; @@ -1384,8 +1386,8 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba ListBase top_capbase = {NULL, NULL}; for (dlb = dlbev.first; dlb; dlb = dlb->next) { - const float bevfac1 = minf(cu->bevfac1, cu->bevfac2); - const float bevfac2 = maxf(cu->bevfac1, cu->bevfac2); + const float bevfac1 = min_ff(cu->bevfac1, cu->bevfac2); + const float bevfac2 = max_ff(cu->bevfac1, cu->bevfac2); float firstblend = 0.0f, lastblend = 0.0f; int i, start, steps; diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 1cb29b90133..89d728c0419 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -32,6 +32,8 @@ #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" @@ -87,6 +89,9 @@ #include #endif +/* could enable at some point but for now there are far too many conversions */ +#pragma GCC diagnostic ignored "-Wdouble-promotion" + /* precalculated gaussian factors for 5x super sampling */ static float gaussianFactors[5] = {0.996849f, 0.596145f, @@ -120,8 +125,16 @@ static int neighY[8] = {0, 1, 1, 1, 0, -1, -1, -1}; /* drying limits */ #define MIN_WETNESS 0.001f #define MAX_WETNESS 5.0f -/* dissolve macro */ -#define VALUE_DISSOLVE(VALUE, TIME, SCALE, LOG) (VALUE) = (LOG) ? (VALUE) *(pow(MIN_WETNESS, 1.0f / (1.2f * ((float)(TIME)) / (SCALE)))) : (VALUE) -1.0f / (TIME)*(SCALE) + + +/* dissolve inline function */ +BLI_INLINE void value_dissolve(float *r_value, const float time, const float scale, const int is_log) +{ + *r_value = (is_log) ? + (*r_value) * (powf(MIN_WETNESS, 1.0f / (1.2f * time / scale))) : + (*r_value) - 1.0f / time * scale; +} + /***************************** Internal Structs ***************************/ @@ -569,7 +582,7 @@ static void scene_setSubframe(Scene *scene, float subframe) static int surface_getBrushFlags(DynamicPaintSurface *surface, Scene *scene) { Base *base = NULL; - GroupObject *go = NULL; + GroupObject *go = NULL; Object *brushObj = NULL; ModifierData *md = NULL; @@ -757,7 +770,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface) volume = td[0] * td[1] * td[2]; /* determine final grid size by trying to fit average 10.000 points per grid cell */ - dim_factor = (float)pow(volume / ((double)sData->total_points / 10000.0), 1.0 / (double)axis); + dim_factor = (float)pow((double)volume / ((double)sData->total_points / 10000.0), 1.0 / (double)axis); /* define final grid size using dim_factor, use min 3 for active axises */ for (i = 0; i < 3; i++) { @@ -848,7 +861,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface) grid->s_num = MEM_reallocN(grid->s_num, sizeof(int) * grid_cells); if (error || !grid->s_num) { - setError(surface->canvas, "Not enough free memory."); + setError(surface->canvas, N_("Not enough free memory")); freeGrid(sData); } } @@ -1235,7 +1248,7 @@ static void dynamicPaint_allocateSurfaceType(DynamicPaintSurface *surface) break; } - if (sData->type_data == NULL) setError(surface->canvas, "Not enough free memory!"); + if (sData->type_data == NULL) setError(surface->canvas, N_("Not enough free memory")); } static int surface_usesAdjDistance(DynamicPaintSurface *surface) @@ -1292,7 +1305,7 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int for if (!ad->n_index || !ad->n_num || !ad->n_target || !temp_data) { dynamicPaint_freeAdjData(sData); if (temp_data) MEM_freeN(temp_data); - setError(surface->canvas, "Not enough free memory."); + setError(surface->canvas, N_("Not enough free memory")); return; } @@ -1762,10 +1775,10 @@ static DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, } /* apply weights into a vertex group, if doesnt exists add a new layer */ - if (defgrp_index >= 0 && !dvert && (surface->output_name[0] != '\0')) + if (defgrp_index != -1 && !dvert && (surface->output_name[0] != '\0')) dvert = CustomData_add_layer_named(&result->vertData, CD_MDEFORMVERT, CD_CALLOC, NULL, sData->total_points, surface->output_name); - if (defgrp_index >= 0 && dvert) { + if (defgrp_index != -1 && dvert) { int i; for (i = 0; i < sData->total_points; i++) { MDeformVert *dv = &dvert[i]; @@ -1944,7 +1957,7 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh { /* Note: Current method only uses polygon edges to detect neighboring pixels. * -> It doesn't always lead to the optimum pixel but is accurate enough - * and faster/simplier than including possible face tip point links) + * and faster/simpler than including possible face tip point links) */ int x, y; @@ -2165,8 +2178,10 @@ int dynamicPaint_createUVSurface(DynamicPaintSurface *surface) int *final_index; int aa_samples; - if (!dm) return setError(canvas, "Canvas mesh not updated."); - if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ) return setError(canvas, "Can't bake non-\"image sequence\" formats."); + if (!dm) + return setError(canvas, N_("Canvas mesh not updated")); + if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ) + return setError(canvas, N_("Cannot bake non-'image sequence' formats")); numOfFaces = dm->getNumTessFaces(dm); mface = dm->getTessFaceArray(dm); @@ -2176,8 +2191,10 @@ int dynamicPaint_createUVSurface(DynamicPaintSurface *surface) tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname); /* Check for validity */ - if (!tface) return setError(canvas, "No UV data on canvas."); - if (surface->image_resolution < 16 || surface->image_resolution > 8192) return setError(canvas, "Invalid resolution."); + if (!tface) + return setError(canvas, N_("No UV data on canvas")); + if (surface->image_resolution < 16 || surface->image_resolution > 8192) + return setError(canvas, N_("Invalid resolution")); w = h = surface->image_resolution; @@ -2189,7 +2206,8 @@ int dynamicPaint_createUVSurface(DynamicPaintSurface *surface) /* Init data struct */ if (surface->data) dynamicPaint_freeSurfaceData(surface); sData = surface->data = MEM_callocN(sizeof(PaintSurfaceData), "PaintSurfaceData"); - if (!surface->data) return setError(canvas, "Not enough free memory."); + if (!surface->data) + return setError(canvas, N_("Not enough free memory")); aa_samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1; tempPoints = (struct PaintUVPoint *) MEM_callocN(w * h * sizeof(struct PaintUVPoint), "Temp PaintUVPoint"); @@ -2547,7 +2565,8 @@ int dynamicPaint_createUVSurface(DynamicPaintSurface *surface) } } } - if (error == 1) setError(canvas, "Not enough free memory."); + if (error == 1) + setError(canvas, N_("Not enough free memory")); if (faceBB) MEM_freeN(faceBB); if (tempPoints) MEM_freeN(tempPoints); @@ -2598,7 +2617,10 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, char *filenam int format = (surface->image_fileformat & MOD_DPAINT_IMGFORMAT_OPENEXR) ? R_IMF_IMTYPE_OPENEXR : R_IMF_IMTYPE_PNG; char output_file[FILE_MAX]; - if (!sData->type_data) { setError(surface->canvas, "Image save failed: Invalid surface."); return; } + if (!sData->type_data) { + setError(surface->canvas, N_("Image save failed: invalid surface")); + return; + } /* if selected format is openexr, but current build doesnt support one */ #ifndef WITH_OPENEXR if (format == R_IMF_IMTYPE_OPENEXR) format = R_IMF_IMTYPE_PNG; @@ -2612,7 +2634,10 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, char *filenam /* Init image buffer */ ibuf = IMB_allocImBuf(surface->image_resolution, surface->image_resolution, 32, IB_rectfloat); - if (ibuf == NULL) { setError(surface->canvas, "Image save failed: Not enough free memory."); return; } + if (ibuf == NULL) { + setError(surface->canvas, N_("Image save failed: not enough free memory")); + return; + } #pragma omp parallel for schedule(static) for (index = 0; index < sData->total_points; index++) { @@ -2852,15 +2877,15 @@ static void mesh_faces_nearest_point_dp(void *userdata, int index, const float c /***************************** Brush Painting Calls ******************************/ -/* - * Mix color values to canvas point. +/** + * Mix color values to canvas point. * - * surface : canvas surface - * index : surface point index - * paintFlags : paint object flags - * paintColor,Alpha,Wetness : to be mixed paint values - * timescale : value used to adjust time dependand - * operations when using substeps + * \param surface canvas surface + * \param index surface point index + * \param paintFlags paint object flags + * \param paintColor,Alpha,Wetness to be mixed paint values + * \param timescale value used to adjust time dependent + * operations when using substeps */ static void dynamicPaint_mixPaintColors(DynamicPaintSurface *surface, int index, int paintFlags, const float paintColor[3], float *paintAlpha, float *paintWetness, float *timescale) @@ -4161,7 +4186,7 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s pdEndEffectors(&effectors); } - /* Get number of required steps using averate point distance + /* Get number of required steps using average point distance * so that just a few ultra close pixels wont up substeps to max */ /* adjust number of required substep by fastest active effect */ @@ -4224,7 +4249,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force /* Only continue if surrounding point has higher wetness */ if (ePoint->wetness < pPoint->wetness || ePoint->wetness < MIN_WETNESS) continue; - w_factor = 1.0f / numOfNeighs *MIN2(ePoint->wetness, 1.0f) * speed_scale; + w_factor = 1.0f / numOfNeighs * MIN2(ePoint->wetness, 1.0f) * speed_scale; CLAMP(w_factor, 0.0f, 1.0f); /* mix new wetness and color */ @@ -4473,7 +4498,7 @@ static void dynamicPaint_surfacePreStep(DynamicPaintSurface *surface, float time int i; float dry_ratio, f_color[4]; float p_wetness = pPoint->wetness; - VALUE_DISSOLVE(pPoint->wetness, surface->dry_speed, timescale, (surface->flags & MOD_DPAINT_DRY_LOG)); + value_dissolve(&pPoint->wetness, surface->dry_speed, timescale, (surface->flags & MOD_DPAINT_DRY_LOG)); if (pPoint->wetness < 0.0f) pPoint->wetness = 0.0f; if (pPoint->wetness < surface->color_dry_threshold) { @@ -4518,10 +4543,10 @@ static void dynamicPaint_surfacePreStep(DynamicPaintSurface *surface, float time } if (surface->flags & MOD_DPAINT_DISSOLVE) { - VALUE_DISSOLVE(pPoint->alpha, surface->diss_speed, timescale, (surface->flags & MOD_DPAINT_DISSOLVE_LOG)); + value_dissolve(&pPoint->alpha, surface->diss_speed, timescale, (surface->flags & MOD_DPAINT_DISSOLVE_LOG)); if (pPoint->alpha < 0.0f) pPoint->alpha = 0.0f; - VALUE_DISSOLVE(pPoint->e_alpha, surface->diss_speed, timescale, (surface->flags & MOD_DPAINT_DISSOLVE_LOG)); + value_dissolve(&pPoint->e_alpha, surface->diss_speed, timescale, (surface->flags & MOD_DPAINT_DISSOLVE_LOG)); if (pPoint->e_alpha < 0.0f) pPoint->e_alpha = 0.0f; } } @@ -4533,7 +4558,7 @@ static void dynamicPaint_surfacePreStep(DynamicPaintSurface *surface, float time float *point = &((float *)sData->type_data)[index]; /* log or linear */ - VALUE_DISSOLVE(*point, surface->diss_speed, timescale, (surface->flags & MOD_DPAINT_DISSOLVE_LOG)); + value_dissolve(point, surface->diss_speed, timescale, (surface->flags & MOD_DPAINT_DISSOLVE_LOG)); if (*point < 0.0f) *point = 0.0f; } } @@ -4649,7 +4674,7 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *sc if (bData->realCoord) MEM_freeN(bData->realCoord); if (canvas_verts) MEM_freeN(canvas_verts); - return setError(surface->canvas, "Not enough free memory."); + return setError(surface->canvas, N_("Not enough free memory")); } new_bdata = 1; @@ -4811,7 +4836,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su */ { Base *base = NULL; - GroupObject *go = NULL; + GroupObject *go = NULL; Object *brushObj = NULL; ModifierData *md = NULL; @@ -4878,7 +4903,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su /* Apply brush on the surface depending on it's collision type */ /* Particle brush: */ if (brush->collision == MOD_DPAINT_COL_PSYS) { - if (brush->psys && brush->psys->part && brush->psys->part->type == PART_EMITTER && + if (brush->psys && brush->psys->part && ELEM(brush->psys->part->type, PART_EMITTER, PART_FLUID) && psys_check_enabled(brushObj, brush->psys)) { @@ -4934,7 +4959,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su /* Allocate memory for surface previous points to read unchanged values from */ prevPoint = MEM_mallocN(sData->total_points * sizeof(struct PaintPoint), "PaintSurfaceDataCopy"); if (!prevPoint) - return setError(canvas, "Not enough free memory."); + return setError(canvas, N_("Not enough free memory")); /* Prepare effects and get number of required steps */ steps = dynamicPaint_prepareEffectStep(surface, scene, ob, &force, timescale); diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index befec1907da..8d430eb58b5 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -152,7 +152,7 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *tm) BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { /* don't consider two-edged faces */ - if (efa->len < 3) { + if (UNLIKELY(efa->len < 3)) { /* do nothing */ } diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 4f4bafd00b4..1f6db19ac27 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -54,6 +54,7 @@ #include "BLI_math.h" #include "BLI_blenlib.h" +#include "BLI_noise.h" #include "BLI_jitter.h" #include "BLI_rand.h" #include "BLI_utildefines.h" @@ -84,6 +85,7 @@ #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_scene.h" +#include "BKE_smoke.h" #include "RE_render_ext.h" @@ -137,6 +139,9 @@ PartDeflect *object_add_collision_fields(int type) case PFIELD_TEXTURE: pd->f_size = 1.0f; break; + case PFIELD_SMOKEFLOW: + pd->f_flow = 1.0f; + break; } pd->flag = PFIELD_DO_LOCATION|PFIELD_DO_ROTATION; @@ -161,7 +166,7 @@ void free_partdeflect(PartDeflect *pd) pd->tex->id.us--; if (pd->rng) - rng_free(pd->rng); + BLI_rng_free(pd->rng); MEM_freeN(pd); } @@ -170,9 +175,9 @@ static void precalculate_effector(EffectorCache *eff) { unsigned int cfra = (unsigned int)(eff->scene->r.cfra >= 0 ? eff->scene->r.cfra : -eff->scene->r.cfra); if (!eff->pd->rng) - eff->pd->rng = rng_new(eff->pd->seed + cfra); + eff->pd->rng = BLI_rng_new(eff->pd->seed + cfra); else - rng_srandom(eff->pd->rng, eff->pd->seed + cfra); + BLI_rng_srandom(eff->pd->rng, eff->pd->seed + cfra); if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type==OB_CURVE) { Curve *cu= eff->ob->data; @@ -200,7 +205,7 @@ static void precalculate_effector(EffectorCache *eff) float old_vel[3]; BKE_object_where_is_calc_time(eff->scene, eff->ob, cfra - 1.0f); - copy_v3_v3(old_vel, eff->ob->obmat[3]); + copy_v3_v3(old_vel, eff->ob->obmat[3]); BKE_object_where_is_calc_time(eff->scene, eff->ob, cfra); sub_v3_v3v3(eff->velocity, eff->ob->obmat[3], old_vel); } @@ -450,8 +455,8 @@ static float eff_calc_visibility(ListBase *colliders, EffectorCache *eff, Effect // noise function for wind e.g. static float wind_func(struct RNG *rng, float strength) { - int random = (rng_getInt(rng)+1) % 128; // max 2357 - float force = rng_getFloat(rng) + 1.0f; + int random = (BLI_rng_get_int(rng)+1) % 128; // max 2357 + float force = BLI_rng_get_float(rng) + 1.0f; float ret; float sign = 0; @@ -713,8 +718,8 @@ static void get_effector_tot(EffectorCache *eff, EffectorData *efd, EffectedPoin if (eff->pd->forcefield == PFIELD_CHARGE) { /* Only the charge of the effected particle is used for - * interaction, not fall-offs. If the fall-offs aren't the - * same this will be unphysical, but for animation this + * interaction, not fall-offs. If the fall-offs aren't the + * same this will be unphysical, but for animation this * could be the wanted behavior. If you want physical * correctness the fall-off should be spherical 2.0 anyways. */ @@ -823,7 +828,7 @@ static void do_physical_effector(EffectorCache *eff, EffectorData *efd, Effected { PartDeflect *pd = eff->pd; RNG *rng = pd->rng; - float force[3]={0, 0, 0}; + float force[3] = {0, 0, 0}; float temp[3]; float fac; float strength = pd->f_strength; @@ -922,12 +927,27 @@ static void do_physical_effector(EffectorCache *eff, EffectorData *efd, Effected mul_v3_fl(force, -efd->falloff * fac * (strength * fac + damp)); break; + case PFIELD_SMOKEFLOW: + zero_v3(force); + if (pd->f_source) { + float density; + if ((density = smoke_get_velocity_at(pd->f_source, point->loc, force)) >= 0.0f) { + float influence = strength * efd->falloff; + if (pd->flag & PFIELD_SMOKE_DENSITY) + influence *= density; + mul_v3_fl(force, influence); + /* apply flow */ + madd_v3_v3fl(total_force, point->vel, -pd->f_flow * influence); + } + } + break; + } if (pd->flag & PFIELD_DO_LOCATION) { madd_v3_v3fl(total_force, force, 1.0f/point->vel_to_sec); - if (ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG)==0 && pd->f_flow != 0.0f) { + if (ELEM3(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG, PFIELD_SMOKEFLOW)==0 && pd->f_flow != 0.0f) { madd_v3_v3fl(total_force, point->vel, -pd->f_flow * efd->falloff); } } @@ -993,12 +1013,14 @@ void pdDoEffectors(ListBase *effectors, ListBase *colliders, EffectorWeights *we if (efd.falloff > 0.0f) efd.falloff *= eff_calc_visibility(colliders, eff, &efd, point); - if (efd.falloff <= 0.0f) - ; /* don't do anything */ - else if (eff->pd->forcefield == PFIELD_TEXTURE) + if (efd.falloff <= 0.0f) { + /* don't do anything */ + } + else if (eff->pd->forcefield == PFIELD_TEXTURE) { do_texture_effector(eff, &efd, point, force); + } else { - float temp1[3]={0, 0, 0}, temp2[3]; + float temp1[3] = {0, 0, 0}, temp2[3]; copy_v3_v3(temp1, force); do_physical_effector(eff, &efd, point, force); diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 2dbc63e6944..ec61311d89e 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -504,14 +504,14 @@ short calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, flo xmaxv = MAX3(xmaxv, bezt_last->vec[1][0], bezt_last->vec[2][0]); } else { - xminv = minf(xminv, bezt_first->vec[1][0]); - xmaxv = maxf(xmaxv, bezt_last->vec[1][0]); + xminv = min_ff(xminv, bezt_first->vec[1][0]); + xmaxv = max_ff(xmaxv, bezt_last->vec[1][0]); } } } /* only loop over keyframes to find extents for values if needed */ - if (ymin || ymax) { + if (ymin || ymax) { BezTriple *bezt; for (bezt = fcu->bezt, i = 0; i < fcu->totvert; bezt++, i++) { @@ -521,8 +521,8 @@ short calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, flo ymaxv = MAX4(ymaxv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]); } else { - yminv = minf(yminv, bezt->vec[1][1]); - ymaxv = maxf(ymaxv, bezt->vec[1][1]); + yminv = min_ff(yminv, bezt->vec[1][1]); + ymaxv = max_ff(ymaxv, bezt->vec[1][1]); } foundvert = TRUE; @@ -533,8 +533,8 @@ short calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, flo else if (fcu->fpt) { /* frame range can be directly calculated from end verts */ if (xmin || xmax) { - xminv = minf(xminv, fcu->fpt[0].vec[0]); - xmaxv = maxf(xmaxv, fcu->fpt[fcu->totvert - 1].vec[0]); + xminv = min_ff(xminv, fcu->fpt[0].vec[0]); + xmaxv = max_ff(xmaxv, fcu->fpt[fcu->totvert - 1].vec[0]); } /* only loop over keyframes to find extents for values if needed */ @@ -591,15 +591,15 @@ void calc_fcurve_range(FCurve *fcu, float *start, float *end, if (bezt_first) { BLI_assert(bezt_last != NULL); - min = minf(min, bezt_first->vec[1][0]); - max = maxf(max, bezt_last->vec[1][0]); + min = min_ff(min, bezt_first->vec[1][0]); + max = max_ff(max, bezt_last->vec[1][0]); foundvert = TRUE; } } else if (fcu->fpt) { - min = minf(min, fcu->fpt[0].vec[0]); - max = maxf(max, fcu->fpt[fcu->totvert - 1].vec[0]); + min = min_ff(min, fcu->fpt[0].vec[0]); + max = max_ff(max, fcu->fpt[fcu->totvert - 1].vec[0]); foundvert = TRUE; } @@ -1039,7 +1039,7 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar) if (RNA_path_resolve_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) { if (RNA_property_array_check(prop)) { /* array */ - if (index < RNA_property_array_length(&ptr, prop)) { + if (index < RNA_property_array_length(&ptr, prop)) { switch (RNA_property_type(prop)) { case PROP_BOOLEAN: value = (float)RNA_property_boolean_get_index(&ptr, prop, index); @@ -1143,7 +1143,7 @@ static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar) /* stop here... */ return 0.0f; - } + } /* use the final posed locations */ mat4_to_quat(q1, pchan->pose_mat); @@ -1549,7 +1549,7 @@ ChannelDriver *fcurve_copy_driver(ChannelDriver *driver) for (dvar = ndriver->variables.first; dvar; dvar = dvar->next) { /* need to go over all targets so that we don't leave any dangling paths */ DRIVER_TARGETS_LOOPER(dvar) - { + { /* make a copy of target's rna path if available */ if (dtar->rna_path) dtar->rna_path = MEM_dupallocN(dtar->rna_path); @@ -1832,7 +1832,7 @@ static int findzero(float x, float q0, float q1, float q2, float q3, float *o) return 1; } - return 0; + return 0; } } @@ -1916,7 +1916,7 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime cvalue = prevbezt->vec[1][1]; } } - } + } else { /* Use the first handle (earlier) of first BezTriple to calculate the * gradient and thus the value of the curve at evaltime @@ -1968,7 +1968,7 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime cvalue = lastbezt->vec[1][1]; } } - } + } else { /* Use the gradient of the second handle (later) of last BezTriple to calculate the * gradient and thus the value of the curve at evaltime diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c index 9be599ac66c..efc9869c5ca 100644 --- a/source/blender/blenkernel/intern/fluidsim.c +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -41,7 +41,7 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_fluidsim.h" -#include "DNA_object_force.h" // for pointcache +#include "DNA_object_force.h" // for pointcache #include "DNA_object_types.h" #include "DNA_particle_types.h" #include "DNA_scene_types.h" // N_T @@ -66,14 +66,14 @@ //------------------------------------------------------------------------------- void initElbeemMesh(struct Scene *scene, struct Object *ob, - int *numVertices, float **vertices, - int *numTriangles, int **triangles, - int useGlobalCoords, int modifierIndex) + int *numVertices, float **vertices, + int *numTriangles, int **triangles, + int useGlobalCoords, int modifierIndex) { DerivedMesh *dm = NULL; MVert *mvert; MFace *mface; - int countTris=0, i, totvert, totface; + int countTris = 0, i, totvert, totface; float *verts; int *tris; @@ -87,35 +87,35 @@ void initElbeemMesh(struct Scene *scene, struct Object *ob, totface = dm->getNumTessFaces(dm); *numVertices = totvert; - verts = MEM_callocN(totvert*3*sizeof(float), "elbeemmesh_vertices"); - for (i=0; iobmat, &verts[i*3]); } + verts = MEM_callocN(totvert * 3 * sizeof(float), "elbeemmesh_vertices"); + for (i = 0; i < totvert; i++) { + copy_v3_v3(&verts[i * 3], mvert[i].co); + if (useGlobalCoords) { mul_m4_v3(ob->obmat, &verts[i * 3]); } } *vertices = verts; - for (i=0; icoefficients); - } + } /* set the new data */ data->coefficients = nc; @@ -185,7 +182,7 @@ static void fcm_generator_verify(FModifier *fcm) /* free the old data */ MEM_freeN(data->coefficients); - } + } /* set the new data */ data->coefficients = nc; @@ -279,7 +276,7 @@ static FModifierTypeInfo FMI_GENERATOR = { /* Built-In Function Generator F-Curve Modifier --------------------------- */ /* This uses the general equation for equations: - * y = amplitude * fn(phase_multiplier*x + phase_offset) + y_offset + * y = amplitude * fn(phase_multiplier * x + phase_offset) + y_offset * * where amplitude, phase_multiplier/offset, y_offset are user-defined coefficients, * x is the evaluation 'time', and 'y' is the resultant value @@ -319,7 +316,7 @@ static void fcm_fn_generator_evaluate(FCurve *UNUSED(fcu), FModifier *fcm, float * WARNING: must perform special argument validation hereto guard against crashes */ switch (data->type) { - /* simple ones */ + /* simple ones */ case FCM_GENERATOR_FN_SIN: /* sine wave */ fn = sin; break; @@ -1025,7 +1022,7 @@ FModifier *add_fmodifier(ListBase *modifiers, int type) fcm->data = MEM_callocN(fmi->size, fmi->structName); /* init custom settings if necessary */ - if (fmi->new_data) + if (fmi->new_data) fmi->new_data(fcm->data); /* return modifier for further editing */ @@ -1102,7 +1099,7 @@ int remove_fmodifier(ListBase *modifiers, FModifier *fcm) if (modifiers) { BLI_freelinkN(modifiers, fcm); return 1; - } + } else { /* XXX this case can probably be removed some day, as it shouldn't happen... */ printf("remove_fmodifier() - no modifier stack given\n"); diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 8b35974ea62..d4634748c71 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -177,7 +177,7 @@ static VFontData *vfont_get_data(Main *bmain, VFont *vfont) } } - return vfont->data; + return vfont->data; } VFont *BKE_vfont_load(Main *bmain, const char *name) @@ -306,23 +306,23 @@ static void build_underline(Curve *cu, float x1, float y1, float x2, float y2, i nu2->bp = bp; nu2->bp[0].vec[0] = x1; - nu2->bp[0].vec[1] = y1; + nu2->bp[0].vec[1] = y1; nu2->bp[0].vec[2] = 0; nu2->bp[0].vec[3] = 1.0f; nu2->bp[1].vec[0] = x2; nu2->bp[1].vec[1] = y1; - nu2->bp[1].vec[2] = 0; + nu2->bp[1].vec[2] = 0; nu2->bp[1].vec[3] = 1.0f; nu2->bp[2].vec[0] = x2; - nu2->bp[2].vec[1] = y2; + nu2->bp[2].vec[1] = y2; nu2->bp[2].vec[2] = 0; nu2->bp[2].vec[3] = 1.0f; nu2->bp[3].vec[0] = x1; nu2->bp[3].vec[1] = y2; - nu2->bp[3].vec[2] = 0; + nu2->bp[3].vec[2] = 0; nu2->bp[3].vec[3] = 1.0f; - BLI_addtail(&(cu->nurb), nu2); + BLI_addtail(&(cu->nurb), nu2); } @@ -545,7 +545,7 @@ struct CharTrans *BKE_vfont_to_curve(Main *bmain, Scene *scene, Object *ob, int /* The VFont Data can not be found */ if (!vfd) { if (mem) - MEM_freeN(mem); + MEM_freeN(mem); return NULL; } @@ -671,7 +671,7 @@ makebreak: yof -= linedist; - maxlen = maxf(maxlen, (xof - tb->x / cu->fsize)); + maxlen = max_ff(maxlen, (xof - tb->x / cu->fsize)); linedata[lnr] = xof - tb->x / cu->fsize; linedata2[lnr] = cnr; linedata3[lnr] = tb->w / cu->fsize; @@ -731,7 +731,7 @@ makebreak: if (ascii == 32) { wsfac = cu->wordspace; wsnr++; - } + } else { wsfac = 1.0f; } @@ -754,7 +754,7 @@ makebreak: for (i = 0; i <= slen; i++, tmp++, ct++) { ascii = *tmp; if (ascii == '\n' || ascii == '\r' || ct->dobreak) cu->lines++; - } + } /* linedata is now: width of line * linedata2 is now: number of characters @@ -792,7 +792,7 @@ makebreak: // } ct++; } - } + } else if ((cu->spacemode == CU_JUSTIFY) && (cu->tb[0].w != 0.0f)) { float curofs = 0.0f; for (i = 0; i <= slen; i++) { @@ -928,8 +928,12 @@ makebreak: * 3: curs down */ ct = chartransdata + cu->pos; - if ((mode == FO_CURSUP || mode == FO_PAGEUP) && ct->linenr == 0) ; - else if ((mode == FO_CURSDOWN || mode == FO_PAGEDOWN) && ct->linenr == lnr) ; + if ((mode == FO_CURSUP || mode == FO_PAGEUP) && ct->linenr == 0) { + /* pass */ + } + else if ((mode == FO_CURSDOWN || mode == FO_PAGEDOWN) && ct->linenr == lnr) { + /* pass */ + } else { switch (mode) { case FO_CURSUP: lnr = ct->linenr - 1; break; diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 2ec5801746c..a7d0152a799 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -87,6 +87,7 @@ void free_gpencil_frames(bGPDlayer *gpl) free_gpencil_strokes(gpf); BLI_freelinkN(&gpl->frames, gpf); } + gpl->actframe = NULL; } /* Free all of the gp-layers for a viewport (list should be &gpd->layers or so) */ @@ -163,7 +164,7 @@ bGPDframe *gpencil_frame_addnew(bGPDlayer *gpl, int cframe) } /* add a new gp-layer and make it the active layer */ -bGPDlayer *gpencil_layer_addnew(bGPdata *gpd) +bGPDlayer *gpencil_layer_addnew(bGPdata *gpd, const char *name, int setactive) { bGPDlayer *gpl; @@ -182,11 +183,12 @@ bGPDlayer *gpencil_layer_addnew(bGPdata *gpd) gpl->thickness = 3; /* auto-name */ - strcpy(gpl->info, "GP_Layer"); + strcpy(gpl->info, name); BLI_uniquename(&gpd->layers, gpl, "GP_Layer", '.', offsetof(bGPDlayer, info), sizeof(gpl->info)); /* make this one the active one */ - gpencil_layer_setactive(gpd, gpl); + if (setactive) + gpencil_layer_setactive(gpd, gpl); /* return layer */ return gpl; @@ -509,15 +511,13 @@ void gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active) } /* delete the active gp-layer */ -void gpencil_layer_delactive(bGPdata *gpd) +void gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl) { - bGPDlayer *gpl = gpencil_layer_getactive(gpd); - /* error checking */ if (ELEM(NULL, gpd, gpl)) return; - /* free layer */ + /* free layer */ free_gpencil_frames(gpl); BLI_freelinkN(&gpd->layers, gpl); } diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index 500df1b7b75..20d874e7243 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -98,7 +98,7 @@ void BKE_group_unlink(Group *group) base->object->flag &= ~OB_FROMGROUP; base->flag &= ~OB_FROMGROUP; } - } + } for (srl = sce->r.layers.first; srl; srl = srl->next) { if (srl->light_override == group) @@ -110,16 +110,6 @@ void BKE_group_unlink(Group *group) if (ob->dup_group == group) { ob->dup_group = NULL; -#if 0 /* XXX OLD ANIMSYS, NLASTRIPS ARE NO LONGER USED */ - { - bActionStrip *strip; - /* duplicator strips use a group object, we remove it */ - for (strip = ob->nlastrips.first; strip; strip = strip->next) { - if (strip->object) - strip->object = NULL; - } - } -#endif } for (psys = ob->particlesystem.first; psys; psys = psys->next) { @@ -383,57 +373,3 @@ void group_handle_recalc_and_update(Scene *scene, Object *UNUSED(parent), Group } } } - -#if 0 -Object *group_get_member_with_action(Group *group, bAction *act) -{ - GroupObject *go; - - if (group == NULL || act == NULL) return NULL; - - for (go = group->gobject.first; go; go = go->next) { - if (go->ob) { - if (go->ob->action == act) - return go->ob; - if (go->ob->nlastrips.first) { - bActionStrip *strip; - - for (strip = go->ob->nlastrips.first; strip; strip = strip->next) { - if (strip->act == act) - return go->ob; - } - } - } - } - return NULL; -} - -/* if group has NLA, we try to map the used objects in NLA to group members */ -/* this assuming that object has received a new group link */ -void group_relink_nla_objects(Object *ob) -{ - Group *group; - GroupObject *go; - bActionStrip *strip; - - if (ob == NULL || ob->dup_group == NULL) return; - group = ob->dup_group; - - for (strip = ob->nlastrips.first; strip; strip = strip->next) { - if (strip->object) { - for (go = group->gobject.first; go; go = go->next) { - if (go->ob) { - if (strcmp(go->ob->id.name, strip->object->id.name) == 0) - break; - } - } - if (go) - strip->object = go->ob; - else - strip->object = NULL; - } - - } -} - -#endif diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index 8a49cba7649..d8c3e260399 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -65,7 +65,7 @@ static void icon_free(void *val) Icon *icon = val; if (icon) { - if (icon->drawinfo_free) { + if (icon->drawinfo_free) { icon->drawinfo_free(icon->drawinfo); } else if (icon->drawinfo) { @@ -255,7 +255,7 @@ void BKE_icon_changed(int id) prv->changed_timestamp[i]++; } } - } + } } int BKE_icon_getid(struct ID *id) diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 8229df28ab8..5dd0f08dc71 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -484,7 +484,7 @@ void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) BLI_remlink(&group->data.group, loop); IDP_FreeProperty(loop); - MEM_freeN(loop); + MEM_freeN(loop); } else { group->len++; @@ -492,6 +492,30 @@ void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) } } +/* + * If a property is missing in \a dest, add it. + */ +void IDP_MergeGroup(IDProperty *dest, IDProperty *src, const int do_overwrite) +{ + IDProperty *prop; + + if (do_overwrite) { + for (prop = src->data.group.first; prop; prop = prop->next) { + IDProperty *copy = IDP_CopyProperty(prop); + IDP_ReplaceInGroup(dest, copy); + } + } + else { + for (prop = src->data.group.first; prop; prop = prop->next) { + if (IDP_GetPropertyFromGroup(dest, prop->name) == NULL) { + IDProperty *copy = IDP_CopyProperty(prop); + dest->len++; + BLI_addtail(&dest->data.group, copy); + } + } + } +} + /* returns 0 if an id property with the same name exists and it failed, * or 1 if it succeeded in adding to the group.*/ int IDP_AddToGroup(IDProperty *group, IDProperty *prop) @@ -608,60 +632,77 @@ IDProperty *IDP_GetProperties(ID *id, int create_if_needed) } } -int IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2) +/** + * \param is_strict When FALSE treat missing items as a match */ +int IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const int is_strict) { if (prop1 == NULL && prop2 == NULL) return 1; else if (prop1 == NULL || prop2 == NULL) - return 0; + return is_strict ? 0 : 1; else if (prop1->type != prop2->type) return 0; - if (prop1->type == IDP_INT) - return (IDP_Int(prop1) == IDP_Int(prop2)); - else if (prop1->type == IDP_FLOAT) - return (IDP_Float(prop1) == IDP_Float(prop2)); - else if (prop1->type == IDP_DOUBLE) - return (IDP_Double(prop1) == IDP_Double(prop2)); - else if (prop1->type == IDP_STRING) - return ((prop1->len == prop2->len) && strncmp(IDP_String(prop1), IDP_String(prop2), prop1->len) == 0); - else if (prop1->type == IDP_ARRAY) { - if (prop1->len == prop2->len && prop1->subtype == prop2->subtype) - return memcmp(IDP_Array(prop1), IDP_Array(prop2), idp_size_table[(int)prop1->subtype] * prop1->len); - else - return 0; - } - else if (prop1->type == IDP_GROUP) { - IDProperty *link1, *link2; - - if (BLI_countlist(&prop1->data.group) != BLI_countlist(&prop2->data.group)) - return 0; - - for (link1 = prop1->data.group.first; link1; link1 = link1->next) { - link2 = IDP_GetPropertyFromGroup(prop2, link1->name); - - if (!IDP_EqualsProperties(link1, link2)) + switch (prop1->type) { + case IDP_INT: + return (IDP_Int(prop1) == IDP_Int(prop2)); + case IDP_FLOAT: + return (IDP_Float(prop1) == IDP_Float(prop2)); + case IDP_DOUBLE: + return (IDP_Double(prop1) == IDP_Double(prop2)); + case IDP_STRING: + return ((prop1->len == prop2->len) && strncmp(IDP_String(prop1), IDP_String(prop2), prop1->len) == 0); + case IDP_ARRAY: + if (prop1->len == prop2->len && prop1->subtype == prop2->subtype) { + return memcmp(IDP_Array(prop1), IDP_Array(prop2), idp_size_table[(int)prop1->subtype] * prop1->len); + } + else { return 0; + } + case IDP_GROUP: + { + IDProperty *link1, *link2; + + if (is_strict && BLI_countlist(&prop1->data.group) != BLI_countlist(&prop2->data.group)) + return 0; + + for (link1 = prop1->data.group.first; link1; link1 = link1->next) { + link2 = IDP_GetPropertyFromGroup(prop2, link1->name); + + if (!IDP_EqualsProperties_ex(link1, link2, is_strict)) + return 0; + } + + return 1; } + case IDP_IDPARRAY: + { + IDProperty *array1 = IDP_IDPArray(prop1); + IDProperty *array2 = IDP_IDPArray(prop2); + int i; - return 1; - } - else if (prop1->type == IDP_IDPARRAY) { - IDProperty *array1 = IDP_IDPArray(prop1); - IDProperty *array2 = IDP_IDPArray(prop2); - int i; - - if (prop1->len != prop2->len) - return 0; - - for (i = 0; i < prop1->len; i++) - if (!IDP_EqualsProperties(&array1[i], &array2[i])) + if (prop1->len != prop2->len) return 0; + + for (i = 0; i < prop1->len; i++) + if (!IDP_EqualsProperties(&array1[i], &array2[i])) + return 0; + return 1; + } + default: + /* should never get here */ + BLI_assert(0); + break; } - + return 1; } +int IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2) +{ + return IDP_EqualsProperties_ex(prop1, prop2, TRUE); +} + /* 'val' is never NULL, don't check */ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *name) { @@ -679,7 +720,7 @@ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *n case IDP_DOUBLE: prop = MEM_callocN(sizeof(IDProperty), "IDProperty float"); *(double *)&prop->data.val = val->d; - break; + break; case IDP_ARRAY: { /* for now, we only support float and int and double arrays */ diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index f08af55c36e..ef751ce3493 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -603,7 +603,8 @@ Image *BKE_image_load_exists(const char *filepath) return BKE_image_load(filepath); } -static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, float color[4]) +static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, + float color[4], ColorManagedColorspaceSettings *colorspace_settings) { ImBuf *ibuf; unsigned char *rect = NULL; @@ -612,10 +613,26 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char if (floatbuf) { ibuf = IMB_allocImBuf(width, height, depth, IB_rectfloat); rect_float = ibuf->rect_float; + + if (colorspace_settings->name[0] == '\0') { + const char *colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_FLOAT); + + BLI_strncpy(colorspace_settings->name, colorspace, sizeof(colorspace_settings->name)); + } + + IMB_colormanagement_check_is_data(ibuf, colorspace_settings->name); } else { ibuf = IMB_allocImBuf(width, height, depth, IB_rect); rect = (unsigned char *)ibuf->rect; + + if (colorspace_settings->name[0] == '\0') { + const char *colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_BYTE); + + BLI_strncpy(colorspace_settings->name, colorspace, sizeof(colorspace_settings->name)); + } + + IMB_colormanagement_assign_rect_colorspace(ibuf, colorspace_settings->name); } BLI_strncpy(ibuf->name, name, sizeof(ibuf->name)); @@ -650,7 +667,7 @@ Image *BKE_image_add_generated(unsigned int width, unsigned int height, const ch ima->gen_type = gen_type; ima->gen_flag |= (floatbuf ? IMA_GEN_FLOAT : 0); - ibuf = add_ibuf_size(width, height, ima->name, depth, floatbuf, gen_type, color); + ibuf = add_ibuf_size(width, height, ima->name, depth, floatbuf, gen_type, color, &ima->colorspace_settings); image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); ima->ok = IMA_OK_LOADED; @@ -1016,7 +1033,7 @@ int BKE_imtype_supports_quality(const char imtype) return 0; } -int BKE_imtype_supports_float(const char imtype) +int BKE_imtype_requires_linear_float(const char imtype) { switch (imtype) { case R_IMF_IMTYPE_CINEON: @@ -1046,6 +1063,7 @@ char BKE_imtype_valid_channels(const char imtype) case R_IMF_IMTYPE_DDS: case R_IMF_IMTYPE_JP2: case R_IMF_IMTYPE_QUICKTIME: + case R_IMF_IMTYPE_DPX: chan_flag |= IMA_CHAN_FLAG_ALPHA; } @@ -1074,10 +1092,11 @@ char BKE_imtype_valid_depths(const char imtype) return R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_32; case R_IMF_IMTYPE_MULTILAYER: return R_IMF_CHAN_DEPTH_32; - /* eeh, cineone does some strange 10bits per channel */ + /* eeh, cineon does some strange 10bits per channel */ case R_IMF_IMTYPE_DPX: + return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_10 | R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16; case R_IMF_IMTYPE_CINEON: - return R_IMF_CHAN_DEPTH_12; + return R_IMF_CHAN_DEPTH_10; case R_IMF_IMTYPE_JP2: return R_IMF_CHAN_DEPTH_8 | R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16; /* most formats are 8bit only */ @@ -1227,6 +1246,9 @@ void BKE_imformat_defaults(ImageFormatData *im_format) im_format->imtype = R_IMF_IMTYPE_PNG; im_format->quality = 90; im_format->compress = 90; + + BKE_color_managed_display_settings_init(&im_format->display_settings); + BKE_color_managed_view_settings_init(&im_format->view_settings); } void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *imbuf) @@ -1805,9 +1827,33 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf) #ifdef WITH_CINEON else if (imtype == R_IMF_IMTYPE_CINEON) { ibuf->ftype = CINEON; + if (imf->cineon_flag & R_IMF_CINEON_FLAG_LOG) { + ibuf->ftype |= CINEON_LOG; + } + if (imf->depth == R_IMF_CHAN_DEPTH_16) { + ibuf->ftype |= CINEON_16BIT; + } + else if (imf->depth == R_IMF_CHAN_DEPTH_12) { + ibuf->ftype |= CINEON_12BIT; + } + else if (imf->depth == R_IMF_CHAN_DEPTH_10) { + ibuf->ftype |= CINEON_10BIT; + } } else if (imtype == R_IMF_IMTYPE_DPX) { ibuf->ftype = DPX; + if (imf->cineon_flag & R_IMF_CINEON_FLAG_LOG) { + ibuf->ftype |= CINEON_LOG; + } + if (imf->depth == R_IMF_CHAN_DEPTH_16) { + ibuf->ftype |= CINEON_16BIT; + } + else if (imf->depth == R_IMF_CHAN_DEPTH_12) { + ibuf->ftype |= CINEON_12BIT; + } + else if (imf->depth == R_IMF_CHAN_DEPTH_10) { + ibuf->ftype |= CINEON_10BIT; + } } #endif else if (imtype == R_IMF_IMTYPE_TARGA) { @@ -2100,6 +2146,15 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) } } break; + case IMA_SIGNAL_COLORMANAGE: + image_free_buffers(ima); + + ima->ok = 1; + + if (iuser) + iuser->ok = 1; + + break; } /* don't use notifiers because they are not 100% sure to succeeded @@ -2201,8 +2256,10 @@ void BKE_image_backup_render(Scene *scene, Image *ima) /* in that case we have to build a render-result */ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr) { + const char *colorspace = ima->colorspace_settings.name; + int predivide = ima->flag & IMA_CM_PREDIVIDE; - ima->rr = RE_MultilayerConvert(ibuf->userdata, ibuf->x, ibuf->y); + ima->rr = RE_MultilayerConvert(ibuf->userdata, colorspace, predivide, ibuf->x, ibuf->y); #ifdef WITH_OPENEXR IMB_exr_close(ibuf->userdata); @@ -2541,7 +2598,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ *lock_r = re; } - /* this gives active layer, composite or seqence result */ + /* this gives active layer, composite or sequence result */ rect = (unsigned int *)rres.rect32; rectf = rres.rectf; rectz = rres.rectz; @@ -2595,15 +2652,21 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ /* free rect buffer if float buffer changes, so it can be recreated with * the updated result, and also in case we got byte buffer from sequencer, * so we don't keep reference to freed buffer */ - - /* todo: this fix breaks save buffers render progress - if (ibuf->rect_float != rectf || rect || !rectf) */ - if (ibuf->rect_float != rectf || rect) imb_freerectImBuf(ibuf); - if (rect) + if (rect) { ibuf->rect = rect; + } + else { + /* byte buffer of render result has been freed, make sure image buffers + * does not reference to this buffer anymore + * need check for whether byte buffer was allocated and owned by image itself + * or if it's reusing buffer from render result + */ + if ((ibuf->mall & IB_rect) == 0) + ibuf->rect = NULL; + } if (rectf) { ibuf->rect_float = rectf; @@ -2782,7 +2845,8 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) /* UV testgrid or black or solid etc */ if (ima->gen_x == 0) ima->gen_x = 1024; if (ima->gen_y == 0) ima->gen_y = 1024; - ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 24, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type, color); + ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 24, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type, + color, &ima->colorspace_settings); image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); ima->ok = IMA_OK_LOADED; } @@ -2998,5 +3062,8 @@ void BKE_image_get_aspect(Image *image, float *aspx, float *aspy) *aspx = 1.0; /* x is always 1 */ - *aspy = image->aspy / image->aspx; + if (image) + *aspy = image->aspy / image->aspx; + else + *aspy = 1.0f; } diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c index 37572eebed6..468a88775c6 100644 --- a/source/blender/blenkernel/intern/image_gen.c +++ b/source/blender/blenkernel/intern/image_gen.c @@ -244,7 +244,7 @@ static void checker_board_color_tint(unsigned char *rect, float *rect_float, int } } - } + } } static void checker_board_grid_fill(unsigned char *rect, float *rect_float, int width, int height, float blend) diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index fcc8b4322a0..90cd7bc2df5 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -48,7 +48,9 @@ #include "BKE_global.h" -#define CLOTH_OPENMP_LIMIT 512 +#ifdef _OPENMP +# define CLOTH_OPENMP_LIMIT 512 +#endif #if 0 /* debug timing */ #ifdef _WIN32 @@ -588,7 +590,7 @@ DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, lfVector for (i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) { muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]); } - } + } #pragma omp section { for (i = 0; i < from[0].vcount+from[0].scount; i++) { @@ -621,7 +623,7 @@ DO_INLINE void add_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix /* process diagonal elements */ for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) { - add_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); + add_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); } } @@ -632,7 +634,7 @@ DO_INLINE void addadd_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmat /* process diagonal elements */ for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) { - addadd_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); + addadd_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); } } @@ -643,7 +645,7 @@ DO_INLINE void subadd_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmat /* process diagonal elements */ for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) { - subadd_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); + subadd_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); } } @@ -654,7 +656,7 @@ DO_INLINE void sub_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix /* process diagonal elements */ for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) { - sub_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); + sub_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); } } @@ -665,7 +667,7 @@ DO_INLINE void sub_bfmatrix_Smatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3 /* process diagonal elements */ for (i = 0; i < matrix[0].vcount; i++) { - sub_fmatrix_fmatrix(to[matrix[i].c].m, from[matrix[i].c].m, matrix[i].m); + sub_fmatrix_fmatrix(to[matrix[i].c].m, from[matrix[i].c].m, matrix[i].m); } } @@ -676,7 +678,7 @@ DO_INLINE void addsub_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmat /* process diagonal elements */ for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) { - addsub_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); + addsub_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); } } @@ -689,7 +691,7 @@ DO_INLINE void subadd_bfmatrixS_bfmatrixS( fmatrix3x3 *to, fmatrix3x3 *from, flo /* process diagonal elements */ for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) { - subadd_fmatrixS_fmatrixS(to[i].m, from[i].m, aS, matrix[i].m, bS); + subadd_fmatrixS_fmatrixS(to[i].m, from[i].m, aS, matrix[i].m, bS); } } @@ -709,7 +711,7 @@ static void update_matrixS(ClothVertex *verts, int numverts, fmatrix3x3 *S) int i = 0; /* Clear matrix from old vertex constraints */ - for(i = 0; i < S[0].vcount; i++) + for (i = 0; i < S[0].vcount; i++) S[i].c = S[i].r = 0; /* Set new vertex constraints */ @@ -747,7 +749,7 @@ int implicit_init(Object *UNUSED(ob), ClothModifierData *clmd) id = (Implicit_Data *)MEM_callocN(sizeof(Implicit_Data), "implicit vecmat"); cloth->implicit = id; - /* process diagonal elements */ + /* process diagonal elements */ id->A = create_bfmatrix(cloth->numverts, cloth->numsprings); id->dFdV = create_bfmatrix(cloth->numverts, cloth->numsprings); id->dFdX = create_bfmatrix(cloth->numverts, cloth->numsprings); @@ -842,41 +844,40 @@ int implicit_free(ClothModifierData *clmd) DO_INLINE float fb(float length, float L) { - float x = length/L; - return (-11.541f*pow(x, 4)+34.193f*pow(x, 3)-39.083f*pow(x, 2)+23.116f*x-9.713f); + float x = length / L; + return (-11.541f * powf(x, 4) + 34.193f * powf(x, 3) - 39.083f * powf(x, 2) + 23.116f * x - 9.713f); } DO_INLINE float fbderiv(float length, float L) { float x = length/L; - return (-46.164f*pow(x, 3)+102.579f*pow(x, 2)-78.166f*x+23.116f); + return (-46.164f * powf(x, 3) + 102.579f * powf(x, 2) - 78.166f * x + 23.116f); } DO_INLINE float fbstar(float length, float L, float kb, float cb) { - float tempfb = kb * fb(length, L); - - float fbstar = cb * (length - L); + float tempfb_fl = kb * fb(length, L); + float fbstar_fl = cb * (length - L); - if (tempfb < fbstar) - return fbstar; + if (tempfb_fl < fbstar_fl) + return fbstar_fl; else - return tempfb; + return tempfb_fl; } // function to calculae bending spring force (taken from Choi & Co) DO_INLINE float fbstar_jacobi(float length, float L, float kb, float cb) { - float tempfb = kb * fb(length, L); - float fbstar = cb * (length - L); + float tempfb_fl = kb * fb(length, L); + float fbstar_fl = cb * (length - L); - if (tempfb < fbstar) { + if (tempfb_fl < fbstar_fl) { return cb; } else { - return kb * fbderiv(length, L); - } + return kb * fbderiv(length, L); + } } DO_INLINE void filter(lfVector *V, fmatrix3x3 *S) @@ -916,7 +917,7 @@ static int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z cp_lfvector(d, r, numverts); s = dot_lfvector(r, r, numverts); - starget = s * sqrt(conjgrad_epsilon); + starget = s * sqrtf(conjgrad_epsilon); while (s>starget && conjgrad_loopcount < conjgrad_looplimit) { // Mul(q, A, d); // q = A*d; @@ -1147,9 +1148,9 @@ DO_INLINE void dfdx_spring_type1(float to[3][3], float extent[3], float length, // dir is unit length direction, rest is spring's restlength, k is spring constant. // return (outerprod(dir, dir)*k + (I - outerprod(dir, dir))*(k - ((k*L)/length))); float temp[3][3]; - float temp1 = k*(1.0 - (L/length)); + float temp1 = k * (1.0f - (L / length)); - mul_fvectorT_fvectorS(temp, extent, extent, 1.0 / dot); + mul_fvectorT_fvectorS(temp, extent, extent, 1.0f / dot); sub_fmatrix_fmatrix(to, I, temp); mul_fmatrix_S(to, temp1); @@ -1217,7 +1218,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float stretch_force[3] = {0, 0, 0}; float bending_force[3] = {0, 0, 0}; float damping_force[3] = {0, 0, 0}; - float nulldfdx[3][3]={ {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; + float nulldfdx[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; float scaling = 0.0; @@ -1245,7 +1246,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, s->flags |= CSPRING_FLAG_DEACTIVATE; return; } - } + } */ mul_fvector_S(dir, extent, 1.0f/length); } @@ -1306,7 +1307,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, VECADDS(s->f, s->f, extent, -k); - mul_fvector_S(damping_force, dir, clmd->sim_parms->goalfrict * 0.01 * dot_v3v3(vel, dir)); + mul_fvector_S(damping_force, dir, clmd->sim_parms->goalfrict * 0.01f * dot_v3v3(vel, dir)); VECADD(s->f, s->f, damping_force); // HERE IS THE PROBLEM!!!! @@ -1317,10 +1318,10 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, if (length < L) { s->flags |= CLOTH_SPRING_FLAG_NEEDED; - k = clmd->sim_parms->bending; + k = clmd->sim_parms->bending; - scaling = k + s->stiffness * ABS(clmd->sim_parms->max_bend-k); - cb = k = scaling / (20.0*(clmd->sim_parms->avg_spring_len + FLT_EPSILON)); + scaling = k + s->stiffness * ABS(clmd->sim_parms->max_bend-k); + cb = k = scaling / (20.0f * (clmd->sim_parms->avg_spring_len + FLT_EPSILON)); mul_fvector_S(bending_force, dir, fbstar(length, L, k, cb)); VECADD(s->f, s->f, bending_force); @@ -1336,7 +1337,7 @@ DO_INLINE void cloth_apply_spring_force(ClothModifierData *UNUSED(clmd), ClothSp if (!(s->type & CLOTH_SPRING_TYPE_BENDING)) { sub_fmatrix_fmatrix(dFdV[s->ij].m, dFdV[s->ij].m, s->dfdv); sub_fmatrix_fmatrix(dFdV[s->kl].m, dFdV[s->kl].m, s->dfdv); - add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, s->dfdv); + add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, s->dfdv); } VECADD(lF[s->ij], lF[s->ij], s->f); @@ -1347,7 +1348,7 @@ DO_INLINE void cloth_apply_spring_force(ClothModifierData *UNUSED(clmd), ClothSp sub_fmatrix_fmatrix(dFdX[s->kl].m, dFdX[s->kl].m, s->dfdx); sub_fmatrix_fmatrix(dFdX[s->ij].m, dFdX[s->ij].m, s->dfdx); add_fmatrix_fmatrix(dFdX[s->matrix_index].m, dFdX[s->matrix_index].m, s->dfdx); - } + } } @@ -1355,15 +1356,15 @@ static void CalcFloat( float *v1, float *v2, float *v3, float *n) { float n1[3], n2[3]; - n1[0]= v1[0]-v2[0]; - n2[0]= v2[0]-v3[0]; - n1[1]= v1[1]-v2[1]; - n2[1]= v2[1]-v3[1]; - n1[2]= v1[2]-v2[2]; - n2[2]= v2[2]-v3[2]; - n[0]= n1[1]*n2[2]-n1[2]*n2[1]; - n[1]= n1[2]*n2[0]-n1[0]*n2[2]; - n[2]= n1[0]*n2[1]-n1[1]*n2[0]; + n1[0] = v1[0]-v2[0]; + n2[0] = v2[0]-v3[0]; + n1[1] = v1[1]-v2[1]; + n2[1] = v2[1]-v3[1]; + n1[2] = v1[2]-v2[2]; + n2[2] = v2[2]-v3[2]; + n[0] = n1[1]*n2[2]-n1[2]*n2[1]; + n[1] = n1[2]*n2[0]-n1[0]*n2[2]; + n[2] = n1[0]*n2[1]-n1[1]*n2[0]; } static void CalcFloat4( float *v1, float *v2, float *v3, float *v4, float *n) @@ -1371,17 +1372,17 @@ static void CalcFloat4( float *v1, float *v2, float *v3, float *v4, float *n) /* real cross! */ float n1[3], n2[3]; - n1[0]= v1[0]-v3[0]; - n1[1]= v1[1]-v3[1]; - n1[2]= v1[2]-v3[2]; + n1[0] = v1[0]-v3[0]; + n1[1] = v1[1]-v3[1]; + n1[2] = v1[2]-v3[2]; - n2[0]= v2[0]-v4[0]; - n2[1]= v2[1]-v4[1]; - n2[2]= v2[2]-v4[2]; + n2[0] = v2[0]-v4[0]; + n2[1] = v2[1]-v4[1]; + n2[2] = v2[2]-v4[2]; - n[0]= n1[1]*n2[2]-n1[2]*n2[1]; - n[1]= n1[2]*n2[0]-n1[0]*n2[2]; - n[2]= n1[0]*n2[1]-n1[1]*n2[0]; + n[0] = n1[1]*n2[2]-n1[2]*n2[1]; + n[1] = n1[2]*n2[0]-n1[0]*n2[2]; + n[2] = n1[0]*n2[1]-n1[1]*n2[0]; } static float calculateVertexWindForce(float wind[3], float vertexnormal[3]) @@ -1448,7 +1449,7 @@ static void hair_velocity_smoothing(ClothModifierData *clmd, lfVector *lF, lfVec i = HAIR_GRID_INDEX(lX[v], gmin, gmax, 0); j = HAIR_GRID_INDEX(lX[v], gmin, gmax, 1); k = HAIR_GRID_INDEX(lX[v], gmin, gmax, 2); - if (i < 0 || j < 0 || k < 0 || i > 10 || j >= 10 || k >= 10) + if (i < 0 || j < 0 || k < 0 || i >= 10 || j >= 10 || k >= 10) continue; grid[i][j][k].velocity[0] += lV[v][0]; @@ -1478,7 +1479,7 @@ static void hair_velocity_smoothing(ClothModifierData *clmd, lfVector *lF, lfVec colg[i][j][k].velocity[0] += vel[0]; colg[i][j][k].velocity[1] += vel[1]; colg[i][j][k].velocity[2] += vel[2]; - colg[i][j][k].density += 1.0; + colg[i][j][k].density += 1.0f; } } } @@ -1512,7 +1513,7 @@ static void hair_velocity_smoothing(ClothModifierData *clmd, lfVector *lF, lfVec i = HAIR_GRID_INDEX(lX[v], gmin, gmax, 0); j = HAIR_GRID_INDEX(lX[v], gmin, gmax, 1); k = HAIR_GRID_INDEX(lX[v], gmin, gmax, 2); - if (i < 0 || j < 0 || k < 0 || i > 10 || j >= 10 || k >= 10) + if (i < 0 || j < 0 || k < 0 || i >= 10 || j >= 10 || k >= 10) continue; lF[v][0] += smoothfac * (grid[i][j][k].velocity[0] - lV[v][0]); @@ -1543,7 +1544,7 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), lfVec lfVector *winvec; EffectedPoint epoint; - tm2[0][0]= tm2[1][1]= tm2[2][2]= -spring_air; + tm2[0][0] = tm2[1][1] = tm2[2][2] = -spring_air; /* global acceleration (gravitation) */ if (clmd->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { @@ -1587,11 +1588,11 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), lfVec } for (i = 0; i < cloth->numfaces; i++) { - float trinormal[3]={0, 0, 0}; // normalized triangle normal - float triunnormal[3]={0, 0, 0}; // not-normalized-triangle normal - float tmp[3]={0, 0, 0}; + float trinormal[3] = {0, 0, 0}; // normalized triangle normal + float triunnormal[3] = {0, 0, 0}; // not-normalized-triangle normal + float tmp[3] = {0, 0, 0}; float factor = (mfaces[i].v4) ? 0.25 : 1.0 / 3.0; - factor *= 0.02; + factor *= 0.02f; // calculate face normal if (mfaces[i].v4) @@ -1627,9 +1628,9 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), lfVec /* Hair has only edges */ if (cloth->numfaces == 0) { ClothSpring *spring; - float edgevec[3]={0, 0, 0}; //edge vector - float edgeunnormal[3]={0, 0, 0}; // not-normalized-edge normal - float tmp[3]={0, 0, 0}; + float edgevec[3] = {0, 0, 0}; //edge vector + float edgeunnormal[3] = {0, 0, 0}; // not-normalized-edge normal + float tmp[3] = {0, 0, 0}; float factor = 0.01; search = cloth->springs; @@ -1661,7 +1662,7 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), lfVec while (search) { // only handle active springs ClothSpring *spring = search->link; - if( !(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE)) + if (!(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE)) cloth_calc_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX, time); search = search->next; @@ -1729,8 +1730,8 @@ static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothMo for (i=0; inumverts; i++, cv++) { copy_v3_v3(cos[i], cv->tx); - if (cv->goal == 1.0f || len_v3v3(initial_cos[i], cv->tx) != 0.0) { - masses[i] = 1e+10; + if (cv->goal == 1.0f || len_squared_v3v3(initial_cos[i], cv->tx) != 0.0f) { + masses[i] = 1e+10; } else { masses[i] = cv->mass; @@ -1757,18 +1758,18 @@ static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothMo normalize_v3(vec); c = (len - spring->restlen); - if (c == 0.0) + if (c == 0.0f) continue; - l = c / ((1.0/masses[v1]) + (1.0/masses[v2])); + l = c / ((1.0f / masses[v1]) + (1.0f / masses[v2])); - mul_v3_fl(vec, -(1.0/masses[v1])*l); + mul_v3_fl(vec, -(1.0f / masses[v1]) * l); add_v3_v3(cos[v1], vec); sub_v3_v3v3(vec, cos[v2], cos[v1]); normalize_v3(vec); - mul_v3_fl(vec, -(1.0/masses[v2])*l); + mul_v3_fl(vec, -(1.0f / masses[v2]) * l); add_v3_v3(cos[v2], vec); } } @@ -1813,7 +1814,7 @@ int implicit_solver(Object *ob, float frame, ClothModifierData *clmd, ListBase * sub_v3_v3v3(id->V[i], verts[i].xconst, verts[i].xold); // mul_v3_fl(id->V[i], clmd->sim_parms->stepsPerFrame); } - } + } } while (step < tf) { @@ -1838,7 +1839,7 @@ int implicit_solver(Object *ob, float frame, ClothModifierData *clmd, ListBase * mul_fvector_S(tvect, tvect, step+dt); VECADD(tvect, tvect, verts[i].xold); copy_v3_v3(id->Xnew[i], tvect); - } + } } copy_v3_v3(verts[i].txold, id->X[i]); @@ -1896,7 +1897,7 @@ int implicit_solver(Object *ob, float frame, ClothModifierData *clmd, ListBase * cp_lfvector(id->V, id->Vnew, numverts); // calculate - cloth_calc_force(clmd, frame, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step+dt, id->M); + cloth_calc_force(clmd, frame, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step+dt, id->M); simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv, id->M, id->bigI); } @@ -1945,6 +1946,6 @@ void implicit_set_positions(ClothModifierData *clmd) copy_v3_v3(id->V[i], verts[i].v); } if (G.debug_value > 0) - printf("implicit_set_positions\n"); + printf("implicit_set_positions\n"); } diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index b2a9e229be9..59dd02849dd 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -32,7 +32,7 @@ /* NOTE: * - * This file is no longer used to provide tools for the depreceated IPO system. Instead, it + * This file is no longer used to provide tools for the deprecated IPO system. Instead, it * is only used to house the conversion code to the new system. * * -- Joshua Leung, Jan 2009 @@ -569,7 +569,7 @@ static const char *material_adrcodes_to_paths(int adrcode, int *array_index) return mtex_adrcodes_to_paths(adrcode, array_index); } - return NULL; + return NULL; } /* Camera Types */ @@ -727,7 +727,7 @@ static const char *world_adrcodes_to_paths(int adrcode, int *array_index) return mtex_adrcodes_to_paths(adrcode, array_index); } - return NULL; + return NULL; } /* Particle Types */ @@ -873,7 +873,7 @@ static char *get_rna_access(int blocktype, int adrcode, char actname[], char con propname = "eval_time"; break; - /* XXX problematic blocktypes */ + /* XXX problematic blocktypes */ case ID_SEQ: /* sequencer strip */ //SEQ_FAC1: switch (adrcode) { @@ -981,21 +981,21 @@ static char *get_rna_access(int blocktype, int adrcode, char actname[], char con static short adrcode_to_dtar_transchan(short adrcode) { switch (adrcode) { - case OB_LOC_X: + case OB_LOC_X: return DTAR_TRANSCHAN_LOCX; case OB_LOC_Y: return DTAR_TRANSCHAN_LOCY; case OB_LOC_Z: return DTAR_TRANSCHAN_LOCZ; - case OB_ROT_X: + case OB_ROT_X: return DTAR_TRANSCHAN_ROTX; case OB_ROT_Y: return DTAR_TRANSCHAN_ROTY; case OB_ROT_Z: return DTAR_TRANSCHAN_ROTZ; - case OB_SIZE_X: + case OB_SIZE_X: return DTAR_TRANSCHAN_SCALEX; case OB_SIZE_Y: return DTAR_TRANSCHAN_SCALEX; @@ -1359,8 +1359,8 @@ static void icu_to_fcurves(ID *id, ListBase *groups, ListBase *list, IpoCurve *i /* correct values for sequencer curves, that were not locked to frame */ if (seq && (seq->flag & SEQ_IPO_FRAME_LOCKED) == 0) { - double mul = (seq->enddisp - seq->startdisp) / 100.0f; - double offset = seq->startdisp; + const float mul = (seq->enddisp - seq->startdisp) / 100.0f; + const float offset = seq->startdisp; dst->vec[0][0] *= mul; dst->vec[0][0] += offset; @@ -1645,7 +1645,7 @@ static void nlastrips_to_animdata(ID *id, ListBase *strips) /* by default, we now always extrapolate, while in the past this was optional */ if ((as->flag & ACTSTRIP_HOLDLASTFRAME) == 0) strip->extendmode = NLASTRIP_EXTEND_NOTHING; - } + } /* try to add this strip to the current NLA-Track (i.e. the 'last' one on the stack atm) */ if (BKE_nlatrack_add_strip(nlt, strip) == 0) { @@ -1757,15 +1757,15 @@ void do_versions_ipos_to_animato(Main *main) { /* If we have any empty action actuators, assume they were - converted IPO Actuators using the object IPO */ + * converted IPO Actuators using the object IPO */ bActuator *act; bActionActuator *aa; for (act = ob->actuators.first; act; act = act->next) { /* Any actuators set to ACT_IPO at this point are actually Action Actuators that - need this converted IPO to finish converting the actuator. */ + * need this converted IPO to finish converting the actuator. */ if (act->type == ACT_IPO) { - aa = (bActionActuator*)act->data; + aa = (bActionActuator *)act->data; aa->act = ob->adt->action; act->type = ACT_ACTION; } @@ -2093,7 +2093,7 @@ void do_versions_ipos_to_animato(Main *main) bAction *new_act; /* add a new action for this, and convert all data into that action */ - new_act = add_empty_action(id->name+2); + new_act = add_empty_action(id->name + 2); ipo_to_animato(NULL, ipo, NULL, NULL, NULL, NULL, &new_act->curves, &drivers); new_act->idroot = ipo->blocktype; } diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index b79608342dd..782d796b8a7 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -94,7 +94,7 @@ void BKE_key_free(Key *key) } -void free_key_nolib(Key *key) +void BKE_key_free_nolib(Key *key) { KeyBlock *kb; @@ -121,7 +121,7 @@ void free_key_nolib(Key *key) /* from misc_util: flip the bytes from x */ /* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */ -Key *add_key(ID *id) /* common function */ +Key *BKE_key_add(ID *id) /* common function */ { Key *key; char *el; @@ -133,7 +133,7 @@ Key *add_key(ID *id) /* common function */ key->uidgen = 1; - /* XXX the code here uses some defines which will soon be depreceated... */ + /* XXX the code here uses some defines which will soon be deprecated... */ switch (GS(id->name)) { case ID_ME: el = key->elemstr; @@ -196,7 +196,7 @@ Key *BKE_key_copy(Key *key) } -Key *copy_key_nolib(Key *key) +Key *BKE_key_copy_nolib(Key *key) { Key *keyn; KeyBlock *kbn, *kb; @@ -241,7 +241,7 @@ void BKE_key_make_local(Key *key) * currently being called. */ -void sort_keys(Key *key) +void BKE_key_sort(Key *key) { KeyBlock *kb; KeyBlock *kb2; @@ -389,7 +389,7 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float t[4], int cycl) if (k1->next == NULL) k[0] = k1; k1 = k1->next; } - /* k1= k[1]; */ /* UNUSED */ + /* k1 = k[1]; */ /* UNUSED */ t[0] = k[0]->pos; t[1] += dpos; t[2] = k[2]->pos + dpos; @@ -609,7 +609,7 @@ static void cp_key(const int start, int end, const int tot, char *poin, Key *key } } else k1 += start * key->elemsize; - } + } if (mode == KEY_MODE_BEZTRIPLE) { elemstr[0] = 1; @@ -691,8 +691,8 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const if (nu->bp) { step = nu->pntsu * nu->pntsv; - a1 = maxi(a, start); - a2 = mini(a + step, end); + a1 = max_ii(a, start); + a2 = min_ii(a + step, end); if (a1 < a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_MODE_BPOINT); } @@ -700,8 +700,8 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const step = 3 * nu->pntsu; /* exception because keys prefer to work with complete blocks */ - a1 = maxi(a, start); - a2 = mini(a + step, end); + a1 = max_ii(a, start); + a2 = min_ii(a + step, end); if (a1 < a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_MODE_BEZTRIPLE); } @@ -711,7 +711,7 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const } } -void do_rel_key(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb, const int mode) +void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb, const int mode) { KeyBlock *kb; int *ofsp, ofs[3], elemsize, b; @@ -1043,7 +1043,7 @@ static float *get_weights_array(Object *ob, char *vgroup) /* find the group (weak loop-in-loop) */ defgrp_index = defgroup_name_index(ob, vgroup); - if (defgrp_index >= 0) { + if (defgrp_index != -1) { float *weights; int i; @@ -1071,7 +1071,7 @@ static float *get_weights_array(Object *ob, char *vgroup) static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int tot) { - KeyBlock *k[4], *actkb = ob_get_keyblock(ob); + KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob); float t[4]; int flag = 0; @@ -1106,7 +1106,7 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int kb->weights = get_weights_array(ob, kb->vgroup); } - do_rel_key(0, tot, tot, (char *)out, key, actkb, KEY_MODE_DUMMY); + BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, KEY_MODE_DUMMY); for (kb = key->block.first; kb; kb = kb->next) { if (kb->weights) MEM_freeN(kb->weights); @@ -1154,11 +1154,11 @@ static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, char *out, const for (a = 0, nu = cu->nurb.first; nu; nu = nu->next, a += step) { if (nu->bp) { step = nu->pntsu * nu->pntsv; - do_rel_key(a, a + step, tot, out, key, actkb, KEY_MODE_BPOINT); + BKE_key_evaluate_relative(a, a + step, tot, out, key, actkb, KEY_MODE_BPOINT); } else if (nu->bezt) { step = 3 * nu->pntsu; - do_rel_key(a, a + step, tot, out, key, actkb, KEY_MODE_BEZTRIPLE); + BKE_key_evaluate_relative(a, a + step, tot, out, key, actkb, KEY_MODE_BEZTRIPLE); } else { step = 0; @@ -1169,7 +1169,7 @@ static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, char *out, const static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, const int tot) { Curve *cu = ob->data; - KeyBlock *k[4], *actkb = ob_get_keyblock(ob); + KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob); float t[4]; int flag = 0; @@ -1217,7 +1217,7 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, const in remain = step; } - count = mini(remain, estep); + count = min_ii(remain, estep); if (mode == KEY_MODE_BEZTRIPLE) { count += 3 - count % 3; } @@ -1251,7 +1251,7 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, const in static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int tot) { Lattice *lt = ob->data; - KeyBlock *k[4], *actkb = ob_get_keyblock(ob); + KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob); float t[4]; int flag; @@ -1268,7 +1268,7 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int do_key(a, a + 1, tot, out, key, actkb, k, t, KEY_MODE_DUMMY); else cp_key(a, a + 1, tot, out, key, actkb, k[2], NULL, KEY_MODE_DUMMY); - } + } } else { if (key->type == KEY_RELATIVE) { @@ -1277,7 +1277,7 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int for (kb = key->block.first; kb; kb = kb->next) kb->weights = get_weights_array(ob, kb->vgroup); - do_rel_key(0, tot, tot, out, key, actkb, KEY_MODE_DUMMY); + BKE_key_evaluate_relative(0, tot, tot, out, key, actkb, KEY_MODE_DUMMY); for (kb = key->block.first; kb; kb = kb->next) { if (kb->weights) MEM_freeN(kb->weights); @@ -1302,8 +1302,8 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int /* returns key coordinates (+ tilt) when key applied, NULL otherwise */ float *do_ob_key(Scene *scene, Object *ob) { - Key *key = ob_get_key(ob); - KeyBlock *actkb = ob_get_keyblock(ob); + Key *key = BKE_key_from_object(ob); + KeyBlock *actkb = BKE_keyblock_from_object(ob); char *out; int tot = 0, size = 0; @@ -1386,7 +1386,7 @@ float *do_ob_key(Scene *scene, Object *ob) return (float *)out; } -Key *ob_get_key(Object *ob) +Key *BKE_key_from_object(Object *ob) { if (ob == NULL) return NULL; @@ -1405,7 +1405,7 @@ Key *ob_get_key(Object *ob) return NULL; } -KeyBlock *add_keyblock(Key *key, const char *name) +KeyBlock *BKE_keyblock_add(Key *key, const char *name) { KeyBlock *kb; float curpos = -0.1; @@ -1439,7 +1439,7 @@ KeyBlock *add_keyblock(Key *key, const char *name) /** * \note caller may want to set this to current time, but don't do it here since we need to sort - * which could cause problems in some cases, see #add_keyblock_ctime */ + * which could cause problems in some cases, see #BKE_keyblock_add_ctime */ kb->pos = curpos + 0.1f; /* only used for absolute shape keys */ return kb; @@ -1453,22 +1453,22 @@ KeyBlock *add_keyblock(Key *key, const char *name) * \param name Optional name for the new keyblock. * \param do_force always use ctime even for relative keys. */ -KeyBlock *add_keyblock_ctime(Key *key, const char *name, const short do_force) +KeyBlock *BKE_keyblock_add_ctime(Key *key, const char *name, const short do_force) { - KeyBlock *kb = add_keyblock(key, name); + KeyBlock *kb = BKE_keyblock_add(key, name); if (do_force || (key->type != KEY_RELATIVE)) { kb->pos = key->ctime / 100.0f; - sort_keys(key); + BKE_key_sort(key); } return kb; } /* only the active keyblock */ -KeyBlock *ob_get_keyblock(Object *ob) +KeyBlock *BKE_keyblock_from_object(Object *ob) { - Key *key = ob_get_key(ob); + Key *key = BKE_key_from_object(ob); if (key) { KeyBlock *kb = BLI_findlink(&key->block, ob->shapenr - 1); @@ -1478,9 +1478,9 @@ KeyBlock *ob_get_keyblock(Object *ob) return NULL; } -KeyBlock *ob_get_reference_keyblock(Object *ob) +KeyBlock *BKE_keyblock_from_object_reference(Object *ob) { - Key *key = ob_get_key(ob); + Key *key = BKE_key_from_object(ob); if (key) return key->refkey; @@ -1489,7 +1489,7 @@ KeyBlock *ob_get_reference_keyblock(Object *ob) } /* get the appropriate KeyBlock given an index */ -KeyBlock *key_get_keyblock(Key *key, int index) +KeyBlock *BKE_keyblock_from_key(Key *key, int index) { KeyBlock *kb; int i; @@ -1509,18 +1509,29 @@ KeyBlock *key_get_keyblock(Key *key, int index) } /* get the appropriate KeyBlock given a name to search for */ -KeyBlock *key_get_named_keyblock(Key *key, const char name[]) +KeyBlock *BKE_keyblock_find_name(Key *key, const char name[]) { - if (key && name) - return BLI_findstring(&key->block, name, offsetof(KeyBlock, name)); - - return NULL; + return BLI_findstring(&key->block, name, offsetof(KeyBlock, name)); +} + +/** + * \brief copy shape-key attributes, but not key data.or name/uid + */ +void BKE_keyblock_copy_settings(KeyBlock *kb_dst, const KeyBlock *kb_src) +{ + kb_dst->pos = kb_src->pos; + kb_dst->curval = kb_src->curval; + kb_dst->type = kb_src->type; + kb_dst->relative = kb_src->relative; + BLI_strncpy(kb_dst->vgroup, kb_src->vgroup, sizeof(kb_dst->vgroup)); + kb_dst->slidermin = kb_src->slidermin; + kb_dst->slidermax = kb_src->slidermax; } /* Get RNA-Path for 'value' setting of the given ShapeKey * NOTE: the user needs to free the returned string once they're finish with it */ -char *key_get_curValue_rnaPath(Key *key, KeyBlock *kb) +char *BKE_keyblock_curval_rnapath_get(Key *key, KeyBlock *kb) { PointerRNA ptr; PropertyRNA *prop; @@ -1542,7 +1553,7 @@ char *key_get_curValue_rnaPath(Key *key, KeyBlock *kb) /* conversion functions */ /************************* Lattice ************************/ -void latt_to_key(Lattice *lt, KeyBlock *kb) +void BKE_key_convert_from_lattice(Lattice *lt, KeyBlock *kb) { BPoint *bp; float *fp; @@ -1563,7 +1574,7 @@ void latt_to_key(Lattice *lt, KeyBlock *kb) } } -void key_to_latt(KeyBlock *kb, Lattice *lt) +void BKE_key_convert_to_lattice(KeyBlock *kb, Lattice *lt) { BPoint *bp; float *fp; @@ -1573,7 +1584,7 @@ void key_to_latt(KeyBlock *kb, Lattice *lt) fp = kb->data; tot = lt->pntsu * lt->pntsv * lt->pntsw; - tot = mini(kb->totelem, tot); + tot = min_ii(kb->totelem, tot); for (a = 0; a < tot; a++, fp += 3, bp++) { copy_v3_v3(bp->vec, fp); @@ -1581,7 +1592,7 @@ void key_to_latt(KeyBlock *kb, Lattice *lt) } /************************* Curve ************************/ -void curve_to_key(Curve *cu, KeyBlock *kb, ListBase *nurb) +void BKE_key_convert_from_curve(Curve *cu, KeyBlock *kb, ListBase *nurb) { Nurb *nu; BezTriple *bezt; @@ -1632,7 +1643,7 @@ void curve_to_key(Curve *cu, KeyBlock *kb, ListBase *nurb) } } -void key_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb) +void BKE_key_convert_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb) { Nurb *nu; BezTriple *bezt; @@ -1645,7 +1656,7 @@ void key_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb) tot = BKE_nurbList_verts_count(nurb); - tot = mini(kb->totelem, tot); + tot = min_ii(kb->totelem, tot); while (nu && tot > 0) { @@ -1683,7 +1694,7 @@ void key_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb) } /************************* Mesh ************************/ -void mesh_to_key(Mesh *me, KeyBlock *kb) +void BKE_key_convert_from_mesh(Mesh *me, KeyBlock *kb) { MVert *mvert; float *fp; @@ -1704,7 +1715,7 @@ void mesh_to_key(Mesh *me, KeyBlock *kb) } } -void key_to_mesh(KeyBlock *kb, Mesh *me) +void BKE_key_convert_to_mesh(KeyBlock *kb, Mesh *me) { MVert *mvert; float *fp; @@ -1713,7 +1724,7 @@ void key_to_mesh(KeyBlock *kb, Mesh *me) mvert = me->mvert; fp = kb->data; - tot = mini(kb->totelem, me->totvert); + tot = min_ii(kb->totelem, me->totvert); for (a = 0; a < tot; a++, fp += 3, mvert++) { copy_v3_v3(mvert->co, fp); @@ -1721,7 +1732,7 @@ void key_to_mesh(KeyBlock *kb, Mesh *me) } /************************* vert coords ************************/ -float (*key_to_vertcos(Object * ob, KeyBlock * kb))[3] +float (*BKE_key_convert_to_vertcos(Object * ob, KeyBlock * kb))[3] { float (*vertCos)[3], *co; float *fp = kb->data; @@ -1743,7 +1754,7 @@ float (*key_to_vertcos(Object * ob, KeyBlock * kb))[3] if (tot == 0) return NULL; - vertCos = MEM_callocN(tot * sizeof(*vertCos), "key_to_vertcos vertCos"); + vertCos = MEM_callocN(tot * sizeof(*vertCos), "BKE_key_convert_to_vertcos vertCos"); /* Copy coords to array */ co = (float *)vertCos; @@ -1797,7 +1808,7 @@ float (*key_to_vertcos(Object * ob, KeyBlock * kb))[3] return vertCos; } -void vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]) +void BKE_key_convert_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)[3]) { float *co = (float *)vertCos, *fp; int tot = 0, a, elemsize; @@ -1826,7 +1837,7 @@ void vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]) return; } - fp = kb->data = MEM_callocN(tot * elemsize, "key_to_vertcos vertCos"); + fp = kb->data = MEM_callocN(tot * elemsize, "BKE_key_convert_to_vertcos vertCos"); /* Copy coords to keyblock */ @@ -1877,7 +1888,7 @@ void vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]) } } -void offset_to_key(Object *ob, KeyBlock *kb, float (*ofs)[3]) +void BKE_key_convert_from_offset(Object *ob, KeyBlock *kb, float (*ofs)[3]) { int a; float *co = (float *)ofs, *fp = kb->data; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 17e4103c7d3..a15ca7cb5ce 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -64,19 +64,19 @@ #include "BKE_deform.h" -void calc_lat_fudu(int flag, int res, float *fu, float *du) +void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du) { if (res == 1) { - *fu = 0.0; - *du = 0.0; + *r_fu = 0.0; + *r_du = 0.0; } else if (flag & LT_GRID) { - *fu = -0.5f * (res - 1); - *du = 1.0f; + *r_fu = -0.5f * (res - 1); + *r_du = 1.0f; } else { - *fu = -1.0f; - *du = 2.0f / (res - 1); + *r_fu = -1.0f; + *r_du = 2.0f / (res - 1); } } @@ -348,7 +348,7 @@ void calc_latt_deform(Object *ob, float co[3], float weight) int ui, vi, wi, uu, vv, ww; /* vgroup influence */ - int defgroup_nr = -1; + int defgrp_index = -1; float co_prev[3], weight_blend = 0.0f; MDeformVert *dvert = BKE_lattice_deform_verts_get(ob); @@ -357,7 +357,7 @@ void calc_latt_deform(Object *ob, float co[3], float weight) if (lt->latticedata == NULL) return; if (lt->vgroup[0] && dvert) { - defgroup_nr = defgroup_name_index(ob, lt->vgroup); + defgrp_index = defgroup_name_index(ob, lt->vgroup); copy_v3_v3(co_prev, co); } @@ -431,8 +431,8 @@ void calc_latt_deform(Object *ob, float co[3], float weight) madd_v3_v3fl(co, <->latticedata[idx_u * 3], u); - if (defgroup_nr != -1) - weight_blend += (u * defvert_find_weight(dvert + idx_u, defgroup_nr)); + if (defgrp_index != -1) + weight_blend += (u * defvert_find_weight(dvert + idx_u, defgrp_index)); } } } @@ -440,7 +440,7 @@ void calc_latt_deform(Object *ob, float co[3], float weight) } } - if (defgroup_nr != -1) + if (defgrp_index != -1) interp_v3_v3v3(co, co_prev, co, weight_blend); } @@ -669,9 +669,9 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, if (vgroup && vgroup[0] && use_vgroups) { Mesh *me = target->data; - int index = defgroup_name_index(target, vgroup); + const int defgrp_index = defgroup_name_index(target, vgroup); - if (index != -1 && (me->dvert || dm)) { + if (defgrp_index != -1 && (me->dvert || dm)) { MDeformVert *dvert = me->dvert; float vec[3]; float weight; @@ -681,7 +681,7 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, dvert = me->dvert; for (a = 0; a < numVerts; a++, dvert++) { if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT); - weight = defvert_find_weight(dvert, index); + weight = defvert_find_weight(dvert, defgrp_index); if (weight > 0.0f) { mul_m4_v3(cd.curvespace, vertexCos[a]); @@ -699,7 +699,7 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, for (a = 0; a < numVerts; a++, dvert++) { if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT); - if (defvert_find_weight(dvert, index) > 0.0f) { + if (defvert_find_weight(dvert, defgrp_index) > 0.0f) { mul_m4_v3(cd.curvespace, vertexCos[a]); minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]); } @@ -709,7 +709,7 @@ void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, for (a = 0; a < numVerts; a++, dvert++) { if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT); - weight = defvert_find_weight(dvert, index); + weight = defvert_find_weight(dvert, defgrp_index); if (weight > 0.0f) { /* already in 'cd.curvespace', prev for loop */ @@ -815,16 +815,16 @@ void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm, if (vgroup && vgroup[0] && use_vgroups) { Mesh *me = target->data; - int index = defgroup_name_index(target, vgroup); + const int defgrp_index = defgroup_name_index(target, vgroup); float weight; - if (index >= 0 && (me->dvert || dm)) { + if (defgrp_index >= 0 && (me->dvert || dm)) { MDeformVert *dvert = me->dvert; for (a = 0; a < numVerts; a++, dvert++) { if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT); - weight = defvert_find_weight(dvert, index); + weight = defvert_find_weight(dvert, defgrp_index); if (weight > 0.0f) calc_latt_deform(laOb, vertexCos[a], weight * fac); @@ -879,9 +879,10 @@ void outside_lattice(Lattice *lt) for (v = 0; v < lt->pntsv; v++) { for (u = 0; u < lt->pntsu; u++, bp++) { - if (u == 0 || v == 0 || w == 0 || u == lt->pntsu - 1 || v == lt->pntsv - 1 || w == lt->pntsw - 1) ; + if (u == 0 || v == 0 || w == 0 || u == lt->pntsu - 1 || v == lt->pntsv - 1 || w == lt->pntsw - 1) { + /* pass */ + } else { - bp->hide = 1; bp->f1 &= ~SELECT; diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 45364f5aafa..942e71b5052 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -796,6 +796,18 @@ static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata } } +void BKE_libblock_free_data(ID *id) +{ + Main *bmain = G.main; /* should eventually be an arg */ + + if (id->properties) { + IDP_FreeProperty(id->properties); + MEM_freeN(id->properties); + } + + /* this ID may be a driver target! */ + BKE_animdata_main_cb(bmain, animdata_dtar_clear_cb, (void *)id); +} /* used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c */ void BKE_libblock_free(ListBase *lb, void *idv) @@ -904,15 +916,9 @@ void BKE_libblock_free(ListBase *lb, void *idv) break; } - if (id->properties) { - IDP_FreeProperty(id->properties); - MEM_freeN(id->properties); - } - BLI_remlink(lb, id); - /* this ID may be a driver target! */ - BKE_animdata_main_cb(bmain, animdata_dtar_clear_cb, (void *)id); + BKE_libblock_free_data(id); MEM_freeN(id); } @@ -1200,7 +1206,7 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name) char left[MAX_ID_NAME + 8], leftest[MAX_ID_NAME + 8]; /* make sure input name is terminated properly */ - /* if ( strlen(name) > MAX_ID_NAME-3 ) name[MAX_ID_NAME-3]= 0; */ + /* if ( strlen(name) > MAX_ID_NAME-3 ) name[MAX_ID_NAME-3] = 0; */ /* removed since this is only ever called from one place - campbell */ while (1) { @@ -1547,7 +1553,7 @@ void rename_id(ID *id, const char *name) BLI_strncpy(id->name + 2, name, sizeof(id->name) - 2); lb = which_libbase(G.main, GS(id->name) ); - new_id(lb, id, name); + new_id(lb, id, name); } void name_uiprefix_id(char *name, ID *id) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 3564071334c..b7f4c4bd61e 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -378,8 +378,8 @@ float BKE_mask_spline_project_co(MaskSpline *spline, MaskSplinePoint *point, if (len_squared_v2(v1) > proj_eps_squared) { ang1 = angle_v2v2(v1, n1); - if (ang1 > M_PI / 2.0f) - ang1 = M_PI - ang1; + if (ang1 > (float)M_PI / 2.0f) + ang1 = (float)M_PI - ang1; if (ang < 0.0f || ang1 < ang) { ang = ang1; @@ -405,8 +405,8 @@ float BKE_mask_spline_project_co(MaskSpline *spline, MaskSplinePoint *point, if (len_squared_v2(v2) > proj_eps_squared) { ang2 = angle_v2v2(v2, n2); - if (ang2 > M_PI / 2.0f) - ang2 = M_PI - ang2; + if (ang2 > (float)M_PI / 2.0f) + ang2 = (float)M_PI - ang2; if (ang2 < ang) { ang = ang2; @@ -555,7 +555,7 @@ float BKE_mask_point_weight_scalar(MaskSpline *spline, MaskSplinePoint *point, c if (!bezt_next) { return bezt->weight; } - else if (u <= 0.0) { + else if (u <= 0.0f) { return bezt->weight; } else if (u >= 1.0f) { @@ -576,7 +576,7 @@ float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, const fl if (!bezt_next) { return bezt->weight; } - else if (u <= 0.0) { + else if (u <= 0.0f) { return bezt->weight; } else if (u >= 1.0f) { @@ -916,19 +916,6 @@ void BKE_mask_free_nolib(Mask *mask) BKE_mask_layer_free_list(&mask->masklayers); } - -static void ntree_unlink_mask_cb(void *calldata, struct ID *UNUSED(owner_id), struct bNodeTree *ntree) -{ - ID *id = (ID *)calldata; - bNode *node; - - for (node = ntree->nodes.first; node; node = node->next) { - if (node->id == id) { - node->id = NULL; - } - } -} - void BKE_mask_free(Main *bmain, Mask *mask) { bScreen *scr; @@ -975,21 +962,11 @@ void BKE_mask_free(Main *bmain, Mask *mask) } SEQ_END } - - - if (scene->nodetree) { - bNode *node; - for (node = scene->nodetree->nodes.first; node; node = node->next) { - if (node->id == &mask->id) { - node->id = NULL; - } - } - } } { bNodeTreeType *treetype = ntreeGetType(NTREE_COMPOSIT); - treetype->foreach_nodetree(bmain, (void *)mask, &ntree_unlink_mask_cb); + treetype->foreach_nodetree(bmain, (void *)mask, &BKE_node_tree_unlink_id_cb); } /* free mask data */ @@ -1548,7 +1525,7 @@ void BKE_mask_parent_init(MaskParent *parent) } -/* *** own animation/shapekey implimentation *** +/* *** own animation/shapekey implementation *** * BKE_mask_layer_shape_XXX */ int BKE_mask_layer_shape_totvert(MaskLayer *masklay) @@ -1828,7 +1805,7 @@ static void interp_weights_uv_v2_calc(float r_uv[2], const float pt[2], const fl float pt_on_line[2]; r_uv[0] = closest_to_line_v2(pt_on_line, pt, pt_a, pt_b); r_uv[1] = (len_v2v2(pt_on_line, pt) / len_v2v2(pt_a, pt_b)) * - ((line_point_side_v2(pt_a, pt_b, pt) < 0.0f) ? -1.0 : 1.0); /* this line only sets the sign */ + ((line_point_side_v2(pt_a, pt_b, pt) < 0.0f) ? -1.0f : 1.0f); /* this line only sets the sign */ } @@ -1978,5 +1955,5 @@ void BKE_mask_layer_shape_changed_remove(MaskLayer *masklay, int index, int coun int BKE_mask_get_duration(Mask *mask) { - return maxi(1, mask->efra - mask->sfra); + return max_ii(1, mask->efra - mask->sfra); } diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c index 4a8601df0b8..e67df9c6419 100644 --- a/source/blender/blenkernel/intern/mask_evaluate.c +++ b/source/blender/blenkernel/intern/mask_evaluate.c @@ -69,7 +69,7 @@ unsigned int BKE_mask_spline_resolution(MaskSpline *spline, int width, int heigh unsigned int i, resol = 1; if (width != 0 && height != 0) { - max_segment = 1.0f / (float)maxi(width, height); + max_segment = 1.0f / (float)max_ii(width, height); } for (i = 0; i < spline->tot_point; i++) { @@ -131,7 +131,7 @@ unsigned int BKE_mask_spline_feather_resolution(MaskSpline *spline, int width, i if (u_diff > FLT_EPSILON) { float jump = fabsf(w_diff / u_diff); - max_jump = MAX2(max_jump, jump); + max_jump = max_ff(max_jump, jump); } prev_u = point->uw[j].u; @@ -418,7 +418,7 @@ void BKE_mask_spline_feather_collapse_inner_loops(MaskSpline *spline, float (*fe max_delta = MAX2(max_delta_x, max_delta_y); - buckets_per_side = MIN2(512, 0.9f / max_delta); + buckets_per_side = min_ii(512, 0.9f / max_delta); if (buckets_per_side == 0) { /* happens when some segment fills the whole bounding box across some of dimension */ diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 00898b0fe10..88393fab79c 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -104,7 +104,7 @@ /* for debugging add... */ #ifndef NDEBUG -/* printf("%u %u %u %u\n", _t[0], _t[1], _t[2], _t[3]); \ */ +/* printf("%u %u %u %u\n", _t[0], _t[1], _t[2], _t[3]); \ */ # define FACE_ASSERT(face, vert_max) \ { \ unsigned int *_t = face; \ @@ -410,8 +410,8 @@ static void layer_bucket_init(MaskRasterLayer *layer, const float pixel_size) { MemArena *arena = BLI_memarena_new(1 << 16, __func__); - const float bucket_dim_x = BLI_RCT_SIZE_X(&layer->bounds); - const float bucket_dim_y = BLI_RCT_SIZE_Y(&layer->bounds); + const float bucket_dim_x = BLI_rctf_size_x(&layer->bounds); + const float bucket_dim_y = BLI_rctf_size_y(&layer->bounds); layer->buckets_x = (bucket_dim_x / pixel_size) / (float)BUCKET_PIXELS_PER_CELL; layer->buckets_y = (bucket_dim_y / pixel_size) / (float)BUCKET_PIXELS_PER_CELL; @@ -428,7 +428,7 @@ static void layer_bucket_init(MaskRasterLayer *layer, const float pixel_size) /* width and height of each bucket */ const float bucket_size_x = (bucket_dim_x + FLT_EPSILON) / layer->buckets_x; const float bucket_size_y = (bucket_dim_y + FLT_EPSILON) / layer->buckets_y; - const float bucket_max_rad = (maxf(bucket_size_x, bucket_size_y) * M_SQRT2) + FLT_EPSILON; + const float bucket_max_rad = (max_ff(bucket_size_x, bucket_size_y) * (float)M_SQRT2) + FLT_EPSILON; const float bucket_max_rad_squared = bucket_max_rad * bucket_max_rad; unsigned int *face = &layer->face_array[0][0]; @@ -451,10 +451,10 @@ static void layer_bucket_init(MaskRasterLayer *layer, const float pixel_size) const float *v2 = cos[face[1]]; const float *v3 = cos[face[2]]; - xmin = minf(v1[0], minf(v2[0], v3[0])); - xmax = maxf(v1[0], maxf(v2[0], v3[0])); - ymin = minf(v1[1], minf(v2[1], v3[1])); - ymax = maxf(v1[1], maxf(v2[1], v3[1])); + xmin = min_ff(v1[0], min_ff(v2[0], v3[0])); + xmax = max_ff(v1[0], max_ff(v2[0], v3[0])); + ymin = min_ff(v1[1], min_ff(v2[1], v3[1])); + ymax = max_ff(v1[1], max_ff(v2[1], v3[1])); } else { const float *v1 = cos[face[0]]; @@ -462,10 +462,10 @@ static void layer_bucket_init(MaskRasterLayer *layer, const float pixel_size) const float *v3 = cos[face[2]]; const float *v4 = cos[face[3]]; - xmin = minf(v1[0], minf(v2[0], minf(v3[0], v4[0]))); - xmax = maxf(v1[0], maxf(v2[0], maxf(v3[0], v4[0]))); - ymin = minf(v1[1], minf(v2[1], minf(v3[1], v4[1]))); - ymax = maxf(v1[1], maxf(v2[1], maxf(v3[1], v4[1]))); + xmin = min_ff(v1[0], min_ff(v2[0], min_ff(v3[0], v4[0]))); + xmax = max_ff(v1[0], max_ff(v2[0], max_ff(v3[0], v4[0]))); + ymin = min_ff(v1[1], min_ff(v2[1], min_ff(v3[1], v4[1]))); + ymax = max_ff(v1[1], max_ff(v2[1], max_ff(v3[1], v4[1]))); } @@ -503,7 +503,7 @@ static void layer_bucket_init(MaskRasterLayer *layer, const float pixel_size) BLI_assert(bucket_index < bucket_tot); /* check if the bucket intersects with the face */ - /* note: there is a tradeoff here since checking box/tri intersections isn't + /* note: there is a trade off here since checking box/tri intersections isn't * as optimal as it could be, but checking pixels against faces they will never intersect * with is likely the greater slowdown here - so check if the cell intersects the face */ if (layer_bucket_isect_test(layer, face_index, @@ -560,7 +560,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas const short do_feather) { const rctf default_bounds = {0.0f, 1.0f, 0.0f, 1.0f}; - const float pixel_size = 1.0f / MIN2(width, height); + const float pixel_size = 1.0f / (float)min_ii(width, height); const float asp_xy[2] = {(do_aspect_correct && width > height) ? (float)height / (float)width : 1.0f, (do_aspect_correct && width < height) ? (float)width / (float)height : 1.0f}; @@ -1208,7 +1208,7 @@ static float maskrasterize_layer_isect(unsigned int *face, float (*cos)[3], cons /* needs work */ #if 1 - /* quad check fails for bowtie, so keep using 2 tri checks */ + /* quad check fails for bow-tie, so keep using 2 tri checks */ //if (isect_point_quad_v2(xy, cos[face[0]], cos[face[1]], cos[face[2]], cos[face[3]])) if (isect_point_tri_v2(xy, cos[face[0]], cos[face[1]], cos[face[2]]) || isect_point_tri_v2(xy, cos[face[0]], cos[face[2]], cos[face[3]])) @@ -1216,7 +1216,7 @@ static float maskrasterize_layer_isect(unsigned int *face, float (*cos)[3], cons return maskrasterize_layer_z_depth_quad(xy, cos[face[0]], cos[face[1]], cos[face[2]], cos[face[3]]); } #elif 1 - /* don't use isect_point_tri_v2_cw because we could have bowtie quads */ + /* don't use isect_point_tri_v2_cw because we could have bow-tie quads */ if (isect_point_tri_v2(xy, cos[face[0]], cos[face[1]], cos[face[2]])) { return maskrasterize_layer_z_depth_tri(xy, cos[face[0]], cos[face[1]], cos[face[2]]); @@ -1335,10 +1335,10 @@ float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float x value -= value_layer; break; case MASK_BLEND_LIGHTEN: - value = maxf(value, value_layer); + value = max_ff(value, value_layer); break; case MASK_BLEND_DARKEN: - value = minf(value, value_layer); + value = min_ff(value, value_layer); break; case MASK_BLEND_MUL: value *= value_layer; diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 7523c59a879..ea317956255 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -38,6 +38,7 @@ #include "DNA_anim_types.h" #include "DNA_curve_types.h" +#include "DNA_group_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -214,7 +215,7 @@ Material *BKE_material_add(const char *name) init_material(ma); - return ma; + return ma; } /* XXX keep synced with next function */ @@ -903,7 +904,7 @@ short find_material_index(Object *ob, Material *ma) break; if (a < *totcolp) return a + 1; - return 0; + return 0; } int object_add_material_slot(Object *ob) @@ -941,7 +942,7 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb) if (ma->texco & (TEXCO_ORCO | TEXCO_REFL | TEXCO_NORM | TEXCO_STRAND | TEXCO_STRESS)) needuv = 1; else if (ma->texco & (TEXCO_GLOB | TEXCO_UV | TEXCO_OBJECT | TEXCO_SPEED)) needuv = 1; - else if (ma->texco & (TEXCO_LAVECTOR | TEXCO_VIEW | TEXCO_STICKY)) needuv = 1; + else if (ma->texco & (TEXCO_LAVECTOR | TEXCO_VIEW)) needuv = 1; if ((ma->mapto & MAP_NORM) && (mtex->normapspace == MTEX_NSPACE_TANGENT)) needtang = 1; @@ -969,7 +970,7 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb) ma->ambr = ma->amb * amb[0]; ma->ambg = ma->amb * amb[1]; ma->ambb = ma->amb * amb[2]; - } + } /* will become or-ed result of all node modes */ ma->mode_l = ma->mode; ma->mode_l &= ~MA_SHLESS; @@ -980,6 +981,17 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb) /* parses the geom+tex nodes */ if (ma->nodetree && ma->use_nodes) ntreeShaderGetTexcoMode(ma->nodetree, r_mode, &ma->texco, &ma->mode_l); + + /* local group override */ + if ((ma->shade_flag & MA_GROUP_LOCAL) && ma->id.lib && ma->group && ma->group->id.lib) { + Group *group; + + for (group = G.main->group.first; group; group = group->id.next) { + if (!group->id.lib && strcmp(group->id.name, ma->group->id.name) == 0) { + ma->group = group; + } + } + } } static void init_render_nodetree(bNodeTree *ntree, Material *basemat, int r_mode, float *amb) @@ -1147,7 +1159,7 @@ void material_drivers_update(Scene *scene, Material *ma, float ctime) /* ****************** */ #if 0 /* UNUSED */ -static char colname_array[125][20]= { +static char colname_array[125][20] = { "Black", "DarkRed", "HalfRed", "Red", "Red", "DarkGreen", "DarkOlive", "Brown", "Chocolate", "OrangeRed", "HalfGreen", "GreenOlive", "DryOlive", "Goldenrod", "DarkOrange", @@ -1327,9 +1339,9 @@ void ramp_blend(int type, float r_col[3], const float fac, const float col[3]) r_col[2] = facm * (r_col[2]) + fac * (r_col[2]) / col[2]; break; case MA_RAMP_DIFF: - r_col[0] = facm * (r_col[0]) + fac *fabsf(r_col[0] - col[0]); - r_col[1] = facm * (r_col[1]) + fac *fabsf(r_col[1] - col[1]); - r_col[2] = facm * (r_col[2]) + fac *fabsf(r_col[2] - col[2]); + r_col[0] = facm * (r_col[0]) + fac * fabsf(r_col[0] - col[0]); + r_col[1] = facm * (r_col[1]) + fac * fabsf(r_col[1] - col[1]); + r_col[2] = facm * (r_col[2]) + fac * fabsf(r_col[2] - col[2]); break; case MA_RAMP_DARK: tmp = col[0] + ((1 - col[0]) * facm); @@ -1490,7 +1502,7 @@ void ramp_blend(int type, float r_col[3], const float fac, const float col[3]) } /** - * \brief copy/paste buffer, if we had a propper py api that would be better + * \brief copy/paste buffer, if we had a proper py api that would be better * \note matcopybuf.nodetree does _NOT_ use ID's * \todo matcopybuf.nodetree's node->id's are NOT validated, this will crash! */ @@ -1603,7 +1615,7 @@ static int encode_tfaceflag(MTFace *tf, int convertall) /* calculate the flag */ int flag = tf->mode; - /* options that change the material offline render */ + /* options that change the material offline render */ if (!convertall) { flag &= ~TF_OBCOL; } @@ -1627,7 +1639,7 @@ static int encode_tfaceflag(MTFace *tf, int convertall) /* set the material options based in the tface flag */ static void decode_tfaceflag(Material *ma, int flag, int convertall) { - int alphablend; + int alphablend; GameSettings *game = &ma->game; /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */ @@ -1786,13 +1798,13 @@ static short convert_tfacenomaterial(Main *main, Mesh *me, MTFace *tf, int flag) * for now store the flag into the material and change light/tex/collision * store the flag as a negative number */ ma->game.flag = -flag; - id_us_min((ID *)ma); + id_us_min((ID *)ma); } else printf("Error: Unable to create Material \"%s\" for Mesh \"%s\".", idname + 2, me->id.name + 2); } /* set as converted, no need to go bad to this face */ - tf->mode |= TF_CONVERTED; + tf->mode |= TF_CONVERTED; return mat_nr; } @@ -1845,7 +1857,7 @@ static void convert_tfacematerial(Main *main, Material *ma) if (mat_new) { /* rename the material*/ strcpy(mat_new->id.name, idname); - id_us_min((ID *)mat_new); + id_us_min((ID *)mat_new); mat_nr = mesh_addmaterial(me, mat_new); decode_tfaceflag(mat_new, flag, 1); @@ -2033,7 +2045,7 @@ int do_version_tface(Main *main, int fileload) nowarning = 0; } else - convert_tfacematerial(main, ma); continue; + convert_tfacematerial(main, ma); continue; } /* no conflicts in this material - 90% of cases diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 3925c3cc858..805e77cf84f 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -186,7 +186,7 @@ void BKE_mball_unlink(MetaBall *mb) /* do not free mball itself */ void BKE_mball_free(MetaBall *mb) { - BKE_mball_unlink(mb); + BKE_mball_unlink(mb); if (mb->adt) { BKE_free_animdata((ID *)mb); @@ -562,7 +562,7 @@ Object *BKE_mball_basis_find(Scene *scene, Object *basis) basis = ob; basisnr = obnr; } - } + } } } @@ -691,7 +691,7 @@ static float densfunc(MetaElem *ball, float x, float y, float z) /* *** end deprecated *** */ } - dist2 = 1.0f - (len_v3(dvec) / ball->rad2); + dist2 = 1.0f - (len_squared_v3(dvec) / ball->rad2); if ((ball->flag & MB_NEGATIVE) == 0) { return (dist2 < 0.0f) ? -0.5f : (ball->s * dist2 * dist2 * dist2) - 0.5f; @@ -732,7 +732,7 @@ static octal_node *find_metaball_octal_node(octal_node *node, float x, float y, return find_metaball_octal_node(node->nodes[2], x, y, z, depth--); else return node; - } + } } } else { @@ -762,7 +762,7 @@ static octal_node *find_metaball_octal_node(octal_node *node, float x, float y, return find_metaball_octal_node(node->nodes[6], x, y, z, depth--); else return node; - } + } } } @@ -861,7 +861,7 @@ static void *new_pgn_element(int size) } BLI_freelistN(&lb); - return NULL; + return NULL; } size = 4 * ( (size + 3) / 4); @@ -1319,12 +1319,16 @@ static void addtovertices(VERTICES *vertices, VERTEX v) static void vnormal(const float point[3], PROCESS *p, float r_no[3]) { - float delta = 0.2f * p->delta; - float f = p->function(point[0], point[1], point[2]); + const float delta = 0.2f * p->delta; + const float f = p->function(point[0], point[1], point[2]); r_no[0] = p->function(point[0] + delta, point[1], point[2]) - f; r_no[1] = p->function(point[0], point[1] + delta, point[2]) - f; r_no[2] = p->function(point[0], point[1], point[2] + delta) - f; + +#if 1 + normalize_v3(r_no); +#else f = normalize_v3(r_no); if (0) { @@ -1343,6 +1347,7 @@ static void vnormal(const float point[3], PROCESS *p, float r_no[3]) normalize_v3(r_no); } } +#endif } @@ -1500,7 +1505,7 @@ static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) float f = 0.0f; ml = G_mb.mainb[a]; - f = 1.0 - (mb->thresh / ml->s); + f = 1.0f - (mb->thresh / ml->s); /* Skip, when Stiffness of MetaElement is too small ... MetaElement can't be * visible alone ... but still can influence others MetaElements :-) */ @@ -1628,7 +1633,7 @@ static void polygonize(PROCESS *mbproc, MetaBall *mb) for (a = 0; a < G_mb.totelem; a++) { /* try to find 8 points on the surface for each MetaElem */ - find_first_points(mbproc, mb, a); + find_first_points(mbproc, mb, a); } /* polygonize all MetaElems of current MetaBall */ @@ -2038,7 +2043,7 @@ static void subdivide_metaball_octal_node(octal_node *node, float size_x, float } - /* ml belongs to the (4)5th node too */ + /* ml belongs to the (4)5th node too */ if (ml->bb->vec[6][2] >= z) { fill_metaball_octal_node(node, ml, 4); } @@ -2226,7 +2231,7 @@ static void init_metaball_octal_tree(int depth) } } - /* size of first node */ + /* size of first node */ size[0] = node->x_max - node->x_min; size[1] = node->y_max - node->y_min; size[2] = node->z_max - node->z_min; @@ -2388,7 +2393,7 @@ int BKE_mball_center_bounds(MetaBall *mb, float r_cent[3]) return 0; } -void BKE_mball_translate(MetaBall *mb, float offset[3]) +void BKE_mball_translate(MetaBall *mb, const float offset[3]) { MetaElem *ml; @@ -2396,3 +2401,32 @@ void BKE_mball_translate(MetaBall *mb, float offset[3]) add_v3_v3(&ml->x, offset); } } + +/* *** select funcs *** */ +void BKE_mball_select_all(struct MetaBall *mb) +{ + MetaElem *ml; + + for (ml = mb->editelems->first; ml; ml = ml->next) { + ml->flag |= SELECT; + } +} + +void BKE_mball_deselect_all(MetaBall *mb) +{ + MetaElem *ml; + + for (ml = mb->editelems->first; ml; ml = ml->next) { + ml->flag &= ~SELECT; + } +} + +void BKE_mball_select_swap(struct MetaBall *mb) +{ + MetaElem *ml; + + for (ml = mb->editelems->first; ml; ml = ml->next) { + ml->flag ^= SELECT; + } +} + diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 8c3ec7e2e40..6d44473583f 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -367,7 +367,6 @@ void mesh_update_customdata_pointers(Mesh *me, const short do_ensure_tess_cd) me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT); me->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT); - me->msticky = CustomData_get_layer(&me->vdata, CD_MSTICKY); me->medge = CustomData_get_layer(&me->edata, CD_MEDGE); @@ -470,15 +469,17 @@ void free_dverts(MDeformVert *dvert, int totvert) static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata) { - if (free_customdata) + if (free_customdata) { CustomData_free(&mesh->fdata, mesh->totface); + } + else { + CustomData_reset(&mesh->fdata); + } mesh->mface = NULL; mesh->mtface = NULL; mesh->mcol = NULL; mesh->totface = 0; - - memset(&mesh->fdata, 0, sizeof(mesh->fdata)); } Mesh *BKE_mesh_add(const char *name) @@ -492,7 +493,13 @@ Mesh *BKE_mesh_add(const char *name) me->texflag = ME_AUTOSPACE; me->flag = ME_TWOSIDED; me->drawflag = ME_DRAWEDGES | ME_DRAWFACES | ME_DRAWCREASES; - + + CustomData_reset(&me->vdata); + CustomData_reset(&me->edata); + CustomData_reset(&me->fdata); + CustomData_reset(&me->pdata); + CustomData_reset(&me->ldata); + return me; } @@ -577,7 +584,7 @@ static void expand_local_mesh(Mesh *me) for (i = 0; i < me->pdata.totlayer; i++) { if (me->pdata.layers[i].type == CD_MTEXPOLY) { - MTexPoly *txface = (MTexPoly *)me->fdata.layers[i].data; + MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data; for (a = 0; a < me->totpoly; a++, txface++) { /* special case: ima always local immediately */ @@ -736,7 +743,7 @@ float *BKE_mesh_orco_verts_get(Object *ob) /* Get appropriate vertex coordinates */ vcos = MEM_callocN(sizeof(*vcos) * me->totvert, "orco mesh"); mvert = tme->mvert; - totvert = MIN2(tme->totvert, me->totvert); + totvert = min_ii(tme->totvert, me->totvert); for (a = 0; a < totvert; a++, mvert++) { copy_v3_v3(vcos[a], mvert->co); @@ -789,7 +796,7 @@ int test_index_face(MFace *mface, CustomData *fdata, int mfindex, int nr) nr--; } - /* check corrupt cases, bowtie geometry, cant handle these because edge data wont exist so just return 0 */ + /* check corrupt cases, bow-tie geometry, cant handle these because edge data wont exist so just return 0 */ if (nr == 3) { if ( /* real edges */ @@ -1865,7 +1872,7 @@ void BKE_mesh_calc_normals_mapping_ex(MVert *mverts, int numVerts, /* only calc poly normals */ mp = mpolys; for (i = 0; i < numPolys; i++, mp++) { - mesh_calc_poly_normal(mp, mloop + mp->loopstart, mverts, pnors[i]); + BKE_mesh_calc_poly_normal(mp, mloop + mp->loopstart, mverts, pnors[i]); } } @@ -1915,7 +1922,7 @@ void BKE_mesh_calc_normals(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpo mp = mpolys; for (i = 0; i < numPolys; i++, mp++) { - mesh_calc_poly_normal(mp, mloop + mp->loopstart, mverts, pnors[i]); + BKE_mesh_calc_poly_normal(mp, mloop + mp->loopstart, mverts, pnors[i]); ml = mloop + mp->loopstart; BLI_array_empty(vertcos); @@ -1944,8 +1951,9 @@ void BKE_mesh_calc_normals(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpo MVert *mv = &mverts[i]; float *no = tnorms[i]; - if (normalize_v3(no) == 0.0f) + if (UNLIKELY(normalize_v3(no) == 0.0f)) { normalize_v3_v3(no, mv->co); + } normal_float_to_short_v3(mv->no, no); } @@ -1981,8 +1989,9 @@ void BKE_mesh_calc_normals_tessface(MVert *mverts, int numVerts, MFace *mfaces, MVert *mv = &mverts[i]; float *no = tnorms[i]; - if (normalize_v3(no) == 0.0f) + if (UNLIKELY(normalize_v3(no) == 0.0f)) { normalize_v3_v3(no, mv->co); + } normal_float_to_short_v3(mv->no, no); } @@ -2038,11 +2047,11 @@ static void bm_corners_to_loops_ex(ID *id, CustomData *fdata, CustomData *ldata, MDisps *ld = CustomData_get(ldata, loopstart, CD_MDISPS); MDisps *fd = CustomData_get(fdata, findex, CD_MDISPS); float (*disps)[3] = fd->disps; - int i, tot = mf->v4 ? 4 : 3; + int tot = mf->v4 ? 4 : 3; int side, corners; if (CustomData_external_test(fdata, CD_MDISPS)) { - if (id) { + if (id && fdata->external) { CustomData_external_add(ldata, id, CD_MDISPS, totloop, fdata->external->filename); } @@ -2124,8 +2133,6 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, CustomData *fdata, CustomData /* just in case some of these layers are filled in (can happen with python created meshes) */ CustomData_free(ldata, totloop_i); CustomData_free(pdata, totpoly_i); - memset(ldata, 0, sizeof(*ldata)); - memset(pdata, 0, sizeof(*pdata)); totpoly = totface_i; mpoly = MEM_callocN(sizeof(MPoly) * totpoly, "mpoly converted"); @@ -2162,7 +2169,7 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, CustomData *fdata, CustomData me->flag &= ~ME_FGON; } - polyindex = CustomData_get_layer(fdata, CD_POLYINDEX); + polyindex = CustomData_get_layer(fdata, CD_ORIGINDEX); j = 0; /* current loop index */ ml = mloop; @@ -2504,12 +2511,9 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, ScanFillContext sf_ctx; ScanFillVert *sf_vert, *sf_vert_last, *sf_vert_first; ScanFillFace *sf_tri; - int *mface_orig_index = NULL; - BLI_array_declare(mface_orig_index); int *mface_to_poly_map = NULL; BLI_array_declare(mface_to_poly_map); int lindex[4]; /* only ever use 3 in this case */ - int *poly_orig_index; int poly_index, j, mface_index; const int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY); @@ -2527,7 +2531,6 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, mface_index = 0; mp = mpoly; - poly_orig_index = CustomData_get_layer(pdata, CD_ORIGINDEX); for (poly_index = 0; poly_index < totpoly; poly_index++, mp++) { if (mp->totloop < 3) { /* do nothing */ @@ -2547,10 +2550,6 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, mf->v4 = 0; \ mf->mat_nr = mp->mat_nr; \ mf->flag = mp->flag; \ - if (poly_orig_index) { \ - BLI_array_append(mface_orig_index, \ - poly_orig_index[poly_index]); \ - } \ (void)0 /* ALMOST IDENTICAL TO DEFINE ABOVE (see EXCEPTION) */ @@ -2566,10 +2565,6 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, mf->v4 = mp->loopstart + 3; /* EXCEPTION */ \ mf->mat_nr = mp->mat_nr; \ mf->flag = mp->flag; \ - if (poly_orig_index) { \ - BLI_array_append(mface_orig_index, \ - poly_orig_index[poly_index]); \ - } \ mf->edcode |= TESSFACE_IS_QUAD; /* EXCEPTION */ \ (void)0 @@ -2616,9 +2611,6 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, if (totfilltri) { BLI_array_grow_items(mface_to_poly_map, totfilltri); BLI_array_grow_items(mface, totfilltri); - if (poly_orig_index) { - BLI_array_grow_items(mface_orig_index, totfilltri); - } for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next, mf++) { mface_to_poly_map[mface_index] = poly_index; @@ -2637,10 +2629,6 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, mf->edcode |= TESSFACE_SCANFILL; /* tag for sorting loop indices */ #endif - if (poly_orig_index) { - mface_orig_index[mface_index] = poly_orig_index[poly_index]; - } - mface_index++; } } @@ -2650,7 +2638,6 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, } CustomData_free(fdata, totface); - memset(fdata, 0, sizeof(CustomData)); totface = mface_index; @@ -2658,23 +2645,13 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, if (LIKELY((MEM_allocN_len(mface) / sizeof(*mface)) != totface)) { mface = MEM_reallocN(mface, sizeof(*mface) * totface); mface_to_poly_map = MEM_reallocN(mface_to_poly_map, sizeof(*mface_to_poly_map) * totface); - if (mface_orig_index) { - mface_orig_index = MEM_reallocN(mface_orig_index, sizeof(*mface_orig_index) * totface); - } } CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mface, totface); - /* CD_POLYINDEX will contain an array of indices from tessfaces to the polygons + /* CD_ORIGINDEX will contain an array of indices from tessfaces to the polygons * they are directly tessellated from */ - CustomData_add_layer(fdata, CD_POLYINDEX, CD_ASSIGN, mface_to_poly_map, totface); - if (mface_orig_index) { - /* If polys had a CD_ORIGINDEX layer, then the tessellated faces will get this - * layer as well, pointing to polys from the original mesh (not the polys - * that just got tessellated) */ - CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, mface_orig_index, totface); - } - + CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, mface_to_poly_map, totface); CustomData_from_bmeshpoly(fdata, pdata, ldata, totface); if (do_face_nor_cpy) { @@ -2805,7 +2782,6 @@ int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata, } CustomData_free(fdata, totface); - memset(fdata, 0, sizeof(CustomData)); totface = k; @@ -2899,8 +2875,8 @@ static void mesh_calc_ngon_normal(MPoly *mpoly, MLoop *loopstart, } } -void mesh_calc_poly_normal(MPoly *mpoly, MLoop *loopstart, - MVert *mvarray, float no[3]) +void BKE_mesh_calc_poly_normal(MPoly *mpoly, MLoop *loopstart, + MVert *mvarray, float no[3]) { if (mpoly->totloop > 4) { mesh_calc_ngon_normal(mpoly, loopstart, mvarray, no); @@ -3015,7 +2991,7 @@ void BKE_mesh_calc_poly_center(MPoly *mpoly, MLoop *loopstart, /* note, passing polynormal is only a speedup so we can skip calculating it */ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart, - MVert *mvarray, float polynormal[3]) + MVert *mvarray, const float polynormal[3]) { if (mpoly->totloop == 3) { return area_tri_v3(mvarray[loopstart[0].v].co, @@ -3034,7 +3010,7 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart, int i; MLoop *l_iter = loopstart; float area, polynorm_local[3], (*vertexcos)[3]; - float *no = polynormal ? polynormal : polynorm_local; + const float *no = polynormal ? polynormal : polynorm_local; BLI_array_fixedstack_declare(vertexcos, BM_NGON_STACK_SIZE, mpoly->totloop, __func__); /* pack vertex cos into an array for area_poly_v3 */ @@ -3044,7 +3020,7 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart, /* need normal for area_poly_v3 as well */ if (polynormal == NULL) { - mesh_calc_poly_normal(mpoly, loopstart, mvarray, no); + BKE_mesh_calc_poly_normal(mpoly, loopstart, mvarray, polynorm_local); } /* finally calculate the area */ @@ -3174,6 +3150,32 @@ int BKE_mesh_center_bounds(Mesh *me, float cent[3]) return 0; } +int BKE_mesh_center_centroid(Mesh *me, float cent[3]) +{ + int i = me->totpoly; + MPoly *mpoly; + float poly_area; + float total_area = 0.0f; + float poly_cent[3]; + + zero_v3(cent); + + /* calculate a weighted average of polygon centroids */ + for (mpoly = me->mpoly; i--; mpoly++) { + BKE_mesh_calc_poly_center(mpoly, me->mloop + mpoly->loopstart, me->mvert, poly_cent); + poly_area = BKE_mesh_calc_poly_area(mpoly, me->mloop + mpoly->loopstart, me->mvert, NULL); + + madd_v3_v3fl(cent, poly_cent, poly_area); + total_area += poly_area; + } + /* otherwise we get NAN for 0 polys */ + if (me->totpoly) { + mul_v3_fl(cent, 1.0f / total_area); + } + + return (me->totpoly != 0); +} + void BKE_mesh_translate(Mesh *me, float offset[3], int do_keys) { int i = me->totvert; diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index 79e3fc19d20..128b9ae242e 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -228,7 +228,6 @@ int BKE_mesh_validate_arrays(Mesh *mesh, } for (i = 1; i < totvert; i++, mv++) { - int j; int fix_normal = TRUE; for (j = 0; j < 3; j++) { @@ -717,7 +716,6 @@ int BKE_mesh_validate_arrays(Mesh *mesh, MDeformVert *dv; for (i = 0, dv = dverts; i < totvert; i++, dv++) { MDeformWeight *dw; - unsigned int j; for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) { /* note, greater then max defgroups is accounted for in our code, but not < 0 */ @@ -914,7 +912,7 @@ void BKE_mesh_calc_edges(Mesh *mesh, int update) { CustomData edata; EdgeHashIterator *ehi; - MPoly *mp = mesh->mpoly; + MPoly *mp; MEdge *med, *med_orig; EdgeHash *eh = BLI_edgehash_new(); int i, totedge, totpoly = mesh->totpoly; @@ -932,7 +930,7 @@ void BKE_mesh_calc_edges(Mesh *mesh, int update) } /* mesh loops (bmesh only) */ - for (i = 0; i < totpoly; i++, mp++) { + for (mp = mesh->mpoly, i = 0; i < totpoly; mp++, i++) { MLoop *l = &mesh->mloop[mp->loopstart]; int j, l_prev = (l + (mp->totloop - 1))->v; for (j = 0; j < mp->totloop; j++, l++) { @@ -946,7 +944,7 @@ void BKE_mesh_calc_edges(Mesh *mesh, int update) totedge = BLI_edgehash_size(eh); /* write new edges into a temporary CustomData */ - memset(&edata, 0, sizeof(edata)); + CustomData_reset(&edata); CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge); med = CustomData_get_layer(&edata, CD_MEDGE); @@ -970,8 +968,7 @@ void BKE_mesh_calc_edges(Mesh *mesh, int update) if (mesh->totpoly) { /* second pass, iterate through all loops again and assign * the newly created edges to them. */ - MPoly *mp = mesh->mpoly; - for (i = 0; i < mesh->totpoly; i++, mp++) { + for (mp = mesh->mpoly, i = 0; i < mesh->totpoly; mp++, i++) { MLoop *l = &mesh->mloop[mp->loopstart]; MLoop *l_prev = (l + (mp->totloop - 1)); int j; diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 65538e5bea2..9c7cbc42bdd 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -55,6 +55,8 @@ #include "BLI_linklist.h" #include "BLI_string.h" +#include "BLF_translation.h" + #include "BKE_cloth.h" #include "BKE_key.h" #include "BKE_multires.h" @@ -259,12 +261,13 @@ int modifier_nonGeometrical(ModifierData *md) return (mti->type == eModifierTypeType_NonGeometrical); } -void modifier_setError(ModifierData *md, const char *format, ...) +void modifier_setError(ModifierData *md, const char *_format, ...) { char buffer[512]; va_list ap; + const char *format = TIP_(_format); - va_start(ap, format); + va_start(ap, _format); vsnprintf(buffer, sizeof(buffer), format, ap); va_end(ap); buffer[sizeof(buffer) - 1] = '\0'; @@ -482,7 +485,7 @@ ModifierData *modifiers_getVirtualModifierList(Object *ob) } /* shape key modifier, not yet for curves */ - if (ELEM(ob->type, OB_MESH, OB_LATTICE) && ob_get_key(ob)) { + if (ELEM(ob->type, OB_MESH, OB_LATTICE) && BKE_key_from_object(ob)) { if (ob->type == OB_MESH && (ob->shapeflag & OB_SHAPE_EDIT_MODE)) smd.modifier.mode |= eModifierMode_Editmode | eModifierMode_OnCage; else @@ -494,8 +497,8 @@ ModifierData *modifiers_getVirtualModifierList(Object *ob) return md; } -/* Takes an object and returns its first selected armature, else just its - * armature + +/* Takes an object and returns its first selected armature, else just its armature * This should work for multiple armatures per object */ Object *modifiers_isDeformedByArmature(Object *ob) @@ -518,9 +521,8 @@ Object *modifiers_isDeformedByArmature(Object *ob) return NULL; } -/* Takes an object and returns its first selected lattice, else just its - * lattice - * This should work for multiple lattics per object +/* Takes an object and returns its first selected lattice, else just its lattice + * This should work for multiple lattices per object */ Object *modifiers_isDeformedByLattice(Object *ob) { @@ -542,7 +544,28 @@ Object *modifiers_isDeformedByLattice(Object *ob) return NULL; } - +/* Takes an object and returns its first selected curve, else just its curve + * This should work for multiple curves per object + */ +Object *modifiers_isDeformedByCurve(Object *ob) +{ + ModifierData *md = modifiers_getVirtualModifierList(ob); + CurveModifierData *cmd = NULL; + + /* return the first selected curve, this lets us use multiple curves */ + for (; md; md = md->next) { + if (md->type == eModifierType_Curve) { + cmd = (CurveModifierData *) md; + if (cmd->object && (cmd->object->flag & SELECT)) + return cmd->object; + } + } + + if (cmd) /* if were still here then return the last curve */ + return cmd->object; + + return NULL; +} int modifiers_usesArmature(Object *ob, bArmature *arm) { @@ -574,10 +597,12 @@ int modifiers_isCorrectableDeformed(Object *ob) ModifierData *md = modifiers_getVirtualModifierList(ob); for (; md; md = md->next) { - if (ob->mode == OB_MODE_EDIT && (md->mode & eModifierMode_Editmode) == 0) ; - else - if (modifier_isCorrectableDeformed(md)) + if (ob->mode == OB_MODE_EDIT && (md->mode & eModifierMode_Editmode) == 0) { + /* pass */ + } + else if (modifier_isCorrectableDeformed(md)) { return 1; + } } return 0; } diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c index 72c3cda9272..98eac9b95af 100644 --- a/source/blender/blenkernel/intern/modifiers_bmesh.c +++ b/source/blender/blenkernel/intern/modifiers_bmesh.c @@ -49,12 +49,13 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) MLoop *mloop, *ml; BMVert *v, **vtable, **verts = NULL; BMEdge *e, **etable, **edges = NULL; - float has_face_normals; + float (*face_normals)[3]; BMFace *f; BMIter liter; BLI_array_declare(verts); BLI_array_declare(edges); int i, j, k, totvert, totedge /* , totface */ /* UNUSED */ ; + int is_init = (bm->totvert == 0) && (bm->totedge == 0) && (bm->totface == 0); /*merge custom data layout*/ CustomData_bmesh_merge(&dm->vertData, &bm->vdata, CD_MASK_DERIVEDMESH, CD_CALLOC, bm, BM_VERT); @@ -72,8 +73,8 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) BM_data_layer_add(bm, &bm->edata, CD_BWEIGHT); BM_data_layer_add(bm, &bm->vdata, CD_BWEIGHT); - vtable = MEM_callocN(sizeof(void **) * totvert, "vert table in BMDM_Copy"); - etable = MEM_callocN(sizeof(void **) * totedge, "edge table in BMDM_Copy"); + vtable = MEM_callocN(sizeof(void **) * totvert, __func__); + etable = MEM_callocN(sizeof(void **) * totedge, __func__); /*do verts*/ mv = mvert = dm->dupVertArray(dm); @@ -81,6 +82,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) v = BM_vert_create(bm, mv->co, NULL); normal_short_to_float_v3(v->no, mv->no); v->head.hflag = BM_vert_flag_from_mflag(mv->flag); + BM_elem_index_set(v, i); /* set_inline */ CustomData_to_bmesh_block(&dm->vertData, &bm->vdata, i, &v->head.data); @@ -89,13 +91,16 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) vtable[i] = v; } MEM_freeN(mvert); + if (is_init) bm->elem_index_dirty &= ~BM_VERT; /*do edges*/ me = medge = dm->dupEdgeArray(dm); for (i = 0; i < totedge; i++, me++) { + //BLI_assert(BM_edge_exists(vtable[me->v1], vtable[me->v2]) == NULL); e = BM_edge_create(bm, vtable[me->v1], vtable[me->v2], NULL, FALSE); e->head.hflag = BM_edge_flag_from_mflag(me->flag); + BM_elem_index_set(e, i); /* set_inline */ CustomData_to_bmesh_block(&dm->edgeData, &bm->edata, i, &e->head.data); etable[i] = e; @@ -106,11 +111,13 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) BM_elem_float_data_set(&bm->edata, e, CD_BWEIGHT, (float)me->bweight / 255.0f); } MEM_freeN(medge); + if (is_init) bm->elem_index_dirty &= ~BM_EDGE; - /*do faces*/ + /* do faces */ + /* note: i_alt is aligned with bmesh faces which may not always align with mpolys */ mp = dm->getPolyArray(dm); mloop = dm->getLoopArray(dm); - has_face_normals = CustomData_has_layer(&dm->polyData, CD_NORMAL); + face_normals = CustomData_get_layer(&dm->polyData, CD_NORMAL); /* can be NULL */ for (i = 0; i < dm->numPolyData; i++, mp++) { BMLoop *l; @@ -129,10 +136,12 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) f = BM_face_create_ngon(bm, verts[0], verts[1], edges, mp->totloop, FALSE); - if (!f) + if (UNLIKELY(f == NULL)) { continue; + } f->head.hflag = BM_face_flag_from_mflag(mp->flag); + BM_elem_index_set(f, bm->totface - 1); /* set_inline */ f->mat_nr = mp->mat_nr; l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f); @@ -143,13 +152,14 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) CustomData_to_bmesh_block(&dm->polyData, &bm->pdata, i, &f->head.data); - if (has_face_normals) { - float *fno; - - fno = CustomData_bmesh_get(&bm->pdata, &f->head.data, CD_NORMAL); - copy_v3_v3(f->no, fno); + if (face_normals) { + copy_v3_v3(f->no, face_normals[i]); + } + else { + BM_face_normal_update(f); } } + if (is_init) bm->elem_index_dirty &= ~BM_FACE; MEM_freeN(vtable); MEM_freeN(etable); diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 97d4c150b84..6e8f2697ee1 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -52,6 +52,7 @@ #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_movieclip_types.h" +#include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_view3d_types.h" @@ -71,6 +72,7 @@ #include "BKE_global.h" #include "BKE_main.h" #include "BKE_movieclip.h" +#include "BKE_node.h" #include "BKE_image.h" /* openanim */ #include "BKE_tracking.h" @@ -292,11 +294,11 @@ static void movieclip_calc_length(MovieClip *clip) clip->len = framenr + 1; } else { - for (;; ) { + for (;;) { get_sequence_fname(clip, framenr, name); if (!BLI_exists(name)) { - clip->len = framenr + 1; + clip->len = framenr; break; } @@ -518,6 +520,24 @@ static void movieclip_load_get_szie(MovieClip *clip) } } +static void detect_clip_source(MovieClip *clip) +{ + ImBuf *ibuf; + char name[FILE_MAX]; + + BLI_strncpy(name, clip->name, sizeof(name)); + BLI_path_abs(name, G.main->name); + + ibuf = IMB_testiffname(name, IB_rect | IB_multilayer); + if (ibuf) { + clip->source = MCLIP_SRC_SEQUENCE; + IMB_freeImBuf(ibuf); + } + else { + clip->source = MCLIP_SRC_MOVIE; + } +} + /* checks if image was already loaded, then returns same image * otherwise creates new. * does not load ibuf itself @@ -563,10 +583,7 @@ MovieClip *BKE_movieclip_file_add(const char *name) clip = movieclip_alloc(libname); BLI_strncpy(clip->name, name, sizeof(clip->name)); - if (BLI_testextensie_array(name, imb_ext_movie)) - clip->source = MCLIP_SRC_MOVIE; - else - clip->source = MCLIP_SRC_SEQUENCE; + detect_clip_source(clip); movieclip_load_get_szie(clip); if (clip->lastsize[0]) { @@ -614,34 +631,27 @@ static ImBuf *get_undistorted_ibuf(MovieClip *clip, struct MovieDistortion *dist else undistibuf = BKE_tracking_undistort_frame(&clip->tracking, ibuf, ibuf->x, ibuf->y, 0.0f); - if (undistibuf->userflags & IB_RECT_INVALID) { - ibuf->userflags &= ~IB_RECT_INVALID; - IMB_rect_from_float(undistibuf); - } - IMB_scaleImBuf(undistibuf, ibuf->x, ibuf->y); return undistibuf; } -static int need_undistortion_postprocess(MovieClipUser *user, int flag) +static int need_undistortion_postprocess(MovieClipUser *user) { int result = 0; /* only full undistorted render can be used as on-fly undistorting image */ - if (flag & MCLIP_USE_PROXY) { - result |= (user->render_size == MCLIP_PROXY_RENDER_SIZE_FULL) && - (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0; - } + result |= (user->render_size == MCLIP_PROXY_RENDER_SIZE_FULL) && + (user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0; return result; } -static int need_postprocessed_frame(MovieClipUser *user, int flag, int postprocess_flag) +static int need_postprocessed_frame(MovieClipUser *user, int postprocess_flag) { int result = postprocess_flag; - result |= need_undistortion_postprocess(user, flag); + result |= need_undistortion_postprocess(user); return result; } @@ -688,7 +698,7 @@ static ImBuf *get_postprocessed_cached_frame(MovieClip *clip, MovieClipUser *use if (cache->postprocessed.flag != postprocess_flag) return NULL; - if (need_undistortion_postprocess(user, flag)) { + if (need_undistortion_postprocess(user)) { if (!check_undistortion_cache_flags(clip)) return NULL; } @@ -719,7 +729,7 @@ static ImBuf *put_postprocessed_frame_to_cache(MovieClip *clip, MovieClipUser *u cache->postprocessed.render_flag = 0; } - if (need_undistortion_postprocess(user, flag)) { + if (need_undistortion_postprocess(user)) { copy_v2_v2(cache->postprocessed.principal, camera->principal); copy_v3_v3(&cache->postprocessed.k1, &camera->k1); cache->postprocessed.undistortion_used = TRUE; @@ -763,7 +773,7 @@ static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *u BLI_lock_thread(LOCK_MOVIECLIP); /* try to obtain cached postprocessed frame first */ - if (need_postprocessed_frame(user, flag, postprocess_flag)) { + if (need_postprocessed_frame(user, postprocess_flag)) { ibuf = get_postprocessed_cached_frame(clip, user, flag, postprocess_flag); if (!ibuf) @@ -1087,15 +1097,24 @@ void BKE_movieclip_reload(MovieClip *clip) clip->tracking.stabilization.ok = FALSE; /* update clip source */ - if (BLI_testextensie_array(clip->name, imb_ext_movie)) - clip->source = MCLIP_SRC_MOVIE; - else - clip->source = MCLIP_SRC_SEQUENCE; + detect_clip_source(clip); clip->lastsize[0] = clip->lastsize[1] = 0; movieclip_load_get_szie(clip); movieclip_calc_length(clip); + + /* same as for image update -- don't use notifiers because they are not 100% sure to succeeded + * (node trees which are not currently visible wouldn't be refreshed) + */ + { + Scene *scene; + for (scene = G.main->scene.first; scene; scene = scene->id.next) { + if (scene->nodetree) { + nodeUpdateID(scene->nodetree, &clip->id); + } + } + } } void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClipScopes *scopes) @@ -1326,6 +1345,11 @@ void BKE_movieclip_unlink(Main *bmain, MovieClip *clip) } } + { + bNodeTreeType *treetype = ntreeGetType(NTREE_COMPOSIT); + treetype->foreach_nodetree(bmain, (void *)clip, &BKE_node_tree_unlink_id_cb); + } + clip->id.us = 0; } diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 1c06d95a70b..66f2ff12258 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -666,7 +666,9 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl) mdisp->totdisp = totdisp; mdisp->level = lvl; - multires_grid_paint_mask_downsample(&gpm[g], lvl); + if (gpm) { + multires_grid_paint_mask_downsample(&gpm[g], lvl); + } } } } @@ -893,15 +895,16 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl CCGKey highGridKey, lowGridKey; CCGSubSurf *ss; int i, numGrids, highGridSize; + int has_mask = CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK); /* create subsurf DM from original mesh at high level */ cddm = CDDM_from_mesh(me, NULL); DM_set_only_copy(cddm, CD_MASK_BAREMESH); - highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, TRUE); + highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, has_mask); ss = ((CCGDerivedMesh *)highdm)->ss; /* create multires DM from original mesh at low level */ - lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple, TRUE); + lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple, has_mask); cddm->release(cddm); /* copy subsurf grids and replace them with low displaced grids */ @@ -1042,7 +1045,7 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm k = 0; /*current loop/mdisp index within the mloop array*/ - #pragma omp parallel for private(i) if (totloop*gridSize*gridSize >= CCG_OMP_LIMIT) + #pragma omp parallel for private(i) if (totloop * gridSize * gridSize >= CCG_OMP_LIMIT) for (i = 0; i < totpoly; ++i) { const int numVerts = mpoly[i].totloop; @@ -1158,23 +1161,23 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm) int totlvl = ccgdm->multires.totlvl; if (lvl < totlvl) { - Mesh *me = ob->data; DerivedMesh *lowdm, *cddm, *highdm; CCGElem **highGridData, **lowGridData, **subGridData, **gridData, *diffGrid; CCGKey highGridKey, lowGridKey; CCGSubSurf *ss; int i, j, numGrids, highGridSize, lowGridSize; + int has_mask = CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK); /* create subsurf DM from original mesh at high level */ if (ob->derivedDeform) cddm = CDDM_copy(ob->derivedDeform); else cddm = CDDM_from_mesh(me, NULL); DM_set_only_copy(cddm, CD_MASK_BAREMESH); - highdm = subsurf_dm_create_local(ob, cddm, totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, TRUE); + highdm = subsurf_dm_create_local(ob, cddm, totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, has_mask); ss = ((CCGDerivedMesh *)highdm)->ss; /* create multires DM from original mesh and displacements */ - lowdm = multires_dm_create_local(ob, cddm, lvl, totlvl, mmd->simple, TRUE); + lowdm = multires_dm_create_local(ob, cddm, lvl, totlvl, mmd->simple, has_mask); cddm->release(cddm); /* gather grid data */ @@ -1226,12 +1229,13 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm) } else { DerivedMesh *cddm, *subdm; + int has_mask = CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK); if (ob->derivedDeform) cddm = CDDM_copy(ob->derivedDeform); else cddm = CDDM_from_mesh(me, NULL); DM_set_only_copy(cddm, CD_MASK_BAREMESH); - subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, TRUE); + subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, has_mask); cddm->release(cddm); multiresModifier_disp_run(dm, me, NULL, CALC_DISPLACEMENTS, subdm->getGridData(subdm), mmd->totlvl); @@ -1321,7 +1325,7 @@ void multires_set_space(DerivedMesh *dm, Object *ob, int from, int to) k = 0; /*current loop/mdisp index within the mloop array*/ - //#pragma omp parallel for private(i) if (dm->numLoopData*gridSize*gridSize >= CCG_OMP_LIMIT) + //#pragma omp parallel for private(i) if (dm->numLoopData * gridSize * gridSize >= CCG_OMP_LIMIT) for (i = 0; i < dm->numPolyData; ++i) { const int numVerts = mpoly[i].totloop; @@ -1626,7 +1630,7 @@ void multires_free(Multires *mr) } while (lvl) { - multires_free_level(lvl); + multires_free_level(lvl); lvl = lvl->next; } @@ -2081,8 +2085,8 @@ void multires_load_old(Object *ob, Mesh *me) CustomData_add_layer(&me->vdata, l->type, CD_REFERENCE, l->data, me->totvert); for (i = 0, l = me->mr->fdata.layers; i < me->mr->fdata.totlayer; ++i, ++l) CustomData_add_layer(&me->fdata, l->type, CD_REFERENCE, l->data, me->totface); - memset(&me->mr->vdata, 0, sizeof(CustomData)); - memset(&me->mr->fdata, 0, sizeof(CustomData)); + CustomData_reset(&me->mr->vdata); + CustomData_reset(&me->mr->fdata); multires_load_old_vcols(me); multires_load_old_face_flags(me); @@ -2107,7 +2111,7 @@ void multires_load_old(Object *ob, Mesh *me) * reference subsurfed dm with this option, before calling multiresModifier_disp_run(), * which implicitly expects both subsurfs from its first dm and oldGridData parameters to * be of the same "format"! */ - dm = multires_make_derived_from_derived(orig, mmd, ob, MULTIRES_ALLOC_PAINT_MASK); + dm = multires_make_derived_from_derived(orig, mmd, ob, 0); multires_load_old_dm(dm, me, mmd->totlvl + 1); @@ -2196,7 +2200,7 @@ static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3]) dGridSize = multires_side_tot[high_mmd.totlvl]; dSkip = (dGridSize - 1) / (gridSize - 1); - #pragma omp parallel for private(i) if (me->totface*gridSize*gridSize*4 >= CCG_OMP_LIMIT) + #pragma omp parallel for private(i) if (me->totface * gridSize * gridSize * 4 >= CCG_OMP_LIMIT) for (i = 0; i < me->totpoly; ++i) { const int numVerts = mpoly[i].totloop; MDisps *mdisp = &mdisps[mpoly[i].loopstart]; diff --git a/source/blender/blenkernel/intern/navmesh_conversion.c b/source/blender/blenkernel/intern/navmesh_conversion.c index a21878d1d7d..3bf5f863557 100644 --- a/source/blender/blenkernel/intern/navmesh_conversion.c +++ b/source/blender/blenkernel/intern/navmesh_conversion.c @@ -36,44 +36,44 @@ #include "DNA_meshdata_types.h" -#include "BKE_navmesh_conversion.h" -#include "BKE_cdderivedmesh.h" - #include "BLI_utildefines.h" #include "BLI_math.h" +#include "BKE_navmesh_conversion.h" +#include "BKE_cdderivedmesh.h" + #include "recast-capi.h" -BLI_INLINE float area2(const float* a, const float* b, const float* c) +BLI_INLINE float area2(const float *a, const float *b, const float *c) { return (b[0] - a[0]) * (c[2] - a[2]) - (c[0] - a[0]) * (b[2] - a[2]); } -BLI_INLINE int left(const float* a, const float* b, const float* c) +BLI_INLINE int left(const float *a, const float *b, const float *c) { return area2(a, b, c) < 0; } -int polyNumVerts(const unsigned short* p, const int vertsPerPoly) +int polyNumVerts(const unsigned short *p, const int vertsPerPoly) { int i, nv = 0; - for (i=0; i 0) + if (d > 0.0f) t /= d; - if (t < 0) - t = 0; - else if (t > 1) - t = 1; - dx[0] = a[0] + t*abx[0] - point[0]; - dx[2] = a[2] + t*abx[2] - point[2]; + if (t < 0.0f) + t = 0.0f; + else if (t > 1.0f) + t = 1.0f; + dx[0] = a[0] + t * abx[0] - point[0]; + dx[2] = a[2] + t * abx[2] - point[2]; - return dx[0]*dx[0] + dx[2]*dx[2]; + return dx[0] * dx[0] + dx[2] * dx[2]; } -int buildRawVertIndicesData(DerivedMesh* dm, int *nverts_r, float **verts_r, - int *ntris_r, unsigned short **tris_r, int **trisToFacesMap_r, - int **recastData) +int buildRawVertIndicesData(DerivedMesh *dm, int *nverts_r, float **verts_r, + int *ntris_r, unsigned short **tris_r, int **trisToFacesMap_r, + int **recastData) { int vi, fi, triIdx; int nverts, ntris; @@ -117,49 +118,49 @@ int buildRawVertIndicesData(DerivedMesh* dm, int *nverts_r, float **verts_r, MFace *faces; nverts = dm->getNumVerts(dm); - if (nverts>=0xffff) { + if (nverts >= 0xffff) { printf("Converting navmesh: Error! Too many vertices. Max number of vertices %d\n", 0xffff); return 0; } - verts = MEM_callocN(sizeof(float)*3*nverts, "buildRawVertIndicesData verts"); + verts = MEM_callocN(sizeof(float) * 3 * nverts, "buildRawVertIndicesData verts"); dm->getVertCos(dm, (float(*)[3])verts); - //flip coordinates - for (vi=0; vigetNumTessFaces(dm); faces = dm->getTessFaceArray(dm); ntris = nfaces; - for (fi=0; fiv4) ntris++; } - //copy and transform to triangles (reorder on the run) - trisToFacesMap = MEM_callocN(sizeof(int)*ntris, "buildRawVertIndicesData trisToFacesMap"); - tris = MEM_callocN(sizeof(unsigned short)*3*ntris, "buildRawVertIndicesData tris"); + /* copy and transform to triangles (reorder on the run) */ + trisToFacesMap = MEM_callocN(sizeof(int) * ntris, "buildRawVertIndicesData trisToFacesMap"); + tris = MEM_callocN(sizeof(unsigned short) * 3 * ntris, "buildRawVertIndicesData tris"); tri = tris; triIdx = 0; - for (fi=0; fiv1; - tri[3*triIdx+1] = (unsigned short) face->v3; - tri[3*triIdx+2] = (unsigned short) face->v2; - trisToFacesMap[triIdx++]=fi; + for (fi = 0; fi < nfaces; fi++) { + MFace *face = &faces[fi]; + tri[3 * triIdx + 0] = (unsigned short) face->v1; + tri[3 * triIdx + 1] = (unsigned short) face->v3; + tri[3 * triIdx + 2] = (unsigned short) face->v2; + trisToFacesMap[triIdx++] = fi; if (face->v4) { - tri[3*triIdx+0] = (unsigned short) face->v1; - tri[3*triIdx+1] = (unsigned short) face->v4; - tri[3*triIdx+2] = (unsigned short) face->v3; - trisToFacesMap[triIdx++]=fi; + tri[3 * triIdx + 0] = (unsigned short) face->v1; + tri[3 * triIdx + 1] = (unsigned short) face->v4; + tri[3 * triIdx + 2] = (unsigned short) face->v3; + trisToFacesMap[triIdx++] = fi; } } - //carefully, recast data is just reference to data in derived mesh - *recastData = (int*)CustomData_get_layer(&dm->polyData, CD_RECAST); + /* carefully, recast data is just reference to data in derived mesh */ + *recastData = (int *)CustomData_get_layer(&dm->polyData, CD_RECAST); *nverts_r = nverts; *verts_r = verts; @@ -170,122 +171,122 @@ int buildRawVertIndicesData(DerivedMesh* dm, int *nverts_r, float **verts_r, return 1; } -int buildPolygonsByDetailedMeshes(const int vertsPerPoly, const int npolys, - unsigned short* polys, const unsigned short* dmeshes, - const float* verts, const unsigned short* dtris, - const int* dtrisToPolysMap) +int buildPolygonsByDetailedMeshes(const int vertsPerPoly, const int npolys, + unsigned short *polys, const unsigned short *dmeshes, + const float *verts, const unsigned short *dtris, + const int *dtrisToPolysMap) { int polyidx; int capacity = vertsPerPoly; - unsigned short* newPoly = MEM_callocN(sizeof(unsigned short)*capacity, "buildPolygonsByDetailedMeshes newPoly"); - memset(newPoly, 0xff, sizeof(unsigned short)*capacity); + unsigned short *newPoly = MEM_callocN(sizeof(unsigned short) * capacity, "buildPolygonsByDetailedMeshes newPoly"); + memset(newPoly, 0xff, sizeof(unsigned short) * capacity); - for (polyidx=0; polyidxtolerance) + if (distSq > tolerance) adjustedPoly[adjustedNv++] = cur; } - memcpy(newPoly, adjustedPoly, adjustedNv*sizeof(unsigned short)); + memcpy(newPoly, adjustedPoly, adjustedNv * sizeof(unsigned short)); MEM_freeN(adjustedPoly); nv = adjustedNv; allBorderTraversed = 1; - for (i=0; irecastData[((struct SortContext *)ctx)->trisToFacesMap[*(int*)a]] - - ((struct SortContext *)ctx)->recastData[((struct SortContext *)ctx)->trisToFacesMap[*(int*)b]] ); + return (((struct SortContext *)ctx)->recastData[((struct SortContext *)ctx)->trisToFacesMap[*(int *)a]] - + ((struct SortContext *)ctx)->recastData[((struct SortContext *)ctx)->trisToFacesMap[*(int *)b]]); } -int buildNavMeshData(const int nverts, const float* verts, +int buildNavMeshData(const int nverts, const float *verts, const int ntris, const unsigned short *tris, - const int* recastData, const int* trisToFacesMap, + const int *recastData, const int *trisToFacesMap, int *ndtris_r, unsigned short **dtris_r, int *npolys_r, unsigned short **dmeshes_r, unsigned short **polys_r, int *vertsPerPoly_r, int **dtrisToPolysMap_r, int **dtrisToTrisMap_r) @@ -333,86 +333,86 @@ int buildNavMeshData(const int nverts, const float* verts, return 0; } - trisMapping = MEM_callocN(sizeof(int)*ntris, "buildNavMeshData trisMapping"); + trisMapping = MEM_callocN(sizeof(int) * ntris, "buildNavMeshData trisMapping"); - //sort the triangles by polygon idx - for (i=0; i0) { + for (i = 0; i < ntris; i++) { + if (recastData[trisToFacesMap[trisMapping[i]]] > 0) { validTriStart = i; break; } } - if (validTriStart<0) { + if (validTriStart < 0) { printf("Converting navmesh: Error! No valid polygons in mesh\n"); MEM_freeN(trisMapping); return 0; } - ndtris = ntris-validTriStart; - //fill dtris to faces mapping - dtrisToTrisMap = MEM_callocN(sizeof(int)*ndtris, "buildNavMeshData dtrisToTrisMap"); - memcpy(dtrisToTrisMap, &trisMapping[validTriStart], ndtris*sizeof(int)); + ndtris = ntris - validTriStart; + /* fill dtris to faces mapping */ + dtrisToTrisMap = MEM_callocN(sizeof(int) * ndtris, "buildNavMeshData dtrisToTrisMap"); + memcpy(dtrisToTrisMap, &trisMapping[validTriStart], ndtris * sizeof(int)); MEM_freeN(trisMapping); - //create detailed mesh triangles - copy only valid triangles - //and reserve memory for adjacency info - dtris = MEM_callocN(sizeof(unsigned short)*3*2*ndtris, "buildNavMeshData dtris"); - memset(dtris, 0xffff, sizeof(unsigned short)*3*2*ndtris); - for (i=0; iactstart; } else { - /* - the 'fmod(..., actlength*scale)' is needed to get the repeats working + /* - the 'fmod(..., actlength * scale)' is needed to get the repeats working * - the '/ scale' is needed to ensure that scaling influences the timing within the repeat */ return strip->actend - fmodf(cframe - strip->start, actlength * scale) / scale; @@ -446,7 +446,7 @@ static float nlastrip_get_frame_actionclip(NlaStrip *strip, float cframe, short return strip->actend; } else { - /* - the 'fmod(..., actlength*scale)' is needed to get the repeats working + /* - the 'fmod(..., actlength * scale)' is needed to get the repeats working * - the '/ scale' is needed to ensure that scaling influences the timing within the repeat */ return strip->actstart + fmodf(cframe - strip->start, actlength * scale) / scale; @@ -496,7 +496,7 @@ float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode) case NLASTRIP_TYPE_CLIP: /* action-clip (default) */ default: return nlastrip_get_frame_actionclip(strip, cframe, mode); - } + } } @@ -1162,7 +1162,7 @@ static short nlastrip_is_first(AnimData *adt, NlaStrip *strip) if (ns->start < strip->start) return 0; } - } + } /* should be first now */ return 1; @@ -1491,7 +1491,7 @@ void BKE_nla_action_pushdown(AnimData *adt) /* add a new NLA strip to the track, which references the active action */ strip = add_nlastrip_to_stack(adt, adt->action); - /* do other necessary work on strip */ + /* do other necessary work on strip */ if (strip) { /* clear reference to action now that we've pushed it onto the stack */ id_us_min(&adt->action->id); @@ -1545,7 +1545,7 @@ short BKE_nla_tweakmode_enter(AnimData *adt) /* now try to find active strip */ activeStrip = BKE_nlastrip_find_active(nlt); break; - } + } } /* There are situations where we may have multiple strips selected and we want to enter tweakmode on all @@ -1563,7 +1563,7 @@ short BKE_nla_tweakmode_enter(AnimData *adt) activeStrip = BKE_nlastrip_find_active(nlt); break; } - } + } } if ((activeTrack) && (activeStrip == NULL)) { /* no active strip in active or last selected track; compromise for first selected (assuming only single)... */ diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index ade418e409f..153eb5271c5 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -147,6 +147,7 @@ static bNodeSocket *make_socket(bNodeTree *UNUSED(ntree), int in_out, const char sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF); sock->type = type; sock->storage = NULL; + sock->flag |= SOCK_COLLAPSED; sock->default_value = node_socket_make_default_value(type); node_socket_init_default_value(type, sock->default_value); @@ -326,10 +327,13 @@ bNode *nodeAddNode(bNodeTree *ntree, struct bNodeTemplate *ntemp) ntype->initfunc(ntree, node, ntemp); /* initialize the node name with the node label. - * note: do this after the initfunc so nodes get - * their data set which may be used in naming + * note: do this after the initfunc so nodes get their data set which may be used in naming * (node groups for example) */ - BLI_strncpy(node->name, nodeLabel(node), NODE_MAXSTR); + /* XXX Do not use nodeLabel() here, it returns translated content, which should *only* be used + * in UI, *never* in data... + * This solution may be a bit rougher than nodeLabel()'s returned string, but it's simpler + * than adding a "no translate" flag to this func (and labelfunc() as well). */ + BLI_strncpy(node->name, node->typeinfo->name, NODE_MAXSTR); nodeUniqueName(ntree, node); ntree->update |= NTREE_UPDATE_NODES; @@ -343,6 +347,7 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node) { bNode *nnode = MEM_callocN(sizeof(bNode), "dupli node"); bNodeSocket *sock, *oldsock; + bNodeLink *link, *oldlink; *nnode = *node; /* can be called for nodes outside a node tree (e.g. clipboard) */ @@ -382,6 +387,15 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node) sock->cache = NULL; } + BLI_duplicatelist(&nnode->internal_links, &node->internal_links); + oldlink = node->internal_links.first; + for (link = nnode->internal_links.first; link; link = link->next, oldlink = oldlink->next) { + link->fromnode = nnode; + link->tonode = nnode; + link->fromsock = link->fromsock->new_sock; + link->tosock = link->tosock->new_sock; + } + /* don't increase node->id users, freenode doesn't decrement either */ if (node->typeinfo->copystoragefunc) @@ -389,7 +403,17 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node) node->new_node = nnode; nnode->new_node = NULL; - nnode->preview = NULL; + + /* only shader nodes get pleasant preview updating this way, compo uses own system */ + if (node->preview) { + if (ntree->type == NTREE_SHADER) { + nnode->preview = MEM_dupallocN(node->preview); + if (node->preview->rect) + nnode->preview->rect = MEM_dupallocN(node->preview->rect); + } + else + nnode->preview = NULL; + } if (ntree) ntree->update |= NTREE_UPDATE_NODES; @@ -520,15 +544,12 @@ void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock) void nodeInternalRelink(bNodeTree *ntree, bNode *node) { bNodeLink *link, *link_next; - ListBase intlinks; - if (!node->typeinfo->internal_connect) + if (node->internal_links.first == NULL) return; - intlinks = node->typeinfo->internal_connect(ntree, node); - /* store link pointers in output sockets, for efficient lookup */ - for (link = intlinks.first; link; link = link->next) + for (link = node->internal_links.first; link; link = link->next) link->tosock->link = link; /* redirect downstream links */ @@ -562,8 +583,6 @@ void nodeInternalRelink(bNodeTree *ntree, bNode *node) if (link->tonode == node) nodeRemLink(ntree, link); } - - BLI_freelistN(&intlinks); } void nodeToView(bNode *node, float x, float y, float *rx, float *ry) @@ -710,7 +729,7 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_use } node->new_node = NULL; - /* nnode= */ nodeCopyNode(newtree, node); /* sets node->new */ + /* nnode = */ nodeCopyNode(newtree, node); /* sets node->new */ /* make sure we don't copy new nodes again! */ if (node == last) @@ -815,7 +834,7 @@ void nodeFreePreview(bNode *node) MEM_freeN(node->preview->rect); MEM_freeN(node->preview); node->preview = NULL; - } + } } static void node_init_preview(bNode *node, int xsize, int ysize) @@ -858,7 +877,7 @@ void ntreeInitPreview(bNodeTree *ntree, int xsize, int ysize) node_init_preview(node, xsize, ysize); if (node->type == NODE_GROUP && (node->flag & NODE_GROUP_EDIT)) ntreeInitPreview((bNodeTree *)node->id, xsize, ysize); - } + } } static void nodeClearPreview(bNode *node) @@ -880,13 +899,13 @@ void ntreeClearPreview(bNodeTree *ntree) nodeClearPreview(node); if (node->type == NODE_GROUP && (node->flag & NODE_GROUP_EDIT)) ntreeClearPreview((bNodeTree *)node->id); - } + } } /* hack warning! this function is only used for shader previews, and * since it gets called multiple times per pixel for Ztransp we only * add the color once. Preview gets cleared before it starts render though */ -void nodeAddToPreview(bNode *node, float col[4], int x, int y, int do_manage) +void nodeAddToPreview(bNode *node, const float col[4], int x, int y, int do_manage) { bNodePreview *preview = node->preview; if (preview) { @@ -985,6 +1004,8 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node) MEM_freeN(sock); } + BLI_freelistN(&node->internal_links); + nodeFreePreview(node); MEM_freeN(node); @@ -996,6 +1017,7 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node) /* do not free ntree itself here, BKE_libblock_free calls this function too */ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user) { + bNodeTree *tntree; bNode *node, *next; bNodeSocket *sock; @@ -1030,9 +1052,18 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user) next = node->next; /* ntreeUserIncrefID inline */ + + /* XXX, this is correct, however when freeing the entire database + * this ends up accessing freed data which isn't properly unlinking + * its self from scene nodes, SO - for now prefer invalid usercounts + * on free rather then bad memory access - Campbell */ +#if 0 if (do_id_user) { id_us_min(node->id); } +#else + (void)do_id_user; +#endif nodeFreeNode(ntree, node); } @@ -1043,6 +1074,14 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user) for (sock = ntree->outputs.first; sock; sock = sock->next) node_socket_free_default_value(sock->type, sock->default_value); BLI_freelistN(&ntree->outputs); + + /* if ntree is not part of library, free the libblock data explicitly */ + for (tntree = G.main->nodetree.first; tntree; tntree = tntree->id.next) + if (tntree == ntree) + break; + if (tntree == NULL) { + BKE_libblock_free_data(&ntree->id); + } } /* same as ntreeFreeTree_ex but always manage users */ void ntreeFreeTree(bNodeTree *ntree) @@ -1545,11 +1584,11 @@ int BKE_node_clipboard_validate(void) /* lists must be aligned */ BLI_assert(BLI_countlist(&node_clipboard.nodes) == - BLI_countlist(&node_clipboard.nodes_extra_info)); + BLI_countlist(&node_clipboard.nodes_extra_info)); for (node = node_clipboard.nodes.first, node_info = node_clipboard.nodes_extra_info.first; - node; - node = node->next, node_info = node_info->next) + node; + node = node->next, node_info = node_info->next) { /* validate the node against the stored node info */ @@ -1629,21 +1668,21 @@ int BKE_node_clipboard_get_type(void) /* ************** dependency stuff *********** */ /* node is guaranteed to be not checked before */ -static int node_get_deplist_recurs(bNode *node, bNode ***nsort) +static int node_get_deplist_recurs(bNodeTree *ntree, bNode *node, bNode ***nsort) { bNode *fromnode; - bNodeSocket *sock; + bNodeLink *link; int level = 0xFFF; node->done = TRUE; /* check linked nodes */ - for (sock = node->inputs.first; sock; sock = sock->next) { - if (sock->link) { - fromnode = sock->link->fromnode; + for (link = ntree->links.first; link; link = link->next) { + if (link->tonode == node) { + fromnode = link->fromnode; if (fromnode) { if (fromnode->done == 0) - fromnode->level = node_get_deplist_recurs(fromnode, nsort); + fromnode->level = node_get_deplist_recurs(ntree, fromnode, nsort); if (fromnode->level <= level) level = fromnode->level - 1; } @@ -1653,7 +1692,7 @@ static int node_get_deplist_recurs(bNode *node, bNode ***nsort) /* check parent node */ if (node->parent) { if (node->parent->done == 0) - node->parent->level = node_get_deplist_recurs(node->parent, nsort); + node->parent->level = node_get_deplist_recurs(ntree, node->parent, nsort); if (node->parent->level <= level) level = node->parent->level - 1; } @@ -1687,7 +1726,7 @@ void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***deplist, in /* recursive check */ for (node = ntree->nodes.first; node; node = node->next) { if (node->done == 0) { - node->level = node_get_deplist_recurs(node, &nsort); + node->level = node_get_deplist_recurs(ntree, node, &nsort); } } } @@ -1705,7 +1744,7 @@ static void ntree_update_node_level(bNodeTree *ntree) /* recursive check */ for (node = ntree->nodes.first; node; node = node->next) { if (node->done == 0) { - node->level = node_get_deplist_recurs(node, NULL); + node->level = node_get_deplist_recurs(ntree, node, NULL); } } } @@ -1804,6 +1843,8 @@ void ntreeUpdateTree(bNodeTree *ntree) ntreetype->update_node(ntree, node); else if (node->typeinfo->updatefunc) node->typeinfo->updatefunc(ntree, node); + + nodeUpdateInternalLinks(ntree, node); } } @@ -1841,6 +1882,9 @@ void nodeUpdate(bNodeTree *ntree, bNode *node) ntreetype->update_node(ntree, node); else if (node->typeinfo->updatefunc) node->typeinfo->updatefunc(ntree, node); + + nodeUpdateInternalLinks(ntree, node); + /* clear update flag */ node->update = 0; } @@ -1880,9 +1924,21 @@ int nodeUpdateID(bNodeTree *ntree, ID *id) } } + for (node = ntree->nodes.first; node; node = node->next) { + nodeUpdateInternalLinks(ntree, node); + } + return change; } +void nodeUpdateInternalLinks(bNodeTree *ntree, bNode *node) +{ + BLI_freelistN(&node->internal_links); + + if (node->typeinfo && node->typeinfo->update_internal_links) + node->typeinfo->update_internal_links(ntree, node); +} + /* ************* node type access ********** */ @@ -1955,7 +2011,7 @@ void node_type_base(bNodeTreeType *ttype, bNodeType *ntype, int type, const char /* Default muting stuff. */ if (ttype) - ntype->internal_connect = ttype->internal_connect; + ntype->update_internal_links = ttype->update_internal_links; /* default size values */ ntype->width = 140; @@ -2051,9 +2107,9 @@ void node_type_exec_new(struct bNodeType *ntype, ntype->newexecfunc = newexecfunc; } -void node_type_internal_connect(bNodeType *ntype, ListBase (*internal_connect)(bNodeTree *, bNode *)) +void node_type_internal_links(bNodeType *ntype, void (*update_internal_links)(bNodeTree *, bNode *)) { - ntype->internal_connect = internal_connect; + ntype->update_internal_links = update_internal_links; } void node_type_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out)) @@ -2186,6 +2242,7 @@ static void registerCompositNodes(bNodeTreeType *ttype) register_node_type_cmp_bokehimage(ttype); register_node_type_cmp_bokehblur(ttype); register_node_type_cmp_switch(ttype); + register_node_type_cmp_pixelate(ttype); register_node_type_cmp_mask(ttype); register_node_type_cmp_trackpos(ttype); @@ -2234,8 +2291,11 @@ static void registerShaderNodes(bNodeTreeType *ttype) register_node_type_sh_layer_weight(ttype); register_node_type_sh_tex_coord(ttype); register_node_type_sh_particle_info(ttype); + register_node_type_sh_bump(ttype); + register_node_type_sh_script(ttype); register_node_type_sh_background(ttype); + register_node_type_sh_bsdf_anisotropic(ttype); register_node_type_sh_bsdf_diffuse(ttype); register_node_type_sh_bsdf_glossy(ttype); register_node_type_sh_bsdf_glass(ttype); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 5ba56a85c72..0611e84bdf3 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -300,11 +300,11 @@ void BKE_object_free(Object *ob) BKE_object_free_display(ob); - /* disconnect specific data */ + /* disconnect specific data, but not for lib data (might be indirect data, can get relinked) */ if (ob->data) { ID *id = ob->data; id->us--; - if (id->us == 0) { + if (id->us == 0 && id->lib == NULL) { switch (ob->type) { case OB_MESH: BKE_mesh_unlink((Mesh *)id); @@ -340,7 +340,7 @@ void BKE_object_free(Object *ob) BKE_pose_free(ob->pose); if (ob->mpath) animviz_free_motionpath(ob->mpath); - free_properties(&ob->prop); + BKE_bproperty_free_list(&ob->prop); BKE_object_free_modifiers(ob); free_sensors(&ob->sensors); @@ -454,7 +454,7 @@ void BKE_object_unlink(Object *ob) if (pchan->custom == ob) pchan->custom = NULL; } - } + } else if (ELEM(OB_MBALL, ob->type, obt->type)) { if (BKE_mball_is_basis_for(obt, ob)) obt->recalc |= OB_RECALC_DATA; @@ -689,8 +689,8 @@ void BKE_object_unlink(Object *ob) if (so->treestore) { TreeStoreElem *tselem = so->treestore->data; - int a; - for (a = 0; a < so->treestore->usedelem; a++, tselem++) { + int i; + for (i = 0; i < so->treestore->usedelem; i++, tselem++) { if (tselem->id == (ID *)ob) tselem->id = NULL; } } @@ -854,7 +854,9 @@ Object *BKE_object_add_only_object(int type, const char *name) ob->step_height = 0.15f; ob->jump_speed = 10.0f; ob->fall_speed = 55.0f; - + ob->col_group = 0x01; + ob->col_mask = 0xff; + /* NT fluid sim defaults */ ob->fluidsimSettings = NULL; @@ -889,23 +891,44 @@ Object *BKE_object_add(struct Scene *scene, int type) return ob; } -SoftBody *copy_softbody(SoftBody *sb) +SoftBody *copy_softbody(SoftBody *sb, int copy_caches) { SoftBody *sbn; if (sb == NULL) return(NULL); sbn = MEM_dupallocN(sb); - sbn->totspring = sbn->totpoint = 0; - sbn->bpoint = NULL; - sbn->bspring = NULL; + + if (copy_caches == FALSE) { + sbn->totspring = sbn->totpoint = 0; + sbn->bpoint = NULL; + sbn->bspring = NULL; + } + else { + sbn->totspring = sb->totspring; + sbn->totpoint = sb->totpoint; + + if (sbn->bpoint) { + int i; + + sbn->bpoint = MEM_dupallocN(sbn->bpoint); + + for (i = 0; i < sbn->totpoint; i++) { + if (sbn->bpoint[i].springs) + sbn->bpoint[i].springs = MEM_dupallocN(sbn->bpoint[i].springs); + } + } + + if (sb->bspring) + sbn->bspring = MEM_dupallocN(sb->bspring); + } sbn->keys = NULL; sbn->totkey = sbn->totpointkey = 0; sbn->scratch = NULL; - sbn->pointcache = BKE_ptcache_copy_list(&sbn->ptcaches, &sb->ptcaches); + sbn->pointcache = BKE_ptcache_copy_list(&sbn->ptcaches, &sb->ptcaches, copy_caches); if (sb->effector_weights) sbn->effector_weights = MEM_dupallocN(sb->effector_weights); @@ -978,7 +1001,7 @@ static ParticleSystem *copy_particlesystem(ParticleSystem *psys) psysn->childcachebufs.first = psysn->childcachebufs.last = NULL; psysn->renderdata = NULL; - psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches); + psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, FALSE); /* XXX - from reading existing code this seems correct but intended usage of * pointcache should /w cloth should be added in 'ParticleSystem' - campbell */ @@ -1039,7 +1062,7 @@ void BKE_object_copy_particlesystems(Object *obn, Object *ob) void BKE_object_copy_softbody(Object *obn, Object *ob) { if (ob->soft) - obn->soft = copy_softbody(ob->soft); + obn->soft = copy_softbody(ob->soft, FALSE); } static void copy_object_pose(Object *obn, Object *ob) @@ -1079,12 +1102,12 @@ static void copy_object_pose(Object *obn, Object *ob) } } -static int object_pose_context(Object *ob) +int BKE_object_pose_context_check(Object *ob) { - if ( (ob) && - (ob->type == OB_ARMATURE) && - (ob->pose) && - (ob->mode & OB_MODE_POSE)) + if ((ob) && + (ob->type == OB_ARMATURE) && + (ob->pose) && + (ob->mode & OB_MODE_POSE)) { return 1; } @@ -1098,12 +1121,12 @@ Object *BKE_object_pose_armature_get(Object *ob) if (ob == NULL) return NULL; - if (object_pose_context(ob)) + if (BKE_object_pose_context_check(ob)) return ob; ob = modifiers_isDeformedByArmature(ob); - if (object_pose_context(ob)) + if (BKE_object_pose_context_check(ob)) return ob; return NULL; @@ -1120,7 +1143,7 @@ void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src) copy_v3_v3(ob_tar->size, ob_src->size); } -Object *BKE_object_copy(Object *ob) +static Object *object_copy_do(Object *ob, int copy_caches) { Object *obn; ModifierData *md; @@ -1147,7 +1170,7 @@ Object *BKE_object_copy(Object *ob) } obn->prop.first = obn->prop.last = NULL; - copy_properties(&obn->prop, &ob->prop); + BKE_bproperty_copy_list(&obn->prop, &ob->prop); copy_sensors(&obn->sensors, &ob->sensors); copy_controllers(&obn->controllers, &ob->controllers); @@ -1181,7 +1204,7 @@ Object *BKE_object_copy(Object *ob) if (obn->pd->rng) obn->pd->rng = MEM_dupallocN(ob->pd->rng); } - obn->soft = copy_softbody(ob->soft); + obn->soft = copy_softbody(ob->soft, copy_caches); obn->bsoft = copy_bulletsoftbody(ob->bsoft); BKE_object_copy_particlesystems(obn, ob); @@ -1197,6 +1220,18 @@ Object *BKE_object_copy(Object *ob) return obn; } +/* copy objects, will re-initialize cached simulation data */ +Object *BKE_object_copy(Object *ob) +{ + return object_copy_do(ob, FALSE); +} + +/* copy objects, will duplicate cached simulation data */ +Object *BKE_object_copy_with_caches(Object *ob) +{ + return object_copy_do(ob, TRUE); +} + static void extern_local_object(Object *ob) { ParticleSystem *psys; @@ -1748,7 +1783,7 @@ static void ob_parbone(Object *ob, Object *par, float mat[][4]) /* Make sure the bone is still valid */ pchan = BKE_pose_channel_find_name(par->pose, ob->parsubstr); - if (!pchan) { + if (!pchan || !pchan->bone) { printf("Object %s with Bone parent: bone %s doesn't exist\n", ob->id.name + 2, ob->parsubstr); unit_m4(mat); return; @@ -1766,7 +1801,6 @@ static void ob_parbone(Object *ob, Object *par, float mat[][4]) static void give_parvert(Object *par, int nr, float vec[3]) { BMEditMesh *em; - int a, count; zero_v3(vec); @@ -1795,18 +1829,28 @@ static void give_parvert(Object *par, int nr, float vec[3]) dm = (em) ? em->derivedFinal : par->derivedFinal; if (dm) { - MVert *mvert = dm->getVertArray(dm); - int *index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX); - int i, vindex, numVerts = dm->getNumVerts(dm); + int count = 0; + int numVerts = dm->getNumVerts(dm); - /* get the average of all verts with (original index == nr) */ - count = 0; - for (i = 0; i < numVerts; i++) { - vindex = (index) ? index[i] : i; + if (nr < numVerts) { + MVert *mvert = dm->getVertArray(dm); + int *index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX); + int i; - if (vindex == nr) { - add_v3_v3(vec, mvert[i].co); - count++; + /* get the average of all verts with (original index == nr) */ + if (index) { + for (i = 0; i < numVerts; i++) { + if (index[i] == nr) { + add_v3_v3(vec, mvert[i].co); + count++; + } + } + } + else { + if (nr < numVerts) { + add_v3_v3(vec, mvert[nr].co); + count++; + } } } @@ -1828,71 +1872,31 @@ static void give_parvert(Object *par, int nr, float vec[3]) } } else if (ELEM(par->type, OB_CURVE, OB_SURF)) { - Nurb *nu; - Curve *cu; - BPoint *bp; - BezTriple *bezt; - int found = 0; - ListBase *nurbs; - - cu = par->data; - nurbs = BKE_curve_nurbs_get(cu); - nu = nurbs->first; - - count = 0; - while (nu && !found) { - if (nu->type == CU_BEZIER) { - bezt = nu->bezt; - a = nu->pntsu; - while (a--) { - if (count == nr) { - found = 1; - copy_v3_v3(vec, bezt->vec[1]); - break; - } - count++; - bezt++; - } - } - else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - while (a--) { - if (count == nr) { - found = 1; - copy_v3_v3(vec, bp->vec); - break; - } - count++; - bp++; - } - } - nu = nu->next; - } + Curve *cu = par->data; + ListBase *nurb = BKE_curve_nurbs_get(cu);; + BKE_nurbList_index_get_co(nurb, nr, vec); } else if (par->type == OB_LATTICE) { - Lattice *latt = par->data; - BPoint *bp; - DispList *dl = BKE_displist_find(&par->disp, DL_VERTS); - float *co = dl ? dl->verts : NULL; - + Lattice *latt = par->data; + DispList *dl = BKE_displist_find(&par->disp, DL_VERTS); + float (*co)[3] = dl ? (float (*)[3])dl->verts : NULL; + int tot; + if (latt->editlatt) latt = latt->editlatt->latt; - - a = latt->pntsu * latt->pntsv * latt->pntsw; - count = 0; - bp = latt->def; - while (a--) { - if (count == nr) { - if (co) - copy_v3_v3(vec, co); - else - copy_v3_v3(vec, bp->vec); - break; + + tot = latt->pntsu * latt->pntsv * latt->pntsw; + + /* ensure dl is correct size */ + BLI_assert(dl == NULL || dl->nr == tot); + + if (nr < tot) { + if (co) { + copy_v3_v3(vec, co[nr]); + } + else { + copy_v3_v3(vec, latt->def[nr].vec); } - count++; - if (co) co += 3; - else bp++; } } } @@ -2259,7 +2263,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const short u Curve *cu = ob->data; /* Use the object bounding box so that modifier output - gets taken into account */ + * gets taken into account */ if (ob->bb) bb = *(ob->bb); else { @@ -2298,11 +2302,9 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const short u bPoseChannel *pchan; for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { - - if ((use_hidden == FALSE) && (PBONE_VISIBLE(arm, pchan->bone) == FALSE)) { - /* pass */ - } - else { + /* XXX pchan->bone may be NULL for duplicated bones, see duplicateEditBoneObjects() comment + * (editarmature.c:2592)... Skip in this case too! */ + if (pchan->bone && !((use_hidden == FALSE) && (PBONE_VISIBLE(arm, pchan->bone) == FALSE))) { mul_v3_m4v3(vec, ob->obmat, pchan->pose_head); minmax_v3v3_v3(min_r, max_r, vec); mul_v3_m4v3(vec, ob->obmat, pchan->pose_tail); @@ -2360,7 +2362,7 @@ int BKE_object_minmax_dupli(Scene *scene, Object *ob, float r_min[3], float r_ma ListBase *lb; DupliObject *dob; - lb = object_duplilist(scene, ob); + lb = object_duplilist(scene, ob, FALSE); for (dob = lb->first; dob; dob = dob->next) { if ((use_hidden == FALSE) && (dob->no_draw != 0)) { /* pass */ @@ -2437,7 +2439,7 @@ void BKE_scene_foreach_display_point( ListBase *lb; DupliObject *dob; - lb = object_duplilist(scene, ob); + lb = object_duplilist(scene, ob, FALSE); for (dob = lb->first; dob; dob = dob->next) { if (dob->no_draw == 0) { BKE_object_foreach_display_point(dob->ob, dob->mat, func_cb, user_data); @@ -2571,9 +2573,7 @@ void BKE_object_handle_update(Scene *scene, Object *ob) if (ob->recalc & OB_RECALC_DATA) { ID *data_id = (ID *)ob->data; AnimData *adt = BKE_animdata_from_id(data_id); - float ctime = (float)scene->r.cfra; // XXX this is bad... - ListBase pidlist; - PTCacheID *pid; + float ctime = (float)scene->r.cfra; /* XXX this is bad... */ if (G.debug & G_DEBUG) printf("recalcdata %s\n", ob->id.name + 2); @@ -2696,26 +2696,8 @@ void BKE_object_handle_update(Scene *scene, Object *ob) psys_get_modifier(ob, psys)->flag &= ~eParticleSystemFlag_psys_updated; } } - - /* check if quick cache is needed */ - BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR); - - for (pid = pidlist.first; pid; pid = pid->next) { - if ((pid->cache->flag & PTCACHE_BAKED) || - (pid->cache->flag & PTCACHE_QUICK_CACHE) == 0) - { - continue; - } - - if (pid->cache->flag & PTCACHE_OUTDATED || (pid->cache->flag & PTCACHE_SIMULATION_VALID) == 0) { - scene->physics_settings.quick_cache_step = - scene->physics_settings.quick_cache_step ? - mini(scene->physics_settings.quick_cache_step, pid->cache->step) : - pid->cache->step; - } - } - - BLI_freelistN(&pidlist); + + /* quick cache removed */ } /* the no-group proxy case, we call update */ @@ -2899,22 +2881,22 @@ static KeyBlock *insert_meshkey(Scene *scene, Object *ob, const char *name, int int newkey = 0; if (key == NULL) { - key = me->key = add_key((ID *)me); + key = me->key = BKE_key_add((ID *)me); key->type = KEY_RELATIVE; newkey = 1; } if (newkey || from_mix == FALSE) { /* create from mesh */ - kb = add_keyblock_ctime(key, name, FALSE); - mesh_to_key(me, kb); + kb = BKE_keyblock_add_ctime(key, name, FALSE); + BKE_key_convert_from_mesh(me, kb); } else { /* copy from current values */ float *data = do_ob_key(scene, ob); /* create new block with prepared data */ - kb = add_keyblock_ctime(key, name, FALSE); + kb = BKE_keyblock_add_ctime(key, name, FALSE); kb->data = data; kb->totelem = me->totvert; } @@ -2930,20 +2912,20 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, int int newkey = 0; if (key == NULL) { - key = lt->key = add_key((ID *)lt); + key = lt->key = BKE_key_add((ID *)lt); key->type = KEY_RELATIVE; newkey = 1; } if (newkey || from_mix == FALSE) { - kb = add_keyblock_ctime(key, name, FALSE); + kb = BKE_keyblock_add_ctime(key, name, FALSE); if (!newkey) { KeyBlock *basekb = (KeyBlock *)key->block.first; kb->data = MEM_dupallocN(basekb->data); kb->totelem = basekb->totelem; } else { - latt_to_key(lt, kb); + BKE_key_convert_from_lattice(lt, kb); } } else { @@ -2951,7 +2933,7 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, int float *data = do_ob_key(scene, ob); /* create new block with prepared data */ - kb = add_keyblock_ctime(key, name, FALSE); + kb = BKE_keyblock_add_ctime(key, name, FALSE); kb->totelem = lt->pntsu * lt->pntsv * lt->pntsw; kb->data = data; } @@ -2968,21 +2950,21 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, int int newkey = 0; if (key == NULL) { - key = cu->key = add_key((ID *)cu); + key = cu->key = BKE_key_add((ID *)cu); key->type = KEY_RELATIVE; newkey = 1; } if (newkey || from_mix == FALSE) { /* create from curve */ - kb = add_keyblock_ctime(key, name, FALSE); + kb = BKE_keyblock_add_ctime(key, name, FALSE); if (!newkey) { KeyBlock *basekb = (KeyBlock *)key->block.first; kb->data = MEM_dupallocN(basekb->data); kb->totelem = basekb->totelem; } else { - curve_to_key(cu, kb, lb); + BKE_key_convert_from_curve(cu, kb, lb); } } else { @@ -2990,7 +2972,7 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, int float *data = do_ob_key(scene, ob); /* create new block with prepared data */ - kb = add_keyblock_ctime(key, name, FALSE); + kb = BKE_keyblock_add_ctime(key, name, FALSE); kb->totelem = BKE_nurbList_verts_count(lb); kb->data = data; } @@ -3020,7 +3002,7 @@ int BKE_object_is_modified(Scene *scene, Object *ob) { int flag = 0; - if (ob_get_key(ob)) { + if (BKE_key_from_object(ob)) { flag |= eModifierMode_Render; } else { diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 4f3921936e8..7bc736d394e 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -475,7 +475,7 @@ void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j) if (oc->_do_normals) { ocr->normal[0] = oc->_N_x[i * oc->_N + j]; - ocr->normal[1] = oc->_N_y /*oc->_N_y[i*oc->_N+j] (MEM01)*/; + ocr->normal[1] = oc->_N_y /* oc->_N_y[i * oc->_N + j] (MEM01) */; ocr->normal[2] = oc->_N_z[i * oc->_N + j]; normalize_v3(ocr->normal); diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 03342d0f6d1..dec49f417ae 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -201,7 +201,7 @@ PackedFile *newPackedFile(ReportList *reports, const char *filename, const char file = BLI_open(name, O_BINARY | O_RDONLY, 0); if (file <= 0) { - BKE_reportf(reports, RPT_ERROR, "Unable to pack file, source path not found: \"%s\"", name); + BKE_reportf(reports, RPT_ERROR, "Unable to pack file, source path '%s' not found", name); } else { filelen = BLI_file_descriptor_size(file); @@ -238,7 +238,8 @@ void packAll(Main *bmain, ReportList *reports) ima->packedfile = newPackedFile(reports, ima->name, ID_BLEND_PATH(bmain, &ima->id)); } else if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) { - BKE_reportf(reports, RPT_WARNING, "Image '%s' skipped, movies and image sequences not supported.", ima->id.name + 2); + BKE_reportf(reports, RPT_WARNING, "Image '%s' skipped, movies and image sequences not supported", + ima->id.name + 2); } } } @@ -310,20 +311,20 @@ int writePackedFile(ReportList *reports, const char *filename, PackedFile *pf, i file = BLI_open(name, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666); if (file >= 0) { if (write(file, pf->data, pf->size) != pf->size) { - BKE_reportf(reports, RPT_ERROR, "Error writing file: %s", name); + BKE_reportf(reports, RPT_ERROR, "Error writing file '%s'", name); ret_value = RET_ERROR; } close(file); } else { - BKE_reportf(reports, RPT_ERROR, "Error creating file: %s", name); + BKE_reportf(reports, RPT_ERROR, "Error creating file '%s'", name); ret_value = RET_ERROR; } if (remove_tmp) { if (ret_value == RET_ERROR) { if (BLI_rename(tempname, name) != 0) { - BKE_reportf(reports, RPT_ERROR, "Error restoring tempfile. Check files: '%s' '%s'", tempname, name); + BKE_reportf(reports, RPT_ERROR, "Error restoring temp file (check files '%s' '%s')", tempname, name); } } else { diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 3267253e744..36f96045ced 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -36,6 +36,7 @@ #include "DNA_meshdata_types.h" #include "DNA_scene_types.h" #include "DNA_brush_types.h" +#include "DNA_space_types.h" #include "BLI_bitmap.h" #include "BLI_utildefines.h" @@ -87,6 +88,7 @@ Paint *paint_get_active(Scene *sce) Paint *paint_get_active_from_context(const bContext *C) { Scene *sce = CTX_data_scene(C); + SpaceImage *sima; if (sce) { ToolSettings *ts = sce->toolsettings; @@ -95,12 +97,12 @@ Paint *paint_get_active_from_context(const bContext *C) if (sce->basact && sce->basact->object) obact = sce->basact->object; - if (CTX_wm_space_image(C) != NULL) { + if ((sima = CTX_wm_space_image(C)) != NULL) { if (obact && obact->mode == OB_MODE_EDIT) { - if (ts->use_uv_sculpt) - return &ts->uvsculpt->paint; - else + if (sima->mode == SI_MODE_PAINT) return &ts->imapaint.paint; + else if (ts->use_uv_sculpt) + return &ts->uvsculpt->paint; } else { return &ts->imapaint.paint; @@ -190,7 +192,7 @@ void BKE_paint_free(Paint *paint) } /* called when copying scene settings, so even if 'src' and 'tar' are the same - * still do a id_us_plus(), rather then if we were copying betweem 2 existing + * still do a id_us_plus(), rather then if we were copying between 2 existing * scenes where a matching value should decrease the existing user count as * with paint_brush_set() */ void BKE_paint_copy(Paint *src, Paint *tar) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 26952db8fba..d645204d29c 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -48,6 +48,7 @@ #include "DNA_dynamicpaint_types.h" #include "BLI_blenlib.h" +#include "BLI_noise.h" #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_kdtree.h" @@ -97,8 +98,8 @@ int count_particles(ParticleSystem *psys) int tot = 0; LOOP_SHOWN_PARTICLES { - if (pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN) == 0) ; - else if (pa->alive == PARS_DEAD && (part->flag & PART_DIED) == 0) ; + if (pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN) == 0) {} + else if (pa->alive == PARS_DEAD && (part->flag & PART_DIED) == 0) {} else tot++; } return tot; @@ -110,13 +111,13 @@ int count_particles_mod(ParticleSystem *psys, int totgr, int cur) int tot = 0; LOOP_SHOWN_PARTICLES { - if (pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN) == 0) ; - else if (pa->alive == PARS_DEAD && (part->flag & PART_DIED) == 0) ; + if (pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN) == 0) {} + else if (pa->alive == PARS_DEAD && (part->flag & PART_DIED) == 0) {} else if (p % totgr == cur) tot++; } return tot; } -/* we allocate path cache memory in chunks instead of a big continguous +/* we allocate path cache memory in chunks instead of a big contiguous * chunk, windows' memory allocater fails to find big blocks of memory often */ #define PATH_CACHE_BUF_SIZE 1024 @@ -335,7 +336,7 @@ void psys_check_group_weights(ParticleSettings *part) BLI_addtail(&part->dupliweights, dw); } - go = go->next; + go = go->next; } dw = part->dupliweights.first; @@ -560,7 +561,7 @@ void psys_free(Object *ob, ParticleSystem *psys) ob->transflag &= ~OB_DUPLIPARTS; if (psys->part) { - psys->part->id.us--; + psys->part->id.us--; psys->part = NULL; } @@ -617,7 +618,10 @@ typedef struct ParticleRenderData { int do_simplify; int timeoffset; ParticleRenderElem *elems; - int *origindex; + + /* ORIGINDEX */ + const int *index_mf_to_mpoly; + const int *index_mp_to_orig; } ParticleRenderData; static float psys_render_viewport_falloff(double rate, float dist, float width) @@ -790,9 +794,13 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) float *facearea, (*facecenter)[3], size[3], fac, powrate, scaleclamp; float co1[3], co2[3], co3[3], co4[3], lambda, arearatio, t, area, viewport; double vprate; - int *origindex, *facetotvert; + int *facetotvert; int a, b, totorigface, totface, newtot, skipped; + /* double lookup */ + const int *index_mf_to_mpoly; + const int *index_mp_to_orig; + if (part->ren_as != PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND)) return tot; if (!ctx->sim.psys->renderdata) @@ -806,13 +814,18 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) mvert = dm->getVertArray(dm); mface = dm->getTessFaceArray(dm); - origindex = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); totface = dm->getNumTessFaces(dm); totorigface = me->totpoly; if (totface == 0 || totorigface == 0) return tot; + index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); + if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { + index_mf_to_mpoly = index_mp_to_orig = NULL; + } + facearea = MEM_callocN(sizeof(float) * totorigface, "SimplifyFaceArea"); facecenter = MEM_callocN(sizeof(float[3]) * totorigface, "SimplifyFaceCenter"); facetotvert = MEM_callocN(sizeof(int) * totorigface, "SimplifyFaceArea"); @@ -823,20 +836,22 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) data->do_simplify = TRUE; data->elems = elems; - data->origindex = origindex; + data->index_mf_to_mpoly = index_mf_to_mpoly; + data->index_mp_to_orig = index_mp_to_orig; /* compute number of children per original face */ for (a = 0; a < tot; a++) { - b = (origindex) ? origindex[ctx->index[a]] : ctx->index[a]; - if (b != -1) + b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a]; + if (b != ORIGINDEX_NONE) { elems[b].totchild++; + } } /* compute areas and centers of original faces */ for (mf = mface, a = 0; a < totface; a++, mf++) { - b = (origindex) ? origindex[a] : a; + b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a; - if (b != -1) { + if (b != ORIGINDEX_NONE) { copy_v3_v3(co1, mvert[mf->v1].co); copy_v3_v3(co2, mvert[mf->v2].co); copy_v3_v3(co3, mvert[mf->v3].co); @@ -898,7 +913,7 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) elem->scalemax = sqrt(elem->scalemax); /* clamp scaling */ - scaleclamp = MIN2(elem->totchild, 10.0f); + scaleclamp = (float)min_ii(elem->totchild, 10); elem->scalemin = MIN2(scaleclamp, elem->scalemin); elem->scalemax = MIN2(scaleclamp, elem->scalemax); @@ -930,8 +945,9 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) skipped = 0; for (a = 0, newtot = 0; a < tot; a++) { - b = (origindex) ? origindex[ctx->index[a]] : ctx->index[a]; - if (b != -1) { + b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a]; + + if (b != ORIGINDEX_NONE) { if (elems[b].curchild++ < ceil(elems[b].lambda * elems[b].totchild)) { ctx->index[newtot] = ctx->index[a]; ctx->skip[newtot] = skipped; @@ -962,10 +978,10 @@ int psys_render_simplify_params(ParticleSystem *psys, ChildParticle *cpa, float data = psys->renderdata; if (!data->do_simplify) return 0; - - b = (data->origindex) ? data->origindex[cpa->num] : cpa->num; - if (b == -1) + b = (data->index_mf_to_mpoly) ? DM_origindex_mface_mpoly(data->index_mf_to_mpoly, data->index_mp_to_orig, cpa->num) : cpa->num; + if (b == ORIGINDEX_NONE) { return 0; + } elem = &data->elems[b]; @@ -1403,7 +1419,8 @@ static void interpolate_pathcache(ParticleCacheKey *first, float t, ParticleCach /************************************************/ /* interpolate a location on a face based on face coordinates */ void psys_interpolate_face(MVert *mvert, MFace *mface, MTFace *tface, float (*orcodata)[3], - float *w, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor) + float w[4], float vec[3], float nor[3], float utan[3], float vtan[3], + float orco[3], float ornor[3]) { float *v1 = 0, *v2 = 0, *v3 = 0, *v4 = 0; float e1[3], e2[3], s1, s2, t1, t2; @@ -1622,17 +1639,22 @@ int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, const f Mesh *me = (Mesh *)ob->data; MPoly *mpoly; OrigSpaceFace *osface; - int *origindex; int quad, findex, totface; float uv[2], (*faceuv)[2]; + /* double lookup */ + const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); + if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { + index_mf_to_mpoly = index_mp_to_orig = NULL; + } + mpoly = dm->getPolyArray(dm); - origindex = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); osface = dm->getTessFaceDataArray(dm, CD_ORIGSPACE); totface = dm->getNumTessFaces(dm); - if (osface == NULL || origindex == NULL) { + if (osface == NULL || index_mf_to_mpoly == NULL) { /* Assume we don't need osface data */ if (index < totface) { //printf("\tNO CD_ORIGSPACE, assuming not needed\n"); @@ -1666,7 +1688,8 @@ int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, const f } else { /* if we have no node, try every face */ for (findex = 0; findex < totface; findex++) { - if (origindex[findex] == index) { + const int findex_orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, findex); + if (findex_orig == index) { faceuv = osface[findex].uv; quad = (mpoly[findex].totloop == 4); @@ -1746,7 +1769,9 @@ static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_ } /* interprets particle data to get a point on a mesh in object space */ -void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache, const float fw[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3], float orco[3], float ornor[3]) +void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache, + const float fw[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3], + float orco[3], float ornor[3]) { float tmpnor[3], mapfw[4]; float (*orcodata)[3]; @@ -1842,7 +1867,9 @@ ParticleSystemModifierData *psys_get_modifier(Object *ob, ParticleSystem *psys) /* Particles on a shape */ /************************************************/ /* ready for future use */ -static void psys_particle_on_shape(int UNUSED(distr), int UNUSED(index), float *UNUSED(fuv), float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor) +static void psys_particle_on_shape(int UNUSED(distr), int UNUSED(index), + float *UNUSED(fuv), float vec[3], float nor[3], float utan[3], float vtan[3], + float orco[3], float ornor[3]) { /* TODO */ float zerovec[3] = {0.0f, 0.0f, 0.0f}; @@ -1868,7 +1895,9 @@ static void psys_particle_on_shape(int UNUSED(distr), int UNUSED(index), float * /************************************************/ /* Particles on emitter */ /************************************************/ -void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor) +void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int index, int index_dmcache, + float fuv[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3], + float orco[3], float ornor[3]) { if (psmd) { if (psmd->psys->part->distr == PART_DISTR_GRID && psmd->psys->part->from != PART_FROM_VERT) { @@ -2456,7 +2485,7 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c totthread = 1; for (i = 0; i < totthread; i++) { - threads[i].rng_path = rng_new(seed); + threads[i].rng_path = BLI_rng_new(seed); threads[i].tot = totthread; } @@ -3298,7 +3327,7 @@ void copy_particle_key(ParticleKey *to, ParticleKey *from, int time) to->time = to_time; } } -void psys_get_from_key(ParticleKey *key, float *loc, float *vel, float *rot, float *time) +void psys_get_from_key(ParticleKey *key, float loc[3], float vel[3], float rot[4], float *time) { if (loc) copy_v3_v3(loc, key->co); if (vel) copy_v3_v3(vel, key->vel); @@ -3776,7 +3805,7 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink = ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.f; - ptex->length = 1.0f - part->randlength *PSYS_FRAND(child_index + 26); + ptex->length = 1.0f - part->randlength * PSYS_FRAND(child_index + 26); ptex->length *= part->clength_thres < PSYS_FRAND(child_index + 27) ? part->clength : 1.0f; for (m = 0; m < MAX_MTEX; m++, mtexp++) { @@ -3968,7 +3997,7 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float UNUSED size *= part->childsize; if (part->childrandsize != 0.0f) - size *= 1.0f - part->childrandsize *PSYS_FRAND(cpa - psys->child + 26); + size *= 1.0f - part->childrandsize * PSYS_FRAND(cpa - psys->child + 26); return size; } @@ -4319,7 +4348,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta if (pa) { if (!always) { if ((cfra < pa->time && (part->flag & PART_UNBORN) == 0) || - (cfra > pa->dietime && (part->flag & PART_DIED) == 0)) + (cfra >= pa->dietime && (part->flag & PART_DIED) == 0)) { return 0; } @@ -4414,7 +4443,9 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta } } -void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, float *uv, float *orco) +void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part, + ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, + float uv[2], float orco[3]) { MFace *mface; MTFace *mtface; @@ -4539,8 +4570,8 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3] /* can happen with bad pointcache or physics calculation * since this becomes geometry, nan's and inf's crash raytrace code. * better not allow this. */ - if (!finite(bb->vec[0]) || !finite(bb->vec[1]) || !finite(bb->vec[2]) || - !finite(bb->vel[0]) || !finite(bb->vel[1]) || !finite(bb->vel[2]) ) + if ((!finite(bb->vec[0])) || (!finite(bb->vec[1])) || (!finite(bb->vec[2])) || + (!finite(bb->vel[0])) || (!finite(bb->vel[1])) || (!finite(bb->vel[2])) ) { zero_v3(bb->vec); zero_v3(bb->vel); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 2c0452bc2d1..2b95946f571 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -346,7 +346,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys) if (!dm->deformedOnly) { /* Will use later to speed up subsurf/derivedmesh */ LinkNode *node, *nodedmelem, **nodearray; - int totdmelem, totelem, i, *origindex; + int totdmelem, totelem, i, *origindex, *origindex_poly = NULL; if (psys->part->from == PART_FROM_VERT) { totdmelem= dm->getNumVerts(dm); @@ -356,23 +356,37 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys) else { /* FROM_FACE/FROM_VOLUME */ totdmelem= dm->getNumTessFaces(dm); totelem= me->totpoly; - origindex= dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + origindex = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + /* for face lookups we need the poly origindex too */ + origindex_poly = dm->getPolyDataArray(dm, CD_ORIGINDEX); + if (origindex_poly == NULL) { + origindex = NULL; + } } nodedmelem= MEM_callocN(sizeof(LinkNode)*totdmelem, "psys node elems"); nodearray= MEM_callocN(sizeof(LinkNode *)*totelem, "psys node array"); for (i=0, node=nodedmelem; ilink= SET_INT_IN_POINTER(i); + int origindex_final; + node->link = SET_INT_IN_POINTER(i); - if (*origindex != -1) { - if (nodearray[*origindex]) { + origindex_final = *origindex; + + /* if we have a poly source, do an index lookup */ + if (origindex_poly && origindex_final != ORIGINDEX_NONE) { + origindex_final = origindex_poly[origindex_final]; + } + + if (origindex_final != ORIGINDEX_NONE) { + if (nodearray[origindex_final]) { /* prepend */ - node->next = nodearray[*origindex]; - nodearray[*origindex]= node; + node->next = nodearray[origindex_final]; + nodearray[origindex_final] = node; + } + else { + nodearray[origindex_final] = node; } - else - nodearray[*origindex]= node; } } @@ -556,8 +570,7 @@ static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys) else /* store number of intersections */ (pa+(int)(lambda*size[a])*a0mul)->hair_index++; } - - if (mface->v4) { + else if (mface->v4) { copy_v3_v3(v4, mvert[mface->v4].co); if (isect_axial_line_tri_v3(a, co1, co2, v4, v1, v3, &lambda)) { @@ -632,10 +645,10 @@ static void hammersley_create(float *out, int n, int seed, float amount) double p, t, offs[2]; int k, kk; - rng = rng_new(31415926 + n + seed); - offs[0]= rng_getDouble(rng) + (double)amount; - offs[1]= rng_getDouble(rng) + (double)amount; - rng_free(rng); + rng = BLI_rng_new(31415926 + n + seed); + offs[0] = BLI_rng_get_double(rng) + (double)amount; + offs[1] = BLI_rng_get_double(rng) + (double)amount; + BLI_rng_free(rng); for (k = 0; k < n; k++) { t = 0; @@ -643,8 +656,8 @@ static void hammersley_create(float *out, int n, int seed, float amount) if (kk & 1) /* kk mod 2 = 1 */ t += p; - out[2*k + 0]= fmod((double)k/(double)n + offs[0], 1.0); - out[2*k + 1]= fmod(t + offs[1], 1.0); + out[2*k + 0] = fmod((double)k/(double)n + offs[0], 1.0); + out[2*k + 1] = fmod(t + offs[1], 1.0); } } @@ -661,13 +674,13 @@ static void init_mv_jit(float *jit, int num, int seed2, float amount) rad2= (float)(1.0f/((float)num)); rad3= (float)sqrt((float)num)/((float)num); - rng = rng_new(31415926 + num + seed2); + rng = BLI_rng_new(31415926 + num + seed2); x= 0; num2 = 2 * num; for (i=0; ijitoff[i] = fmod(ctx->jitoff[i],(float)ctx->jitlevel); - psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mface->v4, pa->fuv); - ctx->jitoff[i]++; + if (!isnan(ctx->jitoff[i])) { + psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mface->v4, pa->fuv); + ctx->jitoff[i]++; + } } break; case PART_DISTR_RAND: - randu= rng_getFloat(thread->rng); - randv= rng_getFloat(thread->rng); + randu= BLI_rng_get_float(thread->rng); + randv= BLI_rng_get_float(thread->rng); rng_skip_tot -= 2; psys_uv_to_w(randu, randv, mface->v4, pa->fuv); @@ -879,8 +894,8 @@ static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, Ch mf= dm->getTessFaceData(dm, ctx->index[p], CD_MFACE); - randu= rng_getFloat(thread->rng); - randv= rng_getFloat(thread->rng); + randu= BLI_rng_get_float(thread->rng); + randv= BLI_rng_get_float(thread->rng); rng_skip_tot -= 2; psys_uv_to_w(randu, randv, mf->v4, cpa->fuv); @@ -932,7 +947,7 @@ static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, Ch } if (rng_skip_tot > 0) /* should never be below zero */ - rng_skip(thread->rng, rng_skip_tot); + BLI_rng_skip(thread->rng, rng_skip_tot); } static void *distribute_threads_exec_cb(void *data) @@ -949,12 +964,12 @@ static void *distribute_threads_exec_cb(void *data) for (p=0; pctx->skip) /* simplification skip */ - rng_skip(thread->rng, PSYS_RND_DIST_SKIP * thread->ctx->skip[p]); + BLI_rng_skip(thread->rng, PSYS_RND_DIST_SKIP * thread->ctx->skip[p]); if ((p+thread->num) % thread->tot == 0) distribute_threads_exec(thread, NULL, cpa, p); else /* thread skip */ - rng_skip(thread->rng, PSYS_RND_DIST_SKIP); + BLI_rng_skip(thread->rng, PSYS_RND_DIST_SKIP); } } else { @@ -971,8 +986,8 @@ static void *distribute_threads_exec_cb(void *data) static int *COMPARE_ORIG_INDEX = NULL; static int distribute_compare_orig_index(const void *p1, const void *p2) { - int index1 = COMPARE_ORIG_INDEX[*(const int*)p1]; - int index2 = COMPARE_ORIG_INDEX[*(const int*)p2]; + int index1 = COMPARE_ORIG_INDEX[*(const int *)p1]; + int index2 = COMPARE_ORIG_INDEX[*(const int *)p2]; if (index1 < index2) return -1; @@ -998,7 +1013,7 @@ static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from) if (psys->child && totchild) { for (p=0,cpa=psys->child; pfuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]= 0.0; + cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3] = 0.0; cpa->foffset= 0.0f; cpa->parent=0; cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0; @@ -1009,7 +1024,7 @@ static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from) else { PARTICLE_P; LOOP_PARTICLES { - pa->fuv[0]=pa->fuv[1]=pa->fuv[2]= pa->fuv[3]= 0.0; + pa->fuv[0] = pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0; pa->foffset= 0.0f; pa->num= -1; } @@ -1111,7 +1126,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D if (from == PART_FROM_VERT) { MVert *mv= dm->getVertDataArray(dm, CD_MVERT); - float (*orcodata)[3]= dm->getVertDataArray(dm, CD_ORCO); + float (*orcodata)[3] = dm->getVertDataArray(dm, CD_ORCO); int totvert = dm->getNumVerts(dm); tree=BLI_kdtree_new(totvert); @@ -1243,9 +1258,9 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D inv_totweight = (totweight > 0.f ? 1.f/totweight : 0.f); /* Calculate cumulative weights */ - element_sum[0]= 0.0f; + element_sum[0] = 0.0f; for (i=0; iflag&PART_TRAND) || (part->simplify_flag&PART_SIMPLIFY_ENABLE)) { @@ -1254,9 +1269,9 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D for (p=0; p element_sum[i+1])) + while ((i < totelem) && (pos > (double)element_sum[i + 1])) i++; - particle_element[p]= MIN2(totelem-1, i); + particle_element[p] = MIN2(totelem-1, i); /* avoid zero weight face */ if (p == totpart-1 && element_weight[particle_element[p]] == 0.0f) - particle_element[p]= particle_element[p-1]; + particle_element[p] = particle_element[p-1]; - jitter_offset[particle_element[p]]= pos; + jitter_offset[particle_element[p]] = pos; } } @@ -1351,7 +1366,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D seed= 31415926 + ctx->sim.psys->seed; for (i=0; ivel); - break; + break; case PART_AVE_HORIZONTAL: { float zvec[3]; @@ -1620,9 +1635,9 @@ void psys_get_birth_coordinates(ParticleSimulationData *sim, ParticleData *pa, P ParticleSystem *psys = sim->psys; ParticleSettings *part; ParticleTexture ptex; - float fac, phasefac, nor[3]={0,0,0},loc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4]; - float r_vel[3],r_ave[3],r_rot[4],vec[3],p_vel[3]={0.0,0.0,0.0}; - float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0}; + float fac, phasefac, nor[3] = {0,0,0},loc[3],vel[3] = {0.0,0.0,0.0},rot[4],q2[4]; + float r_vel[3],r_ave[3],r_rot[4],vec[3],p_vel[3] = {0.0,0.0,0.0}; + float x_vec[3] = {1.0,0.0,0.0}, utan[3] = {0.0,1.0,0.0}, vtan[3] = {0.0,0.0,1.0}, rot_vec[3] = {0.0,0.0,0.0}; float q_phase[4]; int p = pa - psys->particles; part=psys->part; @@ -2535,7 +2550,7 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa madd_v3_v3fl(force, vec, -(pressure + near_pressure*q)*q); /* Viscosity */ - if (visc > 0.f || stiff_visc > 0.f) { + if (visc > 0.f || stiff_visc > 0.f) { sub_v3_v3v3(dv, vel, state->vel); u = dot_v3v3(vec, dv); @@ -2734,7 +2749,7 @@ static void basic_integrate(ParticleSimulationData *sim, int p, float dfra, floa } static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, float timestep) { - float rotfac, rot1[4], rot2[4]={1.0,0.0,0.0,0.0}, dtime=dfra*timestep, extrotfac; + float rotfac, rot1[4], rot2[4] = {1.0,0.0,0.0,0.0}, dtime=dfra*timestep, extrotfac; if ((part->flag & PART_ROTATIONS) == 0) { unit_qt(pa->state.rot); @@ -3164,8 +3179,7 @@ void BKE_psys_collision_neartest_cb(void *userdata, int index, const BVHTreeRay if (col->hit == col->current && col->pce.index == index && col->pce.tot == 3) return; - do - { + do { collision = collision_sphere_to_tri(col, ray->radius, &pce, &t); if (col->pce.inside == 0) { collision += collision_sphere_to_edges(col, ray->radius, &pce, &t); @@ -3775,7 +3789,7 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra)) /* Calculate the speed of the particle relative to the local scale of the * simulation. This should be called once per particle during a simulation * step, after the velocity has been updated. element_size defines the scale of - * the simulation, and is typically the distance to neighbourning particles. */ + * the simulation, and is typically the distance to neighboring particles. */ static void update_courant_num(ParticleSimulationData *sim, ParticleData *pa, float dtime, SPHData *sphdata) { @@ -4074,7 +4088,7 @@ static void particles_fluid_step(ParticleSimulationData *sim, int UNUSED(cfra)) { FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(sim->ob, eModifierType_Fluidsim); - if ( fluidmd && fluidmd->fss) { + if ( fluidmd && fluidmd->fss) { FluidsimSettings *fss= fluidmd->fss; ParticleSettings *part = psys->part; ParticleData *pa=NULL; @@ -4119,7 +4133,7 @@ static void particles_fluid_step(ParticleSimulationData *sim, int UNUSED(cfra)) int ptype=0; gzread(gzf, &ptype, sizeof( ptype )); - if (ptype&readMask) { + if (ptype & readMask) { activeParts++; gzread(gzf, &(pa->size), sizeof(float)); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 780528f4a0d..f195b3d71b0 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -249,9 +249,9 @@ static int ptcache_particle_write(int index, void *psys_v, void **data, int cfr if (data[BPHYS_DATA_INDEX] && (cfra < pa->time - step || cfra > pa->dietime + step)) return 0; - times[0]= pa->time; - times[1]= pa->dietime; - times[2]= pa->lifetime; + times[0] = pa->time; + times[1] = pa->dietime; + times[2] = pa->lifetime; PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index); PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co); @@ -532,20 +532,31 @@ static int ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra)) SmokeDomainSettings *sds = smd->domain; if (sds->fluid) { - return sds->res[0]*sds->res[1]*sds->res[2]; + return sds->base_res[0]*sds->base_res[1]*sds->base_res[2]; } else return 0; } + +#define SMOKE_CACHE_VERSION "1.04" + static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v) { SmokeModifierData *smd= (SmokeModifierData *)smoke_v; SmokeDomainSettings *sds = smd->domain; int ret = 0; + int fluid_fields = smoke_get_data_flags(sds); + + /* version header */ + ptcache_file_write(pf, SMOKE_CACHE_VERSION, 4, sizeof(char)); + ptcache_file_write(pf, &fluid_fields, 1, sizeof(int)); + ptcache_file_write(pf, &sds->active_fields, 1, sizeof(int)); + ptcache_file_write(pf, &sds->res, 3, sizeof(int)); + ptcache_file_write(pf, &sds->dx, 1, sizeof(float)); if (sds->fluid) { size_t res = sds->res[0]*sds->res[1]*sds->res[2]; - float dt, dx, *dens, *densold, *heat, *heatold, *vx, *vy, *vz, *vxold, *vyold, *vzold; + float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b; unsigned char *obstacles; unsigned int in_len = sizeof(float)*(unsigned int)res; unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer"); @@ -553,22 +564,40 @@ static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v) int mode=1; // light if (sds->cache_comp == SM_CACHE_HEAVY) mode=2; // heavy - smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles); + smoke_export(sds->fluid, &dt, &dx, &dens, &react, &flame, &fuel, &heat, &heatold, &vx, &vy, &vz, &r, &g, &b, &obstacles); ptcache_file_compressed_write(pf, (unsigned char *)sds->shadow, in_len, out, mode); ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len, out, mode); - ptcache_file_compressed_write(pf, (unsigned char *)densold, in_len, out, mode); - ptcache_file_compressed_write(pf, (unsigned char *)heat, in_len, out, mode); - ptcache_file_compressed_write(pf, (unsigned char *)heatold, in_len, out, mode); + if (fluid_fields & SM_ACTIVE_HEAT) { + ptcache_file_compressed_write(pf, (unsigned char *)heat, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)heatold, in_len, out, mode); + } + if (fluid_fields & SM_ACTIVE_FIRE) { + ptcache_file_compressed_write(pf, (unsigned char *)flame, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)fuel, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)react, in_len, out, mode); + } + if (fluid_fields & SM_ACTIVE_COLORS) { + ptcache_file_compressed_write(pf, (unsigned char *)r, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)g, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)b, in_len, out, mode); + } ptcache_file_compressed_write(pf, (unsigned char *)vx, in_len, out, mode); ptcache_file_compressed_write(pf, (unsigned char *)vy, in_len, out, mode); ptcache_file_compressed_write(pf, (unsigned char *)vz, in_len, out, mode); - ptcache_file_compressed_write(pf, (unsigned char *)vxold, in_len, out, mode); - ptcache_file_compressed_write(pf, (unsigned char *)vyold, in_len, out, mode); - ptcache_file_compressed_write(pf, (unsigned char *)vzold, in_len, out, mode); ptcache_file_compressed_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode); ptcache_file_write(pf, &dt, 1, sizeof(float)); ptcache_file_write(pf, &dx, 1, sizeof(float)); + ptcache_file_write(pf, &sds->p0, 3, sizeof(float)); + ptcache_file_write(pf, &sds->p1, 3, sizeof(float)); + ptcache_file_write(pf, &sds->dp0, 3, sizeof(float)); + ptcache_file_write(pf, &sds->shift, 3, sizeof(int)); + ptcache_file_write(pf, &sds->obj_shift_f, 3, sizeof(float)); + ptcache_file_write(pf, &sds->obmat, 16, sizeof(float)); + ptcache_file_write(pf, &sds->base_res, 3, sizeof(int)); + ptcache_file_write(pf, &sds->res_min, 3, sizeof(int)); + ptcache_file_write(pf, &sds->res_max, 3, sizeof(int)); + ptcache_file_write(pf, &sds->active_color, 3, sizeof(float)); MEM_freeN(out); @@ -579,7 +608,7 @@ static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v) int res_big_array[3]; int res_big; int res = sds->res[0]*sds->res[1]*sds->res[2]; - float *dens, *densold, *tcu, *tcv, *tcw; + float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b; unsigned int in_len = sizeof(float)*(unsigned int)res; unsigned int in_len_big; unsigned char *out; @@ -593,11 +622,20 @@ static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v) in_len_big = sizeof(float) * (unsigned int)res_big; - smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw); + smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw); out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len_big), "pointcache_lzo_buffer"); ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len_big, out, mode); - ptcache_file_compressed_write(pf, (unsigned char *)densold, in_len_big, out, mode); + if (fluid_fields & SM_ACTIVE_FIRE) { + ptcache_file_compressed_write(pf, (unsigned char *)flame, in_len_big, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)fuel, in_len_big, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)react, in_len_big, out, mode); + } + if (fluid_fields & SM_ACTIVE_COLORS) { + ptcache_file_compressed_write(pf, (unsigned char *)r, in_len_big, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)g, in_len_big, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)b, in_len_big, out, mode); + } MEM_freeN(out); out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer"); @@ -615,34 +653,95 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v) { SmokeModifierData *smd= (SmokeModifierData *)smoke_v; SmokeDomainSettings *sds = smd->domain; + char version[4]; + int ch_res[3]; + float ch_dx; + int fluid_fields = smoke_get_data_flags(sds); + int cache_fields = 0; + int active_fields = 0; + int reallocate = 0; + + /* version header */ + ptcache_file_read(pf, version, 4, sizeof(char)); + if (strncmp(version, SMOKE_CACHE_VERSION, 4)) return 0; + /* fluid info */ + ptcache_file_read(pf, &cache_fields, 1, sizeof(int)); + ptcache_file_read(pf, &active_fields, 1, sizeof(int)); + ptcache_file_read(pf, &ch_res, 3, sizeof(int)); + ptcache_file_read(pf, &ch_dx, 1, sizeof(float)); + + /* check if resolution has changed */ + if (sds->res[0] != ch_res[0] || + sds->res[1] != ch_res[1] || + sds->res[2] != ch_res[2]) { + if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) + reallocate = 1; + else + return 0; + } + /* check if active fields have changed */ + if (fluid_fields != cache_fields || + active_fields != sds->active_fields) + reallocate = 1; + + /* reallocate fluid if needed*/ + if (reallocate) { + sds->active_fields = active_fields; + smoke_reallocate_fluid(sds, ch_dx, ch_res, 1); + sds->dx = ch_dx; + VECCOPY(sds->res, ch_res); + sds->total_cells = ch_res[0]*ch_res[1]*ch_res[2]; + if (sds->flags & MOD_SMOKE_HIGHRES) { + smoke_reallocate_highres_fluid(sds, ch_dx, ch_res, 1); + } + } if (sds->fluid) { size_t res = sds->res[0]*sds->res[1]*sds->res[2]; - float dt, dx, *dens, *densold, *heat, *heatold, *vx, *vy, *vz, *vxold, *vyold, *vzold; + float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b; unsigned char *obstacles; unsigned int out_len = (unsigned int)res * sizeof(float); - smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles); + smoke_export(sds->fluid, &dt, &dx, &dens, &react, &flame, &fuel, &heat, &heatold, &vx, &vy, &vz, &r, &g, &b, &obstacles); ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len); - ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len); - ptcache_file_compressed_read(pf, (unsigned char*)densold, out_len); - ptcache_file_compressed_read(pf, (unsigned char*)heat, out_len); - ptcache_file_compressed_read(pf, (unsigned char*)heatold, out_len); - ptcache_file_compressed_read(pf, (unsigned char*)vx, out_len); - ptcache_file_compressed_read(pf, (unsigned char*)vy, out_len); - ptcache_file_compressed_read(pf, (unsigned char*)vz, out_len); - ptcache_file_compressed_read(pf, (unsigned char*)vxold, out_len); - ptcache_file_compressed_read(pf, (unsigned char*)vyold, out_len); - ptcache_file_compressed_read(pf, (unsigned char*)vzold, out_len); - ptcache_file_compressed_read(pf, (unsigned char*)obstacles, (unsigned int)res); + ptcache_file_compressed_read(pf, (unsigned char *)dens, out_len); + if (cache_fields & SM_ACTIVE_HEAT) { + ptcache_file_compressed_read(pf, (unsigned char *)heat, out_len); + ptcache_file_compressed_read(pf, (unsigned char *)heatold, out_len); + } + if (cache_fields & SM_ACTIVE_FIRE) { + ptcache_file_compressed_read(pf, (unsigned char *)flame, out_len); + ptcache_file_compressed_read(pf, (unsigned char *)fuel, out_len); + ptcache_file_compressed_read(pf, (unsigned char *)react, out_len); + } + if (cache_fields & SM_ACTIVE_COLORS) { + ptcache_file_compressed_read(pf, (unsigned char *)r, out_len); + ptcache_file_compressed_read(pf, (unsigned char *)g, out_len); + ptcache_file_compressed_read(pf, (unsigned char *)b, out_len); + } + ptcache_file_compressed_read(pf, (unsigned char *)vx, out_len); + ptcache_file_compressed_read(pf, (unsigned char *)vy, out_len); + ptcache_file_compressed_read(pf, (unsigned char *)vz, out_len); + ptcache_file_compressed_read(pf, (unsigned char *)obstacles, (unsigned int)res); ptcache_file_read(pf, &dt, 1, sizeof(float)); ptcache_file_read(pf, &dx, 1, sizeof(float)); + ptcache_file_read(pf, &sds->p0, 3, sizeof(float)); + ptcache_file_read(pf, &sds->p1, 3, sizeof(float)); + ptcache_file_read(pf, &sds->dp0, 3, sizeof(float)); + ptcache_file_read(pf, &sds->shift, 3, sizeof(int)); + ptcache_file_read(pf, &sds->obj_shift_f, 3, sizeof(float)); + ptcache_file_read(pf, &sds->obmat, 16, sizeof(float)); + ptcache_file_read(pf, &sds->base_res, 3, sizeof(int)); + ptcache_file_read(pf, &sds->res_min, 3, sizeof(int)); + ptcache_file_read(pf, &sds->res_max, 3, sizeof(int)); + ptcache_file_read(pf, &sds->active_color, 3, sizeof(float)); + } - if (pf->data_types & (1<wt) { + if (pf->data_types & (1<wt) { int res = sds->res[0]*sds->res[1]*sds->res[2]; int res_big, res_big_array[3]; - float *dens, *densold, *tcu, *tcv, *tcw; + float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b; unsigned int out_len = sizeof(float)*(unsigned int)res; unsigned int out_len_big; @@ -650,16 +749,23 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v) res_big = res_big_array[0]*res_big_array[1]*res_big_array[2]; out_len_big = sizeof(float) * (unsigned int)res_big; - smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw); + smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw); - ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len_big); - ptcache_file_compressed_read(pf, (unsigned char*)densold, out_len_big); + ptcache_file_compressed_read(pf, (unsigned char *)dens, out_len_big); + if (cache_fields & SM_ACTIVE_FIRE) { + ptcache_file_compressed_read(pf, (unsigned char *)flame, out_len_big); + ptcache_file_compressed_read(pf, (unsigned char *)fuel, out_len_big); + } + if (cache_fields & SM_ACTIVE_COLORS) { + ptcache_file_compressed_read(pf, (unsigned char *)r, out_len_big); + ptcache_file_compressed_read(pf, (unsigned char *)g, out_len_big); + ptcache_file_compressed_read(pf, (unsigned char *)b, out_len_big); + } - ptcache_file_compressed_read(pf, (unsigned char*)tcu, out_len); - ptcache_file_compressed_read(pf, (unsigned char*)tcv, out_len); - ptcache_file_compressed_read(pf, (unsigned char*)tcw, out_len); + ptcache_file_compressed_read(pf, (unsigned char *)tcu, out_len); + ptcache_file_compressed_read(pf, (unsigned char *)tcv, out_len); + ptcache_file_compressed_read(pf, (unsigned char *)tcw, out_len); } - } return 1; } @@ -753,7 +859,7 @@ static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v) return 0; } - ptcache_file_compressed_read(pf, (unsigned char*)surface->data->type_data, data_len*surface->data->total_points); + ptcache_file_compressed_read(pf, (unsigned char *)surface->data->type_data, data_len*surface->data->total_points); } return 1; @@ -1030,7 +1136,7 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup ListBase *lb_dupli_ob; /* don't update the dupli groups, we only wan't their pid's */ - if ((lb_dupli_ob = object_duplilist_ex(scene, ob, FALSE))) { + if ((lb_dupli_ob = object_duplilist_ex(scene, ob, FALSE, FALSE))) { DupliObject *dob; for (dob= lb_dupli_ob->first; dob; dob= dob->next) { if (dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */ @@ -1257,7 +1363,7 @@ static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, uns if (mode == 1) { LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS); - r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem); + r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem); if (!(r == LZO_E_OK) || (out_len >= in_len)) compressed = 0; else @@ -1593,7 +1699,7 @@ static PTCacheMem *ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra) for (i=0; itotpoint*ptcache_data_size[i]; if (pf->data_types & (1<data[i]), out_len); + ptcache_file_compressed_read(pf, (unsigned char *)(pm->data[i]), out_len); } } else { @@ -1624,7 +1730,7 @@ static PTCacheMem *ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra) extra->data = MEM_callocN(extra->totdata * ptcache_extra_datasize[extra->type], "Pointcache extradata->data"); if (pf->flag & PTCACHE_TYPEFLAG_COMPRESS) - ptcache_file_compressed_read(pf, (unsigned char*)(extra->data), extra->totdata*ptcache_extra_datasize[extra->type]); + ptcache_file_compressed_read(pf, (unsigned char *)(extra->data), extra->totdata*ptcache_extra_datasize[extra->type]); else ptcache_file_read(pf, extra->data, extra->totdata, ptcache_extra_datasize[extra->type]); @@ -1681,7 +1787,7 @@ static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm) if (pm->data[i]) { unsigned int in_len = pm->totpoint*ptcache_data_size[i]; unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer"); - ptcache_file_compressed_write(pf, (unsigned char*)(pm->data[i]), in_len, out, pid->cache->compression); + ptcache_file_compressed_write(pf, (unsigned char *)(pm->data[i]), in_len, out, pid->cache->compression); MEM_freeN(out); } } @@ -1714,7 +1820,7 @@ static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm) if (pid->cache->compression) { unsigned int in_len = extra->totdata * ptcache_extra_datasize[extra->type]; unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer"); - ptcache_file_compressed_write(pf, (unsigned char*)(extra->data), in_len, out, pid->cache->compression); + ptcache_file_compressed_write(pf, (unsigned char *)(extra->data), in_len, out, pid->cache->compression); MEM_freeN(out); } else { @@ -1925,18 +2031,16 @@ int BKE_ptcache_read(PTCacheID *pid, float cfra) pid->cache->simframe = cfra2; } - if ((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) { - cfrai = (int)cfra; - /* clear invalid cache frames so that better stuff can be simulated */ - if (pid->cache->flag & PTCACHE_OUTDATED) { - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfrai); - } - else if (pid->cache->flag & PTCACHE_FRAMES_SKIPPED) { - if (cfra <= pid->cache->last_exact) - pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED; + cfrai = (int)cfra; + /* clear invalid cache frames so that better stuff can be simulated */ + if (pid->cache->flag & PTCACHE_OUTDATED) { + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfrai); + } + else if (pid->cache->flag & PTCACHE_FRAMES_SKIPPED) { + if (cfra <= pid->cache->last_exact) + pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED; - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai, pid->cache->last_exact)); - } + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai, pid->cache->last_exact)); } return ret; @@ -2167,7 +2271,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra) /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */ switch (mode) { case PTCACHE_CLEAR_ALL: - case PTCACHE_CLEAR_BEFORE: + case PTCACHE_CLEAR_BEFORE: case PTCACHE_CLEAR_AFTER: if (pid->cache->flag & PTCACHE_DISK_CACHE) { ptcache_path(pid, path); @@ -2271,7 +2375,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra) } } } - if (pid->cache->cached_frames && cfra>=sta && cfra<=end) + if (pid->cache->cached_frames && cfra >= sta && cfra <= end) pid->cache->cached_frames[cfra-sta] = 0; break; } @@ -2358,7 +2462,7 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra if (MEM_allocN_len(cache->cached_frames) != sizeof(char) * (cache->endframe-cache->startframe+1)) { MEM_freeN(cache->cached_frames); cache->cached_frames = NULL; - } + } } if (cache->cached_frames==NULL && cache->endframe > cache->startframe) { @@ -2431,8 +2535,6 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) if (mode == PTCACHE_RESET_DEPSGRAPH) { if (!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) { - if (cache->flag & PTCACHE_QUICK_CACHE) - clear= 1; after= 1; } @@ -2466,10 +2568,10 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) sbFreeSimulation(pid->calldata); else if (pid->type == PTCACHE_TYPE_PARTICLES) psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH); - else if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) + /*else if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) smokeModifier_reset(pid->calldata); else if (pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) - smokeModifier_reset_turbulence(pid->calldata); + smokeModifier_reset_turbulence(pid->calldata);*/ else if (pid->type == PTCACHE_TYPE_DYNAMICPAINT) dynamicPaint_clearSurface((DynamicPaintSurface*)pid->calldata); } @@ -2496,7 +2598,7 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) } for (psys=ob->particlesystem.first; psys; psys=psys->next) { - /* children or just redo can be calculated without reseting anything */ + /* children or just redo can be calculated without resetting anything */ if (psys->recalc & PSYS_RECALC_REDO || psys->recalc & PSYS_RECALC_CHILD) skip = 1; /* Baked cloth hair has to be checked too, because we don't want to reset */ @@ -2663,36 +2765,65 @@ void BKE_ptcache_free_list(ListBase *ptcaches) } } -static PointCache *ptcache_copy(PointCache *cache) +static PointCache *ptcache_copy(PointCache *cache, int copy_data) { PointCache *ncache; ncache= MEM_dupallocN(cache); - /* hmm, should these be copied over instead? */ ncache->mem_cache.first = NULL; ncache->mem_cache.last = NULL; - ncache->cached_frames = NULL; - ncache->edit = NULL; - ncache->flag= 0; - ncache->simframe= 0; + if (copy_data == FALSE) { + ncache->mem_cache.first = NULL; + ncache->mem_cache.last = NULL; + ncache->cached_frames = NULL; + + ncache->flag= 0; + ncache->simframe= 0; + } + else { + PTCacheMem *pm; + + for (pm = cache->mem_cache.first; pm; pm = pm->next) { + PTCacheMem *pmn = MEM_dupallocN(pm); + int i; + + for (i = 0; i < BPHYS_TOT_DATA; i++) { + if (pmn->data[i]) + pmn->data[i] = MEM_dupallocN(pm->data[i]); + } + + BKE_ptcache_mem_pointers_init(pm); + + BLI_addtail(&ncache->mem_cache, pmn); + } + + if (ncache->cached_frames) + ncache->cached_frames = MEM_dupallocN(cache->cached_frames); + } + + /* hmm, should these be copied over instead? */ + ncache->edit = NULL; return ncache; } + /* returns first point cache */ -PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, ListBase *ptcaches_old) +PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, ListBase *ptcaches_old, int copy_data) { PointCache *cache = ptcaches_old->first; ptcaches_new->first = ptcaches_new->last = NULL; for (; cache; cache=cache->next) - BLI_addtail(ptcaches_new, ptcache_copy(cache)); + BLI_addtail(ptcaches_new, ptcache_copy(cache, copy_data)); return ptcaches_new->first; } +/* Disabled this code; this is being called on scene_update_tagged, and that in turn gets called on + * every user action changing stuff, and then it runs a complete bake??? (ton) */ /* Baking */ void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene) @@ -2876,7 +3007,7 @@ void BKE_ptcache_bake(PTCacheBaker* baker) } if ((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0) && - ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake)) + (render || bake)) { BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); } @@ -3195,8 +3326,9 @@ void BKE_ptcache_load_external(PTCacheID *pid) cache->endframe = end; cache->totpoint = 0; - if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) - ; /*necessary info in every file*/ + if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) { + /* necessary info in every file */ + } /* read totpoint from info file (frame 0) */ else if (info) { pf= ptcache_file_open(pid, PTCACHE_FILE_READ, 0); @@ -3244,7 +3376,7 @@ void BKE_ptcache_update_info(PTCacheID *pid) if (cache->flag & PTCACHE_EXTERNAL) { int cfra = cache->startframe; - for (; cfra<=cache->endframe; cfra++) { + for (; cfra <= cache->endframe; cfra++) { if (BKE_ptcache_id_exist(pid, cfra)) totframes++; } @@ -3271,7 +3403,7 @@ void BKE_ptcache_update_info(PTCacheID *pid) else { int cfra = cache->startframe; - for (; cfra<=cache->endframe; cfra++) { + for (; cfra <= cache->endframe; cfra++) { if (BKE_ptcache_id_exist(pid, cfra)) totframes++; } @@ -3280,7 +3412,7 @@ void BKE_ptcache_update_info(PTCacheID *pid) } } else { - PTCacheMem *pm = cache->mem_cache.first; + PTCacheMem *pm = cache->mem_cache.first; float bytes = 0.0f; int i, mb; diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c index 46ddce4b51b..8da4f11fed3 100644 --- a/source/blender/blenkernel/intern/property.c +++ b/source/blender/blenkernel/intern/property.c @@ -27,9 +27,12 @@ /** \file blender/blenkernel/intern/property.c * \ingroup bke + * + * This module deals with bProperty only, + * they are used on blender objects in the game engine + * (where they get converted into C++ classes - CValue and subclasses) */ - #include #include #include @@ -45,7 +48,7 @@ #include "BKE_property.h" -void free_property(bProperty *prop) +void BKE_bproperty_free(bProperty *prop) { if (prop->poin && prop->poin != &prop->data) MEM_freeN(prop->poin); @@ -53,17 +56,17 @@ void free_property(bProperty *prop) } -void free_properties(ListBase *lb) +void BKE_bproperty_free_list(ListBase *lb) { bProperty *prop; while ( (prop = lb->first) ) { BLI_remlink(lb, prop); - free_property(prop); + BKE_bproperty_free(prop); } } -bProperty *copy_property(bProperty *prop) +bProperty *BKE_bproperty_copy(bProperty *prop) { bProperty *propn; @@ -76,13 +79,13 @@ bProperty *copy_property(bProperty *prop) return propn; } -void copy_properties(ListBase *lbn, ListBase *lbo) +void BKE_bproperty_copy_list(ListBase *lbn, ListBase *lbo) { bProperty *prop, *propn; - free_properties(lbn); /* in case we are copying to an object with props */ + BKE_bproperty_free_list(lbn); /* in case we are copying to an object with props */ prop = lbo->first; while (prop) { - propn = copy_property(prop); + propn = BKE_bproperty_copy(prop); BLI_addtail(lbn, propn); prop = prop->next; } @@ -90,7 +93,7 @@ void copy_properties(ListBase *lbn, ListBase *lbo) } -void init_property(bProperty *prop) +void BKE_bproperty_init(bProperty *prop) { /* also use when property changes type */ @@ -113,22 +116,22 @@ void init_property(bProperty *prop) } -bProperty *new_property(int type) +bProperty *BKE_bproperty_new(int type) { bProperty *prop; prop = MEM_callocN(sizeof(bProperty), "property"); prop->type = type; - init_property(prop); + BKE_bproperty_init(prop); strcpy(prop->name, "prop"); return prop; } -/* used by unique_property() only */ -static bProperty *get_property__internal(bProperty *first, bProperty *self, const char *name) +/* used by BKE_bproperty_unique() only */ +static bProperty *bproperty_get(bProperty *first, bProperty *self, const char *name) { bProperty *p; for (p = first; p; p = p->next) { @@ -137,7 +140,7 @@ static bProperty *get_property__internal(bProperty *first, bProperty *self, cons } return NULL; } -void unique_property(bProperty *first, bProperty *prop, int force) +void BKE_bproperty_unique(bProperty *first, bProperty *prop, int force) { bProperty *p; @@ -151,13 +154,13 @@ void unique_property(bProperty *first, bProperty *prop, int force) if (force) { /* change other names to make them unique */ - while ((p = get_property__internal(first, prop, prop->name))) { - unique_property(first, p, 0); + while ((p = bproperty_get(first, prop, prop->name))) { + BKE_bproperty_unique(first, p, 0); } } else { /* change our own name until its unique */ - if (get_property__internal(first, prop, prop->name)) { + if (bproperty_get(first, prop, prop->name)) { /* there is a collision */ char new_name[sizeof(prop->name)]; char base_name[sizeof(prop->name)]; @@ -175,33 +178,34 @@ void unique_property(bProperty *first, bProperty *prop, int force) BLI_snprintf(num, sizeof(num), "%d", i++); BLI_strncpy(new_name, base_name, sizeof(prop->name) - strlen(num)); strcat(new_name, num); - } while (get_property__internal(first, prop, new_name)); + } while (bproperty_get(first, prop, new_name)); BLI_strncpy(prop->name, new_name, sizeof(prop->name)); } } } -bProperty *get_ob_property(Object *ob, const char *name) +bProperty *BKE_bproperty_object_get(Object *ob, const char *name) { return BLI_findstring(&ob->prop, name, offsetof(bProperty, name)); } -void set_ob_property(Object *ob, bProperty *propc) +void BKE_bproperty_object_set(Object *ob, bProperty *propc) { bProperty *prop; - prop = get_ob_property(ob, propc->name); + prop = BKE_bproperty_object_get(ob, propc->name); if (prop) { - free_property(prop); + BKE_bproperty_free(prop); BLI_remlink(&ob->prop, prop); } - BLI_addtail(&ob->prop, copy_property(propc)); + BLI_addtail(&ob->prop, BKE_bproperty_copy(propc)); } /* negative: prop is smaller * positive: prop is larger */ -int compare_property(bProperty *prop, const char *str) +#if 0 /* UNUSED */ +int BKE_bproperty_cmp(bProperty *prop, const char *str) { // extern int Gdfra; /* sector.c */ float fvalue, ftest; @@ -237,8 +241,9 @@ int compare_property(bProperty *prop, const char *str) return 0; } +#endif -void set_property(bProperty *prop, const char *str) +void BKE_bproperty_set(bProperty *prop, const char *str) { // extern int Gdfra; /* sector.c */ @@ -262,7 +267,7 @@ void set_property(bProperty *prop, const char *str) } -void add_property(bProperty *prop, const char *str) +void BKE_bproperty_add(bProperty *prop, const char *str) { // extern int Gdfra; /* sector.c */ @@ -282,7 +287,7 @@ void add_property(bProperty *prop, const char *str) } /* reads value of property, sets it in chars in str */ -void set_property_valstr(bProperty *prop, char *str) +void BKE_bproperty_set_valstr(bProperty *prop, char *str) { // extern int Gdfra; /* sector.c */ @@ -303,11 +308,13 @@ void set_property_valstr(bProperty *prop, char *str) } } +#if 0 /* UNUSED */ void cp_property(bProperty *prop1, bProperty *prop2) { char str[128]; - set_property_valstr(prop2, str); + BKE_bproperty_set_valstr(prop2, str); - set_property(prop1, str); + BKE_bproperty_set(prop1, str); } +#endif diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c index 3a66ec23412..d925d736358 100644 --- a/source/blender/blenkernel/intern/report.c +++ b/source/blender/blenkernel/intern/report.c @@ -34,6 +34,8 @@ #include "BLI_dynstr.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "BKE_report.h" #include "BKE_global.h" /* G.background only */ @@ -44,15 +46,24 @@ static const char *report_type_str(int type) { switch (type) { - case RPT_DEBUG: return "Debug"; - case RPT_INFO: return "Info"; - case RPT_OPERATOR: return "Operator"; - case RPT_WARNING: return "Warning"; - case RPT_ERROR: return "Error"; - case RPT_ERROR_INVALID_INPUT: return "Invalid Input Error"; - case RPT_ERROR_INVALID_CONTEXT: return "Invalid Context Error"; - case RPT_ERROR_OUT_OF_MEMORY: return "Out Of Memory Error"; - default: return "Undefined Type"; + case RPT_DEBUG: + return TIP_("Debug"); + case RPT_INFO: + return TIP_("Info"); + case RPT_OPERATOR: + return TIP_("Operator"); + case RPT_WARNING: + return TIP_("Warning"); + case RPT_ERROR: + return TIP_("Error"); + case RPT_ERROR_INVALID_INPUT: + return TIP_("Invalid Input Error"); + case RPT_ERROR_INVALID_CONTEXT: + return TIP_("Invalid Context Error"); + case RPT_ERROR_OUT_OF_MEMORY: + return TIP_("Out Of Memory Error"); + default: + return TIP_("Undefined Type"); } } @@ -87,10 +98,11 @@ void BKE_reports_clear(ReportList *reports) reports->list.first = reports->list.last = NULL; } -void BKE_report(ReportList *reports, ReportType type, const char *message) +void BKE_report(ReportList *reports, ReportType type, const char *_message) { Report *report; int len; + const char *message = TIP_(_message); /* in background mode always print otherwise there are cases the errors wont be displayed, * but still add to the report list since this is used for python exception handling */ @@ -114,14 +126,16 @@ void BKE_report(ReportList *reports, ReportType type, const char *message) } } -void BKE_reportf(ReportList *reports, ReportType type, const char *format, ...) +void BKE_reportf(ReportList *reports, ReportType type, const char *_format, ...) { DynStr *ds; Report *report; va_list args; + const char *format = TIP_(_format); if (G.background || !reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) { - va_start(args, format); + printf("%s: ", report_type_str(type)); + va_start(args, _format); vprintf(format, args); va_end(args); fprintf(stdout, "\n"); /* otherise each report needs to include a \n */ @@ -132,7 +146,7 @@ void BKE_reportf(ReportList *reports, ReportType type, const char *format, ...) report = MEM_callocN(sizeof(Report), "Report"); ds = BLI_dynstr_new(); - va_start(args, format); + va_start(args, _format); BLI_dynstr_vappendf(ds, format, args); va_end(args); @@ -147,10 +161,11 @@ void BKE_reportf(ReportList *reports, ReportType type, const char *format, ...) } } -void BKE_reports_prepend(ReportList *reports, const char *prepend) +void BKE_reports_prepend(ReportList *reports, const char *_prepend) { Report *report; DynStr *ds; + const char *prepend = TIP_(_prepend); if (!reports) return; @@ -169,18 +184,19 @@ void BKE_reports_prepend(ReportList *reports, const char *prepend) } } -void BKE_reports_prependf(ReportList *reports, const char *prepend, ...) +void BKE_reports_prependf(ReportList *reports, const char *_prepend, ...) { Report *report; DynStr *ds; va_list args; + const char *prepend = TIP_(_prepend); if (!reports) return; for (report = reports->list.first; report; report = report->next) { ds = BLI_dynstr_new(); - va_start(args, prepend); + va_start(args, _prepend); BLI_dynstr_vappendf(ds, prepend, args); va_end(args); diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index 7d9d2f02c06..eb4e0d9c679 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -210,7 +210,7 @@ void unlink_controllers(ListBase *lb) bController *cont; for (cont= lb->first; cont; cont= cont->next) - unlink_controller(cont); + unlink_controller(cont); } void free_controller(bController *cont) @@ -536,7 +536,7 @@ void clear_sca_new_poins(void) ob= G.main->object.first; while (ob) { clear_sca_new_poins_ob(ob); - ob= ob->id.next; + ob= ob->id.next; } } @@ -552,7 +552,7 @@ void set_sca_new_poins_ob(Object *ob) if (sens->flag & SENS_NEW) { for (a=0; atotlinks; a++) { if (sens->links[a] && sens->links[a]->mynew) - sens->links[a]= sens->links[a]->mynew; + sens->links[a] = sens->links[a]->mynew; } } sens= sens->next; @@ -563,7 +563,7 @@ void set_sca_new_poins_ob(Object *ob) if (cont->flag & CONT_NEW) { for (a=0; atotlinks; a++) { if ( cont->links[a] && cont->links[a]->mynew) - cont->links[a]= cont->links[a]->mynew; + cont->links[a] = cont->links[a]->mynew; } } cont= cont->next; @@ -624,7 +624,7 @@ void set_sca_new_poins(void) ob= G.main->object.first; while (ob) { set_sca_new_poins_ob(ob); - ob= ob->id.next; + ob= ob->id.next; } } @@ -696,7 +696,7 @@ void sca_remove_ob_poin(Object *obt, Object *ob) if (sta->target == ob) sta->target = NULL; } act= act->next; - } + } } /* ******************** INTERFACE ******************* */ @@ -875,3 +875,20 @@ void unlink_logicbricks(void **poin, void ***ppoin, short *tot) return; } } + +const char *sca_state_name_get(Object *ob, short bit) +{ + bController *cont; + unsigned int mask; + + mask = (1<controllers.first; + while (cont) { + if (cont->state_mask & mask) { + return cont->name; + } + cont = cont->next; + } + return NULL; +} + diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 2dec72560a2..a1918b77a1e 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -54,6 +54,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "BLI_callbacks.h" +#include "BLI_string.h" #include "BKE_anim.h" #include "BKE_animsys.h" @@ -135,8 +136,6 @@ Scene *BKE_scene_copy(Scene *sce, int type) MEM_freeN(scen->toolsettings); } else { - ImageFormatData *im_format, *im_formatn; - scen = BKE_libblock_copy(&sce->id); BLI_duplicatelist(&(scen->base), &(sce->base)); @@ -174,11 +173,12 @@ Scene *BKE_scene_copy(Scene *sce, int type) } /* copy color management settings */ - im_format = &sce->r.im_format; - im_formatn = &scen->r.im_format; - BKE_color_managed_display_settings_copy(&scen->display_settings, &sce->display_settings); BKE_color_managed_view_settings_copy(&scen->view_settings, &sce->view_settings); + BKE_color_managed_view_settings_copy(&scen->r.im_format.view_settings, &sce->r.im_format.view_settings); + + BLI_strncpy(scen->sequencer_colorspace_settings.name, sce->sequencer_colorspace_settings.name, + sizeof(scen->sequencer_colorspace_settings.name)); } /* tool settings */ @@ -325,7 +325,7 @@ void BKE_scene_free(Scene *sce) BKE_paint_free(&sce->toolsettings->imapaint.paint); MEM_freeN(sce->toolsettings); - sce->toolsettings = NULL; + sce->toolsettings = NULL; } if (sce->theDag) { @@ -354,6 +354,7 @@ Scene *BKE_scene_add(const char *name) Scene *sce; ParticleEditSettings *pset; int a; + const char *colorspace_name; sce = BKE_libblock_alloc(&bmain->scene, ID_SCE, name); sce->lay = sce->layact = 1; @@ -367,8 +368,8 @@ Scene *BKE_scene_add(const char *name) sce->r.ysch = 1080; sce->r.xasp = 1; sce->r.yasp = 1; - sce->r.xparts = 8; - sce->r.yparts = 8; + sce->r.tilex = 256; + sce->r.tiley = 256; sce->r.mblur_samples = 1; sce->r.filtertype = R_FILTER_MITCH; sce->r.size = 50; @@ -387,7 +388,7 @@ Scene *BKE_scene_add(const char *name) sce->r.edgeint = 10; sce->r.ocres = 128; - /* OCIO_TODO: for forwards compatibiliy only, so if no tonecurve are used, + /* OCIO_TODO: for forwards compatibility only, so if no tonecurve are used, * images would look in the same way as in current blender * * perhaps at some point should be completely deprecated? @@ -435,7 +436,7 @@ Scene *BKE_scene_add(const char *name) sce->toolsettings->cornertype = 1; sce->toolsettings->degr = 90; sce->toolsettings->step = 9; - sce->toolsettings->turn = 1; + sce->toolsettings->turn = 1; sce->toolsettings->extr_offs = 1; sce->toolsettings->doublimit = 0.001; sce->toolsettings->segments = 32; @@ -445,6 +446,7 @@ Scene *BKE_scene_add(const char *name) sce->toolsettings->uvcalc_cubesize = 1.0f; sce->toolsettings->uvcalc_mapdir = 1; sce->toolsettings->uvcalc_mapalign = 1; + sce->toolsettings->uvcalc_margin = 0.001f; sce->toolsettings->unwrapper = 1; sce->toolsettings->select_thresh = 0.01f; sce->toolsettings->jointrilimit = 0.8f; @@ -567,8 +569,13 @@ Scene *BKE_scene_add(const char *name) sound_create_scene(sce); + /* color management */ + colorspace_name = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_SEQUENCER); + BKE_color_managed_display_settings_init(&sce->display_settings); BKE_color_managed_view_settings_init(&sce->view_settings); + BLI_strncpy(sce->sequencer_colorspace_settings.name, colorspace_name, + sizeof(sce->sequencer_colorspace_settings.name)); return sce; } @@ -748,7 +755,7 @@ int BKE_scene_base_iter_next(Scene **scene, int val, Base **base, Object **ob) * this enters eternal loop because of * makeDispListMBall getting called inside of group_duplilist */ if ((*base)->object->dup_group == NULL) { - duplilist = object_duplilist((*scene), (*base)->object); + duplilist = object_duplilist((*scene), (*base)->object, FALSE); dupob = duplilist->first; @@ -951,7 +958,7 @@ float BKE_scene_frame_get_from_ctime(Scene *scene, const float frame) { float ctime = frame; ctime += scene->r.subframe; - ctime *= scene->r.framelen; + ctime *= scene->r.framelen; return ctime; } @@ -1035,7 +1042,7 @@ void BKE_scene_update_tagged(Main *bmain, Scene *scene) /* flush recalc flags to dependencies */ DAG_ids_flush_tagged(bmain); - scene->physics_settings.quick_cache_step = 0; + /* removed calls to quick_cache, see pointcache.c */ /* clear "LIB_DOIT" flag from all materials, to prevent infinite recursion problems later * when trying to find materials with drivers that need evaluating [#32017] @@ -1058,10 +1065,6 @@ void BKE_scene_update_tagged(Main *bmain, Scene *scene) BKE_animsys_evaluate_animdata(scene, &scene->id, adt, ctime, 0); } - /* quick point cache updates */ - if (scene->physics_settings.quick_cache_step) - BKE_ptcache_quick_cache_all(bmain, scene); - /* notify editors and python about recalc */ BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_POST); DAG_ids_check_recalc(bmain, scene, FALSE); @@ -1110,6 +1113,11 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay) BKE_animsys_evaluate_all_animation(bmain, sce, ctime); /*...done with recusrive funcs */ + /* clear "LIB_DOIT" flag from all materials, to prevent infinite recursion problems later + * when trying to find materials with drivers that need evaluating [#32017] + */ + tag_main_idcode(bmain, ID_MA, FALSE); + /* BKE_object_handle_update() on all objects, groups and sets */ scene_update_tagged_recursive(bmain, sce, sce); @@ -1186,7 +1194,7 @@ int BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer *s int get_render_subsurf_level(RenderData *r, int lvl) { if (r->mode & R_SIMPLIFY) - return MIN2(r->simplify_subsurf, lvl); + return min_ii(r->simplify_subsurf, lvl); else return lvl; } @@ -1202,7 +1210,7 @@ int get_render_child_particle_number(RenderData *r, int num) int get_render_shadow_samples(RenderData *r, int samples) { if ((r->mode & R_SIMPLIFY) && samples > 0) - return MIN2(r->simplify_shadowsamples, samples); + return min_ii(r->simplify_shadowsamples, samples); else return samples; } @@ -1270,9 +1278,11 @@ void BKE_scene_disable_color_management(Scene *scene) ColorManagedDisplaySettings *display_settings = &scene->display_settings; ColorManagedViewSettings *view_settings = &scene->view_settings; const char *view; + const char *none_display_name; - /* NOTE: None display with Default view should always exist in OCIO configuration, otherwise it wouldn't work as expected */ - BLI_strncpy(display_settings->display_device, "None", sizeof(display_settings->display_device)); + none_display_name = IMB_colormanagement_display_get_none_name(); + + BLI_strncpy(display_settings->display_device, none_display_name, sizeof(display_settings->display_device)); view = IMB_colormanagement_view_get_default_name(display_settings->display_device); @@ -1280,3 +1290,8 @@ void BKE_scene_disable_color_management(Scene *scene) BLI_strncpy(view_settings->view_transform, view, sizeof(view_settings->view_transform)); } } + +int BKE_scene_check_color_management_enabled(const Scene *scene) +{ + return strcmp(scene->display_settings.display_device, "None") != 0; +} diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index eaf3ec384c8..469881020c1 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -62,14 +62,14 @@ static void slice_get_byte_buffers(const SeqRenderData *context, const ImBuf *ib { int offset = 4 * start_line * context->rectx; - *rect1 = (unsigned char*) ibuf1->rect + offset; - *rect_out = (unsigned char*) out->rect + offset; + *rect1 = (unsigned char *)ibuf1->rect + offset; + *rect_out = (unsigned char *)out->rect + offset; if (ibuf2) - *rect2 = (unsigned char*) ibuf2->rect + offset; + *rect2 = (unsigned char *)ibuf2->rect + offset; if (ibuf3) - *rect3 = (unsigned char*) ibuf3->rect + offset; + *rect3 = (unsigned char *)ibuf3->rect + offset; } static void slice_get_float_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2, @@ -600,7 +600,7 @@ static void makeGammaTables(float gamma) color_step = 1.0f / RE_GAMMA_TABLE_SIZE; inv_color_step = (float) RE_GAMMA_TABLE_SIZE; - /* We could squeeze out the two range tables to gain some memory */ + /* We could squeeze out the two range tables to gain some memory */ for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) { color_domain_table[i] = i * color_step; gamma_range_table[i] = pow(color_domain_table[i], valid_gamma); @@ -609,9 +609,9 @@ static void makeGammaTables(float gamma) /* The end of the table should match 1.0 carefully. In order to avoid * rounding errors, we just set this explicitly. The last segment may - * have a different length than the other segments, but our - * interpolation is insensitive to that - */ + * have a different length than the other segments, but our + * interpolation is insensitive to that + */ color_domain_table[RE_GAMMA_TABLE_SIZE] = 1.0; gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0; inv_gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0; @@ -1178,7 +1178,7 @@ static void do_mul_effect_float(float facf0, float facf1, int x, int y, float *r fac3 = facf1; /* formula: - * fac*(a*b) + (1-fac)*a => fac*a*(b-1)+a + * fac * (a * b) + (1 - fac) * a => fac * a * (b - 1) + a */ while (y--) { @@ -1353,7 +1353,7 @@ static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float f hyp2 = fabsf(angle * x + y + (-(yo - posy * 0.5f) - angle * (xo - posx * 0.5f))) * wipezone->pythangle; } - hwidth = minf(hwidth, fabsf(b3 - b1) / 2.0f); + hwidth = min_ff(hwidth, fabsf(b3 - b1) / 2.0f); if (b2 < b1 && b2 < b3) { output = in_band(hwidth, hyp, 0, 1); @@ -2373,7 +2373,7 @@ static ImBuf *do_solid_color(SeqRenderData context, Sequence *seq, float UNUSED( rect[1] = col1[1]; rect[2] = col1[2]; rect[3] = 255; - } + } } } @@ -2609,7 +2609,7 @@ static void store_icu_yrange_speed(Sequence *seq, short UNUSED(adrcode), float * *ymin = 0.0; *ymax = seq->len; } - } + } } void BKE_sequence_effect_speed_rebuild_map(Scene *scene, Sequence *seq, int force) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 8d7ca94ed48..80ea00fc703 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -53,6 +53,8 @@ #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "BKE_animsys.h" #include "BKE_global.h" #include "BKE_image.h" @@ -313,7 +315,7 @@ void BKE_sequencer_editing_free(Scene *scene) static void sequencer_imbuf_assign_spaces(Scene *scene, ImBuf *ibuf) { - IMB_colormanagement_imbuf_assign_float_space(ibuf, &scene->sequencer_colorspace_settings); + IMB_colormanagement_assign_float_colorspace(ibuf, scene->sequencer_colorspace_settings.name); } void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_float) @@ -461,7 +463,7 @@ static void seq_array(Editing *ed, Sequence ***seqarray, int *tot, int use_point seq_build_array(&ed->seqbase, &array, 0); } -void BKE_seqence_iterator_begin(Editing *ed, SeqIterator *iter, int use_pointer) +void BKE_sequence_iterator_begin(Editing *ed, SeqIterator *iter, int use_pointer) { memset(iter, 0, sizeof(*iter)); seq_array(ed, &iter->array, &iter->tot, use_pointer); @@ -473,7 +475,7 @@ void BKE_seqence_iterator_begin(Editing *ed, SeqIterator *iter, int use_pointer) } } -void BKE_seqence_iterator_next(SeqIterator *iter) +void BKE_sequence_iterator_next(SeqIterator *iter) { if (++iter->cur < iter->tot) iter->seq = iter->array[iter->cur]; @@ -481,7 +483,7 @@ void BKE_seqence_iterator_next(SeqIterator *iter) iter->valid = 0; } -void BKE_seqence_iterator_end(SeqIterator *iter) +void BKE_sequence_iterator_end(SeqIterator *iter) { if (iter->array) MEM_freeN(iter->array); @@ -507,8 +509,8 @@ static void seq_update_sound_bounds_recursive_rec(Scene *scene, Sequence *metase * since sound is played outside of evaluating the imbufs, */ for (seq = metaseq->seqbase.first; seq; seq = seq->next) { if (seq->type == SEQ_TYPE_META) { - seq_update_sound_bounds_recursive_rec(scene, seq, maxi(start, metaseq_start(seq)), - mini(end, metaseq_end(seq))); + seq_update_sound_bounds_recursive_rec(scene, seq, max_ii(start, metaseq_start(seq)), + min_ii(end, metaseq_end(seq))); } else if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) { if (seq->scene_sound) { @@ -717,7 +719,7 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, int lock_range) #ifdef WITH_AUDASPACE if (!seq->sound) return; - seq->len = ceil(AUD_getInfo(seq->sound->playback_handle).length * FPS); + seq->len = ceil((double)AUD_getInfo(seq->sound->playback_handle).length * FPS); seq->len -= seq->anim_startofs; seq->len -= seq->anim_endofs; if (seq->len < 0) { @@ -843,7 +845,7 @@ static int seqbase_unique_name_recursive_cb(Sequence *seq, void *arg_pt) return 1; } -void BKE_seqence_base_unique_name_recursive(ListBase *seqbasep, Sequence *seq) +void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, Sequence *seq) { SeqUniqueInfo sui; char *dot; @@ -991,7 +993,7 @@ static float give_stripelem_index(Sequence *seq, float cfra) if (seq->type & SEQ_TYPE_EFFECT) { end = seq->enddisp; - } + } if (end < sta) { return -1; @@ -1835,8 +1837,6 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, StripCrop c = {0}; StripTransform t = {0}; int sx, sy, dx, dy; - double xscale = 1.0; - double yscale = 1.0; if (is_proxy_image) { double f = seq_rendersize_to_scale_factor(context.preview_render_size); @@ -1853,14 +1853,6 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, t = *seq->strip->transform; } - xscale = context.scene->r.xsch ? ((double) context.rectx / (double) context.scene->r.xsch) : 1.0; - yscale = context.scene->r.ysch ? ((double) context.recty / (double) context.scene->r.ysch) : 1.0; - - c.left *= xscale; c.right *= xscale; - c.top *= yscale; c.bottom *= yscale; - - t.xofs *= xscale; t.yofs *= yscale; - sx = ibuf->x - c.left - c.right; sy = ibuf->y - c.top - c.bottom; dx = sx; @@ -1892,7 +1884,7 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, ibuf = i; } - } + } if (seq->flag & SEQ_FLIPX) { IMB_flipx(ibuf); @@ -1975,17 +1967,20 @@ static ImBuf *copy_from_ibuf_still(SeqRenderData context, Sequence *seq, float n static void copy_to_ibuf_still(SeqRenderData context, Sequence *seq, float nr, ImBuf *ibuf) { + /* warning: ibuf may be NULL if the video fails to load */ if (nr == 0 || nr == seq->len - 1) { /* we have to store a copy, since the passed ibuf * could be preprocessed afterwards (thereby silently * changing the cached image... */ ibuf = IMB_dupImBuf(ibuf); - sequencer_imbuf_assign_spaces(context.scene, ibuf); + if (ibuf) { + sequencer_imbuf_assign_spaces(context.scene, ibuf); + } if (nr == 0) { BKE_sequencer_cache_put(context, seq, seq->start, SEQ_STRIPELEM_IBUF_STARTSTILL, ibuf); - } + } if (nr == seq->len - 1) { BKE_sequencer_cache_put(context, seq, seq->start, SEQ_STRIPELEM_IBUF_ENDSTILL, ibuf); @@ -2186,7 +2181,7 @@ static ImBuf *seq_render_movieclip_strip(SeqRenderData context, Sequence *seq, f memset(&user, 0, sizeof(MovieClipUser)); - BKE_movieclip_user_set_frame(&user, nr + seq->anim_startofs); + BKE_movieclip_user_set_frame(&user, nr + seq->anim_startofs + seq->clip->start_frame); user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL; @@ -2344,9 +2339,11 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float * -jahka */ - int rendering = G.is_rendering; - int doseq; - int doseq_gl = G.is_rendering ? /*(scene->r.seq_flag & R_SEQ_GL_REND)*/ 0 : /*(scene->r.seq_flag & R_SEQ_GL_PREV)*/ 1; + const short is_rendering = G.is_rendering; + const int do_seq_gl = G.is_rendering ? + 0 /* (context.scene->r.seq_flag & R_SEQ_GL_REND) */ : + (context.scene->r.seq_flag & R_SEQ_GL_PREV); + int do_seq; int have_seq = FALSE; Scene *scene; @@ -2363,9 +2360,10 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float oldcfra = scene->r.cfra; scene->r.cfra = frame; - if (seq->scene_camera) + if (seq->scene_camera) { camera = seq->scene_camera; - else { + } + else { BKE_scene_camera_switch_update(scene); camera = scene->camera; } @@ -2376,7 +2374,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float } /* prevent eternal loop */ - doseq = context.scene->r.scemode & R_DOSEQ; + do_seq = context.scene->r.scemode & R_DOSEQ; context.scene->r.scemode &= ~R_DOSEQ; #ifdef DURIAN_CAMERA_SWITCH @@ -2386,8 +2384,11 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float #else (void)oldmarkers; #endif - - if (sequencer_view3d_cb && BLI_thread_is_main() && doseq_gl && (scene == context.scene || have_seq == 0) && camera) { + + if ((sequencer_view3d_cb && do_seq_gl && camera) && + (BLI_thread_is_main() == TRUE) && + ((have_seq == FALSE) || (scene == context.scene))) + { char err_out[256] = "unknown"; /* for old scened this can be uninitialized, * should probably be added to do_versions at some point if the functionality stays */ @@ -2407,14 +2408,14 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float RenderResult rres; /* XXX: this if can be removed when sequence preview rendering uses the job system */ - if (rendering || context.scene != scene) { + if (is_rendering || context.scene != scene) { if (re == NULL) re = RE_NewRender(scene->id.name); RE_BlenderFrame(re, context.bmain, scene, NULL, camera, scene->lay, frame, FALSE); /* restore previous state after it was toggled on & off by RE_BlenderFrame */ - G.is_rendering = rendering; + G.is_rendering = is_rendering; } RE_AcquireResultImage(re, &rres); @@ -2441,7 +2442,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float } /* restore */ - context.scene->r.scemode |= doseq; + context.scene->r.scemode |= do_seq; scene->r.cfra = oldcfra; @@ -2583,17 +2584,19 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo case SEQ_TYPE_MOVIECLIP: { ibuf = seq_render_movieclip_strip(context, seq, nr); - sequencer_imbuf_assign_spaces(context.scene, ibuf); - if (ibuf && use_preprocess) { + if (ibuf) { + /* duplicate frame so movie cache wouldn't be confused by sequencer's stuff */ ImBuf *i = IMB_dupImBuf(ibuf); - IMB_freeImBuf(ibuf); - ibuf = i; + + if (ibuf->rect_float) + BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf, FALSE); + + copy_to_ibuf_still(context, seq, nr, ibuf); } - copy_to_ibuf_still(context, seq, nr, ibuf); break; } @@ -2830,7 +2833,7 @@ ImBuf *BKE_sequencer_give_ibuf(SeqRenderData context, float cfra, int chanshown) count = BLI_countlist(&ed->metastack); if ((chanshown < 0) && (count > 0)) { - count = MAX2(count + chanshown, 0); + count = max_ii(count + chanshown, 0); seqbasep = ((MetaStack *)BLI_findlink(&ed->metastack, count))->oldbasep; } else { @@ -3040,10 +3043,27 @@ int BKE_sequence_check_depend(Sequence *seq, Sequence *cur) return TRUE; } +static void sequence_do_invalidate_dependent(Sequence *seq, ListBase *seqbase) +{ + Sequence *cur; + + for (cur = seqbase->first; cur; cur = cur->next) { + if (cur == seq) + continue; + + if (BKE_sequence_check_depend(seq, cur)) { + BKE_sequencer_cache_cleanup_sequence(cur); + BKE_sequencer_preprocessed_cache_cleanup_sequence(cur); + } + + if (cur->seqbase.first) + sequence_do_invalidate_dependent(seq, &cur->seqbase); + } +} + static void sequence_invalidate_cache(Scene *scene, Sequence *seq, int invalidate_self, int invalidate_preprocess) { Editing *ed = scene->ed; - Sequence *cur; /* invalidate cache for current sequence */ if (invalidate_self) @@ -3057,17 +3077,11 @@ static void sequence_invalidate_cache(Scene *scene, Sequence *seq, int invalidat BKE_sequencer_preprocessed_cache_cleanup_sequence(seq); /* invalidate cache for all dependent sequences */ - SEQ_BEGIN (ed, cur) - { - if (cur == seq) - continue; - if (BKE_sequence_check_depend(seq, cur)) { - BKE_sequencer_cache_cleanup_sequence(cur); - BKE_sequencer_preprocessed_cache_cleanup_sequence(cur); - } - } - SEQ_END + /* NOTE: can not use SEQ_BEGIN/SEQ_END here because that macro will change sequence's depth, + * which makes transformation routines work incorrect + */ + sequence_do_invalidate_dependent(seq, &ed->seqbase); } void BKE_sequence_invalidate_cache(Scene *scene, Sequence *seq) @@ -3075,7 +3089,7 @@ void BKE_sequence_invalidate_cache(Scene *scene, Sequence *seq) sequence_invalidate_cache(scene, seq, TRUE, TRUE); } -void BKE_sequence_invalidate_deendent(Scene *scene, Sequence *seq) +void BKE_sequence_invalidate_dependent(Scene *scene, Sequence *seq) { sequence_invalidate_cache(scene, seq, FALSE, TRUE); } @@ -3188,7 +3202,7 @@ int BKE_sequence_tx_get_final_left(Sequence *seq, int metaclip) { if (metaclip && seq->tmp) { /* return the range clipped by the parents range */ - return maxi(BKE_sequence_tx_get_final_left(seq, 0), BKE_sequence_tx_get_final_left((Sequence *)seq->tmp, TRUE)); + return max_ii(BKE_sequence_tx_get_final_left(seq, 0), BKE_sequence_tx_get_final_left((Sequence *)seq->tmp, TRUE)); } else { return (seq->start - seq->startstill) + seq->startofs; @@ -3199,7 +3213,7 @@ int BKE_sequence_tx_get_final_right(Sequence *seq, int metaclip) { if (metaclip && seq->tmp) { /* return the range clipped by the parents range */ - return mini(BKE_sequence_tx_get_final_right(seq, 0), BKE_sequence_tx_get_final_right((Sequence *)seq->tmp, TRUE)); + return min_ii(BKE_sequence_tx_get_final_right(seq, 0), BKE_sequence_tx_get_final_right((Sequence *)seq->tmp, TRUE)); } else { return ((seq->start + seq->len) + seq->endstill) - seq->endofs; @@ -3451,7 +3465,7 @@ int BKE_sequence_base_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_sc for (seq = seqbasep->first; seq; seq = seq->next) { if (seq->machine == orig_machine) - new_frame = MAX2(new_frame, seq->enddisp); + new_frame = max_ii(new_frame, seq->enddisp); } test->machine = orig_machine; @@ -3476,10 +3490,10 @@ static int shuffle_seq_time_offset_test(ListBase *seqbasep, char dir) for (seq_other = seqbasep->first; seq_other; seq_other = seq_other->next) { if (!seq_other->tmp && seq_overlap(seq, seq_other)) { if (dir == 'L') { - offset = MIN2(offset, seq_other->startdisp - seq->enddisp); + offset = min_ii(offset, seq_other->startdisp - seq->enddisp); } else { - offset = MAX2(offset, seq_other->enddisp - seq->startdisp); + offset = max_ii(offset, seq_other->enddisp - seq->startdisp); } } } @@ -3664,26 +3678,26 @@ int BKE_sequence_swap(Sequence *seq_a, Sequence *seq_b, const char **error_str) char name[sizeof(seq_a->name)]; if (seq_a->len != seq_b->len) { - *error_str = "Strips must be the same length"; + *error_str = N_("Strips must be the same length"); return 0; } - /* type checking, could be more advanced but disalow sound vs non-sound copy */ + /* type checking, could be more advanced but disallow sound vs non-sound copy */ if (seq_a->type != seq_b->type) { if (seq_a->type == SEQ_TYPE_SOUND_RAM || seq_b->type == SEQ_TYPE_SOUND_RAM) { - *error_str = "Strips were not compatible"; + *error_str = N_("Strips were not compatible"); return 0; } /* disallow effects to swap with non-effects strips */ if ((seq_a->type & SEQ_TYPE_EFFECT) != (seq_b->type & SEQ_TYPE_EFFECT)) { - *error_str = "Strips were not compatible"; + *error_str = N_("Strips were not compatible"); return 0; } if ((seq_a->type & SEQ_TYPE_EFFECT) && (seq_b->type & SEQ_TYPE_EFFECT)) { if (BKE_sequence_effect_get_num_inputs(seq_a->type) != BKE_sequence_effect_get_num_inputs(seq_b->type)) { - *error_str = "Strips must have the same number of inputs"; + *error_str = N_("Strips must have the same number of inputs"); return 0; } } @@ -3880,7 +3894,7 @@ static void seq_load_apply(Scene *scene, Sequence *seq, SeqLoadInfo *seq_load) { if (seq) { BLI_strncpy(seq->name + 2, seq_load->name, sizeof(seq->name) - 2); - BKE_seqence_base_unique_name_recursive(&scene->ed->seqbase, seq); + BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); if (seq_load->flag & SEQ_LOAD_FRAME_ADVANCE) { seq_load->start_frame += (seq->enddisp - seq->startdisp); @@ -3967,10 +3981,10 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad sound = sound_new_file(bmain, seq_load->path); /* handles relative paths */ if (sound == NULL || sound->playback_handle == NULL) { - /* +#if 0 if (op) BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); - */ +#endif return NULL; } @@ -3979,10 +3993,10 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad if (info.specs.channels == AUD_CHANNELS_INVALID) { sound_delete(bmain, sound); - /* +#if 0 if (op) BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); - */ +#endif return NULL; } @@ -3991,11 +4005,11 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad seq->type = SEQ_TYPE_SOUND_RAM; seq->sound = sound; BLI_strncpy(seq->name + 2, "Sound", SEQ_NAME_MAXSTR - 2); - BKE_seqence_base_unique_name_recursive(&scene->ed->seqbase, seq); + BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); /* basic defaults */ seq->strip = strip = MEM_callocN(sizeof(Strip), "strip"); - seq->len = ceil(info.length * FPS); + seq->len = (int)ceil((double)info.length * FPS); strip->us = 1; /* we only need 1 element to store the filename */ @@ -4051,7 +4065,7 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad seq->anim = an; seq->anim_preseek = IMB_anim_get_preseek(an); BLI_strncpy(seq->name + 2, "Movie", SEQ_NAME_MAXSTR - 2); - BKE_seqence_base_unique_name_recursive(&scene->ed->seqbase, seq); + BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); /* basic defaults */ seq->strip = strip = MEM_callocN(sizeof(Strip), "strip"); @@ -4163,7 +4177,7 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup } if (dupe_flag & SEQ_DUPE_UNIQUE_NAME) - BKE_seqence_base_unique_name_recursive(&scene->ed->seqbase, seqn); + BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seqn); if (dupe_flag & SEQ_DUPE_ANIM) BKE_sequencer_dupe_animdata(scene, seq->name + 2, seqn->name + 2); @@ -4218,7 +4232,7 @@ void BKE_sequence_base_dupli_recursive(Scene *scene, Scene *scene_to, ListBase * /* called on draw, needs to be fast, * we could cache and use a flag if we want to make checks for file paths resolving for eg. */ -int BKE_seqence_is_valid_check(Sequence *seq) +int BKE_sequence_is_valid_check(Sequence *seq) { switch (seq->type) { case SEQ_TYPE_MASK: diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 9a8bcaabe0c..96faec389df 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -84,7 +84,7 @@ #endif /* get derived mesh */ -//TODO is anyfunction that does this? returning the derivedFinal without we caring if its in edit mode or not? +/* TODO is anyfunction that does this? returning the derivedFinal without we caring if its in edit mode or not? */ DerivedMesh *object_get_derived_final(Object *ob) { Mesh *me = ob->data; @@ -149,7 +149,7 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) return; } - //Setup nearest + /* Setup nearest */ nearest.index = -1; nearest.dist = FLT_MAX; #ifndef __APPLE__ @@ -159,10 +159,12 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) float *co = calc->vertexCos[i]; float tmp_co[3]; float weight = defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup); - if (weight == 0.0f) continue; + if (weight == 0.0f) { + continue; + } - //Convert the vertex to tree coordinates + /* Convert the vertex to tree coordinates */ if (calc->vert) { copy_v3_v3(tmp_co, calc->vert[i].co); } @@ -171,11 +173,11 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) } space_transform_apply(&calc->local2target, tmp_co); - //Use local proximity heuristics (to reduce the nearest search) - // - //If we already had an hit before.. we assume this vertex is going to have a close hit to that other vertex - //so we can initiate the "nearest.dist" with the expected value to that last hit. - //This will lead in prunning of the search tree. + /* Use local proximity heuristics (to reduce the nearest search) + * + * If we already had an hit before.. we assume this vertex is going to have a close hit to that other vertex + * so we can initiate the "nearest.dist" with the expected value to that last hit. + * This will lead in prunning of the search tree. */ if (nearest.index != -1) nearest.dist = len_squared_v3v3(tmp_co, nearest.co); else @@ -184,23 +186,27 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) BLI_bvhtree_find_nearest(treeData.tree, tmp_co, &nearest, treeData.nearest_callback, &treeData); - //Found the nearest vertex + /* Found the nearest vertex */ if (nearest.index != -1) { - //Adjusting the vertex weight, so that after interpolating it keeps a certain distance from the nearest position - float dist = sasqrt(nearest.dist); - if (dist > FLT_EPSILON) weight *= (dist - calc->keepDist) / dist; + /* Adjusting the vertex weight, + * so that after interpolating it keeps a certain distance from the nearest position */ + if (nearest.dist > FLT_EPSILON) { + const float dist = sqrtf(nearest.dist); + weight *= (dist - calc->keepDist) / dist; + } - //Convert the coordinates back to mesh coordinates + /* Convert the coordinates back to mesh coordinates */ copy_v3_v3(tmp_co, nearest.co); space_transform_invert(&calc->local2target, tmp_co); - interp_v3_v3v3(co, co, tmp_co, weight); //linear interpolation + interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */ } } free_bvhtree_from_mesh(&treeData); } + /* * This function raycast a single vertex and updates the hit if the "hit" is considered valid. * Returns TRUE if "hit" was updated. @@ -209,16 +215,24 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) * MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE (front faces hits are ignored) * MOD_SHRINKWRAP_CULL_TARGET_BACKFACE (back faces hits are ignored) */ -int normal_projection_project_vertex(char options, const float vert[3], const float dir[3], const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) +int normal_projection_project_vertex(char options, const float vert[3], const float dir[3], + const SpaceTransform *transf, + BVHTree *tree, BVHTreeRayHit *hit, + BVHTree_RayCastCallback callback, void *userdata) { + /* don't use this because this dist value could be incompatible + * this value used by the callback for comparing prev/new dist values. + * also, at the moment there is no need to have a corrected 'dist' value */ +// #define USE_DIST_CORRECT + float tmp_co[3], tmp_no[3]; const float *co, *no; BVHTreeRayHit hit_tmp; - //Copy from hit (we need to convert hit rays from one space coordinates to the other + /* Copy from hit (we need to convert hit rays from one space coordinates to the other */ memcpy(&hit_tmp, hit, sizeof(hit_tmp)); - //Apply space transform (TODO readjust dist) + /* Apply space transform (TODO readjust dist) */ if (transf) { copy_v3_v3(tmp_co, vert); space_transform_apply(transf, tmp_co); @@ -228,7 +242,9 @@ int normal_projection_project_vertex(char options, const float vert[3], const fl space_transform_apply_normal(transf, tmp_no); no = tmp_no; +#ifdef USE_DIST_CORRECT hit_tmp.dist *= mat4_to_scale(((SpaceTransform *)transf)->local2target); +#endif } else { co = vert; @@ -249,7 +265,7 @@ int normal_projection_project_vertex(char options, const float vert[3], const fl /* apply backface */ const float dot = dot_v3v3(dir, hit_tmp.no); if (((options & MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE) && dot <= 0.0f) || - ((options & MOD_SHRINKWRAP_CULL_TARGET_BACKFACE) && dot >= 0.0f)) + ((options & MOD_SHRINKWRAP_CULL_TARGET_BACKFACE) && dot >= 0.0f)) { return FALSE; /* Ignore hit */ } @@ -258,9 +274,13 @@ int normal_projection_project_vertex(char options, const float vert[3], const fl if (transf) { /* Inverting space transform (TODO make coeherent with the initial dist readjust) */ space_transform_invert(transf, hit_tmp.co); - hit_tmp.dist = len_v3v3((float *)vert, hit_tmp.co); +#ifdef USE_DIST_CORRECT + hit_tmp.dist = len_v3v3(vert, hit_tmp.co); +#endif } + BLI_assert(hit_tmp.dist <= hit->dist); + memcpy(hit, &hit_tmp, sizeof(hit_tmp)); return TRUE; } @@ -272,41 +292,46 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) { int i; - //Options about projection direction + /* Options about projection direction */ const char use_normal = calc->smd->shrinkOpts; float proj_axis[3] = {0.0f, 0.0f, 0.0f}; - //Raycast and tree stuff + /* Raycast and tree stuff */ + + /** \note 'hit.dist' is kept in the targets space, this is only used + * for finding the best hit, to get the real dist, + * measure the len_v3v3() from the input coord to hit.co */ BVHTreeRayHit hit; BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh; - //auxiliary target + /* auxiliary target */ DerivedMesh *auxMesh = NULL; BVHTreeFromMesh auxData = NULL_BVHTreeFromMesh; SpaceTransform local2aux; - //If the user doesn't allows to project in any direction of projection axis - //then theres nothing todo. + /* If the user doesn't allows to project in any direction of projection axis + * then theres nothing todo. */ if ((use_normal & (MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR | MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR)) == 0) return; - //Prepare data to retrieve the direction in which we should project each vertex + /* Prepare data to retrieve the direction in which we should project each vertex */ if (calc->smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL) { if (calc->vert == NULL) return; } else { - //The code supports any axis that is a combination of X,Y,Z - //although currently UI only allows to set the 3 different axis + /* The code supports any axis that is a combination of X,Y,Z + * although currently UI only allows to set the 3 different axis */ if (calc->smd->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS) proj_axis[0] = 1.0f; if (calc->smd->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS) proj_axis[1] = 1.0f; if (calc->smd->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS) proj_axis[2] = 1.0f; normalize_v3(proj_axis); - //Invalid projection direction - if (dot_v3v3(proj_axis, proj_axis) < FLT_EPSILON) - return; + /* Invalid projection direction */ + if (len_squared_v3(proj_axis) < FLT_EPSILON) { + return; + } } if (calc->smd->auxTarget) { @@ -316,7 +341,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->smd->auxTarget); } - //After sucessufuly build the trees, start projection vertexs + /* After sucessufuly build the trees, start projection vertexs */ if (bvhtree_from_mesh_faces(&treeData, calc->target, 0.0, 4, 6) && (auxMesh == NULL || bvhtree_from_mesh_faces(&auxData, auxMesh, 0.0, 4, 6))) { @@ -327,9 +352,11 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) for (i = 0; i < calc->numVerts; ++i) { float *co = calc->vertexCos[i]; float tmp_co[3], tmp_no[3]; - float weight = defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup); + const float weight = defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup); - if (weight == 0.0f) continue; + if (weight == 0.0f) { + continue; + } if (calc->vert) { /* calc->vert contains verts from derivedMesh */ @@ -351,26 +378,36 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) hit.index = -1; - hit.dist = 10000.0f; //TODO: we should use FLT_MAX here, but sweepsphere code isn't prepared for that + hit.dist = 10000.0f; /* TODO: we should use FLT_MAX here, but sweepsphere code isn't prepared for that */ - //Project over positive direction of axis + /* Project over positive direction of axis */ if (use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR) { - if (auxData.tree) - normal_projection_project_vertex(0, tmp_co, tmp_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData); + if (auxData.tree) { + normal_projection_project_vertex(0, tmp_co, tmp_no, + &local2aux, auxData.tree, &hit, + auxData.raycast_callback, &auxData); + } - normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, tmp_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData); + normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, tmp_no, + &calc->local2target, treeData.tree, &hit, + treeData.raycast_callback, &treeData); } - //Project over negative direction of axis - if (use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR && hit.index == -1) { + /* Project over negative direction of axis */ + if (use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR) { float inv_no[3]; negate_v3_v3(inv_no, tmp_no); - if (auxData.tree) - normal_projection_project_vertex(0, tmp_co, inv_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData); + if (auxData.tree) { + normal_projection_project_vertex(0, tmp_co, inv_no, + &local2aux, auxData.tree, &hit, + auxData.raycast_callback, &auxData); + } - normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, inv_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData); + normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, inv_no, + &calc->local2target, treeData.tree, &hit, + treeData.raycast_callback, &treeData); } @@ -381,7 +418,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) } } - //free data structures + /* free data structures */ free_bvhtree_from_mesh(&treeData); free_bvhtree_from_mesh(&auxData); } @@ -399,19 +436,19 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh; BVHTreeNearest nearest = NULL_BVHTreeNearest; - //Create a bvh-tree of the given target + /* Create a bvh-tree of the given target */ BENCH(bvhtree_from_mesh_faces(&treeData, calc->target, 0.0, 2, 6)); if (treeData.tree == NULL) { OUT_OF_MEMORY(); return; } - //Setup nearest + /* Setup nearest */ nearest.index = -1; nearest.dist = FLT_MAX; - //Find the nearest vertex + /* Find the nearest vertex */ #ifndef __APPLE__ #pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(calc,treeData) schedule(static) #endif @@ -421,7 +458,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) float weight = defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup); if (weight == 0.0f) continue; - //Convert the vertex to tree coordinates + /* Convert the vertex to tree coordinates */ if (calc->vert) { copy_v3_v3(tmp_co, calc->vert[i].co); } @@ -430,11 +467,11 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) } space_transform_apply(&calc->local2target, tmp_co); - //Use local proximity heuristics (to reduce the nearest search) - // - //If we already had an hit before.. we assume this vertex is going to have a close hit to that other vertex - //so we can initiate the "nearest.dist" with the expected value to that last hit. - //This will lead in prunning of the search tree. + /* Use local proximity heuristics (to reduce the nearest search) + * + * If we already had an hit before.. we assume this vertex is going to have a close hit to that other vertex + * so we can initiate the "nearest.dist" with the expected value to that last hit. + * This will lead in prunning of the search tree. */ if (nearest.index != -1) nearest.dist = len_squared_v3v3(tmp_co, nearest.co); else @@ -442,24 +479,28 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) BLI_bvhtree_find_nearest(treeData.tree, tmp_co, &nearest, treeData.nearest_callback, &treeData); - //Found the nearest vertex + /* Found the nearest vertex */ if (nearest.index != -1) { if (calc->smd->shrinkOpts & MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE) { - //Make the vertex stay on the front side of the face + /* Make the vertex stay on the front side of the face */ madd_v3_v3v3fl(tmp_co, nearest.co, nearest.no, calc->keepDist); } else { - //Adjusting the vertex weight, so that after interpolating it keeps a certain distance from the nearest position + /* Adjusting the vertex weight, + * so that after interpolating it keeps a certain distance from the nearest position */ float dist = sasqrt(nearest.dist); - if (dist > FLT_EPSILON) - interp_v3_v3v3(tmp_co, tmp_co, nearest.co, (dist - calc->keepDist) / dist); //linear interpolation - else + if (dist > FLT_EPSILON) { + /* linear interpolation */ + interp_v3_v3v3(tmp_co, tmp_co, nearest.co, (dist - calc->keepDist) / dist); + } + else { copy_v3_v3(tmp_co, nearest.co); + } } - //Convert the coordinates back to mesh coordinates + /* Convert the coordinates back to mesh coordinates */ space_transform_invert(&calc->local2target, tmp_co); - interp_v3_v3v3(co, co, tmp_co, weight); //linear interpolation + interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */ } } @@ -467,24 +508,25 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) } /* Main shrinkwrap function */ -void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) +void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, + float (*vertexCos)[3], int numVerts) { DerivedMesh *ss_mesh = NULL; ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData; - //remove loop dependencies on derived meshs (TODO should this be done elsewhere?) + /* remove loop dependencies on derived meshs (TODO should this be done elsewhere?) */ if (smd->target == ob) smd->target = NULL; if (smd->auxTarget == ob) smd->auxTarget = NULL; - //Configure Shrinkwrap calc data + /* Configure Shrinkwrap calc data */ calc.smd = smd; calc.ob = ob; calc.numVerts = numVerts; calc.vertexCos = vertexCos; - //DeformVertex + /* DeformVertex */ calc.vgroup = defgroup_name_index(calc.ob, calc.smd->vgroup_name); if (dm) { calc.dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); @@ -497,12 +539,12 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM if (smd->target) { calc.target = object_get_derived_final(smd->target); - //TODO there might be several "bugs" on non-uniform scales matrixs - //because it will no longer be nearest surface, not sphere projection - //because space has been deformed + /* TODO there might be several "bugs" on non-uniform scales matrixs + * because it will no longer be nearest surface, not sphere projection + * because space has been deformed */ SPACE_TRANSFORM_SETUP(&calc.local2target, ob, smd->target); - //TODO: smd->keepDist is in global units.. must change to local + /* TODO: smd->keepDist is in global units.. must change to local */ calc.keepDist = smd->keepDist; } @@ -511,15 +553,15 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM calc.vgroup = defgroup_name_index(calc.ob, smd->vgroup_name); if (dm != NULL && smd->shrinkType == MOD_SHRINKWRAP_PROJECT) { - //Setup arrays to get vertexs positions, normals and deform weights + /* Setup arrays to get vertexs positions, normals and deform weights */ calc.vert = dm->getVertDataArray(dm, CD_MVERT); calc.dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); - //Using vertexs positions/normals as if a subsurface was applied + /* Using vertexs positions/normals as if a subsurface was applied */ if (smd->subsurfLevels) { SubsurfModifierData ssmd = {{NULL}}; - ssmd.subdivType = ME_CC_SUBSURF; //catmull clark - ssmd.levels = smd->subsurfLevels; //levels + ssmd.subdivType = ME_CC_SUBSURF; /* catmull clark */ + ssmd.levels = smd->subsurfLevels; /* levels */ ss_mesh = subsurf_make_derived_from_derived(dm, &ssmd, NULL, (ob->mode & OB_MODE_EDIT) ? SUBSURF_IN_EDIT_MODE : 0); @@ -532,13 +574,13 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM } } - //Just to make sure we are not leaving any memory behind + /* Just to make sure we are not leaving any memory behind */ assert(ssmd.emCache == NULL); assert(ssmd.mCache == NULL); } } - //Projecting target defined - lets work! + /* Projecting target defined - lets work! */ if (calc.target) { switch (smd->shrinkType) { case MOD_SHRINKWRAP_NEAREST_SURFACE: @@ -555,8 +597,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM } } - //free memory + /* free memory */ if (ss_mesh) ss_mesh->release(ss_mesh); } - diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 5e67e094e43..443aed1fc41 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -51,18 +51,7 @@ #include "BLI_kdtree.h" #include "BLI_kdopbvh.h" #include "BLI_utildefines.h" - -#include "BKE_bvhutils.h" -#include "BKE_cdderivedmesh.h" -#include "BKE_collision.h" -#include "BKE_customdata.h" -#include "BKE_DerivedMesh.h" -#include "BKE_effect.h" -#include "BKE_modifier.h" -#include "BKE_particle.h" -#include "BKE_pointcache.h" -#include "BKE_smoke.h" - +#include "BLI_voxel.h" #include "DNA_customdata_types.h" #include "DNA_group_types.h" @@ -75,8 +64,20 @@ #include "DNA_scene_types.h" #include "DNA_smoke_types.h" +#include "BKE_bvhutils.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_collision.h" +#include "BKE_customdata.h" +#include "BKE_deform.h" +#include "BKE_DerivedMesh.h" +#include "BKE_effect.h" +#include "BKE_modifier.h" +#include "BKE_particle.h" +#include "BKE_pointcache.h" #include "BKE_smoke.h" +#include "RE_shader_ext.h" + /* UNUSED so far, may be enabled later */ /* #define USE_SMOKE_COLLISION_DM */ @@ -94,38 +95,38 @@ static LARGE_INTEGER liFrequency; static LARGE_INTEGER liStartTime; static LARGE_INTEGER liCurrentTime; -static void tstart ( void ) +static void tstart(void) { - QueryPerformanceFrequency ( &liFrequency ); - QueryPerformanceCounter ( &liStartTime ); + QueryPerformanceFrequency(&liFrequency); + QueryPerformanceCounter(&liStartTime); } -static void tend ( void ) +static void tend(void) { - QueryPerformanceCounter ( &liCurrentTime ); + QueryPerformanceCounter(&liCurrentTime); } -static double UNUSED_FUNCTION(tval)( void ) +static double tval(void) { - return ((double)( (liCurrentTime.QuadPart - liStartTime.QuadPart)* (double)1000.0/(double)liFrequency.QuadPart )); + return ((double)( (liCurrentTime.QuadPart - liStartTime.QuadPart) * (double)1000.0 / (double)liFrequency.QuadPart)); } #else #include static struct timeval _tstart, _tend; static struct timezone tz; -static void tstart ( void ) +static void tstart(void) { - gettimeofday ( &_tstart, &tz ); + gettimeofday(&_tstart, &tz); } -static void tend ( void ) +static void tend(void) { - gettimeofday ( &_tend,&tz ); + gettimeofday(&_tend, &tz); } -static double UNUSED_FUNCTION(tval)( void ) +static double UNUSED_FUNCTION(tval) (void) { double t1, t2; - t1 = ( double ) _tstart.tv_sec*1000 + ( double ) _tstart.tv_usec/ ( 1000 ); - t2 = ( double ) _tend.tv_sec*1000 + ( double ) _tend.tv_usec/ ( 1000 ); - return t2-t1; + t1 = ( double ) _tstart.tv_sec * 1000 + ( double ) _tstart.tv_usec / (1000); + t2 = ( double ) _tend.tv_sec * 1000 + ( double ) _tend.tv_usec / (1000); + return t2 - t1; } #endif @@ -134,608 +135,238 @@ struct Scene; struct DerivedMesh; struct SmokeModifierData; -#define TRI_UVOFFSET (1./4.) - // timestep default value for nice appearance 0.1f #define DT_DEFAULT 0.1f -/* forward declerations */ -static void calcTriangleDivs(Object *ob, MVert *verts, int numverts, MFace *tris, int numfaces, int numtris, int **tridivs, float cell_len); -static void get_cell(const float p0[3], const int res[3], float dx, const float pos[3], int cell[3], int correct); -static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs); +#define ADD_IF_LOWER_POS(a, b) (MIN2((a) + (b), MAX2((a), (b)))) +#define ADD_IF_LOWER_NEG(a, b) (MAX2((a) + (b), MIN2((a), (b)))) +#define ADD_IF_LOWER(a, b) (((b) > 0) ? ADD_IF_LOWER_POS((a), (b)) : ADD_IF_LOWER_NEG((a), (b))) #else /* WITH_SMOKE */ /* Stubs to use when smoke is disabled */ -struct WTURBULENCE *smoke_turbulence_init(int *UNUSED(res), int UNUSED(amplify), int UNUSED(noisetype)) { return NULL; } -// struct FLUID_3D *smoke_init(int *UNUSED(res), float *UNUSED(p0)) { return NULL; } +struct WTURBULENCE *smoke_turbulence_init(int *UNUSED(res), int UNUSED(amplify), int UNUSED(noisetype), int UNUSED(use_fire), int UNUSED(use_colors)) { return NULL; } +//struct FLUID_3D *smoke_init(int *UNUSED(res), float *UNUSED(dx), float *UNUSED(dtdef), int UNUSED(use_heat), int UNUSED(use_fire), int UNUSED(use_colors)) { return NULL; } void smoke_free(struct FLUID_3D *UNUSED(fluid)) {} float *smoke_get_density(struct FLUID_3D *UNUSED(fluid)) { return NULL; } void smoke_turbulence_free(struct WTURBULENCE *UNUSED(wt)) {} void smoke_initWaveletBlenderRNA(struct WTURBULENCE *UNUSED(wt), float *UNUSED(strength)) {} -void smoke_initBlenderRNA(struct FLUID_3D *UNUSED(fluid), float *UNUSED(alpha), float *UNUSED(beta), float *UNUSED(dt_factor), float *UNUSED(vorticity), int *UNUSED(border_colli)) {} -long long smoke_get_mem_req(int UNUSED(xres), int UNUSED(yres), int UNUSED(zres), int UNUSED(amplify)) { return 0; } -void smokeModifier_do(SmokeModifierData *UNUSED(smd), Scene *UNUSED(scene), Object *UNUSED(ob), DerivedMesh *UNUSED(dm)) {} +void smoke_initBlenderRNA(struct FLUID_3D *UNUSED(fluid), float *UNUSED(alpha), float *UNUSED(beta), float *UNUSED(dt_factor), float *UNUSED(vorticity), + int *UNUSED(border_colli), float *UNUSED(burning_rate), float *UNUSED(flame_smoke), float *UNUSED(flame_smoke_color), + float *UNUSED(flame_vorticity), float *UNUSED(flame_ignition_temp), float *UNUSED(flame_max_temp)) {} +struct DerivedMesh *smokeModifier_do(SmokeModifierData *UNUSED(smd), Scene *UNUSED(scene), Object *UNUSED(ob), DerivedMesh *UNUSED(dm)) { return NULL; } +float smoke_get_velocity_at(struct Object *UNUSED(ob), float UNUSED(position[3]), float UNUSED(velocity[3])) { return 0.0f; } +void flame_get_spectrum(unsigned char *UNUSED(spec), int UNUSED(width), float UNUSED(t1), float UNUSED(t2)) {} #endif /* WITH_SMOKE */ #ifdef WITH_SMOKE -static int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, DerivedMesh *dm) +void smoke_reallocate_fluid(SmokeDomainSettings *sds, float dx, int res[3], int free_old) { - if((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain && !smd->domain->fluid) + int use_heat = (sds->active_fields & SM_ACTIVE_HEAT); + int use_fire = (sds->active_fields & (SM_ACTIVE_HEAT | SM_ACTIVE_FIRE)); + int use_colors = (sds->active_fields & SM_ACTIVE_COLORS); + + if (free_old && sds->fluid) + smoke_free(sds->fluid); + if (!MIN3(res[0], res[1], res[2])) { + sds->fluid = NULL; + return; + } + sds->fluid = smoke_init(res, dx, DT_DEFAULT, use_heat, use_fire, use_colors); + smoke_initBlenderRNA(sds->fluid, &(sds->alpha), &(sds->beta), &(sds->time_scale), &(sds->vorticity), &(sds->border_collisions), + &(sds->burning_rate), &(sds->flame_smoke), sds->flame_smoke_color, &(sds->flame_vorticity), &(sds->flame_ignition), &(sds->flame_max_temp)); + + /* reallocate shadow buffer */ + if (sds->shadow) + MEM_freeN(sds->shadow); + sds->shadow = MEM_callocN(sizeof(float) * res[0] * res[1] * res[2], "SmokeDomainShadow"); +} + +void smoke_reallocate_highres_fluid(SmokeDomainSettings *sds, float dx, int res[3], int free_old) +{ + int use_fire = (sds->active_fields & (SM_ACTIVE_HEAT | SM_ACTIVE_FIRE)); + int use_colors = (sds->active_fields & SM_ACTIVE_COLORS); + + if (free_old && sds->wt) + smoke_turbulence_free(sds->wt); + if (!MIN3(res[0], res[1], res[2])) { + sds->wt = NULL; + return; + } + sds->wt = smoke_turbulence_init(res, sds->amplify + 1, sds->noise, use_fire, use_colors); + sds->res_wt[0] = res[0] * (sds->amplify + 1); + sds->res_wt[1] = res[1] * (sds->amplify + 1); + sds->res_wt[2] = res[2] * (sds->amplify + 1); + sds->dx_wt = dx / (sds->amplify + 1); + smoke_initWaveletBlenderRNA(sds->wt, &(sds->strength)); +} + +/* convert global position to domain cell space */ +static void smoke_pos_to_cell(SmokeDomainSettings *sds, float pos[3]) +{ + mul_m4_v3(sds->imat, pos); + sub_v3_v3(pos, sds->p0); + pos[0] *= 1.0f / sds->cell_size[0]; + pos[1] *= 1.0f / sds->cell_size[1]; + pos[2] *= 1.0f / sds->cell_size[2]; +} + +/* set domain resolution and dimensions from object derivedmesh */ +static void smoke_set_domain_from_derivedmesh(SmokeDomainSettings *sds, Object *ob, DerivedMesh *dm) +{ + size_t i; + float min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}, max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX}; + float size[3]; + MVert *verts = dm->getVertArray(dm); + float scale = 0.0; + int res; + + res = sds->maxres; + + // get BB of domain + for (i = 0; i < dm->getNumVerts(dm); i++) { - size_t i; - float min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}, max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX}; - float size[3]; - MVert *verts = dm->getVertArray(dm); - float scale = 0.0; - int res; + // min BB + min[0] = MIN2(min[0], verts[i].co[0]); + min[1] = MIN2(min[1], verts[i].co[1]); + min[2] = MIN2(min[2], verts[i].co[2]); - res = smd->domain->maxres; + // max BB + max[0] = MAX2(max[0], verts[i].co[0]); + max[1] = MAX2(max[1], verts[i].co[1]); + max[2] = MAX2(max[2], verts[i].co[2]); + } - // get BB of domain - for(i = 0; i < dm->getNumVerts(dm); i++) - { - float tmp[3]; + /* set domain bounds */ + copy_v3_v3(sds->p0, min); + copy_v3_v3(sds->p1, max); + sds->dx = 1.0f / res; - copy_v3_v3(tmp, verts[i].co); - mul_m4_v3(ob->obmat, tmp); + /* calculate domain dimensions */ + sub_v3_v3v3(size, max, min); + copy_v3_v3(sds->cell_size, size); + mul_v3_v3(size, ob->size); + copy_v3_v3(sds->global_size, size); + copy_v3_v3(sds->dp0, min); - // min BB - min[0] = MIN2(min[0], tmp[0]); - min[1] = MIN2(min[1], tmp[1]); - min[2] = MIN2(min[2], tmp[2]); + invert_m4_m4(sds->imat, ob->obmat); - // max BB - max[0] = MAX2(max[0], tmp[0]); - max[1] = MAX2(max[1], tmp[1]); - max[2] = MAX2(max[2], tmp[2]); - } + // prevent crash when initializing a plane as domain + if ((size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) || (size[2] < FLT_EPSILON)) + return; - copy_v3_v3(smd->domain->p0, min); - copy_v3_v3(smd->domain->p1, max); + /* define grid resolutions from longest domain side */ + if (size[0] > MAX2(size[1], size[2])) { + scale = res / size[0]; + sds->scale = size[0] / ob->size[0]; + sds->base_res[0] = res; + sds->base_res[1] = (int)(size[1] * scale + 0.5); + sds->base_res[2] = (int)(size[2] * scale + 0.5); + } + else if (size[1] > MAX2(size[0], size[2])) { + scale = res / size[1]; + sds->scale = size[1] / ob->size[1]; + sds->base_res[0] = (int)(size[0] * scale + 0.5); + sds->base_res[1] = res; + sds->base_res[2] = (int)(size[2] * scale + 0.5); + } + else { + scale = res / size[2]; + sds->scale = size[2] / ob->size[2]; + sds->base_res[0] = (int)(size[0] * scale + 0.5); + sds->base_res[1] = (int)(size[1] * scale + 0.5); + sds->base_res[2] = res; + } - // calc other res with max_res provided - sub_v3_v3v3(size, max, min); + /* set cell size */ + sds->cell_size[0] /= (float)sds->base_res[0]; + sds->cell_size[1] /= (float)sds->base_res[1]; + sds->cell_size[2] /= (float)sds->base_res[2]; +} - // prevent crash when initializing a plane as domain - if((size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) || (size[2] < FLT_EPSILON)) - return 0; +static int smokeModifier_init(SmokeModifierData *smd, Object *ob, Scene *scene, DerivedMesh *dm) +{ + if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain && !smd->domain->fluid) + { + SmokeDomainSettings *sds = smd->domain; + int res[3]; + /* set domain dimensions from derivedmesh */ + smoke_set_domain_from_derivedmesh(sds, ob, dm); + /* reset domain values */ + zero_v3_int(sds->shift); + zero_v3(sds->shift_f); + add_v3_fl(sds->shift_f, 0.5f); + zero_v3(sds->prev_loc); + mul_m4_v3(ob->obmat, sds->prev_loc); - if(size[0] > size[1]) - { - if(size[0] > size[2]) - { - scale = res / size[0]; - smd->domain->scale = size[0]; - smd->domain->dx = 1.0f / res; - smd->domain->res[0] = res; - smd->domain->res[1] = (int)(size[1] * scale + 0.5); - smd->domain->res[2] = (int)(size[2] * scale + 0.5); - } - else { - scale = res / size[2]; - smd->domain->scale = size[2]; - smd->domain->dx = 1.0f / res; - smd->domain->res[2] = res; - smd->domain->res[0] = (int)(size[0] * scale + 0.5); - smd->domain->res[1] = (int)(size[1] * scale + 0.5); - } + /* set resolutions */ + if (smd->domain->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) { + res[0] = res[1] = res[2] = 1; /* use minimum res for adaptive init */ } else { - if(size[1] > size[2]) - { - scale = res / size[1]; - smd->domain->scale = size[1]; - smd->domain->dx = 1.0f / res; - smd->domain->res[1] = res; - smd->domain->res[0] = (int)(size[0] * scale + 0.5); - smd->domain->res[2] = (int)(size[2] * scale + 0.5); - } - else { - scale = res / size[2]; - smd->domain->scale = size[2]; - smd->domain->dx = 1.0f / res; - smd->domain->res[2] = res; - smd->domain->res[0] = (int)(size[0] * scale + 0.5); - smd->domain->res[1] = (int)(size[1] * scale + 0.5); - } + VECCOPY(res, sds->base_res); } + VECCOPY(sds->res, res); + sds->total_cells = sds->res[0] * sds->res[1] * sds->res[2]; + sds->res_min[0] = sds->res_min[1] = sds->res_min[2] = 0; + VECCOPY(sds->res_max, res); - // TODO: put in failsafe if res<=0 - dg + /* allocate fluid */ + smoke_reallocate_fluid(sds, sds->dx, sds->res, 0); - // dt max is 0.1 - smd->domain->fluid = smoke_init(smd->domain->res, smd->domain->p0, DT_DEFAULT); smd->time = scene->r.cfra; - if(smd->domain->flags & MOD_SMOKE_HIGHRES) - { - smd->domain->wt = smoke_turbulence_init(smd->domain->res, smd->domain->amplify + 1, smd->domain->noise); - smd->domain->res_wt[0] = smd->domain->res[0] * (smd->domain->amplify + 1); - smd->domain->res_wt[1] = smd->domain->res[1] * (smd->domain->amplify + 1); - smd->domain->res_wt[2] = smd->domain->res[2] * (smd->domain->amplify + 1); - smd->domain->dx_wt = smd->domain->dx / (smd->domain->amplify + 1); + /* allocate highres fluid */ + if (sds->flags & MOD_SMOKE_HIGHRES) { + smoke_reallocate_highres_fluid(sds, sds->dx, sds->res, 0); } + /* allocate shadow buffer */ + if (!sds->shadow) + sds->shadow = MEM_callocN(sizeof(float) * sds->res[0] * sds->res[1] * sds->res[2], "SmokeDomainShadow"); - if(!smd->domain->shadow) - smd->domain->shadow = MEM_callocN(sizeof(float) * smd->domain->res[0] * smd->domain->res[1] * smd->domain->res[2], "SmokeDomainShadow"); - - smoke_initBlenderRNA(smd->domain->fluid, &(smd->domain->alpha), &(smd->domain->beta), &(smd->domain->time_scale), &(smd->domain->vorticity), &(smd->domain->border_collisions)); - - if(smd->domain->wt) - { - smoke_initWaveletBlenderRNA(smd->domain->wt, &(smd->domain->strength)); - } return 1; } - else if((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) + else if ((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) { - // handle flow object here - // XXX TODO - smd->time = scene->r.cfra; return 1; } - else if((smd->type & MOD_SMOKE_TYPE_COLL)) + else if ((smd->type & MOD_SMOKE_TYPE_COLL)) { - // todo: delete this when loading colls work -dg - - if(!smd->coll) + if (!smd->coll) { smokeModifier_createType(smd); } - if(!smd->coll->points) - { - // init collision points - SmokeCollSettings *scs = smd->coll; + smd->time = scene->r.cfra; - smd->time = scene->r.cfra; - - // copy obmat - copy_m4_m4(scs->mat, ob->obmat); - copy_m4_m4(scs->mat_old, ob->obmat); - - DM_ensure_tessface(dm); - fill_scs_points(ob, dm, scs); - } - - if(!smd->coll->bvhtree) - { - smd->coll->bvhtree = NULL; // bvhtree_build_from_smoke ( ob->obmat, dm->getTessFaceArray(dm), dm->getNumTessFaces(dm), dm->getVertArray(dm), dm->getNumVerts(dm), 0.0 ); - } return 1; } return 2; } -static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs) -{ - MVert *mvert = dm->getVertArray(dm); - MFace *mface = dm->getTessFaceArray(dm); - int i = 0, divs = 0; - - // DG TODO: need to do this dynamically according to the domain object! - float cell_len = scs->dx; - int newdivs = 0; - int quads = 0, facecounter = 0; - - // count quads - for(i = 0; i < dm->getNumTessFaces(dm); i++) - { - if(mface[i].v4) - quads++; - } - - scs->numtris = dm->getNumTessFaces(dm) + quads; - scs->tridivs = NULL; - calcTriangleDivs(ob, mvert, dm->getNumVerts(dm), mface, dm->getNumTessFaces(dm), scs->numtris, &(scs->tridivs), cell_len); - - // count triangle divisions - for(i = 0; i < dm->getNumTessFaces(dm) + quads; i++) - { - divs += (scs->tridivs[3 * i] + 1) * (scs->tridivs[3 * i + 1] + 1) * (scs->tridivs[3 * i + 2] + 1); - } - - scs->points = MEM_callocN(sizeof(float) * (dm->getNumVerts(dm) + divs) * 3, "SmokeCollPoints"); - scs->points_old = MEM_callocN(sizeof(float) * (dm->getNumVerts(dm) + divs) * 3, "SmokeCollPointsOld"); - - for(i = 0; i < dm->getNumVerts(dm); i++) - { - float tmpvec[3]; - copy_v3_v3(tmpvec, mvert[i].co); - // mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway - copy_v3_v3(&scs->points[i * 3], tmpvec); - } - - for(i = 0, facecounter = 0; i < dm->getNumTessFaces(dm); i++) - { - int again = 0; - do - { - int j, k; - int divs1 = scs->tridivs[3 * facecounter + 0]; - int divs2 = scs->tridivs[3 * facecounter + 1]; - //int divs3 = scs->tridivs[3 * facecounter + 2]; - float side1[3], side2[3], trinormorg[3], trinorm[3]; - - if(again == 1 && mface[i].v4) - { - sub_v3_v3v3(side1, mvert[ mface[i].v3 ].co, mvert[ mface[i].v1 ].co); - sub_v3_v3v3(side2, mvert[ mface[i].v4 ].co, mvert[ mface[i].v1 ].co); - } - else { - sub_v3_v3v3(side1, mvert[ mface[i].v2 ].co, mvert[ mface[i].v1 ].co); - sub_v3_v3v3(side2, mvert[ mface[i].v3 ].co, mvert[ mface[i].v1 ].co); - } - - cross_v3_v3v3(trinormorg, side1, side2); - normalize_v3(trinormorg); - copy_v3_v3(trinorm, trinormorg); - mul_v3_fl(trinorm, 0.25 * cell_len); - - for(j = 0; j <= divs1; j++) - { - for(k = 0; k <= divs2; k++) - { - float p1[3], p2[3], p3[3], p[3]={0,0,0}; - const float uf = (float)(j + TRI_UVOFFSET) / (float)(divs1 + 0.0); - const float vf = (float)(k + TRI_UVOFFSET) / (float)(divs2 + 0.0); - float tmpvec[3]; - - if(uf+vf > 1.0) - { - // printf("bigger - divs1: %d, divs2: %d\n", divs1, divs2); - continue; - } - - copy_v3_v3(p1, mvert[ mface[i].v1 ].co); - if(again == 1 && mface[i].v4) - { - copy_v3_v3(p2, mvert[ mface[i].v3 ].co); - copy_v3_v3(p3, mvert[ mface[i].v4 ].co); - } - else { - copy_v3_v3(p2, mvert[ mface[i].v2 ].co); - copy_v3_v3(p3, mvert[ mface[i].v3 ].co); - } - - mul_v3_fl(p1, (1.0-uf-vf)); - mul_v3_fl(p2, uf); - mul_v3_fl(p3, vf); - - add_v3_v3v3(p, p1, p2); - add_v3_v3(p, p3); - - if(newdivs > divs) - printf("mem problem\n"); - - // mMovPoints.push_back(p + trinorm); - add_v3_v3v3(tmpvec, p, trinorm); - // mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway - copy_v3_v3(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], tmpvec); - newdivs++; - - if(newdivs > divs) - printf("mem problem\n"); - - // mMovPoints.push_back(p - trinorm); - copy_v3_v3(tmpvec, p); - sub_v3_v3(tmpvec, trinorm); - // mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway - copy_v3_v3(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], tmpvec); - newdivs++; - } - } - - if(again == 0 && mface[i].v4) - again++; - else - again = 0; - - facecounter++; - - } while(again!=0); - } - - scs->numverts = dm->getNumVerts(dm); - // DG TODO: also save triangle count? - - scs->numpoints = dm->getNumVerts(dm) + newdivs; - - for(i = 0; i < scs->numpoints * 3; i++) - { - scs->points_old[i] = scs->points[i]; - } -} - - -static void fill_scs_points_anim(Object *UNUSED(ob), DerivedMesh *dm, SmokeCollSettings *scs) -{ - MVert *mvert = dm->getVertArray(dm); - MFace *mface = dm->getTessFaceArray(dm); - int quads = 0, numtris = 0, facecounter = 0; - unsigned int i = 0; - int divs = 0, newdivs = 0; - - // DG TODO: need to do this dynamically according to the domain object! - float cell_len = scs->dx; - - // count quads - for(i = 0; i < dm->getNumTessFaces(dm); i++) - { - if(mface[i].v4) - quads++; - } - - numtris = dm->getNumTessFaces(dm) + quads; - - // check if mesh changed topology - if(scs->numtris != numtris) - return; - if(scs->numverts != dm->getNumVerts(dm)) - return; - - // update new positions - for(i = 0; i < dm->getNumVerts(dm); i++) - { - float tmpvec[3]; - copy_v3_v3(tmpvec, mvert[i].co); - copy_v3_v3(&scs->points[i * 3], tmpvec); - } - - // for every triangle // update div points - for(i = 0, facecounter = 0; i < dm->getNumTessFaces(dm); i++) - { - int again = 0; - do - { - int j, k; - int divs1 = scs->tridivs[3 * facecounter + 0]; - int divs2 = scs->tridivs[3 * facecounter + 1]; - float srcside1[3], srcside2[3], destside1[3], destside2[3], src_trinormorg[3], dest_trinormorg[3], src_trinorm[3], dest_trinorm[3]; - - if(again == 1 && mface[i].v4) - { - sub_v3_v3v3(srcside1, &scs->points_old[mface[i].v3 * 3], &scs->points_old[mface[i].v1 * 3]); - sub_v3_v3v3(destside1, &scs->points[mface[i].v3 * 3], &scs->points[mface[i].v1 * 3]); - - sub_v3_v3v3(srcside2, &scs->points_old[mface[i].v4 * 3], &scs->points_old[mface[i].v1 * 3]); - sub_v3_v3v3(destside2, &scs->points[mface[i].v4 * 3], &scs->points[mface[i].v1 * 3]); - } - else { - sub_v3_v3v3(srcside1, &scs->points_old[mface[i].v2 * 3], &scs->points_old[mface[i].v1 * 3]); - sub_v3_v3v3(destside1, &scs->points[mface[i].v2 * 3], &scs->points[mface[i].v1 * 3]); - - sub_v3_v3v3(srcside2, &scs->points_old[mface[i].v3 * 3], &scs->points_old[mface[i].v1 * 3]); - sub_v3_v3v3(destside2, &scs->points[mface[i].v3 * 3], &scs->points[mface[i].v1 * 3]); - } - - cross_v3_v3v3(src_trinormorg, srcside1, srcside2); - cross_v3_v3v3(dest_trinormorg, destside1, destside2); - - normalize_v3(src_trinormorg); - normalize_v3(dest_trinormorg); - - copy_v3_v3(src_trinorm, src_trinormorg); - copy_v3_v3(dest_trinorm, dest_trinormorg); - - mul_v3_fl(src_trinorm, 0.25 * cell_len); - mul_v3_fl(dest_trinorm, 0.25 * cell_len); - - for(j = 0; j <= divs1; j++) - { - for(k = 0; k <= divs2; k++) - { - float src_p1[3], src_p2[3], src_p3[3], src_p[3]={0,0,0}; - float dest_p1[3], dest_p2[3], dest_p3[3], dest_p[3]={0,0,0}; - const float uf = (float)(j + TRI_UVOFFSET) / (float)(divs1 + 0.0); - const float vf = (float)(k + TRI_UVOFFSET) / (float)(divs2 + 0.0); - float src_tmpvec[3], dest_tmpvec[3]; - - if(uf+vf > 1.0) - { - // printf("bigger - divs1: %d, divs2: %d\n", divs1, divs2); - continue; - } - - copy_v3_v3(src_p1, &scs->points_old[mface[i].v1 * 3]); - copy_v3_v3(dest_p1, &scs->points[mface[i].v1 * 3]); - if(again == 1 && mface[i].v4) - { - copy_v3_v3(src_p2, &scs->points_old[mface[i].v3 * 3]); - copy_v3_v3(dest_p2, &scs->points[mface[i].v3 * 3]); - - copy_v3_v3(src_p3,&scs->points_old[mface[i].v4 * 3]); - copy_v3_v3(dest_p3, &scs->points[mface[i].v4 * 3]); - } - else { - copy_v3_v3(src_p2, &scs->points_old[mface[i].v2 * 3]); - copy_v3_v3(dest_p2, &scs->points[mface[i].v2 * 3]); - copy_v3_v3(src_p3, &scs->points_old[mface[i].v3 * 3]); - copy_v3_v3(dest_p3, &scs->points[mface[i].v3 * 3]); - } - - mul_v3_fl(src_p1, (1.0-uf-vf)); - mul_v3_fl(dest_p1, (1.0-uf-vf)); - - mul_v3_fl(src_p2, uf); - mul_v3_fl(dest_p2, uf); - - mul_v3_fl(src_p3, vf); - mul_v3_fl(dest_p3, vf); - - add_v3_v3v3(src_p, src_p1, src_p2); - add_v3_v3v3(dest_p, dest_p1, dest_p2); - - add_v3_v3(src_p, src_p3); - add_v3_v3(dest_p, dest_p3); - - if(newdivs > divs) - printf("mem problem\n"); - - // mMovPoints.push_back(p + trinorm); - add_v3_v3v3(src_tmpvec, src_p, src_trinorm); - add_v3_v3v3(dest_tmpvec, dest_p, dest_trinorm); - - // mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway - copy_v3_v3(&scs->points_old[3 * (dm->getNumVerts(dm) + newdivs)], src_tmpvec); - copy_v3_v3(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], dest_tmpvec); - newdivs++; - - if(newdivs > divs) - printf("mem problem\n"); - - // mMovPoints.push_back(p - trinorm); - copy_v3_v3(src_tmpvec, src_p); - copy_v3_v3(dest_tmpvec, dest_p); - - sub_v3_v3(src_tmpvec, src_trinorm); - sub_v3_v3(dest_tmpvec, dest_trinorm); - - // mul_m4_v3(ob->obmat, tmpvec); // DG: use local coordinates, we save MAT anyway - copy_v3_v3(&scs->points_old[3 * (dm->getNumVerts(dm) + newdivs)], src_tmpvec); - copy_v3_v3(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], dest_tmpvec); - newdivs++; - } - } - - if(again == 0 && mface[i].v4) - again++; - else - again = 0; - - facecounter++; - - } while(again!=0); - } - - // scs->numpoints = dm->getNumVerts(dm) + newdivs; - -} - -/*! init triangle divisions */ -static void calcTriangleDivs(Object *ob, MVert *verts, int UNUSED(numverts), MFace *faces, int numfaces, int numtris, int **tridivs, float cell_len) -{ - // mTriangleDivs1.resize( faces.size() ); - // mTriangleDivs2.resize( faces.size() ); - // mTriangleDivs3.resize( faces.size() ); - - size_t i = 0, facecounter = 0; - float maxscale[3] = {1,1,1}; // = channelFindMaxVf(mcScale); get max scale value - float maxpart = ABS(maxscale[0]); - float scaleFac = 0; - float fsTri = 0; - if(ABS(maxscale[1])>maxpart) maxpart = ABS(maxscale[1]); - if(ABS(maxscale[2])>maxpart) maxpart = ABS(maxscale[2]); - scaleFac = 1.0 / maxpart; - // featureSize = mLevel[mMaxRefine].nodeSize - fsTri = cell_len * 0.75 * scaleFac; // fsTri = cell_len * 0.9; - - if(*tridivs) - MEM_freeN(*tridivs); - - *tridivs = MEM_callocN(sizeof(int) * numtris * 3, "Smoke_Tridivs"); - - for(i = 0, facecounter = 0; i < numfaces; i++) - { - float p0[3], p1[3], p2[3]; - float side1[3]; - float side2[3]; - float side3[3]; - int divs1=0, divs2=0, divs3=0; - - copy_v3_v3(p0, verts[faces[i].v1].co); - mul_m4_v3(ob->obmat, p0); - copy_v3_v3(p1, verts[faces[i].v2].co); - mul_m4_v3(ob->obmat, p1); - copy_v3_v3(p2, verts[faces[i].v3].co); - mul_m4_v3(ob->obmat, p2); - - sub_v3_v3v3(side1, p1, p0); - sub_v3_v3v3(side2, p2, p0); - sub_v3_v3v3(side3, p1, p2); - - if(dot_v3v3(side1, side1) > fsTri*fsTri) - { - float tmp = normalize_v3(side1); - divs1 = (int)ceil(tmp/fsTri); - } - if(dot_v3v3(side2, side2) > fsTri*fsTri) - { - float tmp = normalize_v3(side2); - divs2 = (int)ceil(tmp/fsTri); - - /* - // debug - if(i==0) - printf("b tmp: %f, fsTri: %f, divs2: %d\n", tmp, fsTri, divs2); - */ - - } - - (*tridivs)[3 * facecounter + 0] = divs1; - (*tridivs)[3 * facecounter + 1] = divs2; - (*tridivs)[3 * facecounter + 2] = divs3; - - // TODO quad case - if(faces[i].v4) - { - divs1=0, divs2=0, divs3=0; - - facecounter++; - - copy_v3_v3(p0, verts[faces[i].v3].co); - mul_m4_v3(ob->obmat, p0); - copy_v3_v3(p1, verts[faces[i].v4].co); - mul_m4_v3(ob->obmat, p1); - copy_v3_v3(p2, verts[faces[i].v1].co); - mul_m4_v3(ob->obmat, p2); - - sub_v3_v3v3(side1, p1, p0); - sub_v3_v3v3(side2, p2, p0); - sub_v3_v3v3(side3, p1, p2); - - if(dot_v3v3(side1, side1) > fsTri*fsTri) - { - float tmp = normalize_v3(side1); - divs1 = (int)ceil(tmp/fsTri); - } - if(dot_v3v3(side2, side2) > fsTri*fsTri) - { - float tmp = normalize_v3(side2); - divs2 = (int)ceil(tmp/fsTri); - } - - (*tridivs)[3 * facecounter + 0] = divs1; - (*tridivs)[3 * facecounter + 1] = divs2; - (*tridivs)[3 * facecounter + 2] = divs3; - } - facecounter++; - } -} - #endif /* WITH_SMOKE */ static void smokeModifier_freeDomain(SmokeModifierData *smd) { - if(smd->domain) + if (smd->domain) { - if(smd->domain->shadow) - MEM_freeN(smd->domain->shadow); - smd->domain->shadow = NULL; + if (smd->domain->shadow) + MEM_freeN(smd->domain->shadow); + smd->domain->shadow = NULL; - if(smd->domain->fluid) + if (smd->domain->fluid) smoke_free(smd->domain->fluid); - if(smd->domain->wt) + if (smd->domain->wt) smoke_turbulence_free(smd->domain->wt); - if(smd->domain->effector_weights) - MEM_freeN(smd->domain->effector_weights); + if (smd->domain->effector_weights) + MEM_freeN(smd->domain->effector_weights); smd->domain->effector_weights = NULL; BKE_ptcache_free_list(&(smd->domain->ptcaches[0])); @@ -748,16 +379,10 @@ static void smokeModifier_freeDomain(SmokeModifierData *smd) static void smokeModifier_freeFlow(SmokeModifierData *smd) { - if(smd->flow) + if (smd->flow) { -/* - if(smd->flow->bvh) - { - free_bvhtree_from_mesh(smd->flow->bvh); - MEM_freeN(smd->flow->bvh); - } - smd->flow->bvh = NULL; -*/ + if (smd->flow->dm) smd->flow->dm->release(smd->flow->dm); + if (smd->flow->verts_old) MEM_freeN(smd->flow->verts_old); MEM_freeN(smd->flow); smd->flow = NULL; } @@ -765,40 +390,22 @@ static void smokeModifier_freeFlow(SmokeModifierData *smd) static void smokeModifier_freeCollision(SmokeModifierData *smd) { - if(smd->coll) + if (smd->coll) { SmokeCollSettings *scs = smd->coll; - if(scs->numpoints) + if (scs->numverts) { - if(scs->points) + if (scs->verts_old) { - MEM_freeN(scs->points); - scs->points = NULL; - } - if(scs->points_old) - { - MEM_freeN(scs->points_old); - scs->points_old = NULL; - } - if(scs->tridivs) - { - MEM_freeN(scs->tridivs); - scs->tridivs = NULL; + MEM_freeN(scs->verts_old); + scs->verts_old = NULL; } } - if(scs->bvhtree) - { - BLI_bvhtree_free(scs->bvhtree); - scs->bvhtree = NULL; - } - -#ifdef USE_SMOKE_COLLISION_DM - if(smd->coll->dm) + if (smd->coll->dm) smd->coll->dm->release(smd->coll->dm); smd->coll->dm = NULL; -#endif MEM_freeN(smd->coll); smd->coll = NULL; @@ -807,7 +414,7 @@ static void smokeModifier_freeCollision(SmokeModifierData *smd) void smokeModifier_reset_turbulence(struct SmokeModifierData *smd) { - if(smd && smd->domain && smd->domain->wt) + if (smd && smd->domain && smd->domain->wt) { smoke_turbulence_free(smd->domain->wt); smd->domain->wt = NULL; @@ -816,15 +423,15 @@ void smokeModifier_reset_turbulence(struct SmokeModifierData *smd) void smokeModifier_reset(struct SmokeModifierData *smd) { - if(smd) + if (smd) { - if(smd->domain) + if (smd->domain) { - if(smd->domain->shadow) + if (smd->domain->shadow) MEM_freeN(smd->domain->shadow); smd->domain->shadow = NULL; - if(smd->domain->fluid) + if (smd->domain->fluid) { smoke_free(smd->domain->fluid); smd->domain->fluid = NULL; @@ -833,39 +440,23 @@ void smokeModifier_reset(struct SmokeModifierData *smd) smokeModifier_reset_turbulence(smd); smd->time = -1; - - // printf("reset domain end\n"); + smd->domain->total_cells = 0; + smd->domain->active_fields = 0; } - else if(smd->flow) + else if (smd->flow) { - /* - if(smd->flow->bvh) - { - free_bvhtree_from_mesh(smd->flow->bvh); - MEM_freeN(smd->flow->bvh); - } - smd->flow->bvh = NULL; - */ + if (smd->flow->verts_old) MEM_freeN(smd->flow->verts_old); + smd->flow->verts_old = NULL; + smd->flow->numverts = 0; } - else if(smd->coll) + else if (smd->coll) { SmokeCollSettings *scs = smd->coll; - if(scs->numpoints && scs->points) + if (scs->numverts && scs->verts_old) { - MEM_freeN(scs->points); - scs->points = NULL; - - if(scs->points_old) - { - MEM_freeN(scs->points_old); - scs->points_old = NULL; - } - if(scs->tridivs) - { - MEM_freeN(scs->tridivs); - scs->tridivs = NULL; - } + MEM_freeN(scs->verts_old); + scs->verts_old = NULL; } } } @@ -873,7 +464,7 @@ void smokeModifier_reset(struct SmokeModifierData *smd) void smokeModifier_free(SmokeModifierData *smd) { - if(smd) + if (smd) { smokeModifier_freeDomain(smd); smokeModifier_freeFlow(smd); @@ -883,11 +474,11 @@ void smokeModifier_free(SmokeModifierData *smd) void smokeModifier_createType(struct SmokeModifierData *smd) { - if(smd) + if (smd) { - if(smd->type & MOD_SMOKE_TYPE_DOMAIN) + if (smd->type & MOD_SMOKE_TYPE_DOMAIN) { - if(smd->domain) + if (smd->domain) smokeModifier_freeDomain(smd); smd->domain = MEM_callocN(sizeof(SmokeDomainSettings), "SmokeDomain"); @@ -903,13 +494,12 @@ void smokeModifier_createType(struct SmokeModifierData *smd) smd->domain->ptcaches[1].first = smd->domain->ptcaches[1].last = NULL; /* set some standard values */ smd->domain->fluid = NULL; - smd->domain->wt = NULL; + smd->domain->wt = NULL; smd->domain->eff_group = NULL; smd->domain->fluid_group = NULL; smd->domain->coll_group = NULL; smd->domain->maxres = 32; - smd->domain->amplify = 1; - smd->domain->omega = 1.0; + smd->domain->amplify = 1; smd->domain->alpha = -0.001; smd->domain->beta = 0.1; smd->domain->time_scale = 1.0; @@ -919,14 +509,28 @@ void smokeModifier_createType(struct SmokeModifierData *smd) smd->domain->strength = 2.0; smd->domain->noise = MOD_SMOKE_NOISEWAVE; smd->domain->diss_speed = 5; - // init 3dview buffer + smd->domain->active_fields = 0; + + smd->domain->adapt_margin = 4; + smd->domain->adapt_res = 0; + smd->domain->adapt_threshold = 0.02f; + + smd->domain->burning_rate = 0.75f; + smd->domain->flame_smoke = 1.0f; + smd->domain->flame_vorticity = 0.5f; + smd->domain->flame_ignition = 1.25f; + smd->domain->flame_max_temp = 1.75f; + /* color */ + smd->domain->flame_smoke_color[0] = 0.7f; + smd->domain->flame_smoke_color[1] = 0.7f; + smd->domain->flame_smoke_color[2] = 0.7f; smd->domain->viewsettings = MOD_SMOKE_VIEW_SHOWBIG; smd->domain->effector_weights = BKE_add_effector_weights(NULL); } - else if(smd->type & MOD_SMOKE_TYPE_FLOW) + else if (smd->type & MOD_SMOKE_TYPE_FLOW) { - if(smd->flow) + if (smd->flow) smokeModifier_freeFlow(smd); smd->flow = MEM_callocN(sizeof(SmokeFlowSettings), "SmokeFlow"); @@ -934,31 +538,35 @@ void smokeModifier_createType(struct SmokeModifierData *smd) smd->flow->smd = smd; /* set some standard values */ - smd->flow->density = 1.0; - smd->flow->temp = 1.0; + smd->flow->density = 1.0f; + smd->flow->fuel_amount = 1.0f; + smd->flow->temp = 1.0f; smd->flow->flags = MOD_SMOKE_FLOW_ABSOLUTE; - smd->flow->vel_multi = 1.0; + smd->flow->vel_multi = 1.0f; + smd->flow->surface_distance = 1.5f; + smd->flow->source = MOD_SMOKE_FLOW_SOURCE_MESH; + smd->flow->texture_size = 1.0f; + smd->flow->color[0] = 0.7f; + smd->flow->color[1] = 0.7f; + smd->flow->color[2] = 0.7f; + + smd->flow->dm = NULL; smd->flow->psys = NULL; } - else if(smd->type & MOD_SMOKE_TYPE_COLL) + else if (smd->type & MOD_SMOKE_TYPE_COLL) { - if(smd->coll) + if (smd->coll) smokeModifier_freeCollision(smd); smd->coll = MEM_callocN(sizeof(SmokeCollSettings), "SmokeColl"); smd->coll->smd = smd; - smd->coll->points = NULL; - smd->coll->points_old = NULL; - smd->coll->tridivs = NULL; - smd->coll->vel = NULL; - smd->coll->numpoints = 0; - smd->coll->numtris = 0; - smd->coll->bvhtree = NULL; + smd->coll->verts_old = NULL; + smd->coll->numverts = 0; smd->coll->type = 0; // static obstacle - smd->coll->dx = 1.0f / 50.0f; + smd->coll->dm = NULL; #ifdef USE_SMOKE_COLLISION_DM smd->coll->dm = NULL; @@ -971,39 +579,67 @@ void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData { tsmd->type = smd->type; tsmd->time = smd->time; - + smokeModifier_createType(tsmd); if (tsmd->domain) { - tsmd->domain->maxres = smd->domain->maxres; - tsmd->domain->amplify = smd->domain->amplify; - tsmd->domain->omega = smd->domain->omega; - tsmd->domain->alpha = smd->domain->alpha; - tsmd->domain->beta = smd->domain->beta; - tsmd->domain->flags = smd->domain->flags; - tsmd->domain->strength = smd->domain->strength; - tsmd->domain->noise = smd->domain->noise; - tsmd->domain->diss_speed = smd->domain->diss_speed; - tsmd->domain->viewsettings = smd->domain->viewsettings; tsmd->domain->fluid_group = smd->domain->fluid_group; tsmd->domain->coll_group = smd->domain->coll_group; + + tsmd->domain->adapt_margin = smd->domain->adapt_margin; + tsmd->domain->adapt_res = smd->domain->adapt_res; + tsmd->domain->adapt_threshold = smd->domain->adapt_threshold; + + tsmd->domain->alpha = smd->domain->alpha; + tsmd->domain->beta = smd->domain->beta; + tsmd->domain->amplify = smd->domain->amplify; + tsmd->domain->maxres = smd->domain->maxres; + tsmd->domain->flags = smd->domain->flags; + tsmd->domain->viewsettings = smd->domain->viewsettings; + tsmd->domain->noise = smd->domain->noise; + tsmd->domain->diss_speed = smd->domain->diss_speed; + tsmd->domain->strength = smd->domain->strength; + + tsmd->domain->border_collisions = smd->domain->border_collisions; tsmd->domain->vorticity = smd->domain->vorticity; tsmd->domain->time_scale = smd->domain->time_scale; - tsmd->domain->border_collisions = smd->domain->border_collisions; - + + tsmd->domain->burning_rate = smd->domain->burning_rate; + tsmd->domain->flame_smoke = smd->domain->flame_smoke; + tsmd->domain->flame_vorticity = smd->domain->flame_vorticity; + tsmd->domain->flame_ignition = smd->domain->flame_ignition; + tsmd->domain->flame_max_temp = smd->domain->flame_max_temp; + copy_v3_v3(tsmd->domain->flame_smoke_color, smd->domain->flame_smoke_color); + MEM_freeN(tsmd->domain->effector_weights); tsmd->domain->effector_weights = MEM_dupallocN(smd->domain->effector_weights); - } + } else if (tsmd->flow) { - tsmd->flow->density = smd->flow->density; - tsmd->flow->temp = smd->flow->temp; tsmd->flow->psys = smd->flow->psys; - tsmd->flow->type = smd->flow->type; - tsmd->flow->flags = smd->flow->flags; + tsmd->flow->noise_texture = smd->flow->noise_texture; + tsmd->flow->vel_multi = smd->flow->vel_multi; + tsmd->flow->vel_normal = smd->flow->vel_normal; + tsmd->flow->vel_random = smd->flow->vel_random; + + tsmd->flow->density = smd->flow->density; + copy_v3_v3(tsmd->flow->color, smd->flow->color); + tsmd->flow->fuel_amount = smd->flow->fuel_amount; + tsmd->flow->temp = smd->flow->temp; + tsmd->flow->volume_density = smd->flow->volume_density; + tsmd->flow->surface_distance = smd->flow->surface_distance; + + tsmd->flow->texture_size = smd->flow->texture_size; + tsmd->flow->texture_offset = smd->flow->texture_offset; + BLI_strncpy(tsmd->flow->uvlayer_name, tsmd->flow->uvlayer_name, sizeof(tsmd->flow->uvlayer_name)); + tsmd->flow->vgroup_density = smd->flow->vgroup_density; + + tsmd->flow->type = smd->flow->type; + tsmd->flow->source = smd->flow->source; + tsmd->flow->texture_type = smd->flow->texture_type; + tsmd->flow->flags = smd->flow->flags; } else if (tsmd->coll) { - ; /* leave it as initialized, collision settings is mostly caches */ } } @@ -1011,24 +647,24 @@ void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData #ifdef WITH_SMOKE // forward decleration -static void smoke_calc_transparency(float *result, float *input, float *p0, float *p1, int res[3], float dx, float *light, bresenham_callback cb, float correct); +static void smoke_calc_transparency(SmokeDomainSettings *sds, Scene *scene); static float calc_voxel_transp(float *result, float *input, int res[3], int *pixel, float *tRay, float correct); static int get_lamp(Scene *scene, float *light) -{ - Base *base_tmp = NULL; +{ + Base *base_tmp = NULL; int found_lamp = 0; // try to find a lamp, preferably local - for(base_tmp = scene->base.first; base_tmp; base_tmp= base_tmp->next) { - if(base_tmp->object->type == OB_LAMP) { + for (base_tmp = scene->base.first; base_tmp; base_tmp = base_tmp->next) { + if (base_tmp->object->type == OB_LAMP) { Lamp *la = base_tmp->object->data; - if(la->type == LA_LOCAL) { + if (la->type == LA_LOCAL) { copy_v3_v3(light, base_tmp->object->obmat[3]); return 1; } - else if(!found_lamp) { + else if (!found_lamp) { copy_v3_v3(light, base_tmp->object->obmat[3]); found_lamp = 1; } @@ -1038,48 +674,131 @@ static int get_lamp(Scene *scene, float *light) return found_lamp; } -static void smoke_calc_domain(Scene *UNUSED(scene), Object *UNUSED(ob), SmokeModifierData *UNUSED(smd)) +static void obstacles_from_derivedmesh(Object *coll_ob, SmokeDomainSettings *sds, SmokeCollSettings *scs, unsigned char *obstacle_map, float *velocityX, float *velocityY, float *velocityZ, float dt) { -#if 0 - SmokeDomainSettings *sds = smd->domain; - GroupObject *go = NULL; - Base *base = NULL; - - /* do collisions, needs to be done before emission, so that smoke isn't emitted inside collision cells */ - if(1) + if (!scs->dm) return; { - unsigned int i; - Object **collobjs = NULL; - unsigned int numcollobj = 0; - collobjs = get_collisionobjects(scene, ob, sds->coll_group, &numcollobj); + DerivedMesh *dm = NULL; + MVert *mvert = NULL; + MFace *mface = NULL; + BVHTreeFromMesh treeData = {0}; + int numverts, i, z; + + float surface_distance = 0.6; + + float *vert_vel = NULL; + int has_velocity = 0; + + tstart(); + + dm = CDDM_copy(scs->dm); + CDDM_calc_normals(dm); + mvert = dm->getVertArray(dm); + mface = dm->getTessFaceArray(dm); + numverts = dm->getNumVerts(dm); + + // DG TODO + // if (scs->type > SM_COLL_STATIC) + // if line above is used, the code is in trouble if the object moves but is declared as "does not move" - for(i = 0; i < numcollobj; i++) { - Object *collob= collobjs[i]; - SmokeModifierData *smd2 = (SmokeModifierData*)modifiers_findByType(collob, eModifierType_Smoke); - - // check for active smoke modifier - // if(md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) - // SmokeModifierData *smd2 = (SmokeModifierData *)md; + vert_vel = MEM_callocN(sizeof(float) * numverts * 3, "smoke_obs_velocity"); - if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll && smd2->coll->points && smd2->coll->points_old) - { - // ??? anything to do here? - - // TODO: only something to do for ANIMATED obstacles: need to update positions + if (scs->numverts != numverts || !scs->verts_old) { + if (scs->verts_old) MEM_freeN(scs->verts_old); + scs->verts_old = MEM_callocN(sizeof(float) * numverts * 3, "smoke_obs_verts_old"); + scs->numverts = numverts; + } + else { + has_velocity = 1; } } - if(collobjs) - MEM_freeN(collobjs); - } + /* Transform collider vertices to + * domain grid space for fast lookups */ + for (i = 0; i < numverts; i++) { + float n[3]; + float co[3]; -#endif + /* vert pos */ + mul_m4_v3(coll_ob->obmat, mvert[i].co); + smoke_pos_to_cell(sds, mvert[i].co); + + /* vert normal */ + normal_short_to_float_v3(n, mvert[i].no); + mul_mat3_m4_v3(coll_ob->obmat, n); + mul_mat3_m4_v3(sds->imat, n); + normalize_v3(n); + normal_float_to_short_v3(mvert[i].no, n); + + /* vert velocity */ + VECADD(co, mvert[i].co, sds->shift); + if (has_velocity) + { + sub_v3_v3v3(&vert_vel[i * 3], co, &scs->verts_old[i * 3]); + mul_v3_fl(&vert_vel[i * 3], sds->dx / dt); + } + copy_v3_v3(&scs->verts_old[i * 3], co); + } + + if (bvhtree_from_mesh_faces(&treeData, dm, 0.0f, 4, 6)) { + #pragma omp parallel for schedule(static) + for (z = sds->res_min[2]; z < sds->res_max[2]; z++) { + int x, y; + for (x = sds->res_min[0]; x < sds->res_max[0]; x++) + for (y = sds->res_min[1]; y < sds->res_max[1]; y++) { + int index = smoke_get_index(x - sds->res_min[0], sds->res[0], y - sds->res_min[1], sds->res[1], z - sds->res_min[2]); + + float ray_start[3] = {(float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f}; + BVHTreeNearest nearest = {0}; + nearest.index = -1; + nearest.dist = surface_distance * surface_distance; /* find_nearest uses squared distance */ + + /* find the nearest point on the mesh */ + if (BLI_bvhtree_find_nearest(treeData.tree, ray_start, &nearest, treeData.nearest_callback, &treeData) != -1) { + float weights[4]; + int v1, v2, v3, f_index = nearest.index; + + /* calculate barycentric weights for nearest point */ + v1 = mface[f_index].v1; + v2 = (nearest.flags & BVH_ONQUAD) ? mface[f_index].v3 : mface[f_index].v2; + v3 = (nearest.flags & BVH_ONQUAD) ? mface[f_index].v4 : mface[f_index].v3; + interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, nearest.co); + + // DG TODO + if (has_velocity) + { + /* apply object velocity */ + { + float hit_vel[3]; + interp_v3_v3v3v3(hit_vel, &vert_vel[v1 * 3], &vert_vel[v2 * 3], &vert_vel[v3 * 3], weights); + velocityX[index] += hit_vel[0]; + velocityY[index] += hit_vel[1]; + velocityZ[index] += hit_vel[2]; + } + } + + /* tag obstacle cells */ + obstacle_map[index] = 1; + + if (has_velocity) + obstacle_map[index] |= 8; + } + } + } + } + /* free bvh tree */ + free_bvhtree_from_mesh(&treeData); + dm->release(dm); + + if (vert_vel) MEM_freeN(vert_vel); + } } /* Animated obstacles: dx_step = ((x_new - x_old) / totalsteps) * substep */ -static void update_obstacles(Scene *scene, Object *ob, SmokeDomainSettings *sds, float dt, int substep, int totalsteps) +static void update_obstacles(Scene *scene, Object *ob, SmokeDomainSettings *sds, float dt, + int UNUSED(substep), int UNUSED(totalsteps)) { Object **collobjs = NULL; unsigned int numcollobj = 0; @@ -1092,24 +811,20 @@ static void update_obstacles(Scene *scene, Object *ob, SmokeDomainSettings *sds, float *velxOrig = smoke_get_velocity_x(sds->fluid); float *velyOrig = smoke_get_velocity_y(sds->fluid); float *velzOrig = smoke_get_velocity_z(sds->fluid); - // float *density = smoke_get_density(sds->fluid); + float *density = smoke_get_density(sds->fluid); + float *fuel = smoke_get_fuel(sds->fluid); + float *flame = smoke_get_flame(sds->fluid); + float *r = smoke_get_color_r(sds->fluid); + float *g = smoke_get_color_g(sds->fluid); + float *b = smoke_get_color_b(sds->fluid); unsigned int z; smoke_get_ob_velocity(sds->fluid, &velx, &vely, &velz); // TODO: delete old obstacle flags - for(z = 0; z < sds->res[0] * sds->res[1] * sds->res[2]; z++) + for (z = 0; z < sds->res[0] * sds->res[1] * sds->res[2]; z++) { - if(obstacles[z]) - { - // density[z] = 0; - - velxOrig[z] = 0; - velyOrig[z] = 0; - velzOrig[z] = 0; - } - - if(obstacles[z] & 8) // Do not delete static obstacles + if (obstacles[z] & 8) // Do not delete static obstacles { obstacles[z] = 0; } @@ -1119,410 +834,1064 @@ static void update_obstacles(Scene *scene, Object *ob, SmokeDomainSettings *sds, velz[z] = 0; } + collobjs = get_collisionobjects(scene, ob, sds->coll_group, &numcollobj, eModifierType_Smoke); // update obstacle tags in cells - for(collIndex = 0; collIndex < numcollobj; collIndex++) + for (collIndex = 0; collIndex < numcollobj; collIndex++) { - Object *collob= collobjs[collIndex]; - SmokeModifierData *smd2 = (SmokeModifierData*)modifiers_findByType(collob, eModifierType_Smoke); + Object *collob = collobjs[collIndex]; + SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(collob, eModifierType_Smoke); // DG TODO: check if modifier is active? - - if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll && smd2->coll->points && smd2->coll->points_old) + + if ((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll) { SmokeCollSettings *scs = smd2->coll; - unsigned int i; - - /* - // DG TODO: support static cobstacles, but basicly we could even support static + rigid with one set of code - if(scs->type > SM_COLL_STATIC) - */ - - /* Handle collisions */ - for(i = 0; i < scs->numpoints; i++) - { - // 1. get corresponding cell - int cell[3]; - float pos[3], oldpos[3], vel[3]; - float cPos[3], cOldpos[3]; /* current position in substeps */ - int badcell = 0; - size_t index; - int j; - - // translate local points into global positions - copy_v3_v3(cPos, &scs->points[3 * i]); - mul_m4_v3(scs->mat, cPos); - copy_v3_v3(pos, cPos); - - copy_v3_v3(cOldpos, &scs->points_old[3 * i]); - mul_m4_v3(scs->mat_old, cOldpos); - copy_v3_v3(oldpos, cOldpos); - - /* support for rigid bodies, armatures etc */ - { - float tmp[3]; - - /* x_current = x_old + (x_new - x_old) * step_current / steps_total */ - float mulStep = (float)(((float)substep) / ((float)totalsteps)); - - sub_v3_v3v3(tmp, cPos, cOldpos); - mul_v3_fl(tmp, mulStep); - add_v3_v3(cOldpos, tmp); - } - - sub_v3_v3v3(vel, pos, oldpos); - /* Scale velocity to incorperate the object movement during this step */ - mul_v3_fl(vel, 1.0 / (totalsteps * dt * sds->scale)); - // mul_v3_fl(vel, 1.0 / dt); - - // DG TODO: cap velocity to maxVelMag (or maxvel) - - // oldpos + velocity * dt = newpos - get_cell(sds->p0, sds->res, sds->dx*sds->scale, cOldpos /* use current position here instead of "pos" */, cell, 0); - - // check if cell is valid (in the domain boundary) - for(j = 0; j < 3; j++) - if((cell[j] > sds->res[j] - 1) || (cell[j] < 0)) - { - badcell = 1; - break; - } - - if(badcell) - continue; - - // 2. set cell values (heat, density and velocity) - index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]); - - // Don't overwrite existing obstacles - if(obstacles[index]) - continue; - - // printf("cell[0]: %d, cell[1]: %d, cell[2]: %d\n", cell[0], cell[1], cell[2]); - // printf("res[0]: %d, res[1]: %d, res[2]: %d, index: %d\n\n", sds->res[0], sds->res[1], sds->res[2], index); - obstacles[index] = 1 | 8 /* ANIMATED */; - - if(len_v3(vel) > FLT_EPSILON) - { - // Collision object is moving - - velx[index] = vel[0]; // use "+="? - vely[index] = vel[1]; - velz[index] = vel[2]; - } - } + obstacles_from_derivedmesh(collob, sds, scs, obstacles, velx, vely, velz, dt); } } - if(collobjs) + if (collobjs) MEM_freeN(collobjs); + + /* obstacle cells should not contain any velocity from the smoke simulation */ + for (z = 0; z < sds->res[0] * sds->res[1] * sds->res[2]; z++) + { + if (obstacles[z]) + { + velxOrig[z] = 0; + velyOrig[z] = 0; + velzOrig[z] = 0; + density[z] = 0; + if (fuel) { + fuel[z] = 0; + flame[z] = 0; + } + if (r) { + r[z] = 0; + g[z] = 0; + b[z] = 0; + } + } + } } -static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sds, float time) + +typedef struct EmissionMap { + float *influence; + float *velocity; + int min[3], max[3], res[3]; + int total_cells, valid; +} EmissionMap; + +static void em_boundInsert(EmissionMap *em, float point[3]) +{ + int i = 0; + if (!em->valid) { + VECCOPY(em->min, point); + VECCOPY(em->max, point); + em->valid = 1; + } + else { + for (; i < 3; i++) { + if (point[i] < em->min[i]) em->min[i] = (int)floor(point[i]); + if (point[i] > em->max[i]) em->max[i] = (int)ceil(point[i]); + } + } +} + +static void clampBoundsInDomain(SmokeDomainSettings *sds, int min[3], int max[3], float *min_vel, float *max_vel, int margin, float dt) +{ + int i; + for (i = 0; i < 3; i++) { + int adapt = (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) ? sds->adapt_res : 0; + /* add margin */ + min[i] -= margin; + max[i] += margin; + + /* adapt to velocity */ + if (min_vel && min_vel[i] < 0.0f) { + min[i] += (int)ceil(min_vel[i] * dt); + } + if (max_vel && max_vel[i] > 0.0f) { + max[i] += (int)ceil(max_vel[i] * dt); + } + + /* clamp within domain max size */ + CLAMP(min[i], -adapt, sds->base_res[i] + adapt); + CLAMP(max[i], -adapt, sds->base_res[i] + adapt); + } +} + +static void em_allocateData(EmissionMap *em, int use_velocity) { + int i, res[3]; + + for (i = 0; i < 3; i++) { + res[i] = em->max[i] - em->min[i]; + if (res[i] <= 0) + return; + } + em->total_cells = res[0] * res[1] * res[2]; + copy_v3_v3_int(em->res, res); + + + em->influence = MEM_callocN(sizeof(float) * em->total_cells, "smoke_flow_influence"); + if (use_velocity) + em->velocity = MEM_callocN(sizeof(float) * em->total_cells * 3, "smoke_flow_velocity"); +} + +static void em_freeData(EmissionMap *em) { + if (em->influence) + MEM_freeN(em->influence); + if (em->velocity) + MEM_freeN(em->velocity); +} + + +static void emit_from_particles(Object *flow_ob, SmokeDomainSettings *sds, SmokeFlowSettings *sfs, EmissionMap *em, Scene *scene, float time, float dt) +{ + if (sfs && sfs->psys && sfs->psys->part && ELEM(sfs->psys->part->type, PART_EMITTER, PART_FLUID)) // is particle system selected + { + ParticleSimulationData sim; + ParticleSystem *psys = sfs->psys; + float *particle_pos; + float *particle_vel; + int totpart = psys->totpart, totchild; + int p = 0; + int valid_particles = 0; + + sim.scene = scene; + sim.ob = flow_ob; + sim.psys = psys; + + if (psys->part->type == PART_HAIR) + { + // TODO: PART_HAIR not supported whatsoever + totchild = 0; + } + else + totchild = psys->totchild * psys->part->disp / 100; + + particle_pos = MEM_callocN(sizeof(float) * (totpart + totchild) * 3, "smoke_flow_particles"); + particle_vel = MEM_callocN(sizeof(float) * (totpart + totchild) * 3, "smoke_flow_particles"); + + /* calculate local position for each particle */ + for (p = 0; p < totpart + totchild; p++) + { + ParticleKey state; + float *pos; + if (p < totpart) { + if (psys->particles[p].flag & (PARS_NO_DISP | PARS_UNEXIST)) + continue; + } + else { + /* handle child particle */ + ChildParticle *cpa = &psys->child[p - totpart]; + if (psys->particles[cpa->parent].flag & (PARS_NO_DISP | PARS_UNEXIST)) + continue; + } + + state.time = time; + if (psys_get_particle_state(&sim, p, &state, 0) == 0) + continue; + + /* location */ + pos = &particle_pos[valid_particles * 3]; + copy_v3_v3(pos, state.co); + smoke_pos_to_cell(sds, pos); + + /* velocity */ + copy_v3_v3(&particle_vel[valid_particles * 3], state.vel); + mul_mat3_m4_v3(sds->imat, &particle_vel[valid_particles * 3]); + + /* calculate emission map bounds */ + em_boundInsert(em, pos); + valid_particles++; + } + + /* set emission map */ + clampBoundsInDomain(sds, em->min, em->max, NULL, NULL, 1, dt); + em_allocateData(em, sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY); + + for (p = 0; p < valid_particles; p++) + { + int cell[3]; + size_t i = 0; + size_t index = 0; + int badcell = 0; + + /* 1. get corresponding cell */ + cell[0] = floor(particle_pos[p * 3]) - em->min[0]; + cell[1] = floor(particle_pos[p * 3 + 1]) - em->min[1]; + cell[2] = floor(particle_pos[p * 3 + 2]) - em->min[2]; + /* check if cell is valid (in the domain boundary) */ + for (i = 0; i < 3; i++) { + if ((cell[i] > em->res[i] - 1) || (cell[i] < 0)) { + badcell = 1; + break; + } + } + if (badcell) + continue; + /* get cell index */ + index = smoke_get_index(cell[0], em->res[0], cell[1], em->res[1], cell[2]); + /* Add influence to emission map */ + em->influence[index] = 1.0f; + /* Uses particle velocity as initial velocity for smoke */ + if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && (psys->part->phystype != PART_PHYS_NO)) + { + VECADDFAC(&em->velocity[index * 3], &em->velocity[index * 3], &particle_vel[p * 3], sfs->vel_multi); + } + } // particles loop + + /* free data */ + if (particle_pos) + MEM_freeN(particle_pos); + if (particle_vel) + MEM_freeN(particle_vel); + } +} + +static void get_texture_value(Tex *texture, float tex_co[3], TexResult *texres) +{ + int result_type; + + /* no node textures for now */ + result_type = multitex_ext_safe(texture, tex_co, texres); + + /* if the texture gave an RGB value, we assume it didn't give a valid + * intensity, since this is in the context of modifiers don't use perceptual color conversion. + * if the texture didn't give an RGB value, copy the intensity across + */ + if (result_type & TEX_RGB) { + texres->tin = (1.0f / 3.0f) * (texres->tr + texres->tg + texres->tb); + } + else { + copy_v3_fl(&texres->tr, texres->tin); + } +} + +static void emit_from_derivedmesh(Object *flow_ob, SmokeDomainSettings *sds, SmokeFlowSettings *sfs, EmissionMap *em, float dt) +{ + if (!sfs->dm) return; + { + DerivedMesh *dm = sfs->dm; + int defgrp_index = sfs->vgroup_density - 1; + MDeformVert *dvert = NULL; + MVert *mvert = NULL; + MVert *mvert_orig = NULL; + MFace *mface = NULL; + MTFace *tface = NULL; + BVHTreeFromMesh treeData = {0}; + int numOfVerts, i, z; + float flow_center[3] = {0}; + + float *vert_vel = NULL; + int has_velocity = 0; + + CDDM_calc_normals(dm); + mvert = dm->getVertArray(dm); + mvert_orig = dm->dupVertArray(dm); /* copy original mvert and restore when done */ + mface = dm->getTessFaceArray(dm); + numOfVerts = dm->getNumVerts(dm); + dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); + tface = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, sfs->uvlayer_name); + + if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY) { + vert_vel = MEM_callocN(sizeof(float) * numOfVerts * 3, "smoke_flow_velocity"); + + if (sfs->numverts != numOfVerts || !sfs->verts_old) { + if (sfs->verts_old) MEM_freeN(sfs->verts_old); + sfs->verts_old = MEM_callocN(sizeof(float) * numOfVerts * 3, "smoke_flow_verts_old"); + sfs->numverts = numOfVerts; + } + else { + has_velocity = 1; + } + } + + /* Transform dm vertices to + * domain grid space for fast lookups */ + for (i = 0; i < numOfVerts; i++) { + float n[3]; + /* vert pos */ + mul_m4_v3(flow_ob->obmat, mvert[i].co); + smoke_pos_to_cell(sds, mvert[i].co); + /* vert normal */ + normal_short_to_float_v3(n, mvert[i].no); + mul_mat3_m4_v3(flow_ob->obmat, n); + mul_mat3_m4_v3(sds->imat, n); + normalize_v3(n); + normal_float_to_short_v3(mvert[i].no, n); + /* vert velocity */ + if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY) { + float co[3]; + VECADD(co, mvert[i].co, sds->shift); + if (has_velocity) { + sub_v3_v3v3(&vert_vel[i * 3], co, &sfs->verts_old[i * 3]); + mul_v3_fl(&vert_vel[i * 3], sds->dx / dt); + } + copy_v3_v3(&sfs->verts_old[i * 3], co); + } + + /* calculate emission map bounds */ + em_boundInsert(em, mvert[i].co); + } + mul_m4_v3(flow_ob->obmat, flow_center); + smoke_pos_to_cell(sds, flow_center); + + /* set emission map */ + clampBoundsInDomain(sds, em->min, em->max, NULL, NULL, sfs->surface_distance, dt); + em_allocateData(em, sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY); + + if (bvhtree_from_mesh_faces(&treeData, dm, 0.0f, 4, 6)) { + #pragma omp parallel for schedule(static) + for (z = em->min[2]; z < em->max[2]; z++) { + int x, y; + for (x = em->min[0]; x < em->max[0]; x++) + for (y = em->min[1]; y < em->max[1]; y++) { + int index = smoke_get_index(x - em->min[0], em->res[0], y - em->min[1], em->res[1], z - em->min[2]); + + float ray_start[3] = {(float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f}; + float ray_dir[3] = {1.0f, 0.0f, 0.0f}; + + BVHTreeRayHit hit = {0}; + BVHTreeNearest nearest = {0}; + + float volume_factor = 0.0f; + float sample_str = 0.0f; + + hit.index = -1; + hit.dist = 9999; + nearest.index = -1; + nearest.dist = sfs->surface_distance * sfs->surface_distance; /* find_nearest uses squared distance */ + + /* Check volume collision */ + if (sfs->volume_density) { + if (BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_dir, 0.0f, &hit, treeData.raycast_callback, &treeData) != -1) { + float dot = ray_dir[0] * hit.no[0] + ray_dir[1] * hit.no[1] + ray_dir[2] * hit.no[2]; + /* If ray and hit face normal are facing same direction + * hit point is inside a closed mesh. */ + if (dot >= 0) { + /* Also cast a ray in opposite direction to make sure + * point is at least surrounded by two faces */ + negate_v3(ray_dir); + hit.index = -1; + hit.dist = 9999; + + BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_dir, 0.0f, &hit, treeData.raycast_callback, &treeData); + if (hit.index != -1) { + volume_factor = sfs->volume_density; + nearest.dist = hit.dist * hit.dist; + } + } + } + } + + /* find the nearest point on the mesh */ + if (BLI_bvhtree_find_nearest(treeData.tree, ray_start, &nearest, treeData.nearest_callback, &treeData) != -1) { + float weights[4]; + int v1, v2, v3, f_index = nearest.index; + float n1[3], n2[3], n3[3], hit_normal[3]; + + /* emit from surface based on distance */ + if (sfs->surface_distance) { + sample_str = sqrtf(nearest.dist) / sfs->surface_distance; + CLAMP(sample_str, 0.0f, 1.0f); + sample_str = pow(1.0f - sample_str, 0.5f); + } + else + sample_str = 0.0f; + + /* calculate barycentric weights for nearest point */ + v1 = mface[f_index].v1; + v2 = (nearest.flags & BVH_ONQUAD) ? mface[f_index].v3 : mface[f_index].v2; + v3 = (nearest.flags & BVH_ONQUAD) ? mface[f_index].v4 : mface[f_index].v3; + interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, nearest.co); + + if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY) { + /* apply normal directional velocity */ + if (sfs->vel_normal) { + /* interpolate vertex normal vectors to get nearest point normal */ + normal_short_to_float_v3(n1, mvert[v1].no); + normal_short_to_float_v3(n2, mvert[v2].no); + normal_short_to_float_v3(n3, mvert[v3].no); + interp_v3_v3v3v3(hit_normal, n1, n2, n3, weights); + normalize_v3(hit_normal); + /* apply normal directional and random velocity + * - TODO: random disabled for now since it doesnt really work well as pressure calc smoothens it out... */ + em->velocity[index * 3] += hit_normal[0] * sfs->vel_normal * 0.25f; + em->velocity[index * 3 + 1] += hit_normal[1] * sfs->vel_normal * 0.25f; + em->velocity[index * 3 + 2] += hit_normal[2] * sfs->vel_normal * 0.25f; + /* TODO: for fire emitted from mesh surface we can use + * Vf = Vs + (Ps/Pf - 1)*S to model gaseous expansion from solid to fuel */ + } + /* apply object velocity */ + if (has_velocity && sfs->vel_multi) { + float hit_vel[3]; + interp_v3_v3v3v3(hit_vel, &vert_vel[v1 * 3], &vert_vel[v2 * 3], &vert_vel[v3 * 3], weights); + em->velocity[index * 3] += hit_vel[0] * sfs->vel_multi; + em->velocity[index * 3 + 1] += hit_vel[1] * sfs->vel_multi; + em->velocity[index * 3 + 2] += hit_vel[2] * sfs->vel_multi; + } + } + + /* apply vertex group influence if used */ + if (defgrp_index != -1 && dvert) { + float weight_mask = defvert_find_weight(&dvert[v1], defgrp_index) * weights[0] + + defvert_find_weight(&dvert[v2], defgrp_index) * weights[1] + + defvert_find_weight(&dvert[v3], defgrp_index) * weights[2]; + sample_str *= weight_mask; + } + + /* apply emission texture */ + if ((sfs->flags & MOD_SMOKE_FLOW_TEXTUREEMIT) && sfs->noise_texture) { + float tex_co[3] = {0}; + TexResult texres; + + if (sfs->texture_type == MOD_SMOKE_FLOW_TEXTURE_MAP_AUTO) { + tex_co[0] = ((float)(x - flow_center[0]) / sds->base_res[0]) / sfs->texture_size; + tex_co[1] = ((float)(y - flow_center[1]) / sds->base_res[1]) / sfs->texture_size; + tex_co[2] = ((float)(z - flow_center[2]) / sds->base_res[2] - sfs->texture_offset) / sfs->texture_size; + } + else if (tface) { + interp_v2_v2v2v2(tex_co, tface[f_index].uv[0], tface[f_index].uv[(nearest.flags & BVH_ONQUAD) ? 2 : 1], + tface[f_index].uv[(nearest.flags & BVH_ONQUAD) ? 3 : 2], weights); + /* map between -1.0f and 1.0f */ + tex_co[0] = tex_co[0] * 2.0f - 1.0f; + tex_co[1] = tex_co[1] * 2.0f - 1.0f; + tex_co[2] = sfs->texture_offset; + } + texres.nor = NULL; + get_texture_value(sfs->noise_texture, tex_co, &texres); + sample_str *= texres.tin; + } + } + + /* multiply initial velocity by emitter influence */ + if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY) { + mul_v3_fl(&em->velocity[index * 3], sample_str); + } + + /* apply final influence based on volume factor */ + em->influence[index] = MAX2(volume_factor, sample_str); + } + } + } + /* free bvh tree */ + free_bvhtree_from_mesh(&treeData); + /* restore original mverts */ + CustomData_set_layer(&dm->vertData, CD_MVERT, mvert_orig); + if (mvert) + MEM_freeN(mvert); + + if (vert_vel) MEM_freeN(vert_vel); + } +} + +static void adjustDomainResolution(SmokeDomainSettings *sds, int new_shift[3], EmissionMap *emaps, unsigned int numflowobj, float dt) +{ + int min[3] = {32767, 32767, 32767}, max[3] = {-32767, -32767, -32767}, res[3]; + int total_cells = 1, res_changed = 0, shift_changed = 0; + float min_vel[3], max_vel[3]; + int x, y, z, i; + float *density = smoke_get_density(sds->fluid); + float *fuel = smoke_get_fuel(sds->fluid); + float *vx = smoke_get_velocity_x(sds->fluid); + float *vy = smoke_get_velocity_y(sds->fluid); + float *vz = smoke_get_velocity_z(sds->fluid); + + INIT_MINMAX(min_vel, max_vel); + + /* Calculate bounds for current domain content */ + for (x = sds->res_min[0]; x < sds->res_max[0]; x++) + for (y = sds->res_min[1]; y < sds->res_max[1]; y++) + for (z = sds->res_min[2]; z < sds->res_max[2]; z++) + { + int xn = x - new_shift[0]; + int yn = y - new_shift[1]; + int zn = z - new_shift[2]; + int index = smoke_get_index(x - sds->res_min[0], sds->res[0], y - sds->res_min[1], sds->res[1], z - sds->res_min[2]); + float max_den = (fuel) ? MAX2(density[index], fuel[index]) : density[index]; + + /* content bounds (use shifted coordinates) */ + if (max_den >= sds->adapt_threshold) { + if (min[0] > xn) min[0] = xn; + if (min[1] > yn) min[1] = yn; + if (min[2] > zn) min[2] = zn; + if (max[0] < xn) max[0] = xn; + if (max[1] < yn) max[1] = yn; + if (max[2] < zn) max[2] = zn; + } + /* velocity bounds */ + if (min_vel[0] > vx[index]) min_vel[0] = vx[index]; + if (min_vel[1] > vy[index]) min_vel[1] = vy[index]; + if (min_vel[2] > vz[index]) min_vel[2] = vz[index]; + if (max_vel[0] < vx[index]) max_vel[0] = vx[index]; + if (max_vel[1] < vy[index]) max_vel[1] = vy[index]; + if (max_vel[2] < vz[index]) max_vel[2] = vz[index]; + } + + /* also apply emission maps */ + for (i = 0; i < numflowobj; i++) + { + EmissionMap *em = &emaps[i]; + + for (x = em->min[0]; x < em->max[0]; x++) + for (y = em->min[1]; y < em->max[1]; y++) + for (z = em->min[2]; z < em->max[2]; z++) + { + int index = smoke_get_index(x - em->min[0], em->res[0], y - em->min[1], em->res[1], z - em->min[2]); + float max_den = em->influence[index]; + + /* density bounds */ + if (max_den >= sds->adapt_threshold) { + if (min[0] > x) min[0] = x; + if (min[1] > y) min[1] = y; + if (min[2] > z) min[2] = z; + if (max[0] < x) max[0] = x; + if (max[1] < y) max[1] = y; + if (max[2] < z) max[2] = z; + } + /* velocity bounds */ + if (em->velocity) { + if (min_vel[0] > em->velocity[index * 3]) min_vel[0] = em->velocity[index * 3]; + if (min_vel[1] > em->velocity[index * 3 + 1]) min_vel[1] = em->velocity[index * 3 + 1]; + if (min_vel[2] > em->velocity[index * 3 + 2]) min_vel[2] = em->velocity[index * 3 + 2]; + if (max_vel[0] < em->velocity[index * 3]) max_vel[0] = em->velocity[index * 3]; + if (max_vel[1] < em->velocity[index * 3 + 1]) max_vel[1] = em->velocity[index * 3 + 1]; + if (max_vel[2] < em->velocity[index * 3 + 2]) max_vel[2] = em->velocity[index * 3 + 2]; + } + } + } + + /* calculate new bounds based on these values */ + clampBoundsInDomain(sds, min, max, min_vel, max_vel, sds->adapt_margin + 1, dt); + + for (i = 0; i < 3; i++) { + /* calculate new resolution */ + res[i] = max[i] - min[i]; + total_cells *= res[i]; + + if (new_shift[i]) + shift_changed = 1; + + /* if no content set minimum dimensions */ + if (res[i] <= 0) { + int j; + for (j = 0; j < 3; j++) { + min[j] = 0; + max[j] = 1; + res[j] = 1; + } + res_changed = 1; + total_cells = 1; + break; + } + if (min[i] != sds->res_min[i] || max[i] != sds->res_max[i]) + res_changed = 1; + } + + if (res_changed || shift_changed) { + struct FLUID_3D *fluid_old = sds->fluid; + struct WTURBULENCE *turb_old = sds->wt; + /* allocate new fluid data */ + smoke_reallocate_fluid(sds, sds->dx, res, 0); + if (sds->flags & MOD_SMOKE_HIGHRES) { + smoke_reallocate_highres_fluid(sds, sds->dx, res, 0); + } + + /* copy values from old fluid to new */ + if (sds->total_cells > 1 && total_cells > 1) { + /* low res smoke */ + float *o_dens, *o_react, *o_flame, *o_fuel, *o_heat, *o_heatold, *o_vx, *o_vy, *o_vz, *o_r, *o_g, *o_b; + float *n_dens, *n_react, *n_flame, *n_fuel, *n_heat, *n_heatold, *n_vx, *n_vy, *n_vz, *n_r, *n_g, *n_b; + float dummy; + unsigned char *dummy_p; + /* high res smoke */ + int wt_res_old[3]; + float *o_wt_dens, *o_wt_react, *o_wt_flame, *o_wt_fuel, *o_wt_tcu, *o_wt_tcv, *o_wt_tcw, *o_wt_r, *o_wt_g, *o_wt_b; + float *n_wt_dens, *n_wt_react, *n_wt_flame, *n_wt_fuel, *n_wt_tcu, *n_wt_tcv, *n_wt_tcw, *n_wt_r, *n_wt_g, *n_wt_b; + + smoke_export(fluid_old, &dummy, &dummy, &o_dens, &o_react, &o_flame, &o_fuel, &o_heat, &o_heatold, &o_vx, &o_vy, &o_vz, &o_r, &o_g, &o_b, &dummy_p); + smoke_export(sds->fluid, &dummy, &dummy, &n_dens, &n_react, &n_flame, &n_fuel, &n_heat, &n_heatold, &n_vx, &n_vy, &n_vz, &n_r, &n_g, &n_b, &dummy_p); + + if (sds->flags & MOD_SMOKE_HIGHRES) { + smoke_turbulence_export(turb_old, &o_wt_dens, &o_wt_react, &o_wt_flame, &o_wt_fuel, &o_wt_r, &o_wt_g, &o_wt_b, &o_wt_tcu, &o_wt_tcv, &o_wt_tcw); + smoke_turbulence_get_res(turb_old, wt_res_old); + smoke_turbulence_export(sds->wt, &n_wt_dens, &n_wt_react, &n_wt_flame, &n_wt_fuel, &n_wt_r, &n_wt_g, &n_wt_b, &n_wt_tcu, &n_wt_tcv, &n_wt_tcw); + } + + + for (x = sds->res_min[0]; x < sds->res_max[0]; x++) + for (y = sds->res_min[1]; y < sds->res_max[1]; y++) + for (z = sds->res_min[2]; z < sds->res_max[2]; z++) + { + /* old grid index */ + int xo = x - sds->res_min[0]; + int yo = y - sds->res_min[1]; + int zo = z - sds->res_min[2]; + int index_old = smoke_get_index(xo, sds->res[0], yo, sds->res[1], zo); + /* new grid index */ + int xn = x - min[0] - new_shift[0]; + int yn = y - min[1] - new_shift[1]; + int zn = z - min[2] - new_shift[2]; + int index_new = smoke_get_index(xn, res[0], yn, res[1], zn); + + /* skip if outside new domain */ + if (xn < 0 || xn >= res[0] || + yn < 0 || yn >= res[1] || + zn < 0 || zn >= res[2]) + continue; + + /* copy data */ + n_dens[index_new] = o_dens[index_old]; + /* heat */ + if (n_heat && o_heat) { + n_heat[index_new] = o_heat[index_old]; + n_heatold[index_new] = o_heatold[index_old]; + } + /* fuel */ + if (n_fuel && o_fuel) { + n_flame[index_new] = o_flame[index_old]; + n_fuel[index_new] = o_fuel[index_old]; + n_react[index_new] = o_react[index_old]; + } + /* color */ + if (o_r && n_r) { + n_r[index_new] = o_r[index_old]; + n_g[index_new] = o_g[index_old]; + n_b[index_new] = o_b[index_old]; + } + n_vx[index_new] = o_vx[index_old]; + n_vy[index_new] = o_vy[index_old]; + n_vz[index_new] = o_vz[index_old]; + + if (sds->flags & MOD_SMOKE_HIGHRES && turb_old) { + int block_size = sds->amplify + 1; + int i, j, k; + /* old grid index */ + int xx_o = xo * block_size; + int yy_o = yo * block_size; + int zz_o = zo * block_size; + /* new grid index */ + int xx_n = xn * block_size; + int yy_n = yn * block_size; + int zz_n = zn * block_size; + + n_wt_tcu[index_new] = o_wt_tcu[index_old]; + n_wt_tcv[index_new] = o_wt_tcv[index_old]; + n_wt_tcw[index_new] = o_wt_tcw[index_old]; + + for (i = 0; i < block_size; i++) + for (j = 0; j < block_size; j++) + for (k = 0; k < block_size; k++) + { + int big_index_old = smoke_get_index(xx_o + i, wt_res_old[0], yy_o + j, wt_res_old[1], zz_o + k); + int big_index_new = smoke_get_index(xx_n + i, sds->res_wt[0], yy_n + j, sds->res_wt[1], zz_n + k); + /* copy data */ + n_wt_dens[big_index_new] = o_wt_dens[big_index_old]; + if (n_wt_flame && o_wt_flame) { + n_wt_flame[big_index_new] = o_wt_flame[big_index_old]; + n_wt_fuel[big_index_new] = o_wt_fuel[big_index_old]; + n_wt_react[big_index_new] = o_wt_react[big_index_old]; + } + if (n_wt_r && o_wt_r) { + n_wt_r[big_index_new] = o_wt_r[big_index_old]; + n_wt_g[big_index_new] = o_wt_g[big_index_old]; + n_wt_b[big_index_new] = o_wt_b[big_index_old]; + } + } + } + } + } + smoke_free(fluid_old); + if (turb_old) + smoke_turbulence_free(turb_old); + + /* set new domain dimensions */ + VECCOPY(sds->res_min, min); + VECCOPY(sds->res_max, max); + VECCOPY(sds->res, res); + sds->total_cells = total_cells; + } +} + +BLI_INLINE void apply_outflow_fields(int index, float *density, float *heat, float *fuel, float *react, float *color_r, float *color_g, float *color_b) +{ + density[index] = 0.f; + if (heat) { + heat[index] = 0.f; + } + if (fuel) { + fuel[index] = 0.f; + react[index] = 0.f; + } + if (color_r) { + color_r[index] = 0.f; + color_g[index] = 0.f; + color_b[index] = 0.f; + } +} + +BLI_INLINE void apply_inflow_fields(SmokeFlowSettings *sfs, float emission_value, int index, float *density, float *heat, float *fuel, float *react, float *color_r, float *color_g, float *color_b) +{ + int absolute_flow = (sfs->flags & MOD_SMOKE_FLOW_ABSOLUTE); + float dens_old = density[index]; + // float fuel_old = (fuel) ? fuel[index] : 0.0f; /* UNUSED */ + float dens_flow = (sfs->type == MOD_SMOKE_FLOW_TYPE_FIRE) ? 0.0f : emission_value * sfs->density; + float fuel_flow = emission_value * sfs->fuel_amount; + /* add heat */ + if (heat) { + heat[index] = MAX2(emission_value * sfs->temp, heat[index]); + } + /* absolute */ + if (absolute_flow) { + if (sfs->type != MOD_SMOKE_FLOW_TYPE_FIRE) { + if (dens_flow > density[index]) + density[index] = dens_flow; + } + if (sfs->type != MOD_SMOKE_FLOW_TYPE_SMOKE && fuel && fuel_flow) { + if (fuel_flow > fuel[index]) + fuel[index] = fuel_flow; + } + } + /* additive */ + else { + if (sfs->type != MOD_SMOKE_FLOW_TYPE_FIRE) { + density[index] += dens_flow; + CLAMP(density[index], 0.0f, 1.0f); + } + if (sfs->type != MOD_SMOKE_FLOW_TYPE_SMOKE && fuel && sfs->fuel_amount) { + fuel[index] += fuel_flow; + CLAMP(fuel[index], 0.0f, 10.0f); + } + } + + /* set color */ + if (color_r && dens_flow) { + float total_dens = density[index] / (dens_old + dens_flow); + color_r[index] = (color_r[index] + sfs->color[0] * dens_flow) * total_dens; + color_g[index] = (color_g[index] + sfs->color[1] * dens_flow) * total_dens; + color_b[index] = (color_b[index] + sfs->color[2] * dens_flow) * total_dens; + } + + /* set fire reaction coordinate */ + if (fuel && fuel[index]) { + /* instead of using 1.0 for all new fuel add slight falloff + * to reduce flow blockiness */ + float value = 1.0f - pow(1.0f - emission_value, 2.0f); + + if (value > react[index]) { + float f = fuel_flow / fuel[index]; + react[index] = value * f + (1.0f - f) * react[index]; + } + } +} + +static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sds, float time, float dt) { Object **flowobjs = NULL; + EmissionMap *emaps = NULL; unsigned int numflowobj = 0; unsigned int flowIndex; + int new_shift[3] = {0}; + int active_fields = sds->active_fields; + + /* calculate domain shift for current frame if using adaptive domain */ + if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) { + int total_shift[3]; + float frame_shift_f[3]; + float ob_loc[3] = {0}; + + mul_m4_v3(ob->obmat, ob_loc); + + VECSUB(frame_shift_f, ob_loc, sds->prev_loc); + copy_v3_v3(sds->prev_loc, ob_loc); + /* convert global space shift to local "cell" space */ + mul_mat3_m4_v3(sds->imat, frame_shift_f); + frame_shift_f[0] = frame_shift_f[0] / sds->cell_size[0]; + frame_shift_f[1] = frame_shift_f[1] / sds->cell_size[1]; + frame_shift_f[2] = frame_shift_f[2] / sds->cell_size[2]; + /* add to total shift */ + VECADD(sds->shift_f, sds->shift_f, frame_shift_f); + /* convert to integer */ + total_shift[0] = floor(sds->shift_f[0]); + total_shift[1] = floor(sds->shift_f[1]); + total_shift[2] = floor(sds->shift_f[2]); + VECSUB(new_shift, total_shift, sds->shift); + copy_v3_v3_int(sds->shift, total_shift); + + /* calculate new domain boundary points so that smoke doesnt slide on sub-cell movement */ + sds->p0[0] = sds->dp0[0] - sds->cell_size[0] * (sds->shift_f[0] - total_shift[0] - 0.5f); + sds->p0[1] = sds->dp0[1] - sds->cell_size[1] * (sds->shift_f[1] - total_shift[1] - 0.5f); + sds->p0[2] = sds->dp0[2] - sds->cell_size[2] * (sds->shift_f[2] - total_shift[2] - 0.5f); + sds->p1[0] = sds->p0[0] + sds->cell_size[0] * sds->base_res[0]; + sds->p1[1] = sds->p0[1] + sds->cell_size[1] * sds->base_res[1]; + sds->p1[2] = sds->p0[2] + sds->cell_size[2] * sds->base_res[2]; + } flowobjs = get_collisionobjects(scene, ob, sds->fluid_group, &numflowobj, eModifierType_Smoke); - // update obstacle tags in cells - for(flowIndex = 0; flowIndex < numflowobj; flowIndex++) + /* init emission maps for each flow */ + emaps = MEM_callocN(sizeof(struct EmissionMap) * numflowobj, "smoke_flow_maps"); + + /* Prepare flow emission maps */ + for (flowIndex = 0; flowIndex < numflowobj; flowIndex++) { - Object *collob= flowobjs[flowIndex]; - SmokeModifierData *smd2 = (SmokeModifierData*)modifiers_findByType(collob, eModifierType_Smoke); + Object *collob = flowobjs[flowIndex]; + SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(collob, eModifierType_Smoke); // check for initialized smoke object - if((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) + if ((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) { // we got nice flow object SmokeFlowSettings *sfs = smd2->flow; + EmissionMap *em = &emaps[flowIndex]; - if(sfs && sfs->psys && sfs->psys->part && sfs->psys->part->type==PART_EMITTER) // is particle system selected - { - ParticleSimulationData sim; - ParticleSystem *psys = sfs->psys; - int totpart=psys->totpart, totchild; - int p = 0; - float *density = smoke_get_density(sds->fluid); - float *bigdensity = smoke_turbulence_get_density(sds->wt); - float *heat = smoke_get_heat(sds->fluid); - float *velocity_x = smoke_get_velocity_x(sds->fluid); - float *velocity_y = smoke_get_velocity_y(sds->fluid); - float *velocity_z = smoke_get_velocity_z(sds->fluid); - unsigned char *obstacle = smoke_get_obstacle(sds->fluid); - // DG TODO UNUSED unsigned char *obstacleAnim = smoke_get_obstacle_anim(sds->fluid); - int bigres[3]; - short absolute_flow = (sfs->flags & MOD_SMOKE_FLOW_ABSOLUTE); - short high_emission_smoothing = bigdensity ? (sds->flags & MOD_SMOKE_HIGH_SMOOTH) : 0; + if (sfs->source == MOD_SMOKE_FLOW_SOURCE_PARTICLES) { + emit_from_particles(collob, sds, sfs, em, scene, time, dt); + } + else { + emit_from_derivedmesh(collob, sds, sfs, em, dt); + } - /* - * A temporary volume map used to store whole emissive - * area to be added to smoke density and interpolated - * for high resolution smoke. - */ - float *temp_emission_map = NULL; - - sim.scene = scene; - sim.ob = collob; - sim.psys = psys; - - // initialize temp emission map - if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW)) - { - int i; - temp_emission_map = MEM_callocN(sizeof(float) * sds->res[0]*sds->res[1]*sds->res[2], "SmokeTempEmission"); - // set whole volume to 0.0f - for (i=0; ires[0]*sds->res[1]*sds->res[2]; i++) { - temp_emission_map[i] = 0.0f; + /* update required data fields */ + if (em->total_cells && sfs->type != MOD_SMOKE_FLOW_TYPE_OUTFLOW) { + /* activate heat field if flow produces any heat */ + if (sfs->temp) { + active_fields |= SM_ACTIVE_HEAT; + } + /* activate fuel field if flow adds any fuel */ + if (sfs->type != MOD_SMOKE_FLOW_TYPE_SMOKE && sfs->fuel_amount) { + active_fields |= SM_ACTIVE_FIRE; + } + /* activate color field if flows add smoke with varying colors */ + if (sfs->type != MOD_SMOKE_FLOW_TYPE_FIRE && sfs->density) { + if (!(active_fields & SM_ACTIVE_COLOR_SET)) { + copy_v3_v3(sds->active_color, sfs->color); + active_fields |= SM_ACTIVE_COLOR_SET; + } + else if (!equals_v3v3(sds->active_color, sfs->color)) { + active_fields |= SM_ACTIVE_COLORS; } } - - // mostly copied from particle code - if(psys->part->type==PART_HAIR) - { - /* - if(psys->childcache) - { - totchild = psys->totchildcache; - } - else - */ - - // TODO: PART_HAIR not supported whatsoever - totchild=0; - } - else - totchild=psys->totchild*psys->part->disp/100; - - for(p=0; pparticles[p].flag & (PARS_NO_DISP|PARS_UNEXIST)) - continue; - } - else { - /* handle child particle */ - ChildParticle *cpa = &psys->child[p - totpart]; - - if(psys->particles[cpa->parent].flag & (PARS_NO_DISP|PARS_UNEXIST)) - continue; - } - - state.time = time; - if(psys_get_particle_state(&sim, p, &state, 0) == 0) - continue; - - // copy_v3_v3(pos, pa->state.co); - // mul_m4_v3(ob->imat, pos); - // 1. get corresponding cell - get_cell(sds->p0, sds->res, sds->dx*sds->scale, state.co, cell, 0); - // check if cell is valid (in the domain boundary) - for(i = 0; i < 3; i++) - { - if((cell[i] > sds->res[i] - 1) || (cell[i] < 0)) - { - badcell = 1; - break; - } - } - if(badcell) - continue; - // 2. set cell values (heat, density and velocity) - index = smoke_get_index(cell[0], sds->res[0], cell[1], sds->res[1], cell[2]); - if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) && !(obstacle[index])) // this is inflow - { - // heat[index] += sfs->temp * 0.1; - // density[index] += sfs->density * 0.1; - heat[index] = sfs->temp; - - // Add emitter density to temp emission map - temp_emission_map[index] = sfs->density; - - // Uses particle velocity as initial velocity for smoke - if(sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && (psys->part->phystype != PART_PHYS_NO)) - { - velocity_x[index] = state.vel[0]*sfs->vel_multi; - velocity_y[index] = state.vel[1]*sfs->vel_multi; - velocity_z[index] = state.vel[2]*sfs->vel_multi; - } - } - else if(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) // outflow - { - heat[index] = 0.f; - density[index] = 0.f; - velocity_x[index] = 0.f; - velocity_y[index] = 0.f; - velocity_z[index] = 0.f; - // we need different handling for the high-res feature - if(bigdensity) - { - // init all surrounding cells according to amplification, too - int i, j, k; - smoke_turbulence_get_res(sds->wt, bigres); - - for(i = 0; i < sds->amplify + 1; i++) - for(j = 0; j < sds->amplify + 1; j++) - for(k = 0; k < sds->amplify + 1; k++) - { - index = smoke_get_index((sds->amplify + 1)* cell[0] + i, bigres[0], (sds->amplify + 1)* cell[1] + j, bigres[1], (sds->amplify + 1)* cell[2] + k); - bigdensity[index] = 0.f; - } - } - } - } // particles loop - - // apply emission values - if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW)) - { - // initialize variables - int ii, jj, kk, x, y, z, block_size; - size_t index, index_big; - - smoke_turbulence_get_res(sds->wt, bigres); - block_size = sds->amplify + 1; // high res block size - - // loop through every low res cell - for(x = 0; x < sds->res[0]; x++) - for(y = 0; y < sds->res[1]; y++) - for(z = 0; z < sds->res[2]; z++) - { - // neighbor cell emission densities (for high resolution smoke smooth interpolation) - float c000, c001, c010, c011, c100, c101, c110, c111; - - c000 = (x>0 && y>0 && z>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y-1, sds->res[1], z-1)] : 0; - c001 = (x>0 && y>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y-1, sds->res[1], z)] : 0; - c010 = (x>0 && z>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y, sds->res[1], z-1)] : 0; - c011 = (x>0) ? temp_emission_map[smoke_get_index(x-1, sds->res[0], y, sds->res[1], z)] : 0; - - c100 = (y>0 && z>0) ? temp_emission_map[smoke_get_index(x, sds->res[0], y-1, sds->res[1], z-1)] : 0; - c101 = (y>0) ? temp_emission_map[smoke_get_index(x, sds->res[0], y-1, sds->res[1], z)] : 0; - c110 = (z>0) ? temp_emission_map[smoke_get_index(x, sds->res[0], y, sds->res[1], z-1)] : 0; - c111 = temp_emission_map[smoke_get_index(x, sds->res[0], y, sds->res[1], z)]; // this cell - - // get cell index - index = smoke_get_index(x, sds->res[0], y, sds->res[1], z); - - // add emission to low resolution density - if (absolute_flow) - { - if (temp_emission_map[index]>0) - density[index] = temp_emission_map[index]; - } - else - { - density[index] += temp_emission_map[index]; - - if (density[index]>1) - density[index]=1.0f; - } - - smoke_turbulence_get_res(sds->wt, bigres); - - /* loop through high res blocks if high res enabled */ - if (bigdensity) - for(ii = 0; ii < block_size; ii++) - for(jj = 0; jj < block_size; jj++) - for(kk = 0; kk < block_size; kk++) - { - - float fx,fy,fz, interpolated_value; - int shift_x, shift_y, shift_z; - - - /* - * Do volume interpolation if emitter smoothing - * is enabled - */ - if (high_emission_smoothing) - { - // convert block position to relative - // for interpolation smoothing - fx = (float)ii/block_size + 0.5f/block_size; - fy = (float)jj/block_size + 0.5f/block_size; - fz = (float)kk/block_size + 0.5f/block_size; - - // calculate trilinear interpolation - interpolated_value = c000 * (1-fx) * (1-fy) * (1-fz) + - c100 * fx * (1-fy) * (1-fz) + - c010 * (1-fx) * fy * (1-fz) + - c001 * (1-fx) * (1-fy) * fz + - c101 * fx * (1-fy) * fz + - c011 * (1-fx) * fy * fz + - c110 * fx * fy * (1-fz) + - c111 * fx * fy * fz; - - - // add some contrast / sharpness - // depending on hi-res block size - - interpolated_value = (interpolated_value-0.4f*sfs->density)*(block_size/2) + 0.4f*sfs->density; - if (interpolated_value<0.0f) interpolated_value = 0.0f; - if (interpolated_value>1.0f) interpolated_value = 1.0f; - - // shift smoke block index - // (because pixel center is actually - // in halfway of the low res block) - shift_x = (x < 1) ? 0 : block_size/2; - shift_y = (y < 1) ? 0 : block_size/2; - shift_z = (z < 1) ? 0 : block_size/2; - } - else - { - // without interpolation use same low resolution - // block value for all hi-res blocks - interpolated_value = c111; - shift_x = 0; - shift_y = 0; - shift_z = 0; - } - - // get shifted index for current high resolution block - index_big = smoke_get_index(block_size * x + ii - shift_x, bigres[0], block_size * y + jj - shift_y, bigres[1], block_size * z + kk - shift_z); - - // add emission data to high resolution density - if (absolute_flow) - { - if (interpolated_value > 0) - bigdensity[index_big] = interpolated_value; - } - else - { - bigdensity[index_big] += interpolated_value; - - if (bigdensity[index_big]>1) - bigdensity[index_big]=1.0f; - } - } // end of hires loop - - } // end of low res loop - - // free temporary emission map - if (temp_emission_map) - MEM_freeN(temp_emission_map); - - } // end emission } } } - if(flowobjs) + /* monitor active fields based on domain settings */ + /* if domain has fire, activate new fields if required */ + if (active_fields & SM_ACTIVE_FIRE) { + /* heat is always needed for fire */ + active_fields |= SM_ACTIVE_HEAT; + /* also activate colors if domain smoke color differs from active color */ + if (!(active_fields & SM_ACTIVE_COLOR_SET)) { + copy_v3_v3(sds->active_color, sds->flame_smoke_color); + active_fields |= SM_ACTIVE_COLOR_SET; + } + else if (!equals_v3v3(sds->active_color, sds->flame_smoke_color)) { + active_fields |= SM_ACTIVE_COLORS; + } + } + + /* Adjust domain size if needed */ + if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) { + adjustDomainResolution(sds, new_shift, emaps, numflowobj, dt); + } + + /* Initialize new data fields if any */ + if (active_fields & SM_ACTIVE_HEAT) { + smoke_ensure_heat(sds->fluid); + } + if (active_fields & SM_ACTIVE_FIRE) { + smoke_ensure_fire(sds->fluid, sds->wt); + } + if (active_fields & SM_ACTIVE_COLORS) { + /* initialize all smoke with "active_color" */ + smoke_ensure_colors(sds->fluid, sds->wt, sds->active_color[0], sds->active_color[1], sds->active_color[2]); + } + sds->active_fields = active_fields; + + /* Apply emission data */ + if (sds->fluid) { + for (flowIndex = 0; flowIndex < numflowobj; flowIndex++) + { + Object *collob = flowobjs[flowIndex]; + SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(collob, eModifierType_Smoke); + + // check for initialized smoke object + if ((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) + { + // we got nice flow object + SmokeFlowSettings *sfs = smd2->flow; + EmissionMap *em = &emaps[flowIndex]; + + float *density = smoke_get_density(sds->fluid); + float *color_r = smoke_get_color_r(sds->fluid); + float *color_g = smoke_get_color_g(sds->fluid); + float *color_b = smoke_get_color_b(sds->fluid); + float *fuel = smoke_get_fuel(sds->fluid); + float *react = smoke_get_react(sds->fluid); + float *bigdensity = smoke_turbulence_get_density(sds->wt); + float *bigfuel = smoke_turbulence_get_fuel(sds->wt); + float *bigreact = smoke_turbulence_get_react(sds->wt); + float *bigcolor_r = smoke_turbulence_get_color_r(sds->wt); + float *bigcolor_g = smoke_turbulence_get_color_g(sds->wt); + float *bigcolor_b = smoke_turbulence_get_color_b(sds->wt); + float *heat = smoke_get_heat(sds->fluid); + float *velocity_x = smoke_get_velocity_x(sds->fluid); + float *velocity_y = smoke_get_velocity_y(sds->fluid); + float *velocity_z = smoke_get_velocity_z(sds->fluid); + //unsigned char *obstacle = smoke_get_obstacle(sds->fluid); + // DG TODO UNUSED unsigned char *obstacleAnim = smoke_get_obstacle_anim(sds->fluid); + int bigres[3]; + short high_emission_smoothing = (sds->flags & MOD_SMOKE_HIGH_SMOOTH); + float *velocity_map = em->velocity; + float *emission_map = em->influence; + + int ii, jj, kk, gx, gy, gz, ex, ey, ez, dx, dy, dz, block_size; + size_t e_index, d_index, index_big; + + // loop through every emission map cell + for (gx = em->min[0]; gx < em->max[0]; gx++) + for (gy = em->min[1]; gy < em->max[1]; gy++) + for (gz = em->min[2]; gz < em->max[2]; gz++) + { + /* get emission map index */ + ex = gx - em->min[0]; + ey = gy - em->min[1]; + ez = gz - em->min[2]; + e_index = smoke_get_index(ex, em->res[0], ey, em->res[1], ez); + if (!emission_map[e_index]) continue; + /* get domain index */ + dx = gx - sds->res_min[0]; + dy = gy - sds->res_min[1]; + dz = gz - sds->res_min[2]; + d_index = smoke_get_index(dx, sds->res[0], dy, sds->res[1], dz); + + if (sfs->type == MOD_SMOKE_FLOW_TYPE_OUTFLOW) { // outflow + apply_outflow_fields(d_index, density, heat, fuel, react, color_r, color_g, color_b); + } + else { // inflow + apply_inflow_fields(sfs, emission_map[e_index], d_index, density, heat, fuel, react, color_r, color_g, color_b); + + /* initial velocity */ + if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY) { + velocity_x[d_index] = ADD_IF_LOWER(velocity_x[d_index], velocity_map[e_index * 3]); + velocity_y[d_index] = ADD_IF_LOWER(velocity_y[d_index], velocity_map[e_index * 3 + 1]); + velocity_z[d_index] = ADD_IF_LOWER(velocity_z[d_index], velocity_map[e_index * 3 + 2]); + } + } + + /* loop through high res blocks if high res enabled */ + if (bigdensity) { + // neighbor cell emission densities (for high resolution smoke smooth interpolation) + float c000, c001, c010, c011, c100, c101, c110, c111; + + smoke_turbulence_get_res(sds->wt, bigres); + block_size = sds->amplify + 1; // high res block size + + c000 = (ex > 0 && ey > 0 && ez > 0) ? emission_map[smoke_get_index(ex - 1, em->res[0], ey - 1, em->res[1], ez - 1)] : 0; + c001 = (ex > 0 && ey > 0) ? emission_map[smoke_get_index(ex - 1, em->res[0], ey - 1, em->res[1], ez)] : 0; + c010 = (ex > 0 && ez > 0) ? emission_map[smoke_get_index(ex - 1, em->res[0], ey, em->res[1], ez - 1)] : 0; + c011 = (ex > 0) ? emission_map[smoke_get_index(ex - 1, em->res[0], ey, em->res[1], ez)] : 0; + + c100 = (ey > 0 && ez > 0) ? emission_map[smoke_get_index(ex, em->res[0], ey - 1, em->res[1], ez - 1)] : 0; + c101 = (ey > 0) ? emission_map[smoke_get_index(ex, em->res[0], ey - 1, em->res[1], ez)] : 0; + c110 = (ez > 0) ? emission_map[smoke_get_index(ex, em->res[0], ey, em->res[1], ez - 1)] : 0; + c111 = emission_map[smoke_get_index(ex, em->res[0], ey, em->res[1], ez)]; // this cell + + for (ii = 0; ii < block_size; ii++) + for (jj = 0; jj < block_size; jj++) + for (kk = 0; kk < block_size; kk++) + { + + float fx, fy, fz, interpolated_value; + int shift_x, shift_y, shift_z; + + + /* + * Do volume interpolation if emitter smoothing + * is enabled + */ + if (high_emission_smoothing) + { + /* get relative block position + * for interpolation smoothing */ + fx = (float)ii / block_size + 0.5f / block_size; + fy = (float)jj / block_size + 0.5f / block_size; + fz = (float)kk / block_size + 0.5f / block_size; + + /* calculate trilinear interpolation */ + interpolated_value = c000 * (1 - fx) * (1 - fy) * (1 - fz) + + c100 * fx * (1 - fy) * (1 - fz) + + c010 * (1 - fx) * fy * (1 - fz) + + c001 * (1 - fx) * (1 - fy) * fz + + c101 * fx * (1 - fy) * fz + + c011 * (1 - fx) * fy * fz + + c110 * fx * fy * (1 - fz) + + c111 * fx * fy * fz; + + + /* add some contrast / sharpness + * depending on hi-res block size */ + interpolated_value = (interpolated_value - 0.4f) * (block_size / 2) + 0.4f; + CLAMP(interpolated_value, 0.0f, 1.0f); + + /* shift smoke block index + * (because pixel center is actually + * in halfway of the low res block) */ + shift_x = (dx < 1) ? 0 : block_size / 2; + shift_y = (dy < 1) ? 0 : block_size / 2; + shift_z = (dz < 1) ? 0 : block_size / 2; + } + else { + /* without interpolation use same low resolution + * block value for all hi-res blocks */ + interpolated_value = c111; + shift_x = 0; + shift_y = 0; + shift_z = 0; + } + + /* get shifted index for current high resolution block */ + index_big = smoke_get_index(block_size * dx + ii - shift_x, bigres[0], block_size * dy + jj - shift_y, bigres[1], block_size * dz + kk - shift_z); + + if (sfs->type == MOD_SMOKE_FLOW_TYPE_OUTFLOW) { // outflow + if (interpolated_value) { + apply_outflow_fields(index_big, bigdensity, NULL, bigfuel, bigreact, bigcolor_r, bigcolor_g, bigcolor_b); + } + } + else { // inflow + apply_inflow_fields(sfs, interpolated_value, index_big, bigdensity, NULL, bigfuel, bigreact, bigcolor_r, bigcolor_g, bigcolor_b); + } + } // hires loop + } // bigdensity + } // low res loop + + // free emission maps + em_freeData(em); + + } // end emission + } + } + + if (flowobjs) MEM_freeN(flowobjs); + if (emaps) + MEM_freeN(emaps); } static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds, float UNUSED(dt)) { - ListBase *effectors = pdInitEffectors(scene, ob, NULL, sds->effector_weights); + ListBase *effectors; + /* make sure smoke flow influence is 0.0f */ + sds->effector_weights->weight[PFIELD_SMOKEFLOW] = 0.0f; + effectors = pdInitEffectors(scene, ob, NULL, sds->effector_weights); - if(effectors) + if (effectors) { float *density = smoke_get_density(sds->fluid); float *force_x = smoke_get_force_x(sds->fluid); @@ -1532,76 +1901,113 @@ static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds, float *velocity_y = smoke_get_velocity_y(sds->fluid); float *velocity_z = smoke_get_velocity_z(sds->fluid); unsigned char *obstacle = smoke_get_obstacle(sds->fluid); - int x, y, z; + int x; // precalculate wind forces - for(x = 0; x < sds->res[0]; x++) - for(y = 0; y < sds->res[1]; y++) - for(z = 0; z < sds->res[2]; z++) - { - EffectedPoint epoint; - float voxelCenter[3] = {0,0,0}, vel[3] = {0,0,0}, retvel[3] = {0,0,0}; - unsigned int index = smoke_get_index(x, sds->res[0], y, sds->res[1], z); + #pragma omp parallel for schedule(static) + for (x = 0; x < sds->res[0]; x++) + { + int y, z; + for (y = 0; y < sds->res[1]; y++) + for (z = 0; z < sds->res[2]; z++) + { + EffectedPoint epoint; + float mag; + float voxelCenter[3] = {0, 0, 0}, vel[3] = {0, 0, 0}, retvel[3] = {0, 0, 0}; + unsigned int index = smoke_get_index(x, sds->res[0], y, sds->res[1], z); - if((density[index] < FLT_EPSILON) || obstacle[index]) - continue; + if ((density[index] < FLT_EPSILON) || obstacle[index]) + continue; - vel[0] = velocity_x[index]; - vel[1] = velocity_y[index]; - vel[2] = velocity_z[index]; + vel[0] = velocity_x[index]; + vel[1] = velocity_y[index]; + vel[2] = velocity_z[index]; - voxelCenter[0] = sds->p0[0] + sds->dx * sds->scale * x + sds->dx * sds->scale * 0.5; - voxelCenter[1] = sds->p0[1] + sds->dx * sds->scale * y + sds->dx * sds->scale * 0.5; - voxelCenter[2] = sds->p0[2] + sds->dx * sds->scale * z + sds->dx * sds->scale * 0.5; + /* convert vel to global space */ + mag = len_v3(vel); + mul_mat3_m4_v3(sds->obmat, vel); + normalize_v3(vel); + mul_v3_fl(vel, mag); - pd_point_from_loc(scene, voxelCenter, vel, index, &epoint); - pdDoEffectors(effectors, NULL, sds->effector_weights, &epoint, retvel, NULL); + voxelCenter[0] = sds->p0[0] + sds->cell_size[0] * ((float)(x + sds->res_min[0]) + 0.5f); + voxelCenter[1] = sds->p0[1] + sds->cell_size[1] * ((float)(y + sds->res_min[1]) + 0.5f); + voxelCenter[2] = sds->p0[2] + sds->cell_size[2] * ((float)(z + sds->res_min[2]) + 0.5f); + mul_m4_v3(sds->obmat, voxelCenter); - // TODO dg - do in force! - force_x[index] = MIN2(MAX2(-1.0, retvel[0] * 0.2), 1.0); - force_y[index] = MIN2(MAX2(-1.0, retvel[1] * 0.2), 1.0); - force_z[index] = MIN2(MAX2(-1.0, retvel[2] * 0.2), 1.0); + pd_point_from_loc(scene, voxelCenter, vel, index, &epoint); + pdDoEffectors(effectors, NULL, sds->effector_weights, &epoint, retvel, NULL); + + /* convert retvel to local space */ + mag = len_v3(retvel); + mul_mat3_m4_v3(sds->imat, retvel); + normalize_v3(retvel); + mul_v3_fl(retvel, mag); + + // TODO dg - do in force! + force_x[index] = MIN2(MAX2(-1.0, retvel[0] * 0.2), 1.0); + force_y[index] = MIN2(MAX2(-1.0, retvel[1] * 0.2), 1.0); + force_z[index] = MIN2(MAX2(-1.0, retvel[2] * 0.2), 1.0); + } } } pdEndEffectors(&effectors); } -static void step(Scene *scene, Object *ob, SmokeModifierData *smd, float fps) +static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh *domain_dm, float fps) { + SmokeDomainSettings *sds = smd->domain; /* stability values copied from wturbulence.cpp */ const int maxSubSteps = 25; float maxVel; // maxVel should be 1.5 (1.5 cell max movement) * dx (cell size) - float dt = DT_DEFAULT; + float dt; float maxVelMag = 0.0f; int totalSubsteps; int substep = 0; float dtSubdiv; + float gravity[3] = {0.0f, 0.0f, -1.0f}; + float gravity_mag; - SmokeDomainSettings *sds = smd->domain; - - /* get max velocity and lower the dt value if it is too high */ - size_t size= sds->res[0] * sds->res[1] * sds->res[2]; - +#if 0 /* UNUSED */ + /* get max velocity and lower the dt value if it is too high */ + size_t size = sds->res[0] * sds->res[1] * sds->res[2]; float *velX = smoke_get_velocity_x(sds->fluid); float *velY = smoke_get_velocity_y(sds->fluid); float *velZ = smoke_get_velocity_z(sds->fluid); size_t i; +#endif + + /* update object state */ + invert_m4_m4(sds->imat, ob->obmat); + copy_m4_m4(sds->obmat, ob->obmat); + smoke_set_domain_from_derivedmesh(sds, ob, domain_dm); + + /* use global gravity if enabled */ + if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { + copy_v3_v3(gravity, scene->physics_settings.gravity); + /* map default value to 1.0 */ + mul_v3_fl(gravity, 1.0f / 9.810f); + } + /* convert gravity to domain space */ + gravity_mag = len_v3(gravity); + mul_mat3_m4_v3(sds->imat, gravity); + normalize_v3(gravity); + mul_v3_fl(gravity, gravity_mag); /* adapt timestep for different framerates, dt = 0.1 is at 25fps */ - dt *= (25.0f / fps); - + dt = DT_DEFAULT * (25.0f / fps); // maximum timestep/"CFL" constraint: dt < 5.0 *dx / maxVel maxVel = (sds->dx * 5.0); - for(i = 0; i < size; i++) - { - float vtemp = (velX[i]*velX[i]+velY[i]*velY[i]+velZ[i]*velZ[i]); - if(vtemp > maxVelMag) +#if 0 + for (i = 0; i < size; i++) { + float vtemp = (velX[i] * velX[i] + velY[i] * velY[i] + velZ[i] * velZ[i]); + if (vtemp > maxVelMag) maxVelMag = vtemp; } +#endif maxVelMag = sqrt(maxVelMag) * dt * sds->time_scale; totalSubsteps = (int)((maxVelMag / maxVel) + 1.0f); /* always round up */ @@ -1609,146 +2015,155 @@ static void step(Scene *scene, Object *ob, SmokeModifierData *smd, float fps) totalSubsteps = (totalSubsteps > maxSubSteps) ? maxSubSteps : totalSubsteps; /* Disable substeps for now, since it results in numerical instability */ - totalSubsteps = 1.0f; + totalSubsteps = 1.0f; dtSubdiv = (float)dt / (float)totalSubsteps; // printf("totalSubsteps: %d, maxVelMag: %f, dt: %f\n", totalSubsteps, maxVelMag, dt); - for(substep = 0; substep < totalSubsteps; substep++) + for (substep = 0; substep < totalSubsteps; substep++) { // calc animated obstacle velocities + update_flowsfluids(scene, ob, sds, smd->time, dtSubdiv); update_obstacles(scene, ob, sds, dtSubdiv, substep, totalSubsteps); - update_flowsfluids(scene, ob, sds, smd->time); - update_effectors(scene, ob, sds, dtSubdiv); // DG TODO? problem --> uses forces instead of velocity, need to check how they need to be changed with variable dt - smoke_step(sds->fluid, dtSubdiv); - - // move animated obstacle: Done in update_obstacles() */ - - // where to delete old obstacles from array? Done in update_obstacles() */ + if (sds->total_cells > 1) { + update_effectors(scene, ob, sds, dtSubdiv); // DG TODO? problem --> uses forces instead of velocity, need to check how they need to be changed with variable dt + smoke_step(sds->fluid, gravity, dtSubdiv); + } } } -void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm) -{ - if((smd->type & MOD_SMOKE_TYPE_FLOW)) +static DerivedMesh *createDomainGeometry(SmokeDomainSettings *sds, Object *ob) +{ + DerivedMesh *result; + MVert *mverts; + MPoly *mpolys; + MLoop *mloops; + float min[3]; + float max[3]; + float *co; + MPoly *mp; + MLoop *ml; + + int num_verts = 8; + int num_faces = 6; + int i; + float ob_loc[3] = {0}; + float ob_cache_loc[3] = {0}; + + /* dont generate any mesh if there isnt any content */ + if (sds->total_cells <= 1) { + num_verts = 0; + num_faces = 0; + } + + result = CDDM_new(num_verts, 0, 0, num_faces * 4, num_faces); + mverts = CDDM_get_verts(result); + mpolys = CDDM_get_polys(result); + mloops = CDDM_get_loops(result); + + + if (num_verts) { + /* volume bounds */ + VECMADD(min, sds->p0, sds->cell_size, sds->res_min); + VECMADD(max, sds->p0, sds->cell_size, sds->res_max); + + /* set vertices */ + /* top slab */ + co = mverts[0].co; co[0] = min[0]; co[1] = min[1]; co[2] = max[2]; + co = mverts[1].co; co[0] = max[0]; co[1] = min[1]; co[2] = max[2]; + co = mverts[2].co; co[0] = max[0]; co[1] = max[1]; co[2] = max[2]; + co = mverts[3].co; co[0] = min[0]; co[1] = max[1]; co[2] = max[2]; + /* bottom slab */ + co = mverts[4].co; co[0] = min[0]; co[1] = min[1]; co[2] = min[2]; + co = mverts[5].co; co[0] = max[0]; co[1] = min[1]; co[2] = min[2]; + co = mverts[6].co; co[0] = max[0]; co[1] = max[1]; co[2] = min[2]; + co = mverts[7].co; co[0] = min[0]; co[1] = max[1]; co[2] = min[2]; + + /* create faces */ + /* top */ + mp = &mpolys[0]; ml = &mloops[0 * 4]; mp->loopstart = 0 * 4; mp->totloop = 4; + ml[0].v = 0; ml[1].v = 1; ml[2].v = 2; ml[3].v = 3; + /* right */ + mp = &mpolys[1]; ml = &mloops[1 * 4]; mp->loopstart = 1 * 4; mp->totloop = 4; + ml[0].v = 2; ml[1].v = 1; ml[2].v = 5; ml[3].v = 6; + /* bottom */ + mp = &mpolys[2]; ml = &mloops[2 * 4]; mp->loopstart = 2 * 4; mp->totloop = 4; + ml[0].v = 7; ml[1].v = 6; ml[2].v = 5; ml[3].v = 4; + /* left */ + mp = &mpolys[3]; ml = &mloops[3 * 4]; mp->loopstart = 3 * 4; mp->totloop = 4; + ml[0].v = 0; ml[1].v = 3; ml[2].v = 7; ml[3].v = 4; + /* front */ + mp = &mpolys[4]; ml = &mloops[4 * 4]; mp->loopstart = 4 * 4; mp->totloop = 4; + ml[0].v = 3; ml[1].v = 2; ml[2].v = 6; ml[3].v = 7; + /* back */ + mp = &mpolys[5]; ml = &mloops[5 * 4]; mp->loopstart = 5 * 4; mp->totloop = 4; + ml[0].v = 1; ml[1].v = 0; ml[2].v = 4; ml[3].v = 5; + + /* calculate required shift to match domain's global position + * it was originally simulated at (if object moves without smoke step) */ + invert_m4_m4(ob->imat, ob->obmat); + mul_m4_v3(ob->obmat, ob_loc); + mul_m4_v3(sds->obmat, ob_cache_loc); + VECSUB(sds->obj_shift_f, ob_cache_loc, ob_loc); + /* convert shift to local space and apply to vertices */ + mul_mat3_m4_v3(ob->imat, sds->obj_shift_f); + /* apply */ + for (i = 0; i < num_verts; i++) { + add_v3_v3(mverts[i].co, sds->obj_shift_f); + } + } + + + CDDM_calc_edges(result); + return result; +} + +static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm) +{ + if ((smd->type & MOD_SMOKE_TYPE_FLOW)) { - if(scene->r.cfra >= smd->time) + if (scene->r.cfra >= smd->time) smokeModifier_init(smd, ob, scene, dm); - if(scene->r.cfra > smd->time) - { - // XXX TODO - smd->time = scene->r.cfra; + if (smd->flow->dm) smd->flow->dm->release(smd->flow->dm); + smd->flow->dm = CDDM_copy(dm); + DM_ensure_tessface(smd->flow->dm); - // rigid movement support - /* - copy_m4_m4(smd->flow->mat_old, smd->flow->mat); - copy_m4_m4(smd->flow->mat, ob->obmat); - */ + if (scene->r.cfra > smd->time) + { + smd->time = scene->r.cfra; } - else if(scene->r.cfra < smd->time) + else if (scene->r.cfra < smd->time) { smd->time = scene->r.cfra; smokeModifier_reset(smd); } } - else if(smd->type & MOD_SMOKE_TYPE_COLL) + else if (smd->type & MOD_SMOKE_TYPE_COLL) { - /* Check if domain resolution changed */ - /* DG TODO: can this be solved more elegant using dependancy graph? */ - { - SmokeCollSettings *scs = smd->coll; - Base *base = scene->base.first; - int changed = 0; - float dx = FLT_MAX; - float scale = 1.0f; - int haveDomain = 0; - - for ( ; base; base = base->next) - { - SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(base->object, eModifierType_Smoke); - - if (smd2 && (smd2->type & MOD_SMOKE_TYPE_DOMAIN) && smd2->domain) - { - SmokeDomainSettings *sds = smd2->domain; - - if(sds->dx * sds->scale < dx) - { - dx = sds->dx; - scale = sds->scale; - changed = 1; - } - - haveDomain = 1; - } - } - - if(!haveDomain) - return; - - if(changed) - { - if(dx*scale != scs->dx) - { - scs->dx = dx*scale; - smokeModifier_reset(smd); - } - } - } - - if(scene->r.cfra >= smd->time) + if (scene->r.cfra >= smd->time) smokeModifier_init(smd, ob, scene, dm); - if(scene->r.cfra > smd->time) + if (smd->coll) { - unsigned int i; - SmokeCollSettings *scs = smd->coll; - float *points_old = scs->points_old; - float *points = scs->points; - unsigned int numpoints = scs->numpoints; + if (smd->coll->dm) + smd->coll->dm->release(smd->coll->dm); - // XXX TODO <-- DG: what is TODO here? - smd->time = scene->r.cfra; - - // rigid movement support - copy_m4_m4(scs->mat_old, scs->mat); - copy_m4_m4(scs->mat, ob->obmat); - - if(scs->type != SM_COLL_ANIMATED) // if(not_animated) - { - // nothing to do, "mat" is already up to date - } - else - { - // XXX TODO: need to update positions + divs - - if(scs->numverts != dm->getNumVerts(dm)) - { - // DG TODO: reset modifier? - return; - } - - for(i = 0; i < numpoints * 3; i++) - { - points_old[i] = points[i]; - } - - DM_ensure_tessface(dm); - fill_scs_points_anim(ob, dm, scs); - } + smd->coll->dm = CDDM_copy(dm); + DM_ensure_tessface(smd->coll->dm); } - else if(scene->r.cfra < smd->time) + + smd->time = scene->r.cfra; + if (scene->r.cfra < smd->time) { - smd->time = scene->r.cfra; smokeModifier_reset(smd); } } - else if(smd->type & MOD_SMOKE_TYPE_DOMAIN) + else if (smd->type & MOD_SMOKE_TYPE_DOMAIN) { SmokeDomainSettings *sds = smd->domain; - float light[3]; PointCache *cache = NULL; PTCacheID pid; int startframe, endframe, framenr; @@ -1762,41 +2177,39 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM BKE_ptcache_id_from_smoke(&pid, ob, smd); BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, ×cale); - if(!smd->domain->fluid || framenr == startframe) + if (!smd->domain->fluid || framenr == startframe) { BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + smokeModifier_reset(smd); BKE_ptcache_validate(cache, framenr); cache->flag &= ~PTCACHE_REDO_NEEDED; } - if(!smd->domain->fluid && (framenr != startframe) && (smd->domain->flags & MOD_SMOKE_FILE_LOAD)==0 && (cache->flag & PTCACHE_BAKED)==0) + if (!smd->domain->fluid && (framenr != startframe) && (smd->domain->flags & MOD_SMOKE_FILE_LOAD) == 0 && (cache->flag & PTCACHE_BAKED) == 0) return; smd->domain->flags &= ~MOD_SMOKE_FILE_LOAD; - CLAMP(framenr, startframe, endframe); /* If already viewing a pre/after frame, no need to reload */ if ((smd->time == framenr) && (framenr != scene->r.cfra)) return; - // printf("startframe: %d, framenr: %d\n", startframe, framenr); - - if(smokeModifier_init(smd, ob, scene, dm)==0) + if (smokeModifier_init(smd, ob, scene, dm) == 0) { printf("bad smokeModifier_init\n"); return; } /* try to read from cache */ - if(BKE_ptcache_read(&pid, (float)framenr) == PTCACHE_READ_EXACT) { + if (BKE_ptcache_read(&pid, (float)framenr) == PTCACHE_READ_EXACT) { BKE_ptcache_validate(cache, framenr); smd->time = framenr; return; } - + /* only calculate something when we advanced a single frame */ - if(framenr != (int)smd->time+1) + if (framenr != (int)smd->time + 1) return; /* don't simulate if viewing start frame, but scene frame is not real start frame */ @@ -1805,54 +2218,48 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM tstart(); - smoke_calc_domain(scene, ob, smd); - /* if on second frame, write cache for first frame */ - if((int)smd->time == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) { + if ((int)smd->time == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) { // create shadows straight after domain initialization so we get nice shadows for startframe, too - if(get_lamp(scene, light)) - smoke_calc_transparency(sds->shadow, smoke_get_density(sds->fluid), sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp, -7.0*sds->dx); + smoke_calc_transparency(sds, scene); - if(sds->wt) + if (sds->wt && sds->total_cells > 1) { - if(sds->flags & MOD_SMOKE_DISSOLVE) + if (sds->flags & MOD_SMOKE_DISSOLVE) smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); smoke_turbulence_step(sds->wt, sds->fluid); } BKE_ptcache_write(&pid, startframe); } - + // set new time smd->time = scene->r.cfra; /* do simulation */ - // low res - // simulate the actual smoke (c++ code in intern/smoke) // DG: interesting commenting this line + deactivating loading of noise files - if(framenr!=startframe) + if (framenr != startframe) { - if(sds->flags & MOD_SMOKE_DISSOLVE) + if (sds->flags & MOD_SMOKE_DISSOLVE) smoke_dissolve(sds->fluid, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); - - step(scene, ob, smd, scene->r.frs_sec / scene->r.frs_sec_base); + + step(scene, ob, smd, dm, scene->r.frs_sec / scene->r.frs_sec_base); } // create shadows before writing cache so they get stored - if(get_lamp(scene, light)) - smoke_calc_transparency(sds->shadow, smoke_get_density(sds->fluid), sds->p0, sds->p1, sds->res, sds->dx, light, calc_voxel_transp, -7.0*sds->dx); + smoke_calc_transparency(sds, scene); - if(sds->wt) + if (sds->wt) { - if(sds->flags & MOD_SMOKE_DISSOLVE) + if (sds->flags & MOD_SMOKE_DISSOLVE) smoke_dissolve_wavelet(sds->wt, sds->diss_speed, sds->flags & MOD_SMOKE_DISSOLVE_LOG); smoke_turbulence_step(sds->wt, sds->fluid); } - + BKE_ptcache_validate(cache, framenr); - if(framenr != startframe) + if (framenr != startframe) BKE_ptcache_write(&pid, framenr); tend(); @@ -1860,40 +2267,35 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM } } +struct DerivedMesh *smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm){ + smokeModifier_process(smd, scene, ob, dm); + + /* return generated geometry for adaptive domain */ + if (smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain && + smd->domain->flags & MOD_SMOKE_ADAPTIVE_DOMAIN && + smd->domain->base_res[0]) + { + return createDomainGeometry(smd->domain, ob); + } + else return CDDM_copy(dm); +} + static float calc_voxel_transp(float *result, float *input, int res[3], int *pixel, float *tRay, float correct) { const size_t index = smoke_get_index(pixel[0], res[0], pixel[1], res[1], pixel[2]); // T_ray *= T_vox - *tRay *= exp(input[index]*correct); - - if(result[index] < 0.0f) + *tRay *= exp(input[index] * correct); + + if (result[index] < 0.0f) { -// #pragma omp critical - result[index] = *tRay; - } +// #pragma omp critical + result[index] = *tRay; + } return *tRay; } -long long smoke_get_mem_req(int xres, int yres, int zres, int amplify) -{ - int totalCells = xres * yres * zres; - int amplifiedCells = totalCells * amplify * amplify * amplify; - - // print out memory requirements - long long int coarseSize = sizeof(float) * totalCells * 22 + - sizeof(unsigned char) * totalCells; - - long long int fineSize = sizeof(float) * amplifiedCells * 7 + // big grids - sizeof(float) * totalCells * 8 + // small grids - sizeof(float) * 128 * 128 * 128; // noise tile - - long long int totalMB = (coarseSize + fineSize) / (1024 * 1024); - - return totalMB; -} - static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, float *tRay, bresenham_callback cb, float *result, float *input, int res[3], float correct) { int dx, dy, dz, i, l, m, n, x_inc, y_inc, z_inc, err_1, err_2, dx2, dy2, dz2; @@ -1921,7 +2323,7 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f err_1 = dy2 - l; err_2 = dz2 - l; for (i = 0; i < l; i++) { - if(cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON) + if (cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON) break; if (err_1 > 0) { pixel[1] += y_inc; @@ -1935,12 +2337,12 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f err_2 += dz2; pixel[0] += x_inc; } - } + } else if ((m >= l) && (m >= n)) { err_1 = dx2 - m; err_2 = dz2 - m; for (i = 0; i < m; i++) { - if(cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON) + if (cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON) break; if (err_1 > 0) { pixel[0] += x_inc; @@ -1954,12 +2356,12 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f err_2 += dz2; pixel[1] += y_inc; } - } + } else { err_1 = dy2 - n; err_2 = dx2 - n; for (i = 0; i < n; i++) { - if(cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON) + if (cb(result, input, res, pixel, tRay, correct) <= FLT_EPSILON) break; if (err_1 > 0) { pixel[1] += y_inc; @@ -1977,80 +2379,142 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f cb(result, input, res, pixel, tRay, correct); } -static void get_cell(const float p0[3], const int res[3], float dx, const float pos[3], int cell[3], int correct) +static void smoke_calc_transparency(SmokeDomainSettings *sds, Scene *scene) { - float tmp[3]; + float bv[6] = {0}; + float light[3]; + int a, z, slabsize = sds->res[0] * sds->res[1], size = sds->res[0] * sds->res[1] * sds->res[2]; + float *density = smoke_get_density(sds->fluid); + float correct = -7.0 * sds->dx; - sub_v3_v3v3(tmp, pos, p0); - mul_v3_fl(tmp, 1.0 / dx); + if (!get_lamp(scene, light)) return; - if (correct) { - cell[0] = MIN2(res[0] - 1, MAX2(0, (int)floor(tmp[0]))); - cell[1] = MIN2(res[1] - 1, MAX2(0, (int)floor(tmp[1]))); - cell[2] = MIN2(res[2] - 1, MAX2(0, (int)floor(tmp[2]))); - } - else { - cell[0] = (int)floor(tmp[0]); - cell[1] = (int)floor(tmp[1]); - cell[2] = (int)floor(tmp[2]); - } -} + /* convert light pos to sim cell space */ + mul_m4_v3(sds->imat, light); + light[0] = (light[0] - sds->p0[0]) / sds->cell_size[0] - 0.5f - (float)sds->res_min[0]; + light[1] = (light[1] - sds->p0[1]) / sds->cell_size[1] - 0.5f - (float)sds->res_min[1]; + light[2] = (light[2] - sds->p0[2]) / sds->cell_size[2] - 0.5f - (float)sds->res_min[2]; -static void smoke_calc_transparency(float *result, float *input, float *p0, float *p1, int res[3], float dx, float *light, bresenham_callback cb, float correct) -{ - float bv[6]; - int a, z, slabsize=res[0]*res[1], size= res[0]*res[1]*res[2]; + for (a = 0; a < size; a++) + sds->shadow[a] = -1.0f; - for(a=0; ares[0]; // x + bv[3] = (float)sds->res[1]; // y + bv[5] = (float)sds->res[2]; // z // #pragma omp parallel for schedule(static,1) - for(z = 0; z < res[2]; z++) + for (z = 0; z < sds->res[2]; z++) { - size_t index = z*slabsize; - int x,y; + size_t index = z * slabsize; + int x, y; - for(y = 0; y < res[1]; y++) - for(x = 0; x < res[0]; x++, index++) + for (y = 0; y < sds->res[1]; y++) + for (x = 0; x < sds->res[0]; x++, index++) { float voxelCenter[3]; float pos[3]; int cell[3]; float tRay = 1.0; - if(result[index] >= 0.0f) - continue; - voxelCenter[0] = p0[0] + dx * x + dx * 0.5; - voxelCenter[1] = p0[1] + dx * y + dx * 0.5; - voxelCenter[2] = p0[2] + dx * z + dx * 0.5; + if (sds->shadow[index] >= 0.0f) + continue; + voxelCenter[0] = (float)x; + voxelCenter[1] = (float)y; + voxelCenter[2] = (float)z; - // get starting position (in voxel coords) - if(BLI_bvhtree_bb_raycast(bv, light, voxelCenter, pos) > FLT_EPSILON) + // get starting cell (light pos) + if (BLI_bvhtree_bb_raycast(bv, light, voxelCenter, pos) > FLT_EPSILON) { - // we're ouside - get_cell(p0, res, dx, pos, cell, 1); + // we're ouside -> use point on side of domain + cell[0] = (int)floor(pos[0]); + cell[1] = (int)floor(pos[1]); + cell[2] = (int)floor(pos[2]); } else { - // we're inside - get_cell(p0, res, dx, light, cell, 1); + // we're inside -> use light itself + cell[0] = (int)floor(light[0]); + cell[1] = (int)floor(light[1]); + cell[2] = (int)floor(light[2]); } + /* clamp within grid bounds */ + CLAMP(cell[0], 0, sds->res[0] - 1); + CLAMP(cell[1], 0, sds->res[1] - 1); + CLAMP(cell[2], 0, sds->res[2] - 1); - bresenham_linie_3D(cell[0], cell[1], cell[2], x, y, z, &tRay, cb, result, input, res, correct); + bresenham_linie_3D(cell[0], cell[1], cell[2], x, y, z, &tRay, calc_voxel_transp, sds->shadow, density, sds->res, correct); // convention -> from a RGBA float array, use G value for tRay // #pragma omp critical - result[index] = tRay; + sds->shadow[index] = tRay; } } } +/* get smoke velocity and density at given coordinates + * returns fluid density or -1.0f if outside domain*/ +float smoke_get_velocity_at(struct Object *ob, float position[3], float velocity[3]) +{ + SmokeModifierData *smd = (SmokeModifierData *)modifiers_findByType(ob, eModifierType_Smoke); + zero_v3(velocity); + + if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain && smd->domain->fluid) { + SmokeDomainSettings *sds = smd->domain; + float time_mult = 25.f * DT_DEFAULT; + float vel_mag; + float *velX = smoke_get_velocity_x(sds->fluid); + float *velY = smoke_get_velocity_y(sds->fluid); + float *velZ = smoke_get_velocity_z(sds->fluid); + float density = 0.0f, fuel = 0.0f; + float pos[3]; + copy_v3_v3(pos, position); + smoke_pos_to_cell(sds, pos); + + /* check if point is outside domain max bounds */ + if (pos[0] < sds->res_min[0] || pos[1] < sds->res_min[1] || pos[2] < sds->res_min[2]) return -1.0f; + if (pos[0] > sds->res_max[0] || pos[1] > sds->res_max[1] || pos[2] > sds->res_max[2]) return -1.0f; + + /* map pos between 0.0 - 1.0 */ + pos[0] = (pos[0] - sds->res_min[0]) / ((float)sds->res[0]); + pos[1] = (pos[1] - sds->res_min[1]) / ((float)sds->res[1]); + pos[2] = (pos[2] - sds->res_min[2]) / ((float)sds->res[2]); + + + /* check if point is outside active area */ + if (smd->domain->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) { + if (pos[0] < 0.0f || pos[1] < 0.0f || pos[2] < 0.0f) return 0.0f; + if (pos[0] > 1.0f || pos[1] > 1.0f || pos[2] > 1.0f) return 0.0f; + } + + /* get interpolated velocity */ + velocity[0] = BLI_voxel_sample_trilinear(velX, sds->res, pos) * sds->global_size[0] * time_mult; + velocity[1] = BLI_voxel_sample_trilinear(velY, sds->res, pos) * sds->global_size[1] * time_mult; + velocity[2] = BLI_voxel_sample_trilinear(velZ, sds->res, pos) * sds->global_size[2] * time_mult; + + /* convert velocity direction to global space */ + vel_mag = len_v3(velocity); + mul_mat3_m4_v3(sds->obmat, velocity); + normalize_v3(velocity); + mul_v3_fl(velocity, vel_mag); + + /* use max value of fuel or smoke density */ + density = BLI_voxel_sample_trilinear(smoke_get_density(sds->fluid), sds->res, pos); + if (smoke_has_fuel(sds->fluid)) { + fuel = BLI_voxel_sample_trilinear(smoke_get_fuel(sds->fluid), sds->res, pos); + } + return MAX2(density, fuel); + } + return -1.0f; +} + +int smoke_get_data_flags(SmokeDomainSettings *sds) { + int flags = 0; + if (smoke_has_heat(sds->fluid)) flags |= SM_ACTIVE_HEAT; + if (smoke_has_fuel(sds->fluid)) flags |= SM_ACTIVE_FIRE; + if (smoke_has_colors(sds->fluid)) flags |= SM_ACTIVE_COLORS; + + return flags; +} + #endif /* WITH_SMOKE */ diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 4a88bfbfdad..bb0cfe1a5c6 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -143,13 +143,15 @@ typedef struct SB_thread_context { } SB_thread_context; #define NLF_BUILD 1 -#define NLF_SOLVE 2 +#if 0 +# define NLF_SOLVE 2 +#endif #define MID_PRESERVE 1 #define SOFTGOALSNAP 0.999f /* if bp-> goal is above make it a *forced follow original* and skip all ODE stuff for this bp - * removes *unnecessary* stiffnes from ODE system + * removes *unnecessary* stiffness from ODE system */ #define HEUNWARNLIMIT 1 /* 500 would be fine i think for detecting severe *stiff* stuff */ @@ -1168,7 +1170,7 @@ static int sb_detect_face_pointCached(float face_v1[3], float face_v2[3], float *damp=df*tune*ob->pd->pdef_sbdamp; - df = 0.01f*exp(- 100.0f*df); + df = 0.01f * expf(-100.0f * df); Vec3PlusStVec(force, -df, d_nvect); deflected = 3; } @@ -1596,7 +1598,7 @@ static void _scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow, /*see if we have wind*/ if (do_effector) { EffectedPoint epoint; - float speed[3]={0.0f, 0.0f, 0.0f}; + float speed[3] = {0.0f, 0.0f, 0.0f}; float pos[3]; mid_v3_v3v3(pos, sb->bpoint[bs->v1].pos, sb->bpoint[bs->v2].pos); mid_v3_v3v3(vel, sb->bpoint[bs->v1].vec, sb->bpoint[bs->v2].vec); @@ -1747,8 +1749,8 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3], Object *ob= NULL; GHash *hash; GHashIterator *ihash; - float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3], d_nvect[3], dv1[3], ve[3], avel[3]={0.0, 0.0, 0.0}, - vv1[3], vv2[3], vv3[3], vv4[3], coledge[3]={0.0f, 0.0f, 0.0f}, mindistedge = 1000.0f, + float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3], d_nvect[3], dv1[3], ve[3], avel[3] = {0.0, 0.0, 0.0}, + vv1[3], vv2[3], vv3[3], vv4[3], coledge[3] = {0.0f, 0.0f, 0.0f}, mindistedge = 1000.0f, outerforceaccu[3], innerforceaccu[3], facedist, /* n_mag, */ /* UNUSED */ force_mag_norm, minx, miny, minz, maxx, maxy, maxz, innerfacethickness = -0.5f, outerfacethickness = 0.2f, @@ -2207,7 +2209,7 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, flo bp = &sb->bpoint[ifirst]; for (bb=number_of_points_here; bb>0; bb--, bp++) { /* clear forces accumulator */ - bp->force[0]= bp->force[1]= bp->force[2]= 0.0; + bp->force[0] = bp->force[1] = bp->force[2] = 0.0; /* naive ball self collision */ /* needs to be done if goal snaps or not */ if (do_selfcollision) { @@ -2302,8 +2304,8 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, flo if (do_effector) { EffectedPoint epoint; float kd; - float force[3]= {0.0f, 0.0f, 0.0f}; - float speed[3]= {0.0f, 0.0f, 0.0f}; + float force[3] = {0.0f, 0.0f, 0.0f}; + float speed[3] = {0.0f, 0.0f, 0.0f}; float eval_sb_fric_force_scale = sb_fric_force_scale(ob); /* just for calling function once */ pd_point_from_soft(scene, bp->pos, bp->vec, sb->bpoint-bp, &epoint); pdDoEffectors(do_effector, NULL, sb->effector_weights, &epoint, force, speed); @@ -2555,7 +2557,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa for (a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) { /* clear forces accumulator */ - bp->force[0]= bp->force[1]= bp->force[2]= 0.0; + bp->force[0] = bp->force[1] = bp->force[2] = 0.0; if (nl_flags & NLF_BUILD) { //int ia =3*(sb->totpoint-a); //int op =3*sb->totpoint; @@ -2710,8 +2712,8 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa /* particle field & vortex */ if (do_effector) { EffectedPoint epoint; - float force[3]= {0.0f, 0.0f, 0.0f}; - float speed[3]= {0.0f, 0.0f, 0.0f}; + float force[3] = {0.0f, 0.0f, 0.0f}; + float speed[3] = {0.0f, 0.0f, 0.0f}; float eval_sb_fric_force_scale = sb_fric_force_scale(ob); /* just for calling function once */ pd_point_from_soft(scene, bp->pos, bp->vec, sb->bpoint-bp, &epoint); pdDoEffectors(do_effector, NULL, sb->effector_weights, &epoint, force, speed); @@ -2903,7 +2905,7 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float * /* or heun ~ 2nd order runge-kutta steps, mode 1, 2 */ SoftBody *sb= ob->soft; /* is supposed to be there */ BodyPoint *bp; - float dx[3]={0}, dv[3], aabbmin[3], aabbmax[3], cm[3]={0.0f, 0.0f, 0.0f}; + float dx[3] = {0}, dv[3], aabbmin[3], aabbmax[3], cm[3] = {0.0f, 0.0f, 0.0f}; float timeovermass/*, freezeloc=0.00001f, freezeforce=0.00000000001f*/; float maxerrpos= 0.0f, maxerrvel = 0.0f; int a, fuzzy=0; @@ -3192,7 +3194,7 @@ static void interpolate_exciter(Object *ob, int timescale, int time) - xxxx_to_softbody(Object *ob) : a full (new) copy, creates SB geometry */ -static void get_scalar_from_vertexgroup(Object *ob, int vertID, short groupindex, float *target) +static void get_scalar_from_vertexgroup(Object *ob, int vertID, int groupindex, float *target) /* result 0 on success, else indicates error number -- kind of *inverse* result defintion, -- but this way we can signal error condition to caller @@ -3295,7 +3297,7 @@ static void mesh_to_softbody(Scene *scene, Object *ob) if ((ob->softflag & OB_SB_GOAL) && sb->vertgroup) { /* even this is a deprecated evil hack */ /* I'd like to have it .. if (sb->namedVG_Goal[0]) */ - get_scalar_from_vertexgroup(ob, a, (short) (sb->vertgroup-1), &bp->goal); + get_scalar_from_vertexgroup(ob, a, sb->vertgroup - 1, &bp->goal); /* do this always, regardless successful read from vertex group */ /* this is where '2.5 every thing is animatable' goes wrong in the first place jow_go_for2_5 */ /* 1st coding action to take : move this to frame level */ @@ -3314,10 +3316,10 @@ static void mesh_to_softbody(Scene *scene, Object *ob) */ if (sb->namedVG_Mass[0]) { - int grp= defgroup_name_index (ob, sb->namedVG_Mass); - /* printf("VGN %s %d\n", sb->namedVG_Mass, grp); */ - if (grp > -1) { - get_scalar_from_vertexgroup(ob, a, (short) (grp), &bp->mass); + int defgrp_index = defgroup_name_index (ob, sb->namedVG_Mass); + /* printf("VGN %s %d\n", sb->namedVG_Mass, defgrp_index); */ + if (defgrp_index != -1) { + get_scalar_from_vertexgroup(ob, a, defgrp_index, &bp->mass); /* 2.5 bp->mass = bp->mass * sb->nodemass; */ /* printf("bp->mass %f\n", bp->mass); */ @@ -3327,10 +3329,10 @@ static void mesh_to_softbody(Scene *scene, Object *ob) bp->springweight = 1.0f; if (sb->namedVG_Spring_K[0]) { - int grp= defgroup_name_index (ob, sb->namedVG_Spring_K); - //printf("VGN %s %d\n", sb->namedVG_Spring_K, grp); - if (grp > -1) { - get_scalar_from_vertexgroup(ob, a, (short) (grp), &bp->springweight); + int defgrp_index = defgroup_name_index (ob, sb->namedVG_Spring_K); + //printf("VGN %s %d\n", sb->namedVG_Spring_K, defgrp_index); + if (defgrp_index != -1) { + get_scalar_from_vertexgroup(ob, a, defgrp_index , &bp->springweight); //printf("bp->springweight %f\n", bp->springweight); } @@ -3863,7 +3865,7 @@ static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int copy_v3_v3(bp->origS, bp->pos); copy_v3_v3(bp->origE, bp->pos); copy_v3_v3(bp->origT, bp->pos); - bp->vec[0]= bp->vec[1]= bp->vec[2]= 0.0f; + bp->vec[0] = bp->vec[1] = bp->vec[2] = 0.0f; /* the bp->prev*'s are for rolling back from a canceled try to propagate in time * adaptive step size algo in a nutshell: @@ -3923,7 +3925,7 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime) sst=PIL_check_seconds_timer(); /* Integration back in time is possible in theory, but pretty useless here. - * So we refuse to do so. Since we do not know anything about 'outside' canges + * So we refuse to do so. Since we do not know anything about 'outside' changes * especially colliders we refuse to go more than 10 frames. */ if (dtime < 0 || dtime > 10.5f) return; @@ -4006,8 +4008,8 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime) } loops++; if (sb->solverflags & SBSO_MONITOR ) { - sct=PIL_check_seconds_timer(); - if (sct-sst > 0.5f) printf("%3.0f%% \r", 100.0f*timedone/dtime); + sct = PIL_check_seconds_timer(); + if (sct - sst > 0.5) printf("%3.0f%% \r", 100.0f * timedone / dtime); } /* ask for user break */ if (SB_localInterruptCallBack && SB_localInterruptCallBack()) break; @@ -4043,7 +4045,7 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime) if (sb->solverflags & SBSO_MONITOR ) { sct=PIL_check_seconds_timer(); - if ((sct-sst > 0.5f) || (G.debug & G_DEBUG)) printf(" solver time %f sec %s\n", sct-sst, ob->id.name); + if ((sct - sst > 0.5) || (G.debug & G_DEBUG)) printf(" solver time %f sec %s\n", sct-sst, ob->id.name); } } diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index f340bcb5b1e..aad205bb5bf 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -701,7 +701,7 @@ void sound_update_scene(struct Scene *scene) if (AUD_removeSet(scene->speaker_handles, strip->speaker_handle)) { if (speaker->sound) - AUD_moveSequence(strip->speaker_handle, strip->start / FPS, -1, 0); + AUD_moveSequence(strip->speaker_handle, (double)strip->start / FPS, -1, 0); else { AUD_removeSequence(scene->sound_scene, strip->speaker_handle); strip->speaker_handle = NULL; @@ -709,7 +709,9 @@ void sound_update_scene(struct Scene *scene) } else { if (speaker->sound) { - strip->speaker_handle = AUD_addSequence(scene->sound_scene, speaker->sound->playback_handle, strip->start / FPS, -1, 0); + strip->speaker_handle = AUD_addSequence(scene->sound_scene, + speaker->sound->playback_handle, + (double)strip->start / FPS, -1, 0); AUD_setRelativeSequence(strip->speaker_handle, 0); } } @@ -792,7 +794,6 @@ void sound_stop_scene(struct Scene *UNUSED(scene)) {} void sound_seek_scene(struct Main *UNUSED(bmain), struct Scene *UNUSED(scene)) {} float sound_sync_scene(struct Scene *UNUSED(scene)) { return NAN_FLT; } int sound_scene_playing(struct Scene *UNUSED(scene)) { return -1; } -int sound_read_sound_buffer(struct bSound *UNUSED(sound), float *UNUSED(buffer), int UNUSED(length), float UNUSED(start), float UNUSED(end)) { return 0; } void sound_read_waveform(struct bSound *sound) { (void)sound; } void sound_init_main(struct Main *bmain) { (void)bmain; } void sound_set_cfra(int cfra) { (void)cfra; } diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 555ed5890c8..8a669b89907 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -513,10 +513,14 @@ static float *get_ss_weights(WeightTable *wtable, int gridCuts, int faceLen) w2 = (1.0f - fx + fac2 * fx * -fac) * (fy); w4 = (fx) * (1.0f - fy + -fac2 * fy * fac); - fac2 = 1.0f - (w1 + w2 + w4); - fac2 = fac2 / (float)(faceLen - 3); - for (j = 0; j < faceLen; j++) - w[j] = fac2; + /* these values aren't used for tri's and cause divide by zero */ + if (faceLen > 3) { + fac2 = 1.0f - (w1 + w2 + w4); + fac2 = fac2 / (float)(faceLen - 3); + for (j = 0; j < faceLen; j++) { + w[j] = fac2; + } + } w[i] = w1; w[(i - 1 + faceLen) % faceLen] = w2; @@ -598,7 +602,7 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm, } mp = mpoly; - index = DM_get_poly_data_layer(dm, CD_ORIGINDEX); + index = (int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); for (i = 0; i < dm->numPolyData; i++, mp++) { CCGFace *f; @@ -2702,11 +2706,7 @@ static void *ccgDM_get_tessface_data_layer(DerivedMesh *dm, int type) { if (type == CD_ORIGINDEX) { /* create origindex on demand to save memory */ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; - CCGSubSurf *ss = ccgdm->ss; int *origindex; - int a, i, index, totface; - int gridFaces = ccgSubSurf_getGridSize(ss) - 1; /* Avoid re-creation if the layer exists already */ origindex = DM_get_tessface_data_layer(dm, CD_ORIGINDEX); @@ -2717,6 +2717,34 @@ static void *ccgDM_get_tessface_data_layer(DerivedMesh *dm, int type) DM_add_tessface_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); origindex = DM_get_tessface_data_layer(dm, CD_ORIGINDEX); + /* silly loop counting up */ + range_vn_i(origindex, dm->getNumTessFaces(dm), 0); + + return origindex; + } + + return DM_get_tessface_data_layer(dm, type); +} + +static void *ccgDM_get_poly_data_layer(DerivedMesh *dm, int type) +{ + if (type == CD_ORIGINDEX) { + /* create origindex on demand to save memory */ + CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; + CCGSubSurf *ss = ccgdm->ss; + int *origindex; + int a, i, index, totface; + int gridFaces = ccgSubSurf_getGridSize(ss) - 1; + + /* Avoid re-creation if the layer exists already */ + origindex = DM_get_poly_data_layer(dm, CD_ORIGINDEX); + if (origindex) { + return origindex; + } + + DM_add_poly_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); + origindex = DM_get_poly_data_layer(dm, CD_ORIGINDEX); + totface = ccgSubSurf_getNumFaces(ss); for (a = 0, index = 0; index < totface; index++) { @@ -2731,7 +2759,7 @@ static void *ccgDM_get_tessface_data_layer(DerivedMesh *dm, int type) return origindex; } - return DM_get_tessface_data_layer(dm, type); + return DM_get_poly_data_layer(dm, type); } static void *ccgDM_get_vert_data(DerivedMesh *dm, int index, int type) @@ -2764,6 +2792,16 @@ static void *ccgDM_get_tessface_data(DerivedMesh *dm, int index, int type) return DM_get_tessface_data(dm, index, type); } +static void *ccgDM_get_poly_data(DerivedMesh *dm, int index, int type) +{ + if (type == CD_ORIGINDEX) { + /* ensure creation of CD_ORIGINDEX layer */ + ccgDM_get_tessface_data_layer(dm, type); + } + + return DM_get_poly_data(dm, index, type); +} + static int ccgDM_getNumGrids(DerivedMesh *dm) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; @@ -3016,6 +3054,9 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) me->totface, me->totvert, &me->vdata); } + if (ccgdm->pbvh) + pbvh_show_diffuse_color_set(ccgdm->pbvh, ob->sculpt->show_diffuse_color); + return ccgdm->pbvh; } @@ -3091,7 +3132,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, } /* We absolutely need that layer, else it's no valid tessellated data! */ - polyidx = CustomData_add_layer(&ccgdm->dm.faceData, CD_POLYINDEX, CD_CALLOC, + polyidx = CustomData_add_layer(&ccgdm->dm.faceData, CD_ORIGINDEX, CD_CALLOC, NULL, ccgSubSurf_getNumFinalFaces(ss)); ccgdm->dm.getMinMax = ccgDM_getMinMax; @@ -3119,9 +3160,11 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, ccgdm->dm.getVertData = ccgDM_get_vert_data; ccgdm->dm.getEdgeData = ccgDM_get_edge_data; ccgdm->dm.getTessFaceData = ccgDM_get_tessface_data; + ccgdm->dm.getPolyData = ccgDM_get_poly_data; ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer; ccgdm->dm.getEdgeDataArray = ccgDM_get_edge_data_layer; ccgdm->dm.getTessFaceDataArray = ccgDM_get_tessface_data_layer; + ccgdm->dm.getPolyDataArray = ccgDM_get_poly_data_layer; ccgdm->dm.getNumGrids = ccgDM_getNumGrids; ccgdm->dm.getGridSize = ccgDM_getGridSize; ccgdm->dm.getGridData = ccgDM_getGridData; @@ -3220,8 +3263,8 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, vertOrigIndex = DM_get_vert_data_layer(&ccgdm->dm, CD_ORIGINDEX); /*edgeOrigIndex = DM_get_edge_data_layer(&ccgdm->dm, CD_ORIGINDEX);*/ - faceOrigIndex = DM_get_tessface_data_layer(&ccgdm->dm, CD_ORIGINDEX); + faceOrigIndex = DM_get_tessface_data_layer(&ccgdm->dm, CD_ORIGINDEX); polyOrigIndex = DM_get_poly_data_layer(&ccgdm->dm, CD_ORIGINDEX); #if 0 @@ -3359,7 +3402,8 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, /*set original index data*/ if (faceOrigIndex) { - *faceOrigIndex = origIndex; + /* reference the index in 'polyOrigIndex' */ + *faceOrigIndex = faceNum; faceOrigIndex++; } if (polyOrigIndex) { diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 3c89fdba13a..b3497b9932f 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -48,18 +48,22 @@ #include "DNA_constraint_types.h" #include "DNA_controller_types.h" +#include "DNA_actuator_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_text_types.h" #include "DNA_userdef_types.h" #include "DNA_object_types.h" +#include "DNA_node_types.h" +#include "DNA_material_types.h" #include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_text.h" +#include "BKE_node.h" #ifdef WITH_PYTHON @@ -313,7 +317,7 @@ int BKE_text_reload(Text *text) fseek(fp, 0L, SEEK_END); len = ftell(fp); - fseek(fp, 0L, SEEK_SET); + fseek(fp, 0L, SEEK_SET); text->undo_pos = -1; @@ -369,7 +373,7 @@ int BKE_text_reload(Text *text) text->curl = text->sell = text->lines.first; text->curc = text->selc = 0; - MEM_freeN(buffer); + MEM_freeN(buffer); return 1; } @@ -403,7 +407,7 @@ Text *BKE_text_load(const char *file, const char *relpath) fseek(fp, 0L, SEEK_END); len = ftell(fp); - fseek(fp, 0L, SEEK_SET); + fseek(fp, 0L, SEEK_SET); ta->name = MEM_mallocN(strlen(file) + 1, "text_name"); strcpy(ta->name, file); @@ -468,7 +472,7 @@ Text *BKE_text_load(const char *file, const char *relpath) ta->curl = ta->sell = ta->lines.first; ta->curc = ta->selc = 0; - MEM_freeN(buffer); + MEM_freeN(buffer); return ta; } @@ -528,7 +532,11 @@ void BKE_text_unlink(Main *bmain, Text *text) SpaceLink *sl; Object *ob; bController *cont; + bActuator *act; bConstraint *con; + bNodeTree *ntree; + bNode *node; + Material *mat; short update; for (ob = bmain->object.first; ob; ob = ob->id.next) { @@ -541,6 +549,15 @@ void BKE_text_unlink(Main *bmain, Text *text) if (pc->text == text) pc->text = NULL; } } + /* game actuators */ + for (act = ob->actuators.first; act; act = act->next) { + if (act->type == ACT_2DFILTER) { + bTwoDFilterActuator *tfa; + + tfa = act->data; + if (tfa->text == text) tfa->text = NULL; + } + } /* pyconstraints */ update = 0; @@ -571,6 +588,28 @@ void BKE_text_unlink(Main *bmain, Text *text) DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } + /* nodes */ + for (mat = bmain->mat.first; mat; mat = mat->id.next) { + ntree = mat->nodetree; + if (!ntree) + continue; + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_SCRIPT) { + Text *ntext = (Text *)node->id; + if (ntext == text) node->id = NULL; + } + } + } + + for (ntree = bmain->nodetree.first; ntree; ntree = ntree->id.next) { + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_SCRIPT) { + Text *ntext = (Text *)node->id; + if (ntext == text) node->id = NULL; + } + } + } + /* text space */ for (scr = bmain->screen.first; scr; scr = scr->id.next) { for (area = scr->areabase.first; area; area = area->next) { @@ -672,7 +711,7 @@ void txt_clean_text(Text *text) if (!text->lines.first) { if (text->lines.last) text->lines.first = text->lines.last; else text->lines.first = text->lines.last = txt_new_line(NULL); - } + } if (!text->lines.last) text->lines.last = text->lines.first; @@ -721,7 +760,7 @@ int txt_get_span(TextLine *from, TextLine *to) if (!tmp) ret = 0; } - return ret; + return ret; } static void txt_make_dirty(Text *text) @@ -923,7 +962,7 @@ void txt_move_right(Text *text, short sel) txt_move_down(text, sel); *charp = 0; } - } + } else { // do nice right only if there are only spaces // spaces hardcoded in DNA_text_types.h @@ -1365,7 +1404,7 @@ int txt_find_string(Text *text, const char *findstr, int wrap, int match_case) int newc = (int)(s - tl->line); txt_move_to(text, newl, newc, 0); txt_move_to(text, newl, newc + strlen(findstr), 1); - return 1; + return 1; } else return 0; @@ -1447,7 +1486,7 @@ char *txt_sel_to_buf(Text *text) length += charl; buf[length] = 0; - } + } return buf; } @@ -1919,6 +1958,7 @@ static unsigned int txt_undo_read_unicode(const char *undo_buf, int *undo_pos, s break; case 4: /* 32-bit unicode symbol */ unicode = txt_undo_read_uint32(undo_buf, undo_pos); + break; default: /* should never happen */ BLI_assert(0); @@ -1970,6 +2010,7 @@ static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, s break; case 4: /* 32-bit unicode symbol */ unicode = txt_undo_read_uint32(undo_buf, undo_pos); + break; default: /* should never happen */ BLI_assert(0); @@ -2065,7 +2106,7 @@ void txt_do_undo(Text *text) charp = op - UNDO_BS_1 + 1; txt_add_char(text, txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp)); text->undo_pos--; - break; + break; case UNDO_DEL_1: case UNDO_DEL_2: case UNDO_DEL_3: case UNDO_DEL_4: charp = op - UNDO_DEL_1 + 1; @@ -2091,7 +2132,7 @@ void txt_do_undo(Text *text) txt_curs_first(text, &holdl, &holdc); holdln = txt_get_span(text->lines.first, holdl); - txt_insert_buf(text, buf); + txt_insert_buf(text, buf); MEM_freeN(buf); text->curl = text->lines.first; @@ -2222,7 +2263,7 @@ void txt_do_redo(Text *text) unsigned short charp; char *buf; - text->undo_pos++; + text->undo_pos++; op = text->undo_buf[text->undo_pos]; if (!op) { @@ -2338,7 +2379,7 @@ void txt_do_redo(Text *text) text->undo_pos += linep; buf[linep] = 0; - txt_insert_buf(text, buf); + txt_insert_buf(text, buf); MEM_freeN(buf); text->undo_pos++; @@ -2356,7 +2397,7 @@ void txt_do_redo(Text *text) //charp is the first char selected or 0 linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); - //linep is now the first line of the selection + //linep is now the first line of the selection //set the selcetion for this now text->curc = charp; text->curl = text->lines.first; @@ -2463,7 +2504,7 @@ void txt_split_curline(Text *text) text->curl->format = NULL; text->curl->len = text->curl->len - text->curc; - BLI_insertlinkbefore(&text->lines, text->curl, ins); + BLI_insertlinkbefore(&text->lines, text->curl, ins); text->curc = 0; diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index bdd9b424f3b..6d0313f6334 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -571,7 +571,7 @@ void default_mtex(MTex *mtex) mtex->size[1] = 1.0; mtex->size[2] = 1.0; mtex->tex = NULL; - mtex->texflag = MTEX_3TAP_BUMP | MTEX_BUMP_OBJECTSPACE; + mtex->texflag = MTEX_3TAP_BUMP | MTEX_BUMP_OBJECTSPACE | MTEX_MAPTO_BOUNDS; mtex->colormodel = 0; mtex->r = 1.0; mtex->g = 0.0; @@ -646,7 +646,7 @@ MTex *add_mtex_id(ID *id, int slot) if (slot == -1) { /* find first free */ - int i; + int i; for (i = 0; i < MAX_MTEX; i++) { if (!mtex_ar[i]) { slot = i; @@ -909,8 +909,7 @@ void autotexname(Tex *tex) if (tex->use_nodes) { new_id(&bmain->tex, (ID *)tex, "Noddy"); } - else - if (tex->type == TEX_IMAGE) { + else if (tex->type == TEX_IMAGE) { ima = tex->ima; if (ima) { BLI_strncpy(di, ima->name, sizeof(di)); @@ -1073,19 +1072,21 @@ void set_current_material_texture(Material *ma, Tex *newtex) { Tex *tex = NULL; bNode *node; - - if (ma && ma->use_nodes && ma->nodetree) { - node = nodeGetActiveID(ma->nodetree, ID_TE); - if (node) { - tex = (Tex *)node->id; - id_us_min(&tex->id); + if ((ma->use_nodes && ma->nodetree) && + (node = nodeGetActiveID(ma->nodetree, ID_TE))) + { + tex = (Tex *)node->id; + id_us_min(&tex->id); + if (newtex) { node->id = &newtex->id; id_us_plus(&newtex->id); - ma = NULL; + } + else { + node->id = NULL; } } - if (ma) { + else { int act = (int)ma->texact; tex = (ma->mtex[act]) ? ma->mtex[act]->tex : NULL; diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 97ebc3a90ba..89446a1856f 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -51,6 +51,8 @@ #include "BLI_string.h" #include "BLI_threads.h" +#include "BLF_translation.h" + #include "BKE_global.h" #include "BKE_tracking.h" #include "BKE_movieclip.h" @@ -169,10 +171,9 @@ void BKE_tracking_settings_init(MovieTracking *tracking) tracking->settings.default_minimum_correlation = 0.75; tracking->settings.default_pattern_size = 11; tracking->settings.default_search_size = 61; - tracking->settings.keyframe1 = 1; - tracking->settings.keyframe2 = 30; tracking->settings.dist = 1; tracking->settings.object_distance = 1; + tracking->settings.reconstruction_success_threshold = 1e-3; tracking->stabilization.scaleinf = 1.0f; tracking->stabilization.locinf = 1.0f; @@ -223,7 +224,7 @@ void BKE_tracking_get_projection_matrix(MovieTracking *tracking, MovieTrackingOb float viewfac, pixsize, left, right, bottom, top, clipsta, clipend; float winmat[4][4]; float ycor = 1.0f / tracking->camera.pixel_aspect; - float shiftx, shifty, winside = MAX2(winx, winy); + float shiftx, shifty, winside = (float)min_ii(winx, winy); BKE_tracking_camera_shift_get(tracking, winx, winy, &shiftx, &shifty); @@ -335,7 +336,7 @@ static void search_pixel_to_marker_unified(int frame_width, int frame_height, } /* Each marker has 5 coordinates associated with it that get warped with - * tracking: the four corners ("pattern_corners"), and the cernter ("pos"). + * tracking: the four corners ("pattern_corners"), and the center ("pos"). * This function puts those 5 points into the appropriate frame for tracking * (the "search" coordinate frame). */ @@ -455,7 +456,7 @@ void BKE_tracking_clipboard_paste_tracks(MovieTracking *tracking, MovieTrackingO /*********************** Tracks *************************/ -static void tracking_marker_insert_disabled(MovieTrackingTrack *track, MovieTrackingMarker *ref_marker, +static void tracking_marker_insert_disabled(MovieTrackingTrack *track, const MovieTrackingMarker *ref_marker, int before, int overwrite) { MovieTrackingMarker marker_new; @@ -633,7 +634,7 @@ void BKE_tracking_track_path_clear(MovieTrackingTrack *track, int ref_frame, int } } -void BKE_tracking_tracks_join(MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track) +void BKE_tracking_tracks_join(MovieTracking *tracking, MovieTrackingTrack *dst_track, MovieTrackingTrack *src_track) { int i = 0, a = 0, b = 0, tot; MovieTrackingMarker *markers; @@ -736,6 +737,8 @@ void BKE_tracking_tracks_join(MovieTrackingTrack *dst_track, MovieTrackingTrack dst_track->markersnr = i; MEM_freeN(markers); + + BKE_tracking_dopesheet_tag_update(tracking); } MovieTrackingTrack *BKE_tracking_track_get_named(MovieTracking *tracking, MovieTrackingObject *object, const char *name) @@ -856,7 +859,7 @@ static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height } /* TODO: add an option to control whether AA is enabled or not */ - PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, mask_width, mask_height, FALSE); + PLX_raskterize((float (*)[2])mask_points, stroke->totpoints, mask, mask_width, mask_height); MEM_freeN(mask_points); } @@ -997,8 +1000,8 @@ void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event) if (event == CLAMP_PAT_DIM) { for (a = 0; a < 2; a++) { /* search shouldn't be resized smaller than pattern */ - marker->search_min[a] = minf(pat_min[a], marker->search_min[a]); - marker->search_max[a] = maxf(pat_max[a], marker->search_max[a]); + marker->search_min[a] = min_ff(pat_min[a], marker->search_min[a]); + marker->search_max[a] = max_ff(pat_max[a], marker->search_max[a]); } } else if (event == CLAMP_PAT_POS) { @@ -1022,8 +1025,8 @@ void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event) else if (event == CLAMP_SEARCH_DIM) { for (a = 0; a < 2; a++) { /* search shouldn't be resized smaller than pattern */ - marker->search_min[a] = minf(pat_min[a], marker->search_min[a]); - marker->search_max[a] = maxf(pat_max[a], marker->search_max[a]); + marker->search_min[a] = min_ff(pat_min[a], marker->search_min[a]); + marker->search_max[a] = max_ff(pat_max[a], marker->search_max[a]); } } else if (event == CLAMP_SEARCH_POS) { @@ -1043,14 +1046,6 @@ void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event) } } } - else if (event == CLAMP_SEARCH_DIM) { - float dim[2]; - sub_v2_v2v2(dim, pat_max, pat_min); - for (a = 0; a < 2; a++) { - marker->search_min[a] = pat_min[a]; - marker->search_max[a] = pat_max[a]; - } - } } MovieTrackingMarker *BKE_tracking_marker_get(MovieTrackingTrack *track, int framenr) @@ -1187,23 +1182,25 @@ MovieTrackingObject *BKE_tracking_object_add(MovieTracking *tracking, const char tracking->objectnr = BLI_countlist(&tracking->objects) - 1; object->scale = 1.0f; + object->keyframe1 = 1; + object->keyframe2 = 30; BKE_tracking_object_unique_name(tracking, object); return object; } -void BKE_tracking_object_delete(MovieTracking *tracking, MovieTrackingObject *object) +int BKE_tracking_object_delete(MovieTracking *tracking, MovieTrackingObject *object) { MovieTrackingTrack *track; int index = BLI_findindex(&tracking->objects, object); - if (index < 0) - return; + if (index == -1) + return FALSE; if (object->flag & TRACKING_OBJECT_CAMERA) { /* object used for camera solving can't be deleted */ - return; + return FALSE; } track = object->tracks.first; @@ -1219,10 +1216,11 @@ void BKE_tracking_object_delete(MovieTracking *tracking, MovieTrackingObject *ob tracking->tot_object--; - if (index > 0) + if (index != 0) tracking->objectnr = index - 1; else tracking->objectnr = 0; + return TRUE; } void BKE_tracking_object_unique_name(MovieTracking *tracking, MovieTrackingObject *object) @@ -1502,7 +1500,8 @@ ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking * ibuf->x, ibuf->y, overscan, ibuf->channels); } - resibuf->userflags |= IB_RECT_INVALID; + if (ibuf->rect) + imb_freerectImBuf(ibuf); } else { if (undistort) { @@ -1520,9 +1519,8 @@ ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking * (void) overscan; (void) undistort; - if (ibuf->rect_float) { - resibuf->userflags |= IB_RECT_INVALID; - } + if (ibuf->rect_float && ibuf->rect) + imb_freerectImBuf(ibuf); #endif return resibuf; @@ -2029,7 +2027,7 @@ static void track_context_free(void *customdata) { TrackContext *track_context = (TrackContext *)customdata; -#if WITH_LIBMV +#ifdef WITH_LIBMV if (track_context->search_area) MEM_freeN(track_context->search_area); @@ -2144,7 +2142,7 @@ void BKE_tracking_context_sync(MovieTrackingContext *context) context->sync_frame = newframe; - tracking->dopesheet.ok = FALSE; + BKE_tracking_dopesheet_tag_update(tracking); } void BKE_tracking_context_sync_user(const MovieTrackingContext *context, MovieClipUser *user) @@ -2289,9 +2287,9 @@ static ImBuf *tracking_context_get_reference_ibuf(MovieTrackingContext *context, return ibuf; } -static void track_context_update_reference(MovieTrackingContext *context, TrackContext *track_context, - MovieTrackingTrack *track, MovieTrackingMarker *marker, int curfra, - int frame_width, int frame_height) +static int track_context_update_reference(MovieTrackingContext *context, TrackContext *track_context, + MovieTrackingTrack *track, MovieTrackingMarker *marker, int curfra, + int frame_width, int frame_height) { MovieTrackingMarker *marker_keyed = NULL; ImBuf *reference_ibuf = NULL; @@ -2299,6 +2297,10 @@ static void track_context_update_reference(MovieTrackingContext *context, TrackC /* calculate patch for keyframed position */ reference_ibuf = tracking_context_get_reference_ibuf(context, track, marker, curfra, &marker_keyed); + + if (!reference_ibuf) + return FALSE; + track_context->marker = *marker_keyed; if (track_context->search_area) { @@ -2317,6 +2319,8 @@ static void track_context_update_reference(MovieTrackingContext *context, TrackC } IMB_freeImBuf(reference_ibuf); + + return TRUE; } static void tracking_configure_tracker(TrackContext *track_context, MovieTrackingTrack *track, @@ -2345,10 +2349,10 @@ static int tracking_check_marker_margin(MovieTrackingTrack *track, MovieTracking /* margin from frame boundaries */ BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); sub_v2_v2v2(dim, pat_max, pat_min); - margin[0] = margin[1] = maxf(dim[0], dim[1]) / 2.0f; + margin[0] = margin[1] = max_ff(dim[0], dim[1]) / 2.0f; - margin[0] = maxf(margin[0], (float)track->margin / frame_width); - margin[1] = maxf(margin[1], (float)track->margin / frame_height); + margin[0] = max_ff(margin[0], (float)track->margin / frame_width); + margin[1] = max_ff(margin[1], (float)track->margin / frame_height); /* do not track markers which are too close to boundary */ if (marker->pos[0] < margin[0] || marker->pos[0] > 1.0f - margin[0] || @@ -2402,7 +2406,7 @@ static void tracking_insert_new_marker(MovieTrackingContext *context, MovieTrack * if so -- create disabled marker before currently tracking "segment" */ - tracking_marker_insert_disabled(track, &new_marker, !context->backwards, FALSE); + tracking_marker_insert_disabled(track, old_marker, !context->backwards, FALSE); } /* insert currently tracked marker */ @@ -2481,8 +2485,12 @@ int BKE_tracking_context_step(MovieTrackingContext *context) float *patch_new; if (need_readjust) { - track_context_update_reference(context, track_context, track, marker, - curfra, frame_width, frame_height); + if (track_context_update_reference(context, track_context, track, marker, + curfra, frame_width, frame_height) == FALSE) + { + /* happens when reference frame fails to be loaded */ + continue; + } } /* for now track to the same search area dimension as marker has got for current frame @@ -2554,6 +2562,9 @@ typedef struct MovieReconstructContext { TracksMap *tracks_map; + float success_threshold; + int use_fallback_reconstruction; + int sfra, efra; } MovieReconstructContext; @@ -2753,10 +2764,11 @@ static int reconstruct_refine_intrinsics_get_flags(MovieTracking *tracking, Movi return flags; } -static int reconstruct_count_tracks_on_both_keyframes(MovieTracking *tracking, ListBase *tracksbase) +static int reconstruct_count_tracks_on_both_keyframes(MovieTracking *tracking, MovieTrackingObject *object) { + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); int tot = 0; - int frame1 = tracking->settings.keyframe1, frame2 = tracking->settings.keyframe2; + int frame1 = object->keyframe1, frame2 = object->keyframe2; MovieTrackingTrack *track; track = tracksbase->first; @@ -2776,15 +2788,13 @@ static int reconstruct_count_tracks_on_both_keyframes(MovieTracking *tracking, L int BKE_tracking_reconstruction_check(MovieTracking *tracking, MovieTrackingObject *object, char *error_msg, int error_size) { -#if WITH_LIBMV - ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); - +#ifdef WITH_LIBMV if (tracking->settings.motion_flag & TRACKING_MOTION_MODAL) { /* TODO: check for number of tracks? */ return TRUE; } - else if (reconstruct_count_tracks_on_both_keyframes(tracking, tracksbase) < 8) { - BLI_strncpy(error_msg, "At least 8 common tracks on both of keyframes are needed for reconstruction", + else if (reconstruct_count_tracks_on_both_keyframes(tracking, object) < 8) { + BLI_strncpy(error_msg, N_("At least 8 common tracks on both of keyframes are needed for reconstruction"), error_size); return FALSE; @@ -2792,7 +2802,7 @@ int BKE_tracking_reconstruction_check(MovieTracking *tracking, MovieTrackingObje return TRUE; #else - BLI_strncpy(error_msg, "Blender is compiled without motion tracking library", error_size); + BLI_strncpy(error_msg, N_("Blender is compiled without motion tracking library"), error_size); (void) tracking; (void) object; @@ -2824,6 +2834,9 @@ MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieTracking * context->k2 = camera->k2; context->k3 = camera->k3; + context->success_threshold = tracking->settings.reconstruction_success_threshold; + context->use_fallback_reconstruction = tracking->settings.reconstruction_flag & TRACKING_USE_FALLBACK_RECONSTRUCTION; + context->tracks_map = tracks_map_new(context->object_name, context->is_camera, num_tracks, 0); track = tracksbase->first; @@ -2845,10 +2858,10 @@ MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieTracking * } if (first < track->markersnr - 1) - sfra = MIN2(sfra, first_marker->framenr); + sfra = min_ii(sfra, first_marker->framenr); if (last >= 0) - efra = MAX2(efra, last_marker->framenr); + efra = max_ii(efra, last_marker->framenr); tracks_map_insert(context->tracks_map, track, NULL); @@ -2923,12 +2936,18 @@ void BKE_tracking_reconstruction_solve(MovieReconstructContext *context, short * reconstruct_update_solve_cb, &progressdata); } else { + struct libmv_reconstructionOptions options; + + options.success_threshold = context->success_threshold; + options.use_fallback_reconstruction = context->use_fallback_reconstruction; + context->reconstruction = libmv_solveReconstruction(context->tracks, context->keyframe1, context->keyframe2, context->refine_flags, context->focal_length, context->principal_point[0], context->principal_point[1], context->k1, context->k2, context->k3, + &options, reconstruct_update_solve_cb, &progressdata); } @@ -2950,6 +2969,7 @@ int BKE_tracking_reconstruction_finish(MovieReconstructContext *context, MovieTr MovieTrackingReconstruction *reconstruction; tracks_map_merge(context->tracks_map, tracking); + BKE_tracking_dopesheet_tag_update(tracking); if (context->is_camera) { reconstruction = &tracking->reconstruction; @@ -3195,8 +3215,8 @@ static float stabilization_calculate_autoscale_factor(MovieTracking *tracking, i if (track->flag & TRACK_USE_2D_STAB || ((stab->flag & TRACKING_STABILIZE_ROTATION) && track == stab->rot_track)) { - sfra = MIN2(sfra, track->markers[0].framenr); - efra = MAX2(efra, track->markers[track->markersnr - 1].framenr); + sfra = min_ii(sfra, track->markers[0].framenr); + efra = max_ii(efra, track->markers[track->markersnr - 1].framenr); } track = track->next; @@ -3272,7 +3292,7 @@ static float stabilization_calculate_autoscale_factor(MovieTracking *tracking, i S = (-w * I - h * J) / (dx * I + dy * J + K); - scale = maxf(scale, S); + scale = max_ff(scale, S); } } } @@ -3281,7 +3301,7 @@ static float stabilization_calculate_autoscale_factor(MovieTracking *tracking, i stab->scale = scale; if (stab->maxscale > 0.0f) - stab->scale = minf(stab->scale, stab->maxscale); + stab->scale = min_ff(stab->scale, stab->maxscale); } else { stab->scale = 1.0f; @@ -3640,7 +3660,7 @@ static void channels_segments_calc(MovieTrackingDopesheetChannel *channel) channel->segments[2 * segment] = start_marker->framenr; channel->segments[2 * segment + 1] = start_marker->framenr + len; - channel->max_segment = MAX2(channel->max_segment, len); + channel->max_segment = max_ii(channel->max_segment, len); segment++; } @@ -3648,7 +3668,7 @@ static void channels_segments_calc(MovieTrackingDopesheetChannel *channel) } } -static void tracking_dopesheet_sort(MovieTracking *tracking, int sort_method, int inverse) +static void tracking_dopesheet_sort(MovieTracking *tracking, int sort_method, int inverse) { MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index da5e7ff3db7..84e1f29f6c0 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -259,7 +259,7 @@ static struct bUnitCollection buNaturalTimeCollecton = {buNaturalTimeDef, 3, 0, static struct bUnitDef buNaturalRotDef[] = { - {"degree", "degrees", "°", NULL, "Degrees", M_PI/180.0, 0.0, B_UNIT_DEF_NONE}, + {"degree", "degrees", "°", NULL, "Degrees", M_PI / 180.0, 0.0, B_UNIT_DEF_NONE}, // {"radian", "radians", "r", NULL, "Radians", 1.0, 0.0, B_UNIT_DEF_NONE}, // {"turn", "turns", "t", NULL, "Turns", 1.0/(M_PI*2.0), 0.0,B_UNIT_DEF_NONE}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} @@ -350,7 +350,7 @@ static int unit_as_string(char *str, int len_max, double value, int prec, bUnitC /* Add unit prefix and strip zeros */ /* replace trailing zero's with spaces - * so the number is less complicated but allignment in a button wont + * so the number is less complicated but alignment in a button wont * jump about while dragging */ i = len - 1; diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 434bfe19c1f..4bde895cf7d 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -107,7 +107,7 @@ World *add_world(const char *name) wrld->ao_indirect_energy = 1.0f; wrld->ao_indirect_bounces = 1; wrld->aobias = 0.05f; - wrld->ao_samp_method = WO_AOSAMP_HAMMERSLEY; + wrld->ao_samp_method = WO_AOSAMP_HAMMERSLEY; wrld->ao_approx_error = 0.25f; wrld->preview = NULL; diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index dab44b5463c..d4428be3faf 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -47,7 +47,11 @@ #include "BKE_report.h" #include "BKE_writeavi.h" -#include "AVI_avi.h" + +/* ********************** general blender movie support ***************************** */ + +#ifdef WITH_AVI +# include "AVI_avi.h" /* callbacks */ static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports); @@ -55,30 +59,31 @@ static void end_avi(void); static int append_avi(RenderData *rd, int start_frame, int frame, int *pixels, int rectx, int recty, ReportList *reports); static void filepath_avi(char *string, RenderData *rd); - -/* ********************** general blender movie support ***************************** */ +#endif /* WITH_AVI */ #ifdef WITH_QUICKTIME -#include "quicktime_export.h" +# include "quicktime_export.h" #endif #ifdef WITH_FFMPEG -#include "BKE_writeffmpeg.h" +# include "BKE_writeffmpeg.h" #endif #include "BKE_writeframeserver.h" bMovieHandle *BKE_movie_handle_get(const char imtype) { - static bMovieHandle mh; + static bMovieHandle mh = {0}; /* set the default handle, as builtin */ +#ifdef WITH_AVI mh.start_movie = start_avi; mh.append_movie = append_avi; mh.end_movie = end_avi; mh.get_next_frame = NULL; mh.get_movie_path = filepath_avi; - +#endif + /* do the platform specific handles */ #ifdef WITH_QUICKTIME if (imtype == R_IMF_IMTYPE_QUICKTIME) { @@ -114,6 +119,8 @@ bMovieHandle *BKE_movie_handle_get(const char imtype) /* ****************************************************************** */ +#ifdef WITH_AVI + static AviMovie *avi = NULL; static void filepath_avi(char *string, RenderData *rd) @@ -155,7 +162,7 @@ static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportL else format = AVI_FORMAT_MJPEG; if (AVI_open_compress(name, avi, 1, format) != AVI_ERROR_NONE) { - BKE_report(reports, RPT_ERROR, "Cannot open or start AVI movie file."); + BKE_report(reports, RPT_ERROR, "Cannot open or start AVI movie file"); MEM_freeN(avi); avi = NULL; return 0; @@ -168,8 +175,8 @@ static int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportL avi->interlace = 0; avi->odd_fields = 0; -/* avi->interlace= rd->mode & R_FIELDS; */ -/* avi->odd_fields= (rd->mode & R_ODDFIELD)?1:0; */ +/* avi->interlace = rd->mode & R_FIELDS; */ +/* avi->odd_fields = (rd->mode & R_ODDFIELD) ? 1 : 0; */ printf("Created avi: %s\n", name); return 1; @@ -219,6 +226,7 @@ static void end_avi(void) MEM_freeN(avi); avi = NULL; } +#endif /* WITH_AVI */ /* similar to BKE_makepicstring() */ void BKE_movie_filepath_get(char *string, RenderData *rd) diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 4019eba5177..3a8a14290dc 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -289,7 +289,7 @@ static int write_video_frame(RenderData *rd, int cfra, AVFrame *frame, ReportLis } if (!success) - BKE_report(reports, RPT_ERROR, "Error writing frame."); + BKE_report(reports, RPT_ERROR, "Error writing frame"); return success; } @@ -307,7 +307,7 @@ static AVFrame *generate_video_frame(uint8_t *pixels, ReportList *reports) if (c->pix_fmt != PIX_FMT_BGR32) { rgb_frame = alloc_picture(PIX_FMT_BGR32, width, height); if (!rgb_frame) { - BKE_report(reports, RPT_ERROR, "Couldn't allocate temporary frame."); + BKE_report(reports, RPT_ERROR, "Could not allocate temporary frame"); return NULL; } } @@ -695,12 +695,12 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report exts = get_file_extensions(ffmpeg_type); if (!exts) { - BKE_report(reports, RPT_ERROR, "No valid formats found."); + BKE_report(reports, RPT_ERROR, "No valid formats found"); return 0; } fmt = av_guess_format(NULL, exts[0], NULL); if (!fmt) { - BKE_report(reports, RPT_ERROR, "No valid formats found."); + BKE_report(reports, RPT_ERROR, "No valid formats found"); return 0; } @@ -795,7 +795,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report if (error[0]) BKE_report(reports, RPT_ERROR, error); else - BKE_report(reports, RPT_ERROR, "Error initializing video stream."); + BKE_report(reports, RPT_ERROR, "Error initializing video stream"); av_dict_free(&opts); return 0; @@ -805,20 +805,20 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report if (ffmpeg_audio_codec != CODEC_ID_NONE) { audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of); if (!audio_stream) { - BKE_report(reports, RPT_ERROR, "Error initializing audio stream."); + BKE_report(reports, RPT_ERROR, "Error initializing audio stream"); av_dict_free(&opts); return 0; } } if (!(fmt->flags & AVFMT_NOFILE)) { if (avio_open(&of->pb, name, AVIO_FLAG_WRITE) < 0) { - BKE_report(reports, RPT_ERROR, "Could not open file for writing."); + BKE_report(reports, RPT_ERROR, "Could not open file for writing"); av_dict_free(&opts); return 0; } } if (avformat_write_header(of, NULL) < 0) { - BKE_report(reports, RPT_ERROR, "Could not initialize streams. Probably unsupported codec combination."); + BKE_report(reports, RPT_ERROR, "Could not initialize streams, probably unsupported codec combination"); av_dict_free(&opts); return 0; } @@ -839,7 +839,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report * inter-frames (H.264 B-frames, for example), it can output the frames * in a different order from the one it was given. * For example, when sending frames 1, 2, 3, 4 to the encoder, it may write - * them in the order 1, 4, 2, 3 - first the two frames used for predition, + * them in the order 1, 4, 2, 3 - first the two frames used for prediction, * and then the bidirectionally-predicted frames. What this means in practice * is that the encoder may not immediately produce one output frame for each * input frame. These delayed frames must be flushed before we close the @@ -914,8 +914,7 @@ void BKE_ffmpeg_filepath_get(char *string, RenderData *rd) } while (*fe) { - if (BLI_strcasecmp(string + strlen(string) - strlen(*fe), *fe) == 0) - { + if (BLI_strcasecmp(string + strlen(string) - strlen(*fe), *fe) == 0) { break; } fe++; @@ -983,7 +982,7 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i PRINT("Writing frame %i, render width=%d, render height=%d\n", frame, rectx, recty); -// why is this done before writing the video frame and again at end_ffmpeg? +/* why is this done before writing the video frame and again at end_ffmpeg? */ // write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base)); if (video_stream) { @@ -1226,7 +1225,7 @@ int BKE_ffmpeg_property_add_string(RenderData *rd, const char *type, const char while (*param == ' ') param++; } - o = my_av_find_opt(&c, name, NULL, 0, 0); + o = my_av_find_opt(&c, name, NULL, 0, 0); if (!o) { return 0; } @@ -1234,7 +1233,7 @@ int BKE_ffmpeg_property_add_string(RenderData *rd, const char *type, const char return 0; } if (param && o->type != FF_OPT_TYPE_CONST && o->unit) { - p = my_av_find_opt(&c, param, o->unit, 0, 0); + p = my_av_find_opt(&c, param, o->unit, 0, 0); if (p) { prop = BKE_ffmpeg_property_add(rd, (char *) type, p - c.av_class->option, o - c.av_class->option); } diff --git a/source/blender/blenkernel/intern/writeframeserver.c b/source/blender/blenkernel/intern/writeframeserver.c index d8fddb9851a..acbbcb0b043 100644 --- a/source/blender/blenkernel/intern/writeframeserver.c +++ b/source/blender/blenkernel/intern/writeframeserver.c @@ -118,13 +118,13 @@ int BKE_frameserver_start(struct Scene *scene, RenderData *UNUSED(rd), int rectx (void)scene; /* unused */ if (!startup_socket_system()) { - BKE_report(reports, RPT_ERROR, "Can't startup socket system"); + BKE_report(reports, RPT_ERROR, "Cannot startup socket system"); return 0; } if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { shutdown_socket_system(); - BKE_report(reports, RPT_ERROR, "Can't open socket"); + BKE_report(reports, RPT_ERROR, "Cannot open socket"); return 0; } @@ -136,13 +136,13 @@ int BKE_frameserver_start(struct Scene *scene, RenderData *UNUSED(rd), int rectx if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { shutdown_socket_system(); - BKE_report(reports, RPT_ERROR, "Can't bind to socket"); + BKE_report(reports, RPT_ERROR, "Cannot bind to socket"); return 0; } if (listen(sock, SOMAXCONN) < 0) { shutdown_socket_system(); - BKE_report(reports, RPT_ERROR, "Can't establish listen backlog"); + BKE_report(reports, RPT_ERROR, "Cannot establish listen backlog"); return 0; } connsock = -1; diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h index 941a74ec2ab..f068c4c58f0 100644 --- a/source/blender/blenkernel/nla_private.h +++ b/source/blender/blenkernel/nla_private.h @@ -85,4 +85,4 @@ NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, ListBase *strips, short void nlastrip_evaluate(PointerRNA *ptr, ListBase *channels, ListBase *modifiers, NlaEvalStrip *nes); void nladata_flush_channels(ListBase *channels); -#endif // __NLA_PRIVATE_H__ +#endif /* __NLA_PRIVATE_H__ */ diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index 74b477bacaf..03b75975af4 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -78,8 +78,6 @@ extern "C" { #include "BLI_rect.h" -#include "BLI_noise.h" - #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_bpath.h b/source/blender/blenlib/BLI_bpath.h index 52b839d11a9..a86b362c271 100644 --- a/source/blender/blenlib/BLI_bpath.h +++ b/source/blender/blenlib/BLI_bpath.h @@ -64,4 +64,4 @@ void BLI_bpath_missing_files_find(struct Main *bmain, const char *searchpath, st void BLI_bpath_relative_convert(struct Main *bmain, const char *basedir, struct ReportList *reports); void BLI_bpath_absolute_convert(struct Main *bmain, const char *basedir, struct ReportList *reports); -#endif // __BLI_BPATH_H__ +#endif /* __BLI_BPATH_H__ */ diff --git a/source/blender/blenlib/BLI_dlrbTree.h b/source/blender/blenlib/BLI_dlrbTree.h index 92356b24403..bdde8dbd597 100644 --- a/source/blender/blenlib/BLI_dlrbTree.h +++ b/source/blender/blenlib/BLI_dlrbTree.h @@ -46,7 +46,7 @@ /* Basic Layout for a Node */ typedef struct DLRBT_Node { /* ListBase capabilities */ - struct DLRBT_Node *next, *prev; + struct DLRBT_Node *next, *prev; /* Tree Associativity settings */ struct DLRBT_Node *left, *right; @@ -158,4 +158,4 @@ void BLI_dlrbTree_insert(DLRBT_Tree *tree, DLRBT_Node *node); /* ********************************************** */ -#endif // __BLI_DLRBTREE_H__ +#endif /* __BLI_DLRBTREE_H__ */ diff --git a/source/blender/blenlib/BLI_dynstr.h b/source/blender/blenlib/BLI_dynstr.h index 3b7f2d6bbaf..833c416c1c1 100644 --- a/source/blender/blenlib/BLI_dynstr.h +++ b/source/blender/blenlib/BLI_dynstr.h @@ -80,7 +80,11 @@ void BLI_dynstr_appendf(DynStr *ds, const char *format, ...) __attribute__ ((format(printf, 2, 3))) #endif ; -void BLI_dynstr_vappendf(DynStr *ds, const char *format, va_list args); +void BLI_dynstr_vappendf(DynStr *ds, const char *format, va_list args) +#ifdef __GNUC__ +__attribute__ ((format(printf, 2, 0))) +#endif +; /** * Find the length of a DynStr. @@ -107,7 +111,6 @@ char *BLI_dynstr_get_cstring(DynStr *ds); * * \param ds The DynStr of interest. * \param str The string to fill. - * \return The contents of \a ds as a c-string. */ void BLI_dynstr_get_cstring_ex(DynStr *ds, char *str); diff --git a/source/blender/blenlib/BLI_endian_switch.h b/source/blender/blenlib/BLI_endian_switch.h index 7017e7ba789..7cb2790525d 100644 --- a/source/blender/blenlib/BLI_endian_switch.h +++ b/source/blender/blenlib/BLI_endian_switch.h @@ -27,16 +27,36 @@ * \ingroup bli */ -#include "BLI_endian_switch_inline.h" +#ifdef __GNUC__ +# define ATTR_ENDIAN_SWITCH \ + __attribute__((nonnull(1))) \ + __attribute__((pure)) +#else +# define ATTR_ENDIAN_SWITCH +#endif + +/* BLI_endian_switch_inline.h */ +BLI_INLINE void BLI_endian_switch_int16(short *val) ATTR_ENDIAN_SWITCH; +BLI_INLINE void BLI_endian_switch_uint16(unsigned short *val) ATTR_ENDIAN_SWITCH; +BLI_INLINE void BLI_endian_switch_int32(int *val) ATTR_ENDIAN_SWITCH; +BLI_INLINE void BLI_endian_switch_uint32(unsigned int *val) ATTR_ENDIAN_SWITCH; +BLI_INLINE void BLI_endian_switch_float(float *val) ATTR_ENDIAN_SWITCH; +BLI_INLINE void BLI_endian_switch_int64(int64_t *val) ATTR_ENDIAN_SWITCH; +BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val) ATTR_ENDIAN_SWITCH; +BLI_INLINE void BLI_endian_switch_double(double *val) ATTR_ENDIAN_SWITCH; /* endian_switch.c */ -void BLI_endian_switch_int16_array(short *val, const int size); -void BLI_endian_switch_uint16_array(unsigned short *val, const int size); -void BLI_endian_switch_int32_array(int *val, const int size); -void BLI_endian_switch_uint32_array(unsigned int *val, const int size); -void BLI_endian_switch_float_array(float *val, const int size); -void BLI_endian_switch_int64_array(int64_t *val, const int size); -void BLI_endian_switch_uint64_array(uint64_t *val, const int size); -void BLI_endian_switch_double_array(double *val, const int size); +void BLI_endian_switch_int16_array(short *val, const int size) ATTR_ENDIAN_SWITCH; +void BLI_endian_switch_uint16_array(unsigned short *val, const int size) ATTR_ENDIAN_SWITCH; +void BLI_endian_switch_int32_array(int *val, const int size) ATTR_ENDIAN_SWITCH; +void BLI_endian_switch_uint32_array(unsigned int *val, const int size) ATTR_ENDIAN_SWITCH; +void BLI_endian_switch_float_array(float *val, const int size) ATTR_ENDIAN_SWITCH; +void BLI_endian_switch_int64_array(int64_t *val, const int size) ATTR_ENDIAN_SWITCH; +void BLI_endian_switch_uint64_array(uint64_t *val, const int size) ATTR_ENDIAN_SWITCH; +void BLI_endian_switch_double_array(double *val, const int size) ATTR_ENDIAN_SWITCH; + +#include "BLI_endian_switch_inline.h" + +#undef ATTR_ENDIAN_SWITCH #endif /* __BLI_ENDIAN_SWITCH_H__ */ diff --git a/source/blender/blenlib/BLI_endian_switch_inline.h b/source/blender/blenlib/BLI_endian_switch_inline.h index b747da3b738..4bc6d3828b9 100644 --- a/source/blender/blenlib/BLI_endian_switch_inline.h +++ b/source/blender/blenlib/BLI_endian_switch_inline.h @@ -32,85 +32,63 @@ * \ingroup bli */ +/* note: using a temp char to switch endian is a lot slower, + * use bit shifting instead. */ +/* *** 16 *** */ BLI_INLINE void BLI_endian_switch_int16(short *val) { - char *p_i = (char *)val; - char s_i; + short tval = *val; + *val = (tval >> 8) | + (tval << 8); - s_i = p_i[0]; - p_i[0] = p_i[1]; - p_i[1] = s_i; } - BLI_INLINE void BLI_endian_switch_uint16(unsigned short *val) { - char *p_i = (char *)val; - char s_i; - - s_i = p_i[0]; - p_i[0] = p_i[1]; - p_i[1] = s_i; + BLI_endian_switch_int16((short *)val); } + +/* *** 32 *** */ BLI_INLINE void BLI_endian_switch_int32(int *val) { - char *p_i = (char *)val; - char s_i; + int tval = *val; + *val = ((tval >> 24)) | + ((tval << 8) & 0x00ff0000) | + ((tval >> 8) & 0x0000ff00) | + ((tval << 24)); - s_i = p_i[0]; p_i[0] = p_i[3]; p_i[3] = s_i; - s_i = p_i[1]; p_i[1] = p_i[2]; p_i[2] = s_i; } - BLI_INLINE void BLI_endian_switch_uint32(unsigned int *val) { - char *p_i = (char *)val; - char s_i; - - s_i = p_i[0]; p_i[0] = p_i[3]; p_i[3] = s_i; - s_i = p_i[1]; p_i[1] = p_i[2]; p_i[2] = s_i; + BLI_endian_switch_int32((int *)val); } - BLI_INLINE void BLI_endian_switch_float(float *val) { - char *p_i = (char *)val; - char s_i; - - s_i = p_i[0]; p_i[0] = p_i[3]; p_i[3] = s_i; - s_i = p_i[1]; p_i[1] = p_i[2]; p_i[2] = s_i; + BLI_endian_switch_int32((int *)val); } + +/* *** 64 *** */ BLI_INLINE void BLI_endian_switch_int64(int64_t *val) { - char *p_i = (char *)val; - char s_i; - - s_i = p_i[0]; p_i[0] = p_i[7]; p_i[7] = s_i; - s_i = p_i[1]; p_i[1] = p_i[6]; p_i[6] = s_i; - s_i = p_i[2]; p_i[2] = p_i[5]; p_i[5] = s_i; - s_i = p_i[3]; p_i[3] = p_i[4]; p_i[4] = s_i; + int64_t tval = *val; + *val = ((tval >> 56)) | + ((tval << 40) & 0x00ff000000000000ll) | + ((tval << 24) & 0x0000ff0000000000ll) | + ((tval << 8) & 0x000000ff00000000ll) | + ((tval >> 8) & 0x00000000ff000000ll) | + ((tval >> 24) & 0x0000000000ff0000ll) | + ((tval >> 40) & 0x000000000000ff00ll) | + ((tval << 56)); } - BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val) { - char *p_i = (char *)val; - char s_i; - - s_i = p_i[0]; p_i[0] = p_i[7]; p_i[7] = s_i; - s_i = p_i[1]; p_i[1] = p_i[6]; p_i[6] = s_i; - s_i = p_i[2]; p_i[2] = p_i[5]; p_i[5] = s_i; - s_i = p_i[3]; p_i[3] = p_i[4]; p_i[4] = s_i; + BLI_endian_switch_int64((int64_t *)val); } - BLI_INLINE void BLI_endian_switch_double(double *val) { - char *p_i = (char *)val; - char s_i; - - s_i = p_i[0]; p_i[0] = p_i[7]; p_i[7] = s_i; - s_i = p_i[1]; p_i[1] = p_i[6]; p_i[6] = s_i; - s_i = p_i[2]; p_i[2] = p_i[5]; p_i[5] = s_i; - s_i = p_i[3]; p_i[3] = p_i[4]; p_i[4] = s_i; + BLI_endian_switch_int64((int64_t *)val); } #endif /* __BLI_ENDIAN_SWITCH_INLINE_H__ */ diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h index e8d6336a994..c278370d211 100644 --- a/source/blender/blenlib/BLI_fileops.h +++ b/source/blender/blenlib/BLI_fileops.h @@ -96,6 +96,8 @@ void BLI_file_free_lines(struct LinkNode *lines); # ifndef O_BINARY # define O_BINARY 0 # endif +#else +void BLI_get_short_name(char short_name[256], const char *filename); #endif #ifdef __cplusplus diff --git a/source/blender/blenlib/BLI_fileops_types.h b/source/blender/blenlib/BLI_fileops_types.h index a19909a8f26..1c6463eb6ea 100644 --- a/source/blender/blenlib/BLI_fileops_types.h +++ b/source/blender/blenlib/BLI_fileops_types.h @@ -46,7 +46,7 @@ struct direntry { mode_t type; char *relname; char *path; -#if (defined(WIN32) || defined(WIN64)) && (_MSC_VER >= 1500) +#if (defined(WIN32) || defined(WIN64)) && !defined(__MINGW32__) && (_MSC_VER >= 1500) struct _stat64 s; #elif defined(__MINGW32__) struct _stati64 s; diff --git a/source/blender/blenlib/BLI_heap.h b/source/blender/blenlib/BLI_heap.h index b378f2bb365..c0941e00c9b 100644 --- a/source/blender/blenlib/BLI_heap.h +++ b/source/blender/blenlib/BLI_heap.h @@ -42,6 +42,7 @@ typedef void (*HeapFreeFP)(void *ptr); /* Creates a new heap. BLI_memarena is used for allocating nodes. Removed nodes * are recycled, so memory usage will not shrink. */ +Heap *BLI_heap_new_ex(unsigned int tot_reserve); Heap *BLI_heap_new(void); void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp); @@ -53,10 +54,10 @@ HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr); void BLI_heap_remove(Heap *heap, HeapNode *node); /* Return 0 if the heap is empty, 1 otherwise. */ -int BLI_heap_empty(Heap *heap); +int BLI_heap_is_empty(Heap *heap); /* Return the size of the heap. */ -int BLI_heap_size(Heap *heap); +unsigned int BLI_heap_size(Heap *heap); /* Return the top node of the heap. This is the node with the lowest value. */ HeapNode *BLI_heap_top(Heap *heap); @@ -68,5 +69,4 @@ void *BLI_heap_popmin(Heap *heap); float BLI_heap_node_value(HeapNode *heap); void *BLI_heap_node_ptr(HeapNode *heap); -#endif - +#endif /* __BLI_HEAP_H__ */ diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index 985b5af3b94..8441413fba9 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -75,7 +75,7 @@ typedef struct BVHTreeRayHit { } BVHTreeRayHit; /* callback must update nearest in case it finds a nearest result */ -typedef void (*BVHTree_NearestPointCallback)(void *userdata, int index, const float *co, BVHTreeNearest *nearest); +typedef void (*BVHTree_NearestPointCallback)(void *userdata, int index, const float co[3], BVHTreeNearest *nearest); /* callback must update hit in case it finds a nearest successful hit */ typedef void (*BVHTree_RayCastCallback)(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit); @@ -87,31 +87,34 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis); void BLI_bvhtree_free(BVHTree *tree); /* construct: first insert points, then call balance */ -int BLI_bvhtree_insert(BVHTree *tree, int index, const float *co, int numpoints); +int BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints); void BLI_bvhtree_balance(BVHTree *tree); /* update: first update points/nodes, then call update_tree to refit the bounding volumes */ -int BLI_bvhtree_update_node(BVHTree *tree, int index, const float *co, const float *co_moving, int numpoints); +int BLI_bvhtree_update_node(BVHTree *tree, int index, const float co[3], const float co_moving[3], int numpoints); void BLI_bvhtree_update_tree(BVHTree *tree); /* collision/overlap: check two trees if they overlap, alloc's *overlap with length of the int return value */ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int *result); -float BLI_bvhtree_getepsilon(BVHTree *tree); +float BLI_bvhtree_getepsilon(const BVHTree *tree); -/* find nearest node to the given coordinates (if nearest is given it will only search nodes where square distance is smaller than nearest->dist) */ -int BLI_bvhtree_find_nearest(BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata); +/* find nearest node to the given coordinates + * (if nearest is given it will only search nodes where square distance is smaller than nearest->dist) */ +int BLI_bvhtree_find_nearest(BVHTree *tree, const float co[3], BVHTreeNearest *nearest, + BVHTree_NearestPointCallback callback, void *userdata); -int BLI_bvhtree_ray_cast(BVHTree *tree, const float co[3], const float *dir, float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata); +int BLI_bvhtree_ray_cast(BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, + BVHTree_RayCastCallback callback, void *userdata); -float BLI_bvhtree_bb_raycast(const float *bv, const float light_start[3], const float light_end[3], float pos[3]); +float BLI_bvhtree_bb_raycast(const float bv[6], const float light_start[3], const float light_end[3], float pos[3]); /* range query */ -int BLI_bvhtree_range_query(BVHTree *tree, const float co[3], float radius, BVHTree_RangeQuery callback, void *userdata); +int BLI_bvhtree_range_query(BVHTree *tree, const float co[3], float radius, + BVHTree_RangeQuery callback, void *userdata); #ifdef __cplusplus } #endif -#endif // __BLI_KDOPBVH_H__ - +#endif /* __BLI_KDOPBVH_H__ */ diff --git a/source/blender/blenlib/BLI_kdtree.h b/source/blender/blenlib/BLI_kdtree.h index e90566408d4..f9b52f34102 100644 --- a/source/blender/blenlib/BLI_kdtree.h +++ b/source/blender/blenlib/BLI_kdtree.h @@ -56,7 +56,7 @@ void BLI_kdtree_balance(KDTree *tree); /* Find nearest returns index, and -1 if no node is found. * Find n nearest returns number of points found, with results in nearest. * Normal is optional, but if given will limit results to points in normal direction from co. */ -int BLI_kdtree_find_nearest(KDTree *tree, float *co, float *nor, KDTreeNearest *nearest); +int BLI_kdtree_find_nearest(KDTree *tree, const float co[3], const float nor[3], KDTreeNearest *nearest); int BLI_kdtree_find_n_nearest(KDTree *tree, int n, const float co[3], const float nor[3], KDTreeNearest *nearest); /* Range search returns number of points found, with results in nearest */ diff --git a/source/blender/blenlib/BLI_lasso.h b/source/blender/blenlib/BLI_lasso.h index 85a000b000c..a7e90a51e86 100644 --- a/source/blender/blenlib/BLI_lasso.h +++ b/source/blender/blenlib/BLI_lasso.h @@ -34,8 +34,8 @@ struct rcti; -void BLI_lasso_boundbox(struct rcti *rect, int mcords[][2], short moves); -int BLI_lasso_is_point_inside(int mcords[][2], short moves, const int sx, const int sy, const int error_value); -int BLI_lasso_is_edge_inside(int mcords[][2], short moves, int x0, int y0, int x1, int y1, const int error_value); +void BLI_lasso_boundbox(struct rcti *rect, const int mcords[][2], const short moves); +int BLI_lasso_is_point_inside(const int mcords[][2], const short moves, const int sx, const int sy, const int error_value); +int BLI_lasso_is_edge_inside(const int mcords[][2], const short moves, int x0, int y0, int x1, int y1, const int error_value); #endif diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index 886ed6f495d..2b513cbec41 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -30,8 +30,8 @@ * \ingroup bli */ -#ifdef WIN32 -#define _USE_MATH_DEFINES +#ifdef _MSC_VER +# define _USE_MATH_DEFINES #endif #include @@ -188,8 +188,11 @@ MINLINE float sasqrt(float fac); MINLINE float interpf(float a, float b, float t); -MINLINE float minf(float a, float b); -MINLINE float maxf(float a, float b); +MINLINE float min_ff(float a, float b); +MINLINE float max_ff(float a, float b); + +MINLINE int min_ii(int a, int b); +MINLINE int max_ii(int a, int b); MINLINE float signf(float f); diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 6fe5d48d06e..7c8bf88943d 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -115,6 +115,8 @@ void rgba_float_to_uchar(unsigned char col_r[4], const float col_f[4]); void xyz_to_lab(float x, float y, float z, float *l, float *a, float *b); +MINLINE int compare_rgb_uchar(const unsigned char a[3], const unsigned char b[3], const int limit); + /***************** lift/gamma/gain / ASC-CDL conversion *****************/ void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *offset, float *slope, float *power); diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 107b688b36a..80169e952bf 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -95,12 +95,6 @@ int isect_line_sphere_v2(const float l1[2], const float l2[2], const float sp[2] int isect_seg_seg_v2_point(const float v1[2], const float v2[2], const float v3[2], const float v4[2], float vi[2]); int isect_seg_seg_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2]); -/* Returns the number of point of interests - * 0 - lines are colinear - * 1 - lines are coplanar, i1 is set to intersection - * 2 - i1 and i2 are the nearest points on line 1 (v1, v2) and line 2 (v3, v4) respectively - * */ - int isect_line_line_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float i1[3], float i2[3]); @@ -108,35 +102,13 @@ int isect_line_line_strict_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float vi[3], float *r_lambda); -/* if clip is nonzero, will only return true if lambda is >= 0.0 - * (i.e. intersection point is along positive d)*/ int isect_ray_plane_v3(const float p1[3], const float d[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, const int clip); -/** - * Intersect line/plane, optionally treat line as directional (like a ray) with the no_flip argument. - * \param out The intersection point. - * \param l1 The first point of the line. - * \param l2 The second point of the line. - * \param plane_co A point on the plane to intersect with. - * \param plane_no The direction of the plane (does not need to be normalized). - * \param no_flip When true, the intersection point will always be from l1 to l2, even if this is not on the plane. - */ int isect_line_plane_v3(float out[3], const float l1[3], const float l2[3], const float plane_co[3], const float plane_no[3], const short no_flip); -/** - * Intersect two planes, return a point on the intersection and a vector - * that runs on the direction of the intersection. - * Return error code is the same as 'isect_line_line_v3'. - * \param r_isect_co The resulting intersection point. - * \param r_isect_no The resulting vector of the intersection. - * \param plane_a_co The point on the first plane. - * \param plane_a_no The normal of the first plane. - * \param plane_b_co The point on the second plane. - * \param plane_b_no The normal of the second plane. - */ void isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3], const float plane_a_co[3], const float plane_a_no[3], const float plane_b_co[3], const float plane_b_no[3]); @@ -250,14 +222,6 @@ void accumulate_vertex_normals_poly(float **vertnos, float polyno[3], /********************************* Tangents **********************************/ -typedef struct VertexTangent { - struct VertexTangent *next; - float tang[3], uv[2]; -} VertexTangent; - -float *find_vertex_tangent(VertexTangent *vtang, const float uv[2]); -void sum_or_add_vertex_tangent(void *arena, VertexTangent **vtang, - const float tang[3], const float uv[2]); void tangent_from_uv(float uv1[2], float uv2[2], float uv3[2], float co1[3], float co2[3], float co3[3], float n[3], float tang[3]); @@ -291,6 +255,9 @@ float form_factor_hemi_poly(float p[3], float n[3], void axis_dominant_v3(int *axis_a, int *axis_b, const float axis[3]); +MINLINE int max_axis_v3(const float vec[3]); +MINLINE int min_axis_v3(const float vec[3]); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index 8e9955beb61..9e34631d460 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -128,6 +128,7 @@ int is_orthonormal_m4(float mat[4][4]); int is_uniform_scaled_m3(float mat[3][3]); +void adjoint_m2_m2(float R[2][2], float A[2][2]); void adjoint_m3_m3(float R[3][3], float A[3][3]); void adjoint_m4_m4(float R[4][4], float A[4][4]); diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h index 8a439c7cf7a..652925fbe49 100644 --- a/source/blender/blenlib/BLI_math_rotation.h +++ b/source/blender/blenlib/BLI_math_rotation.h @@ -78,6 +78,8 @@ void quat_to_mat4(float mat[4][4], const float q[4]); void mat3_to_quat(float q[4], float mat[3][3]); void mat4_to_quat(float q[4], float mat[4][4]); +void tri_to_quat_ex(float quat[4], const float v1[3], const float v2[3], const float v3[3], + const float no_orig[3]); void tri_to_quat(float q[4], const float a[3], const float b[3], const float c[3]); void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag); /* note: v1 and v2 must be normalized */ @@ -105,7 +107,7 @@ void single_axis_angle_to_mat3(float R[3][3], const char axis, const float angle /****************************** Vector/Rotation ******************************/ /* old axis angle code */ -/* TODO: the following calls should probably be depreceated sometime */ +/* TODO: the following calls should probably be deprecated sometime */ /* conversion */ void vec_rot_to_mat3(float mat[3][3], const float vec[3], const float phi); diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 6c81ca3f0a9..77c0ec0a88f 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -67,6 +67,7 @@ MINLINE void copy_v2_v2_short(short r[2], const short a[2]); MINLINE void copy_v3_v3_short(short r[3], const short a[3]); MINLINE void copy_v4_v4_short(short r[4], const short a[4]); /* int */ +MINLINE void zero_v3_int(int r[3]); MINLINE void copy_v2_v2_int(int r[2], const int a[2]); MINLINE void copy_v3_v3_int(int r[3], const int a[3]); MINLINE void copy_v4_v4_int(int r[4], const int a[4]); @@ -139,12 +140,16 @@ MINLINE void star_m3_v3(float rmat[3][3], float a[3]); MINLINE float len_squared_v2(const float v[2]); MINLINE float len_squared_v3(const float v[3]); +MINLINE float len_manhattan_v2(const float v[2]); +MINLINE float len_manhattan_v3(const float v[3]); MINLINE float len_v2(const float a[2]); MINLINE float len_v2v2(const float a[2], const float b[2]); MINLINE float len_squared_v2v2(const float a[2], const float b[2]); +MINLINE float len_squared_v3v3(const float a[3], const float b[3]); +MINLINE float len_manhattan_v2v2(const float a[2], const float b[2]); +MINLINE float len_manhattan_v3v3(const float a[3], const float b[3]); MINLINE float len_v3(const float a[3]); MINLINE float len_v3v3(const float a[3], const float b[3]); -MINLINE float len_squared_v3v3(const float a[3], const float b[3]); MINLINE float normalize_v2(float r[2]); MINLINE float normalize_v2_v2(float r[2], const float a[2]); @@ -173,6 +178,7 @@ MINLINE int is_one_v3(const float a[3]); MINLINE int equals_v2v2(const float v1[2], const float v2[2]); MINLINE int equals_v3v3(const float a[3], const float b[3]); +MINLINE int compare_v2v2(const float a[3], const float b[3], const float limit); MINLINE int compare_v3v3(const float a[3], const float b[3], const float limit); MINLINE int compare_len_v3v3(const float a[3], const float b[3], const float limit); @@ -220,6 +226,7 @@ MINLINE void normal_short_to_float_v3(float r[3], const short n[3]); MINLINE void normal_float_to_short_v3(short r[3], const float n[3]); void minmax_v3v3_v3(float min[3], float max[3], const float vec[3]); +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); diff --git a/source/blender/blenlib/BLI_pbvh.h b/source/blender/blenlib/BLI_pbvh.h index 20d04f7881e..9483d068bb9 100644 --- a/source/blender/blenlib/BLI_pbvh.h +++ b/source/blender/blenlib/BLI_pbvh.h @@ -233,7 +233,7 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, if (vi.grid) { \ vi.co = CCG_elem_co(vi.key, vi.grid); \ vi.fno = CCG_elem_no(vi.key, vi.grid); \ - vi.mask = CCG_elem_mask(vi.key, vi.grid); \ + vi.mask = vi.key->has_mask ? CCG_elem_mask(vi.key, vi.grid) : NULL; \ vi.grid = CCG_elem_next(vi.key, vi.grid); \ if (vi.gh) { \ if (BLI_BITMAP_GET(vi.gh, vi.gy * vi.gridsize + vi.gx)) \ @@ -263,5 +263,7 @@ void BLI_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***nodes, int *totnode); //void BLI_pbvh_node_BB_reset(PBVHNode *node); //void BLI_pbvh_node_BB_expand(PBVHNode *node, float co[3]); +void pbvh_show_diffuse_color_set(PBVH *bvh, int show_diffuse_color); + #endif /* __BLI_PBVH_H__ */ diff --git a/intern/decimation/intern/LOD_MeshException.h b/source/blender/blenlib/BLI_quadric.h similarity index 50% rename from intern/decimation/intern/LOD_MeshException.h rename to source/blender/blenlib/BLI_quadric.h index 67bd8188c41..aec11ec2b44 100644 --- a/intern/decimation/intern/LOD_MeshException.h +++ b/source/blender/blenlib/BLI_quadric.h @@ -18,38 +18,39 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. + * Contributor(s): Laurence Bourn, Campbell Barton * * ***** END GPL LICENSE BLOCK ***** */ -/** \file decimation/intern/LOD_MeshException.h - * \ingroup decimation +#ifndef __BLI_QUADRIC_H__ +#define __BLI_QUADRIC_H__ + +/** \file BLI_quadric.h + * \ingroup bli */ +typedef struct Quadric { + float a2, ab, ac, ad, + b2, bc, bd, + c2, cd, + d2; +} Quadric; -#ifndef __LOD_MESHEXCEPTION_H__ -#define __LOD_MESHEXCEPTION_H__ +/* conversion */ +void BLI_quadric_from_v3_dist(Quadric *q, const float v[3], const float offset); +void BLI_quadric_to_tensor_m3(const Quadric *q, float m[3][3]); +void BLI_quadric_to_vector_v3(const Quadric *q, float v[3]); -class LOD_MeshException { +void BLI_quadric_clear(Quadric *q); -public : +/* math */ +void BLI_quadric_add_qu_qu(Quadric *a, const Quadric *b); +void BLI_quadric_add_qu_ququ(Quadric *r, const Quadric *a, const Quadric *b); +void BLI_quadric_mul(Quadric *a, const float scalar); - // stick in more error types as you think of them - - enum ExceptionType{ - e_non_manifold, - e_search_error - } m_e_type; - - LOD_MeshException ( - ExceptionType type - ) : m_e_type (type) - { - } -}; - -#endif +/* solve */ +float BLI_quadric_evaluate(const Quadric *q, const float v[3]); +int BLI_quadric_optimize(const Quadric *q, float v[3]); +#endif /* __BLI_QUADRIC_H__ */ diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h index 7dd6c8575c9..3bc9a3bdb32 100644 --- a/source/blender/blenlib/BLI_rand.h +++ b/source/blender/blenlib/BLI_rand.h @@ -40,18 +40,18 @@ struct RNG; typedef struct RNG RNG; -struct RNG *rng_new(unsigned int seed); -void rng_free(struct RNG *rng); +struct RNG *BLI_rng_new(unsigned int seed); +void BLI_rng_free(struct RNG *rng); -void rng_seed(struct RNG *rng, unsigned int seed); -void rng_srandom(struct RNG *rng, unsigned int seed); -int rng_getInt(struct RNG *rng); -double rng_getDouble(struct RNG *rng); -float rng_getFloat(struct RNG *rng); -void rng_shuffleArray(struct RNG *rng, void *data, int elemSize, int numElems); +void BLI_rng_seed(struct RNG *rng, unsigned int seed); +void BLI_rng_srandom(struct RNG *rng, unsigned int seed); +int BLI_rng_get_int(struct RNG *rng); +double BLI_rng_get_double(struct RNG *rng); +float BLI_rng_get_float(struct RNG *rng); +void BLI_rng_shuffle_array(struct RNG *rng, void *data, int elemSize, int numElems); /** Note that skipping is as slow as generating n numbers! */ -void rng_skip(struct RNG *rng, int n); +void BLI_rng_skip(struct RNG *rng, int n); /** Seed the random number generator */ void BLI_srand(unsigned int seed); @@ -94,7 +94,4 @@ int BLI_thread_rand(int thread); /** Allows up to BLENDER_MAX_THREADS threads to address */ float BLI_thread_frand(int thread); - - -#endif - +#endif /* __BLI_RAND_H__ */ diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h index eb9915d6c9b..f84820e94f3 100644 --- a/source/blender/blenlib/BLI_rect.h +++ b/source/blender/blenlib/BLI_rect.h @@ -55,6 +55,8 @@ void BLI_rcti_resize(struct rcti *rect, int x, int y); void BLI_rctf_resize(struct rctf *rect, float x, float y); void BLI_rctf_interp(struct rctf *rect, const struct rctf *rect_a, const struct rctf *rect_b, const float fac); //void BLI_rcti_interp(struct rctf *rect, struct rctf *rect_a, struct rctf *rect_b, float fac); +int BLI_rctf_clamp_pt_v(const struct rctf *rect, float xy[2]); +int BLI_rcti_clamp_pt_v(const struct rcti *rect, int xy[2]); int BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, const float limit); int BLI_rcti_compare(const struct rcti *rect_a, const struct rcti *rect_b); int BLI_rctf_isect(const struct rctf *src1, const struct rctf *src2, struct rctf *dest); @@ -64,9 +66,7 @@ int BLI_rcti_isect_pt_v(const struct rcti *rect, const int xy[2]); int BLI_rctf_isect_pt(const struct rctf *rect, const float x, const float y); int BLI_rctf_isect_pt_v(const struct rctf *rect, const float xy[2]); int BLI_rcti_isect_segment(const struct rcti *rect, const int s1[2], const int s2[2]); -#if 0 /* NOT NEEDED YET */ -int BLI_rctf_isect_segment(struct rcti *rect, int s1[2], int s2[2]); -#endif +int BLI_rctf_isect_segment(const struct rctf *rect, const float s1[2], const float s2[2]); void BLI_rctf_union(struct rctf *rctf1, const struct rctf *rctf2); void BLI_rcti_union(struct rcti *rcti1, const struct rcti *rcti2); void BLI_rcti_rctf_copy(struct rcti *dst, const struct rctf *src); @@ -75,14 +75,28 @@ void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src); void print_rctf(const char *str, const struct rctf *rect); void print_rcti(const char *str, const struct rcti *rect); -#define BLI_RCT_SIZE_X(rct) ((rct)->xmax - (rct)->xmin) -#define BLI_RCT_SIZE_Y(rct) ((rct)->ymax - (rct)->ymin) +/* hrmf, we need to work out this inline stuff */ +#if defined(_MSC_VER) +# define BLI_INLINE static __forceinline +#elif defined(__GNUC__) +# define BLI_INLINE static inline __attribute((always_inline)) +#else +/* #warning "MSC/GNUC defines not found, inline non-functional" */ +# define BLI_INLINE static +#endif -#define BLI_RCT_CENTER_X(rct) (((rct)->xmin + (rct)->xmax) / 2) -#define BLI_RCT_CENTER_Y(rct) (((rct)->ymin + (rct)->ymax) / 2) +#include "DNA_vec_types.h" +BLI_INLINE float BLI_rcti_cent_x_fl(const struct rcti *rct) { return (float)(rct->xmin + rct->xmax) / 2.0f; } +BLI_INLINE float BLI_rcti_cent_y_fl(const struct rcti *rct) { return (float)(rct->ymin + rct->ymax) / 2.0f; } +BLI_INLINE int BLI_rcti_cent_x(const struct rcti *rct) { return (rct->xmin + rct->xmax) / 2; } +BLI_INLINE int BLI_rcti_cent_y(const struct rcti *rct) { return (rct->ymin + rct->ymax) / 2; } +BLI_INLINE float BLI_rctf_cent_x(const struct rctf *rct) { return (rct->xmin + rct->xmax) / 2.0f; } +BLI_INLINE float BLI_rctf_cent_y(const struct rctf *rct) { return (rct->ymin + rct->ymax) / 2.0f; } -#define BLI_RCT_CENTER_X_FL(rct) ((float)((rct)->xmin + (rct)->xmax) / 2.0f) -#define BLI_RCT_CENTER_Y_FL(rct) ((float)((rct)->ymin + (rct)->ymax) / 2.0f) +BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct) { return (rct->xmax - rct->xmin); } +BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct) { return (rct->ymax - rct->ymin); } +BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct) { return (rct->xmax - rct->xmin); } +BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct) { return (rct->ymax - rct->ymin); } #ifdef __cplusplus } diff --git a/source/blender/blenlib/BLI_scanfill.h b/source/blender/blenlib/BLI_scanfill.h index a6b1943cb4d..892afdd0b27 100644 --- a/source/blender/blenlib/BLI_scanfill.h +++ b/source/blender/blenlib/BLI_scanfill.h @@ -103,7 +103,7 @@ void BLI_scanfill_end(ScanFillContext *sf_ctx); /* These callbacks are needed to make the lib finction properly */ /** - * Set a function taking a char* as argument to flag errors. If the + * Set a function taking a (char *) as argument to flag errors. If the * callback is not set, the error is discarded. * \param f The function to use as callback * \attention used in creator.c diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index b3d0df04eb1..70c89773f02 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -74,7 +74,7 @@ __attribute__((nonnull)) * \param str2 second string for append * \retval Returns dst */ -char *BLI_strdupcat(const char *str1, const char *str2) +char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2) #ifdef __GNUC__ __attribute__((warn_unused_result)) __attribute__((nonnull)) @@ -91,7 +91,7 @@ __attribute__((nonnull)) * the size of dst) * \retval Returns dst */ -char *BLI_strncpy(char *dst, const char *src, const size_t maxncpy) +char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) #ifdef __GNUC__ __attribute__((nonnull)) #endif @@ -107,7 +107,7 @@ __attribute__((nonnull)) * Assume that the strings returned must be freed afterwards, and that the inputs will contain * data we want... */ -char *BLI_str_quoted_substrN(const char *str, const char *prefix) +char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix) #ifdef __GNUC__ __attribute__((warn_unused_result)) __attribute__((nonnull)) @@ -124,7 +124,7 @@ __attribute__((nonnull)) * \param newText The text in the string to find and replace * \retval Returns the duplicated string */ -char *BLI_replacestr(char *str, const char *oldText, const char *newText) +char *BLI_replacestr(char *__restrict str, const char *__restrict oldText, const char *__restrict newText) #ifdef __GNUC__ __attribute__((warn_unused_result)) __attribute__((nonnull)) @@ -134,7 +134,7 @@ __attribute__((nonnull)) /* * Replacement for snprintf */ -size_t BLI_snprintf(char *buffer, size_t len, const char *format, ...) +size_t BLI_snprintf(char *__restrict buffer, size_t len, const char *__restrict format, ...) #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) __attribute__((nonnull)) @@ -144,13 +144,17 @@ __attribute__((nonnull)) /* * Replacement for vsnprintf */ -size_t BLI_vsnprintf(char *buffer, size_t count, const char *format, va_list arg); +size_t BLI_vsnprintf(char *__restrict buffer, size_t count, const char *__restrict format, va_list arg) +#ifdef __GNUC__ +__attribute__ ((format(printf, 3, 0))) +#endif +; /* * Print formatted string into a newly mallocN'd string * and return it. */ -char *BLI_sprintfN(const char *format, ...) +char *BLI_sprintfN(const char *__restrict format, ...) #ifdef __GNUC__ __attribute__ ((format(printf, 1, 2))) __attribute__((warn_unused_result)) @@ -158,7 +162,7 @@ __attribute__((nonnull)) #endif ; -size_t BLI_strescape(char *dst, const char *src, const size_t maxlen) +size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) #ifdef __GNUC__ __attribute__((nonnull)) #endif @@ -200,7 +204,7 @@ __attribute__((warn_unused_result)) __attribute__((nonnull)) #endif ; -size_t BLI_strnlen(const char *str, size_t maxlen) +size_t BLI_strnlen(const char *str, const size_t maxlen) #ifdef __GNUC__ __attribute__((warn_unused_result)) __attribute__((nonnull)) @@ -212,12 +216,12 @@ __attribute__((nonnull)) #endif ; /* time var is global */ -void BLI_ascii_strtolower(char *str, int len) +void BLI_ascii_strtolower(char *str, const size_t len) #ifdef __GNUC__ __attribute__((nonnull)) #endif ; -void BLI_ascii_strtoupper(char *str, int len) +void BLI_ascii_strtoupper(char *str, const size_t len) #ifdef __GNUC__ __attribute__((nonnull)) #endif diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h index 56ed4beba53..73f138a750d 100644 --- a/source/blender/blenlib/BLI_string_utf8.h +++ b/source/blender/blenlib/BLI_string_utf8.h @@ -31,16 +31,16 @@ extern "C" { #endif -char *BLI_strncpy_utf8(char *dst, const char *src, size_t maxncpy); -char *BLI_strncat_utf8(char *dst, const char *src, size_t maxncpy); +char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy); +char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy); int BLI_utf8_invalid_byte(const char *str, int length); int BLI_utf8_invalid_strip(char *str, int length); int BLI_str_utf8_size(const char *p); /* warning, can return -1 on bad chars */ /* copied from glib */ unsigned int BLI_str_utf8_as_unicode(const char *p); -unsigned int BLI_str_utf8_as_unicode_and_size(const char *p, size_t *index); -unsigned int BLI_str_utf8_as_unicode_step(const char *p, size_t *index); +unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index); +unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index); size_t BLI_str_utf8_from_unicode(unsigned int c, char *outbuf); char *BLI_str_find_prev_char_utf8(const char *str, const char *p); @@ -50,8 +50,9 @@ char *BLI_str_prev_char_utf8(const char *p); /* wchar_t functions, copied from blenders own font.c originally */ size_t BLI_wstrlen_utf8(const wchar_t *src); size_t BLI_strlen_utf8(const char *strc); -size_t BLI_strncpy_wchar_as_utf8(char *dst, const wchar_t *src, const size_t maxcpy); -size_t BLI_strncpy_wchar_from_utf8(wchar_t *dst, const char *src, const size_t maxcpy); +size_t BLI_strnlen_utf8(const char *start, const size_t maxlen); +size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, const size_t maxcpy); +size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst, const char *__restrict src, const size_t maxcpy); #define BLI_UTF8_MAX 6 #define BLI_UTF8_ERR ((unsigned int)-1) diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index 29097a4c6c3..056fa916da1 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -40,43 +40,22 @@ # define TRUE 1 #endif - -#define ELEM(a, b, c) ((a) == (b) || (a) == (c)) -#define ELEM3(a, b, c, d) (ELEM(a, b, c) || (a) == (d) ) -#define ELEM4(a, b, c, d, e) (ELEM(a, b, c) || ELEM(a, d, e) ) -#define ELEM5(a, b, c, d, e, f) (ELEM(a, b, c) || ELEM3(a, d, e, f) ) -#define ELEM6(a, b, c, d, e, f, g) (ELEM(a, b, c) || ELEM4(a, d, e, f, g) ) -#define ELEM7(a, b, c, d, e, f, g, h) (ELEM3(a, b, c, d) || ELEM4(a, e, f, g, h) ) -#define ELEM8(a, b, c, d, e, f, g, h, i) (ELEM4(a, b, c, d, e) || ELEM4(a, f, g, h, i) ) -#define ELEM9(a, b, c, d, e, f, g, h, i, j) (ELEM4(a, b, c, d, e) || ELEM5(a, f, g, h, i, j) ) -#define ELEM10(a, b, c, d, e, f, g, h, i, j, k) (ELEM4(a, b, c, d, e) || ELEM6(a, f, g, h, i, j, k) ) -#define ELEM11(a, b, c, d, e, f, g, h, i, j, k, l) (ELEM4(a, b, c, d, e) || ELEM7(a, f, g, h, i, j, k, l) ) - -/* shift around elements */ -#define SHIFT3(type, a, b, c) { \ - type tmp; \ - tmp = a; \ - a = c; \ - c = b; \ - b = tmp; \ -} (void)0 -#define SHIFT4(type, a, b, c, d) { \ - type tmp; \ - tmp = a; \ - a = d; \ - d = c; \ - c = b; \ - b = tmp; \ -} (void)0 +/* useful for finding bad use of min/max */ +#if 0 +/* gcc only */ +# define _TYPECHECK(a, b) ((void)(((typeof(a) *)0) == ((typeof(b) *)0))) +# define MIN2(x, y) (_TYPECHECK(x, y), (((x) < (y) ? (x) : (y)))) +# define MAX2(x, y) (_TYPECHECK(x, y), (((x) > (y) ? (x) : (y)))) +#endif /* min/max */ -#define MIN2(x, y) ( (x) < (y) ? (x) : (y) ) -#define MIN3(x, y, z) MIN2(MIN2((x), (y)), (z) ) -#define MIN4(x, y, z, a) MIN2(MIN2((x), (y)), MIN2((z), (a)) ) +#define MIN2(x, y) ((x) < (y) ? (x) : (y)) +#define MIN3(x, y, z) (MIN2(MIN2((x), (y)), (z))) +#define MIN4(x, y, z, a) (MIN2(MIN2((x), (y)), MIN2((z), (a)))) -#define MAX2(x, y) ( (x) > (y) ? (x) : (y) ) -#define MAX3(x, y, z) MAX2(MAX2((x), (y)), (z) ) -#define MAX4(x, y, z, a) MAX2(MAX2((x), (y)), MAX2((z), (a)) ) +#define MAX2(x, y) ((x) > (y) ? (x) : (y)) +#define MAX3(x, y, z) (MAX2(MAX2((x), (y)), (z))) +#define MAX4(x, y, z, a) (MAX2(MAX2((x), (y)), MAX2((z), (a)))) #define INIT_MINMAX(min, max) { \ (min)[0] = (min)[1] = (min)[2] = 1.0e30f; \ @@ -116,20 +95,28 @@ /* Causes warning: * incompatible types when assigning to type 'Foo' from type 'Bar' * ... the compiler optimizes away the temp var */ -#ifndef CHECK_TYPE #ifdef __GNUC__ #define CHECK_TYPE(var, type) { \ __typeof(var) *__tmp; \ __tmp = (type *)NULL; \ (void)__tmp; \ } (void)0 + +#define CHECK_TYPE_PAIR(var_a, var_b) { \ + __typeof(var_a) *__tmp; \ + __tmp = (__typeof(var_b) *)NULL; \ + (void)__tmp; \ +} (void)0 #else -#define CHECK_TYPE(var, type) -#endif +# define CHECK_TYPE(var, type) +# define CHECK_TYPE_PAIR(var_a, var_b) #endif -#ifndef SWAP -# define SWAP(type, a, b) { \ +/* can be used in simple macros */ +#define CHECK_TYPE_INLINE(val, type) \ + ((void)(((type *)0) != (val))) + +#define SWAP(type, a, b) { \ type sw_ap; \ CHECK_TYPE(a, type); \ CHECK_TYPE(b, type); \ @@ -137,7 +124,53 @@ (a) = (b); \ (b) = sw_ap; \ } (void)0 -#endif + +/* swap with a temp value */ +#define SWAP_TVAL(tval, a, b) { \ + CHECK_TYPE_PAIR(tval, a); \ + CHECK_TYPE_PAIR(tval, b); \ + (tval) = (a); \ + (a) = (b); \ + (b) = (tval); \ +} (void)0 + + +#define ELEM(a, b, c) ((a) == (b) || (a) == (c)) +#define ELEM3(a, b, c, d) (ELEM(a, b, c) || (a) == (d) ) +#define ELEM4(a, b, c, d, e) (ELEM(a, b, c) || ELEM(a, d, e) ) +#define ELEM5(a, b, c, d, e, f) (ELEM(a, b, c) || ELEM3(a, d, e, f) ) +#define ELEM6(a, b, c, d, e, f, g) (ELEM(a, b, c) || ELEM4(a, d, e, f, g) ) +#define ELEM7(a, b, c, d, e, f, g, h) (ELEM3(a, b, c, d) || ELEM4(a, e, f, g, h) ) +#define ELEM8(a, b, c, d, e, f, g, h, i) (ELEM4(a, b, c, d, e) || ELEM4(a, f, g, h, i) ) +#define ELEM9(a, b, c, d, e, f, g, h, i, j) (ELEM4(a, b, c, d, e) || ELEM5(a, f, g, h, i, j) ) +#define ELEM10(a, b, c, d, e, f, g, h, i, j, k) (ELEM4(a, b, c, d, e) || ELEM6(a, f, g, h, i, j, k) ) +#define ELEM11(a, b, c, d, e, f, g, h, i, j, k, l) (ELEM4(a, b, c, d, e) || ELEM7(a, f, g, h, i, j, k, l) ) + +/* shift around elements */ +#define SHIFT3(type, a, b, c) { \ + type tmp; \ + CHECK_TYPE(a, type); \ + CHECK_TYPE(b, type); \ + CHECK_TYPE(c, type); \ + tmp = a; \ + a = c; \ + c = b; \ + b = tmp; \ +} (void)0 + +#define SHIFT4(type, a, b, c, d) { \ + type tmp; \ + CHECK_TYPE(a, type); \ + CHECK_TYPE(b, type); \ + CHECK_TYPE(c, type); \ + CHECK_TYPE(d, type); \ + tmp = a; \ + a = d; \ + d = c; \ + c = b; \ + b = tmp; \ +} (void)0 + #define ABS(a) ( (a) < 0 ? (-(a)) : (a) ) @@ -189,6 +222,11 @@ *(v1 + 1) = *(v2 + 1) + *(v3 + 1) * (fac); \ *(v1 + 2) = *(v2 + 2) + *(v3 + 2) * (fac); \ } (void)0 +#define VECMADD(v1, v2, v3, v4) { \ + *(v1) = *(v2) + *(v3) * (*(v4)); \ + *(v1 + 1) = *(v2 + 1) + *(v3 + 1) * (*(v4 + 1)); \ + *(v1 + 2) = *(v2 + 2) + *(v3 + 2) * (*(v4 + 2)); \ +} (void)0 #define VECSUBFAC(v1, v2, v3, fac) { \ *(v1) = *(v2) - *(v3) * (fac); \ *(v1 + 1) = *(v2 + 1) - *(v3 + 1) * (fac); \ @@ -317,6 +355,13 @@ # define BLI_assert(a) (void)0 #endif +#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) /* gcc4.6+ only */ +# define BLI_STATIC_ASSERT(a, msg) _Static_assert(a, msg); +#else + /* TODO msvc, clang */ +# define BLI_STATIC_ASSERT(a, msg) +#endif + /* hints for branch pradiction, only use in code that runs a _lot_ where */ #ifdef __GNUC__ # define LIKELY(x) __builtin_expect(!!(x), 1) @@ -326,4 +371,4 @@ # define UNLIKELY(x) (x) #endif -#endif // __BLI_UTILDEFINES_H__ +#endif /* __BLI_UTILDEFINES_H__ */ diff --git a/source/blender/blenlib/BLI_voronoi.h b/source/blender/blenlib/BLI_voronoi.h index a67b01c5175..68d7398d89b 100644 --- a/source/blender/blenlib/BLI_voronoi.h +++ b/source/blender/blenlib/BLI_voronoi.h @@ -49,7 +49,7 @@ typedef struct VoronoiEdge { float left[2]; /* point on Voronoi place on the left side of edge */ float right[2]; /* point on Voronoi place on the right side of edge */ - float f, g; /* directional coeffitients satisfying equation y = f*x + g (edge lies on this line) */ + float f, g; /* directional coeffitients satisfying equation y = f * x + g (edge lies on this line) */ /* some edges consist of two parts, so we add the pointer to another part to connect them at the end of an algorithm */ struct VoronoiEdge *neighbour; diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 2836174be73..6839f05bfbc 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -78,6 +78,7 @@ set(SRC intern/noise.c intern/path_util.c intern/pbvh.c + intern/quadric.c intern/rand.c intern/rct.c intern/scanfill.c @@ -90,8 +91,8 @@ set(SRC intern/threads.c intern/time.c intern/uvproject.c - intern/voxel.c intern/voronoi.c + intern/voxel.c intern/winstuff.c BLI_args.h @@ -135,6 +136,7 @@ set(SRC BLI_noise.h BLI_path_util.h BLI_pbvh.h + BLI_quadric.h BLI_rand.h BLI_rect.h BLI_scanfill.h diff --git a/source/blender/blenlib/PIL_time.h b/source/blender/blenlib/PIL_time.h index 288d2fe78e5..b8f895c5c82 100644 --- a/source/blender/blenlib/PIL_time.h +++ b/source/blender/blenlib/PIL_time.h @@ -30,7 +30,6 @@ * \brief Platform independent time functions. */ - #ifndef __PIL_TIME_H__ #define __PIL_TIME_H__ @@ -61,20 +60,24 @@ void PIL_sleep_ms(int ms); double _timeit_##var = PIL_check_seconds_timer(); \ printf("time start (" #var "): " AT "\n"); \ fflush(stdout); \ - { (void)0 \ - + { (void)0 #define TIMEIT_VALUE(var) (float)(PIL_check_seconds_timer() - _timeit_##var) +#define TIMEIT_VALUE_PRINT(var) \ + { \ + printf("time update(" #var "): %.6f" " " AT "\n", TIMEIT_VALUE(var));\ + fflush(stdout); \ + } (void)0 #define TIMEIT_END(var) \ } \ - printf("time end (" #var "): %.6f" " " AT "\n", TIMEIT_VALUE(var)); \ + printf("time end (" #var "): %.6f" " " AT "\n", TIMEIT_VALUE(var)); \ fflush(stdout); \ -} (void)0 \ +} (void)0 #ifdef __cplusplus } #endif -#endif /* !__PIL_TIME_H__ */ +#endif /* !__PIL_TIME_H__ */ diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 844407f9e06..0cae9bab531 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -135,7 +135,7 @@ int BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFre BLI_mempool_free(gh->entrypool, e); /* correct but 'e' isn't used before return */ - /* e= n; *//*UNUSED*/ + /* e = n; *//*UNUSED*/ if (p) p->next = n; else gh->buckets[hash] = n; @@ -165,7 +165,7 @@ void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp) BLI_mempool_free(gh->entrypool, e); /* correct but 'e' isn't used before return */ - /* e= n; *//*UNUSED*/ + /* e = n; *//*UNUSED*/ if (p) p->next = n; else gh->buckets[hash] = n; diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c index c1175192434..dcc028630e2 100644 --- a/source/blender/blenlib/intern/BLI_heap.c +++ b/source/blender/blenlib/intern/BLI_heap.c @@ -40,9 +40,9 @@ /***/ struct HeapNode { - void *ptr; - float value; - int index; + void *ptr; + float value; + unsigned int index; }; struct Heap { @@ -54,48 +54,43 @@ struct Heap { HeapNode **tree; }; +/* internal functions */ + #define HEAP_PARENT(i) ((i - 1) >> 1) #define HEAP_LEFT(i) ((i << 1) + 1) #define HEAP_RIGHT(i) ((i << 1) + 2) #define HEAP_COMPARE(a, b) (a->value < b->value) + +#if 0 /* UNUSED */ #define HEAP_EQUALS(a, b) (a->value == b->value) -#define HEAP_SWAP(heap, i, j) \ - { \ - SWAP(int, heap->tree[i]->index, heap->tree[j]->index); \ - SWAP(HeapNode *, heap->tree[i], heap->tree[j]); \ - } (void)0 +#endif -/***/ - -Heap *BLI_heap_new(void) +BLI_INLINE void heap_swap(Heap *heap, const unsigned int i, const unsigned int j) { - Heap *heap = (Heap *)MEM_callocN(sizeof(Heap), __func__); - heap->bufsize = 1; - heap->tree = (HeapNode **)MEM_mallocN(sizeof(HeapNode *), "BLIHeapTree"); - heap->arena = BLI_memarena_new(1 << 16, "heap arena"); - return heap; +#if 0 + SWAP(unsigned int, heap->tree[i]->index, heap->tree[j]->index); + SWAP(HeapNode *, heap->tree[i], heap->tree[j]); +#else + HeapNode **tree = heap->tree; + union { + unsigned int index; + HeapNode *node; + } tmp; + SWAP_TVAL(tmp.index, tree[i]->index, tree[j]->index); + SWAP_TVAL(tmp.node, tree[i], tree[j]); +#endif } -void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp) +static void heap_down(Heap *heap, unsigned int i) { - int i; + /* size won't change in the loop */ + const unsigned int size = heap->size; - if (ptrfreefp) - for (i = 0; i < heap->size; i++) - ptrfreefp(heap->tree[i]->ptr); - - MEM_freeN(heap->tree); - BLI_memarena_free(heap->arena); - MEM_freeN(heap); -} - -static void BLI_heap_down(Heap *heap, int i) -{ while (1) { - int size = heap->size, smallest; - int l = HEAP_LEFT(i); - int r = HEAP_RIGHT(i); + const unsigned int l = HEAP_LEFT(i); + const unsigned int r = HEAP_RIGHT(i); + unsigned int smallest; smallest = ((l < size) && HEAP_COMPARE(heap->tree[l], heap->tree[i])) ? l : i; @@ -105,46 +100,75 @@ static void BLI_heap_down(Heap *heap, int i) if (smallest == i) break; - HEAP_SWAP(heap, i, smallest); + heap_swap(heap, i, smallest); i = smallest; } } -static void BLI_heap_up(Heap *heap, int i) +static void heap_up(Heap *heap, unsigned int i) { while (i > 0) { - int p = HEAP_PARENT(i); + const unsigned int p = HEAP_PARENT(i); if (HEAP_COMPARE(heap->tree[p], heap->tree[i])) break; - HEAP_SWAP(heap, p, i); + heap_swap(heap, p, i); i = p; } } + +/***/ + +/* use when the size of the heap is known in advance */ +Heap *BLI_heap_new_ex(unsigned int tot_reserve) +{ + Heap *heap = (Heap *)MEM_callocN(sizeof(Heap), __func__); + /* ensure we have at least one so we can keep doubling it */ + heap->bufsize = MAX2(1, tot_reserve); + heap->tree = (HeapNode **)MEM_mallocN(heap->bufsize * sizeof(HeapNode *), "BLIHeapTree"); + heap->arena = BLI_memarena_new(1 << 16, "heap arena"); + + return heap; +} + +Heap *BLI_heap_new(void) +{ + return BLI_heap_new_ex(1); +} + +void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp) +{ + unsigned int i; + + if (ptrfreefp) { + for (i = 0; i < heap->size; i++) { + ptrfreefp(heap->tree[i]->ptr); + } + } + + MEM_freeN(heap->tree); + BLI_memarena_free(heap->arena); + MEM_freeN(heap); +} + HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr) { HeapNode *node; - if ((heap->size + 1) > heap->bufsize) { - int newsize = heap->bufsize * 2; - HeapNode **newtree; - - newtree = (HeapNode **)MEM_mallocN(newsize * sizeof(*newtree), __func__); - memcpy(newtree, heap->tree, sizeof(HeapNode *) * heap->size); - MEM_freeN(heap->tree); - - heap->tree = newtree; - heap->bufsize = newsize; + if (UNLIKELY((heap->size + 1) > heap->bufsize)) { + heap->bufsize *= 2; + heap->tree = MEM_reallocN(heap->tree, heap->bufsize * sizeof(*heap->tree)); } if (heap->freenodes) { node = heap->freenodes; heap->freenodes = (HeapNode *)(((HeapNode *)heap->freenodes)->ptr); } - else + else { node = (HeapNode *)BLI_memarena_alloc(heap->arena, sizeof *node); + } node->value = value; node->ptr = ptr; @@ -154,17 +178,17 @@ HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr) heap->size++; - BLI_heap_up(heap, heap->size - 1); + heap_up(heap, heap->size - 1); return node; } -int BLI_heap_empty(Heap *heap) +int BLI_heap_is_empty(Heap *heap) { return (heap->size == 0); } -int BLI_heap_size(Heap *heap) +unsigned int BLI_heap_size(Heap *heap) { return heap->size; } @@ -181,13 +205,14 @@ void *BLI_heap_popmin(Heap *heap) heap->tree[0]->ptr = heap->freenodes; heap->freenodes = heap->tree[0]; - if (heap->size == 1) + if (UNLIKELY(heap->size == 1)) { heap->size--; + } else { - HEAP_SWAP(heap, 0, heap->size - 1); + heap_swap(heap, 0, heap->size - 1); heap->size--; - BLI_heap_down(heap, 0); + heap_down(heap, 0); } return ptr; @@ -195,12 +220,12 @@ void *BLI_heap_popmin(Heap *heap) void BLI_heap_remove(Heap *heap, HeapNode *node) { - int i = node->index; + unsigned int i = node->index; while (i > 0) { - int p = HEAP_PARENT(i); + unsigned int p = HEAP_PARENT(i); - HEAP_SWAP(heap, p, i); + heap_swap(heap, p, i); i = p; } diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 2b3c314131b..70617453eff 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -42,7 +42,8 @@ #endif #define MAX_TREETYPE 32 -#define DEFAULT_FIND_NEAREST_HEAP_SIZE 1024 + +typedef unsigned char axis_t; typedef struct BVHNode { struct BVHNode **children; @@ -54,6 +55,7 @@ typedef struct BVHNode { char main_axis; /* Axis used to split this node */ } BVHNode; +/* keep under 26 bytes for speed purposes */ struct BVHTree { BVHNode **nodes; BVHNode *nodearray; /* pre-alloc branch nodes */ @@ -62,16 +64,21 @@ struct BVHTree { float epsilon; /* epslion is used for inflation of the k-dop */ int totleaf; /* leafs */ int totbranch; + axis_t start_axis, stop_axis; /* KDOP_AXES array indices according to axis */ + axis_t axis; /* kdop type (6 => OBB, 7 => AABB, ...) */ char tree_type; /* type of tree (4 => quadtree) */ - char axis; /* kdop type (6 => OBB, 7 => AABB, ...) */ - char start_axis, stop_axis; /* KDOP_AXES array indices according to axis */ }; +/* optimization, ensure we stay small */ +BLI_STATIC_ASSERT((sizeof(void *) == 8 && sizeof(BVHTree) <= 48) || + (sizeof(void *) == 4 && sizeof(BVHTree) <= 32), + "over sized"); + typedef struct BVHOverlapData { BVHTree *tree1, *tree2; BVHTreeOverlap *overlap; int i, max_overlap; /* i is number of overlaps */ - int start_axis, stop_axis; + axis_t start_axis, stop_axis; } BVHOverlapData; typedef struct BVHNearestData { @@ -114,6 +121,17 @@ static float KDOP_AXES[13][3] = { {0, 1.0, -1.0} }; +MINLINE axis_t min_axis(axis_t a, axis_t b) +{ + return (a < b) ? a : b; +} +MINLINE axis_t max_axis(axis_t a, axis_t b) +{ + return (b < a) ? a : b; +} + +#if 0 + /* * Generic push and pop heap */ @@ -153,7 +171,6 @@ static float KDOP_AXES[13][3] = { heap[parent] = element; \ } (void)0 -#if 0 static int ADJUST_MEMORY(void *local_memblock, void **memblock, int new_size, int *max_size, int size_per_item) { int new_max_size = *max_size * 2; @@ -269,7 +286,7 @@ static void bvh_heapsort(BVHNode **a, int lo, int hi, int axis) } #endif -static BVHNode *bvh_medianof3(BVHNode **a, int lo, int mid, int hi, int axis) // returns Sortable +static BVHNode *bvh_medianof3(BVHNode **a, int lo, int mid, int hi, int axis) /* returns Sortable */ { if ((a[mid])->bv[axis] < (a[lo])->bv[axis]) { if ((a[hi])->bv[axis] < (a[mid])->bv[axis]) @@ -374,24 +391,25 @@ static void create_kdop_hull(BVHTree *tree, BVHNode *node, const float *co, int { float newminmax; float *bv = node->bv; - int i, k; + int k; + axis_t axis_iter; /* don't init boudings for the moving case */ if (!moving) { - for (i = tree->start_axis; i < tree->stop_axis; i++) { - bv[2 * i] = FLT_MAX; - bv[2 * i + 1] = -FLT_MAX; + for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { + bv[2 * axis_iter] = FLT_MAX; + bv[2 * axis_iter + 1] = -FLT_MAX; } } for (k = 0; k < numpoints; k++) { /* for all Axes. */ - for (i = tree->start_axis; i < tree->stop_axis; i++) { - newminmax = dot_v3v3(&co[k * 3], KDOP_AXES[i]); - if (newminmax < bv[2 * i]) - bv[2 * i] = newminmax; - if (newminmax > bv[(2 * i) + 1]) - bv[(2 * i) + 1] = newminmax; + for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { + newminmax = dot_v3v3(&co[k * 3], KDOP_AXES[axis_iter]); + if (newminmax < bv[2 * axis_iter]) + bv[2 * axis_iter] = newminmax; + if (newminmax > bv[(2 * axis_iter) + 1]) + bv[(2 * axis_iter) + 1] = newminmax; } } } @@ -400,25 +418,25 @@ static void create_kdop_hull(BVHTree *tree, BVHNode *node, const float *co, int static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end) { float newmin, newmax; - int i, j; float *bv = node->bv; + int j; + axis_t axis_iter; - - for (i = tree->start_axis; i < tree->stop_axis; i++) { - bv[2 * i] = FLT_MAX; - bv[2 * i + 1] = -FLT_MAX; + for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { + bv[(2 * axis_iter)] = FLT_MAX; + bv[(2 * axis_iter) + 1] = -FLT_MAX; } for (j = start; j < end; j++) { /* for all Axes. */ - for (i = tree->start_axis; i < tree->stop_axis; i++) { - newmin = tree->nodes[j]->bv[(2 * i)]; - if ((newmin < bv[(2 * i)])) - bv[(2 * i)] = newmin; - - newmax = tree->nodes[j]->bv[(2 * i) + 1]; - if ((newmax > bv[(2 * i) + 1])) - bv[(2 * i) + 1] = newmax; + for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { + newmin = tree->nodes[j]->bv[(2 * axis_iter)]; + if ((newmin < bv[(2 * axis_iter)])) + bv[(2 * axis_iter)] = newmin; + + newmax = tree->nodes[j]->bv[(2 * axis_iter) + 1]; + if ((newmax > bv[(2 * axis_iter) + 1])) + bv[(2 * axis_iter) + 1] = newmax; } } @@ -451,23 +469,24 @@ static char get_largest_axis(float *bv) * join the children on the parent BV */ static void node_join(BVHTree *tree, BVHNode *node) { - int i, j; - - for (i = tree->start_axis; i < tree->stop_axis; i++) { - node->bv[2 * i] = FLT_MAX; - node->bv[2 * i + 1] = -FLT_MAX; + int i; + axis_t axis_iter; + + for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { + node->bv[(2 * axis_iter)] = FLT_MAX; + node->bv[(2 * axis_iter) + 1] = -FLT_MAX; } for (i = 0; i < tree->tree_type; i++) { if (node->children[i]) { - for (j = tree->start_axis; j < tree->stop_axis; j++) { + for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { /* update minimum */ - if (node->children[i]->bv[(2 * j)] < node->bv[(2 * j)]) - node->bv[(2 * j)] = node->children[i]->bv[(2 * j)]; + if (node->children[i]->bv[(2 * axis_iter)] < node->bv[(2 * axis_iter)]) + node->bv[(2 * axis_iter)] = node->children[i]->bv[(2 * axis_iter)]; /* update maximum */ - if (node->children[i]->bv[(2 * j) + 1] > node->bv[(2 * j) + 1]) - node->bv[(2 * j) + 1] = node->children[i]->bv[(2 * j) + 1]; + if (node->children[i]->bv[(2 * axis_iter) + 1] > node->bv[(2 * axis_iter) + 1]) + node->bv[(2 * axis_iter) + 1] = node->children[i]->bv[(2 * axis_iter) + 1]; } } else @@ -482,10 +501,12 @@ static void node_join(BVHTree *tree, BVHNode *node) static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth) { int i; + axis_t axis_iter; + for (i = 0; i < depth; i++) printf(" "); printf(" - %d (%ld): ", node->index, node - tree->nodearray); - for (i = 2 * tree->start_axis; i < 2 * tree->stop_axis; i++) - printf("%.3f ", node->bv[i]); + for (axis_iter = 2 * tree->start_axis; axis_iter < 2 * tree->stop_axis; axis_iter++) + printf("%.3f ", node->bv[axis_iter]); printf("\n"); for (i = 0; i < tree->tree_type; i++) @@ -645,10 +666,10 @@ static int implicit_leafs_index(BVHBuildHelper *data, int depth, int child_index * (looping elements, knowing if its a leaf or not.. etc...) */ -// This functions returns the number of branches needed to have the requested number of leafs. +/* This functions returns the number of branches needed to have the requested number of leafs. */ static int implicit_needed_branches(int tree_type, int leafs) { - return maxi(1, (leafs + tree_type - 3) / (tree_type - 1) ); + return max_ii(1, (leafs + tree_type - 3) / (tree_type - 1) ); } /* @@ -705,8 +726,8 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, BVHNode *tmp = branches_array + 0; tmp->parent = NULL; - /*Most of bvhtree code relies on 1-leaf trees having at least one branch - *We handle that special case here */ + /* Most of bvhtree code relies on 1-leaf trees having at least one branch + * We handle that special case here */ if (num_leafs == 1) { BVHNode *root = branches_array + 0; refit_kdop_hull(tree, root, 0, num_leafs); @@ -724,7 +745,7 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, /* Loop tree levels (log N) loops */ for (i = 1, depth = 1; i <= num_branches; i = i * tree_type + tree_offset, depth++) { const int first_of_next_level = i * tree_type + tree_offset; - const int end_j = MIN2(first_of_next_level, num_branches + 1); /* index of last branch on this level */ + const int end_j = min_ii(first_of_next_level, num_branches + 1); /* index of last branch on this level */ int j; /* Loop all branches on this level */ @@ -810,7 +831,7 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) /* tree epsilon must be >= FLT_EPSILON * so that tangent rays can still hit a bounding volume.. * this bug would show up when casting a ray aligned with a kdop-axis and with an edge of 2 faces */ - epsilon = MAX2(FLT_EPSILON, epsilon); + epsilon = max_ff(FLT_EPSILON, epsilon); if (tree) { tree->epsilon = epsilon; @@ -843,7 +864,7 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) } - //Allocate arrays + /* Allocate arrays */ numnodes = maxsize + implicit_needed_branches(tree_type, maxsize) + tree_type; tree->nodes = (BVHNode **)MEM_callocN(sizeof(BVHNode *) * numnodes, "BVHNodes"); @@ -876,7 +897,7 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) return NULL; } - //link the dynamic bv and child links + /* link the dynamic bv and child links */ for (i = 0; i < numnodes; i++) { tree->nodearray[i].bv = tree->nodebv + i * axis; tree->nodearray[i].children = tree->nodechild + i * tree_type; @@ -921,9 +942,9 @@ void BLI_bvhtree_balance(BVHTree *tree) /* bvhtree_info(tree); */ } -int BLI_bvhtree_insert(BVHTree *tree, int index, const float *co, int numpoints) +int BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints) { - int i; + axis_t axis_iter; BVHNode *node = NULL; /* insert should only possible as long as tree->totbranch is 0 */ @@ -942,9 +963,9 @@ int BLI_bvhtree_insert(BVHTree *tree, int index, const float *co, int numpoints) node->index = index; /* inflate the bv with some epsilon */ - for (i = tree->start_axis; i < tree->stop_axis; i++) { - node->bv[(2 * i)] -= tree->epsilon; /* minimum */ - node->bv[(2 * i) + 1] += tree->epsilon; /* maximum */ + for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { + node->bv[(2 * axis_iter)] -= tree->epsilon; /* minimum */ + node->bv[(2 * axis_iter) + 1] += tree->epsilon; /* maximum */ } return 1; @@ -952,10 +973,10 @@ int BLI_bvhtree_insert(BVHTree *tree, int index, const float *co, int numpoints) /* call before BLI_bvhtree_update_tree() */ -int BLI_bvhtree_update_node(BVHTree *tree, int index, const float *co, const float *co_moving, int numpoints) +int BLI_bvhtree_update_node(BVHTree *tree, int index, const float co[3], const float co_moving[3], int numpoints) { - int i; BVHNode *node = NULL; + axis_t axis_iter; /* check if index exists */ if (index > tree->totleaf) @@ -968,10 +989,10 @@ int BLI_bvhtree_update_node(BVHTree *tree, int index, const float *co, const flo if (co_moving) create_kdop_hull(tree, node, co_moving, numpoints, 1); - // inflate the bv with some epsilon - for (i = tree->start_axis; i < tree->stop_axis; i++) { - node->bv[(2 * i)] -= tree->epsilon; // minimum - node->bv[(2 * i) + 1] += tree->epsilon; // maximum + /* inflate the bv with some epsilon */ + for (axis_iter = tree->start_axis; axis_iter < tree->stop_axis; axis_iter++) { + node->bv[(2 * axis_iter)] -= tree->epsilon; /* minimum */ + node->bv[(2 * axis_iter) + 1] += tree->epsilon; /* maximum */ } return 1; @@ -991,7 +1012,7 @@ void BLI_bvhtree_update_tree(BVHTree *tree) node_join(tree, *index); } -float BLI_bvhtree_getepsilon(BVHTree *tree) +float BLI_bvhtree_getepsilon(const BVHTree *tree) { return tree->epsilon; } @@ -1001,7 +1022,7 @@ float BLI_bvhtree_getepsilon(BVHTree *tree) * BLI_bvhtree_overlap * * overlap - is it possible for 2 bv's to collide ? */ -static int tree_overlap(BVHNode *node1, BVHNode *node2, int start_axis, int stop_axis) +static int tree_overlap(BVHNode *node1, BVHNode *node2, axis_t start_axis, axis_t stop_axis) { float *bv1 = node1->bv; float *bv2 = node2->bv; @@ -1045,7 +1066,7 @@ static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2) data->max_overlap *= 2; } - // both leafs, insert overlap! + /* both leafs, insert overlap! */ data->overlap[data->i].indexA = node1->index; data->overlap[data->i].indexB = node2->index; @@ -1075,27 +1096,31 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int BVHTreeOverlap *overlap = NULL, *to = NULL; BVHOverlapData **data; - // check for compatibility of both trees (can't compare 14-DOP with 18-DOP) + /* check for compatibility of both trees (can't compare 14-DOP with 18-DOP) */ if ((tree1->axis != tree2->axis) && (tree1->axis == 14 || tree2->axis == 14) && (tree1->axis == 18 || tree2->axis == 18)) return NULL; - // fast check root nodes for collision before doing big splitting + traversal - if (!tree_overlap(tree1->nodes[tree1->totleaf], tree2->nodes[tree2->totleaf], MIN2(tree1->start_axis, tree2->start_axis), MIN2(tree1->stop_axis, tree2->stop_axis))) + /* fast check root nodes for collision before doing big splitting + traversal */ + if (!tree_overlap(tree1->nodes[tree1->totleaf], tree2->nodes[tree2->totleaf], + min_axis(tree1->start_axis, tree2->start_axis), + min_axis(tree1->stop_axis, tree2->stop_axis))) + { return NULL; + } data = MEM_callocN(sizeof(BVHOverlapData *) * tree1->tree_type, "BVHOverlapData_star"); for (j = 0; j < tree1->tree_type; j++) { data[j] = (BVHOverlapData *)MEM_callocN(sizeof(BVHOverlapData), "BVHOverlapData"); - // init BVHOverlapData - data[j]->overlap = (BVHTreeOverlap *)malloc(sizeof(BVHTreeOverlap) * MAX2(tree1->totleaf, tree2->totleaf)); + /* init BVHOverlapData */ + data[j]->overlap = (BVHTreeOverlap *)malloc(sizeof(BVHTreeOverlap) * max_ii(tree1->totleaf, tree2->totleaf)); data[j]->tree1 = tree1; data[j]->tree2 = tree2; data[j]->max_overlap = MAX2(tree1->totleaf, tree2->totleaf); data[j]->i = 0; - data[j]->start_axis = MIN2(tree1->start_axis, tree2->start_axis); - data[j]->stop_axis = MIN2(tree1->stop_axis, tree2->stop_axis); + data[j]->start_axis = min_axis(tree1->start_axis, tree2->start_axis); + data[j]->stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis); } #pragma omp parallel for private(j) schedule(static) @@ -1123,13 +1148,13 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int return overlap; } -//Determines the nearest point of the given node BV. Returns the squared distance to that point. +/* Determines the nearest point of the given node BV. Returns the squared distance to that point. */ static float calc_nearest_point(const float proj[3], BVHNode *node, float *nearest) { int i; const float *bv = node->bv; - //nearest on AABB hull + /* nearest on AABB hull */ for (i = 0; i != 3; i++, bv += 2) { if (bv[0] > proj[i]) nearest[i] = bv[0]; @@ -1140,7 +1165,7 @@ static float calc_nearest_point(const float proj[3], BVHNode *node, float *neare } #if 0 - //nearest on a general hull + /* nearest on a general hull */ copy_v3_v3(nearest, data->co); for (i = data->tree->start_axis; i != data->tree->stop_axis; i++, bv += 2) { @@ -1167,9 +1192,7 @@ typedef struct NodeDistance { } NodeDistance; -#define NodeDistance_priority(a, b) ( (a).dist < (b).dist) - -// TODO: use a priority queue to reduce the number of nodes looked on +/* TODO: use a priority queue to reduce the number of nodes looked on */ static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node) { if (node->totnode == 0) { @@ -1181,7 +1204,7 @@ static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node) } } else { - //Better heuristic to pick the closest node to dive on + /* Better heuristic to pick the closest node to dive on */ int i; float nearest[3]; @@ -1211,6 +1234,11 @@ static void dfs_find_nearest_begin(BVHNearestData *data, BVHNode *node) #if 0 + +#define DEFAULT_FIND_NEAREST_HEAP_SIZE 1024 + +#define NodeDistance_priority(a, b) ( (a).dist < (b).dist) + static void NodeDistance_push_heap(NodeDistance *heap, int heap_size) PUSH_HEAP_BODY(NodeDistance, NodeDistance_priority, heap, heap_size) @@ -1256,7 +1284,7 @@ static void bfs_find_nearest(BVHNearestData *data, BVHNode *node) dfs_find_nearest_dfs(data, child); } else { - //adjust heap size + /* adjust heap size */ if ((heap_size >= max_heap_size) && ADJUST_MEMORY(default_heap, (void **)&heap, heap_size + 1, &max_heap_size, sizeof(heap[0])) == FALSE) { @@ -1296,22 +1324,23 @@ static void bfs_find_nearest(BVHNearestData *data, BVHNode *node) #endif -int BLI_bvhtree_find_nearest(BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata) +int BLI_bvhtree_find_nearest(BVHTree *tree, const float co[3], BVHTreeNearest *nearest, + BVHTree_NearestPointCallback callback, void *userdata) { - int i; + axis_t axis_iter; BVHNearestData data; BVHNode *root = tree->nodes[tree->totleaf]; - //init data to search + /* init data to search */ data.tree = tree; data.co = co; data.callback = callback; data.userdata = userdata; - for (i = data.tree->start_axis; i != data.tree->stop_axis; i++) { - data.proj[i] = dot_v3v3(data.co, KDOP_AXES[i]); + for (axis_iter = data.tree->start_axis; axis_iter != data.tree->stop_axis; axis_iter++) { + data.proj[axis_iter] = dot_v3v3(data.co, KDOP_AXES[axis_iter]); } if (nearest) { @@ -1343,7 +1372,7 @@ int BLI_bvhtree_find_nearest(BVHTree *tree, const float co[3], BVHTreeNearest *n /* Determines the distance that the ray must travel to hit the bounding volume of the given node */ -static float ray_nearest_hit(BVHRayCastData *data, const float *bv) +static float ray_nearest_hit(BVHRayCastData *data, const float bv[6]) { int i; @@ -1351,7 +1380,7 @@ static float ray_nearest_hit(BVHRayCastData *data, const float *bv) for (i = 0; i != 3; i++, bv += 2) { if (data->ray_dot_axis[i] == 0.0f) { - //axis aligned ray + /* axis aligned ray */ if (data->ray.origin[i] < bv[0] - data->ray.radius || data->ray.origin[i] > bv[1] + data->ray.radius) { @@ -1466,12 +1495,13 @@ static void iterative_raycast(BVHRayCastData *data, BVHNode *node) } else { node = node->children[0]; - } + } } } #endif -int BLI_bvhtree_ray_cast(BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) +int BLI_bvhtree_ray_cast(BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, + BVHTree_RayCastCallback callback, void *userdata) { int i; BVHRayCastData data; @@ -1521,14 +1551,14 @@ int BLI_bvhtree_ray_cast(BVHTree *tree, const float co[3], const float dir[3], f return data.hit.index; } -float BLI_bvhtree_bb_raycast(const float *bv, const float light_start[3], const float light_end[3], float pos[3]) +float BLI_bvhtree_bb_raycast(const float bv[6], const float light_start[3], const float light_end[3], float pos[3]) { BVHRayCastData data; float dist = 0.0; data.hit.dist = FLT_MAX; - // get light direction + /* get light direction */ data.ray.direction[0] = light_end[0] - light_start[0]; data.ray.direction[1] = light_end[1] - light_start[1]; data.ray.direction[2] = light_end[2] - light_start[2]; @@ -1560,7 +1590,7 @@ float BLI_bvhtree_bb_raycast(const float *bv, const float light_start[3], const typedef struct RangeQueryData { BVHTree *tree; const float *center; - float radius; //squared radius + float radius; /* squared radius */ int hits; @@ -1575,7 +1605,7 @@ static void dfs_range_query(RangeQueryData *data, BVHNode *node) { if (node->totnode == 0) { #if 0 /*UNUSED*/ - //Calculate the node min-coords (if the node was a point then this is the point coordinates) + /* Calculate the node min-coords (if the node was a point then this is the point coordinates) */ float co[3]; co[0] = node->bv[0]; co[1] = node->bv[2]; @@ -1588,7 +1618,7 @@ static void dfs_range_query(RangeQueryData *data, BVHNode *node) float nearest[3]; float dist = calc_nearest_point(data->center, node->children[i], nearest); if (dist < data->radius) { - //Its a leaf.. call the callback + /* Its a leaf.. call the callback */ if (node->children[i]->totnode == 0) { data->hits++; data->callback(data->userdata, node->children[i]->index, dist); diff --git a/source/blender/blenlib/intern/BLI_kdtree.c b/source/blender/blenlib/intern/BLI_kdtree.c index 19985c56b84..dd6c25ab6ad 100644 --- a/source/blender/blenlib/intern/BLI_kdtree.c +++ b/source/blender/blenlib/intern/BLI_kdtree.c @@ -30,16 +30,12 @@ * \ingroup bli */ - - #include "MEM_guardedalloc.h" #include "BLI_math.h" #include "BLI_kdtree.h" +#include "BLI_utildefines.h" -#ifndef SWAP -# define SWAP(type, a, b) { type sw_ap; sw_ap = (a); (a) = (b); (b) = sw_ap; } (void)0 -#endif typedef struct KDTreeNode { struct KDTreeNode *left, *right; @@ -132,7 +128,7 @@ void BLI_kdtree_balance(KDTree *tree) tree->root = kdtree_balance(tree->nodes, tree->totnode, 0); } -static float squared_distance(const float v2[3], const float v1[3], const float *UNUSED(n1), const float *n2) +static float squared_distance(const float v2[3], const float v1[3], const float UNUSED(n1[3]), const float n2[3]) { float d[3], dist; @@ -152,7 +148,7 @@ static float squared_distance(const float v2[3], const float v1[3], const float return dist; } -int BLI_kdtree_find_nearest(KDTree *tree, float *co, float *nor, KDTreeNearest *nearest) +int BLI_kdtree_find_nearest(KDTree *tree, const float co[3], const float nor[3], KDTreeNearest *nearest) { KDTreeNode *root, *node, *min_node; KDTreeNode **stack, *defaultstack[100]; diff --git a/source/blender/blenlib/intern/DLRB_tree.c b/source/blender/blenlib/intern/DLRB_tree.c index 930ab4fc400..688372b3a28 100644 --- a/source/blender/blenlib/intern/DLRB_tree.c +++ b/source/blender/blenlib/intern/DLRB_tree.c @@ -364,7 +364,7 @@ static void rotate_right(DLRBT_Tree *tree, DLRBT_Node *root) root_slot = &root->parent->right; } else - root_slot = ((DLRBT_Node **)&tree->root); /* &((DLRBT_Node*)tree->root); */ + root_slot = ((DLRBT_Node **)&tree->root); /* &((DLRBT_Node *)tree->root); */ /* - pivot's right child becomes root's left child * - root now becomes pivot's right child @@ -502,7 +502,7 @@ void BLI_dlrbTree_insert(DLRBT_Tree *tree, DLRBT_Node *node) /* ----- */ /* Add the given data to the tree, and return the node added */ -// NOTE: for duplicates, the update_cb is called (if available), and the existing node is returned +/* NOTE: for duplicates, the update_cb is called (if available), and the existing node is returned */ DLRBT_Node *BLI_dlrbTree_add(DLRBT_Tree *tree, DLRBT_Comparator_FP cmp_cb, DLRBT_NAlloc_FP new_cb, DLRBT_NUpdate_FP update_cb, void *data) { diff --git a/source/blender/blenlib/intern/boxpack2d.c b/source/blender/blenlib/intern/boxpack2d.c index 5da719cd500..8a97fdcab67 100644 --- a/source/blender/blenlib/intern/boxpack2d.c +++ b/source/blender/blenlib/intern/boxpack2d.c @@ -73,7 +73,9 @@ typedef struct BoxVert { ((b)->v[BR]->x = (b)->v[TR]->x) #define UPDATE_V34Y(b) ((b)->v[TL]->y = (b)->v[TR]->y); \ ((b)->v[BR]->y = (b)->v[BL]->y) -#define UPDATE_V34(b) UPDATE_V34X(b); UPDATE_V34Y(b) + +/* UNUSED */ +// #define UPDATE_V34(b) UPDATE_V34X(b); UPDATE_V34Y(b) #define SET_BOXLEFT(b, f) (b)->v[TR]->x = f + (b)->w; \ (b)->v[BL]->x = f; \ @@ -93,8 +95,8 @@ typedef struct BoxVert { BOXRIGHT(b1) - EPSILON <= BOXLEFT(b2) || \ BOXTOP(b1) - EPSILON <= BOXBOTTOM(b2)) -#define MIN2(x, y) ((x) < (y) ? (x) : (y)) -#define MAX2(x, y) ((x) > (y) ? (x) : (y)) +/* compiler should inline */ +static float max_ff(const float a, const float b) { return b > a ? b : a; } #if 0 #define BOXDEBUG(b) \ @@ -131,8 +133,8 @@ static int vertex_sort(const void *p1, const void *p2) v1 = vertarray + ((int *)p1)[0]; v2 = vertarray + ((int *)p2)[0]; - a1 = MAX2(v1->x + box_width, v1->y + box_height); - a2 = MAX2(v2->x + box_width, v2->y + box_height); + a1 = max_ff(v1->x + box_width, v1->y + box_height); + a2 = max_ff(v2->x + box_width, v2->y + box_height); /* sort largest to smallest */ if (a1 > a2) return 1; @@ -312,8 +314,8 @@ void BLI_box_pack_2D(BoxPack *boxarray, const int len, float *tot_width, float * if (!isect) { /* maintain the total width and height */ - (*tot_width) = MAX2(BOXRIGHT(box), (*tot_width)); - (*tot_height) = MAX2(BOXTOP(box), (*tot_height)); + (*tot_width) = max_ff(BOXRIGHT(box), (*tot_width)); + (*tot_height) = max_ff(BOXTOP(box), (*tot_height)); /* Place the box */ vert->free &= ~quad_flags[j]; diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c index be1f4eb3a35..8ae2b941fa8 100644 --- a/source/blender/blenlib/intern/bpath.c +++ b/source/blender/blenlib/intern/bpath.c @@ -85,7 +85,7 @@ static int checkMissingFiles_visit_cb(void *userdata, char *UNUSED(path_dst), co ReportList *reports = (ReportList *)userdata; if (!BLI_exists(path_src)) { - BKE_reportf(reports, RPT_WARNING, "Path Not Found \"%s\"", path_src); + BKE_reportf(reports, RPT_WARNING, "Path '%s' not found", path_src); } return FALSE; @@ -122,7 +122,7 @@ static int makeFilesRelative_visit_cb(void *userdata, char *path_dst, const char data->count_changed++; } else { - BKE_reportf(data->reports, RPT_WARNING, "Path cant be made relative \"%s\"", path_src); + BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made relative", path_src); data->count_failed++; } return TRUE; @@ -144,7 +144,7 @@ void BLI_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *re BLI_bpath_traverse_main(bmain, makeFilesRelative_visit_cb, 0, (void *)&data); BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO, - "Total files %d|Changed %d|Failed %d", + "Total files %d | Changed %d | Failed %d", data.count_tot, data.count_changed, data.count_failed); } @@ -164,7 +164,7 @@ static int makeFilesAbsolute_visit_cb(void *userdata, char *path_dst, const char data->count_changed++; } else { - BKE_reportf(data->reports, RPT_WARNING, "Path cant be made absolute \"%s\"", path_src); + BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made absolute", path_src); data->count_failed++; } return TRUE; @@ -187,13 +187,13 @@ void BLI_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *re BLI_bpath_traverse_main(bmain, makeFilesAbsolute_visit_cb, 0, (void *)&data); BKE_reportf(reports, data.count_failed ? RPT_WARNING : RPT_INFO, - "Total files %d|Changed %d|Failed %d", + "Total files %d | Changed %d | Failed %d", data.count_tot, data.count_changed, data.count_failed); } /** * find this file recursively, use the biggest file so thumbnails don't get used by mistake - * \param filename_new: the path will be copied here, caller must initialize as empyu string. + * \param filename_new: the path will be copied here, caller must initialize as empty string. * \param dirname: subdir to search * \param filename: set this filename * \param filesize: filesize for the file @@ -279,13 +279,13 @@ static int findMissingFiles_visit_cb(void *userdata, char *path_dst, const char if (filesize == -1) { /* could not open dir */ BKE_reportf(data->reports, RPT_WARNING, - "Could open directory \"%s\"", + "Could not open directory '%s'", BLI_path_basename(data->searchdir)); return FALSE; } else if (found == FALSE) { BKE_reportf(data->reports, RPT_WARNING, - "Could not find \"%s\" in \"%s\"", + "Could not find '%s' in '%s'", BLI_path_basename((char *)path_src), data->searchdir); return FALSE; } @@ -544,8 +544,8 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int case ID_ME: { Mesh *me = (Mesh *)id; - if (me->fdata.external) { - rewrite_path_fixed(me->fdata.external->filename, visit_cb, absbase, bpath_user_data); + if (me->ldata.external) { + rewrite_path_fixed(me->ldata.external->filename, visit_cb, absbase, bpath_user_data); } } break; diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c index d58ccbbd48e..4fb48d19239 100644 --- a/source/blender/blenlib/intern/edgehash.c +++ b/source/blender/blenlib/intern/edgehash.c @@ -108,7 +108,7 @@ void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *v eh->buckets[hash] = e; if (++eh->nentries > eh->nbuckets * 3) { - EdgeEntry *e, **old = eh->buckets; + EdgeEntry **old = eh->buckets; int i, nold = eh->nbuckets; eh->nbuckets = _ehash_hashsizes[++eh->cursize]; diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index f3107b565b9..883cdfde426 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -42,6 +42,9 @@ #include "zlib.h" #ifdef WIN32 +#ifdef __MINGW32__ +#include +#endif #include # include "BLI_winstuff.h" # include "BLI_callbacks.h" @@ -137,6 +140,8 @@ char *BLI_file_ungzip_to_mem(const char *from_file, int *size_r) } else break; } + + gzclose(gzfile); if (size == 0) { MEM_freeN(mem); @@ -207,6 +212,22 @@ FILE *BLI_fopen(const char *filename, const char *mode) return ufopen(filename, mode); } +void BLI_get_short_name(char short_name[256], const char *filename) +{ + wchar_t short_name_16[256]; + int i = 0; + + UTF16_ENCODE(filename); + + GetShortPathNameW(filename_16, short_name_16, 256); + + for (i = 0; i < 256; i++) { + short_name[i] = (char)short_name_16[i]; + } + + UTF16_UN_ENCODE(filename); +} + void *BLI_gzopen(const char *filename, const char *mode) { gzFile gzfile; @@ -215,25 +236,15 @@ void *BLI_gzopen(const char *filename, const char *mode) return 0; } else { - wchar_t short_name_16[256]; char short_name[256]; - int i = 0; /* xxx Creates file before transcribing the path */ if (mode[0] == 'w') fclose(ufopen(filename, "a")); - UTF16_ENCODE(filename); - - GetShortPathNameW(filename_16, short_name_16, 256); - - for (i = 0; i < 256; i++) { - short_name[i] = (char)short_name_16[i]; - } + BLI_get_short_name(short_name, filename); gzfile = gzopen(short_name, mode); - - UTF16_UN_ENCODE(filename); } return gzfile; @@ -341,7 +352,7 @@ void BLI_dir_create_recursive(const char *dirname) { char *lslash; char tmp[MAXPATHLEN]; - + /* First remove possible slash at the end of the dirname. * This routine otherwise tries to create * blah1/blah2/ (with slash) after creating @@ -349,23 +360,29 @@ void BLI_dir_create_recursive(const char *dirname) BLI_strncpy(tmp, dirname, sizeof(tmp)); lslash = BLI_last_slash(tmp); - - if (lslash == tmp + strlen(tmp) - 1) { - *lslash = 0; + + if (lslash && (*(lslash + 1) == '\0')) { + *lslash = '\0'; } - + + /* check special case "c:\foo", don't try create "c:", harmless but prints an error below */ + if (isalpha(tmp[0]) && (tmp[1] == ':') && tmp[2] == '\0') return; + if (BLI_exists(tmp)) return; lslash = BLI_last_slash(tmp); + if (lslash) { /* Split about the last slash and recurse */ *lslash = 0; BLI_dir_create_recursive(tmp); } - - if (dirname[0]) /* patch, this recursive loop tries to create a nameless directory */ - if (umkdir(dirname) == -1) + + if (dirname[0]) { /* patch, this recursive loop tries to create a nameless directory */ + if (umkdir(dirname) == -1) { printf("Unable to create directory %s\n", dirname); + } + } } int BLI_rename(const char *from, const char *to) @@ -508,8 +525,9 @@ static int recursive_operation(const char *startfrom, const char *startto, Recur } if (ret != 0) { - while (i < n) - free(dirlist[i]); + while (i < n) { + free(dirlist[i++]); + } break; } } diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c index 597a645eb9c..0a87316aa81 100644 --- a/source/blender/blenlib/intern/freetypefont.c +++ b/source/blender/blenlib/intern/freetypefont.c @@ -33,8 +33,8 @@ */ -#ifdef WIN32 -#pragma warning (disable:4244) +#ifdef _MSC_VER +# pragma warning (disable:4244) #endif #include @@ -58,9 +58,6 @@ #include "DNA_packedFile_types.h" #include "DNA_curve_types.h" -#define myMIN_ASCII 32 -#define myMAX_ASCII 255 - /* local variables */ static FT_Library library; static FT_Error err; @@ -274,7 +271,7 @@ static void freetypechar_to_vchar(FT_Face face, FT_ULong charcode, VFontData *vf (len_squared_v2v2(bezt->vec[1], bezt->vec[2]) > 0.0001f * 0.0001f) && (len_squared_v2v2(bezt->vec[0], bezt->vec[2]) > 0.0002f * 0.0001f) && (len_squared_v2v2(bezt->vec[0], bezt->vec[2]) > - maxf(len_squared_v2v2(bezt->vec[0], bezt->vec[1]), + max_ff(len_squared_v2v2(bezt->vec[0], bezt->vec[1]), len_squared_v2v2(bezt->vec[1], bezt->vec[2])))) { bezt->h1 = bezt->h2 = HD_ALIGN; @@ -285,7 +282,7 @@ static void freetypechar_to_vchar(FT_Face face, FT_ULong charcode, VFontData *vf } } if (npoints) MEM_freeN(npoints); - if (onpoints) MEM_freeN(onpoints); + if (onpoints) MEM_freeN(onpoints); } } @@ -407,7 +404,7 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile *pf) lcode = charcode; } - return vfd; + return vfd; } @@ -476,10 +473,10 @@ VFontData *BLI_vfontdata_from_freetypefont(PackedFile *pf) VFontData *vfd = NULL; int success = 0; - //init Freetype + /* init Freetype */ err = FT_Init_FreeType(&library); if (err) { - //XXX error("Failed to load the Freetype font library"); + /* XXX error("Failed to load the Freetype font library"); */ return NULL; } @@ -489,7 +486,7 @@ VFontData *BLI_vfontdata_from_freetypefont(PackedFile *pf) vfd = objfnt_to_ftvfontdata(pf); } - //free Freetype + /* free Freetype */ FT_Done_FreeType(library); return vfd; @@ -521,16 +518,16 @@ int BLI_vfontchar_from_freetypefont(VFont *vfont, unsigned long character) #if 0 -// Freetype2 Outline struct +/* Freetype2 Outline struct */ typedef struct FT_Outline_ - { +{ short n_contours; /* number of contours in glyph */ short n_points; /* number of points in the glyph */ - FT_Vector* points; /* the outline's points */ - char* tags; /* the points flags */ - short* contours; /* the contour end points */ + FT_Vector *points; /* the outline's points */ + char *tags; /* the points flags */ + short *contours; /* the contour end points */ int flags; /* outline masks */ } FT_Outline; diff --git a/source/blender/blenlib/intern/graph.c b/source/blender/blenlib/intern/graph.c index 51d7cb58b00..a93bbd97b51 100644 --- a/source/blender/blenlib/intern/graph.c +++ b/source/blender/blenlib/intern/graph.c @@ -353,12 +353,12 @@ int BLI_isGraphCyclic(BGraph *graph) /* Mark all nodes as not visited */ BLI_flagNodes(graph, 0); - /* detectCycles in subgraphs */ + /* detectCycles in subgraphs */ for (node = graph->nodes.first; node && value == 0; node = node->next) { /* only for nodes in subgraphs that haven't been visited yet */ if (node->flag == 0) { value = value || detectCycle(node, NULL); - } + } } return value; @@ -639,11 +639,11 @@ static void handleRadialSymmetry(BGraph *graph, BNode *root_node, int depth, flo /* if not dispatching already and on last arc * Dispatch using current arc as last - * */ + */ if (dispatch == 0 && i == total - 1) { last = i; dispatch = 1; - } + } if (dispatch) { int sub_total = last - first + 1; @@ -796,7 +796,7 @@ static void markdownSecondarySymmetry(BGraph *graph, BNode *node, int depth, int /* count the number of branches in this symmetry group * and determinate the axis of symmetry - * */ + */ for (i = 0; i < node->degree; i++) { BArc *connectedArc = node->arcs[i]; @@ -821,7 +821,7 @@ static void markdownSecondarySymmetry(BGraph *graph, BNode *node, int depth, int handleRadialSymmetry(graph, node, depth, axis, limit); } - /* markdown secondary symetries */ + /* markdown secondary symetries */ for (i = 0; i < node->degree; i++) { BArc *connectedArc = node->arcs[i]; @@ -836,7 +836,7 @@ static void markdownSymmetryArc(BGraph *graph, BArc *arc, BNode *node, int level { int i; - /* if arc is null, we start straight from a node */ + /* if arc is null, we start straight from a node */ if (arc) { arc->symmetry_level = level; @@ -875,7 +875,7 @@ static void markdownSymmetryArc(BGraph *graph, BArc *arc, BNode *node, int level /* not on the symmetry axis */ issymmetryAxis = 0; break; - } + } } } diff --git a/source/blender/blenlib/intern/lasso.c b/source/blender/blenlib/intern/lasso.c index 7df4da80e16..5cd8bb813a1 100644 --- a/source/blender/blenlib/intern/lasso.c +++ b/source/blender/blenlib/intern/lasso.c @@ -37,7 +37,7 @@ #include "BLI_lasso.h" /* own include */ -void BLI_lasso_boundbox(rcti *rect, int mcords[][2], short moves) +void BLI_lasso_boundbox(rcti *rect, const int mcords[][2], const short moves) { short a; @@ -53,14 +53,14 @@ void BLI_lasso_boundbox(rcti *rect, int mcords[][2], short moves) } -int BLI_lasso_is_point_inside(int mcords[][2], short moves, +int BLI_lasso_is_point_inside(const int mcords[][2], const short moves, const int sx, const int sy, const int error_value) { /* we do the angle rule, define that all added angles should be about zero or (2 * PI) */ float angletot = 0.0, dot, ang, cross, fp1[2], fp2[2]; int a; - int *p1, *p2; + const int *p1, *p2; if (sx == error_value) { return 0; @@ -100,7 +100,7 @@ int BLI_lasso_is_point_inside(int mcords[][2], short moves, } /* edge version for lasso select. we assume boundbox check was done */ -int BLI_lasso_is_edge_inside(int mcords[][2], short moves, +int BLI_lasso_is_edge_inside(const int mcords[][2], const short moves, int x0, int y0, int x1, int y1, const int error_value) { diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c index ad718ed8e11..9f6f409c473 100644 --- a/source/blender/blenlib/intern/listbase.c +++ b/source/blender/blenlib/intern/listbase.c @@ -141,7 +141,7 @@ void BLI_insertlink(ListBase *listbase, void *vprevlink, void *vnewlink) if (listbase == NULL) return; /* empty list */ - if (listbase->first == NULL) { + if (listbase->first == NULL) { listbase->first = newlink; listbase->last = newlink; @@ -149,7 +149,7 @@ void BLI_insertlink(ListBase *listbase, void *vprevlink, void *vnewlink) } /* insert before first element */ - if (prevlink == NULL) { + if (prevlink == NULL) { newlink->next = listbase->first; newlink->prev = NULL; newlink->next->prev = newlink; @@ -203,14 +203,14 @@ void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink) if (listbase == NULL) return; /* empty list */ - if (listbase->first == NULL) { + if (listbase->first == NULL) { listbase->first = newlink; listbase->last = newlink; return; } /* insert at head of list */ - if (prevlink == NULL) { + if (prevlink == NULL) { newlink->prev = NULL; newlink->next = listbase->first; ((Link *)listbase->first)->prev = newlink; @@ -238,14 +238,14 @@ void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink) if (listbase == NULL) return; /* empty list */ - if (listbase->first == NULL) { + if (listbase->first == NULL) { listbase->first = newlink; listbase->last = newlink; return; } /* insert at end of list */ - if (nextlink == NULL) { + if (nextlink == NULL) { newlink->prev = listbase->last; newlink->next = NULL; ((Link *)listbase->last)->next = newlink; diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index 97fc431d8fa..f27da759482 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -59,34 +59,34 @@ MINLINE float saacos(float fac) { if (fac <= -1.0f) return (float)M_PI; else if (fac >= 1.0f) return 0.0; - else return (float)acos(fac); + else return acosf(fac); } MINLINE float saasin(float fac) { if (fac <= -1.0f) return (float)-M_PI / 2.0f; else if (fac >= 1.0f) return (float)M_PI / 2.0f; - else return (float)asin(fac); + else return asinf(fac); } MINLINE float sasqrt(float fac) { if (fac <= 0.0f) return 0.0f; - return (float)sqrt(fac); + return sqrtf(fac); } MINLINE float saacosf(float fac) { if (fac <= -1.0f) return (float)M_PI; else if (fac >= 1.0f) return 0.0f; - else return (float)acosf(fac); + else return acosf(fac); } MINLINE float saasinf(float fac) { if (fac <= -1.0f) return (float)-M_PI / 2.0f; else if (fac >= 1.0f) return (float)M_PI / 2.0f; - else return (float)asinf(fac); + else return asinf(fac); } MINLINE float sasqrtf(float fac) @@ -139,20 +139,20 @@ MINLINE int power_of_2_min_i(int n) return n; } -MINLINE float minf(float a, float b) +MINLINE float min_ff(float a, float b) { return (a < b) ? a : b; } -MINLINE float maxf(float a, float b) +MINLINE float max_ff(float a, float b) { return (a > b) ? a : b; } -MINLINE int mini(int a, int b) +MINLINE int min_ii(int a, int b) { return (a < b) ? a : b; } -MINLINE int maxi(int a, int b) +MINLINE int max_ii(int a, int b) { return (b < a) ? a : b; } diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c index 6b90cbfe9c3..f520b2318e5 100644 --- a/source/blender/blenlib/intern/math_color_inline.c +++ b/source/blender/blenlib/intern/math_color_inline.c @@ -273,5 +273,20 @@ MINLINE float rgb_to_luma_y(const float rgb[3]) return 0.212671f * rgb[0] + 0.71516f * rgb[1] + 0.072169f * rgb[2]; } +MINLINE int compare_rgb_uchar(const unsigned char col_a[3], const unsigned char col_b[3], const int limit) +{ + int r = (int)col_a[0] - (int)col_b[0]; + if (ABS(r) < limit) { + int g = (int)col_a[1] - (int)col_b[1]; + if (ABS(g) < limit) { + int b = (int)col_a[2] - (int)col_b[2]; + if (ABS(b) < limit) { + return 1; + } + } + } + + return 0; +} #endif /* __MATH_COLOR_INLINE_C__ */ diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 53e9a6b66cb..e10229f11da 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -404,8 +404,8 @@ int isect_seg_seg_v2_point(const float v1[2], const float v2[2], const float v3[ if (u > u2) SWAP(float, u, u2); if (u > 1.0f + eps || u2 < -eps) return -1; /* non-ovlerlapping segments */ - else if (maxf(0.0f, u) == minf(1.0f, u2)) { /* one common point: can return result */ - interp_v2_v2v2(vi, v1, v2, maxf(0, u)); + else if (max_ff(0.0f, u) == min_ff(1.0f, u2)) { /* one common point: can return result */ + interp_v2_v2v2(vi, v1, v2, max_ff(0, u)); return 1; } } @@ -560,7 +560,8 @@ int isect_line_sphere_v2(const float l1[2], const float l2[2], } } -/* +/** + * \return * -1: collinear * 1: intersection */ @@ -758,6 +759,10 @@ int isect_ray_tri_v3(const float p1[3], const float d[3], return 1; } +/** + * if clip is nonzero, will only return true if lambda is >= 0.0 + * (i.e. intersection point is along positive d) + */ int isect_ray_plane_v3(const float p1[3], const float d[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, const int clip) @@ -876,6 +881,16 @@ int isect_ray_tri_threshold_v3(const float p1[3], const float d[3], return 1; } +/** + * Intersect line/plane, optionally treat line as directional (like a ray) with the no_flip argument. + * + * \param out The intersection point. + * \param l1 The first point of the line. + * \param l2 The second point of the line. + * \param plane_co A point on the plane to intersect with. + * \param plane_no The direction of the plane (does not need to be normalized). + * \param no_flip When true, the intersection point will always be from l1 to l2, even if this is not on the plane. + */ int isect_line_plane_v3(float out[3], const float l1[3], const float l2[3], const float plane_co[3], const float plane_no[3], const short no_flip) @@ -921,7 +936,20 @@ int isect_line_plane_v3(float out[3], } } -/* note: return normal isn't unit length */ +/** + * Intersect two planes, return a point on the intersection and a vector + * that runs on the direction of the intersection. + * Return error code is the same as 'isect_line_line_v3'. + * + * \param r_isect_co The resulting intersection point. + * \param r_isect_no The resulting vector of the intersection. + * \param plane_a_co The point on the first plane. + * \param plane_a_no The normal of the first plane. + * \param plane_b_co The point on the second plane. + * \param plane_b_no The normal of the second plane. + * + * \note return normal isn't unit length + */ void isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3], const float plane_a_co[3], const float plane_a_no[3], const float plane_b_co[3], const float plane_b_no[3]) @@ -939,10 +967,10 @@ void isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3], /* "Improved Collision detection and Response" */ static int getLowestRoot(const float a, const float b, const float c, const float maxR, float *root) { - // Check if a solution exists + /* Check if a solution exists */ float determinant = b * b - 4.0f * a * c; - // If determinant is negative it means no solutions. + /* If determinant is negative it means no solutions. */ if (determinant >= 0.0f) { /* calculate the two roots: (if determinant == 0 then * x1==x2 but lets disregard that slight optimization) */ @@ -950,24 +978,24 @@ static int getLowestRoot(const float a, const float b, const float c, const floa float r1 = (-b - sqrtD) / (2.0f * a); float r2 = (-b + sqrtD) / (2.0f * a); - // Sort so x1 <= x2 + /* Sort so x1 <= x2 */ if (r1 > r2) SWAP(float, r1, r2); - // Get lowest root: + /* Get lowest root: */ if (r1 > 0.0f && r1 < maxR) { *root = r1; return 1; } - // It is possible that we want x2 - this can happen - // if x1 < 0 + /* It is possible that we want x2 - this can happen */ + /* if x1 < 0 */ if (r2 > 0.0f && r2 < maxR) { *root = r2; return 1; } } - // No (valid) solutions + /* No (valid) solutions */ return 0; } @@ -1080,7 +1108,7 @@ int isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const flo } /*---test edges---*/ - sub_v3_v3v3(e3, v2, v1); //wasnt yet calculated + sub_v3_v3v3(e3, v2, v1); /* wasnt yet calculated */ /*e1*/ @@ -1206,11 +1234,12 @@ int isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3] return 1; } -/* Returns the number of point of interests +/** + * \return The number of point of interests * 0 - lines are colinear * 1 - lines are coplanar, i1 is set to intersection * 2 - i1 and i2 are the nearest points on line 1 (v1, v2) and line 2 (v3, v4) respectively - * */ + */ int isect_line_line_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float i1[3], float i2[3]) { float a[3], b[3], c[3], ab[3], cb[3], dir1[3], dir2[3]; @@ -1344,7 +1373,7 @@ void isect_ray_aabb_initialize(IsectRayAABBData *data, const float ray_start[3], /* Adapted from http://www.gamedev.net/community/forums/topic.asp?topic_id=459973 */ int isect_ray_aabb(const IsectRayAABBData *data, const float bb_min[3], - const float bb_max[3], float *tmin_out) + const float bb_max[3], float *tmin_out) { float bbox[2][3]; float tmin, tmax, tymin, tymax, tzmin, tzmax; @@ -1387,7 +1416,7 @@ int isect_ray_aabb(const IsectRayAABBData *data, const float bb_min[3], } /* find closest point to p on line through l1,l2 and return lambda, - * where (0 <= lambda <= 1) when cp is in the line segement l1,l2 + * where (0 <= lambda <= 1) when cp is in the line segment l1,l2 */ float closest_to_line_v3(float cp[3], const float p[3], const float l1[3], const float l2[3]) { @@ -1429,7 +1458,7 @@ float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2 return (dot_v2v2(u, h) / dot_v2v2(u, u)); } -/* ensyre the distance between these points is no greater then 'dist' +/* ensure the distance between these points is no greater then 'dist' * if it is, scale then both into the center */ void limit_dist_v3(float v1[3], float v2[3], const float dist) { @@ -1587,7 +1616,7 @@ void isect_point_face_uv_v2(const int isquad, } } -#if 0 // XXX this version used to be used in isect_point_tri_v2_int() and was called IsPointInTri2D +#if 0 /* XXX this version used to be used in isect_point_tri_v2_int() and was called IsPointInTri2D */ int isect_point_tri_v2(float pt[2], float v1[2], float v2[2], float v3[2]) { @@ -1672,7 +1701,7 @@ static int point_in_slice(const float p[3], const float v1[3], const float l1[3] * the room inside usually is rather small compared to R3 though still infinite * useful for restricting (speeding up) searches * e.g. all points of triangular prism are within the intersection of 3 'slices' - * onother trivial case : cube + * another trivial case : cube * but see a 'spat' which is a deformed cube with paired parallel planes needs only 3 slices too */ float h, rp[3], cp[3], q[3]; @@ -1777,7 +1806,7 @@ void plot_line_v2v2i(const int p1[2], const int p2[2], int (*callback)(int, int, signed char ix; signed char iy; - // if x1 == x2 or y1 == y2, then it does not matter what we set here + /* if x1 == x2 or y1 == y2, then it does not matter what we set here */ int delta_x = (x2 > x1 ? (ix = 1, x2 - x1) : (ix = -1, x1 - x2)) << 1; int delta_y = (y2 > y1 ? (iy = 1, y2 - y1) : (iy = -1, y1 - y2)) << 1; @@ -1786,7 +1815,7 @@ void plot_line_v2v2i(const int p1[2], const int p2[2], int (*callback)(int, int, } if (delta_x >= delta_y) { - // error may go below zero + /* error may go below zero */ int error = delta_y - (delta_x >> 1); while (x1 != x2) { @@ -1795,9 +1824,9 @@ void plot_line_v2v2i(const int p1[2], const int p2[2], int (*callback)(int, int, y1 += iy; error -= delta_x; } - // else do nothing + /* else do nothing */ } - // else do nothing + /* else do nothing */ x1 += ix; error += delta_y; @@ -1808,7 +1837,7 @@ void plot_line_v2v2i(const int p1[2], const int p2[2], int (*callback)(int, int, } } else { - // error may go below zero + /* error may go below zero */ int error = delta_x - (delta_y >> 1); while (y1 != y2) { @@ -1817,9 +1846,9 @@ void plot_line_v2v2i(const int p1[2], const int p2[2], int (*callback)(int, int, x1 += ix; error -= delta_y; } - // else do nothing + /* else do nothing */ } - // else do nothing + /* else do nothing */ y1 += iy; error += delta_x; @@ -1992,8 +2021,8 @@ void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const flo const float co[2], float w[4]) { /* note: fabsf() here is not needed for convex quads (and not used in interp_weights_poly_v2). - * but in the case of concave/bowtie quads for the mask rasterizer it gives unreliable results - * without adding absf(). If this becomes an issue for more general useage we could have + * but in the case of concave/bow-tie quads for the mask rasterizer it gives unreliable results + * without adding absf(). If this becomes an issue for more general usage we could have * this optional or use a different function - Campbell */ #define MEAN_VALUE_HALF_TAN_V2(_area, i1, i2) \ ((_area = cross_v2v2(dirs[i1], dirs[i2])) != 0.0f ? \ @@ -2323,18 +2352,18 @@ void resolve_quad_uv(float r_uv[2], const float st[2], const float st0[2], const (st2[0] * st3[1] - st2[1] * st3[0]) + (st3[0] * st0[1] - st3[1] * st0[0]); /* X is 2D cross product (determinant) - * A= (p0-p) X (p0-p3)*/ + * A = (p0 - p) X (p0 - p3)*/ const double a = (st0[0] - st[0]) * (st0[1] - st3[1]) - (st0[1] - st[1]) * (st0[0] - st3[0]); - /* B= ( (p0-p) X (p1-p2) + (p1-p) X (p0-p3) ) / 2 */ - const double b = 0.5 * (((st0[0] - st[0]) * (st1[1] - st2[1]) - (st0[1] - st[1]) * (st1[0] - st2[0])) + - ((st1[0] - st[0]) * (st0[1] - st3[1]) - (st1[1] - st[1]) * (st0[0] - st3[0]))); + /* B = ( (p0 - p) X (p1 - p2) + (p1 - p) X (p0 - p3) ) / 2 */ + const double b = 0.5 * (double)(((st0[0] - st[0]) * (st1[1] - st2[1]) - (st0[1] - st[1]) * (st1[0] - st2[0])) + + ((st1[0] - st[0]) * (st0[1] - st3[1]) - (st1[1] - st[1]) * (st0[0] - st3[0]))); /* C = (p1-p) X (p1-p2) */ const double fC = (st1[0] - st[0]) * (st1[1] - st2[1]) - (st1[1] - st[1]) * (st1[0] - st2[0]); const double denom = a - 2 * b + fC; - // clear outputs + /* clear outputs */ zero_v2(r_uv); if (IS_ZERO(denom) != 0) { @@ -2364,7 +2393,7 @@ void resolve_quad_uv(float r_uv[2], const float st[2], const float st0[2], const } if (IS_ZERO(denom) == 0) - r_uv[1] = (float)(((1.0f - r_uv[0]) * (st0[i] - st[i]) + r_uv[0] * (st1[i] - st[i])) / denom); + r_uv[1] = (float)((double)((1.0f - r_uv[0]) * (st0[i] - st[i]) + r_uv[0] * (st1[i] - st[i])) / denom); } } @@ -2650,7 +2679,7 @@ void accumulate_vertex_normals(float n1[3], float n2[3], float n3[3], const float *cur_edge = vdiffs[i]; const float fac = saacos(-dot_v3v3(cur_edge, prev_edge)); - // accumulate + /* accumulate */ madd_v3_v3fl(vn[i], f_no, fac); prev_edge = cur_edge; } @@ -2691,50 +2720,6 @@ void accumulate_vertex_normals_poly(float **vertnos, float polyno[3], /********************************* Tangents **********************************/ -/* For normal map tangents we need to detect uv boundaries, and only average - * tangents in case the uvs are connected. Alternative would be to store 1 - * tangent per face rather than 4 per face vertex, but that's not compatible - * with games */ - - -/* from BKE_mesh.h */ -#define STD_UV_CONNECT_LIMIT 0.0001f - -void sum_or_add_vertex_tangent(void *arena, VertexTangent **vtang, const float tang[3], const float uv[2]) -{ - VertexTangent *vt; - - /* find a tangent with connected uvs */ - for (vt = *vtang; vt; vt = vt->next) { - if (fabsf(uv[0] - vt->uv[0]) < STD_UV_CONNECT_LIMIT && fabsf(uv[1] - vt->uv[1]) < STD_UV_CONNECT_LIMIT) { - add_v3_v3(vt->tang, tang); - return; - } - } - - /* if not found, append a new one */ - vt = BLI_memarena_alloc((MemArena *) arena, sizeof(VertexTangent)); - copy_v3_v3(vt->tang, tang); - vt->uv[0] = uv[0]; - vt->uv[1] = uv[1]; - - if (*vtang) - vt->next = *vtang; - *vtang = vt; -} - -float *find_vertex_tangent(VertexTangent *vtang, const float uv[2]) -{ - VertexTangent *vt; - static float nulltang[3] = {0.0f, 0.0f, 0.0f}; - - for (vt = vtang; vt; vt = vt->next) - if (fabsf(uv[0] - vt->uv[0]) < STD_UV_CONNECT_LIMIT && fabsf(uv[1] - vt->uv[1]) < STD_UV_CONNECT_LIMIT) - return vt->tang; - - return nulltang; /* shouldn't happen, except for nan or so */ -} - void tangent_from_uv(float uv1[2], float uv2[2], float uv3[3], float co1[3], float co2[3], float co3[3], float n[3], float tang[3]) { float s1 = uv2[0] - uv1[0]; diff --git a/source/blender/blenlib/intern/math_geom_inline.c b/source/blender/blenlib/intern/math_geom_inline.c index 0d4c797cefb..01585c93bc8 100644 --- a/source/blender/blenlib/intern/math_geom_inline.c +++ b/source/blender/blenlib/intern/math_geom_inline.c @@ -137,4 +137,24 @@ MINLINE void madd_sh_shfl(float r[9], const float sh[9], const float f) add_sh_shsh(r, r, tmp); } +MINLINE int max_axis_v3(const float vec[3]) +{ + const float x = vec[0]; + const float y = vec[1]; + const float z = vec[2]; + return ((x > y) ? + ((x > z) ? 0 : 2) : + ((y > z) ? 1 : 2)); +} + +MINLINE int min_axis_v3(const float vec[3]) +{ + const float x = vec[0]; + const float y = vec[1]; + const float z = vec[2]; + return ((x < y) ? + ((x < z) ? 0 : 2) : + ((y < z) ? 1 : 2)); +} + #endif /* __MATH_GEOM_INLINE_C__ */ diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 3fb3d2b58ff..f622a5ace35 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -195,7 +195,7 @@ void mul_m3_m3m3(float m1[][3], float m3_[][3], float m2_[][3]) m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2]; } -void mul_m4_m4m3(float (*m1)[4], float (*m3_)[4], float (*m2_)[3]) +void mul_m4_m4m3(float m1[][4], float m3_[][4], float m2_[][3]) { float m2[3][3], m3[4][4]; @@ -215,8 +215,14 @@ void mul_m4_m4m3(float (*m1)[4], float (*m3_)[4], float (*m2_)[3]) } /* m1 = m2 * m3, ignore the elements on the 4th row/column of m3 */ -void mult_m3_m3m4(float m1[][3], float m3[][4], float m2[][3]) +void mult_m3_m3m4(float m1[][3], float m3_[][4], float m2_[][3]) { + float m2[3][3], m3[4][4]; + + /* copy so it works when m1 is the same pointer as m2 or m3 */ + copy_m3_m3(m2, m2_); + copy_m4_m4(m3, m3_); + /* m1[i][j] = m2[i][k] * m3[k][j] */ m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0]; m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1]; @@ -231,8 +237,14 @@ void mult_m3_m3m4(float m1[][3], float m3[][4], float m2[][3]) m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] + m2[2][2] * m3[2][2]; } -void mul_m4_m3m4(float (*m1)[4], float (*m3)[3], float (*m2)[4]) +void mul_m4_m3m4(float m1[][4], float m3_[][3], float m2_[][4]) { + float m2[4][4], m3[3][3]; + + /* copy so it works when m1 is the same pointer as m2 or m3 */ + copy_m4_m4(m2, m2_); + copy_m3_m3(m3, m3_); + m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] + m2[0][2] * m3[2][0]; m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] + m2[0][2] * m3[2][1]; m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] + m2[0][2] * m3[2][2]; @@ -591,15 +603,15 @@ int invert_m4_m4(float inverse[4][4], float mat[4][4]) if (temp == 0) return 0; /* No non-zero pivot */ for (k = 0; k < 4; k++) { - tempmat[i][k] = (float)(tempmat[i][k] / temp); - inverse[i][k] = (float)(inverse[i][k] / temp); + tempmat[i][k] = (float)((double)tempmat[i][k] / temp); + inverse[i][k] = (float)((double)inverse[i][k] / temp); } for (j = 0; j < 4; j++) { if (j != i) { temp = tempmat[j][i]; for (k = 0; k < 4; k++) { - tempmat[j][k] -= (float)(tempmat[i][k] * temp); - inverse[j][k] -= (float)(inverse[i][k] * temp); + tempmat[j][k] -= (float)((double)tempmat[i][k] * temp); + inverse[j][k] -= (float)((double)inverse[i][k] * temp); } } } @@ -933,8 +945,18 @@ void normalize_m4_m4(float rmat[][4], float mat[][4]) if (len != 0.0f) rmat[2][3] = mat[2][3] / len; } +void adjoint_m2_m2(float m1[][2], float m[][2]) +{ + BLI_assert(m1 != m); + m1[0][0] = m[1][1]; + m1[0][1] = -m[1][0]; + m1[1][0] = -m[0][1]; + m1[1][1] = m[0][0]; +} + void adjoint_m3_m3(float m1[][3], float m[][3]) { + BLI_assert(m1 != m); m1[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1]; m1[0][1] = -m[0][1] * m[2][2] + m[0][2] * m[2][1]; m1[0][2] = m[0][1] * m[1][2] - m[0][2] * m[1][1]; @@ -1388,7 +1410,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) int m = 4; int n = 4; int maxiter = 200; - int nu = minf(m, n); + int nu = min_ff(m, n); float *work = work1; float *e = work2; @@ -1396,22 +1418,22 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) int i = 0, j = 0, k = 0, p, pp, iter; - // Reduce A to bidiagonal form, storing the diagonal elements - // in s and the super-diagonal elements in e. + /* Reduce A to bidiagonal form, storing the diagonal elements + * in s and the super-diagonal elements in e. */ - int nct = minf(m - 1, n); - int nrt = maxf(0, minf(n - 2, m)); + int nct = min_ff(m - 1, n); + int nrt = max_ff(0, min_ff(n - 2, m)); copy_m4_m4(A, A_); zero_m4(U); zero_v4(s); - for (k = 0; k < maxf(nct, nrt); k++) { + for (k = 0; k < max_ff(nct, nrt); k++) { if (k < nct) { - // Compute the transformation for the k-th column and - // place the k-th diagonal in s[k]. - // Compute 2-norm of k-th column without under/overflow. + /* Compute the transformation for the k-th column and + * place the k-th diagonal in s[k]. + * Compute 2-norm of k-th column without under/overflow. */ s[k] = 0; for (i = k; i < m; i++) { s[k] = hypotf(s[k], A[i][k]); @@ -1432,7 +1454,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) for (j = k + 1; j < n; j++) { if ((k < nct) && (s[k] != 0.0f)) { - // Apply the transformation. + /* Apply the transformation. */ float t = 0; for (i = k; i < m; i++) { @@ -1444,24 +1466,24 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) } } - // Place the k-th row of A into e for the - // subsequent calculation of the row transformation. + /* Place the k-th row of A into e for the */ + /* subsequent calculation of the row transformation. */ e[j] = A[k][j]; } if (k < nct) { - // Place the transformation in U for subsequent back - // multiplication. + /* Place the transformation in U for subsequent back + * multiplication. */ for (i = k; i < m; i++) U[i][k] = A[i][k]; } if (k < nrt) { - // Compute the k-th row transformation and place the - // k-th super-diagonal in e[k]. - // Compute 2-norm without under/overflow. + /* Compute the k-th row transformation and place the + * k-th super-diagonal in e[k]. + * Compute 2-norm without under/overflow. */ e[k] = 0; for (i = k + 1; i < n; i++) { e[k] = hypotf(e[k], e[i]); @@ -1481,7 +1503,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) if ((k + 1 < m) & (e[k] != 0.0f)) { float invek1; - // Apply the transformation. + /* Apply the transformation. */ for (i = k + 1; i < m; i++) { work[i] = 0.0f; @@ -1500,17 +1522,17 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) } } - // Place the transformation in V for subsequent - // back multiplication. + /* Place the transformation in V for subsequent + * back multiplication. */ for (i = k + 1; i < n; i++) V[i][k] = e[i]; } } - // Set up the final bidiagonal matrix or order p. + /* Set up the final bidiagonal matrix or order p. */ - p = minf(n, m + 1); + p = min_ff(n, m + 1); if (nct < n) { s[nct] = A[nct][nct]; } @@ -1522,7 +1544,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) } e[p - 1] = 0.0f; - // If required, generate U. + /* If required, generate U. */ for (j = nct; j < nu; j++) { for (i = 0; i < m; i++) { @@ -1558,7 +1580,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) } } - // If required, generate V. + /* If required, generate V. */ for (k = n - 1; k >= 0; k--) { if ((k < nrt) & (e[k] != 0.0f)) { @@ -1579,7 +1601,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) V[k][k] = 1.0f; } - // Main iteration loop for the singular values. + /* Main iteration loop for the singular values. */ pp = p - 1; iter = 0; @@ -1587,20 +1609,20 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) while (p > 0) { int kase = 0; - // Test for maximum iterations to avoid infinite loop + /* Test for maximum iterations to avoid infinite loop */ if (maxiter == 0) break; maxiter--; - // This section of the program inspects for - // negligible elements in the s and e arrays. On - // completion the variables kase and k are set as follows. - - // kase = 1 if s(p) and e[k - 1] are negligible and k

      = -1; k--) { if (k == -1) { @@ -1641,11 +1663,11 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) } k++; - // Perform the task indicated by kase. + /* Perform the task indicated by kase. */ switch (kase) { - // Deflate negligible s(p). + /* Deflate negligible s(p). */ case 1: { @@ -1671,7 +1693,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) break; } - // Split at negligible s(k). + /* Split at negligible s(k). */ case 2: { @@ -1695,14 +1717,14 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) break; } - // Perform one qr step. + /* Perform one qr step. */ case 3: { - // Calculate the shift. + /* Calculate the shift. */ - float scale = maxf(maxf(maxf(maxf( + float scale = max_ff(max_ff(max_ff(max_ff( fabsf(s[p - 1]), fabsf(s[p - 2])), fabsf(e[p - 2])), fabsf(s[k])), fabsf(e[k])); float invscale = 1.0f / scale; @@ -1725,7 +1747,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) f = (sk + sp) * (sk - sp) + shift; g = sk * ek; - // Chase zeros. + /* Chase zeros. */ for (j = k; j < p - 1; j++) { float t = hypotf(f, g); @@ -1767,12 +1789,12 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) iter = iter + 1; break; } - // Convergence. + /* Convergence. */ case 4: { - // Make the singular values positive. + /* Make the singular values positive. */ if (s[k] <= 0.0f) { s[k] = (s[k] < 0.0f ? -s[k] : 0.0f); @@ -1781,7 +1803,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) V[i][k] = -V[i][k]; } - // Order the singular values. + /* Order the singular values. */ while (k < pp) { float t; diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index f0ed23aabc9..b0c4724e1ec 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -35,7 +35,9 @@ /******************************** Quaternions ********************************/ /* used to test is a quat is not normalized (only used for debug prints) */ -#define QUAT_EPSILON 0.0001 +#ifdef DEBUG +# define QUAT_EPSILON 0.0001 +#endif /* convenience, avoids setting Y axis everywhere */ void unit_axis_angle(float axis[3], float *angle) @@ -232,7 +234,7 @@ void quat_to_mat4(float m[][4], const float q[4]) double q0, q1, q2, q3, qda, qdb, qdc, qaa, qab, qac, qbb, qbc, qcc; #ifdef DEBUG - if (!((q0 = dot_qtqt(q, q)) == 0.0f || (fabsf(q0 - 1.0) < QUAT_EPSILON))) { + if (!((q0 = dot_qtqt(q, q)) == 0.0 || (fabs(q0 - 1.0) < QUAT_EPSILON))) { fprintf(stderr, "Warning! quat_to_mat4() called with non-normalized: size %.8f *** report a bug ***\n", (float)q0); } #endif @@ -286,9 +288,9 @@ void mat3_to_quat(float q[4], float wmat[][3]) s = sqrt(tr); q[0] = (float)s; s = 1.0 / (4.0 * s); - q[1] = (float)((mat[1][2] - mat[2][1]) * s); - q[2] = (float)((mat[2][0] - mat[0][2]) * s); - q[3] = (float)((mat[0][1] - mat[1][0]) * s); + q[1] = (float)((double)(mat[1][2] - mat[2][1]) * s); + q[2] = (float)((double)(mat[2][0] - mat[0][2]) * s); + q[3] = (float)((double)(mat[0][1] - mat[1][0]) * s); } else { if (mat[0][0] > mat[1][1] && mat[0][0] > mat[2][2]) { @@ -611,13 +613,21 @@ void add_qt_qtqt(float result[4], const float quat1[4], const float quat2[4], co result[3] = quat1[3] + t * quat2[3]; } -void tri_to_quat(float quat[4], const float v1[3], const float v2[3], const float v3[3]) +/* same as tri_to_quat() but takes pre-computed normal from the triangle + * used for ngons when we know their normal */ +void tri_to_quat_ex(float quat[4], const float v1[3], const float v2[3], const float v3[3], + const float no_orig[3]) { /* imaginary x-axis, y-axis triangle is being rotated */ float vec[3], q1[4], q2[4], n[3], si, co, angle, mat[3][3], imat[3][3]; /* move z-axis to face-normal */ +#if 0 normal_tri_v3(vec, v1, v2, v3); +#else + copy_v3_v3(vec, no_orig); + (void)v3; +#endif n[0] = vec[1]; n[1] = -vec[0]; @@ -657,6 +667,13 @@ void tri_to_quat(float quat[4], const float v1[3], const float v2[3], const floa mul_qt_qtqt(quat, q1, q2); } +void tri_to_quat(float quat[4], const float v1[3], const float v2[3], const float v3[3]) +{ + float vec[3]; + normal_tri_v3(vec, v1, v2, v3); + tri_to_quat_ex(quat, v1, v2, v3, vec); +} + void print_qt(const char *str, const float q[4]) { printf("%s: %.3f %.3f %.3f %.3f\n", str, q[0], q[1], q[2], q[3]); @@ -780,7 +797,7 @@ void mat3_to_axis_angle(float axis[3], float *angle, float mat[3][3]) float q[4]; /* use quaternions as intermediate representation */ - // TODO: it would be nicer to go straight there... + /* TODO: it would be nicer to go straight there... */ mat3_to_quat(q, mat); quat_to_axis_angle(axis, angle, q); } @@ -791,7 +808,7 @@ void mat4_to_axis_angle(float axis[3], float *angle, float mat[4][4]) float q[4]; /* use quaternions as intermediate representation */ - // TODO: it would be nicer to go straight there... + /* TODO: it would be nicer to go straight there... */ mat4_to_quat(q, mat); quat_to_axis_angle(axis, angle, q); } @@ -841,7 +858,7 @@ void single_axis_angle_to_mat3(float mat[3][3], const char axis, const float ang } /****************************** Vector/Rotation ******************************/ -/* TODO: the following calls should probably be depreceated sometime */ +/* TODO: the following calls should probably be deprecated sometime */ /* TODO, replace use of this function with axis_angle_to_mat3() */ void vec_rot_to_mat3(float mat[][3], const float vec[3], const float phi) @@ -1060,11 +1077,11 @@ void compatible_eul(float eul[3], const float oldrot[3]) for (i = 0; i < 3; i++) { deul[i] = eul[i] - oldrot[i]; if (deul[i] > pi_thresh) { - eul[i] -= floorf(( deul[i] / pi_x2) + 0.5) * pi_x2; + eul[i] -= floorf(( deul[i] / pi_x2) + 0.5f) * pi_x2; deul[i] = eul[i] - oldrot[i]; } else if (deul[i] < -pi_thresh) { - eul[i] += floorf((-deul[i] / pi_x2) + 0.5) * pi_x2; + eul[i] += floorf((-deul[i] / pi_x2) + 0.5f) * pi_x2; deul[i] = eul[i] - oldrot[i]; } } @@ -1346,7 +1363,7 @@ void mat4_to_compatible_eulO(float eul[3], float oldrot[3], const short order, f mat3_to_compatible_eulO(eul, oldrot, order, m); } /* rotate the given euler by the given angle on the specified axis */ -// NOTE: is this safe to do with different axis orders? +/* NOTE: is this safe to do with different axis orders? */ void rotate_eulO(float beul[3], const short order, char axis, float ang) { @@ -1662,34 +1679,34 @@ void vec_apply_track(float vec[3], short axis) switch (axis) { case 0: /* pos-x */ - /* vec[0]= 0.0; */ + /* vec[0] = 0.0; */ vec[1] = tvec[2]; vec[2] = -tvec[1]; break; case 1: /* pos-y */ - /* vec[0]= tvec[0]; */ - /* vec[1]= 0.0; */ - /* vec[2]= tvec[2]; */ + /* vec[0] = tvec[0]; */ + /* vec[1] = 0.0; */ + /* vec[2] = tvec[2]; */ break; case 2: /* pos-z */ - /* vec[0]= tvec[0]; */ - /* vec[1]= tvec[1]; */ - // vec[2]= 0.0; */ + /* vec[0] = tvec[0]; */ + /* vec[1] = tvec[1]; */ + /* vec[2] = 0.0; */ break; case 3: /* neg-x */ - /* vec[0]= 0.0; */ + /* vec[0] = 0.0; */ vec[1] = tvec[2]; vec[2] = -tvec[1]; break; case 4: /* neg-y */ vec[0] = -tvec[2]; - /* vec[1]= 0.0; */ + /* vec[1] = 0.0; */ vec[2] = tvec[0]; break; case 5: /* neg-z */ vec[0] = -tvec[0]; vec[1] = -tvec[1]; - /* vec[2]= 0.0; */ + /* vec[2] = 0.0; */ break; } } diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 4196bab0474..976895fe6fc 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -451,6 +451,15 @@ void minmax_v3v3_v3(float min[3], float max[3], const float vec[3]) if (max[2] < vec[2]) max[2] = vec[2]; } +void minmax_v2v2_v2(float min[2], float max[2], const float vec[2]) +{ + if (min[0] > vec[0]) min[0] = vec[0]; + if (min[1] > vec[1]) min[1] = vec[1]; + + if (max[0] < vec[0]) max[0] = vec[0]; + if (max[1] < vec[1]) max[1] = vec[1]; +} + /** ensure \a v1 is \a dist from \a v2 */ void dist_ensure_v3_v3fl(float v1[3], const float v2[3], const float dist) { @@ -483,7 +492,7 @@ double dot_vn_vn(const float *array_src_a, const float *array_src_b, const int s const float *array_pt_b = array_src_b + (size - 1); int i = size; while (i--) { - d += *(array_pt_a--) * *(array_pt_b--); + d += (double)(*(array_pt_a--) * *(array_pt_b--)); } return d; } diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index 0a8f57214d7..191b0e16025 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -121,6 +121,13 @@ MINLINE void copy_v4_v4_char(char r[4], const char a[4]) } /* short */ +MINLINE void zero_v3_int(int r[3]) +{ + r[0] = 0; + r[1] = 0; + r[2] = 0; +} + MINLINE void copy_v2_v2_short(short r[2], const short a[2]) { r[0] = a[0]; @@ -561,6 +568,16 @@ MINLINE float len_squared_v3(const float v[3]) return v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; } +MINLINE float len_manhattan_v2(const float v[2]) +{ + return fabsf(v[0]) + fabsf(v[1]); +} + +MINLINE float len_manhattan_v3(const float v[3]) +{ + return fabsf(v[0]) + fabsf(v[1]) + fabsf(v[2]); +} + MINLINE float len_v2(const float v[2]) { return sqrtf(v[0] * v[0] + v[1] * v[1]); @@ -588,14 +605,6 @@ MINLINE float len_squared_v2v2(const float a[2], const float b[2]) return dot_v2v2(d, d); } -MINLINE float len_v3v3(const float a[3], const float b[3]) -{ - float d[3]; - - sub_v3_v3v3(d, b, a); - return len_v3(d); -} - MINLINE float len_squared_v3v3(const float a[3], const float b[3]) { float d[3]; @@ -604,6 +613,30 @@ MINLINE float len_squared_v3v3(const float a[3], const float b[3]) return dot_v3v3(d, d); } +MINLINE float len_manhattan_v2v2(const float a[2], const float b[2]) +{ + float d[2]; + + sub_v2_v2v2(d, b, a); + return len_manhattan_v2(d); +} + +MINLINE float len_manhattan_v3v3(const float a[3], const float b[3]) +{ + float d[3]; + + sub_v3_v3v3(d, b, a); + return len_manhattan_v3(d); +} + +MINLINE float len_v3v3(const float a[3], const float b[3]) +{ + float d[3]; + + sub_v3_v3v3(d, b, a); + return len_v3(d); +} + MINLINE float normalize_v2_v2(float r[2], const float a[2]) { float d = dot_v2v2(a, a); @@ -689,7 +722,7 @@ MINLINE void normal_float_to_short_v3(short out[3], const float in[3]) /********************************* Comparison ********************************/ -MINLINE int is_zero_v2(const float v[3]) +MINLINE int is_zero_v2(const float v[2]) { return (v[0] == 0 && v[1] == 0); } @@ -724,6 +757,15 @@ MINLINE int equals_v4v4(const float v1[4], const float v2[4]) return ((v1[0] == v2[0]) && (v1[1] == v2[1]) && (v1[2] == v2[2]) && (v1[3] == v2[3])); } +MINLINE int compare_v2v2(const float v1[2], const float v2[2], const float limit) +{ + if (fabsf(v1[0] - v2[0]) < limit) + if (fabsf(v1[1] - v2[1]) < limit) + return 1; + + return 0; +} + MINLINE int compare_v3v3(const float v1[3], const float v2[3], const float limit) { if (fabsf(v1[0] - v2[0]) < limit) diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c index bd83c5e018c..fb33d7ce127 100644 --- a/source/blender/blenlib/intern/noise.c +++ b/source/blender/blenlib/intern/noise.c @@ -31,9 +31,9 @@ */ -#ifdef _WIN32 -#pragma warning (disable : 4244) // "conversion from double to float" -#pragma warning (disable : 4305) // "truncation from const double to float" +#ifdef _MSC_VER +# pragma warning (disable:4244) /* "conversion from double to float" */ +# pragma warning (disable:4305) /* "truncation from const double to float" */ #endif #include @@ -45,7 +45,8 @@ static float noise3_perlin(float vec[3]); //static float turbulence_perlin(float *point, float lofreq, float hifreq); //static float turbulencep(float noisesize, float x, float y, float z, int nr); -#define HASHVEC(x, y, z) hashvectf + 3 * hash[(hash[(hash[(z) & 255] + (y)) & 255] + (x)) & 255] +/* UNUSED */ +// #define HASHVEC(x, y, z) hashvectf + 3 * hash[(hash[(hash[(z) & 255] + (y)) & 255] + (x)) & 255] /* needed for voronoi */ #define HASHPNT(x, y, z) hashpntf + 3 * hash[(hash[(hash[(z) & 255] + (y)) & 255] + (x)) & 255] @@ -300,8 +301,8 @@ static float newPerlin(float x, float y, float z) u = npfade(x); /* COMPUTE FADE CURVES */ v = npfade(y); /* FOR EACH OF X,Y,Z. */ w = npfade(z); - A = hash[X ]+Y; AA = hash[A]+Z; AB = hash[A+1]+Z; /* HASH COORDINATES OF */ - B = hash[X+1]+Y; BA = hash[B]+Z; BB = hash[B+1]+Z; /* THE 8 CUBE CORNERS, */ + A = hash[X ] + Y; AA = hash[A] + Z; AB = hash[A + 1] + Z; /* HASH COORDINATES OF */ + B = hash[X + 1] + Y; BA = hash[B] + Z; BB = hash[B + 1] + Z; /* THE 8 CUBE CORNERS, */ return lerp(w, lerp(v, lerp(u, grad(hash[AA ], x, y, z ), /* AND ADD */ grad(hash[BA ], x - 1, y, z )), /* BLENDED */ lerp(u, grad(hash[AB ], x, y - 1, z ), /* RESULTS */ diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index a7a66718445..444daf8817c 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -47,7 +47,7 @@ #include "BLI_string_utf8.h" #include "BLI_utildefines.h" -#include "BKE_blender.h" // BLENDER_VERSION +#include "BKE_blender.h" /* BLENDER_VERSION */ #include "GHOST_Path-api.h" @@ -330,7 +330,7 @@ void BLI_cleanup_path(const char *relabase, char *dir) if (strcmp(dir, ".") == 0) { /* happens for example in FILE_MAIN */ get_default_root(dir); return; - } + } while ( (start = strstr(dir, "\\..\\")) ) { eind = start + strlen("\\..\\") - 1; @@ -492,7 +492,7 @@ void BLI_path_rel(char *file, const char *relfile) */ if (*q != '/') { while ( (q >= file) && (*q != '/') ) { --q; --p; } - } + } else if (*p != '/') { while ( (p >= temp) && (*p != '/') ) { --p; --q; } } @@ -544,7 +544,7 @@ int BLI_parent_dir(char *path) BLI_cleanup_dir(NULL, tmp); if (!BLI_testextensie(tmp, parent_dir)) { - BLI_strncpy(path, tmp, sizeof(tmp)); + BLI_strncpy(path, tmp, sizeof(tmp)); return 1; } else { @@ -691,7 +691,7 @@ int BLI_path_abs(char *path, const char *basepath) * of paths and solving some problems (and prevent potential future * ones) -jesterKing. */ BLI_char_switch(tmp, '\\', '/'); - BLI_char_switch(base, '\\', '/'); + BLI_char_switch(base, '\\', '/'); /* Paths starting with // will get the blend file as their base, * this isn't standard in any os but is used in blender all over the place */ @@ -1300,7 +1300,7 @@ void BLI_make_file_string(const char *relabase, char *string, const char *dir, BLI_char_switch(file, '\\', '/'); #endif - /* Resolve relative references */ + /* Resolve relative references */ if (relabase && dir[0] == '/' && dir[1] == '/') { char *lslash; @@ -1321,7 +1321,7 @@ void BLI_make_file_string(const char *relabase, char *string, const char *dir, else { /* no drive specified */ /* first option: get the drive from the relabase if it has one */ if (relabase && strlen(relabase) >= 2 && relabase[1] == ':') { - BLI_strncpy(string, relabase, 3); + BLI_strncpy(string, relabase, 3); string[2] = '\\'; string[3] = '\0'; } @@ -1337,7 +1337,7 @@ void BLI_make_file_string(const char *relabase, char *string, const char *dir, strcat(string, dir); - /* Make sure string ends in one (and only one) slash */ + /* Make sure string ends in one (and only one) slash */ /* first trim all slashes from the end of the string */ sl = strlen(string); while (sl > 0 && (string[sl - 1] == '/' || string[sl - 1] == '\\') ) { @@ -1368,7 +1368,7 @@ int BLI_testextensie(const char *str, const char *ext) retval = 0; } else if (BLI_strcasecmp(ext, str + a - b)) { - retval = 0; + retval = 0; } else { retval = 1; diff --git a/source/blender/blenlib/intern/pbvh.c b/source/blender/blenlib/intern/pbvh.c index d3d8d371f60..7637c60ec16 100644 --- a/source/blender/blenlib/intern/pbvh.c +++ b/source/blender/blenlib/intern/pbvh.c @@ -157,6 +157,8 @@ struct PBVH { /* flag are verts/faces deformed */ int deformed; + + int show_diffuse_color; }; #define STACK_FIXED_DEPTH 100 @@ -189,8 +191,8 @@ static void BB_expand(BB *bb, float co[3]) { int i; for (i = 0; i < 3; ++i) { - bb->bmin[i] = minf(bb->bmin[i], co[i]); - bb->bmax[i] = maxf(bb->bmax[i], co[i]); + bb->bmin[i] = min_ff(bb->bmin[i], co[i]); + bb->bmax[i] = max_ff(bb->bmax[i], co[i]); } } @@ -199,8 +201,8 @@ static void BB_expand_with_bb(BB *bb, BB *bb2) { int i; for (i = 0; i < 3; ++i) { - bb->bmin[i] = minf(bb->bmin[i], bb2->bmin[i]); - bb->bmax[i] = maxf(bb->bmax[i], bb2->bmax[i]); + bb->bmin[i] = min_ff(bb->bmin[i], bb2->bmin[i]); + bb->bmax[i] = max_ff(bb->bmax[i], bb2->bmax[i]); } } @@ -663,7 +665,7 @@ void BLI_pbvh_build_grids(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, bvh->totgrid = totgrid; bvh->gridkey = *key; bvh->grid_hidden = grid_hidden; - bvh->leaf_limit = maxi(LEAF_LIMIT / ((gridsize - 1) * (gridsize - 1)), 1); + bvh->leaf_limit = max_ii(LEAF_LIMIT / ((gridsize - 1) * (gridsize - 1)), 1); BB_reset(&cb); @@ -1001,7 +1003,7 @@ static int update_search_cb(PBVHNode *node, void *data_v) if (node->flag & PBVH_Leaf) return (node->flag & flag); - + return 1; } @@ -1165,7 +1167,8 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode) bvh->grid_flag_mats, node->prim_indices, node->totprim, - &bvh->gridkey); + &bvh->gridkey, + bvh->show_diffuse_color); break; case PBVH_FACES: GPU_update_mesh_buffers(node->draw_buffers, @@ -1174,7 +1177,9 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode) node->uniq_verts + node->face_verts, CustomData_get_layer(bvh->vdata, - CD_PAINT_MASK)); + CD_PAINT_MASK), + node->face_vert_indices, + bvh->show_diffuse_color); break; } @@ -1630,9 +1635,9 @@ static PlaneAABBIsect test_planes_aabb(const float bb_min[3], PlaneAABBIsect ret = ISECT_INSIDE; int i, axis; - for (i = 0; i < 4; ++i) { + for (i = 0; i < 4; ++i) { for (axis = 0; axis < 3; ++axis) { - if (planes[i][axis] > 0) { + if (planes[i][axis] > 0) { vmin[axis] = bb_min[axis]; vmax[axis] = bb_max[axis]; } @@ -1646,7 +1651,7 @@ static PlaneAABBIsect test_planes_aabb(const float bb_min[3], return ISECT_OUTSIDE; else if (dot_v3v3(planes[i], vmax) + planes[i][3] >= 0) ret = ISECT_INTERSECT; - } + } return ret; } @@ -1667,11 +1672,23 @@ int BLI_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data) return test_planes_aabb(bb_min, bb_max, data) != ISECT_INSIDE; } +static void pbvh_node_check_diffuse_changed(PBVH *bvh, PBVHNode *node) +{ + if (!node->draw_buffers) + return; + + if (GPU_buffers_diffuse_changed(node->draw_buffers, bvh->show_diffuse_color)) + node->flag |= PBVH_UpdateDrawBuffers; +} + void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3], DMSetMaterial setMaterial) { PBVHNode **nodes; - int totnode; + int a, totnode; + + for (a = 0; a < bvh->totnode; a++) + pbvh_node_check_diffuse_changed(bvh, &bvh->nodes[a]); BLI_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(PBVH_UpdateNormals | PBVH_UpdateDrawBuffers), &nodes, &totnode); @@ -1876,3 +1893,8 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, if (!vi->grids) vi->vmask = CustomData_get_layer(bvh->vdata, CD_PAINT_MASK); } + +void pbvh_show_diffuse_color_set(PBVH *bvh, int show_diffuse_color) +{ + bvh->show_diffuse_color = show_diffuse_color; +} diff --git a/source/blender/blenlib/intern/quadric.c b/source/blender/blenlib/intern/quadric.c new file mode 100644 index 00000000000..bb39cb61e78 --- /dev/null +++ b/source/blender/blenlib/intern/quadric.c @@ -0,0 +1,131 @@ +/* + * ***** 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): Laurence Bourn, Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenlib/intern/quadric.c + * \ingroup bli + * + * \note This isn't fully complete, + * possible there are other useful functions to add here. + * + * \note try to follow BLI_math naming convention here. + */ + +//#include + +#include "BLI_math.h" +#include "BLI_quadric.h" /* own include */ + + +#define QUADRIC_FLT_TOT (sizeof(Quadric) / sizeof(float)) + +void BLI_quadric_from_v3_dist(Quadric *q, const float v[3], const float offset) +{ + q->a2 = v[0] * v[0]; + q->b2 = v[1] * v[1]; + q->c2 = v[2] * v[2]; + + q->ab = v[0] * v[1]; + q->ac = v[0] * v[2]; + q->bc = v[1] * v[2]; + + q->ad = v[0] * offset; + q->bd = v[1] * offset; + q->cd = v[2] * offset; + + q->d2 = offset * offset; +} + +void BLI_quadric_to_tensor_m3(const Quadric *q, float m[3][3]) +{ + m[0][0] = q->a2; + m[0][1] = q->ab; + m[0][2] = q->ac; + + m[1][0] = q->ab; + m[1][1] = q->b2; + m[1][2] = q->bc; + + m[2][0] = q->ac; + m[2][1] = q->bc; + m[2][2] = q->c2; +} + +void BLI_quadric_to_vector_v3(const Quadric *q, float v[3]) +{ + v[0] = q->ad; + v[1] = q->bd; + v[2] = q->cd; +} + +void BLI_quadric_clear(Quadric *q) +{ + memset(q, 0, sizeof(*q)); +} + +void BLI_quadric_add_qu_qu(Quadric *a, const Quadric *b) +{ + add_vn_vn((float *)a, (float *)b, QUADRIC_FLT_TOT); +} + +void BLI_quadric_add_qu_ququ(Quadric *r, const Quadric *a, const Quadric *b) +{ + add_vn_vnvn((float *)r, (const float *)a, (const float *)b, QUADRIC_FLT_TOT); +} + +void BLI_quadric_mul(Quadric *a, const float scalar) +{ + mul_vn_fl((float *)a, QUADRIC_FLT_TOT, scalar); +} + +float BLI_quadric_evaluate(const Quadric *q, const float v[3]) +{ + return (v[0] * v[0] * q->a2 + 2.0f * v[0] * v[1] * q->ab + 2.0f * v[0] * v[2] * q->ac + 2.0f * v[0] * q->ad + + v[1] * v[1] * q->b2 + 2.0f * v[1] * v[2] * q->bc + 2.0f * v[1] * q->bd + + v[2] * v[2] * q->c2 + 2.0f * v[2] * q->cd + + q->d2); +} + +int BLI_quadric_optimize(const Quadric *q, float v[3]) +{ + float m[3][3]; + float det; + + BLI_quadric_to_tensor_m3(q, m); + det = determinant_m3(m[0][0], m[0][1], m[0][2], + m[1][0], m[1][1], m[1][2], + m[2][0], m[2][1], m[2][2]); + + if (fabsf(det) > FLT_EPSILON) { + invert_m3(m); + BLI_quadric_to_vector_v3(q, v); + mul_m3_v3(m, v); + negate_v3(v); + + return TRUE; + } + else { + return FALSE; + } +} diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c index 4435e9ce09c..76d17f34b5e 100644 --- a/source/blender/blenlib/intern/rand.c +++ b/source/blender/blenlib/intern/rand.c @@ -40,7 +40,7 @@ #include "BLI_threads.h" #include "BLI_rand.h" -#if defined(WIN32) && !defined(FREE_WINDOWS) +#ifdef _MSC_VER typedef unsigned __int64 r_uint64; #define MULTIPLIER 0x5DEECE66Di64 @@ -64,51 +64,51 @@ struct RNG { r_uint64 X; }; -RNG *rng_new(unsigned int seed) +RNG *BLI_rng_new(unsigned int seed) { RNG *rng = MEM_mallocN(sizeof(*rng), "rng"); - rng_seed(rng, seed); + BLI_rng_seed(rng, seed); return rng; } -void rng_free(RNG *rng) +void BLI_rng_free(RNG *rng) { MEM_freeN(rng); } -void rng_seed(RNG *rng, unsigned int seed) +void BLI_rng_seed(RNG *rng, unsigned int seed) { rng->X = (((r_uint64) seed) << 16) | LOWSEED; } -void rng_srandom(RNG *rng, unsigned int seed) +void BLI_rng_srandom(RNG *rng, unsigned int seed) { - rng_seed(rng, seed + hash[seed & 255]); - seed = rng_getInt(rng); - rng_seed(rng, seed + hash[seed & 255]); - seed = rng_getInt(rng); - rng_seed(rng, seed + hash[seed & 255]); + BLI_rng_seed(rng, seed + hash[seed & 255]); + seed = BLI_rng_get_int(rng); + BLI_rng_seed(rng, seed + hash[seed & 255]); + seed = BLI_rng_get_int(rng); + BLI_rng_seed(rng, seed + hash[seed & 255]); } -int rng_getInt(RNG *rng) +int BLI_rng_get_int(RNG *rng) { rng->X = (MULTIPLIER * rng->X + ADDEND) & MASK; return (int) (rng->X >> 17); } -double rng_getDouble(RNG *rng) +double BLI_rng_get_double(RNG *rng) { - return (double) rng_getInt(rng) / 0x80000000; + return (double) BLI_rng_get_int(rng) / 0x80000000; } -float rng_getFloat(RNG *rng) +float BLI_rng_get_float(RNG *rng) { - return (float) rng_getInt(rng) / 0x80000000; + return (float) BLI_rng_get_int(rng) / 0x80000000; } -void rng_shuffleArray(RNG *rng, void *data, int elemSize, int numElems) +void BLI_rng_shuffle_array(RNG *rng, void *data, int elemSize, int numElems) { int i = numElems; void *temp; @@ -122,7 +122,7 @@ void rng_shuffleArray(RNG *rng, void *data, int elemSize, int numElems) /* XXX Shouldn't it rather be "while (i--) {" ? * Else we have no guaranty first (0) element has a chance to be shuffled... --mont29 */ while (--i) { - int j = rng_getInt(rng) % numElems; + int j = BLI_rng_get_int(rng) % numElems; if (i != j) { void *iElem = (unsigned char *)data + i * elemSize; void *jElem = (unsigned char *)data + j * elemSize; @@ -135,12 +135,12 @@ void rng_shuffleArray(RNG *rng, void *data, int elemSize, int numElems) free(temp); } -void rng_skip(RNG *rng, int n) +void BLI_rng_skip(RNG *rng, int n) { int i; for (i = 0; i < n; i++) - rng_getInt(rng); + BLI_rng_get_int(rng); } /***/ @@ -150,28 +150,28 @@ static RNG theBLI_rng = {0}; /* note, this one creates periodical patterns */ void BLI_srand(unsigned int seed) { - rng_seed(&theBLI_rng, seed); + BLI_rng_seed(&theBLI_rng, seed); } /* using hash table to create better seed */ void BLI_srandom(unsigned int seed) { - rng_srandom(&theBLI_rng, seed); + BLI_rng_srandom(&theBLI_rng, seed); } int BLI_rand(void) { - return rng_getInt(&theBLI_rng); + return BLI_rng_get_int(&theBLI_rng); } double BLI_drand(void) { - return rng_getDouble(&theBLI_rng); + return BLI_rng_get_double(&theBLI_rng); } float BLI_frand(void) { - return rng_getFloat(&theBLI_rng); + return BLI_rng_get_float(&theBLI_rng); } void BLI_fillrand(void *addr, int len) @@ -179,16 +179,16 @@ void BLI_fillrand(void *addr, int len) RNG rng; unsigned char *p = addr; - rng_seed(&rng, (unsigned int) (PIL_check_seconds_timer() * 0x7FFFFFFF)); - while (len--) *p++ = rng_getInt(&rng) & 0xFF; + BLI_rng_seed(&rng, (unsigned int) (PIL_check_seconds_timer() * 0x7FFFFFFF)); + while (len--) *p++ = BLI_rng_get_int(&rng) & 0xFF; } void BLI_array_randomize(void *data, int elemSize, int numElems, unsigned int seed) { RNG rng; - rng_seed(&rng, seed); - rng_shuffleArray(&rng, data, elemSize, numElems); + BLI_rng_seed(&rng, seed); + BLI_rng_shuffle_array(&rng, data, elemSize, numElems); } /* ********* for threaded random ************** */ @@ -200,20 +200,20 @@ void BLI_thread_srandom(int thread, unsigned int seed) if (thread >= BLENDER_MAX_THREADS) thread = 0; - rng_seed(&rng_tab[thread], seed + hash[seed & 255]); - seed = rng_getInt(&rng_tab[thread]); - rng_seed(&rng_tab[thread], seed + hash[seed & 255]); - seed = rng_getInt(&rng_tab[thread]); - rng_seed(&rng_tab[thread], seed + hash[seed & 255]); + BLI_rng_seed(&rng_tab[thread], seed + hash[seed & 255]); + seed = BLI_rng_get_int(&rng_tab[thread]); + BLI_rng_seed(&rng_tab[thread], seed + hash[seed & 255]); + seed = BLI_rng_get_int(&rng_tab[thread]); + BLI_rng_seed(&rng_tab[thread], seed + hash[seed & 255]); } int BLI_thread_rand(int thread) { - return rng_getInt(&rng_tab[thread]); + return BLI_rng_get_int(&rng_tab[thread]); } float BLI_thread_frand(int thread) { - return rng_getFloat(&rng_tab[thread]); + return BLI_rng_get_float(&rng_tab[thread]); } diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c index 225ede8a8ef..ee073d5d309 100644 --- a/source/blender/blenlib/intern/rct.c +++ b/source/blender/blenlib/intern/rct.c @@ -102,16 +102,28 @@ int BLI_rctf_isect_pt_v(const rctf *rect, const float xy[2]) } /* based closely on 'isect_line_line_v2_int', but in modified so corner cases are treated as intersections */ -static int isect_segments(const int v1[2], const int v2[2], const int v3[2], const int v4[2]) +static int isect_segments_i(const int v1[2], const int v2[2], const int v3[2], const int v4[2]) { const double div = (double)((v2[0] - v1[0]) * (v4[1] - v3[1]) - (v2[1] - v1[1]) * (v4[0] - v3[0])); - if (div == 0.0f) { + if (div == 0.0) { return 1; /* co-linear */ } else { const double labda = (double)((v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div; const double mu = (double)((v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div; - return (labda >= 0.0f && labda <= 1.0f && mu >= 0.0f && mu <= 1.0f); + return (labda >= 0.0 && labda <= 1.0 && mu >= 0.0 && mu <= 1.0); + } +} +static int isect_segments_fl(const float v1[2], const float v2[2], const float v3[2], const float v4[2]) +{ + const double div = (double)((v2[0] - v1[0]) * (v4[1] - v3[1]) - (v2[1] - v1[1]) * (v4[0] - v3[0])); + if (div == 0.0) { + return 1; /* co-linear */ + } + else { + const double labda = (double)((v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div; + const double mu = (double)((v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div; + return (labda >= 0.0 && labda <= 1.0 && mu >= 0.0 && mu <= 1.0); } } @@ -134,14 +146,49 @@ int BLI_rcti_isect_segment(const rcti *rect, const int s1[2], const int s2[2]) /* diagonal: [/] */ tvec1[0] = rect->xmin; tvec1[1] = rect->ymin; tvec2[0] = rect->xmin; tvec2[1] = rect->ymax; - if (isect_segments(s1, s2, tvec1, tvec2)) { + if (isect_segments_i(s1, s2, tvec1, tvec2)) { return 1; } /* diagonal: [\] */ tvec1[0] = rect->xmin; tvec1[1] = rect->ymax; tvec2[0] = rect->xmax; tvec2[1] = rect->ymin; - if (isect_segments(s1, s2, tvec1, tvec2)) { + if (isect_segments_i(s1, s2, tvec1, tvec2)) { + return 1; + } + + /* no intersection */ + return 0; + } +} + +int BLI_rctf_isect_segment(const rctf *rect, const float s1[2], const float s2[2]) +{ + /* first do outside-bounds check for both points of the segment */ + if (s1[0] < rect->xmin && s2[0] < rect->xmin) return 0; + if (s1[0] > rect->xmax && s2[0] > rect->xmax) return 0; + if (s1[1] < rect->ymin && s2[1] < rect->ymin) return 0; + if (s1[1] > rect->ymax && s2[1] > rect->ymax) return 0; + + /* if either points intersect then we definetly intersect */ + if (BLI_rctf_isect_pt_v(rect, s1) || BLI_rctf_isect_pt_v(rect, s2)) { + return 1; + } + else { + /* both points are outside but may insersect the rect */ + float tvec1[2]; + float tvec2[2]; + /* diagonal: [/] */ + tvec1[0] = rect->xmin; tvec1[1] = rect->ymin; + tvec2[0] = rect->xmin; tvec2[1] = rect->ymax; + if (isect_segments_fl(s1, s2, tvec1, tvec2)) { + return 1; + } + + /* diagonal: [\] */ + tvec1[0] = rect->xmin; tvec1[1] = rect->ymax; + tvec2[0] = rect->xmax; tvec2[1] = rect->ymin; + if (isect_segments_fl(s1, s2, tvec1, tvec2)) { return 1; } @@ -252,8 +299,8 @@ void BLI_rctf_translate(rctf *rect, float x, float y) /* change width & height around the central location */ void BLI_rcti_resize(rcti *rect, int x, int y) { - rect->xmin = rect->xmax = BLI_RCT_CENTER_X(rect); - rect->ymin = rect->ymax = BLI_RCT_CENTER_Y(rect); + rect->xmin = rect->xmax = BLI_rcti_cent_x(rect); + rect->ymin = rect->ymax = BLI_rcti_cent_y(rect); rect->xmin -= x / 2; rect->ymin -= y / 2; rect->xmax = rect->xmin + x; @@ -262,8 +309,8 @@ void BLI_rcti_resize(rcti *rect, int x, int y) void BLI_rctf_resize(rctf *rect, float x, float y) { - rect->xmin = rect->xmax = BLI_RCT_CENTER_X(rect); - rect->ymin = rect->ymax = BLI_RCT_CENTER_Y(rect); + rect->xmin = rect->xmax = BLI_rctf_cent_x(rect); + rect->ymin = rect->ymax = BLI_rctf_cent_y(rect); rect->xmin -= x * 0.5f; rect->ymin -= y * 0.5f; rect->xmax = rect->xmin + x; @@ -281,6 +328,27 @@ void BLI_rctf_interp(rctf *rect, const rctf *rect_a, const rctf *rect_b, const f /* BLI_rcti_interp() not needed yet */ + +int BLI_rctf_clamp_pt_v(const struct rctf *rect, float xy[2]) +{ + int change = 0; + if (xy[0] < rect->xmin) { xy[0] = rect->xmin; change = 1; } + if (xy[0] > rect->xmax) { xy[0] = rect->xmax; change = 1; } + if (xy[1] < rect->ymin) { xy[1] = rect->ymin; change = 1; } + if (xy[1] > rect->ymax) { xy[1] = rect->ymax; change = 1; } + return change; +} + +int BLI_rcti_clamp_pt_v(const struct rcti *rect, int xy[2]) +{ + int change = 0; + if (xy[0] < rect->xmin) { xy[0] = rect->xmin; change = 1; } + if (xy[0] > rect->xmax) { xy[0] = rect->xmax; change = 1; } + if (xy[1] < rect->ymin) { xy[1] = rect->ymin; change = 1; } + if (xy[1] > rect->ymax) { xy[1] = rect->ymax; change = 1; } + return change; +} + int BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, const float limit) { if (fabsf(rect_a->xmin - rect_b->xmin) < limit) @@ -366,9 +434,9 @@ int BLI_rcti_isect(const rcti *src1, const rcti *src2, rcti *dest) void BLI_rcti_rctf_copy(rcti *dst, const rctf *src) { dst->xmin = floorf(src->xmin + 0.5f); - dst->xmax = dst->xmin + floorf(BLI_RCT_SIZE_X(src) + 0.5f); + dst->xmax = dst->xmin + floorf(BLI_rctf_size_x(src) + 0.5f); dst->ymin = floorf(src->ymin + 0.5f); - dst->ymax = dst->ymin + floorf(BLI_RCT_SIZE_Y(src) + 0.5f); + dst->ymax = dst->ymin + floorf(BLI_rctf_size_y(src) + 0.5f); } void BLI_rctf_rcti_copy(rctf *dst, const rcti *src) @@ -382,11 +450,11 @@ void BLI_rctf_rcti_copy(rctf *dst, const rcti *src) void print_rctf(const char *str, const rctf *rect) { printf("%s: xmin %.3f, xmax %.3f, ymin %.3f, ymax %.3f (%.3fx%.3f)\n", str, - rect->xmin, rect->xmax, rect->ymin, rect->ymax, BLI_RCT_SIZE_X(rect), BLI_RCT_SIZE_Y(rect)); + rect->xmin, rect->xmax, rect->ymin, rect->ymax, BLI_rctf_size_x(rect), BLI_rctf_size_y(rect)); } void print_rcti(const char *str, const rcti *rect) { printf("%s: xmin %d, xmax %d, ymin %d, ymax %d (%dx%d)\n", str, - rect->xmin, rect->xmax, rect->ymin, rect->ymax, BLI_RCT_SIZE_X(rect), BLI_RCT_SIZE_Y(rect)); + rect->xmin, rect->xmax, rect->ymin, rect->ymax, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)); } diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index 32afaba2b5c..362a87782c6 100644 --- a/source/blender/blenlib/intern/scanfill.c +++ b/source/blender/blenlib/intern/scanfill.c @@ -211,7 +211,7 @@ ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3]) copy_v3_v3(eve->co, vec); - return eve; + return eve; } ScanFillEdge *BLI_scanfill_edge_add(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert *v2) @@ -521,7 +521,7 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf) while (eve) { printf("vert: %x co: %f %f\n", eve, eve->xy[0], eve->xy[1]); eve = eve->next; - } + } eed = sf_ctx->filledgebase.first; while (eed) { printf("edge: %x verts: %x %x\n", eed, eed->v1, eed->v2); @@ -661,8 +661,8 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf) /* this happens with a serial of overlapping edges */ if (v1 == v2 || v2 == v3) break; /* printf("test verts %x %x %x\n",v1,v2,v3); */ - miny = minf(v1->xy[1], v3->xy[1]); - /* miny= minf(v1->xy[1],v3->xy[1]); */ + miny = min_ff(v1->xy[1], v3->xy[1]); + /* miny = min_ff(v1->xy[1],v3->xy[1]); */ sc1 = sc + 1; test = 0; @@ -985,12 +985,12 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedu /* CURRENT STATUS: - * - eve->f :1= availalble in edges + * - eve->f :1 = availalble in edges * - eve->xs :polynumber * - eve->h :amount of edges connected to vertex * - eve->tmp.v :store! original vertex number * - * - eed->f :1= boundary edge (optionally set by caller) + * - eed->f :1 = boundary edge (optionally set by caller) * - eed->poly_nr :poly number */ diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index 0fccd91fc02..1358fdd2a62 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -34,7 +34,7 @@ #include #include -#include +#include #ifndef WIN32 #include @@ -187,7 +187,7 @@ double BLI_dir_free_space(const char *dir) #endif #if defined(__sun__) || defined(__sun) || defined(__NetBSD__) - if (statvfs(name, &disk)) return(-1); + if (statvfs(name, &disk)) return(-1); #elif !defined(__FreeBSD__) && !defined(linux) && (defined(__sparc) || defined(__sparc__)) /* WARNING - This may not be supported by geeneric unix os's - Campbell */ if (statfs(name, &disk, sizeof(struct statfs), 0)) return(-1); @@ -418,9 +418,9 @@ static void bli_adddirstrings(void) unsigned int BLI_dir_contents(const char *dirname, struct direntry **filelist) { - // reset global variables - // memory stored in files is free()'d in - // filesel.c:freefilelist() + /* reset global variables + * memory stored in files is free()'d in + * filesel.c:freefilelist() */ actnum = totnum = 0; files = NULL; diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 8501db7c8b8..ff589764287 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -41,6 +41,8 @@ #include "BLI_dynstr.h" #include "BLI_string.h" +#include "BLI_utildefines.h" + char *BLI_strdupn(const char *str, const size_t len) { char *n = MEM_mallocN(len + 1, "strdup"); @@ -71,6 +73,7 @@ char *BLI_strncpy(char *dst, const char *src, const size_t maxncpy) { size_t srclen = strlen(src); size_t cpylen = (srclen > (maxncpy - 1)) ? (maxncpy - 1) : srclen; + BLI_assert(maxncpy != 0); memcpy(dst, src, cpylen); dst[cpylen] = '\0'; @@ -130,10 +133,13 @@ char *BLI_sprintfN(const char *format, ...) * TODO: support more fancy string escaping. current code is primitive * this basically is an ascii version of PyUnicode_EncodeUnicodeEscape() * which is a useful reference. */ -size_t BLI_strescape(char *dst, const char *src, const size_t maxlen) +size_t BLI_strescape(char *dst, const char *src, const size_t maxncpy) { size_t len = 0; - while (len < maxlen) { + + BLI_assert(maxncpy != 0); + + while (len < maxncpy) { switch (*src) { case '\0': goto escape_finish; @@ -144,7 +150,7 @@ size_t BLI_strescape(char *dst, const char *src, const size_t maxlen) case '\t': case '\n': case '\r': - if (len + 1 < maxlen) { + if (len + 1 < maxncpy) { *dst++ = '\\'; len++; } @@ -296,11 +302,12 @@ char *BLI_strcasestr(const char *s, const char *find) int BLI_strcasecmp(const char *s1, const char *s2) { - int i; + register int i; + register char c1, c2; for (i = 0;; i++) { - char c1 = tolower(s1[i]); - char c2 = tolower(s2[i]); + c1 = tolower(s1[i]); + c2 = tolower(s2[i]); if (c1 < c2) { return -1; @@ -318,11 +325,12 @@ int BLI_strcasecmp(const char *s1, const char *s2) int BLI_strncasecmp(const char *s1, const char *s2, size_t len) { - int i; + register size_t i; + register char c1, c2; for (i = 0; i < len; i++) { - char c1 = tolower(s1[i]); - char c2 = tolower(s2[i]); + c1 = tolower(s1[i]); + c2 = tolower(s2[i]); if (c1 < c2) { return -1; @@ -341,15 +349,16 @@ int BLI_strncasecmp(const char *s1, const char *s2, size_t len) /* natural string compare, keeping numbers in order */ int BLI_natstrcmp(const char *s1, const char *s2) { - int d1 = 0, d2 = 0; + register int d1 = 0, d2 = 0; + register char c1, c2; /* if both chars are numeric, to a strtol(). * then increase string deltas as long they are * numeric, else do a tolower and char compare */ while (1) { - char c1 = tolower(s1[d1]); - char c2 = tolower(s2[d2]); + c1 = tolower(s1[d1]); + c2 = tolower(s2[d2]); if (isdigit(c1) && isdigit(c2) ) { int val1, val2; @@ -374,7 +383,7 @@ int BLI_natstrcmp(const char *s1, const char *s2) c2 = tolower(s2[d2]); } - /* first check for '.' so "foo.bar" comes before "foo 1.bar" */ + /* first check for '.' so "foo.bar" comes before "foo 1.bar" */ if (c1 == '.' && c2 != '.') return -1; if (c1 != '.' && c2 == '.') @@ -413,27 +422,26 @@ void BLI_timestr(double _time, char *str) } /* determine the length of a fixed-size string */ -size_t BLI_strnlen(const char *str, size_t maxlen) +size_t BLI_strnlen(const char *str, const size_t maxlen) { const char *end = memchr(str, '\0', maxlen); return end ? (size_t) (end - str) : maxlen; } -void BLI_ascii_strtolower(char *str, int len) +void BLI_ascii_strtolower(char *str, const size_t len) { - int i; + size_t i; for (i = 0; i < len; i++) if (str[i] >= 'A' && str[i] <= 'Z') str[i] += 'a' - 'A'; } -void BLI_ascii_strtoupper(char *str, int len) +void BLI_ascii_strtoupper(char *str, const size_t len) { - int i; + size_t i; for (i = 0; i < len; i++) if (str[i] >= 'a' && str[i] <= 'z') str[i] -= 'a' - 'A'; } - diff --git a/source/blender/blenlib/intern/string_cursor_utf8.c b/source/blender/blenlib/intern/string_cursor_utf8.c index 422a600e51c..bab144266a4 100644 --- a/source/blender/blenlib/intern/string_cursor_utf8.c +++ b/source/blender/blenlib/intern/string_cursor_utf8.c @@ -147,7 +147,7 @@ void BLI_str_cursor_step_utf8(const char *str, size_t maxlen, int *pos, strCursorJumpDirection direction, strCursorJumpType jump) { - const short pos_prev = *pos; + const int pos_prev = *pos; if (direction == STRCUR_DIR_NEXT) { BLI_str_cursor_step_next_utf8(str, maxlen, pos); diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index f5c09791a68..0b737e0eff5 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -33,8 +33,12 @@ #include #include #include +#include +#include -#include "BLI_string_utf8.h" +#include "BLI_utildefines.h" + +#include "BLI_string_utf8.h" /* own include */ /* from libswish3, originally called u8_isvalid(), * modified to return the index of the bad character (byte index not utf). @@ -58,11 +62,11 @@ static const char trailingBytesForUTF8[256] = { int BLI_utf8_invalid_byte(const char *str, int length) { - const unsigned char *p, *pend = (unsigned char*)str + length; + const unsigned char *p, *pend = (unsigned char *)str + length; unsigned char c; int ab; - for (p = (unsigned char*)str; p < pend; p++) { + for (p = (unsigned char *)str; p < pend; p++) { c = *p; if (c < 128) continue; @@ -124,15 +128,15 @@ utf8_error: int BLI_utf8_invalid_strip(char *str, int length) { - int bad_char, tot= 0; + int bad_char, tot = 0; - while ((bad_char= BLI_utf8_invalid_byte(str, length)) != -1) { + while ((bad_char = BLI_utf8_invalid_byte(str, length)) != -1) { str += bad_char; length -= bad_char; if (length == 0) { /* last character bad, strip it */ - *str= '\0'; + *str = '\0'; tot++; break; } @@ -153,22 +157,22 @@ int BLI_utf8_invalid_strip(char *str, int length) * note: this looks to be at odd's with 'trailingBytesForUTF8', * need to find out what gives here! - campbell */ static const size_t utf8_skip_data[256] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1 }; #define BLI_STR_UTF8_CPY(dst, src, maxncpy) \ { \ size_t utf8_size; \ - while (*src != '\0' && (utf8_size= utf8_skip_data[*src]) < maxncpy) { \ + while (*src != '\0' && (utf8_size = utf8_skip_data[*src]) < maxncpy) {\ maxncpy -= utf8_size; \ - switch (utf8_size) { \ + switch (utf8_size) { \ case 6: *dst ++ = *src ++; \ case 5: *dst ++ = *src ++; \ case 4: *dst ++ = *src ++; \ @@ -177,12 +181,14 @@ static const size_t utf8_skip_data[256] = { case 1: *dst ++ = *src ++; \ } \ } \ - *dst= '\0'; \ + *dst = '\0'; \ } (void)0 char *BLI_strncpy_utf8(char *dst, const char *src, size_t maxncpy) { - char *dst_r= dst; + char *dst_r = dst; + + BLI_assert(maxncpy != 0); /* note: currently we don't attempt to deal with invalid utf8 chars */ BLI_STR_UTF8_CPY(dst, src, maxncpy); @@ -207,14 +213,17 @@ char *BLI_strncat_utf8(char *dst, const char *src, size_t maxncpy) /* --------------------------------------------------------------------------*/ /* wchar_t / utf8 functions */ -size_t BLI_strncpy_wchar_as_utf8(char *dst, const wchar_t *src, const size_t maxcpy) +size_t BLI_strncpy_wchar_as_utf8(char *dst, const wchar_t *src, const size_t maxncpy) { size_t len = 0; - while (*src && len < maxcpy) { /* XXX can still run over the buffer because utf8 size isn't known :| */ + + BLI_assert(maxncpy != 0); + + while (*src && len < maxncpy) { /* XXX can still run over the buffer because utf8 size isn't known :| */ len += BLI_str_utf8_from_unicode(*src++, dst + len); } - dst[len]= '\0'; + dst[len] = '\0'; return len; } @@ -231,33 +240,56 @@ size_t BLI_wstrlen_utf8(const wchar_t *src) return len; } -// utf8slen +/* this is very close to 'BLI_str_utf8_size' functionality, perhaps we should de-duplicate */ +/* size of UTF-8 character in bytes */ +static size_t strlen_utf8_char(const char *strc) +{ + if ((*strc & 0xe0) == 0xc0) { + if ((strc[1] & 0x80) && (strc[1] & 0x40) == 0x00) + return 2; + } + else if ((*strc & 0xf0) == 0xe0) { + if ((strc[1] & strc[2] & 0x80) && ((strc[1] | strc[2]) & 0x40) == 0x00) + return 3; + } + else if ((*strc & 0xf8) == 0xf0) { + if ((strc[1] & strc[2] & strc[3] & 0x80) && ((strc[1] | strc[2] | strc[3]) & 0x40) == 0x00) + return 4; + } + + return 1; +} + size_t BLI_strlen_utf8(const char *strc) { - int len = 0; + int len; - while (*strc) { - if ((*strc & 0xe0) == 0xc0) { - if ((strc[1] & 0x80) && (strc[1] & 0x40) == 0x00) - strc++; - } - else if ((*strc & 0xf0) == 0xe0) { - if ((strc[1] & strc[2] & 0x80) && ((strc[1] | strc[2]) & 0x40) == 0x00) - strc += 2; - } - else if ((*strc & 0xf8) == 0xf0) { - if ((strc[1] & strc[2] & strc[3] & 0x80) && ((strc[1] | strc[2] | strc[3]) & 0x40) == 0x00) - strc += 3; - } + for (len = 0; *strc; len++) + strc += strlen_utf8_char(strc); - strc++; - len++; + return len; +} + +/** + * \param start the string to measure the length. + * \param maxlen the string length (in bytes) + * \return the unicode length (not in bytes!) + */ +size_t BLI_strnlen_utf8(const char *start, const size_t maxlen) +{ + const char *strc = start; + const char *strc_end = start + maxlen; + + size_t len; + + for (len = 0; *strc && strc < strc_end; len++) { + strc += strlen_utf8_char(strc); } return len; } -size_t BLI_strncpy_wchar_from_utf8(wchar_t *dst_w, const char *src_c, const size_t maxcpy) +size_t BLI_strncpy_wchar_from_utf8(wchar_t *dst_w, const char *src_c, const size_t maxncpy) { int len = 0; @@ -265,16 +297,16 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *dst_w, const char *src_c, const size return 0; } - while (*src_c && len < maxcpy) { - size_t step= 0; - unsigned int unicode= BLI_str_utf8_as_unicode_and_size(src_c, &step); + while (*src_c && len < maxncpy) { + size_t step = 0; + unsigned int unicode = BLI_str_utf8_as_unicode_and_size(src_c, &step); if (unicode != BLI_UTF8_ERR) { - *dst_w= (wchar_t)unicode; + *dst_w = (wchar_t)unicode; src_c += step; } else { *dst_w = '?'; - src_c= BLI_str_find_next_char_utf8(src_c, NULL); + src_c = BLI_str_find_next_char_utf8(src_c, NULL); } dst_w++; len++; @@ -397,13 +429,13 @@ unsigned int BLI_str_utf8_as_unicode_step(const char *p, size_t *index) unsigned char c; p += *index; - c= (unsigned char) *p; + c = (unsigned char) *p; UTF8_COMPUTE (c, mask, len); if (len == -1) { /* when called with NULL end, result will never be NULL, * checks for a NULL character */ - char *p_next= BLI_str_find_next_char_utf8(p, NULL); + char *p_next = BLI_str_find_next_char_utf8(p, NULL); /* will never return the same pointer unless '\0', * eternal loop is prevented */ *index += (size_t)(p_next - p); @@ -420,8 +452,8 @@ unsigned int BLI_str_utf8_as_unicode_step(const char *p, size_t *index) * characters */ UTF8_GET (result, p, i, mask, len, BLI_UTF8_ERR); if (result == BLI_UTF8_ERR) { - len= 1; - result= *p; + len = 1; + result = *p; } /* end warning! */ #else diff --git a/source/blender/blenlib/intern/time.c b/source/blender/blenlib/intern/time.c index bf9720fee09..078fc2c295b 100644 --- a/source/blender/blenlib/intern/time.c +++ b/source/blender/blenlib/intern/time.c @@ -44,7 +44,7 @@ double PIL_check_seconds_timer(void) __int64 ifreq; hasperfcounter = QueryPerformanceFrequency((LARGE_INTEGER *) &ifreq); perffreq = (double) ifreq; - } + } if (hasperfcounter) { __int64 count; diff --git a/source/blender/blenlib/intern/uvproject.c b/source/blender/blenlib/intern/uvproject.c index 1b59dc6a3f5..05ebc9500a1 100644 --- a/source/blender/blenlib/intern/uvproject.c +++ b/source/blender/blenlib/intern/uvproject.c @@ -105,7 +105,7 @@ void BLI_uvproject_from_view(float target[2], float source[3], float persmat[4][ /* rotmat is the object matrix in this case */ mul_m4_v4(rotmat, pv4); - /* almost project_short */ + /* almost ED_view3d_project_short */ mul_m4_v4(persmat, pv4); if (fabsf(pv4[3]) > 0.00001f) { /* avoid division by zero */ target[0] = winx / 2.0f + (winx / 2.0f) * pv4[0] / pv4[3]; diff --git a/source/blender/blenlib/intern/voronoi.c b/source/blender/blenlib/intern/voronoi.c index 3030e54eb78..0d411038b3e 100644 --- a/source/blender/blenlib/intern/voronoi.c +++ b/source/blender/blenlib/intern/voronoi.c @@ -39,7 +39,7 @@ #include "BLI_voronoi.h" #include "BLI_utildefines.h" -#define VORONOI_EPS 1e-2 +#define VORONOI_EPS 1e-2f enum { voronoiEventType_Site = 0, @@ -259,9 +259,9 @@ static float voronoi_getXOfEdge(VoronoiProcess *process, VoronoiParabola *par, f x2 = (-b - sqrtf(disc)) / (2 * a); if (p[1] < r[1]) - ry = maxf(x1, x2); + ry = max_ff(x1, x2); else - ry = minf(x1, x2); + ry = min_ff(x1, x2); return ry; } @@ -490,9 +490,9 @@ static void voronoi_finishEdge(VoronoiProcess *process, VoronoiParabola *parabol } if (parabola->edge->direction[0] > 0.0f) - mx = MAX2(process->width, parabola->edge->start[0] + 10); + mx = max_ff(process->width, parabola->edge->start[0] + 10); else - mx = MIN2(0.0, parabola->edge->start[0] - 10); + mx = min_ff(0.0f, parabola->edge->start[0] - 10.0f); parabola->edge->end[0] = mx; parabola->edge->end[1] = mx * parabola->edge->f + parabola->edge->g; diff --git a/source/blender/blenlib/intern/voxel.c b/source/blender/blenlib/intern/voxel.c index bc775cb8f0c..5d58f9e9231 100644 --- a/source/blender/blenlib/intern/voxel.c +++ b/source/blender/blenlib/intern/voxel.c @@ -117,19 +117,19 @@ float BLI_voxel_sample_triquadratic(float *data, const int res[3], const float c const int zc[3] = {res[0] * res[1] * _clamp(z - 1, 0, res[2] - 1), res[0] * res[1] * _clamp(z, 0, res[2] - 1), res[0] * res[1] * _clamp(z + 1, 0, res[2] - 1)}; const float dx = xf - (float)x, dy = yf - (float)y, dz = zf - (float)z; - const float u[3] = {dx*(0.5f*dx - 1.f) + 0.5f, dx*(1.f - dx) + 0.5f, 0.5f*dx*dx}; - const float v[3] = {dy*(0.5f*dy - 1.f) + 0.5f, dy*(1.f - dy) + 0.5f, 0.5f*dy*dy}; - const float w[3] = {dz*(0.5f*dz - 1.f) + 0.5f, dz*(1.f - dz) + 0.5f, 0.5f*dz*dz}; + const float u[3] = {dx * (0.5f * dx - 1.f) + 0.5f, dx * (1.0f - dx) + 0.5f, 0.5f * dx * dx}; + const float v[3] = {dy * (0.5f * dy - 1.f) + 0.5f, dy * (1.0f - dy) + 0.5f, 0.5f * dy * dy}; + const float w[3] = {dz * (0.5f * dz - 1.f) + 0.5f, dz * (1.0f - dz) + 0.5f, 0.5f * dz * dz}; return w[0] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[0]] + u[1] * data[xc[1] + yc[0] + zc[0]] + u[2] * data[xc[2] + yc[0] + zc[0]] ) - + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[0]] + u[1] * data[xc[1] + yc[1] + zc[0]] + u[2] * data[xc[2] + yc[1] + zc[0]] ) - + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[0]] + u[1] * data[xc[1] + yc[2] + zc[0]] + u[2] * data[xc[2] + yc[2] + zc[0]] ) ) - + w[1] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[1]] + u[1] * data[xc[1] + yc[0] + zc[1]] + u[2] * data[xc[2] + yc[0] + zc[1]] ) - + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[1]] + u[1] * data[xc[1] + yc[1] + zc[1]] + u[2] * data[xc[2] + yc[1] + zc[1]] ) - + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[1]] + u[1] * data[xc[1] + yc[2] + zc[1]] + u[2] * data[xc[2] + yc[2] + zc[1]] ) ) - + w[2] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[2]] + u[1] * data[xc[1] + yc[0] + zc[2]] + u[2] * data[xc[2] + yc[0] + zc[2]] ) - + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[2]] + u[1] * data[xc[1] + yc[1] + zc[2]] + u[2] * data[xc[2] + yc[1] + zc[2]] ) - + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[2]] + u[1] * data[xc[1] + yc[2] + zc[2]] + u[2] * data[xc[2] + yc[2] + zc[2]] ) ); + + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[0]] + u[1] * data[xc[1] + yc[1] + zc[0]] + u[2] * data[xc[2] + yc[1] + zc[0]] ) + + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[0]] + u[1] * data[xc[1] + yc[2] + zc[0]] + u[2] * data[xc[2] + yc[2] + zc[0]] ) ) + + w[1] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[1]] + u[1] * data[xc[1] + yc[0] + zc[1]] + u[2] * data[xc[2] + yc[0] + zc[1]] ) + + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[1]] + u[1] * data[xc[1] + yc[1] + zc[1]] + u[2] * data[xc[2] + yc[1] + zc[1]] ) + + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[1]] + u[1] * data[xc[1] + yc[2] + zc[1]] + u[2] * data[xc[2] + yc[2] + zc[1]] ) ) + + w[2] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[2]] + u[1] * data[xc[1] + yc[0] + zc[2]] + u[2] * data[xc[2] + yc[0] + zc[2]] ) + + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[2]] + u[1] * data[xc[1] + yc[1] + zc[2]] + u[2] * data[xc[2] + yc[1] + zc[2]] ) + + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[2]] + u[1] * data[xc[1] + yc[2] + zc[2]] + u[2] * data[xc[2] + yc[2] + zc[2]] ) ); } return 0.f; @@ -179,21 +179,21 @@ float BLI_voxel_sample_tricubic(float *data, const int res[3], const float co[3] } return w[0] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[0]] + u[1] * data[xc[1] + yc[0] + zc[0]] + u[2] * data[xc[2] + yc[0] + zc[0]] + u[3] * data[xc[3] + yc[0] + zc[0]] ) - + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[0]] + u[1] * data[xc[1] + yc[1] + zc[0]] + u[2] * data[xc[2] + yc[1] + zc[0]] + u[3] * data[xc[3] + yc[1] + zc[0]] ) - + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[0]] + u[1] * data[xc[1] + yc[2] + zc[0]] + u[2] * data[xc[2] + yc[2] + zc[0]] + u[3] * data[xc[3] + yc[2] + zc[0]] ) - + v[3] * ( u[0] * data[xc[0] + yc[3] + zc[0]] + u[1] * data[xc[1] + yc[3] + zc[0]] + u[2] * data[xc[2] + yc[3] + zc[0]] + u[3] * data[xc[3] + yc[3] + zc[0]] ) ) - + w[1] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[1]] + u[1] * data[xc[1] + yc[0] + zc[1]] + u[2] * data[xc[2] + yc[0] + zc[1]] + u[3] * data[xc[3] + yc[0] + zc[1]] ) - + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[1]] + u[1] * data[xc[1] + yc[1] + zc[1]] + u[2] * data[xc[2] + yc[1] + zc[1]] + u[3] * data[xc[3] + yc[1] + zc[1]] ) - + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[1]] + u[1] * data[xc[1] + yc[2] + zc[1]] + u[2] * data[xc[2] + yc[2] + zc[1]] + u[3] * data[xc[3] + yc[2] + zc[1]] ) - + v[3] * ( u[0] * data[xc[0] + yc[3] + zc[1]] + u[1] * data[xc[1] + yc[3] + zc[1]] + u[2] * data[xc[2] + yc[3] + zc[1]] + u[3] * data[xc[3] + yc[3] + zc[1]] ) ) - + w[2] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[2]] + u[1] * data[xc[1] + yc[0] + zc[2]] + u[2] * data[xc[2] + yc[0] + zc[2]] + u[3] * data[xc[3] + yc[0] + zc[2]] ) - + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[2]] + u[1] * data[xc[1] + yc[1] + zc[2]] + u[2] * data[xc[2] + yc[1] + zc[2]] + u[3] * data[xc[3] + yc[1] + zc[2]] ) - + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[2]] + u[1] * data[xc[1] + yc[2] + zc[2]] + u[2] * data[xc[2] + yc[2] + zc[2]] + u[3] * data[xc[3] + yc[2] + zc[2]] ) - + v[3] * ( u[0] * data[xc[0] + yc[3] + zc[2]] + u[1] * data[xc[1] + yc[3] + zc[2]] + u[2] * data[xc[2] + yc[3] + zc[2]] + u[3] * data[xc[3] + yc[3] + zc[2]] ) ) - + w[3] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[3]] + u[1] * data[xc[1] + yc[0] + zc[3]] + u[2] * data[xc[2] + yc[0] + zc[3]] + u[3] * data[xc[3] + yc[0] + zc[3]] ) - + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[3]] + u[1] * data[xc[1] + yc[1] + zc[3]] + u[2] * data[xc[2] + yc[1] + zc[3]] + u[3] * data[xc[3] + yc[1] + zc[3]] ) - + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[3]] + u[1] * data[xc[1] + yc[2] + zc[3]] + u[2] * data[xc[2] + yc[2] + zc[3]] + u[3] * data[xc[3] + yc[2] + zc[3]] ) - + v[3] * ( u[0] * data[xc[0] + yc[3] + zc[3]] + u[1] * data[xc[1] + yc[3] + zc[3]] + u[2] * data[xc[2] + yc[3] + zc[3]] + u[3] * data[xc[3] + yc[3] + zc[3]] ) ); + + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[0]] + u[1] * data[xc[1] + yc[1] + zc[0]] + u[2] * data[xc[2] + yc[1] + zc[0]] + u[3] * data[xc[3] + yc[1] + zc[0]] ) + + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[0]] + u[1] * data[xc[1] + yc[2] + zc[0]] + u[2] * data[xc[2] + yc[2] + zc[0]] + u[3] * data[xc[3] + yc[2] + zc[0]] ) + + v[3] * ( u[0] * data[xc[0] + yc[3] + zc[0]] + u[1] * data[xc[1] + yc[3] + zc[0]] + u[2] * data[xc[2] + yc[3] + zc[0]] + u[3] * data[xc[3] + yc[3] + zc[0]] ) ) + + w[1] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[1]] + u[1] * data[xc[1] + yc[0] + zc[1]] + u[2] * data[xc[2] + yc[0] + zc[1]] + u[3] * data[xc[3] + yc[0] + zc[1]] ) + + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[1]] + u[1] * data[xc[1] + yc[1] + zc[1]] + u[2] * data[xc[2] + yc[1] + zc[1]] + u[3] * data[xc[3] + yc[1] + zc[1]] ) + + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[1]] + u[1] * data[xc[1] + yc[2] + zc[1]] + u[2] * data[xc[2] + yc[2] + zc[1]] + u[3] * data[xc[3] + yc[2] + zc[1]] ) + + v[3] * ( u[0] * data[xc[0] + yc[3] + zc[1]] + u[1] * data[xc[1] + yc[3] + zc[1]] + u[2] * data[xc[2] + yc[3] + zc[1]] + u[3] * data[xc[3] + yc[3] + zc[1]] ) ) + + w[2] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[2]] + u[1] * data[xc[1] + yc[0] + zc[2]] + u[2] * data[xc[2] + yc[0] + zc[2]] + u[3] * data[xc[3] + yc[0] + zc[2]] ) + + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[2]] + u[1] * data[xc[1] + yc[1] + zc[2]] + u[2] * data[xc[2] + yc[1] + zc[2]] + u[3] * data[xc[3] + yc[1] + zc[2]] ) + + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[2]] + u[1] * data[xc[1] + yc[2] + zc[2]] + u[2] * data[xc[2] + yc[2] + zc[2]] + u[3] * data[xc[3] + yc[2] + zc[2]] ) + + v[3] * ( u[0] * data[xc[0] + yc[3] + zc[2]] + u[1] * data[xc[1] + yc[3] + zc[2]] + u[2] * data[xc[2] + yc[3] + zc[2]] + u[3] * data[xc[3] + yc[3] + zc[2]] ) ) + + w[3] * ( v[0] * ( u[0] * data[xc[0] + yc[0] + zc[3]] + u[1] * data[xc[1] + yc[0] + zc[3]] + u[2] * data[xc[2] + yc[0] + zc[3]] + u[3] * data[xc[3] + yc[0] + zc[3]] ) + + v[1] * ( u[0] * data[xc[0] + yc[1] + zc[3]] + u[1] * data[xc[1] + yc[1] + zc[3]] + u[2] * data[xc[2] + yc[1] + zc[3]] + u[3] * data[xc[3] + yc[1] + zc[3]] ) + + v[2] * ( u[0] * data[xc[0] + yc[2] + zc[3]] + u[1] * data[xc[1] + yc[2] + zc[3]] + u[2] * data[xc[2] + yc[2] + zc[3]] + u[3] * data[xc[3] + yc[2] + zc[3]] ) + + v[3] * ( u[0] * data[xc[0] + yc[3] + zc[3]] + u[1] * data[xc[1] + yc[3] + zc[3]] + u[2] * data[xc[2] + yc[3] + zc[3]] + u[3] * data[xc[3] + yc[3] + zc[3]] ) ); } return 0.f; diff --git a/source/blender/blenlib/intern/winstuff.c b/source/blender/blenlib/intern/winstuff.c index a0b31f8d5b8..68d9d74cca4 100644 --- a/source/blender/blenlib/intern/winstuff.c +++ b/source/blender/blenlib/intern/winstuff.c @@ -293,7 +293,7 @@ void get_default_root(char *root) root[3] = '\0'; if (GetFileAttributes(root) != 0xFFFFFFFF) { rc = i; - break; + break; } } } @@ -304,7 +304,7 @@ void get_default_root(char *root) root[2] = '\\'; root[3] = '\0'; } - } + } } } diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt index 74df5211dad..3c5812fa513 100644 --- a/source/blender/blenloader/CMakeLists.txt +++ b/source/blender/blenloader/CMakeLists.txt @@ -25,6 +25,7 @@ set(INC . + ../blenfont ../blenkernel ../blenlib ../makesdna @@ -62,4 +63,8 @@ if(WITH_BUILDINFO) add_definitions(-DWITH_BUILDINFO) endif() +if(WITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) +endif() + blender_add_lib(bf_blenloader "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/blenloader/SConscript b/source/blender/blenloader/SConscript index 20b560744b3..49e8869637e 100644 --- a/source/blender/blenloader/SConscript +++ b/source/blender/blenloader/SConscript @@ -3,7 +3,7 @@ Import ('env') sources = env.Glob('intern/*.c') -incs = '. #/intern/guardedalloc ../blenlib ../blenkernel' +incs = '. #/intern/guardedalloc ../blenfont ../blenlib ../blenkernel' incs += ' ../makesdna ../editors/include' incs += ' ../render/extern/include ../makesrna ../nodes ../bmesh ../imbuf' @@ -11,6 +11,9 @@ incs += ' ' + env['BF_ZLIB_INC'] defs = [] +if env['WITH_BF_INTERNATIONAL']: + defs.append('WITH_INTERNATIONAL') + if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): env.BlenderLib ( 'bf_blenloader', sources, Split(incs), defs, libtype=['core','player'], priority = [167,30]) #, cc_compileflags=['/WX'] ) else: diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c index e917ccdf342..e9caa337129 100644 --- a/source/blender/blenloader/intern/readblenentry.c +++ b/source/blender/blenloader/intern/readblenentry.c @@ -175,7 +175,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to else if (bhead->code == DATA) { if (looking) { if (bhead->SDNAnr == DNA_struct_find_nr(fd->filesdna, "PreviewImage") ) { - prv = BLO_library_read_struct(fd, bhead, "PreviewImage"); + prv = BLO_library_read_struct(fd, bhead, "PreviewImage"); if (prv) { memcpy(new_prv, prv, sizeof(PreviewImage)); if (prv->rect[0]) { @@ -183,7 +183,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to new_prv->rect[0] = MEM_callocN(new_prv->w[0] * new_prv->h[0] * sizeof(unsigned int), "prvrect"); bhead = blo_nextbhead(fd, bhead); rect = (unsigned int *)(bhead + 1); - memcpy(new_prv->rect[0], rect, bhead->len); + memcpy(new_prv->rect[0], rect, bhead->len); } else { new_prv->rect[0] = NULL; @@ -194,7 +194,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to new_prv->rect[1] = MEM_callocN(new_prv->w[1] * new_prv->h[1] * sizeof(unsigned int), "prvrect"); bhead = blo_nextbhead(fd, bhead); rect = (unsigned int *)(bhead + 1); - memcpy(new_prv->rect[1], rect, bhead->len); + memcpy(new_prv->rect[1], rect, bhead->len); } else { new_prv->rect[1] = NULL; @@ -265,10 +265,10 @@ BlendFileData *BLO_read_from_file(const char *filepath, ReportList *reports) if (fd) { fd->reports = reports; bfd = blo_read_file_internal(fd, filepath); - blo_freefiledata(fd); + blo_freefiledata(fd); } - return bfd; + return bfd; } BlendFileData *BLO_read_from_memory(void *mem, int memsize, ReportList *reports) @@ -280,10 +280,10 @@ BlendFileData *BLO_read_from_memory(void *mem, int memsize, ReportList *reports) if (fd) { fd->reports = reports; bfd = blo_read_file_internal(fd, ""); - blo_freefiledata(fd); + blo_freefiledata(fd); } - return bfd; + return bfd; } BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFile *memfile, ReportList *reports) @@ -332,10 +332,10 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil } blo_join_main(&mainlist); - blo_freefiledata(fd); + blo_freefiledata(fd); } - return bfd; + return bfd; } void BLO_blendfiledata_free(BlendFileData *bfd) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 8656812f90f..2ea3fb75709 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -105,6 +105,8 @@ #include "BLI_math.h" #include "BLI_edgehash.h" +#include "BLF_translation.h" + #include "BKE_anim.h" #include "BKE_action.h" #include "BKE_armature.h" @@ -133,7 +135,7 @@ #include "BKE_paint.h" #include "BKE_particle.h" #include "BKE_pointcache.h" -#include "BKE_property.h" // for get_ob_property +#include "BKE_property.h" // for BKE_bproperty_object_get #include "BKE_report.h" #include "BKE_sca.h" // for init_actuator #include "BKE_scene.h" @@ -206,7 +208,7 @@ * - join all Mains * - link all LibBlocks and indirect pointers to libblocks * - initialize FileGlobal and copy pointers to Global -*/ + */ /* also occurs in library.c */ /* GS reads the memory pointed at in a specific ordering. There are, @@ -248,6 +250,12 @@ static void convert_tface_mt(FileData *fd, Main *main); * bit kludge but better then doubling up on prints, * we could alternatively have a versions of a report function which forces printing - campbell */ + +static void BKE_reportf_wrap(ReportList *reports, ReportType type, const char *format, ...) +#ifdef __GNUC__ +__attribute__ ((format(printf, 3, 4))) +#endif +; static void BKE_reportf_wrap(ReportList *reports, ReportType type, const char *format, ...) { char fixed_buf[1024]; /* should be long enough */ @@ -810,7 +818,7 @@ static void decode_blender_header(FileData *fd) /* is the file saved in a different endian * than we need ? */ - if (((((char*)&remove_this_endian_test)[0]==1)?L_ENDIAN:B_ENDIAN) != ((header[8]=='v')?L_ENDIAN:B_ENDIAN)) { + if (((((char *)&remove_this_endian_test)[0] == 1) ? L_ENDIAN : B_ENDIAN) != ((header[8] == 'v') ? L_ENDIAN : B_ENDIAN)) { fd->flags |= FD_FLAGS_SWITCH_ENDIAN; } @@ -932,7 +940,7 @@ static int fd_read_from_memfile(FileData *filedata, void *buffer, unsigned int s if (chunkoffset+readsize > chunk->size) readsize= chunk->size-chunkoffset; - memcpy((char*)buffer + totread, chunk->buf + chunkoffset, readsize); + memcpy((char *)buffer + totread, chunk->buf + chunkoffset, readsize); totread += readsize; filedata->seek += readsize; seek += readsize; @@ -970,13 +978,13 @@ static FileData *blo_decode_and_check(FileData *fd, ReportList *reports) if (fd->flags & FD_FLAGS_FILE_OK) { if (!read_file_dna(fd)) { - BKE_reportf(reports, RPT_ERROR, "Failed to read blend file: \"%s\", incomplete", fd->relabase); + BKE_reportf(reports, RPT_ERROR, "Failed to read blend file '%s', incomplete", fd->relabase); blo_freefiledata(fd); fd = NULL; } - } + } else { - BKE_reportf(reports, RPT_ERROR, "Failed to read blend file: \"%s\", not a blend file", fd->relabase); + BKE_reportf(reports, RPT_ERROR, "Failed to read blend file '%s', not a blend file", fd->relabase); blo_freefiledata(fd); fd = NULL; } @@ -993,7 +1001,8 @@ FileData *blo_openblenderfile(const char *filepath, ReportList *reports) gzfile = BLI_gzopen(filepath, "rb"); if (gzfile == (gzFile)Z_NULL) { - BKE_reportf(reports, RPT_ERROR, "Unable to open \"%s\": %s.", filepath, errno ? strerror(errno) : "Unknown error reading file"); + BKE_reportf(reports, RPT_WARNING, "Unable to open '%s': %s", + filepath, errno ? strerror(errno) : TIP_("unknown error reading file")); return NULL; } else { @@ -1011,7 +1020,7 @@ FileData *blo_openblenderfile(const char *filepath, ReportList *reports) FileData *blo_openblendermemory(void *mem, int memsize, ReportList *reports) { if (!mem || memsize"); + BKE_report(reports, RPT_WARNING, "Unable to open blend "); return NULL; } else { @@ -1120,7 +1129,7 @@ int BLO_is_a_library(const char *path, char *dir, char *group) /* the last part of the dir is a .blend file, no group follows */ *fd = '/'; /* put back the removed slash separating the dir and the .blend file name */ } - else { + else { char *gp = fd + 1; // in case we have a .blend file, gp points to the group /* Find the last slash */ @@ -1284,6 +1293,7 @@ void blo_end_image_pointer_map(FileData *fd, Main *oldmain) if (NULL == newimaadr(fd, ibuf)) { /* so was restored */ BLI_remlink(&ima->ibufs, ibuf); ima->bindcode = 0; + ima->tpageflag &= ~IMA_GLBIND_IS_DATA; ima->gputexture = NULL; } } @@ -1622,6 +1632,19 @@ static void IDP_LibLinkProperty(IDProperty *UNUSED(prop), int UNUSED(switch_endi { } +/* ************ READ ID *************** */ + +static void direct_link_id(FileData *fd, ID *id) +{ + /*link direct data of ID properties*/ + if (id->properties) { + id->properties = newdataadr(fd, id->properties); + if (id->properties) { /* this case means the data was written incorrectly, it should not happen */ + IDP_DirectLinkProperty(id->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + } + } +} + /* ************ READ CurveMapping *************** */ /* cuma itself has been read! */ @@ -1713,7 +1736,7 @@ static PreviewImage *direct_link_preview_image(FileData *fd, PreviewImage *old_p /* Legacy Data Support (for Version Patching) ----------------------------- */ -// XXX depreceated - old animation system +// XXX deprecated - old animation system static void lib_link_ipo(FileData *fd, Main *main) { Ipo *ipo; @@ -1730,7 +1753,7 @@ static void lib_link_ipo(FileData *fd, Main *main) } } -// XXX depreceated - old animation system +// XXX deprecated - old animation system static void direct_link_ipo(FileData *fd, Ipo *ipo) { IpoCurve *icu; @@ -1744,7 +1767,7 @@ static void direct_link_ipo(FileData *fd, Ipo *ipo) } } -// XXX depreceated - old animation system +// XXX deprecated - old animation system static void lib_link_nlastrips(FileData *fd, ID *id, ListBase *striplist) { bActionStrip *strip; @@ -1759,7 +1782,7 @@ static void lib_link_nlastrips(FileData *fd, ID *id, ListBase *striplist) } } -// XXX depreceated - old animation system +// XXX deprecated - old animation system static void direct_link_nlastrips(FileData *fd, ListBase *strips) { bActionStrip *strip; @@ -1770,7 +1793,7 @@ static void direct_link_nlastrips(FileData *fd, ListBase *strips) link_list(fd, &strip->modifiers); } -// XXX depreceated - old animation system +// XXX deprecated - old animation system static void lib_link_constraint_channels(FileData *fd, ID *id, ListBase *chanbase) { bConstraintChannel *chan; @@ -1815,7 +1838,7 @@ static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list) for (dvar= driver->variables.first; dvar; dvar= dvar->next) { DRIVER_TARGETS_LOOPER(dvar) - { + { /* only relink if still used */ if (tarIndex < dvar->num_targets) dtar->id = newlibadr(fd, id->lib, dtar->id); @@ -1941,12 +1964,12 @@ static void lib_link_action(FileData *fd, Main *main) if (act->id.flag & LIB_NEED_LINK) { act->id.flag -= LIB_NEED_LINK; -// XXX depreceated - old animation system <<< +// XXX deprecated - old animation system <<< for (chan=act->chanbase.first; chan; chan=chan->next) { chan->ipo = newlibadr_us(fd, act->id.lib, chan->ipo); lib_link_constraint_channels(fd, &act->id, &chan->constraintChannels); } -// >>> XXX depreceated - old animation system +// >>> XXX deprecated - old animation system lib_link_fcurves(fd, &act->id, &act->curves); } @@ -1955,21 +1978,21 @@ static void lib_link_action(FileData *fd, Main *main) static void direct_link_action(FileData *fd, bAction *act) { - bActionChannel *achan; // XXX depreceated - old animation system + bActionChannel *achan; // XXX deprecated - old animation system bActionGroup *agrp; link_list(fd, &act->curves); - link_list(fd, &act->chanbase); // XXX depreceated - old animation system + link_list(fd, &act->chanbase); // XXX deprecated - old animation system link_list(fd, &act->groups); link_list(fd, &act->markers); -// XXX depreceated - old animation system <<< +// XXX deprecated - old animation system <<< for (achan = act->chanbase.first; achan; achan=achan->next) { achan->grp = newdataadr(fd, achan->grp); link_list(fd, &achan->constraintChannels); } -// >>> XXX depreceated - old animation system +// >>> XXX deprecated - old animation system direct_link_fcurves(fd, &act->curves); @@ -2390,6 +2413,14 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree) link_list(fd, &node->inputs); link_list(fd, &node->outputs); + link_list(fd, &node->internal_links); + for (link = node->internal_links.first; link; link = link->next) { + link->fromnode = newdataadr(fd, link->fromnode); + link->fromsock = newdataadr(fd, link->fromsock); + link->tonode = newdataadr(fd, link->tonode); + link->tosock = newdataadr(fd, link->tosock); + } + if (node->type == CMP_NODE_MOVIEDISTORTION) { node->storage = newmclipadr(fd, node->storage); } @@ -2398,8 +2429,18 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree) if (node->storage) { /* could be handlerized at some point */ - if (ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB)) - direct_link_curvemapping(fd, node->storage); + if (ntree->type==NTREE_SHADER) { + if (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB) { + direct_link_curvemapping(fd, node->storage); + } + else if (node->type==SH_NODE_SCRIPT) { + NodeShaderScript *nss = (NodeShaderScript *) node->storage; + nss->bytecode = newdataadr(fd, nss->bytecode); + nss->prop = newdataadr(fd, nss->prop); + if (nss->prop) + IDP_DirectLinkProperty(nss->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + } + } else if (ntree->type==NTREE_COMPOSIT) { if (ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT)) direct_link_curvemapping(fd, node->storage); @@ -2482,7 +2523,7 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist) con->type = CONSTRAINT_TYPE_NULL; } /* own ipo, all constraints have it */ - con->ipo = newlibadr_us(fd, id->lib, con->ipo); // XXX depreceated - old animation system + con->ipo = newlibadr_us(fd, id->lib, con->ipo); // XXX deprecated - old animation system } /* relink all ID-blocks used by the constraints */ @@ -2521,8 +2562,13 @@ static void direct_link_constraints(FileData *fd, ListBase *lb) break; case CONSTRAINT_TYPE_KINEMATIC: { + bKinematicConstraint *data = con->data; + con->lin_error = 0.f; con->rot_error = 0.f; + + /* version patch for runtime flag, was not cleared in some case */ + data->flag &= ~CONSTRAINT_IK_AUTO; } case CONSTRAINT_TYPE_CHILDOF: { @@ -2641,7 +2687,7 @@ static void lib_link_camera(FileData *fd, Main *main) if (ca->id.flag & LIB_NEED_LINK) { if (ca->adt) lib_link_animdata(fd, &ca->id, ca->adt); - ca->ipo = newlibadr_us(fd, ca->id.lib, ca->ipo); // XXX depreceated - old animation system + ca->ipo = newlibadr_us(fd, ca->id.lib, ca->ipo); // XXX deprecated - old animation system ca->dof_ob = newlibadr_us(fd, ca->id.lib, ca->dof_ob); @@ -2677,7 +2723,7 @@ static void lib_link_lamp(FileData *fd, Main *main) } } - la->ipo = newlibadr_us(fd, la->id.lib, la->ipo); // XXX depreceated - old animation system + la->ipo = newlibadr_us(fd, la->id.lib, la->ipo); // XXX deprecated - old animation system if (la->nodetree) lib_link_ntree(fd, &la->id, la->nodetree); @@ -2703,14 +2749,26 @@ static void direct_link_lamp(FileData *fd, Lamp *la) direct_link_curvemapping(fd, la->curfalloff); la->nodetree= newdataadr(fd, la->nodetree); - if (la->nodetree) + if (la->nodetree) { + direct_link_id(fd, &la->nodetree->id); direct_link_nodetree(fd, la->nodetree); + } la->preview = direct_link_preview_image(fd, la->preview); } /* ************ READ keys ***************** */ +static void do_versions_key_uidgen(Key *key) +{ + KeyBlock *block; + + key->uidgen = 1; + for (block = key->block.first; block; block = block->next) { + block->uid = key->uidgen++; + } +} + static void lib_link_key(FileData *fd, Main *main) { Key *key; @@ -2718,18 +2776,13 @@ static void lib_link_key(FileData *fd, Main *main) for (key = main->key.first; key; key = key->id.next) { /*check if we need to generate unique ids for the shapekeys*/ if (!key->uidgen) { - KeyBlock *block; - - key->uidgen = 1; - for (block=key->block.first; block; block=block->next) { - block->uid = key->uidgen++; - } + do_versions_key_uidgen(key); } if (key->id.flag & LIB_NEED_LINK) { if (key->adt) lib_link_animdata(fd, &key->id, key->adt); - key->ipo = newlibadr_us(fd, key->id.lib, key->ipo); // XXX depreceated - old animation system + key->ipo = newlibadr_us(fd, key->id.lib, key->ipo); // XXX deprecated - old animation system key->from = newlibadr(fd, key->id.lib, key->from); key->id.flag -= LIB_NEED_LINK; @@ -2762,7 +2815,7 @@ static void switch_endian_keyblock(Key *key, KeyBlock *kb) cp += 2; } - data+= elemsize; + data += elemsize; } } @@ -2797,9 +2850,9 @@ static void lib_link_mball(FileData *fd, Main *main) if (mb->adt) lib_link_animdata(fd, &mb->id, mb->adt); for (a = 0; a < mb->totcol; a++) - mb->mat[a]= newlibadr_us(fd, mb->id.lib, mb->mat[a]); + mb->mat[a] = newlibadr_us(fd, mb->id.lib, mb->mat[a]); - mb->ipo = newlibadr_us(fd, mb->id.lib, mb->ipo); // XXX depreceated - old animation system + mb->ipo = newlibadr_us(fd, mb->id.lib, mb->ipo); // XXX deprecated - old animation system mb->id.flag -= LIB_NEED_LINK; } @@ -2835,7 +2888,7 @@ static void lib_link_world(FileData *fd, Main *main) if (wrld->id.flag & LIB_NEED_LINK) { if (wrld->adt) lib_link_animdata(fd, &wrld->id, wrld->adt); - wrld->ipo = newlibadr_us(fd, wrld->id.lib, wrld->ipo); // XXX depreceated - old animation system + wrld->ipo = newlibadr_us(fd, wrld->id.lib, wrld->ipo); // XXX deprecated - old animation system for (a=0; a < MAX_MTEX; a++) { mtex = wrld->mtex[a]; @@ -2865,8 +2918,10 @@ static void direct_link_world(FileData *fd, World *wrld) } wrld->nodetree = newdataadr(fd, wrld->nodetree); - if (wrld->nodetree) + if (wrld->nodetree) { + direct_link_id(fd, &wrld->nodetree->id); direct_link_nodetree(fd, wrld->nodetree); + } wrld->preview = direct_link_preview_image(fd, wrld->preview); } @@ -2989,6 +3044,7 @@ static void direct_link_image(FileData *fd, Image *ima) /* if not restored, we keep the binded opengl index */ if (ima->ibufs.first == NULL) { ima->bindcode = 0; + ima->tpageflag &= ~IMA_GLBIND_IS_DATA; ima->gputexture = NULL; } @@ -3032,11 +3088,11 @@ static void lib_link_curve(FileData *fd, Main *main) cu->taperobj = newlibadr(fd, cu->id.lib, cu->taperobj); cu->textoncurve = newlibadr(fd, cu->id.lib, cu->textoncurve); cu->vfont = newlibadr_us(fd, cu->id.lib, cu->vfont); - cu->vfontb = newlibadr_us(fd, cu->id.lib, cu->vfontb); + cu->vfontb = newlibadr_us(fd, cu->id.lib, cu->vfontb); cu->vfonti = newlibadr_us(fd, cu->id.lib, cu->vfonti); cu->vfontbi = newlibadr_us(fd, cu->id.lib, cu->vfontbi); - cu->ipo = newlibadr_us(fd, cu->id.lib, cu->ipo); // XXX depreceated - old animation system + cu->ipo = newlibadr_us(fd, cu->id.lib, cu->ipo); // XXX deprecated - old animation system cu->key = newlibadr_us(fd, cu->id.lib, cu->key); cu->id.flag -= LIB_NEED_LINK; @@ -3066,7 +3122,7 @@ static void direct_link_curve(FileData *fd, Curve *cu) cu->mat = newdataadr(fd, cu->mat); test_pointer_array(fd, (void **)&cu->mat); cu->str = newdataadr(fd, cu->str); - cu->strinfo= newdataadr(fd, cu->strinfo); + cu->strinfo= newdataadr(fd, cu->strinfo); cu->tb = newdataadr(fd, cu->tb); if (cu->vfont == NULL) link_list(fd, &(cu->nurb)); @@ -3077,14 +3133,14 @@ static void direct_link_curve(FileData *fd, Curve *cu) if (cu->tb) { memcpy(tb, cu->tb, cu->totbox*sizeof(TextBox)); MEM_freeN(cu->tb); - cu->tb = tb; + cu->tb = tb; } else { cu->totbox = 1; cu->actbox = 1; cu->tb = tb; cu->tb[0].w = cu->linewidth; - } + } if (cu->wordspace == 0.0f) cu->wordspace = 1.0f; } @@ -3173,8 +3229,10 @@ static void direct_link_texture(FileData *fd, Tex *tex) tex->ot = newdataadr(fd, tex->ot); tex->nodetree = newdataadr(fd, tex->nodetree); - if (tex->nodetree) + if (tex->nodetree) { + direct_link_id(fd, &tex->nodetree->id); direct_link_nodetree(fd, tex->nodetree); + } tex->preview = direct_link_preview_image(fd, tex->preview); @@ -3233,8 +3291,10 @@ static void direct_link_material(FileData *fd, Material *ma) ma->ramp_spec = newdataadr(fd, ma->ramp_spec); ma->nodetree = newdataadr(fd, ma->nodetree); - if (ma->nodetree) + if (ma->nodetree) { + direct_link_id(fd, &ma->nodetree->id); direct_link_nodetree(fd, ma->nodetree); + } ma->preview = direct_link_preview_image(fd, ma->preview); ma->gpumaterial.first = ma->gpumaterial.last = NULL; @@ -3249,7 +3309,7 @@ static const char *ptcache_data_struct[] = { "", // BPHYS_DATA_ROTATION "", // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST */ "", // BPHYS_DATA_SIZE: - "", // BPHYS_DATA_TIMES: + "", // BPHYS_DATA_TIMES: "BoidData" // case BPHYS_DATA_BOIDS: }; static void direct_link_pointcache(FileData *fd, PointCache *cache) @@ -3324,6 +3384,8 @@ static void lib_link_partdeflect(FileData *fd, ID *id, PartDeflect *pd) { if (pd && pd->tex) pd->tex = newlibadr_us(fd, id->lib, pd->tex); + if (pd && pd->f_source) + pd->f_source = newlibadr_us(fd, id->lib, pd->f_source); } static void lib_link_particlesettings(FileData *fd, Main *main) @@ -3336,7 +3398,7 @@ static void lib_link_particlesettings(FileData *fd, Main *main) for (part = main->particle.first; part; part = part->id.next) { if (part->id.flag & LIB_NEED_LINK) { if (part->adt) lib_link_animdata(fd, &part->id, part->adt); - part->ipo = newlibadr_us(fd, part->id.lib, part->ipo); // XXX depreceated - old animation system + part->ipo = newlibadr_us(fd, part->id.lib, part->ipo); // XXX deprecated - old animation system part->dup_ob = newlibadr(fd, part->id.lib, part->dup_ob); part->dup_group = newlibadr(fd, part->id.lib, part->dup_group); @@ -3352,32 +3414,31 @@ static void lib_link_particlesettings(FileData *fd, Main *main) if (part->dupliweights.first && part->dup_group) { int index_ok = 0; /* check for old files without indices (all indexes 0) */ - dw = part->dupliweights.first; if (part->dupliweights.first == part->dupliweights.last) { /* special case for only one object in the group */ index_ok = 1; } - else { - for (; dw; dw=dw->next) { + else { + for (dw = part->dupliweights.first; dw; dw = dw->next) { if (dw->index > 0) { index_ok = 1; break; } } } - + if (index_ok) { /* if we have indexes, let's use them */ - dw = part->dupliweights.first; - for (; dw; dw=dw->next) { + for (dw = part->dupliweights.first; dw; dw = dw->next) { GroupObject *go = (GroupObject *)BLI_findlink(&part->dup_group->gobject, dw->index); - dw->ob = go ? go->ob : NULL; + dw->ob = go ? newlibadr(fd, part->id.lib, dw->ob) : NULL; } } else { /* otherwise try to get objects from own library (won't work on library linked groups) */ - for (; dw; dw=dw->next) + for (dw = part->dupliweights.first; dw; dw = dw->next) { dw->ob = newlibadr(fd, part->id.lib, dw->ob); + } } } else { @@ -3556,10 +3617,10 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles) psys->clmd->clothObject = NULL; psys->clmd->sim_parms= newdataadr(fd, psys->clmd->sim_parms); - psys->clmd->sim_parms->effector_weights = NULL; psys->clmd->coll_parms= newdataadr(fd, psys->clmd->coll_parms); if (psys->clmd->sim_parms) { + psys->clmd->sim_parms->effector_weights = NULL; if (psys->clmd->sim_parms->presets > 10) psys->clmd->sim_parms->presets = 0; } @@ -3594,7 +3655,7 @@ static void lib_link_mtface(FileData *fd, Mesh *me, MTFace *mtface, int totface) static void lib_link_customdata_mtface(FileData *fd, Mesh *me, CustomData *fdata, int totface) { - int i; + int i; for (i = 0; i < fdata->totlayer; i++) { CustomDataLayer *layer = &fdata->layers[i]; @@ -3613,12 +3674,13 @@ static void lib_link_customdata_mtpoly(FileData *fd, Mesh *me, CustomData *pdata if (layer->type == CD_MTEXPOLY) { MTexPoly *tf= layer->data; - int i; + int j; - for (i = 0; i < totface; i++, tf++) { + for (j = 0; j < totface; j++, tf++) { tf->tpage = newlibadr(fd, me->id.lib, tf->tpage); - if (tf->tpage && tf->tpage->id.us==0) + if (tf->tpage && tf->tpage->id.us == 0) { tf->tpage->id.us = 1; + } } } } @@ -3654,7 +3716,14 @@ static void lib_link_mesh(FileData *fd, Main *main) if (me->mr && me->mr->levels.first) lib_link_customdata_mtface(fd, me, &me->mr->fdata, ((MultiresLevel*)me->mr->levels.first)->totface); - + } + } + + /* convert texface options to material */ + convert_tface_mt(fd, main); + + for (me = main->mesh.first; me; me = me->id.next) { + if (me->id.flag & LIB_NEED_LINK) { /*check if we need to convert mfaces to mpolys*/ if (me->totface && !me->totpoly) { /* temporarily switch main so that reading from @@ -3666,18 +3735,11 @@ static void lib_link_mesh(FileData *fd, Main *main) G.main = gmain; } - } - } - /* convert texface options to material */ - convert_tface_mt(fd, main); - - for (me = main->mesh.first; me; me = me->id.next) { - if (me->id.flag & LIB_NEED_LINK) { /* * Re-tessellate, even if the polys were just created from tessfaces, this * is important because it: - * - fill the CD_POLYINDEX layer + * - fill the CD_ORIGINDEX layer * - gives consistency of tessface between loading from a file and * converting an edited BMesh back into a mesh (i.e. it replaces * quad tessfaces in a loaded mesh immediately, instead of lazily @@ -3772,7 +3834,7 @@ static void direct_link_customdata(FileData *fd, CustomData *data, int count) /* annoying workaround for bug [#31079] loading legacy files with * no polygons _but_ have stale customdata */ if (UNLIKELY(count == 0 && data->layers == NULL && data->totlayer != 0)) { - memset(data, 0, sizeof(*data)); + CustomData_reset(data); return; } @@ -3810,7 +3872,6 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh) mesh->tface = newdataadr(fd, mesh->tface); mesh->mtface = newdataadr(fd, mesh->mtface); mesh->mcol = newdataadr(fd, mesh->mcol); - mesh->msticky = newdataadr(fd, mesh->msticky); mesh->dvert = newdataadr(fd, mesh->dvert); mesh->mloopcol = newdataadr(fd, mesh->mloopcol); mesh->mloopuv = newdataadr(fd, mesh->mloopuv); @@ -3831,35 +3892,6 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh) direct_link_customdata(fd, &mesh->ldata, mesh->totloop); direct_link_customdata(fd, &mesh->pdata, mesh->totpoly); - -#ifdef USE_BMESH_FORWARD_COMPAT - /* NEVER ENABLE THIS CODE INTO BMESH! - * THIS IS FOR LOADING BMESH INTO OLDER FILES ONLY */ - mesh->mpoly = newdataadr(fd, mesh->mpoly); - mesh->mloop = newdataadr(fd, mesh->mloop); - - direct_link_customdata(fd, &mesh->pdata, mesh->totpoly); - direct_link_customdata(fd, &mesh->ldata, mesh->totloop); - - if (mesh->mpoly) { - /* be clever and load polygons as mfaces */ - mesh->totface= BKE_mesh_mpoly_to_mface(&mesh->fdata, &mesh->ldata, &mesh->pdata, - mesh->totface, mesh->totloop, mesh->totpoly); - - CustomData_free(&mesh->pdata, mesh->totpoly); - memset(&mesh->pdata, 0, sizeof(CustomData)); - mesh->totpoly = 0; - - CustomData_free(&mesh->ldata, mesh->totloop); - memset(&mesh->ldata, 0, sizeof(CustomData)); - mesh->totloop = 0; - - mesh_update_customdata_pointers(mesh); - } - -#endif - - mesh->bb = NULL; mesh->edit_btmesh = NULL; @@ -3927,7 +3959,7 @@ static void lib_link_latt(FileData *fd, Main *main) if (lt->id.flag & LIB_NEED_LINK) { if (lt->adt) lib_link_animdata(fd, <->id, lt->adt); - lt->ipo = newlibadr_us(fd, lt->id.lib, lt->ipo); // XXX depreceated - old animation system + lt->ipo = newlibadr_us(fd, lt->id.lib, lt->ipo); // XXX deprecated - old animation system lt->key = newlibadr_us(fd, lt->id.lib, lt->key); lt->id.flag -= LIB_NEED_LINK; @@ -3981,10 +4013,10 @@ static void lib_link_object(FileData *fd, Main *main) if (ob->id.properties) IDP_LibLinkProperty(ob->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); if (ob->adt) lib_link_animdata(fd, &ob->id, ob->adt); -// XXX depreceated - old animation system <<< +// XXX deprecated - old animation system <<< ob->ipo = newlibadr_us(fd, ob->id.lib, ob->ipo); ob->action = newlibadr_us(fd, ob->id.lib, ob->action); -// >>> XXX depreceated - old animation system +// >>> XXX deprecated - old animation system ob->parent = newlibadr(fd, ob->id.lib, ob->parent); ob->track = newlibadr(fd, ob->id.lib, ob->track); @@ -4063,16 +4095,16 @@ static void lib_link_object(FileData *fd, Main *main) lib_link_pose(fd, ob, ob->pose); lib_link_constraints(fd, &ob->id, &ob->constraints); -// XXX depreceated - old animation system <<< +// XXX deprecated - old animation system <<< lib_link_constraint_channels(fd, &ob->id, &ob->constraintChannels); lib_link_nlastrips(fd, &ob->id, &ob->nlastrips); -// >>> XXX depreceated - old animation system +// >>> XXX deprecated - old animation system for (paf = ob->effect.first; paf; paf = paf->next) { if (paf->type == EFF_PARTICLE) { paf->group = newlibadr_us(fd, ob->id.lib, paf->group); } - } + } for (sens = ob->sensors.first; sens; sens = sens->next) { for (a = 0; a < sens->totlinks; a++) @@ -4336,10 +4368,12 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) if (smd->domain->ptcaches[1].first || smd->domain->point_cache[1]) { if (smd->domain->point_cache[1]) { PointCache *cache = newdataadr(fd, smd->domain->point_cache[1]); - if (cache->flag & PTCACHE_FAKE_SMOKE) - ; /* Smoke was already saved in "new format" and this cache is a fake one. */ - else + if (cache->flag & PTCACHE_FAKE_SMOKE) { + /* Smoke was already saved in "new format" and this cache is a fake one. */ + } + else { printf("High resolution smoke cache not available due to pointcache update. Please reset the simulation.\n"); + } BKE_ptcache_free(cache); } smd->domain->ptcaches[1].first = NULL; @@ -4352,19 +4386,27 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) smd->coll = NULL; smd->flow = newdataadr(fd, smd->flow); smd->flow->smd = smd; + smd->flow->dm = NULL; + smd->flow->verts_old = NULL; + smd->flow->numverts = 0; smd->flow->psys = newdataadr(fd, smd->flow->psys); } else if (smd->type == MOD_SMOKE_TYPE_COLL) { smd->flow = NULL; smd->domain = NULL; smd->coll = newdataadr(fd, smd->coll); - smd->coll->smd = smd; if (smd->coll) { - smd->coll->points = NULL; - smd->coll->numpoints = 0; + smd->coll->smd = smd; + smd->coll->verts_old = NULL; + smd->coll->numverts = 0; + smd->coll->dm = NULL; } - else + else { smd->type = 0; + smd->flow = NULL; + smd->domain = NULL; + smd->coll = NULL; + } } } else if (md->type == eModifierType_DynamicPaint) { @@ -4527,10 +4569,10 @@ static void direct_link_object(FileData *fd, Object *ob) direct_link_motionpath(fd, ob->mpath); link_list(fd, &ob->defbase); -// XXX depreceated - old animation system <<< +// XXX deprecated - old animation system <<< direct_link_nlastrips(fd, &ob->nlastrips); link_list(fd, &ob->constraintChannels); -// >>> XXX depreceated - old animation system +// >>> XXX deprecated - old animation system ob->mat= newdataadr(fd, ob->mat); test_pointer_array(fd, (void **)&ob->mat); @@ -4594,7 +4636,7 @@ static void direct_link_object(FileData *fd, Object *ob) direct_link_partdeflect(ob->pd); ob->soft= newdataadr(fd, ob->soft); if (ob->soft) { - SoftBody *sb = ob->soft; + SoftBody *sb = ob->soft; sb->bpoint = NULL; // init pointers so it gets rebuilt nicely sb->bspring = NULL; @@ -4771,8 +4813,7 @@ static void lib_link_scene(FileData *fd, Main *main) base->object = newlibadr_us(fd, sce->id.lib, base->object); if (base->object == NULL) { - BKE_reportf_wrap(fd->reports, RPT_ERROR, - "LIB ERROR: Object lost from scene:'%s\'", + BKE_reportf_wrap(fd->reports, RPT_WARNING, TIP_("LIB ERROR: object lost from scene: '%s'"), sce->id.name + 2); BLI_remlink(&sce->base, base); if (base == sce->basact) sce->basact = NULL; @@ -5038,7 +5079,7 @@ static void direct_link_scene(FileData *fd, Scene *sce) ed->seqbasep = (ListBase *)(poin+offset); else ed->seqbasep = &ed->seqbase; - } + } /* stack */ link_list(fd, &(ed->metastack)); @@ -5072,7 +5113,7 @@ static void direct_link_scene(FileData *fd, Scene *sce) } if (sce->r.ffcodecdata.properties) { sce->r.ffcodecdata.properties = newdataadr(fd, sce->r.ffcodecdata.properties); - if (sce->r.ffcodecdata.properties) { + if (sce->r.ffcodecdata.properties) { IDP_DirectLinkProperty(sce->r.ffcodecdata.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); } @@ -5083,8 +5124,10 @@ static void direct_link_scene(FileData *fd, Scene *sce) link_list(fd, &(sce->r.layers)); sce->nodetree = newdataadr(fd, sce->nodetree); - if (sce->nodetree) + if (sce->nodetree) { + direct_link_id(fd, &sce->nodetree->id); direct_link_nodetree(fd, sce->nodetree); + } direct_link_view_settings(fd, &sce->view_settings); } @@ -5998,11 +6041,11 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main) if (newmain->curlib) { if (BLI_path_cmp(newmain->curlib->filepath, lib->filepath) == 0) { BKE_reportf_wrap(fd->reports, RPT_WARNING, - "Library '%s', '%s' had multiple instances, save and reload!", + TIP_("Library '%s', '%s' had multiple instances, save and reload!"), lib->name, lib->filepath); change_idid_adr(fd->mainlist, fd, lib, newmain->curlib); -// change_idid_adr_fd(fd, lib, newmain->curlib); +/* change_idid_adr_fd(fd, lib, newmain->curlib); */ BLI_remlink(&main->library, lib); MEM_freeN(lib); @@ -6016,8 +6059,10 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main) BLI_strncpy(lib->filepath, lib->name, sizeof(lib->name)); cleanup_path(fd->relabase, lib->filepath); -// printf("direct_link_library: name %s\n", lib->name); -// printf("direct_link_library: filename %s\n", lib->filename); +#if 0 + printf("direct_link_library: name %s\n", lib->name); + printf("direct_link_library: filename %s\n", lib->filename); +#endif /* new main */ newmain= MEM_callocN(sizeof(Main), "directlink"); @@ -6120,7 +6165,7 @@ static void lib_link_sound(FileData *fd, Main *main) for (sound = main->sound.first; sound; sound = sound->id.next) { if (sound->id.flag & LIB_NEED_LINK) { sound->id.flag -= LIB_NEED_LINK; - sound->ipo = newlibadr_us(fd, sound->id.lib, sound->ipo); // XXX depreceated - old animation system + sound->ipo = newlibadr_us(fd, sound->id.lib, sound->ipo); // XXX deprecated - old animation system sound_load(main, sound); } @@ -6283,6 +6328,14 @@ static void direct_link_mask(FileData *fd, Mask *mask) for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { masklay_shape->data = newdataadr(fd, masklay_shape->data); + + if (masklay_shape->tot_vert) { + if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) { + BLI_endian_switch_float_array(masklay_shape->data, + masklay_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE); + + } + } } masklay->act_spline = newdataadr(fd, masklay->act_spline); @@ -6446,6 +6499,8 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID bhead = read_data_into_oldnewmap(fd, bhead, allocname); /* init pointers direct data */ + direct_link_id(fd, id); + switch (GS(id->name)) { case ID_WM: direct_link_windowmanager(fd, (wmWindowManager *)id); @@ -6542,14 +6597,6 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID break; } - /*link direct data of ID properties*/ - if (id->properties) { - id->properties = newdataadr(fd, id->properties); - if (id->properties) { /* this case means the data was written incorrectly, it should not happen */ - IDP_DirectLinkProperty(id->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); - } - } - oldnewmap_free_unused(fd->datamap); oldnewmap_clear(fd->datamap); @@ -6612,7 +6659,7 @@ void convert_tface_mt(FileData *fd, Main *main) G.main = main; if (!(do_version_tface(main, 1))) { - BKE_report(fd->reports, RPT_WARNING, "Texface conversion problem. Error in console"); + BKE_report(fd->reports, RPT_WARNING, "Texface conversion problem (see error in console)"); } //XXX hack, material.c uses G.main allover the place, instead of main @@ -6785,7 +6832,6 @@ static void do_versions_nodetree_socket_use_flags_2_62(bNodeTree *ntree) static void do_versions_nodetree_multi_file_output_format_2_62_1(Scene *sce, bNodeTree *ntree) { bNode *node; - bNodeSocket *sock; for (node = ntree->nodes.first; node; node = node->next) { if (node->type == CMP_NODE_OUTPUT_FILE) { @@ -6862,6 +6908,7 @@ static void do_versions_nodetree_multi_file_output_format_2_62_1(Scene *sce, bNo } else if (node->type==CMP_NODE_OUTPUT_MULTI_FILE__DEPRECATED) { NodeImageMultiFile *nimf = node->storage; + bNodeSocket *sock; /* CMP_NODE_OUTPUT_MULTI_FILE has been redeclared as CMP_NODE_OUTPUT_FILE */ node->type = CMP_NODE_OUTPUT_FILE; @@ -7015,6 +7062,20 @@ static void do_version_ntree_dilateerode_264(void *UNUSED(data), ID *UNUSED(id), } } +static void do_version_ntree_defocus_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) +{ + bNode *node; + + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == CMP_NODE_DEFOCUS) { + NodeDefocus *data = node->storage; + if (data->maxblur == 0.0f) { + data->maxblur = 16.0f; + } + } + } +} + static void do_version_ntree_mask_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) { bNode *node; @@ -7048,6 +7109,68 @@ static void do_version_ntree_keying_despill_balance(void *UNUSED(data), ID *UNUS } } +static void do_version_ntree_tex_coord_from_dupli_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) +{ + bNode *node; + + for (node = ntree->nodes.first; node; node = node->next) + if (node->type == SH_NODE_TEX_COORD) + node->flag |= NODE_OPTIONS; +} + +static void do_version_node_cleanup_dynamic_sockets_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) +{ + bNode *node; + bNodeSocket *sock; + + for (node = ntree->nodes.first; node; node = node->next) { + if (!ELEM(node->type, NODE_GROUP, CMP_NODE_IMAGE)) { + for (sock = node->inputs.first; sock; sock = sock->next) + sock->flag &= ~SOCK_DYNAMIC; + for (sock = node->outputs.first; sock; sock = sock->next) + sock->flag &= ~SOCK_DYNAMIC; + } + } +} + +static void do_version_node_fix_internal_links_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree) +{ + bNode *node; + bNodeLink *link, *nextlink; + + for (node = ntree->nodes.first; node; node = node->next) { + for (link = node->internal_links.first; link; link = nextlink) { + nextlink = link->next; + if (!link->fromnode || !link->fromsock || !link->tonode || !link->tosock) { + BLI_remlink(&node->internal_links, link); + } + } + } +} + +static void do_version_logic_264(ListBase *regionbase) +{ + ARegion *ar; + + /* view settings for logic changed */ + for (ar = regionbase->first; ar; ar = ar->next) { + if (ar->regiontype == RGN_TYPE_WINDOW) { + if (ar->v2d.keeptot == 0) { + ar->v2d.maxzoom = 1.5f; + + ar->v2d.keepzoom = V2D_KEEPZOOM | V2D_LIMITZOOM | V2D_KEEPASPECT; + ar->v2d.keeptot = V2D_KEEPTOT_BOUNDS; + ar->v2d.align = V2D_ALIGN_NO_POS_Y | V2D_ALIGN_NO_NEG_X; + ar->v2d.keepofs = V2D_KEEPOFS_Y; + } + } + } + + +} + + + static void do_versions(FileData *fd, Library *lib, Main *main) { /* WATCH IT!!!: pointers from libdata have not been converted */ @@ -7161,9 +7284,9 @@ static void do_versions(FileData *fd, Library *lib, Main *main) v3d->bundle_drawtype = OB_PLAINAXES; } else if (sl->spacetype == SPACE_CLIP) { - SpaceClip *sc = (SpaceClip *)sl; - if (sc->scopes.track_preview_height == 0) - sc->scopes.track_preview_height = 120; + SpaceClip *sclip = (SpaceClip *)sl; + if (sclip->scopes.track_preview_height == 0) + sclip->scopes.track_preview_height = 120; } } } @@ -7243,10 +7366,10 @@ static void do_versions(FileData *fd, Library *lib, Main *main) if ( (ob->dsize[i] == 0.0f) || /* simple case, user never touched dsize */ (ob->size[i] == 0.0f)) /* cant scale the dsize to give a non zero result, so fallback to 1.0f */ { - ob->dscale[i]= 1.0f; + ob->dscale[i] = 1.0f; } else { - ob->dscale[i]= (ob->size[i] + ob->dsize[i]) / ob->size[i]; + ob->dscale[i] = (ob->size[i] + ob->dsize[i]) / ob->size[i]; } } } @@ -7368,11 +7491,11 @@ static void do_versions(FileData *fd, Library *lib, Main *main) for (ob= main->object.first; ob; ob= ob->id.next) { if (ob->type == OB_FONT) { - prop = get_ob_property(ob, "Text"); + prop = BKE_bproperty_object_get(ob, "Text"); if (prop) { BKE_reportf_wrap(fd->reports, RPT_WARNING, - "Game property name conflict in object: \"%s\".\nText objects reserve the " - "[\"Text\"] game property to change their content through Logic Bricks.", + TIP_("Game property name conflict in object '%s':\ntext objects reserve the " + "['Text'] game property to change their content through logic bricks"), ob->id.name + 2); } } @@ -7565,13 +7688,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main) if (main->versionfile < 263) { /* Default for old files is to save particle rotations to pointcache */ ParticleSettings *part; - for (part = main->particle.first; part; part = part->id.next) + for (part = main->particle.first; part; part = part->id.next) { part->flag |= PART_ROTATIONS; - { - /* Default for old files is to save particle rotations to pointcache */ - ParticleSettings *part; - for (part = main->particle.first; part; part = part->id.next) - part->flag |= PART_ROTATIONS; } } @@ -7766,6 +7884,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 10)) { { Scene *scene; + bNodeTreeType *ntreetype; // composite redesign for (scene=main->scene.first; scene; scene=scene->id.next) { if (scene->nodetree) { @@ -7774,6 +7893,11 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } } + ntreetype = ntreeGetType(NTREE_COMPOSIT); + + if (ntreetype && ntreetype->foreach_nodetree) + ntreetype->foreach_nodetree(main, NULL, do_version_ntree_defocus_264); + } { @@ -7920,7 +8044,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } /* color management pipeline changes compatibility code */ - { + if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 19)) { Scene *scene; Image *ima; int colormanagement_disabled = FALSE; @@ -7960,6 +8084,260 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 20)) { + Key *key; + for (key = main->key.first; key; key = key->id.next) { + do_versions_key_uidgen(key); + } + } + + /* remove texco */ + if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 21)) { + Material *ma; + for (ma = main->mat.first; ma; ma = ma->id.next) { + int a; + for (a = 0; a < MAX_MTEX; a++) { + if (ma->mtex[a]) { + if (ma->mtex[a]->texco == TEXCO_STICKY_) { + ma->mtex[a]->texco = TEXCO_UV; + } + } + } + } + + { + Mesh *me; + for (me = main->mesh.first; me; me = me->id.next) { + CustomData_update_typemap(&me->vdata); + CustomData_free_layers(&me->vdata, CD_MSTICKY, me->totvert); + } + } + } + + /* correction for files saved in blender version when BKE_pose_copy_data + * didn't copy animation visualization, which lead to deadlocks on motion + * path calculation for proxied armatures, see [#32742] + */ + if (main->versionfile < 264) { + Object *ob; + + for (ob = main->object.first; ob; ob = ob->id.next) { + if (ob->pose) { + if (ob->pose->avs.path_step == 0) { + animviz_settings_init(&ob->pose->avs); + } + } + } + } + + if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 1)) { + bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER); + bNodeTree *ntree; + + if (ntreetype && ntreetype->foreach_nodetree) + ntreetype->foreach_nodetree(main, NULL, do_version_ntree_tex_coord_from_dupli_264); + + for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) + if (ntree->type==NTREE_SHADER) + do_version_ntree_tex_coord_from_dupli_264(NULL, NULL, ntree); + } + + if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 2)) { + MovieClip *clip; + + for (clip = main->movieclip.first; clip; clip = clip->id.next) { + MovieTracking *tracking = &clip->tracking; + MovieTrackingObject *tracking_object; + + for (tracking_object = tracking->objects.first; + tracking_object; + tracking_object = tracking_object->next) + { + if (tracking_object->keyframe1 == 0 && tracking_object->keyframe2 == 0) { + tracking_object->keyframe1 = tracking->settings.keyframe1; + tracking_object->keyframe2 = tracking->settings.keyframe2; + } + } + } + } + + if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 3)) { + /* smoke branch */ + { + Object *ob; + + for (ob = main->object.first; ob; ob = ob->id.next) { + ModifierData *md; + for (md = ob->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_Smoke) { + SmokeModifierData *smd = (SmokeModifierData *)md; + if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) { + /* keep branch saves if possible */ + if (!smd->domain->flame_max_temp) { + smd->domain->burning_rate = 0.75f; + smd->domain->flame_smoke = 1.0f; + smd->domain->flame_vorticity = 0.5f; + smd->domain->flame_ignition = 1.25f; + smd->domain->flame_max_temp = 1.75f; + smd->domain->adapt_threshold = 0.02f; + smd->domain->adapt_margin = 4; + smd->domain->flame_smoke_color[0] = 0.7f; + smd->domain->flame_smoke_color[1] = 0.7f; + smd->domain->flame_smoke_color[2] = 0.7f; + } + } + else if ((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) { + if (!smd->flow->texture_size) { + smd->flow->fuel_amount = 1.0; + smd->flow->surface_distance = 1.5; + smd->flow->color[0] = 0.7f; + smd->flow->color[1] = 0.7f; + smd->flow->color[2] = 0.7f; + smd->flow->texture_size = 1.0f; + } + } + } + } + } + } + + /* render border for viewport */ + { + bScreen *sc; + + for (sc = main->screen.first; sc; sc = sc->id.next) { + ScrArea *sa; + for (sa = sc->areabase.first; sa; sa = sa->next) { + SpaceLink *sl; + for (sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; + if (v3d->render_border.xmin == 0.0f && v3d->render_border.ymin == 0.0f && + v3d->render_border.xmax == 0.0f && v3d->render_border.ymax == 0.0f) + { + v3d->render_border.xmax = 1.0f; + v3d->render_border.ymax = 1.0f; + } + } + } + } + } + } + } + + if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 4)) { + /* Fix for old node flags: Apparently the SOCK_DYNAMIC flag has been in use for other + * purposes before and then removed and later reused for SOCK_DYNAMIC. This socket should + * only be used by certain node types which don't use template lists, cleaning this up here. + */ + bNodeTreeType *ntreetype; + bNodeTree *ntree; + + ntreetype = ntreeGetType(NTREE_COMPOSIT); + if (ntreetype && ntreetype->foreach_nodetree) + ntreetype->foreach_nodetree(main, NULL, do_version_node_cleanup_dynamic_sockets_264); + ntreetype = ntreeGetType(NTREE_SHADER); + if (ntreetype && ntreetype->foreach_nodetree) + ntreetype->foreach_nodetree(main, NULL, do_version_node_cleanup_dynamic_sockets_264); + ntreetype = ntreeGetType(NTREE_TEXTURE); + if (ntreetype && ntreetype->foreach_nodetree) + ntreetype->foreach_nodetree(main, NULL, do_version_node_cleanup_dynamic_sockets_264); + + for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) + do_version_node_cleanup_dynamic_sockets_264(NULL, NULL, ntree); + } + + if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 5)) { + /* set a unwrapping margin and ABF by default */ + Scene *scene; + + for (scene=main->scene.first; scene; scene=scene->id.next) { + if (scene->toolsettings->uvcalc_margin == 0.0f) { + scene->toolsettings->uvcalc_margin = 0.001f; + scene->toolsettings->unwrapper = 0; + } + } + } + + if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 6)) { + /* Fix for bug #32982, internal_links list could get corrupted from r51630 onward. + * Simply remove bad internal_links lists to avoid NULL pointers. + */ + bNodeTreeType *ntreetype; + bNodeTree *ntree; + + ntreetype = ntreeGetType(NTREE_COMPOSIT); + if (ntreetype && ntreetype->foreach_nodetree) + ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_internal_links_264); + ntreetype = ntreeGetType(NTREE_SHADER); + if (ntreetype && ntreetype->foreach_nodetree) + ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_internal_links_264); + ntreetype = ntreeGetType(NTREE_TEXTURE); + if (ntreetype && ntreetype->foreach_nodetree) + ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_internal_links_264); + + for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) + do_version_node_fix_internal_links_264(NULL, NULL, ntree); + + } + + if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 6)) { + bScreen *sc; + + for (sc = main->screen.first; sc; sc = sc->id.next) { + ScrArea *sa; + for (sa = sc->areabase.first; sa; sa = sa->next) { + SpaceLink *sl; + if ( sa->spacetype == SPACE_LOGIC) + do_version_logic_264(&sa->regionbase); + + for (sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_LOGIC) + do_version_logic_264(&sl->regionbase); + } + } + } + } + + if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 7)) { + /* convert tiles size from resolution and number of tiles */ + { + Scene *scene; + + for (scene = main->scene.first; scene; scene = scene->id.next) { + if (scene->r.tilex == 0 || scene->r.tiley == 1) { + /* scene could be set for panoramic rendering, so clamp with the + * lowest possible tile size value + */ + scene->r.tilex = max_ii(scene->r.xsch * scene->r.size / scene->r.xparts / 100, 8); + scene->r.tiley = max_ii(scene->r.ysch * scene->r.size / scene->r.yparts / 100, 8); + } + } + } + + /* collision masks */ + { + Object *ob; + for (ob = main->object.first; ob; ob = ob->id.next) { + if (ob->col_group == 0) { + ob->col_group = 0x01; + ob->col_mask = 0xff; + } + } + } + + /* fallbck resection method settings */ + { + MovieClip *clip; + + for (clip = main->movieclip.first; clip; clip = clip->id.next) { + if (clip->tracking.settings.reconstruction_success_threshold == 0.0f) { + clip->tracking.settings.reconstruction_success_threshold = 1e-3; + } + } + } + } + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */ @@ -7988,7 +8366,7 @@ static void lib_link_all(FileData *fd, Main *main) lib_link_material(fd, main); lib_link_texture(fd, main); lib_link_image(fd, main); - lib_link_ipo(fd, main); // XXX depreceated... still needs to be maintained for version patches still + lib_link_ipo(fd, main); // XXX deprecated... still needs to be maintained for version patches still lib_link_key(fd, main); lib_link_world(fd, main); lib_link_lamp(fd, main); @@ -8324,7 +8702,7 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old) -// XXX depreceated - old animation system +// XXX deprecated - old animation system static void expand_ipo(FileData *fd, Main *mainvar, Ipo *ipo) { IpoCurve *icu; @@ -8334,7 +8712,7 @@ static void expand_ipo(FileData *fd, Main *mainvar, Ipo *ipo) } } -// XXX depreceated - old animation system +// XXX deprecated - old animation system static void expand_constraint_channels(FileData *fd, Main *mainvar, ListBase *chanbase) { bConstraintChannel *chan; @@ -8390,7 +8768,7 @@ static void expand_action(FileData *fd, Main *mainvar, bAction *act) { bActionChannel *chan; - // XXX depreceated - old animation system -------------- + // XXX deprecated - old animation system -------------- for (chan=act->chanbase.first; chan; chan=chan->next) { expand_doit(fd, mainvar, chan->ipo); expand_constraint_channels(fd, mainvar, &chan->constraintChannels); @@ -8480,7 +8858,7 @@ static void expand_group(FileData *fd, Main *mainvar, Group *group) static void expand_key(FileData *fd, Main *mainvar, Key *key) { - expand_doit(fd, mainvar, key->ipo); // XXX depreceated - old animation system + expand_doit(fd, mainvar, key->ipo); // XXX deprecated - old animation system if (key->adt) expand_animdata(fd, mainvar, key->adt); @@ -8506,7 +8884,7 @@ static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree) static void expand_texture(FileData *fd, Main *mainvar, Tex *tex) { expand_doit(fd, mainvar, tex->ima); - expand_doit(fd, mainvar, tex->ipo); // XXX depreceated - old animation system + expand_doit(fd, mainvar, tex->ipo); // XXX deprecated - old animation system if (tex->adt) expand_animdata(fd, mainvar, tex->adt); @@ -8532,7 +8910,7 @@ static void expand_material(FileData *fd, Main *mainvar, Material *ma) } } - expand_doit(fd, mainvar, ma->ipo); // XXX depreceated - old animation system + expand_doit(fd, mainvar, ma->ipo); // XXX deprecated - old animation system if (ma->adt) expand_animdata(fd, mainvar, ma->adt); @@ -8555,7 +8933,7 @@ static void expand_lamp(FileData *fd, Main *mainvar, Lamp *la) } } - expand_doit(fd, mainvar, la->ipo); // XXX depreceated - old animation system + expand_doit(fd, mainvar, la->ipo); // XXX deprecated - old animation system if (la->adt) expand_animdata(fd, mainvar, la->adt); @@ -8566,7 +8944,7 @@ static void expand_lamp(FileData *fd, Main *mainvar, Lamp *la) static void expand_lattice(FileData *fd, Main *mainvar, Lattice *lt) { - expand_doit(fd, mainvar, lt->ipo); // XXX depreceated - old animation system + expand_doit(fd, mainvar, lt->ipo); // XXX deprecated - old animation system expand_doit(fd, mainvar, lt->key); if (lt->adt) @@ -8585,7 +8963,7 @@ static void expand_world(FileData *fd, Main *mainvar, World *wrld) } } - expand_doit(fd, mainvar, wrld->ipo); // XXX depreceated - old animation system + expand_doit(fd, mainvar, wrld->ipo); // XXX deprecated - old animation system if (wrld->adt) expand_animdata(fd, mainvar, wrld->adt); @@ -8616,11 +8994,11 @@ static void expand_curve(FileData *fd, Main *mainvar, Curve *cu) } expand_doit(fd, mainvar, cu->vfont); - expand_doit(fd, mainvar, cu->vfontb); + expand_doit(fd, mainvar, cu->vfontb); expand_doit(fd, mainvar, cu->vfonti); expand_doit(fd, mainvar, cu->vfontbi); expand_doit(fd, mainvar, cu->key); - expand_doit(fd, mainvar, cu->ipo); // XXX depreceated - old animation system + expand_doit(fd, mainvar, cu->ipo); // XXX deprecated - old animation system expand_doit(fd, mainvar, cu->bevobj); expand_doit(fd, mainvar, cu->taperobj); expand_doit(fd, mainvar, cu->textoncurve); @@ -8709,10 +9087,10 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb) id_loop_constraints(lb, expand_constraint_cb, &ced); - /* depreceated manual expansion stuff */ + /* deprecated manual expansion stuff */ for (curcon = lb->first; curcon; curcon = curcon->next) { if (curcon->ipo) - expand_doit(fd, mainvar, curcon->ipo); // XXX depreceated - old animation system + expand_doit(fd, mainvar, curcon->ipo); // XXX deprecated - old animation system } } @@ -8794,7 +9172,7 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) expand_doit(fd, mainvar, ob->gpd); -// XXX depreceated - old animation system (for version patching only) +// XXX deprecated - old animation system (for version patching only) expand_doit(fd, mainvar, ob->ipo); expand_doit(fd, mainvar, ob->action); @@ -8805,7 +9183,7 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) expand_doit(fd, mainvar, strip->act); expand_doit(fd, mainvar, strip->ipo); } -// XXX depreceated - old animation system (for version patching only) +// XXX deprecated - old animation system (for version patching only) if (ob->adt) expand_animdata(fd, mainvar, ob->adt); @@ -8977,7 +9355,7 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce) static void expand_camera(FileData *fd, Main *mainvar, Camera *ca) { - expand_doit(fd, mainvar, ca->ipo); // XXX depreceated - old animation system + expand_doit(fd, mainvar, ca->ipo); // XXX deprecated - old animation system if (ca->adt) expand_animdata(fd, mainvar, ca->adt); @@ -8993,7 +9371,7 @@ static void expand_speaker(FileData *fd, Main *mainvar, Speaker *spk) static void expand_sound(FileData *fd, Main *mainvar, bSound *snd) { - expand_doit(fd, mainvar, snd->ipo); // XXX depreceated - old animation system + expand_doit(fd, mainvar, snd->ipo); // XXX deprecated - old animation system } static void expand_movieclip(FileData *fd, Main *mainvar, MovieClip *clip) @@ -9096,7 +9474,7 @@ static void expand_main(FileData *fd, Main *mainvar) expand_armature(fd, mainvar, (bArmature *)id); break; case ID_AC: - expand_action(fd, mainvar, (bAction *)id); // XXX depreceated - old animation system + expand_action(fd, mainvar, (bAction *)id); // XXX deprecated - old animation system break; case ID_GR: expand_group(fd, mainvar, (Group *)id); @@ -9108,7 +9486,7 @@ static void expand_main(FileData *fd, Main *mainvar) expand_brush(fd, mainvar, (Brush *)id); break; case ID_IP: - expand_ipo(fd, mainvar, (Ipo *)id); // XXX depreceated - old animation system + expand_ipo(fd, mainvar, (Ipo *)id); // XXX deprecated - old animation system break; case ID_PA: expand_particlesettings(fd, mainvar, (ParticleSettings *)id); @@ -9438,7 +9816,7 @@ static void library_append_end(const bContext *C, Main *mainl, FileData **fd, in if ((*fd)->flags & FD_FLAGS_SWITCH_ENDIAN) { blo_freefiledata(*fd); *fd = NULL; - } + } } void BLO_library_append_end(const bContext *C, struct Main *mainl, BlendHandle** bh, int idcode, short flag) @@ -9493,8 +9871,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) if (fd == NULL) { /* printf and reports for now... its important users know this */ - BKE_reportf_wrap(basefd->reports, RPT_INFO, - "read library: '%s', '%s'", + BKE_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read library: '%s', '%s'"), mainptr->curlib->filepath, mainptr->curlib->name); fd = blo_openblenderfile(mainptr->curlib->filepath, basefd->reports); @@ -9547,8 +9924,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) else mainptr->curlib->filedata = NULL; if (fd == NULL) { - BKE_reportf_wrap(basefd->reports, RPT_ERROR, - "Can't find lib '%s'", + BKE_reportf_wrap(basefd->reports, RPT_WARNING, TIP_("Cannot find lib '%s'"), mainptr->curlib->filepath); } } @@ -9566,8 +9942,8 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) append_id_part(fd, mainptr, id, &realid); if (!realid) { - BKE_reportf_wrap(fd->reports, RPT_ERROR, - "LIB ERROR: %s:'%s' missing from '%s'", + BKE_reportf_wrap(fd->reports, RPT_WARNING, + TIP_("LIB ERROR: %s: '%s' missing from '%s'"), BKE_idcode_to_name(GS(id->name)), id->name+2, mainptr->curlib->filepath); } @@ -9598,8 +9974,8 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) idn = id->next; if (id->flag & LIB_READ) { BLI_remlink(lbarray[a], id); - BKE_reportf_wrap(basefd->reports, RPT_ERROR, - "LIB ERROR: %s:'%s' unread libblock missing from '%s'", + BKE_reportf_wrap(basefd->reports, RPT_WARNING, + TIP_("LIB ERROR: %s: '%s' unread lib block missing from '%s'"), BKE_idcode_to_name(GS(id->name)), id->name + 2, mainptr->curlib->filepath); change_idid_adr(mainlist, basefd, id, NULL); diff --git a/source/blender/blenloader/intern/runtime.c b/source/blender/blenloader/intern/runtime.c index eaf725dda9e..5d8a865eea8 100644 --- a/source/blender/blenloader/intern/runtime.c +++ b/source/blender/blenloader/intern/runtime.c @@ -91,7 +91,7 @@ cleanup: if (fd != -1) close(fd); - return res; + return res; } BlendFileData *BLO_read_runtime(const char *path, ReportList *reports) @@ -104,7 +104,7 @@ BlendFileData *BLO_read_runtime(const char *path, ReportList *reports) fd = BLI_open(path, O_BINARY | O_RDONLY, 0); if (fd == -1) { - BKE_reportf(reports, RPT_ERROR, "Unable to open \"%s\": %s.", path, strerror(errno)); + BKE_reportf(reports, RPT_ERROR, "Unable to open '%s': %s", path, strerror(errno)); goto cleanup; } @@ -115,18 +115,18 @@ BlendFileData *BLO_read_runtime(const char *path, ReportList *reports) datastart = handle_read_msb_int(fd); if (datastart == -1) { - BKE_reportf(reports, RPT_ERROR, "Unable to read \"%s\" (problem seeking)", path); + BKE_reportf(reports, RPT_ERROR, "Unable to read '%s' (problem seeking)", path); goto cleanup; } else if (read(fd, buf, 8) != 8) { - BKE_reportf(reports, RPT_ERROR, "Unable to read \"%s\" (truncated header)", path); + BKE_reportf(reports, RPT_ERROR, "Unable to read '%s' (truncated header)", path); goto cleanup; } else if (memcmp(buf, "BRUNTIME", 8) != 0) { - BKE_reportf(reports, RPT_ERROR, "Unable to read \"%s\" (not a blend file)", path); + BKE_reportf(reports, RPT_ERROR, "Unable to read '%s' (not a blend file)", path); goto cleanup; } - else { + else { //printf("starting to read runtime from %s at datastart %d\n", path, datastart); lseek(fd, datastart, SEEK_SET); bfd = blo_read_blendafterruntime(fd, path, actualsize - datastart, reports); diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index a4f190c8167..d75339252d9 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -32,7 +32,7 @@ #include "zlib.h" #ifndef WIN32 -# include // for read close +# include /* for read close */ #else # include // for open close read # include "winsock2.h" @@ -652,7 +652,7 @@ static void do_versions_seq_unique_name_all_strips(Scene * sce, ListBase *seqbas Sequence * seq = seqbasep->first; while (seq) { - BKE_seqence_base_unique_name_recursive(&sce->ed->seqbase, seq); + BKE_sequence_base_unique_name_recursive(&sce->ed->seqbase, seq); if (seq->seqbase.first) { do_versions_seq_unique_name_all_strips(sce, &seq->seqbase); } @@ -1134,7 +1134,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main) /* Add default gravity to scenes */ for (sce = main->scene.first; sce; sce = sce->id.next) { if ((sce->physics_settings.flag & PHYS_GLOBAL_GRAVITY) == 0 && - len_v3(sce->physics_settings.gravity) == 0.0f) + is_zero_v3(sce->physics_settings.gravity)) { sce->physics_settings.gravity[0] = sce->physics_settings.gravity[1] = 0.0f; sce->physics_settings.gravity[2] = -9.81f; @@ -2062,7 +2062,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main) { brush->add_col[0] = 1.00f; brush->add_col[1] = 0.39f; - brush->add_col[2] = 0.39f; + brush->add_col[2] = 0.39f; } if (brush->sub_col[0] == 0 && @@ -2333,7 +2333,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main) for (sc = main->screen.first; sc; sc = sc->id.next) { if (sc->redraws_flag == 0) { /* just initialize to default? */ - // XXX: we could also have iterated through areas, and taken them from the first timeline available... + /* XXX: we could also have iterated through areas, and taken them from the first timeline available... */ sc->redraws_flag = TIME_ALL_3D_WIN|TIME_ALL_ANIM_WIN; } } diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index 1cc0d4180ab..8a56e3c2ab8 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -92,7 +92,7 @@ #include "BKE_modifier.h" #include "BKE_particle.h" #include "BKE_pointcache.h" -#include "BKE_property.h" // for get_ob_property +#include "BKE_property.h" // for BKE_bproperty_object_get #include "BKE_scene.h" #include "BKE_sequencer.h" @@ -387,8 +387,6 @@ static void customdata_version_242(Mesh *me) if (!me->vdata.totlayer) { CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, me->mvert, me->totvert); - if (me->msticky) - CustomData_add_layer(&me->vdata, CD_MSTICKY, CD_ASSIGN, me->msticky, me->totvert); if (me->dvert) CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_ASSIGN, me->dvert, me->totvert); } @@ -945,7 +943,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) while (act) { if (act->type == ACT_IPO) { ia = act->data; - prop = get_ob_property(ob, ia->name); + prop = BKE_bproperty_object_get(ob, ia->name); if (prop) { ia->type = ACT_IPO_FROM_PROP; } @@ -1239,7 +1237,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) TFace *tf = &((TFace*) me->tface)[i]; for (j = 0; j < 4; j++) { - char *col = (char*) &tf->col[j]; + char *col = (char *) &tf->col[j]; col[0] = 255; } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index b8d63b3c5d5..8521b43e437 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -30,46 +30,46 @@ /* -FILEFORMAT: IFF-style structure (but not IFF compatible!) - -start file: - BLENDER_V100 12 bytes (versie 1.00) - V = big endian, v = little endian - _ = 4 byte pointer, - = 8 byte pointer - -datablocks: also see struct BHead - 4 chars - int, len data after BHead - void, old pointer - int - int, in case of array: amount of structs - data - ... - ... - -Almost all data in Blender are structures. Each struct saved -gets a BHead header. With BHead the struct can be linked again -and compared with StructDNA . - -WRITE - -Preferred writing order: (not really a must, but why would you do it random?) -Any case: direct data is ALWAYS after the lib block - -(Local file data) -- for each LibBlock - - write LibBlock - - write associated direct data -(External file data) -- per library - - write library block - - per LibBlock - - write the ID of LibBlock -- write TEST (128x128, blend file preview, optional) -- write FileGlobal (some global vars) -- write SDNA -- write USER if filename is ~/X.XX/config/startup.blend -*/ + * FILEFORMAT: IFF-style structure (but not IFF compatible!) + * + * start file: + * BLENDER_V100 12 bytes (versie 1.00) + * V = big endian, v = little endian + * _ = 4 byte pointer, - = 8 byte pointer + * + * datablocks: also see struct BHead + * 4 chars + * int, len data after BHead + * void, old pointer + * int + * int, in case of array: amount of structs + * data + * ... + * ... + * + * Almost all data in Blender are structures. Each struct saved + * gets a BHead header. With BHead the struct can be linked again + * and compared with StructDNA . + * + * WRITE + * + * Preferred writing order: (not really a must, but why would you do it random?) + * Any case: direct data is ALWAYS after the lib block + * + * (Local file data) + * - for each LibBlock + * - write LibBlock + * - write associated direct data + * (External file data) + * - per library + * - write library block + * - per LibBlock + * - write the ID of LibBlock + * - write TEST (128x128, blend file preview, optional) + * - write FileGlobal (some global vars) + * - write SDNA + * - write USER if filename is ~/X.XX/config/startup.blend + */ #include @@ -197,7 +197,7 @@ static WriteData *writedata_new(int file) if (wd == NULL) return NULL; - wd->sdna= DNA_sdna_from_data(DNAstr, DNAlen, 0); + wd->sdna = DNA_sdna_from_data(DNAstr, DNAlen, 0); wd->file= file; @@ -511,7 +511,7 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves) writestruct(wd, DATA, "FCurve", 1, fcu); /* curve data */ - if (fcu->bezt) + if (fcu->bezt) writestruct(wd, DATA, "BezTriple", fcu->totvert, fcu->bezt); if (fcu->fpt) writestruct(wd, DATA, "FPoint", fcu->totvert, fcu->fpt); @@ -720,18 +720,31 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree) write_node_socket(wd, sock); for (sock= node->outputs.first; sock; sock= sock->next) write_node_socket(wd, sock); - + + for (link = node->internal_links.first; link; link = link->next) + writestruct(wd, DATA, "bNodeLink", 1, link); if (node->storage) { /* could be handlerized at some point, now only 1 exception still */ if (ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB)) write_curvemapping(wd, node->storage); + else if (ntree->type==NTREE_SHADER && node->type==SH_NODE_SCRIPT) { + NodeShaderScript *nss = (NodeShaderScript *)node->storage; + if (nss->bytecode) + writedata(wd, DATA, strlen(nss->bytecode)+1, nss->bytecode); + /* Write ID Properties -- and copy this comment EXACTLY for easy finding + * of library blocks that implement this.*/ + if (nss->prop) + IDP_WriteProperty(nss->prop, wd); + writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage); + } else if (ntree->type==NTREE_COMPOSIT && ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT)) write_curvemapping(wd, node->storage); else if (ntree->type==NTREE_TEXTURE && (node->type==TEX_NODE_CURVE_RGB || node->type==TEX_NODE_CURVE_TIME) ) write_curvemapping(wd, node->storage); - else if (ntree->type==NTREE_COMPOSIT && node->type==CMP_NODE_MOVIEDISTORTION) - /* pass */; + else if (ntree->type==NTREE_COMPOSIT && node->type==CMP_NODE_MOVIEDISTORTION) { + /* pass */ + } else writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage); } @@ -776,13 +789,16 @@ typedef struct RenderInfo { char scene_name[MAX_ID_NAME - 2]; } RenderInfo; -static void write_renderinfo(WriteData *wd, Main *mainvar) /* for renderdeamon */ +/* was for historic render-deamon feature, + * now write because it can be easily extracted without + * reading the whole blend file */ +static void write_renderinfo(WriteData *wd, Main *mainvar) { bScreen *curscreen; Scene *sce; RenderInfo data; - /* XXX in future, handle multiple windows with multiple screnes? */ + /* XXX in future, handle multiple windows with multiple screens? */ current_screen_compat(mainvar, &curscreen); for (sce= mainvar->scene.first; sce; sce= sce->id.next) { @@ -884,7 +900,7 @@ static const char *ptcache_data_struct[] = { "", // BPHYS_DATA_ROTATION "", // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST */ "", // BPHYS_DATA_SIZE: - "", // BPHYS_DATA_TIMES: + "", // BPHYS_DATA_TIMES: "BoidData" // case BPHYS_DATA_BOIDS: }; static const char *ptcache_extra_struct[] = { @@ -1237,7 +1253,7 @@ static void write_constraints(WriteData *wd, ListBase *conlist) break; case CONSTRAINT_TYPE_SPLINEIK: { - bSplineIKConstraint *data= (bSplineIKConstraint*)con->data; + bSplineIKConstraint *data = (bSplineIKConstraint *)con->data; /* write points array */ writedata(wd, DATA, sizeof(float)*(data->numpoints), data->points); @@ -1325,7 +1341,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) writestruct(wd, DATA, "ClothCollSettings", 1, clmd->coll_parms); writestruct(wd, DATA, "EffectorWeights", 1, clmd->sim_parms->effector_weights); write_pointcaches(wd, &clmd->ptcaches); - } + } else if (md->type==eModifierType_Smoke) { SmokeModifierData *smd = (SmokeModifierData*) md; @@ -1355,7 +1371,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) writestruct(wd, DATA, "SmokeFlowSettings", 1, smd->flow); else if (smd->type & MOD_SMOKE_TYPE_COLL) writestruct(wd, DATA, "SmokeCollSettings", 1, smd->coll); - } + } else if (md->type==eModifierType_Fluidsim) { FluidsimModifierData *fluidmd = (FluidsimModifierData*) md; @@ -1383,7 +1399,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) writestruct(wd, DATA, "ColorBand", 1, pmd->brush->paint_ramp); writestruct(wd, DATA, "ColorBand", 1, pmd->brush->vel_ramp); } - } + } else if (md->type==eModifierType_Collision) { #if 0 @@ -1603,7 +1619,7 @@ static void write_curves(WriteData *wd, ListBase *idbase) if (cu->vfont) { writedata(wd, DATA, amount_of_chars(cu->str)+1, cu->str); writestruct(wd, DATA, "CharInfo", cu->len+1, cu->strinfo); - writestruct(wd, DATA, "TextBox", cu->totbox, cu->tb); + writestruct(wd, DATA, "TextBox", cu->totbox, cu->tb); } else { /* is also the order of reading */ @@ -1725,9 +1741,10 @@ static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data, writestruct(wd, DATA, structname, datasize, layer->data); } - else + else { printf("%s error: layer '%s':%d - can't be written to file\n", __func__, structname, layer->type); + } } } @@ -1759,6 +1776,9 @@ static void write_meshs(WriteData *wd, ListBase *idbase) backup_mesh.totface = mesh->totface; mesh->totface = 0; /* -- */ + backup_mesh.fdata = mesh->fdata; + memset(&mesh->fdata, 0, sizeof(mesh->fdata)); + /* -- */ #endif /* USE_BMESH_SAVE_WITHOUT_MFACE */ writestruct(wd, ID_ME, "Mesh", 1, mesh); @@ -1782,6 +1802,8 @@ static void write_meshs(WriteData *wd, ListBase *idbase) mesh->mface = backup_mesh.mface; /* -- */ mesh->totface = backup_mesh.totface; + /* -- */ + mesh->fdata = backup_mesh.fdata; #endif /* USE_BMESH_SAVE_WITHOUT_MFACE */ } @@ -1808,13 +1830,13 @@ static void write_meshs(WriteData *wd, ListBase *idbase) mesh->totloop = 0; /* -- */ backup_mesh.fdata = mesh->fdata; - memset(&mesh->fdata, 0, sizeof(CustomData)); + CustomData_reset(&mesh->fdata); /* -- */ backup_mesh.pdata = mesh->pdata; - memset(&mesh->pdata, 0, sizeof(CustomData)); + CustomData_reset(&mesh->pdata); /* -- */ backup_mesh.ldata = mesh->ldata; - memset(&mesh->ldata, 0, sizeof(CustomData)); + CustomData_reset(&mesh->ldata); /* -- */ backup_mesh.edit_btmesh = mesh->edit_btmesh; mesh->edit_btmesh = NULL; @@ -2021,7 +2043,7 @@ static void write_materials(WriteData *wd, ListBase *idbase) write_nodetree(wd, ma->nodetree); } - write_previews(wd, ma->preview); + write_previews(wd, ma->preview); } ma= ma->id.next; } @@ -2077,7 +2099,7 @@ static void write_lamps(WriteData *wd, ListBase *idbase) } if (la->curfalloff) - write_curvemapping(wd, la->curfalloff); + write_curvemapping(wd, la->curfalloff); /* nodetree is integral part of lamps, no libdata */ if (la->nodetree) { @@ -2300,7 +2322,7 @@ static void write_gpencils(WriteData *wd, ListBase *lb) /* write strokes */ for (gps= gpf->strokes.first; gps; gps= gps->next) { writestruct(wd, DATA, "bGPDstroke", 1, gps); - writestruct(wd, DATA, "bGPDspoint", gps->totpoints, gps->points); + writestruct(wd, DATA, "bGPDspoint", gps->totpoints, gps->points); } } } @@ -2536,7 +2558,7 @@ static void write_bone(WriteData *wd, Bone *bone) Bone* cbone; // PATCH for upward compatibility after 2.37+ armature recode - bone->size[0]= bone->size[1]= bone->size[2]= 1.0f; + bone->size[0] = bone->size[1] = bone->size[2] = 1.0f; // Write this bone writestruct(wd, DATA, "Bone", 1, bone); @@ -2995,7 +3017,7 @@ static int do_history(const char *name, ReportList *reports) if (BLI_rename(tempname1, tempname2)) { BKE_report(reports, RPT_ERROR, "Unable to make version backup"); return 1; - } + } hisnr--; } @@ -3022,7 +3044,7 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL file = BLI_open(tempname, O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666); if (file == -1) { - BKE_reportf(reports, RPT_ERROR, "Can't open file %s for writing: %s.", tempname, strerror(errno)); + BKE_reportf(reports, RPT_ERROR, "Cannot open file %s for writing: %s", tempname, strerror(errno)); return 0; } @@ -3070,10 +3092,10 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL /* file save to temporary file was successful */ /* now do reverse file history (move .blend1 -> .blend2, .blend -> .blend1) */ - if (write_flags & G_FILE_HISTORY) { + if (write_flags & G_FILE_HISTORY) { int err_hist = do_history(filepath, reports); if (err_hist) { - BKE_report(reports, RPT_ERROR, "Version backup failed. File saved with @"); + BKE_report(reports, RPT_ERROR, "Version backup failed (file saved with @)"); return 0; } } @@ -3090,23 +3112,23 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL if (0==ret) { /* now rename to real file name, and delete temp @ file too */ if (BLI_rename(gzname, filepath) != 0) { - BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @."); + BKE_report(reports, RPT_ERROR, "Cannot change old file (file saved with @)"); return 0; } BLI_delete(tempname, 0, 0); } else if (-1==ret) { - BKE_report(reports, RPT_ERROR, "Failed opening .gz file."); + BKE_report(reports, RPT_ERROR, "Failed opening .gz file"); return 0; } else if (-2==ret) { - BKE_report(reports, RPT_ERROR, "Failed opening .blend file for compression."); + BKE_report(reports, RPT_ERROR, "Failed opening .blend file for compression"); return 0; } } else if (BLI_rename(tempname, filepath) != 0) { - BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @"); + BKE_report(reports, RPT_ERROR, "Cannot change old file (file saved with @)"); return 0; } diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt index 4bce7a6ff51..d7858ebbc0d 100644 --- a/source/blender/bmesh/CMakeLists.txt +++ b/source/blender/bmesh/CMakeLists.txt @@ -1,4 +1,3 @@ -# $Id: CMakeLists.txt 31746 2010-09-04 05:31:25Z joeedh $ # ***** BEGIN GPL LICENSE BLOCK ***** # # This program is free software; you can redistribute it and/or @@ -26,10 +25,13 @@ set(INC . + ../blenfont ../blenkernel ../blenlib ../makesdna ../../../intern/guardedalloc + ../../../extern/bullet2/src + ../../../intern/opennl/extern ) set(INC_SYS @@ -52,9 +54,13 @@ set(SRC operators/bmo_mirror.c operators/bmo_primitive.c operators/bmo_removedoubles.c + operators/bmo_similar.c + operators/bmo_smooth_laplacian.c + operators/bmo_symmetrize.c operators/bmo_subdivide.c operators/bmo_subdivide.h operators/bmo_triangulate.c + operators/bmo_unsubdivide.c operators/bmo_utils.c operators/bmo_wireframe.c @@ -62,6 +68,10 @@ set(SRC intern/bmesh_construct.h intern/bmesh_core.c intern/bmesh_core.h + intern/bmesh_decimate_collapse.c + intern/bmesh_decimate_dissolve.c + intern/bmesh_decimate_unsubdivide.c + intern/bmesh_decimate.h intern/bmesh_inline.h intern/bmesh_interp.c intern/bmesh_interp.h @@ -108,4 +118,12 @@ if(MSVC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") endif() +if(WITH_BULLET) + add_definitions(-DWITH_BULLET) +endif() + +if(WITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) +endif() + blender_add_lib(bf_bmesh "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/bmesh/SConscript b/source/blender/bmesh/SConscript index fb00aef4d78..6765d57cb3e 100644 --- a/source/blender/bmesh/SConscript +++ b/source/blender/bmesh/SConscript @@ -9,11 +9,20 @@ sources += env.Glob('tools/*.c') incs = [ './', + '../blenfont', '../blenlib', '../makesdna', '../blenkernel', '#/intern/guardedalloc', - ] + '#/extern/bullet2/src', + '#/intern/opennl/extern', ] defs = [] + +if env['WITH_BF_BULLET']: + defs.append('WITH_BULLET') + +if env['WITH_BF_INTERNATIONAL']: + defs.append('WITH_INTERNATIONAL') + env.BlenderLib ( libname = 'bf_bmesh', sources = sources, includes = Split(incs), libtype = ['core','player'], defines=defs, priority=[100, 100], compileflags=cflags ) diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h index 955b1a729c5..a672ec0b6a7 100644 --- a/source/blender/bmesh/bmesh.h +++ b/source/blender/bmesh/bmesh.h @@ -252,6 +252,7 @@ extern "C" { #include "intern/bmesh_construct.h" #include "intern/bmesh_core.h" +#include "intern/bmesh_decimate.h" #include "intern/bmesh_interp.h" #include "intern/bmesh_iterators.h" #include "intern/bmesh_marking.h" diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index 3bd99b748f6..cff7da78ef2 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -225,9 +225,8 @@ enum { BM_ELEM_DRAW = (1 << 5), /* edge display */ - /* we have 1 spare flag which is awesome but since we're limited to 8 - * only add new flags with care! - campbell */ - /* BM_ELEM_SPARE = (1 << 6), */ + /* spare tag, assumed dirty, use define in each function to name based on use */ + // _BM_ELEM_TAG_ALT = (1 << 6), // UNUSED BM_ELEM_INTERNAL_TAG = (1 << 7) /* for low level internal API tagging, * since tools may want to tag verts and diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index 4740140187d..d86a26e19ac 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -380,7 +380,7 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, int n } sub_v3_v3v3(far_vec, far, cent); - far_dist = len_v3(far_vec); /* real dist */ + // far_dist = len_v3(far_vec); /* real dist */ /* UNUSED */ /* --- */ @@ -725,6 +725,7 @@ static void bm_vert_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, const BMVert *source_vertex, BMVert *target_vertex) { if ((source_mesh == target_mesh) && (source_vertex == target_vertex)) { + BLI_assert(!"BMVert: source and targer match"); return; } copy_v3_v3(target_vertex->no, source_vertex->no); @@ -737,6 +738,7 @@ static void bm_edge_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, const BMEdge *source_edge, BMEdge *target_edge) { if ((source_mesh == target_mesh) && (source_edge == target_edge)) { + BLI_assert(!"BMEdge: source and targer match"); return; } CustomData_bmesh_free_block(&target_mesh->edata, &target_edge->head.data); @@ -748,6 +750,7 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, const BMLoop *source_loop, BMLoop *target_loop) { if ((source_mesh == target_mesh) && (source_loop == target_loop)) { + BLI_assert(!"BMLoop: source and targer match"); return; } CustomData_bmesh_free_block(&target_mesh->ldata, &target_loop->head.data); @@ -759,6 +762,7 @@ static void bm_face_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, const BMFace *source_face, BMFace *target_face) { if ((source_mesh == target_mesh) && (source_face == target_face)) { + BLI_assert(!"BMFace: source and targer match"); return; } copy_v3_v3(target_face->no, source_face->no); @@ -781,8 +785,10 @@ void BM_elem_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, const void *sour BLI_assert(sheader->htype == theader->htype); - if (sheader->htype != theader->htype) + if (sheader->htype != theader->htype) { + BLI_assert(!"type mismatch"); return; + } /* First we copy select */ if (BM_elem_flag_test((BMElem *)sheader, BM_ELEM_SELECT)) { @@ -902,8 +908,9 @@ BMesh *BM_mesh_copy(BMesh *bm_old) } f2 = BM_face_create_ngon(bm_new, v, v2, edges, f->len, FALSE); - if (!f2) + if (UNLIKELY(f2 == NULL)) { continue; + } /* use totface in case adding some faces fails */ BM_elem_index_set(f2, (bm_new->totface - 1)); /* set_inline */ diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index f03ce9b8543..0910dd82701 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -28,12 +28,13 @@ #include "MEM_guardedalloc.h" #include "BLI_math_vector.h" - -#include "BKE_DerivedMesh.h" - #include "BLI_listbase.h" #include "BLI_array.h" +#include "BLF_translation.h" + +#include "BKE_DerivedMesh.h" + #include "bmesh.h" #include "intern/bmesh_private.h" @@ -810,7 +811,7 @@ static int bm_loop_reverse_loop(BMesh *bm, BMFace *f int bmesh_loop_reverse(BMesh *bm, BMFace *f) { #ifdef USE_BMESH_HOLES - return bmesh_loop_reverse_loop(bm, f, f->loops.first); + return bm_loop_reverse_loop(bm, f, f->loops.first); #else return bm_loop_reverse_loop(bm, f); #endif @@ -836,8 +837,6 @@ static void bm_elements_systag_disable(void *veles, int tot, int flag) } } -#define FACE_MARK (1 << 10) - static int count_flagged_radial(BMesh *bm, BMLoop *l, int flag) { BMLoop *l2 = l; @@ -962,7 +961,7 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del int rlen = count_flagged_radial(bm, l_iter, _FLAG_JF); if (rlen > 2) { - err = "Input faces do not form a contiguous manifold region"; + err = N_("Input faces do not form a contiguous manifold region"); goto error; } else if (rlen == 1) { @@ -1023,9 +1022,9 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del /* create region face */ newf = BM_face_create_ngon(bm, v1, v2, edges, tote, FALSE); - if (!newf || BMO_error_occurred(bm)) { + if (UNLIKELY(!newf || BMO_error_occurred(bm))) { if (!BMO_error_occurred(bm)) - err = "Invalid boundary region to join faces"; + err = N_("Invalid boundary region to join faces"); goto error; } @@ -1145,6 +1144,8 @@ static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *UNUSED(example)) /** * \brief Split Face Make Edge (SFME) * + * \warning this is a low level function, most likely you want to use #BM_face_split() + * * Takes as input two vertices in a single face. An edge is created which divides the original face * into two distinct regions. One of the regions is assigned to the original face and it is closed off. * The second region has a new face assigned to it. @@ -1188,13 +1189,15 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, { #ifdef USE_BMESH_HOLES BMLoopList *lst, *lst2; +#else + int first_loop_f1; #endif BMFace *f2; BMLoop *l_iter, *l_first; BMLoop *v1loop = NULL, *v2loop = NULL, *f1loop = NULL, *f2loop = NULL; BMEdge *e; - int i, len, f1len, f2len, first_loop_f1; + int i, len, f1len, f2len; /* verify that v1 and v2 are in face */ len = f->len; @@ -1605,10 +1608,10 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_dou BMESH_ASSERT(edok != FALSE); } - /* deallocate edg */ + /* deallocate edge */ bm_kill_only_edge(bm, ke); - /* deallocate verte */ + /* deallocate vertex */ bm_kill_only_vert(bm, kv); /* Validate disk cycle lengths of ov, tv are unchanged */ @@ -1617,7 +1620,7 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_dou edok = bmesh_disk_validate(valence2, tv->e, tv); BMESH_ASSERT(edok != FALSE); - /* Validate loop cycle of all faces attached to oe */ + /* Validate loop cycle of all faces attached to 'oe' */ for (i = 0, l = oe->l; i < radlen; i++, l = l->radial_next) { BMESH_ASSERT(l->e == oe); edok = bmesh_verts_in_edge(l->v, l->next->v, oe); @@ -1798,8 +1801,12 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) * Merges two verts into one (\a v into \a vtarget). * * \return Success + * + * \warning This does't work for collapsing edges, + * where \a v and \a vtarget are connected by an edge + * (assert checks for this case). */ -int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *vtarget) +int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target) { BMEdge *e; @@ -1807,26 +1814,29 @@ int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *vtarget) int i, loops_tot; /* verts already spliced */ - if (v == vtarget) { + if (v == v_target) { return FALSE; } /* we can't modify the vert while iterating so first allocate an array of loops */ loops = BM_iter_as_arrayN(bm, BM_LOOPS_OF_VERT, v, &loops_tot); - for (i = 0; i < loops_tot; i++) { - loops[i]->v = vtarget; + if (loops) { + for (i = 0; i < loops_tot; i++) { + loops[i]->v = v_target; + } + MEM_freeN(loops); } - MEM_freeN(loops); /* move all the edges from v's disk to vtarget's disk */ while ((e = v->e)) { bmesh_disk_edge_remove(e, v); - bmesh_edge_swapverts(e, v, vtarget); - bmesh_disk_edge_append(e, vtarget); + bmesh_edge_swapverts(e, v, v_target); + bmesh_disk_edge_append(e, v_target); + BLI_assert(e->v1 != e->v2); } BM_CHECK_ELEMENT(v); - BM_CHECK_ELEMENT(vtarget); + BM_CHECK_ELEMENT(v_target); /* v is unused now, and can be killed */ BM_vert_kill(bm, v); @@ -1992,27 +2002,32 @@ int BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, * * \note Edges must already have the same vertices. */ -int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *etarget) +int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target) { BMLoop *l; - if (!BM_vert_in_edge(e, etarget->v1) || !BM_vert_in_edge(e, etarget->v2)) { + if (!BM_vert_in_edge(e, e_target->v1) || !BM_vert_in_edge(e, e_target->v2)) { /* not the same vertices can't splice */ + + /* the caller should really make sure this doesn't happen ever + * so assert on release builds */ + BLI_assert(0); + return FALSE; } while (e->l) { l = e->l; - BLI_assert(BM_vert_in_edge(etarget, l->v)); - BLI_assert(BM_vert_in_edge(etarget, l->next->v)); + BLI_assert(BM_vert_in_edge(e_target, l->v)); + BLI_assert(BM_vert_in_edge(e_target, l->next->v)); bmesh_radial_loop_remove(l, e); - bmesh_radial_append(etarget, l); + bmesh_radial_append(e_target, l); } BLI_assert(bmesh_radial_length(e->l) == 0); BM_CHECK_ELEMENT(e); - BM_CHECK_ELEMENT(etarget); + BM_CHECK_ELEMENT(e_target); /* removes from disks too */ BM_edge_kill(bm, e); diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index 491287993df..0667ed9ea1c 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -41,8 +41,8 @@ void BM_edge_kill(BMesh *bm, BMEdge *e); void BM_vert_kill(BMesh *bm, BMVert *v); int bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep); -int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *etarget); -int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *vtarget); +int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target); +int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target); int bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len); diff --git a/source/blender/bmesh/intern/bmesh_decimate.h b/source/blender/bmesh/intern/bmesh_decimate.h new file mode 100644 index 00000000000..04dc0cfd2ea --- /dev/null +++ b/source/blender/bmesh/intern/bmesh_decimate.h @@ -0,0 +1,41 @@ +/* + * ***** 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. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BMESH_DECIMATE_H__ +#define __BMESH_DECIMATE_H__ + +/** \file blender/bmesh/intern/bmesh_decimate.h + * \ingroup bmesh + */ + +void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const int do_triangulate); + +void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int tag_only); +void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations); + +void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries, + BMVert **vinput_arr, const int vinput_len, + BMEdge **einput_arr, const int einput_len); +void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries); + + +#endif /* __BMESH_DECIMATE_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_decimate_collapse.c b/source/blender/bmesh/intern/bmesh_decimate_collapse.c new file mode 100644 index 00000000000..feeb2a926f3 --- /dev/null +++ b/source/blender/bmesh/intern/bmesh_decimate_collapse.c @@ -0,0 +1,949 @@ +/* + * ***** 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. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/bmesh/intern/bmesh_decimate_collapse.c + * \ingroup bmesh + * + * BMesh decimator that uses an edge collapse method. + */ + +#include + +#include "MEM_guardedalloc.h" + +#include "DNA_scene_types.h" + +#include "BLI_math.h" +#include "BLI_quadric.h" +#include "BLI_heap.h" + +#include "BKE_customdata.h" + +#include "bmesh.h" +#include "bmesh_structure.h" +#include "bmesh_decimate.h" /* own include */ + +/* defines for testing */ +#define USE_CUSTOMDATA +#define USE_TRIANGULATE + +/* these checks are for rare cases that we can't avoid since they are valid meshes still */ +#define USE_SAFETY_CHECKS + +#define BOUNDARY_PRESERVE_WEIGHT 100.0f + +typedef enum CD_UseFlag { + CD_DO_VERT = (1 << 0), + CD_DO_EDGE = (1 << 1), + CD_DO_LOOP = (1 << 2) +} CD_UseFlag; + + +/* BMesh Helper Functions + * ********************** */ + +/** + * \param vquadrics must be calloc'd + */ +static void bm_decim_build_quadrics(BMesh *bm, Quadric *vquadrics) +{ + BMIter iter; + BMFace *f; + BMEdge *e; + + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + BMLoop *l_first; + BMLoop *l_iter; + + const float *co = BM_FACE_FIRST_LOOP(f)->v->co; + const float *no = f->no; + const float offset = -dot_v3v3(no, co); + Quadric q; + + BLI_quadric_from_v3_dist(&q, no, offset); + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(l_iter->v)], &q); + } while ((l_iter = l_iter->next) != l_first); + } + + /* boundary edges */ + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (UNLIKELY(BM_edge_is_boundary(e))) { + float edge_vector[3]; + float edge_cross[3]; + sub_v3_v3v3(edge_vector, e->v2->co, e->v1->co); + f = e->l->f; + cross_v3_v3v3(edge_cross, edge_vector, f->no); + + if (fabsf(normalize_v3(edge_cross)) > FLT_EPSILON) { + Quadric q; + BLI_quadric_from_v3_dist(&q, edge_cross, -dot_v3v3(edge_cross, e->v1->co)); + BLI_quadric_mul(&q, BOUNDARY_PRESERVE_WEIGHT); + + BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(e->v1)], &q); + BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(e->v2)], &q); + } + } + } +} + + +static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3], + const Quadric *vquadrics) +{ + /* compute an edge contration target for edge 'e' + * this is computed by summing it's vertices quadrics and + * optimizing the result. */ + Quadric q; + + BLI_quadric_add_qu_ququ(&q, + &vquadrics[BM_elem_index_get(e->v1)], + &vquadrics[BM_elem_index_get(e->v2)]); + + + if (BLI_quadric_optimize(&q, optimize_co)) { + return; /* all is good */ + } + else { + mid_v3_v3v3(optimize_co, e->v1->co, e->v2->co); + } +} + +static void bm_decim_build_edge_cost_single(BMEdge *e, + const Quadric *vquadrics, const float *vweights, + Heap *eheap, HeapNode **eheap_table) +{ + const Quadric *q1, *q2; + float optimize_co[3]; + float cost; + + if (eheap_table[BM_elem_index_get(e)]) { + BLI_heap_remove(eheap, eheap_table[BM_elem_index_get(e)]); + } + + /* check we can collapse, some edges we better not touch */ + if (BM_edge_is_boundary(e)) { + if (e->l->f->len == 3) { + /* pass */ + } + else { + /* only collapse tri's */ + eheap_table[BM_elem_index_get(e)] = NULL; + return; + } + } + else if (BM_edge_is_manifold(e)) { + if ((e->l->f->len == 3) && (e->l->radial_next->f->len == 3)) { + /* pass */ + } + else { + /* only collapse tri's */ + eheap_table[BM_elem_index_get(e)] = NULL; + return; + } + } + else { + eheap_table[BM_elem_index_get(e)] = NULL; + return; + } + + if (vweights) { + if ((vweights[BM_elem_index_get(e->v1)] < FLT_EPSILON) && + (vweights[BM_elem_index_get(e->v2)] < FLT_EPSILON)) + { + /* skip collapsing this edge */ + eheap_table[BM_elem_index_get(e)] = NULL; + return; + } + } + /* end sanity check */ + + + bm_decim_calc_target_co(e, optimize_co, vquadrics); + + q1 = &vquadrics[BM_elem_index_get(e->v1)]; + q2 = &vquadrics[BM_elem_index_get(e->v2)]; + + if (vweights == NULL) { + cost = (BLI_quadric_evaluate(q1, optimize_co) + + BLI_quadric_evaluate(q2, optimize_co)); + } + else { + cost = ((BLI_quadric_evaluate(q1, optimize_co) * vweights[BM_elem_index_get(e->v1)]) + + (BLI_quadric_evaluate(q2, optimize_co) * vweights[BM_elem_index_get(e->v2)])); + } + // print("COST %.12f\n"); + + eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, cost, e); +} + +static void bm_decim_build_edge_cost(BMesh *bm, + const Quadric *vquadrics, const float *vweights, + Heap *eheap, HeapNode **eheap_table) +{ + BMIter iter; + BMEdge *e; + unsigned int i; + + BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { + eheap_table[i] = NULL; /* keep sanity check happy */ + bm_decim_build_edge_cost_single(e, vquadrics, vweights, eheap, eheap_table); + } +} + +#ifdef USE_TRIANGULATE +/* Temp Triangulation + * ****************** */ + +/** + * To keep things simple we can only collapse edges on triangulated data + * (limitation with edge collapse and error calculation functions). + * + * But to avoid annoying users by only giving triangle results, we can + * triangulate, keeping a reference between the faces, then join after + * if the edges don't collapse, this will also allow more choices when + * collapsing edges so even has some advantage over decimating quads + * directly. + * + * \return TRUE if any faces were triangulated. + */ + +static int bm_decim_triangulate_begin(BMesh *bm) +{ + BMIter iter; + BMFace *f; + // int has_quad; // could optimize this a little + int has_cut = FALSE; + + BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); + + /* first clear loop index values */ + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BM_elem_index_set(l_iter, -1); + } while ((l_iter = l_iter->next) != l_first); + + // has_quad |= (f->len == 4) + } + + /* adding new faces as we loop over faces + * is normally best avoided, however in this case its not so bad because any face touched twice + * will already be triangulated*/ + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (f->len == 4) { + BMLoop *f_l[4]; + BMLoop *l_a, *l_b; + + { + BMLoop *l_iter = BM_FACE_FIRST_LOOP(f); + + f_l[0] = l_iter; l_iter = l_iter->next; + f_l[1] = l_iter; l_iter = l_iter->next; + f_l[2] = l_iter; l_iter = l_iter->next; + f_l[3] = l_iter; + } + + if (len_squared_v3v3(f_l[0]->v->co, f_l[2]->v->co) < + len_squared_v3v3(f_l[1]->v->co, f_l[3]->v->co)) + { + l_a = f_l[0]; + l_b = f_l[2]; + } + else { + l_a = f_l[1]; + l_b = f_l[3]; + } + +#ifdef USE_SAFETY_CHECKS + if (BM_edge_exists(l_a->v, l_b->v) == FALSE) +#endif + { + BMFace *f_new; + BMLoop *l_new; + + /* warning, NO_DOUBLE option here isn't handled as nice as it could be + * - if there is a quad that has a free standing edge joining it along + * where we want to split the face, there isnt a good way we can handle this. + * currently that edge will get removed when joining the tris back into a quad. */ + f_new = BM_face_split(bm, f, l_a->v, l_b->v, &l_new, NULL, FALSE); + + if (f_new) { + /* the value of this doesn't matter, only that the 2 loops match and have unique values */ + const int f_index = BM_elem_index_get(f); + + /* since we just split theres only ever 2 loops */ + BLI_assert(BM_edge_is_manifold(l_new->e)); + + BM_elem_index_set(l_new, f_index); + BM_elem_index_set(l_new->radial_next, f_index); + + BM_face_normal_update(f); + BM_face_normal_update(f_new); + + has_cut = TRUE; + } + } + } + } + + BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); + + if (has_cut) { + /* now triangulation is done we need to correct index values */ + BM_mesh_elem_index_ensure(bm, BM_EDGE | BM_FACE); + } + + return has_cut; +} + +static void bm_decim_triangulate_end(BMesh *bm) +{ + /* decimation finished, now re-join */ + BMIter iter; + BMEdge *e; + + /* boundary edges */ + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BMLoop *l_a, *l_b; + if (BM_edge_loop_pair(e, &l_a, &l_b)) { + const int l_a_index = BM_elem_index_get(l_a); + if (l_a_index != -1) { + const int l_b_index = BM_elem_index_get(l_b); + if (l_a_index == l_b_index) { + if (LIKELY(l_a->f->len == 3 && l_b->f->len == 3)) { + if (l_a->v != l_b->v) { /* if this is the case, faces have become flipped */ + /* check we are not making a degenerate quad */ + BMVert *vquad[4] = { + e->v1, + BM_vert_in_edge(e, l_a->next->v) ? l_a->prev->v : l_a->next->v, + e->v2, + BM_vert_in_edge(e, l_b->next->v) ? l_b->prev->v : l_b->next->v, + }; + + BLI_assert(ELEM3(vquad[0], vquad[1], vquad[2], vquad[3]) == FALSE); + BLI_assert(ELEM3(vquad[1], vquad[0], vquad[2], vquad[3]) == FALSE); + BLI_assert(ELEM3(vquad[2], vquad[1], vquad[0], vquad[3]) == FALSE); + BLI_assert(ELEM3(vquad[3], vquad[1], vquad[2], vquad[0]) == FALSE); + + if (is_quad_convex_v3(vquad[0]->co, vquad[1]->co, vquad[2]->co, vquad[3]->co)) { + /* highly unlikely to fail, but prevents possible double-ups */ + BMFace *f[2] = {l_a->f, l_b->f}; + BM_faces_join(bm, f, 2, TRUE); + } + } + } + } + } + } + } +} + +#endif /* USE_TRIANGULATE */ + +/* Edge Collapse Functions + * *********************** */ + +#ifdef USE_CUSTOMDATA + +/** + * \param v is the target to merge into. + */ +static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_clear, BMVert *v_other, + const float customdata_fac) +{ + /* these don't need to be updated, since they will get removed when the edge collapses */ + BMLoop *l_clear, *l_other; + const int is_manifold = BM_edge_is_manifold(l->e); + int side; + + /* l defines the vert to collapse into */ + + /* first find the loop of 'v_other' thats attached to the face of 'l' */ + if (l->v == v_clear) { + l_clear = l; + l_other = l->next; + } + else { + l_clear = l->next; + l_other = l; + } + + BLI_assert(l_clear->v == v_clear); + BLI_assert(l_other->v == v_other); + (void)v_other; /* quiet warnings for release */ + + /* now we have both corners of the face 'l->f' */ + for (side = 0; side < 2; side++) { + int is_seam = FALSE; + void *src[2]; + BMFace *f_exit = is_manifold ? l->radial_next->f : NULL; + BMEdge *e_prev = l->e; + BMLoop *l_first; + BMLoop *l_iter; + float w[2]; + + if (side == 0) { + l_iter = l_first = l_clear; + src[0] = l_clear->head.data; + src[1] = l_other->head.data; + + w[0] = customdata_fac; + w[1] = 1.0f - customdata_fac; + } + else { + l_iter = l_first = l_other; + src[0] = l_other->head.data; + src[1] = l_clear->head.data; + + w[0] = 1.0f - customdata_fac; + w[1] = customdata_fac; + } + + // print_v2("weights", w); + + /* WATCH IT! - should NOT reference (_clear or _other) vars for this while loop */ + + /* walk around the fan using 'e_prev' */ + while (((l_iter = BM_vert_step_fan_loop(l_iter, &e_prev)) != l_first) && (l_iter != NULL)) { + int i; + /* quit once we hit the opposite face, if we have one */ + if (f_exit && UNLIKELY(f_exit == l_iter->f)) { + break; + } + + /* break out unless we find a match */ + is_seam = TRUE; + + /* ok. we have a loop. now be smart with it! */ + for (i = 0; i < bm->ldata.totlayer; i++) { + if (CustomData_layer_has_math(&bm->ldata, i)) { + const int offset = bm->ldata.layers[i].offset; + const int type = bm->ldata.layers[i].type; + void *cd_src, *cd_iter; + + /* todo, make nicer macros for this */ + cd_src = (char *)src[0] + offset; + // cd_dst = (char *)src[1] + offset; // UNUSED + cd_iter = (char *)l_iter->head.data + offset; + + /* detect seams */ + if (CustomData_data_equals(type, cd_src, cd_iter)) { + CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_iter->head.data); + is_seam = FALSE; + } + } + } + + if (is_seam) { + break; + } + } + } +} +#endif /* USE_CUSTOMDATA */ + +/** + * Check if the collapse will result in a degenerate mesh, + * that is - duplicate edges or faces. + * + * This situation could be checked for when calculating collapse cost + * however its quite slow and a degenerate collapse could eventuate + * after the cost is calculated, so instead, check just before collapsing. + */ + +static void bm_edge_tag_enable(BMEdge *e) +{ + BM_elem_flag_enable(e->v1, BM_ELEM_TAG); + BM_elem_flag_enable(e->v2, BM_ELEM_TAG); + if (e->l) { + BM_elem_flag_enable(e->l->f, BM_ELEM_TAG); + if (e->l != e->l->radial_next) { + BM_elem_flag_enable(e->l->radial_next->f, BM_ELEM_TAG); + } + } +} + +static void bm_edge_tag_disable(BMEdge *e) +{ + BM_elem_flag_disable(e->v1, BM_ELEM_TAG); + BM_elem_flag_disable(e->v2, BM_ELEM_TAG); + if (e->l) { + BM_elem_flag_disable(e->l->f, BM_ELEM_TAG); + if (e->l != e->l->radial_next) { + BM_elem_flag_disable(e->l->radial_next->f, BM_ELEM_TAG); + } + } +} + +static int bm_edge_tag_test(BMEdge *e) +{ + /* is the edge or one of its faces tagged? */ + return (BM_elem_flag_test(e->v1, BM_ELEM_TAG) || + BM_elem_flag_test(e->v2, BM_ELEM_TAG) || + (e->l && (BM_elem_flag_test(e->l->f, BM_ELEM_TAG) || + (e->l != e->l->radial_next && + BM_elem_flag_test(e->l->radial_next->f, BM_ELEM_TAG)))) + ); +} + +/* takes the edges loop */ +BLI_INLINE int bm_edge_is_manifold_or_boundary(BMLoop *l) +{ +#if 0 + /* less optimized version of check below */ + return (BM_edge_is_manifold(l->e) || BM_edge_is_boundary(l->e); +#else + /* if the edge is a boundary it points to its self, else this must be a manifold */ + return LIKELY(l) && LIKELY(l->radial_next->radial_next == l); +#endif +} + +static int bm_edge_collapse_is_degenerate(BMEdge *e_first) +{ + /* simply check that there is no overlap between faces and edges of each vert, + * (excluding the 2 faces attached to 'e' and 'e' its self) */ + + BMEdge *e_iter; + + /* clear flags on both disks */ + e_iter = e_first; + do { + if (!bm_edge_is_manifold_or_boundary(e_iter->l)) { + return TRUE; + } + bm_edge_tag_disable(e_iter); + } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v1)) != e_first); + + e_iter = e_first; + do { + if (!bm_edge_is_manifold_or_boundary(e_iter->l)) { + return TRUE; + } + bm_edge_tag_disable(e_iter); + } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first); + + /* now enable one side... */ + e_iter = e_first; + do { + bm_edge_tag_enable(e_iter); + } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v1)) != e_first); + + /* ... except for the edge we will collapse, we know thats shared, + * disable this to avoid false positive. We could be smart and never enable these + * face/edge tags in the first place but easier to do this */ + // bm_edge_tag_disable(e_first); + /* do inline... */ + { +#if 0 + BMIter iter; + BMIter liter; + BMLoop *l; + BMVert *v; + BM_ITER_ELEM (l, &liter, e_first, BM_LOOPS_OF_EDGE) { + BM_elem_flag_disable(l->f, BM_ELEM_TAG); + BM_ITER_ELEM (v, &iter, l->f, BM_VERTS_OF_FACE) { + BM_elem_flag_disable(v, BM_ELEM_TAG); + } + } +#else + /* we know each face is a triangle, no looping/iterators needed here */ + + BMLoop *l_radial; + BMLoop *l_face; + + l_radial = e_first->l; + l_face = l_radial; + BLI_assert(l_face->f->len == 3); + BM_elem_flag_disable(l_face->f, BM_ELEM_TAG); + BM_elem_flag_disable((l_face = l_radial)->v, BM_ELEM_TAG); + BM_elem_flag_disable((l_face = l_face->next)->v, BM_ELEM_TAG); + BM_elem_flag_disable(( l_face->next)->v, BM_ELEM_TAG); + l_face = l_radial->radial_next; + if (l_radial != l_face) { + BLI_assert(l_face->f->len == 3); + BM_elem_flag_disable(l_face->f, BM_ELEM_TAG); + BM_elem_flag_disable((l_face = l_radial->radial_next)->v, BM_ELEM_TAG); + BM_elem_flag_disable((l_face = l_face->next)->v, BM_ELEM_TAG); + BM_elem_flag_disable(( l_face->next)->v, BM_ELEM_TAG); + } +#endif + } + + /* and check for overlap */ + e_iter = e_first; + do { + if (bm_edge_tag_test(e_iter)) { + return TRUE; + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first); + + return FALSE; +} + +/** + * special, highly limited edge collapse function + * intended for speed over flexibiliy. + * can only collapse edges connected to (1, 2) tris. + * + * Important - dont add vert/edge/face data on collapsing! + * + * \param e_clear_other let caller know what edges we remove besides \a e_clear + * \param customdata_flag merge factor, scales from 0 - 1 ('v_clear' -> 'v_other') + */ +static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2], +#ifdef USE_CUSTOMDATA + const CD_UseFlag customdata_flag, + const float customdata_fac +#else + const CD_UseFlag UNUSED(customdata_flag), + const float UNUSED(customdata_fac) +#endif + ) +{ + BMVert *v_other; + + /* disallow collapsing which results in degenerate cases */ + if (bm_edge_collapse_is_degenerate(e_clear)) { + return FALSE; + } + + v_other = BM_edge_other_vert(e_clear, v_clear); + BLI_assert(v_other != NULL); + + if (BM_edge_is_manifold(e_clear)) { + BMLoop *l_a, *l_b; + BMEdge *e_a_other[2], *e_b_other[2]; + int ok; + + ok = BM_edge_loop_pair(e_clear, &l_a, &l_b); + + BLI_assert(ok == TRUE); + BLI_assert(l_a->f->len == 3); + BLI_assert(l_b->f->len == 3); + + /* keep 'v_clear' 0th */ + if (BM_vert_in_edge(l_a->prev->e, v_clear)) { + e_a_other[0] = l_a->prev->e; + e_a_other[1] = l_a->next->e; + } + else { + e_a_other[1] = l_a->prev->e; + e_a_other[0] = l_a->next->e; + } + + if (BM_vert_in_edge(l_b->prev->e, v_clear)) { + e_b_other[0] = l_b->prev->e; + e_b_other[1] = l_b->next->e; + } + else { + e_b_other[1] = l_b->prev->e; + e_b_other[0] = l_b->next->e; + } + + BLI_assert(BM_edge_share_vert(e_a_other[0], e_b_other[0])); + BLI_assert(BM_edge_share_vert(e_a_other[1], e_b_other[1])); + + /* we could assert this case, but better just bail out */ +#if 0 + BLI_assert(e_a_other[0] != e_b_other[0]); + BLI_assert(e_a_other[0] != e_b_other[1]); + BLI_assert(e_b_other[0] != e_a_other[0]); + BLI_assert(e_b_other[0] != e_a_other[1]); +#endif + /* not totally common but we want to avoid */ + if (ELEM(e_a_other[0], e_b_other[0], e_b_other[1]) || + ELEM(e_a_other[1], e_b_other[0], e_b_other[1])) + { + return FALSE; + } + + r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]); + r_e_clear_other[1] = BM_elem_index_get(e_b_other[0]); + +#ifdef USE_CUSTOMDATA + /* before killing, do customdata */ + if (customdata_flag & CD_DO_VERT) { + BM_data_interp_from_verts(bm, v_other, v_clear, v_other, customdata_fac); + } + if (customdata_flag & CD_DO_EDGE) { + BM_data_interp_from_edges(bm, e_a_other[1], e_a_other[0], e_a_other[1], customdata_fac); + BM_data_interp_from_edges(bm, e_b_other[1], e_b_other[0], e_b_other[1], customdata_fac); + } + if (customdata_flag & CD_DO_LOOP) { + bm_edge_collapse_loop_customdata(bm, e_clear->l, v_clear, v_other, customdata_fac); + bm_edge_collapse_loop_customdata(bm, e_clear->l->radial_next, v_clear, v_other, customdata_fac); + } +#endif + + BM_edge_kill(bm, e_clear); + + BM_vert_splice(bm, v_clear, v_other); + + BM_edge_splice(bm, e_a_other[0], e_a_other[1]); + BM_edge_splice(bm, e_b_other[0], e_b_other[1]); + + // BM_mesh_validate(bm); + + return TRUE; + } + else if (BM_edge_is_boundary(e_clear)) { + /* same as above but only one triangle */ + BMLoop *l_a; + BMEdge *e_a_other[2]; + + l_a = e_clear->l; + + BLI_assert(l_a->f->len == 3); + + /* keep 'v_clear' 0th */ + if (BM_vert_in_edge(l_a->prev->e, v_clear)) { + e_a_other[0] = l_a->prev->e; + e_a_other[1] = l_a->next->e; + } + else { + e_a_other[1] = l_a->prev->e; + e_a_other[0] = l_a->next->e; + } + + r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]); + r_e_clear_other[1] = -1; + +#ifdef USE_CUSTOMDATA + /* before killing, do customdata */ + if (customdata_flag & CD_DO_VERT) { + BM_data_interp_from_verts(bm, v_other, v_clear, v_other, customdata_fac); + } + if (customdata_flag & CD_DO_EDGE) { + BM_data_interp_from_edges(bm, e_a_other[1], e_a_other[0], e_a_other[1], customdata_fac); + } + if (customdata_flag & CD_DO_LOOP) { + bm_edge_collapse_loop_customdata(bm, e_clear->l, v_clear, v_other, customdata_fac); + } +#endif + + BM_edge_kill(bm, e_clear); + + BM_vert_splice(bm, v_clear, v_other); + + BM_edge_splice(bm, e_a_other[0], e_a_other[1]); + + // BM_mesh_validate(bm); + + return TRUE; + } + else { + return FALSE; + } +} + + +/* collapse e the edge, removing e->v2 */ +static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, + Quadric *vquadrics, float *vweights, + Heap *eheap, HeapNode **eheap_table, + const CD_UseFlag customdata_flag) +{ + int e_clear_other[2]; + BMVert *v_other = e->v1; + int v_clear_index = BM_elem_index_get(e->v2); /* the vert is removed so only store the index */ + float optimize_co[3]; + float customdata_fac; + + bm_decim_calc_target_co(e, optimize_co, vquadrics); + + /* use for customdata merging */ + if (LIKELY(compare_v3v3(e->v1->co, e->v2->co, FLT_EPSILON) == FALSE)) { + customdata_fac = line_point_factor_v3(optimize_co, e->v1->co, e->v2->co); + +#if 0 + /* simple test for stupid collapse */ + if (customdata_fac < 0.0 - FLT_EPSILON || customdata_fac > 1.0f + FLT_EPSILON) { + return; + } +#endif + } + else { + /* avoid divide by zero */ + customdata_fac = 0.5f; + } + + if (bm_edge_collapse(bm, e, e->v2, e_clear_other, customdata_flag, customdata_fac)) { + /* update collapse info */ + int i; + + if (vweights) { + const int fac = CLAMPIS(customdata_fac, 0.0f, 1.0f); + vweights[BM_elem_index_get(v_other)] = (vweights[v_clear_index] * (1.0f - fac)) + + (vweights[BM_elem_index_get(v_other)] * fac); + } + + e = NULL; /* paranoid safety check */ + + copy_v3_v3(v_other->co, optimize_co); + + /* remove eheap */ + for (i = 0; i < 2; i++) { + /* highly unlikely 'eheap_table[ke_other[i]]' would be NULL, but do for sanity sake */ + if ((e_clear_other[i] != -1) && (eheap_table[e_clear_other[i]] != NULL)) { + BLI_heap_remove(eheap, eheap_table[e_clear_other[i]]); + eheap_table[e_clear_other[i]] = NULL; + } + } + + /* update vertex quadric, add kept vertex from killed vertex */ + BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(v_other)], &vquadrics[v_clear_index]); + + /* update connected normals */ + + /* in fact face normals are not used for progressive updates, no need to update them */ + // BM_vert_normal_update_all(v); + BM_vert_normal_update(v_other); + + /* update error costs and the eheap */ + if (LIKELY(v_other->e)) { + BMEdge *e_iter; + BMEdge *e_first; + e_iter = e_first = v_other->e; + do { + BLI_assert(BM_edge_find_double(e_iter) == NULL); + bm_decim_build_edge_cost_single(e_iter, vquadrics, vweights, eheap, eheap_table); + } while ((e_iter = bmesh_disk_edge_next(e_iter, v_other)) != e_first); + } + +#if 0 + /* optional, update edges around the vertex face fan */ + { + BMIter liter; + BMLoop *l; + BM_ITER_ELEM (l, &liter, v_other, BM_LOOPS_OF_VERT) { + if (l->f->len == 3) { + BMEdge *e_outer; + if (BM_vert_in_edge(l->prev->e, l->v)) + e_outer = l->next->e; + else + e_outer = l->prev->e; + + BLI_assert(BM_vert_in_edge(e_outer, l->v) == FALSE); + + bm_decim_build_edge_cost_single(e_outer, vquadrics, eheap, eheap_table); + } + } + } + /* end optional update */ +#endif + } +} + + +/* Main Decimate Function + * ********************** */ + +/** + * \brief BM_mesh_decimate + * \param bm The mesh + * \param factor face count multiplier [0 - 1] + * \param vertex_weights Optional array of vertex aligned weights [0 - 1], + * a vertex group is the usual source for this. + */ +void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const int do_triangulate) +{ + Heap *eheap; /* edge heap */ + HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */ + Quadric *vquadrics; /* vert index aligned quadrics */ + int tot_edge_orig; + int face_tot_target; + int use_triangulate; + + CD_UseFlag customdata_flag = 0; + +#ifdef USE_TRIANGULATE + /* temp convert quads to triangles */ + use_triangulate = bm_decim_triangulate_begin(bm); +#endif + + + /* alloc vars */ + vquadrics = MEM_callocN(sizeof(Quadric) * bm->totvert, __func__); + /* since some edges may be degenerate, we might be over allocing a little here */ + eheap = BLI_heap_new_ex(bm->totedge); + eheap_table = MEM_callocN(sizeof(HeapNode *) * bm->totedge, __func__); + tot_edge_orig = bm->totedge; + + + /* build initial edge collapse cost data */ + bm_decim_build_quadrics(bm, vquadrics); + + bm_decim_build_edge_cost(bm, vquadrics, vweights, eheap, eheap_table); + + face_tot_target = bm->totface * factor; + bm->elem_index_dirty |= BM_FACE | BM_EDGE | BM_VERT; + + +#ifdef USE_CUSTOMDATA + /* initialize customdata flag, we only need math for loops */ + if (CustomData_has_interp(&bm->vdata)) customdata_flag |= CD_DO_VERT; + if (CustomData_has_interp(&bm->edata)) customdata_flag |= CD_DO_EDGE; + if (CustomData_has_math(&bm->ldata)) customdata_flag |= CD_DO_LOOP; +#endif + + /* iterative edge collapse and maintain the eheap */ + while ((bm->totface > face_tot_target) && (BLI_heap_is_empty(eheap) == FALSE)) { + // const float value = BLI_heap_node_value(BLI_heap_top(eheap)); + BMEdge *e = BLI_heap_popmin(eheap); + BLI_assert(BM_elem_index_get(e) < tot_edge_orig); /* handy to detect corruptions elsewhere */ + + // printf("COST %.10f\n", value); + + /* under normal conditions wont be accessed again, + * but NULL just incase so we don't use freed node */ + eheap_table[BM_elem_index_get(e)] = NULL; + + bm_decim_edge_collapse(bm, e, vquadrics, vweights, eheap, eheap_table, customdata_flag); + } + + +#ifdef USE_TRIANGULATE + if (do_triangulate == FALSE) { + /* its possible we only had triangles, skip this step in that case */ + if (LIKELY(use_triangulate)) { + /* temp convert quads to triangles */ + bm_decim_triangulate_end(bm); + } + } +#endif + + /* free vars */ + MEM_freeN(vquadrics); + MEM_freeN(eheap_table); + BLI_heap_free(eheap, NULL); + + /* testing only */ + // BM_mesh_validate(bm); + + (void)tot_edge_orig; /* quiet release build warning */ +} diff --git a/source/blender/bmesh/intern/bmesh_decimate_dissolve.c b/source/blender/bmesh/intern/bmesh_decimate_dissolve.c new file mode 100644 index 00000000000..d1371a18160 --- /dev/null +++ b/source/blender/bmesh/intern/bmesh_decimate_dissolve.c @@ -0,0 +1,243 @@ +/* + * ***** 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. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/bmesh/intern/bmesh_decimate_dissolve.c + * \ingroup bmesh + * + * BMesh decimator that dissolves flat areas into polygons (ngons). + */ + + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" + +#include "bmesh.h" +#include "bmesh_decimate.h" /* own include */ + +#define UNIT_TO_ANGLE DEG2RADF(90.0f) +#define ANGLE_TO_UNIT (1.0f / UNIT_TO_ANGLE) + +/* multiply vertex edge angle by face angle + * this means we are not left with sharp corners between _almost_ planer faces + * convert angles [0-PI/2] -> [0-1], multiply together, then convert back to radians. */ +static float bm_vert_edge_face_angle(BMVert *v) +{ + const float angle = BM_vert_calc_edge_angle(v); + /* note: could be either edge, it doesn't matter */ + if (v->e && BM_edge_is_manifold(v->e)) { + return ((angle * ANGLE_TO_UNIT) * (BM_edge_calc_face_angle(v->e) * ANGLE_TO_UNIT)) * UNIT_TO_ANGLE; + } + else { + return angle; + } +} + +#undef UNIT_TO_ANGLE +#undef ANGLE_TO_UNIT + +typedef struct DissolveElemWeight { + BMHeader *ele; + float weight; +} DissolveElemWeight; + +static int dissolve_elem_cmp(const void *a1, const void *a2) +{ + const struct DissolveElemWeight *d1 = a1, *d2 = a2; + + if (d1->weight > d2->weight) return 1; + else if (d1->weight < d2->weight) return -1; + return 0; +} + +/** + * \param do_all_verts Collapse all verts between 2 faces - don't check their edge angle. + */ +void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries, + BMVert **vinput_arr, const int vinput_len, + BMEdge **einput_arr, const int einput_len) +{ + const float angle_max = (float)M_PI / 2.0f; + DissolveElemWeight *weight_elems = MEM_mallocN(max_ii(einput_len, vinput_len) * + sizeof(DissolveElemWeight), __func__); + int i, tot_found; + + BMIter iter; + BMEdge *e_iter; + BMEdge **earray; + + int *vert_reverse_lookup; + + /* --- first edges --- */ + + /* wire -> tag */ + BM_ITER_MESH (e_iter, &iter, bm, BM_EDGES_OF_MESH) { + BM_elem_flag_set(e_iter, BM_ELEM_TAG, BM_edge_is_wire(e_iter)); + } + + /* go through and split edge */ + for (i = 0, tot_found = 0; i < einput_len; i++) { + BMEdge *e = einput_arr[i]; + const float angle = BM_edge_calc_face_angle(e); + + if (angle < angle_limit) { + tot_found++; + } + weight_elems[i].ele = (BMHeader *)e; + weight_elems[i].weight = angle; + } + + if (tot_found != 0) { + qsort(weight_elems, einput_len, sizeof(DissolveElemWeight), dissolve_elem_cmp); + + for (i = 0; i < tot_found; i++) { + BMEdge *e = (BMEdge *)weight_elems[i].ele; + + if (/* may have become non-manifold */ + BM_edge_is_manifold(e) && + /* check twice because cumulative effect could dissolve over angle limit */ + (BM_edge_calc_face_angle(e) < angle_limit)) + { + BMFace *nf = BM_faces_join_pair(bm, e->l->f, + e->l->radial_next->f, + e, + FALSE); /* join faces */ + + /* there may be some errors, we don't mind, just move on */ + if (nf) { + BM_face_normal_update(nf); + } + else { + BMO_error_clear(bm); + } + } + } + } + + /* prepare for cleanup */ + BM_mesh_elem_index_ensure(bm, BM_VERT); + vert_reverse_lookup = MEM_mallocN(sizeof(int) * bm->totvert, __func__); + fill_vn_i(vert_reverse_lookup, bm->totvert, -1); + for (i = 0, tot_found = 0; i < vinput_len; i++) { + BMVert *v = vinput_arr[i]; + vert_reverse_lookup[BM_elem_index_get(v)] = i; + } + + /* --- cleanup --- */ + earray = MEM_mallocN(sizeof(BMEdge *) * bm->totedge, __func__); + BM_ITER_MESH_INDEX (e_iter, &iter, bm, BM_EDGES_OF_MESH, i) { + earray[i] = e_iter; + } + /* remove all edges/verts left behind from dissolving, NULL'ing the vertex array so we dont re-use */ + for (i = bm->totedge - 1; i != -1; i--) { + e_iter = earray[i]; + + if (BM_edge_is_wire(e_iter) && (BM_elem_flag_test(e_iter, BM_ELEM_TAG) == FALSE)) { + /* edge has become wire */ + int vidx_reverse; + BMVert *v1 = e_iter->v1; + BMVert *v2 = e_iter->v2; + BM_edge_kill(bm, e_iter); + if (v1->e == NULL) { + vidx_reverse = vert_reverse_lookup[BM_elem_index_get(v1)]; + if (vidx_reverse != -1) vinput_arr[vidx_reverse] = NULL; + BM_vert_kill(bm, v1); + } + if (v2->e == NULL) { + vidx_reverse = vert_reverse_lookup[BM_elem_index_get(v2)]; + if (vidx_reverse != -1) vinput_arr[vidx_reverse] = NULL; + BM_vert_kill(bm, v2); + } + } + } + MEM_freeN(vert_reverse_lookup); + + MEM_freeN(earray); + + + /* --- second verts --- */ + if (do_dissolve_boundaries) { + /* simple version of the branch below, sincve we will dissolve _all_ verts that use 2 edges */ + for (i = 0; i < vinput_len; i++) { + BMVert *v = vinput_arr[i]; + if (LIKELY(v != NULL) && + BM_vert_edge_count(v) == 2) + { + BM_vert_collapse_edge(bm, v->e, v, TRUE); /* join edges */ + } + } + } + else { + for (i = 0, tot_found = 0; i < vinput_len; i++) { + BMVert *v = vinput_arr[i]; + const float angle = v ? bm_vert_edge_face_angle(v) : angle_limit; + + if (angle < angle_limit) { + weight_elems[i].ele = (BMHeader *)v; + weight_elems[i].weight = angle; + tot_found++; + } + else { + weight_elems[i].ele = NULL; + weight_elems[i].weight = angle_max; + } + } + + if (tot_found != 0) { + qsort(weight_elems, vinput_len, sizeof(DissolveElemWeight), dissolve_elem_cmp); + + for (i = 0; i < tot_found; i++) { + BMVert *v = (BMVert *)weight_elems[i].ele; + if (LIKELY(v != NULL) && + /* topology changes may cause this to be un-collapsable */ + (BM_vert_edge_count(v) == 2) && + /* check twice because cumulative effect could dissolve over angle limit */ + bm_vert_edge_face_angle(v) < angle_limit) + { + BMEdge *ne = BM_vert_collapse_edge(bm, v->e, v, TRUE); /* join edges */ + + if (ne && ne->l) { + BM_edge_normals_update(ne); + } + } + } + } + } + + MEM_freeN(weight_elems); +} + +void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries) +{ + int vinput_len; + int einput_len; + + BMVert **vinput_arr = BM_iter_as_arrayN(bm, BM_VERTS_OF_MESH, NULL, &vinput_len); + BMEdge **einput_arr = BM_iter_as_arrayN(bm, BM_EDGES_OF_MESH, NULL, &einput_len); + + BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries, + vinput_arr, vinput_len, + einput_arr, einput_len); + + MEM_freeN(vinput_arr); + MEM_freeN(einput_arr); +} diff --git a/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c new file mode 100644 index 00000000000..68c0652d2c4 --- /dev/null +++ b/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c @@ -0,0 +1,344 @@ +/* + * ***** 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. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/bmesh/intern/bmesh_decimate_unsubdivide.c + * \ingroup bmesh + * + * BMesh decimator that uses a grid un-subdivide method. + */ + + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" + +#include "bmesh.h" + +#include "intern/bmesh_operators_private.h" /* own include */ + + +static int bm_vert_dissolve_fan_test(BMVert *v) +{ + /* check if we should walk over these verts */ + BMIter iter; + BMEdge *e; + + unsigned int tot_edge = 0; + unsigned int tot_edge_boundary = 0; + unsigned int tot_edge_manifold = 0; + unsigned int tot_edge_wire = 0; + + BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { + if (BM_edge_is_boundary(e)) { + tot_edge_boundary++; + } + else if (BM_edge_is_manifold(e)) { + tot_edge_manifold++; + } + else if (BM_edge_is_wire(e)) { + tot_edge_wire++; + } + tot_edge++; + } + + if ((tot_edge == 4) && (tot_edge_boundary == 0) && (tot_edge_manifold == 4)) { + return TRUE; + } + else if ((tot_edge == 3) && (tot_edge_boundary == 0) && (tot_edge_manifold == 3)) { + return TRUE; + } + else if ((tot_edge == 3) && (tot_edge_boundary == 2) && (tot_edge_manifold == 1)) { + return TRUE; + } + else if ((tot_edge == 2) && (tot_edge_wire == 2)) { + return TRUE; + } + return FALSE; +} + +static int bm_vert_dissolve_fan(BMesh *bm, BMVert *v) +{ + /* collapse under 2 conditions. + * - vert connects to 4 manifold edges (and 4 faces). + * - vert connecrs to 1 manifold edge, 2 boundary edges (and 2 faces). + * + * This covers boundary verts of a quad grid and center verts. + * note that surrounding faces dont have to be quads. + */ + + BMIter iter; + BMEdge *e; + + unsigned int tot_loop = 0; + unsigned int tot_edge = 0; + unsigned int tot_edge_boundary = 0; + unsigned int tot_edge_manifold = 0; + unsigned int tot_edge_wire = 0; + + BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { + if (BM_edge_is_boundary(e)) { + tot_edge_boundary++; + } + else if (BM_edge_is_manifold(e)) { + tot_edge_manifold++; + } + else if (BM_edge_is_wire(e)) { + tot_edge_wire++; + } + tot_edge++; + } + + if (tot_edge == 2) { + /* check for 2 wire verts only */ + if (tot_edge_wire == 2) { + return (BM_vert_collapse_edge(bm, v->e, v, TRUE) != NULL); + } + } + else if (tot_edge == 4) { + /* check for 4 faces surrounding */ + if (tot_edge_boundary == 0 && tot_edge_manifold == 4) { + /* good to go! */ + tot_loop = 4; + } + } + else if (tot_edge == 3) { + /* check for 2 faces surrounding at a boundary */ + if (tot_edge_boundary == 2 && tot_edge_manifold == 1) { + /* good to go! */ + tot_loop = 2; + } + else if (tot_edge_boundary == 0 && tot_edge_manifold == 3) { + /* good to go! */ + tot_loop = 3; + } + } + + if (tot_loop) { + BMLoop *f_loop[4]; + unsigned int i; + + /* ensure there are exactly tot_loop loops */ + BLI_assert(BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v, tot_loop) == NULL); + BM_iter_as_array(bm, BM_LOOPS_OF_VERT, v, (void **)f_loop, tot_loop); + + for (i = 0; i < tot_loop; i++) { + BMLoop *l = f_loop[i]; + if (l->f->len > 3) { + BMLoop *l_new; + BLI_assert(l->prev->v != l->next->v); + BM_face_split(bm, l->f, l->prev->v, l->next->v, &l_new, NULL, TRUE); + BM_elem_flag_merge_into(l_new->e, l->e, l->prev->e); + } + } + + return BM_vert_dissolve(bm, v); + } + + return FALSE; +} + +enum { + VERT_INDEX_DO_COLLAPSE = -1, + VERT_INDEX_INIT = 0, + VERT_INDEX_IGNORE = 1 +}; + +// #define USE_WALKER /* gives uneven results, disable for now */ + +/* - BMVert.flag & BM_ELEM_TAG: shows we touched this vert + * - BMVert.index == -1: shows we will remove this vert + */ + +/** + * \param tag_only so we can call this from an operator */ +void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int tag_only) +{ +#ifdef USE_WALKER +# define ELE_VERT_TAG 1 +#else + BMVert **vert_seek_a = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__); + BMVert **vert_seek_b = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__); + unsigned vert_seek_a_tot = 0; + unsigned vert_seek_b_tot = 0; +#endif + + BMVert *v; + BMIter iter; + + const unsigned int offset = 0; + const unsigned int nth = 2; + + int iter_step; + + /* if tag_only is set, we assyme the caller knows what verts to tag + * needed for the operator */ + if (tag_only == FALSE) { + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_elem_flag_enable(v, BM_ELEM_TAG); + } + } + + for (iter_step = 0; iter_step < iterations; iter_step++) { + int iter_done; + + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG) && bm_vert_dissolve_fan_test(v)) { +#ifdef USE_WALKER + BMO_elem_flag_enable(bm, v, ELE_VERT_TAG); +#endif + BM_elem_index_set(v, VERT_INDEX_INIT); /* set_dirty! */ + } + else { + BM_elem_index_set(v, VERT_INDEX_IGNORE); /* set_dirty! */ + } + } + /* done with selecting tagged verts */ + + + /* main loop, keep tagging until we can't tag any more islands */ + while (TRUE) { +#ifdef USE_WALKER + BMWalker walker; +#else + unsigned int depth = 1; + unsigned int i; +#endif + BMVert *v_first = NULL; + BMVert *v; + + /* we could avoid iterating from the start each time */ + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (v->e && (BM_elem_index_get(v) == VERT_INDEX_INIT)) { +#ifdef USE_WALKER + if (BMO_elem_flag_test(bm, v, ELE_VERT_TAG)) +#endif + { + /* check again incase the topology changed */ + if (bm_vert_dissolve_fan_test(v)) { + v_first = v; + } + break; + } + } + } + if (v_first == NULL) { + break; + } + +#ifdef USE_WALKER + /* Walk over selected elements starting at active */ + BMW_init(&walker, bm, BMW_CONNECTED_VERTEX, + ELE_VERT_TAG, BMW_MASK_NOP, BMW_MASK_NOP, + BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */ + BMW_NIL_LAY); + + BLI_assert(walker.order == BMW_BREADTH_FIRST); + for (v = BMW_begin(&walker, v_first); v != NULL; v = BMW_step(&walker)) { + /* Deselect elements that aren't at "nth" depth from active */ + if (BM_elem_index_get(v) == VERT_INDEX_INIT) { + if ((offset + BMW_current_depth(&walker)) % nth) { + /* tag for removal */ + BM_elem_index_set(v, VERT_INDEX_DO_COLLAPSE); /* set_dirty! */ + } + else { + /* works better to allow these verts to be checked again */ + //BM_elem_index_set(v, VERT_INDEX_IGNORE); /* set_dirty! */ + } + } + } + BMW_end(&walker); +#else + + BM_elem_index_set(v_first, (offset + depth) % nth ? VERT_INDEX_IGNORE : VERT_INDEX_DO_COLLAPSE); /* set_dirty! */ + + vert_seek_b_tot = 0; + vert_seek_b[vert_seek_b_tot++] = v_first; + + while (TRUE) { + BMEdge *e; + + if ((offset + depth) % nth) { + vert_seek_a_tot = 0; + for (i = 0; i < vert_seek_b_tot; i++) { + v = vert_seek_b[i]; + BLI_assert(BM_elem_index_get(v) == VERT_INDEX_IGNORE); + BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { + BMVert *v_other = BM_edge_other_vert(e, v); + if (BM_elem_index_get(v_other) == VERT_INDEX_INIT) { + BM_elem_index_set(v_other, VERT_INDEX_DO_COLLAPSE); /* set_dirty! */ + vert_seek_a[vert_seek_a_tot++] = v_other; + } + } + } + if (vert_seek_a_tot == 0) { + break; + } + } + else { + vert_seek_b_tot = 0; + for (i = 0; i < vert_seek_a_tot; i++) { + v = vert_seek_a[i]; + BLI_assert(BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE); + BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { + BMVert *v_other = BM_edge_other_vert(e, v); + if (BM_elem_index_get(v_other) == VERT_INDEX_INIT) { + BM_elem_index_set(v_other, VERT_INDEX_IGNORE); /* set_dirty! */ + vert_seek_b[vert_seek_b_tot++] = v_other; + } + } + } + if (vert_seek_b_tot == 0) { + break; + } + } + + depth++; + } +#endif /* USE_WALKER */ + + } + + /* now we tagged all verts -1 for removal, lets loop over and rebuild faces */ + iter_done = FALSE; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE) { + iter_done |= bm_vert_dissolve_fan(bm, v); + } + } + + if (iter_done == FALSE) { + break; + } + } + + bm->elem_index_dirty |= BM_VERT; + +#ifndef USE_WALKER + MEM_freeN(vert_seek_a); + MEM_freeN(vert_seek_b); +#endif +} + +void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations) +{ + BM_mesh_decimate_unsubdivide_ex(bm, iterations, FALSE); +} diff --git a/source/blender/bmesh/intern/bmesh_inline.h b/source/blender/bmesh/intern/bmesh_inline.h index 400f4a55b0e..04b214f725a 100644 --- a/source/blender/bmesh/intern/bmesh_inline.h +++ b/source/blender/bmesh/intern/bmesh_inline.h @@ -37,6 +37,7 @@ #define BM_elem_flag_set( ele, hflag, val) _bm_elem_flag_set (&(ele)->head, hflag, val) #define BM_elem_flag_toggle( ele, hflag) _bm_elem_flag_toggle (&(ele)->head, hflag) #define BM_elem_flag_merge( ele_a, ele_b) _bm_elem_flag_merge (&(ele_a)->head, &(ele_b)->head) +#define BM_elem_flag_merge_into(ele, ele_a, ele_b)_bm_elem_flag_merge_into (&(ele)->head, &(ele_a)->head, &(ele_b)->head) BLI_INLINE char _bm_elem_flag_test(const BMHeader *head, const char hflag) { @@ -74,6 +75,11 @@ BLI_INLINE void _bm_elem_flag_merge(BMHeader *head_a, BMHeader *head_b) head_a->hflag = head_b->hflag = head_a->hflag | head_b->hflag; } +BLI_INLINE void _bm_elem_flag_merge_into(BMHeader *head, const BMHeader *head_a, const BMHeader *head_b) +{ + head->hflag = head_a->hflag | head_b->hflag; +} + /** * notes on #BM_elem_index_set(...) usage, * Set index is sometimes abused as temp storage, other times we cant be diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index 9033436d1b2..508b3b8fcdf 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -224,10 +224,8 @@ static int compute_mdisp_quad(BMLoop *l, float v1[3], float v2[3], float v3[3], /* computer center */ BM_face_calc_center_mean(l->f, cent); - add_v3_v3v3(p, l->prev->v->co, l->v->co); - mul_v3_fl(p, 0.5); - add_v3_v3v3(n, l->next->v->co, l->v->co); - mul_v3_fl(n, 0.5); + mid_v3_v3v3(p, l->prev->v->co, l->v->co); + mid_v3_v3v3(n, l->next->v->co, l->v->co); copy_v3_v3(v1, cent); copy_v3_v3(v2, p); @@ -257,7 +255,7 @@ static float quad_coord(float aa[3], float bb[3], float cc[3], float dd[3], int f1 = fabsf(f1); f2 = fabsf(f2); - f1 = minf(f1, f2); + f1 = min_ff(f1, f2); CLAMP(f1, 0.0f, 1.0f + FLT_EPSILON); } else { @@ -345,9 +343,9 @@ static int mdisp_in_mdispquad(BMLoop *l, BMLoop *tl, float p[3], float *x, float float v1[3], v2[3], c[3], v3[3], v4[3], e1[3], e2[3]; float eps = FLT_EPSILON * 4000; - if (len_v3(l->v->no) == 0.0f) + if (is_zero_v3(l->v->no)) BM_vert_normal_update_all(l->v); - if (len_v3(tl->v->no) == 0.0f) + if (is_zero_v3(tl->v->no)) BM_vert_normal_update_all(tl->v); compute_mdisp_quad(tl, v1, v2, v3, v4, e1, e2); @@ -424,7 +422,7 @@ static void bm_loop_interp_mdisps(BMesh *bm, BMLoop *target, BMFace *source) float axis_x[3], axis_y[3]; /* ignore 2-edged faces */ - if (target->f->len < 3) + if (UNLIKELY(target->f->len < 3)) return; if (!CustomData_has_layer(&bm->ldata, CD_MDISPS)) @@ -490,7 +488,7 @@ static void bm_loop_interp_mdisps(BMesh *bm, BMLoop *target, BMFace *source) } /** - * smoothes boundaries between multires grids, + * smooths boundaries between multires grids, * including some borders in adjacent faces */ void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f) @@ -525,8 +523,7 @@ void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f) sides = (int)sqrt(mdp->totdisp); for (y = 0; y < sides; y++) { - add_v3_v3v3(co1, mdn->disps[y * sides], mdl->disps[y]); - mul_v3_fl(co1, 0.5); + mid_v3_v3v3(co1, mdn->disps[y * sides], mdl->disps[y]); copy_v3_v3(mdn->disps[y * sides], co1); copy_v3_v3(mdl->disps[y], co1); diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c index 726127fdcad..1cb95d94e9b 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.c +++ b/source/blender/bmesh/intern/bmesh_iterators.c @@ -120,6 +120,21 @@ void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len) { BMIter iter; + /* we can't rely on coun't being set */ + switch (itype) { + case BM_VERTS_OF_MESH: + iter.count = bm->totvert; + break; + case BM_EDGES_OF_MESH: + iter.count = bm->totedge; + break; + case BM_FACES_OF_MESH: + iter.count = bm->totface; + break; + default: + break; + } + if (BM_iter_init(&iter, bm, itype, data) && iter.count > 0) { BMElem *ele; BMElem **array = MEM_mallocN(sizeof(ele) * iter.count, __func__); @@ -190,10 +205,10 @@ int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const */ static void init_iterator(BMIter *iter) { - iter->firstvert = iter->nextvert = NULL; - iter->firstedge = iter->nextedge = NULL; - iter->firstloop = iter->nextloop = NULL; - iter->firstpoly = iter->nextpoly = NULL; +// iter->v_first = iter->v_next = NULL; // UNUSED + iter->e_first = iter->e_next = NULL; + iter->l_first = iter->l_next = NULL; +// iter->f_first = iter->f_next = NULL; // UNUSED iter->ldata = NULL; } @@ -229,6 +244,7 @@ void *bmiter__vert_of_mesh_step(BMIter *iter) void bmiter__edge_of_mesh_begin(BMIter *iter) { BLI_mempool_iternew(iter->bm->epool, &iter->pooliter); + iter->count = iter->bm->totedge; /* */ } void *bmiter__edge_of_mesh_step(BMIter *iter) @@ -256,19 +272,19 @@ void bmiter__edge_of_vert_begin(BMIter *iter) { init_iterator(iter); if (iter->vdata->e) { - iter->firstedge = iter->vdata->e; - iter->nextedge = iter->vdata->e; + iter->e_first = iter->vdata->e; + iter->e_next = iter->vdata->e; } } void *bmiter__edge_of_vert_step(BMIter *iter) { - BMEdge *current = iter->nextedge; + BMEdge *current = iter->e_next; - if (iter->nextedge) - iter->nextedge = bmesh_disk_edge_next(iter->nextedge, iter->vdata); + if (iter->e_next) + iter->e_next = bmesh_disk_edge_next(iter->e_next, iter->vdata); - if (iter->nextedge == iter->firstedge) iter->nextedge = NULL; + if (iter->e_next == iter->e_first) iter->e_next = NULL; return current; } @@ -284,27 +300,27 @@ void bmiter__face_of_vert_begin(BMIter *iter) if (iter->vdata->e) iter->count = bmesh_disk_facevert_count(iter->vdata); if (iter->count) { - iter->firstedge = bmesh_disk_faceedge_find_first(iter->vdata->e, iter->vdata); - iter->nextedge = iter->firstedge; - iter->firstloop = bmesh_radial_faceloop_find_first(iter->firstedge->l, iter->vdata); - iter->nextloop = iter->firstloop; + iter->e_first = bmesh_disk_faceedge_find_first(iter->vdata->e, iter->vdata); + iter->e_next = iter->e_first; + iter->l_first = bmesh_radial_faceloop_find_first(iter->e_first->l, iter->vdata); + iter->l_next = iter->l_first; } } void *bmiter__face_of_vert_step(BMIter *iter) { - BMLoop *current = iter->nextloop; + BMLoop *current = iter->l_next; - if (iter->count && iter->nextloop) { + if (iter->count && iter->l_next) { iter->count--; - iter->nextloop = bmesh_radial_faceloop_find_next(iter->nextloop, iter->vdata); - if (iter->nextloop == iter->firstloop) { - iter->nextedge = bmesh_disk_faceedge_find_next(iter->nextedge, iter->vdata); - iter->firstloop = bmesh_radial_faceloop_find_first(iter->nextedge->l, iter->vdata); - iter->nextloop = iter->firstloop; + iter->l_next = bmesh_radial_faceloop_find_next(iter->l_next, iter->vdata); + if (iter->l_next == iter->l_first) { + iter->e_next = bmesh_disk_faceedge_find_next(iter->e_next, iter->vdata); + iter->l_first = bmesh_radial_faceloop_find_first(iter->e_next->l, iter->vdata); + iter->l_next = iter->l_first; } } - if (!iter->count) iter->nextloop = NULL; + if (!iter->count) iter->l_next = NULL; return current ? current->f : NULL; } @@ -322,27 +338,27 @@ void bmiter__loop_of_vert_begin(BMIter *iter) if (iter->vdata->e) iter->count = bmesh_disk_facevert_count(iter->vdata); if (iter->count) { - iter->firstedge = bmesh_disk_faceedge_find_first(iter->vdata->e, iter->vdata); - iter->nextedge = iter->firstedge; - iter->firstloop = bmesh_radial_faceloop_find_first(iter->firstedge->l, iter->vdata); - iter->nextloop = iter->firstloop; + iter->e_first = bmesh_disk_faceedge_find_first(iter->vdata->e, iter->vdata); + iter->e_next = iter->e_first; + iter->l_first = bmesh_radial_faceloop_find_first(iter->e_first->l, iter->vdata); + iter->l_next = iter->l_first; } } void *bmiter__loop_of_vert_step(BMIter *iter) { - BMLoop *current = iter->nextloop; + BMLoop *current = iter->l_next; if (iter->count) { iter->count--; - iter->nextloop = bmesh_radial_faceloop_find_next(iter->nextloop, iter->vdata); - if (iter->nextloop == iter->firstloop) { - iter->nextedge = bmesh_disk_faceedge_find_next(iter->nextedge, iter->vdata); - iter->firstloop = bmesh_radial_faceloop_find_first(iter->nextedge->l, iter->vdata); - iter->nextloop = iter->firstloop; + iter->l_next = bmesh_radial_faceloop_find_next(iter->l_next, iter->vdata); + if (iter->l_next == iter->l_first) { + iter->e_next = bmesh_disk_faceedge_find_next(iter->e_next, iter->vdata); + iter->l_first = bmesh_radial_faceloop_find_first(iter->e_next->l, iter->vdata); + iter->l_next = iter->l_first; } } - if (!iter->count) iter->nextloop = NULL; + if (!iter->count) iter->l_next = NULL; if (current) { @@ -362,19 +378,19 @@ void bmiter__loops_of_edge_begin(BMIter *iter) /* note sure why this sets ldata ... */ init_iterator(iter); - iter->firstloop = iter->nextloop = l; + iter->l_first = iter->l_next = l; } void *bmiter__loops_of_edge_step(BMIter *iter) { - BMLoop *current = iter->nextloop; + BMLoop *current = iter->l_next; - if (iter->nextloop) { - iter->nextloop = iter->nextloop->radial_next; + if (iter->l_next) { + iter->l_next = iter->l_next->radial_next; } - if (iter->nextloop == iter->firstloop) { - iter->nextloop = NULL; + if (iter->l_next == iter->l_first) { + iter->l_next = NULL; } if (current) { @@ -393,23 +409,23 @@ void bmiter__loops_of_loop_begin(BMIter *iter) /* note sure why this sets ldata ... */ init_iterator(iter); - iter->firstloop = l; - iter->nextloop = iter->firstloop->radial_next; + iter->l_first = l; + iter->l_next = iter->l_first->radial_next; - if (iter->nextloop == iter->firstloop) - iter->nextloop = NULL; + if (iter->l_next == iter->l_first) + iter->l_next = NULL; } void *bmiter__loops_of_loop_step(BMIter *iter) { - BMLoop *current = iter->nextloop; + BMLoop *current = iter->l_next; - if (iter->nextloop) { - iter->nextloop = iter->nextloop->radial_next; + if (iter->l_next) { + iter->l_next = iter->l_next->radial_next; } - if (iter->nextloop == iter->firstloop) { - iter->nextloop = NULL; + if (iter->l_next == iter->l_first) { + iter->l_next = NULL; } if (current) { @@ -428,20 +444,20 @@ void bmiter__face_of_edge_begin(BMIter *iter) init_iterator(iter); if (iter->edata->l) { - iter->firstloop = iter->edata->l; - iter->nextloop = iter->edata->l; + iter->l_first = iter->edata->l; + iter->l_next = iter->edata->l; } } void *bmiter__face_of_edge_step(BMIter *iter) { - BMLoop *current = iter->nextloop; + BMLoop *current = iter->l_next; - if (iter->nextloop) { - iter->nextloop = iter->nextloop->radial_next; + if (iter->l_next) { + iter->l_next = iter->l_next->radial_next; } - if (iter->nextloop == iter->firstloop) iter->nextloop = NULL; + if (iter->l_next == iter->l_first) iter->l_next = NULL; return current ? current->f : NULL; } @@ -476,15 +492,15 @@ void *bmiter__vert_of_edge_step(BMIter *iter) void bmiter__vert_of_face_begin(BMIter *iter) { init_iterator(iter); - iter->firstloop = iter->nextloop = BM_FACE_FIRST_LOOP(iter->pdata); + iter->l_first = iter->l_next = BM_FACE_FIRST_LOOP(iter->pdata); } void *bmiter__vert_of_face_step(BMIter *iter) { - BMLoop *current = iter->nextloop; + BMLoop *current = iter->l_next; - if (iter->nextloop) iter->nextloop = iter->nextloop->next; - if (iter->nextloop == iter->firstloop) iter->nextloop = NULL; + if (iter->l_next) iter->l_next = iter->l_next->next; + if (iter->l_next == iter->l_first) iter->l_next = NULL; return current ? current->v : NULL; } @@ -496,15 +512,15 @@ void *bmiter__vert_of_face_step(BMIter *iter) void bmiter__edge_of_face_begin(BMIter *iter) { init_iterator(iter); - iter->firstloop = iter->nextloop = BM_FACE_FIRST_LOOP(iter->pdata); + iter->l_first = iter->l_next = BM_FACE_FIRST_LOOP(iter->pdata); } void *bmiter__edge_of_face_step(BMIter *iter) { - BMLoop *current = iter->nextloop; + BMLoop *current = iter->l_next; - if (iter->nextloop) iter->nextloop = iter->nextloop->next; - if (iter->nextloop == iter->firstloop) iter->nextloop = NULL; + if (iter->l_next) iter->l_next = iter->l_next->next; + if (iter->l_next == iter->l_first) iter->l_next = NULL; return current ? current->e : NULL; } @@ -516,15 +532,15 @@ void *bmiter__edge_of_face_step(BMIter *iter) void bmiter__loop_of_face_begin(BMIter *iter) { init_iterator(iter); - iter->firstloop = iter->nextloop = BM_FACE_FIRST_LOOP(iter->pdata); + iter->l_first = iter->l_next = BM_FACE_FIRST_LOOP(iter->pdata); } void *bmiter__loop_of_face_step(BMIter *iter) { - BMLoop *current = iter->nextloop; + BMLoop *current = iter->l_next; - if (iter->nextloop) iter->nextloop = iter->nextloop->next; - if (iter->nextloop == iter->firstloop) iter->nextloop = NULL; + if (iter->l_next) iter->l_next = iter->l_next->next; + if (iter->l_next == iter->l_first) iter->l_next = NULL; return current; } diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h index 8d0eeca31ed..3c42b3d610c 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.h +++ b/source/blender/bmesh/intern/bmesh_iterators.h @@ -95,23 +95,27 @@ extern const char bm_iter_itype_htype_map[BM_ITYPE_MAX]; for (ele = BM_iter_new(iter, NULL, itype, data), indexvar = 0; ele; ele = BM_iter_step(iter), (indexvar)++) /* Iterator Structure */ +/* note: some of these vars are not used, + * so they have beem commented to save stack space since this struct is used all over */ typedef struct BMIter { BLI_mempool_iter pooliter; - BMVert *firstvert, *nextvert, *vdata; - BMEdge *firstedge, *nextedge, *edata; - BMLoop *firstloop, *nextloop, *ldata, *l; - BMFace *firstpoly, *nextpoly, *pdata; + BMVert /* *v_first, *v_next, */ *vdata; + BMEdge *e_first, *e_next, *edata; + BMLoop *l_first, *l_next, *ldata; + BMFace /* *f_first, *f_next, */ *pdata; BMesh *bm; void (*begin)(struct BMIter *iter); void *(*step)(struct BMIter *iter); + /* union { void *p; int i; long l; float f; } filter; - int count; + */ + int count; /* note, only some iterators set this, don't rely on it */ char itype; } BMIter; diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index c0439311104..9af65d7dd7e 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -584,8 +584,7 @@ void BM_editselection_center(BMEditSelection *ese, float r_center[3]) } else if (ese->htype == BM_EDGE) { BMEdge *eed = (BMEdge *)ese->ele; - add_v3_v3v3(r_center, eed->v1->co, eed->v2->co); - mul_v3_fl(r_center, 0.5); + mid_v3_v3v3(r_center, eed->v1->co, eed->v2->co); } else if (ese->htype == BM_FACE) { BMFace *efa = (BMFace *)ese->ele; @@ -672,7 +671,7 @@ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3]) * we cant make a crossvec from a vec thats the same as the vec * unlikely but possible, so make sure if the normal is (0, 0, 1) * that vec isn't the same or in the same direction even. */ - if (efa->len < 3) { + if (UNLIKELY(efa->len < 3)) { /* crappy fallback method */ if (efa->no[0] < 0.5f) vec[0] = 1.0f; else if (efa->no[1] < 0.5f) vec[1] = 1.0f; diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index cf593627e8d..d3e3bcd3556 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -57,7 +57,7 @@ static void bm_mempool_init(BMesh *bm, const BMAllocTemplate *allocsize) bm_mesh_chunksize_default.totface, BLI_MEMPOOL_ALLOW_ITER); #ifdef USE_BMESH_HOLES - bm->looplistpool = BLI_mempool_create(sizeof(BMLoopList), allocsize[3], allocsize[3], FALSE, FALSE); + bm->looplistpool = BLI_mempool_create(sizeof(BMLoopList), 512, 512, 0); #endif /* allocate one flag pool that we don't get rid of. */ @@ -85,6 +85,11 @@ BMesh *BM_mesh_create(BMAllocTemplate *allocsize) bm->stackdepth = 1; bm->totflags = 1; + CustomData_reset(&bm->vdata); + CustomData_reset(&bm->edata); + CustomData_reset(&bm->ldata); + CustomData_reset(&bm->pdata); + return bm; } @@ -282,7 +287,7 @@ void BM_mesh_normals_update(BMesh *bm, const short skip_hidden) if (skip_hidden && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) continue; - if (normalize_v3(v->no) == 0.0f) { + if (UNLIKELY(normalize_v3(v->no) == 0.0f)) { normalize_v3_v3(v->no, v->co); } } @@ -295,7 +300,7 @@ static void UNUSED_FUNCTION(bm_mdisps_space_set)(Object *ob, BMesh *bm, int from /* switch multires data out of tangent space */ if (CustomData_has_layer(&bm->ldata, CD_MDISPS)) { BMEditMesh *em = BMEdit_Create(bm, FALSE); - DerivedMesh *dm = CDDM_from_BMEditMesh(em, NULL, TRUE, FALSE); + DerivedMesh *dm = CDDM_from_editbmesh(em, TRUE, FALSE); MDisps *mdisps; BMFace *f; BMIter iter; @@ -356,7 +361,7 @@ void bmesh_edit_begin(BMesh *UNUSED(bm), int UNUSED(type_flag)) * (loop cuts, edge subdivides, etc) are not reflected in the higher levels of * the mesh at all, which doesn't seem right. Turning off completely for now, * until this is shown to be better for certain types of mesh edits. */ -#if BMOP_UNTAN_MULTIRES_ENABLED +#ifdef BMOP_UNTAN_MULTIRES_ENABLED /* switch multires data out of tangent space */ if ((type_flag & BMO_OP_FLAG_UNTAN_MULTIRES) && CustomData_has_layer(&bm->ldata, CD_MDISPS)) { bmesh_mdisps_space_set(bm, MULTIRES_SPACE_TANGENT, MULTIRES_SPACE_ABSOLUTE); @@ -374,7 +379,7 @@ void bmesh_edit_begin(BMesh *UNUSED(bm), int UNUSED(type_flag)) void bmesh_edit_end(BMesh *bm, int UNUSED(flag)) { /* BMO_OP_FLAG_UNTAN_MULTIRES disabled for now, see comment above in bmesh_edit_begin. */ -#if BMOP_UNTAN_MULTIRES_ENABLED +#ifdef BMOP_UNTAN_MULTIRES_ENABLED /* switch multires data into tangent space */ if ((flag & BMO_OP_FLAG_UNTAN_MULTIRES) && CustomData_has_layer(&bm->ldata, CD_MDISPS)) { /* set normals to their previous winding */ @@ -665,7 +670,7 @@ void BM_mesh_remap(BMesh *bm, int *vert_idx, int *edge_idx, int *face_idx) /* Verts' pointers, only edge pointers... */ if (eptr_map) { BM_ITER_MESH (ve, &iter, bm, BM_VERTS_OF_MESH) { -/* printf("Vert e: %p -> %p\n", ve->e, BLI_ghash_lookup(eptr_map, (const void*)ve->e));*/ +/* printf("Vert e: %p -> %p\n", ve->e, BLI_ghash_lookup(eptr_map, (const void *)ve->e));*/ ve->e = BLI_ghash_lookup(eptr_map, (const void *)ve->e); } } @@ -675,20 +680,20 @@ void BM_mesh_remap(BMesh *bm, int *vert_idx, int *edge_idx, int *face_idx) if (vptr_map || eptr_map) { BM_ITER_MESH (ed, &iter, bm, BM_EDGES_OF_MESH) { if (vptr_map) { -/* printf("Edge v1: %p -> %p\n", ed->v1, BLI_ghash_lookup(vptr_map, (const void*)ed->v1));*/ -/* printf("Edge v2: %p -> %p\n", ed->v2, BLI_ghash_lookup(vptr_map, (const void*)ed->v2));*/ +/* printf("Edge v1: %p -> %p\n", ed->v1, BLI_ghash_lookup(vptr_map, (const void *)ed->v1));*/ +/* printf("Edge v2: %p -> %p\n", ed->v2, BLI_ghash_lookup(vptr_map, (const void* )ed->v2));*/ ed->v1 = BLI_ghash_lookup(vptr_map, (const void *)ed->v1); ed->v2 = BLI_ghash_lookup(vptr_map, (const void *)ed->v2); } if (eptr_map) { /* printf("Edge v1_disk_link prev: %p -> %p\n", ed->v1_disk_link.prev,*/ -/* BLI_ghash_lookup(eptr_map, (const void*)ed->v1_disk_link.prev));*/ +/* BLI_ghash_lookup(eptr_map, (const void *)ed->v1_disk_link.prev));*/ /* printf("Edge v1_disk_link next: %p -> %p\n", ed->v1_disk_link.next,*/ -/* BLI_ghash_lookup(eptr_map, (const void*)ed->v1_disk_link.next));*/ +/* BLI_ghash_lookup(eptr_map, (const void *)ed->v1_disk_link.next));*/ /* printf("Edge v2_disk_link prev: %p -> %p\n", ed->v2_disk_link.prev,*/ -/* BLI_ghash_lookup(eptr_map, (const void*)ed->v2_disk_link.prev));*/ +/* BLI_ghash_lookup(eptr_map, (const void *)ed->v2_disk_link.prev));*/ /* printf("Edge v2_disk_link next: %p -> %p\n", ed->v2_disk_link.next,*/ -/* BLI_ghash_lookup(eptr_map, (const void*)ed->v2_disk_link.next));*/ +/* BLI_ghash_lookup(eptr_map, (const void *)ed->v2_disk_link.next));*/ ed->v1_disk_link.prev = BLI_ghash_lookup(eptr_map, (const void *)ed->v1_disk_link.prev); ed->v1_disk_link.next = BLI_ghash_lookup(eptr_map, (const void *)ed->v1_disk_link.next); ed->v2_disk_link.prev = BLI_ghash_lookup(eptr_map, (const void *)ed->v2_disk_link.prev); @@ -701,15 +706,15 @@ void BM_mesh_remap(BMesh *bm, int *vert_idx, int *edge_idx, int *face_idx) BM_ITER_MESH (fa, &iter, bm, BM_FACES_OF_MESH) { BM_ITER_ELEM (lo, &iterl, fa, BM_LOOPS_OF_FACE) { if (vptr_map) { -/* printf("Loop v: %p -> %p\n", lo->v, BLI_ghash_lookup(vptr_map, (const void*)lo->v));*/ +/* printf("Loop v: %p -> %p\n", lo->v, BLI_ghash_lookup(vptr_map, (const void *)lo->v));*/ lo->v = BLI_ghash_lookup(vptr_map, (const void *)lo->v); } if (eptr_map) { -/* printf("Loop e: %p -> %p\n", lo->e, BLI_ghash_lookup(eptr_map, (const void*)lo->e));*/ +/* printf("Loop e: %p -> %p\n", lo->e, BLI_ghash_lookup(eptr_map, (const void *)lo->e));*/ lo->e = BLI_ghash_lookup(eptr_map, (const void *)lo->e); } if (fptr_map) { -/* printf("Loop f: %p -> %p\n", lo->f, BLI_ghash_lookup(fptr_map, (const void*)lo->f));*/ +/* printf("Loop f: %p -> %p\n", lo->f, BLI_ghash_lookup(fptr_map, (const void *)lo->f));*/ lo->f = BLI_ghash_lookup(fptr_map, (const void *)lo->f); } } diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 51c8b5d3bd8..62abf43829b 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -314,7 +314,7 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) f = BM_face_create(bm, verts, fedges, mpoly->totloop, FALSE); - if (!f) { + if (UNLIKELY(f == NULL)) { printf("%s: Warning! Bad face in mesh" " \"%s\" at index %d!, skipping\n", __func__, me->id.name + 2, i); @@ -536,7 +536,9 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, int dotess) oldverts = me->mvert; /* don't free this yet */ - CustomData_set_layer(&me->vdata, CD_MVERT, NULL); + if (oldverts) { + CustomData_set_layer(&me->vdata, CD_MVERT, NULL); + } /* free custom data */ CustomData_free(&me->vdata, me->totvert); @@ -758,7 +760,7 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, int dotess) } if (!currkey) { - currkey = add_keyblock(me->key, bm->vdata.layers[i].name); + currkey = BKE_keyblock_add(me->key, bm->vdata.layers[i].name); currkey->uid = bm->vdata.layers[i].uid; } diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 73e2d83520c..62374d8b7bb 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -130,6 +130,7 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v) /* this code for handling 2 and 3-valence verts * may be totally bad */ if (keepedge == NULL && len == 3) { +#if 0 /* handle specific case for three-valence. solve it by * increasing valence to four. this may be hackish. . */ BMLoop *loop = e->l; @@ -140,6 +141,13 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v) if (!BM_disk_dissolve(bm, v)) { return FALSE; } +#else + BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, TRUE); + + if (!BM_vert_collapse_faces(bm, v->e, v, 1.0, FALSE, TRUE)) { + return FALSE; + } +#endif return TRUE; } else if (keepedge == NULL && len == 2) { @@ -188,8 +196,9 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v) } while (e != v->e); } - /* collapse the verte */ - e = BM_vert_collapse_faces(bm, baseedge, v, 1.0, TRUE, TRUE); + /* collapse the vertex */ + /* note, the baseedge can be a boundary of manifold, use this as join_faces arg */ + e = BM_vert_collapse_faces(bm, baseedge, v, 1.0, !BM_edge_is_boundary(baseedge), TRUE); if (!e) { return FALSE; @@ -428,7 +437,7 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, float cos[ /* bmesh_semv returns in newe the edge going from newv to tv */ copy_v3_v3(newv->co, cos[i]); - /* interpolate the loop data for the loops with v==newv, using orig face */ + /* interpolate the loop data for the loops with (v == newv), using orig face */ for (j = 0; j < 2; j++) { BMEdge *e_iter = (j == 0) ? e : newe; BMLoop *l_iter = e_iter->l; @@ -461,9 +470,6 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, float cos[ * both collapse a vertex and return a new edge. * Except this takes a factor and merges custom data. * - * BMESH_TODO: - * Insert error checking for KV valance. - * * \param bm The bmesh * \param ke The edge to collapse * \param kv The vertex to collapse into the edge @@ -558,7 +564,7 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, /* cant kill data we loop on, build a list and remove those */ BLI_array_empty(bad_faces); BM_ITER_ELEM (f, &fiter, verts[i], BM_FACES_OF_VERT) { - if (f->len < 3) { + if (UNLIKELY(f->len < 3)) { BLI_array_append(bad_faces, f); } } diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 362157ad71b..31698f0abc1 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -113,6 +113,26 @@ static BMOpDefine bmo_smooth_vert_def = { 0 }; +/* + * Vertext Smooth Laplacian + * Smooths vertices by using Laplacian smoothing propose by. + * Desbrun, et al. Implicit Fairing of Irregular Meshes using Diffusion and Curvature Flow +*/ +static BMOpDefine bmo_smooth_laplacian_vert_def = { + "smooth_laplacian_vert", + {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, //input vertices + {BMO_OP_SLOT_FLT, "lambda"}, //lambda param + {BMO_OP_SLOT_FLT, "lambda_border"}, //lambda param in border + {BMO_OP_SLOT_BOOL, "use_x"}, //Smooth object along X axis + {BMO_OP_SLOT_BOOL, "use_y"}, //Smooth object along Y axis + {BMO_OP_SLOT_BOOL, "use_z"}, //Smooth object along Z axis + {BMO_OP_SLOT_BOOL, "volume_preservation"}, //Apply volume preservation after smooth + {0} /* null-terminating sentinel */, + }, + bmo_smooth_laplacian_vert_exec, + 0 +}; + /* * Right-Hand Faces * @@ -679,6 +699,7 @@ static BMOpDefine bmo_dissolve_faces_def = { static BMOpDefine bmo_dissolve_limit_def = { "dissolve_limit", {{BMO_OP_SLOT_FLT, "angle_limit"}, /* total rotation angle (degrees) */ + {BMO_OP_SLOT_BOOL, "use_dissolve_boundaries"}, {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, {BMO_OP_SLOT_ELEMENT_BUF, "edges"}, {0} /* null-terminating sentinel */}, @@ -698,6 +719,15 @@ static BMOpDefine bmo_triangulate_def = { BMO_OP_FLAG_UNTAN_MULTIRES }; +static BMOpDefine bmo_unsubdivide_def = { + "unsubdivide", + {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ + {BMO_OP_SLOT_INT, "iterations"}, + {0} /* null-terminating sentinel */}, + bmo_unsubdivide_exec, + BMO_OP_FLAG_UNTAN_MULTIRES +}; + static BMOpDefine bmo_subdivide_edges_def = { "subdivide_edges", {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, @@ -792,10 +822,11 @@ static BMOpDefine bmo_spin_def = { */ static BMOpDefine bmo_similar_faces_def = { "similar_faces", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ + {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ + {BMO_OP_SLOT_INT, "type"}, /* type of selection */ + {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ + {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ {0} /* null-terminating sentinel */}, bmo_similar_faces_exec, 0 @@ -808,10 +839,11 @@ static BMOpDefine bmo_similar_faces_def = { */ static BMOpDefine bmo_similar_edges_def = { "similar_edges", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* output edges */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ + {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* output edges */ + {BMO_OP_SLOT_INT, "type"}, /* type of selection */ + {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ + {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ {0} /* null-terminating sentinel */}, bmo_similar_edges_exec, 0 @@ -824,10 +856,11 @@ static BMOpDefine bmo_similar_edges_def = { */ static BMOpDefine bmo_similar_verts_def = { "similar_verts", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ + {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */ + {BMO_OP_SLOT_INT, "type"}, /* type of selection */ + {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ + {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ {0} /* null-terminating sentinel */}, bmo_similar_verts_exec, 0 @@ -1152,6 +1185,7 @@ static BMOpDefine bmo_slide_vert_def = { BMO_OP_FLAG_UNTAN_MULTIRES }; +#ifdef WITH_BULLET /* * Convex Hull * @@ -1181,6 +1215,30 @@ static BMOpDefine bmo_convex_hull_def = { bmo_convex_hull_exec, 0 }; +#endif + +/* + * Symmetrize + * + * Mekes the mesh elements in the "input" slot symmetrical. Unlike + * normal mirroring, it only copies in one direction, as specified by + * the "direction" slot. The edges and faces that cross the plane of + * symmetry are split as needed to enforce symmetry. + * + * All new vertices, edges, and faces are added to the "geomout" slot. + */ +static BMOpDefine bmo_symmetrize_def = { + "symmetrize", + {{BMO_OP_SLOT_ELEMENT_BUF, "input"}, + {BMO_OP_SLOT_INT, "direction"}, + + /* Outputs */ + {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, + + {0} /* null-terminating sentinel */}, + bmo_symmetrize_exec, + 0 +}; BMOpDefine *opdefines[] = { &bmo_automerge_def, @@ -1194,7 +1252,9 @@ BMOpDefine *opdefines[] = { &bmo_collapse_uvs_def, &bmo_connect_verts_def, &bmo_contextual_create_def, +#ifdef WITH_BULLET &bmo_convex_hull_def, +#endif &bmo_create_circle_def, &bmo_create_cone_def, &bmo_create_cube_def, @@ -1241,15 +1301,18 @@ BMOpDefine *opdefines[] = { &bmo_similar_verts_def, &bmo_slide_vert_def, &bmo_smooth_vert_def, + &bmo_smooth_laplacian_vert_def, &bmo_solidify_def, &bmo_spin_def, &bmo_split_def, &bmo_split_edges_def, &bmo_subdivide_edges_def, + &bmo_symmetrize_def, &bmo_transform_def, &bmo_translate_def, &bmo_triangle_fill_def, &bmo_triangulate_def, + &bmo_unsubdivide_def, &bmo_weld_verts_def, &bmo_wireframe_def, diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index 0674103162c..a2f4cdc8c6a 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -266,6 +266,16 @@ enum { DEL_ONLYTAGGED }; +typedef enum { + BMO_SYMMETRIZE_NEGATIVE_X, + BMO_SYMMETRIZE_NEGATIVE_Y, + BMO_SYMMETRIZE_NEGATIVE_Z, + + BMO_SYMMETRIZE_POSITIVE_X, + BMO_SYMMETRIZE_POSITIVE_Y, + BMO_SYMMETRIZE_POSITIVE_Z, +} BMO_SymmDirection; + void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag); void BMO_op_flag_disable(BMesh *bm, BMOperator *op, const int op_flag); diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 53b95c97c8b..2413f3a7be0 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -36,6 +36,8 @@ #include "BLI_listbase.h" #include "BLI_array.h" +#include "BLF_translation.h" + #include "bmesh.h" #include "intern/bmesh_private.h" @@ -49,16 +51,16 @@ static int bmo_opname_to_opcode(const char *opname); static const char *bmo_error_messages[] = { NULL, - "Self intersection error", - "Could not dissolve vert", - "Could not connect vertices", - "Could not traverse mesh", - "Could not dissolve faces", - "Could not dissolve vertices", - "Tessellation error", - "Can not deal with non-manifold geometry", - "Invalid selection", - "Internal mesh error", + N_("Self intersection error"), + N_("Could not dissolve vert"), + N_("Could not connect vertices"), + N_("Could not traverse mesh"), + N_("Could not dissolve faces"), + N_("Could not dissolve vertices"), + N_("Tessellation error"), + N_("Cannot deal with non-manifold geometry"), + N_("Invalid selection"), + N_("Internal mesh error"), }; @@ -1024,7 +1026,7 @@ static void bmo_flag_layer_alloc(BMesh *bm) int i; BMIter iter; - BLI_mempool *oldpool = bm->toolflagpool; /* old flag pool */ + BLI_mempool *oldpool = bm->toolflagpool; /* old flag pool */ BLI_mempool *newpool; void *oldflags; @@ -1241,7 +1243,9 @@ void BMO_error_raise(BMesh *bm, BMOperator *owner, int errcode, const char *msg) BMOpError *err = MEM_callocN(sizeof(BMOpError), "bmop_error"); err->errorcode = errcode; - if (!msg) msg = bmo_error_messages[errcode]; + if (!msg) { + msg = bmo_error_messages[errcode]; + } err->msg = msg; err->op = owner; @@ -1253,7 +1257,7 @@ int BMO_error_occurred(BMesh *bm) return bm->errorstack.first != NULL; } -/* returns error code or 0 if no erro */ +/* returns error code or 0 if no error */ int BMO_error_get(BMesh *bm, const char **msg, BMOperator **op) { BMOpError *err = bm->errorstack.first; diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h index b1da8ecb275..14da93302b9 100644 --- a/source/blender/bmesh/intern/bmesh_operators.h +++ b/source/blender/bmesh/intern/bmesh_operators.h @@ -46,11 +46,18 @@ enum { SUBDIV_SELECT_LOOPCUT }; +enum { + SIM_CMP_EQ = 0, + SIM_CMP_GT, + SIM_CMP_LT +}; + /* similar face selection slot values */ enum { SIMFACE_MATERIAL = 201, SIMFACE_IMAGE, SIMFACE_AREA, + SIMFACE_SIDES, SIMFACE_PERIMETER, SIMFACE_NORMAL, SIMFACE_COPLANAR diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h index dc1bdaa4689..65c9cf0c421 100644 --- a/source/blender/bmesh/intern/bmesh_operators_private.h +++ b/source/blender/bmesh/intern/bmesh_operators_private.h @@ -91,15 +91,18 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op); void bmo_similar_verts_exec(BMesh *bm, BMOperator *op); void bmo_slide_vert_exec(BMesh *bm, BMOperator *op); void bmo_smooth_vert_exec(BMesh *bm, BMOperator *op); +void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op); void bmo_solidify_face_region_exec(BMesh *bm, BMOperator *op); void bmo_spin_exec(BMesh *bm, BMOperator *op); void bmo_split_edges_exec(BMesh *bm, BMOperator *op); void bmo_split_exec(BMesh *bm, BMOperator *op); void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op); +void bmo_symmetrize_exec(BMesh *bm, BMOperator *op); void bmo_transform_exec(BMesh *bm, BMOperator *op); void bmo_translate_exec(BMesh *bm, BMOperator *op); void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op); void bmo_triangulate_exec(BMesh *bm, BMOperator *op); +void bmo_unsubdivide_exec(BMesh *bm, BMOperator *op); void bmo_weld_verts_exec(BMesh *bm, BMOperator *op); void bmo_wireframe_exec(BMesh *bm, BMOperator *op); diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index eb2b7721bdc..98edceb30a2 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -313,7 +313,7 @@ void poly_rotate_plane(const float normal[3], float (*verts)[3], const int nvert float up[3] = {0.0f, 0.0f, 1.0f}, axis[3], q[4]; float mat[3][3]; - double angle; + float angle; int i; cross_v3_v3v3(axis, normal, up); @@ -329,7 +329,7 @@ void poly_rotate_plane(const float normal[3], float (*verts)[3], const int nvert axis[2] = 0.0f; } - axis_angle_to_quat(q, axis, (float)angle); + axis_angle_to_quat(q, axis, angle); quat_to_mat3(mat, q); for (i = 0; i < nverts; i++) @@ -507,8 +507,8 @@ static int line_crosses_v2f(const float v1[2], const float v2[2], const float v3 #define GETMIN2_AXIS(a, b, ma, mb, axis) \ { \ - ma[axis] = minf(a[axis], b[axis]); \ - mb[axis] = maxf(a[axis], b[axis]); \ + ma[axis] = min_ff(a[axis], b[axis]); \ + mb[axis] = max_ff(a[axis], b[axis]); \ } (void)0 #define GETMIN2(a, b, ma, mb) \ @@ -994,8 +994,8 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) for (i = 0, l = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l = l->next) { p1 = projverts[i]; - out[0] = maxf(out[0], p1[0]); - out[1] = maxf(out[1], p1[1]); + out[0] = max_ff(out[0], p1[0]); + out[1] = max_ff(out[1], p1[1]); /* out[2] = 0.0f; */ /* keep at zero */ p1[2] = 0.0f; diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index d850eb34477..4b07dd74eef 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -297,6 +297,14 @@ int BM_edge_in_face(BMFace *f, BMEdge *e) return FALSE; } +/** + * Returns whether or not a given edge is is part of a given loop. + */ +int BM_edge_in_loop(BMEdge *e, BMLoop *l) +{ + return (l->e == e || l->prev->e == e); +} + /** * Returns whether or not two vertices are in * a given edge @@ -315,6 +323,96 @@ BMVert *BM_edge_other_vert(BMEdge *e, BMVert *v) return bmesh_edge_other_vert_get(e, v); } +/** + * Given a edge and a loop (assumes the edge is manifold). returns + * the other faces loop, sharing the same vertex. + * + *

      + * +-------------------+
      + * |                   |
      + * |                   |
      + * |l_other <-- return |
      + * +-------------------+ <-- A manifold edge between 2 faces
      + * |l    e  <-- edge   |
      + * |^ <-------- loop   |
      + * |                   |
      + * +-------------------+
      + * 
      + */ +BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l) +{ + BMLoop *l_other; + + // BLI_assert(BM_edge_is_manifold(e)); // TOO strict, just check if we have another radial face + BLI_assert(e->l && e->l->radial_next != e->l); + BLI_assert(BM_vert_in_edge(e, l->v)); + + l_other = (l->e == e) ? l : l->prev; + l_other = l_other->radial_next; + BLI_assert(l_other->e == e); + + if (l_other->v == l->v) { + /* pass */ + } + else if (l_other->next->v == l->v) { + l_other = l_other->next; + } + else { + BLI_assert(0); + } + + return l_other; +} + +/** + * Utility function to step around a fan of loops, + * using an edge to mark the previous side. + * + * \note all edges must be manifold, + * once a non manifold edge is hit, return NULL. + * + *
      + *                ,.,-->|
      + *            _,-'      |
      + *          ,'          | (notice how 'e_step'
      + *         /            |  and 'l' define the
      + *        /             |  direction the arrow
      + *       |     return   |  points).
      + *       |     loop --> |
      + * ---------------------+---------------------
      + *         ^      l --> |
      + *         |            |
      + *  assign e_step       |
      + *                      |
      + *   begin e_step ----> |
      + *                      |
      + * 
      + */ + +BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step) +{ + BMEdge *e_prev = *e_step; + BMEdge *e_next; + if (l->e == e_prev) { + e_next = l->prev->e; + } + else if (l->prev->e == e_prev) { + e_next = l->e; + } + else { + BLI_assert(0); + } + + if (BM_edge_is_manifold(e_next)) { + return BM_edge_other_loop((*e_step = e_next), l); + } + else { + return NULL; + } +} + + + /** * The function takes a vertex at the center of a fan and returns the opposite edge in the fan. * All edges in the fan must be manifold, otherwise return NULL. @@ -1017,6 +1115,28 @@ BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2) return NULL; } +/** + * Returns an edge sharing the same vertices as this one. + * This isn't an invalid state but tools should clean up these cases before + * returning the mesh to the user. + */ +BMEdge *BM_edge_find_double(BMEdge *e) +{ + BMVert *v = e->v1; + BMVert *v_other = e->v2; + + BMEdge *e_iter; + + e_iter = e; + while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e) { + if (UNLIKELY(BM_vert_in_edge(e_iter, v_other))) { + return e_iter; + } + } + + return NULL; +} + /** * Given a set of vertices \a varr, find out if * all those vertices overlap an existing face. diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 36ffc296759..34d0747676c 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -31,6 +31,7 @@ int BM_vert_in_face(BMFace *f, BMVert *v); int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len); int BM_edge_in_face(BMFace *f, BMEdge *e); +int BM_edge_in_loop(BMEdge *e, BMLoop *l); int BM_vert_in_edge(BMEdge *e, BMVert *v); int BM_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e); @@ -39,9 +40,11 @@ float BM_edge_calc_length(BMEdge *e); int BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb); int BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb); BMVert *BM_edge_other_vert(BMEdge *e, BMVert *v); +BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l); BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v); BMLoop *BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v); BMLoop *BM_loop_other_vert_loop(BMLoop *l, BMVert *v); +BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step); BMLoop *BM_vert_find_first_loop(BMVert *v); int BM_vert_edge_count_nonwire(BMVert *v); @@ -72,6 +75,7 @@ BMLoop *BM_face_find_shortest_loop(BMFace *f); BMLoop *BM_face_find_longest_loop(BMFace *f); BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2); +BMEdge *BM_edge_find_double(BMEdge *e); int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_existface); diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c index a72bfe47127..bb013e6428e 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_impl.c +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -303,8 +303,7 @@ static void *bmw_IslandboundWalker_step(BMWalker *walker) if (!BM_vert_is_manifold(v)) { BMW_reset(walker); BMO_error_raise(walker->bm, NULL, BMERR_WALKER_FAILED, - "Non-manifold vert " - "while searching region boundary"); + "Non-manifold vert while searching region boundary"); return NULL; } @@ -499,7 +498,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker) BMEdge *e = lwalk->cur, *nexte = NULL; BMLoop *l; BMVert *v; - int i; + int i = 0; owalk = *lwalk; BMW_state_remove(walker); @@ -534,7 +533,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker) } else if (l) { /* NORMAL EDGE WITH FACES */ int vert_edge_tot; - int stopi; + int stopi = 0; v = BM_edge_other_vert(e, lwalk->lastv); @@ -599,7 +598,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker) } } } - else { /* WIRE EDGE */ + else { /* WIRE EDGE */ BMIter eiter; /* match trunk: mark all connected wire edges */ diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index 8210ea973e6..c5120571755 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -126,7 +126,7 @@ static void calc_corner_co(BMLoop *l, const float fac, float r_co[3], * gives nicer, move even output. * * Use the minimum rather then the middle value so skinny faces don't flip along the short axis */ - float min_fac = minf(normalize_v3(l_vec_prev), normalize_v3(l_vec_next)); + float min_fac = min_ff(normalize_v3(l_vec_prev), normalize_v3(l_vec_next)); float angle; if (do_even) { @@ -233,7 +233,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) } #if 0 - //a bit of cleaner code that, alas, doens't work. + /* a bit of cleaner code that, alas, doens't work. */ /* build edge tag */ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BMO_elem_flag_test(bm, e->v1, BEVEL_FLAG) || BMO_elem_flag_test(bm, e->v2, BEVEL_FLAG)) { @@ -475,7 +475,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) BLI_array_append(edges, e); f = BM_face_create_ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), FALSE); - if (!f) { + if (UNLIKELY(f == NULL)) { printf("%s: could not make face!\n", __func__); continue; } @@ -592,7 +592,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) *d3 = (d1 + d2) * 0.5f; } - if (!f) { + if (UNLIKELY(f == NULL)) { fprintf(stderr, "%s: face index out of range! (bmesh internal error)\n", __func__); continue; } @@ -771,7 +771,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) continue; f = BM_face_create_ngon(bm, lastv, vstart, edges, BLI_array_count(edges), FALSE); - if (!f) { + if (UNLIKELY(f == NULL)) { fprintf(stderr, "%s: in bevel vert fill! (bmesh internal error)\n", __func__); } else { diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c index 1987294fc42..ebd848ff8b2 100644 --- a/source/blender/bmesh/operators/bmo_connect.c +++ b/source/blender/bmesh/operators/bmo_connect.c @@ -380,8 +380,9 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) /* compute summed length between vertices in forward direction */ len = 0.0f; - for (j = 0; j < lenv2; j++) - len += len_v3v3(vv1[clamp_index(i+j, lenv1)]->co, vv2[j]->co); + for (j = 0; j < lenv2; j++) { + len += len_v3v3(vv1[clamp_index(i + j, lenv1)]->co, vv2[j]->co); + } if (len < min) { min = len; @@ -390,8 +391,9 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) /* compute summed length between vertices in backward direction */ len = 0.0f; - for (j = 0; j < lenv2; j++) - len += len_v3v3(vv1[clamp_index(i-j, lenv1)]->co, vv2[j]->co); + for (j = 0; j < lenv2; j++) { + len += len_v3v3(vv1[clamp_index(i - j, lenv1)]->co, vv2[j]->co); + } if (len < min) { min = len; @@ -423,8 +425,8 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) /* merge loops of bridge faces */ if (use_merge) { - const int vert_len = mini(BLI_array_count(vv1), BLI_array_count(vv2)) - ((cl1 || cl2) ? 1 : 0); - const int edge_len = mini(BLI_array_count(ee1), BLI_array_count(ee2)); + const int vert_len = min_ii(BLI_array_count(vv1), BLI_array_count(vv2)) - ((cl1 || cl2) ? 1 : 0); + const int edge_len = min_ii(BLI_array_count(ee1), BLI_array_count(ee2)); if (merge_factor <= 0.0f) { /* 2 --> 1 */ @@ -504,7 +506,7 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) vv2[i2next], vv1[i1next], f_example, TRUE); - if (!f || f->len != 4) { + if (UNLIKELY((f == NULL) || (f->len != 4))) { fprintf(stderr, "%s: in bridge! (bmesh internal error)\n", __func__); } else { diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c index 4723b631c5f..bd1c0f809bd 100644 --- a/source/blender/bmesh/operators/bmo_create.c +++ b/source/blender/bmesh/operators/bmo_create.c @@ -84,7 +84,7 @@ static int count_edge_faces(BMesh *bm, BMEdge *e); BLI_INLINE BMDiskLink *rs_edge_link_get(BMEdge *e, BMVert *v, EdgeData *e_data) { return v == ((BMEdge *)e)->v1 ? &(((EdgeData *)e_data)->v1_disk_link) : - &(((EdgeData *)e_data)->v2_disk_link) ; + &(((EdgeData *)e_data)->v2_disk_link); } static int rotsys_append_edge(BMEdge *e, BMVert *v, @@ -275,8 +275,9 @@ static int UNUSED_FUNCTION(rotsys_fill_faces)(BMesh *bm, EdgeData *edata, VertDa continue; f = BM_face_create_ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), TRUE); - if (!f) + if (UNLIKELY(f == NULL)) { continue; + } } } @@ -364,8 +365,6 @@ static void init_rotsys(BMesh *bm, EdgeData *edata, VertData *vdata) /* BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE); */ /* UNUSE */ int i; -#define SIGN(n) ((n) < 0.0f) - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { BMIter eiter; float no[3], cent[3]; @@ -1225,7 +1224,7 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) v4 = BM_vert_in_edge(edges2[i - 1], edges2[i]->v1) ? edges2[i]->v2 : edges2[i]->v1; } - /* if there is ever bowtie quads between two edges the problem is here! [#30367] */ + /* if there is ever bow-tie quads between two edges the problem is here! [#30367] */ #if 0 normal_tri_v3(dvec1, v1->co, v2->co, v4->co); normal_tri_v3(dvec2, v1->co, v4->co, v3->co); diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index 84f6cb27b3b..9addb1b1657 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -477,182 +477,15 @@ void dummy_exec(BMesh *bm, BMOperator *op) #endif /* Limited Dissolve */ - -#define UNIT_TO_ANGLE DEG2RADF(90.0f) -#define ANGLE_TO_UNIT (1.0f / UNIT_TO_ANGLE) - -/* multiply vertex edge angle by face angle - * this means we are not left with sharp corners between _almost_ planer faces - * convert angles [0-PI/2] -> [0-1], multiply together, then convert back to radians. */ -static float bm_vert_edge_face_angle(BMVert *v) -{ - const float angle = BM_vert_calc_edge_angle(v); - /* note: could be either edge, it doesn't matter */ - if (v->e && BM_edge_is_manifold(v->e)) { - return ((angle * ANGLE_TO_UNIT) * (BM_edge_calc_face_angle(v->e) * ANGLE_TO_UNIT)) * UNIT_TO_ANGLE; - } - else { - return angle; - } -} - -#undef UNIT_TO_ANGLE -#undef ANGLE_TO_UNIT - -typedef struct DissolveElemWeight { - BMHeader *ele; - float weight; -} DissolveElemWeight; - -static int dissolve_elem_cmp(const void *a1, const void *a2) -{ - const struct DissolveElemWeight *d1 = a1, *d2 = a2; - - if (d1->weight > d2->weight) return 1; - else if (d1->weight < d2->weight) return -1; - return 0; -} - void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op) { BMOpSlot *einput = BMO_slot_get(op, "edges"); BMOpSlot *vinput = BMO_slot_get(op, "verts"); const float angle_max = (float)M_PI / 2.0f; - const float angle_limit = minf(angle_max, BMO_slot_float_get(op, "angle_limit")); - DissolveElemWeight *weight_elems = MEM_mallocN(MAX2(einput->len, vinput->len) * - sizeof(DissolveElemWeight), __func__); - int i, tot_found; + const float angle_limit = min_ff(angle_max, BMO_slot_float_get(op, "angle_limit")); + const int do_dissolve_boundaries = BMO_slot_bool_get(op, "use_dissolve_boundaries"); - BMIter iter; - BMEdge *e_iter; - BMEdge **earray; - - int *vert_reverse_lookup; - - BMEdge **einput_arr = (BMEdge **)einput->data.p; - BMVert **vinput_arr = (BMVert **)vinput->data.p; - - /* --- first edges --- */ - - /* wire -> tag */ - BM_ITER_MESH (e_iter, &iter, bm, BM_EDGES_OF_MESH) { - BM_elem_flag_set(e_iter, BM_ELEM_TAG, BM_edge_is_wire(e_iter)); - } - - /* go through and split edge */ - for (i = 0, tot_found = 0; i < einput->len; i++) { - BMEdge *e = einput_arr[i]; - const float angle = BM_edge_calc_face_angle(e); - - if (angle < angle_limit) { - tot_found++; - } - weight_elems[i].ele = (BMHeader *)e; - weight_elems[i].weight = angle; - } - - if (tot_found != 0) { - qsort(weight_elems, einput->len, sizeof(DissolveElemWeight), dissolve_elem_cmp); - - for (i = 0; i < tot_found; i++) { - BMEdge *e = (BMEdge *)weight_elems[i].ele; - - if (/* may have become non-manifold */ - BM_edge_is_manifold(e) && - /* check twice because cumulative effect could dissolve over angle limit */ - (BM_edge_calc_face_angle(e) < angle_limit)) - { - BMFace *nf = BM_faces_join_pair(bm, e->l->f, - e->l->radial_next->f, - e, - FALSE); /* join faces */ - - /* there may be some errors, we don't mind, just move on */ - if (nf) { - BM_face_normal_update(nf); - } - else { - BMO_error_clear(bm); - } - } - } - } - - /* prepare for cleanup */ - BM_mesh_elem_index_ensure(bm, BM_VERT); - vert_reverse_lookup = MEM_mallocN(sizeof(int) * bm->totvert, __func__); - fill_vn_i(vert_reverse_lookup, bm->totvert, -1); - for (i = 0, tot_found = 0; i < vinput->len; i++) { - BMVert *v = vinput_arr[i]; - vert_reverse_lookup[BM_elem_index_get(v)] = i; - } - - /* --- cleanup --- */ - earray = MEM_mallocN(sizeof(BMEdge *) * bm->totedge, __func__); - BM_ITER_MESH_INDEX (e_iter, &iter, bm, BM_EDGES_OF_MESH, i) { - earray[i] = e_iter; - } - /* remove all edges/verts left behind from dissolving, NULL'ing the vertex array so we dont re-use */ - for (i = bm->totedge - 1; i != -1; i--) { - e_iter = earray[i]; - - if (BM_edge_is_wire(e_iter) && (BM_elem_flag_test(e_iter, BM_ELEM_TAG) == FALSE)) { - /* edge has become wire */ - int vidx_reverse; - BMVert *v1 = e_iter->v1; - BMVert *v2 = e_iter->v2; - BM_edge_kill(bm, e_iter); - if (v1->e == NULL) { - vidx_reverse = vert_reverse_lookup[BM_elem_index_get(v1)]; - if (vidx_reverse != -1) vinput_arr[vidx_reverse] = NULL; - BM_vert_kill(bm, v1); - } - if (v2->e == NULL) { - vidx_reverse = vert_reverse_lookup[BM_elem_index_get(v2)]; - if (vidx_reverse != -1) vinput_arr[vidx_reverse] = NULL; - BM_vert_kill(bm, v2); - } - } - } - MEM_freeN(vert_reverse_lookup); - - MEM_freeN(earray); - - - /* --- second verts --- */ - for (i = 0, tot_found = 0; i < vinput->len; i++) { - BMVert *v = vinput_arr[i]; - const float angle = v ? bm_vert_edge_face_angle(v) : angle_limit; - - if (angle < angle_limit) { - weight_elems[i].ele = (BMHeader *)v; - weight_elems[i].weight = angle; - tot_found++; - } - else { - weight_elems[i].ele = NULL; - weight_elems[i].weight = angle_max; - } - } - - if (tot_found != 0) { - qsort(weight_elems, vinput->len, sizeof(DissolveElemWeight), dissolve_elem_cmp); - - for (i = 0; i < tot_found; i++) { - BMVert *v = (BMVert *)weight_elems[i].ele; - if (/* topology changes may cause this to be un-collapsable */ - (BM_vert_edge_count(v) == 2) && - /* check twice because cumulative effect could dissolve over angle limit */ - bm_vert_edge_face_angle(v) < angle_limit) - { - BMEdge *ne = BM_vert_collapse_edge(bm, v->e, v, TRUE); /* join edges */ - - if (ne && ne->l) { - BM_edge_normals_update(ne); - } - } - } - } - - MEM_freeN(weight_elems); + BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries, + vinput->data.p, vinput->len, + einput->data.p, einput->len); } diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c index 4d4d7e30a4e..32270007a0b 100644 --- a/source/blender/bmesh/operators/bmo_dupe.c +++ b/source/blender/bmesh/operators/bmo_dupe.c @@ -37,7 +37,7 @@ #define DUPE_INPUT 1 /* input from operator */ #define DUPE_NEW 2 #define DUPE_DONE 4 -#define DUPE_MAPPED 8 +// #define DUPE_MAPPED 8 // UNUSED /** * COPY VERTEX diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c index c8be7c9ce34..627351ead11 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -87,8 +87,8 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) BMO_elem_flag_enable(bm, f, EXT_DEL); f2 = BM_face_create_ngon(bm, firstv, BM_edge_other_vert(edges[0], firstv), edges, f->len, FALSE); - if (!f2) { - BMO_error_raise(bm, op, BMERR_MESH_ERROR, "Extrude failed; could not create face"); + if (UNLIKELY(f2 == NULL)) { + BMO_error_raise(bm, op, BMERR_MESH_ERROR, "Extrude failed: could not create face"); BLI_array_free(edges); return; } @@ -104,6 +104,7 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) l4 = l2->next; f3 = BM_face_create_quad_tri(bm, l3->v, l4->v, l2->v, l->v, f, FALSE); + /* XXX, no error check here, why? - Campbell */ l_tmp = BM_FACE_FIRST_LOOP(f3); @@ -131,46 +132,36 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) * This function won't crash if its not but won't work right either. * \a e_b is the new edge. * - * \note this function could be exposed as an api call if other areas need it, - * so far only extrude does. + * \note The edge this face comes from needs to be from the first and second verts fo the face. + * The caller must ensure this else we will copy from the wrong source. */ -static void bm_extrude_copy_face_loop_attributes(BMesh *bm, BMFace *f, BMEdge *e_a, BMEdge *e_b) +static void bm_extrude_copy_face_loop_attributes(BMesh *bm, BMFace *f) { - /* 'a' is the starting edge #e, 'b' is the final edge #newedge */ - BMLoop *l_dst_a = BM_face_edge_share_loop(f, e_a); - BMLoop *l_dst_b = BM_face_edge_share_loop(f, e_b); - /* we could only have a face on one-or the other edges, - * check if either side of the face has an adjacent face */ - BMLoop *l_src_1; - BMLoop *l_src_2; + /* edge we are extruded from */ + BMLoop *l_first_0 = BM_FACE_FIRST_LOOP(f); + BMLoop *l_first_1 = l_first_0->next; + BMLoop *l_first_2 = l_first_1->next; + BMLoop *l_first_3 = l_first_2->next; - /* there is no l_src_b */ + BMLoop *l_other_0; + BMLoop *l_other_1; - /* sanity */ - BLI_assert(l_dst_a->f == l_dst_b->f); - - if (l_dst_a != l_dst_a->radial_next) { - l_src_1 = l_dst_a->radial_next; - l_src_2 = l_src_1->next; - } - else if (l_dst_b != l_dst_b->radial_next) { - l_src_2 = l_dst_b->radial_next; - l_src_1 = l_src_2->next; - } - else { - /* no new faces on either edge, nothing to copy from */ + if (UNLIKELY(l_first_0 == l_first_0->radial_next)) { return; } - BM_elem_attrs_copy(bm, bm, l_src_1->f, l_dst_a->f); - BM_elem_flag_disable(f, BM_ELEM_HIDDEN); /* possibly we copy from a hidden face */ + l_other_0 = BM_edge_other_loop(l_first_0->e, l_first_0); + l_other_1 = BM_edge_other_loop(l_first_0->e, l_first_1); /* copy data */ - BM_elem_attrs_copy(bm, bm, l_src_2, l_dst_a); - BM_elem_attrs_copy(bm, bm, l_src_2, l_dst_b->next); + BM_elem_attrs_copy(bm, bm, l_other_0->f, f); + BM_elem_flag_disable(f, BM_ELEM_HIDDEN); /* possibly we copy from a hidden face */ - BM_elem_attrs_copy(bm, bm, l_src_1, l_dst_a->next); - BM_elem_attrs_copy(bm, bm, l_src_1, l_dst_b); + BM_elem_attrs_copy(bm, bm, l_other_0, l_first_0); + BM_elem_attrs_copy(bm, bm, l_other_0, l_first_3); + + BM_elem_attrs_copy(bm, bm, l_other_1, l_first_1); + BM_elem_attrs_copy(bm, bm, l_other_1, l_first_2); } /* Disable the skin root flag on the input vert, assumes that the vert @@ -187,9 +178,8 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op) { BMOIter siter; BMOperator dupeop; - BMVert *v1, *v2, *v3, *v4; - BMEdge *e, *e2; BMFace *f; + BMEdge *e, *e_new; BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { BMO_elem_flag_enable(bm, e, EXT_INPUT); @@ -202,33 +192,34 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op) /* disable root flag on all new skin nodes */ if (CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { - BMO_ITER(v1, &siter, bm, &dupeop, "newout", BM_VERT) { - bm_extrude_disable_skin_root(bm, v1); + BMVert *v; + BMO_ITER(v, &siter, bm, &dupeop, "newout", BM_VERT) { + bm_extrude_disable_skin_root(bm, v); } } for (e = BMO_iter_new(&siter, bm, &dupeop, "boundarymap", 0); e; e = BMO_iter_step(&siter)) { - e2 = BMO_iter_map_value(&siter); - e2 = *(BMEdge **)e2; + BMVert *f_verts[4]; + e_new = *(BMEdge **)BMO_iter_map_value(&siter); if (e->l && e->v1 != e->l->v) { - v1 = e->v1; - v2 = e->v2; - v3 = e2->v2; - v4 = e2->v1; + f_verts[0] = e->v1; + f_verts[1] = e->v2; + f_verts[2] = e_new->v2; + f_verts[3] = e_new->v1; } else { - v1 = e2->v1; - v2 = e2->v2; - v3 = e->v2; - v4 = e->v1; + f_verts[0] = e->v2; + f_verts[1] = e->v1; + f_verts[2] = e_new->v1; + f_verts[3] = e_new->v2; } /* not sure what to do about example face, pass NULL for now */ - f = BM_face_create_quad_tri(bm, v1, v2, v3, v4, NULL, FALSE); - bm_extrude_copy_face_loop_attributes(bm, f, e, e2); + f = BM_face_create_quad_tri_v(bm, f_verts, 4, NULL, FALSE); + bm_extrude_copy_face_loop_attributes(bm, f); if (BMO_elem_flag_test(bm, e, EXT_INPUT)) - e = e2; + e = e_new; BMO_elem_flag_enable(bm, f, EXT_KEEP); BMO_elem_flag_enable(bm, e, EXT_KEEP); @@ -269,8 +260,8 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) BMOperator dupeop, delop; BMOIter siter; BMIter iter, fiter, viter; - BMEdge *e, *newedge; - BMVert *verts[4], *v, *v2; + BMEdge *e, *e_new; + BMVert *v, *v2; BMFace *f; int found, fwd, delorig = FALSE; @@ -377,6 +368,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) BMO_slot_copy(&dupeop, op, "newout", "geomout"); for (e = BMO_iter_new(&siter, bm, &dupeop, "boundarymap", 0); e; e = BMO_iter_step(&siter)) { + BMVert *f_verts[4]; /* this should always be wire, so this is mainly a speedup to avoid map lookup */ if (BM_edge_is_wire(e) && BMO_slot_map_contains(bm, op, "exclude", e)) { @@ -395,37 +387,37 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) continue; } - newedge = *(BMEdge **)BMO_iter_map_value(&siter); + e_new = *(BMEdge **)BMO_iter_map_value(&siter); - if (!newedge) { + if (!e_new) { continue; } /* orient loop to give same normal as a loop of newedge * if it exists (will be an extruded face), * else same normal as a loop of e, if it exists */ - if (!newedge->l) + if (!e_new->l) fwd = !e->l || !(e->l->v == e->v1); else - fwd = (newedge->l->v == newedge->v1); + fwd = (e_new->l->v == e_new->v1); if (fwd) { - verts[0] = e->v1; - verts[1] = e->v2; - verts[2] = newedge->v2; - verts[3] = newedge->v1; + f_verts[0] = e->v1; + f_verts[1] = e->v2; + f_verts[2] = e_new->v2; + f_verts[3] = e_new->v1; } else { - verts[3] = e->v1; - verts[2] = e->v2; - verts[1] = newedge->v2; - verts[0] = newedge->v1; + f_verts[0] = e->v2; + f_verts[1] = e->v1; + f_verts[2] = e_new->v1; + f_verts[3] = e_new->v2; } /* not sure what to do about example face, pass NULL for now */ - f = BM_face_create_quad_tri_v(bm, verts, 4, NULL, FALSE); - bm_extrude_copy_face_loop_attributes(bm, f, e, newedge); + f = BM_face_create_quad_tri_v(bm, f_verts, 4, NULL, FALSE); + bm_extrude_copy_face_loop_attributes(bm, f); } /* link isolated vert */ diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c index d97d901777c..013b6183f84 100644 --- a/source/blender/bmesh/operators/bmo_hull.c +++ b/source/blender/bmesh/operators/bmo_hull.c @@ -24,19 +24,17 @@ * \ingroup bmesh */ +#ifdef WITH_BULLET + #include "MEM_guardedalloc.h" +#include "BLI_array.h" #include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_utildefines.h" -/*XXX: This operator doesn't work well (at all?) for flat surfaces with - * >3 sides - creating overlapping faces at times. - * An easy workaround is to add in some noise but this is - * weak and unreliable, ideally this would detect flat surfaces - * (possibly making them into ngons) - see - */ +#include "Bullet-C-Api.h" /* XXX: using 128 for totelem and pchunk of mempool, no idea what good * values would be though */ @@ -46,21 +44,15 @@ #include "intern/bmesh_operators_private.h" /* own include */ -#define HULL_EPSILON_FLT 0.0001f -/* values above 0.0001 cause errors, see below for details, don't increase - * without checking against bug [#32027] */ -#define HULL_EPSILON_DOT_FLT 0.00000001f - /* Internal operator flags */ typedef enum { HULL_FLAG_INPUT = (1 << 0), - HULL_FLAG_TETRA_VERT = (1 << 1), - HULL_FLAG_INTERIOR_ELE = (1 << 2), - HULL_FLAG_OUTPUT_GEOM = (1 << 3), + HULL_FLAG_INTERIOR_ELE = (1 << 1), + HULL_FLAG_OUTPUT_GEOM = (1 << 2), - HULL_FLAG_DEL = (1 << 4), - HULL_FLAG_HOLE = (1 << 5) + HULL_FLAG_DEL = (1 << 3), + HULL_FLAG_HOLE = (1 << 4) } HullFlags; /* Store hull triangles separate from BMesh faces until the end; this @@ -72,63 +64,6 @@ typedef struct HullTriangle { int skip; } HullTriangle; -/* These edges define the hole created in the hull by deleting faces - * that can "see" a new vertex (the boundary edges then form the edge - * of a new triangle fan that has the new vertex as its center) */ -typedef struct HullBoundaryEdge { - struct HullBoundaryEdge *next, *prev; - BMVert *v[2]; -} HullBoundaryEdge; - - - -/*************************** Boundary Edges ***************************/ - -static int edge_match(BMVert *e1_v1, BMVert *e1_v2, BMVert *e2[2]) -{ - return (e1_v1 == e2[0] && e1_v2 == e2[1]) || - (e1_v1 == e2[1] && e1_v2 == e2[0]); -} - -/* Returns true if the edge (e1, e2) is already in edges; that edge is - * deleted here as well. if not found just returns 0 */ -static int check_for_dup(ListBase *edges, BLI_mempool *pool, - BMVert *v1, BMVert *v2) -{ - HullBoundaryEdge *e, *e_next; - - for (e = edges->first; e; e = e_next) { - e_next = e->next; - - if (edge_match(v1, v2, e->v)) { - /* remove the interior edge */ - BLI_remlink(edges, e); - BLI_mempool_free(pool, e); - return 1; - } - } - - return 0; -} - -static void expand_boundary_edges(ListBase *edges, BLI_mempool *edge_pool, - const HullTriangle *t) -{ - HullBoundaryEdge *e_new; - int i; - - /* Insert each triangle edge into the boundary list; if any of - * its edges are already in there, remove the edge entirely */ - for (i = 0; i < 3; i++) { - if (!check_for_dup(edges, edge_pool, t->v[i], t->v[(i + 1) % 3])) { - e_new = BLI_mempool_calloc(edge_pool); - e_new->v[0] = t->v[i]; - e_new->v[1] = t->v[(i + 1) % 3]; - BLI_addtail(edges, e_new); - } - } -} - /*************************** Hull Triangles ***************************/ @@ -152,75 +87,6 @@ static void hull_add_triangle(BMesh *bm, GHash *hull_triangles, BLI_mempool *poo normal_tri_v3(t->no, v1->co, v2->co, v3->co); } -static int hull_point_tri_side(const HullTriangle *t, const float co[3]) -{ - /* Added epsilon to fix bug [#31941], improves output when some - * vertices are nearly coplanar. Might need further tweaking for - * other cases though. - * ... - * Update: epsilon of 0.0001 causes [#32027], use HULL_EPSILON_DOT_FLT - * and give it a much smaller value - * */ - float p[3], d; - sub_v3_v3v3(p, co, t->v[0]->co); - d = dot_v3v3(t->no, p); - if (d < -HULL_EPSILON_DOT_FLT) return -1; - else if (d > HULL_EPSILON_DOT_FLT) return 1; - else return 0; -} - -/* Get all hull triangles that vertex 'v' is outside of */ -static GHash *hull_triangles_v_outside(GHash *hull_triangles, const BMVert *v) -{ - GHash *outside; - GHashIterator iter; - - outside = BLI_ghash_ptr_new("outside"); - - GHASH_ITER (iter, hull_triangles) { - HullTriangle *t = BLI_ghashIterator_getKey(&iter); - - if (hull_point_tri_side(t, v->co) > 0) - BLI_ghash_insert(outside, t, NULL); - } - - return outside; -} - -/* For vertex 'v', find which triangles must be deleted to extend the - * hull; find the boundary edges of that hole so that it can be filled - * with connections to the new vertex, and update the hull_triangles - * to delete the marked triangles */ -static void add_point(BMesh *bm, GHash *hull_triangles, BLI_mempool *hull_pool, - BLI_mempool *edge_pool, GHash *outside, BMVert *v) -{ - ListBase edges = {NULL, NULL}; - HullBoundaryEdge *e, *e_next; - GHashIterator iter; - - GHASH_ITER (iter, outside) { - HullTriangle *t = BLI_ghashIterator_getKey(&iter); - int i; - - expand_boundary_edges(&edges, edge_pool, t); - - /* Mark triangle's vertices as interior */ - for (i = 0; i < 3; i++) - BMO_elem_flag_enable(bm, t->v[i], HULL_FLAG_INTERIOR_ELE); - - /* Delete the triangle */ - BLI_ghash_remove(hull_triangles, t, NULL, NULL); - BLI_mempool_free(hull_pool, t); - } - - /* Fill hole boundary with triangles to new point */ - for (e = edges.first; e; e = e_next) { - e_next = e->next; - hull_add_triangle(bm, hull_triangles, hull_pool, e->v[0], e->v[1], v); - BLI_mempool_free(edge_pool, e); - } -} - static BMFace *hull_find_example_face(BMesh *bm, BMEdge *e) { BMIter iter; @@ -243,6 +109,7 @@ static void hull_output_triangles(BMesh *bm, GHash *hull_triangles) GHASH_ITER (iter, hull_triangles) { HullTriangle *t = BLI_ghashIterator_getKey(&iter); + int i; if (!t->skip) { BMEdge *edges[3] = { @@ -251,25 +118,53 @@ static void hull_output_triangles(BMesh *bm, GHash *hull_triangles) BM_edge_create(bm, t->v[2], t->v[0], NULL, TRUE) }; BMFace *f, *example = NULL; - int i; - /* Look for an adjacent face that existed before the hull */ - for (i = 0; i < 3; i++) { - if (!example) - example = hull_find_example_face(bm, edges[i]); + if (BM_face_exists(bm, t->v, 3, &f)) { + /* If the operator is run with "use_existing_faces" + * disabled, but an output face in the hull is the + * same as a face in the existing mesh, it should not + * be marked as unused or interior. */ + BMO_elem_flag_enable(bm, f, HULL_FLAG_OUTPUT_GEOM); + BMO_elem_flag_disable(bm, f, HULL_FLAG_HOLE); + BMO_elem_flag_disable(bm, f, HULL_FLAG_INTERIOR_ELE); } + else { + /* Look for an adjacent face that existed before the hull */ + for (i = 0; i < 3; i++) { + if (!example) + example = hull_find_example_face(bm, edges[i]); + } - f = BM_face_create_quad_tri_v(bm, t->v, 3, example, FALSE); - BM_face_copy_shared(bm, f); - - /* Mark face/verts/edges for 'geomout' slot and select */ + /* Create new hull face */ + f = BM_face_create_quad_tri_v(bm, t->v, 3, example, TRUE); + BM_face_copy_shared(bm, f); + } + /* Mark face for 'geomout' slot and select */ BMO_elem_flag_enable(bm, f, HULL_FLAG_OUTPUT_GEOM); BM_face_select_set(bm, f, TRUE); + + /* Mark edges for 'geomout' slot */ for (i = 0; i < 3; i++) { - BMO_elem_flag_enable(bm, t->v[i], HULL_FLAG_OUTPUT_GEOM); BMO_elem_flag_enable(bm, edges[i], HULL_FLAG_OUTPUT_GEOM); } } + else { + /* Mark input edges for 'geomout' slot */ + for (i = 0; i < 3; i++) { + const int next = (i == 2 ? 0 : i + 1); + BMEdge *e = BM_edge_exists(t->v[i], t->v[next]); + if (e && + BMO_elem_flag_test(bm, e, HULL_FLAG_INPUT) && + !BMO_elem_flag_test(bm, e, HULL_FLAG_HOLE)) { + BMO_elem_flag_enable(bm, e, HULL_FLAG_OUTPUT_GEOM); + } + } + } + + /* Mark verts for 'geomout' slot */ + for (i = 0; i < 3; i++) { + BMO_elem_flag_enable(bm, t->v[i], HULL_FLAG_OUTPUT_GEOM); + } } } @@ -362,158 +257,6 @@ static void hull_final_edges_free(HullFinalEdges *final_edges) -/************************* Initial Tetrahedron ************************/ - -static void hull_add_tetrahedron(BMesh *bm, GHash *hull_triangles, BLI_mempool *pool, - BMVert *tetra[4]) -{ - float center[3]; - int i, indices[4][3] = { - {0, 1, 2}, - {0, 2, 3}, - {1, 0, 3}, - {2, 1, 3} - }; - - /* Calculate center */ - zero_v3(center); - for (i = 0; i < 4; i++) - add_v3_v3(center, tetra[i]->co); - mul_v3_fl(center, 0.25f); - - for (i = 0; i < 4; i++) { - BMVert *v1 = tetra[indices[i][0]]; - BMVert *v2 = tetra[indices[i][1]]; - BMVert *v3 = tetra[indices[i][2]]; - float no[3], d[3]; - - normal_tri_v3(no, v1->co, v2->co, v3->co); - sub_v3_v3v3(d, center, v1->co); - if (dot_v3v3(no, d) > 0) - SWAP(BMVert *, v1, v3); - - hull_add_triangle(bm, hull_triangles, pool, v1, v2, v3); - } -} - -/* For each axis, get the minimum and maximum input vertices */ -static void hull_get_min_max(BMesh *bm, BMOperator *op, - BMVert *min[3], BMVert *max[3]) -{ - BMOIter oiter; - BMVert *v; - - min[0] = min[1] = min[2] = NULL; - max[0] = max[1] = max[2] = NULL; - - BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { - int i; - - for (i = 0; i < 3; i++) { - if (!min[i] || v->co[i] < min[i]->co[i]) - min[i] = v; - if (!max[i] || v->co[i] > max[i]->co[i]) - max[i] = v; - } - } -} - -/* Returns true if input is coplanar */ -static int hull_find_large_tetrahedron(BMesh *bm, BMOperator *op, - BMVert *tetra[4]) -{ - BMVert *min[3], *max[3], *v; - BMOIter oiter; - float widest_axis_len, largest_dist, plane_normal[3]; - int i, j, widest_axis; - - tetra[0] = tetra[1] = tetra[2] = tetra[3] = NULL; - hull_get_min_max(bm, op, min, max); - - /* Check for flat axis */ - for (i = 0; i < 3; i++) { - if (min[i] == max[i]) { - return TRUE; - } - } - - /* Find widest axis */ - widest_axis_len = 0.0f; - widest_axis = 0; /* set here in the unlikey case this isn't set below */ - for (i = 0; i < 3; i++) { - float len = (max[i]->co[i] - min[i]->co[i]); - if (len >= widest_axis_len) { - widest_axis_len = len; - widest_axis = i; - } - } - - /* Use widest axis for first two points */ - tetra[0] = min[widest_axis]; - tetra[1] = max[widest_axis]; - BMO_elem_flag_enable(bm, tetra[0], HULL_FLAG_TETRA_VERT); - BMO_elem_flag_enable(bm, tetra[1], HULL_FLAG_TETRA_VERT); - - /* Choose third vertex farthest from existing line segment */ - largest_dist = 0; - for (i = 0; i < 3; i++) { - BMVert *v; - float dist; - - if (i == widest_axis) - continue; - - v = min[i]; - for (j = 0; j < 2; j++) { - dist = dist_to_line_segment_v3(v->co, tetra[0]->co, tetra[1]->co); - if (dist > largest_dist) { - largest_dist = dist; - tetra[2] = v; - } - - v = max[i]; - } - } - - if (tetra[2]) { - BMO_elem_flag_enable(bm, tetra[2], HULL_FLAG_TETRA_VERT); - } - else { - return TRUE; - } - - /* Check for colinear vertices */ - if (largest_dist < HULL_EPSILON_FLT) - return TRUE; - - /* Choose fourth point farthest from existing plane */ - largest_dist = 0; - normal_tri_v3(plane_normal, tetra[0]->co, tetra[1]->co, tetra[2]->co); - BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { - if (!BMO_elem_flag_test(bm, v, HULL_FLAG_TETRA_VERT)) { - float dist = fabsf(dist_to_plane_v3(v->co, tetra[0]->co, plane_normal)); - if (dist > largest_dist) { - largest_dist = dist; - tetra[3] = v; - } - } - } - - if (tetra[3]) { - BMO_elem_flag_enable(bm, tetra[3], HULL_FLAG_TETRA_VERT); - } - else { - return TRUE; - } - - if (largest_dist < HULL_EPSILON_FLT) - return TRUE; - - return FALSE; -} - - - /**************************** Final Output ****************************/ static void hull_remove_overlapping(BMesh *bm, GHash *hull_triangles, @@ -650,44 +393,175 @@ static void hull_tag_holes(BMesh *bm, BMOperator *op) } } - /* Mark edges too if all adjacent faces are holes */ + /* Mark edges too if all adjacent faces are holes and the edge is + * not already isolated */ BMO_ITER (e, &oiter, bm, op, "input", BM_EDGE) { int hole = TRUE; + int any_faces = FALSE; BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) { + any_faces = TRUE; if (!BMO_elem_flag_test(bm, f, HULL_FLAG_HOLE)) { hole = FALSE; break; } } - if (hole) + if (hole && any_faces) BMO_elem_flag_enable(bm, e, HULL_FLAG_HOLE); } } +static int hull_input_vert_count(BMesh *bm, BMOperator *op) +{ + BMOIter oiter; + BMVert *v; + int count = 0; + + BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { + count++; + } + + return count; +} + +static BMVert **hull_input_verts_copy(BMesh *bm, BMOperator *op, + const int num_input_verts) +{ + BMOIter oiter; + BMVert *v; + BMVert **input_verts = MEM_callocN(sizeof(*input_verts) * + num_input_verts, AT); + int i = 0; + + BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { + input_verts[i++] = v; + } + + return input_verts; +} + +static float (*hull_verts_for_bullet(BMVert **input_verts, + const int num_input_verts))[3] +{ + float (*coords)[3] = MEM_callocN(sizeof(*coords) * num_input_verts, AT); + int i; + + for (i = 0; i < num_input_verts; i++) { + copy_v3_v3(coords[i], input_verts[i]->co); + } + + return coords; +} + +static BMVert **hull_verts_from_bullet(plConvexHull hull, + BMVert **input_verts, + const int num_input_verts) +{ + const int num_verts = plConvexHullNumVertices(hull); + BMVert **hull_verts = MEM_mallocN(sizeof(*hull_verts) * + num_verts, AT); + int i; + + for (i = 0; i < num_verts; i++) { + float co[3]; + int original_index; + plConvexHullGetVertex(hull, i, co, &original_index); + + if (original_index >= 0 && original_index < num_input_verts) { + hull_verts[i] = input_verts[original_index]; + } + else + BLI_assert(!"Unexpected new vertex in hull output"); + } + + return hull_verts; +} + +static void hull_from_bullet(BMesh *bm, BMOperator *op, + GHash *hull_triangles, + BLI_mempool *pool) +{ + int *fvi = NULL; + BLI_array_declare(fvi); + + BMVert **input_verts; + float (*coords)[3]; + BMVert **hull_verts; + + plConvexHull hull; + int i, count = 0; + + const int num_input_verts = hull_input_vert_count(bm, op); + + input_verts = hull_input_verts_copy(bm, op, num_input_verts); + coords = hull_verts_for_bullet(input_verts, num_input_verts); + + hull = plConvexHullCompute(coords, num_input_verts); + hull_verts = hull_verts_from_bullet(hull, input_verts, num_input_verts); + + count = plConvexHullNumFaces(hull); + for (i = 0; i < count; i++) { + const int len = plConvexHullGetFaceSize(hull, i); + + if (len > 2) { + BMVert *fv[3]; + int j; + + /* Get face vertex indices */ + BLI_array_empty(fvi); + BLI_array_grow_items(fvi, len); + plConvexHullGetFaceVertices(hull, i, fvi); + + /* Note: here we throw away any NGons from Bullet and turn + * them into triangle fans. Would be nice to use these + * directly, but will have to wait until HullTriangle goes + * away (TODO) */ + fv[0] = hull_verts[fvi[0]]; + for (j = 2; j < len; j++) { + fv[1] = hull_verts[fvi[j - 1]]; + fv[2] = hull_verts[fvi[j]]; + + hull_add_triangle(bm, hull_triangles, pool, + fv[0], fv[1], fv[2]); + } + } + } + + BLI_array_free(fvi); + MEM_freeN(hull_verts); + MEM_freeN(coords); + MEM_freeN(input_verts); +} + +/* Check that there are at least three vertices in the input */ +static int hull_num_input_verts_is_ok(BMesh *bm, BMOperator *op) +{ + BMOIter oiter; + BMVert *v; + int partial_num_verts = 0; + + BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { + partial_num_verts++; + if (partial_num_verts >= 3) + break; + } + + return (partial_num_verts >= 3); +} + void bmo_convex_hull_exec(BMesh *bm, BMOperator *op) { HullFinalEdges *final_edges; - BLI_mempool *hull_pool, *edge_pool; - BMVert *v, *tetra[4]; + BLI_mempool *hull_pool; BMElemF *ele; BMOIter oiter; GHash *hull_triangles; - /* Verify that at least four verts in the input */ - if (BMO_slot_get(op, "input")->len < 4) { + /* Verify that at least three verts in the input */ + if (!hull_num_input_verts_is_ok(bm, op)) { BMO_error_raise(bm, op, BMERR_CONVEX_HULL_FAILED, - "Requires at least four vertices"); - return; - } - - /* Initialize the convex hull by building a tetrahedron. A - * degenerate tetrahedron can cause problems, so report error and - * fail if the result is coplanar */ - if (hull_find_large_tetrahedron(bm, op, tetra)) { - BMO_error_raise(bm, op, BMERR_CONVEX_HULL_FAILED, - "Input vertices are coplanar"); + "Requires at least three vertices"); return; } @@ -700,26 +574,11 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op) BMO_elem_flag_enable(bm, ele, HULL_FLAG_INTERIOR_ELE); } - edge_pool = BLI_mempool_create(sizeof(HullBoundaryEdge), 128, 128, 0); hull_pool = BLI_mempool_create(sizeof(HullTriangle), 128, 128, 0); hull_triangles = BLI_ghash_ptr_new("hull_triangles"); - /* Add tetrahedron triangles */ - hull_add_tetrahedron(bm, hull_triangles, hull_pool, tetra); + hull_from_bullet(bm, op, hull_triangles, hull_pool); - /* Expand hull to cover new vertices outside the existing hull */ - BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { - if (!BMO_elem_flag_test(bm, v, HULL_FLAG_TETRA_VERT)) { - GHash *outside = hull_triangles_v_outside(hull_triangles, v); - if (BLI_ghash_size(outside)) { - /* Expand hull and delete interior triangles */ - add_point(bm, hull_triangles, hull_pool, edge_pool, outside, v); - } - BLI_ghash_free(outside, NULL, NULL); - } - } - - BLI_mempool_destroy(edge_pool); final_edges = hull_final_edges(hull_triangles); hull_mark_interior_elements(bm, op, final_edges); @@ -762,3 +621,5 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op) BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, HULL_FLAG_OUTPUT_GEOM); } + +#endif /* WITH_BULLET */ diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c index d780e309118..3dbc0d0a5eb 100644 --- a/source/blender/bmesh/operators/bmo_join_triangles.c +++ b/source/blender/bmesh/operators/bmo_join_triangles.c @@ -37,11 +37,6 @@ #include "intern/bmesh_operators_private.h" /* own include */ -/* Bitflags for edges */ -#define T2QDELETE 1 -#define T2QCOMPLEX 2 -#define T2QJOIN 4 - /* assumes edges are validated before reaching this poin */ static float measure_facepair(BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, float limit) @@ -110,93 +105,73 @@ static float measure_facepair(BMVert *v1, BMVert *v2, #define T2QUV_LIMIT 0.005f #define T2QCOL_LIMIT 3 -static int compareFaceAttribs(BMesh *bm, BMEdge *e, int douvs, int dovcols) +static int bm_edge_faces_cmp(BMesh *bm, BMEdge *e, const int do_uv, const int do_tf, const int do_vcol) { - MTexPoly *tp1, *tp2; - MLoopCol *lcol1, *lcol2, *lcol3, *lcol4; - MLoopUV *luv1, *luv2, *luv3, *luv4; - BMLoop *l1, *l2, *l3, *l4; - int mergeok_uvs = !douvs, mergeok_vcols = !dovcols; + /* first get loops */ + BMLoop *l[4]; + + l[0] = e->l; + l[2] = e->l->radial_next; - l1 = e->l; - l3 = e->l->radial_next; - - /* match up loops on each side of an edge corresponding to each ver */ - if (l1->v == l3->v) { - l2 = l1->next; - l4 = l2->next; + /* match up loops on each side of an edge corresponding to each vert */ + if (l[0]->v == l[2]->v) { + l[1] = l[0]->next; + l[3] = l[1]->next; } else { - l2 = l1->next; + l[1] = l[0]->next; - l4 = l3; - l3 = l4->next; + l[3] = l[2]; + l[2] = l[3]->next; } - lcol1 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPCOL); - lcol2 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPCOL); - lcol3 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPCOL); - lcol4 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPCOL); + /* Test UV's */ + if (do_uv) { + const MLoopUV *luv[4] = { + CustomData_bmesh_get(&bm->ldata, l[0]->head.data, CD_MLOOPUV), + CustomData_bmesh_get(&bm->ldata, l[1]->head.data, CD_MLOOPUV), + CustomData_bmesh_get(&bm->ldata, l[2]->head.data, CD_MLOOPUV), + CustomData_bmesh_get(&bm->ldata, l[3]->head.data, CD_MLOOPUV), + }; - luv1 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPUV); - luv2 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPUV); - luv3 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPUV); - luv4 = CustomData_bmesh_get(&bm->ldata, l1->head.data, CD_MLOOPUV); - - tp1 = CustomData_bmesh_get(&bm->pdata, l1->f->head.data, CD_MTEXPOLY); - tp2 = CustomData_bmesh_get(&bm->pdata, l2->f->head.data, CD_MTEXPOLY); - - if (!lcol1) - mergeok_vcols = 1; - - if (!luv1) - mergeok_uvs = 1; - - /* compare faceedges for each face attribute. Additional per face attributes can be added late */ - - /* do VCOL */ - if (lcol1 && dovcols) { - char *cols[4] = {(char *)lcol1, (char *)lcol2, (char *)lcol3, (char *)lcol4}; - int i; - - for (i = 0; i < 3; i++) { - if (cols[0][i] + T2QCOL_LIMIT < cols[2][i] - T2QCOL_LIMIT) - break; - if (cols[1][i] + T2QCOL_LIMIT < cols[3][i] - T2QCOL_LIMIT) - break; + /* do UV */ + if (luv[0] && (!compare_v2v2(luv[0]->uv, luv[2]->uv, T2QUV_LIMIT) || + !compare_v2v2(luv[1]->uv, luv[3]->uv, T2QUV_LIMIT))) + { + return FALSE; } - - if (i == 3) - mergeok_vcols = 1; } - /* do UV */ - if (luv1 && douvs) { - if (tp1->tpage != tp2->tpage) { - /* do nothing */ - } - else { - int i; + if (do_tf) { + const MTexPoly *tp[2] = { + CustomData_bmesh_get(&bm->pdata, l[0]->f->head.data, CD_MTEXPOLY), + CustomData_bmesh_get(&bm->pdata, l[1]->f->head.data, CD_MTEXPOLY), + }; - for (i = 0; i < 2; i++) { - if (luv1->uv[0] + T2QUV_LIMIT > luv3->uv[0] && luv1->uv[0] - T2QUV_LIMIT < luv3->uv[0] && - luv1->uv[1] + T2QUV_LIMIT > luv3->uv[1] && luv1->uv[1] - T2QUV_LIMIT < luv3->uv[1]) - { - if (luv2->uv[0] + T2QUV_LIMIT > luv4->uv[0] && luv2->uv[0] - T2QUV_LIMIT < luv4->uv[0] && - luv2->uv[1] + T2QUV_LIMIT > luv4->uv[1] && luv2->uv[1] - T2QUV_LIMIT < luv4->uv[1]) - { - mergeok_uvs = 1; - } - } + if (tp[0] && (tp[0]->tpage != tp[1]->tpage)) { + return FALSE; + } + } + + /* Test Vertex Colors */ + if (do_vcol) { + const MLoopCol *lcol[4] = { + CustomData_bmesh_get(&bm->ldata, l[0]->head.data, CD_MLOOPCOL), + CustomData_bmesh_get(&bm->ldata, l[1]->head.data, CD_MLOOPCOL), + CustomData_bmesh_get(&bm->ldata, l[2]->head.data, CD_MLOOPCOL), + CustomData_bmesh_get(&bm->ldata, l[3]->head.data, CD_MLOOPCOL), + }; + + if (lcol[0]) { + if (!compare_rgb_uchar((unsigned char *)&lcol[0]->r, (unsigned char *)&lcol[2]->r, T2QCOL_LIMIT) || + !compare_rgb_uchar((unsigned char *)&lcol[1]->r, (unsigned char *)&lcol[3]->r, T2QCOL_LIMIT)) + { + return FALSE; } } } - if (douvs == mergeok_uvs && dovcols == mergeok_vcols) { - return TRUE; - } - - return FALSE; + return TRUE; } typedef struct JoinEdge { @@ -224,28 +199,30 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) { BMIter iter, liter; BMOIter siter; - BMFace *f1, *f2; + BMFace *f; BMLoop *l; BMEdge *e; BLI_array_declare(jedges); JoinEdge *jedges = NULL; - int dosharp = BMO_slot_bool_get(op, "cmp_sharp"); - int douvs = BMO_slot_bool_get(op, "cmp_uvs"); - int dovcols = BMO_slot_bool_get(op, "cmp_vcols"); - int domat = BMO_slot_bool_get(op, "cmp_materials"); - float limit = BMO_slot_float_get(op, "limit"); + int do_sharp = BMO_slot_bool_get(op, "cmp_sharp"); + int do_uv = BMO_slot_bool_get(op, "cmp_uvs"); + int do_tf = do_uv; /* texture face, make make its own option eventually */ + int do_vcol = BMO_slot_bool_get(op, "cmp_vcols"); + int do_mat = BMO_slot_bool_get(op, "cmp_materials"); + float limit = BMO_slot_float_get(op, "limit"); int i, totedge; /* flag all edges of all input face */ - BMO_ITER (f1, &siter, bm, op, "faces", BM_FACE) { - BMO_elem_flag_enable(bm, f1, FACE_INPUT); - BM_ITER_ELEM (l, &liter, f1, BM_LOOPS_OF_FACE) { + BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_elem_flag_enable(bm, f, FACE_INPUT); + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { BMO_elem_flag_enable(bm, l->e, EDGE_MARK); } } /* unflag edges that are invalid; e.g. aren't surrounded by triangle */ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BMFace *f1, *f2; if (!BMO_elem_flag_test(bm, e, EDGE_MARK)) continue; @@ -282,13 +259,13 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) v3 = e->l->next->v; v4 = e->l->radial_next->prev->v; - if (dosharp && !BM_elem_flag_test(e, BM_ELEM_SMOOTH)) - continue; - - if ((douvs || dovcols) && compareFaceAttribs(bm, e, douvs, dovcols)) + if (do_sharp && !BM_elem_flag_test(e, BM_ELEM_SMOOTH)) continue; - if (domat && f1->mat_nr != f2->mat_nr) + if (do_mat && f1->mat_nr != f2->mat_nr) + continue; + + if ((do_uv || do_tf || do_vcol) && (bm_edge_faces_cmp(bm, e, do_uv, do_tf, do_vcol) == FALSE)) continue; measure = measure_facepair(v1, v2, v3, v4, limit); @@ -324,6 +301,8 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) } BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BMFace *f1, *f2; + if (!BMO_elem_flag_test(bm, e, EDGE_CHOSEN)) continue; @@ -334,6 +313,8 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BMO_elem_flag_test(bm, e, EDGE_MARK)) { + BMFace *f1, *f2; + /* ok, this edge wasn't merged, check if it's * in a 2-tri-pair island, and if so merg */ diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c index 70173d942a1..d7b163cb760 100644 --- a/source/blender/bmesh/operators/bmo_primitive.c +++ b/source/blender/bmesh/operators/bmo_primitive.c @@ -309,7 +309,7 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) phid /= 2; for (a = 0; a <= tot; a++) { /* Going in this direction, then edge extruding, makes normals face outward */ - vec[0] = -dia *sinf(phi); + vec[0] = -dia * sinf(phi); vec[1] = 0.0; vec[2] = dia * cosf(phi); eve = BM_vert_create(bm, vec, NULL); @@ -354,7 +354,7 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) { float len, len2, vec2[3]; - len = 2 *dia *sinf(phid / 2.0f); + len = 2 *dia * sinf(phid / 2.0f); /* length of one segment in shortest parallen */ vec[0] = dia * sinf(phid); @@ -365,7 +365,7 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) len2 = len_v3v3(vec, vec2); /* use shortest segment length divided by 3 as merge threshold */ - BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, MIN2(len, len2) / 3.0f); + BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, min_ff(len, len2) / 3.0f); } /* and now do imat */ @@ -517,16 +517,16 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) phi = 0; if (cap_ends) { - vec[0] = vec[1] = 0.0f; - vec[2] = 0.0; + zero_v3(vec); mul_m4_v3(mat, vec); cent1 = BM_vert_create(bm, vec, NULL); + BMO_elem_flag_enable(bm, cent1, VERT_MARK); } for (a = 0; a < segs; a++, phi += phid) { /* Going this way ends up with normal(s) upward */ - vec[0] = -dia *sinf(phi); + vec[0] = -dia * sinf(phi); vec[1] = dia * cosf(phi); vec[2] = 0.0f; mul_m4_v3(mat, vec); diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index 0caa766c0f0..cd792f911a9 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -244,11 +244,11 @@ static int vergaverco(const void *e1, const void *e2) else return 0; } -#define VERT_TESTED 1 +// #define VERT_TESTED 1 // UNUSED #define VERT_DOUBLE 2 #define VERT_TARGET 4 #define VERT_KEEP 8 -#define VERT_MARK 16 +// #define VERT_MARK 16 // UNUSED #define VERT_IN 32 #define EDGE_MARK 1 @@ -371,7 +371,7 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) BMIter iter; BMEdge *e, **edges = NULL; BLI_array_declare(edges); - float min[3], max[3]; + float min[3], max[3], center[3]; int i, tot; BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges"); @@ -400,13 +400,12 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) minmax_v3v3_v3(min, max, e->v2->co); } - add_v3_v3v3(min, min, max); - mul_v3_fl(min, 0.5f); + mid_v3_v3v3(center, min, max); /* snap edges to a point. for initial testing purposes anyway */ for (i = 0; i < tot; i++) { - copy_v3_v3(edges[i]->v1->co, min); - copy_v3_v3(edges[i]->v2->co, min); + copy_v3_v3(edges[i]->v1->co, center); + copy_v3_v3(edges[i]->v2->co, center); if (edges[i]->v1 != edges[0]->v1) BMO_slot_map_ptr_insert(bm, &weldop, "targetmap", edges[i]->v1, edges[0]->v1); diff --git a/source/blender/bmesh/operators/bmo_similar.c b/source/blender/bmesh/operators/bmo_similar.c new file mode 100644 index 00000000000..df03e50d2c4 --- /dev/null +++ b/source/blender/bmesh/operators/bmo_similar.c @@ -0,0 +1,614 @@ +/* + * ***** 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. + * + * Contributor(s): Joseph Eagar, Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/bmesh/operators/bmo_similar.c + * \ingroup bmesh + * + * bmesh operators to select based on + * comparisons with the existing selection. + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_object_types.h" +#include "DNA_meshdata_types.h" + +#include "BLI_math.h" + +#include "BKE_customdata.h" +#include "BKE_deform.h" + +#include "bmesh.h" + +#include "intern/bmesh_operators_private.h" /* own include */ + +/* in fact these could all be the same */ + +/* + * extra face data (computed data) + */ +typedef struct SimSel_FaceExt { + BMFace *f; /* the face */ + float c[3]; /* center */ + union { + float area; /* area */ + float perim; /* perimeter */ + float d; /* 4th component of plane (the first three being the normal) */ + struct Image *t; /* image pointer */ + }; +} SimSel_FaceExt; + +static int bm_sel_similar_cmp_fl(const float delta, const float thresh, const int compare) +{ + switch (compare) { + case SIM_CMP_EQ: + return (fabsf(delta) <= thresh); + case SIM_CMP_GT: + return ((delta + thresh) >= 0.0f); + case SIM_CMP_LT: + return ((delta - thresh) <= 0.0f); + default: + BLI_assert(0); + return 0; + } +} + +static int bm_sel_similar_cmp_i(const int delta, const int compare) +{ + switch (compare) { + case SIM_CMP_EQ: + return (delta == 0); + case SIM_CMP_GT: + return (delta > 0); + case SIM_CMP_LT: + return (delta < 0); + default: + BLI_assert(0); + return 0; + } +} + +/* + * Select similar faces, the choices are in the enum in source/blender/bmesh/bmesh_operators.h + * We select either similar faces based on material, image, area, perimeter, normal, or the coplanar faces + */ +void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) +{ +#define FACE_MARK 1 + + BMIter fm_iter; + BMFace *fs, *fm; + BMOIter fs_iter; + int num_sels = 0, num_total = 0, i = 0, idx = 0; + float angle = 0.0f; + SimSel_FaceExt *f_ext = NULL; + int *indices = NULL; + float t_no[3]; /* temporary normal */ + const int type = BMO_slot_int_get(op, "type"); + const float thresh = BMO_slot_float_get(op, "thresh"); + const float thresh_radians = thresh * (float)M_PI; + const int compare = BMO_slot_int_get(op, "compare"); + + /* initial_elem - other_elem */ + float delta_fl; + int delta_i; + + num_total = BM_mesh_elem_count(bm, BM_FACE); + + /* + * The first thing to do is to iterate through all the the selected items and mark them since + * they will be in the selection anyway. + * This will increase performance, (especially when the number of originally selected faces is high) + * so the overall complexity will be less than $O(mn)$ where is the total number of selected faces, + * and n is the total number of faces + */ + BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { + if (!BMO_elem_flag_test(bm, fs, FACE_MARK)) { /* is this really needed ? */ + BMO_elem_flag_enable(bm, fs, FACE_MARK); + num_sels++; + } + } + + /* allocate memory for the selected faces indices and for all temporary faces */ + indices = (int *)MEM_callocN(sizeof(int) * num_sels, "face indices util.c"); + f_ext = (SimSel_FaceExt *)MEM_callocN(sizeof(SimSel_FaceExt) * num_total, "f_ext util.c"); + + /* loop through all the faces and fill the faces/indices structure */ + BM_ITER_MESH (fm, &fm_iter, bm, BM_FACES_OF_MESH) { + f_ext[i].f = fm; + if (BMO_elem_flag_test(bm, fm, FACE_MARK)) { + indices[idx] = i; + idx++; + } + i++; + } + + /* + * Save us some computation burden: In case of perimeter/area/coplanar selection we compute + * only once. + */ + if (type == SIMFACE_PERIMETER || type == SIMFACE_AREA || type == SIMFACE_COPLANAR || type == SIMFACE_IMAGE) { + for (i = 0; i < num_total; i++) { + switch (type) { + case SIMFACE_PERIMETER: + /* set the perimeter */ + f_ext[i].perim = BM_face_calc_perimeter(f_ext[i].f); + break; + + case SIMFACE_COPLANAR: + /* compute the center of the polygon */ + BM_face_calc_center_mean(f_ext[i].f, f_ext[i].c); + + /* normalize the polygon normal */ + copy_v3_v3(t_no, f_ext[i].f->no); + normalize_v3(t_no); + + /* compute the plane distance */ + f_ext[i].d = dot_v3v3(t_no, f_ext[i].c); + break; + + case SIMFACE_AREA: + f_ext[i].area = BM_face_calc_area(f_ext[i].f); + break; + + case SIMFACE_IMAGE: + f_ext[i].t = NULL; + if (CustomData_has_layer(&(bm->pdata), CD_MTEXPOLY)) { + MTexPoly *mtpoly = CustomData_bmesh_get(&bm->pdata, f_ext[i].f->head.data, CD_MTEXPOLY); + f_ext[i].t = mtpoly->tpage; + } + break; + } + } + } + + /* now select the rest (if any) */ + for (i = 0; i < num_total; i++) { + fm = f_ext[i].f; + if (!BMO_elem_flag_test(bm, fm, FACE_MARK) && !BM_elem_flag_test(fm, BM_ELEM_HIDDEN)) { + int cont = TRUE; + for (idx = 0; idx < num_sels && cont == TRUE; idx++) { + fs = f_ext[indices[idx]].f; + switch (type) { + case SIMFACE_MATERIAL: + if (fm->mat_nr == fs->mat_nr) { + BMO_elem_flag_enable(bm, fm, FACE_MARK); + cont = FALSE; + } + break; + + case SIMFACE_IMAGE: + if (f_ext[i].t == f_ext[indices[idx]].t) { + BMO_elem_flag_enable(bm, fm, FACE_MARK); + cont = FALSE; + } + break; + + case SIMFACE_NORMAL: + angle = angle_normalized_v3v3(fs->no, fm->no); /* if the angle between the normals -> 0 */ + if (angle <= thresh_radians) { + BMO_elem_flag_enable(bm, fm, FACE_MARK); + cont = FALSE; + } + break; + + case SIMFACE_COPLANAR: + angle = angle_normalized_v3v3(fs->no, fm->no); /* angle -> 0 */ + if (angle <= thresh_radians) { /* and dot product difference -> 0 */ + delta_fl = f_ext[i].d - f_ext[indices[idx]].d; + if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { + BMO_elem_flag_enable(bm, fm, FACE_MARK); + cont = FALSE; + } + } + break; + + case SIMFACE_AREA: + delta_fl = f_ext[i].area - f_ext[indices[idx]].area; + if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { + BMO_elem_flag_enable(bm, fm, FACE_MARK); + cont = FALSE; + } + break; + + case SIMFACE_SIDES: + delta_i = fm->len - fs->len; + if (bm_sel_similar_cmp_i(delta_i, compare)) { + BMO_elem_flag_enable(bm, fm, FACE_MARK); + cont = FALSE; + } + break; + + case SIMFACE_PERIMETER: + delta_fl = f_ext[i].perim - f_ext[indices[idx]].perim; + if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { + BMO_elem_flag_enable(bm, fm, FACE_MARK); + cont = FALSE; + } + break; + default: + BLI_assert(0); + } + } + } + } + + MEM_freeN(f_ext); + MEM_freeN(indices); + + /* transfer all marked faces to the output slot */ + BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_MARK); +#undef FACE_MARK +} + +/**************************************************************************** * + * Similar Edges + **************************************************************************** */ + +/* + * extra edge information + */ +typedef struct SimSel_EdgeExt { + BMEdge *e; + union { + float dir[3]; + float angle; /* angle between the face */ + }; + + union { + float length; /* edge length */ + int faces; /* faces count */ + }; +} SimSel_EdgeExt; + +/* + * select similar edges: the choices are in the enum in source/blender/bmesh/bmesh_operators.h + * choices are length, direction, face, ... + */ +void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) +{ +#define EDGE_MARK 1 + + BMOIter es_iter; /* selected edges iterator */ + BMIter e_iter; /* mesh edges iterator */ + BMEdge *es; /* selected edge */ + BMEdge *e; /* mesh edge */ + int idx = 0, i = 0 /* , f = 0 */; + int *indices = NULL; + SimSel_EdgeExt *e_ext = NULL; + // float *angles = NULL; + float angle; + + int num_sels = 0, num_total = 0; + const int type = BMO_slot_int_get(op, "type"); + const float thresh = BMO_slot_float_get(op, "thresh"); + const int compare = BMO_slot_int_get(op, "compare"); + + /* initial_elem - other_elem */ + float delta_fl; + int delta_i; + + /* sanity checks that the data we need is available */ + switch (type) { + case SIMEDGE_CREASE: + if (!CustomData_has_layer(&bm->edata, CD_CREASE)) { + return; + } + break; + case SIMEDGE_BEVEL: + if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { + return; + } + break; + } + + num_total = BM_mesh_elem_count(bm, BM_EDGE); + + /* iterate through all selected edges and mark them */ + BMO_ITER (es, &es_iter, bm, op, "edges", BM_EDGE) { + BMO_elem_flag_enable(bm, es, EDGE_MARK); + num_sels++; + } + + /* allocate memory for the selected edges indices and for all temporary edges */ + indices = (int *)MEM_callocN(sizeof(int) * num_sels, __func__); + e_ext = (SimSel_EdgeExt *)MEM_callocN(sizeof(SimSel_EdgeExt) * num_total, __func__); + + /* loop through all the edges and fill the edges/indices structure */ + BM_ITER_MESH (e, &e_iter, bm, BM_EDGES_OF_MESH) { + e_ext[i].e = e; + if (BMO_elem_flag_test(bm, e, EDGE_MARK)) { + indices[idx] = i; + idx++; + } + i++; + } + + /* save us some computation time by doing heavy computation once */ + if (type == SIMEDGE_LENGTH || type == SIMEDGE_FACE || type == SIMEDGE_DIR || type == SIMEDGE_FACE_ANGLE) { + for (i = 0; i < num_total; i++) { + switch (type) { + case SIMEDGE_LENGTH: /* compute the length of the edge */ + e_ext[i].length = len_v3v3(e_ext[i].e->v1->co, e_ext[i].e->v2->co); + break; + + case SIMEDGE_DIR: /* compute the direction */ + sub_v3_v3v3(e_ext[i].dir, e_ext[i].e->v1->co, e_ext[i].e->v2->co); + normalize_v3(e_ext[i].dir); + break; + + case SIMEDGE_FACE: /* count the faces around the edge */ + e_ext[i].faces = BM_edge_face_count(e_ext[i].e); + break; + + case SIMEDGE_FACE_ANGLE: + e_ext[i].faces = BM_edge_face_count(e_ext[i].e); + if (e_ext[i].faces == 2) + e_ext[i].angle = BM_edge_calc_face_angle(e_ext[i].e); + break; + } + } + } + + /* select the edges if any */ + for (i = 0; i < num_total; i++) { + e = e_ext[i].e; + if (!BMO_elem_flag_test(bm, e, EDGE_MARK) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + int cont = TRUE; + for (idx = 0; idx < num_sels && cont == TRUE; idx++) { + es = e_ext[indices[idx]].e; + switch (type) { + case SIMEDGE_LENGTH: + delta_fl = e_ext[i].length - e_ext[indices[idx]].length; + if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { + BMO_elem_flag_enable(bm, e, EDGE_MARK); + cont = FALSE; + } + break; + + case SIMEDGE_DIR: + /* compute the angle between the two edges */ + angle = angle_normalized_v3v3(e_ext[i].dir, e_ext[indices[idx]].dir); + + if (angle > (float)(M_PI / 2.0)) /* use the smallest angle between the edges */ + angle = fabsf(angle - (float)M_PI); + + if (angle / (float)(M_PI / 2.0) <= thresh) { + BMO_elem_flag_enable(bm, e, EDGE_MARK); + cont = FALSE; + } + break; + + case SIMEDGE_FACE: + delta_i = e_ext[i].faces - e_ext[indices[idx]].faces; + if (bm_sel_similar_cmp_i(delta_i, compare)) { + BMO_elem_flag_enable(bm, e, EDGE_MARK); + cont = FALSE; + } + break; + + case SIMEDGE_FACE_ANGLE: + if (e_ext[i].faces == 2) { + if (e_ext[indices[idx]].faces == 2) { + if (fabsf(e_ext[i].angle - e_ext[indices[idx]].angle) <= thresh) { + BMO_elem_flag_enable(bm, e, EDGE_MARK); + cont = FALSE; + } + } + } + else { + cont = FALSE; + } + break; + + case SIMEDGE_CREASE: + { + float *c1, *c2; + + c1 = CustomData_bmesh_get(&bm->edata, e->head.data, CD_CREASE); + c2 = CustomData_bmesh_get(&bm->edata, es->head.data, CD_CREASE); + delta_fl = *c1 - *c2; + + if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { + BMO_elem_flag_enable(bm, e, EDGE_MARK); + cont = FALSE; + } + } + break; + + case SIMEDGE_BEVEL: + { + float *c1, *c2; + + c1 = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BWEIGHT); + c2 = CustomData_bmesh_get(&bm->edata, es->head.data, CD_BWEIGHT); + delta_fl = *c1 - *c2; + + if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { + BMO_elem_flag_enable(bm, e, EDGE_MARK); + cont = FALSE; + } + } + break; + + case SIMEDGE_SEAM: + if (BM_elem_flag_test(e, BM_ELEM_SEAM) == BM_elem_flag_test(es, BM_ELEM_SEAM)) { + BMO_elem_flag_enable(bm, e, EDGE_MARK); + cont = FALSE; + } + break; + + case SIMEDGE_SHARP: + if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == BM_elem_flag_test(es, BM_ELEM_SMOOTH)) { + BMO_elem_flag_enable(bm, e, EDGE_MARK); + cont = FALSE; + } + break; + default: + BLI_assert(0); + } + } + } + } + + MEM_freeN(e_ext); + MEM_freeN(indices); + + /* transfer all marked edges to the output slot */ + BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EDGE_MARK); + +#undef EDGE_MARK +} + +/**************************************************************************** * + * Similar Vertices + **************************************************************************** */ + +typedef struct SimSel_VertExt { + BMVert *v; + union { + int num_faces; /* adjacent faces */ + int num_edges; /* adjacent edges */ + MDeformVert *dvert; /* deform vertex */ + }; +} SimSel_VertExt; + +/* + * select similar vertices: the choices are in the enum in source/blender/bmesh/bmesh_operators.h + * choices are normal, face, vertex group... + */ +void bmo_similar_verts_exec(BMesh *bm, BMOperator *op) +{ +#define VERT_MARK 1 + + BMOIter vs_iter; /* selected verts iterator */ + BMIter v_iter; /* mesh verts iterator */ + BMVert *vs; /* selected vertex */ + BMVert *v; /* mesh vertex */ + SimSel_VertExt *v_ext = NULL; + int *indices = NULL; + int num_total = 0, num_sels = 0, i = 0, idx = 0; + const int type = BMO_slot_int_get(op, "type"); + const float thresh = BMO_slot_float_get(op, "thresh"); + const float thresh_radians = thresh * (float)M_PI; + const int compare = BMO_slot_int_get(op, "compare"); + + /* initial_elem - other_elem */ +// float delta_fl; + int delta_i; + + num_total = BM_mesh_elem_count(bm, BM_VERT); + + /* iterate through all selected edges and mark them */ + BMO_ITER (vs, &vs_iter, bm, op, "verts", BM_VERT) { + BMO_elem_flag_enable(bm, vs, VERT_MARK); + num_sels++; + } + + /* allocate memory for the selected vertices indices and for all temporary vertices */ + indices = (int *)MEM_mallocN(sizeof(int) * num_sels, "vertex indices"); + v_ext = (SimSel_VertExt *)MEM_mallocN(sizeof(SimSel_VertExt) * num_total, "vertex extra"); + + /* loop through all the vertices and fill the vertices/indices structure */ + BM_ITER_MESH (v, &v_iter, bm, BM_VERTS_OF_MESH) { + v_ext[i].v = v; + if (BMO_elem_flag_test(bm, v, VERT_MARK)) { + indices[idx] = i; + idx++; + } + + switch (type) { + case SIMVERT_FACE: + /* calling BM_vert_face_count every time is time consumming, so call it only once per vertex */ + v_ext[i].num_faces = BM_vert_face_count(v); + break; + + case SIMVERT_VGROUP: + if (CustomData_has_layer(&(bm->vdata), CD_MDEFORMVERT)) { + v_ext[i].dvert = CustomData_bmesh_get(&bm->vdata, v_ext[i].v->head.data, CD_MDEFORMVERT); + } + else { + v_ext[i].dvert = NULL; + } + break; + case SIMVERT_EDGE: + v_ext[i].num_edges = BM_vert_edge_count(v); + break; + } + + i++; + } + + /* select the vertices if any */ + for (i = 0; i < num_total; i++) { + v = v_ext[i].v; + if (!BMO_elem_flag_test(bm, v, VERT_MARK) && !BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { + int cont = TRUE; + for (idx = 0; idx < num_sels && cont == TRUE; idx++) { + vs = v_ext[indices[idx]].v; + switch (type) { + case SIMVERT_NORMAL: + /* compare the angle between the normals */ + if (angle_normalized_v3v3(v->no, vs->no) <= thresh_radians) { + BMO_elem_flag_enable(bm, v, VERT_MARK); + cont = FALSE; + } + break; + case SIMVERT_FACE: + /* number of adjacent faces */ + delta_i = v_ext[i].num_faces - v_ext[indices[idx]].num_faces; + if (bm_sel_similar_cmp_i(delta_i, compare)) { + BMO_elem_flag_enable(bm, v, VERT_MARK); + cont = FALSE; + } + break; + + case SIMVERT_VGROUP: + if (v_ext[i].dvert != NULL && v_ext[indices[idx]].dvert != NULL) { + if (defvert_find_shared(v_ext[i].dvert, v_ext[indices[idx]].dvert) != -1) { + BMO_elem_flag_enable(bm, v, VERT_MARK); + cont = FALSE; + } + } + break; + case SIMVERT_EDGE: + /* number of adjacent edges */ + delta_i = v_ext[i].num_edges - v_ext[indices[idx]].num_edges; + if (bm_sel_similar_cmp_i(delta_i, compare)) { + BMO_elem_flag_enable(bm, v, VERT_MARK); + cont = FALSE; + } + break; + default: + BLI_assert(0); + } + } + } + } + + MEM_freeN(indices); + MEM_freeN(v_ext); + + BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + +#undef VERT_MARK +} diff --git a/source/blender/bmesh/operators/bmo_slide.c b/source/blender/bmesh/operators/bmo_slide.c index 0036f095d00..6db76119205 100644 --- a/source/blender/bmesh/operators/bmo_slide.c +++ b/source/blender/bmesh/operators/bmo_slide.c @@ -63,7 +63,7 @@ void bmo_slide_vert_exec(BMesh *bm, BMOperator *op) if (G.debug & G_DEBUG) { fprintf(stderr, "slide_vert: No vertex selected..."); } - BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Vertex Slide Error: Invalid selection."); + BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Vertex Slide error: invalid selection"); return; } @@ -83,7 +83,7 @@ void bmo_slide_vert_exec(BMesh *bm, BMOperator *op) if (G.debug & G_DEBUG) { fprintf(stderr, "slide_vert: select a single edge\n"); } - BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Vertex Slide Error: Invalid selection."); + BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Vertex Slide error: invalid selection"); return; } diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c new file mode 100644 index 00000000000..51b9adb5de3 --- /dev/null +++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c @@ -0,0 +1,619 @@ +/* + * ***** 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. + * + * Contributor(s): Alexander Pinzon + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/bmesh/operators/bmo_smooth_laplacian.c + * \ingroup bmesh + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_meshdata_types.h" + +#include "BLI_array.h" +#include "BLI_heap.h" +#include "BLI_math.h" +#include "BLI_math_geom.h" +#include "BLI_smallhash.h" + +#include "BKE_customdata.h" +#include "BKE_mesh.h" + +#include "bmesh.h" + +#include "ONL_opennl.h" + +#include "intern/bmesh_operators_private.h" /* own include */ + +#define SMOOTH_LAPLACIAN_AREA_FACTOR 4.0f +#define SMOOTH_LAPLACIAN_EDGE_FACTOR 2.0f +#define SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE 1.8f +#define SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE 0.15f + +struct BLaplacianSystem { + float *eweights; /* Length weights per Edge */ + float (*fweights)[3]; /* Cotangent weights per face */ + float *ring_areas; /* Total area per ring*/ + float *vlengths; /* Total sum of lengths(edges) per vertice*/ + float *vweights; /* Total sum of weights per vertice*/ + int numEdges; /* Number of edges*/ + int numFaces; /* Number of faces*/ + int numVerts; /* Number of verts*/ + short *zerola; /* Is zero area or length*/ + + /* Pointers to data*/ + BMesh *bm; + BMOperator *op; + NLContext *context; + + /*Data*/ + float min_area; +}; +typedef struct BLaplacianSystem LaplacianSystem; + +static float compute_volume(BMesh *bm); +static float cotan_weight(float *v1, float *v2, float *v3); +static int vert_is_boundary(BMVert *v); +static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts); +static void init_laplacian_matrix(LaplacianSystem *sys); +static void delete_laplacian_system(LaplacianSystem *sys); +static void delete_void_pointer(void *data); +static void fill_laplacian_matrix(LaplacianSystem *sys); +static void memset_laplacian_system(LaplacianSystem *sys, int val); +static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int volumepreservation); +static void volume_preservation(BMesh *bm, BMOperator *op, float vini, float vend, int usex, int usey, int usez); + +static void delete_void_pointer(void *data) +{ + if (data) { + MEM_freeN(data); + data = NULL; + } +} + +static void delete_laplacian_system(LaplacianSystem *sys) +{ + delete_void_pointer(sys->eweights); + delete_void_pointer(sys->fweights); + delete_void_pointer(sys->ring_areas); + delete_void_pointer(sys->vlengths); + delete_void_pointer(sys->vweights); + delete_void_pointer(sys->zerola); + if (sys->context) { + nlDeleteContext(sys->context); + } + sys->bm = NULL; + sys->op = NULL; + MEM_freeN(sys); +} + +static void memset_laplacian_system(LaplacianSystem *sys, int val) +{ + memset(sys->eweights, val, sizeof(float) * sys->numEdges); + memset(sys->fweights, val, sizeof(float) * sys->numFaces * 3); + memset(sys->ring_areas, val, sizeof(float) * sys->numVerts); + memset(sys->vlengths, val, sizeof(float) * sys->numVerts); + memset(sys->vweights, val, sizeof(float) * sys->numVerts); + memset(sys->zerola, val, sizeof(short) * sys->numVerts); +} + +static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts) +{ + LaplacianSystem *sys; + sys = MEM_callocN(sizeof(LaplacianSystem), "ModLaplSmoothSystem"); + sys->numEdges = a_numEdges; + sys->numFaces = a_numFaces; + sys->numVerts = a_numVerts; + + sys->eweights = MEM_callocN(sizeof(float) * sys->numEdges, "ModLaplSmoothEWeight"); + if (!sys->eweights) { + delete_laplacian_system(sys); + return NULL; + } + + sys->fweights = MEM_callocN(sizeof(float) * 3 * sys->numFaces, "ModLaplSmoothFWeight"); + if (!sys->fweights) { + delete_laplacian_system(sys); + return NULL; + } + + sys->ring_areas = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothRingAreas"); + if (!sys->ring_areas) { + delete_laplacian_system(sys); + return NULL; + } + + sys->vlengths = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothVlengths"); + if (!sys->vlengths) { + delete_laplacian_system(sys); + return NULL; + } + + sys->vweights = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothVweights"); + if (!sys->vweights) { + delete_laplacian_system(sys); + return NULL; + } + + sys->zerola = MEM_callocN(sizeof(short) * sys->numVerts, "ModLaplSmoothZeloa"); + if (!sys->zerola) { + delete_laplacian_system(sys); + return NULL; + } + + return sys; +} + +/* Compute weigth between vertice v_i and all your neighbors + * weight between v_i and v_neighbor + * Wij = cot(alpha) + cot(beta) / (4.0 * total area of all faces * sum all weight) + * v_i * + * / | \ + * / | \ + * v_beta* | * v_alpha + * \ | / + * \ | / + * * v_neighbor + */ + +static void init_laplacian_matrix(LaplacianSystem *sys) +{ + float areaf; + float *v1, *v2, *v3, *v4; + float w1, w2, w3, w4; + int i, j; + int has_4_vert; + unsigned int idv1, idv2, idv3, idv4, idv[4]; + BMEdge *e; + BMFace *f; + BMIter eiter; + BMIter fiter; + BMIter vi; + BMVert *vn; + BMVert *vf[4]; + + BM_ITER_MESH_INDEX (e, &eiter, sys->bm, BM_EDGES_OF_MESH, j) { + if (!BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_boundary(e)) { + v1 = e->v1->co; + v2 = e->v2->co; + idv1 = BM_elem_index_get(e->v1); + idv2 = BM_elem_index_get(e->v2); + + w1 = len_v3v3(v1, v2); + if (w1 > sys->min_area) { + w1 = 1.0f / w1; + i = BM_elem_index_get(e); + sys->eweights[i] = w1; + sys->vlengths[idv1] += w1; + sys->vlengths[idv2] += w1; + } + else { + sys->zerola[idv1] = 1; + sys->zerola[idv2] = 1; + } + } + } + + BM_ITER_MESH (f, &fiter, sys->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { + + BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, i) { + vf[i] = vn; + } + has_4_vert = (i == 4) ? 1 : 0; + idv1 = BM_elem_index_get(vf[0]); + idv2 = BM_elem_index_get(vf[1]); + idv3 = BM_elem_index_get(vf[2]); + idv4 = has_4_vert ? BM_elem_index_get(vf[3]) : 0; + + v1 = vf[0]->co; + v2 = vf[1]->co; + v3 = vf[2]->co; + v4 = has_4_vert ? vf[3]->co : 0; + + if (has_4_vert) { + areaf = area_quad_v3(v1, v2, v3, v4); + } + else { + areaf = area_tri_v3(v1, v2, v3); + } + + if (fabsf(areaf) < sys->min_area) { + sys->zerola[idv1] = 1; + sys->zerola[idv2] = 1; + sys->zerola[idv3] = 1; + if (has_4_vert) sys->zerola[idv4] = 1; + } + + sys->ring_areas[idv1] += areaf; + sys->ring_areas[idv2] += areaf; + sys->ring_areas[idv3] += areaf; + if (has_4_vert) sys->ring_areas[idv4] += areaf; + + if (has_4_vert) { + + idv[0] = idv1; + idv[1] = idv2; + idv[2] = idv3; + idv[3] = idv4; + + for (j = 0; j < 4; j++) { + idv1 = idv[j]; + idv2 = idv[(j + 1) % 4]; + idv3 = idv[(j + 2) % 4]; + idv4 = idv[(j + 3) % 4]; + + v1 = vf[j]->co; + v2 = vf[(j + 1) % 4]->co; + v3 = vf[(j + 2) % 4]->co; + v4 = vf[(j + 3) % 4]->co; + + w2 = cotan_weight(v4, v1, v2) + cotan_weight(v3, v1, v2); + w3 = cotan_weight(v2, v3, v1) + cotan_weight(v4, v1, v3); + w4 = cotan_weight(v2, v4, v1) + cotan_weight(v3, v4, v1); + + sys->vweights[idv1] += (w2 + w3 + w4) / 4.0f; + } + } + else { + i = BM_elem_index_get(f); + + w1 = cotan_weight(v1, v2, v3); + w2 = cotan_weight(v2, v3, v1); + w3 = cotan_weight(v3, v1, v2); + + sys->fweights[i][0] += w1; + sys->fweights[i][1] += w2; + sys->fweights[i][2] += w3; + + sys->vweights[idv1] += w2 + w3; + sys->vweights[idv2] += w1 + w3; + sys->vweights[idv3] += w1 + w2; + } + } + } +} + +static void fill_laplacian_matrix(LaplacianSystem *sys) +{ + float *v1, *v2, *v3, *v4; + float w2, w3, w4; + int i, j; + int has_4_vert; + unsigned int idv1, idv2, idv3, idv4, idv[4]; + + BMEdge *e; + BMFace *f; + BMIter eiter; + BMIter fiter; + BMIter vi; + BMVert *vn; + BMVert *vf[4]; + + BM_ITER_MESH (f, &fiter, sys->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { + BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, i) { + vf[i] = vn; + } + has_4_vert = (i == 4) ? 1 : 0; + if (has_4_vert) { + idv[0] = BM_elem_index_get(vf[0]); + idv[1] = BM_elem_index_get(vf[1]); + idv[2] = BM_elem_index_get(vf[2]); + idv[3] = BM_elem_index_get(vf[3]); + for (j = 0; j < 4; j++) { + idv1 = idv[j]; + idv2 = idv[(j + 1) % 4]; + idv3 = idv[(j + 2) % 4]; + idv4 = idv[(j + 3) % 4]; + + v1 = vf[j]->co; + v2 = vf[(j + 1) % 4]->co; + v3 = vf[(j + 2) % 4]->co; + v4 = vf[(j + 3) % 4]->co; + + w2 = cotan_weight(v4, v1, v2) + cotan_weight(v3, v1, v2); + w3 = cotan_weight(v2, v3, v1) + cotan_weight(v4, v1, v3); + w4 = cotan_weight(v2, v4, v1) + cotan_weight(v3, v4, v1); + + w2 = w2 / 4.0f; + w3 = w3 / 4.0f; + w4 = w4 / 4.0f; + + if (!vert_is_boundary(vf[j]) && sys->zerola[idv1] == 0) { + nlMatrixAdd(idv1, idv2, w2 * sys->vweights[idv1]); + nlMatrixAdd(idv1, idv3, w3 * sys->vweights[idv1]); + nlMatrixAdd(idv1, idv4, w4 * sys->vweights[idv1]); + } + } + } + else { + idv1 = BM_elem_index_get(vf[0]); + idv2 = BM_elem_index_get(vf[1]); + idv3 = BM_elem_index_get(vf[2]); + /* Is ring if number of faces == number of edges around vertice*/ + i = BM_elem_index_get(f); + if (!vert_is_boundary(vf[0]) && sys->zerola[idv1] == 0) { + nlMatrixAdd(idv1, idv2, sys->fweights[i][2] * sys->vweights[idv1]); + nlMatrixAdd(idv1, idv3, sys->fweights[i][1] * sys->vweights[idv1]); + } + if (!vert_is_boundary(vf[1]) && sys->zerola[idv2] == 0) { + nlMatrixAdd(idv2, idv1, sys->fweights[i][2] * sys->vweights[idv2]); + nlMatrixAdd(idv2, idv3, sys->fweights[i][0] * sys->vweights[idv2]); + } + if (!vert_is_boundary(vf[2]) && sys->zerola[idv3] == 0) { + nlMatrixAdd(idv3, idv1, sys->fweights[i][1] * sys->vweights[idv3]); + nlMatrixAdd(idv3, idv2, sys->fweights[i][0] * sys->vweights[idv3]); + } + } + } + } + BM_ITER_MESH (e, &eiter, sys->bm, BM_EDGES_OF_MESH) { + if (!BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_boundary(e) ) { + v1 = e->v1->co; + v2 = e->v2->co; + idv1 = BM_elem_index_get(e->v1); + idv2 = BM_elem_index_get(e->v2); + if (sys->zerola[idv1] == 0 && sys->zerola[idv2] == 0) { + i = BM_elem_index_get(e); + nlMatrixAdd(idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]); + nlMatrixAdd(idv2, idv1, sys->eweights[i] * sys->vlengths[idv2]); + } + } + } +} + +static float cotan_weight(float *v1, float *v2, float *v3) +{ + float a[3], b[3], c[3], clen; + + sub_v3_v3v3(a, v2, v1); + sub_v3_v3v3(b, v3, v1); + cross_v3_v3v3(c, a, b); + + clen = len_v3(c); + + if (clen == 0.0f) + return 0.0f; + + return dot_v3v3(a, b) / clen; +} + +static int vert_is_boundary(BMVert *v) +{ + BMEdge *ed; + BMFace *f; + BMIter ei; + BMIter fi; + BM_ITER_ELEM (ed, &ei, v, BM_EDGES_OF_VERT) { + if (BM_edge_is_boundary(ed)) { + return 1; + } + } + BM_ITER_ELEM (f, &fi, v, BM_FACES_OF_VERT) { + if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) { + return 1; + } + } + return 0; +} + +static float compute_volume(BMesh *bm) +{ + float vol = 0.0f; + float x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4; + int i; + BMFace *f; + BMIter fiter; + BMIter vi; + BMVert *vn; + BMVert *vf[4]; + + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, i) { + vf[i] = vn; + } + x1 = vf[0]->co[0]; + y1 = vf[0]->co[1]; + z1 = vf[0]->co[2]; + + x2 = vf[1]->co[0]; + y2 = vf[1]->co[1]; + z2 = vf[1]->co[2]; + + x3 = vf[2]->co[0]; + y3 = vf[2]->co[1]; + z3 = vf[2]->co[2]; + + vol += (1.0f / 6.0f) * (0.0f - x3 * y2 * z1 + x2 * y3 * z1 + x3 * y1 * z2 - x1 * y3 * z2 - x2 * y1 * z3 + x1 * y2 * z3); + + if (i == 4) { + x4 = vf[3]->co[0]; + y4 = vf[3]->co[1]; + z4 = vf[3]->co[2]; + vol += (1.0f / 6.0f) * (x1 * y3 * z4 - x1 * y4 * z3 - x3 * y1 * z4 + x3 * z1 * y4 + y1 * x4 * z3 - x4 * y3 * z1); + } + } + return fabs(vol); +} + +static void volume_preservation(BMesh *bm, BMOperator *op, float vini, float vend, int usex, int usey, int usez) +{ + float beta; + BMOIter siter; + BMVert *v; + + if (vend != 0.0f) { + beta = pow(vini / vend, 1.0f / 3.0f); + BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + if (usex) { + v->co[0] *= beta; + } + if (usey) { + v->co[1] *= beta; + } + if (usez) { + v->co[2] *= beta; + } + + } + } +} + +static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int volumepreservation) +{ + int m_vertex_id; + float leni, lene; + float vini, vend; + float *vi1, *vi2, ve1[3], ve2[3]; + unsigned int idv1, idv2; + BMOIter siter; + BMVert *v; + BMEdge *e; + BMIter eiter; + + BM_ITER_MESH (e, &eiter, sys->bm, BM_EDGES_OF_MESH) { + idv1 = BM_elem_index_get(e->v1); + idv2 = BM_elem_index_get(e->v2); + vi1 = e->v1->co; + vi2 = e->v2->co; + ve1[0] = nlGetVariable(0, idv1); + ve1[1] = nlGetVariable(1, idv1); + ve1[2] = nlGetVariable(2, idv1); + ve2[0] = nlGetVariable(0, idv2); + ve2[1] = nlGetVariable(1, idv2); + ve2[2] = nlGetVariable(2, idv2); + leni = len_v3v3(vi1, vi2); + lene = len_v3v3(ve1, ve2); + if (lene > leni * SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE || lene < leni * SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE) { + sys->zerola[idv1] = 1; + sys->zerola[idv2] = 1; + } + } + + if (volumepreservation) { + vini = compute_volume(sys->bm); + } + BMO_ITER (v, &siter, sys->bm, sys->op, "verts", BM_VERT) { + m_vertex_id = BM_elem_index_get(v); + if (sys->zerola[m_vertex_id] == 0) { + if (usex) { + v->co[0] = nlGetVariable(0, m_vertex_id); + } + if (usey) { + v->co[1] = nlGetVariable(1, m_vertex_id); + } + if (usez) { + v->co[2] = nlGetVariable(2, m_vertex_id); + } + } + } + if (volumepreservation) { + vend = compute_volume(sys->bm); + volume_preservation(sys->bm, sys->op, vini, vend, usex, usey, usez); + } + +} + +void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) +{ + int i; + int m_vertex_id; + int usex, usey, usez, volumepreservation; + float lambda, lambda_border; + float w; + BMOIter siter; + BMVert *v; + LaplacianSystem *sys; + + sys = init_laplacian_system(bm->totedge, bm->totface, bm->totvert); + if (!sys) return; + sys->bm = bm; + sys->op = op; + + memset_laplacian_system(sys, 0); + + BM_mesh_elem_index_ensure(bm, BM_VERT); + lambda = BMO_slot_float_get(op, "lambda"); + lambda_border = BMO_slot_float_get(op, "lambda_border"); + sys->min_area = 0.00001f; + usex = BMO_slot_bool_get(op, "use_x"); + usey = BMO_slot_bool_get(op, "use_y"); + usez = BMO_slot_bool_get(op, "use_z"); + volumepreservation = BMO_slot_bool_get(op, "volume_preservation"); + + + nlNewContext(); + sys->context = nlGetCurrent(); + + nlSolverParameteri(NL_NB_VARIABLES, bm->totvert); + nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); + nlSolverParameteri(NL_NB_ROWS, bm->totvert); + nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 3); + + nlBegin(NL_SYSTEM); + for (i = 0; i < bm->totvert; i++) { + nlLockVariable(i); + } + BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + m_vertex_id = BM_elem_index_get(v); + nlUnlockVariable(m_vertex_id); + nlSetVariable(0, m_vertex_id, v->co[0]); + nlSetVariable(1, m_vertex_id, v->co[1]); + nlSetVariable(2, m_vertex_id, v->co[2]); + } + + nlBegin(NL_MATRIX); + init_laplacian_matrix(sys); + BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + m_vertex_id = BM_elem_index_get(v); + nlRightHandSideAdd(0, m_vertex_id, v->co[0]); + nlRightHandSideAdd(1, m_vertex_id, v->co[1]); + nlRightHandSideAdd(2, m_vertex_id, v->co[2]); + i = m_vertex_id; + if (sys->zerola[i] == 0) { + w = sys->vweights[i] * sys->ring_areas[i]; + sys->vweights[i] = (w == 0.0f) ? 0.0f : -lambda / (4.0f * w); + w = sys->vlengths[i]; + sys->vlengths[i] = (w == 0.0f) ? 0.0f : -lambda_border * 2.0f / w; + + if (!vert_is_boundary(v)) { + nlMatrixAdd(i, i, 1.0f + lambda / (4.0f * sys->ring_areas[i])); + } + else { + nlMatrixAdd(i, i, 1.0f + lambda_border * 2.0f); + } + } + else { + nlMatrixAdd(i, i, 1.0f); + } + } + fill_laplacian_matrix(sys); + + nlEnd(NL_MATRIX); + nlEnd(NL_SYSTEM); + + if (nlSolveAdvanced(NULL, NL_TRUE) ) { + validate_solution(sys, usex, usey, usez, volumepreservation); + } + + delete_laplacian_system(sys); +} diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index b239be1c83b..346daf830d0 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -53,6 +53,9 @@ #define ELE_INNER 8 #define ELE_SPLIT 16 +/* see bug [#32665], 0.00005 means a we get face splits at a little under 1.0 degrees */ +#define FLT_FACE_SPLIT_EPSILON 0.00005f + /* * NOTE: beauty has been renamed to flag! */ @@ -823,16 +826,12 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) /* make sure the two edges have a valid angle to each other */ if (totesel == 2 && BM_edge_share_vert_count(e1, e2)) { - float angle; - sub_v3_v3v3(vec1, e1->v2->co, e1->v1->co); sub_v3_v3v3(vec2, e2->v2->co, e2->v1->co); normalize_v3(vec1); normalize_v3(vec2); - angle = dot_v3v3(vec1, vec2); - angle = fabsf(angle); - if (fabsf(angle - 1.0f) < 0.01f) { + if (fabsf(dot_v3v3(vec1, vec2)) > 1.0f - FLT_FACE_SPLIT_EPSILON) { totesel = 0; } } @@ -983,7 +982,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) * This edge pair could be used by more then one face, * in this case it used to (2.63), split both faces along the same verts * while it could be calculated which face should do the split, - * its ambigious, so in this case we're better off to skip them as exceptional cases + * it's ambiguous, so in this case we're better off to skip them as exceptional cases * and not try to be clever guessing which face to cut up. * * To avoid this case we need to check: diff --git a/source/blender/bmesh/operators/bmo_symmetrize.c b/source/blender/bmesh/operators/bmo_symmetrize.c new file mode 100644 index 00000000000..a428405fb8b --- /dev/null +++ b/source/blender/bmesh/operators/bmo_symmetrize.c @@ -0,0 +1,663 @@ +/* + * ***** 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. + * + * Contributor(s): Nicholas Bishop + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_array.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "bmesh.h" +#include "intern/bmesh_operators_private.h" + +enum { + SYMM_OUTPUT_GEOM = (1 << 0) +}; + +/* Note: don't think there's much need to make these user-adjustable? */ +#define SYMM_AXIS_THRESHOLD 0.00002f +#define SYMM_VERT_THRESHOLD 0.00002f + +typedef enum { + /* Coordinate lies on the side being copied from */ + SYMM_SIDE_KEEP, + /* Coordinate lies on the side being copied from and within the + * axis threshold */ + SYMM_SIDE_AXIS, + /* Coordinate lies on the side being copied to */ + SYMM_SIDE_KILL +} SymmSide; + +typedef struct { + BMesh *bm; + BMOperator *op; + + int axis; + BMO_SymmDirection direction; + + /* Maps from input vertices to their mirrors. If the vertex + * doesn't have a mirror, it's not in this map. If the vertex is + * within the axis threshold, it's mapped to itself. */ + GHash *vert_symm_map; + + /* Edges that cross the symmetry plane and are asymmetric get + * split. This map goes from input edges to output vertices. If an + * edge is not split, it's not in this map. */ + GHash *edge_split_map; +} Symm; + +/* Return which side the coordinate lies on */ +static SymmSide symm_co_side(const Symm *symm, + const float *co) +{ + float comp = co[symm->axis]; + if (ELEM3(symm->direction, + BMO_SYMMETRIZE_NEGATIVE_X, + BMO_SYMMETRIZE_NEGATIVE_Y, + BMO_SYMMETRIZE_NEGATIVE_Z)) + { + comp = -comp; + } + + if (comp >= 0) { + if (comp < SYMM_AXIS_THRESHOLD) + return SYMM_SIDE_AXIS; + else + return SYMM_SIDE_KEEP; + } + else + return SYMM_SIDE_KILL; +} + +/* Output vertices and the vert_map array */ +static void symm_verts_mirror(Symm *symm) +{ + BMOIter oiter; + BMVert *src_v, *dst_v; + + symm->vert_symm_map = BLI_ghash_ptr_new(AT); + + BMO_ITER (src_v, &oiter, symm->bm, symm->op, "input", BM_VERT) { + SymmSide side = symm_co_side(symm, src_v->co); + float co[3]; + + switch (side) { + case SYMM_SIDE_KEEP: + /* The vertex is outside the axis area; output its mirror */ + copy_v3_v3(co, src_v->co); + co[symm->axis] = -co[symm->axis]; + + dst_v = BM_vert_create(symm->bm, co, src_v); + BMO_elem_flag_enable(symm->bm, dst_v, SYMM_OUTPUT_GEOM); + BLI_ghash_insert(symm->vert_symm_map, src_v, dst_v); + break; + + case SYMM_SIDE_AXIS: + /* The vertex is within the axis area, snap to center */ + src_v->co[symm->axis] = 0; + /* Vertex isn't copied, map to itself */ + BLI_ghash_insert(symm->vert_symm_map, src_v, src_v); + break; + + case SYMM_SIDE_KILL: + /* The vertex does not lie in the half-space being + * copied from, nothing to do */ + break; + } + } +} + +static int symm_edge_crosses_axis(const Symm *symm, const BMEdge *e) +{ + const int sides[2] = {symm_co_side(symm, e->v1->co), + symm_co_side(symm, e->v2->co)}; + + return ((sides[0] != SYMM_SIDE_AXIS) && + (sides[1] != SYMM_SIDE_AXIS) && + (sides[0] != sides[1])); +} + +/* Output edge split vertices for asymmetric edges and the edge_splits + * mapping array */ +static void symm_split_asymmetric_edges(Symm *symm) +{ + BMOIter oiter; + BMEdge *e; + + symm->edge_split_map = BLI_ghash_ptr_new(AT); + + BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) { + float flipped[3]; + + copy_v3_v3(flipped, e->v1->co); + flipped[symm->axis] = -flipped[symm->axis]; + + if (symm_edge_crosses_axis(symm, e) && + (!compare_v3v3(e->v2->co, flipped, SYMM_VERT_THRESHOLD))) + { + /* Endpoints lie on opposite sides and are asymmetric */ + + BMVert *v; + float lambda = 0, edge_dir[3], co[3]; + float plane_co[3][3][3] = { + /* axis == 0 */ + {{0, 0, 0}, {0, 1, 0}, {0, 0, 1}}, + /* axis == 1 */ + {{0, 0, 0}, {1, 0, 0}, {0, 0, 1}}, + /* axis == 2 */ + {{0, 0, 0}, {1, 0, 0}, {0, 1, 0}}, + }; + int r; + + /* Find intersection of edge with symmetry plane */ + sub_v3_v3v3(edge_dir, e->v2->co, e->v1->co); + normalize_v3(edge_dir); + r = isect_ray_plane_v3(e->v1->co, + edge_dir, + plane_co[symm->axis][0], + plane_co[symm->axis][1], + plane_co[symm->axis][2], + &lambda, TRUE); + BLI_assert(r); + + madd_v3_v3v3fl(co, e->v1->co, edge_dir, lambda); + co[symm->axis] = 0; + + /* Edge is asymmetric, split it with a new vertex */ + v = BM_vert_create(symm->bm, co, e->v1); + BMO_elem_flag_enable(symm->bm, v, SYMM_OUTPUT_GEOM); + BLI_ghash_insert(symm->edge_split_map, e, v); + } + } +} + +static void symm_mirror_edges(Symm *symm) +{ + BMOIter oiter; + BMEdge *e; + + BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) { + BMVert *v1 = NULL, *v2 = NULL; + BMEdge *e_new; + + v1 = BLI_ghash_lookup(symm->vert_symm_map, e->v1); + v2 = BLI_ghash_lookup(symm->vert_symm_map, e->v2); + + if (v1 && v2) { + e_new = BM_edge_create(symm->bm, v1, v2, e, TRUE); + BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM); + } + else if (v1 || v2) { + if (BLI_ghash_haskey(symm->edge_split_map, e)) { + BMVert *v_split = BLI_ghash_lookup(symm->edge_split_map, e); + + /* Output the keep side of the split edge */ + if (!v1) { + e_new = BM_edge_create(symm->bm, v_split, e->v2, e, TRUE); + BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM); + v1 = v_split; + } + else { + e_new = BM_edge_create(symm->bm, e->v1, v_split, e, TRUE); + BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM); + v2 = v_split; + } + + /* Output the kill side of the split edge */ + e_new = BM_edge_create(symm->bm, v1, v2, e, TRUE); + BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM); + } + } + } +} + +/****************************** SymmPoly ******************************/ + +typedef struct { + /* Indices into the source mvert array (or -1 if not in that array) */ + BMVert **src_verts; + /* Indices into the destination mvert array, these are vertices + * created by an edge split (-1 for vertices not created by edge + * split) */ + BMVert **edge_verts; + + /* Number of vertices in the polygon */ + int len; + + /* True only if none of the polygon's edges were split */ + int already_symmetric; +} SymmPoly; + +static void symm_poly_with_splits(const Symm *symm, + BMFace *f, + SymmPoly *out) +{ + BMIter iter; + BMLoop *l; + int i; + + /* Count vertices and check for edge splits */ + out->len = f->len; + out->already_symmetric = TRUE; + BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { + if (BLI_ghash_haskey(symm->edge_split_map, l->e)) { + out->len++; + out->already_symmetric = FALSE; + } + } + + i = 0; + BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { + BMVert *split = BLI_ghash_lookup(symm->edge_split_map, l->e); + + out->src_verts[i] = l->v; + out->edge_verts[i] = NULL; + i++; + + if (split) { + out->src_verts[i] = NULL; + out->edge_verts[i] = split; + i++; + } + } +} + +static const float *symm_poly_co(const SymmPoly *sp, int v) +{ + if (sp->src_verts[v]) + return sp->src_verts[v]->co; + else if (sp->edge_verts[v]) + return sp->edge_verts[v]->co; + else + return NULL; +} + +static SymmSide symm_poly_co_side(const Symm *symm, + const SymmPoly *sp, + int v) +{ + return symm_co_side(symm, symm_poly_co(sp, v)); +} + +/* Return the index of the vertex in the destination array at corner + * 'v' of the polygon, or -1 if not in that array */ +static BMVert *symm_poly_dst(const SymmPoly *sp, int v) +{ + if (sp->edge_verts[v]) + return sp->edge_verts[v]; + else if (sp->src_verts[v]) + return sp->src_verts[v]; + else + return NULL; +} + +/* Same as above, but returns the index of the mirror if available, or + * the same index if on the axis, or -1 otherwise */ +static BMVert *symm_poly_mirror_dst(const Symm *symm, + const SymmPoly *sp, + int v) +{ + if (sp->edge_verts[v]) + return sp->edge_verts[v]; + else if (sp->src_verts[v]) { + if (BLI_ghash_haskey(symm->vert_symm_map, sp->src_verts[v])) + return BLI_ghash_lookup(symm->vert_symm_map, sp->src_verts[v]); + else + return sp->src_verts[v]; + } + else + return NULL; +} + +static int symm_poly_next_crossing(const Symm *symm, + const SymmPoly *sp, + int start, + int *l1, + int *l2) +{ + int i; + + for (i = 0; i < sp->len; i++) { + (*l1) = (start + i) % sp->len; + (*l2) = ((*l1) + 1) % sp->len; + + if ((symm_poly_co_side(symm, sp, *l1) == SYMM_SIDE_KILL) ^ + (symm_poly_co_side(symm, sp, *l2) == SYMM_SIDE_KILL)) + { + return TRUE; + } + } + + BLI_assert(!"symm_poly_next_crossing failed"); + return FALSE; +} + +static BMFace *symm_face_create_v(BMesh *bm, BMVert **fv, BMEdge **fe, int len) +{ + BMFace *f_new; + int i; + + for (i = 0; i < len; i++) { + int j = (i + 1) % len; + fe[i] = BM_edge_exists(fv[i], fv[j]); + if (!fe[i]) { + fe[i] = BM_edge_create(bm, fv[i], fv[j], NULL, FALSE); + BMO_elem_flag_enable(bm, fe[i], SYMM_OUTPUT_GEOM); + } + } + f_new = BM_face_create(bm, fv, fe, len, TRUE); + BM_face_select_set(bm, f_new, TRUE); + BMO_elem_flag_enable(bm, f_new, SYMM_OUTPUT_GEOM); + return f_new; +} + +static void symm_mesh_output_poly_zero_splits(Symm *symm, + SymmPoly *sp, + BMVert **fv, + BMEdge **fe, + int segment_len, + int start) +{ + int i, j; + + j = 0; + + /* Output the keep side of the input polygon */ + for (i = 0; i < segment_len; i++) { + const int offset = (start + i) % sp->len; + BLI_assert(sp->src_verts[offset]); + fv[j++] = sp->src_verts[offset]; + } + + /* Output the kill side of the polygon */ + for (i = segment_len - 1; i >= 0; i--) { + const int offset = (start + i) % sp->len; + + if (symm_poly_co_side(symm, sp, offset) == SYMM_SIDE_KEEP) { + BLI_assert(sp->src_verts[offset]); + fv[j++] = BLI_ghash_lookup(symm->vert_symm_map, + sp->src_verts[offset]); + } + } + + symm_face_create_v(symm->bm, fv, fe, j); +} + +static void symm_mesh_output_poly_with_splits(Symm *symm, + SymmPoly *sp, + BMVert **fv, + BMEdge **fe, + int segment_len, + int start) +{ + int i; + + /* Output the keep side of the input polygon */ + + for (i = 0; i < segment_len; i++) { + const int offset = (start + i) % sp->len; + BMVert *v = symm_poly_dst(sp, offset); + + BLI_assert(v); + + fv[i] = v; + } + + symm_face_create_v(symm->bm, fv, fe, segment_len); + + /* Output the kill side of the input polygon */ + + for (i = 0; i < segment_len; i++) { + const int offset = (start + i) % sp->len; + BMVert *v = symm_poly_mirror_dst(symm, sp, offset); + + fv[segment_len - i - 1] = v; + + } + + symm_face_create_v(symm->bm, fv, fe, segment_len); +} + +static void symm_mirror_polygons(Symm *symm) +{ + BMOIter oiter; + BMFace *f; + BMVert **pv = NULL; + BMVert **fv = NULL; + BMEdge **fe = NULL; + BLI_array_declare(pv); + BLI_array_declare(fv); + BLI_array_declare(fe); + + BMO_ITER (f, &oiter, symm->bm, symm->op, "input", BM_FACE) { + BMIter iter; + BMLoop *l; + int mirror_all = TRUE, ignore_all = TRUE; + + /* Check if entire polygon can be mirrored or ignored */ + BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { + const SymmSide side = symm_co_side(symm, l->v->co); + if (side == SYMM_SIDE_KILL) + mirror_all = FALSE; + else if (side == SYMM_SIDE_KEEP) + ignore_all = FALSE; + } + + if (mirror_all) { + int i; + + /* Make a mirrored copy of the polygon */ + + BLI_array_empty(fv); + BLI_array_empty(fe); + BLI_array_grow_items(fv, f->len); + BLI_array_grow_items(fe, f->len); + + i = f->len; + BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { + i--; + + if (symm_co_side(symm, l->v->co) == SYMM_SIDE_KEEP) + fv[i] = BLI_ghash_lookup(symm->vert_symm_map, l->v); + else + fv[i] = l->v; + } + + symm_face_create_v(symm->bm, fv, fe, f->len); + } + else if (ignore_all) { + BM_face_kill(symm->bm, f); + } + else { + SymmPoly sp; + int l1, l2, l3, l4; + int double_l2, double_l3; + int segment_len; + + BLI_array_empty(pv); + BLI_array_grow_items(pv, f->len * 4); + sp.src_verts = pv; + sp.edge_verts = pv + f->len * 2; + symm_poly_with_splits(symm, f, &sp); + + /* Find first loop edge crossing the axis */ + symm_poly_next_crossing(symm, &sp, 0, &l1, &l2); + + /* If crossing isn't kill to keep, find the next one */ + if (symm_poly_co_side(symm, &sp, l1) != SYMM_SIDE_KILL) { + symm_poly_next_crossing(symm, &sp, l2, &l1, &l2); + } + + /* Find next crossing (keep to kill) */ + symm_poly_next_crossing(symm, &sp, l2, &l3, &l4); + + if (l2 == l3) + segment_len = 0; + else if (l2 < l3) + segment_len = l3 - l2 + 1; + else + segment_len = (sp.len - l2 + 1) + l3; + + double_l2 = symm_poly_co_side(symm, &sp, l2) == SYMM_SIDE_KEEP; + double_l3 = symm_poly_co_side(symm, &sp, l3) == SYMM_SIDE_KEEP; + + /* Calculate number of new polygons/loops */ + if (segment_len == 0) { + } + else if (sp.already_symmetric) { + int new_loops; + + if (double_l2 && double_l3) + new_loops = segment_len * 2; + else if (!double_l2 && !double_l3) + new_loops = segment_len * 2 - 2; + else + new_loops = segment_len * 2 - 1; + + BLI_array_empty(fv); + BLI_array_empty(fe); + BLI_array_grow_items(fv, new_loops); + BLI_array_grow_items(fe, new_loops); + + symm_mesh_output_poly_zero_splits(symm, &sp, + fv, fe, + segment_len, l2); + BM_face_kill(symm->bm, f); + } + else if (!double_l2 && !double_l3) { + BLI_array_empty(fv); + BLI_array_empty(fe); + BLI_array_grow_items(fv, segment_len); + BLI_array_grow_items(fe, segment_len); + + symm_mesh_output_poly_with_splits(symm, &sp, + fv, fe, + segment_len, + l2); + + BM_face_kill(symm->bm, f); + } + else { + BLI_array_empty(fv); + BLI_array_empty(fe); + BLI_array_grow_items(fv, segment_len); + BLI_array_grow_items(fe, segment_len); + + symm_mesh_output_poly_with_splits(symm, &sp, + fv, fe, + segment_len, + l2); + + BM_face_kill(symm->bm, f); + + /* Output bridge triangle */ + + BLI_array_empty(fv); + BLI_array_empty(fe); + BLI_array_grow_items(fv, 3); + BLI_array_grow_items(fe, 3); + + if (double_l2) { + fv[0] = symm_poly_dst(&sp, l2); + fv[1] = symm_poly_mirror_dst(symm, &sp, l2); + fv[2] = symm_poly_dst(&sp, l3); + } + else if (double_l3) { + fv[0] = symm_poly_dst(&sp, l3); + fv[1] = symm_poly_mirror_dst(symm, &sp, l3); + fv[2] = symm_poly_dst(&sp, l2); + } + + BLI_assert(fv[0] && fv[1] && fv[2]); + + symm_face_create_v(symm->bm, fv, fe, 3); + } + } + } + + BLI_array_free(pv); + BLI_array_free(fv); + BLI_array_free(fe); +} + +/* Remove unused edges and vertices from the side being copied to */ +static void symm_kill_unused(Symm *symm) +{ + BMOIter oiter; + BMEdge *e; + BMVert *v; + + /* Kill unused edges */ + BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) { + const int crosses = symm_edge_crosses_axis(symm, e); + const int symmetric = (crosses && + (!BLI_ghash_haskey(symm->edge_split_map, e))); + + if (((symm_co_side(symm, e->v1->co) == SYMM_SIDE_KILL) || + (symm_co_side(symm, e->v2->co) == SYMM_SIDE_KILL)) && + !symmetric) + { + /* The edge might be used by a face outside the input set */ + if (BM_edge_face_count(e) == 0) + BM_edge_kill(symm->bm, e); + } + } + + /* Kill unused vertices */ + BMO_ITER (v, &oiter, symm->bm, symm->op, "input", BM_VERT) { + if (symm_co_side(symm, v->co) == SYMM_SIDE_KILL) { + if (BM_vert_edge_count(v) == 0) + BM_vert_kill(symm->bm, v); + } + } +} + +void bmo_symmetrize_exec(BMesh *bm, BMOperator *op) +{ + Symm symm; + BMO_SymmDirection direction = BMO_slot_int_get(op, "direction"); + + symm.bm = bm; + symm.op = op; + symm.axis = (ELEM(direction, + BMO_SYMMETRIZE_NEGATIVE_X, + BMO_SYMMETRIZE_POSITIVE_X) ? 0 : + ELEM(direction, + BMO_SYMMETRIZE_NEGATIVE_Y, + BMO_SYMMETRIZE_POSITIVE_Y) ? 1 : + ELEM(direction, + BMO_SYMMETRIZE_NEGATIVE_Z, + BMO_SYMMETRIZE_POSITIVE_Z) ? 2 : 0); + symm.direction = direction; + + symm_verts_mirror(&symm); + symm_split_asymmetric_edges(&symm); + symm_mirror_edges(&symm); + symm_mirror_polygons(&symm); + symm_kill_unused(&symm); + + BLI_ghash_free(symm.vert_symm_map, NULL, NULL); + BLI_ghash_free(symm.edge_split_map, NULL, NULL); + + BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, + SYMM_OUTPUT_GEOM); +} diff --git a/source/blender/bmesh/operators/bmo_unsubdivide.c b/source/blender/bmesh/operators/bmo_unsubdivide.c new file mode 100644 index 00000000000..3d44feac380 --- /dev/null +++ b/source/blender/bmesh/operators/bmo_unsubdivide.c @@ -0,0 +1,59 @@ +/* + * ***** 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. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/bmesh/operators/bmo_unsubdivide.c + * \ingroup bmesh + */ + +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "bmesh.h" + +#include "intern/bmesh_operators_private.h" /* own include */ + +/* - BMVert.flag & BM_ELEM_TAG: shows we touched this vert + * - BMVert.index == -1: shows we will remove this vert + */ +void bmo_unsubdivide_exec(BMesh *bm, BMOperator *op) +{ + BMVert *v; + BMIter iter; + + const int iterations = max_ii(1, BMO_slot_int_get(op, "iterations")); + + BMOpSlot *vinput = BMO_slot_get(op, "verts"); + BMVert **vinput_arr = (BMVert **)vinput->data.p; + int v_index; + + /* tag verts */ + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_elem_flag_disable(v, BM_ELEM_TAG); + } + for (v_index = 0; v_index < vinput->len; v_index++) { + v = vinput_arr[v_index]; + BM_elem_flag_enable(v, BM_ELEM_TAG); + } + + /* do all the real work here */ + BM_mesh_decimate_unsubdivide_ex(bm, iterations, TRUE); +} diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c index 88ed1250264..e311b383b86 100644 --- a/source/blender/bmesh/operators/bmo_utils.c +++ b/source/blender/bmesh/operators/bmo_utils.c @@ -479,550 +479,15 @@ void bmo_smooth_vert_exec(BMesh *bm, BMOperator *op) BLI_array_free(cos); } -/* - * compute the fake surface of an ngon - * This is done by decomposing the ngon into triangles who share the centroid of the ngon - * while this method is far from being exact, it should guarantee an invariance. - * - * NOTE: This should probably go to bmesh_polygon.c - */ -static float ngon_fake_area(BMFace *f) -{ - BMIter liter; - BMLoop *l; - int num_verts = 0; - float v[3], sv[3], c[3]; - float area = 0.0f; - - BM_face_calc_center_mean(f, c); - - BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - if (num_verts == 0) { - copy_v3_v3(v, l->v->co); - copy_v3_v3(sv, l->v->co); - num_verts++; - } - else { - area += area_tri_v3(v, c, l->v->co); - copy_v3_v3(v, l->v->co); - num_verts++; - } - } - - area += area_tri_v3(v, c, sv); - - return area; -} - -/* - * extra face data (computed data) - */ -typedef struct SimSel_FaceExt { - BMFace *f; /* the face */ - float c[3]; /* center */ - union { - float area; /* area */ - float perim; /* perimeter */ - float d; /* 4th component of plane (the first three being the normal) */ - struct Image *t; /* image pointer */ - }; -} SimSel_FaceExt; - -/* - * Select similar faces, the choices are in the enum in source/blender/bmesh/bmesh_operators.h - * We select either similar faces based on material, image, area, perimeter, normal, or the coplanar faces - */ -void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) -{ - BMIter fm_iter; - BMFace *fs, *fm; - BMOIter fs_iter; - int num_sels = 0, num_total = 0, i = 0, idx = 0; - float angle = 0.0f; - SimSel_FaceExt *f_ext = NULL; - int *indices = NULL; - float t_no[3]; /* temporary normal */ - int type = BMO_slot_int_get(op, "type"); - const float thresh = BMO_slot_float_get(op, "thresh"); - const float thresh_radians = thresh * (float)M_PI; - - num_total = BM_mesh_elem_count(bm, BM_FACE); - - /* - * The first thing to do is to iterate through all the the selected items and mark them since - * they will be in the selection anyway. - * This will increase performance, (especially when the number of originally selected faces is high) - * so the overall complexity will be less than $O(mn)$ where is the total number of selected faces, - * and n is the total number of faces - */ - BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { - if (!BMO_elem_flag_test(bm, fs, FACE_MARK)) { /* is this really needed ? */ - BMO_elem_flag_enable(bm, fs, FACE_MARK); - num_sels++; - } - } - - /* allocate memory for the selected faces indices and for all temporary faces */ - indices = (int *)MEM_callocN(sizeof(int) * num_sels, "face indices util.c"); - f_ext = (SimSel_FaceExt *)MEM_callocN(sizeof(SimSel_FaceExt) * num_total, "f_ext util.c"); - - /* loop through all the faces and fill the faces/indices structure */ - BM_ITER_MESH (fm, &fm_iter, bm, BM_FACES_OF_MESH) { - f_ext[i].f = fm; - if (BMO_elem_flag_test(bm, fm, FACE_MARK)) { - indices[idx] = i; - idx++; - } - i++; - } - - /* - * Save us some computation burden: In case of perimeter/area/coplanar selection we compute - * only once. - */ - if (type == SIMFACE_PERIMETER || type == SIMFACE_AREA || type == SIMFACE_COPLANAR || type == SIMFACE_IMAGE) { - for (i = 0; i < num_total; i++) { - switch (type) { - case SIMFACE_PERIMETER: - /* set the perimeter */ - f_ext[i].perim = BM_face_calc_perimeter(f_ext[i].f); - break; - - case SIMFACE_COPLANAR: - /* compute the center of the polygon */ - BM_face_calc_center_mean(f_ext[i].f, f_ext[i].c); - - /* normalize the polygon normal */ - copy_v3_v3(t_no, f_ext[i].f->no); - normalize_v3(t_no); - - /* compute the plane distance */ - f_ext[i].d = dot_v3v3(t_no, f_ext[i].c); - break; - - case SIMFACE_AREA: - f_ext[i].area = ngon_fake_area(f_ext[i].f); - break; - - case SIMFACE_IMAGE: - f_ext[i].t = NULL; - if (CustomData_has_layer(&(bm->pdata), CD_MTEXPOLY)) { - MTexPoly *mtpoly = CustomData_bmesh_get(&bm->pdata, f_ext[i].f->head.data, CD_MTEXPOLY); - f_ext[i].t = mtpoly->tpage; - } - break; - } - } - } - - /* now select the rest (if any) */ - for (i = 0; i < num_total; i++) { - fm = f_ext[i].f; - if (!BMO_elem_flag_test(bm, fm, FACE_MARK) && !BM_elem_flag_test(fm, BM_ELEM_HIDDEN)) { - int cont = TRUE; - for (idx = 0; idx < num_sels && cont == TRUE; idx++) { - fs = f_ext[indices[idx]].f; - switch (type) { - case SIMFACE_MATERIAL: - if (fm->mat_nr == fs->mat_nr) { - BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; - } - break; - - case SIMFACE_IMAGE: - if (f_ext[i].t == f_ext[indices[idx]].t) { - BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; - } - break; - - case SIMFACE_NORMAL: - angle = angle_normalized_v3v3(fs->no, fm->no); /* if the angle between the normals -> 0 */ - if (angle <= thresh_radians) { - BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; - } - break; - - case SIMFACE_COPLANAR: - angle = angle_normalized_v3v3(fs->no, fm->no); /* angle -> 0 */ - if (angle <= thresh_radians) { /* and dot product difference -> 0 */ - if (fabsf(f_ext[i].d - f_ext[indices[idx]].d) <= thresh) { - BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; - } - } - break; - - case SIMFACE_AREA: - if (fabsf(f_ext[i].area - f_ext[indices[idx]].area) <= thresh) { - BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; - } - break; - - case SIMFACE_PERIMETER: - if (fabsf(f_ext[i].perim - f_ext[indices[idx]].perim) <= thresh) { - BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; - } - break; - } - } - } - } - - MEM_freeN(f_ext); - MEM_freeN(indices); - - /* transfer all marked faces to the output slot */ - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_MARK); -} - -/**************************************************************************** * - * Similar Edges - **************************************************************************** */ -#define EDGE_MARK 1 - -/* - * extra edge information - */ -typedef struct SimSel_EdgeExt { - BMEdge *e; - union { - float dir[3]; - float angle; /* angle between the face */ - }; - - union { - float length; /* edge length */ - int faces; /* faces count */ - }; -} SimSel_EdgeExt; - -/* - * select similar edges: the choices are in the enum in source/blender/bmesh/bmesh_operators.h - * choices are length, direction, face, ... - */ -void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) -{ - BMOIter es_iter; /* selected edges iterator */ - BMIter e_iter; /* mesh edges iterator */ - BMEdge *es; /* selected edge */ - BMEdge *e; /* mesh edge */ - int idx = 0, i = 0 /* , f = 0 */; - int *indices = NULL; - SimSel_EdgeExt *e_ext = NULL; - // float *angles = NULL; - float angle; - - int num_sels = 0, num_total = 0; - int type = BMO_slot_int_get(op, "type"); - const float thresh = BMO_slot_float_get(op, "thresh"); - - /* sanity checks that the data we need is available */ - switch (type) { - case SIMEDGE_CREASE: - if (!CustomData_has_layer(&bm->edata, CD_CREASE)) { - return; - } - break; - case SIMEDGE_BEVEL: - if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { - return; - } - break; - } - - num_total = BM_mesh_elem_count(bm, BM_EDGE); - - /* iterate through all selected edges and mark them */ - BMO_ITER (es, &es_iter, bm, op, "edges", BM_EDGE) { - BMO_elem_flag_enable(bm, es, EDGE_MARK); - num_sels++; - } - - /* allocate memory for the selected edges indices and for all temporary edges */ - indices = (int *)MEM_callocN(sizeof(int) * num_sels, __func__); - e_ext = (SimSel_EdgeExt *)MEM_callocN(sizeof(SimSel_EdgeExt) * num_total, __func__); - - /* loop through all the edges and fill the edges/indices structure */ - BM_ITER_MESH (e, &e_iter, bm, BM_EDGES_OF_MESH) { - e_ext[i].e = e; - if (BMO_elem_flag_test(bm, e, EDGE_MARK)) { - indices[idx] = i; - idx++; - } - i++; - } - - /* save us some computation time by doing heavy computation once */ - if (type == SIMEDGE_LENGTH || type == SIMEDGE_FACE || type == SIMEDGE_DIR || type == SIMEDGE_FACE_ANGLE) { - for (i = 0; i < num_total; i++) { - switch (type) { - case SIMEDGE_LENGTH: /* compute the length of the edge */ - e_ext[i].length = len_v3v3(e_ext[i].e->v1->co, e_ext[i].e->v2->co); - break; - - case SIMEDGE_DIR: /* compute the direction */ - sub_v3_v3v3(e_ext[i].dir, e_ext[i].e->v1->co, e_ext[i].e->v2->co); - normalize_v3(e_ext[i].dir); - break; - - case SIMEDGE_FACE: /* count the faces around the edge */ - e_ext[i].faces = BM_edge_face_count(e_ext[i].e); - break; - - case SIMEDGE_FACE_ANGLE: - e_ext[i].faces = BM_edge_face_count(e_ext[i].e); - if (e_ext[i].faces == 2) - e_ext[i].angle = BM_edge_calc_face_angle(e_ext[i].e); - break; - } - } - } - - /* select the edges if any */ - for (i = 0; i < num_total; i++) { - e = e_ext[i].e; - if (!BMO_elem_flag_test(bm, e, EDGE_MARK) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - int cont = TRUE; - for (idx = 0; idx < num_sels && cont == TRUE; idx++) { - es = e_ext[indices[idx]].e; - switch (type) { - case SIMEDGE_LENGTH: - if (fabsf(e_ext[i].length - e_ext[indices[idx]].length) <= thresh) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; - } - break; - - case SIMEDGE_DIR: - /* compute the angle between the two edges */ - angle = angle_normalized_v3v3(e_ext[i].dir, e_ext[indices[idx]].dir); - - if (angle > (float)(M_PI / 2.0)) /* use the smallest angle between the edges */ - angle = fabsf(angle - (float)M_PI); - - if (angle / (float)(M_PI / 2.0) <= thresh) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; - } - break; - - case SIMEDGE_FACE: - if (e_ext[i].faces == e_ext[indices[idx]].faces) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; - } - break; - - case SIMEDGE_FACE_ANGLE: - if (e_ext[i].faces == 2) { - if (e_ext[indices[idx]].faces == 2) { - if (fabsf(e_ext[i].angle - e_ext[indices[idx]].angle) <= thresh) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; - } - } - } - else { - cont = FALSE; - } - break; - - case SIMEDGE_CREASE: - { - float *c1, *c2; - - c1 = CustomData_bmesh_get(&bm->edata, e->head.data, CD_CREASE); - c2 = CustomData_bmesh_get(&bm->edata, es->head.data, CD_CREASE); - - if (fabsf(*c1 - *c2) <= thresh) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; - } - } - break; - - case SIMEDGE_BEVEL: - { - float *c1, *c2; - - c1 = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BWEIGHT); - c2 = CustomData_bmesh_get(&bm->edata, es->head.data, CD_BWEIGHT); - - if (fabsf(*c1 - *c2) <= thresh) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; - } - } - break; - - case SIMEDGE_SEAM: - if (BM_elem_flag_test(e, BM_ELEM_SEAM) == BM_elem_flag_test(es, BM_ELEM_SEAM)) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; - } - break; - - case SIMEDGE_SHARP: - if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == BM_elem_flag_test(es, BM_ELEM_SMOOTH)) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; - } - break; - } - } - } - } - - MEM_freeN(e_ext); - MEM_freeN(indices); - - /* transfer all marked edges to the output slot */ - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EDGE_MARK); -} - -/**************************************************************************** * - * Similar Vertices - **************************************************************************** */ -#define VERT_MARK 1 - -typedef struct SimSel_VertExt { - BMVert *v; - union { - int num_faces; /* adjacent faces */ - int num_edges; /* adjacent edges */ - MDeformVert *dvert; /* deform vertex */ - }; -} SimSel_VertExt; - -/* - * select similar vertices: the choices are in the enum in source/blender/bmesh/bmesh_operators.h - * choices are normal, face, vertex group... - */ -void bmo_similar_verts_exec(BMesh *bm, BMOperator *op) -{ - BMOIter vs_iter; /* selected verts iterator */ - BMIter v_iter; /* mesh verts iterator */ - BMVert *vs; /* selected vertex */ - BMVert *v; /* mesh vertex */ - SimSel_VertExt *v_ext = NULL; - int *indices = NULL; - int num_total = 0, num_sels = 0, i = 0, idx = 0; - int type = BMO_slot_int_get(op, "type"); - const float thresh = BMO_slot_float_get(op, "thresh"); - const float thresh_radians = thresh * (float)M_PI; - - num_total = BM_mesh_elem_count(bm, BM_VERT); - - /* iterate through all selected edges and mark them */ - BMO_ITER (vs, &vs_iter, bm, op, "verts", BM_VERT) { - BMO_elem_flag_enable(bm, vs, VERT_MARK); - num_sels++; - } - - /* allocate memory for the selected vertices indices and for all temporary vertices */ - indices = (int *)MEM_mallocN(sizeof(int) * num_sels, "vertex indices"); - v_ext = (SimSel_VertExt *)MEM_mallocN(sizeof(SimSel_VertExt) * num_total, "vertex extra"); - - /* loop through all the vertices and fill the vertices/indices structure */ - BM_ITER_MESH (v, &v_iter, bm, BM_VERTS_OF_MESH) { - v_ext[i].v = v; - if (BMO_elem_flag_test(bm, v, VERT_MARK)) { - indices[idx] = i; - idx++; - } - - switch (type) { - case SIMVERT_FACE: - /* calling BM_vert_face_count every time is time consumming, so call it only once per vertex */ - v_ext[i].num_faces = BM_vert_face_count(v); - break; - - case SIMVERT_VGROUP: - if (CustomData_has_layer(&(bm->vdata), CD_MDEFORMVERT)) { - v_ext[i].dvert = CustomData_bmesh_get(&bm->vdata, v_ext[i].v->head.data, CD_MDEFORMVERT); - } - else { - v_ext[i].dvert = NULL; - } - break; - case SIMVERT_EDGE: - v_ext[i].num_edges = BM_vert_edge_count(v); - break; - } - - i++; - } - - /* select the vertices if any */ - for (i = 0; i < num_total; i++) { - v = v_ext[i].v; - if (!BMO_elem_flag_test(bm, v, VERT_MARK) && !BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { - int cont = TRUE; - for (idx = 0; idx < num_sels && cont == TRUE; idx++) { - vs = v_ext[indices[idx]].v; - switch (type) { - case SIMVERT_NORMAL: - /* compare the angle between the normals */ - if (angle_normalized_v3v3(v->no, vs->no) <= thresh_radians) { - BMO_elem_flag_enable(bm, v, VERT_MARK); - cont = FALSE; - } - break; - case SIMVERT_FACE: - /* number of adjacent faces */ - if (v_ext[i].num_faces == v_ext[indices[idx]].num_faces) { - BMO_elem_flag_enable(bm, v, VERT_MARK); - cont = FALSE; - } - break; - - case SIMVERT_VGROUP: - if (v_ext[i].dvert != NULL && v_ext[indices[idx]].dvert != NULL) { - int v1, v2; - for (v1 = 0; v1 < v_ext[i].dvert->totweight && cont == 1; v1++) { - for (v2 = 0; v2 < v_ext[indices[idx]].dvert->totweight; v2++) { - if (v_ext[i].dvert->dw[v1].def_nr == v_ext[indices[idx]].dvert->dw[v2].def_nr) { - BMO_elem_flag_enable(bm, v, VERT_MARK); - cont = FALSE; - break; - } - } - } - } - break; - case SIMVERT_EDGE: - /* number of adjacent edges */ - if (v_ext[i].num_edges == v_ext[indices[idx]].num_edges) { - BMO_elem_flag_enable(bm, v, VERT_MARK); - cont = FALSE; - } - break; - } - } - } - } - - MEM_freeN(indices); - MEM_freeN(v_ext); - - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); -} - /**************************************************************************** * * Cycle UVs for a face **************************************************************************** */ void bmo_rotate_uvs_exec(BMesh *bm, BMOperator *op) { - BMOIter fs_iter; /* selected faces iterator */ - BMFace *fs; /* current face */ - BMIter l_iter; /* iteration loop */ - // int n; + BMOIter fs_iter; /* selected faces iterator */ + BMFace *fs; /* current face */ + BMIter l_iter; /* iteration loop */ int dir = BMO_slot_int_get(op, "dir"); @@ -1077,7 +542,6 @@ void bmo_rotate_uvs_exec(BMesh *bm, BMOperator *op) } } } - } /**************************************************************************** * @@ -1126,10 +590,9 @@ void bmo_reverse_uvs_exec(BMesh *bm, BMOperator *op) void bmo_rotate_colors_exec(BMesh *bm, BMOperator *op) { - BMOIter fs_iter; /* selected faces iterator */ - BMFace *fs; /* current face */ - BMIter l_iter; /* iteration loop */ - // int n; + BMOIter fs_iter; /* selected faces iterator */ + BMFace *fs; /* current face */ + BMIter l_iter; /* iteration loop */ int dir = BMO_slot_int_get(op, "dir"); @@ -1234,6 +697,8 @@ typedef struct ElemNode { HeapNode *hn; /* heap node */ } ElemNode; +#define VERT_MARK 1 + void bmo_shortest_path_exec(BMesh *bm, BMOperator *op) { BMOIter vs_iter /* , vs2_iter */; /* selected verts iterator */ @@ -1245,7 +710,7 @@ void bmo_shortest_path_exec(BMesh *bm, BMOperator *op) ElemNode *vert_list = NULL; int num_total = 0 /*, num_sels = 0 */, i = 0; - int type = BMO_slot_int_get(op, "type"); + const int type = BMO_slot_int_get(op, "type"); BMO_ITER (vs, &vs_iter, bm, op, "startv", BM_VERT) { sv = vs; @@ -1284,7 +749,7 @@ void bmo_shortest_path_exec(BMesh *bm, BMOperator *op) vert_list[i].hn = BLI_heap_insert(h, vert_list[i].weight, vert_list[i].v); } - while (!BLI_heap_empty(h)) { + while (!BLI_heap_is_empty(h)) { BMEdge *e; BMIter e_i; float v_weight; diff --git a/source/blender/bmesh/tools/BME_bevel.c b/source/blender/bmesh/tools/BME_bevel.c index 98f270abd16..a632a4446ed 100644 --- a/source/blender/bmesh/tools/BME_bevel.c +++ b/source/blender/bmesh/tools/BME_bevel.c @@ -1096,10 +1096,9 @@ static BMesh *BME_bevel_mesh(BMesh *bm, float value, int UNUSED(res), int option return bm; } -BMesh *BME_bevel(BMEditMesh *em, float value, int res, int options, int defgrp_index, float angle, - BME_TransData_Head **rtd, int do_tessface) +BMesh *BME_bevel(BMesh *bm, float value, int res, int options, int defgrp_index, float angle, + BME_TransData_Head **rtd) { - BMesh *bm = em->bm; BMVert *v; BMIter iter; @@ -1126,12 +1125,6 @@ BMesh *BME_bevel(BMEditMesh *em, float value, int res, int options, int defgrp_i BMO_pop(bm); } - /* possibly needed when running as a tool (which is no longer functional) - * but keep as an option for now */ - if (do_tessface) { - BMEdit_RecalcTessellation(em); - } - /* interactive preview? */ if (rtd) { *rtd = td; diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp index 0e8ead61437..26b5edf7ea6 100644 --- a/source/blender/collada/AnimationExporter.cpp +++ b/source/blender/collada/AnimationExporter.cpp @@ -184,7 +184,7 @@ std::string AnimationExporter::getObjectBoneName(Object *ob, const FCurve *fcu) if (boneName != NULL) return /*id_name(ob) + "_" +*/ std::string(boneName); - else + else return id_name(ob); } @@ -265,7 +265,7 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa MEM_freeN(eul); MEM_freeN(eul_axis); } - else if(!strcmp(transformName, "lens") && (ob->type == OB_CAMERA)) { + else if (!strcmp(transformName, "lens") && (ob->type == OB_CAMERA)) { output_id = create_lens_source_from_fcurve((Camera *) ob->data, COLLADASW::InputSemantic::OUTPUT, fcu, anim_id); } else { @@ -584,8 +584,8 @@ void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSeman values[0] = convert_time(bezt->vec[0][0]); if (bezt->ipo != BEZT_IPO_BEZ) { // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data - values[0] = 0; - values[1] = 0; + values[0] = 0; + values[1] = 0; } else if (is_rotation) { values[1] = RAD2DEGF(bezt->vec[0][1]); @@ -600,8 +600,8 @@ void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSeman values[0] = convert_time(bezt->vec[2][0]); if (bezt->ipo != BEZT_IPO_BEZ) { // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data - values[0] = 0; - values[1] = 0; + values[0] = 0; + values[1] = 0; } else if (is_rotation) { values[1] = RAD2DEGF(bezt->vec[2][1]); @@ -634,11 +634,11 @@ std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemanti switch (semantic) { case COLLADASW::InputSemantic::INPUT: case COLLADASW::InputSemantic::OUTPUT: - source.setAccessorStride(1); + source.setAccessorStride(1); break; case COLLADASW::InputSemantic::IN_TANGENT: case COLLADASW::InputSemantic::OUT_TANGENT: - source.setAccessorStride(2); + source.setAccessorStride(2); break; default: break; @@ -1082,13 +1082,13 @@ std::string AnimationExporter::get_transform_sid(char *rna_path, int tm_type, co break; case 6: tm_name = "diffuse"; - break; + break; case 7: tm_name = "transparency"; - break; + break; case 8: tm_name = "index_of_refraction"; - break; + break; default: tm_name = ""; diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h index 7fd39765cc9..349930dea8f 100644 --- a/source/blender/collada/AnimationExporter.h +++ b/source/blender/collada/AnimationExporter.h @@ -35,10 +35,19 @@ extern "C" #include "DNA_armature_types.h" #include "DNA_material_types.h" +#include "BLI_math.h" +#include "BLI_string.h" +#include "BLI_listbase.h" +#include "BLI_utildefines.h" + #include "BKE_DerivedMesh.h" #include "BKE_fcurve.h" #include "BKE_animsys.h" #include "BKE_scene.h" +#include "BKE_action.h" // pose functions +#include "BKE_armature.h" +#include "BKE_object.h" + #ifdef NAN_BUILDINFO extern char build_rev[]; #endif @@ -46,14 +55,6 @@ extern char build_rev[]; #include "MEM_guardedalloc.h" -#include "BKE_action.h" // pose functions -#include "BKE_armature.h" -#include "BKE_object.h" - -#include "BLI_math.h" -#include "BLI_string.h" -#include "BLI_listbase.h" - #include "RNA_access.h" #include "COLLADASWSource.h" @@ -122,7 +123,7 @@ protected: float convert_angle(float angle); - std::string get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic); + std::string get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic); void add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param, COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis, bool transform); diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp index b2748a55b6a..374f6385ea7 100644 --- a/source/blender/collada/AnimationImporter.cpp +++ b/source/blender/collada/AnimationImporter.cpp @@ -136,7 +136,7 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve) bez.ipo = BEZT_IPO_BEZ; else bez.ipo = BEZT_IPO_CONST; - //bez.h1 = bez.h2 = HD_AUTO; + //bez.h1 = bez.h2 = HD_AUTO; } else { bez.h1 = bez.h2 = HD_AUTO; @@ -617,7 +617,7 @@ void AnimationImporter:: Assign_color_animations(const COLLADAFW::UniqueId& list //Add the curves of the current animation to the object for (iter = animcurves.begin(); iter != animcurves.end(); iter++) { FCurve *fcu = *iter; - BLI_addtail(AnimCurves, fcu); + BLI_addtail(AnimCurves, fcu); } } @@ -854,14 +854,13 @@ static const double get_aspect_ratio(const COLLADAFW::Camera *camera) { double aspect = camera->getAspectRatio().getValue(); - if(aspect == 0) - { + if (aspect == 0) { const double yfov = camera->getYFov().getValue(); - if(yfov == 0) - aspect=1; // assume yfov and xfov are equal - else - { + if (yfov == 0) { + aspect = 1; // assume yfov and xfov are equal + } + else { const double xfov = camera->getXFov().getValue(); if (xfov==0) aspect = 1; @@ -885,7 +884,7 @@ void AnimationImporter::translate_Animations(COLLADAFW::Node *node, COLLADAFW::Node *root = root_map.find(uid) == root_map.end() ? node : root_map[uid]; Object *ob; - if(is_joint) + if (is_joint) ob = armature_importer->get_armature_for_joint(root); else ob = object_map.find(uid) == object_map.end() ? NULL : object_map.find(uid)->second; @@ -938,7 +937,7 @@ void AnimationImporter::translate_Animations(COLLADAFW::Node *node, if (is_matrix) { apply_matrix_curves(ob, animcurves, root, node, transform); } - else { + else { if (is_joint) { @@ -1094,7 +1093,7 @@ void AnimationImporter::translate_Animations(COLLADAFW::Node *node, } } } - } + } } } @@ -1114,8 +1113,8 @@ void AnimationImporter::add_bone_animation_sampled(Object *ob, std::vector* curves, const char* rna_path, int array_index ); + void modify_fcurve(std::vector* curves, const char *rna_path, int array_index ); void unused_fcurve(std::vector* curves ); // prerequisites: // animlist_map - map animlist id -> animlist diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp index 30e9baccbf1..134fd639a73 100644 --- a/source/blender/collada/ArmatureExporter.cpp +++ b/source/blender/collada/ArmatureExporter.cpp @@ -346,7 +346,7 @@ void ArmatureExporter::export_controller(Object *ob, Object *ob_arm) if (this->export_settings->apply_modifiers) { me = bc_to_mesh_apply_modifiers(scene, ob, this->export_settings->export_mesh_type); - } + } else { me = (Mesh *)ob->data; } diff --git a/source/blender/collada/ArmatureImporter.h b/source/blender/collada/ArmatureImporter.h index eead45353af..a6b37287479 100644 --- a/source/blender/collada/ArmatureImporter.h +++ b/source/blender/collada/ArmatureImporter.h @@ -104,7 +104,7 @@ private: #endif void create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBone *parent, int totchild, - float parent_mat[][4], bArmature *arm); + float parent_mat[][4], bArmature *arm); void create_unskinned_bone(COLLADAFW::Node *node, EditBone *parent, int totchild, float parent_mat[][4], Object * ob_arm); diff --git a/source/blender/collada/CMakeLists.txt b/source/blender/collada/CMakeLists.txt index 3b7a38eb950..0091df3c502 100644 --- a/source/blender/collada/CMakeLists.txt +++ b/source/blender/collada/CMakeLists.txt @@ -70,7 +70,7 @@ set(SRC collada_utils.cpp AnimationImporter.h - AnimationExporter.h + AnimationExporter.h ArmatureExporter.h ArmatureImporter.h CameraExporter.h diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index 7683ec1e9cd..c491326519f 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -79,11 +79,26 @@ extern "C" #include "DNA_modifier_types.h" #include "DNA_userdef_types.h" -#include "BKE_DerivedMesh.h" -#include "BKE_fcurve.h" -#include "BKE_animsys.h" #include "BLI_path_util.h" #include "BLI_fileops.h" +#include "BLI_math.h" +#include "BLI_string.h" +#include "BLI_listbase.h" +#include "BLI_utildefines.h" + +#include "BKE_DerivedMesh.h" +#include "BKE_action.h" // pose functions +#include "BKE_animsys.h" +#include "BKE_armature.h" +#include "BKE_blender.h" // version info +#include "BKE_fcurve.h" +#include "BKE_global.h" +#include "BKE_image.h" +#include "BKE_main.h" +#include "BKE_material.h" +#include "BKE_object.h" +#include "BKE_scene.h" + #include "ED_keyframing.h" #ifdef WITH_BUILDINFO extern char build_rev[]; @@ -91,24 +106,11 @@ extern char build_rev[]; #include "MEM_guardedalloc.h" -#include "BKE_blender.h" // version info -#include "BKE_scene.h" -#include "BKE_global.h" -#include "BKE_main.h" -#include "BKE_material.h" -#include "BKE_action.h" // pose functions -#include "BKE_armature.h" -#include "BKE_image.h" -#include "BKE_object.h" - -#include "BLI_math.h" -#include "BLI_string.h" -#include "BLI_listbase.h" - #include "RNA_access.h" } #include "collada_internal.h" +#include "collada_utils.h" #include "DocumentExporter.h" extern bool bc_has_object_type(LinkNode *export_set, short obtype); @@ -160,7 +162,7 @@ void DocumentExporter::exportCurrentScene(Scene *sce) clear_global_id_map(); COLLADABU::NativeString native_filename = - COLLADABU::NativeString(std::string(this->export_settings->filepath)); + COLLADABU::NativeString(std::string(this->export_settings->filepath), COLLADABU::NativeString::ENCODING_UTF8); COLLADASW::StreamWriter sw(native_filename); fprintf(stdout, "Collada export: %s\n", this->export_settings->filepath); diff --git a/source/blender/collada/DocumentExporter.h b/source/blender/collada/DocumentExporter.h index 05620087d76..84c0610282e 100644 --- a/source/blender/collada/DocumentExporter.h +++ b/source/blender/collada/DocumentExporter.h @@ -40,7 +40,7 @@ class DocumentExporter public: DocumentExporter(const ExportSettings *export_settings); void exportCurrentScene(Scene *sce); - void exportScenes(const char* filename); + void exportScenes(const char *filename); private: const ExportSettings *export_settings; }; diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index f29933ea0c1..1c4f0974c6d 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -88,8 +88,8 @@ extern "C" { /* - COLLADA Importer limitations: - - no multiple scene import, all objects are added to active scene + * COLLADA Importer limitations: + * - no multiple scene import, all objects are added to active scene */ // #define COLLADA_DEBUG @@ -210,7 +210,7 @@ void DocumentImporter::finish() } - mesh_importer.optimize_material_assignements(); + mesh_importer.optimize_material_assignments(); armature_importer.set_tags_map(this->uid_tags_map); armature_importer.make_armatures(mContext); @@ -311,7 +311,7 @@ bool DocumentImporter::writeScene(const COLLADAFW::Scene *scene) Object *DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera, Scene *sce) { const COLLADAFW::UniqueId& cam_uid = camera->getInstanciatedObjectId(); - if (uid_camera_map.find(cam_uid) == uid_camera_map.end()) { + if (uid_camera_map.find(cam_uid) == uid_camera_map.end()) { // fprintf(stderr, "Couldn't find camera by UID.\n"); return NULL; } @@ -329,7 +329,7 @@ Object *DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera Object *DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Scene *sce) { const COLLADAFW::UniqueId& lamp_uid = lamp->getInstanciatedObjectId(); - if (uid_lamp_map.find(lamp_uid) == uid_lamp_map.end()) { + if (uid_lamp_map.find(lamp_uid) == uid_lamp_map.end()) { fprintf(stderr, "Couldn't find lamp by UID.\n"); return NULL; } @@ -524,7 +524,7 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent } // if node has child nodes write them COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes(); - for (unsigned int i = 0; i < child_nodes.getCount(); i++) { + for (unsigned int i = 0; i < child_nodes.getCount(); i++) { write_node(child_nodes[i], node, sce, ob, is_library_node); } } @@ -878,7 +878,7 @@ bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera) } break; /* XXX correct way to do following four is probably to get also render - size and determine proper settings from that somehow */ + * size and determine proper settings from that somehow */ case COLLADAFW::Camera::ASPECTRATIO_AND_X: case COLLADAFW::Camera::SINGLE_X: case COLLADAFW::Camera::X_AND_Y: diff --git a/source/blender/collada/DocumentImporter.h b/source/blender/collada/DocumentImporter.h index 13f23b23388..e878a5a5b48 100644 --- a/source/blender/collada/DocumentImporter.h +++ b/source/blender/collada/DocumentImporter.h @@ -78,8 +78,9 @@ public: void write_profile_COMMON(COLLADAFW::EffectCommon*, Material*); void translate_anim_recursive(COLLADAFW::Node*, COLLADAFW::Node*, Object*); - /** This method will be called if an error in the loading process occurred and the loader cannot - continue to load. The writer should undo all operations that have been performed. + /** + * This method will be called if an error in the loading process occurred and the loader cannot + * continue to load. The writer should undo all operations that have been performed. \param errorMessage A message containing informations about the error that occurred. */ void cancel(const COLLADAFW::String& errorMessage); diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp index dd59fb9fb91..e4a654dc99a 100644 --- a/source/blender/collada/EffectExporter.cpp +++ b/source/blender/collada/EffectExporter.cpp @@ -255,7 +255,7 @@ void EffectsExporter::operator()(Material *ma, Object *ob) if (ep.getShaderType() != COLLADASW::EffectProfile::LAMBERT) { cot = getcol(ma->specr * ma->spec, ma->specg * ma->spec, ma->specb * ma->spec, 1.0f); ep.setSpecular(cot, false, "specular"); - } + } // XXX make this more readable if possible @@ -381,7 +381,7 @@ void EffectsExporter::operator()(Material *ma, Object *ob) } std::set::iterator uv_t_iter; - for(uv_t_iter = uv_textures.begin(); uv_t_iter != uv_textures.end(); uv_t_iter++ ) { + for (uv_t_iter = uv_textures.begin(); uv_t_iter != uv_textures.end(); uv_t_iter++ ) { Image *ima = *uv_t_iter; std::string key(id_name(ima)); key = translate_id(key); @@ -405,7 +405,7 @@ void EffectsExporter::operator()(Material *ma, Object *ob) ep.closeProfile(); if (twoSided) mSW->appendTextBlock("1"); - closeEffect(); + closeEffect(); } COLLADASW::ColorOrTexture EffectsExporter::createTexture(Image *ima, diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp index 27700444ba9..f33f0fa110d 100644 --- a/source/blender/collada/GeometryExporter.cpp +++ b/source/blender/collada/GeometryExporter.cpp @@ -38,6 +38,8 @@ #include "DNA_meshdata_types.h" extern "C" { + #include "BLI_utildefines.h" + #include "BKE_DerivedMesh.h" #include "BKE_main.h" #include "BKE_global.h" @@ -78,7 +80,7 @@ void GeometryExporter::operator()(Object *ob) Mesh *me; if (this->export_settings->apply_modifiers) { me = bc_to_mesh_apply_modifiers(mScene, ob, this->export_settings->export_mesh_type); - } + } else { me = (Mesh *)ob->data; } @@ -358,13 +360,13 @@ void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me) param.push_back("X"); param.push_back("Y"); param.push_back("Z"); - /*main function, it creates , */ + /* main function, it creates , */ source.prepareToAppendValues(); //appends data to int i = 0; for (i = 0; i < totverts; i++) { - source.appendValues(verts[i].co[0], verts[i].co[1], verts[i].co[2]); + source.appendValues(verts[i].co[0], verts[i].co[1], verts[i].co[2]); } source.finish(); diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp index f1f1efdbd33..2e0c0f1ea57 100644 --- a/source/blender/collada/ImageExporter.cpp +++ b/source/blender/collada/ImageExporter.cpp @@ -62,7 +62,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) if (not_yet_exported) { ImBuf *imbuf = BKE_image_get_ibuf(image, NULL); - if(!imbuf) { + if (!imbuf) { fprintf(stderr, "Collada export: image does not exist:\n%s\n", image->name); return; } @@ -103,7 +103,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) // So we have to export it. The export will keep the image state intact, // so the exported file will not be associated with the image. - if (BKE_imbuf_write_as(imbuf, export_path, &imageFormat, image->colorspace_settings.name, true) == 0) { + if (BKE_imbuf_write_as(imbuf, export_path, &imageFormat, true) == 0) { fprintf(stderr, "Collada export: Cannot export image to:\n%s\n", export_path); return; } diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp index cf211e2fbb1..8337a977b3b 100644 --- a/source/blender/collada/MeshImporter.cpp +++ b/source/blender/collada/MeshImporter.cpp @@ -478,7 +478,7 @@ void MeshImporter::allocate_face_data(COLLADAFW::Mesh *mesh, Mesh *me, int new_t int total_facecount = 0; // collect edge_count and face_count from all parts - for (int i = 0; i < prim_arr.getCount(); i++) { + for (int i = 0; i < prim_arr.getCount(); i++) { COLLADAFW::MeshPrimitive *mp = prim_arr[i]; int type = mp->getPrimitiveType(); switch (type) { @@ -506,7 +506,7 @@ unsigned int MeshImporter::get_loose_edge_count(COLLADAFW::Mesh *mesh) { int loose_edge_count = 0; // collect edge_count and face_count from all parts - for (int i = 0; i < prim_arr.getCount(); i++) { + for (int i = 0; i < prim_arr.getCount(); i++) { COLLADAFW::MeshPrimitive *mp = prim_arr[i]; int type = mp->getPrimitiveType(); switch (type) { @@ -998,7 +998,7 @@ static bool bc_has_same_material_configuration(Object *ob1, Object *ob2) if (ob1->totcol != ob2->totcol) return false; // not same number of materials if (ob1->totcol == 0) return false; // no material at all - for(int index=0; index < ob1->totcol; index++) { + for (int index=0; index < ob1->totcol; index++) { if (ob1->matbits[index] != ob2->matbits[index]) return false; // shouldn't happen if (ob1->matbits[index] == 0) return false; // shouldn't happen if (ob1->mat[index] != ob2->mat[index]) return false; // different material assignment @@ -1061,7 +1061,7 @@ std::vector MeshImporter::get_all_users_of(Mesh *reference_mesh) * * During import all materials have been assigned to Object. * Now we iterate over the imported objects and optimize - * the assignements as follows: + * the assignments as follows: * * for each imported geometry: * if number of users is 1: @@ -1075,7 +1075,7 @@ std::vector MeshImporter::get_all_users_of(Mesh *reference_mesh) * adjust all other users accordingly. * **/ -void MeshImporter::optimize_material_assignements() +void MeshImporter::optimize_material_assignments() { for (std::vector::iterator it = imported_objects.begin(); it != imported_objects.end(); ++it) @@ -1119,7 +1119,7 @@ void MeshImporter::optimize_material_assignements() * come along with different materials. So we first create the objects * and assign the materials to Object, then in a later cleanup we decide * which materials shall be moved to the created geometries. Also see - * optimize_material_assignements() above. + * optimize_material_assignments() above. */ MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial, std::map& uid_material_map, diff --git a/source/blender/collada/MeshImporter.h b/source/blender/collada/MeshImporter.h index 2cac26d5329..746b0738108 100644 --- a/source/blender/collada/MeshImporter.h +++ b/source/blender/collada/MeshImporter.h @@ -106,10 +106,10 @@ private: #endif void set_face_uv(MTFace *mtface, UVDataWrapper &uvs, - COLLADAFW::IndexList& index_list, unsigned int *tris_indices); + COLLADAFW::IndexList& index_list, unsigned int *tris_indices); void set_face_uv(MTFace *mtface, UVDataWrapper &uvs, - COLLADAFW::IndexList& index_list, int index, bool quad); + COLLADAFW::IndexList& index_list, int index, bool quad); #ifdef COLLADA_DEBUG void print_index_list(COLLADAFW::IndexList& index_list); @@ -132,7 +132,7 @@ private: CustomData create_edge_custom_data(EdgeHash *eh); - void allocate_face_data(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris); + void allocate_face_data(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris); // TODO: import uv set names void read_faces(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris); @@ -153,22 +153,22 @@ public: virtual Object *get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid); MTex *assign_textures_to_uvlayer(COLLADAFW::TextureCoordinateBinding &ctexture, - Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map, - MTex *color_texture); + Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map, + MTex *color_texture); - void optimize_material_assignements(); + void optimize_material_assignments(); MTFace *assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial, - std::map& uid_material_map, - Object *ob, const COLLADAFW::UniqueId *geom_uid, - MTex **color_texture, char *layername, MTFace *texture_face, - std::map& material_texture_mapping_map, short mat_index); + std::map& uid_material_map, + Object *ob, const COLLADAFW::UniqueId *geom_uid, + MTex **color_texture, char *layername, MTFace *texture_face, + std::map& material_texture_mapping_map, short mat_index); Object *create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom, - bool isController, - std::map& uid_material_map, - std::map& material_texture_mapping_map); + bool isController, + std::map& uid_material_map, + std::map& material_texture_mapping_map); // create a mesh storing a pointer in a map so it can be retrieved later by geometry UID bool write_geometry(const COLLADAFW::Geometry* geom); diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp index 4aaff024cac..6d239ae0fb1 100644 --- a/source/blender/collada/SceneExporter.cpp +++ b/source/blender/collada/SceneExporter.cpp @@ -24,9 +24,13 @@ * \ingroup collada */ +extern "C" { + #include "BLI_utildefines.h" + #include "BKE_object.h" +} + #include "SceneExporter.h" #include "collada_utils.h" -#include "BKE_object.h" SceneExporter::SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings) : COLLADASW::LibraryVisualScenes(sw), arm_exporter(arm), export_settings(export_settings) diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp index f7e0f75ec5c..fbb18887d1b 100644 --- a/source/blender/collada/collada.cpp +++ b/source/blender/collada/collada.cpp @@ -76,6 +76,7 @@ int collada_export(Scene *sce, if (!BLI_exists(filepath)) { BLI_make_existing_file(filepath); /* makes the dir if its not there */ if (BLI_file_touch(filepath) == 0) { + fprintf(stdout, "Collada export: Can not create: %s\n", filepath); return 0; } } diff --git a/source/blender/collada/collada_internal.h b/source/blender/collada/collada_internal.h index c1f75f996ce..6eec6a1675e 100644 --- a/source/blender/collada/collada_internal.h +++ b/source/blender/collada/collada_internal.h @@ -88,6 +88,7 @@ extern std::string translate_id(const std::string &id); extern std::string id_name(void *id); +extern std::string get_geometry_id(Object *ob); extern std::string get_geometry_id(Object *ob, bool use_instantiation); extern std::string get_light_id(Object *ob); diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 018d66c6f55..35844b549de 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -35,7 +35,6 @@ #include "collada_utils.h" extern "C" { - #include "DNA_modifier_types.h" #include "DNA_customdata_types.h" #include "DNA_object_types.h" @@ -44,6 +43,7 @@ extern "C" { #include "DNA_armature_types.h" #include "BLI_math.h" +#include "BLI_linklist.h" #include "BKE_context.h" #include "BKE_customdata.h" @@ -51,10 +51,7 @@ extern "C" { #include "BKE_object.h" #include "BKE_mesh.h" #include "BKE_scene.h" - #include "BKE_DerivedMesh.h" -#include "BLI_linklist.h" - #include "WM_api.h" // XXX hrm, see if we can do without this #include "WM_types.h" diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h index b52115722fe..b8990c3fcdd 100644 --- a/source/blender/collada/collada_utils.h +++ b/source/blender/collada/collada_utils.h @@ -35,18 +35,19 @@ #include #include +extern "C" { #include "DNA_object_types.h" #include "DNA_mesh_types.h" #include "DNA_customdata_types.h" #include "DNA_texture_types.h" -#include "BKE_context.h" -#include "BKE_object.h" - #include "DNA_scene_types.h" -extern "C" { -#include "BKE_DerivedMesh.h" #include "BLI_linklist.h" +#include "BLI_utildefines.h" + +#include "BKE_context.h" +#include "BKE_object.h" +#include "BKE_DerivedMesh.h" } #include "ExportSettings.h" diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 9932ed17378..b3e76a287ea 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -1,4 +1,3 @@ -# $Id: CMakeLists.txt 14444 2008-04-16 22:40:48Z hos $ # ***** BEGIN GPL LICENSE BLOCK ***** # # This program is free software; you can redistribute it and/or @@ -272,6 +271,11 @@ set(SRC operations/COM_NormalizeOperation.cpp operations/COM_NormalizeOperation.h + nodes/COM_PixelateNode.cpp + nodes/COM_PixelateNode.h + operations/COM_PixelateOperation.cpp + operations/COM_PixelateOperation.h + # Filter nodes nodes/COM_BilateralBlurNode.cpp nodes/COM_BilateralBlurNode.h @@ -650,6 +654,6 @@ list(APPEND INC ${CMAKE_CURRENT_BINARY_DIR}/operations ) data_to_c(${CMAKE_CURRENT_SOURCE_DIR}/operations/COM_OpenCLKernels.cl - ${CMAKE_CURRENT_BINARY_DIR}/operations/COM_OpenCLKernels.cl.h SRC) + ${CMAKE_CURRENT_BINARY_DIR}/operations/COM_OpenCLKernels.cl.h SRC) blender_add_lib(bf_compositor "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index 71067ac8f15..2b09c9d5b8c 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -119,6 +119,7 @@ #include "COM_ViewLevelsNode.h" #include "COM_ViewerNode.h" #include "COM_ZCombineNode.h" +#include "COM_PixelateNode.h" Node *Converter::convert(bNode *b_node, bool fast) { @@ -390,6 +391,9 @@ Node *Converter::convert(bNode *b_node, bool fast) node = new TrackPositionNode(b_node); break; /* not inplemented yet */ + case CMP_NODE_PIXELATE: + node = new PixelateNode(b_node); + break; default: node = new MuteNode(b_node); break; diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp index 5c891705089..0553aebbba6 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp +++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp @@ -204,7 +204,7 @@ void ExecutionGroup::determineNumberOfChunks() this->m_numberOfXChunks = 1; this->m_numberOfYChunks = 1; this->m_numberOfChunks = 1; - } + } else { const float chunkSizef = this->m_chunkSize; this->m_numberOfXChunks = ceil(this->m_width / chunkSizef); @@ -475,10 +475,10 @@ bool ExecutionGroup::scheduleAreaWhenPossible(ExecutionSystem *graph, rcti *area int maxxchunk = ceil((area->xmax - 1) / chunkSizef); int minychunk = floor(area->ymin / chunkSizef); int maxychunk = ceil((area->ymax - 1) / chunkSizef); - minxchunk = MAX2(minxchunk, 0); - minychunk = MAX2(minychunk, 0); - maxxchunk = MIN2(maxxchunk, this->m_numberOfXChunks); - maxychunk = MIN2(maxychunk, this->m_numberOfYChunks); + minxchunk = max(minxchunk, 0); + minychunk = max(minychunk, 0); + maxxchunk = min(maxxchunk, (int)this->m_numberOfXChunks); + maxychunk = min(maxychunk, (int)this->m_numberOfYChunks); bool result = true; for (indexx = minxchunk; indexx < maxxchunk; indexx++) { diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp index a13717c9d86..c6e0f6c2cfb 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp @@ -25,6 +25,7 @@ #include #include "PIL_time.h" +#include "BLI_utildefines.h" #include "BKE_node.h" #include "COM_Converter.h" @@ -50,7 +51,7 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re this->m_context.setbNodeTree(editingtree); this->m_context.setFastCalculation(fastcalculation); bNode *gnode; - for (gnode = (bNode *)editingtree->nodes.first; gnode; gnode = (bNode *)gnode->next) { + for (gnode = (bNode *)editingtree->nodes.first; gnode; gnode = gnode->next) { if (gnode->type == NODE_GROUP && gnode->typeinfo->group_edit_get(gnode)) { this->m_context.setActivegNode(gnode); break; @@ -240,12 +241,32 @@ void ExecutionSystem::addReadWriteBufferOperations(NodeOperation *operation) } } +#ifndef NDEBUG +/* if this fails, there are still connection to/from this node, + * which have not been properly relinked to operations! + */ +static void debug_check_node_connections(Node *node) +{ + for (int i = 0; i < node->getNumberOfInputSockets(); ++i) { + BLI_assert(!node->getInputSocket(i)->isConnected()); + } + for (int i = 0; i < node->getNumberOfOutputSockets(); ++i) { + BLI_assert(!node->getOutputSocket(i)->isConnected()); + } +} +#else +/* stub */ +#define debug_check_node_connections(node) +#endif + void ExecutionSystem::convertToOperations() { unsigned int index; for (index = 0; index < this->m_nodes.size(); index++) { Node *node = (Node *)this->m_nodes[index]; node->convertToOperations(this, &this->m_context); + + debug_check_node_connections(node); } for (index = 0; index < this->m_connections.size(); index++) { @@ -315,6 +336,16 @@ void ExecutionSystem::addSocketConnection(SocketConnection *connection) this->m_connections.push_back(connection); } +void ExecutionSystem::removeSocketConnection(SocketConnection *connection) +{ + for (vector::iterator it = m_connections.begin(); it != m_connections.end(); ++it) { + if (*it == connection) { + this->m_connections.erase(it); + return; + } + } +} + void ExecutionSystem::findOutputExecutionGroup(vector *result, CompositorPriority priority) const { diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.h b/source/blender/compositor/intern/COM_ExecutionSystem.h index 56a60bf7a03..25f06108d96 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.h +++ b/source/blender/compositor/intern/COM_ExecutionSystem.h @@ -188,6 +188,11 @@ public: SocketConnection *addNodeLink(bNodeLink *bNodeLink); void addSocketConnection(SocketConnection *connection); + /** + * Remove a socket connection from the system. + */ + void removeSocketConnection(SocketConnection *connection); + /** * @brief Convert all nodes to operations */ diff --git a/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp b/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp index bedbfc72722..506bd42ace3 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp @@ -49,8 +49,9 @@ void ExecutionSystemHelper::addbNodeTree(ExecutionSystem &system, int nodes_star /* add all nodes of the tree to the node list */ bNode *node = (bNode *)tree->nodes.first; while (node != NULL) { - addNode(nodes, node, isActiveGroup, system.getContext().isFastCalculation()); - node = (bNode *)node->next; + Node *nnode = addNode(nodes, node, isActiveGroup, system.getContext().isFastCalculation()); + nnode->setbNodeGroup(groupnode); + node = node->next; } NodeRange node_range(nodes.begin() + nodes_start, nodes.end()); @@ -59,7 +60,7 @@ void ExecutionSystemHelper::addbNodeTree(ExecutionSystem &system, int nodes_star bNodeLink *nodelink = (bNodeLink *)tree->links.first; while (nodelink != NULL) { addNodeLink(node_range, links, nodelink); - nodelink = (bNodeLink *)nodelink->next; + nodelink = nodelink->next; } /* Expand group nodes */ diff --git a/source/blender/compositor/intern/COM_InputSocket.cpp b/source/blender/compositor/intern/COM_InputSocket.cpp index a9c280e0367..2493d4e5a27 100644 --- a/source/blender/compositor/intern/COM_InputSocket.cpp +++ b/source/blender/compositor/intern/COM_InputSocket.cpp @@ -122,6 +122,17 @@ void InputSocket::relinkConnections(InputSocket *relinkToSocket, int editorNode } } +void InputSocket::unlinkConnections(ExecutionSystem *system) +{ + SocketConnection *connection = getConnection(); + if (connection) { + system->removeSocketConnection(connection); + connection->getFromSocket()->removeConnection(connection); + setConnection(NULL); + delete connection; + } +} + bool InputSocket::isStatic() { if (isConnected()) { diff --git a/source/blender/compositor/intern/COM_InputSocket.h b/source/blender/compositor/intern/COM_InputSocket.h index 259479015aa..5cd4cf3beb7 100644 --- a/source/blender/compositor/intern/COM_InputSocket.h +++ b/source/blender/compositor/intern/COM_InputSocket.h @@ -87,16 +87,10 @@ public: /** * @brief determine the resolution of this data going through this socket * @param resolution the result of this operation - * @param preferredResolution the preferrable resolution as no resolution could be determined + * @param preferredResolution the preferable resolution as no resolution could be determined */ void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - /** - * @brief Notifies the Input of the data type (via a SocketConnection) - * @param datatype the datatype to evaluate - */ - void notifyActualInputType(DataType datatype); - /** * @brief move all connections of this input socket to another socket * only use this method when already checked the availability of a SocketConnection @@ -114,13 +108,21 @@ public: void relinkConnections(InputSocket *relinkToSocket, int editorNodeInputSocketIndex, ExecutionSystem *system); /** - * @brief move all connections of this input socket to another socket + * @brief add a connection of this input socket to another socket + * @warning make sure to remove the original connection with \a unlinkConnections afterward. * @param relinkToSocket the socket to move to connections to * @param editorNodeInputSocketIndex index of the socket number of the bNode (used to retrieve the value for autoconnection) * @param system ExecutionSystem to update to */ void relinkConnectionsDuplicate(InputSocket *relinkToSocket, int editorNodeInputSocketIndex, ExecutionSystem *system); + /** + * @brief remove all connections of this input socket. + * @warning \a relinkConnectionsDuplicate should be used to ensure this socket is still connected. + * @param system ExecutionSystem to update to + */ + void unlinkConnections(ExecutionSystem *system); + /** * @brief set the resize mode * @param resizeMode the new resize mode. diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cpp b/source/blender/compositor/intern/COM_MemoryBuffer.cpp index 0994f3f8890..357a4c1d4c0 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.cpp +++ b/source/blender/compositor/intern/COM_MemoryBuffer.cpp @@ -160,7 +160,7 @@ void MemoryBuffer::writePixel(int x, int y, const float color[4]) if (x >= this->m_rect.xmin && x < this->m_rect.xmax && y >= this->m_rect.ymin && y < this->m_rect.ymax) { - const int offset = (this->m_chunkWidth * (y-this->m_rect.ymin) + x-this->m_rect.xmin) * COM_NUMBER_OF_CHANNELS; + const int offset = (this->m_chunkWidth * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * COM_NUMBER_OF_CHANNELS; copy_v4_v4(&this->m_buffer[offset], color); } } @@ -170,7 +170,7 @@ void MemoryBuffer::addPixel(int x, int y, const float color[4]) if (x >= this->m_rect.xmin && x < this->m_rect.xmax && y >= this->m_rect.ymin && y < this->m_rect.ymax) { - const int offset = (this->m_chunkWidth * (y-this->m_rect.ymin) + x-this->m_rect.xmin) * COM_NUMBER_OF_CHANNELS; + const int offset = (this->m_chunkWidth * (y - this->m_rect.ymin) + x - this->m_rect.xmin) * COM_NUMBER_OF_CHANNELS; add_v4_v4(&this->m_buffer[offset], color); } } @@ -253,7 +253,7 @@ static void imp2radangle(float A, float B, float C, float F, float *a, float *b, } } -float clipuv(float x, float limit) +static float clipuv(float x, float limit) { x = (x < 0) ? 0 : ((x >= limit) ? (limit - 1) : x); return x; diff --git a/source/blender/compositor/intern/COM_Node.cpp b/source/blender/compositor/intern/COM_Node.cpp index 5922b0e6b08..300d7ef1952 100644 --- a/source/blender/compositor/intern/COM_Node.cpp +++ b/source/blender/compositor/intern/COM_Node.cpp @@ -51,7 +51,7 @@ Node::Node(bNode *editorNode, bool create_sockets): NodeBase() if (input->type == SOCK_VECTOR) dt = COM_DT_VECTOR; this->addInputSocket(dt, (InputSocketResizeMode)input->resizemode, input); - input = (bNodeSocket *)input->next; + input = input->next; } bNodeSocket *output = (bNodeSocket *)editorNode->outputs.first; while (output != NULL) { @@ -60,14 +60,14 @@ Node::Node(bNode *editorNode, bool create_sockets): NodeBase() if (output->type == SOCK_VECTOR) dt = COM_DT_VECTOR; this->addOutputSocket(dt, output); - output = (bNodeSocket *)output->next; + output = output->next; } } } void Node::addSetValueOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex) { - bNodeSocket *bSock = (bNodeSocket *)this->getEditorInputSocket(editorNodeInputSocketIndex); + bNodeSocket *bSock = this->getEditorInputSocket(editorNodeInputSocketIndex); SetValueOperation *operation = new SetValueOperation(); bNodeSocketValueFloat *val = (bNodeSocketValueFloat *)bSock->default_value; operation->setValue(val->value); @@ -114,7 +114,7 @@ SocketConnection *Node::addLink(ExecutionSystem *graph, OutputSocket *outputSock void Node::addSetColorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex) { - bNodeSocket *bSock = (bNodeSocket *)this->getEditorInputSocket(editorNodeInputSocketIndex); + bNodeSocket *bSock = this->getEditorInputSocket(editorNodeInputSocketIndex); SetColorOperation *operation = new SetColorOperation(); bNodeSocketValueRGBA *val = (bNodeSocketValueRGBA *)bSock->default_value; operation->setChannel1(val->value[0]); @@ -127,7 +127,7 @@ void Node::addSetColorOperation(ExecutionSystem *graph, InputSocket *inputsocket void Node::addSetVectorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex) { - bNodeSocket *bSock = (bNodeSocket *)this->getEditorInputSocket(editorNodeInputSocketIndex); + bNodeSocket *bSock = this->getEditorInputSocket(editorNodeInputSocketIndex); bNodeSocketValueVector *val = (bNodeSocketValueVector *)bSock->default_value; SetVectorOperation *operation = new SetVectorOperation(); operation->setX(val->value[0]); diff --git a/source/blender/compositor/intern/COM_Node.h b/source/blender/compositor/intern/COM_Node.h index bfccd069ad1..468a95ed434 100644 --- a/source/blender/compositor/intern/COM_Node.h +++ b/source/blender/compositor/intern/COM_Node.h @@ -20,8 +20,8 @@ * Monique Dewanchand */ -#ifndef _COM_Node_h -#define _COM_Node_h +#ifndef __COM_NODE_H__ +#define __COM_NODE_H__ #include "COM_NodeBase.h" #include "COM_InputSocket.h" @@ -53,6 +53,12 @@ private: * @brief Is this node part of the active group */ bool m_inActiveGroup; + + /** + * @brief The group node this node belongs to. + * @note: used to find the links in the current subtree for muting nodes + */ + bNode* m_bNodeGroup; public: Node(bNode *editorNode, bool create_sockets = true); @@ -134,6 +140,9 @@ public: * @param socket */ OutputSocket *findOutputSocketBybNodeSocket(bNodeSocket *socket); + + inline void setbNodeGroup(bNode* group) {this->m_bNodeGroup = group;} + inline bNode* getbNodeGroup() {return this->m_bNodeGroup;} protected: void addPreviewOperation(ExecutionSystem *system, CompositorContext *context, InputSocket *inputSocket); void addPreviewOperation(ExecutionSystem *system, CompositorContext *context, OutputSocket *outputSocket); @@ -143,4 +152,4 @@ protected: private: }; -#endif +#endif /* __COM_NODE_H__ */ diff --git a/source/blender/compositor/intern/COM_NodeBase.h b/source/blender/compositor/intern/COM_NodeBase.h index b55e444be80..e386b5e08a0 100644 --- a/source/blender/compositor/intern/COM_NodeBase.h +++ b/source/blender/compositor/intern/COM_NodeBase.h @@ -20,8 +20,8 @@ * Monique Dewanchand */ -#ifndef _COM_NodeBase_h -#define _COM_NodeBase_h +#ifndef __COM_NODEBASE_H__ +#define __COM_NODEBASE_H__ #include "COM_InputSocket.h" #include "COM_OutputSocket.h" @@ -97,7 +97,7 @@ public: * @return [true:false] * @see NodeOperation */ - virtual const int isOperation() const { return false; } + virtual const bool isOperation() const { return false; } /** * @brief check if this is an input node @@ -166,4 +166,4 @@ protected: #endif }; -#endif +#endif /* __COM_NODEBASE_H__ */ diff --git a/source/blender/compositor/intern/COM_NodeOperation.cpp b/source/blender/compositor/intern/COM_NodeOperation.cpp index 4ae114bd031..a05c37e1b09 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.cpp +++ b/source/blender/compositor/intern/COM_NodeOperation.cpp @@ -126,7 +126,7 @@ bool NodeOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOper else { rcti tempOutput; bool first = true; - for (int i = 0 ; i < getNumberOfInputSockets() ; i ++) { + for (int i = 0; i < getNumberOfInputSockets(); i ++) { NodeOperation * inputOperation = this->getInputOperation(i); if (inputOperation && inputOperation->determineDependingAreaOfInterest(input, readOperation, &tempOutput)) { if (first) { @@ -137,10 +137,10 @@ bool NodeOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOper first = false; } else { - output->xmin = MIN2(output->xmin, tempOutput.xmin); - output->ymin = MIN2(output->ymin, tempOutput.ymin); - output->xmax = MAX2(output->xmax, tempOutput.xmax); - output->ymax = MAX2(output->ymax, tempOutput.ymax); + output->xmin = min(output->xmin, tempOutput.xmin); + output->ymin = min(output->ymin, tempOutput.ymin); + output->xmax = max(output->xmax, tempOutput.xmax); + output->ymax = max(output->ymax, tempOutput.ymax); } } } diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h index 93a19529d34..42d90eca38f 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.h +++ b/source/blender/compositor/intern/COM_NodeOperation.h @@ -88,13 +88,13 @@ public: * @return [true:false] * @see NodeBase */ - const int isOperation() const { return true; } + const bool isOperation() const { return true; } /** * @brief determine the resolution of this node * @note this method will not set the resolution, this is the responsibility of the caller * @param resolution the result of this operation - * @param preferredResolution the preferrable resolution as no resolution could be determined + * @param preferredResolution the preferable resolution as no resolution could be determined */ virtual void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); @@ -163,7 +163,10 @@ public: * @param clMemToCleanUp all created cl_mem references must be added to this list. Framework will clean this after execution * @param clKernelsToCleanUp all created cl_kernel references must be added to this list. Framework will clean this after execution */ - virtual void executeOpenCL(OpenCLDevice *device, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list *clMemToCleanUp, list *clKernelsToCleanUp) {} + virtual void executeOpenCL(OpenCLDevice *device, + MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, list *clMemToCleanUp, + list *clKernelsToCleanUp) {} virtual void deinitExecution(); bool isResolutionSet() { diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp index d23ed245844..d5da079c9fd 100644 --- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp +++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp @@ -74,7 +74,7 @@ cl_mem OpenCLDevice::COM_clAttachMemoryBufferToKernelParameter(cl_kernel kernel, { cl_int error; - MemoryBuffer *result = (MemoryBuffer *)reader->getInputMemoryBuffer(inputMemoryBuffers); + MemoryBuffer *result = reader->getInputMemoryBuffer(inputMemoryBuffers); const cl_image_format imageFormat = { CL_RGBA, diff --git a/source/blender/compositor/intern/COM_OutputSocket.cpp b/source/blender/compositor/intern/COM_OutputSocket.cpp index f23a48979da..50e9b75b072 100644 --- a/source/blender/compositor/intern/COM_OutputSocket.cpp +++ b/source/blender/compositor/intern/COM_OutputSocket.cpp @@ -54,6 +54,16 @@ void OutputSocket::addConnection(SocketConnection *connection) this->m_connections.push_back(connection); } +void OutputSocket::removeConnection(SocketConnection *connection) +{ + for (vector::iterator it = m_connections.begin(); it != m_connections.end(); ++it) { + if (*it == connection) { + m_connections.erase(it); + return; + } + } +} + void OutputSocket::relinkConnections(OutputSocket *relinkToSocket, bool single) { if (isConnected()) { diff --git a/source/blender/compositor/intern/COM_OutputSocket.h b/source/blender/compositor/intern/COM_OutputSocket.h index dc5ca27cbda..709005a6de0 100644 --- a/source/blender/compositor/intern/COM_OutputSocket.h +++ b/source/blender/compositor/intern/COM_OutputSocket.h @@ -50,6 +50,7 @@ public: OutputSocket(DataType datatype, int inputSocketDataTypeDeterminatorIndex); OutputSocket(OutputSocket *from); void addConnection(SocketConnection *connection); + void removeConnection(SocketConnection *connection); SocketConnection *getConnection(unsigned int index) { return this->m_connections[index]; } const int isConnected() const; int isOutputSocket() const; @@ -57,14 +58,14 @@ public: /** * @brief determine the resolution of this socket * @param resolution the result of this operation - * @param preferredResolution the preferrable resolution as no resolution could be determined + * @param preferredResolution the preferable resolution as no resolution could be determined */ void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); /** * @brief determine the actual data type and channel info. */ - void relinkConnections(OutputSocket *relinkToSocket) { this->relinkConnections(relinkToSocket, false); }; + void relinkConnections(OutputSocket *relinkToSocket) { this->relinkConnections(relinkToSocket, false); } void relinkConnections(OutputSocket *relinkToSocket, bool single); const int getNumberOfConnections() { return this->m_connections.size(); } diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp index f732a40e768..724abb59bcf 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.cpp +++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp @@ -25,6 +25,7 @@ #include "BKE_global.h" +#include "COM_compositor.h" #include "COM_WorkScheduler.h" #include "COM_CPUDevice.h" #include "COM_OpenCLDevice.h" @@ -105,13 +106,11 @@ void **g_highlightedNodesRead; void COM_startReadHighlights() { - if (!g_highlightInitialized) - { + if (!g_highlightInitialized) { return; } - if (g_highlightedNodesRead) - { + if (g_highlightedNodesRead) { MEM_freeN(g_highlightedNodesRead); } @@ -265,7 +264,7 @@ bool WorkScheduler::hasGPUDevices() #endif } -extern void clContextError(const char *errinfo, const void *private_info, size_t cb, void *user_data) +static void clContextError(const char *errinfo, const void *private_info, size_t cb, void *user_data) { printf("OPENCL error: %s\n", errinfo); } @@ -331,10 +330,10 @@ void WorkScheduler::initialize(bool use_opencl) const char *cl_str[2] = {datatoc_COM_OpenCLKernels_cl, NULL}; g_program = clCreateProgramWithSource(g_context, 1, cl_str, 0, &error); error = clBuildProgram(g_program, numberOfDevices, cldevices, 0, 0, 0); - if (error != CL_SUCCESS) { + if (error != CL_SUCCESS) { cl_int error2; size_t ret_val_size = 0; - printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); + printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); error2 = clGetProgramBuildInfo(g_program, cldevices[0], CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size); if (error2 != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } char *build_log = (char *)MEM_mallocN(sizeof(char) * ret_val_size + 1, __func__); diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp index 5cfcd83f8f1..49ab9db5dd8 100644 --- a/source/blender/compositor/intern/COM_compositor.cpp +++ b/source/blender/compositor/intern/COM_compositor.cpp @@ -37,7 +37,7 @@ extern "C" { static ThreadMutex s_compositorMutex; static char is_compositorMutex_init = FALSE; -void intern_freeCompositorCaches() +static void intern_freeCompositorCaches() { deintializeDistortionCache(); } @@ -93,7 +93,7 @@ void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering, BLI_mutex_unlock(&s_compositorMutex); } -void COM_freeCaches() +static void UNUSED_FUNCTION(COM_freeCaches)() { if (is_compositorMutex_init) { BLI_mutex_lock(&s_compositorMutex); @@ -102,7 +102,7 @@ void COM_freeCaches() } } -void COM_deinitialize() +void COM_deinitialize() { if (is_compositorMutex_init) { BLI_mutex_lock(&s_compositorMutex); diff --git a/source/blender/compositor/nodes/COM_ChannelMatteNode.h b/source/blender/compositor/nodes/COM_ChannelMatteNode.h index 4efb06c9f87..29c6000a245 100644 --- a/source/blender/compositor/nodes/COM_ChannelMatteNode.h +++ b/source/blender/compositor/nodes/COM_ChannelMatteNode.h @@ -34,4 +34,4 @@ public: void convertToOperations(ExecutionSystem *graph, CompositorContext *context); }; -#endif // COM_ChannelMatteNODE_H +#endif /* COM_ChannelMatteNODE_H */ diff --git a/source/blender/compositor/nodes/COM_ChromaMatteNode.h b/source/blender/compositor/nodes/COM_ChromaMatteNode.h index ddd350aab40..bf5302ccdbb 100644 --- a/source/blender/compositor/nodes/COM_ChromaMatteNode.h +++ b/source/blender/compositor/nodes/COM_ChromaMatteNode.h @@ -34,4 +34,4 @@ public: void convertToOperations(ExecutionSystem *graph, CompositorContext *context); }; -#endif // COM_ChromaMatteNODE_H +#endif /* COM_ChromaMatteNODE_H */ diff --git a/source/blender/compositor/nodes/COM_ColorBalanceNode.h b/source/blender/compositor/nodes/COM_ColorBalanceNode.h index cdad02fc831..30d22ef2e63 100644 --- a/source/blender/compositor/nodes/COM_ColorBalanceNode.h +++ b/source/blender/compositor/nodes/COM_ColorBalanceNode.h @@ -35,4 +35,4 @@ public: void convertToOperations(ExecutionSystem *graph, CompositorContext *context); }; -#endif // COM_ColorBalanceNODE_H +#endif /* COM_ColorBalanceNODE_H */ diff --git a/source/blender/compositor/nodes/COM_ColorMatteNode.h b/source/blender/compositor/nodes/COM_ColorMatteNode.h index 92a4fa79408..3386476bc85 100644 --- a/source/blender/compositor/nodes/COM_ColorMatteNode.h +++ b/source/blender/compositor/nodes/COM_ColorMatteNode.h @@ -34,4 +34,4 @@ public: void convertToOperations(ExecutionSystem *graph, CompositorContext *context); }; -#endif // COM_ColorMatteNODE_H +#endif /* COM_ColorMatteNODE_H */ diff --git a/source/blender/compositor/nodes/COM_ColorRampNode.h b/source/blender/compositor/nodes/COM_ColorRampNode.h index 6c256c09e68..3f00e1c2190 100644 --- a/source/blender/compositor/nodes/COM_ColorRampNode.h +++ b/source/blender/compositor/nodes/COM_ColorRampNode.h @@ -35,4 +35,4 @@ public: void convertToOperations(ExecutionSystem *graph, CompositorContext *context); }; -#endif // COM_ColorRampNODE_H +#endif /* COM_ColorRampNODE_H */ diff --git a/source/blender/compositor/nodes/COM_ColorSpillNode.h b/source/blender/compositor/nodes/COM_ColorSpillNode.h index 1d976fc65ae..01722fac826 100644 --- a/source/blender/compositor/nodes/COM_ColorSpillNode.h +++ b/source/blender/compositor/nodes/COM_ColorSpillNode.h @@ -35,4 +35,4 @@ public: void convertToOperations(ExecutionSystem *graph, CompositorContext *context); }; -#endif // COM_ColorSpillNODE_H +#endif /* COM_ColorSpillNODE_H */ diff --git a/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp b/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp index 70aeee8fc27..254dfb7b9c7 100644 --- a/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp +++ b/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp @@ -35,7 +35,7 @@ void ConvertAlphaNode::convertToOperations(ExecutionSystem *graph, CompositorCon } else { operation = new ConvertKeyToPremulOperation(); - } + } this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); diff --git a/source/blender/compositor/nodes/COM_CropNode.cpp b/source/blender/compositor/nodes/COM_CropNode.cpp index b80a3e088f2..f09bb7e1c26 100644 --- a/source/blender/compositor/nodes/COM_CropNode.cpp +++ b/source/blender/compositor/nodes/COM_CropNode.cpp @@ -40,7 +40,7 @@ void CropNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co operation = new CropImageOperation(); } else { - operation = new CropOperation(); + operation = new CropOperation(); } operation->setCropSettings(cropSettings); operation->setRelative(relative); diff --git a/source/blender/compositor/nodes/COM_DifferenceMatteNode.h b/source/blender/compositor/nodes/COM_DifferenceMatteNode.h index 191b7361c3c..0b571889571 100644 --- a/source/blender/compositor/nodes/COM_DifferenceMatteNode.h +++ b/source/blender/compositor/nodes/COM_DifferenceMatteNode.h @@ -35,4 +35,4 @@ public: void convertToOperations(ExecutionSystem *graph, CompositorContext *context); }; -#endif // COM_DifferenceMatteNODE_H +#endif /* COM_DifferenceMatteNODE_H */ diff --git a/source/blender/compositor/nodes/COM_DilateErodeNode.cpp b/source/blender/compositor/nodes/COM_DilateErodeNode.cpp index 5bd2f78d8a6..0fb7ea7d264 100644 --- a/source/blender/compositor/nodes/COM_DilateErodeNode.cpp +++ b/source/blender/compositor/nodes/COM_DilateErodeNode.cpp @@ -79,7 +79,7 @@ void DilateErodeNode::convertToOperations(ExecutionSystem *graph, CompositorCont CompositorQuality quality = context->getQuality(); /* initialize node data */ - NodeBlurData *data = (NodeBlurData *)&this->m_alpha_blur; + NodeBlurData *data = &this->m_alpha_blur; memset(data, 0, sizeof(*data)); data->filtertype = R_FILTER_GAUSS; @@ -95,6 +95,7 @@ void DilateErodeNode::convertToOperations(ExecutionSystem *graph, CompositorCont operationx->setbNode(editorNode); operationx->setData(data); operationx->setQuality(quality); + operationx->setFalloff(PROP_SMOOTH); this->getInputSocket(0)->relinkConnections(operationx->getInputSocket(0), 0, graph); // this->getInputSocket(1)->relinkConnections(operationx->getInputSocket(1), 1, graph); // no size input yet graph->addOperation(operationx); @@ -102,6 +103,7 @@ void DilateErodeNode::convertToOperations(ExecutionSystem *graph, CompositorCont operationy->setbNode(editorNode); operationy->setData(data); operationy->setQuality(quality); + operationy->setFalloff(PROP_SMOOTH); this->getOutputSocket(0)->relinkConnections(operationy->getOutputSocket()); graph->addOperation(operationy); addLink(graph, operationx->getOutputSocket(), operationy->getInputSocket(0)); diff --git a/source/blender/compositor/nodes/COM_DistanceMatteNode.h b/source/blender/compositor/nodes/COM_DistanceMatteNode.h index 4e6682424e8..46ceae7c4f4 100644 --- a/source/blender/compositor/nodes/COM_DistanceMatteNode.h +++ b/source/blender/compositor/nodes/COM_DistanceMatteNode.h @@ -34,4 +34,4 @@ public: void convertToOperations(ExecutionSystem *graph, CompositorContext *context); }; -#endif // COM_DistanceMatteNODE_H +#endif /* COM_DistanceMatteNODE_H */ diff --git a/source/blender/compositor/nodes/COM_FilterNode.h b/source/blender/compositor/nodes/COM_FilterNode.h index d65166944d8..9be3bb02494 100644 --- a/source/blender/compositor/nodes/COM_FilterNode.h +++ b/source/blender/compositor/nodes/COM_FilterNode.h @@ -20,8 +20,8 @@ * Monique Dewanchand */ -#ifndef _COM_FilterNode_h_ -#define _COM_FilterNode_h_ +#ifndef __COM_FILTERNODE_H__ +#define __COM_FILTERNODE_H__ #include "COM_Node.h" @@ -35,4 +35,4 @@ public: void convertToOperations(ExecutionSystem *graph, CompositorContext *context); }; -#endif // _COM_FilterNode_h_ +#endif /* __COM_FILTERNODE_H__ */ diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp index 9b55b809212..29e10db0758 100644 --- a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp +++ b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp @@ -50,7 +50,7 @@ void HueSaturationValueNode::convertToOperations(ExecutionSystem *graph, Composi ChangeHSVOperation *changeHSV = new ChangeHSVOperation(); MixBlendOperation *blend = new MixBlendOperation(); - colorSocket->relinkConnections(rgbToHSV->getInputSocket(0), 0, graph); + colorSocket->relinkConnections(rgbToHSV->getInputSocket(0), 1, graph); addLink(graph, rgbToHSV->getOutputSocket(), changeHSV->getInputSocket(0)); addLink(graph, changeHSV->getOutputSocket(), hsvToRGB->getInputSocket(0)); addLink(graph, hsvToRGB->getOutputSocket(), blend->getInputSocket(2)); diff --git a/source/blender/compositor/nodes/COM_KeyingNode.cpp b/source/blender/compositor/nodes/COM_KeyingNode.cpp index 6bc9afba32c..51ea2913e65 100644 --- a/source/blender/compositor/nodes/COM_KeyingNode.cpp +++ b/source/blender/compositor/nodes/COM_KeyingNode.cpp @@ -151,7 +151,7 @@ OutputSocket *KeyingNode::setupFeather(ExecutionSystem *graph, CompositorContext CompositorQuality quality = context->getQuality(); /* initialize node data */ - NodeBlurData *data = (NodeBlurData *)&this->m_alpha_blur; + NodeBlurData *data = &this->m_alpha_blur; memset(data, 0, sizeof(*data)); data->filtertype = R_FILTER_GAUSS; diff --git a/source/blender/compositor/nodes/COM_LuminanceMatteNode.h b/source/blender/compositor/nodes/COM_LuminanceMatteNode.h index 37f3c31113f..a71e68cf636 100644 --- a/source/blender/compositor/nodes/COM_LuminanceMatteNode.h +++ b/source/blender/compositor/nodes/COM_LuminanceMatteNode.h @@ -19,8 +19,8 @@ * Dalai Felinto */ -#ifndef _COM_LuminanceMatteNode_h_ -#define _COM_LuminanceMatteNode_h_ +#ifndef __COM_LUMINANCEMATTENODE_H__ +#define __COM_LUMINANCEMATTENODE_H__ #include "COM_Node.h" @@ -34,4 +34,4 @@ public: void convertToOperations(ExecutionSystem *graph, CompositorContext *context); }; -#endif // _COM_LuminanceMatteNode_h_ +#endif /* __COM_LUMINANCEMATTENODE_H__ */ diff --git a/source/blender/compositor/nodes/COM_MapValueNode.h b/source/blender/compositor/nodes/COM_MapValueNode.h index 22aa5459ec0..bd8e3d08e9c 100644 --- a/source/blender/compositor/nodes/COM_MapValueNode.h +++ b/source/blender/compositor/nodes/COM_MapValueNode.h @@ -20,8 +20,8 @@ * Monique Dewanchand */ -#ifndef _COM_MapValueNode_h_ -#define _COM_MapValueNode_h_ +#ifndef __COM_MAPVALUENODE_H__ +#define __COM_MAPVALUENODE_H__ #include "COM_Node.h" #include "DNA_node_types.h" @@ -35,4 +35,4 @@ public: void convertToOperations(ExecutionSystem *graph, CompositorContext *context); }; -#endif // _COM_MapValueNode_h_ +#endif /* __COM_MAPVALUENODE_H__ */ diff --git a/source/blender/compositor/nodes/COM_MaskNode.h b/source/blender/compositor/nodes/COM_MaskNode.h index cdd5d3c362e..9ef3e5deb50 100644 --- a/source/blender/compositor/nodes/COM_MaskNode.h +++ b/source/blender/compositor/nodes/COM_MaskNode.h @@ -21,8 +21,8 @@ * Sergey Sharybin */ -#ifndef _COM_MaskNode_h_ -#define _COM_MaskNode_h_ +#ifndef __COM_MASKNODE_H__ +#define __COM_MASKNODE_H__ #include "COM_Node.h" #include "DNA_node_types.h" @@ -38,4 +38,4 @@ public: }; -#endif // _COM_MaskNode_h_ +#endif /* __COM_MASKNODE_H__ */ diff --git a/source/blender/compositor/nodes/COM_MovieClipNode.h b/source/blender/compositor/nodes/COM_MovieClipNode.h index 52ea11ea8e9..2fb38860a34 100644 --- a/source/blender/compositor/nodes/COM_MovieClipNode.h +++ b/source/blender/compositor/nodes/COM_MovieClipNode.h @@ -20,8 +20,8 @@ * Monique Dewanchand */ -#ifndef _COM_MovieClipNode_h_ -#define _COM_MovieClipNode_h_ +#ifndef __COM_MOVIECLIPNODE_H__ +#define __COM_MOVIECLIPNODE_H__ #include "COM_Node.h" #include "DNA_node_types.h" @@ -36,4 +36,4 @@ public: void convertToOperations(ExecutionSystem *graph, CompositorContext *context); }; -#endif // _COM_MovieClipNode_h_ +#endif /* __COM_MOVIECLIPNODE_H__ */ diff --git a/source/blender/compositor/nodes/COM_MuteNode.cpp b/source/blender/compositor/nodes/COM_MuteNode.cpp index eb2da147eca..4502dcf469c 100644 --- a/source/blender/compositor/nodes/COM_MuteNode.cpp +++ b/source/blender/compositor/nodes/COM_MuteNode.cpp @@ -108,20 +108,16 @@ void MuteNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co /* mute node is also used for unknown nodes and couple of nodes in fast mode * can't use generic routines in that case */ - if ((editorNode->flag & NODE_MUTED) && editorNode->typeinfo->internal_connect) { + if (editorNode->flag & NODE_MUTED) { vector &inputsockets = this->getInputSockets(); vector relinkedsockets; - bNodeTree *editorTree = (bNodeTree *) context->getbNodeTree(); SocketMap socketMap; - ListBase intlinks; bNodeLink *link; - intlinks = editorNode->typeinfo->internal_connect(editorTree, editorNode); - this->fillSocketMap(outputsockets, socketMap); this->fillSocketMap(inputsockets, socketMap); - for (link = (bNodeLink *) intlinks.first; link; link = link->next) { + for (link = (bNodeLink *) editorNode->internal_links.first; link; link = link->next) { if (link->fromnode == editorNode) { InputSocket *fromSocket = (InputSocket *) socketMap.find(link->fromsock)->second; OutputSocket *toSocket = (OutputSocket *) socketMap.find(link->tosock)->second; @@ -163,8 +159,6 @@ void MuteNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co createDefaultOutput(graph, output); } } - - BLI_freelistN(&intlinks); } else { for (unsigned int index = 0; index < outputsockets.size(); index++) { diff --git a/source/blender/compositor/nodes/COM_NormalNode.h b/source/blender/compositor/nodes/COM_NormalNode.h index 660d90040bd..64d4e3a3656 100644 --- a/source/blender/compositor/nodes/COM_NormalNode.h +++ b/source/blender/compositor/nodes/COM_NormalNode.h @@ -35,4 +35,4 @@ public: void convertToOperations(ExecutionSystem *graph, CompositorContext *context); }; -#endif // COM_NormalNODE_H +#endif /* COM_NormalNODE_H */ diff --git a/source/blender/compositor/nodes/COM_PixelateNode.cpp b/source/blender/compositor/nodes/COM_PixelateNode.cpp new file mode 100644 index 00000000000..f1c7c616a30 --- /dev/null +++ b/source/blender/compositor/nodes/COM_PixelateNode.cpp @@ -0,0 +1,48 @@ +/* + * 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. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + */ + +#include "COM_PixelateNode.h" + +#include "COM_PixelateOperation.h" +#include "COM_ExecutionSystem.h" + +PixelateNode::PixelateNode(bNode *editorNode) : Node(editorNode) +{ + /* pass */ +} + +void PixelateNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) +{ + InputSocket *inputSocket = this->getInputSocket(0); + OutputSocket *outputSocket = this->getOutputSocket(0); + DataType datatype = inputSocket->getDataType(); + if (inputSocket->isConnected()) { + SocketConnection * connection = inputSocket->getConnection(); + OutputSocket* otherOutputSocket = connection->getFromSocket(); + datatype = otherOutputSocket->getDataType(); + } + + PixelateOperation *operation = new PixelateOperation(datatype); + inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); + outputSocket->relinkConnections(operation->getOutputSocket(0)); + graph->addOperation(operation); +} diff --git a/source/blender/compositor/nodes/COM_PixelateNode.h b/source/blender/compositor/nodes/COM_PixelateNode.h new file mode 100644 index 00000000000..c142d2d7a5b --- /dev/null +++ b/source/blender/compositor/nodes/COM_PixelateNode.h @@ -0,0 +1,38 @@ +/* + * 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. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + */ + +#ifndef _COM_PixelateNode_h_ +#define _COM_PixelateNode_h_ + +#include "COM_Node.h" + +/** + * @brief PixelateNode + * @ingroup Node + */ +class PixelateNode : public Node { +public: + PixelateNode(bNode *editorNode); + void convertToOperations(ExecutionSystem *graph, CompositorContext *context); +}; + +#endif diff --git a/source/blender/compositor/nodes/COM_SeparateRGBANode.cpp b/source/blender/compositor/nodes/COM_SeparateRGBANode.cpp index 67ac6ffc388..7fcdebadb46 100644 --- a/source/blender/compositor/nodes/COM_SeparateRGBANode.cpp +++ b/source/blender/compositor/nodes/COM_SeparateRGBANode.cpp @@ -70,4 +70,7 @@ void SeparateRGBANode::convertToOperations(ExecutionSystem *graph, CompositorCon outputASocket->relinkConnections(operation->getOutputSocket(0)); graph->addOperation(operation); } + + /* remove the original connection to the node, this has been duplicated for all operations */ + imageSocket->unlinkConnections(graph); } diff --git a/source/blender/compositor/nodes/COM_TransformNode.h b/source/blender/compositor/nodes/COM_TransformNode.h index 57a7a0229ec..666f2da775e 100644 --- a/source/blender/compositor/nodes/COM_TransformNode.h +++ b/source/blender/compositor/nodes/COM_TransformNode.h @@ -20,8 +20,8 @@ * Monique Dewanchand */ -#ifndef _COM_TransformNode_h_ -#define _COM_TransformNode_h_ +#ifndef __COM_TRANSFORMNODE_H__ +#define __COM_TRANSFORMNODE_H__ #include "COM_Node.h" #include "DNA_node_types.h" @@ -36,4 +36,4 @@ public: void convertToOperations(ExecutionSystem *graph, CompositorContext *context); }; -#endif // _COM_TransformNode_h_ +#endif /* __COM_TRANSFORMNODE_H__ */ diff --git a/source/blender/compositor/nodes/COM_ViewLevelsNode.cpp b/source/blender/compositor/nodes/COM_ViewLevelsNode.cpp index 6bb873e0dec..a515bfc7f47 100644 --- a/source/blender/compositor/nodes/COM_ViewLevelsNode.cpp +++ b/source/blender/compositor/nodes/COM_ViewLevelsNode.cpp @@ -24,6 +24,7 @@ #include "COM_ExecutionSystem.h" #include "COM_CalculateMeanOperation.h" #include "COM_CalculateStandardDeviationOperation.h" +#include "COM_SetValueOperation.h" ViewLevelsNode::ViewLevelsNode(bNode *editorNode) : Node(editorNode) { @@ -64,5 +65,18 @@ void ViewLevelsNode::convertToOperations(ExecutionSystem *graph, CompositorConte graph->addOperation(operation); } } + else { + SetValueOperation *meanOutput = new SetValueOperation(); + SetValueOperation *stdDevOutput = new SetValueOperation(); + + meanOutput->setValue(0.0f); + stdDevOutput->setValue(0.0f); + + this->getOutputSocket(0)->relinkConnections(meanOutput->getOutputSocket()); + this->getOutputSocket(1)->relinkConnections(stdDevOutput->getOutputSocket()); + + graph->addOperation(meanOutput); + graph->addOperation(stdDevOutput); + } } diff --git a/source/blender/compositor/nodes/COM_ViewerNode.cpp b/source/blender/compositor/nodes/COM_ViewerNode.cpp index d67e9e274b0..f44470a9b9a 100644 --- a/source/blender/compositor/nodes/COM_ViewerNode.cpp +++ b/source/blender/compositor/nodes/COM_ViewerNode.cpp @@ -52,8 +52,7 @@ void ViewerNode::convertToOperations(ExecutionSystem *graph, CompositorContext * viewerOperation->setDisplaySettings(context->getDisplaySettings()); viewerOperation->setResolutionInputSocketIndex(0); - if (!imageSocket->isConnected()) - { + if (!imageSocket->isConnected()) { if (alphaSocket->isConnected()) { viewerOperation->setResolutionInputSocketIndex(1); } diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.h b/source/blender/compositor/operations/COM_BokehBlurOperation.h index 37483d3dc69..74ca6b7b058 100644 --- a/source/blender/compositor/operations/COM_BokehBlurOperation.h +++ b/source/blender/compositor/operations/COM_BokehBlurOperation.h @@ -59,6 +59,9 @@ public: void setSize(float size) { this->m_size = size; this->m_sizeavailable = true; } - void executeOpenCL(OpenCLDevice *device, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list *clMemToCleanUp, list *clKernelsToCleanUp); + void executeOpenCL(OpenCLDevice *device, + MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, + MemoryBuffer **inputMemoryBuffers, list *clMemToCleanUp, + list *clKernelsToCleanUp); }; #endif diff --git a/source/blender/compositor/operations/COM_ColorSpillOperation.cpp b/source/blender/compositor/operations/COM_ColorSpillOperation.cpp index 152b10709fb..a8e8cb98564 100644 --- a/source/blender/compositor/operations/COM_ColorSpillOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorSpillOperation.cpp @@ -100,7 +100,7 @@ void ColorSpillOperation::executePixel(float output[4], float x, float y, PixelS } else { copy_v4_v4(output, input); - } + } } float ColorSpillOperation::calculateMapValue(float fac, float *input) { diff --git a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cpp b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cpp index 88289f12ebb..f39a28b87a8 100644 --- a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cpp +++ b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cpp @@ -64,8 +64,8 @@ void ConvertDepthToRadiusOperation::initExecution() this->m_inverseFocalDistance = 1.0f / focalDistance; this->m_aspect = (this->getWidth() > this->getHeight()) ? (this->getHeight() / (float)this->getWidth()) : (this->getWidth() / (float)this->getHeight()); this->m_aperture = 0.5f * (this->m_cam_lens / (this->m_aspect * cam_sensor)) / this->m_fStop; - float minsz = min(getWidth(), getHeight()); - this->m_dof_sp = (float)minsz / ((cam_sensor / 2.0f) / this->m_cam_lens); // <- == aspect * MIN2(img->x, img->y) / tan(0.5f * fov); + const float minsz = min(getWidth(), getHeight()); + this->m_dof_sp = minsz / ((cam_sensor / 2.0f) / this->m_cam_lens); // <- == aspect * min(img->x, img->y) / tan(0.5f * fov); if (this->m_blurPostOperation) { m_blurPostOperation->setSigma(min(m_aperture * 128.0f, this->m_maxRadius)); diff --git a/source/blender/compositor/operations/COM_CropOperation.cpp b/source/blender/compositor/operations/COM_CropOperation.cpp index c33bd2544ac..16c19f3ebaa 100644 --- a/source/blender/compositor/operations/COM_CropOperation.cpp +++ b/source/blender/compositor/operations/COM_CropOperation.cpp @@ -36,25 +36,28 @@ void CropBaseOperation::updateArea() SocketReader *inputReference = this->getInputSocketReader(0); float width = inputReference->getWidth(); float height = inputReference->getHeight(); - if (this->m_relative) { - this->m_settings->x1 = width * this->m_settings->fac_x1; - this->m_settings->x2 = width * this->m_settings->fac_x2; - this->m_settings->y1 = height * this->m_settings->fac_y1; - this->m_settings->y2 = height * this->m_settings->fac_y2; - } - if (width <= this->m_settings->x1 + 1) - this->m_settings->x1 = width - 1; - if (height <= this->m_settings->y1 + 1) - this->m_settings->y1 = height - 1; - if (width <= this->m_settings->x2 + 1) - this->m_settings->x2 = width - 1; - if (height <= this->m_settings->y2 + 1) - this->m_settings->y2 = height - 1; - this->m_xmax = MAX2(this->m_settings->x1, this->m_settings->x2) + 1; - this->m_xmin = MIN2(this->m_settings->x1, this->m_settings->x2); - this->m_ymax = MAX2(this->m_settings->y1, this->m_settings->y2) + 1; - this->m_ymin = MIN2(this->m_settings->y1, this->m_settings->y2); + if (width > 0.0f && height > 0.0f) { + if (this->m_relative) { + this->m_settings->x1 = width * this->m_settings->fac_x1; + this->m_settings->x2 = width * this->m_settings->fac_x2; + this->m_settings->y1 = height * this->m_settings->fac_y1; + this->m_settings->y2 = height * this->m_settings->fac_y2; + } + if (width <= this->m_settings->x1 + 1) + this->m_settings->x1 = width - 1; + if (height <= this->m_settings->y1 + 1) + this->m_settings->y1 = height - 1; + if (width <= this->m_settings->x2 + 1) + this->m_settings->x2 = width - 1; + if (height <= this->m_settings->y2 + 1) + this->m_settings->y2 = height - 1; + + this->m_xmax = max(this->m_settings->x1, this->m_settings->x2) + 1; + this->m_xmin = min(this->m_settings->x1, this->m_settings->x2); + this->m_ymax = max(this->m_settings->y1, this->m_settings->y2) + 1; + this->m_ymin = min(this->m_settings->y1, this->m_settings->y2); + } } void CropBaseOperation::initExecution() @@ -110,5 +113,10 @@ void CropImageOperation::determineResolution(unsigned int resolution[2], unsigne void CropImageOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) { - this->m_inputOperation->read(output, (x + this->m_xmin), (y + this->m_ymin), sampler); + if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) { + this->m_inputOperation->read(output, (x + this->m_xmin), (y + this->m_ymin), sampler); + } + else { + zero_v4(output); + } } diff --git a/source/blender/compositor/operations/COM_CropOperation.h b/source/blender/compositor/operations/COM_CropOperation.h index ddc7f855bf1..d2f2b15aa36 100644 --- a/source/blender/compositor/operations/COM_CropOperation.h +++ b/source/blender/compositor/operations/COM_CropOperation.h @@ -37,7 +37,7 @@ protected: void updateArea(); public: - CropBaseOperation(); + CropBaseOperation(); void initExecution(); void deinitExecution(); void setCropSettings(NodeTwoXYs *settings) { this->m_settings = settings; } diff --git a/source/blender/compositor/operations/COM_DespeckleOperation.h b/source/blender/compositor/operations/COM_DespeckleOperation.h index 5b79d7cb7e0..99635e61544 100644 --- a/source/blender/compositor/operations/COM_DespeckleOperation.h +++ b/source/blender/compositor/operations/COM_DespeckleOperation.h @@ -27,8 +27,8 @@ private: float m_threshold; float m_threshold_neighbour; - int m_filterWidth; - int m_filterHeight; + // int m_filterWidth; + // int m_filterHeight; protected: SocketReader *m_inputOperation; diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp index c4b4452fbb0..f0fffa770f8 100644 --- a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp +++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp @@ -79,7 +79,7 @@ void DilateErodeThresholdOperation::executePixel(float output[4], int x, int y, const int miny = max(y - this->m_scope, rect->ymin); const int maxx = min(x + this->m_scope, rect->xmax); const int maxy = min(y + this->m_scope, rect->ymax); - const int bufferWidth = BLI_RCT_SIZE_X(rect); + const int bufferWidth = BLI_rcti_size_x(rect); int offset; this->m_inputProgram->read(inputValue, x, y, NULL); @@ -199,7 +199,7 @@ void DilateDistanceOperation::executePixel(float output[4], int x, int y, void * const int miny = max(y - this->m_scope, rect->ymin); const int maxx = min(x + this->m_scope, rect->xmax); const int maxy = min(y + this->m_scope, rect->ymax); - const int bufferWidth = BLI_RCT_SIZE_X(rect); + const int bufferWidth = BLI_rcti_size_x(rect); int offset; float value = 0.0f; @@ -273,7 +273,7 @@ void ErodeDistanceOperation::executePixel(float output[4], int x, int y, void *d const int miny = max(y - this->m_scope, rect->ymin); const int maxx = min(x + this->m_scope, rect->xmax); const int maxy = min(y + this->m_scope, rect->ymax); - const int bufferWidth = BLI_RCT_SIZE_X(rect); + const int bufferWidth = BLI_rcti_size_x(rect); int offset; float value = 1.0f; @@ -344,28 +344,28 @@ void *DilateStepOperation::initializeTileData(rcti *rect) for (y = 0; y < bheight; y++) { for (x = 0; x < bwidth - 1; x++) { p = rectf + (bwidth * y + x); - *p = MAX2(*p, *(p + 1)); + *p = max(*p, *(p + 1)); } } for (y = 0; y < bheight; y++) { for (x = bwidth - 1; x >= 1; x--) { p = rectf + (bwidth * y + x); - *p = MAX2(*p, *(p - 1)); + *p = max(*p, *(p - 1)); } } for (x = 0; x < bwidth; x++) { for (y = 0; y < bheight - 1; y++) { p = rectf + (bwidth * y + x); - *p = MAX2(*p, *(p + bwidth)); + *p = max(*p, *(p + bwidth)); } } for (x = 0; x < bwidth; x++) { for (y = bheight - 1; y >= 1; y--) { p = rectf + (bwidth * y + x); - *p = MAX2(*p, *(p - bwidth)); + *p = max(*p, *(p - bwidth)); } } } diff --git a/source/blender/compositor/operations/COM_DisplaceOperation.cpp b/source/blender/compositor/operations/COM_DisplaceOperation.cpp index 31608c88274..1723da11f21 100644 --- a/source/blender/compositor/operations/COM_DisplaceOperation.cpp +++ b/source/blender/compositor/operations/COM_DisplaceOperation.cpp @@ -92,8 +92,8 @@ void DisplaceOperation::executePixel(float output[4], int x, int y, void *data) dxt = p_dx - d_dx; dyt = p_dy - d_dy; - dxt = signf(dxt) * maxf(fabsf(dxt), DISPLACE_EPSILON) / this->getWidth(); - dyt = signf(dyt) * maxf(fabsf(dyt), DISPLACE_EPSILON) / this->getHeight(); + dxt = signf(dxt) * max_ff(fabsf(dxt), DISPLACE_EPSILON) / this->getWidth(); + dyt = signf(dyt) * max_ff(fabsf(dyt), DISPLACE_EPSILON) / this->getHeight(); /* EWA filtering (without nearest it gets blurry with NO distortion) */ this->m_inputColorProgram->read(output, u, v, dxt, dyt, COM_PS_NEAREST); diff --git a/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cpp b/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cpp index 560bbbdd244..c8ebb845bb6 100644 --- a/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cpp +++ b/source/blender/compositor/operations/COM_DisplaceSimpleOperation.cpp @@ -51,7 +51,7 @@ void DisplaceSimpleOperation::initExecution() /* minimum distance (in pixels) a pixel has to be displaced * in order to take effect */ -#define DISPLACE_EPSILON 0.01f +// #define DISPLACE_EPSILON 0.01f void DisplaceSimpleOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) { diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp index 2b2928c98db..4bdb2591cb7 100644 --- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp @@ -128,8 +128,8 @@ void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src, float sigma, unsign // XXX The YVV macro defined below explicitly expects sources of at least 3x3 pixels, // so just skiping blur along faulty direction if src's def is below that limit! - if (src_width < 3) xy &= ~(int) 1; - if (src_height < 3) xy &= ~(int) 2; + if (src_width < 3) xy &= ~1; + if (src_height < 3) xy &= ~2; if (xy < 1) return; // see "Recursive Gabor Filtering" by Young/VanVliet @@ -190,7 +190,7 @@ void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src, float sigma, unsign } (void)0 // intermediate buffers - sz = MAX2(src_width, src_height); + sz = max(src_width, src_height); X = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss X buf"); Y = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss Y buf"); W = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss W buf"); diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp index 8c5e5faf12a..0efead77cd4 100644 --- a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp @@ -102,12 +102,12 @@ void GaussianAlphaXBlurOperation::executePixel(float output[4], int x, int y, vo int bufferstarty = inputBuffer->getRect()->ymin; int miny = y; - int maxy = y; + // int maxy = y; // UNUSED int minx = x - this->m_rad; - int maxx = x + this->m_rad; + int maxx = x + this->m_rad; // UNUSED miny = max(miny, inputBuffer->getRect()->ymin); minx = max(minx, inputBuffer->getRect()->xmin); - maxy = min(maxy, inputBuffer->getRect()->ymax); + // maxy = min(maxy, inputBuffer->getRect()->ymax); maxx = min(maxx, inputBuffer->getRect()->xmax); /* *** this is the main part which is different to 'GaussianXBlurOperation' *** */ @@ -123,7 +123,7 @@ void GaussianAlphaXBlurOperation::executePixel(float output[4], int x, int y, vo float value_max = finv_test(buffer[(x * 4) + (y * 4 * bufferwidth)], do_invert); /* init with the current color to avoid unneeded lookups */ float distfacinv_max = 1.0f; /* 0 to 1 */ - for (int nx = minx; nx < maxx; nx += step) { + for (int nx = minx; nx <= maxx; nx += step) { const int index = (nx - x) + this->m_rad; float value = finv_test(buffer[bufferindex], do_invert); float multiplier; diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp index 197715595ed..1f9cc8e461a 100644 --- a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp @@ -104,11 +104,11 @@ void GaussianAlphaYBlurOperation::executePixel(float output[4], int x, int y, vo int miny = y - this->m_rad; int maxy = y + this->m_rad; int minx = x; - int maxx = x; + // int maxx = x; // UNUSED miny = max(miny, inputBuffer->getRect()->ymin); minx = max(minx, inputBuffer->getRect()->xmin); - maxy = min(maxy, inputBuffer->getRect()->ymax); - maxx = min(maxx, inputBuffer->getRect()->xmax); + maxy = min(maxy, inputBuffer->getRect()->ymax - 1); + // maxx = min(maxx, inputBuffer->getRect()->xmax); /* *** this is the main part which is different to 'GaussianYBlurOperation' *** */ int step = getStep(); @@ -121,7 +121,7 @@ void GaussianAlphaYBlurOperation::executePixel(float output[4], int x, int y, vo float value_max = finv_test(buffer[(x * 4) + (y * 4 * bufferwidth)], do_invert); /* init with the current color to avoid unneeded lookups */ float distfacinv_max = 1.0f; /* 0 to 1 */ - for (int ny = miny; ny < maxy; ny += step) { + for (int ny = miny; ny <= maxy; ny += step) { int bufferindex = ((minx - bufferstartx) * 4) + ((ny - bufferstarty) * 4 * bufferwidth); const int index = (ny - y) + this->m_rad; diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp index a9bcb2dd752..2d662c1061e 100644 --- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp @@ -236,7 +236,7 @@ void GaussianBlurReferenceOperation::initExecution() /* horizontal */ m_radx = (float)this->m_data->sizex; - int imgx = getWidth()/2; + int imgx = getWidth() / 2; if (m_radx > imgx) m_radx = imgx; else if (m_radx < 1) @@ -245,7 +245,7 @@ void GaussianBlurReferenceOperation::initExecution() /* vertical */ m_rady = (float)this->m_data->sizey; - int imgy = getHeight()/2; + int imgy = getHeight() / 2; if (m_rady > imgy) m_rady = imgy; else if (m_rady < 1) @@ -257,7 +257,7 @@ void GaussianBlurReferenceOperation::initExecution() void GaussianBlurReferenceOperation::updateGauss() { int i; - int x = MAX2(m_radx, m_rady); + int x = max(m_radx, m_rady); this->m_maintabs = (float **)MEM_mallocN(x * sizeof(float *), "gauss array"); for (i = 0; i < x; i++) { m_maintabs[i] = make_gausstab(i + 1); @@ -327,11 +327,11 @@ void GaussianBlurReferenceOperation::executePixel(float output[4], int x, int y, void GaussianBlurReferenceOperation::deinitExecution() { int x, i; - x = MAX2(m_radx, m_rady); + x = max(this->m_radx, this->m_rady); for (i = 0; i < x; i++) { - MEM_freeN(m_maintabs[i]); + MEM_freeN(this->m_maintabs[i]); } - MEM_freeN(m_maintabs); + MEM_freeN(this->m_maintabs); BlurBaseOperation::deinitExecution(); } @@ -344,8 +344,8 @@ bool GaussianBlurReferenceOperation::determineDependingAreaOfInterest(rcti *inpu return true; } else { - int addx = this->m_data->sizex+2; - int addy = this->m_data->sizey+2; + int addx = this->m_data->sizex + 2; + int addy = this->m_data->sizey + 2; newInput.xmax = input->xmax + addx; newInput.xmin = input->xmin - addx; newInput.ymax = input->ymax + addy; diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp index 984119b926a..573a19466e8 100644 --- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp @@ -85,18 +85,18 @@ void GaussianXBlurOperation::executePixel(float output[4], int x, int y, void *d int bufferstarty = inputBuffer->getRect()->ymin; int miny = y; - int maxy = y; + // int maxy = y; // UNUSED int minx = x - this->m_rad; int maxx = x + this->m_rad; miny = max(miny, inputBuffer->getRect()->ymin); minx = max(minx, inputBuffer->getRect()->xmin); - maxy = min(maxy, inputBuffer->getRect()->ymax); - maxx = min(maxx, inputBuffer->getRect()->xmax); + // maxy = min(maxy, inputBuffer->getRect()->ymax); + maxx = min(maxx, inputBuffer->getRect()->xmax - 1); int step = getStep(); int offsetadd = getOffsetAdd(); int bufferindex = ((minx - bufferstartx) * 4) + ((miny - bufferstarty) * 4 * bufferwidth); - for (int nx = minx, index = (minx - x) + this->m_rad; nx < maxx; nx += step, index += step) { + for (int nx = minx, index = (minx - x) + this->m_rad; nx <= maxx; nx += step, index += step) { const float multiplier = this->m_gausstab[index]; madd_v4_v4fl(color_accum, &buffer[bufferindex], multiplier); multiplier_accum += multiplier; @@ -108,8 +108,10 @@ void GaussianXBlurOperation::executePixel(float output[4], int x, int y, void *d void GaussianXBlurOperation::deinitExecution() { BlurBaseOperation::deinitExecution(); - MEM_freeN(this->m_gausstab); - this->m_gausstab = NULL; + if (this->m_gausstab) { + MEM_freeN(this->m_gausstab); + this->m_gausstab = NULL; + } deinitMutex(); } diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp index 192bc29e1ae..0c0a4d8aa4f 100644 --- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp @@ -87,16 +87,16 @@ void GaussianYBlurOperation::executePixel(float output[4], int x, int y, void *d int miny = y - this->m_rad; int maxy = y + this->m_rad; int minx = x; - int maxx = x; + // int maxx = x; // UNUSED miny = max(miny, inputBuffer->getRect()->ymin); minx = max(minx, inputBuffer->getRect()->xmin); - maxy = min(maxy, inputBuffer->getRect()->ymax); - maxx = min(maxx, inputBuffer->getRect()->xmax); + maxy = min(maxy, inputBuffer->getRect()->ymax - 1); + // maxx = min(maxx, inputBuffer->getRect()->xmax); int index; int step = getStep(); - const int bufferIndexx = ((minx - bufferstartx) * 4) ; - for (int ny = miny; ny < maxy; ny += step) { + const int bufferIndexx = ((minx - bufferstartx) * 4); + for (int ny = miny; ny <= maxy; ny += step) { index = (ny - y) + this->m_rad; int bufferindex = bufferIndexx + ((ny - bufferstarty) * 4 * bufferwidth); const float multiplier = this->m_gausstab[index]; @@ -109,8 +109,10 @@ void GaussianYBlurOperation::executePixel(float output[4], int x, int y, void *d void GaussianYBlurOperation::deinitExecution() { BlurBaseOperation::deinitExecution(); - MEM_freeN(this->m_gausstab); - this->m_gausstab = NULL; + if (this->m_gausstab) { + MEM_freeN(this->m_gausstab); + this->m_gausstab = NULL; + } deinitMutex(); } diff --git a/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp b/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp index 7f7429bf2e6..592ad114113 100644 --- a/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp @@ -86,8 +86,8 @@ static void FHT(fREAL *data, unsigned int M, unsigned int inverse) fREAL *data_nbd = &data_n[bd]; fREAL *data_bd = &data[bd]; for (k = bl; k < len; k += istep) { - t1 = fc * data_n[k] + fs * data_nbd[k]; - t2 = fs * data_n[k] - fc * data_nbd[k]; + t1 = fc * (double)data_n[k] + fs * (double)data_nbd[k]; + t2 = fs * (double)data_n[k] - fc * (double)data_nbd[k]; data_n[k] = data[k] - t1; data_nbd[k] = data_bd[k] - t2; data[k] += t1; @@ -244,7 +244,7 @@ static void fht_convolve(fREAL *d1, fREAL *d2, unsigned int M, unsigned int N) } //------------------------------------------------------------------------------ -void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2) +static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2) { fREAL *data1, *data2, *fp; unsigned int w2, h2, hw, hh, log2_w, log2_h; @@ -395,7 +395,7 @@ void GlareFogGlowOperation::generateGlare(float *data, MemoryBuffer *inputTile, // linear window good enough here, visual result counts, not scientific analysis //w = (1.f-fabs(u))*(1.f-fabs(v)); // actually, Hanning window is ok, cos^2 for some reason is slower - w = (0.5f + 0.5f * cos((double)u * M_PI)) * (0.5f + 0.5f * cos((double)v * M_PI)); + w = (0.5f + 0.5f * cosf(u * (float)M_PI)) * (0.5f + 0.5f * cosf(v * (float)M_PI)); mul_v3_fl(fcol, w); ckrn->writePixel(x, y, fcol); } diff --git a/source/blender/compositor/operations/COM_GlareGhostOperation.cpp b/source/blender/compositor/operations/COM_GlareGhostOperation.cpp index ace04237b29..c4f8b3a0ddb 100644 --- a/source/blender/compositor/operations/COM_GlareGhostOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareGhostOperation.cpp @@ -79,9 +79,9 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No sc = 2.13; isc = -0.97; for (y = 0; y < gbuf->getHeight() && (!breaked); y++) { - v = (float)(y + 0.5f) / (float)gbuf->getHeight(); + v = ((float)y + 0.5f) / (float)gbuf->getHeight(); for (x = 0; x < gbuf->getWidth(); x++) { - u = (float)(x + 0.5f) / (float)gbuf->getWidth(); + u = ((float)x + 0.5f) / (float)gbuf->getWidth(); s = (u - 0.5f) * sc + 0.5f, t = (v - 0.5f) * sc + 0.5f; tbuf1->readCubic(c, s * gbuf->getWidth(), t * gbuf->getHeight()); sm = smoothMask(s, t); @@ -100,9 +100,9 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No memset(tbuf1->getBuffer(), 0, tbuf1->getWidth() * tbuf1->getHeight() * COM_NUMBER_OF_CHANNELS * sizeof(float)); for (n = 1; n < settings->iter && (!breaked); n++) { for (y = 0; y < gbuf->getHeight() && (!breaked); y++) { - v = (float)(y + 0.5f) / (float)gbuf->getHeight(); + v = ((float)y + 0.5f) / (float)gbuf->getHeight(); for (x = 0; x < gbuf->getWidth(); x++) { - u = (float)(x + 0.5f) / (float)gbuf->getWidth(); + u = ((float)x + 0.5f) / (float)gbuf->getWidth(); tc[0] = tc[1] = tc[2] = 0.f; for (p = 0; p < 4; p++) { np = (n << 2) + p; diff --git a/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp b/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp index 9125783c222..60d37fb8145 100644 --- a/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp @@ -81,11 +81,9 @@ void GlareStreaksOperation::generateGlare(float *data, MemoryBuffer *inputTile, float *sourcebuffer = tsrc->getBuffer(); float factor = 1.f / (float)(6 - settings->iter); - for (int i = 0; i < size4; i++) { - data[i] += sourcebuffer[i] * factor; - } - for (int i = 0; i < size; i++) { - data[i * 4 + 3] = 1.0f; + for (int i = 0; i < size4; i += 4) { + madd_v3_v3fl(&data[i], &sourcebuffer[i], factor); + data[i + 3] = 1.0f; } tdst->clear(); diff --git a/source/blender/compositor/operations/COM_InpaintOperation.cpp b/source/blender/compositor/operations/COM_InpaintOperation.cpp index 70d4d987c81..81ca06cfff0 100644 --- a/source/blender/compositor/operations/COM_InpaintOperation.cpp +++ b/source/blender/compositor/operations/COM_InpaintOperation.cpp @@ -133,9 +133,9 @@ void InpaintSimpleOperation::calc_manhatten_distance() if (this->get_pixel(i, j)[3] < 1.0f) { r = width + height; if (i > 0) - r = mini(r, m[j * width + i - 1] + 1); + r = min_ii(r, m[j * width + i - 1] + 1); if (j > 0) - r = mini(r, m[(j - 1) * width + i] + 1); + r = min_ii(r, m[(j - 1) * width + i] + 1); } m[j * width + i] = r; } @@ -146,9 +146,9 @@ void InpaintSimpleOperation::calc_manhatten_distance() int r = m[j * width + i]; if (i + 1 < width) - r = mini(r, m[j * width + i + 1] + 1); + r = min_ii(r, m[j * width + i + 1] + 1); if (j + 1 < height) - r = mini(r, m[(j + 1) * width + i] + 1); + r = min_ii(r, m[(j + 1) * width + i] + 1); m[j * width + i] = r; diff --git a/source/blender/compositor/operations/COM_KeyingDespillOperation.cpp b/source/blender/compositor/operations/COM_KeyingDespillOperation.cpp index 4426666f100..01f5c032730 100644 --- a/source/blender/compositor/operations/COM_KeyingDespillOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingDespillOperation.cpp @@ -28,18 +28,6 @@ #include "BLI_listbase.h" #include "BLI_math.h" -static int get_pixel_primary_channel(float *pixel) -{ - float max_value = MAX3(pixel[0], pixel[1], pixel[2]); - - if (max_value == pixel[0]) - return 0; - else if (max_value == pixel[1]) - return 1; - - return 2; -} - KeyingDespillOperation::KeyingDespillOperation() : NodeOperation() { this->addInputSocket(COM_DT_COLOR); @@ -73,12 +61,12 @@ void KeyingDespillOperation::executePixel(float output[4], float x, float y, Pix this->m_pixelReader->read(pixelColor, x, y, sampler); this->m_screenReader->read(screenColor, x, y, sampler); - int screen_primary_channel = get_pixel_primary_channel(screenColor); - int other_1 = (screen_primary_channel + 1) % 3; - int other_2 = (screen_primary_channel + 2) % 3; + const int screen_primary_channel = max_axis_v3(screenColor); + const int other_1 = (screen_primary_channel + 1) % 3; + const int other_2 = (screen_primary_channel + 2) % 3; - int min_channel = MIN2(other_1, other_2); - int max_channel = MAX2(other_1, other_2); + const int min_channel = min(other_1, other_2); + const int max_channel = max(other_1, other_2); float average_value, amount; @@ -87,7 +75,8 @@ void KeyingDespillOperation::executePixel(float output[4], float x, float y, Pix copy_v4_v4(output, pixelColor); - if (this->m_despillFactor * amount > 0) { - output[screen_primary_channel] = pixelColor[screen_primary_channel] - this->m_despillFactor * amount; + const float amount_despill = this->m_despillFactor * amount; + if (amount_despill > 0.0f) { + output[screen_primary_channel] = pixelColor[screen_primary_channel] - amount_despill; } } diff --git a/source/blender/compositor/operations/COM_KeyingOperation.cpp b/source/blender/compositor/operations/COM_KeyingOperation.cpp index 35138cf0b92..baeacb56744 100644 --- a/source/blender/compositor/operations/COM_KeyingOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingOperation.cpp @@ -28,27 +28,15 @@ #include "BLI_listbase.h" #include "BLI_math.h" -static int get_pixel_primary_channel(float pixelColor[4]) +static float get_pixel_saturation(const float pixelColor[4], float screen_balance, int primary_channel) { - float max_value = MAX3(pixelColor[0], pixelColor[1], pixelColor[2]); + const int other_1 = (primary_channel + 1) % 3; + const int other_2 = (primary_channel + 2) % 3; - if (max_value == pixelColor[0]) - return 0; - else if (max_value == pixelColor[1]) - return 1; + const int min_channel = min(other_1, other_2); + const int max_channel = max(other_1, other_2); - return 2; -} - -static float get_pixel_saturation(float pixelColor[4], float screen_balance, int primary_channel) -{ - int other_1 = (primary_channel + 1) % 3; - int other_2 = (primary_channel + 2) % 3; - - int min_channel = MIN2(other_1, other_2); - int max_channel = MAX2(other_1, other_2); - - float val = screen_balance * pixelColor[min_channel] + (1.0f - screen_balance) * pixelColor[max_channel]; + const float val = screen_balance * pixelColor[min_channel] + (1.0f - screen_balance) * pixelColor[max_channel]; return (pixelColor[primary_channel] - val) * fabsf(1.0f - val); } @@ -85,13 +73,13 @@ void KeyingOperation::executePixel(float output[4], float x, float y, PixelSampl this->m_pixelReader->read(pixelColor, x, y, sampler); this->m_screenReader->read(screenColor, x, y, sampler); - int primary_channel = get_pixel_primary_channel(screenColor); + const int primary_channel = max_axis_v3(screenColor); if (pixelColor[primary_channel] > 1.0f) { /* overexposure doesn't happen on screen itself and usually happens * on light sources in the shot, this need to be checked separately * because saturation and falloff calculation is based on the fact - * that pixels are not overexposured + * that pixels are not overexposed */ output[0] = 1.0f; } diff --git a/source/blender/compositor/operations/COM_MapUVOperation.cpp b/source/blender/compositor/operations/COM_MapUVOperation.cpp index fe6ebcebf97..1fa484ea2b6 100644 --- a/source/blender/compositor/operations/COM_MapUVOperation.cpp +++ b/source/blender/compositor/operations/COM_MapUVOperation.cpp @@ -24,7 +24,7 @@ MapUVOperation::MapUVOperation() : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); this->addInputSocket(COM_DT_VECTOR); this->addOutputSocket(COM_DT_COLOR); this->m_alpha = 0.0f; diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp index 36b3f2023ae..ba1059c4eb5 100644 --- a/source/blender/compositor/operations/COM_MaskOperation.cpp +++ b/source/blender/compositor/operations/COM_MaskOperation.cpp @@ -73,7 +73,7 @@ void MaskOperation::initExecution() for (masklay = (MaskLayer *)mask_temp->masklayers.first; masklay; - masklay = (MaskLayer *)masklay->next) + masklay = masklay->next) { masklay_shape = BKE_mask_layer_shape_varify_frame(masklay, this->m_frame_number); BKE_mask_layer_shape_from_mask(masklay, masklay_shape); diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.h b/source/blender/compositor/operations/COM_MathBaseOperation.h index b492d06a697..febfa9662c6 100644 --- a/source/blender/compositor/operations/COM_MathBaseOperation.h +++ b/source/blender/compositor/operations/COM_MathBaseOperation.h @@ -45,7 +45,7 @@ protected: */ MathBaseOperation(); - void clampIfNeeded(float *color); + void clampIfNeeded(float color[4]); public: /** * the inner loop of this program diff --git a/source/blender/compositor/operations/COM_MixBaseOperation.h b/source/blender/compositor/operations/COM_MixBaseOperation.h index 4b466d193d6..88d1d00c2bf 100644 --- a/source/blender/compositor/operations/COM_MixBaseOperation.h +++ b/source/blender/compositor/operations/COM_MixBaseOperation.h @@ -40,7 +40,7 @@ protected: bool m_valueAlphaMultiply; bool m_useClamp; - inline void clampIfNeeded(float *color) + inline void clampIfNeeded(float color[4]) { if (m_useClamp) { CLAMP(color[0], 0.0f, 1.0f); diff --git a/source/blender/compositor/operations/COM_MixColorOperation.cpp b/source/blender/compositor/operations/COM_MixColorOperation.cpp index f8aca92abc7..56aca27eaef 100644 --- a/source/blender/compositor/operations/COM_MixColorOperation.cpp +++ b/source/blender/compositor/operations/COM_MixColorOperation.cpp @@ -53,9 +53,12 @@ void MixColorOperation::executePixel(float output[4], float x, float y, PixelSam float tmpr, tmpg, tmpb; rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV); hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb); - output[0] = valuem * (inputColor1[0]) + value * tmpr; - output[1] = valuem * (inputColor1[1]) + value * tmpg; - output[2] = valuem * (inputColor1[2]) + value * tmpb; + output[0] = (valuem * inputColor1[0]) + (value * tmpr); + output[1] = (valuem * inputColor1[1]) + (value * tmpg); + output[2] = (valuem * inputColor1[2]) + (value * tmpb); + } + else { + copy_v3_v3(output, inputColor1); } output[3] = inputColor1[3]; diff --git a/source/blender/compositor/operations/COM_MixGlareOperation.cpp b/source/blender/compositor/operations/COM_MixGlareOperation.cpp index b6a9aa3da3c..1c6555206da 100644 --- a/source/blender/compositor/operations/COM_MixGlareOperation.cpp +++ b/source/blender/compositor/operations/COM_MixGlareOperation.cpp @@ -40,9 +40,13 @@ void MixGlareOperation::executePixel(float output[4], float x, float y, PixelSam value = inputValue[0]; float mf = 2.f - 2.f * fabsf(value - 0.5f); - output[0] = mf * ((inputColor1[0]) + value * (inputColor2[0] - inputColor1[0])); - output[1] = mf * ((inputColor1[1]) + value * (inputColor2[1] - inputColor1[1])); - output[2] = mf * ((inputColor1[2]) + value * (inputColor2[2] - inputColor1[2])); + if (inputColor1[0] < 0.0f) inputColor1[0] = 0.0f; + if (inputColor1[1] < 0.0f) inputColor1[1] = 0.0f; + if (inputColor1[2] < 0.0f) inputColor1[2] = 0.0f; + + output[0] = mf * max(inputColor1[0] + value * (inputColor2[0] - inputColor1[0]), 0.0f); + output[1] = mf * max(inputColor1[1] + value * (inputColor2[1] - inputColor1[1]), 0.0f); + output[2] = mf * max(inputColor1[2] + value * (inputColor2[2] - inputColor1[2]), 0.0f); output[3] = inputColor1[3]; clampIfNeeded(output); diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp index a3e00e9325b..df48c7a6716 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp @@ -33,8 +33,7 @@ vector s_cache; void deintializeDistortionCache(void) { - while (s_cache.size()>0) - { + while (s_cache.size() > 0) { DistortionCache * cache = s_cache.back(); s_cache.pop_back(); delete cache; @@ -61,8 +60,7 @@ void MovieDistortionOperation::initExecution() BKE_movieclip_user_set_frame(&clipUser, this->m_framenumber); BKE_movieclip_get_size(this->m_movieClip, &clipUser, &calibration_width, &calibration_height); - for (unsigned int i = 0; i < s_cache.size(); i++) - { + for (unsigned int i = 0; i < s_cache.size(); i++) { DistortionCache *c = (DistortionCache *)s_cache[i]; if (c->isCacheFor(this->m_movieClip, this->m_width, this->m_height, calibration_width, calibration_height, this->m_distortion)) @@ -86,15 +84,12 @@ void MovieDistortionOperation::deinitExecution() { this->m_inputOperation = NULL; this->m_movieClip = NULL; - while (s_cache.size() > COM_DISTORTIONCACHE_MAXSIZE) - { + while (s_cache.size() > COM_DISTORTIONCACHE_MAXSIZE) { double minTime = PIL_check_seconds_timer(); vector::iterator minTimeIterator = s_cache.begin(); - for (vector::iterator it = s_cache.begin(); it < s_cache.end(); it ++) - { + for (vector::iterator it = s_cache.begin(); it < s_cache.end(); it ++) { DistortionCache * cache = *it; - if (cache->getTimeLastUsage()getTimeLastUsage() < minTime) { minTime = cache->getTimeLastUsage(); minTimeIterator = it; } @@ -111,7 +106,7 @@ void MovieDistortionOperation::executePixel(float output[4], float x, float y, P float u, v; this->m_cache->getUV(&this->m_movieClip->tracking, x, y, &u, &v); this->m_inputOperation->read(output, u, v, sampler); - } + } else { this->m_inputOperation->read(output, x, y, sampler); } diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.h b/source/blender/compositor/operations/COM_MovieDistortionOperation.h index f3eeb2f48ba..93cc555fdbc 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.h +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.h @@ -115,10 +115,10 @@ public: if (!this->m_bufferCalculated[offset]) { //float overscan = 0.0f; - float w = (float)this->m_width /* / (1 + overscan) */; - float h = (float)this->m_height /* / (1 + overscan) */; - float aspx = (float)w / this->m_calibration_width; - float aspy = (float)h / this->m_calibration_height; + const float w = (float)this->m_width /* / (1 + overscan) */; + const float h = (float)this->m_height /* / (1 + overscan) */; + const float aspx = w / (float)this->m_calibration_width; + const float aspy = h / (float)this->m_calibration_height; float in[2]; float out[2]; diff --git a/source/blender/compositor/operations/COM_OpenCLKernels.cl b/source/blender/compositor/operations/COM_OpenCLKernels.cl index 4d366a864c4..36205bb94cc 100644 --- a/source/blender/compositor/operations/COM_OpenCLKernels.cl +++ b/source/blender/compositor/operations/COM_OpenCLKernels.cl @@ -33,7 +33,7 @@ __kernel void bokehBlurKernel(__read_only image2d_t boundingBox, __read_only ima __read_only image2d_t bokehImage, __write_only image2d_t output, int2 offsetInput, int2 offsetOutput, int radius, int step, int2 dimension, int2 offset) { - int2 coords = {get_global_id(0), get_global_id(1)}; + int2 coords = {get_global_id(0), get_global_id(1)}; coords += offset; float tempBoundingBox; float4 color = {0.0f,0.0f,0.0f,0.0f}; @@ -54,10 +54,10 @@ __kernel void bokehBlurKernel(__read_only image2d_t boundingBox, __read_only ima float2 uv; int2 inputXy; - for (ny = minXY.y, inputXy.y = ny - offsetInput.y ; ny < maxXY.y ; ny +=step, inputXy.y+=step) { + for (ny = minXY.y, inputXy.y = ny - offsetInput.y ; ny < maxXY.y ; ny += step, inputXy.y += step) { uv.y = ((realCoordinate.y-ny)/radius2)*bokehImageDim.y+bokehImageCenter.y; - for (nx = minXY.x, inputXy.x = nx - offsetInput.x; nx < maxXY.x ; nx +=step, inputXy.x+=step) { + for (nx = minXY.x, inputXy.x = nx - offsetInput.x; nx < maxXY.x ; nx += step, inputXy.x += step) { uv.x = ((realCoordinate.x-nx)/radius2)*bokehImageDim.x+bokehImageCenter.x; bokeh = read_imagef(bokehImage, SAMPLER_NEAREST, uv); color += bokeh * read_imagef(inputImage, SAMPLER_NEAREST, inputXy); @@ -124,7 +124,7 @@ __kernel void defocusKernel(__read_only image2d_t inputImage, __read_only image2 } } } - } + } } color = color_accum * (1.0f / multiplier_accum); @@ -148,7 +148,7 @@ __kernel void dilateKernel(__read_only image2d_t inputImage, __write_only image int2 offsetInput, int2 offsetOutput, int scope, int distanceSquared, int2 dimension, int2 offset) { - int2 coords = {get_global_id(0), get_global_id(1)}; + int2 coords = {get_global_id(0), get_global_id(1)}; coords += offset; const int2 realCoordinate = coords + offsetOutput; @@ -179,7 +179,7 @@ __kernel void erodeKernel(__read_only image2d_t inputImage, __write_only image2 int2 offsetInput, int2 offsetOutput, int scope, int distanceSquared, int2 dimension, int2 offset) { - int2 coords = {get_global_id(0), get_global_id(1)}; + int2 coords = {get_global_id(0), get_global_id(1)}; coords += offset; const int2 realCoordinate = coords + offsetOutput; @@ -210,7 +210,7 @@ __kernel void directionalBlurKernel(__read_only image2d_t inputImage, __write_o int2 offsetOutput, int iterations, float scale, float rotation, float2 translate, float2 center, int2 offset) { - int2 coords = {get_global_id(0), get_global_id(1)}; + int2 coords = {get_global_id(0), get_global_id(1)}; coords += offset; const int2 realCoordinate = coords + offsetOutput; diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp index 21ecfdb5272..7d05202df96 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.cpp +++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp @@ -94,8 +94,8 @@ static void write_buffer_rect(rcti *rect, const bNodeTree *tree, OutputSingleLayerOperation::OutputSingleLayerOperation( - const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path, - const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings) + const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path, + const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings) { this->m_rd = rd; this->m_tree = tree; @@ -129,7 +129,7 @@ void OutputSingleLayerOperation::deinitExecution() if (this->getWidth() * this->getHeight() != 0) { int size = get_datatype_size(this->m_datatype); - ImBuf *ibuf = IMB_allocImBuf(this->getWidth(), this->getHeight(), size * 8, 0); + ImBuf *ibuf = IMB_allocImBuf(this->getWidth(), this->getHeight(), this->m_format->planes, 0); Main *bmain = G.main; /* TODO, have this passed along */ char filename[FILE_MAX]; @@ -138,8 +138,9 @@ void OutputSingleLayerOperation::deinitExecution() ibuf->mall |= IB_rectfloat; ibuf->dither = this->m_rd->dither_intensity; - IMB_display_buffer_to_imbuf_rect(ibuf, m_viewSettings, m_displaySettings); - + IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, m_viewSettings, m_displaySettings, + this->m_format); + BKE_makepicstring(filename, this->m_path, bmain->name, this->m_rd->cfra, this->m_format->imtype, (this->m_rd->scemode & R_EXTENSION), true); @@ -148,7 +149,7 @@ void OutputSingleLayerOperation::deinitExecution() else printf("Saved: %s\n", filename); - IMB_freeImBuf(ibuf); + IMB_freeImBuf(ibuf); } this->m_outputBuffer = NULL; this->m_imageInput = NULL; diff --git a/source/blender/compositor/operations/COM_PixelateOperation.cpp b/source/blender/compositor/operations/COM_PixelateOperation.cpp new file mode 100644 index 00000000000..89e7f0093a1 --- /dev/null +++ b/source/blender/compositor/operations/COM_PixelateOperation.cpp @@ -0,0 +1,49 @@ +/* + * 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. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + */ + +#include "COM_PixelateOperation.h" + +PixelateOperation::PixelateOperation(DataType datatype) : NodeOperation() +{ + this->addInputSocket(datatype); + this->addOutputSocket(datatype); + this->setResolutionInputSocketIndex(0); + this->m_inputOperation = NULL; +} + +void PixelateOperation::initExecution() +{ + this->m_inputOperation = this->getInputSocketReader(0); +} + +void PixelateOperation::deinitExecution() +{ + this->m_inputOperation = NULL; +} + +void PixelateOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float nx = round(x); + float ny = round(y); + this->m_inputOperation->read(output, nx, ny, sampler); +} + diff --git a/source/blender/compositor/operations/COM_PixelateOperation.h b/source/blender/compositor/operations/COM_PixelateOperation.h new file mode 100644 index 00000000000..b16b21b2ec1 --- /dev/null +++ b/source/blender/compositor/operations/COM_PixelateOperation.h @@ -0,0 +1,68 @@ +/* + * 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. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + */ + +#ifndef _COM_PixelateOperation_h_ +#define _COM_PixelateOperation_h_ + +#include "COM_NodeOperation.h" + +/** + * @brief Pixelate operation + * + * The Tile compositor is by default sub-pixel accurate. + * For some setups you don want this. + * This operation will remove the sub-pixel accuracy + */ +class PixelateOperation : public NodeOperation { +private: + /** + * @brief cached refeerence to the input operation + */ + SocketReader *m_inputOperation; +public: + /** + * @brief PixelateOperation + * @param dataType the datatype to create this operator for (saves datatype conversions) + */ + PixelateOperation(DataType dataType); + + /** + * @brief initialization of the execution + */ + void initExecution(); + + /** + * @brief de-initialization of the execution + */ + void deinitExecution(); + + /** + * @brief executePixel + * @param output result + * @param x x-coordinate + * @param y y-coordinate + * @param sampler sampler + */ + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +#endif diff --git a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp index d92fe04eb15..5cc02a1ed65 100644 --- a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp @@ -81,7 +81,7 @@ bool ProjectorLensDistortionOperation::determineDependingAreaOfInterest(rcti *in } else { rcti dispInput; - BLI_rcti_init(&dispInput, 0,5,0,5); + BLI_rcti_init(&dispInput, 0, 5, 0, 5); if (this->getInputOperation(1)->determineDependingAreaOfInterest(&dispInput, readOperation, output)) { return true; } @@ -104,7 +104,7 @@ void ProjectorLensDistortionOperation::updateDispersion() float result[4]; this->getInputSocketReader(1)->read(result, 1, 1, COM_PS_NEAREST); this->m_dispersion = result[0]; - this->m_kr = 0.25f * maxf(minf(this->m_dispersion, 1.0f), 0.0f); + this->m_kr = 0.25f * max_ff(min_ff(this->m_dispersion, 1.0f), 0.0f); this->m_kr2 = this->m_kr * 20; this->m_dispersionAvailable = true; } diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp index 193ab669f40..d2c6c833e2e 100644 --- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp @@ -98,7 +98,7 @@ void ScreenLensDistortionOperation::executePixel(float output[4], int x, int y, const float sd = 1.0f / (float)ds; for (z = 0; z < ds; ++z) { - const float tz = ((float)z + (jit ? BLI_frand() : 0.5f)) * sd; + const float tz = (z + (jit ? BLI_frand() : 0.5f)) * sd; t = 1.0f - (this->m_kr4 + tz * this->m_drg) * uv_dot; d = 1.0f / (1.0f + sqrtf(t)); const float nx = (u * d + 0.5f) * width - 0.5f; @@ -116,7 +116,7 @@ void ScreenLensDistortionOperation::executePixel(float output[4], int x, int y, const float sd = 1.0f / (float)ds; for (z = 0; z < ds; ++z) { - const float tz = ((float)z + (jit ? BLI_frand() : 0.5f)) * sd; + const float tz = (z + (jit ? BLI_frand() : 0.5f)) * sd; t = 1.0f - (this->m_kg4 + tz * this->m_dgb) * uv_dot; d = 1.0f / (1.0f + sqrtf(t)); const float nx = (u * d + 0.5f) * width - 0.5f; @@ -226,7 +226,7 @@ bool ScreenLensDistortionOperation::determineDependingAreaOfInterest(rcti *input UPDATE_INPUT; determineUV(coords, input->xmax, input->ymin); UPDATE_INPUT; - } + } else { determineUV(coords, input->xmin, input->ymin, 1.0f, 1.0f); newInput.xmin = coords[0]; @@ -268,11 +268,11 @@ bool ScreenLensDistortionOperation::determineDependingAreaOfInterest(rcti *input void ScreenLensDistortionOperation::updateVariables(float distortion, float dispersion) { - this->m_kg = maxf(minf(distortion, 1.0f), -0.999f); + this->m_kg = max_ff(min_ff(distortion, 1.0f), -0.999f); // smaller dispersion range for somewhat more control - const float d = 0.25f * maxf(minf(dispersion, 1.0f), 0.0f); - this->m_kr = maxf(minf((this->m_kg + d), 1.0f), -0.999f); - this->m_kb = maxf(minf((this->m_kg - d), 1.0f), -0.999f); + const float d = 0.25f * max_ff(min_ff(dispersion, 1.0f), 0.0f); + this->m_kr = max_ff(min_ff((this->m_kg + d), 1.0f), -0.999f); + this->m_kb = max_ff(min_ff((this->m_kg - d), 1.0f), -0.999f); this->m_maxk = MAX3(this->m_kr, this->m_kg, this->m_kb); this->m_sc = (this->m_data->fit && (this->m_maxk > 0.0f)) ? (1.0f / (1.0f + 2.0f * this->m_maxk)) : (1.0f / (1.0f + this->m_maxk)); diff --git a/source/blender/compositor/operations/COM_TrackPositionOperation.h b/source/blender/compositor/operations/COM_TrackPositionOperation.h index 3a9e6f25cd9..b934719a92b 100644 --- a/source/blender/compositor/operations/COM_TrackPositionOperation.h +++ b/source/blender/compositor/operations/COM_TrackPositionOperation.h @@ -35,8 +35,8 @@ #include "BLI_listbase.h" /** - * Class with implementation of green screen gradient rasterization - */ + * Class with implementation of green screen gradient rasterization + */ class TrackPositionOperation : public NodeOperation { protected: enum { @@ -58,8 +58,8 @@ protected: float m_relativePos[2]; /** - * Determine the output resolution. The resolution is retrieved from the Renderer - */ + * Determine the output resolution. The resolution is retrieved from the Renderer + */ void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); public: diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp index 7ccc91072bc..61720c7676d 100644 --- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp @@ -118,7 +118,7 @@ void VariableSizeBokehBlurOperation::executePixel(float output[4], int x, int y, #ifdef COM_DEFOCUS_SEARCH float search[4]; - this->m_inputSearchProgram->read(search, x/InverseSearchRadiusOperation::DIVIDER, y / InverseSearchRadiusOperation::DIVIDER, NULL); + this->m_inputSearchProgram->read(search, x / InverseSearchRadiusOperation::DIVIDER, y / InverseSearchRadiusOperation::DIVIDER, NULL); int minx = search[0]; int miny = search[1]; int maxx = search[2]; @@ -192,13 +192,13 @@ void VariableSizeBokehBlurOperation::executeOpenCL(OpenCLDevice *device, cl_int maxBlur; cl_float threshold = this->m_threshold; - MemoryBuffer *sizeMemoryBuffer = (MemoryBuffer *)this->m_inputSizeProgram->getInputMemoryBuffer(inputMemoryBuffers); + MemoryBuffer *sizeMemoryBuffer = this->m_inputSizeProgram->getInputMemoryBuffer(inputMemoryBuffers); const float max_dim = max(m_width, m_height); cl_float scalar = this->m_do_size_scale ? (max_dim / 100.0f) : 1.0f; maxBlur = (cl_int)sizeMemoryBuffer->getMaximumValue() * scalar; - maxBlur = MIN2(maxBlur, this->m_maxBlur); + maxBlur = min(maxBlur, this->m_maxBlur); device->COM_clAttachMemoryBufferToKernelParameter(defocusKernel, 0, -1, clMemToCleanUp, inputMemoryBuffers, this->m_inputProgram); device->COM_clAttachMemoryBufferToKernelParameter(defocusKernel, 1, -1, clMemToCleanUp, inputMemoryBuffers, this->m_inputBokehProgram); @@ -298,9 +298,9 @@ voi *InverseSearchRadiusOperation::initializeTileData(rcti *rect) int rx = x * DIVIDER; int ry = y * DIVIDER; buffer[offset] = MAX2(rx - m_maxBlur, 0); - buffer[offset+1] = MAX2(ry- m_maxBlur, 0); - buffer[offset+2] = MIN2(rx+DIVIDER + m_maxBlur, width); - buffer[offset+3] = MIN2(ry+DIVIDER + m_maxBlur, height); + buffer[offset + 1] = MAX2(ry - m_maxBlur, 0); + buffer[offset + 2] = MIN2(rx + DIVIDER + m_maxBlur, width); + buffer[offset + 3] = MIN2(ry + DIVIDER + m_maxBlur, height); offset += 4; } } diff --git a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp index d9ca131721f..4d4c1199f3e 100644 --- a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp @@ -79,8 +79,7 @@ void ViewerBaseOperation::initImage() BLI_unlock_thread(LOCK_DRAW_IMAGE); } - if (m_doDepthBuffer) - { + if (m_doDepthBuffer) { addzbuffloatImBuf(ibuf); } BLI_unlock_thread(LOCK_DRAW_IMAGE); @@ -96,8 +95,7 @@ void ViewerBaseOperation::initImage() */ this->m_ibuf = ibuf; - if (m_doDepthBuffer) - { + if (m_doDepthBuffer) { this->m_depthBuffer = ibuf->zbuf_float; } @@ -107,7 +105,7 @@ void ViewerBaseOperation:: updateImage(rcti *rect) { IMB_partial_display_buffer_update(this->m_ibuf, this->m_outputBuffer, NULL, getWidth(), 0, 0, this->m_viewSettings, this->m_displaySettings, - rect->xmin, rect->ymin, rect->xmax, rect->ymax); + rect->xmin, rect->ymin, rect->xmax, rect->ymax, FALSE); WM_main_add_notifier(NC_WINDOW | ND_DRAW, NULL); } diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cpp b/source/blender/compositor/operations/COM_ViewerOperation.cpp index 576d5da4d74..d1ac7d74ead 100644 --- a/source/blender/compositor/operations/COM_ViewerOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerOperation.cpp @@ -96,7 +96,7 @@ void ViewerOperation::executeRegion(rcti *rect, unsigned int tileNumber) if (m_depthInput) { this->m_depthInput->read(depth, x, y, COM_PS_NEAREST); depthbuffer[offset] = depth[0]; - } + } offset ++; offset4 += 4; diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp index 273c10b60ac..17c8f4d9fd1 100644 --- a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp +++ b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp @@ -110,7 +110,8 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber) memoryBuffer->setCreatedState(); } -void WriteBufferOperation::executeOpenCLRegion(OpenCLDevice *device, rcti *rect, unsigned int chunkNumber, MemoryBuffer **inputMemoryBuffers, MemoryBuffer *outputBuffer) +void WriteBufferOperation::executeOpenCLRegion(OpenCLDevice *device, rcti *rect, unsigned int chunkNumber, + MemoryBuffer **inputMemoryBuffers, MemoryBuffer *outputBuffer) { float *outputFloatBuffer = outputBuffer->getBuffer(); cl_int error; diff --git a/source/blender/compositor/operations/COM_ZCombineOperation.cpp b/source/blender/compositor/operations/COM_ZCombineOperation.cpp index 7e23e7290f8..5e4f90b0269 100644 --- a/source/blender/compositor/operations/COM_ZCombineOperation.cpp +++ b/source/blender/compositor/operations/COM_ZCombineOperation.cpp @@ -69,7 +69,7 @@ void ZCombineAlphaOperation::executePixel(float output[4], float x, float y, Pix this->m_depth1Reader->read(depth1, x, y, sampler); this->m_depth2Reader->read(depth2, x, y, sampler); - if (depth1[0] < depth2[0]) { + if (depth1[0] <= depth2[0]) { this->m_image1Reader->read(color1, x, y, sampler); this->m_image2Reader->read(color2, x, y, sampler); } @@ -79,10 +79,10 @@ void ZCombineAlphaOperation::executePixel(float output[4], float x, float y, Pix } float fac = color1[3]; float ifac = 1.0f - fac; - output[0] = color1[0] + ifac * color2[0]; - output[1] = color1[1] + ifac * color2[1]; - output[2] = color1[2] + ifac * color2[2]; - output[3] = MAX2(color1[3], color2[3]); + output[0] = fac * color1[0] + ifac * color2[0]; + output[1] = fac * color1[1] + ifac * color2[1]; + output[2] = fac * color1[2] + ifac * color2[2]; + output[3] = max(color1[3], color2[3]); } void ZCombineOperation::deinitExecution() diff --git a/source/blender/datatoc/datatoc.c b/source/blender/datatoc/datatoc.c index a7da037ff16..379658bb4c4 100644 --- a/source/blender/datatoc/datatoc.c +++ b/source/blender/datatoc/datatoc.c @@ -49,7 +49,6 @@ static char *basename(char *string) int main(int argc, char **argv) { FILE *fpin, *fpout; - char sizest[256]; long size; int i; @@ -79,8 +78,6 @@ int main(int argc, char **argv) for (i = 0; i < (int)strlen(argv[1]); i++) if (argv[1][i] == '.') argv[1][i] = '_'; - sprintf(sizest, "%d", (int)size); - fpout = fopen(argv[2], "w"); if (!fpout) { fprintf(stderr, "Unable to open output <%s>\n", argv[2]); @@ -88,7 +85,7 @@ int main(int argc, char **argv) } fprintf(fpout, "/* DataToC output of file <%s> */\n\n", argv[1]); - fprintf(fpout, "int datatoc_%s_size = %s;\n", argv[1], sizest); + fprintf(fpout, "int datatoc_%s_size = %d;\n", argv[1], (int)size); fprintf(fpout, "char datatoc_%s[] = {\n", argv[1]); while (size--) { /* if we want to open in an editor diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 86f729502bb..9ceecd60bef 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -84,6 +84,7 @@ /* size of indent steps */ #define INDENT_STEP_SIZE 7 +/* size of string buffers used for animation channel displayed names */ #define ANIM_CHAN_NAME_SIZE 256 /* get the pointer used for some flag */ @@ -292,7 +293,7 @@ static short acf_nodetree_rootType_offset(bNodeTree *ntree) } } - // unknown + /* unknown */ return 0; } @@ -422,7 +423,7 @@ static void acf_summary_name(bAnimListElem *UNUSED(ale), char *name) BLI_strncpy(name, "DopeSheet Summary", ANIM_CHAN_NAME_SIZE); } -// TODO: this is really a temp icon I think +// FIXME: this is really a temp icon I think static int acf_summary_icon(bAnimListElem *UNUSED(ale)) { return ICON_BORDERMOVE; @@ -601,7 +602,6 @@ static int acf_object_icon(bAnimListElem *ale) Object *ob = base->object; /* icon depends on object-type */ - switch (ob->type) { case OB_LAMP: return ICON_OUTLINER_OB_LAMP; @@ -628,7 +628,6 @@ static int acf_object_icon(bAnimListElem *ale) default: return ICON_OBJECT_DATA; } - } /* name for object */ @@ -753,7 +752,7 @@ static void acf_group_color(bAnimContext *ac, bAnimListElem *ale, float r_color[ /* highlight only for active */ if (ale->flag & AGRP_ACTIVE) - copy_v3_v3_char((char *)cp, agrp->cs.active); + copy_v3_v3_char((char *)cp, agrp->cs.select); else copy_v3_v3_char((char *)cp, agrp->cs.solid); @@ -1187,7 +1186,7 @@ static void *acf_dsmat_setting_ptr(bAnimListElem *ale, int setting, short *type) if (ma->adt) return GET_ACF_FLAG_PTR(ma->adt->flag, type); else - return NULL; + return NULL; default: /* unsupported */ return NULL; @@ -1264,7 +1263,7 @@ static void *acf_dslam_setting_ptr(bAnimListElem *ale, int setting, short *type) if (la->adt) return GET_ACF_FLAG_PTR(la->adt->flag, type); else - return NULL; + return NULL; default: /* unsupported */ return NULL; @@ -1348,7 +1347,7 @@ static void *acf_dstex_setting_ptr(bAnimListElem *ale, int setting, short *type) if (tex->adt) return GET_ACF_FLAG_PTR(tex->adt->flag, type); else - return NULL; + return NULL; default: /* unsupported */ return NULL; @@ -2178,7 +2177,7 @@ static int acf_dsspk_setting_flag(bAnimContext *UNUSED(ac), int setting, short * { /* clear extra return data first */ *neg = 0; - + switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ return SPK_DS_EXPAND; @@ -2202,10 +2201,10 @@ static int acf_dsspk_setting_flag(bAnimContext *UNUSED(ac), int setting, short * static void *acf_dsspk_setting_ptr(bAnimListElem *ale, int setting, short *type) { Speaker *spk = (Speaker *)ale->data; - + /* clear extra return data first */ *type = 0; - + switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ return GET_ACF_FLAG_PTR(spk->flag, type); @@ -2477,7 +2476,7 @@ static int acf_gpl_setting_flag(bAnimContext *UNUSED(ac), int setting, short *ne return GP_LAYER_HIDE; case ACHANNEL_SETTING_PROTECT: /* protected */ - // *neg = 1; - if we change this to edtiability + // *neg = 1; - if we change this to editability return GP_LAYER_LOCKED; default: /* unsupported */ @@ -2526,7 +2525,7 @@ static void acf_mask_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), // TODO: just get this from RNA? static int acf_mask_icon(bAnimListElem *UNUSED(ale)) { - return ICON_GREASEPENCIL; // MASK_TODO - need real icon + return ICON_MOD_MASK; } /* check if some setting exists for this channel */ @@ -2573,15 +2572,15 @@ static void *acf_mask_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short /* mask datablock type define */ static bAnimChannelType ACF_MASKDATA = { - "Mask Datablock", /* type name */ + "Mask Datablock", /* type name */ acf_mask_color, /* backdrop color */ - acf_group_backdrop, /* backdrop */ - acf_generic_indention_0, /* indent level */ - acf_generic_group_offset, /* offset */ + acf_group_backdrop, /* backdrop */ + acf_generic_indention_0, /* indent level */ + acf_generic_group_offset, /* offset */ - acf_generic_idblock_name, /* name */ - acf_generic_idfill_nameprop, /* name prop */ + acf_generic_idblock_name, /* name */ + acf_generic_idfill_nameprop, /* name prop */ acf_mask_icon, /* icon */ acf_mask_setting_valid, /* has setting */ @@ -2642,7 +2641,7 @@ static int acf_masklay_setting_flag(bAnimContext *UNUSED(ac), int setting, short // return GP_LAYER_HIDE; case ACHANNEL_SETTING_PROTECT: /* protected */ - // *neg = 1; - if we change this to edtiability + // *neg = 1; - if we change this to editability return MASK_LAYERFLAG_LOCKED; default: /* unsupported */ @@ -2654,7 +2653,7 @@ static int acf_masklay_setting_flag(bAnimContext *UNUSED(ac), int setting, short static void *acf_masklay_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type) { MaskLayer *masklay = (MaskLayer *)ale->data; - + /* all flags are just in agrp->flag for now... */ return GET_ACF_FLAG_PTR(masklay->flag, type); } @@ -2662,20 +2661,20 @@ static void *acf_masklay_setting_ptr(bAnimListElem *ale, int UNUSED(setting), sh /* grease pencil layer type define */ static bAnimChannelType ACF_MASKLAYER = { - "Mask Layer", /* type name */ - + "Mask Layer", /* type name */ + acf_generic_channel_color, /* backdrop color */ acf_generic_channel_backdrop, /* backdrop */ acf_generic_indention_flexible, /* indent level */ acf_generic_group_offset, /* offset */ - - acf_masklay_name, /* name */ - acf_masklay_name_prop, /* name prop */ + + acf_masklay_name, /* name */ + acf_masklay_name_prop, /* name prop */ NULL, /* icon */ - - acf_masklay_setting_valid, /* has setting */ - acf_masklay_setting_flag, /* flag for setting */ - acf_masklay_setting_ptr /* pointer for setting */ + + acf_masklay_setting_valid, /* has setting */ + acf_masklay_setting_flag, /* flag for setting */ + acf_masklay_setting_ptr /* pointer for setting */ }; @@ -2776,7 +2775,7 @@ void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level) acf->name(ale, name); else BLI_strncpy(name, "", sizeof(name)); - + /* print type name + ui name */ printf("ChanType: <%s> Name: \"%s\"\n", acf->channel_type_name, name); } @@ -2920,7 +2919,6 @@ void ANIM_channel_setting_set(bAnimContext *ac, bAnimListElem *ale, int setting, #define RENAME_TEXT_WIDTH 100 /* Draw the given channel */ -// TODO: make this use UI controls for the buttons void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); @@ -3010,20 +3008,20 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float /* TODO: when renaming, we might not want to draw this, especially if name happens to be longer than channel */ if (acf->name) { char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */ - + /* set text color */ /* XXX: if active, highlight differently? */ if (selected) UI_ThemeColor(TH_TEXT_HI); else UI_ThemeColor(TH_TEXT); - + /* get name */ acf->name(ale, name); - + offset += 3; UI_DrawString(offset, ytext, name); - + /* draw red underline if channel is disabled */ if ((ale->type == ANIMTYPE_FCURVE) && (ale->flag & FCURVE_DISABLED)) { /* FIXME: replace hardcoded color here, and check on extents! */ @@ -3068,7 +3066,7 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float } /* check if there's enough space for the toggles if the sliders are drawn too */ - if (!(draw_sliders) || (BLI_RCT_SIZE_X(&v2d->mask) > ACHANNEL_BUTTON_WIDTH / 2) ) { + if (!(draw_sliders) || (BLI_rcti_size_x(&v2d->mask) > ACHANNEL_BUTTON_WIDTH / 2) ) { /* protect... */ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT)) offset += ICON_WIDTH; @@ -3153,7 +3151,6 @@ static void achannel_setting_rename_done_cb(bContext *C, void *ads_poin, void *U ads->renameIndex = 0; /* send notifiers */ - // XXX: right notifier? WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_RENAME, NULL); } @@ -3199,7 +3196,7 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi { Key *key = (Key *)key_poin; KeyBlock *kb = (KeyBlock *)kb_poin; - char *rna_path = key_get_curValue_rnaPath(key, kb); + char *rna_path = BKE_keyblock_curval_rnapath_get(key, kb); ReportList *reports = CTX_wm_reports(C); Scene *scene = CTX_data_scene(C); @@ -3254,7 +3251,7 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChann /* get the flag and the pointer to that flag */ flag = acf->setting_flag(ac, setting, &negflag); ptr = acf->setting_ptr(ale, setting, &ptrsize); - /* enabled= ANIM_channel_setting_get(ac, ale, setting); */ /* UNUSED */ + /* enabled = ANIM_channel_setting_get(ac, ale, setting); */ /* UNUSED */ /* get the base icon for the setting */ switch (setting) { @@ -3269,13 +3266,13 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChann break; case ACHANNEL_SETTING_EXPAND: /* expanded triangle */ - //icon= ((enabled)? ICON_TRIA_DOWN : ICON_TRIA_RIGHT); + //icon = ((enabled)? ICON_TRIA_DOWN : ICON_TRIA_RIGHT); icon = ICON_TRIA_RIGHT; tooltip = "Make channels grouped under this channel visible"; break; case ACHANNEL_SETTING_SOLO: /* NLA Tracks only */ - //icon= ((enabled)? ICON_LAYER_ACTIVE : ICON_LAYER_USED); + //icon = ((enabled)? ICON_LAYER_ACTIVE : ICON_LAYER_USED); icon = ICON_LAYER_USED; tooltip = "NLA Track is the only one evaluated for the AnimData block it belongs to"; break; @@ -3284,13 +3281,13 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, bAnimChann case ACHANNEL_SETTING_PROTECT: /* protected lock */ // TODO: what about when there's no protect needed? - //icon= ((enabled)? ICON_LOCKED : ICON_UNLOCKED); + //icon = ((enabled)? ICON_LOCKED : ICON_UNLOCKED); icon = ICON_UNLOCKED; tooltip = "Editability of keyframes for this channel"; break; case ACHANNEL_SETTING_MUTE: /* muted speaker */ - //icon= ((enabled)? ICON_MUTE_IPO_ON : ICON_MUTE_IPO_OFF); + //icon = ((enabled)? ICON_MUTE_IPO_ON : ICON_MUTE_IPO_OFF); icon = ICON_MUTE_IPO_OFF; if (ale->type == ALE_FCURVE) @@ -3373,7 +3370,7 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale y = (ymaxc - yminc) / 2 + yminc; ymid = y - 7; /* y-coordinates for text is only 4 down from middle */ - /* ytext= y - 4; */ + /* ytext = y - 4; */ /* no button backdrop behind icons */ uiBlockSetEmboss(block, UI_EMBOSSN); @@ -3437,7 +3434,6 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale offset = 0; // TODO: when drawing sliders, make those draw instead of these toggles if not enough space - if (v2d) { short draw_sliders = 0; @@ -3460,7 +3456,7 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale } /* check if there's enough space for the toggles if the sliders are drawn too */ - if (!(draw_sliders) || (BLI_RCT_SIZE_X(&v2d->mask) > ACHANNEL_BUTTON_WIDTH / 2) ) { + if (!(draw_sliders) || (BLI_rcti_size_x(&v2d->mask) > ACHANNEL_BUTTON_WIDTH / 2) ) { /* protect... */ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT)) { offset += ICON_WIDTH; @@ -3507,7 +3503,7 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale KeyBlock *kb = (KeyBlock *)ale->data; Key *key = (Key *)ale->id; - rna_path = key_get_curValue_rnaPath(key, kb); + rna_path = BKE_keyblock_curval_rnapath_get(key, kb); free_path = 1; } diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index d35f39a48e0..f19dbe740bc 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -464,7 +464,7 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, ListBase *anim_data, bAn /* store this level as the 'old' level now */ prevLevel = level; - } + } /* if the level is 'greater than' (i.e. less important) than the previous level... */ else if (level > prevLevel) { /* if previous level was a base-level (i.e. 0 offset / root of one hierarchy), @@ -600,7 +600,7 @@ static int animedit_poll_channels_nla_tweakmode_off(bContext *C) if (ELEM3(sa->spacetype, SPACE_ACTION, SPACE_IPO, SPACE_NLA) == 0) return 0; - /* NLA TweakMode test */ + /* NLA TweakMode test */ if (sa->spacetype == SPACE_NLA) { if ((scene == NULL) || (scene->flag & SCE_NLA_EDIT_ON)) return 0; @@ -794,7 +794,7 @@ static void rearrange_animchannel_add_to_islands(ListBase *islands, ListBase *sr FCurve *fcu = (FCurve *)channel; is_sel = SEL_FCU(fcu); - } + } break; case ANIMTYPE_NLATRACK: { @@ -910,7 +910,7 @@ static void rearrange_nla_channels(bAnimContext *UNUSED(ac), AnimData *adt, shor if (rearrange_func == NULL) return; - /* only consider NLA data if it's accessible */ + /* only consider NLA data if it's accessible */ //if (EXPANDED_DRVD(adt) == 0) // return; @@ -931,7 +931,7 @@ static void rearrange_driver_channels(bAnimContext *UNUSED(ac), AnimData *adt, s if (rearrange_func == NULL) return; - /* only consider drivers if they're accessible */ + /* only consider drivers if they're accessible */ if (EXPANDED_DRVD(adt) == 0) return; @@ -2206,7 +2206,7 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in } notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); - } + } break; case ANIMTYPE_GROUP: @@ -2219,7 +2219,7 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in agrp->flag ^= AGRP_SELECTED; } else if (selectmode == -1) { - /* select all in group (and deselect everthing else) */ + /* select all in group (and deselect everthing else) */ FCurve *fcu; /* deselect all other channels */ @@ -2228,7 +2228,7 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in /* only select channels in group and group itself */ for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next) fcu->flag |= FCURVE_SELECTED; - agrp->flag |= AGRP_SELECTED; + agrp->flag |= AGRP_SELECTED; } else { /* select group by itself */ @@ -2306,7 +2306,7 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in /* invert selection status of this layer only */ gpl->flag ^= GP_LAYER_SELECT; } - else { + else { /* select layer by itself */ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); gpl->flag |= GP_LAYER_SELECT; diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index 6ce9fc638be..98071fafc1e 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -142,7 +142,6 @@ static void animchan_sync_group(bAnimContext *ac, bAnimListElem *ale, bActionGro /* check if there are bones, and whether the name matches any * NOTE: this feature will only really work if groups by default contain the F-Curves for a single bone */ - // TODO: if bone gets renamed, it would be best to be able to rename the group if (ob->pose) { bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, agrp->name); bArmature *arm = ob->data; @@ -319,7 +318,6 @@ void ANIM_sync_animchannels_to_data(const bContext *C) FCurve *active_fcurve = NULL; /* get animation context info for filtering the channels */ - // TODO: check on whether we need to set the area specially instead, since active area might not be ok? if (ANIM_animdata_get_context(C, &ac) == 0) return; diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 620f5de9db7..01c0a95e200 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -261,8 +261,8 @@ void ANIM_draw_previewrange(const bContext *C, View2D *v2d) /* only draw two separate 'curtains' if there's no overlap between them */ if (PSFRA < PEFRA) { glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)PSFRA, v2d->cur.ymax); - glRectf((float)PEFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); - } + glRectf((float)PEFRA, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); + } else { glRectf(v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax); } diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 209414550e3..721b3473792 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -99,7 +99,7 @@ /* ----------- Private Stuff - Action Editor ------------- */ /* Get shapekey data being edited (for Action Editor -> ShapeKey mode) */ -/* Note: there's a similar function in key.c (ob_get_key) */ +/* Note: there's a similar function in key.c (BKE_key_from_object) */ static Key *actedit_get_shapekeys(bAnimContext *ac) { Scene *scene = ac->scene; @@ -114,7 +114,7 @@ static Key *actedit_get_shapekeys(bAnimContext *ac) //if (saction->pin) return NULL; /* shapekey data is stored with geometry data */ - key = ob_get_key(ob); + key = BKE_key_from_object(ob); if (key) { if (key->type == KEY_RELATIVE) @@ -163,30 +163,30 @@ static short actedit_get_context(bAnimContext *ac, SpaceAction *saction) ac->mode = saction->mode; return 1; - + case SACTCONT_GPENCIL: /* Grease Pencil */ /* XXX review how this mode is handled... */ /* update scene-pointer (no need to check for pinning yet, as not implemented) */ saction->ads.source = (ID *)ac->scene; - + ac->datatype = ANIMCONT_GPENCIL; ac->data = &saction->ads; - + ac->mode = saction->mode; return 1; - - case SACTCONT_MASK: /* Grease Pencil */ /* XXX review how this mode is handled... */ - /* update scene-pointer (no need to check for pinning yet, as not implemented) */ + + case SACTCONT_MASK: /* Mask */ /* XXX review how this mode is handled... */ { /* TODO, other methods to get the mask */ // Sequence *seq = BKE_sequencer_active_get(ac->scene); //MovieClip *clip = ac->scene->clip; // struct Mask *mask = seq ? seq->mask : NULL; - + + /* update scene-pointer (no need to check for pinning yet, as not implemented) */ saction->ads.source = (ID *)ac->scene; - + ac->datatype = ANIMCONT_MASK; ac->data = &saction->ads; - + ac->mode = saction->mode; return 1; } @@ -682,18 +682,18 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne ale->datatype = ALE_ACT; ale->adt = BKE_animdata_from_id(data); - } + } break; case ANIMTYPE_DSSPK: { Speaker *spk = (Speaker *)data; AnimData *adt = spk->adt; - + ale->flag = FILTER_SPK_OBJD(spk); - + ale->key_data = (adt) ? adt->action : NULL; ale->datatype = ALE_ACT; - + ale->adt = BKE_animdata_from_id(data); } break; @@ -799,7 +799,7 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne /* the corresponding keyframes are from the animdata */ if (ale->adt && ale->adt->action) { bAction *act = ale->adt->action; - char *rna_path = key_get_curValue_rnaPath(key, kb); + char *rna_path = BKE_keyblock_curval_rnapath_get(key, kb); /* try to find the F-Curve which corresponds to this exactly, * then free the MEM_alloc'd string @@ -811,7 +811,7 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne } ale->datatype = (ale->key_data) ? ALE_FCURVE : ALE_NONE; } - } + } break; case ANIMTYPE_GPLAYER: @@ -824,18 +824,18 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne ale->datatype = ALE_GPFRAME; } break; - + case ANIMTYPE_MASKLAYER: { MaskLayer *masklay = (MaskLayer *)data; - + ale->flag = masklay->flag; - + ale->key_data = NULL; ale->datatype = ALE_MASKLAY; } break; - + case ANIMTYPE_NLATRACK: { NlaTrack *nlt = (NlaTrack *)data; @@ -980,6 +980,27 @@ static short skip_fcurve_with_name(bDopeSheet *ads, FCurve *fcu, ID *owner_id) return 1; } +/* Check if F-Curve has errors and/or is disabled + * > returns: (bool) True if F-Curve has errors/is disabled + */ +static short fcurve_has_errors(FCurve *fcu) +{ + /* F-Curve disabled - path eval error */ + if (fcu->flag & FCURVE_DISABLED) { + return 1; + } + + /* driver? */ + if (fcu->driver) { + /* for now, just check if the entire thing got disabled... */ + if (fcu->driver->flag & DRIVER_FLAG_INVALID) + return 1; + } + + /* no errors found */ + return 0; +} + /* find the next F-Curve that is usable for inclusion */ static FCurve *animfilter_fcurve_next(bDopeSheet *ads, FCurve *first, bActionGroup *grp, int filter_mode, ID *owner_id) { @@ -1002,7 +1023,7 @@ static FCurve *animfilter_fcurve_next(bDopeSheet *ads, FCurve *first, bActionGro if (skip_fcurve_selected_data(ads, fcu, owner_id, filter_mode)) continue; } - } + } /* only include if visible (Graph Editor check, not channels check) */ if (!(filter_mode & ANIMFILTER_CURVE_VISIBLE) || (fcu->flag & FCURVE_VISIBLE)) { @@ -1018,6 +1039,13 @@ static FCurve *animfilter_fcurve_next(bDopeSheet *ads, FCurve *first, bActionGro continue; } + /* error-based filtering... */ + if ((ads) && (ads->filterflag & ADS_FILTER_ONLY_ERRORS)) { + /* skip if no errors... */ + if (fcurve_has_errors(fcu) == 0) + continue; + } + /* this F-Curve can be used, so return it */ return fcu; } @@ -1138,7 +1166,6 @@ static size_t animfilter_action(bAnimContext *ac, ListBase *anim_data, bDopeShee /* don't include anything from this action if it is linked in from another file, * and we're getting stuff for editing... */ - // TODO: need a way of tagging other channels that may also be affected... if ((filter_mode & ANIMFILTER_FOREDIT) && (act->id.lib)) return 0; @@ -1184,7 +1211,7 @@ static size_t animfilter_nla(bAnimContext *UNUSED(ac), ListBase *anim_data, bDop */ if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) || (adt->action)) { /* there isn't really anything editable here, so skip if need editable */ - if ((filter_mode & ANIMFILTER_FOREDIT) == 0) { + if ((filter_mode & ANIMFILTER_FOREDIT) == 0) { /* just add the action track now (this MUST appear for drawing) * - as AnimData may not have an action, we pass a dummy pointer just to get the list elem created, then * overwrite this with the real value - REVIEW THIS... @@ -1240,11 +1267,11 @@ static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDope { AnimData *adt = BKE_animdata_from_id(id); size_t items = 0; - + /* image object datablocks have no anim-data so check for NULL */ if (adt) { IdAdtTemplate *iat = (IdAdtTemplate *)id; - + /* NOTE: this macro is used instead of inlining the logic here, since this sort of filtering is still needed * in a few places in he rest of the code still - notably for the few cases where special mode-based * different types of data expanders are required. @@ -1265,7 +1292,7 @@ static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDope } ); } - + return items; } @@ -1283,7 +1310,6 @@ static size_t animdata_filter_shapekey(bAnimContext *ac, ListBase *anim_data, Ke /* loop through the channels adding ShapeKeys as appropriate */ for (kb = key->block.first; kb; kb = kb->next) { /* skip the first one, since that's the non-animatable basis */ - // XXX maybe in future this may become handy? if (kb == key->block.first) continue; /* only work with this channel and its subchannels if it is editable */ @@ -1597,7 +1623,6 @@ static size_t animdata_filter_ds_material(bAnimContext *ac, ListBase *anim_data, /* did we find anything? */ if (tmp_items) { /* include material-expand widget first */ - // hmm... do we need to store the index of this material in the array anywhere? if (filter_mode & ANIMFILTER_LIST_CHANNELS) { /* check if filtering by active status */ if (ANIMCHANNEL_ACTIVEOK(ma)) { @@ -1809,11 +1834,11 @@ static size_t animdata_filter_ds_obdata(bAnimContext *ac, ListBase *anim_data, b { Lamp *la = ob->data; bNodeTree *ntree = la->nodetree; - + /* nodetree */ if ((ntree) && !(ads->filterflag & ADS_FILTER_NONTREE)) tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, &la->id, ntree, filter_mode); - + /* textures */ if (!(ads->filterflag & ADS_FILTER_NOTEX)) tmp_items += animdata_filter_ds_textures(ac, &tmp_data, ads, &la->id, filter_mode); @@ -1943,7 +1968,7 @@ static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data /* filter data contained under object first */ BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_OBJC(ob)) { - Key *key = ob_get_key(ob); + Key *key = BKE_key_from_object(ob); /* object-level animation */ if ((ob->adt) && !(ads->filterflag & ADS_FILTER_NOOBJ)) { @@ -2277,7 +2302,7 @@ static size_t animdata_filter_animchan(bAnimContext *ac, ListBase *anim_data, bD size_t items = 0; /* data to filter depends on channel type */ - // XXX: only common channel-types have been handled for now + /* NOTE: only common channel-types have been handled for now. More can be added as necessary */ switch (channel->type) { case ANIMTYPE_SUMMARY: items += animdata_filter_dopesheet(ac, anim_data, ads, filter_mode); @@ -2290,6 +2315,10 @@ static size_t animdata_filter_animchan(bAnimContext *ac, ListBase *anim_data, bD case ANIMTYPE_OBJECT: items += animdata_filter_dopesheet_ob(ac, anim_data, ads, channel->data, filter_mode); break; + + default: + printf("ERROR: Unsupported channel type (%d) in animdata_filter_animchan()\n", channel->type); + break; } return items; @@ -2414,9 +2443,9 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, int filter_mo } break; - case ANIMCONT_FCURVES: /* Graph Editor -> FCurves/Animation Editing */ + case ANIMCONT_FCURVES: /* Graph Editor -> F-Curves/Animation Editing */ case ANIMCONT_DRIVERS: /* Graph Editor -> Drivers Editing */ - case ANIMCONT_NLA: /* NLA Editor */ + case ANIMCONT_NLA: /* NLA Editor */ { /* all of these editors use the basic DopeSheet data for filtering options, but don't have all the same features */ items = animdata_filter_dopesheet(ac, anim_data, data, filter_mode); diff --git a/source/blender/editors/animation/anim_intern.h b/source/blender/editors/animation/anim_intern.h index cf84eb04b10..54c7f7ea30f 100644 --- a/source/blender/editors/animation/anim_intern.h +++ b/source/blender/editors/animation/anim_intern.h @@ -50,7 +50,9 @@ void ANIM_OT_keyframe_delete(struct wmOperatorType *ot); * required for each space. */ void ANIM_OT_keyframe_insert_menu(struct wmOperatorType *ot); + void ANIM_OT_keyframe_delete_v3d(struct wmOperatorType *ot); +void ANIM_OT_keyframe_clear_v3d(struct wmOperatorType *ot); /* Keyframe managment operators for UI buttons (RMB menu). */ void ANIM_OT_keyframe_insert_button(struct wmOperatorType *ot); @@ -80,4 +82,4 @@ void ANIM_OT_driver_button_remove(struct wmOperatorType *ot); void ANIM_OT_copy_driver_button(struct wmOperatorType *ot); void ANIM_OT_paste_driver_button(struct wmOperatorType *ot); -#endif // __ANIM_INTERN_H__ +#endif /* __ANIM_INTERN_H__ */ diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c index 5295950546d..d8e3349e998 100644 --- a/source/blender/editors/animation/anim_ipo_utils.c +++ b/source/blender/editors/animation/anim_ipo_utils.c @@ -89,7 +89,7 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu) * i.e. Bone1.Location.X, or Object.Location.X * 2) () * i.e. X Location (Bone1), or X Location (Object) - * + * * Currently, option 2 is in use, to try and make it easier to quickly identify F-Curves (it does have * problems with looking rather odd though). Option 1 is better in terms of revealing a consistent sense of * hierarchy though, which isn't so clear with option 2. diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 445b684c261..852f3fa5469 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -150,7 +150,7 @@ int ED_markers_post_apply_transform(ListBase *markers, Scene *scene, int mode, f break; case TFM_TIME_SCALE: - { + { /* rescale the distance between the marker and the current frame */ marker->frame = cfra + (int)floorf(((float)(marker->frame - cfra) * value) + 0.5f); changed++; @@ -249,7 +249,7 @@ void ED_markers_get_minmax(ListBase *markers, short sel, float *first, float *la min = (float)marker->frame; if (marker->frame > max) max = (float)marker->frame; - } + } } } @@ -278,7 +278,7 @@ static void add_marker_to_cfra_elem(ListBase *lb, TimeMarker *marker, short only return; } else if (ce->cfra > marker->frame) break; - } + } cen = MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem"); if (ce) BLI_insertlinkbefore(lb, ce, cen); @@ -354,13 +354,13 @@ static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag) xpos = marker->frame; /* no time correction for framelen! space is drawn with old values */ - ypixels = BLI_RCT_SIZE_Y(&v2d->mask); + ypixels = BLI_rcti_size_y(&v2d->mask); UI_view2d_getscale(v2d, &xscale, &yscale); glScalef(1.0f / xscale, 1.0f, 1.0f); glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* vertical line - dotted */ #ifdef DURIAN_CAMERA_SWITCH @@ -504,7 +504,7 @@ static int ed_markers_poll_markers_exist(bContext *C) * "custom"/third-tier invoke() callback supplied as the last arg (which would normally * be the operator's invoke() callback elsewhere) * - * < invoke_func: (fn(bContext*, wmOperator*, wmEvent*)=int) "standard" invoke function + * < invoke_func: (fn(bContext *, wmOperator *, wmEvent *)=int) "standard" invoke function * that operator would otherwise have used. If NULL, the operator's standard * exec() callback will be called instead in the appropriate places. */ @@ -522,7 +522,7 @@ static int ed_markers_opwrap_invoke_custom(bContext *C, wmOperator *op, wmEvent else if (op->type->exec) retval = op->type->exec(C, op); else - BKE_report(op->reports, RPT_ERROR, "Programming error: operator doesn't actually have code to do anything!"); + BKE_report(op->reports, RPT_ERROR, "Programming error: operator does not actually have code to do anything!"); /* return status modifications - for now, make this spacetype dependent as above */ if (sa->spacetype != SPACE_TIME) { @@ -726,7 +726,7 @@ static int ed_marker_move_cancel(bContext *C, wmOperator *op) { RNA_int_set(op->ptr, "frames", 0); ed_marker_move_apply(op); - ed_marker_move_exit(C, op); + ed_marker_move_exit(C, op); WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL); WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL); @@ -773,7 +773,7 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) if (hasNumInput(&mm->num)) break; - dx = BLI_RCT_SIZE_X(&v2d->cur) / BLI_RCT_SIZE_X(&v2d->mask); + dx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); if (evt->x != mm->evtx) { /* XXX maybe init for first time */ int a, offs, totmark = 0; @@ -821,7 +821,7 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) } else { /* we only print the offset */ - if (mm->slink->spacetype == SPACE_TIME) { + if (mm->slink->spacetype == SPACE_TIME) { SpaceTime *stime = (SpaceTime *)mm->slink; if (stime->flag & TIME_DRAWFRAMES) BLI_snprintf(str, sizeof(str), "Marker offset %d ", offs); @@ -1030,7 +1030,7 @@ static int ed_marker_select(bContext *C, wmEvent *evt, int extend, int camera) x = evt->x - ar->winrct.xmin; y = evt->y - ar->winrct.ymin; - UI_view2d_region_to_view(v2d, x, y, &viewx, NULL); + UI_view2d_region_to_view(v2d, x, y, &viewx, NULL); cfra = ED_markers_find_nearest_marker_time(markers, viewx); @@ -1377,7 +1377,7 @@ static int ed_marker_make_links_scene_exec(bContext *C, wmOperator *op) } if (scene_to == CTX_data_scene(C)) { - BKE_report(op->reports, RPT_ERROR, "Can't re-link markers into the same scene"); + BKE_report(op->reports, RPT_ERROR, "Cannot re-link markers into the same scene"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index e24a4d49a05..ca036a8540e 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -172,7 +172,7 @@ static void ANIM_OT_change_frame(wmOperatorType *ot) ot->poll = change_frame_poll; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO; + ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO | OPTYPE_GRAB_POINTER; /* rna */ RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME); @@ -290,6 +290,7 @@ void ED_operatortypes_anim(void) WM_operatortype_append(ANIM_OT_keyframe_delete); WM_operatortype_append(ANIM_OT_keyframe_insert_menu); WM_operatortype_append(ANIM_OT_keyframe_delete_v3d); + WM_operatortype_append(ANIM_OT_keyframe_clear_v3d); WM_operatortype_append(ANIM_OT_keyframe_insert_button); WM_operatortype_append(ANIM_OT_keyframe_delete_button); WM_operatortype_append(ANIM_OT_keyframe_clear_button); diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 672e11ac613..25833c13925 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -91,7 +91,7 @@ FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_inde adt = BKE_animdata_from_id(id); if ((adt == NULL) && (add)) adt = BKE_id_add_animdata(id); - if (adt == NULL) { + if (adt == NULL) { /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */ return NULL; } @@ -147,7 +147,7 @@ short ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int ar RNA_id_pointer_create(id, &id_ptr); if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { BKE_reportf(reports, RPT_ERROR, - "Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", + "Could not add driver, as RNA path is invalid for the given ID (ID = %s, path = %s)", id->name, rna_path); return 0; } @@ -310,7 +310,7 @@ short ANIM_copy_driver(ReportList *reports, ID *id, const char rna_path[], int a RNA_id_pointer_create(id, &id_ptr); if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { BKE_reportf(reports, RPT_ERROR, - "Could not find Driver to copy, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", + "Could not find driver to copy, as RNA path is invalid for the given ID (ID = %s, path = %s)", id->name, rna_path); return 0; } @@ -357,14 +357,14 @@ short ANIM_paste_driver(ReportList *reports, ID *id, const char rna_path[], int RNA_id_pointer_create(id, &id_ptr); if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { BKE_reportf(reports, RPT_ERROR, - "Could not paste Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", + "Could not paste driver, as RNA path is invalid for the given ID (ID = %s, path = %s)", id->name, rna_path); return 0; } /* if the buffer is empty, cannot paste... */ if (channeldriver_copypaste_buf == NULL) { - BKE_report(reports, RPT_ERROR, "Paste Driver: No Driver to paste"); + BKE_report(reports, RPT_ERROR, "Paste driver: no driver to paste"); return 0; } @@ -478,7 +478,7 @@ static int add_driver_button_exec(bContext *C, wmOperator *op) char *path = get_driver_path_hack(C, &ptr, prop); short flags = CREATEDRIVER_WITH_DEFAULT_DVAR; - if (path) { + if (path) { success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON); MEM_freeN(path); diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index e254fb7a3c4..79a4c9a769d 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -74,13 +74,6 @@ #define B_REDR 1 #define B_FMODIFIER_REDRAW 20 -/* macro for use here to draw background box and set height */ -// XXX for now, roundbox has it's callback func set to NULL to not intercept events -#define DRAW_BACKDROP(height) \ - { \ - uiDefBut(block, ROUNDBOX, B_REDR, "", -3, yco - height, width + 3, height - 1, NULL, 5.0, 0.0, 12.0, (float)rb_col, ""); \ - } (void)0 - /* callback to verify modifier data */ static void validate_fmodifier_cb(bContext *UNUSED(C), void *fcm_v, void *UNUSED(arg)) { @@ -118,6 +111,7 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s uiBlock *block; uiBut *but; PointerRNA ptr; + short bwidth = width - 30; /* max button width */ /* init the RNA-pointer */ RNA_pointer_create(id, &RNA_FModifierFunctionGenerator, fcm, &ptr); @@ -126,10 +120,10 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s /* col = uiLayoutColumn(layout, TRUE); */ /* UNUSED */ block = uiLayoutGetBlock(layout); uiBlockBeginAlign(block); - but = uiDefButR(block, MENU, B_FMODIFIER_REDRAW, NULL, 0, 0, width - 30, UI_UNIT_Y, &ptr, "mode", -1, 0, 0, -1, -1, NULL); + but = uiDefButR(block, MENU, B_FMODIFIER_REDRAW, NULL, 0, 0, bwidth, UI_UNIT_Y, &ptr, "mode", -1, 0, 0, -1, -1, NULL); uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL); - - uiDefButR(block, TOG, B_FMODIFIER_REDRAW, NULL, 0, 0, width - 30, UI_UNIT_Y, &ptr, "use_additive", -1, 0, 0, -1, -1, NULL); + + uiDefButR(block, TOG, B_FMODIFIER_REDRAW, NULL, 0, 0, bwidth, UI_UNIT_Y, &ptr, "use_additive", -1, 0, 0, -1, -1, NULL); uiBlockEndAlign(block); /* now add settings for individual modes */ @@ -139,50 +133,62 @@ static void draw_modifier__generator(uiLayout *layout, ID *id, FModifier *fcm, s float *cp = NULL; char xval[32]; unsigned int i; + int maxXWidth; /* draw polynomial order selector */ row = uiLayoutRow(layout, FALSE); block = uiLayoutGetBlock(row); - but = uiDefButI(block, NUM, B_FMODIFIER_REDRAW, IFACE_("Poly Order:"), 10, 0, width - 30, 19, + but = uiDefButI(block, NUM, B_FMODIFIER_REDRAW, IFACE_("Poly Order:"), 10, 0, bwidth, 20, &data->poly_order, 1, 100, 0, 0, TIP_("'Order' of the Polynomial (for a polynomial with n terms, 'order' is n-1)")); uiButSetFunc(but, validate_fmodifier_cb, fcm, NULL); + /* calculate maximum width of label for "x^n" labels */ + if (data->arraysize > 2) { + BLI_snprintf(xval, sizeof(xval), "x^%u", data->arraysize); + maxXWidth = UI_GetStringWidth(xval) + 10; /* XXX: UI_GetStringWidth is not accurate */ + } + else { + /* basic size (just "x") */ + maxXWidth = 15; + } + /* draw controls for each coefficient and a + sign at end of row */ row = uiLayoutRow(layout, TRUE); block = uiLayoutGetBlock(row); cp = data->coefficients; for (i = 0; (i < data->arraysize) && (cp); i++, cp++) { - /* To align with first line */ + /* To align with first line... */ if (i) - uiDefBut(block, LABEL, 1, " ", 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, ""); + uiDefBut(block, LABEL, 1, " ", 0, 0, 40, 20, NULL, 0.0, 0.0, 0, 0, ""); else - uiDefBut(block, LABEL, 1, "y =", 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, ""); + uiDefBut(block, LABEL, 1, "y =", 0, 0, 40, 20, NULL, 0.0, 0.0, 0, 0, ""); + /* coefficient */ - uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, 150, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, + uiDefButF(block, NUM, B_FMODIFIER_REDRAW, "", 0, 0, bwidth / 2, 20, cp, -UI_FLT_MAX, UI_FLT_MAX, 10, 3, TIP_("Coefficient for polynomial")); /* 'x' param (and '+' if necessary) */ if (i == 0) - strcpy(xval, ""); + BLI_strncpy(xval, "", sizeof(xval)); else if (i == 1) - strcpy(xval, "x"); + BLI_strncpy(xval, "x", sizeof(xval)); else - sprintf(xval, "x^%u", i); - uiDefBut(block, LABEL, 1, xval, 0, 0, 50, 20, NULL, 0.0, 0.0, 0, 0, TIP_("Power of x")); + BLI_snprintf(xval, sizeof(xval), "x^%u", i); + uiDefBut(block, LABEL, 1, xval, 0, 0, maxXWidth, 20, NULL, 0.0, 0.0, 0, 0, TIP_("Power of x")); if ( (i != (data->arraysize - 1)) || ((i == 0) && data->arraysize == 2) ) { - uiDefBut(block, LABEL, 1, "+", 0, 0, 30, 20, NULL, 0.0, 0.0, 0, 0, ""); + uiDefBut(block, LABEL, 1, "+", 0, 0, 20, 20, NULL, 0.0, 0.0, 0, 0, ""); /* next coefficient on a new row */ row = uiLayoutRow(layout, TRUE); block = uiLayoutGetBlock(row); } else { - /* For alignement in UI! */ - uiDefBut(block, LABEL, 1, " ", 0, 0, 30, 20, NULL, 0.0, 0.0, 0, 0, ""); + /* For alignment in UI! */ + uiDefBut(block, LABEL, 1, " ", 0, 0, 20, 20, NULL, 0.0, 0.0, 0, 0, ""); } } break; diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index 6c9105dde69..e520a95aa95 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -322,7 +322,7 @@ static void nupdate_abk_bezt(void *node, void *data) /* just add the BezTriple to the buffer if there's space, or allocate a new one */ if (abk->numBezts >= MAX_ABK_BUFSIZE) { // TODO: need to allocate new array to cater... - //bezts_extra= MEM_callocN(...); + //bezts_extra = MEM_callocN(...); if (G.debug & G_DEBUG) printf("FIXME: nupdate_abk_bezt() missing case for too many overlapping BezTriples\n"); } @@ -345,7 +345,7 @@ static BezTriple *abk_get_bezt_with_value(ActBeztColumn *abk, float value) return NULL; /* look over each BezTriple in this container */ - for (i = 0; i < abk->numBezts; i++) { + for (i = 0; i < abk->numBezts; i++) { /* only do exact match for now... */ if (/*i >= MAX_ABK_BUFSIZE*/ 0) { // TODO: this case needs special handling @@ -582,7 +582,7 @@ void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel, } /* tweak size of keyframe shape according to type of keyframe - * - 'proper' keyframes have key_type=0, so get drawn at full size + * - 'proper' keyframes have key_type = 0, so get drawn at full size */ hsize -= 0.5f * key_type; @@ -960,7 +960,7 @@ void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, DLRBT_Tree if (fcu && fcu->totvert && fcu->bezt) { /* apply NLA-mapping (if applicable) */ - if (adt) + if (adt) ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0); /* if getting long keyframes too, grab the BezTriples in a BST for diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index b277d0eccb5..015c2667a93 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -154,7 +154,7 @@ short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked, FCurve *fcu, KeyframeEdi if (fcu_cb) fcu_cb(fcu); - /* done */ + /* done */ return 0; } @@ -639,7 +639,7 @@ static short snap_bezier_horizontal(KeyframeEditData *UNUSED(ked), BezTriple *be if (ELEM3(bezt->h1, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) bezt->h1 = HD_ALIGN; if (ELEM3(bezt->h2, HD_AUTO, HD_AUTO_ANIM, HD_VECT)) bezt->h2 = HD_ALIGN; } - return 0; + return 0; } /* value to snap to is stored in the custom data -> first float value slot */ @@ -880,7 +880,7 @@ KeyframeEditFunc ANIM_editkeyframes_ipo(short code) switch (code) { case BEZT_IPO_CONST: /* constant */ return set_bezt_constant; - case BEZT_IPO_LIN: /* linear */ + case BEZT_IPO_LIN: /* linear */ return set_bezt_linear; default: /* bezier */ return set_bezt_bezier; @@ -930,7 +930,7 @@ KeyframeEditFunc ANIM_editkeyframes_keytype(short code) case BEZT_KEYTYPE_JITTER: /* jitter keyframe */ return set_keytype_jitter; - case BEZT_KEYTYPE_KEYFRAME: /* proper keyframe */ + case BEZT_KEYTYPE_KEYFRAME: /* proper keyframe */ default: return set_keytype_keyframe; } diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index b5c0555bf63..9249b912da6 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -188,7 +188,7 @@ void clean_fcurve(FCurve *fcu, float thresh) /* make a copy of the old BezTriples, and clear F-Curve */ old_bezts = fcu->bezt; - totCount = fcu->totvert; + totCount = fcu->totvert; fcu->bezt = NULL; fcu->totvert = 0; @@ -256,7 +256,7 @@ void clean_fcurve(FCurve *fcu, float thresh) insert_vert_fcurve(fcu, cur[0], cur[1], 0); } } - else { + else { /* add if value doesn't equal that of previous */ if (IS_EQT(cur[1], prev[1], thresh) == 0) { /* add new keyframe */ diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 5e0459bea90..8ba330e7c3c 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -43,6 +43,8 @@ #include "BLI_dynstr.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" @@ -106,7 +108,7 @@ short ANIM_get_keyframing_flags(Scene *scene, short incl_mode) } /* only if including settings from the autokeying mode... */ - if (incl_mode) { + if (incl_mode) { /* keyframing mode - only replace existing keyframes */ if (IS_AUTOKEY_MODE(scene, EDITKEYS)) flag |= INSERTKEY_REPLACE; @@ -129,7 +131,7 @@ bAction *verify_adt_action(ID *id, short add) adt = BKE_animdata_from_id(id); if ((adt == NULL) && (add)) adt = BKE_id_add_animdata(id); - if (adt == NULL) { + if (adt == NULL) { /* if still none (as not allowed to add, or ID doesn't have animdata for some reason) */ printf("ERROR: Couldn't add AnimData (ID = %s)\n", (id) ? (id->name) : ""); return NULL; @@ -238,7 +240,7 @@ int insert_bezt_fcurve(FCurve *fcu, BezTriple *bezt, short flag) i = binarysearch_bezt_index(fcu->bezt, bezt->vec[1][0], fcu->totvert, &replace); /* replace an existing keyframe? */ - if (replace) { + if (replace) { /* sanity check: 'i' may in rare cases exceed arraylen */ if ((i >= 0) && (i < fcu->totvert)) { /* just change the values when replacing, so as to not overwrite handles */ @@ -410,12 +412,12 @@ static short new_key_needed(FCurve *fcu, float cFrame, float nValue) float prevPosi = 0.0f, prevVal = 0.0f; float beztPosi = 0.0f, beztVal = 0.0f; - /* get current time+value */ + /* get current time+value */ beztPosi = bezt->vec[1][0]; beztVal = bezt->vec[1][1]; if (prev) { - /* there is a keyframe before the one currently being examined */ + /* there is a keyframe before the one currently being examined */ /* get previous time+value */ prevPosi = prev->vec[1][0]; @@ -477,10 +479,10 @@ static short new_key_needed(FCurve *fcu, float cFrame, float nValue) /* Frame in which to add a new-keyframe occurs after all other keys * -> If there are at least two existing keyframes, then if the values of the - * last two keyframes and the new-keyframe match, the last existing keyframe - * gets deleted as it is no longer required. + * last two keyframes and the new-keyframe match, the last existing keyframe + * gets deleted as it is no longer required. * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last - * keyframe is not equal to last keyframe. + * keyframe is not equal to last keyframe. */ bezt = (fcu->bezt + (fcu->totvert - 1)); valA = bezt->vec[1][1]; @@ -787,14 +789,15 @@ short insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *p /* F-Curve not editable? */ if (fcurve_is_keyframable(fcu) == 0) { BKE_reportf(reports, RPT_ERROR, - "F-Curve with path = '%s' [%d] cannot be keyframed. Ensure that it is not locked or sampled. Also, try removing F-Modifiers", + "F-Curve with path '%s[%d]' cannot be keyframed, ensure that it is not locked or sampled, " + "and try removing F-Modifiers", fcu->rna_path, fcu->array_index); return 0; } /* if no property given yet, try to validate from F-Curve info */ if ((ptr.id.data == NULL) && (ptr.data == NULL)) { - BKE_report(reports, RPT_ERROR, "No RNA-pointer available to retrieve values for keyframing from"); + BKE_report(reports, RPT_ERROR, "No RNA pointer available to retrieve values for keyframing from"); return 0; } if (prop == NULL) { @@ -803,10 +806,10 @@ short insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *p /* try to get property we should be affecting */ if ((RNA_path_resolve(&ptr, fcu->rna_path, &tmp_ptr, &prop) == 0) || (prop == NULL)) { /* property not found... */ - const char *idname = (ptr.id.data) ? ((ID *)ptr.id.data)->name : ""; + const char *idname = (ptr.id.data) ? ((ID *)ptr.id.data)->name : TIP_(""); BKE_reportf(reports, RPT_ERROR, - "Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", + "Could not insert keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)", idname, fcu->rna_path); return 0; } @@ -906,15 +909,15 @@ short insert_keyframe(ReportList *reports, ID *id, bAction *act, const char grou /* validate pointer first - exit if failure */ if (id == NULL) { - BKE_reportf(reports, RPT_ERROR, "No ID-block to insert keyframe in (Path = %s)", rna_path); + BKE_reportf(reports, RPT_ERROR, "No ID block to insert keyframe in (path = %s)", rna_path); return 0; } RNA_id_pointer_create(id, &id_ptr); if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { BKE_reportf(reports, RPT_ERROR, - "Could not insert keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", - (id) ? id->name : "", rna_path); + "Could not insert keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)", + (id) ? id->name : TIP_(""), rna_path); return 0; } @@ -927,7 +930,7 @@ short insert_keyframe(ReportList *reports, ID *id, bAction *act, const char grou if (act == NULL) { BKE_reportf(reports, RPT_ERROR, - "Could not insert keyframe, as this type does not support animation data (ID = %s, Path = %s)", + "Could not insert keyframe, as this type does not support animation data (ID = %s, path = %s)", id->name, rna_path); return 0; } @@ -937,7 +940,7 @@ short insert_keyframe(ReportList *reports, ID *id, bAction *act, const char grou } /* key entire array convenience method */ - if (array_index == -1) { + if (array_index == -1) { array_index = 0; array_index_max = RNA_property_array_length(&ptr, prop); @@ -997,14 +1000,16 @@ short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char grou /* sanity checks */ if (ELEM(NULL, id, adt)) { - BKE_report(reports, RPT_ERROR, "No ID-Block and/Or AnimData to delete keyframe from"); + BKE_report(reports, RPT_ERROR, "No ID block and/or AnimData to delete keyframe from"); return 0; } /* validate pointer first - exit if failure */ RNA_id_pointer_create(id, &id_ptr); if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { - BKE_reportf(reports, RPT_ERROR, "Could not delete keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", id->name, rna_path); + BKE_reportf(reports, RPT_ERROR, + "Could not delete keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)", + id->name, rna_path); return 0; } @@ -1023,13 +1028,13 @@ short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char grou cfra = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP); } else { - BKE_reportf(reports, RPT_ERROR, "No Action to delete keyframes from for ID = %s\n", id->name); + BKE_reportf(reports, RPT_ERROR, "No action to delete keyframes from for ID = %s", id->name); return 0; } } /* key entire array convenience method */ - if (array_index == -1) { + if (array_index == -1) { array_index = 0; array_index_max = RNA_property_array_length(&ptr, prop); @@ -1059,7 +1064,7 @@ short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char grou /* try to find index of beztriple to get rid of */ i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found); - if (found) { + if (found) { /* delete the key at the index (will sanity check + do recalc afterwards) */ delete_fcurve_key(fcu, i, 1); @@ -1096,14 +1101,16 @@ static short clear_keyframe(ReportList *reports, ID *id, bAction *act, const cha /* sanity checks */ if (ELEM(NULL, id, adt)) { - BKE_report(reports, RPT_ERROR, "No ID-Block and/Or AnimData to delete keyframe from"); + BKE_report(reports, RPT_ERROR, "No ID block and/or AnimData to delete keyframe from"); return 0; } /* validate pointer first - exit if failure */ RNA_id_pointer_create(id, &id_ptr); if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) { - BKE_reportf(reports, RPT_ERROR, "Could not clear keyframe, as RNA Path is invalid for the given ID (ID = %s, Path = %s)", id->name, rna_path); + BKE_reportf(reports, RPT_ERROR, + "Could not clear keyframe, as RNA path is invalid for the given ID (ID = %s, path = %s)", + id->name, rna_path); return 0; } @@ -1119,7 +1126,7 @@ static short clear_keyframe(ReportList *reports, ID *id, bAction *act, const cha act = adt->action; } else { - BKE_reportf(reports, RPT_ERROR, "No Action to delete keyframes from for ID = %s\n", id->name); + BKE_reportf(reports, RPT_ERROR, "No action to delete keyframes from for ID = %s", id->name); return 0; } } @@ -1186,10 +1193,9 @@ static int modify_key_op_poll(bContext *C) /* if Outliner, don't allow in some views */ if (so) { - if (ELEM4(so->outlinevis, SO_GROUPS, SO_LIBRARIES, SO_VERSE_SESSION, SO_VERSE_SESSION)) - return 0; - if (ELEM3(so->outlinevis, SO_SEQUENCE, SO_USERDEF, SO_KEYMAP)) + if (ELEM5(so->outlinevis, SO_GROUPS, SO_LIBRARIES, SO_SEQUENCE, SO_USERDEF, SO_KEYMAP)) { return 0; + } } /* TODO: checks for other space types can be added here */ @@ -1223,30 +1229,30 @@ static int insert_key_exec(bContext *C, wmOperator *op) /* report failures */ if (ks == NULL) { - BKE_report(op->reports, RPT_ERROR, "No active Keying Set"); + BKE_report(op->reports, RPT_ERROR, "No active keying set"); return OPERATOR_CANCELLED; } /* try to insert keyframes for the channels specified by KeyingSet */ success = ANIM_apply_keyingset(C, NULL, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); if (G.debug & G_DEBUG) - BKE_reportf(op->reports, RPT_INFO, "KeyingSet '%s' - Successfully added %d Keyframes\n", ks->name, success); + BKE_reportf(op->reports, RPT_INFO, "Keying set '%s' - successfully added %d keyframes", ks->name, success); /* report failure or do updates? */ if (success == MODIFYKEY_INVALID_CONTEXT) { - BKE_report(op->reports, RPT_ERROR, "No suitable context info for active Keying Set"); + BKE_report(op->reports, RPT_ERROR, "No suitable context info for active keying set"); return OPERATOR_CANCELLED; } else if (success) { /* if the appropriate properties have been set, make a note that we've inserted something */ if (RNA_boolean_get(op->ptr, "confirm_success")) - BKE_reportf(op->reports, RPT_INFO, "Successfully added %d Keyframes for KeyingSet '%s'", success, ks->name); + BKE_reportf(op->reports, RPT_INFO, "Successfully added %d keyframes for keying set '%s'", success, ks->name); /* send notifiers that keyframes have been changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); } else - BKE_report(op->reports, RPT_WARNING, "Keying Set failed to insert any keyframes"); + BKE_report(op->reports, RPT_WARNING, "Keying set failed to insert any keyframes"); /* send updates */ DAG_ids_flush_update(bmain, 0); @@ -1390,19 +1396,19 @@ static int delete_key_exec(bContext *C, wmOperator *op) /* report failure or do updates? */ if (success == MODIFYKEY_INVALID_CONTEXT) { - BKE_report(op->reports, RPT_ERROR, "No suitable context info for active Keying Set"); + BKE_report(op->reports, RPT_ERROR, "No suitable context info for active keying set"); return OPERATOR_CANCELLED; } else if (success) { /* if the appropriate properties have been set, make a note that we've inserted something */ if (RNA_boolean_get(op->ptr, "confirm_success")) - BKE_reportf(op->reports, RPT_INFO, "Successfully removed %d Keyframes for KeyingSet '%s'", success, ks->name); + BKE_reportf(op->reports, RPT_INFO, "Successfully removed %d keyframes for keying set '%s'", success, ks->name); /* send notifiers that keyframes have been changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); } else - BKE_report(op->reports, RPT_WARNING, "Keying Set failed to remove any keyframes"); + BKE_report(op->reports, RPT_WARNING, "Keying set failed to remove any keyframes"); /* send updates */ DAG_ids_flush_update(bmain, 0); @@ -1440,46 +1446,122 @@ void ANIM_OT_keyframe_delete(wmOperatorType *ot) } /* Delete Key Operator ------------------------ */ - -/* XXX WARNING: - * This is currently just a basic operator, which work in 3d-view context on objects only. - * Should this be kept? It does have advantages over a version which requires selecting a keyingset to use... - * -- Joshua Leung, Jan 2009 +/* NOTE: Although this version is simpler than the more generic version for KeyingSets, + * it is more useful for animators working in the 3D view. */ -static int delete_key_v3d_exec(bContext *C, wmOperator *op) +static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap - // XXX more comprehensive tests will be needed CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { - ID *id = (ID *)ob; - FCurve *fcu, *fcn; - short success = 0; - - /* loop through all curves in animdata and delete keys on this frame */ + /* just those in active action... */ if ((ob->adt) && (ob->adt->action)) { AnimData *adt = ob->adt; bAction *act = adt->action; + FCurve *fcu, *fcn; for (fcu = act->curves.first; fcu; fcu = fcn) { + short can_delete = FALSE; + fcn = fcu->next; - success += delete_keyframe(op->reports, id, NULL, NULL, fcu->rna_path, fcu->array_index, cfra, 0); + + /* in pose mode, only delete the F-Curve if it belongs to a selected bone */ + if (ob->mode & OB_MODE_POSE) { + if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones[")) { + bPoseChannel *pchan; + char *bone_name; + + /* get bone-name, and check if this bone is selected */ + bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); + pchan = BKE_pose_channel_find_name(ob->pose, bone_name); + if (bone_name) MEM_freeN(bone_name); + + /* delete if bone is selected*/ + if ((pchan) && (pchan->bone)) { + if (pchan->bone->flag & BONE_SELECTED) + can_delete = TRUE; + } + } + } + else { + /* object mode - all of Object's F-Curves are affected */ + can_delete = TRUE; + } + + /* delete F-Curve completely */ + if (can_delete) { + ANIM_fcurve_delete_from_animdata(NULL, adt, fcu); + } } } - BKE_reportf(op->reports, RPT_INFO, "Ob '%s' - Successfully had %d keyframes removed", id->name + 2, success); - + /* update... */ ob->recalc |= OB_RECALC_OB; } CTX_DATA_END; /* send updates */ DAG_ids_flush_update(bmain, 0); + WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL); + return OPERATOR_FINISHED; +} + +void ANIM_OT_keyframe_clear_v3d(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Animation"; + ot->description = "Remove all keyframe animation for selected objects"; + ot->idname = "ANIM_OT_keyframe_clear_v3d"; + + /* callbacks */ + ot->invoke = WM_operator_confirm; + ot->exec = clear_anim_v3d_exec; + + ot->poll = ED_operator_areaactive; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + + +static int delete_key_v3d_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + float cfra = (float)CFRA; + + CTX_DATA_BEGIN (C, Object *, ob, selected_objects) + { + ID *id = &ob->id; + int success = 0; + + /* just those in active action... */ + if ((ob->adt) && (ob->adt->action)) { + AnimData *adt = ob->adt; + bAction *act = adt->action; + FCurve *fcu, *fcn; + + for (fcu = act->curves.first; fcu; fcu = fcn) { + fcn = fcu->next; + + /* delete keyframes on current frame + * WARNING: this can delete the next F-Curve, hence the "fcn" copying + */ + success += delete_keyframe(op->reports, id, NULL, NULL, fcu->rna_path, fcu->array_index, cfra, 0); + } + } + + /* report success (or failure) */ + BKE_reportf(op->reports, RPT_INFO, "Object '%s' successfully had %d keyframes removed", id->name + 2, success); + ob->recalc |= OB_RECALC_OB; + } + CTX_DATA_END; + + /* send updates */ + DAG_ids_flush_update(bmain, 0); WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL); return OPERATOR_FINISHED; @@ -1489,7 +1571,7 @@ void ANIM_OT_keyframe_delete_v3d(wmOperatorType *ot) { /* identifiers */ ot->name = "Delete Keyframe"; - ot->description = "Remove keyframes on current frame for selected object"; + ot->description = "Remove keyframes on current frame for selected objects"; ot->idname = "ANIM_OT_keyframe_delete_v3d"; /* callbacks */ @@ -1512,7 +1594,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) PointerRNA ptr = {{NULL}}; PropertyRNA *prop = NULL; char *path; - float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap + float cfra = (float)CFRA; short success = 0; int a, index, length, all = RNA_boolean_get(op->ptr, "all"); short flag = 0; @@ -1551,7 +1633,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) else { if (G.debug & G_DEBUG) printf("Button Insert-Key: no path to property\n"); - BKE_report(op->reports, RPT_WARNING, "Failed to resolve path to property. Try using a Keying Set instead"); + BKE_report(op->reports, RPT_WARNING, "Failed to resolve path to property, try using a keying set instead"); } } else if (G.debug & G_DEBUG) { @@ -1683,20 +1765,20 @@ static int clear_key_button_exec(bContext *C, wmOperator *op) if (ptr.id.data && ptr.data && prop) { path = RNA_path_from_ID_to_property(&ptr, prop); - + if (path) { if (all) { length = RNA_property_array_length(&ptr, prop); - + if (length) index = 0; else length = 1; } else length = 1; - + for (a = 0; a < length; a++) success += clear_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, 0); - + MEM_freeN(path); } else if (G.debug & G_DEBUG) @@ -1710,9 +1792,9 @@ static int clear_key_button_exec(bContext *C, wmOperator *op) if (success) { /* send updates */ uiContextAnimUpdate(C); - + DAG_ids_flush_update(bmain, 0); - + /* send notifiers that keyframes have been changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); } @@ -1781,7 +1863,7 @@ short fcurve_frame_has_keyframe(FCurve *fcu, float frame, short filter) /* binarysearch_bezt_index will set replace to be 0 or 1 * - obviously, 1 represents a match */ - if (replace) { + if (replace) { /* sanity check: 'i' may in rare cases exceed arraylen */ if ((i >= 0) && (i < fcu->totvert)) return 1; @@ -1836,7 +1918,7 @@ static short object_frame_has_keyframe(Object *ob, float frame, short filter) /* try shapekey keyframes (if available, and allowed by filter) */ if (!(filter & ANIMFILTER_KEYS_LOCAL) && !(filter & ANIMFILTER_KEYS_NOSKEY) ) { - Key *key = ob_get_key(ob); + Key *key = BKE_key_from_object(ob); /* shapekeys can have keyframes ('Relative Shape Keys') * or depend on time (old 'Absolute Shape Keys') diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index 04fd7f677b0..ae7abd82600 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -161,11 +161,11 @@ static int remove_active_keyingset_exec(bContext *C, wmOperator *op) * - return error if it doesn't exist */ if (scene->active_keyingset == 0) { - BKE_report(op->reports, RPT_ERROR, "No active Keying Set to remove"); + BKE_report(op->reports, RPT_ERROR, "No active keying set to remove"); return OPERATOR_CANCELLED; } else if (scene->active_keyingset < 0) { - BKE_report(op->reports, RPT_ERROR, "Cannot remove built in Keying Set"); + BKE_report(op->reports, RPT_ERROR, "Cannot remove built in keying set"); return OPERATOR_CANCELLED; } else @@ -209,7 +209,7 @@ static int add_empty_ks_path_exec(bContext *C, wmOperator *op) * - return error if it doesn't exist */ if (scene->active_keyingset == 0) { - BKE_report(op->reports, RPT_ERROR, "No active Keying Set to add empty path to"); + BKE_report(op->reports, RPT_ERROR, "No active keying set to add empty path to"); return OPERATOR_CANCELLED; } else @@ -258,12 +258,12 @@ static int remove_active_ks_path_exec(bContext *C, wmOperator *op) ks->active_path--; } else { - BKE_report(op->reports, RPT_ERROR, "No active Keying Set Path to remove"); + BKE_report(op->reports, RPT_ERROR, "No active keying set path to remove"); return OPERATOR_CANCELLED; } } else { - BKE_report(op->reports, RPT_ERROR, "No active Keying Set to remove a path from"); + BKE_report(op->reports, RPT_ERROR, "No active keying set to remove a path from"); return OPERATOR_CANCELLED; } @@ -322,7 +322,7 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op) scene->active_keyingset = BLI_countlist(&scene->keyingsets); } else if (scene->active_keyingset < 0) { - BKE_report(op->reports, RPT_ERROR, "Cannot add property to built in Keying Set"); + BKE_report(op->reports, RPT_ERROR, "Cannot add property to built in keying set"); return OPERATOR_CANCELLED; } else @@ -377,7 +377,7 @@ void ANIM_OT_keyingset_button_add(wmOperatorType *ot) /* callbacks */ ot->exec = add_keyingset_button_exec; - //op->poll= ??? + //op->poll = ??? /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -404,11 +404,11 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op) * - return error if it doesn't exist */ if (scene->active_keyingset == 0) { - BKE_report(op->reports, RPT_ERROR, "No active Keying Set to remove property from"); + BKE_report(op->reports, RPT_ERROR, "No active keying set to remove property from"); return OPERATOR_CANCELLED; } else if (scene->active_keyingset < 0) { - BKE_report(op->reports, RPT_ERROR, "Cannot remove property from built in Keying Set"); + BKE_report(op->reports, RPT_ERROR, "Cannot remove property from built in keying set"); return OPERATOR_CANCELLED; } else @@ -457,7 +457,7 @@ void ANIM_OT_keyingset_button_remove(wmOperatorType *ot) /* callbacks */ ot->exec = remove_keyingset_button_exec; - //op->poll= ??? + //op->poll = ??? /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -947,7 +947,7 @@ int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSe /* skip path if no ID pointer is specified */ if (ksp->id == NULL) { BKE_reportf(reports, RPT_WARNING, - "Skipping path in Keying Set, as it has no ID (KS = '%s', Path = '%s'[%d])", + "Skipping path in keying set, as it has no ID (KS = '%s', path = '%s[%d]')", ks->name, ksp->rna_path, ksp->array_index); continue; } diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index c19904d39ac..7c5b75e56ae 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -88,7 +88,7 @@ void ED_operatortypes_armature(void) WM_operatortype_append(ARMATURE_OT_armature_layers); WM_operatortype_append(ARMATURE_OT_bone_layers); - /* SKETCH */ + /* SKETCH */ WM_operatortype_append(SKETCH_OT_gesture); WM_operatortype_append(SKETCH_OT_delete); WM_operatortype_append(SKETCH_OT_draw_stroke); @@ -221,7 +221,7 @@ void ED_keymap_armature(wmKeyConfig *keyconf) /* Already part of view3d select */ //WM_keymap_add_item(keymap, "SKETCH_OT_select", SELECTMOUSE, KM_PRESS, 0, 0); - /* sketch poll checks mode */ + /* sketch poll checks mode */ WM_keymap_add_item(keymap, "SKETCH_OT_gesture", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "SKETCH_OT_draw_stroke", LEFTMOUSE, KM_PRESS, 0, 0); kmi = WM_keymap_add_item(keymap, "SKETCH_OT_draw_stroke", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index cb52d88f985..48da23d5e8d 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -117,14 +117,14 @@ void ED_armature_sync_selection(ListBase *edbo) else ebo->flag &= ~BONE_SELECTED; } - } + } } void ED_armature_validate_active(struct bArmature *arm) { EditBone *ebone = arm->act_edbone; - if (ebone) { + if (ebone) { if (ebone->flag & BONE_HIDDEN_A) arm->act_edbone = NULL; } @@ -304,7 +304,7 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone eBone->ease2 = curBone->ease2; eBone->rad_head = curBone->rad_head; eBone->rad_tail = curBone->rad_tail; - eBone->segments = curBone->segments; + eBone->segments = curBone->segments; eBone->layer = curBone->layer; if (curBone->prop) @@ -654,17 +654,19 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op) if (ob->type != OB_ARMATURE) return OPERATOR_CANCELLED; if (BKE_object_obdata_is_libdata(ob)) { - BKE_report(op->reports, RPT_ERROR, "Cannot apply pose to lib-linked armature"); //error_libdata(); + BKE_report(op->reports, RPT_ERROR, "Cannot apply pose to lib-linked armature"); /* error_libdata(); */ return OPERATOR_CANCELLED; } /* helpful warnings... */ /* TODO: add warnings to be careful about actions, applying deforms first, etc. */ if (ob->adt && ob->adt->action) - BKE_report(op->reports, RPT_WARNING, "Actions on this armature will be destroyed by this new rest pose as the transforms stored are relative to the old rest pose"); + BKE_report(op->reports, RPT_WARNING, + "Actions on this armature will be destroyed by this new rest pose as the " + "transforms stored are relative to the old rest pose"); /* Get editbones of active armature to alter */ - ED_armature_to_edit(ob); + ED_armature_to_edit(ob); /* get pose of active object and move it out of posemode */ pose = ob->pose; @@ -895,7 +897,7 @@ static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChann /* make tar armature be new parent */ ob->parent = tarArm; } - } + } } /* join armature exec is exported for use in object->join objects operator... */ @@ -1111,7 +1113,7 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm) } } } - } + } } /* Helper function for armature separating - remove certain bones from the given armature @@ -1438,7 +1440,7 @@ static int pose_select_connected_invoke(bContext *C, wmOperator *op, wmEvent *ev /* Select parents */ for (curBone = bone; curBone; curBone = next) { /* ignore bone if cannot be selected */ - if ((curBone->flag & BONE_UNSELECTABLE) == 0) { + if ((curBone->flag & BONE_UNSELECTABLE) == 0) { // XXX old cruft! use notifiers instead //select_actionchannel_by_name (ob->action, curBone->name, !(shift)); @@ -1491,7 +1493,7 @@ void POSE_OT_select_linked(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* props */ + /* props */ RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first"); } @@ -1548,7 +1550,7 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e bone = curBone; break; } - else { + else { bone = NULL; break; } @@ -1591,7 +1593,8 @@ void ARMATURE_OT_select_linked(wmOperatorType *ot) /* does bones and points */ /* note that BONE ROOT only gets drawn for root bones (or without IK) */ -static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2], ListBase *edbo, int findunsel, int *selmask) +static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2], + ListBase *edbo, int findunsel, int *selmask) { EditBone *ebone; rcti rect; @@ -1831,7 +1834,7 @@ void ED_armature_deselect_all_visible(Object *obedit) for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { /* first and foremost, bone must be visible and selected */ - if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_UNSELECTABLE) == 0) { + if (EBONE_SELECTABLE(arm, ebone)) { ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); } } @@ -2096,7 +2099,7 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op) } sub_v3_v3v3(nor, ebone->tail, ebone->head); - vec_roll_to_mat3(nor, ebone->roll, mat); + vec_roll_to_mat3(nor, ebone->roll, mat); copy_v3_v3(vec, mat[2]); } else { /* Axis */ @@ -2556,7 +2559,8 @@ void updateDuplicateSubtarget(EditBone *dupBone, ListBase *editbones, Object *ob } -EditBone *duplicateEditBoneObjects(EditBone *curBone, const char *name, ListBase *editbones, Object *src_ob, Object *dst_ob) +EditBone *duplicateEditBoneObjects(EditBone *curBone, const char *name, ListBase *editbones, + Object *src_ob, Object *dst_ob) { EditBone *eBone = MEM_mallocN(sizeof(EditBone), "addup_editbone"); @@ -2683,7 +2687,7 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *UNUSED(op)) updateDuplicateSubtarget(eBone, arm->edbo, obedit); } } - } + } /* correct the active bone */ if (arm->act_edbone) { @@ -2798,7 +2802,7 @@ static void fill_add_joint(EditBone *ebo, short eb_tail, ListBase *points) } for (ebp = points->first; ebp; ebp = ebp->next) { - if (equals_v3v3(ebp->vec, vec)) { + if (equals_v3v3(ebp->vec, vec)) { if (eb_tail) { if ((ebp->head_owner) && (ebp->head_owner->parent == ebo)) { /* so this bone's tail owner is this bone */ @@ -2882,7 +2886,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op) mul_v3_m4v3(curs, obedit->imat, give_cursor(scene, v3d)); /* Create a bone */ - /* newbone= */ add_points_bone(obedit, ebp->vec, curs); + /* newbone = */ add_points_bone(obedit, ebp->vec, curs); } else if (count == 2) { EditBonePoint *ebp, *ebp2; @@ -2965,8 +2969,8 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op) } } else { - // FIXME.. figure out a method for multiple bones - BKE_reportf(op->reports, RPT_ERROR, "Too many points selected: %d\n", count); + /* FIXME.. figure out a method for multiple bones */ + BKE_reportf(op->reports, RPT_ERROR, "Too many points selected: %d", count); BLI_freelistN(&points); return OPERATOR_CANCELLED; } @@ -3036,7 +3040,8 @@ static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone newbone->parent = start->parent; /* TODO, copy more things to the new bone */ - newbone->flag = start->flag & (BONE_HINGE | BONE_NO_DEFORM | BONE_NO_SCALE | BONE_NO_CYCLICOFFSET | BONE_NO_LOCAL_LOCATION | BONE_DONE); + newbone->flag = start->flag & (BONE_HINGE | BONE_NO_DEFORM | BONE_NO_SCALE | + BONE_NO_CYCLICOFFSET | BONE_NO_LOCAL_LOCATION | BONE_DONE); /* step 2a: reparent any side chains which may be parented to any bone in the chain of bones to merge * - potentially several tips for side chains leading to some tree exist... @@ -3145,7 +3150,7 @@ static int armature_merge_exec(bContext *C, wmOperator *op) /* put back link */ BLI_insertlinkbefore(&chains, nchain, chain); - } + } armature_tag_unselect(arm); @@ -3296,7 +3301,9 @@ static void hide_unselected_armature_bones(Scene *scene) for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { bArmature *arm = obedit->data; if (EBONE_VISIBLE(arm, ebone)) { - if (ebone->flag & (BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL)) ; + if (ebone->flag & (BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL)) { + /* pass */ + } else { ebone->flag |= BONE_HIDDEN_A; } @@ -3357,12 +3364,17 @@ static int armature_extrude_exec(bContext *C, wmOperator *op) if (EBONE_VISIBLE(arm, ebone)) { /* we extrude per definition the tip */ do_extrude = FALSE; - if (ebone->flag & (BONE_TIPSEL | BONE_SELECTED)) + if (ebone->flag & (BONE_TIPSEL | BONE_SELECTED)) { do_extrude = TRUE; + } else if (ebone->flag & BONE_ROOTSEL) { /* but, a bone with parent deselected we do the root... */ - if (ebone->parent && (ebone->parent->flag & BONE_TIPSEL)) ; - else do_extrude = 2; + if (ebone->parent && (ebone->parent->flag & BONE_TIPSEL)) { + /* pass */ + } + else { + do_extrude = 2; + } } if (do_extrude) { @@ -3447,7 +3459,7 @@ static int armature_extrude_exec(bContext *C, wmOperator *op) /* Deselect the old bone */ ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL); - } + } } /* if only one bone, make this one active */ if (totbone == 1 && first) arm->act_edbone = first; @@ -3671,7 +3683,7 @@ static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) parent = ebo->parent; /* only if selected and editable */ - if (EBONE_VISIBLE(arm, ebo) && EBONE_EDITABLE(ebo)) { + if (EBONE_VISIBLE(arm, ebo) && EBONE_EDITABLE(ebo)) { /* swap head and tail coordinates */ SWAP(float, ebo->head[0], ebo->tail[0]); SWAP(float, ebo->head[1], ebo->tail[1]); @@ -3711,7 +3723,7 @@ static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) } /* free chains */ - BLI_freelistN(&chains); + BLI_freelistN(&chains); armature_tag_unselect(arm); @@ -3768,7 +3780,7 @@ static void bone_connect_to_new_parent(ListBase *edbo, EditBone *selbone, EditBo } } - if (mode == ARM_PAR_CONNECT) { + if (mode == ARM_PAR_CONNECT) { /* Connected: Child bones will be moved to the parent tip */ selbone->flag |= BONE_CONNECTED; sub_v3_v3v3(offset, actbone->tail, selbone->head); @@ -3813,7 +3825,7 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op) /* there must be an active bone */ if (actbone == NULL) { - BKE_report(op->reports, RPT_ERROR, "Operation requires an Active Bone"); + BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone"); return OPERATOR_CANCELLED; } else if (arm->flag & ARM_MIRROR_EDIT) { @@ -3883,7 +3895,7 @@ static int armature_parent_set_invoke(bContext *C, wmOperator *UNUSED(op), wmEve { if (ebone != actbone) { if (ebone->parent != actbone) allchildbones = 1; - } + } } CTX_DATA_END; @@ -3891,7 +3903,7 @@ static int armature_parent_set_invoke(bContext *C, wmOperator *UNUSED(op), wmEve /* ob becomes parent, make the associated menus */ if (allchildbones) - uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_OFFSET); + uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_OFFSET); uiPupMenuEnd(C, pup); @@ -3984,7 +3996,7 @@ static int armature_select_inverse_exec(bContext *C, wmOperator *UNUSED(op)) ebone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); } } - CTX_DATA_END; + CTX_DATA_END; WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL); @@ -4045,7 +4057,7 @@ static int armature_de_select_all_exec(bContext *C, wmOperator *op) } } } - CTX_DATA_END; + CTX_DATA_END; WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL); @@ -4106,7 +4118,7 @@ static void select_similar_length(bArmature *arm, EditBone *ebone_act, const flo const float len_max = ebone_act->length * (1.0f + thresh); for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { - if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_UNSELECTABLE) == 0) { + if (EBONE_SELECTABLE(arm, ebone)) { if ((ebone->length >= len_min) && (ebone->length <= len_max)) { @@ -4123,7 +4135,7 @@ static void select_similar_direction(bArmature *arm, EditBone *ebone_act, const sub_v3_v3v3(dir_act, ebone_act->head, ebone_act->tail); for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { - if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_UNSELECTABLE) == 0) { + if (EBONE_SELECTABLE(arm, ebone)) { float dir[3]; sub_v3_v3v3(dir, ebone->head, ebone->tail); @@ -4139,7 +4151,7 @@ static void select_similar_layer(bArmature *arm, EditBone *ebone_act) EditBone *ebone; for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { - if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_UNSELECTABLE) == 0) { + if (EBONE_SELECTABLE(arm, ebone)) { if (ebone->layer & ebone_act->layer) { ED_armature_edit_bone_select(ebone); } @@ -4161,7 +4173,7 @@ static void select_similar_prefix(bArmature *arm, EditBone *ebone_act) /* Find matches */ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { - if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_UNSELECTABLE) == 0) { + if (EBONE_SELECTABLE(arm, ebone)) { char prefix_other[MAX_VGROUP_NAME]; BKE_deform_split_prefix(ebone->name, prefix_other, body_tmp); if (!strcmp(prefix_act, prefix_other)) { @@ -4185,7 +4197,7 @@ static void select_similar_suffix(bArmature *arm, EditBone *ebone_act) /* Find matches */ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { - if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_UNSELECTABLE) == 0) { + if (EBONE_SELECTABLE(arm, ebone)) { char suffix_other[MAX_VGROUP_NAME]; BKE_deform_split_suffix(ebone->name, body_tmp, suffix_other); if (!strcmp(suffix_act, suffix_other)) { @@ -4207,7 +4219,7 @@ static int armature_select_similar_exec(bContext *C, wmOperator *op) /* Check for active bone */ if (ebone_act == NULL) { - BKE_report(op->reports, RPT_ERROR, "Operation requires an Active Bone"); + BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone"); return OPERATOR_CANCELLED; } @@ -4270,7 +4282,7 @@ static int armature_select_hierarchy_exec(bContext *C, wmOperator *op) for (curbone = arm->edbo->first; curbone; curbone = curbone->next) { /* only work on bone if it is visible and its selection can change */ - if (EBONE_VISIBLE(arm, curbone) && (curbone->flag & BONE_UNSELECTABLE) == 0) { + if (EBONE_SELECTABLE(arm, curbone)) { if (curbone == arm->act_edbone) { if (direction == BONE_SELECT_PARENT) { if (curbone->parent == NULL) continue; @@ -4285,12 +4297,12 @@ static int armature_select_hierarchy_exec(bContext *C, wmOperator *op) break; } - } + } else { // BONE_SELECT_CHILD chbone = editbone_get_child(arm, curbone, 1); if (chbone == NULL) continue; - if (EBONE_VISIBLE(arm, chbone) && (chbone->flag & BONE_UNSELECTABLE) == 0) { + if (EBONE_SELECTABLE(arm, chbone)) { chbone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); arm->act_edbone = chbone; @@ -4399,7 +4411,7 @@ static int armature_align_bones_exec(bContext *C, wmOperator *op) /* there must be an active bone */ if (actbone == NULL) { - BKE_report(op->reports, RPT_ERROR, "Operation requires an Active Bone"); + BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone"); return OPERATOR_CANCELLED; } else if (arm->flag & ARM_MIRROR_EDIT) { @@ -4476,7 +4488,8 @@ void ARMATURE_OT_align(wmOperatorType *ot) /* ***************** Pose tools ********************* */ -// XXX bone_looper is only to be used when we want to access settings (i.e. editability/visibility/selected) that context doesn't offer +/* XXX bone_looper is only to be used when we want to access settings + * (i.e. editability/visibility/selected) that context doesn't offer */ static int bone_looper(Object *ob, Bone *bone, void *data, int (*bone_func)(Object *, Bone *, void *)) { @@ -4506,7 +4519,8 @@ static int bone_looper(Object *ob, Bone *bone, void *data, /* called from editview.c, for mode-less pose selection */ /* assumes scene obact and basact is still on old situation */ -int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short extend, short deselect, short toggle) +int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, + short extend, short deselect, short toggle) { Object *ob = base->object; Bone *nearBone; @@ -4554,7 +4568,7 @@ int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, shor nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); arm->act_bone = nearBone; } - } + } } if (ob_act) { @@ -4752,7 +4766,9 @@ static void add_vgroups__mapFunc(void *userData, int index, const float co[3], copy_v3_v3(verts[index], co); } -static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], int numbones, Bone **bonelist, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float (*root)[3], float (*tip)[3], int *selected, float scale) +static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], int numbones, Bone **bonelist, + bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, + float (*root)[3], float (*tip)[3], int *selected, float scale) { /* Create vertex group weights from envelopes */ @@ -4842,7 +4858,7 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob, bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb); /* create an array of pointers to the deform groups that - * coorespond to the skinnable bones (creating them + * correspond to the skinnable bones (creating them * as necessary. */ dgrouplist = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgrouplist"); dgroupflip = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgroupflip"); @@ -5104,7 +5120,7 @@ static void pchan_clear_rot(bPoseChannel *pchan) } } } /* Duplicated in source/blender/editors/object/object_transform.c */ - else { + else { if (pchan->rotmode == ROT_MODE_QUAT) { unit_qt(pchan->quat); } @@ -5138,7 +5154,7 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op, /* sanity checks */ if (ELEM(NULL, clear_func, default_ksName)) { - BKE_report(op->reports, RPT_ERROR, "Programming error: missing clear transform func or Keying Set Name"); + BKE_report(op->reports, RPT_ERROR, "Programming error: missing clear transform function or keying set name"); return OPERATOR_CANCELLED; } @@ -5530,7 +5546,7 @@ static void constraint_bone_name_fix(Object *ob, ListBase *conlist, char *oldnam if (cti->flush_constraint_targets) cti->flush_constraint_targets(curcon, &targets, 0); - } + } } } @@ -5617,7 +5633,7 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n } } - if (modifiers_usesArmature(ob, arm)) { + if (modifiers_usesArmature(ob, arm)) { bDeformGroup *dg = defgroup_find_name(ob, oldname); if (dg) { BLI_strncpy(dg->name, newname, MAXBONENAME); @@ -5945,7 +5961,7 @@ float arcLengthRatio(ReebArc *arc) embedLength = arcLength; } - return embedLength / arcLength; + return embedLength / arcLength; } EditBone *test_subdivideByLength(Scene *scene, Object *obedit, ReebArc *arc, ReebNode *head, ReebNode *tail) @@ -6046,7 +6062,7 @@ void generateSkeletonFromReebGraph(Scene *scene, ReebGraph *rg) arc->flag = 1; /* mark arc direction */ } - /* Loop over subdivision methods */ + /* Loop over subdivision methods */ for (i = 0; lastBone == NULL && i < SKGEN_SUB_TOTAL; i++) { switch (scene->toolsettings->skgen_subdivisions[i]) { case SKGEN_SUB_LENGTH: diff --git a/source/blender/editors/armature/editarmature_generate.c b/source/blender/editors/armature/editarmature_generate.c index 23dd3b15476..d9c7e78c01e 100644 --- a/source/blender/editors/armature/editarmature_generate.c +++ b/source/blender/editors/armature/editarmature_generate.c @@ -55,7 +55,7 @@ void setBoneRollFromNormal(EditBone *bone, const float no[3], float UNUSED(invma if (no != NULL && !is_zero_v3(no)) { float normal[3]; - copy_v3_v3(normal, no); + copy_v3_v3(normal, no); mul_m3_v3(tmat, normal); bone->roll = ED_rollBoneToVector(bone, normal, FALSE); diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c index fad06f0d020..68cfc7fb8c0 100644 --- a/source/blender/editors/armature/editarmature_retarget.c +++ b/source/blender/editors/armature/editarmature_retarget.c @@ -191,7 +191,7 @@ static float rollBoneByQuatJoint(RigEdge *edge, RigEdge *previous, float qrot[4] if (previous->bone) { sub_v3_v3v3(vec_first, previous->bone->tail, previous->bone->head); - } + } else if (previous->prev->bone) { sub_v3_v3v3(vec_first, edge->bone->head, previous->prev->bone->tail); } @@ -653,7 +653,7 @@ static int RIG_parentControl(RigControl *ctrl, EditBone *link) sub_v3_v3v3(offset, ctrl->bone->head, link->head); - /* if root matches, check for direction too */ + /* if root matches, check for direction too */ if (dot_v3v3(offset, offset) < 0.0001f) { float vbone[3], vparent[3]; @@ -802,7 +802,7 @@ static void RIG_reconnectControlBones(RigGraph *rg) } } - /* if not found yet, check child */ + /* if not found yet, check child */ if (found == 0) { RigArc *arc; RigArc *best_arc = NULL; @@ -863,7 +863,7 @@ static void RIG_reconnectControlBones(RigGraph *rg) /* SET bone link to ctrl corresponding to pchan */ RigControl *link = BLI_ghash_lookup(rg->controls_map, pchan->name); - /* if owner is a control bone, link with it */ + /* if owner is a control bone, link with it */ if (link && link->link) { RIG_parentControl(ctrl, link->bone); found = 1; @@ -876,7 +876,7 @@ static void RIG_reconnectControlBones(RigGraph *rg) cti->flush_constraint_targets(con, &targets, 0); } } - } + } if (found == 0) { /* check if parent is already linked */ @@ -1319,12 +1319,12 @@ void RIG_printArc(RigGraph *rg, RigArc *arc) for (edge = arc->edges.first; edge; edge = edge->next) { printf("\tinner joints %0.3f %0.3f %0.3f\n", edge->tail[0], edge->tail[1], edge->tail[2]); printf("\t\tlength %f\n", edge->length); - printf("\t\tangle %f\n", edge->angle * 180 / M_PI); + printf("\t\tangle %f\n", edge->angle * (float)(180 / M_PI)); if (edge->bone) { printf("\t\t%s\n", edge->bone->name); RIG_printLinkedCtrl(rg, edge->bone, 3); } - } + } printf("symmetry level: %i flag: %i group %i\n", arc->symmetry_level, arc->symmetry_flag, arc->symmetry_group); RIG_printNode((RigNode *)arc->tail, "tail"); @@ -1336,7 +1336,7 @@ void RIG_printGraph(RigGraph *rg) printf("---- ARCS ----\n"); for (arc = rg->arcs.first; arc; arc = arc->next) { - RIG_printArc(rg, arc); + RIG_printArc(rg, arc); printf("\n"); } @@ -1345,7 +1345,7 @@ void RIG_printGraph(RigGraph *rg) } else { printf("HEAD NODE: NONE\n"); - } + } } /*******************************************************************************************************/ @@ -1584,7 +1584,7 @@ static void finalizeControl(RigGraph *rigg, RigControl *ctrl, float resize) repositionTailControl(rigg, ctrl_child); } } - } + } } static void repositionTailControl(RigGraph *rigg, RigControl *ctrl) @@ -1840,7 +1840,7 @@ static float calcCostAngleLengthDistance(BArcIterator *iter, float **UNUSED(vec_ length2 = normalize_v3(vec_second); - /* Angle cost */ + /* Angle cost */ if (edge->prev) { sub_v3_v3v3(vec_first, vec1, vec0); normalize_v3(vec_first); @@ -1962,7 +1962,6 @@ static void retargetArctoArcAggresive(bContext *C, RigGraph *rigg, RigArc *iarc, ReebArcIterator arc_iter; BArcIterator *iter = (BArcIterator *)&arc_iter; RigEdge *edge; - EmbedBucket *bucket = NULL; ReebNode *node_start, *node_end; ReebArc *earc = iarc->link_mesh; float angle_weight = 1.0; // GET FROM CONTEXT @@ -1996,8 +1995,6 @@ static void retargetArctoArcAggresive(bContext *C, RigGraph *rigg, RigArc *iarc, /* equal number of joints and potential position, just fill them in */ if (nb_joints == earc->bcount) { - int i; - /* init with first values */ for (i = 0; i < nb_joints; i++) { best_positions[i] = i + 1; @@ -2011,7 +2008,6 @@ static void retargetArctoArcAggresive(bContext *C, RigGraph *rigg, RigArc *iarc, MemoNode *result; #endif float **positions_cache = MEM_callocN(sizeof(float *) * (nb_positions + 2), "positions cache"); - int i; positions_cache[0] = node_start->p; positions_cache[nb_positions + 1] = node_end->p; @@ -2053,7 +2049,7 @@ static void retargetArctoArcAggresive(bContext *C, RigGraph *rigg, RigArc *iarc, { float *no = NULL; if (i < nb_joints) { - bucket = IT_peek(iter, best_positions[i]); + EmbedBucket *bucket = IT_peek(iter, best_positions[i]); vec1 = bucket->p; no = bucket->no; } @@ -2139,7 +2135,7 @@ static void retargetArctoArcLength(bContext *C, RigGraph *rigg, RigArc *iarc, Ri no = node_end->no; } - /* no need to move virtual edges (space between unconnected bones) */ + /* no need to move virtual edges (space between unconnected bones) */ if (edge->bone) { repositionBone(C, rigg, edge, vec0, vec1, no); } @@ -2177,7 +2173,7 @@ void *exec_retargetArctoArc(void *param) RetargetParam *p = (RetargetParam *)param; RigGraph *rigg = p->rigg; RigArc *iarc = p->iarc; - bContext *C = p->context; + bContext *C = p->context; RigNode *inode_start = p->inode_start; ReebArc *earc = iarc->link_mesh; @@ -2226,7 +2222,7 @@ static void matchMultiResolutionNode(RigGraph *rigg, RigNode *inode, ReebNode *t enode = enode->link_down; reebg = BIF_graphForMultiNode(rigg->link_mesh, enode); /* replace with call to link_down once that exists */ eshape = BLI_subtreeShape((BGraph *)reebg, (BNode *)enode, NULL, 0) % SHAPE_LEVELS; - } + } } static void markMultiResolutionChildArc(ReebNode *end_enode, ReebNode *enode) @@ -2277,7 +2273,7 @@ static void matchMultiResolutionArc(RigGraph *rigg, RigNode *start_node, RigArc reebg = reebg->link_up; enode = next_earc->head; eshape = BLI_subtreeShape((BGraph *)reebg, (BNode *)enode, (BArc *)next_earc, 1) % SHAPE_LEVELS; - } + } next_earc->flag = ARC_USED; next_iarc->link_mesh = next_earc; @@ -2307,7 +2303,7 @@ static void matchMultiResolutionStartingNode(RigGraph *rigg, ReebGraph *reebg, R enode = reebg->nodes.first; eshape = BLI_subtreeShape((BGraph *)reebg, (BNode *)enode, NULL, 0) % SHAPE_LEVELS; - } + } inode->link_mesh = enode; } @@ -2604,7 +2600,7 @@ void BIF_retargetArmature(bContext *C) ED_undo_push(C, "Retarget Skeleton"); - // XXX + // XXX // allqueue(REDRAWVIEW3D, 0); } diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c index 78d3d8dc64d..da8fc328343 100644 --- a/source/blender/editors/armature/editarmature_sketch.c +++ b/source/blender/editors/armature/editarmature_sketch.c @@ -41,6 +41,8 @@ #include "BLI_graph.h" #include "BLI_ghash.h" +#include "BLF_translation.h" + #include "BKE_context.h" #include "BKE_sketch.h" @@ -175,7 +177,7 @@ void BIF_makeListTemplates(const bContext *C) const char *BIF_listTemplates(const bContext *UNUSED(C)) { GHashIterator ghi; - char menu_header[] = "Template%t|None%x0|"; + const char *menu_header = IFACE_("Template %t|None %x0|"); char *p; if (TEMPLATES_MENU != NULL) { @@ -194,7 +196,7 @@ const char *BIF_listTemplates(const bContext *UNUSED(C)) Object *ob = BLI_ghashIterator_getValue(&ghi); int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi)); - p += sprintf(p, "|%s%%x%i", ob->id.name + 2, key); + p += sprintf(p, "|%s %%x%i", ob->id.name + 2, key); BLI_ghashIterator_step(&ghi); } @@ -438,7 +440,7 @@ static void sk_cancelStroke(SK_Sketch *sketch) static float sk_clampPointSize(SK_Point *pt, float size) { - return MAX2(size * pt->size, size / 2); + return max_ff(size * pt->size, size / 2); } static void sk_drawPoint(GLUquadric *quad, SK_Point *pt, float size) @@ -644,16 +646,17 @@ static SK_Point *sk_snapPointStroke(bContext *C, SK_Stroke *stk, int mval[2], in short pval[2]; int pdist; - project_short_noclip(ar, stk->points[i].p, pval); + if (ED_view3d_project_short_global(ar, stk->points[i].p, pval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]); + pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]); - if (pdist < *dist) { - *dist = pdist; - pt = stk->points + i; + if (pdist < *dist) { + *dist = pdist; + pt = stk->points + i; - if (index != NULL) { - *index = i; + if (index != NULL) { + *index = i; + } } } } @@ -679,7 +682,24 @@ static SK_Point *sk_snapPointArmature(bContext *C, Object *ob, ListBase *ebones, { copy_v3_v3(vec, bone->head); mul_m4_v3(ob->obmat, vec); - project_short_noclip(ar, vec, pval); + if (ED_view3d_project_short_noclip(ar, vec, pval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + + pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]); + + if (pdist < *dist) + { + *dist = pdist; + pt = &boneSnap; + copy_v3_v3(pt->p, vec); + pt->type = PT_EXACT; + } + } + } + + + copy_v3_v3(vec, bone->tail); + mul_m4_v3(ob->obmat, vec); + if (ED_view3d_project_short_noclip(ar, vec, pval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]); @@ -691,21 +711,6 @@ static SK_Point *sk_snapPointArmature(bContext *C, Object *ob, ListBase *ebones, pt->type = PT_EXACT; } } - - - copy_v3_v3(vec, bone->tail); - mul_m4_v3(ob->obmat, vec); - project_short_noclip(ar, vec, pval); - - pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]); - - if (pdist < *dist) - { - *dist = pdist; - pt = &boneSnap; - copy_v3_v3(pt->p, vec); - pt->type = PT_EXACT; - } } return pt; @@ -905,9 +910,9 @@ static void sk_interpolateDepth(bContext *C, SK_Stroke *stk, int start, int end, for (i = start; i <= end; i++) { float ray_start[3], ray_normal[3]; float delta = len_v3v3(stk->points[i].p, stk->points[i + 1].p); - float pval[2]; + float pval[2] = {0, 0}; - project_float(ar, stk->points[i].p, pval); + ED_view3d_project_float_global(ar, stk->points[i].p, pval, V3D_PROJ_TEST_NOP); ED_view3d_win_to_ray(ar, v3d, pval, ray_start, ray_normal); mul_v3_fl(ray_normal, distance * progress / length); @@ -934,10 +939,14 @@ static void sk_projectDrawPoint(bContext *C, float vec[3], SK_Stroke *stk, SK_Dr initgrabz(ar->regiondata, fp[0], fp[1], fp[2]); /* method taken from editview.c - mouse_cursor() */ - project_short_noclip(ar, fp, cval); - VECSUB2D(mval_f, cval, dd->mval); - ED_view3d_win_to_delta(ar, mval_f, dvec); - sub_v3_v3v3(vec, fp, dvec); + if (ED_view3d_project_short_global(ar, fp, cval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + VECSUB2D(mval_f, cval, dd->mval); + ED_view3d_win_to_delta(ar, mval_f, dvec); + sub_v3_v3v3(vec, fp, dvec); + } + else { + zero_v3(vec); + } } static int sk_getStrokeDrawPoint(bContext *C, SK_Point *pt, SK_Sketch *UNUSED(sketch), SK_Stroke *stk, SK_DrawData *dd) @@ -1453,8 +1462,8 @@ static int sk_getSelfIntersections(bContext *C, ListBase *list, SK_Stroke *gestu float s_p2[3] = {0, 0, 0}; int g_i; - project_float(ar, gesture->points[s_i].p, s_p1); - project_float(ar, gesture->points[s_i + 1].p, s_p2); + ED_view3d_project_float_global(ar, gesture->points[s_i].p, s_p1, V3D_PROJ_TEST_NOP); + ED_view3d_project_float_global(ar, gesture->points[s_i + 1].p, s_p2, V3D_PROJ_TEST_NOP); /* start checking from second next, because two consecutive cannot intersect */ for (g_i = s_i + 2; g_i < gesture->nb_points - 1; g_i++) { @@ -1463,8 +1472,8 @@ static int sk_getSelfIntersections(bContext *C, ListBase *list, SK_Stroke *gestu float vi[3]; float lambda; - project_float(ar, gesture->points[g_i].p, g_p1); - project_float(ar, gesture->points[g_i + 1].p, g_p2); + ED_view3d_project_float_global(ar, gesture->points[g_i].p, g_p1, V3D_PROJ_TEST_NOP); + ED_view3d_project_float_global(ar, gesture->points[g_i + 1].p, g_p2, V3D_PROJ_TEST_NOP); if (isect_line_line_strict_v3(s_p1, s_p2, g_p1, g_p2, vi, &lambda)) { SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection"); @@ -1531,8 +1540,8 @@ static int sk_getIntersections(bContext *C, ListBase *list, SK_Sketch *sketch, S float s_p2[3] = {0, 0, 0}; int g_i; - project_float(ar, stk->points[s_i].p, s_p1); - project_float(ar, stk->points[s_i + 1].p, s_p2); + ED_view3d_project_float_global(ar, stk->points[s_i].p, s_p1, V3D_PROJ_TEST_NOP); + ED_view3d_project_float_global(ar, stk->points[s_i + 1].p, s_p2, V3D_PROJ_TEST_NOP); for (g_i = 0; g_i < gesture->nb_points - 1; g_i++) { float g_p1[3] = {0, 0, 0}; @@ -1540,8 +1549,8 @@ static int sk_getIntersections(bContext *C, ListBase *list, SK_Sketch *sketch, S float vi[3]; float lambda; - project_float(ar, gesture->points[g_i].p, g_p1); - project_float(ar, gesture->points[g_i + 1].p, g_p2); + ED_view3d_project_float_global(ar, gesture->points[g_i].p, g_p1, V3D_PROJ_TEST_NOP); + ED_view3d_project_float_global(ar, gesture->points[g_i + 1].p, g_p2, V3D_PROJ_TEST_NOP); if (isect_line_line_strict_v3(s_p1, s_p2, g_p1, g_p2, vi, &lambda)) { SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection"); @@ -1717,8 +1726,8 @@ void sk_applyCommandGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UN SK_Intersection *isect; int command = 1; -// XXX -// command = pupmenu("Action %t|Flatten %x1|Straighten %x2|Polygonize %x3"); +/* XXX */ +/* command = pupmenu("Action %t|Flatten %x1|Straighten %x2|Polygonize %x3"); */ if (command < 1) return; for (isect = gest->intersections.first; isect; isect = isect->next) { @@ -1784,33 +1793,35 @@ int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *UNUSED(sketc short start_val[2], end_val[2]; short dist; - project_short_noclip(ar, gest->stk->points[0].p, start_val); - project_short_noclip(ar, sk_lastStrokePoint(gest->stk)->p, end_val); + if ((ED_view3d_project_short_global(ar, gest->stk->points[0].p, start_val, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) && + (ED_view3d_project_short_global(ar, sk_lastStrokePoint(gest->stk)->p, end_val, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK)) + { - dist = MAX2(ABS(start_val[0] - end_val[0]), ABS(start_val[1] - end_val[1])); + dist = MAX2(ABS(start_val[0] - end_val[0]), ABS(start_val[1] - end_val[1])); - /* if gesture is a circle */ - if (dist <= 20) { - SK_Intersection *isect; + /* if gesture is a circle */ + if (dist <= 20) { + SK_Intersection *isect; - /* check if it circled around an exact point */ - for (isect = gest->intersections.first; isect; isect = isect->next) { - /* only delete strokes that are crossed twice */ - if (isect->next && isect->next->stroke == isect->stroke) { - int start_index, end_index; - int i; + /* check if it circled around an exact point */ + for (isect = gest->intersections.first; isect; isect = isect->next) { + /* only delete strokes that are crossed twice */ + if (isect->next && isect->next->stroke == isect->stroke) { + int start_index, end_index; + int i; - start_index = MIN2(isect->after, isect->next->after); - end_index = MAX2(isect->before, isect->next->before); + start_index = MIN2(isect->after, isect->next->after); + end_index = MAX2(isect->before, isect->next->before); - for (i = start_index; i <= end_index; i++) { - if (isect->stroke->points[i].type == PT_EXACT) { - return 1; /* at least one exact point found, stop detect here */ + for (i = start_index; i <= end_index; i++) { + if (isect->stroke->points[i].type == PT_EXACT) { + return 1; /* at least one exact point found, stop detect here */ + } } - } - /* skip next */ - isect = isect->next; + /* skip next */ + isect = isect->next; + } } } } diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 346ed0002bd..9152ea8e198 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -53,7 +53,6 @@ #include "BKE_modifier.h" #include "BKE_mesh.h" - #ifdef RIGID_DEFORM #include "BLI_polardecomp.h" #endif @@ -563,7 +562,7 @@ static void heat_set_H(LaplacianSystem *sys, int vertex) /* compute H entry */ if (numclosest > 0) { - mindist = maxf(mindist, 1e-4f); + mindist = max_ff(mindist, 1e-4f); h = numclosest * C_WEIGHT / (mindist * mindist); } else @@ -794,7 +793,7 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource, } } else if (*err_str == NULL) { - *err_str = "Bone Heat Weighting: failed to find solution for one or more bones"; + *err_str = N_("Bone Heat Weighting: failed to find solution for one or more bones"); break; } @@ -1113,6 +1112,9 @@ typedef struct MeshDeformBind { /* direct solver */ int *varidx; + + BVHTree *bvhtree; + BVHTreeFromMesh bvhdata; } MeshDeformBind; typedef struct MeshDeformIsect { @@ -1130,8 +1132,9 @@ typedef struct MeshDeformIsect { /* our own triangle intersection, so we can fully control the epsilons and * prevent corner case from going wrong*/ -static int meshdeform_tri_intersect(float orig[3], float end[3], float vert0[3], - float vert1[3], float vert2[3], float *isectco, float *uvw) +static int meshdeform_tri_intersect(const float orig[3], const float end[3], const float vert0[3], + const float vert1[3], const float vert2[3], + float r_isectco[3], float r_uvw[3]) { float edge1[3], edge2[3], tvec[3], pvec[3], qvec[3]; float det, inv_det, u, v, dir[3], isectdir[3]; @@ -1148,8 +1151,10 @@ static int meshdeform_tri_intersect(float orig[3], float end[3], float vert0[3], /* if determinant is near zero, ray lies in plane of triangle */ det = dot_v3v3(edge1, pvec); - if (det == 0.0f) + if (UNLIKELY(det == 0.0f)) { return 0; + } + inv_det = 1.0f / det; /* calculate distance from vert0 to ray origin */ @@ -1168,16 +1173,16 @@ static int meshdeform_tri_intersect(float orig[3], float end[3], float vert0[3], if (v < -EPSILON || u + v > 1.0f + EPSILON) return 0; - isectco[0] = (1.0f - u - v) * vert0[0] + u * vert1[0] + v * vert2[0]; - isectco[1] = (1.0f - u - v) * vert0[1] + u * vert1[1] + v * vert2[1]; - isectco[2] = (1.0f - u - v) * vert0[2] + u * vert1[2] + v * vert2[2]; + r_isectco[0] = (1.0f - u - v) * vert0[0] + u * vert1[0] + v * vert2[0]; + r_isectco[1] = (1.0f - u - v) * vert0[1] + u * vert1[1] + v * vert2[1]; + r_isectco[2] = (1.0f - u - v) * vert0[2] + u * vert1[2] + v * vert2[2]; - uvw[0] = 1.0f - u - v; - uvw[1] = u; - uvw[2] = v; + r_uvw[0] = 1.0f - u - v; + r_uvw[1] = u; + r_uvw[2] = v; /* check if it is within the length of the line segment */ - sub_v3_v3v3(isectdir, isectco, orig); + sub_v3_v3v3(isectdir, r_isectco, orig); if (dot_v3v3(dir, isectdir) < -EPSILON) return 0; @@ -1188,83 +1193,79 @@ static int meshdeform_tri_intersect(float orig[3], float end[3], float vert0[3], return 1; } -static int meshdeform_intersect(MeshDeformBind *mdb, MeshDeformIsect *isec) +static void harmonic_ray_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) { - MFace *mface; - float face[4][3], co[3], uvw[3], len, nor[3], end[3]; - int f, hit, is = 0, totface; - - isec->labda = 1e10; - - mface = mdb->cagedm->getTessFaceArray(mdb->cagedm); - totface = mdb->cagedm->getNumTessFaces(mdb->cagedm); - + void **data = userdata; + MeshDeformBind *mdb = data[1]; + MFace *mface = data[0], *mf; + MeshDeformIsect *isec = data[2]; + float no[3], co[3], end[3], uvw[3], dist, face[4][3]; + + mf = mface + index; + + copy_v3_v3(face[0], mdb->cagecos[mf->v1]); + copy_v3_v3(face[1], mdb->cagecos[mf->v2]); + copy_v3_v3(face[2], mdb->cagecos[mf->v3]); + if (mf->v4) + copy_v3_v3(face[3], mdb->cagecos[mf->v4]); + add_v3_v3v3(end, isec->start, isec->vec); - - for (f = 0; f < totface; f++, mface++) { - copy_v3_v3(face[0], mdb->cagecos[mface->v1]); - copy_v3_v3(face[1], mdb->cagecos[mface->v2]); - copy_v3_v3(face[2], mdb->cagecos[mface->v3]); - - if (mface->v4) { - copy_v3_v3(face[3], mdb->cagecos[mface->v4]); - hit = meshdeform_tri_intersect(isec->start, end, face[0], face[1], face[2], co, uvw); - - if (hit) { - normal_tri_v3(nor, face[0], face[1], face[2]); - } - else { - hit = meshdeform_tri_intersect(isec->start, end, face[0], face[2], face[3], co, uvw); - normal_tri_v3(nor, face[0], face[2], face[3]); - } - } - else { - hit = meshdeform_tri_intersect(isec->start, end, face[0], face[1], face[2], co, uvw); - normal_tri_v3(nor, face[0], face[1], face[2]); - } - - if (hit) { - len = len_v3v3(isec->start, co) / len_v3v3(isec->start, end); - if (len < isec->labda) { - isec->labda = len; - isec->face = mface; - isec->isect = (dot_v3v3(isec->vec, nor) <= 0.0f); - is = 1; - } - } + + if (!meshdeform_tri_intersect(ray->origin, end, face[0], face[1], face[2], co, uvw)) + if (!mf->v4 || !meshdeform_tri_intersect(ray->origin, end, face[0], face[2], face[3], co, uvw)) + return; + + if (!mf->v4) + normal_tri_v3(no, face[0], face[1], face[2]); + else + normal_quad_v3(no, face[0], face[1], face[2], face[3]); + + dist = len_v3v3(ray->origin, co) / len_v3(isec->vec); + if (dist < hit->dist) { + hit->index = index; + hit->dist = dist; + copy_v3_v3(hit->co, co); + + isec->isect = (dot_v3v3(no, ray->direction) <= 0.0f); + isec->labda = dist; + isec->face = mf; } - - return is; } static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, float *co1, float *co2) { MDefBoundIsect *isect; - MeshDeformIsect isec; + BVHTreeRayHit hit; + MeshDeformIsect isect_mdef; float (*cagecos)[3]; - MFace *mface; + void *data[3] = {mdb->cagedm->getTessFaceArray(mdb->cagedm), mdb, &isect_mdef}; + MFace *mface1 = data[0], *mface; float vert[4][3], len, end[3]; static float epsilon[3] = {0, 0, 0}; //1e-4, 1e-4, 1e-4}; /* setup isec */ - memset(&isec, 0, sizeof(isec)); - isec.labda = 1e10f; + memset(&isect_mdef, 0, sizeof(isect_mdef)); + isect_mdef.labda = 1e10f; - add_v3_v3v3(isec.start, co1, epsilon); + add_v3_v3v3(isect_mdef.start, co1, epsilon); add_v3_v3v3(end, co2, epsilon); - sub_v3_v3v3(isec.vec, end, isec.start); + sub_v3_v3v3(isect_mdef.vec, end, isect_mdef.start); - if (meshdeform_intersect(mdb, &isec)) { - len = isec.labda; - mface = (MFace *)isec.face; + hit.index = -1; + hit.dist = FLT_MAX; + if (BLI_bvhtree_ray_cast(mdb->bvhtree, isect_mdef.start, isect_mdef.vec, + 0.0, &hit, harmonic_ray_callback, data) != -1) + { + len = isect_mdef.labda; + isect_mdef.face = mface = mface1 + hit.index; /* create MDefBoundIsect */ isect = BLI_memarena_alloc(mdb->memarena, sizeof(*isect)); /* compute intersection coordinate */ - isect->co[0] = co1[0] + isec.vec[0] * len; - isect->co[1] = co1[1] + isec.vec[1] * len; - isect->co[2] = co1[2] + isec.vec[2] * len; + isect->co[0] = co1[0] + isect_mdef.vec[0] * len; + isect->co[1] = co1[1] + isect_mdef.vec[1] * len; + isect->co[2] = co1[2] + isect_mdef.vec[2] * len; isect->len = len_v3v3(co1, isect->co); if (isect->len < MESHDEFORM_LEN_THRESHOLD) @@ -1276,7 +1277,7 @@ static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, float isect->v[3] = mface->v4; isect->nvert = (mface->v4) ? 4 : 3; - isect->facing = isec.isect; + isect->facing = isect_mdef.isect; /* compute mean value coordinates for interpolation */ cagecos = mdb->cagecos; @@ -1720,7 +1721,7 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind } } else { - modifier_setError(&mmd->modifier, "%s", TIP_("Failed to find bind solution (increase precision?).")); + modifier_setError(&mmd->modifier, "Failed to find bind solution (increase precision?)"); error("Mesh Deform: failed to find bind solution."); break; } @@ -1766,7 +1767,7 @@ static void harmonic_coordinates_bind(Scene *UNUSED(scene), MeshDeformModifierDa mdb->totalphi = MEM_callocN(sizeof(float) * mdb->size3, "MeshDeformBindTotalPhi"); mdb->boundisect = MEM_callocN(sizeof(*mdb->boundisect) * mdb->size3, "MDefBoundIsect"); mdb->semibound = MEM_callocN(sizeof(int) * mdb->size3, "MDefSemiBound"); - + mdb->bvhtree = bvhtree_from_mesh_faces(&mdb->bvhdata, mdb->cagedm, FLT_EPSILON*100, 4, 6); mdb->inside = MEM_callocN(sizeof(int) * mdb->totvert, "MDefInside"); if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) @@ -1882,6 +1883,7 @@ static void harmonic_coordinates_bind(Scene *UNUSED(scene), MeshDeformModifierDa MEM_freeN(mdb->boundisect); MEM_freeN(mdb->semibound); BLI_memarena_free(mdb->memarena); + free_bvhtree_from_mesh(&mdb->bvhdata); } #if 0 diff --git a/source/blender/editors/armature/poseSlide.c b/source/blender/editors/armature/poseSlide.c index cdcb3ab4683..3fd65de6c04 100644 --- a/source/blender/editors/armature/poseSlide.c +++ b/source/blender/editors/armature/poseSlide.c @@ -105,7 +105,7 @@ typedef struct tPoseSlideOp { int nextFrame; /* frame after current frame (blend-to) */ int mode; /* sliding mode (ePoseSlide_Modes) */ - int flag; // unused for now, but can later get used for storing runtime settings.... + int flag; /* unused for now, but can later get used for storing runtime settings.... */ float percentage; /* 0-1 value for determining the influence of whatever is relevant */ } tPoseSlideOp; @@ -486,7 +486,7 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso) pose_slide_apply_vec3(pso, pfl, pchan->eul, "rotation_euler"); } else if (pchan->rotmode == ROT_MODE_AXISANGLE) { - // TODO: need to figure out how to do this! + /* TODO: need to figure out how to do this! */ } else { /* quaternions - use quaternion blending */ @@ -538,7 +538,7 @@ static void pose_slide_draw_status(tPoseSlideOp *pso) break; default: - // unknown + /* unknown */ strcpy(mode_str, "Sliding-Tool"); break; } @@ -606,7 +606,7 @@ static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *p } /* initial apply for operator... */ - // TODO: need to calculate percentage for initial round too... + /* TODO: need to calculate percentage for initial round too... */ pose_slide_apply(C, pso); /* depsgraph updates + redraws */ @@ -631,6 +631,7 @@ static int pose_slide_modal(bContext *C, wmOperator *op, wmEvent *evt) switch (evt->type) { case LEFTMOUSE: /* confirm */ + case RETKEY: { /* return to normal cursor and header status */ ED_area_headerprint(pso->sa, NULL); @@ -1151,7 +1152,7 @@ static void pose_propagate_fcurve(wmOperator *op, Object *ob, FCurve *fcu, } /* just flatten handles, since values will now be the same either side... */ - // TODO: perhaps a fade-out modulation of the value is required here (optional once again)? + /* TODO: perhaps a fade-out modulation of the value is required here (optional once again)? */ bezt->vec[0][1] = bezt->vec[1][1] = bezt->vec[2][1] = refVal; /* select keyframe to indicate that it's been changed */ @@ -1246,13 +1247,13 @@ void POSE_OT_propagate(wmOperatorType *ot) /* callbacks */ ot->exec = pose_propagate_exec; - ot->poll = ED_operator_posemode; // XXX: needs selected bones! + ot->poll = ED_operator_posemode; /* XXX: needs selected bones! */ /* flag */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - // TODO: add "fade out" control for tapering off amount of propagation as time goes by? + /* TODO: add "fade out" control for tapering off amount of propagation as time goes by? */ ot->prop = RNA_def_enum(ot->srna, "mode", terminate_items, POSE_PROPAGATE_SMART_HOLDS, "Terminate Mode", "Method used to determine when to stop propagating pose to keyframes"); RNA_def_float(ot->srna, "end_frame", 250.0, FLT_MIN, FLT_MAX, "End Frame", "Frame to stop propagating frames to (for 'Before Frame' mode)", 1.0, 250.0); } diff --git a/source/blender/editors/armature/poseUtils.c b/source/blender/editors/armature/poseUtils.c index e2e3c49e7e0..f3c32399ad6 100644 --- a/source/blender/editors/armature/poseUtils.c +++ b/source/blender/editors/armature/poseUtils.c @@ -274,7 +274,7 @@ LinkData *poseAnim_mapping_getNextFCurve(ListBase *fcuLinks, LinkData *prev, con /* check if paths match */ if (strcmp(path, fcu->rna_path) == 0) return ld; - } + } /* none found */ return NULL; diff --git a/source/blender/editors/armature/poselib.c b/source/blender/editors/armature/poselib.c index eea7424c59a..ae3d496b641 100644 --- a/source/blender/editors/armature/poselib.c +++ b/source/blender/editors/armature/poselib.c @@ -298,7 +298,7 @@ static int poselib_sanitize_exec(bContext *C, wmOperator *op) /* validate action */ if (act == NULL) { - BKE_report(op->reports, RPT_WARNING, "No Action to validate"); + BKE_report(op->reports, RPT_WARNING, "No action to validate"); return OPERATOR_CANCELLED; } @@ -547,7 +547,7 @@ static int poselib_remove_exec(bContext *C, wmOperator *op) /* check if valid poselib */ if (act == NULL) { - BKE_report(op->reports, RPT_ERROR, "Object doesn't have PoseLib data"); + BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data"); return OPERATOR_CANCELLED; } @@ -562,7 +562,7 @@ static int poselib_remove_exec(bContext *C, wmOperator *op) /* get index (and pointer) of pose to remove */ marker = BLI_findlink(&act->markers, marker_index); if (marker == NULL) { - BKE_reportf(op->reports, RPT_ERROR, "Invalid Pose specified %d", marker_index); + BKE_reportf(op->reports, RPT_ERROR, "Invalid pose specified %d", marker_index); return OPERATOR_CANCELLED; } @@ -628,14 +628,14 @@ static int poselib_rename_invoke(bContext *C, wmOperator *op, wmEvent *evt) /* check if valid poselib */ if (act == NULL) { - BKE_report(op->reports, RPT_ERROR, "Object doesn't have PoseLib data"); + BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data"); return OPERATOR_CANCELLED; } /* get index (and pointer) of pose to remove */ marker = BLI_findlink(&act->markers, act->active_marker - 1); if (marker == NULL) { - BKE_report(op->reports, RPT_ERROR, "Invalid index for Pose"); + BKE_report(op->reports, RPT_ERROR, "Invalid index for pose"); return OPERATOR_CANCELLED; } else { @@ -657,14 +657,14 @@ static int poselib_rename_exec(bContext *C, wmOperator *op) /* check if valid poselib */ if (act == NULL) { - BKE_report(op->reports, RPT_ERROR, "Object doesn't have PoseLib data"); + BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data"); return OPERATOR_CANCELLED; } /* get index (and pointer) of pose to remove */ marker = BLI_findlink(&act->markers, RNA_int_get(op->ptr, "pose")); if (marker == NULL) { - BKE_report(op->reports, RPT_ERROR, "Invalid index for Pose"); + BKE_report(op->reports, RPT_ERROR, "Invalid index for pose"); return OPERATOR_CANCELLED; } @@ -871,7 +871,7 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld) if (pld->marker) frame = pld->marker->frame; else - return; + return; /* init settings for testing groups for keyframes */ @@ -887,7 +887,7 @@ static void poselib_apply_pose(tPoseLib_PreviewData *pld) /* has keyframe on this frame, so try to get a PoseChannel with this name */ pchan = BKE_pose_channel_find_name(pose, agrp->name); - if (pchan) { + if (pchan) { short ok = 0; /* check if this bone should get any animation applied */ @@ -1079,7 +1079,7 @@ static void poselib_preview_get_next(tPoseLib_PreviewData *pld, int step) } /* check if any matches */ - if (pld->searchp.first == NULL) { + if (pld->searchp.first == NULL) { pld->marker = NULL; return; } @@ -1152,7 +1152,7 @@ static void poselib_preview_handle_search(tPoseLib_PreviewData *pld, unsigned sh poselib_preview_get_next(pld, 1); pld->redraw = PL_PREVIEW_REDRAWALL; return; - } + } break; case DELKEY: @@ -1424,12 +1424,12 @@ static void poselib_preview_init_data(bContext *C, wmOperator *op) /* check if valid poselib */ if (ELEM3(NULL, pld->ob, pld->pose, pld->arm)) { - BKE_report(op->reports, RPT_ERROR, "PoseLib is only for Armatures in PoseMode"); + BKE_report(op->reports, RPT_ERROR, "Pose lib is only for armatures in pose mode"); pld->state = PL_PREVIEW_ERROR; return; } if (pld->act == NULL) { - BKE_report(op->reports, RPT_ERROR, "Object doesn't have a valid PoseLib"); + BKE_report(op->reports, RPT_ERROR, "Object does not have a valid pose lib"); pld->state = PL_PREVIEW_ERROR; return; } @@ -1438,10 +1438,10 @@ static void poselib_preview_init_data(bContext *C, wmOperator *op) /* just use first one then... */ pld->marker = pld->act->markers.first; if (pose_index > -2) - BKE_report(op->reports, RPT_WARNING, "PoseLib had no active pose"); + BKE_report(op->reports, RPT_WARNING, "Pose lib had no active pose"); } else { - BKE_report(op->reports, RPT_ERROR, "PoseLib has no poses to preview/apply"); + BKE_report(op->reports, RPT_ERROR, "Pose lib has no poses to preview/apply"); pld->state = PL_PREVIEW_ERROR; return; } @@ -1639,7 +1639,7 @@ void POSELIB_OT_browse_interactive(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; - /* properties */ + /* properties */ // TODO: make the pose_index into a proper enum instead of a cryptic int... ot->prop = RNA_def_int(ot->srna, "pose_index", -1, -2, INT_MAX, "Pose", "Index of the pose to apply (-2 for no change to pose, -1 for poselib active pose)", 0, INT_MAX); diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index ac1766aff69..576e5983d16 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -81,6 +81,23 @@ #include "armature_intern.h" +/* matches logic with ED_operator_posemode_context() */ +Object *ED_pose_object_from_context(bContext *C) +{ + ScrArea *sa = CTX_wm_area(C); + Object *ob; + + /* since this call may also be used from the buttons window, we need to check for where to get the object */ + if (sa && sa->spacetype == SPACE_BUTS) { + ob = ED_object_context(C); + } + else { + ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); + } + + return ob; +} + /* This function is used to process the necessary updates for */ void ED_armature_enter_posemode(bContext *C, Base *base) { @@ -88,7 +105,7 @@ void ED_armature_enter_posemode(bContext *C, Base *base) Object *ob = base->object; if (ob->id.lib) { - BKE_report(reports, RPT_WARNING, "Can't pose libdata"); + BKE_report(reports, RPT_WARNING, "Cannot pose libdata"); return; } @@ -117,7 +134,7 @@ void ED_armature_exit_posemode(bContext *C, Base *base) ob->mode &= ~OB_MODE_POSE; WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL); - } + } } /* if a selected or active bone is protected, throw error (oonly if warn == 1) and return 1 */ @@ -475,7 +492,7 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op) if (pchan->parent == NULL) continue; else pabone = pchan->parent->bone; - if (PBONE_VISIBLE(arm, pabone)) { + if (PBONE_SELECTABLE(arm, pabone)) { if (!add_to_sel) curbone->flag &= ~BONE_SELECTED; pabone->flag |= BONE_SELECTED; arm->act_bone = pabone; @@ -483,7 +500,7 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op) found = 1; break; } - } + } else { /* direction == BONE_SELECT_CHILD */ /* the child member is only assigned to connected bones, see [#30340] */ #if 0 @@ -497,7 +514,7 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op) for (pchan_child = ob->pose->chanbase.first; pchan_child; pchan_child = pchan_child->next) { /* possible we have multiple children, some invisible */ - if (PBONE_VISIBLE(arm, pchan_child->bone)) { + if (PBONE_SELECTABLE(arm, pchan_child->bone)) { if (pchan_child->parent == pchan) { chbone = pchan_child->bone; break; @@ -509,7 +526,7 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op) if (chbone == NULL) continue; #endif - if (PBONE_VISIBLE(arm, chbone)) { + if (PBONE_SELECTABLE(arm, chbone)) { if (!add_to_sel) curbone->flag &= ~BONE_SELECTED; chbone->flag |= BONE_SELECTED; arm->act_bone = chbone; @@ -702,9 +719,7 @@ static int pose_select_same_keyingset(bContext *C, Object *ob, short extend) if (pchan) { /* select if bone is visible and can be affected */ - if ((PBONE_VISIBLE(arm, pchan->bone)) && - (pchan->bone->flag & BONE_UNSELECTABLE) == 0) - { + if (PBONE_SELECTABLE(arm, pchan->bone)) { pchan->bone->flag |= BONE_SELECTED; changed = 1; } @@ -871,16 +886,16 @@ static void pose_copy_menu(Scene *scene) if (pose_has_protected_selected(ob, 0)) { i = BLI_countlist(&(pchanact->constraints)); /* if there are 24 or less, allow for the user to select constraints */ if (i < 25) - nr = pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4|Constraints...%x5"); + nr = pupmenu("Copy Pose Attributes %t|Local Location %x1|Local Rotation %x2|Local Size %x3|%l|Visual Location %x9|Visual Rotation %x10|Visual Size %x11|%l|Constraints (All) %x4|Constraints... %x5"); else - nr = pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4"); + nr = pupmenu("Copy Pose Attributes %t|Local Location %x1|Local Rotation %x2|Local Size %x3|%l|Visual Location %x9|Visual Rotation %x10|Visual Size %x11|%l|Constraints (All) %x4"); } else { i = BLI_countlist(&(pchanact->constraints)); /* if there are 24 or less, allow for the user to select constraints */ if (i < 25) - nr = pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4|Constraints...%x5|%l|Transform Locks%x6|IK Limits%x7|Bone Shape%x8"); + nr = pupmenu("Copy Pose Attributes %t|Local Location %x1|Local Rotation %x2|Local Size %x3|%l|Visual Location %x9|Visual Rotation %x10|Visual Size %x11|%l|Constraints (All) %x4|Constraints... %x5|%l|Transform Locks %x6|IK Limits %x7|Bone Shape %x8"); else - nr = pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4|%l|Transform Locks%x6|IK Limits%x7|Bone Shape%x8"); + nr = pupmenu("Copy Pose Attributes %t|Local Location %x1|Local Rotation %x2|Local Size %x3|%l|Visual Location %x9|Visual Rotation %x10|Visual Size %x11|%l|Constraints (All) %x4|%l|Transform Locks %x6|IK Limits %x7|Bone Shape %x8"); } if (nr <= 0) @@ -977,7 +992,7 @@ static void pose_copy_menu(Scene *scene) } } } - } + } else { /* constraints, optional (note: max we can have is 24 constraints) */ bConstraint *con, *con_back; int const_toggle[24] = {0}; /* XXX, initialize as 0 to quiet errors */ @@ -1003,7 +1018,7 @@ static void pose_copy_menu(Scene *scene) con_back = con->next; BLI_freelinkN(&const_copy, con); con = con_back; - } + } else con = con->next; } @@ -1020,7 +1035,7 @@ static void pose_copy_menu(Scene *scene) * appending to list of constraints for this channel */ copy_constraints(&tmp_constraints, &const_copy, TRUE); - if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) { + if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) { /* add proxy-local tags */ for (con = tmp_constraints.first; con; con = con->next) con->flag |= CONSTRAINT_PROXY_LOCAL; @@ -1082,7 +1097,7 @@ static void set_pose_keys(Object *ob) for (chan = ob->pose->chanbase.first; chan; chan = chan->next) { Bone *bone = chan->bone; if ((bone) && (bone->flag & BONE_SELECTED) && (arm->layer & bone->layer)) - chan->flag |= POSE_KEY; + chan->flag |= POSE_KEY; else chan->flag &= ~POSE_KEY; } @@ -1221,7 +1236,7 @@ static int pose_copy_exec(bContext *C, wmOperator *op) /* sanity checking */ if (ELEM(NULL, ob, ob->pose)) { - BKE_report(op->reports, RPT_ERROR, "No Pose to Copy"); + BKE_report(op->reports, RPT_ERROR, "No pose to copy"); return OPERATOR_CANCELLED; } @@ -1331,15 +1346,8 @@ void POSE_OT_paste(wmOperatorType *ot) static int pose_group_add_exec(bContext *C, wmOperator *UNUSED(op)) { - ScrArea *sa = CTX_wm_area(C); - Object *ob; - - /* since this call may also be used from the buttons window, we need to check for where to get the object */ - if (sa->spacetype == SPACE_BUTS) - ob = ED_object_context(C); - else - ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); - + Object *ob = ED_pose_object_from_context(C); + /* only continue if there's an object */ if (ob == NULL) return OPERATOR_CANCELLED; @@ -1362,7 +1370,7 @@ void POSE_OT_group_add(wmOperatorType *ot) /* api callbacks */ ot->exec = pose_group_add_exec; - ot->poll = ED_operator_posemode; + ot->poll = ED_operator_posemode_context; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1371,14 +1379,7 @@ void POSE_OT_group_add(wmOperatorType *ot) static int pose_group_remove_exec(bContext *C, wmOperator *UNUSED(op)) { - ScrArea *sa = CTX_wm_area(C); - Object *ob; - - /* since this call may also be used from the buttons window, we need to check for where to get the object */ - if (sa->spacetype == SPACE_BUTS) - ob = ED_object_context(C); - else - ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); + Object *ob = ED_pose_object_from_context(C); /* only continue if there's an object */ if (ob == NULL) @@ -1398,11 +1399,11 @@ void POSE_OT_group_remove(wmOperatorType *ot) /* identifiers */ ot->name = "Remove Bone Group"; ot->idname = "POSE_OT_group_remove"; - ot->description = "Removes the active bone group"; + ot->description = "Remove the active bone group"; /* api callbacks */ ot->exec = pose_group_remove_exec; - ot->poll = ED_operator_posemode; + ot->poll = ED_operator_posemode_context; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1413,8 +1414,7 @@ void POSE_OT_group_remove(wmOperatorType *ot) /* invoke callback which presents a list of bone-groups for the user to choose from */ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt)) { - ScrArea *sa = CTX_wm_area(C); - Object *ob; + Object *ob = ED_pose_object_from_context(C); bPose *pose; uiPopupMenu *pup; @@ -1422,12 +1422,6 @@ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED( bActionGroup *grp; int i; - /* since this call may also be used from the buttons window, we need to check for where to get the object */ - if (sa->spacetype == SPACE_BUTS) - ob = ED_object_context(C); - else - ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); - /* only continue if there's an object, and a pose there too */ if (ELEM(NULL, ob, ob->pose)) return OPERATOR_CANCELLED; @@ -1466,17 +1460,10 @@ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED( /* Assign selected pchans to the bone group that the user selects */ static int pose_group_assign_exec(bContext *C, wmOperator *op) { - ScrArea *sa = CTX_wm_area(C); - Object *ob; + Object *ob = ED_pose_object_from_context(C); bPose *pose; short done = FALSE; - - /* since this call may also be used from the buttons window, we need to check for where to get the object */ - if (sa->spacetype == SPACE_BUTS) - ob = ED_object_context(C); - else - ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); - + /* only continue if there's an object, and a pose there too */ if (ELEM(NULL, ob, ob->pose)) return OPERATOR_CANCELLED; @@ -1518,28 +1505,21 @@ void POSE_OT_group_assign(wmOperatorType *ot) /* api callbacks */ ot->invoke = pose_groups_menu_invoke; ot->exec = pose_group_assign_exec; - ot->poll = ED_operator_posemode; + ot->poll = ED_operator_posemode_context; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - RNA_def_int(ot->srna, "type", 0, 0, 10, "Bone Group Index", "", 0, INT_MAX); + RNA_def_int(ot->srna, "type", 0, 0, INT_MAX, "Bone Group Index", "", 0, 10); } static int pose_group_unassign_exec(bContext *C, wmOperator *UNUSED(op)) { - ScrArea *sa = CTX_wm_area(C); - Object *ob; + Object *ob = ED_pose_object_from_context(C); short done = FALSE; - /* since this call may also be used from the buttons window, we need to check for where to get the object */ - if (sa->spacetype == SPACE_BUTS) - ob = ED_object_context(C); - else - ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); - /* only continue if there's an object, and a pose there too */ if (ELEM(NULL, ob, ob->pose)) return OPERATOR_CANCELLED; @@ -1573,7 +1553,7 @@ void POSE_OT_group_unassign(wmOperatorType *ot) /* api callbacks */ ot->exec = pose_group_unassign_exec; - ot->poll = ED_operator_posemode; + ot->poll = ED_operator_posemode_context; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1581,7 +1561,7 @@ void POSE_OT_group_unassign(wmOperatorType *ot) static int group_move_exec(bContext *C, wmOperator *op) { - Object *ob = ED_object_context(C); + Object *ob = ED_pose_object_from_context(C); bPose *pose = (ob) ? ob->pose : NULL; bPoseChannel *pchan; bActionGroup *grp; @@ -1654,7 +1634,7 @@ void POSE_OT_group_move(wmOperatorType *ot) /* api callbacks */ ot->exec = group_move_exec; - ot->poll = ED_operator_posemode; + ot->poll = ED_operator_posemode_context; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1679,7 +1659,7 @@ static int compare_agroup(const void *sgrp_a_ptr, const void *sgrp_b_ptr) static int group_sort_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *ob = ED_object_context(C); + Object *ob = ED_pose_object_from_context(C); bPose *pose = (ob) ? ob->pose : NULL; bPoseChannel *pchan; tSortActionGroup *agrp_array; @@ -1738,7 +1718,7 @@ void POSE_OT_group_sort(wmOperatorType *ot) /* api callbacks */ ot->exec = group_sort_exec; - ot->poll = ED_operator_posemode; + ot->poll = ED_operator_posemode_context; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1766,14 +1746,7 @@ static void pose_group_select(bContext *C, Object *ob, int select) static int pose_group_select_exec(bContext *C, wmOperator *UNUSED(op)) { - ScrArea *sa = CTX_wm_area(C); - Object *ob; - - /* since this call may also be used from the buttons window, we need to check for where to get the object */ - if (sa->spacetype == SPACE_BUTS) - ob = ED_object_context(C); - else - ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); + Object *ob = ED_pose_object_from_context(C); /* only continue if there's an object, and a pose there too */ if (ELEM(NULL, ob, ob->pose)) @@ -1796,7 +1769,7 @@ void POSE_OT_group_select(wmOperatorType *ot) /* api callbacks */ ot->exec = pose_group_select_exec; - ot->poll = ED_operator_posemode; + ot->poll = ED_operator_posemode_context; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1804,14 +1777,7 @@ void POSE_OT_group_select(wmOperatorType *ot) static int pose_group_deselect_exec(bContext *C, wmOperator *UNUSED(op)) { - ScrArea *sa = CTX_wm_area(C); - Object *ob; - - /* since this call may also be used from the buttons window, we need to check for where to get the object */ - if (sa->spacetype == SPACE_BUTS) - ob = ED_object_context(C); - else - ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); + Object *ob = ED_pose_object_from_context(C); /* only continue if there's an object, and a pose there too */ if (ELEM(NULL, ob, ob->pose)) @@ -1834,7 +1800,7 @@ void POSE_OT_group_deselect(wmOperatorType *ot) /* api callbacks */ ot->exec = pose_group_deselect_exec; - ot->poll = ED_operator_posemode; + ot->poll = ED_operator_posemode_context; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1950,7 +1916,7 @@ static int pose_bone_rotmode_exec(bContext *C, wmOperator *op) Object *ob = CTX_data_active_object(C); int mode = RNA_enum_get(op->ptr, "type"); - /* set rotation mode of selected bones */ + /* set rotation mode of selected bones */ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones) { pchan->rotmode = mode; @@ -2134,7 +2100,7 @@ static int pose_bone_layers_invoke(bContext *C, wmOperator *op, wmEvent *evt) { int layers[32] = {0}; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */ - /* get layers that are active already */ + /* get layers that are active already */ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones) { short bit; @@ -2333,10 +2299,10 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op) * just pose values should change, so this should be fine */ bPose *dummyPose = NULL; - Object workob = {{0}}; + Object workob = {{0}}; bPoseChannel *pchan; - /* execute animation step for current frame using a dummy copy of the pose */ + /* execute animation step for current frame using a dummy copy of the pose */ BKE_pose_copy_data(&dummyPose, ob->pose, 0); BLI_strncpy(workob.id.name, "OB", sizeof(workob.id.name)); diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c index 00f88a69fb6..b1bf13db69b 100644 --- a/source/blender/editors/armature/reeb.c +++ b/source/blender/editors/armature/reeb.c @@ -340,7 +340,7 @@ static ReebArc *copyArc(ReebGraph *rg, ReebArc *arc) cp_arc->edges.first = NULL; cp_arc->edges.last = NULL; - /* copy buckets */ + /* copy buckets */ cp_arc->buckets = MEM_callocN(sizeof(EmbedBucket) * cp_arc->bcount, "embed bucket"); memcpy(cp_arc->buckets, arc->buckets, sizeof(EmbedBucket) * cp_arc->bcount); @@ -377,7 +377,7 @@ static ReebGraph *copyReebGraph(ReebGraph *rg, int level) cp_rg->link_up = rg; cp_rg->multi_level = level; - /* Copy nodes */ + /* Copy nodes */ for (node = rg->nodes.first; node; node = node->next) { ReebNode *cp_node = copyNode(cp_rg, node); @@ -889,7 +889,7 @@ static void calculateArcLength(ReebArc *arc) vec0 = vec1; } - arc->length += len_v3v3(arc->tail->p, vec1); + arc->length += len_v3v3(arc->tail->p, vec1); } static void calculateGraphLength(ReebGraph *rg) @@ -948,7 +948,7 @@ void REEB_RadialSymmetry(BNode *root_node, RadialArc *ring, int count) bucket1 = IT_next(iter1); bucket2 = IT_next(iter2); - /* Make sure they both start at the same value */ + /* Make sure they both start at the same value */ while (bucket1 && bucket2 && bucket1->val < bucket2->val) { bucket1 = IT_next(iter1); } @@ -1005,7 +1005,7 @@ void REEB_RadialSymmetry(BNode *root_node, RadialArc *ring, int count) bucket1 = IT_next(iter1); bucket2 = IT_next(iter2); - /* Make sure they both start at the same value */ + /* Make sure they both start at the same value */ while (bucket1 && bucket1->val < bucket2->val) { bucket1 = IT_next(iter1); } @@ -1016,7 +1016,7 @@ void REEB_RadialSymmetry(BNode *root_node, RadialArc *ring, int count) for (; bucket1 && bucket2; bucket1 = IT_next(iter1), bucket2 = IT_next(iter2)) { - /* copy and mirror back to bucket2 */ + /* copy and mirror back to bucket2 */ bucket2->nv = bucket1->nv; copy_v3_v3(bucket2->p, bucket1->p); BLI_mirrorAlongAxis(bucket2->p, node->p, normal); @@ -1062,7 +1062,7 @@ void REEB_AxialSymmetry(BNode *root_node, BNode *node1, BNode *node2, struct BAr bucket1 = IT_next(iter1); bucket2 = IT_next(iter2); - /* Make sure they both start at the same value */ + /* Make sure they both start at the same value */ while (bucket1 && bucket1->val < bucket2->val) { bucket1 = IT_next(iter1); } @@ -1080,7 +1080,7 @@ void REEB_AxialSymmetry(BNode *root_node, BNode *node1, BNode *node2, struct BAr /* add bucket2 in bucket1 */ interp_v3_v3v3(bucket1->p, bucket1->p, bucket2->p, (float)bucket2->nv / (float)(bucket1->nv)); - /* copy and mirror back to bucket2 */ + /* copy and mirror back to bucket2 */ bucket2->nv = bucket1->nv; copy_v3_v3(bucket2->p, bucket1->p); BLI_mirrorAlongAxis(bucket2->p, root_node->p, nor); @@ -1212,7 +1212,7 @@ static void reweightArc(ReebGraph *rg, ReebArc *arc, ReebNode *start_node, float reweightArc(rg, next_arc, node, end_weight); } - /* update only if needed */ + /* update only if needed */ if (arc->head->weight != start_weight || arc->tail->weight != end_weight) { old_weight = arc->head->weight; /* backup head weight, other arcs need it intact, it will be fixed by the source arc */ @@ -1318,7 +1318,7 @@ static int joinSubgraphsEnds(ReebGraph *rg, float threshold, int nb_subgraphs) } joined = 1; - } + } } return joined; @@ -1450,7 +1450,7 @@ static void filterArc(ReebGraph *rg, ReebNode *newNode, ReebNode *removedNode, R arc->tail = newNode; } - // Remove looped arcs + // Remove looped arcs if (arc->head == arc->tail) { // v1 or v2 was already newNode, since we're removing an arc, decrement degree NodeDegreeDecrement(rg, newNode); @@ -1648,7 +1648,7 @@ int filterSmartReebGraph(ReebGraph *UNUSED(rg), float UNUSED(threshold)) BLI_sortlist(&rg->arcs, compareArcs); #ifdef DEBUG_REEB - { + { EditFace *efa; for (efa = G.editMesh->faces.first; efa; efa = efa->next) { efa->tmp.fp = -1; @@ -1731,7 +1731,7 @@ int filterSmartReebGraph(ReebGraph *UNUSED(rg), float UNUSED(threshold)) efa->tmp.fp = saacos(fabs(angle)); #endif #else - add_v3_v3(avg_vec, efa->n); + add_v3_v3(avg_vec, efa->n); #endif } @@ -1873,7 +1873,7 @@ static int compareVerts(const void *a, const void *b) value = 1; } - return value; + return value; } static void spreadWeight(EditMesh *em) @@ -1947,7 +1947,7 @@ void REEB_exportGraph(ReebGraph *rg, int count) fprintf(f, "angle %0.3f %0.3f %0.3f %0.3f %i\n", p[0], p[1], p[2], arc->angle, BLI_ghash_size(arc->faces)); exportNode(f, "v2", arc->tail); - } + } fclose(f); } @@ -1983,7 +1983,7 @@ void removeNormalNodes(ReebGraph *rg) /* If arcs are one after the other */ if (arc->head == connectedArc->tail) { - /* remove furthest arc */ + /* remove furthest arc */ if (arc->tail->weight < connectedArc->head->weight) { mergeConnectedArcs(rg, arc, connectedArc); nextArc = arc->next; @@ -2006,7 +2006,7 @@ void removeNormalNodes(ReebGraph *rg) /* If arcs are one after the other */ if (arc->tail == connectedArc->head) { - /* remove furthest arc */ + /* remove furthest arc */ if (arc->head->weight < connectedArc->tail->weight) { mergeConnectedArcs(rg, arc, connectedArc); nextArc = arc->next; @@ -2092,7 +2092,7 @@ void mergeArcEdges(ReebGraph *rg, ReebArc *aDst, ReebArc *aSrc, MergeDirection d newEdge->nextEdge = e; - // if edge was the first in the list, point the edit edge to the new reeb edge instead. + // if edge was the first in the list, point the edit edge to the new reeb edge instead. if (*p == e) { *p = (void *)newEdge; } @@ -2289,12 +2289,12 @@ static ReebEdge *createArc(ReebGraph *rg, ReebNode *node1, ReebNode *node2) arc->faces = BLI_ghash_ptr_new("createArc gh"); if (node1->weight <= node2->weight) { - v1 = node1; - v2 = node2; + v1 = node1; + v2 = node2; } else { - v1 = node2; - v2 = node1; + v1 = node2; + v2 = node1; } arc->head = v1; @@ -2857,7 +2857,7 @@ int weightFromDistance(EditMesh *em, EdgeIndex *indexed_edges) /* Apply dijkstra spf for each selected vert */ for (eve = em->verts.first; eve; eve = eve->next) { if (eve->f & SELECT) { - shortestPathsFromVert(em, eve, indexed_edges); + shortestPathsFromVert(em, eve, indexed_edges); } } @@ -2927,7 +2927,7 @@ static void initIteratorFct(ReebArcIterator *iter) iter->next = nextBucket; iter->nextN = nextNBucket; iter->previous = previousBucket; - iter->stopped = iteratorStopped; + iter->stopped = iteratorStopped; } static void setIteratorValues(ReebArcIterator *iter, EmbedBucket *bucket) @@ -3419,7 +3419,7 @@ void REEB_draw() if (G.scene->toolsettings->skgen_options & SKGEN_DISP_EMBED) { - glColor3f(1, 1, 1); + glColor3f(1, 1, 1); glBegin(GL_POINTS); glVertex3fv(arc->head->p); glVertex3fv(arc->tail->p); diff --git a/source/blender/editors/armature/reeb.h b/source/blender/editors/armature/reeb.h index bb8b3003baf..b0e1fd3ae34 100644 --- a/source/blender/editors/armature/reeb.h +++ b/source/blender/editors/armature/reeb.h @@ -114,7 +114,7 @@ typedef struct ReebArc { int bcount; struct EmbedBucket *buckets; - struct GHash *faces; + struct GHash *faces; float angle; struct ReebArc *link_up; /* for multi resolution filtering, points to higher levels */ } ReebArc; diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index d780429784f..485d73974cd 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -162,9 +162,9 @@ static short select_beztriple(BezTriple *bezt, short selstatus, short flag, shor bezt->f1 |= flag; bezt->f2 |= flag; bezt->f3 |= flag; - return 1; + return 1; } - else { /* deselects */ + else { /* deselects */ bezt->f1 &= ~flag; bezt->f2 &= ~flag; bezt->f3 &= ~flag; @@ -1233,12 +1233,12 @@ void make_editNurb(Object *obedit) set_actNurb(obedit, NULL); if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { - actkey = ob_get_keyblock(obedit); + actkey = BKE_keyblock_from_object(obedit); if (actkey) { // XXX strcpy(G.editModeTitleExtra, "(Key) "); undo_editmode_clear(); - key_to_curve(actkey, cu, &cu->nurb); + BKE_key_convert_to_curve(actkey, cu, &cu->nurb); } if (editnurb) { @@ -1361,7 +1361,7 @@ static int separate_exec(bContext *C, wmOperator *op) oldedit = oldcu->editnurb; if (oldcu->key) { - BKE_report(op->reports, RPT_ERROR, "Can't separate a curve with vertex keys"); + BKE_report(op->reports, RPT_ERROR, "Cannot separate a curve with vertex keys"); return OPERATOR_CANCELLED; } @@ -1579,8 +1579,9 @@ static int deleteflagNurb(bContext *C, wmOperator *UNUSED(op), int flag) BPoint *bp, *bpn, *newbp; int a, b, newu, newv, sel; - if (obedit->type == OB_SURF) ; - else return OPERATOR_CANCELLED; + if (obedit->type != OB_SURF) { + return OPERATOR_CANCELLED; + } cu->lastsel = NULL; @@ -1593,8 +1594,12 @@ static int deleteflagNurb(bContext *C, wmOperator *UNUSED(op), int flag) a = nu->pntsu * nu->pntsv; while (a) { a--; - if (bp->f1 & flag) ; - else break; + if (bp->f1 & flag) { + /* pass */ + } + else { + break; + } bp++; } if (a == 0) { @@ -1715,8 +1720,12 @@ static short extrudeflagNurb(EditNurb *editnurb, int flag) bp = nu->bp; a = nu->pntsu; while (a) { - if (bp->f1 & flag) ; - else break; + if (bp->f1 & flag) { + /* pass */ + } + else { + break; + } bp++; a--; } @@ -2054,7 +2063,7 @@ static int set_goal_weight_exec(bContext *C, wmOperator *op) bp->weight = weight; } } - } + } DAG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); @@ -2106,7 +2115,7 @@ static int set_radius_exec(bContext *C, wmOperator *op) bp->radius = radius; } } - } + } WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); DAG_id_tag_update(obedit->data, 0); @@ -2399,7 +2408,7 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short for (nu = editnurb->first; nu; nu = nu->next) { lastsel = 0; - if (nu->type == CU_BEZIER) { + if (nu->type == CU_BEZIER) { a = nu->pntsu; bezt = nu->bezt; if (next < 0) bezt = &nu->bezt[a - 1]; @@ -2416,7 +2425,7 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short bezt += next; lastsel = 0; } - /* move around in zigzag way so that we go through each */ + /* move around in zigzag way so that we go through each */ bezt -= (next - next / abs(next)); } } @@ -2431,7 +2440,7 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short if (!(bp->f1 & SELECT) || (selstatus == 0)) { short sel = select_bpoint(bp, selstatus, 1, VISIBLE); if ((sel == 1) && (cont == 0)) lastsel = 1; - } + } } else { bp += next; @@ -2697,7 +2706,7 @@ static int hide_exec(bContext *C, wmOperator *op) DAG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void CURVE_OT_hide(wmOperatorType *ot) @@ -2758,7 +2767,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) DAG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void CURVE_OT_reveal(wmOperatorType *ot) @@ -3082,7 +3091,7 @@ static void subdividenurb(Object *obedit, int number_cuts) nu->pntsv = (number_cuts + 1) * nu->pntsv - number_cuts; BKE_nurb_knot_calc_u(nu); BKE_nurb_knot_calc_v(nu); - } /* End of 'if (sel == nu->pntsu*nu->pntsv)' (subdivide entire NURB) */ + } /* End of 'if (sel == nu->pntsu * nu->pntsv)' (subdivide entire NURB) */ else { /* subdivide in v direction? */ sel = 0; @@ -3191,7 +3200,7 @@ static int subdivide_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); DAG_id_tag_update(obedit->data, 0); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void CURVE_OT_subdivide(wmOperatorType *ot) @@ -3217,12 +3226,12 @@ void CURVE_OT_subdivide(wmOperatorType *ot) /******************** find nearest ************************/ -static void findnearestNurbvert__doClosest(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y) +static void findnearestNurbvert__doClosest(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) { - struct { BPoint *bp; BezTriple *bezt; Nurb *nurb; int dist, hpoint, select, mval[2]; } *data = userData; + struct { BPoint *bp; BezTriple *bezt; Nurb *nurb; float dist; int hpoint, select; float mval_fl[2]; } *data = userData; short flag; - short temp; + float dist_test; if (bp) { flag = bp->f1; @@ -3239,12 +3248,12 @@ static void findnearestNurbvert__doClosest(void *userData, Nurb *nu, BPoint *bp, } } - temp = abs(data->mval[0] - x) + abs(data->mval[1] - y); - if ((flag & 1) == data->select) temp += 5; - if (bezt && beztindex == 1) temp += 3; /* middle points get a small disadvantage */ + dist_test = len_manhattan_v2v2(data->mval_fl, screen_co); + if ((flag & SELECT) == data->select) dist_test += 5.0f; + if (bezt && beztindex == 1) dist_test += 3.0f; /* middle points get a small disadvantage */ - if (temp < data->dist) { - data->dist = temp; + if (dist_test < data->dist) { + data->dist = dist_test; data->bp = bp; data->bezt = bezt; @@ -3258,16 +3267,16 @@ static short findnearestNurbvert(ViewContext *vc, short sel, const int mval[2], /* (sel == 1): selected gets a disadvantage */ /* in nurb and bezt or bp the nearest is written */ /* return 0 1 2: handlepunt */ - struct { BPoint *bp; BezTriple *bezt; Nurb *nurb; int dist, hpoint, select, mval[2]; } data = {NULL}; + struct { BPoint *bp; BezTriple *bezt; Nurb *nurb; float dist; int hpoint, select; float mval_fl[2]; } data = {NULL}; data.dist = 100; data.hpoint = 0; data.select = sel; - data.mval[0] = mval[0]; - data.mval[1] = mval[1]; + data.mval_fl[0] = mval[0]; + data.mval_fl[1] = mval[1]; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - nurbs_foreachScreenVert(vc, findnearestNurbvert__doClosest, &data); + nurbs_foreachScreenVert(vc, findnearestNurbvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); *nurb = data.nurb; *bezt = data.bezt; @@ -3492,7 +3501,7 @@ static int set_spline_type_exec(bContext *C, wmOperator *op) int changed = 0, type = RNA_enum_get(op->ptr, "type"); if (type == CU_CARDINAL || type == CU_BSPLINE) { - BKE_report(op->reports, RPT_ERROR, "Not implemented yet"); + BKE_report(op->reports, RPT_ERROR, "Not yet implemented"); return OPERATOR_CANCELLED; } @@ -3762,20 +3771,28 @@ static void merge_2_nurb(wmOperator *op, ListBase *editnurb, Nurb *nu1, Nurb *nu /* first nurbs: u = resolu-1 selected */ - if (is_u_selected(nu1, nu1->pntsu - 1) ) ; + if (is_u_selected(nu1, nu1->pntsu - 1) ) { + /* pass */ + } else { /* For 2D curves blender uses (orderv = 0). It doesn't make any sense mathematically. */ /* but after rotating (orderu = 0) will be confusing. */ if (nu1->orderv == 0) nu1->orderv = 1; rotate_direction_nurb(nu1); - if (is_u_selected(nu1, nu1->pntsu - 1)) ; + if (is_u_selected(nu1, nu1->pntsu - 1)) { + /* pass */ + } else { rotate_direction_nurb(nu1); - if (is_u_selected(nu1, nu1->pntsu - 1)) ; + if (is_u_selected(nu1, nu1->pntsu - 1)) { + /* pass */ + } else { rotate_direction_nurb(nu1); - if (is_u_selected(nu1, nu1->pntsu - 1)) ; + if (is_u_selected(nu1, nu1->pntsu - 1)) { + /* pass */ + } else { /* rotate again, now its OK! */ if (nu1->pntsv != 1) rotate_direction_nurb(nu1); @@ -3786,17 +3803,25 @@ static void merge_2_nurb(wmOperator *op, ListBase *editnurb, Nurb *nu1, Nurb *nu } /* 2nd nurbs: u = 0 selected */ - if (is_u_selected(nu2, 0) ) ; + if (is_u_selected(nu2, 0) ) { + /* pass */ + } else { if (nu2->orderv == 0) nu2->orderv = 1; rotate_direction_nurb(nu2); - if (is_u_selected(nu2, 0)) ; + if (is_u_selected(nu2, 0)) { + /* pass */ + } else { rotate_direction_nurb(nu2); - if (is_u_selected(nu2, 0)) ; + if (is_u_selected(nu2, 0)) { + /* pass */ + } else { rotate_direction_nurb(nu2); - if (is_u_selected(nu2, 0)) ; + if (is_u_selected(nu2, 0)) { + /* pass */ + } else { /* rotate again, now its OK! */ if (nu1->pntsu == 1) rotate_direction_nurb(nu1); @@ -3808,7 +3833,7 @@ static void merge_2_nurb(wmOperator *op, ListBase *editnurb, Nurb *nu1, Nurb *nu } if (nu1->pntsv != nu2->pntsv) { - BKE_report(op->reports, RPT_ERROR, "Resolution doesn't match"); + BKE_report(op->reports, RPT_ERROR, "Resolution does not match"); return; } @@ -3892,21 +3917,33 @@ static int merge_nurb(bContext *C, wmOperator *op) /* resolution match, to avoid uv rotations */ if (nus1->nu->pntsv == 1) { - if (nus1->nu->pntsu == nus2->nu->pntsu || nus1->nu->pntsu == nus2->nu->pntsv) ; - else ok = 0; + if (nus1->nu->pntsu == nus2->nu->pntsu || nus1->nu->pntsu == nus2->nu->pntsv) { + /* pass */ + } + else { + ok = 0; + } } else if (nus2->nu->pntsv == 1) { - if (nus2->nu->pntsu == nus1->nu->pntsu || nus2->nu->pntsu == nus1->nu->pntsv) ; - else ok = 0; + if (nus2->nu->pntsu == nus1->nu->pntsu || nus2->nu->pntsu == nus1->nu->pntsv) { + /* pass */ + } + else { + ok = 0; + } + } + else if (nus1->nu->pntsu == nus2->nu->pntsu || nus1->nu->pntsv == nus2->nu->pntsv) { + /* pass */ + } + else if (nus1->nu->pntsu == nus2->nu->pntsv || nus1->nu->pntsv == nus2->nu->pntsu) { + /* pass */ } - else if (nus1->nu->pntsu == nus2->nu->pntsu || nus1->nu->pntsv == nus2->nu->pntsv) ; - else if (nus1->nu->pntsu == nus2->nu->pntsv || nus1->nu->pntsv == nus2->nu->pntsu) ; else { ok = 0; } if (ok == 0) { - BKE_report(op->reports, RPT_ERROR, "Resolution doesn't match"); + BKE_report(op->reports, RPT_ERROR, "Resolution does not match"); BLI_freelistN(&nsortbase); return OPERATOR_CANCELLED; } @@ -3949,8 +3986,12 @@ static int make_segment_exec(bContext *C, wmOperator *op) if (isNurbsel_count(cu, nu) == 1) { /* only 1 selected, not first or last, a little complex, but intuitive */ if (nu->pntsv == 1) { - if ( (nu->bp->f1 & SELECT) || (nu->bp[nu->pntsu - 1].f1 & SELECT)) ; - else break; + if ( (nu->bp->f1 & SELECT) || (nu->bp[nu->pntsu - 1].f1 & SELECT)) { + /* pass */ + } + else { + break; + } } } } @@ -4082,7 +4123,7 @@ static int make_segment_exec(bContext *C, wmOperator *op) } if (!ok) { - BKE_report(op->reports, RPT_ERROR, "Can't make segment"); + BKE_report(op->reports, RPT_ERROR, "Cannot make segment"); return OPERATOR_CANCELLED; } @@ -4335,7 +4376,7 @@ static int spin_exec(bContext *C, wmOperator *op) unit_m4(viewmat); if (!spin_nurb(viewmat, obedit, axis, cent)) { - BKE_report(op->reports, RPT_ERROR, "Can't spin"); + BKE_report(op->reports, RPT_ERROR, "Cannot spin"); return OPERATOR_CANCELLED; } @@ -4380,7 +4421,7 @@ void CURVE_OT_spin(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_float_vector_xyz(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX); - RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -FLT_MAX, FLT_MAX); + RNA_def_float_vector(ot->srna, "axis", 3, NULL, -FLT_MAX, FLT_MAX, "Axis", "Axis in global view space", -1.0f, 1.0f); } /***************** add vertex operator **********************/ @@ -5211,10 +5252,10 @@ static int select_more_exec(bContext *C, wmOperator *UNUSED(op)) tempbp = bp + 1; if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, 1, VISIBLE); if (sel) { - bp++; + bp++; a--; } - } + } } bp++; @@ -5272,8 +5313,8 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) if ((bp->hide == 0) && (bp->f1 & SELECT)) { sel = 0; - /* check if neighbors have been selected */ - /* edges of surface are an exception */ + /* check if neighbors have been selected */ + /* edges of surface are an exception */ if ((a + 1) % nu->pntsu == 0) sel++; else { bp--; @@ -5305,7 +5346,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) if (sel != 4) { select_bpoint(bp, DESELECT, 1, VISIBLE); selbpoints[a] = 1; - } + } } else lastsel = 0; @@ -5319,7 +5360,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) for (nu = editnurb->first; nu; nu = nu->next) { lastsel = 0; /* check what type of curve/nurb it is */ - if (nu->type == CU_BEZIER) { + if (nu->type == CU_BEZIER) { a = nu->pntsu; bezt = nu->bezt; while (a--) { @@ -5327,10 +5368,10 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) if (lastsel == 1) sel = 1; else sel = 0; - /* check if neighbors have been selected */ - /* first and last are exceptions */ + /* check if neighbors have been selected */ + /* first and last are exceptions */ if (a == nu->pntsu - 1) sel++; - else { + else { bezt--; if ((bezt->hide == 0) && (bezt->f2 & SELECT)) sel++; bezt++; @@ -5344,14 +5385,14 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) } if (sel != 2) { - select_beztriple(bezt, DESELECT, 1, VISIBLE); + select_beztriple(bezt, DESELECT, 1, VISIBLE); lastsel = 1; } else lastsel = 0; } else lastsel = 0; - bezt++; + bezt++; } } else { @@ -5362,9 +5403,9 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) if (lastsel != 0) sel = 1; else sel = 0; - /* first and last are exceptions */ + /* first and last are exceptions */ if (a == nu->pntsu * nu->pntsv - 1) sel++; - else { + else { bp--; if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++; bp++; @@ -5378,9 +5419,9 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) } if (sel != 2) { - select_bpoint(bp, DESELECT, 1, VISIBLE); + select_bpoint(bp, DESELECT, 1, VISIBLE); lastsel = 1; - } + } else lastsel = 0; } else lastsel = 0; @@ -5441,7 +5482,7 @@ static void selectrandom_curve(ListBase *editnurb, float randfac) select_bpoint(bp, SELECT, 1, VISIBLE); bp++; } - } + } } } @@ -5583,10 +5624,10 @@ static int select_nth_exec(bContext *C, wmOperator *op) if (!CU_select_nth(obedit, nth)) { if (obedit->type == OB_SURF) { - BKE_report(op->reports, RPT_ERROR, "Surface hasn't got active point"); + BKE_report(op->reports, RPT_ERROR, "Surface has not got active point"); } else { - BKE_report(op->reports, RPT_ERROR, "Curve hasn't got active point"); + BKE_report(op->reports, RPT_ERROR, "Curve has not got active point"); } return OPERATOR_CANCELLED; @@ -5600,8 +5641,8 @@ static int select_nth_exec(bContext *C, wmOperator *op) void CURVE_OT_select_nth(wmOperatorType *ot) { /* identifiers */ - ot->name = "Select Nth"; - ot->description = ""; + ot->name = "Checker Deselect"; + ot->description = "Deselect every other vertex"; ot->idname = "CURVE_OT_select_nth"; /* api callbacks */ @@ -5611,7 +5652,7 @@ void CURVE_OT_select_nth(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_int(ot->srna, "nth", 2, 2, 100, "Nth Selection", "", 1, INT_MAX); + RNA_def_int(ot->srna, "nth", 2, 2, INT_MAX, "Nth Selection", "", 2, 100); } /********************** add duplicate operator *********************/ @@ -5684,8 +5725,12 @@ static int delete_exec(bContext *C, wmOperator *op) a = nu->pntsu; if (a) { while (a) { - if (BEZSELECTED_HIDDENHANDLES(cu, bezt) ) ; - else break; + if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) { + /* pass */ + } + else { + break; + } a--; bezt++; } @@ -5704,8 +5749,12 @@ static int delete_exec(bContext *C, wmOperator *op) a = nu->pntsu * nu->pntsv; if (a) { while (a) { - if (bp->f1 & SELECT) ; - else break; + if (bp->f1 & SELECT) { + /* pass */ + } + else { + break; + } a--; bp++; } @@ -6070,7 +6119,7 @@ void CURVE_OT_shade_flat(wmOperatorType *ot) } /************** join operator, to be used externally? ****************/ - +/* TODO: shape keys - as with meshes */ int join_curve_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); @@ -6191,10 +6240,9 @@ static const char *get_surf_defname(int type) } -Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newob) +Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type, int newob) { static int xzproj = 0; /* this function calls itself... */ - Object *obedit = CTX_data_edit_object(C); ListBase *editnurb = object_editcurve_get(obedit); View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = ED_view3d_context_rv3d(C); @@ -6431,19 +6479,14 @@ Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newob) break; case CU_PRIM_TUBE: /* Cylinder */ if (cutype == CU_NURBS) { - nu = add_nurbs_primitive(C, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); /* circle */ + nu = add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); /* circle */ nu->resolu = cu->resolu; nu->flag = CU_SMOOTH; BLI_addtail(editnurb, nu); /* temporal for extrude and translate */ vec[0] = vec[1] = 0.0; vec[2] = -grid; - if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) { - /* pass */ - } - else { - mul_mat3_m4_v3(mat, vec); - } + mul_mat3_m4_v3(mat, vec); translateflagNurb(editnurb, 1, vec); extrudeflagNurb(cu->editnurb, 1); @@ -6510,7 +6553,7 @@ Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newob) float tmp_vec[3] = {0.f, 0.f, 1.f}; xzproj = 1; - nu = add_nurbs_primitive(C, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); /* circle */ + nu = add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); /* circle */ xzproj = 0; nu->resolu = cu->resolu; nu->resolv = cu->resolv; @@ -6568,29 +6611,28 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) if (!isSurf) { /* adding curve */ if (obedit == NULL || obedit->type != OB_CURVE) { Curve *cu; - + obedit = ED_object_add_type(C, OB_CURVE, loc, rot, TRUE, layer); newob = 1; cu = (Curve *)obedit->data; cu->flag |= CU_DEFORM_FILL; - + if (type & CU_PRIM_PATH) cu->flag |= CU_PATH | CU_3D; - } + } else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); - } + } else { /* adding surface */ if (obedit == NULL || obedit->type != OB_SURF) { obedit = ED_object_add_type(C, OB_SURF, loc, rot, TRUE, layer); newob = 1; - } + } else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); } /* rename here, the undo stack checks name for valid undo pushes */ if (newob) { - if (obedit->type == OB_CURVE) { rename_id((ID *)obedit, get_curve_defname(type)); rename_id((ID *)obedit->data, get_curve_defname(type)); @@ -6600,14 +6642,14 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) rename_id((ID *)obedit->data, get_surf_defname(type)); } } - + /* ED_object_add_type doesnt do an undo, is needed for redo operator on primitive */ if (newob && enter_editmode) ED_undo_push(C, "Enter Editmode"); - - ED_object_new_primitive_matrix(C, obedit, loc, rot, mat); - nu = add_nurbs_primitive(C, mat, type, newob); + ED_object_new_primitive_matrix(C, obedit, loc, rot, mat, TRUE); + + nu = add_nurbs_primitive(C, obedit, mat, type, newob); editnurb = object_editcurve_get(obedit); BLI_addtail(editnurb, nu); @@ -6644,12 +6686,11 @@ void CURVE_OT_primitive_bezier_curve_add(wmOperatorType *ot) ot->name = "Add Bezier"; ot->description = "Construct a Bezier Curve"; ot->idname = "CURVE_OT_primitive_bezier_curve_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_bezier_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -6667,12 +6708,11 @@ void CURVE_OT_primitive_bezier_circle_add(wmOperatorType *ot) ot->name = "Add Bezier Circle"; ot->description = "Construct a Bezier Circle"; ot->idname = "CURVE_OT_primitive_bezier_circle_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_bezier_circle_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -6690,12 +6730,11 @@ void CURVE_OT_primitive_nurbs_curve_add(wmOperatorType *ot) ot->name = "Add Nurbs Curve"; ot->description = "Construct a Nurbs Curve"; ot->idname = "CURVE_OT_primitive_nurbs_curve_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_nurbs_curve_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -6713,12 +6752,11 @@ void CURVE_OT_primitive_nurbs_circle_add(wmOperatorType *ot) ot->name = "Add Nurbs Circle"; ot->description = "Construct a Nurbs Circle"; ot->idname = "CURVE_OT_primitive_nurbs_circle_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_nurbs_circle_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -6736,12 +6774,11 @@ void CURVE_OT_primitive_nurbs_path_add(wmOperatorType *ot) ot->name = "Add Path"; ot->description = "Construct a Path"; ot->idname = "CURVE_OT_primitive_nurbs_path_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_curve_path_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -6760,12 +6797,11 @@ void SURFACE_OT_primitive_nurbs_surface_curve_add(wmOperatorType *ot) ot->name = "Add Surface Curve"; ot->description = "Construct a Nurbs surface Curve"; ot->idname = "SURFACE_OT_primitive_nurbs_surface_curve_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_nurbs_surface_curve_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -6783,12 +6819,11 @@ void SURFACE_OT_primitive_nurbs_surface_circle_add(wmOperatorType *ot) ot->name = "Add Surface Circle"; ot->description = "Construct a Nurbs surface Circle"; ot->idname = "SURFACE_OT_primitive_nurbs_surface_circle_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_nurbs_surface_circle_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -6806,12 +6841,11 @@ void SURFACE_OT_primitive_nurbs_surface_surface_add(wmOperatorType *ot) ot->name = "Add Surface Patch"; ot->description = "Construct a Nurbs surface Patch"; ot->idname = "SURFACE_OT_primitive_nurbs_surface_surface_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_nurbs_surface_surface_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -6829,12 +6863,11 @@ void SURFACE_OT_primitive_nurbs_surface_cylinder_add(wmOperatorType *ot) ot->name = "Add Surface Cylinder"; ot->description = "Construct a Nurbs surface Cylinder"; ot->idname = "SURFACE_OT_primitive_nurbs_surface_cylinder_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_nurbs_surface_cylinder_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -6852,12 +6885,11 @@ void SURFACE_OT_primitive_nurbs_surface_sphere_add(wmOperatorType *ot) ot->name = "Add Surface Sphere"; ot->description = "Construct a Nurbs surface Sphere"; ot->idname = "SURFACE_OT_primitive_nurbs_surface_sphere_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_nurbs_surface_sphere_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -6875,12 +6907,11 @@ void SURFACE_OT_primitive_nurbs_surface_torus_add(wmOperatorType *ot) ot->name = "Add Surface Torus"; ot->description = "Construct a Nurbs surface Torus"; ot->idname = "SURFACE_OT_primitive_nurbs_surface_torus_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_nurbs_surface_torus_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index b11d640256c..fd87e6752f2 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -94,7 +94,8 @@ static char findaccent(char char1, unsigned int code) } else if (char1 == 'c') { if (code == ',') new = 231; - if (code == '|') new = 162; + else if (code == '|') new = 162; + else if (code == 'o') new = 169; } else if (char1 == 'e') { if (code == '`') new = 232; @@ -120,10 +121,18 @@ static char findaccent(char char1, unsigned int code) else if (code == '/') new = 248; else if (code == '-') new = 186; else if (code == 'e') new = 143; + else if (code == 'c') new = 169; + else if (code == 'r') new = 174; + } + else if (char1 == 'r') { + if (code == 'o') new = 174; } else if (char1 == 's') { if (code == 's') new = 167; } + else if (char1 == 't') { + if (code == 'm') new = 153; + } else if (char1 == 'u') { if (code == '`') new = 249; else if (code == 39) new = 250; @@ -310,7 +319,7 @@ static int insert_lorem_exec(bContext *C, wmOperator *UNUSED(op)) lastlorem = ED_lorem; insert_into_textbuf(obedit, '\n'); - insert_into_textbuf(obedit, '\n'); + insert_into_textbuf(obedit, '\n'); DAG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); @@ -441,8 +450,9 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, float obedit = BKE_object_add(scene, OB_FONT); base = scene->basact; - - ED_object_base_init_transform(C, base, NULL, rot); /* seems to assume view align ? TODO - look into this, could be an operator option */ + /* seems to assume view align ? TODO - look into this, could be an operator option */ + ED_object_base_init_transform(C, base, NULL, rot); + BKE_object_where_is_calc(scene, obedit); obedit->loc[0] += offset[0]; @@ -457,7 +467,7 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, float nchars += strlen(tmp->line) + 1; if (cu->str) MEM_freeN(cu->str); - if (cu->strinfo) MEM_freeN(cu->strinfo); + if (cu->strinfo) MEM_freeN(cu->strinfo); cu->str = MEM_callocN(nchars + 4, "str"); cu->strinfo = MEM_callocN((nchars + 4) * sizeof(CharInfo), "strinfo"); @@ -756,7 +766,7 @@ static int paste_selection(Object *obedit, ReportList *reports) /* Verify that the copy buffer => [copy buffer len] + cu->len < MAXTEXT */ if (cu->len + len <= MAXTEXT) { - if (len) { + if (len) { int size = (cu->len * sizeof(wchar_t)) - (cu->pos * sizeof(wchar_t)) + sizeof(wchar_t); memmove(ef->textbuf + cu->pos + len, ef->textbuf + cu->pos, size); memcpy(ef->textbuf + cu->pos, ef->copybuf, len * sizeof(wchar_t)); @@ -834,7 +844,7 @@ static int move_cursor(bContext *C, int type, int select) if (ef->textbuf[cu->pos - 1] == '\n') break; if (ef->textbufinfo[cu->pos - 1].flag & CU_CHINFO_WRAP) break; cu->pos--; - } + } cursmove = FO_CURS; break; @@ -867,7 +877,7 @@ static int move_cursor(bContext *C, int type, int select) cursmove = FO_CURS; break; - case NEXT_CHAR: + case NEXT_CHAR: if ((select) && (cu->selstart == 0)) cu->selstart = cu->selend = cu->pos + 1; cu->pos++; cursmove = FO_CURS; @@ -1250,8 +1260,12 @@ static int insert_text_invoke(bContext *C, wmOperator *op, wmEvent *evt) else ascii = 9; } - else if (event == BACKSPACEKEY) - ascii = 0; + + if (event == BACKSPACEKEY) { + if (alt && cu->len != 0 && cu->pos > 0) + accentcode = 1; + return OPERATOR_PASS_THROUGH; + } if (val && (ascii || evt->utf8_buf[0])) { /* handle case like TAB (== 9) */ @@ -1262,44 +1276,18 @@ static int insert_text_invoke(bContext *C, wmOperator *op, wmEvent *evt) (evt->utf8_buf[0])) { - if (evt->utf8_buf[0]) { - BLI_strncpy_wchar_from_utf8(inserted_text, evt->utf8_buf, 1); - ascii = inserted_text[0]; - insert_into_textbuf(obedit, ascii); - accentcode = 0; - } - else if (accentcode) { + if (accentcode) { if (cu->pos > 0) { inserted_text[0] = findaccent(ef->textbuf[cu->pos - 1], ascii); ef->textbuf[cu->pos - 1] = inserted_text[0]; } accentcode = 0; } - else if (cu->len < MAXTEXT - 1) { - if (alt) { - /* might become obsolete, apple has default values for this, other OS's too? */ - if (ascii == 't') ascii = 137; - else if (ascii == 'c') ascii = 169; - else if (ascii == 'f') ascii = 164; - else if (ascii == 'g') ascii = 176; - else if (ascii == 'l') ascii = 163; - else if (ascii == 'r') ascii = 174; - else if (ascii == 's') ascii = 223; - else if (ascii == 'y') ascii = 165; - else if (ascii == '.') ascii = 138; - else if (ascii == '1') ascii = 185; - else if (ascii == '2') ascii = 178; - else if (ascii == '3') ascii = 179; - else if (ascii == '%') ascii = 139; - else if (ascii == '?') ascii = 191; - else if (ascii == '!') ascii = 161; - else if (ascii == 'x') ascii = 215; - else if (ascii == '>') ascii = 187; - else if (ascii == '<') ascii = 171; - } - - inserted_text[0] = ascii; + else if (evt->utf8_buf[0]) { + BLI_strncpy_wchar_from_utf8(inserted_text, evt->utf8_buf, 1); + ascii = inserted_text[0]; insert_into_textbuf(obedit, ascii); + accentcode = 0; } kill_selection(obedit, 1); @@ -1311,12 +1299,6 @@ static int insert_text_invoke(bContext *C, wmOperator *op, wmEvent *evt) text_update_edited(C, scene, obedit, 1, FO_EDIT); } } - else if (val && event == BACKSPACEKEY) { - if (alt && cu->len != 0 && cu->pos > 0) - accentcode = 1; - - return OPERATOR_PASS_THROUGH; - } else return OPERATOR_PASS_THROUGH; @@ -1329,7 +1311,8 @@ static int insert_text_invoke(bContext *C, wmOperator *op, wmEvent *evt) } /* reset property? */ - accentcode = 0; + if (val == 0) + accentcode = 0; return OPERATOR_FINISHED; } diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 5a94d54f329..11e07584405 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -98,8 +98,8 @@ static void gp_draw_stroke_buffer(tGPspoint *points, int totpoints, short thickn if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D)) return; - /* if drawing a single point, draw it larger */ - if (totpoints == 1) { + /* if drawing a single point, draw it larger */ + if (totpoints == 1) { /* draw point */ glBegin(GL_POINTS); glVertex2iv(&points->x); @@ -149,7 +149,8 @@ static void gp_draw_stroke_buffer(tGPspoint *points, int totpoints, short thickn /* ----- Existing Strokes Drawing (3D and Point) ------ */ /* draw a given stroke - just a single dot (only one point) */ -static void gp_draw_stroke_point(bGPDspoint *points, short thickness, short dflag, short sflag, int offsx, int offsy, int winx, int winy) +static void gp_draw_stroke_point(bGPDspoint *points, short thickness, short dflag, short sflag, + int offsx, int offsy, int winx, int winy) { /* draw point */ if (sflag & GP_STROKE_3DSPACE) { @@ -314,7 +315,7 @@ static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s, s0[1] = (pt1->y / 100 * winy) + offsy; s1[0] = (pt2->x / 100 * winx) + offsx; s1[1] = (pt2->y / 100 * winy) + offsy; - } + } /* calculate gradient and normal - 'angle'=(ny/nx) */ m1[1] = s1[1] - s0[1]; @@ -330,7 +331,7 @@ static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s, if (i == 0) { /* draw start cap first * - make points slightly closer to center (about halfway across) - */ + */ mt[0] = m2[0] * pthick * 0.5f; mt[1] = m2[1] * pthick * 0.5f; sc[0] = s0[0] - (m1[0] * pthick * 0.75f); @@ -381,7 +382,7 @@ static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s, if (((athick * 2.0f) < pthick) && (IS_EQF(athick, pthick) == 0)) { mt[0] += (mb[0] * dfac); mt[1] += (mb[1] * dfac); - } + } /* calculate points for start of segment */ t0[0] = s0[0] - mt[0]; @@ -419,7 +420,7 @@ static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s, /* draw end cap as last step * - make points slightly closer to center (about halfway across) - */ + */ mt[0] = m2[0] * pthick * 0.5f; mt[1] = m2[1] * pthick * 0.5f; sc[0] = s1[0] + (m1[0] * pthick * 0.75f); @@ -508,7 +509,8 @@ static void gp_draw_strokes(bGPDframe *gpf, int offsx, int offsy, int winx, int glDepthMask(0); glEnable(GL_DEPTH_TEST); - /* first arg is normally rv3d->dist, but this isn't available here and seems to work quite well without */ + /* first arg is normally rv3d->dist, but this isn't + * available here and seems to work quite well without */ bglPolygonOffset(1.0f, 1.0f); #if 0 glEnable(GL_POLYGON_OFFSET_LINE); @@ -529,7 +531,7 @@ static void gp_draw_strokes(bGPDframe *gpf, int offsx, int offsy, int winx, int #endif } } - else if (gps->totpoints > 1) + else if (gps->totpoints > 1) gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, offsx, offsy, winx, winy); } } @@ -579,7 +581,8 @@ static void gp_draw_data(bGPdata *gpd, int offsx, int offsy, int winx, int winy, /* draw 'onionskins' (frame left + right) */ if (gpl->flag & GP_LAYER_ONIONSKIN) { - /* drawing method - only immediately surrounding (gstep = 0), or within a frame range on either side (gstep > 0)*/ + /* drawing method - only immediately surrounding (gstep = 0), + * or within a frame range on either side (gstep > 0)*/ if (gpl->gstep) { bGPDframe *gf; float fac; @@ -608,7 +611,7 @@ static void gp_draw_data(bGPdata *gpd, int offsx, int offsy, int winx, int winy, } else break; - } + } /* restore alpha */ glColor4fv(color); @@ -640,7 +643,8 @@ static void gp_draw_data(bGPdata *gpd, int offsx, int offsy, int winx, int winy, if (ED_gpencil_session_active() && (gpl->flag & GP_LAYER_ACTIVE) && (gpf->flag & GP_FRAME_PAINT)) { - /* Buffer stroke needs to be drawn with a different linestyle to help differentiate them from normal strokes. */ + /* Buffer stroke needs to be drawn with a different linestyle + * to help differentiate them from normal strokes. */ gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag); } } @@ -657,11 +661,11 @@ static void gp_draw_data(bGPdata *gpd, int offsx, int offsy, int winx, int winy, /* ----- Grease Pencil Sketches Drawing API ------ */ -// ............................ -// XXX -// We need to review the calls below, since they may be/are not that suitable for -// the new ways that we intend to be drawing data... -// ............................ +/* ............................ + * XXX + * We need to review the calls below, since they may be/are not that suitable for + * the new ways that we intend to be drawing data... + * ............................ */ /* draw grease-pencil sketches to specified 2d-view that uses ibuf corrections */ void draw_gpencil_2dimage(const bContext *C) @@ -724,8 +728,8 @@ void draw_gpencil_2dimage(const bContext *C) } /* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly - * Note: this gets called twice - first time with onlyv2d=1 to draw 'canvas' strokes, second time with onlyv2d=0 for screen-aligned strokes - */ + * Note: this gets called twice - first time with onlyv2d=1 to draw 'canvas' strokes, + * second time with onlyv2d=0 for screen-aligned strokes */ void draw_gpencil_view2d(const bContext *C, short onlyv2d) { ScrArea *sa = CTX_wm_area(C); @@ -750,15 +754,14 @@ void draw_gpencil_view2d(const bContext *C, short onlyv2d) } /* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly - * Note: this gets called twice - first time with only3d=1 to draw 3d-strokes, second time with only3d=0 for screen-aligned strokes - */ - + * Note: this gets called twice - first time with only3d=1 to draw 3d-strokes, + * second time with only3d=0 for screen-aligned strokes */ void draw_gpencil_view3d(Scene *scene, View3D *v3d, ARegion *ar, short only3d) { bGPdata *gpd; int dflag = 0; - rcti rect; RegionView3D *rv3d = ar->regiondata; + int offsx, offsy, winx, winy; /* check that we have grease-pencil stuff to draw */ gpd = gpencil_data_get_active_v3d(scene); // XXX @@ -769,19 +772,23 @@ void draw_gpencil_view3d(Scene *scene, View3D *v3d, ARegion *ar, short only3d) if ((rv3d->persp == RV3D_CAMOB) && !(G.f & G_RENDER_OGL)) { rctf rectf; ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &rectf, TRUE); /* no shift */ - BLI_rcti_rctf_copy(&rect, &rectf); + + offsx = floorf(rectf.xmin + 0.5f); + offsy = floorf(rectf.ymin + 0.5f); + winx = floorf((rectf.xmax - rectf.xmin) + 0.5f); + winy = floorf((rectf.ymax - rectf.ymin) + 0.5f); } else { - rect.xmin = 0; - rect.ymin = 0; - rect.xmax = ar->winx; - rect.ymax = ar->winy; + offsx = 0; + offsy = 0; + winx = ar->winx; + winy = ar->winy; } /* draw it! */ if (only3d) dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS); - gp_draw_data(gpd, rect.xmin, rect.ymin, rect.xmax, rect.ymax, CFRA, dflag); + gp_draw_data(gpd, offsx, offsy, winx, winy, CFRA, dflag); } /* ************************************************** */ diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c index b69db0040b5..a59a3f7a5ec 100644 --- a/source/blender/editors/gpencil/editaction_gpencil.c +++ b/source/blender/editors/gpencil/editaction_gpencil.c @@ -393,7 +393,7 @@ void paste_gpdata(Scene *scene) ScrArea *sa; /* get area that gp-data comes from */ - //sa= gpencil_data_findowner((bGPdata *)ale->owner); + //sa = gpencil_data_findowner((bGPdata *)ale->owner); sa = NULL; /* this should be the right frame... as it may be a pre-existing frame, diff --git a/source/blender/editors/gpencil/gpencil_buttons.c b/source/blender/editors/gpencil/gpencil_buttons.c index d90ec02b0c1..8a3c996a481 100644 --- a/source/blender/editors/gpencil/gpencil_buttons.c +++ b/source/blender/editors/gpencil/gpencil_buttons.c @@ -75,17 +75,15 @@ static void gp_ui_activelayer_cb(bContext *C, void *gpd, void *gpl) /* make sure the layer we want to remove is the active one */ gpencil_layer_setactive(gpd, gpl); - WM_event_add_notifier(C, NC_SCREEN | ND_GPENCIL | NA_EDITED, NULL); /* XXX please work! */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); } /* delete 'active' layer */ static void gp_ui_dellayer_cb(bContext *C, void *gpd, void *gpl) { - /* make sure the layer we want to remove is the active one */ - gpencil_layer_setactive(gpd, gpl); - gpencil_layer_delactive(gpd); + gpencil_layer_delete((bGPdata *)gpd, (bGPDlayer *)gpl); - WM_event_add_notifier(C, NC_SCREEN | ND_GPENCIL | NA_EDITED, NULL); /* XXX please work! */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); } diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 5d67b63af18..ed8a1ea8280 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -212,7 +212,7 @@ static int gp_data_add_exec(bContext *C, wmOperator *op) bGPdata **gpd_ptr = gpencil_data_get_pointers(C, NULL); if (gpd_ptr == NULL) { - BKE_report(op->reports, RPT_ERROR, "Nowhere for Grease Pencil data to go"); + BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go"); return OPERATOR_CANCELLED; } else { @@ -224,7 +224,7 @@ static int gp_data_add_exec(bContext *C, wmOperator *op) } /* notifiers */ - WM_event_add_notifier(C, NC_SCREEN | ND_GPENCIL | NA_EDITED, NULL); // XXX need a nicer one that will work + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); return OPERATOR_FINISHED; } @@ -260,7 +260,7 @@ static int gp_data_unlink_exec(bContext *C, wmOperator *op) bGPdata **gpd_ptr = gpencil_data_get_pointers(C, NULL); if (gpd_ptr == NULL) { - BKE_report(op->reports, RPT_ERROR, "Nowhere for Grease Pencil data to go"); + BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go"); return OPERATOR_CANCELLED; } else { @@ -272,7 +272,7 @@ static int gp_data_unlink_exec(bContext *C, wmOperator *op) } /* notifiers */ - WM_event_add_notifier(C, NC_SCREEN | ND_GPENCIL | NA_EDITED, NULL); // XXX need a nicer one that will work + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); return OPERATOR_FINISHED; } @@ -299,17 +299,17 @@ static int gp_layer_add_exec(bContext *C, wmOperator *op) /* if there's no existing Grease-Pencil data there, add some */ if (gpd_ptr == NULL) { - BKE_report(op->reports, RPT_ERROR, "Nowhere for Grease Pencil data to go"); + BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go"); return OPERATOR_CANCELLED; } if (*gpd_ptr == NULL) *gpd_ptr = gpencil_data_addnew("GPencil"); /* add new layer now */ - gpencil_layer_addnew(*gpd_ptr); + gpencil_layer_addnew(*gpd_ptr, "GP_Layer", 1); /* notifiers */ - WM_event_add_notifier(C, NC_SCREEN | ND_GPENCIL | NA_EDITED, NULL); // XXX please work! + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); return OPERATOR_FINISHED; } @@ -348,7 +348,7 @@ static int gp_actframe_delete_exec(bContext *C, wmOperator *op) /* if there's no existing Grease-Pencil data there, add some */ if (gpd == NULL) { - BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data"); + BKE_report(op->reports, RPT_ERROR, "No grease pencil data"); return OPERATOR_CANCELLED; } if (ELEM(NULL, gpl, gpf)) { @@ -360,7 +360,7 @@ static int gp_actframe_delete_exec(bContext *C, wmOperator *op) gpencil_layer_delframe(gpl, gpf); /* notifiers */ - WM_event_add_notifier(C, NC_SCREEN | ND_GPENCIL | NA_EDITED, NULL); // XXX please work! + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); return OPERATOR_FINISHED; } @@ -422,8 +422,8 @@ static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoin } else { if (subrect) { - mvalf[0] = (((float)pt->x / 100.0f) * BLI_RCT_SIZE_X(subrect)) + subrect->xmin; - mvalf[1] = (((float)pt->y / 100.0f) * BLI_RCT_SIZE_Y(subrect)) + subrect->ymin; + mvalf[0] = (((float)pt->x / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin; + mvalf[1] = (((float)pt->y / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin; } else { mvalf[0] = (float)pt->x / 100.0f * ar->winx; @@ -634,7 +634,7 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op) /* check if there's data to work with */ if (gpd == NULL) { - BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data to work on"); + BKE_report(op->reports, RPT_ERROR, "No grease pencil data to work on"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 4e281b96fc3..9bfd89075af 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -278,11 +278,15 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3] gp_get_3d_reference(p, rvec); /* method taken from editview.c - mouse_cursor() */ - project_int_noclip(p->ar, rvec, mval_prj); - - VECSUB2D(mval_f, mval_prj, mval); - ED_view3d_win_to_delta(p->ar, mval_f, dvec); - sub_v3_v3v3(out, rvec, dvec); + /* TODO, use ED_view3d_project_float_global */ + if (ED_view3d_project_int_global(p->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + VECSUB2D(mval_f, mval_prj, mval); + ED_view3d_win_to_delta(p->ar, mval_f, dvec); + sub_v3_v3v3(out, rvec, dvec); + } + else { + zero_v3(out); + } } } @@ -299,8 +303,8 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3] out[1] = (float)(mval[1]) / (float)(p->ar->winy) * 100; } else { /* camera view, use subrect */ - out[0] = ((mval[0] - p->subrect->xmin) / BLI_RCT_SIZE_X(p->subrect)) * 100; - out[1] = ((mval[1] - p->subrect->ymin) / BLI_RCT_SIZE_Y(p->subrect)) * 100; + out[0] = ((mval[0] - p->subrect->xmin) / BLI_rctf_size_x(p->subrect)) * 100; + out[1] = ((mval[1] - p->subrect->ymin) / BLI_rctf_size_y(p->subrect)) * 100; } } } @@ -391,8 +395,10 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) pts = &gps->points[gps->totpoints - 1]; - /* special case for poly lines: normally, depth is needed only when creating new stroke from buffer, - * but poly lines are converting to stroke instantly, so initialize depth buffer before converting coordinates + /* special case for poly lines: normally, + * depth is needed only when creating new stroke from buffer, + * but poly lines are converting to stroke instantly, + * so initialize depth buffer before converting coordinates */ if (gpencil_project_check(p)) { View3D *v3d = p->sa->spacedata.first; @@ -530,7 +536,7 @@ static void gp_stroke_simplify(tGPsdata *p) j += 2; } - } + } /* free old buffer */ MEM_freeN(old_points); @@ -781,13 +787,49 @@ static short gp_stroke_eraser_strokeinside(const int mval[], const int UNUSED(mv int rad, int x0, int y0, int x1, int y1) { /* simple within-radius check for now */ - if (edge_inside_circle(mval[0], mval[1], rad, x0, y0, x1, y1)) - return 1; + const float mval_fl[2] = {mval[0], mval[1]}; + const float screen_co_a[2] = {x0, y0}; + const float screen_co_b[2] = {x1, y1}; + + if (edge_inside_circle(mval_fl, rad, screen_co_a, screen_co_b)) { + return TRUE; + } /* not inside */ - return 0; + return FALSE; } +static void gp_point_to_xy(ARegion *ar, View2D *v2d, rctf *subrect, bGPDstroke *gps, bGPDspoint *pt, + int *r_x, int *r_y) +{ + int xyval[2]; + + if (gps->flag & GP_STROKE_3DSPACE) { + if (ED_view3d_project_int_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + *r_x = xyval[0]; + *r_y = xyval[1]; + } + else { + *r_x = V2D_IS_CLIPPED; + *r_y = V2D_IS_CLIPPED; + } + } + else if (gps->flag & GP_STROKE_2DSPACE) { + UI_view2d_view_to_region(v2d, pt->x, pt->y, r_x, r_y); + } + else { + if (subrect == NULL) { /* normal 3D view */ + *r_x = (int)(pt->x / 100 * ar->winx); + *r_y = (int)(pt->y / 100 * ar->winy); + } + else { /* camera view, use subrect */ + *r_x = (int)((pt->x / 100) * BLI_rctf_size_x(subrect)) + subrect->xmin; + *r_y = (int)((pt->y / 100) * BLI_rctf_size_y(subrect)) + subrect->ymin; + } + } +} + + /* eraser tool - evaluation per stroke */ // TODO: this could really do with some optimization (KD-Tree/BVH?) static void gp_stroke_eraser_dostroke(tGPsdata *p, @@ -796,7 +838,6 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, { bGPDspoint *pt1, *pt2; int x0 = 0, y0 = 0, x1 = 0, y1 = 0; - int xyval[2]; int i; if (gps->totpoints == 0) { @@ -806,28 +847,11 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, BLI_freelinkN(&gpf->strokes, gps); } else if (gps->totpoints == 1) { - /* get coordinates */ - if (gps->flag & GP_STROKE_3DSPACE) { - project_int(p->ar, &gps->points->x, xyval); - x0 = xyval[0]; - y0 = xyval[1]; - } - else if (gps->flag & GP_STROKE_2DSPACE) { - UI_view2d_view_to_region(p->v2d, gps->points->x, gps->points->y, &x0, &y0); - } - else { - if (p->subrect == NULL) { /* normal 3D view */ - x0 = (int)(gps->points->x / 100 * p->ar->winx); - y0 = (int)(gps->points->y / 100 * p->ar->winy); - } - else { /* camera view, use subrect */ - x0 = (int)((gps->points->x / 100) * BLI_RCT_SIZE_X(p->subrect)) + p->subrect->xmin; - y0 = (int)((gps->points->y / 100) * BLI_RCT_SIZE_Y(p->subrect)) + p->subrect->ymin; - } - } + gp_point_to_xy(p->ar, p->v2d, p->subrect, gps, gps->points, &x0, &y0); /* do boundbox check first */ - if (BLI_rcti_isect_pt(rect, x0, y0)) { + + if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) { /* only check if point is inside */ if (((x0 - mval[0]) * (x0 - mval[0]) + (y0 - mval[1]) * (y0 - mval[1])) <= rad * rad) { /* free stroke */ @@ -836,7 +860,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, } } } - else { + else { /* loop over the points in the stroke, checking for intersections * - an intersection will require the stroke to be split */ @@ -844,39 +868,13 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, /* get points to work with */ pt1 = gps->points + i; pt2 = gps->points + i + 1; - - /* get coordinates */ - if (gps->flag & GP_STROKE_3DSPACE) { - project_int(p->ar, &pt1->x, xyval); - x0 = xyval[0]; - y0 = xyval[1]; - - project_int(p->ar, &pt2->x, xyval); - x1 = xyval[0]; - y1 = xyval[1]; - } - else if (gps->flag & GP_STROKE_2DSPACE) { - UI_view2d_view_to_region(p->v2d, pt1->x, pt1->y, &x0, &y0); - - UI_view2d_view_to_region(p->v2d, pt2->x, pt2->y, &x1, &y1); - } - else { - if (p->subrect == NULL) { /* normal 3D view */ - x0 = (int)(pt1->x / 100 * p->ar->winx); - y0 = (int)(pt1->y / 100 * p->ar->winy); - x1 = (int)(pt2->x / 100 * p->ar->winx); - y1 = (int)(pt2->y / 100 * p->ar->winy); - } - else { /* camera view, use subrect */ - x0 = (int)((pt1->x / 100) * BLI_RCT_SIZE_X(p->subrect)) + p->subrect->xmin; - y0 = (int)((pt1->y / 100) * BLI_RCT_SIZE_Y(p->subrect)) + p->subrect->ymin; - x1 = (int)((pt2->x / 100) * BLI_RCT_SIZE_X(p->subrect)) + p->subrect->xmin; - y1 = (int)((pt2->y / 100) * BLI_RCT_SIZE_Y(p->subrect)) + p->subrect->ymin; - } - } - + + gp_point_to_xy(p->ar, p->v2d, p->subrect, gps, pt1, &x0, &y0); + gp_point_to_xy(p->ar, p->v2d, p->subrect, gps, pt2, &x1, &y1); + /* check that point segment of the boundbox of the eraser stroke */ - if (BLI_rcti_isect_pt(rect, x0, y0) || BLI_rcti_isect_pt(rect, x1, y1)) { + if (((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) || + ((!ELEM(V2D_IS_CLIPPED, x1, y1)) && BLI_rcti_isect_pt(rect, x1, y1))) { /* check if point segment of stroke had anything to do with * eraser region (either within stroke painted, or on its lines) * - this assumes that linewidth is irrelevant @@ -961,8 +959,8 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) /* supported views first */ case SPACE_VIEW3D: { - // View3D *v3d= curarea->spacedata.first; - // RegionView3D *rv3d= ar->regiondata; + // View3D *v3d = curarea->spacedata.first; + // RegionView3D *rv3d = ar->regiondata; /* set current area * - must verify that region data is 3D-view (and not something else) @@ -981,7 +979,7 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) case SPACE_NODE: { - //SpaceNode *snode= curarea->spacedata.first; + //SpaceNode *snode = curarea->spacedata.first; /* set current area */ p->sa = curarea; @@ -1009,7 +1007,7 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) break; case SPACE_IMAGE: { - //SpaceImage *sima= curarea->spacedata.first; + //SpaceImage *sima = curarea->spacedata.first; /* set the current area */ p->sa = curarea; @@ -1125,7 +1123,7 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode) /* get active layer (or add a new one if non-existent) */ p->gpl = gpencil_layer_getactive(p->gpd); if (p->gpl == NULL) { - p->gpl = gpencil_layer_addnew(p->gpd); + p->gpl = gpencil_layer_addnew(p->gpd, "GP_Layer", 1); if (p->custom_color[3]) copy_v3_v3(p->gpl->color, p->custom_color); @@ -1212,7 +1210,7 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode) /* make strokes be drawn in screen space */ p->gpd->sbuffer_sflag &= ~GP_STROKE_2DSPACE; p->gpd->flag &= ~GP_DATA_VIEWALIGN; - } + } else p->gpd->sbuffer_sflag |= GP_STROKE_2DSPACE; } @@ -1344,7 +1342,7 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op) gp_session_cleanup(p); /* finally, free the temp data */ - MEM_freeN(p); + MEM_freeN(p); } op->customdata = NULL; @@ -1405,13 +1403,17 @@ static void gpencil_draw_status_indicators(tGPsdata *p) /* print status info */ switch (p->paintmode) { case GP_PAINTMODE_ERASER: - ED_area_headerprint(p->sa, "Grease Pencil Erase Session: Hold and drag LMB or RMB to erase | ESC/Enter to end"); + ED_area_headerprint(p->sa, + "Grease Pencil Erase Session: Hold and drag LMB or RMB to erase |" + " ESC/Enter to end"); break; case GP_PAINTMODE_DRAW_STRAIGHT: - ED_area_headerprint(p->sa, "Grease Pencil Line Session: Hold and drag LMB to draw | ESC/Enter to end"); + ED_area_headerprint(p->sa, "Grease Pencil Line Session: Hold and drag LMB to draw | " + "ESC/Enter to end"); break; case GP_PAINTMODE_DRAW: - ED_area_headerprint(p->sa, "Grease Pencil Freehand Session: Hold and drag LMB to draw | ESC/Enter to end"); + ED_area_headerprint(p->sa, "Grease Pencil Freehand Session: Hold and drag LMB to draw | " + "ESC/Enter to end"); break; default: /* unhandled future cases */ @@ -1598,7 +1600,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) gpencil_draw_exit(C, op); /* refreshes */ - WM_event_add_notifier(C, NC_SCREEN | ND_GPENCIL | NA_EDITED, NULL); // XXX need a nicer one that will work + WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); /* done */ return OPERATOR_FINISHED; @@ -1646,7 +1648,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event) * painting should start immediately. Otherwise, this was called from a toolbar, in which * case we should wait for the mouse to be clicked. */ - if (event->type) { + if (event->val == KM_PRESS) { /* hotkey invoked - start drawing */ //printf("\tGP - set first spot\n"); p->status = GP_STATUS_PAINTING; @@ -1659,7 +1661,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event) //printf("\tGP - hotkey invoked... waiting for click-drag\n"); } - WM_event_add_notifier(C, NC_SCREEN | ND_GPENCIL, NULL); + WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); /* add a modal handler for this operator, so that we can then draw continuous strokes */ WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; @@ -1687,7 +1689,8 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) //printf("\t\tGP - start stroke\n"); /* we may need to set up paint env again if we're resuming */ - /* XXX: watch it with the paintmode! in future, it'd be nice to allow changing paint-mode when in sketching-sessions */ + /* XXX: watch it with the paintmode! in future, + * it'd be nice to allow changing paint-mode when in sketching-sessions */ /* XXX: with tablet events, we may event want to check for eraser here, for nicer tablet support */ if (gp_session_initdata(C, p)) @@ -1720,7 +1723,7 @@ static void gpencil_stroke_end(wmOperator *op) static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) { tGPsdata *p = op->customdata; - int estate = OPERATOR_PASS_THROUGH; /* default exit state - not handled, so let others have a share of the pie */ + int estate = OPERATOR_RUNNING_MODAL; /* default exit state - we don't pass on events, GP is used with key-modifiers */ /* if (event->type == NDOF_MOTION) * return OPERATOR_PASS_THROUGH; @@ -1736,25 +1739,32 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) //printf("\tGP - handle modal event...\n"); - /* exit painting mode (and/or end current stroke) */ - if (ELEM5(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY, RIGHTMOUSE)) { + /* exit painting mode (and/or end current stroke) + * NOTE: cannot do RIGHTMOUSE (as is standard for cancelling) as that would break polyline [#32647] + */ + if (ELEM4(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY)) { /* exit() ends the current stroke before cleaning up */ //printf("\t\tGP - end of paint op + end of stroke\n"); p->status = GP_STATUS_DONE; estate = OPERATOR_FINISHED; } - /* toggle painting mode upon mouse-button movement */ - if (event->type == LEFTMOUSE) { + /* toggle painting mode upon mouse-button movement + * - LEFTMOUSE = standard drawing (all) / straight line drawing (all) / polyline (toolbox only) + * - RIGHTMOUSE = polyline (hotkey) / eraser (all) + * (Disabling RIGHTMOUSE case here results in bugs like [#32647]) + */ + if (ELEM(event->type, LEFTMOUSE, RIGHTMOUSE)) { /* if painting, end stroke */ if (p->status == GP_STATUS_PAINTING) { int sketch = 0; + /* basically, this should be mouse-button up = end stroke * BUT what happens next depends on whether we 'painting sessions' is enabled */ sketch |= GPENCIL_SKETCH_SESSIONS_ON(p->scene); /* polyline drawing is also 'sketching' -- all knots should be added during one session */ - sketch |= p->paintmode == GP_PAINTMODE_DRAW_POLY; + sketch |= (p->paintmode == GP_PAINTMODE_DRAW_POLY); if (sketch) { /* end stroke only, and then wait to resume painting soon */ @@ -1765,7 +1775,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) estate = OPERATOR_RUNNING_MODAL; /* stroke could be smoothed, send notifier to refresh screen */ - WM_event_add_notifier(C, NC_SCREEN | ND_GPENCIL | NA_EDITED, NULL); + WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); } else { //printf("\t\tGP - end of stroke + op\n"); @@ -1780,7 +1790,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) if (p->status == GP_STATUS_ERROR) { estate = OPERATOR_CANCELLED; } - } + } else { p->status = GP_STATUS_IDLING; } @@ -1855,7 +1865,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) case OPERATOR_FINISHED: /* one last flush before we're done */ gpencil_draw_exit(C, op); - WM_event_add_notifier(C, NC_SCREEN | ND_GPENCIL | NA_EDITED, NULL); // XXX need a nicer one that will work + WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); break; case OPERATOR_CANCELLED: @@ -1864,7 +1874,10 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) case OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH: /* event doesn't need to be handled */ - //printf("unhandled event -> %d (mmb? = %d | mmv? = %d)\n", event->type, event->type == MIDDLEMOUSE, event->type==MOUSEMOVE); +#if 0 + printf("unhandled event -> %d (mmb? = %d | mmv? = %d)\n", + event->type, event->type == MIDDLEMOUSE, event->type==MOUSEMOVE); +#endif break; } @@ -1875,10 +1888,10 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) /* ------------------------------- */ static EnumPropertyItem prop_gpencil_drawmodes[] = { - {GP_PAINTMODE_DRAW, "DRAW", 0, "Draw Freehand", ""}, - {GP_PAINTMODE_DRAW_STRAIGHT, "DRAW_STRAIGHT", 0, "Draw Straight Lines", ""}, - {GP_PAINTMODE_DRAW_POLY, "DRAW_POLY", 0, "Draw Poly Line", ""}, - {GP_PAINTMODE_ERASER, "ERASER", 0, "Eraser", ""}, + {GP_PAINTMODE_DRAW, "DRAW", 0, "Draw Freehand", "Draw freehand stroke(s)"}, + {GP_PAINTMODE_DRAW_STRAIGHT, "DRAW_STRAIGHT", 0, "Draw Straight Lines", "Draw straight line segment(s)"}, + {GP_PAINTMODE_DRAW_POLY, "DRAW_POLY", 0, "Draw Poly Line", "Click to place endpoints of straight line segments (connected)"}, + {GP_PAINTMODE_ERASER, "ERASER", 0, "Eraser", "Erase Grease Pencil strokes"}, {0, NULL, 0, NULL, NULL} }; @@ -1900,7 +1913,7 @@ void GPENCIL_OT_draw(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; /* settings for drawing */ - RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements"); + ot->prop = RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements"); RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); } diff --git a/source/blender/editors/gpencil/gpencil_undo.c b/source/blender/editors/gpencil/gpencil_undo.c index fa9f5196866..3d2cd260fb9 100644 --- a/source/blender/editors/gpencil/gpencil_undo.c +++ b/source/blender/editors/gpencil/gpencil_undo.c @@ -111,7 +111,7 @@ int ED_undo_gpencil_step(bContext *C, int step, const char *name) } } - WM_event_add_notifier(C, NC_SCREEN | ND_GPENCIL | NA_EDITED, NULL); + WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index e1401a8ff88..8d7ae3aad6a 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -232,28 +232,28 @@ typedef enum eAnimFilter_Flags { /* Dopesheet only */ /* 'Scene' channels */ -#define SEL_SCEC(sce) ((sce->flag & SCE_DS_SELECTED)) -#define EXPANDED_SCEC(sce) ((sce->flag & SCE_DS_COLLAPSED) == 0) +#define SEL_SCEC(sce) (CHECK_TYPE_INLINE(sce, Scene), ((sce->flag & SCE_DS_SELECTED))) +#define EXPANDED_SCEC(sce) (CHECK_TYPE_INLINE(sce, Scene), ((sce->flag & SCE_DS_COLLAPSED) == 0)) /* 'Sub-Scene' channels (flags stored in Data block) */ -#define FILTER_WOR_SCED(wo) ((wo->flag & WO_DS_EXPAND)) +#define FILTER_WOR_SCED(wo) (CHECK_TYPE_INLINE(wo, World), (wo->flag & WO_DS_EXPAND)) /* 'Object' channels */ -#define SEL_OBJC(base) ((base->flag & SELECT)) -#define EXPANDED_OBJC(ob) ((ob->nlaflag & OB_ADS_COLLAPSED) == 0) +#define SEL_OBJC(base) (CHECK_TYPE_INLINE(base, Base), ((base->flag & SELECT))) +#define EXPANDED_OBJC(ob) (CHECK_TYPE_INLINE(ob, Object), ((ob->nlaflag & OB_ADS_COLLAPSED) == 0)) /* 'Sub-object' channels (flags stored in Data block) */ -#define FILTER_SKE_OBJD(key) ((key->flag & KEY_DS_EXPAND)) -#define FILTER_MAT_OBJD(ma) ((ma->flag & MA_DS_EXPAND)) -#define FILTER_LAM_OBJD(la) ((la->flag & LA_DS_EXPAND)) -#define FILTER_CAM_OBJD(ca) ((ca->flag & CAM_DS_EXPAND)) -#define FILTER_CUR_OBJD(cu) ((cu->flag & CU_DS_EXPAND)) -#define FILTER_PART_OBJD(part) ((part->flag & PART_DS_EXPAND)) -#define FILTER_MBALL_OBJD(mb) ((mb->flag2 & MB_DS_EXPAND)) -#define FILTER_ARM_OBJD(arm) ((arm->flag & ARM_DS_EXPAND)) -#define FILTER_MESH_OBJD(me) ((me->flag & ME_DS_EXPAND)) -#define FILTER_LATTICE_OBJD(lt) ((lt->flag & LT_DS_EXPAND)) -#define FILTER_SPK_OBJD(spk) ((spk->flag & SPK_DS_EXPAND)) +#define FILTER_SKE_OBJD(key) (CHECK_TYPE_INLINE(key, Key), ((key->flag & KEY_DS_EXPAND))) +#define FILTER_MAT_OBJD(ma) (CHECK_TYPE_INLINE(ma, Material), ((ma->flag & MA_DS_EXPAND))) +#define FILTER_LAM_OBJD(la) (CHECK_TYPE_INLINE(la, Lamp), ((la->flag & LA_DS_EXPAND))) +#define FILTER_CAM_OBJD(ca) (CHECK_TYPE_INLINE(ca, Camera), ((ca->flag & CAM_DS_EXPAND))) +#define FILTER_CUR_OBJD(cu) (CHECK_TYPE_INLINE(cu, Curve), ((cu->flag & CU_DS_EXPAND))) +#define FILTER_PART_OBJD(part) (CHECK_TYPE_INLINE(part, ParticleSettings), ((part->flag & PART_DS_EXPAND))) +#define FILTER_MBALL_OBJD(mb) (CHECK_TYPE_INLINE(mb, MetaBall), ((mb->flag2 & MB_DS_EXPAND))) +#define FILTER_ARM_OBJD(arm) (CHECK_TYPE_INLINE(arm, bArmature), ((arm->flag & ARM_DS_EXPAND))) +#define FILTER_MESH_OBJD(me) (CHECK_TYPE_INLINE(me, Mesh), ((me->flag & ME_DS_EXPAND))) +#define FILTER_LATTICE_OBJD(lt) (CHECK_TYPE_INLINE(lt, Lattice), ((lt->flag & LT_DS_EXPAND))) +#define FILTER_SPK_OBJD(spk) (CHECK_TYPE_INLINE(spk, Speaker), ((spk->flag & SPK_DS_EXPAND))) /* Variable use expanders */ -#define FILTER_NTREE_DATA(ntree) ((ntree->flag & NTREE_DS_EXPAND)) -#define FILTER_TEX_DATA(tex) ((tex->flag & TEX_DS_EXPAND)) +#define FILTER_NTREE_DATA(ntree) (CHECK_TYPE_INLINE(ntree, bNodeTree), ((ntree->flag & NTREE_DS_EXPAND))) +#define FILTER_TEX_DATA(tex) (CHECK_TYPE_INLINE(tex, Tex), ((tex->flag & TEX_DS_EXPAND))) /* 'Sub-object/Action' channels (flags stored in Action) */ #define SEL_ACTC(actc) ((actc->flag & ACT_SELECTED)) diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 07f3498580c..efd10f3cb6b 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -93,8 +93,18 @@ typedef struct EditBone { #define BONESEL_NOSEL (1 << 31) /* Indicates a negative number */ /* useful macros */ -#define EBONE_VISIBLE(arm, ebone) (((arm)->layer & (ebone)->layer) && !((ebone)->flag & BONE_HIDDEN_A)) -#define EBONE_EDITABLE(ebone) (((ebone)->flag & BONE_SELECTED) && !((ebone)->flag & BONE_EDITMODE_LOCKED)) +#define EBONE_VISIBLE(arm, ebone) ( \ + CHECK_TYPE_INLINE(arm, bArmature), \ + CHECK_TYPE_INLINE(ebone, EditBone), \ + (((arm)->layer & (ebone)->layer) && !((ebone)->flag & BONE_HIDDEN_A)) \ + ) + +#define EBONE_SELECTABLE(arm, ebone) (EBONE_VISIBLE(arm, ebone) && !(ebone->flag & BONE_UNSELECTABLE)) + +#define EBONE_EDITABLE(ebone) ( \ + CHECK_TYPE_INLINE(ebone, EditBone), \ + (((ebone)->flag & BONE_SELECTED) && !((ebone)->flag & BONE_EDITMODE_LOCKED)) \ + ) /* used in bone_select_hierachy() */ #define BONE_SELECT_PARENT 0 @@ -148,6 +158,7 @@ void ED_armature_enter_posemode(struct bContext *C, struct Base *base); int ED_pose_channel_in_IK_chain(struct Object *ob, struct bPoseChannel *pchan); void ED_pose_deselectall(struct Object *ob, int test); void ED_pose_recalculate_paths(struct Scene *scene, struct Object *ob); +struct Object *ED_pose_object_from_context(struct bContext *C); /* sketch */ diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h index ac8d82e9060..d66cc49a5d0 100644 --- a/source/blender/editors/include/ED_curve.h +++ b/source/blender/editors/include/ED_curve.h @@ -67,7 +67,7 @@ void BKE_curve_editNurb_free(struct Curve *cu); int mouse_nurb(struct bContext *C, const int mval[2], int extend, int deselect, int toggle); -struct Nurb *add_nurbs_primitive(struct bContext *C, float mat[4][4], int type, int newob); +struct Nurb *add_nurbs_primitive(struct bContext *C, struct Object *obedit, float mat[4][4], int type, int newob); int isNurbsel(struct Nurb *nu); void ED_nurb_set_spline_type(struct Nurb *nu, int type); diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h index 8a65699f404..ffee46e30c6 100644 --- a/source/blender/editors/include/ED_keyframes_draw.h +++ b/source/blender/editors/include/ED_keyframes_draw.h @@ -157,4 +157,3 @@ short compare_ab_cfraPtr(void *node, void *data); short actkeyblock_is_valid(ActKeyBlock *ab, struct DLRBT_Tree *keys); #endif /* __ED_KEYFRAMES_DRAW_H__ */ - diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index dc40b687dfd..46ed9798d32 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -88,8 +88,8 @@ void free_gpcopybuf(void); void copy_gpdata(void); void paste_gpdata(void); - void snap_masklayer_frames(struct MaskLayer *masklay, short mode); - void mirror_masklayer_frames(struct MaskLayer *masklay, short mode); +void snap_masklayer_frames(struct MaskLayer *masklay, short mode); +void mirror_masklayer_frames(struct MaskLayer *masklay, short mode); #endif #endif /* __ED_MASK_H__ */ diff --git a/source/blender/editors/include/ED_mball.h b/source/blender/editors/include/ED_mball.h index b4b739e4d06..1321765588d 100644 --- a/source/blender/editors/include/ED_mball.h +++ b/source/blender/editors/include/ED_mball.h @@ -38,7 +38,7 @@ struct wmKeyConfig; void ED_operatortypes_metaball(void); void ED_keymap_metaball(struct wmKeyConfig *keyconf); -struct MetaElem *add_metaball_primitive(struct bContext *C, float mat[4][4], int type, int newname); +struct MetaElem *add_metaball_primitive(struct bContext *C, struct Object *obedit, float mat[4][4], float dia, int type, int newname); int mouse_mball(struct bContext *C, const int mval[2], int extend, int deselect, int toggle); diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 1d4fbe81e02..5ffcfbd94f0 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -61,6 +61,7 @@ struct BMEditMesh; struct BMEditSelection; struct BMesh; struct BMVert; +struct BMLoop; struct MLoopCol; struct BMEdge; struct BMFace; @@ -79,6 +80,7 @@ struct BMVert *EDBM_verts_mirror_get(struct BMEditMesh *em, struct BMVert *v); void EDBM_verts_mirror_cache_clear(struct BMEditMesh *em, struct BMVert *v); void EDBM_verts_mirror_cache_end(struct BMEditMesh *em); +void EDBM_mesh_ensure_valid_dm_hack(struct Scene *scene, struct BMEditMesh *em); void EDBM_mesh_normals_update(struct BMEditMesh *em); void EDBM_mesh_clear(struct BMEditMesh *em); @@ -117,6 +119,7 @@ void EDBM_update_generic(struct bContext *C, struct BMEditMesh *em, const short struct UvElementMap *EDBM_uv_element_map_create(struct BMEditMesh *em, int selected, int doIslands); void EDBM_uv_element_map_free(struct UvElementMap *vmap); +struct UvElement *ED_uv_element_get(struct UvElementMap *map, struct BMFace *efa, struct BMLoop *l); int EDBM_mtexpoly_check(struct BMEditMesh *em); struct MTexPoly *EDBM_mtexpoly_active_get(struct BMEditMesh *em, struct BMFace **r_act_efa, int sloppy, int selected); @@ -137,18 +140,18 @@ int EDBM_backbuf_border_init(struct ViewContext *vc, short xmin, short ymin, sh int EDBM_backbuf_check(unsigned int index); void EDBM_backbuf_free(void); -int EDBM_backbuf_border_mask_init(struct ViewContext *vc, int mcords[][2], short tot, +int EDBM_backbuf_border_mask_init(struct ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax); int EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads); -struct BMVert *EDBM_vert_find_nearest(struct ViewContext *vc, int *dist, short sel, short strict); -struct BMEdge *EDBM_edge_find_nearest(struct ViewContext *vc, int *dist); -struct BMFace *EDBM_face_find_nearest(struct ViewContext *vc, int *dist); +struct BMVert *EDBM_vert_find_nearest(struct ViewContext *vc, float *r_dist, const short sel, const short strict); +struct BMEdge *EDBM_edge_find_nearest(struct ViewContext *vc, float *r_dist); +struct BMFace *EDBM_face_find_nearest(struct ViewContext *vc, float *r_dist); int EDBM_select_pick(struct bContext *C, const int mval[2], short extend, short deselect, short toggle); void EDBM_selectmode_set(struct BMEditMesh *em); -void EDBM_selectmode_convert(struct BMEditMesh *em, short oldmode, const short selectmode); +void EDBM_selectmode_convert(struct BMEditMesh *em, const short selectmode_old, const short selectmode_new); void EDBM_deselect_by_material(struct BMEditMesh *em, const short index, const short select); @@ -173,7 +176,7 @@ void ED_spacetypes_init(void); /* editmesh_tools.c (could be moved) */ -void EMBM_project_snap_verts(struct bContext *C, struct ARegion *ar, struct Object *obedit, struct BMEditMesh *em); +void EMBM_project_snap_verts(struct bContext *C, struct ARegion *ar, struct BMEditMesh *em); /* editface.c */ @@ -247,7 +250,7 @@ void ED_mesh_update(struct Mesh *mesh, struct bContext *C, int calc_edges, int c int ED_mesh_uv_texture_add(struct bContext *C, struct Mesh *me, const char *name, int active_set); int ED_mesh_uv_texture_remove(struct bContext *C, struct Object *ob, struct Mesh *me); int ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me); -int ED_mesh_uv_loop_reset_ex(struct bContext *C, struct Mesh *me, const int layernum); +int ED_mesh_uv_loop_reset_ex(struct Mesh *me, const int layernum); int ED_mesh_color_add(struct bContext *C, struct Scene *scene, struct Object *ob, struct Mesh *me, const char *name, int active_set); int ED_mesh_color_remove(struct bContext *C, struct Object *ob, struct Mesh *me); int ED_mesh_color_remove_named(struct bContext *C, struct Object *ob, struct Mesh *me, const char *name); diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index a08db8072f2..0d0b8d8e797 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -35,22 +35,31 @@ extern "C" { #endif +struct BMEdge; +struct BMFace; +struct BMVert; +struct BPoint; struct Base; -struct bConstraint; -struct bContext; -struct bPoseChannel; +struct BezTriple; struct Curve; +struct EditBone; struct EnumPropertyItem; struct ID; struct KeyBlock; struct Lattice; struct Main; struct Mesh; +struct MetaElem; struct ModifierData; +struct Nurb; struct Object; struct ReportList; struct Scene; struct View3D; +struct ViewContext; +struct bConstraint; +struct bContext; +struct bPoseChannel; struct wmEvent; struct wmKeyConfig; struct wmKeyMap; @@ -82,11 +91,13 @@ typedef enum eParentType { PAR_TRIA } eParentType; +#ifdef __RNA_TYPES_H__ extern struct EnumPropertyItem prop_clear_parent_types[]; extern struct EnumPropertyItem prop_make_parent_types[]; +#endif int ED_object_parent_set(struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct Object *ob, - struct Object *par, int partype, int xmirror); + struct Object *par, int partype, int xmirror, int keep_transform); void ED_object_parent_clear(struct Object *ob, int type); struct Base *ED_object_scene_link(struct Scene *scene, struct Object *ob); @@ -123,10 +134,10 @@ void ED_object_location_from_view(struct bContext *C, float loc[3]); void ED_object_rotation_from_view(struct bContext *C, float rot[3]); void ED_object_base_init_transform(struct bContext *C, struct Base *base, const float loc[3], const float rot[3]); float ED_object_new_primitive_matrix(struct bContext *C, struct Object *editob, - const float loc[3], const float rot[3], float primmat[][4]); + const float loc[3], const float rot[3], float primmat[][4], + int apply_diameter); void ED_object_add_generic_props(struct wmOperatorType *ot, int do_editmode); -int ED_object_add_generic_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int ED_object_add_generic_get_opts(struct bContext *C, struct wmOperator *op, float loc[3], float rot[3], int *enter_editmode, unsigned int *layer, int *is_view_aligned); @@ -184,7 +195,7 @@ int ED_object_iter_other(struct Main *bmain, struct Object *orig_ob, int include int ED_object_multires_update_totlevels_cb(struct Object *ob, void *totlevel_v); -/* ibject_select.c */ +/* object_select.c */ void ED_object_select_linked_by_id(struct bContext *C, struct ID *id); #ifdef __cplusplus @@ -192,4 +203,3 @@ void ED_object_select_linked_by_id(struct bContext *C, struct ID *id); #endif #endif /* __ED_OBJECT_H__ */ - diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h index 0076b08da99..dee97c7882a 100644 --- a/source/blender/editors/include/ED_particle.h +++ b/source/blender/editors/include/ED_particle.h @@ -61,7 +61,7 @@ void PE_update_object(struct Scene *scene, struct Object *ob, int useflag); int PE_mouse_particles(struct bContext *C, const int mval[2], int extend, int deselect, int toggle); int PE_border_select(struct bContext *C, struct rcti *rect, int select, int extend); int PE_circle_select(struct bContext *C, int selecting, const int mval[2], float rad); -int PE_lasso_select(struct bContext *C, int mcords[][2], short moves, short extend, short select); +int PE_lasso_select(struct bContext *C, const int mcords[][2], const short moves, short extend, short select); void PE_deselect_all_visible(struct PTCacheEdit *edit); /* undo */ diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index fc20bdfb9c5..860d176ffb3 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -111,6 +111,7 @@ ScrArea *ED_screen_full_newspace(struct bContext *C, ScrArea *sa, int type); void ED_screen_full_prevspace(struct bContext *C, ScrArea *sa); void ED_screen_full_restore(struct bContext *C, ScrArea *sa); struct ScrArea *ED_screen_full_toggle(struct bContext *C, struct wmWindow *win, struct ScrArea *sa); +void ED_screens_header_tools_menu_create(struct bContext *C, struct uiLayout *layout, void *arg); /* anim */ void ED_update_for_newframe(struct Main *bmain, struct Scene *scene, int mute); @@ -170,6 +171,7 @@ int ED_operator_editmball(struct bContext *C); int ED_operator_uvedit(struct bContext *C); int ED_operator_uvmap(struct bContext *C); int ED_operator_posemode_exclusive(struct bContext *C); +int ED_operator_posemode_context(struct bContext *C); int ED_operator_posemode(struct bContext *C); int ED_operator_mask(struct bContext *C); diff --git a/source/blender/editors/include/ED_screen_types.h b/source/blender/editors/include/ED_screen_types.h index 527ebb6c3ef..9f42fd042c3 100644 --- a/source/blender/editors/include/ED_screen_types.h +++ b/source/blender/editors/include/ED_screen_types.h @@ -94,7 +94,7 @@ typedef struct AZone { /* for draw */ short x1, y1, x2, y2; /* for clip */ - rcti rect; + rcti rect; } AZone; /* actionzone type */ diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h index e908868df75..0381ecc1fb3 100644 --- a/source/blender/editors/include/ED_sculpt.h +++ b/source/blender/editors/include/ED_sculpt.h @@ -45,8 +45,12 @@ void sculpt_get_redraw_planes(float planes[4][4], struct ARegion *ar, void ED_sculpt_force_update(struct bContext *C); float *ED_sculpt_get_last_stroke(struct Object *ob); int ED_sculpt_minmax(struct bContext *C, float min[3], float max[3]); -void ED_sculpt_mask_layers_ensure(struct Object *ob, +int ED_sculpt_mask_layers_ensure(struct Object *ob, struct MultiresModifierData *mmd); +enum { + ED_SCULPT_MASK_LAYER_CALC_VERT = (1 << 0), + ED_SCULPT_MASK_LAYER_CALC_LOOP = (1 << 1) +}; /* paint_ops.c */ void ED_operatortypes_paint(void); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index b1bccfa32c5..bd85e93f1af 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -37,20 +37,26 @@ struct BMEdge; struct BMFace; struct BMVert; struct BPoint; +struct Base; struct BezTriple; struct BezTriple; struct BoundBox; +struct EditBone; struct ImBuf; struct MVert; struct Main; +struct MetaElem; struct Nurb; struct Nurb; struct Object; struct RegionView3D; struct Scene; +struct ScrArea; struct View3D; struct ViewContext; struct bContext; +struct bPoseChannel; +struct bScreen; struct bglMats; struct rcti; struct wmOperator; @@ -78,159 +84,134 @@ typedef struct ViewDepths { char damaged; } ViewDepths; -/* enum for passing to foreach functions to test RV3D_CLIPPING */ -typedef enum eV3DClipTest { - V3D_CLIP_TEST_OFF = 0, /* clipping is off */ - V3D_CLIP_TEST_RV3D_CLIPPING = 1, /* clip single points */ - V3D_CLIP_TEST_REGION = 2 /* use for edges to check if both verts are in the view, but not RV3D_CLIPPING */ -} eV3DClipTest; - float *give_cursor(struct Scene *scene, struct View3D *v3d); -int initgrabz(struct RegionView3D *rv3d, float x, float y, float z); - -/** - * Calculate a 3d location from 2d window coordinates. - * \param ar The region (used for the window width and height). - * \param depth_pt The reference location used to calculate the Z depth. - * \param mval The area relative location (such as event->mval converted to floats). - * \param out The resulting world-space location. - */ -void ED_view3d_win_to_3d(struct ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]); - -/** - * Calculate a 3d difference vector from 2d window offset. - * note that initgrabz() must be called first to determine - * the depth used to calculate the delta. - * \param ar The region (used for the window width and height). - * \param mval The area relative 2d difference (such as event->mval[0] - other_x). - * \param out The resulting world-space delta. - */ -void ED_view3d_win_to_delta(struct ARegion *ar, const float mval[2], float out[3]); - -/** - * Calculate a 3d direction vector from 2d window coordinates. - * This direction vector starts and the view in the direction of the 2d window coordinates. - * In orthographic view all window coordinates yield the same vector. - * \param ar The region (used for the window width and height). - * \param mval The area relative 2d location (such as event->mval converted to floats). - * \param out The resulting normalized world-space direction vector. - */ -void ED_view3d_win_to_vector(struct ARegion *ar, const float mval[2], float out[3]); - -/** - * Calculate a 3d segment from 2d window coordinates. - * This ray_start is located at the viewpoint, ray_end is a far point. - * ray_start and ray_end are clipped by the view near and far limits - * so points along this line are always in view. - * In orthographic view all resulting segments will be parallel. - * \param ar The region (used for the window width and height). - * \param v3d The 3d viewport (used for near and far clipping range). - * \param mval The area relative 2d location (such as event->mval, converted into float[2]). - * \param ray_start The world-space starting point of the segment. - * \param ray_end The world-space end point of the segment. - */ -void ED_view3d_win_to_segment_clip(struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]); - -/** - * Calculate a 3d viewpoint and direction vector from 2d window coordinates. - * This ray_start is located at the viewpoint, ray_normal is the direction towards mval. - * ray_start is clipped by the view near limit so points in front of it are always in view. - * In orthographic view the resulting ray_normal will match the view vector. - * \param ar The region (used for the window width and height). - * \param v3d The 3d viewport (used for near clipping value). - * \param mval The area relative 2d location (such as event->mval, converted into float[2]). - * \param ray_start The world-space starting point of the segment. - * \param ray_normal The normalized world-space direction of towards mval. - */ -void ED_view3d_win_to_ray(struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_normal[3]); - -/** - * Calculate a normalized 3d direction vector from the viewpoint towards a global location. - * In orthographic view the resulting vector will match the view vector. - * \param rv3d The region (used for the window width and height). - * \param coord The world-space location. - * \param vec The resulting normalized vector. - */ -void ED_view3d_global_to_vector(struct RegionView3D *rv3d, const float coord[3], float vec[3]); - -/** - * Calculate the view transformation matrix from RegionView3D input. - * The resulting matrix is equivalent to RegionView3D.viewinv - * \param mat The view 4x4 transformation matrix to calculate. - * \param ofs The view offset, normally from RegionView3D.ofs. - * \param quat The view rotation, quaternion normally from RegionView3D.viewquat. - * \param dist The view distance from ofs, normally from RegionView3D.dist. - */ void ED_view3d_to_m4(float mat[][4], const float ofs[3], const float quat[4], const float dist); - -/** - * Set the view transformation from a 4x4 matrix. - * \param mat The view 4x4 transformation matrix to assign. - * \param ofs The view offset, normally from RegionView3D.ofs. - * \param quat The view rotation, quaternion normally from RegionView3D.viewquat. - * \param dist The view distance from ofs, normally from RegionView3D.dist. - */ void ED_view3d_from_m4(float mat[][4], float ofs[3], float quat[4], float *dist); -/** - * Set the RegionView3D members from an objects transformation and optionally lens. - * \param ob The object to set the view to. - * \param ofs The view offset to be set, normally from RegionView3D.ofs. - * \param quat The view rotation to be set, quaternion normally from RegionView3D.viewquat. - * \param dist The view distance from ofs to be set, normally from RegionView3D.dist. - * \param lens The view lens angle set for cameras and lamps, normally from View3D.lens. - */ void ED_view3d_from_object(struct Object *ob, float ofs[3], float quat[4], float *dist, float *lens); - -/** - * Set the object transformation from RegionView3D members. - * \param ob The object which has the transformation assigned. - * \param ofs The view offset, normally from RegionView3D.ofs. - * \param quat The view rotation, quaternion normally from RegionView3D.viewquat. - * \param dist The view distance from ofs, normally from RegionView3D.dist. - */ void ED_view3d_to_object(struct Object *ob, const float ofs[3], const float quat[4], const float dist); -//#if 0 /* UNUSED */ -void view3d_unproject(struct bglMats *mats, float out[3], const short x, const short y, const float z); -//#endif - /* Depth buffer */ -void ED_view3d_depth_update(struct ARegion *ar); +void ED_view3d_depth_update(struct ARegion *ar); float ED_view3d_depth_read_cached(struct ViewContext *vc, int x, int y); -void ED_view3d_depth_tag_update(struct RegionView3D *rv3d); +void ED_view3d_depth_tag_update(struct RegionView3D *rv3d); /* Projection */ #define IS_CLIPPED 12000 -void ED_view3d_calc_clipping(struct BoundBox *bb, float planes[4][4], struct bglMats *mats, const struct rcti *rect); +/* TODO, these functions work quite differently, we should make them behave in a uniform way + * otherwise we can't be sure bugs are not added when we need to move from short->float types for eg + * - Campbell */ -void project_short(struct ARegion *ar, const float vec[3], short adr[2]); -void project_short_noclip(struct ARegion *ar, const float vec[3], short adr[2]); -void project_int(struct ARegion *ar, const float vec[3], int adr[2]); -void project_int_noclip(struct ARegion *ar, const float vec[3], int adr[2]); +/* return values for ED_view3d_project_...() */ +typedef enum { + V3D_PROJ_RET_OK = 0, + V3D_PROJ_RET_CLIP_NEAR = 1, /* can't avoid this when in perspective mode, (can't avoid) */ + V3D_PROJ_RET_CLIP_BB = 2, /* bounding box clip - RV3D_CLIPPING */ + V3D_PROJ_RET_CLIP_WIN = 3, /* outside window bounds */ + V3D_PROJ_RET_OVERFLOW = 4 /* outside range (mainly for short), (can't avoid) */ +} eV3DProjStatus; -void apply_project_float(float persmat[4][4], int winx, int winy, const float vec[], float adr[2]); -void project_float(struct ARegion *ar, const float vec[3], float adr[2]); -void project_float_noclip(struct ARegion *ar, const float vec[3], float adr[2]); +/* some clipping tests are optional */ +typedef enum { + V3D_PROJ_TEST_NOP = 0, + V3D_PROJ_TEST_CLIP_BB = (1 << 0), + V3D_PROJ_TEST_CLIP_WIN = (1 << 1), +} eV3DProjTest; -int ED_view3d_clip_range_get(struct View3D *v3d, struct RegionView3D *rv3d, float *clipsta, float *clipend); -int ED_view3d_viewplane_get(struct View3D *v3d, struct RegionView3D *rv3d, int winxi, int winyi, struct rctf *viewplane, float *clipsta, float *clipend); +#define V3D_PROJ_TEST_CLIP_DEFAULT (V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN) +#define V3D_PROJ_TEST_ALL (V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN) + + +/* view3d_iterators.c */ + +/* foreach iterators */ +void mesh_foreachScreenVert( + struct ViewContext *vc, + void (*func)(void *userData, struct BMVert *eve, const float screen_co[2], int index), + void *userData, const eV3DProjTest clip_flag); +void mesh_foreachScreenEdge( + struct ViewContext *vc, + void (*func)(void *userData, struct BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], + int index), + void *userData, const eV3DProjTest clip_flag); +void mesh_foreachScreenFace( + struct ViewContext *vc, + void (*func)(void *userData, struct BMFace *efa, const float screen_co[2], int index), + void *userData, const eV3DProjTest clip_flag); +void nurbs_foreachScreenVert( + struct ViewContext *vc, + void (*func)(void *userData, struct Nurb *nu, struct BPoint *bp, struct BezTriple *bezt, + int beztindex, const float screen_co[2]), + void *userData, const eV3DProjTest clip_flag); +void mball_foreachScreenElem( + struct ViewContext *vc, + void (*func)(void *userData, struct MetaElem *ml, const float screen_co[2]), + void *userData, const eV3DProjTest clip_flag); +void lattice_foreachScreenVert( + struct ViewContext *vc, + void (*func)(void *userData, struct BPoint *bp, + const float screen_co[2]), + void *userData, const eV3DProjTest clip_flag); +void armature_foreachScreenBone( + struct ViewContext *vc, + void (*func)(void *userData, struct EditBone *ebone, + const float screen_co_a[2], const float screen_co_b[2]), + void *userData, const eV3DProjTest clip_flag); +void pose_foreachScreenBone( + struct ViewContext *vc, + void (*func)(void *userData, struct bPoseChannel *pchan, + const float screen_co_a[2], const float screen_co_b[2]), + void *userData, const eV3DProjTest clip_flag); +/* *** end iterators *** */ + + +/* view3d_project.c */ +void ED_view3d_project_float_v2_m4(const struct ARegion *a, const float co[3], float r_co[2], float mat[4][4]); +void ED_view3d_project_float_v3_m4(struct ARegion *a, const float co[3], float r_co[3], float mat[4][4]); + +eV3DProjStatus ED_view3d_project_base(struct ARegion *ar, struct Base *base); + +/* *** short *** */ +eV3DProjStatus ED_view3d_project_short_ex(struct ARegion *ar, float perspmat[4][4], const int is_local, + const float co[3], short r_co[2], const eV3DProjTest flag); +eV3DProjStatus ED_view3d_project_short_global(struct ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag); +eV3DProjStatus ED_view3d_project_short_object(struct ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag); + +/* *** int *** */ +eV3DProjStatus ED_view3d_project_int_ex(struct ARegion *ar, float perspmat[4][4], const int is_local, + const float co[3], int r_co[2], const eV3DProjTest flag); +eV3DProjStatus ED_view3d_project_int_global(struct ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag); +eV3DProjStatus ED_view3d_project_int_object(struct ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag); + +/* *** float *** */ +eV3DProjStatus ED_view3d_project_float_ex(struct ARegion *ar, float perspmat[4][4], const int is_local, + const float co[3], float r_co[2], const eV3DProjTest flag); +eV3DProjStatus ED_view3d_project_float_global(struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag); +eV3DProjStatus ED_view3d_project_float_object(struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag); + +int initgrabz(struct RegionView3D *rv3d, float x, float y, float z); +void ED_view3d_win_to_ray(struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_normal[3]); +void ED_view3d_global_to_vector(struct RegionView3D *rv3d, const float coord[3], float vec[3]); +void ED_view3d_win_to_3d(struct ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]); +void ED_view3d_win_to_delta(struct ARegion *ar, const float mval[2], float out[3]); +void ED_view3d_win_to_vector(struct ARegion *ar, const float mval[2], float out[3]); +void ED_view3d_win_to_segment_clip(struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]); void ED_view3d_ob_project_mat_get(struct RegionView3D *v3d, struct Object *ob, float pmat[4][4]); +void ED_view3d_unproject(struct bglMats *mats, float out[3], const float x, const float y, const float z); + +/* end */ + + + +int ED_view3d_clip_range_get(struct View3D *v3d, struct RegionView3D *rv3d, float *clipsta, float *clipend); +int ED_view3d_viewplane_get(struct View3D *v3d, struct RegionView3D *rv3d, int winxi, int winyi, struct rctf *viewplane, float *clipsta, float *clipend); void ED_view3d_calc_camera_border(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, struct RegionView3D *rv3d, struct rctf *viewborder_r, short no_shift); -void ED_view3d_project_float_v2(const struct ARegion *a, const float vec[3], float adr[2], float mat[4][4]); -void ED_view3d_project_float_v3(struct ARegion *a, const float vec[3], float adr[3], float mat[4][4]); void ED_view3d_calc_camera_border_size(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, struct RegionView3D *rv3d, float size_r[2]); -/* drawobject.c iterators */ -void mesh_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct BMVert *eve, int x, int y, int index), void *userData, eV3DClipTest clipVerts); -void mesh_foreachScreenEdge(struct ViewContext *vc, void (*func)(void *userData, struct BMEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, eV3DClipTest clipVerts); -void mesh_foreachScreenFace(struct ViewContext *vc, void (*func)(void *userData, struct BMFace *efa, int x, int y, int index), void *userData); -void nurbs_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct Nurb *nu, struct BPoint *bp, struct BezTriple *bezt, int beztindex, int x, int y), void *userData); -void lattice_foreachScreenVert(struct ViewContext *vc, void (*func)(void *userData, struct BPoint *bp, int x, int y), void *userData); - +void ED_view3d_clipping_calc(struct BoundBox *bb, float planes[4][4], struct bglMats *mats, const struct rcti *rect); void ED_view3d_clipping_local(struct RegionView3D *rv3d, float mat[][4]); int ED_view3d_clipping_test(struct RegionView3D *rv3d, const float vec[3], const int is_local); void ED_view3d_clipping_set(struct RegionView3D *rv3d); @@ -244,7 +225,8 @@ void drawcircball(int mode, const float cent[3], float rad, float tmat[][4]); /* backbuffer select and draw support */ void view3d_validate_backbuf(struct ViewContext *vc); struct ImBuf *view3d_read_backbuf(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax); -unsigned int view3d_sample_backbuf_rect(struct ViewContext *vc, const int mval[2], int size, unsigned int min, unsigned int max, int *dist, short strict, +unsigned int view3d_sample_backbuf_rect(struct ViewContext *vc, const int mval[2], int size, + unsigned int min, unsigned int max, float *dist, short strict, void *handle, unsigned int (*indextest)(void *handle, unsigned int index)); unsigned int view3d_sample_backbuf(struct ViewContext *vc, int x, int y); @@ -268,7 +250,7 @@ int view3d_get_view_aligned_coordinate(struct ViewContext *vc, float fp[3], cons void view3d_get_transformation(const struct ARegion *ar, struct RegionView3D *rv3d, struct Object *ob, struct bglMats *mats); /* XXX should move to BLI_math */ -int edge_inside_circle(int centx, int centy, int rad, int x1, int y1, int x2, int y2); +int edge_inside_circle(const float cent[2], float radius, const float screen_co_a[2], const float screen_co_b[2]); /* get 3d region from context, also if mouse is in header or toolbar */ struct RegionView3D *ED_view3d_context_rv3d(struct bContext *C); @@ -281,6 +263,7 @@ void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d); int ED_view3d_scene_layer_set(int lay, const int *values, int *active); int ED_view3d_context_activate(struct bContext *C); +void ED_view3d_draw_offscreen_init(struct Scene *scene, struct View3D *v3d); void ED_view3d_draw_offscreen(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int winx, int winy, float viewmat[][4], float winmat[][4], int do_bgpic, int colormanage_background); @@ -312,6 +295,7 @@ struct BGpic *ED_view3D_background_image_new(struct View3D *v3d); void ED_view3D_background_image_remove(struct View3D *v3d, struct BGpic *bgpic); void ED_view3D_background_image_clear(struct View3D *v3d); +float ED_view3d_offset_distance(float mat[4][4], float ofs[3]); float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit); /* view matrix properties utilities */ diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index ef7b8ed3a41..e400e44e944 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -94,7 +94,7 @@ DEF_ICON(LINK) DEF_ICON(INLINK) DEF_ICON(PLUGIN) - /* various ui */ + /* various ui */ DEF_ICON(HELP) DEF_ICON(GHOST_ENABLED) DEF_ICON(COLOR) @@ -450,8 +450,8 @@ DEF_ICON(FORCE_CURVE) DEF_ICON(FORCE_BOID) DEF_ICON(FORCE_TURBULENCE) DEF_ICON(FORCE_DRAG) +DEF_ICON(FORCE_SMOKEFLOW) #ifndef DEF_ICON_BLANK_SKIP - DEF_ICON(BLANK672) DEF_ICON(BLANK673) DEF_ICON(BLANK674) DEF_ICON(BLANK675) @@ -799,13 +799,12 @@ DEF_ICON(NDOF_TRANS) DEF_ICON(LAYER_USED) DEF_ICON(LAYER_ACTIVE) #ifndef DEF_ICON_BLANK_SKIP + /* available */ DEF_ICON(BLANK254) DEF_ICON(BLANK255) DEF_ICON(BLANK256) DEF_ICON(BLANK257) DEF_ICON(BLANK257b) - - /* available */ DEF_ICON(BLANK258) DEF_ICON(BLANK259) DEF_ICON(BLANK260) @@ -890,8 +889,8 @@ DEF_ICON(FORWARD) DEF_ICON(BLANK313) DEF_ICON(BLANK314) DEF_ICON(BLANK315) - DEF_ICON(BLANK316) #endif +DEF_ICON(FILE_BACKUP) DEF_ICON(DISK_DRIVE) /* SHADING / TEXT */ diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 917153c9199..ed4b4ae027f 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -106,9 +106,9 @@ typedef struct uiLayout uiLayout; /* uiBlock->flag (controls) */ #define UI_BLOCK_LOOP 1 #define UI_BLOCK_REDRAW 2 -#define UI_BLOCK_RET_1 4 /* XXX 2.5 not implemented */ +#define UI_BLOCK_SEARCH_MENU 4 #define UI_BLOCK_NUMSELECT 8 -/*#define UI_BLOCK_ENTER_OK 16*/ /*UNUSED*/ +#define UI_BLOCK_NO_WIN_CLIP 16 /* don't apply window clipping */ /* was UI_BLOCK_ENTER_OK */ #define UI_BLOCK_CLIPBOTTOM 32 #define UI_BLOCK_CLIPTOP 64 #define UI_BLOCK_MOVEMOUSE_QUIT 128 @@ -120,11 +120,12 @@ typedef struct uiLayout uiLayout; #define UI_BLOCK_CLIP_EVENTS 8192 /* stop handling mouse events */ /* uiPopupBlockHandle->menuretval */ -#define UI_RETURN_CANCEL 1 /* cancel all menus cascading */ -#define UI_RETURN_OK 2 /* choice made */ -#define UI_RETURN_OUT 4 /* left the menu */ -#define UI_RETURN_UPDATE 8 /* update the button that opened */ -#define UI_RETURN_POPUP_OK 16 /* popup is ok to be handled */ +#define UI_RETURN_CANCEL 1 /* cancel all menus cascading */ +#define UI_RETURN_OK 2 /* choice made */ +#define UI_RETURN_OUT 4 /* left the menu */ +#define UI_RETURN_OUT_PARENT 8 /* let the parent handle this event */ +#define UI_RETURN_UPDATE 16 /* update the button that opened */ +#define UI_RETURN_POPUP_OK 32 /* popup is ok to be handled */ /* block->flag bits 12-15 are identical to but->flag bits */ @@ -420,7 +421,6 @@ void uiBlockSetDirection(uiBlock *block, int direction); void uiBlockFlipOrder(uiBlock *block); void uiBlockSetFlag(uiBlock *block, int flag); void uiBlockClearFlag(uiBlock *block, int flag); -void uiBlockSetXOfs(uiBlock *block, int xofs); int uiButGetRetVal(uiBut *but); @@ -810,6 +810,8 @@ void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, const char void uiTemplateColorWheel(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic); void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, const char *propname, PointerRNA *used_ptr, const char *used_propname, int active_layer); +void uiTemplateGameStates(uiLayout *layout, struct PointerRNA *ptr, const char *propname, + PointerRNA *used_ptr, const char *used_propname, int active_state); void uiTemplateImage(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, struct PointerRNA *userptr, int compact); void uiTemplateImageSettings(uiLayout *layout, struct PointerRNA *imfptr, int color_management); void uiTemplateImageLayers(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser); diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index 792c96fe7c8..24759fa778a 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -163,7 +163,8 @@ void UI_view2d_view_orthoSpecial(struct ARegion *ar, struct View2D *v2d, short x void UI_view2d_view_restore(const struct bContext *C); /* grid drawing */ -View2DGrid *UI_view2d_grid_calc(struct Scene *scene, struct View2D *v2d, short xunits, short xclamp, short yunits, short yclamp, int winx, int winy); +View2DGrid *UI_view2d_grid_calc(struct Scene *scene, struct View2D *v2d, + short xunits, short xclamp, short yunits, short yclamp, int winx, int winy); void UI_view2d_grid_draw(struct View2D *v2d, View2DGrid *grid, int flag); void UI_view2d_constant_grid_draw(struct View2D *v2d); void UI_view2d_multi_grid_draw(struct View2D *v2d, float step, int level_size, int totlevels); @@ -171,14 +172,21 @@ void UI_view2d_grid_size(View2DGrid *grid, float *r_dx, float *r_dy); void UI_view2d_grid_free(View2DGrid *grid); /* scrollbar drawing */ -View2DScrollers *UI_view2d_scrollers_calc(const struct bContext *C, struct View2D *v2d, short xunits, short xclamp, short yunits, short yclamp); +View2DScrollers *UI_view2d_scrollers_calc(const struct bContext *C, struct View2D *v2d, + short xunits, short xclamp, short yunits, short yclamp); void UI_view2d_scrollers_draw(const struct bContext *C, struct View2D *v2d, View2DScrollers *scrollers); void UI_view2d_scrollers_free(View2DScrollers *scrollers); /* list view tools */ -void UI_view2d_listview_cell_to_view(struct View2D *v2d, short columnwidth, short rowheight, float startx, float starty, int column, int row, struct rctf *rect); -void UI_view2d_listview_view_to_cell(struct View2D *v2d, short columnwidth, short rowheight, float startx, float starty, float viewx, float viewy, int *column, int *row); -void UI_view2d_listview_visible_cells(struct View2D *v2d, short columnwidth, short rowheight, float startx, float starty, int *column_min, int *column_max, int *row_min, int *row_max); +void UI_view2d_listview_cell_to_view(struct View2D *v2d, short columnwidth, short rowheight, + float startx, float starty, int column, int row, + struct rctf *rect); +void UI_view2d_listview_view_to_cell(struct View2D *v2d, short columnwidth, short rowheight, + float startx, float starty, float viewx, float viewy, + int *column, int *row); +void UI_view2d_listview_visible_cells(struct View2D *v2d, short columnwidth, short rowheight, + float startx, float starty, int *column_min, int *column_max, + int *row_min, int *row_max); /* coordinate conversion */ void UI_view2d_region_to_view(struct View2D *v2d, int x, int y, float *viewx, float *viewy); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 742aed4fbb1..b8e4fec1259 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -79,10 +79,6 @@ #include "interface_intern.h" -#define MENU_WIDTH 120 -#define MENU_ITEM_HEIGHT 20 -#define MENU_SEP_HEIGHT 6 - #define PRECISION_FLOAT_MAX 6 #define PRECISION_FLOAT_MAX_POW 1000000 /* pow(10, PRECISION_FLOAT_MAX) */ @@ -106,8 +102,8 @@ void ui_block_to_window_fl(const ARegion *ar, uiBlock *block, float *x, float *y float gx, gy; int sx, sy, getsizex, getsizey; - getsizex = BLI_RCT_SIZE_X(&ar->winrct) + 1; - getsizey = BLI_RCT_SIZE_Y(&ar->winrct) + 1; + getsizex = BLI_rcti_size_x(&ar->winrct) + 1; + getsizey = BLI_rcti_size_y(&ar->winrct) + 1; sx = ar->winrct.xmin; sy = ar->winrct.ymin; @@ -152,8 +148,8 @@ void ui_window_to_block_fl(const ARegion *ar, uiBlock *block, float *x, float *y float a, b, c, d, e, f, px, py; int sx, sy, getsizex, getsizey; - getsizex = BLI_RCT_SIZE_X(&ar->winrct) + 1; - getsizey = BLI_RCT_SIZE_Y(&ar->winrct) + 1; + getsizex = BLI_rcti_size_x(&ar->winrct) + 1; + getsizey = BLI_rcti_size_y(&ar->winrct) + 1; sx = ar->winrct.xmin; sy = ar->winrct.ymin; @@ -242,7 +238,7 @@ static void ui_text_bounds_block(uiBlock *block, float offset) bt->rect.xmax = bt->rect.xmin + i + block->bounds; if (col == lastcol) { - bt->rect.xmax = maxf(bt->rect.xmax, offset + block->minbounds); + bt->rect.xmax = max_ff(bt->rect.xmax, offset + block->minbounds); } ui_check_but(bt); /* clips text again */ @@ -279,7 +275,7 @@ void ui_bounds_block(uiBlock *block) block->rect.ymax += block->bounds; } - block->rect.xmax = block->rect.xmin + maxf(BLI_RCT_SIZE_X(&block->rect), block->minbounds); + block->rect.xmax = block->rect.xmin + max_ff(BLI_rctf_size_x(&block->rect), block->minbounds); /* hardcoded exception... but that one is annoying with larger safety */ bt = block->buttons.first; @@ -307,8 +303,8 @@ static void ui_centered_bounds_block(const bContext *C, uiBlock *block) ui_bounds_block(block); - width = BLI_RCT_SIZE_X(&block->rect); - height = BLI_RCT_SIZE_Y(&block->rect); + width = BLI_rctf_size_x(&block->rect); + height = BLI_rctf_size_y(&block->rect); startx = (xmax * 0.5f) - (width * 0.5f); starty = (ymax * 0.5f) - (height * 0.5f); @@ -332,8 +328,8 @@ static void ui_popup_bounds_block(const bContext *C, uiBlock *block, eBlockBound wm_window_get_size(window, &xmax, &ymax); - oldwidth = BLI_RCT_SIZE_X(&block->rect); - oldheight = BLI_RCT_SIZE_Y(&block->rect); + oldwidth = BLI_rctf_size_x(&block->rect); + oldheight = BLI_rctf_size_y(&block->rect); /* first we ensure wide enough text bounds */ if (bounds_calc == UI_BLOCK_BOUNDS_POPUP_MENU) { @@ -348,8 +344,8 @@ static void ui_popup_bounds_block(const bContext *C, uiBlock *block, eBlockBound ui_bounds_block(block); /* and we adjust the position to fit within window */ - width = BLI_RCT_SIZE_X(&block->rect); - height = BLI_RCT_SIZE_Y(&block->rect); + width = BLI_rctf_size_x(&block->rect); + height = BLI_rctf_size_y(&block->rect); /* avoid divide by zero below, caused by calling with no UI, but better not crash */ oldwidth = oldwidth > 0 ? oldwidth : MAX2(1, width); @@ -495,10 +491,10 @@ static void ui_draw_linkline(uiLinkLine *line, int highlightActiveLines) if (line->from == NULL || line->to == NULL) return; - rect.xmin = BLI_RCT_CENTER_X(&line->from->rect); - rect.ymin = BLI_RCT_CENTER_Y(&line->from->rect); - rect.xmax = BLI_RCT_CENTER_X(&line->to->rect); - rect.ymax = BLI_RCT_CENTER_Y(&line->to->rect); + rect.xmin = BLI_rctf_cent_x(&line->from->rect); + rect.ymin = BLI_rctf_cent_y(&line->from->rect); + rect.xmax = BLI_rctf_cent_x(&line->to->rect); + rect.ymax = BLI_rctf_cent_y(&line->to->rect); if (line->flag & UI_SELECT) glColor3ub(100, 100, 100); @@ -531,7 +527,7 @@ static void ui_draw_links(uiBlock *block) foundselectline = TRUE; } } - } + } /* Draw any active lines (lines with either button being hovered over). * Do this last so they appear on top of inactive lines. */ @@ -543,7 +539,7 @@ static void ui_draw_links(uiBlock *block) ui_draw_linkline(line, !foundselectline); } } - } + } } } @@ -585,7 +581,7 @@ static void ui_but_update_linklines(uiBlock *block, uiBut *oldbut, uiBut *newbut if (line->from == newbut) line->from = oldbut; } - } + } /* check all other button links */ for (but = block->buttons.first; but; but = but->next) { @@ -614,28 +610,28 @@ static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut if (ui_but_equals_old(oldbut, but)) { if (oldbut->active) { #if 0 -// but->flag= oldbut->flag; +// but->flag = oldbut->flag; #else /* exception! redalert flag can't be update from old button. * perhaps it should only copy specific flags rather than all. */ -// but->flag= (oldbut->flag & ~UI_BUT_REDALERT) | (but->flag & UI_BUT_REDALERT); +// but->flag = (oldbut->flag & ~UI_BUT_REDALERT) | (but->flag & UI_BUT_REDALERT); #endif -// but->active= oldbut->active; -// but->pos= oldbut->pos; -// but->ofs= oldbut->ofs; -// but->editstr= oldbut->editstr; -// but->editval= oldbut->editval; -// but->editvec= oldbut->editvec; -// but->editcoba= oldbut->editcoba; -// but->editcumap= oldbut->editcumap; -// but->selsta= oldbut->selsta; -// but->selend= oldbut->selend; -// but->softmin= oldbut->softmin; -// but->softmax= oldbut->softmax; -// but->linkto[0]= oldbut->linkto[0]; -// but->linkto[1]= oldbut->linkto[1]; +// but->active = oldbut->active; +// but->pos = oldbut->pos; +// but->ofs = oldbut->ofs; +// but->editstr = oldbut->editstr; +// but->editval = oldbut->editval; +// but->editvec = oldbut->editvec; +// but->editcoba = oldbut->editcoba; +// but->editcumap = oldbut->editcumap; +// but->selsta = oldbut->selsta; +// but->selend = oldbut->selend; +// but->softmin = oldbut->softmin; +// but->softmax = oldbut->softmax; +// but->linkto[0] = oldbut->linkto[0]; +// but->linkto[1] = oldbut->linkto[1]; found = 1; -// oldbut->active= NULL; +// oldbut->active = NULL; /* move button over from oldblock to new block */ BLI_remlink(&oldblock->buttons, oldbut); @@ -1000,24 +996,20 @@ void ui_fontscale(short *points, float aspect) /* project button or block (but==NULL) to pixels in regionspace */ static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, uiBut *but) { - float gx, gy; - float getsizex, getsizey; + rctf rectf = (but)? but->rect: block->rect; - getsizex = ar->winx; - getsizey = ar->winy; + ui_block_to_window_fl(ar, block, &rectf.xmin, &rectf.ymin); + ui_block_to_window_fl(ar, block, &rectf.xmax, &rectf.ymax); - gx = (but ? but->rect.xmin : block->rect.xmin) + (block->panel ? block->panel->ofsx : 0.0f); - gy = (but ? but->rect.ymin : block->rect.ymin) + (block->panel ? block->panel->ofsy : 0.0f); - - rect->xmin = floorf(getsizex * (0.5f + 0.5f * (gx * block->winmat[0][0] + gy * block->winmat[1][0] + block->winmat[3][0]))); - rect->ymin = floorf(getsizey * (0.5f + 0.5f * (gx * block->winmat[0][1] + gy * block->winmat[1][1] + block->winmat[3][1]))); - - gx = (but ? but->rect.xmax : block->rect.xmax) + (block->panel ? block->panel->ofsx : 0.0f); - gy = (but ? but->rect.ymax : block->rect.ymax) + (block->panel ? block->panel->ofsy : 0.0f); - - rect->xmax = floorf(getsizex * (0.5f + 0.5f * (gx * block->winmat[0][0] + gy * block->winmat[1][0] + block->winmat[3][0]))); - rect->ymax = floorf(getsizey * (0.5f + 0.5f * (gx * block->winmat[0][1] + gy * block->winmat[1][1] + block->winmat[3][1]))); + rectf.xmin -= ar->winrct.xmin; + rectf.ymin -= ar->winrct.ymin; + rectf.xmax -= ar->winrct.xmin; + rectf.ymax -= ar->winrct.ymin; + rect->xmin = floorf(rectf.xmin); + rect->ymin = floorf(rectf.ymin); + rect->xmax = floorf(rectf.xmax); + rect->ymax = floorf(rectf.ymax); } /* uses local copy of style, to scale things down, and allow widgets to change stuff */ @@ -1160,9 +1152,15 @@ static void ui_is_but_sel(uiBut *but, double *value) } } - if (is_push == 2) ; - else if (is_push == 1) but->flag |= UI_SELECT; - else but->flag &= ~UI_SELECT; + if (is_push == 2) { + /* pass */ + } + else if (is_push == 1) { + but->flag |= UI_SELECT; + } + else { + but->flag &= ~UI_SELECT; + } } static uiBut *ui_find_inlink(uiBlock *block, void *poin) @@ -1272,7 +1270,7 @@ void ui_delete_linkline(uiLinkLine *line, uiBut *but) (*(link->ppoin))[b] = (*(link->ppoin))[a]; b++; } - } + } (*(link->totlink))--; } } @@ -1305,7 +1303,7 @@ void ui_get_but_vectorf(uiBut *but, float vec[3]) if (RNA_property_type(prop) == PROP_FLOAT) { tot = RNA_property_array_length(&but->rnapoin, prop); - tot = MIN2(tot, 3); + tot = min_ii(tot, 3); for (a = 0; a < tot; a++) vec[a] = RNA_property_float_get_index(&but->rnapoin, prop, a); @@ -1350,7 +1348,7 @@ void ui_set_but_vectorf(uiBut *but, const float vec[3]) int a; tot = RNA_property_array_length(&but->rnapoin, prop); - tot = MIN2(tot, 3); + tot = min_ii(tot, 3); for (a = 0; a < tot; a++) { RNA_property_float_set_index(&but->rnapoin, prop, a, vec[a]); @@ -1393,7 +1391,7 @@ int ui_is_but_unit(uiBut *but) return 0; #endif - /* for now disable time unit conversion */ + /* for now disable time unit conversion */ if (unit_type == PROP_UNIT_TIME) return 0; @@ -1466,16 +1464,16 @@ double ui_get_but_val(uiBut *but) case 'S': value = hsv[1]; break; case 'V': value = hsv[2]; break; } - } + } else if (but->pointype == UI_BUT_POIN_CHAR) { value = *(char *)but->poin; } else if (but->pointype == UI_BUT_POIN_SHORT) { value = *(short *)but->poin; - } + } else if (but->pointype == UI_BUT_POIN_INT) { value = *(int *)but->poin; - } + } else if (but->pointype == UI_BUT_POIN_FLOAT) { value = *(float *)but->poin; } @@ -1530,7 +1528,9 @@ void ui_set_but_val(uiBut *but, double value) * so leave this unset */ value = UI_BUT_VALUE_UNSET; } - else if (but->pointype == 0) ; + else if (but->pointype == 0) { + /* pass */ + } else if (but->type == HSVSLI) { float *fp, hsv[3]; @@ -1697,7 +1697,7 @@ void ui_get_but_string(uiBut *but, char *str, size_t maxlen) } else if (buf && buf != str) { /* string was too long, we have to truncate */ - memcpy(str, buf, MIN2(maxlen, buf_len + 1)); + memcpy(str, buf, MIN2(maxlen, (size_t)buf_len + 1)); MEM_freeN(buf); } } @@ -1723,8 +1723,9 @@ void ui_get_but_string(uiBut *but, char *str, size_t maxlen) BLI_strncpy(str, but->poin, maxlen); return; } - else if (ui_but_anim_expression_get(but, str, maxlen)) - ; /* driver expression */ + else if (ui_but_anim_expression_get(but, str, maxlen)) { + /* driver expression */ + } else { /* number editing */ double value; @@ -1946,8 +1947,8 @@ void ui_set_but_soft_range(uiBut *but, double value) RNA_property_int_ui_range(&but->rnapoin, but->rnaprop, &imin, &imax, &istep); softmin = (imin == INT_MIN) ? -1e4 : imin; softmax = (imin == INT_MAX) ? 1e4 : imax; - /*step= istep;*/ /*UNUSED*/ - /*precision= 1;*/ /*UNUSED*/ + /*step = istep;*/ /*UNUSED*/ + /*precision = 1;*/ /*UNUSED*/ if (array_len >= 2) { int value_range[2]; @@ -1963,8 +1964,8 @@ void ui_set_but_soft_range(uiBut *but, double value) RNA_property_float_ui_range(&but->rnapoin, but->rnaprop, &fmin, &fmax, &fstep, &fprecision); softmin = (fmin == -FLT_MAX) ? (float)-1e4 : fmin; softmax = (fmax == FLT_MAX) ? (float)1e4 : fmax; - /*step= fstep;*/ /*UNUSED*/ - /*precision= fprecision;*/ /*UNUSED*/ + /*step = fstep;*/ /*UNUSED*/ + /*precision = fprecision;*/ /*UNUSED*/ if (array_len >= 2) { float value_range[2]; @@ -2005,7 +2006,7 @@ void ui_set_but_soft_range(uiBut *but, double value) static void ui_free_link(uiLink *link) { - if (link) { + if (link) { BLI_freelistN(&link->lines); MEM_freeN(link); } @@ -2054,7 +2055,7 @@ void uiFreeBlock(const bContext *C, uiBlock *block) uiBut *but; while ( (but = block->buttons.first) ) { - BLI_remlink(&block->buttons, but); + BLI_remlink(&block->buttons, but); ui_free_but(C, but); } @@ -2164,8 +2165,6 @@ uiBlock *uiBeginBlock(const bContext *C, ARegion *region, const char *name, shor wm_subwindow_getmatrix(window, region->swinid, block->winmat); wm_subwindow_getsize(window, region->swinid, &getsizex, &getsizey); - /* TODO - investigate why block->winmat[0][0] is negative - * in the image view when viewRedrawForce is called */ block->aspect = 2.0f / fabsf(getsizex * block->winmat[0][0]); } else { @@ -2257,7 +2256,7 @@ void ui_check_but(uiBut *but) /* safety is 4 to enable small number buttons (like 'users') */ - // okwidth= -4 + (BLI_RCT_SIZE_X(&but->rect)); // UNUSED + // okwidth = -4 + (BLI_rcti_size_x(&but->rect)); // UNUSED /* name: */ switch (but->type) { @@ -2265,7 +2264,7 @@ void ui_check_but(uiBut *but) case MENU: case ICONTEXTROW: - if (BLI_RCT_SIZE_X(&but->rect) > 24.0f) { + if (BLI_rctf_size_x(&but->rect) > 24.0f) { UI_GET_BUT_VALUE_INIT(but, value); ui_set_name_menu(but, (int)value); } @@ -2399,7 +2398,7 @@ void uiBlockBeginAlign(uiBlock *block) /* if other align was active, end it */ if (block->flag & UI_BUT_ALIGN) uiBlockEndAlign(block); - block->flag |= UI_BUT_ALIGN_DOWN; + block->flag |= UI_BUT_ALIGN_DOWN; block->alignnr++; /* buttons declared after this call will get this align nr */ // XXX flag? @@ -2440,7 +2439,7 @@ static void ui_block_do_align_but(uiBut *first, short nr) } } - /* rows==0: 1 row, cols==0: 1 column */ + /* rows == 0: 1 row, cols == 0: 1 column */ /* note; how it uses 'flag' in loop below (either set it, or OR it) is confusing */ for (but = first, prev = NULL; but && but->alignnr == nr; prev = but, but = but->next) { @@ -2484,7 +2483,9 @@ static void ui_block_do_align_but(uiBut *first, short nr) if (rows > 0) { uiBut *bt = but; while (bt && bt->alignnr == nr) { - if (bt->next && bt->next->alignnr == nr && buts_are_horiz(bt, bt->next) == 0) break; + if (bt->next && bt->next->alignnr == nr && buts_are_horiz(bt, bt->next) == 0) { + break; + } bt = bt->next; } if (bt == NULL || bt->alignnr != nr) flag = UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_RIGHT; @@ -2572,7 +2573,9 @@ void ui_block_do_align(uiBlock *block) ui_block_do_align_but(but, nr); /* skip with same number */ - for (; but && but->alignnr == nr; but = but->next) ; + for (; but && but->alignnr == nr; but = but->next) { + /* pass */ + } if (!but) { break; @@ -2621,6 +2624,9 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str, uiBut *but; int slen; + BLI_assert(width >= 0); + BLI_assert(height >= 0); + /* we could do some more error checks here */ if ((type & BUTTYPE) == LABEL) { BLI_assert((poin != NULL || min != 0.0f || max != 0.0f || (a1 == 0.0f && a2 != 0.0f) || (a1 != 0.0f && a1 != 1.0f)) == FALSE); @@ -2713,9 +2719,8 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str, } /* keep track of UI_interface.h */ - if (ELEM7(but->type, BLOCK, BUT, LABEL, PULLDOWN, ROUNDBOX, LISTBOX, BUTM)) ; - else if (ELEM(but->type, SCROLL, SEPR /* , FTPREVIEW */ )) ; - else if (but->type >= SEARCH_MENU) ; + if (ELEM9(but->type, BLOCK, BUT, LABEL, PULLDOWN, ROUNDBOX, LISTBOX, BUTM, SCROLL, SEPR /* , FTPREVIEW */)) {} + else if (but->type >= SEARCH_MENU) {} else but->flag |= UI_BUT_UNDO; BLI_addtail(&block->buttons, but); @@ -2749,7 +2754,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str, static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *str, - int x, int y, short width, short height, + int x, int y, short width, short height, PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip) { @@ -3422,11 +3427,6 @@ void uiBlockClearFlag(uiBlock *block, int flag) block->flag &= ~flag; } -void uiBlockSetXOfs(uiBlock *block, int xofs) -{ - block->xofs = xofs; -} - void uiButSetFlag(uiBut *but, int flag) { but->flag |= flag; @@ -3788,15 +3788,16 @@ void uiButGetStrInfo(bContext *C, uiBut *but, int nbr, ...) if (type == BUT_GET_LABEL) { if (but->str) { /* Menu labels can have some complex formating stuff marked by pipes or %t, we don't want those here! */ - const char *tc; - - if (but->type == MENU) - tc = strstr(but->str, "%t"); - else - tc = strchr(but->str, '|'); - - if (tc) - tmp = BLI_strdupn(but->str, tc - but->str); + const char *tc1, *tc2; + + tc1 = strstr(but->str, "%t"); + tc2 = strstr(but->str, "|"); /* XXX For some reason strchr seems to not work here? */ + + if (tc2 && (!tc1 || tc1 > tc2)) + tc1 = tc2; + + if (tc1) + tmp = BLI_strdupn(but->str, tc1 - but->str); else tmp = BLI_strdup(but->str); } @@ -3872,12 +3873,41 @@ void uiButGetStrInfo(bContext *C, uiBut *but, int nbr, ...) } } else if (ELEM3(type, BUT_GET_RNAENUM_IDENTIFIER, BUT_GET_RNAENUM_LABEL, BUT_GET_RNAENUM_TIP)) { + PointerRNA *ptr = NULL; + PropertyRNA *prop = NULL; + int value = 0; + + /* get the enum property... */ if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) { + /* enum property */ + ptr = &but->rnapoin; + prop = but->rnaprop; + value = (but->type == ROW) ? (int)but->hardmax : (int)ui_get_but_val(but); + } + else if (but->optype) { + PointerRNA *opptr = uiButGetOperatorPtrRNA(but); + wmOperatorType *ot = but->optype; + + /* if the default property of the operator is enum and it is set, + * fetch the tooltip of the selected value so that "Snap" and "Mirror" + * operator menus in the Anim Editors will show tooltips for the different + * operations instead of the meaningless generic operator tooltip + */ + if (ot->prop && RNA_property_type(ot->prop) == PROP_ENUM) { + if (RNA_struct_contains_property(opptr, ot->prop)) { + ptr = opptr; + prop = ot->prop; + value = RNA_property_enum_get(opptr, ot->prop); + } + } + } + + /* get strings from matching enum item */ + if (ptr && prop) { if (!item) { int i; - int value = (but->type == ROW) ? (int)but->hardmax : (int)ui_get_but_val(but); - RNA_property_enum_items_gettexted(C, &but->rnapoin, but->rnaprop, &items, &totitems, &free_items); - + + RNA_property_enum_items_gettexted(C, ptr, prop, &items, &totitems, &free_items); for (i = 0, item = items; i < totitems; i++, item++) { if (item->identifier[0] && item->value == value) break; diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index f535c3c3e2a..469bd11215e 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -60,8 +60,6 @@ /* own include */ #include "interface_intern.h" -#define UI_DISABLED_ALPHA_OFFS -160 - static int roundboxtype = UI_CNR_ALL; void uiSetRoundBox(int type) @@ -86,7 +84,7 @@ void uiDrawBox(int mode, float minx, float miny, float maxx, float maxy, float r /* mult */ for (a = 0; a < 7; a++) { - vec[a][0] *= rad; vec[a][1] *= rad; + mul_v2_fl(vec[a], rad); } glBegin(mode); @@ -157,18 +155,18 @@ void uiDrawBoxShade(int mode, float minx, float miny, float maxx, float maxy, fl /* mult */ for (a = 0; a < 7; a++) { - vec[a][0] *= rad; vec[a][1] *= rad; + mul_v2_fl(vec[a], rad); } /* get current color, needs to be outside of glBegin/End */ glGetFloatv(GL_CURRENT_COLOR, color); - /* 'shade' defines strength of shading */ - coltop[0] = color[0] + shadetop; if (coltop[0] > 1.0f) coltop[0] = 1.0f; - coltop[1] = color[1] + shadetop; if (coltop[1] > 1.0f) coltop[1] = 1.0f; - coltop[2] = color[2] + shadetop; if (coltop[2] > 1.0f) coltop[2] = 1.0f; - coldown[0] = color[0] + shadedown; if (coldown[0] < 0.0f) coldown[0] = 0.0f; - coldown[1] = color[1] + shadedown; if (coldown[1] < 0.0f) coldown[1] = 0.0f; - coldown[2] = color[2] + shadedown; if (coldown[2] < 0.0f) coldown[2] = 0.0f; + /* 'shade' defines strength of shading */ + coltop[0] = min_ff(1.0f, color[0] + shadetop); + coltop[1] = min_ff(1.0f, color[1] + shadetop); + coltop[2] = min_ff(1.0f, color[2] + shadetop); + coldown[0] = max_ff(0.0f, color[0] + shadedown); + coldown[1] = max_ff(0.0f, color[1] + shadedown); + coldown[2] = max_ff(0.0f, color[2] + shadedown); glShadeModel(GL_SMOOTH); glBegin(mode); @@ -266,18 +264,18 @@ void uiDrawBoxVerticalShade(int mode, float minx, float miny, float maxx, float /* mult */ for (a = 0; a < 7; a++) { - vec[a][0] *= rad; vec[a][1] *= rad; + mul_v2_fl(vec[a], rad); } /* get current color, needs to be outside of glBegin/End */ glGetFloatv(GL_CURRENT_COLOR, color); - /* 'shade' defines strength of shading */ - colLeft[0] = color[0] + shadeLeft; if (colLeft[0] > 1.0f) colLeft[0] = 1.0f; - colLeft[1] = color[1] + shadeLeft; if (colLeft[1] > 1.0f) colLeft[1] = 1.0f; - colLeft[2] = color[2] + shadeLeft; if (colLeft[2] > 1.0f) colLeft[2] = 1.0f; - colRight[0] = color[0] + shadeRight; if (colRight[0] < 0.0f) colRight[0] = 0.0f; - colRight[1] = color[1] + shadeRight; if (colRight[1] < 0.0f) colRight[1] = 0.0f; - colRight[2] = color[2] + shadeRight; if (colRight[2] < 0.0f) colRight[2] = 0.0f; + /* 'shade' defines strength of shading */ + colLeft[0] = min_ff(1.0f, color[0] + shadeLeft); + colLeft[1] = min_ff(1.0f, color[1] + shadeLeft); + colLeft[2] = min_ff(1.0f, color[2] + shadeLeft); + colRight[0] = max_ff(0.0f, color[0] + shadeRight); + colRight[1] = max_ff(0.0f, color[1] + shadeRight); + colRight[2] = max_ff(0.0f, color[2] + shadeRight); glShadeModel(GL_SMOOTH); glBegin(mode); @@ -440,8 +438,8 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w //glColor4f(1.0, 0.f, 0.f, 1.f); //fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax) - w = BLI_RCT_SIZE_X(rect); - h = BLI_RCT_SIZE_Y(rect); + w = BLI_rcti_size_x(rect); + h = BLI_rcti_size_y(rect); /* prevent drawing outside widget area */ glGetIntegerv(GL_SCISSOR_BOX, scissor); glScissor(ar->winrct.xmin + rect->xmin, ar->winrct.ymin + rect->ymin, w, h); @@ -494,8 +492,8 @@ static void ui_draw_but_CHARTAB(uiBut *but) charmax = G.charmax = 0xffff; /* Calculate the size of the button */ - width = abs(BLI_RCT_SIZE_X(rect)); - height = abs(BLI_RCT_SIZE_Y(rect)); + width = abs(BLI_rcti_size_x(rect)); + height = abs(BLI_rcti_size_y(rect)); butw = floor(width / 12); buth = floor(height / 6); @@ -512,7 +510,7 @@ static void ui_draw_but_CHARTAB(uiBut *but) if (G.selfont && BKE_vfont_is_builtin(G.selfont) == FALSE) { /* Is the font file packed, if so then use the packed file */ if (G.selfont->packedfile) { - pf = G.selfont->packedfile; + pf = G.selfont->packedfile; FTF_SetFont(pf->data, pf->size, 14.0); } else { @@ -601,7 +599,8 @@ static void ui_draw_but_CHARTAB(uiBut *but) } /* Calculate the next position and character */ - sx += butw; ex += butw; + sx += butw; + ex += butw; cs++; } /* Add the y position and reset x position */ @@ -609,7 +608,7 @@ static void ui_draw_but_CHARTAB(uiBut *but) ey -= buth; sx = rect->xmin; ex = rect->xmin + butw; - } + } glShadeModel(GL_FLAT); /* Return Font Settings to original */ @@ -633,7 +632,7 @@ static void ui_draw_but_CHARTAB(uiBut *but) #endif /* WITH_INTERNATIONAL */ #endif -static void draw_scope_end(rctf *rect, GLint *scissor) +static void draw_scope_end(const rctf *rect, GLint *scissor) { float scaler_x1, scaler_x2; @@ -643,8 +642,8 @@ static void draw_scope_end(rctf *rect, GLint *scissor) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* scale widget */ - scaler_x1 = rect->xmin + BLI_RCT_SIZE_X(rect) / 2 - SCOPE_RESIZE_PAD; - scaler_x2 = rect->xmin + BLI_RCT_SIZE_X(rect) / 2 + SCOPE_RESIZE_PAD; + scaler_x1 = rect->xmin + BLI_rctf_size_x(rect) / 2 - SCOPE_RESIZE_PAD; + scaler_x2 = rect->xmin + BLI_rctf_size_x(rect) / 2 + SCOPE_RESIZE_PAD; glColor4f(0.f, 0.f, 0.f, 0.25f); fdrawline(scaler_x1, rect->ymin - 4, scaler_x2, rect->ymin - 4); @@ -733,8 +732,8 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol) rect.ymin = (float)recti->ymin + SCOPE_RESIZE_PAD + 2; rect.ymax = (float)recti->ymax - 1; - w = BLI_RCT_SIZE_X(&rect); - h = BLI_RCT_SIZE_Y(&rect) * hist->ymax; + w = BLI_rctf_size_x(&rect); + h = BLI_rctf_size_y(&rect) * hist->ymax; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -806,9 +805,9 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), if (scopes->wavefrm_yfac < 0.5f) scopes->wavefrm_yfac = 0.98f; - w = BLI_RCT_SIZE_X(&rect) - 7; - h = BLI_RCT_SIZE_Y(&rect) * scopes->wavefrm_yfac; - yofs = rect.ymin + (BLI_RCT_SIZE_Y(&rect) - h) / 2.0f; + w = BLI_rctf_size_x(&rect) - 7; + h = BLI_rctf_size_y(&rect) * scopes->wavefrm_yfac; + yofs = rect.ymin + (BLI_rctf_size_y(&rect) - h) / 2.0f; w3 = w / 3.0f; /* log scale for alpha */ @@ -955,12 +954,12 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), static float polar_to_x(float center, float diam, float ampli, float angle) { - return center + diam *ampli *cosf(angle); + return center + diam *ampli * cosf(angle); } static float polar_to_y(float center, float diam, float ampli, float angle) { - return center + diam *ampli *sinf(angle); + return center + diam *ampli * sinf(angle); } static void vectorscope_draw_target(float centerx, float centery, float diam, const float colf[3]) @@ -1034,8 +1033,8 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco rect.ymin = (float)recti->ymin + SCOPE_RESIZE_PAD + 2; rect.ymax = (float)recti->ymax - 1; - w = BLI_RCT_SIZE_X(&rect); - h = BLI_RCT_SIZE_Y(&rect); + w = BLI_rctf_size_x(&rect); + h = BLI_rctf_size_y(&rect); centerx = rect.xmin + w / 2; centery = rect.ymin + h / 2; diam = (w < h) ? w : h; @@ -1146,8 +1145,9 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect) glBegin(GL_QUAD_STRIP); glColor4fv(&cbd->r); - glVertex2fv(v1); glVertex2fv(v2); - + glVertex2fv(v1); + glVertex2fv(v2); + for (a = 1; a <= sizex; a++) { pos = ((float)a) / (sizex - 1); do_colorband(coba, pos, colf); @@ -1157,7 +1157,8 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect) v1[0] = v2[0] = x1 + a; glColor4fv(colf); - glVertex2fv(v1); glVertex2fv(v2); + glVertex2fv(v1); + glVertex2fv(v2); } glEnd(); @@ -1220,7 +1221,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect) glColor3ub(255, 255, 255); glVertex2fv(v2); glVertex2fv(v3); - } + } } glEnd(); @@ -1244,7 +1245,8 @@ void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, rcti *rect) /* sphere color */ glMaterialfv(GL_FRONT, GL_DIFFUSE, diffn); - glCullFace(GL_BACK); glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glEnable(GL_CULL_FACE); /* disable blender light */ for (a = 0; a < 8; a++) { @@ -1267,12 +1269,12 @@ void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, rcti *rect) /* transform to button */ glPushMatrix(); - glTranslatef(rect->xmin + 0.5f * BLI_RCT_SIZE_X(rect), rect->ymin + 0.5f * BLI_RCT_SIZE_Y(rect), 0.0f); + glTranslatef(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect), 0.0f); - if (BLI_RCT_SIZE_X(rect) < BLI_RCT_SIZE_Y(rect)) - size = BLI_RCT_SIZE_X(rect) / 200.f; + if (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect)) + size = BLI_rcti_size_x(rect) / 200.f; else - size = BLI_RCT_SIZE_Y(rect) / 200.f; + size = BLI_rcti_size_y(rect) / 200.f; glScalef(size, size, size); @@ -1378,12 +1380,12 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, uiWidgetColors *wcol, rcti *rect BLI_rcti_isect(&scissor_new, &ar->winrct, &scissor_new); glScissor(scissor_new.xmin, scissor_new.ymin, - BLI_RCT_SIZE_X(&scissor_new), - BLI_RCT_SIZE_Y(&scissor_new)); + BLI_rcti_size_x(&scissor_new), + BLI_rcti_size_y(&scissor_new)); /* calculate offset and zoom */ - zoomx = (BLI_RCT_SIZE_X(rect) - 2.0f * but->aspect) / BLI_RCT_SIZE_X(&cumap->curr); - zoomy = (BLI_RCT_SIZE_Y(rect) - 2.0f * but->aspect) / BLI_RCT_SIZE_Y(&cumap->curr); + zoomx = (BLI_rcti_size_x(rect) - 2.0f * but->aspect) / BLI_rctf_size_x(&cumap->curr); + zoomy = (BLI_rcti_size_y(rect) - 2.0f * but->aspect) / BLI_rctf_size_y(&cumap->curr); offsx = cumap->curr.xmin - but->aspect / zoomx; offsy = cumap->curr.ymin - but->aspect / zoomy; @@ -1561,8 +1563,8 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc rect.ymin = (float)recti->ymin + SCOPE_RESIZE_PAD + 2; rect.ymax = (float)recti->ymax - 1; - width = BLI_RCT_SIZE_X(&rect) + 1; - height = BLI_RCT_SIZE_Y(&rect); + width = BLI_rctf_size_x(&rect) + 1; + height = BLI_rctf_size_y(&rect); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -1637,8 +1639,8 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc glTranslatef(rect.xmin + track_pos[0], rect.ymin + track_pos[1], 0.f); glScissor(ar->winrct.xmin + rect.xmin, ar->winrct.ymin + rect.ymin, - BLI_RCT_SIZE_X(&rect), - BLI_RCT_SIZE_Y(&rect)); + BLI_rctf_size_x(&rect), + BLI_rctf_size_y(&rect)); for (a = 0; a < 2; a++) { if (a == 1) { @@ -1705,7 +1707,7 @@ static void ui_shadowbox(float minx, float miny, float maxx, float maxy, float s glVertex2f(maxx, miny - shadsize); glEnd(); - /* bottom quad */ + /* bottom quad */ glBegin(GL_POLYGON); glColor4ub(0, 0, 0, alpha); glVertex2f(minx + 0.3f * shadsize, miny); @@ -1729,7 +1731,7 @@ void uiDrawBoxShadow(unsigned char alpha, float minx, float miny, float maxx, fl } -void ui_dropshadow(rctf *rct, float radius, float aspect, float alpha, int UNUSED(select)) +void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int UNUSED(select)) { int i; float rad; @@ -1738,8 +1740,8 @@ void ui_dropshadow(rctf *rct, float radius, float aspect, float alpha, int UNUSE glEnable(GL_BLEND); - if (radius > (BLI_RCT_SIZE_Y(rct) - 10.0f) / 2.0f) - rad = (BLI_RCT_SIZE_Y(rct) - 10.0f) / 2.0f; + if (radius > (BLI_rctf_size_y(rct) - 10.0f) / 2.0f) + rad = (BLI_rctf_size_y(rct) - 10.0f) / 2.0f; else rad = radius; diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index f7b22098835..6d262daab12 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -78,6 +78,9 @@ #include "WM_api.h" #include "WM_types.h" +/* place the mouse at the scaled down location when un-grabbing */ +#define USE_CONT_MOUSE_CORRECT + /* proto */ static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to); static void ui_add_link(bContext *C, uiBut *from, uiBut *to); @@ -152,6 +155,12 @@ typedef struct uiHandleButtonData { float dragf, dragfstart; CBData *dragcbd; +#ifdef USE_CONT_MOUSE_CORRECT + /* when ungrabbing buttons which are #ui_is_a_warp_but(), we may want to position them + * FLT_MAX signifies do-nothing, use #ui_block_to_window_fl() to get this into a usable space */ + float ungrab_mval[2]; +#endif + /* menu open (watch uiFreeActiveButtons) */ uiPopupBlockHandle *menu; int menuretval; @@ -695,12 +704,14 @@ static int ui_but_mouse_inside_icon(uiBut *but, ARegion *ar, wmEvent *event) BLI_rcti_rctf_copy(&rect, &but->rect); - if (but->imb) ; /* use button size itself */ + if (but->imb) { + /* use button size itself */ + } else if (but->flag & UI_ICON_LEFT) { - rect.xmax = rect.xmin + (BLI_RCT_SIZE_Y(&rect)); + rect.xmax = rect.xmin + (BLI_rcti_size_y(&rect)); } else { - int delta = BLI_RCT_SIZE_X(&rect) - BLI_RCT_SIZE_Y(&rect); + int delta = BLI_rcti_size_x(&rect) - BLI_rcti_size_y(&rect); rect.xmin += delta / 2; rect.xmax -= delta / 2; } @@ -721,7 +732,7 @@ static int ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data, drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but)); if (but->imb) - WM_event_drag_image(drag, but->imb, but->imb_scale, BLI_RCT_SIZE_X(&but->rect), BLI_RCT_SIZE_Y(&but->rect)); + WM_event_drag_image(drag, but->imb, but->imb_scale, BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect)); return 1; } @@ -763,7 +774,7 @@ static void ui_delete_active_linkline(uiBlock *block) (*(link->ppoin))[b] = (*(link->ppoin))[a]; b++; } - } + } (*(link->totlink))--; } } @@ -808,6 +819,8 @@ static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to) uiLink *link = from->link; + PointerRNA props_ptr, object_ptr; + if (link->ppoin) sens_from_links = (bController ***)(link->ppoin); else return; @@ -836,9 +849,15 @@ static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to) /* only works if the sensor and the actuator are from the same object */ if (!act_iter) return; + + /* in case the linked controller is not the active one */ + RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr); + + WM_operator_properties_create(&props_ptr, "LOGIC_OT_controller_add"); + RNA_string_set(&props_ptr, "object", ob->id.name + 2); /* (3) add a new controller */ - if (WM_operator_name_call(C, "LOGIC_OT_controller_add", WM_OP_EXEC_DEFAULT, NULL) & OPERATOR_FINISHED) { + if (WM_operator_name_call(C, "LOGIC_OT_controller_add", WM_OP_EXEC_DEFAULT, &props_ptr) & OPERATOR_FINISHED) { cont = (bController *)ob->controllers.last; cont->type = CONT_LOGIC_AND; /* Quick fix to make sure we always have an AND controller. It might be nicer to make sure the operator gives us the right one though... */ @@ -858,6 +877,7 @@ static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to) MEM_freeN(tmp_but->link); MEM_freeN(tmp_but); } + WM_operator_properties_free(&props_ptr); } static void ui_add_link(bContext *C, uiBut *from, uiBut *to) @@ -1043,7 +1063,7 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut break; case HSVSLI: break; - case TOG3: + case TOG3: ui_apply_but_TOG3(C, but, data); break; case MENU: @@ -1089,10 +1109,10 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut case INLINK: ui_apply_but_LINK(C, but, data); break; - case BUT_IMAGE: + case BUT_IMAGE: ui_apply_but_IMAGE(C, but, data); break; - case HISTOGRAM: + case HISTOGRAM: ui_apply_but_HISTOGRAM(C, but, data); break; case WAVEFORM: @@ -1166,7 +1186,9 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, /* numeric value */ if (ELEM4(but->type, NUM, NUMABS, NUMSLI, HSVSLI)) { - if (but->poin == NULL && but->rnapoin.data == NULL) ; + if (but->poin == NULL && but->rnapoin.data == NULL) { + /* pass */ + } else if (mode == 'c') { ui_get_but_string(but, buf, sizeof(buf)); WM_clipboard_text_set(buf, 0); @@ -1187,7 +1209,9 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, else if (but->type == COLOR) { float rgb[3]; - if (but->poin == NULL && but->rnapoin.data == NULL) ; + if (but->poin == NULL && but->rnapoin.data == NULL) { + /* pass */ + } else if (mode == 'c') { ui_get_but_vectorf(but, rgb); @@ -1216,7 +1240,9 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, else if (ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) { uiHandleButtonData *active_data = but->active; - if (but->poin == NULL && but->rnapoin.data == NULL) ; + if (but->poin == NULL && but->rnapoin.data == NULL) { + /* pass */ + } else if (mode == 'c') { button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); BLI_strncpy(buf, active_data->str, UI_MAX_DRAW_STR); @@ -1273,6 +1299,71 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, } } +/* ************************ password text ****************************** + * + * Functions to convert password strings that should not be displayed + * to asterisk representation (e.g. mysecretpasswd -> *************) + * + * It converts every UTF-8 character to an asterisk, and also remaps + * the cursor position and selection start/end. + * + * Note: remaping is used, because password could contain UTF-8 characters. + * + */ + +static int ui_text_position_from_hidden(uiBut *but, int pos) +{ + const char *strpos; + int i; + + for (i = 0, strpos = but->drawstr; i < pos; i++) + strpos = BLI_str_find_next_char_utf8(strpos, NULL); + + return (strpos - but->drawstr); +} + +static int ui_text_position_to_hidden(uiBut *but, int pos) +{ + return BLI_strnlen_utf8(but->drawstr, pos); +} + +void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, int restore) +{ + if (!(but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_PASSWORD)) + return; + + if (restore) { + /* restore original string */ + BLI_strncpy(but->drawstr, password_str, UI_MAX_DRAW_STR); + + /* remap cursor positions */ + if (but->pos >= 0) { + but->pos = ui_text_position_from_hidden(but, but->pos); + but->selsta = ui_text_position_from_hidden(but, but->selsta); + but->selend = ui_text_position_from_hidden(but, but->selend); + } + } + else { + /* convert text to hidden test using asterisks (e.g. pass -> ****) */ + int i, len = BLI_strlen_utf8(but->drawstr); + + /* remap cursor positions */ + if (but->pos >= 0) { + but->pos = ui_text_position_to_hidden(but, but->pos); + but->selsta = ui_text_position_to_hidden(but, but->selsta); + but->selend = ui_text_position_to_hidden(but, but->selend); + } + + /* save original string */ + BLI_strncpy(password_str, but->drawstr, UI_MAX_DRAW_STR); + + for (i = 0; i < len; i++) + but->drawstr[i] = '*'; + but->drawstr[i] = '\0'; + } +} + + /* ************* in-button text selection/editing ************* */ @@ -1296,20 +1387,22 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho uiStyle *style = UI_GetStyle(); // XXX pass on as arg uiFontStyle *fstyle = &style->widget; int startx = but->rect.xmin; - char *origstr; + char *origstr, password_str[UI_MAX_DRAW_STR]; uiStyleFontSet(fstyle); if (fstyle->kerning == 1) /* for BLF_width */ BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT); + ui_button_text_password_hide(password_str, but, FALSE); + origstr = MEM_callocN(sizeof(char) * data->maxlen, "ui_textedit origstr"); BLI_strncpy(origstr, but->drawstr, data->maxlen); /* XXX solve generic */ if (but->type == NUM || but->type == NUMSLI) - startx += (int)(0.5f * (BLI_RCT_SIZE_Y(&but->rect))); + startx += (int)(0.5f * (BLI_rctf_size_y(&but->rect))); else if (ELEM(but->type, TEX, SEARCH_MENU)) { startx += 5; if (but->flag & UI_HAS_ICON) @@ -1317,7 +1410,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho } /* mouse dragged outside the widget to the left */ - if (x < startx && but->ofs > 0) { + if (x < startx && but->ofs > 0) { int i = but->ofs; origstr[but->ofs] = 0; @@ -1350,7 +1443,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho while (TRUE) { /* XXX does not take zoom level into account */ - cdist = startx + aspect_sqrt *BLF_width(fstyle->uifont_id, origstr + but->ofs); + cdist = startx + aspect_sqrt * BLF_width(fstyle->uifont_id, origstr + but->ofs); /* check if position is found */ if (cdist < x) { @@ -1381,18 +1474,20 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho if (fstyle->kerning == 1) BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT); + ui_button_text_password_hide(password_str, but, TRUE); + MEM_freeN(origstr); } static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data, short x) { - if (x > data->selstartx) data->selextend = EXTEND_RIGHT; + if (x > data->selstartx) data->selextend = EXTEND_RIGHT; else if (x < data->selstartx) data->selextend = EXTEND_LEFT; ui_textedit_set_cursor_pos(but, data, x); - if (data->selextend == EXTEND_RIGHT) but->selend = but->pos; - if (data->selextend == EXTEND_LEFT) but->selsta = but->pos; + if (data->selextend == EXTEND_RIGHT) but->selend = but->pos; + else if (data->selextend == EXTEND_LEFT) but->selsta = but->pos; ui_check_but(but); } @@ -1561,7 +1656,7 @@ static int ui_textedit_delete(uiBut *but, uiHandleButtonData *data, int directio but->pos -= step; changed = 1; } - } + } } return changed; @@ -1596,6 +1691,7 @@ static int ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, int paste /* paste */ if (paste) { + /* TODO, ensure UTF8 ui_is_but_utf8() - campbell */ /* extract the first line from the clipboard */ p = pbuf = WM_clipboard_text_get(0); @@ -1649,7 +1745,7 @@ static int ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, int paste if (cut) if ((but->selend - but->selsta) > 0) changed = ui_textedit_delete_selection(but, data); - } + } return changed; } @@ -1688,7 +1784,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data) /* optional searchbox */ if (but->type == SEARCH_MENU) { data->searchbox = ui_searchbox_create(C, data->region, but); - ui_searchbox_update(C, data->searchbox, but, 1); /* 1= reset */ + ui_searchbox_update(C, data->searchbox, but, 1); /* 1 = reset */ } ui_check_but(but); @@ -1955,8 +2051,12 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle if (changed) { /* only update when typing for TAB key */ - if (update && data->interactive) ui_apply_button(C, block, but, data, 1); - else ui_check_but(but); + if (update && data->interactive) { + ui_apply_button(C, block, but, data, 1); + } + else { + ui_check_but(but); + } but->changed = TRUE; if (data->searchbox) @@ -2047,8 +2147,12 @@ static void ui_numedit_end(uiBut *but, uiHandleButtonData *data) static void ui_numedit_apply(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data) { - if (data->interactive) ui_apply_button(C, block, but, data, 1); - else ui_check_but(but); + if (data->interactive) { + ui_apply_button(C, block, but, data, 1); + } + else { + ui_check_but(but); + } ED_region_tag_redraw(data->region); } @@ -2122,7 +2226,7 @@ static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data } /* this makes adjacent blocks auto open from now on */ - //if (but->block->auto_open ==0 ) but->block->auto_open = 1; + //if (but->block->auto_open == 0) but->block->auto_open = 1; } static void ui_blockopen_end(bContext *C, uiBut *but, uiHandleButtonData *data) @@ -2140,6 +2244,16 @@ static void ui_blockopen_end(bContext *C, uiBut *but, uiHandleButtonData *data) } } +int ui_button_open_menu_direction(uiBut *but) +{ + uiHandleButtonData *data = but->active; + + if (data && data->menu) + return data->menu->direction; + + return 0; +} + /* ***************** events for different button types *************** */ static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEvent *event) @@ -2209,7 +2323,7 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data ED_region_tag_redraw(data->region); if (event->val == KM_PRESS) { - if (ISHOTKEY(event->type)) { + if (ISHOTKEY(event->type)) { if (WM_key_event_string(event->type)[0]) ui_set_but_val(but, event->type); @@ -2260,7 +2374,9 @@ static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButton { if (data->state == BUTTON_STATE_HIGHLIGHT) { if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN) && event->val == KM_PRESS) { - if (but->dt == UI_EMBOSSN && !event->ctrl) ; + if (but->dt == UI_EMBOSSN && !event->ctrl) { + /* pass */ + } else { button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); return WM_UI_HANDLER_BREAK; @@ -2373,14 +2489,14 @@ static float ui_numedit_apply_snapf(uiBut *but, float tempf, float softmin, floa } if (snap == 1) { - if (softrange < 2.10f) tempf = 0.1f * floorf(10.0f * tempf); + if (softrange < 2.10f) tempf = 0.1f * floorf(10.0f * tempf); else if (softrange < 21.0f) tempf = floorf(tempf); - else tempf = 10.0f * floorf(tempf / 10.0f); + else tempf = 10.0f * floorf(tempf / 10.0f); } else if (snap == 2) { - if (softrange < 2.10f) tempf = 0.01f * floorf(100.0f * tempf); - else if (softrange < 21.0f) tempf = 0.1f * floorf(10.0f * tempf); - else tempf = floor(tempf); + if (softrange < 2.10f) tempf = 0.01f * floorf(100.0f * tempf); + else if (softrange < 21.0f) tempf = 0.1f * floorf(10.0f * tempf); + else tempf = floor(tempf); } if (fac != 1.0f) @@ -2459,9 +2575,9 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i } } else { - if (softrange > 256) fac = 1.0; /* 1px == 1 */ - else if (softrange > 32) fac = 1.0 / 2.0; /* 2px == 1 */ - else fac = 1.0 / 16.0; /* 16px == 1? */ + if (softrange > 256) fac = 1.0; /* 1px == 1 */ + else if (softrange > 32) fac = 1.0 / 2.0; /* 2px == 1 */ + else fac = 1.0 / 16.0; /* 16px == 1? */ temp = data->startvalue + (((double)mx - data->dragstartx) * (double)fac); temp = ui_numedit_apply_snap(temp, softmin, softmax, snap); @@ -2493,10 +2609,9 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i deler = 500; if (!ui_is_but_float(but)) { /* prevent large ranges from getting too out of control */ - if (softrange > 600) deler = powf(softrange, 0.75); - - if (softrange < 100) deler = 200.0; - if (softrange < 25) deler = 50.0; + if (softrange > 600) deler = powf(softrange, 0.75); + else if (softrange < 100) deler = 200.0; + else if (softrange < 25) deler = 50.0; } deler /= fac; @@ -2582,8 +2697,9 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); retval = WM_UI_HANDLER_BREAK; } - else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS) + else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS) { click = 1; + } else if (event->type == MINUSKEY && event->val == KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); data->value = -data->value; @@ -2611,7 +2727,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton fac = 1.0f; if (event->shift) fac /= 10.0f; - if (event->alt) fac /= 20.0f; + if (event->alt) fac /= 20.0f; snap = (event->ctrl) ? (event->shift) ? 2 : 1 : 0; @@ -2639,7 +2755,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton softmax = but->softmax; if (!ui_is_but_float(but)) { - if (mx < (but->rect.xmin + BLI_RCT_SIZE_X(&but->rect) / 3 - 3)) { + if (mx < (but->rect.xmin + BLI_rctf_size_x(&but->rect) / 3 - 3)) { button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); temp = (int)data->value - 1; @@ -2650,7 +2766,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton button_activate_state(C, but, BUTTON_STATE_EXIT); } - else if (mx > (but->rect.xmin + (2 * BLI_RCT_SIZE_X(&but->rect) / 3) + 3)) { + else if (mx > (but->rect.xmin + (2 * BLI_rctf_size_x(&but->rect) / 3) + 3)) { button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); temp = (int)data->value + 1; @@ -2661,11 +2777,12 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton button_activate_state(C, but, BUTTON_STATE_EXIT); } - else + else { button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); + } } else { - if (mx < (but->rect.xmin + BLI_RCT_SIZE_X(&but->rect) / 3 - 3)) { + if (mx < (but->rect.xmin + BLI_rctf_size_x(&but->rect) / 3 - 3)) { button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); tempf = (float)data->value - 0.01f * but->a1; @@ -2674,7 +2791,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton button_activate_state(C, but, BUTTON_STATE_EXIT); } - else if (mx > but->rect.xmin + (2 * (BLI_RCT_SIZE_X(&but->rect) / 3) + 3)) { + else if (mx > but->rect.xmin + (2 * (BLI_rctf_size_x(&but->rect) / 3) + 3)) { button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); tempf = (float)data->value + 0.01f * but->a1; @@ -2683,8 +2800,9 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton button_activate_state(C, but, BUTTON_STATE_EXIT); } - else + else { button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); + } } retval = WM_UI_HANDLER_BREAK; @@ -2702,14 +2820,20 @@ static int ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, const short softmax = but->softmax; softrange = softmax - softmin; - if (but->type == NUMSLI) deler = (BLI_RCT_SIZE_X(&but->rect) - 5.0f * but->aspect); - else if (but->type == HSVSLI) deler = (BLI_RCT_SIZE_X(&but->rect) / 2.0f - 5.0f * but->aspect); + if (but->type == NUMSLI) { + deler = (BLI_rctf_size_x(&but->rect) - 5.0f * but->aspect); + } + else if (but->type == HSVSLI) { + deler = (BLI_rctf_size_x(&but->rect) / 2.0f - 5.0f * but->aspect); + } else if (but->type == SCROLL) { - int horizontal = (BLI_RCT_SIZE_X(&but->rect) > BLI_RCT_SIZE_Y(&but->rect)); - float size = (horizontal) ? BLI_RCT_SIZE_X(&but->rect) : -BLI_RCT_SIZE_Y(&but->rect); + int horizontal = (BLI_rctf_size_x(&but->rect) > BLI_rctf_size_y(&but->rect)); + float size = (horizontal) ? BLI_rctf_size_x(&but->rect) : -BLI_rctf_size_y(&but->rect); deler = size * (but->softmax - but->softmin) / (but->softmax - but->softmin + but->a1); } - else deler = (BLI_RCT_SIZE_X(&but->rect) - 5.0f * but->aspect); + else { + deler = (BLI_rctf_size_x(&but->rect) - 5.0f * but->aspect); + } f = (float)(mx - data->dragstartx) / deler + data->dragfstart; @@ -2721,19 +2845,21 @@ static int ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, const short temp = floorf(tempf + 0.5f); if (ctrl) { - if (tempf == softmin || tempf == softmax) ; + if (tempf == softmin || tempf == softmax) { + /* pass */ + } else if (ui_is_but_float(but)) { if (shift) { - if (tempf == softmin || tempf == softmax) ; + if (tempf == softmin || tempf == softmax) {} else if (softmax - softmin < 2.10f) tempf = 0.01f * floorf(100.0f * tempf); - else if (softmax - softmin < 21.0f) tempf = 0.1f * floorf(10.0f * tempf); - else tempf = floorf(tempf); + else if (softmax - softmin < 21.0f) tempf = 0.1f * floorf(10.0f * tempf); + else tempf = floorf(tempf); } else { - if (softmax - softmin < 2.10f) tempf = 0.1f * floorf(10.0f * tempf); + if (softmax - softmin < 2.10f) tempf = 0.1f * floorf(10.0f * tempf); else if (softmax - softmin < 21.0f) tempf = floorf(tempf); - else tempf = 10.0f * floorf(tempf / 10.0f); + else tempf = 10.0f * floorf(tempf / 10.0f); } } else { @@ -2792,7 +2918,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton } /* alt-click on sides to get "arrows" like in NUM buttons, and match wheel usage above */ else if (event->type == LEFTMOUSE && event->alt) { - int halfpos = BLI_RCT_CENTER_X(&but->rect); + int halfpos = BLI_rctf_cent_x(&but->rect); click = 2; if (mx < halfpos) mx = but->rect.xmin; @@ -2805,8 +2931,9 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); retval = WM_UI_HANDLER_BREAK; } - else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS) + else if (ELEM(event->type, PADENTER, RETKEY) && event->val == KM_PRESS) { click = 1; + } else if (event->type == MINUSKEY && event->val == KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); data->value = -data->value; @@ -2859,12 +2986,12 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton #if 0 if (but->type == SLI) { - f = (float)(mx - but->rect.xmin) / (BLI_RCT_SIZE_X(&but->rect)); /* same as below */ + f = (float)(mx - but->rect.xmin) / (BLI_rctf_size_x(&but->rect)); /* same as below */ } else #endif { - f = (float)(mx - but->rect.xmin) / (BLI_RCT_SIZE_X(&but->rect)); + f = (float)(mx - but->rect.xmin) / (BLI_rctf_size_x(&but->rect)); } f = softmin + f * softrange; @@ -2877,7 +3004,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton data->value = temp; else data->cancel = TRUE; - } + } else { if (f < tempf) tempf -= 0.01f; else tempf += 0.01f; @@ -2903,9 +3030,9 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event) { - int mx, my /*, click= 0 */; + int mx, my /*, click = 0 */; int retval = WM_UI_HANDLER_CONTINUE; - int horizontal = (BLI_RCT_SIZE_X(&but->rect) > BLI_RCT_SIZE_Y(&but->rect)); + int horizontal = (BLI_rctf_size_x(&but->rect) > BLI_rctf_size_y(&but->rect)); mx = event->x; my = event->y; @@ -3063,7 +3190,7 @@ static int ui_numedit_but_NORMAL(uiBut *but, uiHandleButtonData *data, int mx, i * else we'll get a harmless but annoying jump when first clicking */ fp = data->origvec; - rad = BLI_RCT_SIZE_X(&but->rect); + rad = BLI_rctf_size_x(&but->rect); radsq = rad * rad; if (fp[2] > 0.0f) { @@ -3076,7 +3203,9 @@ static int ui_numedit_but_NORMAL(uiBut *but, uiHandleButtonData *data, int mx, i mdx = 2.0f * mrad * fp[0] - (rad * fp[0]); mdy = 2.0f * mrad * fp[1] - (rad * fp[1]); } - else mdx = mdy = 0; + else { + mdx = mdy = 0; + } dx = (float)(mx + mdx - data->dragstartx); dy = (float)(my + mdy - data->dragstarty); @@ -3140,8 +3269,9 @@ static int ui_do_but_NORMAL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut ui_numedit_apply(C, block, but, data); } } - else if (event->type == LEFTMOUSE && event->val != KM_PRESS) + else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_EXIT); + } return WM_UI_HANDLER_BREAK; } @@ -3160,6 +3290,15 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, ui_mouse_scale_warp(data, mx, my, &mx_fl, &my_fl, shift); +#ifdef USE_CONT_MOUSE_CORRECT + if (ui_is_a_warp_but(but)) { + /* OK but can go outside bounds */ + data->ungrab_mval[0] = mx_fl; + data->ungrab_mval[1] = my_fl; + BLI_rctf_clamp_pt_v(&but->rect, data->ungrab_mval); + } +#endif + if (but->rnaprop) { if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) color_profile = FALSE; @@ -3173,8 +3312,8 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, rgb_to_hsv_compat_v(rgb, hsv); /* relative position within box */ - x = ((float)mx_fl - but->rect.xmin) / BLI_RCT_SIZE_X(&but->rect); - y = ((float)my_fl - but->rect.ymin) / BLI_RCT_SIZE_Y(&but->rect); + x = ((float)mx_fl - but->rect.xmin) / BLI_rctf_size_x(&but->rect); + y = ((float)my_fl - but->rect.ymin) / BLI_rctf_size_y(&but->rect); CLAMP(x, 0.0f, 1.0f); CLAMP(y, 0.0f, 1.0f); @@ -3266,7 +3405,7 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, wmNDOF case UI_GRAD_V: hsv[2] += ndof->ry * sensitivity; break; - case UI_GRAD_V_ALT: + case UI_GRAD_V_ALT: /* vertical 'value' strip */ /* exception only for value strip - use the range set in but->min/max */ @@ -3364,8 +3503,9 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu ui_numedit_apply(C, block, but, data); } } - else if (event->type == LEFTMOUSE && event->val != KM_PRESS) + else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_EXIT); + } return WM_UI_HANDLER_BREAK; } @@ -3383,6 +3523,22 @@ static int ui_numedit_but_HSVCIRCLE(uiBut *but, uiHandleButtonData *data, float ui_mouse_scale_warp(data, mx, my, &mx_fl, &my_fl, shift); +#ifdef USE_CONT_MOUSE_CORRECT + if (ui_is_a_warp_but(but)) { + /* OK but can go outside bounds */ + data->ungrab_mval[0] = mx_fl; + data->ungrab_mval[1] = my_fl; + { /* clamp */ + const float radius = min_ff(BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect)) / 2.0f; + const float cent[2] = {BLI_rctf_cent_x(&but->rect), BLI_rctf_cent_y(&but->rect)}; + const float len = len_v2v2(cent, data->ungrab_mval); + if (len > radius) { + dist_ensure_v2_v2fl(data->ungrab_mval, cent, radius); + } + } + } +#endif + BLI_rcti_rctf_copy(&rect, &but->rect); ui_get_but_vectorf(but, rgb); @@ -3575,7 +3731,7 @@ static int ui_numedit_but_COLORBAND(uiBut *but, uiHandleButtonData *data, int mx if (data->draglastx == mx) return changed; - dx = ((float)(mx - data->draglastx)) / BLI_RCT_SIZE_X(&but->rect); + dx = ((float)(mx - data->draglastx)) / BLI_rctf_size_x(&but->rect); data->dragcbd->pos += dx; CLAMP(data->dragcbd->pos, 0.0f, 1.0f); @@ -3604,7 +3760,7 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle if (event->ctrl) { /* insert new key on mouse location */ - float pos = ((float)(mx - but->rect.xmin)) / BLI_RCT_SIZE_X(&but->rect); + float pos = ((float)(mx - but->rect.xmin)) / BLI_rctf_size_x(&but->rect); colorband_element_add(coba, pos); button_activate_state(C, but, BUTTON_STATE_EXIT); } @@ -3616,7 +3772,7 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle /* activate new key when mouse is close */ for (a = 0, cbd = coba->data; a < coba->tot; a++, cbd++) { - xco = but->rect.xmin + (cbd->pos * BLI_RCT_SIZE_X(&but->rect)); + xco = but->rect.xmin + (cbd->pos * BLI_rctf_size_x(&but->rect)); xco = ABS(xco - mx); if (a == coba->cur) xco += 5; // selected one disadvantage if (xco < mindist) { @@ -3639,8 +3795,9 @@ static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandle ui_numedit_apply(C, block, but, data); } } - else if (event->type == LEFTMOUSE && event->val != KM_PRESS) + else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { button_activate_state(C, but, BUTTON_STATE_EXIT); + } return WM_UI_HANDLER_BREAK; } @@ -3657,10 +3814,10 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap, float fx, fy, zoomx, zoomy /*, offsx, offsy */ /* UNUSED */; int a, changed = 0; - zoomx = BLI_RCT_SIZE_X(&but->rect) / BLI_RCT_SIZE_X(&cumap->curr); - zoomy = BLI_RCT_SIZE_Y(&but->rect) / BLI_RCT_SIZE_Y(&cumap->curr); - /* offsx= cumap->curr.xmin; */ - /* offsy= cumap->curr.ymin; */ + zoomx = BLI_rctf_size_x(&but->rect) / BLI_rctf_size_x(&cumap->curr); + zoomy = BLI_rctf_size_y(&but->rect) / BLI_rctf_size_y(&cumap->curr); + /* offsx = cumap->curr.xmin; */ + /* offsy = cumap->curr.ymin; */ if (snap) { float d[2]; @@ -3673,9 +3830,10 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap, } if (data->dragsel != -1) { + CurveMapPoint *cmp_last = NULL; const float mval_factor = ui_mouse_scale_warp_factor(shift); int moved_point = 0; /* for ctrl grid, can't use orig coords because of sorting */ - + fx = (mx - data->draglastx) / zoomx; fy = (my - data->draglasty) / zoomy; @@ -3693,6 +3851,8 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap, } if (cmp[a].x != origx || cmp[a].y != origy) moved_point = 1; + + cmp_last = &cmp[a]; } } @@ -3702,6 +3862,18 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap, data->draglastx = mx; data->draglasty = my; changed = 1; + +#ifdef USE_CONT_MOUSE_CORRECT + /* note: using 'cmp_last' is weak since there may be multiple points selected, + * but in practice this isnt really an issue */ + if (ui_is_a_warp_but(but)) { + /* OK but can go outside bounds */ + data->ungrab_mval[0] = but->rect.xmin + ((cmp_last->x - cumap->curr.xmin) * zoomx); + data->ungrab_mval[1] = but->rect.ymin + ((cmp_last->y - cumap->curr.ymin) * zoomy); + BLI_rctf_clamp_pt_v(&but->rect, data->ungrab_mval); + } +#endif + } data->dragchange = 1; /* mark for selection */ @@ -3753,8 +3925,8 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt float dist, mindist = 200.0f; // 14 pixels radius int sel = -1; - zoomx = BLI_RCT_SIZE_X(&but->rect) / BLI_RCT_SIZE_X(&cumap->curr); - zoomy = BLI_RCT_SIZE_Y(&but->rect) / BLI_RCT_SIZE_Y(&cumap->curr); + zoomx = BLI_rctf_size_x(&but->rect) / BLI_rctf_size_x(&cumap->curr); + zoomy = BLI_rctf_size_y(&but->rect) / BLI_rctf_size_y(&cumap->curr); offsx = cumap->curr.xmin; offsy = cumap->curr.ymin; @@ -3801,7 +3973,7 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt changed = 1; - /* reset cmp back to the curve points again, rather than drawing segments */ + /* reset cmp back to the curve points again, rather than drawing segments */ cmp = cuma->curve; /* find newly added point and make it 'sel' */ @@ -3818,12 +3990,14 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt /* ok, we move a point */ /* deselect all if this one is deselect. except if we hold shift */ if (event->shift == FALSE) { - for (a = 0; a < cuma->totpoint; a++) + for (a = 0; a < cuma->totpoint; a++) { cmp[a].flag &= ~CUMA_SELECT; + } cmp[sel].flag |= CUMA_SELECT; } - else + else { cmp[sel].flag ^= CUMA_SELECT; + } } else { /* move the view */ @@ -3899,11 +4073,11 @@ static int ui_numedit_but_HISTOGRAM(uiBut *but, uiHandleButtonData *data, int mx if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) { /* resize histogram widget itself */ - hist->height = BLI_RCT_SIZE_Y(&but->rect) + (data->dragstarty - my); + hist->height = BLI_rctf_size_y(&but->rect) + (data->dragstarty - my); } else { /* scale histogram values (dy / 10 for better control) */ - const float yfac = minf(powf(hist->ymax, 2.0f), 1.0f) * 0.5f; + const float yfac = min_ff(powf(hist->ymax, 2.0f), 1.0f) * 0.5f; hist->ymax += (dy * 0.1f) * yfac; /* 0.1 allows us to see HDR colors up to 10 */ @@ -3973,7 +4147,7 @@ static int ui_numedit_but_WAVEFORM(uiBut *but, uiHandleButtonData *data, int mx, Scopes *scopes = (Scopes *)but->poin; /* rcti rect; */ int changed = 1; - float /* dx, */ dy /* , yfac=1.f */; /* UNUSED */ + float /* dx, */ dy /* , yfac =1.0f */; /* UNUSED */ /* BLI_rcti_rctf_copy(&rect, &but->rect); */ @@ -3983,7 +4157,7 @@ static int ui_numedit_but_WAVEFORM(uiBut *but, uiHandleButtonData *data, int mx, if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) { /* resize waveform widget itself */ - scopes->wavefrm_height = BLI_RCT_SIZE_Y(&but->rect) + (data->dragstarty - my); + scopes->wavefrm_height = BLI_rctf_size_y(&but->rect) + (data->dragstarty - my); } else { /* scale waveform values */ @@ -4065,7 +4239,7 @@ static int ui_numedit_but_VECTORSCOPE(uiBut *but, uiHandleButtonData *data, int if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) { /* resize vectorscope widget itself */ - scopes->vecscope_height = BLI_RCT_SIZE_Y(&but->rect) + (data->dragstarty - my); + scopes->vecscope_height = BLI_rctf_size_y(&but->rect) + (data->dragstarty - my); } data->draglastx = mx; @@ -4135,8 +4309,8 @@ static int ui_do_but_CHARTAB(bContext *UNUSED(C), uiBlock *UNUSED(block), uiBut if (data->state == BUTTON_STATE_HIGHLIGHT) { if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) { /* Calculate the size of the button */ - width = abs(BLI_RCT_SIZE_X(&but->rect)); - height = abs(BLI_RCT_SIZE_Y(&but->rect)); + width = abs(BLI_rctf_size_x(&but->rect)); + height = abs(BLI_rctf_size_y(&but->rect)); butw = floor(width / 12); buth = floor(height / 6); @@ -4268,7 +4442,7 @@ static int ui_numedit_but_TRACKPREVIEW(bContext *C, uiBut *but, uiHandleButtonDa if (in_scope_resize_zone(but, data->dragstartx, data->dragstarty)) { /* resize preview widget itself */ - scopes->track_preview_height = BLI_RCT_SIZE_Y(&but->rect) + (data->dragstarty - my); + scopes->track_preview_height = BLI_rctf_size_y(&but->rect) + (data->dragstarty - my); } else { if (!scopes->track_locked) { @@ -4276,8 +4450,8 @@ static int ui_numedit_but_TRACKPREVIEW(bContext *C, uiBut *but, uiHandleButtonDa scopes->marker = BKE_tracking_marker_ensure(scopes->track, scopes->framenr); scopes->marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED); - scopes->marker->pos[0] += -dx * scopes->slide_scale[0] / BLI_RCT_SIZE_X(&but->block->rect); - scopes->marker->pos[1] += -dy * scopes->slide_scale[1] / BLI_RCT_SIZE_Y(&but->block->rect); + scopes->marker->pos[0] += -dx * scopes->slide_scale[0] / BLI_rctf_size_x(&but->block->rect); + scopes->marker->pos[1] += -dy * scopes->slide_scale[1] / BLI_rctf_size_y(&but->block->rect); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL); } @@ -4403,11 +4577,11 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg) int kmi_id; /* XXX this guess_opname can potentially return a different keymap than being found on adding later... */ - km = WM_keymap_guess_opname(C, but->optype->idname); + km = WM_keymap_guess_opname(C, but->optype->idname); kmi = WM_keymap_add_item(km, but->optype->idname, AKEY, KM_PRESS, 0, 0); kmi_id = kmi->id; - /* copy properties, prop can be NULL for reset */ + /* copy properties, prop can be NULL for reset */ if (prop) prop = IDP_CopyProperty(prop); WM_keymap_properties_reset(kmi, prop); @@ -4415,14 +4589,13 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg) /* update and get pointers again */ WM_keyconfig_update(wm); - km = WM_keymap_guess_opname(C, but->optype->idname); + km = WM_keymap_guess_opname(C, but->optype->idname); kmi = WM_keymap_item_find_id(km, kmi_id); RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr); block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS); uiBlockSetHandleFunc(block, but_shortcut_name_func, but); - uiBlockSetFlag(block, UI_BLOCK_RET_1); uiBlockSetDirection(block, UI_CENTER); layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, style); @@ -4466,6 +4639,7 @@ static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) static int ui_but_menu(bContext *C, uiBut *but) { + ARegion *ar = CTX_wm_region(C); uiPopupMenu *pup; uiLayout *layout; int length; @@ -4477,17 +4651,8 @@ static int ui_but_menu(bContext *C, uiBut *but) button_timers_tooltip_remove(C, but); -#if 0 - if (but->rnaprop) - name = RNA_property_ui_name(but->rnaprop); - else if (but->optype && but->optype->srna) - name = RNA_struct_ui_name(but->optype->srna); - else - name = IFACE_(""); // XXX - should never happen. -#else uiButGetStrInfo(C, but, 1, &label); name = label.strinfo; -#endif pup = uiPupMenuBegin(C, name, ICON_NONE); layout = uiPupMenuLayout(pup); @@ -4531,7 +4696,9 @@ static int ui_but_menu(bContext *C, uiBut *but) } - else if (but->flag & UI_BUT_DRIVEN) ; + else if (but->flag & UI_BUT_DRIVEN) { + /* pass */ + } else if (is_anim) { if (length) { uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframes"), @@ -4539,9 +4706,10 @@ static int ui_but_menu(bContext *C, uiBut *but) uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Single Keyframe"), ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0); } - else + else { uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframe"), ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0); + } } if (but->flag & UI_BUT_ANIMATED) { @@ -4567,17 +4735,21 @@ static int ui_but_menu(bContext *C, uiBut *but) uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Driver"), ICON_NONE, "ANIM_OT_driver_button_remove", "all", 0); } - else + else { uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Driver"), ICON_NONE, "ANIM_OT_driver_button_remove", "all", 0); + } uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Driver"), ICON_NONE, "ANIM_OT_copy_driver_button"); - if (ANIM_driver_can_paste()) + if (ANIM_driver_can_paste()) { uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"), ICON_NONE, "ANIM_OT_paste_driver_button"); + } + } + else if (but->flag & (UI_BUT_ANIMATED_KEY | UI_BUT_ANIMATED)) { + /* pass */ } - else if (but->flag & (UI_BUT_ANIMATED_KEY | UI_BUT_ANIMATED)) ; else if (is_anim) { uiItemS(layout); @@ -4587,13 +4759,15 @@ static int ui_but_menu(bContext *C, uiBut *but) uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add Single Driver"), ICON_NONE, "ANIM_OT_driver_button_add", "all", 0); } - else + else { uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"), ICON_NONE, "ANIM_OT_driver_button_add", "all", 0); + } - if (ANIM_driver_can_paste()) + if (ANIM_driver_can_paste()) { uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"), ICON_NONE, "ANIM_OT_paste_driver_button"); + } } /* Keying Sets */ @@ -4621,8 +4795,8 @@ static int ui_but_menu(bContext *C, uiBut *but) /* Property Operators */ - /*Copy Property Value - *Paste Property Value */ + /* Copy Property Value + * Paste Property Value */ if (length) { uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Reset All to Default Values"), @@ -4630,9 +4804,10 @@ static int ui_but_menu(bContext *C, uiBut *but) uiItemBooleanO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Reset Single to Default Value"), ICON_NONE, "UI_OT_reset_default_button", "all", 0); } - else + else { uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Reset to Default Value"), ICON_NONE, "UI_OT_reset_default_button"); + } uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Data Path"), ICON_NONE, "UI_OT_copy_data_path_button"); @@ -4679,7 +4854,12 @@ static int ui_but_menu(bContext *C, uiBut *but) uiItemS(layout); } - + /* Show header tools for header buttons. */ + if (ar->regiontype == RGN_TYPE_HEADER) { + uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL); + uiItemS(layout); + } + { /* Docs */ char buf[512]; PointerRNA ptr_props; @@ -4753,14 +4933,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) if (but->flag & UI_BUT_DISABLED) return WM_UI_HANDLER_CONTINUE; - if ((data->state == BUTTON_STATE_HIGHLIGHT) && - /* check prevval because of modal operators [#24016], - * modifier check is to allow Ctrl+C for copy. - * if this causes other problems, remove this check and suffer the bug :) - campbell */ - ((event->prevval != KM_PRESS) || (ISKEYMODIFIER(event->prevtype)) || (event->type == EVT_DROP))) - { + if ((data->state == BUTTON_STATE_HIGHLIGHT) || (event->type == EVT_DROP)) { /* handle copy-paste */ if (ELEM(event->type, CKEY, VKEY) && event->val == KM_PRESS && (event->ctrl || event->oskey)) { + ui_but_copy_paste(C, but, data, (event->type == CKEY) ? 'c' : 'v'); return WM_UI_HANDLER_BREAK; } @@ -4842,7 +5018,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) button_activate_state(C, but, BUTTON_STATE_EXIT); return WM_UI_HANDLER_BREAK; } - } + } else if (but->pointype && but->poin == NULL) { /* there's a pointer needed */ BKE_reportf(NULL, RPT_WARNING, "DoButton pointer error: %s", but->str); @@ -5237,12 +5413,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s /* automatic open pulldown block timer */ if (ELEM3(but->type, BLOCK, PULLDOWN, ICONTEXTROW)) { - if ((data->used_mouse == TRUE) && - (data->autoopentimer == FALSE) && - /* don't popup the first time, - * see description on this member for info */ - (but->block->auto_is_first_event == FALSE)) - { + if (data->used_mouse && !data->autoopentimer) { int time; if (but->block->auto_open == TRUE) { /* test for toolbox */ @@ -5262,8 +5433,6 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s data->autoopentimer = WM_event_add_timer(data->wm, data->window, TIMER, 0.02 * (double)time); } } - - but->block->auto_is_first_event = FALSE; } } else { @@ -5287,8 +5456,24 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s } else if (data->state == BUTTON_STATE_NUM_EDITING) { ui_numedit_end(but, data); - if (ui_is_a_warp_but(but)) - WM_cursor_grab_disable(CTX_wm_window(C)); + if (ui_is_a_warp_but(but)) { + +#ifdef USE_CONT_MOUSE_CORRECT + if (data->ungrab_mval[0] != FLT_MAX) { + int mouse_ungrab_xy[2]; + ui_block_to_window_fl(data->region, but->block, &data->ungrab_mval[0], &data->ungrab_mval[1]); + mouse_ungrab_xy[0] = data->ungrab_mval[0]; + mouse_ungrab_xy[1] = data->ungrab_mval[1]; + + WM_cursor_grab_disable(data->window, mouse_ungrab_xy); + } + else { + WM_cursor_grab_disable(data->window, NULL); + } +#else + WM_cursor_grab_disable(data->window, ); +#endif + } } /* menu open */ if (state == BUTTON_STATE_MENU_OPEN) @@ -5351,6 +5536,10 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA data->window = CTX_wm_window(C); data->region = ar; +#ifdef USE_CONT_MOUSE_CORRECT + copy_v2_fl(data->ungrab_mval, FLT_MAX); +#endif + if (ELEM(but->type, BUT_CURVE, SEARCH_MENU)) { /* XXX curve is temp */ } @@ -5632,20 +5821,24 @@ void uiContextAnimUpdate(const bContext *C) ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f); ED_region_tag_redraw(ar); - if (but->active) + if (but->active) { activebut = but; - else if (!activebut && (but->flag & UI_BUT_LAST_ACTIVE)) + } + else if (!activebut && (but->flag & UI_BUT_LAST_ACTIVE)) { activebut = but; + } } } if (activebut) { /* always recurse into opened menu, so all buttons update (like colorpicker) */ uiHandleButtonData *data = activebut->active; - if (data && data->menu) + if (data && data->menu) { ar = data->menu->region; - else + } + else { return; + } } else { /* no active button */ @@ -5675,8 +5868,9 @@ static int ui_handle_button_over(bContext *C, wmEvent *event, ARegion *ar) if (event->type == MOUSEMOVE) { but = ui_but_find_mouse_over(ar, event->x, event->y); - if (but) + if (but) { button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER); + } } else if (event->type == EVT_BUT_OPEN) { but = uit_but_find_open_event(ar, event); @@ -5897,7 +6091,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) } else { retval = ui_do_button(C, block, but, event); - // retval= WM_UI_HANDLER_BREAK; XXX why ? + // retval = WM_UI_HANDLER_BREAK; XXX why ? } if (data->state == BUTTON_STATE_EXIT) { @@ -6113,73 +6307,81 @@ static char ui_menu_scroll_test(uiBlock *block, int my) { if (block->flag & (UI_BLOCK_CLIPTOP | UI_BLOCK_CLIPBOTTOM)) { if (block->flag & UI_BLOCK_CLIPTOP) - if (my > block->rect.ymax - 14) + if (my > block->rect.ymax - UI_MENU_SCROLL_MOUSE) return 't'; if (block->flag & UI_BLOCK_CLIPBOTTOM) - if (my < block->rect.ymin + 14) + if (my < block->rect.ymin + UI_MENU_SCROLL_MOUSE) return 'b'; } return 0; } -static int ui_menu_scroll(ARegion *ar, uiBlock *block, int my) +static int ui_menu_scroll(ARegion *ar, uiBlock *block, int my, uiBut *to_bt) { - char test = ui_menu_scroll_test(block, my); - - if (test) { - uiBut *b1 = block->buttons.first; - uiBut *b2 = block->buttons.last; - uiBut *bnext; - uiBut *bprev; - int dy = 0; - - /* get first and last visible buttons */ - while (b1 && ui_but_next(b1) && (b1->flag & UI_SCROLLED)) - b1 = ui_but_next(b1); - while (b2 && ui_but_prev(b2) && (b2->flag & UI_SCROLLED)) - b2 = ui_but_prev(b2); - /* skips separators */ - bnext = ui_but_next(b1); - bprev = ui_but_prev(b2); - - if (bnext == NULL || bprev == NULL) - return 0; - - if (test == 't') { - /* bottom button is first button */ - if (b1->rect.ymin < b2->rect.ymin) - dy = bnext->rect.ymin - b1->rect.ymin; - /* bottom button is last button */ - else - dy = bprev->rect.ymin - b2->rect.ymin; + uiBut *bt; + float dy = 0.0f; + + if (to_bt) { + /* scroll to activated button */ + if (block->flag & UI_BLOCK_CLIPTOP) { + if (to_bt->rect.ymax > block->rect.ymax - UI_MENU_SCROLL_ARROW) + dy = block->rect.ymax - to_bt->rect.ymax - UI_MENU_SCROLL_ARROW; } - else if (test == 'b') { - /* bottom button is first button */ - if (b1->rect.ymin < b2->rect.ymin) - dy = b1->rect.ymin - bnext->rect.ymin; - /* bottom button is last button */ - else - dy = b2->rect.ymin - bprev->rect.ymin; + if (block->flag & UI_BLOCK_CLIPBOTTOM) { + if (to_bt->rect.ymin < block->rect.ymin + UI_MENU_SCROLL_ARROW) + dy = block->rect.ymin - to_bt->rect.ymin + UI_MENU_SCROLL_ARROW; } - if (dy) { - - for (b1 = block->buttons.first; b1; b1 = b1->next) { - b1->rect.ymin -= dy; - b1->rect.ymax -= dy; - } - /* set flags again */ - ui_popup_block_scrolltest(block); - - ED_region_tag_redraw(ar); - - return 1; + } + else { + /* scroll when mouse over arrow buttons */ + char test = ui_menu_scroll_test(block, my); + + if (test == 't') + dy = -UI_UNIT_Y; /* scroll to the top */ + else if (test == 'b') + dy = UI_UNIT_Y; /* scroll to the bottom */ + } + + if (dy != 0.0f) { + if (dy < 0.0f) { + /* stop at top item, extra 0.5 unit Y makes it snap nicer */ + float ymax = -FLT_MAX; + + for (bt = block->buttons.first; bt; bt = bt->next) + ymax = max_ff(ymax, bt->rect.ymax); + + if (ymax + dy - UI_UNIT_Y*0.5f < block->rect.ymax - UI_MENU_SCROLL_PAD) + dy = block->rect.ymax - ymax - UI_MENU_SCROLL_PAD; } + else { + /* stop at bottom item, extra 0.5 unit Y makes it snap nicer */ + float ymin = FLT_MAX; + + for (bt = block->buttons.first; bt; bt = bt->next) + ymin = min_ff(ymin, bt->rect.ymin); + + if (ymin + dy + UI_UNIT_Y*0.5f > block->rect.ymin + UI_MENU_SCROLL_PAD) + dy = block->rect.ymin - ymin + UI_MENU_SCROLL_PAD; + } + + /* apply scroll offset */ + for (bt = block->buttons.first; bt; bt = bt->next) { + bt->rect.ymin += dy; + bt->rect.ymax += dy; + } + + /* set flags again */ + ui_popup_block_scrolltest(block); + + ED_region_tag_redraw(ar); + + return 1; } return 0; } -static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle *menu, int UNUSED(topmenu)) +static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle *menu, int level) { ARegion *ar; uiBlock *block; @@ -6209,7 +6411,7 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle } else if (event->type == TIMER) { if (event->customdata == menu->scrolltimer) - ui_menu_scroll(ar, block, my); + ui_menu_scroll(ar, block, my, NULL); } else { /* for ui_mouse_motion_towards_block */ @@ -6224,10 +6426,22 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle } /* first block own event func */ - if (block->block_event_func && block->block_event_func(C, block, event)) ; - /* events not for active search menu button */ + if (block->block_event_func && block->block_event_func(C, block, event)) { + /* pass */ + } /* events not for active search menu button */ else if (but == NULL || but->type != SEARCH_MENU) { switch (event->type) { + + + /* let the parent menu get the event */ +#define PASS_EVENT_TO_PARENT_IF_NONACTIVE \ + if ((level != 0) && (but == NULL)) { \ + menu->menuretval = UI_RETURN_OUT | UI_RETURN_OUT_PARENT; \ + BLI_assert(retval == WM_UI_HANDLER_CONTINUE); \ + break; \ + } (void)0 + + /* closing sublevels of pulldowns */ case LEFTARROWKEY: if (event->val == KM_PRESS && (block->flag & UI_BLOCK_LOOP)) @@ -6238,8 +6452,11 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle break; /* opening sublevels of pulldowns */ - case RIGHTARROWKEY: + case RIGHTARROWKEY: if (event->val == KM_PRESS && (block->flag & UI_BLOCK_LOOP)) { + + PASS_EVENT_TO_PARENT_IF_NONACTIVE; + but = ui_but_find_activated(ar); if (!but) { @@ -6265,6 +6482,9 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle } else if (inside || (block->flag & UI_BLOCK_LOOP)) { if (event->val == KM_PRESS) { + + PASS_EVENT_TO_PARENT_IF_NONACTIVE; + but = ui_but_find_activated(ar); if (but) { /* is there a situation where UI_LEFT or UI_RIGHT would also change navigation direction? */ @@ -6286,8 +6506,10 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle but = ui_but_next(but); } - if (but) + if (but) { ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE); + ui_menu_scroll(ar, block, my, but); + } } if (!but) { @@ -6313,6 +6535,7 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle if (bt) { ui_handle_button_activate(C, ar, bt, BUTTON_ACTIVATE); + ui_menu_scroll(ar, block, my, bt); } } } @@ -6344,6 +6567,9 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle if (act == 0) act = 10; if ((block->flag & UI_BLOCK_NUMSELECT) && event->val == KM_PRESS) { + + PASS_EVENT_TO_PARENT_IF_NONACTIVE; + if (event->alt) act += 10; count = 0; @@ -6416,11 +6642,13 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle case YKEY: case ZKEY: { - if ((event->val == KM_PRESS) && + if ((event->val == KM_PRESS || event->val == KM_DBL_CLICK) && (event->shift == FALSE) && (event->ctrl == FALSE) && (event->oskey == FALSE)) { + PASS_EVENT_TO_PARENT_IF_NONACTIVE; + for (but = block->buttons.first; but; but = but->next) { if (but->menu_key == event->type) { @@ -6468,7 +6696,9 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle } } - if (menu->menuretval) ; + if (menu->menuretval) { + /* pass */ + } else if (event->type == ESCKEY && event->val == KM_PRESS) { /* esc cancels this and all preceding menus */ menu->menuretval = UI_RETURN_CANCEL; @@ -6510,6 +6740,10 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle retval = WM_UI_HANDLER_BREAK; } } + + /* end switch */ +#undef PASS_EVENT_TO_PARENT_IF_NONACTIVE + } } @@ -6598,7 +6832,7 @@ static int ui_handle_menu_return_submenu(bContext *C, wmEvent *event, uiPopupBlo return WM_UI_HANDLER_BREAK; } -static int ui_handle_menus_recursive(bContext *C, wmEvent *event, uiPopupBlockHandle *menu) +static int ui_handle_menus_recursive(bContext *C, wmEvent *event, uiPopupBlockHandle *menu, int level) { uiBut *but; uiHandleButtonData *data; @@ -6611,14 +6845,24 @@ static int ui_handle_menus_recursive(bContext *C, wmEvent *event, uiPopupBlockHa submenu = (data) ? data->menu : NULL; if (submenu) - retval = ui_handle_menus_recursive(C, event, submenu); + retval = ui_handle_menus_recursive(C, event, submenu, level + 1); /* now handle events for our own menu */ if (retval == WM_UI_HANDLER_CONTINUE || event->type == TIMER) { - if (submenu && submenu->menuretval) + if (submenu && submenu->menuretval) { + int do_ret_out_parent = (submenu->menuretval & UI_RETURN_OUT_PARENT); retval = ui_handle_menu_return_submenu(C, event, menu); - else - retval = ui_handle_menu_event(C, event, menu, (submenu == NULL)); + submenu = NULL; /* hint not to use this, it may be freed by call above */ + (void)submenu; + /* we may wan't to quit the submenu and handle the even in this menu, + * if its important to use it, check 'data->menu' first */ + if ((retval == WM_UI_HANDLER_BREAK) && do_ret_out_parent) { + retval = ui_handle_menu_event(C, event, menu, level); + } + } + else { + retval = ui_handle_menu_event(C, event, menu, level); /* same as above */ + } } return retval; @@ -6706,7 +6950,7 @@ static int ui_handler_region_menu(bContext *C, wmEvent *event, void *UNUSED(user if (data->state == BUTTON_STATE_MENU_OPEN) { /* handle events for menus and their buttons recursively, * this will handle events from the top to the bottom menu */ - retval = ui_handle_menus_recursive(C, event, data->menu); + retval = ui_handle_menus_recursive(C, event, data->menu, 0); /* handle events for the activated button */ if (retval == WM_UI_HANDLER_CONTINUE || event->type == TIMER) { @@ -6750,7 +6994,7 @@ static int ui_handler_popup(bContext *C, wmEvent *event, void *userdata) retval = WM_UI_HANDLER_CONTINUE; } - ui_handle_menus_recursive(C, event, menu); + ui_handle_menus_recursive(C, event, menu, 0); /* free if done, does not free handle itself */ if (menu->menuretval) { diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 0921107b8e6..bb0cc1176d8 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -142,7 +142,7 @@ static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int new_icon = MEM_callocN(sizeof(Icon), "texicon"); new_icon->obj = NULL; /* icon is not for library object */ - new_icon->type = 0; + new_icon->type = 0; di = MEM_callocN(sizeof(DrawInfo), "drawinfo"); di->type = type; @@ -852,7 +852,7 @@ static void icon_set_image(bContext *C, ID *id, PreviewImage *prv_img, enum eIco if (G.debug & G_DEBUG) printf("%s: no preview image for this ID: %s\n", __func__, id->name); return; - } + } icon_create_rect(prv_img, size); @@ -982,8 +982,8 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al if (!di) { di = icon_create_drawinfo(); - icon->drawinfo = di; - icon->drawinfo_free = UI_icons_free_drawinfo; + icon->drawinfo = di; + icon->drawinfo_free = UI_icons_free_drawinfo; } /* scale width and height according to aspect */ @@ -994,13 +994,13 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al /* vector icons use the uiBlock transformation, they are not drawn * with untransformed coordinates like the other icons */ di->data.vector.func((int)x, (int)y, ICON_DEFAULT_HEIGHT, ICON_DEFAULT_HEIGHT, 1.0f); - } + } else if (di->type == ICON_TYPE_TEXTURE) { icon_draw_texture(x, y, (float)w, (float)h, di->data.texture.x, di->data.texture.y, di->data.texture.w, di->data.texture.h, alpha, rgb); } else if (di->type == ICON_TYPE_BUFFER) { - /* it is a builtin icon */ + /* it is a builtin icon */ iimg = di->data.buffer.image; if (!iimg->rect) return; /* something has gone wrong! */ @@ -1010,7 +1010,7 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al else if (di->type == ICON_TYPE_PREVIEW) { PreviewImage *pi = BKE_previewimg_get((ID *)icon->obj); - if (pi) { + if (pi) { /* no create icon on this level in code */ if (!pi->rect[size]) return; /* something has gone wrong! */ diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 928e1671cee..16159e0f73a 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -97,6 +97,11 @@ typedef enum { UI_WTYPE_PROGRESSBAR } uiWidgetTypeEnum; +/* menu scrolling */ +#define UI_MENU_SCROLL_ARROW 12 +#define UI_MENU_SCROLL_MOUSE (UI_MENU_SCROLL_ARROW + 2) +#define UI_MENU_SCROLL_PAD 4 + /* panel limits */ #define UI_PANEL_MINX 100 #define UI_PANEL_MINY 70 @@ -160,7 +165,8 @@ struct uiBut { int flag, drawflag; eButType type; eButPointerType pointype; - short bit, bitnr, retval, strwidth, ofs, pos, selsta, selend, alignnr; + short bit, bitnr, retval, strwidth, alignnr; + short ofs, pos, selsta, selend; char *str; char strdata[UI_MAX_NAME_STR]; @@ -305,17 +311,7 @@ struct uiBlock { char direction; char dt; /* drawtype: UI_EMBOSS, UI_EMBOSSN ... etc, copied to buttons */ char auto_open; - - /* this setting is used so newly opened menu's dont popout the first item under the mouse, - * the reasoning behind this is because of muscle memory for opening menus. - * - * Without this, the first time opening a Submenu and activating an item in it will be 2 steps, - * but the second time the same item is accessed the menu memory would auto activate the - * last used menu and the key intended to select that submenu ends up being passed into the submenu. - * - Campbell - */ - char auto_is_first_event; - char _pad[6]; + char _pad[7]; double auto_open_last; const char *lockstr; @@ -325,7 +321,6 @@ struct uiBlock { char tooltipdisabled; /* to avoid tooltip after click */ char endblock; /* uiEndBlock done? */ - float xofs, yofs; /* offset to parent button */ eBlockBoundsCalc bounds_type; /* for doing delayed */ int mx, my; int bounds, minbounds; /* for doing delayed */ @@ -375,7 +370,8 @@ extern void ui_set_but_hsv(uiBut *but); extern void ui_get_but_vectorf(uiBut *but, float vec[3]); extern void ui_set_but_vectorf(uiBut *but, const float vec[3]); -extern void ui_hsvcircle_vals_from_pos(float *valrad, float *valdist, rcti *rect, float mx, float my); +extern void ui_hsvcircle_vals_from_pos(float *val_rad, float *val_dist, const rcti *rect, + const float mx, const float my); extern void ui_get_but_string(uiBut *but, char *str, size_t maxlen); extern void ui_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen); @@ -428,6 +424,9 @@ struct uiPopupBlockHandle { int menuretval; float retvalue; float retvec[4]; + + /* menu direction */ + int direction; }; uiBlock *ui_block_func_COLOR(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but); @@ -473,7 +472,7 @@ extern int ui_handler_panel_region(struct bContext *C, struct wmEvent *event); extern void ui_draw_aligned_panel(struct uiStyle *style, uiBlock *block, rcti *rect); /* interface_draw.c */ -extern void ui_dropshadow(rctf *rct, float radius, float aspect, float alpha, int select); +extern void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select); void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const float alpha); @@ -490,6 +489,8 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, struct uiWidgetColors *wc extern void ui_button_activate_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 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); /* interface_widgets.c */ void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); @@ -509,7 +510,7 @@ void ui_widget_color_init(struct ThemeUI *tui); void ui_draw_menu_item(struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state); void ui_draw_preview_item(struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state); -extern unsigned char checker_stipple_sml[]; +extern unsigned char checker_stipple_sml[32 * 32 / 8]; /* used for transp checkers */ #define UI_TRANSP_DARK 100 #define UI_TRANSP_LIGHT 160 diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 803fd928085..5170fc7d51b 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -41,6 +41,7 @@ #include "BLI_string.h" #include "BLI_rect.h" #include "BLI_utildefines.h" +#include "BLI_math.h" #include "BLF_translation.h" @@ -239,10 +240,8 @@ static void ui_item_size(uiItem *item, int *r_w, int *r_h) if (item->type == ITEM_BUTTON) { uiButtonItem *bitem = (uiButtonItem *)item; - - - if (r_w) *r_w = BLI_RCT_SIZE_X(&bitem->but->rect); - if (r_h) *r_h = BLI_RCT_SIZE_Y(&bitem->but->rect); + if (r_w) *r_w = BLI_rctf_size_x(&bitem->but->rect); + if (r_h) *r_h = BLI_rctf_size_y(&bitem->but->rect); } else { uiLayout *litem = (uiLayout *)item; @@ -837,8 +836,9 @@ void uiItemsFullEnumO(uiLayout *layout, const char *opname, const char *propname bt = block->buttons.last; bt->flag = UI_TEXT_LEFT; } - else /* XXX bug here, collums draw bottom item badly */ + else { /* XXX bug here, colums draw bottom item badly */ uiItemS(column); + } } } @@ -1314,7 +1314,7 @@ static void rna_search_cb(const struct bContext *C, void *arg_but, const char *s BLI_addtail(items_list, cis); } MEM_freeN(name); - } + } i++; } @@ -1377,7 +1377,7 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN /* turn button into search button */ if (searchprop) { but->type = SEARCH_MENU; - but->hardmax = MAX2(but->hardmax, 256); + but->hardmax = MAX2(but->hardmax, 256.0f); but->rnasearchpoin = *searchptr; but->rnasearchprop = searchprop; but->flag |= UI_ICON_LEFT | UI_TEXT_LEFT; @@ -1450,6 +1450,11 @@ static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt) menu.type = mt; menu.layout = layout; + + if (G.debug & G_DEBUG_WM) { + printf("%s: opening menu \"%s\"\n", __func__, mt->idname); + } + mt->draw(C, &menu); } @@ -1709,7 +1714,7 @@ static void ui_litem_layout_row(uiLayout *litem) int x, y, w, tot, totw, neww, itemw, minw, itemh, offset; int fixedw, freew, fixedx, freex, flag = 0, lastw = 0; - /* x= litem->x; */ /* UNUSED */ + /* x = litem->x; */ /* UNUSED */ y = litem->y; w = litem->w; totw = 0; @@ -1933,8 +1938,8 @@ static void ui_litem_estimate_column_flow(uiLayout *litem) return; } - flow->totcol = MAX2(litem->root->emw / maxw, 1); - flow->totcol = MIN2(flow->totcol, totitem); + flow->totcol = max_ii(litem->root->emw / maxw, 1); + flow->totcol = min_ii(flow->totcol, totitem); } else flow->totcol = flow->number; @@ -2008,7 +2013,7 @@ static void ui_litem_layout_column_flow(uiLayout *litem) emy -= itemh; ui_item_position(item, x + offset, y, itemw, itemh); y -= style->buttonspacey; - miny = MIN2(miny, y); + miny = min_ii(miny, y); /* decide to go to next one */ if (col < flow->totcol - 1 && emy <= -emh) { @@ -2039,8 +2044,8 @@ static void ui_litem_estimate_absolute(uiLayout *litem) ui_item_offset(item, &itemx, &itemy); ui_item_size(item, &itemw, &itemh); - minx = MIN2(minx, itemx); - miny = MIN2(miny, itemy); + minx = min_ii(minx, itemx); + miny = min_ii(miny, itemy); litem->w = MAX2(litem->w, itemx + itemw); litem->h = MAX2(litem->h, itemy + itemh); @@ -2065,11 +2070,11 @@ static void ui_litem_layout_absolute(uiLayout *litem) ui_item_offset(item, &itemx, &itemy); ui_item_size(item, &itemw, &itemh); - minx = MIN2(minx, itemx); - miny = MIN2(miny, itemy); + minx = min_ii(minx, itemx); + miny = min_ii(miny, itemy); - totw = MAX2(totw, itemx + itemw); - toth = MAX2(toth, itemy + itemh); + totw = max_ii(totw, itemx + itemw); + toth = max_ii(toth, itemy + itemh); } totw -= minx; @@ -2517,8 +2522,12 @@ static void ui_item_align(uiLayout *litem, short nr) if (!bitem->but->alignnr) bitem->but->alignnr = nr; } - else if (item->type == ITEM_LAYOUT_ABSOLUTE) ; - else if (item->type == ITEM_LAYOUT_OVERLAP) ; + else if (item->type == ITEM_LAYOUT_ABSOLUTE) { + /* pass */ + } + else if (item->type == ITEM_LAYOUT_OVERLAP) { + /* pass */ + } else if (item->type == ITEM_LAYOUT_BOX) { box = (uiLayoutItemBx *)item; box->roundbox->alignnr = nr; @@ -2872,12 +2881,12 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op, WM_operator_properties_create(&op_ptr, "WM_OT_operator_preset_add"); RNA_string_set(&op_ptr, "operator", op->type->idname); - op_ptr = uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMIN, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); + uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMIN, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); WM_operator_properties_create(&op_ptr, "WM_OT_operator_preset_add"); RNA_string_set(&op_ptr, "operator", op->type->idname); RNA_boolean_set(&op_ptr, "remove_active", TRUE); - op_ptr = uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMOUT, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); + uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMOUT, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); } if (op->type->ui) { diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index ded5887f7f2..e7a5f993d32 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -216,7 +216,7 @@ static void eyedropper_color_set(bContext *C, Eyedropper *eye, const float col[3 /* set sample from accumulated values */ static void eyedropper_color_set_accum(bContext *C, Eyedropper *eye) { - float col[4]; + float col[3]; mul_v3_v3fl(col, eye->accum_col, 1.0f / (float)eye->accum_tot); eyedropper_color_set(C, eye, col); } @@ -807,8 +807,7 @@ static int editsource_text_edit(bContext *C, wmOperator *op, } if (text == NULL) { - BKE_reportf(op->reports, RPT_WARNING, - "file: '%s' can't be opened", filepath); + BKE_reportf(op->reports, RPT_WARNING, "File '%s' cannot be opened", filepath); return OPERATOR_CANCELLED; } else { @@ -820,8 +819,7 @@ static int editsource_text_edit(bContext *C, wmOperator *op, st->text = text; } else { - BKE_reportf(op->reports, RPT_INFO, - "See '%s' in the text editor", text->id.name + 2); + BKE_reportf(op->reports, RPT_INFO, "See '%s' in the text editor", text->id.name + 2); } txt_move_toline(text, line - 1, FALSE); @@ -857,8 +855,8 @@ static int editsource_exec(bContext *C, wmOperator *op) !BLI_ghashIterator_isDone(&ghi); BLI_ghashIterator_step(&ghi)) { - uiBut *but = BLI_ghashIterator_getKey(&ghi); - if (but && ui_editsource_uibut_match(&ui_editsource_info->but_orig, but)) { + uiBut *but_key = BLI_ghashIterator_getKey(&ghi); + if (but_key && ui_editsource_uibut_match(&ui_editsource_info->but_orig, but_key)) { but_store = BLI_ghashIterator_getValue(&ghi); break; } @@ -872,14 +870,12 @@ static int editsource_exec(bContext *C, wmOperator *op) but_store->py_dbg_ln); } else { - BKE_report(op->reports, RPT_ERROR, - "Active button isn't from a script, cant edit source."); + BKE_report(op->reports, RPT_ERROR, "Active button is not from a script, cannot edit source"); ret = OPERATOR_CANCELLED; } } else { - BKE_report(op->reports, RPT_ERROR, - "Active button match can't be found."); + BKE_report(op->reports, RPT_ERROR, "Active button match cannot be found"); ret = OPERATOR_CANCELLED; } @@ -915,20 +911,41 @@ static void UI_OT_editsource(wmOperatorType *ot) static void edittranslation_find_po_file(const char *root, const char *uilng, char *path, const size_t maxlen) { char tstr[32]; /* Should be more than enough! */ + /* First, full lang code. */ BLI_snprintf(tstr, sizeof(tstr), "%s.po", uilng); BLI_join_dirfile(path, maxlen, root, uilng); BLI_join_dirfile(path, maxlen, path, tstr); if (BLI_is_file(path)) return; + /* Now try without the second iso code part (_ES in es_ES). */ - strncpy(tstr, uilng, 2); - BLI_strncpy(tstr + 2, uilng + 5, sizeof(tstr) - 2); /* Because of some codes like sr_SR@latin... */ - BLI_join_dirfile(path, maxlen, root, tstr); - strcat(tstr, ".po"); - BLI_join_dirfile(path, maxlen, path, tstr); - if (BLI_is_file(path)) - return; + { + char *tc = NULL; + size_t szt = 0; + tstr[0] = '\0'; + + tc = strchr(uilng, '_'); + if (tc) { + szt = tc - uilng; + if (szt < sizeof(tstr)) /* Paranoid, should always be true! */ + BLI_strncpy(tstr, uilng, szt + 1); /* +1 for '\0' char! */ + } + if (tstr[0]) { + /* Because of some codes like sr_SR@latin... */ + tc = strchr(uilng, '@'); + if (tc) + BLI_strncpy(tstr + szt, tc, sizeof(tstr) - szt); + + BLI_join_dirfile(path, maxlen, root, tstr); + strcat(tstr, ".po"); + BLI_join_dirfile(path, maxlen, path, tstr); + if (BLI_is_file(path)) + return; + } + } + + /* Else no po file! */ path[0] = '\0'; } @@ -956,20 +973,20 @@ static int edittranslation_exec(bContext *C, wmOperator *op) uiStringInfo rna_ctxt = {BUT_GET_RNA_LABEL_CONTEXT, NULL}; if (!BLI_is_dir(root)) { - BKE_report(op->reports, RPT_ERROR, "Please set your User Preferences' \"Translation Branches " - "Directory\" path to a valid directory."); + BKE_report(op->reports, RPT_ERROR, "Please set your User Preferences' 'Translation Branches " + "Directory' path to a valid directory"); return OPERATOR_CANCELLED; } if (!WM_operatortype_find(EDTSRC_I18N_OP_NAME, 0)) { - BKE_reportf(op->reports, RPT_ERROR, "Could not find operator \"%s\"! Please enable ui_translate addon " - "in the User Preferences.", EDTSRC_I18N_OP_NAME); + BKE_reportf(op->reports, RPT_ERROR, "Could not find operator '%s'! Please enable ui_translate addon " + "in the User Preferences", EDTSRC_I18N_OP_NAME); return OPERATOR_CANCELLED; } /* Try to find a valid po file for current language... */ edittranslation_find_po_file(root, uilng, popath, FILE_MAX); - printf("po path: %s\n", popath); +/* printf("po path: %s\n", popath);*/ if (popath[0] == '\0') { - BKE_reportf(op->reports, RPT_ERROR, "No valid po found for language '%s' under %s.", uilng, root); + BKE_reportf(op->reports, RPT_ERROR, "No valid po found for language '%s' under %s", uilng, root); return OPERATOR_CANCELLED; } @@ -1021,14 +1038,6 @@ static int edittranslation_exec(bContext *C, wmOperator *op) } } -#if 0 -static int edittranslation_poll(bContext *UNUSED(C)) -{ - /* We need the i18n py addon to be enabled! */ - return WM_operatortype_find(EDTSRC_I18N_OP_NAME, 0) ? TRUE : FALSE; -} -#endif - static void UI_OT_edittranslation_init(wmOperatorType *ot) { /* identifiers */ @@ -1038,7 +1047,6 @@ static void UI_OT_edittranslation_init(wmOperatorType *ot) /* callbacks */ ot->exec = edittranslation_exec; -/* ot->poll = edittranslation_poll;*/ } #endif /* WITH_PYTHON */ diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index fa3e04d1351..2b170ea546b 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -240,7 +240,7 @@ Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, int } } } - } + } } } @@ -357,14 +357,14 @@ void UI_DrawTriIcon(float x, float y, char dir) } /* triangle 'icon' inside rect */ -static void ui_draw_tria_rect(rctf *rect, char dir) +static void ui_draw_tria_rect(const rctf *rect, char dir) { if (dir == 'h') { - float half = 0.5f * BLI_RCT_SIZE_Y(rect); + float half = 0.5f * BLI_rctf_size_y(rect); ui_draw_anti_tria(rect->xmin, rect->ymin, rect->xmin, rect->ymax, rect->xmax, rect->ymin + half); } else { - float half = 0.5f * BLI_RCT_SIZE_X(rect); + float half = 0.5f * BLI_rctf_size_x(rect); ui_draw_anti_tria(rect->xmin, rect->ymax, rect->xmax, rect->ymax, rect->xmin + half, rect->ymin); } } @@ -479,12 +479,12 @@ static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, rcti *r } } -static void rectf_scale(rctf *rect, float scale) +static void rectf_scale(rctf *rect, const float scale) { - float centx = 0.5f * (rect->xmin + rect->xmax); - float centy = 0.5f * (rect->ymin + rect->ymax); - float sizex = 0.5f * scale * BLI_RCT_SIZE_X(rect); - float sizey = 0.5f * scale * BLI_RCT_SIZE_Y(rect); + float centx = BLI_rctf_cent_x(rect); + float centy = BLI_rctf_cent_y(rect); + float sizex = BLI_rctf_size_x(rect) * 0.5f * scale; + float sizey = BLI_rctf_size_y(rect) * 0.5f * scale; rect->xmin = centx - sizex; rect->xmax = centx + sizex; @@ -545,9 +545,9 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect) if (!(panel->flag & PNL_CLOSEDX)) { ui_draw_aligned_panel_header(style, block, &headrect, 'h'); - /* itemrect smaller */ + /* itemrect smaller */ itemrect.xmax = headrect.xmax - 5.0f / block->aspect; - itemrect.xmin = itemrect.xmax - BLI_RCT_SIZE_Y(&headrect); + itemrect.xmin = itemrect.xmax - BLI_rcti_size_y(&headrect); itemrect.ymin = headrect.ymin; itemrect.ymax = headrect.ymax; @@ -594,9 +594,9 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect) /* draw collapse icon */ UI_ThemeColor(TH_TEXT); - /* itemrect smaller */ + /* itemrect smaller */ itemrect.xmin = headrect.xmin + 5.0f / block->aspect; - itemrect.xmax = itemrect.xmin + BLI_RCT_SIZE_Y(&headrect); + itemrect.xmax = itemrect.xmin + BLI_rcti_size_y(&headrect); itemrect.ymin = headrect.ymin; itemrect.ymax = headrect.ymax; @@ -814,8 +814,8 @@ static void ui_panels_size(ScrArea *sa, ARegion *ar, int *x, int *y) pa_sizey = pa->ofsy + get_panel_size_y(pa); } - sizex = MAX2(sizex, pa_sizex); - sizey = MIN2(sizey, pa_sizey); + sizex = max_ii(sizex, pa_sizex); + sizey = min_ii(sizey, pa_sizey); } } @@ -831,7 +831,7 @@ static void ui_do_animate(const bContext *C, Panel *panel) float fac; fac = (PIL_check_seconds_timer() - data->starttime) / ANIMATION_TIME; - fac = minf(sqrt(fac), 1.0f); + fac = min_ff(sqrt(fac), 1.0f); /* for max 1 second, interpolate positions */ if (uiAlignPanelStep(sa, ar, fac, 0)) { @@ -895,7 +895,7 @@ void uiEndPanels(const bContext *C, ARegion *ar, int *x, int *y) panew->paneltab = NULL; ED_region_tag_redraw(ar); /* the buttons panew were not made */ } - } + } } /* re-align, possibly with animation */ @@ -985,8 +985,8 @@ static void ui_do_drag(const bContext *C, wmEvent *event, Panel *panel) dx = (event->x - data->startx) & ~(PNL_GRID - 1); dy = (event->y - data->starty) & ~(PNL_GRID - 1); - dx *= (float)BLI_RCT_SIZE_X(&ar->v2d.cur) / (float)BLI_RCT_SIZE_X(&ar->winrct); - dy *= (float)BLI_RCT_SIZE_Y(&ar->v2d.cur) / (float)BLI_RCT_SIZE_Y(&ar->winrct); + dx *= (float)BLI_rctf_size_x(&ar->v2d.cur) / (float)BLI_rcti_size_x(&ar->winrct); + dy *= (float)BLI_rctf_size_y(&ar->v2d.cur) / (float)BLI_rcti_size_y(&ar->winrct); if (data->state == PANEL_STATE_DRAG_SCALE) { panel->sizex = MAX2(data->startsizex + dx, UI_PANEL_MINX); @@ -1200,7 +1200,7 @@ int ui_handler_panel_region(bContext *C, wmEvent *event) ED_region_tag_redraw(ar); retval = WM_UI_HANDLER_BREAK; - } + } } } #endif diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index dc9347b3852..28e361ccf5a 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -46,6 +46,7 @@ #include "BKE_context.h" #include "BKE_screen.h" +#include "BKE_global.h" #include "WM_api.h" #include "WM_types.h" @@ -70,7 +71,6 @@ #include "interface_intern.h" -#define MENU_SEPR_HEIGHT 6 #define B_NOP -1 #define MENU_SHADOW_SIDE 8 #define MENU_SHADOW_BOTTOM 10 @@ -153,7 +153,7 @@ static void menudata_free(MenuData *md) * if %xNN is given then NN is the return value if * that option is selected otherwise the return value * is the index of the option (starting with 1). %l - * indicates a seperator, sss%l indicates a label and + * indicates a separator, sss%l indicates a label and * new column. * * \param str String to be parsed. @@ -214,7 +214,7 @@ static MenuData *decompose_menu_string(const char *str) else { menudata_add_item(md, nitem, nretval, nicon, 0); nretval = md->nitems + 1; - } + } nitem = NULL; nicon = 0; @@ -393,7 +393,7 @@ static void ui_tooltip_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) /* draw text */ uiStyleFontSet(&data->fstyle); - bbox.ymax = bbox.ymax - 0.5f * (BLI_RCT_SIZE_Y(&bbox) - data->toth); + bbox.ymax = bbox.ymax - 0.5f * (BLI_rcti_size_y(&bbox) - data->toth); bbox.ymin = bbox.ymax - data->lineh; for (i = 0; i < data->totline; i++) { @@ -671,7 +671,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) for (a = 0, fontw = 0, fonth = 0; a < data->totline; a++) { w = BLF_width(data->fstyle.uifont_id, data->lines[a]); - fontw = MAX2(fontw, w); + fontw = max_ff(fontw, (float)w); fonth += (a == 0) ? h : h + TIP_MARGIN_Y; } @@ -732,9 +732,9 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) /* widget rect, in region coords */ data->bbox.xmin = MENU_SHADOW_SIDE; - data->bbox.xmax = BLI_RCT_SIZE_X(&rect_i) + MENU_SHADOW_SIDE; + data->bbox.xmax = BLI_rcti_size_x(&rect_i) + MENU_SHADOW_SIDE; data->bbox.ymin = MENU_SHADOW_BOTTOM; - data->bbox.ymax = BLI_RCT_SIZE_Y(&rect_i) + MENU_SHADOW_BOTTOM; + data->bbox.ymax = BLI_rcti_size_y(&rect_i) + MENU_SHADOW_BOTTOM; /* region bigger for shadow */ ar->winrct.xmin = rect_i.xmin - MENU_SHADOW_SIDE; @@ -867,8 +867,8 @@ static void ui_searchbox_butrect(rcti *rect, uiSearchboxData *data, int itemnr) { /* thumbnail preview */ if (data->preview) { - int butw = BLI_RCT_SIZE_X(&data->bbox) / data->prv_cols; - int buth = (BLI_RCT_SIZE_Y(&data->bbox) - 2 * MENU_TOP) / data->prv_rows; + int butw = BLI_rcti_size_x(&data->bbox) / data->prv_cols; + int buth = (BLI_rcti_size_y(&data->bbox) - 2 * MENU_TOP) / data->prv_rows; int row, col; *rect = data->bbox; @@ -884,7 +884,7 @@ static void ui_searchbox_butrect(rcti *rect, uiSearchboxData *data, int itemnr) } /* list view */ else { - int buth = (BLI_RCT_SIZE_Y(&data->bbox) - 2 * MENU_TOP) / SEARCH_ITEMS; + int buth = (BLI_rcti_size_y(&data->bbox) - 2 * MENU_TOP) / SEARCH_ITEMS; *rect = data->bbox; rect->xmin = data->bbox.xmin + 3.0f; @@ -1097,13 +1097,13 @@ static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) if (data->items.more) { ui_searchbox_butrect(&rect, data, data->items.maxitem - 1); glEnable(GL_BLEND); - UI_icon_draw((BLI_RCT_SIZE_X(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN); + UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymin - 9, ICON_TRIA_DOWN); glDisable(GL_BLEND); } if (data->items.offset) { ui_searchbox_butrect(&rect, data, 0); glEnable(GL_BLEND); - UI_icon_draw((BLI_RCT_SIZE_X(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP); + UI_icon_draw((BLI_rcti_size_x(&rect)) / 2, rect.ymax - 7, ICON_TRIA_UP); glDisable(GL_BLEND); } } @@ -1160,7 +1160,7 @@ 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_LOOP) + if (but->block->flag & UI_BLOCK_SEARCH_MENU) data->noback = 1; if (but->a1 > 0 && but->a2 > 0) { @@ -1170,7 +1170,7 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but) } /* compute position */ - if (but->block->flag & UI_BLOCK_LOOP) { + if (but->block->flag & UI_BLOCK_SEARCH_MENU) { /* this case is search menu inside other menu */ /* we copy region size */ @@ -1178,16 +1178,16 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but) /* widget rect, in region coords */ data->bbox.xmin = MENU_SHADOW_SIDE; - data->bbox.xmax = BLI_RCT_SIZE_X(&ar->winrct) - MENU_SHADOW_SIDE; + data->bbox.xmax = BLI_rcti_size_x(&ar->winrct) - MENU_SHADOW_SIDE; data->bbox.ymin = MENU_SHADOW_BOTTOM; - data->bbox.ymax = BLI_RCT_SIZE_Y(&ar->winrct) - MENU_SHADOW_BOTTOM; + data->bbox.ymax = BLI_rcti_size_y(&ar->winrct) - MENU_SHADOW_BOTTOM; /* check if button is lower half */ - if (but->rect.ymax < BLI_RCT_CENTER_Y(&but->block->rect)) { - data->bbox.ymin += BLI_RCT_SIZE_Y(&but->rect); + if (but->rect.ymax < BLI_rctf_cent_y(&but->block->rect)) { + data->bbox.ymin += BLI_rctf_size_y(&but->rect); } else { - data->bbox.ymax -= BLI_RCT_SIZE_Y(&but->rect); + data->bbox.ymax -= BLI_rctf_size_y(&but->rect); } } else { @@ -1202,7 +1202,7 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but) BLI_rctf_translate(&rect_fl, ofsx, ofsy); /* minimal width */ - if (BLI_RCT_SIZE_X(&rect_fl) < 150) { + if (BLI_rctf_size_x(&rect_fl) < 150) { rect_fl.xmax = rect_fl.xmin + 150; /* XXX arbitrary */ } @@ -1235,15 +1235,15 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but) UI_view2d_to_region_no_clip(&butregion->v2d, 0, but->rect.ymax + ofsy, NULL, &newy1); newy1 += butregion->winrct.ymin; - rect_i.ymax = BLI_RCT_SIZE_Y(&rect_i) + newy1; + rect_i.ymax = BLI_rcti_size_y(&rect_i) + newy1; rect_i.ymin = newy1; } /* widget rect, in region coords */ data->bbox.xmin = MENU_SHADOW_SIDE; - data->bbox.xmax = BLI_RCT_SIZE_X(&rect_i) + MENU_SHADOW_SIDE; + data->bbox.xmax = BLI_rcti_size_x(&rect_i) + MENU_SHADOW_SIDE; data->bbox.ymin = MENU_SHADOW_BOTTOM; - data->bbox.ymax = BLI_RCT_SIZE_Y(&rect_i) + MENU_SHADOW_BOTTOM; + data->bbox.ymax = BLI_rcti_size_y(&rect_i) + MENU_SHADOW_BOTTOM; /* region bigger for shadow */ ar->winrct.xmin = rect_i.xmin - MENU_SHADOW_SIDE; @@ -1342,6 +1342,14 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, ui_block_to_window_fl(butregion, but->block, &butrct.xmin, &butrct.ymin); ui_block_to_window_fl(butregion, but->block, &butrct.xmax, &butrct.ymax); + /* widget_roundbox_set has this correction too, keep in sync */ + if (but->type != PULLDOWN) { + if (but->flag & UI_BUT_ALIGN_TOP) + butrct.ymax += 1.0f; + if (but->flag & UI_BUT_ALIGN_LEFT) + butrct.xmin -= 1.0f; + } + /* calc block rect */ if (block->rect.xmin == 0.0f && block->rect.xmax == 0.0f) { if (block->buttons.first) { @@ -1358,15 +1366,15 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, } } - /* aspect = (float)(BLI_RCT_SIZE_X(&block->rect) + 4);*/ /*UNUSED*/ + /* aspect = (float)(BLI_rcti_size_x(&block->rect) + 4);*/ /*UNUSED*/ ui_block_to_window_fl(butregion, but->block, &block->rect.xmin, &block->rect.ymin); ui_block_to_window_fl(butregion, but->block, &block->rect.xmax, &block->rect.ymax); //block->rect.xmin -= 2.0; block->rect.ymin -= 2.0; //block->rect.xmax += 2.0; block->rect.ymax += 2.0; - xsize = BLI_RCT_SIZE_X(&block->rect) + 4; /* 4 for shadow */ - ysize = BLI_RCT_SIZE_Y(&block->rect) + 4; + xsize = BLI_rctf_size_x(&block->rect) + 4; /* 4 for shadow */ + ysize = BLI_rctf_size_y(&block->rect) + 4; /* aspect /= (float)xsize;*/ /*UNUSED*/ { @@ -1456,7 +1464,7 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, if (top == 0 && down == 0) { if (dir1 == UI_LEFT || dir1 == UI_RIGHT) { /* align with bottom of screen */ - // yof= ysize; (not with menu scrolls) + // yof = ysize; (not with menu scrolls) } } @@ -1468,9 +1476,6 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, } } - /* apply requested offset in the block */ - xof += block->xofs / block->aspect; - yof += block->yofs / block->aspect; #if 0 /* clamp to window bounds, could be made into an option if its ever annoying */ if ( (offscreen = (block->rect.ymin + yof)) < 0) yof -= offscreen; /* bottom */ @@ -1497,8 +1502,8 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, /* safety calculus */ { - const float midx = BLI_RCT_CENTER_X(&butrct); - const float midy = BLI_RCT_CENTER_Y(&butrct); + const float midx = BLI_rctf_cent_x(&butrct); + const float midy = BLI_rctf_cent_y(&butrct); /* when you are outside parent button, safety there should be smaller */ @@ -1544,7 +1549,11 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar) static void ui_popup_block_clip(wmWindow *window, uiBlock *block) { int winx, winy; - + + if (block->flag & UI_BLOCK_NO_WIN_CLIP) { + return; + } + wm_window_get_size(window, &winx, &winy); if (block->rect.xmin < MENU_SHADOW_SIDE) @@ -1561,8 +1570,6 @@ static void ui_popup_block_clip(wmWindow *window, uiBlock *block) void ui_popup_block_scrolltest(uiBlock *block) { uiBut *bt; - /* Knowing direction is necessary for multi-column menus... */ - int is_flip = (block->direction & UI_TOP) && !(block->flag & UI_BLOCK_NO_FLIP); block->flag &= ~(UI_BLOCK_CLIPBOTTOM | UI_BLOCK_CLIPTOP); @@ -1572,29 +1579,27 @@ void ui_popup_block_scrolltest(uiBlock *block) if (block->buttons.first == block->buttons.last) return; - /* mark buttons that are outside boundary and the ones next to it for arrow(s) */ + /* mark buttons that are outside boundary */ for (bt = block->buttons.first; bt; bt = bt->next) { if (bt->rect.ymin < block->rect.ymin) { bt->flag |= UI_SCROLLED; block->flag |= UI_BLOCK_CLIPBOTTOM; - /* make space for arrow */ - if (bt->rect.ymax < block->rect.ymin + 10) { - if (is_flip && bt->next && bt->next->rect.ymin > bt->rect.ymin) - bt->next->flag |= UI_SCROLLED; - else if (!is_flip && bt->prev && bt->prev->rect.ymin > bt->rect.ymin) - bt->prev->flag |= UI_SCROLLED; - } } if (bt->rect.ymax > block->rect.ymax) { bt->flag |= UI_SCROLLED; block->flag |= UI_BLOCK_CLIPTOP; - /* make space for arrow */ - if (bt->rect.ymin > block->rect.ymax - 10) { - if (!is_flip && bt->next && bt->next->rect.ymax < bt->rect.ymax) - bt->next->flag |= UI_SCROLLED; - else if (is_flip && bt->prev && bt->prev->rect.ymax < bt->rect.ymax) - bt->prev->flag |= UI_SCROLLED; - } + } + } + + /* mark buttons overlapping arrows, if we have them */ + for (bt = block->buttons.first; bt; bt = bt->next) { + if (block->flag & UI_BLOCK_CLIPBOTTOM) { + if (bt->rect.ymin < block->rect.ymin + UI_MENU_SCROLL_ARROW) + bt->flag |= UI_SCROLLED; + } + if (block->flag & UI_BLOCK_CLIPTOP) { + if (bt->rect.ymax > block->rect.ymax - UI_MENU_SCROLL_ARROW) + bt->flag |= UI_SCROLLED; } } } @@ -1660,12 +1665,10 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut /* if this is being created from a button */ if (but) { - if (ELEM(but->type, BLOCK, PULLDOWN)) - block->xofs = -2; /* for proper alignment */ - block->aspect = but->block->aspect; ui_block_position(window, butregion, but, block); + handle->direction = block->direction; } else { /* keep a list of these, needed for pulldown menus */ @@ -1874,12 +1877,6 @@ static void ui_warp_pointer(int x, int y) /********************* Color Button ****************/ -/* picker sizes S hsize, F full size, D spacer, B button/pallette height */ -#define SPICK 110.0 -#define FPICK 180.0 -#define DPICK 6.0 -#define BPICK 24.0 - /* for picker, while editing hsv */ void ui_set_but_hsv(uiBut *but) { @@ -1954,7 +1951,7 @@ static void ui_update_block_buts_rgb(uiBlock *block, const float rgb[3]) else if (bt->str[0] == 'V') { ui_set_but_val(bt, hsv[2]); } - } + } ui_check_but(bt); } @@ -2053,10 +2050,6 @@ static void do_picker_new_mode_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(a picker_new_hide_reveal(bt->block, colormode); } -/* picker sizes S hsize, F full size, D spacer, B button/pallette height */ -#define SPICK1 150.0 -#define DPICK1 6.0 - #define PICKER_H 150 #define PICKER_W 150 #define PICKER_SPACE 6 @@ -2094,7 +2087,7 @@ static void square_picker(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, in /* a HS circle, V slider, rgb/hsv/hex sliders */ -static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, PropertyRNA *prop) +static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, PropertyRNA *prop, int show_picker) { static short colormode = 0; /* temp? 0=rgb, 1=hsv, 2=hex */ uiBut *bt; @@ -2155,8 +2148,10 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper uiButSetFunc(bt, do_picker_new_mode_cb, bt, NULL); uiBlockEndAlign(block); - bt = uiDefIconButO(block, BUT, "UI_OT_eyedropper", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER, butwidth + 10, -60, UI_UNIT_X, UI_UNIT_Y, NULL); - uiButSetFunc(bt, close_popup_cb, bt, NULL); + if (show_picker) { + bt = uiDefIconButO(block, BUT, "UI_OT_eyedropper", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER, butwidth + 10, -60, UI_UNIT_X, UI_UNIT_Y, NULL); + uiButSetFunc(bt, close_popup_cb, bt, NULL); + } /* RGB values */ uiBlockBeginAlign(block); @@ -2241,6 +2236,7 @@ uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_ { uiBut *but = arg_but; uiBlock *block; + int show_picker = TRUE; block = uiBeginBlock(C, handle->region, __func__, UI_EMBOSS); @@ -2249,12 +2245,20 @@ uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_ block->color_profile = FALSE; } } + + if (but->block) { + /* if color block is invoked from a popup we wouldn't be able to set color properly + * this is because color picker will close popups first and then will try to figure + * out active button RNA, and of course it'll fail + */ + show_picker = (but->block->flag & UI_BLOCK_POPUP) == 0; + } uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT); copy_v3_v3(handle->retvec, but->editvec); - uiBlockPicker(block, handle->retvec, &but->rnapoin, but->rnaprop); + uiBlockPicker(block, handle->retvec, &but->rnapoin, but->rnaprop, show_picker); block->flag = UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_KEEP_OPEN | UI_BLOCK_OUT_1; uiBoundsBlock(block, 10); @@ -2343,7 +2347,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi if (pup->but) { /* minimum width to enforece */ - minwidth = BLI_RCT_SIZE_X(&pup->but->rect); + minwidth = BLI_rctf_size_x(&pup->but->rect); if (pup->but->type == PULLDOWN || pup->but->menu_create_func) { direction = UI_DOWN; @@ -2374,7 +2378,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT); if (pup->popup) { - uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_NUMSELECT | UI_BLOCK_RET_1); + uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_NUMSELECT); uiBlockSetDirection(block, direction); /* offset the mouse position, possibly based on earlier selection */ @@ -2385,7 +2389,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi * button, so it doesn't overlap the text too much, also note * the offset is negative because we are inverse moving the * block to be under the mouse */ - offset[0] = -(bt->rect.xmin + 0.8f * BLI_RCT_SIZE_X(&bt->rect)); + offset[0] = -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect)); offset[1] = -(bt->rect.ymin + 0.5f * UI_UNIT_Y); } else { @@ -2393,7 +2397,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi * on the first item */ offset[0] = 0; for (bt = block->buttons.first; bt; bt = bt->next) - offset[0] = mini(offset[0], -(bt->rect.xmin + 0.8f * BLI_RCT_SIZE_X(&bt->rect))); + offset[0] = min_ii(offset[0], -(bt->rect.xmin + 0.8f * BLI_rctf_size_x(&bt->rect))); offset[1] = 1.5 * UI_UNIT_Y; } @@ -2502,8 +2506,10 @@ uiPopupMenu *uiPupMenuBegin(bContext *C, const char *title, int icon) pup->block = uiBeginBlock(C, NULL, __func__, UI_EMBOSSP); pup->block->flag |= UI_BLOCK_POPUP_MEMORY; pup->block->puphash = ui_popup_menu_hash(title); - pup->block->auto_is_first_event = TRUE; pup->layout = uiBlockLayout(pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, style); + + /* note, this intentionally differs from the menu & submenu default because many operators + * use popups like this to select one of their options - where having invoke doesn't make sense */ uiLayoutSetOperatorContext(pup->layout, WM_OP_EXEC_REGION_WIN); /* create in advance so we can let buttons point to retval already */ @@ -2575,6 +2581,11 @@ static void confirm_cancel_operator(void *opv) WM_operator_free(opv); } +static void vconfirm_opname(bContext *C, const char *opname, const char *title, const char *itemfmt, va_list ap) +#ifdef __GNUC__ +__attribute__ ((format(printf, 4, 0))) +#endif +; static void vconfirm_opname(bContext *C, const char *opname, const char *title, const char *itemfmt, va_list ap) { uiPopupBlockHandle *handle; @@ -2667,14 +2678,18 @@ void uiPupMenuReports(bContext *C, ReportList *reports) ds = BLI_dynstr_new(); for (report = reports->list.first; report; report = report->next) { - if (report->type < reports->printlevel) - ; /* pass */ - else if (report->type >= RPT_ERROR) + if (report->type < reports->printlevel) { + /* pass */ + } + else if (report->type >= RPT_ERROR) { BLI_dynstr_appendf(ds, "Error %%i%d%%t|%s", ICON_ERROR, report->message); - else if (report->type >= RPT_WARNING) + } + else if (report->type >= RPT_WARNING) { BLI_dynstr_appendf(ds, "Warning %%i%d%%t|%s", ICON_ERROR, report->message); - else if (report->type >= RPT_INFO) + } + else if (report->type >= RPT_INFO) { BLI_dynstr_appendf(ds, "Info %%i%d%%t|%s", ICON_INFO, report->message); + } } str = BLI_dynstr_get_cstring(ds); @@ -2706,6 +2721,10 @@ void uiPupMenuInvoke(bContext *C, const char *idname) menu.layout = layout; menu.type = mt; + if (G.debug & G_DEBUG_WM) { + printf("%s: opening menu \"%s\"\n", __func__, idname); + } + mt->draw(C, &menu); uiPupMenuEnd(C, pup); diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c index b16250021d3..7e7db6aeaaa 100644 --- a/source/blender/editors/interface/interface_style.c +++ b/source/blender/editors/interface/interface_style.c @@ -152,17 +152,17 @@ void uiStyleFontDrawExt(uiFontStyle *fs, rcti *rect, const char *str, uiStyleFontSet(fs); height = BLF_ascender(fs->uifont_id); - yofs = ceil(0.5f * (BLI_RCT_SIZE_Y(rect) - height)); + yofs = ceil(0.5f * (BLI_rcti_size_y(rect) - height)); if (fs->align == UI_STYLE_TEXT_CENTER) { - xofs = floor(0.5f * (BLI_RCT_SIZE_X(rect) - BLF_width(fs->uifont_id, str))); + xofs = floor(0.5f * (BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str))); /* don't center text if it chops off the start of the text, 2 gives some margin */ if (xofs < 2) { xofs = 2; } } else if (fs->align == UI_STYLE_TEXT_RIGHT) { - xofs = BLI_RCT_SIZE_X(rect) - BLF_width(fs->uifont_id, str) - 1; + xofs = BLI_rcti_size_x(rect) - BLF_width(fs->uifont_id, str) - 1; } /* clip is very strict, so we give it some space */ @@ -209,7 +209,7 @@ void uiStyleFontDrawRotated(uiFontStyle *fs, rcti *rect, const char *str) height = BLF_ascender(fs->uifont_id); /* becomes x-offset when rotated */ - xofs = ceil(0.5f * (BLI_RCT_SIZE_Y(rect) - height)); + xofs = ceil(0.5f * (BLI_rcti_size_y(rect) - height)); /* ignore UI_STYLE, always aligned to top */ @@ -219,8 +219,8 @@ void uiStyleFontDrawRotated(uiFontStyle *fs, rcti *rect, const char *str) angle = 90.0f; /* translate rect to vertical */ - txtrect.xmin = rect->xmin - BLI_RCT_SIZE_Y(rect); - txtrect.ymin = rect->ymin - BLI_RCT_SIZE_X(rect); + txtrect.xmin = rect->xmin - BLI_rcti_size_y(rect); + txtrect.ymin = rect->ymin - BLI_rcti_size_x(rect); txtrect.xmax = rect->xmin; txtrect.ymax = rect->ymin; @@ -348,7 +348,7 @@ void uiStyleInit(void) #else font->blf_id = BLF_load_mem("default", (unsigned char *)datatoc_bfont_ttf, datatoc_bfont_ttf_size); #endif - } + } else { font->blf_id = BLF_load(font->filename); if (font->blf_id == -1) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 79b9d313775..24aca0c037d 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -35,6 +35,7 @@ #include "DNA_dynamicpaint_types.h" #include "DNA_key_types.h" #include "DNA_scene_types.h" +#include "DNA_object_types.h" #include "DNA_userdef_types.h" #include "BLI_utildefines.h" @@ -56,6 +57,7 @@ #include "BKE_texture.h" #include "BKE_report.h" #include "BKE_displist.h" +#include "BKE_sca.h" #include "BKE_scene.h" #include "ED_screen.h" @@ -173,7 +175,7 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem) idptr = RNA_property_pointer_get(&template.ptr, template.prop); block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS); - uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_RET_1); + uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_SEARCH_MENU); /* preview thumbnails */ if (template.prv_rows > 0 && template.prv_cols > 0) { @@ -197,7 +199,7 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem) uiBoundsBlock(block, 6); - uiBlockSetDirection(block, UI_DOWN); + uiBlockSetDirection(block, UI_DOWN); uiEndBlock(C, block); /* give search-field focus */ @@ -360,6 +362,7 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str type = idptr.type; if (flag & UI_ID_PREVIEWS) { + 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))); @@ -372,7 +375,6 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str uiButSetFlag(but, UI_BUT_DISABLED); uiLayoutRow(layout, TRUE); - template->preview = 1; } else if (flag & UI_ID_BROWSE) { but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y, @@ -398,7 +400,7 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str //text_idbutton(id, name); name[0] = '\0'; - but = uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, NULL); + but = uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type)); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME)); if (user_alert) uiButSetFlag(but, UI_BUT_REDALERT); @@ -427,8 +429,15 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str TIP_("Display number of users of this data (click to make a single-user copy)")); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE)); - if (!id_copy(id, NULL, 1 /* test only */) || (idfrom && idfrom->lib) || !editable) + if (/* test only */ + (id_copy(id, NULL, 1) == FALSE) || + (idfrom && idfrom->lib) || + (editable == FALSE) || + /* object in editmode - don't change data */ + (idfrom && GS(idfrom->name) == ID_OB && (((Object *)idfrom)->mode & OB_MODE_EDIT))) + { uiButSetFlag(but, UI_BUT_DISABLED); + } } if (user_alert) uiButSetFlag(but, UI_BUT_REDALERT); @@ -571,7 +580,7 @@ void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, co RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); return; } - if (!propType || RNA_property_type(propType) != PROP_ENUM) { + if (!propType || RNA_property_type(propType) != PROP_ENUM) { RNA_warning("pointer-type property not found: %s.%s", RNA_struct_identifier(ptr->type), proptypename); return; } @@ -929,28 +938,26 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr) #include "BKE_action.h" #include "BKE_constraint.h" -#define REDRAWIPO 1 -#define REDRAWNLA 2 -#define REDRAWBUTSOBJECT 3 -#define REDRAWACTION 4 #define B_CONSTRAINT_TEST 5 -#define B_CONSTRAINT_CHANGETARGET 6 -#define REMAKEIPO 8 -#define B_DIFF 9 +// #define B_CONSTRAINT_CHANGETARGET 6 static void do_constraint_panels(bContext *C, void *ob_pt, int event) { - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); Object *ob = (Object *)ob_pt; switch (event) { case B_CONSTRAINT_TEST: break; /* no handling */ +#if 0 /* UNUSED */ case B_CONSTRAINT_CHANGETARGET: + { + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); if (ob->pose) ob->pose->flag |= POSE_RECALC; /* checks & sorts pose channels */ DAG_scene_sort(bmain, scene); break; + } +#endif default: break; } @@ -1214,7 +1221,7 @@ void uiTemplatePreview(uiLayout *layout, ID *id, int show_buttons, ID *parent, M else ma = (Material *)pparent; /* Create RNA Pointer */ - RNA_pointer_create(id, &RNA_Material, ma, &material_ptr); + RNA_pointer_create(&ma->id, &RNA_Material, ma, &material_ptr); col = uiLayoutColumn(row, TRUE); uiLayoutSetScaleX(col, 1.5); @@ -1262,8 +1269,6 @@ static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg)) RNA_property_update(C, &cb->ptr, cb->prop); } -#define B_BANDCOL 1 - static void colorband_add_cb(bContext *C, void *cb_v, void *coba_v) { ColorBand *coba = coba_v; @@ -1276,7 +1281,7 @@ static void colorband_add_cb(bContext *C, void *cb_v, void *coba_v) if (colorband_element_add(coba, pos)) { rna_update_cb(C, cb_v, NULL); - ED_undo_push(C, "Add colorband"); + ED_undo_push(C, "Add colorband"); } } @@ -1379,7 +1384,7 @@ static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, RNAUpdateCb *cb) { uiBut *bt; - float unit = BLI_RCT_SIZE_X(butr) / 14.0f; + float unit = BLI_rctf_size_x(butr) / 14.0f; float xs = butr->xmin; uiBlockBeginAlign(block); @@ -1400,12 +1405,12 @@ static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand uiItemR(layout, &ptr, "color", 0, "", ICON_NONE); } - bt = uiDefButS(block, MENU, 0, TIP_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"), + bt = uiDefButS(block, MENU, 0, IFACE_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"), xs + 10.0f * unit, butr->ymin + UI_UNIT_Y, unit * 4, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, TIP_("Set interpolation between color stops")); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); - bt = uiDefBut(block, BUT_COLORBAND, 0, "", xs, butr->ymin, BLI_RCT_SIZE_X(butr), UI_UNIT_Y, coba, 0, 0, 0, 0, ""); + bt = uiDefBut(block, BUT_COLORBAND, 0, "", xs, butr->ymin, BLI_rctf_size_x(butr), UI_UNIT_Y, coba, 0, 0, 0, 0, ""); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); uiBlockEndAlign(block); @@ -1480,7 +1485,7 @@ void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname hist->height = (hist->height <= UI_UNIT_Y) ? UI_UNIT_Y : hist->height; - bt = uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, BLI_RCT_SIZE_X(&rect), hist->height, hist, 0, 0, 0, 0, ""); + bt = uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), hist->height, hist, 0, 0, 0, 0, ""); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); MEM_freeN(cb); @@ -1517,7 +1522,7 @@ void uiTemplateWaveform(uiLayout *layout, PointerRNA *ptr, const char *propname) scopes->wavefrm_height = (scopes->wavefrm_height <= UI_UNIT_Y) ? UI_UNIT_Y : scopes->wavefrm_height; - bt = uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, BLI_RCT_SIZE_X(&rect), scopes->wavefrm_height, scopes, 0, 0, 0, 0, ""); + bt = uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), scopes->wavefrm_height, scopes, 0, 0, 0, 0, ""); (void)bt; /* UNUSED */ MEM_freeN(cb); @@ -1554,7 +1559,7 @@ void uiTemplateVectorscope(uiLayout *layout, PointerRNA *ptr, const char *propna scopes->vecscope_height = (scopes->vecscope_height <= UI_UNIT_Y) ? UI_UNIT_Y : scopes->vecscope_height; - bt = uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, BLI_RCT_SIZE_X(&rect), scopes->vecscope_height, scopes, 0, 0, 0, 0, ""); + bt = uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), scopes->vecscope_height, scopes, 0, 0, 0, 0, ""); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); MEM_freeN(cb); @@ -1569,11 +1574,11 @@ static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *UNUSED(ar float d; /* we allow 20 times zoom */ - if (BLI_RCT_SIZE_X(&cumap->curr) > 0.04f * BLI_RCT_SIZE_X(&cumap->clipr)) { - d = 0.1154f * BLI_RCT_SIZE_X(&cumap->curr); + if (BLI_rctf_size_x(&cumap->curr) > 0.04f * BLI_rctf_size_x(&cumap->clipr)) { + d = 0.1154f * BLI_rctf_size_x(&cumap->curr); cumap->curr.xmin += d; cumap->curr.xmax -= d; - d = 0.1154f * BLI_RCT_SIZE_Y(&cumap->curr); + d = 0.1154f * BLI_rctf_size_y(&cumap->curr); cumap->curr.ymin += d; cumap->curr.ymax -= d; } @@ -1587,8 +1592,8 @@ static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *UNUSED(u float d, d1; /* we allow 20 times zoom, but don't view outside clip */ - if (BLI_RCT_SIZE_X(&cumap->curr) < 20.0f * BLI_RCT_SIZE_X(&cumap->clipr)) { - d = d1 = 0.15f * BLI_RCT_SIZE_X(&cumap->curr); + if (BLI_rctf_size_x(&cumap->curr) < 20.0f * BLI_rctf_size_x(&cumap->clipr)) { + d = d1 = 0.15f * BLI_rctf_size_x(&cumap->curr); if (cumap->flag & CUMA_DO_CLIP) if (cumap->curr.xmin - d < cumap->clipr.xmin) @@ -1601,7 +1606,7 @@ static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *UNUSED(u d1 = -cumap->curr.xmax + cumap->clipr.xmax; cumap->curr.xmax += d1; - d = d1 = 0.15f * BLI_RCT_SIZE_Y(&cumap->curr); + d = d1 = 0.15f * BLI_rctf_size_y(&cumap->curr); if (cumap->flag & CUMA_DO_CLIP) if (cumap->curr.ymin - d < cumap->clipr.ymin) @@ -1744,11 +1749,11 @@ static void curvemap_buttons_redraw(bContext *C, void *UNUSED(arg1), void *UNUSE ED_region_tag_redraw(CTX_wm_region(C)); } -static void curvemap_buttons_update(bContext *UNUSED(C), void *UNUSED(arg1), void *cumap_v) +static void curvemap_buttons_update(bContext *C, void *arg1_v, void *cumap_v) { CurveMapping *cumap = cumap_v; - curvemapping_changed(cumap, TRUE); + rna_update_cb(C, arg1_v, NULL); } static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v) @@ -1869,7 +1874,7 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); - if (cumap->flag & CUMA_DO_CLIP) icon = ICON_CLIPUV_HLT; else icon = ICON_CLIPUV_DEHLT; + icon = (cumap->flag & CUMA_DO_CLIP) ? ICON_CLIPUV_HLT : ICON_CLIPUV_DEHLT; bt = uiDefIconBlockBut(block, curvemap_clipping_func, cumap, 0, icon, 0, 0, dx, dx, TIP_("Clipping Options")); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); @@ -1895,9 +1900,9 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe if (cmp) { uiLayoutRow(layout, TRUE); - uiBlockSetNFunc(block, curvemap_buttons_update, NULL, cumap); - uiDefButF(block, NUM, 0, "X", 0, 2 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, &cmp->x, 0.0f, 1.0f, 1, 5, ""); - uiDefButF(block, NUM, 0, "Y", 0, 1 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, &cmp->y, 0.0f, 1.0f, 1, 5, ""); + uiBlockSetNFunc(block, curvemap_buttons_update, MEM_dupallocN(cb), cumap); + bt = uiDefButF(block, NUM, 0, "X", 0, 2 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, &cmp->x, 0.0f, 1.0f, 1, 5, ""); + bt = uiDefButF(block, NUM, 0, "Y", 0, 1 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, &cmp->y, 0.0f, 1.0f, 1, 5, ""); } /* black/white levels */ @@ -2085,6 +2090,74 @@ void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, const char *propname, } } +void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propname, + PointerRNA *used_ptr, const char *used_propname, int active_state) +{ + uiLayout *uRow, *uCol; + PropertyRNA *prop, *used_prop = NULL; + int groups, cols, states; + int group, col, state, row; + int cols_per_group = 5; + Object *ob = (Object *)ptr->id.data; + + prop = RNA_struct_find_property(ptr, propname); + if (!prop) { + RNA_warning("states property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); + return; + } + + /* the number of states determines the way we group them + * - we want 2 rows only (for now) + * - the number of columns (cols) is the total number of buttons per row + * the 'remainder' is added to this, as it will be ok to have first row slightly wider if need be + * - for now, only split into groups if group will have at least 5 items + */ + states = RNA_property_array_length(ptr, prop); + cols = (states / 2) + (states % 2); + groups = ((cols / 2) < cols_per_group) ? (1) : (cols / cols_per_group); + + if (used_ptr && used_propname) { + used_prop = RNA_struct_find_property(used_ptr, used_propname); + if (!used_prop) { + RNA_warning("used layers property not found: %s.%s", RNA_struct_identifier(ptr->type), used_propname); + return; + } + + if (RNA_property_array_length(used_ptr, used_prop) < states) + used_prop = NULL; + } + + /* layers are laid out going across rows, with the columns being divided into groups */ + + for (group = 0; group < groups; group++) { + uCol = uiLayoutColumn(layout, TRUE); + + for (row = 0; row < 2; row++) { + uiBlock *block; + uiBut *but; + + uRow = uiLayoutRow(uCol, TRUE); + block = uiLayoutGetBlock(uRow); + state = groups * cols_per_group * row + cols_per_group * group; + + /* add layers as toggle buts */ + for (col = 0; (col < cols_per_group) && (state < states); col++, state++) { + int icon = 0; + int butlay = 1 << state; + + if (active_state & butlay) + icon = ICON_LAYER_ACTIVE; + else if (used_prop && RNA_property_boolean_get_index(used_ptr, used_prop, state)) + icon = ICON_LAYER_USED; + + but = uiDefIconButR_prop(block, ICONTOG, 0, icon, 0, 0, UI_UNIT_X / 2, UI_UNIT_Y / 2, ptr, prop, state, 0, 0, -1, -1, sca_state_name_get(ob, state)); + uiButSetFunc(but, handle_layer_buttons, but, SET_INT_IN_POINTER(state)); + but->type = TOG; + } + } + } +} + /************************* List Template **************************/ @@ -2671,7 +2744,7 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C) uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_CANCEL, IFACE_("Capture"), 0, 0, 85, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop screencast")); if (screen->animtimer) - uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_CANCEL, TIP_("Anim Player"), 0, 0, 100, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, + uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_CANCEL, IFACE_("Anim Player"), 0, 0, 100, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop animation playback")); } @@ -2701,8 +2774,8 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) block = uiLayoutGetBlock(ui_abs); width = BLF_width(style->widget.uifont_id, report->message); - width = MIN2(rti->widthfac * width, width); - width = MAX2(width, 10); + width = min_ii((int)(rti->widthfac * width), width); + width = max_ii(width, 10); /* make a box around the report to make it stand out */ uiBlockBeginAlign(block); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 8a7f2d9ca47..f41abce947e 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -259,8 +259,8 @@ static int round_box_shadow_edges(float (*vert)[2], rcti *rect, float rad, int r rad += step; - if (2.0f * rad > BLI_RCT_SIZE_Y(rect)) - rad = 0.5f * BLI_RCT_SIZE_Y(rect); + if (2.0f * rad > BLI_rcti_size_y(rect)) + rad = 0.5f * BLI_rcti_size_y(rect); minx = rect->xmin - step; miny = rect->ymin - step; @@ -345,8 +345,8 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, rcti *rect, fl const int vnum = ((roundboxalign & (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)) == (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT) || (roundboxalign & (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) == (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) ? 1 : 2; - minsize = mini(BLI_RCT_SIZE_X(rect) * hnum, - BLI_RCT_SIZE_Y(rect) * vnum); + minsize = min_ii(BLI_rcti_size_x(rect) * hnum, + BLI_rcti_size_y(rect) * vnum); if (2.0f * rad > minsize) rad = 0.5f * minsize; @@ -491,7 +491,7 @@ static void widget_num_tria(uiWidgetTrias *tria, rcti *rect, float triasize, cha float centx, centy, sizex, sizey, minsize; int a, i1 = 0, i2 = 1; - minsize = mini(BLI_RCT_SIZE_X(rect), BLI_RCT_SIZE_Y(rect)); + minsize = min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)); /* center position and size */ centx = (float)rect->xmin + 0.5f * minsize; @@ -501,16 +501,16 @@ static void widget_num_tria(uiWidgetTrias *tria, rcti *rect, float triasize, cha if (where == 'r') { centx = (float)rect->xmax - 0.5f * minsize; sizex = -sizex; - } + } else if (where == 't') { centy = (float)rect->ymax - 0.5f * minsize; sizey = -sizey; i2 = 0; i1 = 1; - } + } else if (where == 'b') { sizex = -sizex; i2 = 0; i1 = 1; - } + } for (a = 0; a < 3; a++) { tria->vec[a][0] = sizex * num_tria_vert[a][i1] + centx; @@ -526,7 +526,7 @@ static void widget_scroll_circle(uiWidgetTrias *tria, rcti *rect, float triasize float centx, centy, sizex, sizey, minsize; int a, i1 = 0, i2 = 1; - minsize = mini(BLI_RCT_SIZE_X(rect), BLI_RCT_SIZE_Y(rect)); + minsize = min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)); /* center position and size */ centx = (float)rect->xmin + 0.5f * minsize; @@ -536,16 +536,16 @@ static void widget_scroll_circle(uiWidgetTrias *tria, rcti *rect, float triasize if (where == 'r') { centx = (float)rect->xmax - 0.5f * minsize; sizex = -sizex; - } + } else if (where == 't') { centy = (float)rect->ymax - 0.5f * minsize; sizey = -sizey; i2 = 0; i1 = 1; - } + } else if (where == 'b') { sizex = -sizex; i2 = 0; i1 = 1; - } + } for (a = 0; a < 16; a++) { tria->vec[a][0] = sizex * scroll_circle_vert[a][i1] + centx; @@ -570,14 +570,14 @@ static void widget_menu_trias(uiWidgetTrias *tria, rcti *rect) int a; /* center position and size */ - centx = rect->xmax - 0.5f * BLI_RCT_SIZE_Y(rect); - centy = rect->ymin + 0.5f * BLI_RCT_SIZE_Y(rect); - size = 0.4f * BLI_RCT_SIZE_Y(rect); + centx = rect->xmax - 0.5f * BLI_rcti_size_y(rect); + centy = rect->ymin + 0.5f * BLI_rcti_size_y(rect); + size = 0.4f * (float)BLI_rcti_size_y(rect); /* XXX exception */ - asp = ((float)BLI_RCT_SIZE_X(rect)) / ((float)BLI_RCT_SIZE_Y(rect)); + asp = ((float)BLI_rcti_size_x(rect)) / ((float)BLI_rcti_size_y(rect)); if (asp > 1.2f && asp < 2.6f) - centx = rect->xmax - 0.3f * BLI_RCT_SIZE_Y(rect); + centx = rect->xmax - 0.4f * (float)BLI_rcti_size_y(rect); for (a = 0; a < 6; a++) { tria->vec[a][0] = size * menu_tria_vert[a][0] + centx; @@ -594,9 +594,9 @@ static void widget_check_trias(uiWidgetTrias *tria, rcti *rect) int a; /* center position and size */ - centx = rect->xmin + 0.5f * BLI_RCT_SIZE_Y(rect); - centy = rect->ymin + 0.5f * BLI_RCT_SIZE_Y(rect); - size = 0.5f * BLI_RCT_SIZE_Y(rect); + centx = rect->xmin + 0.5f * BLI_rcti_size_y(rect); + centy = rect->ymin + 0.5f * BLI_rcti_size_y(rect); + size = 0.5f * BLI_rcti_size_y(rect); for (a = 0; a < 6; a++) { tria->vec[a][0] = size * check_tria_vert[a][0] + centx; @@ -840,8 +840,8 @@ static void widget_draw_preview(BIFIconID icon, float UNUSED(alpha), rcti *rect) if (icon == ICON_NONE) return; - w = BLI_RCT_SIZE_X(rect); - h = BLI_RCT_SIZE_Y(rect); + w = BLI_rcti_size_x(rect); + h = BLI_rcti_size_y(rect); size = MIN2(w, h); size -= PREVIEW_PAD * 2; /* padding */ @@ -878,7 +878,7 @@ static void widget_draw_icon(uiBut *but, BIFIconID icon, float alpha, rcti *rect aspect = but->block->aspect; if (aspect != but->aspect) { /* prevent scaling up icon in pupmenu */ - if (aspect < 1.0f) { + if (aspect < 1.0f) { height = UI_DPI_ICON_SIZE; aspect = 1.0f; @@ -891,8 +891,8 @@ static void widget_draw_icon(uiBut *but, BIFIconID icon, float alpha, rcti *rect /* calculate blend color */ if (ELEM4(but->type, TOG, ROW, TOGN, LISTROW)) { - if (but->flag & UI_SELECT) ; - else if (but->flag & UI_ACTIVE) ; + if (but->flag & UI_SELECT) {} + else if (but->flag & UI_ACTIVE) {} else alpha = 0.5f; } @@ -965,76 +965,110 @@ static void ui_text_clip_give_next_off(uiBut *but) but->ofs += bytes; } -/* sets but->ofs to make sure text is correctly visible */ -static void ui_text_leftclip(uiFontStyle *fstyle, uiBut *but, rcti *rect) +/** + * Cut off the start of the text to fit into the width of \a rect + * + * \note Sets but->ofs to make sure text is correctly visible. + * \note Clips right in some cases, this function could be cleaned up. + */ +static void ui_text_clip_left(uiFontStyle *fstyle, uiBut *but, rcti *rect) { int border = (but->flag & UI_BUT_ALIGN_RIGHT) ? 8 : 10; - int okwidth = BLI_RCT_SIZE_X(rect) - border; - + int okwidth = BLI_rcti_size_x(rect) - border; if (but->flag & UI_HAS_ICON) okwidth -= UI_DPI_ICON_SIZE; - + /* need to set this first */ uiStyleFontSet(fstyle); if (fstyle->kerning == 1) /* for BLF_width */ BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT); - /* if text editing we define ofs dynamically */ - if (but->editstr && but->pos >= 0) { - if (but->ofs > but->pos) - but->ofs = but->pos; + but->ofs = 0; + but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr); - if (BLF_width(fstyle->uifont_id, but->drawstr) <= okwidth) - but->ofs = 0; - } - else but->ofs = 0; - - but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs); - while (but->strwidth > okwidth) { - - /* textbut exception, clip right when... */ - if (but->editstr && but->pos >= 0) { - float width; - char buf[UI_MAX_DRAW_STR]; - - /* copy draw string */ - BLI_strncpy_utf8(buf, but->drawstr, sizeof(buf)); - /* string position of cursor */ - buf[but->pos] = 0; - width = BLF_width(fstyle->uifont_id, buf + but->ofs); - - /* if cursor is at 20 pixels of right side button we clip left */ - if (width > okwidth - 20) - ui_text_clip_give_next_off(but); - else { - int len, bytes; - /* shift string to the left */ - if (width < 20 && but->ofs > 0) - ui_text_clip_give_prev_off(but); - len = strlen(but->drawstr); - bytes = BLI_str_utf8_size(BLI_str_find_prev_char_utf8(but->drawstr, but->drawstr + len)); - but->drawstr[len - bytes] = 0; - } - } - else - ui_text_clip_give_next_off(but); - + ui_text_clip_give_next_off(but); but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs); - if (but->strwidth < 10) break; } - - if (fstyle->kerning == 1) + + if (fstyle->kerning == 1) { BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT); + } } -static void ui_text_label_rightclip(uiFontStyle *fstyle, uiBut *but, rcti *rect) +/** + * Cut off the text, taking into account the cursor location (text display while editing). + */ +static void ui_text_clip_cursor(uiFontStyle *fstyle, uiBut *but, rcti *rect) { int border = (but->flag & UI_BUT_ALIGN_RIGHT) ? 8 : 10; - int okwidth = BLI_RCT_SIZE_X(rect) - border; + int okwidth = BLI_rcti_size_x(rect) - border; + if (but->flag & UI_HAS_ICON) okwidth -= UI_DPI_ICON_SIZE; + + BLI_assert(but->editstr && but->pos >= 0); + + /* need to set this first */ + uiStyleFontSet(fstyle); + + if (fstyle->kerning == 1) /* for BLF_width */ + BLF_enable(fstyle->uifont_id, BLF_KERNING_DEFAULT); + + /* define ofs dynamically */ + if (but->ofs > but->pos) + but->ofs = but->pos; + + if (BLF_width(fstyle->uifont_id, but->drawstr) <= okwidth) + but->ofs = 0; + + but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs); + + while (but->strwidth > okwidth) { + float width; + char buf[UI_MAX_DRAW_STR]; + + /* copy draw string */ + BLI_strncpy_utf8(buf, but->drawstr, sizeof(buf)); + /* string position of cursor */ + buf[but->pos] = 0; + width = BLF_width(fstyle->uifont_id, buf + but->ofs); + + /* if cursor is at 20 pixels of right side button we clip left */ + if (width > okwidth - 20) { + ui_text_clip_give_next_off(but); + } + else { + int len, bytes; + /* shift string to the left */ + if (width < 20 && but->ofs > 0) + ui_text_clip_give_prev_off(but); + len = strlen(but->drawstr); + bytes = BLI_str_utf8_size(BLI_str_find_prev_char_utf8(but->drawstr, but->drawstr + len)); + but->drawstr[len - bytes] = 0; + } + + but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs); + + if (but->strwidth < 10) break; + } + + if (fstyle->kerning == 1) { + BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT); + } +} + +/** + * Cut off the end of text to fit into the width of \a rect. + * + * \note deals with ': ' especially for number buttons + */ +static void ui_text_clip_right_label(uiFontStyle *fstyle, uiBut *but, rcti *rect) +{ + int border = (but->flag & UI_BUT_ALIGN_RIGHT) ? 8 : 10; + int okwidth = BLI_rcti_size_x(rect) - border; char *cpoin = NULL; - char *cpend = but->drawstr + strlen(but->drawstr); + int drawstr_len = strlen(but->drawstr); + char *cpend = but->drawstr + drawstr_len; /* need to set this first */ uiStyleFontSet(fstyle); @@ -1045,6 +1079,13 @@ static void ui_text_label_rightclip(uiFontStyle *fstyle, uiBut *but, rcti *rect) but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr); but->ofs = 0; + + /* First shorten num-buttopns eg, + * Translucency: 0.000 + * becomes + * Trans: 0.000 + */ + /* find the space after ':' separator */ cpoin = strrchr(but->drawstr, ':'); @@ -1057,8 +1098,11 @@ static void ui_text_label_rightclip(uiFontStyle *fstyle, uiBut *but, rcti *rect) int bytes = cp2 - prev_utf8; /* shift the text after and including cp2 back by 1 char, +1 to include null terminator */ - memmove(cp2 - bytes, cp2, strlen(cp2) + 1); + memmove(cp2 - bytes, cp2, drawstr_len + 1); cp2 -= bytes; + + drawstr_len -= bytes; + // BLI_assert(strlen(but->drawstr) == drawstr_len); but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs); if (but->strwidth < 10) break; @@ -1074,14 +1118,17 @@ static void ui_text_label_rightclip(uiFontStyle *fstyle, uiBut *but, rcti *rect) } + + /* Now just remove trailing chars */ /* once the label's gone, chop off the least significant digits */ while (but->strwidth > okwidth) { - int len = strlen(but->drawstr); - int bytes = BLI_str_utf8_size(BLI_str_find_prev_char_utf8(but->drawstr, but->drawstr + len)); + int bytes = BLI_str_utf8_size(BLI_str_find_prev_char_utf8(but->drawstr, but->drawstr + drawstr_len)); if (bytes < 0) bytes = 1; - but->drawstr[len - bytes] = 0; + drawstr_len -= bytes; + but->drawstr[drawstr_len] = 0; + // BLI_assert(strlen(but->drawstr) == drawstr_len); but->strwidth = BLF_width(fstyle->uifont_id, but->drawstr + but->ofs); if (but->strwidth < 10) break; @@ -1229,30 +1276,34 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b /* draws text and icons for buttons */ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect) { - - if (but == NULL) return; + char password_str[UI_MAX_DRAW_STR]; + + if (but == NULL) + return; + + ui_button_text_password_hide(password_str, but, FALSE); /* clip but->drawstr to fit in available space */ if (but->editstr && but->pos >= 0) { - ui_text_leftclip(fstyle, but, rect); + ui_text_clip_cursor(fstyle, but, rect); } else if (ELEM4(but->type, NUM, NUMABS, NUMSLI, SLI)) { - ui_text_label_rightclip(fstyle, but, rect); + ui_text_clip_right_label(fstyle, but, rect); } else if (ELEM(but->type, TEX, SEARCH_MENU)) { - ui_text_leftclip(fstyle, but, rect); + ui_text_clip_left(fstyle, but, rect); } else if ((but->block->flag & UI_BLOCK_LOOP) && (but->type == BUT)) { - ui_text_leftclip(fstyle, but, rect); + ui_text_clip_left(fstyle, but, rect); } else but->ofs = 0; - + /* check for button text label */ if (but->type == ICONTEXTROW) { widget_draw_icon(but, (BIFIconID) (but->icon + but->iconadd), 1.0f, rect); } else { - + if (but->type == BUT_TOGDUAL) { int dualset = 0; if (but->pointype == UI_BUT_POIN_SHORT) { @@ -1261,34 +1312,36 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB else if (but->pointype == UI_BUT_POIN_INT) { dualset = UI_BITBUT_TEST(*(((int *)but->poin) + 1), but->bitnr); } - + widget_draw_icon(but, ICON_DOT, dualset ? 1.0f : 0.25f, rect); } else if (but->type == MENU && (but->flag & UI_BUT_NODE_LINK)) { int tmp = rect->xmin; - rect->xmin = rect->xmax - BLI_RCT_SIZE_Y(rect) - 1; + rect->xmin = rect->xmax - BLI_rcti_size_y(rect) - 1; widget_draw_icon(but, ICON_LAYER_USED, 1.0f, rect); rect->xmin = tmp; } - + /* If there's an icon too (made with uiDefIconTextBut) then draw the icon * and offset the text label to accommodate it */ - + if (but->flag & UI_HAS_ICON) { widget_draw_icon(but, but->icon + but->iconadd, 1.0f, rect); - + rect->xmin += (int)((float)UI_icon_get_width(but->icon + but->iconadd) * UI_DPI_ICON_FAC); - - if (but->editstr || (but->flag & UI_TEXT_LEFT)) + + if (but->editstr || (but->flag & UI_TEXT_LEFT)) rect->xmin += 5; } - else if ((but->flag & UI_TEXT_LEFT)) + else if ((but->flag & UI_TEXT_LEFT)) rect->xmin += 5; - + /* always draw text for textbutton cursor */ widget_draw_text(fstyle, wcol, but, rect); } + + ui_button_text_password_hide(password_str, but, TRUE); } @@ -1761,8 +1814,8 @@ static void widget_softshadow(rcti *rect, int roundboxalign, float radin, float float quad_strip[WIDGET_SIZE_MAX * 2][2]; /* prevent tooltips to not show round shadow */ - if (2.0f * radout > 0.2f * BLI_RCT_SIZE_Y(&rect1)) - rect1.ymax -= 0.2f * BLI_RCT_SIZE_Y(&rect1); + if (2.0f * radout > 0.2f * BLI_rcti_size_y(&rect1)) + rect1.ymax -= 0.2f * BLI_rcti_size_y(&rect1); else rect1.ymax -= 2.0f * radout; @@ -1804,7 +1857,7 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir else if (direction == UI_DOWN) { roundboxalign = (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT); rect->ymin -= 4.0; - } + } else if (direction == UI_TOP) { roundboxalign = UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT; rect->ymax += 4.0; @@ -1841,53 +1894,47 @@ static void ui_hsv_cursor(float x, float y) } -void ui_hsvcircle_vals_from_pos(float *valrad, float *valdist, rcti *rect, float mx, float my) +void ui_hsvcircle_vals_from_pos(float *val_rad, float *val_dist, const rcti *rect, + const float mx, const float my) { /* duplication of code... well, simple is better now */ - float centx = BLI_RCT_CENTER_X_FL(rect); - float centy = BLI_RCT_CENTER_Y_FL(rect); - float radius, dist; - - if (BLI_RCT_SIZE_X(rect) > BLI_RCT_SIZE_Y(rect)) - radius = (float)BLI_RCT_SIZE_Y(rect) / 2; - else - radius = (float)BLI_RCT_SIZE_X(rect) / 2; + const float centx = BLI_rcti_cent_x_fl(rect); + const float centy = BLI_rcti_cent_y_fl(rect); + const float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f; + const float m_delta[2] = {mx - centx, my - centy}; + const float dist_squared = len_squared_v2(m_delta); - mx -= centx; - my -= centy; - dist = sqrt(mx * mx + my * my); - if (dist < radius) - *valdist = dist / radius; - else - *valdist = 1.0f; - - *valrad = atan2f(mx, my) / (2.0f * (float)M_PI) + 0.5f; + *val_dist = (dist_squared < (radius * radius)) ? sqrtf(dist_squared) / radius : 1.0f; + *val_rad = atan2f(m_delta[0], m_delta[1]) / (2.0f * (float)M_PI) + 0.5f; } -static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, rcti *rect) +static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *rect) { + const int tot = 32; + const float radstep = 2.0f * (float)M_PI / (float)tot; + + const float centx = BLI_rcti_cent_x_fl(rect); + const float centy = BLI_rcti_cent_y_fl(rect); + float radius = (float)min_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)) / 2.0f; + /* gouraud triangle fan */ - float radstep, ang = 0.0f; - float centx, centy, radius, cursor_radius; + const float *hsv_ptr = ui_block_hsv_get(but->block); + float ang = 0.0f; + float cursor_radius; float rgb[3], hsvo[3], hsv[3], col[3], colcent[3]; - int a, tot = 32; + int a; int color_profile = but->block->color_profile; if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) color_profile = FALSE; - radstep = 2.0f * (float)M_PI / (float)tot; - centx = BLI_RCT_CENTER_X_FL(rect); - centy = BLI_RCT_CENTER_Y_FL(rect); - - if (BLI_RCT_SIZE_X(rect) > BLI_RCT_SIZE_Y(rect)) - radius = (float)BLI_RCT_SIZE_Y(rect) / 2; - else - radius = (float)BLI_RCT_SIZE_X(rect) / 2; - /* color */ ui_get_but_vectorf(but, rgb); - /* copy_v3_v3(hsv, ui_block_hsv_get(but->block)); */ /* UNUSED */ + + /* since we use compat functions on both 'hsv' and 'hsvo', they need to be initialized */ + hsvo[0] = hsv[0] = hsv_ptr[0]; + hsvo[1] = hsv[1] = hsv_ptr[1]; + hsvo[2] = hsv[2] = hsv_ptr[2]; rgb_to_hsv_compat_v(rgb, hsvo); @@ -1953,7 +2000,7 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, rcti *rect) /* draws in resolution of 20x4 colors */ void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const float alpha) { - const float color_step = (type == UI_GRAD_H) ? 0.02 : 0.05f; + const float color_step = (type == UI_GRAD_H) ? 0.02f : 0.05f; int a; float h = hsv[0], s = hsv[1], v = hsv[2]; float dx, dy, sx1, sx2, sy; @@ -2062,10 +2109,10 @@ void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const floa } /* rect */ - sx1 = rect->xmin + dx * BLI_RCT_SIZE_X(rect); - sx2 = rect->xmin + (dx + color_step) * BLI_RCT_SIZE_X(rect); + sx1 = rect->xmin + dx * BLI_rcti_size_x(rect); + sx2 = rect->xmin + (dx + color_step) * BLI_rcti_size_x(rect); sy = rect->ymin; - dy = BLI_RCT_SIZE_Y(rect) / 3.0; + dy = BLI_rcti_size_y(rect) / 3.0; glBegin(GL_QUADS); for (a = 0; a < 3; a++, sy += dy) { @@ -2120,8 +2167,8 @@ static void ui_draw_but_HSVCUBE(uiBut *but, rcti *rect) } /* cursor */ - x = rect->xmin + x * BLI_RCT_SIZE_X(rect); - y = rect->ymin + y * BLI_RCT_SIZE_Y(rect); + x = rect->xmin + x * BLI_rcti_size_x(rect); + y = rect->ymin + y * BLI_rcti_size_y(rect); CLAMP(x, rect->xmin + 3.0f, rect->xmax - 3.0f); CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f); @@ -2136,7 +2183,7 @@ static void ui_draw_but_HSVCUBE(uiBut *but, rcti *rect) static void ui_draw_but_HSV_v(uiBut *but, rcti *rect) { uiWidgetBase wtb; - float rad = 0.5f * BLI_RCT_SIZE_X(rect); + float rad = 0.5f * BLI_rcti_size_x(rect); float x, y; float rgb[3], hsv[3], v, range; int color_profile = but->block->color_profile; @@ -2171,8 +2218,8 @@ static void ui_draw_but_HSV_v(uiBut *but, rcti *rect) widgetbase_draw(&wtb, &wcol_tmp); /* cursor */ - x = rect->xmin + 0.5f * BLI_RCT_SIZE_X(rect); - y = rect->ymin + v * BLI_RCT_SIZE_Y(rect); + x = rect->xmin + 0.5f * BLI_rcti_size_x(rect); + y = rect->ymin + v * BLI_rcti_size_y(rect); CLAMP(y, rect->ymin + 3.0f, rect->ymax - 3.0f); ui_hsv_cursor(x, y); @@ -2183,7 +2230,7 @@ static void ui_draw_but_HSV_v(uiBut *but, rcti *rect) /* ************ separator, for menus etc ***************** */ static void ui_draw_separator(rcti *rect, uiWidgetColors *wcol) { - int y = rect->ymin + BLI_RCT_SIZE_Y(rect) / 2 - 1; + int y = rect->ymin + BLI_rcti_size_y(rect) / 2 - 1; unsigned char col[4]; col[0] = wcol->text[0]; @@ -2202,7 +2249,7 @@ static void ui_draw_separator(rcti *rect, uiWidgetColors *wcol) static void widget_numbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign) { uiWidgetBase wtb; - float rad = 0.5f * BLI_RCT_SIZE_Y(rect); + float rad = 0.5f * BLI_rcti_size_y(rect); float textofs = rad * 0.75f; if (state & UI_SELECT) @@ -2283,12 +2330,12 @@ void uiWidgetScrollDraw(uiWidgetColors *wcol, rcti *rect, rcti *slider, int stat widget_init(&wtb); /* determine horizontal/vertical */ - horizontal = (BLI_RCT_SIZE_X(rect) > BLI_RCT_SIZE_Y(rect)); + horizontal = (BLI_rcti_size_x(rect) > BLI_rcti_size_y(rect)); if (horizontal) - rad = 0.5f * BLI_RCT_SIZE_Y(rect); + rad = 0.5f * BLI_rcti_size_y(rect); else - rad = 0.5f * BLI_RCT_SIZE_X(rect); + rad = 0.5f * BLI_rcti_size_x(rect); wtb.shadedir = (horizontal) ? 1 : 0; @@ -2300,7 +2347,7 @@ void uiWidgetScrollDraw(uiWidgetColors *wcol, rcti *rect, rcti *slider, int stat widgetbase_draw(&wtb, wcol); /* slider */ - if ((BLI_RCT_SIZE_X(slider) < 2) || (BLI_RCT_SIZE_Y(slider) < 2)) { + if ((BLI_rcti_size_x(slider) < 2) || (BLI_rcti_size_y(slider) < 2)) { /* pass */ } else { @@ -2322,7 +2369,7 @@ void uiWidgetScrollDraw(uiWidgetColors *wcol, rcti *rect, rcti *slider, int stat wtb.emboss = 0; /* only emboss once */ /* exception for progress bar */ - if (state & UI_SCROLL_NO_OUTLINE) + if (state & UI_SCROLL_NO_OUTLINE) SWAP(short, outline, wtb.outline); round_box_edges(&wtb, UI_CNR_ALL, slider, rad); @@ -2346,7 +2393,7 @@ void uiWidgetScrollDraw(uiWidgetColors *wcol, rcti *rect, rcti *slider, int stat if (state & UI_SCROLL_NO_OUTLINE) SWAP(short, outline, wtb.outline); - } + } } static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign)) @@ -2360,45 +2407,45 @@ static void widget_scroll(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat value = ui_get_but_val(but); size = (but->softmax + but->a1 - but->softmin); - size = MAX2(size, 2); + size = max_ff(size, 2.0f); /* position */ rect1 = *rect; /* determine horizontal/vertical */ - horizontal = (BLI_RCT_SIZE_X(rect) > BLI_RCT_SIZE_Y(rect)); + horizontal = (BLI_rcti_size_x(rect) > BLI_rcti_size_y(rect)); if (horizontal) { - fac = BLI_RCT_SIZE_X(rect) / size; + fac = BLI_rcti_size_x(rect) / size; rect1.xmin = rect1.xmin + ceilf(fac * ((float)value - but->softmin)); rect1.xmax = rect1.xmin + ceilf(fac * (but->a1 - but->softmin)); /* ensure minimium size */ - min = BLI_RCT_SIZE_Y(rect); + min = BLI_rcti_size_y(rect); - if (BLI_RCT_SIZE_X(&rect1) < min) { + if (BLI_rcti_size_x(&rect1) < min) { rect1.xmax = rect1.xmin + min; if (rect1.xmax > rect->xmax) { rect1.xmax = rect->xmax; - rect1.xmin = maxi(rect1.xmax - min, rect->xmin); + rect1.xmin = max_ii(rect1.xmax - min, rect->xmin); } } } else { - fac = BLI_RCT_SIZE_Y(rect) / size; + fac = BLI_rcti_size_y(rect) / size; rect1.ymax = rect1.ymax - ceilf(fac * ((float)value - but->softmin)); rect1.ymin = rect1.ymax - ceilf(fac * (but->a1 - but->softmin)); /* ensure minimium size */ - min = BLI_RCT_SIZE_X(rect); + min = BLI_rcti_size_x(rect); - if (BLI_RCT_SIZE_Y(&rect1) < min) { + if (BLI_rcti_size_y(&rect1) < min) { rect1.ymax = rect1.ymin + min; if (rect1.ymax > rect->ymax) { rect1.ymax = rect->ymax; - rect1.ymin = MAX2(rect1.ymax - min, rect->ymin); + rect1.ymin = max_ii(rect1.ymax - min, rect->ymin); } } } @@ -2421,10 +2468,10 @@ static void widget_progressbar(uiBut *but, uiWidgetColors *wcol, rcti *rect, int rect_prog.ymax = rect_prog.ymin + 4; rect_bar.ymax = rect_bar.ymin + 4; - w = value * BLI_RCT_SIZE_X(&rect_prog); + w = value * BLI_rcti_size_x(&rect_prog); /* ensure minimium size */ - min = BLI_RCT_SIZE_Y(&rect_prog); + min = BLI_rcti_size_y(&rect_prog); w = MAX2(w, min); rect_bar.xmax = rect_bar.xmin + w; @@ -2444,8 +2491,8 @@ static void widget_link(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect, in UI_ThemeColor(TH_TEXT_HI); - rectlink.xmin = BLI_RCT_CENTER_X(rect); - rectlink.ymin = BLI_RCT_CENTER_Y(rect); + rectlink.xmin = BLI_rcti_cent_x(rect); + rectlink.ymin = BLI_rcti_cent_y(rect); rectlink.xmax = but->linkto[0]; rectlink.ymax = but->linkto[1]; @@ -2467,7 +2514,7 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s /* backdrop first */ /* fully rounded */ - offs = 0.5f * BLI_RCT_SIZE_Y(rect); + offs = 0.5f * BLI_rcti_size_y(rect); toffs = offs * 0.75f; round_box_edges(&wtb, roundboxalign, rect, offs); @@ -2488,7 +2535,7 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s rect1 = *rect; value = ui_get_but_val(but); - fac = ((float)value - but->softmin) * (BLI_RCT_SIZE_X(&rect1) - offs) / (but->softmax - but->softmin); + fac = ((float)value - but->softmin) * (BLI_rcti_size_x(&rect1) - offs) / (but->softmax - but->softmin); /* left part of slider, always rounded */ rect1.xmax = rect1.xmin + ceil(offs + 1.0f); @@ -2585,7 +2632,7 @@ static void widget_icon_has_anim(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti /* rounded */ round_box_edges(&wtb, UI_CNR_ALL, rect, 10.0f); widgetbase_draw(&wtb, wcol); - } + } } @@ -2620,8 +2667,8 @@ static void widget_menubut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), widgetbase_draw(&wtb, wcol); - /* text space */ - rect->xmax -= BLI_RCT_SIZE_Y(rect); + /* text space, arrows are about 0.6 height of button */ + rect->xmax -= (6 * BLI_rcti_size_y(rect)) / 10; } static void widget_menuiconbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign) @@ -2660,16 +2707,16 @@ static void widget_menunodebut(uiWidgetColors *wcol, rcti *rect, int UNUSED(stat *wcol = wcol_backup; } -static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign)) +static void widget_pulldownbut(uiWidgetColors *wcol, rcti *rect, int state, int roundboxalign) { if (state & UI_ACTIVE) { uiWidgetBase wtb; - float rad = 0.5f * BLI_RCT_SIZE_Y(rect); /* 4.0f */ - + float rad = 0.25f * BLI_rcti_size_y(rect); /* 4.0f */ + widget_init(&wtb); - + /* half rounded */ - round_box_edges(&wtb, UI_CNR_ALL, rect, rad); + round_box_edges(&wtb, roundboxalign, rect, rad); widgetbase_draw(&wtb, wcol); } @@ -2710,10 +2757,10 @@ static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UN widget_init(&wtb); /* square */ - recttemp.xmax = recttemp.xmin + BLI_RCT_SIZE_Y(&recttemp); + recttemp.xmax = recttemp.xmin + BLI_rcti_size_y(&recttemp); /* smaller */ - delta = 1 + BLI_RCT_SIZE_Y(&recttemp) / 8; + delta = 1 + BLI_rcti_size_y(&recttemp) / 8; recttemp.xmin += delta; recttemp.ymin += delta; recttemp.xmax -= delta; @@ -2730,7 +2777,7 @@ static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UN widgetbase_draw(&wtb, wcol); /* text space */ - rect->xmin += BLI_RCT_SIZE_Y(rect) * 0.7 + delta; + rect->xmin += BLI_rcti_size_y(rect) * 0.7 + delta; } @@ -2792,7 +2839,7 @@ static void widget_but(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign) { uiWidgetBase wtb; - float rad = 5.0f; /* 0.5f * BLI_RCT_SIZE_Y(rect); */ + float rad = 5.0f; /* 0.5f * BLI_rcti_size_y(rect); */ widget_init(&wtb); @@ -3006,9 +3053,12 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type) static int widget_roundbox_set(uiBut *but, rcti *rect) { + int roundbox = UI_CNR_ALL; + /* alignment */ - if (but->flag & UI_BUT_ALIGN) { + if ((but->flag & UI_BUT_ALIGN) && but->type != PULLDOWN) { + /* ui_block_position has this correction too, keep in sync */ if (but->flag & UI_BUT_ALIGN_TOP) rect->ymax += 1; if (but->flag & UI_BUT_ALIGN_LEFT) @@ -3016,27 +3066,46 @@ static int widget_roundbox_set(uiBut *but, rcti *rect) switch (but->flag & UI_BUT_ALIGN) { case UI_BUT_ALIGN_TOP: - return UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT; + roundbox = UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT; + break; case UI_BUT_ALIGN_DOWN: - return UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT; + roundbox = UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT; + break; case UI_BUT_ALIGN_LEFT: - return UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT; + roundbox = UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT; + break; case UI_BUT_ALIGN_RIGHT: - return UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT; + roundbox = UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT; + break; case UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_RIGHT: - return UI_CNR_TOP_LEFT; + roundbox = UI_CNR_TOP_LEFT; + break; case UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_LEFT: - return UI_CNR_TOP_RIGHT; + roundbox = UI_CNR_TOP_RIGHT; + break; case UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_RIGHT: - return UI_CNR_BOTTOM_LEFT; + roundbox = UI_CNR_BOTTOM_LEFT; + break; case UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_LEFT: - return UI_CNR_BOTTOM_RIGHT; + roundbox = UI_CNR_BOTTOM_RIGHT; + break; default: - return 0; + roundbox = 0; + break; } } - return UI_CNR_ALL; + /* align with open menu */ + if (but->active) { + int direction = ui_button_open_menu_direction(but); + + if (direction == UI_TOP) roundbox &= ~(UI_CNR_TOP_RIGHT | UI_CNR_TOP_LEFT); + else if (direction == UI_DOWN) roundbox &= ~(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT); + else if (direction == UI_LEFT) roundbox &= ~(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT); + else if (direction == UI_RIGHT) roundbox &= ~(UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT); + } + + return roundbox; } /* conversion from old to new buttons, so still messy */ @@ -3275,14 +3344,14 @@ void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect) if (block->flag & UI_BLOCK_CLIPTOP) { /* XXX no scaling for UI here yet */ glColor3ubv((unsigned char *)wt->wcol.text); - UI_DrawTriIcon(BLI_RCT_CENTER_X(rect), rect->ymax - 8, 't'); + UI_DrawTriIcon(BLI_rcti_cent_x(rect), rect->ymax - 8, 't'); } if (block->flag & UI_BLOCK_CLIPBOTTOM) { /* XXX no scaling for UI here yet */ glColor3ubv((unsigned char *)wt->wcol.text); - UI_DrawTriIcon(BLI_RCT_CENTER_X(rect), rect->ymin + 10, 'v'); + UI_DrawTriIcon(BLI_rcti_cent_x(rect), rect->ymin + 10, 'v'); } - } + } } uiWidgetColors *ui_tooltip_get_theme(void) diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index b379a2e7b4c..e03a2887866 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -651,7 +651,7 @@ void ui_theme_init_default(void) strcpy(btheme->name, "Default"); } - UI_SetTheme(0, 0); // make sure the global used in this file is set + UI_SetTheme(0, 0); /* make sure the global used in this file is set */ /* UI buttons */ ui_widget_color_init(&btheme->tui); @@ -808,9 +808,9 @@ void ui_theme_init_default(void) rgba_char_args_set_fl(btheme->tfile.list, 0.4, 0.4, 0.4, 1); rgba_char_args_set(btheme->tfile.text, 250, 250, 250, 255); rgba_char_args_set(btheme->tfile.text_hi, 15, 15, 15, 255); - rgba_char_args_set(btheme->tfile.panel, 145, 145, 145, 255); // bookmark/ui regions - rgba_char_args_set(btheme->tfile.active, 130, 130, 130, 255); // selected files - rgba_char_args_set(btheme->tfile.hilite, 255, 140, 25, 255); // selected files + rgba_char_args_set(btheme->tfile.panel, 145, 145, 145, 255); /* bookmark/ui regions */ + rgba_char_args_set(btheme->tfile.active, 130, 130, 130, 255); /* selected files */ + rgba_char_args_set(btheme->tfile.hilite, 255, 140, 25, 255); /* selected files */ rgba_char_args_set(btheme->tfile.grid, 250, 250, 250, 255); rgba_char_args_set(btheme->tfile.image, 250, 250, 250, 255); @@ -891,7 +891,7 @@ void ui_theme_init_default(void) btheme->ttime = btheme->tv3d; rgba_char_args_set_fl(btheme->ttime.back, 0.45, 0.45, 0.45, 1.0); rgba_char_args_set_fl(btheme->ttime.grid, 0.36, 0.36, 0.36, 1.0); - rgba_char_args_set(btheme->ttime.shade1, 173, 173, 173, 255); // sliders + rgba_char_args_set(btheme->ttime.shade1, 173, 173, 173, 255); /* sliders */ /* space node, re-uses syntax color storage */ btheme->tnode = btheme->tv3d; @@ -901,6 +901,7 @@ void ui_theme_init_default(void) rgba_char_args_set(btheme->tnode.syntaxb, 108, 105, 111, 255); /* operator */ rgba_char_args_set(btheme->tnode.syntaxv, 104, 106, 117, 255); /* generator */ rgba_char_args_set(btheme->tnode.syntaxc, 105, 117, 110, 255); /* group */ + rgba_char_args_set(btheme->tnode.movie, 155, 155, 155, 160); /* frame */ btheme->tnode.noodle_curving = 5; /* space logic */ @@ -931,7 +932,7 @@ void ui_theme_init_default(void) void UI_SetTheme(int spacetype, int regionid) { - if (spacetype == 0) { // called for safety, when delete themes + if (spacetype == 0) { /* called for safety, when delete themes */ theme_active = U.themes.first; theme_spacetype = SPACE_VIEW3D; theme_regionid = RGN_TYPE_WINDOW; @@ -949,7 +950,7 @@ bTheme *UI_GetTheme(void) return U.themes.first; } -// for space windows only +/* for space windows only */ void UI_ThemeColor(int colorid) { const unsigned char *cp; @@ -959,7 +960,7 @@ void UI_ThemeColor(int colorid) } -// plus alpha +/* plus alpha */ void UI_ThemeColor4(int colorid) { const unsigned char *cp; @@ -969,7 +970,7 @@ void UI_ThemeColor4(int colorid) } -// set the color with offset for shades +/* set the color with offset for shades */ void UI_ThemeColorShade(int colorid, int offset) { int r, g, b; @@ -1002,7 +1003,7 @@ void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset) glColor4ub(r, g, b, a); } -// blend between to theme colors, and set it +/* blend between to theme colors, and set it */ void UI_ThemeColorBlend(int colorid1, int colorid2, float fac) { int r, g, b; @@ -1019,7 +1020,7 @@ void UI_ThemeColorBlend(int colorid1, int colorid2, float fac) glColor3ub(r, g, b); } -// blend between to theme colors, shade it, and set it +/* blend between to theme colors, shade it, and set it */ void UI_ThemeColorBlendShade(int colorid1, int colorid2, float fac, int offset) { int r, g, b; @@ -1040,7 +1041,7 @@ void UI_ThemeColorBlendShade(int colorid1, int colorid2, float fac, int offset) glColor3ub(r, g, b); } -// blend between to theme colors, shade it, and set it +/* blend between to theme colors, shade it, and set it */ void UI_ThemeColorBlendShadeAlpha(int colorid1, int colorid2, float fac, int offset, int alphaoffset) { int r, g, b, a; @@ -1064,7 +1065,7 @@ void UI_ThemeColorBlendShadeAlpha(int colorid1, int colorid2, float fac, int off } -// get individual values, not scaled +/* get individual values, not scaled */ float UI_GetThemeValuef(int colorid) { const unsigned char *cp; @@ -1074,7 +1075,7 @@ float UI_GetThemeValuef(int colorid) } -// get individual values, not scaled +/* get individual values, not scaled */ int UI_GetThemeValue(int colorid) { const unsigned char *cp; @@ -1085,7 +1086,7 @@ int UI_GetThemeValue(int colorid) } -// get the color, range 0.0-1.0 +/* get the color, range 0.0-1.0 */ void UI_GetThemeColor3fv(int colorid, float col[3]) { const unsigned char *cp; @@ -1107,7 +1108,7 @@ void UI_GetThemeColor4fv(int colorid, float col[4]) col[3] = ((float)cp[3]) / 255.0f; } -// get the color, range 0.0-1.0, complete with shading offset +/* get the color, range 0.0-1.0, complete with shading offset */ void UI_GetThemeColorShade3fv(int colorid, int offset, float col[3]) { int r, g, b; @@ -1146,7 +1147,7 @@ void UI_GetThemeColorShade3ubv(int colorid, int offset, unsigned char col[3]) col[2] = b; } -// get the color, in char pointer +/* get the color, in char pointer */ void UI_GetThemeColor3ubv(int colorid, unsigned char col[3]) { const unsigned char *cp; @@ -1157,7 +1158,7 @@ void UI_GetThemeColor3ubv(int colorid, unsigned char col[3]) col[2] = cp[2]; } -// get the color, in char pointer +/* get the color, in char pointer */ void UI_GetThemeColor4ubv(int colorid, unsigned char col[4]) { const unsigned char *cp; @@ -1180,7 +1181,7 @@ void UI_GetThemeColorType4ubv(int colorid, int spacetype, char col[4]) col[3] = cp[3]; } -// blends and shades between two char color pointers +/* blends and shades between two char color pointers */ void UI_ColorPtrBlendShade3ubv(const unsigned char cp1[3], const unsigned char cp2[3], float fac, int offset) { int r, g, b; @@ -1213,7 +1214,7 @@ void UI_GetColorPtrShade3ubv(const unsigned char cp[3], unsigned char col[3], in col[2] = b; } -// get a 3 byte color, blended and shaded between two other char color pointers +/* get a 3 byte color, blended and shaded between two other char color pointers */ void UI_GetColorPtrBlendShade3ubv(const unsigned char cp1[3], const unsigned char cp2[3], unsigned char col[3], float fac, int offset) { @@ -1359,7 +1360,7 @@ void init_userdef_do_versions(void) btheme->ttime = btheme->tv3d; rgba_char_args_set_fl(btheme->ttime.back, 0.45, 0.45, 0.45, 1.0); rgba_char_args_set_fl(btheme->ttime.grid, 0.36, 0.36, 0.36, 1.0); - rgba_char_args_set(btheme->ttime.shade1, 173, 173, 173, 255); // sliders + rgba_char_args_set(btheme->ttime.shade1, 173, 173, 173, 255); /* sliders */ } if (btheme->text.syntaxn[3] == 0) { rgba_char_args_set(btheme->text.syntaxn, 0, 0, 200, 255); /* Numbers Blue*/ @@ -1934,6 +1935,18 @@ void init_userdef_do_versions(void) } } + if (bmain->versionfile < 263 || (bmain->versionfile == 263 && bmain->subversionfile < 22)) { + bTheme *btheme; + + for (btheme = U.themes.first; btheme; btheme = btheme->next) { + if (btheme->tipo.lastsel_point[3] == 0) + rgba_char_args_set(btheme->tipo.lastsel_point, 0xff, 0xff, 0xff, 255); + + if (btheme->tv3d.skin_root[3] == 0) + rgba_char_args_set(btheme->tv3d.skin_root, 180, 77, 77, 255); + } + } + /* GL Texture Garbage Collection (variable abused above!) */ if (U.textimeout == 0) { U.texcollectrate = 60; @@ -1969,7 +1982,10 @@ void init_userdef_do_versions(void) } if (U.ndof_orbit_sensitivity == 0.0f) { - U.ndof_orbit_sensitivity = 1.0f; + U.ndof_orbit_sensitivity = U.ndof_sensitivity; + + if (!(U.flag & USER_TRACKBALL)) + U.ndof_flag |= NDOF_TURNTABLE; } if (U.tweak_threshold == 0) U.tweak_threshold = 10; diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index 9c71746d045..f1a3f59bc22 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -96,11 +96,11 @@ static void view2d_masks(View2D *v2d) /* check size if: */ if (v2d->scroll & V2D_SCROLL_HORIZONTAL) if (!(v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL)) - if (BLI_RCT_SIZE_X(&v2d->tot) <= BLI_RCT_SIZE_X(&v2d->cur)) + if (BLI_rctf_size_x(&v2d->tot) <= BLI_rcti_size_x(&v2d->cur)) v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE; if (v2d->scroll & V2D_SCROLL_VERTICAL) if (!(v2d->scroll & V2D_SCROLL_SCALE_VERTICAL)) - if (BLI_RCT_SIZE_Y(&v2d->tot) <= BLI_RCT_SIZE_Y(&v2d->cur)) + if (BLI_rctf_size_y(&v2d->tot) <= BLI_rctf_size_y(&v2d->cur)) v2d->scroll |= V2D_SCROLL_VERTICAL_HIDE; #endif scroll = view2d_scroll_mapped(v2d->scroll); @@ -299,7 +299,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) /* other view types are completely defined using their own settings already */ default: /* we don't do anything here, as settings should be fine, but just make sure that rect */ - break; + break; } } @@ -328,8 +328,8 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize) rctf *cur, *tot; /* use mask as size of region that View2D resides in, as it takes into account scrollbars already */ - winx = (float)(BLI_RCT_SIZE_X(&v2d->mask) + 1); - winy = (float)(BLI_RCT_SIZE_Y(&v2d->mask) + 1); + winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1); + winy = (float)(BLI_rcti_size_y(&v2d->mask) + 1); /* get pointers to rcts for less typing */ cur = &v2d->cur; @@ -347,10 +347,10 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize) * - firstly, we calculate the sizes of the rects * - curwidth and curheight are saved as reference... modify width and height values here */ - totwidth = BLI_RCT_SIZE_X(tot); - totheight = BLI_RCT_SIZE_Y(tot); - curwidth = width = BLI_RCT_SIZE_X(cur); - curheight = height = BLI_RCT_SIZE_Y(cur); + totwidth = BLI_rctf_size_x(tot); + totheight = BLI_rctf_size_y(tot); + curwidth = width = BLI_rctf_size_x(cur); + curheight = height = BLI_rctf_size_y(cur); /* if zoom is locked, size on the appropriate axis is reset to mask size */ if (v2d->keepzoom & V2D_LOCKZOOM_X) @@ -476,8 +476,14 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize) if (winy < v2d->oldwiny) { float temp = v2d->oldwiny - winy; - cur->ymin += temp; - cur->ymax += temp; + if (v2d->align & V2D_ALIGN_NO_NEG_Y) { + cur->ymin -= temp; + cur->ymax -= temp; + } + else { /* Assume V2D_ALIGN_NO_POS_Y or combination */ + cur->ymin += temp; + cur->ymax += temp; + } } } @@ -499,16 +505,16 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize) /* resize from centerpoint, unless otherwise specified */ if (width != curwidth) { if (v2d->keepofs & V2D_LOCKOFS_X) { - cur->xmax += width - BLI_RCT_SIZE_X(cur); + cur->xmax += width - BLI_rctf_size_x(cur); } else if (v2d->keepofs & V2D_KEEPOFS_X) { if (v2d->align & V2D_ALIGN_NO_POS_X) - cur->xmin -= width - BLI_RCT_SIZE_X(cur); + cur->xmin -= width - BLI_rctf_size_x(cur); else - cur->xmax += width - BLI_RCT_SIZE_X(cur); + cur->xmax += width - BLI_rctf_size_x(cur); } else { - temp = BLI_RCT_CENTER_X(cur); + temp = BLI_rctf_cent_x(cur); dh = width * 0.5f; cur->xmin = temp - dh; @@ -517,16 +523,16 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize) } if (height != curheight) { if (v2d->keepofs & V2D_LOCKOFS_Y) { - cur->ymax += height - BLI_RCT_SIZE_Y(cur); + cur->ymax += height - BLI_rctf_size_y(cur); } else if (v2d->keepofs & V2D_KEEPOFS_Y) { if (v2d->align & V2D_ALIGN_NO_POS_Y) - cur->ymin -= height - BLI_RCT_SIZE_Y(cur); + cur->ymin -= height - BLI_rctf_size_y(cur); else - cur->ymax += height - BLI_RCT_SIZE_Y(cur); + cur->ymax += height - BLI_rctf_size_y(cur); } else { - temp = BLI_RCT_CENTER_Y(cur); + temp = BLI_rctf_cent_y(cur); dh = height * 0.5f; cur->ymin = temp - dh; @@ -540,8 +546,8 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize) float temp, diff; /* recalculate extents of cur */ - curwidth = BLI_RCT_SIZE_X(cur); - curheight = BLI_RCT_SIZE_Y(cur); + curwidth = BLI_rctf_size_x(cur); + curheight = BLI_rctf_size_y(cur); /* width */ if ((curwidth > totwidth) && !(v2d->keepzoom & (V2D_KEEPZOOM | V2D_LOCKZOOM_X | V2D_LIMITZOOM))) { @@ -592,8 +598,8 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize) */ if ((cur->xmin < tot->xmin) && (cur->xmax > tot->xmax)) { /* outside boundaries on both sides, so take middle-point of tot, and place in balanced way */ - temp = BLI_RCT_CENTER_X(tot); - diff = curheight * 0.5f; + temp = BLI_rctf_cent_x(tot); + diff = curwidth * 0.5f; cur->xmin = temp - diff; cur->xmax = temp + diff; @@ -642,7 +648,7 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize) */ if ((cur->ymin < tot->ymin) && (cur->ymax > tot->ymax)) { /* outside boundaries on both sides, so take middle-point of tot, and place in balanced way */ - temp = BLI_RCT_CENTER_Y(tot); + temp = BLI_rctf_cent_y(tot); diff = curheight * 0.5f; cur->ymin = temp - diff; @@ -791,8 +797,8 @@ void UI_view2d_curRect_reset(View2D *v2d) float width, height; /* assume width and height of 'cur' rect by default, should be same size as mask */ - width = (float)(BLI_RCT_SIZE_X(&v2d->mask) + 1); - height = (float)(BLI_RCT_SIZE_Y(&v2d->mask) + 1); + width = (float)(BLI_rcti_size_x(&v2d->mask) + 1); + height = (float)(BLI_rcti_size_y(&v2d->mask) + 1); /* handle width - posx and negx flags are mutually exclusive, so watch out */ if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) { @@ -958,8 +964,8 @@ static void view2d_map_cur_using_mask(View2D *v2d, rctf *curmasked) *curmasked = v2d->cur; if (view2d_scroll_mapped(v2d->scroll)) { - float dx = BLI_RCT_SIZE_X(&v2d->cur) / ((float)(BLI_RCT_SIZE_X(&v2d->mask) + 1)); - float dy = BLI_RCT_SIZE_Y(&v2d->cur) / ((float)(BLI_RCT_SIZE_Y(&v2d->mask) + 1)); + float dx = BLI_rctf_size_x(&v2d->cur) / ((float)(BLI_rcti_size_x(&v2d->mask) + 1)); + float dy = BLI_rctf_size_y(&v2d->cur) / ((float)(BLI_rcti_size_y(&v2d->mask) + 1)); if (v2d->mask.xmin != 0) curmasked->xmin -= dx * (float)v2d->mask.xmin; @@ -985,14 +991,13 @@ void UI_view2d_view_ortho(View2D *v2d) */ /* XXX brecht: instead of zero at least use a tiny offset, otherwise * pixel rounding is effectively random due to float inaccuracy */ - xofs = 0.001f * BLI_RCT_SIZE_X(&v2d->cur) / BLI_RCT_SIZE_X(&v2d->mask); - yofs = 0.001f * BLI_RCT_SIZE_Y(&v2d->cur) / BLI_RCT_SIZE_Y(&v2d->mask); + xofs = 0.001f * BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); + yofs = 0.001f * BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask); /* apply mask-based adjustments to cur rect (due to scrollers), to eliminate scaling artifacts */ view2d_map_cur_using_mask(v2d, &curmasked); - - curmasked.xmin -= xofs; curmasked.xmax -= xofs; - curmasked.ymin -= yofs; curmasked.ymax -= yofs; + + BLI_rctf_translate(&curmasked, -xofs, -yofs); /* XXX ton: this flag set by outliner, for icons */ if (v2d->flag & V2D_PIXELOFS_X) { @@ -1044,8 +1049,8 @@ void UI_view2d_view_orthoSpecial(ARegion *ar, View2D *v2d, short xaxis) void UI_view2d_view_restore(const bContext *C) { ARegion *ar = CTX_wm_region(C); - int width = BLI_RCT_SIZE_X(&ar->winrct) + 1; - int height = BLI_RCT_SIZE_Y(&ar->winrct) + 1; + int width = BLI_rcti_size_x(&ar->winrct) + 1; + int height = BLI_rcti_size_y(&ar->winrct) + 1; wmOrtho2(0.0f, (float)width, 0.0f, (float)height); glLoadIdentity(); @@ -1090,7 +1095,7 @@ static void step_to_grid(float *step, int *power, int unit) } /* prevents printing 1.0 2.0 3.0 etc */ - if (rem == 1.0f) (*power)++; + if (rem == 1.0f) (*power)++; } else { if (rem < 2.0f) rem = 2.0f; @@ -1101,7 +1106,7 @@ static void step_to_grid(float *step, int *power, int unit) (*power)++; /* prevents printing 1.0, 2.0, 3.0, etc. */ - if (rem == 10.0f) (*power)++; + if (rem == 10.0f) (*power)++; } } @@ -1117,7 +1122,8 @@ static void step_to_grid(float *step, int *power, int unit) * - winx = width of region we're drawing to, note: not used but keeping for completeness. * - winy = height of region we're drawing into */ -View2DGrid *UI_view2d_grid_calc(Scene *scene, View2D *v2d, short xunits, short xclamp, short yunits, short yclamp, int UNUSED(winx), int winy) +View2DGrid *UI_view2d_grid_calc(Scene *scene, View2D *v2d, + short xunits, short xclamp, short yunits, short yclamp, int UNUSED(winx), int winy) { View2DGrid *grid; @@ -1140,8 +1146,8 @@ View2DGrid *UI_view2d_grid_calc(Scene *scene, View2D *v2d, short xunits, short x /* calculate x-axis grid scale (only if both args are valid) */ if (ELEM(V2D_ARG_DUMMY, xunits, xclamp) == 0) { - space = BLI_RCT_SIZE_X(&v2d->cur); - pixels = (float)BLI_RCT_SIZE_X(&v2d->mask); + space = BLI_rctf_size_x(&v2d->cur); + pixels = (float)BLI_rcti_size_x(&v2d->mask); if (pixels != 0.0f) { grid->dx = (U.v2d_min_gridsize * space) / (seconddiv * pixels); @@ -1158,7 +1164,7 @@ View2DGrid *UI_view2d_grid_calc(Scene *scene, View2D *v2d, short xunits, short x /* calculate y-axis grid scale (only if both args are valid) */ if (ELEM(V2D_ARG_DUMMY, yunits, yclamp) == 0) { - space = BLI_RCT_SIZE_Y(&v2d->cur); + space = BLI_rctf_size_y(&v2d->cur); pixels = (float)winy; grid->dy = U.v2d_min_gridsize * space / pixels; @@ -1206,7 +1212,7 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag) vec2[1] = v2d->cur.ymax; /* minor gridlines */ - step = (BLI_RCT_SIZE_X(&v2d->mask) + 1) / U.v2d_min_gridsize; + step = (BLI_rcti_size_x(&v2d->mask) + 1) / U.v2d_min_gridsize; UI_ThemeColor(TH_GRID); for (a = 0; a < step; a++) { @@ -1240,7 +1246,7 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag) vec1[0] = grid->startx; vec2[0] = v2d->cur.xmax; - step = (BLI_RCT_SIZE_Y(&v2d->mask) + 1) / U.v2d_min_gridsize; + step = (BLI_rcti_size_y(&v2d->mask) + 1) / U.v2d_min_gridsize; UI_ThemeColor(TH_GRID); for (a = 0; a <= step; a++) { @@ -1256,7 +1262,7 @@ void UI_view2d_grid_draw(View2D *v2d, View2DGrid *grid, int flag) vec2[1] = vec1[1] -= 0.5f * grid->dy; step++; - if (flag & V2D_HORIZONTAL_FINELINES) { + if (flag & V2D_HORIZONTAL_FINELINES) { UI_ThemeColorShade(TH_GRID, 16); for (a = 0; a < step; a++) { glBegin(GL_LINE_STRIP); @@ -1414,7 +1420,8 @@ struct View2DScrollers { }; /* Calculate relevant scroller properties */ -View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d, short xunits, short xclamp, short yunits, short yclamp) +View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d, + short xunits, short xclamp, short yunits, short yclamp) { View2DScrollers *scrollers; rcti vert, hor; @@ -1457,8 +1464,8 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d, short /* horizontal scrollers */ if (scroll & V2D_SCROLL_HORIZONTAL) { /* scroller 'button' extents */ - totsize = BLI_RCT_SIZE_X(&v2d->tot); - scrollsize = (float)BLI_RCT_SIZE_X(&hor); + totsize = BLI_rctf_size_x(&v2d->tot); + scrollsize = (float)BLI_rcti_size_x(&hor); if (totsize == 0.0f) totsize = 1.0f; /* avoid divide by zero */ fac1 = (v2d->cur.xmin - v2d->tot.xmin) / totsize; @@ -1486,7 +1493,7 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d, short /* check whether sliders can disappear due to the full-range being used */ if (v2d->keeptot) { - if ((fac1 <= 0.0f) && (fac2 >= 1.0f)) { + if ((fac1 <= 0.0f) && (fac2 >= 1.0f)) { v2d->scroll |= V2D_SCROLL_HORIZONTAL_FULLR; scrollers->horfull = 1; } @@ -1498,8 +1505,8 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d, short /* vertical scrollers */ if (scroll & V2D_SCROLL_VERTICAL) { /* scroller 'button' extents */ - totsize = BLI_RCT_SIZE_Y(&v2d->tot); - scrollsize = (float)BLI_RCT_SIZE_Y(&vert); + totsize = BLI_rctf_size_y(&v2d->tot); + scrollsize = (float)BLI_rcti_size_y(&vert); if (totsize == 0.0f) totsize = 1.0f; /* avoid divide by zero */ fac1 = (v2d->cur.ymin - v2d->tot.ymin) / totsize; @@ -1528,7 +1535,7 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d, short /* check whether sliders can disappear due to the full-range being used */ if (v2d->keeptot) { - if ((fac1 <= 0.0f) && (fac2 >= 1.0f)) { + if ((fac1 <= 0.0f) && (fac2 >= 1.0f)) { v2d->scroll |= V2D_SCROLL_VERTICAL_FULLR; scrollers->vertfull = 1; } @@ -1547,7 +1554,7 @@ View2DScrollers *UI_view2d_scrollers_calc(const bContext *C, View2D *v2d, short scrollers->grid = UI_view2d_grid_calc(CTX_data_scene(C), v2d, xunits, xclamp, yunits, yclamp, - BLI_RCT_SIZE_X(&hor), BLI_RCT_SIZE_Y(&vert)); + BLI_rcti_size_x(&hor), BLI_rcti_size_y(&vert)); } /* return scrollers */ @@ -1631,7 +1638,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v */ if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 && (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) && - (BLI_RCT_SIZE_X(&slider) > V2D_SCROLLER_HANDLE_SIZE)) + (BLI_rcti_size_x(&slider) > V2D_SCROLLER_HANDLE_SIZE)) { state |= UI_SCROLL_ARROWS; } @@ -1651,11 +1658,11 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v * - fac is x-coordinate to draw to * - dfac is gap between scale markings */ - fac = (grid->startx - v2d->cur.xmin) / BLI_RCT_SIZE_X(&v2d->cur); - fac = (float)hor.xmin + fac * BLI_RCT_SIZE_X(&hor); + fac = (grid->startx - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur); + fac = (float)hor.xmin + fac * BLI_rcti_size_x(&hor); - dfac = grid->dx / BLI_RCT_SIZE_X(&v2d->cur); - dfac = dfac * BLI_RCT_SIZE_X(&hor); + dfac = grid->dx / BLI_rctf_size_x(&v2d->cur); + dfac = dfac * BLI_rcti_size_x(&hor); /* set starting value, and text color */ UI_ThemeColor(TH_TEXT); @@ -1681,7 +1688,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v if (fac < hor.xmin + 10) continue; - switch (vs->xunits) { + switch (vs->xunits) { case V2D_UNIT_FRAMES: /* frames (as whole numbers)*/ scroll_printstr(scene, fac, h, val, grid->powerx, V2D_UNIT_FRAMES, 'h'); break; @@ -1742,7 +1749,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v */ if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 && (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) && - (BLI_RCT_SIZE_Y(&slider) > V2D_SCROLLER_HANDLE_SIZE)) + (BLI_rcti_size_y(&slider) > V2D_SCROLLER_HANDLE_SIZE)) { state |= UI_SCROLL_ARROWS; } @@ -1765,11 +1772,11 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v * - these involve a correction for horizontal scrollbar * NOTE: it's assumed that that scrollbar is there if this is involved! */ - fac = (grid->starty - v2d->cur.ymin) / BLI_RCT_SIZE_Y(&v2d->cur); - fac = vert.ymin + fac * BLI_RCT_SIZE_Y(&vert); + fac = (grid->starty - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur); + fac = vert.ymin + fac * BLI_rcti_size_y(&vert); - dfac = grid->dy / BLI_RCT_SIZE_Y(&v2d->cur); - dfac = dfac * BLI_RCT_SIZE_Y(&vert); + dfac = grid->dy / BLI_rctf_size_y(&v2d->cur); + dfac = dfac * BLI_rcti_size_y(&vert); /* set starting value, and text color */ UI_ThemeColor(TH_TEXT); @@ -1796,7 +1803,7 @@ void UI_view2d_scrollers_draw(const bContext *C, View2D *v2d, View2DScrollers *v BLF_disable_default(BLF_ROTATION); } - } + } } } @@ -1823,7 +1830,9 @@ void UI_view2d_scrollers_free(View2DScrollers *scrollers) * - column, row = the 2d-coordinates (in 2D-view / 'tot' rect space) the cell exists at * - rect = coordinates of the cell (passed as single var instead of 4 separate, as it's more useful this way) */ -void UI_view2d_listview_cell_to_view(View2D *v2d, short columnwidth, short rowheight, float startx, float starty, int column, int row, rctf *rect) +void UI_view2d_listview_cell_to_view(View2D *v2d, short columnwidth, short rowheight, + float startx, float starty, + int column, int row, rctf *rect) { /* sanity checks */ if (ELEM(NULL, v2d, rect)) { @@ -1927,17 +1936,17 @@ void UI_view2d_region_to_view(View2D *v2d, int x, int y, float *r_viewx, float * float div, ofs; if (r_viewx) { - div = (float)BLI_RCT_SIZE_X(&v2d->mask); + div = (float)BLI_rcti_size_x(&v2d->mask); ofs = (float)v2d->mask.xmin; - *r_viewx = v2d->cur.xmin + BLI_RCT_SIZE_X(&v2d->cur) * ((float)x - ofs) / div; + *r_viewx = v2d->cur.xmin + BLI_rctf_size_x(&v2d->cur) * ((float)x - ofs) / div; } if (r_viewy) { - div = (float)BLI_RCT_SIZE_Y(&v2d->mask); + div = (float)BLI_rcti_size_y(&v2d->mask); ofs = (float)v2d->mask.ymin; - *r_viewy = v2d->cur.ymin + BLI_RCT_SIZE_Y(&v2d->cur) * ((float)y - ofs) / div; + *r_viewy = v2d->cur.ymin + BLI_rctf_size_y(&v2d->cur) * ((float)y - ofs) / div; } } @@ -1956,15 +1965,15 @@ void UI_view2d_view_to_region(View2D *v2d, float x, float y, int *regionx, int * *regiony = V2D_IS_CLIPPED; /* express given coordinates as proportional values */ - x = (x - v2d->cur.xmin) / BLI_RCT_SIZE_X(&v2d->cur); - y = (y - v2d->cur.ymin) / BLI_RCT_SIZE_Y(&v2d->cur); + x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur); + y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur); /* check if values are within bounds */ if ((x >= 0.0f) && (x <= 1.0f) && (y >= 0.0f) && (y <= 1.0f)) { if (regionx) - *regionx = (int)(v2d->mask.xmin + x * BLI_RCT_SIZE_X(&v2d->mask)); + *regionx = (int)(v2d->mask.xmin + x * BLI_rcti_size_x(&v2d->mask)); if (regiony) - *regiony = (int)(v2d->mask.ymin + y * BLI_RCT_SIZE_Y(&v2d->mask)); + *regiony = (int)(v2d->mask.ymin + y * BLI_rcti_size_y(&v2d->mask)); } } @@ -1977,12 +1986,12 @@ void UI_view2d_view_to_region(View2D *v2d, float x, float y, int *regionx, int * void UI_view2d_to_region_no_clip(View2D *v2d, float x, float y, int *regionx, int *regiony) { /* step 1: express given coordinates as proportional values */ - x = (x - v2d->cur.xmin) / BLI_RCT_SIZE_X(&v2d->cur); - y = (y - v2d->cur.ymin) / BLI_RCT_SIZE_Y(&v2d->cur); + x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur); + y = (y - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur); /* step 2: convert proportional distances to screen coordinates */ - x = v2d->mask.xmin + x * BLI_RCT_SIZE_X(&v2d->mask); - y = v2d->mask.ymin + y * BLI_RCT_SIZE_Y(&v2d->mask); + x = v2d->mask.xmin + x * BLI_rcti_size_x(&v2d->mask); + y = v2d->mask.ymin + y * BLI_rcti_size_y(&v2d->mask); /* although we don't clamp to lie within region bounds, we must avoid exceeding size of ints */ if (regionx) { @@ -2035,8 +2044,8 @@ View2D *UI_view2d_fromcontext_rwin(const bContext *C) */ void UI_view2d_getscale(View2D *v2d, float *x, float *y) { - if (x) *x = BLI_RCT_SIZE_X(&v2d->mask) / BLI_RCT_SIZE_X(&v2d->cur); - if (y) *y = BLI_RCT_SIZE_Y(&v2d->mask) / BLI_RCT_SIZE_Y(&v2d->cur); + if (x) *x = BLI_rcti_size_x(&v2d->mask) / BLI_rctf_size_x(&v2d->cur); + if (y) *y = BLI_rcti_size_y(&v2d->mask) / BLI_rctf_size_y(&v2d->cur); } /* Check if mouse is within scrollers @@ -2063,7 +2072,7 @@ short UI_view2d_mouse_in_scrollers(const bContext *C, View2D *v2d, int x, int y) } if (scroll & V2D_SCROLL_VERTICAL) { if (IN_2D_VERT_SCROLL(v2d, co)) return 'v'; - } + } /* not found */ return 0; @@ -2142,7 +2151,7 @@ void UI_view2d_text_cache_draw(ARegion *ar) const char *str = (const char *)(v2s + 1); int xofs = 0, yofs; - yofs = ceil(0.5f * (BLI_RCT_SIZE_Y(&v2s->rect) - default_height)); + yofs = ceil(0.5f * (BLI_rcti_size_y(&v2s->rect) - default_height)); if (yofs < 1) yofs = 1; if (col_pack_prev != v2s->col.pack) { diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 99313edc289..48a1f8bf0f3 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -119,10 +119,10 @@ static int view_pan_init(bContext *C, wmOperator *op) vpd->ar = ar; /* calculate translation factor - based on size of view */ - winx = (float)(BLI_RCT_SIZE_X(&ar->winrct) + 1); - winy = (float)(BLI_RCT_SIZE_Y(&ar->winrct) + 1); - vpd->facx = (BLI_RCT_SIZE_X(&v2d->cur)) / winx; - vpd->facy = (BLI_RCT_SIZE_Y(&v2d->cur)) / winy; + winx = (float)(BLI_rcti_size_x(&ar->winrct) + 1); + winy = (float)(BLI_rcti_size_y(&ar->winrct) + 1); + vpd->facx = (BLI_rctf_size_x(&v2d->cur)) / winx; + vpd->facy = (BLI_rctf_size_y(&v2d->cur)) / winy; return 1; } @@ -471,7 +471,7 @@ static int view_scrollup_exec(bContext *C, wmOperator *op) if (RNA_boolean_get(op->ptr, "page")) { ARegion *ar = CTX_wm_region(C); - RNA_int_set(op->ptr, "deltay", BLI_RCT_SIZE_Y(&ar->v2d.mask)); + RNA_int_set(op->ptr, "deltay", BLI_rcti_size_y(&ar->v2d.mask)); } /* apply movement, then we're done */ @@ -590,12 +590,12 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op) facy = RNA_float_get(op->ptr, "zoomfacy"); if (facx >= 0.0f) { - dx = BLI_RCT_SIZE_X(&v2d->cur) * facx; - dy = BLI_RCT_SIZE_Y(&v2d->cur) * facy; + dx = BLI_rctf_size_x(&v2d->cur) * facx; + dy = BLI_rctf_size_y(&v2d->cur) * facy; } else { - dx = (BLI_RCT_SIZE_X(&v2d->cur) / (1.0f + 2.0f * facx)) * facx; - dy = (BLI_RCT_SIZE_Y(&v2d->cur) / (1.0f + 2.0f * facy)) * facy; + dx = (BLI_rctf_size_x(&v2d->cur) / (1.0f + 2.0f * facx)) * facx; + dy = (BLI_rctf_size_y(&v2d->cur) / (1.0f + 2.0f * facy)) * facy; } /* only resize view on an axis if change is allowed */ @@ -611,7 +611,7 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op) } else { if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { - float mval_fac = (vzd->mx_2d - v2d->cur.xmin) / BLI_RCT_SIZE_X(&v2d->cur); + float mval_fac = (vzd->mx_2d - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur); float mval_faci = 1.0f - mval_fac; float ofs = (mval_fac * dx) - (mval_faci * dx); @@ -636,13 +636,13 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op) } else { if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { - float mval_fac = (vzd->my_2d - v2d->cur.ymin) / BLI_RCT_SIZE_Y(&v2d->cur); + float mval_fac = (vzd->my_2d - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur); float mval_faci = 1.0f - mval_fac; float ofs = (mval_fac * dy) - (mval_faci * dy); v2d->cur.ymin += ofs + dy; v2d->cur.ymax += ofs - dy; - } + } else { v2d->cur.ymin += dy; v2d->cur.ymax -= dy; @@ -827,6 +827,11 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op) dx = RNA_float_get(op->ptr, "deltax"); dy = RNA_float_get(op->ptr, "deltay"); + if (U.uiflag & USER_ZOOM_INVERT) { + dx *= -1; + dy *= -1; + } + /* continuous zoom shouldn't move that fast... */ if (U.viewzoom == USER_ZOOM_CONT) { // XXX store this setting as RNA prop? double time = PIL_check_seconds_timer(); @@ -845,7 +850,7 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op) } else { if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { - float mval_fac = (vzd->mx_2d - v2d->cur.xmin) / BLI_RCT_SIZE_X(&v2d->cur); + float mval_fac = (vzd->mx_2d - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur); float mval_faci = 1.0f - mval_fac; float ofs = (mval_fac * dx) - (mval_faci * dx); @@ -864,7 +869,7 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op) } else { if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { - float mval_fac = (vzd->my_2d - v2d->cur.ymin) / BLI_RCT_SIZE_Y(&v2d->cur); + float mval_fac = (vzd->my_2d - v2d->cur.ymin) / BLI_rctf_size_y(&v2d->cur); float mval_faci = 1.0f - mval_fac; float ofs = (mval_fac * dy) - (mval_faci * dy); @@ -942,8 +947,8 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event) * with magnify information that is stored in x axis */ fac = 0.01f * (event->x - event->prevx); - dx = fac * BLI_RCT_SIZE_X(&v2d->cur) / 10.0f; - dy = fac * BLI_RCT_SIZE_Y(&v2d->cur) / 10.0f; + dx = fac * BLI_rctf_size_x(&v2d->cur) / 10.0f; + dy = fac * BLI_rctf_size_y(&v2d->cur) / 10.0f; RNA_float_set(op->ptr, "deltax", dx); RNA_float_set(op->ptr, "deltay", dy); @@ -951,7 +956,7 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event) view_zoomdrag_apply(C, op); view_zoomdrag_exit(C, op); return OPERATOR_FINISHED; - } + } /* set initial settings */ vzd->lastx = event->x; @@ -1009,14 +1014,14 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, wmEvent *event) float dist; /* x-axis transform */ - dist = BLI_RCT_SIZE_X(&v2d->mask) / 2.0f; + dist = BLI_rcti_size_x(&v2d->mask) / 2.0f; dx = 1.0f - (fabsf(vzd->lastx - dist) + 2.0f) / (fabsf(event->x - dist) + 2.0f); - dx *= 0.5f * BLI_RCT_SIZE_X(&v2d->cur); + dx *= 0.5f * BLI_rctf_size_x(&v2d->cur); /* y-axis transform */ - dist = BLI_RCT_SIZE_Y(&v2d->mask) / 2.0f; + dist = BLI_rcti_size_y(&v2d->mask) / 2.0f; dy = 1.0f - (fabsf(vzd->lasty - dist) + 2.0f) / (fabsf(event->y - dist) + 2.0f); - dy *= 0.5f * BLI_RCT_SIZE_Y(&v2d->cur); + dy *= 0.5f * BLI_rctf_size_y(&v2d->cur); } else { /* 'continuous' or 'dolly' */ @@ -1024,11 +1029,11 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, wmEvent *event) /* x-axis transform */ fac = 0.01f * (event->x - vzd->lastx); - dx = fac * BLI_RCT_SIZE_X(&v2d->cur); + dx = fac * BLI_rctf_size_x(&v2d->cur); /* y-axis transform */ fac = 0.01f * (event->y - vzd->lasty); - dy = fac * BLI_RCT_SIZE_Y(&v2d->cur); + dy = fac * BLI_rctf_size_y(&v2d->cur); #if 0 /* continuous zoom shouldn't move that fast... */ if (U.viewzoom == USER_ZOOM_CONT) { // XXX store this setting as RNA prop? @@ -1046,6 +1051,7 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, wmEvent *event) /* set transform amount, and add current deltas to stored total delta (for redo) */ RNA_float_set(op->ptr, "deltax", dx); RNA_float_set(op->ptr, "deltay", dy); + vzd->dx += dx; vzd->dy += dy; @@ -1059,7 +1065,7 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, wmEvent *event) /* apply zooming */ view_zoomdrag_apply(C, op); - } + } else if (event->type == vzd->invoke_event || event->type == ESCKEY) { if (event->val == KM_RELEASE) { @@ -1161,17 +1167,17 @@ static int view_borderzoom_exec(bContext *C, wmOperator *op) /* TODO: is this zoom factor calculation valid? It seems to produce same results everytime... */ if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0) { - size = BLI_RCT_SIZE_X(&cur_new); - zoom = size / BLI_RCT_SIZE_X(&rect); - center = BLI_RCT_CENTER_X(&cur_new); + size = BLI_rctf_size_x(&cur_new); + zoom = size / BLI_rctf_size_x(&rect); + center = BLI_rctf_cent_x(&cur_new); cur_new.xmin = center - (size * zoom); cur_new.xmax = center + (size * zoom); } if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0) { - size = BLI_RCT_SIZE_Y(&cur_new); - zoom = size / BLI_RCT_SIZE_Y(&rect); - center = BLI_RCT_CENTER_Y(&cur_new); + size = BLI_rctf_size_y(&cur_new); + zoom = size / BLI_rctf_size_y(&rect); + center = BLI_rctf_cent_y(&cur_new); cur_new.ymin = center - (size * zoom); cur_new.ymax = center + (size * zoom); @@ -1221,14 +1227,14 @@ struct SmoothView2DStore { */ static float smooth_view_rect_to_fac(const rctf *rect_a, const rctf *rect_b) { - float size_a[2] = {BLI_RCT_SIZE_X(rect_a), - BLI_RCT_SIZE_Y(rect_a)}; - float size_b[2] = {BLI_RCT_SIZE_X(rect_b), - BLI_RCT_SIZE_Y(rect_b)}; - float cent_a[2] = {BLI_RCT_CENTER_X(rect_a), - BLI_RCT_CENTER_Y(rect_a)}; - float cent_b[2] = {BLI_RCT_CENTER_X(rect_b), - BLI_RCT_CENTER_Y(rect_b)}; + float size_a[2] = {BLI_rctf_size_x(rect_a), + BLI_rctf_size_y(rect_a)}; + float size_b[2] = {BLI_rctf_size_x(rect_b), + BLI_rctf_size_y(rect_b)}; + float cent_a[2] = {BLI_rctf_cent_x(rect_a), + BLI_rctf_cent_y(rect_a)}; + float cent_b[2] = {BLI_rctf_cent_x(rect_b), + BLI_rctf_cent_y(rect_b)}; float fac_max = 0.0f; float tfac; @@ -1237,16 +1243,16 @@ static float smooth_view_rect_to_fac(const rctf *rect_a, const rctf *rect_b) for (i = 0; i < 2; i++) { /* axis translation normalized to scale */ - tfac = fabsf(cent_a[i] - cent_b[i]) / minf(size_a[i], size_b[i]); - fac_max = maxf(fac_max, tfac); + tfac = fabsf(cent_a[i] - cent_b[i]) / min_ff(size_a[i], size_b[i]); + fac_max = max_ff(fac_max, tfac); if (fac_max >= 1.0f) break; /* axis scale difference, x2 so doubling or half gives 1.0f */ - tfac = (1.0f - (minf(size_a[i], size_b[i]) / maxf(size_a[i], size_b[i]))) * 2.0f; - fac_max = maxf(fac_max, tfac); + tfac = (1.0f - (min_ff(size_a[i], size_b[i]) / max_ff(size_a[i], size_b[i]))) * 2.0f; + fac_max = max_ff(fac_max, tfac); if (fac_max >= 1.0f) break; } - return minf(fac_max, 1.0f); + return min_ff(fac_max, 1.0f); } /* will start timer if appropriate */ @@ -1273,11 +1279,10 @@ void UI_view2d_smooth_view(bContext *C, ARegion *ar, } if (C && U.smooth_viewtx && fac > FLT_EPSILON) { - int changed = 0; /* zero means no difference */ + int changed = FALSE; if (BLI_rctf_compare(&sms.new_cur, &v2d->cur, FLT_EPSILON) == FALSE) - changed = 1; - changed=1; + changed = TRUE; /* The new view is different from the old one * so animate the view */ @@ -1464,7 +1469,7 @@ static short mouse_in_scroller_handle(int mouse, int sc_min, int sc_max, int sh_ else if (in_min) return SCROLLHANDLE_MIN; else if (out_min) - return SCROLLHANDLE_MIN_OUTSIDE; + return SCROLLHANDLE_MIN_OUTSIDE; else if (out_max) return SCROLLHANDLE_MAX_OUTSIDE; @@ -1479,6 +1484,7 @@ static void scroller_activate_init(bContext *C, wmOperator *op, wmEvent *event, View2DScrollers *scrollers; ARegion *ar = CTX_wm_region(C); View2D *v2d = &ar->v2d; + rctf tot_cur_union; float mask_size; /* set custom-data for operator */ @@ -1498,14 +1504,20 @@ static void scroller_activate_init(bContext *C, wmOperator *op, wmEvent *event, */ scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY); + /* use a union of 'cur' & 'tot' incase the current view is far outside 'tot'. + * In this cases moving the scroll bars has far too little effect and the view can get stuck [#31476] */ + tot_cur_union = v2d->tot; + BLI_rctf_union(&tot_cur_union, &v2d->cur); if (in_scroller == 'h') { /* horizontal scroller - calculate adjustment factor first */ - mask_size = (float)BLI_RCT_SIZE_X(&v2d->hor); - vsm->fac = BLI_RCT_SIZE_X(&v2d->tot) / mask_size; + mask_size = (float)BLI_rcti_size_x(&v2d->hor); + vsm->fac = BLI_rctf_size_x(&tot_cur_union) / mask_size; /* get 'zone' (i.e. which part of scroller is activated) */ - vsm->zone = mouse_in_scroller_handle(event->mval[0], v2d->hor.xmin, v2d->hor.xmax, scrollers->hor_min, scrollers->hor_max); + vsm->zone = mouse_in_scroller_handle(event->mval[0], + v2d->hor.xmin, v2d->hor.xmax, + scrollers->hor_min, scrollers->hor_max); if ((v2d->keepzoom & V2D_LOCKZOOM_X) && ELEM(vsm->zone, SCROLLHANDLE_MIN, SCROLLHANDLE_MAX)) { /* default to scroll, as handles not usable */ @@ -1517,11 +1529,13 @@ static void scroller_activate_init(bContext *C, wmOperator *op, wmEvent *event, } else { /* vertical scroller - calculate adjustment factor first */ - mask_size = (float)BLI_RCT_SIZE_Y(&v2d->vert); - vsm->fac = BLI_RCT_SIZE_Y(&v2d->tot) / mask_size; + mask_size = (float)BLI_rcti_size_y(&v2d->vert); + vsm->fac = BLI_rctf_size_y(&tot_cur_union) / mask_size; /* get 'zone' (i.e. which part of scroller is activated) */ - vsm->zone = mouse_in_scroller_handle(event->mval[1], v2d->vert.ymin, v2d->vert.ymax, scrollers->vert_min, scrollers->vert_max); + vsm->zone = mouse_in_scroller_handle(event->mval[1], + v2d->vert.ymin, v2d->vert.ymax, + scrollers->vert_min, scrollers->vert_max); if ((v2d->keepzoom & V2D_LOCKZOOM_Y) && ELEM(vsm->zone, SCROLLHANDLE_MIN, SCROLLHANDLE_MAX)) { /* default to scroll, as handles not usable */ @@ -1529,7 +1543,7 @@ static void scroller_activate_init(bContext *C, wmOperator *op, wmEvent *event, } vsm->scrollbarwidth = scrollers->vert_max - scrollers->vert_min; - vsm->scrollbar_orig = ((scrollers->vert_max + scrollers->vert_min) / 2) + +ar->winrct.ymin; + vsm->scrollbar_orig = ((scrollers->vert_max + scrollers->vert_min) / 2) + ar->winrct.ymin; } UI_view2d_scrollers_free(scrollers); @@ -1737,7 +1751,7 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, wmEvent *event) /* can't catch this event for ourselves, so let it go to someone else? */ return OPERATOR_PASS_THROUGH; - } + } } /* zone is also inappropriate if scroller is not visible... */ @@ -1798,8 +1812,8 @@ static int reset_exec(bContext *C, wmOperator *UNUSED(op)) int winx, winy; /* zoom 1.0 */ - winx = (float)(BLI_RCT_SIZE_X(&v2d->mask) + 1); - winy = (float)(BLI_RCT_SIZE_Y(&v2d->mask) + 1); + winx = (float)(BLI_rcti_size_x(&v2d->mask) + 1); + winy = (float)(BLI_rcti_size_y(&v2d->mask) + 1); v2d->cur.xmax = v2d->cur.xmin + winx; v2d->cur.ymax = v2d->cur.ymin + winy; diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index 0e6b8f77528..ba93206e63a 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -54,6 +54,8 @@ #include "../../collada/collada.h" +#include "io_collada.h" + static int wm_collada_export_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { if (!RNA_struct_property_is_set(op->ptr, "filepath")) { @@ -121,32 +123,32 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) /* get editmode results */ ED_object_exit_editmode(C, 0); /* 0 = does not exit editmode */ - if (collada_export( - CTX_data_scene(C), - filepath, - apply_modifiers, - export_mesh_type, - selected, - include_children, - include_armatures, - deform_bones_only, + if (collada_export(CTX_data_scene(C), + filepath, + apply_modifiers, + export_mesh_type, + selected, + include_children, + include_armatures, + deform_bones_only, - active_uv_only, - include_uv_textures, - include_material_textures, - use_texture_copies, + active_uv_only, + include_uv_textures, + include_material_textures, + use_texture_copies, - use_object_instantiation, - sort_by_name, - second_life)) { + use_object_instantiation, + sort_by_name, + second_life)) { return OPERATOR_FINISHED; } else { + BKE_report(op->reports, RPT_WARNING, "Export file not created"); return OPERATOR_CANCELLED; } } -void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) +static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) { uiLayout *box, *row, *col, *split; @@ -233,7 +235,7 @@ void WM_OT_collada_export(wmOperatorType *ot) ot->name = "Export COLLADA"; ot->description = "Save a Collada file"; ot->idname = "WM_OT_collada_export"; - + ot->invoke = wm_collada_export_invoke; ot->exec = wm_collada_export_exec; ot->poll = WM_operator_winactive; @@ -241,7 +243,7 @@ void WM_OT_collada_export(wmOperatorType *ot) ot->flag |= OPTYPE_PRESET; ot->ui = wm_collada_export_draw; - + WM_operator_properties_filesel(ot, FOLDERFILE | COLLADAFILE, FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY); @@ -296,7 +298,7 @@ void WM_OT_collada_export(wmOperatorType *ot) static int wm_collada_import_exec(bContext *C, wmOperator *op) { char filename[FILE_MAX]; - + if (!RNA_struct_property_is_set(op->ptr, "filepath")) { BKE_report(op->reports, RPT_ERROR, "No filename given"); return OPERATOR_CANCELLED; @@ -304,9 +306,9 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op) RNA_string_get(op->ptr, "filepath", filename); if (collada_import(C, filename)) return OPERATOR_FINISHED; - - BKE_report(op->reports, RPT_ERROR, "Errors found during parsing COLLADA document. Please see console for error log."); - + + BKE_report(op->reports, RPT_ERROR, "Errors found during parsing COLLADA document (see console for details)"); + return OPERATOR_FINISHED; } @@ -315,11 +317,11 @@ void WM_OT_collada_import(wmOperatorType *ot) ot->name = "Import COLLADA"; ot->description = "Load a Collada file"; ot->idname = "WM_OT_collada_import"; - + ot->invoke = WM_operator_filesel; ot->exec = wm_collada_import_exec; ot->poll = WM_operator_winactive; - + WM_operator_properties_filesel(ot, FOLDERFILE | COLLADAFILE, FILE_BLENDER, FILE_OPENFILE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY); } diff --git a/source/blender/editors/mask/CMakeLists.txt b/source/blender/editors/mask/CMakeLists.txt index 57be5a2234a..25fb9cb6430 100644 --- a/source/blender/editors/mask/CMakeLists.txt +++ b/source/blender/editors/mask/CMakeLists.txt @@ -30,10 +30,10 @@ set(INC ../../makesrna ../../windowmanager ../../../../intern/guardedalloc - ${GLEW_INCLUDE_PATH} ) set(INC_SYS + ${GLEW_INCLUDE_PATH} ) set(SRC diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index 7fe1ac09df6..e43c8a2b53b 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -46,6 +46,7 @@ #include "WM_types.h" #include "ED_mask.h" /* own include */ +#include "ED_screen.h" #include "RNA_access.h" #include "RNA_define.h" @@ -64,7 +65,7 @@ static int find_nearest_diff_point(const bContext *C, Mask *mask, const float no MaskLayer *masklay, *point_masklay; MaskSpline *point_spline; MaskSplinePoint *point = NULL; - float dist, co[2]; + float dist = FLT_MAX, co[2]; int width, height; float u; float scalex, scaley; @@ -97,7 +98,7 @@ static int find_nearest_diff_point(const bContext *C, Mask *mask, const float no &tot_diff_point); if (diff_points) { - int i, tot_point; + int j, tot_point; unsigned int tot_feather_point; float *feather_points = NULL, *points; @@ -114,26 +115,26 @@ static int find_nearest_diff_point(const bContext *C, Mask *mask, const float no tot_point = tot_diff_point; } - for (i = 0; i < tot_point - 1; i++) { + for (j = 0; j < tot_point - 1; j++) { float cur_dist, a[2], b[2]; - a[0] = points[2 * i] * scalex; - a[1] = points[2 * i + 1] * scaley; + a[0] = points[2 * j] * scalex; + a[1] = points[2 * j + 1] * scaley; - b[0] = points[2 * i + 2] * scalex; - b[1] = points[2 * i + 3] * scaley; + b[0] = points[2 * j + 2] * scalex; + b[1] = points[2 * j + 3] * scaley; cur_dist = dist_to_line_segment_v2(co, a, b); - if (point == NULL || cur_dist < dist) { + if (cur_dist < dist) { if (tangent) - sub_v2_v2v2(tangent, &diff_points[2 * i + 2], &diff_points[2 * i]); + sub_v2_v2v2(tangent, &diff_points[2 * j + 2], &diff_points[2 * j]); point_masklay = masklay; point_spline = spline; point = use_deform ? &spline->points[(cur_point - spline->points_deform)] : cur_point; dist = cur_dist; - u = (float)i / tot_point; + u = (float)j / tot_point; } } @@ -562,6 +563,11 @@ static int add_vertex_exec(bContext *C, wmOperator *op) float co[2]; + if (mask == NULL) { + /* if there's no active mask, create one */ + mask = ED_mask_new(C, NULL); + } + masklay = BKE_mask_layer_active(mask); if (masklay && masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { @@ -647,7 +653,7 @@ void MASK_OT_add_vertex(wmOperatorType *ot) /* api callbacks */ ot->exec = add_vertex_exec; ot->invoke = add_vertex_invoke; - ot->poll = ED_maskedit_mask_poll; + ot->poll = ED_operator_mask; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 655458bd4cb..74cdf4c2a11 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -20,6 +20,7 @@ * * * Contributor(s): Blender Foundation, + * Campbell Barton, * Sergey Sharybin * * ***** END GPL LICENSE BLOCK ***** @@ -41,7 +42,9 @@ #include "DNA_mask_types.h" #include "DNA_screen_types.h" #include "DNA_object_types.h" /* SELECT */ +#include "DNA_space_types.h" +#include "ED_clip.h" #include "ED_mask.h" /* own include */ #include "ED_space_api.h" #include "BIF_gl.h" @@ -120,13 +123,22 @@ static void draw_spline_parents(MaskLayer *UNUSED(masklay), MaskSpline *spline) } #endif +static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], float co[2]) +{ + BKE_mask_coord_to_movieclip(sc->clip, &sc->user, r_co, co); + ED_clip_point_undistorted_pos(sc, r_co, r_co); + BKE_mask_coord_from_movieclip(sc->clip, &sc->user, r_co, r_co); +} + /* return non-zero if spline is selected */ -static void draw_spline_points(MaskLayer *masklay, MaskSpline *spline, +static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline *spline, const char UNUSED(draw_flag), const char draw_type) { const int is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0; unsigned char rgb_spline[4]; MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + SpaceClip *sc = CTX_wm_space_clip(C); + int undistort = FALSE; int i, hsize, tot_feather_point; float (*feather_points)[2], (*fp)[2]; @@ -134,6 +146,9 @@ static void draw_spline_points(MaskLayer *masklay, MaskSpline *spline, if (!spline->tot_point) return; + if (sc) + undistort = sc->clip && sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT; + /* TODO, add this to sequence editor */ hsize = 4; /* UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE); */ @@ -151,8 +166,14 @@ static void draw_spline_points(MaskLayer *masklay, MaskSpline *spline, int j; for (j = 0; j < point->tot_uw + 1; j++) { + float feather_point[2]; int sel = FALSE; + copy_v2_v2(feather_point, *fp); + + if (undistort) + mask_point_undistort_pos(sc, feather_point, feather_point); + if (j == 0) { sel = MASKPOINT_ISSEL_ANY(point); } @@ -171,7 +192,7 @@ static void draw_spline_points(MaskLayer *masklay, MaskSpline *spline, } glBegin(GL_POINTS); - glVertex2fv(*fp); + glVertex2fv(feather_point); glEnd(); fp++; @@ -188,11 +209,17 @@ static void draw_spline_points(MaskLayer *masklay, MaskSpline *spline, BezTriple *bezt = &point_deform->bezt; float handle[2]; - float *vert = bezt->vec[1]; + float vert[2]; int has_handle = BKE_mask_point_has_handle(point); + copy_v2_v2(vert, bezt->vec[1]); BKE_mask_point_handle(point_deform, handle); + if (undistort) { + mask_point_undistort_pos(sc, vert, vert); + mask_point_undistort_pos(sc, handle, handle); + } + /* draw handle segment */ if (has_handle) { @@ -202,16 +229,16 @@ static void draw_spline_points(MaskLayer *masklay, MaskSpline *spline, glLineWidth(3); glColor4ubv(rgb_gray); glBegin(GL_LINES); - glVertex3fv(vert); - glVertex3fv(handle); + glVertex2fv(vert); + glVertex2fv(handle); glEnd(); glLineWidth(1); } glColor3ubv(rgb_spline); glBegin(GL_LINES); - glVertex3fv(vert); - glVertex3fv(handle); + glVertex2fv(vert); + glVertex2fv(handle); glEnd(); } @@ -226,7 +253,7 @@ static void draw_spline_points(MaskLayer *masklay, MaskSpline *spline, glColor3f(0.5f, 0.5f, 0.0f); glBegin(GL_POINTS); - glVertex3fv(vert); + glVertex2fv(vert); glEnd(); /* draw handle points */ @@ -242,7 +269,7 @@ static void draw_spline_points(MaskLayer *masklay, MaskSpline *spline, } glBegin(GL_POINTS); - glVertex3fv(handle); + glVertex2fv(handle); glEnd(); } } @@ -265,7 +292,7 @@ static void mask_color_active_tint(unsigned char r_rgb[4], const unsigned char r } } -static void mask_draw_curve_type(MaskSpline *spline, float (*points)[2], int tot_point, +static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*orig_points)[2], int tot_point, const short is_feather, const short is_smooth, const short is_active, const unsigned char rgb_spline[4], const char draw_type) { @@ -273,6 +300,22 @@ static void mask_draw_curve_type(MaskSpline *spline, float (*points)[2], int tot const unsigned char rgb_black[4] = {0x00, 0x00, 0x00, 0xff}; // const unsigned char rgb_white[4] = {0xff, 0xff, 0xff, 0xff}; unsigned char rgb_tmp[4]; + SpaceClip *sc = CTX_wm_space_clip(C); + float (*points)[2] = orig_points; + + if (sc) { + int undistort = sc->clip && sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT; + + if (undistort) { + int i; + + points = MEM_callocN(2 * tot_point * sizeof(float), "undistorthed mask curve"); + + for (i = 0; i < tot_point; i++) { + mask_point_undistort_pos(sc, points[i], orig_points[i]); + } + } + } glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, points); @@ -347,8 +390,6 @@ static void mask_draw_curve_type(MaskSpline *spline, float (*points)[2], int tot glVertexPointer(2, GL_FLOAT, 0, points); glDrawArrays(draw_method, 0, tot_point); - glDrawArrays(draw_method, 0, tot_point); - if (is_smooth == FALSE && is_feather) { glDisable(GL_BLEND); } @@ -358,14 +399,16 @@ static void mask_draw_curve_type(MaskSpline *spline, float (*points)[2], int tot glDisableClientState(GL_VERTEX_ARRAY); + if (points != orig_points) + MEM_freeN(points); } -static void draw_spline_curve(MaskLayer *masklay, MaskSpline *spline, +static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline *spline, const char draw_flag, const char draw_type, const short is_active, int width, int height) { - const unsigned int resol = maxi(BKE_mask_spline_feather_resolution(spline, width, height), + const unsigned int resol = max_ii(BKE_mask_spline_feather_resolution(spline, width, height), BKE_mask_spline_resolution(spline, width, height)); unsigned char rgb_tmp[4]; @@ -395,7 +438,7 @@ static void draw_spline_curve(MaskLayer *masklay, MaskSpline *spline, /* draw feather */ mask_spline_feather_color_get(masklay, spline, is_spline_sel, rgb_tmp); - mask_draw_curve_type(spline, feather_points, tot_feather_point, + mask_draw_curve_type(C, spline, feather_points, tot_feather_point, TRUE, is_smooth, is_active, rgb_tmp, draw_type); @@ -414,7 +457,7 @@ static void draw_spline_curve(MaskLayer *masklay, MaskSpline *spline, } /* same as above */ - mask_draw_curve_type(spline, feather_points, tot_feather_point, + mask_draw_curve_type(C, spline, feather_points, tot_feather_point, TRUE, is_smooth, is_active, rgb_tmp, draw_type); } @@ -423,7 +466,7 @@ static void draw_spline_curve(MaskLayer *masklay, MaskSpline *spline, /* draw main curve */ mask_spline_color_get(masklay, spline, is_spline_sel, rgb_tmp); - mask_draw_curve_type(spline, diff_points, tot_diff_point, + mask_draw_curve_type(C, spline, diff_points, tot_diff_point, FALSE, is_smooth, is_active, rgb_tmp, draw_type); MEM_freeN(diff_points); @@ -436,7 +479,7 @@ static void draw_spline_curve(MaskLayer *masklay, MaskSpline *spline, (void)draw_type; } -static void draw_masklays(Mask *mask, const char draw_flag, const char draw_type, +static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, const char draw_type, int width, int height) { MaskLayer *masklay; @@ -453,13 +496,13 @@ static void draw_masklays(Mask *mask, const char draw_flag, const char draw_type for (spline = masklay->splines.first; spline; spline = spline->next) { /* draw curve itself first... */ - draw_spline_curve(masklay, spline, draw_flag, draw_type, is_active, width, height); + draw_spline_curve(C, masklay, spline, draw_flag, draw_type, is_active, width, height); // draw_spline_parents(masklay, spline); if (!(masklay->restrictflag & MASK_RESTRICT_SELECT)) { /* ...and then handles over the curve so they're nicely visible */ - draw_spline_points(masklay, spline, draw_flag, draw_type); + draw_spline_points(C, masklay, spline, draw_flag, draw_type); } /* show undeform for testing */ @@ -467,9 +510,9 @@ static void draw_masklays(Mask *mask, const char draw_flag, const char draw_type void *back = spline->points_deform; spline->points_deform = NULL; - draw_spline_curve(masklay, spline, draw_flag, draw_type, is_active, width, height); + draw_spline_curve(C, masklay, spline, draw_flag, draw_type, is_active, width, height); // draw_spline_parents(masklay, spline); - draw_spline_points(masklay, spline, draw_flag, draw_type); + draw_spline_points(C, masklay, spline, draw_flag, draw_type); spline->points_deform = back; } } @@ -489,7 +532,7 @@ void ED_mask_draw(const bContext *C, ED_mask_get_size(sa, &width, &height); - draw_masklays(mask, draw_flag, draw_type, width, height); + draw_masklays(C, mask, draw_flag, draw_type, width, height); } /* sets up the opengl context. @@ -500,7 +543,7 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar, const float aspx, const float aspy, const short do_scale_applied, const short do_post_draw, float stabmat[4][4], /* optional - only used by clip */ - const bContext *C /* optional - only used when do_post_draw is set */ + const bContext *C /* optional - only used when do_post_draw is set or called from clip editor */ ) { struct View2D *v2d = &ar->v2d; @@ -520,12 +563,12 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar, UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y); - /* w = BLI_RCT_SIZE_X(&v2d->tot); */ - /* h = BLI_RCT_SIZE_Y(&v2d->tot);/*/ + /* w = BLI_rctf_size_x(&v2d->tot); */ + /* h = BLI_rctf_size_y(&v2d->tot);/*/ - zoomx = (float)(BLI_RCT_SIZE_X(&ar->winrct) + 1) / (float)(BLI_RCT_SIZE_X(&ar->v2d.cur)); - zoomy = (float)(BLI_RCT_SIZE_Y(&ar->winrct) + 1) / (float)(BLI_RCT_SIZE_Y(&ar->v2d.cur)); + zoomx = (float)(BLI_rcti_size_x(&ar->winrct) + 1) / BLI_rctf_size_x(&ar->v2d.cur); + zoomy = (float)(BLI_rcti_size_y(&ar->winrct) + 1) / BLI_rctf_size_y(&ar->v2d.cur); if (do_scale_applied) { zoomx /= width; @@ -536,7 +579,7 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar, y += v2d->tot.ymin * zoomy; /* frame the image */ - maxdim = maxf(width, height); + maxdim = max_ff(width, height); if (width == height) { xofs = yofs = 0; } @@ -559,7 +602,7 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar, } /* draw! */ - draw_masklays(mask, draw_flag, draw_type, width, height); + draw_masklays(C, mask, draw_flag, draw_type, width, height); if (do_post_draw) { ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index 39a19bdaa5f..18384ad9de4 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -436,8 +436,8 @@ void ED_keymap_mask(wmKeyConfig *keyconf) ED_keymap_proportional_maskmode(keyconf, keymap); /* geometry */ - WM_keymap_add_item(keymap, "MASK_OT_add_vertex_slide", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "MASK_OT_add_feather_vertex_slide", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "MASK_OT_add_vertex_slide", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "MASK_OT_add_feather_vertex_slide", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "MASK_OT_delete", XKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "MASK_OT_delete", DELKEY, KM_PRESS, 0, 0); @@ -486,7 +486,7 @@ void ED_keymap_mask(wmKeyConfig *keyconf) /* shape */ WM_keymap_add_item(keymap, "MASK_OT_cyclic_toggle", CKEY, KM_PRESS, KM_ALT, 0); - WM_keymap_add_item(keymap, "MASK_OT_slide_point", LEFTMOUSE, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "MASK_OT_slide_point", ACTIONMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "MASK_OT_handle_type_set", VKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "MASK_OT_normals_make_consistent", NKEY, KM_PRESS, KM_CTRL, 0); // WM_keymap_add_item(keymap, "MASK_OT_feather_weight_clear", SKEY, KM_PRESS, KM_ALT, 0); diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index ffd4afca182..fcfcfb237e9 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -33,6 +33,7 @@ #define __MASK_INTERN_H__ struct bContext; +struct Mask; struct wmEvent; struct wmOperatorType; @@ -43,6 +44,8 @@ void MASK_OT_add_vertex(struct wmOperatorType *ot); void MASK_OT_add_feather_vertex(struct wmOperatorType *ot); /* mask_ops.c */ +struct Mask *ED_mask_new(struct bContext *C, const char *name); + void MASK_OT_new(struct wmOperatorType *ot); void MASK_OT_layer_new(struct wmOperatorType *ot); void MASK_OT_layer_remove(struct wmOperatorType *ot); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 88fbb91edfb..35f85f3faee 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -258,13 +258,10 @@ int ED_mask_feather_find_nearest(const bContext *C, Mask *mask, float normal_co[ /******************** create new mask *********************/ -static int mask_new_exec(bContext *C, wmOperator *op) +Mask *ED_mask_new(bContext *C, const char *name) { ScrArea *sa = CTX_wm_area(C); Mask *mask; - char name[MAX_ID_NAME - 2]; - - RNA_string_get(op->ptr, "name", name); mask = BKE_mask_new(name); @@ -290,6 +287,17 @@ static int mask_new_exec(bContext *C, wmOperator *op) } } + return mask; +} + +static int mask_new_exec(bContext *C, wmOperator *op) +{ + char name[MAX_ID_NAME - 2]; + + RNA_string_get(op->ptr, "name", name); + + ED_mask_new(C, name); + return OPERATOR_FINISHED; } @@ -483,15 +491,15 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) customdata->uw = uw; if (uw) { - float co[2]; + float co_uw[2]; float weight_scalar = BKE_mask_point_weight_scalar(spline, point, uw->u); customdata->weight = uw->w; customdata->weight_scalar = weight_scalar; - BKE_mask_point_segment_co(spline, point, uw->u, co); + BKE_mask_point_segment_co(spline, point, uw->u, co_uw); BKE_mask_point_normal(spline, point, uw->u, customdata->no); - madd_v2_v2v2fl(customdata->feather, co, customdata->no, uw->w * weight_scalar); + madd_v2_v2v2fl(customdata->feather, co_uw, customdata->no, uw->w * weight_scalar); } else { BezTriple *bezt = &point->bezt; diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index ace427f65ab..cd1a47754f8 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -34,6 +34,7 @@ #include "BLI_utildefines.h" #include "BLI_rect.h" #include "BLI_lasso.h" +#include "BLI_math.h" #include "BKE_context.h" #include "BKE_mask.h" @@ -148,7 +149,7 @@ void ED_mask_select_toggle_all(Mask *mask, int action) } if (action == SEL_INVERT) { - /* we don't have generic functons for this, its restricted to this operator + /* we don't have generic functions for this, its restricted to this operator * if one day we need to re-use such functionality, they can be split out */ MaskSpline *spline; @@ -485,7 +486,7 @@ void MASK_OT_select_border(wmOperatorType *ot) WM_operator_properties_gesture_border(ot, TRUE); } -static int do_lasso_select_mask(bContext *C, int mcords[][2], short moves, short select) +static int do_lasso_select_mask(bContext *C, const int mcords[][2], short moves, short select) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); @@ -549,7 +550,7 @@ static int do_lasso_select_mask(bContext *C, int mcords[][2], short moves, short static int clip_lasso_select_exec(bContext *C, wmOperator *op) { int mcords_tot; - int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); if (mcords) { short select; @@ -557,7 +558,7 @@ static int clip_lasso_select_exec(bContext *C, wmOperator *op) select = !RNA_boolean_get(op->ptr, "deselect"); do_lasso_select_mask(C, mcords, mcords_tot, select); - MEM_freeN(mcords); + MEM_freeN((void *)mcords); return OPERATOR_FINISHED; } @@ -622,7 +623,7 @@ static int circle_select_exec(bContext *C, wmOperator *op) /* compute ellipse and position in unified coordinates */ ED_mask_get_size(sa, &width, &height); ED_mask_zoom(sa, ar, &zoomx, &zoomy); - width = height = MAX2(width, height); + width = height = max_ii(width, height); ellipse[0] = width * zoomx / radius; ellipse[1] = height * zoomy / radius; diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt index 246c323213c..c51d2cfb2e5 100644 --- a/source/blender/editors/mesh/CMakeLists.txt +++ b/source/blender/editors/mesh/CMakeLists.txt @@ -21,6 +21,7 @@ set(INC ../include ../uvedit + ../../blenfont ../../blenkernel ../../blenlib ../../blenloader @@ -68,4 +69,12 @@ if(WITH_GAMEENGINE) ) endif() +if(WITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) +endif() + +if(WITH_BULLET) + add_definitions(-DWITH_BULLET) +endif() + blender_add_lib(bf_editor_mesh "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/mesh/SConscript b/source/blender/editors/mesh/SConscript index b3aba977b21..91ffdc91685 100644 --- a/source/blender/editors/mesh/SConscript +++ b/source/blender/editors/mesh/SConscript @@ -5,7 +5,7 @@ sources = env.Glob('*.c') defs = [] -incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' +incs = '../include ../../blenfont ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../gpu ../../blenloader' incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern' @@ -24,4 +24,10 @@ if env['WITH_BF_GAMEENGINE']: else: sources.remove('mesh_navmesh.c') +if env['WITH_BF_INTERNATIONAL']: + defs.append('WITH_INTERNATIONAL') + +if env['WITH_BF_BULLET']: + defs.append('WITH_BULLET') + env.BlenderLib ( 'bf_editors_mesh', sources, Split(incs), defs, libtype=['core'], priority=[45] ) diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 94e10b53b29..4350c005f95 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -85,7 +85,7 @@ void paintface_flush_flags(Object *ob) * - Final derived polys => Final derived tessfaces */ - if ((index_array = CustomData_get_layer(&me->fdata, CD_POLYINDEX))) { + if ((index_array = CustomData_get_layer(&me->fdata, CD_ORIGINDEX))) { faces = me->mface; totface = me->totface; @@ -109,7 +109,7 @@ void paintface_flush_flags(Object *ob) } } - if ((index_array = CustomData_get_layer(&dm->faceData, CD_POLYINDEX))) { + if ((index_array = CustomData_get_layer(&dm->faceData, CD_ORIGINDEX))) { polys = dm->getPolyArray(dm); faces = dm->getTessFaceArray(dm); totface = dm->getNumTessFaces(dm); @@ -214,7 +214,9 @@ static void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int ind /* fill array by selection */ mp = me->mpoly; for (a = 0; a < me->totpoly; a++, mp++) { - if (mp->flag & ME_HIDE) ; + if (mp->flag & ME_HIDE) { + /* pass */ + } else if (mp->flag & ME_FACE_SEL) { hash_add_face(ehash, mp, me->mloop + mp->loopstart); linkflag[a] = 1; @@ -426,7 +428,7 @@ void seam_mark_clear_tface(Scene *scene, short mode) if (me == 0 || me->totpoly == 0) return; if (mode == 0) - mode = pupmenu("Seams%t|Mark Border Seam %x1|Clear Seam %x2"); + mode = pupmenu("Seams %t|Mark Border Seam %x1|Clear Seam %x2"); if (mode != 1 && mode != 2) return; @@ -533,8 +535,8 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, int select, int extend) unsigned int *rt; char *selar; int a, index; - int sx = BLI_RCT_SIZE_X(rect) + 1; - int sy = BLI_RCT_SIZE_Y(rect) + 1; + int sx = BLI_rcti_size_x(rect) + 1; + int sy = BLI_rcti_size_y(rect) + 1; me = BKE_mesh_from_object(ob); @@ -572,7 +574,9 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, int select, int extend) mpoly = me->mpoly; for (a = 1; a <= me->totpoly; a++, mpoly++) { if (selar[a]) { - if (mpoly->flag & ME_HIDE) ; + if (mpoly->flag & ME_HIDE) { + /* pass */ + } else { if (select) mpoly->flag |= ME_FACE_SEL; else mpoly->flag &= ~ME_FACE_SEL; diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index 8b032bb1a3d..70b359d3e28 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -55,16 +55,16 @@ /* ********* add primitive operators ************* */ -static void make_prim_init(bContext *C, const char *idname, - float *dia, float mat[][4], - int *state, const float loc[3], const float rot[3], const unsigned int layer) +static Object *make_prim_init(bContext *C, const char *idname, + float *dia, float mat[][4], + int *state, const float loc[3], const float rot[3], const unsigned int layer) { Object *obedit = CTX_data_edit_object(C); *state = 0; if (obedit == NULL || obedit->type != OB_MESH) { obedit = ED_object_add_type(C, OB_MESH, loc, rot, FALSE, layer); - + rename_id((ID *)obedit, idname); rename_id((ID *)obedit->data, idname); @@ -73,12 +73,13 @@ static void make_prim_init(bContext *C, const char *idname, *state = 1; } - *dia = ED_object_new_primitive_matrix(C, obedit, loc, rot, mat); + *dia = ED_object_new_primitive_matrix(C, obedit, loc, rot, mat, FALSE); + + return obedit; } -static void make_prim_finish(bContext *C, int *state, int enter_editmode) +static void make_prim_finish(bContext *C, Object *obedit, int *state, int enter_editmode) { - Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); /* Primitive has all verts selected, use vert select flush @@ -102,11 +103,9 @@ static int add_primitive_plane_exec(bContext *C, wmOperator *op) int enter_editmode; int state; unsigned int layer; - - ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); - make_prim_init(C, "Plane", &dia, mat, &state, loc, rot, layer); - obedit = CTX_data_edit_object(C); + ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); + obedit = make_prim_init(C, "Plane", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf(em, op, "vertout", @@ -115,7 +114,7 @@ static int add_primitive_plane_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - make_prim_finish(C, &state, enter_editmode); + make_prim_finish(C, obedit, &state, enter_editmode); return OPERATOR_FINISHED; } @@ -126,12 +125,11 @@ void MESH_OT_primitive_plane_add(wmOperatorType *ot) ot->name = "Add Plane"; ot->description = "Construct a filled planar mesh with 4 vertices"; ot->idname = "MESH_OT_primitive_plane_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_plane_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -146,19 +144,17 @@ static int add_primitive_cube_exec(bContext *C, wmOperator *op) int enter_editmode; int state; unsigned int layer; - - ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); - make_prim_init(C, "Cube", &dia, mat, &state, loc, rot, layer); - obedit = CTX_data_edit_object(C); + ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); + obedit = make_prim_init(C, "Cube", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf(em, op, "vertout", "create_cube mat=%m4 size=%f", mat, dia * 2.0f)) { return OPERATOR_CANCELLED; } - + /* BMESH_TODO make plane side this: M_SQRT2 - plane (diameter of 1.41 makes it unit size) */ - make_prim_finish(C, &state, enter_editmode); + make_prim_finish(C, obedit, &state, enter_editmode); return OPERATOR_FINISHED; } @@ -169,12 +165,11 @@ void MESH_OT_primitive_cube_add(wmOperatorType *ot) ot->name = "Add Cube"; ot->description = "Construct a cube mesh"; ot->idname = "MESH_OT_primitive_cube_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_cube_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -195,26 +190,24 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op) int enter_editmode; int state, cap_end, cap_tri; unsigned int layer; - + cap_end = RNA_enum_get(op->ptr, "fill_type"); cap_tri = (cap_end == 2); - - ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); - make_prim_init(C, "Circle", &dia, mat, &state, loc, rot, layer); - obedit = CTX_data_edit_object(C); + ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); + obedit = make_prim_init(C, "Circle", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf(em, op, "vertout", "create_circle segments=%i diameter=%f cap_ends=%b cap_tris=%b mat=%m4", - RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius"), + RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius") * dia, cap_end, cap_tri, mat)) { return OPERATOR_CANCELLED; } - - make_prim_finish(C, &state, enter_editmode); - + + make_prim_finish(C, obedit, &state, enter_editmode); + return OPERATOR_FINISHED; } @@ -226,15 +219,14 @@ void MESH_OT_primitive_circle_add(wmOperatorType *ot) ot->name = "Add Circle"; ot->description = "Construct a circle mesh"; ot->idname = "MESH_OT_primitive_circle_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_circle_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* props */ RNA_def_int(ot->srna, "vertices", 32, 3, INT_MAX, "Vertices", "", 3, 500); prop = RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00); @@ -252,30 +244,28 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op) int enter_editmode; int state, cap_end, cap_tri; unsigned int layer; - + cap_end = RNA_enum_get(op->ptr, "end_fill_type"); cap_tri = (cap_end == 2); - - ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); - make_prim_init(C, "Cylinder", &dia, mat, &state, loc, rot, layer); - obedit = CTX_data_edit_object(C); + ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); + obedit = make_prim_init(C, "Cylinder", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf( em, op, "vertout", "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f mat=%m4", RNA_int_get(op->ptr, "vertices"), - RNA_float_get(op->ptr, "radius"), - RNA_float_get(op->ptr, "radius"), + RNA_float_get(op->ptr, "radius") * dia, + RNA_float_get(op->ptr, "radius") * dia, cap_end, cap_tri, - RNA_float_get(op->ptr, "depth"), mat)) + RNA_float_get(op->ptr, "depth") * dia, mat)) { return OPERATOR_CANCELLED; } - - make_prim_finish(C, &state, enter_editmode); - + + make_prim_finish(C, obedit, &state, enter_editmode); + return OPERATOR_FINISHED; } @@ -287,15 +277,14 @@ void MESH_OT_primitive_cylinder_add(wmOperatorType *ot) ot->name = "Add Cylinder"; ot->description = "Construct a cylinder mesh"; ot->idname = "MESH_OT_primitive_cylinder_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_cylinder_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* props */ RNA_def_int(ot->srna, "vertices", 32, 3, INT_MAX, "Vertices", "", 3, 500); prop = RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00); @@ -315,26 +304,24 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op) int enter_editmode; int state, cap_end, cap_tri; unsigned int layer; - + cap_end = RNA_enum_get(op->ptr, "end_fill_type"); cap_tri = (cap_end == 2); - - ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); - make_prim_init(C, "Cone", &dia, mat, &state, loc, rot, layer); - obedit = CTX_data_edit_object(C); + ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); + obedit = make_prim_init(C, "Cone", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf( em, op, "vertout", "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f mat=%m4", - RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius1"), - RNA_float_get(op->ptr, "radius2"), cap_end, cap_tri, RNA_float_get(op->ptr, "depth"), mat)) + RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius1") * dia, + RNA_float_get(op->ptr, "radius2") * dia, cap_end, cap_tri, RNA_float_get(op->ptr, "depth") * dia, mat)) { return OPERATOR_CANCELLED; } - - make_prim_finish(C, &state, enter_editmode); + + make_prim_finish(C, obedit, &state, enter_editmode); return OPERATOR_FINISHED; } @@ -347,15 +334,14 @@ void MESH_OT_primitive_cone_add(wmOperatorType *ot) ot->name = "Add Cone"; ot->description = "Construct a conic mesh"; ot->idname = "MESH_OT_primitive_cone_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_cone_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* props */ RNA_def_int(ot->srna, "vertices", 32, 3, INT_MAX, "Vertices", "", 3, 500); prop = RNA_def_float(ot->srna, "radius1", 1.0f, 0.0, FLT_MAX, "Radius 1", "", 0.001, 100.00); @@ -377,11 +363,9 @@ static int add_primitive_grid_exec(bContext *C, wmOperator *op) int enter_editmode; int state; unsigned int layer; - - ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); - make_prim_init(C, "Grid", &dia, mat, &state, loc, rot, layer); - obedit = CTX_data_edit_object(C); + ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); + obedit = make_prim_init(C, "Grid", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf(em, op, "vertout", @@ -392,8 +376,9 @@ static int add_primitive_grid_exec(bContext *C, wmOperator *op) { return OPERATOR_CANCELLED; } - - make_prim_finish(C, &state, enter_editmode); + + make_prim_finish(C, obedit, &state, enter_editmode); + return OPERATOR_FINISHED; } @@ -405,15 +390,14 @@ void MESH_OT_primitive_grid_add(wmOperatorType *ot) ot->name = "Add Grid"; ot->description = "Construct a grid mesh"; ot->idname = "MESH_OT_primitive_grid_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_grid_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* props */ RNA_def_int(ot->srna, "x_subdivisions", 10, 3, INT_MAX, "X Subdivisions", "", 3, 1000); RNA_def_int(ot->srna, "y_subdivisions", 10, 3, INT_MAX, "Y Subdivisions", "", 3, 1000); @@ -431,21 +415,24 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op) int enter_editmode; int state, view_aligned; unsigned int layer; - + ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, &view_aligned); if (!view_aligned) rot[0] += (float)M_PI / 2.0f; - - make_prim_init(C, "Monkey", &dia, mat, &state, loc, rot, layer); - obedit = CTX_data_edit_object(C); + obedit = make_prim_init(C, "Monkey", &dia, mat, &state, loc, rot, layer); + mat[0][0] *= dia; + mat[1][1] *= dia; + mat[2][2] *= dia; + em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf(em, op, "vertout", "create_monkey mat=%m4", mat)) { return OPERATOR_CANCELLED; } - - make_prim_finish(C, &state, enter_editmode); + + make_prim_finish(C, obedit, &state, enter_editmode); + return OPERATOR_FINISHED; } @@ -455,12 +442,11 @@ void MESH_OT_primitive_monkey_add(wmOperatorType *ot) ot->name = "Add Monkey"; ot->description = "Construct a Suzanne mesh"; ot->idname = "MESH_OT_primitive_monkey_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_monkey_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -475,24 +461,22 @@ static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op) int enter_editmode; int state; unsigned int layer; - - ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); - make_prim_init(C, "Sphere", &dia, mat, &state, loc, rot, layer); - obedit = CTX_data_edit_object(C); + ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); + obedit = make_prim_init(C, "Sphere", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf(em, op, "vertout", "create_uvsphere segments=%i revolutions=%i diameter=%f mat=%m4", RNA_int_get(op->ptr, "segments"), RNA_int_get(op->ptr, "ring_count"), - RNA_float_get(op->ptr, "size"), mat)) + RNA_float_get(op->ptr, "size") * dia, mat)) { return OPERATOR_CANCELLED; } - - make_prim_finish(C, &state, enter_editmode); - return OPERATOR_FINISHED; + make_prim_finish(C, obedit, &state, enter_editmode); + + return OPERATOR_FINISHED; } void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot) @@ -503,15 +487,14 @@ void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot) ot->name = "Add UV Sphere"; ot->description = "Construct a UV sphere mesh"; ot->idname = "MESH_OT_primitive_uv_sphere_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_uvsphere_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* props */ RNA_def_int(ot->srna, "segments", 32, 3, INT_MAX, "Segments", "", 3, 500); RNA_def_int(ot->srna, "ring_count", 16, 3, INT_MAX, "Rings", "", 3, 500); @@ -529,25 +512,23 @@ static int add_primitive_icosphere_exec(bContext *C, wmOperator *op) int enter_editmode; int state; unsigned int layer; - - ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); - make_prim_init(C, "Icosphere", &dia, mat, &state, loc, rot, layer); - obedit = CTX_data_edit_object(C); + ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL); + obedit = make_prim_init(C, "Icosphere", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf( em, op, "vertout", "create_icosphere subdivisions=%i diameter=%f mat=%m4", RNA_int_get(op->ptr, "subdivisions"), - RNA_float_get(op->ptr, "size"), mat)) + RNA_float_get(op->ptr, "size") * dia, mat)) { return OPERATOR_CANCELLED; } - - make_prim_finish(C, &state, enter_editmode); - return OPERATOR_FINISHED; + make_prim_finish(C, obedit, &state, enter_editmode); + + return OPERATOR_FINISHED; } void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot) @@ -558,15 +539,14 @@ void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot) ot->name = "Add Ico Sphere"; ot->description = "Construct an Icosphere mesh"; ot->idname = "MESH_OT_primitive_ico_sphere_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = add_primitive_icosphere_exec; ot->poll = ED_operator_scene_editable; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* props */ RNA_def_int(ot->srna, "subdivisions", 2, 1, INT_MAX, "Subdivisions", "", 1, 8); prop = RNA_def_float(ot->srna, "size", 1.0f, 0.0f, FLT_MAX, "Size", "", 0.001f, 100.00); diff --git a/source/blender/editors/mesh/editmesh_bvh.c b/source/blender/editors/mesh/editmesh_bvh.c index 0b7d396b696..468d0d8d8c6 100644 --- a/source/blender/editors/mesh/editmesh_bvh.c +++ b/source/blender/editors/mesh/editmesh_bvh.c @@ -309,7 +309,7 @@ static void vertsearchcallback(void *userdata, int index, const float *UNUSED(co } } -BMVert *BMBVH_FindClosestVert(BMBVHTree *tree, const float co[3], float maxdist) +BMVert *BMBVH_FindClosestVert(BMBVHTree *tree, const float co[3], const float maxdist) { BVHTreeNearest hit; @@ -325,7 +325,7 @@ BMVert *BMBVH_FindClosestVert(BMBVHTree *tree, const float co[3], float maxdist) float dist, curdist = tree->maxdist, v[3]; int cur = 0, i; - maxdist = tree->maxdist; + /* maxdist = tree->maxdist; */ /* UNUSED */ for (i = 0; i < 3; i++) { sub_v3_v3v3(v, hit.co, ls[i]->v->co); @@ -371,9 +371,9 @@ int BMBVH_VertVisible(BMBVHTree *tree, BMEdge *e, RegionView3D *r3d) } #endif -static BMFace *edge_ray_cast(BMBVHTree *tree, const float co[3], const float dir[3], float *hitout, BMEdge *e) +static BMFace *edge_ray_cast(BMBVHTree *tree, const float co[3], const float dir[3], float *r_hitout, BMEdge *e) { - BMFace *f = BMBVH_RayCast(tree, co, dir, hitout, NULL); + BMFace *f = BMBVH_RayCast(tree, co, dir, r_hitout, NULL); if (f && BM_edge_in_face(f, e)) return NULL; @@ -392,7 +392,7 @@ static void scale_point(float c1[3], const float p[3], const float s) int BMBVH_EdgeVisible(BMBVHTree *tree, BMEdge *e, ARegion *ar, View3D *v3d, Object *obedit) { BMFace *f; - float co1[3], co2[3], co3[3], dir1[4], dir2[4], dir3[4]; + float co1[3], co2[3], co3[3], dir1[3], dir2[3], dir3[3]; float origin[3], invmat[4][4]; float epsilon = 0.01f; float end[3]; @@ -405,8 +405,7 @@ int BMBVH_EdgeVisible(BMBVHTree *tree, BMEdge *e, ARegion *ar, View3D *v3d, Obje mul_m4_v3(invmat, origin); copy_v3_v3(co1, e->v1->co); - add_v3_v3v3(co2, e->v1->co, e->v2->co); - mul_v3_fl(co2, 0.5f); + mid_v3_v3v3(co2, e->v1->co, e->v2->co); copy_v3_v3(co3, e->v2->co); scale_point(co1, co2, 0.99); diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 7ecfb712c18..82447cc0168 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -29,7 +29,9 @@ * \ingroup edmesh */ -#define _USE_MATH_DEFINES +#ifdef _MSC_VER +# define _USE_MATH_DEFINES +#endif #include "MEM_guardedalloc.h" @@ -71,6 +73,9 @@ #define KMAXDIST 10 /* max mouse distance from edge before not detecting it */ +#define KNIFE_FLT_EPS 0.00001f +#define KNIFE_FLT_EPS_SQUARED (KNIFE_FLT_EPS * KNIFE_FLT_EPS) + typedef struct KnifeColors { unsigned char line[3]; unsigned char edge[3]; @@ -176,6 +181,7 @@ typedef struct KnifeTool_OpData { char select_result; /* set on initialization */ short is_ortho; + float ortho_extent; float clipsta, clipend; enum { @@ -222,7 +228,7 @@ static void knife_update_header(bContext *C, KnifeTool_OpData *kcd) static void knife_project_v3(KnifeTool_OpData *kcd, const float co[3], float sco[3]) { - ED_view3d_project_float_v3(kcd->ar, co, sco, kcd->projmat); + ED_view3d_project_float_v3_m4(kcd->ar, co, sco, kcd->projmat); } static void knife_pos_data_clear(KnifePosData *kpd) @@ -428,7 +434,7 @@ static KnifeVert *knife_split_edge(KnifeTool_OpData *kcd, KnifeEdge *kfe, float float perc, cageco[3], l12; l12 = len_v3v3(kfe->v1->co, kfe->v2->co); - if (l12 < FLT_EPSILON * 80) { + if (l12 < KNIFE_FLT_EPS) { copy_v3_v3(cageco, kfe->v1->cageco); } else { @@ -444,8 +450,8 @@ static KnifeVert *knife_split_edge(KnifeTool_OpData *kcd, KnifeEdge *kfe, float } else { /* kfe cuts across an existing face. - If v1 and v2 are in multiple faces together (e.g., if they - are in doubled polys) then this arbitrarily chooses one of them */ + * If v1 and v2 are in multiple faces together (e.g., if they + * are in doubled polys) then this arbitrarily chooses one of them */ f = knife_find_common_face(&kfe->v1->faces, &kfe->v2->faces); if (f) knife_append_list(kcd, &newkfe->v2->faces, f); @@ -564,7 +570,9 @@ static int find_connected_linehit(KnifeTool_OpData *kcd, int testi, BMFace *f, i if (testi >= 0 && testi < kcd->totlinehit) { if (knife_find_common_face(&kcd->linehits[testi].kfe->faces, &kcd->linehits[i].kfe->faces)) + { return i; + } } else if (f) { if (find_ref(&kcd->linehits[i].kfe->faces, f)) @@ -585,7 +593,7 @@ static void knife_sort_linehits(KnifeTool_OpData *kcd) * successor faces connected to the linehits at either end of the range */ for (i = 0; i < kcd->totlinehit - 1; i = nexti) { for (j = i + 1; j < kcd->totlinehit; j++) { - if (fabsf(kcd->linehits[j].l - kcd->linehits[i].l) > 80 * FLT_EPSILON) + if (fabsf(kcd->linehits[j].l - kcd->linehits[i].l) > KNIFE_FLT_EPS) break; } nexti = j; @@ -793,7 +801,7 @@ static void knife_add_cut(KnifeTool_OpData *kcd) for (i = 0; i < kcd->totlinehit; i++, (lastlh = lh), lh++) { BMFace *f = lastlh ? lastlh->f : lh->f; - if (lastlh && len_v3v3(lastlh->hit, lh->hit) == 0.0f) { + if (lastlh && len_squared_v3v3(lastlh->hit, lh->hit) == 0.0f) { if (!firstlh) firstlh = lastlh; continue; @@ -812,13 +820,13 @@ static void knife_add_cut(KnifeTool_OpData *kcd) lastlh = firstlh = NULL; } - if (len_v3v3(kcd->prev.cage, lh->realhit) < FLT_EPSILON * 80) + if (len_squared_v3v3(kcd->prev.cage, lh->realhit) < KNIFE_FLT_EPS_SQUARED) continue; - if (len_v3v3(kcd->curr.cage, lh->realhit) < FLT_EPSILON * 80) + if (len_squared_v3v3(kcd->curr.cage, lh->realhit) < KNIFE_FLT_EPS_SQUARED) continue; /* first linehit may be down face parallel to view */ - if (!lastlh && fabsf(lh->l) < FLT_EPSILON * 80) + if (!lastlh && fabsf(lh->l) < KNIFE_FLT_EPS) continue; if (kcd->prev.is_space) { @@ -839,7 +847,7 @@ static void knife_add_cut(KnifeTool_OpData *kcd) copy_v3_v3(kcd->curr.cage, lh->cagehit); /* don't draw edges down faces parallel to view */ - if (lastlh && fabsf(lastlh->l - lh->l) < FLT_EPSILON * 80) { + if (lastlh && fabsf(lastlh->l - lh->l) < KNIFE_FLT_EPS) { kcd->prev = kcd->curr; continue; } @@ -1040,6 +1048,9 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) } if (kcd->totlinehit > 0) { + const float vthresh4 = kcd->vthresh / 4.0f; + const float vthresh4_squared = vthresh4 * vthresh4; + BMEdgeHit *lh; int i; @@ -1058,12 +1069,12 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) knife_project_v3(kcd, lh->kfe->v2->cageco, sv2); knife_project_v3(kcd, lh->cagehit, lh->schit); - if (len_v2v2(lh->schit, sv1) < kcd->vthresh / 4.0f) { + if (len_squared_v2v2(lh->schit, sv1) < vthresh4_squared) { copy_v3_v3(lh->cagehit, lh->kfe->v1->cageco); glVertex3fv(lh->cagehit); lh->v = lh->kfe->v1; } - else if (len_v2v2(lh->schit, sv2) < kcd->vthresh / 4.0f) { + else if (len_squared_v2v2(lh->schit, sv2) < vthresh4_squared) { copy_v3_v3(lh->cagehit, lh->kfe->v2->cageco); glVertex3fv(lh->cagehit); lh->v = lh->kfe->v2; @@ -1132,11 +1143,11 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) static float len_v3_tri_side_max(const float v1[3], const float v2[3], const float v3[3]) { - const float s1 = len_v3v3(v1, v2); - const float s2 = len_v3v3(v2, v3); - const float s3 = len_v3v3(v3, v1); + const float s1 = len_squared_v3v3(v1, v2); + const float s2 = len_squared_v3v3(v2, v3); + const float s3 = len_squared_v3v3(v3, v1); - return MAX3(s1, s2, s3); + return sqrtf(MAX3(s1, s2, s3)); } static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, @@ -1154,7 +1165,7 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, /* for comparing distances, error of intersection depends on triangle scale. * need to scale down before squaring for accurate comparison */ - const float depsilon = 50 *FLT_EPSILON *len_v3_tri_side_max(v1, v2, v3); + const float depsilon = (FLT_EPSILON / 2.0f) * len_v3_tri_side_max(v1, v2, v3); const float depsilon_squared = depsilon * depsilon; copy_v3_v3(cos + 0, v1); @@ -1203,7 +1214,7 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, } knife_project_v3(kcd, p, sp); - view3d_unproject(mats, view, sp[0], sp[1], 0.0f); + ED_view3d_unproject(mats, view, sp[0], sp[1], 0.0f); mul_m4_v3(kcd->ob->imat, view); if (kcd->cut_through) { @@ -1301,6 +1312,22 @@ static void knife_bgl_get_mats(KnifeTool_OpData *UNUSED(kcd), bglMats *mats) //copy_m4_m4(mats->projection, kcd->vc.rv3d->winmat); } +/* Calculate maximum excursion (doubled) from (0,0,0) of mesh */ +static void calc_ortho_extent(KnifeTool_OpData *kcd) +{ + BMIter iter; + BMVert *v; + BMesh* bm = kcd->em->bm; + float max_xyz = 0.0f; + int i; + + BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) { + for (i = 0; i < 3; i++) + max_xyz = max_ff(max_xyz, fabs(v->co[i])); + } + kcd->ortho_extent = 2 * max_xyz; +} + /* Finds visible (or all, if cutting through) edges that intersects the current screen drag line */ static void knife_find_line_hits(KnifeTool_OpData *kcd) { @@ -1343,8 +1370,10 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) * (which may involve using doubles everywhere!), * limit the distance between these points */ if (kcd->is_ortho) { - limit_dist_v3(v1, v3, 200.0f); - limit_dist_v3(v2, v4, 200.0f); + if (kcd->ortho_extent == 0.0f) + calc_ortho_extent(kcd); + limit_dist_v3(v1, v3, kcd->ortho_extent + 10.0f); + limit_dist_v3(v2, v4, kcd->ortho_extent + 10.0f); } BLI_smallhash_init(ehash); @@ -1386,7 +1415,7 @@ static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2], mval[1] = (float)mval_i[1]; /* unproject to find view ray */ - view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f); + ED_view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f); if (kcd->is_ortho) { negate_v3_v3(r_ray, kcd->vc.rv3d->viewinv[2]); @@ -1408,7 +1437,7 @@ static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2], static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float cageco[3], int *is_space) { BMFace *f; - int dist = KMAXDIST; + float dist = KMAXDIST; float origin[3]; float ray[3]; @@ -1496,7 +1525,7 @@ static float knife_snap_size(KnifeTool_OpData *kcd, float maxsize) if (density < 1.0f) density = 1.0f; - return minf(maxsize / (density * 0.5f), maxsize); + return min_ff(maxsize / (density * 0.5f), maxsize); } /* p is closest point on edge to the mouse cursor */ @@ -1753,6 +1782,9 @@ static int knife_update_active(KnifeTool_OpData *kcd) return 1; } +#define SCANFILL_CUTS 0 +#if SCANFILL_CUTS + #define MARK 4 #define DEL 8 #define VERT_ON_EDGE 16 @@ -1761,9 +1793,6 @@ static int knife_update_active(KnifeTool_OpData *kcd) #define BOUNDARY 128 #define FACE_NEW 256 -#define SCANFILL_CUTS 0 -#if SCANFILL_CUTS - typedef struct facenet_entry { struct facenet_entry *next, *prev; KnifeEdge *kfe; @@ -1981,7 +2010,7 @@ static void knifenet_fill_faces(KnifeTool_OpData *kcd) ScanFillFace *sf_tri; ScanFillVert *sf_vert, *sf_vert_last; int j; - float rndscale = FLT_EPSILON * 25; + float rndscale = (KNIFE_FLT_EPS / 4.0f); f = faces[i]; BLI_smallhash_init(hash); @@ -3054,14 +3083,9 @@ wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf) static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) { - Object *obedit; + Object *obedit = CTX_data_edit_object(C); KnifeTool_OpData *kcd = op->customdata; - if (!C) { - return OPERATOR_FINISHED; - } - - obedit = CTX_data_edit_object(C); if (!obedit || obedit->type != OB_MESH || BMEdit_FromObject(obedit) != kcd->em) { knifetool_exit(C, op); ED_area_headerprint(CTX_wm_area(C), NULL); @@ -3125,6 +3149,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) break; case KNF_MODAL_CUT_THROUGH_TOGGLE: kcd->cut_through = !kcd->cut_through; + knifetool_update_mval(kcd, event->mval); /* refresh knife path */ knife_update_header(C, kcd); break; case KNF_MODAL_NEW_CUT: diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 60c5244ddbc..8e5c89adfca 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -29,7 +29,9 @@ */ #include -#define _USE_MATH_DEFINES +#ifdef _MSC_VER +# define _USE_MATH_DEFINES +#endif #include #include #include @@ -371,11 +373,12 @@ static void ringsel_exit(bContext *UNUSED(C), wmOperator *op) op->customdata = NULL; } + /* called when modal loop selection gets set up... */ static int ringsel_init(bContext *C, wmOperator *op, int do_cut) { RingSelOpData *lcd; - + /* alloc new customdata */ lcd = op->customdata = MEM_callocN(sizeof(RingSelOpData), "ringsel Modal Op Data"); @@ -390,7 +393,10 @@ static int ringsel_init(bContext *C, wmOperator *op, int do_cut) initNumInput(&lcd->num); lcd->num.idx_max = 0; lcd->num.flag |= NUM_NO_NEGATIVE | NUM_NO_FRACTION; - + + /* XXX, temp, workaround for [# ] */ + EDBM_mesh_ensure_valid_dm_hack(CTX_data_scene(C), lcd->em); + em_setup_viewcontext(C, &lcd->vc); ED_region_tag_redraw(lcd->ar); @@ -410,10 +416,10 @@ static int ringcut_invoke(bContext *C, wmOperator *op, wmEvent *evt) Object *obedit = CTX_data_edit_object(C); RingSelOpData *lcd; BMEdge *edge; - int dist = 75; + float dist = 75.0f; if (modifiers_isDeformedByLattice(obedit) || modifiers_isDeformedByArmature(obedit)) - BKE_report(op->reports, RPT_WARNING, "Loop cut doesn't work well on deformed edit mesh display"); + BKE_report(op->reports, RPT_WARNING, "Loop cut does not work well on deformed edit mesh display"); view3d_operator_needs_opengl(C); @@ -499,7 +505,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) if (event->val == KM_RELEASE) break; - cuts = MAX2(cuts - 1, 0); + cuts = max_ii(cuts - 1, 0); RNA_int_set(op->ptr, "number_cuts", cuts); ringsel_find_edge(lcd, cuts); show_cuts = TRUE; @@ -507,7 +513,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) ED_region_tag_redraw(lcd->ar); break; case MOUSEMOVE: { /* mouse moved somewhere to select another loop */ - int dist = 75; + float dist = 75.0f; BMEdge *edge; lcd->vc.mval[0] = event->mval[0]; @@ -521,7 +527,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) ED_region_tag_redraw(lcd->ar); break; - } + } } /* using the keyboard to input the number of cuts */ diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 4d4a890300f..6379bdbc0ca 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -55,19 +55,59 @@ #include "mesh_intern.h" -/* helper to find edge for edge_rip */ -static float edbm_rip_rip_edgedist(ARegion *ar, float mat[][4], - const float co1[3], const float co2[2], const float mvalf[2]) +/** + * helper to find edge for edge_rip, + * + * \param inset is used so we get some useful distance + * when comparing multiple edges that meet at the same + * point and would result in teh same distance. + */ +#define INSET_DEFAULT 0.00001f +static float edbm_rip_edgedist(ARegion *ar, float mat[][4], + const float co1[3], const float co2[3], const float mvalf[2], + const float inset) { - float vec1[3], vec2[3]; + float vec1[2], vec2[2]; - ED_view3d_project_float_v2(ar, co1, vec1, mat); - ED_view3d_project_float_v2(ar, co2, vec2, mat); + ED_view3d_project_float_v2_m4(ar, co1, vec1, mat); + ED_view3d_project_float_v2_m4(ar, co2, vec2, mat); + + if (inset != 0.0f) { + const float dist = inset / len_v2v2(vec1, vec2); + interp_v2_v2v2(vec1, vec1, vec2, dist); + interp_v2_v2v2(vec2, vec2, vec1, dist); + } /* TODO: use dist_squared_to_line_segment_v2() looks like we only ever use for comparison */ return dist_to_line_segment_v2(mvalf, vec1, vec2); } +#if 0 +static float edbm_rip_linedist(ARegion *ar, float mat[][4], + const float co1[3], const float co2[3], const float mvalf[2]) +{ + float vec1[2], vec2[2]; + + ED_view3d_project_float_v2_m4(ar, co1, vec1, mat); + ED_view3d_project_float_v2_m4(ar, co2, vec2, mat); + + return dist_to_line_v2(mvalf, vec1, vec2); +} +#endif + +/* calculaters a point along the loop tangent which can be used to measure against edges */ +static void edbm_calc_loop_co(BMLoop *l, float l_mid_co[3]) +{ + BM_loop_calc_face_tangent(l, l_mid_co); + + /* scale to average of surrounding edge size, only needs to be approx, but should + * be roughly equivalent to the check below which uses the middle of the edge. */ + mul_v3_fl(l_mid_co, (BM_edge_calc_length(l->e) + BM_edge_calc_length(l->prev->e)) / 2.0f); + + add_v3_v3(l_mid_co, l->v->co); +} + + static float edbm_rip_edge_side_measure(BMEdge *e, BMLoop *e_l, ARegion *ar, float projectMat[4][4], const float fmval[2]) @@ -97,11 +137,11 @@ static float edbm_rip_edge_side_measure(BMEdge *e, BMLoop *e_l, mid_v3_v3v3(cent, v1_other->co, v2_other->co); mid_v3_v3v3(mid, e->v1->co, e->v2->co); - ED_view3d_project_float_v2(ar, cent, cent, projectMat); - ED_view3d_project_float_v2(ar, mid, mid, projectMat); + ED_view3d_project_float_v2_m4(ar, cent, cent, projectMat); + ED_view3d_project_float_v2_m4(ar, mid, mid, projectMat); - ED_view3d_project_float_v2(ar, e->v1->co, e_v1_co, projectMat); - ED_view3d_project_float_v2(ar, e->v2->co, e_v2_co, projectMat); + ED_view3d_project_float_v2_m4(ar, e->v1->co, e_v1_co, projectMat); + ED_view3d_project_float_v2_m4(ar, e->v2->co, e_v2_co, projectMat); sub_v2_v2v2(vec, cent, mid); normalize_v2(vec); @@ -237,7 +277,6 @@ static EdgeLoopPair *edbm_ripsel_looptag_helper(BMesh *bm) uid_start = uid; while ((e = edbm_ripsel_edge_mark_step(v_step, uid))) { - BM_elem_flag_disable(e, BM_ELEM_SMOOTH); v_step = BM_edge_other_vert((e_step = e), v_step); uid++; /* only different line */ tot++; @@ -254,7 +293,6 @@ static EdgeLoopPair *edbm_ripsel_looptag_helper(BMesh *bm) v_step = e_first->v1; while ((e = edbm_ripsel_edge_mark_step(v_step, uid))) { - BM_elem_flag_disable(e, BM_ELEM_SMOOTH); v_step = BM_edge_other_vert((e_step = e), v_step); uid--; /* only different line */ tot++; @@ -344,6 +382,145 @@ static void edbm_ripsel_deselect_helper(BMesh *bm, EdgeLoopPair *eloop_pairs, } /* --- end 'ripsel' selection handling code --- */ + +/* --- face-fill code --- */ +/** + * return an un-ordered array of loop pairs + * use for rebuilding face-fill + * + * \note the method currenly used fails for edges with 3+ face users and gives + * nasty holes in the mesh, there isnt a good way of knowing ahead of time + * which loops will be split apart (its possible to figure out but quite involved). + * So for now this is a known limitation of current rip-fill option. + */ + +typedef struct UnorderedLoopPair { + BMLoop *l_pair[2]; + char flag; +} UnorderedLoopPair; +enum { + ULP_FLIP_0 = (1 << 0), + ULP_FLIP_1 = (1 << 1) +}; + +static UnorderedLoopPair *edbm_tagged_loop_pairs_to_fill(BMesh *bm) +{ + BMIter iter; + BMEdge *e; + + unsigned int total_tag = 0; + /* count tags, could be pre-calculated */ + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + total_tag++; + } + } + + if (total_tag) { + UnorderedLoopPair *uloop_pairs = MEM_mallocN(total_tag * sizeof(UnorderedLoopPair), __func__); + UnorderedLoopPair *ulp = uloop_pairs; + + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + BMLoop *l1, *l2; + if (BM_edge_loop_pair(e, &l1, &l2)) { + BMVert *v_cmp = l1->e->v1; + ulp->flag = (((l1->v != v_cmp) ? ULP_FLIP_0 : 0) | + ((l2->v == v_cmp) ? ULP_FLIP_1 : 0)); + } + else { + ulp->flag = 0; + } + ulp->l_pair[0] = l1; + ulp->l_pair[1] = l2; + + ulp++; + } + } + + return uloop_pairs; + } + else { + return NULL; + } +} + +static void edbm_tagged_loop_pairs_do_fill_faces(BMesh *bm, UnorderedLoopPair *uloop_pairs) +{ + UnorderedLoopPair *ulp; + unsigned int total_tag = MEM_allocN_len(uloop_pairs) / sizeof(UnorderedLoopPair); + unsigned int i; + + for (i = 0, ulp = uloop_pairs; i < total_tag; i++, ulp++) { + if ((ulp->l_pair[0] && ulp->l_pair[1]) && + (ulp->l_pair[0]->e != ulp->l_pair[1]->e)) + { + /* time has come to make a face! */ + BMVert *v_shared = BM_edge_share_vert(ulp->l_pair[0]->e, ulp->l_pair[1]->e); + BMFace *f, *f_example = ulp->l_pair[0]->f; + BMLoop *l_iter; + BMVert *f_verts[4]; + + if (v_shared == NULL) { + /* quad */ + f_verts[0] = ulp->l_pair[0]->e->v1; + f_verts[1] = ulp->l_pair[1]->e->v1; + f_verts[2] = ulp->l_pair[1]->e->v2; + f_verts[3] = ulp->l_pair[0]->e->v2; + + if (ulp->flag & ULP_FLIP_0) { + SWAP(BMVert *, f_verts[0], f_verts[3]); + } + if (ulp->flag & ULP_FLIP_1) { + SWAP(BMVert *, f_verts[1], f_verts[2]); + } + } + else { + /* tri */ + f_verts[0] = v_shared; + f_verts[1] = BM_edge_other_vert(ulp->l_pair[0]->e, v_shared); + f_verts[2] = BM_edge_other_vert(ulp->l_pair[1]->e, v_shared); + f_verts[3] = NULL; + + /* don't use the flip flags */ + if (v_shared == ulp->l_pair[0]->v) { + SWAP(BMVert *, f_verts[0], f_verts[1]); + } + } + + /* face should never exist */ + BLI_assert(BM_face_exists(bm, f_verts, f_verts[3] ? 4 : 3, &f) == FALSE); + + f = BM_face_create_quad_tri_v(bm, f_verts, f_verts[3] ? 4 : 3, f_example, FALSE); + + l_iter = BM_FACE_FIRST_LOOP(f); + + if (f_verts[3]) { + BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next; + BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter); l_iter = l_iter->next; + BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter); l_iter = l_iter->next; + BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); + } + else { + if (v_shared == f_verts[0]) { + BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next; + BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next; + BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter); + } + else { + BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next; + BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next; + BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter); + } + } + + } + } +} + +/* --- end 'face-fill' code --- */ + + static int edbm_rip_call_edgesplit(BMEditMesh *em, wmOperator *op) { BMOperator bmop; @@ -366,6 +543,8 @@ static int edbm_rip_call_edgesplit(BMEditMesh *em, wmOperator *op) */ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event) { + const int do_fill = RNA_boolean_get(op->ptr, "use_fill"); + UnorderedLoopPair *fill_uloop_pairs = NULL; Object *obedit = CTX_data_edit_object(C); ARegion *ar = CTX_wm_region(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); @@ -388,7 +567,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event) ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat); /* find selected vert - same some time and check history first */ - if (BM_select_history_active_get(em->bm, &ese) && ese.htype == BM_VERT) { + if (BM_select_history_active_get(bm, &ese) && ese.htype == BM_VERT) { v = (BMVert *)ese.ele; } else { @@ -417,7 +596,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event) totboundary_edge += (is_boundary != 0 || BM_edge_is_wire(e)); if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { if (is_boundary == FALSE && BM_edge_is_manifold(e)) { - d = edbm_rip_rip_edgedist(ar, projectMat, e->v1->co, e->v2->co, fmval); + d = edbm_rip_edgedist(ar, projectMat, e->v1->co, e->v2->co, fmval, INSET_DEFAULT); if (d < dist) { dist = d; e2 = e; @@ -426,6 +605,42 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event) } } + /* if we are ripping a single vertex from 3 faces, + * then measure the distance to the face corner as well as the edge */ + if (BM_vert_face_count(v) == 3 && + BM_vert_edge_count(v) == 3) + { + BMEdge *e_all[3]; + BMLoop *l_all[3]; + int i1, i2; + + BM_iter_as_array(bm, BM_EDGES_OF_VERT, v, (void **)e_all, 3); + BM_iter_as_array(bm, BM_LOOPS_OF_VERT, v, (void **)l_all, 3); + + /* not do a loop similar to the one above, but test against loops */ + for (i1 = 0; i1 < 3; i1++) { + /* consider wire as boundary for this purpose, + * otherwise we can't a face away from a wire edge */ + float l_mid_co[3]; + l = l_all[i1]; + edbm_calc_loop_co(l, l_mid_co); + d = edbm_rip_edgedist(ar, projectMat, l->v->co, l_mid_co, fmval, INSET_DEFAULT); + + if (d < dist) { + dist = d; + + /* find the edge that is not in this loop */ + e2 = NULL; + for (i2 = 0; i2 < 3; i2++) { + if (!BM_edge_in_loop(e_all[i2], l)) { + e2 = e_all[i2]; + break; + } + } + BLI_assert(e2 != NULL); + } + } + } } /* should we go ahead with edge rip or do we need to do special case, split off vertex?: @@ -459,7 +674,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event) int vi_best = 0; if (ese.ele) { - BM_select_history_remove(em->bm, ese.ele); + BM_select_history_remove(bm, ese.ele); } dist = FLT_MAX; @@ -473,14 +688,9 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event) BM_ITER_ELEM (l, &iter, vout[i], BM_LOOPS_OF_VERT) { if (!BM_elem_flag_test(l->f, BM_ELEM_HIDDEN)) { float l_mid_co[3]; - BM_loop_calc_face_tangent(l, l_mid_co); + edbm_calc_loop_co(l, l_mid_co); - /* scale to average of surrounding edge size, only needs to be approx, but should - * be roughly equivalent to the check below which uses the middle of the edge. */ - mul_v3_fl(l_mid_co, (BM_edge_calc_length(l->e) + BM_edge_calc_length(l->prev->e)) / 2.0f); - add_v3_v3(l_mid_co, v->co); - - d = edbm_rip_rip_edgedist(ar, projectMat, v->co, l_mid_co, fmval); + d = edbm_rip_edgedist(ar, projectMat, v->co, l_mid_co, fmval, INSET_DEFAULT); if (d < dist) { dist = d; @@ -496,7 +706,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event) float e_mid_co[3]; mid_v3_v3v3(e_mid_co, e->v1->co, e->v2->co); - d = edbm_rip_rip_edgedist(ar, projectMat, v->co, e_mid_co, fmval); + d = edbm_rip_edgedist(ar, projectMat, v->co, e_mid_co, fmval, INSET_DEFAULT); if (d < dist) { dist = d; @@ -512,7 +722,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event) BM_vert_select_set(bm, v, TRUE); if (ese.ele) { - BM_select_history_store(em->bm, v); + BM_select_history_store(bm, v); } /* splice all others back together */ @@ -543,39 +753,65 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_CANCELLED; } + /* *** Execute the split! *** */ + /* unlike edge split, for single vertex split we only use the operator in one of the cases + * but both allocate fill */ + /* rip two adjacent edges */ if (BM_edge_is_boundary(e2) || BM_vert_face_count(v) == 2) { + /* Don't run the edge split operator in this case */ + + BM_elem_flag_enable(e2, BM_ELEM_TAG); /* only for face-fill (we don't call the operator) */ + + /* keep directly before edgesplit */ + if (do_fill) { + fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm); + } + l = e2->l; ripvert = BM_face_vert_separate(bm, l->f, v); BLI_assert(ripvert); if (!ripvert) { + if (fill_uloop_pairs) MEM_freeN(fill_uloop_pairs); return OPERATOR_CANCELLED; } } - else if (BM_edge_is_manifold(e2)) { - l = e2->l; - e = BM_face_other_edge_loop(l->f, e2, v)->e; - BM_elem_flag_enable(e, BM_ELEM_TAG); + else { + if (BM_edge_is_manifold(e2)) { + l = e2->l; + e = BM_face_other_edge_loop(l->f, e2, v)->e; + BM_elem_flag_enable(e, BM_ELEM_TAG); - l = e2->l->radial_next; - e = BM_face_other_edge_loop(l->f, e2, v)->e; - BM_elem_flag_enable(e, BM_ELEM_TAG); + l = e2->l->radial_next; + e = BM_face_other_edge_loop(l->f, e2, v)->e; + BM_elem_flag_enable(e, BM_ELEM_TAG); + } + else { + /* looks like there are no split edges, we could just return/report-error? - Campbell */ + } + + /* keep directly before edgesplit */ + if (do_fill) { + fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm); + } + + if (!edbm_rip_call_edgesplit(em, op)) { + if (fill_uloop_pairs) MEM_freeN(fill_uloop_pairs); + return OPERATOR_CANCELLED; + } } dist = FLT_MAX; - if (!edbm_rip_call_edgesplit(em, op)) { - return OPERATOR_CANCELLED; - } - else { + { /* --- select which vert --- */ BMVert *v_best = NULL; float l_prev_co[3], l_next_co[3], l_corner_co[3]; float scale; dist = FLT_MAX; - BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { /* disable by default, re-enable winner at end */ BM_vert_select_set(bm, v, FALSE); @@ -593,7 +829,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event) add_v3_v3v3(l_corner_co, l_prev_co, l_next_co); add_v3_v3(l_corner_co, l->v->co); - d = edbm_rip_rip_edgedist(ar, projectMat, l->v->co, l_corner_co, fmval); + d = edbm_rip_edgedist(ar, projectMat, l->v->co, l_corner_co, fmval, INSET_DEFAULT); if (d < dist) { v_best = v; dist = d; @@ -605,11 +841,17 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event) if (v_best) { BM_vert_select_set(bm, v_best, TRUE); if (ese.ele) { - BM_select_history_store(em->bm, v_best); + BM_select_history_store(bm, v_best); } } } + if (do_fill && fill_uloop_pairs) { + edbm_tagged_loop_pairs_do_fill_faces(bm, fill_uloop_pairs); + MEM_freeN(fill_uloop_pairs); + } + + if (totvert_orig == bm->totvert) { BKE_report(op->reports, RPT_ERROR, "No vertices could be ripped"); return OPERATOR_CANCELLED; @@ -623,6 +865,8 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event) */ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, wmEvent *event) { + const int do_fill = RNA_boolean_get(op->ptr, "use_fill"); + UnorderedLoopPair *fill_uloop_pairs = NULL; Object *obedit = CTX_data_edit_object(C); ARegion *ar = CTX_wm_region(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); @@ -633,25 +877,25 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, wmEvent *event) BMEdge *e, *e2; BMVert *v; const int totedge_orig = bm->totedge; - int i; float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]}; - int totedge; - int all_minifold; - EdgeLoopPair *eloop_pairs; ED_view3d_ob_project_mat_get(rv3d, obedit, projectMat); - /* important this runs on the original selection, before tempering with tagging */ + /* important this runs on the original selection, before tampering with tagging */ eloop_pairs = edbm_ripsel_looptag_helper(bm); /* expand edge selection */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + int all_manifold; + int totedge_manifold; /* manifold, visible edges */ + int i; + e2 = NULL; i = 0; - totedge = 0; - all_minifold = TRUE; + totedge_manifold = 0; + all_manifold = TRUE; BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { if (!BM_edge_is_wire(e) && @@ -663,22 +907,25 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, wmEvent *event) e2 = e; i++; } - totedge++; + totedge_manifold++; } /** #BM_vert_other_disk_edge has no hidden checks so don't check hidden here */ - if ((all_minifold == TRUE) && (BM_edge_is_manifold(e) == FALSE)) { - all_minifold = FALSE; + if ((all_manifold == TRUE) && (BM_edge_is_manifold(e) == FALSE)) { + all_manifold = FALSE; } } /* single edge, extend */ if (i == 1 && e2->l) { - if ((totedge == 4) || (all_minifold == FALSE)) { + /* note: if the case of 3 edges has one change in loop stepping, + * if this becomes more involved we may be better off splitting + * the 3 edge case into its own else-if branch */ + if ((totedge_manifold == 4 || totedge_manifold == 3) || (all_manifold == FALSE)) { BMLoop *l_a = e2->l; BMLoop *l_b = l_a->radial_next; - /* find the best face to follow, this what the edge won't point away from + /* find the best face to follow, this way the edge won't point away from * the mouse when there are more then 4 (takes the shortest face fan around) */ l = (edbm_rip_edge_side_measure(e2, l_a, ar, projectMat, fmval) < edbm_rip_edge_side_measure(e2, l_b, ar, projectMat, fmval)) ? l_a : l_b; @@ -688,9 +935,12 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, wmEvent *event) * not crashing but adds duplicate edge. */ if (BM_edge_is_manifold(l->e)) { l = l->radial_next; - l = BM_face_other_edge_loop(l->f, l->e, v); + + if (totedge_manifold != 3) + l = BM_face_other_edge_loop(l->f, l->e, v); if (l) { + BLI_assert(!BM_elem_flag_test(l->e, BM_ELEM_TAG)); BM_elem_flag_enable(l->e, BM_ELEM_TAG); } } @@ -699,13 +949,20 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, wmEvent *event) e = BM_vert_other_disk_edge(v, e2); if (e) { + BLI_assert(!BM_elem_flag_test(e, BM_ELEM_TAG)); BM_elem_flag_enable(e, BM_ELEM_TAG); } } } } + /* keep directly before edgesplit */ + if (do_fill) { + fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm); + } + if (!edbm_rip_call_edgesplit(em, op)) { + if (fill_uloop_pairs) MEM_freeN(fill_uloop_pairs); return OPERATOR_CANCELLED; } @@ -718,6 +975,11 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, wmEvent *event) ar, projectMat, fmval); MEM_freeN(eloop_pairs); + if (do_fill && fill_uloop_pairs) { + edbm_tagged_loop_pairs_do_fill_faces(bm, fill_uloop_pairs); + MEM_freeN(fill_uloop_pairs); + } + if (totedge_orig == bm->totedge) { BKE_report(op->reports, RPT_ERROR, "No edges could be ripped"); return OPERATOR_CANCELLED; @@ -740,12 +1002,12 @@ static int edbm_rip_invoke(bContext *C, wmOperator *op, wmEvent *event) int ret; /* running in face mode hardly makes sense, so convert to region loop and rip */ - if (em->bm->totfacesel) { + if (bm->totfacesel) { /* highly nifty but hard to support since the operator can fail and we're left * with modified selection */ // WM_operator_name_call(C, "MESH_OT_region_to_loop", WM_OP_INVOKE_DEFAULT, NULL); - BKE_report(op->reports, RPT_ERROR, "Can't rip selected faces"); + BKE_report(op->reports, RPT_ERROR, "Cannot rip selected faces"); return OPERATOR_CANCELLED; } @@ -760,7 +1022,7 @@ static int edbm_rip_invoke(bContext *C, wmOperator *op, wmEvent *event) */ /* BM_ELEM_SELECT --> BM_ELEM_TAG */ - BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT)); } @@ -804,5 +1066,6 @@ void MESH_OT_rip(wmOperatorType *ot) /* to give to transform */ Transform_Properties(ot, P_PROPORTIONAL); - RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", ""); + RNA_def_boolean(ot->srna, "mirror", FALSE, "Mirror Editing", ""); + RNA_def_boolean(ot->srna, "use_fill", FALSE, "Fill", "Fill the ripped region"); } diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 81776ff7f4f..0379068afd9 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -57,6 +57,7 @@ #include "ED_mesh.h" #include "ED_screen.h" #include "ED_uvedit.h" +#include "ED_object.h" #include "ED_view3d.h" #include "BIF_gl.h" @@ -131,7 +132,7 @@ unsigned int bm_solidoffs = 0, bm_wireoffs = 0, bm_vertoffs = 0; /* set in dr static char *selbuf = NULL; /* opengl doesn't support concave... */ -static void draw_triangulated(int mcords[][2], short tot) +static void draw_triangulated(const int mcords[][2], const short tot) { ListBase lb = {NULL, NULL}; DispList *dl; @@ -227,7 +228,7 @@ void EDBM_backbuf_free(void) * - grab again and compare * returns 'OK' */ -int EDBM_backbuf_border_mask_init(ViewContext *vc, int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax) +int EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax) { unsigned int *dr, *drm; struct ImBuf *buf, *bufmask; @@ -330,9 +331,9 @@ int EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) } -static void findnearestvert__doClosest(void *userData, BMVert *eve, int x, int y, int index) +static void findnearestvert__doClosest(void *userData, BMVert *eve, const float screen_co[2], int index) { - struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; BMVert *closest; } *data = userData; + struct { float mval_fl[2], pass, select, strict; float dist, lastIndex, closestIndex; BMVert *closest; } *data = userData; if (data->pass == 0) { if (index <= data->lastIndex) @@ -344,18 +345,18 @@ static void findnearestvert__doClosest(void *userData, BMVert *eve, int x, int y } if (data->dist > 3) { - int temp = abs(data->mval[0] - x) + abs(data->mval[1] - y); + float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co); if (BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->select) { if (data->strict == 1) { return; } else { - temp += 5; + dist_test += 5; } } - if (temp < data->dist) { - data->dist = temp; + if (dist_test < data->dist) { + data->dist = dist_test; data->closest = eve; data->closestIndex = index; } @@ -382,10 +383,10 @@ static unsigned int findnearestvert__backbufIndextest(void *handle, unsigned int * if 0, unselected vertice are given the bias * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased */ -BMVert *EDBM_vert_find_nearest(ViewContext *vc, int *dist, short sel, short strict) +BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist, const short sel, const short strict) { if (vc->v3d->drawtype > OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) { - int distance; + float distance; unsigned int index; BMVert *eve; @@ -400,8 +401,8 @@ BMVert *EDBM_vert_find_nearest(ViewContext *vc, int *dist, short sel, short stri eve = BM_vert_at_index(vc->em->bm, index - 1); - if (eve && distance < *dist) { - *dist = distance; + if (eve && distance < *r_dist) { + *r_dist = distance; return eve; } else { @@ -410,7 +411,7 @@ BMVert *EDBM_vert_find_nearest(ViewContext *vc, int *dist, short sel, short stri } else { - struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; BMVert *closest; } data; + struct { float mval_fl[2], pass, select, strict; float dist, lastIndex, closestIndex; BMVert *closest; } data; static int lastSelectedIndex = 0; static BMVert *lastSelected = NULL; @@ -420,10 +421,10 @@ BMVert *EDBM_vert_find_nearest(ViewContext *vc, int *dist, short sel, short stri } data.lastIndex = lastSelectedIndex; - data.mval[0] = vc->mval[0]; - data.mval[1] = vc->mval[1]; + data.mval_fl[0] = vc->mval[0]; + data.mval_fl[1] = vc->mval[1]; data.select = sel; - data.dist = *dist; + data.dist = *r_dist; data.strict = strict; data.closest = NULL; data.closestIndex = 0; @@ -432,14 +433,14 @@ BMVert *EDBM_vert_find_nearest(ViewContext *vc, int *dist, short sel, short stri ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_CLIP_TEST_RV3D_CLIPPING); + mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); if (data.dist > 3) { data.pass = 1; - mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_CLIP_TEST_RV3D_CLIPPING); + mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } - *dist = data.dist; + *r_dist = data.dist; lastSelected = data.closest; lastSelectedIndex = data.closestIndex; @@ -448,7 +449,7 @@ BMVert *EDBM_vert_find_nearest(ViewContext *vc, int *dist, short sel, short stri } /* returns labda for closest distance v1 to line-piece v2 - v3 */ -float labda_PdistVL2Dfl(const float v1[3], const float v2[3], const float v3[3]) +float labda_PdistVL2Dfl(const float v1[2], const float v2[2], const float v3[2]) { float rc[2], len; @@ -462,18 +463,12 @@ float labda_PdistVL2Dfl(const float v1[3], const float v2[3], const float v3[3]) } /* note; uses v3d, so needs active 3d window */ -static void findnearestedge__doClosest(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int UNUSED(index)) +static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index)) { - struct { ViewContext vc; float mval[2]; int dist; BMEdge *closest; } *data = userData; - float v1[2], v2[2]; + struct { ViewContext vc; float mval_fl[2]; float dist; BMEdge *closest; } *data = userData; int distance; - - v1[0] = x0; - v1[1] = y0; - v2[0] = x1; - v2[1] = y1; - - distance = dist_to_line_segment_v2(data->mval, v1, v2); + + distance = dist_to_line_segment_v2(data->mval_fl, screen_co_a, screen_co_b); if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { distance += 5; @@ -481,13 +476,12 @@ static void findnearestedge__doClosest(void *userData, BMEdge *eed, int x0, int if (distance < data->dist) { if (data->vc.rv3d->rflag & RV3D_CLIPPING) { - float labda = labda_PdistVL2Dfl(data->mval, v1, v2); + float labda = labda_PdistVL2Dfl(data->mval_fl, screen_co_a, screen_co_b); float vec[3]; vec[0] = eed->v1->co[0] + labda * (eed->v2->co[0] - eed->v1->co[0]); vec[1] = eed->v1->co[1] + labda * (eed->v2->co[1] - eed->v1->co[1]); vec[2] = eed->v1->co[2] + labda * (eed->v2->co[2] - eed->v1->co[2]); - mul_m4_v3(data->vc.obedit->obmat, vec); if (ED_view3d_clipping_test(data->vc.rv3d, vec, TRUE) == 0) { data->dist = distance; @@ -500,11 +494,11 @@ static void findnearestedge__doClosest(void *userData, BMEdge *eed, int x0, int } } } -BMEdge *EDBM_edge_find_nearest(ViewContext *vc, int *dist) +BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist) { if (vc->v3d->drawtype > OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) { - int distance; + float distance; unsigned int index; BMEdge *eed; @@ -513,8 +507,8 @@ BMEdge *EDBM_edge_find_nearest(ViewContext *vc, int *dist) index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_solidoffs, bm_wireoffs, &distance, 0, NULL, NULL); eed = BM_edge_at_index(vc->em->bm, index - 1); - if (eed && distance < *dist) { - *dist = distance; + if (eed && distance < *r_dist) { + *r_dist = distance; return eed; } else { @@ -522,36 +516,37 @@ BMEdge *EDBM_edge_find_nearest(ViewContext *vc, int *dist) } } else { - struct { ViewContext vc; float mval[2]; int dist; BMEdge *closest; } data; + struct { ViewContext vc; float mval_fl[2]; float dist; BMEdge *closest; } data; data.vc = *vc; - data.mval[0] = vc->mval[0]; - data.mval[1] = vc->mval[1]; - data.dist = *dist; + data.mval_fl[0] = vc->mval[0]; + data.mval_fl[1] = vc->mval[1]; + data.dist = *r_dist; data.closest = NULL; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, 2); + mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, V3D_PROJ_TEST_CLIP_WIN); - *dist = data.dist; + *r_dist = data.dist; return data.closest; } } -static void findnearestface__getDistance(void *userData, BMFace *efa, int x, int y, int UNUSED(index)) +static void findnearestface__getDistance(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index)) { - struct { short mval[2]; int dist; BMFace *toFace; } *data = userData; + struct { float mval_fl[2]; float dist; BMFace *toFace; } *data = userData; if (efa == data->toFace) { - int temp = abs(data->mval[0] - x) + abs(data->mval[1] - y); + const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co); - if (temp < data->dist) - data->dist = temp; + if (dist_test < data->dist) { + data->dist = dist_test; + } } } -static void findnearestface__doClosest(void *userData, BMFace *efa, int x, int y, int index) +static void findnearestface__doClosest(void *userData, BMFace *efa, const float screen_co[2], int index) { - struct { short mval[2], pass; int dist, lastIndex, closestIndex; BMFace *closest; } *data = userData; + struct { float mval_fl[2], pass; float dist, lastIndex, closestIndex; BMFace *closest; } *data = userData; if (data->pass == 0) { if (index <= data->lastIndex) @@ -563,17 +558,17 @@ static void findnearestface__doClosest(void *userData, BMFace *efa, int x, int y } if (data->dist > 3) { - int temp = abs(data->mval[0] - x) + abs(data->mval[1] - y); + const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co); - if (temp < data->dist) { - data->dist = temp; + if (dist_test < data->dist) { + data->dist = dist_test; data->closest = efa; data->closestIndex = index; } } } -BMFace *EDBM_face_find_nearest(ViewContext *vc, int *dist) +BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) { if (vc->v3d->drawtype > OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) { @@ -586,17 +581,17 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, int *dist) efa = BM_face_at_index(vc->em->bm, index - 1); if (efa) { - struct { short mval[2]; int dist; BMFace *toFace; } data; + struct { float mval_fl[2]; float dist; BMFace *toFace; } data; - data.mval[0] = vc->mval[0]; - data.mval[1] = vc->mval[1]; + data.mval_fl[0] = vc->mval[0]; + data.mval_fl[1] = vc->mval[1]; data.dist = 0x7FFF; /* largest short */ data.toFace = efa; - mesh_foreachScreenFace(vc, findnearestface__getDistance, &data); + mesh_foreachScreenFace(vc, findnearestface__getDistance, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - if (vc->em->selectmode == SCE_SELECT_FACE || data.dist < *dist) { /* only faces, no dist check */ - *dist = data.dist; + if ((vc->em->selectmode == SCE_SELECT_FACE) || (data.dist < *r_dist)) { /* only faces, no dist check */ + *r_dist = data.dist; return efa; } } @@ -604,7 +599,7 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, int *dist) return NULL; } else { - struct { short mval[2], pass; int dist, lastIndex, closestIndex; BMFace *closest; } data; + struct { float mval_fl[2], pass; float dist, lastIndex, closestIndex; BMFace *closest; } data; static int lastSelectedIndex = 0; static BMFace *lastSelected = NULL; @@ -614,23 +609,23 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, int *dist) } data.lastIndex = lastSelectedIndex; - data.mval[0] = vc->mval[0]; - data.mval[1] = vc->mval[1]; - data.dist = *dist; + data.mval_fl[0] = vc->mval[0]; + data.mval_fl[1] = vc->mval[1]; + data.dist = *r_dist; data.closest = NULL; data.closestIndex = 0; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); data.pass = 0; - mesh_foreachScreenFace(vc, findnearestface__doClosest, &data); + mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - if (data.dist > 3) { + if (data.dist > 3.0f) { data.pass = 1; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenFace(vc, findnearestface__doClosest, &data); + mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } - *dist = data.dist; + *r_dist = data.dist; lastSelected = data.closest; lastSelectedIndex = data.closestIndex; @@ -646,7 +641,7 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, int *dist) static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa) { BMEditMesh *em = vc->em; - int dist = 75; + float dist = 75.0f; *r_eve = NULL; *r_eed = NULL; @@ -676,6 +671,13 @@ static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, } /* **************** SIMILAR "group" SELECTS. FACE, EDGE AND VERTEX ************** */ +static EnumPropertyItem prop_similar_compare_types[] = { + {SIM_CMP_EQ, "EQUAL", 0, "Equal", ""}, + {SIM_CMP_GT, "GREATER", 0, "Greater", ""}, + {SIM_CMP_LT, "LESS", 0, "Less", ""}, + + {0, NULL, 0, NULL, NULL} +}; static EnumPropertyItem prop_similar_types[] = { {SIMVERT_NORMAL, "NORMAL", 0, "Normal", ""}, @@ -695,6 +697,7 @@ static EnumPropertyItem prop_similar_types[] = { {SIMFACE_MATERIAL, "MATERIAL", 0, "Material", ""}, {SIMFACE_IMAGE, "IMAGE", 0, "Image", ""}, {SIMFACE_AREA, "AREA", 0, "Area", ""}, + {SIMFACE_SIDES, "SIDES", 0, "Polygon Sides", ""}, {SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""}, {SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""}, {SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""}, @@ -711,11 +714,14 @@ static int similar_face_select_exec(bContext *C, wmOperator *op) BMOperator bmop; /* get the type from RNA */ - int type = RNA_enum_get(op->ptr, "type"); - float thresh = RNA_float_get(op->ptr, "threshold"); + const int type = RNA_enum_get(op->ptr, "type"); + const float thresh = RNA_float_get(op->ptr, "threshold"); + const int compare = RNA_enum_get(op->ptr, "compare"); /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ - EDBM_op_init(em, &bmop, op, "similar_faces faces=%hf type=%i thresh=%f", BM_ELEM_SELECT, type, thresh); + EDBM_op_init(em, &bmop, op, + "similar_faces faces=%hf type=%i thresh=%f compare=%i", + BM_ELEM_SELECT, type, thresh, compare); /* execute the operator */ BMO_op_exec(em->bm, &bmop); @@ -749,11 +755,14 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op) BMOperator bmop; /* get the type from RNA */ - int type = RNA_enum_get(op->ptr, "type"); - float thresh = RNA_float_get(op->ptr, "threshold"); + const int type = RNA_enum_get(op->ptr, "type"); + const float thresh = RNA_float_get(op->ptr, "threshold"); + const int compare = RNA_enum_get(op->ptr, "compare"); /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ - EDBM_op_init(em, &bmop, op, "similar_edges edges=%he type=%i thresh=%f", BM_ELEM_SELECT, type, thresh); + EDBM_op_init(em, &bmop, op, + "similar_edges edges=%he type=%i thresh=%f compare=%i", + BM_ELEM_SELECT, type, thresh, compare); /* execute the operator */ BMO_op_exec(em->bm, &bmop); @@ -790,11 +799,14 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) BMEditMesh *em = BMEdit_FromObject(ob); BMOperator bmop; /* get the type from RNA */ - int type = RNA_enum_get(op->ptr, "type"); + const int type = RNA_enum_get(op->ptr, "type"); float thresh = RNA_float_get(op->ptr, "threshold"); + const int compare = RNA_enum_get(op->ptr, "compare"); /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ - EDBM_op_init(em, &bmop, op, "similar_verts verts=%hv type=%i thresh=%f", BM_ELEM_SELECT, type, thresh); + EDBM_op_init(em, &bmop, op, + "similar_verts verts=%hv type=%i thresh=%f compare=%i", + BM_ELEM_SELECT, type, thresh, compare); /* execute the operator */ BMO_op_exec(em->bm, &bmop); @@ -823,7 +835,7 @@ static int edbm_select_similar_exec(bContext *C, wmOperator *op) ToolSettings *ts = CTX_data_tool_settings(C); PropertyRNA *prop = RNA_struct_find_property(op->ptr, "threshold"); - int type = RNA_enum_get(op->ptr, "type"); + const int type = RNA_enum_get(op->ptr, "type"); if (!RNA_property_is_set(op->ptr, prop)) { RNA_property_float_set(op->ptr, prop, ts->select_thresh); @@ -834,7 +846,7 @@ static int edbm_select_similar_exec(bContext *C, wmOperator *op) if (type < 100) return similar_vert_select_exec(C, op); else if (type < 200) return similar_edge_select_exec(C, op); - else return similar_face_select_exec(C, op); + else return similar_face_select_exec(C, op); } static EnumPropertyItem *select_similar_type_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), @@ -898,7 +910,9 @@ void MESH_OT_select_similar(wmOperatorType *ot) prop = ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, SIMVERT_NORMAL, "Type", ""); RNA_def_enum_funcs(prop, select_similar_type_itemf); - RNA_def_float(ot->srna, "threshold", 0.0, 0.0, 1.0, "Threshold", "", 0.01, 1.0); + RNA_def_enum(ot->srna, "compare", prop_similar_compare_types, SIM_CMP_EQ, "Compare", ""); + + RNA_def_float(ot->srna, "threshold", 0.0, 0.0, 1.0, "Threshold", "", 0.0, 1.0); } /* ***************************************************** */ @@ -1005,7 +1019,7 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short ring) BMEditMesh *em; BMEdge *eed; int select = TRUE; - int dist = 50; + float dist = 50.0f; float mvalf[2]; em_setup_viewcontext(C, &vc); @@ -1051,21 +1065,27 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short ring) /* sets as active, useful for other tools */ if (select) { if (em->selectmode & SCE_SELECT_VERTEX) { - /* Find nearest vert from mouse. */ + /* Find nearest vert from mouse + * (initialize to large values incase only one vertex can be projected) */ float v1_co[2], v2_co[2]; + float length_1 = FLT_MAX; + float length_2 = FLT_MAX; /* We can't be sure this has already been set... */ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); - project_float_noclip(vc.ar, eed->v1->co, v1_co); - project_float_noclip(vc.ar, eed->v2->co, v2_co); + + if (ED_view3d_project_float_object(vc.ar, eed->v1->co, v1_co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + length_1 = len_squared_v2v2(mvalf, v1_co); + } + + if (ED_view3d_project_float_object(vc.ar, eed->v2->co, v2_co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + length_2 = len_squared_v2v2(mvalf, v2_co); + } #if 0 printf("mouse to v1: %f\nmouse to v2: %f\n", len_squared_v2v2(mvalf, v1_co), len_squared_v2v2(mvalf, v2_co)); #endif - if (len_squared_v2v2(mvalf, v1_co) < len_squared_v2v2(mvalf, v2_co)) - BM_select_history_store(em->bm, eed->v1); - else - BM_select_history_store(em->bm, eed->v2); + BM_select_history_store(em->bm, (length_1 < length_2) ? eed->v1 : eed->v2); } else if (em->selectmode & SCE_SELECT_EDGE) { BM_select_history_store(em->bm, eed); @@ -1085,12 +1105,13 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short ring) float co[2], tdist; BM_face_calc_center_mean(f, cent); - project_float_noclip(vc.ar, cent, co); - tdist = len_squared_v2v2(mvalf, co); - if (tdist < best_dist) { -/* printf("Best face: %p (%f)\n", f, tdist);*/ - best_dist = tdist; - efa = f; + if (ED_view3d_project_float_object(vc.ar, cent, co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + tdist = len_squared_v2v2(mvalf, co); + if (tdist < best_dist) { +/* printf("Best face: %p (%f)\n", f, tdist);*/ + best_dist = tdist; + efa = f; + } } } } @@ -1324,7 +1345,7 @@ static int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *source, B EDBM_index_arrays_init(em, 1, 1, 0); targetnum = BM_elem_index_get(target); - while (!BLI_heap_empty(heap)) { + while (!BLI_heap_is_empty(heap)) { mednum = GET_INT_FROM_POINTER(BLI_heap_popmin(heap)); e = EDBM_edge_at_index(em, mednum); @@ -1386,7 +1407,7 @@ static int mouse_mesh_shortest_path(bContext *C, int mval[2]) ViewContext vc; BMEditMesh *em; BMEdge *e; - int dist = 50; + float dist = 75.0f; em_setup_viewcontext(C, &vc); vc.mval[0] = mval[0]; @@ -1435,7 +1456,7 @@ static int mouse_mesh_shortest_path(bContext *C, int mval[2]) case EDGE_MODE_TAG_SHARP: me->drawflag |= ME_DRAWSHARP; break; - case EDGE_MODE_TAG_CREASE: + case EDGE_MODE_TAG_CREASE: me->drawflag |= ME_DRAWCREASES; break; case EDGE_MODE_TAG_BEVEL: @@ -1705,7 +1726,7 @@ void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const s BM_edge_select_set(em->bm, eed, TRUE); } } - } + } else if (selectmode_new == SCE_SELECT_FACE) { BMIter liter; BMLoop *l; @@ -2163,11 +2184,19 @@ static void walker_deselect_nth(BMEditMesh *em, int nth, int offset, BMHeader *h BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */ BMW_NIL_LAY); + /* use tag to avoid touching the same verts twice */ + BM_ITER_MESH (ele, &iter, bm, itertype) { + BM_elem_flag_disable(ele, BM_ELEM_TAG); + } + BLI_assert(walker.order == BMW_BREADTH_FIRST); for (ele = BMW_begin(&walker, h_act); ele != NULL; ele = BMW_step(&walker)) { - /* Deselect elements that aren't at "nth" depth from active */ - if ((offset + BMW_current_depth(&walker)) % nth) { - BM_elem_select_set(bm, ele, FALSE); + if (!BM_elem_flag_test(ele, BM_ELEM_TAG)) { + /* Deselect elements that aren't at "nth" depth from active */ + if ((offset + BMW_current_depth(&walker)) % nth) { + BM_elem_select_set(bm, ele, FALSE); + } + BM_elem_flag_enable(ele, BM_ELEM_TAG); } } BMW_end(&walker); @@ -2279,9 +2308,9 @@ static int edbm_select_nth_exec(bContext *C, wmOperator *op) void MESH_OT_select_nth(wmOperatorType *ot) { /* identifiers */ - ot->name = "Select Nth"; + ot->name = "Checker Deselect"; ot->idname = "MESH_OT_select_nth"; - ot->description = "Select every Nth element starting from a selected vertex, edge or face"; + ot->description = "Deselect every Nth element starting from a selected vertex, edge or face"; /* api callbacks */ ot->exec = edbm_select_nth_exec; @@ -2290,8 +2319,8 @@ void MESH_OT_select_nth(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_int(ot->srna, "nth", 2, 2, 100, "Nth Selection", "", 1, INT_MAX); - RNA_def_int(ot->srna, "offset", 0, 0, 100, "Offset", "", 0, INT_MAX); + RNA_def_int(ot->srna, "nth", 2, 2, INT_MAX, "Nth Selection", "", 2, 100); + RNA_def_int(ot->srna, "offset", 0, 0, INT_MAX, "Offset", "", 0, 100); } void em_setup_viewcontext(bContext *C, ViewContext *vc) @@ -2462,7 +2491,7 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op) */ if (em->selectmode == SCE_SELECT_FACE) { - BKE_report(op->reports, RPT_ERROR, "Doesn't work in face selection mode"); + BKE_report(op->reports, RPT_ERROR, "Does not work in face selection mode"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/mesh/editmesh_slide.c b/source/blender/editors/mesh/editmesh_slide.c index 86ea5bc8651..d370b5a881e 100644 --- a/source/blender/editors/mesh/editmesh_slide.c +++ b/source/blender/editors/mesh/editmesh_slide.c @@ -34,6 +34,8 @@ #include "BLI_array.h" #include "BLI_math.h" +#include "BLF_translation.h" + #include "BKE_context.h" #include "BKE_report.h" #include "BKE_tessmesh.h" @@ -113,11 +115,11 @@ static int vtx_slide_init(bContext *C, wmOperator *op) /* Custom data */ VertexSlideOp *vso; - const char *header_str = "Vertex Slide: Hover over an edge and left-click to select slide edge. " - "Left-Shift: Midpoint Snap, Left-Alt: Snap, Left-Ctrl: Snap&Merge"; + const char *header_str = TIP_("Vertex Slide: Hover over an edge and left-click to select slide edge. " + "Left-Shift: Midpoint Snap, Left-Alt: Snap, Left-Ctrl: Snap & Merge"); if (!obedit) { - BKE_report(op->reports, RPT_ERROR, "Vertex Slide Error: Not object in context"); + BKE_report(op->reports, RPT_ERROR, "Vertex slide error: no object in context"); return FALSE; } @@ -126,7 +128,7 @@ static int vtx_slide_init(bContext *C, wmOperator *op) /* Is there a starting vertex ? */ if (ese == NULL || (ese->htype != BM_VERT && ese->htype != BM_EDGE)) { - BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex Slide Error: Select a (single) vertex"); + BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex slide error: select a (single) vertex"); return FALSE; } @@ -177,7 +179,7 @@ static int vtx_slide_init(bContext *C, wmOperator *op) /* Init frame */ if (!vtx_slide_set_frame(vso)) { - BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex Slide: Can't find starting vertex!"); + BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex slide error: cannot find starting vertex!"); vtx_slide_exit(C, op); return FALSE; } @@ -381,22 +383,23 @@ static BMEdge *vtx_slide_nrst_in_frame(VertexSlideOp *vso, const float mval[2]) BMEdge *edge = NULL; float v1_proj[3], v2_proj[3]; - float dist = 0; float min_dist = FLT_MAX; for (i = 0; i < vso->disk_edges; i++) { edge = vso->edge_frame[i]; mul_v3_m4v3(v1_proj, vso->obj->obmat, edge->v1->co); - project_float_noclip(vso->active_region, v1_proj, v1_proj); - mul_v3_m4v3(v2_proj, vso->obj->obmat, edge->v2->co); - project_float_noclip(vso->active_region, v2_proj, v2_proj); - dist = dist_to_line_segment_v2(mval, v1_proj, v2_proj); - if (dist < min_dist) { - min_dist = dist; - cl_edge = edge; + /* we could use ED_view3d_project_float_object here, but for now dont since we dont have the context */ + if ((ED_view3d_project_float_global(vso->active_region, v1_proj, v1_proj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) && + (ED_view3d_project_float_global(vso->active_region, v2_proj, v2_proj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK)) + { + const float dist = dist_to_line_segment_v2(mval, v1_proj, v2_proj); + if (dist < min_dist) { + min_dist = dist; + cl_edge = edge; + } } } } @@ -408,7 +411,8 @@ static void vtx_slide_find_edge(VertexSlideOp *vso, wmEvent *event) /* Nearest edge */ BMEdge *nst_edge = NULL; - const float mval_float[] = { (float)event->mval[0], (float)event->mval[1]}; + const float mval_float[2] = {(float)event->mval[0], + (float)event->mval[1]}; /* Set mouse coords */ copy_v2_v2_int(vso->view_context->mval, event->mval); @@ -448,17 +452,21 @@ static void vtx_slide_update(VertexSlideOp *vso, wmEvent *event) /* Calculate interpolation value for preview */ float t_val; - float mval_float[] = { (float)event->mval[0], (float)event->mval[1]}; + float mval_float[2] = { (float)event->mval[0], (float)event->mval[1]}; float closest_2d[2]; other = BM_edge_other_vert(edge, vso->start_vtx); /* Project points onto screen and do interpolation in 2D */ mul_v3_m4v3(start_vtx_proj, vso->obj->obmat, vso->start_vtx->co); - project_float_noclip(vso->active_region, start_vtx_proj, start_vtx_proj); - mul_v3_m4v3(edge_other_proj, vso->obj->obmat, other->co); - project_float_noclip(vso->active_region, edge_other_proj, edge_other_proj); + + if ((ED_view3d_project_float_global(vso->active_region, edge_other_proj, edge_other_proj, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) || + (ED_view3d_project_float_global(vso->active_region, start_vtx_proj, start_vtx_proj, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK)) + { + /* not much we can do here */ + return; + } closest_to_line_v2(closest_2d, mval_float, start_vtx_proj, edge_other_proj); @@ -470,7 +478,7 @@ static void vtx_slide_update(VertexSlideOp *vso, wmEvent *event) if (edge_len <= 0.0f) edge_len = VTX_SLIDE_SNAP_THRSH; - edge_len = (len_v3v3(edge->v1->co, edge->v2->co) * VTX_SLIDE_SNAP_THRSH) / edge_len; + edge_len = (BM_edge_calc_length(edge) * VTX_SLIDE_SNAP_THRSH) / edge_len; vso->snap_threshold = edge_len; @@ -713,7 +721,7 @@ static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_u /* Is there a starting vertex ? */ if ((ese == NULL) || (ese->htype != BM_VERT && ese->htype != BM_EDGE)) { - BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex Slide Error: Select a (single) vertex"); + BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex slide error: select a (single) vertex"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 546b28bfb25..f10faddc169 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -41,7 +41,9 @@ #include "RNA_define.h" #include "RNA_access.h" +#include "BLI_array.h" #include "BLI_blenlib.h" +#include "BLI_noise.h" #include "BLI_math.h" #include "BLI_rand.h" @@ -49,6 +51,7 @@ #include "BKE_context.h" #include "BKE_cdderivedmesh.h" #include "BKE_depsgraph.h" +#include "BKE_mesh.h" #include "BKE_object.h" #include "BKE_report.h" #include "BKE_texture.h" @@ -72,6 +75,8 @@ #include "mesh_intern.h" +#define MVAL_PIXEL_MARGIN 5.0f + /* allow accumulated normals to form a new direction but don't * accept direct opposite directions else they will cancel each other out */ static void add_normal_aligned(float nor[3], const float add[3]) @@ -153,19 +158,67 @@ void MESH_OT_subdivide(wmOperatorType *ot) } -void EMBM_project_snap_verts(bContext *C, ARegion *ar, Object *obedit, BMEditMesh *em) +static int edbm_unsubdivide_exec(bContext *C, wmOperator *op) { + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BMEdit_FromObject(obedit); + BMOperator bmop; + + int iterations = RNA_int_get(op->ptr, "iterations"); + + EDBM_op_init(em, &bmop, op, + "unsubdivide verts=%hv iterations=%i", BM_ELEM_SELECT, iterations); + + BMO_op_exec(em->bm, &bmop); + + if (!EDBM_op_finish(em, &bmop, op, TRUE)) { + return 0; + } + + if ((em->selectmode & SCE_SELECT_VERTEX) == 0) { + EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX); /* need to flush vert->face first */ + } + EDBM_selectmode_flush(em); + + EDBM_update_generic(C, em, TRUE); + + return OPERATOR_FINISHED; +} + +void MESH_OT_unsubdivide(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Un-Subdivide"; + ot->description = "UnSubdivide selected edges & faces"; + ot->idname = "MESH_OT_unsubdivide"; + + /* api callbacks */ + ot->exec = edbm_unsubdivide_exec; + ot->poll = ED_operator_editmesh; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* props */ + RNA_def_int(ot->srna, "iterations", 2, 1, INT_MAX, "Iterations", "Number of times to unsubdivide", 1, 100); +} + +void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em) +{ + Object *obedit = em->ob; BMIter iter; BMVert *eve; + ED_view3d_init_mats_rv3d(obedit, ar->regiondata); + BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { - float mval[2], vec[3], no_dummy[3]; + float mval[2], co_proj[3], no_dummy[3]; int dist_dummy; - mul_v3_m4v3(vec, obedit->obmat, eve->co); - project_float_noclip(ar, vec, mval); - if (snapObjectsContext(C, mval, &dist_dummy, vec, no_dummy, SNAP_NOT_OBEDIT)) { - mul_v3_m4v3(eve->co, obedit->imat, vec); + 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)) { + mul_v3_m4v3(eve->co, obedit->imat, co_proj); + } } } } @@ -202,7 +255,7 @@ static short edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const c return 0; } - return 's'; // s is shrink/fatten + return 's'; /* s is shrink/fatten */ } /* extrudes individual edges */ @@ -222,7 +275,7 @@ static short edbm_extrude_edges_indiv(BMEditMesh *em, wmOperator *op, const char return 0; } - return 'n'; // n is normal grab + return 'n'; /* n is normal grab */ } /* extrudes individual vertices */ @@ -242,7 +295,7 @@ static short edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char return 0; } - return 'g'; // g is grab + return 'g'; /* g is grab */ } static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag, float nor[3]) @@ -426,8 +479,8 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* props */ - RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, 100.0f, "Offset", "", 0.0f, FLT_MAX); - RNA_def_int(ot->srna, "steps", 10, 0, 180, "Steps", "", 0, INT_MAX); + RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, FLT_MAX, "Offset", "", 0.0f, 100.0f); + RNA_def_int(ot->srna, "steps", 10, 0, INT_MAX, "Steps", "", 0, 180); } /* generic extern called extruder */ @@ -439,16 +492,17 @@ static int edbm_extrude_mesh(Scene *scene, Object *obedit, BMEditMesh *em, wmOpe zero_v3(nor); + /* XXX If those popup menus were to be enabled again, please get rid of this "menu string" syntax! */ if (em->selectmode & SCE_SELECT_VERTEX) { if (em->bm->totvertsel == 0) nr = 0; else if (em->bm->totvertsel == 1) nr = 4; else if (em->bm->totedgesel == 0) nr = 4; else if (em->bm->totfacesel == 0) - nr = 3; // pupmenu("Extrude %t|Only Edges%x3|Only Vertices%x4"); + nr = 3; /* pupmenu("Extrude %t|Only Edges %x3|Only Vertices %x4"); */ else if (em->bm->totfacesel == 1) - nr = 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3|Only Vertices%x4"); + nr = 1; /* pupmenu("Extrude %t|Region %x1|Only Edges% x3|Only Vertices %x4"); */ else - nr = 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3|Only Vertices%x4"); + nr = 1; /* pupmenu("Extrude %t|Region %x1|Individual Faces %x2|Only Edges %x3|Only Vertices %x4"); */ } else if (em->selectmode & SCE_SELECT_EDGE) { if (em->bm->totedgesel == 0) nr = 0; @@ -458,16 +512,16 @@ static int edbm_extrude_mesh(Scene *scene, Object *obedit, BMEditMesh *em, wmOpe else if (em->totedgesel == 1) nr = 3; else if (em->totfacesel == 0) nr = 3; else if (em->totfacesel == 1) - nr = 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3"); + nr = 1; /* pupmenu("Extrude %t|Region %x1|Only Edges %x3"); */ else - nr = 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3"); + nr = 1; /* pupmenu("Extrude %t|Region %x1|Individual Faces %x2|Only Edges %x3"); */ #endif } else { if (em->bm->totfacesel == 0) nr = 0; else if (em->bm->totfacesel == 1) nr = 1; else - nr = 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2"); + nr = 1; /* pupmenu("Extrude %t|Region %x1|Individual Faces %x2"); */ } if (nr < 1) return 'g'; @@ -730,7 +784,10 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent short use_proj; em_setup_viewcontext(C, &vc); - + + ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); + + use_proj = ((vc.scene->toolsettings->snap_flag & SCE_SNAP) && (vc.scene->toolsettings->snap_mode == SCE_SNAP_MODE_FACE)); @@ -758,27 +815,27 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent done = FALSE; BM_ITER_MESH (eed, &iter, vc.em->bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { - float co1[3], co2[3]; - mul_v3_m4v3(co1, vc.obedit->obmat, eed->v1->co); - mul_v3_m4v3(co2, vc.obedit->obmat, eed->v2->co); - project_float_noclip(vc.ar, co1, co1); - project_float_noclip(vc.ar, co2, co2); + float co1[2], co2[2]; - /* 2D rotate by 90d while adding. - * (x, y) = (y, -x) - * - * accumulate the screenspace normal in 2D, - * with screenspace edge length weighting the result. */ - if (line_point_side_v2(co1, co2, mval_f) >= 0.0f) { - nor[0] += (co1[1] - co2[1]); - nor[1] += -(co1[0] - co2[0]); - } - else { - nor[0] += (co2[1] - co1[1]); - nor[1] += -(co2[0] - co1[0]); + if ((ED_view3d_project_float_object(vc.ar, eed->v1->co, co1, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) && + (ED_view3d_project_float_object(vc.ar, eed->v2->co, co2, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK)) + { + /* 2D rotate by 90d while adding. + * (x, y) = (y, -x) + * + * accumulate the screenspace normal in 2D, + * with screenspace edge length weighting the result. */ + if (line_point_side_v2(co1, co2, mval_f) >= 0.0f) { + nor[0] += (co1[1] - co2[1]); + nor[1] += -(co1[0] - co2[0]); + } + else { + nor[0] += (co2[1] - co1[1]); + nor[1] += -(co2[0] - co1[0]); + } + done = TRUE; } } - done = TRUE; } if (done) { @@ -835,7 +892,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent /* also project the source, for retopo workflow */ if (use_proj) - EMBM_project_snap_verts(C, vc.ar, vc.obedit, vc.em); + EMBM_project_snap_verts(C, vc.ar, vc.em); } edbm_extrude_edge(vc.obedit, vc.em, BM_ELEM_SELECT, nor); @@ -868,7 +925,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent } if (use_proj) - EMBM_project_snap_verts(C, vc.ar, vc.obedit, vc.em); + EMBM_project_snap_verts(C, vc.ar, vc.em); /* This normally happens when pushing undo but modal operators * like this one don't push undo data until after modal mode is @@ -1208,10 +1265,13 @@ static int edbm_vert_connect(bContext *C, wmOperator *op) if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; } - - EDBM_update_generic(C, em, TRUE); + else { + EDBM_selectmode_flush(em); /* so newly created edges get the selection state from the vertex */ - return len ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + EDBM_update_generic(C, em, TRUE); + + return len ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + } } void MESH_OT_vert_connect(wmOperatorType *ot) @@ -1600,12 +1660,94 @@ void MESH_OT_vertices_smooth(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_int(ot->srna, "repeat", 1, 1, 100, "Number of times to smooth the mesh", "", 1, INT_MAX); + RNA_def_int(ot->srna, "repeat", 1, 1, 1000, "Number of times to smooth the mesh", "", 1, 100); RNA_def_boolean(ot->srna, "xaxis", 1, "X-Axis", "Smooth along the X axis"); RNA_def_boolean(ot->srna, "yaxis", 1, "Y-Axis", "Smooth along the Y axis"); RNA_def_boolean(ot->srna, "zaxis", 1, "Z-Axis", "Smooth along the Z axis"); } +static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) +{ + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BMEdit_FromObject(obedit); + int usex = TRUE, usey = TRUE, usez = TRUE, volume_preservation = TRUE; + int i, repeat; + float lambda; + float lambda_border; + BMIter fiter; + BMFace *f; + + /* Check if select faces are triangles */ + BM_ITER_MESH (f, &fiter, em->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { + if (f->len > 4) { + BKE_report(op->reports, RPT_WARNING, "Selected faces must be triangles or quads"); + return OPERATOR_CANCELLED; + } + } + } + + /* mirror before smooth */ + if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) { + EDBM_verts_mirror_cache_begin(em, TRUE); + } + + repeat = RNA_int_get(op->ptr, "repeat"); + lambda = RNA_float_get(op->ptr, "lambda"); + lambda_border = RNA_float_get(op->ptr, "lambda_border"); + usex = RNA_boolean_get(op->ptr, "use_x"); + usey = RNA_boolean_get(op->ptr, "use_y"); + usez = RNA_boolean_get(op->ptr, "use_z"); + volume_preservation = RNA_boolean_get(op->ptr, "volume_preservation"); + if (!repeat) + repeat = 1; + + for (i = 0; i < repeat; i++) { + if (!EDBM_op_callf(em, op, + "smooth_laplacian_vert verts=%hv lambda=%f lambda_border=%f use_x=%b use_y=%b use_z=%b volume_preservation=%b", + BM_ELEM_SELECT, lambda, lambda_border, usex, usey, usez, volume_preservation)) + { + return OPERATOR_CANCELLED; + } + } + + /* apply mirror */ + if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) { + EDBM_verts_mirror_apply(em, BM_ELEM_SELECT, 0); + EDBM_verts_mirror_cache_end(em); + } + + EDBM_update_generic(C, em, TRUE); + + return OPERATOR_FINISHED; +} + +void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Laplacian Smooth Vertex"; + ot->description = "Laplacian smooth of selected vertices"; + ot->idname = "MESH_OT_vertices_smooth_laplacian"; + + /* api callbacks */ + ot->exec = edbm_do_smooth_laplacian_vertex_exec; + ot->poll = ED_operator_editmesh; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_int(ot->srna, "repeat", 1, 1, 200, + "Number of iterations to smooth the mesh", "", 1, 200); + RNA_def_float(ot->srna, "lambda", 0.00005f, 0.0000001f, 1000.0f, + "Lambda factor", "", 0.0000001f, 1000.0f); + RNA_def_float(ot->srna, "lambda_border", 0.00005f, 0.0000001f, 1000.0f, + "Lambda factor in border", "", 0.0000001f, 1000.0f); + RNA_def_boolean(ot->srna, "use_x", 1, "Smooth X Axis", "Smooth object along X axis"); + RNA_def_boolean(ot->srna, "use_y", 1, "Smooth Y Axis", "Smooth object along Y axis"); + RNA_def_boolean(ot->srna, "use_z", 1, "Smooth Z Axis", "Smooth object along Z axis"); + RNA_def_boolean(ot->srna, "volume_preservation", 1, "Preserve Volume", "Apply volume preservation after smooth"); +} + /********************** Smooth/Solid Operators *************************/ static void mesh_set_smooth_faces(BMEditMesh *em, short smooth) @@ -2073,7 +2215,7 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op) } count = totvert_orig - em->bm->totvert; - BKE_reportf(op->reports, RPT_INFO, "Removed %d vert%s", count, (count == 1) ? "ex" : "ices"); + BKE_reportf(op->reports, RPT_INFO, "Removed %d vertices", count); EDBM_update_generic(C, em, TRUE); @@ -2140,7 +2282,7 @@ static int edbm_select_vertex_path_exec(bContext *C, wmOperator *op) } /* if those are not found, because vertices where selected by e.g. - border or circle select, find two selected vertices */ + * border or circle select, find two selected vertices */ if (svert == NULL) { BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (!BM_elem_flag_test(eve, BM_ELEM_SELECT) || BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) @@ -2150,7 +2292,7 @@ static int edbm_select_vertex_path_exec(bContext *C, wmOperator *op) else if (evert == NULL) evert = eve; else { /* more than two vertices are selected, - show warning message and cancel operator */ + * show warning message and cancel operator */ svert = evert = NULL; break; } @@ -2158,7 +2300,7 @@ static int edbm_select_vertex_path_exec(bContext *C, wmOperator *op) } if (svert == NULL || evert == NULL) { - BKE_report(op->reports, RPT_WARNING, "Path Selection requires that two vertices be selected"); + BKE_report(op->reports, RPT_WARNING, "Path selection requires two vertices to be selected"); return OPERATOR_CANCELLED; } @@ -2526,17 +2668,6 @@ void MESH_OT_solidify(wmOperatorType *ot) RNA_def_property_ui_range(prop, -10, 10, 0.1, 4); } -#define TRAIL_POLYLINE 1 /* For future use, They don't do anything yet */ -#define TRAIL_FREEHAND 2 -#define TRAIL_MIXED 3 /* (1|2) */ -#define TRAIL_AUTO 4 -#define TRAIL_MIDPOINTS 8 - -typedef struct CutCurve { - float x; - float y; -} CutCurve; - /* ******************************************************************** */ /* Knife Subdivide Tool. Subdivides edges intersected by a mouse trail * drawn by user. @@ -2570,15 +2701,14 @@ static EnumPropertyItem knife_items[] = { /* bm_edge_seg_isect() Determines if and where a mouse trail intersects an BMEdge */ -static float bm_edge_seg_isect(BMEdge *e, CutCurve *c, int len, char mode, - struct GHash *gh, int *isected) +static float bm_edge_seg_isect(const float sco_a[2], const float sco_b[2], + float (*mouse_path)[2], int len, char mode, int *isected) { #define MAXSLOPE 100000 float x11, y11, x12 = 0, y12 = 0, x2max, x2min, y2max; float y2min, dist, lastdist = 0, xdiff2, xdiff1; float m1, b1, m2, b2, x21, x22, y21, y22, xi; float yi, x1min, x1max, y1max, y1min, perc = 0; - float *scr; float threshold = 0.0; int i; @@ -2586,13 +2716,11 @@ static float bm_edge_seg_isect(BMEdge *e, CutCurve *c, int len, char mode, // XXX threshold = scene->toolsettings->select_thresh / 100; /* Get screen coords of verts */ - scr = BLI_ghash_lookup(gh, e->v1); - x21 = scr[0]; - y21 = scr[1]; + x21 = sco_a[0]; + y21 = sco_a[1]; - scr = BLI_ghash_lookup(gh, e->v2); - x22 = scr[0]; - y22 = scr[1]; + x22 = sco_b[0]; + y22 = sco_b[1]; xdiff2 = (x22 - x21); if (xdiff2) { @@ -2614,11 +2742,11 @@ static float bm_edge_seg_isect(BMEdge *e, CutCurve *c, int len, char mode, y11 = y12; } else { - x11 = c[i].x; - y11 = c[i].y; + x11 = mouse_path[i][0]; + y11 = mouse_path[i][1]; } - x12 = c[i].x; - y12 = c[i].y; + x12 = mouse_path[i][0]; + y12 = mouse_path[i][1]; /* test e->v1 */ if ((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)) { @@ -2642,11 +2770,11 @@ static float bm_edge_seg_isect(BMEdge *e, CutCurve *c, int len, char mode, y11 = y12; } else { - x11 = c[i].x; - y11 = c[i].y; + x11 = mouse_path[i][0]; + y11 = mouse_path[i][1]; } - x12 = c[i].x; - y12 = c[i].y; + x12 = mouse_path[i][0]; + y12 = mouse_path[i][1]; /* Perp. Distance from point to line */ if (m2 != MAXSLOPE) dist = (y12 - m2 * x12 - b2); /* /sqrt(m2 * m2 + 1); Only looking for */ @@ -2666,21 +2794,21 @@ static float bm_edge_seg_isect(BMEdge *e, CutCurve *c, int len, char mode, m1 = MAXSLOPE; b1 = x12; } - x2max = maxf(x21, x22) + 0.001f; /* prevent missed edges */ - x2min = minf(x21, x22) - 0.001f; /* due to round off error */ - y2max = maxf(y21, y22) + 0.001f; - y2min = minf(y21, y22) - 0.001f; + x2max = max_ff(x21, x22) + 0.001f; /* prevent missed edges */ + x2min = min_ff(x21, x22) - 0.001f; /* due to round off error */ + y2max = max_ff(y21, y22) + 0.001f; + y2min = min_ff(y21, y22) - 0.001f; /* Found an intersect, calc intersect point */ if (m1 == m2) { /* co-incident lines */ /* cut at 50% of overlap area */ - x1max = maxf(x11, x12); - x1min = minf(x11, x12); - xi = (minf(x2max, x1max) + maxf(x2min, x1min)) / 2.0f; + x1max = max_ff(x11, x12); + x1min = min_ff(x11, x12); + xi = (min_ff(x2max, x1max) + max_ff(x2min, x1min)) / 2.0f; - y1max = maxf(y11, y12); - y1min = minf(y11, y12); - yi = (minf(y2max, y1max) + maxf(y2min, y1min)) / 2.0f; + y1max = max_ff(y11, y12); + y1min = min_ff(y11, y12); + yi = (min_ff(y2max, y1max) + max_ff(y2min, y1min)) / 2.0f; } else if (m2 == MAXSLOPE) { xi = x22; @@ -2720,13 +2848,13 @@ static float bm_edge_seg_isect(BMEdge *e, CutCurve *c, int len, char mode, break; } - } + } lastdist = dist; } return perc; -} +} -#define MAX_CUTS 2048 +#define ELE_EDGE_CUT 1 static int edbm_knife_cut_exec(bContext *C, wmOperator *op) { @@ -2738,76 +2866,93 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) BMIter iter; BMEdge *be; BMOperator bmop; - CutCurve curve[MAX_CUTS]; - struct GHash *gh; float isect = 0.0f; - float *scr, co[4]; - int len = 0, isected; + int len = 0, isected, i; short numcuts = 1, mode = RNA_int_get(op->ptr, "type"); + + /* allocd vars */ + float (*screen_vert_coords)[2], (*sco)[2], (*mouse_path)[2]; /* edit-object needed for matrix, and ar->regiondata for projections to work */ if (ELEM3(NULL, obedit, ar, ar->regiondata)) return OPERATOR_CANCELLED; if (bm->totvertsel < 2) { - //error("No edges are selected to operate on"); + BKE_report(op->reports, RPT_ERROR, "No edges are selected to operate on"); return OPERATOR_CANCELLED; } + len = RNA_collection_length(op->ptr, "path"); + + if (len < 2) { + BKE_report(op->reports, RPT_ERROR, "Mouse path too short"); + return OPERATOR_CANCELLED; + } + + mouse_path = MEM_mallocN(len * sizeof(*mouse_path), __func__); + /* get the cut curve */ RNA_BEGIN(op->ptr, itemptr, "path") { - RNA_float_get_array(&itemptr, "loc", (float *)&curve[len]); - len++; - if (len >= MAX_CUTS) { - break; - } + RNA_float_get_array(&itemptr, "loc", (float *)&mouse_path[len]); } RNA_END; - - if (len < 2) { - return OPERATOR_CANCELLED; - } + + /* for ED_view3d_project_float_object */ + ED_view3d_init_mats_rv3d(obedit, ar->regiondata); + + /* TODO, investigate using index lookup for screen_vert_coords() rather then a hash table */ /* the floating point coordinates of verts in screen space will be stored in a hash table according to the vertices pointer */ - gh = BLI_ghash_ptr_new("knife cut exec"); - for (bv = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); bv; bv = BM_iter_step(&iter)) { - scr = MEM_mallocN(sizeof(float) * 2, "Vertex Screen Coordinates"); - copy_v3_v3(co, bv->co); - co[3] = 1.0f; - mul_m4_v4(obedit->obmat, co); - project_float(ar, co, scr); - BLI_ghash_insert(gh, bv, scr); + screen_vert_coords = sco = MEM_mallocN(bm->totvert * sizeof(float) * 2, __func__); + + BM_ITER_MESH_INDEX (bv, &iter, bm, BM_VERTS_OF_MESH, i) { + if (ED_view3d_project_float_object(ar, bv->co, *sco, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) { + copy_v2_fl(*sco, FLT_MAX); /* set error value */ + } + BM_elem_index_set(bv, i); /* set_ok */ + sco++; + } + bm->elem_index_dirty &= ~BM_VERT; /* clear dirty flag */ if (!EDBM_op_init(em, &bmop, op, "subdivide_edges")) { + MEM_freeN(mouse_path); + MEM_freeN(screen_vert_coords); return OPERATOR_CANCELLED; } /* store percentage of edge cut for KNIFE_EXACT here.*/ for (be = BM_iter_new(&iter, bm, BM_EDGES_OF_MESH, NULL); be; be = BM_iter_step(&iter)) { + int is_cut = FALSE; if (BM_elem_flag_test(be, BM_ELEM_SELECT)) { - isect = bm_edge_seg_isect(be, curve, len, mode, gh, &isected); - - if (isect != 0.0f) { - if (mode != KNIFE_MULTICUT && mode != KNIFE_MIDPOINT) { - BMO_slot_map_float_insert(bm, &bmop, - "edgepercents", - be, isect); + const float *sco_a = screen_vert_coords[BM_elem_index_get(be->v1)]; + const float *sco_b = screen_vert_coords[BM_elem_index_get(be->v2)]; + /* check for error value (vert cant be projected) */ + if ((sco_a[0] != FLT_MAX) && (sco_b[0] != FLT_MAX)) { + isect = bm_edge_seg_isect(sco_a, sco_b, mouse_path, len, mode, &isected); + + if (isect != 0.0f) { + if (mode != KNIFE_MULTICUT && mode != KNIFE_MIDPOINT) { + BMO_slot_map_float_insert(bm, &bmop, + "edgepercents", + be, isect); + } } - BMO_elem_flag_enable(bm, be, 1); - } - else { - BMO_elem_flag_disable(bm, be, 1); } } - else { - BMO_elem_flag_disable(bm, be, 1); - } + + BMO_elem_flag_set(bm, be, ELE_EDGE_CUT, is_cut); } - - BMO_slot_buffer_from_enabled_flag(bm, &bmop, "edges", BM_EDGE, 1); + + + /* free all allocs */ + MEM_freeN(screen_vert_coords); + MEM_freeN(mouse_path); + + + BMO_slot_buffer_from_enabled_flag(bm, &bmop, "edges", BM_EDGE, ELE_EDGE_CUT); if (mode == KNIFE_MIDPOINT) numcuts = 1; BMO_slot_int_set(&bmop, "numcuts", numcuts); @@ -2822,14 +2967,14 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; } - - BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN); EDBM_update_generic(C, em, TRUE); return OPERATOR_FINISHED; } +#undef ELE_EDGE_CUT + void MESH_OT_knife_cut(wmOperatorType *ot) { PropertyRNA *prop; @@ -2858,9 +3003,6 @@ void MESH_OT_knife_cut(wmOperatorType *ot) static int mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old) { Base *base_new; - BMIter iter; - BMVert *v; - BMEdge *e; Object *obedit = base_old->object; BMesh *bm_new; @@ -2886,15 +3028,10 @@ static int mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh BMO_op_callf(bm_old, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "delete geom=%hvef context=%i", BM_ELEM_TAG, DEL_FACES); - /* deselect loose data - this used to get deleted */ - BM_ITER_MESH (e, &iter, bm_old, BM_EDGES_OF_MESH) { - BM_edge_select_set(bm_old, e, FALSE); - } - - /* clean up any loose verts */ - BM_ITER_MESH (v, &iter, bm_old, BM_VERTS_OF_MESH) { - BM_vert_select_set(bm_old, v, FALSE); - } + /* deselect loose data - this used to get deleted, + * we could de-select edges and verts only, but this turns out to be less complicated + * since de-selecting all skips selection flushing logic */ + BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE); BM_mesh_normals_update(bm_new, FALSE); @@ -2908,7 +3045,10 @@ static int mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh static int mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old) { - /* tag -> select */ + /* we may have tags from previous operators */ + BM_mesh_elem_hflag_disable_all(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, FALSE); + + /* sel -> tag */ BM_mesh_elem_hflag_enable_test(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, TRUE, BM_ELEM_SELECT); return mesh_separate_tagged(bmain, scene, base_old, bm_old); @@ -3073,7 +3213,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) } else { if (type == 0) { - BKE_report(op->reports, RPT_ERROR, "Selecton not supported in object mode"); + BKE_report(op->reports, RPT_ERROR, "Selection not supported in object mode"); return OPERATOR_CANCELLED; } @@ -3354,7 +3494,8 @@ static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op) Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); BMesh *bm = em->bm; - float angle_limit = RNA_float_get(op->ptr, "angle_limit"); + const float angle_limit = RNA_float_get(op->ptr, "angle_limit"); + const int use_dissolve_boundaries = RNA_boolean_get(op->ptr, "use_dissolve_boundaries"); char dissolve_flag; @@ -3390,8 +3531,8 @@ static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op) } if (!EDBM_op_callf(em, op, - "dissolve_limit edges=%he verts=%hv angle_limit=%f", - dissolve_flag, dissolve_flag, angle_limit)) + "dissolve_limit edges=%he verts=%hv angle_limit=%f use_dissolve_boundaries=%b", + dissolve_flag, dissolve_flag, angle_limit, use_dissolve_boundaries)) { return OPERATOR_CANCELLED; } @@ -3418,8 +3559,10 @@ void MESH_OT_dissolve_limited(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; prop = RNA_def_float_rotation(ot->srna, "angle_limit", 0, NULL, 0.0f, DEG2RADF(180.0f), - "Max Angle", "Angle Limit in Degrees", 0.0f, DEG2RADF(180.0f)); + "Max Angle", "Angle limit", 0.0f, DEG2RADF(180.0f)); RNA_def_property_float_default(prop, DEG2RADF(15.0f)); + RNA_def_boolean(ot->srna, "use_dissolve_boundaries", 0, "All Boundaries", + "Dissolve all vertices inbetween face boundaries"); } static int edbm_split_exec(bContext *C, wmOperator *op) @@ -3537,7 +3680,7 @@ void MESH_OT_spin(wmOperatorType *ot) RNA_def_float(ot->srna, "degrees", 90.0f, -FLT_MAX, FLT_MAX, "Degrees", "Degrees", -360.0f, 360.0f); RNA_def_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX); - RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -FLT_MAX, FLT_MAX); + RNA_def_float_vector(ot->srna, "axis", 3, NULL, -FLT_MAX, FLT_MAX, "Axis", "Axis in global view space", -1.0f, 1.0f); } @@ -3661,34 +3804,40 @@ void MESH_OT_screw(wmOperatorType *ot) RNA_def_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX); - RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, - "Axis", "Axis in global view space", -FLT_MAX, FLT_MAX); + RNA_def_float_vector(ot->srna, "axis", 3, NULL, -FLT_MAX, FLT_MAX, + "Axis", "Axis in global view space", -1.0f, 1.0f); } -static int edbm_select_by_number_vertices_exec(bContext *C, wmOperator *op) +static int edbm_select_face_by_sides_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); BMFace *efa; BMIter iter; - int numverts = RNA_int_get(op->ptr, "number"); - int type = RNA_enum_get(op->ptr, "type"); + const int numverts = RNA_int_get(op->ptr, "number"); + const int type = RNA_enum_get(op->ptr, "type"); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - int select = 0; + int select; - if (type == 0 && efa->len < numverts) { - select = 1; - } - else if (type == 1 && efa->len == numverts) { - select = 1; - } - else if (type == 2 && efa->len > numverts) { - select = 1; - } - else if (type == 3 && efa->len != numverts) { - select = 1; + switch (type) { + case 0: + select = (efa->len < numverts); + break; + case 1: + select = (efa->len == numverts); + break; + case 2: + select = (efa->len > numverts); + break; + case 3: + select = (efa->len != numverts); + break; + default: + BLI_assert(0); + select = FALSE; + break; } if (select) { @@ -3702,7 +3851,7 @@ static int edbm_select_by_number_vertices_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void MESH_OT_select_by_number_vertices(wmOperatorType *ot) +void MESH_OT_select_face_by_sides(wmOperatorType *ot) { static const EnumPropertyItem type_items[] = { {0, "LESS", 0, "Less Than", ""}, @@ -3713,12 +3862,12 @@ void MESH_OT_select_by_number_vertices(wmOperatorType *ot) }; /* identifiers */ - ot->name = "Select by Number of Vertices"; - ot->description = "Select vertices or faces by vertex count"; - ot->idname = "MESH_OT_select_by_number_vertices"; + ot->name = "Select Faces by Sides"; + ot->description = "Select vertices or faces by the number of polygon sides"; + ot->idname = "MESH_OT_select_face_by_sides"; /* api callbacks */ - ot->exec = edbm_select_by_number_vertices_exec; + ot->exec = edbm_select_face_by_sides_exec; ot->poll = ED_operator_editmesh; /* flags */ @@ -3846,8 +3995,8 @@ static void sort_bmelem_flag(Scene *scene, Object *ob, char *pblock[3] = {NULL, NULL, NULL}, *pb; BMElemSort *sblock[3] = {NULL, NULL, NULL}, *sb; int *map[3] = {NULL, NULL, NULL}, *mp; - int totelem[3] = {0, 0, 0}, tot; - int affected[3] = {0, 0, 0}, aff; + int totelem[3] = {0, 0, 0}; + int affected[3] = {0, 0, 0}; int i, j; if (!(types && flag && action)) @@ -4222,8 +4371,8 @@ static void sort_bmelem_flag(Scene *scene, Object *ob, if (pb && sb && !map[j]) { char *p_blk; BMElemSort *s_blk; - tot = totelem[j]; - aff = affected[j]; + int tot = totelem[j]; + int aff = affected[j]; qsort(sb, aff, sizeof(BMElemSort), bmelemsort_comp); @@ -4272,7 +4421,7 @@ static int edbm_sort_elements_exec(bContext *C, wmOperator *op) if (ELEM(action, SRT_VIEW_ZAXIS, SRT_VIEW_XAXIS)) { if (rv3d == NULL) { - BKE_report(op->reports, RPT_ERROR, "View not found, can't sort by view axis"); + BKE_report(op->reports, RPT_ERROR, "View not found, cannot sort by view axis"); return OPERATOR_CANCELLED; } } @@ -4460,6 +4609,7 @@ typedef struct { int li; int mcenter[2]; float initial_length; + float pixel_size; /* use when mouse input is interpreted as spatial distance */ int is_modal; NumInput num_input; float shift_factor; /* The current factor when shift is pressed. Negative when shift not active. */ @@ -4657,8 +4807,10 @@ static int edbm_bevel_exec(bContext *C, wmOperator *op) static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event) { /* TODO make modal keymap (see fly mode) */ + RegionView3D *rv3d = CTX_wm_region_view3d(C); BevelData *opdata; float mlen[2]; + float center_3d[3]; if (!edbm_bevel_init(C, op, TRUE)) { return OPERATOR_CANCELLED; @@ -4667,7 +4819,7 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event) opdata = op->customdata; /* initialize mouse values */ - if (!calculateTransformCenter(C, V3D_CENTROID, NULL, opdata->mcenter)) { + if (!calculateTransformCenter(C, V3D_CENTROID, center_3d, opdata->mcenter)) { /* in this case the tool will likely do nothing, * ideally this will never happen and should be checked for above */ opdata->mcenter[0] = opdata->mcenter[1] = 0; @@ -4675,6 +4827,7 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event) mlen[0] = opdata->mcenter[0] - event->mval[0]; mlen[1] = opdata->mcenter[1] - event->mval[1]; opdata->initial_length = len_v2(mlen); + opdata->pixel_size = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f; edbm_bevel_update_header(op, C); @@ -4688,6 +4841,44 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } +static float edbm_bevel_mval_factor(wmOperator *op, wmEvent *event) +{ + BevelData *opdata = op->customdata; + int use_dist = RNA_boolean_get(op->ptr, "use_dist"); + float mdiff[2]; + float factor; + + mdiff[0] = opdata->mcenter[0] - event->mval[0]; + mdiff[1] = opdata->mcenter[1] - event->mval[1]; + + if (use_dist) { + factor = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length) * opdata->pixel_size; + } + else { + factor = (len_v2(mdiff) - MVAL_PIXEL_MARGIN) / opdata->initial_length; + factor = factor - 1.0f; /* a different kind of buffer where nothing happens */ + } + + /* Fake shift-transform... */ + if (event->shift) { + if (opdata->shift_factor < 0.0f) + opdata->shift_factor = RNA_float_get(op->ptr, "percent"); + factor = (factor - opdata->shift_factor) * 0.1f + opdata->shift_factor; + } + else if (opdata->shift_factor >= 0.0f) + opdata->shift_factor = -1.0f; + + /* clamp differently based on distance/factor */ + if (use_dist) { + if (factor < 0.0f) factor = 0.0f; + } + else { + CLAMP(factor, 0.0f, 1.0f); + } + + return factor; +} + static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) { BevelData *opdata = op->customdata; @@ -4715,25 +4906,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) case MOUSEMOVE: if (!hasNumInput(&opdata->num_input)) { - float factor; - float mdiff[2]; - - mdiff[0] = opdata->mcenter[0] - event->mval[0]; - mdiff[1] = opdata->mcenter[1] - event->mval[1]; - - factor = -len_v2(mdiff) / opdata->initial_length + 1.0f; - - /* Fake shift-transform... */ - if (event->shift) { - if (opdata->shift_factor < 0.0f) - opdata->shift_factor = RNA_float_get(op->ptr, "percent"); - factor = (factor - opdata->shift_factor) * 0.1f + opdata->shift_factor; - } - else if (opdata->shift_factor >= 0.0f) - opdata->shift_factor = -1.0f; - - CLAMP(factor, 0.0f, 1.0f); - + const float factor = edbm_bevel_mval_factor(op, event); RNA_float_set(op->ptr, "percent", factor); edbm_bevel_calc(C, op); @@ -4763,6 +4936,11 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) int use_dist = RNA_boolean_get(op->ptr, "use_dist"); RNA_boolean_set(op->ptr, "use_dist", !use_dist); + { + const float factor = edbm_bevel_mval_factor(op, event); + RNA_float_set(op->ptr, "percent", factor); + } + edbm_bevel_calc(C, op); edbm_bevel_update_header(op, C); } @@ -4787,8 +4965,9 @@ void MESH_OT_bevel(wmOperatorType *ot) ot->poll = ED_operator_editmesh; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING; + /* take note, used as a factor _and_ a distance depending on 'use_dist' */ RNA_def_float(ot->srna, "percent", 0.0f, -FLT_MAX, FLT_MAX, "Percentage", "", 0.0f, 1.0f); /* XXX, disabled for 2.63 release, needs to work much better without overlap before we can give to users. */ /* RNA_def_int(ot->srna, "recursion", 1, 1, 50, "Recursion Level", "Recursion Level", 1, 8); */ @@ -4853,8 +5032,9 @@ typedef struct { float old_depth; int mcenter[2]; int modify_depth; - int is_modal; float initial_length; + float pixel_size; /* use when mouse input is interpreted as spatial distance */ + int is_modal; int shift; float shift_amount; BMBackup backup; @@ -5020,15 +5200,17 @@ static int edbm_inset_exec(bContext *C, wmOperator *op) static int edbm_inset_invoke(bContext *C, wmOperator *op, wmEvent *event) { + RegionView3D *rv3d = CTX_wm_region_view3d(C); InsetData *opdata; float mlen[2]; + float center_3d[3]; edbm_inset_init(C, op, TRUE); opdata = op->customdata; /* initialize mouse values */ - if (!calculateTransformCenter(C, V3D_CENTROID, NULL, opdata->mcenter)) { + if (!calculateTransformCenter(C, V3D_CENTROID, center_3d, opdata->mcenter)) { /* in this case the tool will likely do nothing, * ideally this will never happen and should be checked for above */ opdata->mcenter[0] = opdata->mcenter[1] = 0; @@ -5036,6 +5218,7 @@ static int edbm_inset_invoke(bContext *C, wmOperator *op, wmEvent *event) mlen[0] = opdata->mcenter[0] - event->mval[0]; mlen[1] = opdata->mcenter[1] - event->mval[1]; opdata->initial_length = len_v2(mlen); + opdata->pixel_size = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f; edbm_inset_calc(C, op); @@ -5055,7 +5238,7 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event) if (handleNumInput(&opdata->num_input, event)) { applyNumInput(&opdata->num_input, amounts); - amounts[0] = maxf(amounts[0], 0.0f); + amounts[0] = max_ff(amounts[0], 0.0f); RNA_float_set(op->ptr, "thickness", amounts[0]); RNA_float_set(op->ptr, "depth", amounts[1]); @@ -5085,9 +5268,9 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event) mdiff[1] = opdata->mcenter[1] - event->mval[1]; if (opdata->modify_depth) - amount = opdata->old_depth + len_v2(mdiff) / opdata->initial_length - 1.0f; + amount = opdata->old_depth + ((len_v2(mdiff) - opdata->initial_length) * opdata->pixel_size); else - amount = opdata->old_thickness - len_v2(mdiff) / opdata->initial_length + 1.0f; + amount = opdata->old_thickness - ((len_v2(mdiff) - opdata->initial_length) * opdata->pixel_size); /* Fake shift-transform... */ if (opdata->shift) @@ -5096,7 +5279,7 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event) if (opdata->modify_depth) RNA_float_set(op->ptr, "depth", amount); else { - amount = maxf(amount, 0.0f); + amount = max_ff(amount, 0.0f); RNA_float_set(op->ptr, "thickness", amount); } @@ -5206,7 +5389,7 @@ void MESH_OT_inset(wmOperatorType *ot) ot->poll = ED_operator_editmesh; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING; /* properties */ RNA_def_boolean(ot->srna, "use_boundary", TRUE, "Boundary", "Inset face boundaries"); @@ -5294,6 +5477,7 @@ void MESH_OT_wireframe(wmOperatorType *ot) RNA_def_boolean(ot->srna, "use_replace", TRUE, "Replace", "Remove original faces"); } +#ifdef WITH_BULLET static int edbm_convex_hull_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -5387,3 +5571,55 @@ void MESH_OT_convex_hull(wmOperatorType *ot) join_triangle_props(ot); } +#endif + +static int mesh_symmetrize_exec(bContext *C, wmOperator *op) +{ + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BMEdit_FromObject(obedit); + BMOperator bmop; + + EDBM_op_init(em, &bmop, op, "symmetrize input=%hvef direction=%i", + BM_ELEM_SELECT, RNA_enum_get(op->ptr, "direction")); + BMO_op_exec(em->bm, &bmop); + + if (!EDBM_op_finish(em, &bmop, op, TRUE)) { + return OPERATOR_CANCELLED; + } + else { + EDBM_update_generic(C, em, TRUE); + EDBM_selectmode_flush(em); + return OPERATOR_FINISHED; + } +} + +void MESH_OT_symmetrize(struct wmOperatorType *ot) +{ + static EnumPropertyItem axis_direction_items[] = { + {BMO_SYMMETRIZE_NEGATIVE_X, "NEGATIVE_X", 0, "-X to +X", ""}, + {BMO_SYMMETRIZE_POSITIVE_X, "POSITIVE_X", 0, "+X to -X", ""}, + + {BMO_SYMMETRIZE_NEGATIVE_Y, "NEGATIVE_Y", 0, "-Y to +Y", ""}, + {BMO_SYMMETRIZE_POSITIVE_Y, "POSITIVE_Y", 0, "+Y to -Y", ""}, + + {BMO_SYMMETRIZE_NEGATIVE_Z, "NEGATIVE_Z", 0, "-Z to +Z", ""}, + {BMO_SYMMETRIZE_POSITIVE_Z, "POSITIVE_Z", 0, "+Z to -Z", ""}, + {0, NULL, 0, NULL, NULL}, + }; + + /* identifiers */ + ot->name = "Symmetrize"; + ot->description = "Enforce symmetry (both form and topological) across an axis"; + ot->idname = "MESH_OT_symmetrize"; + + /* api callbacks */ + ot->exec = mesh_symmetrize_exec; + ot->poll = ED_operator_editmesh; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + ot->prop = RNA_def_enum(ot->srna, "direction", axis_direction_items, + BMO_SYMMETRIZE_NEGATIVE_X, + "Direction", "Which sides to copy from and to"); +} diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 03e2f2691a8..ef3d8db4156 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -48,6 +48,8 @@ #include "BKE_report.h" #include "BKE_tessmesh.h" +#include "BKE_object.h" /* XXX. only for EDBM_mesh_ensure_valid_dm_hack() which will be removed */ + #include "WM_api.h" #include "WM_types.h" @@ -102,7 +104,17 @@ void EDBM_redo_state_free(BMBackup *backup, BMEditMesh *em, int recalctess) BMEdit_RecalcTessellation(em); } - +/* hack to workaround multiple operators being called within the same event loop without an update + * see: [#31811] */ +void EDBM_mesh_ensure_valid_dm_hack(Scene *scene, BMEditMesh *em) +{ + if ((((ID *)em->ob->data)->flag & LIB_ID_RECALC) || + (em->ob->recalc & OB_RECALC_DATA)) + { + em->ob->recalc |= OB_RECALC_DATA; /* since we may not have done selection flushing */ + BKE_object_handle_update(scene, em->ob); + } +} void EDBM_mesh_normals_update(BMEditMesh *em) { @@ -535,6 +547,16 @@ static void *getEditMesh(bContext *C) typedef struct UndoMesh { Mesh me; int selectmode; + + /** \note + * this isn't a prefect solution, if you edit keys and change shapes this works well (fixing [#32442]), + * but editing shape keys, going into object mode, removing or changing their order, + * then go back into editmode and undo will give issues - where the old index will be out of sync + * with the new object index. + * + * There are a few ways this could be made to work but for now its a known limitation with mixing + * object and editmode operations - Campbell */ + int shapenr; } UndoMesh; /* undo simply makes copies of a bmesh */ @@ -546,13 +568,14 @@ static void *editbtMesh_to_undoMesh(void *emv, void *obdata) UndoMesh *um = MEM_callocN(sizeof(UndoMesh), "undo Mesh"); /* make sure shape keys work */ - um->me.key = obme->key ? copy_key_nolib(obme->key) : NULL; + um->me.key = obme->key ? BKE_key_copy_nolib(obme->key) : NULL; /* BM_mesh_validate(em->bm); */ /* for troubleshooting */ BM_mesh_bm_to_me(em->bm, &um->me, FALSE); um->selectmode = em->selectmode; + um->shapenr = em->bm->shapenr; return um; } @@ -564,7 +587,7 @@ static void undoMesh_to_editbtMesh(void *umv, void *em_v, void *UNUSED(obdata)) UndoMesh *um = umv; BMesh *bm; - ob->shapenr = em->bm->shapenr; + ob->shapenr = em->bm->shapenr = um->shapenr; EDBM_mesh_free(em); @@ -989,6 +1012,19 @@ void EDBM_uv_element_map_free(UvElementMap *element_map) } } +UvElement *ED_uv_element_get(UvElementMap *map, BMFace *efa, BMLoop *l) +{ + UvElement *element; + + element = map->vert[BM_elem_index_get(l->v)]; + + for (; element; element = element->next) + if (element->face == efa) + return element; + + return NULL; +} + /* last_sel, use em->act_face otherwise get the last selected face in the editselections * at the moment, last_sel is mainly useful for making sure the space image dosnt flicker */ MTexPoly *EDBM_mtexpoly_active_get(BMEditMesh *em, BMFace **r_act_efa, int sloppy, int selected) diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 09d89a961e4..e9906f852de 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -47,6 +47,8 @@ #include "BLI_array.h" #include "BLI_math.h" #include "BLI_edgehash.h" +#include "BLI_linklist.h" +#include "BLI_listbase.h" #include "BKE_context.h" #include "BKE_depsgraph.h" @@ -74,6 +76,64 @@ #include "mesh_intern.h" +static CustomData *mesh_customdata_get_type(Mesh *me, const char htype, int *r_tot) +{ + CustomData *data; + BMesh *bm = (me->edit_btmesh) ? me->edit_btmesh->bm : NULL; + int tot; + + /* this */ + switch (htype) { + case BM_VERT: + if (bm) { + data = &bm->vdata; + tot = bm->totvert; + } + else { + data = &me->vdata; + tot = me->totvert; + } + break; + case BM_EDGE: + if (bm) { + data = &bm->edata; + tot = bm->totedge; + } + else { + data = &me->edata; + tot = me->totedge; + } + break; + case BM_LOOP: + if (bm) { + data = &bm->ldata; + tot = bm->totloop; + } + else { + data = &me->ldata; + tot = me->totloop; + } + break; + case BM_FACE: + if (bm) { + data = &bm->pdata; + tot = bm->totface; + } + else { + data = &me->pdata; + tot = me->totpoly; + } + break; + default: + BLI_assert(0); + tot = 0; + data = NULL; + } + + *r_tot = tot; + return data; +} + #define GET_CD_DATA(me, data) (me->edit_btmesh ? &me->edit_btmesh->bm->data : &me->data) static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *layer) { @@ -85,24 +145,10 @@ static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *la int i, actindex, rndindex, cloneindex, stencilindex, tot; if (layer->type == CD_MLOOPCOL || layer->type == CD_MLOOPUV) { - if (me->edit_btmesh) { - data = &me->edit_btmesh->bm->ldata; - tot = me->edit_btmesh->bm->totloop; - } - else { - data = &me->ldata; - tot = me->totloop; - } + data = mesh_customdata_get_type(me, BM_LOOP, &tot); } else { - if (me->edit_btmesh) { - data = &me->edit_btmesh->bm->pdata; - tot = me->edit_btmesh->bm->totface; - } - else { - data = &me->pdata; - tot = me->totpoly; - } + data = mesh_customdata_get_type(me, BM_FACE, &tot); } index = CustomData_get_layer_index(data, type); @@ -189,7 +235,8 @@ static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *la } } -int ED_mesh_uv_loop_reset_ex(struct bContext *C, struct Mesh *me, const int layernum) +/* without bContext, called in uvedit */ +int ED_mesh_uv_loop_reset_ex(struct Mesh *me, const int layernum) { BMEditMesh *em = me->edit_btmesh; MLoopUV *luv; @@ -292,7 +339,6 @@ int ED_mesh_uv_loop_reset_ex(struct bContext *C, struct Mesh *me, const int laye BLI_array_free(polylengths); DAG_id_tag_update(&me->id, 0); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); return 1; } @@ -302,7 +348,11 @@ int ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me) /* could be ldata or pdata */ CustomData *pdata = GET_CD_DATA(me, pdata); const int layernum = CustomData_get_active_layer_index(pdata, CD_MTEXPOLY); - return ED_mesh_uv_loop_reset_ex(C, me, layernum); + int retval = ED_mesh_uv_loop_reset_ex(me, layernum); + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); + + return retval; } /* note: keep in sync with ED_mesh_color_add */ @@ -373,7 +423,7 @@ int ED_mesh_uv_texture_add(bContext *C, Mesh *me, const char *name, int active_s /* don't overwrite our copied coords */ if (is_init == FALSE) { - ED_mesh_uv_loop_reset_ex(C, me, layernum_dst); + ED_mesh_uv_loop_reset_ex(me, layernum_dst); } DAG_id_tag_update(&me->id, 0); @@ -547,7 +597,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, wmEvent *event) /* Check context */ if (base == NULL || base->object->type != OB_MESH) { - BKE_report(op->reports, RPT_ERROR, "Not an Object or Mesh"); + BKE_report(op->reports, RPT_ERROR, "Not an object or mesh"); return OPERATOR_CANCELLED; } @@ -564,7 +614,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, wmEvent *event) } if (!ima) { - BKE_report(op->reports, RPT_ERROR, "Not an Image"); + BKE_report(op->reports, RPT_ERROR, "Not an image"); return OPERATOR_CANCELLED; } @@ -701,71 +751,124 @@ void MESH_OT_vertex_color_remove(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/*********************** sticky operators ************************/ +/* *** CustomData clear functions, we need an operator for each *** */ -static int mesh_sticky_add_exec(bContext *C, wmOperator *UNUSED(op)) +static int mesh_customdata_clear_exec__internal(bContext *C, + char htype, int type) { - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); - Object *ob = ED_object_context(C); - Mesh *me = ob->data; + Object *obedit = ED_object_context(C); + Mesh *me = obedit->data; - /* why is this commented out? */ -#if 0 - if (me->msticky) + int tot; + CustomData *data = mesh_customdata_get_type(me, htype, &tot); + + BLI_assert(CustomData_layertype_is_singleton(type) == TRUE); + + if (CustomData_has_layer(data, type)) { + if (me->edit_btmesh) { + BM_data_layer_free(me->edit_btmesh->bm, data, type); + } + else { + CustomData_free_layers(data, type, tot); + } + + DAG_id_tag_update(&me->id, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); + + return OPERATOR_FINISHED; + } + else { return OPERATOR_CANCELLED; -#endif - - RE_make_sticky(scene, v3d); - - DAG_id_tag_update(&me->id, 0); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); - - return OPERATOR_FINISHED; + } } -void MESH_OT_sticky_add(wmOperatorType *ot) +/* Clear Mask */ +static int mesh_customdata_clear_mask_poll(bContext *C) { + Object *ob = ED_object_context(C); + if (ob && ob->type == OB_MESH) { + Mesh *me = ob->data; + + /* special case - can't run this if we're in sculpt mode */ + if (ob->mode & OB_MODE_SCULPT) { + return FALSE; + } + + if (me->id.lib == NULL) { + CustomData *data = GET_CD_DATA(me, vdata); + if (CustomData_has_layer(data, CD_PAINT_MASK)) { + return TRUE; + } + data = GET_CD_DATA(me, ldata); + if (CustomData_has_layer(data, CD_GRID_PAINT_MASK)) { + return TRUE; + } + } + } + return FALSE; +} +static int mesh_customdata_clear_mask_exec(bContext *C, wmOperator *UNUSED(op)) +{ + int ret_a = mesh_customdata_clear_exec__internal(C, BM_VERT, CD_PAINT_MASK); + int ret_b = mesh_customdata_clear_exec__internal(C, BM_LOOP, CD_GRID_PAINT_MASK); + + if (ret_a == OPERATOR_FINISHED || + ret_b == OPERATOR_FINISHED) + { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void MESH_OT_customdata_clear_mask(wmOperatorType *ot) +{ + /* identifiers */ - ot->name = "Add Sticky"; - ot->description = "Add sticky UV texture layer"; - ot->idname = "MESH_OT_sticky_add"; - + ot->name = "Clear Sculpt-Mask Data"; + ot->idname = "MESH_OT_customdata_clear_mask"; + ot->description = "Clear vertex sculpt masking data from the mesh"; + /* api callbacks */ - ot->poll = layers_poll; - ot->exec = mesh_sticky_add_exec; + ot->exec = mesh_customdata_clear_mask_exec; + ot->poll = mesh_customdata_clear_mask_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -static int mesh_sticky_remove_exec(bContext *C, wmOperator *UNUSED(op)) +/* Clear Skin */ +static int mesh_customdata_clear_skin_poll(bContext *C) { Object *ob = ED_object_context(C); - Mesh *me = ob->data; - if (!me->msticky) - return OPERATOR_CANCELLED; - - CustomData_free_layer_active(&me->vdata, CD_MSTICKY, me->totvert); - me->msticky = NULL; - - DAG_id_tag_update(&me->id, 0); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); - - return OPERATOR_FINISHED; + if (ob && ob->type == OB_MESH) { + Mesh *me = ob->data; + if (me->id.lib == NULL) { + CustomData *data = GET_CD_DATA(me, vdata); + if (CustomData_has_layer(data, CD_MVERT_SKIN)) { + return TRUE; + } + } + } + return FALSE; +} +static int mesh_customdata_clear_skin_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return mesh_customdata_clear_exec__internal(C, BM_VERT, CD_MVERT_SKIN); } -void MESH_OT_sticky_remove(wmOperatorType *ot) +void MESH_OT_customdata_clear_skin(wmOperatorType *ot) { /* identifiers */ - ot->name = "Remove Sticky"; - ot->description = "Remove sticky UV texture layer"; - ot->idname = "MESH_OT_sticky_remove"; - + ot->name = "Clear Skin Data"; + ot->idname = "MESH_OT_customdata_clear_skin"; + ot->description = "Clear vertex skin layer"; + /* api callbacks */ - ot->poll = layers_poll; - ot->exec = mesh_sticky_remove_exec; + ot->exec = mesh_customdata_clear_skin_exec; + ot->poll = mesh_customdata_clear_skin_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -803,7 +906,7 @@ void ED_mesh_update(Mesh *mesh, bContext *C, int calc_edges, int calc_tessface) * so rather then add poly-index layer and calculate normals for it * calculate normals only for the mvert's. - campbell */ #ifdef USE_BMESH_MPOLY_NORMALS - polyindex = CustomData_get_layer(&mesh->fdata, CD_POLYINDEX); + polyindex = CustomData_get_layer(&mesh->fdata, CD_ORIGINDEX); /* add a normals layer for tessellated faces, a tessface normal will * contain the normal of the poly the face was tessellated from. */ face_nors = CustomData_add_layer(&mesh->fdata, CD_NORMAL, CD_CALLOC, NULL, mesh->totface); @@ -848,6 +951,7 @@ static void mesh_add_verts(Mesh *mesh, int len) /* scan the input list and insert the new vertices */ + /* set default flags */ mvert = &mesh->mvert[mesh->totvert]; for (i = 0; i < len; i++, mvert++) mvert->flag |= SELECT; @@ -1025,7 +1129,7 @@ static void mesh_remove_faces(Mesh *mesh, int len) void ED_mesh_geometry_add(Mesh *mesh, ReportList *reports, int verts, int edges, int faces) { if (mesh->edit_btmesh) { - BKE_report(reports, RPT_ERROR, "Can't add geometry in edit mode"); + BKE_report(reports, RPT_ERROR, "Cannot add geometry in edit mode"); return; } @@ -1041,12 +1145,12 @@ void ED_mesh_geometry_add(Mesh *mesh, ReportList *reports, int verts, int edges, void ED_mesh_tessfaces_add(Mesh *mesh, ReportList *reports, int count) { if (mesh->edit_btmesh) { - BKE_report(reports, RPT_ERROR, "Can't add tessfaces in edit mode"); + BKE_report(reports, RPT_ERROR, "Cannot add tessfaces in edit mode"); return; } if (mesh->mpoly) { - BKE_report(reports, RPT_ERROR, "Can't add tessfaces to a mesh that already has polygons"); + BKE_report(reports, RPT_ERROR, "Cannot add tessfaces to a mesh that already has polygons"); return; } @@ -1056,7 +1160,7 @@ void ED_mesh_tessfaces_add(Mesh *mesh, ReportList *reports, int count) void ED_mesh_edges_add(Mesh *mesh, ReportList *reports, int count) { if (mesh->edit_btmesh) { - BKE_report(reports, RPT_ERROR, "Can't add edges in edit mode"); + BKE_report(reports, RPT_ERROR, "Cannot add edges in edit mode"); return; } @@ -1066,7 +1170,7 @@ void ED_mesh_edges_add(Mesh *mesh, ReportList *reports, int count) void ED_mesh_vertices_add(Mesh *mesh, ReportList *reports, int count) { if (mesh->edit_btmesh) { - BKE_report(reports, RPT_ERROR, "Can't add vertices in edit mode"); + BKE_report(reports, RPT_ERROR, "Cannot add vertices in edit mode"); return; } @@ -1076,11 +1180,11 @@ void ED_mesh_vertices_add(Mesh *mesh, ReportList *reports, int count) void ED_mesh_faces_remove(Mesh *mesh, ReportList *reports, int count) { if (mesh->edit_btmesh) { - BKE_report(reports, RPT_ERROR, "Can't remove faces in edit mode"); + BKE_report(reports, RPT_ERROR, "Cannot remove faces in edit mode"); return; } else if (count > mesh->totface) { - BKE_report(reports, RPT_ERROR, "Can't remove more faces than the mesh contains"); + BKE_report(reports, RPT_ERROR, "Cannot remove more faces than the mesh contains"); return; } @@ -1090,11 +1194,11 @@ void ED_mesh_faces_remove(Mesh *mesh, ReportList *reports, int count) void ED_mesh_edges_remove(Mesh *mesh, ReportList *reports, int count) { if (mesh->edit_btmesh) { - BKE_report(reports, RPT_ERROR, "Can't remove edges in edit mode"); + BKE_report(reports, RPT_ERROR, "Cannot remove edges in edit mode"); return; } else if (count > mesh->totedge) { - BKE_report(reports, RPT_ERROR, "Can't remove more edges than the mesh contains"); + BKE_report(reports, RPT_ERROR, "Cannot remove more edges than the mesh contains"); return; } @@ -1104,11 +1208,11 @@ void ED_mesh_edges_remove(Mesh *mesh, ReportList *reports, int count) void ED_mesh_vertices_remove(Mesh *mesh, ReportList *reports, int count) { if (mesh->edit_btmesh) { - BKE_report(reports, RPT_ERROR, "Can't remove vertices in edit mode"); + BKE_report(reports, RPT_ERROR, "Cannot remove vertices in edit mode"); return; } else if (count > mesh->totvert) { - BKE_report(reports, RPT_ERROR, "Can't remove more vertices than the mesh contains"); + BKE_report(reports, RPT_ERROR, "Cannot remove more vertices than the mesh contains"); return; } @@ -1118,7 +1222,7 @@ void ED_mesh_vertices_remove(Mesh *mesh, ReportList *reports, int count) void ED_mesh_loops_add(Mesh *mesh, ReportList *reports, int count) { if (mesh->edit_btmesh) { - BKE_report(reports, RPT_ERROR, "Can't add loops in edit mode."); + BKE_report(reports, RPT_ERROR, "Cannot add loops in edit mode"); return; } @@ -1128,7 +1232,7 @@ void ED_mesh_loops_add(Mesh *mesh, ReportList *reports, int count) void ED_mesh_polys_add(Mesh *mesh, ReportList *reports, int count) { if (mesh->edit_btmesh) { - BKE_report(reports, RPT_ERROR, "Can't add polys in edit mode."); + BKE_report(reports, RPT_ERROR, "Cannot add polygons in edit mode"); return; } diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 41666740730..82b785e5785 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -121,7 +121,7 @@ void MESH_OT_select_linked(struct wmOperatorType *ot); void MESH_OT_select_linked_pick(struct wmOperatorType *ot); void MESH_OT_hide(struct wmOperatorType *ot); void MESH_OT_reveal(struct wmOperatorType *ot); -void MESH_OT_select_by_number_vertices(struct wmOperatorType *ot); +void MESH_OT_select_face_by_sides(struct wmOperatorType *ot); void MESH_OT_select_loose_verts(struct wmOperatorType *ot); void MESH_OT_select_mirror(struct wmOperatorType *ot); void MESH_OT_normals_make_consistent(struct wmOperatorType *ot); @@ -134,6 +134,7 @@ void MESH_OT_loop_multi_select(struct wmOperatorType *ot); void MESH_OT_mark_seam(struct wmOperatorType *ot); void MESH_OT_mark_sharp(struct wmOperatorType *ot); void MESH_OT_vertices_smooth(struct wmOperatorType *ot); +void MESH_OT_vertices_smooth_laplacian(struct wmOperatorType *ot); void MESH_OT_noise(struct wmOperatorType *ot); void MESH_OT_flip_normals(struct wmOperatorType *ot); void MESH_OT_solidify(struct wmOperatorType *ot); @@ -144,6 +145,7 @@ extern struct EnumPropertyItem *corner_type_items; void MESH_OT_merge(struct wmOperatorType *ot); void MESH_OT_subdivide(struct wmOperatorType *ot); +void MESH_OT_unsubdivide(struct wmOperatorType *ot); void MESH_OT_remove_doubles(struct wmOperatorType *ot); void MESH_OT_spin(struct wmOperatorType *ot); void MESH_OT_screw(struct wmOperatorType *ot); @@ -187,8 +189,10 @@ void MESH_OT_uv_texture_add(struct wmOperatorType *ot); void MESH_OT_uv_texture_remove(struct wmOperatorType *ot); void MESH_OT_vertex_color_add(struct wmOperatorType *ot); void MESH_OT_vertex_color_remove(struct wmOperatorType *ot); -void MESH_OT_sticky_add(struct wmOperatorType *ot); -void MESH_OT_sticky_remove(struct wmOperatorType *ot); +/* no create_mask yet */ +void MESH_OT_customdata_clear_mask(struct wmOperatorType *ot); +void MESH_OT_customdata_clear_skin(struct wmOperatorType *ot); + void MESH_OT_drop_named_image(struct wmOperatorType *ot); /* ************* bmesh_tools.c ***********/ @@ -212,6 +216,8 @@ void MESH_OT_vert_slide(struct wmOperatorType *ot); void MESH_OT_convex_hull(struct wmOperatorType *ot); +void MESH_OT_symmetrize(struct wmOperatorType *ot); + /* ******************* mesh_navmesh.c */ void MESH_OT_navmesh_make(struct wmOperatorType *ot); void MESH_OT_navmesh_face_copy(struct wmOperatorType *ot); @@ -219,5 +225,4 @@ void MESH_OT_navmesh_face_add(struct wmOperatorType *ot); void MESH_OT_navmesh_reset(struct wmOperatorType *ot); void MESH_OT_navmesh_clear(struct wmOperatorType *ot); -#endif // __MESH_INTERN_H__ - +#endif /* __MESH_INTERN_H__ */ diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c index 88b1f191e3a..f6f8eee0a69 100644 --- a/source/blender/editors/mesh/mesh_navmesh.c +++ b/source/blender/editors/mesh/mesh_navmesh.c @@ -209,7 +209,7 @@ static int buildNavMesh(const RecastData *recastParams, int nverts, float *verts triflags = MEM_callocN(sizeof(unsigned char) * ntris, "buildNavMesh triflags"); /* Find triangles which are walkable based on their slope and rasterize them */ - recast_markWalkableTriangles(RAD2DEG(recastParams->agentmaxslope), verts, nverts, tris, ntris, triflags); + recast_markWalkableTriangles(RAD2DEGF(recastParams->agentmaxslope), verts, nverts, tris, ntris, triflags); recast_rasterizeTriangles(verts, nverts, tris, triflags, ntris, solid); MEM_freeN(triflags); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index dfa1beb614f..d319fdcca26 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -68,12 +68,13 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_select_random); WM_operatortype_append(MESH_OT_hide); WM_operatortype_append(MESH_OT_reveal); - WM_operatortype_append(MESH_OT_select_by_number_vertices); + WM_operatortype_append(MESH_OT_select_face_by_sides); WM_operatortype_append(MESH_OT_select_loose_verts); WM_operatortype_append(MESH_OT_select_mirror); WM_operatortype_append(MESH_OT_normals_make_consistent); WM_operatortype_append(MESH_OT_merge); WM_operatortype_append(MESH_OT_subdivide); + WM_operatortype_append(MESH_OT_unsubdivide); WM_operatortype_append(MESH_OT_faces_select_linked_flat); WM_operatortype_append(MESH_OT_edges_select_sharp); WM_operatortype_append(MESH_OT_primitive_plane_add); @@ -132,9 +133,9 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_mark_seam); WM_operatortype_append(MESH_OT_mark_sharp); WM_operatortype_append(MESH_OT_vertices_smooth); + WM_operatortype_append(MESH_OT_vertices_smooth_laplacian); WM_operatortype_append(MESH_OT_noise); WM_operatortype_append(MESH_OT_flip_normals); - //WM_operatortype_append(MESH_OT_knife_cut); WM_operatortype_append(MESH_OT_rip); WM_operatortype_append(MESH_OT_blend_from_shape); WM_operatortype_append(MESH_OT_shape_propagate_to_all); @@ -143,8 +144,8 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_uv_texture_remove); WM_operatortype_append(MESH_OT_vertex_color_add); WM_operatortype_append(MESH_OT_vertex_color_remove); - WM_operatortype_append(MESH_OT_sticky_add); - WM_operatortype_append(MESH_OT_sticky_remove); + WM_operatortype_append(MESH_OT_customdata_clear_mask); + WM_operatortype_append(MESH_OT_customdata_clear_skin); WM_operatortype_append(MESH_OT_drop_named_image); WM_operatortype_append(MESH_OT_edgering_select); @@ -165,7 +166,11 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_wireframe); WM_operatortype_append(MESH_OT_edge_split); +#ifdef WITH_BULLET WM_operatortype_append(MESH_OT_convex_hull); +#endif + + WM_operatortype_append(MESH_OT_symmetrize); #ifdef WITH_GAMEENGINE WM_operatortype_append(MESH_OT_navmesh_make); @@ -210,7 +215,17 @@ void ED_operatormacros_mesh(void) ot = WM_operatortype_append_macro("MESH_OT_rip_move", "Rip", "Rip polygons and move the result", OPTYPE_UNDO | OPTYPE_REGISTER); - WM_operatortype_macro_define(ot, "MESH_OT_rip"); + otmacro = WM_operatortype_macro_define(ot, "MESH_OT_rip"); + RNA_boolean_set(otmacro->ptr, "use_fill", FALSE); + otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + RNA_enum_set(otmacro->ptr, "proportional", 0); + RNA_boolean_set(otmacro->ptr, "mirror", FALSE); + + /* annoying we can't pass 'use_fill' through the macro */ + ot = WM_operatortype_append_macro("MESH_OT_rip_move_fill", "Rip Fill", "Rip-fill polygons and move the result", + OPTYPE_UNDO | OPTYPE_REGISTER); + otmacro = WM_operatortype_macro_define(ot, "MESH_OT_rip"); + RNA_boolean_set(otmacro->ptr, "use_fill", TRUE); otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); RNA_enum_set(otmacro->ptr, "proportional", 0); RNA_boolean_set(otmacro->ptr, "mirror", FALSE); @@ -325,6 +340,8 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MESH_OT_tris_convert_to_quads", JKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "MESH_OT_rip_move", VKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "MESH_OT_rip_move_fill", VKEY, KM_PRESS, KM_ALT, 0); + WM_keymap_add_item(keymap, "MESH_OT_merge", MKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "TRANSFORM_OT_shrink_fatten", SKEY, KM_PRESS, KM_ALT, 0); diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index a7467ee4c79..c0b6327d740 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -104,7 +104,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) MLoop *mloop = NULL; Key *key, *nkey = NULL; KeyBlock *kb, *okb, *kbn; - float imat[4][4], cmat[4][4], *fp1, *fp2, curpos; + float imat[4][4], cmat[4][4], *fp1, *fp2; int a, b, totcol, totmat = 0, totedge = 0, totvert = 0, ok = 0; int totloop = 0, totpoly = 0, vertofs, *matmap = NULL; int i, j, index, haskey = 0, edgeofs, loopofs, polyofs; @@ -113,7 +113,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) CustomData vdata, edata, fdata, ldata, pdata; if (scene->obedit) { - BKE_report(op->reports, RPT_WARNING, "Cant join while in editmode"); + BKE_report(op->reports, RPT_WARNING, "Cannot join while in edit mode"); return OPERATOR_CANCELLED; } @@ -161,10 +161,13 @@ int join_mesh_exec(bContext *C, wmOperator *op) } if (totvert > MESH_MAX_VERTS) { - BKE_reportf(op->reports, RPT_WARNING, "Joining results in %d vertices, limit is " STRINGIFY(MESH_MAX_VERTS), totvert); - return OPERATOR_CANCELLED; + BKE_reportf(op->reports, RPT_WARNING, "Joining results in %d vertices, limit is %ld", totvert, MESH_MAX_VERTS); + return OPERATOR_CANCELLED; } + /* remove tessface to ensure we don't old references to invalid faces */ + BKE_mesh_tessface_clear(me); + /* new material indices and material array */ matar = MEM_callocN(sizeof(void *) * totmat, "join_mesh matar"); if (totmat) matmap = MEM_callocN(sizeof(int) * totmat, "join_mesh matmap"); @@ -196,7 +199,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) } else if (haskey) { /* add a new key-block and add to the mesh */ - key = me->key = add_key((ID *)me); + key = me->key = BKE_key_add((ID *)me); key->type = KEY_RELATIVE; } @@ -243,29 +246,29 @@ int join_mesh_exec(bContext *C, wmOperator *op) /* if this mesh has shapekeys, check if destination mesh already has matching entries too */ if (me->key && key) { - for (kb = me->key->block.first; kb; kb = kb->next) { + /* for remapping KeyBlock.relative */ + int *index_map = MEM_mallocN(sizeof(int) * me->key->totkey, __func__); + KeyBlock **kb_map = MEM_mallocN(sizeof(KeyBlock *) * me->key->totkey, __func__); + + for (kb = me->key->block.first, i = 0; kb; kb = kb->next, i++) { + BLI_assert(i < me->key->totkey); + + kbn = BKE_keyblock_find_name(key, kb->name); /* if key doesn't exist in destination mesh, add it */ - if (key_get_named_keyblock(key, kb->name) == NULL) { - /* copy this existing one over to the new shapekey block */ - kbn = MEM_dupallocN(kb); - kbn->prev = kbn->next = NULL; - + if (kbn) { + index_map[i] = BLI_findindex(&key->block, kbn); + } + else { + index_map[i] = key->totkey; + + kbn = BKE_keyblock_add(key, kb->name); + + BKE_keyblock_copy_settings(kbn, kb); + /* adjust settings to fit (allocate a new data-array) */ kbn->data = MEM_callocN(sizeof(float) * 3 * totvert, "joined_shapekey"); kbn->totelem = totvert; - kbn->weights = NULL; - - okb = key->block.last; - curpos = (okb) ? okb->pos : -0.1f; - if (key->type == KEY_RELATIVE) - kbn->pos = curpos + 0.1f; - else - kbn->pos = curpos; - - BLI_addtail(&key->block, kbn); - key->totkey++; - if (key->totkey == 1) key->refkey = kbn; - + /* XXX 2.5 Animato */ #if 0 /* also, copy corresponding ipo-curve to ipo-block if applicable */ @@ -275,20 +278,33 @@ int join_mesh_exec(bContext *C, wmOperator *op) } #endif } + + kb_map[i] = kbn; } + + /* remap relative index values */ + for (kb = me->key->block.first, i = 0; kb; kb = kb->next, i++) { + if (LIKELY(kb->relative < me->key->totkey)) { /* sanity check, should always be true */ + kb_map[i]->relative = index_map[kb->relative]; + } + } + + MEM_freeN(index_map); + MEM_freeN(kb_map); } } } } CTX_DATA_END; - + + /* setup new data for destination mesh */ - memset(&vdata, 0, sizeof(vdata)); - memset(&edata, 0, sizeof(edata)); - memset(&fdata, 0, sizeof(fdata)); - memset(&ldata, 0, sizeof(ldata)); - memset(&pdata, 0, sizeof(pdata)); - + CustomData_reset(&vdata); + CustomData_reset(&edata); + CustomData_reset(&fdata); + CustomData_reset(&ldata); + CustomData_reset(&pdata); + mvert = CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert); medge = CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge); mloop = CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, NULL, totloop); @@ -356,7 +372,8 @@ int join_mesh_exec(bContext *C, wmOperator *op) fp1 = ((float *)kb->data) + (vertofs * 3); /* check if this mesh has such a shapekey */ - okb = key_get_named_keyblock(me->key, kb->name); + okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL; + if (okb) { /* copy this mesh's shapekey to the destination shapekey (need to transform first) */ fp2 = ((float *)(okb->data)); @@ -386,7 +403,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) fp1 = ((float *)kb->data) + (vertofs * 3); /* check if this was one of the original shapekeys */ - okb = key_get_named_keyblock(nkey, kb->name); + okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL; if (okb) { /* copy this mesh's shapekey to the destination shapekey */ fp2 = ((float *)(okb->data)); @@ -427,8 +444,8 @@ int join_mesh_exec(bContext *C, wmOperator *op) if ((mmd = get_multires_modifier(scene, base->object, TRUE))) { ED_object_iter_other(bmain, base->object, TRUE, - ED_object_multires_update_totlevels_cb, - &mmd->totlvl); + ED_object_multires_update_totlevels_cb, + &mmd->totlvl); } } @@ -499,7 +516,8 @@ int join_mesh_exec(bContext *C, wmOperator *op) me->ldata = ldata; me->pdata = pdata; - mesh_update_customdata_pointers(me, TRUE); /* BMESH_TODO, check if this arg can be failse, non urgent - campbell */ + /* tessface data removed above, no need to update */ + mesh_update_customdata_pointers(me, FALSE); /* old material array */ for (a = 1; a <= ob->totcol; a++) { @@ -548,6 +566,12 @@ int join_mesh_exec(bContext *C, wmOperator *op) MEM_freeN(nkey); } + /* ensure newly inserted keys are time sorted */ + if (key && (key->type != KEY_RELATIVE)) { + BKE_key_sort(key); + } + + DAG_scene_sort(bmain, scene); // removed objects, need to rebuild dag before editmode call #if 0 @@ -607,12 +631,12 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op) } if (key == NULL) { - key = me->key = add_key((ID *)me); + key = me->key = BKE_key_add((ID *)me); key->type = KEY_RELATIVE; /* first key added, so it was the basis. initialize it with the existing mesh */ - kb = add_keyblock(key, NULL); - mesh_to_key(me, kb); + kb = BKE_keyblock_add(key, NULL); + BKE_key_convert_from_mesh(me, kb); } /* now ready to add new keys from selected meshes */ @@ -628,7 +652,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op) if (!dm) continue; - kb = add_keyblock(key, base->object->id.name + 2); + kb = BKE_keyblock_add(key, base->object->id.name + 2); DM_to_meshkey(dm, me, kb); @@ -709,9 +733,9 @@ static void mesh_octree_add_nodes(MocNode **basetable, const float co[3], const float fx, fy, fz; int vx, vy, vz; - if (!finite(co[0]) || - !finite(co[1]) || - !finite(co[2])) + if ((finite(co[0]) == FALSE) || + (finite(co[1]) == FALSE) || + (finite(co[2]) == FALSE)) { return; } @@ -823,7 +847,7 @@ intptr_t mesh_octree_table(Object *ob, BMEditMesh *em, const float co[3], char m minmax_v3v3_v3(min, max, eve->co); } } - else { + else { MVert *mvert; int a; @@ -858,7 +882,7 @@ intptr_t mesh_octree_table(Object *ob, BMEditMesh *em, const float co[3], char m mesh_octree_add_nodes(MeshOctree.table, eve->co, MeshOctree.offs, MeshOctree.div, (intptr_t)(eve)); } } - else { + else { MVert *mvert; int a; @@ -940,9 +964,9 @@ static BMVert *editbmesh_get_x_mirror_vert_spatial(Object *ob, BMEditMesh *em, c intptr_t poinval; /* ignore nan verts */ - if (!finite(co[0]) || - !finite(co[1]) || - !finite(co[2])) + if ((finite(co[0]) == FALSE) || + (finite(co[1]) == FALSE) || + (finite(co[2]) == FALSE)) { return NULL; } @@ -1172,7 +1196,7 @@ int ED_mesh_pick_face(bContext *C, Mesh *me, const int mval[2], unsigned int *in /* sample rect to increase chances of selecting, so that when clicking * on an edge in the backbuf, we can still select a face */ - int dummy_dist; + float dummy_dist; *index = view3d_sample_backbuf_rect(&vc, mval, size, 1, me->totpoly + 1, &dummy_dist, 0, NULL, NULL); } else { @@ -1217,11 +1241,12 @@ int ED_mesh_pick_face_vert(bContext *C, Mesh *me, Object *ob, const int mval[2], const int v_idx = me->mloop[mp->loopstart + fidx].v; dm->getVertCo(dm, v_idx, co); mul_m4_v3(ob->obmat, co); - project_float_noclip(ar, co, sco); - len = len_squared_v2v2(mval_f, sco); - if (len < len_best) { - len_best = len; - v_idx_best = v_idx; + if (ED_view3d_project_float_global(ar, co, sco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + len = len_squared_v2v2(mval_f, sco); + if (len < len_best) { + len_best = len; + v_idx_best = v_idx; + } } } while (fidx--); } @@ -1256,7 +1281,7 @@ int ED_mesh_pick_vert(bContext *C, Mesh *me, const int mval[2], unsigned int *in /* sample rect to increase chances of selecting, so that when clicking * on an face in the backbuf, we can still select a vert */ - int dummy_dist; + float dummy_dist; *index = view3d_sample_backbuf_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist, 0, NULL, NULL); } else { diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c index 50d5569c483..8633a7a9b38 100644 --- a/source/blender/editors/metaball/mball_edit.c +++ b/source/blender/editors/metaball/mball_edit.c @@ -98,9 +98,8 @@ void load_editMball(Object *UNUSED(obedit)) } /* Add metaelem primitive to metaball object (which is in edit mode) */ -MetaElem *add_metaball_primitive(bContext *C, float mat[4][4], int type, int UNUSED(newname)) +MetaElem *add_metaball_primitive(bContext *UNUSED(C), Object *obedit, float mat[4][4], float dia, int type, int UNUSED(newname)) { - Object *obedit = CTX_data_edit_object(C); MetaBall *mball = (MetaBall *)obedit->data; MetaElem *ml; @@ -112,6 +111,7 @@ MetaElem *add_metaball_primitive(bContext *C, float mat[4][4], int type, int UNU } ml = BKE_mball_element_add(mball, type); + ml->rad *= dia; copy_v3_v3(&ml->x, mat[3]); ml->flag |= SELECT; @@ -124,43 +124,38 @@ MetaElem *add_metaball_primitive(bContext *C, float mat[4][4], int type, int UNU /* Select or deselect all MetaElements */ static int mball_select_all_exec(bContext *C, wmOperator *op) { - //Scene *scene= CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); MetaBall *mb = (MetaBall *)obedit->data; MetaElem *ml; int action = RNA_enum_get(op->ptr, "action"); - ml = mb->editelems->first; - if (ml) { - if (action == SEL_TOGGLE) { - action = SEL_SELECT; - while (ml) { - if (ml->flag & SELECT) { - action = SEL_DESELECT; - break; - } - ml = ml->next; - } - } + if (mb->editelems->first == NULL) + return OPERATOR_CANCELLED; - ml = mb->editelems->first; - while (ml) { - switch (action) { - case SEL_SELECT: - ml->flag |= SELECT; - break; - case SEL_DESELECT: - ml->flag &= ~SELECT; - break; - case SEL_INVERT: - ml->flag ^= SELECT; - break; + if (action == SEL_TOGGLE) { + action = SEL_SELECT; + for (ml = mb->editelems->first; ml; ml = ml->next) { + if (ml->flag & SELECT) { + action = SEL_DESELECT; + break; } - ml = ml->next; } - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb); } + switch (action) { + case SEL_SELECT: + BKE_mball_select_all(mb); + break; + case SEL_DESELECT: + BKE_mball_deselect_all(mb); + break; + case SEL_INVERT: + BKE_mball_select_swap(mb); + break; + } + + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb); + return OPERATOR_FINISHED; } @@ -422,7 +417,7 @@ int mouse_mball(bContext *C, const int mval[2], int extend, int deselect, int to Object *obedit = CTX_data_edit_object(C); ViewContext vc; MetaBall *mb = (MetaBall *)obedit->data; - MetaElem *ml, *act = NULL; + MetaElem *ml, *ml_act = NULL; int a, hits; unsigned int buffer[4 * MAXPICKBUF]; rcti rect; @@ -452,14 +447,14 @@ int mouse_mball(bContext *C, const int mval[2], int extend, int deselect, int to /* index converted for gl stuff */ if (ml->selcol1 == buffer[4 * a + 3]) { ml->flag |= MB_SCALE_RAD; - act = ml; + ml_act = ml; } if (ml->selcol2 == buffer[4 * a + 3]) { ml->flag &= ~MB_SCALE_RAD; - act = ml; + ml_act = ml; } } - if (act) break; + if (ml_act) break; ml = ml->next; if (ml == NULL) ml = mb->editelems->first; if (ml == startelem) break; @@ -467,31 +462,28 @@ int mouse_mball(bContext *C, const int mval[2], int extend, int deselect, int to /* When some metaelem was found, then it is necessary to select or * deselect it. */ - if (act) { + if (ml_act) { if (extend) { - act->flag |= SELECT; + ml_act->flag |= SELECT; } else if (deselect) { - act->flag &= ~SELECT; + ml_act->flag &= ~SELECT; } else if (toggle) { - if (act->flag & SELECT) - act->flag &= ~SELECT; + if (ml_act->flag & SELECT) + ml_act->flag &= ~SELECT; else - act->flag |= SELECT; + ml_act->flag |= SELECT; } else { /* Deselect all existing metaelems */ - ml = mb->editelems->first; - while (ml) { - ml->flag &= ~SELECT; - ml = ml->next; - } + BKE_mball_deselect_all(mb); + /* Select only metaelem clicked on */ - act->flag |= SELECT; + ml_act->flag |= SELECT; } - mb->lastelem = act; + mb->lastelem = ml_act; WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index d73bbbabf84..9fc4e0a906d 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -43,6 +43,7 @@ #include "DNA_meta_types.h" #include "DNA_object_fluidsim.h" #include "DNA_object_force.h" +#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_speaker_types.h" #include "DNA_vfont_types.h" @@ -110,7 +111,7 @@ #include "object_intern.h" /* this is an exact copy of the define in rna_lamp.c - * kept here because of linking order. + * kept here because of linking order. * Icons are only defined here */ EnumPropertyItem lamp_type_items[] = { {LA_LOCAL, "POINT", ICON_LAMP_POINT, "Point", "Omnidirectional point light source"}, @@ -121,6 +122,24 @@ EnumPropertyItem lamp_type_items[] = { {0, NULL, 0, NULL, NULL} }; +/* copy from rna_object_force.c */ +static EnumPropertyItem field_type_items[] = { + {PFIELD_FORCE, "FORCE", ICON_FORCE_FORCE, "Force", ""}, + {PFIELD_WIND, "WIND", ICON_FORCE_WIND, "Wind", ""}, + {PFIELD_VORTEX, "VORTEX", ICON_FORCE_VORTEX, "Vortex", ""}, + {PFIELD_MAGNET, "MAGNET", ICON_FORCE_MAGNETIC, "Magnetic", ""}, + {PFIELD_HARMONIC, "HARMONIC", ICON_FORCE_HARMONIC, "Harmonic", ""}, + {PFIELD_CHARGE, "CHARGE", ICON_FORCE_CHARGE, "Charge", ""}, + {PFIELD_LENNARDJ, "LENNARDJ", ICON_FORCE_LENNARDJONES, "Lennard-Jones", ""}, + {PFIELD_TEXTURE, "TEXTURE", ICON_FORCE_TEXTURE, "Texture", ""}, + {PFIELD_GUIDE, "GUIDE", ICON_FORCE_CURVE, "Curve Guide", ""}, + {PFIELD_BOID, "BOID", ICON_FORCE_BOID, "Boid", ""}, + {PFIELD_TURBULENCE, "TURBULENCE", ICON_FORCE_TURBULENCE, "Turbulence", ""}, + {PFIELD_DRAG, "DRAG", ICON_FORCE_DRAG, "Drag", ""}, + {PFIELD_SMOKEFLOW, "SMOKE", ICON_FORCE_SMOKEFLOW, "Smoke Flow", ""}, + {0, NULL, 0, NULL, NULL} +}; + /************************** Exported *****************************/ void ED_object_location_from_view(bContext *C, float loc[3]) @@ -128,7 +147,7 @@ void ED_object_location_from_view(bContext *C, float loc[3]) View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); float *cursor; - + cursor = give_cursor(scene, v3d); copy_v3_v3(loc, cursor); @@ -152,46 +171,56 @@ void ED_object_base_init_transform(bContext *C, Base *base, const float loc[3], { Object *ob = base->object; Scene *scene = CTX_data_scene(C); - + if (!scene) return; - + if (loc) copy_v3_v3(ob->loc, loc); - + if (rot) copy_v3_v3(ob->rot, rot); - + BKE_object_where_is_calc(scene, ob); } -/* uses context to figure out transform for primitive */ -/* returns standard diameter */ +/* Uses context to figure out transform for primitive. + * Returns standard diameter. */ float ED_object_new_primitive_matrix(bContext *C, Object *obedit, - const float loc[3], const float rot[3], float primmat[][4]) + const float loc[3], const float rot[3], float primmat[][4], + int apply_diameter) { Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); float mat[3][3], rmat[3][3], cmat[3][3], imat[3][3]; - + unit_m4(primmat); - + eul_to_mat3(rmat, rot); invert_m3(rmat); - + /* inverse transform for initial rotation and object */ copy_m3_m4(mat, obedit->obmat); mul_m3_m3m3(cmat, rmat, mat); invert_m3_m3(imat, cmat); copy_m4_m3(primmat, imat); - + /* center */ copy_v3_v3(primmat[3], loc); sub_v3_v3v3(primmat[3], primmat[3], obedit->obmat[3]); invert_m3_m3(imat, mat); mul_m3_v3(imat, primmat[3]); - - if (v3d) - return ED_view3d_grid_scale(scene, v3d, NULL); + + if (v3d) { + float dia = ED_view3d_grid_scale(scene, v3d, NULL); + + if (apply_diameter) { + primmat[0][0] *= dia; + primmat[1][1] *= dia; + primmat[2][2] *= dia; + } + + return dia; + } return 1.0f; } @@ -206,7 +235,7 @@ static void view_align_update(struct Main *UNUSED(main), struct Scene *UNUSED(sc void ED_object_add_generic_props(wmOperatorType *ot, int do_editmode) { PropertyRNA *prop; - + /* note: this property gets hidden for add-camera operator */ prop = RNA_def_boolean(ot->srna, "view_align", 0, "Align to View", "Align the new object to the view"); RNA_def_property_update_runtime(prop, view_align_update); @@ -216,112 +245,112 @@ void ED_object_add_generic_props(wmOperatorType *ot, int do_editmode) "Enter editmode when adding this object"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } - + prop = RNA_def_float_vector_xyz(ot->srna, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location", "Location for the newly added object", -FLT_MAX, FLT_MAX); RNA_def_property_flag(prop, PROP_SKIP_SAVE); prop = RNA_def_float_rotation(ot->srna, "rotation", 3, NULL, -FLT_MAX, FLT_MAX, "Rotation", "Rotation for the newly added object", (float)-M_PI * 2.0f, (float)M_PI * 2.0f); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - + prop = RNA_def_boolean_layer_member(ot->srna, "layers", 20, NULL, "Layer", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } -static void object_add_generic_invoke_options(bContext *C, wmOperator *op) -{ - if (RNA_struct_find_property(op->ptr, "enter_editmode")) /* optional */ - if (!RNA_struct_property_is_set(op->ptr, "enter_editmode")) - RNA_boolean_set(op->ptr, "enter_editmode", U.flag & USER_ADD_EDITMODE); - - if (!RNA_struct_property_is_set(op->ptr, "location")) { - float loc[3]; - - ED_object_location_from_view(C, loc); - RNA_float_set_array(op->ptr, "location", loc); - } - - if (!RNA_struct_property_is_set(op->ptr, "layers")) { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - int a, values[20], layer; - - if (v3d) { - layer = (v3d->scenelock && !v3d->localvd) ? scene->layact : v3d->layact; - } - else { - layer = scene->layact; - } - - for (a = 0; a < 20; a++) { - values[a] = (layer & (1 << a)); - } - - RNA_boolean_set_array(op->ptr, "layers", values); - } -} - -int ED_object_add_generic_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) -{ - object_add_generic_invoke_options(C, op); - return op->type->exec(C, op); -} - int ED_object_add_generic_get_opts(bContext *C, wmOperator *op, float loc[3], float rot[3], int *enter_editmode, unsigned int *layer, int *is_view_aligned) { View3D *v3d = CTX_wm_view3d(C); - int a, layer_values[20]; - int view_align; - - *enter_editmode = FALSE; - if (RNA_struct_find_property(op->ptr, "enter_editmode") && RNA_boolean_get(op->ptr, "enter_editmode")) { - *enter_editmode = TRUE; - } - if (RNA_struct_property_is_set(op->ptr, "layers")) { - RNA_boolean_get_array(op->ptr, "layers", layer_values); - *layer = 0; - for (a = 0; a < 20; a++) { - if (layer_values[a]) - *layer |= (1 << a); - else - *layer &= ~(1 << a); + /* Switch to Edit mode? */ + if (RNA_struct_find_property(op->ptr, "enter_editmode")) { /* optional */ + int _enter_editmode; + if (!enter_editmode) + enter_editmode = &_enter_editmode; + + if (RNA_struct_property_is_set(op->ptr, "enter_editmode") && enter_editmode) + *enter_editmode = RNA_boolean_get(op->ptr, "enter_editmode"); + else { + *enter_editmode = U.flag & USER_ADD_EDITMODE; + RNA_boolean_set(op->ptr, "enter_editmode", *enter_editmode); } } - else { - /* not set, use the scenes layers */ - Scene *scene = CTX_data_scene(C); - *layer = scene->layact; + + /* Get layers! */ + { + int a, layer_values[20]; + unsigned int _layer; + if (!layer) + layer = &_layer; + + if (RNA_struct_property_is_set(op->ptr, "layers")) { + RNA_boolean_get_array(op->ptr, "layers", layer_values); + *layer = 0; + for (a = 0; a < 20; a++) { + if (layer_values[a]) + *layer |= (1 << a); + } + } + else { + Scene *scene = CTX_data_scene(C); + if (v3d) + *layer = (v3d->scenelock && !v3d->localvd) ? scene->layact : v3d->layact; + else + *layer = scene->layact; + for (a = 0; a < 20; a++) { + layer_values[a] = *layer & (1 << a); + } + RNA_boolean_set_array(op->ptr, "layers", layer_values); + } + + /* in local view we additionally add local view layers, + * not part of operator properties */ + if (v3d && v3d->localvd) + *layer |= v3d->lay; } - /* in local view we additionally add local view layers, - * not part of operator properties */ - if (v3d && v3d->localvd) - *layer |= v3d->lay; + /* Location! */ + { + float _loc[3]; + if (!loc) + loc = _loc; - if (RNA_struct_property_is_set(op->ptr, "rotation")) - view_align = FALSE; - else if (RNA_struct_property_is_set(op->ptr, "view_align")) - view_align = RNA_boolean_get(op->ptr, "view_align"); - else { - view_align = U.flag & USER_ADD_VIEWALIGNED; - RNA_boolean_set(op->ptr, "view_align", view_align); + if (RNA_struct_property_is_set(op->ptr, "location")) { + RNA_float_get_array(op->ptr, "location", loc); + } + else { + ED_object_location_from_view(C, loc); + RNA_float_set_array(op->ptr, "location", loc); + } } - - if (view_align) { - ED_object_rotation_from_view(C, rot); - RNA_float_set_array(op->ptr, "rotation", rot); - } - else - RNA_float_get_array(op->ptr, "rotation", rot); - - if (is_view_aligned) - *is_view_aligned = view_align; - - RNA_float_get_array(op->ptr, "location", loc); - if (*layer == 0) { + /* Rotation! */ + { + int _is_view_aligned; + float _rot[3]; + if (!is_view_aligned) + is_view_aligned = &_is_view_aligned; + if (!rot) + rot = _rot; + + if (RNA_struct_property_is_set(op->ptr, "rotation")) + *is_view_aligned = FALSE; + else if (RNA_struct_property_is_set(op->ptr, "view_align")) + *is_view_aligned = RNA_boolean_get(op->ptr, "view_align"); + else { + *is_view_aligned = U.flag & USER_ADD_VIEWALIGNED; + RNA_boolean_set(op->ptr, "view_align", *is_view_aligned); + } + + if (*is_view_aligned) { + ED_object_rotation_from_view(C, rot); + RNA_float_set_array(op->ptr, "rotation", rot); + } + else + RNA_float_get_array(op->ptr, "rotation", rot); + } + + if (layer && *layer == 0) { BKE_report(op->reports, RPT_ERROR, "Property 'layer' has no values set"); return 0; } @@ -329,19 +358,19 @@ int ED_object_add_generic_get_opts(bContext *C, wmOperator *op, float loc[3], fl return 1; } -/* for object add primitive operators */ -/* do not call undo push in this function (users of this function have to) */ +/* For object add primitive operators. + * Do not call undo push in this function (users of this function have to). */ Object *ED_object_add_type(bContext *C, int type, const float loc[3], const float rot[3], int enter_editmode, unsigned int layer) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); Object *ob; - + /* for as long scene has editmode... */ if (CTX_data_edit_object(C)) ED_object_exit_editmode(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); /* freedata, and undo */ - + /* deselects all, sets scene->basact */ ob = BKE_object_add(scene, type); BASACT->lay = ob->lay = layer; @@ -371,12 +400,12 @@ static int object_add_exec(bContext *C, wmOperator *op) int enter_editmode; unsigned int layer; float loc[3], rot[3]; - + if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL)) return OPERATOR_CANCELLED; ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), loc, rot, enter_editmode, layer); - + return OPERATOR_FINISHED; } @@ -386,89 +415,62 @@ void OBJECT_OT_add(wmOperatorType *ot) ot->name = "Add Object"; ot->description = "Add an object to the scene"; ot->idname = "OBJECT_OT_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = object_add_exec; - ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + RNA_def_enum(ot->srna, "type", object_type_items, 0, "Type", ""); ED_object_add_generic_props(ot, TRUE); } /********************* Add Effector Operator ********************/ -/* copy from rna_object_force.c*/ -static EnumPropertyItem field_type_items[] = { - {PFIELD_FORCE, "FORCE", ICON_FORCE_FORCE, "Force", ""}, - {PFIELD_WIND, "WIND", ICON_FORCE_WIND, "Wind", ""}, - {PFIELD_VORTEX, "VORTEX", ICON_FORCE_VORTEX, "Vortex", ""}, - {PFIELD_MAGNET, "MAGNET", ICON_FORCE_MAGNETIC, "Magnetic", ""}, - {PFIELD_HARMONIC, "HARMONIC", ICON_FORCE_HARMONIC, "Harmonic", ""}, - {PFIELD_CHARGE, "CHARGE", ICON_FORCE_CHARGE, "Charge", ""}, - {PFIELD_LENNARDJ, "LENNARDJ", ICON_FORCE_LENNARDJONES, "Lennard-Jones", ""}, - {PFIELD_TEXTURE, "TEXTURE", ICON_FORCE_TEXTURE, "Texture", ""}, - {PFIELD_GUIDE, "GUIDE", ICON_FORCE_CURVE, "Curve Guide", ""}, - {PFIELD_BOID, "BOID", ICON_FORCE_BOID, "Boid", ""}, - {PFIELD_TURBULENCE, "TURBULENCE", ICON_FORCE_TURBULENCE, "Turbulence", ""}, - {PFIELD_DRAG, "DRAG", ICON_FORCE_DRAG, "Drag", ""}, - {0, NULL, 0, NULL, NULL}}; -/* for effector add primitive operators */ -static Object *effector_add_type(bContext *C, wmOperator *op, int type) +/* for object add operator */ +static int effector_add_exec(bContext *C, wmOperator *op) { Object *ob; - int enter_editmode; + int type, enter_editmode; unsigned int layer; float loc[3], rot[3]; float mat[4][4]; - - object_add_generic_invoke_options(C, op); if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL)) - return NULL; + return OPERATOR_CANCELLED; + + type = RNA_enum_get(op->ptr, "type"); if (type == PFIELD_GUIDE) { ob = ED_object_add_type(C, OB_CURVE, loc, rot, FALSE, layer); - rename_id(&ob->id, "CurveGuide"); + if (!ob) + return OPERATOR_CANCELLED; + rename_id(&ob->id, "CurveGuide"); ((Curve *)ob->data)->flag |= CU_PATH | CU_3D; ED_object_enter_editmode(C, 0); - ED_object_new_primitive_matrix(C, ob, loc, rot, mat); - BLI_addtail(object_editcurve_get(ob), add_nurbs_primitive(C, mat, CU_NURBS | CU_PRIM_PATH, 1)); - + ED_object_new_primitive_matrix(C, ob, loc, rot, mat, FALSE); + BLI_addtail(object_editcurve_get(ob), add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, 1)); if (!enter_editmode) ED_object_exit_editmode(C, EM_FREEDATA); } else { ob = ED_object_add_type(C, OB_EMPTY, loc, rot, FALSE, layer); - rename_id(&ob->id, "Field"); + if (!ob) + return OPERATOR_CANCELLED; - switch (type) { - case PFIELD_WIND: - case PFIELD_VORTEX: - ob->empty_drawtype = OB_SINGLE_ARROW; - break; - } + rename_id(&ob->id, "Field"); + if (ELEM(type, PFIELD_WIND, PFIELD_VORTEX)) + ob->empty_drawtype = OB_SINGLE_ARROW; } ob->pd = object_add_collision_fields(type); DAG_scene_sort(CTX_data_main(C), CTX_data_scene(C)); - return ob; -} - -/* for object add operator */ -static int effector_add_exec(bContext *C, wmOperator *op) -{ - if (effector_add_type(C, op, RNA_enum_get(op->ptr, "type")) == NULL) - return OPERATOR_CANCELLED; - return OPERATOR_FINISHED; } @@ -478,22 +480,20 @@ void OBJECT_OT_effector_add(wmOperatorType *ot) ot->name = "Add Effector"; ot->description = "Add an empty object with a physics effector to the scene"; ot->idname = "OBJECT_OT_effector_add"; - + /* api callbacks */ - ot->invoke = WM_menu_invoke; ot->exec = effector_add_exec; - ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + ot->prop = RNA_def_enum(ot->srna, "type", field_type_items, 0, "Type", ""); ED_object_add_generic_props(ot, TRUE); } -/* ***************** Add Camera *************** */ +/********************* Add Camera Operator ********************/ static int object_camera_add_exec(bContext *C, wmOperator *op) { @@ -503,17 +503,15 @@ static int object_camera_add_exec(bContext *C, wmOperator *op) int enter_editmode; unsigned int layer; float loc[3], rot[3]; - + /* force view align for cameras */ RNA_boolean_set(op->ptr, "view_align", TRUE); - - object_add_generic_invoke_options(C, op); if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL)) return OPERATOR_CANCELLED; ob = ED_object_add_type(C, OB_CAMERA, loc, rot, FALSE, layer); - + if (v3d) { if (v3d->camera == NULL) v3d->camera = ob; @@ -528,83 +526,63 @@ static int object_camera_add_exec(bContext *C, wmOperator *op) void OBJECT_OT_camera_add(wmOperatorType *ot) { PropertyRNA *prop; - + /* identifiers */ ot->name = "Add Camera"; ot->description = "Add a camera object to the scene"; ot->idname = "OBJECT_OT_camera_add"; - + /* api callbacks */ ot->exec = object_camera_add_exec; ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + ED_object_add_generic_props(ot, TRUE); - + /* hide this for cameras, default */ prop = RNA_struct_type_find_property(ot->srna, "view_align"); RNA_def_property_flag(prop, PROP_HIDDEN); - } -/* ***************** add primitives *************** */ +/********************* Add Metaball Operator ********************/ + static int object_metaball_add_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); - /*MetaElem *elem;*/ /*UNUSED*/ int newob = 0; int enter_editmode; unsigned int layer; float loc[3], rot[3]; float mat[4][4]; - - object_add_generic_invoke_options(C, op); /* XXX these props don't get set right when only exec() is called */ + float dia; if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL)) return OPERATOR_CANCELLED; - + if (obedit == NULL || obedit->type != OB_MBALL) { obedit = ED_object_add_type(C, OB_MBALL, loc, rot, TRUE, layer); newob = 1; } - else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); - - ED_object_new_primitive_matrix(C, obedit, loc, rot, mat); - - /* elem= (MetaElem *) */ add_metaball_primitive(C, mat, RNA_enum_get(op->ptr, "type"), newob); + else + DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + + dia = ED_object_new_primitive_matrix(C, obedit, loc, rot, mat, FALSE); + + add_metaball_primitive(C, obedit, mat, dia, RNA_enum_get(op->ptr, "type"), newob); /* userdef */ if (newob && !enter_editmode) { ED_object_exit_editmode(C, EM_FREEDATA); } - + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); - + return OPERATOR_FINISHED; } -static int object_metaball_add_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) -{ - Object *obedit = CTX_data_edit_object(C); - uiPopupMenu *pup; - uiLayout *layout; - - object_add_generic_invoke_options(C, op); - - pup = uiPupMenuBegin(C, op->type->name, ICON_NONE); - layout = uiPupMenuLayout(pup); - if (!obedit || obedit->type == OB_MBALL) - uiItemsEnumO(layout, op->type->idname, "type"); - else - uiItemsEnumO(layout, "OBJECT_OT_metaball_add", "type"); - uiPupMenuEnd(C, pup); - - return OPERATOR_CANCELLED; -} - void OBJECT_OT_metaball_add(wmOperatorType *ot) { /* identifiers */ @@ -613,35 +591,37 @@ void OBJECT_OT_metaball_add(wmOperatorType *ot) ot->idname = "OBJECT_OT_metaball_add"; /* api callbacks */ - ot->invoke = object_metaball_add_invoke; + ot->invoke = WM_menu_invoke;/* object_metaball_add_invoke; */ ot->exec = object_metaball_add_exec; ot->poll = ED_operator_scene_editable; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - RNA_def_enum(ot->srna, "type", metaelem_type_items, 0, "Primitive", ""); + + ot->prop = RNA_def_enum(ot->srna, "type", metaelem_type_items, 0, "Primitive", ""); + ED_object_add_generic_props(ot, TRUE); } +/********************* Add Text Operator ********************/ + static int object_add_text_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); int enter_editmode; unsigned int layer; float loc[3], rot[3]; - - object_add_generic_invoke_options(C, op); /* XXX these props don't get set right when only exec() is called */ + if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL)) return OPERATOR_CANCELLED; - + if (obedit && obedit->type == OB_FONT) return OPERATOR_CANCELLED; obedit = ED_object_add_type(C, OB_FONT, loc, rot, enter_editmode, layer); - + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); - + return OPERATOR_FINISHED; } @@ -651,17 +631,18 @@ void OBJECT_OT_text_add(wmOperatorType *ot) ot->name = "Add Text"; ot->description = "Add a text object to the scene"; ot->idname = "OBJECT_OT_text_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = object_add_text_exec; ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; ED_object_add_generic_props(ot, TRUE); } +/********************* Add Armature Operator ********************/ + static int object_armature_add_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -672,7 +653,6 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) unsigned int layer; float loc[3], rot[3]; - object_add_generic_invoke_options(C, op); /* XXX these props don't get set right when only exec() is called */ if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL)) return OPERATOR_CANCELLED; @@ -687,36 +667,76 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Cannot create editmode armature"); return OPERATOR_CANCELLED; } - + /* v3d and rv3d are allowed to be NULL */ add_primitive_bone(CTX_data_scene(C), v3d, rv3d); /* userdef */ if (newob && !enter_editmode) ED_object_exit_editmode(C, EM_FREEDATA); - + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); - + return OPERATOR_FINISHED; } void OBJECT_OT_armature_add(wmOperatorType *ot) -{ +{ /* identifiers */ ot->name = "Add Armature"; ot->description = "Add an armature object to the scene"; ot->idname = "OBJECT_OT_armature_add"; - + /* api callbacks */ - ot->invoke = ED_object_add_generic_invoke; ot->exec = object_armature_add_exec; ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; ED_object_add_generic_props(ot, TRUE); } +/********************* Add Empty Operator ********************/ + +static int object_empty_add_exec(bContext *C, wmOperator *op) +{ + Object *ob; + int type = RNA_enum_get(op->ptr, "type"); + unsigned int layer; + float loc[3], rot[3]; + + if (!ED_object_add_generic_get_opts(C, op, loc, rot, NULL, &layer, NULL)) + return OPERATOR_CANCELLED; + + ob = ED_object_add_type(C, OB_EMPTY, loc, rot, FALSE, layer); + ob->empty_drawtype = type; + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_empty_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Empty"; + ot->description = "Add an empty object to the scene"; + ot->idname = "OBJECT_OT_empty_add"; + + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = object_empty_add_exec; + ot->poll = ED_operator_objectmode; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", object_empty_drawtype_items, 0, "Type", ""); + + ED_object_add_generic_props(ot, FALSE); +} + +/********************* Add Lamp Operator ********************/ + static const char *get_lamp_defname(int type) { switch (type) { @@ -736,12 +756,10 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op) Object *ob; Lamp *la; int type = RNA_enum_get(op->ptr, "type"); - int enter_editmode; unsigned int layer; float loc[3], rot[3]; - - object_add_generic_invoke_options(C, op); - if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL)) + + if (!ED_object_add_generic_get_opts(C, op, loc, rot, NULL, &layer, NULL)) return OPERATOR_CANCELLED; ob = ED_object_add_type(C, OB_LAMP, loc, rot, FALSE, layer); @@ -755,7 +773,7 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op) ED_node_shader_default(scene, &la->id); la->use_nodes = TRUE; } - + return OPERATOR_FINISHED; } @@ -765,12 +783,12 @@ void OBJECT_OT_lamp_add(wmOperatorType *ot) ot->name = "Add Lamp"; ot->description = "Add a lamp object to the scene"; ot->idname = "OBJECT_OT_lamp_add"; - + /* api callbacks */ ot->invoke = WM_menu_invoke; ot->exec = object_lamp_add_exec; ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -780,16 +798,16 @@ void OBJECT_OT_lamp_add(wmOperatorType *ot) ED_object_add_generic_props(ot, FALSE); } +/********************* Add Group Instance Operator ********************/ + static int group_instance_add_exec(bContext *C, wmOperator *op) { Group *group = BLI_findlink(&CTX_data_main(C)->group, RNA_enum_get(op->ptr, "group")); - int enter_editmode; unsigned int layer; float loc[3], rot[3]; - - object_add_generic_invoke_options(C, op); - if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL)) + + if (!ED_object_add_generic_get_opts(C, op, loc, rot, NULL, &layer, NULL)) return OPERATOR_CANCELLED; if (group) { @@ -812,20 +830,42 @@ static int group_instance_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } +/* only used as menu */ +void OBJECT_OT_group_instance_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Group Instance"; + ot->description = "Add a dupligroup instance"; + ot->idname = "OBJECT_OT_group_instance_add"; + + /* api callbacks */ + ot->invoke = WM_enum_search_invoke; + ot->exec = group_instance_add_exec; + ot->poll = ED_operator_objectmode; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", ""); + RNA_def_enum_funcs(ot->prop, RNA_group_itemf); + ED_object_add_generic_props(ot, FALSE); +} + +/********************* Add Speaker Operator ********************/ + static int object_speaker_add_exec(bContext *C, wmOperator *op) { Object *ob; - int enter_editmode; unsigned int layer; float loc[3], rot[3]; Scene *scene = CTX_data_scene(C); - object_add_generic_invoke_options(C, op); - if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL)) + if (!ED_object_add_generic_get_opts(C, op, loc, rot, NULL, &layer, NULL)) return OPERATOR_CANCELLED; ob = ED_object_add_type(C, OB_SPEAKER, loc, rot, FALSE, layer); - + /* to make it easier to start using this immediately in NLA, a default sound clip is created * ready to be moved around to retime the sound and/or make new sound clips */ @@ -836,14 +876,14 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) NlaStrip *strip = add_nla_soundstrip(CTX_data_scene(C), ob->data); strip->start = CFRA; strip->end += strip->start; - + /* hook them up */ BKE_nlatrack_add_strip(nlt, strip); - + /* auto-name the strip, and give the track an interesting name */ strcpy(nlt->name, "SoundTrack"); BKE_nlastrip_validate_name(adt, strip); - + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); } @@ -867,32 +907,6 @@ void OBJECT_OT_speaker_add(wmOperatorType *ot) ED_object_add_generic_props(ot, TRUE); } -/* only used as menu */ -void OBJECT_OT_group_instance_add(wmOperatorType *ot) -{ - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Add Group Instance"; - ot->description = "Add a dupligroup instance"; - ot->idname = "OBJECT_OT_group_instance_add"; - - /* api callbacks */ - ot->invoke = WM_enum_search_invoke; - ot->exec = group_instance_add_exec; - - ot->poll = ED_operator_objectmode; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", ""); - RNA_def_enum_funcs(prop, RNA_group_itemf); - ot->prop = prop; - ED_object_add_generic_props(ot, FALSE); -} - /**************************** Delete Object *************************/ static void object_delete_check_glsl_update(Object *ob) @@ -901,7 +915,7 @@ static void object_delete_check_glsl_update(Object *ob) * are being tagged to be updated when object is removing from scene */ if (ob->type == OB_LAMP) { - if (ob->gpulamp.first) + if (ob->gpulamp.first) GPU_lamp_free(ob); } } @@ -923,16 +937,12 @@ static int object_delete_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); const short use_global = RNA_boolean_get(op->ptr, "use_global"); - /* int is_lamp = FALSE; */ /* UNUSED */ - + if (CTX_data_edit_object(C)) return OPERATOR_CANCELLED; - + CTX_DATA_BEGIN (C, Base *, base, selected_bases) { - - /* if (base->object->type==OB_LAMP) is_lamp = TRUE; */ - /* deselect object -- it could be used in other scenes */ base->object->flag &= ~SELECT; @@ -959,10 +969,10 @@ static int object_delete_exec(bContext *C, wmOperator *op) DAG_scene_sort(bmain, scene); DAG_ids_flush_update(bmain, 0); - + WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); - + return OPERATOR_FINISHED; } @@ -972,12 +982,12 @@ void OBJECT_OT_delete(wmOperatorType *ot) ot->name = "Delete"; ot->description = "Delete selected objects"; ot->idname = "OBJECT_OT_delete"; - + /* api callbacks */ ot->invoke = WM_operator_confirm; ot->exec = object_delete_exec; ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -993,29 +1003,29 @@ static void copy_object_set_idnew(bContext *C, int dupflag) Material *ma, *mao; ID *id; int a; - + /* XXX check object pointers */ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { BKE_object_relink(ob); } CTX_DATA_END; - + /* materials */ if (dupflag & USER_DUP_MAT) { mao = bmain->mat.first; while (mao) { if (mao->id.newid) { - ma = (Material *)mao->id.newid; - + if (dupflag & USER_DUP_TEX) { for (a = 0; a < MAX_MTEX; a++) { if (ma->mtex[a]) { id = (ID *)ma->mtex[a]->tex; if (id) { ID_NEW_US(ma->mtex[a]->tex) - else ma->mtex[a]->tex = BKE_texture_copy(ma->mtex[a]->tex); + else + ma->mtex[a]->tex = BKE_texture_copy(ma->mtex[a]->tex); id->us--; } } @@ -1025,7 +1035,8 @@ static void copy_object_set_idnew(bContext *C, int dupflag) id = (ID *)ma->ipo; if (id) { ID_NEW_US(ma->ipo) - else ma->ipo = copy_ipo(ma->ipo); + else + ma->ipo = copy_ipo(ma->ipo); id->us--; } #endif // XXX old animation system @@ -1033,7 +1044,7 @@ static void copy_object_set_idnew(bContext *C, int dupflag) mao = mao->id.next; } } - + #if 0 // XXX old animation system /* lamps */ if (dupflag & USER_DUP_IPO) { @@ -1044,14 +1055,15 @@ static void copy_object_set_idnew(bContext *C, int dupflag) id = (ID *)lan->ipo; if (id) { ID_NEW_US(lan->ipo) - else lan->ipo = copy_ipo(lan->ipo); + else + lan->ipo = copy_ipo(lan->ipo); id->us--; } } la = la->id.next; } } - + /* ipos */ ipo = bmain->ipo.first; while (ipo) { @@ -1067,9 +1079,9 @@ static void copy_object_set_idnew(bContext *C, int dupflag) ipo = ipo->id.next; } #endif // XXX old animation system - + set_sca_new_poins(); - + clear_id_newpoins(); } @@ -1082,17 +1094,17 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, ListBase *lb; DupliObject *dob; GHash *dupli_gh = NULL, *parent_gh = NULL; - + if (!(base->object->transflag & OB_DUPLI)) return; - - lb = object_duplilist(scene, base->object); + + lb = object_duplilist(scene, base->object, FALSE); if (use_hierarchy || use_base_parent) { dupli_gh = BLI_ghash_ptr_new("make_object_duplilist_real dupli_gh"); parent_gh = BLI_ghash_pair_new("make_object_duplilist_real parent_gh"); } - + for (dob = lb->first; dob; dob = dob->next) { Base *basen; Object *ob = BKE_object_copy(dob->ob); @@ -1100,24 +1112,24 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, * should be implemented better... */ if (ob->mat == NULL) ob->totcol = 0; - + basen = MEM_dupallocN(base); basen->flag &= ~(OB_FROMDUPLI | OB_FROMGROUP); ob->flag = basen->flag; basen->lay = base->lay; BLI_addhead(&scene->base, basen); /* addhead: othwise eternal loop */ basen->object = ob; - + /* make sure apply works */ - BKE_free_animdata(&ob->id); + BKE_free_animdata(&ob->id); ob->adt = NULL; - + ob->parent = NULL; ob->constraints.first = ob->constraints.last = NULL; ob->disp.first = ob->disp.last = NULL; - ob->transflag &= ~OB_DUPLI; + ob->transflag &= ~OB_DUPLI; ob->lay = base->lay; - + copy_m4_m4(ob->obmat, dob->mat); BKE_object_apply_mat4(ob, ob->obmat, FALSE, FALSE); @@ -1126,7 +1138,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, if (parent_gh) BLI_ghash_insert(parent_gh, BLI_ghashutil_pairalloc(dob->ob, SET_INT_IN_POINTER(dob->index)), ob); } - + if (use_hierarchy) { for (dob = lb->first; dob; dob = dob->next) { /* original parents */ @@ -1186,8 +1198,6 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, invert_m4_m4(ob_dst->parentinv, dob->mat); BKE_object_apply_mat4(ob_dst, dob->mat, FALSE, TRUE); DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB); - - } } @@ -1197,9 +1207,9 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, BLI_ghash_free(parent_gh, BLI_ghashutil_pairfree, NULL); copy_object_set_idnew(C, 0); - + free_object_duplilist(lb); - + base->object->transflag &= ~OB_DUPLI; } @@ -1210,9 +1220,9 @@ static int object_duplicates_make_real_exec(bContext *C, wmOperator *op) const short use_base_parent = RNA_boolean_get(op->ptr, "use_base_parent"); const short use_hierarchy = RNA_boolean_get(op->ptr, "use_hierarchy"); - + clear_id_newpoins(); - + CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { make_object_duplilist_real(C, scene, base, use_base_parent, use_hierarchy); @@ -1226,23 +1236,22 @@ static int object_duplicates_make_real_exec(bContext *C, wmOperator *op) DAG_ids_flush_update(bmain, 0); WM_event_add_notifier(C, NC_SCENE, scene); WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL); - + return OPERATOR_FINISHED; } void OBJECT_OT_duplicates_make_real(wmOperatorType *ot) { - /* identifiers */ ot->name = "Make Duplicates Real"; ot->description = "Make dupli objects attached to this object real"; ot->idname = "OBJECT_OT_duplicates_make_real"; - + /* api callbacks */ ot->exec = object_duplicates_make_real_exec; - + ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1398,7 +1407,7 @@ static int convert_exec(bContext *C, wmOperator *op) * cases this doesnt give correct results (when MDEF is used for eg) */ dm = mesh_get_derived_final(scene, newob, CD_MASK_MESH); - /* dm= mesh_create_derived_no_deform(ob1, NULL); this was called original (instead of get_derived). man o man why! (ton) */ + // dm = mesh_create_derived_no_deform(ob1, NULL); /* this was called original (instead of get_derived). man o man why! (ton) */ DM_to_mesh(dm, newob->data, newob); @@ -1564,7 +1573,7 @@ static int convert_exec(bContext *C, wmOperator *op) /* delete original if needed */ if (basedel) { if (!keep_original) - ED_base_object_free_and_unlink(bmain, scene, basedel); + ED_base_object_free_and_unlink(bmain, scene, basedel); basedel = NULL; } @@ -1616,12 +1625,12 @@ void OBJECT_OT_convert(wmOperatorType *ot) ot->name = "Convert to"; ot->description = "Convert selected objects to another type"; ot->idname = "OBJECT_OT_convert"; - + /* api callbacks */ ot->invoke = WM_menu_invoke; ot->exec = convert_exec; ot->poll = convert_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1655,12 +1664,12 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base else { obn = BKE_object_copy(ob); obn->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; - + basen = MEM_mallocN(sizeof(Base), "duplibase"); *basen = *base; BLI_addhead(&scene->base, basen); /* addhead: prevent eternal loop */ basen->object = obn; - + if (basen->flag & OB_FROMGROUP) { Group *group; for (group = bmain->group.first; group; group = group->id.next) { @@ -1668,20 +1677,21 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base add_to_group(group, obn, scene, basen); } } - + /* duplicates using userflags */ if (dupflag & USER_DUP_ACT) { BKE_copy_animdata_id_action(&obn->id); } - + if (dupflag & USER_DUP_MAT) { for (a = 0; a < obn->totcol; a++) { id = (ID *)obn->mat[a]; if (id) { ID_NEW_US(obn->mat[a]) - else obn->mat[a] = BKE_material_copy(obn->mat[a]); + else + obn->mat[a] = BKE_material_copy(obn->mat[a]); id->us--; - + if (dupflag & USER_DUP_ACT) { BKE_copy_animdata_id_action(&obn->mat[a]->id); } @@ -1694,8 +1704,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base id = (ID *) psys->part; if (id) { ID_NEW_US(psys->part) - else psys->part = BKE_particlesettings_copy(psys->part); - + else + psys->part = BKE_particlesettings_copy(psys->part); + if (dupflag & USER_DUP_ACT) { BKE_copy_animdata_id_action(&psys->part->id); } @@ -1704,21 +1715,19 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base } } } - + id = obn->data; didit = 0; - + switch (obn->type) { case OB_MESH: if (dupflag & USER_DUP_MESH) { ID_NEW_US2(obn->data) else { obn->data = BKE_mesh_copy(obn->data); - if (obn->fluidsimSettings) { obn->fluidsimSettings->orgMesh = (Mesh *)obn->data; } - didit = 1; } id->us--; @@ -1774,11 +1783,10 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base id->us--; } break; - case OB_ARMATURE: obn->recalc |= OB_RECALC_DATA; - if (obn->pose) obn->pose->flag |= POSE_RECALC; - + if (obn->pose) + obn->pose->flag |= POSE_RECALC; if (dupflag & USER_DUP_ARM) { ID_NEW_US2(obn->data) else { @@ -1788,9 +1796,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base } id->us--; } - break; - case OB_LATTICE: if (dupflag != 0) { ID_NEW_US2(obn->data) @@ -1821,13 +1827,12 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base id->us--; } break; - } /* check if obdata is copied */ if (didit) { - Key *key = ob_get_key(obn); - + Key *key = BKE_key_from_object(obn); + if (dupflag & USER_DUP_ACT) { bActuator *act; @@ -1846,7 +1851,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base } } } - + if (dupflag & USER_DUP_MAT) { matarar = give_matarar(obn); if (matarar) { @@ -1854,8 +1859,8 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base id = (ID *)(*matarar)[a]; if (id) { ID_NEW_US((*matarar)[a]) - else (*matarar)[a] = BKE_material_copy((*matarar)[a]); - + else + (*matarar)[a] = BKE_material_copy((*matarar)[a]); id->us--; } } @@ -1906,14 +1911,14 @@ static int duplicate_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); int linked = RNA_boolean_get(op->ptr, "linked"); int dupflag = (linked) ? 0 : U.dupflag; - + clear_id_newpoins(); clear_sca_new_poins(); /* sensor/contr/act */ - + CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { Base *basen = object_add_duplicate_internal(bmain, scene, base, dupflag); - + /* note that this is safe to do with this context iterator, * the list is made in advance */ ED_base_object_select(base, BA_DESELECT); @@ -1945,19 +1950,19 @@ static int duplicate_exec(bContext *C, wmOperator *op) void OBJECT_OT_duplicate(wmOperatorType *ot) { PropertyRNA *prop; - + /* identifiers */ ot->name = "Duplicate Objects"; ot->description = "Duplicate selected objects"; ot->idname = "OBJECT_OT_duplicate"; - + /* api callbacks */ ot->exec = duplicate_exec; ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* to give to transform */ RNA_def_boolean(ot->srna, "linked", 0, "Linked", "Duplicate object but not object data, linking to the original data"); prop = RNA_def_enum(ot->srna, "mode", transform_mode_types, TFM_TRANSLATION, "Mode", ""); @@ -1966,7 +1971,6 @@ void OBJECT_OT_duplicate(wmOperatorType *ot) /* **************** add named object, for dragdrop ************* */ - static int add_named_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -2021,45 +2025,43 @@ void OBJECT_OT_add_named(wmOperatorType *ot) ot->name = "Add Named Object"; ot->description = "Add named object"; ot->idname = "OBJECT_OT_add_named"; - + /* api callbacks */ ot->exec = add_named_exec; ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + RNA_def_boolean(ot->srna, "linked", 0, "Linked", "Duplicate object but not object data, linking to the original data"); RNA_def_string(ot->srna, "name", "Cube", MAX_ID_NAME - 2, "Name", "Object name to add"); } - - /**************************** Join *************************/ + static int join_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - + if (!ob || ob->id.lib) return 0; - + if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE)) return ED_operator_screenactive(C); else return 0; } - static int join_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); if (scene->obedit) { - BKE_report(op->reports, RPT_ERROR, "This data does not support joining in editmode"); + BKE_report(op->reports, RPT_ERROR, "This data does not support joining in edit mode"); return OPERATOR_CANCELLED; } else if (BKE_object_obdata_is_libdata(ob)) { - BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata"); + BKE_report(op->reports, RPT_ERROR, "Cannot edit external libdata"); return OPERATOR_CANCELLED; } @@ -2069,7 +2071,7 @@ static int join_exec(bContext *C, wmOperator *op) return join_curve_exec(C, op); else if (ob->type == OB_ARMATURE) return join_armature_exec(C, op); - + return OPERATOR_CANCELLED; } @@ -2079,22 +2081,23 @@ void OBJECT_OT_join(wmOperatorType *ot) ot->name = "Join"; ot->description = "Join selected objects into active object"; ot->idname = "OBJECT_OT_join"; - + /* api callbacks */ ot->exec = join_exec; ot->poll = join_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /**************************** Join as Shape Key*************************/ + static int join_shapes_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - + if (!ob || ob->id.lib) return 0; - + /* only meshes supported at the moment */ if (ob->type == OB_MESH) return ED_operator_screenactive(C); @@ -2106,19 +2109,19 @@ static int join_shapes_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); - + if (scene->obedit) { - BKE_report(op->reports, RPT_ERROR, "This data does not support joining in editmode"); + BKE_report(op->reports, RPT_ERROR, "This data does not support joining in edit mode"); return OPERATOR_CANCELLED; } else if (BKE_object_obdata_is_libdata(ob)) { - BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata"); + BKE_report(op->reports, RPT_ERROR, "Cannot edit external libdata"); return OPERATOR_CANCELLED; } - + if (ob->type == OB_MESH) return join_mesh_shapes_exec(C, op); - + return OPERATOR_CANCELLED; } @@ -2128,11 +2131,11 @@ void OBJECT_OT_join_shapes(wmOperatorType *ot) ot->name = "Join as Shapes"; ot->description = "Merge selected objects to shapes of active object"; ot->idname = "OBJECT_OT_join_shapes"; - + /* api callbacks */ ot->exec = join_shapes_exec; ot->poll = join_shapes_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index f03cb312e3e..ee3c66b6eac 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -150,11 +150,13 @@ typedef struct { float height_min, height_max; Image *ima; DerivedMesh *ssdm; - const int *origindex; + const int *orig_index_mf_to_mpoly; + const int *orig_index_mp_to_orig; } MHeightBakeData; typedef struct { - const int *origindex; + const int *orig_index_mf_to_mpoly; + const int *orig_index_mp_to_orig; } MNormalBakeData; static void multiresbake_get_normal(const MResolvePixelData *data, float norm[], const int face_num, const int vert_index) @@ -508,7 +510,9 @@ static void interp_bilinear_grid(CCGKey *key, CCGElem *grid, float crn_x, float interp_bilinear_quad_data(data, u, v, res); } -static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm, const int *origindex, const int lvl, const int face_index, const float u, const float v, float co[3], float n[3]) +static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm, + const int *index_mf_to_mpoly, const int *index_mp_to_orig, + const int lvl, const int face_index, const float u, const float v, float co[3], float n[3]) { MFace mface; CCGElem **grid_data; @@ -532,7 +536,7 @@ static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm, const int *orig } else { int side = (1 << (lvl - 1)) + 1; - int grid_index = origindex[face_index]; + int grid_index = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, face_index); int loc_offs = face_index % (1 << (2 * lvl)); int cell_index = loc_offs % ((side - 1) * (side - 1)); int cell_side = (grid_size - 1) / (side - 1); @@ -628,7 +632,8 @@ static void *init_heights_data(MultiresBakeRender *bkr, Image *ima) } } - height_data->origindex = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX); + height_data->orig_index_mf_to_mpoly = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX); + height_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX); return (void *)height_data; } @@ -640,7 +645,8 @@ static void *init_normal_data(MultiresBakeRender *bkr, Image *UNUSED(ima)) normal_data = MEM_callocN(sizeof(MNormalBakeData), "MultiresBake normalData"); - normal_data->origindex = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX); + normal_data->orig_index_mf_to_mpoly = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX); + normal_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX); return (void *)normal_data; } @@ -735,10 +741,14 @@ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, CLAMP(uv[0], 0.0f, 1.0f); CLAMP(uv[1], 0.0f, 1.0f); - get_ccgdm_data(lores_dm, hires_dm, height_data->origindex, lvl, face_index, uv[0], uv[1], p1, 0); + get_ccgdm_data(lores_dm, hires_dm, + height_data->orig_index_mf_to_mpoly, height_data->orig_index_mf_to_mpoly, + lvl, face_index, uv[0], uv[1], p1, 0); if (height_data->ssdm) { - get_ccgdm_data(lores_dm, height_data->ssdm, height_data->origindex, 0, face_index, uv[0], uv[1], p0, n); + get_ccgdm_data(lores_dm, height_data->ssdm, + height_data->orig_index_mf_to_mpoly, height_data->orig_index_mf_to_mpoly, + 0, face_index, uv[0], uv[1], p0, n); } else { lores_dm->getTessFace(lores_dm, face_index, &mface); @@ -808,7 +818,9 @@ static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, CLAMP(uv[0], 0.0f, 1.0f); CLAMP(uv[1], 0.0f, 1.0f); - get_ccgdm_data(lores_dm, hires_dm, normal_data->origindex, lvl, face_index, uv[0], uv[1], NULL, n); + get_ccgdm_data(lores_dm, hires_dm, + normal_data->orig_index_mf_to_mpoly, normal_data->orig_index_mp_to_orig, + lvl, face_index, uv[0], uv[1], NULL, n); mul_v3_m3v3(vec, tangmat, n); normalize_v3(vec); @@ -900,7 +912,7 @@ static void finish_images(MultiresBakeRender *bkr) RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, bkr->bake_filter); - ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID;; + ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID; if (ibuf->rect_float) ibuf->userflags |= IB_RECT_INVALID; @@ -937,7 +949,7 @@ static int multiresbake_check(bContext *C, wmOperator *op) ob = base->object; if (ob->type != OB_MESH) { - BKE_report(op->reports, RPT_ERROR, "Basking of multires data only works with active object which is a mesh"); + BKE_report(op->reports, RPT_ERROR, "Baking of multires data only works with an active mesh object"); ok = 0; break; @@ -966,6 +978,12 @@ static int multiresbake_check(bContext *C, wmOperator *op) break; } + if (mmd->lvl == 0) { + BKE_report(op->reports, RPT_ERROR, "Multires data baking is not supported for preview subdivision level 0"); + + break; + } + if (!me->mtpoly) { BKE_report(op->reports, RPT_ERROR, "Mesh should be unwrapped before multires data baking"); @@ -985,7 +1003,7 @@ static int multiresbake_check(bContext *C, wmOperator *op) ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); if (!ibuf) { - BKE_report(op->reports, RPT_ERROR, "Baking should happend to image with image buffer"); + BKE_report(op->reports, RPT_ERROR, "Baking should happen to image with image buffer"); ok = 0; } @@ -1030,8 +1048,7 @@ static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *l tmp_mmd.lvl = *lvl; tmp_mmd.sculptlvl = *lvl; - dm = multires_make_derived_from_derived(cddm, &tmp_mmd, ob, - MULTIRES_USE_LOCAL_MMD); + dm = multires_make_derived_from_derived(cddm, &tmp_mmd, ob, 0); cddm->release(cddm); } @@ -1051,8 +1068,7 @@ static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *l tmp_mmd.lvl = mmd->totlvl; tmp_mmd.sculptlvl = mmd->totlvl; - dm = multires_make_derived_from_derived(cddm, &tmp_mmd, ob, - MULTIRES_USE_LOCAL_MMD); + dm = multires_make_derived_from_derived(cddm, &tmp_mmd, ob, 0); cddm->release(cddm); return dm; @@ -1329,11 +1345,12 @@ static int test_bake_internal(bContext *C, ReportList *reports) static void init_bake_internal(BakeRender *bkr, bContext *C) { Scene *scene = CTX_data_scene(C); + bScreen *sc = CTX_wm_screen(C); /* get editmode results */ ED_object_exit_editmode(C, 0); /* 0 = does not exit editmode */ - bkr->sa = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_IMAGE, 10); /* can be NULL */ + bkr->sa = sc ? BKE_screen_find_big_area(sc, SPACE_IMAGE, 10) : NULL; /* can be NULL */ bkr->main = CTX_data_main(C); bkr->scene = scene; bkr->actob = (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT : NULL; @@ -1365,20 +1382,23 @@ static void finish_bake_internal(BakeRender *bkr) if (bkr->prev_r_raytrace == 0) bkr->scene->r.mode &= ~R_RAYTRACE; - /* force OpenGL reload and mipmap recalc */ for (ima = G.main->image.first; ima; ima = ima->id.next) { ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); - if (bkr->result == BAKE_RESULT_OK) { - if (ima->ok == IMA_OK_LOADED) { - if (ibuf) { - if (ibuf->userflags & IB_BITMAPDIRTY) { - ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; - GPU_free_image(ima); - imb_freemipmapImBuf(ibuf); - } + /* some of the images could have been changed during bake, + * so recreate mipmaps regardless bake result status + */ + if (ima->ok == IMA_OK_LOADED) { + if (ibuf) { + if (ibuf->userflags & IB_BITMAPDIRTY) { + GPU_free_image(ima); + imb_freemipmapImBuf(ibuf); } + + /* invalidate display buffers for changed images */ + if (ibuf->userflags & IB_BITMAPDIRTY) + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; } } diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 1ef7c12b409..f78e1203bc4 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -40,6 +40,7 @@ #include "BLI_dynstr.h" #include "BLI_utildefines.h" +#include "DNA_anim_types.h" #include "DNA_constraint_types.h" #include "DNA_curve_types.h" #include "DNA_scene_types.h" @@ -51,6 +52,7 @@ #include "BKE_constraint.h" #include "BKE_context.h" #include "BKE_depsgraph.h" +#include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_object.h" @@ -71,6 +73,7 @@ #include "ED_object.h" #include "ED_armature.h" +#include "ED_keyframing.h" #include "ED_screen.h" #include "UI_interface.h" @@ -491,9 +494,9 @@ static void test_constraints(Object *owner, bPoseChannel *pchan) /* auto-set 'Path' setting on curve so this works */ cu->flag |= CU_PATH; } - } + } } - } + } /* free any temporary targets */ if (cti->flush_constraint_targets) @@ -590,7 +593,7 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) { list = &ob->constraints; - } + } else if (owner == EDIT_CONSTRAINT_OWNER_BONE) { bPoseChannel *pchan = BKE_pose_channel_active(ob); if (pchan) @@ -655,12 +658,15 @@ void CONSTRAINT_OT_stretchto_reset(wmOperatorType *ot) ot->idname = "CONSTRAINT_OT_stretchto_reset"; ot->description = "Reset original length of bone for Stretch To Constraint"; - ot->exec = stretchto_reset_exec; + /* callbacks */ ot->invoke = stretchto_reset_invoke; + ot->exec = stretchto_reset_exec; ot->poll = edit_constraint_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ edit_constraint_properties(ot); } @@ -698,12 +704,15 @@ void CONSTRAINT_OT_limitdistance_reset(wmOperatorType *ot) ot->idname = "CONSTRAINT_OT_limitdistance_reset"; ot->description = "Reset limiting distance for Limit Distance Constraint"; - ot->exec = limitdistance_reset_exec; + /* callbacks */ ot->invoke = limitdistance_reset_invoke; + ot->exec = limitdistance_reset_exec; ot->poll = edit_constraint_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ edit_constraint_properties(ot); } @@ -798,7 +807,7 @@ static int childof_set_inverse_exec(bContext *C, wmOperator *op) /* despite 3 layers of checks, we may still not be able to find a constraint */ if (data == NULL) { printf("DEBUG: Child-Of Set Inverse - object = '%s'\n", (ob) ? ob->id.name + 2 : ""); - BKE_report(op->reports, RPT_ERROR, "Couldn't find constraint data for Child-Of Set Inverse"); + BKE_report(op->reports, RPT_ERROR, "Could not find constraint data for Child-Of Set Inverse"); return OPERATOR_CANCELLED; } @@ -824,12 +833,15 @@ void CONSTRAINT_OT_childof_set_inverse(wmOperatorType *ot) ot->idname = "CONSTRAINT_OT_childof_set_inverse"; ot->description = "Set inverse correction for ChildOf constraint"; - ot->exec = childof_set_inverse_exec; + /* callbacks */ ot->invoke = childof_set_inverse_invoke; + ot->exec = childof_set_inverse_exec; ot->poll = edit_constraint_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ edit_constraint_properties(ot); } @@ -841,7 +853,7 @@ static int childof_clear_inverse_exec(bContext *C, wmOperator *op) bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL; if (data == NULL) { - BKE_report(op->reports, RPT_ERROR, "Childof constraint not found"); + BKE_report(op->reports, RPT_ERROR, "Child Of constraint not found"); return OPERATOR_CANCELLED; } @@ -868,15 +880,142 @@ void CONSTRAINT_OT_childof_clear_inverse(wmOperatorType *ot) ot->idname = "CONSTRAINT_OT_childof_clear_inverse"; ot->description = "Clear inverse correction for ChildOf constraint"; - ot->exec = childof_clear_inverse_exec; + /* callbacks */ ot->invoke = childof_clear_inverse_invoke; + ot->exec = childof_clear_inverse_exec; ot->poll = edit_constraint_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ edit_constraint_properties(ot); } +/* --------------- Follow Path Constraint ------------------ */ + +static int followpath_path_animate_exec(bContext *C, wmOperator *op) +{ + Object *ob = ED_object_active_context(C); + bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_FOLLOWPATH); + bFollowPathConstraint *data = (con) ? (bFollowPathConstraint *)con->data : NULL; + + bAction *act = NULL; + FCurve *fcu = NULL; + int sfra = RNA_int_get(op->ptr, "frame_start"); + int len = RNA_int_get(op->ptr, "length"); + float standardRange = 1.0; + + /* nearly impossible sanity check */ + if (data == NULL) { + BKE_report(op->reports, RPT_ERROR, "Follow Path constraint not found"); + return OPERATOR_CANCELLED; + } + + /* add F-Curve as appropriate */ + if (data->tar) { + Curve *cu = (Curve *)data->tar->data; + + if ( ELEM(NULL, cu->adt, cu->adt->action) || + (list_find_fcurve(&cu->adt->action->curves, "eval_time", 0) == NULL)) + { + /* create F-Curve for path animation */ + act = verify_adt_action(&cu->id, 1); + fcu = verify_fcurve(act, NULL, NULL, "eval_time", 0, 1); + + /* standard vertical range - 1:1 = 100 frames */ + standardRange = 100.0f; + } + else { + /* path anim exists already - abort for now as this may well be what was intended */ + BKE_report(op->reports, RPT_WARNING, "Path is already animated"); + return OPERATOR_CANCELLED; + } + } + else { + /* animate constraint's "fixed offset" */ + PointerRNA ptr; + PropertyRNA *prop; + char *path; + + /* get RNA pointer to constraint's "offset_factor" property - to build RNA path */ + RNA_pointer_create(&ob->id, &RNA_FollowPathConstraint, con, &ptr); + prop = RNA_struct_find_property(&ptr, "offset_factor"); + + path = RNA_path_from_ID_to_property(&ptr, prop); + + /* create F-Curve for constraint */ + act = verify_adt_action(&ob->id, 1); + fcu = verify_fcurve(act, NULL, NULL, path, 0, 1); + + /* standard vertical range - 0.0 to 1.0 */ + standardRange = 1.0f; + + /* enable "Use Fixed Position" so that animating this has effect */ + data->followflag |= FOLLOWPATH_STATIC; + + /* path needs to be freed */ + if (path) + MEM_freeN(path); + } + + /* setup dummy 'generator' modifier here to get 1-1 correspondence still working + * and define basic slope of this curve based on the properties + */ + if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first) { + FModifier *fcm = add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR); + FMod_Generator *gen = fcm->data; + + /* Assume that we have the following equation: + * y = Ax + B + * 1 0 <-- coefficients array indices + */ + float A = standardRange / (float)(len); + float B = (float)(-sfra) * A; + + gen->coefficients[1] = A; + gen->coefficients[0] = B; + } + + /* updates... */ + WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob); + return OPERATOR_FINISHED; +} + +static int followpath_path_animate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +{ + /* hook up invoke properties for figuring out which constraint we're dealing with */ + if (edit_constraint_invoke_properties(C, op)) { + return followpath_path_animate_exec(C, op); + } + else { + return OPERATOR_CANCELLED; + } +} + +void CONSTRAINT_OT_followpath_path_animate(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Auto Animate Path"; + ot->idname = "CONSTRAINT_OT_followpath_path_animate"; + ot->description = "Add default animation for path used by constraint if it isn't animated already"; + + /* callbacks */ + ot->invoke = followpath_path_animate_invoke; + ot->exec = followpath_path_animate_exec; + ot->poll = edit_constraint_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* props */ + edit_constraint_properties(ot); + RNA_def_int(ot->srna, "frame_start", 1, MINAFRAME, MAXFRAME, "Start Frame", + "First frame of path animation", MINAFRAME, MAXFRAME); + RNA_def_int(ot->srna, "length", 100, 0, MAXFRAME, "Length", + "Number of frames that path animation should take", 0, MAXFRAME); +} + /* ------------- Object Solver Constraint ------------------ */ static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op) @@ -889,7 +1028,7 @@ static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op) /* despite 3 layers of checks, we may still not be able to find a constraint */ if (data == NULL) { printf("DEBUG: Child-Of Set Inverse - object = '%s'\n", (ob) ? ob->id.name + 2 : ""); - BKE_report(op->reports, RPT_ERROR, "Couldn't find constraint data for Child-Of Set Inverse"); + BKE_report(op->reports, RPT_ERROR, "Could not find constraint data for Child-Of Set Inverse"); return OPERATOR_CANCELLED; } @@ -914,13 +1053,16 @@ void CONSTRAINT_OT_objectsolver_set_inverse(wmOperatorType *ot) ot->name = "Set Inverse"; ot->idname = "CONSTRAINT_OT_objectsolver_set_inverse"; ot->description = "Set inverse correction for ObjectSolver constraint"; - - ot->exec = objectsolver_set_inverse_exec; + + /* callbacks */ ot->invoke = objectsolver_set_inverse_invoke; + ot->exec = objectsolver_set_inverse_exec; ot->poll = edit_constraint_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ edit_constraint_properties(ot); } @@ -931,7 +1073,7 @@ static int objectsolver_clear_inverse_exec(bContext *C, wmOperator *op) bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL; if (data == NULL) { - BKE_report(op->reports, RPT_ERROR, "Childof constraint not found"); + BKE_report(op->reports, RPT_ERROR, "Child Of constraint not found"); return OPERATOR_CANCELLED; } @@ -957,13 +1099,16 @@ void CONSTRAINT_OT_objectsolver_clear_inverse(wmOperatorType *ot) ot->name = "Clear Inverse"; ot->idname = "CONSTRAINT_OT_objectsolver_clear_inverse"; ot->description = "Clear inverse correction for ObjectSolver constraint"; - - ot->exec = objectsolver_clear_inverse_exec; + + /* callbacks */ ot->invoke = objectsolver_clear_inverse_invoke; + ot->exec = objectsolver_clear_inverse_exec; ot->poll = edit_constraint_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ edit_constraint_properties(ot); } @@ -983,13 +1128,14 @@ void ED_object_constraint_set_active(Object *ob, bConstraint *con) void ED_object_constraint_update(Object *ob) { - if (ob->pose) BKE_pose_update_constraint_flags(ob->pose); object_test_constraints(ob); - if (ob->type == OB_ARMATURE) DAG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB); - else DAG_id_tag_update(&ob->id, OB_RECALC_OB); + if (ob->type == OB_ARMATURE) + DAG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB); + else + DAG_id_tag_update(&ob->id, OB_RECALC_OB); } void ED_object_constraint_dependency_update(Main *bmain, Scene *scene, Object *ob) @@ -1006,6 +1152,7 @@ static int constraint_poll(bContext *C) return (ptr.id.data && ptr.data); } + static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint); @@ -1020,12 +1167,12 @@ static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op)) constraints_set_active(lb, NULL); ED_object_constraint_update(ob); /* needed to set the flags on posebones correctly */ - + /* ITASC needs to be rebuilt once a constraint is removed [#26920] */ if (is_ik) { BIK_clear_data(ob->pose); } - + /* notifiers */ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob); @@ -1052,6 +1199,7 @@ void CONSTRAINT_OT_delete(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } + static int constraint_move_down_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_active_context(C); @@ -1081,7 +1229,6 @@ static int constraint_move_down_invoke(bContext *C, wmOperator *op, wmEvent *UNU return OPERATOR_CANCELLED; } - void CONSTRAINT_OT_move_down(wmOperatorType *ot) { /* identifiers */ @@ -1090,12 +1237,14 @@ void CONSTRAINT_OT_move_down(wmOperatorType *ot) ot->description = "Move constraint down in constraint stack"; /* callbacks */ - ot->exec = constraint_move_down_exec; ot->invoke = constraint_move_down_invoke; + ot->exec = constraint_move_down_exec; ot->poll = edit_constraint_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ edit_constraint_properties(ot); } @@ -1479,15 +1628,15 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase return OPERATOR_CANCELLED; } if ((type == CONSTRAINT_TYPE_RIGIDBODYJOINT) && (list != &ob->constraints)) { - BKE_report(op->reports, RPT_ERROR, "Rigid Body Joint Constraint can only be added to Objects"); + BKE_report(op->reports, RPT_ERROR, "Rigid Body Joint constraint can only be added to objects"); return OPERATOR_CANCELLED; } if ((type == CONSTRAINT_TYPE_KINEMATIC) && ((!pchan) || (list != &pchan->constraints))) { - BKE_report(op->reports, RPT_ERROR, "IK Constraint can only be added to Bones"); + BKE_report(op->reports, RPT_ERROR, "IK constraint can only be added to bones"); return OPERATOR_CANCELLED; } if ((type == CONSTRAINT_TYPE_SPLINEIK) && ((!pchan) || (list != &pchan->constraints))) { - BKE_report(op->reports, RPT_ERROR, "Spline IK Constraint can only be added to Bones"); + BKE_report(op->reports, RPT_ERROR, "Spline IK constraint can only be added to bones"); return OPERATOR_CANCELLED; } @@ -1707,7 +1856,7 @@ static int pose_ik_add_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt)) /* must have active bone */ if (ELEM(NULL, ob, pchan)) { - BKE_report(op->reports, RPT_ERROR, "Must have active bone to add IK Constraint to"); + BKE_report(op->reports, RPT_ERROR, "Must have an active bone to add IK constraint to"); return OPERATOR_CANCELLED; } @@ -1716,7 +1865,7 @@ static int pose_ik_add_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt)) if (con->type == CONSTRAINT_TYPE_KINEMATIC) break; } if (con) { - BKE_report(op->reports, RPT_ERROR, "Bone already has IK Constraint"); + BKE_report(op->reports, RPT_ERROR, "Bone already has an IK constraint"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index aa885320b37..c0c2195592b 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -201,7 +201,7 @@ static int object_hide_view_set_exec(bContext *C, wmOperator *op) ED_base_object_activate(C, NULL); } } - } + } } CTX_DATA_END; @@ -649,11 +649,11 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob) for (base = FIRSTBASE; base; base = base->next) { if ((base != BASACT) && (TESTBASELIB(v3d, base))) { if (nr == 1) { /* replace */ - copy_properties(&base->object->prop, &ob->prop); + BKE_bproperty_copy_list(&base->object->prop, &ob->prop); } else { for (prop = ob->prop.first; prop; prop = prop->next) { - set_ob_property(base->object, prop); + BKE_bproperty_object_set(base->object, prop); } } } @@ -665,7 +665,7 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob) if (prop) { for (base = FIRSTBASE; base; base = base->next) { if ((base != BASACT) && (TESTBASELIB(v3d, base))) { - set_ob_property(base->object, prop); + BKE_bproperty_object_set(base->object, prop); } } } @@ -684,7 +684,7 @@ static void copymenu_logicbricks(Scene *scene, View3D *v3d, Object *ob) if (TESTBASELIB(v3d, base)) { /* first: free all logic */ - free_sensors(&base->object->sensors); + free_sensors(&base->object->sensors); unlink_controllers(&base->object->controllers); free_controllers(&base->object->controllers); unlink_actuators(&base->object->actuators); @@ -885,7 +885,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) id_us_plus((ID *)cu1->vfonti); if (cu1->vfontbi) cu1->vfontbi->id.us--; cu1->vfontbi = cu->vfontbi; - id_us_plus((ID *)cu1->vfontbi); + id_us_plus((ID *)cu1->vfontbi); BKE_vfont_to_curve(bmain, scene, base->object, 0); /* needed? */ @@ -957,7 +957,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) base->object->softflag = ob->softflag; if (base->object->soft) sbFree(base->object->soft); - base->object->soft = copy_softbody(ob->soft); + base->object->soft = copy_softbody(ob->soft, FALSE); if (!modifiers_findByType(base->object, eModifierType_Softbody)) { BLI_addhead(&base->object->modifiers, modifier_new(eModifierType_Softbody)); @@ -988,7 +988,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) cu1->flag |= CU_UV_ORCO; else cu1->flag &= ~CU_UV_ORCO; - } + } } else if (event == 29) { /* protected bits */ base->object->protectflag = ob->protectflag; @@ -1017,9 +1017,9 @@ static void UNUSED_FUNCTION(copy_attr_menu) (Main * bmain, Scene * scene, View3D if (!(ob = OBACT)) return; - if (scene->obedit) { // XXX get from context -// if (ob->type == OB_MESH) -// XXX mesh_copy_menu(); + if (scene->obedit) { /* XXX get from context */ +/* if (ob->type == OB_MESH) */ +/* XXX mesh_copy_menu(); */ return; } @@ -1030,34 +1030,34 @@ static void UNUSED_FUNCTION(copy_attr_menu) (Main * bmain, Scene * scene, View3D */ strcpy(str, - "Copy Attributes %t|Location%x1|Rotation%x2|Size%x3|Draw Options%x4|" - "Time Offset%x5|Dupli%x6|Object Color%x31|%l|Mass%x7|Damping%x8|All Physical Attributes%x11|Properties%x9|" - "Logic Bricks%x10|Protected Transform%x29|%l"); + "Copy Attributes %t|Location %x1|Rotation %x2|Size %x3|Draw Options %x4|" + "Time Offset %x5|Dupli %x6|Object Color %x31|%l|Mass %x7|Damping %x8|All Physical Attributes %x11|Properties %x9|" + "Logic Bricks %x10|Protected Transform %x29|%l"); - strcat(str, "|Object Constraints%x22"); - strcat(str, "|NLA Strips%x26"); + strcat(str, "|Object Constraints %x22"); + strcat(str, "|NLA Strips %x26"); -// XXX if (OB_TYPE_SUPPORT_MATERIAL(ob->type)) { -// strcat(str, "|Texture Space%x17"); -// } +/* XXX if (OB_TYPE_SUPPORT_MATERIAL(ob->type)) { */ +/* strcat(str, "|Texture Space %x17"); */ +/* } */ - if (ob->type == OB_FONT) strcat(str, "|Font Settings%x18|Bevel Settings%x19"); - if (ob->type == OB_CURVE) strcat(str, "|Bevel Settings%x19|UV Orco%x28"); + if (ob->type == OB_FONT) strcat(str, "|Font Settings %x18|Bevel Settings %x19"); + if (ob->type == OB_CURVE) strcat(str, "|Bevel Settings %x19|UV Orco %x28"); if ((ob->type == OB_FONT) || (ob->type == OB_CURVE)) { - strcat(str, "|Curve Resolution%x25"); + strcat(str, "|Curve Resolution %x25"); } if (ob->type == OB_MESH) { - strcat(str, "|Subsurf Settings%x21|AutoSmooth%x27"); + strcat(str, "|Subsurf Settings %x21|AutoSmooth %x27"); } - if (ob->soft) strcat(str, "|Soft Body Settings%x23"); + if (ob->soft) strcat(str, "|Soft Body Settings %x23"); - strcat(str, "|Pass Index%x30"); + strcat(str, "|Pass Index %x30"); if (ob->type == OB_MESH || ob->type == OB_CURVE || ob->type == OB_LATTICE || ob->type == OB_SURF) { - strcat(str, "|Modifiers ...%x24"); + strcat(str, "|Modifiers ... %x24"); } event = pupmenu(str); @@ -1401,7 +1401,7 @@ static void UNUSED_FUNCTION(image_aspect) (Scene * scene, View3D * v3d) else ob->size[1] = ob->size[0] * y / x; done = TRUE; - DAG_id_tag_update(&ob->id, OB_RECALC_OB); + DAG_id_tag_update(&ob->id, OB_RECALC_OB); } } if (done) break; @@ -1585,7 +1585,7 @@ static int game_property_new(bContext *C, wmOperator *op) char name[MAX_NAME]; int type = RNA_enum_get(op->ptr, "type"); - prop = new_property(type); + prop = BKE_bproperty_new(type); BLI_addtail(&ob->prop, prop); RNA_string_get(op->ptr, "name", name); @@ -1593,7 +1593,7 @@ static int game_property_new(bContext *C, wmOperator *op) BLI_strncpy(prop->name, name, sizeof(prop->name)); } - unique_property(NULL, prop, 0); // make_unique_prop_names(prop->name); + BKE_bproperty_unique(NULL, prop, 0); // make_unique_prop_names(prop->name); WM_event_add_notifier(C, NC_LOGIC, NULL); return OPERATOR_FINISHED; @@ -1631,7 +1631,7 @@ static int game_property_remove(bContext *C, wmOperator *op) if (prop) { BLI_remlink(&ob->prop, prop); - free_property(prop); + BKE_bproperty_free(prop); WM_event_add_notifier(C, NC_LOGIC, NULL); return OPERATOR_FINISHED; @@ -1711,7 +1711,7 @@ static int game_property_copy_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects) { if (ob != ob_iter) - set_ob_property(ob_iter, prop); + BKE_bproperty_object_set(ob_iter, prop); } CTX_DATA_END; } } @@ -1721,12 +1721,12 @@ static int game_property_copy_exec(bContext *C, wmOperator *op) { if (ob != ob_iter) { if (type == COPY_PROPERTIES_REPLACE) { - copy_properties(&ob_iter->prop, &ob->prop); + BKE_bproperty_copy_list(&ob_iter->prop, &ob->prop); } else { /* merge - the default when calling with no argument */ for (prop = ob->prop.first; prop; prop = prop->next) { - set_ob_property(ob_iter, prop); + BKE_bproperty_object_set(ob_iter, prop); } } } @@ -1763,7 +1763,7 @@ static int game_property_clear_exec(bContext *C, wmOperator *UNUSED(op)) { CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects) { - free_properties(&ob_iter->prop); + BKE_bproperty_free_list(&ob_iter->prop); } CTX_DATA_END; @@ -1795,7 +1795,7 @@ static int logicbricks_copy_exec(bContext *C, wmOperator *UNUSED(op)) { if (ob != ob_iter) { /* first: free all logic */ - free_sensors(&ob_iter->sensors); + free_sensors(&ob_iter->sensors); unlink_controllers(&ob_iter->controllers); free_controllers(&ob_iter->controllers); unlink_actuators(&ob_iter->actuators); @@ -1864,7 +1864,7 @@ static int game_physics_copy_exec(bContext *C, wmOperator *UNUSED(op)) ob_iter->anisotropicFriction[0] = ob->anisotropicFriction[0]; ob_iter->anisotropicFriction[1] = ob->anisotropicFriction[1]; ob_iter->anisotropicFriction[2] = ob->anisotropicFriction[2]; - ob_iter->collision_boundtype = ob->collision_boundtype; + ob_iter->collision_boundtype = ob->collision_boundtype; ob_iter->margin = ob->margin; ob_iter->bsoft = copy_bulletsoftbody(ob->bsoft); if (ob->restrictflag & OB_RESTRICT_RENDER) diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c index cca37cf3a44..a3bf27a19d6 100644 --- a/source/blender/editors/object/object_group.c +++ b/source/blender/editors/object/object_group.c @@ -195,7 +195,7 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op) } } - if (!ok) BKE_report(op->reports, RPT_ERROR, "Active Object contains no groups"); + if (!ok) BKE_report(op->reports, RPT_ERROR, "Active object contains no groups"); DAG_scene_sort(bmain, scene); WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); @@ -211,7 +211,7 @@ void GROUP_OT_objects_remove_active(wmOperatorType *ot) ot->idname = "GROUP_OT_objects_remove_active"; /* api callbacks */ - ot->exec = objects_remove_active_exec; + ot->exec = objects_remove_active_exec; ot->poll = ED_operator_objectmode; /* flags */ @@ -333,7 +333,7 @@ void GROUP_OT_create(wmOperatorType *ot) ot->idname = "GROUP_OT_create"; /* api callbacks */ - ot->exec = group_create_exec; + ot->exec = group_create_exec; ot->poll = ED_operator_objectmode; /* flags */ diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index a6afe6b2d04..caeff1e82a7 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -442,7 +442,7 @@ static int add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob ok = object_hook_index_array(scene, obedit, &tot, &indexar, name, cent); if (!ok) { - BKE_report(reports, RPT_ERROR, "Requires selected vertices or active Vertex Group"); + BKE_report(reports, RPT_ERROR, "Requires selected vertices or active vertex group"); return FALSE; } @@ -515,12 +515,12 @@ static int object_add_hook_selob_exec(bContext *C, wmOperator *op) CTX_DATA_END; if (!obsel) { - BKE_report(op->reports, RPT_ERROR, "Can't add hook with no other selected objects"); + BKE_report(op->reports, RPT_ERROR, "Cannot add hook with no other selected objects"); return OPERATOR_CANCELLED; } if (use_bone && obsel->type != OB_ARMATURE) { - BKE_report(op->reports, RPT_ERROR, "Can't add hook bone for a non armature object"); + BKE_report(op->reports, RPT_ERROR, "Cannot add hook bone for a non armature object"); return OPERATOR_CANCELLED; } @@ -590,7 +590,7 @@ static int object_hook_remove_exec(bContext *C, wmOperator *op) hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num); if (!hmd) { - BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier"); + BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier"); return OPERATOR_CANCELLED; } @@ -667,13 +667,13 @@ static int object_hook_reset_exec(bContext *C, wmOperator *op) if (ptr.data) { /* if modifier context is available, use that */ ob = ptr.id.data; hmd = ptr.data; - } + } else { /* use the provided property */ ob = CTX_data_edit_object(C); hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num); } if (!ob || !hmd) { - BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier"); + BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier"); return OPERATOR_CANCELLED; } @@ -735,13 +735,13 @@ static int object_hook_recenter_exec(bContext *C, wmOperator *op) if (ptr.data) { /* if modifier context is available, use that */ ob = ptr.id.data; hmd = ptr.data; - } + } else { /* use the provided property */ ob = CTX_data_edit_object(C); hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num); } if (!ob || !hmd) { - BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier"); + BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier"); return OPERATOR_CANCELLED; } @@ -793,13 +793,13 @@ static int object_hook_assign_exec(bContext *C, wmOperator *op) if (ptr.data) { /* if modifier context is available, use that */ ob = ptr.id.data; hmd = ptr.data; - } + } else { /* use the provided property */ ob = CTX_data_edit_object(C); hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num); } if (!ob || !hmd) { - BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier"); + BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier"); return OPERATOR_CANCELLED; } @@ -855,13 +855,13 @@ static int object_hook_select_exec(bContext *C, wmOperator *op) if (ptr.data) { /* if modifier context is available, use that */ ob = ptr.id.data; hmd = ptr.data; - } + } else { /* use the provided property */ ob = CTX_data_edit_object(C); hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num); } if (!ob || !hmd) { - BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier"); + BKE_report(op->reports, RPT_ERROR, "Could not find hook modifier"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index b62ff676066..0be9c92897e 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -112,6 +112,7 @@ void OBJECT_OT_add_named(struct wmOperatorType *ot); void OBJECT_OT_metaball_add(struct wmOperatorType *ot); void OBJECT_OT_text_add(struct wmOperatorType *ot); void OBJECT_OT_armature_add(struct wmOperatorType *ot); +void OBJECT_OT_empty_add(struct wmOperatorType *ot); void OBJECT_OT_lamp_add(struct wmOperatorType *ot); void OBJECT_OT_effector_add(struct wmOperatorType *ot); void OBJECT_OT_camera_add(struct wmOperatorType *ot); @@ -137,6 +138,7 @@ void OBJECT_OT_hook_recenter(struct wmOperatorType *ot); /* object_lattice.c */ void LATTICE_OT_select_all(struct wmOperatorType *ot); void LATTICE_OT_make_regular(struct wmOperatorType *ot); +void LATTICE_OT_flip(struct wmOperatorType *ot); /* object_group.c */ void GROUP_OT_create(struct wmOperatorType *ot); @@ -193,6 +195,7 @@ void CONSTRAINT_OT_childof_set_inverse(struct wmOperatorType *ot); void CONSTRAINT_OT_childof_clear_inverse(struct wmOperatorType *ot); void CONSTRAINT_OT_objectsolver_set_inverse(struct wmOperatorType *ot); void CONSTRAINT_OT_objectsolver_clear_inverse(struct wmOperatorType *ot); +void CONSTRAINT_OT_followpath_path_animate(struct wmOperatorType *ot); /* object_vgroup.c */ void OBJECT_OT_vertex_group_add(struct wmOperatorType *ot); @@ -202,6 +205,7 @@ void OBJECT_OT_vertex_group_remove_from(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_select(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_deselect(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_copy_to_linked(struct wmOperatorType *ot); +void OBJECT_OT_vertex_group_transfer_weight(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_copy_to_selected(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_copy(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_normalize(struct wmOperatorType *ot); @@ -212,6 +216,7 @@ void OBJECT_OT_vertex_group_fix(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_invert(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_blend(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_clean(struct wmOperatorType *ot); +void OBJECT_OT_vertex_group_limit_total(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_mirror(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_set_active(struct wmOperatorType *ot); void OBJECT_OT_vertex_group_sort(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/object/object_lattice.c index 89f9f5de311..4aa2e825954 100644 --- a/source/blender/editors/object/object_lattice.c +++ b/source/blender/editors/object/object_lattice.c @@ -46,6 +46,7 @@ #include "DNA_scene_types.h" #include "RNA_access.h" +#include "RNA_define.h" #include "BKE_context.h" #include "BKE_depsgraph.h" @@ -92,9 +93,9 @@ void make_editLatt(Object *obedit) free_editLatt(obedit); - actkey = ob_get_keyblock(obedit); + actkey = BKE_keyblock_from_object(obedit); if (actkey) - key_to_latt(actkey, lt); + BKE_key_convert_to_lattice(actkey, lt); lt->editlatt = MEM_callocN(sizeof(EditLatt), "editlatt"); lt->editlatt->latt = MEM_dupallocN(lt); @@ -167,7 +168,7 @@ void load_editLatt(Object *obedit) } } -/************************** Operators *************************/ +/************************** Select All Operator *************************/ void ED_setflagsLatt(Object *obedit, int flag) { @@ -254,6 +255,8 @@ void LATTICE_OT_select_all(wmOperatorType *ot) WM_operator_properties_select_all(ot); } +/************************** Make Regular Operator *************************/ + static int make_regular_poll(bContext *C) { Object *ob; @@ -300,18 +303,265 @@ void LATTICE_OT_make_regular(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/************************** Flip Verts Operator *************************/ + +/* flipping options */ +typedef enum eLattice_FlipAxes { + LATTICE_FLIP_U = 0, + LATTICE_FLIP_V = 1, + LATTICE_FLIP_W = 2 +} eLattice_FlipAxes; + +/* Helper macro for accessing item at index (u, v, w) + * < lt: (Lattice) + * < U: (int) u-axis coordinate of point + * < V: (int) v-axis coordinate of point + * < W: (int) w-axis coordinate of point + * < dimU: (int) number of points per row or number of columns (U-Axis) + * < dimV: (int) number of rows (V-Axis) + * > returns: (BPoint *) pointer to BPoint at this index + */ +#define LATTICE_PT(lt, U, V, W, dimU, dimV) \ + ( (lt)->def + \ + ((dimU) * (dimV)) * (W) + \ + (dimU) * (V) + \ + (U) \ + ) + +/* Flip midpoint value so that relative distances between midpoint and neighbour-pair is maintained + * ! Assumes that uvw <=> xyz (i.e. axis-aligned index-axes with coordinate-axes) + * - Helper for lattice_flip_exec() + */ +static void lattice_flip_point_value(Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis) +{ + BPoint *bp; + float diff; + + /* just the point in the middle (unpaired) */ + bp = LATTICE_PT(lt, u, v, w, lt->pntsu, lt->pntsv); + + /* flip over axis */ + diff = mid - bp->vec[axis]; + bp->vec[axis] = mid + diff; +} + +/* Swap pairs of lattice points along a specified axis + * - Helper for lattice_flip_exec() + */ +static void lattice_swap_point_pairs(Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis) +{ + BPoint *bpA, *bpB; + + int numU = lt->pntsu; + int numV = lt->pntsv; + int numW = lt->pntsw; + + int u0 = u, u1 = u; + int v0 = v, v1 = v; + int w0 = w, w1 = w; + + /* get pair index by just overriding the relevant pair-value + * - "-1" else buffer overflow + */ + switch (axis) { + case LATTICE_FLIP_U: + u1 = numU - u - 1; + break; + case LATTICE_FLIP_V: + v1 = numV - v - 1; + break; + case LATTICE_FLIP_W: + w1 = numW - w - 1; + break; + } + + /* get points to operate on */ + bpA = LATTICE_PT(lt, u0, v0, w0, numU, numV); + bpB = LATTICE_PT(lt, u1, v1, w1, numU, numV); + + /* Swap all coordinates, so that flipped coordinates belong to + * the indices on the correct side of the lattice. + * + * Coords: (-2 4) |0| (3 4) --> (3 4) |0| (-2 4) + * Indices: (0,L) (1,R) --> (0,L) (1,R) + */ + swap_v3_v3(bpA->vec, bpB->vec); + + /* However, we need to mirror the coordinate values on the axis we're dealing with, + * otherwise we'd have effectively only rotated the points around. If we don't do this, + * we'd just be reimplementing the naive mirroring algorithm, which causes unwanted deforms + * such as flipped normals, etc. + * + * Coords: (3 4) |0| (-2 4) --\ + * \-> (-3 4) |0| (2 4) + * Indices: (0,L) (1,R) --> (0,L) (1,R) + */ + lattice_flip_point_value(lt, u0, v0, w0, mid, axis); + lattice_flip_point_value(lt, u1, v1, w1, mid, axis); +} + +static int lattice_flip_exec(bContext *C, wmOperator *op) +{ + Object *obedit = CTX_data_edit_object(C); + Lattice *lt; + + eLattice_FlipAxes axis = RNA_enum_get(op->ptr, "axis"); + int numU, numV, numW; + int totP; + + float mid = 0.0f; + short isOdd = 0; + + /* get lattice - we need the "edit lattice" from the lattice... confusing... */ + lt = (Lattice *)obedit->data; + lt = lt->editlatt->latt; + + numU = lt->pntsu; + numV = lt->pntsv; + numW = lt->pntsw; + totP = numU * numV * numW; + + /* First Pass: determine midpoint - used for flipping center verts if there are odd number of points on axis */ + switch (axis) { + case LATTICE_FLIP_U: + isOdd = numU & 1; + break; + case LATTICE_FLIP_V: + isOdd = numV & 1; + break; + case LATTICE_FLIP_W: + isOdd = numW & 1; + break; + + default: + printf("lattice_flip(): Unknown flipping axis (%d)\n", axis); + return OPERATOR_CANCELLED; + } + + if (isOdd) { + BPoint *bp; + float avgInv = 1.0f / (float)totP; + int i; + + /* midpoint calculation - assuming that u/v/w are axis-aligned */ + for (i = 0, bp = lt->def; i < totP; i++, bp++) { + mid += bp->vec[axis] * avgInv; + } + } + + /* Second Pass: swap pairs of vertices per axis, assuming they are all sorted */ + switch (axis) { + case LATTICE_FLIP_U: + { + int u, v, w; + + /* v/w strips - front to back, top to bottom */ + for (w = 0; w < numW; w++) { + for (v = 0; v < numV; v++) { + /* swap coordinates of pairs of vertices on u */ + for (u = 0; u < (numU / 2); u++) { + lattice_swap_point_pairs(lt, u, v, w, mid, axis); + } + + /* flip u-coordinate of midpoint (i.e. unpaired point on u) */ + if (isOdd) { + u = (numU / 2); + lattice_flip_point_value(lt, u, v, w, mid, axis); + } + } + } + } + break; + case LATTICE_FLIP_V: + { + int u, v, w; + + /* u/w strips - front to back, left to right */ + for (w = 0; w < numW; w++) { + for (u = 0; u < numU; u++) { + /* swap coordinates of pairs of vertices on v */ + for (v = 0; v < (numV / 2); v++) { + lattice_swap_point_pairs(lt, u, v, w, mid, axis); + } + + /* flip v-coordinate of midpoint (i.e. unpaired point on v) */ + if (isOdd) { + v = (numV / 2); + lattice_flip_point_value(lt, u, v, w, mid, axis); + } + } + } + } + break; + case LATTICE_FLIP_W: + { + int u, v, w; + + for (v = 0; v < numV; v++) { + for (u = 0; u < numU; u++) { + /* swap coordinates of pairs of vertices on w */ + for (w = 0; w < (numW / 2); w++) { + lattice_swap_point_pairs(lt, u, v, w, mid, axis); + } + + /* flip w-coordinate of midpoint (i.e. unpaired point on w) */ + if (isOdd) { + w = (numW / 2); + lattice_flip_point_value(lt, u, v, w, mid, axis); + } + } + } + } + break; + + default: /* shouldn't happen, but just in case */ + break; + } + + /* updates */ + DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void LATTICE_OT_flip(wmOperatorType *ot) +{ + static EnumPropertyItem flip_items[] = { + {LATTICE_FLIP_U, "U", 0, "U (X) Axis", ""}, + {LATTICE_FLIP_V, "V", 0, "V (Y) Axis", ""}, + {LATTICE_FLIP_W, "W", 0, "W (Z) Axis", ""}, + {0, NULL, 0, NULL, NULL}}; + + /* identifiers */ + ot->name = "Flip (Distortion Free)"; + ot->description = "Mirror all control points without inverting the lattice deform"; + ot->idname = "LATTICE_OT_flip"; + + /* api callbacks */ + ot->poll = ED_operator_editlattice; + ot->invoke = WM_menu_invoke; + ot->exec = lattice_flip_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "axis", flip_items, LATTICE_FLIP_U, "Flip Axis", "Coordinates along this axis get flipped"); +} + /****************************** Mouse Selection *************************/ -static void findnearestLattvert__doClosest(void *userData, BPoint *bp, int x, int y) +static void findnearestLattvert__doClosest(void *userData, BPoint *bp, const float screen_co[2]) { - struct { BPoint *bp; short dist, select; int mval[2]; } *data = userData; - float temp = abs(data->mval[0] - x) + abs(data->mval[1] - y); + struct { BPoint *bp; float dist; int select; float mval_fl[2]; } *data = userData; + float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co); - if ((bp->f1 & SELECT) == data->select) - temp += 5; + if ((bp->f1 & SELECT) && data->select) + dist_test += 5.0f; - if (temp < data->dist) { - data->dist = temp; + if (dist_test < data->dist) { + data->dist = dist_test; data->bp = bp; } @@ -319,18 +569,18 @@ static void findnearestLattvert__doClosest(void *userData, BPoint *bp, int x, in static BPoint *findnearestLattvert(ViewContext *vc, const int mval[2], int sel) { - /* sel==1: selected gets a disadvantage */ + /* (sel == 1): selected gets a disadvantage */ /* in nurb and bezt or bp the nearest is written */ /* return 0 1 2: handlepunt */ - struct { BPoint *bp; short dist, select; int mval[2]; } data = {NULL}; + struct { BPoint *bp; float dist; int select; float mval_fl[2]; } data = {NULL}; data.dist = 100; data.select = sel; - data.mval[0] = mval[0]; - data.mval[1] = mval[1]; + data.mval_fl[0] = mval[0]; + data.mval_fl[1] = mval[1]; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - lattice_foreachScreenVert(vc, findnearestLattvert__doClosest, &data); + lattice_foreachScreenVert(vc, findnearestLattvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); return data.bp; } @@ -341,7 +591,7 @@ int mouse_lattice(bContext *C, const int mval[2], int extend, int deselect, int BPoint *bp = NULL; view3d_set_viewcontext(C, &vc); - bp = findnearestLattvert(&vc, mval, 1); + bp = findnearestLattvert(&vc, mval, TRUE); if (bp) { if (extend) { diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 4858fdf1c35..3d2c4f95624 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -99,13 +99,13 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc /* only geometry objects should be able to get modifiers [#25291] */ if (!ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { - BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to Object '%s'", ob->id.name + 2); + BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2); return NULL; } if (mti->flags & eModifierTypeFlag_Single) { if (modifiers_findByType(ob, type)) { - BKE_report(reports, RPT_WARNING, "Only one modifier of this type allowed"); + BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed"); return NULL; } } @@ -159,8 +159,10 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc /* set totlvl from existing MDISPS layer if object already had it */ multiresModifier_set_levels_from_disps((MultiresModifierData *)new_md, ob); - /* ensure that grid paint mask layer is created */ - ED_sculpt_mask_layers_ensure(ob, (MultiresModifierData *)new_md); + if (ob->mode & OB_MODE_SCULPT) { + /* ensure that grid paint mask layer is created */ + ED_sculpt_mask_layers_ensure(ob, (MultiresModifierData *)new_md); + } } else if (type == eModifierType_Skin) { /* ensure skin-node customdata exists */ @@ -554,7 +556,7 @@ static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, M KeyBlock *kb; if (!modifier_sameTopology(md) || mti->type == eModifierTypeType_NonGeometrical) { - BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to Shapes"); + BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to shapes"); return 0; } @@ -565,15 +567,15 @@ static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, M } if (key == NULL) { - key = me->key = add_key((ID *)me); + key = me->key = BKE_key_add((ID *)me); key->type = KEY_RELATIVE; /* if that was the first key block added, then it was the basis. * Initialize it with the mesh, and add another for the modifier */ - kb = add_keyblock(key, NULL); - mesh_to_key(me, kb); + kb = BKE_keyblock_add(key, NULL); + BKE_key_convert_from_mesh(me, kb); } - kb = add_keyblock(key, md->name); + kb = BKE_keyblock_add(key, md->name); DM_to_meshkey(dm, me, kb); dm->release(dm); @@ -602,7 +604,7 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, MultiresModifierData *mmd = find_multires_modifier_before(scene, md); if (me->key && mti->type != eModifierTypeType_NonGeometrical) { - BKE_report(reports, RPT_ERROR, "Modifier cannot be applied to Mesh with Shape Keys"); + BKE_report(reports, RPT_ERROR, "Modifier cannot be applied to a mesh with shape keys"); return 0; } @@ -679,7 +681,7 @@ int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, Modi int prev_mode; if (scene->obedit) { - BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in editmode"); + BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in edit mode"); return 0; } else if (((ID *) ob->data)->us > 1) { @@ -710,11 +712,6 @@ int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, Modi BLI_remlink(&ob->modifiers, md); modifier_free(md); - if (ob->type == OB_MESH) { - /* ensure mesh paint mask layer remains after applying */ - ED_sculpt_mask_layers_ensure(ob, NULL); - } - return 1; } @@ -1245,7 +1242,7 @@ static int multires_reshape_exec(bContext *C, wmOperator *op) CTX_DATA_END; if (!secondob) { - BKE_report(op->reports, RPT_ERROR, "Second selected mesh object require to copy shape from"); + BKE_report(op->reports, RPT_ERROR, "Second selected mesh object required to copy shape from"); return OPERATOR_CANCELLED; } @@ -1692,11 +1689,9 @@ static void skin_armature_bone_create(Object *skin_ob, v = (e->v1 == parent_v ? e->v2 : e->v1); - bone = MEM_callocN(sizeof(EditBone), - "skin_armature_bone_create EditBone"); + bone = ED_armature_edit_bone_add(arm, "Bone"); bone->parent = parent_bone; - bone->layer = 1; bone->flag |= BONE_CONNECTED; copy_v3_v3(bone->head, mvert[parent_v].co); @@ -1704,8 +1699,6 @@ static void skin_armature_bone_create(Object *skin_ob, bone->rad_head = bone->rad_tail = 0.25; BLI_snprintf(bone->name, sizeof(bone->name), "Bone.%.2d", endx); - BLI_addtail(arm->edbo, bone); - /* add bDeformGroup */ if ((dg = ED_vgroup_add_name(skin_ob, bone->name))) { ED_vgroup_vert_add(skin_ob, dg, parent_v, 1, WEIGHT_REPLACE); @@ -1770,16 +1763,13 @@ static Object *modifier_skin_armature_create(struct Scene *scene, * a fake root bone (have it going off in the Y direction * (arbitrary) */ if (emap[v].count > 1) { - bone = MEM_callocN(sizeof(EditBone), "EditBone"); + bone = ED_armature_edit_bone_add(arm, "Bone"); copy_v3_v3(bone->head, me->mvert[v].co); copy_v3_v3(bone->tail, me->mvert[v].co); - bone->layer = 1; bone->head[1] = 1.0f; bone->rad_head = bone->rad_tail = 0.25; - - BLI_addtail(arm->edbo, bone); } if (emap[v].count >= 1) { diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index cec849efca7..d19277d20a2 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -113,6 +113,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_delete); WM_operatortype_append(OBJECT_OT_text_add); WM_operatortype_append(OBJECT_OT_armature_add); + WM_operatortype_append(OBJECT_OT_empty_add); WM_operatortype_append(OBJECT_OT_lamp_add); WM_operatortype_append(OBJECT_OT_camera_add); WM_operatortype_append(OBJECT_OT_speaker_add); @@ -168,6 +169,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(CONSTRAINT_OT_childof_clear_inverse); WM_operatortype_append(CONSTRAINT_OT_objectsolver_set_inverse); WM_operatortype_append(CONSTRAINT_OT_objectsolver_clear_inverse); + WM_operatortype_append(CONSTRAINT_OT_followpath_path_animate); WM_operatortype_append(OBJECT_OT_vertex_group_add); WM_operatortype_append(OBJECT_OT_vertex_group_remove); @@ -176,6 +178,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_vertex_group_select); WM_operatortype_append(OBJECT_OT_vertex_group_deselect); WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_linked); + WM_operatortype_append(OBJECT_OT_vertex_group_transfer_weight); WM_operatortype_append(OBJECT_OT_vertex_group_copy_to_selected); WM_operatortype_append(OBJECT_OT_vertex_group_copy); WM_operatortype_append(OBJECT_OT_vertex_group_normalize); @@ -186,6 +189,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_vertex_group_levels); WM_operatortype_append(OBJECT_OT_vertex_group_blend); WM_operatortype_append(OBJECT_OT_vertex_group_clean); + WM_operatortype_append(OBJECT_OT_vertex_group_limit_total); WM_operatortype_append(OBJECT_OT_vertex_group_mirror); WM_operatortype_append(OBJECT_OT_vertex_group_set_active); WM_operatortype_append(OBJECT_OT_vertex_group_sort); @@ -207,6 +211,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(LATTICE_OT_select_all); WM_operatortype_append(LATTICE_OT_make_regular); + WM_operatortype_append(LATTICE_OT_flip); WM_operatortype_append(OBJECT_OT_group_add); WM_operatortype_append(OBJECT_OT_group_link); @@ -388,7 +393,7 @@ void ED_keymap_object(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "OBJECT_OT_proxy_make", PKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); WM_keymap_add_item(keymap, "OBJECT_OT_make_local", LKEY, KM_PRESS, 0, 0); - // XXX this should probably be in screen instead... here for testing purposes in the meantime... - Aligorith + /* XXX this should probably be in screen instead... here for testing purposes in the meantime... - Aligorith */ WM_keymap_verify_item(keymap, "ANIM_OT_keyframe_insert_menu", IKEY, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "ANIM_OT_keyframe_delete_v3d", IKEY, KM_PRESS, KM_ALT, 0); WM_keymap_verify_item(keymap, "ANIM_OT_keying_set_active_set", IKEY, KM_PRESS, KM_CTRL | KM_SHIFT | KM_ALT, 0); @@ -420,6 +425,8 @@ void ED_keymap_object(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "OBJECT_OT_vertex_parent_set", PKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "LATTICE_OT_flip", FKEY, KM_PRESS, KM_CTRL, 0); + /* menus */ WM_keymap_add_menu(keymap, "VIEW3D_MT_hook", HKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index cafc7ce9300..58c6959d6f0 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -423,29 +423,92 @@ void OBJECT_OT_proxy_make(wmOperatorType *ot) /********************** Clear Parent Operator ******************* */ +typedef enum eObClearParentTypes { + CLEAR_PARENT_ALL = 0, + CLEAR_PARENT_KEEP_TRANSFORM, + CLEAR_PARENT_INVERSE +} eObClearParentTypes; + EnumPropertyItem prop_clear_parent_types[] = { - {0, "CLEAR", 0, "Clear Parent", ""}, - {1, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation", ""}, - {2, "CLEAR_INVERSE", 0, "Clear Parent Inverse", ""}, + {CLEAR_PARENT_ALL, "CLEAR", 0, "Clear Parent", ""}, + {CLEAR_PARENT_KEEP_TRANSFORM, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation", ""}, + {CLEAR_PARENT_INVERSE, "CLEAR_INVERSE", 0, "Clear Parent Inverse", ""}, {0, NULL, 0, NULL, NULL} }; +/* Helper for ED_object_parent_clear() - Remove deform-modifiers associated with parent */ +static void object_remove_parent_deform_modifiers(Object *ob, const Object *par) +{ + if (ELEM3(par->type, OB_ARMATURE, OB_LATTICE, OB_CURVE)) { + ModifierData *md, *mdn; + + /* assume that we only need to remove the first instance of matching deform modifier here */ + for (md = ob->modifiers.first; md; md = mdn) { + short free = FALSE; + + mdn = md->next; + + /* need to match types (modifier + parent) and references */ + if ((md->type == eModifierType_Armature) && (par->type == OB_ARMATURE)) { + ArmatureModifierData *amd = (ArmatureModifierData *)md; + if (amd->object == par) { + free = TRUE; + } + } + else if ((md->type == eModifierType_Lattice) && (par->type == OB_LATTICE)) { + LatticeModifierData *lmd = (LatticeModifierData *)md; + if (lmd->object == par) { + free = TRUE; + } + } + else if ((md->type == eModifierType_Curve) && (par->type == OB_CURVE)) { + CurveModifierData *cmd = (CurveModifierData *)md; + if (cmd->object == par) { + free = TRUE; + } + } + + /* free modifier if match */ + if (free) { + BLI_remlink(&ob->modifiers, md); + modifier_free(md); + } + } + } +} + void ED_object_parent_clear(Object *ob, int type) { - if (ob->parent == NULL) return; + + switch (type) { + case CLEAR_PARENT_ALL: + { + /* for deformers, remove corresponding modifiers to prevent a large number of modifiers building up */ + object_remove_parent_deform_modifiers(ob, ob->parent); + + /* clear parenting relationship completely */ + ob->parent = NULL; + } + break; - if (type == 0) { - ob->parent = NULL; - } - else if (type == 1) { - ob->parent = NULL; - BKE_object_apply_mat4(ob, ob->obmat, TRUE, FALSE); - } - else if (type == 2) - unit_m4(ob->parentinv); + case CLEAR_PARENT_KEEP_TRANSFORM: + { + /* remove parent, and apply the parented transform result as object's local transforms */ + ob->parent = NULL; + BKE_object_apply_mat4(ob, ob->obmat, TRUE, FALSE); + } + break; + case CLEAR_PARENT_INVERSE: + { + /* object stays parented, but the parent inverse (i.e. offset from parent to retain binding state) is cleared */ + unit_m4(ob->parentinv); + } + break; + } + ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; } @@ -525,7 +588,7 @@ EnumPropertyItem prop_make_parent_types[] = { }; int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object *ob, Object *par, - int partype, int xmirror) + int partype, int xmirror, int keep_transform) { bPoseChannel *pchan = NULL; int pararm = ELEM4(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO); @@ -559,13 +622,13 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object /* fall back on regular parenting now (for follow only) */ if (partype == PAR_FOLLOW) partype = PAR_OBJECT; - } + } } else if (partype == PAR_BONE) { pchan = BKE_pose_channel_active(par); if (pchan == NULL) { - BKE_report(reports, RPT_ERROR, "No active Bone"); + BKE_report(reports, RPT_ERROR, "No active bone"); return 0; } } @@ -577,10 +640,14 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object } else { Object workob; - + /* apply transformation of previous parenting */ - /* BKE_object_apply_mat4(ob, ob->obmat); */ /* removed because of bug [#23577] */ - + if (keep_transform) { + /* was removed because of bug [#23577], + * but this can be handy in some cases too [#32616], so make optional */ + BKE_object_apply_mat4(ob, ob->obmat, FALSE, FALSE); + } + /* set the parent (except for follow-path constraint option) */ if (partype != PAR_PATH_CONST) { ob->parent = par; @@ -600,25 +667,40 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object * NOTE: the old (2.4x) method was to set ob->partype = PARSKEL, creating the virtual modifiers */ ob->partype = PAROBJECT; /* note, dna define, not operator property */ - //ob->partype= PARSKEL; /* note, dna define, not operator property */ + //ob->partype = PARSKEL; /* note, dna define, not operator property */ - /* BUT, to keep the deforms, we need a modifier, and then we need to set the object that it uses */ + /* BUT, to keep the deforms, we need a modifier, and then we need to set the object that it uses + * - We need to ensure that the modifier we're adding doesn't already exist, so we check this by + * assuming that the parent is selected too... + */ // XXX currently this should only happen for meshes, curves, surfaces, and lattices - this stuff isn't available for metas yet if (ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { ModifierData *md; switch (partype) { case PAR_CURVE: /* curve deform */ - md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Curve); - ((CurveModifierData *)md)->object = par; + if ( modifiers_isDeformedByCurve(ob) != par) { + md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Curve); + if (md) { + ((CurveModifierData *)md)->object = par; + } + } break; case PAR_LATTICE: /* lattice deform */ - md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Lattice); - ((LatticeModifierData *)md)->object = par; + if (modifiers_isDeformedByLattice(ob) != par) { + md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Lattice); + if (md) { + ((LatticeModifierData *)md)->object = par; + } + } break; default: /* armature deform */ - md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Armature); - ((ArmatureModifierData *)md)->object = par; + if (modifiers_isDeformedByArmature(ob) != par) { + md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Armature); + if (md) { + ((ArmatureModifierData *)md)->object = par; + } + } break; } } @@ -682,11 +764,12 @@ static int parent_set_exec(bContext *C, wmOperator *op) Object *par = ED_object_active_context(C); int partype = RNA_enum_get(op->ptr, "type"); int xmirror = RNA_boolean_get(op->ptr, "xmirror"); + int keep_transform = RNA_boolean_get(op->ptr, "keep_transform"); int ok = 1; CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { - if (!ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, xmirror)) { + if (!ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, xmirror, keep_transform)) { ok = 0; break; } @@ -710,25 +793,36 @@ static int parent_set_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSE Object *ob = ED_object_active_context(C); uiPopupMenu *pup = uiPupMenuBegin(C, "Set Parent To", ICON_NONE); uiLayout *layout = uiPupMenuLayout(pup); - - uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT); - uiItemEnumO(layout, "OBJECT_OT_parent_set", NULL, 0, "type", PAR_OBJECT); - + + wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_parent_set", TRUE); + PointerRNA opptr; + +#if 0 + uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_OBJECT); +#else + opptr = uiItemFullO_ptr(layout, ot, "Object", ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); + RNA_enum_set(&opptr, "type", PAR_OBJECT); + RNA_boolean_set(&opptr, "keep_transform", FALSE); + + opptr = uiItemFullO_ptr(layout, ot, "Object (Keep Transform)", ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); + RNA_enum_set(&opptr, "type", PAR_OBJECT); + RNA_boolean_set(&opptr, "keep_transform", TRUE); +#endif /* ob becomes parent, make the associated menus */ if (ob->type == OB_ARMATURE) { - uiItemEnumO(layout, "OBJECT_OT_parent_set", NULL, 0, "type", PAR_ARMATURE); - uiItemEnumO(layout, "OBJECT_OT_parent_set", NULL, 0, "type", PAR_ARMATURE_NAME); - uiItemEnumO(layout, "OBJECT_OT_parent_set", NULL, 0, "type", PAR_ARMATURE_ENVELOPE); - uiItemEnumO(layout, "OBJECT_OT_parent_set", NULL, 0, "type", PAR_ARMATURE_AUTO); - uiItemEnumO(layout, "OBJECT_OT_parent_set", NULL, 0, "type", PAR_BONE); + uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE); + uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_NAME); + uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_ENVELOPE); + uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_ARMATURE_AUTO); + uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_BONE); } else if (ob->type == OB_CURVE) { - uiItemEnumO(layout, "OBJECT_OT_parent_set", NULL, 0, "type", PAR_CURVE); - uiItemEnumO(layout, "OBJECT_OT_parent_set", NULL, 0, "type", PAR_FOLLOW); - uiItemEnumO(layout, "OBJECT_OT_parent_set", NULL, 0, "type", PAR_PATH_CONST); + uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_CURVE); + uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_FOLLOW); + uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_PATH_CONST); } else if (ob->type == OB_LATTICE) { - uiItemEnumO(layout, "OBJECT_OT_parent_set", NULL, 0, "type", PAR_LATTICE); + uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_LATTICE); } uiPupMenuEnd(C, pup); @@ -783,6 +877,9 @@ void OBJECT_OT_parent_set(wmOperatorType *ot) RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", ""); RNA_def_boolean(ot->srna, "xmirror", FALSE, "X Mirror", "Apply weights symmetrically along X axis, for Envelope/Automatic vertex groups creation"); + RNA_def_boolean(ot->srna, "keep_transform", FALSE, "Keep Transform", + "Apply transformation before parenting"); + } /* ************ Make Parent Without Inverse Operator ******************* */ @@ -939,7 +1036,7 @@ static int object_track_clear_exec(bContext *C, wmOperator *op) int type = RNA_enum_get(op->ptr, "type"); if (CTX_data_edit_object(C)) { - BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in EditMode"); + BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in edit mode"); return OPERATOR_CANCELLED; } CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) @@ -1163,7 +1260,7 @@ static int move_to_layer_exec(bContext *C, wmOperator *op) base->object->lay = lay; base->object->flag &= ~SELECT; base->flag &= ~SELECT; - /* if (base->object->type==OB_LAMP) is_lamp = TRUE; */ + /* if (base->object->type == OB_LAMP) is_lamp = TRUE; */ } CTX_DATA_END; } @@ -1176,7 +1273,7 @@ static int move_to_layer_exec(bContext *C, wmOperator *op) local = base->lay & 0xFF000000; base->lay = lay + local; base->object->lay = lay; - /* if (base->object->type==OB_LAMP) is_lamp = TRUE; */ + /* if (base->object->type == OB_LAMP) is_lamp = TRUE; */ } CTX_DATA_END; } @@ -1253,17 +1350,17 @@ static int make_links_scene_exec(bContext *C, wmOperator *op) Scene *scene_to = BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene")); if (scene_to == NULL) { - BKE_report(op->reports, RPT_ERROR, "Couldn't find scene"); + BKE_report(op->reports, RPT_ERROR, "Could not find scene"); return OPERATOR_CANCELLED; } if (scene_to == CTX_data_scene(C)) { - BKE_report(op->reports, RPT_ERROR, "Can't link objects into the same scene"); + BKE_report(op->reports, RPT_ERROR, "Cannot link objects into the same scene"); return OPERATOR_CANCELLED; } if (scene_to->id.lib) { - BKE_report(op->reports, RPT_ERROR, "Can't link objects into a linked scene"); + BKE_report(op->reports, RPT_ERROR, "Cannot link objects into a linked scene"); return OPERATOR_CANCELLED; } @@ -1275,6 +1372,9 @@ static int make_links_scene_exec(bContext *C, wmOperator *op) DAG_ids_flush_update(bmain, 0); + /* redraw the 3D view because the object center points are colored differently */ + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); + /* one day multiple scenes will be visible, then we should have some update function for them */ return OPERATOR_FINISHED; } @@ -1610,7 +1710,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, int flag) break; case OB_MESH: ob->data = BKE_mesh_copy(ob->data); - //me= ob->data; + //me = ob->data; //if (me && me->key) // ipo_idnew(me->key->ipo); /* drivers */ break; diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index 7eb8cc01db9..2aa737d204d 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -198,7 +198,7 @@ enum { }; static EnumPropertyItem prop_select_linked_types[] = { - //{OBJECT_SELECT_LINKED_IPO, "IPO", 0, "Object IPO", ""}, // XXX depreceated animation system stuff... + //{OBJECT_SELECT_LINKED_IPO, "IPO", 0, "Object IPO", ""}, // XXX deprecated animation system stuff... {OBJECT_SELECT_LINKED_OBDATA, "OBDATA", 0, "Object Data", ""}, {OBJECT_SELECT_LINKED_MATERIAL, "MATERIAL", 0, "Material", ""}, {OBJECT_SELECT_LINKED_TEXTURE, "TEXTURE", 0, "Texture", ""}, @@ -425,7 +425,7 @@ static int object_select_linked_exec(bContext *C, wmOperator *op) ob = OBACT; if (ob == NULL) { - BKE_report(op->reports, RPT_ERROR, "No Active Object"); + BKE_report(op->reports, RPT_ERROR, "No active object"); return OPERATOR_CANCELLED; } @@ -608,11 +608,11 @@ static short select_grouped_group(bContext *C, Object *ob) /* Select objects in for (i = 0; i < group_count; i++) { group = ob_groups[i]; - uiItemStringO(layout, group->id.name + 2, 0, "OBJECT_OT_select_same_group", "group", group->id.name); + uiItemStringO(layout, group->id.name + 2, 0, "OBJECT_OT_select_same_group", "group", group->id.name + 2); } uiPupMenuEnd(C, pup); - return changed; // The operator already handle this! + return changed; /* The operator already handle this! */ } static short select_grouped_object_hooks(bContext *C, Object *ob) @@ -723,7 +723,7 @@ static short objects_share_gameprop(Object *a, Object *b) /*make a copy of all its properties*/ for (prop = a->prop.first; prop; prop = prop->next) { - if (get_ob_property(b, prop->name) ) + if (BKE_bproperty_object_get(b, prop->name) ) return 1; } return 0; @@ -754,8 +754,8 @@ static short select_grouped_keyingset(bContext *C, Object *UNUSED(ob)) return 0; /* select each object that Keying Set refers to */ - // TODO: perhaps to be more in line with the rest of these, we should only take objects - // if the passed in object is included in this too + /* TODO: perhaps to be more in line with the rest of these, we should only take objects + * if the passed in object is included in this too */ CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { /* only check for this object if it isn't selected already, to limit time wasted */ @@ -800,7 +800,7 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op) ob = OBACT; if (ob == NULL) { - BKE_report(op->reports, RPT_ERROR, "No Active Object"); + BKE_report(op->reports, RPT_ERROR, "No active object"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index 40b653a62fd..2b6d69ca694 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -78,7 +78,7 @@ static void ED_object_shape_key_add(bContext *C, Scene *scene, Object *ob, int f { KeyBlock *kb; if ((kb = BKE_object_insert_shape_key(scene, ob, NULL, from_mix))) { - Key *key = ob_get_key(ob); + Key *key = BKE_key_from_object(ob); /* for absolute shape keys, new keys may not be added last */ ob->shapenr = BLI_findindex(&key->block, kb) + 1; @@ -95,7 +95,7 @@ static int ED_object_shape_key_remove(bContext *C, Object *ob) Key *key; //IpoCurve *icu; - key = ob_get_key(ob); + key = BKE_key_from_object(ob); if (key == NULL) return 0; @@ -115,14 +115,14 @@ static int ED_object_shape_key_remove(bContext *C, Object *ob) /* apply new basis key on original data */ switch (ob->type) { case OB_MESH: - key_to_mesh(key->refkey, ob->data); + BKE_key_convert_to_mesh(key->refkey, ob->data); break; case OB_CURVE: case OB_SURF: - key_to_curve(key->refkey, ob->data, BKE_curve_nurbs_get(ob->data)); + BKE_key_convert_to_curve(key->refkey, ob->data, BKE_curve_nurbs_get(ob->data)); break; case OB_LATTICE: - key_to_latt(key->refkey, ob->data); + BKE_key_convert_to_lattice(key->refkey, ob->data); break; } } @@ -155,22 +155,22 @@ static int object_shape_key_mirror(bContext *C, Object *ob) KeyBlock *kb; Key *key; - key = ob_get_key(ob); + key = BKE_key_from_object(ob); if (key == NULL) return 0; kb = BLI_findlink(&key->block, ob->shapenr - 1); if (kb) { - int i1, i2; - float *fp1, *fp2; - float tvec[3]; char *tag_elem = MEM_callocN(sizeof(char) * kb->totelem, "shape_key_mirror"); if (ob->type == OB_MESH) { Mesh *me = ob->data; MVert *mv; + int i1, i2; + float *fp1, *fp2; + float tvec[3]; mesh_octree_table(ob, NULL, NULL, 's'); @@ -211,7 +211,7 @@ static int object_shape_key_mirror(bContext *C, Object *ob) /* currently editmode isn't supported by mesh so * ignore here for now too */ - /* if (lt->editlatt) lt= lt->editlatt->latt; */ + /* if (lt->editlatt) lt = lt->editlatt->latt; */ for (w = 0; w < lt->pntsw; w++) { for (v = 0; v < lt->pntsv; v++) { @@ -323,8 +323,8 @@ void OBJECT_OT_shape_key_remove(wmOperatorType *ot) static int shape_key_clear_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); - Key *key = ob_get_key(ob); - KeyBlock *kb = ob_get_keyblock(ob); + Key *key = BKE_key_from_object(ob); + KeyBlock *kb = BKE_keyblock_from_object(ob); if (!key || !kb) return OPERATOR_CANCELLED; @@ -357,8 +357,8 @@ void OBJECT_OT_shape_key_clear(wmOperatorType *ot) static int shape_key_retime_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_object_context(C); - Key *key = ob_get_key(ob); - KeyBlock *kb = ob_get_keyblock(ob); + Key *key = BKE_key_from_object(ob); + KeyBlock *kb = BKE_keyblock_from_object(ob); float cfra = 0.0f; if (!key || !kb) @@ -419,7 +419,7 @@ static int shape_key_move_exec(bContext *C, wmOperator *op) Object *ob = ED_object_context(C); int type = RNA_enum_get(op->ptr, "type"); - Key *key = ob_get_key(ob); + Key *key = BKE_key_from_object(ob); if (key) { KeyBlock *kb, *kb_other; diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 9129d651d4d..900bf57b509 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -171,7 +171,7 @@ static void object_clear_rot(Object *ob) } } } // Duplicated in source/blender/editors/armature/editarmature.c - else { + else { if (ob->rotmode == ROT_MODE_QUAT) { unit_qt(ob->quat); unit_qt(ob->dquat); @@ -217,7 +217,7 @@ static int object_clear_transform_generic_exec(bContext *C, wmOperator *op, /* sanity checks */ if (ELEM(NULL, clear_func, default_ksName)) { - BKE_report(op->reports, RPT_ERROR, "Programming error: missing clear transform func or Keying Set Name"); + BKE_report(op->reports, RPT_ERROR, "Programming error: missing clear transform function or keying set name"); return OPERATOR_CANCELLED; } @@ -381,8 +381,8 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - float rsmat[3][3], tmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale; - int a, change = 1; + float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale; + int change = 1; /* first check if we can execute */ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) @@ -390,19 +390,19 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo if (ob->type == OB_MESH) { if (ID_REAL_USERS(ob->data) > 1) { - BKE_report(reports, RPT_ERROR, "Can't apply to a multi user mesh, doing nothing"); + BKE_report(reports, RPT_ERROR, "Cannot apply to a multi user mesh, doing nothing"); change = 0; } } else if (ob->type == OB_ARMATURE) { if (ID_REAL_USERS(ob->data) > 1) { - BKE_report(reports, RPT_ERROR, "Can't apply to a multi user armature, doing nothing"); + BKE_report(reports, RPT_ERROR, "Cannot apply to a multi user armature, doing nothing"); change = 0; } } else if (ob->type == OB_LATTICE) { if (ID_REAL_USERS(ob->data) > 1) { - BKE_report(reports, RPT_ERROR, "Can't apply to a multi user lattice, doing nothing"); + BKE_report(reports, RPT_ERROR, "Cannot apply to a multi user lattice, doing nothing"); change = 0; } } @@ -410,18 +410,19 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo Curve *cu; if (ID_REAL_USERS(ob->data) > 1) { - BKE_report(reports, RPT_ERROR, "Can't apply to a multi user curve, doing nothing"); + BKE_report(reports, RPT_ERROR, "Cannot apply to a multi user curve, doing nothing"); change = 0; } cu = ob->data; if (!(cu->flag & CU_3D) && (apply_rot || apply_loc)) { - BKE_report(reports, RPT_ERROR, "Neither rotation nor location could be applied to a 2d curve, doing nothing"); + BKE_report(reports, RPT_ERROR, + "Neither rotation nor location could be applied to a 2D curve, doing nothing"); change = 0; } if (cu->key) { - BKE_report(reports, RPT_ERROR, "Can't apply to a curve with vertex keys, doing nothing"); + BKE_report(reports, RPT_ERROR, "Cannot apply to a curve with vertex keys, doing nothing"); change = 0; } } @@ -464,6 +465,7 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo copy_v3_v3(mat[3], ob->loc); if (!(apply_scale && apply_rot)) { + float tmat[3][3]; /* correct for scale and rotation that is still applied */ BKE_object_to_mat3(ob, obmat); invert_m3_m3(iobmat, obmat); @@ -476,6 +478,7 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo if (ob->type == OB_MESH) { Mesh *me = ob->data; MVert *mvert; + int a; if (apply_scale) multiresModifier_scale_disp(scene, ob); @@ -518,6 +521,7 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo Nurb *nu; BPoint *bp; BezTriple *bezt; + int a; scale = mat3_to_scale(rsmat); @@ -650,7 +654,8 @@ void OBJECT_OT_transform_apply(wmOperatorType *ot) enum { GEOMETRY_TO_ORIGIN = 0, ORIGIN_TO_GEOMETRY, - ORIGIN_TO_CURSOR + ORIGIN_TO_CURSOR, + ORIGIN_TO_CENTER_OF_MASS }; static int object_origin_set_exec(bContext *C, wmOperator *op) @@ -667,7 +672,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) int tot_change = 0, tot_lib_error = 0, tot_multiuser_arm_error = 0; if (obedit && centermode != GEOMETRY_TO_ORIGIN) { - BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in EditMode"); + BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in edit mode"); return OPERATOR_CANCELLED; } else { @@ -781,6 +786,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) Mesh *me = ob->data; if (centermode == ORIGIN_TO_CURSOR) { /* done */ } + else if (centermode == ORIGIN_TO_CENTER_OF_MASS) { BKE_mesh_center_centroid(me, cent); } else if (around == V3D_CENTROID) { BKE_mesh_center_median(me, cent); } else { BKE_mesh_center_bounds(me, cent); } @@ -848,7 +854,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) if (ID_REAL_USERS(arm) > 1) { #if 0 - BKE_report(op->reports, RPT_ERROR, "Can't apply to a multi user armature"); + BKE_report(op->reports, RPT_ERROR, "Cannot apply to a multi user armature"); return; #endif tot_multiuser_arm_error++; @@ -861,7 +867,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) tot_change++; arm->id.flag |= LIB_DOIT; - /* do_inverse_offset= TRUE; */ /* docenter_armature() handles this */ + /* do_inverse_offset = TRUE; */ /* docenter_armature() handles this */ BKE_object_where_is_calc(scene, ob); BKE_pose_where_is(scene, ob); /* needed for bone parents */ @@ -896,10 +902,17 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) /* offset other selected objects */ if (do_inverse_offset && (centermode != GEOMETRY_TO_ORIGIN)) { + CollectionPointerLink *ctx_link_other; + float obmat[4][4]; + /* was the object data modified * note: the functions above must set 'cent' */ + + /* convert the offset to parent space */ + BKE_object_to_mat4(ob, obmat); copy_v3_v3(centn, cent); - mul_mat3_m4_v3(ob->obmat, centn); /* ommit translation part */ + mul_mat3_m4_v3(obmat, centn); /* omit translation part */ + add_v3_v3(ob->loc, centn); BKE_object_where_is_calc(scene, ob); @@ -910,8 +923,16 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) ignore_parent_tx(bmain, scene, ob); /* other users? */ - CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects) + //CTX_DATA_BEGIN (C, Object *, ob_other, selected_editable_objects) + //{ + + /* use existing context looper */ + for (ctx_link_other = ctx_data_list.first; + ctx_link_other; + ctx_link_other = ctx_link_other->next) { + Object *ob_other = ctx_link_other->ptr.data; + if ((ob_other->flag & OB_DONE) == 0 && ((ob->data && (ob->data == ob_other->data)) || (ob->dup_group == ob_other->dup_group && @@ -931,7 +952,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) ignore_parent_tx(bmain, scene, ob_other); } } - CTX_DATA_END; + //CTX_DATA_END; } } } @@ -948,9 +969,9 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) /* Warn if any errors occurred */ if (tot_lib_error + tot_multiuser_arm_error) { - BKE_reportf(op->reports, RPT_WARNING, "%i Object(s) Not Centered, %i Changed:", tot_lib_error + tot_multiuser_arm_error, tot_change); + BKE_reportf(op->reports, RPT_WARNING, "%i object(s) not centered, %i changed:", tot_lib_error + tot_multiuser_arm_error, tot_change); if (tot_lib_error) - BKE_reportf(op->reports, RPT_WARNING, "|%i linked library objects", tot_lib_error); + BKE_reportf(op->reports, RPT_WARNING, "|%i linked library object(s)", tot_lib_error); if (tot_multiuser_arm_error) BKE_reportf(op->reports, RPT_WARNING, "|%i multiuser armature object(s)", tot_multiuser_arm_error); } @@ -962,8 +983,12 @@ void OBJECT_OT_origin_set(wmOperatorType *ot) { static EnumPropertyItem prop_set_center_types[] = { {GEOMETRY_TO_ORIGIN, "GEOMETRY_ORIGIN", 0, "Geometry to Origin", "Move object geometry to object origin"}, - {ORIGIN_TO_GEOMETRY, "ORIGIN_GEOMETRY", 0, "Origin to Geometry", "Move object origin to center of object geometry"}, - {ORIGIN_TO_CURSOR, "ORIGIN_CURSOR", 0, "Origin to 3D Cursor", "Move object origin to position of the 3d cursor"}, + {ORIGIN_TO_GEOMETRY, "ORIGIN_GEOMETRY", 0, "Origin to Geometry", + "Move object origin to center of object geometry"}, + {ORIGIN_TO_CURSOR, "ORIGIN_CURSOR", 0, "Origin to 3D Cursor", + "Move object origin to position of the 3D cursor"}, + {ORIGIN_TO_CENTER_OF_MASS, "ORIGIN_CENTER_OF_MASS", 0, "Origin to Center of Mass", + "Move object origin to the object center of mass (assuming uniform density)"}, {0, NULL, 0, NULL, NULL} }; @@ -975,7 +1000,7 @@ void OBJECT_OT_origin_set(wmOperatorType *ot) /* identifiers */ ot->name = "Set Origin"; - ot->description = "Set the object's origin, by either moving the data, or set to center of data, or use 3d cursor"; + ot->description = "Set the object's origin, by either moving the data, or set to center of data, or use 3D cursor"; ot->idname = "OBJECT_OT_origin_set"; /* api callbacks */ @@ -990,4 +1015,3 @@ void OBJECT_OT_origin_set(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_set_center_types, 0, "Type", ""); RNA_def_enum(ot->srna, "center", prop_set_bounds_types, V3D_CENTROID, "Center", ""); } - diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index b31d2b8b076..05524af34f0 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -20,7 +20,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Ove M Henriksen. * * ***** END GPL LICENSE BLOCK ***** */ @@ -29,7 +29,6 @@ * \ingroup edobj */ - #include #include #include @@ -83,6 +82,19 @@ static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *defgroup); static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg); static void vgroup_delete_all(Object *ob); +static int vertex_group_use_vert_sel(Object *ob) +{ + if (ob->mode == OB_MODE_EDIT) { + return TRUE; + } + else if (ob->type == OB_MESH && ((Mesh *)ob->data)->editflag & ME_EDIT_VERT_SEL) { + return TRUE; + } + else { + return FALSE; + } +} + static Lattice *vgroup_edit_lattice(Object *ob) { Lattice *lt = ob->data; @@ -126,21 +138,12 @@ bDeformGroup *ED_vgroup_add(Object *ob) void ED_vgroup_delete(Object *ob, bDeformGroup *defgroup) { - bDeformGroup *dg = (bDeformGroup *)ob->defbase.first; - - while (dg) { - if (dg == defgroup) - break; - dg = dg->next; - } - - if (dg == NULL) - return; + BLI_assert(BLI_findindex(&ob->defbase, defgroup) != -1); if (ED_vgroup_object_is_edit_mode(ob)) - vgroup_delete_edit_mode(ob, dg); + vgroup_delete_edit_mode(ob, defgroup); else - vgroup_delete_object_mode(ob, dg); + vgroup_delete_object_mode(ob, defgroup); } void ED_vgroup_clear(Object *ob) @@ -377,6 +380,332 @@ int ED_vgroup_copy_array(Object *ob, Object *ob_from) return 1; } +/***********************Start weight transfer (WT)*********************************/ + +typedef enum WT_VertexGroupMode { + WT_REPLACE_ACTIVE_VERTEX_GROUP = 1, + WT_REPLACE_ALL_VERTEX_GROUPS = 2 +} WT_VertexGroupMode; + +typedef enum WT_Method { + WT_BY_INDEX = 1, + WT_BY_NEAREST_VERTEX = 2, + WT_BY_NEAREST_FACE = 3, + WT_BY_NEAREST_VERTEX_IN_FACE = 4 +} WT_Method; + +typedef enum WT_ReplaceMode { + WT_REPLACE_ALL_WEIGHTS = 1, + WT_REPLACE_EMPTY_WEIGHTS = 2 +} WT_ReplaceMode; + +static EnumPropertyItem WT_vertex_group_mode_item[] = { + {WT_REPLACE_ACTIVE_VERTEX_GROUP, "WT_REPLACE_ACTIVE_VERTEX_GROUP", 1, "Active", "Transfer active vertex group from selected to active mesh"}, + {WT_REPLACE_ALL_VERTEX_GROUPS, "WT_REPLACE_ALL_VERTEX_GROUPS", 1, "All", "Transfer all vertex groups from selected to active mesh"}, + {0, NULL, 0, NULL, NULL} +}; + +static EnumPropertyItem WT_method_item[] = { + {WT_BY_INDEX, "WT_BY_INDEX", 1, "Vertex index", "Copy for identical meshes"}, + {WT_BY_NEAREST_VERTEX, "WT_BY_NEAREST_VERTEX", 1, "Nearest vertex", "Copy weight from closest vertex"}, + {WT_BY_NEAREST_FACE, "WT_BY_NEAREST_FACE", 1, "Nearest face", "Barycentric interpolation from nearest face"}, + {WT_BY_NEAREST_VERTEX_IN_FACE, "WT_BY_NEAREST_VERTEX_IN_FACE", 1, "Nearest vertex in face", "Copy weight from closest vertex in nearest face"}, + {0, NULL, 0, NULL, NULL} +}; + +static EnumPropertyItem WT_replace_mode_item[] = { + {WT_REPLACE_ALL_WEIGHTS, "WT_REPLACE_ALL_WEIGHTS", 1, "All", "Overwrite all weights"}, + {WT_REPLACE_EMPTY_WEIGHTS, "WT_REPLACE_EMPTY_WEIGHTS", 1, "Empty", "Add weights to vertices with no weight"}, + {0, NULL, 0, NULL, NULL} +}; + +/*copy weight*/ +static void vgroup_transfer_weight(float *r_weight_dst, const float weight_src, const WT_ReplaceMode replace_mode) +{ + switch (replace_mode) { + case WT_REPLACE_ALL_WEIGHTS: + *r_weight_dst = weight_src; + break; + + case WT_REPLACE_EMPTY_WEIGHTS: + if (*r_weight_dst == 0.0f) { + *r_weight_dst = weight_src; + } + break; + + default: + BLI_assert(0); + break; + } +} + +/* could be exposed externally */ +static int ed_vgroup_transfer_weight(Object *ob_dst, Object *ob_src, bDeformGroup *dg_src, Scene *scene, + WT_Method method, WT_ReplaceMode replace_mode, wmOperator *op) +{ + bDeformGroup *dg_dst; + Mesh *me_dst, *me_src; + DerivedMesh *dmesh_src; + BVHTreeFromMesh tree_mesh_vertices_src, tree_mesh_faces_src = {NULL}; + MDeformVert **dv_array_src, **dv_array_dst, **dv_src, **dv_dst; + MVert *mv_dst, *mv_src; + MFace *mface_src, *mf; + BVHTreeNearest nearest; + MDeformWeight *dw_dst, *dw_src; + int dv_tot_src, dv_tot_dst, i, v_index, index_dst, index_src, index_nearest, index_nearest_vertex; + unsigned int f_index; + float weight, tmp_weight[4], tmp_co[3], normal[3], tmp_mat[4][4], dist_v1, dist_v2, dist_v3, dist_v4; + const int use_vert_sel = vertex_group_use_vert_sel(ob_dst); + + /* create new and overwrite vertex group on destination without data */ + if (!defgroup_find_name(ob_dst, dg_src->name)) { + ED_vgroup_delete(ob_dst, defgroup_find_name(ob_dst, dg_src->name)); + ED_vgroup_add_name(ob_dst, dg_src->name); + } + + /* get destination deformgroup */ + dg_dst = defgroup_find_name(ob_dst, dg_src->name); + + /* get meshes */ + dmesh_src = mesh_get_derived_deform(scene, ob_src, CD_MASK_BAREMESH); + me_dst = ob_dst->data; + me_src = ob_src->data; + + /* sanity check */ + if (!me_src->dvert) { + BKE_report(op->reports, RPT_ERROR, "Transfer failed (source mesh does not have any vertex groups)"); + return 0; + } + + /* create data in memory when nothing there */ + if (!me_dst->dvert) ED_vgroup_data_create(ob_dst->data); + + /* get vertex group arrays */ + ED_vgroup_give_parray(ob_src->data, &dv_array_src, &dv_tot_src, FALSE); + ED_vgroup_give_parray(ob_dst->data, &dv_array_dst, &dv_tot_dst, use_vert_sel); + + /* get indexes of vertex groups */ + index_src = BLI_findindex(&ob_src->defbase, dg_src); + index_dst = BLI_findindex(&ob_dst->defbase, dg_dst); + + /* get vertices */ + mv_dst = me_dst->mvert; + mv_src = dmesh_src->getVertArray(dmesh_src); + + /* prepare transformation matrix */ + invert_m4_m4(ob_src->imat, ob_src->obmat); + mult_m4_m4m4(tmp_mat, ob_src->imat, ob_dst->obmat); + + /* clear weights */ + if (replace_mode == WT_REPLACE_ALL_WEIGHTS) { + for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++) { + + if (*dv_dst == NULL) continue; + + dw_dst = defvert_find_index(*dv_dst, index_dst); + /* remove vertex from group */ + if (dw_dst) defvert_remove_group(*dv_dst, dw_dst); + } + } + + switch (method) { + + case WT_BY_INDEX: + /* check if indices are matching, delete and return if not */ + if (ob_dst == ob_src || dv_tot_dst == 0 || dv_tot_dst != dv_tot_src || + dv_array_src == NULL || dv_array_dst == NULL) + { + ED_vgroup_delete(ob_dst, defgroup_find_name(ob_dst, dg_dst->name)); + if (dv_array_src) MEM_freeN(dv_array_src); + if (dv_array_dst) MEM_freeN(dv_array_dst); + dmesh_src->release(dmesh_src); + BKE_report(op->reports, RPT_ERROR, "Transfer failed (indices are not matching)"); + return 0; + } + + /* loop through the vertices*/ + for (i = 0, dv_src = dv_array_src, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++, dv_src++, mv_src++, mv_dst++) { + + if (*dv_dst == NULL) { + continue; + } + + /* copy weight */ + dw_src = defvert_find_index(*dv_src, index_src); + if (dw_src && dw_src->weight) { + dw_dst = defvert_verify_index(*dv_dst, index_dst); + vgroup_transfer_weight(&dw_dst->weight, dw_src->weight, replace_mode); + } + } + break; + + case WT_BY_NEAREST_VERTEX: + /* make node tree */ + bvhtree_from_mesh_verts(&tree_mesh_vertices_src, dmesh_src, FLT_EPSILON, 2, 6); + + /* loop trough vertices */ + for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++, mv_dst++) { + + if (*dv_dst == NULL) { + continue; + } + + /* reset nearest */ + nearest.dist = FLT_MAX; + /* with current binary tree its marginally faster to start searching at the top, as opposed to previous search. */ + nearest.index = -1; + + /* transform into target space */ + mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co); + + /* node tree accelerated search for closest vetex */ + BLI_bvhtree_find_nearest(tree_mesh_vertices_src.tree, tmp_co, + &nearest, tree_mesh_vertices_src.nearest_callback, &tree_mesh_vertices_src); + + /* copy weight that are not NULL including weight value 0. Existing target weights are overwritten prior to this in relevant cases. */ + dw_src = defvert_find_index(dv_array_src[nearest.index], index_src); + if (dw_src && dw_src->weight) { + dw_dst = defvert_verify_index(*dv_dst, index_dst); + vgroup_transfer_weight(&dw_dst->weight, dw_src->weight, replace_mode); + } + } + + /* free memory */ + free_bvhtree_from_mesh(&tree_mesh_vertices_src); + break; + + case WT_BY_NEAREST_FACE: + /* get faces */ + DM_ensure_tessface(dmesh_src); + mface_src = dmesh_src->getTessFaceArray(dmesh_src); + + /* make node tree */ + bvhtree_from_mesh_faces(&tree_mesh_faces_src, dmesh_src, FLT_EPSILON, 2, 6); + + /* loop through the vertices */ + for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++, mv_dst++) { + + if (*dv_dst == NULL) { + continue; + } + + /* reset nearest */ + nearest.dist = FLT_MAX; + /* with current binary tree its marginally faster to start searching at the top, as opposed to previous search. */ + nearest.index = -1; + + /* transform into target space */ + mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co); + + /* node tree accelerated search for closest face */ + BLI_bvhtree_find_nearest(tree_mesh_faces_src.tree, tmp_co, + &nearest, tree_mesh_faces_src.nearest_callback, &tree_mesh_faces_src); + index_nearest = nearest.index; + + /* project onto face */ + mf = &mface_src[index_nearest]; + normal_tri_v3(normal, mv_src[mf->v1].co, mv_src[mf->v2].co, mv_src[mf->v3].co); + project_v3_plane(tmp_co, normal, mv_src[mf->v1].co); + + /* interpolate weights over face*/ + f_index = mf->v4 ? 3 : 2; + if (f_index == 3) { + interp_weights_face_v3(tmp_weight, mv_src[mf->v1].co, mv_src[mf->v2].co, mv_src[mf->v3].co, mv_src[mf->v4].co, tmp_co); + } + else { + interp_weights_face_v3(tmp_weight, mv_src[mf->v1].co, mv_src[mf->v2].co, mv_src[mf->v3].co, NULL, tmp_co); + } + + /* get weights from face*/ + weight = 0; + do { + v_index = (&mf->v1)[f_index]; + weight += tmp_weight[f_index] * defvert_find_weight(dv_array_src[v_index], index_src); + } while (f_index--); + + /* copy weight that are not NULL including weight value 0. Existing target weights are overwritten prior to this in relevant cases. */ + if (weight > 0) { + dw_dst = defvert_verify_index(*dv_dst, index_dst); + vgroup_transfer_weight(&dw_dst->weight, weight, replace_mode); + } + } + + /* free memory */ + free_bvhtree_from_mesh(&tree_mesh_faces_src); + break; + + case WT_BY_NEAREST_VERTEX_IN_FACE: + /* get faces */ + DM_ensure_tessface(dmesh_src); + mface_src = dmesh_src->getTessFaceArray(dmesh_src); + + /* make node tree */ + bvhtree_from_mesh_faces(&tree_mesh_faces_src, dmesh_src, FLT_EPSILON, 2, 6); + + /* loop through the vertices */ + for (i = 0, dv_dst = dv_array_dst; i < me_dst->totvert; i++, dv_dst++, mv_dst++) { + + if (*dv_dst == NULL) { + continue; + } + + /* reset nearest */ + nearest.dist = FLT_MAX; + /* With current binary tree its marginally faster to start searching at the top, as opposed to previous search. */ + nearest.index = -1; + + /* transform into target space */ + mul_v3_m4v3(tmp_co, tmp_mat, mv_dst->co); + + /* node tree accelerated search for closest face */ + BLI_bvhtree_find_nearest(tree_mesh_faces_src.tree, tmp_co, + &nearest, tree_mesh_faces_src.nearest_callback, &tree_mesh_faces_src); + index_nearest = nearest.index; + + /* get distances */ + mf = &mface_src[index_nearest]; + dist_v1 = len_squared_v3v3(tmp_co, mv_src[mf->v1].co); + dist_v2 = len_squared_v3v3(tmp_co, mv_src[mf->v2].co); + dist_v3 = len_squared_v3v3(tmp_co, mv_src[mf->v3].co); + + /* get closest vertex */ + f_index = mf->v4 ? 3 : 2; + if (dist_v1 < dist_v2 && dist_v1 < dist_v3) index_nearest_vertex = mf->v1; + else if (dist_v2 < dist_v3) index_nearest_vertex = mf->v2; + else index_nearest_vertex = mf->v3; + if (f_index == 3) { + dist_v4 = len_squared_v3v3(tmp_co, mv_src[mf->v4].co); + if (dist_v4 < dist_v1 && dist_v4 < dist_v2 && dist_v4 < dist_v3) { + index_nearest_vertex = mf->v4; + } + } + + /* copy weight that are not NULL including weight value 0. Existing target weights are overwritten prior to this in relevant cases. */ + dw_src = defvert_find_index(dv_array_src[index_nearest_vertex], index_src); + if (dw_src && dw_src->weight) { + dw_dst = defvert_verify_index(*dv_dst, index_dst); + vgroup_transfer_weight(&dw_dst->weight, dw_src->weight, replace_mode); + } + } + + /* free memory */ + free_bvhtree_from_mesh(&tree_mesh_faces_src); + break; + + default: + BLI_assert(0); + break; + } + + /*free memory*/ + if (dv_array_src) MEM_freeN(dv_array_src); + if (dv_array_dst) MEM_freeN(dv_array_dst); + dmesh_src->release(dmesh_src); + + return 1; +} + +/***********************End weight transfer (WT)***********************************/ /* for Mesh in Object mode */ /* allows editmode for Lattice */ @@ -580,7 +909,6 @@ void ED_vgroup_select_by_name(Object *ob, const char *name) static void vgroup_select_verts(Object *ob, int select) { const int def_nr = ob->actdef - 1; - MDeformVert *dv; if (!BLI_findlink(&ob->defbase, def_nr)) { return; @@ -596,7 +924,7 @@ static void vgroup_select_verts(Object *ob, int select) BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { - dv = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT); + MDeformVert *dv = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT); if (defvert_find_index(dv, def_nr)) { BM_vert_select_set(em->bm, eve, select); } @@ -604,7 +932,7 @@ static void vgroup_select_verts(Object *ob, int select) } /* this has to be called, because this function operates on vertices only */ - if (select) EDBM_select_flush(em); // vertices to edges/faces + if (select) EDBM_select_flush(em); /* vertices to edges/faces */ else EDBM_deselect_flush(em); } else { @@ -633,6 +961,7 @@ static void vgroup_select_verts(Object *ob, int select) Lattice *lt = vgroup_edit_lattice(ob); if (lt->dvert) { + MDeformVert *dv; BPoint *bp; int a, tot; @@ -704,7 +1033,7 @@ static void vgroup_normalize(Object *ob) int i, dvert_tot = 0; const int def_nr = ob->actdef - 1; - const int use_vert_sel = (ob->type == OB_MESH && ((Mesh *)ob->data)->editflag & ME_EDIT_VERT_SEL) != 0; + const int use_vert_sel = vertex_group_use_vert_sel(ob); if (!BLI_findlink(&ob->defbase, def_nr)) { return; @@ -724,7 +1053,7 @@ static void vgroup_normalize(Object *ob) dw = defvert_find_index(dv, def_nr); if (dw) { - weight_max = MAX2(dw->weight, weight_max); + weight_max = max_ff(dw->weight, weight_max); } } @@ -836,23 +1165,24 @@ static void getVerticalAndHorizontalChange(const float norm[3], float d, const f const float start[3], float distToStart, float *end, float (*changes)[2], float *dists, int index) { - // A=Q-((Q-P).N)N - // D = (a*x0 + b*y0 +c*z0 +d) + /* A = Q - ((Q - P).N)N + * D = (a * x0 + b * y0 +c * z0 + d) */ float projA[3], projB[3]; closest_to_plane_v3(projA, coord, norm, start); closest_to_plane_v3(projB, coord, norm, end); - // (vertical and horizontal refer to the plane's y and xz respectively) - // vertical distance + /* (vertical and horizontal refer to the plane's y and xz respectively) + * vertical distance */ dists[index] = dot_v3v3(norm, end) + d; - // vertical change + /* vertical change */ changes[index][0] = dists[index] - distToStart; //printf("vc %f %f\n", distance(end, projB, 3)-distance(start, projA, 3), changes[index][0]); - // horizontal change + /* horizontal change */ changes[index][1] = len_v3v3(projA, projB); } -// I need the derived mesh to be forgotten so the positions are recalculated with weight changes (see dm_deform_recalc) +/* I need the derived mesh to be forgotten so the positions are recalculated + * with weight changes (see dm_deform_recalc) */ static void dm_deform_clear(DerivedMesh *dm, Object *ob) { if (ob->derivedDeform && (ob->derivedDeform) == dm) { @@ -973,7 +1303,7 @@ static void moveCloserToDistanceFromPlane(Scene *scene, Object *ob, Mesh *me, in } } } - // sort the changes by the vertical change + /* sort the changes by the vertical change */ for (k = 0; k < totweight; k++) { float tf; int ti; @@ -985,7 +1315,7 @@ static void moveCloserToDistanceFromPlane(Scene *scene, Object *ob, Mesh *me, in bestIndex = i; } } - // switch with k + /* switch with k */ if (bestIndex != k) { ti = upDown[k]; upDown[k] = upDown[bestIndex]; @@ -1109,7 +1439,7 @@ static void vgroup_levels(Object *ob, float offset, float gain) int i, dvert_tot = 0; const int def_nr = ob->actdef - 1; - const int use_vert_sel = (ob->type == OB_MESH && ((Mesh *)ob->data)->editflag & ME_EDIT_VERT_SEL) != 0; + const int use_vert_sel = vertex_group_use_vert_sel(ob); if (!BLI_findlink(&ob->defbase, def_nr)) { return; @@ -1143,7 +1473,7 @@ static void vgroup_normalize_all(Object *ob, int lock_active) int i, dvert_tot = 0; const int def_nr = ob->actdef - 1; - const int use_vert_sel = (ob->type == OB_MESH && ((Mesh *)ob->data)->editflag & ME_EDIT_VERT_SEL) != 0; + const int use_vert_sel = vertex_group_use_vert_sel(ob); if (lock_active && !BLI_findlink(&ob->defbase, def_nr)) { return; @@ -1221,7 +1551,7 @@ static void vgroup_invert(Object *ob, const short auto_assign, const short auto_ MDeformVert *dv, **dvert_array = NULL; int i, dvert_tot = 0; const int def_nr = ob->actdef - 1; - const int use_vert_sel = (ob->type == OB_MESH && ((Mesh *)ob->data)->editflag & ME_EDIT_VERT_SEL) != 0; + const int use_vert_sel = vertex_group_use_vert_sel(ob); if (!BLI_findlink(&ob->defbase, def_nr)) { return; @@ -1312,11 +1642,11 @@ static void vgroup_blend(Object *ob, const float fac) /* i1 is always the selected one */ if (sel1) { i1 = BM_elem_index_get(eed->v1); - /* i2= BM_elem_index_get(eed->v2); */ /* UNUSED */ + /* i2 = BM_elem_index_get(eed->v2); */ /* UNUSED */ eve = eed->v2; } else { - /* i2= BM_elem_index_get(eed->v1); */ /* UNUSED */ + /* i2 = BM_elem_index_get(eed->v1); */ /* UNUSED */ i1 = BM_elem_index_get(eed->v2); eve = eed->v1; } @@ -1389,13 +1719,119 @@ static void vgroup_blend(Object *ob, const float fac) } } +static int inv_cmp_mdef_vert_weights(const void *a1, const void *a2) +{ + /* qsort sorts in ascending order. We want descending order to save a memcopy + * so this compare function is inverted from the standard greater than comparison qsort needs. + * A normal compare function is called with two pointer arguments and should return an integer less than, equal to, + * or greater than zero corresponding to whether its first argument is considered less than, equal to, + * or greater than its second argument. This does the opposite. */ + const struct MDeformWeight *dw1 = a1, *dw2 = a2; + + if (dw1->weight < dw2->weight) return 1; + else if (dw1->weight > dw2->weight) return -1; + else if (&dw1 < &dw2) return 1; /* compare addresses so we have a stable sort algorithm */ + else return -1; +} + +/* Used for limiting the number of influencing bones per vertex when exporting + * skinned meshes. if all_deform_weights is True, limit all deform modifiers + * to max_weights regardless of type, otherwise, only limit the number of influencing bones per vertex*/ +static int vertex_group_limit_total(Object *ob, + const int max_weights, + const int all_deform_weights) +{ + MDeformVert *dv, **dvert_array = NULL; + int i, dvert_tot = 0; + const int use_vert_sel = vertex_group_use_vert_sel(ob); + int is_change = FALSE; + + ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, use_vert_sel); + + if (dvert_array) { + int defbase_tot = BLI_countlist(&ob->defbase); + const char *vgroup_validmap = (all_deform_weights == FALSE) ? + BKE_objdef_validmap_get(ob, defbase_tot) : + NULL; + int num_to_drop = 0; + + /* only the active group */ + for (i = 0; i < dvert_tot; i++) { + + /* in case its not selected */ + if (!(dv = dvert_array[i])) { + continue; + } + + if (all_deform_weights) { + /* keep only the largest weights, discarding the rest + * qsort will put array in descending order because of invCompare function */ + num_to_drop = dv->totweight - max_weights; + if (num_to_drop > 0) { + qsort(dv->dw, dv->totweight, sizeof(MDeformWeight), inv_cmp_mdef_vert_weights); + dv->dw = MEM_reallocN(dv->dw, sizeof(MDeformWeight) * max_weights); + dv->totweight = max_weights; + is_change = TRUE; + } + } + else { + MDeformWeight *dw_temp; + int bone_count = 0, non_bone_count = 0; + int j; + /* only consider vgroups with bone modifiers attached (in vgroup_validmap) */ + + num_to_drop = dv->totweight - max_weights; + + /* first check if we even need to test further */ + if (num_to_drop > 0) { + /* re-pack dw array so that non-bone weights are first, bone-weighted verts at end + * sort the tail, then copy only the truncated array back to dv->dw */ + dw_temp = MEM_mallocN(sizeof(MDeformWeight) * (dv->totweight), __func__); + bone_count = 0; non_bone_count = 0; + for (j = 0; j < dv->totweight; j++) { + BLI_assert(dv->dw[j].def_nr < defbase_tot); + if (!vgroup_validmap[(dv->dw[j]).def_nr]) { + dw_temp[non_bone_count] = dv->dw[j]; + non_bone_count += 1; + } + else { + dw_temp[dv->totweight - 1 - bone_count] = dv->dw[j]; + bone_count += 1; + } + } + BLI_assert(bone_count + non_bone_count == dv->totweight); + num_to_drop = bone_count - max_weights; + if (num_to_drop > 0) { + qsort(&dw_temp[non_bone_count], bone_count, sizeof(MDeformWeight), inv_cmp_mdef_vert_weights); + dv->totweight -= num_to_drop; + /* Do we want to clean/normalize here? */ + MEM_freeN(dv->dw); + dv->dw = MEM_reallocN(dw_temp, sizeof(MDeformWeight) * dv->totweight); + is_change = TRUE; + } + else { + MEM_freeN(dw_temp); + } + } + } + } + MEM_freeN(dvert_array); + + if (vgroup_validmap) { + MEM_freeN((void *)vgroup_validmap); + } + } + + return is_change; +} + static void vgroup_clean(Object *ob, const float epsilon, int keep_single) { MDeformWeight *dw; MDeformVert *dv, **dvert_array = NULL; int i, dvert_tot = 0; const int def_nr = ob->actdef - 1; - const int use_vert_sel = (ob->type == OB_MESH && ((Mesh *)ob->data)->editflag & ME_EDIT_VERT_SEL) != 0; + const int use_vert_sel = vertex_group_use_vert_sel(ob); if (!BLI_findlink(&ob->defbase, def_nr)) { return; @@ -1431,7 +1867,7 @@ static void vgroup_clean_all(Object *ob, const float epsilon, const int keep_sin { MDeformVert **dvert_array = NULL; int i, dvert_tot = 0; - const int use_vert_sel = (ob->type == OB_MESH && ((Mesh *)ob->data)->editflag & ME_EDIT_VERT_SEL) != 0; + const int use_vert_sel = vertex_group_use_vert_sel(ob); ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, use_vert_sel); @@ -2007,7 +2443,6 @@ static void vgroup_delete_all(Object *ob) /* only in editmode */ static void vgroup_assign_verts(Object *ob, const float weight) { - MDeformVert *dv; const int def_nr = ob->actdef - 1; if (!BLI_findlink(&ob->defbase, def_nr)) @@ -2027,6 +2462,7 @@ static void vgroup_assign_verts(Object *ob, const float weight) /* Go through the list of editverts and assign them */ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + MDeformVert *dv; MDeformWeight *dw; dv = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT); /* can be NULL */ dw = defvert_verify_index(dv, def_nr); @@ -2061,6 +2497,7 @@ static void vgroup_assign_verts(Object *ob, const float weight) } else if (ob->type == OB_LATTICE) { Lattice *lt = vgroup_edit_lattice(ob); + MDeformVert *dv; BPoint *bp; int a, tot; @@ -2665,6 +3102,47 @@ void OBJECT_OT_vertex_group_clean(wmOperatorType *ot) "Keep verts assigned to at least one group when cleaning"); } +static int vertex_group_limit_total_exec(bContext *C, wmOperator *op) +{ + Object *ob = ED_object_context(C); + + const int limit = RNA_int_get(op->ptr, "limit"); + const int all_deform_weights = RNA_boolean_get(op->ptr, "all_deform_weights"); + + if (vertex_group_limit_total(ob, limit, all_deform_weights)) { + + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + + return OPERATOR_FINISHED; + } + else { + BKE_report(op->reports, RPT_WARNING, "No vertex groups limited"); + + /* note, would normally return cancelled, except we want the redo + * UI to show up for users to change */ + return OPERATOR_FINISHED; + } +} + +void OBJECT_OT_vertex_group_limit_total(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Limit Number of Weights per Vertex"; + ot->idname = "OBJECT_OT_vertex_group_limit_total"; + ot->description = "Limit deform weights associated with a vertex to a specified number by removing lowest weights"; + + /* api callbacks */ + ot->poll = vertex_group_poll; + ot->exec = vertex_group_limit_total_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_int(ot->srna, "limit", 4, 1, 32, "Limit", "Maximum number of deform weights", 1, 32); + RNA_def_boolean(ot->srna, "all_deform_weights", FALSE, "All Deform Weights", "Cull all deform weights, not just bones"); +} static int vertex_group_mirror_exec(bContext *C, wmOperator *op) { @@ -2762,14 +3240,13 @@ static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op) if ((change == 0 && fail == 0) || fail) { BKE_reportf(op->reports, RPT_ERROR, - "Copy to VGroups to Selected warning done %d, failed %d, object data must have matching indices", + "Copy VGroups to Selected warning, %d done, %d failed (object data must have matching indices)", change, fail); } return OPERATOR_FINISHED; } - void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot) { /* identifiers */ @@ -2785,6 +3262,86 @@ void OBJECT_OT_vertex_group_copy_to_selected(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +static int vertex_group_transfer_weight_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *ob_act = CTX_data_active_object(C); + bDeformGroup *dg_src; + int fail = 0; + + WT_VertexGroupMode vertex_group_mode = RNA_enum_get(op->ptr, "WT_vertex_group_mode"); + WT_Method method = RNA_enum_get(op->ptr, "WT_method"); + WT_ReplaceMode replace_mode = RNA_enum_get(op->ptr, "WT_replace_mode"); + + /* Macro to loop through selected objects and perform operation depending on function, option and method */ + CTX_DATA_BEGIN (C, Object *, ob_slc, selected_editable_objects) + { + + if (ob_act != ob_slc && ob_slc->defbase.first) { + switch (vertex_group_mode) { + + case WT_REPLACE_ACTIVE_VERTEX_GROUP: + if (!ed_vgroup_transfer_weight(ob_act, ob_slc, + BLI_findlink(&ob_slc->defbase, ob_slc->actdef - 1), + scene, method, replace_mode, op)) + { + fail++; + } + break; + + case WT_REPLACE_ALL_VERTEX_GROUPS: + for (dg_src = ob_slc->defbase.first; dg_src; dg_src = dg_src->next) { + if (!ed_vgroup_transfer_weight(ob_act, ob_slc, + dg_src, scene, method, replace_mode, op)) + { + fail++; + } + } + break; + + default: + BLI_assert(0); + break; + } + } + } + + /* Event notifiers for correct display of data */ + DAG_id_tag_update(&ob_slc->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_slc); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob_slc->data); + + CTX_DATA_END; + + if (fail != 0) { + return OPERATOR_CANCELLED; + } + else { + return OPERATOR_FINISHED; + } +} + +/* transfers weight from active to selected */ +void OBJECT_OT_vertex_group_transfer_weight(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Transfer Weights"; + ot->idname = "OBJECT_OT_vertex_group_transfer_weight"; + ot->description = "Transfer weight paint to active from selected mesh"; + + /* api callbacks */ + ot->poll = vertex_group_poll; + ot->exec = vertex_group_transfer_weight_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "WT_vertex_group_mode", WT_vertex_group_mode_item, 1, "Group", ""); + ot->prop = RNA_def_enum(ot->srna, "WT_method", WT_method_item, 3, "Method", ""); + ot->prop = RNA_def_enum(ot->srna, "WT_replace_mode", WT_replace_mode_item, 1, "Replace", ""); +} + static EnumPropertyItem vgroup_items[] = { {0, NULL, 0, NULL, NULL} }; @@ -2904,7 +3461,7 @@ static int vgroup_do_remap(Object *ob, char *name_array, wmOperator *op) } } else { - BKE_report(op->reports, RPT_ERROR, "Editmode lattice isn't supported yet"); + BKE_report(op->reports, RPT_ERROR, "Editmode lattice is not supported yet"); MEM_freeN(sort_map_update); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/physics/CMakeLists.txt b/source/blender/editors/physics/CMakeLists.txt index 4d43c618568..da12a26e747 100644 --- a/source/blender/editors/physics/CMakeLists.txt +++ b/source/blender/editors/physics/CMakeLists.txt @@ -20,6 +20,7 @@ set(INC ../include + ../../blenfont ../../blenkernel ../../blenlib ../../blenloader @@ -54,4 +55,8 @@ if(WITH_OPENMP) add_definitions(-DPARALLEL=1) endif() +if(WITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) +endif() + blender_add_lib(bf_editor_physics "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/physics/SConscript b/source/blender/editors/physics/SConscript index 9fe6cff4349..fffe05d6a0d 100644 --- a/source/blender/editors/physics/SConscript +++ b/source/blender/editors/physics/SConscript @@ -3,12 +3,12 @@ Import ('env') sources = env.Glob('*.c') -incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' +incs = '../include ../../blenfont ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../gpu ../../blenloader ../../bmesh' incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern' -defs = '' +defs = [] if env['OURPLATFORM'] == 'linux': cflags='-pthread' @@ -17,9 +17,11 @@ if env['OURPLATFORM'] == 'linux': if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): incs += ' ' + env['BF_PTHREADS_INC'] - if env['OURPLATFORM'] == 'darwin': if env['WITH_BF_OPENMP']: - defs += ' PARALLEL=1' + defs.append('PARALLEL=1') -env.BlenderLib ( 'bf_editors_physics', sources, Split(incs), Split(defs), libtype=['core'], priority=[45] ) +if env['WITH_BF_INTERNATIONAL']: + defs.append('WITH_INTERNATIONAL') + +env.BlenderLib ( 'bf_editors_physics', sources, Split(incs), defs, libtype=['core'], priority=[45] ) diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c index 70fe87e5c01..c51b3ca4c43 100644 --- a/source/blender/editors/physics/dynamicpaint_ops.c +++ b/source/blender/editors/physics/dynamicpaint_ops.c @@ -26,6 +26,8 @@ #include "BLI_string.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "DNA_dynamicpaint_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" @@ -73,9 +75,9 @@ static int surface_slot_add_exec(bContext *C, wmOperator *UNUSED(op)) /* set preview for this surface only and set active */ canvas->active_sur = 0; - for (surface=surface->prev; surface; surface=surface->prev) { - surface->flags &= ~MOD_DPAINT_PREVIEW; - canvas->active_sur++; + for (surface = surface->prev; surface; surface = surface->prev) { + surface->flags &= ~MOD_DPAINT_PREVIEW; + canvas->active_sur++; } return OPERATOR_FINISHED; @@ -94,26 +96,26 @@ void DPAINT_OT_surface_slot_add(wmOperatorType *ot) ot->poll = ED_operator_object_active_editable; /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } static int surface_slot_remove_exec(bContext *C, wmOperator *UNUSED(op)) { DynamicPaintModifierData *pmd = NULL; - Object *cObject = ED_object_context(C); + Object *obj_ctx = ED_object_context(C); DynamicPaintCanvasSettings *canvas; DynamicPaintSurface *surface; - int id=0; + int id = 0; /* Make sure we're dealing with a canvas */ - pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint); + pmd = (DynamicPaintModifierData *)modifiers_findByType(obj_ctx, eModifierType_DynamicPaint); if (!pmd || !pmd->canvas) return OPERATOR_CANCELLED; canvas = pmd->canvas; surface = canvas->surfaces.first; /* find active surface and remove it */ - for (; surface; surface=surface->next) { + for (; surface; surface = surface->next) { if (id == canvas->active_sur) { canvas->active_sur -= 1; dynamicPaint_freeSurface(surface); @@ -123,8 +125,8 @@ static int surface_slot_remove_exec(bContext *C, wmOperator *UNUSED(op)) } dynamicPaint_resetPreview(canvas); - DAG_id_tag_update(&cObject->id, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, cObject); + DAG_id_tag_update(&obj_ctx->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obj_ctx); return OPERATOR_FINISHED; } @@ -142,7 +144,7 @@ void DPAINT_OT_surface_slot_remove(wmOperatorType *ot) ot->poll = ED_operator_object_active_editable; /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } static int type_toggle_exec(bContext *C, wmOperator *op) @@ -151,7 +153,7 @@ static int type_toggle_exec(bContext *C, wmOperator *op) Object *cObject = ED_object_context(C); Scene *scene = CTX_data_scene(C); DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint); - int type= RNA_enum_get(op->ptr, "type"); + int type = RNA_enum_get(op->ptr, "type"); if (!pmd) return OPERATOR_CANCELLED; @@ -170,7 +172,7 @@ static int type_toggle_exec(bContext *C, wmOperator *op) /* update dependency */ DAG_id_tag_update(&cObject->id, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, cObject); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, cObject); DAG_scene_sort(CTX_data_main(C), scene); return OPERATOR_FINISHED; @@ -190,10 +192,10 @@ void DPAINT_OT_type_toggle(wmOperatorType *ot) ot->poll = ED_operator_object_active_editable; /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - prop= RNA_def_enum(ot->srna, "type", prop_dynamicpaint_type_items, MOD_DYNAMICPAINT_TYPE_CANVAS, "Type", ""); + prop = RNA_def_enum(ot->srna, "type", prop_dynamicpaint_type_items, MOD_DYNAMICPAINT_TYPE_CANVAS, "Type", ""); ot->prop = prop; } @@ -203,7 +205,7 @@ static int output_toggle_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); DynamicPaintSurface *surface; DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint); - int output= RNA_enum_get(op->ptr, "output"); /* currently only 1/0 */ + int output = RNA_enum_get(op->ptr, "output"); /* currently only 1/0 */ if (!pmd || !pmd->canvas) return OPERATOR_CANCELLED; surface = get_activeSurface(pmd->canvas); @@ -258,7 +260,7 @@ void DPAINT_OT_output_toggle(wmOperatorType *ot) ot->poll = ED_operator_object_active_editable; /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ ot->prop = RNA_def_enum(ot->srna, "output", prop_output_toggle_types, 0, "Output Toggle", ""); @@ -274,13 +276,16 @@ void DPAINT_OT_output_toggle(wmOperatorType *ot) static int dynamicPaint_bakeImageSequence(bContext *C, DynamicPaintSurface *surface, Object *cObject) { DynamicPaintCanvasSettings *canvas = surface->canvas; - Scene *scene= CTX_data_scene(C); + Scene *scene = CTX_data_scene(C); wmWindow *win = CTX_wm_window(C); int frame = 1; int frames; frames = surface->end_frame - surface->start_frame + 1; - if (frames <= 0) {BLI_strncpy(canvas->error, "No frames to bake.", sizeof(canvas->error)); return 0;} + if (frames <= 0) { + BLI_strncpy(canvas->error, N_("No frames to bake"), sizeof(canvas->error)); + return 0; + } /* Set frame to start point (also inits modifier data) */ frame = surface->start_frame; @@ -291,7 +296,7 @@ static int dynamicPaint_bakeImageSequence(bContext *C, DynamicPaintSurface *surf if (!dynamicPaint_createUVSurface(surface)) return 0; /* Loop through selected frames */ - for (frame=surface->start_frame; frame<=surface->end_frame; frame++) { + for (frame = surface->start_frame; frame <= surface->end_frame; frame++) { float progress = (frame - surface->start_frame) / (float)frames * 100; surface->current_frame = frame; @@ -346,7 +351,6 @@ static int dynamicPaint_initBake(struct bContext *C, struct wmOperator *op) Object *ob = ED_object_context(C); int status = 0; double timer = PIL_check_seconds_timer(); - char result_str[80]; DynamicPaintSurface *surface; /* @@ -354,14 +358,14 @@ static int dynamicPaint_initBake(struct bContext *C, struct wmOperator *op) */ pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint); if (!pmd) { - BKE_report(op->reports, RPT_ERROR, "Bake Failed: No Dynamic Paint modifier found."); + BKE_report(op->reports, RPT_ERROR, "Bake failed: no Dynamic Paint modifier found"); return 0; } /* Make sure we're dealing with a canvas */ canvas = pmd->canvas; if (!canvas) { - BKE_report(op->reports, RPT_ERROR, "Bake Failed: Invalid Canvas."); + BKE_report(op->reports, RPT_ERROR, "Bake failed: invalid canvas"); return 0; } surface = get_activeSurface(canvas); @@ -381,23 +385,20 @@ static int dynamicPaint_initBake(struct bContext *C, struct wmOperator *op) /* Bake was successful: * Report for ended bake and how long it took */ if (status) { - /* Format time string */ + /* Format time string */ char time_str[30]; double time = PIL_check_seconds_timer() - timer; BLI_timestr(time, time_str); /* Show bake info */ - BLI_snprintf(result_str, sizeof(result_str), "Bake Complete! (%s)", time_str); - BKE_report(op->reports, RPT_INFO, result_str); + BKE_reportf(op->reports, RPT_INFO, "Bake complete! (%s)", time_str); } else { - if (strlen(canvas->error)) { /* If an error occured */ - BLI_snprintf(result_str, sizeof(result_str), "Bake Failed: %s", canvas->error); - BKE_report(op->reports, RPT_ERROR, result_str); + if (strlen(canvas->error)) { /* If an error occurred */ + BKE_reportf(op->reports, RPT_ERROR, "Bake failed: %s", canvas->error); } - else { /* User canceled the bake */ - BLI_strncpy(result_str, "Baking Cancelled!", sizeof(result_str)); - BKE_report(op->reports, RPT_WARNING, result_str); + else { /* User canceled the bake */ + BKE_report(op->reports, RPT_WARNING, "Baking canceled!"); } } diff --git a/source/blender/editors/physics/particle_boids.c b/source/blender/editors/physics/particle_boids.c index aff66b272fe..dc309ec3c31 100644 --- a/source/blender/editors/physics/particle_boids.c +++ b/source/blender/editors/physics/particle_boids.c @@ -273,7 +273,7 @@ static int state_del_exec(bContext *C, wmOperator *UNUSED(op)) /* there must be at least one state */ if (!part->boids->states.first) { state = boid_new_state(part->boids); - BLI_addtail(&part->boids->states, state); + BLI_addtail(&part->boids->states, state); } else state = part->boids->states.first; diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index b7ce32aa10a..f8ec51c7a7c 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -328,7 +328,7 @@ void PE_hide_keys_time(Scene *scene, PTCacheEdit *edit, float cfra) static int pe_x_mirror(Object *ob) { if (ob->type == OB_MESH) - return (((Mesh*)ob->data)->editflag & ME_EDIT_MIRROR_X); + return (((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X); return 0; } @@ -398,41 +398,41 @@ static void PE_set_view3d_data(bContext *C, PEData *data) /*************************** selection utilities *******************************/ -static int key_test_depth(PEData *data, const float co[3]) +static int key_test_depth(PEData *data, const float co[3], const int screen_co[2]) { View3D *v3d= data->vc.v3d; double ux, uy, uz; float depth; - short wco[3], x, y; /* nothing to do */ if ((v3d->drawtype<=OB_WIRE) || (v3d->flag & V3D_ZBUF_SELECT)==0) return 1; - project_short(data->vc.ar, co, wco); - - if (wco[0] == IS_CLIPPED) + /* used to calculate here but all callers have the screen_co already, so pass as arg */ +#if 0 + if (ED_view3d_project_int_global(data->vc.ar, co, screen_co, + V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN) != V3D_PROJ_RET_OK) + { return 0; + } +#endif gluProject(co[0], co[1], co[2], data->mats.modelview, data->mats.projection, (GLint *)data->mats.viewport, &ux, &uy, &uz); - x=wco[0]; - y=wco[1]; - #if 0 /* works well but too slow on some systems [#23118] */ - x+= (short)data->vc.ar->winrct.xmin; - y+= (short)data->vc.ar->winrct.ymin; + screen_co[0] += (short)data->vc.ar->winrct.xmin; + screen_co[1] += (short)data->vc.ar->winrct.ymin; /* PE_set_view3d_data calls this. no need to call here */ /* view3d_validate_backbuf(&data->vc); */ - glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth); + glReadPixels(screen_co[0], screen_co[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth); #else /* faster to use depths, these are calculated in PE_set_view3d_data */ { ViewDepths *vd = data->vc.rv3d->depths; assert(vd && vd->depths); /* we know its not clipped */ - depth= vd->depths[y * vd->w + x]; + depth = vd->depths[screen_co[1] * vd->w + screen_co[0]]; } #endif @@ -445,21 +445,21 @@ static int key_test_depth(PEData *data, const float co[3]) static int key_inside_circle(PEData *data, float rad, const float co[3], float *distance) { float dx, dy, dist; - int sco[2]; + int screen_co[2]; - project_int(data->vc.ar, co, sco); - - if (sco[0] == IS_CLIPPED) + /* TODO, should this check V3D_PROJ_TEST_CLIP_BB too? */ + if (ED_view3d_project_int_global(data->vc.ar, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) != V3D_PROJ_RET_OK) { return 0; - - dx= data->mval[0] - sco[0]; - dy= data->mval[1] - sco[1]; + } + + dx= data->mval[0] - screen_co[0]; + dy= data->mval[1] - screen_co[1]; dist= sqrt(dx*dx + dy*dy); if (dist > rad) return 0; - if (key_test_depth(data, co)) { + if (key_test_depth(data, co, screen_co)) { if (distance) *distance=dist; @@ -471,17 +471,16 @@ static int key_inside_circle(PEData *data, float rad, const float co[3], float * static int key_inside_rect(PEData *data, const float co[3]) { - int sco[2]; + int screen_co[2]; - project_int(data->vc.ar, co, sco); - - if (sco[0] == IS_CLIPPED) + if (ED_view3d_project_int_global(data->vc.ar, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) != V3D_PROJ_RET_OK) { return 0; + } - if (sco[0] > data->rect->xmin && sco[0] < data->rect->xmax && - sco[1] > data->rect->ymin && sco[1] < data->rect->ymax) + if (screen_co[0] > data->rect->xmin && screen_co[0] < data->rect->xmax && + screen_co[1] > data->rect->ymin && screen_co[1] < data->rect->ymax) { - return key_test_depth(data, co); + return key_test_depth(data, co, screen_co); } return 0; @@ -604,7 +603,7 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected ParticleSystemModifierData *psmd = NULL; ParticleEditSettings *pset= PE_settings(data->scene); POINT_P; KEY_K; - float mat[4][4]= MAT4_UNITY, imat[4][4]= MAT4_UNITY; + float mat[4][4] = MAT4_UNITY, imat[4][4] = MAT4_UNITY; if (edit->psys) psmd= psys_get_modifier(data->ob, edit->psys); @@ -674,7 +673,7 @@ static void foreach_point(PEData *data, ForPointFunc func) PTCacheEdit *edit = data->edit; POINT_P; - LOOP_POINTS { + LOOP_POINTS { func(data, p); } } @@ -745,15 +744,15 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys) psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat); copy_v3_v3(co, key->co); mul_m4_v3(mat, co); - co[0]= -co[0]; + co[0] = -co[0]; index= BLI_kdtree_find_nearest(tree, co, NULL, &nearest); /* this needs a custom threshold still, duplicated for editmode mirror */ if (index != -1 && index != p && (nearest.dist <= 0.0002f)) - edit->mirror_cache[p]= index; + edit->mirror_cache[p] = index; else - edit->mirror_cache[p]= -1; + edit->mirror_cache[p] = -1; } /* make sure mirrors are in two directions */ @@ -761,7 +760,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys) if (edit->mirror_cache[p]) { index= edit->mirror_cache[p]; if (edit->mirror_cache[index] != p) - edit->mirror_cache[p]= -1; + edit->mirror_cache[p] = -1; } } @@ -830,7 +829,7 @@ static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys for (k=0; ktotkey; k++, hkey++, mhkey++, key++, mkey++) { copy_v3_v3(mhkey->co, hkey->co); mul_m4_v3(mat, mhkey->co); - mhkey->co[0]= -mhkey->co[0]; + mhkey->co[0] = -mhkey->co[0]; mul_m4_v3(immat, mhkey->co); if (key->flag & PEK_TAG) @@ -987,9 +986,9 @@ static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit) PTCacheEditKey *key; int j, k; float tlen; - float dv0[3]= {0.0f, 0.0f, 0.0f}; - float dv1[3]= {0.0f, 0.0f, 0.0f}; - float dv2[3]= {0.0f, 0.0f, 0.0f}; + float dv0[3] = {0.0f, 0.0f, 0.0f}; + float dv1[3] = {0.0f, 0.0f, 0.0f}; + float dv2[3] = {0.0f, 0.0f, 0.0f}; if (edit==0 || (pset->flag & PE_KEEP_LENGTHS)==0) return; @@ -1004,12 +1003,12 @@ static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit) if (pset->flag & PE_LOCK_FIRST) { key= point->keys + 1; k= 1; - dv1[0]= dv1[1]= dv1[2]= 0.0; + dv1[0] = dv1[1] = dv1[2] = 0.0; } else { key= point->keys; k= 0; - dv0[0]= dv0[1]= dv0[2]= 0.0; + dv0[0] = dv0[1] = dv0[2] = 0.0; } for (; ktotkey; k++, key++) { @@ -1528,8 +1527,8 @@ static int select_linked_exec(bContext *C, wmOperator *op) int location[2]; RNA_int_get_array(op->ptr, "location", location); - mval[0]= location[0]; - mval[1]= location[1]; + mval[0] = location[0]; + mval[1] = location[1]; PE_set_view3d_data(C, &data); data.mval= mval; @@ -1634,7 +1633,7 @@ int PE_circle_select(bContext *C, int selecting, const int mval[2], float rad) /************************ lasso select operator ************************/ -int PE_lasso_select(bContext *C, int mcords[][2], short moves, short extend, short select) +int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, short extend, short select) { Scene *scene= CTX_data_scene(C); Object *ob= CTX_data_active_object(C); @@ -1644,8 +1643,8 @@ int PE_lasso_select(bContext *C, int mcords[][2], short moves, short extend, sho ParticleSystem *psys = edit->psys; ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); POINT_P; KEY_K; - float co[3], mat[4][4]= MAT4_UNITY; - int vertco[2]; + float co[3], mat[4][4] = MAT4_UNITY; + int screen_co[2]; PEData data; @@ -1666,9 +1665,9 @@ int PE_lasso_select(bContext *C, int mcords[][2], short moves, short extend, sho LOOP_KEYS { copy_v3_v3(co, key->co); mul_m4_v3(mat, co); - project_int(ar, co, vertco); - if (BLI_lasso_is_point_inside(mcords, moves, vertco[0], vertco[1], IS_CLIPPED) && - key_test_depth(&data, co)) + if ((ED_view3d_project_int_global(ar, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_OK) && + BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], IS_CLIPPED) && + key_test_depth(&data, co, screen_co)) { if (select && !(key->flag & PEK_SELECT)) { key->flag |= PEK_SELECT; @@ -1686,9 +1685,9 @@ int PE_lasso_select(bContext *C, int mcords[][2], short moves, short extend, sho copy_v3_v3(co, key->co); mul_m4_v3(mat, co); - project_int(ar, co, vertco); - if (BLI_lasso_is_point_inside(mcords, moves, vertco[0], vertco[1], IS_CLIPPED) && - key_test_depth(&data, co)) + if ((ED_view3d_project_int_global(ar, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_OK) && + BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], IS_CLIPPED) && + key_test_depth(&data, co, screen_co)) { if (select && !(key->flag & PEK_SELECT)) { key->flag |= PEK_SELECT; @@ -2415,7 +2414,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) if (totremoved == 0) return OPERATOR_CANCELLED; - BKE_reportf(op->reports, RPT_INFO, "Remove %d double particles", totremoved); + BKE_reportf(op->reports, RPT_INFO, "Removed %d double particles", totremoved); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob); @@ -2536,7 +2535,7 @@ static void toggle_particle_cursor(bContext *C, int enable) enum { DEL_PARTICLE, DEL_KEY }; -static EnumPropertyItem delete_type_items[]= { +static EnumPropertyItem delete_type_items[] = { {DEL_PARTICLE, "PARTICLE", 0, "Particle", ""}, {DEL_KEY, "KEY", 0, "Key", ""}, {0, NULL, 0, NULL, NULL}}; @@ -2602,7 +2601,7 @@ void PARTICLE_OT_delete(wmOperatorType *ot) static void PE_mirror_x(Scene *scene, Object *ob, int tagged) { - Mesh *me= (Mesh*)(ob->data); + Mesh *me= (Mesh *)(ob->data); ParticleSystemModifierData *psmd; PTCacheEdit *edit= PE_get_current(scene, ob); ParticleSystem *psys = edit->psys; @@ -2692,10 +2691,10 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged) /* rotate weights according to vertex index rotation */ rotation= mirrorfaces[pa->num*2+1]; - newpa->fuv[0]= pa->fuv[2]; - newpa->fuv[1]= pa->fuv[1]; - newpa->fuv[2]= pa->fuv[0]; - newpa->fuv[3]= pa->fuv[3]; + newpa->fuv[0] = pa->fuv[2]; + newpa->fuv[1] = pa->fuv[1]; + newpa->fuv[2] = pa->fuv[0]; + newpa->fuv[3] = pa->fuv[3]; while (rotation-- > 0) if (me->mface[pa->num].v4) { SHIFT4(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2], newpa->fuv[3]); @@ -2789,7 +2788,7 @@ static void brush_cut(PEData *data, int pa_index) float rad2, cut_time= 1.0; float x0, x1, v0, v1, o0, o1, xo0, xo1, d, dv; int k, cut, keys= (int)pow(2.0, (double)pset->draw_step); - int vertco[2]; + int screen_co[2]; /* blunt scissors */ if (BLI_frand() > data->cutfac) return; @@ -2798,13 +2797,15 @@ static void brush_cut(PEData *data, int pa_index) if (edit->points[pa_index].flag & PEP_HIDE) return; + if (ED_view3d_project_int_global(ar, key->co, screen_co, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) + return; + rad2= data->rad * data->rad; cut=0; - project_int_noclip(ar, key->co, vertco); - x0= (float)vertco[0]; - x1= (float)vertco[1]; + x0 = (float)screen_co[0]; + x1 = (float)screen_co[1]; o0= (float)data->mval[0]; o1= (float)data->mval[1]; @@ -2813,26 +2814,27 @@ static void brush_cut(PEData *data, int pa_index) xo1= x1 - o1; /* check if root is inside circle */ - if (xo0*xo0 + xo1*xo1 < rad2 && key_test_depth(data, key->co)) { + if (xo0*xo0 + xo1*xo1 < rad2 && key_test_depth(data, key->co, screen_co)) { cut_time= -1.0f; cut= 1; } else { /* calculate path time closest to root that was inside the circle */ for (k=1, key++; k<=keys; k++, key++) { - project_int_noclip(ar, key->co, vertco); - if (key_test_depth(data, key->co) == 0) { - x0= (float)vertco[0]; - x1= (float)vertco[1]; + if ((ED_view3d_project_int_global(ar, key->co, screen_co, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) || + key_test_depth(data, key->co, screen_co) == 0) + { + x0 = (float)screen_co[0]; + x1 = (float)screen_co[1]; xo0= x0 - o0; xo1= x1 - o1; continue; } - v0= (float)vertco[0] - x0; - v1= (float)vertco[1] - x1; + v0 = (float)screen_co[0] - x0; + v1 = (float)screen_co[1] - x1; dv= v0*v0 + v1*v1; @@ -2857,8 +2859,8 @@ static void brush_cut(PEData *data, int pa_index) } } - x0= (float)vertco[0]; - x1= (float)vertco[1]; + x0 = (float)screen_co[0]; + x1 = (float)screen_co[1]; xo0= x0 - o0; xo1= x1 - o1; @@ -3086,9 +3088,9 @@ static void intersect_dm_quad_weights(const float v1[3], const float v2[3], cons copy_v3_v3(vert[2], v3); copy_v3_v3(vert[3], v4); - co[0]= v1[0]*w[0] + v2[0]*w[1] + v3[0]*w[2] + v4[0]*w[3]; - co[1]= v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2] + v4[1]*w[3]; - co[2]= v1[2]*w[0] + v2[2]*w[1] + v3[2]*w[2] + v4[2]*w[3]; + co[0] = v1[0]*w[0] + v2[0]*w[1] + v3[0]*w[2] + v4[0]*w[3]; + co[1] = v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2] + v4[1]*w[3]; + co[2] = v1[2]*w[0] + v2[2]*w[1] + v3[2]*w[2] + v4[2]*w[3]; interp_weights_poly_v3(w, vert, 4, co); } @@ -3196,10 +3198,10 @@ static int particle_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm, if (isect_line_tri_v3(co1, co2, v1, v2, v3, &cur_d, cur_uv)) { if (cur_d<*min_d) { *min_d=cur_d; - min_w[0]= 1.0f - cur_uv[0] - cur_uv[1]; - min_w[1]= cur_uv[0]; - min_w[2]= cur_uv[1]; - min_w[3]= 0.0f; + min_w[0] = 1.0f - cur_uv[0] - cur_uv[1]; + min_w[1] = cur_uv[0]; + min_w[2] = cur_uv[1]; + min_w[3] = 0.0f; if (mface->v4) intersect_dm_quad_weights(v1, v2, v3, v4, min_w); *min_face=i; @@ -3210,10 +3212,10 @@ static int particle_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm, if (isect_line_tri_v3(co1, co2, v1, v3, v4, &cur_d, cur_uv)) { if (cur_d<*min_d) { *min_d=cur_d; - min_w[0]= 1.0f - cur_uv[0] - cur_uv[1]; - min_w[1]= 0.0f; - min_w[2]= cur_uv[0]; - min_w[3]= cur_uv[1]; + min_w[0] = 1.0f - cur_uv[0] - cur_uv[1]; + min_w[1] = 0.0f; + min_w[2] = cur_uv[0]; + min_w[3] = cur_uv[1]; intersect_dm_quad_weights(v1, v2, v3, v4, min_w); *min_face=i; intersect=1; @@ -3272,8 +3274,8 @@ static int brush_add(PEData *data, short number) } } - mco[0]= data->mval[0] + dmx; - mco[1]= data->mval[1] + dmy; + mco[0] = data->mval[0] + dmx; + mco[1] = data->mval[1] + dmy; ED_view3d_win_to_segment_clip(data->vc.ar, data->vc.v3d, mco, co1, co2); mul_m4_v3(imat, co1); @@ -3366,11 +3368,11 @@ static int brush_add(PEData *data, short number) maxd= ptn[maxw-1].dist; for (w=0; wparticles+ptn[0].index; for (k=0; ktotaddkey; k++) { - thkey= (HairKey*)pa->hair + k; + thkey= (HairKey *)pa->hair + k; thkey->time= pa->time + k * framestep; key3[0].time= thkey->time/ 100.0f; @@ -3504,15 +3506,15 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) flip= RNA_boolean_get(itemptr, "pen_flip"); if (bedit->first) { - bedit->lastmouse[0]= mouse[0]; - bedit->lastmouse[1]= mouse[1]; + bedit->lastmouse[0] = mouse[0]; + bedit->lastmouse[1] = mouse[1]; } dx= mouse[0] - bedit->lastmouse[0]; dy= mouse[1] - bedit->lastmouse[1]; - mval[0]= mouse[0]; - mval[1]= mouse[1]; + mval[0] = mouse[0]; + mval[1] = mouse[1]; /* disable locking temporatily for disconnected hair */ @@ -3527,7 +3529,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) view3d_operator_needs_opengl(C); selected= (short)count_selected_keys(scene, edit); - dmax = maxf(fabsf(dx), fabsf(dy)); + dmax = max_ff(fabsf(dx), fabsf(dy)); tot_steps = dmax/(0.2f * brush->size) + 1; dx /= (float)tot_steps; @@ -3637,7 +3639,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) data.mval= mval; data.rad= (float)brush->size; - data.vec[0]= data.vec[1]= data.vec[2]= 0.0f; + data.vec[0] = data.vec[1] = data.vec[2] = 0.0f; data.tot= 0; data.smoothfac= brush->strength; @@ -3691,8 +3693,8 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob); } - bedit->lastmouse[0]= mouse[0]; - bedit->lastmouse[1]= mouse[1]; + bedit->lastmouse[0] = mouse[0]; + bedit->lastmouse[1] = mouse[1]; bedit->first= 0; } @@ -3987,7 +3989,9 @@ void PE_undo_step(Scene *scene, int step) } else if (step==1) { - if (edit->curundo==NULL || edit->curundo->prev==NULL); + if (edit->curundo==NULL || edit->curundo->prev==NULL) { + /* pass */ + } else { if (G.debug & G_DEBUG) printf("undo %s\n", edit->curundo->name); edit->curundo= edit->curundo->prev; @@ -3997,7 +4001,9 @@ void PE_undo_step(Scene *scene, int step) else { /* curundo has to remain current situation! */ - if (edit->curundo==NULL || edit->curundo->next==NULL); + if (edit->curundo==NULL || edit->curundo->next==NULL) { + /* pass */ + } else { get_PTCacheUndo(edit, edit->curundo->next); edit->curundo= edit->curundo->next; @@ -4103,7 +4109,7 @@ int PE_minmax(Scene *scene, float min[3], float max[3]) LOOP_SELECTED_KEYS { copy_v3_v3(co, key->co); mul_m4_v3(mat, co); - DO_MINMAX(co, min, max); + DO_MINMAX(co, min, max); ok= 1; } } @@ -4139,7 +4145,7 @@ static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, return; if (!edit) { - totpoint = psys ? psys->totpart : (int)((PTCacheMem*)cache->mem_cache.first)->totpoint; + totpoint = psys ? psys->totpart : (int)((PTCacheMem *)cache->mem_cache.first)->totpoint; edit= MEM_callocN(sizeof(PTCacheEdit), "PE_create_particle_edit"); edit->points=MEM_callocN(totpoint*sizeof(PTCacheEditPoint), "PTCacheEditPoints"); diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index a17d84af128..221aad2161c 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -110,11 +110,14 @@ static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op)) /* possible this isn't the active object * object_remove_particle_system() clears the mode on the last psys - * */ - if (mode_orig & OB_MODE_PARTICLE_EDIT) - if ((ob->mode & OB_MODE_PARTICLE_EDIT)==0) - if (scene->basact && scene->basact->object==ob) + */ + if (mode_orig & OB_MODE_PARTICLE_EDIT) { + if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) { + if (scene->basact && scene->basact->object == ob) { WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL); + } + } + } WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob); WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob); diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index 099d868a0ad..218af8f0f33 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -196,10 +196,10 @@ static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char int i, j; int channelSize = paramsize; - if (entries==3) { + if (entries == 3) { elbeemSimplifyChannelVec3(channel, &channelSize); } - else if (entries==1) { + else if (entries == 1) { elbeemSimplifyChannelFloat(channel, &channelSize); } else { @@ -211,10 +211,10 @@ static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char fprintf(file, " "); for (j=0;j <= entries;j++) { // also print time value fprintf(file, " %f ", channel[i*(entries + 1) + j]); - if (j==entries-1) { fprintf(file, " "); } - } + if (j == entries-1) { fprintf(file, " "); } + } fprintf(file, "\n"); - } + } fprintf(file, " ;\n"); } @@ -242,7 +242,7 @@ static void init_time(FluidsimSettings *domainSettings, FluidAnimChannels *chann channels->timeAtFrame[0] = channels->timeAtFrame[1] = domainSettings->animStart; // start at index 1 for (i=2; i <= channels->length; i++) { - channels->timeAtFrame[i] = channels->timeAtFrame[i-1] + channels->aniFrameTime; + channels->timeAtFrame[i] = channels->timeAtFrame[i - 1] + (float)channels->aniFrameTime; } } @@ -402,7 +402,7 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid } /* now we loop over the frames and fill the allocated channels with data */ - for (i=0; ilength; i++) { + for (i=0; i < channels->length; i++) { FluidObject *fobj; float viscosity, gravity[3]; float timeAtFrame, time; @@ -426,7 +426,7 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid /* Domain time */ // TODO: have option for not running sim, time mangling, in which case second case comes in handy if (channels->DomainTime) { - time = get_fluid_rate(domainSettings) * channels->aniFrameTime; + time = get_fluid_rate(domainSettings) * (float)channels->aniFrameTime; timeAtFrame = channels->timeAtFrame[i] + time; channels->timeAtFrame[i+1] = timeAtFrame; @@ -456,11 +456,11 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid /* get the rotation from ob->obmat rather than ob->rot to account for parent animations */ if (i) { copy_v3_v3(old_rot, fobj->Rotation + 4*(i-1)); - mul_v3_fl(old_rot, -M_PI/180.f); + mul_v3_fl(old_rot, (float)-M_PI / 180.f); } mat4_to_compatible_eulO(rot_d, old_rot, 0, ob->obmat); - mul_v3_fl(rot_d, -180.f/M_PI); + mul_v3_fl(rot_d, -180.0f / (float)M_PI); set_channel(fobj->Translation, timeAtFrame, ob->loc, i, CHANNEL_VEC); set_channel(fobj->Rotation, timeAtFrame, rot_d, i, CHANNEL_VEC); @@ -527,7 +527,7 @@ static void export_fluid_objects(ListBase *fobjects, Scene *scene, int length) if ( ELEM(fsmesh.type, OB_FLUIDSIM_FLUID, OB_FLUIDSIM_INFLOW)) { fsmesh.channelInitialVel = fobj->InitialVelocity; fsmesh.localInivelCoords = ((fluidmd->fss->typeFlags & OB_FSINFLOW_LOCALCOORD)?1:0); - } + } if (fluidmd->fss->typeFlags & OB_FSBND_NOSLIP) fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP; @@ -593,7 +593,7 @@ static int fluid_validate_scene(ReportList *reports, Scene *scene, Object *fsDom for (base=scene->base.first; base; base= base->next) { Object *ob = base->object; - FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); + FluidsimModifierData *fluidmdtmp = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); /* only find objects with fluid modifiers */ if (!fluidmdtmp || ob->type != OB_MESH) continue; @@ -627,7 +627,7 @@ static int fluid_validate_scene(ReportList *reports, Scene *scene, Object *fsDom return 0; } - if (channelObjCount>=255) { + if (channelObjCount >= 255) { BKE_report(reports, RPT_ERROR, "Cannot bake with more then 256 objects"); return 0; } @@ -648,7 +648,7 @@ static int fluid_validate_scene(ReportList *reports, Scene *scene, Object *fsDom static int fluid_init_filepaths(Object *fsDomain, char *targetDir, char *targetFile, char *debugStrBuffer) { FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim); - FluidsimSettings *domainSettings= fluidmd->fss; + FluidsimSettings *domainSettings= fluidmd->fss; FILE *fileCfg; int dirExist = 0; char newSurfdataPath[FILE_MAX]; /* modified output settings */ @@ -673,7 +673,7 @@ static int fluid_init_filepaths(Object *fsDomain, char *targetDir, char *targetF // check selected directory // simply try to open cfg file for writing to test validity of settings fileCfg = BLI_fopen(targetFile, "w"); - if (fileCfg) { + if (fileCfg) { dirExist = 1; fclose(fileCfg); // remove cfg dummy from directory test BLI_delete(targetFile, 0, 0); @@ -695,21 +695,21 @@ static int fluid_init_filepaths(Object *fsDomain, char *targetDir, char *targetF outStringsChanged=1; } - // check if modified output dir is ok + /* check if modified output dir is ok */ #if 0 if (outStringsChanged) { char dispmsg[FILE_MAX+256]; int selection=0; BLI_strncpy(dispmsg, "Output settings set to: '", sizeof(dispmsg)); strcat(dispmsg, newSurfdataPath); - strcat(dispmsg, "'%t|Continue with changed settings%x1|Discard and abort%x0"); + strcat(dispmsg, "'%t|Continue with changed settings %x1|Discard and abort %x0"); - // ask user if thats what he/she wants... + /* ask user if thats what he/she wants... */ selection = pupmenu(dispmsg); - if (selection < 1) return 0; // 0 from menu, or -1 aborted + if (selection < 1) return 0; /* 0 from menu, or -1 aborted */ BLI_strncpy(targetDir, newSurfdataPath, sizeof(targetDir)); strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR); - BLI_path_abs(targetDir, G.main->name); // fixed #frame-no + BLI_path_abs(targetDir, G.main->name); /* fixed #frame-no */ } #endif return outStringsChanged; @@ -902,7 +902,7 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor /* make sure it corresponds to startFrame setting (old: noFrames = scene->r.efra - scene->r.sfra +1) */; noFrames = scene->r.efra - 0; if (noFrames<=0) { - BKE_report(reports, RPT_ERROR, "No frames to export - check your animation range settings"); + BKE_report(reports, RPT_ERROR, "No frames to export (check your animation range settings)"); fluidbake_free_data(channels, fobjects, fsset, fb); return 0; } @@ -944,8 +944,7 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor if (domainSettings->resolutionxyz>128) { gridlevels = 2; } - else - if (domainSettings->resolutionxyz>64) { + else if (domainSettings->resolutionxyz > 64) { gridlevels = 1; } else { @@ -963,7 +962,7 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor /* ******** prepare output file paths ******** */ outStringsChanged = fluid_init_filepaths(fsDomain, targetDir, targetFile, debugStrBuffer); channels->length = scene->r.efra; - channels->aniFrameTime = (domainSettings->animEnd - domainSettings->animStart)/(double)noFrames; + channels->aniFrameTime = (double)(domainSettings->animEnd - domainSettings->animStart) / (double)noFrames; /* ******** initialize and allocate animation channels ******** */ fluid_init_all_channels(C, fsDomain, domainSettings, channels, fobjects); @@ -1050,7 +1049,7 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor fsset->generateVertexVectors = (domainSettings->domainNovecgen==0); // init blender domain transform matrix - { int j; + { int j; for (i=0; i<4; i++) { for (j=0; j<4; j++) { fsset->surfaceTrafo[i*4+j] = invDomMat[j][i]; diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c index 89ddfe02208..fb99d296a54 100644 --- a/source/blender/editors/physics/physics_ops.c +++ b/source/blender/editors/physics/physics_ops.c @@ -61,7 +61,7 @@ static void operatortypes_particle(void) WM_operatortype_append(PARTICLE_OT_rekey); WM_operatortype_append(PARTICLE_OT_subdivide); WM_operatortype_append(PARTICLE_OT_remove_doubles); - WM_operatortype_append(PARTICLE_OT_weight_set); + WM_operatortype_append(PARTICLE_OT_weight_set); WM_operatortype_append(PARTICLE_OT_delete); WM_operatortype_append(PARTICLE_OT_mirror); diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c index 218ae628d3f..bbce94b6215 100644 --- a/source/blender/editors/physics/physics_pointcache.c +++ b/source/blender/editors/physics/physics_pointcache.c @@ -325,9 +325,9 @@ static int ptcache_add_new_exec(bContext *C, wmOperator *UNUSED(op)) for (pid=pidlist.first; pid; pid=pid->next) { if (pid->cache == cache) { - PointCache *cache = BKE_ptcache_add(pid->ptcaches); - cache->step = pid->default_step; - *(pid->cache_ptr) = cache; + PointCache *cache_new = BKE_ptcache_add(pid->ptcaches); + cache_new->step = pid->default_step; + *(pid->cache_ptr) = cache_new; break; } } diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index ebacac917e8..4b177629f72 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -80,11 +80,10 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat float *rectf = NULL; int ymin, ymax, xmin, xmax; int rymin, rxmin; - unsigned char *rectc; /* if renrect argument, we only refresh scanlines */ if (renrect) { - /* if ymax==recty, rendering of layer is ready, we should not draw, other things happen... */ + /* if (ymax == recty), rendering of layer is ready, we should not draw, other things happen... */ if (rr->renlay == NULL || renrect->ymax >= rr->recty) return; @@ -124,8 +123,14 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat if (rr->rectf) rectf = rr->rectf; else { - if (rr->rect32) + if (rr->rect32) { + /* special case, currently only happens with sequencer rendering, + * which updates the whole frame, so we can only mark display buffer + * as invalid here (sergey) + */ + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; return; + } else { if (rr->renlay == NULL || rr->renlay->rectf == NULL) return; rectf = rr->renlay->rectf; @@ -137,11 +142,10 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat imb_addrectImBuf(ibuf); rectf += 4 * (rr->rectx * ymin + xmin); - rectc = (unsigned char *)(ibuf->rect + ibuf->x * rymin + rxmin); IMB_partial_display_buffer_update(ibuf, rectf, NULL, rr->rectx, rxmin, rymin, &scene->view_settings, &scene->display_settings, - rxmin, rymin, rxmin + xmax, rymin + ymax); + rxmin, rymin, rxmin + xmax, rymin + ymax, TRUE); } /* ****************************** render invoking ***************** */ @@ -198,7 +202,7 @@ static int screen_render_exec(bContext *C, wmOperator *op) screen_render_scene_layer_set(op, mainp, &scene, &srl); if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) { - BKE_report(op->reports, RPT_ERROR, "Can't write a single file with an animation format selected"); + BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected"); return OPERATOR_CANCELLED; } @@ -291,7 +295,11 @@ static void make_renderinfo_string(RenderStats *rs, Scene *scene, char *str) if (rs->tothalo) spos += sprintf(spos, "Ha:%d ", rs->tothalo); if (rs->totstrand) spos += sprintf(spos, "St:%d ", rs->totstrand); if (rs->totlamp) spos += sprintf(spos, "La:%d ", rs->totlamp); - spos += sprintf(spos, "Mem:%.2fM (%.2fM, peak %.2fM) ", megs_used_memory, mmap_used_memory, megs_peak_memory); + + if (rs->mem_peak == 0.0f) + spos += sprintf(spos, "Mem:%.2fM (%.2fM, peak %.2fM) ", megs_used_memory, mmap_used_memory, megs_peak_memory); + else + spos += sprintf(spos, "Mem:%.2fM, Peak: %.2fM ", rs->mem_used, rs->mem_peak); if (rs->curfield) spos += sprintf(spos, "Field %d ", rs->curfield); @@ -489,12 +497,12 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event) } if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) { - BKE_report(op->reports, RPT_ERROR, "Can't write a single file with an animation format selected"); + BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected"); return OPERATOR_CANCELLED; - } + } - /* stop all running jobs, currently previews frustrate Render */ - WM_jobs_stop_all(CTX_wm_manager(C)); + /* stop all running jobs, except screen one. currently previews frustrate Render */ + WM_jobs_kill_all_except(CTX_wm_manager(C), CTX_wm_screen(C)); /* get main */ if (G.debug_value == 101) { diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index d9618e89b68..e4592a4f77e 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -171,11 +171,13 @@ static void screen_opengl_render_apply(OGLRender *oglrender) } } else if (view_context) { + ED_view3d_draw_offscreen_init(scene, v3d); + GPU_offscreen_bind(oglrender->ofs); /* bind */ /* render 3d view */ if (rv3d->persp == RV3D_CAMOB && v3d->camera) { - /*int is_ortho= scene->r.mode & R_ORTHO;*/ + /*int is_ortho = scene->r.mode & R_ORTHO;*/ camera = v3d->camera; RE_GetCameraWindow(oglrender->re, camera, scene->r.cfra, winmat); @@ -189,7 +191,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) else perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); } - if ((scene->r.mode & R_OSA) == 0) { + if ((scene->r.mode & R_OSA) == 0) { ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE, FALSE); GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, rr->rectf); } @@ -306,7 +308,7 @@ static int screen_opengl_render_init(bContext *C, wmOperator *op) char err_out[256] = "unknown"; if (G.background) { - BKE_report(op->reports, RPT_ERROR, "Can't use OpenGL render in background mode (no opengl context)"); + BKE_report(op->reports, RPT_ERROR, "Cannot use OpenGL render in background mode (no opengl context)"); return 0; } @@ -327,12 +329,12 @@ static int screen_opengl_render_init(bContext *C, wmOperator *op) } if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) { - BKE_report(op->reports, RPT_ERROR, "Can't write a single file with an animation format selected"); + BKE_report(op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected"); return 0; } - /* stop all running jobs, currently previews frustrate Render */ - WM_jobs_stop_all(CTX_wm_manager(C)); + /* stop all running jobs, except screen one. currently previews frustrate Render */ + WM_jobs_kill_all_except(CTX_wm_manager(C), CTX_wm_screen(C)); /* create offscreen buffer */ sizex = (scene->r.size * scene->r.xsch) / 100; @@ -342,7 +344,7 @@ static int screen_opengl_render_init(bContext *C, wmOperator *op) ofs = GPU_offscreen_create(sizex, sizey, err_out); if (!ofs) { - BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL offscreen buffer, %s", err_out); + BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out); return 0; } @@ -547,11 +549,11 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) if (ibuf) { int needs_free = FALSE; - if (is_movie || !BKE_imtype_supports_float(scene->r.im_format.imtype)) { - ImBuf *colormanage_ibuf = IMB_dupImBuf(ibuf); + if (is_movie || !BKE_imtype_requires_linear_float(scene->r.im_format.imtype)) { + ImBuf *colormanage_ibuf; - IMB_display_buffer_to_imbuf_rect(colormanage_ibuf, &scene->view_settings, &scene->display_settings); - imb_freerectfloatImBuf(colormanage_ibuf); + colormanage_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, TRUE, TRUE, &scene->view_settings, + &scene->display_settings, &scene->r.im_format); // IMB_freeImBuf(ibuf); /* owned by the image */ ibuf = colormanage_ibuf; @@ -716,7 +718,7 @@ static int screen_opengl_render_exec(bContext *C, wmOperator *op) } } - // no redraw needed, we leave state as we entered it + /* no redraw needed, we leave state as we entered it */ // ED_update_for_newframe(C, 1); WM_event_add_notifier(C, NC_SCENE | ND_RENDER_RESULT, CTX_data_scene(C)); diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index a829ef57b85..53cb5340940 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -266,14 +266,18 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre BKE_color_managed_view_settings_copy(&sce->view_settings, &scene->view_settings); /* prevent overhead for small renders and icons (32) */ - if (id && sp->sizex < 40) - sce->r.xparts = sce->r.yparts = 1; - else - sce->r.xparts = sce->r.yparts = 4; + if (id && sp->sizex < 40) { + sce->r.tilex = sce->r.tiley = 64; + } + else { + sce->r.tilex = sce->r.xsch / 4; + sce->r.tiley = sce->r.ysch / 4; + } - /* exception: don't color manage texture previews or icons */ - if ((id && sp->pr_method == PR_ICON_RENDER) || id_type == ID_TE) + /* exception: don't apply render part of display transform for texture previews or icons */ + if ((id && sp->pr_method == PR_ICON_RENDER) || id_type == ID_TE) { BKE_scene_disable_color_management(sce); + } if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO) sce->r.alphamode = R_ALPHAPREMUL; @@ -340,7 +344,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre if (sp->pr_method == PR_ICON_RENDER) { if (mat->material_type == MA_TYPE_HALO) { sce->lay = 1 << MA_FLAT; - } + } else { sce->lay = 1 << MA_SPHERE_A; } @@ -367,7 +371,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre if (OB_TYPE_SUPPORT_MATERIAL(base->object->type)) { /* don't use assign_material, it changed mat->id.us, which shows in the UI */ Material ***matar = give_matarar(base->object); - int actcol = MAX2(base->object->actcol - 1, 0); + int actcol = max_ii(base->object->actcol - 1, 0); if (matar && actcol < base->object->totcol) (*matar)[actcol] = mat; @@ -385,7 +389,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre tex = localize_texture(origtex); sp->texcopy = tex; BLI_addtail(&pr_main->tex, tex); - } + } sce->lay = 1 << MA_TEXTURE; for (base = sce->base.first; base; base = base->next) { @@ -485,8 +489,8 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int char name[32]; int do_gamma_correct = FALSE, do_predivide = FALSE; int offx = 0; - int newx = BLI_RCT_SIZE_X(rect); - int newy = BLI_RCT_SIZE_Y(rect); + int newx = BLI_rcti_size_x(rect); + int newy = BLI_rcti_size_y(rect); if (id && GS(id->name) != ID_TE) { /* exception: don't color manage texture previews - show the raw values */ @@ -517,8 +521,8 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int if (ABS(rres.rectx - newx) < 2 && ABS(rres.recty - newy) < 2) { - newrect->xmax = MAX2(newrect->xmax, rect->xmin + rres.rectx + offx); - newrect->ymax = MAX2(newrect->ymax, rect->ymin + rres.recty); + newrect->xmax = max_ii(newrect->xmax, rect->xmin + rres.rectx + offx); + newrect->ymax = max_ii(newrect->ymax, rect->ymin + rres.recty); if (rres.rectx && rres.recty) { /* temporary conversion to byte for drawing */ @@ -540,7 +544,7 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int * color managed as well? */ IMB_buffer_byte_from_float(rect_byte, rres.rectf, - 4, dither, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, do_predivide, + 4, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, do_predivide, rres.rectx, rres.recty, rres.rectx, rres.rectx); } @@ -569,8 +573,8 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r SpaceButs *sbuts = sa->spacedata.first; rcti newrect; int ok; - int newx = BLI_RCT_SIZE_X(rect); - int newy = BLI_RCT_SIZE_Y(rect); + int newx = BLI_rcti_size_x(rect); + int newy = BLI_rcti_size_y(rect); newrect.xmin = rect->xmin; newrect.xmax = rect->xmin; @@ -596,7 +600,7 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r if (ok == 0) { ED_preview_shader_job(C, sa, id, parent, slot, newx, newy, PR_BUTS_RENDER); } - } + } } /* **************************** new shader preview system ****************** */ @@ -648,7 +652,7 @@ static void shader_preview_updatejob(void *spv) if (sp->lampcopy && la->nodetree && sp->lampcopy->nodetree) ntreeLocalSync(sp->lampcopy->nodetree, la->nodetree); } - } + } } } @@ -808,7 +812,7 @@ static void shader_preview_free(void *customdata) /* get rid of copied world */ BLI_remlink(&pr_main->world, sp->worldcopy); - BKE_world_free_ex(sp->worldcopy, FALSE); + BKE_world_free_ex(sp->worldcopy, TRUE); /* [#32865] - we need to unlink the texture copies, unlike for materials */ properties = IDP_GetProperties((ID *)sp->worldcopy, FALSE); if (properties) { @@ -860,7 +864,7 @@ static void icon_copy_rect(ImBuf *ibuf, unsigned int w, unsigned int h, unsigned scaledx = (float)w; scaledy = ( (float)ima->y / (float)ima->x) * (float)w; } - else { + else { scaledx = ( (float)ima->x / (float)ima->y) * (float)h; scaledy = (float)h; } diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 8bdd4e544e8..25a01d38dd5 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -747,7 +747,11 @@ void TEXTURE_OT_envmap_save(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER; /* no undo since this doesnt modify the env-map */ /* properties */ - prop = RNA_def_float_array(ot->srna, "layout", 12, default_envmap_layout, 0.0f, 0.0f, "File layout", "Flat array describing the X,Y position of each cube face in the output image, where 1 is the size of a face - order is [+Z -Z +Y -X -Y +X] (use -1 to skip a face)", 0.0f, 0.0f); + prop = RNA_def_float_array(ot->srna, "layout", 12, default_envmap_layout, 0.0f, 0.0f, + "File layout", + "Flat array describing the X,Y position of each cube face in the output image, " + "where 1 is the size of a face - order is [+Z -Z +Y -X -Y +X] " + "(use -1 to skip a face)", 0.0f, 0.0f); RNA_def_property_flag(prop, PROP_HIDDEN); WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE | MOVIEFILE, FILE_SPECIAL, FILE_SAVE, diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index 08ccf37265b..c5320fde0ff 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -74,12 +74,19 @@ void ED_render_scene_update(Main *bmain, Scene *scene, int updated) bScreen *sc; ScrArea *sa; ARegion *ar; + static int recursive_check = FALSE; /* don't do this render engine update if we're updating the scene from * other threads doing e.g. rendering or baking jobs */ if (!BLI_thread_is_main()) return; + /* don't call this recursively for frame updates */ + if (recursive_check) + return; + + recursive_check = TRUE; + C = CTX_create(); CTX_data_main_set(C, bmain); CTX_data_scene_set(C, scene); @@ -114,6 +121,8 @@ void ED_render_scene_update(Main *bmain, Scene *scene, int updated) } CTX_free(C); + + recursive_check = FALSE; } void ED_render_engine_area_exit(ScrArea *sa) @@ -224,8 +233,12 @@ static void material_changed(Main *bmain, Material *ma) /* find node materials using this */ for (parent = bmain->mat.first; parent; parent = parent->id.next) { - if (parent->use_nodes && parent->nodetree && nodes_use_material(parent->nodetree, ma)) ; - else continue; + if (parent->use_nodes && parent->nodetree && nodes_use_material(parent->nodetree, ma)) { + /* pass */ + } + else { + continue; + } BKE_icon_changed(BKE_icon_getid(&parent->id)); @@ -247,9 +260,15 @@ static void texture_changed(Main *bmain, Tex *tex) /* find materials */ for (ma = bmain->mat.first; ma; ma = ma->id.next) { - if (mtex_use_tex(ma->mtex, MAX_MTEX, tex)) ; - else if (ma->use_nodes && ma->nodetree && nodes_use_tex(ma->nodetree, tex)) ; - else continue; + if (mtex_use_tex(ma->mtex, MAX_MTEX, tex)) { + /* pass */ + } + else if (ma->use_nodes && ma->nodetree && nodes_use_tex(ma->nodetree, tex)) { + /* pass */ + } + else { + continue; + } BKE_icon_changed(BKE_icon_getid(&ma->id)); @@ -259,18 +278,30 @@ static void texture_changed(Main *bmain, Tex *tex) /* find lamps */ for (la = bmain->lamp.first; la; la = la->id.next) { - if (mtex_use_tex(la->mtex, MAX_MTEX, tex)) ; - else if (la->nodetree && nodes_use_tex(la->nodetree, tex)) ; - else continue; + if (mtex_use_tex(la->mtex, MAX_MTEX, tex)) { + /* pass */ + } + else if (la->nodetree && nodes_use_tex(la->nodetree, tex)) { + /* pass */ + } + else { + continue; + } BKE_icon_changed(BKE_icon_getid(&la->id)); } /* find worlds */ for (wo = bmain->world.first; wo; wo = wo->id.next) { - if (mtex_use_tex(wo->mtex, MAX_MTEX, tex)) ; - else if (wo->nodetree && nodes_use_tex(wo->nodetree, tex)) ; - else continue; + if (mtex_use_tex(wo->mtex, MAX_MTEX, tex)) { + /* pass */ + } + else if (wo->nodetree && nodes_use_tex(wo->nodetree, tex)) { + /* pass */ + } + else { + continue; + } BKE_icon_changed(BKE_icon_getid(&wo->id)); } diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c index 01c0169eb50..5ec7f4d05b6 100644 --- a/source/blender/editors/render/render_view.c +++ b/source/blender/editors/render/render_view.c @@ -220,7 +220,6 @@ void render_view_open(bContext *C, int mx, int my) else { /* Leave it alone so the image editor will just go back from * full screen to the original tiled setup */ - ; } } } @@ -282,7 +281,7 @@ static int render_view_show_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent if (wincur->screen->temp) { wm_window_lower(wincur); } - else { + else { wmWindow *win, *winshow; ScrArea *sa = find_area_showing_r_result(C, &winshow); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 0bfe5d04e5e..f30e0abb4f3 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -104,8 +104,8 @@ static void region_draw_emboss(ARegion *ar, rcti *scirct) void ED_region_pixelspace(ARegion *ar) { - int width = BLI_RCT_SIZE_X(&ar->winrct) + 1; - int height = BLI_RCT_SIZE_Y(&ar->winrct) + 1; + int width = BLI_rcti_size_x(&ar->winrct) + 1; + int height = BLI_rcti_size_y(&ar->winrct) + 1; wmOrtho2(-GLA_PIXEL_OFS, (float)width - GLA_PIXEL_OFS, -GLA_PIXEL_OFS, (float)height - GLA_PIXEL_OFS); glLoadIdentity(); @@ -390,7 +390,7 @@ void ED_area_overdraw(bContext *C) az->do_draw = FALSE; } } - } + } glDisable(GL_BLEND); } @@ -407,8 +407,12 @@ void region_scissor_winrct(ARegion *ar, rcti *winrct) ar = ar->prev; if (BLI_rcti_isect(winrct, &ar->winrct, NULL)) { - if (ar->flag & RGN_FLAG_HIDDEN) ; - else if (ar->alignment & RGN_SPLIT_PREV) ; + if (ar->flag & RGN_FLAG_HIDDEN) { + /* pass */ + } + else if (ar->alignment & RGN_SPLIT_PREV) { + /* pass */ + } else if (ar->alignment == RGN_OVERLAP_LEFT) { winrct->xmin = ar->winrct.xmax + 1; } @@ -461,11 +465,11 @@ void ED_region_do_draw(bContext *C, ARegion *ar) if (ar->drawrct.xmin == ar->drawrct.xmax) ar->drawrct = winrct; else { - /* extra clip for safety */ - ar->drawrct.xmin = MAX2(winrct.xmin, ar->drawrct.xmin); - ar->drawrct.ymin = MAX2(winrct.ymin, ar->drawrct.ymin); - ar->drawrct.xmax = MIN2(winrct.xmax, ar->drawrct.xmax); - ar->drawrct.ymax = MIN2(winrct.ymax, ar->drawrct.ymax); + /* extra clip for safety (intersect the rects, could use API func) */ + ar->drawrct.xmin = max_ii(winrct.xmin, ar->drawrct.xmin); + ar->drawrct.ymin = max_ii(winrct.ymin, ar->drawrct.ymin); + ar->drawrct.xmax = min_ii(winrct.xmax, ar->drawrct.xmax); + ar->drawrct.ymax = min_ii(winrct.ymax, ar->drawrct.ymax); } /* note; this sets state, so we can use wmOrtho and friends */ @@ -529,10 +533,7 @@ void ED_region_tag_redraw_partial(ARegion *ar, rcti *rct) } else if (ar->drawrct.xmin != ar->drawrct.xmax) { /* partial redraw already set, expand region */ - ar->drawrct.xmin = MIN2(ar->drawrct.xmin, rct->xmin); - ar->drawrct.ymin = MIN2(ar->drawrct.ymin, rct->ymin); - ar->drawrct.xmax = MAX2(ar->drawrct.xmax, rct->xmax); - ar->drawrct.ymax = MAX2(ar->drawrct.ymax, rct->ymax); + BLI_rcti_union(&ar->drawrct, rct); } } } @@ -901,10 +902,10 @@ static void region_azone_add(ScrArea *sa, ARegion *ar, int alignment) static int rct_fits(rcti *rect, char dir, int size) { if (dir == 'h') { - return BLI_RCT_SIZE_X(rect) - size; + return BLI_rcti_size_x(rect) - size; } else { /* 'v' */ - return BLI_RCT_SIZE_Y(rect) - size; + return BLI_rcti_size_y(rect) - size; } } @@ -935,20 +936,25 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int /* prefsize, for header we stick to exception */ prefsizex = ar->sizex ? ar->sizex : ar->type->prefsizex; - if (ar->regiontype == RGN_TYPE_HEADER) + if (ar->regiontype == RGN_TYPE_HEADER) { prefsizey = ar->type->prefsizey; + } else if (ar->regiontype == RGN_TYPE_UI && sa->spacetype == SPACE_FILE) { prefsizey = UI_UNIT_Y * 2 + (UI_UNIT_Y / 2); } - else + else { prefsizey = ar->sizey ? ar->sizey : ar->type->prefsizey; - - /* hidden is user flag */ - if (ar->flag & RGN_FLAG_HIDDEN) ; - /* XXX floating area region, not handled yet here */ - else if (alignment == RGN_ALIGN_FLOAT) ; - /* remainder is too small for any usage */ + } + + + if (ar->flag & RGN_FLAG_HIDDEN) { + /* hidden is user flag */ + } + else if (alignment == RGN_ALIGN_FLOAT) { + /* XXX floating area region, not handled yet here */ + } else if (rct_fits(remainder, 'v', 1) < 0 || rct_fits(remainder, 'h', 1) < 0) { + /* remainder is too small for any usage */ ar->flag |= RGN_FLAG_TOO_SMALL; } else if (alignment == RGN_ALIGN_NONE) { @@ -1010,7 +1016,7 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int if (alignment == RGN_ALIGN_HSPLIT) { if (rct_fits(remainder, 'h', prefsizex) > 4) { - ar->winrct.xmax = BLI_RCT_CENTER_X(remainder); + ar->winrct.xmax = BLI_rcti_cent_x(remainder); remainder->xmin = ar->winrct.xmax + 1; } else { @@ -1019,7 +1025,7 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int } else { if (rct_fits(remainder, 'v', prefsizey) > 4) { - ar->winrct.ymax = BLI_RCT_CENTER_Y(remainder); + ar->winrct.ymax = BLI_rcti_cent_y(remainder); remainder->ymin = ar->winrct.ymax + 1; } else { @@ -1051,20 +1057,20 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int } if (quad) { if (quad == 1) { /* left bottom */ - ar->winrct.xmax = BLI_RCT_CENTER_X(remainder); - ar->winrct.ymax = BLI_RCT_CENTER_Y(remainder); + ar->winrct.xmax = BLI_rcti_cent_x(remainder); + ar->winrct.ymax = BLI_rcti_cent_y(remainder); } else if (quad == 2) { /* left top */ - ar->winrct.xmax = BLI_RCT_CENTER_X(remainder); - ar->winrct.ymin = BLI_RCT_CENTER_Y(remainder) + 1; + ar->winrct.xmax = BLI_rcti_cent_x(remainder); + ar->winrct.ymin = BLI_rcti_cent_y(remainder) + 1; } else if (quad == 3) { /* right bottom */ - ar->winrct.xmin = BLI_RCT_CENTER_X(remainder) + 1; - ar->winrct.ymax = BLI_RCT_CENTER_Y(remainder); + ar->winrct.xmin = BLI_rcti_cent_x(remainder) + 1; + ar->winrct.ymax = BLI_rcti_cent_y(remainder); } else { /* right top */ - ar->winrct.xmin = BLI_RCT_CENTER_X(remainder) + 1; - ar->winrct.ymin = BLI_RCT_CENTER_Y(remainder) + 1; + ar->winrct.xmin = BLI_rcti_cent_x(remainder) + 1; + ar->winrct.ymin = BLI_rcti_cent_y(remainder) + 1; BLI_rcti_init(remainder, 0, 0, 0, 0); } @@ -1073,8 +1079,8 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int } /* for speedup */ - ar->winx = BLI_RCT_SIZE_X(&ar->winrct) + 1; - ar->winy = BLI_RCT_SIZE_Y(&ar->winrct) + 1; + ar->winx = BLI_rcti_size_x(&ar->winrct) + 1; + ar->winy = BLI_rcti_size_y(&ar->winrct) + 1; /* set winrect for azones */ if (ar->flag & (RGN_FLAG_HIDDEN | RGN_FLAG_TOO_SMALL)) { @@ -1096,8 +1102,8 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int if (ar->alignment & RGN_SPLIT_PREV) { if (ar->prev) { remainder = remainder_prev; - ar->prev->winx = BLI_RCT_SIZE_X(&ar->prev->winrct) + 1; - ar->prev->winy = BLI_RCT_SIZE_Y(&ar->prev->winrct) + 1; + ar->prev->winx = BLI_rcti_size_x(&ar->prev->winrct) + 1; + ar->prev->winy = BLI_rcti_size_y(&ar->prev->winrct) + 1; } } @@ -1133,8 +1139,8 @@ static void area_calc_totrct(ScrArea *sa, int sizex, int sizey) else sa->totrct.ymax = sa->v2->vec.y; /* for speedup */ - sa->winx = BLI_RCT_SIZE_X(&sa->totrct) + 1; - sa->winy = BLI_RCT_SIZE_Y(&sa->totrct) + 1; + sa->winx = BLI_rcti_size_x(&sa->totrct) + 1; + sa->winy = BLI_rcti_size_y(&sa->totrct) + 1; } @@ -1251,25 +1257,21 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) } else { /* prevent uiblocks to run */ - uiFreeBlocks(NULL, &ar->uiblocks); + uiFreeBlocks(NULL, &ar->uiblocks); } - - /* rechecks 2d matrix for header on dpi changing, do not do for other regions, it resets view && blocks view2d operator polls (ton) */ - if (ar->regiontype == RGN_TYPE_HEADER) - ar->v2d.flag &= ~V2D_IS_INITIALISED; } } /* externally called for floating regions like menus */ void ED_region_init(bContext *C, ARegion *ar) { -// ARegionType *at= ar->type; +// ARegionType *at = ar->type; /* refresh can be called before window opened */ region_subwindow(CTX_wm_window(C), ar); - ar->winx = BLI_RCT_SIZE_X(&ar->winrct) + 1; - ar->winy = BLI_RCT_SIZE_Y(&ar->winrct) + 1; + ar->winx = BLI_rcti_size_x(&ar->winrct) + 1; + ar->winy = BLI_rcti_size_y(&ar->winrct) + 1; /* UI convention */ wmOrtho2(-0.01f, ar->winx - 0.01f, -0.01f, ar->winy - 0.01f); @@ -1405,7 +1407,7 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type) /* put in front of list */ BLI_remlink(&sa->spacedata, sl); BLI_addhead(&sa->spacedata, sl); - } + } else { /* new space */ if (st) { @@ -1448,7 +1450,8 @@ void ED_area_prevspace(bContext *C, ScrArea *sa) ED_area_newspace(C, sa, sl->next->spacetype); } else { - ED_area_newspace(C, sa, SPACE_INFO); + /* no change */ + return; } ED_area_tag_redraw(sa); @@ -1459,39 +1462,39 @@ void ED_area_prevspace(bContext *C, ScrArea *sa) static const char *editortype_pup(void) { const char *types = N_( - "Editor type:%t" + "Editor type: %t" "|3D View %x1" "|%l" - + "|Timeline %x15" "|Graph Editor %x2" "|DopeSheet %x12" "|NLA Editor %x13" - + "|%l" - + "|UV/Image Editor %x6" - + "|Video Sequence Editor %x8" "|Movie Clip Editor %x20" "|Text Editor %x9" "|Node Editor %x16" "|Logic Editor %x17" - + "|%l" - + "|Properties %x4" "|Outliner %x3" "|User Preferences %x19" - "|Info%x7" + "|Info %x7" "|%l" "|File Browser %x5" - + "|%l" - + "|Python Console %x18" ); @@ -1517,7 +1520,7 @@ int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco) but = uiDefIconTextButC(block, ICONTEXTROW, 0, ICON_VIEW3D, editortype_pup(), xco, yco, UI_UNIT_X + 10, UI_UNIT_Y, &(sa->butspacetype), 1.0, SPACEICONMAX, 0, 0, - TIP_("Displays current editor type. Click for menu of available types")); + TIP_("Display current editor type (click for a menu of available types)")); uiButSetFunc(but, spacefunc, NULL, NULL); uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */ @@ -1574,7 +1577,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char * newcontext = UI_view2d_tab_set(v2d, contextnr); if (vertical) { - w = BLI_RCT_SIZE_X(&v2d->cur); + w = BLI_rctf_size_x(&v2d->cur); em = (ar->type->prefsizex) ? UI_UNIT_Y / 2 : UI_UNIT_Y; } else { @@ -1661,11 +1664,9 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char * v2d->scroll |= V2D_SCROLL_HORIZONTAL_HIDE; v2d->scroll &= ~V2D_SCROLL_VERTICAL_HIDE; - /* don't jump back when panels close or hide */ - if (!newcontext) - y = MAX2(-y, -v2d->cur.ymin); - else - y = -y; + /* ensure tot is set correctly, to keep views on bottons, with sliders */ + y = min_ii(y, v2d->cur.ymin); + y = -y; } else { /* for now, allow scrolling in both directions (since layouts are optimized for vertical, @@ -1679,7 +1680,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char * /* don't jump back when panels close or hide */ if (!newcontext) - x = MAX2(x, v2d->cur.xmax); + x = max_ii(x, v2d->cur.xmax); y = -y; } @@ -1732,7 +1733,7 @@ void ED_region_header(const bContext *C, ARegion *ar) int maxco, xco, yco; int headery = ED_area_headersize(); - /* clear */ + /* clear */ UI_ThemeClearColor((ED_screen_area_active(C)) ? TH_HEADER : TH_HEADERDESEL); glClear(GL_COLOR_BUFFER_BIT); @@ -1769,7 +1770,7 @@ void ED_region_header(const bContext *C, ARegion *ar) } /* always as last */ - UI_view2d_totRect_set(&ar->v2d, maxco + UI_UNIT_X + 80, BLI_RCT_SIZE_Y(&ar->v2d.tot)); + UI_view2d_totRect_set(&ar->v2d, maxco + UI_UNIT_X + 80, headery); /* restore view matrix? */ UI_view2d_view_restore(C); @@ -1798,16 +1799,16 @@ void ED_region_info_draw(ARegion *ar, const char *text, int block, float alpha) /* background box */ rect = ar->winrct; rect.xmin = 0; - rect.ymin = BLI_RCT_SIZE_Y(&ar->winrct) - header_height; + rect.ymin = BLI_rcti_size_y(&ar->winrct) - header_height; if (block) { - rect.xmax = BLI_RCT_SIZE_X(&ar->winrct); + rect.xmax = BLI_rcti_size_x(&ar->winrct); } else { rect.xmax = rect.xmin + BLF_width(fontid, text) + 24; } - rect.ymax = BLI_RCT_SIZE_Y(&ar->winrct); + rect.ymax = BLI_rcti_size_y(&ar->winrct); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index c93f4156eeb..ce2d045dc80 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -600,8 +600,8 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo /* The maximum pixel amounts the image can be cropped * at the lower left without exceeding the origin. */ - int off_x = floor(MAX2(ix, 0)); - int off_y = floor(MAX2(iy, 0)); + int off_x = floor(max_ff(ix, 0.0f)); + int off_y = floor(max_ff(iy, 0.0f)); /* The zoomed space coordinate of the raster position * (starting at the lower left most unclipped pixel). @@ -625,8 +625,8 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo * covers the entire screen). */ glGetFloatv(GL_SCISSOR_BOX, scissor); - draw_w = mini(img_w - off_x, ceil((scissor[2] - rast_x) / xzoom)); - draw_h = mini(img_h - off_y, ceil((scissor[3] - rast_y) / yzoom)); + draw_w = min_ii(img_w - off_x, ceil((scissor[2] - rast_x) / xzoom)); + draw_h = min_ii(img_h - off_y, ceil((scissor[3] - rast_y) / yzoom)); if (draw_w > 0 && draw_h > 0) { int old_row_length = glaGetOneInteger(GL_UNPACK_ROW_LENGTH); @@ -669,8 +669,8 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo void glaDefine2DArea(rcti *screen_rect) { - const int sc_w = BLI_RCT_SIZE_X(screen_rect) + 1; - const int sc_h = BLI_RCT_SIZE_Y(screen_rect) + 1; + const int sc_w = BLI_rcti_size_x(screen_rect) + 1; + const int sc_h = BLI_rcti_size_y(screen_rect) + 1; glViewport(screen_rect->xmin, screen_rect->ymin, sc_w, sc_h); glScissor(screen_rect->xmin, screen_rect->ymin, sc_w, sc_h); @@ -714,10 +714,10 @@ void gla2DSetMap(gla2DDrawInfo *di, rctf *rect) di->world_rect = *rect; - sc_w = BLI_RCT_SIZE_X(&di->screen_rect); - sc_h = BLI_RCT_SIZE_Y(&di->screen_rect); - wo_w = BLI_RCT_SIZE_X(&di->world_rect); - wo_h = BLI_RCT_SIZE_Y(&di->world_rect); + sc_w = BLI_rcti_size_x(&di->screen_rect); + sc_h = BLI_rcti_size_y(&di->screen_rect); + wo_w = BLI_rcti_size_x(&di->world_rect); + wo_h = BLI_rcti_size_y(&di->world_rect); di->wo_to_sc[0] = sc_w / wo_w; di->wo_to_sc[1] = sc_h / wo_h; @@ -745,10 +745,10 @@ gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect) di->world_rect.ymax = di->screen_rect.ymax; } - sc_w = BLI_RCT_SIZE_X(&di->screen_rect); - sc_h = BLI_RCT_SIZE_Y(&di->screen_rect); - wo_w = BLI_RCT_SIZE_X(&di->world_rect); - wo_h = BLI_RCT_SIZE_Y(&di->world_rect); + sc_w = BLI_rcti_size_x(&di->screen_rect); + sc_h = BLI_rcti_size_y(&di->screen_rect); + wo_w = BLI_rcti_size_x(&di->world_rect); + wo_h = BLI_rcti_size_y(&di->world_rect); di->wo_to_sc[0] = sc_w / wo_w; di->wo_to_sc[1] = sc_h / wo_h; diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 352039c5a61..a516603cfd4 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -194,7 +194,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone); } } - } + } CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); return 1; } @@ -236,7 +236,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone); } } - } + } CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); return 1; } diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 11d32e11cd0..60aad14efcf 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -36,10 +36,12 @@ #include "DNA_scene_types.h" #include "DNA_userdef_types.h" +#include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_library.h" #include "BKE_main.h" @@ -270,7 +272,7 @@ ScrEdge *screen_find_active_scredge(bScreen *sc, int mx, int my) if (abs(my - se->v1->vec.y) <= 2 && mx >= min && mx <= max) return se; - } + } else { short min, max; min = MIN2(se->v1->vec.y, se->v2->vec.y); @@ -630,10 +632,8 @@ static void screen_test_scale(bScreen *sc, int winsizex, int winsizey) max[0] = max[1] = 0.0f; for (sv = sc->vertbase.first; sv; sv = sv->next) { - min[0] = MIN2(min[0], sv->vec.x); - min[1] = MIN2(min[1], sv->vec.y); - max[0] = MAX2(max[0], sv->vec.x); - max[1] = MAX2(max[1], sv->vec.y); + const float fv[2] = {(float)sv->vec.x, (float)sv->vec.y}; + minmax_v2v2_v2(min, max, fv); } /* always make 0.0 left under */ @@ -704,10 +704,6 @@ static void screen_test_scale(bScreen *sc, int winsizex, int winsizey) /* *********************** DRAWING **************************************** */ - -#define SCR_BACK 0.55 -#define SCR_ROUND 12 - /* draw vertical shape visualizing future joining (left as well * right direction of future joining) */ static void draw_horizontal_join_shape(ScrArea *sa, char dir) @@ -878,7 +874,7 @@ static void scrarea_draw_shape_light(ScrArea *sa, char UNUSED(dir)) glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA); glEnable(GL_BLEND); /* value 181 was hardly computed: 181~105 */ - glColor4ub(255, 255, 255, 50); + glColor4ub(255, 255, 255, 50); /* draw_join_shape(sa, dir); */ glRecti(sa->v1->vec.x, sa->v1->vec.y, sa->v3->vec.x, sa->v3->vec.y); glDisable(GL_BLEND); @@ -1069,7 +1065,7 @@ static void screen_refresh_headersizes(void) for (st = lb->first; st; st = st->next) { ARegionType *art = BKE_regiontype_from_id(st, RGN_TYPE_HEADER); if (art) art->prefsizey = ED_area_headersize(); - } + } } /* make this screen usable */ @@ -1323,7 +1319,7 @@ int ED_screen_area_active(const bContext *C) for (ar = sa->regionbase.first; ar; ar = ar->next) if (ar->swinid == sc->subwinactive) return 1; - } + } return 0; } @@ -1456,10 +1452,10 @@ void ED_screen_set_scene(bContext *C, bScreen *screen, Scene *scene) if (scene != sc->scene) { /* all areas endlocalview */ - // XXX ScrArea *sa= sc->areabase.first; + // XXX ScrArea *sa = sc->areabase.first; // while (sa) { // endlocalview(sa); - // sa= sa->next; + // sa = sa->next; // } sc->scene = scene; } @@ -1506,6 +1502,7 @@ void ED_screen_set_scene(bContext *C, bScreen *screen, Scene *scene) CTX_data_scene_set(C, scene); BKE_scene_set_background(bmain, scene); + DAG_on_visible_update(bmain, FALSE); ED_render_engine_changed(bmain); ED_update_for_newframe(bmain, scene, 1); @@ -1735,7 +1732,7 @@ void ED_refresh_viewport_fps(bContext *C) fpsi->redrawtime = fpsi->lredrawtime; fpsi->lredrawtime = animtimer->ltime; } - else { + else { /* playback stopped or shouldn't be running */ if (scene->fps_info) MEM_freeN(scene->fps_info); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 50a210e5d7c..6a9c24d2913 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -192,7 +192,7 @@ int ED_operator_region_view3d_active(bContext *C) return TRUE; CTX_wm_operator_poll_msg_set(C, "expected a view3d region"); - return FALSE; + return FALSE; } /* generic for any view2d which uses anim_ops */ @@ -256,7 +256,7 @@ int ED_operator_node_active(bContext *C) return 0; } -// XXX rename +/* XXX rename */ int ED_operator_graphedit_active(bContext *C) { return ed_spacetype_test(C, SPACE_IPO); @@ -372,6 +372,21 @@ int ED_operator_posemode_exclusive(bContext *C) return 0; } +/* allows for pinned pose objects to be used in the object buttons + * and the the non-active pose object to be used in the 3D view */ +int ED_operator_posemode_context(bContext *C) +{ + Object *obpose = ED_pose_object_from_context(C); + + if (obpose && !(obpose->mode & OB_MODE_EDIT)) { + if (BKE_object_pose_context_check(obpose)) { + return 1; + } + } + + return 0; +} + int ED_operator_posemode(bContext *C) { Object *obact = CTX_data_active_object(C); @@ -565,7 +580,7 @@ static int actionzone_area_poll(bContext *C) for (az = sa->actionzones.first; az; az = az->next) if (BLI_rcti_isect_pt(&az->rect, x, y)) return 1; - } + } return 0; } @@ -613,6 +628,7 @@ static void actionzone_apply(bContext *C, wmOperator *op, int type) event.type = EVT_ACTIONZONE_AREA; else event.type = EVT_ACTIONZONE_REGION; + event.val = 0; event.customdata = op->customdata; event.customdatafree = TRUE; op->customdata = NULL; @@ -686,7 +702,7 @@ static int actionzone_modal(bContext *C, wmOperator *op, wmEvent *event) case ESCKEY: actionzone_exit(op); return OPERATOR_CANCELLED; - case LEFTMOUSE: + case LEFTMOUSE: actionzone_exit(op); return OPERATOR_CANCELLED; @@ -954,18 +970,18 @@ static void area_move_set_limits(bScreen *sc, int dir, int *bigger, int *smaller /* if top or down edge selected, test height */ if (sa->v1->flag && sa->v4->flag) - *bigger = MIN2(*bigger, y1); + *bigger = min_ii(*bigger, y1); else if (sa->v2->flag && sa->v3->flag) - *smaller = MIN2(*smaller, y1); + *smaller = min_ii(*smaller, y1); } else { int x1 = sa->v4->vec.x - sa->v1->vec.x - AREAMINX; /* if left or right edge selected, test width */ if (sa->v1->flag && sa->v2->flag) - *bigger = MIN2(*bigger, x1); + *bigger = min_ii(*bigger, x1); else if (sa->v3->flag && sa->v4->flag) - *smaller = MIN2(*smaller, x1); + *smaller = min_ii(*smaller, x1); } } } @@ -1196,9 +1212,6 @@ static void SCREEN_OT_area_move(wmOperatorType *ot) * call exit() or cancel() and remove handler */ -#define SPLIT_STARTED 1 -#define SPLIT_PROGRESS 2 - typedef struct sAreaSplitData { int x, y; /* last used mouse position */ @@ -1329,7 +1342,7 @@ static int area_split_apply(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); return 1; - } + } return 0; } @@ -1635,10 +1648,10 @@ static int area_max_regionsize(ScrArea *sa, ARegion *scalear, AZEdge edge) int dist; if (edge == AE_RIGHT_TO_TOPLEFT || edge == AE_LEFT_TO_TOPRIGHT) { - dist = BLI_RCT_SIZE_X(&sa->totrct); + dist = BLI_rcti_size_x(&sa->totrct); } else { /* AE_BOTTOM_TO_TOPLEFT, AE_TOP_TO_BOTTOMRIGHT */ - dist = BLI_RCT_SIZE_Y(&sa->totrct); + dist = BLI_rcti_size_y(&sa->totrct); } /* subtractwidth of regions on opposite side @@ -1679,7 +1692,7 @@ static int region_scale_invoke(bContext *C, wmOperator *op, wmEvent *event) AZone *az; if (event->type != EVT_ACTIONZONE_REGION) { - BKE_report(op->reports, RPT_ERROR, "Can only scale region size from an action zone"); + BKE_report(op->reports, RPT_ERROR, "Can only scale region size from an action zone"); return OPERATOR_CANCELLED; } @@ -1843,7 +1856,7 @@ static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event) break; case ESCKEY: - ; + break; } return OPERATOR_RUNNING_MODAL; @@ -2059,15 +2072,23 @@ static void SCREEN_OT_keyframe_jump(wmOperatorType *ot) /* ************** switch screen operator ***************************** */ +static int screen_set_is_ok(bScreen *screen, bScreen *screen_prev) +{ + return ((screen->winid == 0) && + (screen->full == 0) && + (screen != screen_prev) && + (screen->id.name[2] != '.' || !(U.uiflag & USER_HIDE_DOT))); +} /* function to be called outside UI context, or for redo */ static int screen_set_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); bScreen *screen = CTX_wm_screen(C); bScreen *screen_prev = screen; ScrArea *sa = CTX_wm_area(C); - int tot = BLI_countlist(&CTX_data_main(C)->screen); + int tot = BLI_countlist(&bmain->screen); int delta = RNA_int_get(op->ptr, "delta"); /* temp screens are for userpref or render display */ @@ -2077,17 +2098,19 @@ static int screen_set_exec(bContext *C, wmOperator *op) if (delta == 1) { while (tot--) { screen = screen->id.next; - if (screen == NULL) screen = CTX_data_main(C)->screen.first; - if (screen->winid == 0 && screen->full == 0 && screen != screen_prev) + if (screen == NULL) screen = bmain->screen.first; + if (screen_set_is_ok(screen, screen_prev)) { break; + } } } else if (delta == -1) { while (tot--) { screen = screen->id.prev; - if (screen == NULL) screen = CTX_data_main(C)->screen.last; - if (screen->winid == 0 && screen->full == 0 && screen != screen_prev) + if (screen == NULL) screen = bmain->screen.last; + if (screen_set_is_ok(screen, screen_prev)) { break; + } } } else { @@ -2347,14 +2370,14 @@ static int area_join_modal(bContext *C, wmOperator *op, wmEvent *event) ScrArea *sa = screen_areahascursor(sc, event->x, event->y); int dir; - if (sa) { + if (sa) { if (jd->sa1 != sa) { dir = area_getorientation(jd->sa1, sa); if (dir >= 0) { if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO; jd->sa2 = sa; jd->sa2->flag |= AREA_FLAG_DRAWJOINTO; - } + } else { /* we are not bordering on the previously selected area * we check if area has common border with the one marked for removal @@ -2368,14 +2391,14 @@ static int area_join_modal(bContext *C, wmOperator *op, wmEvent *event) jd->sa2 = sa; if (jd->sa1) jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM; if (jd->sa2) jd->sa2->flag |= AREA_FLAG_DRAWJOINTO; - } + } else { if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO; jd->sa2 = NULL; } } WM_event_add_notifier(C, NC_WINDOW, NULL); - } + } else { /* we are back in the area previously selected for keeping * we swap the areas if possible to allow user to choose */ @@ -2390,7 +2413,7 @@ static int area_join_modal(bContext *C, wmOperator *op, wmEvent *event) if (dir < 0) { printf("oops, didn't expect that!\n"); } - } + } else { dir = area_getorientation(jd->sa1, sa); if (dir >= 0) { @@ -2704,6 +2727,8 @@ static int region_quadview_exec(bContext *C, wmOperator *op) /* lock views and set them */ if (sa->spacetype == SPACE_VIEW3D) { + View3D *v3d = sa->spacedata.first; + /* run ED_view3d_lock() so the correct 'rv3d->viewquat' is set, * otherwise when restoring rv3d->localvd the 'viewquat' won't * match the 'view', set on entering localview See: [#26315], @@ -2731,7 +2756,15 @@ static int region_quadview_exec(bContext *C, wmOperator *op) ar = ar->next; rv3d = ar->regiondata; - rv3d->view = RV3D_VIEW_CAMERA; rv3d->persp = RV3D_CAMOB; + + /* check if we have a camera */ + if (v3d->camera) { + rv3d->view = RV3D_VIEW_CAMERA; rv3d->persp = RV3D_CAMOB; + } + else { + rv3d->view = RV3D_VIEW_PERSPORTHO; rv3d->persp = RV3D_PERSP; + } + ED_view3d_lock(rv3d); view3d_localview_update_rv3d(rv3d); } @@ -2815,7 +2848,7 @@ static int header_flip_exec(bContext *C, wmOperator *UNUSED(op)) /* don't do anything if no region */ if (ar == NULL) return OPERATOR_CANCELLED; - } + } /* copied from SCREEN_OT_region_flip */ if (ar->alignment == RGN_ALIGN_TOP) @@ -2849,36 +2882,78 @@ static void SCREEN_OT_header_flip(wmOperatorType *ot) ot->flag = 0; } -/* ************** header tools operator ***************************** */ -static int header_toolbox_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) + +/* ************** show menus operator ***************************** */ + +/* show/hide header text menus */ +static int header_toggle_menus_exec(bContext *C, wmOperator *UNUSED(op)) +{ + ScrArea *sa = CTX_wm_area(C); + + sa->flag = sa->flag ^ HEADER_NO_PULLDOWN; + + ED_area_tag_redraw(CTX_wm_area(C)); + WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + + +static void SCREEN_OT_header_toggle_menus(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Show/Hide Header Menus"; + ot->idname = "SCREEN_OT_header_toggle_menus"; + ot->description = "Show or hide the header pulldown menus"; + + /* api callbacks */ + ot->exec = header_toggle_menus_exec; + ot->poll = ED_operator_areaactive; + ot->flag = 0; +} + + +/* ************** header tools operator ***************************** */ +void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg)) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); - uiPopupMenu *pup; - uiLayout *layout; - - pup = uiPupMenuBegin(C, "Header", ICON_NONE); - layout = uiPupMenuLayout(pup); - - // XXX SCREEN_OT_region_flip doesn't work - gets wrong context for active region, so added custom operator + + /* XXX SCREEN_OT_region_flip doesn't work - gets wrong context for active region, so added custom operator. */ if (ar->alignment == RGN_ALIGN_TOP) - uiItemO(layout, "Flip to Bottom", ICON_NONE, "SCREEN_OT_header_flip"); + uiItemO(layout, IFACE_("Flip to Bottom"), ICON_NONE, "SCREEN_OT_header_flip"); else - uiItemO(layout, "Flip to Top", ICON_NONE, "SCREEN_OT_header_flip"); - + uiItemO(layout, IFACE_("Flip to Top"), ICON_NONE, "SCREEN_OT_header_flip"); + + if (sa->flag & HEADER_NO_PULLDOWN) + uiItemO(layout, IFACE_("Show Menus"), ICON_NONE, "SCREEN_OT_header_toggle_menus"); + else + uiItemO(layout, IFACE_("Hide Menus"), ICON_NONE, "SCREEN_OT_header_toggle_menus"); + uiItemS(layout); - + /* file browser should be fullscreen all the time, but other regions can be maximized/restored... */ if (sa->spacetype != SPACE_FILE) { if (sa->full) - uiItemO(layout, "Tile Area", ICON_NONE, "SCREEN_OT_screen_full_area"); + uiItemO(layout, IFACE_("Tile Area"), ICON_NONE, "SCREEN_OT_screen_full_area"); else - uiItemO(layout, "Maximize Area", ICON_NONE, "SCREEN_OT_screen_full_area"); + uiItemO(layout, IFACE_("Maximize Area"), ICON_NONE, "SCREEN_OT_screen_full_area"); } - +} + +static int header_toolbox_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) +{ + uiPopupMenu *pup; + uiLayout *layout; + + pup = uiPupMenuBegin(C, N_("Header"), ICON_NONE); + layout = uiPupMenuLayout(pup); + + ED_screens_header_tools_menu_create(C, layout, NULL); + uiPupMenuEnd(C, pup); - + return OPERATOR_CANCELLED; } @@ -3008,7 +3083,11 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), wmEvent *e } else { if (sync) { - int step = floor((wt->duration - sad->last_duration) * FPS); + /* note: this is very simplistic, + * its has problem that it may skip too many frames. + * however at least this gives a less jittery playback */ + const int step = max_ii(1, floor((wt->duration - sad->last_duration) * FPS)); + /* skip frames */ if (sad->flag & ANIMPLAY_FLAG_REVERSE) scene->r.cfra -= step; @@ -3077,11 +3156,12 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), wmEvent *e for (sa = window->screen->areabase.first; sa; sa = sa->next) { ARegion *ar; for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar == sad->ar) + if (ar == sad->ar) { ED_region_tag_redraw(ar); - else - if (match_region_with_redraws(sa->spacetype, ar->regiontype, sad->redraws)) + } + else if (match_region_with_redraws(sa->spacetype, ar->regiontype, sad->redraws)) { ED_region_tag_redraw(ar); + } } if (match_area_with_refresh(sa->spacetype, sad->refresh)) @@ -3098,7 +3178,7 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), wmEvent *e /* recalculate the timestep for the timer now that we've finished calculating this, * since the frames-per-second value may have been changed */ - // TODO: this may make evaluation a bit slower if the value doesn't change... any way to avoid this? + /* TODO: this may make evaluation a bit slower if the value doesn't change... any way to avoid this? */ wt->timestep = (1.0 / FPS); return OPERATOR_FINISHED; @@ -3148,7 +3228,7 @@ int ED_screen_animation_play(bContext *C, int sync, int mode) else { int refresh = SPACE_TIME; /* these settings are currently only available from a menu in the TimeLine */ - if (mode == 1) // XXX only play audio forwards!? + if (mode == 1) /* XXX only play audio forwards!? */ sound_play_scene(scene); ED_screen_animation_timer(C, screen->redraws_flag, refresh, sync, mode); @@ -3400,7 +3480,7 @@ static int screen_delete_exec(bContext *C, wmOperator *UNUSED(op)) static void SCREEN_OT_delete(wmOperatorType *ot) { /* identifiers */ - ot->name = "Delete Screen"; //was scene + ot->name = "Delete Screen"; /* was scene */ ot->description = "Delete active screen"; ot->idname = "SCREEN_OT_delete"; @@ -3520,6 +3600,7 @@ void ED_operatortypes_screen(void) WM_operatortype_append(SCREEN_OT_region_scale); WM_operatortype_append(SCREEN_OT_region_flip); WM_operatortype_append(SCREEN_OT_header_flip); + WM_operatortype_append(SCREEN_OT_header_toggle_menus); WM_operatortype_append(SCREEN_OT_header_toolbox); WM_operatortype_append(SCREEN_OT_screen_set); WM_operatortype_append(SCREEN_OT_screen_full_area); @@ -3547,7 +3628,7 @@ void ED_operatortypes_screen(void) /* tools shared by more space types */ WM_operatortype_append(ED_OT_undo); WM_operatortype_append(ED_OT_undo_push); - WM_operatortype_append(ED_OT_redo); + WM_operatortype_append(ED_OT_redo); WM_operatortype_append(ED_OT_undo_history); } @@ -3717,7 +3798,7 @@ void ED_keymap_screen(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "SCREEN_OT_animation_cancel", MEDIASTOP, KM_PRESS, 0, 0); /* Alternative keys for animation and sequencer playing */ -#if 0 // XXX: disabled for restoring later... bad implementation +#if 0 /* XXX: disabled for restoring later... bad implementation */ keymap = WM_keymap_find(keyconf, "Frames", 0, 0); kmi = WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", RIGHTARROWKEY, KM_PRESS, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "cycle_speed", TRUE); diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 5e54119118a..0ecac5fc497 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -149,8 +149,8 @@ static void screenshot_crop(ImBuf *ibuf, rcti crop) { unsigned int *to = ibuf->rect; unsigned int *from = ibuf->rect + crop.ymin * ibuf->x + crop.xmin; - int crop_x = BLI_RCT_SIZE_X(&crop); - int crop_y = BLI_RCT_SIZE_Y(&crop); + int crop_x = BLI_rcti_size_x(&crop); + int crop_y = BLI_rcti_size_y(&crop); int y; if (crop_x > 0 && crop_y > 0) { @@ -214,7 +214,7 @@ static int screenshot_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event) WM_event_add_fileselect(C, op); return OPERATOR_RUNNING_MODAL; - } + } return OPERATOR_CANCELLED; } @@ -245,7 +245,7 @@ static void screenshot_draw(bContext *UNUSED(C), wmOperator *op) /* image template */ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &scd->im_format, &ptr); - uiTemplateImageSettings(layout, &ptr, TRUE); + uiTemplateImageSettings(layout, &ptr, FALSE); /* main draw call */ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); @@ -365,7 +365,7 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float if (ok == 0) { printf("Write error: cannot save %s\n", name); - BKE_reportf(&sj->reports, RPT_INFO, "Write error: cannot save %s\n", name); + BKE_reportf(&sj->reports, RPT_INFO, "Write error: cannot save %s", name); break; } else { @@ -374,7 +374,7 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float } /* imbuf knows which rects are not part of ibuf */ - IMB_freeImBuf(ibuf); + IMB_freeImBuf(ibuf); } MEM_freeN(sj->dumprect); @@ -408,7 +408,7 @@ static int screencast_exec(bContext *C, wmOperator *op) sj->y = 0; sj->dumpsx = win->sizex; sj->dumpsy = win->sizey; - } + } else { ScrArea *curarea = CTX_wm_area(C); sj->x = curarea->totrct.xmin; diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt index 043b7ecb5cb..ae72dce1415 100644 --- a/source/blender/editors/sculpt_paint/CMakeLists.txt +++ b/source/blender/editors/sculpt_paint/CMakeLists.txt @@ -20,6 +20,7 @@ set(INC ../include + ../uvedit ../../blenkernel ../../blenlib ../../blenloader @@ -28,7 +29,6 @@ set(INC ../../imbuf ../../makesdna ../../makesrna - ../uvedit ../../render/extern/include ../../windowmanager ../../../../intern/guardedalloc diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 8616d4e66eb..5e23a144408 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -322,11 +322,16 @@ static int project_brush_radius(ViewContext *vc, add_v3_v3v3(offset, location, ortho); /* project the center of the brush, and the tangent point to the view onto the screen */ - project_float(vc->ar, location, p1); - project_float(vc->ar, offset, p2); - - /* the distance between these points is the size of the projected brush in pixels */ - return len_v2v2(p1, p2); + if ((ED_view3d_project_float_global(vc->ar, location, p1, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) && + (ED_view3d_project_float_global(vc->ar, offset, p2, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK)) + { + /* the distance between these points is the size of the projected brush in pixels */ + return len_v2v2(p1, p2); + } + else { + BLI_assert(0); /* assert because the code that sets up the vectors should disallow this */ + return 0; + } } static int sculpt_get_brush_geometry(bContext *C, ViewContext *vc, @@ -335,7 +340,6 @@ static int sculpt_get_brush_geometry(bContext *C, ViewContext *vc, { Scene *scene = CTX_data_scene(C); Paint *paint = paint_get_active_from_context(C); - Brush *brush = paint_brush(paint); float window[2]; int hit; @@ -345,6 +349,7 @@ static int sculpt_get_brush_geometry(bContext *C, ViewContext *vc, if (vc->obact->sculpt && vc->obact->sculpt->pbvh && sculpt_stroke_get_location(C, location, window)) { + Brush *brush = paint_brush(paint); *pixel_radius = project_brush_radius(vc, BKE_brush_unprojected_radius_get(scene, brush), @@ -441,8 +446,8 @@ static void paint_draw_alpha_overlay(Sculpt *sd, Brush *brush, else { quad.xmin = 0; quad.ymin = 0; - quad.xmax = BLI_RCT_SIZE_X(&vc->ar->winrct); - quad.ymax = BLI_RCT_SIZE_Y(&vc->ar->winrct); + quad.xmax = BLI_rcti_size_x(&vc->ar->winrct); + quad.ymax = BLI_rcti_size_y(&vc->ar->winrct); } /* set quad color */ diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c index e809267d076..bdd73cd6db3 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.c +++ b/source/blender/editors/sculpt_paint/paint_hide.c @@ -197,7 +197,7 @@ static void partialvis_update_grids(Object *ob, for (x = 0; x < key.grid_size; x++) { CCGElem *elem = CCG_grid_elem(&key, grids[g], x, y); const float *co = CCG_elem_co(&key, elem); - float mask = *CCG_elem_mask(&key, elem); + float mask = key.has_mask ? *CCG_elem_mask(&key, elem) : 0.0f; /* skip grid element if not in the effected area */ if (is_effected(area, planes, co, mask)) { @@ -251,7 +251,7 @@ static void clip_planes_from_rect(bContext *C, view3d_operator_needs_opengl(C); view3d_set_viewcontext(C, &vc); view3d_get_transformation(vc.ar, vc.rv3d, vc.obact, &mats); - ED_view3d_calc_clipping(&bb, clip_planes, &mats, rect); + ED_view3d_clipping_calc(&bb, clip_planes, &mats, rect); mul_m4_fl(clip_planes, -1.0f); } @@ -388,7 +388,7 @@ void PAINT_OT_hide_show(struct wmOperatorType *ot) ot->modal = WM_border_select_modal; ot->exec = hide_show_exec; /* sculpt-only for now */ - ot->poll = sculpt_mode_poll; + ot->poll = sculpt_mode_poll_view3d; ot->flag = OPTYPE_REGISTER; diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 64430a263f0..e00a8776bea 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -113,26 +113,26 @@ #define IMAPAINT_CHAR_TO_FLOAT(c) ((c) / 255.0f) #define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { \ - (c)[0]= FTOCHAR((f)[0]); \ - (c)[1]= FTOCHAR((f)[1]); \ - (c)[2]= FTOCHAR((f)[2]); \ + (c)[0] = FTOCHAR((f)[0]); \ + (c)[1] = FTOCHAR((f)[1]); \ + (c)[2] = FTOCHAR((f)[2]); \ } (void)0 #define IMAPAINT_FLOAT_RGBA_TO_CHAR(c, f) { \ - (c)[0]= FTOCHAR((f)[0]); \ - (c)[1]= FTOCHAR((f)[1]); \ - (c)[2]= FTOCHAR((f)[2]); \ - (c)[3]= FTOCHAR((f)[3]); \ + (c)[0] = FTOCHAR((f)[0]); \ + (c)[1] = FTOCHAR((f)[1]); \ + (c)[2] = FTOCHAR((f)[2]); \ + (c)[3] = FTOCHAR((f)[3]); \ } (void)0 #define IMAPAINT_CHAR_RGB_TO_FLOAT(f, c) { \ - (f)[0]= IMAPAINT_CHAR_TO_FLOAT((c)[0]); \ - (f)[1]= IMAPAINT_CHAR_TO_FLOAT((c)[1]); \ - (f)[2]= IMAPAINT_CHAR_TO_FLOAT((c)[2]); \ + (f)[0] = IMAPAINT_CHAR_TO_FLOAT((c)[0]); \ + (f)[1] = IMAPAINT_CHAR_TO_FLOAT((c)[1]); \ + (f)[2] = IMAPAINT_CHAR_TO_FLOAT((c)[2]); \ } (void)0 #define IMAPAINT_CHAR_RGBA_TO_FLOAT(f, c) { \ - (f)[0]= IMAPAINT_CHAR_TO_FLOAT((c)[0]); \ - (f)[1]= IMAPAINT_CHAR_TO_FLOAT((c)[1]); \ - (f)[2]= IMAPAINT_CHAR_TO_FLOAT((c)[2]); \ - (f)[3]= IMAPAINT_CHAR_TO_FLOAT((c)[3]); \ + (f)[0] = IMAPAINT_CHAR_TO_FLOAT((c)[0]); \ + (f)[1] = IMAPAINT_CHAR_TO_FLOAT((c)[1]); \ + (f)[2] = IMAPAINT_CHAR_TO_FLOAT((c)[2]); \ + (f)[3] = IMAPAINT_CHAR_TO_FLOAT((c)[3]); \ } (void)0 #define IMAPAINT_FLOAT_RGB_COPY(a, b) copy_v3_v3(a, b) @@ -173,7 +173,7 @@ typedef struct ImagePaintState { } ImagePaintState; typedef struct ImagePaintPartialRedraw { - int x1, y1, x2, y2; + int x1, y1, x2, y2; /* XXX, could use 'rcti' */ int enabled; } ImagePaintPartialRedraw; @@ -240,8 +240,6 @@ typedef struct ImagePaintRegion { /* vert flags */ #define PROJ_VERT_CULL 1 -#define PI_80_DEG ((M_PI_2 / 9) * 8) - /* This is mainly a convenience struct used so we can keep an array of images we use * Thir imbufs, etc, in 1 array, When using threads this array is copied for each thread * because 'partRedrawRect' and 'touch' values would not be thread safe */ @@ -785,7 +783,7 @@ static int project_paint_PickColor(const ProjPaintState *ps, float pt[2], float else { //xi = (int)((uv[0]*ibuf->x) + 0.5f); //yi = (int)((uv[1]*ibuf->y) + 0.5f); - //if (xi<0 || xi>=ibuf->x || yi<0 || yi>=ibuf->y) return 0; + //if (xi < 0 || xi >= ibuf->x || yi < 0 || yi >= ibuf->y) return 0; /* wrap */ xi = ((int)(uv[0] * ibuf->x)) % ibuf->x; @@ -905,7 +903,7 @@ static int project_bucket_point_occluded(const ProjPaintState *ps, LinkNode *buc else isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3], w, ps->is_ortho); - /* Note, if isect_ret==-1 then we don't want to test the other side of the quad */ + /* Note, if (isect_ret == -1) then we don't want to test the other side of the quad */ if (isect_ret == 0 && mf->v4) { if (do_clip) isect_ret = project_paint_occlude_ptv_clip(ps, mf, pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], 1); @@ -944,7 +942,7 @@ static int line_isect_y(const float p1[2], const float p2[2], const float y_leve if (y_diff < 0.000001f) { *x_isect = (p1[0] + p2[0]) * 0.5f; - return ISECT_TRUE; + return ISECT_TRUE; } if (p1[1] > y_level && p2[1] < y_level) { @@ -977,7 +975,7 @@ static int line_isect_x(const float p1[2], const float p2[2], const float x_leve if (x_diff < 0.000001f) { /* yuck, vertical line, we cant do much here */ *y_isect = (p1[0] + p2[0]) * 0.5f; - return ISECT_TRUE; + return ISECT_TRUE; } if (p1[0] > x_level && p2[0] < x_level) { @@ -1005,7 +1003,7 @@ static int cmp_uv(const float vec2a[2], const float vec2b[2]) float ya = (float)fmodf(vec2a[1], 1.0f); float xb = (float)fmodf(vec2b[0], 1.0f); - float yb = (float)fmodf(vec2b[1], 1.0f); + float yb = (float)fmodf(vec2b[1], 1.0f); if (xa < 0.0f) xa += 1.0f; if (ya < 0.0f) ya += 1.0f; @@ -1862,7 +1860,7 @@ static int project_bucket_isect_circle(const float cent[2], const float radius_s /* lower left out of radius test */ if (cent[1] < bucket_bounds->ymin) { return (len_squared_v2v2_alt(cent, bucket_bounds->xmin, bucket_bounds->ymin) < radius_squared) ? 1 : 0; - } + } /* top left test */ else if (cent[1] > bucket_bounds->ymax) { return (len_squared_v2v2_alt(cent, bucket_bounds->xmin, bucket_bounds->ymax) < radius_squared) ? 1 : 0; @@ -1872,7 +1870,7 @@ static int project_bucket_isect_circle(const float cent[2], const float radius_s /* lower right out of radius test */ if (cent[1] < bucket_bounds->ymin) { return (len_squared_v2v2_alt(cent, bucket_bounds->xmax, bucket_bounds->ymin) < radius_squared) ? 1 : 0; - } + } /* top right test */ else if (cent[1] > bucket_bounds->ymax) { return (len_squared_v2v2_alt(cent, bucket_bounds->xmax, bucket_bounds->ymax) < radius_squared) ? 1 : 0; @@ -2113,7 +2111,7 @@ static void project_bucket_clip_face( if ((inside_bucket_flag & ISECT_2) == 0) { copy_v2_v2(isectVCosSS[*tot], v1_clipSS); (*tot)++; } if ((inside_bucket_flag & ISECT_3) == 0) { copy_v2_v2(isectVCosSS[*tot], v2_clipSS); (*tot)++; } } - } + } if ((inside_bucket_flag & (ISECT_3 | ISECT_1)) != (ISECT_3 | ISECT_1)) { if (line_clip_rect2f(bucket_bounds, v3coSS, v1coSS, v1_clipSS, v2_clipSS)) { @@ -2322,7 +2320,7 @@ static int IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot) return 1; } -/* One of the most important function for projectiopn painting, since it selects the pixels to be added into each bucket. +/* One of the most important function for projection painting, since it selects the pixels to be added into each bucket. * initialize pixels from this face where it intersects with the bucket_index, optionally initialize pixels for removing seams */ static void project_paint_face_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, rctf *bucket_bounds, const ImBuf *ibuf, const short clamp_u, const short clamp_v) { @@ -2396,7 +2394,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i tf_uv_pxoffset[1][1] = tf->uv[1][1] - yhalfpx; tf_uv_pxoffset[2][0] = tf->uv[2][0] - xhalfpx; - tf_uv_pxoffset[2][1] = tf->uv[2][1] - yhalfpx; + tf_uv_pxoffset[2][1] = tf->uv[2][1] - yhalfpx; if (mf->v4) { vCo[3] = ps->dm_mvert[mf->v4].co; @@ -2556,7 +2554,6 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i float (*outset_uv)[2] = ps->faceSeamUVs[face_index]; float insetCos[4][3]; /* inset face coords. NOTE!!! ScreenSace for ortho, Worldspace in prespective view */ - float fac; float *vCoSS[4]; /* vertex screenspace coords */ float bucket_clip_edges[2][2]; /* store the screenspace coords of the face, clipped by the bucket's screen aligned rectangle */ @@ -2638,6 +2635,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i /* test we're inside uvspace bucket and triangle bounds */ if (isect_point_quad_v2(uv, seam_subsection[0], seam_subsection[1], seam_subsection[2], seam_subsection[3])) { + float fac; /* We need to find the closest point along the face edge, * getting the screen_px_from_*** wont work because our actual location @@ -2672,9 +2670,9 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i #if 1 /* get the UV on the line since we want to copy the pixels from there for bleeding */ float uv_close[2]; - float fac = closest_to_line_v2(uv_close, uv, tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2]); - if (fac < 0.0f) copy_v2_v2(uv_close, tf_uv_pxoffset[fidx1]); - else if (fac > 1.0f) copy_v2_v2(uv_close, tf_uv_pxoffset[fidx2]); + float uv_fac = closest_to_line_v2(uv_close, uv, tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2]); + if (uv_fac < 0.0f) copy_v2_v2(uv_close, tf_uv_pxoffset[fidx1]); + else if (uv_fac > 1.0f) copy_v2_v2(uv_close, tf_uv_pxoffset[fidx2]); if (side) { barycentric_weights_v2(tf_uv_pxoffset[0], tf_uv_pxoffset[2], tf_uv_pxoffset[3], uv_close, w); @@ -2685,16 +2683,16 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i #else /* this is buggy with quads, don't use for now */ /* Cheat, we know where we are along the edge so work out the weights from that */ - fac = fac1 + (fac * (fac2 - fac1)); + uv_fac = fac1 + (uv_fac * (fac2 - fac1)); w[0] = w[1] = w[2] = 0.0; if (side) { - w[fidx1 ? fidx1 - 1 : 0] = 1.0f - fac; - w[fidx2 ? fidx2 - 1 : 0] = fac; + w[fidx1 ? fidx1 - 1 : 0] = 1.0f - uv_fac; + w[fidx2 ? fidx2 - 1 : 0] = uv_fac; } else { - w[fidx1] = 1.0f - fac; - w[fidx2] = fac; + w[fidx1] = 1.0f - uv_fac; + w[fidx2] = uv_fac; } #endif } @@ -3138,7 +3136,7 @@ static void project_paint_begin(ProjPaintState *ps) ps->is_ortho = params.is_ortho; } - /* same as view3d_get_object_project_mat */ + /* same as #ED_view3d_ob_project_mat_get */ mult_m4_m4m4(vmat, viewmat, ps->ob->obmat); mult_m4_m4m4(ps->projectMat, winmat, vmat); } @@ -3434,7 +3432,7 @@ static void project_paint_begin_clone(ProjPaintState *ps, int mouse[2]) mul_m4_v4(ps->projectMat, projCo); ps->cloneOffset[0] = mouse[0] - ((float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projCo[0] / projCo[3]); ps->cloneOffset[1] = mouse[1] - ((float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projCo[1] / projCo[3]); - } + } } static void project_paint_end(ProjPaintState *ps) @@ -3563,7 +3561,7 @@ static void project_paint_end(ProjPaintState *ps) ps->dm->release(ps->dm); } -/* 1= an undo, -1 is a redo. */ +/* 1 = an undo, -1 is a redo. */ static void partial_redraw_array_init(ImagePaintPartialRedraw *pr) { int tot = PROJ_BOUNDBOX_SQUARED; @@ -3585,11 +3583,11 @@ static int partial_redraw_array_merge(ImagePaintPartialRedraw *pr, ImagePaintPar { int touch = 0; while (tot--) { - pr->x1 = MIN2(pr->x1, pr_other->x1); - pr->y1 = MIN2(pr->y1, pr_other->y1); + pr->x1 = min_ii(pr->x1, pr_other->x1); + pr->y1 = min_ii(pr->y1, pr_other->y1); - pr->x2 = MAX2(pr->x2, pr_other->x2); - pr->y2 = MAX2(pr->y2, pr_other->y2); + pr->x2 = max_ii(pr->x2, pr_other->x2); + pr->y2 = max_ii(pr->y2, pr_other->y2); if (pr->x2 != -1) touch = 1; @@ -4034,11 +4032,11 @@ static void *do_projectpaint_thread(void *ph_v) /* end copy */ last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index; - last_partial_redraw_cell->x1 = MIN2(last_partial_redraw_cell->x1, projPixel->x_px); - last_partial_redraw_cell->y1 = MIN2(last_partial_redraw_cell->y1, projPixel->y_px); + last_partial_redraw_cell->x1 = min_ii(last_partial_redraw_cell->x1, (int)projPixel->x_px); + last_partial_redraw_cell->y1 = min_ii(last_partial_redraw_cell->y1, (int)projPixel->y_px); - last_partial_redraw_cell->x2 = MAX2(last_partial_redraw_cell->x2, projPixel->x_px + 1); - last_partial_redraw_cell->y2 = MAX2(last_partial_redraw_cell->y2, projPixel->y_px + 1); + last_partial_redraw_cell->x2 = max_ii(last_partial_redraw_cell->x2, (int)projPixel->x_px + 1); + last_partial_redraw_cell->y2 = max_ii(last_partial_redraw_cell->y2, (int)projPixel->y_px + 1); switch (tool) { @@ -4102,7 +4100,7 @@ static int project_paint_op(void *state, ImBuf *UNUSED(ibufb), const float lastp { /* First unpack args from the struct */ ProjPaintState *ps = (ProjPaintState *)state; - int touch_any = 0; + int touch_any = 0; ProjectHandle handles[BLENDER_MAX_THREADS]; ListBase threads; @@ -4135,7 +4133,7 @@ static int project_paint_op(void *state, ImBuf *UNUSED(ibufb), const float lastp /* image bounds */ for (i = 0; i < ps->image_tot; i++) { handles[a].projImages[i].partRedrawRect = (ImagePaintPartialRedraw *)BLI_memarena_alloc(ps->arena_mt[a], sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); - memcpy(handles[a].projImages[i].partRedrawRect, ps->projImages[i].partRedrawRect, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); + memcpy(handles[a].projImages[i].partRedrawRect, ps->projImages[i].partRedrawRect, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); } if (ps->thread_tot > 1) @@ -4224,10 +4222,10 @@ static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, imapaintpartial.enabled = 1; } else { - imapaintpartial.x1 = MIN2(imapaintpartial.x1, x); - imapaintpartial.y1 = MIN2(imapaintpartial.y1, y); - imapaintpartial.x2 = MAX2(imapaintpartial.x2, x + w); - imapaintpartial.y2 = MAX2(imapaintpartial.y2, y + h); + imapaintpartial.x1 = min_ii(imapaintpartial.x1, x); + imapaintpartial.y1 = min_ii(imapaintpartial.y1, y); + imapaintpartial.x2 = max_ii(imapaintpartial.x2, x + w); + imapaintpartial.y2 = max_ii(imapaintpartial.y2, y + h); } w = ((x + w - 1) >> IMAPAINT_TILE_BITS); @@ -4251,7 +4249,7 @@ static void imapaint_image_update(Scene *scene, SpaceImage *sima, Image *image, IMB_partial_display_buffer_update(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect, ibuf->x, 0, 0, &scene->view_settings, &scene->display_settings, imapaintpartial.x1, imapaintpartial.y1, - imapaintpartial.x2, imapaintpartial.y2); + imapaintpartial.x2, imapaintpartial.y2, FALSE); } else { ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; @@ -4265,7 +4263,7 @@ static void imapaint_image_update(Scene *scene, SpaceImage *sima, Image *image, int w = imapaintpartial.x2 - imapaintpartial.x1; int h = imapaintpartial.y2 - imapaintpartial.y1; /* Testing with partial update in uv editor too */ - GPU_paint_update_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h, 0); //!texpaint); + GPU_paint_update_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h); //!texpaint); } } @@ -4556,7 +4554,7 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima) else if (ima->packedfile && ima->rr) { s->warnpackedfile = ima->id.name + 2; return 0; - } + } else if (ibuf && ibuf->channels != 4) { s->warnmultifile = ima->id.name + 2; return 0; @@ -4596,10 +4594,13 @@ static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, { ImBuf *ibuf = BKE_image_get_ibuf(image, s->sima ? &s->sima->iuser : NULL); float pos[2]; + int is_data; if (!ibuf) return 0; + is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA; + pos[0] = uv[0] * ibuf->x; pos[1] = uv[1] * ibuf->y; @@ -4608,7 +4609,7 @@ static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, /* OCIO_TODO: float buffers are now always linear, so always use color correction * this should probably be changed when texture painting color space is supported */ - if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, TRUE)) { + if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, is_data == FALSE)) { if (update) imapaint_image_update(s->scene, s->sima, image, ibuf, texpaint); return 1; @@ -5047,7 +5048,7 @@ static void paint_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) pop->prevmouse[1] = mouse[1]; } - else { + else { redraw = imapaint_paint_stroke(&pop->vc, &pop->s, pop->painter, pop->mode == PAINT_MODE_3D, pop->prevmouse, mouse, time, pressure); pop->prevmouse[0] = mouse[0]; pop->prevmouse[1] = mouse[1]; @@ -5065,7 +5066,7 @@ static void paint_brush_exit_tex(Brush *brush) MTex *mtex = &brush->mtex; if (mtex->tex && mtex->tex->nodetree) ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1); - } + } } static void paint_exit(bContext *C, wmOperator *op) @@ -5265,10 +5266,12 @@ static int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy) if (!rv3d) { SpaceImage *sima = CTX_wm_space_image(C); ARegion *ar = CTX_wm_region(C); - - ED_space_image_get_zoom(sima, ar, zoomx, zoomy); - return 1; + if (sima->mode == SI_MODE_PAINT) { + ED_space_image_get_zoom(sima, ar, zoomx, zoomy); + + return 1; + } } *zoomx = *zoomy = 1; @@ -5284,24 +5287,21 @@ static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata) #define PX_SIZE_FADE_MIN 4.0f Scene *scene = CTX_data_scene(C); - //Brush *brush= image_paint_brush(C); + //Brush *brush = image_paint_brush(C); Paint *paint = paint_get_active_from_context(C); Brush *brush = paint_brush(paint); if (paint && brush && paint->flags & PAINT_SHOW_BRUSH) { - ToolSettings *ts; float zoomx, zoomy; const float size = (float)BKE_brush_size_get(scene, brush); short use_zoom; float pixel_size; float alpha = 0.5f; - ts = scene->toolsettings; - use_zoom = get_imapaint_zoom(C, &zoomx, &zoomy) && - !(ts->use_uv_sculpt && (scene->basact->object->mode == OB_MODE_EDIT)); + use_zoom = get_imapaint_zoom(C, &zoomx, &zoomy); if (use_zoom) { - pixel_size = size * maxf(zoomx, zoomy); + pixel_size = size * max_ff(zoomx, zoomy); } else { pixel_size = size; @@ -5365,7 +5365,7 @@ void ED_space_image_paint_update(wmWindowManager *wm, ToolSettings *settings) for (win = wm->windows.first; win; win = win->next) for (sa = win->screen->areabase.first; sa; sa = sa->next) if (sa->spacetype == SPACE_IMAGE) - if (((SpaceImage*)sa->spacedata.first)->mode == SI_MODE_PAINT) + if (((SpaceImage *)sa->spacedata.first)->mode == SI_MODE_PAINT) enabled = TRUE; if (enabled) { @@ -5653,7 +5653,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; if (BKE_object_obdata_is_libdata(ob)) { - BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata"); + BKE_report(op->reports, RPT_ERROR, "Cannot edit external libdata"); return OPERATOR_CANCELLED; } @@ -5889,7 +5889,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) if (!ibuf) { /* Mostly happens when OpenGL offscreen buffer was failed to create, */ /* but could be other reasons. Should be handled in the future. nazgul */ - BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL offscreen buffer: %s", err_out); + BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer: %s", err_out); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 794e7755636..162e2fa15d6 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -51,7 +51,7 @@ struct wmOperator; struct wmOperatorType; /* paint_stroke.c */ -typedef int (*StrokeGetLocation)(struct bContext *C, float location[3], float mouse[2]); +typedef int (*StrokeGetLocation)(struct bContext *C, float location[3], const float mouse[2]); typedef int (*StrokeTestStart)(struct bContext *C, struct wmOperator *op, const float mouse[2]); typedef void (*StrokeUpdateStep)(struct bContext *C, struct PaintStroke *stroke, struct PointerRNA *itemptr); typedef void (*StrokeDone)(const struct bContext *C, struct PaintStroke *stroke); diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index e309bdb99cb..697d7c63d1f 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -54,6 +54,7 @@ #include "WM_types.h" #include "ED_screen.h" +#include "ED_sculpt.h" #include "paint_intern.h" #include "sculpt_intern.h" /* for undo push */ @@ -77,7 +78,9 @@ static void mask_flood_fill_set_elem(float *elem, static int mask_flood_fill_exec(bContext *C, wmOperator *op) { ARegion *ar = CTX_wm_region(C); + struct Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); + struct MultiresModifierData *mmd = sculpt_multires_active(scene, ob); PaintMaskFloodMode mode; float value; DerivedMesh *dm; @@ -88,7 +91,9 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op) mode = RNA_enum_get(op->ptr, "mode"); value = RNA_float_get(op->ptr, "value"); - dm = mesh_get_derived_final(CTX_data_scene(C), ob, CD_MASK_BAREMESH); + ED_sculpt_mask_layers_ensure(ob, mmd); + + dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); pbvh = dm->getPBVH(ob, dm); ob->sculpt->pbvh = pbvh; diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index 39a95300d5d..40dcb92f087 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -93,7 +93,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); - // Object *ob= CTX_data_active_object(C); + // Object *ob = CTX_data_active_object(C); float scalar = RNA_float_get(op->ptr, "scalar"); if (brush) { diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 7657f78596a..6396a0c2cbc 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -139,13 +139,13 @@ static float event_tablet_data(wmEvent *event, int *pen_flip) } /* Put the location of the next stroke dot into the stroke RNA and apply it to the mesh */ -static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *event, float mouse_in[2]) +static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *event, const float mouse_in[2]) { Scene *scene = CTX_data_scene(C); Paint *paint = paint_get_active_from_context(C); Brush *brush = paint_brush(paint); PaintStroke *stroke = op->customdata; - float mouse[3]; + float mouse_out[2]; PointerRNA itemptr; float location[3]; float pressure; @@ -159,24 +159,24 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *ev if (stroke->vc.obact->sculpt) { float delta[2]; - BKE_brush_jitter_pos(scene, brush, mouse_in, mouse); + BKE_brush_jitter_pos(scene, brush, mouse_in, mouse_out); /* XXX: meh, this is round about because * BKE_brush_jitter_pos isn't written in the best way to * be reused here */ if (brush->flag & BRUSH_JITTER_PRESSURE) { - sub_v2_v2v2(delta, mouse, mouse_in); + sub_v2_v2v2(delta, mouse_out, mouse_in); mul_v2_fl(delta, pressure); - add_v2_v2v2(mouse, mouse_in, delta); + add_v2_v2v2(mouse_out, mouse_in, delta); } } else { - copy_v2_v2(mouse, mouse_in); + copy_v2_v2(mouse_out, mouse_in); } /* TODO: can remove the if statement once all modes have this */ if (stroke->get_location) - stroke->get_location(C, location, mouse); + stroke->get_location(C, location, mouse_out); else zero_v3(location); @@ -184,12 +184,11 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *ev RNA_collection_add(op->ptr, "stroke", &itemptr); RNA_float_set_array(&itemptr, "location", location); - RNA_float_set_array(&itemptr, "mouse", mouse); + RNA_float_set_array(&itemptr, "mouse", mouse_out); RNA_boolean_set(&itemptr, "pen_flip", pen_flip); RNA_float_set(&itemptr, "pressure", pressure); - stroke->last_mouse_position[0] = mouse[0]; - stroke->last_mouse_position[1] = mouse[1]; + copy_v2_v2(stroke->last_mouse_position, mouse_out); stroke->update_step(C, stroke, &itemptr); } @@ -256,7 +255,7 @@ static int paint_space_stroke(bContext *C, wmOperator *op, wmEvent *event, const if (pressure > FLT_EPSILON) { /* brushes can have a minimum size of 1.0 but with pressure it can be smaller then a pixel * causing very high step sizes, hanging blender [#32381] */ - const float size_clamp = maxf(1.0f, BKE_brush_size_get(scene, stroke->brush) * pressure); + const float size_clamp = max_ff(1.0f, BKE_brush_size_get(scene, stroke->brush) * pressure); scale = (size_clamp * stroke->brush->spacing / 50.0f) / length; if (scale > FLT_EPSILON) { mul_v2_fl(vec, scale); @@ -407,10 +406,10 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) paint_stroke_add_sample(p, stroke, event->x, event->y); paint_stroke_sample_average(stroke, &sample_average); - // let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously! - // this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it - // since the 2D deltas are zero -- code in this file needs to be updated to use the - // post-NDOF_MOTION MOUSEMOVE + /* let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously! + * this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it + * since the 2D deltas are zero -- code in this file needs to be updated to use the + * post-NDOF_MOTION MOUSEMOVE */ if (event->type == NDOF_MOTION) return OPERATOR_PASS_THROUGH; @@ -524,8 +523,10 @@ int paint_poll(bContext *C) { Paint *p = paint_get_active_from_context(C); Object *ob = CTX_data_active_object(C); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); return p && ob && paint_brush(p) && - CTX_wm_area(C)->spacetype == SPACE_VIEW3D && - CTX_wm_region(C)->regiontype == RGN_TYPE_WINDOW; + (sa && sa->spacetype == SPACE_VIEW3D) && + (ar && ar->regiontype == RGN_TYPE_WINDOW); } diff --git a/source/blender/editors/sculpt_paint/paint_undo.c b/source/blender/editors/sculpt_paint/paint_undo.c index f5b9aa742c6..e406d4f5c3b 100644 --- a/source/blender/editors/sculpt_paint/paint_undo.c +++ b/source/blender/editors/sculpt_paint/paint_undo.c @@ -152,7 +152,9 @@ static int undo_stack_step(bContext *C, UndoStack *stack, int step, const char * UndoElem *undo; if (step == 1) { - if (stack->current == NULL) ; + if (stack->current == NULL) { + /* pass */ + } else { if (!name || strcmp(stack->current->name, name) == 0) { if (G.debug & G_DEBUG_WM) { @@ -165,7 +167,9 @@ static int undo_stack_step(bContext *C, UndoStack *stack, int step, const char * } } else if (step == -1) { - if ((stack->current != NULL && stack->current->next == NULL) || stack->elems.first == NULL) ; + if ((stack->current != NULL && stack->current->next == NULL) || stack->elems.first == NULL) { + /* pass */ + } else { if (!name || strcmp(stack->current->name, name) == 0) { undo = (stack->current && stack->current->next) ? stack->current->next : stack->elems.first; @@ -254,7 +258,9 @@ int ED_undo_paint_valid(int type, const char *name) else return 0; - if (stack->current == NULL) ; + if (stack->current == NULL) { + /* pass */ + } else { if (name && strcmp(stack->current->name, name) == 0) return 1; diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index df64e1c9d90..c5eff1a1f0e 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -98,7 +98,7 @@ int paint_convert_bb_to_rect(rcti *rect, vec[1] = j ? bb_min[1] : bb_max[1]; vec[2] = k ? bb_min[2] : bb_max[2]; /* convert corner to screen space */ - ED_view3d_project_float_v2(ar, vec, proj, projection_mat); + ED_view3d_project_float_v2_m4(ar, vec, proj, projection_mat); /* expand 2D rectangle */ /* we could project directly to int? */ @@ -137,7 +137,7 @@ void paint_calc_redraw_planes(float planes[4][4], rect.ymin -= 2; rect.ymax += 2; - ED_view3d_calc_clipping(&bb, planes, &mats, &rect); + ED_view3d_clipping_calc(&bb, planes, &mats, &rect); mul_m4_fl(planes, -1.0f); } @@ -201,7 +201,7 @@ static void imapaint_project(Object *ob, float model[][4], float proj[][4], cons static void imapaint_tri_weights(Object *ob, const float v1[3], const float v2[3], const float v3[3], - const float co[3], float w[3]) + const float co[2], float w[3]) { float pv1[4], pv2[4], pv3[4], h[3], divw; float model[4][4], proj[4][4], wmat[3][3], invwmat[3][3]; @@ -248,19 +248,25 @@ static void imapaint_tri_weights(Object *ob, void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, const int xy[2], float uv[2]) { DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); - const int *index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); MTFace *tface = dm->getTessFaceDataArray(dm, CD_MTFACE), *tf; int numfaces = dm->getNumTessFaces(dm), a, findex; float p[2], w[3], absw, minabsw; MFace mf; MVert mv[4]; + /* double lookup */ + const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); + if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { + index_mf_to_mpoly = index_mp_to_orig = NULL; + } + minabsw = 1e10; uv[0] = uv[1] = 0.0; /* test all faces in the derivedmesh with the original index of the picked face */ for (a = 0; a < numfaces; a++) { - findex = index ? index[a] : a; + findex = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a; if (findex == faceindex) { dm->getTessFace(dm, a, &mf); diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index fd5044afc44..56d46a22e10 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -79,6 +79,7 @@ #include "WM_api.h" #include "WM_types.h" +#include "GPU_buffers.h" #include "ED_armature.h" #include "ED_mesh.h" @@ -106,18 +107,40 @@ static int vertex_paint_use_fast_update_check(Object *ob) /* if the polygons from the mesh and the 'derivedFinal' match * we can assume that no modifiers are applied and that its worth adding tessellated faces * so 'vertex_paint_use_fast_update_check()' returns TRUE */ -static int vertex_paint_use_tessface_check(Object *ob) +static int vertex_paint_use_tessface_check(Object *ob, Mesh *me) { DerivedMesh *dm = ob->derivedFinal; - if (dm) { - Mesh *me = BKE_mesh_from_object(ob); - return (me->mpoly == CustomData_get_layer(&dm->faceData, CD_MPOLY)); + if (me && dm) { + return (me->mpoly == CustomData_get_layer(&dm->polyData, CD_MPOLY)); } return FALSE; } +static void update_tessface_data(Object *ob, Mesh *me) +{ + if (vertex_paint_use_tessface_check(ob, me)) { + /* assume if these exist, that they are up to date & valid */ + if (!me->mcol || !me->mface) { + /* should always be true */ + /* XXX Why this clearing? tessface_calc will reset it anyway! */ +/* if (me->mcol) {*/ +/* memset(me->mcol, 255, 4 * sizeof(MCol) * me->totface);*/ +/* }*/ + + /* create tessfaces because they will be used for drawing & fast updates */ + BKE_mesh_tessface_calc(me); /* does own call to update pointers */ + } + } + else { + if (me->totface) { + /* this wont be used, theres no need to keep it */ + BKE_mesh_tessface_clear(me); + } + } + +} /* polling - retrieve whether cursor should be set or operator should be done */ /* Returns true if vertex paint mode is active */ @@ -134,7 +157,7 @@ int vertex_paint_poll(bContext *C) paint_brush(&CTX_data_tool_settings(C)->vpaint->paint)) { ScrArea *sa = CTX_wm_area(C); - if (sa->spacetype == SPACE_VIEW3D) { + if (sa && sa->spacetype == SPACE_VIEW3D) { ARegion *ar = CTX_wm_region(C); if (ar->regiontype == RGN_TYPE_WINDOW) return 1; @@ -326,29 +349,12 @@ static void make_vertexcol(Object *ob) /* single ob */ CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface); } if (!me->mloopcol) { - CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop); + CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop); } mesh_update_customdata_pointers(me, TRUE); } - if (vertex_paint_use_tessface_check(ob)) { - /* assume if these exist, that they are up to date & valid */ - if (!me->mcol || !me->mface) { - /* should always be true */ - if (me->mcol) { - memset(me->mcol, 255, 4 * sizeof(MCol) * me->totface); - } - - /* create tessfaces because they will be used for drawing & fast updates */ - BKE_mesh_tessface_calc(me); /* does own call to update pointers */ - } - } - else { - if (me->totface) { - /* this wont be used, theres no need to keep it */ - BKE_mesh_tessface_clear(me); - } - } + update_tessface_data(ob, me); //if (shade) // shadeMeshMCol(scene, ob, me); @@ -846,20 +852,22 @@ static int sample_backbuf_area(ViewContext *vc, int *indexar, int totface, int x static float calc_vp_strength_dl(VPaint *vp, ViewContext *vc, const float vert_nor[3], const float mval[2], const float brush_size_pressure) { - Brush *brush = paint_brush(&vp->paint); - float dist_squared; - float vertco[2], delta[2]; + float vertco[2]; - project_float_noclip(vc->ar, vert_nor, vertco); - sub_v2_v2v2(delta, mval, vertco); - dist_squared = dot_v2v2(delta, delta); /* len squared */ - if (dist_squared > brush_size_pressure * brush_size_pressure) { - return 0.0f; - } - else { - const float dist = sqrtf(dist_squared); - return BKE_brush_curve_strength_clamp(brush, dist, brush_size_pressure); + if (ED_view3d_project_float_global(vc->ar, vert_nor, vertco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + float delta[2]; + float dist_squared; + + sub_v2_v2v2(delta, mval, vertco); + dist_squared = dot_v2v2(delta, delta); /* len squared */ + if (dist_squared <= brush_size_pressure * brush_size_pressure) { + Brush *brush = paint_brush(&vp->paint); + const float dist = sqrtf(dist_squared); + return BKE_brush_curve_strength_clamp(brush, dist, brush_size_pressure); + } } + + return 0.0f; } static float calc_vp_alpha_dl(VPaint *vp, ViewContext *vc, @@ -1524,7 +1532,7 @@ static void enforce_locks(MDeformVert *odv, MDeformVert *ndv, if (total_changed > 1 && do_multipaint) { float undo_change = get_mp_change(ndv, defbase_tot, defbase_sel, left_over); multipaint_selection(ndv, defbase_tot, undo_change, defbase_sel); - } + } /* or designatedw is still -1 put weight back as evenly as possible */ else { redistribute_change(ndv, defbase_tot, change_status, 2, -2, left_over, total_changed, do_auto_normalize); @@ -1533,7 +1541,6 @@ static void enforce_locks(MDeformVert *odv, MDeformVert *ndv, } else { /* reset the weights */ - unsigned int i; MDeformWeight *dw_old = odv->dw; MDeformWeight *dw_new = ndv->dw; @@ -2047,7 +2054,6 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNU Object *ob = CTX_data_active_object(C); struct WPaintData *wpd; Mesh *me; - bDeformGroup *dg; float mat[4][4], imat[4][4]; @@ -2096,12 +2102,14 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNU return FALSE; } - /* check if we are attempting to paint onto a locked vertex group, - * and other options disallow it from doing anything useful */ - dg = BLI_findlink(&ob->defbase, (ob->actdef - 1)); - if (dg->flag & DG_LOCK_WEIGHT) { - BKE_report(op->reports, RPT_WARNING, "Active group is locked, aborting"); - return FALSE; + { + /* check if we are attempting to paint onto a locked vertex group, + * and other options disallow it from doing anything useful */ + bDeformGroup *dg = BLI_findlink(&ob->defbase, (ob->actdef - 1)); + if (dg->flag & DG_LOCK_WEIGHT) { + BKE_report(op->reports, RPT_WARNING, "Active group is locked, aborting"); + return FALSE; + } } /* ALLOCATIONS! no return after this line */ @@ -2227,19 +2235,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P if (indexar[0]) totindex = 1; else totindex = 0; } - - if (wp->flag & VP_COLINDEX) { - for (index = 0; index < totindex; index++) { - if (indexar[index] && indexar[index] <= me->totpoly) { - MPoly *mpoly = ((MPoly *)me->mpoly) + (indexar[index] - 1); - - if (mpoly->mat_nr != ob->actcol - 1) { - indexar[index] = 0; - } - } - } - } - + if ((me->editflag & ME_EDIT_PAINT_MASK) && me->mpoly) { for (index = 0; index < totindex; index++) { if (indexar[index] && indexar[index] <= me->totpoly) { @@ -2382,7 +2378,8 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) static int wpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) { - + int retval; + op->customdata = paint_stroke_new(C, NULL, wpaint_stroke_test_start, wpaint_stroke_update_step, wpaint_stroke_done, event->type); @@ -2390,7 +2387,9 @@ static int wpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) /* add modal handler */ WM_event_add_modal_handler(C, op); - op->type->modal(C, op, event); + retval = op->type->modal(C, op, event); + OPERATOR_RETVAL_CHECK(retval); + BLI_assert(retval == OPERATOR_RUNNING_MODAL); return OPERATOR_RUNNING_MODAL; } @@ -2571,7 +2570,7 @@ static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me) vd->polyfacemap = BLI_memarena_alloc(vd->polyfacemap_arena, sizeof(ListBase) * me->totpoly); - origIndex = CustomData_get_layer(&me->fdata, CD_POLYINDEX); + origIndex = CustomData_get_layer(&me->fdata, CD_ORIGINDEX); mf = me->mface; if (!origIndex) @@ -2607,7 +2606,12 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const fl make_vertexcol(ob); if (me->mloopcol == NULL) return OPERATOR_CANCELLED; - + + /* Update tessface data if needed + * Added here too because e.g. switching to/from edit mode would remove tessface data, + * yet "fast_update" could still be used! */ + update_tessface_data(ob, me); + /* make mode data storage */ vpd = MEM_callocN(sizeof(struct VPaintData), "VPaintData"); paint_stroke_set_mode_data(stroke, vpd); @@ -2623,9 +2627,11 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const fl if (vertex_paint_use_fast_update_check(ob)) { vpaint_build_poly_facemap(vpd, me); vpd->use_fast_update = TRUE; +/* printf("Fast update!\n");*/ } else { vpd->use_fast_update = FALSE; +/* printf("No fast update!\n");*/ } /* for filtering */ @@ -2639,53 +2645,6 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const fl return 1; } -#if 0 -static void vpaint_paint_face(VPaint *vp, VPaintData *vpd, Object *ob, - const unsigned int index, const float mval[2], - const float brush_size_pressure, const float brush_alpha_pressure, - int UNUSED(flip)) -{ - ViewContext *vc = &vpd->vc; - Brush *brush = paint_brush(&vp->paint); - Mesh *me = BKE_mesh_from_object(ob); - MFace *mface = &me->mface[index]; - unsigned int *mcol = ((unsigned int *)me->mcol) + 4 * index; - unsigned int *mcolorig = ((unsigned int *)vp->vpaint_prev) + 4 * index; - float alpha; - int i; - - int brush_alpha_pressure_i; - - if ((vp->flag & VP_COLINDEX && mface->mat_nr != ob->actcol - 1) || - ((me->editflag & ME_EDIT_PAINT_MASK) && !(mface->flag & ME_FACE_SEL))) - return; - - if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) { - unsigned int fcol1 = mcol_blend(mcol[0], mcol[1], 128); - if (mface->v4) { - unsigned int fcol2 = mcol_blend(mcol[2], mcol[3], 128); - vpd->paintcol = mcol_blend(fcol1, fcol2, 128); - } - else { - vpd->paintcol = mcol_blend(mcol[2], fcol1, 170); - } - } - - brush_alpha_pressure_i = (int)(brush_alpha_pressure * 255.0f); - - for (i = 0; i < (mface->v4 ? 4 : 3); ++i) { - alpha = calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos + 6 * (&mface->v1)[i], - mval, brush_size_pressure, brush_alpha_pressure); - if (alpha) { - const int alpha_i = (int)(alpha * 255.0f); - mcol[i] = vpaint_blend(vp, mcol[i], mcolorig[i], vpd->paintcol, alpha_i, brush_alpha_pressure_i); - } - } -} -#endif - -/* BMESH version of vpaint_paint_face (commented above) */ - static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Object *ob, const unsigned int index, const float mval[2], const float brush_size_pressure, const float brush_alpha_pressure) @@ -2744,33 +2703,29 @@ static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Object *ob, } if (vpd->use_fast_update) { - -#ifdef CPYCOL -# undef CPYCOL -#endif -#define CPYCOL(c, l) (c)->a = (l)->a, (c)->r = (l)->r, (c)->g = (l)->g, (c)->b = (l)->b - /* update vertex colors for tessellations incrementally, * rather then regenerating the tessellation altogether */ for (e = vpd->polyfacemap[index].first; e; e = e->next) { - mf = me->mface + e->facenr; - mc = me->mcol + e->facenr * 4; + mf = &me->mface[e->facenr]; + mc = &me->mcol[e->facenr * 4]; ml = me->mloop + mpoly->loopstart; mlc = me->mloopcol + mpoly->loopstart; for (j = 0; j < mpoly->totloop; j++, ml++, mlc++) { - if (ml->v == mf->v1) - CPYCOL(mc, mlc); - else if (ml->v == mf->v2) - CPYCOL(mc + 1, mlc); - else if (ml->v == mf->v3) - CPYCOL(mc + 2, mlc); - else if (mf->v4 && ml->v == mf->v4) - CPYCOL(mc + 3, mlc); - + if (ml->v == mf->v1) { + MESH_MLOOPCOL_TO_MCOL(mlc, mc + 0); + } + else if (ml->v == mf->v2) { + MESH_MLOOPCOL_TO_MCOL(mlc, mc + 1); + } + else if (ml->v == mf->v3) { + MESH_MLOOPCOL_TO_MCOL(mlc, mc + 2); + } + else if (mf->v4 && ml->v == mf->v4) { + MESH_MLOOPCOL_TO_MCOL(mlc, mc + 3); + } } } -#undef CPYCOL } } @@ -2804,7 +2759,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P mval[0] -= vc->ar->winrct.xmin; mval[1] -= vc->ar->winrct.ymin; - + /* which faces are involved */ if (vp->flag & VP_AREA) { totindex = sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size_pressure); @@ -2814,19 +2769,6 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P if (indexar[0]) totindex = 1; else totindex = 0; } - - - if (vp->flag & VP_COLINDEX) { - for (index = 0; index < totindex; index++) { - if (indexar[index] && indexar[index] <= me->totpoly) { - MPoly *mpoly = ((MPoly *)me->mpoly) + (indexar[index] - 1); - - if (mpoly->mat_nr != ob->actcol - 1) { - indexar[index] = 0; - } - } - } - } if ((me->editflag & ME_EDIT_PAINT_MASK) && me->mpoly) { for (index = 0; index < totindex; index++) { @@ -2835,15 +2777,13 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P if ((mpoly->flag & ME_FACE_SEL) == 0) indexar[index] = 0; - } + } } } swap_m4m4(vc->rv3d->persmat, mat); - for (index = 0; index < totindex; index++) { - if (indexar[index] && indexar[index] <= me->totpoly) { vpaint_paint_poly(vp, vpd, ob, indexar[index] - 1, mval, brush_size_pressure, brush_alpha_pressure); } @@ -2864,6 +2804,10 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P * avoid this if we can! */ DAG_id_tag_update(ob->data, 0); } + else if (!GPU_buffer_legacy(ob->derivedFinal)) { + /* If using new VBO drawing, mark mcol as dirty to force colors gpu buffer refresh! */ + ob->derivedFinal->dirty |= DM_DIRTY_MCOL_UPDATE_DRAW; + } } static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) @@ -2891,7 +2835,8 @@ static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) { - + int retval; + op->customdata = paint_stroke_new(C, NULL, vpaint_stroke_test_start, vpaint_stroke_update_step, vpaint_stroke_done, event->type); @@ -2899,7 +2844,9 @@ static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) /* add modal handler */ WM_event_add_modal_handler(C, op); - op->type->modal(C, op, event); + retval = op->type->modal(C, op, event); + OPERATOR_RETVAL_CHECK(retval); + BLI_assert(retval == OPERATOR_RUNNING_MODAL); return OPERATOR_RUNNING_MODAL; } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 210477e3e5a..38dbdcd8337 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -771,7 +771,7 @@ static float tex_strength(SculptSession *ss, Brush *br, float point[3], if (ss->cache->radial_symmetry_pass) mul_m4_v3(ss->cache->symm_rot_mat_inv, symm_point); - ED_view3d_project_float_v2(ss->cache->vc->ar, symm_point, point_2d, ss->cache->projection_mat); + ED_view3d_project_float_v2_m4(ss->cache->vc->ar, symm_point, point_2d, ss->cache->projection_mat); if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { /* keep coordinates relative to mouse */ @@ -1225,7 +1225,7 @@ static void do_mesh_smooth_brush(Sculpt *sd, SculptSession *ss, PBVHNode *node, if (sculpt_brush_test(&test, vd.co)) { const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist, ss->cache->view_normal, vd.no, vd.fno, - smooth_mask ? 0 : *vd.mask); + smooth_mask ? 0 : (vd.mask ? *vd.mask : 0.0f)); if (smooth_mask) { float val = neighbor_average_mask(ss, vd.vert_indices[vd.i]) - *vd.mask; val *= fade * bstrength; @@ -1524,7 +1524,7 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) /* offset vertex */ float fade = tex_strength(ss, brush, vd.co, test.dist, ss->cache->sculpt_normal_symm, vd.no, - vd.fno, *vd.mask); + vd.fno, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], offset, fade); @@ -1580,7 +1580,7 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod /* offset vertex */ const float fade = tex_strength(ss, brush, vd.co, test.dist, ss->cache->sculpt_normal_symm, - vd.no, vd.fno, *vd.mask); + vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); float val1[3]; float val2[3]; @@ -1623,7 +1623,7 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode if (sculpt_brush_test(&test, vd.co)) { float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist, ss->cache->view_normal, vd.no, - vd.fno, *vd.mask); + vd.fno, vd.mask ? *vd.mask : 0.0f); float val[3]; sub_v3_v3v3(val, test.location, vd.co); @@ -1677,7 +1677,8 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) { if (sculpt_brush_test(&test, origco[vd.i])) { const float fade = bstrength * tex_strength(ss, brush, origco[vd.i], test.dist, - ss->cache->sculpt_normal_symm, origno[vd.i], NULL, *vd.mask); + ss->cache->sculpt_normal_symm, origno[vd.i], + NULL, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], grab_delta, fade); @@ -1718,7 +1719,7 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode if (sculpt_brush_test(&test, vd.co)) { const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist, ss->cache->sculpt_normal_symm, - vd.no, vd.fno, *vd.mask); + vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], cono, fade); @@ -1767,7 +1768,7 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to if (sculpt_brush_test(&test, vd.co)) { const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist, ss->cache->sculpt_normal_symm, - vd.no, vd.fno, *vd.mask); + vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], grab_delta, fade); @@ -1815,7 +1816,7 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode if (sculpt_brush_test(&test, origco[vd.i])) { const float fade = bstrength * tex_strength(ss, brush, origco[vd.i], test.dist, ss->cache->sculpt_normal_symm, - origno[vd.i], NULL, *vd.mask); + origno[vd.i], NULL, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], cono, fade); @@ -1868,7 +1869,7 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod if (sculpt_brush_test(&test, origco[vd.i])) { const float fade = bstrength * tex_strength(ss, brush, origco[vd.i], test.dist, ss->cache->sculpt_normal_symm, - origno[vd.i], NULL, *vd.mask); + origno[vd.i], NULL, vd.mask ? *vd.mask : 0.0f); mul_v3_m4v3(proxy[vd.i], m, origco[vd.i]); sub_v3_v3(proxy[vd.i], origco[vd.i]); @@ -1921,7 +1922,7 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode if (sculpt_brush_test(&test, origco[vd.i])) { const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist, ss->cache->sculpt_normal_symm, - vd.no, vd.fno, *vd.mask); + vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); float *disp = &layer_disp[vd.i]; float val[3]; @@ -1974,7 +1975,8 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno { if (sculpt_brush_test(&test, vd.co)) { const float fade = bstrength * tex_strength(ss, brush, vd.co, test.dist, - ss->cache->view_normal, vd.no, vd.fno, *vd.mask); + ss->cache->view_normal, + vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); float val[3]; if (vd.fno) copy_v3_v3(val, vd.fno); @@ -2315,7 +2317,7 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno if (plane_trim(ss->cache, brush, val)) { const float fade = bstrength * tex_strength(ss, brush, vd.co, sqrt(test.dist), - an, vd.no, vd.fno, *vd.mask); + an, vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -2389,7 +2391,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) if (plane_trim(ss->cache, brush, val)) { const float fade = bstrength * tex_strength(ss, brush, vd.co, sqrt(test.dist), - an, vd.no, vd.fno, *vd.mask); + an, vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -2491,7 +2493,7 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t if (plane_trim(ss->cache, brush, val)) { const float fade = bstrength * tex_strength(ss, brush, vd.co, ss->cache->radius * test.dist, - an, vd.no, vd.fno, *vd.mask); + an, vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -2555,7 +2557,7 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) if (plane_trim(ss->cache, brush, val)) { const float fade = bstrength * tex_strength(ss, brush, vd.co, sqrt(test.dist), - an, vd.no, vd.fno, *vd.mask); + an, vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -2619,7 +2621,7 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod if (plane_trim(ss->cache, brush, val)) { const float fade = bstrength * tex_strength(ss, brush, vd.co, sqrt(test.dist), - an, vd.no, vd.fno, *vd.mask); + an, vd.no, vd.fno, vd.mask ? *vd.mask : 0.0f); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -2649,7 +2651,7 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]) } if (is_basis) { - ofs = key_to_vertcos(ob, kb); + ofs = BKE_key_convert_to_vertcos(ob, kb); /* calculate key coord offsets (from previous location) */ for (a = 0; a < me->totvert; a++) { @@ -2662,7 +2664,7 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]) int apply_offset = ((currkey != kb) && (ob->shapenr - 1 == currkey->relative)); if (apply_offset) - offset_to_key(ob, currkey, ofs); + BKE_key_convert_from_offset(ob, currkey, ofs); currkey = currkey->next; } @@ -2683,7 +2685,7 @@ void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]) } /* apply new coords on active key block */ - vertcos_to_key(ob, kb, vertCos); + BKE_key_convert_from_vertcos(ob, kb, vertCos); } static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush) @@ -3062,7 +3064,11 @@ static void sculpt_update_tex(const Scene *scene, Sculpt *sd, SculptSession *ss) } } -void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, int need_pmap) +/** + * \param need_mask So the DerivedMesh thats returned has mask data + */ +void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, + int need_pmap, int need_mask) { DerivedMesh *dm; SculptSession *ss = ob->sculpt; @@ -3070,11 +3076,33 @@ void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, int need_ MultiresModifierData *mmd = sculpt_multires_active(scene, ob); ss->modifiers_active = sculpt_modifiers_active(scene, sd, ob); + ss->show_diffuse_color = sd->flags & SCULPT_SHOW_DIFFUSE; + + if (need_mask) { + if (mmd == NULL) { + if (!CustomData_has_layer(&me->vdata, CD_PAINT_MASK)) { + ED_sculpt_mask_layers_ensure(ob, NULL); + } + } + else { + if (!CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK)) { +#if 1 + ED_sculpt_mask_layers_ensure(ob, mmd); +#else /* if we wanted to support adding mask data while multi-res painting, we would need to do this */ + if ((ED_sculpt_mask_layers_ensure(ob, mmd) & ED_SCULPT_MASK_LAYER_CALC_LOOP)) { + /* remake the derived mesh */ + ob->recalc |= OB_RECALC_DATA; + BKE_object_handle_update(scene, ob); + } +#endif + } + } + } /* BMESH ONLY --- at some point we should move sculpt code to use polygons only - but for now it needs tessfaces */ BKE_mesh_tessface_ensure(me); - if (!mmd) ss->kb = ob_get_keyblock(ob); + if (!mmd) ss->kb = BKE_keyblock_from_object(ob); else ss->kb = NULL; /* needs to be called after we ensure tessface */ @@ -3103,13 +3131,15 @@ void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, int need_ ss->pbvh = dm->getPBVH(ob, dm); ss->pmap = (need_pmap && dm->getPolyMap) ? dm->getPolyMap(ob, dm) : NULL; + pbvh_show_diffuse_color_set(ss->pbvh, ss->show_diffuse_color); + if (ss->modifiers_active) { if (!ss->orig_cos) { int a; free_sculptsession_deformMats(ss); - ss->orig_cos = (ss->kb) ? key_to_vertcos(ob, ss->kb) : mesh_getVertexCos(me, NULL); + ss->orig_cos = (ss->kb) ? BKE_key_convert_to_vertcos(ob, ss->kb) : mesh_getVertexCos(me, NULL); crazyspace_build_sculpt(scene, ob, &ss->deform_imats, &ss->deform_cos); BLI_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos); @@ -3123,7 +3153,7 @@ void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, int need_ /* if pbvh is deformed, key block is already applied to it */ if (ss->kb && !BLI_pbvh_isDeformed(ss->pbvh)) { - float (*vertCos)[3] = key_to_vertcos(ob, ss->kb); + float (*vertCos)[3] = BKE_key_convert_to_vertcos(ob, ss->kb); if (vertCos) { /* apply shape keys coordinates to PBVH */ @@ -3139,6 +3169,11 @@ int sculpt_mode_poll(bContext *C) return ob && ob->mode & OB_MODE_SCULPT; } +int sculpt_mode_poll_view3d(bContext *C) +{ + return (sculpt_mode_poll(C) && CTX_wm_region_view3d(C)); +} + int sculpt_poll(bContext *C) { return sculpt_mode_poll(C) && paint_poll(C); @@ -3481,7 +3516,7 @@ static void sculpt_update_brush_delta(Sculpt *sd, Object *ob, Brush *brush) if (tool == SCULPT_TOOL_GRAB) copy_v3_v3(sd->anchored_location, cache->true_location); else if (tool == SCULPT_TOOL_THUMB) - copy_v3_v3(sd->anchored_location, cache->orig_grab_location); + copy_v3_v3(sd->anchored_location, cache->orig_grab_location); if (ELEM(tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB)) { /* location stays the same for finding vertices in brush radius */ @@ -3504,8 +3539,6 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, StrokeCache *cache = ss->cache; Brush *brush = paint_brush(&sd->paint); - int dx, dy; - /* RNA_float_get_array(ptr, "location", cache->traced_location); */ if (cache->first_time || @@ -3574,8 +3607,8 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, if (brush->flag & BRUSH_ANCHORED) { int hit = 0; - dx = cache->mouse[0] - cache->initial_mouse[0]; - dy = cache->mouse[1] - cache->initial_mouse[1]; + const float dx = cache->mouse[0] - cache->initial_mouse[0]; + const float dy = cache->mouse[1] - cache->initial_mouse[1]; sd->anchored_size = cache->pixel_radius = sqrt(dx * dx + dy * dy); @@ -3585,8 +3618,8 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, float halfway[2]; float out[3]; - halfway[0] = (float)dx * 0.5f + cache->initial_mouse[0]; - halfway[1] = (float)dy * 0.5f + cache->initial_mouse[1]; + halfway[0] = dx * 0.5f + cache->initial_mouse[0]; + halfway[1] = dy * 0.5f + cache->initial_mouse[1]; if (sculpt_stroke_get_location(C, out, halfway)) { copy_v3_v3(sd->anchored_location, out); @@ -3633,8 +3666,8 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, sculpt_update_brush_delta(sd, ob, brush); if (brush->sculpt_tool == SCULPT_TOOL_ROTATE) { - dx = cache->mouse[0] - cache->initial_mouse[0]; - dy = cache->mouse[1] - cache->initial_mouse[1]; + const float dx = cache->mouse[0] - cache->initial_mouse[0]; + const float dy = cache->mouse[1] - cache->initial_mouse[1]; cache->vertex_rotation = -atan2f(dx, dy) * cache->bstrength; @@ -3671,7 +3704,7 @@ static void sculpt_stroke_modifiers_check(const bContext *C, Object *ob) Brush *brush = paint_brush(&sd->paint); sculpt_update_mesh_elements(CTX_data_scene(C), sd, ob, - sculpt_any_smooth_mode(brush, ss->cache, 0)); + sculpt_any_smooth_mode(brush, ss->cache, 0), FALSE); } } @@ -3706,7 +3739,7 @@ static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin) * (This allows us to ignore the GL depth buffer) * Returns 0 if the ray doesn't hit the mesh, non-zero otherwise */ -int sculpt_stroke_get_location(bContext *C, float out[3], float mouse[2]) +int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2]) { ViewContext vc; Object *ob; @@ -3777,12 +3810,17 @@ static int sculpt_brush_stroke_init(bContext *C, wmOperator *op) Brush *brush = paint_brush(&sd->paint); int mode = RNA_enum_get(op->ptr, "mode"); int is_smooth = 0; + int need_mask = FALSE; + + if (brush->sculpt_tool == SCULPT_TOOL_MASK) { + need_mask = TRUE; + } view3d_operator_needs_opengl(C); sculpt_brush_init_tex(scene, sd, ss); is_smooth = sculpt_any_smooth_mode(brush, NULL, mode); - sculpt_update_mesh_elements(scene, sd, ob, is_smooth); + sculpt_update_mesh_elements(scene, sd, ob, is_smooth, need_mask); return 1; } @@ -3961,6 +3999,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *even { struct PaintStroke *stroke; int ignore_background_click; + int retval; if (!sculpt_brush_stroke_init(C, op)) return OPERATOR_CANCELLED; @@ -3984,7 +4023,9 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *even /* add modal handler */ WM_event_add_modal_handler(C, op); - op->type->modal(C, op, event); + retval = op->type->modal(C, op, event); + OPERATOR_RETVAL_CHECK(retval); + BLI_assert(retval == OPERATOR_RUNNING_MODAL); return OPERATOR_RUNNING_MODAL; } @@ -4098,13 +4139,14 @@ static void sculpt_init_session(Scene *scene, Object *ob) { ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session"); - sculpt_update_mesh_elements(scene, scene->toolsettings->sculpt, ob, 0); + sculpt_update_mesh_elements(scene, scene->toolsettings->sculpt, ob, 0, FALSE); } -void ED_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd) +int ED_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd) { float *paint_mask; Mesh *me = ob->data; + int ret = 0; paint_mask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK); @@ -4112,7 +4154,7 @@ void ED_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd) * isn't one already */ if (mmd && !CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK)) { GridPaintMask *gmask; - int level = MAX2(1, mmd->sculptlvl); + int level = max_ii(1, mmd->sculptlvl); int gridsize = ccg_gridsize(level); int gridarea = gridsize * gridsize; int i, j; @@ -4157,13 +4199,18 @@ void ED_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd) } } } + + ret |= ED_SCULPT_MASK_LAYER_CALC_LOOP; } /* create vertex paint mask layer if there isn't one already */ if (!paint_mask) { CustomData_add_layer(&me->vdata, CD_PAINT_MASK, CD_CALLOC, NULL, me->totvert); + ret |= ED_SCULPT_MASK_LAYER_CALC_VERT; } + + return ret; } static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op)) @@ -4213,14 +4260,18 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op)) sculpt_init_session(scene, ob); /* Mask layer is required */ - ED_sculpt_mask_layers_ensure(ob, mmd); + if (mmd) { + /* XXX, we could attempt to support adding mask data mid-sculpt mode (with multi-res) + * but this ends up being quite tricky (and slow) */ + ED_sculpt_mask_layers_ensure(ob, mmd); + } BKE_paint_init(&ts->sculpt->paint, PAINT_CURSOR_SCULPT); paint_cursor_start(C, sculpt_poll); } - WM_event_add_notifier(C, NC_SCENE | ND_MODE, CTX_data_scene(C)); + WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index f4467dc22fc..acb906e4a91 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -56,14 +56,16 @@ struct MultiresModifierData *sculpt_multires_active(struct Scene *scene, struct 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); -void sculpt_update_mesh_elements(struct Scene *scene, struct Sculpt *sd, struct Object *ob, int need_pmap); +void sculpt_update_mesh_elements(struct Scene *scene, struct Sculpt *sd, struct Object *ob, + int need_pmap, int need_mask); /* Deformed mesh sculpt */ void free_sculptsession_deformMats(struct SculptSession *ss); /* Stroke */ -int sculpt_stroke_get_location(bContext *C, float out[3], float mouse[2]); +int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2]); /* Undo */ diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index c62dc687c73..1b3fd24ae22 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -99,7 +99,7 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; MVert *mvert; - int *index, i, j; + int *index, i, j; if (unode->maxvert) { /* regular mesh restore */ @@ -107,13 +107,13 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo if (ss->kb && strcmp(ss->kb->name, unode->shapeName)) { /* shape key has been changed before calling undo operator */ - Key *key = ob_get_key(ob); - KeyBlock *kb = key_get_named_keyblock(key, unode->shapeName); + Key *key = BKE_key_from_object(ob); + KeyBlock *kb = key ? BKE_keyblock_find_name(key, unode->shapeName) : NULL; if (kb) { ob->shapenr = BLI_findindex(&key->block, kb) + 1; - sculpt_update_mesh_elements(scene, sd, ob, 0); + sculpt_update_mesh_elements(scene, sd, ob, 0, FALSE); WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob); } else { @@ -127,7 +127,7 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo if (ss->kb) { float (*vertCos)[3]; - vertCos = key_to_vertcos(ob, ss->kb); + vertCos = BKE_key_convert_to_vertcos(ob, ss->kb); for (i = 0; i < unode->totvert; i++) { if (ss->modifiers_active) sculpt_undo_restore_deformed(ss, unode, i, index[i], vertCos[index[i]]); @@ -224,7 +224,7 @@ static int sculpt_undo_restore_mask(bContext *C, DerivedMesh *dm, SculptUndoNode SculptSession *ss = ob->sculpt; MVert *mvert; float *vmask; - int *index, i, j; + int *index, i, j; if (unode->maxvert) { /* regular mesh restore */ @@ -266,13 +266,28 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb) Scene *scene = CTX_data_scene(C); Sculpt *sd = CTX_data_tool_settings(C)->sculpt; Object *ob = CTX_data_active_object(C); - DerivedMesh *dm = mesh_get_derived_final(scene, ob, 0); + DerivedMesh *dm; SculptSession *ss = ob->sculpt; SculptUndoNode *unode; MultiresModifierData *mmd; int update = FALSE, rebuild = FALSE; + int need_mask = FALSE; - sculpt_update_mesh_elements(scene, sd, ob, 0); + for (unode = lb->first; unode; unode = unode->next) { + if (strcmp(unode->idname, ob->id.name) == 0) { + if (unode->type == SCULPT_UNDO_MASK) { + /* is possible that we can't do the mask undo (below) + * because of the vertex count */ + need_mask = TRUE; + break; + } + } + } + + sculpt_update_mesh_elements(scene, sd, ob, 0, need_mask); + + /* call _after_ sculpt_update_mesh_elements() which may update 'ob->derivedFinal' */ + dm = mesh_get_derived_final(scene, ob, 0); for (unode = lb->first; unode; unode = unode->next) { if (!(strcmp(unode->idname, ob->id.name) == 0)) diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index 878fd20b27e..9bd7d2a44ca 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -89,7 +89,7 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar) * start of list offset, and the second is as a correction for the scrollers. */ height = ((items * ACHANNEL_STEP) + (ACHANNEL_HEIGHT * 2)); - if (height > BLI_RCT_SIZE_Y(&v2d->mask)) { + if (height > BLI_rcti_size_y(&v2d->mask)) { /* don't use totrect set, as the width stays the same * (NOTE: this is ok here, the configuration is pretty straightforward) */ @@ -98,7 +98,7 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar) /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */ UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY); - /* loop through channels, and set up drawing depending on their type */ + /* loop through channels, and set up drawing depending on their type */ { /* first pass: just the standard GL-drawing for backdrop + text */ y = (float)ACHANNEL_FIRST; @@ -189,7 +189,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) /* if in NLA there's a strip active, map the view */ if (ac->datatype == ANIMCONT_ACTION) { - /* adt= ANIM_nla_mapping_get(ac, NULL); */ /* UNUSED */ + /* adt = ANIM_nla_mapping_get(ac, NULL); */ /* UNUSED */ /* start and end of action itself */ calc_action_range(ac->data, &act_start, &act_end, 0); @@ -307,7 +307,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) /* Increment the step */ y -= ACHANNEL_STEP; - } + } glDisable(GL_BLEND); /* Draw keyframes diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index c95f1dba31d..ae78b71f2ad 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -132,7 +132,7 @@ void ACTION_OT_new(wmOperatorType *ot) /* api callbacks */ ot->exec = act_new_exec; - // NOTE: this is used in the NLA too... + /* NOTE: this is used in the NLA too... */ //ot->poll = ED_operator_action_active; /* flags */ @@ -234,8 +234,8 @@ static void get_keyframe_extents(bAnimContext *ac, float *min, float *max, const int filter; /* get data to filter, from Action or Dopesheet */ - // XXX: what is sel doing here?! - // Commented it, was breaking things (eg. the "auto preview range" tool). + /* XXX: what is sel doing here?! + * Commented it, was breaking things (eg. the "auto preview range" tool). */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_SEL *//*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); @@ -254,8 +254,9 @@ static void get_keyframe_extents(bAnimContext *ac, float *min, float *max, const /* find gp-frame which is less than or equal to cframe */ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - *min = MIN2(*min, gpf->framenum); - *max = MAX2(*max, gpf->framenum); + const float framenum = (float)gpf->framenum; + *min = min_ff(*min, framenum); + *max = max_ff(*max, framenum); } } else if (ale->datatype == ALE_MASKLAY) { @@ -267,8 +268,9 @@ static void get_keyframe_extents(bAnimContext *ac, float *min, float *max, const masklay_shape; masklay_shape = masklay_shape->next) { - *min = MIN2(*min, masklay_shape->frame); - *max = MAX2(*max, masklay_shape->frame); + const float framenum = (float)masklay_shape->frame; + *min = min_ff(*min, framenum); + *max = max_ff(*max, framenum); } } else { @@ -284,8 +286,8 @@ static void get_keyframe_extents(bAnimContext *ac, float *min, float *max, const } /* try to set cur using these values, if they're more extreme than previously set values */ - *min = MIN2(*min, tmin); - *max = MAX2(*max, tmax); + *min = min_ff(*min, tmin); + *max = max_ff(*max, tmax); } } @@ -365,13 +367,13 @@ static int actkeys_viewall(bContext *C, const short onlySel) /* set the horizontal range, with an extra offset so that the extreme keys will be in view */ get_keyframe_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax, onlySel); - extra = 0.1f * BLI_RCT_SIZE_X(&v2d->cur); + extra = 0.1f * BLI_rctf_size_x(&v2d->cur); v2d->cur.xmin -= extra; v2d->cur.xmax += extra; /* set vertical range */ v2d->cur.ymax = 0.0f; - v2d->cur.ymin = (float)-BLI_RCT_SIZE_Y(&v2d->mask); + v2d->cur.ymin = (float)-BLI_rcti_size_y(&v2d->mask); /* do View2D syncing */ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); @@ -493,7 +495,7 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op) /* copy keyframes */ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) { /* FIXME... */ - BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for Grease Pencil mode"); + BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for grease pencil mode"); return OPERATOR_CANCELLED; } else if (ac.datatype == ANIMCONT_MASK) { @@ -502,7 +504,7 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } else { - if (copy_action_keys(&ac)) { + if (copy_action_keys(&ac)) { BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer"); return OPERATOR_CANCELLED; } @@ -542,8 +544,8 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op) /* paste keyframes */ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) { - // FIXME... - BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for Grease Pencil or Mask mode"); + /* FIXME... */ + BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for grease pencil or mask mode"); return OPERATOR_CANCELLED; } else { @@ -588,7 +590,7 @@ void ACTION_OT_paste(wmOperatorType *ot) static EnumPropertyItem prop_actkeys_insertkey_types[] = { {1, "ALL", 0, "All Channels", ""}, {2, "SEL", 0, "Only Selected Channels", ""}, - {3, "GROUP", 0, "In Active Group", ""}, // xxx not in all cases + {3, "GROUP", 0, "In Active Group", ""}, /* XXX not in all cases */ {0, NULL, 0, NULL, NULL} }; @@ -976,8 +978,8 @@ void ACTION_OT_sample(wmOperatorType *ot) /* defines for set extrapolation-type for selected keyframes tool */ static EnumPropertyItem prop_actkeys_expo_types[] = { - {FCURVE_EXTRAPOLATE_CONSTANT, "CONSTANT", 0, "Constant Extrapolation", ""}, - {FCURVE_EXTRAPOLATE_LINEAR, "LINEAR", 0, "Linear Extrapolation", ""}, + {FCURVE_EXTRAPOLATE_CONSTANT, "CONSTANT", 0, "Constant Extrapolation", "Values on endpoint keyframes are held"}, + {FCURVE_EXTRAPOLATE_LINEAR, "LINEAR", 0, "Linear Extrapolation", "Straight-line slope of end segments are extended past the endpoint keyframes"}, {MAKE_CYCLIC_EXPO, "MAKE_CYCLIC", 0, "Make Cyclic (F-Modifier)", "Add Cycles F-Modifier if one doesn't exist already"}, {CLEAR_CYCLIC_EXPO, "CLEAR_CYCLIC", 0, "Clear Cyclic (F-Modifier)", "Remove Cycles F-Modifier if not needed anymore"}, @@ -1010,7 +1012,7 @@ static void setexpo_action_keys(bAnimContext *ac, short mode) if (mode == MAKE_CYCLIC_EXPO) { /* only add if one doesn't exist */ if (list_has_suitable_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, -1) == 0) { - // TODO: add some more preset versions which set different extrapolation options? + /* TODO: add some more preset versions which set different extrapolation options? */ add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES); } } @@ -1319,7 +1321,7 @@ static int actkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op)) if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; - /* init edit data */ + /* init edit data */ /* loop over action data, averaging values */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); @@ -1353,9 +1355,9 @@ static int actkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op)) void ACTION_OT_frame_jump(wmOperatorType *ot) { /* identifiers */ - ot->name = "Jump to Frame"; + ot->name = "Jump to Keyframes"; ot->idname = "ACTION_OT_frame_jump"; - ot->description = "Set the current frame to the average frame of the selected keyframes"; + ot->description = "Set the current frame to the average frame value of selected keyframes"; /* api callbacks */ ot->exec = actkeys_framejump_exec; @@ -1369,10 +1371,14 @@ void ACTION_OT_frame_jump(wmOperatorType *ot) /* defines for snap keyframes tool */ static EnumPropertyItem prop_actkeys_snap_types[] = { - {ACTKEYS_SNAP_CFRA, "CFRA", 0, "Current frame", ""}, - {ACTKEYS_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame", ""}, // XXX as single entry? - {ACTKEYS_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Nearest Second", ""}, // XXX as single entry? - {ACTKEYS_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker", ""}, + {ACTKEYS_SNAP_CFRA, "CFRA", 0, "Current frame", + "Snap selected keyframes to the current frame"}, + {ACTKEYS_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame", + "Snap selected keyframes to the nearest (whole) frame (use to fix accidental sub-frame offsets)"}, + {ACTKEYS_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Nearest Second", + "Snap selected keyframes to the nearest second"}, + {ACTKEYS_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker", + "Snap selected keyframes to the nearest marker"}, {0, NULL, 0, NULL, NULL} }; @@ -1431,7 +1437,7 @@ static int actkeys_snap_exec(bContext *C, wmOperator *op) if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; - // XXX... + /* XXX... */ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) return OPERATOR_PASS_THROUGH; @@ -1473,9 +1479,12 @@ void ACTION_OT_snap(wmOperatorType *ot) /* defines for mirror keyframes tool */ static EnumPropertyItem prop_actkeys_mirror_types[] = { - {ACTKEYS_MIRROR_CFRA, "CFRA", 0, "By Times over Current frame", ""}, - {ACTKEYS_MIRROR_XAXIS, "XAXIS", 0, "By Values over Value=0", ""}, - {ACTKEYS_MIRROR_MARKER, "MARKER", 0, "By Times over First Selected Marker", ""}, + {ACTKEYS_MIRROR_CFRA, "CFRA", 0, "By Times over Current frame", + "Flip times of selected keyframes using the current frame as the mirror line"}, + {ACTKEYS_MIRROR_XAXIS, "XAXIS", 0, "By Values over Value=0", + "Flip values of selected keyframes (i.e. negative values become positive, and vice versa)"}, + {ACTKEYS_MIRROR_MARKER, "MARKER", 0, "By Times over First Selected Marker", + "Flip times of selected keyframes using the first selected marker as the reference point"}, {0, NULL, 0, NULL, NULL} }; @@ -1495,14 +1504,10 @@ static void mirror_action_keys(bAnimContext *ac, short mode) ked.scene = ac->scene; /* for 'first selected marker' mode, need to find first selected marker first! */ - // XXX should this be made into a helper func in the API? + /* XXX should this be made into a helper func in the API? */ if (mode == ACTKEYS_MIRROR_MARKER) { - TimeMarker *marker = NULL; + TimeMarker *marker = ED_markers_get_first_selected(ac->markers); - /* find first selected marker */ - marker = ED_markers_get_first_selected(ac->markers); - - /* store marker's time (if available) */ if (marker) ked.f1 = (float)marker->frame; else @@ -1545,7 +1550,7 @@ static int actkeys_mirror_exec(bContext *C, wmOperator *op) if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; - // XXX... + /* XXX... */ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) return OPERATOR_PASS_THROUGH; diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h index c684ae1de51..10085d8a149 100644 --- a/source/blender/editors/space_action/action_intern.h +++ b/source/blender/editors/space_action/action_intern.h @@ -111,7 +111,7 @@ enum { ACTKEYS_SNAP_CFRA = 1, ACTKEYS_SNAP_NEAREST_FRAME, ACTKEYS_SNAP_NEAREST_SECOND, - ACTKEYS_SNAP_NEAREST_MARKER, + ACTKEYS_SNAP_NEAREST_MARKER, } eActKeys_Snap_Mode; /* defines for mirror keyframes @@ -121,7 +121,7 @@ enum { ACTKEYS_MIRROR_CFRA = 1, ACTKEYS_MIRROR_YAXIS, ACTKEYS_MIRROR_XAXIS, - ACTKEYS_MIRROR_MARKER, + ACTKEYS_MIRROR_MARKER, } eActKeys_Mirror_Mode; /* ***************************************** */ diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index e4a161e3e22..cca71bb1331 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -168,9 +168,8 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) /* action_edit.c */ - /* snap - current frame to selected keys */ - // TODO: maybe since this is called jump, we're better to have it on -J? - WM_keymap_add_item(keymap, "ACTION_OT_frame_jump", SKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); + /* jump to selected keyframes */ + WM_keymap_add_item(keymap, "ACTION_OT_frame_jump", GKEY, KM_PRESS, KM_CTRL, 0); /* menu + single-step transform */ WM_keymap_add_item(keymap, "ACTION_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0); diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 9ab79d73e76..d0f76c21019 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -309,7 +309,7 @@ static int actkeys_borderselect_exec(bContext *C, wmOperator *op) * - the frame-range select option is favored over the channel one (x over y), as frame-range one is often * used for tweaking timing when "blocking", while channels is not that useful... */ - if (BLI_RCT_SIZE_X(&rect) >= BLI_RCT_SIZE_Y(&rect)) + if (BLI_rcti_size_x(&rect) >= BLI_rcti_size_y(&rect)) mode = ACTKEYS_BORDERSEL_FRAMERANGE; else mode = ACTKEYS_BORDERSEL_CHANNELS; @@ -763,7 +763,7 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se if (leftright == ACTKEYS_LRSEL_LEFT) { ked.f1 = MINAFRAMEF; ked.f2 = (float)(CFRA + 0.1f); - } + } else { ked.f1 = (float)(CFRA - 0.1f); ked.f2 = MAXFRAMEF; @@ -785,7 +785,7 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } - else if (ale->type == ANIMTYPE_GPLAYER) + else if (ale->type == ANIMTYPE_GPLAYER) ED_gplayer_frames_select_border(ale->data, ked.f1, ked.f2, select_mode); else if (ale->type == ANIMTYPE_MASKLAYER) ED_masklayer_frames_select_border(ale->data, ked.f1, ked.f2, select_mode); @@ -869,7 +869,7 @@ static int actkeys_select_leftright_invoke(bContext *C, wmOperator *op, wmEvent UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, NULL); if (x < CFRA) RNA_enum_set(op->ptr, "mode", ACTKEYS_LRSEL_LEFT); - else + else RNA_enum_set(op->ptr, "mode", ACTKEYS_LRSEL_RIGHT); } @@ -912,9 +912,6 @@ void ACTION_OT_select_leftright(wmOperatorType *ot) * selection mode between replacing the selection (without) and inverting the selection (with). */ -/* sensitivity factor for frame-selections */ -#define FRAME_CLICK_THRESH 0.1f - /* ------------------- */ /* option 1) select keyframe directly under mouse */ @@ -1084,7 +1081,7 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_ /* dopesheet summary covers everything */ summary_to_keylist(ac, &anim_keys, NULL); } - else if (ale->type == ANIMTYPE_GROUP) { + else if (ale->type == ANIMTYPE_GROUP) { // TODO: why don't we just give groups key_data too? bActionGroup *agrp = (bActionGroup *)ale->data; agroup_to_keylist(adt, agrp, &anim_keys, NULL); @@ -1147,7 +1144,7 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_ agrp->flag |= AGRP_SELECTED; ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP); - } + } else if (ale->type == ANIMTYPE_FCURVE) { FCurve *fcu = ale->data; @@ -1213,7 +1210,7 @@ static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *even return OPERATOR_CANCELLED; /* get useful pointers from animation context data */ - /* ar= ac.ar; */ /* UNUSED */ + /* ar = ac.ar; */ /* UNUSED */ /* select mode is either replace (deselect all, then add) or add/extend */ if (RNA_boolean_get(op->ptr, "extend")) diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 1f641829e7e..c5f3ccee101 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -129,7 +129,7 @@ static SpaceLink *action_new(const bContext *C) /* not spacelink itself */ static void action_free(SpaceLink *UNUSED(sl)) { -// SpaceAction *saction= (SpaceAction *) sl; +// SpaceAction *saction = (SpaceAction *) sl; } @@ -357,8 +357,8 @@ static void action_listener(ScrArea *sa, wmNotifier *wmn) /* context changes */ switch (wmn->category) { - case NC_SCREEN: - if (wmn->data == ND_GPENCIL) { + case NC_GPENCIL: + if (wmn->action == NA_EDITED) { /* only handle this event in GPencil mode for performance considerations */ if (saction->mode == SACTCONT_GPENCIL) ED_area_tag_redraw(sa); @@ -377,7 +377,7 @@ static void action_listener(ScrArea *sa, wmNotifier *wmn) ED_area_tag_refresh(sa); break; case NC_SCENE: - switch (wmn->data) { + switch (wmn->data) { case ND_OB_ACTIVE: /* selection changed, so force refresh to flush (needs flag set to do syncing) */ case ND_OB_SELECT: saction->flag |= SACTION_TEMP_NEEDCHANSYNC; @@ -409,6 +409,7 @@ static void action_listener(ScrArea *sa, wmNotifier *wmn) switch (wmn->data) { case ND_DATA: ED_area_tag_refresh(sa); + ED_area_tag_redraw(sa); break; default: /* just redrawing the view will do */ ED_area_tag_redraw(sa); @@ -432,7 +433,7 @@ static void action_listener(ScrArea *sa, wmNotifier *wmn) saction->flag |= SACTION_TEMP_NEEDCHANSYNC; ED_area_tag_refresh(sa); break; - } + } break; case NC_WINDOW: if (saction->flag & SACTION_TEMP_NEEDCHANSYNC) { diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 2cbcbcdbc9a..35344f2c5a4 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -193,7 +193,7 @@ void ED_spacetypes_keymap(wmKeyConfig *keyconf) typedef struct RegionDrawCB { struct RegionDrawCB *next, *prev; - void (*draw)(const struct bContext *, struct ARegion *, void *); + void (*draw)(const struct bContext *, struct ARegion *, void *); void *customdata; int type; @@ -239,7 +239,7 @@ void ED_region_draw_cb_draw(const bContext *C, ARegion *ar, int type) for (rdc = ar->type->drawcalls.first; rdc; rdc = rdc->next) { if (rdc->type == type) rdc->draw(C, ar, rdc->customdata); - } + } } diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index c41d2521ee8..9c47c407bd9 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -236,7 +236,7 @@ static int buttons_context_path_material(ButsContextPath *path, int for_texture) if (ma) { RNA_id_pointer_create(&ma->id, &path->ptr[path->len]); path->len++; - } + } return 1; } } @@ -889,7 +889,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r else CTX_data_pointer_set(result, NULL, &RNA_ParticleSystem, NULL); return 1; - } + } else if (CTX_data_equals(member, "particle_settings")) { /* only available when pinned */ PointerRNA *ptr = get_pointer_type(path, &RNA_ParticleSettings); @@ -900,7 +900,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r } else { /* get settings from active particle system instead */ - PointerRNA *ptr = get_pointer_type(path, &RNA_ParticleSystem); + ptr = get_pointer_type(path, &RNA_ParticleSystem); if (ptr && ptr->data) { ParticleSettings *part = ((ParticleSystem *)ptr->data)->part; diff --git a/source/blender/editors/space_buttons/buttons_header.c b/source/blender/editors/space_buttons/buttons_header.c index 4bcd4a933ed..ebba7d92819 100644 --- a/source/blender/editors/space_buttons/buttons_header.c +++ b/source/blender/editors/space_buttons/buttons_header.c @@ -148,7 +148,7 @@ void buttons_header_buttons(const bContext *C, ARegion *ar) uiBlockEndAlign(block); /* always as last */ - UI_view2d_totRect_set(&ar->v2d, xco + (UI_UNIT_X / 2), BLI_RCT_SIZE_Y(&ar->v2d.tot)); + UI_view2d_totRect_set(&ar->v2d, xco + (UI_UNIT_X / 2), BLI_rctf_size_y(&ar->v2d.tot)); uiEndBlock(C, block); uiDrawBlock(C, block); diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index c8cf69e3e17..d40426a5bc9 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -162,7 +162,7 @@ static int file_browse_invoke(bContext *C, wmOperator *op, wmEvent *event) char *str; if (CTX_wm_space_file(C)) { - BKE_report(op->reports, RPT_ERROR, "Can't activate a file selector, one already open"); + BKE_report(op->reports, RPT_ERROR, "Cannot activate a file selector, one already open"); return OPERATOR_CANCELLED; } @@ -207,7 +207,7 @@ static int file_browse_invoke(bContext *C, wmOperator *op, wmEvent *event) * user-prefs exception - campbell */ if (RNA_struct_find_property(op->ptr, "relative_path")) { if (!RNA_struct_property_is_set(op->ptr, "relative_path")) { - /* annoying exception!, if were dealign with the user prefs, default relative to be off */ + /* annoying exception!, if were dealing with the user prefs, default relative to be off */ RNA_boolean_set(op->ptr, "relative_path", U.flag & USER_RELPATHS && (ptr.data != &U)); } } diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 33229496d0b..09ad7312123 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -323,7 +323,7 @@ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn) /* currently works by redraws... if preview is set, it (re)starts job */ sbuts->preview = 1; break; - } + } break; case NC_WORLD: buttons_area_redraw(sa, BCONTEXT_WORLD); diff --git a/source/blender/editors/space_clip/CMakeLists.txt b/source/blender/editors/space_clip/CMakeLists.txt index ecc4dea8b05..75e3d8d5685 100644 --- a/source/blender/editors/space_clip/CMakeLists.txt +++ b/source/blender/editors/space_clip/CMakeLists.txt @@ -33,10 +33,10 @@ set(INC ../../windowmanager ../../gpu ../../../../intern/guardedalloc - ${GLEW_INCLUDE_PATH} ) set(INC_SYS + ${GLEW_INCLUDE_PATH} ) set(SRC diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index 0a1e1d75098..969b0e25928 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -174,7 +174,7 @@ void uiTemplateTrack(uiLayout *layout, PointerRNA *ptr, const char *propname) scopes->track_preview_height = (scopes->track_preview_height <= UI_UNIT_Y) ? UI_UNIT_Y : scopes->track_preview_height; - uiDefBut(block, TRACKPREVIEW, 0, "", rect.xmin, rect.ymin, BLI_RCT_SIZE_X(&rect), + uiDefBut(block, TRACKPREVIEW, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), scopes->track_preview_height, scopes, 0, 0, 0, 0, ""); } diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c index 5d890155e25..cc1b8d444bc 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_draw.c +++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c @@ -274,7 +274,7 @@ void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar) dopesheet = &tracking->dopesheet; height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT * 2); - if (height > BLI_RCT_SIZE_Y(&v2d->mask)) { + if (height > BLI_rcti_size_y(&v2d->mask)) { /* don't use totrect set, as the width stays the same * (NOTE: this is ok here, the configuration is pretty straightforward) */ diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index d486caeacc2..a2e4da719e9 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -117,6 +117,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc int *points, totseg, i, a; float sfra = SFRA, efra = EFRA, framelen = ar->winx / (efra - sfra + 1); MovieTracking *tracking = &clip->tracking; + MovieTrackingObject *act_object = BKE_tracking_object_get_active(tracking); MovieTrackingTrack *act_track = BKE_tracking_track_get_active(&clip->tracking); MovieTrackingReconstruction *reconstruction = BKE_tracking_get_active_reconstruction(tracking); @@ -212,14 +213,14 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc x = (sc->user.framenr - sfra) / (efra - sfra + 1) * ar->winx; UI_ThemeColor(TH_CFRAME); - glRecti(x, 0, x + framelen, 8); + glRecti(x, 0, x + ceilf(framelen), 8); clip_draw_curfra_label(sc->user.framenr, x, 8.0f); /* solver keyframes */ glColor4ub(175, 255, 0, 255); - draw_keyframe(tracking->settings.keyframe1 + clip->start_frame - 1, CFRA, sfra, framelen, 2); - draw_keyframe(tracking->settings.keyframe2 + clip->start_frame - 1, CFRA, sfra, framelen, 2); + draw_keyframe(act_object->keyframe1 + clip->start_frame - 1, CFRA, sfra, framelen, 2); + draw_keyframe(act_object->keyframe2 + clip->start_frame - 1, CFRA, sfra, framelen, 2); /* movie clip animation */ if ((sc->mode == SC_MODE_MASKEDIT) && sc->mask_info.mask) { @@ -715,7 +716,7 @@ static float get_shortest_pattern_side(MovieTrackingMarker *marker) cur_len = len_v2v2(marker->pattern_corners[i], marker->pattern_corners[next]); - len = minf(cur_len, len); + len = min_ff(cur_len, len); } return len; @@ -787,11 +788,11 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo dy = 6.0f / height / sc->zoom; side = get_shortest_pattern_side(marker); - patdx = minf(dx * 2.0f / 3.0f, side / 6.0f); - patdy = minf(dy * 2.0f / 3.0f, side * width / height / 6.0f); + patdx = min_ff(dx * 2.0f / 3.0f, side / 6.0f); + patdy = min_ff(dy * 2.0f / 3.0f, side * width / height / 6.0f); - searchdx = minf(dx, (marker->search_max[0] - marker->search_min[0]) / 6.0f); - searchdy = minf(dy, (marker->search_max[1] - marker->search_min[1]) / 6.0f); + searchdx = min_ff(dx, (marker->search_max[0] - marker->search_min[0]) / 6.0f); + searchdy = min_ff(dy, (marker->search_max[1] - marker->search_min[1]) / 6.0f); px[0] = 1.0f / sc->zoom / width / sc->scale; px[1] = 1.0f / sc->zoom / height / sc->scale; @@ -957,12 +958,12 @@ static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTra static void view2d_to_region_float(View2D *v2d, float x, float y, float *regionx, float *regiony) { /* express given coordinates as proportional values */ - x = -v2d->cur.xmin / BLI_RCT_SIZE_X(&v2d->cur); - y = -v2d->cur.ymin / BLI_RCT_SIZE_Y(&v2d->cur); + x = -v2d->cur.xmin / BLI_rctf_size_x(&v2d->cur); + y = -v2d->cur.ymin / BLI_rctf_size_y(&v2d->cur); /* convert proportional distances to screen coordinates */ - *regionx = v2d->mask.xmin + x * BLI_RCT_SIZE_X(&v2d->mask); - *regiony = v2d->mask.ymin + y * BLI_RCT_SIZE_Y(&v2d->mask); + *regionx = v2d->mask.xmin + x * BLI_rcti_size_x(&v2d->mask); + *regiony = v2d->mask.ymin + y * BLI_rcti_size_y(&v2d->mask); } static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, @@ -1126,7 +1127,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, if (MARKER_VISIBLE(sc, track, marker)) { float npos[2]; - copy_v4_v4(vec, track->bundle_pos); + copy_v3_v3(vec, track->bundle_pos); vec[3] = 1; mul_v4_m4v4(pos, mat, vec); diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index f2a48f299cf..71589517c83 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -44,6 +44,7 @@ #include "BLI_utildefines.h" #include "BLI_math.h" +#include "BLI_string.h" #include "BLI_rect.h" #include "GPU_extensions.h" @@ -149,8 +150,8 @@ void ED_space_clip_get_zoom(SpaceClip *sc, ARegion *ar, float *zoomx, float *zoo ED_space_clip_get_size(sc, &width, &height); - *zoomx = (float)(BLI_RCT_SIZE_X(&ar->winrct) + 1) / (float)(BLI_RCT_SIZE_X(&ar->v2d.cur) * width); - *zoomy = (float)(BLI_RCT_SIZE_Y(&ar->winrct) + 1) / (float)(BLI_RCT_SIZE_Y(&ar->v2d.cur) * height); + *zoomx = (float)(BLI_rcti_size_x(&ar->winrct) + 1) / (BLI_rctf_size_x(&ar->v2d.cur) * width); + *zoomy = (float)(BLI_rcti_size_y(&ar->winrct) + 1) / (BLI_rctf_size_y(&ar->v2d.cur) * height); } void ED_space_clip_get_aspect(SpaceClip *sc, float *aspx, float *aspy) @@ -368,7 +369,7 @@ int ED_clip_view_selection(const bContext *C, ARegion *ar, int fit) ED_space_clip_get_size(sc, &frame_width, &frame_height); - if (frame_width == 0 || frame_height == 0) + if ((frame_width == 0) || (frame_height == 0) || (sc->clip == NULL)) return FALSE; if (!selected_boundbox(sc, min, max)) @@ -388,13 +389,13 @@ int ED_clip_view_selection(const bContext *C, ARegion *ar, int fit) ED_space_clip_get_aspect(sc, &aspx, &aspy); - width = BLI_RCT_SIZE_X(&ar->winrct) + 1; - height = BLI_RCT_SIZE_Y(&ar->winrct) + 1; + width = BLI_rcti_size_x(&ar->winrct) + 1; + height = BLI_rcti_size_y(&ar->winrct) + 1; zoomx = (float)width / w / aspx; zoomy = (float)height / h / aspy; - newzoom = 1.0f / power_of_2(1.0f / minf(zoomx, zoomy)); + newzoom = 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)); if (fit || sc->zoom > newzoom) sc->zoom = newzoom; @@ -692,7 +693,7 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf, const unsign context->start_frame = clip->start_frame; context->frame_offset = clip->frame_offset; - strcpy(context->colorspace, clip->colorspace_settings.name); + BLI_strncpy(context->colorspace, clip->colorspace_settings.name, sizeof(context->colorspace)); } else { /* displaying exactly the same image which was loaded t oa texture, diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c index f48d4e8d946..fa235bd2997 100644 --- a/source/blender/editors/space_clip/clip_graph_ops.c +++ b/source/blender/editors/space_clip/clip_graph_ops.c @@ -580,11 +580,11 @@ static int view_all_exec(bContext *C, wmOperator *UNUSED(op)) } /* we need an extra "buffer" factor on either side so that the endpoints are visible */ - extra = 0.01f * BLI_RCT_SIZE_X(&v2d->cur); + extra = 0.01f * BLI_rctf_size_x(&v2d->cur); v2d->cur.xmin -= extra; v2d->cur.xmax += extra; - extra = 0.01f * BLI_RCT_SIZE_Y(&v2d->cur); + extra = 0.01f * BLI_rctf_size_y(&v2d->cur); v2d->cur.ymin -= extra; v2d->cur.ymax += extra; @@ -610,7 +610,7 @@ void CLIP_OT_graph_view_all(wmOperatorType *ot) void ED_clip_graph_center_current_frame(Scene *scene, ARegion *ar) { View2D *v2d = &ar->v2d; - float extra = BLI_RCT_SIZE_X(&v2d->cur) / 2.0f; + float extra = BLI_rctf_size_x(&v2d->cur) / 2.0f; /* set extents of view to start/end frames */ v2d->cur.xmin = (float)CFRA - extra; diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index aa2cadbd2d3..9ec2ad82bef 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -41,6 +41,8 @@ #include "BLI_math.h" #include "BLI_rect.h" +#include "BLF_translation.h" + #include "BKE_context.h" #include "BKE_global.h" #include "BKE_report.h" @@ -90,9 +92,9 @@ static void sclip_zoom_set(const bContext *C, float zoom, float location[2]) if ((width < 4) && (height < 4)) sc->zoom = oldzoom; - else if (BLI_RCT_SIZE_X(&ar->winrct) <= sc->zoom) + else if (BLI_rcti_size_x(&ar->winrct) <= sc->zoom) sc->zoom = oldzoom; - else if (BLI_RCT_SIZE_Y(&ar->winrct) <= sc->zoom) + else if (BLI_rcti_size_y(&ar->winrct) <= sc->zoom) sc->zoom = oldzoom; } @@ -180,7 +182,7 @@ static int open_exec(bContext *C, wmOperator *op) BLI_join_dirfile(str, sizeof(str), dir_only, file_only); } else { - BKE_reportf(op->reports, RPT_ERROR, "No files selected to be opened"); + BKE_report(op->reports, RPT_ERROR, "No files selected to be opened"); return OPERATOR_CANCELLED; } @@ -195,8 +197,8 @@ static int open_exec(bContext *C, wmOperator *op) if (op->customdata) MEM_freeN(op->customdata); - BKE_reportf(op->reports, RPT_ERROR, "Can't read: \"%s\", %s.", str, - errno ? strerror(errno) : "Unsupported movie clip format"); + BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s", str, + errno ? strerror(errno) : TIP_("unsupported movie clip format")); return OPERATOR_CANCELLED; } @@ -514,9 +516,14 @@ static int view_zoom_exec(bContext *C, wmOperator *op) static int view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event) { if (event->type == MOUSEZOOM) { - float factor; + float delta, factor; - factor = 1.0f + (event->x - event->prevx + event->y - event->prevy) / 300.0f; + delta = event->x - event->prevx + event->y - event->prevy; + + if (U.uiflag & USER_ZOOM_INVERT) + delta *= -1; + + factor = 1.0f + delta / 300.0f; RNA_float_set(op->ptr, "factor", factor); sclip_zoom_set_factor_exec(C, event, factor); @@ -533,11 +540,16 @@ static int view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event) static int view_zoom_modal(bContext *C, wmOperator *op, wmEvent *event) { ViewZoomData *vpd = op->customdata; - float factor; + float delta, factor; switch (event->type) { case MOUSEMOVE: - factor = 1.0f + (vpd->x - event->x + vpd->y - event->y) / 300.0f; + delta = event->x - vpd->x + event->y - vpd->y; + + if (U.uiflag & USER_ZOOM_INVERT) + delta *= -1; + + factor = 1.0f + delta / 300.0f; RNA_float_set(op->ptr, "factor", factor); sclip_zoom_set(C, vpd->zoom * factor, vpd->location); ED_region_tag_redraw(CTX_wm_region(C)); @@ -579,7 +591,7 @@ void CLIP_OT_view_zoom(wmOperatorType *ot) ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; /* properties */ - RNA_def_float(ot->srna, "factor", 0.0f, 0.0f, FLT_MAX, + RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Factor", "Zoom factor, values higher than 1.0 zoom in, lower values zoom out", -FLT_MAX, FLT_MAX); } @@ -700,7 +712,7 @@ void CLIP_OT_view_zoom_ratio(wmOperatorType *ot) ot->poll = ED_space_clip_view_clip_poll; /* properties */ - RNA_def_float(ot->srna, "ratio", 0.0f, 0.0f, FLT_MAX, + RNA_def_float(ot->srna, "ratio", 0.0f, -FLT_MAX, FLT_MAX, "Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out", -FLT_MAX, FLT_MAX); } @@ -726,8 +738,8 @@ static int view_all_exec(bContext *C, wmOperator *op) h = h * aspy; /* check if the image will fit in the image with zoom == 1 */ - width = BLI_RCT_SIZE_X(&ar->winrct) + 1; - height = BLI_RCT_SIZE_Y(&ar->winrct) + 1; + width = BLI_rcti_size_x(&ar->winrct) + 1; + height = BLI_rcti_size_y(&ar->winrct) + 1; if (fit_view) { const int margin = 5; /* margin from border */ @@ -735,7 +747,7 @@ static int view_all_exec(bContext *C, wmOperator *op) zoomx = (float) width / (w + 2 * margin); zoomy = (float) height / (h + 2 * margin); - sclip_zoom_set(C, minf(zoomx, zoomy), NULL); + sclip_zoom_set(C, min_ff(zoomx, zoomy), NULL); } else { if ((w >= width || h >= height) && (width > 0 && height > 0)) { @@ -743,7 +755,7 @@ static int view_all_exec(bContext *C, wmOperator *op) zoomy = (float) height / h; /* find the zoom value that will fit the image in the image space */ - sclip_zoom_set(C, 1.0f / power_of_2(1.0f / minf(zoomx, zoomy)), NULL); + sclip_zoom_set(C, 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)), NULL); } else sclip_zoom_set(C, 1.0f, NULL); diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 7f43c404095..ffe4762ad15 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -407,8 +407,6 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn) case NC_SCREEN: switch (wmn->data) { case ND_ANIMPLAY: - case ND_GPENCIL: - clip_scopes_check_gpencil_change(sa); ED_area_tag_redraw(sa); break; } @@ -420,6 +418,12 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn) ED_area_tag_redraw(sa); } break; + case NC_GPENCIL: + if (wmn->action == NA_EDITED) { + clip_scopes_check_gpencil_change(sa); + ED_area_tag_redraw(sa); + } + break; } } @@ -1036,8 +1040,8 @@ static void movieclip_main_area_set_view2d(const bContext *C, ARegion *ar) if (clip) h *= clip->aspy / clip->aspx / clip->tracking.camera.pixel_aspect; - winx = BLI_RCT_SIZE_X(&ar->winrct) + 1; - winy = BLI_RCT_SIZE_Y(&ar->winrct) + 1; + winx = BLI_rcti_size_x(&ar->winrct) + 1; + winy = BLI_rcti_size_y(&ar->winrct) + 1; ar->v2d.tot.xmin = 0; ar->v2d.tot.ymin = 0; @@ -1159,8 +1163,8 @@ static void clip_main_area_listener(ARegion *ar, wmNotifier *wmn) { /* context changes */ switch (wmn->category) { - case NC_SCREEN: - if (wmn->data == ND_GPENCIL) + case NC_GPENCIL: + if (wmn->action == NA_EDITED) ED_region_tag_redraw(ar); break; } @@ -1373,8 +1377,8 @@ static void clip_props_area_listener(ARegion *ar, wmNotifier *wmn) if (wmn->data == ND_SPACE_CLIP) ED_region_tag_redraw(ar); break; - case NC_SCREEN: - if (wmn->data == ND_GPENCIL) + case NC_GPENCIL: + if (wmn->action == NA_EDITED) ED_region_tag_redraw(ar); break; } @@ -1406,8 +1410,8 @@ static void clip_properties_area_listener(ARegion *ar, wmNotifier *wmn) { /* context changes */ switch (wmn->category) { - case NC_SCREEN: - if (wmn->data == ND_GPENCIL) + case NC_GPENCIL: + if (wmn->data == ND_DATA) ED_region_tag_redraw(ar); break; case NC_BRUSH: diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 97f7d7bf132..dd939d57cbe 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -154,7 +154,7 @@ void CLIP_OT_add_marker(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MIN, FLT_MAX, + RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location", "Location of marker on frame", -1.0f, 1.0f); } @@ -372,8 +372,8 @@ static int mouse_on_slide_zone(SpaceClip *sc, MovieTrackingMarker *marker, dx = size / width / sc->zoom; dy = size / height / sc->zoom; - dx = minf(dx, (max[0] - min[0]) / 6.0f); - dy = minf(dy, (max[1] - min[1]) / 6.0f); + dx = min_ff(dx, (max[0] - min[0]) / 6.0f); + dy = min_ff(dy, (max[1] - min[1]) / 6.0f); return IN_RANGE_INCL(co[0], slide_zone[0] - dx, slide_zone[0] + dx) && IN_RANGE_INCL(co[1], slide_zone[1] - dy, slide_zone[1] + dy); @@ -424,14 +424,14 @@ static int get_mouse_pattern_corner(SpaceClip *sc, MovieTrackingMarker *marker, cur_len = len_v2v2(marker->pattern_corners[i], marker->pattern_corners[next]); - len = minf(cur_len, len); + len = min_ff(cur_len, len); } dx = 12.0f / width / sc->zoom; dy = 12.0f / height / sc->zoom; - dx = minf(dx, len * 2.0f / 3.0f); - dy = minf(dy, len * width / height * 2.0f / 3.0f); + dx = min_ff(dx, len * 2.0f / 3.0f); + dy = min_ff(dy, len * width / height * 2.0f / 3.0f); for (i = 0; i < 4; i++) { float crn[2]; @@ -462,8 +462,8 @@ static int mouse_on_offset(SpaceClip *sc, MovieTrackingTrack *track, MovieTracki dx = 12.0f / width / sc->zoom; dy = 12.0f / height / sc->zoom; - dx = minf(dx, (pat_max[0] - pat_min[0]) / 2.0f); - dy = minf(dy, (pat_max[1] - pat_min[1]) / 2.0f); + dx = min_ff(dx, (pat_max[0] - pat_min[0]) / 2.0f); + dy = min_ff(dy, (pat_max[1] - pat_min[1]) / 2.0f); return co[0] >= pos[0] - dx && co[0] <= pos[0] + dx && co[1] >= pos[1] - dy && co[1] <= pos[1] + dy; } @@ -855,8 +855,8 @@ static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event) vec[0] *= data->width; vec[1] *= data->height; - data->corners[a][0] = (vec[0] * cos(angle) - vec[1] * sin(angle)) / data->width; - data->corners[a][1] = (vec[1] * cos(angle) + vec[0] * sin(angle)) / data->height; + data->corners[a][0] = (vec[0] * cosf(angle) - vec[1] * sinf(angle)) / data->width; + data->corners[a][1] = (vec[1] * cosf(angle) + vec[0] * sinf(angle)) / data->height; } BKE_tracking_marker_clamp(data->marker, CLAMP_PAT_DIM); @@ -1018,7 +1018,7 @@ static void track_init_markers(SpaceClip *sc, MovieClip *clip, int *frames_limit if (frames_limit == 0) frames_limit = track->frames_limit; else - frames_limit = MIN2(frames_limit, track->frames_limit); + frames_limit = min_ii(frames_limit, (int)track->frames_limit); } } } @@ -1343,7 +1343,6 @@ static int solve_camera_initjob(bContext *C, SolveCameraJob *scj, wmOperator *op MovieClip *clip = ED_space_clip_get_clip(sc); Scene *scene = CTX_data_scene(C); MovieTracking *tracking = &clip->tracking; - MovieTrackingSettings *settings = &clip->tracking.settings; MovieTrackingObject *object = BKE_tracking_object_get_active(tracking); int width, height; @@ -1359,7 +1358,7 @@ static int solve_camera_initjob(bContext *C, SolveCameraJob *scj, wmOperator *op scj->user = sc->user; scj->context = BKE_tracking_reconstruction_context_new(tracking, object, - settings->keyframe1, settings->keyframe2, width, height); + object->keyframe1, object->keyframe2, width, height); tracking->stats = MEM_callocN(sizeof(MovieTrackingStats), "solve camera stats"); @@ -1397,11 +1396,10 @@ static void solve_camera_freejob(void *scv) } solved = BKE_tracking_reconstruction_finish(scj->context, tracking); - if (!solved) - BKE_report(scj->reports, RPT_WARNING, "Some data failed to reconstruct, see console for details"); + BKE_report(scj->reports, RPT_WARNING, "Some data failed to reconstruct (see console for details)"); else - BKE_reportf(scj->reports, RPT_INFO, "Average re-projection error %.3f", tracking->reconstruction.error); + BKE_reportf(scj->reports, RPT_INFO, "Average re-projection error: %.3f", tracking->reconstruction.error); /* set currently solved clip as active for scene */ if (scene->clip) @@ -1411,7 +1409,7 @@ static void solve_camera_freejob(void *scv) id_us_plus(&clip->id); /* set blender camera focal length so result would look fine there */ - if (scene->camera) { + if (scene->camera && GS(scene->camera->id.name) == ID_CA) { Camera *camera = (Camera *)scene->camera->data; int width, height; @@ -2767,7 +2765,7 @@ static int join_tracks_exec(bContext *C, wmOperator *op) next = track->next; if (TRACK_VIEW_SELECTED(sc, track) && track != act_track) { - BKE_tracking_tracks_join(act_track, track); + BKE_tracking_tracks_join(tracking, act_track, track); if (tracking->stabilization.rot_track == track) tracking->stabilization.rot_track = act_track; @@ -2859,14 +2857,14 @@ static int set_solver_keyframe_exec(bContext *C, wmOperator *op) SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; - MovieTrackingSettings *settings = &tracking->settings; + MovieTrackingObject *object = BKE_tracking_object_get_active(tracking); int keyframe = RNA_enum_get(op->ptr, "keyframe"); int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, sc->user.framenr); if (keyframe == 0) - settings->keyframe1 = framenr; + object->keyframe1 = framenr; else - settings->keyframe2 = framenr; + object->keyframe2 = framenr; WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); @@ -3373,7 +3371,7 @@ static int tracking_object_remove_exec(bContext *C, wmOperator *op) object = BKE_tracking_object_get_active(tracking); if (object->flag & TRACKING_OBJECT_CAMERA) { - BKE_report(op->reports, RPT_WARNING, "Object used for camera tracking can't be deleted"); + BKE_report(op->reports, RPT_WARNING, "Object used for camera tracking cannot be deleted"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c index 507e492497d..b8e162bfb17 100644 --- a/source/blender/editors/space_clip/tracking_select.c +++ b/source/blender/editors/space_clip/tracking_select.c @@ -107,7 +107,7 @@ static int mouse_on_crns(float co[2], float pos[2], float crns[4][2], float epsx { float dist = dist_to_crns(co, pos, crns); - return dist < maxf(epsx, epsy); + return dist < max_ff(epsx, epsy); } static int track_mouse_area(const bContext *C, float co[2], MovieTrackingTrack *track) @@ -128,8 +128,8 @@ static int track_mouse_area(const bContext *C, float co[2], MovieTrackingTrack * epsy = MIN4(pat_min[1] - marker->search_min[1], marker->search_max[1] - pat_max[1], fabsf(pat_min[1]), fabsf(pat_max[1])) / 2; - epsx = maxf(epsx, 2.0f / width); - epsy = maxf(epsy, 2.0f / height); + epsx = max_ff(epsx, 2.0f / width); + epsy = max_ff(epsy, 2.0f / height); if (sc->flag & SC_SHOW_MARKER_SEARCH) { if (mouse_on_rect(co, marker->pos, marker->search_min, marker->search_max, epsx, epsy)) @@ -291,7 +291,6 @@ static int select_invoke(bContext *C, wmOperator *op, wmEvent *event) MovieTrackingTrack *track = tracking_marker_check_slide(C, event, NULL, NULL, NULL); if (track) { - SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); clip->tracking.act_track = track; @@ -413,7 +412,7 @@ void CLIP_OT_select_border(wmOperatorType *ot) /********************** lasso select operator *********************/ -static int do_lasso_select_marker(bContext *C, int mcords[][2], short moves, short select) +static int do_lasso_select_marker(bContext *C, const int mcords[][2], const short moves, short select) { SpaceClip *sc = CTX_wm_space_clip(C); ARegion *ar = CTX_wm_region(C); @@ -469,7 +468,7 @@ static int do_lasso_select_marker(bContext *C, int mcords[][2], short moves, sho static int clip_lasso_select_exec(bContext *C, wmOperator *op) { int mcords_tot; - int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); if (mcords) { short select; @@ -477,7 +476,7 @@ static int clip_lasso_select_exec(bContext *C, wmOperator *op) select = !RNA_boolean_get(op->ptr, "deselect"); do_lasso_select_marker(C, mcords, mcords_tot, select); - MEM_freeN(mcords); + MEM_freeN((void *)mcords); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c index 4c2f0ac73d4..f19835b7f85 100644 --- a/source/blender/editors/space_console/console_draw.c +++ b/source/blender/editors/space_console/console_draw.c @@ -84,7 +84,7 @@ typedef struct ConsoleDrawContext { #if 0 /* used by textview, may use later */ int *xy; // [2] int *sel; // [2] - int *pos_pick; // bottom of view == 0, top of file == combine chars, end of line is lower then start. + int *pos_pick; /* bottom of view == 0, top of file == combine chars, end of line is lower then start. */ int *mval; // [2] int draw; #endif @@ -94,12 +94,14 @@ void console_scrollback_prompt_begin(struct SpaceConsole *sc, ConsoleLine *cl_du { /* fake the edit line being in the scroll buffer */ ConsoleLine *cl = sc->history.last; + int prompt_len = strlen(sc->prompt); + cl_dummy->type = CONSOLE_LINE_INPUT; - cl_dummy->len = cl_dummy->len_alloc = strlen(sc->prompt) + cl->len; + cl_dummy->len = prompt_len + cl->len; cl_dummy->len_alloc = cl_dummy->len + 1; cl_dummy->line = MEM_mallocN(cl_dummy->len_alloc, "cl_dummy"); - memcpy(cl_dummy->line, sc->prompt, (cl_dummy->len_alloc - cl->len)); - memcpy(cl_dummy->line + ((cl_dummy->len_alloc - cl->len)) - 1, cl->line, cl->len + 1); + memcpy(cl_dummy->line, sc->prompt, prompt_len); + memcpy(cl_dummy->line + prompt_len, cl->line, cl->len + 1); BLI_addtail(&sc->scrollback, cl_dummy); } void console_scrollback_prompt_end(struct SpaceConsole *sc, ConsoleLine *cl_dummy) @@ -158,12 +160,13 @@ static int console_textview_line_color(struct TextViewContext *tvc, unsigned cha const ConsoleLine *cl = (ConsoleLine *)sc->history.last; const int prompt_len = strlen(sc->prompt); const int cursor_loc = cl->cursor + prompt_len; + const int line_len = cl->len + prompt_len; int xy[2] = {CONSOLE_DRAW_MARGIN, CONSOLE_DRAW_MARGIN}; int pen[2]; xy[1] += tvc->lheight / 6; /* account for wrapping */ - if (cl->len < tvc->console_width) { + if (line_len < tvc->console_width) { /* simple case, no wrapping */ pen[0] = tvc->cwidth * cursor_loc; pen[1] = -2; @@ -171,7 +174,7 @@ static int console_textview_line_color(struct TextViewContext *tvc, unsigned cha else { /* wrap */ pen[0] = tvc->cwidth * (cursor_loc % tvc->console_width); - pen[1] = -2 + (((cl->len / tvc->console_width) - (cursor_loc / tvc->console_width)) * tvc->lheight); + pen[1] = -2 + (((line_len / tvc->console_width) - (cursor_loc / tvc->console_width)) * tvc->lheight); } /* cursor */ diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index 7efcbcceb3c..d3ae5373a18 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -39,6 +39,7 @@ #include "BLI_string.h" #include "BLI_dynstr.h" #include "BLI_utildefines.h" +#include "BLI_math.h" #include "BKE_context.h" #include "BKE_text.h" /* only for character utility funcs */ @@ -449,7 +450,9 @@ static int console_indent_exec(bContext *C, wmOperator *UNUSED(op)) memmove(ci->line + len, ci->line, ci->len); memset(ci->line, ' ', len); ci->len += len; + BLI_assert(ci->len >= 0); console_line_cursor_set(ci, ci->cursor + len); + console_select_offset(sc, len); console_textview_update_rect(sc, ar); ED_area_tag_redraw(CTX_wm_area(C)); @@ -495,9 +498,10 @@ static int console_unindent_exec(bContext *C, wmOperator *UNUSED(op)) memmove(ci->line, ci->line + len, (ci->len - len) + 1); ci->len -= len; - console_line_cursor_set(ci, ci->cursor - len); + BLI_assert(ci->len >= 0); - //console_select_offset(sc, -4); + console_line_cursor_set(ci, ci->cursor - len); + console_select_offset(sc, -len); console_textview_update_rect(sc, ar); ED_area_tag_redraw(CTX_wm_area(C)); @@ -554,6 +558,7 @@ static int console_delete_exec(bContext *C, wmOperator *op) if (stride) { memmove(ci->line + ci->cursor, ci->line + ci->cursor + stride, (ci->len - ci->cursor) + 1); ci->len -= stride; + BLI_assert(ci->len >= 0); done = TRUE; } } @@ -570,6 +575,7 @@ static int console_delete_exec(bContext *C, wmOperator *op) ci->cursor -= stride; /* same as above */ memmove(ci->line + ci->cursor, ci->line + ci->cursor + stride, (ci->len - ci->cursor) + 1); ci->len -= stride; + BLI_assert(ci->len >= 0); done = TRUE; } } @@ -580,7 +586,7 @@ static int console_delete_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } else { - console_select_offset(sc, -1); + console_select_offset(sc, -stride); } console_textview_update_rect(sc, ar); @@ -650,7 +656,7 @@ static int console_clear_exec(bContext *C, wmOperator *op) short scrollback = RNA_boolean_get(op->ptr, "scrollback"); short history = RNA_boolean_get(op->ptr, "history"); - /*ConsoleLine *ci= */ console_history_verify(C); + /*ConsoleLine *ci = */ console_history_verify(C); if (scrollback) { /* last item in mistory */ while (sc->scrollback.first) @@ -803,7 +809,7 @@ void CONSOLE_OT_history_append(wmOperatorType *ot) ot->poll = ED_operator_console_active; /* properties */ - RNA_def_string(ot->srna, "text", "", 0, "Text", "Text to insert at the cursor position"); + RNA_def_string(ot->srna, "text", "", 0, "Text", "Text to insert at the cursor position"); RNA_def_int(ot->srna, "current_character", 0, 0, INT_MAX, "Cursor", "The index of the cursor", 0, 10000); RNA_def_boolean(ot->srna, "remove_duplicates", 0, "Remove Duplicates", "Remove duplicate items in the history"); } @@ -904,8 +910,8 @@ static int console_copy_exec(bContext *C, wmOperator *UNUSED(op)) for (cl = sc->scrollback.first; cl; cl = cl->next) { if (sel[0] <= cl->len && sel[1] >= 0) { - int sta = MAX2(sel[0], 0); - int end = MIN2(sel[1], cl->len); + int sta = max_ii(sel[0], 0); + int end = min_ii(sel[1], cl->len); if (BLI_dynstr_get_len(buf_dyn)) BLI_dynstr_append(buf_dyn, "\n"); @@ -1050,7 +1056,7 @@ static void console_modal_select_apply(bContext *C, wmOperator *op, wmEvent *eve static void console_cursor_set_exit(bContext *UNUSED(C), wmOperator *op) { -// SpaceConsole *sc= CTX_wm_space_console(C); +// SpaceConsole *sc = CTX_wm_space_console(C); SetConsoleCursor *scu = op->customdata; #if 0 @@ -1067,7 +1073,7 @@ static void console_cursor_set_exit(bContext *UNUSED(C), wmOperator *op) static int console_modal_select_invoke(bContext *C, wmOperator *op, wmEvent *event) { SpaceConsole *sc = CTX_wm_space_console(C); -// ARegion *ar= CTX_wm_region(C); +// ARegion *ar = CTX_wm_region(C); SetConsoleCursor *scu; op->customdata = MEM_callocN(sizeof(SetConsoleCursor), "SetConsoleCursor"); diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index a4f7e30ed7b..75add570708 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -91,7 +91,7 @@ static SpaceLink *console_new(const bContext *UNUSED(C)) ar->v2d.minzoom = ar->v2d.maxzoom = 1.0f; /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */ - //ar->v2d.keepzoom= (V2D_KEEPASPECT|V2D_LIMITZOOM); + //ar->v2d.keepzoom = (V2D_KEEPASPECT|V2D_LIMITZOOM); return (SpaceLink *)sconsole; } @@ -142,7 +142,7 @@ static void console_main_area_init(wmWindowManager *wm, ARegion *ar) /* always keep the bottom part of the view aligned, less annoying */ if (prev_y_min != ar->v2d.cur.ymin) { - const float cur_y_range = BLI_RCT_SIZE_Y(&ar->v2d.cur); + const float cur_y_range = BLI_rctf_size_y(&ar->v2d.cur); ar->v2d.cur.ymin = prev_y_min; ar->v2d.cur.ymax = prev_y_min + cur_y_range; } @@ -162,7 +162,7 @@ static void console_main_area_init(wmWindowManager *wm, ARegion *ar) static int id_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event)) { -// SpaceConsole *sc= CTX_wm_space_console(C); +// SpaceConsole *sc = CTX_wm_space_console(C); if (drag->type == WM_DRAG_ID) return 1; return 0; @@ -184,7 +184,7 @@ static void id_drop_copy(wmDrag *drag, wmDropBox *drop) static int path_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event)) { -// SpaceConsole *sc= CTX_wm_space_console(C); + // SpaceConsole *sc = CTX_wm_space_console(C); if (drag->type == WM_DRAG_PATH) return 1; return 0; @@ -359,7 +359,7 @@ static void console_header_area_draw(const bContext *C, ARegion *ar) static void console_main_area_listener(ARegion *ar, wmNotifier *wmn) { - // SpaceInfo *sinfo= sa->spacedata.first; + // SpaceInfo *sinfo = sa->spacedata.first; /* context changes */ switch (wmn->category) { diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 55e75992b89..fb438ae45fb 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -257,21 +257,23 @@ static int get_file_icon(struct direntry *file) else if (file->flags & BLENDERFILE) return ICON_FILE_BLEND; else if (file->flags & BLENDERFILE_BACKUP) - return ICON_FILE_BLEND; + return ICON_FILE_BACKUP; else if (file->flags & IMAGEFILE) return ICON_FILE_IMAGE; else if (file->flags & MOVIEFILE) return ICON_FILE_MOVIE; else if (file->flags & PYSCRIPTFILE) return ICON_FILE_SCRIPT; - else if (file->flags & SOUNDFILE) + else if (file->flags & SOUNDFILE) return ICON_FILE_SOUND; - else if (file->flags & FTFONTFILE) + else if (file->flags & FTFONTFILE) return ICON_FILE_FONT; - else if (file->flags & BTXFILE) + else if (file->flags & BTXFILE) return ICON_FILE_BLANK; - else if (file->flags & COLLADAFILE) + else if (file->flags & COLLADAFILE) return ICON_FILE_BLANK; + else if (file->flags & TEXTFILE) + return ICON_FILE_TEXT; else return ICON_FILE_BLANK; } @@ -280,7 +282,7 @@ static void file_draw_icon(uiBlock *block, char *path, int sx, int sy, int icon, { uiBut *but; int x, y; - /*float alpha=1.0f;*/ + // float alpha = 1.0f; x = sx; y = sy - height; @@ -494,7 +496,7 @@ void file_draw_list(const bContext *C, ARegion *ar) sx += (int)(v2d->tot.xmin + 2.0f); sy = (int)(v2d->tot.ymax - sy); - file = filelist_file(files, i); + file = filelist_file(files, i); UI_ThemeColor4(TH_TEXT); @@ -544,7 +546,7 @@ void file_draw_list(const bContext *C, ARegion *ar) if (params->display == FILE_SHORTDISPLAY) { sx += (int)layout->column_widths[COLUMN_NAME] + 12; if (!(file->type & S_IFDIR)) { - file_draw_string(sx, sy, file->size, layout->column_widths[COLUMN_SIZE], layout->tile_h, align); + file_draw_string(sx, sy, file->size, layout->column_widths[COLUMN_SIZE], layout->tile_h, align); sx += (int)layout->column_widths[COLUMN_SIZE] + 12; } } diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index a07a560328c..e5c6a839380 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -66,6 +66,7 @@ void FILE_OT_select_border(struct wmOperatorType *ot); void FILE_OT_select_bookmark(struct wmOperatorType *ot); void FILE_OT_bookmark_add(struct wmOperatorType *ot); void FILE_OT_delete_bookmark(struct wmOperatorType *ot); +void FILE_OT_reset_recent(wmOperatorType *ot); void FILE_OT_hidedot(struct wmOperatorType *ot); void FILE_OT_execute(struct wmOperatorType *ot); void FILE_OT_cancel(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 040f276940d..763b18788de 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -64,11 +64,6 @@ #include #include -/* for events */ -#define NOTACTIVEFILE 0 -#define ACTIVATE 1 -#define INACTIVATE 2 - /* ---------- FILE SELECTION ------------ */ static FileSelection find_file_mouse_rect(SpaceFile *sfile, ARegion *ar, const rcti *rect) { @@ -312,7 +307,7 @@ void FILE_OT_select_border(wmOperatorType *ot) ot->poll = ED_operator_file_active; ot->cancel = WM_border_select_cancel; - /* rna */ + /* properties */ WM_operator_properties_gesture_border(ot, 1); } @@ -352,6 +347,8 @@ static int file_select_invoke(bContext *C, wmOperator *op, wmEvent *event) void FILE_OT_select(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Activate/Select File"; ot->description = "Activate/select file"; @@ -361,10 +358,13 @@ void FILE_OT_select(wmOperatorType *ot) ot->invoke = file_select_invoke; ot->poll = ED_operator_file_active; - /* rna */ - RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first"); - RNA_def_boolean(ot->srna, "fill", FALSE, "Fill", "Select everything beginning with the last selection"); - RNA_def_boolean(ot->srna, "open", TRUE, "Open", "Open a directory when selecting it"); + /* properties */ + prop = RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "fill", FALSE, "Fill", "Select everything beginning with the last selection"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "open", TRUE, "Open", "Open a directory when selecting it"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } static int file_select_all_exec(bContext *C, wmOperator *UNUSED(op)) @@ -409,9 +409,7 @@ void FILE_OT_select_all_toggle(wmOperatorType *ot) ot->exec = file_select_all_exec; ot->poll = ED_operator_file_active; - /* rna */ - - + /* properties */ } /* ---------- BOOKMARKS ----------- */ @@ -437,6 +435,8 @@ static int bookmark_select_exec(bContext *C, wmOperator *op) void FILE_OT_select_bookmark(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Select Directory"; ot->description = "Select a bookmarked directory"; @@ -446,7 +446,9 @@ void FILE_OT_select_bookmark(wmOperatorType *ot) ot->exec = bookmark_select_exec; ot->poll = ED_operator_file_active; - RNA_def_string(ot->srna, "dir", "", 256, "Dir", ""); + /* properties */ + prop = RNA_def_string(ot->srna, "dir", "", FILE_MAXDIR, "Dir", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } static int bookmark_add_exec(bContext *C, wmOperator *UNUSED(op)) @@ -459,7 +461,7 @@ static int bookmark_add_exec(bContext *C, wmOperator *UNUSED(op)) if (params->dir[0] != '\0') { char name[FILE_MAX]; - fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir, 0, 1); + fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir, FS_INSERT_SAVE); BLI_make_file_string("/", name, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE); fsmenu_write_file(fsmenu, name); } @@ -503,6 +505,8 @@ static int bookmark_delete_exec(bContext *C, wmOperator *op) void FILE_OT_delete_bookmark(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Delete Bookmark"; ot->description = "Delete selected bookmark"; @@ -512,14 +516,45 @@ void FILE_OT_delete_bookmark(wmOperatorType *ot) ot->exec = bookmark_delete_exec; ot->poll = ED_operator_file_active; - RNA_def_int(ot->srna, "index", -1, -1, 20000, "Index", "", -1, 20000); + /* properties */ + prop = RNA_def_int(ot->srna, "index", -1, -1, 20000, "Index", "", -1, 20000); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); +} + +static int reset_recent_exec(bContext *C, wmOperator *UNUSED(op)) +{ + ScrArea *sa = CTX_wm_area(C); + char name[FILE_MAX]; + struct FSMenu *fsmenu = fsmenu_get(); + + while (fsmenu_get_entry(fsmenu, FS_CATEGORY_RECENT, 0) != NULL) { + fsmenu_remove_entry(fsmenu, FS_CATEGORY_RECENT, 0); + } + BLI_make_file_string("/", name, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE); + fsmenu_write_file(fsmenu, name); + ED_area_tag_redraw(sa); + + return OPERATOR_FINISHED; +} + +void FILE_OT_reset_recent(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Reset Recent"; + ot->description = "Reset Recent files"; + ot->idname = "FILE_OT_reset_recent"; + + /* api callbacks */ + ot->exec = reset_recent_exec; + ot->poll = ED_operator_file_active; + } int file_highlight_set(SpaceFile *sfile, ARegion *ar, int mx, int my) { View2D *v2d = &ar->v2d; FileSelectParams *params; - int numfiles, origfile; + int numfiles, origfile; if (sfile == NULL || sfile->files == NULL) return 0; @@ -770,8 +805,9 @@ int file_exec(bContext *C, wmOperator *exec_op) file_sfile_to_operator(op, sfile, filepath); - if (BLI_exists(sfile->params->dir)) - fsmenu_insert_entry(fsmenu_get(), FS_CATEGORY_RECENT, sfile->params->dir, 0, 1); + if (BLI_exists(sfile->params->dir)) { + fsmenu_insert_entry(fsmenu_get(), FS_CATEGORY_RECENT, sfile->params->dir, FS_INSERT_SAVE | FS_INSERT_FIRST); + } BLI_make_file_string(G.main->name, filepath, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE); fsmenu_write_file(fsmenu_get(), filepath); @@ -794,7 +830,8 @@ void FILE_OT_execute(struct wmOperatorType *ot) /* api callbacks */ ot->exec = file_exec; ot->poll = file_operator_poll; - + + /* properties */ prop = RNA_def_boolean(ot->srna, "need_active", 0, "Need Active", "Only execute if there's an active selected file in the file list"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); @@ -812,7 +849,7 @@ int file_parent_exec(bContext *C, wmOperator *UNUSED(unused)) file_change_dir(C, 0); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); } - } + } return OPERATOR_FINISHED; @@ -905,7 +942,7 @@ int file_next_exec(bContext *C, wmOperator *UNUSED(unused)) folderlist_pushdir(sfile->folders_prev, sfile->params->dir); file_change_dir(C, 1); - } + } WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); return OPERATOR_FINISHED; @@ -1068,7 +1105,7 @@ int file_directory_new_exec(bContext *C, wmOperator *op) if (generate_name) { /* create a new, non-existing folder name */ if (!new_folder_path(sfile->params->dir, path, name)) { - BKE_report(op->reports, RPT_ERROR, "Couldn't create new folder name"); + BKE_report(op->reports, RPT_ERROR, "Could not create new folder name"); return OPERATOR_CANCELLED; } } @@ -1077,9 +1114,9 @@ int file_directory_new_exec(bContext *C, wmOperator *op) BLI_dir_create_recursive(path); if (!BLI_exists(path)) { - BKE_report(op->reports, RPT_ERROR, "Couldn't create new folder"); + BKE_report(op->reports, RPT_ERROR, "Could not create new folder"); return OPERATOR_CANCELLED; - } + } /* now remember file to jump into editing */ BLI_strncpy(sfile->params->renamefile, name, FILE_MAXFILE); @@ -1098,6 +1135,8 @@ int file_directory_new_exec(bContext *C, wmOperator *op) void FILE_OT_directory_new(struct wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Create New Directory"; ot->description = "Create a new directory"; @@ -1108,7 +1147,8 @@ void FILE_OT_directory_new(struct wmOperatorType *ot) ot->exec = file_directory_new_exec; ot->poll = ED_operator_file_active; /* <- important, handler is on window level */ - RNA_def_string_dir_path(ot->srna, "directory", "", FILE_MAX, "Directory", "Name of new directory"); + prop = RNA_def_string_dir_path(ot->srna, "directory", "", FILE_MAX, "Directory", "Name of new directory"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } @@ -1387,11 +1427,11 @@ static int file_rename_poll(bContext *C) SpaceFile *sfile = CTX_wm_space_file(C); if (sfile && sfile->params) { - if (sfile->params->active_file < 0) { + if (sfile->params->active_file < 0) { poll = 0; } else { - char dir[FILE_MAX], group[FILE_MAX]; + char dir[FILE_MAX], group[FILE_MAX]; if (filelist_islibrary(sfile->files, dir, group)) poll = 0; } } @@ -1420,11 +1460,11 @@ static int file_delete_poll(bContext *C) struct direntry *file; if (sfile && sfile->params) { - if (sfile->params->active_file < 0) { + if (sfile->params->active_file < 0) { poll = 0; } else { - char dir[FILE_MAX], group[FILE_MAX]; + char dir[FILE_MAX], group[FILE_MAX]; if (filelist_islibrary(sfile->files, dir, group)) poll = 0; file = filelist_file(sfile->files, sfile->params->active_file); if (file && S_ISDIR(file->type)) poll = 0; @@ -1445,7 +1485,7 @@ int file_delete_exec(bContext *C, wmOperator *UNUSED(op)) file = filelist_file(sfile->files, sfile->params->active_file); BLI_make_file_string(G.main->name, str, sfile->params->dir, file->relname); - BLI_delete(str, 0, 0); + BLI_delete(str, 0, 0); ED_fileselect_clear(C, sfile); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c index 51bd660e126..a159c88221e 100644 --- a/source/blender/editors/space_file/file_panels.c +++ b/source/blender/editors/space_file/file_panels.c @@ -67,14 +67,14 @@ static void file_panel_cb(bContext *C, void *arg_entry, void *UNUSED(arg_v)) WM_operator_properties_free(&ptr); } -static void file_panel_category(const bContext *C, Panel *pa, FSMenuCategory category, short *nr, int icon, int allow_delete, int reverse) +static void file_panel_category(const bContext *C, Panel *pa, FSMenuCategory category, short *nr, int icon, int allow_delete) { SpaceFile *sfile = CTX_wm_space_file(C); uiBlock *block; uiBut *but; uiLayout *box, *col; struct FSMenu *fsmenu = fsmenu_get(); - int i, i_iter, nentries = fsmenu_get_nentries(fsmenu, category); + int i, nentries = fsmenu_get_nentries(fsmenu, category); /* reset each time */ *nr = -1; @@ -89,13 +89,11 @@ static void file_panel_category(const bContext *C, Panel *pa, FSMenuCategory cat box = uiLayoutBox(pa->layout); col = uiLayoutColumn(box, TRUE); - for (i_iter = 0; i_iter < nentries; ++i_iter) { + for (i = 0; i < nentries; ++i) { char dir[FILE_MAX]; char temp[FILE_MAX]; uiLayout *layout = uiLayoutRow(col, FALSE); char *entry; - - i = reverse ? nentries - (i_iter + 1) : i_iter; entry = fsmenu_get_entry(fsmenu, category, i); @@ -134,7 +132,17 @@ static void file_panel_system(const bContext *C, Panel *pa) SpaceFile *sfile = CTX_wm_space_file(C); if (sfile) - file_panel_category(C, pa, FS_CATEGORY_SYSTEM, &sfile->systemnr, ICON_DISK_DRIVE, 0, 0); + file_panel_category(C, pa, FS_CATEGORY_SYSTEM, &sfile->systemnr, ICON_DISK_DRIVE, 0); +} + +static void file_panel_system_bookmarks(const bContext *C, Panel *pa) +{ + SpaceFile *sfile = CTX_wm_space_file(C); + + if (sfile && !(U.uiflag & USER_HIDE_SYSTEM_BOOKMARKS) ) { + file_panel_category(C, pa, FS_CATEGORY_SYSTEM_BOOKMARKS, &sfile->systemnr, ICON_BOOKMARKS, 0); + } + } static void file_panel_bookmarks(const bContext *C, Panel *pa) @@ -147,17 +155,22 @@ static void file_panel_bookmarks(const bContext *C, Panel *pa) uiItemO(row, IFACE_("Add"), ICON_ZOOMIN, "file.bookmark_add"); uiItemL(row, NULL, ICON_NONE); - file_panel_category(C, pa, FS_CATEGORY_BOOKMARKS, &sfile->bookmarknr, ICON_BOOKMARKS, 1, 0); + file_panel_category(C, pa, FS_CATEGORY_BOOKMARKS, &sfile->bookmarknr, ICON_BOOKMARKS, 1); } } static void file_panel_recent(const bContext *C, Panel *pa) { SpaceFile *sfile = CTX_wm_space_file(C); + uiLayout *row; if (sfile) { if (!(U.uiflag & USER_HIDE_RECENT) ) { - file_panel_category(C, pa, FS_CATEGORY_RECENT, &sfile->recentnr, ICON_FILE_FOLDER, 0, 1); + row = uiLayoutRow(pa->layout, FALSE); + uiItemO(row, IFACE_("Reset"), ICON_X, "file.reset_recent"); + uiItemL(row, NULL, ICON_NONE); + + file_panel_category(C, pa, FS_CATEGORY_RECENT, &sfile->recentnr, ICON_FILE_FOLDER, 0); } } } @@ -190,7 +203,7 @@ static void file_panel_operator(const bContext *C, Panel *pa) { SpaceFile *sfile = CTX_wm_space_file(C); wmOperator *op = sfile->op; - // int empty= 1, flag; + // int empty = 1, flag; uiBlockSetFunc(uiLayoutGetBlock(pa->layout), file_draw_check_cb, NULL, NULL); @@ -209,6 +222,12 @@ void file_panels_register(ARegionType *art) pt->draw = file_panel_system; BLI_addtail(&art->paneltypes, pt); + pt = MEM_callocN(sizeof(PanelType), "spacetype file system bookmarks"); + strcpy(pt->idname, "FILE_PT_system_bookmarks"); + strcpy(pt->label, N_("System Bookmarks")); + pt->draw = file_panel_system_bookmarks; + BLI_addtail(&art->paneltypes, pt); + pt = MEM_callocN(sizeof(PanelType), "spacetype file bookmarks"); strcpy(pt->idname, "FILE_PT_bookmarks"); strcpy(pt->label, N_("Bookmarks")); diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index d3b4df05aa9..8f94086013c 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -143,7 +143,8 @@ typedef struct FolderList { #define SPECIAL_IMG_FONTFILE 8 #define SPECIAL_IMG_UNKNOWNFILE 9 #define SPECIAL_IMG_LOADING 10 -#define SPECIAL_IMG_MAX SPECIAL_IMG_LOADING + 1 +#define SPECIAL_IMG_BACKUP 11 +#define SPECIAL_IMG_MAX SPECIAL_IMG_BACKUP + 1 static ImBuf *gSpecialFileImages[SPECIAL_IMG_MAX]; @@ -300,7 +301,7 @@ static int is_hidden_file(const char *filename, short hide_dot) if ( (len > 0) && (filename[len - 1] == '~') ) { is_hidden = 1; /* ignore file~ */ } - } + } } else { if (((filename[0] == '.') && (filename[1] == 0) )) { @@ -360,7 +361,7 @@ void filelist_filter(FileList *filelist) struct direntry *file = &filelist->filelist[i]; if (filelist->filterf(file, filelist->dir, filelist->filter, filelist->hide_dot) ) { num_filtered++; - } + } } if (filelist->fidx) { @@ -420,7 +421,7 @@ void filelist_free_icons(void) } } -//-----------------FOLDERLIST (previous/next) --------------// +/* -----------------FOLDERLIST (previous/next) -------------- */ ListBase *folderlist_new(void) { ListBase *p = MEM_callocN(sizeof(ListBase), "folderlist"); @@ -520,7 +521,7 @@ static void filelist_read_main(struct FileList *filelist); static void filelist_read_library(struct FileList *filelist); static void filelist_read_dir(struct FileList *filelist); -//------------------FILELIST------------------------// +/* ------------------FILELIST------------------------ */ FileList *filelist_new(short type) { FileList *p = MEM_callocN(sizeof(FileList), "filelist"); @@ -557,7 +558,7 @@ void filelist_free(struct FileList *filelist) } for (i = 0; i < filelist->numfiles; ++i) { - if (filelist->filelist[i].image) { + if (filelist->filelist[i].image) { IMB_freeImBuf(filelist->filelist[i].image); } filelist->filelist[i].image = NULL; @@ -573,7 +574,7 @@ void filelist_free(struct FileList *filelist) filelist->numfiles = 0; free(filelist->filelist); - filelist->filelist = NULL; + filelist->filelist = NULL; filelist->filter = 0; filelist->filter_glob[0] = '\0'; filelist->numfiltered = 0; @@ -683,6 +684,9 @@ ImBuf *filelist_geticon(struct FileList *filelist, int index) else if (file->flags & IMAGEFILE) { ibuf = gSpecialFileImages[SPECIAL_IMG_LOADING]; } + else if (file->flags & BLENDERFILE_BACKUP) { + ibuf = gSpecialFileImages[SPECIAL_IMG_BACKUP]; + } return ibuf; } @@ -748,7 +752,9 @@ static int file_is_blend_backup(const char *str) a = strlen(str); b = 7; - if (a == 0 || b >= a) ; + if (a == 0 || b >= a) { + /* pass */ + } else { char *loc; @@ -779,6 +785,7 @@ static int file_extension_type(const char *relname) } else if (BLI_testextensie(relname, ".txt") || BLI_testextensie(relname, ".glsl") || + BLI_testextensie(relname, ".osl") || BLI_testextensie(relname, ".data")) { return TEXTFILE; @@ -789,7 +796,7 @@ static int file_extension_type(const char *relname) BLI_testextensie(relname, ".otf") || BLI_testextensie(relname, ".otc")) { - return FTFONTFILE; + return FTFONTFILE; } else if (BLI_testextensie(relname, ".btx")) { return BTXFILE; @@ -800,14 +807,14 @@ static int file_extension_type(const char *relname) else if (BLI_testextensie_array(relname, imb_ext_image) || (G.have_quicktime && BLI_testextensie_array(relname, imb_ext_image_qt))) { - return IMAGEFILE; + return IMAGEFILE; } else if (BLI_testextensie_array(relname, imb_ext_movie)) { - return MOVIEFILE; + return MOVIEFILE; } else if (BLI_testextensie_array(relname, imb_ext_audio)) { return SOUNDFILE; - } + } return 0; } @@ -815,8 +822,10 @@ int ED_file_extension_icon(const char *relname) { int type = file_extension_type(relname); - if (type == BLENDERFILE || type == BLENDERFILE_BACKUP) + if (type == BLENDERFILE) return ICON_FILE_BLEND; + else if (type == BLENDERFILE_BACKUP) + return ICON_FILE_BACKUP; else if (type == IMAGEFILE) return ICON_FILE_IMAGE; else if (type == MOVIEFILE) @@ -831,6 +840,8 @@ int ED_file_extension_icon(const char *relname) return ICON_FILE_BLANK; else if (type == COLLADAFILE) return ICON_FILE_BLANK; + else if (type == TEXTFILE) + return ICON_FILE_TEXT; return ICON_FILE_BLANK; } @@ -932,7 +943,7 @@ void filelist_parent(struct FileList *filelist) void filelist_select_file(struct FileList *filelist, int index, FileSelType select, unsigned int flag, FileCheckType check) { struct direntry *file = filelist_file(filelist, index); - if (file != NULL) { + if (file != NULL) { int check_ok = 0; switch (check) { case CHECK_DIRS: @@ -967,7 +978,7 @@ void filelist_select(struct FileList *filelist, FileSelection *sel, FileSelType /* select all valid files between first and last indicated */ if ( (sel->first >= 0) && (sel->first < filelist->numfiltered) && (sel->last >= 0) && (sel->last < filelist->numfiltered) ) { int current_file; - for (current_file = sel->first; current_file <= sel->last; current_file++) { + for (current_file = sel->first; current_file <= sel->last; current_file++) { filelist_select_file(filelist, current_file, select, flag, check); } } @@ -1034,7 +1045,7 @@ void filelist_from_library(struct FileList *filelist) struct ImBuf *ima; int ok, i, nprevs, nnames, idcode; char filename[FILE_MAX]; - char dir[FILE_MAX], group[GROUP_MAX]; + char dir[FILE_MAX], group[GROUP_MAX]; /* name test */ ok = filelist_islibrary(filelist, dir, group); @@ -1223,21 +1234,22 @@ void filelist_from_main(struct FileList *filelist) if (ok) { if (!filelist->hide_dot || id->name[2] != '.') { memset(files, 0, sizeof(struct direntry)); - if (id->lib == NULL) + if (id->lib == NULL) { files->relname = BLI_strdup(id->name + 2); + } else { - files->relname = MEM_mallocN(FILE_MAX + 32, "filename for lib"); - sprintf(files->relname, "%s | %s", id->lib->name, id->name + 2); + files->relname = MEM_mallocN(FILE_MAX + (MAX_ID_NAME - 2), "filename for lib"); + BLI_snprintf(files->relname, FILE_MAX + (MAX_ID_NAME - 2) + 3, "%s | %s", id->lib->name, id->name + 2); } files->type |= S_IFREG; -#if 0 // XXXXX TODO show the selection status of the objects +#if 0 /* XXXXX TODO show the selection status of the objects */ if (!filelist->has_func) { /* F4 DATA BROWSE */ if (idcode == ID_OB) { if ( ((Object *)id)->flag & SELECT) files->selflag |= SELECTED_FILE; } else if (idcode == ID_SCE) { if ( ((Scene *)id)->r.scemode & R_BG_RENDER) files->selflag |= SELECTED_FILE; - } + } } #endif files->nr = totbl + 1; @@ -1246,10 +1258,10 @@ void filelist_from_main(struct FileList *filelist) if (idcode == ID_MA || idcode == ID_TE || idcode == ID_LA || idcode == ID_WO || idcode == ID_IM) { files->flags |= IMAGEFILE; } - if (id->lib && fake) BLI_snprintf(files->extra, sizeof(files->extra), "LF %d", id->us); - else if (id->lib) BLI_snprintf(files->extra, sizeof(files->extra), "L %d", id->us); - else if (fake) BLI_snprintf(files->extra, sizeof(files->extra), "F %d", id->us); - else BLI_snprintf(files->extra, sizeof(files->extra), " %d", id->us); + if (id->lib && fake) BLI_snprintf(files->extra, sizeof(files->extra), "LF %d", id->us); + else if (id->lib) BLI_snprintf(files->extra, sizeof(files->extra), "L %d", id->us); + else if (fake) BLI_snprintf(files->extra, sizeof(files->extra), "F %d", id->us); + else BLI_snprintf(files->extra, sizeof(files->extra), " %d", id->us); if (id->lib) { if (totlib == 0) firstlib = files; @@ -1298,7 +1310,7 @@ static void thumbnails_startjob(void *tjv, short *stop, short *do_update, float if (limg->flags & IMAGEFILE) { limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_IMAGE); } - else if (limg->flags & BLENDERFILE) { + else if (limg->flags & (BLENDERFILE | BLENDERFILE_BACKUP)) { limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, THB_SOURCE_BLEND); } else if (limg->flags & MOVIEFILE) { @@ -1355,7 +1367,7 @@ void thumbnails_start(struct FileList *filelist, const struct bContext *C) tj->filelist = filelist; for (idx = 0; idx < filelist->numfiles; idx++) { if (!filelist->filelist[idx].image) { - if ( (filelist->filelist[idx].flags & (IMAGEFILE | MOVIEFILE | BLENDERFILE)) ) { + if ( (filelist->filelist[idx].flags & (IMAGEFILE | MOVIEFILE | BLENDERFILE | BLENDERFILE_BACKUP)) ) { FileImage *limg = MEM_callocN(sizeof(struct FileImage), "loadimage"); BLI_strncpy(limg->path, filelist->filelist[idx].path, FILE_MAX); limg->index = idx; diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 09231efd367..49562958f82 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -94,6 +94,9 @@ FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile) return sfile->params; } +/** + * \note RNA_struct_property_is_set_ex is used here because we wan't + * the previously used settings to be used here rather then overriding them */ short ED_fileselect_set_params(SpaceFile *sfile) { FileSelectParams *params; @@ -124,7 +127,7 @@ short ED_fileselect_set_params(SpaceFile *sfile) else params->type = FILE_SPECIAL; - if (is_filepath && RNA_struct_property_is_set(op->ptr, "filepath")) { + if (is_filepath && RNA_struct_property_is_set_ex(op->ptr, "filepath", FALSE)) { char name[FILE_MAX]; RNA_string_get(op->ptr, "filepath", name); if (params->type == FILE_LOADLIB) { @@ -136,12 +139,12 @@ short ED_fileselect_set_params(SpaceFile *sfile) } } else { - if (is_directory && RNA_struct_property_is_set(op->ptr, "directory")) { + if (is_directory && RNA_struct_property_is_set_ex(op->ptr, "directory", FALSE)) { RNA_string_get(op->ptr, "directory", params->dir); sfile->params->file[0] = '\0'; } - if (is_filename && RNA_struct_property_is_set(op->ptr, "filename")) { + if (is_filename && RNA_struct_property_is_set_ex(op->ptr, "filename", FALSE)) { RNA_string_get(op->ptr, "filename", params->file); } } @@ -165,8 +168,6 @@ short ED_fileselect_set_params(SpaceFile *sfile) params->filter |= RNA_boolean_get(op->ptr, "filter_image") ? IMAGEFILE : 0; if (RNA_struct_find_property(op->ptr, "filter_movie")) params->filter |= RNA_boolean_get(op->ptr, "filter_movie") ? MOVIEFILE : 0; - if (RNA_struct_find_property(op->ptr, "filter_text")) - params->filter |= RNA_boolean_get(op->ptr, "filter_text") ? TEXTFILE : 0; if (RNA_struct_find_property(op->ptr, "filter_python")) params->filter |= RNA_boolean_get(op->ptr, "filter_python") ? PYSCRIPTFILE : 0; if (RNA_struct_find_property(op->ptr, "filter_font")) @@ -228,7 +229,7 @@ short ED_fileselect_set_params(SpaceFile *sfile) } if (is_relative_path) { - if (!RNA_struct_property_is_set(op->ptr, "relative_path")) { + if (!RNA_struct_property_is_set_ex(op->ptr, "relative_path", FALSE)) { RNA_boolean_set(op->ptr, "relative_path", U.flag & USER_RELPATHS); } } @@ -270,12 +271,12 @@ int ED_fileselect_layout_numfiles(FileLayout *layout, ARegion *ar) int numfiles; if (layout->flag & FILE_LAYOUT_HOR) { - int width = (int)(BLI_RCT_SIZE_X(&ar->v2d.cur) - 2 * layout->tile_border_x); + int width = (int)(BLI_rctf_size_x(&ar->v2d.cur) - 2 * layout->tile_border_x); numfiles = (int)((float)width / (float)layout->tile_w + 0.5f); return numfiles * layout->rows; } else { - int height = (int)(BLI_RCT_SIZE_Y(&ar->v2d.cur) - 2 * layout->tile_border_y); + int height = (int)(BLI_rctf_size_y(&ar->v2d.cur) - 2 * layout->tile_border_y); numfiles = (int)((float)height / (float)layout->tile_h + 0.5f); return numfiles * layout->columns; } @@ -307,7 +308,7 @@ FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const rcti *r CLAMP(rowmin, 0, layout->rows - 1); CLAMP(colmax, 0, layout->columns - 1); CLAMP(rowmax, 0, layout->rows - 1); - } + } if ((colmin > layout->columns - 1) || (rowmin > layout->rows - 1)) { sel.first = -1; @@ -503,7 +504,7 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar) layout->prv_border_y = 6; layout->tile_w = layout->prv_w + 2 * layout->prv_border_x; layout->tile_h = layout->prv_h + 2 * layout->prv_border_y + textheight; - layout->width = (int)(BLI_RCT_SIZE_X(&v2d->cur) - 2 * layout->tile_border_x); + layout->width = (int)(BLI_rctf_size_x(&v2d->cur) - 2 * layout->tile_border_x); layout->columns = layout->width / (layout->tile_w + 2 * layout->tile_border_x); if (layout->columns > 0) layout->rows = numfiles / layout->columns + 1; // XXX dirty, modulo is zero @@ -522,7 +523,7 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar) layout->prv_border_x = 0; layout->prv_border_y = 0; layout->tile_h = textheight * 3 / 2; - layout->height = (int)(BLI_RCT_SIZE_Y(&v2d->cur) - 2 * layout->tile_border_y); + layout->height = (int)(BLI_rctf_size_y(&v2d->cur) - 2 * layout->tile_border_y); layout->rows = layout->height / (layout->tile_h + 2 * layout->tile_border_y); column_widths(sfile->files, layout); diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index a127e2ca2bc..a5647c06b92 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -80,9 +80,9 @@ struct _FSMenuEntry { typedef struct FSMenu { FSMenuEntry *fsmenu_system; + FSMenuEntry *fsmenu_system_bookmarks; FSMenuEntry *fsmenu_bookmarks; FSMenuEntry *fsmenu_recent; - } FSMenu; static FSMenu *g_fsmenu = NULL; @@ -97,84 +97,100 @@ FSMenu *fsmenu_get(void) static FSMenuEntry *fsmenu_get_category(struct FSMenu *fsmenu, FSMenuCategory category) { - FSMenuEntry *fsms = NULL; + FSMenuEntry *fsm_head = NULL; switch (category) { case FS_CATEGORY_SYSTEM: - fsms = fsmenu->fsmenu_system; + fsm_head = fsmenu->fsmenu_system; + break; + case FS_CATEGORY_SYSTEM_BOOKMARKS: + fsm_head = fsmenu->fsmenu_system_bookmarks; break; case FS_CATEGORY_BOOKMARKS: - fsms = fsmenu->fsmenu_bookmarks; + fsm_head = fsmenu->fsmenu_bookmarks; break; case FS_CATEGORY_RECENT: - fsms = fsmenu->fsmenu_recent; + fsm_head = fsmenu->fsmenu_recent; break; } - return fsms; + return fsm_head; } -static void fsmenu_set_category(struct FSMenu *fsmenu, FSMenuCategory category, FSMenuEntry *fsms) +static void fsmenu_set_category(struct FSMenu *fsmenu, FSMenuCategory category, FSMenuEntry *fsm_head) { switch (category) { case FS_CATEGORY_SYSTEM: - fsmenu->fsmenu_system = fsms; + fsmenu->fsmenu_system = fsm_head; + break; + case FS_CATEGORY_SYSTEM_BOOKMARKS: + fsmenu->fsmenu_system_bookmarks = fsm_head; break; case FS_CATEGORY_BOOKMARKS: - fsmenu->fsmenu_bookmarks = fsms; + fsmenu->fsmenu_bookmarks = fsm_head; break; case FS_CATEGORY_RECENT: - fsmenu->fsmenu_recent = fsms; + fsmenu->fsmenu_recent = fsm_head; break; } } int fsmenu_get_nentries(struct FSMenu *fsmenu, FSMenuCategory category) { - FSMenuEntry *fsme; + FSMenuEntry *fsm_iter; int count = 0; - for (fsme = fsmenu_get_category(fsmenu, category); fsme; fsme = fsme->next) + for (fsm_iter = fsmenu_get_category(fsmenu, category); fsm_iter; fsm_iter = fsm_iter->next) { count++; + } return count; } char *fsmenu_get_entry(struct FSMenu *fsmenu, FSMenuCategory category, int idx) { - FSMenuEntry *fsme; + FSMenuEntry *fsm_iter; - for (fsme = fsmenu_get_category(fsmenu, category); fsme && idx; fsme = fsme->next) + for (fsm_iter = fsmenu_get_category(fsmenu, category); fsm_iter && idx; fsm_iter = fsm_iter->next) { idx--; + } - return fsme ? fsme->path : NULL; + return fsm_iter ? fsm_iter->path : NULL; } short fsmenu_can_save(struct FSMenu *fsmenu, FSMenuCategory category, int idx) { - FSMenuEntry *fsme; + FSMenuEntry *fsm_iter; - for (fsme = fsmenu_get_category(fsmenu, category); fsme && idx; fsme = fsme->next) + for (fsm_iter = fsmenu_get_category(fsmenu, category); fsm_iter && idx; fsm_iter = fsm_iter->next) { idx--; + } - return fsme ? fsme->save : 0; + return fsm_iter ? fsm_iter->save : 0; } -void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const char *path, int sorted, short save) +void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const char *path, FSMenuInsert flag) { - FSMenuEntry *prev; - FSMenuEntry *fsme; - FSMenuEntry *fsms; + FSMenuEntry *fsm_prev; + FSMenuEntry *fsm_iter; + FSMenuEntry *fsm_head; - fsms = fsmenu_get_category(fsmenu, category); - prev = fsme = fsms; + fsm_head = fsmenu_get_category(fsmenu, category); + fsm_prev = fsm_head; /* this is odd and not really correct? */ - for (; fsme; prev = fsme, fsme = fsme->next) { - if (fsme->path) { - const int cmp_ret = BLI_path_cmp(path, fsme->path); + for (fsm_iter = fsm_head; fsm_iter; fsm_prev = fsm_iter, fsm_iter = fsm_iter->next) { + if (fsm_iter->path) { + const int cmp_ret = BLI_path_cmp(path, fsm_iter->path); if (cmp_ret == 0) { + if (flag & FS_INSERT_FIRST) { + if (fsm_iter != fsm_head) { + fsm_prev->next = fsm_iter->next; + fsm_iter->next = fsm_head; + fsmenu_set_category(fsmenu, category, fsm_iter); + } + } return; } - else if (sorted && cmp_ret < 0) { + else if ((flag & FS_INSERT_SORTED) && cmp_ret < 0) { break; } } @@ -182,78 +198,82 @@ void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const c /* if we're bookmarking this, file should come * before the last separator, only automatically added * current dir go after the last sep. */ - if (save) { + if (flag & FS_INSERT_SAVE) { break; } } } - fsme = MEM_mallocN(sizeof(*fsme), "fsme"); - fsme->path = BLI_strdup(path); - fsme->save = save; + fsm_iter = MEM_mallocN(sizeof(*fsm_iter), "fsme"); + fsm_iter->path = BLI_strdup(path); + fsm_iter->save = (flag & FS_INSERT_SAVE) != 0; - if (prev) { - fsme->next = prev->next; - prev->next = fsme; + if (fsm_prev) { + if (flag & FS_INSERT_FIRST) { + fsm_iter->next = fsm_head; + fsmenu_set_category(fsmenu, category, fsm_iter); + } + else { + fsm_iter->next = fsm_prev->next; + fsm_prev->next = fsm_iter; + } } else { - fsme->next = fsms; - fsmenu_set_category(fsmenu, category, fsme); + fsm_iter->next = fsm_head; + fsmenu_set_category(fsmenu, category, fsm_iter); } } void fsmenu_remove_entry(struct FSMenu *fsmenu, FSMenuCategory category, int idx) { - FSMenuEntry *prev = NULL, *fsme = NULL; - FSMenuEntry *fsms = fsmenu_get_category(fsmenu, category); + FSMenuEntry *fsm_prev = NULL; + FSMenuEntry *fsm_iter; + FSMenuEntry *fsm_head; - for (fsme = fsms; fsme && idx; prev = fsme, fsme = fsme->next) + fsm_head = fsmenu_get_category(fsmenu, category); + + for (fsm_iter = fsm_head; fsm_iter && idx; fsm_prev = fsm_iter, fsm_iter = fsm_iter->next) idx--; - if (fsme) { + if (fsm_iter) { /* you should only be able to remove entries that were * not added by default, like windows drives. * also separators (where path == NULL) shouldn't be removed */ - if (fsme->save && fsme->path) { + if (fsm_iter->save && fsm_iter->path) { /* remove fsme from list */ - if (prev) { - prev->next = fsme->next; + if (fsm_prev) { + fsm_prev->next = fsm_iter->next; } else { - fsms = fsme->next; - fsmenu_set_category(fsmenu, category, fsms); + fsm_head = fsm_iter->next; + fsmenu_set_category(fsmenu, category, fsm_head); } /* free entry */ - MEM_freeN(fsme->path); - MEM_freeN(fsme); + MEM_freeN(fsm_iter->path); + MEM_freeN(fsm_iter); } } } void fsmenu_write_file(struct FSMenu *fsmenu, const char *filename) { - FSMenuEntry *fsme = NULL; - int nskip = 0; + FSMenuEntry *fsm_iter = NULL; + int nwritten = 0; FILE *fp = BLI_fopen(filename, "w"); if (!fp) return; fprintf(fp, "[Bookmarks]\n"); - for (fsme = fsmenu_get_category(fsmenu, FS_CATEGORY_BOOKMARKS); fsme; fsme = fsme->next) { - if (fsme->path && fsme->save) { - fprintf(fp, "%s\n", fsme->path); + for (fsm_iter = fsmenu_get_category(fsmenu, FS_CATEGORY_BOOKMARKS); fsm_iter; fsm_iter = fsm_iter->next) { + if (fsm_iter->path && fsm_iter->save) { + fprintf(fp, "%s\n", fsm_iter->path); } } fprintf(fp, "[Recent]\n"); - nskip = fsmenu_get_nentries(fsmenu, FS_CATEGORY_RECENT) - FSMENU_RECENT_MAX; - /* skip first entries if list too long */ - for (fsme = fsmenu_get_category(fsmenu, FS_CATEGORY_RECENT); fsme && (nskip > 0); fsme = fsme->next, --nskip) { - /* pass */ - } - for (; fsme; fsme = fsme->next) { - if (fsme->path && fsme->save) { - fprintf(fp, "%s\n", fsme->path); + for (fsm_iter = fsmenu_get_category(fsmenu, FS_CATEGORY_RECENT); fsm_iter && (nwritten < FSMENU_RECENT_MAX); fsm_iter = fsm_iter->next, ++nwritten) { + if (fsm_iter->path && fsm_iter->save) { + fprintf(fp, "%s\n", fsm_iter->path); } } fclose(fp); @@ -288,7 +308,7 @@ void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filename) if (BLI_exists(line)) #endif { - fsmenu_insert_entry(fsmenu, category, line, 0, 1); + fsmenu_insert_entry(fsmenu, category, line, FS_INSERT_SAVE); } } } @@ -315,16 +335,16 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) tmps[2] = '\\'; tmps[3] = 0; - fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, tmps, 1, 0); + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, tmps, FS_INSERT_SORTED); } } /* Adding Desktop and My Documents */ if (read_bookmarks) { SHGetSpecialFolderPath(0, line, CSIDL_PERSONAL, 0); - fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0); + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); SHGetSpecialFolderPath(0, line, CSIDL_DESKTOPDIRECTORY, 0); - fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0); + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); } } #else @@ -347,7 +367,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) FSRefMakePath(&dir, path, FILE_MAX); if (strcmp((char *)path, "/home") && strcmp((char *)path, "/net")) { /* /net and /home are meaningless on OSX, home folders are stored in /Users */ - fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, (char *)path, 1, 0); + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, (char *)path, FS_INSERT_SORTED); } } @@ -357,26 +377,26 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) home = getenv("HOME"); if (read_bookmarks && home) { BLI_snprintf(line, 256, "%s/", home); - fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0); + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); BLI_snprintf(line, 256, "%s/Desktop/", home); if (BLI_exists(line)) { - fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0); + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); } BLI_snprintf(line, 256, "%s/Documents/", home); if (BLI_exists(line)) { - fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0); + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); } BLI_snprintf(line, 256, "%s/Pictures/", home); if (BLI_exists(line)) { - fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0); + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); } BLI_snprintf(line, 256, "%s/Music/", home); if (BLI_exists(line)) { - fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0); + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); } BLI_snprintf(line, 256, "%s/Movies/", home); if (BLI_exists(line)) { - fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0); + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); } } #else @@ -409,7 +429,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) if (!CFStringGetCString(pathString, line, 256, kCFStringEncodingASCII)) continue; - fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, line, 1, 0); + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, line, FS_INSERT_SORTED); CFRelease(pathString); CFRelease(cfURL); @@ -436,7 +456,10 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) FSRefMakePath(&dir, path, FILE_MAX); - fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, (char *)path, 1, 0); + if (strcmp((char *)path, "/home") && strcmp((char *)path, "/net")) { + /* /net and /home are meaningless on OSX, home folders are stored in /Users */ + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, (char *)path, FS_INSERT_SORTED); + } } /* Finally get user favorite places */ @@ -459,7 +482,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) if (!CFStringGetCString(pathString, line, 256, kCFStringEncodingASCII)) continue; - fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0); + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); CFRelease(pathString); CFRelease(cfURL); @@ -477,10 +500,10 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) if (read_bookmarks && home) { BLI_snprintf(line, FILE_MAXDIR, "%s/", home); - fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0); + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); BLI_snprintf(line, FILE_MAXDIR, "%s/Desktop/", home); if (BLI_exists(line)) { - fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, line, 1, 0); + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); } } @@ -505,10 +528,11 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) len = strlen(mnt->mnt_dir); if (len && mnt->mnt_dir[len - 1] != '/') { BLI_snprintf(line, FILE_MAXDIR, "%s/", mnt->mnt_dir); - fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, line, 1, 0); + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, line, FS_INSERT_SORTED); + } + else { + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, mnt->mnt_dir, FS_INSERT_SORTED); } - else - fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, mnt->mnt_dir, 1, 0); found = 1; } @@ -520,7 +544,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) /* fallback */ if (!found) - fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, "/", 1, 0); + fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, "/", FS_INSERT_SORTED); } } #endif @@ -530,15 +554,17 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) static void fsmenu_free_category(struct FSMenu *fsmenu, FSMenuCategory category) { - FSMenuEntry *fsme = fsmenu_get_category(fsmenu, category); + FSMenuEntry *fsm_iter = fsmenu_get_category(fsmenu, category); - while (fsme) { - FSMenuEntry *n = fsme->next; + while (fsm_iter) { + FSMenuEntry *fsm_next = fsm_iter->next; - if (fsme->path) MEM_freeN(fsme->path); - MEM_freeN(fsme); + if (fsm_iter->path) { + MEM_freeN(fsm_iter->path); + } + MEM_freeN(fsm_iter); - fsme = n; + fsm_iter = fsm_next; } } @@ -547,13 +573,17 @@ void fsmenu_refresh_system_category(struct FSMenu *fsmenu) fsmenu_free_category(fsmenu, FS_CATEGORY_SYSTEM); fsmenu_set_category(fsmenu, FS_CATEGORY_SYSTEM, NULL); + fsmenu_free_category(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS); + fsmenu_set_category(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, NULL); + /* Add all entries to system category */ - fsmenu_read_system(fsmenu, FALSE); + fsmenu_read_system(fsmenu, TRUE); } void fsmenu_free(struct FSMenu *fsmenu) { fsmenu_free_category(fsmenu, FS_CATEGORY_SYSTEM); + fsmenu_free_category(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS); fsmenu_free_category(fsmenu, FS_CATEGORY_BOOKMARKS); fsmenu_free_category(fsmenu, FS_CATEGORY_RECENT); MEM_freeN(fsmenu); diff --git a/source/blender/editors/space_file/fsmenu.h b/source/blender/editors/space_file/fsmenu.h index d7576d71933..1b69eb09fce 100644 --- a/source/blender/editors/space_file/fsmenu.h +++ b/source/blender/editors/space_file/fsmenu.h @@ -39,10 +39,17 @@ typedef enum FSMenuCategory { FS_CATEGORY_SYSTEM, + FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS, FS_CATEGORY_RECENT } FSMenuCategory; +typedef enum FSMenuInsert { + FS_INSERT_SORTED = (1 << 0), + FS_INSERT_SAVE = (1 << 1), + FS_INSERT_FIRST = (1 << 2) /* moves the item to the front of the list when its not already there */ +} FSMenuInsert; + struct FSMenu; struct FSMenu *fsmenu_get(void); @@ -59,7 +66,7 @@ char *fsmenu_get_entry(struct FSMenu *fsmenu, FSMenuCategory category, int index * Duplicate entries are not added. * \param sorted Should entry be inserted in sorted order? */ -void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const char *path, int sorted, short save); +void fsmenu_insert_entry(struct FSMenu *fsmenu, FSMenuCategory category, const char *path, const FSMenuInsert flag); /** Return whether the entry was created by the user and can be saved and deleted */ short fsmenu_can_save(struct FSMenu *fsmenu, FSMenuCategory category, int index); diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 4b568b43695..be037a0d5ba 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -198,7 +198,7 @@ static void file_refresh(const bContext *C, ScrArea *UNUSED(sa)) params->active_file = -1; // added this so it opens nicer (ton) } filelist_hidedot(sfile->files, params->flag & FILE_HIDE_DOT); - filelist_setfilter(sfile->files, params->flag & FILE_FILTER ? params->filter : 0); + filelist_setfilter(sfile->files, params->flag & FILE_FILTER ? params->filter : 0); filelist_setfilter_types(sfile->files, params->filter_glob); if (filelist_empty(sfile->files)) { @@ -252,7 +252,7 @@ static void file_refresh(const bContext *C, ScrArea *UNUSED(sa)) static void file_listener(ScrArea *sa, wmNotifier *wmn) { - /* SpaceFile *sfile = (SpaceFile*)sa->spacedata.first; */ + /* SpaceFile *sfile = (SpaceFile *)sa->spacedata.first; */ /* context changes */ switch (wmn->category) { @@ -386,6 +386,7 @@ static void file_operatortypes(void) WM_operatortype_append(FILE_OT_bookmark_toggle); WM_operatortype_append(FILE_OT_bookmark_add); WM_operatortype_append(FILE_OT_delete_bookmark); + WM_operatortype_append(FILE_OT_reset_recent); WM_operatortype_append(FILE_OT_hidedot); WM_operatortype_append(FILE_OT_filenum); WM_operatortype_append(FILE_OT_directory_new); @@ -480,7 +481,7 @@ static void file_channel_area_init(wmWindowManager *wm, ARegion *ar) ED_region_panels_init(wm, ar); /* own keymaps */ - keymap = WM_keymap_find(wm->defaultconf, "File Browser", SPACE_FILE, 0); + keymap = WM_keymap_find(wm->defaultconf, "File Browser", SPACE_FILE, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } @@ -504,7 +505,7 @@ static void file_header_area_init(wmWindowManager *wm, ARegion *ar) ED_region_header_init(ar); - keymap = WM_keymap_find(wm->defaultconf, "File Browser", SPACE_FILE, 0); + keymap = WM_keymap_find(wm->defaultconf, "File Browser", SPACE_FILE, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } @@ -537,7 +538,7 @@ static void file_ui_area_draw(const bContext *C, ARegion *ar) glClear(GL_COLOR_BUFFER_BIT); /* scrolling here is just annoying, disable it */ - ar->v2d.cur.ymax = BLI_RCT_SIZE_Y(&ar->v2d.cur); + ar->v2d.cur.ymax = BLI_rctf_size_y(&ar->v2d.cur); ar->v2d.cur.ymin = 0; /* set view2d view matrix for scrolling (without scrollers) */ @@ -597,7 +598,7 @@ void ED_spacetype_file(void) art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER; art->init = file_header_area_init; art->draw = file_header_area_draw; - // art->listener= file_header_area_listener; + // art->listener = file_header_area_listener; BLI_addhead(&st->regiontypes, art); /* regions: ui */ diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index efe62eaf495..8bb57a32090 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -69,12 +69,6 @@ #include "graph_intern.h" // own include -/* XXX */ - -/* temporary definition for limits of float number buttons (FLT_MAX tends to infinity with old system) */ -#define UI_FLT_MAX 10000.0f - - /* ******************* graph editor space & buttons ************** */ #define B_REDR 1 @@ -83,7 +77,7 @@ static void do_graph_region_buttons(bContext *UNUSED(C), void *UNUSED(arg), int event) { - //Scene *scene= CTX_data_scene(C); + //Scene *scene = CTX_data_scene(C); switch (event) { @@ -154,6 +148,7 @@ static void graph_panel_view(const bContext *C, Panel *pa) row = uiLayoutSplit(sub, 0.7f, TRUE); uiItemR(row, &sceneptr, "frame_current", 0, IFACE_("Cursor X"), ICON_NONE); uiItemEnumO(row, "GRAPH_OT_snap", IFACE_("To Keys"), 0, "type", GRAPHKEYS_SNAP_CFRA); + row = uiLayoutSplit(sub, 0.7f, TRUE); uiItemR(row, &spaceptr, "cursor_position_y", 0, IFACE_("Cursor Y"), ICON_NONE); uiItemEnumO(row, "GRAPH_OT_snap", IFACE_("To Keys"), 0, "type", GRAPHKEYS_SNAP_VALUE); @@ -304,7 +299,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *pa) if (RNA_path_resolve(&id_ptr, fcu->rna_path, &fcu_prop_ptr, &fcu_prop) && fcu_prop) { /* determine the unit for this property */ unit = RNA_SUBTYPE_UNIT(RNA_property_subtype(fcu_prop)); - } + } /* interpolation */ col = uiLayoutColumn(layout, FALSE); @@ -314,44 +309,43 @@ static void graph_panel_key_properties(const bContext *C, Panel *pa) * - we use the button-versions of the calls so that we can attach special update handlers * and unit conversion magic that cannot be achieved using a purely RNA-approach */ - // XXX: col = uiLayoutColumn(layout, TRUE); /* keyframe itself */ { uiItemL(col, IFACE_("Key:"), ICON_NONE); - + but = uiDefButR(block, NUM, B_REDR, IFACE_("Frame"), 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "co", 0, 0, 0, -1, -1, NULL); uiButSetFunc(but, graphedit_activekey_update_cb, fcu, bezt); - + but = uiDefButR(block, NUM, B_REDR, IFACE_("Value"), 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "co", 1, 0, 0, -1, -1, NULL); uiButSetFunc(but, graphedit_activekey_update_cb, fcu, bezt); uiButSetUnitType(but, unit); } - + /* previous handle - only if previous was Bezier interpolation */ if ((prevbezt) && (prevbezt->ipo == BEZT_IPO_BEZ)) { uiItemL(col, IFACE_("Left Handle:"), ICON_NONE); - + but = uiDefButR(block, NUM, B_REDR, "X", 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "handle_left", 0, 0, 0, -1, -1, NULL); uiButSetFunc(but, graphedit_activekey_handles_cb, fcu, bezt); - + but = uiDefButR(block, NUM, B_REDR, "Y", 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "handle_left", 1, 0, 0, -1, -1, NULL); uiButSetFunc(but, graphedit_activekey_handles_cb, fcu, bezt); uiButSetUnitType(but, unit); } - + /* next handle - only if current is Bezier interpolation */ if (bezt->ipo == BEZT_IPO_BEZ) { uiItemL(col, IFACE_("Right Handle:"), ICON_NONE); - + but = uiDefButR(block, NUM, B_REDR, "X", 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "handle_right", 0, 0, 0, -1, -1, NULL); uiButSetFunc(but, graphedit_activekey_handles_cb, fcu, bezt); - + but = uiDefButR(block, NUM, B_REDR, "Y", 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "handle_right", 1, 0, 0, -1, -1, NULL); uiButSetFunc(but, graphedit_activekey_handles_cb, fcu, bezt); @@ -413,7 +407,7 @@ static void driver_remove_cb(bContext *C, void *ale_v, void *UNUSED(arg)) if (ELEM(NULL, id, fcu)) return; - /* call API method to remove this driver */ + /* call API method to remove this driver */ ANIM_remove_driver(reports, id, fcu->rna_path, fcu->array_index, 0); } @@ -443,7 +437,7 @@ static void driver_update_flags_cb(bContext *UNUSED(C), void *fcu_v, void *UNUSE ChannelDriver *driver = fcu->driver; /* clear invalid flags */ - fcu->flag &= ~FCURVE_DISABLED; // XXX? + fcu->flag &= ~FCURVE_DISABLED; driver->flag &= ~DRIVER_FLAG_INVALID; } @@ -473,7 +467,6 @@ static void graph_panel_driverVar__singleProp(uiLayout *layout, ID *id, DriverVa uiTemplateAnyID(row, &dtar_ptr, "id", "id_type", IFACE_("Prop:")); /* Target Property */ - // TODO: make this less technical... if (dtar->id) { PointerRNA root_ptr; @@ -636,12 +629,12 @@ static void graph_panel_drivers(const bContext *C, Panel *pa) /* errors? */ if (driver->flag & DRIVER_FLAG_INVALID) - uiItemL(col, IFACE_("ERROR: invalid Python expression"), ICON_ERROR); + uiItemL(col, IFACE_("ERROR: Invalid Python expression"), ICON_ERROR); } else { /* errors? */ if (driver->flag & DRIVER_FLAG_INVALID) - uiItemL(col, IFACE_("ERROR: invalid target channel(s)"), ICON_ERROR); + uiItemL(col, IFACE_("ERROR: Invalid target channel(s)"), ICON_ERROR); } col = uiLayoutColumn(pa->layout, TRUE); @@ -712,15 +705,15 @@ static void graph_panel_drivers(const bContext *C, Panel *pa) graph_panel_driverVar__transChan(box, ale->id, dvar); break; } - + /* value of variable */ if (driver->flag & DRIVER_FLAG_SHOWDEBUG) { char valBuf[32]; - + box = uiLayoutBox(col); row = uiLayoutRow(box, TRUE); uiItemL(row, IFACE_("Value:"), ICON_NONE); - + BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", dvar->curval); uiItemL(row, valBuf, ICON_NONE); } @@ -730,8 +723,8 @@ static void graph_panel_drivers(const bContext *C, Panel *pa) MEM_freeN(ale); } -/* ******************* f-modifiers ******************************** */ -/* all the drawing code is in editors/animation/fmodifier_ui.c */ +/* ******************* F-Modifiers ******************************** */ +/* All the drawing code is in editors/animation/fmodifier_ui.c */ #define B_FMODIFIER_REDRAW 20 @@ -763,7 +756,9 @@ static void graph_panel_modifiers(const bContext *C, Panel *pa) row = uiLayoutRow(pa->layout, FALSE); block = uiLayoutGetBlock(row); - // XXX for now, this will be a operator button which calls a 'add modifier' operator + /* this is an operator button which calls a 'add modifier' operator... + * a menu might be nicer but would be tricky as we need some custom filtering + */ uiDefButO(block, BUT, "GRAPH_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, IFACE_("Add Modifier"), 10, 0, 150, 20, TIP_("Adds a new F-Curve Modifier for the active F-Curve")); diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index e4bda15bc7d..f665b979559 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -83,12 +83,12 @@ static float fcurve_display_alpha(FCurve *fcu) /* Envelope -------------- */ -// TODO: draw a shaded poly showing the region of influence too!!! +/* TODO: draw a shaded poly showing the region of influence too!!! */ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d) { FMod_Envelope *env = (FMod_Envelope *)fcm->data; FCM_EnvelopeData *fed; - const float fac = 0.05f * BLI_RCT_SIZE_X(&v2d->cur); + const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur); int i; /* draw two black lines showing the standard reference levels */ @@ -101,13 +101,13 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d) glVertex2f(v2d->cur.xmin, env->midval + env->max); glVertex2f(v2d->cur.xmax, env->midval + env->max); - glEnd(); // GL_LINES + glEnd(); /* GL_LINES */ setlinestyle(0); /* set size of vertices (non-adjustable for now) */ glPointSize(2.0f); - // for now, point color is fixed, and is white + /* for now, point color is fixed, and is white */ glColor3f(1.0f, 1.0f, 1.0f); /* we use bgl points not standard gl points, to workaround vertex @@ -123,7 +123,7 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d) glVertex2f(fed->time, fed->max); } } - bglEnd(); // GL_POINTS + bglEnd(); /* GL_POINTS */ glPointSize(1.0f); } @@ -137,7 +137,7 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d) static void draw_fcurve_vertices_keyframes(FCurve *fcu, SpaceIpo *UNUSED(sipo), View2D *v2d, short edit, short sel) { BezTriple *bezt = fcu->bezt; - const float fac = 0.05f * BLI_RCT_SIZE_X(&v2d->cur); + const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur); int i; /* we use bgl points not standard gl points, to workaround vertex @@ -160,13 +160,13 @@ static void draw_fcurve_vertices_keyframes(FCurve *fcu, SpaceIpo *UNUSED(sipo), } else { /* no check for selection here, as curve is not editable... */ - // XXX perhaps we don't want to even draw points? maybe add an option for that later + /* XXX perhaps we don't want to even draw points? maybe add an option for that later */ bglVertex3fv(bezt->vec[1]); } } } - bglEnd(); // GL_POINTS + bglEnd(); /* GL_POINTS */ } @@ -262,7 +262,7 @@ static void set_fcurve_vertex_color(FCurve *fcu, short sel) /* Curve's points ARE BEING edited */ if (sel) UI_ThemeColorShadeAlpha(TH_VERTEX_SELECT, 0, alphaOffset); else UI_ThemeColorShadeAlpha(TH_VERTEX, 0, alphaOffset); - } + } else { /* Curve's points CANNOT BE edited */ if (sel) UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, alphaOffset); @@ -318,7 +318,7 @@ static int draw_fcurve_handles_check(SpaceIpo *sipo, FCurve *fcu) ) { return 0; - } + } else { return 1; } @@ -404,7 +404,7 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu) } } - glEnd(); // GL_LINES + glEnd(); /* GL_LINES */ } /* Samples ---------------- */ @@ -428,7 +428,7 @@ static void draw_fcurve_sample_control(float x, float y, float xscale, float ysc glVertex2f(-0.7f, +0.7f); glVertex2f(+0.7f, -0.7f); - glEnd(); // GL_LINES + glEnd(); /* GL_LINES */ glEndList(); } @@ -515,7 +515,7 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d * chosen here is just the coarsest value which still looks reasonable... */ /* grid->dx represents the number of 'frames' between gridlines, but we divide by U.v2d_min_gridsize to get pixels-steps */ - // TODO: perhaps we should have 1.0 frames as upper limit so that curves don't get too distorted? + /* TODO: perhaps we should have 1.0 frames as upper limit so that curves don't get too distorted? */ samplefreq = dx / U.v2d_min_gridsize; if (samplefreq < 0.00001f) samplefreq = 0.00001f; @@ -561,7 +561,7 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert == 1)) { /* just extend across the first keyframe's value */ v[1] = prevfpt->vec[1]; - } + } else { /* extrapolate linear dosnt use the handle, use the next points center instead */ fac = (prevfpt->vec[0] - fpt->vec[0]) / (prevfpt->vec[0] - v[0]); @@ -599,7 +599,7 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert == 1)) { /* based on last keyframe's value */ v[1] = prevfpt->vec[1]; - } + } else { /* extrapolate linear dosnt use the handle, use the previous points center instead */ fpt = prevfpt - 1; @@ -642,13 +642,13 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (prevbezt->ipo == BEZT_IPO_CONST) || (fcu->totvert == 1)) { /* just extend across the first keyframe's value */ v1[1] = prevbezt->vec[1][1]; - } + } else if (prevbezt->ipo == BEZT_IPO_LIN) { /* extrapolate linear dosnt use the handle, use the next points center instead */ fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]); if (fac) fac = 1.0f / fac; v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]); - } + } else { /* based on angle of handle 1 (relative to keyframe) */ fac = (prevbezt->vec[0][0] - prevbezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]); @@ -667,7 +667,7 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 } /* draw curve between first and last keyframe (if there are enough to do so) */ - // TODO: optimize this to not have to calc stuff out of view too? + /* TODO: optimize this to not have to calc stuff out of view too? */ while (b--) { if (prevbezt->ipo == BEZT_IPO_CONST) { /* Constant-Interpolation: draw segment between previous keyframe and next, but holding same value */ @@ -691,7 +691,7 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 */ /* resol depends on distance between points (not just horizontal) OR is a fixed high res */ - // TODO: view scale should factor into this someday too... + /* TODO: view scale should factor into this someday too... */ if (fcu->driver) resol = 32; else @@ -705,7 +705,7 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 } else { /* clamp resolution to max of 32 */ - // NOTE: higher values will crash + /* NOTE: higher values will crash */ if (resol > 32) resol = 32; v1[0] = prevbezt->vec[1][0]; @@ -748,14 +748,14 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2 if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (prevbezt->ipo == BEZT_IPO_CONST) || (fcu->totvert == 1)) { /* based on last keyframe's value */ v1[1] = prevbezt->vec[1][1]; - } + } else if (prevbezt->ipo == BEZT_IPO_LIN) { /* extrapolate linear dosnt use the handle, use the previous points center instead */ bezt = prevbezt - 1; fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]); if (fac) fac = 1.0f / fac; v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]); - } + } else { /* based on angle of handle 1 (relative to keyframe) */ fac = (prevbezt->vec[2][0] - prevbezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]); @@ -852,7 +852,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid } if (((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) || (fcu->flag & FCURVE_MUTED)) { /* muted curves are drawn in a grayish hue */ - // XXX should we have some variations? + /* XXX should we have some variations? */ UI_ThemeColorShade(TH_HEADER, 50); } else { @@ -971,7 +971,7 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar) height = (float)((items * ACHANNEL_STEP) + (ACHANNEL_HEIGHT * 2)); UI_view2d_totRect_set(v2d, ar->winx, height); - /* loop through channels, and set up drawing depending on their type */ + /* loop through channels, and set up drawing depending on their type */ { /* first pass: just the standard GL-drawing for backdrop + text */ y = (float)ACHANNEL_FIRST; diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index f01d64b46b8..453549ebf79 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -229,11 +229,11 @@ static int graphkeys_viewall(bContext *C, const short do_sel_only, const short i &cur_new.ymin, &cur_new.ymax, do_sel_only, include_handles); - extra = 0.1f * BLI_RCT_SIZE_X(&cur_new); + extra = 0.1f * BLI_rctf_size_x(&cur_new); cur_new.xmin -= extra; cur_new.xmax += extra; - extra = 0.1f * BLI_RCT_SIZE_Y(&cur_new); + extra = 0.1f * BLI_rctf_size_y(&cur_new); cur_new.ymin -= extra; cur_new.ymax += extra; @@ -332,7 +332,7 @@ static void create_ghost_curves(bAnimContext *ac, int start, int end) ChannelDriver *driver = fcu->driver; FPoint *fpt; float unitFac; - int cfra; + int cfra; /* disable driver so that it don't muck up the sampling process */ fcu->driver = NULL; @@ -724,7 +724,7 @@ static int graphkeys_copy_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; /* copy keyframes */ - if (copy_graph_keys(&ac)) { + if (copy_graph_keys(&ac)) { BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer"); return OPERATOR_CANCELLED; } @@ -1143,9 +1143,9 @@ static int graphkeys_sound_bake_exec(bContext *C, wmOperator *op) RNA_float_get(op->ptr, "attack"), RNA_float_get(op->ptr, "release"), RNA_float_get(op->ptr, "threshold"), - RNA_boolean_get(op->ptr, "accumulate"), + RNA_boolean_get(op->ptr, "use_accumulate"), RNA_boolean_get(op->ptr, "use_additive"), - RNA_boolean_get(op->ptr, "square"), + RNA_boolean_get(op->ptr, "use_square"), RNA_float_get(op->ptr, "sthreshold"), FPS, &sbi.length); @@ -1225,15 +1225,27 @@ void GRAPH_OT_sound_bake(wmOperatorType *ot) /* properties */ WM_operator_properties_filesel(ot, FOLDERFILE | SOUNDFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY); - RNA_def_float(ot->srna, "low", 0.0f, 0.0, 100000.0, "Lowest frequency", "", 0.1, 1000.00); - RNA_def_float(ot->srna, "high", 100000.0, 0.0, 100000.0, "Highest frequency", "", 0.1, 1000.00); - RNA_def_float(ot->srna, "attack", 0.005, 0.0, 2.0, "Attack time", "", 0.01, 0.1); - RNA_def_float(ot->srna, "release", 0.2, 0.0, 5.0, "Release time", "", 0.01, 0.2); - RNA_def_float(ot->srna, "threshold", 0.0, 0.0, 1.0, "Threshold", "", 0.01, 0.1); - RNA_def_boolean(ot->srna, "accumulate", 0, "Accumulate", ""); - RNA_def_boolean(ot->srna, "use_additive", 0, "Additive", ""); - RNA_def_boolean(ot->srna, "square", 0, "Square", ""); - RNA_def_float(ot->srna, "sthreshold", 0.1, 0.0, 1.0, "Square Threshold", "", 0.01, 0.1); + RNA_def_float(ot->srna, "low", 0.0f, 0.0, 100000.0, "Lowest frequency", + "Cutoff frequency of a high-pass filter that is applied to the audio data", 0.1, 1000.00); + RNA_def_float(ot->srna, "high", 100000.0, 0.0, 100000.0, "Highest frequency", + "Cutoff frequency of a low-pass filter that is applied to the audio data", 0.1, 1000.00); + RNA_def_float(ot->srna, "attack", 0.005, 0.0, 2.0, "Attack time", + "Value for the hull curve calculation that tells how fast the hull curve can rise " + "(the lower the value the steeper it can rise)", 0.01, 0.1); + RNA_def_float(ot->srna, "release", 0.2, 0.0, 5.0, "Release time", + "Value for the hull curve calculation that tells how fast the hull curve can fall " + "(the lower the value the steeper it can fall)", 0.01, 0.2); + RNA_def_float(ot->srna, "threshold", 0.0, 0.0, 1.0, "Threshold", + "Minimum amplitude value needed to influence the hull curve", 0.01, 0.1); + RNA_def_boolean(ot->srna, "use_accumulate", 0, "Accumulate", + "Only the positive differences of the hull curve amplitudes are summarized to produce the output"); + RNA_def_boolean(ot->srna, "use_additive", 0, "Additive", + "The amplitudes of the hull curve are summarized (or, when Accumulate is enabled, " + "both positive and negative differences are accumulated)"); + RNA_def_boolean(ot->srna, "use_square", 0, "Square", + "The output is a square curve (negative values always result in -1, and positive ones in 1)"); + RNA_def_float(ot->srna, "sthreshold", 0.1, 0.0, 1.0, "Square Threshold", + "Square only: all values with an absolute amplitude lower than that result in 0", 0.01, 0.1); } /* ******************** Sample Keyframes Operator *********************** */ @@ -1309,8 +1321,8 @@ void GRAPH_OT_sample(wmOperatorType *ot) /* defines for set extrapolation-type for selected keyframes tool */ static EnumPropertyItem prop_graphkeys_expo_types[] = { - {FCURVE_EXTRAPOLATE_CONSTANT, "CONSTANT", 0, "Constant Extrapolation", ""}, - {FCURVE_EXTRAPOLATE_LINEAR, "LINEAR", 0, "Linear Extrapolation", ""}, + {FCURVE_EXTRAPOLATE_CONSTANT, "CONSTANT", 0, "Constant Extrapolation", "Values on endpoint keyframes are held"}, + {FCURVE_EXTRAPOLATE_LINEAR, "LINEAR", 0, "Linear Extrapolation", "Straight-line slope of end segments are extended past the endpoint keyframes"}, {MAKE_CYCLIC_EXPO, "MAKE_CYCLIC", 0, "Make Cyclic (F-Modifier)", "Add Cycles F-Modifier if one doesn't exist already"}, {CLEAR_CYCLIC_EXPO, "CLEAR_CYCLIC", 0, "Clear Cyclic (F-Modifier)", "Remove Cycles F-Modifier if not needed anymore"}, @@ -1614,7 +1626,7 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op) else if (ELEM3(fcu->array_index, 0, 1, 2) == 0) { BKE_reportf(op->reports, RPT_WARNING, "Euler Rotation F-Curve has invalid index (ID='%s', Path='%s', Index=%d)", - (ale->id) ? ale->id->name : "", fcu->rna_path, fcu->array_index); + (ale->id) ? ale->id->name : TIP_(""), fcu->rna_path, fcu->array_index); continue; } @@ -1711,13 +1723,16 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op) /* updates + finishing warnings */ if (failed == groups) { BKE_report(op->reports, RPT_ERROR, - "No Euler Rotations could be corrected, ensure each rotation has keys for all components, and that F-Curves for these are in consecutive XYZ order and selected"); + "No Euler Rotations could be corrected, ensure each rotation has keys for all components, " + "and that F-Curves for these are in consecutive XYZ order and selected"); return OPERATOR_CANCELLED; } else { if (failed) { BKE_report(op->reports, RPT_ERROR, - "Some Euler Rotations couldn't be corrected due to missing/unselected/out-of-order F-Curves, ensure each rotation has keys for all components, and that F-Curves for these are in consecutive XYZ order and selected"); + "Some Euler Rotations could not be corrected due to missing/unselected/out-of-order F-Curves, " + "ensure each rotation has keys for all components, and that F-Curves for these are in " + "consecutive XYZ order and selected"); } /* validate keyframes after editing */ @@ -1808,9 +1823,9 @@ static int graphkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op)) void GRAPH_OT_frame_jump(wmOperatorType *ot) { /* identifiers */ - ot->name = "Jump to Frame"; + ot->name = "Jump to Keyframes"; ot->idname = "GRAPH_OT_frame_jump"; - ot->description = "Set the current frame to the average frame of the selected keyframes"; + ot->description = "Place the cursor on the midpoint of selected keyframes"; /* api callbacks */ ot->exec = graphkeys_framejump_exec; @@ -1824,12 +1839,18 @@ void GRAPH_OT_frame_jump(wmOperatorType *ot) /* defines for snap keyframes tool */ static EnumPropertyItem prop_graphkeys_snap_types[] = { - {GRAPHKEYS_SNAP_CFRA, "CFRA", 0, "Current Frame", ""}, - {GRAPHKEYS_SNAP_VALUE, "VALUE", 0, "Cursor Value", ""}, - {GRAPHKEYS_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame", ""}, // XXX as single entry? - {GRAPHKEYS_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Nearest Second", ""}, // XXX as single entry? - {GRAPHKEYS_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker", ""}, - {GRAPHKEYS_SNAP_HORIZONTAL, "HORIZONTAL", 0, "Flatten Handles", ""}, + {GRAPHKEYS_SNAP_CFRA, "CFRA", 0, "Current Frame", + "Snap selected keyframes to the current frame"}, + {GRAPHKEYS_SNAP_VALUE, "VALUE", 0, "Cursor Value", + "Set values of selected keyframes to the cursor value (Y/Horizontal component)"}, + {GRAPHKEYS_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame", + "Snap selected keyframes to the nearest (whole) frame (use to fix accidental sub-frame offsets)"}, + {GRAPHKEYS_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Nearest Second", + "Snap selected keyframes to the nearest second"}, + {GRAPHKEYS_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker", + "Snap selected keyframes to the nearest marker"}, + {GRAPHKEYS_SNAP_HORIZONTAL, "HORIZONTAL", 0, "Flatten Handles", + "Flatten handles for a smoother transition"}, {0, NULL, 0, NULL, NULL} }; @@ -1932,11 +1953,16 @@ void GRAPH_OT_snap(wmOperatorType *ot) /* defines for mirror keyframes tool */ static EnumPropertyItem prop_graphkeys_mirror_types[] = { - {GRAPHKEYS_MIRROR_CFRA, "CFRA", 0, "By Times over Current Frame", ""}, - {GRAPHKEYS_MIRROR_VALUE, "VALUE", 0, "By Values over Cursor Value", ""}, - {GRAPHKEYS_MIRROR_YAXIS, "YAXIS", 0, "By Times over Time=0", ""}, - {GRAPHKEYS_MIRROR_XAXIS, "XAXIS", 0, "By Values over Value=0", ""}, - {GRAPHKEYS_MIRROR_MARKER, "MARKER", 0, "By Times over First Selected Marker", ""}, + {GRAPHKEYS_MIRROR_CFRA, "CFRA", 0, "By Times over Current Frame", + "Flip times of selected keyframes using the current frame as the mirror line"}, + {GRAPHKEYS_MIRROR_VALUE, "VALUE", 0, "By Values over Cursor Value", + "Flip values of selected keyframes using the cursor value (Y/Horizontal component) as the mirror line"}, + {GRAPHKEYS_MIRROR_YAXIS, "YAXIS", 0, "By Times over Time=0", + "Flip times of selected keyframes, effectively reversing the order they appear in"}, + {GRAPHKEYS_MIRROR_XAXIS, "XAXIS", 0, "By Values over Value=0", + "Flip values of selected keyframes (i.e. negative values become positive, and vice versa)"}, + {GRAPHKEYS_MIRROR_MARKER, "MARKER", 0, "By Times over First Selected Marker", + "Flip times of selected keyframes using the first selected marker as the reference point"}, {0, NULL, 0, NULL, NULL} }; @@ -2170,7 +2196,7 @@ static int graph_fmodifier_add_exec(bContext *C, wmOperator *op) if (fcm) set_active_fmodifier(&fcu->modifiers, fcm); else { - BKE_report(op->reports, RPT_ERROR, "Modifier couldn't be added, see console for details"); + BKE_report(op->reports, RPT_ERROR, "Modifier could not be added (see console for details)"); break; } } diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index eb657169970..b2dbf764c1d 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -123,7 +123,7 @@ enum { GRAPHKEYS_SNAP_CFRA = 1, GRAPHKEYS_SNAP_NEAREST_FRAME, GRAPHKEYS_SNAP_NEAREST_SECOND, - GRAPHKEYS_SNAP_NEAREST_MARKER, + GRAPHKEYS_SNAP_NEAREST_MARKER, GRAPHKEYS_SNAP_HORIZONTAL, GRAPHKEYS_SNAP_VALUE, } eGraphKeys_Snap_Mode; diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index d54e3694f07..9b031c015a9 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -346,9 +346,8 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) /* graph_edit.c */ - /* snap - current frame to selected keys */ - // TODO: maybe since this is called jump, we're better to have it on -J? - WM_keymap_add_item(keymap, "GRAPH_OT_frame_jump", SKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); + /* jump to selected keyframes */ + WM_keymap_add_item(keymap, "GRAPH_OT_frame_jump", GKEY, KM_PRESS, KM_CTRL, 0); /* menu + single-step transform */ WM_keymap_add_item(keymap, "GRAPH_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0); @@ -372,7 +371,7 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) /* insertkey */ WM_keymap_add_item(keymap, "GRAPH_OT_keyframe_insert", IKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "GRAPH_OT_click_insert", LEFTMOUSE, KM_CLICK, KM_CTRL, 0); + WM_keymap_add_item(keymap, "GRAPH_OT_click_insert", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0); /* copy/paste */ WM_keymap_add_item(keymap, "GRAPH_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 633f2b72cf6..978b3224850 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -325,7 +325,7 @@ static int graphkeys_borderselect_exec(bContext *C, wmOperator *op) * - the frame-range select option is favored over the channel one (x over y), as frame-range one is often * used for tweaking timing when "blocking", while channels is not that useful... */ - if ((BLI_RCT_SIZE_X(&rect)) >= (BLI_RCT_SIZE_Y(&rect))) + if ((BLI_rcti_size_x(&rect)) >= (BLI_rcti_size_y(&rect))) mode = BEZT_OK_FRAMERANGE; else mode = BEZT_OK_VALUERANGE; @@ -757,7 +757,7 @@ static void graphkeys_select_leftright(bAnimContext *ac, short leftright, short if (leftright == GRAPHKEYS_LRSEL_LEFT) { ked.f1 = MINAFRAMEF; ked.f2 = (float)(CFRA + 0.1f); - } + } else { ked.f1 = (float)(CFRA - 0.1f); ked.f2 = MAXFRAMEF; @@ -835,7 +835,7 @@ static int graphkeys_select_leftright_invoke(bContext *C, wmOperator *op, wmEven UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, NULL); if (x < CFRA) RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_LEFT); - else + else RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_RIGHT); } @@ -1113,7 +1113,7 @@ static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_m nvi = find_nearest_fcurve_vert(ac, mval); /* check if anything to select */ - if (nvi == NULL) + if (nvi == NULL) return; /* deselect all other curves? */ @@ -1241,7 +1241,7 @@ static void graphkeys_mselect_column(bAnimContext *ac, const int mval[2], short nvi = find_nearest_fcurve_vert(ac, mval); /* check if anything to select */ - if (nvi == NULL) + if (nvi == NULL) return; /* get frame number on which elements should be selected */ diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index a4611cf1453..f41169b6c39 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -441,7 +441,7 @@ static void graph_listener(ScrArea *sa, wmNotifier *wmn) ED_area_tag_refresh(sa); break; case NC_SCENE: - switch (wmn->data) { + switch (wmn->data) { case ND_OB_ACTIVE: /* selection changed, so force refresh to flush (needs flag set to do syncing) */ case ND_OB_SELECT: sipo->flag |= SIPO_TEMP_NEEDCHANSYNC; @@ -461,7 +461,7 @@ static void graph_listener(ScrArea *sa, wmNotifier *wmn) ED_area_tag_refresh(sa); break; case ND_TRANSFORM: - break; /*do nothing*/ + break; /*do nothing*/ default: /* just redrawing the view will do */ ED_area_tag_redraw(sa); diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index c372973b7b0..ae7a718ab5b 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -71,28 +71,6 @@ #include "image_intern.h" -#define B_REDR 1 -#define B_IMAGECHANGED 2 -#define B_NOP 0 -#define B_TWINANIM 5 -#define B_SIMAGETILE 6 -#define B_IDNAME 10 -#define B_FACESEL_PAINT_TEST 11 -#define B_SIMA_RECORD 12 -#define B_SIMA_PLAY 13 - -#define B_SIMANOTHING 16 -#define B_SIMABRUSHCHANGE 17 -#define B_SIMABRUSHBROWSE 18 -#define B_SIMABRUSHLOCAL 19 -#define B_SIMABRUSHDELETE 20 -#define B_KEEPDATA 21 -#define B_SIMABTEXBROWSE 22 -#define B_SIMABTEXDELETE 23 -#define B_VPCOLSLI 24 -#define B_SIMACLONEBROWSE 25 -#define B_SIMACLONEDELETE 26 - /* proto */ static void image_info(Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf, char *str) @@ -213,7 +191,7 @@ void image_preview_event(int event) waitcursor(0); WM_event_add_notifier(C, NC_IMAGE, ima_v); - } + } } @@ -228,13 +206,13 @@ static void preview_cb(ScrArea *sa, struct uiBlock *block) int mval[2]; if (G.scene->r.mode & R_BORDER) { - winx *= BLI_RCT_SIZE_X(&G.scene->r.border); - winy *= BLI_RCT_SIZE_Y(&G.scene->r.border); + winx *= BLI_rcti_size_x(&G.scene->r.border); + winy *= BLI_rctf_size_y(&G.scene->r.border); } /* while dragging we need to update the rects, otherwise it doesn't end with correct one */ - BLI_rctf_init(&dispf, 15.0f, BLI_RCT_SIZE_X(&block->rect) - 15.0f, 15.0f, (BLI_RCT_SIZE_Y(&block->rect)) - 15.0f); + BLI_rctf_init(&dispf, 15.0f, BLI_rcti_size_x(&block->rect) - 15.0f, 15.0f, (BLI_rctf_size_y(&block->rect)) - 15.0f); ui_graphics_to_window_rct(sa->win, &dispf, disprect); /* correction for gla draw */ @@ -744,8 +722,10 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char split = uiLayoutSplit(layout, 0.0f, FALSE); col = uiLayoutColumn(split, TRUE); + uiLayoutSetEnabled(col, 0); uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE); uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE); + uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE); uiItemR(split, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); @@ -781,9 +761,10 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man uiItemR(sub, imfptr, "color_mode", UI_ITEM_R_EXPAND, IFACE_("Color"), ICON_NONE); /* only display depth setting if multiple depths can be used */ - if ((ELEM6(depth_ok, + if ((ELEM7(depth_ok, R_IMF_CHAN_DEPTH_1, R_IMF_CHAN_DEPTH_8, + R_IMF_CHAN_DEPTH_10, R_IMF_CHAN_DEPTH_12, R_IMF_CHAN_DEPTH_16, R_IMF_CHAN_DEPTH_24, @@ -823,9 +804,13 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man uiItemR(col, imfptr, "use_jpeg2k_ycc", 0, NULL, ICON_NONE); } + if (imf->imtype == R_IMF_IMTYPE_DPX) { + uiItemR(col, imfptr, "use_cineon_log", 0, NULL, ICON_NONE); + } + if (imf->imtype == R_IMF_IMTYPE_CINEON) { #if 1 - uiItemL(col, IFACE_("Hard coded Non-Linear, Gamma: 1.0"), ICON_NONE); + uiItemL(col, IFACE_("Hard coded Non-Linear, Gamma:1.7"), ICON_NONE); #else uiItemR(col, imfptr, "use_cineon_log", 0, NULL, ICON_NONE); uiItemR(col, imfptr, "cineon_black", 0, NULL, ICON_NONE); @@ -836,7 +821,7 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man /* color management */ if (color_management && - (!BKE_imtype_supports_float(imf->imtype) || + (!BKE_imtype_requires_linear_float(imf->imtype) || (show_preview && imf->flag & R_IMF_FLAG_PREVIEW_JPG))) { prop = RNA_struct_find_property(imfptr, "display_settings"); diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 638a2ac6681..9fc2b981547 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -78,8 +78,6 @@ #include "image_intern.h" -#define HEADER_HEIGHT 18 - static void draw_render_info(Scene *scene, Image *ima, ARegion *ar) { RenderResult *rr; @@ -118,7 +116,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def /* noisy, high contrast make impossible to read if lower alpha is used. */ glColor4ub(0, 0, 0, 190); - glRecti(0.0, 0.0, BLI_RCT_SIZE_X(&ar->winrct) + 1, 20); + glRecti(0.0, 0.0, BLI_rcti_size_x(&ar->winrct) + 1, 20); glDisable(GL_BLEND); BLF_size(blf_mono_font, 11, 72); @@ -524,7 +522,7 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene, dy = ibuf->y / ima->yrep; sx = (sima->curtile % ima->xrep) * dx; sy = (sima->curtile / ima->xrep) * dy; - rect = get_part_from_buffer((unsigned int*)display_buffer, ibuf->x, sx, sy, sx + dx, sy + dy); + rect = get_part_from_buffer((unsigned int *)display_buffer, ibuf->x, sx, sy, sx + dx, sy + dy); /* draw repeated */ for (sy = 0; sy + dy <= ibuf->y; sy += dy) { @@ -580,7 +578,7 @@ void draw_image_grease_pencil(bContext *C, short onlyv2d) } else { /* assume that UI_view2d_restore(C) has been called... */ - //SpaceImage *sima= (SpaceImage *)CTX_wm_space_data(C); + //SpaceImage *sima = (SpaceImage *)CTX_wm_space_data(C); /* draw grease-pencil ('screen' strokes) */ draw_gpencil_view2d(C, 0); @@ -793,7 +791,7 @@ void draw_image_main(const bContext *C, ARegion *ar) xoffs = scene->r.disprect.xmin; yoffs = scene->r.disprect.ymin; glColor3ub(0, 0, 0); - calc_image_view(sima, 'f'); + calc_image_view(sima, 'f'); myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax); glRectf(0.0f, 0.0f, 1.0f, 1.0f); glLoadIdentity(); diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index 79d01491df7..4ca2f8888f8 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -78,8 +78,8 @@ void ED_space_image_set(SpaceImage *sima, Scene *scene, Object *obedit, Image *i if (sima->image) BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_USER_NEW_IMAGE); - if (sima->image && sima->image->id.us == 0) - sima->image->id.us = 1; + if (sima->image && ID_REAL_USERS(sima->image) <= 0) + sima->image->id.us = max_ii(sima->image->id.us, 0) + 1; if (obedit) WM_main_add_notifier(NC_GEOM | ND_DATA, obedit->data); @@ -97,8 +97,8 @@ void ED_space_image_set_mask(bContext *C, SpaceImage *sima, Mask *mask) sima->mask_info.mask = mask; /* weak, but same as image/space */ - if (sima->mask_info.mask && sima->mask_info.mask->id.us == 0) - sima->mask_info.mask->id.us = 1; + if (sima->mask_info.mask && ID_REAL_USERS(sima->mask_info.mask) <= 0) + sima->mask_info.mask->id.us = max_ii(sima->mask_info.mask->id.us, 0) + 1; if (C) { WM_event_add_notifier(C, NC_MASK | NA_SELECTED, mask); @@ -120,6 +120,8 @@ ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r) if (ibuf && (ibuf->rect || ibuf->rect_float)) return ibuf; } + else + *lock_r = NULL; return NULL; } @@ -161,8 +163,8 @@ void ED_space_image_get_size(SpaceImage *sima, int *width, int *height) *height = (scene->r.ysch * scene->r.size) / 100; if ((scene->r.mode & R_BORDER) && (scene->r.mode & R_CROP)) { - *width *= BLI_RCT_SIZE_X(&scene->r.border); - *height *= BLI_RCT_SIZE_Y(&scene->r.border); + *width *= BLI_rctf_size_x(&scene->r.border); + *height *= BLI_rctf_size_y(&scene->r.border); } } @@ -204,8 +206,8 @@ void ED_space_image_get_zoom(SpaceImage *sima, ARegion *ar, float *zoomx, float ED_space_image_get_size(sima, &width, &height); - *zoomx = (float)(BLI_RCT_SIZE_X(&ar->winrct) + 1) / (float)(BLI_RCT_SIZE_X(&ar->v2d.cur) * width); - *zoomy = (float)(BLI_RCT_SIZE_Y(&ar->winrct) + 1) / (float)(BLI_RCT_SIZE_Y(&ar->v2d.cur) * height); + *zoomx = (float)(BLI_rcti_size_x(&ar->winrct) + 1) / (float)(BLI_rctf_size_x(&ar->v2d.cur) * width); + *zoomy = (float)(BLI_rcti_size_y(&ar->winrct) + 1) / (float)(BLI_rctf_size_y(&ar->v2d.cur) * height); } void ED_space_image_get_uv_aspect(SpaceImage *sima, float *aspx, float *aspy) diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 16804c5a1c6..ce3c6e1fd26 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -39,6 +39,8 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "DNA_object_types.h" #include "DNA_node_types.h" #include "DNA_packedFile_types.h" @@ -99,9 +101,9 @@ static void sima_zoom_set(SpaceImage *sima, ARegion *ar, float zoom, float locat if ((width < 4) && (height < 4)) sima->zoom = oldzoom; - else if (BLI_RCT_SIZE_X(&ar->winrct) <= sima->zoom) + else if (BLI_rcti_size_x(&ar->winrct) <= sima->zoom) sima->zoom = oldzoom; - else if (BLI_RCT_SIZE_Y(&ar->winrct) <= sima->zoom) + else if (BLI_rcti_size_y(&ar->winrct) <= sima->zoom) sima->zoom = oldzoom; } @@ -183,7 +185,7 @@ static int space_image_poll(bContext *C) int space_image_main_area_poll(bContext *C) { SpaceImage *sima = CTX_wm_space_image(C); - // XXX ARegion *ar= CTX_wm_region(C); + // XXX ARegion *ar = CTX_wm_region(C); if (sima) return 1; // XXX (ar && ar->type->regionid == RGN_TYPE_WINDOW); @@ -430,11 +432,16 @@ static int image_view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event) if (event->type == MOUSEZOOM) { SpaceImage *sima = CTX_wm_space_image(C); ARegion *ar = CTX_wm_region(C); - float factor, location[2]; + float delta, factor, location[2]; UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]); - factor = 1.0f + (event->x - event->prevx + event->y - event->prevy) / 300.0f; + delta = event->x - event->prevx + event->y - event->prevy; + + if (U.uiflag & USER_ZOOM_INVERT) + delta *= -1; + + factor = 1.0f + delta / 300.0f; RNA_float_set(op->ptr, "factor", factor); sima_zoom_set(sima, ar, sima->zoom * factor, location); ED_region_tag_redraw(CTX_wm_region(C)); @@ -452,11 +459,16 @@ static int image_view_zoom_modal(bContext *C, wmOperator *op, wmEvent *event) SpaceImage *sima = CTX_wm_space_image(C); ARegion *ar = CTX_wm_region(C); ViewZoomData *vpd = op->customdata; - float factor; + float delta, factor; switch (event->type) { case MOUSEMOVE: - factor = 1.0f + (vpd->x - event->x + vpd->y - event->y) / 300.0f; + delta = event->x - vpd->x + event->y - vpd->y; + + if (U.uiflag & USER_ZOOM_INVERT) + delta *= -1; + + factor = 1.0f + delta / 300.0f; RNA_float_set(op->ptr, "factor", factor); sima_zoom_set(sima, ar, vpd->zoom * factor, vpd->location); ED_region_tag_redraw(CTX_wm_region(C)); @@ -496,7 +508,7 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot) ot->flag = OPTYPE_BLOCKING; /* properties */ - RNA_def_float(ot->srna, "factor", 0.0f, 0.0f, FLT_MAX, + RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Factor", "Zoom factor, values higher than 1.0 zoom in, lower values zoom out", -FLT_MAX, FLT_MAX); } @@ -541,7 +553,7 @@ static int image_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent * sima->xof += pan_x; sima->yof += pan_y; - ED_region_tag_redraw(ar); + ED_region_tag_redraw(ar); return OPERATOR_FINISHED; } @@ -582,14 +594,14 @@ static int image_view_all_exec(bContext *C, wmOperator *UNUSED(op)) h = height * aspy; /* check if the image will fit in the image with (zoom == 1) */ - width = BLI_RCT_SIZE_X(&ar->winrct) + 1; - height = BLI_RCT_SIZE_Y(&ar->winrct) + 1; + width = BLI_rcti_size_x(&ar->winrct) + 1; + height = BLI_rcti_size_y(&ar->winrct) + 1; if ((w >= width || h >= height) && (width > 0 && height > 0)) { /* find the zoom value that will fit the image in the image space */ zoomx = width / w; zoomy = height / h; - sima_zoom_set(sima, ar, 1.0f / power_of_2(1.0f / minf(zoomx, zoomy)), NULL); + sima_zoom_set(sima, ar, 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)), NULL); } else sima_zoom_set(sima, ar, 1.0f, NULL); @@ -606,7 +618,7 @@ void IMAGE_OT_view_all(wmOperatorType *ot) /* identifiers */ ot->name = "View All"; ot->idname = "IMAGE_OT_view_all"; - ot->description = "View the whole picture"; + ot->description = "View the entire image"; /* api callbacks */ ot->exec = image_view_all_exec; @@ -793,14 +805,14 @@ void IMAGE_OT_view_zoom_ratio(wmOperatorType *ot) /* identifiers */ ot->name = "View Zoom Ratio"; ot->idname = "IMAGE_OT_view_zoom_ratio"; - ot->description = "Set zoom ration of the view"; + ot->description = "Set zoom ratio of the view"; /* api callbacks */ ot->exec = image_view_zoom_ratio_exec; ot->poll = space_image_main_area_poll; /* properties */ - RNA_def_float(ot->srna, "ratio", 0.0f, 0.0f, FLT_MAX, + RNA_def_float(ot->srna, "ratio", 0.0f, -FLT_MAX, FLT_MAX, "Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out", -FLT_MAX, FLT_MAX); } @@ -848,7 +860,8 @@ static int image_open_exec(bContext *C, wmOperator *op) if (!ima) { if (op->customdata) MEM_freeN(op->customdata); - BKE_reportf(op->reports, RPT_ERROR, "Can't read: \"%s\", %s", str, errno ? strerror(errno) : "Unsupported image format"); + BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s", + str, errno ? strerror(errno) : TIP_("unsupported image format")); return OPERATOR_CANCELLED; } @@ -1137,7 +1150,7 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima, else { simopts->im_format.imtype = BKE_ftype_to_imtype(ibuf->ftype); } - //simopts->subimtype= scene->r.subimtype; /* XXX - this is lame, we need to make these available too! */ + //simopts->subimtype = scene->r.subimtype; /* XXX - this is lame, we need to make these available too! */ simopts->im_format.quality = ibuf->ftype & 0xff; BLI_strncpy(simopts->filepath, ibuf->name, sizeof(simopts->filepath)); @@ -1205,39 +1218,6 @@ static void save_image_options_to_op(SaveImageOptions *simopts, wmOperator *op) RNA_string_set(op->ptr, "filepath", simopts->filepath); } -static ImBuf *save_image_colormanaged_imbuf_acquire(ImBuf *ibuf, SaveImageOptions *simopts, int save_as_render, void **cache_handle) -{ - ImageFormatData *imf = &simopts->im_format; - ImBuf *colormanaged_ibuf; - int do_colormanagement; - - *cache_handle = NULL; - do_colormanagement = save_as_render && !BKE_imtype_supports_float(imf->imtype); - - if (do_colormanagement) { - unsigned char *display_buffer; - - display_buffer = IMB_display_buffer_acquire(ibuf, &imf->view_settings, &imf->display_settings, cache_handle); - - if (*cache_handle) { - colormanaged_ibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, 0); - colormanaged_ibuf->rect = (unsigned int *) display_buffer; - } - else { - /* no cache handle means color management didn't run transformation - * or performed transformation to image's byte buffer which doesn't - * require allocating new image buffer - */ - colormanaged_ibuf = ibuf; - } - } - else { - colormanaged_ibuf = ibuf; - } - - return colormanaged_ibuf; -} - /* assumes name is FILE_MAX */ /* ima->name and ibuf->name should end up the same */ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveImageOptions *simopts, int do_newpath) @@ -1247,12 +1227,12 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock); if (ibuf) { - void *cache_handle; ImBuf *colormanaged_ibuf; const char *relbase = ID_BLEND_PATH(CTX_data_main(C), &ima->id); const short relative = (RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path")); const short save_copy = (RNA_struct_find_property(op->ptr, "copy") && RNA_boolean_get(op->ptr, "copy")); const short save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") && RNA_boolean_get(op->ptr, "save_as_render")); + ImageFormatData *imf = &simopts->im_format; short ok = FALSE; /* old global to ensure a 2nd save goes to same dir */ @@ -1277,7 +1257,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI } } - colormanaged_ibuf = save_image_colormanaged_imbuf_acquire(ibuf, simopts, save_as_render, &cache_handle); + colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, TRUE, &imf->view_settings, &imf->display_settings, imf); if (simopts->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) { Scene *scene = CTX_data_scene(C); @@ -1292,8 +1272,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI BKE_image_release_renderresult(scene, ima); } else { - if (BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, &simopts->im_format, save_copy)) - { + if (BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, &simopts->im_format, save_copy)) { ok = TRUE; } } @@ -1337,7 +1316,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI } } else { - BKE_reportf(op->reports, RPT_ERROR, "Couldn't write image: %s", simopts->filepath); + BKE_reportf(op->reports, RPT_ERROR, "Could not write image %s", simopts->filepath); } @@ -1345,12 +1324,8 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI WM_cursor_wait(0); - if (cache_handle) { - colormanaged_ibuf->rect = NULL; + if (colormanaged_ibuf != ibuf) IMB_freeImBuf(colormanaged_ibuf); - - IMB_display_buffer_release(cache_handle); - } } ED_space_image_release_buffer(sima, lock); @@ -1414,7 +1389,7 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(eve RNA_boolean_set(op->ptr, "copy", TRUE); } - if (ima->source == IMA_SRC_VIEWER) + if (ima->source == IMA_SRC_VIEWER || (ima->flag & IMA_VIEW_AS_RENDER)) RNA_boolean_set(op->ptr, "save_as_render", TRUE); else RNA_boolean_set(op->ptr, "save_as_render", FALSE); @@ -1461,6 +1436,24 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op) uiDefAutoButsRNA(layout, &ptr, image_save_as_draw_check_prop, '\0'); } +static int image_save_as_poll(bContext *C) +{ + if (space_image_buffer_exists_poll(C)) { + if (G.is_rendering) { + /* no need to NULL check here */ + SpaceImage *sima = CTX_wm_space_image(C); + Image *ima = ED_space_image(sima); + + if (ima->source == IMA_SRC_VIEWER) { + CTX_wm_operator_poll_msg_set(C, "can't save image while rendering"); + return FALSE; + } + } + return TRUE; + } + return FALSE; +} + void IMAGE_OT_save_as(wmOperatorType *ot) { // PropertyRNA *prop; @@ -1476,7 +1469,7 @@ void IMAGE_OT_save_as(wmOperatorType *ot) ot->invoke = image_save_as_invoke; ot->cancel = image_save_as_cancel; ot->ui = image_save_as_draw; - ot->poll = space_image_buffer_exists_poll; + ot->poll = image_save_as_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1505,7 +1498,7 @@ static int image_save_exec(bContext *C, wmOperator *op) save_image_doit(C, sima, op, &simopts, FALSE); } else { - BKE_reportf(op->reports, RPT_ERROR, "Can not save image, path '%s' is not writable", simopts.filepath); + BKE_reportf(op->reports, RPT_ERROR, "Cannot save image, path '%s' is not writable", simopts.filepath); return OPERATOR_CANCELLED; } @@ -1546,7 +1539,7 @@ static int image_save_sequence_exec(bContext *C, wmOperator *op) } if (sima->image->type == IMA_TYPE_MULTILAYER) { - BKE_report(op->reports, RPT_ERROR, "Can't save multilayer sequences"); + BKE_report(op->reports, RPT_ERROR, "Cannot save multilayer sequences"); return OPERATOR_CANCELLED; } @@ -1568,7 +1561,7 @@ static int image_save_sequence_exec(bContext *C, wmOperator *op) BLI_strncpy(di, ibuf->name, FILE_MAX); BLI_splitdirstring(di, fi); - BKE_reportf(op->reports, RPT_INFO, "%d Image(s) will be saved in %s", tot, di); + BKE_reportf(op->reports, RPT_INFO, "%d image(s) will be saved in %s", tot, di); for (ibuf = sima->image->ibufs.first; ibuf; ibuf = ibuf->next) { if (ibuf->userflags & IB_BITMAPDIRTY) { @@ -1582,7 +1575,7 @@ static int image_save_sequence_exec(bContext *C, wmOperator *op) break; } - BKE_reportf(op->reports, RPT_INFO, "Saved: %s\n", ibuf->name); + BKE_reportf(op->reports, RPT_INFO, "Saved %s", ibuf->name); ibuf->userflags &= ~IB_BITMAPDIRTY; } } @@ -1692,16 +1685,24 @@ static int image_new_exec(bContext *C, wmOperator *op) RNA_property_pointer_set(&ptr, prop, idptr); RNA_property_update(C, &ptr, prop); } - else if (sima) + else if (sima) { ED_space_image_set(sima, scene, obedit, ima); + } + else { + Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data; + if (tex && tex->type == TEX_IMAGE) { + tex->ima = ima; + ED_area_tag_redraw(CTX_wm_area(C)); + } + } - // XXX other users? BKE_image_signal(ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_USER_NEW_IMAGE); return OPERATOR_FINISHED; } /* XXX, Ton is not a fan of OK buttons but using this function to avoid undo/redo bug while in mesh-editmode, - campbell */ +/* XXX Note: the WM_operator_props_dialog_popup() doesn't work for uiIDContextProperty(), image is not being that way */ static int image_new_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { return WM_operator_props_dialog_popup(C, op, 300, 100); @@ -1854,7 +1855,7 @@ static int image_pack_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; if (!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) { - BKE_report(op->reports, RPT_ERROR, "Can't pack edited image from disk, only as internal PNG"); + BKE_report(op->reports, RPT_ERROR, "Cannot pack edited image from disk, only as internal PNG"); return OPERATOR_CANCELLED; } @@ -2372,8 +2373,8 @@ static int image_record_composite_apply(bContext *C, wmOperator *op) WM_cursor_time(CTX_wm_window(C), scene->r.cfra); - // XXX scene->nodetree->test_break= blender_test_break; - // XXX scene->nodetree->test_break= NULL; + // XXX scene->nodetree->test_break = blender_test_break; + // XXX scene->nodetree->test_break = NULL; BKE_image_all_free_anim_ibufs(scene->r.cfra); ntreeCompositTagAnimated(scene->nodetree); @@ -2439,8 +2440,7 @@ static int image_record_composite_exec(bContext *C, wmOperator *op) if (!image_record_composite_init(C, op)) return OPERATOR_CANCELLED; - while (image_record_composite_apply(C, op)) - ; + while (image_record_composite_apply(C, op)) {} image_record_composite_exit(C, op); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 5b288bd6149..4131cbfdd0d 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -408,16 +408,15 @@ static void image_refresh(const bContext *C, ScrArea *sa) MTexPoly *tf; if (em && EDBM_mtexpoly_check(em)) { - sima->image = NULL; - tf = EDBM_mtexpoly_active_get(em, NULL, sloppy, selected); if (tf) { /* don't need to check for pin here, see above */ sima->image = tf->tpage; - if (sima->flag & SI_EDITTILE) ; - else sima->curtile = tf->tile; + if ((sima->flag & SI_EDITTILE) == 0) { + sima->curtile = tf->tile; + } } } } @@ -438,6 +437,10 @@ static void image_listener(ScrArea *sa, wmNotifier *wmn) ED_area_tag_redraw(sa); break; case ND_MODE: + if (wmn->subtype == NS_EDITMODE_MESH) + ED_area_tag_refresh(sa); + ED_area_tag_redraw(sa); + break; case ND_RENDER_RESULT: case ND_RENDER_OPTIONS: case ND_COMPO_RESULT: @@ -454,7 +457,7 @@ static void image_listener(ScrArea *sa, wmNotifier *wmn) ED_area_tag_redraw(sa); } break; - case NC_SPACE: + case NC_SPACE: if (wmn->data == ND_SPACE_IMAGE) { image_scopes_tag_refresh(sa); ED_area_tag_redraw(sa); @@ -547,7 +550,7 @@ static void image_main_area_set_view2d(SpaceImage *sima, ARegion *ar) int width, height, winx, winy; #if 0 - if (image_preview_active(curarea, &width, &height)) ; + if (image_preview_active(curarea, &width, &height)) {} else #endif ED_space_image_get_size(sima, &width, &height); @@ -558,8 +561,8 @@ static void image_main_area_set_view2d(SpaceImage *sima, ARegion *ar) if (ima) h *= ima->aspy / ima->aspx; - winx = BLI_RCT_SIZE_X(&ar->winrct) + 1; - winy = BLI_RCT_SIZE_Y(&ar->winrct) + 1; + winx = BLI_rcti_size_x(&ar->winrct) + 1; + winy = BLI_rcti_size_y(&ar->winrct) + 1; ar->v2d.tot.xmin = 0; ar->v2d.tot.ymin = 0; @@ -706,8 +709,8 @@ static void image_main_area_listener(ARegion *ar, wmNotifier *wmn) { /* context changes */ switch (wmn->category) { - case NC_SCREEN: - if (wmn->data == ND_GPENCIL) + case NC_GPENCIL: + if (wmn->action == NA_EDITED) ED_region_tag_redraw(ar); break; } @@ -735,8 +738,8 @@ static void image_buttons_area_listener(ARegion *ar, wmNotifier *wmn) { /* context changes */ switch (wmn->category) { - case NC_SCREEN: - if (wmn->data == ND_GPENCIL) + case NC_GPENCIL: + if (wmn->data == ND_DATA) ED_region_tag_redraw(ar); break; case NC_BRUSH: diff --git a/source/blender/editors/space_info/info_draw.c b/source/blender/editors/space_info/info_draw.c index 35e19bcce38..5830c4574df 100644 --- a/source/blender/editors/space_info/info_draw.c +++ b/source/blender/editors/space_info/info_draw.c @@ -136,7 +136,7 @@ static int report_textview_skip__internal(TextViewContext *tvc) static int report_textview_begin(TextViewContext *tvc) { - // SpaceConsole *sc= (SpaceConsole *)tvc->arg1; + // SpaceConsole *sc = (SpaceConsole *)tvc->arg1; ReportList *reports = (ReportList *)tvc->arg2; tvc->lheight = 14; //sc->lheight; diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c index 805ff1794c9..131908bc9db 100644 --- a/source/blender/editors/space_info/info_ops.c +++ b/source/blender/editors/space_info/info_ops.c @@ -124,7 +124,7 @@ static const EnumPropertyItem unpack_all_method_items[] = { {PF_WRITE_LOCAL, "WRITE_LOCAL", 0, "Write files to current directory (overwrite existing files)", ""}, {PF_USE_ORIGINAL, "USE_ORIGINAL", 0, "Use files in original location (create when necessary)", ""}, {PF_WRITE_ORIGINAL, "WRITE_ORIGINAL", 0, "Write files to original location (overwrite existing files)", ""}, - {PF_KEEP, "KEEP", 0, "Disable AutoPack, keep all packed files", ""}, + {PF_KEEP, "KEEP", 0, "Disable Auto-pack, keep all packed files", ""}, /* {PF_ASK, "ASK", 0, "Ask for each file", ""}, */ {0, NULL, 0, NULL, NULL}}; @@ -150,7 +150,7 @@ static int unpack_all_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event) count = countPackedFiles(bmain); if (!count) { - BKE_report(op->reports, RPT_WARNING, "No packed files. Autopack disabled"); + BKE_report(op->reports, RPT_WARNING, "No packed files (auto-pack disabled)"); G.fileflags &= ~G_AUTOPACK; return OPERATOR_CANCELLED; } @@ -196,7 +196,7 @@ static int make_paths_relative_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); if (!G.relbase_valid) { - BKE_report(op->reports, RPT_WARNING, "Can't set relative paths with an unsaved blend file"); + BKE_report(op->reports, RPT_WARNING, "Cannot set relative paths with an unsaved blend file"); return OPERATOR_CANCELLED; } @@ -229,7 +229,7 @@ static int make_paths_absolute_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); if (!G.relbase_valid) { - BKE_report(op->reports, RPT_WARNING, "Can't set absolute paths with an unsaved blend file"); + BKE_report(op->reports, RPT_WARNING, "Cannot set absolute paths with an unsaved blend file"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_info/info_report.c b/source/blender/editors/space_info/info_report.c index 2324f735a33..049a50f89fc 100644 --- a/source/blender/editors/space_info/info_report.c +++ b/source/blender/editors/space_info/info_report.c @@ -68,9 +68,9 @@ int info_report_mask(SpaceInfo *UNUSED(sinfo)) // TODO, get this working again! static int report_replay_exec(bContext *C, wmOperator *UNUSED(op)) { -// SpaceInfo *sc= CTX_wm_space_info(C); -// ReportList *reports= CTX_wm_reports(C); -// int report_mask= info_report_mask(sc); +// SpaceInfo *sc = CTX_wm_space_info(C); +// ReportList *reports = CTX_wm_reports(C); +// int report_mask = info_report_mask(sc); // Report *report; #if 0 @@ -223,7 +223,7 @@ static int borderselect_exec(bContext *C, wmOperator *op) int extend = RNA_boolean_get(op->ptr, "extend"); Report *report_min, *report_max, *report; - //View2D *v2d= UI_view2d_fromcontext(C); + //View2D *v2d = UI_view2d_fromcontext(C); rcti rect; diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index 4ffa99319c4..5e5e0c87feb 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -368,7 +368,7 @@ static void stats_string(Scene *scene) s += sprintf(s, "%s | ", versionstr); if (scene->obedit) { - if (ob_get_keyblock(scene->obedit)) + if (BKE_keyblock_from_object(scene->obedit)) s += sprintf(s, "(Key) "); if (scene->obedit->type == OB_MESH) { diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c index 7cb89b6bc6b..f108881091a 100644 --- a/source/blender/editors/space_info/space_info.c +++ b/source/blender/editors/space_info/space_info.c @@ -93,7 +93,7 @@ static SpaceLink *info_new(const bContext *UNUSED(C)) ar->v2d.minzoom = ar->v2d.maxzoom = 1.0f; /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */ - //ar->v2d.keepzoom= (V2D_KEEPASPECT|V2D_LIMITZOOM); + //ar->v2d.keepzoom = (V2D_KEEPASPECT|V2D_LIMITZOOM); return (SpaceLink *)sinfo; } @@ -101,7 +101,7 @@ static SpaceLink *info_new(const bContext *UNUSED(C)) /* not spacelink itself */ static void info_free(SpaceLink *UNUSED(sl)) { -// SpaceInfo *sinfo= (SpaceInfo*) sl; +// SpaceInfo *sinfo = (SpaceInfo *) sl; } @@ -228,7 +228,7 @@ static void info_header_area_draw(const bContext *C, ARegion *ar) static void info_main_area_listener(ARegion *ar, wmNotifier *wmn) { - // SpaceInfo *sinfo= sa->spacedata.first; + // SpaceInfo *sinfo = sa->spacedata.first; /* context changes */ switch (wmn->category) { @@ -249,7 +249,7 @@ static void info_header_listener(ARegion *ar, wmNotifier *wmn) if (ELEM(wmn->data, ND_SCREENCAST, ND_ANIMPLAY)) ED_region_tag_redraw(ar); break; - case NC_WM: + case NC_WM: if (wmn->data == ND_JOB) ED_region_tag_redraw(ar); break; @@ -257,7 +257,7 @@ static void info_header_listener(ARegion *ar, wmNotifier *wmn) if (wmn->data == ND_RENDER_RESULT) ED_region_tag_redraw(ar); break; - case NC_SPACE: + case NC_SPACE: if (wmn->data == ND_SPACE_INFO) ED_region_tag_redraw(ar); break; diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c index 4ba196276da..f454b1dbe7d 100644 --- a/source/blender/editors/space_info/textview.c +++ b/source/blender/editors/space_info/textview.c @@ -36,8 +36,6 @@ #include "BLI_math.h" #include "BLI_utildefines.h" - - #include "BIF_gl.h" #include "BIF_glutil.h" @@ -66,8 +64,8 @@ typedef struct ConsoleDrawContext { static void console_draw_sel(int sel[2], int xy[2], int str_len_draw, int cwidth, int lheight) { if (sel[0] <= str_len_draw && sel[1] >= 0) { - int sta = MAX2(sel[0], 0); - int end = MIN2(sel[1], str_len_draw); + int sta = max_ii(sel[0], 0); + int end = min_ii(sel[1], str_len_draw); glEnable(GL_POLYGON_STIPPLE); glPolygonStipple(stipple_halftone); @@ -128,7 +126,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str return 1; } - if (str_len > cdc->console_width) { /* wrap? */ + if (tot_lines > 1) { /* wrap? */ const int initial_offset = ((tot_lines - 1) * cdc->console_width); const char *line_stride = str + initial_offset; /* advance to the last line and draw it first */ diff --git a/source/blender/editors/space_logic/CMakeLists.txt b/source/blender/editors/space_logic/CMakeLists.txt index 8859d1d8bfd..13e6f9484e8 100644 --- a/source/blender/editors/space_logic/CMakeLists.txt +++ b/source/blender/editors/space_logic/CMakeLists.txt @@ -48,4 +48,8 @@ if(WITH_GAMEENGINE) add_definitions(-DWITH_GAMEENGINE) endif() +if(WITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) +endif() + blender_add_lib(bf_editor_space_logic "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/space_logic/SConscript b/source/blender/editors/space_logic/SConscript index 6beb3ecb48f..e63d88ea5de 100644 --- a/source/blender/editors/space_logic/SConscript +++ b/source/blender/editors/space_logic/SConscript @@ -3,7 +3,7 @@ Import ('env') sources = env.Glob('*.c') -incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' +incs = '../include ../../blenfont ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../makesrna ../interface ../../blenloader' @@ -12,4 +12,7 @@ defs = [] if env['WITH_BF_GAMEENGINE']: defs.append('WITH_GAMEENGINE') +if env['WITH_BF_INTERNATIONAL']: + defs.append('WITH_INTERNATIONAL') + env.BlenderLib ( 'bf_editors_space_game', sources, Split(incs), defs, libtype=['core'], priority=[120] ) diff --git a/source/blender/editors/space_logic/logic_buttons.c b/source/blender/editors/space_logic/logic_buttons.c index abffb955405..e898a1baf74 100644 --- a/source/blender/editors/space_logic/logic_buttons.c +++ b/source/blender/editors/space_logic/logic_buttons.c @@ -52,8 +52,8 @@ static int logic_properties(bContext *C, wmOperator *UNUSED(op)) { - ScrArea *sa= CTX_wm_area(C); - ARegion *ar= logic_has_buttons_region(sa); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = logic_has_buttons_region(sa); if (ar) ED_region_toggle_hidden(C, ar); @@ -84,10 +84,10 @@ static int cut_links_intersect(uiLinkLine *line, float mcoords[][2], int tot) int i, b; rcti rectlink; - rectlink.xmin = (int)BLI_RCT_CENTER_X(&line->from->rect); - rectlink.ymin = (int)BLI_RCT_CENTER_Y(&line->from->rect); - rectlink.xmax = (int)BLI_RCT_CENTER_X(&line->to->rect); - rectlink.ymax = (int)BLI_RCT_CENTER_Y(&line->to->rect); + rectlink.xmin = (int)BLI_rctf_cent_x(&line->from->rect); + rectlink.ymin = (int)BLI_rctf_cent_y(&line->from->rect); + rectlink.xmax = (int)BLI_rctf_cent_x(&line->to->rect); + rectlink.ymax = (int)BLI_rctf_cent_y(&line->to->rect); if (ui_link_bezier_points(&rectlink, coord_array, LINK_RESOL)) { for (i=0; iptr, itemptr, "path") { @@ -113,7 +113,7 @@ static int cut_links_exec(bContext *C, wmOperator *op) (int)loc[0], (int)loc[1], &mcoords[i][0], &mcoords[i][1]); i++; - if (i>= 256) break; + if (i >= 256) break; } RNA_END; @@ -121,23 +121,23 @@ static int cut_links_exec(bContext *C, wmOperator *op) uiBlock *block; uiLinkLine *line, *nline; uiBut *but; - for (block= ar->uiblocks.first; block; block= block->next) { - but= block->buttons.first; + for (block = ar->uiblocks.first; block; block = block->next) { + but = block->buttons.first; while (but) { if (but->type==LINK && but->link) { - for (line= but->link->lines.first; line; line= nline) { - nline= line->next; + for (line = but->link->lines.first; line; line = nline) { + nline = line->next; if (cut_links_intersect(line, mcoords, i)) { ui_delete_linkline(line, but); } } } - but= but->next; + but = but->next; } } return OPERATOR_FINISHED; - } + } return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH; } @@ -159,7 +159,7 @@ void LOGIC_OT_links_cut(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; - prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE); + prop = RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath); /* internal */ RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX); diff --git a/source/blender/editors/space_logic/logic_ops.c b/source/blender/editors/space_logic/logic_ops.c index f2013e405e2..74be7c46d26 100644 --- a/source/blender/editors/space_logic/logic_ops.c +++ b/source/blender/editors/space_logic/logic_ops.c @@ -138,7 +138,7 @@ static bSensor *edit_sensor_property_get(bContext *C, wmOperator *op, Object **o *ob = edit_object_property_get(C, op); if (!*ob) return NULL; - sens = BLI_findstring(&((*ob)->sensors), sensor_name, offsetof(bSensor, name)); + sens = BLI_findstring(&((*ob)->sensors), sensor_name, offsetof(bSensor, name)); return sens; } @@ -177,7 +177,7 @@ static bController *edit_controller_property_get(bContext *C, wmOperator *op, Ob *ob = edit_object_property_get(C, op); if (!*ob) return NULL; - cont = BLI_findstring(&((*ob)->controllers), controller_name, offsetof(bController, name)); + cont = BLI_findstring(&((*ob)->controllers), controller_name, offsetof(bController, name)); return cont; } @@ -216,7 +216,7 @@ static bActuator *edit_actuator_property_get(bContext *C, wmOperator *op, Object *ob = edit_object_property_get(C, op); if (!*ob) return NULL; - act = BLI_findstring(&((*ob)->actuators), actuator_name, offsetof(bActuator, name)); + act = BLI_findstring(&((*ob)->actuators), actuator_name, offsetof(bActuator, name)); return act; } diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index 6ffac1dcd34..5a8a7cef119 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -56,6 +56,7 @@ #include "BKE_library.h" #include "BKE_main.h" #include "BKE_sca.h" +#include "BKE_screen.h" #include "ED_util.h" @@ -63,7 +64,10 @@ #include "BIF_gl.h" +#include "BLF_translation.h" + #include "UI_interface.h" +#include "UI_view2d.h" #include "RNA_access.h" @@ -72,10 +76,7 @@ #include "logic_intern.h" - -#define MAX_RENDER_PASS 100 #define B_REDR 1 -#define B_IDNAME 2 #define B_ADD_SENS 2703 #define B_CHANGE_SENS 2704 @@ -91,7 +92,6 @@ #define B_SOUNDACT_BROWSE 2712 -#define B_SETSECTOR 2713 #define B_SETPROP 2714 #define B_SETACTOR 2715 #define B_SETMAINACTOR 2716 @@ -106,8 +106,8 @@ static int vergname(const void *v1, const void *v2) { char **x1, **x2; - x1= (char **)v1; - x2= (char **)v2; + x1 = (char **)v1; + x2 = (char **)v2; return BLI_natstrcmp(*x1, *x2); } @@ -138,7 +138,7 @@ void make_unique_prop_names(bContext *C, char *str) propcount+= BLI_countlist(&ob->sensors); propcount+= BLI_countlist(&ob->controllers); propcount+= BLI_countlist(&ob->actuators); - } + } if (propcount==0) { if (idar) MEM_freeN(idar); return; @@ -153,22 +153,22 @@ void make_unique_prop_names(bContext *C, char *str) ob= (Object *)idar[a]; prop= ob->prop.first; while (prop) { - names[nr++]= prop->name; + names[nr++] = prop->name; prop= prop->next; } sens= ob->sensors.first; while (sens) { - names[nr++]= sens->name; + names[nr++] = sens->name; sens= sens->next; } cont= ob->controllers.first; while (cont) { - names[nr++]= cont->name; + names[nr++] = cont->name; cont= cont->next; } act= ob->actuators.first; while (act) { - names[nr++]= act->name; + names[nr++] = act->name; act= act->next; } } @@ -187,178 +187,6 @@ void make_unique_prop_names(bContext *C, char *str) MEM_freeN(names); } -static void make_unique_prop_names_cb(bContext *C, void *strv, void *UNUSED(redraw_view3d_flagv)) -{ - char *str= strv; -// int redraw_view3d_flag= GET_INT_FROM_POINTER(redraw_view3d_flagv); - - make_unique_prop_names(C, str); -} - - -static void old_sca_move_sensor(bContext *C, void *datav, void *move_up) -{ - /* deprecated, no longer using it (moved to sca.c) */ - Scene *scene= CTX_data_scene(C); - bSensor *sens_to_delete= datav; - int val; - Base *base; - bSensor *sens, *tmp; - - // val= pupmenu("Move up%x1|Move down %x2"); - val = move_up ? 1:2; - - if (val>0) { - /* now find out which object has this ... */ - base= FIRSTBASE; - while (base) { - - sens= base->object->sensors.first; - while (sens) { - if (sens == sens_to_delete) break; - sens= sens->next; - } - - if (sens) { - if ( val==1 && sens->prev) { - for (tmp=sens->prev; tmp; tmp=tmp->prev) { - if (tmp->flag & SENS_VISIBLE) - break; - } - if (tmp) { - BLI_remlink(&base->object->sensors, sens); - BLI_insertlinkbefore(&base->object->sensors, tmp, sens); - } - } - else if ( val==2 && sens->next) { - for (tmp=sens->next; tmp; tmp=tmp->next) { - if (tmp->flag & SENS_VISIBLE) - break; - } - if (tmp) { - BLI_remlink(&base->object->sensors, sens); - BLI_insertlink(&base->object->sensors, tmp, sens); - } - } - ED_undo_push(C, "Move sensor"); - break; - } - - base= base->next; - } - } -} - -static void old_sca_move_controller(bContext *C, void *datav, void *move_up) -{ - /* deprecated, no longer using it (moved to sca.c) */ - Scene *scene= CTX_data_scene(C); - bController *controller_to_del= datav; - int val; - Base *base; - bController *cont, *tmp; - - //val= pupmenu("Move up%x1|Move down %x2"); - val = move_up ? 1:2; - - if (val>0) { - /* now find out which object has this ... */ - base= FIRSTBASE; - while (base) { - - cont= base->object->controllers.first; - while (cont) { - if (cont == controller_to_del) break; - cont= cont->next; - } - - if (cont) { - if ( val==1 && cont->prev) { - /* locate the controller that has the same state mask but is earlier in the list */ - tmp = cont->prev; - while (tmp) { - if (tmp->state_mask & cont->state_mask) - break; - tmp = tmp->prev; - } - if (tmp) { - BLI_remlink(&base->object->controllers, cont); - BLI_insertlinkbefore(&base->object->controllers, tmp, cont); - } - } - else if ( val==2 && cont->next) { - tmp = cont->next; - while (tmp) { - if (tmp->state_mask & cont->state_mask) - break; - tmp = tmp->next; - } - BLI_remlink(&base->object->controllers, cont); - BLI_insertlink(&base->object->controllers, tmp, cont); - } - ED_undo_push(C, "Move controller"); - break; - } - - base= base->next; - } - } -} - -static void old_sca_move_actuator(bContext *C, void *datav, void *move_up) -{ - /* deprecated, no longer using it (moved to sca.c) */ - Scene *scene= CTX_data_scene(C); - bActuator *actuator_to_move= datav; - int val; - Base *base; - bActuator *act, *tmp; - - //val= pupmenu("Move up%x1|Move down %x2"); - val = move_up ? 1:2; - - if (val>0) { - /* now find out which object has this ... */ - base= FIRSTBASE; - while (base) { - - act= base->object->actuators.first; - while (act) { - if (act == actuator_to_move) break; - act= act->next; - } - - if (act) { - if ( val==1 && act->prev) { - /* locate the first visible actuators before this one */ - for (tmp = act->prev; tmp; tmp=tmp->prev) { - if (tmp->flag & ACT_VISIBLE) - break; - } - if (tmp) { - BLI_remlink(&base->object->actuators, act); - BLI_insertlinkbefore(&base->object->actuators, tmp, act); - } - } - else if ( val==2 && act->next) { - for (tmp=act->next; tmp; tmp=tmp->next) { - if (tmp->flag & ACT_VISIBLE) - break; - } - if (tmp) { - BLI_remlink(&base->object->actuators, act); - BLI_insertlink(&base->object->actuators, tmp, act); - } - } - ED_undo_push(C, "Move actuator"); - break; - } - - base= base->next; - } - } -} - static void do_logic_buts(bContext *C, void *UNUSED(arg), int event) { Main *bmain= CTX_data_main(C); @@ -631,14 +459,6 @@ static const char *sensor_name(int type) return "unknown"; } -static const char *sensor_pup(void) -{ - /* the number needs to match defines in DNA_sensor_types.h */ - return "Sensors %t|Always %x0|Delay %x13|Keyboard %x3|Mouse %x5|" - "Touch %x1|Collision %x6|Near %x2|Radar %x7|" - "Property %x4|Random %x8|Ray %x9|Message %x10|Joystick %x11|Actuator %x12|Armature %x14"; -} - static const char *controller_name(int type) { switch (type) { @@ -662,11 +482,6 @@ static const char *controller_name(int type) return "unknown"; } -static const char *controller_pup(void) -{ - return "Controllers %t|AND %x0|OR %x1|XOR %x6|NAND %x4|NOR %x5|XNOR %x7|Expression %x2|Python %x3"; -} - static const char *actuator_name(int type) { switch (type) { @@ -713,41 +528,11 @@ static const char *actuator_name(int type) case ACT_ARMATURE: return "Armature"; case ACT_STEERING: - return "Steering"; + return "Steering"; } return "unknown"; } - - - -static const char *actuator_pup(Object *owner) -{ - switch (owner->type) { - case OB_ARMATURE: - return ("Actuators %t|Action %x15|Armature %x23|Motion %x0|Constraint %x9|Ipo %x1" - "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10" - "|Scene %x11|Random %x13|Message %x14|Game %x17" - "|Visibility %x18|2D Filter %x19|Parent %x20|State %x22"); - break; - - case OB_MESH: - return ("Actuators %t|Shape Action %x21|Motion %x0|Constraint %x9|Ipo %x1" - "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10" - "|Scene %x11|Random %x13|Message %x14|Game %x17" - "|Visibility %x18|2D Filter %x19|Parent %x20|State %x22"); - break; - - default: - return ("Actuators %t|Motion %x0|Constraint %x9|Ipo %x1" - "|Camera %x3|Sound %x5|Property %x6|Edit Object %x10" - "|Scene %x11|Random %x13|Message %x14|Game %x17" - "|Visibility %x18|2D Filter %x19|Parent %x20|State %x22"); - } -} - - - static void set_sca_ob(Object *ob) { bController *cont; @@ -897,7 +682,7 @@ static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisf ob= ob->id.next; } } - } + } /* now we count */ ob= bmain->object.first; @@ -906,8 +691,8 @@ static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisf ob= ob->id.next; } - if (*count==0) return NULL; - if (*count>24) *count= 24; /* temporal */ + if (*count == 0) return NULL; + if (*count > 24) *count = 24; /* temporal */ idar= MEM_callocN((*count)*sizeof(void *), "idar"); @@ -916,16 +701,16 @@ static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisf /* make the active object always the first one of the list */ if (obact) { - idar[0]= (ID *)obact; + idar[0] = (ID *)obact; nr++; } while (ob) { if ((ob->scavisflag) && (ob != obact)) { - idar[nr]= (ID *)ob; + idar[nr] = (ID *)ob; nr++; } - if (nr>=24) break; + if (nr >= 24) break; ob= ob->id.next; } @@ -935,151 +720,6 @@ static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisf return idar; } - -static int get_col_sensor(int type) -{ - /* XXX themecolors not here */ - - switch (type) { - case SENS_ALWAYS: return TH_PANEL; - case SENS_DELAY: return TH_PANEL; - case SENS_TOUCH: return TH_PANEL; - case SENS_COLLISION: return TH_PANEL; - case SENS_NEAR: return TH_PANEL; - case SENS_KEYBOARD: return TH_PANEL; - case SENS_PROPERTY: return TH_PANEL; - case SENS_ARMATURE: return TH_PANEL; - case SENS_ACTUATOR: return TH_PANEL; - case SENS_MOUSE: return TH_PANEL; - case SENS_RADAR: return TH_PANEL; - case SENS_RANDOM: return TH_PANEL; - case SENS_RAY: return TH_PANEL; - case SENS_MESSAGE: return TH_PANEL; - case SENS_JOYSTICK: return TH_PANEL; - default: return TH_PANEL; - } -} -static void set_col_sensor(int type, int medium) -{ - int col= get_col_sensor(type); - UI_ThemeColorShade(col, medium?30:0); -} - - -static void verify_logicbutton_func(bContext *UNUSED(C), void *data1, void *data2) -{ - bSensor *sens= (bSensor*)data1; - - if (sens->level && sens->tap) { - if (data2 == &(sens->level)) - sens->tap= 0; - else - sens->level= 0; - } -} - -static void test_scriptpoin_but(struct bContext *C, const char *name, ID **idpp) -{ - *idpp= BLI_findstring(&CTX_data_main(C)->text, name, offsetof(ID, name) + 2); -} - -static void test_actionpoin_but(struct bContext *C, const char *name, ID **idpp) -{ - *idpp= BLI_findstring(&CTX_data_main(C)->action, name, offsetof(ID, name) + 2); - if (*idpp) - id_us_plus(*idpp); -} - - -static void test_obpoin_but(struct bContext *C, const char *name, ID **idpp) -{ - *idpp= BLI_findstring(&CTX_data_main(C)->object, name, offsetof(ID, name) + 2); - if (*idpp) - id_lib_extern(*idpp); /* checks lib data, sets correct flag for saving then */ -} - -static void test_meshpoin_but(struct bContext *C, const char *name, ID **idpp) -{ - *idpp= BLI_findstring(&CTX_data_main(C)->mesh, name, offsetof(ID, name) + 2); - if (*idpp) - id_us_plus(*idpp); -} - -static void test_matpoin_but(struct bContext *C, const char *name, ID **idpp) -{ - *idpp= BLI_findstring(&CTX_data_main(C)->mat, name, offsetof(ID, name) + 2); - if (*idpp) - id_us_plus(*idpp); -} - -static void test_scenepoin_but(struct bContext *C, const char *name, ID **idpp) -{ - *idpp= BLI_findstring(&CTX_data_main(C)->scene, name, offsetof(ID, name) + 2); - if (*idpp) - id_us_plus(*idpp); -} - -static void test_keyboard_event(struct bContext *UNUSED(C), void *arg_ks, void *UNUSED(arg)) -{ - bKeyboardSensor *ks= (bKeyboardSensor*)arg_ks; - - if (!ISKEYBOARD(ks->key)) - ks->key= 0; - if (!ISKEYBOARD(ks->qual)) - ks->qual= 0; - if (!ISKEYBOARD(ks->qual2)) - ks->qual2= 0; -} - -/** - * Draws a toggle for pulse mode, a frequency field and a toggle to invert - * the value of this sensor. Operates on the shared data block of sensors. - */ -static void draw_default_sensor_header(bSensor *sens, - uiBlock *block, - short x, - short y, - short w) -{ - uiBut *but; - - /* Pulsing and frequency */ - uiBlockBeginAlign(block); - uiDefIconButBitS(block, TOG, SENS_PULSE_REPEAT, 1, ICON_DOTSUP, - (short)(x + 10 + 0.0 * (w - 20)), (short)(y - 21), (short)(0.1 * (w - 20)), 19, - &sens->pulse, 0.0, 0.0, 0, 0, - "Activate TRUE level triggering (pulse mode)"); - - uiDefIconButBitS(block, TOG, SENS_NEG_PULSE_MODE, 1, ICON_DOTSDOWN, - (short)(x + 10 + 0.1 * (w-20)), (short)(y - 21), (short)(0.1 * (w-20)), 19, - &sens->pulse, 0.0, 0.0, 0, 0, - "Activate FALSE level triggering (pulse mode)"); - uiDefButS(block, NUM, 1, "f:", - (short)(x + 10 + 0.2 * (w-20)), (short)(y - 21), (short)(0.275 * (w-20)), 19, - &sens->freq, 0.0, 10000.0, 0, 0, - "Delay between repeated pulses (in logic tics, 0 = no delay)"); - uiBlockEndAlign(block); - - /* value or shift? */ - uiBlockBeginAlign(block); - but = uiDefButS(block, TOG, 1, "Level", - (short)(x + 10 + 0.5 * (w-20)), (short)(y - 21), (short)(0.20 * (w-20)), 19, - &sens->level, 0.0, 0.0, 0, 0, - "Level detector, trigger controllers of new states (only applicable upon logic state transition)"); - uiButSetFunc(but, verify_logicbutton_func, sens, &(sens->level)); - but = uiDefButS(block, TOG, 1, "Tap", - (short)(x + 10 + 0.702 * (w-20)), (short)(y - 21), (short)(0.12 * (w-20)), 19, - &sens->tap, 0.0, 0.0, 0, 0, - "Trigger controllers only for an instant, even while the sensor remains true"); - uiButSetFunc(but, verify_logicbutton_func, sens, &(sens->tap)); - uiBlockEndAlign(block); - - uiDefButS(block, TOG, 1, "Inv", - (short)(x + 10 + 0.85 * (w-20)), (short)(y - 21), (short)(0.15 * (w-20)), 19, - &sens->invert, 0.0, 0.0, 0, 0, - "Invert the level (output) of this sensor"); -} - static void get_armature_bone_constraint(Object *ob, const char *posechannel, const char *constraint_name, bConstraint **constraint) { /* check that bone exist in the active object */ @@ -1094,1848 +734,6 @@ static void get_armature_bone_constraint(Object *ob, const char *posechannel, co } /* didn't find any */ } -static void check_armature_bone_constraint(Object *ob, char *posechannel, char *constraint) -{ - /* check that bone exist in the active object */ - if (ob->type == OB_ARMATURE && ob->pose) { - bPoseChannel *pchan; - bPose *pose = ob->pose; - for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) { - if (!strcmp(pchan->name, posechannel)) { - /* found it, now look for constraint channel */ - bConstraint *con; - for (con=pchan->constraints.first; con; con=con->next) { - if (!strcmp(con->name, constraint)) { - /* found it, all ok */ - return; - } - } - /* didn't find constraint, make empty */ - constraint[0] = 0; - return; - } - } - } - /* didn't find any */ - posechannel[0] = 0; - constraint[0] = 0; -} - -static void check_armature_sensor(bContext *C, void *arg1_but, void *arg2_sens) -{ - bArmatureSensor *sens = arg2_sens; - uiBut *but = arg1_but; - Object *ob= CTX_data_active_object(C); - - /* check that bone exist in the active object */ - but->retval = B_REDR; - check_armature_bone_constraint(ob, sens->posechannel, sens->constraint); -} - -static short draw_sensorbuttons(Object *ob, bSensor *sens, uiBlock *block, short xco, short yco, short width) -{ - bNearSensor *ns = NULL; - bTouchSensor *ts = NULL; - bKeyboardSensor *ks = NULL; - bPropertySensor *ps = NULL; - bArmatureSensor *arm = NULL; - bMouseSensor *ms = NULL; - bCollisionSensor *cs = NULL; - bRadarSensor *rs = NULL; - bRandomSensor *randomSensor = NULL; - bRaySensor *raySens = NULL; - bMessageSensor *mes = NULL; - bJoystickSensor *joy = NULL; - bActuatorSensor *as = NULL; - bDelaySensor *ds = NULL; - uiBut *but; - short ysize; - const char *str; - - /* yco is at the top of the rect, draw downwards */ - - set_col_sensor(sens->type, 0); - - switch (sens->type) { - case SENS_ALWAYS: - { - ysize= 24; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - draw_default_sensor_header(sens, block, xco, yco, width); - - yco-= ysize; - - break; - } - case SENS_TOUCH: - { - ysize= 48; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - draw_default_sensor_header(sens, block, xco, yco, width); - - ts= sens->data; - - // uiDefBut(block, TEX, 1, "Property:", xco, yco-22, width, 19, &ts->name, 0, MAX_NAME, 0, 0, "Only look for Objects with this property"); - uiDefIDPoinBut(block, test_matpoin_but, ID_MA, 1, "MA:", (short)(xco + 10), (short)(yco-44), (short)(width - 20), 19, &ts->ma, "Only look for floors with this Material"); - // uiDefButF(block, NUM, 1, "Margin:", xco+width/2, yco-44, width/2, 19, &ts->dist, 0.0, 10.0, 100, 0, "Extra margin (distance) for larger sensitivity"); - yco-= ysize; - break; - } - case SENS_COLLISION: - { - ysize= 48; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - draw_default_sensor_header(sens, block, xco, yco, width); - cs= sens->data; - - /* The collision sensor will become a generic collision (i.e. it */ - /* absorb the old touch sensor). */ - - uiDefButBitS(block, TOG, SENS_COLLISION_PULSE, B_REDR, "Pulse", (short)(xco + 10), (short)(yco - 44), - (short)(0.20 * (width-20)), 19, &cs->mode, 0.0, 0.0, 0, 0, - "Changes to the set of colliding objects generated pulses"); - - uiDefButBitS(block, TOG, SENS_COLLISION_MATERIAL, B_REDR, "M/P", (short)(xco + 10 + (0.20 * (width-20))), (short)(yco - 44), - (short)(0.20 * (width-20)), 19, &cs->mode, 0.0, 0.0, 0, 0, - "Toggle collision on material or property"); - - if (cs->mode & SENS_COLLISION_MATERIAL) { - uiDefBut(block, TEX, 1, "Material:", (short)(xco + 10 + 0.40 * (width-20)), - (short)(yco-44), (short)(0.6*(width-20)), 19, &cs->materialName, 0, MAX_NAME, 0, 0, - "Only look for Objects with this material"); - } - else { - uiDefBut(block, TEX, 1, "Property:", (short)(xco + 10 + 0.40 * (width-20)), (short)(yco-44), - (short)(0.6*(width-20)), 19, &cs->name, 0, MAX_NAME, 0, 0, - "Only look for Objects with this property"); - } - - /* uiDefButS(block, NUM, 1, "Damp:", xco+10+width-90, yco-24, 70, 19, &cs->damp, 0, 250, 0, 0, "For 'damp' time don't detect another collision"); */ - - yco-= ysize; - break; - } - case SENS_NEAR: - { - ysize= 72; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - draw_default_sensor_header(sens, block, xco, yco, width); - ns= sens->data; - - uiDefBut(block, TEX, 1, "Property:", (short)(10+xco), (short)(yco-44), (short)(width-20), 19, - &ns->name, 0, MAX_NAME, 0, 0, "Only look for Objects with this property"); - uiDefButF(block, NUM, 1, "Dist", (short)(10+xco), (short)(yco-68), (short)((width-22)/2), 19, - &ns->dist, 0.0, 1000.0, 1000, 0, "Trigger distance"); - uiDefButF(block, NUM, 1, "Reset", (short)(10+xco+(width-22)/2), (short)(yco-68), (short)((width-22)/2), 19, - &ns->resetdist, 0.0, 1000.0, 1000, 0, "Reset distance"); - yco-= ysize; - break; - } - case SENS_RADAR: - { - ysize= 72; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - draw_default_sensor_header(sens, block, xco, yco, width); - - rs= sens->data; - - uiDefBut(block, TEX, 1, "Prop:", - (short)(10+xco), (short)(yco-44), (short)(0.7 * (width-20)), 19, - &rs->name, 0, MAX_NAME, 0, 0, - "Only look for Objects with this property"); - - str = "Type %t|+X axis %x0|+Y axis %x1|+Z axis %x2|-X axis %x3|-Y axis %x4|-Z axis %x5"; - uiDefButS(block, MENU, B_REDR, str, - (short)(10+xco+0.7 * (width-20)), (short)(yco-44), (short)(0.3 * (width-22)), 19, - &rs->axis, 2.0, 31, 0, 0, - "Specify along which axis the radar cone is cast"); - - uiDefButF(block, NUM, 1, "Ang:", - (short)(10+xco), (short)(yco-68), (short)((width-20)/2), 19, - &rs->angle, 0.0, 179.9, 10, 0, - "Opening angle of the radar cone"); - uiDefButF(block, NUM, 1, "Dist:", - (short)(xco+10 + (width-20)/2), (short)(yco-68), (short)((width-20)/2), 19, - &rs->range, 0.01, 10000.0, 100, 0, - "Depth of the radar cone"); - yco-= ysize; - break; - } - case SENS_KEYBOARD: - { - ks= sens->data; - - /* 5 lines: 120 height */ - ysize= (ks->type&1) ? 96:120; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - /* header line */ - draw_default_sensor_header(sens, block, xco, yco, width); - - /* part of line 1 */ - uiDefBut(block, LABEL, 0, "Key", xco, yco-44, 40, 19, NULL, 0, 0, 0, 0, ""); - uiDefButBitS(block, TOG, 1, B_REDR, "All keys", xco+40+(width/2), yco-44, (width/2)-50, 19, - &ks->type, 0, 0, 0, 0, ""); - - - if ((ks->type&1)==0) { /* is All Keys option off? */ - /* line 2: hotkey and allkeys toggle */ - but = uiDefKeyevtButS(block, 0, "", xco+40, yco-44, (width)/2, 19, &ks->key, "Key code"); - uiButSetFunc(but, test_keyboard_event, ks, NULL); - - /* line 3: two key modifyers (qual1, qual2) */ - uiDefBut(block, LABEL, 0, "Hold", xco, yco-68, 40, 19, NULL, 0, 0, 0, 0, ""); - but = uiDefKeyevtButS(block, 0, "", xco+40, yco-68, (width-50)/2, 19, &ks->qual, "Modifier key code"); - uiButSetFunc(but, test_keyboard_event, ks, NULL); - but = uiDefKeyevtButS(block, 0, "", xco+40+(width-50)/2, yco-68, (width-50)/2, 19, &ks->qual2, "Second Modifier key code"); - uiButSetFunc(but, test_keyboard_event, ks, NULL); - } - - /* line 4: toggle property for string logging mode */ - uiDefBut(block, TEX, 1, "LogToggle: ", - xco+10, yco-((ks->type&1) ? 68:92), (width-20), 19, - ks->toggleName, 0, MAX_NAME, 0, 0, - "Property that indicates whether to log " - "keystrokes as a string"); - - /* line 5: target property for string logging mode */ - uiDefBut(block, TEX, 1, "Target: ", - xco+10, yco-((ks->type&1) ? 92:116), (width-20), 19, - ks->targetName, 0, MAX_NAME, 0, 0, - "Property that receives the keystrokes in case " - "a string is logged"); - - yco-= ysize; - break; - } - case SENS_PROPERTY: - { - ysize= 96; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, - (float)xco+width, (float)yco, 1); - - draw_default_sensor_header(sens, block, xco, yco, width); - ps= sens->data; - - str= "Type %t|Equal %x0|Not Equal %x1|Interval %x2|Changed %x3"; - /* str= "Type %t|Equal %x0|Not Equal %x1"; */ - uiDefButI(block, MENU, B_REDR, str, xco+30, yco-44, width-60, 19, - &ps->type, 0, 31, 0, 0, "Type"); - - if (ps->type != SENS_PROP_EXPRESSION) { - uiDefBut(block, TEX, 1, "Prop: ", xco+30, yco-68, width-60, 19, - ps->name, 0, MAX_NAME, 0, 0, "Property name"); - } - - if (ps->type == SENS_PROP_INTERVAL) { - uiDefBut(block, TEX, 1, "Min: ", xco, yco-92, width/2, 19, - ps->value, 0, MAX_NAME, 0, 0, "check for min value"); - uiDefBut(block, TEX, 1, "Max: ", xco+width/2, yco-92, width/2, 19, - ps->maxvalue, 0, MAX_NAME, 0, 0, "check for max value"); - } - else if (ps->type == SENS_PROP_CHANGED) { - /* pass */ - } - else { - uiDefBut(block, TEX, 1, "Value: ", xco+30, yco-92, width-60, 19, - ps->value, 0, MAX_NAME, 0, 0, "check for value"); - } - - yco-= ysize; - break; - } - case SENS_ARMATURE: - { - ysize= 70; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, - (float)xco+width, (float)yco, 1); - - draw_default_sensor_header(sens, block, xco, yco, width); - arm= sens->data; - - if (ob->type == OB_ARMATURE) { - uiBlockBeginAlign(block); - but = uiDefBut(block, TEX, 1, "Bone: ", - (xco+10), (yco-44), (width-20)/2, 19, - arm->posechannel, 0, MAX_NAME, 0, 0, - "Bone on which you want to check a constraint"); - uiButSetFunc(but, check_armature_sensor, but, arm); - but = uiDefBut(block, TEX, 1, "Cons: ", - (xco+10)+(width-20)/2, (yco-44), (width-20)/2, 19, - arm->constraint, 0, MAX_NAME, 0, 0, - "Name of the constraint you want to control"); - uiButSetFunc(but, check_armature_sensor, but, arm); - uiBlockEndAlign(block); - - str= "Type %t|State changed %x0|Lin error below %x1|Lin error above %x2|Rot error below %x3|Rot error above %x4"; - - uiDefButI(block, MENU, B_REDR, str, xco+10, yco-66, 0.4*(width-20), 19, - &arm->type, 0, 31, 0, 0, "Type"); - - if (arm->type != SENS_ARM_STATE_CHANGED) { - uiDefButF(block, NUM, 1, "Value: ", xco+10+0.4*(width-20), yco-66, 0.6*(width-20), 19, - &arm->value, -10000.0, 10000.0, 100, 0, "Test the error against this value"); - } - } - yco-= ysize; - break; - } - case SENS_ACTUATOR: - { - ysize= 48; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, - (float)xco+width, (float)yco, 1); - - draw_default_sensor_header(sens, block, xco, yco, width); - as= sens->data; - - uiDefBut(block, TEX, 1, "Act: ", xco+30, yco-44, width-60, 19, - as->name, 0, MAX_NAME, 0, 0, "Actuator name, actuator active state modifications will be detected"); - yco-= ysize; - break; - } - case SENS_DELAY: - { - ysize= 48; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, - (float)xco+width, (float)yco, 1); - - draw_default_sensor_header(sens, block, xco, yco, width); - ds = sens->data; - - uiDefButS(block, NUM, 0, "Delay", (short)(10+xco), (short)(yco-44), (short)((width-22)*0.4+10), 19, - &ds->delay, 0.0, 5000.0, 0, 0, "Delay in number of logic tics before the positive trigger (default 60 per second)"); - uiDefButS(block, NUM, 0, "Dur", (short)(10+xco+(width-22)*0.4+10), (short)(yco-44), (short)((width-22)*0.4-10), 19, - &ds->duration, 0.0, 5000.0, 0, 0, "If >0, delay in number of logic tics before the negative trigger following the positive trigger"); - uiDefButBitS(block, TOG, SENS_DELAY_REPEAT, 0, "REP", (short)(xco + 10 + (width-22)*0.8), (short)(yco - 44), - (short)(0.20 * (width-22)), 19, &ds->flag, 0.0, 0.0, 0, 0, - "Toggle repeat option. If selected, the sensor restarts after Delay+Dur logic tics"); - yco-= ysize; - break; - } - case SENS_MOUSE: - { - ms= sens->data; - /* Two lines: 48 pixels high. */ - ysize = 48; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - /* line 1: header */ - draw_default_sensor_header(sens, block, xco, yco, width); - - /* Line 2: type selection. The number are a bit mangled to get - * proper compatibility with older .blend files. */ - - /* Any sensor type default is 0 but the ms enum starts in 1. - * Therefore the mouse sensor is initialized to 1 in sca.c */ - str= "Type %t|Left button %x1|Middle button %x2|" - "Right button %x4|Wheel Up %x5|Wheel Down %x6|Movement %x8|Mouse over %x16|Mouse over any%x32"; - uiDefButS(block, MENU, B_REDR, str, xco+10, yco-44, (width*0.8f)-20, 19, - &ms->type, 0, 31, 0, 0, - "Specify the type of event this mouse sensor should trigger on"); - - if (ms->type==32) { - uiDefButBitS(block, TOG, SENS_MOUSE_FOCUS_PULSE, B_REDR, "Pulse", (short)(xco + 10) + (width*0.8f)-20, (short)(yco - 44), - (short)(0.20 * (width-20)), 19, &ms->flag, 0.0, 0.0, 0, 0, - "Moving the mouse over a different object generates a pulse"); - } - - yco-= ysize; - break; - } - case SENS_RANDOM: - { - ysize = 48; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - draw_default_sensor_header(sens, block, xco, yco, width); - randomSensor = sens->data; - /* some files were wrongly written, avoid crash now */ - if (randomSensor) { - uiDefButI(block, NUM, 1, "Seed: ", xco+10, yco-44, (width-20), 19, - &randomSensor->seed, 0, 1000, 0, 0, - "Initial seed of the generator. (Choose 0 for not random)"); - } - yco-= ysize; - break; - } - case SENS_RAY: - { - ysize = 72; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - draw_default_sensor_header(sens, block, xco, yco, width); - raySens = sens->data; - - /* 1. property or material */ - uiDefButBitS(block, TOG, SENS_COLLISION_MATERIAL, B_REDR, "M/P", - xco + 10, yco - 44, 0.20 * (width-20), 19, - &raySens->mode, 0.0, 0.0, 0, 0, - "Toggle collision on material or property"); - - if (raySens->mode & SENS_COLLISION_MATERIAL) { - uiDefBut(block, TEX, 1, "Material:", xco + 10 + 0.20 * (width-20), yco-44, 0.8*(width-20), 19, - &raySens->matname, 0, MAX_NAME, 0, 0, - "Only look for Objects with this material"); - } - else { - uiDefBut(block, TEX, 1, "Property:", xco + 10 + 0.20 * (width-20), yco-44, 0.8*(width-20), 19, - &raySens->propname, 0, MAX_NAME, 0, 0, - "Only look for Objects with this property"); - } - - /* X-Ray option */ - uiDefButBitS(block, TOG, SENS_RAY_XRAY, 1, "X", - xco + 10, yco - 68, 0.10 * (width-20), 19, - &raySens->mode, 0.0, 0.0, 0, 0, - "Toggle X-Ray option (see through objects that don't have the property)"); - /* 2. sensing range */ - uiDefButF(block, NUM, 1, "Range", xco+10 + 0.10 * (width-20), yco-68, 0.5 * (width-20), 19, - &raySens->range, 0.01, 10000.0, 100, 0, - "Sense objects no farther than this distance"); - - /* 3. axis choice */ - str = "Type %t|+ X axis %x1|+ Y axis %x0|+ Z axis %x2|- X axis %x3|- Y axis %x4|- Z axis %x5"; - uiDefButI(block, MENU, B_REDR, str, xco+10 + 0.6 * (width-20), yco-68, 0.4 * (width-20), 19, - &raySens->axisflag, 2.0, 31, 0, 0, - "Specify along which axis the ray is cast"); - - yco-= ysize; - break; - } - case SENS_MESSAGE: - { - mes = sens->data; - ysize = 2 * 24; /* total number of lines * 24 pixels/line */ - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, - (float)xco+width, (float)yco, 1); - - /* line 1: header line */ - draw_default_sensor_header(sens, block, xco, yco, width); - - /* line 2: Subject filter */ - uiDefBut(block, TEX, 1, "Subject: ", - (xco+10), (yco-44), (width-20), 19, - mes->subject, 0, MAX_NAME, 0, 0, - "Optional subject filter: only accept messages with this subject" - ", or empty for all"); - - yco -= ysize; - break; - } - case SENS_JOYSTICK: - { - - ysize = 72; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - /* line 1: header */ - draw_default_sensor_header(sens, block, xco, yco, width); - - joy= sens->data; - - uiDefButC(block, NUM, 1, "Index:", xco+10, yco-44, 0.33 * (width-20), 19, - &joy->joyindex, 0, SENS_JOY_MAXINDEX-1, 100, 0, - "Specify which joystick to use"); - - str= "Type %t|Button %x0|Axis %x1|Single Axis %x3|Hat%x2"; - uiDefButC(block, MENU, B_REDR, str, xco+87, yco-44, 0.26 * (width-20), 19, - &joy->type, 0, 31, 0, 0, - "The type of event this joystick sensor is triggered on"); - - if (joy->type != SENS_JOY_AXIS_SINGLE) { - if (joy->flag & SENS_JOY_ANY_EVENT) { - switch (joy->type) { - case SENS_JOY_AXIS: - str = "All Axis Events"; - break; - case SENS_JOY_BUTTON: - str = "All Button Events"; - break; - default: - str = "All Hat Events"; - break; - } - } - else { - str = "All"; - } - - uiDefButBitS(block, TOG, SENS_JOY_ANY_EVENT, B_REDR, str, - xco+10 + 0.475 * (width-20), yco-68, ((joy->flag & SENS_JOY_ANY_EVENT) ? 0.525 : 0.12) * (width-20), 19, - &joy->flag, 0, 0, 0, 0, - "Triggered by all events on this joysticks current type (axis/button/hat)"); - } - if (joy->type == SENS_JOY_BUTTON) { - if ((joy->flag & SENS_JOY_ANY_EVENT)==0) { - uiDefButI(block, NUM, 1, "Number:", xco+10 + 0.6 * (width-20), yco-68, 0.4 * (width-20), 19, - &joy->button, 0, 18, 100, 0, - "Specify which button to use"); - } - } - else if (joy->type == SENS_JOY_AXIS) { - uiDefButS(block, NUM, 1, "Number:", xco+10, yco-68, 0.46 * (width-20), 19, - &joy->axis, 1, 8.0, 100, 0, - "Specify which axis pair to use, 1 is useually the main direction input"); - - uiDefButI(block, NUM, 1, "Threshold:", xco+10 + 0.6 * (width-20), yco-44, 0.4 * (width-20), 19, - &joy->precision, 0, 32768.0, 100, 0, - "Specify the precision of the axis"); - - if ((joy->flag & SENS_JOY_ANY_EVENT)==0) { - str = "Type %t|Up Axis %x1 |Down Axis %x3|Left Axis %x2|Right Axis %x0"; - uiDefButI(block, MENU, B_REDR, str, xco+10 + 0.6 * (width-20), yco-68, 0.4 * (width-20), 19, - &joy->axisf, 2.0, 31, 0, 0, - "The direction of the axis, use 'All Events' to receive events on any direction"); - } - } - else if (joy->type == SENS_JOY_HAT) { - uiDefButI(block, NUM, 1, "Number:", xco+10, yco-68, 0.46 * (width-20), 19, - &joy->hat, 1, 4.0, 100, 0, - "Specify which hat to use"); - - if ((joy->flag & SENS_JOY_ANY_EVENT)==0) { - str = "Direction%t|Up%x1|Down%x4|Left%x8|Right%x2|%l|Up/Right%x3|Down/Left%x12|Up/Left%x9|Down/Right%x6"; - uiDefButI(block, MENU, 0, str, xco+10 + 0.6 * (width-20), yco-68, 0.4 * (width-20), 19, - &joy->hatf, 2.0, 31, 0, 0, - "The direction of the hat, use 'All Events' to receive events on any direction"); - } - } - else { /* (joy->type == SENS_JOY_AXIS_SINGLE)*/ - uiDefButS(block, NUM, 1, "Number:", xco+10, yco-68, 0.46 * (width-20), 19, - &joy->axis_single, 1, 16.0, 100, 0, - "Specify a single axis (verticle/horizontal/other) to detect"); - - uiDefButI(block, NUM, 1, "Threshold:", xco+10 + 0.6 * (width-20), yco-44, 0.4 * (width-20), 19, - &joy->precision, 0, 32768.0, 100, 0, - "Specify the precision of the axis"); - } - yco-= ysize; - break; - } - } - - return yco-4; -} - - - -static short draw_controllerbuttons(bController *cont, uiBlock *block, short xco, short yco, short width) -{ - bExpressionCont *ec; - bPythonCont *pc; - short ysize; - - switch (cont->type) { - case CONT_EXPRESSION: - ysize= 28; - - UI_ThemeColor(TH_PANEL); - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - /* uiDefBut(block, LABEL, 1, "Not yet...", xco, yco-24, 80, 19, NULL, 0, 0, 0, 0, ""); */ - ec= cont->data; - /* uiDefBut(block, BUT, 1, "Variables", xco, yco-24, 80, 19, NULL, 0, 0, 0, 0, "Available variables for expression"); */ - uiDefBut(block, TEX, 1, "Exp:", xco + 10, yco-21, width-20, 19, - ec->str, 0, sizeof(ec->str), 0, 0, - "Expression"); - - yco-= ysize; - break; - case CONT_PYTHON: - ysize= 28; - - if (cont->data==NULL) init_controller(cont); - pc= cont->data; - - UI_ThemeColor(TH_PANEL); - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - - uiBlockBeginAlign(block); - uiDefButI(block, MENU, B_REDR, "Execution Method%t|Script%x0|Module%x1", xco+4, yco-23, 66, 19, &pc->mode, 0, 0, 0, 0, "Python script type (textblock or module - faster)"); - if (pc->mode==0) - uiDefIDPoinBut(block, test_scriptpoin_but, ID_TXT, 1, "", xco+70, yco-23, width-74, 19, &pc->text, "Blender textblock to run as a script"); - else { - uiDefBut(block, TEX, 1, "", xco+70, yco-23, (width-70)-25, 19, pc->module, 0, sizeof(pc->module), 0, 0, "Module name and function to run e.g. \"someModule.main\". Internal texts and external python files can be used"); - uiDefButBitI(block, TOG, CONT_PY_DEBUG, B_REDR, "D", (xco+width)-25, yco-23, 19, 19, &pc->flag, 0, 0, 0, 0, "Continuously reload the module from disk for editing external modules without restarting"); - } - uiBlockEndAlign(block); - - yco-= ysize; - break; - - default: - ysize= 4; - - UI_ThemeColor(TH_PANEL); - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - yco-= ysize; - } - - return yco; -} - -static int get_col_actuator(int type) -{ - switch (type) { - case ACT_ACTION: return TH_PANEL; - case ACT_SHAPEACTION: return TH_PANEL; - case ACT_OBJECT: return TH_PANEL; - case ACT_IPO: return TH_PANEL; - case ACT_PROPERTY: return TH_PANEL; - case ACT_SOUND: return TH_PANEL; - case ACT_CAMERA: return TH_PANEL; - case ACT_EDIT_OBJECT: return TH_PANEL; - case ACT_GROUP: return TH_PANEL; - case ACT_RANDOM: return TH_PANEL; - case ACT_SCENE: return TH_PANEL; - case ACT_MESSAGE: return TH_PANEL; - case ACT_GAME: return TH_PANEL; - case ACT_VISIBILITY: return TH_PANEL; - case ACT_CONSTRAINT: return TH_PANEL; - case ACT_STATE: return TH_PANEL; - case ACT_ARMATURE: return TH_PANEL; - case ACT_STEERING: return TH_PANEL; - default: return TH_PANEL; - } -} -static void set_col_actuator(int item, int medium) -{ - int col= get_col_actuator(item); - UI_ThemeColorShade(col, medium?30:10); - -} - -static void change_object_actuator(bContext *UNUSED(C), void *act, void *UNUSED(arg)) -{ - bObjectActuator *oa = act; - - if (oa->type != oa->otype) { - switch (oa->type) { - case ACT_OBJECT_NORMAL: - memset(oa, 0, sizeof(bObjectActuator)); - oa->flag = ACT_FORCE_LOCAL|ACT_TORQUE_LOCAL|ACT_DLOC_LOCAL|ACT_DROT_LOCAL; - oa->type = ACT_OBJECT_NORMAL; - break; - - case ACT_OBJECT_SERVO: - memset(oa, 0, sizeof(bObjectActuator)); - oa->flag = ACT_LIN_VEL_LOCAL; - oa->type = ACT_OBJECT_SERVO; - oa->forcerot[0] = 30.0f; - oa->forcerot[1] = 0.5f; - oa->forcerot[2] = 0.0f; - break; - } - } -} - -static void change_ipo_actuator(bContext *UNUSED(C), void *arg1_but, void *arg2_ia) -{ - bIpoActuator *ia = arg2_ia; - uiBut *but = arg1_but; - - if (but->retval & ACT_IPOFORCE) - ia->flag &= ~ACT_IPOADD; - else if (but->retval & ACT_IPOADD) - ia->flag &= ~ACT_IPOFORCE; - but->retval = B_REDR; -} - -static void update_object_actuator_PID(bContext *UNUSED(C), void *act, void *UNUSED(arg)) -{ - bObjectActuator *oa = act; - oa->forcerot[0] = 60.0f*oa->forcerot[1]; -} - -static char *get_state_name(Object *ob, short bit) -{ - bController *cont; - unsigned int mask; - - mask = (1<controllers.first; - while (cont) { - if (cont->state_mask & mask) { - return cont->name; - } - cont = cont->next; - } - return (char*)""; -} - -static void check_state_mask(bContext *C, void *arg1_but, void *arg2_mask) -{ - wmWindow *win= CTX_wm_window(C); - int shift= win->eventstate->shift; - unsigned int *cont_mask = arg2_mask; - uiBut *but = arg1_but; - - if (*cont_mask == 0 || !(shift)) - *cont_mask = (1<retval); - but->retval = B_REDR; -} - -static void check_armature_actuator(bContext *C, void *arg1_but, void *arg2_act) -{ - bArmatureActuator *act = arg2_act; - uiBut *but = arg1_but; - Object *ob= CTX_data_active_object(C); - - /* check that bone exist in the active object */ - but->retval = B_REDR; - check_armature_bone_constraint(ob, act->posechannel, act->constraint); -} - - -static short draw_actuatorbuttons(Main *bmain, Object *ob, bActuator *act, uiBlock *block, short xco, short yco, short width) -{ - bSoundActuator *sa = NULL; - bObjectActuator *oa = NULL; - bIpoActuator *ia = NULL; - bPropertyActuator *pa = NULL; - bCameraActuator *ca = NULL; - bEditObjectActuator *eoa = NULL; - bConstraintActuator *coa = NULL; - bSceneActuator *sca = NULL; - bGroupActuator *ga = NULL; - bRandomActuator *randAct = NULL; - bMessageActuator *ma = NULL; - bActionActuator *aa = NULL; - bGameActuator *gma = NULL; - bVisibilityActuator *visAct = NULL; - bTwoDFilterActuator *tdfa = NULL; - bParentActuator *parAct = NULL; - bStateActuator *staAct = NULL; - bArmatureActuator *armAct = NULL; - - float *fp; - short ysize = 0, wval; - const char *str; - int myline, stbit; - uiBut *but; - - - /* yco is at the top of the rect, draw downwards */ - set_col_actuator(act->type, 0); - - switch (act->type) { - case ACT_OBJECT: - { - oa = act->data; - wval = (width-100)/3; - if (oa->type == ACT_OBJECT_NORMAL) { - if (ob->gameflag & OB_DYNAMIC) { - ysize= 175; - } - else { - ysize= 72; - } - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - uiBlockBeginAlign(block); - uiDefBut(block, LABEL, 0, "Loc", xco, yco-45, 45, 19, NULL, 0, 0, 0, 0, "Sets the location"); - uiDefButF(block, NUM, 0, "", xco+45, yco-45, wval, 19, oa->dloc, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-45, wval, 19, oa->dloc+1, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-45, wval, 19, oa->dloc+2, -10000.0, 10000.0, 10, 0, ""); - uiBlockEndAlign(block); - - uiDefBut(block, LABEL, 0, "Rot", xco, yco-64, 45, 19, NULL, 0, 0, 0, 0, "Sets the rotation"); - uiBlockBeginAlign(block); - uiDefButF(block, NUM, 0, "", xco+45, yco-64, wval, 19, oa->drot, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-64, wval, 19, oa->drot+1, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-64, wval, 19, oa->drot+2, -10000.0, 10000.0, 10, 0, ""); - uiBlockEndAlign(block); - - uiDefButBitS(block, TOG, ACT_DLOC_LOCAL, 0, "L", xco+45+3*wval, yco-45, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); - uiDefButBitS(block, TOG, ACT_DROT_LOCAL, 0, "L", xco+45+3*wval, yco-64, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); - - if (ob->gameflag & OB_DYNAMIC) { - uiDefBut(block, LABEL, 0, "Force", xco, yco-87, 55, 19, NULL, 0, 0, 0, 0, "Sets the force"); - uiBlockBeginAlign(block); - uiDefButF(block, NUM, 0, "", xco+45, yco-87, wval, 19, oa->forceloc, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-87, wval, 19, oa->forceloc+1, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-87, wval, 19, oa->forceloc+2, -10000.0, 10000.0, 10, 0, ""); - uiBlockEndAlign(block); - - uiDefBut(block, LABEL, 0, "Torque", xco, yco-106, 55, 19, NULL, 0, 0, 0, 0, "Sets the torque"); - uiBlockBeginAlign(block); - uiDefButF(block, NUM, 0, "", xco+45, yco-106, wval, 19, oa->forcerot, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-106, wval, 19, oa->forcerot+1, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-106, wval, 19, oa->forcerot+2, -10000.0, 10000.0, 10, 0, ""); - uiBlockEndAlign(block); - } - - if (ob->gameflag & OB_DYNAMIC) { - uiDefBut(block, LABEL, 0, "LinV", xco, yco-129, 45, 19, NULL, 0, 0, 0, 0, "Sets the linear velocity"); - uiBlockBeginAlign(block); - uiDefButF(block, NUM, 0, "", xco+45, yco-129, wval, 19, oa->linearvelocity, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-129, wval, 19, oa->linearvelocity+1, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-129, wval, 19, oa->linearvelocity+2, -10000.0, 10000.0, 10, 0, ""); - uiBlockEndAlign(block); - - uiDefBut(block, LABEL, 0, "AngV", xco, yco-148, 45, 19, NULL, 0, 0, 0, 0, "Sets the angular velocity"); - uiBlockBeginAlign(block); - uiDefButF(block, NUM, 0, "", xco+45, yco-148, wval, 19, oa->angularvelocity, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-148, wval, 19, oa->angularvelocity+1, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-148, wval, 19, oa->angularvelocity+2, -10000.0, 10000.0, 10, 0, ""); - uiBlockEndAlign(block); - - uiDefBut(block, LABEL, 0, "Damp", xco, yco-171, 45, 19, NULL, 0, 0, 0, 0, "Number of frames to reach the target velocity"); - uiDefButS(block, NUM, 0, "", xco+45, yco-171, wval, 19, &oa->damping, 0.0, 1000.0, 100, 0, ""); - - uiDefButBitS(block, TOG, ACT_FORCE_LOCAL, 0, "L", xco+45+3*wval, yco-87, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); - uiDefButBitS(block, TOG, ACT_TORQUE_LOCAL, 0, "L", xco+45+3*wval, yco-106, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); - uiDefButBitS(block, TOG, ACT_LIN_VEL_LOCAL, 0, "L", xco+45+3*wval, yco-129, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); - uiDefButBitS(block, TOG, ACT_ANG_VEL_LOCAL, 0, "L", xco+45+3*wval, yco-148, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Local transformation"); - - uiDefButBitS(block, TOG, ACT_ADD_LIN_VEL, 0, "use_additive", xco+45+3*wval+15, yco-129, 35, 19, &oa->flag, 0.0, 0.0, 0, 0, "Toggles between ADD and SET linV"); - } - } - else if (oa->type == ACT_OBJECT_SERVO) { - ysize= 195; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - uiDefBut(block, LABEL, 0, "Ref", xco, yco-45, 45, 19, NULL, 0, 0, 0, 0, ""); - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+45, yco-45, wval*3, 19, &(oa->reference), "Reference object for velocity calculation, leave empty for world reference"); - uiDefBut(block, LABEL, 0, "linV", xco, yco-68, 45, 19, NULL, 0, 0, 0, 0, "Sets the target relative linear velocity, it will be achieved by automatic application of force. Null velocity is a valid target"); - uiBlockBeginAlign(block); - uiDefButF(block, NUM, 0, "", xco+45, yco-68, wval, 19, oa->linearvelocity, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-68, wval, 19, oa->linearvelocity+1, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-68, wval, 19, oa->linearvelocity+2, -10000.0, 10000.0, 10, 0, ""); - uiBlockEndAlign(block); - uiDefButBitS(block, TOG, ACT_LIN_VEL_LOCAL, 0, "L", xco+45+3*wval, yco-68, 15, 19, &oa->flag, 0.0, 0.0, 0, 0, "Velocity is defined in local coordinates"); - - uiDefBut(block, LABEL, 0, "Limit", xco, yco-91, 45, 19, NULL, 0, 0, 0, 0, "Select if the force needs to be limited along certain axis (local or global depending on LinV Local flag)"); - uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, ACT_SERVO_LIMIT_X, B_REDR, "X", xco+45, yco-91, wval, 19, &oa->flag, 0.0, 0.0, 0, 0, "Set limit to force along the X axis"); - uiDefButBitS(block, TOG, ACT_SERVO_LIMIT_Y, B_REDR, "Y", xco+45+wval, yco-91, wval, 19, &oa->flag, 0.0, 0.0, 0, 0, "Set limit to force along the Y axis"); - uiDefButBitS(block, TOG, ACT_SERVO_LIMIT_Z, B_REDR, "Z", xco+45+2*wval, yco-91, wval, 19, &oa->flag, 0.0, 0.0, 0, 0, "Set limit to force along the Z axis"); - uiBlockEndAlign(block); - uiDefBut(block, LABEL, 0, "Max", xco, yco-110, 45, 19, NULL, 0, 0, 0, 0, "Set the upper limit for force"); - uiDefBut(block, LABEL, 0, "Min", xco, yco-129, 45, 19, NULL, 0, 0, 0, 0, "Set the lower limit for force"); - if (oa->flag & ACT_SERVO_LIMIT_X) { - uiDefButF(block, NUM, 0, "", xco+45, yco-110, wval, 19, oa->dloc, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45, yco-129, wval, 19, oa->drot, -10000.0, 10000.0, 10, 0, ""); - } - if (oa->flag & ACT_SERVO_LIMIT_Y) { - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-110, wval, 19, oa->dloc+1, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-129, wval, 19, oa->drot+1, -10000.0, 10000.0, 10, 0, ""); - } - if (oa->flag & ACT_SERVO_LIMIT_Z) { - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-110, wval, 19, oa->dloc+2, -10000.0, 10000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-129, wval, 19, oa->drot+2, -10000.0, 10000.0, 10, 0, ""); - } - uiDefBut(block, LABEL, 0, "Servo", xco, yco-152, 45, 19, NULL, 0, 0, 0, 0, "Coefficients of the PID servo controller"); - uiDefButF(block, NUMSLI, B_REDR, "P: ", xco+45, yco-152, wval*3, 19, oa->forcerot, 0.00, 200.0, 100, 0, "Proportional coefficient, typical value is 60x Integral coefficient"); - uiDefBut(block, LABEL, 0, "Slow", xco, yco-171, 45, 19, NULL, 0, 0, 0, 0, "Low value of I coefficient correspond to slow response"); - but = uiDefButF(block, NUMSLI, B_REDR, " I : ", xco+45, yco-171, wval*3, 19, oa->forcerot+1, 0.0, 3.0, 1, 0, "Integral coefficient, low value (0.01) for slow response, high value (0.5) for fast response"); - uiButSetFunc(but, update_object_actuator_PID, oa, NULL); - uiDefBut(block, LABEL, 0, "Fast", xco+45+3*wval, yco-171, 45, 19, NULL, 0, 0, 0, 0, "High value of I coefficient correspond to fast response"); - uiDefButF(block, NUMSLI, B_REDR, "D: ", xco+45, yco-190, wval*3, 19, oa->forcerot+2, -100.0, 100.0, 100, 0, "Derivate coefficient, not required, high values can cause instability"); - } - str= "Motion Type %t|Simple motion %x0|Servo Control %x1"; - but = uiDefButS(block, MENU, B_REDR, str, xco+40, yco-23, (width-80), 19, &oa->type, 0.0, 0.0, 0, 0, ""); - oa->otype = oa->type; - uiButSetFunc(but, change_object_actuator, oa, NULL); - yco-= ysize; - break; - } - case ACT_ACTION: - case ACT_SHAPEACTION: - { - /* DrawAct */ -#ifdef __NLA_ACTION_BY_MOTION_ACTUATOR - ysize = 112; -#else - ysize= 92; -#endif - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - aa = act->data; - wval = (width-60)/3; - - // str= "Action types %t|Play %x0|Ping Pong %x1|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6"; -#ifdef __NLA_ACTION_BY_MOTION_ACTUATOR - str= "Action types %t|Play %x0|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6|Displacement %x7"; -#else - str= "Action types %t|Play %x0|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6"; -#endif - uiDefButS(block, MENU, B_REDR, str, xco+10, yco-24, width/3, 19, &aa->type, 0.0, 0.0, 0.0, 0.0, "Action playback type"); - uiDefIDPoinBut(block, test_actionpoin_but, ID_AC, 1, "AC: ", xco+10+ (width/3), yco-24, ((width/3)*2) - (20 + 60), 19, &aa->act, "Action name"); - - uiDefButBitS(block, TOGN, 1, 0, "Continue", xco+((width/3)*2)+20, yco-24, 60, 19, - &aa->end_reset, 0.0, 0.0, 0, 0, "Restore last frame when switching on/off, otherwise play from the start each time"); - - - if (aa->type == ACT_ACTION_FROM_PROP) { - uiDefBut(block, TEX, 0, "Prop: ", xco+10, yco-44, width-20, 19, aa->name, 0.0, MAX_NAME, 0, 0, "Use this property to define the Action position"); - } - else { - uiDefButF(block, NUM, 0, "Sta: ", xco+10, yco-44, (width-20)/2, 19, &aa->sta, 1.0, MAXFRAMEF, 0, 0, "Start frame"); - uiDefButF(block, NUM, 0, "End: ", xco+10+(width-20)/2, yco-44, (width-20)/2, 19, &aa->end, 1.0, MAXFRAMEF, 0, 0, "End frame"); - } - - uiDefButS(block, NUM, 0, "Blendin: ", xco+10, yco-64, (width-20)/2, 19, &aa->blendin, 0.0, 32767, 0.0, 0.0, "Number of frames of motion blending"); - uiDefButS(block, NUM, 0, "Priority: ", xco+10+(width-20)/2, yco-64, (width-20)/2, 19, &aa->priority, 0.0, 100.0, 0.0, 0.0, "Execution priority - lower numbers will override actions with higher numbers, With 2 or more actions at once, the overriding channels must be lower in the stack"); - - uiDefBut(block, TEX, 0, "FrameProp: ", xco+10, yco-84, width-20, 19, aa->frameProp, 0.0, MAX_NAME, 0, 0, "Assign the action's current frame number to this property"); - - -#ifdef __NLA_ACTION_BY_MOTION_ACTUATOR - if (aa->type == ACT_ACTION_MOTION) { - uiDefButF(block, NUM, 0, "Cycle: ", xco+30, yco-84, (width-60)/2, 19, &aa->stridelength, 0.0, 2500.0, 0, 0, "Distance covered by a single cycle of the action"); - } -#endif - - - - yco-=ysize; - break; - } - case ACT_IPO: - { - ia= act->data; - - ysize= 72; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - str = "Ipo types %t|Play %x0|Ping Pong %x1|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6"; - - uiDefButS(block, MENU, B_REDR, str, xco+10, yco-24, (width-20)/2, 19, &ia->type, 0, 0, 0, 0, ""); - - but = uiDefButBitS(block, TOG, ACT_IPOFORCE, ACT_IPOFORCE, - "Force", xco+10+(width-20)/2, yco-24, (width-20)/4-10, 19, - &ia->flag, 0, 0, 0, 0, - "Apply Ipo as a global or local force depending on the local option (dynamic objects only)"); - uiButSetFunc(but, change_ipo_actuator, but, ia); - - but = uiDefButBitS(block, TOG, ACT_IPOADD, ACT_IPOADD, - "Add", xco+3*(width-20)/4, yco-24, (width-20)/4-10, 19, - &ia->flag, 0, 0, 0, 0, - "Ipo is added to the current loc/rot/scale in global or local coordinate according to Local flag"); - uiButSetFunc(but, change_ipo_actuator, but, ia); - - /* Only show the do-force-local toggle if force is requested */ - if (ia->flag & (ACT_IPOFORCE|ACT_IPOADD)) { - uiDefButBitS(block, TOG, ACT_IPOLOCAL, 0, - "L", xco+width-30, yco-24, 20, 19, - &ia->flag, 0, 0, 0, 0, - "Let the ipo acts in local coordinates, used in Force and Add mode"); - } - - if (ia->type==ACT_IPO_FROM_PROP) { - uiDefBut(block, TEX, 0, - "Prop: ", xco+10, yco-44, width-80, 19, - ia->name, 0.0, MAX_NAME, 0, 0, - "Use this property to define the Ipo position"); - } - else { - uiDefButF(block, NUM, 0, - "Sta", xco+10, yco-44, (width-80)/2, 19, - &ia->sta, 1.0, MAXFRAMEF, 0, 0, - "Start frame"); - uiDefButF(block, NUM, 0, - "End", xco+10+(width-80)/2, yco-44, (width-80)/2, 19, - &ia->end, 1.0, MAXFRAMEF, 0, 0, - "End frame"); - } - uiDefButBitS(block, TOG, ACT_IPOCHILD, B_REDR, - "Child", xco+10+(width-80), yco-44, 60, 19, - &ia->flag, 0, 0, 0, 0, - "Update IPO on all children Objects as well"); - uiDefBut(block, TEX, 0, - "FrameProp: ", xco+10, yco-64, width-20, 19, - ia->frameProp, 0.0, MAX_NAME, 0, 0, - "Assign the action's current frame number to this property"); - - yco-= ysize; - break; - } - case ACT_PROPERTY: - { - ysize= 68; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - pa= act->data; - - str= "Type%t|Assign%x0|Add %x1|Copy %x2|Toggle (bool/int/float/timer)%x3"; - uiDefButI(block, MENU, B_REDR, str, xco+30, yco-24, width-60, 19, &pa->type, 0, 31, 0, 0, "Type"); - - uiDefBut(block, TEX, 1, "Prop: ", xco+30, yco-44, width-60, 19, pa->name, 0, MAX_NAME, 0, 0, "Property name"); - - - if (pa->type==ACT_PROP_TOGGLE) { - /* no ui */ - ysize -= 22; - } - else if (pa->type==ACT_PROP_COPY) { - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+10, yco-64, (width-20)/2, 19, &(pa->ob), "Copy from this Object"); - uiDefBut(block, TEX, 1, "Prop: ", xco+10+(width-20)/2, yco-64, (width-20)/2, 19, pa->value, 0, MAX_NAME, 0, 0, "Copy this property"); - } - else { - uiDefBut(block, TEX, 1, "Value: ", xco+30, yco-64, width-60, 19, pa->value, 0, MAX_NAME, 0, 0, "change with this value, use \"\" around strings"); - } - yco-= ysize; - - break; - } - case ACT_SOUND: - { - sa = act->data; - sa->sndnr = 0; - - if (sa->flag & ACT_SND_3D_SOUND) - ysize = 180; - else - ysize = 92; - - wval = (width-20)/2; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - if (bmain->sound.first) { - IDnames_to_pupstring(&str, "Sound files", NULL, &(bmain->sound), (ID *)sa->sound, &(sa->sndnr)); - /* reset this value, it is for handling the event */ - sa->sndnr = 0; - uiDefButS(block, MENU, B_SOUNDACT_BROWSE, str, xco+10, yco-22, 20, 19, &(sa->sndnr), 0, 0, 0, 0, ""); - uiDefButO(block, BUT, "sound.open", 0, "Load Sound", xco+wval+10, yco-22, wval, 19, - "Load a sound file (remember to set caching on for small sounds that are played often)"); - - if (sa->sound) { - char dummy_str[] = "Sound mode %t|Play Stop %x0|Play End %x1|Loop Stop %x2|" - "Loop End %x3|Loop Ping Pong Stop %x5|Loop Ping Pong %x4"; - uiDefBut(block, TEX, B_IDNAME, "SO:", xco+30, yco-22, wval-20, 19, - ((ID *)sa->sound)->name+2, 0.0, MAX_ID_NAME-2, 0, 0, ""); - uiDefButS(block, MENU, 1, dummy_str, xco+10, yco-44, width-20, 19, - &sa->type, 0.0, 0.0, 0, 0, ""); - uiDefButF(block, NUM, 0, "Volume:", xco+10, yco-66, wval, 19, &sa->volume, - 0.0, 1.0, 0, 0, "Sets the volume of this sound"); - uiDefButF(block, NUM, 0, "Pitch:", xco+wval+10, yco-66, wval, 19, &sa->pitch, -12.0, - 12.0, 0, 0, "Sets the pitch of this sound"); - uiDefButS(block, TOG | UI_BUT_POIN_BIT, 0, "3D Sound", xco+10, yco-88, width-20, 19, - &sa->flag, 0.0, 1.0, 0.0, 0.0, "Plays the sound positioned in 3D space"); - if (sa->flag & ACT_SND_3D_SOUND) { - uiDefButF(block, NUM, 0, "Minimum Gain: ", xco+10, yco-110, wval, 19, - &sa->sound3D.min_gain, 0.0, 1.0, 0.0, 0.0, - "The minimum gain of the sound, no matter how far it is away"); - uiDefButF(block, NUM, 0, "Maximum Gain: ", xco+10, yco-132, wval, 19, - &sa->sound3D.max_gain, 0.0, 1.0, 0.0, 0.0, - "The maximum gain of the sound, no matter how near it is"); - uiDefButF(block, NUM, 0, "Reference Distance: ", xco+10, yco-154, wval, 19, - &sa->sound3D.reference_distance, 0.0, FLT_MAX, 0.0, 0.0, - "The reference distance is the distance where the sound has a gain of 1.0"); - uiDefButF(block, NUM, 0, "Maximum Distance: ", xco+10, yco-176, wval, 19, - &sa->sound3D.max_distance, 0.0, FLT_MAX, 0.0, 0.0, - "The maximum distance at which you can hear the sound"); - uiDefButF(block, NUM, 0, "Rolloff: ", xco+wval+10, yco-110, wval, 19, - &sa->sound3D.rolloff_factor, 0.0, 5.0, 0.0, 0.0, - "The rolloff factor defines the influence factor on volume depending on distance"); - uiDefButF(block, NUM, 0, "Cone Outer Gain: ", xco+wval+10, yco-132, wval, 19, - &sa->sound3D.cone_outer_gain, 0.0, 1.0, 0.0, 0.0, - "The gain outside the outer cone. The gain in the outer cone will be " - "interpolated between this value and the normal gain in the inner cone"); - uiDefButF(block, NUM, 0, "Cone Outer Angle: ", xco+wval+10, yco-154, wval, - 19, &sa->sound3D.cone_outer_angle, 0.0, 360.0, 0.0, 0.0, - "The angle of the outer cone"); - uiDefButF(block, NUM, 0, "Cone Inner Angle: ", xco+wval+10, yco-176, wval, - 19, &sa->sound3D.cone_inner_angle, 0.0, 360.0, 0.0, 0.0, - "The angle of the inner cone"); - } - } - MEM_freeN((void *)str); - } - else { - uiDefButO(block, BUT, "sound.open", 0, "Load Sound", xco+10, yco-22, width-20, 19, "Load a sound file"); - } - - yco-= ysize; - - break; - } - case ACT_CAMERA: - - ysize= 48; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - ca= act->data; - - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+10, yco-24, (width-20)/2, 19, &(ca->ob), "Look at this Object"); - uiDefButF(block, NUM, 0, "Height:", xco+10+(width-20)/2, yco-24, (width-20)/2, 19, &ca->height, 0.0, 20.0, 0, 0, ""); - - uiDefButF(block, NUM, 0, "Min:", xco+10, yco-44, (width-60)/2, 19, &ca->min, 0.0, 20.0, 0, 0, ""); - - if (ca->axis==0) ca->axis= 'x'; - uiDefButS(block, ROW, 0, "X", xco+10+(width-60)/2, yco-44, 20, 19, &ca->axis, 4.0, (float)'x', 0, 0, "Camera tries to get behind the X axis"); - uiDefButS(block, ROW, 0, "Y", xco+30+(width-60)/2, yco-44, 20, 19, &ca->axis, 4.0, (float)'y', 0, 0, "Camera tries to get behind the Y axis"); - - uiDefButF(block, NUM, 0, "Max:", xco+20+(width)/2, yco-44, (width-60)/2, 19, &ca->max, 0.0, 20.0, 0, 0, ""); - - yco-= ysize; - - break; - - case ACT_EDIT_OBJECT: - - eoa= act->data; - - if (eoa->type==ACT_EDOB_ADD_OBJECT) { - ysize = 92; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+10, yco-44, (width-20)/2, 19, &(eoa->ob), "Add this Object and all its children (cant be on an visible layer)"); - uiDefButI(block, NUM, 0, "Time:", xco+10+(width-20)/2, yco-44, (width-20)/2, 19, &eoa->time, 0.0, 2000.0, 0, 0, "Duration the new Object lives"); - - wval= (width-60)/3; - uiDefBut(block, LABEL, 0, "linV", xco, yco-68, 45, 19, - NULL, 0, 0, 0, 0, - "Velocity upon creation"); - uiDefButF(block, NUM, 0, "", xco+45, yco-68, wval, 19, - eoa->linVelocity, -100.0, 100.0, 10, 0, - "Velocity upon creation, x component"); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-68, wval, 19, - eoa->linVelocity+1, -100.0, 100.0, 10, 0, - "Velocity upon creation, y component"); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-68, wval, 19, - eoa->linVelocity+2, -100.0, 100.0, 10, 0, - "Velocity upon creation, z component"); - uiDefButBitS(block, TOG, ACT_EDOB_LOCAL_LINV, 0, "L", xco+45+3*wval, yco-68, 15, 19, - &eoa->localflag, 0.0, 0.0, 0, 0, - "Apply the transformation locally"); - - - uiDefBut(block, LABEL, 0, "AngV", xco, yco-90, 45, 19, - NULL, 0, 0, 0, 0, - "Angular velocity upon creation"); - uiDefButF(block, NUM, 0, "", xco+45, yco-90, wval, 19, - eoa->angVelocity, -10000.0, 10000.0, 10, 0, - "Angular velocity upon creation, x component"); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-90, wval, 19, - eoa->angVelocity+1, -10000.0, 10000.0, 10, 0, - "Angular velocity upon creation, y component"); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-90, wval, 19, - eoa->angVelocity+2, -10000.0, 10000.0, 10, 0, - "Angular velocity upon creation, z component"); - uiDefButBitS(block, TOG, ACT_EDOB_LOCAL_ANGV, 0, "L", xco+45+3*wval, yco-90, 15, 19, - &eoa->localflag, 0.0, 0.0, 0, 0, - "Apply the rotation locally"); - - - } - else if (eoa->type==ACT_EDOB_END_OBJECT) { - ysize= 28; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - } - else if (eoa->type==ACT_EDOB_REPLACE_MESH) { - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - uiDefIDPoinBut(block, test_meshpoin_but, ID_ME, 1, "ME:", xco+40, yco-44, (width-80)/2, 19, &(eoa->me), "replace the existing, when left blank 'Phys' will remake the existing physics mesh"); - - uiDefButBitS(block, TOGN, ACT_EDOB_REPLACE_MESH_NOGFX, 0, "Gfx", xco+40 + (width-80)/2, yco-44, (width-80)/4, 19, &eoa->flag, 0, 0, 0, 0, "Replace the display mesh"); - uiDefButBitS(block, TOG, ACT_EDOB_REPLACE_MESH_PHYS, 0, "Phys", xco+40 + (width-80)/2 +(width-80)/4, yco-44, (width-80)/4, 19, &eoa->flag, 0, 0, 0, 0, "Replace the physics mesh (triangle bounds only. compound shapes not supported)"); - } - else if (eoa->type==ACT_EDOB_TRACK_TO) { - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+10, yco-44, (width-20)/2, 19, &(eoa->ob), "Track to this Object"); - uiDefButI(block, NUM, 0, "Time:", xco+10+(width-20)/2, yco-44, (width-20)/2-40, 19, &eoa->time, 0.0, 2000.0, 0, 0, "Duration the tracking takes"); - uiDefButS(block, TOG, 0, "3D", xco+width-50, yco-44, 40, 19, &eoa->flag, 0.0, 0.0, 0, 0, "Enable 3D tracking"); - } - else if (eoa->type==ACT_EDOB_DYNAMICS) { - ysize= 69; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - str= "Dynamic Operation %t|Restore Dynamics %x0|Suspend Dynamics %x1|Enable Rigid Body %x2|Disable Rigid Body %x3|Set Mass %x4"; - uiDefButS(block, MENU, B_REDR, str, xco+40, yco-44, (width-80), 19, &(eoa->dyn_operation), 0.0, 0.0, 0, 0, ""); - if (eoa->dyn_operation==4) { - uiDefButF(block, NUM, 0, "", xco+40, yco-63, width-80, 19, - &eoa->mass, 0.0, 10000.0, 10, 0, - "Mass for object"); - } - } - str= "Edit Object %t|Add Object %x0|End Object %x1|Replace Mesh %x2|Track to %x3|Dynamics %x4"; - uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &eoa->type, 0.0, 0.0, 0, 0, ""); - - yco-= ysize; - - break; - - case ACT_CONSTRAINT: - coa= act->data; - - if (coa->type == ACT_CONST_TYPE_LOC) { - ysize= 69; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - /* str= "Limit %t|None %x0|Loc X %x1|Loc Y %x2|Loc Z %x4|Rot X %x8|Rot Y %x16|Rot Z %x32"; */ - /* coa->flag &= ~(63); */ - str= "Limit %t|None %x0|Loc X %x1|Loc Y %x2|Loc Z %x4"; - coa->flag &= 7; - coa->time = 0; - uiDefButS(block, MENU, 1, str, xco+10, yco-65, 70, 19, &coa->flag, 0.0, 0.0, 0, 0, ""); - - uiDefButS(block, NUM, 0, "damp", xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter"); - uiDefBut(block, LABEL, 0, "Min", xco+80, yco-45, (width-90)/2, 19, NULL, 0.0, 0.0, 0, 0, ""); - uiDefBut(block, LABEL, 0, "Max", xco+80+(width-90)/2, yco-45, (width-90)/2, 19, NULL, 0.0, 0.0, 0, 0, ""); - - if (coa->flag & ACT_CONST_LOCX) fp= coa->minloc; - else if (coa->flag & ACT_CONST_LOCY) fp= coa->minloc+1; - else if (coa->flag & ACT_CONST_LOCZ) fp= coa->minloc+2; - else if (coa->flag & ACT_CONST_ROTX) fp= coa->minrot; - else if (coa->flag & ACT_CONST_ROTY) fp= coa->minrot+1; - else fp= coa->minrot+2; - - uiDefButF(block, NUM, 0, "", xco+80, yco-65, (width-90)/2, 19, fp, -2000.0, 2000.0, 10, 0, ""); - uiDefButF(block, NUM, 0, "", xco+80+(width-90)/2, yco-65, (width-90)/2, 19, fp+3, -2000.0, 2000.0, 10, 0, ""); - } - else if (coa->type == ACT_CONST_TYPE_DIST) { - ysize= 106; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - str= "Direction %t|None %x0|X axis %x1|Y axis %x2|Z axis %x4|-X axis %x8|-Y axis %x16|-Z axis %x32"; - uiDefButS(block, MENU, B_REDR, str, xco+10, yco-65, 70, 19, &coa->mode, 0.0, 0.0, 0, 0, "Set the direction of the ray"); - - uiDefButS(block, NUM, 0, "damp", xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter"); - uiDefBut(block, LABEL, 0, "Range", xco+80, yco-45, (width-115)/2, 19, NULL, 0.0, 0.0, 0, 0, "Set the maximum length of ray"); - uiDefButBitS(block, TOG, ACT_CONST_DISTANCE, B_REDR, "Dist", xco+80+(width-115)/2, yco-45, (width-115)/2, 19, &coa->flag, 0.0, 0.0, 0, 0, "Force distance of object to point of impact of ray"); - uiDefButBitS(block, TOG, ACT_CONST_LOCAL, 0, "L", xco+80+(width-115), yco-45, 25, 19, - &coa->flag, 0.0, 0.0, 0, 0, "Set ray along object's axis or global axis"); - - if (coa->mode & (ACT_CONST_DIRPX|ACT_CONST_DIRNX)) fp= coa->minloc; - else if (coa->mode & (ACT_CONST_DIRPY|ACT_CONST_DIRNY)) fp= coa->minloc+1; - else fp= coa->minloc+2; - - uiDefButF(block, NUM, 0, "", xco+80, yco-65, (width-115)/2, 19, fp+3, 0.0, 2000.0, 10, 0, "Maximum length of ray"); - if (coa->flag & ACT_CONST_DISTANCE) - uiDefButF(block, NUM, 0, "", xco+80+(width-115)/2, yco-65, (width-115)/2, 19, fp, -2000.0, 2000.0, 10, 0, "Keep this distance to target"); - uiDefButBitS(block, TOG, ACT_CONST_NORMAL, 0, "N", xco+80+(width-115), yco-65, 25, 19, - &coa->flag, 0.0, 0.0, 0, 0, "Set object axis along (local axis) or parallel (global axis) to the normal at hit position"); - uiDefButBitS(block, TOG, ACT_CONST_MATERIAL, B_REDR, "M/P", xco+10, yco-84, 40, 19, - &coa->flag, 0.0, 0.0, 0, 0, "Detect material instead of property"); - if (coa->flag & ACT_CONST_MATERIAL) { - uiDefBut(block, TEX, 1, "Material:", xco + 50, yco-84, (width-60), 19, - coa->matprop, 0, MAX_NAME, 0, 0, - "Ray detects only Objects with this material"); - } - else { - uiDefBut(block, TEX, 1, "Property:", xco + 50, yco-84, (width-60), 19, - coa->matprop, 0, MAX_NAME, 0, 0, - "Ray detect only Objects with this property"); - } - uiDefButBitS(block, TOG, ACT_CONST_PERMANENT, 0, "PER", xco+10, yco-103, 40, 19, - &coa->flag, 0.0, 0.0, 0, 0, "Persistent actuator: stays active even if ray does not reach target"); - uiDefButS(block, NUM, 0, "time", xco+50, yco-103, (width-60)/2, 19, &(coa->time), 0.0, 1000.0, 0, 0, "Maximum activation time in frame, 0 for unlimited"); - uiDefButS(block, NUM, 0, "rotDamp", xco+50+(width-60)/2, yco-103, (width-60)/2, 19, &(coa->rotdamp), 0.0, 100.0, 0, 0, "Use a different damping for orientation"); - } - else if (coa->type == ACT_CONST_TYPE_ORI) { - ysize= 87; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - str= "Direction %t|None %x0|X axis %x1|Y axis %x2|Z axis %x4"; - uiDefButS(block, MENU, B_REDR, str, xco+10, yco-65, 70, 19, &coa->mode, 0.0, 0.0, 0, 0, "Select the axis to be aligned along the reference direction"); - - uiDefButS(block, NUM, 0, "damp", xco+10, yco-45, 70, 19, &coa->damp, 0.0, 100.0, 0, 0, "Damping factor: time constant (in frame) of low pass filter"); - uiDefBut(block, LABEL, 0, "X", xco+80, yco-45, (width-115)/3, 19, NULL, 0.0, 0.0, 0, 0, ""); - uiDefBut(block, LABEL, 0, "Y", xco+80+(width-115)/3, yco-45, (width-115)/3, 19, NULL, 0.0, 0.0, 0, 0, ""); - uiDefBut(block, LABEL, 0, "Z", xco+80+2*(width-115)/3, yco-45, (width-115)/3, 19, NULL, 0.0, 0.0, 0, 0, ""); - - uiDefButF(block, NUM, 0, "", xco+80, yco-65, (width-115)/3, 19, &coa->maxrot[0], -2000.0, 2000.0, 10, 0, "X component of reference direction"); - uiDefButF(block, NUM, 0, "", xco+80+(width-115)/3, yco-65, (width-115)/3, 19, &coa->maxrot[1], -2000.0, 2000.0, 10, 0, "Y component of reference direction"); - uiDefButF(block, NUM, 0, "", xco+80+2*(width-115)/3, yco-65, (width-115)/3, 19, &coa->maxrot[2], -2000.0, 2000.0, 10, 0, "Z component of reference direction"); - - uiDefButS(block, NUM, 0, "time", xco+10, yco-84, 70, 19, &(coa->time), 0.0, 1000.0, 0, 0, "Maximum activation time in frame, 0 for unlimited"); - uiDefButF(block, NUM, 0, "min", xco+80, yco-84, (width-115)/2, 19, &(coa->minloc[0]), 0.0, 180.0, 10, 1, "Minimum angle (in degree) to maintain with target direction. No correction is done if angle with target direction is between min and max"); - uiDefButF(block, NUM, 0, "max", xco+80+(width-115)/2, yco-84, (width-115)/2, 19, &(coa->maxloc[0]), 0.0, 180.0, 10, 1, "Maximum angle (in degree) allowed with target direction. No correction is done if angle with target direction is between min and max"); - } - else if (coa->type == ACT_CONST_TYPE_FH) { - ysize= 106; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - str= "Direction %t|None %x0|X axis %x1|Y axis %x2|Z axis %x4|-X axis %x8|-Y axis %x16|-Z axis %x32"; - uiDefButS(block, MENU, B_REDR, str, xco+10, yco-65, 70, 19, &coa->mode, 0.0, 0.0, 0, 0, "Set the direction of the ray (in world coordinate)"); - - if (coa->mode & (ACT_CONST_DIRPX|ACT_CONST_DIRNX)) fp= coa->minloc; - else if (coa->mode & (ACT_CONST_DIRPY|ACT_CONST_DIRNY)) fp= coa->minloc+1; - else fp= coa->minloc+2; - - uiDefButF(block, NUM, 0, "damp", xco+10, yco-45, (width-70)/2, 19, &coa->maxrot[0], 0.0, 1.0, 1, 0, "Damping factor of the Fh spring force"); - uiDefButF(block, NUM, 0, "dist", xco+10+(width-70)/2, yco-45, (width-70)/2, 19, fp, 0.010, 2000.0, 10, 0, "Height of the Fh area"); - uiDefButBitS(block, TOG, ACT_CONST_DOROTFH, 0, "Rot Fh", xco+10+(width-70), yco-45, 50, 19, &coa->flag, 0.0, 0.0, 0, 0, "Keep object axis parallel to normal"); - - uiDefButF(block, NUMSLI, 0, "Fh ", xco+80, yco-65, (width-115), 19, fp+3, 0.0, 1.0, 0, 0, "Spring force within the Fh area"); - uiDefButBitS(block, TOG, ACT_CONST_NORMAL, 0, "N", xco+80+(width-115), yco-65, 25, 19, - &coa->flag, 0.0, 0.0, 0, 0, "Add a horizontal spring force on slopes"); - uiDefButBitS(block, TOG, ACT_CONST_MATERIAL, B_REDR, "M/P", xco+10, yco-84, 40, 19, - &coa->flag, 0.0, 0.0, 0, 0, "Detect material instead of property"); - if (coa->flag & ACT_CONST_MATERIAL) { - uiDefBut(block, TEX, 1, "Material:", xco + 50, yco-84, (width-60), 19, - coa->matprop, 0, MAX_NAME, 0, 0, - "Ray detects only Objects with this material"); - } - else { - uiDefBut(block, TEX, 1, "Property:", xco + 50, yco-84, (width-60), 19, - coa->matprop, 0, MAX_NAME, 0, 0, - "Ray detect only Objects with this property"); - } - uiDefButBitS(block, TOG, ACT_CONST_PERMANENT, 0, "PER", xco+10, yco-103, 40, 19, - &coa->flag, 0.0, 0.0, 0, 0, "Persistent actuator: stays active even if ray does not reach target"); - uiDefButS(block, NUM, 0, "time", xco+50, yco-103, 90, 19, &(coa->time), 0.0, 1000.0, 0, 0, "Maximum activation time in frame, 0 for unlimited"); - uiDefButF(block, NUM, 0, "rotDamp", xco+140, yco-103, (width-150), 19, &coa->maxrot[1], 0.0, 1.0, 1, 0, "Use a different damping for rotation"); - } - str= "Constraint Type %t|Location %x0|Distance %x1|Orientation %x2|Force field %x3"; - but = uiDefButS(block, MENU, B_REDR, str, xco+40, yco-23, (width-80), 19, &coa->type, 0.0, 0.0, 0, 0, ""); - yco-= ysize; - break; - - case ACT_SCENE: - sca= act->data; - - if (sca->type==ACT_SCENE_RESTART) { - ysize= 28; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - } - else if (sca->type==ACT_SCENE_CAMERA) { - - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+40, yco-44, (width-80), 19, &(sca->camera), "Set this Camera. Leave empty to refer to self object"); - } - else if (sca->type==ACT_SCENE_SET) { - - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Set this Scene"); - } - else if (sca->type==ACT_SCENE_ADD_FRONT) { - - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Add an Overlay Scene"); - } - else if (sca->type==ACT_SCENE_ADD_BACK) { - - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Add a Background Scene"); - } - else if (sca->type==ACT_SCENE_REMOVE) { - - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Remove a Scene"); - } - else if (sca->type==ACT_SCENE_SUSPEND) { - - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Pause a Scene"); - } - else if (sca->type==ACT_SCENE_RESUME) { - - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - uiDefIDPoinBut(block, test_scenepoin_but, ID_SCE, 1, "SCE:", xco+40, yco-44, (width-80), 19, &(sca->scene), "Unpause a Scene"); - } - - str= "Scene %t|Restart %x0|Set Scene %x1|Set Camera %x2|Add OverlayScene %x3|Add BackgroundScene %x4|Remove Scene %x5|Suspend Scene %x6|Resume Scene %x7"; - uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &sca->type, 0.0, 0.0, 0, 0, ""); - - yco-= ysize; - break; - case ACT_GAME: - { - gma = act->data; - if (gma->type == ACT_GAME_LOAD) { - //ysize = 68; - ysize = 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44, width-20, 19, &(gma->filename), 0, sizeof(gma->filename), 0, 0, "Load this blend file, use the \"//\" prefix for a path relative to the current blend file"); - // uiDefBut(block, TEX, 1, "Anim: ", xco+10, yco-64, width-20, 19, &(gma->loadaniname), 0, sizeof(gma->loadaniname), 0, 0, "Use this loadinganimation"); - } -#if 0 - else if (gma->type == ACT_GAME_START) { - ysize = 68; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44, width-20, 19, &(gma->filename), 0, sizeof(gma->filename), 0, 0, "Load this file"); - uiDefBut(block, TEX, 1, "Anim: ", xco+10, yco-64, width-20, 19, &(gma->loadaniname), 0, sizeof(gma->loadaniname), 0, 0, "Use this loadinganimation"); - } -#endif - else if (ELEM4(gma->type, ACT_GAME_RESTART, ACT_GAME_QUIT, ACT_GAME_SAVECFG, ACT_GAME_LOADCFG)) { - ysize = 28; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - } - - //str = "Scene %t|Load game%x0|Start loaded game%x1|Restart this game%x2|Quit this game %x3"; - str = "Scene %t|Start new game%x0|Restart this game%x2|Quit this game %x3|Save bge.logic.globalDict %x4|Load bge.logic.globalDict %x5"; - uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &gma->type, 0.0, 0.0, 0, 0, ""); - - yco -= ysize; - break; - } - case ACT_GROUP: - ga= act->data; - - ysize= 52; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - str= "GroupKey types %t|Set Key %x6|Play %x0|Ping Pong %x1|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x5"; - - uiDefButS(block, MENU, 1, str, xco+20, yco-24, width-40, 19, &ga->type, 0, 0, 0, 0, ""); - if (ga->type==ACT_GROUP_SET) { - uiDefBut(block, TEX, 0, "Key: ", xco+20, yco-44, (width-10)/2, 19, ga->name, 0.0, MAX_NAME, 0, 0, "This name defines groupkey to be set"); - uiDefButI(block, NUM, 0, "Frame:", xco+20+(width-10)/2, yco-44, (width-70)/2, 19, &ga->sta, 0.0, 2500.0, 0, 0, "Set this frame"); - } - else if (ga->type==ACT_GROUP_FROM_PROP) { - uiDefBut(block, TEX, 0, "Prop: ", xco+20, yco-44, width-40, 19, ga->name, 0.0, MAX_NAME, 0, 0, "Use this property to define the Group position"); - } - else { - uiDefButI(block, NUM, 0, "State", xco+20, yco-44, (width-40)/2, 19, &ga->sta, 0.0, 2500.0, 0, 0, "Start frame"); - uiDefButI(block, NUM, 0, "End", xco+20+(width-40)/2, yco-44, (width-40)/2, 19, &ga->end, 0.0, 2500.0, 0, 0, "End frame"); - } - yco-= ysize; - break; - - case ACT_VISIBILITY: - ysize = 24; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, - (float)yco-ysize, (float)xco+width, (float)yco, 1); - - visAct = act->data; - - uiBlockBeginAlign(block); - uiDefButBitI(block, TOGN, ACT_VISIBILITY_INVISIBLE, B_REDR, - "Visible", - xco + 10, yco - 20, (width - 20)/3, 19, &visAct->flag, - 0.0, 0.0, 0, 0, - "Set the objects visible. Initialized from the objects render restriction toggle (access in the outliner)"); - uiDefButBitI(block, TOG, ACT_VISIBILITY_OCCLUSION, B_REDR, - "Occlusion", - xco + 10 + ((width - 20)/3), yco - 20, (width - 20)/3, 19, &visAct->flag, - 0.0, 0.0, 0, 0, - "Set the object to occlude objects behind it. Initialized from the object type in physics button"); - uiBlockEndAlign(block); - - uiDefButBitI(block, TOG, ACT_VISIBILITY_RECURSIVE, 0, - "Children", - xco + 10 + (((width - 20)/3)*2)+10, yco - 20, ((width - 20)/3)-10, 19, &visAct->flag, - 0.0, 0.0, 0, 0, - "Sets all the children of this object to the same visibility/occlusion recursively"); - - yco-= ysize; - - break; - - case ACT_STATE: - ysize = 34; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, - (float)yco-ysize, (float)xco+width, (float)yco, 1); - - staAct = act->data; - - str= "Operation %t|Cpy %x0|Add %x1|Sub %x2|Inv %x3"; - - uiDefButI(block, MENU, B_REDR, str, - xco + 10, yco - 24, 65, 19, &staAct->type, - 0.0, 0.0, 0, 0, - "Select the bit operation on object state mask"); - - for (wval=0; wval<15; wval+=5) { - uiBlockBeginAlign(block); - for (stbit=0; stbit<5; stbit++) { - but = uiDefButBitI(block, TOG, 1<<(stbit+wval), stbit+wval, "", (short)(xco+85+12*stbit+13*wval), yco-17, 12, 12, (int *)&(staAct->mask), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+wval))); - uiButSetFunc(but, check_state_mask, but, &(staAct->mask)); - } - for (stbit=0; stbit<5; stbit++) { - but = uiDefButBitI(block, TOG, 1<<(stbit+wval+15), stbit+wval+15, "", (short)(xco+85+12*stbit+13*wval), yco-29, 12, 12, (int *)&(staAct->mask), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+wval+15))); - uiButSetFunc(but, check_state_mask, but, &(staAct->mask)); - } - } - uiBlockEndAlign(block); - - yco-= ysize; - - break; - - case ACT_RANDOM: - ysize = 69; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, - (float)yco-ysize, (float)xco+width, (float)yco, 1); - - randAct = act->data; - - /* 1. seed */ - uiDefButI(block, NUM, 1, "Seed: ", (xco+10), yco-24, 0.4 *(width-20), 19, - &randAct->seed, 0, 1000, 0, 0, - "Initial seed of the random generator. Use Python for more freedom. " - " (Choose 0 for not random)"); - - /* 2. distribution type */ - /* One pick per distribution. These numbers MUST match the #defines */ - /* in game.h !!! */ - str= "Distribution %t|Bool Constant %x0|Bool Uniform %x1" - "|Bool Bernoulli %x2|Int Constant %x3|Int Uniform %x4" - "|Int Poisson %x5|Float Constant %x6|Float Uniform %x7" - "|Float Normal %x8|Float Neg. Exp. %x9"; - uiDefButI(block, MENU, B_REDR, str, (xco+10) + 0.4 * (width-20), yco-24, 0.6 * (width-20), 19, - &randAct->distribution, 0.0, 0.0, 0, 0, - "Choose the type of distribution"); - - /* 3. property */ - uiDefBut(block, TEX, 1, "Property:", (xco+10), yco-44, (width-20), 19, - &randAct->propname, 0, MAX_NAME, 0, 0, - "Assign the random value to this property"); - - /*4. and 5. arguments for the distribution*/ - switch (randAct->distribution) { - case ACT_RANDOM_BOOL_CONST: - uiDefButBitI(block, TOG, 1, 1, "Always true", (xco+10), yco-64, (width-20), 19, - &randAct->int_arg_1, 2.0, 1, 0, 0, - "Always false or always true"); - break; - case ACT_RANDOM_BOOL_UNIFORM: - uiDefBut(block, LABEL, 0, " Do a 50-50 pick", (xco+10), yco-64, (width-20), 19, - NULL, 0, 0, 0, 0, - "Choose between true and false, 50% chance each"); - break; - case ACT_RANDOM_BOOL_BERNOUILLI: - uiDefButF(block, NUM, 1, "Chance", (xco+10), yco-64, (width-20), 19, - &randAct->float_arg_1, 0.0, 1.0, 0, 0, - "Pick a number between 0 and 1. Success if you stay " - "below this value"); - break; - case ACT_RANDOM_INT_CONST: - uiDefButI(block, NUM, 1, "Value: ", (xco+10), yco-64, (width-20), 19, - &randAct->int_arg_1, -1000, 1000, 0, 0, - "Always return this number"); - break; - case ACT_RANDOM_INT_UNIFORM: - uiDefButI(block, NUM, 1, "Min: ", (xco+10), yco-64, (width-20)/2, 19, - &randAct->int_arg_1, -1000, 1000, 0, 0, - "Choose a number from a range. " - "Lower boundary of the range"); - uiDefButI(block, NUM, 1, "Max: ", (xco+10) + (width-20)/2, yco-64, (width-20)/2, 19, - &randAct->int_arg_2, -1000, 1000, 0, 0, - "Choose a number from a range. " - "Upper boundary of the range"); - break; - case ACT_RANDOM_INT_POISSON: - uiDefButF(block, NUM, 1, "Mean: ", (xco+10), yco-64, (width-20), 19, - &randAct->float_arg_1, 0.01, 100.0, 0, 0, - "Expected mean value of the distribution"); - break; - case ACT_RANDOM_FLOAT_CONST: - uiDefButF(block, NUM, 1, "Value: ", (xco+10), yco-64, (width-20), 19, - &randAct->float_arg_1, 0.0, 1.0, 0, 0, - "Always return this number"); - break; - case ACT_RANDOM_FLOAT_UNIFORM: - uiDefButF(block, NUM, 1, "Min: ", (xco+10), yco-64, (width-20)/2, 19, - &randAct->float_arg_1, -10000.0, 10000.0, 0, 0, - "Choose a number from a range" - "Lower boundary of the range"); - uiDefButF(block, NUM, 1, "Max: ", (xco+10) + (width-20)/2, yco-64, (width-20)/2, 19, - &randAct->float_arg_2, -10000.0, 10000.0, 0, 0, - "Choose a number from a range" - "Upper boundary of the range"); - break; - case ACT_RANDOM_FLOAT_NORMAL: - uiDefButF(block, NUM, 1, "Mean: ", (xco+10), yco-64, (width-20)/2, 19, - &randAct->float_arg_1, -10000.0, 10000.0, 0, 0, - "A normal distribution. Mean of the distribution"); - uiDefButF(block, NUM, 1, "SD: ", (xco+10) + (width-20)/2, yco-64, (width-20)/2, 19, - &randAct->float_arg_2, 0.0, 10000.0, 0, 0, - "A normal distribution. Standard deviation of the " - "distribution"); - break; - case ACT_RANDOM_FLOAT_NEGATIVE_EXPONENTIAL: - uiDefButF(block, NUM, 1, "Half-life time: ", (xco+10), yco-64, (width-20), 19, - &randAct->float_arg_1, 0.001, 10000.0, 0, 0, - "Negative exponential dropoff"); - break; - default: - ; /* don't know what this distro is... can be useful for testing */ - /* though :) */ - } - - yco-= ysize; - break; - case ACT_MESSAGE: - ma = act->data; - - ysize = 4 + (3 * 24); /* footer + number of lines * 24 pixels/line */ - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, - (float)xco+width, (float)yco, 1); - - myline=1; - - /* line 1: To */ - uiDefBut(block, TEX, 1, "To: ", - (xco+10), (yco-(myline++*24)), (width-20), 19, - &ma->toPropName, 0, MAX_NAME, 0, 0, - "Optional send message to objects with this name only, or empty to broadcast"); - - /* line 2: Message Subject */ - uiDefBut(block, TEX, 1, "Subject: ", - (xco+10), (yco-(myline++*24)), (width-20), 19, - &ma->subject, 0, MAX_NAME, 0, 0, - "Optional message subject. This is what can be filtered on"); - - /* line 3: Text/Property */ - uiDefButBitS(block, TOG, 1, B_REDR, "T/P", - (xco+10), (yco-(myline*24)), (0.20 * (width-20)), 19, - &ma->bodyType, 0.0, 0.0, 0, 0, - "Toggle message type: either Text or a PropertyName"); - - if (ma->bodyType == ACT_MESG_MESG) { - /* line 3: Message Body */ - uiDefBut(block, TEX, 1, "Body: ", - (xco+10+(0.20*(width-20))), (yco-(myline++*24)), (0.8*(width-20)), 19, - &ma->body, 0, MAX_NAME, 0, 0, - "Optional message body Text"); - } - else { - /* line 3: Property body (set by property) */ - uiDefBut(block, TEX, 1, "Propname: ", - (xco+10+(0.20*(width-20))), (yco-(myline++*24)), (0.8*(width-20)), 19, - &ma->body, 0, MAX_NAME, 0, 0, - "The message body will be set by the Property Value"); - } - - yco -= ysize; - break; - case ACT_2DFILTER: - tdfa = act->data; - - ysize = 50; - if (tdfa->type == ACT_2DFILTER_CUSTOMFILTER) { - ysize +=20; - } - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - switch (tdfa->type) { - case ACT_2DFILTER_MOTIONBLUR: - if (!tdfa->flag) { - uiDefButS(block, TOG, B_REDR, "D", xco+30, yco-44, 19, 19, &tdfa->flag, 0.0, 0.0, 0.0, 0.0, "Disable Motion Blur"); - uiDefButF(block, NUM, B_REDR, "Value:", xco+52, yco-44, width-82, 19, &tdfa->float_arg, 0.0, 1.0, 0.0, 0.0, "Set motion blur value"); - } - else { - uiDefButS(block, TOG, B_REDR, "Disabled", xco+30, yco-44, width-60, 19, &tdfa->flag, 0.0, 0.0, 0.0, 0.0, "Enable Motion Blur"); - } - break; - case ACT_2DFILTER_BLUR: - case ACT_2DFILTER_SHARPEN: - case ACT_2DFILTER_DILATION: - case ACT_2DFILTER_EROSION: - case ACT_2DFILTER_LAPLACIAN: - case ACT_2DFILTER_SOBEL: - case ACT_2DFILTER_PREWITT: - case ACT_2DFILTER_GRAYSCALE: - case ACT_2DFILTER_SEPIA: - case ACT_2DFILTER_INVERT: - case ACT_2DFILTER_NOFILTER: - case ACT_2DFILTER_DISABLED: - case ACT_2DFILTER_ENABLED: - uiDefButI(block, NUM, B_REDR, "Pass Number:", xco+30, yco-44, width-60, 19, &tdfa->int_arg, 0.0, MAX_RENDER_PASS-1, 0.0, 0.0, "Set filter order"); - break; - case ACT_2DFILTER_CUSTOMFILTER: - uiDefButI(block, NUM, B_REDR, "Pass Number:", xco+30, yco-44, width-60, 19, &tdfa->int_arg, 0.0, MAX_RENDER_PASS-1, 0.0, 0.0, "Set filter order"); - uiDefIDPoinBut(block, test_scriptpoin_but, ID_SCRIPT, 1, "Script: ", xco+30, yco-64, width-60, 19, &tdfa->text, ""); - break; - } - - str= "2D Filter %t|Motion Blur %x1|Blur %x2|Sharpen %x3|Dilation %x4|Erosion %x5|" - "Laplacian %x6|Sobel %x7|Prewitt %x8|Gray Scale %x9|Sepia %x10|Invert %x11|Custom Filter %x12|" - "Enable Filter %x-2|Disable Filter %x-1|Remove Filter %x0|"; - uiDefButS(block, MENU, B_REDR, str, xco+30, yco-24, width-60, 19, &tdfa->type, 0.0, 0.0, 0.0, 0.0, "2D filter type"); - - yco -= ysize; - break; - case ACT_PARENT: - parAct = act->data; - - if (parAct->type==ACT_PARENT_SET) { - - ysize= 48; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "OB:", xco+95, yco-24, (width-100), 19, &(parAct->ob), "Set this object as parent"); - uiBlockBeginAlign(block); - uiDefButBitS(block, TOGN, ACT_PARENT_COMPOUND, B_REDR, - "Compound", - xco + 5, yco - 44, (width - 10)/2, 19, &parAct->flag, - 0.0, 0.0, 0, 0, - "Add this object shape to the parent shape (only if the parent shape is already compound)"); - uiDefButBitS(block, TOGN, ACT_PARENT_GHOST, B_REDR, - "Ghost", - xco + 5 + ((width - 10)/2), yco - 44, (width - 10)/2, 19, &parAct->flag, - 0.0, 0.0, 0, 0, - "Make this object ghost while parented (only if not compound)"); - uiBlockEndAlign(block); - } - else if (parAct->type==ACT_PARENT_REMOVE) { - - ysize= 28; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - } - - str= "Parent %t|Set Parent %x0|Remove Parent %x1"; - uiDefButI(block, MENU, B_REDR, str, xco+5, yco-24, parAct->type==1?(width-80):90, 19, &parAct->type, 0.0, 0.0, 0, 0, ""); - - yco-= ysize; - break; - case ACT_ARMATURE: - armAct = act->data; - - if (ob->type == OB_ARMATURE) { - str= "Constraint %t|Run armature %x0|Enable %x1|Disable %x2|Set target %x3|Set weight %x4"; - uiDefButI(block, MENU, B_REDR, str, xco+5, yco-24, (width-10)*0.35, 19, &armAct->type, 0.0, 0.0, 0, 0, ""); - - switch (armAct->type) { - case ACT_ARM_RUN: - ysize = 28; - break; - default: - uiBlockBeginAlign(block); - but = uiDefBut(block, TEX, 1, "Bone: ", - (xco+5), (yco-44), (width-10)/2, 19, - armAct->posechannel, 0, MAX_NAME, 0, 0, - "Bone on which the constraint is defined"); - uiButSetFunc(but, check_armature_actuator, but, armAct); - but = uiDefBut(block, TEX, 1, "Cons: ", - (xco+5)+(width-10)/2, (yco-44), (width-10)/2, 19, - armAct->constraint, 0, MAX_NAME, 0, 0, - "Name of the constraint you want to control"); - uiButSetFunc(but, check_armature_actuator, but, armAct); - uiBlockEndAlign(block); - ysize = 48; - switch (armAct->type) { - case ACT_ARM_SETTARGET: - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "Target: ", xco+5, yco-64, (width-10), 19, &(armAct->target), "Set this object as the target of the constraint"); - uiDefIDPoinBut(block, test_obpoin_but, ID_OB, 1, "Secondary Target: ", xco+5, yco-84, (width-10), 19, &(armAct->subtarget), "Set this object as the secondary target of the constraint (only IK polar target at the moment)"); - ysize += 40; - break; - case ACT_ARM_SETWEIGHT: - uiDefButF(block, NUM, B_REDR, "Weight:", xco+5+(width-10)*0.35, yco-24, (width-10)*0.65, 19, &armAct->weight, 0.0, 1.0, 0.0, 0.0, "Set weight of this constraint"); - break; - } - } - } - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - yco-= ysize; - break; - - default: - ysize= 4; - - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - - yco-= ysize; - break; - } - - uiBlockSetEmboss(block, UI_EMBOSS); - - return yco-4; -} static void do_sensor_menu(bContext *C, void *UNUSED(arg), int event) { @@ -2974,11 +772,11 @@ static uiBlock *sensor_menu(bContext *C, ARegion *ar, void *UNUSED(arg)) block= uiBeginBlock(C, ar, __func__, UI_EMBOSSP); uiBlockSetButmFunc(block, do_sensor_menu, NULL); - uiDefBut(block, BUTM, 1, "Show Objects", 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, ""); - uiDefBut(block, BUTM, 1, "Hide Objects", 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, ""); + uiDefBut(block, BUTM, 1, IFACE_("Show Objects"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, ""); + uiDefBut(block, BUTM, 1, IFACE_("Hide Objects"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, ""); uiDefBut(block, SEPR, 0, "", 0, (short)(yco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefBut(block, BUTM, 1, "Show Sensors", 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 2, ""); - uiDefBut(block, BUTM, 1, "Hide Sensors", 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 3, ""); + uiDefBut(block, BUTM, 1, IFACE_("Show Sensors"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 2, ""); + uiDefBut(block, BUTM, 1, IFACE_("Hide Sensors"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 3, ""); uiBlockSetDirection(block, UI_TOP); uiEndBlock(C, block); @@ -3023,11 +821,11 @@ static uiBlock *controller_menu(bContext *C, ARegion *ar, void *UNUSED(arg)) block= uiBeginBlock(C, ar, __func__, UI_EMBOSSP); uiBlockSetButmFunc(block, do_controller_menu, NULL); - uiDefBut(block, BUTM, 1, "Show Objects", 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, ""); - uiDefBut(block, BUTM, 1, "Hide Objects", 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, ""); + uiDefBut(block, BUTM, 1, IFACE_("Show Objects"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, ""); + uiDefBut(block, BUTM, 1, IFACE_("Hide Objects"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, ""); uiDefBut(block, SEPR, 0, "", 0, (short)(yco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefBut(block, BUTM, 1, "Show Controllers", 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 2, 2, ""); - uiDefBut(block, BUTM, 1, "Hide Controllers", 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 3, 3, ""); + uiDefBut(block, BUTM, 1, IFACE_("Show Controllers"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 2, 2, ""); + uiDefBut(block, BUTM, 1, IFACE_("Hide Controllers"), 0, (short)(yco-=20), 160, 19, NULL, 0.0, 0.0, 3, 3, ""); uiBlockSetDirection(block, UI_TOP); uiEndBlock(C, block); @@ -3072,11 +870,11 @@ static uiBlock *actuator_menu(bContext *C, ARegion *ar, void *UNUSED(arg)) block= uiBeginBlock(C, ar, __func__, UI_EMBOSSP); uiBlockSetButmFunc(block, do_actuator_menu, NULL); - uiDefBut(block, BUTM, 1, "Show Objects", 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, ""); - uiDefBut(block, BUTM, 1, "Hide Objects", 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, ""); + uiDefBut(block, BUTM, 1, IFACE_("Show Objects"), 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, ""); + uiDefBut(block, BUTM, 1, IFACE_("Hide Objects"), 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, ""); uiDefBut(block, SEPR, 0, "", 0, (short)(xco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefBut(block, BUTM, 1, "Show Actuators", 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 2, ""); - uiDefBut(block, BUTM, 1, "Hide Actuators", 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 3, ""); + uiDefBut(block, BUTM, 1, IFACE_("Show Actuators"), 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 2, ""); + uiDefBut(block, BUTM, 1, IFACE_("Hide Actuators"), 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 3, ""); uiBlockSetDirection(block, UI_TOP); uiEndBlock(C, block); @@ -3084,8 +882,6 @@ static uiBlock *actuator_menu(bContext *C, ARegion *ar, void *UNUSED(arg)) return block; } - - static void check_controller_state_mask(bContext *UNUSED(C), void *arg1_but, void *arg2_mask) { unsigned int *cont_mask = arg2_mask; @@ -3096,17 +892,6 @@ static void check_controller_state_mask(bContext *UNUSED(C), void *arg1_but, voi but->retval = B_REDR; } -static int first_bit(unsigned int mask) -{ - int bit; - - for (bit=0; bit<32; bit++) { - if (mask & (1<state_mask), 0, 0, 0, 0, ""); @@ -3139,44 +924,6 @@ static uiBlock *controller_state_mask_menu(bContext *C, ARegion *ar, void *arg_c return block; } -static void do_object_state_menu(bContext *UNUSED(C), void *arg, int event) -{ - Object *ob = arg; - - switch (event) { - case 0: - ob->state = 0x3FFFFFFF; - break; - case 1: - ob->state = ob->init_state; - if (!ob->state) - ob->state = 1; - break; - case 2: - ob->init_state = ob->state; - break; - } -} - -static uiBlock *object_state_mask_menu(bContext *C, ARegion *ar, void *arg_obj) -{ - uiBlock *block; - short xco = 0; - - block= uiBeginBlock(C, ar, __func__, UI_EMBOSSP); - uiBlockSetButmFunc(block, do_object_state_menu, arg_obj); - - uiDefBut(block, BUTM, 1, "Set all bits", 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 0, ""); - uiDefBut(block, BUTM, 1, "Recall init state", 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 1, ""); - uiDefBut(block, SEPR, 0, "", 0, (short)(xco-=6), 160, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefBut(block, BUTM, 1, "Store init state", 0, (short)(xco-=20), 160, 19, NULL, 0.0, 0.0, 1, 2, ""); - - uiBlockSetDirection(block, UI_TOP); - uiEndBlock(C, block); - - return block; -} - static int is_sensor_linked(uiBlock *block, bSensor *sens) { bController *cont; @@ -3238,13 +985,13 @@ static void draw_sensor_internal_header(uiLayout *layout, PointerRNA *ptr) sub = uiLayoutRow(row, FALSE); uiLayoutSetActive(sub, (RNA_boolean_get(ptr, "use_pulse_true_level") || RNA_boolean_get(ptr, "use_pulse_false_level"))); - uiItemR(sub, ptr, "frequency", 0, "Freq", ICON_NONE); + uiItemR(sub, ptr, "frequency", 0, IFACE_("Freq"), ICON_NONE); row = uiLayoutRow(split, TRUE); uiItemR(row, ptr, "use_level", UI_ITEM_R_TOGGLE, NULL, ICON_NONE); uiItemR(row, ptr, "use_tap", UI_ITEM_R_TOGGLE, NULL, ICON_NONE); - uiItemR(split, ptr, "invert", UI_ITEM_R_TOGGLE, "Invert", ICON_NONE); + uiItemR(split, ptr, "invert", UI_ITEM_R_TOGGLE, IFACE_("Invert"), ICON_NONE); } /* sensors in alphabetical order */ @@ -3267,7 +1014,7 @@ static void draw_sensor_armature(uiLayout *layout, PointerRNA *ptr) uiLayout *row; if (ob->type != OB_ARMATURE) { - uiItemL(layout, "Sensor only available for armatures", ICON_NONE); + uiItemL(layout, IFACE_("Sensor only available for armatures"), ICON_NONE); return; } @@ -3369,7 +1116,7 @@ static void draw_sensor_keyboard(uiLayout *layout, PointerRNA *ptr) uiLayout *row, *col; row = uiLayoutRow(layout, FALSE); - uiItemL(row, "Key:", ICON_NONE); + uiItemL(row, IFACE_("Key:"), ICON_NONE); col = uiLayoutColumn(row, FALSE); uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_all_keys") == FALSE); uiItemR(col, ptr, "key", UI_ITEM_R_EVENT, "", ICON_NONE); @@ -3379,11 +1126,11 @@ static void draw_sensor_keyboard(uiLayout *layout, PointerRNA *ptr) col = uiLayoutColumn(layout, FALSE); uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_all_keys") == FALSE); row = uiLayoutRow(col, FALSE); - uiItemL(row, "First Modifier:", ICON_NONE); + uiItemL(row, IFACE_("First Modifier:"), ICON_NONE); uiItemR(row, ptr, "modifier_key_1", UI_ITEM_R_EVENT, "", ICON_NONE); row = uiLayoutRow(col, FALSE); - uiItemL(row, "Second Modifier:", ICON_NONE); + uiItemL(row, IFACE_("Second Modifier:"), ICON_NONE); uiItemR(row, ptr, "modifier_key_2", UI_ITEM_R_EVENT, "", ICON_NONE); RNA_pointer_create((ID *)ob, &RNA_GameObjectSettings, ob, &settings_ptr); @@ -3569,7 +1316,7 @@ static void draw_controller_header(uiLayout *layout, PointerRNA *ptr, int xco, i uiItemR(row, ptr, "type", 0, "", ICON_NONE); uiItemR(row, ptr, "name", 0, "", ICON_NONE); /* XXX provisory for Blender 2.50Beta */ - uiDefBlockBut(uiLayoutGetBlock(layout), controller_state_mask_menu, cont, state, (short)(xco+width-44), yco, 22+22, UI_UNIT_Y, "Set controller state index (from 1 to 30)"); + uiDefBlockBut(uiLayoutGetBlock(layout), controller_state_mask_menu, cont, state, (short)(xco+width-44), yco, 22+22, UI_UNIT_Y, IFACE_("Set controller state index (from 1 to 30)")); } else { uiItemL(row, controller_name(cont->type), ICON_NONE); @@ -3737,7 +1484,7 @@ static void draw_actuator_armature(uiLayout *layout, PointerRNA *ptr) PropertyRNA *bones_prop = NULL; if (ob->type != OB_ARMATURE) { - uiItemL(layout, "Actuator only available for armatures", ICON_NONE); + uiItemL(layout, IFACE_("Actuator only available for armatures"), ICON_NONE); return; } @@ -3843,7 +1590,7 @@ static void draw_actuator_constraint(uiLayout *layout, PointerRNA *ptr, bContext row = uiLayoutRow(layout, FALSE); col = uiLayoutColumn(row, TRUE); - uiItemL(col, "Range:", ICON_NONE); + uiItemL(col, IFACE_("Range:"), ICON_NONE); uiItemR(col, ptr, "range", 0, "", ICON_NONE); col = uiLayoutColumn(row, TRUE); @@ -3941,7 +1688,7 @@ static void draw_actuator_edit_object(uiLayout *layout, PointerRNA *ptr) break; case ACT_EDOB_REPLACE_MESH: if (ob->type != OB_MESH) { - uiItemL(layout, "Mode only available for mesh objects", ICON_NONE); + uiItemL(layout, IFACE_("Mode only available for mesh objects"), ICON_NONE); break; } split = uiLayoutSplit(layout, 0.6, FALSE); @@ -3959,7 +1706,7 @@ static void draw_actuator_edit_object(uiLayout *layout, PointerRNA *ptr) break; case ACT_EDOB_DYNAMICS: if (ob->type != OB_MESH) { - uiItemL(layout, "Mode only available for mesh objects", ICON_NONE); + uiItemL(layout, IFACE_("Mode only available for mesh objects"), ICON_NONE); break; } uiItemR(layout, ptr, "dynamic_operation", 0, NULL, ICON_NONE); @@ -4029,7 +1776,7 @@ static void draw_actuator_motion(uiLayout *layout, PointerRNA *ptr) uiLayout *split, *row, *col, *sub; int physics_type; - ob = (Object *)ptr->id.data; + ob = (Object *)ptr->id.data; RNA_pointer_create((ID *)ob, &RNA_GameObjectSettings, ob, &settings_ptr); physics_type = RNA_enum_get(&settings_ptr, "physics_type"); @@ -4047,8 +1794,8 @@ static void draw_actuator_motion(uiLayout *layout, PointerRNA *ptr) uiItemR(row, ptr, "offset_rotation", 0, NULL, ICON_NONE); uiItemR(split, ptr, "use_local_rotation", UI_ITEM_R_TOGGLE, NULL, ICON_NONE); - if (ELEM3(physics_type, OB_BODY_TYPE_DYNAMIC, OB_BODY_TYPE_RIGID, OB_BODY_TYPE_SOFT)) { - uiItemL(layout, "Dynamic Object Settings:", ICON_NONE); + if (ELEM3(physics_type, OB_BODY_TYPE_DYNAMIC, OB_BODY_TYPE_RIGID, OB_BODY_TYPE_SOFT)) { + uiItemL(layout, IFACE_("Dynamic Object Settings:"), ICON_NONE); split = uiLayoutSplit(layout, 0.9, FALSE); row = uiLayoutRow(split, FALSE); uiItemR(row, ptr, "force", 0, NULL, ICON_NONE); @@ -4198,7 +1945,7 @@ static void draw_actuator_random(uiLayout *layout, PointerRNA *ptr) break; case ACT_RANDOM_BOOL_UNIFORM: - uiItemL(row, "Choose between true and false, 50% chance each", ICON_NONE); + uiItemL(row, IFACE_("Choose between true and false, 50% chance each"), ICON_NONE); break; case ACT_RANDOM_BOOL_BERNOUILLI: @@ -4261,7 +2008,7 @@ static void draw_actuator_shape_action(uiLayout *layout, PointerRNA *ptr) uiLayout *row; if (ob->type != OB_MESH) { - uiItemL(layout, "Actuator only available for mesh objects", ICON_NONE); + uiItemL(layout, IFACE_("Actuator only available for mesh objects"), ICON_NONE); return; } @@ -4299,7 +2046,7 @@ static void draw_actuator_sound(uiLayout *layout, PointerRNA *ptr, bContext *C) uiTemplateID(layout, C, ptr, "sound", NULL, "SOUND_OT_open", NULL); if (!RNA_pointer_get(ptr, "sound").data) { - uiItemL(layout, "Select a sound from the list or load a new one", ICON_NONE); + uiItemL(layout, IFACE_("Select a sound from the list or load a new one"), ICON_NONE); return; } uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE); @@ -4458,21 +2205,18 @@ static void draw_brick_actuator(uiLayout *layout, PointerRNA *ptr, bContext *C) } } -static void logic_buttons_new(bContext *C, ARegion *ar) +void logic_buttons(bContext *C, ARegion *ar) { SpaceLogic *slogic= CTX_wm_space_logic(C); Object *ob= CTX_data_active_object(C); - Object *act_ob= ob; ID **idar; - - PointerRNA logic_ptr, settings_ptr; - + PointerRNA logic_ptr, settings_ptr, object_ptr; uiLayout *layout, *row, *box; uiBlock *block; uiBut *but; char uiblockstr[32]; short a, count; - int xco, yco, width; + int xco, yco, width, height; if (ob==NULL) return; @@ -4526,15 +2270,15 @@ static void logic_buttons_new(bContext *C, ARegion *ar) /* ****************** Controllers ****************** */ - xco= 420; yco= 170; width= 300; + xco= 420; yco= -10; width= 300; layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, xco, yco, width, 20, UI_GetStyle()); row = uiLayoutRow(layout, TRUE); - uiDefBlockBut(block, controller_menu, NULL, "Controllers", xco-10, yco, 300, UI_UNIT_Y, ""); /* replace this with uiLayout stuff later */ + uiDefBlockBut(block, controller_menu, NULL, IFACE_("Controllers"), xco-10, yco, 300, UI_UNIT_Y, ""); /* replace this with uiLayout stuff later */ - uiItemR(row, &logic_ptr, "show_controllers_selected_objects", 0, "Sel", ICON_NONE); - uiItemR(row, &logic_ptr, "show_controllers_active_object", 0, "Act", ICON_NONE); - uiItemR(row, &logic_ptr, "show_controllers_linked_controller", 0, "Link", ICON_NONE); + uiItemR(row, &logic_ptr, "show_controllers_selected_objects", 0, IFACE_("Sel"), ICON_NONE); + uiItemR(row, &logic_ptr, "show_controllers_active_object", 0, IFACE_("Act"), ICON_NONE); + uiItemR(row, &logic_ptr, "show_controllers_linked_controller", 0, IFACE_("Link"), ICON_NONE); for (a=0; aid.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide controllers"); - if (ob == act_ob) - uiItemMenuEnumO(row, "LOGIC_OT_controller_add", "type", "Add Controller", ICON_NONE); + uiDefButBitS(block, TOG, OB_SHOWCONT, B_REDR, ob->id.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide controllers")); + + RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr); + uiLayoutSetContextPointer(row, "object", &object_ptr); + uiItemMenuEnumO(row, "LOGIC_OT_controller_add", "type", IFACE_("Add Controller"), ICON_NONE); if (RNA_boolean_get(&settings_ptr, "show_state_panel")) { @@ -4567,16 +2313,16 @@ static void logic_buttons_new(bContext *C, ARegion *ar) split = uiLayoutSplit(box, 0.2f, FALSE); col = uiLayoutColumn(split, FALSE); - uiItemL(col, "Visible", ICON_NONE); - uiItemL(col, "Initial", ICON_NONE); + uiItemL(col, IFACE_("Visible"), ICON_NONE); + uiItemL(col, IFACE_("Initial"), ICON_NONE); subsplit = uiLayoutSplit(split, 0.85f, FALSE); col = uiLayoutColumn(subsplit, FALSE); row = uiLayoutRow(col, FALSE); uiLayoutSetActive(row, RNA_boolean_get(&settings_ptr, "use_all_states") == FALSE); - uiTemplateLayers(row, &settings_ptr, "states_visible", &settings_ptr, "used_states", 0); + uiTemplateGameStates(row, &settings_ptr, "states_visible", &settings_ptr, "used_states", 0); row = uiLayoutRow(col, FALSE); - uiTemplateLayers(row, &settings_ptr, "states_initial", &settings_ptr, "used_states", 0); + uiTemplateGameStates(row, &settings_ptr, "states_initial", &settings_ptr, "used_states", 0); col = uiLayoutColumn(subsplit, FALSE); uiItemR(col, &settings_ptr, "use_all_states", UI_ITEM_R_TOGGLE, NULL, ICON_NONE); @@ -4627,20 +2373,20 @@ static void logic_buttons_new(bContext *C, ARegion *ar) } } uiBlockLayoutResolve(block, NULL, &yco); /* stores final height in yco */ - + height = yco; /* ****************** Sensors ****************** */ - xco= 10; yco= 170; width= 340; + xco= 10; yco= -10; width= 340; layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, xco, yco, width, 20, UI_GetStyle()); row = uiLayoutRow(layout, TRUE); - uiDefBlockBut(block, sensor_menu, NULL, "Sensors", xco-10, yco, 300, UI_UNIT_Y, ""); /* replace this with uiLayout stuff later */ + uiDefBlockBut(block, sensor_menu, NULL, IFACE_("Sensors"), xco-10, yco, 300, UI_UNIT_Y, ""); /* replace this with uiLayout stuff later */ - uiItemR(row, &logic_ptr, "show_sensors_selected_objects", 0, "Sel", ICON_NONE); - uiItemR(row, &logic_ptr, "show_sensors_active_object", 0, "Act", ICON_NONE); - uiItemR(row, &logic_ptr, "show_sensors_linked_controller", 0, "Link", ICON_NONE); - uiItemR(row, &logic_ptr, "show_sensors_active_states", 0, "State", ICON_NONE); + uiItemR(row, &logic_ptr, "show_sensors_selected_objects", 0, IFACE_("Sel"), ICON_NONE); + uiItemR(row, &logic_ptr, "show_sensors_active_object", 0, IFACE_("Act"), ICON_NONE); + uiItemR(row, &logic_ptr, "show_sensors_linked_controller", 0, IFACE_("Link"), ICON_NONE); + uiItemR(row, &logic_ptr, "show_sensors_active_states", 0, IFACE_("State"), ICON_NONE); for (a=0; ascavisflag & OB_VIS_SENS) == 0) continue; row = uiLayoutRow(layout, TRUE); - uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide sensors"); - if (ob == act_ob) - uiItemMenuEnumO(row, "LOGIC_OT_sensor_add", "type", "Add Sensor", ICON_NONE); + uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide sensors")); + + RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr); + uiLayoutSetContextPointer(row, "object", &object_ptr); + uiItemMenuEnumO(row, "LOGIC_OT_sensor_add", "type", IFACE_("Add Sensor"), ICON_NONE); if ((ob->scaflag & OB_SHOWSENS) == 0) continue; @@ -4694,19 +2442,20 @@ static void logic_buttons_new(bContext *C, ARegion *ar) } } uiBlockLayoutResolve(block, NULL, &yco); /* stores final height in yco */ + height = MIN2(height, yco); /* ****************** Actuators ****************** */ - xco= 800; yco= 170; width= 340; + xco= 800; yco= -10; width= 340; layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, xco, yco, width, 20, UI_GetStyle()); row = uiLayoutRow(layout, TRUE); - uiDefBlockBut(block, actuator_menu, NULL, "Actuators", xco-10, yco, 300, UI_UNIT_Y, ""); /* replace this with uiLayout stuff later */ + uiDefBlockBut(block, actuator_menu, NULL, IFACE_("Actuators"), xco-10, yco, 300, UI_UNIT_Y, ""); /* replace this with uiLayout stuff later */ - uiItemR(row, &logic_ptr, "show_actuators_selected_objects", 0, "Sel", ICON_NONE); - uiItemR(row, &logic_ptr, "show_actuators_active_object", 0, "Act", ICON_NONE); - uiItemR(row, &logic_ptr, "show_actuators_linked_controller", 0, "Link", ICON_NONE); - uiItemR(row, &logic_ptr, "show_actuators_active_states", 0, "State", ICON_NONE); + uiItemR(row, &logic_ptr, "show_actuators_selected_objects", 0, IFACE_("Sel"), ICON_NONE); + uiItemR(row, &logic_ptr, "show_actuators_active_object", 0, IFACE_("Act"), ICON_NONE); + uiItemR(row, &logic_ptr, "show_actuators_linked_controller", 0, IFACE_("Link"), ICON_NONE); + uiItemR(row, &logic_ptr, "show_actuators_active_states", 0, IFACE_("State"), ICON_NONE); for (a=0; aid.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide actuators"); - if (ob == act_ob) - uiItemMenuEnumO(row, "LOGIC_OT_actuator_add", "type", "Add Actuator", ICON_NONE); + uiDefButBitS(block, TOG, OB_SHOWACT, B_REDR, ob->id.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide actuators")); + + RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr); + uiLayoutSetContextPointer(row, "object", &object_ptr); + uiItemMenuEnumO(row, "LOGIC_OT_actuator_add", "type", IFACE_("Add Actuator"), ICON_NONE); if ((ob->scaflag & OB_SHOWACT) == 0) continue; @@ -4763,387 +2514,21 @@ static void logic_buttons_new(bContext *C, ARegion *ar) } } uiBlockLayoutResolve(block, NULL, &yco); /* stores final height in yco */ + height = MIN2(height, yco); + + UI_view2d_totRect_set(&ar->v2d, 1150, height); - + /* set the view */ + UI_view2d_view_ortho(&ar->v2d); + uiComposeLinks(block); uiEndBlock(C, block); uiDrawBlock(C, block); + /* restore view matrix */ + UI_view2d_view_restore(C); + if (idar) MEM_freeN(idar); } -void logic_buttons(bContext *C, ARegion *ar) -{ - Main *bmain= CTX_data_main(C); - SpaceLogic *slogic= CTX_wm_space_logic(C); - Object *ob= CTX_data_active_object(C); - ID **idar; - bSensor *sens; - bController *cont; - bActuator *act; - uiBlock *block; - uiBut *but; - PointerRNA logic_ptr; - int a, iact, stbit, offset; - int xco, yco, width, ycoo; - short count; - char numstr[32]; - /* pin is a bool used for actuator and sensor drawing with states - * pin so changing states dosnt hide the logic brick */ - char pin; - - if (G.debug_value == 0) { - logic_buttons_new(C, ar); - return; - } - - if (ob==NULL) return; -// uiSetButLock(BKE_object_is_libdata(ob), ERROR_LIBDATA_MESSAGE); - - BLI_snprintf(numstr, sizeof(numstr), "buttonswin %p", (void *)ar); - block= uiBeginBlock(C, ar, numstr, UI_EMBOSS); - uiBlockSetHandleFunc(block, do_logic_buts, NULL); - - RNA_pointer_create(NULL, &RNA_SpaceLogicEditor, slogic, &logic_ptr); - - idar= get_selected_and_linked_obs(C, &count, slogic->scaflag); - - /* clean ACT_LINKED and ACT_VISIBLE of all potentially visible actuators so that - * we can determine which is actually linked/visible */ - for (a=0; aactuators.first; - while (act) { - act->flag &= ~(ACT_LINKED|ACT_VISIBLE); - act = act->next; - } - /* same for sensors */ - sens= ob->sensors.first; - while (sens) { - sens->flag &= ~(SENS_VISIBLE); - sens = sens->next; - } - } - - /* start with the controller because we need to know which one is visible */ - /* ******************************* */ - xco= 400; yco= 170; width= 300; - - uiDefBlockBut(block, controller_menu, NULL, "Controllers", xco-10, yco+35, 100, UI_UNIT_Y, ""); - - uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, BUTS_CONT_SEL, B_REDR, "Sel", xco+110, yco+35, (width-100)/3, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show all selected Objects"); - uiDefButBitS(block, TOG, BUTS_CONT_ACT, B_REDR, "Act", xco+110+(width-100)/3, yco+35, (width-100)/3, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show active Object"); - uiDefButBitS(block, TOG, BUTS_CONT_LINK, B_REDR, "Link", xco+110+2*(width-100)/3, yco+35, (width-100)/3, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show linked Objects to Sensor/Actuator"); - uiBlockEndAlign(block); - - for (a=0; ascavisflag & OB_VIS_CONT) == 0) { - continue; - } - - /* presume it is only objects for now */ - uiBlockBeginAlign(block); -// if (ob->controllers.first) uiSetCurFont(block, UI_HELVB); - uiDefButBitS(block, TOG, OB_SHOWCONT, B_REDR, ob->id.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Active Object name"); -// if (ob->controllers.first) uiSetCurFont(block, UI_HELV); - uiDefButBitS(block, TOG, OB_ADDCONT, B_ADD_CONT, "Add", (short)(xco+width-40), yco, 50, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Add a new Controller"); - uiBlockEndAlign(block); - yco-=20; - - /* mark all actuators linked to these controllers */ - /* note that some of these actuators could be from objects that are not in the display list. - * It's ok because those actuators will not be displayed here */ - cont= ob->controllers.first; - while (cont) { - for (iact=0; iacttotlinks; iact++) { - act = cont->links[iact]; - if (act) - act->flag |= ACT_LINKED; - } - controller_state_mask |= cont->state_mask; - cont = cont->next; - } - - if (ob->scaflag & OB_SHOWCONT) { - - /* first show the state */ - uiDefBlockBut(block, object_state_mask_menu, ob, "State", (short)(xco-10), (short)(yco-10), 36, UI_UNIT_Y, "Object state menu: store and retrieve initial state"); - - if (!ob->state) - ob->state = 1; - for (offset=0; offset<15; offset+=5) { - uiBlockBeginAlign(block); - for (stbit=0; stbit<5; stbit++) { - but = uiDefButBitI(block, controller_state_mask&(1<<(stbit+offset)) ? BUT_TOGDUAL:TOG, 1<<(stbit+offset), stbit+offset, "", (short)(xco+31+12*stbit+13*offset), yco, 12, 12, (int *)&(ob->state), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+offset))); - uiButSetFunc(but, check_state_mask, but, &(ob->state)); - } - for (stbit=0; stbit<5; stbit++) { - but = uiDefButBitI(block, controller_state_mask&(1<<(stbit+offset+15)) ? BUT_TOGDUAL:TOG, 1<<(stbit+offset+15), stbit+offset+15, "", (short)(xco+31+12*stbit+13*offset), yco-12, 12, 12, (int *)&(ob->state), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+offset+15))); - uiButSetFunc(but, check_state_mask, but, &(ob->state)); - } - } - uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, OB_ALLSTATE, B_SET_STATE_BIT, "All", (short)(xco+226), yco-10, 22, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Set all state bits"); - uiDefButBitS(block, TOG, OB_INITSTBIT, B_INIT_STATE_BIT, "Ini", (short)(xco+248), yco-10, 22, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Set the initial state"); - uiDefButBitS(block, TOG, OB_DEBUGSTATE, 0, "D", (short)(xco+270), yco-10, 15, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Print state debug info"); - uiBlockEndAlign(block); - - yco-=35; - - /* display only the controllers that match the current state */ - offset = 0; - for (stbit=0; stbit<32; stbit++) { - if (!(ob->state & (1<controllers.first; - while (cont) { - if (cont->state_mask & (1<totlinks; iact++) { - act = cont->links[iact]; - if (act) - act->flag |= ACT_VISIBLE; - } - uiDefIconButBitS(block, TOG, CONT_DEL, B_DEL_CONT, ICON_X, xco, yco, 22, UI_UNIT_Y, &cont->flag, 0, 0, 0, 0, "Delete Controller"); - uiDefIconButBitS(block, ICONTOG, CONT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, UI_UNIT_Y, &cont->flag, 0, 0, 0, 0, "Controller settings"); - uiDefIconButBitS(block, TOG, CONT_PRIO, B_REDR, ICON_BOOKMARKS, (short)(xco+width-66), yco, 22, UI_UNIT_Y, &cont->flag, 0, 0, 0, 0, "Mark controller for execution before all non-marked controllers (good for startup scripts)"); - - sprintf(numstr, "%d", first_bit(cont->state_mask)+1); - uiDefBlockBut(block, controller_state_mask_menu, cont, numstr, (short)(xco+width-44), yco, 22, UI_UNIT_Y, "Set controller state index (from 1 to 30)"); - - if (cont->flag & CONT_SHOW) { - cont->otype= cont->type; - uiDefButS(block, MENU, B_CHANGE_CONT, controller_pup(), (short)(xco+22), yco, 70, UI_UNIT_Y, &cont->type, 0, 0, 0, 0, "Controller type"); - but = uiDefBut(block, TEX, 1, "", (short)(xco+92), yco, (short)(width-158), UI_UNIT_Y, cont->name, 0, MAX_NAME, 0, 0, "Controller name"); - uiButSetFunc(but, make_unique_prop_names_cb, cont->name, (void*) 0); - - ycoo= yco; - yco= draw_controllerbuttons(cont, block, xco, yco, width); - if (yco-6 < ycoo) ycoo= (yco+ycoo-20)/2; - } - else { - cpack(0x999999); - glRecti(xco+22, yco, xco+width-22, yco+19); - but = uiDefBut(block, LABEL, 0, controller_name(cont->type), (short)(xco+22), yco, 70, UI_UNIT_Y, cont, 0, 0, 0, 0, "Controller type"); - //uiButSetFunc(but, old_sca_move_controller, cont, NULL); - but = uiDefBut(block, LABEL, 0, cont->name, (short)(xco+92), yco, (short)(width-158), UI_UNIT_Y, cont, 0, 0, 0, 0, "Controller name"); - //uiButSetFunc(but, old_sca_move_controller, cont, NULL); - - uiBlockBeginAlign(block); - but = uiDefIconBut(block, BUT, B_REDR, ICON_TRIA_UP, (short)(xco+width-(110+5)), yco, 22, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Move this logic brick up"); - uiButSetFunc(but, old_sca_move_controller, cont, (void *)TRUE); - but = uiDefIconBut(block, BUT, B_REDR, ICON_TRIA_DOWN, (short)(xco+width-(88+5)), yco, 22, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Move this logic brick down"); - uiButSetFunc(but, old_sca_move_controller, cont, (void *)FALSE); - uiBlockEndAlign(block); - - ycoo= yco; - } - - but = uiDefIconBut(block, LINK, 0, ICON_LINK, (short)(xco+width), ycoo, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); - uiSetButLink(but, NULL, (void ***)&(cont->links), &cont->totlinks, LINK_CONTROLLER, LINK_ACTUATOR); - - uiDefIconBut(block, INLINK, 0, ICON_INLINK, (short)(xco-19), ycoo, UI_UNIT_X, UI_UNIT_Y, cont, LINK_CONTROLLER, 0, 0, 0, ""); - /* offset is >0 if at least one controller was displayed */ - offset++; - yco-=20; - } - cont= cont->next; - } - - } - yco-= 6; - } - } - - /* ******************************* */ - xco= 10; yco= 170; width= 300; - - uiDefBlockBut(block, sensor_menu, NULL, "Sensors", xco-10, yco+35, 70, UI_UNIT_Y, ""); - - uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, BUTS_SENS_SEL, B_REDR, "Sel", xco+80, yco+35, (width-70)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show all selected Objects"); - uiDefButBitS(block, TOG, BUTS_SENS_ACT, B_REDR, "Act", xco+80+(width-70)/4, yco+35, (width-70)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show active Object"); - uiDefButBitS(block, TOG, BUTS_SENS_LINK, B_REDR, "Link", xco+80+2*(width-70)/4, yco+35, (width-70)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller"); - uiDefButBitS(block, TOG, BUTS_SENS_STATE, B_REDR, "State", xco+80+3*(width-70)/4, yco+35, (width-70)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show only sensors connected to active states"); - uiBlockEndAlign(block); - - for (a=0; ascavisflag & OB_VIS_SENS) == 0) { - continue; - } - - /* presume it is only objects for now */ - uiBlockBeginAlign(block); -// if (ob->sensors.first) uiSetCurFont(block, UI_HELVB); - uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide sensors"); -// if (ob->sensors.first) uiSetCurFont(block, UI_HELV); - uiDefButBitS(block, TOG, OB_ADDSENS, B_ADD_SENS, "Add", (short)(xco+width-40), yco, 50, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Add a new Sensor"); - uiBlockEndAlign(block); - yco-=20; - - if (ob->scaflag & OB_SHOWSENS) { - - sens= ob->sensors.first; - while (sens) { - if (!(slogic->scaflag & BUTS_SENS_STATE) || - (sens->totlinks == 0) || /* always display sensor without links so that is can be edited */ - (sens->flag & SENS_PIN && slogic->scaflag & BUTS_SENS_STATE) || /* states can hide some sensors, pinned sensors ignore the visible state */ - (is_sensor_linked(block, sens)) - ) { - /* should we draw the pin? - for now always draw when there is a state */ - pin = (slogic->scaflag & BUTS_SENS_STATE && (sens->flag & SENS_SHOW || sens->flag & SENS_PIN)) ? 1 : 0; - - sens->flag |= SENS_VISIBLE; - uiDefIconButBitS(block, TOG, SENS_DEL, B_DEL_SENS, ICON_X, xco, yco, 22, UI_UNIT_Y, &sens->flag, 0, 0, 0, 0, "Delete Sensor"); - if (pin) - uiDefIconButBitS(block, ICONTOG, SENS_PIN, B_REDR, ICON_PINNED, (short)(xco+width-44), yco, 22, UI_UNIT_Y, &sens->flag, 0, 0, 0, 0, "Display when not linked to a visible states controller"); - - uiDefIconButBitS(block, ICONTOG, SENS_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, UI_UNIT_Y, &sens->flag, 0, 0, 0, 0, "Sensor settings"); - - ycoo= yco; - if (sens->flag & SENS_SHOW) { - uiDefButS(block, MENU, B_CHANGE_SENS, sensor_pup(), (short)(xco+22), yco, 80, UI_UNIT_Y, &sens->type, 0, 0, 0, 0, "Sensor type"); - but = uiDefBut(block, TEX, 1, "", (short)(xco+102), yco, (short)(width-(pin?146:124)), UI_UNIT_Y, sens->name, 0, MAX_NAME, 0, 0, "Sensor name"); - uiButSetFunc(but, make_unique_prop_names_cb, sens->name, (void*) 0); - - sens->otype= sens->type; - yco= draw_sensorbuttons(ob, sens, block, xco, yco, width); - if (yco-6 < ycoo) ycoo= (yco+ycoo-20)/2; - } - else { - set_col_sensor(sens->type, 1); - glRecti(xco + 22, yco, xco + width - 22, yco + 19); - but = uiDefBut(block, LABEL, 0, sensor_name(sens->type), (short)(xco+22), yco, 80, UI_UNIT_Y, sens, 0, 0, 0, 0, ""); - //uiButSetFunc(but, old_sca_move_sensor, sens, NULL); - but = uiDefBut(block, LABEL, 0, sens->name, (short)(xco+102), yco, (short)(width-(pin?146:124)), UI_UNIT_Y, sens, 0, MAX_NAME, 0, 0, ""); - //uiButSetFunc(but, old_sca_move_sensor, sens, NULL); - - uiBlockBeginAlign(block); - but = uiDefIconBut(block, BUT, B_REDR, ICON_TRIA_UP, (short)(xco+width-(66+5)), yco, 22, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Move this logic brick up"); - uiButSetFunc(but, old_sca_move_sensor, sens, (void *)TRUE); - but = uiDefIconBut(block, BUT, B_REDR, ICON_TRIA_DOWN, (short)(xco+width-(44+5)), yco, 22, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Move this logic brick down"); - uiButSetFunc(but, old_sca_move_sensor, sens, (void *)FALSE); - uiBlockEndAlign(block); - } - - but = uiDefIconBut(block, LINK, 0, ICON_LINK, (short)(xco+width), ycoo, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); - uiSetButLink(but, NULL, (void ***)&(sens->links), &sens->totlinks, LINK_SENSOR, LINK_CONTROLLER); - - yco-=20; - } - sens= sens->next; - } - yco-= 6; - } - } - /* ******************************* */ - xco= 800; yco= 170; width= 300; - uiDefBlockBut(block, actuator_menu, NULL, "Actuators", xco-10, yco+35, 90, UI_UNIT_Y, ""); - - uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, BUTS_ACT_SEL, B_REDR, "Sel", xco+110, yco+35, (width-100)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show all selected Objects"); - uiDefButBitS(block, TOG, BUTS_ACT_ACT, B_REDR, "Act", xco+110+(width-100)/4, yco+35, (width-100)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show active Object"); - uiDefButBitS(block, TOG, BUTS_ACT_LINK, B_REDR, "Link", xco+110+2*(width-100)/4, yco+35, (width-100)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show linked Objects to Controller"); - uiDefButBitS(block, TOG, BUTS_ACT_STATE, B_REDR, "State", xco+110+3*(width-100)/4, yco+35, (width-100)/4, UI_UNIT_Y, &slogic->scaflag, 0, 0, 0, 0, "Show only actuators connected to active states"); - uiBlockEndAlign(block); - for (a=0; ascavisflag & OB_VIS_ACT) == 0) { - continue; - } - - /* presume it is only objects for now */ - uiBlockBeginAlign(block); -// if (ob->actuators.first) uiSetCurFont(block, UI_HELVB); - uiDefButBitS(block, TOG, OB_SHOWACT, B_REDR, ob->id.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide actuators"); -// if (ob->actuators.first) uiSetCurFont(block, UI_HELV); - uiDefButBitS(block, TOG, OB_ADDACT, B_ADD_ACT, "Add", (short)(xco+width-40), yco, 50, UI_UNIT_Y, &ob->scaflag, 0, 0, 0, 0, "Add a new Actuator"); - uiBlockEndAlign(block); - yco-=20; - - if (ob->scaflag & OB_SHOWACT) { - - act= ob->actuators.first; - while (act) { - if (!(slogic->scaflag & BUTS_ACT_STATE) || - !(act->flag & ACT_LINKED) || /* always display actuators without links so that is can be edited */ - (act->flag & ACT_VISIBLE) || /* this actuator has visible connection, display it */ - (act->flag & ACT_PIN && slogic->scaflag & BUTS_ACT_STATE)) - { - pin = (slogic->scaflag & BUTS_ACT_STATE && (act->flag & SENS_SHOW || act->flag & SENS_PIN)) ? 1 : 0; - - act->flag |= ACT_VISIBLE; /* mark the actuator as visible to help implementing the up/down action */ - uiDefIconButBitS(block, TOG, ACT_DEL, B_DEL_ACT, ICON_X, xco, yco, 22, UI_UNIT_Y, &act->flag, 0, 0, 0, 0, "Delete Actuator"); - if (pin) - uiDefIconButBitS(block, ICONTOG, ACT_PIN, B_REDR, ICON_PINNED, (short)(xco+width-44), yco, 22, UI_UNIT_Y, &act->flag, 0, 0, 0, 0, "Display when not linked to a visible states controller"); - uiDefIconButBitS(block, ICONTOG, ACT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, UI_UNIT_Y, &act->flag, 0, 0, 0, 0, "Display the actuator"); - - if (act->flag & ACT_SHOW) { - act->otype= act->type; - uiDefButS(block, MENU, B_CHANGE_ACT, actuator_pup(ob), (short)(xco+22), yco, 90, UI_UNIT_Y, &act->type, 0, 0, 0, 0, "Actuator type"); - but = uiDefBut(block, TEX, 1, "", (short)(xco+112), yco, (short)(width-(pin?156:134)), UI_UNIT_Y, act->name, 0, MAX_NAME, 0, 0, "Actuator name"); - uiButSetFunc(but, make_unique_prop_names_cb, act->name, (void*) 0); - - ycoo= yco; - yco= draw_actuatorbuttons(bmain, ob, act, block, xco, yco, width); - if (yco-6 < ycoo) ycoo= (yco+ycoo-20)/2; - } - else { - set_col_actuator(act->type, 1); - glRecti((short)(xco+22), yco, (short)(xco+width-22), (short)(yco+19)); - /* but= */ uiDefBut(block, LABEL, 0, actuator_name(act->type), (short)(xco+22), yco, 90, UI_UNIT_Y, act, 0, 0, 0, 0, "Actuator type"); - // uiButSetFunc(but, old_sca_move_actuator, act, NULL); - /* but= */ uiDefBut(block, LABEL, 0, act->name, (short)(xco+112), yco, (short)(width-(pin?156:134)), UI_UNIT_Y, act, 0, 0, 0, 0, "Actuator name"); - // uiButSetFunc(but, old_sca_move_actuator, act, NULL); - - uiBlockBeginAlign(block); - but = uiDefIconBut(block, BUT, B_REDR, ICON_TRIA_UP, (short)(xco+width-(66+5)), yco, 22, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Move this logic brick up"); - uiButSetFunc(but, old_sca_move_actuator, act, (void *)TRUE); - but = uiDefIconBut(block, BUT, B_REDR, ICON_TRIA_DOWN, (short)(xco+width-(44+5)), yco, 22, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Move this logic brick down"); - uiButSetFunc(but, old_sca_move_actuator, act, (void *)FALSE); - uiBlockEndAlign(block); - - ycoo= yco; - } - - uiDefIconBut(block, INLINK, 0, ICON_INLINK, (short)(xco - 19), ycoo, UI_UNIT_X, UI_UNIT_Y, act, LINK_ACTUATOR, 0, 0, 0, ""); - - yco-=20; - } - act= act->next; - } - yco-= 6; - } - } - - uiComposeLinks(block); - - uiEndBlock(C, block); - uiDrawBlock(C, block); - - if (idar) MEM_freeN(idar); -} - - - - - - diff --git a/source/blender/editors/space_logic/space_logic.c b/source/blender/editors/space_logic/space_logic.c index 1a50f72153a..4cd53215697 100644 --- a/source/blender/editors/space_logic/space_logic.c +++ b/source/blender/editors/space_logic/space_logic.c @@ -62,20 +62,20 @@ ARegion *logic_has_buttons_region(ScrArea *sa) { ARegion *ar, *arnew; - ar= BKE_area_find_region_type(sa, RGN_TYPE_UI); + ar = BKE_area_find_region_type(sa, RGN_TYPE_UI); if (ar) return ar; /* add subdiv level; after header */ - ar= BKE_area_find_region_type(sa, RGN_TYPE_HEADER); + ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER); /* is error! */ - if (ar==NULL) return NULL; + if (ar == NULL) return NULL; arnew= MEM_callocN(sizeof(ARegion), "buttons for image"); BLI_insertlinkafter(&sa->regionbase, ar, arnew); - arnew->regiontype= RGN_TYPE_UI; - arnew->alignment= RGN_ALIGN_LEFT; + arnew->regiontype = RGN_TYPE_UI; + arnew->alignment = RGN_ALIGN_LEFT; arnew->flag = RGN_FLAG_HIDDEN; @@ -84,8 +84,9 @@ ARegion *logic_has_buttons_region(ScrArea *sa) /* ******************** default callbacks for image space ***************** */ -static SpaceLink *logic_new(const bContext *UNUSED(C)) +static SpaceLink *logic_new(const bContext *C) { + ScrArea *sa= CTX_wm_area(C); ARegion *ar; SpaceLogic *slogic; @@ -93,10 +94,10 @@ static SpaceLink *logic_new(const bContext *UNUSED(C)) slogic->spacetype= SPACE_LOGIC; /* default options */ - slogic->scaflag = (BUTS_SENS_SEL|BUTS_SENS_ACT|BUTS_SENS_LINK) | - (BUTS_CONT_SEL|BUTS_CONT_ACT|BUTS_CONT_LINK) | - (BUTS_ACT_SEL|BUTS_ACT_ACT|BUTS_ACT_LINK) | - (BUTS_SENS_STATE|BUTS_ACT_STATE); + slogic->scaflag = ((BUTS_SENS_SEL|BUTS_SENS_ACT|BUTS_SENS_LINK) | + (BUTS_CONT_SEL|BUTS_CONT_ACT|BUTS_CONT_LINK) | + (BUTS_ACT_SEL|BUTS_ACT_ACT|BUTS_ACT_LINK) | + (BUTS_SENS_STATE|BUTS_ACT_STATE)); /* header */ @@ -120,28 +121,26 @@ static SpaceLink *logic_new(const bContext *UNUSED(C)) ar->regiontype= RGN_TYPE_WINDOW; ar->v2d.tot.xmin = 0.0f; - ar->v2d.tot.ymin = 0.0f; - ar->v2d.tot.xmax = 1280; - ar->v2d.tot.ymax = 240.0f; + ar->v2d.tot.ymax = 0.0f; + ar->v2d.tot.xmax = 1150.0f; + ar->v2d.tot.ymin = ( 1150.0f/(float)sa->winx ) * (float)-sa->winy; - ar->v2d.cur.xmin = 0.0f; - ar->v2d.cur.ymin = 0.0f; - ar->v2d.cur.xmax = 1280.0f; - ar->v2d.cur.ymax = 240.0f; + ar->v2d.cur = ar->v2d.tot; - ar->v2d.min[0]= 1.0f; - ar->v2d.min[1]= 1.0f; + ar->v2d.min[0] = 1.0f; + ar->v2d.min[1] = 1.0f; - ar->v2d.max[0]= 32000.0f; - ar->v2d.max[1]= 32000.0f; + ar->v2d.max[0] = 32000.0f; + ar->v2d.max[1] = 32000.0f; - ar->v2d.minzoom= 0.5f; - ar->v2d.maxzoom= 1.21f; - - ar->v2d.scroll= (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM); - ar->v2d.keepzoom= V2D_LIMITZOOM|V2D_KEEPASPECT; - ar->v2d.keeptot= 0; + ar->v2d.minzoom = 0.5f; + ar->v2d.maxzoom = 1.5f; + ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM); + ar->v2d.keepzoom = V2D_KEEPZOOM | V2D_LIMITZOOM | V2D_KEEPASPECT; + ar->v2d.keeptot = V2D_KEEPTOT_BOUNDS; + ar->v2d.align = V2D_ALIGN_NO_POS_Y | V2D_ALIGN_NO_NEG_X; + ar->v2d.keepofs = V2D_KEEPOFS_Y; return (SpaceLink *)slogic; } @@ -183,6 +182,9 @@ static void logic_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "LOGIC_OT_properties", NKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "LOGIC_OT_links_cut", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); WM_keymap_add_menu(keymap, "LOGIC_MT_logicbricks_add", AKEY, KM_PRESS, KM_SHIFT, 0); + + WM_keymap_add_item(keymap, "VIEW2D_OT_reset", HOMEKEY, KM_PRESS, 0, 0); + } static void logic_refresh(const bContext *UNUSED(C), ScrArea *UNUSED(sa)) @@ -234,7 +236,7 @@ static void logic_main_area_init(wmWindowManager *wm, ARegion *ar) wmKeyMap *keymap; UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy); - + /* own keymaps */ keymap = WM_keymap_find(wm->defaultconf, "Logic Editor", SPACE_LOGIC, 0); WM_event_add_keymap_handler(&ar->handlers, keymap); @@ -259,7 +261,7 @@ static void logic_main_area_draw(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); /* scrollers */ - scrollers= UI_view2d_scrollers_calc(C, v2d, 10, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY); + scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY); UI_view2d_scrollers_draw(C, v2d, scrollers); UI_view2d_scrollers_free(scrollers); diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 804d44ba720..d75946c4317 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -67,14 +67,11 @@ /* ******************* nla editor space & buttons ************** */ -#define B_NOP 1 -#define B_REDR 2 - /* -------------- */ static void do_nla_region_buttons(bContext *C, void *UNUSED(arg), int event) { - //Scene *scene= CTX_data_scene(C); + //Scene *scene = CTX_data_scene(C); switch (event) { @@ -159,7 +156,7 @@ static int nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA found = -1; } } - } + } break; } @@ -245,7 +242,7 @@ static void nla_panel_animdata(const bContext *C, Panel *pa) if (!nla_panel_context(C, &adt_ptr, NULL, NULL)) return; - /* adt= adt_ptr.data; */ + /* adt = adt_ptr.data; */ block = uiLayoutGetBlock(layout); uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL); @@ -408,7 +405,7 @@ static void nla_panel_evaluation(const bContext *C, Panel *pa) uiItemR(col, &strip_ptr, "use_animated_influence", 0, NULL, ICON_NONE); sub = uiLayoutColumn(col, TRUE); - uiLayoutSetEnabled(sub, RNA_boolean_get(&strip_ptr, "use_animated_influence")); + uiLayoutSetEnabled(sub, RNA_boolean_get(&strip_ptr, "use_animated_influence")); uiItemR(sub, &strip_ptr, "influence", 0, NULL, ICON_NONE); col = uiLayoutColumn(layout, TRUE); diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index b3a869ed57d..95e75d0e4fc 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -199,7 +199,7 @@ static int mouse_nla_channels(bAnimContext *ac, float x, int channel_index, shor } notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); - } + } break; case ANIMTYPE_NLATRACK: diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 92f014fd804..fd999bf2476 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -163,7 +163,7 @@ static void nla_strip_get_color_inside(AnimData *adt, NlaStrip *strip, float col /* normal, unselected strip - use (hardly noticeable) blue tinge */ UI_GetThemeColor3fv(TH_NLA_TRANSITION, color); } - } + } else if (strip->type == NLASTRIP_TYPE_META) { /* Meta Clip */ // TODO: should temporary metas get different colors too? @@ -528,7 +528,7 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar) */ v2d->tot.ymin = (float)(-height); - /* loop through channels, and set up drawing depending on their type */ + /* loop through channels, and set up drawing depending on their type */ y = (float)(-NLACHANNEL_HEIGHT(snla)); for (ale = anim_data.first; ale; ale = ale->next) { @@ -628,7 +628,7 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View bAnimListElem *ale; float x = 0.0f; - /* loop through channels, and set up drawing depending on their type */ + /* loop through channels, and set up drawing depending on their type */ for (ale = anim_data->first; ale; ale = ale->next) { const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla)); const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla)); @@ -709,7 +709,7 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View // draw backdrops only... ANIM_channel_draw(ac, ale, yminc, ymaxc); break; - } + } /* if special types, draw manually for now... */ if (do_draw) { @@ -737,7 +737,7 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View /* even more */ offset = 21; indent = 1; - } + } break; default: @@ -775,7 +775,7 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View glColor3fv(color); } else { - float alpha = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3 : 1.0f; + float alpha = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3f : 1.0f; glColor4f(color[0], color[1], color[2], alpha); } @@ -849,8 +849,6 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View /* draw NLA-action line 'status-icons' - only when there's an action */ if ((ale->type == ANIMTYPE_NLAACTION) && (ale->data)) { - AnimData *adt = ale->adt; - offset += 16; /* now draw some indicator icons */ @@ -938,7 +936,7 @@ void draw_nla_channel_list(bContext *C, bAnimContext *ac, ARegion *ar) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - /* loop through channels, and set up drawing depending on their type */ + /* loop through channels, and set up drawing depending on their type */ for (ale = anim_data.first; ale; ale = ale->next) { const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla)); const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla)); diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 2861d17b350..3740c3fae5e 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -121,9 +121,9 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op) /* if no blocks, popup error? */ if (anim_data.first == NULL) { - BKE_report(op->reports, RPT_ERROR, "No AnimData blocks to enter tweakmode for"); + BKE_report(op->reports, RPT_ERROR, "No AnimData blocks to enter tweak mode for"); return OPERATOR_CANCELLED; - } + } /* for each AnimData block with NLA-data, try setting it in tweak-mode */ for (ale = anim_data.first; ale; ale = ale->next) { @@ -147,7 +147,7 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL); } else { - BKE_report(op->reports, RPT_ERROR, "No active strip(s) to enter tweakmode on"); + BKE_report(op->reports, RPT_ERROR, "No active strip(s) to enter tweak mode on"); return OPERATOR_CANCELLED; } @@ -190,9 +190,9 @@ static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *op) /* if no blocks, popup error? */ if (anim_data.first == NULL) { - BKE_report(op->reports, RPT_ERROR, "No AnimData blocks to enter tweakmode for"); + BKE_report(op->reports, RPT_ERROR, "No AnimData blocks to enter tweak mode for"); return OPERATOR_CANCELLED; - } + } /* for each AnimData block with NLA-data, try exitting tweak-mode */ for (ale = anim_data.first; ale; ale = ale->next) { @@ -266,8 +266,8 @@ static void get_nlastrip_extents(bAnimContext *ac, float *min, float *max, const /* only consider selected strips? */ if ((onlySel == 0) || (strip->flag & NLASTRIP_FLAG_SELECT)) { /* extend range if appropriate */ - *min = minf(*min, strip->start); - *max = maxf(*max, strip->end); + *min = min_ff(*min, strip->start); + *max = max_ff(*max, strip->end); } } } @@ -304,13 +304,13 @@ static int nlaedit_viewall(bContext *C, const short onlySel) /* set the horizontal range, with an extra offset so that the extreme keys will be in view */ get_nlastrip_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax, onlySel); - extra = 0.1f * BLI_RCT_SIZE_X(&v2d->cur); + extra = 0.1f * BLI_rctf_size_x(&v2d->cur); v2d->cur.xmin -= extra; v2d->cur.xmax += extra; /* set vertical range */ v2d->cur.ymax = 0.0f; - v2d->cur.ymin = (float)-BLI_RCT_SIZE_Y(&v2d->mask); + v2d->cur.ymin = (float)-BLI_rcti_size_y(&v2d->mask); /* do View2D syncing */ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); @@ -398,14 +398,16 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op) act = BLI_findlink(&CTX_data_main(C)->action, RNA_enum_get(op->ptr, "action")); if (act == NULL) { - BKE_report(op->reports, RPT_ERROR, "No valid Action to add"); + BKE_report(op->reports, RPT_ERROR, "No valid action to add"); //printf("Add strip - actname = '%s'\n", actname); return OPERATOR_CANCELLED; } else if (act->idroot == 0) { /* hopefully in this case (i.e. library of userless actions), the user knows what they're doing... */ BKE_reportf(op->reports, RPT_WARNING, - "Action '%s' does not specify what datablocks it can be used on. Try setting the 'ID Root Type' setting from the Datablocks Editor for this Action to avoid future problems", + "Action '%s' does not specify what datablocks it can be used on " + "(try setting the 'ID Root Type' setting from the Datablocks Editor " + "for this action to avoid future problems)", act->id.name + 2); } @@ -431,7 +433,7 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op) */ if ((act->idroot) && (act->idroot != GS(ale->id->name))) { BKE_reportf(op->reports, RPT_ERROR, - "Couldn't add action '%s' as it cannot be used relative to ID-blocks of type '%s'", + "Could not add action '%s' as it cannot be used relative to ID-blocks of type '%s'", act->id.name + 2, ale->id->name); continue; } @@ -1170,7 +1172,8 @@ static int nlaedit_bake_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -static void NLA_OT_bake(wmOperatorType *ot) +/* why isn't this used? */ +static void UNUSED_FUNCTION(NLA_OT_bake)(wmOperatorType *ot) { /* identifiers */ ot->name = "Bake Strips"; @@ -1361,7 +1364,7 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op) "Cannot swap selected strips as they will not be able to fit in their new places"); } else { - BKE_reportf(op->reports, RPT_WARNING, + BKE_reportf(op->reports, RPT_WARNING, "Cannot swap '%s' and '%s' as one or both will not be able to fit in their new places", sa->name, sb->name); } @@ -2020,7 +2023,7 @@ static int nla_fmodifier_add_exec(bContext *C, wmOperator *op) set_active_fmodifier(&strip->modifiers, fcm); else { BKE_reportf(op->reports, RPT_ERROR, - "Modifier couldn't be added to (%s : %s) (see console for details)", + "Modifier could not be added to (%s : %s) (see console for details)", nlt->name, strip->name); } } diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 3a74d0b4c9c..54ade829c0d 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -256,7 +256,7 @@ static void nla_keymap_main(wmKeyConfig *keyconf, wmKeyMap *keymap) WM_keymap_add_item(keymap, "NLA_OT_meta_remove", GKEY, KM_PRESS, KM_ALT, 0); /* duplicate */ - WM_keymap_add_item(keymap, "NLA_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "NLA_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0); /* delete */ WM_keymap_add_item(keymap, "NLA_OT_delete", XKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index 222c2414fcb..97553b7aa56 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -309,7 +309,7 @@ static int nlaedit_borderselect_exec(bContext *C, wmOperator *op) * - the frame-range select option is favored over the channel one (x over y), as frame-range one is often * used for tweaking timing when "blocking", while channels is not that useful... */ - if (BLI_RCT_SIZE_X(&rect) >= BLI_RCT_SIZE_Y(&rect)) + if (BLI_rcti_size_x(&rect) >= BLI_rcti_size_y(&rect)) mode = NLA_BORDERSEL_FRAMERANGE; else mode = NLA_BORDERSEL_CHANNELS; @@ -390,7 +390,7 @@ static void nlaedit_select_leftright(bContext *C, bAnimContext *ac, short leftri if (leftright == NLAEDIT_LRSEL_LEFT) { xmin = MINAFRAMEF; xmax = (float)(CFRA + 0.1f); - } + } else { xmin = (float)(CFRA - 0.1f); xmax = MAXFRAMEF; @@ -471,7 +471,7 @@ static int nlaedit_select_leftright_invoke(bContext *C, wmOperator *op, wmEvent UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, NULL); if (x < CFRA) RNA_int_set(op->ptr, "mode", NLAEDIT_LRSEL_LEFT); - else + else RNA_int_set(op->ptr, "mode", NLAEDIT_LRSEL_RIGHT); } @@ -582,7 +582,7 @@ static void mouse_nla_strips(bContext *C, bAnimContext *ac, const int mval[2], s ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); /* Highlight NLA-Track */ - if (ale->type == ANIMTYPE_NLATRACK) { + if (ale->type == ANIMTYPE_NLATRACK) { NlaTrack *nlt = (NlaTrack *)ale->data; nlt->flag |= NLATRACK_SELECTED; diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 1f266c98020..0938562857b 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -69,9 +69,6 @@ #include "node_intern.h" /* own include */ -/* XXX interface.h */ -extern void ui_dropshadow(rctf *rct, float radius, float aspect, float alpha, int select); - /* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */ static void node_sync_cb(bContext *UNUSED(C), void *snode_v, void *node_v) @@ -200,25 +197,22 @@ static void node_draw_output_default(const bContext *C, uiBlock *block, const char *name, int UNUSED(x), int UNUSED(y), int UNUSED(width)) { SpaceNode *snode = CTX_wm_space_node(C); - float slen; - int ofs = 0; const char *ui_name = IFACE_(name); - int len = strlen(ui_name); + float slen; + UI_ThemeColor(TH_TEXT); slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect_sqrt; - while (slen > node->width && ofs < len) { - ofs++; - slen = (UI_GetStringWidth(ui_name + ofs) + NODE_MARGIN_X) * snode->aspect_sqrt; + while (slen > node->width && *ui_name) { + ui_name = BLI_str_find_next_char_utf8(ui_name, NULL); + slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect_sqrt; } - - if (ofs < len) { - uiDefBut(block, LABEL, 0, ui_name + ofs, - (int)(sock->locx - slen), (int)(sock->locy - 9.0f), - (short)(node->width - NODE_DY), (short)NODE_DY, - NULL, 0, 0, 0, 0, ""); + + if (*ui_name) { + uiDefBut(block, LABEL, 0, ui_name, + (int)(sock->locx - slen), (int)(sock->locy - 9.0f), + (short)slen, (short)NODE_DY, + NULL, 0, 0, 0, 0, ""); } - - (void)snode; } /* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */ @@ -387,7 +381,7 @@ static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA * bt = uiDefButF(block, BUT_NORMAL, B_NODE_EXEC, "", (int)butr->xmin, (int)butr->xmin, - (short)BLI_RCT_SIZE_X(butr), (short)BLI_RCT_SIZE_X(butr), + (short)BLI_rctf_size_x(butr), (short)BLI_rctf_size_x(butr), nor, 0.0f, 1.0f, 0, 0, ""); uiButSetFunc(bt, node_normal_cb, ntree, node); } @@ -523,7 +517,7 @@ static void node_update_group(const bContext *C, bNodeTree *ntree, bNode *gnode) rect->ymax += NODE_DY; /* input sockets */ - dy = BLI_RCT_CENTER_Y(rect) + (NODE_DY * (BLI_countlist(&gnode->inputs) - 1)); + dy = BLI_rctf_cent_y(rect) + (NODE_DY * (BLI_countlist(&gnode->inputs) - 1)); gsock = ngroup->inputs.first; sock = gnode->inputs.first; while (gsock || sock) { @@ -571,7 +565,7 @@ static void node_update_group(const bContext *C, bNodeTree *ntree, bNode *gnode) } /* output sockets */ - dy = BLI_RCT_CENTER_Y(rect) + (NODE_DY * (BLI_countlist(&gnode->outputs) - 1)); + dy = BLI_rctf_cent_y(rect) + (NODE_DY * (BLI_countlist(&gnode->outputs) - 1)); gsock = ngroup->outputs.first; sock = gnode->outputs.first; while (gsock || sock) { @@ -646,13 +640,13 @@ static void update_group_output_cb(bContext *UNUSED(C), void *UNUSED(snode_v), v } static void draw_group_socket_name(SpaceNode *snode, bNode *gnode, bNodeSocket *sock, - int in_out, float xoffset, float yoffset) + int in_out, float xoffset, float yoffset, short width, short height) { if (sock->flag & SOCK_DYNAMIC) { bNodeTree *ngroup = (bNodeTree *)gnode->id; uiBut *but; but = uiDefBut(gnode->block, TEX, 0, "", - sock->locx + xoffset, sock->locy + 1 + yoffset, 72, NODE_DY, + sock->locx + xoffset, sock->locy + 1 + yoffset, width, height, sock->name, 0, sizeof(sock->name), 0, 0, ""); if (in_out == SOCK_IN) uiButSetFunc(but, update_group_input_cb, snode, ngroup); @@ -662,7 +656,7 @@ static void draw_group_socket_name(SpaceNode *snode, bNode *gnode, bNodeSocket * else { const char *ui_name = IFACE_(sock->name); uiDefBut(gnode->block, LABEL, 0, ui_name, - sock->locx + xoffset, sock->locy + 1 + yoffset, 72, NODE_DY, + sock->locx + xoffset, sock->locy + 1 + yoffset, width, height, NULL, 0, 0, 0, 0, ""); } } @@ -670,23 +664,26 @@ static void draw_group_socket_name(SpaceNode *snode, bNode *gnode, bNodeSocket * static void draw_group_socket(const bContext *C, SpaceNode *snode, bNodeTree *ntree, bNode *gnode, bNodeSocket *sock, bNodeSocket *gsock, int index, int in_out) { + const float dpi_fac = U.dpi / 72.0f; bNodeTree *ngroup = (bNodeTree *)gnode->id; bNodeSocketType *stype = ntreeGetSocketType(gsock ? gsock->type : sock->type); uiBut *bt; float offset; int draw_value; - float node_group_frame = U.dpi * NODE_GROUP_FRAME / 72; - float socket_size = NODE_SOCKSIZE * U.dpi / 72; - float arrowbutw = 0.8f * UI_UNIT_X; + const float node_group_frame = NODE_GROUP_FRAME * dpi_fac; + const float socket_size = NODE_SOCKSIZE * dpi_fac; + const float arrowbutw = 0.8f * UI_UNIT_X; + const short co_text_w = 72 * dpi_fac; + const float co_margin = 6.0f * dpi_fac; /* layout stuff for buttons on group left frame */ - float colw = 0.6f * node_group_frame; - float col1 = 6 - node_group_frame; - float col2 = col1 + colw + 6; - float col3 = -arrowbutw - 6; + const float colw = 0.6f * node_group_frame; + const float col1 = co_margin - node_group_frame; + const float col2 = col1 + colw + co_margin; + const float col3 = -arrowbutw - co_margin; /* layout stuff for buttons on group right frame */ - float cor1 = 6; - float cor2 = cor1 + arrowbutw + 6; - float cor3 = cor2 + arrowbutw + 6; + const float cor1 = co_margin; + const float cor2 = cor1 + arrowbutw; + const float cor3 = cor2 + arrowbutw + co_margin; /* node and group socket circles */ if (sock) @@ -716,13 +713,13 @@ static void draw_group_socket(const bContext *C, SpaceNode *snode, bNodeTree *nt if (draw_value) { /* both name and value buttons */ if (gsock) { - draw_group_socket_name(snode, gnode, gsock, in_out, offset, 0); + draw_group_socket_name(snode, gnode, gsock, in_out, offset, 0, co_text_w, NODE_DY); if (stype->buttonfunc) stype->buttonfunc(C, gnode->block, ngroup, NULL, gsock, "", gsock->locx + offset, gsock->locy - NODE_DY, colw); } else { - draw_group_socket_name(snode, gnode, sock, in_out, offset, 0); + draw_group_socket_name(snode, gnode, sock, in_out, offset, 0, co_text_w, NODE_DY); if (stype->buttonfunc) stype->buttonfunc(C, gnode->block, ngroup, NULL, sock, "", sock->locx + offset, sock->locy - NODE_DY, colw); @@ -731,9 +728,9 @@ static void draw_group_socket(const bContext *C, SpaceNode *snode, bNodeTree *nt else { /* only name, no value button */ if (gsock) - draw_group_socket_name(snode, gnode, gsock, in_out, offset, -NODE_DYS); + draw_group_socket_name(snode, gnode, gsock, in_out, offset, -NODE_DYS, co_text_w, NODE_DY); else - draw_group_socket_name(snode, gnode, sock, in_out, offset, -NODE_DYS); + draw_group_socket_name(snode, gnode, sock, in_out, offset, -NODE_DYS, co_text_w, NODE_DY); } if (gsock && (gsock->flag & SOCK_DYNAMIC)) { @@ -837,7 +834,7 @@ static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bN layout = uiBlockLayout(gnode->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, (int)(rect.xmin + NODE_MARGIN_X), (int)(rect.ymax + (group_header - (2.5f * dpi_fac))), - mini((int)(BLI_RCT_SIZE_X(&rect) - 18.0f), node_group_frame + 20), group_header, UI_GetStyle()); + min_ii((int)(BLI_rctf_size_x(&rect) - 18.0f), node_group_frame + 20), group_header, UI_GetStyle()); RNA_pointer_create(&ntree->id, &RNA_Node, gnode, &ptr); uiTemplateIDBrowse(layout, (bContext *)C, &ptr, "node_tree", NULL, NULL, NULL); uiBlockLayoutResolve(gnode->block, NULL, NULL); @@ -898,11 +895,6 @@ static void node_uifunc_group(uiLayout *layout, bContext *C, PointerRNA *ptr) uiTemplateIDBrowse(layout, C, ptr, "node_tree", NULL, NULL, NULL); } -static void node_common_buts_whileloop(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "max_iterations", 0, NULL, ICON_NONE); -} - /* XXX Does a bounding box update by iterating over all children. * Not ideal to do this in every draw call, but doing as transform callback doesn't work, * since the child node totr rects are not updated properly at that point. @@ -979,7 +971,7 @@ static void node_draw_frame_label(bNode *node, const float aspect) ascender = BLF_ascender(fontid); /* 'x' doesn't need aspect correction */ - x = BLI_RCT_CENTER_X(rct) - (0.5f * width); + x = BLI_rctf_cent_x(rct) - (0.5f * width); y = rct->ymax - (((NODE_DY / 4) / aspect) + (ascender * aspect)); BLF_position(fontid, x, y, 0); @@ -1182,16 +1174,6 @@ static void node_common_set_butfunc(bNodeType *ntype) ntype->drawfunc = node_draw_group; ntype->drawupdatefunc = node_update_group; break; - case NODE_FORLOOP: -// ntype->uifunc= node_common_buts_group; - ntype->drawfunc = node_draw_group; - ntype->drawupdatefunc = node_update_group; - break; - case NODE_WHILELOOP: - ntype->uifunc = node_common_buts_whileloop; - ntype->drawfunc = node_draw_group; - ntype->drawupdatefunc = node_update_group; - break; case NODE_FRAME: ntype->drawfunc = node_draw_frame; ntype->drawupdatefunc = node_update_frame; @@ -1392,16 +1374,49 @@ static void node_shader_buts_tex_voronoi(uiLayout *layout, bContext *UNUSED(C), uiItemR(layout, ptr, "coloring", 0, "", ICON_NONE); } +static void node_shader_buts_tex_coord(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "from_dupli", 0, NULL, 0); +} + static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE); } +static void node_shader_buts_script(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiLayout *row; + + row = uiLayoutRow(layout, FALSE); + uiItemR(row, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + + row = uiLayoutRow(layout, TRUE); + + if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_INTERNAL) + uiItemR(row, ptr, "script", 0, "", ICON_NONE); + else + uiItemR(row, ptr, "filepath", 0, "", ICON_NONE); + + uiItemO(row, "", ICON_FILE_REFRESH, "node.shader_script_update"); +} + +static void node_shader_buts_script_details(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + uiItemS(layout); + + node_shader_buts_script(layout, C, ptr); + + /* not implemented yet + if(RNA_enum_get(ptr, "mode") == NODE_SCRIPT_EXTERNAL) + uiItemR(layout, ptr, "use_auto_update", 0, NULL, ICON_NONE);*/ +} + /* only once called */ static void node_shader_set_butfunc(bNodeType *ntype) { switch (ntype->type) { - /* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */ + /* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */ case SH_NODE_MATERIAL: case SH_NODE_MATERIAL_EXT: @@ -1473,10 +1488,17 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_TEX_VORONOI: ntype->uifunc = node_shader_buts_tex_voronoi; break; + case SH_NODE_TEX_COORD: + ntype->uifunc = node_shader_buts_tex_coord; + break; case SH_NODE_BSDF_GLOSSY: case SH_NODE_BSDF_GLASS: ntype->uifunc = node_shader_buts_glossy; break; + case SH_NODE_SCRIPT: + ntype->uifunc = node_shader_buts_script; + ntype->uifuncbut = node_shader_buts_script_details; + break; } } @@ -1497,6 +1519,21 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA * node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr); } +static void node_composit_buts_image_details(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + bNode *node = ptr->data; + PointerRNA imaptr; + + node_composit_buts_image(layout, C, ptr); + + if (!node->id) + return; + + imaptr = RNA_pointer_get(ptr, "image"); + + uiTemplateColorspaceSettings(layout, &imaptr, "colorspace_settings"); +} + static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, PointerRNA *ptr) { bNode *node = ptr->data; @@ -2019,43 +2056,45 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C { PointerRNA imfptr = RNA_pointer_get(ptr, "format"); PointerRNA active_input_ptr, op_ptr; - uiLayout *row; + uiLayout *row, *col; int active_index; int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER); node_composit_buts_file_output(layout, C, ptr); - uiTemplateImageSettings(layout, &imfptr, TRUE); + uiTemplateImageSettings(layout, &imfptr, FALSE); uiItemS(layout); uiItemO(layout, IFACE_("Add Input"), ICON_ZOOMIN, "NODE_OT_output_file_add_socket"); + row = uiLayoutRow(layout, FALSE); + col = uiLayoutColumn(row, TRUE); + active_index = RNA_int_get(ptr, "active_input_index"); /* using different collection properties if multilayer format is enabled */ if (multilayer) { - uiTemplateList(layout, C, ptr, "layer_slots", ptr, "active_input_index", NULL, 0, 0, 0); + uiTemplateList(col, C, ptr, "layer_slots", ptr, "active_input_index", NULL, 0, 0, 0); RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "layer_slots"), active_index, &active_input_ptr); } else { - uiTemplateList(layout, C, ptr, "file_slots", ptr, "active_input_index", NULL, 0, 0, 0); + uiTemplateList(col, C, ptr, "file_slots", ptr, "active_input_index", NULL, 0, 0, 0); RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "file_slots"), active_index, &active_input_ptr); } /* XXX collection lookup does not return the ID part of the pointer, setting this manually here */ active_input_ptr.id.data = ptr->id.data; - row = uiLayoutRow(layout, TRUE); - op_ptr = uiItemFullO(row, "NODE_OT_output_file_move_active_socket", "", + col = uiLayoutColumn(row, TRUE); + op_ptr = uiItemFullO(col, "NODE_OT_output_file_move_active_socket", "", ICON_TRIA_UP, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&op_ptr, "direction", 1); - op_ptr = uiItemFullO(row, "NODE_OT_output_file_move_active_socket", "", + op_ptr = uiItemFullO(col, "NODE_OT_output_file_move_active_socket", "", ICON_TRIA_DOWN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&op_ptr, "direction", 2); if (active_input_ptr.data) { if (multilayer) { - uiLayout *row, *col; col = uiLayoutColumn(layout, TRUE); uiItemL(col, IFACE_("Layer:"), ICON_NONE); @@ -2065,7 +2104,6 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C ICON_X, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY); } else { - uiLayout *row, *col; col = uiLayoutColumn(layout, TRUE); uiItemL(col, IFACE_("File Path:"), ICON_NONE); @@ -2083,7 +2121,7 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C col = uiLayoutColumn(layout, FALSE); uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format") == FALSE); - uiTemplateImageSettings(col, &imfptr, TRUE); + uiTemplateImageSettings(col, &imfptr, FALSE); } } } @@ -2224,6 +2262,21 @@ static void node_composit_buts_movieclip(uiLayout *layout, bContext *C, PointerR uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL); } +static void node_composit_buts_movieclip_details(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + bNode *node = ptr->data; + PointerRNA clipptr; + + uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL); + + if (!node->id) + return; + + clipptr = RNA_pointer_get(ptr, "clip"); + + uiTemplateColorspaceSettings(layout, &clipptr, "colorspace_settings"); +} + static void node_composit_buts_stabilize2d(uiLayout *layout, bContext *C, PointerRNA *ptr) { bNode *node = ptr->data; @@ -2559,7 +2612,7 @@ static void node_composit_buts_keyingscreen(uiLayout *layout, bContext *C, Point static void node_composit_buts_keying(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - /* bNode *node= ptr->data; */ /* UNUSED */ + /* bNode *node = ptr->data; */ /* UNUSED */ uiItemR(layout, ptr, "blur_pre", 0, NULL, ICON_NONE); uiItemR(layout, ptr, "screen_balance", 0, NULL, ICON_NONE); @@ -2609,7 +2662,7 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN uiItemR(layout, ptr, "position", 0, NULL, ICON_NONE); if (node->custom1 == 2) { - uiItemR(layout, ptr, "relative_frame", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "frame_relative", 0, NULL, ICON_NONE); } } } @@ -2618,10 +2671,11 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN static void node_composit_set_butfunc(bNodeType *ntype) { switch (ntype->type) { - /* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */ + /* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */ case CMP_NODE_IMAGE: ntype->uifunc = node_composit_buts_image; + ntype->uifuncbut = node_composit_buts_image_details; break; case CMP_NODE_R_LAYERS: ntype->uifunc = node_composit_buts_renderlayers; @@ -2776,6 +2830,7 @@ static void node_composit_set_butfunc(bNodeType *ntype) break; case CMP_NODE_MOVIECLIP: ntype->uifunc = node_composit_buts_movieclip; + ntype->uifuncbut = node_composit_buts_movieclip_details; break; case CMP_NODE_STABILIZE2D: ntype->uifunc = node_composit_buts_stabilize2d; @@ -3060,7 +3115,6 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode) void *lock; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (ibuf) { - SpaceNode *snode = CTX_wm_space_node(C); float x, y; unsigned char *display_buffer; void *cache_handle; @@ -3103,7 +3157,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode) /* swap bytes, so alpha is most significant one, then just draw it as luminance int */ glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT, - ((unsigned char *)ibuf->rect) + ofs); + display_buffer + ofs); glPixelZoom(1.0f, 1.0f); } @@ -3189,7 +3243,7 @@ static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode) float zoomx, zoomy; zoomx = (float)sa->winx / ibuf->x; zoomy = (float)sa->winy / ibuf->y; - zoom = minf(zoomx, zoomy); + zoom = min_ff(zoomx, zoomy); } x = (sa->winx - zoom * ibuf->x) / 2 + snode->xof; @@ -3520,7 +3574,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) } do_shaded = TRUE; do_triple = TRUE; - } + } else { th_col1 = TH_REDALERT; } diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c index 99d49fa1e8f..04d2947ce89 100644 --- a/source/blender/editors/space_node/node_add.c +++ b/source/blender/editors/space_node/node_add.c @@ -31,10 +31,15 @@ #include +#include "MEM_guardedalloc.h" + #include "DNA_node_types.h" +#include "BLI_listbase.h" #include "BLI_math.h" +#include "BLF_translation.h" + #include "BKE_context.h" #include "BKE_image.h" #include "BKE_library.h" @@ -131,14 +136,105 @@ static int add_reroute_intersect_check(bNodeLink *link, float mcoords[][2], int return 0; } +typedef struct bNodeSocketLink { + struct bNodeSocketLink *next, *prev; + + struct bNodeSocket *sock; + struct bNodeLink *link; + float point[2]; +} bNodeSocketLink; + +static bNodeSocketLink *add_reroute_insert_socket_link(ListBase *lb, bNodeSocket *sock, bNodeLink *link, float point[2]) +{ + bNodeSocketLink *socklink, *prev; + + socklink = MEM_callocN(sizeof(bNodeSocketLink), "socket link"); + socklink->sock = sock; + socklink->link = link; + copy_v2_v2(socklink->point, point); + + for (prev = lb->last; prev; prev = prev->prev) { + if (prev->sock == sock) + break; + } + BLI_insertlinkafter(lb, prev, socklink); + return socklink; +} + +static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, bNodeSocketLink *socklink, int in_out) +{ + SpaceNode *snode = CTX_wm_space_node(C); + bNodeTree *ntree = snode->edittree; + bNode *reroute_node = NULL; + bNodeSocket *cursock = socklink->sock; + float insert_point[2]; + int num_links; + + zero_v2(insert_point); + num_links = 0; + + while (socklink && socklink->sock == cursock) { + if (!(socklink->link->flag & NODE_LINK_TEST)) { + socklink->link->flag |= NODE_LINK_TEST; + + /* create the reroute node for this cursock */ + if (!reroute_node) { + bNodeTemplate ntemp; + ntemp.type = NODE_REROUTE; + reroute_node = nodeAddNode(ntree, &ntemp); + + /* add a single link to/from the reroute node to replace multiple links */ + if (in_out == SOCK_OUT) { + nodeAddLink(ntree, socklink->link->fromnode, socklink->link->fromsock, reroute_node, reroute_node->inputs.first); + } + else { + nodeAddLink(ntree, reroute_node, reroute_node->outputs.first, socklink->link->tonode, socklink->link->tosock); + } + } + + /* insert the reroute node into the link */ + if (in_out == SOCK_OUT) { + socklink->link->fromnode = reroute_node; + socklink->link->fromsock = reroute_node->outputs.first; + } + else { + socklink->link->tonode = reroute_node; + socklink->link->tosock = reroute_node->inputs.first; + } + + add_v2_v2(insert_point, socklink->point); + ++num_links; + } + socklink = socklink->next; + } + + if (num_links > 0) { + bNode *gnode = node_tree_get_editgroup(snode->nodetree); + + /* average cut point from shared links */ + mul_v2_fl(insert_point, 1.0f / num_links); + + if (gnode) { + nodeFromView(gnode, insert_point[0], insert_point[1], &reroute_node->locx, &reroute_node->locy); + } + else { + reroute_node->locx = insert_point[0]; + reroute_node->locy = insert_point[1]; + } + } + + return socklink; +} + static int add_reroute_exec(bContext *C, wmOperator *op) { SpaceNode *snode = CTX_wm_space_node(C); ARegion *ar = CTX_wm_region(C); - bNode *gnode = node_tree_get_editgroup(snode->nodetree); + bNodeTree *ntree = snode->edittree; float mcoords[256][2]; int i = 0; - + + /* Get the cut path */ RNA_BEGIN(op->ptr, itemptr, "path") { float loc[2]; @@ -152,46 +248,52 @@ static int add_reroute_exec(bContext *C, wmOperator *op) RNA_END; if (i > 1) { + ListBase output_links, input_links; bNodeLink *link; - float insertPoint[2]; - - for (link = snode->edittree->links.first; link; link = link->next) { - if (add_reroute_intersect_check(link, mcoords, i, insertPoint)) { - bNodeTemplate ntemp; - bNode *rerouteNode; - - /* always first */ - ED_preview_kill_jobs(C); - - node_deselect_all(snode); - - ntemp.type = NODE_REROUTE; - rerouteNode = nodeAddNode(snode->edittree, &ntemp); - if (gnode) { - nodeFromView(gnode, insertPoint[0], insertPoint[1], &rerouteNode->locx, &rerouteNode->locy); - } - else { - rerouteNode->locx = insertPoint[0]; - rerouteNode->locy = insertPoint[1]; - } - - nodeAddLink(snode->edittree, link->fromnode, link->fromsock, rerouteNode, rerouteNode->inputs.first); - link->fromnode = rerouteNode; - link->fromsock = rerouteNode->outputs.first; - - /* always last */ - ntreeUpdateTree(snode->edittree); - snode_notify(C, snode); - snode_dag_update(C, snode); - - return OPERATOR_FINISHED; // add one reroute at the time. + bNodeSocketLink *socklink; + float insert_point[2]; + + /* always first */ + ED_preview_kill_jobs(C); + + node_deselect_all(snode); + + /* Find cut links and sort them by sockets */ + output_links.first = output_links.last = NULL; + input_links.first = input_links.last = NULL; + for (link = ntree->links.first; link; link = link->next) { + if (add_reroute_intersect_check(link, mcoords, i, insert_point)) { + add_reroute_insert_socket_link(&output_links, link->fromsock, link, insert_point); + add_reroute_insert_socket_link(&input_links, link->tosock, link, insert_point); + + /* Clear flag */ + link->flag &= ~NODE_LINK_TEST; } } - - return OPERATOR_CANCELLED; - + + /* Create reroute nodes for intersected links. + * Only one reroute if links share the same input/output socket. + */ + socklink = output_links.first; + while (socklink) { + socklink = add_reroute_do_socket_section(C, socklink, SOCK_OUT); + } + socklink = input_links.first; + while (socklink) { + socklink = add_reroute_do_socket_section(C, socklink, SOCK_IN); + } + + BLI_freelistN(&output_links); + BLI_freelistN(&input_links); + + /* always last */ + ntreeUpdateTree(ntree); + snode_notify(C, snode); + snode_dag_update(C, snode); + + return OPERATOR_FINISHED; } - + return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; } @@ -240,7 +342,8 @@ static int node_add_file_exec(bContext *C, wmOperator *op) ima = BKE_image_load_exists(path); if (!ima) { - BKE_reportf(op->reports, RPT_ERROR, "Can't read image: \"%s\", %s", path, errno ? strerror(errno) : "Unsupported format"); + BKE_reportf(op->reports, RPT_ERROR, "Cannot read image '%s': %s", + path, errno ? strerror(errno) : TIP_("unsupported format")); return OPERATOR_CANCELLED; } } @@ -250,7 +353,7 @@ static int node_add_file_exec(bContext *C, wmOperator *op) ima = (Image *)BKE_libblock_find_name(ID_IM, name); if (!ima) { - BKE_reportf(op->reports, RPT_ERROR, "Image named \"%s\", not found", name); + BKE_reportf(op->reports, RPT_ERROR, "Image '%s' not found", name); return OPERATOR_CANCELLED; } } diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 7d35f566140..1d3b21fe2d6 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -62,10 +62,8 @@ #include "node_intern.h" /* own include */ #include "COM_compositor.h" -/* width of socket columns in group display */ -#define NODE_GROUP_FRAME 120 /* XXX interface.h */ -extern void ui_dropshadow(rctf *rct, float radius, float aspect, float alpha, int select); +extern void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select); /* XXX update functions for node editor are a mess, needs a clear concept */ void ED_node_tree_update(SpaceNode *snode, Scene *scene) @@ -103,7 +101,7 @@ void ED_node_changed_update(ID *id, bNode *node) nodeUpdateID(nodetree, node->id); WM_main_add_notifier(NC_SCENE | ND_NODES, id); - } + } else if (treetype == NTREE_TEXTURE) { DAG_id_tag_update(id, 0); WM_main_add_notifier(NC_TEXTURE | ND_NODES, id); @@ -343,7 +341,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) if (node->prvr.ymax < node->prvr.ymin) SWAP(float, node->prvr.ymax, node->prvr.ymin); } else { - float oldh = BLI_RCT_SIZE_Y(&node->prvr); + float oldh = BLI_rctf_size_y(&node->prvr); if (oldh == 0.0f) oldh = 0.6f * node->width - NODE_DY; dy -= NODE_DYS / 2; @@ -393,7 +391,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) node->totr.xmin = locx; node->totr.xmax = locx + node->width; node->totr.ymax = locy; - node->totr.ymin = minf(dy, locy - 2 * NODE_DY); + node->totr.ymin = min_ff(dy, locy - 2 * NODE_DY); /* Set the block bounds to clip mouse events from underlying nodes. * Add a margin for sockets on each side. @@ -508,25 +506,16 @@ int node_get_colorid(bNode *node) /* note: in node_edit.c is similar code, for untangle node */ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node) { - ListBase links; bNodeLink *link; - if (node->typeinfo->internal_connect == NULL) - return; - - /* Get default muting links. */ - links = node->typeinfo->internal_connect(snode->edittree, node); - glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); - for (link = links.first; link; link = link->next) + for (link = node->internal_links.first; link; link = link->next) node_draw_link_bezier(v2d, snode, link, TH_REDALERT, 0, TH_WIRE, 0, TH_WIRE); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); - - BLI_freelistN(&links); } /* this might have some more generic use */ @@ -584,9 +573,9 @@ void node_socket_circle_draw(bNodeTree *UNUSED(ntree), bNodeSocket *sock, float /* not a callback */ static void node_draw_preview(bNodePreview *preview, rctf *prv) { - float xscale = BLI_RCT_SIZE_X(prv) / ((float)preview->xsize); - float yscale = BLI_RCT_SIZE_Y(prv) / ((float)preview->ysize); - float tile = BLI_RCT_SIZE_X(prv) / 10.0f; + float xscale = BLI_rctf_size_x(prv) / ((float)preview->xsize); + float yscale = BLI_rctf_size_y(prv) / ((float)preview->ysize); + float tile = BLI_rctf_size_x(prv) / 10.0f; float x, y; /* draw checkerboard backdrop to show alpha */ @@ -670,7 +659,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN bNodeSocket *sock; rctf *rct = &node->totr; float iconofs; - /* float socket_size= NODE_SOCKSIZE*U.dpi/72; */ /* UNUSED */ + /* float socket_size = NODE_SOCKSIZE*U.dpi/72; */ /* UNUSED */ float iconbutw = 0.8f * UI_UNIT_X; int color_id = node_get_colorid(node); char showname[128]; /* 128 used below */ @@ -852,8 +841,8 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b { bNodeSocket *sock; rctf *rct = &node->totr; - float dx, centy = BLI_RCT_CENTER_Y(rct); - float hiddenrad = BLI_RCT_SIZE_Y(rct) / 2.0f; + float dx, centy = BLI_rctf_cent_y(rct); + float hiddenrad = BLI_rctf_size_y(rct) / 2.0f; float socket_size = NODE_SOCKSIZE * U.dpi / 72; int color_id = node_get_colorid(node); char showname[128]; /* 128 is used below */ @@ -917,7 +906,7 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b /* disable lines */ if (node->flag & NODE_MUTED) - node_draw_mute_line(&ar->v2d, snode, node); + node_draw_mute_line(&ar->v2d, snode, node); if (node->flag & SELECT) UI_ThemeColor(TH_SELECT); @@ -932,9 +921,9 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b uiDefBut(node->block, LABEL, 0, showname, (int)(rct->xmin + (NODE_MARGIN_X / snode->aspect_sqrt)), (int)(centy - 10), - (short)(BLI_RCT_SIZE_X(rct) - 18.0f - 12.0f), (short)NODE_DY, + (short)(BLI_rctf_size_x(rct) - 18.0f - 12.0f), (short)NODE_DY, NULL, 0, 0, 0, 0, ""); - } + } /* scale widget thing */ UI_ThemeColorShade(color_id, -10); @@ -1108,9 +1097,9 @@ void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d) glEnable(GL_MAP1_VERTEX_3); /* aspect+font, set each time */ - snode->aspect = BLI_RCT_SIZE_X(&v2d->cur) / (float)ar->winx; + snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)ar->winx; snode->aspect_sqrt = sqrtf(snode->aspect); - // XXX snode->curfont= uiSetCurFont_ext(snode->aspect); + // XXX snode->curfont = uiSetCurFont_ext(snode->aspect); /* grid */ UI_view2d_multi_grid_draw(v2d, 25.0f, 5, 2); @@ -1140,7 +1129,7 @@ void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d) #ifdef WITH_COMPOSITOR if (snode->nodetree->type == NTREE_COMPOSIT) { COM_startReadHighlights(); - } + } #endif node_draw_nodetree(C, ar, snode, snode->nodetree); diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index cc386da2e93..6bf0e9f73e3 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -35,6 +35,7 @@ #include "DNA_material_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" +#include "DNA_text_types.h" #include "DNA_world_types.h" #include "BLI_math.h" @@ -54,6 +55,7 @@ #include "BKE_scene.h" #include "BKE_texture.h" +#include "RE_engine.h" #include "RE_pipeline.h" @@ -1622,7 +1624,7 @@ static int node_mute_exec(bContext *C, wmOperator *UNUSED(op)) for (node = snode->edittree->nodes.first; node; node = node->next) { /* Only allow muting of nodes having a mute func! */ - if ((node->flag & SELECT) && node->typeinfo->internal_connect) { + if ((node->flag & SELECT) && node->typeinfo->update_internal_links) { node->flag ^= NODE_MUTED; snode_update(snode, node); } @@ -1935,7 +1937,7 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op)) bNodeTree *ntree = snode->edittree; bNode *gnode = node_tree_get_editgroup(snode->nodetree); float gnode_x = 0.0f, gnode_y = 0.0f; - bNode *node, *new_node; + bNode *node; bNodeLink *link, *newlink; ED_preview_kill_jobs(C); @@ -1950,6 +1952,7 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op)) for (node = ntree->nodes.first; node; node = node->next) { if (node->flag & SELECT) { + bNode *new_node; new_node = nodeCopyNode(NULL, node); BKE_node_clipboard_add_node(new_node); } @@ -1971,7 +1974,7 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op)) } /* transform to basic view space. child node location is relative to parent */ - if (!new_node->parent) { + if (!new_node->parent) { new_node->locx += gnode_x; new_node->locy += gnode_y; } @@ -2067,8 +2070,8 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) /* calculate "barycenter" for placing on mouse cursor */ zero_v2(center); for (node = clipboard_nodes_lb->first, num_nodes = 0; node; node = node->next, num_nodes++) { - center[0] += BLI_RCT_CENTER_X(&node->totr); - center[1] += BLI_RCT_CENTER_Y(&node->totr); + center[0] += BLI_rctf_cent_x(&node->totr); + center[1] += BLI_rctf_cent_y(&node->totr); } mul_v2_fl(center, 1.0 / num_nodes); @@ -2136,3 +2139,120 @@ void NODE_OT_clipboard_paste(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } + +/* ********************** Shader Script Update ******************/ + +typedef struct ScriptUpdateData { + RenderEngine *engine; + RenderEngineType *type; + + Text *text; + int found; +} ScriptUpdateData; + +static int node_shader_script_update_poll(bContext *C) +{ + Scene *scene = CTX_data_scene(C); + RenderEngineType *type = RE_engines_find(scene->r.engine); + bNode *node; + Text *text; + + /* test if we have a render engine that supports shaders scripts */ + if (!(type && type->update_script_node)) + return 0; + + /* see if we have a shader script node in context */ + node = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript).data; + if (node && node->type == SH_NODE_SCRIPT) { + NodeShaderScript *nss = node->storage; + + if (node->id || nss->filepath[0]) { + return 1; + } + } + + /* see if we have a text datablock in context */ + text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data; + if (text) + return 1; + + /* we don't check if text datablock is actually in use, too slow for poll */ + + return 0; +} + +static void node_shader_script_update_text(void *data_, ID *UNUSED(id), bNodeTree *ntree) +{ + ScriptUpdateData *data = (ScriptUpdateData *)data_; + bNode *node; + + /* update each script that is using this text datablock */ + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == NODE_GROUP) { + node_shader_script_update_text(data_, NULL, (bNodeTree *)node->id); + } + else if (node->type == SH_NODE_SCRIPT && node->id == &data->text->id) { + data->type->update_script_node(data->engine, ntree, node); + data->found = TRUE; + } + } +} + +static int node_shader_script_update_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ScriptUpdateData data; + PointerRNA nodeptr = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript); + + /* setup render engine */ + data.type = RE_engines_find(scene->r.engine); + data.engine = RE_engine_create(data.type); + data.engine->reports = op->reports; + data.text = NULL; + data.found = FALSE; + + if (nodeptr.data) { + /* update single node */ + bNodeTree *ntree = nodeptr.id.data; + bNode *node = nodeptr.data; + + data.type->update_script_node(data.engine, ntree, node); + + data.found = TRUE; + } + else { + /* update all nodes using text datablock */ + data.text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data; + + if (data.text) { + bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER); + + if (ntreetype && ntreetype->foreach_nodetree) + ntreetype->foreach_nodetree(bmain, &data, node_shader_script_update_text); + + if (!data.found) + BKE_report(op->reports, RPT_INFO, "Text not used by any node, no update done."); + } + } + + RE_engine_free(data.engine); + + return (data.found)? OPERATOR_FINISHED: OPERATOR_CANCELLED; +} + +void NODE_OT_shader_script_update(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Script Node Update"; + ot->description = "Update shader script node with new sockets and options from the script"; + ot->idname = "NODE_OT_shader_script_update"; + + /* api callbacks */ + ot->exec = node_shader_script_update_exec; + ot->poll = node_shader_script_update_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index b76cc05af5c..5f8b5db7766 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -583,7 +583,7 @@ static int node_group_ungroup_exec(bContext *C, wmOperator *op) ntreeUpdateTree(snode->nodetree); } else { - BKE_report(op->reports, RPT_WARNING, "Can't ungroup"); + BKE_report(op->reports, RPT_WARNING, "Cannot ungroup"); return OPERATOR_CANCELLED; } @@ -755,13 +755,13 @@ static int node_group_separate_exec(bContext *C, wmOperator *op) switch (type) { case NODE_GS_COPY: if (!node_group_separate_selected(snode->nodetree, gnode, 1)) { - BKE_report(op->reports, RPT_WARNING, "Can't separate nodes"); + BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes"); return OPERATOR_CANCELLED; } break; case NODE_GS_MOVE: if (!node_group_separate_selected(snode->nodetree, gnode, 0)) { - BKE_report(op->reports, RPT_WARNING, "Can't separate nodes"); + BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes"); return OPERATOR_CANCELLED; } break; @@ -875,7 +875,7 @@ static int node_group_make_insert_selected(bNodeTree *ntree, bNode *gnode) bNodeTree *ngroup = (bNodeTree *)gnode->id; bNodeLink *link, *linkn; bNode *node, *nextn; - bNodeSocket *gsock; + bNodeSocket *gsock, *sock; ListBase anim_basepaths = {NULL, NULL}; float min[2], max[2]; @@ -982,8 +982,42 @@ static int node_group_make_insert_selected(bNodeTree *ntree, bNode *gnode) } } + /* auto-add interface for "solo" nodes */ + node = ((bNodeTree *)gnode->id)->nodes.first; + if (node && !node->next) { + for (sock = node->inputs.first; sock; sock = sock->next) { + int skip = FALSE; + + for (link = ((bNodeTree *)gnode->id)->links.first; link; link = link->next) + if (link->tosock == sock) + skip = TRUE; + + if (skip == TRUE) + continue; + + gsock = node_group_expose_socket(ngroup, sock, SOCK_IN); + node_group_add_extern_socket(ntree, &gnode->inputs, SOCK_IN, gsock); + nodeAddLink(ngroup, NULL, gsock, node, sock); + } + + for (sock = node->outputs.first; sock; sock = sock->next) { + int skip = FALSE; + + for (link = ((bNodeTree *)gnode->id)->links.first; link; link = link->next) + if (link->fromsock == sock) + skip = TRUE; + + if (skip == TRUE) + continue; + + gsock = node_group_expose_socket(ngroup, sock, SOCK_OUT); + node_group_add_extern_socket(ntree, &gnode->outputs, SOCK_OUT, gsock); + nodeAddLink(ngroup, NULL, gsock, node, sock); + } + } + /* update of the group tree */ - ngroup->update |= NTREE_UPDATE; + ngroup->update |= NTREE_UPDATE | NTREE_UPDATE_LINKS; /* update of the tree containing the group instance node */ ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS; @@ -1036,7 +1070,7 @@ static int node_group_make_exec(bContext *C, wmOperator *op) int type = RNA_enum_get(op->ptr, "type"); if (snode->edittree != snode->nodetree) { - BKE_report(op->reports, RPT_WARNING, "Can not add a new Group in a Group"); + BKE_report(op->reports, RPT_WARNING, "Cannot add a new group in a group"); return OPERATOR_CANCELLED; } @@ -1049,7 +1083,7 @@ static int node_group_make_exec(bContext *C, wmOperator *op) } if (gnode) { - BKE_report(op->reports, RPT_WARNING, "Can not add RenderLayer in a Group"); + BKE_report(op->reports, RPT_WARNING, "Cannot add a Render Layers node in a group"); return OPERATOR_CANCELLED; } } @@ -1062,21 +1096,21 @@ static int node_group_make_exec(bContext *C, wmOperator *op) gnode = node_group_make_from_selected(snode->nodetree); } else { - BKE_report(op->reports, RPT_WARNING, "Can not make Group"); + BKE_report(op->reports, RPT_WARNING, "Cannot make group"); return OPERATOR_CANCELLED; } break; case NODE_GM_INSERT: gnode = nodeGetActive(snode->nodetree); if (!gnode || gnode->type != NODE_GROUP) { - BKE_report(op->reports, RPT_WARNING, "No active Group node"); + BKE_report(op->reports, RPT_WARNING, "No active group node"); return OPERATOR_CANCELLED; } if (node_group_make_test(snode->nodetree, gnode)) { node_group_make_insert_selected(snode->nodetree, gnode); } else { - BKE_report(op->reports, RPT_WARNING, "Can not insert into Group"); + BKE_report(op->reports, RPT_WARNING, "Cannot insert into group"); return OPERATOR_CANCELLED; } break; diff --git a/source/blender/editors/space_node/node_header.c b/source/blender/editors/space_node/node_header.c index 5ab698cd415..e82917feb21 100644 --- a/source/blender/editors/space_node/node_header.c +++ b/source/blender/editors/space_node/node_header.c @@ -138,12 +138,6 @@ static void do_node_add_group(bContext *C, void *UNUSED(arg), int event) case NODE_GROUP: ntemp.ngroup = ntreeAddTree("Group", snode->treetype, ntemp.type); break; - case NODE_FORLOOP: - ntemp.ngroup = ntreeAddTree("For Loop", snode->treetype, ntemp.type); - break; - case NODE_WHILELOOP: - ntemp.ngroup = ntreeAddTree("While Loop", snode->treetype, ntemp.type); - break; default: ntemp.ngroup = NULL; } @@ -199,15 +193,11 @@ static void node_add_menu(bContext *C, uiLayout *layout, void *arg_nodeclass) /* XXX hack: negative numbers used for empty group types */ if (node_tree_has_type(ntree->type, NODE_GROUP)) uiItemV(layout, IFACE_("New Group"), 0, -NODE_GROUP); - if (node_tree_has_type(ntree->type, NODE_FORLOOP)) - uiItemV(layout, IFACE_("New For Loop"), 0, -NODE_FORLOOP); - if (node_tree_has_type(ntree->type, NODE_WHILELOOP)) - uiItemV(layout, IFACE_("New While Loop"), 0, -NODE_WHILELOOP); uiItemS(layout); for (ngroup = bmain->nodetree.first, event = 0; ngroup; ngroup = ngroup->id.next, ++event) { /* only use group trees */ - if (ngroup->type == ntree->type && ELEM3(ngroup->nodetype, NODE_GROUP, NODE_FORLOOP, NODE_WHILELOOP)) { + if (ngroup->type == ntree->type && ngroup->nodetype == NODE_GROUP) { uiItemV(layout, ngroup->id.name + 2, 0, event); } } diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 36ebddc8d22..45509e02226 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -206,6 +206,8 @@ void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot); void NODE_OT_clipboard_copy(struct wmOperatorType *ot); void NODE_OT_clipboard_paste(struct wmOperatorType *ot); +void NODE_OT_shader_script_update(struct wmOperatorType *ot); + extern const char *node_context_dir[]; // XXXXXX diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index a5032fb6465..64e5f67a348 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -117,6 +117,8 @@ void node_operatortypes(void) WM_operatortype_append(NODE_OT_clipboard_copy); WM_operatortype_append(NODE_OT_clipboard_paste); + + WM_operatortype_append(NODE_OT_shader_script_update); } void ED_operatormacros_node(void) @@ -167,7 +169,7 @@ void ED_operatormacros_node(void) ot = WM_operatortype_append_macro("NODE_OT_move_detach_links_release", "Detach", "Move a node to detach links", OPTYPE_UNDO | OPTYPE_REGISTER); WM_operatortype_macro_define(ot, "NODE_OT_links_detach"); - mot = WM_operatortype_macro_define(ot, "NODE_OT_translate_attach"); + WM_operatortype_macro_define(ot, "NODE_OT_translate_attach"); } /* helper function for repetitive select operator keymap */ diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index fec7366ee73..7fa48c48ad6 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -136,7 +136,7 @@ static bNodeSocket *best_socket_input(bNodeTree *ntree, bNode *node, int num, in int a = 0; for (sock = node->inputs.first; sock; sock = sock->next) { - maxtype = MAX2(sock->type, maxtype); + maxtype = max_ii(sock->type, maxtype); } /* find sockets of higher 'types' first (i.e. image) */ @@ -1368,7 +1368,7 @@ static bNodeSocket *socket_best_match(ListBase *sockets) /* find type range */ for (sock = sockets->first; sock; sock = sock->next) - maxtype = MAX2(sock->type, maxtype); + maxtype = max_ii(sock->type, maxtype); /* try all types, starting from 'highest' (i.e. colors, vectors, values) */ for (type = maxtype; type >= 0; --type) { diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index a56d76a3ef7..a3efa15c54a 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -539,7 +539,7 @@ void NODE_OT_select_border(wmOperatorType *ot) /* ****** Lasso Select ****** */ -static int do_lasso_select_node(bContext *C, int mcords[][2], short moves, short select) +static int do_lasso_select_node(bContext *C, const int mcords[][2], short moves, short select) { SpaceNode *snode = CTX_wm_space_node(C); bNode *node; @@ -555,8 +555,8 @@ static int do_lasso_select_node(bContext *C, int mcords[][2], short moves, short /* do actual selection */ for (node = snode->edittree->nodes.first; node; node = node->next) { int screen_co[2]; - const float cent[2] = {BLI_RCT_CENTER_X(&node->totr), - BLI_RCT_CENTER_Y(&node->totr)}; + const float cent[2] = {BLI_rctf_cent_x(&node->totr), + BLI_rctf_cent_y(&node->totr)}; /* marker in screen coords */ UI_view2d_view_to_region(&ar->v2d, @@ -585,7 +585,7 @@ static int do_lasso_select_node(bContext *C, int mcords[][2], short moves, short static int node_lasso_select_exec(bContext *C, wmOperator *op) { int mcords_tot; - int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); if (mcords) { short select; @@ -593,7 +593,7 @@ static int node_lasso_select_exec(bContext *C, wmOperator *op) select = !RNA_boolean_get(op->ptr, "deselect"); do_lasso_select_node(C, mcords, mcords_tot, select); - MEM_freeN(mcords); + MEM_freeN((void *)mcords); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c index 7881014ed54..23f4e948794 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.c @@ -122,6 +122,7 @@ static void node_socket_disconnect(Main *bmain, bNodeTree *ntree, bNode *node_to return; nodeRemLink(ntree, sock_to->link); + sock_to->flag |= SOCK_COLLAPSED; nodeUpdate(ntree, node_to); ntreeUpdateTree(ntree); @@ -136,6 +137,7 @@ static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bN return; node_remove_linked(ntree, sock_to->link->fromnode); + sock_to->flag |= SOCK_COLLAPSED; nodeUpdate(ntree, node_to); ntreeUpdateTree(ntree); @@ -147,7 +149,7 @@ static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bN static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, bNodeTemplate *ntemp, int sock_num) { bNode *node_from; - bNodeSocket *sock_from; + bNodeSocket *sock_from_tmp; bNode *node_prev = NULL; /* unlink existing node */ @@ -183,8 +185,9 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t nodeSetActive(ntree, node_from); /* add link */ - sock_from = BLI_findlink(&node_from->outputs, sock_num); - nodeAddLink(ntree, node_from, sock_from, node_to, sock_to); + sock_from_tmp = BLI_findlink(&node_from->outputs, sock_num); + nodeAddLink(ntree, node_from, sock_from_tmp, node_to, sock_to); + sock_to->flag &= ~SOCK_COLLAPSED; /* copy input sockets from previous node */ if (node_prev && node_from != node_prev) { @@ -230,7 +233,7 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t /****************************** Node Link Menu *******************************/ -#define UI_NODE_LINK_ADD 0 +// #define UI_NODE_LINK_ADD 0 #define UI_NODE_LINK_DISCONNECT -1 #define UI_NODE_LINK_REMOVE -2 @@ -289,8 +292,7 @@ static void ui_node_sock_name(bNodeSocket *sock, char name[UI_MAX_NAME_STR]) BLI_strncpy(node_name, node->typeinfo->name, UI_MAX_NAME_STR); if (node->inputs.first == NULL && - node->outputs.first != node->outputs.last && - !(node->typeinfo->flag & NODE_OPTIONS)) + node->outputs.first != node->outputs.last) { BLI_snprintf(name, UI_MAX_NAME_STR, "%s | %s", IFACE_(node_name), IFACE_(sock->link->fromsock->name)); } @@ -613,7 +615,7 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, /* input linked to a node */ uiTemplateNodeLink(split, ntree, node, input); - if (!(input->flag & SOCK_COLLAPSED)) { + if (depth == 0 || !(input->flag & SOCK_COLLAPSED)) { if (depth == 0) uiItemS(layout); diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index 8e38247348f..ccf5c4b540f 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -72,8 +72,8 @@ static int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar, cons int tot = 0; int has_frame = FALSE; - oldwidth = BLI_RCT_SIZE_X(&ar->v2d.cur); - oldheight = BLI_RCT_SIZE_Y(&ar->v2d.cur); + oldwidth = BLI_rctf_size_x(&ar->v2d.cur); + oldheight = BLI_rctf_size_y(&ar->v2d.cur); BLI_rctf_init_minmax(&cur_new); @@ -91,8 +91,8 @@ static int space_node_view_flag(bContext *C, SpaceNode *snode, ARegion *ar, cons } if (tot) { - width = BLI_RCT_SIZE_X(&cur_new); - height = BLI_RCT_SIZE_Y(&cur_new); + width = BLI_rctf_size_x(&cur_new); + height = BLI_rctf_size_y(&cur_new); /* for single non-frame nodes, don't zoom in, just pan view, * but do allow zooming out, this allows for big nodes to be zoomed out */ @@ -358,6 +358,13 @@ int ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float float fx, fy, bufx, bufy; int ret = FALSE; + if (snode->treetype != NTREE_COMPOSIT || (snode->flag & SNODE_BACKDRAW) == 0) { + /* use viewer image for color sampling only if we're in compositor tree + * with backdrop enabled + */ + return FALSE; + } + ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (!ibuf) { diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 0601d7c105f..4d2512cdc93 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -111,7 +111,6 @@ static SpaceLink *node_new(const bContext *UNUSED(C)) BLI_addtail(&snode->regionbase, ar); ar->regiontype = RGN_TYPE_UI; ar->alignment = RGN_ALIGN_RIGHT; - ar->flag = RGN_FLAG_HIDDEN; /* main area */ ar = MEM_callocN(sizeof(ARegion), "main area for node"); @@ -254,6 +253,15 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn) } } break; + + case NC_MOVIECLIP: + if (wmn->action == NA_EDITED) { + if (type == NTREE_COMPOSIT) { + if (nodeUpdateID(snode->nodetree, wmn->reference)) + ED_area_tag_refresh(sa); + } + } + break; } } @@ -440,9 +448,6 @@ static void node_region_listener(ARegion *ar, wmNotifier *wmn) break; case NC_SCREEN: switch (wmn->data) { - case ND_GPENCIL: - ED_region_tag_redraw(ar); - break; case ND_SCREENCAST: case ND_ANIMPLAY: ED_region_tag_redraw(ar); @@ -463,6 +468,10 @@ static void node_region_listener(ARegion *ar, wmNotifier *wmn) if (wmn->action == NA_RENAME) ED_region_tag_redraw(ar); break; + case NC_GPENCIL: + if (wmn->action == NA_EDITED) + ED_region_tag_redraw(ar); + break; } } diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 21e06f00d8e..c4afe32e85f 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -36,6 +36,7 @@ #include "DNA_scene_types.h" #include "DNA_sequence_types.h" +#include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "BLI_ghash.h" @@ -92,7 +93,7 @@ static void outliner_width(SpaceOops *soops, ListBase *lb, int *w) { TreeElement *te = lb->first; while (te) { -// TreeStoreElem *tselem= TREESTORE(te); +// TreeStoreElem *tselem = TREESTORE(te); // XXX fixme... te->xend is not set yet if (!TSELEM_OPEN(tselem, soops)) { @@ -238,9 +239,9 @@ static int group_select_flag(Group *gr) void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag) { - Scene *scene = (Scene *)poin; + Scene *scene = (Scene *)poin; GroupObject *gob; - Group *gr = (Group *)poin2; + Group *gr = (Group *)poin2; if (group_restrict_flag(gr, flag)) { for (gob = gr->gobject.first; gob; gob = gob->next) { @@ -256,10 +257,12 @@ void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag) /* not in editmode */ if (scene->obedit != gob->ob) { gob->ob->restrictflag |= flag; - - if (flag == OB_RESTRICT_VIEW) - if ((gob->ob->flag & SELECT) == 0) - ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_SELECT); + + if (ELEM(flag, OB_RESTRICT_SELECT, OB_RESTRICT_VIEW)) { + if ((gob->ob->flag & SELECT)) { + ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_DESELECT); + } + } } } } @@ -307,7 +310,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname) WM_event_add_notifier(C, NC_SCENE, NULL); break; default: WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL); break; - } + } /* Check the library target exists */ if (te->idcode == ID_LI) { Library *lib = (Library *)tselem->id; @@ -625,7 +628,7 @@ static uiBlock *operator_search_menu(bContext *C, ARegion *ar, void *arg_kmi) search[0] = 0; block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS); - uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_RET_1); + uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_SEARCH_MENU); /* fake button, it holds space for search items */ uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); @@ -634,7 +637,7 @@ static uiBlock *operator_search_menu(bContext *C, ARegion *ar, void *arg_kmi) uiButSetSearchFunc(but, operator_search_cb, arg_kmi, operator_call_cb, ot); uiBoundsBlock(block, 6); - uiBlockSetDirection(block, UI_DOWN); + uiBlockSetDirection(block, UI_DOWN); uiEndBlock(C, block); event = *(win->eventstate); /* XXX huh huh? make api call */ @@ -781,7 +784,9 @@ static void outliner_draw_keymapbuts(uiBlock *block, ARegion *ar, SpaceOops *soo wmKeyMapItem *kmi = te->directdata; /* modal map? */ - if (kmi->propvalue) ; + if (kmi->propvalue) { + /* pass */ + } else { uiDefBlockBut(block, operator_search_menu, kmi, "", xstart, (int)te->ys + 1, butw1, UI_UNIT_Y - 1, "Assign new Operator"); } @@ -996,6 +1001,7 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto case eModifierType_Bevel: UI_icon_draw(x, y, ICON_MOD_BEVEL); break; case eModifierType_Smooth: + case eModifierType_LaplacianSmooth: UI_icon_draw(x, y, ICON_MOD_SMOOTH); break; case eModifierType_SimpleDeform: UI_icon_draw(x, y, ICON_MOD_SIMPLEDEFORM); break; @@ -1247,7 +1253,7 @@ static void outliner_set_coord_tree_element(SpaceOops *soops, TreeElement *te, i for (ten = te->subtree.first; ten; ten = ten->next) { outliner_set_coord_tree_element(soops, ten, startx + UI_UNIT_X, starty); - } + } } @@ -1392,7 +1398,7 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT); glPixelTransferf(GL_ALPHA_SCALE, 1.0f); offsx += UI_UNIT_X; - } + } glDisable(GL_BLEND); /* name */ @@ -1407,11 +1413,15 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene /* closed item, we draw the icons, not when it's a scene, or master-server list though */ if (!TSELEM_OPEN(tselem, soops)) { if (te->subtree.first) { - if (tselem->type == 0 && te->idcode == ID_SCE) ; - else if (tselem->type != TSE_R_LAYER) { /* this tree element always has same amount of branches, so don't draw */ + if (tselem->type == 0 && te->idcode == ID_SCE) { + /* pass */ + } + else if (tselem->type != TSE_R_LAYER) { + /* this tree element always has same amount of branches, so don't draw */ + int tempx = startx + offsx; - // divider + /* divider */ UI_ThemeColorShade(TH_BACK, -40); glRecti(tempx - 10, *starty + 4, tempx - 8, *starty + UI_UNIT_Y - 4); @@ -1425,7 +1435,7 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene } } } - } + } /* store coord and continue, we need coordinates for elements outside view too */ te->xs = (float)startx; te->ys = (float)*starty; @@ -1436,7 +1446,7 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene for (ten = te->subtree.first; ten; ten = ten->next) outliner_draw_tree_element(C, block, scene, ar, soops, ten, startx + UI_UNIT_X, starty); - } + } else { for (ten = te->subtree.first; ten; ten = ten->next) outliner_set_coord_tree_element(soops, te, startx, starty); @@ -1523,7 +1533,7 @@ static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegio { TreeElement *te; int starty, startx; - float col[4]; + float col[3]; glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // only once @@ -1640,7 +1650,7 @@ void draw_outliner(const bContext *C) /* get actual width of column 1 */ outliner_rna_width(soops, &soops->tree, &sizex_rna, 0); - sizex_rna = MAX2(OL_RNA_COLX, sizex_rna + OL_RNA_COL_SPACEX); + sizex_rna = max_ii(OL_RNA_COLX, sizex_rna + OL_RNA_COL_SPACEX); /* get width of data (for setting 'tot' rect, this is column 1 + column 2 + a bit extra) */ if (soops->outlinevis == SO_KEYMAP) @@ -1693,7 +1703,7 @@ void draw_outliner(const bContext *C) } /* draw edit buttons if nessecery */ - outliner_buttons(C, block, ar, soops, &soops->tree); + outliner_buttons(C, block, ar, soops, &soops->tree); uiEndBlock(C, block); uiDrawBlock(C, block); diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 0874ddcb279..23766d6a6fe 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -81,7 +81,7 @@ static int outliner_open_back(SpaceOops *soops, TreeElement *te) for (te = te->parent; te; te = te->parent) { tselem = TREESTORE(te); - if (tselem->flag & TSE_CLOSED) { + if (tselem->flag & TSE_CLOSED) { tselem->flag &= ~TSE_CLOSED; retval = 1; } @@ -197,10 +197,10 @@ static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem, } else if (tselem->id->lib) { // XXX error_libdata(); - } + } else if (te->idcode == ID_LI && te->parent) { BKE_report(reports, RPT_WARNING, "Cannot edit the path of an indirectly linked library"); - } + } else { tselem->flag |= TSE_TEXTBUT; ED_region_tag_redraw(ar); @@ -368,12 +368,14 @@ void group_toggle_visibility_cb(bContext *UNUSED(C), Scene *scene, TreeElement * static int outliner_toggle_visibility_exec(bContext *C, wmOperator *UNUSED(op)) { + Main *bmain = CTX_data_main(C); SpaceOops *soops = CTX_wm_space_outliner(C); Scene *scene = CTX_data_scene(C); ARegion *ar = CTX_wm_region(C); outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_visibility_cb); + DAG_id_type_tag(bmain, ID_OB); WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene); ED_region_tag_redraw(ar); @@ -464,11 +466,13 @@ void group_toggle_renderability_cb(bContext *UNUSED(C), Scene *scene, TreeElemen static int outliner_toggle_renderability_exec(bContext *C, wmOperator *UNUSED(op)) { + Main *bmain = CTX_data_main(C); SpaceOops *soops = CTX_wm_space_outliner(C); Scene *scene = CTX_data_scene(C); outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_renderability_cb); + DAG_id_type_tag(bmain, ID_OB); WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, scene); return OPERATOR_FINISHED; @@ -579,11 +583,11 @@ static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op)) te = outliner_find_id(so, &so->tree, (ID *)OBACT); if (te) { /* make te->ys center of view */ - ytop = (int)(te->ys + BLI_RCT_SIZE_Y(&v2d->mask) / 2); + ytop = (int)(te->ys + BLI_rcti_size_y(&v2d->mask) / 2); if (ytop > 0) ytop = 0; v2d->cur.ymax = (float)ytop; - v2d->cur.ymin = (float)(ytop - BLI_RCT_SIZE_Y(&v2d->mask)); + v2d->cur.ymin = (float)(ytop - BLI_rcti_size_y(&v2d->mask)); /* make te->xs ==> te->xend center of view */ xdelta = (int)(te->xs - v2d->cur.xmin); @@ -615,7 +619,7 @@ void OUTLINER_OT_show_active(wmOperatorType *ot) static int outliner_scroll_page_exec(bContext *C, wmOperator *op) { ARegion *ar = CTX_wm_region(C); - int dy = BLI_RCT_SIZE_Y(&ar->v2d.mask); + int dy = BLI_rcti_size_y(&ar->v2d.mask); int up = 0; if (RNA_boolean_get(op->ptr, "up")) @@ -726,7 +730,7 @@ static void outliner_find_panel(Scene *UNUSED(scene), ARegion *ar, SpaceOops *so /* determine which type of search to do */ if (again && last_find) { - /* no popup panel - previous + user wanted to search for next after previous */ + /* no popup panel - previous + user wanted to search for next after previous */ BLI_strncpy(name, soops->search_string, sizeof(name)); flags = soops->search_flags; @@ -742,7 +746,7 @@ static void outliner_find_panel(Scene *UNUSED(scene), ARegion *ar, SpaceOops *so /* pop up panel - no previous, or user didn't want search after previous */ name[0] = '\0'; // XXX if (sbutton(name, 0, sizeof(name)-1, "Find: ") && name[0]) { -// te= outliner_find_name(soops, &soops->tree, name, flags, NULL, &prevFound); +// te = outliner_find_name(soops, &soops->tree, name, flags, NULL, &prevFound); // } // else return; /* XXX RETURN! XXX */ } @@ -760,10 +764,10 @@ static void outliner_find_panel(Scene *UNUSED(scene), ARegion *ar, SpaceOops *so tselem->flag |= TSE_SELECTED; /* make te->ys center of view */ - ytop = (int)(te->ys + BLI_RCT_SIZE_Y(&ar->v2d.mask) / 2); + ytop = (int)(te->ys + BLI_rctf_size_y(&ar->v2d.mask) / 2); if (ytop > 0) ytop = 0; ar->v2d.cur.ymax = (float)ytop; - ar->v2d.cur.ymin = (float)(ytop - BLI_RCT_SIZE_Y(&ar->v2d.mask)); + ar->v2d.cur.ymin = (float)(ytop - BLI_rctf_size_y(&ar->v2d.mask)); /* make te->xs ==> te->xend center of view */ xdelta = (int)(te->xs - ar->v2d.cur.xmin); @@ -782,7 +786,7 @@ static void outliner_find_panel(Scene *UNUSED(scene), ARegion *ar, SpaceOops *so } else { /* no tree-element found */ - BKE_report(reports, RPT_WARNING, "Not found: %s", name); + BKE_reportf(reports, RPT_WARNING, "Not found: %s", name); } } #endif @@ -994,7 +998,7 @@ static void tree_element_to_path(SpaceOops *soops, TreeElement *te, TreeStoreEle char buf[128], *name; temnext = (TreeElement *)(ld->next->data); - /* tsenext= TREESTORE(temnext); */ /* UNUSED */ + /* tsenext = TREESTORE(temnext); */ /* UNUSED */ nextptr = &temnext->rnaptr; name = RNA_struct_name_get_alloc(nextptr, buf, sizeof(buf), NULL); @@ -1340,7 +1344,7 @@ static int outliner_keyingset_additems_exec(bContext *C, wmOperator *op) /* check for invalid states */ if (ks == NULL) { - BKE_report(op->reports, RPT_ERROR, "Operation requires an Active Keying Set"); + BKE_report(op->reports, RPT_ERROR, "Operation requires an active keying set"); return OPERATOR_CANCELLED; } if (soutliner == NULL) @@ -1423,7 +1427,7 @@ static int parent_drop_exec(bContext *C, wmOperator *op) RNA_string_get(op->ptr, "child", childname); ob = (Object *)BKE_libblock_find_name(ID_OB, childname); - ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, FALSE); + ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, FALSE, FALSE); DAG_scene_sort(bmain, scene); DAG_ids_flush_update(bmain, 0); @@ -1514,7 +1518,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, wmEvent *event) } if ((par->type != OB_ARMATURE) && (par->type != OB_CURVE) && (par->type != OB_LATTICE)) { - if (ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, FALSE)) { + if (ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, FALSE, FALSE)) { DAG_scene_sort(bmain, scene); DAG_ids_flush_update(bmain, 0); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); @@ -1854,7 +1858,7 @@ static int material_drop_invoke(bContext *C, wmOperator *op, wmEvent *event) assign_material(ob, ma, ob->totcol + 1, BKE_MAT_ASSIGN_USERPREF); DAG_ids_flush_update(bmain, 0); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C)); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C)); WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING, ma); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 823de61d044..4668dfa1386 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -236,7 +236,7 @@ static int tree_element_active_texture(bContext *C, Scene *scene, SpaceOops *soo if (ob == NULL) return 0; // no active object - /*tselem= TREESTORE(te);*/ /*UNUSED*/ + /*tselem = TREESTORE(te);*/ /*UNUSED*/ /* find buttons area (note, this is undefined really still, needs recode in blender) */ /* XXX removed finding sbuts */ @@ -250,8 +250,8 @@ static int tree_element_active_texture(bContext *C, Scene *scene, SpaceOops *soo if (set) { if (sbuts) { - // XXX sbuts->tabo= TAB_SHADING_TEX; // hack from header_buttonswin.c - // XXX sbuts->texfrom= 1; + // XXX sbuts->tabo = TAB_SHADING_TEX; // hack from header_buttonswin.c + // XXX sbuts->texfrom = 1; } // XXX extern_set_butspace(F6KEY, 0); // force shading buttons texture wrld->texact = te->index; @@ -264,8 +264,8 @@ static int tree_element_active_texture(bContext *C, Scene *scene, SpaceOops *soo Lamp *la = (Lamp *)tselemp->id; if (set) { if (sbuts) { - // XXX sbuts->tabo= TAB_SHADING_TEX; // hack from header_buttonswin.c - // XXX sbuts->texfrom= 2; + // XXX sbuts->tabo = TAB_SHADING_TEX; // hack from header_buttonswin.c + // XXX sbuts->texfrom = 2; } // XXX extern_set_butspace(F6KEY, 0); // force shading buttons texture la->texact = te->index; @@ -280,8 +280,8 @@ static int tree_element_active_texture(bContext *C, Scene *scene, SpaceOops *soo Material *ma = (Material *)tselemp->id; if (set) { if (sbuts) { - //sbuts->tabo= TAB_SHADING_TEX; // hack from header_buttonswin.c - // XXX sbuts->texfrom= 0; + //sbuts->tabo = TAB_SHADING_TEX; // hack from header_buttonswin.c + // XXX sbuts->texfrom = 0; } // XXX extern_set_butspace(F6KEY, 0); // force shading buttons texture ma->texact = (char)te->index; diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index bf76fdda61e..3b83279e09d 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -158,11 +158,16 @@ static void unlink_material_cb(bContext *UNUSED(C), Scene *UNUSED(scene), TreeEl totcol = mb->totcol; matar = mb->mat; } + else { + BLI_assert(0); + } - for (a = 0; a < totcol; a++) { - if (a == te->index && matar[a]) { - matar[a]->id.us--; - matar[a] = NULL; + if (LIKELY(matar != NULL)) { + for (a = 0; a < totcol; a++) { + if (a == te->index && matar[a]) { + matar[a]->id.us--; + matar[a] = NULL; + } } } } @@ -811,7 +816,7 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op) ED_undo_push(C, "Unlink world"); break; default: - BKE_report(op->reports, RPT_WARNING, "Not Yet"); + BKE_report(op->reports, RPT_WARNING, "Not yet implemented"); break; } } @@ -844,7 +849,7 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op) break; default: - BKE_report(op->reports, RPT_WARNING, "Not Yet"); + BKE_report(op->reports, RPT_WARNING, "Not yet implemented"); break; } } @@ -974,15 +979,15 @@ static int outliner_action_set_exec(bContext *C, wmOperator *op) act = BLI_findlink(&CTX_data_main(C)->action, RNA_enum_get(op->ptr, "action")); if (act == NULL) { - BKE_report(op->reports, RPT_ERROR, "No valid Action to add"); + BKE_report(op->reports, RPT_ERROR, "No valid action to add"); return OPERATOR_CANCELLED; } else if (act->idroot == 0) { /* hopefully in this case (i.e. library of userless actions), the user knows what they're doing... */ BKE_reportf(op->reports, RPT_WARNING, - "Action '%s' does not specify what datablocks it can be used on. " - "Try setting the 'ID Root Type' setting from the Datablocks Editor " - "for this Action to avoid future problems", + "Action '%s' does not specify what datablocks it can be used on " + "(try setting the 'ID Root Type' setting from the Datablocks Editor " + "for this action to avoid future problems)", act->id.name + 2); } @@ -1160,37 +1165,50 @@ static int outliner_data_operation_exec(bContext *C, wmOperator *op) event = RNA_enum_get(op->ptr, "type"); set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel); - if (datalevel == TSE_POSE_CHANNEL) { - if (event > 0) { + if (event <= 0) + return OPERATOR_CANCELLED; + + switch (datalevel) { + case TSE_POSE_CHANNEL: + { outliner_do_data_operation(soops, datalevel, event, &soops->tree, pchan_cb, NULL); WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL); ED_undo_push(C, "PoseChannel operation"); } - } - else if (datalevel == TSE_BONE) { - if (event > 0) { + break; + + case TSE_BONE: + { outliner_do_data_operation(soops, datalevel, event, &soops->tree, bone_cb, NULL); WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL); ED_undo_push(C, "Bone operation"); } - } - else if (datalevel == TSE_EBONE) { - if (event > 0) { + break; + + case TSE_EBONE: + { outliner_do_data_operation(soops, datalevel, event, &soops->tree, ebone_cb, NULL); WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL); ED_undo_push(C, "EditBone operation"); } - } - else if (datalevel == TSE_SEQUENCE) { - if (event > 0) { + break; + + case TSE_SEQUENCE: + { Scene *scene = CTX_data_scene(C); outliner_do_data_operation(soops, datalevel, event, &soops->tree, sequence_cb, scene); } - } - else if (datalevel == TSE_RNA_STRUCT) { - if (event == 5) { - outliner_do_data_operation(soops, datalevel, event, &soops->tree, data_select_linked_cb, C); - } + break; + + case TSE_RNA_STRUCT: + if (event == 5) { + outliner_do_data_operation(soops, datalevel, event, &soops->tree, data_select_linked_cb, C); + } + break; + + default: + BKE_report(op->reports, RPT_WARNING, "Not yet implemented"); + break; } return OPERATOR_FINISHED; @@ -1262,12 +1280,15 @@ static int do_outliner_operation_event(bContext *C, Scene *scene, ARegion *ar, S else { if (datalevel == TSE_ANIM_DATA) WM_operator_name_call(C, "OUTLINER_OT_animdata_operation", WM_OP_INVOKE_REGION_WIN, NULL); - else if (datalevel == TSE_DRIVER_BASE) - /* do nothing... no special ops needed yet */; - else if (ELEM3(datalevel, TSE_R_LAYER_BASE, TSE_R_LAYER, TSE_R_PASS)) - /*WM_operator_name_call(C, "OUTLINER_OT_renderdata_operation", WM_OP_INVOKE_REGION_WIN, NULL)*/; - else + else if (datalevel == TSE_DRIVER_BASE) { + /* do nothing... no special ops needed yet */ + } + else if (ELEM3(datalevel, TSE_R_LAYER_BASE, TSE_R_LAYER, TSE_R_PASS)) { + /*WM_operator_name_call(C, "OUTLINER_OT_renderdata_operation", WM_OP_INVOKE_REGION_WIN, NULL)*/ + } + else { WM_operator_name_call(C, "OUTLINER_OT_data_operation", WM_OP_INVOKE_REGION_WIN, NULL); + } } } @@ -1289,11 +1310,13 @@ static int outliner_operation(bContext *C, wmOperator *UNUSED(op), wmEvent *even SpaceOops *soops = CTX_wm_space_outliner(C); TreeElement *te; float fmval[2]; - + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], fmval, fmval + 1); for (te = soops->tree.first; te; te = te->next) { - if (do_outliner_operation_event(C, scene, ar, soops, te, event, fmval)) break; + if (do_outliner_operation_event(C, scene, ar, soops, te, event, fmval)) { + break; + } } return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 3e1ce1fea6e..af890a81ad6 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -553,16 +553,16 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree if (md->type == eModifierType_Lattice) { outliner_add_element(soops, &te->subtree, ((LatticeModifierData *) md)->object, te, TSE_LINKED_OB, 0); - } + } else if (md->type == eModifierType_Curve) { outliner_add_element(soops, &te->subtree, ((CurveModifierData *) md)->object, te, TSE_LINKED_OB, 0); - } + } else if (md->type == eModifierType_Armature) { outliner_add_element(soops, &te->subtree, ((ArmatureModifierData *) md)->object, te, TSE_LINKED_OB, 0); - } + } else if (md->type == eModifierType_Hook) { outliner_add_element(soops, &te->subtree, ((HookModifierData *) md)->object, te, TSE_LINKED_OB, 0); - } + } else if (md->type == eModifierType_ParticleSystem) { TreeElement *ten; ParticleSystem *psys = ((ParticleSystemModifierData *) md)->psys; @@ -590,7 +590,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree /* duplicated group */ if (ob->dup_group) - outliner_add_element(soops, &te->subtree, ob->dup_group, te, 0, 0); + outliner_add_element(soops, &te->subtree, ob->dup_group, te, 0, 0); } // can be inlined if necessary @@ -731,7 +731,7 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor case ID_AC: { // XXX do we want to be exposing the F-Curves here? - //bAction *act= (bAction *)id; + //bAction *act = (bAction *)id; } break; case ID_AR: @@ -769,7 +769,9 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor else { /* do not extend Armature when we have posemode */ tselem = TREESTORE(te->parent); - if (GS(tselem->id->name) == ID_OB && ((Object *)tselem->id)->mode & OB_MODE_POSE) ; + if (GS(tselem->id->name) == ID_OB && ((Object *)tselem->id)->mode & OB_MODE_POSE) { + /* pass */ + } else { Bone *curBone; for (curBone = arm->bonebase.first; curBone; curBone = curBone->next) { @@ -811,9 +813,15 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i te->parent = parent; te->index = index; // for data arays - if (ELEM3(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) ; - else if (ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) ; - else if (type == TSE_ANIM_DATA) ; + if (ELEM3(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) { + /* pass */ + } + else if (ELEM3(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) { + /* pass */ + } + else if (type == TSE_ANIM_DATA) { + /* pass */ + } else { te->name = id->name + 2; // default, can be overridden by Library or non-ID data te->idcode = GS(id->name); @@ -1055,8 +1063,12 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i if (key[0]) { wmOperatorType *ot = NULL; - if (kmi->propvalue) ; - else ot = WM_operatortype_find(kmi->idname, 0); + if (kmi->propvalue) { + /* pass */ + } + else { + ot = WM_operatortype_find(kmi->idname, 0); + } if (ot || kmi->propvalue) { TreeElement *ten = outliner_add_element(soops, &te->subtree, kmi, te, TSE_KEYMAP_ITEM, a); @@ -1136,7 +1148,7 @@ static void outliner_add_seq_dup(SpaceOops *soops, Sequence *seq, TreeElement *t } if (!strcmp(p->strip->stripdata->name, seq->strip->stripdata->name)) - /* ch= */ /* UNUSED */ outliner_add_element(soops, &te->subtree, (void *)p, te, TSE_SEQUENCE, index); + /* ch = */ /* UNUSED */ outliner_add_element(soops, &te->subtree, (void *)p, te, TSE_SEQUENCE, index); p = p->next; } } @@ -1519,7 +1531,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) while (seq) { op = need_add_seq_dup(seq); if (op == 1) { - /* ten= */ outliner_add_element(soops, &soops->tree, (void *)seq, NULL, TSE_SEQUENCE, 0); + /* ten = */ outliner_add_element(soops, &soops->tree, (void *)seq, NULL, TSE_SEQUENCE, 0); } else if (op == 0) { ten = outliner_add_element(soops, &soops->tree, (void *)seq, NULL, TSE_SEQUENCE_DUP, 0); @@ -1557,7 +1569,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) wmKeyMap *km; for (km = wm->defaultconf->keymaps.first; km; km = km->next) { - /* ten= */ outliner_add_element(soops, &soops->tree, (void *)km, NULL, TSE_KEYMAP, 0); + /* ten = */ outliner_add_element(soops, &soops->tree, (void *)km, NULL, TSE_KEYMAP, 0); } } else { diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt index c1f7fc942e4..f108d9f1aaa 100644 --- a/source/blender/editors/space_sequencer/CMakeLists.txt +++ b/source/blender/editors/space_sequencer/CMakeLists.txt @@ -57,4 +57,8 @@ if(WITH_AUDASPACE) add_definitions(-DWITH_AUDASPACE) endif() +if(WITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) +endif() + blender_add_lib(bf_editor_space_sequencer "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/space_sequencer/SConscript b/source/blender/editors/space_sequencer/SConscript index ec06eacae9c..0b429ae750b 100644 --- a/source/blender/editors/space_sequencer/SConscript +++ b/source/blender/editors/space_sequencer/SConscript @@ -8,7 +8,12 @@ incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../makesrna ../../blenloader ../../blenfont' incs += ' #/intern/audaspace/intern' +defs = [] + if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): incs += ' ' + env['BF_PTHREADS_INC'] -env.BlenderLib ( 'bf_editors_space_sequencer', sources, Split(incs), [], libtype=['core'], priority=[100] ) +if env['WITH_BF_INTERNATIONAL']: + defs.append('WITH_INTERNATIONAL') + +env.BlenderLib ( 'bf_editors_space_sequencer', sources, Split(incs), defs, libtype=['core'], priority=[100] ) diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 7b7170d99e0..fd46f69da83 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -242,7 +242,7 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op) strip->us = 1; BLI_strncpy(seq->name + 2, sce_seq->id.name + 2, sizeof(seq->name) - 2); - BKE_seqence_base_unique_name_recursive(&ed->seqbase, seq); + BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq); seq->scene_sound = sound_scene_add_scene_sound(scene, seq, start_frame, start_frame + seq->len, 0); @@ -325,7 +325,7 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op) clip = BLI_findlink(&CTX_data_main(C)->movieclip, RNA_enum_get(op->ptr, "clip")); if (clip == NULL) { - BKE_report(op->reports, RPT_ERROR, "MovieClip not found"); + BKE_report(op->reports, RPT_ERROR, "Movie clip not found"); return OPERATOR_CANCELLED; } @@ -343,7 +343,7 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op) strip->us = 1; BLI_strncpy(seq->name + 2, clip->id.name + 2, sizeof(seq->name) - 2); - BKE_seqence_base_unique_name_recursive(&ed->seqbase, seq); + BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq); BKE_sequence_calc_disp(scene, seq); BKE_sequencer_sort(scene); @@ -439,7 +439,7 @@ static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op) strip->us = 1; BLI_strncpy(seq->name + 2, mask->id.name + 2, sizeof(seq->name) - 2); - BKE_seqence_base_unique_name_recursive(&ed->seqbase, seq); + BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq); BKE_sequence_calc_disp(scene, seq); BKE_sequencer_sort(scene); @@ -553,7 +553,7 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad } if (seq_load.tot_success == 0) { - BKE_reportf(op->reports, RPT_ERROR, "File \"%s\" could not be loaded", seq_load.path); + BKE_reportf(op->reports, RPT_ERROR, "File '%s' could not be loaded", seq_load.path); return OPERATOR_CANCELLED; } @@ -820,7 +820,7 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op) seq->type = type; BLI_strncpy(seq->name + 2, BKE_sequence_give_name(seq), sizeof(seq->name) - 2); - BKE_seqence_base_unique_name_recursive(&ed->seqbase, seq); + BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq); sh = BKE_sequence_get_effect(seq); diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 7363bf2fbd8..29babd355ad 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -355,7 +355,7 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla y2 = seq->machine + SEQ_STRIP_OFSTOP; /* set up co-ordinates/dimensions for either left or right handle */ - if (direction == SEQ_LEFTHANDLE) { + if (direction == SEQ_LEFTHANDLE) { rx1 = x1; rx2 = x1 + handsize_clamped * 0.75f; @@ -415,7 +415,7 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla y1 = y2 + 0.05f; } UI_view2d_text_cache_add(v2d, x1, y1, numstr, col); - } + } } static void draw_seq_extensions(Scene *scene, ARegion *ar, Sequence *seq) @@ -432,7 +432,7 @@ static void draw_seq_extensions(Scene *scene, ARegion *ar, Sequence *seq) y1 = seq->machine + SEQ_STRIP_OFSBOTTOM; y2 = seq->machine + SEQ_STRIP_OFSTOP; - pixely = BLI_RCT_SIZE_Y(&v2d->cur) / BLI_RCT_SIZE_Y(&v2d->mask); + pixely = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask); if (pixely <= 0) return; /* can happen when the view is split/resized */ @@ -725,7 +725,7 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline /* draw sound wave */ if (seq->type == SEQ_TYPE_SOUND_RAM) { - drawseqwave(scene, seq, x1, y1, x2, y2, BLI_RCT_SIZE_X(&ar->v2d.cur) / ar->winx); + drawseqwave(scene, seq, x1, y1, x2, y2, BLI_rctf_size_x(&ar->v2d.cur) / ar->winx); } /* draw lock */ @@ -747,7 +747,7 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline glDisable(GL_BLEND); } - if (!BKE_seqence_is_valid_check(seq)) { + if (!BKE_sequence_is_valid_check(seq)) { glEnable(GL_POLYGON_STIPPLE); /* panic! */ @@ -810,7 +810,7 @@ static void UNUSED_FUNCTION(set_special_seq_update) (int val) /* if mouse over a sequence && LEFTMOUSE */ if (val) { -// XXX special_seq_update= find_nearest_seq(&x); +// XXX special_seq_update = find_nearest_seq(&x); } else special_seq_update = NULL; } @@ -885,7 +885,10 @@ static ImBuf *sequencer_make_scope(Scene *scene, ImBuf *ibuf, ImBuf *(*make_scop ImBuf *display_ibuf = IMB_dupImBuf(ibuf); ImBuf *scope; - IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings, &scene->display_settings); + if (display_ibuf->rect_float) { + IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings, + &scene->display_settings); + } scope = make_scope_cb(display_ibuf); @@ -967,7 +970,10 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq if (!scopes->zebra_ibuf) { ImBuf *display_ibuf = IMB_dupImBuf(ibuf); - IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings, &scene->display_settings); + if (display_ibuf->rect_float) { + IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings, + &scene->display_settings); + } scopes->zebra_ibuf = make_zebra_view_from_ibuf(display_ibuf, sseq->zebra); IMB_freeImBuf(display_ibuf); } @@ -1032,10 +1038,10 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq if (draw_overlay) { if (sseq->overlay_type == SEQ_DRAW_OVERLAY_RECT) { rctf tot_clip; - tot_clip.xmin = v2d->tot.xmin + (ABS(BLI_RCT_SIZE_X(&v2d->tot)) * scene->ed->over_border.xmin); - tot_clip.ymin = v2d->tot.ymin + (ABS(BLI_RCT_SIZE_Y(&v2d->tot)) * scene->ed->over_border.ymin); - tot_clip.xmax = v2d->tot.xmin + (ABS(BLI_RCT_SIZE_X(&v2d->tot)) * scene->ed->over_border.xmax); - tot_clip.ymax = v2d->tot.ymin + (ABS(BLI_RCT_SIZE_Y(&v2d->tot)) * scene->ed->over_border.ymax); + tot_clip.xmin = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmin); + tot_clip.ymin = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymin); + tot_clip.xmax = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmax); + tot_clip.ymax = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymax); glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmin, tot_clip.ymin); glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmin, tot_clip.ymax); @@ -1183,7 +1189,7 @@ static void draw_seq_backdrop(View2D *v2d) glRectf(v2d->cur.xmin, -1.0, v2d->cur.xmax, 1.0); /* Alternating horizontal stripes */ - i = maxi(1, ((int)v2d->cur.ymin) - 1); + i = max_ii(1, ((int)v2d->cur.ymin) - 1); glBegin(GL_QUADS); while (i < v2d->cur.ymax) { @@ -1202,7 +1208,7 @@ static void draw_seq_backdrop(View2D *v2d) glEnd(); /* Darker lines separating the horizontal bands */ - i = maxi(1, ((int)v2d->cur.ymin) - 1); + i = max_ii(1, ((int)v2d->cur.ymin) - 1); UI_ThemeColor(TH_GRID); glBegin(GL_LINES); @@ -1222,7 +1228,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar) View2D *v2d = &ar->v2d; Sequence *last_seq = BKE_sequencer_active_get(scene); int sel = 0, j; - float pixelx = BLI_RCT_SIZE_X(&v2d->cur) / BLI_RCT_SIZE_X(&v2d->mask); + float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); /* loop through twice, first unselected, then selected */ for (j = 0; j < 2; j++) { @@ -1234,8 +1240,8 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar) /* boundbox and selection tests for NOT drawing the strip... */ if ((seq->flag & SELECT) != sel) continue; else if (seq == last_seq) continue; - else if (MIN2(seq->startdisp, seq->start) > v2d->cur.xmax) continue; - else if (MAX2(seq->enddisp, seq->start + seq->len) < v2d->cur.xmin) continue; + else if (min_ii(seq->startdisp, seq->start) > v2d->cur.xmax) continue; + else if (max_ii(seq->enddisp, seq->start + seq->len) < v2d->cur.xmin) continue; else if (seq->machine + 1.0f < v2d->cur.ymin) continue; else if (seq->machine > v2d->cur.ymax) continue; diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index f47eb339878..7270516aa51 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -46,6 +46,8 @@ #include "BLI_utildefines.h" #include "BLI_threads.h" +#include "BLF_translation.h" + #include "DNA_scene_types.h" #include "DNA_userdef_types.h" @@ -372,7 +374,7 @@ Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[ if (ed == NULL) return NULL; - pixelx = BLI_RCT_SIZE_X(&v2d->cur) / BLI_RCT_SIZE_X(&v2d->mask); + pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); @@ -507,7 +509,7 @@ int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequen for (seq = ed->seqbasep->first; seq; seq = seq->next) { if (seq->flag & SELECT) { if (seq->type == SEQ_TYPE_SOUND_RAM && BKE_sequence_effect_get_num_inputs(type) != 0) { - *error_str = "Can't apply effects to audio sequence strips"; + *error_str = N_("Cannot apply effects to audio sequence strips"); return 0; } if ((seq != activeseq) && (seq != seq2)) { @@ -515,7 +517,7 @@ int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequen else if (seq1 == NULL) seq1 = seq; else if (seq3 == NULL) seq3 = seq; else { - *error_str = "Can't apply effect to more than 3 sequence strips"; + *error_str = N_("Cannot apply effect to more than 3 sequence strips"); return 0; } } @@ -537,21 +539,21 @@ int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequen return 1; /* succsess */ case 1: if (seq2 == NULL) { - *error_str = "Need at least one selected sequence strip"; + *error_str = N_("At least one selected sequence strip is needed"); return 0; } if (seq1 == NULL) seq1 = seq2; if (seq3 == NULL) seq3 = seq2; case 2: if (seq1 == NULL || seq2 == NULL) { - *error_str = "Need 2 selected sequence strips"; + *error_str = N_("2 selected sequence strips are needed"); return 0; } if (seq3 == NULL) seq3 = seq2; } if (seq1 == NULL && seq2 == NULL && seq3 == NULL) { - *error_str = "TODO: in what cases does this happen?"; + *error_str = N_("TODO: in what cases does this happen?"); return 0; } @@ -579,7 +581,9 @@ static Sequence *del_seq_find_replace_recurs(Scene *scene, Sequence *seq) seq2 = del_seq_find_replace_recurs(scene, seq->seq2); seq3 = del_seq_find_replace_recurs(scene, seq->seq3); - if (seq1 == seq->seq1 && seq2 == seq->seq2 && seq3 == seq->seq3) ; + if (seq1 == seq->seq1 && seq2 == seq->seq2 && seq3 == seq->seq3) { + /* pass */ + } else if (seq1 || seq2 || seq3) { seq->seq1 = (seq1) ? seq1 : (seq2) ? seq2 : seq3; seq->seq2 = (seq2) ? seq2 : (seq1) ? seq1 : seq3; @@ -678,7 +682,7 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe) seqn = BKE_sequence_dupli_recursive(scene, NULL, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM); } - if (seqn) { + if (seqn) { seqn->flag |= SELECT; /* Second Strip! */ @@ -699,7 +703,7 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe) seqn->anim_startofs += cutframe - ts.start; seqn->anim_endofs = ts.anim_endofs; seqn->endstill = ts.endstill; - } + } /* strips with extended stillframes after */ else if (((seqn->start + seqn->len) < cutframe) && (seqn->endstill)) { @@ -771,7 +775,7 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe) seqn = BKE_sequence_dupli_recursive(scene, NULL, seq, SEQ_DUPE_UNIQUE_NAME | SEQ_DUPE_ANIM); } - if (seqn) { + if (seqn) { seqn->flag |= SELECT; /* Second Strip! */ @@ -789,7 +793,7 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe) seqn->startofs = cutframe - ts.start; seqn->endofs = ts.endofs; seqn->endstill = ts.endstill; - } + } /* strips with extended stillframes after */ else if (((seqn->start + seqn->len) < cutframe) && (seqn->endstill)) { @@ -1054,7 +1058,7 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op) { if ((seq->flag & (SEQ_LEFTSEL + SEQ_RIGHTSEL)) == 0) { /* simple but no anim update */ - /* seq->start= snap_frame-seq->startofs+seq->startstill; */ + /* seq->start = snap_frame-seq->startofs+seq->startstill; */ BKE_sequence_translate(scene, seq, (snap_frame - seq->startofs + seq->startstill) - seq->start); } @@ -1143,13 +1147,13 @@ static int sequencer_mute_exec(bContext *C, wmOperator *op) if (selected) { /* mute unselected */ if (seq->flag & SELECT) { seq->flag |= SEQ_MUTE; - BKE_sequence_invalidate_deendent(scene, seq); + BKE_sequence_invalidate_dependent(scene, seq); } } else { if ((seq->flag & SELECT) == 0) { seq->flag |= SEQ_MUTE; - BKE_sequence_invalidate_deendent(scene, seq); + BKE_sequence_invalidate_dependent(scene, seq); } } } @@ -1194,13 +1198,13 @@ static int sequencer_unmute_exec(bContext *C, wmOperator *op) if (selected) { /* unmute unselected */ if (seq->flag & SELECT) { seq->flag &= ~SEQ_MUTE; - BKE_sequence_invalidate_deendent(scene, seq); + BKE_sequence_invalidate_dependent(scene, seq); } } else { if ((seq->flag & SELECT) == 0) { seq->flag &= ~SEQ_MUTE; - BKE_sequence_invalidate_deendent(scene, seq); + BKE_sequence_invalidate_dependent(scene, seq); } } } @@ -1382,7 +1386,7 @@ static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op) seq_is_predecessor(seq2, last_seq) || seq_is_predecessor(seq3, last_seq)) { - BKE_report(op->reports, RPT_ERROR, "Can't reassign inputs: no cycles allowed"); + BKE_report(op->reports, RPT_ERROR, "Cannot reassign inputs: no cycles allowed"); return OPERATOR_CANCELLED; } @@ -1572,8 +1576,8 @@ static int apply_unique_name_cb(Sequence *seq, void *arg_pt) Scene *scene = (Scene *)arg_pt; char name[sizeof(seq->name) - 2]; - strcpy(name, seq->name + 2); - BKE_seqence_base_unique_name_recursive(&scene->ed->seqbase, seq); + BLI_strncpy_utf8(name, seq->name + 2, sizeof(name)); + BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); BKE_sequencer_dupe_animdata(scene, name, seq->name + 2); return 1; @@ -1851,7 +1855,7 @@ void SEQUENCER_OT_images_separate(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_int(ot->srna, "length", 1, 1, 1000, "Length", "Length of each frame", 1, INT_MAX); + RNA_def_int(ot->srna, "length", 1, 1, INT_MAX, "Length", "Length of each frame", 1, 1000); } @@ -1950,7 +1954,7 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op) while (seq) { next = seq->next; if (seq != seqm && (seq->flag & SELECT)) { - channel_max = MAX2(seq->machine, channel_max); + channel_max = max_ii(seq->machine, channel_max); BLI_remlink(ed->seqbasep, seq); BLI_addtail(&seqm->seqbase, seq); } @@ -1968,7 +1972,7 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op) BKE_sequencer_update_muting(ed); - BKE_seqence_base_unique_name_recursive(&scene->ed->seqbase, seqm); + BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seqm); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); @@ -2127,7 +2131,7 @@ static int sequencer_view_all_preview_exec(bContext *C, wmOperator *UNUSED(op)) zoomY = ((float)height) / ((float)imgheight); sseq->zoom = (zoomX < zoomY) ? zoomX : zoomY; - sseq->zoom = 1.0f / power_of_2(1 / minf(zoomX, zoomY)); + sseq->zoom = 1.0f / power_of_2(1 / min_ff(zoomX, zoomY)); } else { sseq->zoom = 1.0f; @@ -2164,8 +2168,8 @@ static int sequencer_view_zoom_ratio_exec(bContext *C, wmOperator *op) float winx = (int)(rd->size * rd->xsch) / 100; float winy = (int)(rd->size * rd->ysch) / 100; - float facx = BLI_RCT_SIZE_X(&v2d->mask) / winx; - float facy = BLI_RCT_SIZE_Y(&v2d->mask) / winy; + float facx = BLI_rcti_size_x(&v2d->mask) / winx; + float facy = BLI_rcti_size_y(&v2d->mask) / winy; BLI_rctf_resize(&v2d->cur, (int)(winx * facx * ratio) + 1, (int)(winy * facy * ratio) + 1); @@ -2186,7 +2190,7 @@ void SEQUENCER_OT_view_zoom_ratio(wmOperatorType *ot) ot->poll = ED_operator_sequencer_active; /* properties */ - RNA_def_float(ot->srna, "ratio", 1.0f, 0.0f, FLT_MAX, + RNA_def_float(ot->srna, "ratio", 1.0f, -FLT_MAX, FLT_MAX, "Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out", -FLT_MAX, FLT_MAX); } @@ -2253,11 +2257,11 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) for (seq = ed->seqbasep->first; seq; seq = seq->next) { if (seq->flag & SELECT) { - xmin = MIN2(xmin, seq->startdisp); - xmax = MAX2(xmax, seq->enddisp); + xmin = min_ii(xmin, seq->startdisp); + xmax = max_ii(xmax, seq->enddisp); - ymin = MIN2(ymin, seq->machine); - ymax = MAX2(ymax, seq->machine); + ymin = min_ii(ymin, seq->machine); + ymax = max_ii(ymax, seq->machine); } } @@ -2268,7 +2272,7 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) ymax += ymargin; ymin -= ymargin; - orig_height = BLI_RCT_SIZE_Y(&cur_new); + orig_height = BLI_rctf_size_y(&cur_new); cur_new.xmin = xmin; cur_new.xmax = xmax; @@ -2277,8 +2281,8 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) cur_new.ymax = ymax; /* only zoom out vertically */ - if (orig_height > BLI_RCT_SIZE_Y(&cur_new)) { - ymid = BLI_RCT_CENTER_Y(&cur_new); + if (orig_height > BLI_rctf_size_y(&cur_new)) { + ymid = BLI_rctf_cent_y(&cur_new); cur_new.ymin = ymid - (orig_height / 2); cur_new.ymax = ymid + (orig_height / 2); @@ -2618,7 +2622,6 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Editing *ed = BKE_sequencer_editing_get(scene, FALSE); - Sequence *seq; ListBase nseqbase = {NULL, NULL}; @@ -2654,8 +2657,11 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op) seqbase_clipboard_frame = scene->r.cfra; /* Need to remove anything that references the current scene */ - for (seq = seqbase_clipboard.first; seq; seq = seq->next) { - seq_copy_del_sound(scene, seq); + { + Sequence *seq; + for (seq = seqbase_clipboard.first; seq; seq = seq->next) { + seq_copy_del_sound(scene, seq); + } } return OPERATOR_FINISHED; @@ -2738,7 +2744,7 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op) const char *error_msg; if (BKE_sequencer_active_get_pair(scene, &seq_act, &seq_other) == 0) { - BKE_report(op->reports, RPT_ERROR, "Must select 2 strips"); + BKE_report(op->reports, RPT_ERROR, "Please select two strips"); return OPERATOR_CANCELLED; } @@ -2800,11 +2806,11 @@ static int view_ghost_border_exec(bContext *C, wmOperator *op) if (ed == NULL) return OPERATOR_CANCELLED; - rect.xmin /= (float)(ABS(BLI_RCT_SIZE_X(&v2d->tot))); - rect.ymin /= (float)(ABS(BLI_RCT_SIZE_Y(&v2d->tot))); + rect.xmin /= fabsf(BLI_rctf_size_x(&v2d->tot)); + rect.ymin /= fabsf(BLI_rctf_size_y(&v2d->tot)); - rect.xmax /= (float)(ABS(BLI_RCT_SIZE_X(&v2d->tot))); - rect.ymax /= (float)(ABS(BLI_RCT_SIZE_Y(&v2d->tot))); + rect.xmax /= fabsf(BLI_rctf_size_x(&v2d->tot)); + rect.ymax /= fabsf(BLI_rctf_size_y(&v2d->tot)); rect.xmin += 0.5f; rect.xmax += 0.5f; @@ -2901,7 +2907,7 @@ static int sequencer_change_effect_input_exec(bContext *C, wmOperator *op) } if (*seq_1 == NULL || *seq_2 == NULL) { - BKE_report(op->reports, RPT_ERROR, "One of the effect inputs is unset, can't swap"); + BKE_report(op->reports, RPT_ERROR, "One of the effect inputs is unset, cannot swap"); return OPERATOR_CANCELLED; } else { @@ -3038,7 +3044,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op) seq->anim_startofs = seq->anim_endofs = 0; /* correct start/end frames so we don't move - * important not to set seq->len= len; allow the function to handle it */ + * important not to set seq->len = len; allow the function to handle it */ BKE_sequence_reload_new_file(scene, seq, TRUE); BKE_sequence_calc(scene, seq); diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c index dc5cf98f515..70b288a59e6 100644 --- a/source/blender/editors/space_sequencer/sequencer_ops.c +++ b/source/blender/editors/space_sequencer/sequencer_ops.c @@ -78,6 +78,9 @@ void sequencer_operatortypes(void) WM_operatortype_append(SEQUENCER_OT_swap_data); WM_operatortype_append(SEQUENCER_OT_rendersize); + WM_operatortype_append(SEQUENCER_OT_copy); + WM_operatortype_append(SEQUENCER_OT_paste); + WM_operatortype_append(SEQUENCER_OT_view_all); WM_operatortype_append(SEQUENCER_OT_view_selected); WM_operatortype_append(SEQUENCER_OT_view_all_preview); @@ -110,10 +113,9 @@ void sequencer_operatortypes(void) WM_operatortype_append(SEQUENCER_OT_sound_strip_add); WM_operatortype_append(SEQUENCER_OT_image_strip_add); WM_operatortype_append(SEQUENCER_OT_effect_strip_add); - WM_operatortype_append(SEQUENCER_OT_properties); - WM_operatortype_append(SEQUENCER_OT_copy); - WM_operatortype_append(SEQUENCER_OT_paste); + /* sequencer_buttons.c */ + WM_operatortype_append(SEQUENCER_OT_properties); /* sequencer_modifiers.c */ WM_operatortype_append(SEQUENCER_OT_strip_modifier_add); @@ -132,7 +134,9 @@ void sequencer_keymap(wmKeyConfig *keyconf) /* Common items ------------------------------------------------------------------ */ keymap = WM_keymap_find(keyconf, "SequencerCommon", SPACE_SEQ, 0); - + + WM_keymap_add_item(keymap, "SEQUENCER_OT_properties", NKEY, KM_PRESS, 0, 0); + kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", OKEY, KM_PRESS, KM_SHIFT, 0); RNA_string_set(kmi->ptr, "data_path", "scene.sequence_editor.show_overlay"); @@ -141,9 +145,7 @@ void sequencer_keymap(wmKeyConfig *keyconf) /* Strips Region --------------------------------------------------------------- */ keymap = WM_keymap_find(keyconf, "Sequencer", SPACE_SEQ, 0); - - WM_keymap_add_item(keymap, "SEQUENCER_OT_properties", NKEY, KM_PRESS, 0, 0); - + kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_select_all", AKEY, KM_PRESS, 0, 0); RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE); kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0); @@ -153,12 +155,12 @@ void sequencer_keymap(wmKeyConfig *keyconf) RNA_enum_set(kmi->ptr, "type", SEQ_CUT_SOFT); kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_cut", KKEY, KM_PRESS, KM_SHIFT, 0); RNA_enum_set(kmi->ptr, "type", SEQ_CUT_HARD); - + kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_mute", HKEY, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "unselected", FALSE); kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_mute", HKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "unselected", TRUE); - + kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_unmute", HKEY, KM_PRESS, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "unselected", FALSE); kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_unmute", HKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0); @@ -179,7 +181,7 @@ void sequencer_keymap(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "SEQUENCER_OT_delete", XKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "SEQUENCER_OT_delete", DELKEY, KM_PRESS, 0, 0); - + WM_keymap_add_item(keymap, "SEQUENCER_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "SEQUENCER_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0); @@ -210,7 +212,7 @@ void sequencer_keymap(wmKeyConfig *keyconf) RNA_enum_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_swap", LEFTARROWKEY, KM_PRESS, KM_ALT, 0)->ptr, "side", SEQ_SIDE_LEFT); RNA_enum_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_swap", RIGHTARROWKEY, KM_PRESS, KM_ALT, 0)->ptr, "side", SEQ_SIDE_RIGHT); - + WM_keymap_add_item(keymap, "SEQUENCER_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "SEQUENCER_OT_swap_inputs", SKEY, KM_PRESS, KM_ALT, 0); @@ -245,7 +247,7 @@ void sequencer_keymap(wmKeyConfig *keyconf) RNA_boolean_set(kmi->ptr, "linked_left", TRUE); kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "linked_right", TRUE); - + kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_select", SELECTMOUSE, KM_PRESS, KM_CTRL | KM_ALT, 0); RNA_boolean_set(kmi->ptr, "linked_left", TRUE); RNA_boolean_set(kmi->ptr, "linked_right", TRUE); @@ -293,14 +295,14 @@ void sequencer_keymap(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "SEQUENCER_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "SEQUENCER_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0); - + kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_select_linked_pick", LKEY, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "extend", FALSE); kmi = WM_keymap_add_item(keymap, "SEQUENCER_OT_select_linked_pick", LKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "extend", TRUE); - + WM_keymap_add_item(keymap, "SEQUENCER_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0); - + WM_keymap_add_item(keymap, "SEQUENCER_OT_select_border", BKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "SEQUENCER_OT_select_grouped", GKEY, KM_PRESS, KM_SHIFT, 0); @@ -308,33 +310,32 @@ void sequencer_keymap(wmKeyConfig *keyconf) WM_keymap_add_menu(keymap, "SEQUENCER_MT_add", AKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_menu(keymap, "SEQUENCER_MT_change", CKEY, KM_PRESS, 0, 0); - + kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_int", OKEY, KM_PRESS, 0, 0); RNA_string_set(kmi->ptr, "data_path", "scene.sequence_editor.overlay_frame"); RNA_int_set(kmi->ptr, "value", 0); transform_keymap_for_space(keyconf, keymap, SPACE_SEQ); - + /* special markers hotkeys for anim editors: see note in definition of this function */ ED_marker_keymap_animedit_conflictfree(keymap); - - + + /* Preview Region ----------------------------------------------------------- */ keymap = WM_keymap_find(keyconf, "SequencerPreview", SPACE_SEQ, 0); WM_keymap_add_item(keymap, "SEQUENCER_OT_view_all_preview", HOMEKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "SEQUENCER_OT_properties", NKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "SEQUENCER_OT_view_ghost_border", OKEY, KM_PRESS, 0, 0); /* would prefer to use numpad keys for job */ RNA_float_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_view_zoom_ratio", PAD1, KM_PRESS, 0, 0)->ptr, "ratio", 1.0f); - + /* Setting zoom levels is not that useful, except for back to zoom level 1, removing keymap because of conflicts for now */ #if 0 RNA_float_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_view_zoom_ratio", PAD8, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 8.0f); RNA_float_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_view_zoom_ratio", PAD4, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 4.0f); RNA_float_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_view_zoom_ratio", PAD2, KM_PRESS, KM_SHIFT, 0)->ptr, "ratio", 2.0f); - + RNA_float_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_view_zoom_ratio", PAD2, KM_PRESS, 0, 0)->ptr, "ratio", 0.5f); RNA_float_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_view_zoom_ratio", PAD4, KM_PRESS, 0, 0)->ptr, "ratio", 0.25f); RNA_float_set(WM_keymap_add_item(keymap, "SEQUENCER_OT_view_zoom_ratio", PAD8, KM_PRESS, 0, 0)->ptr, "ratio", 0.125f); diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c index d09d6a29c10..6ed34a79510 100644 --- a/source/blender/editors/space_sequencer/sequencer_scopes.c +++ b/source/blender/editors/space_sequencer/sequencer_scopes.c @@ -449,6 +449,8 @@ static void draw_histogram_bar(ImBuf *ibuf, int x, float val, int col) } } +#define HIS_STEPS 512 + static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf) { ImBuf *rval = IMB_allocImBuf(515, 128, 32, IB_rect); @@ -456,13 +458,13 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf) unsigned int n; unsigned char *src = (unsigned char *) ibuf->rect; - unsigned int bins[3][256]; + unsigned int bins[3][HIS_STEPS]; memset(bins, 0, sizeof(bins)); #pragma omp parallel for shared(bins, src, ibuf) private(x, y) if (ibuf->y >= 256) for (y = 0; y < ibuf->y; y++) { - unsigned int cur_bins[3][512]; + unsigned int cur_bins[3][HIS_STEPS]; memset(cur_bins, 0, sizeof(cur_bins)); @@ -477,7 +479,7 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf) #pragma omp critical { int i; - for (i = 0; i < 512; i++) { + for (i = 0; i < HIS_STEPS; i++) { bins[0][i] += cur_bins[0][i]; bins[1][i] += cur_bins[1][i]; bins[2][i] += cur_bins[2][i]; @@ -487,7 +489,7 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf) n = 0; for (c = 0; c < 3; c++) { - for (x = 0; x < 256; x++) { + for (x = 0; x < HIS_STEPS; x++) { if (bins[c][x] > n) { n = bins[c][x]; } @@ -495,7 +497,7 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf) } for (c = 0; c < 3; c++) { - for (x = 0; x < 256; x++) { + for (x = 0; x < HIS_STEPS; x++) { draw_histogram_bar(rval, x * 2 + 1, ((float) bins[c][x]) / n, c); draw_histogram_bar(rval, x * 2 + 2, ((float) bins[c][x]) / n, c); } @@ -524,13 +526,13 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf) int n, c, x, y; float *src = ibuf->rect_float; - unsigned int bins[3][512]; + unsigned int bins[3][HIS_STEPS]; memset(bins, 0, sizeof(bins)); #pragma omp parallel for shared(bins, src, ibuf) private(x, y) if (ibuf->y >= 256) for (y = 0; y < ibuf->y; y++) { - unsigned int cur_bins[3][512]; + unsigned int cur_bins[3][HIS_STEPS]; memset(cur_bins, 0, sizeof(cur_bins)); @@ -545,7 +547,7 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf) #pragma omp critical { int i; - for (i = 0; i < 512; i++) { + for (i = 0; i < HIS_STEPS; i++) { bins[0][i] += cur_bins[0][i]; bins[1][i] += cur_bins[1][i]; bins[2][i] += cur_bins[2][i]; @@ -558,14 +560,14 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf) n = 0; for (c = 0; c < 3; c++) { - for (x = 0; x < 512; x++) { + for (x = 0; x < HIS_STEPS; x++) { if (bins[c][x] > n) { n = bins[c][x]; } } } for (c = 0; c < 3; c++) { - for (x = 0; x < 512; x++) { + for (x = 0; x < HIS_STEPS; x++) { draw_histogram_bar(rval, x + 1, (float) bins[c][x] / n, c); } } @@ -575,6 +577,8 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf) return rval; } +#undef HIS_STEPS + ImBuf *make_histogram_view_from_ibuf(ImBuf *ibuf) { if (ibuf->rect_float) { diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index 3d57f2f88ed..192f45ac918 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -353,7 +353,7 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, wmEvent *event) } else { /* deselect_markers(0, 0); */ /* XXX, in 2.4x, seq selection used to deselect all, need to re-thnik this for 2.5 */ - marker->flag |= SELECT; + marker->flag |= SELECT; } } @@ -399,7 +399,7 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, wmEvent *event) } } else { - // seq= find_nearest_seq(scene, v2d, &hand, mval); + // seq = find_nearest_seq(scene, v2d, &hand, mval); act_orig = ed->act_seq; @@ -414,8 +414,7 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, wmEvent *event) BLI_strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR); } } - else - if (seq->type == SEQ_TYPE_SOUND_RAM) { + else if (seq->type == SEQ_TYPE_SOUND_RAM) { if (seq->strip) { BLI_strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR); } @@ -1109,7 +1108,7 @@ static short select_grouped_effect_link(Editing *ed, Sequence *actseq) actseq->tmp = SET_INT_IN_POINTER(TRUE); - for (BKE_seqence_iterator_begin(ed, &iter, TRUE); iter.valid; BKE_seqence_iterator_next(&iter)) { + for (BKE_sequence_iterator_begin(ed, &iter, TRUE); iter.valid; BKE_sequence_iterator_next(&iter)) { seq = iter.seq; /* Ignore all seqs already selected! */ @@ -1137,8 +1136,8 @@ static short select_grouped_effect_link(Editing *ed, Sequence *actseq) changed = TRUE; /* Unfortunately, we must restart checks from the beginning. */ - BKE_seqence_iterator_end(&iter); - BKE_seqence_iterator_begin(ed, &iter, TRUE); + BKE_sequence_iterator_end(&iter); + BKE_sequence_iterator_begin(ed, &iter, TRUE); } /* Video strips bellow active one, or any strip for audio (order do no matters here!). */ @@ -1147,7 +1146,7 @@ static short select_grouped_effect_link(Editing *ed, Sequence *actseq) changed = TRUE; } } - BKE_seqence_iterator_end(&iter); + BKE_sequence_iterator_end(&iter); return changed; } @@ -1167,7 +1166,7 @@ static int sequencer_select_grouped_exec(bContext *C, wmOperator *op) extend = RNA_boolean_get(op->ptr, "extend"); if (actseq == NULL) { - BKE_report(op->reports, RPT_ERROR, "No Active Sequence!"); + BKE_report(op->reports, RPT_ERROR, "No active sequence!"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index 3c3489115a4..92b17393114 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -25,7 +25,7 @@ */ -/** \file blender/editors/space_sequencer/sequencer_modifier.c +/** \file blender/editors/space_sequencer/sequencer_view.c * \ingroup spseq */ diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 8ac50a57b10..e8d47016608 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -196,7 +196,7 @@ static SpaceLink *sequencer_new(const bContext *C) /* not spacelink itself */ static void sequencer_free(SpaceLink *sl) { - SpaceSeq *sseq= (SpaceSeq *) sl; + SpaceSeq *sseq = (SpaceSeq *) sl; SequencerScopes *scopes = &sseq->scopes; // XXX if (sseq->gpd) BKE_gpencil_free(sseq->gpd); @@ -311,7 +311,7 @@ static SpaceLink *sequencer_duplicate(SpaceLink *sl) SpaceSeq *sseqn = MEM_dupallocN(sl); /* clear or remove stuff from old */ -// XXX sseq->gpd= gpencil_data_duplicate(sseq->gpd); +// XXX sseq->gpd = gpencil_data_duplicate(sseq->gpd); return (SpaceLink *)sseqn; } @@ -363,7 +363,7 @@ static void sequencer_main_area_init(wmWindowManager *wm, ARegion *ar) static void sequencer_main_area_draw(const bContext *C, ARegion *ar) { -// ScrArea *sa= CTX_wm_area(C); +// ScrArea *sa = CTX_wm_area(C); /* NLE - strip editing timeline interface */ draw_timeline_seq(C, ar); @@ -556,8 +556,8 @@ static void sequencer_preview_area_listener(ARegion *ar, wmNotifier *wmn) { /* context changes */ switch (wmn->category) { - case NC_SCREEN: - if (wmn->data == ND_GPENCIL) { + case NC_GPENCIL: + if (wmn->action == NA_EDITED) { ED_region_tag_redraw(ar); } break; @@ -610,8 +610,8 @@ static void sequencer_buttons_area_listener(ARegion *ar, wmNotifier *wmn) { /* context changes */ switch (wmn->category) { - case NC_SCREEN: - if (wmn->data == ND_GPENCIL) { + case NC_GPENCIL: + if (wmn->data == ND_DATA) { ED_region_tag_redraw(ar); } break; diff --git a/source/blender/editors/space_text/CMakeLists.txt b/source/blender/editors/space_text/CMakeLists.txt index ead7de92c5c..9cc407f0604 100644 --- a/source/blender/editors/space_text/CMakeLists.txt +++ b/source/blender/editors/space_text/CMakeLists.txt @@ -54,4 +54,8 @@ if(WITH_PYTHON) add_definitions(-DWITH_PYTHON) endif() +if(WITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) +endif() + blender_add_lib(bf_editor_text "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/space_text/SConscript b/source/blender/editors/space_text/SConscript index 6ad6427f1d3..373564520c8 100644 --- a/source/blender/editors/space_text/SConscript +++ b/source/blender/editors/space_text/SConscript @@ -10,4 +10,7 @@ incs += ' ../../python ../../makesrna ../../blenfont ../../blenloader' if env['WITH_BF_PYTHON']: defs.append('WITH_PYTHON') +if env['WITH_BF_INTERNATIONAL']: + defs.append('WITH_INTERNATIONAL') + env.BlenderLib ( 'bf_editors_space_text', sources, Split(incs), defs, libtype=['core'], priority=[95] ) diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index 501e1cad67e..3f70b2cb66e 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -431,7 +431,7 @@ static void text_main_area_draw(const bContext *C, ARegion *ar) { /* draw entirely, view changes should be handled here */ SpaceText *st = CTX_wm_space_text(C); - //View2D *v2d= &ar->v2d; + //View2D *v2d = &ar->v2d; /* clear and setup matrix */ UI_ThemeClearColor(TH_BACK); diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index 97eb5b41db7..94f64563fd8 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -1139,7 +1139,7 @@ static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll, rcti *back) barheight = (ltexth > 0) ? (st->viewlines * pix_available) / ltexth : 0; pix_bardiff = 0; if (barheight < 20) { - pix_bardiff = 20 - barheight; /* take into account the now non-linear sizing of the bar */ + pix_bardiff = 20 - barheight; /* take into account the now non-linear sizing of the bar */ barheight = 20; } barstart = (ltexth > 0) ? ((pix_available - pix_bardiff) * st->top) / ltexth : 0; @@ -1166,9 +1166,9 @@ static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll, rcti *back) /* the scrollbar is non-linear sized */ if (pix_bardiff > 0) { /* the start of the highlight is in the current viewport */ - if (ltexth && st->viewlines && lhlstart >= st->top && lhlstart <= st->top + st->viewlines) { + if (ltexth && st->viewlines && lhlstart >= st->top && lhlstart <= st->top + st->viewlines) { /* speed the progresion of the start of the highlight through the scrollbar */ - hlstart = ( ( (pix_available - pix_bardiff) * lhlstart) / ltexth) + (pix_bardiff * (lhlstart - st->top) / st->viewlines); + hlstart = ( ( (pix_available - pix_bardiff) * lhlstart) / ltexth) + (pix_bardiff * (lhlstart - st->top) / st->viewlines); } else if (lhlstart > st->top + st->viewlines && hlstart < barstart + barheight && hlstart > barstart) { /* push hl start down */ @@ -1179,35 +1179,35 @@ static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll, rcti *back) hlstart = barstart; } - if (hlend <= hlstart) { + if (hlend <= hlstart) { hlend = hlstart + 2; } /* the end of the highlight is in the current viewport */ - if (ltexth && st->viewlines && lhlend >= st->top && lhlend <= st->top + st->viewlines) { + if (ltexth && st->viewlines && lhlend >= st->top && lhlend <= st->top + st->viewlines) { /* speed the progresion of the end of the highlight through the scrollbar */ hlend = (((pix_available - pix_bardiff) * lhlend) / ltexth) + (pix_bardiff * (lhlend - st->top) / st->viewlines); } else if (lhlend < st->top && hlend >= barstart - 2 && hlend < barstart + barheight) { /* push hl end up */ hlend = barstart; - } + } else if (lhlend > st->top + st->viewlines && lhlstart < st->top + st->viewlines && hlend < barstart + barheight) { /* fill out end */ hlend = barstart + barheight; } - if (hlend <= hlstart) { + if (hlend <= hlstart) { hlstart = hlend - 2; - } - } + } + } } else { hlstart = 0; hlend = 0; } - if (hlend - hlstart < 2) { + if (hlend - hlstart < 2) { hlend = hlstart + 2; } @@ -1232,7 +1232,7 @@ static void draw_textscroll(SpaceText *st, rcti *scroll, rcti *back) uiWidgetScrollDraw(&wcol, scroll, &st->txtbar, (st->flags & ST_SCROLL_SELECT) ? UI_SCROLL_PRESSED : 0); uiSetRoundBox(UI_CNR_ALL); - rad = 0.4f * mini(BLI_RCT_SIZE_X(&st->txtscroll), BLI_RCT_SIZE_Y(&st->txtscroll)); + rad = 0.4f * min_ii(BLI_rcti_size_x(&st->txtscroll), BLI_rcti_size_y(&st->txtscroll)); UI_GetThemeColor3ubv(TH_HILITE, col); col[3] = 48; glColor4ubv(col); @@ -1355,7 +1355,7 @@ static void draw_documentation(SpaceText *st, ARegion *ar) x += SUGG_LIST_WIDTH * st->cwidth + 50; } - /* top= */ /* UNUSED */ y = ar->winy - st->lheight * l - 2; + /* top = */ /* UNUSED */ y = ar->winy - st->lheight * l - 2; boxw = DOC_WIDTH * st->cwidth + 20; boxh = (DOC_HEIGHT + 1) * st->lheight; @@ -1702,7 +1702,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar) if (!endl || endc == -1) return; - UI_ThemeColor(TH_HILITE); + UI_ThemeColor(TH_HILITE); x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; y = ar->winy - st->lheight; @@ -1741,6 +1741,7 @@ void draw_text_main(SpaceText *st, ARegion *ar) char linenr[12]; int i, x, y, winx, linecount = 0, lineno = 0; int wraplinecount = 0, wrap_skip = 0; + int margin_column_x; if (st->lheight) st->viewlines = (int)ar->winy / st->lheight; else st->viewlines = 0; @@ -1788,7 +1789,7 @@ void draw_text_main(SpaceText *st, ARegion *ar) text_font_begin(st); st->cwidth = BLF_fixed_width(mono); - st->cwidth = MAX2(st->cwidth, 1); + st->cwidth = MAX2(st->cwidth, (char)1); /* draw line numbers background */ if (st->showlinenrs) { @@ -1845,10 +1846,14 @@ void draw_text_main(SpaceText *st, ARegion *ar) if (st->flags & ST_SHOW_MARGIN) { UI_ThemeColor(TH_HILITE); - glBegin(GL_LINES); - glVertex2i(x + st->cwidth * st->margin_column, 0); - glVertex2i(x + st->cwidth * st->margin_column, ar->winy - 2); - glEnd(); + margin_column_x = x + st->cwidth * (st->margin_column - st->left); + + if (margin_column_x >= x) { + glBegin(GL_LINES); + glVertex2i(margin_column_x, 0); + glVertex2i(margin_column_x, ar->winy - 2); + glEnd(); + } } /* draw other stuff */ @@ -1868,7 +1873,7 @@ void text_update_character_width(SpaceText *st) { text_font_begin(st); st->cwidth = BLF_fixed_width(mono); - st->cwidth = MAX2(st->cwidth, 1); + st->cwidth = MAX2(st->cwidth, (char)1); text_font_end(st); } diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c index b0cd6aeaab4..7dc3ec1ac60 100644 --- a/source/blender/editors/space_text/text_header.c +++ b/source/blender/editors/space_text/text_header.c @@ -59,17 +59,12 @@ #include "WM_types.h" - - - #ifdef WITH_PYTHON // XXX #include "BPY_menus.h" #endif #include "text_intern.h" -#define HEADER_PATH_MAX 260 - /* ************************ header area region *********************** */ /************************** properties ******************************/ diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 5af44f93d06..2d902c4586a 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -44,6 +44,8 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "PIL_time.h" #include "BKE_context.h" @@ -93,7 +95,7 @@ static int text_edit_poll(bContext *C) return 0; if (text->id.lib) { - // BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata"); + // BKE_report(op->reports, RPT_ERROR, "Cannot edit external libdata"); return 0; } @@ -109,7 +111,7 @@ static int text_space_edit_poll(bContext *C) return 0; if (text->id.lib) { - // BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata"); + // BKE_report(op->reports, RPT_ERROR, "Cannot edit external libdata"); return 0; } @@ -129,7 +131,7 @@ static int text_region_edit_poll(bContext *C) return 0; if (text->id.lib) { - // BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata"); + // BKE_report(op->reports, RPT_ERROR, "Cannot edit external libdata"); return 0; } @@ -463,7 +465,8 @@ static void txt_write_file(Text *text, ReportList *reports) fp = BLI_fopen(filepath, "w"); if (fp == NULL) { - BKE_reportf(reports, RPT_ERROR, "Unable to save \"%s\": %s", filepath, errno ? strerror(errno) : "Unknown error writing file"); + BKE_reportf(reports, RPT_ERROR, "Unable to save '%s': %s", + filepath, errno ? strerror(errno) : TIP_("unknown error writing file")); return; } @@ -482,7 +485,8 @@ static void txt_write_file(Text *text, ReportList *reports) } else { text->mtime = 0; - BKE_reportf(reports, RPT_WARNING, "Unable to stat \"%s\": %s", filepath, errno ? strerror(errno) : "Unknown error starrng file"); + BKE_reportf(reports, RPT_WARNING, "Unable to stat '%s': %s", + filepath, errno ? strerror(errno) : TIP_("unknown error stating file")); } if (text->flags & TXT_ISDIRTY) @@ -602,9 +606,12 @@ static int text_run_script(bContext *C, ReportList *reports) /* Don't report error messages while live editing */ if (!is_live) { - if (text->curl != curl_prev || curc_prev != text->curc) { - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + /* text may have freed its self */ + if (CTX_data_edit_text(C) == text) { + if (text->curl != curl_prev || curc_prev != text->curc) { + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + } } BKE_report(reports, RPT_ERROR, "Python script fail, look in the console for now..."); @@ -967,21 +974,17 @@ static int text_unindent_exec(bContext *C, wmOperator *UNUSED(op)) { Text *text = CTX_data_edit_text(C); - if (txt_has_sel(text)) { - text_drawcache_tag_update(CTX_wm_space_text(C), 0); + text_drawcache_tag_update(CTX_wm_space_text(C), 0); - txt_order_cursors(text); - txt_unindent(text); + txt_order_cursors(text); + txt_unindent(text); - text_update_edited(text); + text_update_edited(text); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - return OPERATOR_FINISHED; - } - - return OPERATOR_CANCELLED; + return OPERATOR_FINISHED; } void TEXT_OT_unindent(wmOperatorType *ot) @@ -1945,7 +1948,7 @@ static int text_move_cursor(bContext *C, int type, int select) txt_move_left(text, select); break; - case NEXT_CHAR: + case NEXT_CHAR: txt_move_right(text, select); break; @@ -2409,8 +2412,8 @@ static int text_scroll_bar_invoke(bContext *C, wmOperator *op, wmEvent *event) /* jump scroll, works in v2d but needs to be added here too :S */ if (event->type == MIDDLEMOUSE) { - tsc->old[0] = ar->winrct.xmin + BLI_RCT_CENTER_X(&st->txtbar); - tsc->old[1] = ar->winrct.ymin + BLI_RCT_CENTER_Y(&st->txtbar); + tsc->old[0] = ar->winrct.xmin + BLI_rcti_cent_x(&st->txtbar); + tsc->old[1] = ar->winrct.ymin + BLI_rcti_cent_y(&st->txtbar); tsc->delta[0] = 0; tsc->delta[1] = 0; @@ -2666,7 +2669,7 @@ static void text_cursor_set_apply(bContext *C, wmOperator *op, wmEvent *event) text_update_cursor_moved(C); WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); - } + } else if (!st->wordwrap && (event->mval[0] < 0 || event->mval[0] > ar->winx)) { if (event->mval[0] > ar->winx) st->left++; else if (event->mval[0] < 0 && st->left > 0) st->left--; @@ -2676,7 +2679,7 @@ static void text_cursor_set_apply(bContext *C, wmOperator *op, wmEvent *event) text_update_cursor_moved(C); WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); // XXX PIL_sleep_ms(10); - } + } else { text_cursor_set_to_pos(st, ar, event->mval[0], event->mval[1], 1); @@ -2685,7 +2688,7 @@ static void text_cursor_set_apply(bContext *C, wmOperator *op, wmEvent *event) ssel->old[0] = event->mval[0]; ssel->old[1] = event->mval[1]; - } + } } static void text_cursor_set_exit(bContext *C, wmOperator *op) @@ -3349,7 +3352,7 @@ void TEXT_OT_to_3d_object(wmOperatorType *ot) /* identifiers */ ot->name = "To 3D Object"; ot->idname = "TEXT_OT_to_3d_object"; - ot->description = "Create 3d text object from active text data block"; + ot->description = "Create 3D text object from active text data block"; /* api callbacks */ ot->exec = text_to_3d_object_exec; diff --git a/source/blender/editors/space_text/text_python.c b/source/blender/editors/space_text/text_python.c index f980e19e9c8..966afe22e42 100644 --- a/source/blender/editors/space_text/text_python.c +++ b/source/blender/editors/space_text/text_python.c @@ -180,13 +180,9 @@ static void confirm_suggestion(Text *text, int skipleft) } // XXX -#define L_MOUSE 0 -#define M_MOUSE 0 -#define R_MOUSE 0 #define LR_SHIFTKEY 0 #define LR_ALTKEY 0 #define LR_CTRLKEY 0 -#define LR_OSKEY 0 // XXX static int doc_scroll = 0; diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c index a9315313d26..13c1938d77c 100644 --- a/source/blender/editors/space_time/space_time.c +++ b/source/blender/editors/space_time/space_time.c @@ -401,6 +401,7 @@ static void time_listener(ScrArea *sa, wmNotifier *wmn) case ND_POINTCACHE: case ND_MODIFIER: case ND_PARTICLE: + case ND_KEYS: ED_area_tag_refresh(sa); ED_area_tag_redraw(sa); break; diff --git a/source/blender/editors/space_time/time_ops.c b/source/blender/editors/space_time/time_ops.c index 733fd27135b..9067fb6933f 100644 --- a/source/blender/editors/space_time/time_ops.c +++ b/source/blender/editors/space_time/time_ops.c @@ -151,7 +151,7 @@ static int time_view_all_exec(bContext *C, wmOperator *UNUSED(op)) v2d->cur.xmax = (float)PEFRA; /* we need an extra "buffer" factor on either side so that the endpoints are visible */ - extra = 0.01f * BLI_RCT_SIZE_X(&v2d->cur); + extra = 0.01f * BLI_rctf_size_x(&v2d->cur); v2d->cur.xmin -= extra; v2d->cur.xmax += extra; diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c index 5376b82f24c..1ea3876f5cc 100644 --- a/source/blender/editors/space_userpref/space_userpref.c +++ b/source/blender/editors/space_userpref/space_userpref.c @@ -80,7 +80,7 @@ static SpaceLink *userpref_new(const bContext *UNUSED(C)) /* not spacelink itself */ static void userpref_free(SpaceLink *UNUSED(sl)) { -// SpaceUserPref *spref= (SpaceUserPref*) sl; +// SpaceUserPref *spref = (SpaceUserPref *)sl; } diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index 1bba237ed5c..35dd88c3209 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -51,7 +51,9 @@ set(SRC view3d_edit.c view3d_fly.c view3d_header.c + view3d_iterators.c view3d_ops.c + view3d_project.c view3d_select.c view3d_snap.c view3d_toolbar.c diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c index 5f312ff7fca..0649edc1ac4 100644 --- a/source/blender/editors/space_view3d/drawanimviz.c +++ b/source/blender/editors/space_view3d/drawanimviz.c @@ -84,7 +84,7 @@ void draw_motion_paths_init(View3D *v3d, ARegion *ar) void draw_motion_path_instance(Scene *scene, Object *ob, bPoseChannel *pchan, bAnimVizSettings *avs, bMotionPath *mpath) { - //RegionView3D *rv3d= ar->regiondata; + //RegionView3D *rv3d = ar->regiondata; bMotionPathVert *mpv, *mpv_start; int i, stepsize = avs->path_step; int sfra, efra, sind, len; @@ -107,11 +107,6 @@ void draw_motion_path_instance(Scene *scene, * - abort if whole range is past ends of path * - otherwise clamp endpoints to extents of path */ - if ((sfra > mpath->end_frame) || (efra < mpath->start_frame)) { - /* whole path is out of bounds */ - return; - } - if (sfra < mpath->start_frame) { /* start clamp */ sfra = mpath->start_frame; @@ -121,9 +116,14 @@ void draw_motion_path_instance(Scene *scene, efra = mpath->end_frame; } + if ((sfra > mpath->end_frame) || (efra < mpath->start_frame)) { + /* whole path is out of bounds */ + return; + } + len = efra - sfra; - if (len <= 0) { + if ((len <= 0) || (mpath->points == NULL)) { return; } @@ -148,11 +148,11 @@ void draw_motion_path_instance(Scene *scene, if ((sfra + i) < CFRA) { /* black - before cfra */ if (sel) { - // intensity= 0.5f; + // intensity = 0.5f; intensity = SET_INTENSITY(sfra, i, CFRA, 0.25f, 0.75f); } else { - //intensity= 0.8f; + //intensity = 0.8f; intensity = SET_INTENSITY(sfra, i, CFRA, 0.68f, 0.92f); } UI_ThemeColorBlend(TH_WIRE, TH_BACK, intensity); @@ -178,9 +178,9 @@ void draw_motion_path_instance(Scene *scene, intensity = 0.99f; } UI_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10); - } + } - /* draw a vertex with this color */ + /* draw a vertex with this color */ glVertex3fv(mpv->co); } @@ -230,7 +230,7 @@ void draw_motion_path_instance(Scene *scene, unsigned char col[4]; UI_GetThemeColor3ubv(TH_TEXT_HI, col); col[3] = 255; - + for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize) { char numstr[32]; float co[3]; diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index ecce12b8cba..beafee335d4 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -100,7 +100,7 @@ static void set_pchan_colorset(Object *ob, bPoseChannel *pchan) } /* only try to set custom color if enabled for armature */ - if (arm->flag & ARM_COL_CUSTOM) { + if (arm->flag & ARM_COL_CUSTOM) { /* currently, a bone can only use a custom color set if it's group (if it has one), * has been set to use one */ @@ -647,7 +647,7 @@ static void draw_sphere_bone_dist(float smat[][4], float imat[][4], bPoseChannel /* this routine doesn't call get_matrix_editbone() that calculates it */ ebone->length = len_v3v3(ebone->head, ebone->tail); - /*length= ebone->length;*/ /*UNUSED*/ + /*length = ebone->length;*/ /*UNUSED*/ tail = ebone->rad_tail; dist = ebone->dist; if (ebone->parent && (ebone->flag & BONE_CONNECTED)) @@ -658,7 +658,7 @@ static void draw_sphere_bone_dist(float smat[][4], float imat[][4], bPoseChannel tailvec = ebone->tail; } else { - /*length= pchan->bone->length;*/ /*UNUSED*/ + /*length = pchan->bone->length;*/ /*UNUSED*/ tail = pchan->bone->rad_tail; dist = pchan->bone->dist; if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) @@ -767,7 +767,7 @@ static void draw_sphere_bone_wire(float smat[][4], float imat[][4], /* this routine doesn't call get_matrix_editbone() that calculates it */ ebone->length = len_v3v3(ebone->head, ebone->tail); - /*length= ebone->length;*/ /*UNUSED*/ + /*length = ebone->length;*/ /*UNUSED*/ tail = ebone->rad_tail; if (ebone->parent && (boneflag & BONE_CONNECTED)) head = ebone->parent->rad_tail; @@ -777,7 +777,7 @@ static void draw_sphere_bone_wire(float smat[][4], float imat[][4], tailvec = ebone->tail; } else { - /*length= pchan->bone->length;*/ /*UNUSED*/ + /*length = pchan->bone->length;*/ /*UNUSED*/ tail = pchan->bone->rad_tail; if ((pchan->parent) && (boneflag & BONE_CONNECTED)) head = pchan->parent->bone->rad_tail; @@ -969,7 +969,7 @@ static void draw_sphere_bone(const short dt, int armflag, int boneflag, short co glTranslatef(0.0f, 0.0f, head); gluSphere(qobj, fac1 * head + (1.0f - fac1) * tail, 16, 10); } - else { + else { /* 1 sphere in center */ glTranslatef(0.0f, 0.0f, (head + length - tail) / 2.0f); gluSphere(qobj, fac1 * head + (1.0f - fac1) * tail, 16, 10); @@ -1040,7 +1040,7 @@ static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned glEnd(); /* tip */ - if (G.f & G_PICKSEL) { + if (G.f & G_PICKSEL) { /* no bitmap in selection mode, crashes 3d cards... */ glLoadName(id | BONESEL_TIP); glBegin(GL_POINTS); @@ -1189,7 +1189,7 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl glDisable(GL_COLOR_MATERIAL); glDisable(GL_LIGHTING); } - else { + else { /* wire */ if (armflag & ARM_POSEMODE) { if (constflag) { @@ -1205,9 +1205,9 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl /* restore colors */ set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag); } - } + } - draw_b_bone_boxes(OB_WIRE, pchan, xwidth, length, zwidth); + draw_b_bone_boxes(OB_WIRE, pchan, xwidth, length, zwidth); } } @@ -1333,7 +1333,7 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag else if (armflag & ARM_POSEMODE) { if (constflag) { /* draw constraint colors */ - if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) { + if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) { glEnable(GL_BLEND); draw_bone_solid_octahedral(); @@ -1344,10 +1344,10 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag /* restore colors */ set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag); } - } + } draw_bone_octahedral(); } - else { + else { /* solid */ if (armflag & ARM_POSEMODE) set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag); @@ -1741,7 +1741,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, if (use_custom && pchan->custom_tx) { glMultMatrixf(pchan->custom_tx->pose_mat); - } + } else { glMultMatrixf(pchan->pose_mat); } @@ -1803,7 +1803,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, */ if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) == 0 && (draw_wire == 0)) { /* object tag, for bordersel optim */ - glLoadName(index & 0xFFFF); + glLoadName(index & 0xFFFF); index = -1; } } @@ -1830,7 +1830,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, if (pchan->custom_tx) { glMultMatrixf(pchan->custom_tx->pose_mat); - } + } else { glMultMatrixf(pchan->pose_mat); } @@ -1869,7 +1869,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* stick or wire bones have not been drawn yet so don't clear object selection in this case */ if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) == 0 && draw_wire) { /* object tag, for bordersel optim */ - glLoadName(index & 0xFFFF); + glLoadName(index & 0xFFFF); index = -1; } } @@ -1938,7 +1938,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, glLoadName(index & 0xFFFF); pchan_draw_IK_root_lines(pchan, !(do_dashed & 2)); } - } + } } } @@ -1992,7 +1992,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* restore things */ if (!ELEM(arm->drawtype, ARM_WIRE, ARM_LINE) && (dt > OB_WIRE) && (arm->flag & ARM_POSEMODE)) bglPolygonOffset(rv3d->dist, 0.0); - } + } /* restore */ glDisable(GL_CULL_FACE); @@ -2045,7 +2045,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, if (arm->flag & ARM_DRAWNAMES) { mid_v3_v3v3(vec, pchan->pose_head, pchan->pose_tail); view3d_cached_text_draw_add(vec, pchan->name, 10, 0, col); - } + } /* Draw additional axes on the bone tail */ if ((arm->flag & ARM_DRAWAXES) && (arm->flag & ARM_POSEMODE)) { @@ -2075,7 +2075,7 @@ static void get_matrix_editbone(EditBone *eBone, float bmat[][4]) float mat[3][3]; /* Compose the parent transforms (i.e. their translations) */ - sub_v3_v3v3(delta, eBone->tail, eBone->head); + sub_v3_v3v3(delta, eBone->tail, eBone->head); eBone->length = (float)sqrt(delta[0] * delta[0] + delta[1] * delta[1] + delta[2] * delta[2]); @@ -2226,9 +2226,16 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt) } /* restore */ - if (index != -1) glLoadName(-1); - if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) ; - else if (dt > OB_WIRE) bglPolygonOffset(rv3d->dist, 0.0f); + if (index != -1) { + glLoadName(-1); + } + + if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) { + /* pass */ + } + else if (dt > OB_WIRE) { + bglPolygonOffset(rv3d->dist, 0.0f); + } /* finally names and axes */ if (arm->flag & (ARM_DRAWNAMES | ARM_DRAWAXES)) { @@ -2251,7 +2258,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt) mid_v3_v3v3(vec, eBone->head, eBone->tail); glRasterPos3fv(vec); view3d_cached_text_draw_add(vec, eBone->name, 10, 0, col); - } + } /* Draw additional axes */ if (arm->flag & ARM_DRAWAXES) { glPushMatrix(); @@ -2636,7 +2643,7 @@ int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } draw_pose_paths(scene, v3d, ar, ob); } - } + } } draw_pose_bones(scene, v3d, ar, base, dt, ob_wire_col, (dflag & DRAW_CONSTCOLOR), is_outline); arm->flag &= ~ARM_POSEMODE; diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index ca4f00be2d5..cb5556396dd 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -373,13 +373,7 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O Gtexdraw.ob = ob; Gtexdraw.is_tex = is_tex; - /* OCIO_TODO: for now assume OpenGL is always doing color management and working in sRGB space - * supporting for real display conversion could be nice here, but it's a bit challenging - * since all the shaders should be aware of such a transform - * perhaps this flag could be completely removed before release in separated commit and - * be re-implemented if real display transform would be needed - */ - Gtexdraw.color_profile = TRUE; + Gtexdraw.color_profile = BKE_scene_check_color_management_enabled(scene); memcpy(Gtexdraw.obcol, obcol, sizeof(obcol)); set_draw_settings_cached(1, NULL, NULL, Gtexdraw); @@ -388,7 +382,7 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O glEnable(GL_CULL_FACE); glCullFace(GL_BACK); } - else { + else { glDisable(GL_CULL_FACE); } glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, (me->flag & ME_TWOSIDED) ? GL_TRUE : GL_FALSE); @@ -412,7 +406,7 @@ static void draw_textured_end(void) * - zr */ glPushMatrix(); - glLoadIdentity(); + glLoadIdentity(); GPU_default_lights(); glPopMatrix(); } @@ -539,8 +533,7 @@ static void update_tface_color_layer(DerivedMesh *dm) } else { float col[3]; - Material *ma = give_current_material(Gtexdraw.ob, mface[i].mat_nr + 1); - + if (ma) { if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r); else copy_v3_v3(col, &ma->r); @@ -638,12 +631,12 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl) MLoopCol *mloopcol = me->mloopcol; /* why does mcol exist? */ MLoopCol *lcol; - bProperty *prop = get_ob_property(ob, "Text"); + bProperty *prop = BKE_bproperty_object_get(ob, "Text"); GPUVertexAttribs gattribs; int a, totpoly = me->totpoly; /* fake values to pass to GPU_render_text() */ - MCol tmp_mcol[4] = {{0}}; + MCol tmp_mcol[4] = {{0}}; MCol *tmp_mcol_pt = mloopcol ? tmp_mcol : NULL; MTFace tmp_tf = {{{0}}}; @@ -710,11 +703,11 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl) /* COLOR */ if (mloopcol) { - unsigned int totloop_clamp = MIN2(4, mp->totloop); + unsigned int totloop_clamp = min_ii(4, mp->totloop); unsigned int j; lcol = &mloopcol[mp->loopstart]; - for (j = 0; j <= totloop_clamp; j++, lcol++) { + for (j = 0; j < totloop_clamp; j++, lcol++) { MESH_MLOOPCOL_TO_MCOL(lcol, &tmp_mcol[j]); } } @@ -732,7 +725,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl) /* The BM_FONT handling is in the gpu module, shared with the * game engine, was duplicated previously */ - set_property_valstr(prop, string); + BKE_bproperty_set_valstr(prop, string); characters = strlen(string); if (!BKE_image_get_ibuf(mtpoly->tpage, NULL)) @@ -832,7 +825,7 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d } /* draw game engine text hack */ - if (get_ob_property(ob, "Text")) + if (BKE_bproperty_object_get(ob, "Text")) draw_mesh_text(scene, ob, 0); draw_textured_end(); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index a51ec15bd86..f100f003ff5 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -27,10 +27,6 @@ * \ingroup spview3d */ - -#include -#include - #include "MEM_guardedalloc.h" #include "DNA_camera_types.h" @@ -40,21 +36,14 @@ #include "DNA_lattice_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" #include "DNA_meta_types.h" #include "DNA_scene_types.h" #include "DNA_smoke_types.h" -#include "DNA_speaker_types.h" #include "DNA_world_types.h" -#include "DNA_armature_types.h" #include "DNA_object_types.h" -#include "BLI_utildefines.h" #include "BLI_blenlib.h" #include "BLI_math.h" -#include "BLI_edgehash.h" -#include "BLI_rand.h" -#include "BLI_utildefines.h" #include "BKE_anim.h" /* for the where_on_path function */ #include "BKE_armature.h" @@ -79,13 +68,10 @@ #include "BKE_pointcache.h" #include "BKE_scene.h" #include "BKE_unit.h" -#include "BKE_movieclip.h" #include "BKE_tracking.h" #include "BKE_tessmesh.h" -#include "smoke_API.h" - #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -100,15 +86,13 @@ #include "ED_screen.h" #include "ED_sculpt.h" #include "ED_types.h" -#include "ED_curve.h" /* for curve_editnurbs */ #include "UI_resources.h" #include "WM_api.h" -#include "wm_subwindow.h" #include "BLF_api.h" -#include "view3d_intern.h" /* own include */ +#include "view3d_intern.h" /* bad level include */ typedef enum eWireDrawMode { OBDRAW_WIRE_OFF = 0, @@ -116,28 +100,6 @@ typedef enum eWireDrawMode { OBDRAW_WIRE_ON_DEPTH = 2 } eWireDrawMode; -/* user data structures for derived mesh callbacks */ -typedef struct foreachScreenVert_userData { - void (*func)(void *userData, BMVert *eve, int x, int y, int index); - void *userData; - ViewContext vc; - eV3DClipTest clipVerts; -} foreachScreenVert_userData; - -typedef struct foreachScreenEdge_userData { - void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index); - void *userData; - ViewContext vc; - rcti win_rect; /* copy of: vc.ar->winx/winy, use for faster tests, minx/y will always be 0 */ - eV3DClipTest clipVerts; -} foreachScreenEdge_userData; - -typedef struct foreachScreenFace_userData { - void (*func)(void *userData, BMFace *efa, int x, int y, int index); - void *userData; - ViewContext vc; -} foreachScreenFace_userData; - typedef struct drawDMVerts_userData { BMEditMesh *em; /* BMESH BRANCH ONLY */ @@ -170,7 +132,8 @@ typedef struct drawDMFacesSel_userData { BMEditMesh *em; /* BMESH BRANCH ONLY */ BMFace *efa_act; - int *orig_index; + int *orig_index_mf_to_mpoly; + int *orig_index_mp_to_orig; } drawDMFacesSel_userData; typedef struct drawDMNormal_userData { @@ -239,107 +202,6 @@ static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt) return 1; } -/* ************* only use while object drawing ************** - * or after running ED_view3d_init_mats_rv3d - * */ -static void view3d_project_short_clip(ARegion *ar, const float vec[3], short adr[2], int is_local) -{ - RegionView3D *rv3d = ar->regiondata; - float fx, fy, vec4[4]; - - adr[0] = IS_CLIPPED; - - /* clipplanes in eye space */ - if (rv3d->rflag & RV3D_CLIPPING) { - if (ED_view3d_clipping_test(rv3d, vec, is_local)) - return; - } - - copy_v3_v3(vec4, vec); - vec4[3] = 1.0; - - mul_m4_v4(rv3d->persmatob, vec4); - - /* clipplanes in window space */ - if (vec4[3] > (float)BL_NEAR_CLIP) { /* is the NEAR clipping cutoff for picking */ - fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]); - - if (fx > 0 && fx < ar->winx) { - - fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]); - - if (fy > 0.0f && fy < (float)ar->winy) { - adr[0] = (short)floorf(fx); - adr[1] = (short)floorf(fy); - } - } - } -} - -/* BMESH NOTE: this function is unused in bmesh only */ - -/* only use while object drawing */ -static void UNUSED_FUNCTION(view3d_project_short_noclip) (ARegion * ar, const float vec[3], short adr[2]) -{ - RegionView3D *rv3d = ar->regiondata; - float fx, fy, vec4[4]; - - adr[0] = IS_CLIPPED; - - copy_v3_v3(vec4, vec); - vec4[3] = 1.0; - - mul_m4_v4(rv3d->persmatob, vec4); - - if (vec4[3] > (float)BL_NEAR_CLIP) { /* is the NEAR clipping cutoff for picking */ - fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]); - - if (fx > -32700 && fx < 32700) { - - fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]); - - if (fy > -32700.0f && fy < 32700.0f) { - adr[0] = (short)floorf(fx); - adr[1] = (short)floorf(fy); - } - } - } -} - -/* same as view3d_project_short_clip but use persmat instead of persmatob for projection */ -static void view3d_project_short_clip_persmat(ARegion *ar, const float vec[3], short adr[2], int is_local) -{ - RegionView3D *rv3d = ar->regiondata; - float fx, fy, vec4[4]; - - adr[0] = IS_CLIPPED; - - /* clipplanes in eye space */ - if (rv3d->rflag & RV3D_CLIPPING) { - if (ED_view3d_clipping_test(rv3d, vec, is_local)) - return; - } - - copy_v3_v3(vec4, vec); - vec4[3] = 1.0; - - mul_m4_v4(rv3d->persmat, vec4); - - /* clipplanes in window space */ - if (vec4[3] > (float)BL_NEAR_CLIP) { /* is the NEAR clipping cutoff for picking */ - fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]); - - if (fx > 0 && fx < ar->winx) { - - fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]); - - if (fy > 0.0f && fy < (float)ar->winy) { - adr[0] = (short)floorf(fx); - adr[1] = (short)floorf(fy); - } - } - } -} /* ************************ */ /* check for glsl drawing */ @@ -372,12 +234,13 @@ static int check_alpha_pass(Base *base) } /***/ -static unsigned int colortab[24] = -{0x0, 0xFF88FF, 0xFFBBFF, - 0x403000, 0xFFFF88, 0xFFFFBB, - 0x104040, 0x66CCCC, 0x77CCCC, - 0x104010, 0x55BB55, 0x66FF66, - 0xFFFFFF}; +static unsigned int colortab[24] = { + 0x0, 0xFF88FF, 0xFFBBFF, + 0x403000, 0xFFFF88, 0xFFFFBB, + 0x104040, 0x66CCCC, 0x77CCCC, + 0x104010, 0x55BB55, 0x66FF66, + 0xFFFFFF +}; static float cube[8][3] = { @@ -717,7 +580,7 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char glTranslatef(0.0f, 0.0f, 0.0f); /* Calculate Image scale */ - scale = (ob->empty_drawsize / (float)MAX2(ima_x * sca_x, ima_y * sca_y)); + scale = (ob->empty_drawsize / max_ff((float)ima_x * sca_x, (float)ima_y * sca_y)); /* Set the object scale */ glScalef(scale * sca_x, scale * sca_y, 1.0f); @@ -883,13 +746,17 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, floa if (mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE)) mul_m4_v3(mat, vos->vec); - if (vos->flag & V3D_CACHE_TEXT_GLOBALSPACE) - view3d_project_short_clip_persmat(ar, vos->vec, vos->sco, (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0); - else - view3d_project_short_clip(ar, vos->vec, vos->sco, (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0); - - if (vos->sco[0] != IS_CLIPPED) + if (ED_view3d_project_short_ex(ar, + (vos->flag & V3D_CACHE_TEXT_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob, + (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0, + vos->vec, vos->sco, + V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_OK) + { tot++; + } + else { + vos->sco[0] = IS_CLIPPED; + } } if (tot) { @@ -954,7 +821,9 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, floa if (depth_write) { if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } - else glDepthMask(1); + else { + glDepthMask(1); + } glMatrixMode(GL_PROJECTION); glPopMatrix(); @@ -996,7 +865,7 @@ static void drawcube(void) glEnd(); } -/* draws a cube on given the scaling of the cube, assuming that +/* draws a cube on given the scaling of the cube, assuming that * all required matrices have been set (used for drawing empties) */ static void drawcube_size(float size) @@ -1380,8 +1249,10 @@ static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, glVertex3fv(tvec); glEnd(); } - else circ(0.0, 0.0, fabsf(z)); - + else { + circ(0.0, 0.0, fabsf(z)); + } + /* draw the circle/square representing spotbl */ if (la->type == LA_SPOT) { float spotblcirc = fabs(z) * (1 - pow(la->spotblend, 2)); @@ -1525,7 +1396,7 @@ static void draw_limit_line(float sta, float end, unsigned int col) glVertex3f(0.0, 0.0, -end); glEnd(); glPointSize(1.0); -} +} /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */ @@ -1966,27 +1837,6 @@ static void lattice_draw_verts(Lattice *lt, DispList *dl, short sel) bglEnd(); } -void lattice_foreachScreenVert(ViewContext *vc, void (*func)(void *userData, BPoint *bp, int x, int y), void *userData) -{ - Object *obedit = vc->obedit; - Lattice *lt = obedit->data; - BPoint *bp = lt->editlatt->latt->def; - DispList *dl = BKE_displist_find(&obedit->disp, DL_VERTS); - float *co = dl ? dl->verts : NULL; - int i, N = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; - short s[2] = {IS_CLIPPED, 0}; - - ED_view3d_clipping_local(vc->rv3d, obedit->obmat); /* for local clipping lookups */ - - for (i = 0; i < N; i++, bp++, co += 3) { - if (bp->hide == 0) { - view3d_project_short_clip(vc->ar, dl ? co : bp->vec, s, TRUE); - if (s[0] != IS_CLIPPED) - func(userData, bp, s[0], s[1]); - } - } -} - static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int use_wcol) { int index = ((w * lt->pntsv + v) * lt->pntsu) + u; @@ -2073,56 +1923,6 @@ static void drawlattice(Scene *scene, View3D *v3d, Object *ob) /* ***************** ******************** */ -/* Note! - foreach funcs should be called while drawing or directly after - * if not, ED_view3d_init_mats_rv3d() can be used for selection tools - * but would not give correct results with dupli's for eg. which don't - * use the object matrix in the usual way */ -static void mesh_foreachScreenVert__mapFunc(void *userData, int index, const float co[3], - const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) -{ - foreachScreenVert_userData *data = userData; - BMVert *eve = EDBM_vert_at_index(data->vc.em, index); - - if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { - short s[2] = {IS_CLIPPED, 0}; - - if (data->clipVerts != V3D_CLIP_TEST_OFF) { - view3d_project_short_clip(data->vc.ar, co, s, TRUE); - } - else { - float co2[2]; - mul_v3_m4v3(co2, data->vc.obedit->obmat, co); - project_short_noclip(data->vc.ar, co2, s); - } - - if (s[0] != IS_CLIPPED) - data->func(data->userData, eve, s[0], s[1], index); - } -} - -void mesh_foreachScreenVert( - ViewContext *vc, - void (*func)(void *userData, BMVert *eve, int x, int y, int index), - void *userData, eV3DClipTest clipVerts) -{ - foreachScreenVert_userData data; - DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); - - data.vc = *vc; - data.func = func; - data.userData = userData; - data.clipVerts = clipVerts; - - if (clipVerts != V3D_CLIP_TEST_OFF) - ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */ - - EDBM_index_arrays_init(vc->em, 1, 0, 0); - dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data); - EDBM_index_arrays_free(vc->em); - - dm->release(dm); -} - /* draw callback */ static void drawSelectedVertices__mapFunc(void *userData, int index, const float co[3], const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) @@ -2151,166 +1951,9 @@ static void drawSelectedVertices(DerivedMesh *dm, Mesh *me) glEnd(); } -static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, const float v0co[3], const float v1co[3]) -{ - foreachScreenEdge_userData *data = userData; - BMEdge *eed = EDBM_edge_at_index(data->vc.em, index); - - if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { - short s[2][2]; - - if (data->clipVerts == V3D_CLIP_TEST_RV3D_CLIPPING) { - view3d_project_short_clip(data->vc.ar, v0co, s[0], TRUE); - view3d_project_short_clip(data->vc.ar, v1co, s[1], TRUE); - } - else { - float v1_co[3], v2_co[3]; - - mul_v3_m4v3(v1_co, data->vc.obedit->obmat, v0co); - mul_v3_m4v3(v2_co, data->vc.obedit->obmat, v1co); - - project_short_noclip(data->vc.ar, v1_co, s[0]); - project_short_noclip(data->vc.ar, v2_co, s[1]); - - if (data->clipVerts == V3D_CLIP_TEST_REGION) { - /* make an int copy */ - int s_int[2][2] = {{s[0][0], s[0][1]}, - {s[1][0], s[1][1]}}; - if (!BLI_rcti_isect_segment(&data->win_rect, s_int[0], s_int[1])) { - return; - } - } - } - - data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index); - } -} - -void mesh_foreachScreenEdge( - ViewContext *vc, - void (*func)(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index), - void *userData, eV3DClipTest clipVerts) -{ - foreachScreenEdge_userData data; - DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); - - data.vc = *vc; - - data.win_rect.xmin = 0; - data.win_rect.ymin = 0; - data.win_rect.xmax = vc->ar->winx; - data.win_rect.ymax = vc->ar->winy; - - data.func = func; - data.userData = userData; - data.clipVerts = clipVerts; - - if (clipVerts != V3D_CLIP_TEST_OFF) - ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */ - - EDBM_index_arrays_init(vc->em, 0, 1, 0); - dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data); - EDBM_index_arrays_free(vc->em); - - dm->release(dm); -} - -static void mesh_foreachScreenFace__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3])) -{ - foreachScreenFace_userData *data = userData; - BMFace *efa = EDBM_face_at_index(data->vc.em, index); - - if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - float cent2[3]; - short s[2]; - - mul_v3_m4v3(cent2, data->vc.obedit->obmat, cent); - project_short(data->vc.ar, cent2, s); - - if (s[0] != IS_CLIPPED) { - data->func(data->userData, efa, s[0], s[1], index); - } - } -} - -void mesh_foreachScreenFace( - ViewContext *vc, - void (*func)(void *userData, BMFace *efa, int x, int y, int index), - void *userData) -{ - foreachScreenFace_userData data; - DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); - - data.vc = *vc; - data.func = func; - data.userData = userData; - - //if (clipVerts) - ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */ - - EDBM_index_arrays_init(vc->em, 0, 0, 1); - dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data); - EDBM_index_arrays_free(vc->em); - - dm->release(dm); -} - -void nurbs_foreachScreenVert( - ViewContext *vc, - void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), - void *userData) -{ - Curve *cu = vc->obedit->data; - short s[2] = {IS_CLIPPED, 0}; - Nurb *nu; - int i; - ListBase *nurbs = BKE_curve_editNurbs_get(cu); - - ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */ - - for (nu = nurbs->first; nu; nu = nu->next) { - if (nu->type == CU_BEZIER) { - for (i = 0; i < nu->pntsu; i++) { - BezTriple *bezt = &nu->bezt[i]; - - if (bezt->hide == 0) { - - if (cu->drawflag & CU_HIDE_HANDLES) { - view3d_project_short_clip(vc->ar, bezt->vec[1], s, TRUE); - if (s[0] != IS_CLIPPED) - func(userData, nu, NULL, bezt, 1, s[0], s[1]); - } - else { - view3d_project_short_clip(vc->ar, bezt->vec[0], s, TRUE); - if (s[0] != IS_CLIPPED) - func(userData, nu, NULL, bezt, 0, s[0], s[1]); - view3d_project_short_clip(vc->ar, bezt->vec[1], s, TRUE); - if (s[0] != IS_CLIPPED) - func(userData, nu, NULL, bezt, 1, s[0], s[1]); - view3d_project_short_clip(vc->ar, bezt->vec[2], s, TRUE); - if (s[0] != IS_CLIPPED) - func(userData, nu, NULL, bezt, 2, s[0], s[1]); - } - } - } - } - else { - for (i = 0; i < nu->pntsu * nu->pntsv; i++) { - BPoint *bp = &nu->bp[i]; - - if (bp->hide == 0) { - view3d_project_short_clip(vc->ar, bp->vec, s, TRUE); - if (s[0] != IS_CLIPPED) - func(userData, nu, bp, NULL, -1, s[0], s[1]); - } - } - } - } -} - /* ************** DRAW MESH ****************** */ -/* First section is all the "simple" draw routines, +/* First section is all the "simple" draw routines, * ones that just pass some sort of primitive to GL, * with perhaps various options to control lighting, * color, etc. @@ -2545,7 +2188,7 @@ static DMDrawOption draw_dm_edges_sel__setDrawOptions(void *userData, int index) return DM_DRAW_OPTION_SKIP; } } -static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, +static void draw_dm_edges_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, BMEdge *eed_act) { drawDMEdgesSel_userData data; @@ -2567,7 +2210,7 @@ static DMDrawOption draw_dm_edges__setDrawOptions(void *userData, int index) return DM_DRAW_OPTION_NORMAL; } -static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm) +static void draw_dm_edges(BMEditMesh *em, DerivedMesh *dm) { dm->drawMappedEdges(dm, draw_dm_edges__setDrawOptions, em); } @@ -2669,11 +2312,11 @@ static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int unsigned char *col, *next_col; - if (!data->orig_index) + if (!data->orig_index_mf_to_mpoly) return 0; - efa = EDBM_face_at_index(data->em, data->orig_index[index]); - next_efa = EDBM_face_at_index(data->em, data->orig_index[next_index]); + efa = EDBM_face_at_index(data->em, DM_origindex_mface_mpoly(data->orig_index_mf_to_mpoly, data->orig_index_mp_to_orig, index)); + next_efa = EDBM_face_at_index(data->em, DM_origindex_mface_mpoly(data->orig_index_mf_to_mpoly, data->orig_index_mp_to_orig, next_index)); if (efa == next_efa) return 1; @@ -2691,7 +2334,7 @@ static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int } /* also draws the active face */ -static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, +static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, BMFace *efa_act) { drawDMFacesSel_userData data; @@ -2701,7 +2344,12 @@ static void draw_dm_faces_sel(BMEditMesh *em, DerivedMesh *dm, unsigned char *ba data.cols[1] = selCol; data.cols[2] = actCol; data.efa_act = efa_act; - data.orig_index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX); + /* double lookup */ + data.orig_index_mf_to_mpoly = DM_get_tessface_data_layer(dm, CD_ORIGINDEX); + data.orig_index_mp_to_orig = DM_get_poly_data_layer(dm, CD_ORIGINDEX); + if ((data.orig_index_mf_to_mpoly && data.orig_index_mp_to_orig) == FALSE) { + data.orig_index_mf_to_mpoly = data.orig_index_mp_to_orig = NULL; + } dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions, &data, 0); } @@ -2788,9 +2436,9 @@ static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm) /* EditMesh drawing routines*/ -static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, +static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, BMEditMesh *em, DerivedMesh *cageDM, BMVert *eve_act, - RegionView3D *rv3d) + RegionView3D *rv3d) { ToolSettings *ts = scene->toolsettings; int sel; @@ -2910,7 +2558,7 @@ static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d, glEnable(GL_DEPTH_TEST); } } -} +} static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitSettings *unit) { @@ -3175,7 +2823,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, if (ese->type == BM_FACE) { efa_act = (BMFace *)ese->data; } - else + else #endif if (ese->htype == BM_EDGE) { eed_act = (BMEdge *)ese->ele; @@ -3344,13 +2992,12 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm) { - if ((v3d->transp == FALSE) && /* not when we draw the transparent pass */ (ob->mode & OB_MODE_ALL_PAINT) == FALSE) /* not when painting (its distracting) - campbell */ { glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); glDepthMask(0); - + /* if transparent, we cannot draw the edges for solid select... edges have no material info. * drawFacesSolid() doesn't draw the transparent faces */ if (ob->dtx & OB_DRAWTRANSP) { @@ -3432,7 +3079,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); dm->drawFacesGLSL(dm, GPU_enable_material); -// if (get_ob_property(ob, "Text")) +// if (BKE_bproperty_object_get(ob, "Text")) // XXX draw_mesh_text(ob, 1); GPU_disable_material(); @@ -3620,7 +3267,7 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D } if (obedit && ob != obedit && ob->data == obedit->data) { - if (ob_get_key(ob) || ob_get_key(obedit)) {} + if (BKE_key_from_object(ob) || BKE_key_from_object(obedit)) {} else if (ob->modifiers.first || obedit->modifiers.first) {} else drawlinked = 1; } @@ -3672,7 +3319,7 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D } } - if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0) { + if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { /* GPU_begin_object_materials checked if this is needed */ if (do_alpha_after) { if (ob->dtx & OB_DRAWXRAY) { @@ -3795,7 +3442,7 @@ static int drawDispListwire(ListBase *dlbase) return 0; } -static void drawDispListsolid(ListBase *lb, Object *ob, +static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, const unsigned char ob_wire_col[4], int use_glsl) { DispList *dl; @@ -3826,7 +3473,9 @@ static void drawDispListsolid(ListBase *lb, Object *ob, int nr; glDisable(GL_LIGHTING); - glColor3ubv(ob_wire_col); + + if ((dflag & DRAW_CONSTCOLOR) == 0) + glColor3ubv(ob_wire_col); // glVertexPointer(3, GL_FLOAT, 0, dl->verts); // glDrawArrays(GL_LINE_STRIP, 0, dl->nr); @@ -3953,7 +3602,7 @@ static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, B /* returns 1 when nothing was drawn */ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dt, const unsigned char ob_wire_col[4]) + const short dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; ListBase *lb = NULL; @@ -4001,12 +3650,12 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas else { if (draw_glsl_material(scene, ob, v3d, dt)) { GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL); - drawDispListsolid(lb, ob, ob_wire_col, TRUE); + drawDispListsolid(lb, ob, dflag, ob_wire_col, TRUE); GPU_end_object_materials(); } else { GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL); - drawDispListsolid(lb, ob, ob_wire_col, FALSE); + drawDispListsolid(lb, ob, dflag, ob_wire_col, FALSE); GPU_end_object_materials(); } if (cu->editnurb && cu->bevobj == NULL && cu->taperobj == NULL && cu->ext1 == 0.0f && cu->ext2 == 0.0f) { @@ -4038,12 +3687,12 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas if (draw_glsl_material(scene, ob, v3d, dt)) { GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL); - drawDispListsolid(lb, ob, ob_wire_col, TRUE); + drawDispListsolid(lb, ob, dflag, ob_wire_col, TRUE); GPU_end_object_materials(); } else { GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL); - drawDispListsolid(lb, ob, ob_wire_col, FALSE); + drawDispListsolid(lb, ob, dflag, ob_wire_col, FALSE); GPU_end_object_materials(); } } @@ -4062,12 +3711,12 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas if (draw_glsl_material(scene, ob, v3d, dt)) { GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL); - drawDispListsolid(lb, ob, ob_wire_col, TRUE); + drawDispListsolid(lb, ob, dflag, ob_wire_col, TRUE); GPU_end_object_materials(); } else { GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL); - drawDispListsolid(lb, ob, ob_wire_col, FALSE); + drawDispListsolid(lb, ob, dflag, ob_wire_col, FALSE); GPU_end_object_materials(); } } @@ -4785,7 +4434,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if (cdata2) MEM_freeN(cdata2); - /* cd2= */ /* UNUSED */ cdata2 = NULL; + /* cd2 = */ /* UNUSED */ cdata2 = NULL; glLineWidth(1.0f); @@ -5580,7 +5229,7 @@ static void draw_editnurb(Object *ob, Nurb *nurb, int sel) } static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb, - const short dt, const unsigned char ob_wire_col[4]) + const short dt, const short dflag, const unsigned char ob_wire_col[4]) { ToolSettings *ts = scene->toolsettings; Object *ob = base->object; @@ -5595,7 +5244,7 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, UI_GetThemeColor3ubv(TH_WIRE, wire_col); glColor3ubv(wire_col); - drawDispList(scene, v3d, rv3d, base, dt, ob_wire_col); + drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); if (v3d->zbuf) glDisable(GL_DEPTH_TEST); @@ -5841,7 +5490,7 @@ static void drawspiral(const float cent[3], float rad, float tmat[][4], int star glEnd(); } -/* draws a circle on x-z plane given the scaling of the circle, assuming that +/* draws a circle on x-z plane given the scaling of the circle, assuming that * all required matrices have been set (used for drawing empties) */ static void drawcircle_size(float size) @@ -5851,7 +5500,7 @@ static void drawcircle_size(float size) glBegin(GL_LINE_LOOP); - /* coordinates are: cos(degrees*11.25)=x, sin(degrees*11.25)=y, 0.0f=z */ + /* coordinates are: cos(degrees * 11.25) = x, sin(degrees*11.25) = y, 0.0f = z */ for (degrees = 0; degrees < CIRCLE_RESOL; degrees++) { x = cosval[degrees]; y = sinval[degrees]; @@ -5920,17 +5569,17 @@ static int drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, if (mb->editelems) { if ((G.f & G_PICKSEL) == 0) { - unsigned char wire_col[3]; - UI_GetThemeColor3ubv(TH_WIRE, wire_col); + unsigned char wire_col[4]; + UI_GetThemeColor4ubv(TH_WIRE, wire_col); glColor3ubv(wire_col); - drawDispList(scene, v3d, rv3d, base, dt, wire_col); + drawDispList(scene, v3d, rv3d, base, dt, dflag, wire_col); } ml = mb->editelems->first; } else { if ((base->flag & OB_FROMDUPLI) == 0) { - drawDispList(scene, v3d, rv3d, base, dt, ob_wire_col); + drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); } ml = mb->elems.first; } @@ -6579,7 +6228,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short return; /* xray delay? */ - if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0) { + if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { /* don't do xray in particle mode, need the z-buffer */ if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) { /* xray and transp are set when it is drawing the 2nd/3rd pass */ @@ -6614,7 +6263,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* which wire color */ if ((dflag & DRAW_CONSTCOLOR) == 0) { - project_short(ar, ob->obmat[3], &base->sx); + ED_view3d_project_base(ar, base); draw_object_wire_color(scene, base, _ob_wire_col, warning_recursive); ob_wire_col = _ob_wire_col; @@ -6698,11 +6347,11 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if (cu->flag & CU_FAST) { cpack(0xFFFFFF); set_inverted_drawing(1); - drawDispList(scene, v3d, rv3d, base, OB_WIRE, ob_wire_col); + drawDispList(scene, v3d, rv3d, base, OB_WIRE, dflag, ob_wire_col); set_inverted_drawing(0); } else { - drawDispList(scene, v3d, rv3d, base, dt, ob_wire_col); + drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); } if (cu->linewidth != 0.0f) { @@ -6777,7 +6426,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } } else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) { - empty_object = drawDispList(scene, v3d, rv3d, base, dt, ob_wire_col); + empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); } break; @@ -6787,7 +6436,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if (cu->editnurb) { ListBase *nurbs = BKE_curve_editNurbs_get(cu); - drawnurb(scene, v3d, rv3d, base, nurbs->first, dt, ob_wire_col); + drawnurb(scene, v3d, rv3d, base, nurbs->first, dt, dflag, ob_wire_col); } else if (dt == OB_BOUNDBOX) { if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && (v3d->drawtype >= OB_WIRE)) == 0) { @@ -6795,7 +6444,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } } else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) { - empty_object = drawDispList(scene, v3d, rv3d, base, dt, ob_wire_col); + empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); //XXX old animsys if (cu->path) // curve_draw_speed(scene, ob); @@ -6898,7 +6547,6 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* code for new particle system */ if ((warning_recursive == 0) && (ob->particlesystem.first) && - (dflag & DRAW_PICKING) == 0 && (ob != scene->obedit) ) { @@ -6986,72 +6634,76 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } /* only draw domains */ - if (smd->domain && smd->domain->fluid) { - if (CFRA < smd->domain->point_cache[0]->startframe) { - /* don't show smoke before simulation starts, this could be made an option in the future */ - } - else if (!smd->domain->wt || !(smd->domain->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) { -// #if 0 - smd->domain->tex = NULL; - GPU_create_smoke(smd, 0); - draw_volume(ar, smd->domain->tex, - smd->domain->p0, smd->domain->p1, - smd->domain->res, smd->domain->dx, - smd->domain->tex_shadow); - GPU_free_smoke(smd); -// #endif + if (smd->domain) { + SmokeDomainSettings *sds = smd->domain; + float p0[3], p1[3], viewnormal[3]; + BoundBox bb; + + glLoadMatrixf(rv3d->viewmat); + glMultMatrixf(ob->obmat); + + /* draw adaptive domain bounds */ + if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) { + /* draw domain max bounds */ + VECSUBFAC(p0, sds->p0, sds->cell_size, sds->adapt_res); + VECADDFAC(p1, sds->p1, sds->cell_size, sds->adapt_res); + BKE_boundbox_init_from_minmax(&bb, p0, p1); + draw_box(bb.vec); + + /* draw base resolution bounds */ #if 0 - int x, y, z; - float *density = smoke_get_density(smd->domain->fluid); - - glLoadMatrixf(rv3d->viewmat); - // glMultMatrixf(ob->obmat); - - if (col || (ob->flag & SELECT)) cpack(0xFFFFFF); - glDepthMask(GL_FALSE); - glEnable(GL_BLEND); - - - // glPointSize(3.0); - bglBegin(GL_POINTS); - - for (x = 0; x < smd->domain->res[0]; x++) { - for (y = 0; y < smd->domain->res[1]; y++) { - for (z = 0; z < smd->domain->res[2]; z++) { - float tmp[3]; - int index = smoke_get_index(x, smd->domain->res[0], y, smd->domain->res[1], z); - - if (density[index] > FLT_EPSILON) { - float color[3]; - copy_v3_v3(tmp, smd->domain->p0); - tmp[0] += smd->domain->dx * x + smd->domain->dx * 0.5; - tmp[1] += smd->domain->dx * y + smd->domain->dx * 0.5; - tmp[2] += smd->domain->dx * z + smd->domain->dx * 0.5; - color[0] = color[1] = color[2] = density[index]; - glColor3fv(color); - bglVertex3fv(tmp); - } - } - } - } - - bglEnd(); - glPointSize(1.0); - - glMultMatrixf(ob->obmat); - glDisable(GL_BLEND); - glDepthMask(GL_TRUE); - if (col) cpack(col); + BKE_boundbox_init_from_minmax(&bb, sds->p0, sds->p1); + draw_box(bb.vec); #endif } - else if (smd->domain->wt && (smd->domain->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) { - smd->domain->tex = NULL; - GPU_create_smoke(smd, 1); - draw_volume(ar, smd->domain->tex, - smd->domain->p0, smd->domain->p1, - smd->domain->res_wt, smd->domain->dx_wt, - smd->domain->tex_shadow); - GPU_free_smoke(smd); + + /* don't show smoke before simulation starts, this could be made an option in the future */ + if (smd->domain->fluid && CFRA >= smd->domain->point_cache[0]->startframe) { + + // get view vector + copy_v3_v3(viewnormal, rv3d->viewinv[2]); + mul_mat3_m4_v3(ob->imat, viewnormal); + normalize_v3(viewnormal); + + /* set dynamic boundaries to draw the volume */ + p0[0] = sds->p0[0] + sds->cell_size[0] * sds->res_min[0] + sds->obj_shift_f[0]; + p0[1] = sds->p0[1] + sds->cell_size[1] * sds->res_min[1] + sds->obj_shift_f[1]; + p0[2] = sds->p0[2] + sds->cell_size[2] * sds->res_min[2] + sds->obj_shift_f[2]; + p1[0] = sds->p0[0] + sds->cell_size[0] * sds->res_max[0] + sds->obj_shift_f[0]; + p1[1] = sds->p0[1] + sds->cell_size[1] * sds->res_max[1] + sds->obj_shift_f[1]; + p1[2] = sds->p0[2] + sds->cell_size[2] * sds->res_max[2] + sds->obj_shift_f[2]; + + /* scale cube to global space to equalize volume slicing on all axises + * (its scaled back before drawing) */ + mul_v3_v3(p0, ob->size); + mul_v3_v3(p1, ob->size); + + if (!sds->wt || !(sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) { + smd->domain->tex = NULL; + GPU_create_smoke(smd, 0); + draw_smoke_volume(sds, ob, sds->tex, + p0, p1, + sds->res, sds->dx, sds->scale * sds->maxres, + viewnormal, sds->tex_shadow, sds->tex_flame); + GPU_free_smoke(smd); + } + else if (sds->wt && (sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) { + sds->tex = NULL; + GPU_create_smoke(smd, 1); + draw_smoke_volume(sds, ob, sds->tex, + p0, p1, + sds->res_wt, sds->dx, sds->scale * sds->maxres, + viewnormal, sds->tex_shadow, sds->tex_flame); + GPU_free_smoke(smd); + } + + /* smoke debug render */ +#ifdef SMOKE_DEBUG_VELOCITY + draw_smoke_velocity(smd->domain, ob); +#endif +#ifdef SMOKE_DEBUG_HEAT + draw_smoke_heat(smd->domain, ob); +#endif } } } @@ -7140,7 +6792,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } /* object centers, need to be drawn in viewmat space for speed, but OK for picking select */ - if (!is_obact || !(ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) { + if (!is_obact || !(ob->mode & OB_MODE_ALL_PAINT)) { int do_draw_center = -1; /* defines below are zero or positive... */ if (v3d->flag2 & V3D_RENDER_OVERRIDE) { @@ -7313,7 +6965,7 @@ static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *dm, int offset) dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, ptrs); bglEnd(); glPointSize(1.0); -} +} static DMDrawOption bbs_mesh_wire__setDrawOptions(void *userData, int index) { @@ -7333,7 +6985,7 @@ static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset) { void *ptrs[2] = {(void *)(intptr_t) offset, em}; dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, ptrs); -} +} static DMDrawOption bbs_mesh_solid__setSolidDrawOptions(void *userData, int index) { @@ -7512,7 +7164,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec /* assumes all matrices/etc set OK */ /* helper function for drawing object instances - meshes */ -static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, +static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const short dt, int outline) { Mesh *me = ob->data; diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index 2c2d4039225..ebb48960b80 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -36,6 +36,7 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "DNA_smoke_types.h" #include "DNA_view3d_types.h" #include "BLI_utildefines.h" @@ -132,7 +133,7 @@ static int intersect_edges(float *points, float a, float b, float c, float d, fl int i; float t; int numpoints = 0; - + for (i = 0; i < 12; i++) { t = -(a * edges[i][0][0] + b * edges[i][0][1] + c * edges[i][0][2] + d) / (a * edges[i][1][0] + b * edges[i][1][1] + c * edges[i][1][2]); @@ -156,12 +157,12 @@ static int convex(const float p0[3], const float up[3], const float a[3], const return dot_v3v3(up, tmp) >= 0; } -void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int res[3], float dx, GPUTexture *tex_shadow) +void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, + GPUTexture *tex, float min[3], float max[3], + int res[3], float dx, float UNUSED(base_scale), float viewnormal[3], + GPUTexture *tex_shadow, GPUTexture *tex_flame) { - RegionView3D *rv3d = ar->regiondata; - - float viewnormal[3]; - int i, j, n, good_index; + int i, j, k, n, good_index; float d /*, d0 */ /* UNUSED */, dd, ds; float *points = NULL; int numpoints = 0; @@ -193,25 +194,76 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r {{-1.0f, 1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}} }; + unsigned char *spec_data; + float *spec_pixels; + GPUTexture *tex_spec; + /* Fragment program to calculate the view3d of smoke */ - /* using 2 textures, density and shadow */ - const char *text = "!!ARBfp1.0\n" - "PARAM dx = program.local[0];\n" - "PARAM darkness = program.local[1];\n" - "PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n" - "TEMP temp, shadow, value;\n" - "TEX temp, fragment.texcoord[0], texture[0], 3D;\n" - "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n" - "MUL value, temp, darkness;\n" - "MUL value, value, dx;\n" - "MUL value, value, f;\n" - "EX2 temp, -value.r;\n" - "SUB temp.a, 1.0, temp.r;\n" - "MUL temp.r, temp.r, shadow.r;\n" - "MUL temp.g, temp.g, shadow.r;\n" - "MUL temp.b, temp.b, shadow.r;\n" - "MOV result.color, temp;\n" - "END\n"; + /* using 4 textures, density, shadow, flame and flame spectrum */ + const char *shader_basic = + "!!ARBfp1.0\n" + "PARAM dx = program.local[0];\n" + "PARAM darkness = program.local[1];\n" + "PARAM render = program.local[2];\n" + "PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n" + "TEMP temp, shadow, flame, spec, value;\n" + "TEX temp, fragment.texcoord[0], texture[0], 3D;\n" + "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n" + "TEX flame, fragment.texcoord[0], texture[2], 3D;\n" + "TEX spec, flame.r, texture[3], 1D;\n" + /* calculate shading factor from density */ + "MUL value.r, temp.a, darkness.a;\n" + "MUL value.r, value.r, dx.r;\n" + "MUL value.r, value.r, f.r;\n" + "EX2 temp, -value.r;\n" + /* alpha */ + "SUB temp.a, 1.0, temp.r;\n" + /* shade colors */ + "MUL temp.r, temp.r, shadow.r;\n" + "MUL temp.g, temp.g, shadow.r;\n" + "MUL temp.b, temp.b, shadow.r;\n" + "MUL temp.r, temp.r, darkness.r;\n" + "MUL temp.g, temp.g, darkness.g;\n" + "MUL temp.b, temp.b, darkness.b;\n" + /* for now this just replace smoke shading if rendering fire */ + "CMP result.color, render.r, temp, spec;\n" + "END\n"; + + /* color shader */ + const char *shader_color = + "!!ARBfp1.0\n" + "PARAM dx = program.local[0];\n" + "PARAM darkness = program.local[1];\n" + "PARAM render = program.local[2];\n" + "PARAM f = {1.442695041, 1.442695041, 1.442695041, 1.442695041};\n" + "TEMP temp, shadow, flame, spec, value;\n" + "TEX temp, fragment.texcoord[0], texture[0], 3D;\n" + "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n" + "TEX flame, fragment.texcoord[0], texture[2], 3D;\n" + "TEX spec, flame.r, texture[3], 1D;\n" + /* unpremultiply volume texture */ + "RCP value.r, temp.a;\n" + "MUL temp.r, temp.r, value.r;\n" + "MUL temp.g, temp.g, value.r;\n" + "MUL temp.b, temp.b, value.r;\n" + /* calculate shading factor from density */ + "MUL value.r, temp.a, darkness.a;\n" + "MUL value.r, value.r, dx.r;\n" + "MUL value.r, value.r, f.r;\n" + "EX2 value.r, -value.r;\n" + /* alpha */ + "SUB temp.a, 1.0, value.r;\n" + /* shade colors */ + "MUL temp.r, temp.r, shadow.r;\n" + "MUL temp.g, temp.g, shadow.r;\n" + "MUL temp.b, temp.b, shadow.r;\n" + "MUL temp.r, temp.r, value.r;\n" + "MUL temp.g, temp.g, value.r;\n" + "MUL temp.b, temp.b, value.r;\n" + /* for now this just replace smoke shading if rendering fire */ + "CMP result.color, render.r, temp, spec;\n" + "END\n"; + GLuint prog; @@ -223,6 +275,33 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r } tstart(); + /* generate flame spectrum texture */ + #define SPEC_WIDTH 256 + #define FIRE_THRESH 7 + #define MAX_FIRE_ALPHA 0.06f + #define FULL_ON_FIRE 100 + spec_data = malloc(SPEC_WIDTH * 4 * sizeof(unsigned char)); + flame_get_spectrum(spec_data, SPEC_WIDTH, 1500, 3000); + spec_pixels = malloc(SPEC_WIDTH * 4 * 16 * 16 * sizeof(float)); + for (i = 0; i < 16; i++) { + for (j = 0; j < 16; j++) { + for (k = 0; k < SPEC_WIDTH; k++) { + int index = (j * SPEC_WIDTH * 16 + i * SPEC_WIDTH + k) * 4; + if (k >= FIRE_THRESH) { + spec_pixels[index] = ((float)spec_data[k * 4]) / 255.0f; + spec_pixels[index + 1] = ((float)spec_data[k * 4 + 1]) / 255.0f; + spec_pixels[index + 2] = ((float)spec_data[k * 4 + 2]) / 255.0f; + spec_pixels[index + 3] = MAX_FIRE_ALPHA * ( + (k > FULL_ON_FIRE) ? 1.0f : (k - FIRE_THRESH) / ((float)FULL_ON_FIRE - FIRE_THRESH)); + } + else { + spec_pixels[index] = spec_pixels[index + 1] = spec_pixels[index + 2] = spec_pixels[index + 3] = 0.0f; + } + } + } + } + + tex_spec = GPU_texture_create_1D(SPEC_WIDTH, spec_pixels, NULL); sub_v3_v3v3(size, max, min); @@ -296,32 +375,17 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend); glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth); - glLoadMatrixf(rv3d->viewmat); - // glMultMatrixf(ob->obmat); - glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - -#if 0 - printf("Viewinv:\n"); - printf("%f, %f, %f\n", rv3d->viewinv[0][0], rv3d->viewinv[0][1], rv3d->viewinv[0][2]); - printf("%f, %f, %f\n", rv3d->viewinv[1][0], rv3d->viewinv[1][1], rv3d->viewinv[1][2]); - printf("%f, %f, %f\n", rv3d->viewinv[2][0], rv3d->viewinv[2][1], rv3d->viewinv[2][2]); -#endif - - /* get view vector */ - copy_v3_v3(viewnormal, rv3d->viewinv[2]); - normalize_v3(viewnormal); /* find cube vertex that is closest to the viewer */ for (i = 0; i < 8; i++) { float x, y, z; - x = cv[i][0] - viewnormal[0]*size[0]*0.5f; - y = cv[i][1] - viewnormal[1]*size[1]*0.5f; - z = cv[i][2] - viewnormal[2]*size[2]*0.5f; + x = cv[i][0] - viewnormal[0] * size[0] * 0.5f; + y = cv[i][1] - viewnormal[1] * size[1] * 0.5f; + z = cv[i][2] - viewnormal[2] * size[2] * 0.5f; if ((x >= min[0]) && (x <= max[0]) && (y >= min[1]) && (y <= max[1]) && @@ -344,12 +408,19 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r glGenProgramsARB(1, &prog); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog); - glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(text), text); + /* set shader */ + if (sds->active_fields & SM_ACTIVE_COLORS) + glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_color), shader_color); + else + glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(shader_basic), shader_basic); /* cell spacing */ glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, dx, dx, dx, 1.0); /* custom parameter for smoke style (higher = thicker) */ - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 7.0, 7.0, 7.0, 1.0); + if (sds->active_fields & SM_ACTIVE_COLORS) + glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 1.0, 1.0, 1.0, 10.0); + else + glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, sds->active_color[0], sds->active_color[1], sds->active_color[2], 10.0); } else printf("Your gfx card does not support 3D View smoke drawing.\n"); @@ -360,6 +431,11 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r else printf("No volume shadow\n"); + if (tex_flame) { + GPU_texture_bind(tex_flame, 2); + GPU_texture_bind(tex_spec, 3); + } + if (!GPU_non_power_of_two_support()) { cor[0] = (float)res[0] / (float)power_of_2_max_i(res[0]); cor[1] = (float)res[1] / (float)power_of_2_max_i(res[1]); @@ -373,7 +449,7 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r /* d0 = (viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]); */ /* UNUSED */ ds = (ABS(viewnormal[0]) * size[0] + ABS(viewnormal[1]) * size[1] + ABS(viewnormal[2]) * size[2]); - dd = ds / 96.f; + dd = MAX3(sds->global_size[0], sds->global_size[1], sds->global_size[2]) / 128.f; n = 0; good_index = i; @@ -416,14 +492,29 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r } } - // printf("numpoints: %d\n", numpoints); + /* render fire slice */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, 1.0, 0.0, 0.0, 0.0); glBegin(GL_POLYGON); glColor3f(1.0, 1.0, 1.0); for (i = 0; i < numpoints; i++) { glTexCoord3d((points[i * 3 + 0] - min[0]) * cor[0] / size[0], (points[i * 3 + 1] - min[1]) * cor[1] / size[1], (points[i * 3 + 2] - min[2]) * cor[2] / size[2]); - glVertex3f(points[i * 3 + 0], points[i * 3 + 1], points[i * 3 + 2]); + glVertex3f(points[i * 3 + 0] / ob->size[0], points[i * 3 + 1] / ob->size[1], points[i * 3 + 2] / ob->size[2]); + } + glEnd(); + + /* render smoke slice */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, -1.0, 0.0, 0.0, 0.0); + glBegin(GL_POLYGON); + glColor3f(1.0, 1.0, 1.0); + for (i = 0; i < numpoints; i++) { + glTexCoord3d((points[i * 3 + 0] - min[0]) * cor[0] / size[0], + (points[i * 3 + 1] - min[1]) * cor[1] / size[1], + (points[i * 3 + 2] - min[2]) * cor[2] / size[2]); + glVertex3f(points[i * 3 + 0] / ob->size[0], points[i * 3 + 1] / ob->size[1], points[i * 3 + 2] / ob->size[2]); } glEnd(); } @@ -436,6 +527,14 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r if (tex_shadow) GPU_texture_unbind(tex_shadow); GPU_texture_unbind(tex); + if (tex_flame) { + GPU_texture_unbind(tex_flame); + GPU_texture_unbind(tex_spec); + } + GPU_texture_free(tex_spec); + + free(spec_data); + free(spec_pixels); if (GLEW_ARB_fragment_program) { glDisable(GL_FRAGMENT_PROGRAM_ARB); @@ -451,6 +550,109 @@ void draw_volume(ARegion *ar, GPUTexture *tex, float min[3], float max[3], int r if (gl_depth) { glEnable(GL_DEPTH_TEST); - glDepthMask(GL_TRUE); + glDepthMask(GL_TRUE); } } + +#ifdef SMOKE_DEBUG_VELOCITY +void draw_smoke_velocity(SmokeDomainSettings *domain, Object *ob) +{ + float x, y, z; + float x0, y0, z0; + int *base_res = domain->base_res; + int *res = domain->res; + int *res_min = domain->res_min; + int *res_max = domain->res_max; + float *vel_x = smoke_get_velocity_x(domain->fluid); + float *vel_y = smoke_get_velocity_y(domain->fluid); + float *vel_z = smoke_get_velocity_z(domain->fluid); + + float min[3]; + float *cell_size = domain->cell_size; + float step_size = ((float)MAX3(base_res[0], base_res[1], base_res[2])) / 16.f; + float vf = domain->scale / 16.f * 2.f; /* velocity factor */ + + glLineWidth(1.0f); + + /* set first position so that it doesn't jump when domain moves */ + x0 = res_min[0] + fmod(-(float)domain->shift[0] + res_min[0], step_size); + y0 = res_min[1] + fmod(-(float)domain->shift[1] + res_min[1], step_size); + z0 = res_min[2] + fmod(-(float)domain->shift[2] + res_min[2], step_size); + if (x0 < res_min[0]) x0 += step_size; + if (y0 < res_min[1]) y0 += step_size; + if (z0 < res_min[2]) z0 += step_size; + add_v3_v3v3(min, domain->p0, domain->obj_shift_f); + + for (x = floor(x0); x < res_max[0]; x += step_size) + for (y = floor(y0); y < res_max[1]; y += step_size) + for (z = floor(z0); z < res_max[2]; z += step_size) { + int index = (floor(x) - res_min[0]) + (floor(y) - res_min[1]) * res[0] + (floor(z) - res_min[2]) * res[0] * res[1]; + + float pos[3] = {min[0] + ((float)x + 0.5f) * cell_size[0], min[1] + ((float)y + 0.5f) * cell_size[1], min[2] + ((float)z + 0.5f) * cell_size[2]}; + float vel = sqrtf(vel_x[index] * vel_x[index] + vel_y[index] * vel_y[index] + vel_z[index] * vel_z[index]); + + /* draw heat as scaled "arrows" */ + if (vel >= 0.01f) { + float col_g = 1.0f - vel; + CLAMP(col_g, 0.0f, 1.0f); + glColor3f(1.0f, col_g, 0.0f); + glPointSize(10.0f * vel); + + glBegin(GL_LINES); + glVertex3f(pos[0], pos[1], pos[2]); + glVertex3f(pos[0] + vel_x[index] * vf, pos[1] + vel_y[index] * vf, pos[2] + vel_z[index] * vf); + glEnd(); + glBegin(GL_POINTS); + glVertex3f(pos[0] + vel_x[index] * vf, pos[1] + vel_y[index] * vf, pos[2] + vel_z[index] * vf); + glEnd(); + } + } +} +#endif + +#ifdef SMOKE_DEBUG_HEAT +void draw_smoke_heat(SmokeDomainSettings *domain, Object *ob) +{ + float x, y, z; + float x0, y0, z0; + int *base_res = domain->base_res; + int *res = domain->res; + int *res_min = domain->res_min; + int *res_max = domain->res_max; + float *heat = smoke_get_heat(domain->fluid); + + float min[3]; + float *cell_size = domain->cell_size; + float step_size = ((float)MAX3(base_res[0], base_res[1], base_res[2])) / 16.f; + float vf = domain->scale / 16.f * 2.f; /* velocity factor */ + + /* set first position so that it doesn't jump when domain moves */ + x0 = res_min[0] + fmod(-(float)domain->shift[0] + res_min[0], step_size); + y0 = res_min[1] + fmod(-(float)domain->shift[1] + res_min[1], step_size); + z0 = res_min[2] + fmod(-(float)domain->shift[2] + res_min[2], step_size); + if (x0 < res_min[0]) x0 += step_size; + if (y0 < res_min[1]) y0 += step_size; + if (z0 < res_min[2]) z0 += step_size; + add_v3_v3v3(min, domain->p0, domain->obj_shift_f); + + for (x = floor(x0); x < res_max[0]; x += step_size) + for (y = floor(y0); y < res_max[1]; y += step_size) + for (z = floor(z0); z < res_max[2]; z += step_size) { + int index = (floor(x) - res_min[0]) + (floor(y) - res_min[1]) * res[0] + (floor(z) - res_min[2]) * res[0] * res[1]; + + float pos[3] = {min[0] + ((float)x + 0.5f) * cell_size[0], min[1] + ((float)y + 0.5f) * cell_size[1], min[2] + ((float)z + 0.5f) * cell_size[2]}; + + /* draw heat as different sized points */ + if (heat[index] >= 0.01f) { + float col_gb = 1.0f - heat[index]; + CLAMP(col_gb, 0.0f, 1.0f); + glColor3f(1.0f, col_gb, col_gb); + glPointSize(24.0f * heat[index]); + + glBegin(GL_POINTS); + glVertex3f(pos[0], pos[1], pos[2]); + glEnd(); + } + } +} +#endif diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 1e371cb074d..6818c78bbd6 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -185,7 +185,7 @@ int ED_view3d_context_user_region(bContext *C, View3D **v3d_r, ARegion **ar_r) ar_unlock_user = ar; break; } - } + } } } @@ -719,7 +719,7 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn) case NC_BRUSH: if (wmn->action == NA_EDITED) ED_region_tag_redraw_overlay(ar); - break; + break; case NC_MATERIAL: switch (wmn->data) { case ND_SHADING_DRAW: @@ -748,12 +748,12 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn) break; } break; - case NC_IMAGE: + case NC_IMAGE: /* this could be more fine grained checks if we had * more context than just the region */ ED_region_tag_redraw(ar); break; - case NC_TEXTURE: + case NC_TEXTURE: /* same as above */ ED_region_tag_redraw(ar); break; @@ -776,7 +776,6 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn) break; case NC_SCREEN: switch (wmn->data) { - case ND_GPENCIL: case ND_ANIMPLAY: case ND_SKETCH: ED_region_tag_redraw(ar); @@ -793,6 +792,10 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn) } break; + case NC_GPENCIL: + if (wmn->action == NA_EDITED) + ED_region_tag_redraw(ar); + break; } } @@ -879,7 +882,7 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn) case ND_KEYFRAME: if (wmn->action == NA_EDITED) ED_region_tag_redraw(ar); - break; + break; } break; case NC_SCENE: @@ -941,8 +944,8 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn) if (wmn->action == NA_RENAME) ED_region_tag_redraw(ar); break; - case NC_SCREEN: - if (wmn->data == ND_GPENCIL) + case NC_GPENCIL: + if (wmn->data == ND_DATA) ED_region_tag_redraw(ar); break; } diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index c819637fd04..bf14d915412 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -83,17 +83,18 @@ /* ******************* view3d space & buttons ************** */ -#define B_NOP 1 #define B_REDR 2 #define B_OBJECTPANELMEDIAN 1008 +#define NBR_TRANSFORM_PROPERTIES 7 + /* temporary struct for storing transform properties */ typedef struct { float ob_eul[4]; /* used for quat too... */ float ob_scale[3]; /* need temp space due to linked values */ float ob_dims[3]; short link_scale; - float ve_median[9]; + float ve_median[NBR_TRANSFORM_PROPERTIES]; int curdef; float *defweightp; } TransformProperties; @@ -132,17 +133,38 @@ static float compute_scale_factor(const float ve_median, const float median) /* is used for both read and write... */ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float lim) { +/* Get rid of those ugly magic numbers, even in a single func they become confusing! */ +/* Location, common to all. */ +/* XXX Those two *must* remain contiguous (used as array)! */ +#define LOC_X 0 +#define LOC_Y 1 +#define LOC_Z 2 +/* Meshes... */ +#define M_CREASE 3 +#define M_WEIGHT 4 +/* XXX Those two *must* remain contiguous (used as array)! */ +#define M_SKIN_X 5 +#define M_SKIN_Y 6 +/* Curves... */ +#define C_BWEIGHT 3 +#define C_WEIGHT 4 +#define C_RADIUS 5 +#define C_TILT 6 +/*Lattice... */ +#define L_WEIGHT 4 + uiBlock *block = (layout) ? uiLayoutAbsoluteBlock(layout) : NULL; MDeformVert *dvert = NULL; TransformProperties *tfp; - float median[9], ve_median[9]; - int tot, totw, totweight, totedge, totradius, totskinradius; + float median[NBR_TRANSFORM_PROPERTIES], ve_median[NBR_TRANSFORM_PROPERTIES]; + int tot, totedgedata, totcurvedata, totlattdata, totskinradius, totcurvebweight; + int meshdata = FALSE; char defstr[320]; - PointerRNA radius_ptr; + PointerRNA data_ptr; - median[0] = median[1] = median[2] = median[3] = median[4] = median[5] = median[6] = median[7] = median[8] = 0.0; - tot = totw = totweight = totedge = totradius = totskinradius = 0; - defstr[0] = 0; + fill_vn_fl(median, NBR_TRANSFORM_PROPERTIES, 0.0f); + tot = totedgedata = totcurvedata = totlattdata = totskinradius = totcurvebweight = 0; + defstr[0] = '\0'; /* make sure we got storage */ if (v3d->properties_storage == NULL) @@ -163,11 +185,11 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float evedef = eve; tot++; - add_v3_v3(median, eve->co); + add_v3_v3(&median[LOC_X], eve->co); vs = (MVertSkin *)CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MVERT_SKIN); if (vs) { - add_v2_v2(median + 7, vs->radius); /* Third val not used currently. */ + add_v2_v2(&median[M_SKIN_X], vs->radius); /* Third val not used currently. */ totskinradius++; } } @@ -177,12 +199,12 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { float *f; - totedge++; + totedgedata++; f = (float *)CustomData_bmesh_get(&bm->edata, eed->head.data, CD_CREASE); - median[3] += f ? *f : 0.0f; + median[M_CREASE] += f ? *f : 0.0f; f = (float *)CustomData_bmesh_get(&bm->edata, eed->head.data, CD_BWEIGHT); - median[6] += f ? *f : 0.0f; + median[M_WEIGHT] += f ? *f : 0.0f; } } @@ -212,6 +234,8 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float tfp->defweightp = &dvert->dw[0].weight; } } + + meshdata = totedgedata || totskinradius; } else if (ob->type == OB_CURVE || ob->type == OB_SURF) { Curve *cu = ob->data; @@ -230,22 +254,24 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float a = nu->pntsu; while (a--) { if (bezt->f2 & SELECT) { - add_v3_v3(median, bezt->vec[1]); + add_v3_v3(&median[LOC_X], bezt->vec[1]); tot++; - median[4] += bezt->weight; - totweight++; - median[5] += bezt->radius; - totradius++; - selp = bezt; - seltype = &RNA_BezierSplinePoint; + median[C_WEIGHT] += bezt->weight; + median[C_RADIUS] += bezt->radius; + median[C_TILT] += bezt->alfa; + if (!totcurvedata) { /* I.e. first time... */ + selp = bezt; + seltype = &RNA_BezierSplinePoint; + } + totcurvedata++; } else { if (bezt->f1 & SELECT) { - add_v3_v3(median, bezt->vec[0]); + add_v3_v3(&median[LOC_X], bezt->vec[0]); tot++; } if (bezt->f3 & SELECT) { - add_v3_v3(median, bezt->vec[2]); + add_v3_v3(&median[LOC_X], bezt->vec[2]); tot++; } } @@ -257,16 +283,18 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float a = nu->pntsu * nu->pntsv; while (a--) { if (bp->f1 & SELECT) { - add_v3_v3(median, bp->vec); - median[3] += bp->vec[3]; - totw++; + add_v3_v3(&median[LOC_X], bp->vec); + median[C_BWEIGHT] += bp->vec[3]; + totcurvebweight++; tot++; - median[4] += bp->weight; - totweight++; - median[5] += bp->radius; - totradius++; - selp = bp; - seltype = &RNA_SplinePoint; + median[C_WEIGHT] += bp->weight; + median[C_RADIUS] += bp->radius; + median[C_TILT] += bp->alfa; + if (!totcurvedata) { /* I.e. first time... */ + selp = bp; + seltype = &RNA_SplinePoint; + } + totcurvedata++; } bp++; } @@ -274,84 +302,102 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float nu = nu->next; } - if (totradius == 1) - RNA_pointer_create(&cu->id, seltype, selp, &radius_ptr); + if (totcurvedata == 1) + RNA_pointer_create(&cu->id, seltype, selp, &data_ptr); } else if (ob->type == OB_LATTICE) { Lattice *lt = ob->data; BPoint *bp; int a; + StructRNA *seltype = NULL; + void *selp = NULL; a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; bp = lt->editlatt->latt->def; while (a--) { if (bp->f1 & SELECT) { - add_v3_v3(median, bp->vec); + add_v3_v3(&median[LOC_X], bp->vec); tot++; - median[4] += bp->weight; - totweight++; + median[L_WEIGHT] += bp->weight; + if (!totlattdata) { /* I.e. first time... */ + selp = bp; + seltype = &RNA_LatticePoint; + } + totlattdata++; } bp++; } + + if (totlattdata == 1) + RNA_pointer_create(<->id, seltype, selp, &data_ptr); } if (tot == 0) { uiDefBut(block, LABEL, 0, IFACE_("Nothing selected"), 0, 130, 200, 20, NULL, 0, 0, 0, 0, ""); return; } - median[0] /= (float)tot; - median[1] /= (float)tot; - median[2] /= (float)tot; - if (totedge) { - median[3] /= (float)totedge; - median[6] /= (float)totedge; - } - else if (totw) - median[3] /= (float)totw; - if (totweight) - median[4] /= (float)totweight; - if (totradius) - median[5] /= (float)totradius; - if (totskinradius) { - median[7] /= (float)totskinradius; - median[8] /= (float)totskinradius; - } + /* Location, X/Y/Z */ + mul_v3_fl(&median[LOC_X], 1.0f / (float)tot); if (v3d->flag & V3D_GLOBAL_STATS) - mul_m4_v3(ob->obmat, median); + mul_m4_v3(ob->obmat, &median[LOC_X]); + + if (meshdata) { + if (totedgedata) { + median[M_CREASE] /= (float)totedgedata; + median[M_WEIGHT] /= (float)totedgedata; + } + if (totskinradius) { + median[M_SKIN_X] /= (float)totskinradius; + median[M_SKIN_Y] /= (float)totskinradius; + } + } + else if (totcurvedata) { + median[C_WEIGHT] /= (float)totcurvedata; + median[C_RADIUS] /= (float)totcurvedata; + median[C_TILT] /= (float)totcurvedata; + if (totcurvebweight) + median[C_BWEIGHT] /= (float)totcurvebweight; + } + else if (totlattdata) + median[L_WEIGHT] /= (float)totlattdata; if (block) { /* buttons */ uiBut *but; int yi = 200; const int buth = 20 * UI_DPI_ICON_FAC; const int but_margin = 2; + const char *c; memcpy(tfp->ve_median, median, sizeof(tfp->ve_median)); uiBlockBeginAlign(block); if (tot == 1) { - uiDefBut(block, LABEL, 0, IFACE_("Vertex:"), 0, yi -= buth, 200, buth, NULL, 0, 0, 0, 0, ""); - } - else { - uiDefBut(block, LABEL, 0, IFACE_("Median:"), 0, yi -= buth, 200, buth, NULL, 0, 0, 0, 0, ""); + if (totcurvedata) /* Curve */ + c = IFACE_("Control Point:"); + else /* Mesh or lattice */ + c = IFACE_("Vertex:"); } + else + c = IFACE_("Median:"); + uiDefBut(block, LABEL, 0, c, 0, yi -= buth, 200, buth, NULL, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); /* Should be no need to translate these. */ but = uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "X:", 0, yi -= buth, 200, buth, - &(tfp->ve_median[0]), -lim, lim, 10, RNA_TRANSLATION_PREC_DEFAULT, ""); + &(tfp->ve_median[LOC_X]), -lim, lim, 10, RNA_TRANSLATION_PREC_DEFAULT, ""); uiButSetUnitType(but, PROP_UNIT_LENGTH); but = uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Y:", 0, yi -= buth, 200, buth, - &(tfp->ve_median[1]), -lim, lim, 10, RNA_TRANSLATION_PREC_DEFAULT, ""); + &(tfp->ve_median[LOC_Y]), -lim, lim, 10, RNA_TRANSLATION_PREC_DEFAULT, ""); uiButSetUnitType(but, PROP_UNIT_LENGTH); but = uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Z:", 0, yi -= buth, 200, buth, - &(tfp->ve_median[2]), -lim, lim, 10, RNA_TRANSLATION_PREC_DEFAULT, ""); + &(tfp->ve_median[LOC_Z]), -lim, lim, 10, RNA_TRANSLATION_PREC_DEFAULT, ""); uiButSetUnitType(but, PROP_UNIT_LENGTH); - if (totw == tot) { + if (totcurvebweight == tot) { uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "W:", 0, yi -= buth, 200, buth, - &(tfp->ve_median[3]), 0.01, 100.0, 1, 3, ""); + &(tfp->ve_median[C_BWEIGHT]), 0.01, 100.0, 1, 3, ""); } uiBlockBeginAlign(block); @@ -363,60 +409,60 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float &v3d->flag, 0, 0, 0, 0, "Displays local values"); uiBlockEndAlign(block); - if (totweight == 1) { - uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Weight:"), - 0, yi -= buth + but_margin, 200, buth, - &(tfp->ve_median[4]), 0.0, 1.0, 1, 3, TIP_("Weight used for SoftBody Goal")); + /* Meshes... */ + if (meshdata) { + if (totedgedata) { + uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, + totedgedata == 1 ? IFACE_("Crease:") : IFACE_("Mean Crease:"), + 0, yi -= buth + but_margin, 200, buth, + &(tfp->ve_median[M_CREASE]), 0.0, 1.0, 1, 3, TIP_("Weight used by SubSurf modifier")); + uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, + totedgedata == 1 ? IFACE_("Bevel Weight:") : IFACE_("Mean Bevel Weight:"), + 0, yi -= buth + but_margin, 200, buth, + &(tfp->ve_median[M_WEIGHT]), 0.0, 1.0, 1, 3, TIP_("Weight used by Bevel modifier")); + } + if (totskinradius) { + uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, + totskinradius == 1 ? IFACE_("Radius X:") : IFACE_("Mean Radius X:"), + 0, yi -= buth + but_margin, 200, buth, + &(tfp->ve_median[M_SKIN_X]), 0.0, 100.0, 1, 3, TIP_("X radius used by Skin modifier")); + uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, + totskinradius == 1 ? IFACE_("Radius Y:") : IFACE_("Mean Radius Y:"), + 0, yi -= buth + but_margin, 200, buth, + &(tfp->ve_median[M_SKIN_Y]), 0.0, 100.0, 1, 3, TIP_("Y radius used by Skin modifier")); + } } - else if (totweight > 1) { + /* Curve... */ + else if (totcurvedata == 1) { + uiDefButR(block, NUM, 0, "Weight", 0, yi -= buth + but_margin, 200, buth, + &data_ptr, "weight_softbody", 0, 0.0, 1.0, 1, 3, NULL); + uiDefButR(block, NUM, 0, "Radius", 0, yi -= buth + but_margin, 200, buth, + &data_ptr, "radius", 0, 0.0, 100.0, 1, 3, NULL); + uiDefButR(block, NUM, 0, "Tilt", 0, yi -= buth + but_margin, 200, buth, + &data_ptr, "tilt", 0, -M_PI * 2.0, M_PI * 2.0, 1, 3, NULL); + } + else if (totcurvedata > 1) { uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Weight:"), - 0, yi -= buth, 200, buth, - &(tfp->ve_median[4]), 0.0, 1.0, 1, 3, TIP_("Weight used for SoftBody Goal")); - } - - if (totradius == 1) { - uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Radius:"), 0, yi -= buth + but_margin, 200, buth, - &(tfp->ve_median[5]), 0.0, 100.0, 1, 3, TIP_("Radius of curve control points")); - } - else if (totradius > 1) { + &(tfp->ve_median[C_WEIGHT]), 0.0, 1.0, 1, 3, TIP_("Weight used for SoftBody Goal")); uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Radius:"), 0, yi -= buth + but_margin, 200, buth, - &(tfp->ve_median[5]), 0.0, 100.0, 1, 3, TIP_("Radius of curve control points")); + &(tfp->ve_median[C_RADIUS]), 0.0, 100.0, 1, 3, TIP_("Radius of curve control points")); + but = uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Tilt:"), + 0, yi -= buth + but_margin, 200, buth, + &(tfp->ve_median[C_TILT]), -M_PI * 2.0, M_PI * 2.0, 1, 3, + TIP_("Tilt of curve control points")); + uiButSetUnitType(but, PROP_UNIT_ROTATION); } - - if (totskinradius == 1) { - uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Radius X:"), - 0, yi -= buth + but_margin, 200, buth, - &(tfp->ve_median[7]), 0.0, 100.0, 1, 3, TIP_("X radius used by Skin modifier")); - uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Radius Y:"), - 0, yi -= buth + but_margin, 200, buth, - &(tfp->ve_median[8]), 0.0, 100.0, 1, 3, TIP_("Y radius used by Skin modifier")); + /* Lattice... */ + else if (totlattdata == 1) { + uiDefButR(block, NUM, 0, "Weight", 0, yi -= buth + but_margin, 200, buth, + &data_ptr, "weight_softbody", 0, 0.0, 1.0, 1, 3, NULL); } - else if (totskinradius > 1) { - uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Radius X:"), + else if (totlattdata > 1) { + uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Weight:"), 0, yi -= buth + but_margin, 200, buth, - &(tfp->ve_median[7]), 0.0, 100.0, 1, 3, TIP_("Median X radius used by Skin modifier")); - uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Radius Y:"), - 0, yi -= buth + but_margin, 200, buth, - &(tfp->ve_median[8]), 0.0, 100.0, 1, 3, TIP_("Median Y radius used by Skin modifier")); - } - - if (totedge == 1) { - uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Crease:"), - 0, yi -= buth + but_margin, 200, buth, - &(tfp->ve_median[3]), 0.0, 1.0, 1, 3, TIP_("Weight used by SubSurf modifier")); - uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Bevel Weight:"), - 0, yi -= buth + but_margin, 200, buth, - &(tfp->ve_median[6]), 0.0, 1.0, 1, 3, TIP_("Weight used by Bevel modifier")); - } - else if (totedge > 1) { - uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Crease:"), - 0, yi -= buth + but_margin, 200, buth, - &(tfp->ve_median[3]), 0.0, 1.0, 1, 3, TIP_("Weight used by SubSurf modifier")); - uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, IFACE_("Mean Bevel Weight:"), - 0, yi -= buth + but_margin, 200, buth, - &(tfp->ve_median[6]), 0.0, 1.0, 1, 3, TIP_("Weight used by Bevel modifier")); + &(tfp->ve_median[L_WEIGHT]), 0.0, 1.0, 1, 3, TIP_("Weight used for SoftBody Goal")); } uiBlockEndAlign(block); @@ -424,42 +470,40 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } else { /* apply */ + int i; + memcpy(ve_median, tfp->ve_median, sizeof(tfp->ve_median)); if (v3d->flag & V3D_GLOBAL_STATS) { invert_m4_m4(ob->imat, ob->obmat); - mul_m4_v3(ob->imat, median); - mul_m4_v3(ob->imat, ve_median); + mul_m4_v3(ob->imat, &median[LOC_X]); + mul_m4_v3(ob->imat, &ve_median[LOC_X]); } - sub_v3_v3v3(median, ve_median, median); - median[3] = ve_median[3] - median[3]; - median[4] = ve_median[4] - median[4]; - median[5] = ve_median[5] - median[5]; - median[6] = ve_median[6] - median[6]; - median[7] = ve_median[7] - median[7]; - median[8] = ve_median[8] - median[8]; + i = NBR_TRANSFORM_PROPERTIES; + while (i--) + median[i] = ve_median[i] - median[i]; if (ob->type == OB_MESH) { Mesh *me = ob->data; BMEditMesh *em = me->edit_btmesh; BMesh *bm = em->bm; - BMVert *eve; BMIter iter; - if (len_v3(median) > 0.000001f) { + if (len_v3(&median[LOC_X]) > 0.000001f) { + BMVert *eve; BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { - add_v3_v3(eve->co, median); + add_v3_v3(eve->co, &median[LOC_X]); } } EDBM_mesh_normals_update(em); } - if (median[3] != 0.0f) { + if (median[M_CREASE] != 0.0f) { BMEdge *eed; - const float sca = compute_scale_factor(ve_median[3], median[3]); + const float sca = compute_scale_factor(ve_median[M_CREASE], median[M_CREASE]); if (ELEM(sca, 0.0f, 1.0f)) { BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { @@ -495,9 +539,9 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } } - if (median[6] != 0.0f) { + if (median[M_WEIGHT] != 0.0f) { BMEdge *eed; - const float sca = compute_scale_factor(ve_median[6], median[6]); + const float sca = compute_scale_factor(ve_median[M_WEIGHT], median[M_WEIGHT]); if (ELEM(sca, 0.0f, 1.0f)) { BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { @@ -533,11 +577,11 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } } - if (median[7] != 0.0f) { + if (median[M_SKIN_X] != 0.0f) { BMVert *eve; /* That one is not clamped to [0.0, 1.0]. */ - float sca = ve_median[7]; - if (ve_median[7] - median[7] == 0.0f) { + float sca = ve_median[M_SKIN_X]; + if (ve_median[M_SKIN_X] - median[M_SKIN_X] == 0.0f) { BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { MVertSkin *vs = (MVertSkin *)CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MVERT_SKIN); @@ -547,7 +591,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } } else { - sca /= (ve_median[7] - median[7]); + sca /= (ve_median[M_SKIN_X] - median[M_SKIN_X]); BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { MVertSkin *vs = (MVertSkin *)CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MVERT_SKIN); @@ -557,11 +601,11 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } } } - if (median[8] != 0.0f) { + if (median[M_SKIN_Y] != 0.0f) { BMVert *eve; /* That one is not clamped to [0.0, 1.0]. */ - float sca = ve_median[8]; - if (ve_median[8] - median[8] == 0.0f) { + float sca = ve_median[M_SKIN_Y]; + if (ve_median[M_SKIN_Y] - median[M_SKIN_Y] == 0.0f) { BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { MVertSkin *vs = (MVertSkin *)CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MVERT_SKIN); @@ -571,7 +615,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } } else { - sca /= (ve_median[8] - median[8]); + sca /= (ve_median[M_SKIN_Y] - median[M_SKIN_Y]); BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { MVertSkin *vs = (MVertSkin *)CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_MVERT_SKIN); @@ -590,7 +634,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float BezTriple *bezt; int a; ListBase *nurbs = BKE_curve_editNurbs_get(cu); - const float scale_w = compute_scale_factor(ve_median[4], median[4]); + const float scale_w = compute_scale_factor(ve_median[C_WEIGHT], median[C_WEIGHT]); nu = nurbs->first; while (nu) { @@ -599,11 +643,11 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float a = nu->pntsu; while (a--) { if (bezt->f2 & SELECT) { - add_v3_v3(bezt->vec[0], median); - add_v3_v3(bezt->vec[1], median); - add_v3_v3(bezt->vec[2], median); + add_v3_v3(bezt->vec[0], &median[LOC_X]); + add_v3_v3(bezt->vec[1], &median[LOC_X]); + add_v3_v3(bezt->vec[2], &median[LOC_X]); - if (median[4] != 0.0f) { + if (median[C_WEIGHT] != 0.0f) { if (ELEM(scale_w, 0.0f, 1.0f)) { bezt->weight = scale_w; } @@ -614,14 +658,15 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } } - bezt->radius += median[5]; + bezt->radius += median[C_RADIUS]; + bezt->alfa += median[C_TILT]; } else { if (bezt->f1 & SELECT) { - add_v3_v3(bezt->vec[0], median); + add_v3_v3(bezt->vec[0], &median[LOC_X]); } if (bezt->f3 & SELECT) { - add_v3_v3(bezt->vec[2], median); + add_v3_v3(bezt->vec[2], &median[LOC_X]); } } bezt++; @@ -632,10 +677,10 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float a = nu->pntsu * nu->pntsv; while (a--) { if (bp->f1 & SELECT) { - add_v3_v3(bp->vec, median); - bp->vec[3] += median[3]; + add_v3_v3(bp->vec, &median[LOC_X]); + bp->vec[3] += median[C_BWEIGHT]; - if (median[4] != 0.0f) { + if (median[C_WEIGHT] != 0.0f) { if (ELEM(scale_w, 0.0f, 1.0f)) { bp->weight = scale_w; } @@ -646,7 +691,8 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } } - bp->radius += median[5]; + bp->radius += median[C_RADIUS]; + bp->alfa += median[C_TILT]; } bp++; } @@ -661,15 +707,15 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float Lattice *lt = ob->data; BPoint *bp; int a; - const float scale_w = compute_scale_factor(ve_median[4], median[4]); + const float scale_w = compute_scale_factor(ve_median[L_WEIGHT], median[L_WEIGHT]); a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; bp = lt->editlatt->latt->def; while (a--) { if (bp->f1 & SELECT) { - add_v3_v3(bp->vec, median); + add_v3_v3(bp->vec, &median[LOC_X]); - if (median[4] != 0.0f) { + if (median[L_WEIGHT] != 0.0f) { if (ELEM(scale_w, 0.0f, 1.0f)) { bp->weight = scale_w; } @@ -686,7 +732,28 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float /* ED_undo_push(C, "Transform properties"); */ } + +/* Clean up! */ +/* Location, common to all. */ +#undef LOC_X +#undef LOC_Y +#undef LOC_Z +/* Meshes (and lattice)... */ +#undef M_CREASE +#undef M_WEIGHT +#undef M_SKIN_X +#undef M_SKIN_Y +/* Curves... */ +#undef C_BWEIGHT +#undef C_WEIGHT +#undef C_RADIUS +#undef C_TILT +/* Lattice... */ +#undef L_WEIGHT } +#undef NBR_TRANSFORM_PROPERTIES + + #define B_VGRP_PNL_COPY 1 #define B_VGRP_PNL_NORMALIZE 2 #define B_VGRP_PNL_EDIT_SINGLE 8 /* or greater */ @@ -1156,13 +1223,12 @@ static void view3d_panel_object(const bContext *C, Panel *pa) if (ob == NULL) return; - lim = 10000.0f * MAX2(1.0f, v3d->grid); + lim = 10000.0f * max_ff(1.0f, v3d->grid); block = uiLayoutGetBlock(pa->layout); uiBlockSetHandleFunc(block, do_view3d_region_buttons, NULL); col = uiLayoutColumn(pa->layout, FALSE); - /* row = uiLayoutRow(col, FALSE); */ /* UNUSED */ RNA_id_pointer_create(&ob->id, &obptr); if (ob == obedit) { diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 5fbf1971349..4d4fad47698 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -243,7 +243,7 @@ static void drawgrid_draw(ARegion *ar, double wx, double wy, double x, double y, verts[1][1] = (double)ar->winy; /* iter over 'X' */ - verts[0][0] = verts[1][0] = x - dx *floor(x / dx); + verts[0][0] = verts[1][0] = x - dx * floor(x / dx); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_DOUBLE, 0, verts); @@ -257,7 +257,7 @@ static void drawgrid_draw(ARegion *ar, double wx, double wy, double x, double y, verts[1][0] = (double)ar->winx; /* iter over 'Y' */ - verts[0][1] = verts[1][1] = y - dx *floor(y / dx); + verts[0][1] = verts[1][1] = y - dx * floor(y / dx); while (verts[0][1] < ar->winy) { glDrawArrays(GL_LINES, 0, 2); verts[0][1] = verts[1][1] = verts[0][1] + dx; @@ -355,7 +355,9 @@ static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char ** if (dx < GRID_MIN_PX_D) { rv3d->gridview *= sublines; dx *= sublines; - if (dx < GRID_MIN_PX_D) ; + if (dx < GRID_MIN_PX_D) { + /* pass */ + } else { UI_ThemeColor(TH_GRID); drawgrid_draw(ar, wx, wy, x, y, dx); @@ -521,7 +523,7 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit) GPU_print_error("sdsd"); } - /* draw the Z axis line */ + /* draw the Z axis line */ /* check for the 'show Z axis' preference */ if (v3d->gridflag & (V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) { int axis; @@ -553,32 +555,23 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit) static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d) { - int mx, my, co[2]; - int flag; - + int co[2]; + /* we don't want the clipping for cursor */ - flag = v3d->flag; - v3d->flag = 0; - project_int(ar, give_cursor(scene, v3d), co); - v3d->flag = flag; - - mx = co[0]; - my = co[1]; - - if (mx != IS_CLIPPED) { + if (ED_view3d_project_int_global(ar, give_cursor(scene, v3d), co, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { setlinestyle(0); cpack(0xFF); - circ((float)mx, (float)my, 10.0); + circ((float)co[0], (float)co[1], 10.0); setlinestyle(4); cpack(0xFFFFFF); - circ((float)mx, (float)my, 10.0); + circ((float)co[0], (float)co[1], 10.0); setlinestyle(0); cpack(0x0); - sdrawline(mx - 20, my, mx - 5, my); - sdrawline(mx + 5, my, mx + 20, my); - sdrawline(mx, my - 20, mx, my - 5); - sdrawline(mx, my + 5, mx, my + 20); + sdrawline(co[0] - 20, co[1], co[0] - 5, co[1]); + sdrawline(co[0] + 5, co[1], co[0] + 20, co[1]); + sdrawline(co[0], co[1] - 20, co[0], co[1] - 5); + sdrawline(co[0], co[1] + 5, co[0], co[1] + 20); } } @@ -730,7 +723,7 @@ static void draw_rotation_guide(RegionView3D *rv3d) glColor4fv(color); glBegin(GL_LINE_LOOP); for (i = 0, angle = 0.f; i < ROT_AXIS_DETAIL; ++i, angle += step) { - float p[3] = {s *cosf(angle), s * sinf(angle), 0.0f}; + float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f}; if (!upright) { mul_qt_v3(q, p); @@ -901,7 +894,7 @@ static void draw_selected_name(Scene *scene, Object *ob) /* try to display active shapekey too */ shapes[0] = '\0'; - key = ob_get_key(ob); + key = BKE_key_from_object(ob); if (key) { kb = BLI_findlink(&key->block, ob->shapenr - 1); if (kb) { @@ -973,10 +966,10 @@ static void view3d_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionV rect_camera = params.viewplane; /* get camera border within viewport */ - viewborder_r->xmin = ((rect_camera.xmin - rect_view.xmin) / BLI_RCT_SIZE_X(&rect_view)) * ar->winx; - viewborder_r->xmax = ((rect_camera.xmax - rect_view.xmin) / BLI_RCT_SIZE_X(&rect_view)) * ar->winx; - viewborder_r->ymin = ((rect_camera.ymin - rect_view.ymin) / BLI_RCT_SIZE_Y(&rect_view)) * ar->winy; - viewborder_r->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_RCT_SIZE_Y(&rect_view)) * ar->winy; + viewborder_r->xmin = ((rect_camera.xmin - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx; + viewborder_r->xmax = ((rect_camera.xmax - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx; + viewborder_r->ymin = ((rect_camera.ymin - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy; + viewborder_r->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy; } void ED_view3d_calc_camera_border_size(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, float size_r[2]) @@ -984,8 +977,8 @@ void ED_view3d_calc_camera_border_size(Scene *scene, ARegion *ar, View3D *v3d, R rctf viewborder; view3d_camera_border(scene, ar, v3d, rv3d, &viewborder, TRUE, TRUE); - size_r[0] = BLI_RCT_SIZE_X(&viewborder); - size_r[1] = BLI_RCT_SIZE_Y(&viewborder); + size_r[0] = BLI_rctf_size_x(&viewborder); + size_r[1] = BLI_rctf_size_y(&viewborder); } void ED_view3d_calc_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, @@ -1067,7 +1060,7 @@ static void drawviewborder_triangle(float x1, float x2, float y1, float y2, cons static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) { - float fac, a; + float hmargin, vmargin; float x1, x2, y1, y2; float x1i, x2i, y1i, y2i; float x3, y3, x4, y4; @@ -1122,7 +1115,7 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) } /* edge */ - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); setlinestyle(0); @@ -1221,20 +1214,15 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) } if (ca->flag & CAM_SHOWTITLESAFE) { - fac = 0.1; - - a = fac * (x2 - x1); - x1 += a; - x2 -= a; - - a = fac * (y2 - y1); - y1 += a; - y2 -= a; - UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 0.25, 0); - uiSetRoundBox(UI_CNR_ALL); - uiDrawBox(GL_LINE_LOOP, x1, y1, x2, y2, 12.0); + hmargin = 0.1f * (x2 - x1); + vmargin = 0.05f * (y2 - y1); + uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1+vmargin, x2 - hmargin, y2 - vmargin, 2.0f); + + hmargin = 0.035f * (x2 - x1); + vmargin = 0.035f * (y2 - y1); + uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1+vmargin, x2 - hmargin, y2 - vmargin, 2.0f); } if (ca && (ca->flag & CAM_SHOWSENSOR)) { /* determine sensor fit, and get sensor x/y, for auto fit we @@ -1341,7 +1329,7 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d) glDisable(GL_MULTISAMPLE_ARB); region_scissor_winrct(ar, &winrct); - glScissor(winrct.xmin, winrct.ymin, BLI_RCT_SIZE_X(&winrct), BLI_RCT_SIZE_Y(&winrct)); + glScissor(winrct.xmin, winrct.ymin, BLI_rcti_size_x(&winrct), BLI_rcti_size_y(&winrct)); glClearColor(0.0, 0.0, 0.0, 0.0); if (v3d->zbuf) { @@ -1436,7 +1424,7 @@ ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, (ymaxc - yminc + 1), GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); - glReadBuffer(GL_BACK); + glReadBuffer(GL_BACK); if (ENDIAN_ORDER == B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf); @@ -1469,7 +1457,7 @@ ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, /* smart function to sample a rect spiralling outside, nice for backbuf selection */ unsigned int view3d_sample_backbuf_rect(ViewContext *vc, const int mval[2], int size, - unsigned int min, unsigned int max, int *dist, short strict, + unsigned int min, unsigned int max, float *r_dist, short strict, void *handle, unsigned int (*indextest)(void *handle, unsigned int index)) { struct ImBuf *buf; @@ -1478,7 +1466,7 @@ unsigned int view3d_sample_backbuf_rect(ViewContext *vc, const int mval[2], int int a, b, rc, nr, amount, dirvec[4][2]; int distance = 0; unsigned int index = 0; - short indexok = 0; + short indexok = 0; amount = (size - 1) / 2; @@ -1507,13 +1495,13 @@ unsigned int view3d_sample_backbuf_rect(ViewContext *vc, const int mval[2], int if (strict) { indexok = indextest(handle, *tbuf - min + 1); if (indexok) { - *dist = (short) sqrt( (float)distance); + *r_dist = sqrtf((float)distance); index = *tbuf - min + 1; goto exit; } } else { - *dist = (short) sqrt( (float)distance); /* XXX, this distance is wrong - */ + *r_dist = sqrtf((float)distance); /* XXX, this distance is wrong - */ index = *tbuf - min + 1; /* messy yah, but indices start at 1 */ goto exit; } @@ -1543,11 +1531,6 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, { RegionView3D *rv3d = ar->regiondata; BGpic *bgpic; - Image *ima; - MovieClip *clip; - ImBuf *ibuf = NULL, *freeibuf; - float vec[4], fac, asp, zoomx, zoomy; - float x1, y1, x2, y2, cx, cy; int fg_flag = do_foreground ? V3D_BGPIC_FOREGROUND : 0; for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) { @@ -1560,6 +1543,13 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, (rv3d->persp == RV3D_CAMOB && bgpic->view == (1 << RV3D_VIEW_CAMERA))) { float image_aspect[2]; + float fac, asp, zoomx, zoomy; + float x1, y1, x2, y2; + + ImBuf *ibuf = NULL, *freeibuf; + + Image *ima; + MovieClip *clip; /* disable individual images */ if ((bgpic->flag & V3D_BGPIC_DISABLED)) @@ -1645,7 +1635,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, /* apply offset last - camera offset is different to offset in blender units */ /* so this has some sane way of working - this matches camera's shift _exactly_ */ { - const float max_dim = maxf(x2 - x1, y2 - y1); + const float max_dim = max_ff(x2 - x1, y2 - y1); const float xof_scale = bgpic->xof * max_dim; const float yof_scale = bgpic->yof * max_dim; @@ -1687,26 +1677,25 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, } } else { + float tvec[3]; float sco[2]; const float mval_f[2] = {1.0f, 0.0f}; /* calc window coord */ initgrabz(rv3d, 0.0, 0.0, 0.0); - ED_view3d_win_to_delta(ar, mval_f, vec); - fac = maxf(fabsf(vec[0]), maxf(fabsf(vec[1]), fabsf(vec[2]))); /* largest abs axis */ + ED_view3d_win_to_delta(ar, mval_f, tvec); + fac = max_ff(fabsf(tvec[0]), max_ff(fabsf(tvec[1]), fabsf(tvec[2]))); /* largest abs axis */ fac = 1.0f / fac; - asp = ( (float)ibuf->y) / (float)ibuf->x; + asp = (float)ibuf->y / (float)ibuf->x; - zero_v3(vec); - ED_view3d_project_float_v2(ar, vec, sco, rv3d->persmat); - cx = sco[0]; - cy = sco[1]; + zero_v3(tvec); + ED_view3d_project_float_v2_m4(ar, tvec, sco, rv3d->persmat); - x1 = cx + fac * (bgpic->xof - bgpic->size); - y1 = cy + asp * fac * (bgpic->yof - bgpic->size); - x2 = cx + fac * (bgpic->xof + bgpic->size); - y2 = cy + asp * fac * (bgpic->yof + bgpic->size); + x1 = sco[0] + fac * (bgpic->xof - bgpic->size); + y1 = sco[1] + asp * fac * (bgpic->yof - bgpic->size); + x2 = sco[0] + fac * (bgpic->xof + bgpic->size); + y2 = sco[1] + asp * fac * (bgpic->yof + bgpic->size); } /* complete clip? */ @@ -1723,7 +1712,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, /* for some reason; zoomlevels down refuses to use GL_ALPHA_SCALE */ if (zoomx < 1.0f || zoomy < 1.0f) { - float tzoom = minf(zoomx, zoomy); + float tzoom = min_ff(zoomx, zoomy); int mip = 0; if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) { @@ -1772,8 +1761,9 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, glDepthMask(1); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); - if (freeibuf) + if (freeibuf) { IMB_freeImBuf(freeibuf); + } } } } @@ -1925,7 +1915,7 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas if (base->object->restrictflag & OB_RESTRICT_VIEW) return; tbase.flag = OB_FROMDUPLI | base->flag; - lb = object_duplilist(scene, base->object); + lb = object_duplilist(scene, base->object, FALSE); // BLI_sortlist(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */ dob = dupli_step(lb->first); @@ -2029,7 +2019,7 @@ static void draw_dupli_objects(Scene *scene, ARegion *ar, View3D *v3d, Base *bas void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect) { - int x, y, w, h; + int x, y, w, h; rcti r; /* clamp rect by area */ @@ -2045,8 +2035,8 @@ void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect) x = rect->xmin; y = rect->ymin; - w = BLI_RCT_SIZE_X(rect); - h = BLI_RCT_SIZE_Y(rect); + w = BLI_rcti_size_x(rect); + h = BLI_rcti_size_y(rect); if (w <= 0 || h <= 0) { if (d->depths) @@ -2127,7 +2117,7 @@ float view3d_depth_near(ViewDepths *d) int i = (int)d->w * (int)d->h; /* cast to avoid short overflow */ /* far is both the starting 'far' value - * and the closest value found. */ + * and the closest value found. */ while (i--) { depth = *depths++; if ((depth < far) && (depth > near)) { @@ -2143,7 +2133,7 @@ void draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d) short zbuf = v3d->zbuf; RegionView3D *rv3d = ar->regiondata; - setwinmatrixview3d(ar, v3d, NULL); /* 0= no pick rect */ + setwinmatrixview3d(ar, v3d, NULL); setviewmatrixview3d(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */ mult_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); @@ -2178,7 +2168,7 @@ void draw_depth(Scene *scene, ARegion *ar, View3D *v3d, int (*func)(void *)) U.glalphaclip = 0.5; /* not that nice but means we wont zoom into billboards */ U.obcenter_dia = 0; - setwinmatrixview3d(ar, v3d, NULL); /* 0= no pick rect */ + setwinmatrixview3d(ar, v3d, NULL); setviewmatrixview3d(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */ mult_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); @@ -2338,7 +2328,7 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d) if (ob->transflag & OB_DUPLI) { DupliObject *dob; - ListBase *lb = object_duplilist(scene, ob); + ListBase *lb = object_duplilist(scene, ob, FALSE); for (dob = lb->first; dob; dob = dob->next) if (dob->ob->type == OB_LAMP) @@ -2376,6 +2366,7 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d) mult_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat); invert_m4_m4(rv3d.persinv, rv3d.viewinv); + /* no need to call ED_view3d_draw_offscreen_init since shadow buffers were already updated */ ED_view3d_draw_offscreen(scene, v3d, &ar, winsize, winsize, viewmat, winmat, FALSE, FALSE); GPU_lamp_shadow_buffer_unbind(shadow->lamp); @@ -2465,7 +2456,7 @@ void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float view if (winmat) copy_m4_m4(rv3d->winmat, winmat); else - setwinmatrixview3d(ar, v3d, NULL); /* NULL= no pickrect */ + setwinmatrixview3d(ar, v3d, NULL); /* setup view matrix */ if (viewmat) @@ -2483,7 +2474,7 @@ void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float view /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])' * because of float point precision problems at large values [#23908] */ float v1[3], v2[3]; - float len1, len2; + float len_px, len_sc; v1[0] = rv3d->persmat[0][0]; v1[1] = rv3d->persmat[1][0]; @@ -2493,10 +2484,10 @@ void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float view v2[1] = rv3d->persmat[1][1]; v2[2] = rv3d->persmat[2][1]; - len1 = 1.0f / len_v3(v1); - len2 = 1.0f / len_v3(v2); + len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2))); + len_sc = (float)MAX2(ar->winx, ar->winy); - rv3d->pixsize = (2.0f * MAX2(len1, len2)) / (float)MAX2(ar->winx, ar->winy); + rv3d->pixsize = len_px / len_sc; } } @@ -2513,6 +2504,16 @@ static void view3d_main_area_setup_view(Scene *scene, View3D *v3d, ARegion *ar, glLoadMatrixf(rv3d->viewmat); } +void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d) +{ + /* shadow buffers, before we setup matrices */ + if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)) + gpu_update_lamps_shadows(scene, v3d); +} + +/* ED_view3d_draw_offscreen_init should be called before this to initialize + * stuff like shadow buffers + */ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy, float viewmat[][4], float winmat[][4], int do_bgpic, int colormanage_background) @@ -2546,10 +2547,6 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, /* free images which can have changed on frame-change * warning! can be slow so only free animated images - campbell */ GPU_free_images_anim(); - - /* shadow buffers, before we setup matrices */ - if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype)) - gpu_update_lamps_shadows(scene, v3d); /* set background color, fallback on the view background color * (if active clip is set but frame is failed to load fallback to horizon color as background) */ @@ -2557,7 +2554,7 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, /* NOTE: currently OpenGL is supposed to always work in sRGB space and do not * apply any tonemaps since it's really tricky to support for all features (GLSL, textures, etc) * but due to compatibility issues background is being affected display transform, so we can - * emulate behavior of disabled colro management + * emulate behavior of disabled color management * but this function is also used for sequencer's scene strips which shouldn't be affected by * tonemaps now and should be purely sRGB, that's why we've got this colormanage_background * we can drop this flag in cost of some compatibility loss -- background wouldn't be @@ -2692,6 +2689,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, if (ofs == NULL) return NULL; + ED_view3d_draw_offscreen_init(scene, v3d); + GPU_offscreen_bind(ofs); /* render 3d view */ @@ -2820,7 +2819,7 @@ static void draw_viewport_fps(Scene *scene, ARegion *ar) if (fps + 0.5f < (float)(FPS)) { UI_ThemeColor(TH_REDALERT); BLI_snprintf(printable, sizeof(printable), "fps: %.2f", fps); - } + } else { UI_ThemeColor(TH_TEXT_HI); BLI_snprintf(printable, sizeof(printable), "fps: %i", (int)(fps + 0.5f)); @@ -2858,8 +2857,8 @@ static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar, int draw engine = RE_engine_create(type); - engine->tile_x = ceil(ar->winx/(float)scene->r.xparts); - engine->tile_y = ceil(ar->winy/(float)scene->r.yparts); + engine->tile_x = scene->r.tilex; + engine->tile_y = scene->r.tiley; type->view_update(engine, C); @@ -2877,12 +2876,20 @@ static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar, int draw rctf viewborder; rcti cliprct; - ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, FALSE); + if (rv3d->persp == RV3D_CAMOB) { + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, FALSE); - cliprct.xmin = viewborder.xmin + scene->r.border.xmin * BLI_RCT_SIZE_X(&viewborder); - cliprct.ymin = viewborder.ymin + scene->r.border.ymin * BLI_RCT_SIZE_Y(&viewborder); - cliprct.xmax = viewborder.xmin + scene->r.border.xmax * BLI_RCT_SIZE_X(&viewborder); - cliprct.ymax = viewborder.ymin + scene->r.border.ymax * BLI_RCT_SIZE_Y(&viewborder); + cliprct.xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder); + cliprct.ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder); + cliprct.xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder); + cliprct.ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder); + } + else { + cliprct.xmin = v3d->render_border.xmin * ar->winx; + cliprct.xmax = v3d->render_border.xmax * ar->winx; + cliprct.ymin = v3d->render_border.ymin * ar->winy; + cliprct.ymax = v3d->render_border.ymax * ar->winy; + } cliprct.xmin += ar->winrct.xmin; cliprct.xmax += ar->winrct.xmin; @@ -2896,7 +2903,7 @@ static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar, int draw if (cliprct.xmax > cliprct.xmin && cliprct.ymax > cliprct.ymin) { glGetIntegerv(GL_SCISSOR_BOX, scissor); - glScissor(cliprct.xmin, cliprct.ymin, BLI_RCT_SIZE_X(&cliprct), BLI_RCT_SIZE_Y(&cliprct)); + glScissor(cliprct.xmin, cliprct.ymin, BLI_rcti_size_x(&cliprct), BLI_rcti_size_y(&cliprct)); } else return 0; @@ -3126,50 +3133,64 @@ static void view3d_main_area_draw_info(const bContext *C, ARegion *ar, const cha View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); - Object *ob; - - if (rv3d->persp == RV3D_CAMOB) + if (rv3d->persp == RV3D_CAMOB) { drawviewborder(scene, ar, v3d); + } + else if (v3d->flag2 & V3D_RENDER_BORDER) { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + setlinestyle(3); + cpack(0x4040FF); + + glRectf(v3d->render_border.xmin * ar->winx, v3d->render_border.ymin * ar->winy, + v3d->render_border.xmax * ar->winx, v3d->render_border.ymax * ar->winy); + + setlinestyle(0); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { + Object *ob; + /* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */ // if (v3d->flag2 & V3D_DISPGP) draw_gpencil_view3d(scene, v3d, ar, 0); drawcursor(scene, ar, v3d); + + if (U.uiflag & USER_SHOW_ROTVIEWICON) + draw_view_axis(rv3d); + else + draw_view_icon(rv3d); + + ob = OBACT; + if (U.uiflag & USER_DRAWVIEWINFO) + draw_selected_name(scene, ob); } - - if (U.uiflag & USER_SHOW_ROTVIEWICON) - draw_view_axis(rv3d); - else - draw_view_icon(rv3d); - - ob = OBACT; - if (U.uiflag & USER_DRAWVIEWINFO) - draw_selected_name(scene, ob); if (rv3d->render_engine) { view3d_main_area_draw_engine_info(rv3d, ar); return; } - if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_playing(wm)) { - draw_viewport_fps(scene, ar); - } - else if (U.uiflag & USER_SHOW_VIEWPORTNAME) { - draw_viewport_name(ar, v3d); - } - - if (grid_unit) { /* draw below the viewport name */ - char numstr[32] = ""; - - UI_ThemeColor(TH_TEXT_HI); - if (v3d->grid != 1.0f) { - BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid); + if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { + if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_playing(wm)) { + draw_viewport_fps(scene, ar); + } + else if (U.uiflag & USER_SHOW_VIEWPORTNAME) { + draw_viewport_name(ar, v3d); } - BLF_draw_default_ascii(22, ar->winy - (USER_SHOW_VIEWPORTNAME ? 40 : 20), 0.0f, - numstr[0] ? numstr : grid_unit, sizeof(numstr)); + if (grid_unit) { /* draw below the viewport name */ + char numstr[32] = ""; + + UI_ThemeColor(TH_TEXT_HI); + if (v3d->grid != 1.0f) { + BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid); + } + + BLF_draw_default_ascii(22, ar->winy - (USER_SHOW_VIEWPORTNAME ? 40 : 20), 0.0f, + numstr[0] ? numstr : grid_unit, sizeof(numstr)); + } } } @@ -3179,18 +3200,12 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar) View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); const char *grid_unit = NULL; - int draw_border = (rv3d->persp == RV3D_CAMOB && (scene->r.mode & R_BORDER)); + int draw_border = FALSE; - /* --- until we get a clue and make viewport threadsafe (temp mango change for stability) */ - if (G.is_rendering) { - ED_region_pixelspace(ar); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - UI_ThemeClearColor(TH_BACK); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - BLF_draw_default(10,10,0, "do do da da.. da da.. da da.. can't touch this! it's render time", 512); - return; - } - /* --- end temp mango change */ + if (rv3d->persp == RV3D_CAMOB) + draw_border = scene->r.mode & R_BORDER; + else + draw_border = v3d->flag2 & V3D_RENDER_BORDER; /* draw viewport using opengl */ if (v3d->drawtype != OB_RENDER || !view3d_main_area_do_render_draw(C) || draw_border) { diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 7accdb0c0e4..36d7341f2f2 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -96,6 +96,7 @@ int ED_view3d_camera_lock_check(View3D *v3d, RegionView3D *rv3d) void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d) { if (ED_view3d_camera_lock_check(v3d, rv3d)) { + rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs); ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL); } } @@ -375,17 +376,17 @@ typedef struct ViewOpsData { #define TRACKBALLSIZE (1.1) -static void calctrackballvec(rcti *rect, int mx, int my, float vec[3]) +static void calctrackballvec(const rcti *rect, int mx, int my, float vec[3]) { float x, y, radius, d, z, t; radius = TRACKBALLSIZE; /* normalize x and y */ - x = BLI_RCT_CENTER_X(rect) - mx; - x /= (float)(BLI_RCT_SIZE_X(rect) / 4); - y = BLI_RCT_CENTER_Y(rect) - my; - y /= (float)(BLI_RCT_SIZE_Y(rect) / 2); + x = BLI_rcti_cent_x(rect) - mx; + x /= (float)(BLI_rcti_size_x(rect) / 4); + y = BLI_rcti_cent_y(rect) - my; + y /= (float)(BLI_rcti_size_y(rect) / 2); d = sqrt(x * x + y * y); if (d < radius * (float)M_SQRT1_2) { /* Inside sphere */ @@ -894,6 +895,7 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event) /* changed since 2.4x, use the camera view */ if (vod->v3d->camera) { + rv3d->dist = ED_view3d_offset_distance(vod->v3d->camera->obmat, rv3d->ofs); ED_view3d_from_object(vod->v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL); } @@ -921,7 +923,7 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; } - else { + else { /* add temp handler */ WM_event_add_modal_handler(C, op); @@ -929,18 +931,6 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event) } } -static int view3d_camera_active_poll(bContext *C) -{ - if (ED_operator_view3d_active(C)) { - RegionView3D *rv3d = CTX_wm_region_view3d(C); - if (rv3d && rv3d->persp == RV3D_CAMOB) { - return 1; - } - } - - return 0; -} - /* test for unlocked camera view in quad view */ static int view3d_camera_user_poll(bContext *C) { @@ -966,7 +956,6 @@ static int viewrotate_cancel(bContext *C, wmOperator *op) void VIEW3D_OT_rotate(wmOperatorType *ot) { - /* identifiers */ ot->name = "Rotate view"; ot->description = "Rotate the view"; @@ -1235,8 +1224,8 @@ void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot) /* -* this is basically just the pan only code + the rotate only code crammed into one function that does both -*/ + * this is basically just the pan only code + the rotate only code crammed into one function that does both + */ static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event) { if (event->type != NDOF_MOTION) @@ -1367,7 +1356,7 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event) ED_view3d_camera_lock_sync(v3d, rv3d); ED_region_tag_redraw(CTX_wm_region(C)); - viewops_data_free(C, op); + viewops_data_free(C, op); return OPERATOR_FINISHED; } } @@ -1514,7 +1503,7 @@ static int viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event) viewmove_apply(vod, event->prevx, event->prevy); ED_view3d_depth_tag_update(vod->rv3d); - viewops_data_free(C, op); + viewops_data_free(C, op); return OPERATOR_FINISHED; } @@ -1637,7 +1626,7 @@ static void viewzoom_apply(ViewOpsData *vod, int x, int y, const short viewzoom, if (use_cam_zoom) { float delta; delta = (x - vod->origx + y - vod->origy) / 10.0f; - vod->rv3d->camzoom = vod->camzoom0 - delta; + vod->rv3d->camzoom = vod->camzoom0 + (zoom_invert ? -delta : delta); CLAMP(vod->rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); } @@ -1666,8 +1655,8 @@ static void viewzoom_apply(ViewOpsData *vod, int x, int y, const short viewzoom, int ctr[2], len1, len2; /* method which zooms based on how far you move the mouse */ - ctr[0] = BLI_RCT_CENTER_X(&vod->ar->winrct); - ctr[1] = BLI_RCT_CENTER_Y(&vod->ar->winrct); + ctr[0] = BLI_rcti_cent_x(&vod->ar->winrct); + ctr[1] = BLI_rcti_cent_y(&vod->ar->winrct); 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; @@ -1692,11 +1681,11 @@ static void viewzoom_apply(ViewOpsData *vod, int x, int y, const short viewzoom, if (use_cam_zoom) { /* zfac is ignored in this case, see below */ #if 0 - zfac = vod->camzoom0 * (2.0f * ((len2 / len1) - 1.0f) + 1.0f) / vod->rv3d->camzoom; + zfac = vod->camzoom0 * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->camzoom; #endif } else { - zfac = vod->dist0 * (2.0f * ((len2 / len1) - 1.0f) + 1.0f) / vod->rv3d->dist; + zfac = vod->dist0 * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->dist; } } @@ -1889,12 +1878,12 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, wmEvent *event) if (U.uiflag & USER_ZOOM_HORIZ) { vod->origx = vod->oldx = event->x; - viewzoom_apply(vod, event->prevx, event->prevy, USER_ZOOM_DOLLY, FALSE); + viewzoom_apply(vod, event->prevx, event->prevy, USER_ZOOM_DOLLY, (U.uiflag & USER_ZOOM_INVERT) == 0); } else { /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */ vod->origy = vod->oldy = vod->origy + event->x - event->prevx; - viewzoom_apply(vod, event->prevx, event->prevy, USER_ZOOM_DOLLY, FALSE); + viewzoom_apply(vod, event->prevx, event->prevy, USER_ZOOM_DOLLY, (U.uiflag & USER_ZOOM_INVERT) == 0); } ED_view3d_depth_tag_update(vod->rv3d); @@ -1972,7 +1961,7 @@ static void viewdolly_apply(ViewOpsData *vod, int x, int y, const short zoom_inv if (zoom_invert) SWAP(float, len1, len2); - zfac = 1.0f + ((len2 - len1) * 0.01f * vod->rv3d->dist); + zfac = 1.0f + ((len1 - len2) * 0.01f * vod->rv3d->dist); } if (zfac != 1.0f) @@ -2052,7 +2041,7 @@ static int viewdolly_exec(bContext *C, wmOperator *op) normalize_v3(mousevec); } - /* v3d= sa->spacedata.first; */ /* UNUSED */ + /* v3d = sa->spacedata.first; */ /* UNUSED */ rv3d = ar->regiondata; /* overwrite the mouse vector with the view direction (zoom into the center) */ @@ -2108,13 +2097,13 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, wmEvent *event) if (U.uiflag & USER_ZOOM_HORIZ) { vod->origx = vod->oldx = event->x; - viewdolly_apply(vod, event->prevx, event->prevy, FALSE); + viewdolly_apply(vod, event->prevx, event->prevy, (U.uiflag & USER_ZOOM_INVERT) == 0); } else { /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */ vod->origy = vod->oldy = vod->origy + event->x - event->prevx; - viewdolly_apply(vod, event->prevx, event->prevy, FALSE); + viewdolly_apply(vod, event->prevx, event->prevy, (U.uiflag & USER_ZOOM_INVERT) == 0); } ED_view3d_depth_tag_update(vod->rv3d); @@ -2179,21 +2168,98 @@ void VIEW3D_OT_dolly(wmOperatorType *ot) RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Zoom Position Y", "", 0, INT_MAX); } +static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar, + const float min[3], const float max[3], + int ok_dist) +{ + RegionView3D *rv3d = ar->regiondata; + float afm[3]; + float size; + /* SMOOTHVIEW */ + float new_ofs[3]; + float new_dist; + + sub_v3_v3v3(afm, max, min); + size = MAX3(afm[0], afm[1], afm[2]); + + if (ok_dist) { + /* fix up zoom distance if needed */ + + if (rv3d->is_persp) { + if (size <= v3d->near * 1.5f) { + /* do not zoom closer than the near clipping plane */ + size = v3d->near * 1.5f; + } + } + else { /* ortho */ + if (size < 0.0001f) { + /* bounding box was a single point so do not zoom */ + ok_dist = 0; + } + else { + /* adjust zoom so it looks nicer */ + size *= 0.7f; + } + } + } + + mid_v3_v3v3(new_ofs, min, max); + negate_v3(new_ofs); + + new_dist = size; + + /* correction for window aspect ratio */ + if (ar->winy > 2 && ar->winx > 2) { + size = (float)ar->winx / (float)ar->winy; + if (size < 1.0f) size = 1.0f / size; + new_dist *= size; + } + + if (rv3d->persp == RV3D_CAMOB && !ED_view3d_camera_lock_check(v3d, rv3d)) { + rv3d->persp = RV3D_PERSP; + view3d_smooth_view(C, v3d, ar, v3d->camera, NULL, new_ofs, NULL, ok_dist ? &new_dist : NULL, NULL); + } + else { + view3d_smooth_view(C, v3d, ar, NULL, NULL, new_ofs, NULL, ok_dist ? &new_dist : NULL, NULL); + } + + /* smooth view does viewlock RV3D_BOXVIEW copy */ +} + +/* same as view3d_from_minmax but for all regions (except cameras) */ +static void view3d_from_minmax_multi(bContext *C, View3D *v3d, + const float min[3], const float max[3], + const int ok_dist) +{ + ScrArea *sa = CTX_wm_area(C); + ARegion *ar; + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->regiontype == RGN_TYPE_WINDOW) { + RegionView3D *rv3d = ar->regiondata; + /* when using all regions, don't jump out of camera view, + * but _do_ allow locked cameras to be moved */ + if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) { + view3d_from_minmax(C, v3d, ar, min, max, ok_dist); + } + } + } +} static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in 2.4x */ { ARegion *ar = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = CTX_wm_region_view3d(C); Scene *scene = CTX_data_scene(C); Base *base; float *curs; - const short skip_camera = ED_view3d_camera_lock_check(v3d, rv3d); - + const short use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions"); + const short skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) || + /* any one of the regions may be locked */ + (use_all_regions && v3d->flag2 & V3D_LOCK_CAMERA)); int center = RNA_boolean_get(op->ptr, "center"); - float size, min[3], max[3], afm[3]; + float min[3], max[3]; int ok = 1, onedone = FALSE; if (center) { @@ -2230,37 +2296,16 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in return OPERATOR_FINISHED; } - sub_v3_v3v3(afm, max, min); - size = 0.7f * MAX3(afm[0], afm[1], afm[2]); - if (size == 0.0f) ok = 0; - - if (ok) { - float new_dist; - float new_ofs[3]; - - new_dist = size; - new_ofs[0] = -(min[0] + max[0]) / 2.0f; - new_ofs[1] = -(min[1] + max[1]) / 2.0f; - new_ofs[2] = -(min[2] + max[2]) / 2.0f; - - /* correction for window aspect ratio */ - if (ar->winy > 2 && ar->winx > 2) { - size = (float)ar->winx / (float)ar->winy; - if (size < 1.0f) size = 1.0f / size; - new_dist *= size; - } - - if ((rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(v3d, rv3d)) { - rv3d->persp = RV3D_PERSP; - view3d_smooth_view(C, v3d, ar, v3d->camera, NULL, new_ofs, NULL, &new_dist, NULL); - } - else { - view3d_smooth_view(C, v3d, ar, NULL, NULL, new_ofs, NULL, &new_dist, NULL); - } + if (ok == 0) { + return OPERATOR_FINISHED; } -// XXX BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); + if (use_all_regions) { + view3d_from_minmax_multi(C, v3d, min, max, TRUE); + } + else { + view3d_from_minmax(C, v3d, ar, min, max, TRUE); + } return OPERATOR_FINISHED; } @@ -2268,6 +2313,8 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in void VIEW3D_OT_view_all(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "View All"; ot->description = "View all objects in scene"; @@ -2280,25 +2327,25 @@ void VIEW3D_OT_view_all(wmOperatorType *ot) /* flags */ ot->flag = 0; + prop = RNA_def_boolean(ot->srna, "use_all_regions", 0, "All Regions", "View selected for all regions"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); RNA_def_boolean(ot->srna, "center", 0, "Center", ""); } /* like a localview without local!, was centerview() in 2.4x */ -static int viewselected_exec(bContext *C, wmOperator *UNUSED(op)) +static int viewselected_exec(bContext *C, wmOperator *op) { ARegion *ar = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = CTX_wm_region_view3d(C); Scene *scene = CTX_data_scene(C); Object *ob = OBACT; Object *obedit = CTX_data_edit_object(C); - float size, min[3], max[3], afm[3]; + float min[3], max[3]; int ok = 0, ok_dist = 1; - const short skip_camera = ED_view3d_camera_lock_check(v3d, rv3d); - - /* SMOOTHVIEW */ - float new_ofs[3]; - float new_dist; + const short use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions"); + const short skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) || + /* any one of the regions may be locked */ + (use_all_regions && v3d->flag2 & V3D_LOCK_CAMERA)); INIT_MINMAX(min, max); @@ -2369,54 +2416,17 @@ static int viewselected_exec(bContext *C, wmOperator *UNUSED(op)) } } - if (ok == 0) return OPERATOR_FINISHED; - - sub_v3_v3v3(afm, max, min); - size = MAX3(afm[0], afm[1], afm[2]); - - if (ok_dist) { - /* fix up zoom distance if needed */ - - if (rv3d->is_persp) { - if (size <= v3d->near * 1.5f) { - /* do not zoom closer than the near clipping plane */ - size = v3d->near * 1.5f; - } - } - else { /* ortho */ - if (size < 0.0001f) { - /* bounding box was a single point so do not zoom */ - ok_dist = 0; - } - else { - /* adjust zoom so it looks nicer */ - size *= 0.7f; - } - } + if (ok == 0) { + return OPERATOR_FINISHED; } - add_v3_v3v3(new_ofs, min, max); - mul_v3_fl(new_ofs, -0.5f); - - new_dist = size; - - /* correction for window aspect ratio */ - if (ar->winy > 2 && ar->winx > 2) { - size = (float)ar->winx / (float)ar->winy; - if (size < 1.0f) size = 1.0f / size; - new_dist *= size; - } - - if (rv3d->persp == RV3D_CAMOB && !ED_view3d_camera_lock_check(v3d, rv3d)) { - rv3d->persp = RV3D_PERSP; - view3d_smooth_view(C, v3d, ar, v3d->camera, NULL, new_ofs, NULL, ok_dist ? &new_dist : NULL, NULL); + if (use_all_regions) { + view3d_from_minmax_multi(C, v3d, min, max, ok_dist); } else { - view3d_smooth_view(C, v3d, ar, NULL, NULL, new_ofs, NULL, ok_dist ? &new_dist : NULL, NULL); + view3d_from_minmax(C, v3d, ar, min, max, ok_dist); } - /* smooth view does viewlock RV3D_BOXVIEW copy */ - // XXX BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); return OPERATOR_FINISHED; @@ -2424,6 +2434,7 @@ static int viewselected_exec(bContext *C, wmOperator *UNUSED(op)) void VIEW3D_OT_view_selected(wmOperatorType *ot) { + PropertyRNA *prop; /* identifiers */ ot->name = "View Selected"; @@ -2436,6 +2447,10 @@ void VIEW3D_OT_view_selected(wmOperatorType *ot) /* flags */ ot->flag = 0; + + /* rna later */ + prop = RNA_def_boolean(ot->srna, "use_all_regions", 0, "All Regions", "View selected for all regions"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } static int view_lock_clear_exec(bContext *C, wmOperator *UNUSED(op)) @@ -2578,7 +2593,7 @@ static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op)) /* was xfac = (float)ar->winx / (float)(size[0] + 4); yfac = (float)ar->winy / (float)(size[1] + 4); - rv3d->camzoom = BKE_screen_view3d_zoom_from_fac(minf(xfac, yfac)); + rv3d->camzoom = BKE_screen_view3d_zoom_from_fac(min_ff(xfac, yfac)); CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C)); @@ -2608,42 +2623,71 @@ static int render_border_exec(bContext *C, wmOperator *op) View3D *v3d = CTX_wm_view3d(C); ARegion *ar = CTX_wm_region(C); RegionView3D *rv3d = ED_view3d_context_rv3d(C); + Scene *scene = CTX_data_scene(C); rcti rect; - rctf vb; + rctf vb, border; + + int camera_only = RNA_boolean_get(op->ptr, "camera_only"); + + if (camera_only && rv3d->persp != RV3D_CAMOB) + return OPERATOR_PASS_THROUGH; /* get border select values using rna */ WM_operator_properties_border_to_rcti(op, &rect); /* calculate range */ - ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, FALSE); - scene->r.border.xmin = ((float)rect.xmin - vb.xmin) / BLI_RCT_SIZE_X(&vb); - scene->r.border.ymin = ((float)rect.ymin - vb.ymin) / BLI_RCT_SIZE_Y(&vb); - scene->r.border.xmax = ((float)rect.xmax - vb.xmin) / BLI_RCT_SIZE_X(&vb); - scene->r.border.ymax = ((float)rect.ymax - vb.ymin) / BLI_RCT_SIZE_Y(&vb); + if (rv3d->persp == RV3D_CAMOB) { + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, FALSE); + } + else { + vb.xmin = 0; + vb.ymin = 0; + vb.xmax = ar->winx; + vb.ymax = ar->winy; + } + + border.xmin = ((float)rect.xmin - vb.xmin) / BLI_rctf_size_x(&vb); + border.ymin = ((float)rect.ymin - vb.ymin) / BLI_rctf_size_y(&vb); + border.xmax = ((float)rect.xmax - vb.xmin) / BLI_rctf_size_x(&vb); + border.ymax = ((float)rect.ymax - vb.ymin) / BLI_rctf_size_y(&vb); /* actually set border */ - CLAMP(scene->r.border.xmin, 0.0f, 1.0f); - CLAMP(scene->r.border.ymin, 0.0f, 1.0f); - CLAMP(scene->r.border.xmax, 0.0f, 1.0f); - CLAMP(scene->r.border.ymax, 0.0f, 1.0f); + CLAMP(border.xmin, 0.0f, 1.0f); + CLAMP(border.ymin, 0.0f, 1.0f); + CLAMP(border.xmax, 0.0f, 1.0f); + CLAMP(border.ymax, 0.0f, 1.0f); + + if (rv3d->persp == RV3D_CAMOB) { + scene->r.border = border; + + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL); + } + else { + v3d->render_border = border; + + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); + } /* drawing a border surrounding the entire camera view switches off border rendering * or the border covers no pixels */ - if ((scene->r.border.xmin <= 0.0f && scene->r.border.xmax >= 1.0f && - scene->r.border.ymin <= 0.0f && scene->r.border.ymax >= 1.0f) || - (scene->r.border.xmin == scene->r.border.xmax || - scene->r.border.ymin == scene->r.border.ymax)) + if ((border.xmin <= 0.0f && border.xmax >= 1.0f && + border.ymin <= 0.0f && border.ymax >= 1.0f) || + (border.xmin == border.xmax || border.ymin == border.ymax)) { - scene->r.mode &= ~R_BORDER; + if (rv3d->persp == RV3D_CAMOB) + scene->r.mode &= ~R_BORDER; + else + v3d->flag2 &= ~V3D_RENDER_BORDER; } else { - scene->r.mode |= R_BORDER; + if (rv3d->persp == RV3D_CAMOB) + scene->r.mode |= R_BORDER; + else + v3d->flag2 |= V3D_RENDER_BORDER; } - - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL); return OPERATOR_FINISHED; @@ -2653,7 +2697,7 @@ void VIEW3D_OT_render_border(wmOperatorType *ot) { /* identifiers */ ot->name = "Set Render Border"; - ot->description = "Set the boundaries of the border render and enables border render"; + ot->description = "Set the boundaries of the border render and enable border render"; ot->idname = "VIEW3D_OT_render_border"; /* api callbacks */ @@ -2662,7 +2706,7 @@ void VIEW3D_OT_render_border(wmOperatorType *ot) ot->modal = WM_border_select_modal; ot->cancel = WM_border_select_cancel; - ot->poll = view3d_camera_active_poll; + ot->poll = ED_operator_view3d_active; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -2670,7 +2714,56 @@ void VIEW3D_OT_render_border(wmOperatorType *ot) /* rna */ WM_operator_properties_border(ot); + RNA_def_boolean(ot->srna, "camera_only", 0, "Camera Only", "Set render border for camera view and final render only"); } + +/* ********************* Clear render border operator ****************** */ + +static int clear_render_border_exec(bContext *C, wmOperator *UNUSED(op)) +{ + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = ED_view3d_context_rv3d(C); + + Scene *scene = CTX_data_scene(C); + rctf *border = NULL; + + if (rv3d->persp == RV3D_CAMOB) { + scene->r.mode &= ~R_BORDER; + border = &scene->r.border; + + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL); + } + else { + v3d->flag2 &= ~V3D_RENDER_BORDER; + border = &v3d->render_border; + + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); + } + + border->xmin = 0.0f; + border->ymin = 0.0f; + border->xmax = 1.0f; + border->ymax = 1.0f; + + return OPERATOR_FINISHED; + +} + +void VIEW3D_OT_clear_render_border(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Clear Render Border"; + ot->description = "Clear the boundaries of the border render and disable border render"; + ot->idname = "VIEW3D_OT_clear_render_border"; + + /* api callbacks */ + ot->exec = clear_render_border_exec; + ot->poll = ED_operator_view3d_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + /* ********************* Border Zoom operator ****************** */ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) @@ -2729,7 +2822,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) /* no depths to use, we cant do anything! */ if (depth_close == FLT_MAX) { - BKE_report(op->reports, RPT_ERROR, "Depth Too Large"); + BKE_report(op->reports, RPT_ERROR, "Depth too large"); return OPERATOR_CANCELLED; } /* convert border to 3d coordinates */ @@ -2786,9 +2879,9 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) } /* work out the ratios, so that everything selected fits when we zoom */ - xscale = (BLI_RCT_SIZE_X(&rect) / vb[0]); - yscale = (BLI_RCT_SIZE_Y(&rect) / vb[1]); - new_dist *= maxf(xscale, yscale); + xscale = (BLI_rcti_size_x(&rect) / vb[0]); + yscale = (BLI_rcti_size_y(&rect) / vb[1]); + new_dist *= max_ff(xscale, yscale); /* zoom in as required, or as far as we can go */ dist_range_min = 0.001f * v3d->grid; @@ -2901,7 +2994,7 @@ static EnumPropertyItem prop_view_items[] = { {RV3D_VIEW_RIGHT, "RIGHT", 0, "Right", "View From the Right"}, {RV3D_VIEW_TOP, "TOP", 0, "Top", "View From the Top"}, {RV3D_VIEW_BOTTOM, "BOTTOM", 0, "Bottom", "View From the Bottom"}, - {RV3D_VIEW_CAMERA, "CAMERA", 0, "Camera", "View From the active camera"}, + {RV3D_VIEW_CAMERA, "CAMERA", 0, "Camera", "View From the Active Camera"}, {0, NULL, 0, NULL, NULL} }; @@ -3125,7 +3218,7 @@ void VIEW3D_OT_viewnumpad(wmOperatorType *ot) /* identifiers */ ot->name = "View numpad"; - ot->description = "Set the view"; + ot->description = "Use a preset viewpoint"; ot->idname = "VIEW3D_OT_viewnumpad"; /* api callbacks */ @@ -3135,8 +3228,8 @@ void VIEW3D_OT_viewnumpad(wmOperatorType *ot) /* flags */ ot->flag = 0; - prop = RNA_def_enum(ot->srna, "type", prop_view_items, 0, "View", "The Type of view"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + ot->prop = RNA_def_enum(ot->srna, "type", prop_view_items, 0, "View", "Preset viewpoint to use"); + RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, "align_active", 0, "Align Active", "Align to the active object's axis"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } @@ -3213,7 +3306,9 @@ void VIEW3D_OT_view_orbit(wmOperatorType *ot) /* flags */ ot->flag = 0; - RNA_def_enum(ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit"); + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit"); } static EnumPropertyItem prop_view_pan_items[] = { @@ -3262,7 +3357,9 @@ void VIEW3D_OT_view_pan(wmOperatorType *ot) /* flags */ ot->flag = 0; - RNA_def_enum(ot->srna, "type", prop_view_pan_items, 0, "Pan", "Direction of View Pan"); + + /* Properties */ + ot->prop = RNA_def_enum(ot->srna, "type", prop_view_pan_items, 0, "Pan", "Direction of View Pan"); } static int viewpersportho_exec(bContext *C, wmOperator *UNUSED(op)) @@ -3290,7 +3387,7 @@ void VIEW3D_OT_view_persportho(wmOperatorType *ot) { /* identifiers */ ot->name = "View Persp/Ortho"; - ot->description = "Switch the current view from perspective/orthographic"; + ot->description = "Switch the current view from perspective/orthographic projection"; ot->idname = "VIEW3D_OT_view_persportho"; /* api callbacks */ @@ -3406,7 +3503,8 @@ void VIEW3D_OT_background_image_remove(wmOperatorType *ot) /* flags */ ot->flag = 0; - + + /* properties */ RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Background image index to remove", 0, INT_MAX); } @@ -3465,7 +3563,7 @@ static int view3d_clipping_exec(bContext *C, wmOperator *op) view3d_set_viewcontext(C, &vc); view3d_get_transformation(vc.ar, vc.rv3d, NULL, &mats); /* NULL because we don't want it in object space */ - ED_view3d_calc_clipping(rv3d->clipbb, rv3d->clip, &mats, &rect); + ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, &mats, &rect); return OPERATOR_FINISHED; } @@ -3514,57 +3612,49 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot) /* ***************** 3d cursor cursor op ******************* */ /* mx my in region coords */ -static int set_3dcursor_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) { Scene *scene = CTX_data_scene(C); ARegion *ar = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); - float dx, dy, fz, *fp = NULL, dvec[3], oldcurs[3]; - int mval[2]; -// short ctrl= 0; // XXX + float *fp = NULL; + float mval_fl[2]; int flip; fp = give_cursor(scene, v3d); -// if (obedit && ctrl) lr_click= 1; - copy_v3_v3(oldcurs, fp); - - project_int_noclip(ar, fp, mval); flip = initgrabz(rv3d, fp[0], fp[1], fp[2]); - /* reset the depth based on the view offset */ + /* reset the depth based on the view offset (we _know_ the offset is infront of us) */ if (flip) { negate_v3_v3(fp, rv3d->ofs); - - /* re initialize */ - project_int_noclip(ar, fp, mval); - flip = initgrabz(rv3d, fp[0], fp[1], fp[2]); - (void)flip; + /* re initialize, no need to check flip again */ + /* flip = */ initgrabz(rv3d, fp[0], fp[1], fp[2]); } - if (mval[0] != IS_CLIPPED) { - short depth_used = 0; + if (ED_view3d_project_float_global(ar, fp, mval_fl, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + short depth_used = FALSE; if (U.uiflag & USER_ZBUF_CURSOR) { /* maybe this should be accessed some other way */ view3d_operator_needs_opengl(C); if (ED_view3d_autodist(scene, ar, v3d, event->mval, fp)) - depth_used = 1; + depth_used = TRUE; } - if (depth_used == 0) { - float mval_f[2]; - VECSUB2D(mval_f, mval, event->mval); - ED_view3d_win_to_delta(ar, mval_f, dvec); + if (depth_used == FALSE) { + float dvec[3]; + VECSUB2D(mval_fl, mval_fl, event->mval); + ED_view3d_win_to_delta(ar, mval_fl, dvec); sub_v3_v3(fp, dvec); } } else { - - dx = ((float)(event->mval[0] - (ar->winx / 2))) * rv3d->zfac / (ar->winx / 2); - dy = ((float)(event->mval[1] - (ar->winy / 2))) * rv3d->zfac / (ar->winy / 2); - - fz = rv3d->persmat[0][3] * fp[0] + rv3d->persmat[1][3] * fp[1] + rv3d->persmat[2][3] * fp[2] + rv3d->persmat[3][3]; - fz = fz / rv3d->zfac; + const float dx = ((float)(event->mval[0] - (ar->winx / 2))) * rv3d->zfac / (ar->winx / 2); + const float dy = ((float)(event->mval[1] - (ar->winy / 2))) * rv3d->zfac / (ar->winy / 2); + const float fz = (rv3d->persmat[0][3] * fp[0] + + rv3d->persmat[1][3] * fp[1] + + rv3d->persmat[2][3] * fp[2] + + rv3d->persmat[3][3]) / rv3d->zfac; fp[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy + rv3d->persinv[2][0] * fz) - rv3d->ofs[0]; fp[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy + rv3d->persinv[2][1] * fz) - rv3d->ofs[1]; @@ -3588,7 +3678,7 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot) ot->idname = "VIEW3D_OT_cursor3d"; /* api callbacks */ - ot->invoke = set_3dcursor_invoke; + ot->invoke = view3d_cursor3d_invoke; ot->poll = ED_operator_view3d_active; @@ -3836,11 +3926,25 @@ int ED_view3d_autodist_depth_seg(ARegion *ar, const int mval_sta[2], const int m return (*depth == FLT_MAX) ? 0 : 1; } +float ED_view3d_offset_distance(float mat[4][4], float ofs[3]) { + float pos[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + float dir[4] = {0.0f, 0.0f, 1.0f, 0.0f}; + + mul_m4_v4(mat, pos); + add_v3_v3(pos, ofs); + mul_m4_v4(mat, dir); + normalize_v3(dir); + + return dot_v3v3(pos, dir); +} + /** - * Gets the view transformation from a camera - * currently dosnt take camzoom into account + * Set the view transformation from a 4x4 matrix. * - * The dist is not modified for this function, if NULL its assumed zero + * \param mat The view 4x4 transformation matrix to assign. + * \param ofs The view offset, normally from RegionView3D.ofs. + * \param quat The view rotation, quaternion normally from RegionView3D.viewquat. + * \param dist The view distance from ofs, normally from RegionView3D.dist. */ void ED_view3d_from_m4(float mat[][4], float ofs[3], float quat[4], float *dist) { @@ -3871,6 +3975,14 @@ void ED_view3d_from_m4(float mat[][4], float ofs[3], float quat[4], float *dist) } } +/** + * Calculate the view transformation matrix from RegionView3D input. + * The resulting matrix is equivalent to RegionView3D.viewinv + * \param mat The view 4x4 transformation matrix to calculate. + * \param ofs The view offset, normally from RegionView3D.ofs. + * \param quat The view rotation, quaternion normally from RegionView3D.viewquat. + * \param dist The view distance from ofs, normally from RegionView3D.dist. + */ void ED_view3d_to_m4(float mat[][4], const float ofs[3], const float quat[4], const float dist) { float iviewquat[4] = {-quat[0], quat[1], quat[2], quat[3]}; @@ -3881,8 +3993,14 @@ void ED_view3d_to_m4(float mat[][4], const float ofs[3], const float quat[4], co sub_v3_v3v3(mat[3], dvec, ofs); } - -/* object -> view */ +/** + * Set the RegionView3D members from an objects transformation and optionally lens. + * \param ob The object to set the view to. + * \param ofs The view offset to be set, normally from RegionView3D.ofs. + * \param quat The view rotation to be set, quaternion normally from RegionView3D.viewquat. + * \param dist The view distance from ofs to be set, normally from RegionView3D.dist. + * \param lens The view lens angle set for cameras and lamps, normally from View3D.lens. + */ void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, float *lens) { ED_view3d_from_m4(ob->obmat, ofs, quat, dist); @@ -3896,7 +4014,13 @@ void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, } } -/* view -> object */ +/** + * Set the object transformation from RegionView3D members. + * \param ob The object which has the transformation assigned. + * \param ofs The view offset, normally from RegionView3D.ofs. + * \param quat The view rotation, quaternion normally from RegionView3D.viewquat. + * \param dist The view distance from ofs, normally from RegionView3D.dist. + */ void ED_view3d_to_object(Object *ob, const float ofs[3], const float quat[4], const float dist) { float mat[4][4]; diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index 855771b17a2..5aee90f0860 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -27,7 +27,7 @@ /* defines VIEW3D_OT_fly modal operator */ //#define NDOF_FLY_DEBUG -//#define NDOF_FLY_DRAW_TOOMUCH // is this needed for ndof? - commented so redraw doesnt thrash - campbell +//#define NDOF_FLY_DRAW_TOOMUCH /* is this needed for ndof? - commented so redraw doesnt thrash - campbell */ #include "DNA_anim_types.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" @@ -284,6 +284,11 @@ static int initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *event puts("\n-- fly begin --"); #endif + /* sanity check: for rare but possible case (if lib-linking the camera fails) */ + if ((fly->rv3d->persp == RV3D_CAMOB) && (fly->v3d->camera == NULL)) { + fly->rv3d->persp = RV3D_PERSP; + } + if (fly->rv3d->persp == RV3D_CAMOB && fly->v3d->camera->id.lib) { BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library"); return FALSE; @@ -346,7 +351,6 @@ static int initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *event /* check for flying ortho camera - which we cant support well * we _could_ also check for an ortho camera but this is easier */ if ((fly->rv3d->persp == RV3D_CAMOB) && - (fly->v3d->camera != NULL) && (fly->rv3d->is_persp == FALSE)) { ((Camera *)fly->v3d->camera->data)->type = CAM_PERSP; @@ -422,7 +426,6 @@ static int flyEnd(bContext *C, FlyInfo *fly) ED_region_draw_cb_exit(fly->ar->type, fly->draw_handle_pixel); rv3d->dist = fly->dist_backup; - if (fly->state == FLY_CANCEL) { /* Revert to original view? */ if (fly->persp_backup == RV3D_CAMOB) { /* a camera view */ @@ -437,12 +440,16 @@ static int flyEnd(bContext *C, FlyInfo *fly) else { /* Non Camera we need to reset the view back to the original location bacause the user canceled*/ copy_qt_qt(rv3d->viewquat, fly->rot_backup); - copy_v3_v3(rv3d->ofs, fly->ofs_backup); rv3d->persp = fly->persp_backup; } + /* always, is set to zero otherwise */ + copy_v3_v3(rv3d->ofs, fly->ofs_backup); } else if (fly->persp_backup == RV3D_CAMOB) { /* camera */ DAG_id_tag_update(fly->root_parent ? &fly->root_parent->id : &v3d->camera->id, OB_RECALC_OB); + + /* always, is set to zero otherwise */ + copy_v3_v3(rv3d->ofs, fly->ofs_backup); } else { /* not camera */ @@ -549,7 +556,7 @@ static void flyEvent(FlyInfo *fly, wmEvent *event) time_wheel = (float)(time_currwheel - fly->time_lastwheel); fly->time_lastwheel = time_currwheel; /* Mouse wheel delays range from (0.5 == slow) to (0.01 == fast) */ - time_wheel = 1.0f + (10.0f - (20.0f * minf(time_wheel, 0.5f))); /* 0-0.5 -> 0-5.0 */ + time_wheel = 1.0f + (10.0f - (20.0f * min_ff(time_wheel, 0.5f))); /* 0-0.5 -> 0-5.0 */ if (fly->speed < 0.0f) { fly->speed = 0.0f; @@ -567,7 +574,7 @@ static void flyEvent(FlyInfo *fly, wmEvent *event) time_currwheel = PIL_check_seconds_timer(); time_wheel = (float)(time_currwheel - fly->time_lastwheel); fly->time_lastwheel = time_currwheel; - time_wheel = 1.0f + (10.0f - (20.0f * minf(time_wheel, 0.5f))); /* 0-0.5 -> 0-5.0 */ + time_wheel = 1.0f + (10.0f - (20.0f * min_ff(time_wheel, 0.5f))); /* 0-0.5 -> 0-5.0 */ if (fly->speed > 0.0f) { fly->speed = 0; @@ -791,8 +798,8 @@ static int flyApply(bContext *C, FlyInfo *fly) ymargin = ar->winy / 20.0f; // UNUSED - // cent_orig[0]= ar->winrct.xmin + ar->winx/2; - // cent_orig[1]= ar->winrct.ymin + ar->winy/2; + // cent_orig[0] = ar->winrct.xmin + ar->winx / 2; + // cent_orig[1] = ar->winrct.ymin + ar->winy / 2; { @@ -843,7 +850,7 @@ static int flyApply(bContext *C, FlyInfo *fly) #endif time_current = PIL_check_seconds_timer(); time_redraw = (float)(time_current - fly->time_lastdraw); - time_redraw_clamped = minf(0.05f, time_redraw); /* clamp redraw time to avoid jitter in roll correction */ + time_redraw_clamped = min_ff(0.05f, time_redraw); /* clamp redraw time to avoid jitter in roll correction */ fly->time_lastdraw = time_current; /* Scale the time to use shift to scale the speed down- just like diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index fd43333acfe..d8fcc7e12e7 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -84,25 +84,10 @@ * This can be cleaned when I make some new 'mode' icons. */ -/* view3d handler codes */ -#define VIEW3D_HANDLER_BACKGROUND 1 -#define VIEW3D_HANDLER_PROPERTIES 2 -#define VIEW3D_HANDLER_OBJECT 3 -#define VIEW3D_HANDLER_PREVIEW 4 -#define VIEW3D_HANDLER_MULTIRES 5 -#define VIEW3D_HANDLER_TRANSFORM 6 -#define VIEW3D_HANDLER_GREASEPENCIL 7 -#define VIEW3D_HANDLER_BONESKETCH 8 - /* end XXX ************* */ static void do_view3d_header_buttons(bContext *C, void *arg, int event); -#define B_SCENELOCK 101 -#define B_FULL 102 -#define B_HOME 103 -#define B_VIEWBUT 104 -#define B_PERSP 105 #define B_MODESELECT 108 #define B_SEL_VERT 110 #define B_SEL_EDGE 111 @@ -110,10 +95,7 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event); #define B_MAN_TRANS 116 #define B_MAN_ROT 117 #define B_MAN_SCALE 118 -#define B_NDOF 119 #define B_MAN_MODE 120 -#define B_REDR 122 -#define B_NOP 123 /* XXX quickly ported across */ static void handle_view3d_lock(bContext *C) @@ -185,7 +167,7 @@ static int view3d_layers_exec(bContext *C, wmOperator *op) } else { v3d->lay |= (1 << 20) - 1; - } + } } else { int bit; @@ -346,10 +328,6 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event) /* watch it: if sa->win does not exist, check that when calling direct drawing routines */ switch (event) { - case B_REDR: - ED_area_tag_redraw(sa); - break; - case B_MODESELECT: WM_operator_properties_create(&props_ptr, "OBJECT_OT_mode_set"); RNA_enum_set(&props_ptr, "mode", v3d->modeselect); @@ -416,9 +394,6 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event) } ED_area_tag_redraw(sa); break; - case B_NDOF: - ED_area_tag_redraw(sa); - break; case B_MAN_MODE: ED_area_tag_redraw(sa); break; @@ -477,7 +452,7 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) const float dpi_fac = UI_DPI_FAC; int is_paint = 0; - RNA_pointer_create(&screen->id, &RNA_SpaceView3D, v3d, &v3dptr); + RNA_pointer_create(&screen->id, &RNA_SpaceView3D, v3d, &v3dptr); RNA_pointer_create(&scene->id, &RNA_ToolSettings, ts, &toolsptr); RNA_pointer_create(&scene->id, &RNA_Scene, scene, &sceneptr); diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 5bfabf4fc4a..5beeda9f220 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -40,6 +40,7 @@ struct ARegionType; struct BoundBox; struct DerivedMesh; struct Object; +struct SmokeDomainSettings; struct ViewContext; struct bAnimVizSettings; struct bContext; @@ -50,8 +51,6 @@ struct wmNDOFMotionData; struct wmOperatorType; struct wmWindowManager; -#define BL_NEAR_CLIP 0.001 - /* drawing flags: */ enum { DRAW_PICKING = (1 << 0), @@ -97,6 +96,7 @@ void VIEW3D_OT_cursor3d(struct wmOperatorType *ot); void VIEW3D_OT_manipulator(struct wmOperatorType *ot); void VIEW3D_OT_enable_manipulator(struct wmOperatorType *ot); void VIEW3D_OT_render_border(struct wmOperatorType *ot); +void VIEW3D_OT_clear_render_border(struct wmOperatorType *ot); void VIEW3D_OT_zoom_border(struct wmOperatorType *ot); void view3d_boxview_copy(ScrArea *sa, ARegion *ar); @@ -177,7 +177,7 @@ int ED_view3d_boundbox_clip(RegionView3D * rv3d, float obmat[][4], struct BoundB void view3d_smooth_view(struct bContext *C, struct View3D *v3d, struct ARegion *ar, struct Object *, struct Object *, float *ofs, float *quat, float *dist, float *lens); -void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect); /* rect: for picking */ +void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect); void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d); void fly_modal_keymap(struct wmKeyConfig *keyconf); @@ -212,7 +212,20 @@ ARegion *view3d_has_tools_region(ScrArea *sa); extern const char *view3d_context_dir[]; /* doc access */ /* draw_volume.c */ -void draw_volume(struct ARegion *ar, struct GPUTexture *tex, float min[3], float max[3], int res[3], float dx, struct GPUTexture *tex_shadow); +void draw_smoke_volume(struct SmokeDomainSettings *sds, struct Object *ob, + struct GPUTexture *tex, float min[3], float max[3], + int res[3], float dx, float base_scale, float viewnormal[3], + struct GPUTexture *tex_shadow, struct GPUTexture *tex_flame); + +//#define SMOKE_DEBUG_VELOCITY +//#define SMOKE_DEBUG_HEAT + +#ifdef SMOKE_DEBUG_VELOCITY +void draw_smoke_velocity(struct SmokeDomainSettings *domain, struct Object *ob); +#endif +#ifdef SMOKE_DEBUG_HEAT +void draw_smoke_heat(struct SmokeDomainSettings *domain, struct Object *ob); +#endif /* workaround for trivial but noticeable camera bug caused by imprecision * between view border calculation in 2D/3D space, workaround for bug [#28037]. diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c new file mode 100644 index 00000000000..b928e060ca0 --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -0,0 +1,416 @@ +/* + * ***** 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. + * + * Contributor(s): Blender Foundation, full recode and added functions + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/object/view3d_iterators.c + * \ingroup spview3d + */ + +#include "DNA_curve_types.h" +#include "DNA_lattice_types.h" +#include "DNA_meta_types.h" +#include "DNA_armature_types.h" +#include "DNA_object_types.h" + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_rect.h" + +#include "BKE_armature.h" +#include "BKE_curve.h" +#include "BKE_DerivedMesh.h" +#include "BKE_displist.h" + +#include "bmesh.h" + +#include "ED_mesh.h" +#include "ED_screen.h" +#include "ED_armature.h" +#include "ED_object.h" +#include "ED_view3d.h" + + +typedef struct foreachScreenVert_userData { + void (*func)(void *userData, BMVert *eve, const float screen_co_b[2], int index); + void *userData; + ViewContext vc; + eV3DProjTest clip_flag; +} foreachScreenVert_userData; + +/* user data structures for derived mesh callbacks */ +typedef struct foreachScreenEdge_userData { + void (*func)(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index); + void *userData; + ViewContext vc; + rctf win_rect; /* copy of: vc.ar->winx/winy, use for faster tests, minx/y will always be 0 */ + eV3DProjTest clip_flag; +} foreachScreenEdge_userData; + +typedef struct foreachScreenFace_userData { + void (*func)(void *userData, BMFace *efa, const float screen_co_b[2], int index); + void *userData; + ViewContext vc; + eV3DProjTest clip_flag; +} foreachScreenFace_userData; + + +/* Note! - foreach funcs should be called while drawing or directly after + * if not, ED_view3d_init_mats_rv3d() can be used for selection tools + * but would not give correct results with dupli's for eg. which don't + * use the object matrix in the usual way */ + +/* ------------------------------------------------------------------------ */ + +static void mesh_foreachScreenVert__mapFunc(void *userData, int index, const float co[3], + const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) +{ + foreachScreenVert_userData *data = userData; + BMVert *eve = EDBM_vert_at_index(data->vc.em, index); + + if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { + float screen_co[2]; + + if (ED_view3d_project_float_object(data->vc.ar, co, screen_co, data->clip_flag) != V3D_PROJ_RET_OK) { + return; + } + + data->func(data->userData, eve, screen_co, index); + } +} + +void mesh_foreachScreenVert( + ViewContext *vc, + void (*func)(void *userData, BMVert *eve, const float screen_co[2], int index), + void *userData, eV3DProjTest clip_flag) +{ + foreachScreenVert_userData data; + DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); + + data.vc = *vc; + data.func = func; + data.userData = userData; + data.clip_flag = clip_flag; + + if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { + ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */ + } + + EDBM_index_arrays_init(vc->em, 1, 0, 0); + dm->foreachMappedVert(dm, mesh_foreachScreenVert__mapFunc, &data); + EDBM_index_arrays_free(vc->em); + + dm->release(dm); +} + +/* ------------------------------------------------------------------------ */ + +static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, const float v0co[3], const float v1co[3]) +{ + foreachScreenEdge_userData *data = userData; + BMEdge *eed = EDBM_edge_at_index(data->vc.em, index); + + if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { + float screen_co_a[2]; + float screen_co_b[2]; + eV3DProjTest clip_flag_nowin = data->clip_flag &= ~V3D_PROJ_TEST_CLIP_WIN; + + if (ED_view3d_project_float_object(data->vc.ar, v0co, screen_co_a, clip_flag_nowin) != V3D_PROJ_RET_OK) { + return; + } + if (ED_view3d_project_float_object(data->vc.ar, v1co, screen_co_b, clip_flag_nowin) != V3D_PROJ_RET_OK) { + return; + } + + if (data->clip_flag & V3D_PROJ_TEST_CLIP_WIN) { + if (!BLI_rctf_isect_segment(&data->win_rect, screen_co_a, screen_co_b)) { + return; + } + } + + data->func(data->userData, eed, screen_co_a, screen_co_b, index); + } +} + +void mesh_foreachScreenEdge( + ViewContext *vc, + void (*func)(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index), + void *userData, eV3DProjTest clip_flag) +{ + foreachScreenEdge_userData data; + DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); + + data.vc = *vc; + + data.win_rect.xmin = 0; + data.win_rect.ymin = 0; + data.win_rect.xmax = vc->ar->winx; + data.win_rect.ymax = vc->ar->winy; + + data.func = func; + data.userData = userData; + data.clip_flag = clip_flag; + + if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { + ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */ + } + + EDBM_index_arrays_init(vc->em, 0, 1, 0); + dm->foreachMappedEdge(dm, mesh_foreachScreenEdge__mapFunc, &data); + EDBM_index_arrays_free(vc->em); + + dm->release(dm); +} + +/* ------------------------------------------------------------------------ */ + +static void mesh_foreachScreenFace__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3])) +{ + foreachScreenFace_userData *data = userData; + BMFace *efa = EDBM_face_at_index(data->vc.em, index); + + if (efa && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + float screen_co[2]; + if (ED_view3d_project_float_object(data->vc.ar, cent, screen_co, data->clip_flag) == V3D_PROJ_RET_OK) { + data->func(data->userData, efa, screen_co, index); + } + } +} + +void mesh_foreachScreenFace( + ViewContext *vc, + void (*func)(void *userData, BMFace *efa, const float screen_co_b[2], int index), + void *userData, const eV3DProjTest clip_flag) +{ + foreachScreenFace_userData data; + DerivedMesh *dm = editbmesh_get_derived_cage(vc->scene, vc->obedit, vc->em, CD_MASK_BAREMESH); + + data.vc = *vc; + data.func = func; + data.userData = userData; + data.clip_flag = clip_flag; + + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + + EDBM_index_arrays_init(vc->em, 0, 0, 1); + dm->foreachMappedFaceCenter(dm, mesh_foreachScreenFace__mapFunc, &data); + EDBM_index_arrays_free(vc->em); + + dm->release(dm); +} + +/* ------------------------------------------------------------------------ */ + +void nurbs_foreachScreenVert( + ViewContext *vc, + void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co_b[2]), + void *userData, const eV3DProjTest clip_flag) +{ + Curve *cu = vc->obedit->data; + Nurb *nu; + int i; + ListBase *nurbs = BKE_curve_editNurbs_get(cu); + + if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { + ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */ + } + + for (nu = nurbs->first; nu; nu = nu->next) { + if (nu->type == CU_BEZIER) { + for (i = 0; i < nu->pntsu; i++) { + BezTriple *bezt = &nu->bezt[i]; + + if (bezt->hide == 0) { + float screen_co[2]; + + if (cu->drawflag & CU_HIDE_HANDLES) { + if (ED_view3d_project_float_object(vc->ar, bezt->vec[1], screen_co, + V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_OK) + { + func(userData, nu, NULL, bezt, 1, screen_co); + } + } + else { + if (ED_view3d_project_float_object(vc->ar, bezt->vec[0], screen_co, + V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_OK) + { + func(userData, nu, NULL, bezt, 0, screen_co); + } + if (ED_view3d_project_float_object(vc->ar, bezt->vec[1], screen_co, + V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_OK) + { + func(userData, nu, NULL, bezt, 1, screen_co); + } + if (ED_view3d_project_float_object(vc->ar, bezt->vec[2], screen_co, + V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_OK) + { + func(userData, nu, NULL, bezt, 2, screen_co); + } + } + } + } + } + else { + for (i = 0; i < nu->pntsu * nu->pntsv; i++) { + BPoint *bp = &nu->bp[i]; + + if (bp->hide == 0) { + float screen_co[2]; + if (ED_view3d_project_float_object(vc->ar, bp->vec, screen_co, + V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_OK) + { + func(userData, nu, bp, NULL, -1, screen_co); + } + } + } + } + } +} + +/* ------------------------------------------------------------------------ */ + +/* ED_view3d_init_mats_rv3d must be called first */ +void mball_foreachScreenElem( + struct ViewContext *vc, + void (*func)(void *userData, struct MetaElem *ml, const float screen_co_b[2]), + void *userData, const eV3DProjTest clip_flag) +{ + MetaBall *mb = (MetaBall *)vc->obedit->data; + MetaElem *ml; + + for (ml = mb->editelems->first; ml; ml = ml->next) { + float screen_co[2]; + if (ED_view3d_project_float_object(vc->ar, &ml->x, screen_co, clip_flag) == V3D_PROJ_RET_OK) { + func(userData, ml, screen_co); + } + } +} + +/* ------------------------------------------------------------------------ */ + +void lattice_foreachScreenVert( + ViewContext *vc, + void (*func)(void *userData, BPoint *bp, const float screen_co[2]), + void *userData, const eV3DProjTest clip_flag) +{ + Object *obedit = vc->obedit; + Lattice *lt = obedit->data; + BPoint *bp = lt->editlatt->latt->def; + DispList *dl = BKE_displist_find(&obedit->disp, DL_VERTS); + float *co = dl ? dl->verts : NULL; + int i, N = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; + + if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { + ED_view3d_clipping_local(vc->rv3d, obedit->obmat); /* for local clipping lookups */ + } + + for (i = 0; i < N; i++, bp++, co += 3) { + if (bp->hide == 0) { + float screen_co[2]; + if (ED_view3d_project_float_object(vc->ar, dl ? co : bp->vec, screen_co, clip_flag) == V3D_PROJ_RET_OK) { + func(userData, bp, screen_co); + } + } + } +} + +/* ------------------------------------------------------------------------ */ + +/* ED_view3d_init_mats_rv3d must be called first */ +void armature_foreachScreenBone( + struct ViewContext *vc, + void (*func)(void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2]), + void *userData, const eV3DProjTest clip_flag) +{ + bArmature *arm = vc->obedit->data; + EditBone *ebone; + + for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { + if (EBONE_VISIBLE(arm, ebone)) { + float screen_co_a[2], screen_co_b[2]; + int points_proj_tot = 0; + + /* project head location to screenspace */ + if (ED_view3d_project_float_object(vc->ar, ebone->head, screen_co_a, clip_flag) == V3D_PROJ_RET_OK) { + points_proj_tot++; + } + else { + screen_co_a[0] = IS_CLIPPED; /* weak */ + /* screen_co_a[1]: intentionally dont set this so we get errors on misuse */ + } + + /* project tail location to screenspace */ + if (ED_view3d_project_float_object(vc->ar, ebone->tail, screen_co_b, clip_flag) == V3D_PROJ_RET_OK) { + points_proj_tot++; + } + else { + screen_co_b[0] = IS_CLIPPED; /* weak */ + /* screen_co_b[1]: intentionally dont set this so we get errors on misuse */ + } + + if (points_proj_tot) { /* at least one point's projection worked */ + func(userData, ebone, screen_co_a, screen_co_b); + } + } + } +} + +/* ------------------------------------------------------------------------ */ + +/* ED_view3d_init_mats_rv3d must be called first */ +/* almost _exact_ copy of #armature_foreachScreenBone */ +void pose_foreachScreenBone( + struct ViewContext *vc, + void (*func)(void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2]), + void *userData, const eV3DProjTest clip_flag) +{ + bArmature *arm = vc->obact->data; + bPose *pose = vc->obact->pose; + bPoseChannel *pchan; + + for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { + if (PBONE_VISIBLE(arm, pchan->bone)) { + float screen_co_a[2], screen_co_b[2]; + int points_proj_tot = 0; + + /* project head location to screenspace */ + if (ED_view3d_project_float_object(vc->ar, pchan->pose_head, screen_co_a, clip_flag) == V3D_PROJ_RET_OK) { + points_proj_tot++; + } + else { + screen_co_a[0] = IS_CLIPPED; /* weak */ + /* screen_co_a[1]: intentionally dont set this so we get errors on misuse */ + } + + /* project tail location to screenspace */ + if (ED_view3d_project_float_object(vc->ar, pchan->pose_tail, screen_co_b, clip_flag) == V3D_PROJ_RET_OK) { + points_proj_tot++; + } + else { + screen_co_b[0] = IS_CLIPPED; /* weak */ + /* screen_co_b[1]: intentionally dont set this so we get errors on misuse */ + } + + if (points_proj_tot) { /* at least one point's projection worked */ + func(userData, pchan, screen_co_a, screen_co_b); + } + } + } +} diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 14c02c2357e..73f1563417c 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -83,6 +83,7 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_select_circle); WM_operatortype_append(VIEW3D_OT_smoothview); WM_operatortype_append(VIEW3D_OT_render_border); + WM_operatortype_append(VIEW3D_OT_clear_render_border); WM_operatortype_append(VIEW3D_OT_zoom_border); WM_operatortype_append(VIEW3D_OT_manipulator); WM_operatortype_append(VIEW3D_OT_enable_manipulator); @@ -136,8 +137,10 @@ void view3d_keymap(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "VIEW3D_OT_move", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0); WM_keymap_verify_item(keymap, "VIEW3D_OT_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0); WM_keymap_verify_item(keymap, "VIEW3D_OT_dolly", MIDDLEMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0); - WM_keymap_verify_item(keymap, "VIEW3D_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0); - WM_keymap_verify_item(keymap, "VIEW3D_OT_view_center_cursor", PADPERIOD, KM_PRESS, KM_CTRL, 0); + kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", PADPERIOD, KM_PRESS, KM_CTRL, 0); + RNA_boolean_set(kmi->ptr, "use_all_regions", TRUE); + kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "use_all_regions", FALSE); WM_keymap_verify_item(keymap, "VIEW3D_OT_view_lock_to_active", PADPERIOD, KM_PRESS, KM_SHIFT, 0); WM_keymap_verify_item(keymap, "VIEW3D_OT_view_lock_clear", PADPERIOD, KM_PRESS, KM_ALT, 0); @@ -169,6 +172,9 @@ void view3d_keymap(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "center", FALSE); /* only without camera view */ + kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", HOMEKEY, KM_PRESS, KM_CTRL, 0); + RNA_boolean_set(kmi->ptr, "use_all_regions", TRUE); + RNA_boolean_set(kmi->ptr, "center", FALSE); /* only without camera view */ kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", CKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "center", TRUE); @@ -340,7 +346,13 @@ void view3d_keymap(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "VIEW3D_OT_clip_border", BKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "VIEW3D_OT_zoom_border", BKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "VIEW3D_OT_render_border", BKEY, KM_PRESS, KM_SHIFT, 0); + + kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_render_border", BKEY, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "camera_only", TRUE); + kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_render_border", BKEY, KM_PRESS, KM_CTRL, 0); + RNA_boolean_set(kmi->ptr, "camera_only", FALSE); + + WM_keymap_add_item(keymap, "VIEW3D_OT_clear_render_border", BKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); WM_keymap_add_item(keymap, "VIEW3D_OT_camera_to_view", PAD0, KM_PRESS, KM_ALT | KM_CTRL, 0); WM_keymap_add_item(keymap, "VIEW3D_OT_object_as_camera", PAD0, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c new file mode 100644 index 00000000000..6ba05abae9a --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -0,0 +1,493 @@ +/* + * ***** 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) 2008 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/view3d_project.c + * \ingroup spview3d + */ + +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_scene_types.h" +#include "DNA_view3d_types.h" + +#include "BLO_sys_types.h" /* int64_t */ + +#include "BIF_gl.h" /* bglMats */ +#include "BIF_glutil.h" /* bglMats */ + +#include "BLI_math_vector.h" + +#include "ED_view3d.h" /* own include */ + +#define BL_NEAR_CLIP 0.001 + +/* Non Clipping Projection Functions + * ********************************* */ + +/** + * \note use #ED_view3d_ob_project_mat_get to get the projection matrix + */ +void ED_view3d_project_float_v2_m4(const ARegion *ar, const float co[3], float r_co[2], float mat[4][4]) +{ + float vec4[4]; + + copy_v3_v3(vec4, co); + vec4[3] = 1.0; + /* r_co[0] = IS_CLIPPED; */ /* always overwritten */ + + mul_m4_v4(mat, vec4); + + if (vec4[3] > FLT_EPSILON) { + r_co[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3]; + r_co[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3]; + } + else { + zero_v2(r_co); + } +} + +/** + * \note use #ED_view3d_ob_project_mat_get to get projecting mat + */ +void ED_view3d_project_float_v3_m4(ARegion *ar, const float vec[3], float r_co[3], float mat[4][4]) +{ + float vec4[4]; + + copy_v3_v3(vec4, vec); + vec4[3] = 1.0; + /* r_co[0] = IS_CLIPPED; */ /* always overwritten */ + + mul_m4_v4(mat, vec4); + + if (vec4[3] > FLT_EPSILON) { + r_co[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3]; + r_co[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3]; + r_co[2] = vec4[2] / vec4[3]; + } + else { + zero_v3(r_co); + } +} + + +/* Clipping Projection Functions + * ***************************** */ + +eV3DProjStatus ED_view3d_project_base(struct ARegion *ar, struct Base *base) +{ + eV3DProjStatus ret = ED_view3d_project_short_global(ar, base->object->obmat[3], &base->sx, V3D_PROJ_TEST_CLIP_DEFAULT); + + if (ret != V3D_PROJ_RET_OK) { + base->sx = IS_CLIPPED; + base->sy = 0; + } + + return ret; +} + +/* perspmat is typically... + * - 'rv3d->perspmat', is_local == FALSE + * - 'rv3d->perspmatob', is_local == TRUE + */ +static eV3DProjStatus ed_view3d_project__internal(ARegion *ar, + float perspmat[4][4], const int is_local, /* normally hidden */ + const float co[3], float r_co[2], const eV3DProjTest flag) +{ + float fx, fy, vec4[4]; + + /* check for bad flags */ + BLI_assert((flag & V3D_PROJ_TEST_ALL) == flag); + + if (flag & V3D_PROJ_TEST_CLIP_BB) { + RegionView3D *rv3d = ar->regiondata; + if (rv3d->rflag & RV3D_CLIPPING) { + if (ED_view3d_clipping_test(rv3d, co, is_local)) { + return V3D_PROJ_RET_CLIP_BB; + } + } + } + + copy_v3_v3(vec4, co); + vec4[3] = 1.0; + mul_m4_v4(perspmat, vec4); + + if (vec4[3] > (float)BL_NEAR_CLIP) { + fx = ((float)ar->winx / 2.0f) * (1.0f + vec4[0] / vec4[3]); + if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fx > 0 && fx < ar->winx)) { + fy = ((float)ar->winy / 2.0f) * (1.0f + vec4[1] / vec4[3]); + if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fy > 0.0f && fy < (float)ar->winy)) { + r_co[0] = (short)floor(fx); + r_co[1] = (short)floor(fy); + } + else { + return V3D_PROJ_RET_CLIP_WIN; + } + } + else { + return V3D_PROJ_RET_CLIP_WIN; + } + } + else { + return V3D_PROJ_RET_CLIP_NEAR; + } + + return V3D_PROJ_RET_OK; +} + +eV3DProjStatus ED_view3d_project_short_ex(ARegion *ar, float perspmat[4][4], const int is_local, + const float co[3], short r_co[2], const eV3DProjTest flag) +{ + float tvec[2]; + eV3DProjStatus ret = ed_view3d_project__internal(ar, perspmat, is_local, co, tvec, flag); + if (ret == V3D_PROJ_RET_OK) { + if ((tvec[0] > -32700.0f && tvec[0] < 32700.0f) && + (tvec[1] > -32700.0f && tvec[1] < 32700.0f)) + { + r_co[0] = (short)floor(tvec[0]); + r_co[1] = (short)floor(tvec[1]); + } + else { + ret = V3D_PROJ_RET_OVERFLOW; + } + } + return ret; +} + +eV3DProjStatus ED_view3d_project_int_ex(ARegion *ar, float perspmat[4][4], const int is_local, + const float co[3], int r_co[2], const eV3DProjTest flag) +{ + float tvec[2]; + eV3DProjStatus ret = ed_view3d_project__internal(ar, perspmat, is_local, co, tvec, flag); + if (ret == V3D_PROJ_RET_OK) { + if ((tvec[0] > -2140000000.0f && tvec[0] < 2140000000.0f) && + (tvec[1] > -2140000000.0f && tvec[1] < 2140000000.0f)) + { + r_co[0] = (int)floor(tvec[0]); + r_co[1] = (int)floor(tvec[1]); + } + else { + ret = V3D_PROJ_RET_OVERFLOW; + } + } + return ret; +} + +eV3DProjStatus ED_view3d_project_float_ex(ARegion *ar, float perspmat[4][4], const int is_local, + const float co[3], float r_co[2], const eV3DProjTest flag) +{ + float tvec[2]; + eV3DProjStatus ret = ed_view3d_project__internal(ar, perspmat, is_local, co, tvec, flag); + if (ret == V3D_PROJ_RET_OK) { + if (finite(tvec[0]) && + finite(tvec[1])) + { + copy_v2_v2(r_co, tvec); + } + else { + ret = V3D_PROJ_RET_OVERFLOW; + } + } + return ret; +} + +/* --- short --- */ +eV3DProjStatus ED_view3d_project_short_global(ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag) +{ + RegionView3D *rv3d = ar->regiondata; + return ED_view3d_project_short_ex(ar, rv3d->persmat, FALSE, co, r_co, flag); +} +/* object space, use ED_view3d_init_mats_rv3d before calling */ +eV3DProjStatus ED_view3d_project_short_object(ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag) +{ + RegionView3D *rv3d = ar->regiondata; + return ED_view3d_project_short_ex(ar, rv3d->persmatob, TRUE, co, r_co, flag); +} + +/* --- int --- */ +eV3DProjStatus ED_view3d_project_int_global(ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag) +{ + RegionView3D *rv3d = ar->regiondata; + return ED_view3d_project_int_ex(ar, rv3d->persmat, FALSE, co, r_co, flag); +} +/* object space, use ED_view3d_init_mats_rv3d before calling */ +eV3DProjStatus ED_view3d_project_int_object(ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag) +{ + RegionView3D *rv3d = ar->regiondata; + return ED_view3d_project_int_ex(ar, rv3d->persmatob, TRUE, co, r_co, flag); +} + +/* --- float --- */ +eV3DProjStatus ED_view3d_project_float_global(ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag) +{ + RegionView3D *rv3d = ar->regiondata; + return ED_view3d_project_float_ex(ar, rv3d->persmat, FALSE, co, r_co, flag); +} +/* object space, use ED_view3d_init_mats_rv3d before calling */ +eV3DProjStatus ED_view3d_project_float_object(ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag) +{ + RegionView3D *rv3d = ar->regiondata; + return ED_view3d_project_float_ex(ar, rv3d->persmatob, TRUE, co, r_co, flag); +} + + + +/* More Generic Window/Ray/Vector projection functions + * *************************************************** */ + +/* odd function, need to document better */ +int initgrabz(RegionView3D *rv3d, float x, float y, float z) +{ + int flip = FALSE; + if (rv3d == NULL) return flip; + rv3d->zfac = rv3d->persmat[0][3] * x + rv3d->persmat[1][3] * y + rv3d->persmat[2][3] * z + rv3d->persmat[3][3]; + if (rv3d->zfac < 0.0f) + flip = TRUE; + /* if x,y,z is exactly the viewport offset, zfac is 0 and we don't want that + * (accounting for near zero values) + */ + if (rv3d->zfac < 1.e-6f && rv3d->zfac > -1.e-6f) rv3d->zfac = 1.0f; + + /* Negative zfac means x, y, z was behind the camera (in perspective). + * This gives flipped directions, so revert back to ok default case. + */ + /* NOTE: I've changed this to flip zfac to be positive again for now so that GPencil draws ok + * Aligorith, 2009Aug31 */ + //if (rv3d->zfac < 0.0f) rv3d->zfac = 1.0f; + if (rv3d->zfac < 0.0f) rv3d->zfac = -rv3d->zfac; + + return flip; +} + +/** + * Calculate a 3d viewpoint and direction vector from 2d window coordinates. + * This ray_start is located at the viewpoint, ray_normal is the direction towards mval. + * ray_start is clipped by the view near limit so points in front of it are always in view. + * In orthographic view the resulting ray_normal will match the view vector. + * \param ar The region (used for the window width and height). + * \param v3d The 3d viewport (used for near clipping value). + * \param mval The area relative 2d location (such as event->mval, converted into float[2]). + * \param ray_start The world-space starting point of the segment. + * \param ray_normal The normalized world-space direction of towards mval. + */ +void ED_view3d_win_to_ray(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_normal[3]) +{ + float ray_end[3]; + + ED_view3d_win_to_segment_clip(ar, v3d, mval, ray_start, ray_end); + sub_v3_v3v3(ray_normal, ray_end, ray_start); + normalize_v3(ray_normal); +} + +/** + * Calculate a normalized 3d direction vector from the viewpoint towards a global location. + * In orthographic view the resulting vector will match the view vector. + * \param rv3d The region (used for the window width and height). + * \param coord The world-space location. + * \param vec The resulting normalized vector. + */ +void ED_view3d_global_to_vector(RegionView3D *rv3d, const float coord[3], float vec[3]) +{ + if (rv3d->is_persp) { + float p1[4], p2[4]; + + copy_v3_v3(p1, coord); + p1[3] = 1.0f; + copy_v3_v3(p2, p1); + p2[3] = 1.0f; + mul_m4_v4(rv3d->viewmat, p2); + + mul_v3_fl(p2, 2.0f); + + mul_m4_v4(rv3d->viewinv, p2); + + sub_v3_v3v3(vec, p1, p2); + } + else { + copy_v3_v3(vec, rv3d->viewinv[2]); + } + normalize_v3(vec); +} + +/** + * Calculate a 3d location from 2d window coordinates. + * \param ar The region (used for the window width and height). + * \param depth_pt The reference location used to calculate the Z depth. + * \param mval The area relative location (such as event->mval converted to floats). + * \param out The resulting world-space location. + */ +void ED_view3d_win_to_3d(ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]) +{ + RegionView3D *rv3d = ar->regiondata; + + float line_sta[3]; + float line_end[3]; + + if (rv3d->is_persp) { + float mousevec[3]; + copy_v3_v3(line_sta, rv3d->viewinv[3]); + ED_view3d_win_to_vector(ar, mval, mousevec); + add_v3_v3v3(line_end, line_sta, mousevec); + + if (isect_line_plane_v3(out, line_sta, line_end, depth_pt, rv3d->viewinv[2], TRUE) == 0) { + /* highly unlikely to ever happen, mouse vec paralelle with view plane */ + zero_v3(out); + } + } + else { + const float dx = (2.0f * mval[0] / (float)ar->winx) - 1.0f; + const float dy = (2.0f * mval[1] / (float)ar->winy) - 1.0f; + line_sta[0] = (rv3d->persinv[0][0] * dx) + (rv3d->persinv[1][0] * dy) + rv3d->viewinv[3][0]; + line_sta[1] = (rv3d->persinv[0][1] * dx) + (rv3d->persinv[1][1] * dy) + rv3d->viewinv[3][1]; + line_sta[2] = (rv3d->persinv[0][2] * dx) + (rv3d->persinv[1][2] * dy) + rv3d->viewinv[3][2]; + + add_v3_v3v3(line_end, line_sta, rv3d->viewinv[2]); + closest_to_line_v3(out, depth_pt, line_sta, line_end); + } +} + +/** + * Calculate a 3d difference vector from 2d window offset. + * note that initgrabz() must be called first to determine + * the depth used to calculate the delta. + * \param ar The region (used for the window width and height). + * \param mval The area relative 2d difference (such as event->mval[0] - other_x). + * \param out The resulting world-space delta. + */ +void ED_view3d_win_to_delta(ARegion *ar, const float mval[2], float out[3]) +{ + RegionView3D *rv3d = ar->regiondata; + float dx, dy; + + dx = 2.0f * mval[0] * rv3d->zfac / ar->winx; + dy = 2.0f * mval[1] * rv3d->zfac / ar->winy; + + out[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy); + out[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy); + out[2] = (rv3d->persinv[0][2] * dx + rv3d->persinv[1][2] * dy); +} + +/** + * Calculate a 3d direction vector from 2d window coordinates. + * This direction vector starts and the view in the direction of the 2d window coordinates. + * In orthographic view all window coordinates yield the same vector. + * + * \note doesn't rely on initgrabz + * for perspective view, get the vector direction to + * the mouse cursor as a normalized vector. + * + * \param ar The region (used for the window width and height). + * \param mval The area relative 2d location (such as event->mval converted to floats). + * \param out The resulting normalized world-space direction vector. + */ +void ED_view3d_win_to_vector(ARegion *ar, const float mval[2], float out[3]) +{ + RegionView3D *rv3d = ar->regiondata; + + if (rv3d->is_persp) { + out[0] = 2.0f * (mval[0] / ar->winx) - 1.0f; + out[1] = 2.0f * (mval[1] / ar->winy) - 1.0f; + out[2] = -0.5f; + mul_project_m4_v3(rv3d->persinv, out); + sub_v3_v3(out, rv3d->viewinv[3]); + } + else { + copy_v3_v3(out, rv3d->viewinv[2]); + } + normalize_v3(out); +} + +/** + * Calculate a 3d segment from 2d window coordinates. + * This ray_start is located at the viewpoint, ray_end is a far point. + * ray_start and ray_end are clipped by the view near and far limits + * so points along this line are always in view. + * In orthographic view all resulting segments will be parallel. + * \param ar The region (used for the window width and height). + * \param v3d The 3d viewport (used for near and far clipping range). + * \param mval The area relative 2d location (such as event->mval, converted into float[2]). + * \param ray_start The world-space starting point of the segment. + * \param ray_end The world-space end point of the segment. + */ +void ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]) +{ + RegionView3D *rv3d = ar->regiondata; + + if (rv3d->is_persp) { + float vec[3]; + ED_view3d_win_to_vector(ar, mval, vec); + + copy_v3_v3(ray_start, rv3d->viewinv[3]); + madd_v3_v3v3fl(ray_start, rv3d->viewinv[3], vec, v3d->near); + madd_v3_v3v3fl(ray_end, rv3d->viewinv[3], vec, v3d->far); + } + else { + float vec[4]; + vec[0] = 2.0f * mval[0] / ar->winx - 1; + vec[1] = 2.0f * mval[1] / ar->winy - 1; + vec[2] = 0.0f; + vec[3] = 1.0f; + + mul_m4_v4(rv3d->persinv, vec); + + madd_v3_v3v3fl(ray_start, vec, rv3d->viewinv[2], 1000.0f); + madd_v3_v3v3fl(ray_end, vec, rv3d->viewinv[2], -1000.0f); + } + + /* clipping */ + if (rv3d->rflag & RV3D_CLIPPING) { + int a; + for (a = 0; a < 4; a++) { + clip_line_plane(ray_start, ray_end, rv3d->clip[a]); + } + } +} + + +/* Utility functions for projection + * ******************************** */ + +void ED_view3d_ob_project_mat_get(RegionView3D *rv3d, Object *ob, float pmat[4][4]) +{ + float vmat[4][4]; + + mult_m4_m4m4(vmat, rv3d->viewmat, ob->obmat); + mult_m4_m4m4(pmat, rv3d->winmat, vmat); +} + +/** + * Uses window coordinates (x,y) and depth component z to find a point in + * modelspace */ +void ED_view3d_unproject(bglMats *mats, float out[3], const float x, const float y, const float z) +{ + double ux, uy, uz; + + gluUnProject(x, y, z, mats->modelview, mats->projection, + (GLint *)mats->viewport, &ux, &uy, &uz); + + out[0] = ux; + out[1] = uy; + out[2] = uz; +} diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 166a62562fd..43626b058d6 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -61,13 +61,14 @@ #include "IMB_imbuf.h" #include "BKE_global.h" -#include "BKE_context.h" -#include "BKE_paint.h" #include "BKE_armature.h" +#include "BKE_context.h" #include "BKE_depsgraph.h" -#include "BKE_tessmesh.h" +#include "BKE_mball.h" #include "BKE_movieclip.h" #include "BKE_object.h" +#include "BKE_paint.h" +#include "BKE_tessmesh.h" #include "BKE_tracking.h" @@ -110,15 +111,16 @@ int view3d_get_view_aligned_coordinate(ViewContext *vc, float fp[3], const int m { float dvec[3]; int mval_cpy[2]; + eV3DProjStatus ret; mval_cpy[0] = mval[0]; mval_cpy[1] = mval[1]; - project_int_noclip(vc->ar, fp, mval_cpy); + ret = ED_view3d_project_int_global(vc->ar, fp, mval_cpy, V3D_PROJ_TEST_NOP); initgrabz(vc->rv3d, fp[0], fp[1], fp[2]); - if (mval_cpy[0] != IS_CLIPPED) { + if (ret == V3D_PROJ_RET_OK) { const float mval_f[2] = {(float)(mval_cpy[0] - mval[0]), (float)(mval_cpy[1] - mval[1])}; ED_view3d_win_to_delta(vc->ar, mval_f, dvec); @@ -163,7 +165,7 @@ void view3d_get_transformation(const ARegion *ar, RegionView3D *rv3d, Object *ob mats->viewport[0] = ar->winrct.xmin; mats->viewport[1] = ar->winrct.ymin; mats->viewport[2] = ar->winx; - mats->viewport[3] = ar->winy; + mats->viewport[3] = ar->winy; } /* ********************** view3d_select: selection manipulations ********************* */ @@ -255,10 +257,39 @@ static void edbm_backbuf_check_and_select_tfaces(Mesh *me, int select) typedef struct LassoSelectUserData { ViewContext *vc; - rcti *rect; - int (*mcords)[2], moves, select, pass, done; + const rcti *rect; + const rctf *rect_fl; + rctf _rect_fl; + const int (*mcords)[2]; + int moves; + int select; + + /* runtime */ + int pass; + int is_done; + int is_change; } LassoSelectUserData; +static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data, + ViewContext *vc, const rcti *rect, const int (*mcords)[2], + const int moves, const int select) +{ + r_data->vc = vc; + + r_data->rect = rect; + r_data->rect_fl = &r_data->_rect_fl; + BLI_rctf_rcti_copy(&r_data->_rect_fl, rect); + + r_data->mcords = mcords; + r_data->moves = moves; + r_data->select = select; + + /* runtime */ + r_data->pass = 0; + r_data->is_done = FALSE; + r_data->is_change = FALSE; +} + static int view3d_selectable_data(bContext *C) { Object *ob = CTX_data_active_object(C); @@ -289,29 +320,29 @@ static int view3d_selectable_data(bContext *C) /* helper also for borderselect */ -static int edge_fully_inside_rect(rcti *rect, short x1, short y1, short x2, short y2) +static int edge_fully_inside_rect(const rctf *rect, const float v1[2], const float v2[2]) { - return BLI_rcti_isect_pt(rect, x1, y1) && BLI_rcti_isect_pt(rect, x2, y2); + return BLI_rctf_isect_pt_v(rect, v1) && BLI_rctf_isect_pt_v(rect, v2); } -static int edge_inside_rect(rcti *rect, short x1, short y1, short x2, short y2) +static int edge_inside_rect(const rctf *rect, const float v1[2], const float v2[2]) { int d1, d2, d3, d4; /* check points in rect */ - if (edge_fully_inside_rect(rect, x1, y1, x2, y2)) return 1; + if (edge_fully_inside_rect(rect, v1, v2)) return 1; /* check points completely out rect */ - if (x1 < rect->xmin && x2 < rect->xmin) return 0; - if (x1 > rect->xmax && x2 > rect->xmax) return 0; - if (y1 < rect->ymin && y2 < rect->ymin) return 0; - if (y1 > rect->ymax && y2 > rect->ymax) return 0; + if (v1[0] < rect->xmin && v2[0] < rect->xmin) return 0; + if (v1[0] > rect->xmax && v2[0] > rect->xmax) return 0; + if (v1[1] < rect->ymin && v2[1] < rect->ymin) return 0; + if (v1[1] > rect->ymax && v2[1] > rect->ymax) return 0; /* simple check lines intersecting. */ - d1 = (y1 - y2) * (x1 - rect->xmin) + (x2 - x1) * (y1 - rect->ymin); - d2 = (y1 - y2) * (x1 - rect->xmin) + (x2 - x1) * (y1 - rect->ymax); - d3 = (y1 - y2) * (x1 - rect->xmax) + (x2 - x1) * (y1 - rect->ymax); - d4 = (y1 - y2) * (x1 - rect->xmax) + (x2 - x1) * (y1 - rect->ymin); + d1 = (v1[1] - v2[1]) * (v1[0] - rect->xmin) + (v2[0] - v1[0]) * (v1[1] - rect->ymin); + d2 = (v1[1] - v2[1]) * (v1[0] - rect->xmin) + (v2[0] - v1[0]) * (v1[1] - rect->ymax); + d3 = (v1[1] - v2[1]) * (v1[0] - rect->xmax) + (v2[0] - v1[0]) * (v1[1] - rect->ymax); + d4 = (v1[1] - v2[1]) * (v1[0] - rect->xmax) + (v2[0] - v1[0]) * (v1[1] - rect->ymin); if (d1 < 0 && d2 < 0 && d3 < 0 && d4 < 0) return 0; if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0) return 0; @@ -319,40 +350,79 @@ static int edge_inside_rect(rcti *rect, short x1, short y1, short x2, short y2) return 1; } - -#define MOVES_GESTURE 50 -#define MOVES_LASSO 500 - - -/* warning; lasso select with backbuffer-check draws in backbuf with persp(PERSP_WIN) - * and returns with persp(PERSP_VIEW). After lasso select backbuf is not OK - */ -static void do_lasso_select_pose(ViewContext *vc, Object *ob, int mcords[][2], short moves, short select) +static void do_lasso_select_pose__doSelectBone(void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2]) { - bPoseChannel *pchan; - float vec[3]; - int sco1[2], sco2[2]; - bArmature *arm = ob->data; - - if ((ob->type != OB_ARMATURE) || (ob->pose == NULL)) return; + LassoSelectUserData *data = userData; + bArmature *arm = data->vc->obact->data; - for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { - if (PBONE_VISIBLE(arm, pchan->bone) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0) { - mul_v3_m4v3(vec, ob->obmat, pchan->pose_head); - project_int(vc->ar, vec, sco1); - mul_v3_m4v3(vec, ob->obmat, pchan->pose_tail); - project_int(vc->ar, vec, sco2); - - if (BLI_lasso_is_edge_inside(mcords, moves, sco1[0], sco1[1], sco2[0], sco2[1], IS_CLIPPED)) { - if (select) pchan->bone->flag |= BONE_SELECTED; - else pchan->bone->flag &= ~BONE_SELECTED; + if (PBONE_SELECTABLE(arm, pchan->bone)) { + int is_point_done = FALSE; + int points_proj_tot = 0; + + const int x0 = screen_co_a[0]; + const int y0 = screen_co_a[1]; + const int x1 = screen_co_b[0]; + const int y1 = screen_co_b[1]; + + /* project head location to screenspace */ + if (x0 != IS_CLIPPED) { + points_proj_tot++; + if (BLI_rcti_isect_pt(data->rect, x0, y0) && + BLI_lasso_is_point_inside(data->mcords, data->moves, x0, y0, INT_MAX)) + { + is_point_done = TRUE; } } + + /* project tail location to screenspace */ + if (x1 != IS_CLIPPED) { + points_proj_tot++; + if (BLI_rcti_isect_pt(data->rect, x1, y1) && + BLI_lasso_is_point_inside(data->mcords, data->moves, x1, y1, INT_MAX)) + { + is_point_done = TRUE; + } + } + + /* if one of points selected, we skip the bone itself */ + if ((is_point_done == TRUE) || + ((is_point_done == FALSE) && (points_proj_tot == 2) && + BLI_lasso_is_edge_inside(data->mcords, data->moves, x0, y0, x1, y1, INT_MAX))) + { + if (data->select) pchan->bone->flag |= BONE_SELECTED; + else pchan->bone->flag &= ~BONE_SELECTED; + data->is_change = TRUE; + } + data->is_change |= is_point_done; } +} +static void do_lasso_select_pose(ViewContext *vc, Object *ob, const int mcords[][2], short moves, short select) +{ + ViewContext vc_tmp; + LassoSelectUserData data; + rcti rect; - if (arm->flag & ARM_HAS_VIZ_DEPS) { - /* mask modifier ('armature' mode), etc. */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + if ((ob->type != OB_ARMATURE) || (ob->pose == NULL)) { + return; + } + + vc_tmp = *vc; + vc_tmp.obact = ob; + + BLI_lasso_boundbox(&rect, mcords, moves); + + view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select); + + ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); + + pose_foreachScreenBone(&vc_tmp, do_lasso_select_pose__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + + if (data.is_change) { + bArmature *arm = ob->data; + if (arm->flag & ARM_HAS_VIZ_DEPS) { + /* mask modifier ('armature' mode), etc. */ + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + } } } @@ -367,7 +437,7 @@ static void object_deselect_all_visible(Scene *scene, View3D *v3d) } } -static void do_lasso_select_objects(ViewContext *vc, int mcords[][2], short moves, short extend, short select) +static void do_lasso_select_objects(ViewContext *vc, const int mcords[][2], const short moves, short extend, short select) { Base *base; @@ -376,7 +446,7 @@ static void do_lasso_select_objects(ViewContext *vc, int mcords[][2], short move for (base = vc->scene->base.first; base; base = base->next) { if (BASE_SELECTABLE(vc->v3d, base)) { /* use this to avoid un-needed lasso lookups */ - project_short(vc->ar, base->object->obmat[3], &base->sx); + ED_view3d_project_base(vc->ar, base); if (BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED)) { if (select) ED_base_object_select(base, BA_SELECT); @@ -390,28 +460,33 @@ static void do_lasso_select_objects(ViewContext *vc, int mcords[][2], short move } } -static void do_lasso_select_mesh__doSelectVert(void *userData, BMVert *eve, int x, int y, int UNUSED(index)) +static void do_lasso_select_mesh__doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index)) { LassoSelectUserData *data = userData; - if (BLI_rcti_isect_pt(data->rect, x, y) && - BLI_lasso_is_point_inside(data->mcords, data->moves, x, y, IS_CLIPPED)) + if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)) { BM_vert_select_set(data->vc->em->bm, eve, data->select); } } -static void do_lasso_select_mesh__doSelectEdge(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index) +static void do_lasso_select_mesh__doSelectEdge(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) { LassoSelectUserData *data = userData; if (EDBM_backbuf_check(bm_solidoffs + index)) { + const int x0 = screen_co_a[0]; + const int y0 = screen_co_a[1]; + const int x1 = screen_co_b[0]; + const int y1 = screen_co_b[1]; + if (data->pass == 0) { - if (edge_fully_inside_rect(data->rect, x0, y0, x1, y1) && + if (edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) && BLI_lasso_is_point_inside(data->mcords, data->moves, x0, y0, IS_CLIPPED) && BLI_lasso_is_point_inside(data->mcords, data->moves, x1, y1, IS_CLIPPED)) { BM_edge_select_set(data->vc->em->bm, eed, data->select); - data->done = TRUE; + data->is_done = TRUE; } } else { @@ -421,36 +496,30 @@ static void do_lasso_select_mesh__doSelectEdge(void *userData, BMEdge *eed, int } } } -static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, int x, int y, int UNUSED(index)) +static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index)) { LassoSelectUserData *data = userData; - if (BLI_rcti_isect_pt(data->rect, x, y) && - BLI_lasso_is_point_inside(data->mcords, data->moves, x, y, IS_CLIPPED)) + if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)) { BM_face_select_set(data->vc->em->bm, efa, data->select); } } -static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves, short extend, short select) +static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short moves, short extend, short select) { LassoSelectUserData data; ToolSettings *ts = vc->scene->toolsettings; rcti rect; int bbsel; - BLI_lasso_boundbox(&rect, mcords, moves); - /* set editmesh */ vc->em = BMEdit_FromObject(vc->obedit); - data.vc = vc; - data.rect = ▭ - data.mcords = mcords; - data.moves = moves; - data.select = select; - data.done = FALSE; - data.pass = 0; + BLI_lasso_boundbox(&rect, mcords, moves); + + view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select); if (extend == 0 && select) EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT); @@ -466,17 +535,17 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves, edbm_backbuf_check_and_select_verts(vc->em, select); } else { - mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, V3D_CLIP_TEST_RV3D_CLIPPING); + mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } if (ts->selectmode & SCE_SELECT_EDGE) { /* Does both bbsel and non-bbsel versions (need screen cos for both) */ data.pass = 0; - mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_CLIP_TEST_OFF); + mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_NOP); - if (data.done == 0) { + if (data.is_done == 0) { data.pass = 1; - mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_CLIP_TEST_OFF); + mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, V3D_PROJ_TEST_NOP); } } @@ -485,7 +554,7 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves, edbm_backbuf_check_and_select_faces(vc->em, select); } else { - mesh_foreachScreenFace(vc, do_lasso_select_mesh__doSelectFace, &data); + mesh_foreachScreenFace(vc, do_lasso_select_mesh__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } @@ -493,16 +562,16 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves, EDBM_selectmode_flush(vc->em); } -static void do_lasso_select_curve__doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, int x, int y) +static void do_lasso_select_curve__doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) { LassoSelectUserData *data = userData; Object *obedit = data->vc->obedit; Curve *cu = (Curve *)obedit->data; - if (BLI_lasso_is_point_inside(data->mcords, data->moves, x, y, IS_CLIPPED)) { + if (BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)) { if (bp) { bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT); - if (bp == cu->lastsel && !(bp->f1 & 1)) cu->lastsel = NULL; + if (bp == cu->lastsel && !(bp->f1 & SELECT)) cu->lastsel = NULL; } else { if (cu->drawflag & CU_HIDE_HANDLES) { @@ -521,129 +590,155 @@ static void do_lasso_select_curve__doSelect(void *userData, Nurb *UNUSED(nu), BP } } - if (bezt == cu->lastsel && !(bezt->f2 & 1)) cu->lastsel = NULL; + if (bezt == cu->lastsel && !(bezt->f2 & SELECT)) cu->lastsel = NULL; } } } -static void do_lasso_select_curve(ViewContext *vc, int mcords[][2], short moves, short extend, short select) +static void do_lasso_select_curve(ViewContext *vc, const int mcords[][2], short moves, short extend, short select) { LassoSelectUserData data; + rcti rect; - /* set vc->editnurb */ - data.vc = vc; - data.mcords = mcords; - data.moves = moves; - data.select = select; + BLI_lasso_boundbox(&rect, mcords, moves); + + view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select); if (extend == 0 && select) CU_deselect_all(vc->obedit); ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - nurbs_foreachScreenVert(vc, do_lasso_select_curve__doSelect, &data); + nurbs_foreachScreenVert(vc, do_lasso_select_curve__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } -static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, int x, int y) +static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const float screen_co[2]) { LassoSelectUserData *data = userData; - if (BLI_lasso_is_point_inside(data->mcords, data->moves, x, y, IS_CLIPPED)) { + if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)) { bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT); } } -static void do_lasso_select_lattice(ViewContext *vc, int mcords[][2], short moves, short extend, short select) +static void do_lasso_select_lattice(ViewContext *vc, const int mcords[][2], short moves, short extend, short select) { LassoSelectUserData data; + rcti rect; - /* set editdata in vc */ - data.mcords = mcords; - data.moves = moves; - data.select = select; + BLI_lasso_boundbox(&rect, mcords, moves); + + view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select); if (extend == 0 && select) ED_setflagsLatt(vc->obedit, 0); ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - lattice_foreachScreenVert(vc, do_lasso_select_lattice__doSelect, &data); + lattice_foreachScreenVert(vc, do_lasso_select_lattice__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } -static void do_lasso_select_armature(ViewContext *vc, int mcords[][2], short moves, short extend, short select) +static void do_lasso_select_armature__doSelectBone(void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2]) { - bArmature *arm = vc->obedit->data; - EditBone *ebone; - float vec[3]; - short sco1[2], sco2[2], didpoint; - int change = FALSE; + LassoSelectUserData *data = userData; + bArmature *arm = data->vc->obedit->data; + + if (EBONE_SELECTABLE(arm, ebone)) { + int is_point_done = FALSE; + int points_proj_tot = 0; + + const int x0 = screen_co_a[0]; + const int y0 = screen_co_a[1]; + const int x1 = screen_co_b[0]; + const int y1 = screen_co_b[1]; + + /* project head location to screenspace */ + if (x0 != IS_CLIPPED) { + points_proj_tot++; + if (BLI_rcti_isect_pt(data->rect, x0, y0) && + BLI_lasso_is_point_inside(data->mcords, data->moves, x0, y0, INT_MAX)) + { + is_point_done = TRUE; + if (data->select) ebone->flag |= BONE_ROOTSEL; + else ebone->flag &= ~BONE_ROOTSEL; + } + } + + /* project tail location to screenspace */ + if (x1 != IS_CLIPPED) { + points_proj_tot++; + if (BLI_rcti_isect_pt(data->rect, x1, y1) && + BLI_lasso_is_point_inside(data->mcords, data->moves, x1, y1, INT_MAX)) + { + is_point_done = TRUE; + if (data->select) ebone->flag |= BONE_TIPSEL; + else ebone->flag &= ~BONE_TIPSEL; + } + } + + /* if one of points selected, we skip the bone itself */ + if ((is_point_done == FALSE) && (points_proj_tot == 2) && + BLI_lasso_is_edge_inside(data->mcords, data->moves, x0, y0, x1, y1, INT_MAX)) + { + if (data->select) ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + else ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + data->is_change = TRUE; + } + + data->is_change |= is_point_done; + } +} + +static void do_lasso_select_armature(ViewContext *vc, const int mcords[][2], short moves, short extend, short select) +{ + LassoSelectUserData data; + rcti rect; + + BLI_lasso_boundbox(&rect, mcords, moves); + + view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select); + + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); if (extend == 0 && select) ED_armature_deselect_all_visible(vc->obedit); - /* set editdata in vc */ - - for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { - if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_UNSELECTABLE) == 0) { - mul_v3_m4v3(vec, vc->obedit->obmat, ebone->head); - project_short(vc->ar, vec, sco1); - mul_v3_m4v3(vec, vc->obedit->obmat, ebone->tail); - project_short(vc->ar, vec, sco2); - - didpoint = 0; - if (BLI_lasso_is_point_inside(mcords, moves, sco1[0], sco1[1], IS_CLIPPED)) { - if (select) ebone->flag |= BONE_ROOTSEL; - else ebone->flag &= ~BONE_ROOTSEL; - didpoint = 1; - change = TRUE; - } - if (BLI_lasso_is_point_inside(mcords, moves, sco2[0], sco2[1], IS_CLIPPED)) { - if (select) ebone->flag |= BONE_TIPSEL; - else ebone->flag &= ~BONE_TIPSEL; - didpoint = 1; - change = TRUE; - } - /* if one of points selected, we skip the bone itself */ - if (didpoint == 0 && - BLI_lasso_is_edge_inside(mcords, moves, sco1[0], sco1[1], sco2[0], sco2[1], IS_CLIPPED)) - { - if (select) ebone->flag |= BONE_TIPSEL | BONE_ROOTSEL | BONE_SELECTED; - else ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - change = TRUE; - } - } - } - - if (change) { + armature_foreachScreenBone(vc, do_lasso_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + + if (data.is_change) { + bArmature *arm = vc->obedit->data; ED_armature_sync_selection(arm->edbo); ED_armature_validate_active(arm); WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit); } } - - - -static void do_lasso_select_meta(ViewContext *vc, int mcords[][2], short moves, short extend, short select) +static void do_lasso_select_mball__doSelectElem(void *userData, struct MetaElem *ml, const float screen_co[2]) { + LassoSelectUserData *data = userData; + + if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], INT_MAX)) { + if (data->select) ml->flag |= SELECT; + else ml->flag &= ~SELECT; + data->is_change = TRUE; + } +} +static void do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short moves, short extend, short select) +{ + LassoSelectUserData data; + rcti rect; + MetaBall *mb = (MetaBall *)vc->obedit->data; - MetaElem *ml; - float vec[3]; - short sco[2]; - if (extend == 0 && select) { - for (ml = mb->editelems->first; ml; ml = ml->next) { - ml->flag &= ~SELECT; - } - } + if (extend == 0 && select) + BKE_mball_deselect_all(mb); - for (ml = mb->editelems->first; ml; ml = ml->next) { - - mul_v3_m4v3(vec, vc->obedit->obmat, &ml->x); - project_short(vc->ar, vec, sco); + BLI_lasso_boundbox(&rect, mcords, moves); - if (BLI_lasso_is_point_inside(mcords, moves, sco[0], sco[1], IS_CLIPPED)) { - if (select) ml->flag |= SELECT; - else ml->flag &= ~SELECT; - } - } + view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select); + + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + + mball_foreachScreenElem(vc, do_lasso_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } static int do_paintvert_box_select(ViewContext *vc, rcti *rect, int select, int extend) @@ -654,8 +749,8 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, int select, int unsigned int *rt; int a, index; char *selar; - int sx = BLI_RCT_SIZE_X(rect) + 1; - int sy = BLI_RCT_SIZE_Y(rect) + 1; + int sx = BLI_rcti_size_x(rect) + 1; + int sy = BLI_rcti_size_y(rect) + 1; me = vc->obact->data; @@ -705,7 +800,7 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, int select, int return OPERATOR_FINISHED; } -static void do_lasso_select_paintvert(ViewContext *vc, int mcords[][2], short moves, short extend, short select) +static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, short extend, short select) { Object *ob = vc->obact; Mesh *me = ob ? ob->data : NULL; @@ -727,7 +822,7 @@ static void do_lasso_select_paintvert(ViewContext *vc, int mcords[][2], short mo paintvert_flush_flags(ob); } -static void do_lasso_select_paintface(ViewContext *vc, int mcords[][2], short moves, short extend, short select) +static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], short moves, short extend, short select) { Object *ob = vc->obact; Mesh *me = ob ? ob->data : NULL; @@ -782,7 +877,9 @@ static void do_lasso_select_node(int mcords[][2], short moves, short select) } #endif -static void view3d_lasso_select(bContext *C, ViewContext *vc, int mcords[][2], short moves, short extend, short select) +static void view3d_lasso_select(bContext *C, ViewContext *vc, + const int mcords[][2], short moves, + short extend, short select) { Object *ob = CTX_data_active_object(C); @@ -791,9 +888,10 @@ static void view3d_lasso_select(bContext *C, ViewContext *vc, int mcords[][2], s do_lasso_select_paintface(vc, mcords, moves, extend, select); else if (paint_vertsel_test(ob)) do_lasso_select_paintvert(vc, mcords, moves, extend, select); - else if (ob && ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) - ; - else if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) + else if (ob && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) { + /* pass */ + } + else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) PE_lasso_select(C, mcords, moves, extend, select); else { do_lasso_select_objects(vc, mcords, moves, extend, select); @@ -833,7 +931,7 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op) { ViewContext vc; int mcords_tot; - int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); if (mcords) { short extend, select; @@ -846,7 +944,7 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op) select = !RNA_boolean_get(op->ptr, "deselect"); view3d_lasso_select(C, &vc, mcords, mcords_tot, extend, select); - MEM_freeN(mcords); + MEM_freeN((void *)mcords); return OPERATOR_FINISHED; } @@ -1064,8 +1162,7 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int } else { int temp, dist = 15; - - project_short(vc->ar, base->object->obmat[3], &base->sx); + ED_view3d_project_base(vc->ar, base); temp = abs(base->sx - mval[0]) + abs(base->sy - mval[1]); if (temp < dist) @@ -1323,9 +1420,12 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); Base *base, *startbase = NULL, *basact = NULL, *oldbasact = NULL; - int temp, a, dist = 100; + int a; + float dist = 100.0f; int retval = 0; short hits; + const float mval_fl[2] = {(float)mval[0], (float)mval[1]}; + /* setup view context for argument to callbacks */ view3d_set_viewcontext(C, &vc); @@ -1346,14 +1446,16 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese base = startbase; while (base) { if (BASE_SELECTABLE(v3d, base)) { - project_short(ar, base->object->obmat[3], &base->sx); - - temp = abs(base->sx - mval[0]) + abs(base->sy - mval[1]); - if (base == BASACT) temp += 10; - if (temp < dist) { - - dist = temp; - basact = base; + float screen_co[2]; + if (ED_view3d_project_float_global(ar, base->object->obmat[3], screen_co, + V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_OK) + { + float dist_temp = len_manhattan_v2v2(mval_fl, screen_co); + if (base == BASACT) dist_temp += 10.0f; + if (dist_temp < dist) { + dist = dist_temp; + basact = base; + } } } base = base->next; @@ -1400,7 +1502,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese } /* index of bundle is 1<<16-based. if there's no "bone" index - * in hight word, this buffer value belongs to camera,. not to bundle */ + * in height word, this buffer value belongs to camera,. not to bundle */ if (buffer[4 * i + 3] & 0xFFFF0000) { MovieClip *clip = BKE_object_movieclip_get(scene, basact->object, 0); MovieTracking *tracking = &clip->tracking; @@ -1443,7 +1545,8 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese } } } - else if (ED_do_pose_selectbuffer(scene, basact, buffer, hits, extend, deselect, toggle) ) { /* then bone is found */ + else if (ED_do_pose_selectbuffer(scene, basact, buffer, hits, extend, deselect, toggle) ) { + /* then bone is found */ /* we make the armature selected: * not-selected active object in posemode won't work well for tools */ @@ -1518,27 +1621,48 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese typedef struct BoxSelectUserData { ViewContext *vc; - rcti *rect; - int select, pass, done; + const rcti *rect; + const rctf *rect_fl; + rctf _rect_fl; + int select; + + /* runtime */ + int pass; + int is_done; + int is_change; } BoxSelectUserData; -int edge_inside_circle(int centx, int centy, int rad, int x1, int y1, int x2, int y2) +static void view3d_userdata_boxselect_init(BoxSelectUserData *r_data, + ViewContext *vc, const rcti *rect, const int select) { - int radsq = rad * rad; + r_data->vc = vc; + + r_data->rect = rect; + r_data->rect_fl = &r_data->_rect_fl; + BLI_rctf_rcti_copy(&r_data->_rect_fl, rect); + + r_data->select = select; + + /* runtime */ + r_data->pass = 0; + r_data->is_done = FALSE; + r_data->is_change = FALSE; +} + +int edge_inside_circle(const float cent[2], float radius, const float screen_co_a[2], const float screen_co_b[2]) +{ + int radius_squared = radius * radius; /* check points in circle itself */ - if ((x1 - centx) * (x1 - centx) + (y1 - centy) * (y1 - centy) <= radsq) { + if (len_squared_v2v2(cent, screen_co_a) <= radius_squared) { return TRUE; } - else if ((x2 - centx) * (x2 - centx) + (y2 - centy) * (y2 - centy) <= radsq) { + if (len_squared_v2v2(cent, screen_co_b) <= radius_squared) { return TRUE; } else { - const float cent[2] = {centx, centy}; - const float v1[2] = {x1, y1}; - const float v2[2] = {x2, y2}; /* pointdistline */ - if (dist_squared_to_line_segment_v2(cent, v1, v2) < (float)radsq) { + if (dist_squared_to_line_segment_v2(cent, screen_co_a, screen_co_b) < (float)radius_squared) { return TRUE; } } @@ -1546,16 +1670,16 @@ int edge_inside_circle(int centx, int centy, int rad, int x1, int y1, int x2, in return FALSE; } -static void do_nurbs_box_select__doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, int x, int y) +static void do_nurbs_box_select__doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) { BoxSelectUserData *data = userData; Object *obedit = data->vc->obedit; Curve *cu = (Curve *)obedit->data; - if (BLI_rcti_isect_pt(data->rect, x, y)) { + if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) { if (bp) { bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT); - if (bp == cu->lastsel && !(bp->f1 & 1)) cu->lastsel = NULL; + if (bp == cu->lastsel && !(bp->f1 & SELECT)) cu->lastsel = NULL; } else { if (cu->drawflag & CU_HIDE_HANDLES) { @@ -1574,7 +1698,7 @@ static void do_nurbs_box_select__doSelect(void *userData, Nurb *UNUSED(nu), BPoi } } - if (bezt == cu->lastsel && !(bezt->f2 & 1)) cu->lastsel = NULL; + if (bezt == cu->lastsel && !(bezt->f2 & SELECT)) cu->lastsel = NULL; } } } @@ -1582,24 +1706,22 @@ static int do_nurbs_box_select(ViewContext *vc, rcti *rect, int select, int exte { BoxSelectUserData data; - data.vc = vc; - data.rect = rect; - data.select = select; + view3d_userdata_boxselect_init(&data, vc, rect, select); if (extend == 0 && select) CU_deselect_all(vc->obedit); ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - nurbs_foreachScreenVert(vc, do_nurbs_box_select__doSelect, &data); + nurbs_foreachScreenVert(vc, do_nurbs_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); return OPERATOR_FINISHED; } -static void do_lattice_box_select__doSelect(void *userData, BPoint *bp, int x, int y) +static void do_lattice_box_select__doSelect(void *userData, BPoint *bp, const float screen_co[2]) { BoxSelectUserData *data = userData; - if (BLI_rcti_isect_pt(data->rect, x, y)) { + if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) { bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT); } } @@ -1607,50 +1729,48 @@ static int do_lattice_box_select(ViewContext *vc, rcti *rect, int select, int ex { BoxSelectUserData data; - data.vc = vc; - data.rect = rect; - data.select = select; + view3d_userdata_boxselect_init(&data, vc, rect, select); if (extend == 0 && select) ED_setflagsLatt(vc->obedit, 0); ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - lattice_foreachScreenVert(vc, do_lattice_box_select__doSelect, &data); + lattice_foreachScreenVert(vc, do_lattice_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); return OPERATOR_FINISHED; } -static void do_mesh_box_select__doSelectVert(void *userData, BMVert *eve, int x, int y, int UNUSED(index)) +static void do_mesh_box_select__doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index)) { BoxSelectUserData *data = userData; - if (BLI_rcti_isect_pt(data->rect, x, y)) { + if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) { BM_vert_select_set(data->vc->em->bm, eve, data->select); } } -static void do_mesh_box_select__doSelectEdge(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int index) +static void do_mesh_box_select__doSelectEdge(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) { BoxSelectUserData *data = userData; if (EDBM_backbuf_check(bm_solidoffs + index)) { if (data->pass == 0) { - if (edge_fully_inside_rect(data->rect, x0, y0, x1, y1)) { + if (edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b)) { BM_edge_select_set(data->vc->em->bm, eed, data->select); - data->done = TRUE; + data->is_done = TRUE; } } else { - if (edge_inside_rect(data->rect, x0, y0, x1, y1)) { + if (edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b)) { BM_edge_select_set(data->vc->em->bm, eed, data->select); } } } } -static void do_mesh_box_select__doSelectFace(void *userData, BMFace *efa, int x, int y, int UNUSED(index)) +static void do_mesh_box_select__doSelectFace(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index)) { BoxSelectUserData *data = userData; - if (BLI_rcti_isect_pt(data->rect, x, y)) { + if (BLI_rctf_isect_pt_v(data->rect_fl, screen_co)) { BM_face_select_set(data->vc->em->bm, efa, data->select); } } @@ -1660,11 +1780,7 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int exten ToolSettings *ts = vc->scene->toolsettings; int bbsel; - data.vc = vc; - data.rect = rect; - data.select = select; - data.pass = 0; - data.done = FALSE; + view3d_userdata_boxselect_init(&data, vc, rect, select); if (extend == 0 && select) EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT); @@ -1680,18 +1796,18 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int exten edbm_backbuf_check_and_select_verts(vc->em, select); } else { - mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, V3D_CLIP_TEST_RV3D_CLIPPING); + mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } if (ts->selectmode & SCE_SELECT_EDGE) { /* Does both bbsel and non-bbsel versions (need screen cos for both) */ data.pass = 0; - mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_CLIP_TEST_OFF); + mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_NOP); - if (data.done == 0) { + if (data.is_done == 0) { data.pass = 1; - mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_CLIP_TEST_OFF); + mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, V3D_PROJ_TEST_NOP); } } @@ -1700,7 +1816,7 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int exten edbm_backbuf_check_and_select_faces(vc->em, select); } else { - mesh_foreachScreenFace(vc, do_mesh_box_select__doSelectFace, &data); + mesh_foreachScreenFace(vc, do_mesh_box_select__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } @@ -1722,11 +1838,8 @@ static int do_meta_box_select(ViewContext *vc, rcti *rect, int select, int exten hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect); - if (extend == 0 && select) { - for (ml = mb->editelems->first; ml; ml = ml->next) { - ml->flag &= ~SELECT; - } - } + if (extend == 0 && select) + BKE_mball_deselect_all(mb); for (ml = mb->editelems->first; ml; ml = ml->next) { for (a = 0; a < hits; a++) { @@ -1902,12 +2015,10 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, i } if (bone_selected) { - Object *ob = base->object; - - if (ob && (ob->type == OB_ARMATURE)) { - bArmature *arm = ob->data; + if (base->object && (base->object->type == OB_ARMATURE)) { + bArmature *arm = base->object->data; - WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); + WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object); if (arm && (arm->flag & ARM_HAS_VIZ_DEPS)) { /* mask modifier ('armature' mode), etc. */ @@ -2145,35 +2256,52 @@ void VIEW3D_OT_select(wmOperatorType *ot) typedef struct CircleSelectUserData { ViewContext *vc; short select; - int mval[2]; + int mval[2]; + float mval_fl[2]; float radius; + float radius_squared; + + /* runtime */ + int is_change; } CircleSelectUserData; -static void mesh_circle_doSelectVert(void *userData, BMVert *eve, int x, int y, int UNUSED(index)) +static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data, + ViewContext *vc, const int select, const int mval[2], const float rad) +{ + r_data->vc = vc; + r_data->select = select; + copy_v2_v2_int(r_data->mval, mval); + r_data->mval_fl[0] = mval[0]; + r_data->mval_fl[1] = mval[1]; + + r_data->radius = rad; + r_data->radius_squared = rad * rad; + + /* runtime */ + r_data->is_change = FALSE; +} + +static void mesh_circle_doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index)) { CircleSelectUserData *data = userData; - int mx = x - data->mval[0], my = y - data->mval[1]; - float r = sqrt(mx * mx + my * my); - if (r <= data->radius) { + if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { BM_vert_select_set(data->vc->em->bm, eve, data->select); } } -static void mesh_circle_doSelectEdge(void *userData, BMEdge *eed, int x0, int y0, int x1, int y1, int UNUSED(index)) +static void mesh_circle_doSelectEdge(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index)) { CircleSelectUserData *data = userData; - if (edge_inside_circle(data->mval[0], data->mval[1], (int)data->radius, x0, y0, x1, y1)) { + if (edge_inside_circle(data->mval_fl, (int)data->radius, screen_co_a, screen_co_b)) { BM_edge_select_set(data->vc->em->bm, eed, data->select); } } -static void mesh_circle_doSelectFace(void *userData, BMFace *efa, int x, int y, int UNUSED(index)) +static void mesh_circle_doSelectFace(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index)) { CircleSelectUserData *data = userData; - int mx = x - data->mval[0], my = y - data->mval[1]; - float r = sqrt(mx * mx + my * my); - - if (r <= data->radius) { + + if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { BM_face_select_set(data->vc->em->bm, efa, data->select); } } @@ -2189,18 +2317,14 @@ static void mesh_circle_select(ViewContext *vc, int select, const int mval[2], f vc->em = BMEdit_FromObject(vc->obedit); - data.vc = vc; - data.select = select; - data.mval[0] = mval[0]; - data.mval[1] = mval[1]; - data.radius = rad; + view3d_userdata_circleselect_init(&data, vc, select, mval, rad); if (ts->selectmode & SCE_SELECT_VERTEX) { if (bbsel) { edbm_backbuf_check_and_select_verts(vc->em, select == LEFTMOUSE); } else { - mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, V3D_CLIP_TEST_RV3D_CLIPPING); + mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } @@ -2209,7 +2333,7 @@ static void mesh_circle_select(ViewContext *vc, int select, const int mval[2], f edbm_backbuf_check_and_select_edges(vc->em, select == LEFTMOUSE); } else { - mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_CLIP_TEST_OFF); + mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_NOP); } } @@ -2218,7 +2342,7 @@ static void mesh_circle_select(ViewContext *vc, int select, const int mval[2], f edbm_backbuf_check_and_select_faces(vc->em, select == LEFTMOUSE); } else { - mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data); + mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } @@ -2235,7 +2359,7 @@ static void paint_facesel_circle_select(ViewContext *vc, int select, const int m if (me) { bm_vertoffs = me->totpoly + 1; /* max index array */ - /* bbsel= */ /* UNUSED */ EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); + /* bbsel = */ /* UNUSED */ EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); edbm_backbuf_check_and_select_tfaces(me, select == LEFTMOUSE); EDBM_backbuf_free(); paintface_flush_flags(ob); @@ -2252,7 +2376,7 @@ static void paint_vertsel_circle_select(ViewContext *vc, int select, const int m if (me) { bm_vertoffs = me->totvert + 1; /* max index array */ - /* bbsel= */ /* UNUSED */ EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); + /* bbsel = */ /* UNUSED */ EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); edbm_backbuf_check_and_select_verts_obmode(me, select == LEFTMOUSE); EDBM_backbuf_free(); @@ -2261,19 +2385,17 @@ static void paint_vertsel_circle_select(ViewContext *vc, int select, const int m } -static void nurbscurve_circle_doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, int x, int y) +static void nurbscurve_circle_doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) { CircleSelectUserData *data = userData; - int mx = x - data->mval[0], my = y - data->mval[1]; - float r = sqrt(mx * mx + my * my); Object *obedit = data->vc->obedit; Curve *cu = (Curve *)obedit->data; - if (r <= data->radius) { + if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { if (bp) { bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT); - if (bp == cu->lastsel && !(bp->f1 & 1)) cu->lastsel = NULL; + if (bp == cu->lastsel && !(bp->f1 & SELECT)) cu->lastsel = NULL; } else { if (cu->drawflag & CU_HIDE_HANDLES) { @@ -2292,7 +2414,7 @@ static void nurbscurve_circle_doSelect(void *userData, Nurb *UNUSED(nu), BPoint } } - if (bezt == cu->lastsel && !(bezt->f2 & 1)) cu->lastsel = NULL; + if (bezt == cu->lastsel && !(bezt->f2 & SELECT)) cu->lastsel = NULL; } } } @@ -2300,26 +2422,18 @@ static void nurbscurve_circle_select(ViewContext *vc, int select, const int mval { CircleSelectUserData data; - /* set vc-> edit data */ - - data.select = select; - data.mval[0] = mval[0]; - data.mval[1] = mval[1]; - data.radius = rad; - data.vc = vc; + view3d_userdata_circleselect_init(&data, vc, select, mval, rad); ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - nurbs_foreachScreenVert(vc, nurbscurve_circle_doSelect, &data); + nurbs_foreachScreenVert(vc, nurbscurve_circle_doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } -static void latticecurve_circle_doSelect(void *userData, BPoint *bp, int x, int y) +static void latticecurve_circle_doSelect(void *userData, BPoint *bp, const float screen_co[2]) { CircleSelectUserData *data = userData; - int mx = x - data->mval[0], my = y - data->mval[1]; - float r = sqrt(mx * mx + my * my); - if (r <= data->radius) { + if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT); } } @@ -2327,26 +2441,19 @@ static void lattice_circle_select(ViewContext *vc, int select, const int mval[2] { CircleSelectUserData data; - /* set vc-> edit data */ - - data.select = select; - data.mval[0] = mval[0]; - data.mval[1] = mval[1]; - data.radius = rad; + view3d_userdata_circleselect_init(&data, vc, select, mval, rad); ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - lattice_foreachScreenVert(vc, latticecurve_circle_doSelect, &data); + lattice_foreachScreenVert(vc, latticecurve_circle_doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } /* NOTE: pose-bone case is copied from editbone case... */ -static short pchan_circle_doSelectJoint(void *userData, bPoseChannel *pchan, int x, int y) +static short pchan_circle_doSelectJoint(void *userData, bPoseChannel *pchan, const float screen_co[2]) { CircleSelectUserData *data = userData; - int mx = x - data->mval[0], my = y - data->mval[1]; - float r = sqrt(mx * mx + my * my); - - if (r <= data->radius) { + + if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { if (data->select) pchan->bone->flag |= BONE_SELECTED; else @@ -2355,63 +2462,76 @@ static short pchan_circle_doSelectJoint(void *userData, bPoseChannel *pchan, int } return 0; } +static void do_circle_select_pose__doSelectBone(void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2]) +{ + CircleSelectUserData *data = userData; + bArmature *arm = data->vc->obact->data; + + if (PBONE_SELECTABLE(arm, pchan->bone)) { + int is_point_done = FALSE; + int points_proj_tot = 0; + + /* project head location to screenspace */ + if (screen_co_a[0] != IS_CLIPPED) { + points_proj_tot++; + if (pchan_circle_doSelectJoint(data, pchan, screen_co_a)) { + is_point_done = TRUE; + } + } + + /* project tail location to screenspace */ + if (screen_co_b[0] != IS_CLIPPED) { + points_proj_tot++; + if (pchan_circle_doSelectJoint(data, pchan, screen_co_a)) { + is_point_done = TRUE; + } + } + + /* check if the head and/or tail is in the circle + * - the call to check also does the selection already + */ + + /* only if the endpoints didn't get selected, deal with the middle of the bone too + * It works nicer to only do this if the head or tail are not in the circle, + * otherwise there is no way to circle select joints alone */ + if ((is_point_done == FALSE) && (points_proj_tot == 2) && + edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) + { + if (data->select) pchan->bone->flag |= BONE_SELECTED; + else pchan->bone->flag &= ~BONE_SELECTED; + data->is_change = TRUE; + } + + data->is_change |= is_point_done; + } +} static void pose_circle_select(ViewContext *vc, int select, const int mval[2], float rad) { CircleSelectUserData data; - bArmature *arm = vc->obact->data; - bPose *pose = vc->obact->pose; - bPoseChannel *pchan; - int change = FALSE; - /* set vc->edit data */ - data.select = select; - data.mval[0] = mval[0]; - data.mval[1] = mval[1]; - data.radius = rad; + view3d_userdata_circleselect_init(&data, vc, select, mval, rad); ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */ - /* check each PoseChannel... */ - /* TODO: could be optimized at some point */ - for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { - short sco1[2], sco2[2], didpoint = 0; - float vec[3]; - - /* skip invisible bones */ - if (PBONE_VISIBLE(arm, pchan->bone) == 0) - continue; - - /* project head location to screenspace */ - mul_v3_m4v3(vec, vc->obact->obmat, pchan->pose_head); - project_short(vc->ar, vec, sco1); - - /* project tail location to screenspace */ - mul_v3_m4v3(vec, vc->obact->obmat, pchan->pose_tail); - project_short(vc->ar, vec, sco2); - - /* check if the head and/or tail is in the circle - * - the call to check also does the selection already - */ - if (pchan_circle_doSelectJoint(&data, pchan, sco1[0], sco1[1])) - didpoint = 1; - if (pchan_circle_doSelectJoint(&data, pchan, sco2[0], sco2[1])) - didpoint = 1; - - change |= didpoint; - } + pose_foreachScreenBone(vc, do_circle_select_pose__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + + if (data.is_change) { + bArmature *arm = vc->obact->data; - if (change) { WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obact); + + if (arm->flag & ARM_HAS_VIZ_DEPS) { + /* mask modifier ('armature' mode), etc. */ + DAG_id_tag_update(&vc->obact->id, OB_RECALC_DATA); + } } } -static short armature_circle_doSelectJoint(void *userData, EditBone *ebone, int x, int y, short head) +static short armature_circle_doSelectJoint(void *userData, EditBone *ebone, const float screen_co[2], short head) { CircleSelectUserData *data = userData; - int mx = x - data->mval[0], my = y - data->mval[1]; - float r = sqrt(mx * mx + my * my); - - if (r <= data->radius) { + + if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { if (head) { if (data->select) ebone->flag |= BONE_ROOTSEL; @@ -2428,63 +2548,88 @@ static short armature_circle_doSelectJoint(void *userData, EditBone *ebone, int } return 0; } +static void do_circle_select_armature__doSelectBone(void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2]) +{ + CircleSelectUserData *data = userData; + bArmature *arm = data->vc->obedit->data; + + if (EBONE_SELECTABLE(arm, ebone)) { + int is_point_done = FALSE; + int points_proj_tot = 0; + + /* project head location to screenspace */ + if (screen_co_a[0] != IS_CLIPPED) { + points_proj_tot++; + if (armature_circle_doSelectJoint(data, ebone, screen_co_a, TRUE)) { + is_point_done = TRUE; + } + } + + /* project tail location to screenspace */ + if (screen_co_b[0] != IS_CLIPPED) { + points_proj_tot++; + if (armature_circle_doSelectJoint(data, ebone, screen_co_b, FALSE)) { + is_point_done = TRUE; + } + } + + /* check if the head and/or tail is in the circle + * - the call to check also does the selection already + */ + + /* only if the endpoints didn't get selected, deal with the middle of the bone too + * It works nicer to only do this if the head or tail are not in the circle, + * otherwise there is no way to circle select joints alone */ + if ((is_point_done == FALSE) && (points_proj_tot == 2) && + edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) + { + if (data->select) ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + else ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + data->is_change = TRUE; + } + + data->is_change |= is_point_done; + } +} static void armature_circle_select(ViewContext *vc, int select, const int mval[2], float rad) { CircleSelectUserData data; bArmature *arm = vc->obedit->data; - EditBone *ebone; - int change = FALSE; - - /* set vc->edit data */ - data.select = select; - data.mval[0] = mval[0]; - data.mval[1] = mval[1]; - data.radius = rad; - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - - /* check each EditBone... */ - /* TODO: could be optimized at some point */ - for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { - short sco1[2], sco2[2], didpoint = 0; - float vec[3]; - - /* project head location to screenspace */ - mul_v3_m4v3(vec, vc->obedit->obmat, ebone->head); - project_short(vc->ar, vec, sco1); - - /* project tail location to screenspace */ - mul_v3_m4v3(vec, vc->obedit->obmat, ebone->tail); - project_short(vc->ar, vec, sco2); - - /* check if the head and/or tail is in the circle - * - the call to check also does the selection already - */ - if (armature_circle_doSelectJoint(&data, ebone, sco1[0], sco1[1], 1)) - didpoint = 1; - if (armature_circle_doSelectJoint(&data, ebone, sco2[0], sco2[1], 0)) - didpoint = 1; - - /* only if the endpoints didn't get selected, deal with the middle of the bone too */ - /* XXX should we just do this always? */ - if ((didpoint == 0) && edge_inside_circle(mval[0], mval[1], rad, sco1[0], sco1[1], sco2[0], sco2[1])) { - if (select) - ebone->flag |= BONE_TIPSEL | BONE_ROOTSEL | BONE_SELECTED; - else - ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - change = TRUE; - } - - change |= didpoint; - } + view3d_userdata_circleselect_init(&data, vc, select, mval, rad); - if (change) { + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + + armature_foreachScreenBone(vc, do_circle_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + + if (data.is_change) { ED_armature_sync_selection(arm->edbo); ED_armature_validate_active(arm); WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit); } } +static void do_circle_select_mball__doSelectElem(void *userData, struct MetaElem *ml, const float screen_co[2]) +{ + CircleSelectUserData *data = userData; + + if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { + if (data->select) ml->flag |= SELECT; + else ml->flag &= ~SELECT; + data->is_change = TRUE; + } +} +static void mball_circle_select(ViewContext *vc, int select, const int mval[2], float rad) +{ + CircleSelectUserData data; + + view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + + mball_foreachScreenElem(vc, do_circle_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT); +} + /** Callbacks for circle selection in Editmode */ static void obedit_circle_select(ViewContext *vc, short select, const int mval[2], float rad) @@ -2503,24 +2648,51 @@ static void obedit_circle_select(ViewContext *vc, short select, const int mval[2 case OB_ARMATURE: armature_circle_select(vc, select, mval, rad); break; + case OB_MBALL: + mball_circle_select(vc, select, mval, rad); + break; default: return; } } +static int object_circle_select(ViewContext *vc, int select, const int mval[2], float rad) +{ + Scene *scene = vc->scene; + const float radius_squared = rad * rad; + const float mval_fl[2] = {mval[0], mval[1]}; + int is_change = FALSE; + int select_flag = select ? SELECT : 0; + + Base *base; + select = select ? BA_SELECT : BA_DESELECT; + for (base = FIRSTBASE; base; base = base->next) { + if (BASE_SELECTABLE(vc->v3d, base) && ((base->flag & SELECT) != select_flag)) { + float screen_co[2]; + if (ED_view3d_project_float_global(vc->ar, base->object->obmat[3], screen_co, + V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_OK) + { + if (len_squared_v2v2(mval_fl, screen_co) <= radius_squared) { + ED_base_object_select(base, select); + is_change = TRUE; + } + } + } + } + + return is_change; +} + /* not a real operator, only for circle test */ static int view3d_circle_select_exec(bContext *C, wmOperator *op) { - ScrArea *sa = CTX_wm_area(C); - ARegion *ar = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); Object *obact = CTX_data_active_object(C); - View3D *v3d = sa->spacedata.first; - int x = RNA_int_get(op->ptr, "x"); - int y = RNA_int_get(op->ptr, "y"); int radius = RNA_int_get(op->ptr, "radius"); int gesture_mode = RNA_int_get(op->ptr, "gesture_mode"); int select; + const int mval[2] = {RNA_int_get(op->ptr, "x"), + RNA_int_get(op->ptr, "y")}; select = (gesture_mode == GESTURE_MODAL_SELECT); @@ -2528,13 +2700,10 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) (obact && (obact->mode & (OB_MODE_PARTICLE_EDIT | OB_MODE_POSE))) ) { ViewContext vc; - int mval[2]; view3d_operator_needs_opengl(C); view3d_set_viewcontext(C, &vc); - mval[0] = x; - mval[1] = y; if (CTX_data_edit_object(C)) { obedit_circle_select(&vc, select, mval, (float)radius); @@ -2557,21 +2726,12 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } else { - Base *base; - select = select ? BA_SELECT : BA_DESELECT; - for (base = FIRSTBASE; base; base = base->next) { - if (BASE_SELECTABLE(v3d, base)) { - project_short(ar, base->object->obmat[3], &base->sx); - if (base->sx != IS_CLIPPED) { - int dx = base->sx - x; - int dy = base->sy - y; - if (dx * dx + dy * dy < radius * radius) - ED_base_object_select(base, select); - } - } + ViewContext vc; + view3d_set_viewcontext(C, &vc); + + if (object_circle_select(&vc, select, mval, (float)radius)) { + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } - - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C)); } return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index 4ca9bd95485..7f1bbb22f24 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -82,10 +82,9 @@ extern float originmat[3][3]; /* XXX object.c */ typedef struct TransVert { float *loc; - float oldloc[3], maploc[3], fac; + float oldloc[3], maploc[3]; float *val, oldval; int flag; - float *nor; } TransVert; /* SELECT == (1 << 0) */ @@ -193,6 +192,20 @@ static void special_transvert_update(Object *obedit) } } +/* currently only used for bmesh index values */ +enum { + TM_INDEX_ON = 1, /* tag to make trans verts */ + TM_INDEX_OFF = 0, /* don't make verts */ + TM_INDEX_SKIP = -1 /* dont make verts (when the index values point to trans-verts) */ +}; + +/* copied from editobject.c, needs to be replaced with new transform code still */ +/* mode flags: */ +enum { + TM_ALL_JOINTS = 1, /* all joints (for bones only) */ + TM_SKIP_HANDLES = 2 /* skip handles when control point is selected (for curves only) */ +}; + static void set_mapped_co(void *vuserdata, int index, const float co[3], const float UNUSED(no[3]), const short UNUSED(no_s[3])) { @@ -201,16 +214,25 @@ static void set_mapped_co(void *vuserdata, int index, const float co[3], TransVert *tv = userdata[1]; BMVert *eve = EDBM_vert_at_index(em, index); - if (BM_elem_index_get(eve) != -1 && !(tv[BM_elem_index_get(eve)].flag & TX_VERT_USE_MAPLOC)) { - copy_v3_v3(tv[BM_elem_index_get(eve)].maploc, co); - tv[BM_elem_index_get(eve)].flag |= TX_VERT_USE_MAPLOC; + if (BM_elem_index_get(eve) != TM_INDEX_SKIP) { + tv = &tv[BM_elem_index_get(eve)]; + + /* be clever, get the closest vertex to the original, + * behaves most logically when the mirror modifier is used for eg [#33051]*/ + if ((tv->flag & TX_VERT_USE_MAPLOC) == 0) { + /* first time */ + copy_v3_v3(tv->maploc, co); + tv->flag |= TX_VERT_USE_MAPLOC; + } + else { + /* find best location to use */ + if (len_squared_v3v3(eve->co, co) < len_squared_v3v3(eve->co, tv->maploc)) { + copy_v3_v3(tv->maploc, co); + } + } } } -/* copied from editobject.c, needs to be replaced with new transform code still */ -/* mode flags: */ -#define TM_ALL_JOINTS 1 /* all joints (for bones only) */ -#define TM_SKIP_HANDLES 2 /* skip handles when control point is selected (for curves only) */ static void make_trans_verts(Object *obedit, float min[3], float max[3], int mode) { Nurb *nu; @@ -233,7 +255,7 @@ static void make_trans_verts(Object *obedit, float min[3], float max[3], int mod BMesh *bm = em->bm; BMIter iter; void *userdata[2] = {em, NULL}; - /*int proptrans= 0; */ /*UNUSED*/ + /*int proptrans = 0; */ /*UNUSED*/ /* abuses vertex index all over, set, just set dirty here, * perhaps this could use its own array instead? - campbell */ @@ -243,35 +265,37 @@ static void make_trans_verts(Object *obedit, float min[3], float max[3], int mod if (em->selectmode & SCE_SELECT_VERTEX) { BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT)) { - BM_elem_index_set(eve, 1); /* set_dirty! */ + BM_elem_index_set(eve, TM_INDEX_ON); /* set_dirty! */ tottrans++; } - else BM_elem_index_set(eve, 0); /* set_dirty! */ + else { + BM_elem_index_set(eve, TM_INDEX_OFF); /* set_dirty! */ + } } } else if (em->selectmode & SCE_SELECT_EDGE) { BMEdge *eed; BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { - BM_elem_index_set(eve, 0); /* set_dirty! */ + BM_elem_index_set(eve, TM_INDEX_OFF); /* set_dirty! */ } BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && BM_elem_flag_test(eed, BM_ELEM_SELECT)) { - BM_elem_index_set(eed->v1, 1); /* set_dirty! */ - BM_elem_index_set(eed->v2, 1); /* set_dirty! */ + BM_elem_index_set(eed->v1, TM_INDEX_ON); /* set_dirty! */ + BM_elem_index_set(eed->v2, TM_INDEX_ON); /* set_dirty! */ } } BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_index_get(eve)) tottrans++; + if (BM_elem_index_get(eve) == TM_INDEX_ON) tottrans++; } } else { BMFace *efa; BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { - BM_elem_index_set(eve, 0); /* set_dirty! */ + BM_elem_index_set(eve, TM_INDEX_OFF); /* set_dirty! */ } BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { @@ -280,13 +304,13 @@ static void make_trans_verts(Object *obedit, float min[3], float max[3], int mod BMLoop *l; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - BM_elem_index_set(l->v, 1); /* set_dirty! */ + BM_elem_index_set(l->v, TM_INDEX_ON); /* set_dirty! */ } } } BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_index_get(eve)) tottrans++; + if (BM_elem_index_get(eve) == TM_INDEX_ON) tottrans++; } } /* for any of the 3 loops above which all dirty the indices */ @@ -299,17 +323,15 @@ static void make_trans_verts(Object *obedit, float min[3], float max[3], int mod a = 0; BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_index_get(eve)) { - BM_elem_index_set(eve, a); /* set_dirty! */ + BM_elem_index_set(eve, a); /* set_dirty! */ copy_v3_v3(tv->oldloc, eve->co); tv->loc = eve->co; - if (eve->no[0] != 0.0f || eve->no[1] != 0.0f || eve->no[2] != 0.0f) - tv->nor = eve->no; /* note this is a hackish signal (ton) */ - tv->flag = BM_elem_index_get(eve) & SELECT; + tv->flag = (BM_elem_index_get(eve) == TM_INDEX_ON) ? SELECT : 0; tv++; a++; } else { - BM_elem_index_set(eve, -1); /* set_dirty! */ + BM_elem_index_set(eve, TM_INDEX_SKIP); /* set_dirty! */ } } /* set dirty already, above */ @@ -345,17 +367,15 @@ static void make_trans_verts(Object *obedit, float min[3], float max[3], int mod if (rootok) { copy_v3_v3(tv->oldloc, ebo->head); tv->loc = ebo->head; - tv->nor = NULL; - tv->flag = 1; + tv->flag = SELECT; tv++; tottrans++; - } + } if ((mode & TM_ALL_JOINTS) && (tipsel)) { copy_v3_v3(tv->oldloc, ebo->tail); tv->loc = ebo->tail; - tv->nor = NULL; - tv->flag = 1; + tv->flag = SELECT; tv++; tottrans++; } @@ -363,8 +383,7 @@ static void make_trans_verts(Object *obedit, float min[3], float max[3], int mod else if (tipsel) { copy_v3_v3(tv->oldloc, ebo->tail); tv->loc = ebo->tail; - tv->nor = NULL; - tv->flag = 1; + tv->flag = SELECT; tv++; tottrans++; } @@ -456,7 +475,7 @@ static void make_trans_verts(Object *obedit, float min[3], float max[3], int mod copy_v3_v3(tv->oldloc, tv->loc); tv->val = &(ml->rad); tv->oldval = ml->rad; - tv->flag = 1; + tv->flag = SELECT; tv++; tottrans++; } @@ -607,9 +626,9 @@ static int snap_sel_to_grid(bContext *C, wmOperator *UNUSED(op)) else { ob->recalc |= OB_RECALC_OB; - vec[0] = -ob->obmat[3][0] + gridf *floorf(0.5f + ob->obmat[3][0] / gridf); - vec[1] = -ob->obmat[3][1] + gridf *floorf(0.5f + ob->obmat[3][1] / gridf); - vec[2] = -ob->obmat[3][2] + gridf *floorf(0.5f + ob->obmat[3][2] / gridf); + vec[0] = -ob->obmat[3][0] + gridf * floorf(0.5f + ob->obmat[3][0] / gridf); + vec[1] = -ob->obmat[3][1] + gridf * floorf(0.5f + ob->obmat[3][1] / gridf); + vec[2] = -ob->obmat[3][2] + gridf * floorf(0.5f + ob->obmat[3][2] / gridf); if (ob->parent) { BKE_object_where_is_calc(scene, ob); diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c index b40e880591a..d36b0085acb 100644 --- a/source/blender/editors/space_view3d/view3d_toolbar.c +++ b/source/blender/editors/space_view3d/view3d_toolbar.c @@ -173,7 +173,7 @@ static uiBlock *tool_search_menu(bContext *C, ARegion *ar, void *arg_listbase) search[0] = 0; block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS); - uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_RET_1); + uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_SEARCH_MENU); /* fake button, it holds space for search items */ uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); @@ -182,7 +182,7 @@ static uiBlock *tool_search_menu(bContext *C, ARegion *ar, void *arg_listbase) uiButSetSearchFunc(but, operator_search_cb, arg_listbase, operator_call_cb, NULL); uiBoundsBlock(block, 6); - uiBlockSetDirection(block, UI_DOWN); + uiBlockSetDirection(block, UI_DOWN); uiEndBlock(C, block); event = *(win->eventstate); /* XXX huh huh? make api call */ diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index c25bb80bfde..c16f04f01f3 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -125,7 +125,7 @@ struct SmoothView3DStore { /* will start timer if appropriate */ /* the arguments are the desired situation */ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera, Object *camera, - float *ofs, float *quat, float *dist, float *lens) + float *ofs, float *quat, float *dist, float *lens) { wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); @@ -140,7 +140,7 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera copy_qt_qt(sms.new_quat, rv3d->viewquat); sms.new_dist = rv3d->dist; sms.new_lens = v3d->lens; - sms.to_camera = 0; + sms.to_camera = FALSE; /* note on camera locking, this is a little confusing but works ok. * we may be changing the view 'as if' there is no active camera, but in fact @@ -161,23 +161,24 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera if (lens) sms.new_lens = *lens; if (camera) { + sms.new_dist = ED_view3d_offset_distance(camera->obmat, ofs); ED_view3d_from_object(camera, sms.new_ofs, sms.new_quat, &sms.new_dist, &sms.new_lens); - sms.to_camera = 1; /* restore view3d values in end */ + sms.to_camera = TRUE; /* restore view3d values in end */ } if (C && U.smooth_viewtx) { - int changed = 0; /* zero means no difference */ + int changed = FALSE; /* zero means no difference */ if (oldcamera != camera) - changed = 1; + changed = TRUE; else if (sms.new_dist != rv3d->dist) - changed = 1; + changed = TRUE; else if (sms.new_lens != v3d->lens) - changed = 1; + changed = TRUE; else if (!equals_v3v3(sms.new_ofs, rv3d->ofs)) - changed = 1; + changed = TRUE; else if (!equals_v4v4(sms.new_quat, rv3d->viewquat)) - changed = 1; + changed = TRUE; /* The new view is different from the old one * so animate the view */ @@ -185,7 +186,7 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera /* original values */ if (oldcamera) { - sms.orig_dist = rv3d->dist; /* below function does weird stuff with it... */ + sms.orig_dist = ED_view3d_offset_distance(oldcamera->obmat, rv3d->ofs); ED_view3d_from_object(oldcamera, sms.orig_ofs, sms.orig_quat, &sms.orig_dist, &sms.orig_lens); } else { @@ -241,13 +242,15 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera /* if we get here nothing happens */ if (ok == FALSE) { - if (sms.to_camera == 0) { + if (sms.to_camera == FALSE) { copy_v3_v3(rv3d->ofs, sms.new_ofs); copy_qt_qt(rv3d->viewquat, sms.new_quat); rv3d->dist = sms.new_dist; v3d->lens = sms.new_lens; } + ED_view3d_camera_lock_sync(v3d, rv3d); + if (rv3d->viewlock & RV3D_BOXVIEW) view3d_boxview_copy(sa, ar); @@ -520,7 +523,7 @@ void VIEW3D_OT_object_as_camera(wmOperatorType *ot) /* ********************************** */ -void ED_view3d_calc_clipping(BoundBox *bb, float planes[4][4], bglMats *mats, const rcti *rect) +void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], bglMats *mats, const rcti *rect) { float modelview[4][4]; double xs, ys, p[3]; @@ -569,160 +572,40 @@ void ED_view3d_calc_clipping(BoundBox *bb, float planes[4][4], bglMats *mats, co } } -/* create intersection coordinates in view Z direction at mouse coordinates */ -void ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]) + +int ED_view3d_boundbox_clip(RegionView3D *rv3d, float obmat[][4], BoundBox *bb) { - RegionView3D *rv3d = ar->regiondata; - - if (rv3d->is_persp) { - float vec[3]; - ED_view3d_win_to_vector(ar, mval, vec); + /* return 1: draw */ - copy_v3_v3(ray_start, rv3d->viewinv[3]); - madd_v3_v3v3fl(ray_start, rv3d->viewinv[3], vec, v3d->near); - madd_v3_v3v3fl(ray_end, rv3d->viewinv[3], vec, v3d->far); - } - else { - float vec[4]; - vec[0] = 2.0f * mval[0] / ar->winx - 1; - vec[1] = 2.0f * mval[1] / ar->winy - 1; - vec[2] = 0.0f; - vec[3] = 1.0f; - - mul_m4_v4(rv3d->persinv, vec); - - madd_v3_v3v3fl(ray_start, vec, rv3d->viewinv[2], 1000.0f); - madd_v3_v3v3fl(ray_end, vec, rv3d->viewinv[2], -1000.0f); + float mat[4][4]; + float vec[4], min, max; + int a, flag = -1, fl; + + if (bb == NULL) return 1; + if (bb->flag & OB_BB_DISABLED) return 1; + + mult_m4_m4m4(mat, rv3d->persmat, obmat); + + for (a = 0; a < 8; a++) { + copy_v3_v3(vec, bb->vec[a]); + vec[3] = 1.0; + mul_m4_v4(mat, vec); + max = vec[3]; + min = -vec[3]; + + fl = 0; + if (vec[0] < min) fl += 1; + if (vec[0] > max) fl += 2; + if (vec[1] < min) fl += 4; + if (vec[1] > max) fl += 8; + if (vec[2] < min) fl += 16; + if (vec[2] > max) fl += 32; + + flag &= fl; + if (flag == 0) return 1; } - /* clipping */ - if (rv3d->rflag & RV3D_CLIPPING) { - int a; - for (a = 0; a < 4; a++) { - clip_line_plane(ray_start, ray_end, rv3d->clip[a]); - } - } -} - -/* create intersection ray in view Z direction at mouse coordinates */ -void ED_view3d_win_to_ray(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_normal[3]) -{ - float ray_end[3]; - - ED_view3d_win_to_segment_clip(ar, v3d, mval, ray_start, ray_end); - sub_v3_v3v3(ray_normal, ray_end, ray_start); - normalize_v3(ray_normal); -} - -void ED_view3d_global_to_vector(RegionView3D *rv3d, const float coord[3], float vec[3]) -{ - if (rv3d->is_persp) { - float p1[4], p2[4]; - - copy_v3_v3(p1, coord); - p1[3] = 1.0f; - copy_v3_v3(p2, p1); - p2[3] = 1.0f; - mul_m4_v4(rv3d->viewmat, p2); - - mul_v3_fl(p2, 2.0f); - - mul_m4_v4(rv3d->viewinv, p2); - - sub_v3_v3v3(vec, p1, p2); - } - else { - copy_v3_v3(vec, rv3d->viewinv[2]); - } - normalize_v3(vec); -} - -int initgrabz(RegionView3D *rv3d, float x, float y, float z) -{ - int flip = FALSE; - if (rv3d == NULL) return flip; - rv3d->zfac = rv3d->persmat[0][3] * x + rv3d->persmat[1][3] * y + rv3d->persmat[2][3] * z + rv3d->persmat[3][3]; - if (rv3d->zfac < 0.0f) - flip = TRUE; - /* if x,y,z is exactly the viewport offset, zfac is 0 and we don't want that - * (accounting for near zero values) - */ - if (rv3d->zfac < 1.e-6f && rv3d->zfac > -1.e-6f) rv3d->zfac = 1.0f; - - /* Negative zfac means x, y, z was behind the camera (in perspective). - * This gives flipped directions, so revert back to ok default case. - */ - /* NOTE: I've changed this to flip zfac to be positive again for now so that GPencil draws ok - * Aligorith, 2009Aug31 */ - //if (rv3d->zfac < 0.0f) rv3d->zfac = 1.0f; - if (rv3d->zfac < 0.0f) rv3d->zfac = -rv3d->zfac; - - return flip; -} - -void ED_view3d_win_to_3d(ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]) -{ - RegionView3D *rv3d = ar->regiondata; - - float line_sta[3]; - float line_end[3]; - - if (rv3d->is_persp) { - float mousevec[3]; - copy_v3_v3(line_sta, rv3d->viewinv[3]); - ED_view3d_win_to_vector(ar, mval, mousevec); - add_v3_v3v3(line_end, line_sta, mousevec); - - if (isect_line_plane_v3(out, line_sta, line_end, depth_pt, rv3d->viewinv[2], TRUE) == 0) { - /* highly unlikely to ever happen, mouse vec paralelle with view plane */ - zero_v3(out); - } - } - else { - const float dx = (2.0f * mval[0] / (float)ar->winx) - 1.0f; - const float dy = (2.0f * mval[1] / (float)ar->winy) - 1.0f; - line_sta[0] = (rv3d->persinv[0][0] * dx) + (rv3d->persinv[1][0] * dy) + rv3d->viewinv[3][0]; - line_sta[1] = (rv3d->persinv[0][1] * dx) + (rv3d->persinv[1][1] * dy) + rv3d->viewinv[3][1]; - line_sta[2] = (rv3d->persinv[0][2] * dx) + (rv3d->persinv[1][2] * dy) + rv3d->viewinv[3][2]; - - add_v3_v3v3(line_end, line_sta, rv3d->viewinv[2]); - closest_to_line_v3(out, depth_pt, line_sta, line_end); - } -} - -/* always call initgrabz */ -/* only to detect delta motion */ -void ED_view3d_win_to_delta(ARegion *ar, const float mval[2], float out[3]) -{ - RegionView3D *rv3d = ar->regiondata; - float dx, dy; - - dx = 2.0f * mval[0] * rv3d->zfac / ar->winx; - dy = 2.0f * mval[1] * rv3d->zfac / ar->winy; - - out[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy); - out[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy); - out[2] = (rv3d->persinv[0][2] * dx + rv3d->persinv[1][2] * dy); -} - -/* doesn't rely on initgrabz */ -/* for perspective view, get the vector direction to - * the mouse cursor as a normalized vector */ -void ED_view3d_win_to_vector(ARegion *ar, const float mval[2], float out[3]) -{ - RegionView3D *rv3d = ar->regiondata; - - if (rv3d->is_persp) { - out[0] = 2.0f * (mval[0] / ar->winx) - 1.0f; - out[1] = 2.0f * (mval[1] / ar->winy) - 1.0f; - out[2] = -0.5f; - mul_project_m4_v3(rv3d->persinv, out); - sub_v3_v3(out, rv3d->viewinv[3]); - } - else { - copy_v3_v3(out, rv3d->viewinv[2]); - } - normalize_v3(out); + return 0; } float ED_view3d_depth_read_cached(ViewContext *vc, int x, int y) @@ -744,253 +627,6 @@ void ED_view3d_depth_tag_update(RegionView3D *rv3d) rv3d->depths->damaged = 1; } -void ED_view3d_ob_project_mat_get(RegionView3D *rv3d, Object *ob, float pmat[4][4]) -{ - float vmat[4][4]; - - mult_m4_m4m4(vmat, rv3d->viewmat, ob->obmat); - mult_m4_m4m4(pmat, rv3d->winmat, vmat); -} - -/* Uses window coordinates (x,y) and depth component z to find a point in - * modelspace */ -void view3d_unproject(bglMats *mats, float out[3], const short x, const short y, const float z) -{ - double ux, uy, uz; - - gluUnProject(x, y, z, mats->modelview, mats->projection, - (GLint *)mats->viewport, &ux, &uy, &uz); - - out[0] = ux; - out[1] = uy; - out[2] = uz; -} - -/* use view3d_get_object_project_mat to get projecting mat */ -void ED_view3d_project_float_v2(const ARegion *ar, const float vec[3], float adr[2], float mat[4][4]) -{ - float vec4[4]; - - copy_v3_v3(vec4, vec); - vec4[3] = 1.0; - /* adr[0]= IS_CLIPPED; */ /* always overwritten */ - - mul_m4_v4(mat, vec4); - - if (vec4[3] > FLT_EPSILON) { - adr[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3]; - adr[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3]; - } - else { - adr[0] = adr[1] = 0.0f; - } -} - -/* use view3d_get_object_project_mat to get projecting mat */ -void ED_view3d_project_float_v3(ARegion *ar, const float vec[3], float adr[3], float mat[4][4]) -{ - float vec4[4]; - - copy_v3_v3(vec4, vec); - vec4[3] = 1.0; - /* adr[0]= IS_CLIPPED; */ /* always overwritten */ - - mul_m4_v4(mat, vec4); - - if (vec4[3] > FLT_EPSILON) { - adr[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3]; - adr[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3]; - adr[2] = vec4[2] / vec4[3]; - } - else { - zero_v3(adr); - } -} - -int ED_view3d_boundbox_clip(RegionView3D *rv3d, float obmat[][4], BoundBox *bb) -{ - /* return 1: draw */ - - float mat[4][4]; - float vec[4], min, max; - int a, flag = -1, fl; - - if (bb == NULL) return 1; - if (bb->flag & OB_BB_DISABLED) return 1; - - mult_m4_m4m4(mat, rv3d->persmat, obmat); - - for (a = 0; a < 8; a++) { - copy_v3_v3(vec, bb->vec[a]); - vec[3] = 1.0; - mul_m4_v4(mat, vec); - max = vec[3]; - min = -vec[3]; - - fl = 0; - if (vec[0] < min) fl += 1; - if (vec[0] > max) fl += 2; - if (vec[1] < min) fl += 4; - if (vec[1] > max) fl += 8; - if (vec[2] < min) fl += 16; - if (vec[2] > max) fl += 32; - - flag &= fl; - if (flag == 0) return 1; - } - - return 0; -} - -void project_short(ARegion *ar, const float vec[3], short adr[2]) /* clips */ -{ - RegionView3D *rv3d = ar->regiondata; - float fx, fy, vec4[4]; - - adr[0] = IS_CLIPPED; - - if (rv3d->rflag & RV3D_CLIPPING) { - if (ED_view3d_clipping_test(rv3d, vec, FALSE)) { - return; - } - } - - copy_v3_v3(vec4, vec); - vec4[3] = 1.0; - mul_m4_v4(rv3d->persmat, vec4); - - if (vec4[3] > (float)BL_NEAR_CLIP) { /* 0.001 is the NEAR clipping cutoff for picking */ - fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]); - - if (fx > 0 && fx < ar->winx) { - - fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]); - - if (fy > 0.0f && fy < (float)ar->winy) { - adr[0] = (short)floor(fx); - adr[1] = (short)floor(fy); - } - } - } -} - -void project_int(ARegion *ar, const float vec[3], int adr[2]) -{ - RegionView3D *rv3d = ar->regiondata; - float fx, fy, vec4[4]; - - copy_v3_v3(vec4, vec); - vec4[3] = 1.0; - adr[0] = (int)2140000000.0f; - - mul_m4_v4(rv3d->persmat, vec4); - - if (vec4[3] > (float)BL_NEAR_CLIP) { /* 0.001 is the NEAR clipping cutoff for picking */ - fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]); - - if (fx > -2140000000.0f && fx < 2140000000.0f) { - fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]); - - if (fy > -2140000000.0f && fy < 2140000000.0f) { - adr[0] = (int)floor(fx); - adr[1] = (int)floor(fy); - } - } - } -} - -void project_int_noclip(ARegion *ar, const float vec[3], int adr[2]) -{ - RegionView3D *rv3d = ar->regiondata; - float fx, fy, vec4[4]; - - copy_v3_v3(vec4, vec); - vec4[3] = 1.0; - - mul_m4_v4(rv3d->persmat, vec4); - - if (fabs(vec4[3]) > BL_NEAR_CLIP) { - fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]); - fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]); - - adr[0] = (int)floor(fx); - adr[1] = (int)floor(fy); - } - else { - adr[0] = ar->winx / 2; - adr[1] = ar->winy / 2; - } -} - -void project_short_noclip(ARegion *ar, const float vec[3], short adr[2]) -{ - RegionView3D *rv3d = ar->regiondata; - float fx, fy, vec4[4]; - - copy_v3_v3(vec4, vec); - vec4[3] = 1.0; - adr[0] = IS_CLIPPED; - - mul_m4_v4(rv3d->persmat, vec4); - - if (vec4[3] > (float)BL_NEAR_CLIP) { /* 0.001 is the NEAR clipping cutoff for picking */ - fx = (ar->winx / 2) * (1 + vec4[0] / vec4[3]); - - if (fx > -32700 && fx < 32700) { - - fy = (ar->winy / 2) * (1 + vec4[1] / vec4[3]); - - if (fy > -32700.0f && fy < 32700.0f) { - adr[0] = (short)floor(fx); - adr[1] = (short)floor(fy); - } - } - } -} - -void apply_project_float(float persmat[4][4], int winx, int winy, const float vec[3], float adr[2]) -{ - float vec4[4]; - - copy_v3_v3(vec4, vec); - vec4[3] = 1.0; - adr[0] = IS_CLIPPED; - - mul_m4_v4(persmat, vec4); - - if (vec4[3] > (float)BL_NEAR_CLIP) { - adr[0] = (float)(winx / 2.0f) + (winx / 2.0f) * vec4[0] / vec4[3]; - adr[1] = (float)(winy / 2.0f) + (winy / 2.0f) * vec4[1] / vec4[3]; - } -} - -void project_float(ARegion *ar, const float vec[3], float adr[2]) -{ - RegionView3D *rv3d = ar->regiondata; - - apply_project_float(rv3d->persmat, ar->winx, ar->winy, vec, adr); -} - -void project_float_noclip(ARegion *ar, const float vec[3], float adr[2]) -{ - RegionView3D *rv3d = ar->regiondata; - float vec4[4]; - - copy_v3_v3(vec4, vec); - vec4[3] = 1.0; - - mul_m4_v4(rv3d->persmat, vec4); - - if (fabs(vec4[3]) > BL_NEAR_CLIP) { - adr[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3]; - adr[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3]; - } - else { - adr[0] = ar->winx / 2.0f; - adr[1] = ar->winy / 2.0f; - } -} - /* copies logic of get_view3d_viewplane(), keep in sync */ int ED_view3d_clip_range_get(View3D *v3d, RegionView3D *rv3d, float *clipsta, float *clipend) { @@ -1022,7 +658,10 @@ int ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winx, int winy, return params.is_ortho; } -void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect) /* rect: for picking */ +/*! + * \param rect for picking, NULL not to use. + */ +void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect) { RegionView3D *rv3d = ar->regiondata; rctf viewplane; @@ -1055,7 +694,7 @@ void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect) /* rect: for if (orth) wmOrtho(rect->xmin, rect->xmax, rect->ymin, rect->ymax, -clipend, clipend); else wmFrustum(rect->xmin, rect->xmax, rect->ymin, rect->ymax, clipsta, clipend); - + } else { if (orth) wmOrtho(x1, x2, y1, y2, clipsta, clipend); @@ -1151,7 +790,7 @@ void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d) { if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */ if (v3d->camera) { - BKE_object_where_is_calc(scene, v3d->camera); + BKE_object_where_is_calc(scene, v3d->camera); obmat_to_viewmat(v3d, rv3d, v3d->camera, 0); } else { @@ -1256,14 +895,14 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b glLoadName(code); draw_object(scene, ar, v3d, base, DRAW_PICKING | DRAW_CONSTCOLOR); - /* we draw group-duplicators for selection too */ - if ((base->object->transflag & OB_DUPLI) && base->object->dup_group) { + /* we draw duplicators for selection too */ + if ((base->object->transflag & OB_DUPLI)) { ListBase *lb; DupliObject *dob; Base tbase; tbase.flag = OB_FROMDUPLI; - lb = object_duplilist(scene, base->object); + lb = object_duplilist(scene, base->object, FALSE); for (dob = lb->first; dob; dob = dob->next) { tbase.object = dob->ob; @@ -1284,7 +923,7 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b free_object_duplilist(lb); } code++; - } + } } } v3d->xray = FALSE; /* restore */ @@ -1402,7 +1041,7 @@ static int view3d_localview_init(Main *bmain, Scene *scene, ScrArea *sa, ReportL locallay = free_localbit(bmain); if (locallay == 0) { - BKE_reportf(reports, RPT_ERROR, "No more than 8 localviews"); + BKE_report(reports, RPT_ERROR, "No more than 8 local views"); ok = FALSE; } else { @@ -1557,7 +1196,7 @@ static int view3d_localview_exit(Main *bmain, Scene *scene, ScrArea *sa) DAG_on_visible_update(bmain, FALSE); return TRUE; - } + } else { return FALSE; } @@ -1591,7 +1230,6 @@ static int localview_exec(bContext *C, wmOperator *op) void VIEW3D_OT_localview(wmOperatorType *ot) { - /* identifiers */ ot->name = "Local View"; ot->description = "Toggle display of selected object(s) separately and centered in view"; @@ -1631,12 +1269,12 @@ static void RestoreState(bContext *C, wmWindow *win) GPU_paint_set_mipmap(0); //XXX curarea->win_swap = 0; - //XXX curarea->head_swap=0; + //XXX curarea->head_swap = 0; //XXX allqueue(REDRAWVIEW3D, 1); //XXX allqueue(REDRAWBUTSALL, 0); //XXX reset_slowparents(); //XXX waitcursor(0); - //XXX G.qual= 0; + //XXX G.qual = 0; if (win) /* check because closing win can set to NULL */ win->queue = queue_back; @@ -1761,7 +1399,7 @@ static int game_engine_exec(bContext *C, wmOperator *op) WM_redraw_windows(C); rv3d = CTX_wm_region_view3d(C); - /* sa= CTX_wm_area(C); */ /* UNUSED */ + /* sa = CTX_wm_area(C); */ /* UNUSED */ ar = CTX_wm_region(C); view3d_operator_needs_opengl(C); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index a3fb4e851e2..245241763fd 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -57,6 +57,8 @@ #include "BIF_gl.h" #include "BIF_glutil.h" +#include "BLF_api.h" + #include "BKE_nla.h" #include "BKE_bmesh.h" #include "BKE_context.h" @@ -89,12 +91,11 @@ #include "BLI_smallhash.h" #include "BLI_array.h" +#include "UI_interface_icons.h" #include "UI_resources.h" #include "transform.h" -#include - static void drawTransformApply(const struct bContext *C, ARegion *ar, void *arg); static int doEdgeSlide(TransInfo *t, float perc); @@ -126,11 +127,11 @@ static void convertViewVec2D(View2D *v2d, float r_vec[3], int dx, int dy) { float divx, divy; - divx = BLI_RCT_SIZE_X(&v2d->mask); - divy = BLI_RCT_SIZE_Y(&v2d->mask); + divx = BLI_rcti_size_x(&v2d->mask); + divy = BLI_rcti_size_y(&v2d->mask); - r_vec[0] = BLI_RCT_SIZE_X(&v2d->cur) * dx / divx; - r_vec[1] = BLI_RCT_SIZE_Y(&v2d->cur) * dy / divy; + r_vec[0] = BLI_rctf_size_x(&v2d->cur) * dx / divx; + r_vec[1] = BLI_rctf_size_y(&v2d->cur) * dy / divy; r_vec[2] = 0.0f; } @@ -139,11 +140,11 @@ static void convertViewVec2D_mask(View2D *v2d, float r_vec[3], int dx, int dy) float divx, divy; float mulx, muly; - divx = BLI_RCT_SIZE_X(&v2d->mask); - divy = BLI_RCT_SIZE_Y(&v2d->mask); + divx = BLI_rcti_size_x(&v2d->mask); + divy = BLI_rcti_size_y(&v2d->mask); - mulx = BLI_RCT_SIZE_X(&v2d->cur); - muly = BLI_RCT_SIZE_Y(&v2d->cur); + mulx = BLI_rctf_size_x(&v2d->cur); + muly = BLI_rctf_size_y(&v2d->cur); /* difference with convertViewVec2D */ /* clamp w/h, mask only */ @@ -225,8 +226,12 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy) void projectIntView(TransInfo *t, const float vec[3], int adr[2]) { if (t->spacetype == SPACE_VIEW3D) { - if (t->ar->regiontype == RGN_TYPE_WINDOW) - project_int_noclip(t->ar, vec, adr); + if (t->ar->regiontype == RGN_TYPE_WINDOW) { + if (ED_view3d_project_int_global(t->ar, vec, adr, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) { + adr[0] = (int)2140000000.0f; /* this is what was done in 2.64, perhaps we can be smarter? */ + adr[1] = (int)2140000000.0f; + } + } } else if (t->spacetype == SPACE_IMAGE) { SpaceImage *sima = t->sa->spacedata.first; @@ -272,7 +277,7 @@ void projectIntView(TransInfo *t, const float vec[3], int adr[2]) //vec[0] = vec[0]/((t->scene->r.frs_sec / t->scene->r.frs_sec_base)); /* same as below */ UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], vec[1], out, out + 1); - } + } else #endif { @@ -332,6 +337,9 @@ void projectIntView(TransInfo *t, const float vec[3], int adr[2]) UI_view2d_to_region_no_clip(t->view, v[0], v[1], adr, adr + 1); } + else { + BLI_assert(0); + } } else if (t->spacetype == SPACE_NODE) { UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], vec[1], adr, adr + 1); @@ -344,7 +352,11 @@ void projectFloatView(TransInfo *t, const float vec[3], float adr[2]) case SPACE_VIEW3D: { if (t->ar->regiontype == RGN_TYPE_WINDOW) { - project_float_noclip(t->ar, vec, adr); + if (ED_view3d_project_float_global(t->ar, vec, adr, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) { + /* XXX, 2.64 and prior did this, weak! */ + adr[0] = t->ar->winx / 2.0f; + adr[1] = t->ar->winy / 2.0f; + } return; } break; @@ -457,11 +469,11 @@ static void viewRedrawForce(const bContext *C, TransInfo *t) } else if (t->spacetype == SPACE_ACTION) { - //SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first; + //SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first; WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); } else if (t->spacetype == SPACE_IPO) { - //SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first; + //SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first; WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); } else if (t->spacetype == SPACE_NLA) { @@ -816,7 +828,7 @@ int transformEvent(TransInfo *t, wmEvent *event) float mati[3][3] = MAT3_UNITY; char cmode = constraintModeToChar(t); int handled = 1; - + t->redraw |= handleMouseInput(t, &t->mouse, event); if (event->type == MOUSEMOVE) { @@ -1011,7 +1023,7 @@ int transformEvent(TransInfo *t, wmEvent *event) if (t->flag & T_PROP_EDIT) { t->prop_size *= 1.1f; if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) - t->prop_size = minf(t->prop_size, ((View3D *)t->view)->far); + t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far); calculatePropRatio(t); } t->redraw |= TREDRAW_HARD; @@ -1181,7 +1193,7 @@ int transformEvent(TransInfo *t, wmEvent *event) if (event->alt && t->flag & T_PROP_EDIT) { t->prop_size *= 1.1f; if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) - t->prop_size = minf(t->prop_size, ((View3D *)t->view)->far); + t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far); calculatePropRatio(t); } t->redraw = 1; @@ -1209,6 +1221,12 @@ int transformEvent(TransInfo *t, wmEvent *event) else view_editmove(event->type); t->redraw = 1; break; + case LEFTALTKEY: + case RIGHTALTKEY: + if (t->spacetype == SPACE_SEQ) + t->flag |= T_ALT_TRANSFORM; + + break; default: handled = 0; break; @@ -1242,6 +1260,12 @@ int transformEvent(TransInfo *t, wmEvent *event) //// if (t->options & CTX_TWEAK) // t->state = TRANS_CONFIRM; // break; + case LEFTALTKEY: + case RIGHTALTKEY: + if (t->spacetype == SPACE_SEQ) + t->flag &= ~T_ALT_TRANSFORM; + + break; default: handled = 0; break; @@ -1255,15 +1279,19 @@ int transformEvent(TransInfo *t, wmEvent *event) } } } + else + handled = 0; // Per transform event, if present if (t->handleEvent) t->redraw |= t->handleEvent(t, event); - if (handled || t->redraw) + if (handled || t->redraw) { return 0; - else + } + else { return OPERATOR_PASS_THROUGH; + } } int calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], int cent2d[2]) @@ -1473,8 +1501,8 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) float dx = t->mval[0] - cent[0], dy = t->mval[1] - cent[1]; float angle = atan2f(dy, dx); float dist = sqrtf(dx * dx + dy * dy); - float delta_angle = minf(15.0f / dist, (float)M_PI / 4.0f); - float spacing_angle = minf(5.0f / dist, (float)M_PI / 12.0f); + float delta_angle = min_ff(15.0f / dist, (float)M_PI / 4.0f); + float spacing_angle = min_ff(5.0f / dist, (float)M_PI / 12.0f); UI_ThemeColor(TH_WIRE); setlinestyle(3); @@ -1546,14 +1574,55 @@ static void drawTransformView(const struct bContext *C, ARegion *UNUSED(ar), voi drawNonPropEdge(C, t); } -#if 0 -static void drawTransformPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar), void *UNUSED(arg)) +/* just draw a little warning message in the top-right corner of the viewport to warn that autokeying is enabled */ +static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar) { -// TransInfo *t = arg; -// -// drawHelpline(C, t->mval[0], t->mval[1], t); + const char printable[] = "Auto Keying On"; + float printable_size[2]; + int xco, yco; + + BLF_width_and_height_default(printable, &printable_size[0], &printable_size[1]); + + xco = ar->winx - (int)printable_size[0] - 10; + yco = ar->winy - (int)printable_size[1] - 10; + + /* warning text (to clarify meaning of overlays) + * - original color was red to match the icon, but that clashes badly with a less nasty border + */ + UI_ThemeColorShade(TH_TEXT_HI, -50); + BLF_draw_default_ascii(xco, ar->winy - 17, 0.0f, printable, sizeof(printable)); + + /* autokey recording icon... */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + xco -= (ICON_DEFAULT_WIDTH + 2); + UI_icon_draw(xco, yco, ICON_REC); + + glDisable(GL_BLEND); +} + +static void drawTransformPixel(const struct bContext *UNUSED(C), ARegion *ar, void *arg) +{ + TransInfo *t = arg; + Scene *scene = t->scene; + Object *ob = OBACT; + + /* draw autokeyframing hint in the corner + * - only draw if enabled (advanced users may be distracted/annoyed), + * for objects that will be autokeyframed (no point ohterwise), + * AND only for the active region (as showing all is too overwhelming) + */ + if ((U.autokey_flag & AUTOKEY_FLAG_NOWARNING) == 0) { + if (ar == t->ar) { + if (t->flag & (T_OBJECT | T_POSE)) { + if (ob && autokeyframe_cfra_can_key(scene, &ob->id)) { + drawAutoKeyWarning(t, ar); + } + } + } + } } -#endif void saveTransform(bContext *C, TransInfo *t, wmOperator *op) { @@ -1723,7 +1792,7 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW); t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); + t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t); } else if (t->spacetype == SPACE_IMAGE) { @@ -2195,7 +2264,6 @@ static void constraintTransLim(TransInfo *t, TransData *td) for (con = td->con; con; con = con->next) { bConstraintTypeInfo *cti = NULL; ListBase targets = {NULL, NULL}; - float tmat[4][4]; /* only consider constraint if enabled */ if (con->flag & CONSTRAINT_DISABLE) continue; @@ -2221,8 +2289,7 @@ static void constraintTransLim(TransInfo *t, TransData *td) /* do space conversions */ if (con->ownspace == CONSTRAINT_SPACE_WORLD) { /* just multiply by td->mtx (this should be ok) */ - copy_m4_m4(tmat, cob.matrix); - mul_m4_m3m4(cob.matrix, td->mtx, tmat); + mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix); } else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) { /* skip... incompatable spacetype */ @@ -2237,9 +2304,8 @@ static void constraintTransLim(TransInfo *t, TransData *td) /* convert spaces again */ if (con->ownspace == CONSTRAINT_SPACE_WORLD) { - /* just multiply by td->mtx (this should be ok) */ - copy_m4_m4(tmat, cob.matrix); - mul_m4_m3m4(cob.matrix, td->smtx, tmat); + /* just multiply by td->smtx (this should be ok) */ + mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix); } /* free targets list */ @@ -2287,18 +2353,17 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td) bConstraintOb cob; bConstraint *con; int do_limit = FALSE; - + /* Evaluate valid constraints */ for (con = td->con; con; con = con->next) { /* only consider constraint if enabled */ if (con->flag & CONSTRAINT_DISABLE) continue; if (con->enforce == 0.0f) continue; - + /* we're only interested in Limit-Rotation constraints */ if (con->type == CONSTRAINT_TYPE_ROTLIMIT) { bRotLimitConstraint *data = con->data; - float tmat[4][4]; - + /* only use it if it's tagged for this purpose */ if ((data->flag2 & LIMIT_TRANSFORM) == 0) continue; @@ -2312,12 +2377,11 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td) constraintob_from_transdata(&cob, td); do_limit = TRUE; } - + /* do space conversions */ if (con->ownspace == CONSTRAINT_SPACE_WORLD) { /* just multiply by td->mtx (this should be ok) */ - copy_m4_m4(tmat, cob.matrix); - mul_m4_m3m4(cob.matrix, td->mtx, tmat); + mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix); } /* do constraint */ @@ -2325,9 +2389,8 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td) /* convert spaces again */ if (con->ownspace == CONSTRAINT_SPACE_WORLD) { - /* just multiply by td->mtx (this should be ok) */ - copy_m4_m4(tmat, cob.matrix); - mul_m4_m3m4(cob.matrix, td->smtx, tmat); + /* just multiply by td->smtx (this should be ok) */ + mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix); } } } @@ -2382,7 +2445,6 @@ static void constraintSizeLim(TransInfo *t, TransData *td) /* we're only interested in Limit-Scale constraints */ if (con->type == CONSTRAINT_TYPE_SIZELIMIT) { bSizeLimitConstraint *data = con->data; - float tmat[4][4]; /* only use it if it's tagged for this purpose */ if ((data->flag2 & LIMIT_TRANSFORM) == 0) @@ -2391,11 +2453,10 @@ static void constraintSizeLim(TransInfo *t, TransData *td) /* do space conversions */ if (con->ownspace == CONSTRAINT_SPACE_WORLD) { /* just multiply by td->mtx (this should be ok) */ - copy_m4_m4(tmat, cob.matrix); - mul_m4_m3m4(cob.matrix, td->mtx, tmat); + mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix); } else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) { - /* skip... incompatable spacetype */ + /* skip... incompatible spacetype */ continue; } @@ -2404,13 +2465,12 @@ static void constraintSizeLim(TransInfo *t, TransData *td) /* convert spaces again */ if (con->ownspace == CONSTRAINT_SPACE_WORLD) { - /* just multiply by td->mtx (this should be ok) */ - copy_m4_m4(tmat, cob.matrix); - mul_m4_m3m4(cob.matrix, td->smtx, tmat); + /* just multiply by td->smtx (this should be ok) */ + mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix); } } } - + /* copy results from cob->matrix */ if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { /* scale val and reset size */ @@ -2420,7 +2480,7 @@ static void constraintSizeLim(TransInfo *t, TransData *td) /* Reset val if SINGLESIZE but using a constraint */ if (td->flag & TD_SINGLESIZE) return; - + mat4_to_size(td->ext->size, cob.matrix); } } @@ -2852,11 +2912,11 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) if (t->flag & (T_OBJECT | T_TEXTURE | T_POSE)) { float obsizemat[3][3]; - // Reorient the size mat to fit the oriented object. + /* Reorient the size mat to fit the oriented object. */ mul_m3_m3m3(obsizemat, tmat, td->axismtx); - //print_m3("obsizemat", obsizemat); + /* print_m3("obsizemat", obsizemat); */ TransMat3ToSize(obsizemat, td->axismtx, fsize); - //print_v3("fsize", fsize); + /* print_v3("fsize", fsize); */ } else { mat3_to_size(fsize, tmat); @@ -2864,7 +2924,7 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) protectedSizeBits(td->protectflag, fsize); - if ((t->flag & T_V3D_ALIGN) == 0) { // align mode doesn't resize objects itself + if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't resize objects itself */ if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { /* scale val and reset size */ *td->val = td->ival * (1 + (fsize[0] - 1) * td->factor); @@ -3339,7 +3399,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short /* this function works on end result */ protectedAxisAngleBits(td->protectflag, td->ext->rotAxis, td->ext->rotAngle, td->ext->irotAxis, td->ext->irotAngle); } - else { + else { float eulmat[3][3]; mul_m3_m3m3(totmat, mat, td->ext->r_mtx); @@ -3915,7 +3975,7 @@ int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) sprintf(str, "Shrink/Fatten: %.4f %s", distance, t->proptext); } - t->values[0] = distance; + t->values[0] = -distance; for (i = 0; i < t->total; i++, td++) { if (td->flag & TD_NOACTION) @@ -3979,12 +4039,15 @@ int Tilt(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, "Tilt: %s %s", &c[0], t->proptext); + sprintf(str, "Tilt: %s° %s", &c[0], t->proptext); final = DEG2RADF(final); + + /* XXX For some reason, this seems needed for this op, else RNA prop is not updated... :/ */ + t->values[0] = final; } else { - sprintf(str, "Tilt: %.2f %s", RAD2DEGF(final), t->proptext); + sprintf(str, "Tilt: %.2f° %s", RAD2DEGF(final), t->proptext); } for (i = 0; i < t->total; i++, td++) { @@ -4100,9 +4163,9 @@ void initMaskShrinkFatten(TransInfo *t) int MaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) { - TransData *td = t->data; + TransData *td; float ratio; - int i; + int i, initial_feather = FALSE; char str[50]; ratio = t->values[0]; @@ -4116,13 +4179,30 @@ int MaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) char c[NUM_STR_REP_LEN]; outputNumInput(&(t->num), c); - sprintf(str, "Shrink/Fatten: %s", c); + sprintf(str, "Feather Shrink/Fatten: %s", c); } else { - sprintf(str, "Shrink/Fatten: %3f", ratio); + sprintf(str, "Feather Shrink/Fatten: %3f", ratio); } - for (i = 0; i < t->total; i++, td++) { + /* detect if no points have feather yet */ + if (ratio > 1.0f) { + initial_feather = TRUE; + + for (td = t->data, i = 0; i < t->total; i++, td++) { + if (td->flag & TD_NOACTION) + break; + + if (td->flag & TD_SKIP) + continue; + + if (td->ival >= 0.001f) + initial_feather = FALSE; + } + } + + /* apply shrink/fatten */ + for (td = t->data, i = 0; i < t->total; i++, td++) { if (td->flag & TD_NOACTION) break; @@ -4130,7 +4210,11 @@ int MaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) continue; if (td->val) { - *td->val = td->ival * ratio; + if (initial_feather) + *td->val = td->ival + (ratio - 1.0f) * 0.01f; + else + *td->val = td->ival * ratio; + /* apply PET */ *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); if (*td->val <= 0.0f) *td->val = 0.001f; @@ -4721,8 +4805,7 @@ static BMLoop *get_next_loop(BMVert *v, BMLoop *l, cross_v3_v3v3(a, f2, l->f->no); mul_v3_fl(a, -1.0f); - add_v3_v3(a, f3); - mul_v3_fl(a, 0.5f); + mid_v3_v3v3(a, a, f3); } copy_v3_v3(vec, a); @@ -4743,7 +4826,7 @@ static BMLoop *get_next_loop(BMVert *v, BMLoop *l, } l = l->radial_next; - } while (l != firstl); + } while (l != firstl); if (i) mul_v3_fl(a, 1.0f / (float)i); @@ -4774,12 +4857,12 @@ static void calcNonProportionalEdgeSlide(TransInfo *t, SlideData *sld, const flo sv->edge_len = len_v3v3(dw_p, up_p); mul_v3_m4v3(v_proj, t->obedit->obmat, sv->v->co); - project_float_noclip(t->ar, v_proj, v_proj); - - dist = len_squared_v2v2(mval, v_proj); - if (dist < min_dist) { - min_dist = dist; - sld->curr_sv_index = i; + if (ED_view3d_project_float_global(t->ar, v_proj, v_proj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + dist = len_squared_v2v2(mval, v_proj); + if (dist < min_dist) { + min_dist = dist; + sld->curr_sv_index = i; + } } } } @@ -4792,10 +4875,9 @@ static int createSlideVerts(TransInfo *t) { BMEditMesh *em = BMEdit_FromObject(t->obedit); BMesh *bm = em->bm; - BMIter iter, iter2; + BMIter iter; BMEdge *e, *e1; BMVert *v, *v2, *first; - BMLoop *l, *l1, *l2; TransDataSlideVert *sv_array; BMBVHTree *btree = BMBVH_NewBVH(em, BMBVH_RESPECT_HIDDEN, NULL, NULL); SmallHash table; @@ -4835,6 +4917,7 @@ static int createSlideVerts(TransInfo *t) /*ensure valid selection*/ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { + BMIter iter2; numsel = 0; BM_ITER_ELEM (e, &iter2, v, BM_EDGES_OF_VERT) { if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { @@ -4887,6 +4970,8 @@ static int createSlideVerts(TransInfo *t) j = 0; while (1) { + BMLoop *l, *l1, *l2; + v = NULL; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_TAG)) @@ -5020,7 +5105,7 @@ static int createSlideVerts(TransInfo *t) if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { BMIter iter2; BMEdge *e2; - float vec1[3], mval[2] = {t->mval[0], t->mval[1]}, d; + float vec1[3], d; /* search cross edges for visible edge to the mouse cursor, * then use the shared vertex to calculate screen vector*/ @@ -5040,19 +5125,19 @@ static int createSlideVerts(TransInfo *t) j = GET_INT_FROM_POINTER(BLI_smallhash_lookup(&table, (uintptr_t)v)); if (sv_array[j].down) { - ED_view3d_project_float_v3(ar, sv_array[j].down->co, vec1, projectMat); + ED_view3d_project_float_v3_m4(ar, sv_array[j].down->co, vec1, projectMat); } else { add_v3_v3v3(vec1, v->co, sv_array[j].downvec); - ED_view3d_project_float_v3(ar, vec1, vec1, projectMat); + ED_view3d_project_float_v3_m4(ar, vec1, vec1, projectMat); } if (sv_array[j].up) { - ED_view3d_project_float_v3(ar, sv_array[j].up->co, vec2, projectMat); + ED_view3d_project_float_v3_m4(ar, sv_array[j].up->co, vec2, projectMat); } else { add_v3_v3v3(vec2, v->co, sv_array[j].upvec); - ED_view3d_project_float_v3(ar, vec2, vec2, projectMat); + ED_view3d_project_float_v3_m4(ar, vec2, vec2, projectMat); } /* global direction */ @@ -5443,7 +5528,7 @@ void drawNonPropEdge(const struct bContext *C, TransInfo *t) float v1[3], v2[3]; float interp_v; TransDataSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; - const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5; + const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; const float guide_size = ctrl_size - 0.5f; const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; const int alpha_shade = -30; @@ -5514,42 +5599,42 @@ static int doEdgeSlide(TransInfo *t, float perc) int i; sld->perc = perc; - sv = svlist; - for (i = 0; i < sld->totsv; i++, sv++) { - if (sld->is_proportional == FALSE) { - TransDataSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; - float cur_sel = curr_sv->edge_len; - float cur_sv = sv->edge_len; - float extd = 0.0f; - float recip_cur_sv = 0.0f; - if (cur_sel == 0.0f) cur_sel = 1.0f; - if (cur_sv == 0.0f) cur_sv = 1.0f; - - recip_cur_sv = 1.0f / cur_sv; - - if (!sld->flipped_vtx) { - extd = (cur_sv - cur_sel) * recip_cur_sv; + if (sld->is_proportional == TRUE) { + for (i = 0; i < sld->totsv; i++, sv++) { + if (perc > 0.0f) { + copy_v3_v3(vec, sv->upvec); + mul_v3_fl(vec, perc); + add_v3_v3v3(sv->v->co, sv->origvert.co, vec); } else { - extd = (cur_sel - cur_sv) * recip_cur_sv; + copy_v3_v3(vec, sv->downvec); + mul_v3_fl(vec, -perc); + add_v3_v3v3(sv->v->co, sv->origvert.co, vec); } - - extd += (sld->perc * cur_sel) * recip_cur_sv; - CLAMP(extd, -1.0f, 1.0f); - perc = extd; } + } + else { + /** + * Implementation note, non proportional mode ignores the starting positions and uses only the + * up/down verts, this could be changed/improved so the distance is still met but the verts are moved along + * their original path (which may not be straight), however how it works now is OK and matches 2.4x - Campbell + */ + TransDataSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + const float curr_length_perc = len_v3v3(curr_sv->up->co, curr_sv->down->co) * + (((sld->flipped_vtx ? perc : -perc) + 1.0f) / 2.0f); - if (perc > 0.0f) { - copy_v3_v3(vec, sv->upvec); - mul_v3_fl(vec, perc); - add_v3_v3v3(sv->v->co, sv->origvert.co, vec); - } - else { - copy_v3_v3(vec, sv->downvec); - mul_v3_fl(vec, -perc); - add_v3_v3v3(sv->v->co, sv->origvert.co, vec); + for (i = 0; i < sld->totsv; i++, sv++) { + const float sv_length = len_v3v3(sv->up->co, sv->down->co); + const float fac = min_ff(sv_length, curr_length_perc) / sv_length; + + if (sld->flipped_vtx) { + interp_v3_v3v3(sv->v->co, sv->down->co, sv->up->co, fac); + } + else { + interp_v3_v3v3(sv->v->co, sv->up->co, sv->down->co, fac); + } } } @@ -6038,7 +6123,7 @@ static short getAnimEdit_DrawTime(TransInfo *t) SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first; drawtime = (sipo->flag & SIPO_DRAWTIME) ? 1 : 0; - } + } else { drawtime = 0; } @@ -6519,5 +6604,5 @@ int TimeScale(TransInfo *t, const int UNUSED(mval[2])) void BIF_TransformSetUndo(const char *UNUSED(str)) { // TRANSFORM_FIX_ME - //Trans.undostr= str; + //Trans.undostr = str; } diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index e645cb2fed6..1f9775821d1 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -322,7 +322,7 @@ typedef struct TransInfo { float auto_values[4]; float axis[3]; float axis_orig[3]; /* TransCon can change 'axis', store the original value here */ - + void *view; struct bContext *context; /* Only valid (non null) during an operator called function. */ struct ScrArea *sa; diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 0aa46a36afe..311cb5ee94d 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -782,7 +782,7 @@ void startConstraint(TransInfo *t) { t->con.mode |= CON_APPLY; *t->con.text = ' '; - t->num.idx_max = MIN2(getConstraintSpaceDimension(t) - 1, t->idx_max); + t->num.idx_max = min_ii(getConstraintSpaceDimension(t) - 1, t->idx_max); } void stopConstraint(TransInfo *t) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 181f9fe6036..f6b888d4881 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -76,6 +76,7 @@ #include "BKE_gpencil.h" #include "BKE_key.h" #include "BKE_main.h" +#include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_movieclip.h" #include "BKE_nla.h" @@ -124,62 +125,46 @@ static short constraints_list_needinv(TransInfo *t, ListBase *list); /* ************************** Functions *************************** */ -static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail, TransData *temp) +static int trans_data_compare_dist(const void *A, const void *B) { - TransData *ihead = head; - TransData *itail = tail; - *temp = *head; + const TransData *td_A = (const TransData*)A; + const TransData *td_B = (const TransData*)B; - while (head < tail) { - if (t->flag & T_PROP_CONNECTED) { - while ((tail->dist >= temp->dist) && (head < tail)) - tail--; - } - else { - while ((tail->rdist >= temp->rdist) && (head < tail)) - tail--; - } + if (td_A->dist < td_B->dist) + return -1; + else if (td_A->dist > td_B->dist) + return 1; + + return 0; +} - if (head != tail) { - *head = *tail; - head++; - } +static int trans_data_compare_rdist(const void *A, const void *B) +{ + const TransData *td_A = (const TransData*)A; + const TransData *td_B = (const TransData*)B; - if (t->flag & T_PROP_CONNECTED) { - while ((head->dist <= temp->dist) && (head < tail)) - head++; - } - else { - while ((head->rdist <= temp->rdist) && (head < tail)) - head++; - } - - if (head != tail) { - *tail = *head; - tail--; - } - } - - *head = *temp; - if (ihead < head) { - qsort_trans_data(t, ihead, head - 1, temp); - } - if (itail > head) { - qsort_trans_data(t, head + 1, itail, temp); - } + if (td_A->rdist < td_B->rdist) + return -1; + else if (td_A->rdist > td_B->rdist) + return 1; + + return 0; } void sort_trans_data_dist(TransInfo *t) { - TransData temp; TransData *start = t->data; - int i = 1; + int i; - while (i < t->total && start->flag & TD_SELECTED) { + for (i = 0; i < t->total && start->flag & TD_SELECTED; i++) start++; - i++; + + if (i < t->total) { + if (t->flag & T_PROP_CONNECTED) + qsort(start, t->total - i, sizeof(TransData), trans_data_compare_dist); + else + qsort(start, t->total - i, sizeof(TransData), trans_data_compare_rdist); } - qsort_trans_data(t, start, t->data + t->total - 1, &temp); } static void sort_trans_data(TransInfo *t) @@ -332,13 +317,9 @@ static void createTransEdge(TransInfo *t) invert_m3_m3(smtx, mtx); BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { - if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && (BM_elem_flag_test(eed, BM_ELEM_SELECT) || propmode)) { - float *bweight = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_BWEIGHT); - float *crease = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE); - + if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && (BM_elem_flag_test(eed, BM_ELEM_SELECT) || propmode)) { /* need to set center for center calculations */ - add_v3_v3v3(td->center, eed->v1->co, eed->v2->co); - mul_v3_fl(td->center, 0.5f); + mid_v3_v3v3(td->center, eed->v1->co, eed->v2->co); td->loc = NULL; if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) @@ -346,16 +327,18 @@ static void createTransEdge(TransInfo *t) else td->flag = 0; - copy_m3_m3(td->smtx, smtx); copy_m3_m3(td->mtx, mtx); td->ext = NULL; if (t->mode == TFM_BWEIGHT) { + float *bweight = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_BWEIGHT); td->val = bweight; td->ival = bweight ? *bweight : 1.0f; } else { + float *crease = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE); + BLI_assert(t->mode == TFM_CREASE); td->val = crease; td->ival = crease ? *crease : 0.0f; } @@ -419,7 +402,7 @@ static short apply_targetless_ik(Object *ob) float rmat[4][4] /*, tmat[4][4], imat[4][4]*/; /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */ - /* we put in channel the entire result of rmat= (channel * constraint * IK) */ + /* we put in channel the entire result of rmat = (channel * constraint * IK) */ /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */ /* rmat = pose_mat(b) * inv(pose_mat(b-1) * offs_bone ) */ @@ -850,7 +833,7 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan) con = add_pose_constraint(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC); pchan->constflag |= (PCHAN_HAS_IK | PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */ data = con->data; - if (targetless) { + if (targetless) { /* if exists, use values from last targetless (but disabled) IK-constraint as base */ *data = *targetless; } @@ -973,7 +956,7 @@ static void createTransPose(TransInfo *t, Object *ob) if (arm->flag & ARM_RESTPOS) { if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE) == 0) { // XXX use transform operator reports - // BKE_report(op->reports, RPT_ERROR, "Can't select linked when sync selection is enabled"); + // BKE_report(op->reports, RPT_ERROR, "Cannot select linked when sync selection is enabled"); return; } } @@ -1334,10 +1317,9 @@ static TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struc return hdata; } -static void createTransCurveVerts(bContext *C, TransInfo *t) +static void createTransCurveVerts(TransInfo *t) { - Object *obedit = CTX_data_edit_object(C); - Curve *cu = obedit->data; + Curve *cu = t->obedit->data; TransData *td = NULL; Nurb *nu; BezTriple *bezt; @@ -1490,6 +1472,8 @@ static void createTransCurveVerts(bContext *C, TransInfo *t) count++; tail++; } + + (void)hdata; /* quiet warning */ } else if (propmode && head != tail) { calc_distanceCurveVerts(head, tail - 1); @@ -1773,9 +1757,6 @@ void flushTransParticles(TransInfo *t) /* ********************* mesh ****************** */ -/* proportional distance based on connectivity */ -#define THRESHOLDFACTOR (1.0f - 0.0001f) - /* I did this wrong, it should be a breadth-first search * but instead it's a depth-first search, fudged * to report shortest distances. I have no idea how fast @@ -1832,7 +1813,7 @@ static void editmesh_set_connectivity_distance(BMEditMesh *em, float mtx[][3], f d2 = d + len_v3(vec); if (dists[BM_elem_index_get(v3)] != FLT_MAX) - dists[BM_elem_index_get(v3)] = minf(d2, dists[BM_elem_index_get(v3)]); + dists[BM_elem_index_get(v3)] = min_ff(d2, dists[BM_elem_index_get(v3)]); else dists[BM_elem_index_get(v3)] = d2; @@ -1938,9 +1919,9 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx } } -static void createTransEditVerts(bContext *C, TransInfo *t) +static void createTransEditVerts(TransInfo *t) { - ToolSettings *ts = CTX_data_tool_settings(C); + ToolSettings *ts = t->scene->toolsettings; TransData *tob = NULL; TransDataExtension *tx = NULL; BMEditMesh *em = BMEdit_FromObject(t->obedit); @@ -2361,6 +2342,7 @@ static void createTransUVs(bContext *C, TransInfo *t) SpaceImage *sima = CTX_wm_space_image(C); Image *ima = CTX_data_edit_image(C); Scene *scene = t->scene; + ToolSettings *ts = CTX_data_tool_settings(C); TransData *td = NULL; TransData2D *td2d = NULL; MTexPoly *tf; @@ -2369,12 +2351,26 @@ static void createTransUVs(bContext *C, TransInfo *t) BMFace *efa; BMLoop *l; BMIter iter, liter; - int count = 0, countsel = 0; + UvElementMap *elementmap; + char *island_enabled; + int count = 0, countsel = 0, count_rejected = 0; int propmode = t->flag & T_PROP_EDIT; + int propconnected = t->flag & T_PROP_CONNECTED; if (!ED_space_image_show_uvedit(sima, t->obedit)) return; /* count */ + if (propconnected) { + /* create element map with island information */ + if (ts->uv_flag & UV_SYNC_SELECTION) { + elementmap = EDBM_uv_element_map_create (em, FALSE, TRUE); + } + else { + elementmap = EDBM_uv_element_map_create (em, TRUE, TRUE); + } + island_enabled = MEM_callocN(sizeof(*island_enabled) * elementmap->totalIslands, "TransIslandData(UV Editing)"); + } + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); @@ -2382,14 +2378,22 @@ static void createTransUVs(bContext *C, TransInfo *t) BM_elem_flag_disable(efa, BM_ELEM_TAG); continue; } - + BM_elem_flag_enable(efa, BM_ELEM_TAG); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (uvedit_uv_select_test(em, scene, l)) + if (uvedit_uv_select_test(em, scene, l)) { countsel++; - if (propmode) + if (propconnected) { + UvElement *element = ED_uv_element_get(elementmap, efa, l); + island_enabled[element->island] = TRUE; + } + + } + + if (propmode) { count++; + } } } @@ -2415,12 +2419,26 @@ static void createTransUVs(bContext *C, TransInfo *t) BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (!propmode && !uvedit_uv_select_test(em, scene, l)) continue; + + if (propconnected) { + UvElement *element = ED_uv_element_get(elementmap, efa, l); + if (!island_enabled[element->island]) { + count_rejected++; + continue; + } + } luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); UVsToTransData(sima, td++, td2d++, luv->uv, uvedit_uv_select_test(em, scene, l)); } } + if (propconnected) { + t->total -= count_rejected; + EDBM_uv_element_map_free(elementmap); + MEM_freeN(island_enabled); + } + if (sima->flag & SI_LIVE_UNWRAP) ED_uvedit_live_unwrap_begin(t->scene, t->obedit); } @@ -2512,8 +2530,8 @@ void clipUVData(TransInfo *t) if ((td->flag & TD_SKIP) || (!td->loc)) continue; - td->loc[0] = minf(maxf(0.0f, td->loc[0]), aspx); - td->loc[1] = minf(maxf(0.0f, td->loc[1]), aspy); + td->loc[0] = min_ff(max_ff(0.0f, td->loc[0]), aspx); + td->loc[1] = min_ff(max_ff(0.0f, td->loc[1]), aspy); } } @@ -3295,15 +3313,19 @@ static void createTransActionData(bContext *C, TransInfo *t) if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) { if (t->mode == TFM_TIME_SLIDE) { t->customData = MEM_callocN((sizeof(float) * 2) + (sizeof(tGPFtransdata) * count), "TimeSlide + tGPFtransdata"); + t->flag |= T_FREE_CUSTOMDATA; tfd = (tGPFtransdata *)((float *)(t->customData) + 2); } else { t->customData = MEM_callocN(sizeof(tGPFtransdata) * count, "tGPFtransdata"); + t->flag |= T_FREE_CUSTOMDATA; tfd = (tGPFtransdata *)(t->customData); } } - else if (t->mode == TFM_TIME_SLIDE) + else if (t->mode == TFM_TIME_SLIDE) { t->customData = MEM_callocN(sizeof(float) * 2, "TimeSlide Min/Max"); + t->flag |= T_FREE_CUSTOMDATA; + } /* loop 2: build transdata array */ for (ale = anim_data.first; ale; ale = ale->next) { @@ -3414,14 +3436,14 @@ static void bezt_to_transdata(TransData *td, TransData2D *td2d, AnimData *adt, B if (td->flag & TD_MOVEHANDLE1) { td2d->h1 = bezt->vec[0]; copy_v2_v2(td2d->ih1, td2d->h1); - } - else + } + else td2d->h1 = NULL; if (td->flag & TD_MOVEHANDLE2) { td2d->h2 = bezt->vec[2]; copy_v2_v2(td2d->ih2, td2d->h2); - } + } else td2d->h2 = NULL; @@ -3525,7 +3547,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) if (sel1) count++; if (sel3) count++; } - } + } else if (sipo->around == V3D_LOCAL) { /* for local-pivot we only need to count the number of selected handles only, so that centerpoints don't * don't get moved wrong @@ -3620,18 +3642,18 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) if (sel1) { hdata = initTransDataCurveHandles(td, bezt); bezt_to_transdata(td++, td2d++, adt, bezt, 0, 1, 1, intvals, mtx, smtx); - } + } else { - /* h1= 0; */ /* UNUSED */ + /* h1 = 0; */ /* UNUSED */ } if (sel3) { if (hdata == NULL) hdata = initTransDataCurveHandles(td, bezt); bezt_to_transdata(td++, td2d++, adt, bezt, 2, 1, 1, intvals, mtx, smtx); - } + } else { - /* h2= 0; */ /* UNUSED */ + /* h2 = 0; */ /* UNUSED */ } } @@ -3984,13 +4006,13 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL); if (t->frame_side == 'R') { - if (right <= cfra) *count = *flag = 0; /* ignore */ - else if (left > cfra) ; /* keep the selection */ + if (right <= cfra) { *count = *flag = 0; } /* ignore */ + else if (left > cfra) { } /* keep the selection */ else *flag |= SEQ_RIGHTSEL; } else { - if (left >= cfra) *count = *flag = 0; /* ignore */ - else if (right < cfra) ; /* keep the selection */ + if (left >= cfra) { *count = *flag = 0; } /* ignore */ + else if (right < cfra) { } /* keep the selection */ else *flag |= SEQ_LEFTSEL; } } @@ -4253,15 +4275,14 @@ static void freeSeqData(TransInfo *t) } } -#if 1 /* (mango hack! - for Ian) this is truely bad - should _never_ be in a release :| */ - if (CTX_wm_window(t->context)->eventstate->alt) { + if (t->flag & T_ALT_TRANSFORM) { int minframe = MAXFRAME; td = t->data; seq_prev = NULL; for (a = 0; a < t->total; a++, td++) { seq = ((TransDataSeq *)td->extra)->seq; if ((seq != seq_prev)) { - minframe = mini(minframe, seq->startdisp); + minframe = min_ii(minframe, seq->startdisp); } } @@ -4291,9 +4312,6 @@ static void freeSeqData(TransInfo *t) else { BKE_sequence_base_shuffle_time(seqbasep, t->scene); } -#else - BKE_sequence_base_shuffle_time(seqbasep, t->scene); -#endif if (has_effect) { /* update effects strips based on strips just moved in time */ @@ -4467,6 +4485,7 @@ static short constraints_list_needinv(TransInfo *t, ListBase *list) 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; /* constraints that require this only under special conditions */ if (con->type == CONSTRAINT_TYPE_ROTLIKE) { @@ -4543,7 +4562,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) td->ext->irotAngle = ob->rotAngle; copy_v3_v3(td->ext->irotAxis, ob->rotAxis); - // td->ext->drotAngle= ob->drotAngle; // XXX, not implemented + // td->ext->drotAngle = ob->drotAngle; // XXX, not implemented // copy_v3_v3(td->ext->drotAxis, ob->drotAxis); // XXX, not implemented } else { @@ -4601,7 +4620,7 @@ static void set_trans_object_base_flags(TransInfo *t) /* * if Base selected and has parent selected: - * base->flag= BA_WAS_SEL + * base->flag = BA_WAS_SEL */ Base *base; @@ -5170,7 +5189,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t) /* Depending on the lock status, draw necessary views */ // fixme... some of this stuff is not good if (ob) { - if (ob->pose || ob_get_key(ob)) + if (ob->pose || BKE_key_from_object(ob)) DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); else DAG_id_tag_update(&ob->id, OB_RECALC_OB); @@ -5554,8 +5573,8 @@ static void createTransObject(bContext *C, TransInfo *t) static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node) { /* hold original location */ - float locxy[2] = {BLI_RCT_CENTER_X(&node->totr), - BLI_RCT_CENTER_Y(&node->totr)}; + float locxy[2] = {BLI_rctf_cent_x(&node->totr), + BLI_rctf_cent_y(&node->totr)}; copy_v2_v2(td2d->loc, locxy); td2d->loc[2] = 0.0f; @@ -5722,10 +5741,9 @@ static void markerToTransDataInit(TransData *td, TransData2D *td2d, TransDataTra unit_m3(td->smtx); } -static void trackToTransData(SpaceClip *sc, TransData *td, TransData2D *td2d, +static void trackToTransData(const int framenr, TransData *td, TransData2D *td2d, TransDataTracking *tdt, MovieTrackingTrack *track, float aspx, float aspy) { - int framenr = ED_space_clip_get_clip_frame_number(sc); MovieTrackingMarker *marker = BKE_tracking_marker_ensure(track, framenr); tdt->flag = marker->flag; @@ -5766,6 +5784,7 @@ static void transDataTrackingFree(TransInfo *t) MEM_freeN(tdt->smarkers); MEM_freeN(tdt); + t->customData = NULL; } } @@ -5777,7 +5796,6 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t) MovieClip *clip = ED_space_clip_get_clip(sc); ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking); MovieTrackingTrack *track; - MovieTrackingMarker *marker; TransDataTracking *tdt; int framenr = ED_space_clip_get_clip_frame_number(sc); float aspx, aspy; @@ -5788,8 +5806,6 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t) track = tracksbase->first; while (track) { if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) { - marker = BKE_tracking_marker_get(track, framenr); - t->total++; /* offset */ if (track->flag & SELECT) @@ -5820,9 +5836,7 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t) track = tracksbase->first; while (track) { if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) { - marker = BKE_tracking_marker_get(track, framenr); - - trackToTransData(sc, td, td2d, tdt, track, aspx, aspy); + trackToTransData(framenr, td, td2d, tdt, track, aspx, aspy); /* offset */ td++; @@ -5845,12 +5859,6 @@ static void createTransTrackingTracksData(bContext *C, TransInfo *t) td += 2; td2d += 2; tdt += 2; - - if (marker->flag & MARKER_DISABLED) { - td += 3; - td2d += 3; - tdt += 3; - }; } } @@ -6435,10 +6443,10 @@ void createTransData(bContext *C, TransInfo *t) else if (t->obedit) { t->ext = NULL; if (t->obedit->type == OB_MESH) { - createTransEditVerts(C, t); + createTransEditVerts(t); } else if (ELEM(t->obedit->type, OB_CURVE, OB_SURF)) { - createTransCurveVerts(C, t); + createTransCurveVerts(t); } else if (t->obedit->type == OB_LATTICE) { createTransLatticeVerts(t); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 325dbe639b4..615bb786071 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -705,7 +705,7 @@ static void recalcData_view3d(TransInfo *t) BKE_nurb_handles_calc(nu); /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */ nu = nu->next; } - } + } else { /* Normal updating */ while (nu) { @@ -895,16 +895,20 @@ static void recalcData_view3d(TransInfo *t) /* helper for recalcData() - for sequencer transforms */ static void recalcData_sequencer(TransInfo *t) { - Editing *ed = BKE_sequencer_editing_get(t->scene, FALSE); - Sequence *seq; + TransData *td; + int a; + Sequence *seq_prev = NULL; - SEQ_BEGIN(ed, seq) - { - if (seq->flag & SELECT) { - BKE_sequence_invalidate_deendent(t->scene, seq); + for (a = 0, td = t->data; a < t->total; a++, td++) { + TransDataSeq *tdsq = (TransDataSeq *) td->extra; + Sequence *seq = tdsq->seq; + + if (seq != seq_prev) { + BKE_sequence_invalidate_dependent(t->scene, seq); } + + seq_prev = seq; } - SEQ_END BKE_sequencer_preprocessed_cache_cleanup(); @@ -998,9 +1002,9 @@ int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) /* moving: is shown in drawobject() (transform color) */ // TRANSFORM_FIX_ME -// if (obedit || (t->flag & T_POSE) ) G.moving= G_TRANSFORM_EDIT; -// else if (G.f & G_PARTICLEEDIT) G.moving= G_TRANSFORM_PARTICLE; -// else G.moving= G_TRANSFORM_OBJ; +// if (obedit || (t->flag & T_POSE) ) G.moving = G_TRANSFORM_EDIT; +// else if (G.f & G_PARTICLEEDIT) G.moving = G_TRANSFORM_PARTICLE; +// else G.moving = G_TRANSFORM_OBJ; t->scene = sce; t->sa = sa; @@ -1248,7 +1252,7 @@ int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) /* TRANSFORM_FIX_ME rna restrictions */ if (t->prop_size <= 0.00001f) { - printf("Proportional size (%f) under 0.00001, reseting to 1!\n", t->prop_size); + printf("Proportional size (%f) under 0.00001, resetting to 1!\n", t->prop_size); t->prop_size = 1.0f; } @@ -1293,19 +1297,26 @@ void postTrans(bContext *C, TransInfo *t) if (t->customFree) { /* Can take over freeing t->data and data2d etc... */ t->customFree(t); + BLI_assert(t->customData == NULL); } else if ((t->customData != NULL) && (t->flag & T_FREE_CUSTOMDATA)) { MEM_freeN(t->customData); + t->customData = NULL; } /* postTrans can be called when nothing is selected, so data is NULL already */ if (t->data) { - int a; /* free data malloced per trans-data */ - for (a = 0, td = t->data; a < t->total; a++, td++) { - if (td->flag & TD_BEZTRIPLE) - MEM_freeN(td->hdata); + if ((t->obedit && ELEM(t->obedit->type, OB_CURVE, OB_SURF)) || + (t->spacetype == SPACE_IPO)) + { + int a; + for (a = 0, td = t->data; a < t->total; a++, td++) { + if (td->flag & TD_BEZTRIPLE) { + MEM_freeN(td->hdata); + } + } } MEM_freeN(t->data); } @@ -1557,9 +1568,8 @@ void calculateCenterBound(TransInfo *t) copy_v3_v3(min, t->data[i].center); } } - add_v3_v3v3(t->center, min, max); - mul_v3_fl(t->center, 0.5); - + mid_v3_v3v3(t->center, min, max); + calculateCenter2D(t); } @@ -1701,8 +1711,9 @@ void calculatePropRatio(TransInfo *t) /* * The elements are sorted according to their dist member in the array, * that means we can stop when it finds one element outside of the propsize. + * do not set 'td->flag |= TD_NOACTION', the prop circle is being changed. */ - td->flag |= TD_NOACTION; + td->factor = 0.0f; restoreElement(td); } diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index 74a2292d74c..0780b8f90b5 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -441,7 +441,7 @@ int calc_manipulator_stats(const bContext *C) } else if (obedit->type == OB_MBALL) { MetaBall *mb = (MetaBall *)obedit->data; - MetaElem *ml /* , *ml_sel=NULL */ /* UNUSED */; + MetaElem *ml /* , *ml_sel = NULL */ /* UNUSED */; ml = mb->editelems->first; while (ml) { @@ -498,7 +498,7 @@ int calc_manipulator_stats(const bContext *C) } } else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) { - ; + /* pass */ } else if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) { PTCacheEdit *edit = PE_get_current(scene, ob); diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 81a4c082dcc..916cf540589 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -284,7 +284,7 @@ static int create_orientation_exec(bContext *C, wmOperator *op) RNA_string_get(op->ptr, "name", name); if (use && !CTX_wm_view3d(C)) { - BKE_report(op->reports, RPT_ERROR, "Create Orientation \"use\" parameter only valid in a 3dView context"); + BKE_report(op->reports, RPT_ERROR, "Create Orientation's 'use' parameter only valid in a 3DView context"); return OPERATOR_CANCELLED; } @@ -605,8 +605,10 @@ static void TRANSFORM_OT_trackball(struct wmOperatorType *ot) static void TRANSFORM_OT_rotate(struct wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ - ot->name = "Rotate"; + ot->name = "Rotate"; ot->description = "Rotate selected items"; ot->idname = OP_ROTATION; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; @@ -618,19 +620,22 @@ static void TRANSFORM_OT_rotate(struct wmOperatorType *ot) ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; - RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2); + prop = RNA_def_float(ot->srna, "value", 0.0f, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2); + RNA_def_property_subtype(prop, PROP_ANGLE); Transform_Properties(ot, P_AXIS | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP); } static void TRANSFORM_OT_tilt(struct wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ - ot->name = "Tilt"; + ot->name = "Tilt"; /* optionals - * "Tilt selected vertices" - * "Specify an extra axis rotation for selected vertices of 3d curve" */ - ot->description = "Tilt selected control vertices of 3d curve"; + * "Specify an extra axis rotation for selected vertices of 3D curve" */ + ot->description = "Tilt selected control vertices of 3D curve"; ot->idname = OP_TILT; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; @@ -641,9 +646,10 @@ static void TRANSFORM_OT_tilt(struct wmOperatorType *ot) ot->cancel = transform_cancel; ot->poll = ED_operator_editcurve_3d; - RNA_def_float_rotation(ot->srna, "value", 1, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2); + prop = RNA_def_float(ot->srna, "value", 0.0, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2); + RNA_def_property_subtype(prop, PROP_ANGLE); - Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_SNAP); + Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP); } static void TRANSFORM_OT_warp(struct wmOperatorType *ot) diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index a155ff7786a..70e4d4cd027 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -142,7 +142,7 @@ TransformOrientation *createObjectSpace(bContext *C, ReportList *UNUSED(reports) strncpy(name, ob->id.name + 2, MAX_ID_NAME - 2); } - return addMatrixSpace(C, mat, name, overwrite); + return addMatrixSpace(C, mat, name, overwrite); } TransformOrientation *createBoneSpace(bContext *C, ReportList *reports, char *name, int overwrite) @@ -402,7 +402,7 @@ EnumPropertyItem *BIF_enumTransformOrientation(bContext *C) const char *BIF_menustringTransformOrientation(const bContext *C, const char *title) { - const char *menu = IFACE_("%t|Global%x0|Local%x1|Gimbal%x4|Normal%x2|View%x3"); + const char *menu = IFACE_("%t|Global %x0|Local %x1|Gimbal %x4|Normal %x2|View %x3"); ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces; TransformOrientation *ts; int i = V3D_MANIP_CUSTOM; @@ -411,14 +411,14 @@ const char *BIF_menustringTransformOrientation(const bContext *C, const char *ti title = IFACE_(title); - str_menu = MEM_callocN(strlen(menu) + strlen(title) + 1 + elem_size * BIF_countTransformOrientation(C), TIP_("UserTransSpace from matrix")); + str_menu = MEM_callocN(strlen(menu) + strlen(title) + 1 + elem_size * BIF_countTransformOrientation(C), "UserTransSpace from matrix"); p = str_menu; p += sprintf(str_menu, "%s", title); p += sprintf(p, "%s", menu); for (ts = transform_spaces->first; ts; ts = ts->next) { - p += sprintf(p, "|%s%%x%d", ts->name, i++); + p += sprintf(p, "|%s %%x%d", ts->name, i++); } return str_menu; @@ -631,7 +631,6 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], /* if there's an edge available, use that for the tangent */ if (em->bm->totedgesel >= 1) { BMEdge *eed = NULL; - BMIter iter; BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { @@ -746,14 +745,14 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], MetaBall *mb = obedit->data; if (mb->lastelem) { - float mat[4][4]; + float qmat[3][3]; /* Rotation of MetaElem is stored in quat */ - quat_to_mat4(mat, mb->lastelem->quat); + quat_to_mat3(qmat, mb->lastelem->quat); - copy_v3_v3(normal, mat[2]); + copy_v3_v3(normal, qmat[2]); - negate_v3_v3(plane, mat[1]); + negate_v3_v3(plane, qmat[1]); result = ORIENTATION_FACE; } diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index b88ae68e00b..a6fb7e7ed00 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -78,7 +78,7 @@ #include "transform.h" -#define USE_BVH_FACE_SNAP +#define TRANSFORM_DIST_MAX_PX 1000 /********************* PROTOTYPES ***********************/ @@ -296,7 +296,7 @@ void applyProject(TransInfo *t) for (i = 0; i < t->total; i++, td++) { float iloc[3], loc[3], no[3]; float mval[2]; - int dist = 1000; + int dist = TRANSFORM_DIST_MAX_PX; if (td->flag & TD_NOACTION) break; @@ -315,18 +315,18 @@ void applyProject(TransInfo *t) copy_v3_v3(iloc, td->ob->obmat[3]); } - project_float(t->ar, iloc, mval); - - if (snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.modeSelect)) { -// if (t->flag & (T_EDIT|T_POSE)) { -// mul_m4_v3(imat, loc); -// } -// - sub_v3_v3v3(tvec, loc, iloc); - - mul_m3_v3(td->smtx, tvec); - - add_v3_v3(td->loc, tvec); + 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 (t->flag & (T_EDIT|T_POSE)) { +// mul_m4_v3(imat, loc); +// } + + sub_v3_v3v3(tvec, loc, iloc); + + mul_m3_v3(td->smtx, tvec); + + add_v3_v3(td->loc, tvec); + } } //XXX constraintTransLim(t, td); @@ -601,7 +601,9 @@ int updateSelectedSnapPoint(TransInfo *t) int dx, dy; int dist; - project_int(t->ar, p->co, screen_loc); + if (ED_view3d_project_int_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]; @@ -719,14 +721,14 @@ static float RotationBetween(TransInfo *t, float p1[3], float p2[3]) { float angle, start[3], end[3], center[3]; - copy_v3_v3(center, t->center); + copy_v3_v3(center, t->center); if (t->flag & (T_EDIT | T_POSE)) { Object *ob = t->obedit ? t->obedit : t->poseobj; mul_m4_v3(ob->obmat, center); } sub_v3_v3v3(start, p1, center); - sub_v3_v3v3(end, p2, center); + sub_v3_v3v3(end, p2, center); // Angle around a constraint axis (error prone, will need debug) if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) { @@ -775,7 +777,7 @@ static float ResizeBetween(TransInfo *t, float p1[3], float p2[3]) { float d1[3], d2[3], center[3], len_d1; - copy_v3_v3(center, t->center); + copy_v3_v3(center, t->center); if (t->flag & (T_EDIT | T_POSE)) { Object *ob = t->obedit ? t->obedit : t->poseobj; mul_m4_v3(ob->obmat, center); @@ -842,7 +844,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) p2 = NULL; p1->flag = 1; - /* if peeling objects, take the first and last from each object */ + /* if peeling objects, take the first and last from each object */ if (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) { DepthPeel *peel; for (peel = p1->next; peel; peel = peel->next) { @@ -960,8 +962,8 @@ static void TargetSnapOffset(TransInfo *t, TransData *td) if (t->spacetype == SPACE_NODE && td != NULL) { bNode *node = td->extra; char border = t->tsnap.snapNodeBorder; - float width = BLI_RCT_SIZE_X(&node->totr); - float height = BLI_RCT_SIZE_Y(&node->totr); + float width = BLI_rctf_size_x(&node->totr); + float height = BLI_rctf_size_y(&node->totr); if (border & NODE_LEFT) t->tsnap.snapTarget[0] -= 0.5f * width; @@ -978,7 +980,7 @@ static void TargetSnapCenter(TransInfo *t) { /* Only need to calculate once */ if ((t->tsnap.status & TARGET_INIT) == 0) { - copy_v3_v3(t->tsnap.snapTarget, t->center); + copy_v3_v3(t->tsnap.snapTarget, t->center); if (t->flag & (T_EDIT | T_POSE)) { Object *ob = t->obedit ? t->obedit : t->poseobj; @@ -987,7 +989,7 @@ static void TargetSnapCenter(TransInfo *t) TargetSnapOffset(t, NULL); - t->tsnap.status |= TARGET_INIT; + t->tsnap.status |= TARGET_INIT; } } @@ -1023,7 +1025,7 @@ static void TargetSnapActive(TransInfo *t) t->tsnap.target = SCE_SNAP_TARGET_MEDIAN; t->tsnap.targetSnap = TargetSnapMedian; TargetSnapMedian(t); - } + } } } @@ -1051,7 +1053,7 @@ static void TargetSnapMedian(TransInfo *t) TargetSnapOffset(t, NULL); - t->tsnap.status |= TARGET_INIT; + t->tsnap.status |= TARGET_INIT; } } @@ -1132,58 +1134,6 @@ static void TargetSnapClosest(TransInfo *t) t->tsnap.status |= TARGET_INIT; } } -/*================================================================*/ -#ifndef USE_BVH_FACE_SNAP -static int snapFace(ARegion *ar, float v1co[3], float v2co[3], float v3co[3], float *v4co, float mval[2], float ray_start[3], float ray_start_local[3], float ray_normal_local[3], float obmat[][4], float timat[][3], float loc[3], float no[3], int *dist, float *depth) -{ - float lambda; - int result; - int retval = 0; - - result = isect_ray_tri_threshold_v3(ray_start_local, ray_normal_local, v1co, v2co, v3co, &lambda, NULL, 0.001); - - if (result) { - float location[3], normal[3]; - float intersect[3]; - float new_depth; - int screen_loc[2]; - int new_dist; - - copy_v3_v3(intersect, ray_normal_local); - mul_v3_fl(intersect, lambda); - add_v3_v3(intersect, ray_start_local); - - copy_v3_v3(location, intersect); - - if (v4co) - normal_quad_v3(normal, v1co, v2co, v3co, v4co); - else - normal_tri_v3(normal, v1co, v2co, v3co); - - mul_m4_v3(obmat, location); - - new_depth = len_v3v3(location, ray_start); - - project_int(ar, location, screen_loc); - new_dist = abs(screen_loc[0] - (int)mval[0]) + abs(screen_loc[1] - (int)mval[1]); - - if (new_dist <= *dist && new_depth < *depth) { - *depth = new_depth; - retval = 1; - - copy_v3_v3(loc, location); - copy_v3_v3(no, normal); - - mul_m3_v3(timat, no); - normalize_v3(no); - - *dist = new_dist; - } - } - - return retval; -} -#endif static int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], short v2no[3], float obmat[][4], float timat[][3], const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2], @@ -1230,10 +1180,14 @@ static int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], sh mul_m4_v3(obmat, location); - new_depth = len_v3v3(location, ray_start); + new_depth = len_v3v3(location, ray_start); - project_int(ar, location, screen_loc); - new_dist = abs(screen_loc[0] - (int)mval[0]) + abs(screen_loc[1] - (int)mval[1]); + 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]); + } + else { + new_dist = TRANSFORM_DIST_MAX_PX; + } /* 10% threshold if edge is closer but a bit further * this takes care of series of connected edges a bit slanted w.r.t the viewport @@ -1251,17 +1205,17 @@ static int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], sh mul = dot_v3v3(vec, edge_loc) / dot_v3v3(edge_loc, edge_loc); if (r_no) { - normal_short_to_float_v3(n1, v1no); + normal_short_to_float_v3(n1, v1no); normal_short_to_float_v3(n2, v2no); interp_v3_v3v3(r_no, n2, n1, mul); mul_m3_v3(timat, r_no); normalize_v3(r_no); - } + } copy_v3_v3(r_loc, location); *r_dist = new_dist; - } + } } } @@ -1289,8 +1243,13 @@ static int snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[][4], new_depth = len_v3v3(location, ray_start); - project_int(ar, location, screen_loc); - new_dist = abs(screen_loc[0] - (int)mval[0]) + abs(screen_loc[1] - (int)mval[1]); + 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]); + } + else { + new_dist = TRANSFORM_DIST_MAX_PX; + } + if (new_dist <= *r_dist && new_depth < *r_depth) { *r_depth = new_depth; @@ -1305,7 +1264,7 @@ static int snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[][4], } *r_dist = new_dist; - } + } } return retval; @@ -1412,8 +1371,7 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh switch (snap_mode) { case SCE_SNAP_MODE_FACE: - { -#ifdef USE_BVH_FACE_SNAP // Added for durian + { BVHTreeRayHit hit; BVHTreeFromMesh treeData; @@ -1443,80 +1401,6 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh } } break; - -#else - MVert *verts = dm->getVertArray(dm); - MFace *faces = dm->getTessFaceArray(dm); - int *index_array = NULL; - int index = 0; - int i; - - if (em != NULL) { - index_array = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); - EDBM_index_arrays_init(em, 0, 0, 1); - } - - for (i = 0; i < totface; i++) { - BMFace *efa = NULL; - MFace *f = faces + i; - - test = 1; /* reset for every face */ - - if (em != NULL) { - if (index_array) { - index = index_array[i]; - } - else { - index = i; - } - - if (index == ORIGINDEX_NONE) { - test = 0; - } - else { - efa = EDBM_face_at_index(em, index); - - if (efa && BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - test = 0; - } - else if (efa) { - BMIter iter; - BMLoop *l; - - l = BM_iter_new(&iter, em->bm, BM_LOOPS_OF_FACE, efa); - for (; l; l = BM_iter_step(&iter)) { - if (BM_elem_flag_test(l->v, BM_ELEM_SELECT)) { - test = 0; - break; - } - } - } - } - } - - - if (test) { - int result; - float *v4co = NULL; - - if (f->v4) { - v4co = verts[f->v4].co; - } - - result = snapFace(ar, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, v4co, mval, ray_start, ray_start_local, ray_normal_local, obmat, timat, loc, no, dist, depth); - retval |= result; - - if (f->v4 && result == 0) { - retval |= snapFace(ar, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, verts[f->v2].co, mval, ray_start, ray_start_local, ray_normal_local, obmat, timat, loc, no, dist, depth); - } - } - } - - if (em != NULL) { - EDBM_index_arrays_free(em); - } -#endif - break; } case SCE_SNAP_MODE_VERTEX: { @@ -1697,7 +1581,7 @@ static int snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, c if (ob->transflag & OB_DUPLI) { DupliObject *dupli_ob; - ListBase *lb = object_duplilist(scene, ob); + ListBase *lb = object_duplilist(scene, ob, FALSE); for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { Object *dob = dupli_ob->ob; @@ -1845,7 +1729,7 @@ static int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], mul_m4_v3(obmat, location); - new_depth = len_v3v3(location, ray_start); + new_depth = len_v3v3(location, ray_start); mul_m3_v3(timat, normal); normalize_v3(normal); @@ -1880,7 +1764,7 @@ static int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], normalize_v3(normal); addDepthPeel(depth_peels, new_depth, location, normal, ob); - } + } } } } @@ -1903,7 +1787,7 @@ static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, L if (ob->transflag & OB_DUPLI) { DupliObject *dupli_ob; - ListBase *lb = object_duplilist(scene, ob); + ListBase *lb = object_duplilist(scene, ob, FALSE); for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { Object *dob = dupli_ob->ob; diff --git a/source/blender/editors/util/crazyspace.c b/source/blender/editors/util/crazyspace.c index b0edc702e48..e953aa2f0ed 100644 --- a/source/blender/editors/util/crazyspace.c +++ b/source/blender/editors/util/crazyspace.c @@ -409,7 +409,7 @@ void crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[3][3 MEM_freeN(quats); } - if (!*deformmats) { + if (*deformmats == NULL) { int a, numVerts; Mesh *me = (Mesh *)ob->data; diff --git a/source/blender/editors/util/editmode_undo.c b/source/blender/editors/util/editmode_undo.c index 9a3b0476205..c8c26ed771d 100644 --- a/source/blender/editors/util/editmode_undo.c +++ b/source/blender/editors/util/editmode_undo.c @@ -104,7 +104,7 @@ static UndoElem *curundo = NULL; static void undo_restore(UndoElem *undo, void *editdata, void *obdata) { if (undo) { - undo->to_editmode(undo->undodata, editdata, obdata); + undo->to_editmode(undo->undodata, editdata, obdata); } } @@ -233,7 +233,7 @@ static void undo_clean_stack(bContext *C) if (curundo == NULL) curundo = undobase.last; } -/* 1= an undo, -1 is a redo. we have to make sure 'curundo' remains at current situation */ +/* 1 = an undo, -1 is a redo. we have to make sure 'curundo' remains at current situation */ void undo_editmode_step(bContext *C, int step) { Object *obedit = CTX_data_edit_object(C); diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c index 281b682465d..b73f5fa0869 100644 --- a/source/blender/editors/util/numinput.c +++ b/source/blender/editors/util/numinput.c @@ -279,7 +279,9 @@ char handleNumInput(NumInput *n, wmEvent *event) if (!n->ctrl[idx]) n->ctrl[idx] = 1; - if (fabsf(n->val[idx]) > 9999999.0f) ; + if (fabsf(n->val[idx]) > 9999999.0f) { + /* pass */ + } else if (n->ctrl[idx] == 1) { n->val[idx] *= 10; n->val[idx] += Val; diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c index 5eafc3e65a9..1753a564a3c 100644 --- a/source/blender/editors/util/undo.c +++ b/source/blender/editors/util/undo.c @@ -505,7 +505,7 @@ static int undo_history_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even MEM_freeN(item); uiPupMenuEnd(C, pup); - } + } } return OPERATOR_CANCELLED; diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index d6794912043..9c2c300c530 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -453,8 +453,6 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) int drawfaces, interpedges; Image *ima = sima->image; - StitchPreviewer *stitch_preview = uv_get_stitch_previewer(); - activetf = EDBM_mtexpoly_active_get(em, &efa_act, FALSE, FALSE); /* will be set to NULL if hidden */ activef = BM_active_face_get(bm, FALSE, FALSE); ts = scene->toolsettings; @@ -536,7 +534,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); - if (uvedit_face_visible_test(scene, ima, efa, tf)) { + if (uvedit_face_visible_test(scene, ima, efa, tf)) { BM_elem_flag_enable(efa, BM_ELEM_TAG); } else { @@ -820,52 +818,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) bglVertex2fv(luv->uv); } } - bglEnd(); - } - - /* finally draw stitch preview */ - if (stitch_preview) { - int i, index = 0; - glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); - glEnableClientState(GL_VERTEX_ARRAY); - - glEnable(GL_BLEND); - - UI_ThemeColor4(TH_STITCH_PREVIEW_ACTIVE); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glVertexPointer(2, GL_FLOAT, 0, stitch_preview->static_tris); - glDrawArrays(GL_TRIANGLES, 0, stitch_preview->num_static_tris * 3); - - glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_polys); - for (i = 0; i < stitch_preview->num_polys; i++) { - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - UI_ThemeColor4(TH_STITCH_PREVIEW_FACE); - glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - UI_ThemeColor4(TH_STITCH_PREVIEW_EDGE); - glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]); - - index += stitch_preview->uvs_per_polygon[i]; - } - glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); -#if 0 - UI_ThemeColor4(TH_STITCH_PREVIEW_VERT); - glDrawArrays(GL_TRIANGLES, 0, stitch_preview->num_tris * 3); -#endif - glDisable(GL_BLEND); - - /* draw vert preview */ - glPointSize(pointsize * 2.0f); - UI_ThemeColor4(TH_STITCH_PREVIEW_STITCHABLE); - glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_stitchable); - glDrawArrays(GL_POINTS, 0, stitch_preview->num_stitchable); - - UI_ThemeColor4(TH_STITCH_PREVIEW_UNSTITCHABLE); - glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_unstitchable); - glDrawArrays(GL_POINTS, 0, stitch_preview->num_unstitchable); - - glPopClientAttrib(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + bglEnd(); } glPointSize(1.0); diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index f0ff79ae25e..b42875f20c2 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -72,33 +72,8 @@ void uv_find_nearest_edge(struct Scene *scene, struct Image *ima, struct BMEditM /* utility tool functions */ -struct UvElement *ED_uv_element_get(struct UvElementMap *map, struct BMFace *efa, struct BMLoop *l); void uvedit_live_unwrap_update(struct SpaceImage *sima, struct Scene *scene, struct Object *obedit); -/* smart stitch */ - -/* object that stores display data for previewing before accepting stitching */ -typedef struct StitchPreviewer { - /* here we'll store the preview triangle indices of the mesh */ - float *preview_polys; - /* uvs per polygon. */ - unsigned int *uvs_per_polygon; - /*number of preview polygons */ - unsigned int num_polys; - /* preview data. These will be either the previewed vertices or edges depending on stitch mode settings */ - float *preview_stitchable; - float *preview_unstitchable; - /* here we'll store the number of elements to be drawn */ - unsigned int num_stitchable; - unsigned int num_unstitchable; - unsigned int preview_uvs; - /* ...and here we'll store the triangles*/ - float *static_tris; - unsigned int num_static_tris; -} StitchPreviewer; - -StitchPreviewer *uv_get_stitch_previewer(void); - /* operators */ void UV_OT_average_islands_scale(struct wmOperatorType *ot); diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 06da1c8bfea..e860d486ea3 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -170,7 +170,6 @@ void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *i void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *ima, Image *previma) { BMEditMesh *em; - BMFace *efa; BMIter iter; MTexPoly *tf; int update = 0; @@ -198,6 +197,8 @@ void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *im ED_object_assign_active_image(bmain, obedit, efa->mat_nr + 1, ima); } else { + BMFace *efa; + /* old shading system, assign image to selected faces */ #ifdef USE_SWITCH_ASPECT float prev_aspect[2], fprev_aspect; @@ -214,6 +215,8 @@ void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *im if (!CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY)) { BM_data_layer_add(em->bm, &em->bm->pdata, CD_MTEXPOLY); BM_data_layer_add(em->bm, &em->bm->ldata, CD_MLOOPUV); + /* make UVs all nice 0-1 */ + ED_mesh_uv_loop_reset_ex(obedit->data, CustomData_get_active_layer_index(&em->bm->pdata, CD_MTEXPOLY)); update = 1; } @@ -759,31 +762,32 @@ static int nearest_uv_between(BMEditMesh *em, BMFace *efa, int UNUSED(nverts), i BMLoop *l; MLoopUV *luv; BMIter iter; - float m[3], v1[3], v2[3], c1, c2, *uv1 = NULL, /* *uv2, */ /* UNUSED */ *uv3 = NULL; + float m[2], v1[2], v2[2], c1, c2, *uv1 = NULL, /* *uv2, */ /* UNUSED */ *uv3 = NULL; int id1, id2, i; id1 = (id + efa->len - 1) % efa->len; id2 = (id + efa->len + 1) % efa->len; - m[0] = co[0] - uv[0]; - m[1] = co[1] - uv[1]; + sub_v2_v2v2(m, co, uv); i = 0; BM_ITER_ELEM (l, &iter, efa, BM_LOOPS_OF_FACE) { luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - if (i == id1) + if (i == id1) { uv1 = luv->uv; - else if (i == id) - ; /* uv2 = luv->uv; */ /* UNUSED */ - else if (i == id2) + } + else if (i == id) { + /* uv2 = luv->uv; */ /* UNUSED */ + } + else if (i == id2) { uv3 = luv->uv; - + } i++; } - sub_v3_v3v3(v1, uv1, uv); - sub_v3_v3v3(v2, uv3, uv); + sub_v2_v2v2(v1, uv1, uv); + sub_v2_v2v2(v2, uv3, uv); /* m and v2 on same side of v-v1? */ c1 = v1[0] * m[1] - v1[1] * m[0]; @@ -893,19 +897,6 @@ int ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, const float c return found; } -UvElement *ED_uv_element_get(UvElementMap *map, BMFace *efa, BMLoop *l) -{ - UvElement *element; - - element = map->vert[BM_elem_index_get(l->v)]; - - for (; element; element = element->next) - if (element->face == efa) - return element; - - return NULL; -} - /*********************** loop select ***********************/ static void select_edgeloop_uv_vertex_loop_flag(UvMapVert *first) @@ -1311,9 +1302,7 @@ static void weld_align_uv(bContext *C, int tool) Object *obedit; Image *ima; BMEditMesh *em; - BMIter iter, liter; MTexPoly *tf; - MLoopUV *luv; float cent[2], min[2], max[2]; scene = CTX_data_scene(C); @@ -1325,6 +1314,7 @@ static void weld_align_uv(bContext *C, int tool) INIT_MINMAX2(min, max); if (tool == 'a') { + BMIter iter, liter; BMFace *efa; BMLoop *l; @@ -1336,7 +1326,7 @@ static void weld_align_uv(bContext *C, int tool) BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); DO_MINMAX2(luv->uv, min, max); } } @@ -1348,6 +1338,7 @@ static void weld_align_uv(bContext *C, int tool) uvedit_center(scene, ima, obedit, cent, 0); if (tool == 'x' || tool == 'w') { + BMIter iter, liter; BMFace *efa; BMLoop *l; @@ -1358,7 +1349,7 @@ static void weld_align_uv(bContext *C, int tool) BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); luv->uv[0] = cent[0]; } @@ -1367,6 +1358,7 @@ static void weld_align_uv(bContext *C, int tool) } if (tool == 'y' || tool == 'w') { + BMIter iter, liter; BMFace *efa; BMLoop *l; @@ -1377,7 +1369,7 @@ static void weld_align_uv(bContext *C, int tool) BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); luv->uv[1] = cent[1]; } @@ -1744,7 +1736,7 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop) * the selection rather than de-selecting the closest. */ uvedit_pixel_to_float(sima, limit, 0.05f); - uvedit_pixel_to_float(sima, penalty, 5.0f / sima->zoom); + uvedit_pixel_to_float(sima, penalty, 5.0f / (sima ? sima->zoom : 1.0f)); /* retrieve operation mode */ if (ts->uv_flag & UV_SYNC_SELECTION) { @@ -1950,7 +1942,7 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop) } flush = 1; - } + } } } else { @@ -2132,7 +2124,7 @@ static int select_linked_internal(bContext *C, wmOperator *op, wmEvent *event, i NearestHit hit, *hit_p = NULL; if (ts->uv_flag & UV_SYNC_SELECTION) { - BKE_report(op->reports, RPT_ERROR, "Can't select linked when sync selection is enabled"); + BKE_report(op->reports, RPT_ERROR, "Cannot select linked when sync selection is enabled"); return OPERATOR_CANCELLED; } @@ -2239,7 +2231,7 @@ static int select_split_exec(bContext *C, wmOperator *op) short change = FALSE; if (ts->uv_flag & UV_SYNC_SELECTION) { - BKE_report(op->reports, RPT_ERROR, "Can't split selection when sync selection is enabled"); + BKE_report(op->reports, RPT_ERROR, "Cannot split selection when sync selection is enabled"); return OPERATOR_CANCELLED; } @@ -2280,6 +2272,7 @@ static int select_split_exec(bContext *C, wmOperator *op) } if (change) { + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL); return OPERATOR_FINISHED; } else { @@ -2317,7 +2310,7 @@ static int unlink_selection_exec(bContext *C, wmOperator *op) MLoopUV *luv; if (ts->uv_flag & UV_SYNC_SELECTION) { - BKE_report(op->reports, RPT_ERROR, "Can't unlink selection when sync selection is enabled"); + BKE_report(op->reports, RPT_ERROR, "Cannot unlink selection when sync selection is enabled"); return OPERATOR_CANCELLED; } @@ -2488,13 +2481,16 @@ static void uv_faces_do_sticky(SpaceImage *sima, Scene *scene, Object *obedit, s break; if (efa_index != vlist_iter->f) { + BMLoop *l_other; efa_vlist = EDBM_face_at_index(em, vlist_iter->f); /* tf_vlist = CustomData_bmesh_get(&em->bm->pdata, efa_vlist->head.data, CD_MTEXPOLY); */ /* UNUSED */ + l_other = BM_iter_at_index(em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->tfindex); + if (select) - uvedit_uv_select_enable(em, scene, BM_iter_at_index(em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->tfindex), FALSE); + uvedit_uv_select_enable(em, scene, l_other, FALSE); else - uvedit_uv_select_disable(em, scene, BM_iter_at_index(em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->tfindex)); + uvedit_uv_select_disable(em, scene, l_other); } vlist_iter = vlist_iter->next; } @@ -2745,7 +2741,7 @@ static void UV_OT_circle_select(wmOperatorType *ot) /* ******************** lasso select operator **************** */ -static int do_lasso_select_mesh_uv(bContext *C, int mcords[][2], short moves, short select) +static int do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short moves, short select) { Image *ima = CTX_data_edit_image(C); ARegion *ar = CTX_wm_region(C); @@ -2819,7 +2815,7 @@ static int do_lasso_select_mesh_uv(bContext *C, int mcords[][2], short moves, sh static int uv_lasso_select_exec(bContext *C, wmOperator *op) { int mcords_tot; - int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); if (mcords) { short select; @@ -2828,7 +2824,7 @@ static int uv_lasso_select_exec(bContext *C, wmOperator *op) select = !RNA_boolean_get(op->ptr, "deselect"); change = do_lasso_select_mesh_uv(C, mcords, mcords_tot, select); - MEM_freeN(mcords); + MEM_freeN((void *)mcords); return change ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c index f017394356e..5b6125b558b 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.c +++ b/source/blender/editors/uvedit/uvedit_parametrizer.c @@ -1566,7 +1566,7 @@ static void p_vert_harmonic_insert(PVert *v) e = v->edge; do { - npoints++; + npoints++; e = p_wheel_edge_next(e); } while (e && (e != v->edge)); @@ -3306,7 +3306,7 @@ static void p_chart_stretch_minimize(PChart *chart, RNG *rng) trusted_radius /= 2 * nedges; - random_angle = rng_getFloat(rng) * 2.0f * (float)M_PI; + random_angle = BLI_rng_get_float(rng) * 2.0f * (float)M_PI; dir[0] = trusted_radius * cosf(random_angle); dir[1] = trusted_radius * sinf(random_angle); @@ -3988,7 +3988,7 @@ static void p_smooth(PChart *chart) diff[1] = p[1] - oldp[1]; length = sqrt(diff[0] * diff[0] + diff[1] * diff[1]); - d = MAX2(d, length); + d = max_ff(d, length); moved += length; } } @@ -4285,7 +4285,7 @@ void param_stretch_begin(ParamHandle *handle) param_assert(phandle->state == PHANDLE_STATE_CONSTRUCTED); phandle->state = PHANDLE_STATE_STRETCH; - phandle->rng = rng_new(31415926); + phandle->rng = BLI_rng_new(31415926); phandle->blend = 0.0f; for (i = 0; i < phandle->ncharts; i++) { @@ -4332,7 +4332,7 @@ void param_stretch_end(ParamHandle *handle) param_assert(phandle->state == PHANDLE_STATE_STRETCH); phandle->state = PHANDLE_STATE_CONSTRUCTED; - rng_free(phandle->rng); + BLI_rng_free(phandle->rng); phandle->rng = NULL; } @@ -4400,7 +4400,7 @@ void param_pack(ParamHandle *handle, float margin) if (margin > 0.0f) area += sqrt(box->w * box->h); - } + } if (margin > 0.0f) { /* multiply the margin by the area to give predictable results not dependent on UV scale, diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index 4e0e7944e84..b1945c37048 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -46,6 +46,8 @@ #include "BLI_math_vector.h" #include "BLI_string.h" +#include "BIF_gl.h" + #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_depsgraph.h" @@ -55,6 +57,7 @@ #include "ED_mesh.h" #include "ED_uvedit.h" #include "ED_screen.h" +#include "ED_space_api.h" #include "RNA_access.h" #include "RNA_define.h" @@ -63,11 +66,32 @@ #include "WM_types.h" #include "UI_view2d.h" +#include "UI_resources.h" #include "uvedit_intern.h" /* ********************** smart stitch operator *********************** */ +/* object that stores display data for previewing before accepting stitching */ +typedef struct StitchPreviewer { + /* here we'll store the preview triangle indices of the mesh */ + float *preview_polys; + /* uvs per polygon. */ + unsigned int *uvs_per_polygon; + /*number of preview polygons */ + unsigned int num_polys; + /* preview data. These will be either the previewed vertices or edges depending on stitch mode settings */ + float *preview_stitchable; + float *preview_unstitchable; + /* here we'll store the number of elements to be drawn */ + unsigned int num_stitchable; + unsigned int num_unstitchable; + unsigned int preview_uvs; + /* ...and here we'll store the triangles*/ + float *static_tris; + unsigned int num_static_tris; +} StitchPreviewer; + struct IslandStitchData; @@ -143,6 +167,8 @@ typedef struct StitchState { int static_island; /* store number of primitives per face so that we can allocate the active island buffer later */ unsigned int *tris_per_island; + + void *draw_handle; } StitchState; typedef struct PreviewPosition { @@ -216,7 +242,7 @@ static void stitch_preview_delete(void) /* "getter method" */ -StitchPreviewer *uv_get_stitch_previewer(void) +static StitchPreviewer *uv_get_stitch_previewer(void) { return _stitch_preview; } @@ -406,8 +432,8 @@ static void stitch_island_calculate_edge_rotation(UvEdge *edge, StitchState *sta edgesin = uv1[0] * uv2[1] - uv2[0] * uv1[1]; rotation = (edgesin > 0.0f) ? - +acosf(maxf(-1.0f, minf(1.0f, edgecos))) : - -acosf(maxf(-1.0f, minf(1.0f, edgecos))); + +acosf(max_ff(-1.0f, min_ff(1.0f, edgecos))) : + -acosf(max_ff(-1.0f, min_ff(1.0f, edgecos))); island_stitch_data[element1->island].num_rot_elements++; island_stitch_data[element1->island].rotation += rotation; @@ -981,6 +1007,55 @@ static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *no normalize_v2(normal); } +static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *UNUSED(arg)) +{ + int i, index = 0; + float pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE); + StitchPreviewer *stitch_preview = uv_get_stitch_previewer(); + + glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); + glEnableClientState(GL_VERTEX_ARRAY); + + glEnable(GL_BLEND); + + UI_ThemeColor4(TH_STITCH_PREVIEW_ACTIVE); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glVertexPointer(2, GL_FLOAT, 0, stitch_preview->static_tris); + glDrawArrays(GL_TRIANGLES, 0, stitch_preview->num_static_tris * 3); + + glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_polys); + for (i = 0; i < stitch_preview->num_polys; i++) { + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + UI_ThemeColor4(TH_STITCH_PREVIEW_FACE); + glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + UI_ThemeColor4(TH_STITCH_PREVIEW_EDGE); + glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]); + + index += stitch_preview->uvs_per_polygon[i]; + } + glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); +#if 0 + UI_ThemeColor4(TH_STITCH_PREVIEW_VERT); + glDrawArrays(GL_TRIANGLES, 0, stitch_preview->num_tris * 3); +#endif + glDisable(GL_BLEND); + + /* draw vert preview */ + glPointSize(pointsize * 2.0f); + UI_ThemeColor4(TH_STITCH_PREVIEW_STITCHABLE); + glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_stitchable); + glDrawArrays(GL_POINTS, 0, stitch_preview->num_stitchable); + + UI_ThemeColor4(TH_STITCH_PREVIEW_UNSTITCHABLE); + glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_unstitchable); + glDrawArrays(GL_POINTS, 0, stitch_preview->num_unstitchable); + + glPopClientAttrib(); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + +} + static int stitch_init(bContext *C, wmOperator *op) { /* for fast edge lookup... */ @@ -1016,6 +1091,7 @@ static int stitch_init(bContext *C, wmOperator *op) state->static_island = RNA_int_get(op->ptr, "static_island"); state->midpoints = RNA_boolean_get(op->ptr, "midpoint_snap"); state->clear_seams = RNA_boolean_get(op->ptr, "clear_seams"); + state->draw_handle = ED_region_draw_cb_activate(CTX_wm_region(C)->type, stitch_draw, NULL, REGION_DRAW_POST_VIEW); /* in uv synch selection, all uv's are visible */ if (ts->uv_flag & UV_SYNC_SELECTION) { state->element_map = EDBM_uv_element_map_create(state->em, 0, 1); @@ -1282,6 +1358,8 @@ static void stitch_exit(bContext *C, wmOperator *op, int finished) if (sa) ED_area_headerprint(sa, NULL); + ED_region_draw_cb_exit(CTX_wm_region(C)->type, stitch_state->draw_handle); + DAG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index c95b2e85248..f615902eedf 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -60,6 +60,7 @@ #include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_report.h" +#include "BKE_scene.h" #include "BKE_tessmesh.h" #include "BLI_math.h" @@ -177,7 +178,33 @@ static int uvedit_have_selection(Scene *scene, BMEditMesh *em, short implicit) return 0; } -static ParamHandle *construct_param_handle(Scene *scene, BMEditMesh *em, +static void ED_uvedit_get_aspect(Scene *scene, Object *ob, BMEditMesh *em, float *aspx, float *aspy) +{ + int sloppy = TRUE; + int selected = FALSE; + BMFace *efa; + Image *ima; + + efa = BM_active_face_get(em->bm, sloppy, selected); + + if (efa) { + if (BKE_scene_use_new_shading_nodes(scene)) { + ED_object_get_active_image(ob, efa->mat_nr + 1, &ima, NULL, NULL); + } + else { + MTexPoly *tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + ima = tf->tpage; + } + + ED_image_get_uv_aspect(ima, NULL, aspx, aspy); + } + else { + *aspx = 1.0f; + *aspy = 1.0f; + } +} + +static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh *em, short implicit, short fill, short sel, short correct_aspect) { @@ -187,27 +214,16 @@ static ParamHandle *construct_param_handle(Scene *scene, BMEditMesh *em, BMLoop *l; BMEdge *eed; BMIter iter, liter; - MTexPoly *tf; handle = param_construct_begin(); if (correct_aspect) { - int sloppy = TRUE; - int selected = FALSE; + float aspx, aspy; - efa = BM_active_face_get(em->bm, sloppy, selected); + ED_uvedit_get_aspect(scene, ob, em, &aspx, &aspy); - if (efa) { - float aspx, aspy; - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); - - ED_image_get_uv_aspect(tf->tpage, NULL, &aspx, &aspy); - - if (aspx != aspy) - param_aspect_ratio(handle, aspx, aspy); - else - param_aspect_ratio(handle, 1.0, 1.0); - } + if (aspx != aspy) + param_aspect_ratio(handle, aspx, aspy); } /* we need the vert indices */ @@ -223,7 +239,7 @@ static ParamHandle *construct_param_handle(Scene *scene, BMEditMesh *em, BMLoop *ls[3]; float *co[4]; float *uv[4]; - int i, lsel; + int lsel; if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || (sel && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0)) continue; @@ -242,9 +258,10 @@ static ParamHandle *construct_param_handle(Scene *scene, BMEditMesh *em, key = (ParamKey)efa; - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + // tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); // UNUSED if (efa->len == 3 || efa->len == 4) { + int i; /* for quads let parametrize split, it can make better decisions * about which split is best for unwrapping than scanfill */ i = 0; @@ -291,6 +308,7 @@ static ParamHandle *construct_param_handle(Scene *scene, BMEditMesh *em, BLI_scanfill_calc_ex(&sf_ctx, TRUE, efa->no); for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { + int i; ls[0] = sf_tri->v1->tmp.p; ls[1] = sf_tri->v2->tmp.p; ls[2] = sf_tri->v3->tmp.p; @@ -353,13 +371,12 @@ static void texface_from_original_index(BMFace *efa, int index, float **uv, Para /* unwrap handle initialization for subsurf aware-unwrapper. The many modifications required to make the original function(see above) * work justified the existence of a new function. */ -static ParamHandle *construct_param_handle_subsurfed(Scene *scene, BMEditMesh *em, short fill, short sel, short correct_aspect) +static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, BMEditMesh *em, short fill, short sel, short correct_aspect) { ParamHandle *handle; /* index pointers */ MFace *face; MEdge *edge; - BMFace *editFace; int i; /* modifier initialization data, will control what type of subdivision will happen*/ @@ -367,7 +384,7 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, BMEditMesh *e /* Used to hold subsurfed Mesh */ DerivedMesh *derivedMesh, *initialDerived; /* holds original indices for subsurfed mesh */ - int *origVertIndices, *origFaceIndices, *origEdgeIndices; + int *origVertIndices, *origEdgeIndices, *origFaceIndices, *origPolyIndices; /* Holds vertices of subsurfed mesh */ MVert *subsurfedVerts; MEdge *subsurfedEdges; @@ -383,30 +400,19 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, BMEditMesh *e handle = param_construct_begin(); if (correct_aspect) { - int sloppy = TRUE; - int selected = FALSE; + float aspx, aspy; - editFace = BM_active_face_get(em->bm, sloppy, selected); + ED_uvedit_get_aspect(scene, ob, em, &aspx, &aspy); - if (editFace) { - MTexPoly *tf; - float aspx, aspy; - tf = CustomData_bmesh_get(&em->bm->pdata, editFace->head.data, CD_MTEXPOLY); - - ED_image_get_uv_aspect(tf->tpage, NULL, &aspx, &aspy); - - if (aspx != aspy) - param_aspect_ratio(handle, aspx, aspy); - else - param_aspect_ratio(handle, 1.0, 1.0); - } + if (aspx != aspy) + param_aspect_ratio(handle, aspx, aspy); } /* number of subdivisions to perform */ smd.levels = scene->toolsettings->uv_subsurf_level; smd.subdivType = ME_CC_SUBSURF; - initialDerived = CDDM_from_BMEditMesh(em, NULL, 0, 0); + initialDerived = CDDM_from_editbmesh(em, FALSE, FALSE); derivedMesh = subsurf_make_derived_from_derived(initialDerived, &smd, NULL, SUBSURF_IN_EDIT_MODE); @@ -420,6 +426,7 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, BMEditMesh *e origVertIndices = derivedMesh->getVertDataArray(derivedMesh, CD_ORIGINDEX); origEdgeIndices = derivedMesh->getEdgeDataArray(derivedMesh, CD_ORIGINDEX); origFaceIndices = derivedMesh->getTessFaceDataArray(derivedMesh, CD_ORIGINDEX); + origPolyIndices = derivedMesh->getPolyDataArray(derivedMesh, CD_ORIGINDEX); numOfEdges = derivedMesh->getNumEdges(derivedMesh); numOfFaces = derivedMesh->getNumTessFaces(derivedMesh); @@ -431,7 +438,7 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, BMEditMesh *e /* map subsurfed faces to original editFaces */ for (i = 0; i < numOfFaces; i++) - faceMap[i] = EDBM_face_at_index(em, origFaceIndices[i]); + faceMap[i] = EDBM_face_at_index(em, DM_origindex_mface_mpoly(origFaceIndices, origPolyIndices, i)); edgeMap = MEM_mallocN(numOfEdges * sizeof(BMEdge *), "unwrap_edit_edge_map"); @@ -538,7 +545,7 @@ static int minimize_stretch_init(bContext *C, wmOperator *op) ms->blend = RNA_float_get(op->ptr, "blend"); ms->iterations = RNA_int_get(op->ptr, "iterations"); ms->i = 0; - ms->handle = construct_param_handle(scene, em, implicit, fill_holes, 1, 1); + ms->handle = construct_param_handle(scene, obedit, em, implicit, fill_holes, 1, 1); ms->lasttime = PIL_check_seconds_timer(); param_stretch_begin(ms->handle); @@ -727,14 +734,12 @@ static int pack_islands_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (RNA_struct_property_is_set(op->ptr, "margin")) { + if (RNA_struct_property_is_set(op->ptr, "margin")) scene->toolsettings->uvcalc_margin = RNA_float_get(op->ptr, "margin"); - } - else { + else RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin); - } - handle = construct_param_handle(scene, em, implicit, 0, 1, 1); + handle = construct_param_handle(scene, obedit, em, implicit, 0, 1, 1); param_pack(handle, scene->toolsettings->uvcalc_margin); param_flush(handle); param_delete(handle); @@ -759,7 +764,7 @@ void UV_OT_pack_islands(wmOperatorType *ot) ot->poll = ED_operator_uvedit; /* properties */ - RNA_def_float_factor(ot->srna, "margin", 0.0f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f); + RNA_def_float_factor(ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f); } /* ******************** Average Islands Scale operator **************** */ @@ -776,7 +781,7 @@ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } - handle = construct_param_handle(scene, em, implicit, 0, 1, 1); + handle = construct_param_handle(scene, obedit, em, implicit, 0, 1, 1); param_average(handle); param_flush(handle); param_delete(handle); @@ -817,9 +822,9 @@ void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit) } if (use_subsurf) - liveHandle = construct_param_handle_subsurfed(scene, em, fillholes, 0, 1); + liveHandle = construct_param_handle_subsurfed(scene, obedit, em, fillholes, 0, 1); else - liveHandle = construct_param_handle(scene, em, 0, fillholes, 0, 1); + liveHandle = construct_param_handle(scene, obedit, em, 0, fillholes, 0, 1); param_lscm_begin(liveHandle, PARAM_TRUE, abf); } @@ -1007,22 +1012,15 @@ static void uv_transform_properties(wmOperatorType *ot, int radius) "Radius of the sphere or cylinder", 0.0001f, 100.0f); } -static void correct_uv_aspect(BMEditMesh *em) +static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em) { - int sloppy = TRUE; - int selected = FALSE; - BMFace *efa = BM_active_face_get(em->bm, sloppy, selected); BMLoop *l; BMIter iter, liter; MLoopUV *luv; - float scale, aspx = 1.0f, aspy = 1.0f; + BMFace *efa; + float scale, aspx, aspy; - if (efa) { - MTexPoly *tf; - - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); - ED_image_get_uv_aspect(tf->tpage, NULL, &aspx, &aspy); - } + ED_uvedit_get_aspect(scene, ob, em, &aspx, &aspy); if (aspx == aspy) return; @@ -1067,7 +1065,7 @@ static void uv_map_clip_correct_properties(wmOperatorType *ot) "Scale UV coordinates to bounds after unwrapping"); } -static void uv_map_clip_correct(BMEditMesh *em, wmOperator *op) +static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOperator *op) { BMFace *efa; BMLoop *l; @@ -1080,7 +1078,7 @@ static void uv_map_clip_correct(BMEditMesh *em, wmOperator *op) /* correct for image aspect ratio */ if (correct_aspect) - correct_uv_aspect(em); + correct_uv_aspect(scene, ob, em); if (scale_to_bounds) { INIT_MINMAX2(min, max); @@ -1144,9 +1142,9 @@ void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel) const short use_subsurf = scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF; if (use_subsurf) - handle = construct_param_handle_subsurfed(scene, em, fill_holes, sel, correct_aspect); + handle = construct_param_handle_subsurfed(scene, obedit, em, fill_holes, sel, correct_aspect); else - handle = construct_param_handle(scene, em, 0, fill_holes, sel, correct_aspect); + handle = construct_param_handle(scene, obedit, em, 0, fill_holes, sel, correct_aspect); param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0); param_lscm_solve(handle); @@ -1170,7 +1168,7 @@ static int unwrap_exec(bContext *C, wmOperator *op) int correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect"); int use_subsurf = RNA_boolean_get(op->ptr, "use_subsurf_data"); int subsurf_level = RNA_int_get(op->ptr, "uv_subsurf_level"); - float obsize[3], unitsize[3] = {1.0f, 1.0f, 1.0f}; + float obsize[3]; short implicit = 0; if (!uvedit_have_selection(scene, em, implicit)) { @@ -1183,8 +1181,9 @@ static int unwrap_exec(bContext *C, wmOperator *op) } mat4_to_size(obsize, obedit->obmat); - if (!compare_v3v3(obsize, unitsize, 1e-4f)) - BKE_report(op->reports, RPT_INFO, "Object scale is not 1.0. Unwrap will operate on a non-scaled version of the mesh."); + if (!(fabsf(obsize[0] - obsize[1]) < 1e-4f && fabsf(obsize[1] - obsize[2]) < 1e-4f)) + BKE_report(op->reports, RPT_INFO, + "Object has non-uniform scale, unwrap will operate on a non-scaled version of the mesh"); /* remember last method for live unwrap */ if (RNA_struct_property_is_set(op->ptr, "method")) @@ -1192,6 +1191,12 @@ static int unwrap_exec(bContext *C, wmOperator *op) else RNA_enum_set(op->ptr, "method", scene->toolsettings->unwrapper); + /* remember packing marging */ + if (RNA_struct_property_is_set(op->ptr, "margin")) + scene->toolsettings->uvcalc_margin = RNA_float_get(op->ptr, "margin"); + else + RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin); + scene->toolsettings->uv_subsurf_level = subsurf_level; if (fill_holes) scene->toolsettings->uvcalc_flag |= UVCALC_FILLHOLES; @@ -1239,8 +1244,9 @@ void UV_OT_unwrap(wmOperatorType *ot) "Map UVs taking image aspect ratio into account"); RNA_def_boolean(ot->srna, "use_subsurf_data", 0, "Use Subsurf Data", "Map UVs taking vertex position after subsurf into account"); - RNA_def_int(ot->srna, "uv_subsurf_level", 1, 1, 6, "SubSurf Target", + RNA_def_int(ot->srna, "uv_subsurf_level", 1, 1, 6, "Subsurf Target", "Number of times to subdivide before calculating UVs", 1, 6); + RNA_def_float_factor(ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f); } /**************** Project From View operator **************/ @@ -1313,7 +1319,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op) } } - uv_map_clip_correct(em, op); + uv_map_clip_correct(scene, obedit, em, op); DAG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); @@ -1428,8 +1434,8 @@ static void uv_map_mirror(BMEditMesh *em, BMFace *efa, MTexPoly *UNUSED(tf)) if (i != mi) { dx = uvs[mi][0] - uvs[i][0]; if (dx > 0.5f) uvs[i][0] += 1.0f; - } - } + } + } BLI_array_fixedstack_free(uvs); } @@ -1467,7 +1473,7 @@ static int sphere_project_exec(bContext *C, wmOperator *op) uv_map_mirror(em, efa, tf); } - uv_map_clip_correct(em, op); + uv_map_clip_correct(scene, obedit, em, op); DAG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); @@ -1542,7 +1548,7 @@ static int cylinder_project_exec(bContext *C, wmOperator *op) uv_map_mirror(em, efa, tf); } - uv_map_clip_correct(em, op); + uv_map_clip_correct(scene, obedit, em, op); DAG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); @@ -1622,7 +1628,7 @@ static int cube_project_exec(bContext *C, wmOperator *op) } } - uv_map_clip_correct(em, op); + uv_map_clip_correct(scene, obedit, em, op); DAG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h index 1729ac06f5a..36fbd818f11 100644 --- a/source/blender/gpu/GPU_buffers.h +++ b/source/blender/gpu/GPU_buffers.h @@ -123,37 +123,36 @@ void GPU_global_buffer_pool_free(void); GPUBuffer *GPU_buffer_alloc(int size); void GPU_buffer_free(GPUBuffer *buffer); -GPUDrawObject *GPU_drawobject_new(struct DerivedMesh *dm ); -void GPU_drawobject_free(struct DerivedMesh *dm ); +GPUDrawObject *GPU_drawobject_new(struct DerivedMesh *dm); +void GPU_drawobject_free(struct DerivedMesh *dm); /* called before drawing */ -void GPU_vertex_setup(struct DerivedMesh *dm ); -void GPU_normal_setup(struct DerivedMesh *dm ); -void GPU_uv_setup(struct DerivedMesh *dm ); -void GPU_color_setup(struct DerivedMesh *dm ); -void GPU_edge_setup(struct DerivedMesh *dm ); /* does not mix with other data */ -void GPU_uvedge_setup(struct DerivedMesh *dm ); -int GPU_attrib_element_size( GPUAttrib data[], int numdata ); -void GPU_interleaved_attrib_setup( GPUBuffer *buffer, GPUAttrib data[], int numdata ); +void GPU_vertex_setup(struct DerivedMesh *dm); +void GPU_normal_setup(struct DerivedMesh *dm); +void GPU_uv_setup(struct DerivedMesh *dm); +/* colType is the cddata MCol type to use! */ +void GPU_color_setup(struct DerivedMesh *dm, int colType); +void GPU_edge_setup(struct DerivedMesh *dm); /* does not mix with other data */ +void GPU_uvedge_setup(struct DerivedMesh *dm); +int GPU_attrib_element_size(GPUAttrib data[], int numdata); +void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numdata); /* can't lock more than one buffer at once */ -void *GPU_buffer_lock( GPUBuffer *buffer ); -void *GPU_buffer_lock_stream( GPUBuffer *buffer ); -void GPU_buffer_unlock( GPUBuffer *buffer ); +void *GPU_buffer_lock(GPUBuffer *buffer); +void *GPU_buffer_lock_stream(GPUBuffer *buffer); +void GPU_buffer_unlock(GPUBuffer *buffer); -/* upload three unsigned chars, representing RGB colors, for each vertex. Resets dm->drawObject->colType to -1 */ -void GPU_color3_upload(struct DerivedMesh *dm, unsigned char *data ); /* switch color rendering on=1/off=0 */ -void GPU_color_switch( int mode ); +void GPU_color_switch(int mode); /* used for drawing edges */ -void GPU_buffer_draw_elements( GPUBuffer *elements, unsigned int mode, int start, int count ); +void GPU_buffer_draw_elements(GPUBuffer *elements, unsigned int mode, int start, int count); /* called after drawing */ void GPU_buffer_unbind(void); /* used to check whether to use the old (without buffers) code */ -int GPU_buffer_legacy(struct DerivedMesh *dm ); +int GPU_buffer_legacy(struct DerivedMesh *dm); /* Buffers for non-DerivedMesh drawing */ typedef struct GPU_Buffers GPU_Buffers; @@ -162,18 +161,22 @@ GPU_Buffers *GPU_build_mesh_buffers(int (*face_vert_indices)[4], struct MFace *mface, struct MVert *mvert, int *face_indices, int totface); -void GPU_update_mesh_buffers(GPU_Buffers *buffers, struct MVert *mvert, - int *vert_indices, int totvert, const float *vmask); +void GPU_update_mesh_buffers(GPU_Buffers *buffers, MVert *mvert, + int *vert_indices, int totvert, const float *vmask, + int (*face_vert_indices)[4], int show_diffuse_color); GPU_Buffers *GPU_build_grid_buffers(int *grid_indices, int totgrid, unsigned int **grid_hidden, int gridsize); void GPU_update_grid_buffers(GPU_Buffers *buffers, struct CCGElem **grids, const struct DMFlagMat *grid_flag_mats, - int *grid_indices, int totgrid, const struct CCGKey *key); + int *grid_indices, int totgrid, const struct CCGKey *key, + int show_diffuse_color); void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial); +int GPU_buffers_diffuse_changed(GPU_Buffers *buffers, int show_diffuse_color); + void GPU_free_buffers(GPU_Buffers *buffers); #endif diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index 467adbe10b8..b26c25558c3 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -75,6 +75,8 @@ void GPU_end_object_materials(void); int GPU_enable_material(int nr, void *attribs); void GPU_disable_material(void); +void GPU_material_diffuse_get(int nr, float diff[4]); + void GPU_set_material_alpha_blend(int alphablend); int GPU_get_material_alpha_blend(void); @@ -119,10 +121,10 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap); /* Image updates and free * - these deal with images bound as opengl textures */ -void GPU_paint_update_image(struct Image *ima, int x, int y, int w, int h, int mipmap); +void GPU_paint_update_image(struct Image *ima, int x, int y, int w, int h); void GPU_update_images_framechange(void); int GPU_update_image_time(struct Image *ima, double time); -int GPU_verify_image(struct Image *ima, struct ImageUser *iuser, int tftile, int compare, int mipmap, int ncd); +int GPU_verify_image(struct Image *ima, struct ImageUser *iuser, int tftile, int compare, int mipmap, int isdata); void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float *frect, int rectw, int recth, int mipmap, int use_hight_bit_depth, struct Image *ima); void GPU_create_gl_tex_compressed(unsigned int *bind, unsigned int *pix, int x, int y, int mipmap, struct Image *ima, struct ImBuf *ibuf); int GPU_upload_dxt_texture(struct ImBuf *ibuf); diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 198d002ff0d..7eaa4084e61 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -107,11 +107,11 @@ int GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver); GPUTexture *GPU_texture_create_1D(int w, float *pixels, char err_out[256]); GPUTexture *GPU_texture_create_2D(int w, int h, float *pixels, char err_out[256]); -GPUTexture *GPU_texture_create_3D(int w, int h, int depth, float *fpixels); +GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, float *fpixels); GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]); GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]); GPUTexture *GPU_texture_from_blender(struct Image *ima, - struct ImageUser *iuser, int ncd, double time, int mipmap); + struct ImageUser *iuser, int isdata, double time, int mipmap); void GPU_texture_free(GPUTexture *tex); void GPU_texture_ref(GPUTexture *tex); diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index baa557c3484..97e8b756d08 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -107,7 +107,7 @@ typedef struct GPUNodeStack { GPUNodeLink *GPU_attribute(int type, const char *name); GPUNodeLink *GPU_uniform(float *num); GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data); -GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, int ncd); +GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, int isdata); GPUNodeLink *GPU_texture(int size, float *pixels); GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex, int dynamictype, void *data); GPUNodeLink *GPU_socket(GPUNodeStack *sock); diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index c44a181841e..6e475ace09d 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -54,6 +54,7 @@ #include "DNA_userdef_types.h" #include "GPU_buffers.h" +#include "GPU_draw.h" typedef enum { GPU_BUFFER_VERTEX_STATE = 1, @@ -707,34 +708,6 @@ static void GPU_buffer_copy_uv(DerivedMesh *dm, float *varray, int *index, int * } } - -static void GPU_buffer_copy_color3(DerivedMesh *dm, float *varray_, int *index, int *mat_orig_to_new, void *user) -{ - int i, totface; - char *varray = (char *)varray_; - char *mcol = (char *)user; - MFace *f = dm->getTessFaceArray(dm); - - totface = dm->getNumTessFaces(dm); - for (i = 0; i < totface; i++, f++) { - int start = index[mat_orig_to_new[f->mat_nr]]; - - /* v1 v2 v3 */ - copy_v3_v3_char(&varray[start], &mcol[i * 12]); - copy_v3_v3_char(&varray[start + 3], &mcol[i * 12 + 3]); - copy_v3_v3_char(&varray[start + 6], &mcol[i * 12 + 6]); - index[mat_orig_to_new[f->mat_nr]] += 9; - - if (f->v4) { - /* v3 v4 v1 */ - copy_v3_v3_char(&varray[start + 9], &mcol[i * 12 + 6]); - copy_v3_v3_char(&varray[start + 12], &mcol[i * 12 + 9]); - copy_v3_v3_char(&varray[start + 15], &mcol[i * 12]); - index[mat_orig_to_new[f->mat_nr]] += 9; - } - } -} - static void copy_mcol_uc3(unsigned char *v, unsigned char *col) { v[0] = col[3]; @@ -819,28 +792,6 @@ static void GPU_buffer_copy_uvedge(DerivedMesh *dm, float *varray, int *UNUSED(i } } -/* get the DerivedMesh's MCols; choose (in decreasing order of - * preference) from CD_ID_MCOL, CD_PREVIEW_MCOL, or CD_MCOL */ -static MCol *gpu_buffer_color_type(DerivedMesh *dm) -{ - MCol *c; - int type; - - type = CD_ID_MCOL; - c = DM_get_tessface_data_layer(dm, type); - if (!c) { - type = CD_PREVIEW_MCOL; - c = DM_get_tessface_data_layer(dm, type); - if (!c) { - type = CD_MCOL; - c = DM_get_tessface_data_layer(dm, type); - } - } - - dm->drawObject->colType = type; - return c; -} - typedef enum { GPU_BUFFER_VERTEX = 0, GPU_BUFFER_NORMAL, @@ -923,7 +874,7 @@ static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type) /* special handling for MCol and UV buffers */ if (type == GPU_BUFFER_COLOR) { - if (!(user_data = gpu_buffer_color_type(dm))) + if (!(user_data = DM_get_tessface_data_layer(dm, dm->drawObject->colType))) return NULL; } else if (type == GPU_BUFFER_UV) { @@ -943,7 +894,7 @@ static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type) static GPUBuffer *gpu_buffer_setup_common(DerivedMesh *dm, GPUBufferType type) { GPUBuffer **buf; - + if (!dm->drawObject) dm->drawObject = GPU_drawobject_new(dm); @@ -1005,8 +956,28 @@ void GPU_uv_setup(DerivedMesh *dm) GLStates |= GPU_BUFFER_TEXCOORD_STATE; } -void GPU_color_setup(DerivedMesh *dm) +void GPU_color_setup(DerivedMesh *dm, int colType) { + if (!dm->drawObject) { + /* XXX Not really nice, but we need a valid gpu draw object to set the colType... + * Else we would have to add a new param to gpu_buffer_setup_common. */ + dm->drawObject = GPU_drawobject_new(dm); + dm->dirty &= ~DM_DIRTY_MCOL_UPDATE_DRAW; + dm->drawObject->colType = colType; + } + /* In paint mode, dm may stay the same during stroke, however we still want to update colors! + * Also check in case we changed color type (i.e. which MCol cdlayer we use). */ + else if ((dm->dirty & DM_DIRTY_MCOL_UPDATE_DRAW) || (colType != dm->drawObject->colType)) { + GPUBuffer **buf = gpu_drawobject_buffer_from_type(dm->drawObject, GPU_BUFFER_COLOR); + /* XXX Freeing this buffer is a bit stupid, as geometry has not changed, size should remain the same. + * Not sure though it would be worth defining a sort of gpu_buffer_update func - nor whether + * it is even possible ! */ + GPU_buffer_free(*buf); + *buf = NULL; + dm->dirty &= ~DM_DIRTY_MCOL_UPDATE_DRAW; + dm->drawObject->colType = colType; + } + if (!gpu_buffer_setup_common(dm, GPU_BUFFER_COLOR)) return; @@ -1167,20 +1138,6 @@ void GPU_buffer_unbind(void) glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); } -/* confusion: code in cdderivedmesh calls both GPU_color_setup and - * GPU_color3_upload; both of these set the `colors' buffer, so seems - * like it will just needlessly overwrite? --nicholas */ -void GPU_color3_upload(DerivedMesh *dm, unsigned char *data) -{ - if (dm->drawObject == 0) - dm->drawObject = GPU_drawobject_new(dm); - GPU_buffer_free(dm->drawObject->colors); - - dm->drawObject->colors = gpu_buffer_setup(dm, dm->drawObject, 3, - sizeof(char) * 3 * dm->drawObject->tot_triangle_point, - GL_ARRAY_BUFFER_ARB, data, GPU_buffer_copy_color3); -} - void GPU_color_switch(int mode) { if (mode) { @@ -1269,6 +1226,14 @@ void GPU_buffer_draw_elements(GPUBuffer *elements, unsigned int mode, int start, /* XXX: the rest of the code in this file is used for optimized PBVH * drawing and doesn't interact at all with the buffer code above */ +/* Return false if VBO is either unavailable or disabled by the user, + * true otherwise */ +static int gpu_vbo_enabled(void) +{ + return (GLEW_ARB_vertex_buffer_object && + !(U.gameflags & USER_DISABLE_VBO)); +} + /* Convenience struct for building the VBO. */ typedef struct { float co[3]; @@ -1304,6 +1269,13 @@ struct GPU_Buffers { int has_hidden; unsigned int tot_tri, tot_quad; + + /* The PBVH ensures that either all faces in the node are + smooth-shaded or all faces are flat-shaded */ + int smooth; + + int show_diffuse_color; + float diffuse_color[4]; }; typedef enum { VBO_ENABLED, @@ -1327,24 +1299,24 @@ static void gpu_colors_disable(VBO_State vbo_state) static float gpu_color_from_mask(float mask) { - return (1.0f - mask) * 0.5f + 0.25f; + return 1.0f - mask * 0.75f; } -static void gpu_color_from_mask_copy(float mask, unsigned char out[3]) +static void gpu_color_from_mask_copy(float mask, const float diffuse_color[4], unsigned char out[3]) { - unsigned char color; - - color = gpu_color_from_mask(mask) * 255.0f; + float mask_color; - out[0] = color; - out[1] = color; - out[2] = color; + mask_color = gpu_color_from_mask(mask) * 255.0f; + + out[0] = diffuse_color[0] * mask_color; + out[1] = diffuse_color[1] * mask_color; + out[2] = diffuse_color[2] * mask_color; } -static void gpu_color_from_mask_set(float mask) +static void gpu_color_from_mask_set(float mask, float diffuse_color[4]) { float color = gpu_color_from_mask(mask); - glColor3f(color, color, color); + glColor3f(diffuse_color[0] * color, diffuse_color[1] * color, diffuse_color[2] * color); } static float gpu_color_from_mask_quad(const CCGKey *key, @@ -1360,52 +1332,149 @@ static float gpu_color_from_mask_quad(const CCGKey *key, static void gpu_color_from_mask_quad_copy(const CCGKey *key, CCGElem *a, CCGElem *b, CCGElem *c, CCGElem *d, + const float *diffuse_color, unsigned char out[3]) { - unsigned char color = + float mask_color = gpu_color_from_mask((*CCG_elem_mask(key, a) + *CCG_elem_mask(key, b) + *CCG_elem_mask(key, c) + *CCG_elem_mask(key, d)) * 0.25f) * 255.0f; - out[0] = color; - out[1] = color; - out[2] = color; + out[0] = diffuse_color[0] * mask_color; + out[1] = diffuse_color[1] * mask_color; + out[2] = diffuse_color[2] * mask_color; } static void gpu_color_from_mask_quad_set(const CCGKey *key, CCGElem *a, CCGElem *b, - CCGElem *c, CCGElem *d) + CCGElem *c, CCGElem *d, + float diffuse_color[4]) { float color = gpu_color_from_mask_quad(key, a, b, c, d); - glColor3f(color, color, color); + glColor3f(diffuse_color[0] * color, diffuse_color[1] * color, diffuse_color[2] * color); } void GPU_update_mesh_buffers(GPU_Buffers *buffers, MVert *mvert, - int *vert_indices, int totvert, const float *vmask) + int *vert_indices, int totvert, const float *vmask, + int (*face_vert_indices)[4], int show_diffuse_color) { VertexBufferFormat *vert_data; - int i; + int i, j, k; buffers->vmask = vmask; + buffers->show_diffuse_color = show_diffuse_color; if (buffers->vert_buf) { + int totelem = (buffers->smooth ? totvert : (buffers->tot_tri * 3)); + float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f}; + + if (buffers->show_diffuse_color) { + MFace *f = buffers->mface + buffers->face_indices[0]; + + GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color); + } + + copy_v4_v4(buffers->diffuse_color, diffuse_color); + /* Build VBO */ glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf); glBufferDataARB(GL_ARRAY_BUFFER_ARB, - sizeof(VertexBufferFormat) * totvert, - NULL, GL_STATIC_DRAW_ARB); + sizeof(VertexBufferFormat) * totelem, + NULL, GL_STATIC_DRAW_ARB); + vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); if (vert_data) { - for (i = 0; i < totvert; ++i) { - MVert *v = mvert + vert_indices[i]; - VertexBufferFormat *out = vert_data + i; + /* Vertex data is shared if smooth-shaded, but seperate + copies are made for flat shading because normals + shouldn't be shared. */ + if (buffers->smooth) { + for (i = 0; i < totvert; ++i) { + MVert *v = mvert + vert_indices[i]; + VertexBufferFormat *out = vert_data + i; - copy_v3_v3(out->co, v->co); - memcpy(out->no, v->no, sizeof(short) * 3); - gpu_color_from_mask_copy(vmask[vert_indices[i]], - out->color); + copy_v3_v3(out->co, v->co); + memcpy(out->no, v->no, sizeof(short) * 3); + } + +#define UPDATE_VERTEX(face, vertex, index, diffuse_color) \ + { \ + VertexBufferFormat *out = vert_data + face_vert_indices[face][index]; \ + if (vmask) \ + gpu_color_from_mask_copy(vmask[vertex], diffuse_color, out->color); \ + else \ + rgb_float_to_uchar(out->color, diffuse_color); \ + } (void)0 + + for (i = 0; i < buffers->totface; i++) { + MFace *f = buffers->mface + buffers->face_indices[i]; + + UPDATE_VERTEX(i, f->v1, 0, diffuse_color); + UPDATE_VERTEX(i, f->v2, 1, diffuse_color); + UPDATE_VERTEX(i, f->v3, 2, diffuse_color); + if (f->v4) + UPDATE_VERTEX(i, f->v4, 3, diffuse_color); + } +#undef UPDATE_VERTEX + } + else { + for (i = 0; i < buffers->totface; ++i) { + const MFace *f = &buffers->mface[buffers->face_indices[i]]; + const unsigned int *fv = &f->v1; + const int vi[2][3] = {{0, 1, 2}, {3, 0, 2}}; + float fno[3]; + short no[3]; + + float fmask; + + if (paint_is_face_hidden(f, mvert)) + continue; + + /* Face normal and mask */ + if (f->v4) { + normal_quad_v3(fno, + mvert[fv[0]].co, + mvert[fv[1]].co, + mvert[fv[2]].co, + mvert[fv[3]].co); + if (vmask) { + fmask = (vmask[fv[0]] + + vmask[fv[1]] + + vmask[fv[2]] + + vmask[fv[3]]) * 0.25f; + } + } + else { + normal_tri_v3(fno, + mvert[fv[0]].co, + mvert[fv[1]].co, + mvert[fv[2]].co); + if (vmask) { + fmask = (vmask[fv[0]] + + vmask[fv[1]] + + vmask[fv[2]]) / 3.0f; + } + } + normal_float_to_short_v3(no, fno); + + for (j = 0; j < (f->v4 ? 2 : 1); j++) { + for (k = 0; k < 3; k++) { + const MVert *v = &mvert[fv[vi[j][k]]]; + VertexBufferFormat *out = vert_data; + + copy_v3_v3(out->co, v->co); + memcpy(out->no, no, sizeof(short) * 3); + + if (vmask) + gpu_color_from_mask_copy(fmask, diffuse_color, out->color); + else + rgb_float_to_uchar(out->color, diffuse_color); + + vert_data++; + } + } + } } glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); @@ -1432,6 +1501,9 @@ GPU_Buffers *GPU_build_mesh_buffers(int (*face_vert_indices)[4], buffers = MEM_callocN(sizeof(GPU_Buffers), "GPU_Buffers"); buffers->index_type = GL_UNSIGNED_SHORT; + buffers->smooth = mface[face_indices[0]].flag & ME_SMOOTH; + + buffers->show_diffuse_color = FALSE; /* Count the number of visible triangles */ for (i = 0, tottri = 0; i < totface; ++i) { @@ -1439,8 +1511,11 @@ GPU_Buffers *GPU_build_mesh_buffers(int (*face_vert_indices)[4], if (!paint_is_face_hidden(f, mvert)) tottri += f->v4 ? 2 : 1; } - - if (GLEW_ARB_vertex_buffer_object && !(U.gameflags & USER_DISABLE_VBO)) + + /* An element index buffer is used for smooth shading, but flat + shading requires separate vertex normals so an index buffer is + can't be used there. */ + if (gpu_vbo_enabled() && buffers->smooth) glGenBuffersARB(1, &buffers->index_buf); if (buffers->index_buf) { @@ -1484,7 +1559,7 @@ GPU_Buffers *GPU_build_mesh_buffers(int (*face_vert_indices)[4], glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); } - if (buffers->index_buf) + if (gpu_vbo_enabled() && (buffers->index_buf || !buffers->smooth)) glGenBuffersARB(1, &buffers->vert_buf); buffers->tot_tri = tottri; @@ -1498,15 +1573,27 @@ GPU_Buffers *GPU_build_mesh_buffers(int (*face_vert_indices)[4], void GPU_update_grid_buffers(GPU_Buffers *buffers, CCGElem **grids, const DMFlagMat *grid_flag_mats, int *grid_indices, - int totgrid, const CCGKey *key) + int totgrid, const CCGKey *key, int show_diffuse_color) { VertexBufferFormat *vert_data; int i, j, k, x, y; + buffers->show_diffuse_color = show_diffuse_color; + /* Build VBO */ if (buffers->vert_buf) { int totvert = key->grid_area * totgrid; int smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH; + const int has_mask = key->has_mask; + float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f}; + + if (buffers->show_diffuse_color) { + const DMFlagMat *flags = &grid_flag_mats[grid_indices[0]]; + + GPU_material_diffuse_get(flags->mat_nr + 1, diffuse_color); + } + + copy_v4_v4(buffers->diffuse_color, diffuse_color); glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf); glBufferDataARB(GL_ARRAY_BUFFER_ARB, @@ -1524,11 +1611,12 @@ void GPU_update_grid_buffers(GPU_Buffers *buffers, CCGElem **grids, copy_v3_v3(vd->co, CCG_elem_co(key, elem)); if (smooth) { - normal_float_to_short_v3(vd->no, - CCG_elem_no(key, elem)); + normal_float_to_short_v3(vd->no, CCG_elem_no(key, elem)); - gpu_color_from_mask_copy(*CCG_elem_mask(key, elem), - vd->color); + if (has_mask) { + gpu_color_from_mask_copy(*CCG_elem_mask(key, elem), + diffuse_color, vd->color); + } } vd++; } @@ -1556,12 +1644,16 @@ void GPU_update_grid_buffers(GPU_Buffers *buffers, CCGElem **grids, vd = vert_data + (j + 1) * key->grid_size + (k + 1); normal_float_to_short_v3(vd->no, fno); - gpu_color_from_mask_quad_copy(key, - elems[0], - elems[1], - elems[2], - elems[3], - vd->color); + + if (has_mask) { + gpu_color_from_mask_quad_copy(key, + elems[0], + elems[1], + elems[2], + elems[3], + diffuse_color, + vd->color); + } } } } @@ -1583,6 +1675,8 @@ void GPU_update_grid_buffers(GPU_Buffers *buffers, CCGElem **grids, buffers->grid_flag_mats = grid_flag_mats; buffers->gridkey = *key; + buffers->smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH; + //printf("node updated %p\n", buffers); } @@ -1677,7 +1771,7 @@ static GLuint gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned *to /* VBO is disabled; delete the previous buffer (if it exists) and * return an invalid handle */ - if (!GLEW_ARB_vertex_buffer_object || (U.gameflags & USER_DISABLE_VBO)) { + if (!gpu_vbo_enabled()) { if (buffer) glDeleteBuffersARB(1, &buffer); return 0; @@ -1726,6 +1820,8 @@ GPU_Buffers *GPU_build_grid_buffers(int *grid_indices, int totgrid, buffers->grid_hidden = grid_hidden; buffers->totgrid = totgrid; + buffers->show_diffuse_color = FALSE; + /* Count the number of quads */ totquad = gpu_count_grid_quads(grid_hidden, grid_indices, totgrid, gridsize); @@ -1765,12 +1861,20 @@ GPU_Buffers *GPU_build_grid_buffers(int *grid_indices, int totgrid, #undef FILL_QUAD_BUFFER -static void gpu_draw_buffers_legacy_mesh(GPU_Buffers *buffers, int smooth) +static void gpu_draw_buffers_legacy_mesh(GPU_Buffers *buffers) { const MVert *mvert = buffers->mvert; int i, j; + const int has_mask = (buffers->vmask != NULL); + const MFace *face = &buffers->mface[buffers->face_indices[0]]; + float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f}; - gpu_colors_enable(VBO_DISABLED); + if (buffers->show_diffuse_color) + GPU_material_diffuse_get(face->mat_nr + 1, diffuse_color); + + if (has_mask) { + gpu_colors_enable(VBO_DISABLED); + } for (i = 0; i < buffers->totface; ++i) { MFace *f = buffers->mface + buffers->face_indices[i]; @@ -1782,15 +1886,17 @@ static void gpu_draw_buffers_legacy_mesh(GPU_Buffers *buffers, int smooth) glBegin((f->v4) ? GL_QUADS : GL_TRIANGLES); - if (smooth) { + if (buffers->smooth) { for (j = 0; j < S; j++) { - gpu_color_from_mask_set(buffers->vmask[fv[j]]); + if (has_mask) { + gpu_color_from_mask_set(buffers->vmask[fv[j]], diffuse_color); + } glNormal3sv(mvert[fv[j]].no); glVertex3fv(mvert[fv[j]].co); } } else { - float fmask, fno[3]; + float fno[3]; /* calculate face normal */ if (f->v4) { @@ -1801,15 +1907,19 @@ static void gpu_draw_buffers_legacy_mesh(GPU_Buffers *buffers, int smooth) normal_tri_v3(fno, mvert[fv[0]].co, mvert[fv[1]].co, mvert[fv[2]].co); glNormal3fv(fno); - /* calculate face mask color */ - fmask = (buffers->vmask[fv[0]] + - buffers->vmask[fv[1]] + - buffers->vmask[fv[2]]); - if (f->v4) - fmask = (fmask + buffers->vmask[fv[3]]) * 0.25; - else - fmask /= 3.0f; - gpu_color_from_mask_set(fmask); + if (has_mask) { + float fmask; + + /* calculate face mask color */ + fmask = (buffers->vmask[fv[0]] + + buffers->vmask[fv[1]] + + buffers->vmask[fv[2]]); + if (f->v4) + fmask = (fmask + buffers->vmask[fv[3]]) * 0.25f; + else + fmask /= 3.0f; + gpu_color_from_mask_set(fmask, diffuse_color); + } for (j = 0; j < S; j++) glVertex3fv(mvert[fv[j]].co); @@ -1818,15 +1928,25 @@ static void gpu_draw_buffers_legacy_mesh(GPU_Buffers *buffers, int smooth) glEnd(); } - gpu_colors_disable(VBO_DISABLED); + if (has_mask) { + gpu_colors_disable(VBO_DISABLED); + } } -static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers, int smooth) +static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers) { const CCGKey *key = &buffers->gridkey; int i, j, x, y, gridsize = buffers->gridkey.grid_size; + const int has_mask = key->has_mask; + const DMFlagMat *flags = &buffers->grid_flag_mats[buffers->grid_indices[0]]; + float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f}; - gpu_colors_enable(VBO_DISABLED); + if (buffers->show_diffuse_color) + GPU_material_diffuse_get(flags->mat_nr + 1, diffuse_color); + + if (has_mask) { + gpu_colors_enable(VBO_DISABLED); + } for (i = 0; i < buffers->totgrid; ++i) { int g = buffers->grid_indices[i]; @@ -1851,9 +1971,11 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers, int smooth) if (paint_is_grid_face_hidden(gh, gridsize, x, y)) continue; - if (smooth) { + if (buffers->smooth) { for (j = 0; j < 4; j++) { - gpu_color_from_mask_set(*CCG_elem_mask(key, e[j])); + if (has_mask) { + gpu_color_from_mask_set(*CCG_elem_mask(key, e[j]), diffuse_color); + } glNormal3fv(CCG_elem_no(key, e[j])); glVertex3fv(CCG_elem_co(key, e[j])); } @@ -1866,7 +1988,10 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers, int smooth) CCG_elem_co(key, e[2]), CCG_elem_co(key, e[3])); glNormal3fv(fno); - gpu_color_from_mask_quad_set(key, e[0], e[1], e[2], e[3]); + + if (has_mask) { + gpu_color_from_mask_quad_set(key, e[0], e[1], e[2], e[3], diffuse_color); + } for (j = 0; j < 4; j++) glVertex3fv(CCG_elem_co(key, e[j])); @@ -1876,17 +2001,21 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers, int smooth) glEnd(); } - else if (smooth) { + else if (buffers->smooth) { for (y = 0; y < gridsize - 1; y++) { glBegin(GL_QUAD_STRIP); for (x = 0; x < gridsize; x++) { CCGElem *a = CCG_grid_elem(key, grid, x, y); CCGElem *b = CCG_grid_elem(key, grid, x, y + 1); - gpu_color_from_mask_set(*CCG_elem_mask(key, a)); + if (has_mask) { + gpu_color_from_mask_set(*CCG_elem_mask(key, a), diffuse_color); + } glNormal3fv(CCG_elem_no(key, a)); glVertex3fv(CCG_elem_co(key, a)); - gpu_color_from_mask_set(*CCG_elem_mask(key, b)); + if (has_mask) { + gpu_color_from_mask_set(*CCG_elem_mask(key, b), diffuse_color); + } glNormal3fv(CCG_elem_no(key, b)); glVertex3fv(CCG_elem_co(key, b)); } @@ -1912,7 +2041,9 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers, int smooth) CCG_elem_co(key, c)); glNormal3fv(fno); - gpu_color_from_mask_quad_set(key, a, b, c, d); + if (has_mask) { + gpu_color_from_mask_quad_set(key, a, b, c, d, diffuse_color); + } } glVertex3fv(CCG_elem_co(key, a)); @@ -1923,37 +2054,35 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers, int smooth) } } - gpu_colors_disable(VBO_DISABLED); + if (has_mask) { + gpu_colors_disable(VBO_DISABLED); + } } void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial) { - int smooth = 0; - if (buffers->totface) { const MFace *f = &buffers->mface[buffers->face_indices[0]]; if (!setMaterial(f->mat_nr + 1, NULL)) return; - - smooth = f->flag & ME_SMOOTH; - glShadeModel(smooth ? GL_SMOOTH : GL_FLAT); } else if (buffers->totgrid) { const DMFlagMat *f = &buffers->grid_flag_mats[buffers->grid_indices[0]]; if (!setMaterial(f->mat_nr + 1, NULL)) return; - - smooth = f->flag & ME_SMOOTH; - glShadeModel(smooth ? GL_SMOOTH : GL_FLAT); } - if (buffers->vert_buf && buffers->index_buf) { + glShadeModel((buffers->smooth || buffers->totface) ? GL_SMOOTH : GL_FLAT); + + if (buffers->vert_buf) { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); gpu_colors_enable(VBO_ENABLED); glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf); - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf); + + if (buffers->index_buf) + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf); if (buffers->tot_quad) { char *offset = 0; @@ -1972,6 +2101,8 @@ void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial) } } else { + int totelem = buffers->tot_tri * 3; + glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat), (void *)offsetof(VertexBufferFormat, co)); glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat), @@ -1979,11 +2110,15 @@ void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial) glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat), (void *)offsetof(VertexBufferFormat, color)); - glDrawElements(GL_TRIANGLES, buffers->tot_tri * 3, buffers->index_type, 0); + if (buffers->index_buf) + glDrawElements(GL_TRIANGLES, totelem, buffers->index_type, 0); + else + glDrawArrays(GL_TRIANGLES, 0, totelem); } glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + if (buffers->index_buf) + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); @@ -1991,13 +2126,39 @@ void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial) } /* fallbacks if we are out of memory or VBO is disabled */ else if (buffers->totface) { - gpu_draw_buffers_legacy_mesh(buffers, smooth); + gpu_draw_buffers_legacy_mesh(buffers); } else if (buffers->totgrid) { - gpu_draw_buffers_legacy_grids(buffers, smooth); + gpu_draw_buffers_legacy_grids(buffers); } } +int GPU_buffers_diffuse_changed(GPU_Buffers *buffers, int show_diffuse_color) +{ + float diffuse_color[4]; + + if (buffers->show_diffuse_color != show_diffuse_color) + return TRUE; + + if (buffers->show_diffuse_color == FALSE) + return FALSE; + + if (buffers->mface) { + MFace *f = buffers->mface + buffers->face_indices[0]; + + GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color); + } + else { + const DMFlagMat *flags = &buffers->grid_flag_mats[buffers->grid_indices[0]]; + + GPU_material_diffuse_get(flags->mat_nr + 1, diffuse_color); + } + + return diffuse_color[0] != buffers->diffuse_color[0] || + diffuse_color[1] != buffers->diffuse_color[1] || + diffuse_color[2] != buffers->diffuse_color[2]; +} + void GPU_free_buffers(GPU_Buffers *buffers) { if (buffers) { diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 25990e8fc6e..b4490e656f3 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -761,7 +761,7 @@ void GPU_pass_bind(GPUPass *pass, double time, int mipmap) /* now bind the textures */ for (input=inputs->first; input; input=input->next) { if (input->ima) - input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->imagencd, time, mipmap); + input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->image_isdata, time, mipmap); if (input->tex && input->bindtex) { GPU_texture_bind(input->tex, input->texid); @@ -917,7 +917,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type) input->ima = link->ptr1; input->iuser = link->ptr2; - input->imagencd = link->imagencd; + input->image_isdata = link->image_isdata; input->textarget = GL_TEXTURE_2D; input->textype = GPU_TEX2D; MEM_freeN(link); @@ -1046,17 +1046,20 @@ static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *a } } - if (a == attribs->totlayer && a < GPU_MAX_ATTRIB) { - input->attribid = attribs->totlayer++; - input->attribfirst = 1; + if (a < GPU_MAX_ATTRIB) { + if (a == attribs->totlayer) { + input->attribid = attribs->totlayer++; + input->attribfirst = 1; - attribs->layer[a].type = input->attribtype; - attribs->layer[a].attribid = input->attribid; - BLI_strncpy(attribs->layer[a].name, input->attribname, - sizeof(attribs->layer[a].name)); + attribs->layer[a].type = input->attribtype; + attribs->layer[a].attribid = input->attribid; + BLI_strncpy(attribs->layer[a].name, input->attribname, + sizeof(attribs->layer[a].name)); + } + else { + input->attribid = attribs->layer[a].attribid; + } } - else - input->attribid = attribs->layer[a].attribid; } } } @@ -1110,14 +1113,14 @@ GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data) return link; } -GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, int ncd) +GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, int isdata) { GPUNodeLink *link = GPU_node_link_create(0); link->image= 1; link->ptr1= ima; link->ptr2= iuser; - link->imagencd= ncd; + link->image_isdata= isdata; return link; } diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h index 3010937a2f3..f61f34908c5 100644 --- a/source/blender/gpu/intern/gpu_codegen.h +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -91,7 +91,7 @@ struct GPUNodeLink { const char *attribname; int image; - int imagencd; + int image_isdata; int texture; int texturesize; @@ -99,7 +99,7 @@ struct GPUNodeLink { void *ptr1, *ptr2; int dynamic; - int dynamictype; + int dynamictype; int type; int users; @@ -138,7 +138,7 @@ typedef struct GPUInput { struct Image *ima; /* image */ struct ImageUser *iuser;/* image user */ - int imagencd; /* image does not contain color data */ + int image_isdata; /* image does not contain color data */ float *dynamicvec; /* vector data in case it is dynamic */ int dynamictype; /* origin of the dynamic uniform (GPUDynamicType) */ void *dynamicdata; /* data source of the dynamic uniform */ diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 9b027f7906d..7bd72430969 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -422,7 +422,7 @@ static void gpu_verify_reflection(Image *ima) } } -int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int mipmap, int ncd) +int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int mipmap, int is_data) { ImBuf *ibuf = NULL; unsigned int *bind = NULL; @@ -492,7 +492,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int } /* TODO unneeded when float images are correctly treated as linear always */ - if (!ncd) + if (!is_data) do_color_management = TRUE; if (ibuf->rect==NULL) @@ -611,12 +611,21 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int rect= tilerect; } } + #ifdef WITH_DDS if (ibuf->ftype & DDS) GPU_create_gl_tex_compressed(bind, rect, rectw, recth, mipmap, ima, ibuf); else #endif GPU_create_gl_tex(bind, rect, frect, rectw, recth, mipmap, use_high_bit_depth, ima); + + /* mark as non-color data texture */ + if (*bind) { + if (is_data) + ima->tpageflag |= IMA_GLBIND_IS_DATA; + else + ima->tpageflag &= ~IMA_GLBIND_IS_DATA; + } /* clean up */ if (tilerect) @@ -709,7 +718,7 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float * frect, int */ int GPU_upload_dxt_texture(ImBuf *ibuf) { -#if WITH_DDS +#ifdef WITH_DDS GLint format = 0; int blocksize, height, width, i, size, offset = 0; @@ -730,12 +739,17 @@ int GPU_upload_dxt_texture(ImBuf *ibuf) return FALSE; } + if (!is_power_of_2_i(width) || !is_power_of_2_i(height)) { + printf("Unable to load non-power-of-two DXT image resolution, falling back to uncompressed\n"); + return FALSE; + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - blocksize = (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16; + blocksize = (ibuf->dds_data.fourcc == FOURCC_DXT1) ? 8 : 16; for (i=0; idds_data.nummipmaps && (width||height); ++i) { if (width == 0) width = 1; @@ -878,13 +892,13 @@ void GPU_paint_set_mipmap(int mipmap) } } -void GPU_paint_update_image(Image *ima, int x, int y, int w, int h, int mipmap) +void GPU_paint_update_image(Image *ima, int x, int y, int w, int h) { ImBuf *ibuf; ibuf = BKE_image_get_ibuf(ima, NULL); - if (ima->repbind || (GPU_get_mipmap() && mipmap) || !ima->bindcode || !ibuf || + if (ima->repbind || (GPU_get_mipmap() && !GTS.gpu_mipmap) || !ima->bindcode || !ibuf || (!is_power_of_2_i(ibuf->x) || !is_power_of_2_i(ibuf->y)) || (w == 0) || (h == 0)) { @@ -903,7 +917,8 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h, int mipmap) /* if color correction is needed, we must update the part that needs updating. */ if (ibuf->rect_float) { float *buffer = MEM_mallocN(w*h*sizeof(float)*4, "temp_texpaint_float_buf"); - IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h); + int is_data = (ima->tpageflag & IMA_GLBIND_IS_DATA); + IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h, is_data); glBindTexture(GL_TEXTURE_2D, ima->bindcode); glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, @@ -911,8 +926,14 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h, int mipmap) MEM_freeN(buffer); - if (ima->tpageflag & IMA_MIPMAP_COMPLETE) + /* we have already accounted for the case where GTS.gpu_mipmap is false + * so we will be using GPU mipmap generation here */ + if (GPU_get_mipmap()) { + glGenerateMipmapEXT(GL_TEXTURE_2D); + } + else { ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; + } return; } @@ -923,19 +944,20 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h, int mipmap) glPixelStorei(GL_UNPACK_SKIP_PIXELS, x); glPixelStorei(GL_UNPACK_SKIP_ROWS, y); - if (ibuf->rect_float) - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, - GL_FLOAT, ibuf->rect_float); - else - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, - GL_UNSIGNED_BYTE, ibuf->rect); + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, + GL_UNSIGNED_BYTE, ibuf->rect); glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows); - if (ima->tpageflag & IMA_MIPMAP_COMPLETE) + /* see comment above as to why we are using gpu mipmap generation here */ + if (GPU_get_mipmap()) { + glGenerateMipmapEXT(GL_TEXTURE_2D); + } + else { ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; + } } } @@ -1008,21 +1030,53 @@ void GPU_free_smoke(SmokeModifierData *smd) if (smd->domain->tex_shadow) GPU_texture_free(smd->domain->tex_shadow); smd->domain->tex_shadow = NULL; + + if (smd->domain->tex_flame) + GPU_texture_free(smd->domain->tex_flame); + smd->domain->tex_flame = NULL; } } void GPU_create_smoke(SmokeModifierData *smd, int highres) { #ifdef WITH_SMOKE - if (smd->type & MOD_SMOKE_TYPE_DOMAIN && !smd->domain->tex && !highres) - smd->domain->tex = GPU_texture_create_3D(smd->domain->res[0], smd->domain->res[1], smd->domain->res[2], smoke_get_density(smd->domain->fluid)); - else if (smd->type & MOD_SMOKE_TYPE_DOMAIN && !smd->domain->tex && highres) - smd->domain->tex = GPU_texture_create_3D(smd->domain->res_wt[0], smd->domain->res_wt[1], smd->domain->res_wt[2], smoke_turbulence_get_density(smd->domain->wt)); + if (smd->type & MOD_SMOKE_TYPE_DOMAIN) { + SmokeDomainSettings *sds = smd->domain; + if (!sds->tex && !highres) { + /* rgba texture for color + density */ + if (smoke_has_colors(sds->fluid)) { + float *data = MEM_callocN(sizeof(float)*sds->total_cells*4, "smokeColorTexture"); + smoke_get_rgba(sds->fluid, data, 0); + sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 4, data); + MEM_freeN(data); + } + /* density only */ + else { + sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, smoke_get_density(sds->fluid)); + } + sds->tex_flame = (smoke_has_fuel(sds->fluid)) ? GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, smoke_get_flame(sds->fluid)) : NULL; + } + else if (!sds->tex && highres) { + /* rgba texture for color + density */ + if (smoke_turbulence_has_colors(sds->wt)) { + float *data = MEM_callocN(sizeof(float)*smoke_turbulence_get_cells(sds->wt)*4, "smokeColorTexture"); + smoke_turbulence_get_rgba(sds->wt, data, 0); + sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 4, data); + MEM_freeN(data); + } + /* density only */ + else { + sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1, smoke_turbulence_get_density(sds->wt)); + } + sds->tex_flame = (smoke_turbulence_has_fuel(sds->wt)) ? GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1, smoke_turbulence_get_flame(sds->wt)) : NULL; + } - smd->domain->tex_shadow = GPU_texture_create_3D(smd->domain->res[0], smd->domain->res[1], smd->domain->res[2], smd->domain->shadow); + sds->tex_shadow = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, sds->shadow); + } #else // WITH_SMOKE (void)highres; smd->domain->tex= NULL; + smd->domain->tex_flame= NULL; smd->domain->tex_shadow= NULL; #endif // WITH_SMOKE } @@ -1087,7 +1141,7 @@ void GPU_free_image(Image *ima) ima->repbind= NULL; } - ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; + ima->tpageflag &= ~(IMA_MIPMAP_COMPLETE|IMA_GLBIND_IS_DATA); } void GPU_free_images(void) @@ -1173,7 +1227,7 @@ static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat, if (gamma) { linearrgb_to_srgb_v3_v3(smat->diff, smat->diff); linearrgb_to_srgb_v3_v3(smat->spec, smat->spec); - } + } } } @@ -1198,10 +1252,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O GPUBlendMode alphablend; int a; - /* OCIO_TODO: assume color management is always enabled. could be nice to support real display transform here, - * but that's not so important and could be done later - */ - int gamma = TRUE; + int gamma = BKE_scene_check_color_management_enabled(scene); int new_shading_nodes = BKE_scene_use_new_shading_nodes(scene); @@ -1429,6 +1480,21 @@ void GPU_disable_material(void) GPU_set_material_alpha_blend(GPU_BLEND_SOLID); } +void GPU_material_diffuse_get(int nr, float diff[4]) +{ + /* prevent index to use un-initialized array items */ + if (nr >= GMS.totmat) + nr = 0; + + /* no GPU_begin_object_materials, use default material */ + if (!GMS.matbuf) { + mul_v3_v3fl(diff, &defmaterial.r, defmaterial.ref + defmaterial.emit); + } + else { + copy_v4_v4(diff, GMS.matbuf[nr].diff); + } +} + void GPU_end_object_materials(void) { GPU_disable_material(); @@ -1587,7 +1653,7 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[][4 glLightfv(GL_LIGHT0+count, GL_SPECULAR, energy); glEnable(GL_LIGHT0+count); - glPopMatrix(); + glPopMatrix(); count++; if (count==8) diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index c5f427fbcab..cef664437b7 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -442,7 +442,7 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in } -GPUTexture *GPU_texture_create_3D(int w, int h, int depth, float *fpixels) +GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, float *fpixels) { GPUTexture *tex; GLenum type, format, internalformat; @@ -480,9 +480,15 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, float *fpixels) GPU_print_error("3D glBindTexture"); - type = GL_FLOAT; // GL_UNSIGNED_BYTE - format = GL_RED; - internalformat = GL_INTENSITY; + type = GL_FLOAT; + if (channels == 4) { + format = GL_RGBA; + internalformat = GL_RGBA; + } + else { + format = GL_RED; + internalformat = GL_INTENSITY; + } //if (fpixels) // pixels = GPU_texture_convert_pixels(w*h*depth, fpixels); @@ -522,7 +528,7 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, float *fpixels) return tex; } -GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int ncd, double time, int mipmap) +GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int isdata, double time, int mipmap) { GPUTexture *tex; GLint w, h, border, lastbindcode, bindcode; @@ -530,7 +536,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int ncd, doub glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode); GPU_update_image_time(ima, time); - bindcode = GPU_verify_image(ima, iuser, 0, 0, mipmap, ncd); + bindcode = GPU_verify_image(ima, iuser, 0, 0, mipmap, isdata); if (ima->gputexture) { ima->gputexture->bindcode = bindcode; @@ -1289,7 +1295,7 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) return retval; } -void GPU_shader_free_builtin_shaders() +void GPU_shader_free_builtin_shaders(void) { if (GG.shaders.vsm_store) { MEM_freeN(GG.shaders.vsm_store); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index dd92b561235..ef73764753c 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -389,10 +389,8 @@ void gpu_material_add_node(GPUMaterial *material, GPUNode *node) int GPU_material_do_color_management(GPUMaterial *mat) { - /* OCIO_TODO: for now assume scene always does color management. probably could be - * improved in the future to support real display transform - * also probably we'll need to get rid ofgame engine's color management flag - */ + if (!BKE_scene_check_color_management_enabled(mat->scene)) + return FALSE; return !((mat->scene->gm.flag & GAME_GLSL_NO_COLOR_MANAGEMENT)); } @@ -782,7 +780,9 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la } } - if (mat->scene->gm.flag & GAME_GLSL_NO_SHADERS); + if (mat->scene->gm.flag & GAME_GLSL_NO_SHADERS) { + /* pass */ + } else if (!(lamp->mode & LA_NO_SPEC) && !(lamp->mode & LA_ONLYSHADOW) && (GPU_link_changed(shi->spec) || ma->spec != 0.0f)) { @@ -843,7 +843,7 @@ static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr) if (ob->transflag & OB_DUPLI) { DupliObject *dob; - ListBase *lb = object_duplilist(shi->gpumat->scene, ob); + ListBase *lb = object_duplilist(shi->gpumat->scene, ob, FALSE); for (dob=lb->first; dob; dob=dob->next) { Object *ob_iter = dob->ob; @@ -1129,7 +1129,7 @@ static void do_material_tex(GPUShadeInput *shi) newnor = tnor; } - norfac = minf(fabsf(mtex->norfac), 1.0f); + norfac = min_ff(fabsf(mtex->norfac), 1.0f); if (norfac == 1.0f && !GPU_link_changed(stencil)) { shi->vn = newnor; @@ -1589,8 +1589,8 @@ void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float a void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend) { - lamp->spotsi= cos(M_PI*spotsize/360.0); - lamp->spotbl= (1.0f - lamp->spotsi)*spotblend; + lamp->spotsi= cosf((float)M_PI * spotsize / 360.0f); + lamp->spotbl= (1.0f - lamp->spotsi) * spotblend; } static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp) @@ -1881,7 +1881,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma) GPUBuiltin gputype; GPUDynamicType dynamictype; GPUDataType datatype; - } builtins[] = { + } builtins[] = { { GPU_VIEW_MATRIX, GPU_DYNAMIC_OBJECT_VIEWMAT, GPU_DATA_16F }, { GPU_INVERSE_VIEW_MATRIX, GPU_DYNAMIC_OBJECT_VIEWIMAT, GPU_DATA_16F }, { GPU_OBJECT_MATRIX, GPU_DYNAMIC_OBJECT_MAT, GPU_DATA_16F }, diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 81c3cab97d4..b930058864c 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -1894,7 +1894,7 @@ void test_shadowbuf_vsm(vec3 rco, sampler2D shadowmap, mat4 shadowpersmat, float } else { result = 1.0; - } + } } } @@ -1992,7 +1992,7 @@ void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out vec4 result) result = vec4(L*color.rgb, 1.0); } -void node_bsdf_glossy(vec4 color, float roughness, vec3 N, vec3 I, out vec4 result) +void node_bsdf_glossy(vec4 color, float roughness, vec3 N, out vec4 result) { /* ambient light */ vec3 L = vec3(0.2); @@ -2013,12 +2013,12 @@ void node_bsdf_glossy(vec4 color, float roughness, vec3 N, vec3 I, out vec4 resu result = vec4(L*color.rgb, 1.0); } -void node_bsdf_anisotropic(vec4 color, float roughnessU, float roughnessV, vec3 N, vec3 I, out vec4 result) +void node_bsdf_anisotropic(vec4 color, float roughness, float anisotropy, float rotation, vec3 N, vec3 T, out vec4 result) { node_bsdf_diffuse(color, 0.0, N, result); } -void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, vec3 I, out vec4 result) +void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, out vec4 result) { node_bsdf_diffuse(color, 0.0, N, result); } @@ -2195,7 +2195,8 @@ void node_light_path( out float is_glossy_ray, out float is_singular_ray, out float is_reflection_ray, - out float is_transmission_ray) + out float is_transmission_ray, + out float ray_length) { is_camera_ray = 1.0; is_shadow_ray = 0.0; @@ -2204,6 +2205,7 @@ void node_light_path( is_singular_ray = 0.0; is_reflection_ray = 0.0; is_transmission_ray = 0.0; + ray_length = 1.0; } void node_light_falloff(float strength, float tsmooth, out float quadratic, out float linear, out float constant) @@ -2221,6 +2223,10 @@ void node_object_info(out vec3 location, out float object_index, out float mater random = 0.0; } +void node_bump(float strength, float height, vec3 N, out vec3 result) +{ + result = N; +} /* output */ diff --git a/source/blender/ikplugin/BIK_api.h b/source/blender/ikplugin/BIK_api.h index e1d5f50edfb..95b1dafd129 100644 --- a/source/blender/ikplugin/BIK_api.h +++ b/source/blender/ikplugin/BIK_api.h @@ -58,7 +58,7 @@ struct BIK_ParamValue { float f[8]; int i[8]; char s[32]; - } value; + } value; }; typedef struct BIK_ParamValue BIK_ParamValue; @@ -92,5 +92,4 @@ void BIK_test_constraint(struct Object *ob, struct bConstraint *cons); } #endif -#endif // __BIK_API_H__ - +#endif /* __BIK_API_H__ */ diff --git a/source/blender/ikplugin/CMakeLists.txt b/source/blender/ikplugin/CMakeLists.txt index 903267c5618..0a0e0e664b4 100644 --- a/source/blender/ikplugin/CMakeLists.txt +++ b/source/blender/ikplugin/CMakeLists.txt @@ -56,9 +56,11 @@ endif() if(WITH_IK_ITASC) add_definitions(-DWITH_IK_ITASC) list(APPEND INC - ../../../extern/Eigen3 ../../../intern/itasc ) + list(APPEND INC_SYS + ../../../extern/Eigen3 + ) list(APPEND SRC intern/itasc_plugin.cpp intern/itasc_plugin.h diff --git a/source/blender/ikplugin/intern/ikplugin_api.h b/source/blender/ikplugin/intern/ikplugin_api.h index 77c962269dc..53d9da8e614 100644 --- a/source/blender/ikplugin/intern/ikplugin_api.h +++ b/source/blender/ikplugin/intern/ikplugin_api.h @@ -60,5 +60,4 @@ typedef struct IKPlugin IKPlugin; } #endif -#endif // __IKPLUGIN_API_H__ - +#endif /* __IKPLUGIN_API_H__ */ diff --git a/source/blender/ikplugin/intern/iksolver_plugin.h b/source/blender/ikplugin/intern/iksolver_plugin.h index dd00c5f4add..c2ae4f937e7 100644 --- a/source/blender/ikplugin/intern/iksolver_plugin.h +++ b/source/blender/ikplugin/intern/iksolver_plugin.h @@ -47,5 +47,4 @@ void iksolver_execute_tree(struct Scene *scene, struct Object *ob, struct bPose } #endif -#endif // __IKSOLVER_PLUGIN_H__ - +#endif /* __IKSOLVER_PLUGIN_H__ */ diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp index c5722995d32..5cf762af3e8 100644 --- a/source/blender/ikplugin/intern/itasc_plugin.cpp +++ b/source/blender/ikplugin/intern/itasc_plugin.cpp @@ -393,7 +393,7 @@ static bool constraint_valid(bConstraint *con) return true; } -int initialize_scene(Object *ob, bPoseChannel *pchan_tip) +static int initialize_scene(Object *ob, bPoseChannel *pchan_tip) { bConstraint *con; int treecount; @@ -1172,10 +1172,8 @@ static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan) switch (ikchan->jointType & ~IK_TRANSY) { case 0: // fixed bone - if (!(ikchan->jointType & IK_TRANSY)) { - joint += ":F"; - ret = arm->addSegment(joint, parent, KDL::Joint::None, 0.0, tip); - } + joint += ":F"; + ret = arm->addSegment(joint, parent, KDL::Joint::None, 0.0, tip); break; case IK_XDOF: // RX only, get the X rotation @@ -1255,7 +1253,7 @@ static IK_Scene *convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan) ret = arm->addSegment(joint, parent, KDL::Joint::TransY, rot[ikchan->ndof - 1]); const float ikstretch = pchan->ikstretch * pchan->ikstretch; /* why invert twice here? */ - weight[1] = (1.0 - minf(1.0 - ikstretch, 1.0f - 0.001f)); + weight[1] = (1.0 - min_ff(1.0 - ikstretch, 1.0f - 0.001f)); weights.push_back(weight[1]); } if (!ret) diff --git a/source/blender/ikplugin/intern/itasc_plugin.h b/source/blender/ikplugin/intern/itasc_plugin.h index 0d5fde0bec0..0500125b4c7 100644 --- a/source/blender/ikplugin/intern/itasc_plugin.h +++ b/source/blender/ikplugin/intern/itasc_plugin.h @@ -52,5 +52,4 @@ void itasc_test_constraint(struct Object *ob, struct bConstraint *cons); } #endif -#endif // __ITASC_PLUGIN_H__ - +#endif /* __ITASC_PLUGIN_H__ */ diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt index 8849265679a..29ed8c95fc6 100644 --- a/source/blender/imbuf/CMakeLists.txt +++ b/source/blender/imbuf/CMakeLists.txt @@ -25,7 +25,6 @@ set(INC . - ../avi ../blenkernel ../blenlib ../blenloader @@ -76,30 +75,12 @@ set(SRC IMB_thumbs.h intern/IMB_allocimbuf.h intern/IMB_anim.h + intern/IMB_colormanagement_intern.h intern/IMB_filetype.h intern/IMB_filter.h intern/IMB_indexer.h intern/IMB_metadata.h - intern/cineon/cin_debug_stuff.h - intern/cineon/cineonfile.h - intern/cineon/cineonlib.h - intern/cineon/dpxfile.h - intern/cineon/dpxlib.h - intern/cineon/logImageCore.h - intern/cineon/logImageLib.h - intern/cineon/logmemfile.h - intern/dds/BlockDXT.h - intern/dds/Color.h - intern/dds/ColorBlock.h - intern/dds/Common.h - intern/dds/DirectDrawSurface.h - intern/dds/Image.h - intern/dds/PixelFormat.h - intern/dds/Stream.h - intern/dds/dds_api.h intern/imbuf.h - intern/openexr/openexr_api.h - intern/openexr/openexr_multi.h # orphan include ../../../intern/ffmpeg/ffmpeg_compat.h @@ -142,6 +123,13 @@ if(WITH_IMAGE_REDCODE) add_definitions(-DWITH_REDCODE) endif() +if(WITH_CODEC_AVI) + list(APPEND INC + ../avi + ) + add_definitions(-DWITH_AVI) +endif() + if(WITH_CODEC_QUICKTIME) list(APPEND INC ../quicktime diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index d09007985b0..0653956e113 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -45,15 +45,11 @@ struct rcti; struct PartialBufferUpdateContext; struct wmWindow; struct Scene; +struct ImageFormatData; struct ColorSpace; struct ColorManagedDisplay; -/* ** Initialization / De-initialization ** */ - -void IMB_colormanagement_init(void); -void IMB_colormanagement_exit(void); - /* ** Generic functions ** */ void IMB_colormanagement_check_file_config(struct Main *bmain); @@ -62,6 +58,9 @@ void IMB_colormanagement_validate_settings(struct ColorManagedDisplaySettings *d struct ColorManagedViewSettings *view_settings); const char *IMB_colormanagement_role_colorspace_name_get(int role); +void IMB_colormanagement_check_is_data(struct ImBuf *ibuf, const char *name); +void IMB_colormanagement_assign_float_colorspace(struct ImBuf *ibuf, const char *name); +void IMB_colormanagement_assign_rect_colorspace(struct ImBuf *ibuf, const char *name); /* ** Color space transformation functions ** */ void IMB_colormanagement_transform(float *buffer, int width, int height, int channels, @@ -84,20 +83,20 @@ void IMB_colormanagement_pixel_to_display_space_v4(float result[4], const float void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float pixel[3], const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings); -void IMB_colormanagement_imbuf_assign_float_space(struct ImBuf *ibuf, struct ColorManagedColorspaceSettings *colorspace_settings); - void IMB_colormanagement_imbuf_make_display_space(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings); +struct ImBuf *IMB_colormanagement_imbuf_for_write(struct ImBuf *ibuf, int save_as_render, int allocate_result, + const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings, + struct ImageFormatData *image_format_data); + /* ** Public display buffers interfaces ** */ unsigned char *IMB_display_buffer_acquire(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, void **cache_handle); unsigned char *IMB_display_buffer_acquire_ctx(const struct bContext *C, struct ImBuf *ibuf, void **cache_handle); -void IMB_display_buffer_to_imbuf_rect(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings); - void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *linear_buffer, int width, int height, int channels, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, int predivide); @@ -109,6 +108,7 @@ int IMB_colormanagement_display_get_named_index(const char *name); const char *IMB_colormanagement_display_get_indexed_name(int index); const char *IMB_colormanagement_display_get_default_name(void); struct ColorManagedDisplay *IMB_colormanagement_display_get_named(const char *name); +const char *IMB_colormanagement_display_get_none_name(void); /* ** View funcrions ** */ int IMB_colormanagement_view_get_named_index(const char *name); @@ -130,7 +130,8 @@ void IMB_colormanagement_colorspace_items_add(struct EnumPropertyItem **items, i void IMB_partial_display_buffer_update(struct ImBuf *ibuf, const float *linear_buffer, const unsigned char *buffer_byte, int stride, int offset_x, int offset_y, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, - int xmin, int ymin, int xmax, int ymax); + int xmin, int ymin, int xmax, int ymax, + int update_orig_byte_buffer); /* ** Pixel processor functions ** */ struct ColormanageProcessor *IMB_colormanagement_display_processor_new(const struct ColorManagedViewSettings *view_settings, diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 1503b9f6f67..d0ac71a7131 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -103,7 +103,7 @@ struct ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, * * \attention Defined in readimage.c */ -struct ImBuf *IMB_testiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE]); +struct ImBuf *IMB_testiffname(const char *filepath, int flags); /** * @@ -371,7 +371,7 @@ void IMB_interlace(struct ImBuf *ibuf); void IMB_rect_from_float(struct ImBuf *ibuf); /* Create char buffer for part of the image, color corrected if necessary, * Changed part will be stored in buffer. This is expected to be used for texture painting updates */ -void IMB_partial_rect_from_float(struct ImBuf *ibuf, float *buffer, int x, int y, int w, int h); +void IMB_partial_rect_from_float(struct ImBuf *ibuf, float *buffer, int x, int y, int w, int h, int is_data); void IMB_float_from_rect(struct ImBuf *ibuf); void IMB_float_from_rect_simple(struct ImBuf *ibuf); /* no profile conversion */ /* note, check that the conversion exists, only some are supported */ @@ -410,10 +410,10 @@ void bicubic_interpolation(struct ImBuf *in, struct ImBuf *out, float u, float v void neareast_interpolation(struct ImBuf *in, struct ImBuf *out, float u, float v, int xout, int yout); void bilinear_interpolation(struct ImBuf *in, struct ImBuf *out, float u, float v, int xout, int yout); -void bicubic_interpolation_color(struct ImBuf *in, unsigned char *col, float *col_float, float u, float v); -void neareast_interpolation_color(struct ImBuf *in, unsigned char *col, float *col_float, float u, float v); -void bilinear_interpolation_color(struct ImBuf *in, unsigned char *col, float *col_float, float u, float v); -void bilinear_interpolation_color_wrap(struct ImBuf *in, unsigned char *col, float *col_float, float u, float v); +void bicubic_interpolation_color(struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v); +void neareast_interpolation_color(struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v); +void bilinear_interpolation_color(struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v); +void bilinear_interpolation_color_wrap(struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v); /** * diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 93e213dc486..28e62d496b2 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -93,7 +93,7 @@ typedef struct ImBuf { /* tiled pixel storage */ int tilex, tiley; int xtiles, ytiles; - unsigned int **tiles; + unsigned int **tiles; /* zbuffer */ int *zbuf; /* z buffer data, original zbuffer */ @@ -131,6 +131,7 @@ typedef struct ImBuf { struct ColorSpace *float_colorspace; /* color space of float buffer, used by sequencer only */ unsigned int *display_buffer_flags; /* array of per-display display buffers dirty flags */ struct ColormanageCache *colormanage_cache; /* cache used by color management */ + int colormanage_flag; /* information for compressed textures */ struct DDSData dds_data; @@ -199,6 +200,10 @@ typedef struct ImBuf { #ifdef WITH_CINEON #define CINEON (1 << 21) #define DPX (1 << 20) +#define CINEON_LOG (1 << 8) +#define CINEON_16BIT (1 << 7) +#define CINEON_12BIT (1 << 6) +#define CINEON_10BIT (1 << 5) #endif #ifdef WITH_DDS @@ -241,7 +246,7 @@ typedef struct ImBuf { ((unsigned long)(unsigned char)(ch1) << 8) | \ ((unsigned long)(unsigned char)(ch2) << 16) | \ ((unsigned long)(unsigned char)(ch3) << 24)) -#endif //MAKEFOURCC +#endif /* MAKEFOURCC */ /* * FOURCC codes for DX compressed-texture pixel formats @@ -254,10 +259,14 @@ typedef struct ImBuf { #define FOURCC_DXT4 (MAKEFOURCC('D','X','T','4')) #define FOURCC_DXT5 (MAKEFOURCC('D','X','T','5')) -#endif // DDS +#endif /* DDS */ extern const char *imb_ext_image[]; extern const char *imb_ext_image_qt[]; extern const char *imb_ext_movie[]; extern const char *imb_ext_audio[]; +enum { + IMB_COLORMANAGE_IS_DATA = (1 << 0) +}; + #endif diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h index d5cc4929aed..ed349e8f7eb 100644 --- a/source/blender/imbuf/intern/IMB_anim.h +++ b/source/blender/imbuf/intern/IMB_anim.h @@ -62,7 +62,9 @@ #include "imbuf.h" -#include "AVI_avi.h" +#ifdef WITH_AVI +# include "AVI_avi.h" +#endif #ifdef WITH_QUICKTIME # if defined(_WIN32) || defined(__APPLE__) diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index 0c002b78848..ba9e20ac411 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -35,7 +35,7 @@ #define BCM_CONFIG_FILE "config.ocio" -struct ConstProcessorRcPtr; +struct OCIO_ConstProcessorRcPtr; struct ImBuf; typedef struct ColorSpace { @@ -44,10 +44,11 @@ typedef struct ColorSpace { char name[64]; char description[64]; - struct ConstProcessorRcPtr *to_scene_linear; - struct ConstProcessorRcPtr *from_scene_linear; + struct OCIO_ConstProcessorRcPtr *to_scene_linear; + struct OCIO_ConstProcessorRcPtr *from_scene_linear; int is_invertible; + int is_data; } ColorSpace; typedef struct ColorManagedDisplay { @@ -56,8 +57,8 @@ typedef struct ColorManagedDisplay { char name[64]; ListBase views; - struct ConstProcessorRcPtr *to_scene_linear; - struct ConstProcessorRcPtr *from_scene_linear; + struct OCIO_ConstProcessorRcPtr *to_scene_linear; + struct OCIO_ConstProcessorRcPtr *from_scene_linear; } ColorManagedDisplay; typedef struct ColorManagedView { @@ -66,8 +67,14 @@ typedef struct ColorManagedView { char name[64]; } ColorManagedView; +/* ** Initialization / De-initialization ** */ + +void colormanagement_init(void); +void colormanagement_exit(void); + void colormanage_cache_free(struct ImBuf *ibuf); +const char *colormanage_display_get_default_name(void); struct ColorManagedDisplay *colormanage_display_get_default(void); struct ColorManagedDisplay *colormanage_display_add(const char *name); struct ColorManagedDisplay *colormanage_display_get_named(const char *name); @@ -79,7 +86,7 @@ struct ColorManagedView *colormanage_view_add(const char *name); struct ColorManagedView *colormanage_view_get_indexed(int index); struct ColorManagedView *colormanage_view_get_named(const char *name); -struct ColorSpace *colormanage_colorspace_add(const char *name, const char *description, int is_invertible); +struct ColorSpace *colormanage_colorspace_add(const char *name, const char *description, int is_invertible, int is_data); struct ColorSpace *colormanage_colorspace_get_named(const char *name); struct ColorSpace *colormanage_colorspace_get_roled(int role); struct ColorSpace *colormanage_colorspace_get_indexed(int index); diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h index 56a03121409..68ad4808c80 100644 --- a/source/blender/imbuf/intern/IMB_filetype.h +++ b/source/blender/imbuf/intern/IMB_filetype.h @@ -97,13 +97,13 @@ struct ImBuf *imb_cocoaLoadImage(unsigned char *mem, size_t size, int flags, cha short imb_cocoaSaveImage(struct ImBuf *ibuf, const char *name, int flags); /* cineon */ -int imb_savecineon(struct ImBuf *buf, const char *name, int flags); -struct ImBuf *imb_loadcineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); +int imb_save_cineon(struct ImBuf *buf, const char *name, int flags); +struct ImBuf *imb_load_cineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); int imb_is_cineon(unsigned char *buf); /* dpx */ int imb_save_dpx(struct ImBuf *buf, const char *name, int flags); -struct ImBuf *imb_loaddpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); +struct ImBuf *imb_load_dpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); int imb_is_dpx(unsigned char *buf); /* hdr */ diff --git a/source/blender/imbuf/intern/IMB_indexer.h b/source/blender/imbuf/intern/IMB_indexer.h index 18816924a9b..9c95531e90d 100644 --- a/source/blender/imbuf/intern/IMB_indexer.h +++ b/source/blender/imbuf/intern/IMB_indexer.h @@ -72,7 +72,7 @@ typedef struct anim_index_builder { char name[FILE_MAX]; char temp_name[FILE_MAX]; - void * private_data; + void *private_data; void (*delete_priv_data)(struct anim_index_builder * idx); void (*proc_frame)(struct anim_index_builder * idx, diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index 69048274104..1b3a6d4a4cd 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -357,7 +357,7 @@ ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar planes, unsigned int ibuf->planes = planes; ibuf->ftype = TGA; ibuf->channels = 4; /* float option, is set to other values when buffers get assigned */ - ibuf->ppm[0] = ibuf->ppm[1] = IMB_DPI_DEFAULT / 0.0254; /* IMB_DPI_DEFAULT -> pixels-per-meter */ + ibuf->ppm[0] = ibuf->ppm[1] = IMB_DPI_DEFAULT / 0.0254f; /* IMB_DPI_DEFAULT -> pixels-per-meter */ if (flags & IB_rect) { if (imb_addrectImBuf(ibuf) == FALSE) { diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index 394f5169046..5b64416c309 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -78,7 +78,9 @@ #include "imbuf.h" -#include "AVI_avi.h" +#ifdef WITH_AVI +# include "AVI_avi.h" +#endif #ifdef WITH_QUICKTIME #if defined(_WIN32) || defined(__APPLE__) @@ -185,6 +187,7 @@ static void an_stringenc(char *string, const char *head, const char *tail, unsig BLI_stringenc(string, head, tail, numlen, pic); } +#ifdef WITH_AVI static void free_anim_avi(struct anim *anim) { #if defined(_WIN32) && !defined(FREE_WINDOWS) @@ -219,6 +222,7 @@ static void free_anim_avi(struct anim *anim) anim->duration = 0; } +#endif /* WITH_AVI */ #ifdef WITH_FFMPEG static void free_anim_ffmpeg(struct anim *anim); @@ -235,7 +239,10 @@ void IMB_free_anim(struct anim *anim) } free_anim_movie(anim); + +#ifdef WITH_AVI free_anim_avi(anim); +#endif #ifdef WITH_QUICKTIME free_anim_quicktime(anim); @@ -287,7 +294,7 @@ struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex, char return(anim); } - +#ifdef WITH_AVI static int startavi(struct anim *anim) { @@ -397,7 +404,9 @@ static int startavi(struct anim *anim) return 0; } +#endif /* WITH_AVI */ +#ifdef WITH_AVI static ImBuf *avi_fetchibuf(struct anim *anim, int position) { ImBuf *ibuf = NULL; @@ -447,6 +456,7 @@ static ImBuf *avi_fetchibuf(struct anim *anim, int position) return ibuf; } +#endif /* WITH_AVI */ #ifdef WITH_FFMPEG @@ -1206,7 +1216,11 @@ static ImBuf *anim_getnew(struct anim *anim) if (anim == NULL) return(NULL); free_anim_movie(anim); + +#ifdef WITH_AVI free_anim_avi(anim); +#endif + #ifdef WITH_QUICKTIME free_anim_quicktime(anim); #endif @@ -1219,7 +1233,7 @@ static ImBuf *anim_getnew(struct anim *anim) if (anim->curtype != 0) return (NULL); - anim->curtype = imb_get_anim_type(anim->name); + anim->curtype = imb_get_anim_type(anim->name); switch (anim->curtype) { case ANIM_SEQUENCE: @@ -1233,6 +1247,7 @@ static ImBuf *anim_getnew(struct anim *anim) if (startmovie(anim)) return (NULL); ibuf = IMB_allocImBuf(anim->x, anim->y, 24, 0); /* fake */ break; +#ifdef WITH_AVI case ANIM_AVI: if (startavi(anim)) { printf("couldnt start avi\n"); @@ -1240,6 +1255,7 @@ static ImBuf *anim_getnew(struct anim *anim) } ibuf = IMB_allocImBuf(anim->x, anim->y, 24, 0); break; +#endif #ifdef WITH_QUICKTIME case ANIM_QTIME: if (startquicktime(anim)) return (0); @@ -1331,11 +1347,13 @@ struct ImBuf *IMB_anim_absolute(struct anim *anim, int position, IMB_convert_rgba_to_abgr(ibuf); } break; +#ifdef WITH_AVI case ANIM_AVI: ibuf = avi_fetchibuf(anim, position); if (ibuf) anim->curposition = position; break; +#endif #ifdef WITH_QUICKTIME case ANIM_QTIME: ibuf = qtime_fetchibuf(anim, position); diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c index df12f0b703e..32733668052 100644 --- a/source/blender/imbuf/intern/bmp.c +++ b/source/blender/imbuf/intern/bmp.c @@ -184,7 +184,7 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char co rect += 4; bmp += 3; } /* for 24-bit images, rows are padded to multiples of 4 */ - bmp += x % 4; + bmp += x % 4; } } else if (depth == 32) { diff --git a/source/blender/imbuf/intern/cineon/CMakeLists.txt b/source/blender/imbuf/intern/cineon/CMakeLists.txt index fdf4f5409a5..b94cfd22058 100644 --- a/source/blender/imbuf/intern/cineon/CMakeLists.txt +++ b/source/blender/imbuf/intern/cineon/CMakeLists.txt @@ -39,12 +39,24 @@ set(INC_SYS ) set(SRC + cin_debug_stuff.h + cineonfile.h + cineonlib.h + dpxfile.h + dpxlib.h + logImageCore.h + logImageLib.h + logmemfile.h + cineon_dpx.c cineonlib.c dpxlib.c logImageCore.c - logImageLib.c logmemfile.c ) +if(WITH_IMAGE_CINEON) + add_definitions(-DWITH_CINEON) +endif() + blender_add_lib(bf_imbuf_cineon "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/imbuf/intern/cineon/SConscript b/source/blender/imbuf/intern/cineon/SConscript index e1afb5ebd2d..a07334632d7 100644 --- a/source/blender/imbuf/intern/cineon/SConscript +++ b/source/blender/imbuf/intern/cineon/SConscript @@ -15,4 +15,7 @@ incs = ['.', defs = [] +if env['WITH_BF_CINEON']: + defs.append('WITH_CINEON') + env.BlenderLib ('bf_imbuf_cineon', source_files, incs, defs, libtype=['core','player'], priority = [220,175]) diff --git a/source/blender/imbuf/intern/cineon/cin_debug_stuff.h b/source/blender/imbuf/intern/cineon/cin_debug_stuff.h index a97499fb1ae..e69de29bb2d 100644 --- a/source/blender/imbuf/intern/cineon/cin_debug_stuff.h +++ b/source/blender/imbuf/intern/cineon/cin_debug_stuff.h @@ -1,4 +0,0 @@ -/** \file blender/imbuf/intern/cineon/cin_debug_stuff.h - * \ingroup imbcineon - */ -#define d_printf printf diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c index 7705af13b1e..d20c6dec9d3 100644 --- a/source/blender/imbuf/intern/cineon/cineon_dpx.c +++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c @@ -4,11 +4,11 @@ * 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. + * 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 + * 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 @@ -20,25 +20,24 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Julien Enche. * * ***** END GPL LICENSE BLOCK ***** * cineon.c - * contributors: joeedh + * contributors: joeedh, Julien Enche * I hearby donate this code and all rights to the Blender Foundation. + * $Id$ */ /** \file blender/imbuf/intern/cineon/cineon_dpx.c * \ingroup imbcineon */ - -#include -#include /*for memcpy*/ -#include "logImageLib.h" -#include "cineonlib.h" -#include "dpxlib.h" +#include +#include +#include +#include "logImageCore.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -51,167 +50,142 @@ #include "MEM_guardedalloc.h" -#if 0 -static void cineon_conversion_parameters(LogImageByteConversionParameters *params) -{ -// params->blackPoint = scene?scene->r.cineonblack:95; -// params->whitePoint = scene?scene->r.cineonwhite:685; -// params->gamma = scene?scene->r.cineongamma:1.7f; -// params->doLogarithm = scene?scene->r.subimtype & R_CINEON_LOG:0; - - params->blackPoint = 95; - params->whitePoint = 685; - params->gamma = 1.0f; - params->doLogarithm = 0; -} -#endif - -static ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int size, int flags, char colorspace[IM_MAX_SPACE]) +static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, size_t size, int use_cineon, int flags, + char colorspace[IM_MAX_SPACE]) { ImBuf *ibuf; LogImageFile *image; - int x, y; - unsigned short *row, *upix; int width, height, depth; - float *frow; colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT); - logImageSetVerbose((G.debug & G_DEBUG) ? 1:0); - - image = logImageOpenFromMem(mem, size, use_cineon); - - if (!image) { - printf("no image!\n"); - return NULL; + logImageSetVerbose((G.f & G_DEBUG) ? 1 : 0); + + image = logImageOpenFromMemory(mem, size); + + if (image == 0) { + printf("DPX/Cineon: error opening image.\n"); + return 0; } - + logImageGetSize(image, &width, &height, &depth); - - if (depth != 3) { /*need to do grayscale loading eventually.*/ + + if (width == 0 || height == 0) { logImageClose(image); - return NULL; + return 0; } - - if (width == 0 && height == 0) { - logImageClose(image); - return NULL; - } - + ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags); - - row = MEM_mallocN(sizeof(unsigned short)*width*depth, "row in cineon_dpx.c"); - frow = ibuf->rect_float+width*height*4; - - for (y = 0; y < height; y++) { - logImageGetRowBytes(image, row, y); /* checks image->params.doLogarithm and convert */ - upix = row; - frow -= width*4; - - for (x=0; xrect_float, 1) != 0) { + /* Conversion not possible (probably because the format is unsupported) */ + logImageClose(image); + MEM_freeN(ibuf); + return 0; } - MEM_freeN(row); logImageClose(image); - - if (flags & IB_rect) { + ibuf->ftype = use_cineon ? CINEON : DPX; + IMB_flipy(ibuf); + + if (flags & IB_rect) IMB_rect_from_float(ibuf); - } + return ibuf; } static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon, int flags) { - LogImageByteConversionParameters conversion; - const int width= ibuf->x; - const int height= ibuf->y; - const int depth= 3; - LogImageFile* logImage; - unsigned short* line, *pixel; - int i, j; - float *fline; + LogImageFile *logImage; float *fbuf; - int is_alloc= 0; - - (void)flags; /* unused */ + float *fbuf_ptr; + unsigned char *rect_ptr; + int x, y, depth, bitspersample, rvalue; - // cineon_conversion_parameters(&conversion); - logImageGetByteConversionDefaults(&conversion); - - /* - * Get the drawable for the current image... - */ - - fbuf= IMB_float_profile_ensure(ibuf, conversion.doLogarithm ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_NONE, &is_alloc); - - if (fbuf == NULL) { /* in the unlikely event that converting to a float buffer fails */ + if (flags & IB_mem) { + printf("DPX/Cineon: saving in memory is not supported.\n"); return 0; } - logImageSetVerbose((G.debug & G_DEBUG) ? 1:0); - logImage = logImageCreate(filename, use_cineon, width, height, depth); + logImageSetVerbose((G.f & G_DEBUG) ? 1 : 0); - if (!logImage) return 0; - - if (logImageSetByteConversion(logImage, &conversion)==0) { - printf("error setting args\n"); + depth = (ibuf->planes + 7) >> 3; + if (depth > 4 || depth < 3) { + printf("DPX/Cineon: unsupported depth: %d for file: '%s'\n", depth, filename); + return 0; } - line = MEM_mallocN(sizeof(unsigned short)*depth*width, "line"); - - /*note that image is flipped when sent to logImageSetRowBytes (see last passed parameter).*/ - for (j = 0; j < height; ++j) { - fline = &fbuf[width*j*4]; - for (i=0; i=1.0f) fpix2[0] = 1.0f; else if (fpix2[0]<0.0f) fpix2[0]= 0.0f; - if (fpix2[1]>=1.0f) fpix2[1] = 1.0f; else if (fpix2[1]<0.0f) fpix2[1]= 0.0f; - if (fpix2[2]>=1.0f) fpix2[2] = 1.0f; else if (fpix2[2]<0.0f) fpix2[2]= 0.0f; - - pixel[0] = (unsigned short)(fpix2[0] * 65535.0f); /*float-float math is faster*/ - pixel[1] = (unsigned short)(fpix2[1] * 65535.0f); - pixel[2] = (unsigned short)(fpix2[2] * 65535.0f); + if (ibuf->ftype & CINEON_10BIT) + bitspersample = 10; + else if (ibuf->ftype & CINEON_12BIT) + bitspersample = 12; + else if (ibuf->ftype & CINEON_16BIT) + bitspersample = 16; + else + bitspersample = 8; + + logImage = logImageCreate(filename, use_cineon, ibuf->x, ibuf->y, bitspersample, (depth == 4), + (ibuf->ftype & CINEON_LOG), -1, -1, -1, "Blender"); + + if (logImage == 0) { + printf("DPX/Cineon: error creating file.\n"); + return 0; + } + + if (ibuf->rect_float != 0 && bitspersample != 8) { + /* don't use the float buffer to save 8 bpp picture to prevent color banding + (there's no dithering algorithm behing the logImageSetDataRGBA function) */ + IMB_flipy(ibuf); + rvalue = (logImageSetDataRGBA(logImage, ibuf->rect_float, 1) == 0); + IMB_flipy(ibuf); + } + else { + if (ibuf->rect == 0) + IMB_rect_from_float(ibuf); + + fbuf = (float *)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), "fbuf in imb_save_dpx_cineon"); + if (fbuf == 0) { + printf("DPX/Cineon: error allocating memory.\n"); + logImageClose(logImage); + return 0; } - logImageSetRowBytes(logImage, (const unsigned short*)line, height-1-j); - } - logImageClose(logImage); - - MEM_freeN(line); - - if (is_alloc) { + for (y = 0; y < ibuf->y; y++) { + for (x = 0; x < ibuf->x; x++) { + fbuf_ptr = fbuf + 4 * ((ibuf->y - y - 1) * ibuf->x + x); + rect_ptr = (unsigned char *)ibuf->rect + 4 * (y * ibuf->x + x); + fbuf_ptr[0] = (float)rect_ptr[0] / 255.0f; + fbuf_ptr[1] = (float)rect_ptr[1] / 255.0f; + fbuf_ptr[2] = (float)rect_ptr[2] / 255.0f; + fbuf_ptr[3] = (depth == 4) ? ((float)rect_ptr[3] / 255.0f) : 1.0f; + } + } + rvalue = (logImageSetDataRGBA(logImage, fbuf, 0) == 0); MEM_freeN(fbuf); } - - return 1; + + logImageClose(logImage); + return rvalue; } -int imb_savecineon(struct ImBuf *buf, const char *myfile, int flags) +int imb_save_cineon(struct ImBuf *buf, const char *myfile, int flags) { return imb_save_dpx_cineon(buf, myfile, 1, flags); } - int imb_is_cineon(unsigned char *buf) { - return cineonIsMemFileCineon(buf); + return logImageIsCineon(buf); } -ImBuf *imb_loadcineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) +ImBuf *imb_load_cineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { if (imb_is_cineon(mem)) - return imb_load_dpx_cineon(mem, 1, size, flags, colorspace); - return NULL; + return imb_load_dpx_cineon(mem, size, 1, flags, colorspace); + return 0; } int imb_save_dpx(struct ImBuf *buf, const char *myfile, int flags) @@ -221,12 +195,12 @@ int imb_save_dpx(struct ImBuf *buf, const char *myfile, int flags) int imb_is_dpx(unsigned char *buf) { - return dpxIsMemFileCineon(buf); + return logImageIsDpx(buf); } -ImBuf *imb_loaddpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) +ImBuf *imb_load_dpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { if (imb_is_dpx(mem)) - return imb_load_dpx_cineon(mem, 0, size, flags, colorspace); - return NULL; + return imb_load_dpx_cineon(mem, size, 0, flags, colorspace); + return 0; } diff --git a/source/blender/imbuf/intern/cineon/cineonfile.h b/source/blender/imbuf/intern/cineon/cineonfile.h index e681153aa6e..e69de29bb2d 100644 --- a/source/blender/imbuf/intern/cineon/cineonfile.h +++ b/source/blender/imbuf/intern/cineon/cineonfile.h @@ -1,134 +0,0 @@ -/* - * Cineon image file format library definitions. - * Cineon file format structures. - * - * This header file contains private details. - * User code should generally use cineonlib.h only. - * - * Copyright 1999,2000,2001 David Hodson - * - * 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 __CINEONFILE_H__ -#define __CINEONFILE_H__ - -/** \file blender/imbuf/intern/cineon/cineonfile.h - * \ingroup imbcineon - */ - -#include "logImageCore.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - U32 magic_num; /* magic number */ - U32 image_offset; /* offset to image data in bytes */ - U32 gen_hdr_size; /* generic header length in bytes */ - U32 ind_hdr_size; /* industry header length in bytes */ - U32 user_data_size; /* user-defined data length in bytes */ - U32 file_size; /* file size in bytes */ - ASCII vers[8]; /* which header format version is being used (v4.5) */ - ASCII file_name[100]; /* image file name */ - ASCII create_date[12]; /* file creation date */ - ASCII create_time[12]; /* file creation time */ - ASCII Reserved[36]; /* reserved field TBD (need to pad) */ -} CineonFileInformation; - -typedef struct { - U8 designator1; - U8 designator2; - U8 bits_per_pixel; - U8 filler; - U32 pixels_per_line; - U32 lines_per_image; - U32 ref_low_data; /* reference low data code value */ - R32 ref_low_quantity; /* reference low quantity represented */ - U32 ref_high_data; /* reference high data code value */ - R32 ref_high_quantity;/* reference high quantity represented */ -} CineonChannelInformation; - -typedef struct { - U8 orientation; /* image orientation */ - U8 channels_per_image; - U16 filler; - CineonChannelInformation channel[8]; - R32 white_point_x; - R32 white_point_y; - R32 red_primary_x; - R32 red_primary_y; - R32 green_primary_x; - R32 green_primary_y; - R32 blue_primary_x; - R32 blue_primary_y; - ASCII label[200]; - ASCII reserved[28]; -} CineonImageInformation; - -typedef struct { - U8 interleave; - U8 packing; - U8 signage; - U8 sense; - U32 line_padding; - U32 channel_padding; - ASCII reserved[20]; -} CineonFormatInformation; - -typedef struct { - S32 x_offset; - S32 y_offset; - ASCII file_name[100]; - ASCII create_date[12]; /* file creation date */ - ASCII create_time[12]; /* file creation time */ - ASCII input_device[64]; - ASCII model_number[32]; - ASCII serial_number[32]; - R32 x_input_samples_per_mm; - R32 y_input_samples_per_mm; - R32 input_device_gamma; - ASCII reserved[40]; -} CineonOriginationInformation; - -typedef struct { - CineonFileInformation fileInfo; - CineonImageInformation imageInfo; - CineonFormatInformation formatInfo; - CineonOriginationInformation originInfo; -} CineonGenericHeader; - -typedef struct { - U8 filmCode; - U8 filmType; - U8 perfOffset; - U8 filler; - U32 keycodePrefix; - U32 keycodeCount; - ASCII format[32]; - U32 framePosition; /* in sequence */ - R32 frameRate; /* frames per second */ - ASCII attribute[32]; - ASCII slate[200]; - ASCII reserved[740]; -} CineonMPISpecificInformation; - -#ifdef __cplusplus -} -#endif - -#endif /* __CINEONFILE_H__ */ diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c index a9001303679..9926d8c8562 100644 --- a/source/blender/imbuf/intern/cineon/cineonlib.c +++ b/source/blender/imbuf/intern/cineon/cineonlib.c @@ -1,21 +1,23 @@ /* - * Cineon image file format library routines. + * Cineon image file format library routines. * - * Copyright 1999,2000,2001 David Hodson + * Copyright 1999,2000,2001 David Hodson * - * 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 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. + * 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. + * 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. + * + * Contributor(s): Julien Enche. * */ @@ -23,800 +25,355 @@ * \ingroup imbcineon */ + #include "cineonlib.h" -#include "cineonfile.h" +#include "logmemfile.h" #include #include #include -#include /* strftime() */ +#include #include -#ifdef WIN32 -#include -#else -#include /* htonl() */ -#endif -#include /* memset */ +#include -#include "BLI_utildefines.h" #include "BLI_fileops.h" +#include "BLI_math_base.h" +#include "BLI_utildefines.h" -#include "cin_debug_stuff.h" -#include "logmemfile.h" +#include "logImageLib.h" -static void -fillCineonFileInfo(CineonFile* cineon, CineonFileInformation* fileInfo, const char* filename) { +#include "MEM_guardedalloc.h" - time_t fileClock; - struct tm* fileTime; - - fileInfo->magic_num = htonl(CINEON_FILE_MAGIC); - fileInfo->image_offset = htonl(cineon->imageOffset); - fileInfo->gen_hdr_size = htonl( - sizeof(CineonFileInformation) + - sizeof(CineonImageInformation) + - sizeof(CineonFormatInformation) + - sizeof(CineonOriginationInformation)); - fileInfo->ind_hdr_size = 0; - fileInfo->user_data_size = 0; - fileInfo->file_size = htonl(cineon->imageOffset + cineon->height * cineon->lineBufferLength); - strcpy(fileInfo->vers, "V4.5"); - strncpy(fileInfo->file_name, filename, 99); - fileInfo->file_name[99] = 0; - - fileClock = time(0); - fileTime = localtime(&fileClock); - strftime(fileInfo->create_date, 12, "%Y:%m:%d", fileTime); - /* Question: is %Z in strftime guaranteed to return 3 chars? */ - strftime(fileInfo->create_time, 12, "%H:%M:%S%Z", fileTime); - fileInfo->create_time[11] = 0; -} - -static void -dumpCineonFileInfo(CineonFileInformation* fileInfo) { - d_printf("\n--File Information--\n"); - d_printf("Magic: %8.8lX\n", (uintptr_t)ntohl(fileInfo->magic_num)); - d_printf("Image Offset %ld\n", (intptr_t)ntohl(fileInfo->image_offset)); - d_printf("Generic Header size %ld\n", (intptr_t)ntohl(fileInfo->gen_hdr_size)); - d_printf("Industry Header size %ld\n", (intptr_t)ntohl(fileInfo->ind_hdr_size)); - d_printf("User Data size %ld\n", (intptr_t)ntohl(fileInfo->user_data_size)); - d_printf("File size %ld\n", (intptr_t)ntohl(fileInfo->file_size)); - d_printf("Version \"%s\"\n", fileInfo->vers); - d_printf("File name \"%s\"\n", fileInfo->file_name); - d_printf("Creation date \"%s\"\n", fileInfo->create_date); - d_printf("Creation time \"%s\"\n", fileInfo->create_time); -} - -static void -fillCineonChannelInfo(CineonFile* cineon, CineonChannelInformation* chan, int des) { - - chan->designator1 = 0; - chan->designator2 = des; - chan->bits_per_pixel = 10; - chan->pixels_per_line = htonl(cineon->width); - chan->lines_per_image = htonl(cineon->height); - chan->ref_low_data = htonl(0); - chan->ref_low_quantity = htonf(0.0); - chan->ref_high_data = htonl(1023); - chan->ref_high_quantity = htonf(2.046); -} - -static void -dumpCineonChannelInfo(CineonChannelInformation* chan) { - d_printf(" Metric selector: %d", chan->designator1); - switch (chan->designator1) { - case 0: d_printf(" (Universal)\n"); break; - default: d_printf(" (Vendor specific)\n"); break; - } - d_printf(" Metric: %d,", chan->designator2); - switch (chan->designator2) { - case 0: d_printf(" B&W (printing density?)\n"); break; - case 1: d_printf(" Red printing density\n"); break; - case 2: d_printf(" Green printing density\n"); break; - case 3: d_printf(" Blue printing density\n"); break; - case 4: d_printf(" Red CCIR XA/11\n"); break; - case 5: d_printf(" Green CCIR XA/11\n"); break; - case 6: d_printf(" Blue CCIR XA/11\n"); break; - default: d_printf(" (unknown)\n"); break; - } - d_printf(" Bits per pixel %d\n", chan->bits_per_pixel); - d_printf(" Pixels per line %ld\n", (intptr_t)ntohl(chan->pixels_per_line)); - d_printf(" Lines per image %ld\n", (intptr_t)ntohl(chan->lines_per_image)); - d_printf(" Ref low data %ld\n", (intptr_t)ntohl(chan->ref_low_data)); - d_printf(" Ref low quantity %f\n", ntohf(chan->ref_low_quantity)); - d_printf(" Ref high data %ld\n", (intptr_t)ntohl(chan->ref_high_data)); - d_printf(" Ref high quantity %f\n", ntohf(chan->ref_high_quantity)); -} - -static void -fillCineonImageInfo(CineonFile* cineon, CineonImageInformation* imageInfo) { - - imageInfo->orientation = 0; - imageInfo->channels_per_image = cineon->depth; - - if (cineon->depth == 1) { - fillCineonChannelInfo(cineon, &imageInfo->channel[0], 0); - - } - else if (cineon->depth == 3) { - fillCineonChannelInfo(cineon, &imageInfo->channel[0], 1); - fillCineonChannelInfo(cineon, &imageInfo->channel[1], 2); - fillCineonChannelInfo(cineon, &imageInfo->channel[2], 3); - } - - imageInfo->white_point_x = htonf(undefined()); - imageInfo->white_point_y = htonf(undefined()); - imageInfo->red_primary_x = htonf(undefined()); - imageInfo->red_primary_y = htonf(undefined()); - imageInfo->green_primary_x = htonf(undefined()); - imageInfo->green_primary_y = htonf(undefined()); - imageInfo->blue_primary_x = htonf(undefined()); - imageInfo->blue_primary_y = htonf(undefined()); - - strcpy(imageInfo->label, "David's Cineon writer."); - -} - -static void -dumpCineonImageInfo(CineonImageInformation* imageInfo) { - - int i; - d_printf("\n--Image Information--\n"); - d_printf("Image orientation %d,", imageInfo->orientation); - switch (imageInfo->orientation) { - case 0: d_printf(" LRTB\n"); break; - case 1: d_printf(" LRBT\n"); break; - case 2: d_printf(" RLTB\n"); break; - case 3: d_printf(" RLBT\n"); break; - case 4: d_printf(" TBLR\n"); break; - case 5: d_printf(" TBRL\n"); break; - case 6: d_printf(" BTLR\n"); break; - case 7: d_printf(" BTRL\n"); break; - default: d_printf(" (unknown)\n"); break; - } - d_printf("Channels %d\n", imageInfo->channels_per_image); - for (i = 0; i < imageInfo->channels_per_image; ++i) { - d_printf(" --Channel %d--\n", i); - dumpCineonChannelInfo(&imageInfo->channel[i]); - } - - d_printf("White point x %f\n", ntohf(imageInfo->white_point_x)); - d_printf("White point y %f\n", ntohf(imageInfo->white_point_y)); - d_printf("Red primary x %f\n", ntohf(imageInfo->red_primary_x)); - d_printf("Red primary y %f\n", ntohf(imageInfo->red_primary_y)); - d_printf("Green primary x %f\n", ntohf(imageInfo->green_primary_x)); - d_printf("Green primary y %f\n", ntohf(imageInfo->green_primary_y)); - d_printf("Blue primary x %f\n", ntohf(imageInfo->blue_primary_x)); - d_printf("Blue primary y %f\n", ntohf(imageInfo->blue_primary_y)); - d_printf("Label \"%s\"\n", imageInfo->label); -} - -static void -fillCineonFormatInfo(CineonFile* cineon, CineonFormatInformation* formatInfo) { - - (void)cineon; /* unused */ - - formatInfo->interleave = 0; - formatInfo->packing = 5; - formatInfo->signage = 0; - formatInfo->sense = 0; - formatInfo->line_padding = htonl(0); - formatInfo->channel_padding = htonl(0); -} - -static void -dumpCineonFormatInfo(CineonFormatInformation* formatInfo) { - d_printf("\n--Format Information--\n"); - d_printf("Interleave %d,", formatInfo->interleave); - switch (formatInfo->interleave) { - case 0: d_printf(" pixel interleave\n"); break; - case 1: d_printf(" line interleave\n"); break; - case 2: d_printf(" channel interleave\n"); break; - default: d_printf(" (unknown)\n"); break; - } - d_printf("Packing %d,", formatInfo->packing); - if (formatInfo->packing & 0x80) { - d_printf(" multi pixel,"); - } - else { - d_printf(" single pixel,"); - } - switch (formatInfo->packing & 0x7F) { - case 0: d_printf(" tight\n"); break; - case 1: d_printf(" byte packed left\n"); break; - case 2: d_printf(" byte packed right\n"); break; - case 3: d_printf(" word packed left\n"); break; - case 4: d_printf(" word packed right\n"); break; - case 5: d_printf(" long packed left\n"); break; - case 6: d_printf(" long packed right\n"); break; - default: d_printf(" (unknown)\n"); break; - } - d_printf("Sign %d,", formatInfo->signage); - if (formatInfo->signage) { - d_printf(" signed\n"); - } - else { - d_printf(" unsigned\n"); - } - d_printf("Sense %d,", formatInfo->signage); - if (formatInfo->signage) { - d_printf(" negative\n"); - } - else { - d_printf(" positive\n"); - } - d_printf("End of line padding %ld\n", (intptr_t)ntohl(formatInfo->line_padding)); - d_printf("End of channel padding %ld\n", (intptr_t)ntohl(formatInfo->channel_padding)); -} - -static void -fillCineonOriginationInfo(CineonFile* cineon, - CineonOriginationInformation* originInfo, CineonFileInformation* fileInfo) { - - (void)cineon; /* unused */ - - originInfo->x_offset = htonl(0); - originInfo->y_offset = htonl(0); - strcpy(originInfo->file_name, fileInfo->file_name); - strcpy(originInfo->create_date, fileInfo->create_date); - strcpy(originInfo->create_time, fileInfo->create_time); - strncpy(originInfo->input_device, "David's Cineon writer", 64); - strncpy(originInfo->model_number, "Software", 32); - strncpy(originInfo->serial_number, "001", 32); - originInfo->x_input_samples_per_mm = htonf(undefined()); - originInfo->y_input_samples_per_mm = htonf(undefined()); - /* this should probably be undefined, too */ - originInfo->input_device_gamma = htonf(1.0); -} - -static void -dumpCineonOriginationInfo(CineonOriginationInformation* originInfo) { - d_printf("\n--Origination Information--\n"); - d_printf("X offset %ld\n", (intptr_t)ntohl(originInfo->x_offset)); - d_printf("Y offset %ld\n", (intptr_t)ntohl(originInfo->y_offset)); - d_printf("File name \"%s\"\n", originInfo->file_name); - d_printf("Creation date \"%s\"\n", originInfo->create_date); - d_printf("Creation time \"%s\"\n", originInfo->create_time); - d_printf("Input device \"%s\"\n", originInfo->input_device); - d_printf("Model number \"%s\"\n", originInfo->model_number); - d_printf("Serial number \"%s\"\n", originInfo->serial_number); - d_printf("Samples per mm in x %f\n", ntohf(originInfo->x_input_samples_per_mm)); - d_printf("Samples per mm in y %f\n", ntohf(originInfo->y_input_samples_per_mm)); - d_printf("Input device gamma %f\n", ntohf(originInfo->input_device_gamma)); -} - -static int -initCineonGenericHeader(CineonFile* cineon, CineonGenericHeader* header, const char* imagename) { - - fillCineonFileInfo(cineon, &header->fileInfo, imagename); - fillCineonImageInfo(cineon, &header->imageInfo); - fillCineonFormatInfo(cineon, &header->formatInfo); - fillCineonOriginationInfo(cineon, &header->originInfo, &header->fileInfo); - - return 0; -} - -static void -UNUSED_FUNCTION(dumpCineonGenericHeader)(CineonGenericHeader* header) { - dumpCineonFileInfo(&header->fileInfo); - dumpCineonImageInfo(&header->imageInfo); - dumpCineonFormatInfo(&header->formatInfo); - dumpCineonOriginationInfo(&header->originInfo); -} +/* + * For debug purpose + */ static int verbose = 0; -void -cineonSetVerbose(int verbosity) { + +void cineonSetVerbose(int verbosity) { verbose = verbosity; } -static void -verboseMe(CineonFile* cineon) { - - d_printf("size %d x %d x %d\n", cineon->width, cineon->height, cineon->depth); - d_printf("ImageStart %d, lineBufferLength %d, implied length %d\n", - cineon->imageOffset, cineon->lineBufferLength * 4, - cineon->imageOffset + cineon->lineBufferLength * 4 * cineon->height); -} - -int -cineonGetRowBytes(CineonFile* cineon, unsigned short* row, int y) { - - int longsRead; - int pixelIndex; - int longIndex; - int numPixels = cineon->width * cineon->depth; - - - /* only seek if not reading consecutive lines */ - if (y != cineon->fileYPos) { - int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4; - if (verbose) d_printf("Seek in getRowBytes\n"); - if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) { - if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset); - return 1; - } - cineon->fileYPos = y; - } - - longsRead = logimage_fread(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon); - if (longsRead != cineon->lineBufferLength) { - if (verbose) { - d_printf("Couldn't read line %d length %d\n", y, cineon->lineBufferLength * 4); - perror("cineonGetRowBytes"); - } - - return 1; - } - - /* remember where we left the car, honey */ - ++cineon->fileYPos; - - /* convert longwords to pixels */ - pixelIndex = 0; - for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) { - unsigned int t = ntohl(cineon->lineBuffer[longIndex]); - t = t >> 2; - cineon->pixelBuffer[pixelIndex+2] = (unsigned short) t & 0x3ff; - t = t >> 10; - cineon->pixelBuffer[pixelIndex+1] = (unsigned short) t & 0x3ff; - t = t >> 10; - cineon->pixelBuffer[pixelIndex] = (unsigned short) t & 0x3ff; - pixelIndex += 3; - } - - /* extract required pixels */ - for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) { - if (cineon->params.doLogarithm) - row[pixelIndex] = cineon->lut10_16[cineon->pixelBuffer[pixelIndex]]; - else - row[pixelIndex] = cineon->pixelBuffer[pixelIndex] << 6; - } - - return 0; -} - -int -cineonSetRowBytes(CineonFile* cineon, const unsigned short* row, int y) { - - int pixelIndex; - int numPixels = cineon->width * cineon->depth; - int longIndex; - int longsWritten; - - /* put new pixels into pixelBuffer */ - for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) { - if (cineon->params.doLogarithm) - cineon->pixelBuffer[pixelIndex] = cineon->lut16_16[row[pixelIndex]]; - else - cineon->pixelBuffer[pixelIndex] = row[pixelIndex] >> 6; - } - - /* pack into longwords */ - pixelIndex = 0; - for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) { - unsigned int t = - (cineon->pixelBuffer[pixelIndex] << 22) | - (cineon->pixelBuffer[pixelIndex+1] << 12) | - (cineon->pixelBuffer[pixelIndex+2] << 2); - cineon->lineBuffer[longIndex] = htonl(t); - pixelIndex += 3; - } - - /* only seek if not reading consecutive lines */ - if (y != cineon->fileYPos) { - int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4; - if (verbose) d_printf("Seek in setRowBytes\n"); - if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) { - if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset); - return 1; - } - cineon->fileYPos = y; - } - - longsWritten = fwrite(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon->file); - if (longsWritten != cineon->lineBufferLength) { - if (verbose) d_printf("Couldn't write line %d length %d\n", y, cineon->lineBufferLength * 4); - return 1; - } - - ++cineon->fileYPos; - - return 0; -} - -int -cineonGetRow(CineonFile* cineon, unsigned short* row, int y) { - - int longsRead; - int pixelIndex; - int longIndex; -/* int numPixels = cineon->width * cineon->depth; -*/ - /* only seek if not reading consecutive lines */ - if (y != cineon->fileYPos) { - int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4; - if (verbose) d_printf("Seek in getRow\n"); - if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) { - if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset); - return 1; - } - cineon->fileYPos = y; - } - - longsRead = logimage_fread(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon); - if (longsRead != cineon->lineBufferLength) { - if (verbose) d_printf("Couldn't read line %d length %d\n", y, cineon->lineBufferLength * 4); - return 1; - } - - /* remember where we left the car, honey */ - ++cineon->fileYPos; - - /* convert longwords to pixels */ - pixelIndex = 0; - for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) { - unsigned int t = ntohl(cineon->lineBuffer[longIndex]); - t = t >> 2; - row[pixelIndex+2] = (unsigned short) t & 0x3ff; - t = t >> 10; - row[pixelIndex+1] = (unsigned short) t & 0x3ff; - t = t >> 10; - row[pixelIndex] = (unsigned short) t & 0x3ff; - pixelIndex += 3; - } - - return 0; -} - -int -cineonSetRow(CineonFile* cineon, const unsigned short* row, int y) { - - int pixelIndex; -/* int numPixels = cineon->width * cineon->depth; -*/ int longIndex; - int longsWritten; - - /* pack into longwords */ - pixelIndex = 0; - for (longIndex = 0; longIndex < cineon->lineBufferLength; ++longIndex) { - unsigned int t = - (row[pixelIndex] << 22) | - (row[pixelIndex+1] << 12) | - (row[pixelIndex+2] << 2); - cineon->lineBuffer[longIndex] = htonl(t); - pixelIndex += 3; - } - - /* only seek if not reading consecutive lines */ - if (y != cineon->fileYPos) { - int lineOffset = cineon->imageOffset + y * cineon->lineBufferLength * 4; - if (verbose) d_printf("Seek in setRowBytes\n"); - if (logimage_fseek(cineon, lineOffset, SEEK_SET) != 0) { - if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, lineOffset); - return 1; - } - cineon->fileYPos = y; - } - - longsWritten = fwrite(cineon->lineBuffer, 4, cineon->lineBufferLength, cineon->file); - if (longsWritten != cineon->lineBufferLength) { - if (verbose) d_printf("Couldn't write line %d length %d\n", y, cineon->lineBufferLength * 4); - return 1; - } - - ++cineon->fileYPos; - - return 0; -} - -CineonFile* -cineonOpen(const char* filename) { - - CineonGenericHeader header; - - CineonFile* cineon = (CineonFile* )malloc(sizeof(CineonFile)); - if (cineon == 0) { - if (verbose) d_printf("Failed to malloc cineon file structure.\n"); - return 0; - } - - /* for close routine */ - cineon->file = 0; - cineon->lineBuffer = 0; - cineon->pixelBuffer = 0; - cineon->membuffer = 0; - cineon->memcursor = 0; - cineon->membuffersize = 0; - - cineon->file = BLI_fopen(filename, "rb"); - if (cineon->file == 0) { - if (verbose) d_printf("Failed to open file \"%s\".\n", filename); - cineonClose(cineon); - return 0; - } - cineon->reading = 1; - - if (logimage_fread(&header, sizeof(CineonGenericHeader), 1, cineon) == 0) { - if (verbose) d_printf("Not enough data for header in \"%s\".\n", filename); - cineonClose(cineon); - return 0; - } - - /* let's assume cineon files are always network order */ - if (header.fileInfo.magic_num != ntohl(CINEON_FILE_MAGIC)) { - if (verbose) d_printf("Bad magic number %8.8lX in \"%s\".\n", - (uintptr_t)ntohl(header.fileInfo.magic_num), filename); - cineonClose(cineon); - return 0; - } - - if (header.formatInfo.packing != 5) { - if (verbose) d_printf("Can't understand packing %d\n", header.formatInfo.packing); - cineonClose(cineon); - return 0; - } - - cineon->width = ntohl(header.imageInfo.channel[0].pixels_per_line); - cineon->height = ntohl(header.imageInfo.channel[0].lines_per_image); - cineon->depth = header.imageInfo.channels_per_image; - /* cineon->bitsPerPixel = 10; */ - cineon->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel; - cineon->imageOffset = ntohl(header.fileInfo.image_offset); - - cineon->lineBufferLength = pixelsToLongs(cineon->width * cineon->depth); - cineon->lineBuffer = malloc(cineon->lineBufferLength * 4); - if (cineon->lineBuffer == 0) { - if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", cineon->lineBufferLength * 4); - cineonClose(cineon); - return 0; - } - - cineon->pixelBuffer = malloc(cineon->lineBufferLength * 3 * sizeof(unsigned short)); - if (cineon->pixelBuffer == 0) { - if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n", - (cineon->width * cineon->depth) * (int)sizeof(unsigned short)); - cineonClose(cineon); - return 0; - } - cineon->pixelBufferUsed = 0; - - if (logimage_fseek(cineon, cineon->imageOffset, SEEK_SET) != 0) { - if (verbose) d_printf("Couldn't seek to image data at %d\n", cineon->imageOffset); - cineonClose(cineon); - return 0; - } - cineon->fileYPos = 0; - - logImageGetByteConversionDefaults(&cineon->params); - setupLut(cineon); - - cineon->getRow = &cineonGetRowBytes; - cineon->setRow = 0; - cineon->close = &cineonClose; - - if (verbose) { - verboseMe(cineon); - } - - return cineon; -} - -int cineonIsMemFileCineon(unsigned char *mem) +static void fillCineonMainHeader(LogImageFile *cineon, CineonMainHeader *header, + const char *filename, const char *creator) { - unsigned int num; - memcpy(&num, mem, sizeof(unsigned int)); - - if (num != ntohl(CINEON_FILE_MAGIC)) { - return 0; + time_t fileClock; + struct tm *fileTime; + int i; + + memset(header, 0, sizeof(CineonMainHeader)); + + /* --- File header --- */ + header->fileHeader.magic_num = swap_uint(CINEON_FILE_MAGIC, cineon->isMSB); + header->fileHeader.offset = swap_uint(cineon->element[0].dataOffset, cineon->isMSB); + header->fileHeader.gen_hdr_size = swap_uint(sizeof(CineonFileHeader) + sizeof(CineonImageHeader) + + sizeof(CineonOriginationHeader), cineon->isMSB); + header->fileHeader.ind_hdr_size = 0; + header->fileHeader.user_data_size = 0; + header->fileHeader.file_size = swap_uint(cineon->element[0].dataOffset + cineon->height * getRowLength(cineon->width, cineon->element[0]), cineon->isMSB); + strcpy(header->fileHeader.version, "v4.5"); + strncpy(header->fileHeader.file_name, filename, 99); + header->fileHeader.file_name[99] = 0; + fileClock = time(0); + fileTime = localtime(&fileClock); + strftime(header->fileHeader.creation_date, 12, "%Y:%m:%d", fileTime); + strftime(header->fileHeader.creation_time, 12, "%H:%M:%S%Z", fileTime); + header->fileHeader.creation_time[11] = 0; + + /* --- Image header --- */ + header->imageHeader.orientation = 0; + header->imageHeader.elements_per_image = cineon->depth; + + for (i = 0; i < 3; i++) { + header->imageHeader.element[i].descriptor1 = 0; + header->imageHeader.element[i].descriptor2 = i; + header->imageHeader.element[i].bits_per_sample = cineon->element[0].bitsPerSample; + header->imageHeader.element[i].pixels_per_line = swap_uint(cineon->width, cineon->isMSB); + header->imageHeader.element[i].lines_per_image = swap_uint(cineon->height, cineon->isMSB); + header->imageHeader.element[i].ref_low_data = swap_uint(cineon->element[0].refLowData, cineon->isMSB); + header->imageHeader.element[i].ref_low_quantity = swap_float(cineon->element[0].refLowQuantity, cineon->isMSB); + header->imageHeader.element[i].ref_high_data = swap_uint(cineon->element[0].refHighData, cineon->isMSB); + header->imageHeader.element[i].ref_high_quantity = swap_float(cineon->element[0].refHighQuantity, cineon->isMSB); } - else return 1; + + header->imageHeader.white_point_x = swap_float(0.0f, cineon->isMSB); + header->imageHeader.white_point_y = swap_float(0.0f, cineon->isMSB); + header->imageHeader.red_primary_x = swap_float(0.0f, cineon->isMSB); + header->imageHeader.red_primary_y = swap_float(0.0f, cineon->isMSB); + header->imageHeader.green_primary_x = swap_float(0.0f, cineon->isMSB); + header->imageHeader.green_primary_y = swap_float(0.0f, cineon->isMSB); + header->imageHeader.blue_primary_x = swap_float(0.0f, cineon->isMSB); + header->imageHeader.blue_primary_y = swap_float(0.0f, cineon->isMSB); + strncpy(header->imageHeader.label, creator, 199); + header->imageHeader.label[199] = 0; + header->imageHeader.interleave = 0; + header->imageHeader.data_sign = 0; + header->imageHeader.sense = 0; + header->imageHeader.line_padding = swap_uint(0, cineon->isMSB); + header->imageHeader.element_padding = swap_uint(0, cineon->isMSB); + + switch (cineon->element[0].packing) { + case 0: + header->imageHeader.packing = 0; + break; + + case 1: + header->imageHeader.packing = 5; + break; + + case 2: + header->imageHeader.packing = 6; + break; + } + + /* --- Origination header --- */ + /* we leave it blank */ + + /* --- Film header --- */ + /* we leave it blank */ } -CineonFile* -cineonOpenFromMem(unsigned char *mem, unsigned int size) { +LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize) +{ + CineonMainHeader header; + LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); + char *filename = (char *)byteStuff; + int i; + unsigned int dataOffset; - CineonGenericHeader header; - - CineonFile* cineon = (CineonFile* )malloc(sizeof(CineonFile)); if (cineon == 0) { - if (verbose) d_printf("Failed to malloc cineon file structure.\n"); + if (verbose) printf("Cineon: Failed to malloc cineon file structure.\n"); return 0; } + /* zero the header */ + memset(&header, 0, sizeof(CineonMainHeader)); + /* for close routine */ cineon->file = 0; - cineon->lineBuffer = 0; - cineon->pixelBuffer = 0; - cineon->membuffer = mem; - cineon->membuffersize = size; - cineon->memcursor = mem; - - cineon->file = 0; - cineon->reading = 1; - verbose = 0; - if (size < sizeof(CineonGenericHeader)) { - if (verbose) d_printf("Not enough data for header!\n"); - cineonClose(cineon); + + if (fromMemory == 0) { + /* byteStuff is then the filename */ + cineon->file = BLI_fopen(filename, "rb"); + if (cineon->file == 0) { + if (verbose) printf("Cineon: Failed to open file \"%s\".\n", filename); + logImageClose(cineon); + return 0; + } + /* not used in this case */ + cineon->memBuffer = 0; + cineon->memCursor = 0; + cineon->memBufferSize = 0; + } + else { + cineon->memBuffer = (unsigned char *)byteStuff; + cineon->memCursor = (unsigned char *)byteStuff; + cineon->memBufferSize = bufferSize; + } + + if (logimage_fread(&header, sizeof(header), 1, cineon) == 0) { + if (verbose) printf("Cineon: Not enough data for header in \"%s\".\n", byteStuff); + logImageClose(cineon); return 0; } - logimage_fread(&header, sizeof(CineonGenericHeader), 1, cineon); - - /* let's assume cineon files are always network order */ - if (header.fileInfo.magic_num != ntohl(CINEON_FILE_MAGIC)) { - if (verbose) d_printf("Bad magic number %8.8lX in\n", (uintptr_t)ntohl(header.fileInfo.magic_num)); - - cineonClose(cineon); + /* endianness determination */ + if (header.fileHeader.magic_num == swap_uint(CINEON_FILE_MAGIC, 1)) { + cineon->isMSB = 1; + if (verbose) printf("Cineon: File is MSB.\n"); + } + else if (header.fileHeader.magic_num == CINEON_FILE_MAGIC) { + cineon->isMSB = 0; + if (verbose) printf("Cineon: File is LSB.\n"); + } + else { + if (verbose) printf("Cineon: Bad magic number %lu in \"%s\".\n", + (uintptr_t)header.fileHeader.magic_num, byteStuff); + logImageClose(cineon); return 0; } - if (header.formatInfo.packing != 5) { - if (verbose) d_printf("Can't understand packing %d\n", header.formatInfo.packing); - cineonClose(cineon); + cineon->width = swap_uint(header.imageHeader.element[0].pixels_per_line, cineon->isMSB); + cineon->height = swap_uint(header.imageHeader.element[0].lines_per_image, cineon->isMSB); + cineon->depth = header.imageHeader.elements_per_image; + cineon->srcFormat = format_Cineon; + + if (header.imageHeader.interleave == 0) + cineon->numElements = 1; + else if (header.imageHeader.interleave == 2) + cineon->numElements = header.imageHeader.elements_per_image; + else { + if (verbose) printf("Cineon: Data interleave not supported: %d\n", header.imageHeader.interleave); return 0; } - cineon->width = ntohl(header.imageInfo.channel[0].pixels_per_line); - cineon->height = ntohl(header.imageInfo.channel[0].lines_per_image); - cineon->depth = header.imageInfo.channels_per_image; - /* cineon->bitsPerPixel = 10; */ - cineon->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel; - cineon->imageOffset = ntohl(header.fileInfo.image_offset); - - cineon->lineBufferLength = pixelsToLongs(cineon->width * cineon->depth); - cineon->lineBuffer = malloc(cineon->lineBufferLength * 4); - if (cineon->lineBuffer == 0) { - if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", cineon->lineBufferLength * 4); - cineonClose(cineon); + if (cineon->depth == 1) { + /* Grayscale image */ + cineon->element[0].descriptor = descriptor_Luminance; + cineon->element[0].transfer = transfer_Linear; + cineon->element[0].depth = 1; + } + else if (cineon->depth == 3) { + /* RGB image */ + if (cineon->numElements == 1) { + cineon->element[0].descriptor = descriptor_RGB; + cineon->element[0].transfer = transfer_PrintingDensity; + cineon->element[0].depth = 3; + } + else if (cineon->numElements == 3) { + cineon->element[0].descriptor = descriptor_Red; + cineon->element[0].transfer = transfer_PrintingDensity; + cineon->element[0].depth = 1; + cineon->element[1].descriptor = descriptor_Green; + cineon->element[1].transfer = transfer_PrintingDensity; + cineon->element[1].depth = 1; + cineon->element[2].descriptor = descriptor_Blue; + cineon->element[2].transfer = transfer_PrintingDensity; + cineon->element[2].depth = 1; + } + } + else { + if (verbose) printf("Cineon: Cineon image depth unsupported: %d\n", cineon->depth); return 0; } - cineon->pixelBuffer = malloc(cineon->lineBufferLength * 3 * sizeof(unsigned short)); - if (cineon->pixelBuffer == 0) { - if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n", - (cineon->width * cineon->depth) * (int)sizeof(unsigned short)); - cineonClose(cineon); - return 0; - } - cineon->pixelBufferUsed = 0; - - if (logimage_fseek(cineon, cineon->imageOffset, SEEK_SET) != 0) { - if (verbose) d_printf("Couldn't seek to image data at %d\n", cineon->imageOffset); - cineonClose(cineon); - return 0; - } - - cineon->fileYPos = 0; + dataOffset = swap_uint(header.fileHeader.offset, cineon->isMSB); - logImageGetByteConversionDefaults(&cineon->params); - setupLut(cineon); + for (i = 0; i < cineon->numElements; i++) { + cineon->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample; + cineon->element[i].maxValue = powf(2, cineon->element[i].bitsPerSample) - 1.0f; + cineon->element[i].refLowData = swap_uint(header.imageHeader.element[i].ref_low_data, cineon->isMSB); + cineon->element[i].refLowQuantity = swap_float(header.imageHeader.element[i].ref_low_quantity, cineon->isMSB); + cineon->element[i].refHighData = swap_uint(header.imageHeader.element[i].ref_high_data, cineon->isMSB); + cineon->element[i].refHighQuantity = swap_float(header.imageHeader.element[i].ref_high_quantity, cineon->isMSB); - cineon->getRow = &cineonGetRowBytes; - cineon->setRow = 0; - cineon->close = &cineonClose; + switch (header.imageHeader.packing) { + case 0: + cineon->element[i].packing = 0; + break; + + case 5: + cineon->element[i].packing = 1; + break; + + case 6: + cineon->element[i].packing = 2; + break; + + default: + /* Not supported */ + if (verbose) printf("Cineon: packing unsupported: %d\n", header.imageHeader.packing); + return 0; + } + + if (cineon->element[i].refLowData == CINEON_UNDEFINED_U32 || isnan(cineon->element[i].refLowData)) + cineon->element[i].refLowData = 0; + + if (cineon->element[i].refHighData == CINEON_UNDEFINED_U32 || isnan(cineon->element[i].refHighData)) + cineon->element[i].refHighData = (unsigned int)cineon->element[i].maxValue; + + if (cineon->element[i].refLowQuantity == CINEON_UNDEFINED_R32 || isnan(cineon->element[i].refLowQuantity)) + cineon->element[i].refLowQuantity = 0.0f; + + if (cineon->element[i].refHighQuantity == CINEON_UNDEFINED_R32 || isnan(cineon->element[i].refHighQuantity)) { + if (cineon->element[i].transfer == transfer_PrintingDensity) + cineon->element[i].refHighQuantity = 2.048f; + else + cineon->element[i].refHighQuantity = cineon->element[i].maxValue; + } + + cineon->element[i].dataOffset = dataOffset; + dataOffset += cineon->height * getRowLength(cineon->width, cineon->element[i]); + } + + cineon->referenceBlack = 95.0f / 1023.0f * cineon->element[0].maxValue; + cineon->referenceWhite = 685.0f / 1023.0f * cineon->element[0].maxValue; + cineon->gamma = 1.7f; if (verbose) { - verboseMe(cineon); - } + printf("size %d x %d x %d elements\n", cineon->width, cineon->height, cineon->numElements); + for (i = 0; i < cineon->numElements; i++) { + printf(" Element %d:\n", i); + printf(" Bits per sample: %d\n", cineon->element[i].bitsPerSample); + printf(" Depth: %d\n", cineon->element[i].depth); + printf(" Transfer characteristics: %d\n", cineon->element[i].transfer); + printf(" Packing: %d\n", cineon->element[i].packing); + printf(" Descriptor: %d\n", cineon->element[i].descriptor); + printf(" Data offset: %u\n", cineon->element[i].dataOffset); + printf(" Reference low data: %u\n", cineon->element[i].refLowData); + printf(" Reference low quantity: %f\n", cineon->element[i].refLowQuantity); + printf(" Reference high data: %u\n", cineon->element[i].refHighData); + printf(" Reference high quantity: %f\n", cineon->element[i].refHighQuantity); + printf("\n"); + } + printf("Gamma: %f\n", cineon->gamma); + printf("Reference black: %f\n", cineon->referenceBlack); + printf("Reference white: %f\n", cineon->referenceWhite); + printf("----------------------------\n"); + } return cineon; } +LogImageFile *cineonCreate(const char *filename, int width, int height, int bitsPerSample, const char *creator) +{ + CineonMainHeader header; + const char *shortFilename = 0; + /* unsigned char pad[6044]; */ -int -cineonGetSize(const CineonFile* cineon, int* width, int* height, int* depth) { - *width = cineon->width; - *height = cineon->height; - *depth = cineon->depth; - return 0; -} - -CineonFile* -cineonCreate(const char* filename, int width, int height, int depth) { - - /* Note: always write files in network order */ - /* By the spec, it shouldn't matter, but ... */ - - CineonGenericHeader header; - const char* shortFilename = 0; - - CineonFile* cineon = (CineonFile*)malloc(sizeof(CineonFile)); + LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); if (cineon == 0) { - if (verbose) d_printf("Failed to malloc cineon file structure.\n"); + if (verbose) printf("cineon: Failed to malloc cineon file structure.\n"); return 0; } - memset(&header, 0, sizeof(header)); - - /* for close routine */ - cineon->file = 0; - cineon->lineBuffer = 0; - cineon->pixelBuffer = 0; - - cineon->file = BLI_fopen(filename, "wb"); - if (cineon->file == 0) { - if (verbose) d_printf("Couldn't open file %s\n", filename); - cineonClose(cineon); + /* Only 10 bits Cineon are supported */ + if (bitsPerSample != 10) { + if (verbose) printf("cineon: Only 10 bits Cineon are supported.\n"); + logImageClose(cineon); return 0; } - cineon->reading = 0; cineon->width = width; cineon->height = height; - cineon->depth = depth; - cineon->bitsPerPixel = 10; - cineon->imageOffset = sizeof(CineonGenericHeader); + cineon->element[0].bitsPerSample = 10; + cineon->element[0].dataOffset = sizeof(CineonMainHeader); + cineon->element[0].maxValue = 1023; + cineon->isMSB = 1; + cineon->numElements = 1; + cineon->element[0].packing = 1; + cineon->depth = 3; + cineon->element[0].depth = 3; + cineon->element[0].descriptor = descriptor_RGB; + cineon->element[0].transfer = transfer_PrintingDensity; + cineon->element[0].refHighQuantity = 2.048f; + cineon->element[0].refLowQuantity = 0; + cineon->element[0].refLowData = 0; + cineon->element[0].refHighData = cineon->element[0].maxValue; + cineon->referenceWhite = 685.0f; + cineon->referenceBlack = 95.0f; + cineon->gamma = 1.7f; - cineon->lineBufferLength = pixelsToLongs(cineon->width * cineon->depth); - cineon->lineBuffer = malloc(cineon->lineBufferLength * 4); - if (cineon->lineBuffer == 0) { - if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", cineon->lineBufferLength * 4); - cineonClose(cineon); - return 0; - } - - cineon->pixelBuffer = malloc(cineon->lineBufferLength * 3 * sizeof(unsigned short)); - if (cineon->pixelBuffer == 0) { - if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n", - (cineon->width * cineon->depth) * (int)sizeof(unsigned short)); - cineonClose(cineon); - return 0; - } - cineon->pixelBufferUsed = 0; - - /* find trailing part of filename */ shortFilename = strrchr(filename, '/'); - if (shortFilename == 0) { + if (shortFilename == 0) shortFilename = filename; - } - else { - ++shortFilename; - } + else + shortFilename++; - if (initCineonGenericHeader(cineon, &header, shortFilename) != 0) { - cineonClose(cineon); + cineon->file = BLI_fopen(filename, "wb"); + if (cineon->file == 0) { + if (verbose) printf("cineon: Couldn't open file %s\n", filename); + logImageClose(cineon); return 0; } + fillCineonMainHeader(cineon, &header, shortFilename, creator); + if (fwrite(&header, sizeof(header), 1, cineon->file) == 0) { - if (verbose) d_printf("Couldn't write image header\n"); - cineonClose(cineon); + if (verbose) printf("cineon: Couldn't write image header\n"); + logImageClose(cineon); return 0; } - cineon->fileYPos = 0; - - logImageGetByteConversionDefaults(&cineon->params); - setupLut(cineon); - - cineon->getRow = 0; - cineon->setRow = &cineonSetRowBytes; - cineon->close = &cineonClose; return cineon; } - -void -cineonClose(CineonFile* cineon) { - - if (cineon == 0) { - return; - } - - if (cineon->file) { - fclose(cineon->file); - cineon->file = 0; - } - - if (cineon->lineBuffer) { - free(cineon->lineBuffer); - cineon->lineBuffer = 0; - } - - if (cineon->pixelBuffer) { - free(cineon->pixelBuffer); - cineon->pixelBuffer = 0; - } - - free(cineon); -} diff --git a/source/blender/imbuf/intern/cineon/cineonlib.h b/source/blender/imbuf/intern/cineon/cineonlib.h index ef992c527b0..9333743a1bf 100644 --- a/source/blender/imbuf/intern/cineon/cineonlib.h +++ b/source/blender/imbuf/intern/cineon/cineonlib.h @@ -1,68 +1,142 @@ /* - * Cineon image file format library definitions. - * Also handles DPX files (almost) + * Cineon image file format library definitions. + * Also handles DPX files (almost) * - * Copyright 1999,2000,2001 David Hodson + * Copyright 1999,2000,2001 David Hodson * - * 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 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. + * 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. + * 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. + * + * Contributor(s): Julien Enche. * */ -#ifndef __CINEONLIB_H__ -#define __CINEONLIB_H__ - /** \file blender/imbuf/intern/cineon/cineonlib.h * \ingroup imbcineon */ -#include "logImageCore.h" + +#ifndef __CINEON_LIB_H__ +#define __CINEON_LIB_H__ #ifdef __cplusplus extern "C" { #endif -/* - * Cineon image structure. You don't care what this is. - */ +#include "logImageCore.h" -typedef struct _Log_Image_File_t_ CineonFile; +#define CINEON_FILE_MAGIC 0x802A5FD7 +#define CINEON_UNDEFINED_U8 0xFF +#define CINEON_UNDEFINED_U16 0xFFFF +#define CINEON_UNDEFINED_U32 0xFFFFFFFF +#define CINEON_UNDEFINED_R32 0x7F800000 +#define CINEON_UNDEFINED_CHAR 0 -/* int functions return 0 for OK */ +typedef struct { + unsigned int magic_num; + unsigned int offset; + unsigned int gen_hdr_size; + unsigned int ind_hdr_size; + unsigned int user_data_size; + unsigned int file_size; + char version[8]; + char file_name[100]; + char creation_date[12]; + char creation_time[12]; + char reserved[36]; +} CineonFileHeader; + +typedef struct { + unsigned char descriptor1; + unsigned char descriptor2; + unsigned char bits_per_sample; + unsigned char filler; + unsigned int pixels_per_line; + unsigned int lines_per_image; + unsigned int ref_low_data; + float ref_low_quantity; + unsigned int ref_high_data; + float ref_high_quantity; +} CineonElementHeader; + +typedef struct { + unsigned char orientation; + unsigned char elements_per_image; + unsigned short filler; + CineonElementHeader element[8]; + float white_point_x; + float white_point_y; + float red_primary_x; + float red_primary_y; + float green_primary_x; + float green_primary_y; + float blue_primary_x; + float blue_primary_y; + char label[200]; + char reserved[28]; + unsigned char interleave; + unsigned char packing; + unsigned char data_sign; + unsigned char sense; + unsigned int line_padding; + unsigned int element_padding; + char reserved2[20]; +} CineonImageHeader; + +typedef struct { + int x_offset; + int y_offset; + char file_name[100]; + char creation_date[12]; + char creation_time[12]; + char input_device[64]; + char model_number[32]; + char input_serial_number[32]; + float x_input_samples_per_mm; + float y_input_samples_per_mm; + float input_device_gamma; + char reserved[40]; +} CineonOriginationHeader; + +typedef struct { + unsigned char film_code; + unsigned char film_type; + unsigned char edge_code_perforation_offset; + unsigned char filler; + unsigned int prefix; + unsigned int count; + char format[32]; + unsigned int frame_position; + float frame_rate; + char attribute[32]; + char slate[200]; + char reserved[740]; +} CineonFilmHeader; + +typedef struct { + CineonFileHeader fileHeader; + CineonImageHeader imageHeader; + CineonOriginationHeader originationHeader; + CineonFilmHeader filmHeader; +} CineonMainHeader; void cineonSetVerbose(int); - -CineonFile* cineonOpenFromMem(unsigned char *mem, unsigned int size); - -CineonFile* cineonOpen(const char* filename); -int cineonGetSize(const CineonFile* cineon, int* xsize, int* ysize, int* channels); -CineonFile* cineonCreate(const char* filename, int xsize, int ysize, int channels); -int cineonIsMemFileCineon(unsigned char *mem); - -/* get/set scanline of converted bytes */ -int cineonGetRowBytes(CineonFile* cineon, unsigned short* row, int y); -int cineonSetRowBytes(CineonFile* cineon, const unsigned short* row, int y); - -/* get/set scanline of unconverted shorts */ -int cineonGetRow(CineonFile* cineon, unsigned short* row, int y); -int cineonSetRow(CineonFile* cineon, const unsigned short* row, int y); - -/* closes file and deletes data */ -void cineonClose(CineonFile* cineon); +LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize); +LogImageFile *cineonCreate(const char *filename, int width, int height, int bitsPerSample, const char *creator); #ifdef __cplusplus } #endif -#endif /* __CINEONLIB_H__ */ +#endif /* __CINEON_LIB_H__ */ diff --git a/source/blender/imbuf/intern/cineon/dpxfile.h b/source/blender/imbuf/intern/cineon/dpxfile.h index e1d95268a80..e69de29bb2d 100644 --- a/source/blender/imbuf/intern/cineon/dpxfile.h +++ b/source/blender/imbuf/intern/cineon/dpxfile.h @@ -1,128 +0,0 @@ -/* - * Cineon image file format library definitions. - * Dpx file format structures. - * - * This header file contains private details. - * User code should generally use cineonlib.h only. - * - * Copyright 1999,2000,2001 David Hodson - * - * 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 __DPXFILE_H__ -#define __DPXFILE_H__ - -/** \file blender/imbuf/intern/cineon/dpxfile.h - * \ingroup imbcineon - */ - -#include "logImageCore.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - U32 magic_num; /* magic number */ - U32 offset; /* offset to image data in bytes */ - ASCII vers[8]; /* which header format version is being used (v1.0) */ - U32 file_size; /* file size in bytes */ - U32 ditto_key; /* I bet some people use this */ - U32 gen_hdr_size; /* generic header length in bytes */ - U32 ind_hdr_size; /* industry header length in bytes */ - U32 user_data_size; /* user-defined data length in bytes */ - ASCII file_name[100]; /* image file name */ - ASCII create_date[24]; /* file creation date, yyyy:mm:dd:hh:mm:ss:LTZ */ - ASCII creator[100]; - ASCII project[200]; - ASCII copyright[200]; - U32 key; /* encryption key, FFFFFFF = unencrypted */ - ASCII Reserved[104]; /* reserved field TBD (need to pad) */ -} DpxFileInformation; - -typedef struct { - U32 signage; - U32 ref_low_data; /* reference low data code value */ - R32 ref_low_quantity; /* reference low quantity represented */ - U32 ref_high_data; /* reference high data code value */ - R32 ref_high_quantity;/* reference high quantity represented */ - U8 designator1; - U8 transfer_characteristics; - U8 colorimetry; - U8 bits_per_pixel; - U16 packing; - U16 encoding; - U32 data_offset; - U32 line_padding; - U32 channel_padding; - ASCII description[32]; -} DpxChannelInformation; - -typedef struct { - U16 orientation; - U16 channels_per_image; - U32 pixels_per_line; - U32 lines_per_image; - DpxChannelInformation channel[8]; - ASCII reserved[52]; -} DpxImageInformation; - -typedef struct { - U32 x_offset; - U32 y_offset; - R32 x_centre; - R32 y_centre; - U32 x_original_size; - U32 y_original_size; - ASCII file_name[100]; - ASCII creation_time[24]; - ASCII input_device[32]; - ASCII input_serial_number[32]; - U16 border_validity[4]; - U32 pixel_aspect_ratio[2]; /* h:v */ - ASCII reserved[28]; -} DpxOriginationInformation; - -typedef struct { - ASCII film_manufacturer_id[2]; - ASCII film_type[2]; - ASCII edge_code_perforation_offset[2]; - ASCII edge_code_prefix[6]; - ASCII edge_code_count[4]; - ASCII film_format[32]; - U32 frame_position; - U32 sequence_length; - U32 held_count; - R32 frame_rate; - R32 shutter_angle; - ASCII frame_identification[32]; - ASCII slate_info[100]; - ASCII reserved[56]; -} DpxMPIInformation; - -typedef struct { - DpxFileInformation fileInfo; - DpxImageInformation imageInfo; - DpxOriginationInformation originInfo; - DpxMPIInformation filmHeader; -} DpxMainHeader; - -#ifdef __cplusplus -} -#endif - -#endif /* __DPXFILE_H__ */ diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c index c1138225e93..aedce52a7bf 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.c +++ b/source/blender/imbuf/intern/cineon/dpxlib.c @@ -1,21 +1,23 @@ /* - * Dpx image file format library routines. + * Dpx image file format library routines. * - * Copyright 1999 - 2002 David Hodson + * Copyright 1999 - 2002 David Hodson * - * 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 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. + * 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. + * 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. + * + * Contributor(s): Julien Enche. * */ @@ -23,689 +25,445 @@ * \ingroup imbcineon */ -#include "dpxfile.h" + #include "dpxlib.h" +#include "logmemfile.h" #include #include #include -#include /* strftime() */ +#include #include -#ifdef WIN32 -#include -#else -#include /* htonl() */ -#endif -#include /* memset */ -#include "cin_debug_stuff.h" -#include "logmemfile.h" +#include + #include "BLI_fileops.h" +#include "BLI_math_base.h" +#include "BLI_utildefines.h" -static void -fillDpxChannelInfo(DpxFile* dpx, DpxChannelInformation* chan, int des) { +#include "MEM_guardedalloc.h" - (void)dpx; /* unused */ - - chan->signage = 0; - chan->ref_low_data = htonl(0); - chan->ref_low_quantity = htonf(0.0); - chan->ref_high_data = htonl(1023); - chan->ref_high_quantity = htonf(2.046); - chan->designator1 = des; - chan->transfer_characteristics = 0; - chan->colorimetry = 0; - chan->bits_per_pixel = 10; - chan->packing = htons(1); - chan->encoding = 0; - chan->data_offset = 0; - chan->line_padding = htonl(0); - chan->channel_padding = htonl(0); - chan->description[0] = 0; -} - -static void -dumpDpxChannelInfo(DpxChannelInformation* chan) { - d_printf(" Signage %ld", (intptr_t)ntohl(chan->signage)); - d_printf(" Ref low data %ld\n", (intptr_t)ntohl(chan->ref_low_data)); - d_printf(" Ref low quantity %f\n", ntohf(chan->ref_low_quantity)); - d_printf(" Ref high data %ld\n", (intptr_t)ntohl(chan->ref_high_data)); - d_printf(" Ref high quantity %f\n", ntohf(chan->ref_high_quantity)); - d_printf(" Designator1: %d,", chan->designator1); - d_printf(" Bits per pixel %d\n", chan->bits_per_pixel); - d_printf(" Packing: %d,", ntohs(chan->packing)); - d_printf(" Data Offset: %ld,", (intptr_t)ntohl(chan->data_offset)); -} - -static void -fillDpxFileInfo( - DpxFile* dpx, DpxFileInformation* fileInfo, const char* filename) { - - time_t fileClock; - struct tm* fileTime; - - /* Note: always write files in network order */ - /* By the spec, it shouldn't matter, but ... */ - - fileInfo->magic_num = htonl(DPX_FILE_MAGIC); - fileInfo->offset = htonl(dpx->imageOffset); - strcpy(fileInfo->vers, "v1.0"); - fileInfo->file_size = htonl(dpx->imageOffset + - pixelsToLongs(dpx->height * dpx->width * dpx->depth) * 4); - fileInfo->ditto_key = 0; - fileInfo->gen_hdr_size = htonl( - sizeof(DpxFileInformation) + - sizeof(DpxImageInformation) + - sizeof(DpxOriginationInformation)); - fileInfo->ind_hdr_size = htonl(sizeof(DpxMPIInformation)); - fileInfo->user_data_size = 0; - strncpy(fileInfo->file_name, filename, 99); - fileInfo->file_name[99] = 0; - - fileClock = time(0); - fileTime = localtime(&fileClock); - strftime(fileInfo->create_date, 24, "%Y:%m:%d:%H:%M:%S%Z", fileTime); - /* Question: is %Z in strftime guaranteed to return 3 chars? */ - fileInfo->create_date[23] = 0; - - strcpy(fileInfo->creator, "David's DPX writer"); - fileInfo->project[0] = 0; - fileInfo->copyright[0] = 0; - fileInfo->key = 0xFFFFFFFF; /* same in any byte order */ -} - -static void -dumpDpxFileInfo(DpxFileInformation* fileInfo) { - d_printf("\n--File Information--\n"); - d_printf("Magic: %8.8lX\n", (unsigned long)ntohl(fileInfo->magic_num)); - d_printf("Image Offset %ld\n", (intptr_t)ntohl(fileInfo->offset)); - d_printf("Version \"%s\"\n", fileInfo->vers); - d_printf("File size %ld\n", (intptr_t)ntohl(fileInfo->file_size)); - d_printf("Ditto key %ld\n", (intptr_t)ntohl(fileInfo->ditto_key)); - d_printf("Generic Header size %ld\n", (intptr_t)ntohl(fileInfo->gen_hdr_size)); - d_printf("Industry Header size %ld\n", (intptr_t)ntohl(fileInfo->ind_hdr_size)); - d_printf("User Data size %ld\n", (intptr_t)ntohl(fileInfo->user_data_size)); - d_printf("File name \"%s\"\n", fileInfo->file_name); - d_printf("Creation date \"%s\"\n", fileInfo->create_date); - d_printf("Creator \"%s\"\n", fileInfo->creator); - d_printf("Project \"%s\"\n", fileInfo->project); - d_printf("Copyright \"%s\"\n", fileInfo->copyright); - d_printf("Key %ld\n", (intptr_t)ntohl(fileInfo->key)); -} - -static void -fillDpxImageInfo( - DpxFile* dpx, DpxImageInformation* imageInfo) { - imageInfo->orientation = 0; - imageInfo->channels_per_image = htons(1); - imageInfo->pixels_per_line = htonl(dpx->width); - imageInfo->lines_per_image = htonl(dpx->height); - - if (dpx->depth == 1) { - fillDpxChannelInfo(dpx, &imageInfo->channel[0], 0); - - } - else if (dpx->depth == 3) { - fillDpxChannelInfo(dpx, &imageInfo->channel[0], 50); - } -} - -static void -dumpDpxImageInfo(DpxImageInformation* imageInfo) { - - int n; - int i; - d_printf("\n--Image Information--\n"); - d_printf("Image orientation %d,", ntohs(imageInfo->orientation)); - n = ntohs(imageInfo->channels_per_image); - d_printf("Channels %d\n", n); - d_printf("Pixels per line %ld\n", (intptr_t)ntohl(imageInfo->pixels_per_line)); - d_printf("Lines per image %ld\n", (intptr_t)ntohl(imageInfo->lines_per_image)); - for (i = 0; i < n; ++i) { - d_printf(" --Channel %d--\n", i); - dumpDpxChannelInfo(&imageInfo->channel[i]); - } -} - -static void -fillDpxOriginationInfo( - DpxFile* dpx, DpxOriginationInformation* originInfo, DpxFileInformation* fileInfo) -{ - /* unused */ - (void)dpx; - (void)originInfo; - (void)fileInfo; -} - -static void -dumpDpxOriginationInfo(DpxOriginationInformation* originInfo) { - d_printf("\n--Origination Information--\n"); - d_printf("X offset %ld\n", (intptr_t)ntohl(originInfo->x_offset)); - d_printf("Y offset %ld\n", (intptr_t)ntohl(originInfo->y_offset)); - d_printf("X centre %f\n", ntohf(originInfo->x_centre)); - d_printf("Y centre %f\n", ntohf(originInfo->y_centre)); - d_printf("Original X %ld\n", (intptr_t)ntohl(originInfo->x_original_size)); - d_printf("Original Y %ld\n", (intptr_t)ntohl(originInfo->y_original_size)); - d_printf("File name \"%s\"\n", originInfo->file_name); - d_printf("Creation time \"%s\"\n", originInfo->creation_time); - d_printf("Input device \"%s\"\n", originInfo->input_device); - d_printf("Serial number \"%s\"\n", originInfo->input_serial_number); -} - -static void -initDpxMainHeader(DpxFile* dpx, DpxMainHeader* header, const char* shortFilename) { - memset(header, 0, sizeof(DpxMainHeader)); - fillDpxFileInfo(dpx, &header->fileInfo, shortFilename); - fillDpxImageInfo(dpx, &header->imageInfo); - fillDpxOriginationInfo(dpx, &header->originInfo, &header->fileInfo); -#if 0 - fillDpxMPIInfo(dpx, &header->filmHeader); -#endif -} - -static void -dumpDpxMainHeader(DpxMainHeader* header) { - dumpDpxFileInfo(&header->fileInfo); - dumpDpxImageInfo(&header->imageInfo); - dumpDpxOriginationInfo(&header->originInfo); -#if 0 - dumpDpxMPIInformation(&header->filmHeader); -#endif -} +/* + * For debug purpose + */ static int verbose = 0; -void -dpxSetVerbose(int verbosity) { + +void dpxSetVerbose(int verbosity) { verbose = verbosity; } -static void -verboseMe(DpxFile* dpx) { - d_printf("size %d x %d x %d\n", dpx->width, dpx->height, dpx->depth); - d_printf("ImageStart %d, lineBufferLength %d, implied length %d\n", - dpx->imageOffset, dpx->lineBufferLength * 4, - dpx->imageOffset + pixelsToLongs(dpx->width * dpx->depth * dpx->height) * 4); +/* + * Headers + */ + +static void fillDpxMainHeader(LogImageFile *dpx, DpxMainHeader *header, const char *filename, const char *creator) +{ + time_t fileClock; + struct tm *fileTime; + + memset(header, 0, sizeof(DpxMainHeader)); + + /* --- File header --- */ + header->fileHeader.magic_num = swap_uint(DPX_FILE_MAGIC, dpx->isMSB); + header->fileHeader.offset = swap_uint(dpx->element[0].dataOffset, dpx->isMSB); + strcpy(header->fileHeader.version, "v2.0"); + header->fileHeader.file_size = swap_uint(dpx->element[0].dataOffset + dpx->height * getRowLength(dpx->width, dpx->element[0]), dpx->isMSB); + header->fileHeader.ditto_key = 0; + header->fileHeader.gen_hdr_size = swap_uint(sizeof(DpxFileHeader) + sizeof(DpxImageHeader) + sizeof(DpxOrientationHeader), dpx->isMSB); + header->fileHeader.ind_hdr_size = swap_uint(sizeof(DpxFilmHeader) + sizeof(DpxTelevisionHeader), dpx->isMSB); + header->fileHeader.user_data_size = DPX_UNDEFINED_U32; + strncpy(header->fileHeader.file_name, filename, 99); + header->fileHeader.file_name[99] = 0; + fileClock = time(0); + fileTime = localtime(&fileClock); + strftime(header->fileHeader.creation_date, 24, "%Y:%m:%d:%H:%M:%S%Z", fileTime); + header->fileHeader.creation_date[23] = 0; + strncpy(header->fileHeader.creator, creator, 99); + header->fileHeader.creator[99] = 0; + header->fileHeader.project[0] = 0; + header->fileHeader.copyright[0] = 0; + header->fileHeader.key = 0xFFFFFFFF; + + /* --- Image header --- */ + header->imageHeader.orientation = 0; + header->imageHeader.elements_per_image = swap_ushort(1, dpx->isMSB); + header->imageHeader.pixels_per_line = swap_uint(dpx->width, dpx->isMSB); + header->imageHeader.lines_per_element = swap_uint(dpx->height, dpx->isMSB); + + /* Fills element */ + header->imageHeader.element[0].data_sign = 0; + header->imageHeader.element[0].ref_low_data = swap_uint(dpx->element[0].refLowData, dpx->isMSB); + header->imageHeader.element[0].ref_low_quantity = swap_float(dpx->element[0].refLowQuantity, dpx->isMSB); + header->imageHeader.element[0].ref_high_data = swap_uint(dpx->element[0].refHighData, dpx->isMSB); + header->imageHeader.element[0].ref_high_quantity = swap_float(dpx->element[0].refHighQuantity, dpx->isMSB); + header->imageHeader.element[0].descriptor = dpx->element[0].descriptor; + header->imageHeader.element[0].transfer = dpx->element[0].transfer; + header->imageHeader.element[0].colorimetric = 0; + header->imageHeader.element[0].bits_per_sample = dpx->element[0].bitsPerSample; + header->imageHeader.element[0].packing = swap_ushort(dpx->element[0].packing, dpx->isMSB); + header->imageHeader.element[0].encoding = 0; + header->imageHeader.element[0].data_offset = swap_uint(dpx->element[0].dataOffset, dpx->isMSB); + header->imageHeader.element[0].line_padding = 0; + header->imageHeader.element[0].element_padding = 0; + header->imageHeader.element[0].description[0] = 0; + + /* --- Orientation header --- */ + /* we leave it blank */ + + /* --- Television header --- */ + header->televisionHeader.time_code = DPX_UNDEFINED_U32; + header->televisionHeader.user_bits = DPX_UNDEFINED_U32; + header->televisionHeader.interlace = DPX_UNDEFINED_U8; + header->televisionHeader.field_number = DPX_UNDEFINED_U8; + header->televisionHeader.video_signal = DPX_UNDEFINED_U8; + header->televisionHeader.padding = DPX_UNDEFINED_U8; + header->televisionHeader.horizontal_sample_rate = DPX_UNDEFINED_R32; + header->televisionHeader.vertical_sample_rate = DPX_UNDEFINED_R32; + header->televisionHeader.frame_rate = DPX_UNDEFINED_R32; + header->televisionHeader.time_offset = DPX_UNDEFINED_R32; + header->televisionHeader.gamma = swap_float(dpx->gamma, dpx->isMSB); + header->televisionHeader.black_level = swap_float(dpx->referenceBlack, dpx->isMSB); + header->televisionHeader.black_gain = DPX_UNDEFINED_R32; + header->televisionHeader.breakpoint = DPX_UNDEFINED_R32; + header->televisionHeader.white_level = swap_float(dpx->referenceWhite, dpx->isMSB); + header->televisionHeader.integration_times = DPX_UNDEFINED_R32; } -int -dpxGetRowBytes(DpxFile* dpx, unsigned short* row, int y) { - - /* Note: this code is bizarre because DPX files can wrap */ - /* packed longwords across line boundaries!!!! */ - - size_t readLongs; - unsigned int longIndex; - int numPixels = dpx->width * dpx->depth; - int pixelIndex; - - /* only seek if not reading consecutive lines */ - /* this is not quite right yet, need to account for leftovers */ - if (y != dpx->fileYPos) { - int lineOffset = pixelsToLongs(y * dpx->width * dpx->depth) * 4; - if (verbose) d_printf("Seek in getRowBytes\n"); - if (logimage_fseek(dpx, dpx->imageOffset + lineOffset, SEEK_SET) != 0) { - if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, dpx->imageOffset + lineOffset); - return 1; - } - dpx->fileYPos = y; - } - - /* read enough longwords */ - readLongs = pixelsToLongs(numPixels - dpx->pixelBufferUsed); - if (logimage_fread(dpx->lineBuffer, 4, readLongs, dpx) != readLongs) { - if (verbose) d_printf("Couldn't read line %d length %d\n", y, (int)readLongs * 4); - return 1; - } - ++dpx->fileYPos; - - /* convert longwords to pixels */ - pixelIndex = dpx->pixelBufferUsed; - - /* this is just strange */ - if (dpx->depth == 1) { - for (longIndex = 0; longIndex < readLongs; ++longIndex) { - unsigned int t = ntohl(dpx->lineBuffer[longIndex]); - dpx->pixelBuffer[pixelIndex] = t & 0x3ff; - t = t >> 10; - dpx->pixelBuffer[pixelIndex+1] = t & 0x3ff; - t = t >> 10; - dpx->pixelBuffer[pixelIndex+2] = t & 0x3ff; - pixelIndex += 3; - } - } - else /* if (dpx->depth == 3) */ { - for (longIndex = 0; longIndex < readLongs; ++longIndex) { - unsigned int t = ntohl(dpx->lineBuffer[longIndex]); - t = t >> 2; - dpx->pixelBuffer[pixelIndex+2] = t & 0x3ff; - t = t >> 10; - dpx->pixelBuffer[pixelIndex+1] = t & 0x3ff; - t = t >> 10; - dpx->pixelBuffer[pixelIndex] = t & 0x3ff; - pixelIndex += 3; - } - } - dpx->pixelBufferUsed = pixelIndex; - - /* extract required pixels */ - for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) { - if (dpx->params.doLogarithm) - row[pixelIndex] = dpx->lut10_16[dpx->pixelBuffer[pixelIndex]]; - else - row[pixelIndex] = dpx->pixelBuffer[pixelIndex] << 6; - } - - /* save remaining pixels */ - while (pixelIndex < dpx->pixelBufferUsed) { - dpx->pixelBuffer[pixelIndex - numPixels] = dpx->pixelBuffer[pixelIndex]; - ++pixelIndex; - } - dpx->pixelBufferUsed -= numPixels; - - /* done! */ - return 0; -} - -int -dpxSetRowBytes(DpxFile* dpx, const unsigned short* row, int y) { - - /* Note: this code is bizarre because DPX files can wrap */ - /* packed longwords across line boundaries!!!! */ - - size_t writeLongs; - int longIndex; - int numPixels = dpx->width * dpx->depth; - int pixelIndex; - int pixelIndex2; - - /* only seek if not reading consecutive lines */ - /* this is not quite right yet */ - if (y != dpx->fileYPos) { - int lineOffset = pixelsToLongs(y * dpx->width * dpx->depth) * 4; - if (verbose) d_printf("Seek in getRowBytes\n"); - if (logimage_fseek(dpx, dpx->imageOffset + lineOffset, SEEK_SET) != 0) { - if (verbose) d_printf("Couldn't seek to line %d at %d\n", y, dpx->imageOffset + lineOffset); - return 1; - } - dpx->fileYPos = y; - } - - /* put new pixels into pixelBuffer */ - for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) { - if (dpx->params.doLogarithm) - dpx->pixelBuffer[dpx->pixelBufferUsed + pixelIndex] = dpx->lut16_16[row[pixelIndex]]; - else - dpx->pixelBuffer[dpx->pixelBufferUsed + pixelIndex] = row[pixelIndex] >> 6; - } - dpx->pixelBufferUsed += numPixels; - - /* pack into longwords */ - writeLongs = dpx->pixelBufferUsed / 3; - /* process whole line at image end */ - if (dpx->fileYPos == (dpx->height - 1)) { - writeLongs = pixelsToLongs(dpx->pixelBufferUsed); - } - pixelIndex = 0; - if (dpx->depth == 1) { - for (longIndex = 0; longIndex < writeLongs; ++longIndex) { - unsigned int t = dpx->pixelBuffer[pixelIndex] | - (dpx->pixelBuffer[pixelIndex+1] << 10) | - (dpx->pixelBuffer[pixelIndex+2] << 20); - dpx->lineBuffer[longIndex] = htonl(t); - pixelIndex += 3; - } - } - else { - for (longIndex = 0; longIndex < writeLongs; ++longIndex) { - unsigned int t = dpx->pixelBuffer[pixelIndex+2] << 2 | - (dpx->pixelBuffer[pixelIndex+1] << 12) | - (dpx->pixelBuffer[pixelIndex] << 22); - dpx->lineBuffer[longIndex] = htonl(t); - pixelIndex += 3; - } - } - - /* write them */ - if (fwrite(dpx->lineBuffer, 4, writeLongs, dpx->file) != writeLongs) { - if (verbose) d_printf("Couldn't write line %d length %d\n", y, (int)writeLongs * 4); - return 1; - } - ++dpx->fileYPos; - - /* save remaining pixels */ - pixelIndex2 = 0; - while (pixelIndex < dpx->pixelBufferUsed) { - dpx->pixelBuffer[pixelIndex2] = dpx->pixelBuffer[pixelIndex]; - ++pixelIndex; - ++pixelIndex2; - } - dpx->pixelBufferUsed = pixelIndex2; - - return 0; -} - -#define LFMEMFILE 0 -#define LFREALFILE 1 - -static DpxFile* -intern_dpxOpen(int mode, const char* bytestuff, int bufsize) { - +LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize) +{ DpxMainHeader header; - const char *filename = bytestuff; - DpxFile* dpx = (DpxFile*)malloc(sizeof(DpxFile)); - + LogImageFile *dpx = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); + char *filename = (char *)byteStuff; + int i; + if (dpx == 0) { - if (verbose) d_printf("Failed to malloc dpx file structure.\n"); + if (verbose) printf("DPX: Failed to malloc dpx file structure.\n"); return 0; } + /* zero the header */ + memset(&header, 0, sizeof(DpxMainHeader)); + /* for close routine */ dpx->file = 0; - dpx->lineBuffer = 0; - dpx->pixelBuffer = 0; - if (mode == LFREALFILE) { - filename = bytestuff; + if (fromMemory == 0) { + /* byteStuff is then the filename */ dpx->file = BLI_fopen(filename, "rb"); - if (dpx->file == 0) { - if (verbose) d_printf("Failed to open file \"%s\".\n", filename); - dpxClose(dpx); + if (dpx->file == 0) { + if (verbose) printf("DPX: Failed to open file \"%s\".\n", filename); + logImageClose(dpx); return 0; } - dpx->membuffer = 0; - dpx->memcursor = 0; - dpx->membuffersize = 0; + /* not used in this case */ + dpx->memBuffer = 0; + dpx->memCursor = 0; + dpx->memBufferSize = 0; } - else if (mode == LFMEMFILE) { - dpx->membuffer = (unsigned char *)bytestuff; - dpx->memcursor = (unsigned char *)bytestuff; - dpx->membuffersize = bufsize; + else { + dpx->memBuffer = (unsigned char *)byteStuff; + dpx->memCursor = (unsigned char *)byteStuff; + dpx->memBufferSize = bufferSize; } - - dpx->reading = 1; if (logimage_fread(&header, sizeof(header), 1, dpx) == 0) { - if (verbose) d_printf("Not enough data for header in \"%s\".\n", filename); - dpxClose(dpx); + if (verbose) printf("DPX: Not enough data for header in \"%s\".\n", byteStuff); + logImageClose(dpx); return 0; } - /* let's assume dpx files are always network order */ - if (header.fileInfo.magic_num != ntohl(DPX_FILE_MAGIC)) { - if (verbose) d_printf("Bad magic number %8.8lX in \"%s\".\n", - (uintptr_t)ntohl(header.fileInfo.magic_num), filename); - dpxClose(dpx); + /* endianness determination */ + if (header.fileHeader.magic_num == swap_uint(DPX_FILE_MAGIC, 1)) { + dpx->isMSB = 1; + if (verbose) printf("DPX: File is MSB.\n"); + } + else if (header.fileHeader.magic_num == DPX_FILE_MAGIC) { + dpx->isMSB = 0; + if (verbose) printf("DPX: File is LSB.\n"); + } + else { + if (verbose) printf("DPX: Bad magic number %lu in \"%s\".\n", + (uintptr_t)header.fileHeader.magic_num, byteStuff); + logImageClose(dpx); return 0; } - if (ntohs(header.imageInfo.channel[0].packing) != 1) { - if (verbose) d_printf("Unknown packing %d\n", header.imageInfo.channel[0].packing); - dpxClose(dpx); - return 0; - } + dpx->srcFormat = format_DPX; + dpx->numElements = swap_ushort(header.imageHeader.elements_per_image, dpx->isMSB); + dpx->width = swap_uint(header.imageHeader.pixels_per_line, dpx->isMSB); + dpx->height = swap_uint(header.imageHeader.lines_per_element, dpx->isMSB); + dpx->depth = 0; + for (i = 0; i < dpx->numElements; i++) { + dpx->element[i].descriptor = header.imageHeader.element[i].descriptor; - dpx->width = ntohl(header.imageInfo.pixels_per_line); - dpx->height = ntohl(header.imageInfo.lines_per_image); - dpx->depth = ntohs(header.imageInfo.channels_per_image); - /* Another DPX vs Cineon wierdness */ - if (dpx->depth == 1) { - switch (header.imageInfo.channel[0].designator1) { - case 50: dpx->depth = 3; break; - case 51: dpx->depth = 4; break; - case 52: dpx->depth = 4; break; - default: break; + switch (dpx->element[i].descriptor) { + case descriptor_Red: + case descriptor_Green: + case descriptor_Blue: + case descriptor_Alpha: + case descriptor_Luminance: + case descriptor_Chrominance: + dpx->depth++; + dpx->element[i].depth = 1; + break; + + case descriptor_CbYCrY: + dpx->depth += 2; + dpx->element[i].depth = 2; + break; + + case descriptor_RGB: + case descriptor_CbYCr: + case descriptor_CbYACrYA: + dpx->depth += 3; + dpx->element[i].depth = 3; + break; + + case descriptor_RGBA: + case descriptor_ABGR: + case descriptor_CbYCrA: + dpx->depth += 4; + dpx->element[i].depth = 4; + break; + + case descriptor_Depth: + case descriptor_Composite: + /* unsupported */ + break; + } + + if (dpx->depth == 0 || dpx->depth > 4) { + if (verbose) printf("DPX: Unsupported image depth: %d\n", dpx->depth); + logImageClose(dpx); + return 0; + } + + dpx->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample; + dpx->element[i].maxValue = powf(2, dpx->element[i].bitsPerSample) - 1.0f; + dpx->element[i].packing = swap_ushort(header.imageHeader.element[i].packing, dpx->isMSB); + + /* Sometimes, the offset is not set correctly in the header */ + dpx->element[i].dataOffset = swap_uint(header.imageHeader.element[i].data_offset, dpx->isMSB); + if (dpx->element[i].dataOffset == 0 && dpx->numElements == 1) + dpx->element[i].dataOffset = swap_uint(header.fileHeader.offset, dpx->isMSB); + + if (dpx->element[i].dataOffset == 0) { + if (verbose) printf("DPX: Image header is corrupted.\n"); + logImageClose(dpx); + return 0; + } + + dpx->element[i].transfer = header.imageHeader.element[i].transfer; + + /* if undefined, assign default */ + dpx->element[i].refLowData = swap_uint(header.imageHeader.element[i].ref_low_data, dpx->isMSB); + dpx->element[i].refLowQuantity = swap_float(header.imageHeader.element[i].ref_low_quantity, dpx->isMSB); + dpx->element[i].refHighData = swap_uint(header.imageHeader.element[i].ref_high_data, dpx->isMSB); + dpx->element[i].refHighQuantity = swap_float(header.imageHeader.element[i].ref_high_quantity, dpx->isMSB); + + switch (dpx->element[i].descriptor) { + case descriptor_Red: + case descriptor_Green: + case descriptor_Blue: + case descriptor_Alpha: + case descriptor_RGB: + case descriptor_RGBA: + case descriptor_ABGR: + if (dpx->element[i].refLowData == DPX_UNDEFINED_U32 || isnan(dpx->element[i].refLowData)) + dpx->element[i].refLowData = 0; + + if (dpx->element[i].refHighData == DPX_UNDEFINED_U32 || isnan(dpx->element[i].refHighData)) + dpx->element[i].refHighData = (unsigned int)dpx->element[i].maxValue; + + if (dpx->element[i].refLowQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refLowQuantity)) + dpx->element[i].refLowQuantity = 0.0f; + + if (dpx->element[i].refHighQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refHighQuantity)) { + if (dpx->element[i].transfer == transfer_PrintingDensity || dpx->element[i].transfer == transfer_Logarithmic) + dpx->element[i].refHighQuantity = 2.048f; + else + dpx->element[i].refHighQuantity = dpx->element[i].maxValue; + } + + break; + + case descriptor_Luminance: + case descriptor_Chrominance: + case descriptor_CbYCrY: + case descriptor_CbYCr: + case descriptor_CbYACrYA: + case descriptor_CbYCrA: + if (dpx->element[i].refLowData == DPX_UNDEFINED_U32 || isnan(dpx->element[i].refLowData)) + dpx->element[i].refLowData = 16.0f / 255.0f * dpx->element[i].maxValue; + + if (dpx->element[i].refHighData == DPX_UNDEFINED_U32 || isnan(dpx->element[i].refHighData)) + dpx->element[i].refHighData = 235.0f / 255.0f * dpx->element[i].maxValue; + + if (dpx->element[i].refLowQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refLowQuantity)) + dpx->element[i].refLowQuantity = 0.0f; + + if (dpx->element[i].refHighQuantity == DPX_UNDEFINED_R32 || isnan(dpx->element[i].refHighQuantity)) + dpx->element[i].refHighQuantity = 0.7f; + + break; + + default: + break; } } - /* dpx->bitsPerPixel = 10; */ - dpx->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel; - if (dpx->bitsPerPixel != 10) { - if (verbose) d_printf("Don't support depth: %d\n", dpx->bitsPerPixel); - dpxClose(dpx); - return 0; - } - dpx->imageOffset = ntohl(header.fileInfo.offset); - dpx->lineBufferLength = pixelsToLongs(dpx->width * dpx->depth); - dpx->lineBuffer = malloc(dpx->lineBufferLength * 4); - if (dpx->lineBuffer == 0) { - if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", dpx->lineBufferLength * 4); - dpxClose(dpx); - return 0; - } + dpx->referenceBlack = swap_float(header.televisionHeader.black_level, dpx->isMSB); + dpx->referenceWhite = swap_float(header.televisionHeader.white_level, dpx->isMSB); + dpx->gamma = swap_float(header.televisionHeader.gamma, dpx->isMSB); - /* could have 2 pixels left over */ - dpx->pixelBuffer = malloc((dpx->lineBufferLength * 3 + 2) * sizeof(unsigned short)); - if (dpx->pixelBuffer == 0) { - if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n", - (dpx->width * dpx->depth + 2 + 2) * (int)sizeof(unsigned short)); - dpxClose(dpx); - return 0; - } - dpx->pixelBufferUsed = 0; + if ((dpx->referenceBlack == DPX_UNDEFINED_R32 || isnan(dpx->referenceBlack)) || + (dpx->referenceWhite == DPX_UNDEFINED_R32 || dpx->referenceWhite <= dpx->referenceBlack || isnan(dpx->referenceWhite)) || + (dpx->gamma == DPX_UNDEFINED_R32 || dpx->gamma <= 0 || isnan(dpx->gamma))) + { - if (logimage_fseek(dpx, dpx->imageOffset, SEEK_SET) != 0) { - if (verbose) d_printf("Couldn't seek to image data start at %d\n", dpx->imageOffset); - dpxClose(dpx); - return 0; + dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue; + dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue; + dpx->gamma = 1.7f; } - dpx->fileYPos = 0; - - logImageGetByteConversionDefaults(&dpx->params); - /* The SMPTE define this code: - * 0 - User-defined - * 1 - Printing density - * 2 - Linear - * 3 - Logarithmic - * 4 - Unspecified video - * 5 - SMPTE 240M - * 6 - CCIR 709-1 - * 7 - CCIR 601-2 system B or G - * 8 - CCIR 601-2 system M - * 9 - NTSC composite video - * 10 - PAL composite video - * 11 - Z linear - * 12 - homogeneous - * - * Note that transfer_characteristics is U8, don't need - * check the byte order. - */ - - switch (header.imageInfo.channel[0].transfer_characteristics) { - case 1: - case 2: /* linear */ - dpx->params.doLogarithm= 0; - break; - - case 3: - dpx->params.doLogarithm= 1; - break; - - /* TODO - Unsupported, but for now just load them, - * colors may look wrong, but can solve color conversion later - */ - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - if (verbose) d_printf("Un-supported Transfer Characteristics: %d using linear color conversion\n", header.imageInfo.channel[0].transfer_characteristics); - dpx->params.doLogarithm= 0; - break; - default: - if (verbose) d_printf("Un-supported Transfer Characteristics: %d\n", header.imageInfo.channel[0].transfer_characteristics); - dpxClose(dpx); - return 0; - break; - } - setupLut(dpx); - - dpx->getRow = &dpxGetRowBytes; - dpx->setRow = 0; - dpx->close = &dpxClose; if (verbose) { - verboseMe(dpx); - } + printf("size %d x %d x %d elements\n", dpx->width, dpx->height, dpx->numElements); + for (i = 0; i < dpx->numElements; i++) { + printf(" Element %d:\n", i); + printf(" Bits per sample: %d\n", dpx->element[i].bitsPerSample); + printf(" Depth: %d\n", dpx->element[i].depth); + printf(" Transfer characteristics: %d\n", dpx->element[i].transfer); + printf(" Packing: %d\n", dpx->element[i].packing); + printf(" Descriptor: %d\n", dpx->element[i].descriptor); + printf(" Data offset: %u\n", dpx->element[i].dataOffset); + printf(" Reference low data: %u\n", dpx->element[i].refLowData); + printf(" Reference low quantity: %f\n", dpx->element[i].refLowQuantity); + printf(" Reference high data: %u\n", dpx->element[i].refHighData); + printf(" Reference high quantity: %f\n", dpx->element[i].refHighQuantity); + printf("\n"); + } + printf("Gamma: %f\n", dpx->gamma); + printf("Reference black: %f\n", dpx->referenceBlack); + printf("Reference white: %f\n", dpx->referenceWhite); + printf("----------------------------\n"); + } return dpx; } -DpxFile* -dpxOpen(const char *filename) { - return intern_dpxOpen(LFREALFILE, filename, 0); -} - -DpxFile* -dpxOpenFromMem(unsigned char *buffer, unsigned int size) { - return intern_dpxOpen(LFMEMFILE, (const char *) buffer, size); -} - -int -dpxIsMemFileCineon(void *buffer) { - int magicnum = 0; - magicnum = *((int*)buffer); - if (magicnum == ntohl(DPX_FILE_MAGIC)) return 1; - else return 0; -} - -DpxFile* -dpxCreate(const char* filename, int width, int height, int depth) { - - /* Note: always write files in network order */ - /* By the spec, it shouldn't matter, but ... */ - +LogImageFile *dpxCreate(const char *filename, int width, int height, int bitsPerSample, int hasAlpha, + int isLogarithmic, int referenceWhite, int referenceBlack, float gamma, + const char *creator) +{ DpxMainHeader header; - const char* shortFilename = 0; + const char *shortFilename = 0; + unsigned char pad[6044]; - DpxFile* dpx = (DpxFile*)malloc(sizeof(DpxFile)); + LogImageFile *dpx = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); if (dpx == 0) { - if (verbose) d_printf("Failed to malloc dpx file structure.\n"); + if (verbose) printf("DPX: Failed to malloc dpx file structure.\n"); return 0; } - memset(&header, 0, sizeof(header)); - - /* for close routine */ - dpx->file = 0; - dpx->lineBuffer = 0; - dpx->pixelBuffer = 0; - - dpx->file = BLI_fopen(filename, "wb"); - if (dpx->file == 0) { - if (verbose) d_printf("Couldn't open file %s\n", filename); - dpxClose(dpx); - return 0; - } - dpx->reading = 0; - dpx->width = width; dpx->height = height; - dpx->depth = depth; - dpx->bitsPerPixel = 10; - dpx->imageOffset = sizeof(DpxMainHeader); + dpx->element[0].bitsPerSample = bitsPerSample; + dpx->element[0].dataOffset = 8092; + dpx->element[0].maxValue = powf(2, dpx->element[0].bitsPerSample) - 1.0f; + dpx->isMSB = 1; + dpx->numElements = 1; - dpx->lineBufferLength = pixelsToLongs(dpx->width * dpx->depth); - dpx->lineBuffer = malloc(dpx->lineBufferLength * 4); - if (dpx->lineBuffer == 0) { - if (verbose) d_printf("Couldn't malloc line buffer of size %d\n", dpx->lineBufferLength * 4); - dpxClose(dpx); - return 0; + switch (bitsPerSample) { + case 8: + case 16: + dpx->element[0].packing = 0; + break; + + case 10: + case 12: + /* Packed Type A padding is the most common 10/12 bits format */ + dpx->element[0].packing = 1; + break; + + default: + if (verbose) printf("DPX: bitsPerSample not supported: %d\n", bitsPerSample); + logImageClose(dpx); + return 0; } - dpx->pixelBuffer = malloc((dpx->lineBufferLength * 3 + 2) * sizeof(unsigned short)); - if (dpx->pixelBuffer == 0) { - if (verbose) d_printf("Couldn't malloc pixel buffer of size %d\n", - (dpx->width * dpx->depth + 2 + 2) * (int)sizeof(unsigned short)); - dpxClose(dpx); - return 0; - } - dpx->pixelBufferUsed = 0; - - /* find trailing part of filename */ - shortFilename = strrchr(filename, '/'); - if (shortFilename == 0) { - shortFilename = filename; + if (hasAlpha == 0) { + dpx->depth = 3; + dpx->element[0].depth = 3; + dpx->element[0].descriptor = descriptor_RGB; } else { - ++shortFilename; + dpx->depth = 4; + dpx->element[0].depth = 4; + dpx->element[0].descriptor = descriptor_RGBA; } - initDpxMainHeader(dpx, &header, shortFilename); - logImageGetByteConversionDefaults(&dpx->params); - /* Need set the file type before write the header! - * 2 - Linear - * 3 - Logarithmic - * - * Note that transfer characteristics is U8, don't need - * check the byte order. - */ - if (dpx->params.doLogarithm == 0) - header.imageInfo.channel[0].transfer_characteristics= 2; - else - header.imageInfo.channel[0].transfer_characteristics= 3; - if (fwrite(&header, sizeof(header), 1, dpx->file) == 0) { - if (verbose) d_printf("Couldn't write image header\n"); - dpxClose(dpx); + if (isLogarithmic == 0) { + dpx->element[0].transfer = transfer_Linear; + dpx->element[0].refHighQuantity = dpx->element[0].maxValue; + } + else { + dpx->element[0].transfer = transfer_PrintingDensity; + dpx->element[0].refHighQuantity = 2.048f; + + } + + dpx->element[0].refLowQuantity = 0; + dpx->element[0].refLowData = 0; + dpx->element[0].refHighData = dpx->element[0].maxValue; + + if (referenceWhite > 0) + dpx->referenceWhite = referenceWhite; + else + dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue; + + if (referenceBlack > 0) + dpx->referenceBlack = referenceBlack; + else + dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue; + + if (gamma > 0.0f) + dpx->gamma = gamma; + else + dpx->gamma = 1.7f; + + + shortFilename = strrchr(filename, '/'); + if (shortFilename == 0) + shortFilename = filename; + else + shortFilename++; + + dpx->file = BLI_fopen(filename, "wb"); + + if (dpx->file == 0) { + if (verbose) printf("DPX: Couldn't open file %s\n", filename); + logImageClose(dpx); return 0; } - dpx->fileYPos = 0; - setupLut(dpx); - dpx->getRow = 0; - dpx->setRow = &dpxSetRowBytes; - dpx->close = &dpxClose; + fillDpxMainHeader(dpx, &header, shortFilename, creator); + + if (fwrite(&header, sizeof(header), 1, dpx->file) == 0) { + if (verbose) printf("DPX: Couldn't write image header\n"); + logImageClose(dpx); + return 0; + } + + /* Header should be rounded to next 8k block + 6044 = 8092 - sizeof(DpxMainHeader) */ + memset(&pad, 0, 6044); + if (fwrite(&pad, 6044, 1, dpx->file) == 0) { + if (verbose) printf("DPX: Couldn't write image header\n"); + logImageClose(dpx); + return 0; + } return dpx; } - -void -dpxClose(DpxFile* dpx) { - - if (dpx == 0) { - return; - } - - if (dpx->file) { - fclose(dpx->file); - dpx->file = 0; - } - - if (dpx->lineBuffer) { - free(dpx->lineBuffer); - dpx->lineBuffer = 0; - } - - if (dpx->pixelBuffer) { - free(dpx->pixelBuffer); - dpx->pixelBuffer = 0; - } - - free(dpx); -} - -void -dpxDump(const char* filename) { - - DpxMainHeader header; - FILE* file; - - file = BLI_fopen(filename, "rb"); - if (file == 0) { - d_printf("Failed to open file \"%s\".\n", filename); - return; - } - - if (fread(&header, sizeof(header), 1, file) == 0) { - d_printf("Not enough data for header in \"%s\".\n", filename); - fclose(file); - return; - } - - fclose(file); - dumpDpxMainHeader(&header); -} diff --git a/source/blender/imbuf/intern/cineon/dpxlib.h b/source/blender/imbuf/intern/cineon/dpxlib.h index eb3937f2bf7..e910aaa61e1 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.h +++ b/source/blender/imbuf/intern/cineon/dpxlib.h @@ -1,60 +1,160 @@ /* - * DPX image file format library definitions. + * DPX image file format library definitions. * - * Copyright 1999 - 2002 David Hodson + * Copyright 1999 - 2002 David Hodson * - * 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 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. + * 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. + * 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. + * + * Contributor(s): Julien Enche. * */ -#ifndef __DPXLIB_H__ -#define __DPXLIB_H__ - /** \file blender/imbuf/intern/cineon/dpxlib.h * \ingroup imbcineon */ + +#ifndef __DPX_LIB_H__ +#define __DPX_LIB_H__ + #ifdef __cplusplus extern "C" { #endif #include "logImageCore.h" -typedef struct _Log_Image_File_t_ DpxFile; +#define DPX_FILE_MAGIC 0x53445058 +#define DPX_UNDEFINED_U8 0xFF +#define DPX_UNDEFINED_U16 0xFFFF +#define DPX_UNDEFINED_U32 0xFFFFFFFF +#define DPX_UNDEFINED_R32 0xFFFFFFFF +#define DPX_UNDEFINED_CHAR 0 -/* int functions return 0 for OK */ +typedef struct { + unsigned int magic_num; + unsigned int offset; + char version[8]; + unsigned int file_size; + unsigned int ditto_key; + unsigned int gen_hdr_size; + unsigned int ind_hdr_size; + unsigned int user_data_size; + char file_name[100]; + char creation_date[24]; + char creator[100]; + char project[200]; + char copyright[200]; + unsigned int key; + char reserved[104]; +} DpxFileHeader; -void dpxSetVerbose(int); +typedef struct { + unsigned int data_sign; + unsigned int ref_low_data; + float ref_low_quantity; + unsigned int ref_high_data; + float ref_high_quantity; + unsigned char descriptor; + unsigned char transfer; + unsigned char colorimetric; + unsigned char bits_per_sample; + unsigned short packing; + unsigned short encoding; + unsigned int data_offset; + unsigned int line_padding; + unsigned int element_padding; + char description[32]; +} DpxElementHeader; -DpxFile* dpxOpen(const char* filename); -DpxFile* dpxCreate(const char* filename, int xsize, int ysize, int channels); -DpxFile* dpxOpenFromMem(unsigned char *buffer, unsigned int size); -int dpxIsMemFileCineon(void *buffer); +typedef struct { + unsigned short orientation; + unsigned short elements_per_image; + unsigned int pixels_per_line; + unsigned int lines_per_element; + DpxElementHeader element[8]; + char reserved[52]; +} DpxImageHeader; -/* get/set scanline of converted bytes */ -int dpxGetRowBytes(DpxFile* dpx, unsigned short* row, int y); -int dpxSetRowBytes(DpxFile* dpx, const unsigned short* row, int y); +typedef struct { + unsigned int x_offset; + unsigned int y_offset; + float x_center; + float y_center; + unsigned int x_original_size; + unsigned int y_original_size; + char file_name[100]; + char creation_time[24]; + char input_device[32]; + char input_serial_number[32]; + unsigned short border_validity[4]; + unsigned int pixel_aspect_ratio[2]; + char reserved[28]; +} DpxOrientationHeader; -/* closes file and deletes data */ -void dpxClose(DpxFile* dpx); +typedef struct { + char film_manufacturer_id[2]; + char film_type[2]; + char edge_code_perforation_offset[2]; + char edge_code_prefix[6]; + char edge_code_count[4]; + char film_format[32]; + unsigned int frame_position; + unsigned int sequence_length; + unsigned int held_count; + float frame_rate; + float shutter_angle; + char frame_identification[32]; + char slate_info[100]; + char reserved[56]; +} DpxFilmHeader; -/* dumps file to stdout */ -void dpxDump(const char* filename); +typedef struct { + unsigned int time_code; + unsigned int user_bits; + unsigned char interlace; + unsigned char field_number; + unsigned char video_signal; + unsigned char padding; + float horizontal_sample_rate; + float vertical_sample_rate; + float frame_rate; + float time_offset; + float gamma; + float black_level; + float black_gain; + float breakpoint; + float white_level; + float integration_times; + unsigned char reserved[76]; +} DpxTelevisionHeader; + + +typedef struct { + DpxFileHeader fileHeader; + DpxImageHeader imageHeader; + DpxOrientationHeader orientationHeader; + DpxFilmHeader filmHeader; + DpxTelevisionHeader televisionHeader; +} DpxMainHeader; + +void dpxSetVerbose(int verbosity); +LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize); +LogImageFile *dpxCreate(const char *filename, int width, int height, int bitsPerSample, int hasAlpha, int isLogarithmic, int referenceWhite, int referenceBlack, float gamma, const char *creator); #ifdef __cplusplus } #endif -#endif /* __DPXLIB_H__ */ +#endif diff --git a/source/blender/imbuf/intern/cineon/logImageCore.c b/source/blender/imbuf/intern/cineon/logImageCore.c index f772cc7d477..3911e5c2ef3 100644 --- a/source/blender/imbuf/intern/cineon/logImageCore.c +++ b/source/blender/imbuf/intern/cineon/logImageCore.c @@ -1,21 +1,23 @@ /* - * Cineon image file format library routines. + * Cineon image file format library routines. * - * Copyright 1999,2000,2001 David Hodson + * Copyright 1999,2000,2001 David Hodson * - * 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 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. + * 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. + * 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. + * + * Contributor(s): Julien Enche. * */ @@ -23,223 +25,1407 @@ * \ingroup imbcineon */ + +#include "logmemfile.h" #include "logImageCore.h" +#include "dpxlib.h" +#include "cineonlib.h" -#include /* strftime() */ +#include +#include #include -/* Makes rint consistent in Windows and Linux: */ -#define rint(x) floor(x+0.5) -#ifdef WIN32 -#include -#else -#include -#include -#include -#include -#endif +#include "BLI_fileops.h" +#include "BLI_utildefines.h" -#if defined(__hpux) -/* These are macros in hpux */ -#ifdef htonl -#undef htonl -#undef htons -#undef ntohl -#undef ntohs -#endif -unsigned int htonl(h) unsigned int h; { return(h); } -unsigned short htons(h) unsigned short h; { return(h); } -unsigned int ntohl(n) unsigned int n; { return(n); } -unsigned short ntohs(n) unsigned short n; { return(n); } -#endif - - -/* obscure LogImage conversion */ -/* from 10 bit int to 0.0 - 1.0 */ -/* magic numbers left intact */ -static double -convertTo(int inp, int white, float gamma) { - /* return pow(pow(10.0, ((inp - white) * 0.002 / 0.6)), gamma); */ - return pow(10.0, (inp - white) * gamma * 0.002 / 0.6); +#include "MEM_guardedalloc.h" + +/* + * Declaration of static functions + */ + +static int logImageSetData8(LogImageFile *logImage, LogImageElement logElement, float *data); +static int logImageSetData10(LogImageFile *logImage, LogImageElement logElement, float *data); +static int logImageSetData12(LogImageFile *logImage, LogImageElement logElement, float *data); +static int logImageSetData16(LogImageFile *logImage, LogImageElement logElement, float *data); +static int logImageElementGetData(LogImageFile *dpx, LogImageElement logElement, float *data); +static int logImageElementGetData1(LogImageFile *dpx, LogImageElement logElement, float *data); +static int logImageElementGetData8(LogImageFile *dpx, LogImageElement logElement, float *data); +static int logImageElementGetData10(LogImageFile *dpx, LogImageElement logElement, float *data); +static int logImageElementGetData10Packed(LogImageFile *dpx, LogImageElement logElement, float *data); +static int logImageElementGetData12(LogImageFile *dpx, LogImageElement logElement, float *data); +static int logImageElementGetData12Packed(LogImageFile *dpx, LogImageElement logElement, float *data); +static int logImageElementGetData16(LogImageFile *dpx, LogImageElement logElement, float *data); +static int convertLogElementToRGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement, int dstIsLinearRGB); +static int convertRGBAToLogElement(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement, int srcIsLinearRGB); + + +/* + * For debug purpose + */ + +static int verbose = 0; + +void logImageSetVerbose(int verbosity) +{ + verbose = verbosity; + cineonSetVerbose(verbosity); + dpxSetVerbose(verbosity); } -static double -convertFrom(double inp, int white, float gamma) { - return white + log10(inp) / (gamma * 0.002 / 0.6); + +/* + * IO stuff + */ + +int logImageIsDpx(const void *buffer) +{ + unsigned int magicNum = *(unsigned int *)buffer; + return (magicNum == DPX_FILE_MAGIC || magicNum == swap_uint(DPX_FILE_MAGIC, 1)); } -/* set up the 10 bit to 8 bit and 8 bit to 10 bit tables */ -void -setupLut(LogImageFile *logImage) { +int logImageIsCineon(const void *buffer) +{ + unsigned int magicNum = *(unsigned int *)buffer; + return (magicNum == CINEON_FILE_MAGIC || magicNum == swap_uint(CINEON_FILE_MAGIC, 1)); +} - int i; - double f_black; - double scale; +LogImageFile *logImageOpenFromFile(const char *filename, int cineon) +{ + unsigned int magicNum; + FILE *f = BLI_fopen(filename, "rb"); - f_black = convertTo(logImage->params.blackPoint, logImage->params.whitePoint, logImage->params.gamma); - scale = 255.0 / (1.0 - f_black); + (void)cineon; - for (i = 0; i <= logImage->params.blackPoint; ++i) { - logImage->lut10[i] = 0; - } - for (; i < logImage->params.whitePoint; ++i) { - double f_i; - f_i = convertTo(i, logImage->params.whitePoint, logImage->params.gamma); - logImage->lut10[i] = (int)rint(scale * (f_i - f_black)); - } - for (; i < 1024; ++i) { - logImage->lut10[i] = 255; + if (f == 0) + return 0; + + if (fread(&magicNum, sizeof(unsigned int), 1, f) != 1) { + fclose(f); + return 0; } - for (i = 0; i < 256; ++i) { - double f_i = f_black + (i / 255.0) * (1.0 - f_black); - logImage->lut8[i] = convertFrom(f_i, logImage->params.whitePoint, logImage->params.gamma); + fclose(f); + + if (logImageIsDpx(&magicNum)) + return dpxOpen((const unsigned char *)filename, 0, 0); + else if (logImageIsCineon(&magicNum)) + return cineonOpen((const unsigned char *)filename, 0, 0); + + return 0; +} + +LogImageFile *logImageOpenFromMemory(const unsigned char *buffer, unsigned int size) +{ + if (logImageIsDpx(buffer)) + return dpxOpen(buffer, 1, size); + else if (logImageIsCineon(buffer)) + return cineonOpen(buffer, 1, size); + + return 0; +} + +LogImageFile *logImageCreate(const char *filename, int cineon, int width, int height, int bitsPerSample, + int isLogarithmic, int hasAlpha, int referenceWhite, int referenceBlack, + float gamma, const char *creator) +{ + /* referenceWhite, referenceBlack and gamma values are only supported for DPX file */ + if (cineon) + return cineonCreate(filename, width, height, bitsPerSample, creator); + else + return dpxCreate(filename, width, height, bitsPerSample, isLogarithmic, hasAlpha, + referenceWhite, referenceBlack, gamma, creator); + + return 0; +} + +void logImageClose(LogImageFile *logImage) +{ + if (logImage != 0) { + if (logImage->file) { + fclose(logImage->file); + logImage->file = 0; + } + MEM_freeN(logImage); } } -/* set up the 10 bit to 16 bit and 16 bit to 10 bit tables */ -void -setupLut16(LogImageFile *logImage) { +void logImageGetSize(LogImageFile *logImage, int *width, int *height, int *depth) +{ + *width = logImage->width; + *height = logImage->height; + *depth = logImage->depth; +} - int i; - double f_black; - double scale; - f_black = convertTo(logImage->params.blackPoint, logImage->params.whitePoint, logImage->params.gamma); - scale = 65535.0 / (1.0 - f_black); +/* + * Helper + */ - for (i = 0; i <= logImage->params.blackPoint; ++i) { - logImage->lut10_16[i] = 0; - } - for (; i < logImage->params.whitePoint; ++i) { - double f_i; - f_i = convertTo(i, logImage->params.whitePoint, logImage->params.gamma); - logImage->lut10_16[i] = (int)rint(scale * (f_i - f_black)); - } - for (; i < 1024; ++i) { - logImage->lut10_16[i] = 65535; - } +unsigned int getRowLength(int width, LogImageElement logElement) +{ + /* return the row length in bytes according to width and packing method */ + switch (logElement.bitsPerSample) { + case 1: + return ((width * logElement.depth - 1) / 32 + 1) * 4; - for (i = 0; i < 65536; ++i) { - double f_i = f_black + (i / 65535.0) * (1.0 - f_black); - logImage->lut16_16[i] = convertFrom(f_i, logImage->params.whitePoint, logImage->params.gamma); + case 8: + return ((width * logElement.depth - 1) / 4 + 1) * 4; + + case 10: + if (logElement.packing == 0) + return ((width * logElement.depth * 10 - 1) / 32 + 1) * 4; + else if (logElement.packing == 1 || logElement.packing == 2) + return ((width * logElement.depth - 1) / 3 + 1) * 4; + + case 12: + if (logElement.packing == 0) + return ((width * logElement.depth * 12 - 1) / 32 + 1) * 4; + else if (logElement.packing == 1 || logElement.packing == 2) + return width * logElement.depth * 2; + + case 16: + return width * logElement.depth * 2; + + default: + return 0; } } -/* how many longwords to hold this many pixels? */ -int -pixelsToLongs(int numPixels) { - return (numPixels + 2) / 3; + +/* + * Data writing + */ + +int logImageSetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB) +{ + float *elementData; + int returnValue; + + elementData = (float *)MEM_mallocN(logImage->width * logImage->height * logImage->depth * sizeof(float), __func__); + if (elementData == 0) + return 1; + + if (convertRGBAToLogElement(data, elementData, logImage, logImage->element[0], dataIsLinearRGB) != 0) { + MEM_freeN(elementData); + return 1; + } + + switch (logImage->element[0].bitsPerSample) { + case 8: + returnValue = logImageSetData8(logImage, logImage->element[0], elementData); + break; + + case 10: + returnValue = logImageSetData10(logImage, logImage->element[0], elementData); + break; + + case 12: + returnValue = logImageSetData12(logImage, logImage->element[0], elementData); + break; + + case 16: + returnValue = logImageSetData16(logImage, logImage->element[0], elementData); + break; + + default: + returnValue = 1; + break; + } + + MEM_freeN(elementData); + return returnValue; } -/* byte reversed float */ +static int logImageSetData8(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int rowLength = getRowLength(logImage->width, logElement); + unsigned char *row; + int x, y; -typedef union { - U32 i; - R32 f; -} Hack; + row = (unsigned char *)MEM_mallocN(rowLength, __func__); + if (row == 0) { + if (verbose) printf("DPX/Cineon: Cannot allocate row.\n"); + return 1; + } + memset(row, 0, rowLength); -R32 -htonf(R32 f) { - Hack hack; - hack.f = f; - hack.i = htonl(hack.i); - return hack.f; + for (y = 0; y < logImage->height; y++) { + for (x = 0; x < logImage->width * logImage->depth; x++) + row[x] = (unsigned char)float_uint(data[y * logImage->width * logImage->depth + x], 255); + + if (logimage_fwrite(row, rowLength, 1, logImage) == 0) { + if (verbose) printf("DPX/Cineon: Error while writing file.\n"); + MEM_freeN(row); + return 1; + } + } + MEM_freeN(row); + return 0; } -R32 -ntohf(R32 f) { - Hack hack; - hack.f = f; - hack.i = ntohl(hack.i); - return hack.f; +static int logImageSetData10(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int rowLength = getRowLength(logImage->width, logElement); + unsigned int pixel, index; + unsigned int *row; + int x, y, offset; + + row = (unsigned int *)MEM_mallocN(rowLength, __func__); + if (row == 0) { + if (verbose) printf("DPX/Cineon: Cannot allocate row.\n"); + return 1; + } + + for (y = 0; y < logImage->height; y++) { + offset = 22; + index = 0; + pixel = 0; + + for (x = 0; x < logImage->width * logImage->depth; x++) { + pixel |= (unsigned int)float_uint(data[y * logImage->width * logImage->depth + x], 1023) << offset; + offset -= 10; + if (offset < 0) { + row[index] = swap_uint(pixel, logImage->isMSB); + index++; + pixel = 0; + offset = 22; + } + } + if (pixel != 0) + row[index] = swap_uint(pixel, logImage->isMSB); + + if (logimage_fwrite(row, rowLength, 1, logImage) == 0) { + if (verbose) printf("DPX/Cineon: Error while writing file.\n"); { + MEM_freeN(row); + return 1; + } + } + } + MEM_freeN(row); + return 0; } -#define UNDEF_FLOAT 0x7F800000 +static int logImageSetData12(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int rowLength = getRowLength(logImage->width, logElement); + unsigned short *row; + int x, y; -R32 -undefined(void) { - Hack hack; - hack.i = UNDEF_FLOAT; - return hack.f; + row = (unsigned short *)MEM_mallocN(rowLength, __func__); + if (row == 0) { + if (verbose) printf("DPX/Cineon: Cannot allocate row.\n"); + return 1; + } + + for (y = 0; y < logImage->height; y++) { + for (x = 0; x < logImage->width * logImage->depth; x++) + row[x] = swap_ushort(((unsigned short)float_uint(data[y * logImage->width * logImage->depth + x], 4095)) << 4, logImage->isMSB); + + if (logimage_fwrite(row, rowLength, 1, logImage) == 0) { + if (verbose) printf("DPX/Cineon: Error while writing file.\n"); + MEM_freeN(row); + return 1; + } + } + MEM_freeN(row); + return 0; } -/* reverse an endian-swapped U16 */ -U16 -reverseU16(U16 value) { +static int logImageSetData16(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int rowLength = getRowLength(logImage->width, logElement); + unsigned short *row; + int x, y; - union { - U16 whole; - char part[2]; - } buff; - char temp; - buff.whole = value; - temp = buff.part[0]; - buff.part[0] = buff.part[1]; - buff.part[1] = temp; - return buff.whole; + row = (unsigned short *)MEM_mallocN(rowLength, __func__); + if (row == 0) { + if (verbose) printf("DPX/Cineon: Cannot allocate row.\n"); + return 1; + } + + for (y = 0; y < logImage->height; y++) { + for (x = 0; x < logImage->width * logImage->depth; x++) + row[x] = swap_ushort((unsigned short)float_uint(data[y * logImage->width * logImage->depth + x], 65535), logImage->isMSB); + + if (logimage_fwrite(row, rowLength, 1, logImage) == 0) { + if (verbose) printf("DPX/Cineon: Error while writing file.\n"); + MEM_freeN(row); + return 1; + } + } + MEM_freeN(row); + return 0; } -/* reverse an endian-swapped U32 */ -U32 -reverseU32(U32 value) { - union { - U32 whole; - char part[4]; - } buff; - char temp; - buff.whole = value; - temp = buff.part[0]; - buff.part[0] = buff.part[3]; - buff.part[3] = temp; - temp = buff.part[1]; - buff.part[1] = buff.part[2]; - buff.part[2] = temp; - return buff.whole; +/* + * Data reading + */ + +int logImageGetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB) +{ + /* Fills data with 32 bits float RGBA values */ + int i, j, returnValue, sortedElementData[8], hasAlpha; + float *elementData[8]; + float *elementData_ptr[8]; + float *mergedData; + unsigned int sampleIndex; + LogImageElement mergedElement; + + /* Determine the depth of the picture and if there's a separate alpha element. + If the element is supported, load it into an unsigned ints array. */ + memset(&elementData, 0, 8 * sizeof(float *)); + hasAlpha = 0; + + for (i = 0; i < logImage->numElements; i++) { + /* descriptor_Depth and descriptor_Composite are not supported */ + if (logImage->element[i].descriptor != descriptor_Depth && logImage->element[i].descriptor != descriptor_Composite) { + /* Allocate memory */ + elementData[i] = (float *)MEM_mallocN(logImage->width * logImage->height * logImage->element[i].depth * sizeof(float), __func__); + if (elementData[i] == 0) { + if (verbose) printf("DPX/Cineon: Cannot allocate memory for elementData[%d]\n.", i); + for (j = 0; j < i; j++) + if (elementData[j] != 0) + MEM_freeN(elementData[j]); + return 1; + } + elementData_ptr[i] = elementData[i]; + + /* Load data */ + if (logImageElementGetData(logImage, logImage->element[i], elementData[i]) != 0) { + if (verbose) printf("DPX/Cineon: Cannot read elementData[%d]\n.", i); + for (j = 0; j < i; j++) + if (elementData[j] != 0) + MEM_freeN(elementData[j]); + return 1; + } + } + + if (logImage->element[i].descriptor == descriptor_Alpha) + hasAlpha = 1; + } + + /* only one element, easy case, no need to do anything */ + if (logImage->numElements == 1) { + returnValue = convertLogElementToRGBA(elementData[0], data, logImage, logImage->element[0], dataIsLinearRGB); + MEM_freeN(elementData[0]); + } + else { + /* The goal here is to merge every elements into only one + * to recreate a classic 16 bits RGB, RGBA or YCbCr element. + * Unsupported elements are skipped (depth, composite) */ + + memcpy(&mergedElement, &logImage->element[0], sizeof(LogImageElement)); + mergedElement.descriptor = -1; + mergedElement.depth = logImage->depth; + memset(&sortedElementData, -1, 8 * sizeof(int)); + + /* Try to know how to assemble the elements */ + for (i = 0; i < logImage->numElements; i++) { + switch (logImage->element[i].descriptor) { + case descriptor_Red: + case descriptor_RGB: + if (hasAlpha == 0) + mergedElement.descriptor = descriptor_RGB; + else + mergedElement.descriptor = descriptor_RGBA; + + sortedElementData[0] = i; + break; + + case descriptor_Green: + if (hasAlpha == 0) + mergedElement.descriptor = descriptor_RGB; + else + mergedElement.descriptor = descriptor_RGBA; + + sortedElementData[1] = i; + break; + + case descriptor_Blue: + if (hasAlpha == 0) + mergedElement.descriptor = descriptor_RGB; + else + mergedElement.descriptor = descriptor_RGBA; + + sortedElementData[2] = i; + break; + + case descriptor_Alpha: + /* Alpha component is always the last one */ + sortedElementData[mergedElement.depth - 1] = i; + break; + + case descriptor_Luminance: + if (mergedElement.descriptor == -1) + if (hasAlpha == 0) + mergedElement.descriptor = descriptor_Luminance; + else + mergedElement.descriptor = descriptor_YA; + else if (mergedElement.descriptor == descriptor_Chrominance) { + if (mergedElement.depth == 2) + mergedElement.descriptor = descriptor_CbYCrY; + else if (mergedElement.depth == 3) + if (hasAlpha == 0) + mergedElement.descriptor = descriptor_CbYCr; + else + mergedElement.descriptor = descriptor_CbYACrYA; + else if (mergedElement.depth == 4) + mergedElement.descriptor = descriptor_CbYCrA; + } + + /* Y component always in 1 except if it's alone or with alpha */ + if (mergedElement.depth == 1 || (mergedElement.depth == 2 && hasAlpha == 1)) + sortedElementData[0] = i; + else + sortedElementData[1] = i; + break; + + case descriptor_Chrominance: + if (mergedElement.descriptor == -1) + mergedElement.descriptor = descriptor_Chrominance; + else if (mergedElement.descriptor == descriptor_Luminance) { + if (mergedElement.depth == 2) + mergedElement.descriptor = descriptor_CbYCrY; + else if (mergedElement.depth == 3) + if (hasAlpha == 0) + mergedElement.descriptor = descriptor_CbYCr; + else + mergedElement.descriptor = descriptor_CbYACrYA; + else if (mergedElement.depth == 4) + mergedElement.descriptor = descriptor_CbYCrA; + } + + /* Cb and Cr always in 0 or 2 */ + if (sortedElementData[0] == -1) + sortedElementData[0] = i; + else + sortedElementData[2] = i; + break; + + case descriptor_CbYCr: + if (hasAlpha == 0) + mergedElement.descriptor = descriptor_CbYCr; + else + mergedElement.descriptor = descriptor_CbYCrA; + + sortedElementData[0] = i; + break; + + case descriptor_RGBA: + case descriptor_ABGR: + case descriptor_CbYACrYA: + case descriptor_CbYCrY: + case descriptor_CbYCrA: + /* I don't think these ones can be seen in a planar image */ + mergedElement.descriptor = logImage->element[i].descriptor; + sortedElementData[0] = i; + break; + + case descriptor_Depth: + case descriptor_Composite: + /* Not supported */ + break; + } + } + + mergedData = (float *)MEM_mallocN(logImage->width * logImage->height * mergedElement.depth * sizeof(float), __func__); + if (mergedData == 0) { + if (verbose) printf("DPX/Cineon: Cannot allocate mergedData.\n"); + for (i = 0; i < logImage->numElements; i++) + if (elementData[i] != 0) + MEM_freeN(elementData[i]); + return 1; + } + + sampleIndex = 0; + while (sampleIndex < logImage->width * logImage->height * mergedElement.depth) { + for (i = 0; i < logImage->numElements; i++) + for (j = 0; j < logImage->element[sortedElementData[i]].depth; j++) + mergedData[sampleIndex++] = *(elementData_ptr[sortedElementData[i]]++); + } + + /* Done with elements data, clean-up */ + for (i = 0; i < logImage->numElements; i++) + if (elementData[i] != 0) + MEM_freeN(elementData[i]); + + returnValue = convertLogElementToRGBA(mergedData, data, logImage, mergedElement, dataIsLinearRGB); + MEM_freeN(mergedData); + } + return returnValue; } -/* reverse an endian-swapped R32 */ -R32 -reverseR32(R32 value) { +static int logImageElementGetData(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + switch (logElement.bitsPerSample) { + case 1: + return logImageElementGetData1(logImage, logElement, data); - union { - R32 whole; - char part[4]; - } buff; - char temp; - buff.whole = value; - temp = buff.part[0]; - buff.part[0] = buff.part[3]; - buff.part[3] = temp; - temp = buff.part[1]; - buff.part[1] = buff.part[2]; - buff.part[2] = temp; - return buff.whole; -} + case 8: + return logImageElementGetData8(logImage, logElement, data); -#if 0 -/* bytes per line for images packed 3 10 bit pixels to 32 bits, 32 bit aligned */ -int -bytesPerLine_10_4(int numPixels) { - return ((numPixels + 2) / 3) * 4; -} + case 10: + if (logElement.packing == 0) + return logImageElementGetData10Packed(logImage, logElement, data); + else if (logElement.packing == 1 || logElement.packing == 2) + return logImageElementGetData10(logImage, logElement, data); -void -seekLine_noPadding(LogImageFile* logImage, int lineNumber) { - int fileOffset = bytesPerLine_10_4(lineNumber * logImage->width * logImage->depth); - int filePos = logImage->imageOffset + fileOffset; - if (fseek(logImage->file, filePos, SEEK_SET) != 0) { - /* complain? */ + case 12: + if (logElement.packing == 0) + return logImageElementGetData12Packed(logImage, logElement, data); + else if (logElement.packing == 1 || logElement.packing == 2) + return logImageElementGetData12(logImage, logElement, data); + + case 16: + return logImageElementGetData16(logImage, logElement, data); + + default: + /* format not supported */ + return 1; } } -void -seekLine_padding(LogImageFile* logImage, int lineNumber) { - int fileOffset = lineNumber * bytesPerLine_10_4(logImage->width * logImage->depth); - int filePos = logImage->imageOffset + fileOffset; - if (fseek(logImage->file, filePos, SEEK_SET) != 0) { - /* complain? */ +static int logImageElementGetData1(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int pixel; + int x, y, offset; + + /* seek at the right place */ + if (logimage_fseek(logImage, logElement.dataOffset, SEEK_SET) != 0) { + if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset); + return 1; + } + + /* read 1 bit data padded to 32 bits */ + for (y = 0; y < logImage->height; y++) { + for (x = 0; x < logImage->width * logElement.depth; x += 32) { + if (logimage_read_uint(&pixel, logImage) != 0) { + if (verbose) printf("DPX/Cineon: EOF reached\n"); + return 1; + } + pixel = swap_uint(pixel, logImage->isMSB); + for (offset = 0; offset < 32 && x + offset < logImage->width; offset++) + data[y * logImage->width * logElement.depth + x + offset] = (float)((pixel >> offset) & 0x01); + } + } + return 0; +} + +static int logImageElementGetData8(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int rowLength = getRowLength(logImage->width, logElement); + unsigned char pixel; + int x, y; + + /* extract required pixels */ + for (y = 0; y < logImage->height; y++) { + /* 8 bits are 32-bits padded so we need to seek at each row */ + if (logimage_fseek(logImage, logElement.dataOffset + y * rowLength, SEEK_SET) != 0) { + if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset + y * rowLength); + return 1; + } + + for (x = 0; x < logImage->width * logElement.depth; x++) { + if (logimage_read_uchar(&pixel, logImage) != 0) { + if (verbose) printf("DPX/Cineon: EOF reached\n"); + return 1; + } + data[y * logImage->width * logElement.depth + x] = (float)pixel / 255.0f; + } + } + return 0; +} + +static int logImageElementGetData10(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int pixel; + int x, y, offset; + + /* seek to data */ + if (logimage_fseek(logImage, logElement.dataOffset, SEEK_SET) != 0) { + if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset); + return 1; + } + + if (logImage->depth == 1 && logImage->srcFormat == format_DPX) { + for (y = 0; y < logImage->height; y++) { + offset = 32; + for (x = 0; x < logImage->width * logElement.depth; x++) { + /* we need to read the next long */ + if (offset >= 30) { + if (logElement.packing == 1) + offset = 2; + else if (logElement.packing == 2) + offset = 0; + + if (logimage_read_uint(&pixel, logImage) != 0) { + if (verbose) printf("DPX/Cineon: EOF reached\n"); + return 1; + } + pixel = swap_uint(pixel, logImage->isMSB); + } + data[y * logImage->width * logElement.depth + x] = (float)((pixel >> offset) & 0x3ff) / 1023.0f; + offset += 10; + } + } + } + else { + for (y = 0; y < logImage->height; y++) { + offset = -1; + for (x = 0; x < logImage->width * logElement.depth; x++) { + /* we need to read the next long */ + if (offset < 0) { + if (logElement.packing == 1) + offset = 22; + else if (logElement.packing == 2) + offset = 20; + + if (logimage_read_uint(&pixel, logImage) != 0) { + if (verbose) printf("DPX/Cineon: EOF reached\n"); + return 1; + } + pixel = swap_uint(pixel, logImage->isMSB); + } + data[y * logImage->width * logElement.depth + x] = (float)((pixel >> offset) & 0x3ff) / 1023.0f; + offset -= 10; + } + } + } + + return 0; +} + +static int logImageElementGetData10Packed(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int rowLength = getRowLength(logImage->width, logElement); + unsigned int pixel, oldPixel; + int offset, offset2, x, y; + + /* converting bytes to pixels */ + for (y = 0; y < logImage->height; y++) { + /* seek to data */ + if (logimage_fseek(logImage, y * rowLength + logElement.dataOffset, SEEK_SET) != 0) { + if (verbose) printf("DPX/Cineon: Couldn't seek at %u\n", y * rowLength + logElement.dataOffset); + return 1; + } + + oldPixel = 0; + offset = 0; + offset2 = 0; + + for (x = 0; x < logImage->width * logElement.depth; x++) { + if (offset2 != 0) { + offset = 10 - offset2; + offset2 = 0; + oldPixel = 0; + } + else if (offset == 32) { + offset = 0; + } + else if (offset + 10 > 32) { + /* next pixel is on two different longs */ + oldPixel = (pixel >> offset); + offset2 = 32 - offset; + offset = 0; + } + + if (offset == 0) { + /* we need to read the next long */ + if (logimage_read_uint(&pixel, logImage) != 0) { + if (verbose) printf("DPX/Cineon: EOF reached\n"); + return 1; + } + pixel = swap_uint(pixel, logImage->isMSB); + } + data[y * logImage->width * logElement.depth + x] = (float)((((pixel << offset2) >> offset) & 0x3ff) | oldPixel) / 1023.0f; + offset += 10; + } + } + return 0; +} + +static int logImageElementGetData12(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int sampleIndex; + unsigned int numSamples = logImage->width * logImage->height * logElement.depth; + unsigned short pixel; + + /* seek to data */ + if (logimage_fseek(logImage, logElement.dataOffset, SEEK_SET) != 0) { + if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset); + return 1; + } + + /* convert bytes to pixels */ + sampleIndex = 0; + + for (sampleIndex = 0; sampleIndex < numSamples; sampleIndex++) { + if (logimage_read_ushort(&pixel, logImage) != 0) { + if (verbose) printf("DPX/Cineon: EOF reached\n"); + return 1; + } + pixel = swap_ushort(pixel, logImage->isMSB); + + if (logElement.packing == 1) /* padded to the right */ + data[sampleIndex] = (float)(pixel >> 4) / 4095.0f; + else if (logElement.packing == 2) /* padded to the left */ + data[sampleIndex] = (float)pixel / 4095.0f; + } + return 0; +} + +static int logImageElementGetData12Packed(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int rowLength = getRowLength(logImage->width, logElement); + unsigned int pixel, oldPixel; + int offset, offset2, x, y; + + /* converting bytes to pixels */ + for (y = 0; y < logImage->height; y++) { + /* seek to data */ + if (logimage_fseek(logImage, y * rowLength + logElement.dataOffset, SEEK_SET) != 0) { + if (verbose) printf("DPX/Cineon: Couldn't seek at %u\n", y * rowLength + logElement.dataOffset); + return 1; + } + + oldPixel = 0; + offset = 0; + offset2 = 0; + + for (x = 0; x < logImage->width * logElement.depth; x++) { + if (offset2 != 0) { + offset = 12 - offset2; + offset2 = 0; + oldPixel = 0; + } + else if (offset == 32) { + offset = 0; + } + else if (offset + 12 > 32) { + /* next pixel is on two different longs */ + oldPixel = (pixel >> offset); + offset2 = 32 - offset; + offset = 0; + } + + if (offset == 0) { + /* we need to read the next long */ + if (logimage_read_uint(&pixel, logImage) != 0) { + if (verbose) printf("DPX/Cineon: EOF reached\n"); + return 1; + } + pixel = swap_uint(pixel, logImage->isMSB); + } + data[y * logImage->width * logElement.depth + x] = (float)((((pixel << offset2) >> offset) & 0xfff) | oldPixel) / 4095.0f; + offset += 12; + } + } + return 0; +} + +static int logImageElementGetData16(LogImageFile *logImage, LogImageElement logElement, float *data) +{ + unsigned int numSamples = logImage->width * logImage->height * logElement.depth; + unsigned int sampleIndex; + unsigned short pixel; + + /* seek to data */ + if (logimage_fseek(logImage, logElement.dataOffset, SEEK_SET) != 0) { + if (verbose) printf("DPX/Cineon: Couldn't seek at %d\n", logElement.dataOffset); + return 1; + } + + for (sampleIndex = 0; sampleIndex < numSamples; sampleIndex++) { + if (logimage_read_ushort(&pixel, logImage) != 0) { + if (verbose) printf("DPX/Cineon: EOF reached\n"); + return 1; + } + pixel = swap_ushort(pixel, logImage->isMSB); + data[sampleIndex] = (float)pixel / 65535.0f; + } + + return 0; +} + + +/* + * Color conversion + */ + +static int getYUVtoRGBMatrix(float *matrix, LogImageElement logElement) +{ + float scaleY, scaleCbCr; + float refHighData = (float)logElement.refHighData / logElement.maxValue; + float refLowData = (float)logElement.refLowData / logElement.maxValue; + + scaleY = 1.0f / (refHighData - refLowData); + scaleCbCr = scaleY * ((940.0f - 64.0f) / (960.0f - 64.0f)); + + switch (logElement.transfer) { + case 2: /* linear */ + matrix[0] = 1.0f * scaleY; + matrix[1] = 1.0f * scaleCbCr; + matrix[2] = 1.0f * scaleCbCr; + matrix[3] = 1.0f * scaleY; + matrix[4] = 1.0f * scaleCbCr; + matrix[5] = 1.0f * scaleCbCr; + matrix[6] = 1.0f * scaleY; + matrix[7] = 1.0f * scaleCbCr; + matrix[8] = 1.0f * scaleCbCr; + return 0; + + case 5: /* SMPTE 240M */ + matrix[0] = 1.0000f * scaleY; + matrix[1] = 0.0000f * scaleCbCr; + matrix[2] = 1.5756f * scaleCbCr; + matrix[3] = 1.0000f * scaleY; + matrix[4] = -0.2253f * scaleCbCr; + matrix[5] = -0.5000f * scaleCbCr; + matrix[6] = 1.0000f * scaleY; + matrix[7] = 1.8270f * scaleCbCr; + matrix[8] = 0.0000f * scaleCbCr; + return 0; + + case 6: /* CCIR 709-1 */ + matrix[0] = 1.000000f * scaleY; + matrix[1] = 0.000000f * scaleCbCr; + matrix[2] = 1.574800f * scaleCbCr; + matrix[3] = 1.000000f * scaleY; + matrix[4] = -0.187324f * scaleCbCr; + matrix[5] = -0.468124f * scaleCbCr; + matrix[6] = 1.000000f * scaleY; + matrix[7] = 1.855600f * scaleCbCr; + matrix[8] = 0.000000f * scaleCbCr; + return 0; + + case 7: /* CCIR 601 */ + case 8: /* I'm not sure 7 and 8 should share the same matrix */ + matrix[0] = 1.000000f * scaleY; + matrix[1] = 0.000000f * scaleCbCr; + matrix[2] = 1.402000f * scaleCbCr; + matrix[3] = 1.000000f * scaleY; + matrix[4] = -0.344136f * scaleCbCr; + matrix[5] = -0.714136f * scaleCbCr; + matrix[6] = 1.000000f * scaleY; + matrix[7] = 1.772000f * scaleCbCr; + matrix[8] = 0.000000f * scaleCbCr; + return 0; + + default: + return 1; } } -#endif + +static void getLinToLogLut(float *lut, LogImageFile *logImage, LogImageElement logElement) +{ + float gain, negativeFilmGamma, offset, step; + unsigned int i; + + negativeFilmGamma = 0.6; + step = logElement.refHighQuantity / logElement.maxValue; + gain = logElement.maxValue / (1.0f - powf(10, (logImage->referenceBlack - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f)); + offset = gain - logElement.maxValue; + + for (i = 0; i < (int)(logElement.maxValue + 1); i++) + lut[i] = (logImage->referenceWhite + log10f(powf((i + offset) / gain, 1.7f / logImage->gamma)) / (step / negativeFilmGamma)) / logElement.maxValue; +} + +static void getLogToLinLut(float *lut, LogImageFile *logImage, LogImageElement logElement) +{ + float breakPoint, gain, kneeGain, kneeOffset, negativeFilmGamma, offset, step, softClip; + /* float filmGamma; unused */ + unsigned int i; + + /* Building the Log -> Lin LUT */ + step = logElement.refHighQuantity / logElement.maxValue; + negativeFilmGamma = 0.6; + + /* these are default values */ + /* filmGamma = 2.2f; unused */ + softClip = 0; + + breakPoint = logImage->referenceWhite - softClip; + gain = logElement.maxValue / (1.0f - powf(10, (logImage->referenceBlack - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f)); + offset = gain - logElement.maxValue; + kneeOffset = powf(10, (breakPoint - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f) * gain - offset; + kneeGain = (logElement.maxValue - kneeOffset) / powf(5 * softClip, softClip / 100); + + for (i = 0; i < (int)(logElement.maxValue + 1); i++) { + if (i < logImage->referenceBlack) + lut[i] = 0.0f; + else if (i > breakPoint) + lut[i] = (powf(i - breakPoint, softClip / 100) * kneeGain + kneeOffset) / logElement.maxValue; + else + lut[i] = (powf(10, ((float)i - logImage->referenceWhite) * step / negativeFilmGamma * logImage->gamma / 1.7f) * gain - offset) / logElement.maxValue; + } +} + +static void getLinToSrgbLut(float *lut, LogImageElement logElement) +{ + unsigned int i; + float col; + + for (i = 0; i < (int)(logElement.maxValue + 1); i++) { + col = (float)i / logElement.maxValue; + if (col < 0.0031308f) + lut[i] = (col < 0.0f) ? 0.0f : col * 12.92f; + else + lut[i] = 1.055f * powf(col, 1.0f / 2.4f) - 0.055f; + } +} + +static void getSrgbToLinLut(float *lut, LogImageElement logElement) +{ + unsigned int i; + float col; + + for (i = 0; i < (int)(logElement.maxValue + 1); i++) { + col = (float)i / logElement.maxValue; + if (col < 0.04045f) + lut[i] = (col < 0.0f) ? 0.0f : col * (1.0f / 12.92f); + else + lut[i] = powf((col + 0.055f) * (1.0f / 1.055f), 2.4f); + } +} + +static int convertRGBA_RGB(float *src, float *dst, LogImageFile *logImage, + LogImageElement logElement, int elementIsSource) +{ + unsigned int i; + float lut[65536]; + float *src_ptr = src; + float *dst_ptr = dst; + + switch (logElement.transfer) { + case transfer_UserDefined: + case transfer_Linear: + case transfer_Logarithmic: + for (i = 0; i < logImage->width * logImage->height; i++) { + *(dst_ptr++) = *(src_ptr++); + *(dst_ptr++) = *(src_ptr++); + *(dst_ptr++) = *(src_ptr++); + src_ptr++; + } + return 0; + + case transfer_PrintingDensity: + if (elementIsSource == 1) + getLogToLinLut((float *)&lut, logImage, logElement); + else + getLinToLogLut((float *)&lut, logImage, logElement); + + for (i = 0; i < logImage->width * logImage->height; i++) { + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + src_ptr++; + } + return 0; + + default: + return 1; + } +} + +static int convertRGB_RGBA(float *src, float *dst, LogImageFile *logImage, + LogImageElement logElement, int elementIsSource) +{ + unsigned int i; + float lut[65536]; + float *src_ptr = src; + float *dst_ptr = dst; + + switch (logElement.transfer) { + case transfer_UserDefined: + case transfer_Linear: + case transfer_Logarithmic: + for (i = 0; i < logImage->width * logImage->height; i++) { + *(dst_ptr++) = *(src_ptr++); + *(dst_ptr++) = *(src_ptr++); + *(dst_ptr++) = *(src_ptr++); + *(dst_ptr++) = 1.0f; + } + return 0; + + case transfer_PrintingDensity: + if (elementIsSource == 1) + getLogToLinLut((float *)&lut, logImage, logElement); + else + getLinToLogLut((float *)&lut, logImage, logElement); + + for (i = 0; i < logImage->width * logImage->height; i++) { + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = 1.0f; + } + return 0; + + default: + return 1; + } +} + +static int convertRGBA_RGBA(float *src, float *dst, LogImageFile *logImage, + LogImageElement logElement, int elementIsSource) +{ + unsigned int i; + float lut[65536]; + float *src_ptr = src; + float *dst_ptr = dst; + + switch (logElement.transfer) { + case transfer_UserDefined: + case transfer_Linear: + case transfer_Logarithmic: + memcpy(dst, src, 4 * logImage->width * logImage->height * sizeof(float)); + return 0; + + case transfer_PrintingDensity: + if (elementIsSource == 1) + getLogToLinLut((float *)&lut, logImage, logElement); + else + getLinToLogLut((float *)&lut, logImage, logElement); + + for (i = 0; i < logImage->width * logImage->height; i++) { + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = *(src_ptr++); + } + return 0; + + default: + return 1; + } +} + +static int convertABGR_RGBA(float *src, float *dst, LogImageFile *logImage, + LogImageElement logElement, int elementIsSource) +{ + unsigned int i; + float lut[65536]; + float *src_ptr = src; + float *dst_ptr = dst; + + switch (logElement.transfer) { + case transfer_UserDefined: + case transfer_Linear: + case transfer_Logarithmic: + for (i = 0; i < logImage->width * logImage->height; i++) { + src_ptr += 4; + *(dst_ptr++) = *(src_ptr--); + *(dst_ptr++) = *(src_ptr--); + *(dst_ptr++) = *(src_ptr--); + *(dst_ptr++) = *(src_ptr--); + src_ptr += 4; + } + return 0; + + case transfer_PrintingDensity: + if (elementIsSource == 1) + getLogToLinLut((float *)&lut, logImage, logElement); + else + getLinToLogLut((float *)&lut, logImage, logElement); + + for (i = 0; i < logImage->width * logImage->height; i++) { + src_ptr += 4; + *(dst_ptr++) = lut[float_uint(*(src_ptr--), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr--), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr--), logElement.maxValue)]; + *(dst_ptr++) = *(src_ptr--); + src_ptr += 4; + } + return 0; + + default: + return 1; + } +} + +static int convertCbYCr_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement) +{ + unsigned int i; + float conversionMatrix[9], refLowData, y, cb, cr; + float *src_ptr = src; + float *dst_ptr = dst; + + if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0) + return 1; + + refLowData = (float)logElement.refLowData / logElement.maxValue; + + for (i = 0; i < logImage->width * logImage->height; i++) { + cb = *(src_ptr++) - 0.5f; + y = *(src_ptr++) - refLowData; + cr = *(src_ptr++) - 0.5f; + + *(dst_ptr++) = clamp_float(y * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f); + *(dst_ptr++) = 1.0f; + } + return 0; +} + +static int convertCbYCrA_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement) +{ + unsigned int i; + float conversionMatrix[9], refLowData, y, cb, cr, a; + float *src_ptr = src; + float *dst_ptr = dst; + + if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0) + return 1; + + refLowData = (float)logElement.refLowData / logElement.maxValue; + + for (i = 0; i < logImage->width * logImage->height; i++) { + cb = *(src_ptr++) - 0.5f; + y = *(src_ptr++) - refLowData; + cr = *(src_ptr++) - 0.5f; + a = *(src_ptr++); + + *(dst_ptr++) = clamp_float(y * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f); + *(dst_ptr++) = a; + } + return 0; +} + +static int convertCbYCrY_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement) +{ + unsigned int i; + float conversionMatrix[9], refLowData, y1, y2, cb, cr; + float *src_ptr = src; + float *dst_ptr = dst; + + if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0) + return 1; + + refLowData = (float)logElement.refLowData / logElement.maxValue; + + for (i = 0; i < logImage->width * logImage->height / 2; i++) { + cb = *(src_ptr++) - 0.5f; + y1 = *(src_ptr++) - refLowData; + cr = *(src_ptr++) - 0.5f; + y2 = *(src_ptr++) - refLowData; + + *(dst_ptr++) = clamp_float(y1 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y1 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y1 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f); + *(dst_ptr++) = 1.0f; + *(dst_ptr++) = clamp_float(y2 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y2 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y2 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f); + *(dst_ptr++) = 1.0f; + } + return 0; +} + +static int convertCbYACrYA_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement) +{ + unsigned int i; + float conversionMatrix[9], refLowData, y1, y2, cb, cr, a1, a2; + float *src_ptr = src; + float *dst_ptr = dst; + + if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0) + return 1; + + refLowData = (float)logElement.refLowData / logElement.maxValue; + + for (i = 0; i < logImage->width * logImage->height / 2; i++) { + cb = *(src_ptr++) - 0.5f; + y1 = *(src_ptr++) - refLowData; + a1 = *(src_ptr++); + cr = *(src_ptr++) - 0.5f; + y2 = *(src_ptr++) - refLowData; + a2 = *(src_ptr++); + + *(dst_ptr++) = clamp_float(y1 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y1 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y1 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f); + *(dst_ptr++) = a1; + *(dst_ptr++) = clamp_float(y2 * conversionMatrix[0] + cb * conversionMatrix[1] + cr * conversionMatrix[2], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y2 * conversionMatrix[3] + cb * conversionMatrix[4] + cr * conversionMatrix[5], 0.0f, 1.0f); + *(dst_ptr++) = clamp_float(y2 * conversionMatrix[6] + cb * conversionMatrix[7] + cr * conversionMatrix[8], 0.0f, 1.0f); + *(dst_ptr++) = a2; + } + return 0; +} + +static int convertLuminance_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement) +{ + unsigned int i; + float conversionMatrix[9], value, refLowData; + float *src_ptr = src; + float *dst_ptr = dst; + + if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0) + return 1; + + refLowData = (float)logElement.refLowData / logElement.maxValue; + + for (i = 0; i < logImage->width * logImage->height; i++) { + value = clamp_float((*(src_ptr++) - refLowData) * conversionMatrix[0], 0.0f, 1.0f); + *(dst_ptr++) = value; + *(dst_ptr++) = value; + *(dst_ptr++) = value; + *(dst_ptr++) = 1.0f; + } + return 0; +} + +static int convertYA_RGBA(float *src, float *dst, LogImageFile *logImage, LogImageElement logElement) +{ + unsigned int i; + float conversionMatrix[9], value, refLowData; + float *src_ptr = src; + float *dst_ptr = dst; + + if (getYUVtoRGBMatrix((float *)&conversionMatrix, logElement) != 0) + return 1; + + refLowData = (float)logElement.refLowData / logElement.maxValue; + + for (i = 0; i < logImage->width * logImage->height; i++) { + value = clamp_float((*(src_ptr++) - refLowData) * conversionMatrix[0], 0.0f, 1.0f); + *(dst_ptr++) = value; + *(dst_ptr++) = value; + *(dst_ptr++) = value; + *(dst_ptr++) = *(src_ptr++); + } + return 0; +} + +static int convertLogElementToRGBA(float *src, float *dst, LogImageFile *logImage, + LogImageElement logElement, int dstIsLinearRGB) +{ + int rvalue; + unsigned int i; + float *src_ptr; + float *dst_ptr; + float lut[65536]; + + /* Convert data in src to linear RGBA in dst */ + switch (logElement.descriptor) { + case descriptor_RGB: + rvalue = convertRGB_RGBA(src, dst, logImage, logElement, 1); + break; + + case descriptor_RGBA: + rvalue = convertRGBA_RGBA(src, dst, logImage, logElement, 1); + break; + + case descriptor_ABGR: + rvalue = convertABGR_RGBA(src, dst, logImage, logElement, 1); + break; + + case descriptor_Luminance: + rvalue = convertLuminance_RGBA(src, dst, logImage, logElement); + break; + + case descriptor_CbYCr: + rvalue = convertCbYCr_RGBA(src, dst, logImage, logElement); + break; + + case descriptor_CbYCrY: + rvalue = convertCbYCrY_RGBA(src, dst, logImage, logElement); + break; + + case descriptor_CbYACrYA: + rvalue = convertCbYACrYA_RGBA(src, dst, logImage, logElement); + break; + + case descriptor_CbYCrA: + rvalue = convertCbYCrA_RGBA(src, dst, logImage, logElement); + break; + + case descriptor_YA: /* this descriptor is for internal use only */ + rvalue = convertYA_RGBA(src, dst, logImage, logElement); + break; + + default: + return 1; + } + + if (rvalue == 1) + return 1; + else if (dstIsLinearRGB) { + /* convert data from sRGB to Linear RGB via lut */ + getSrgbToLinLut((float *)&lut, logElement); + src_ptr = dst; // no error here + dst_ptr = dst; + for (i = 0; i < logImage->width * logImage->height; i++) { + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(dst_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + dst_ptr++; src_ptr++; + } + } + return 0; +} + +static int convertRGBAToLogElement(float *src, float *dst, LogImageFile *logImage, + LogImageElement logElement, int srcIsLinearRGB) +{ + unsigned int i; + int rvalue; + float *srgbSrc; + float *srgbSrc_ptr; + float *src_ptr = src; + float lut[65536]; + + if (srcIsLinearRGB != 0) { + /* we need to convert src to sRGB */ + srgbSrc = (float *)MEM_mallocN(4 * logImage->width * logImage->height * sizeof(float), __func__); + if (srgbSrc == 0) + return 1; + + memcpy(srgbSrc, src, 4 * logImage->width * logImage->height * sizeof(float)); + srgbSrc_ptr = srgbSrc; + + /* convert data from Linear RGB to sRGB via lut */ + getLinToSrgbLut((float *)&lut, logElement); + for (i = 0; i < logImage->width * logImage->height; i++) { + *(srgbSrc_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(srgbSrc_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + *(srgbSrc_ptr++) = lut[float_uint(*(src_ptr++), logElement.maxValue)]; + srgbSrc_ptr++; src_ptr++; + } + } + else + srgbSrc = src; + + /* Convert linear RGBA data in src to format described by logElement in dst */ + switch (logElement.descriptor) { + case descriptor_RGB: + rvalue = convertRGBA_RGB(srgbSrc, dst, logImage, logElement, 0); + break; + + case descriptor_RGBA: + rvalue = convertRGBA_RGBA(srgbSrc, dst, logImage, logElement, 0); + break; + + /* these ones are not supported for the moment */ + case descriptor_ABGR: + case descriptor_Luminance: + case descriptor_CbYCr: + case descriptor_CbYCrY: + case descriptor_CbYACrYA: + case descriptor_CbYCrA: + case descriptor_YA: /* this descriptor is for internal use only */ + default: + rvalue = 1; + } + + if (srcIsLinearRGB != 0) { + MEM_freeN(srgbSrc); + } + + return rvalue; +} diff --git a/source/blender/imbuf/intern/cineon/logImageCore.h b/source/blender/imbuf/intern/cineon/logImageCore.h index 7d88c10c2d6..7c75f8b730b 100644 --- a/source/blender/imbuf/intern/cineon/logImageCore.h +++ b/source/blender/imbuf/intern/cineon/logImageCore.h @@ -1,123 +1,283 @@ /* - * Cineon image file format library definitions. - * Cineon and DPX common structures. + * Cineon image file format library definitions. + * Cineon and DPX common structures. * - * This header file contains private details. - * User code should generally use cineonlib.h and dpxlib.h only. - * Hmm. I thought the two formats would have more in common! + * This header file contains private details. + * User code should generally use cineonlib.h and dpxlib.h only. + * Hmm. I thought the two formats would have more in common! * - * Copyright 1999,2000,2001 David Hodson + * Copyright 1999,2000,2001 David Hodson * - * 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 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. + * 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. + * 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. + * + * Contributor(s): Julien Enche. * */ -#ifndef __LOGIMAGECORE_H__ -#define __LOGIMAGECORE_H__ - /** \file blender/imbuf/intern/cineon/logImageCore.h * \ingroup imbcineon */ +#ifndef __LOG_IMAGE_CORE_H__ +#define __LOG_IMAGE_CORE_H__ + #include -#include "logImageLib.h" + +#include "BLO_sys_types.h" +#include "BLI_utildefines.h" #ifdef __cplusplus extern "C" { #endif -#include "BLO_sys_types.h" // for intptr_t support +/* + * Image structure + */ -#ifdef _MSC_VER -#undef ntohl -#undef htonl -#endif +/* There are some differences between DPX and Cineon so we need to know from what type of file the datas come from */ +enum format { + format_DPX, + format_Cineon +}; -typedef int (GetRowFn)(LogImageFile* logImage, unsigned short* row, int lineNum); -typedef int (SetRowFn)(LogImageFile* logImage, const unsigned short* row, int lineNum); -typedef void (CloseFn)(LogImageFile* logImage); +typedef struct LogImageElement +{ + int depth; + int bitsPerSample; + int dataOffset; + int packing; + int transfer; + int descriptor; + unsigned int refLowData; + unsigned int refHighData; + float refLowQuantity; + float refHighQuantity; + float maxValue; /* = 2^bitsPerSample - 1 (used internally, doesn't come from the file header) */ +} LogImageElement; -struct _Log_Image_File_t_ +typedef struct LogImageFile { /* specified in header */ int width; int height; + int numElements; int depth; - int bitsPerPixel; - int imageOffset; + LogImageElement element[8]; - /* file buffer, measured in longwords (4 byte) */ - int lineBufferLength; - unsigned int* lineBuffer; - - /* pixel buffer, holds 10 bit pixel values */ - unsigned short* pixelBuffer; - int pixelBufferUsed; + /* used for log <-> lin conversion */ + float referenceBlack; + float referenceWhite; + float gamma; /* io stuff */ - FILE* file; - int reading; - int fileYPos; + FILE *file; + unsigned char *memBuffer; + uintptr_t memBufferSize; + unsigned char *memCursor; - /* byte conversion stuff */ - LogImageByteConversionParameters params; -#if 0 - float gamma; - int blackPoint; - int whitePoint; -#endif - unsigned char lut10[1024]; - unsigned short lut8[256]; + /* is the file LSB or MSB ? */ + int isMSB; - unsigned short lut10_16[1024]; - unsigned short lut16_16[65536]; + /* DPX or Cineon ? */ + int srcFormat; +} LogImageFile; - /* pixel access functions */ - GetRowFn* getRow; - SetRowFn* setRow; - CloseFn* close; - - unsigned char *membuffer; - uintptr_t membuffersize; - unsigned char *memcursor; + +/* The SMPTE defines this code: + * 0 - User-defined + * 1 - Printing density + * 2 - Linear + * 3 - Logarithmic + * 4 - Unspecified video + * 5 - SMPTE 240M + * 6 - CCIR 709-1 + * 7 - CCIR 601-2 system B or G + * 8 - CCIR 601-2 system M + * 9 - NTSC composite video + * 10 - PAL composite video + * 11 - Z linear + * 12 - homogeneous + * + * Note that transfer_characteristics is U8, don't need + * check the byte order. + */ + +enum transfer { + transfer_UserDefined, + transfer_PrintingDensity, + transfer_Linear, + transfer_Logarithmic, + transfer_Unspecified, + transfer_Smpte240M, + transfer_Ccir7091, + transfer_Ccir6012BG, + transfer_Ccir6012M, + transfer_NTSC, + transfer_PAL, + transfer_ZLinear, + transfer_Homogeneous }; -void setupLut(LogImageFile*); -void setupLut16(LogImageFile*); +/* The SMPTE defines this code: + * 0 - User-defined + * 1 - Red + * 2 - Green + * 3 - Blue + * 4 - Alpha + * 6 - Luminance + * 7 - Chrominance + * 8 - Depth + * 9 - Composite video + * 50 - RGB + * 51 - RGBA + * 52 - ABGR + * 100 - CbYCrY + * 101 - CbYACrYA + * 102 - CbYCr + * 103 - CbYCrA + * 150 - User-defined 2-component element + * 151 - User-defined 3-component element + * 152 - User-defined 4-component element + * 153 - User-defined 5-component element + * 154 - User-defined 6-component element + * 155 - User-defined 7-component element + * 156 - User-defined 8-component element + */ -int pixelsToLongs(int numPixels); +enum descriptor { + descriptor_UserDefined, + descriptor_Red, + descriptor_Green, + descriptor_Blue, + descriptor_Alpha, + descriptor_Luminance = 6, /* don't ask me why there's no 5 */ + descriptor_Chrominance, + descriptor_Depth, + descriptor_Composite, + descriptor_RGB = 50, + descriptor_RGBA, + descriptor_ABGR, + descriptor_CbYCrY = 100, + descriptor_CbYACrYA, + descriptor_CbYCr, + descriptor_CbYCrA, + descriptor_UserDefined2Elt = 150, + descriptor_UserDefined3Elt, + descriptor_UserDefined4Elt, + descriptor_UserDefined5Elt, + descriptor_UserDefined6Elt, + descriptor_UserDefined7Elt, + descriptor_UserDefined8Elt, + /* following descriptors are for internal use only */ + descriptor_YA +}; -/* typedefs used in original docs */ -/* note size assumptions! */ +/* int functions return 0 for OK */ -typedef unsigned int U32; -typedef unsigned short U16; -typedef unsigned char U8; -typedef signed int S32; -typedef float R32; -typedef char ASCII; +void logImageSetVerbose(int verbosity); +int logImageIsDpx(const void *buffer); +int logImageIsCineon(const void *buffer); +LogImageFile *logImageOpenFromMemory(const unsigned char *buffer, unsigned int size); +LogImageFile *logImageOpenFromFile(const char *filename, int cineon); +void logImageGetSize(LogImageFile *logImage, int *width, int *height, int *depth); +LogImageFile *logImageCreate(const char *filename, int cineon, int width, int height, int bitsPerSample, + int isLogarithmic, int hasAlpha, int referenceWhite, int referenceBlack, + float gamma, const char *creator); +void logImageClose(LogImageFile *logImage); + +/* Data handling */ +unsigned int getRowLength(int width, LogImageElement logElement); +int logImageSetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB); +int logImageGetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB); + +/* + * Inline routines + */ + +/* Endianness swapping */ + +BLI_INLINE unsigned short swap_ushort(unsigned short x, int swap) +{ + if (swap != 0) + return (x >> 8) | (x << 8); + else + return x; +} + +BLI_INLINE unsigned int swap_uint(unsigned int x, int swap) +{ + if (swap != 0) + return (x >> 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x << 24); + else + return x; +} + +BLI_INLINE float swap_float(float x, int swap) +{ + if (swap != 0) { + union { + float f; + unsigned char b[4]; + } dat1, dat2; + + dat1.f = x; + dat2.b[0] = dat1.b[3]; + dat2.b[1] = dat1.b[2]; + dat2.b[2] = dat1.b[1]; + dat2.b[3] = dat1.b[0]; + return dat2.f; + } + else + return x; +} + +/* Other */ + +BLI_INLINE unsigned int clamp_uint(unsigned int x, unsigned int low, unsigned int high) +{ + if (x > high) + return high; + else if (x < low) + return low; + else + return x; +} + +BLI_INLINE float clamp_float(float x, float low, float high) +{ + if (x > high) + return high; + else if (x < low) + return low; + else + return x; +} + +BLI_INLINE unsigned int float_uint(float value, unsigned int max) +{ + if (value < 0.0f) + return 0; + else if (value > (1.0f - 0.5f / (float)max)) + return max; + else + return (unsigned int)(((float)max * value) + 0.5f); +} -R32 htonf(R32 f); -R32 ntohf(R32 f); -R32 undefined(void); -U16 reverseU16(U16 value); -U32 reverseU32(U32 value); -R32 reverseR32(R32 value); #ifdef __cplusplus } #endif -#endif /* __LOGIMAGECORE_H__ */ +#endif /* __LOG_IMAGE_CORE_H__ */ diff --git a/source/blender/imbuf/intern/cineon/logImageLib.c b/source/blender/imbuf/intern/cineon/logImageLib.c deleted file mode 100644 index ccc6045e6e5..00000000000 --- a/source/blender/imbuf/intern/cineon/logImageLib.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Cineon and DPX image file format library routines. - * - * Copyright 1999 - 2002 David Hodson - * - * 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. - * - */ - -/** \file blender/imbuf/intern/cineon/logImageLib.c - * \ingroup imbcineon - */ - -#include "cineonlib.h" -#include "dpxlib.h" - -#include -#include -#include -#include /* strftime() */ -#include -#ifdef WIN32 -#include -#else -#include /* htonl() */ -#endif -#include /* memset */ -#include "BLI_fileops.h" - -#define MIN_GAMMA 0.01 -#define MAX_GAMMA 99.9 -#define DEFAULT_GAMMA 1.0 -#define DEFAULT_BLACK_POINT 95 -#define DEFAULT_WHITE_POINT 685 - -void -logImageSetVerbose(int verbosity) -{ - cineonSetVerbose(verbosity); - dpxSetVerbose(verbosity); -} - -LogImageFile* -logImageOpen(const char* filename, int cineon) -{ - if (cineon) { - return cineonOpen(filename); - } - else { - return dpxOpen(filename); - } - return 0; -} - -LogImageFile* -logImageOpenFromMem(unsigned char *buffer, unsigned int size, int cineon) -{ - if (cineon) { - return cineonOpenFromMem(buffer, size); - } - else { - return dpxOpenFromMem(buffer, size); - } - return 0; -} - -LogImageFile* -logImageCreate(const char* filename, int cineon, int width, int height, int depth) -{ - if (cineon) { - return cineonCreate(filename, width, height, depth); - } - else { - return dpxCreate(filename, width, height, depth); - } - return 0; -} - -int -logImageGetSize(const LogImageFile* logImage, int* width, int* height, int* depth) -{ - *width = logImage->width; - *height = logImage->height; - *depth = logImage->depth; - return 0; -} - -int -logImageGetByteConversionDefaults(LogImageByteConversionParameters* params) -{ - params->gamma = DEFAULT_GAMMA; - params->blackPoint = DEFAULT_BLACK_POINT; - params->whitePoint = DEFAULT_WHITE_POINT; - params->doLogarithm = 0; - return 0; -} - -int -logImageGetByteConversion(const LogImageFile* logImage, LogImageByteConversionParameters* params) -{ - params->gamma = logImage->params.gamma; - params->blackPoint = logImage->params.blackPoint; - params->whitePoint = logImage->params.whitePoint; - params->doLogarithm = 0; - return 0; -} - -int -logImageSetByteConversion(LogImageFile* logImage, const LogImageByteConversionParameters* params) -{ - if ((params->gamma >= MIN_GAMMA) && - (params->gamma <= MAX_GAMMA) && - (params->blackPoint >= 0) && - (params->blackPoint < params->whitePoint) && - (params->whitePoint <= 1023)) - { - logImage->params.gamma = params->gamma; - logImage->params.blackPoint = params->blackPoint; - logImage->params.whitePoint = params->whitePoint; - logImage->params.doLogarithm = params->doLogarithm; - setupLut16(logImage); - return 0; - } - return 1; -} - -int -logImageGetRowBytes(LogImageFile* logImage, unsigned short* row, int y) -{ - return logImage->getRow(logImage, row, y); -} - -int -logImageSetRowBytes(LogImageFile* logImage, const unsigned short* row, int y) -{ - return logImage->setRow(logImage, row, y); -} - -void -logImageClose(LogImageFile* logImage) -{ - logImage->close(logImage); -} - -void -logImageDump(const char* filename) -{ - - U32 magic; - - FILE* foo = BLI_fopen(filename, "rb"); - if (foo == 0) { - return; - } - - if (fread(&magic, sizeof(magic), 1, foo) == 0) { - fclose(foo); - return; - } - - fclose(foo); - - if (magic == ntohl(CINEON_FILE_MAGIC)) { -#if 0 - cineonDump(filename); -#endif - } - else if (magic == ntohl(DPX_FILE_MAGIC)) { - dpxDump(filename); - } -} diff --git a/source/blender/imbuf/intern/cineon/logImageLib.h b/source/blender/imbuf/intern/cineon/logImageLib.h index 1c24358e4ef..e69de29bb2d 100644 --- a/source/blender/imbuf/intern/cineon/logImageLib.h +++ b/source/blender/imbuf/intern/cineon/logImageLib.h @@ -1,87 +0,0 @@ -/* - * Common library definitions for Cineon and DPX image files. - * - * Copyright 1999,2000,2001 David Hodson - * - * 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 __LOGIMAGELIB_H__ -#define __LOGIMAGELIB_H__ - -/** \file blender/imbuf/intern/cineon/logImageLib.h - * \ingroup imbcineon - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Image structure. You don't care what this is. - */ - -typedef struct _Log_Image_File_t_ LogImageFile; - -/* - * Magic numbers for normal and byte-swapped Cineon and Dpx files - */ - -#define CINEON_FILE_MAGIC 0x802A5FD7 -#define DPX_FILE_MAGIC 0x53445058 - -/* - * Image 8 bit <-> 10 bit conversion parameters. - */ - -typedef struct { - float gamma; - int blackPoint; - int whitePoint; - int doLogarithm; -} LogImageByteConversionParameters; - -/* int functions return 0 for OK */ - -void logImageSetVerbose(int); - -LogImageFile* logImageOpenFromMem(unsigned char *buffer, unsigned int size, int cineon); -LogImageFile* logImageOpen(const char* filename, int cineon); -int logImageGetSize(const LogImageFile* logImage, int* xsize, int* ysize, int* channels); -LogImageFile* logImageCreate(const char* filename, int cineon, int xsize, int ysize, int channels); - -/* byte conversion routines for mapping logImage (usually) 10 bit values to 8 bit */ -/* see Kodak docs for details... */ - -int logImageGetByteConversionDefaults(LogImageByteConversionParameters* params); -int logImageGetByteConversion(const LogImageFile* logImage, LogImageByteConversionParameters* params); -int logImageSetByteConversion(LogImageFile* logImage, const LogImageByteConversionParameters* params); - -/* get/set scanline of converted bytes */ -int logImageGetRowBytes(LogImageFile* logImage, unsigned short* row, int y); -int logImageSetRowBytes(LogImageFile* logImage, const unsigned short* row, int y); - -/* closes file and deletes data */ -void logImageClose(LogImageFile* logImage); - -/* read file and dump header info */ -void logImageDump(const char* filename); - -#ifdef __cplusplus -} -#endif - -#endif /* __LOGIMAGELIB_H__ */ diff --git a/source/blender/imbuf/intern/cineon/logmemfile.c b/source/blender/imbuf/intern/cineon/logmemfile.c index a9938582f2a..3914f6dc633 100644 --- a/source/blender/imbuf/intern/cineon/logmemfile.c +++ b/source/blender/imbuf/intern/cineon/logmemfile.c @@ -1,21 +1,23 @@ /* - * Cineon image file format library routines. + * Cineon image file format library routines. * - * Copyright 2006 Joseph Eagar (joeedh@gmail.com) + * Copyright 2006 Joseph Eagar (joeedh@gmail.com) * - * 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 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. + * 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. + * 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. + * + * Contributor(s): Julien Enche. * */ @@ -23,64 +25,102 @@ * \ingroup imbcineon */ + #include #include #include #include "logImageCore.h" +#include "logmemfile.h" -#include "logmemfile.h" /* own include */ +int logimage_fseek(LogImageFile *logFile, intptr_t offset, int origin) +{ + if (logFile->file) + fseek(logFile->file, offset, origin); + else { /* we're seeking in memory */ + if (origin == SEEK_SET) { + if (offset > logFile->memBufferSize) + return 1; + logFile->memCursor = logFile->memBuffer + offset; + } + else if (origin == SEEK_END) { + if (offset > logFile->memBufferSize) + return 1; + logFile->memCursor = (logFile->memBuffer + logFile->memBufferSize) - offset; + } + else if (origin == SEEK_CUR) { + uintptr_t pos = (uintptr_t)logFile->memCursor - (uintptr_t)logFile->memBuffer; + if (pos + offset > logFile->memBufferSize || pos < 0) + return 1; -int logimage_fseek(void* logfile, intptr_t offsett, int origin) -{ - struct _Log_Image_File_t_ *file = (struct _Log_Image_File_t_*) logfile; - intptr_t offset = offsett; - - if (file->file) fseek(file->file, offset, origin); - else { /*we're seeking in memory*/ - if (origin==SEEK_SET) { - if (offset > file->membuffersize) return 1; - file->memcursor = file->membuffer + offset; - } - else if (origin==SEEK_END) { - if (offset > file->membuffersize) return 1; - file->memcursor = (file->membuffer + file->membuffersize) - offset; - } - else if (origin==SEEK_CUR) { - uintptr_t pos = (uintptr_t)file->membuffer - (uintptr_t)file->memcursor; - if (pos + offset > file->membuffersize) return 1; - if (pos < 0) return 1; - file->memcursor += offset; + logFile->memCursor += offset; } } return 0; } -int logimage_fwrite(void *buffer, unsigned int size, unsigned int count, void *logfile) +int logimage_fwrite(void *buffer, size_t size, unsigned int count, LogImageFile *logFile) { - struct _Log_Image_File_t_ *file = (struct _Log_Image_File_t_*) logfile; - if (file->file) return fwrite(buffer, size, count, file->file); - else { /*we're writing to memory*/ - /*do nothing as this isn't supported yet*/ + if (logFile->file) + return fwrite(buffer, size, count, logFile->file); + else { /* we're writing to memory */ + /* do nothing as this isn't supported yet */ return count; } } -int logimage_fread(void *buffer, unsigned int size, unsigned int count, void *logfile) +int logimage_fread(void *buffer, size_t size, unsigned int count, LogImageFile *logFile) { - struct _Log_Image_File_t_ *file = (struct _Log_Image_File_t_*) logfile; - if (file->file) return fread(buffer, size, count, file->file); - else { /*we're reading from memory*/ - int i; - /* we convert ot uchar just on the off chance some platform can't handle - * pointer arithmetic with type (void*). */ - unsigned char *buf = (unsigned char *) buffer; - - for (i=0; imemcursor, size); - file->memcursor += size; - buf += size; + if (logFile->file) { + return fread(buffer, size, count, logFile->file); + } + else { /* we're reading from memory */ + unsigned char *buf = (unsigned char *)buffer; + uintptr_t pos = (uintptr_t)logFile->memCursor - (uintptr_t)logFile->memBuffer; + size_t total_size = size * count; + if (pos + total_size > logFile->memBufferSize) { + /* how many elements can we read without overflow ? */ + count = (logFile->memBufferSize - pos) / size; + /* recompute the size */ + total_size = size * count; } + + if (total_size != 0) + memcpy(buf, logFile->memCursor, total_size); + return count; } } + +int logimage_read_uchar(unsigned char *x, LogImageFile *logFile) +{ + uintptr_t pos = (uintptr_t)logFile->memCursor - (uintptr_t)logFile->memBuffer; + if (pos + sizeof(unsigned char) > logFile->memBufferSize) + return 1; + + *x = *(unsigned char *)logFile->memCursor; + logFile->memCursor += sizeof(unsigned char); + return 0; +} + +int logimage_read_ushort(unsigned short *x, LogImageFile *logFile) +{ + uintptr_t pos = (uintptr_t)logFile->memCursor - (uintptr_t)logFile->memBuffer; + if (pos + sizeof(unsigned short) > logFile->memBufferSize) + return 1; + + *x = *(unsigned short *)logFile->memCursor; + logFile->memCursor += sizeof(unsigned short); + return 0; +} + +int logimage_read_uint(unsigned int *x, LogImageFile *logFile) +{ + uintptr_t pos = (uintptr_t)logFile->memCursor - (uintptr_t)logFile->memBuffer; + if (pos + sizeof(unsigned int) > logFile->memBufferSize) + return 1; + + *x = *(unsigned int *)logFile->memCursor; + logFile->memCursor += sizeof(unsigned int); + return 0; +} diff --git a/source/blender/imbuf/intern/cineon/logmemfile.h b/source/blender/imbuf/intern/cineon/logmemfile.h index df3589a70d3..068a53e641b 100644 --- a/source/blender/imbuf/intern/cineon/logmemfile.h +++ b/source/blender/imbuf/intern/cineon/logmemfile.h @@ -1,33 +1,43 @@ /* - * Cineon image file format library routines. + * Cineon image file format library routines. * - * Copyright 2006 Joseph Eagar (joeedh@gmail.com) + * Copyright 2006 Joseph Eagar (joeedh@gmail.com) * - * 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 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. + * 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. + * 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. + * + * Contributor(s): Julien Enche. * */ - -#ifndef __LOGMEMFILE_H__ -#define __LOGMEMFILE_H__ /** \file blender/imbuf/intern/cineon/logmemfile.h * \ingroup imbcineon */ -int logimage_fseek(void* logfile, intptr_t offsett, int origin); -int logimage_fwrite(void *buffer, unsigned int size, unsigned int count, void *logfile); -int logimage_fread(void *buffer, unsigned int size, unsigned int count, void *logfile); -#endif /* __LOGMEMFILE_H__ */ +#ifndef __LOGMEMFILE_H__ +#define __LOGMEMFILE_H__ + +#include "logImageCore.h" + +#include + +int logimage_fseek(LogImageFile *logFile, intptr_t offset, int origin); +int logimage_fwrite(void *buffer, size_t size, unsigned int count, LogImageFile *logFile); +int logimage_fread(void *buffer, size_t size, unsigned int count, LogImageFile *logFile); +int logimage_read_uchar(unsigned char *x, LogImageFile *logFile); +int logimage_read_ushort(unsigned short *x, LogImageFile *logFile); +int logimage_read_uint(unsigned int *x, LogImageFile *logFile); + +#endif /* __LOGMEMFILE_H__ */ diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 6db45f0308a..6581987aed7 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -51,6 +51,7 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_fileops.h" #include "BLI_math.h" #include "BLI_math_color.h" #include "BLI_path_util.h" @@ -59,6 +60,7 @@ #include "BKE_colortools.h" #include "BKE_context.h" +#include "BKE_image.h" #include "BKE_utildefines.h" #include "BKE_main.h" @@ -68,7 +70,8 @@ /*********************** Global declarations *************************/ -#define MAX_COLORSPACE_NAME 64 +#define MAX_COLORSPACE_NAME 64 +#define DISPLAY_BUFFER_CHANNELS 4 /* ** list of all supported color spaces, displays and views */ static char global_role_scene_linear[MAX_COLORSPACE_NAME]; @@ -86,9 +89,17 @@ static int global_tot_colorspace = 0; static int global_tot_display = 0; static int global_tot_view = 0; +/* lock used by pre-cached processors getters, so processor wouldn't + * be created several times + * LOCK_COLORMANAGE can not be used since this mutex could be needed to + * be locked before pre-cached processor are creating + */ +static pthread_mutex_t processor_lock = BLI_MUTEX_INITIALIZER; + typedef struct ColormanageProcessor { - ConstProcessorRcPtr *processor; + OCIO_ConstProcessorRcPtr *processor; CurveMapping *curve_mapping; + int is_data_result; } ColormanageProcessor; /*********************** Color managed cache *************************/ @@ -329,8 +340,7 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV ColormnaageCacheData *cache_data; BLI_assert(cache_ibuf->x == ibuf->x && - cache_ibuf->y == ibuf->y && - cache_ibuf->channels == ibuf->channels); + cache_ibuf->y == ibuf->y); /* only buffers with different color space conversions are being stored * in cache separately. buffer which were used only different exposure/gamma @@ -411,12 +421,15 @@ static void colormanage_cache_handle_release(void *cache_handle) /*********************** Initialization / De-initialization *************************/ -static void colormanage_role_color_space_name_get(ConstConfigRcPtr *config, char *colorspace_name, const char *role) +static void colormanage_role_color_space_name_get(OCIO_ConstConfigRcPtr *config, char *colorspace_name, const char *role, const char *backup_role) { - ConstColorSpaceRcPtr *ociocs; + OCIO_ConstColorSpaceRcPtr *ociocs; ociocs = OCIO_configGetColorSpace(config, role); + if (!ociocs && backup_role) + ociocs = OCIO_configGetColorSpace(config, backup_role); + if (ociocs) { const char *name = OCIO_colorSpaceGetName(ociocs); @@ -429,33 +442,34 @@ static void colormanage_role_color_space_name_get(ConstConfigRcPtr *config, char } } -static void colormanage_load_config(ConstConfigRcPtr *config) +static void colormanage_load_config(OCIO_ConstConfigRcPtr *config) { int tot_colorspace, tot_display, tot_display_view, index, viewindex, viewindex2; const char *name; /* get roles */ - colormanage_role_color_space_name_get(config, global_role_scene_linear, OCIO_ROLE_SCENE_LINEAR); - colormanage_role_color_space_name_get(config, global_role_color_picking, OCIO_ROLE_COLOR_PICKING); - colormanage_role_color_space_name_get(config, global_role_texture_painting, OCIO_ROLE_TEXTURE_PAINT); - colormanage_role_color_space_name_get(config, global_role_default_sequencer, OCIO_ROLE_DEFAULT_SEQUENCER); - colormanage_role_color_space_name_get(config, global_role_default_byte, OCIO_ROLE_DEFAULT_BYTE); - colormanage_role_color_space_name_get(config, global_role_default_float, OCIO_ROLE_DEFAULT_FLOAT); + colormanage_role_color_space_name_get(config, global_role_scene_linear, OCIO_ROLE_SCENE_LINEAR, NULL); + colormanage_role_color_space_name_get(config, global_role_color_picking, OCIO_ROLE_COLOR_PICKING, NULL); + colormanage_role_color_space_name_get(config, global_role_texture_painting, OCIO_ROLE_TEXTURE_PAINT, NULL); + colormanage_role_color_space_name_get(config, global_role_default_sequencer, OCIO_ROLE_DEFAULT_SEQUENCER, OCIO_ROLE_SCENE_LINEAR); + colormanage_role_color_space_name_get(config, global_role_default_byte, OCIO_ROLE_DEFAULT_BYTE, OCIO_ROLE_TEXTURE_PAINT); + colormanage_role_color_space_name_get(config, global_role_default_float, OCIO_ROLE_DEFAULT_FLOAT, OCIO_ROLE_SCENE_LINEAR); /* load colorspaces */ tot_colorspace = OCIO_configGetNumColorSpaces(config); for (index = 0 ; index < tot_colorspace; index++) { - ConstColorSpaceRcPtr *ocio_colorspace; + OCIO_ConstColorSpaceRcPtr *ocio_colorspace; const char *description; - int is_invertible; + int is_invertible, is_data; name = OCIO_configGetColorSpaceNameByIndex(config, index); ocio_colorspace = OCIO_configGetColorSpace(config, name); description = OCIO_colorSpaceGetDescription(ocio_colorspace); is_invertible = OCIO_colorSpaceIsInvertible(ocio_colorspace); + is_data = OCIO_colorSpaceIsData(ocio_colorspace); - colormanage_colorspace_add(name, description, is_invertible); + colormanage_colorspace_add(name, description, is_invertible, is_data); OCIO_colorSpaceRelease(ocio_colorspace); } @@ -509,10 +523,10 @@ static void colormanage_free_config(void) /* free precomputer processors */ if (colorspace->to_scene_linear) - OCIO_processorRelease((ConstProcessorRcPtr *) colorspace->to_scene_linear); + OCIO_processorRelease((OCIO_ConstProcessorRcPtr *) colorspace->to_scene_linear); if (colorspace->from_scene_linear) - OCIO_processorRelease((ConstProcessorRcPtr *) colorspace->from_scene_linear); + OCIO_processorRelease((OCIO_ConstProcessorRcPtr *) colorspace->from_scene_linear); /* free color space itself */ MEM_freeN(colorspace); @@ -527,10 +541,10 @@ static void colormanage_free_config(void) /* free precomputer processors */ if (display->to_scene_linear) - OCIO_processorRelease((ConstProcessorRcPtr *) display->to_scene_linear); + OCIO_processorRelease((OCIO_ConstProcessorRcPtr *) display->to_scene_linear); if (display->from_scene_linear) - OCIO_processorRelease((ConstProcessorRcPtr *) display->from_scene_linear); + OCIO_processorRelease((OCIO_ConstProcessorRcPtr *) display->from_scene_linear); /* free list of views */ BLI_freelistN(&display->views); @@ -541,14 +555,18 @@ static void colormanage_free_config(void) /* free views */ BLI_freelistN(&global_views); + + OCIO_exit(); } -void IMB_colormanagement_init(void) +void colormanagement_init(void) { const char *ocio_env; const char *configdir; char configfile[FILE_MAX]; - ConstConfigRcPtr *config = NULL; + OCIO_ConstConfigRcPtr *config = NULL; + + OCIO_init(); ocio_env = getenv("OCIO"); @@ -558,13 +576,29 @@ void IMB_colormanagement_init(void) if (config == NULL) { configdir = BLI_get_folder(BLENDER_DATAFILES, "colormanagement"); - if (configdir) { + if (configdir) { BLI_join_dirfile(configfile, sizeof(configfile), configdir, BCM_CONFIG_FILE); +#ifdef WIN32 + { + /* quite a hack to support loading configuration from path with non-acii symbols */ + + char short_name[256]; + BLI_get_short_name(short_name, configfile); + config = OCIO_configCreateFromFile(short_name); + } +#else config = OCIO_configCreateFromFile(configfile); +#endif } } + if (config == NULL) { + printf("Color management: using fallback mode for management\n"); + + config = OCIO_configCreateFallback(); + } + if (config) { OCIO_setCurrentConfig(config); @@ -576,7 +610,7 @@ void IMB_colormanagement_init(void) BLI_init_srgb_conversion(); } -void IMB_colormanagement_exit(void) +void colormanagement_exit(void) { colormanage_free_config(); } @@ -624,18 +658,39 @@ static void display_transform_get_from_ctx(const bContext *C, ColorManagedViewSe } } -static ConstProcessorRcPtr *create_display_buffer_processor(const char *view_transform, const char *display, +static const char *display_transform_get_colorspace_name(const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) +{ + OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + + const char *display = display_settings->display_device; + const char *view = view_settings->view_transform; + const char *colorspace_name; + + colorspace_name = OCIO_configGetDisplayColorSpaceName(config, display, view); + + OCIO_configRelease(config); + + return colorspace_name; +} + +static ColorSpace *display_transform_get_colorspace(const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) +{ + const char *colorspace_name = display_transform_get_colorspace_name(view_settings, display_settings); + + if (colorspace_name) + return colormanage_colorspace_get_named(colorspace_name); + + return NULL; +} + +static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *view_transform, const char *display, float exposure, float gamma) { - ConstConfigRcPtr *config = OCIO_getCurrentConfig(); - DisplayTransformRcPtr *dt; - ConstProcessorRcPtr *processor; - - if (!config) { - /* there's no valid OCIO configuration, can't create processor */ - - return NULL; - } + OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + OCIO_DisplayTransformRcPtr *dt; + OCIO_ConstProcessorRcPtr *processor; dt = OCIO_createDisplayTransform(); @@ -646,7 +701,7 @@ static ConstProcessorRcPtr *create_display_buffer_processor(const char *view_tra /* fstop exposure control */ if (exposure != 0.0f) { - MatrixTransformRcPtr *mt; + OCIO_MatrixTransformRcPtr *mt; float gain = powf(2.0f, exposure); const float scale4f[] = {gain, gain, gain, gain}; float m44[16], offset4[4]; @@ -654,25 +709,25 @@ static ConstProcessorRcPtr *create_display_buffer_processor(const char *view_tra OCIO_matrixTransformScale(m44, offset4, scale4f); mt = OCIO_createMatrixTransform(); OCIO_matrixTransformSetValue(mt, m44, offset4); - OCIO_displayTransformSetLinearCC(dt, (ConstTransformRcPtr *) mt); + OCIO_displayTransformSetLinearCC(dt, (OCIO_ConstTransformRcPtr *) mt); OCIO_matrixTransformRelease(mt); } /* post-display gamma transform */ if (gamma != 1.0f) { - ExponentTransformRcPtr *et; + OCIO_ExponentTransformRcPtr *et; float exponent = 1.0f / MAX2(FLT_EPSILON, gamma); const float exponent4f[] = {exponent, exponent, exponent, exponent}; et = OCIO_createExponentTransform(); OCIO_exponentTransformSetValue(et, exponent4f); - OCIO_displayTransformSetDisplayCC(dt, (ConstTransformRcPtr *) et); + OCIO_displayTransformSetDisplayCC(dt, (OCIO_ConstTransformRcPtr *) et); OCIO_exponentTransformRelease(et); } - processor = OCIO_configGetProcessor(config, (ConstTransformRcPtr *) dt); + processor = OCIO_configGetProcessor(config, (OCIO_ConstTransformRcPtr *) dt); OCIO_displayTransformRelease(dt); OCIO_configRelease(config); @@ -680,17 +735,11 @@ static ConstProcessorRcPtr *create_display_buffer_processor(const char *view_tra return processor; } -static ConstProcessorRcPtr *create_colorspace_transform_processor(const char *from_colorspace, +static OCIO_ConstProcessorRcPtr *create_colorspace_transform_processor(const char *from_colorspace, const char *to_colorspace) { - ConstConfigRcPtr *config = OCIO_getCurrentConfig(); - ConstProcessorRcPtr *processor; - - if (!config) { - /* there's no valid OCIO configuration, can't create processor */ - - return NULL; - } + OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + OCIO_ConstProcessorRcPtr *processor; processor = OCIO_configGetProcessorWithNames(config, from_colorspace, to_colorspace); @@ -699,49 +748,49 @@ static ConstProcessorRcPtr *create_colorspace_transform_processor(const char *fr return processor; } -static ConstProcessorRcPtr *colorspace_to_scene_linear_processor(ColorSpace *colorspace) +static OCIO_ConstProcessorRcPtr *colorspace_to_scene_linear_processor(ColorSpace *colorspace) { if (colorspace->to_scene_linear == NULL) { - BLI_lock_thread(LOCK_COLORMANAGE); + BLI_mutex_lock(&processor_lock); if (colorspace->to_scene_linear == NULL) { - ConstProcessorRcPtr *to_scene_linear; + OCIO_ConstProcessorRcPtr *to_scene_linear; to_scene_linear = create_colorspace_transform_processor(colorspace->name, global_role_scene_linear); - colorspace->to_scene_linear = (struct ConstProcessorRcPtr *) to_scene_linear; + colorspace->to_scene_linear = (struct OCIO_ConstProcessorRcPtr *) to_scene_linear; } - BLI_unlock_thread(LOCK_COLORMANAGE); + BLI_mutex_unlock(&processor_lock); } - return (ConstProcessorRcPtr *) colorspace->to_scene_linear; + return (OCIO_ConstProcessorRcPtr *) colorspace->to_scene_linear; } -static ConstProcessorRcPtr *colorspace_from_scene_linear_processor(ColorSpace *colorspace) +static OCIO_ConstProcessorRcPtr *colorspace_from_scene_linear_processor(ColorSpace *colorspace) { if (colorspace->from_scene_linear == NULL) { - BLI_lock_thread(LOCK_COLORMANAGE); + BLI_mutex_lock(&processor_lock); if (colorspace->from_scene_linear == NULL) { - ConstProcessorRcPtr *from_scene_linear; + OCIO_ConstProcessorRcPtr *from_scene_linear; from_scene_linear = create_colorspace_transform_processor(global_role_scene_linear, colorspace->name); - colorspace->from_scene_linear = (struct ConstProcessorRcPtr *) from_scene_linear; + colorspace->from_scene_linear = (struct OCIO_ConstProcessorRcPtr *) from_scene_linear; } - BLI_unlock_thread(LOCK_COLORMANAGE); + BLI_mutex_unlock(&processor_lock); } - return (ConstProcessorRcPtr *) colorspace->from_scene_linear; + return (OCIO_ConstProcessorRcPtr *) colorspace->from_scene_linear; } -static ConstProcessorRcPtr *display_from_scene_linear_processor(ColorManagedDisplay *display) +static OCIO_ConstProcessorRcPtr *display_from_scene_linear_processor(ColorManagedDisplay *display) { if (display->from_scene_linear == NULL) { - BLI_lock_thread(LOCK_COLORMANAGE); + BLI_mutex_lock(&processor_lock); if (display->from_scene_linear == NULL) { const char *view_name = colormanage_view_get_default_name(display); - ConstConfigRcPtr *config = OCIO_getCurrentConfig(); - ConstProcessorRcPtr *processor = NULL; + OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + OCIO_ConstProcessorRcPtr *processor = NULL; if (view_name && config) { const char *view_colorspace = OCIO_configGetDisplayColorSpaceName(config, display->name, view_name); @@ -750,24 +799,24 @@ static ConstProcessorRcPtr *display_from_scene_linear_processor(ColorManagedDisp OCIO_configRelease(config); } - display->from_scene_linear = (struct ConstProcessorRcPtr *) processor; + display->from_scene_linear = (struct OCIO_ConstProcessorRcPtr *) processor; } - BLI_unlock_thread(LOCK_COLORMANAGE); + BLI_mutex_unlock(&processor_lock); } - return (ConstProcessorRcPtr *) display->from_scene_linear; + return (OCIO_ConstProcessorRcPtr *) display->from_scene_linear; } -static ConstProcessorRcPtr *display_to_scene_linear_processor(ColorManagedDisplay *display) +static OCIO_ConstProcessorRcPtr *display_to_scene_linear_processor(ColorManagedDisplay *display) { if (display->to_scene_linear == NULL) { - BLI_lock_thread(LOCK_COLORMANAGE); + BLI_mutex_lock(&processor_lock); if (display->to_scene_linear == NULL) { const char *view_name = colormanage_view_get_default_name(display); - ConstConfigRcPtr *config = OCIO_getCurrentConfig(); - ConstProcessorRcPtr *processor = NULL; + OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + OCIO_ConstProcessorRcPtr *processor = NULL; if (view_name && config) { const char *view_colorspace = OCIO_configGetDisplayColorSpaceName(config, display->name, view_name); @@ -776,23 +825,25 @@ static ConstProcessorRcPtr *display_to_scene_linear_processor(ColorManagedDispla OCIO_configRelease(config); } - display->to_scene_linear = (struct ConstProcessorRcPtr *) processor; + display->to_scene_linear = (struct OCIO_ConstProcessorRcPtr *) processor; } - BLI_unlock_thread(LOCK_COLORMANAGE); + BLI_mutex_unlock(&processor_lock); } - return (ConstProcessorRcPtr *) display->to_scene_linear; + return (OCIO_ConstProcessorRcPtr *) display->to_scene_linear; } static void init_default_view_settings(const ColorManagedDisplaySettings *display_settings, ColorManagedViewSettings *view_settings) { ColorManagedDisplay *display; - ColorManagedView *default_view; + ColorManagedView *default_view = NULL; display = colormanage_display_get_named(display_settings->display_device); - default_view = colormanage_view_get_default(display); + + if (display) + default_view = colormanage_view_get_default(display); if (default_view) BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform)); @@ -837,6 +888,13 @@ void colormanage_imbuf_set_default_spaces(ImBuf *ibuf) void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace) { + ColorSpace *colorspace = colormanage_colorspace_get_named(from_colorspace); + + if (colorspace->is_data) { + ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; + return; + } + if (ibuf->rect_float) { const char *to_colorspace = global_role_scene_linear; int predivide = ibuf->flags & IB_cm_predivide; @@ -874,11 +932,13 @@ static void colormanage_check_view_settings(ColorManagedDisplaySettings *display ColorManagedViewSettings *view_settings, const char *what) { ColorManagedDisplay *display; - ColorManagedView *default_view; + ColorManagedView *default_view = NULL; if (view_settings->view_transform[0] == '\0') { display = colormanage_display_get_named(display_settings->display_device); - default_view = colormanage_view_get_default(display); + + if (display) + default_view = colormanage_view_get_default(display); if (default_view) BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform)); @@ -888,7 +948,9 @@ static void colormanage_check_view_settings(ColorManagedDisplaySettings *display if (!view) { display = colormanage_display_get_named(display_settings->display_device); - default_view = colormanage_view_get_default(display); + + if (display) + default_view = colormanage_view_get_default(display); if (default_view) { printf("Color management: %s view \"%s\" not found, setting default \"%s\".\n", @@ -970,10 +1032,11 @@ void IMB_colormanagement_validate_settings(ColorManagedDisplaySettings *display_ ColorManagedViewSettings *view_settings) { ColorManagedDisplay *display; - ColorManagedView *default_view; + ColorManagedView *default_view = NULL; LinkData *view_link; display = colormanage_display_get_named(display_settings->display_device); + default_view = colormanage_view_get_default(display); for (view_link = display->views.first; view_link; view_link = view_link->next) { @@ -983,7 +1046,7 @@ void IMB_colormanagement_validate_settings(ColorManagedDisplaySettings *display_ break; } - if (view_link == NULL) + if (view_link == NULL && default_view) BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform)); } @@ -1016,6 +1079,40 @@ const char *IMB_colormanagement_role_colorspace_name_get(int role) return NULL; } +void IMB_colormanagement_check_is_data(ImBuf *ibuf, const char *name) +{ + ColorSpace *colorspace = colormanage_colorspace_get_named(name); + + if (colorspace->is_data) + ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; + else + ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; +} + +void IMB_colormanagement_assign_float_colorspace(ImBuf *ibuf, const char *name) +{ + ColorSpace *colorspace = colormanage_colorspace_get_named(name); + + ibuf->float_colorspace = colorspace; + + if (colorspace->is_data) + ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; + else + ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; +} + +void IMB_colormanagement_assign_rect_colorspace(ImBuf *ibuf, const char *name) +{ + ColorSpace *colorspace = colormanage_colorspace_get_named(name); + + ibuf->rect_colorspace = colorspace; + + if (colorspace->is_data) + ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; + else + ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; +} + /*********************** Threaded display buffer transform routines *************************/ typedef struct DisplayBufferThread { @@ -1034,6 +1131,7 @@ typedef struct DisplayBufferThread { int channels; float dither; int predivide; + int is_data; const char *byte_colorspace; const char *float_colorspace; @@ -1063,8 +1161,10 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l int predivide = ibuf->flags & IB_cm_predivide; int channels = ibuf->channels; float dither = ibuf->dither; + int is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA; int offset = channels * start_line * ibuf->x; + int display_buffer_byte_offset = DISPLAY_BUFFER_CHANNELS * start_line * ibuf->x; memset(handle, 0, sizeof(DisplayBufferThread)); @@ -1080,7 +1180,7 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l handle->display_buffer = init_data->display_buffer + offset; if (init_data->display_buffer_byte) - handle->display_buffer_byte = init_data->display_buffer_byte + offset; + handle->display_buffer_byte = init_data->display_buffer_byte + display_buffer_byte_offset; handle->width = ibuf->x; @@ -1090,6 +1190,7 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l handle->channels = channels; handle->dither = dither; handle->predivide = predivide; + handle->is_data = is_data; handle->byte_colorspace = init_data->byte_colorspace; handle->float_colorspace = init_data->float_colorspace; @@ -1106,6 +1207,8 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) int buffer_size = channels * width * height; int predivide = handle->predivide; + int is_data = handle->is_data; + int is_data_display = handle->cm_processor->is_data_result; linear_buffer = MEM_callocN(buffer_size * sizeof(float), "color conversion linear buffer"); @@ -1122,14 +1225,16 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) /* first convert byte buffer to float, keep in image space */ for (i = 0, fp = linear_buffer, cp = byte_buffer; i < channels * width * height; - i++, fp++, cp++) + i++, fp++, cp++) { *fp = (float)(*cp) / 255.0f; } - /* convert float buffer to scene linear space */ - IMB_colormanagement_transform(linear_buffer, width, height, channels, - from_colorspace, to_colorspace, predivide); + if (!is_data && !is_data_display) { + /* convert float buffer to scene linear space */ + IMB_colormanagement_transform(linear_buffer, width, height, channels, + from_colorspace, to_colorspace, predivide); + } } else if (handle->float_colorspace) { /* currently float is non-linear only in sequencer, which is working @@ -1166,7 +1271,6 @@ static void *do_display_buffer_apply_thread(void *handle_v) { DisplayBufferThread *handle = (DisplayBufferThread *) handle_v; ColormanageProcessor *cm_processor = handle->cm_processor; - float *buffer = handle->buffer; float *display_buffer = handle->display_buffer; unsigned char *display_buffer_byte = handle->display_buffer_byte; int channels = handle->channels; @@ -1174,25 +1278,45 @@ static void *do_display_buffer_apply_thread(void *handle_v) int height = handle->tot_line; float dither = handle->dither; int predivide = handle->predivide; + int is_data = handle->is_data; - float *linear_buffer = display_buffer_apply_get_linear_buffer(handle); + if (cm_processor == NULL) { + if (display_buffer_byte) { + IMB_buffer_byte_from_byte(display_buffer_byte, handle->byte_buffer, IB_PROFILE_SRGB, IB_PROFILE_SRGB, + FALSE, width, height, width, width); + } - /* apply processor */ - IMB_colormanagement_processor_apply(cm_processor, linear_buffer, width, height, channels, predivide); - - /* copy result to output buffers */ - if (display_buffer_byte) { - /* do conversion */ - IMB_buffer_byte_from_float(display_buffer_byte, linear_buffer, - channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, - predivide, width, height, width, width); + if (display_buffer) { + IMB_buffer_float_from_byte(display_buffer, handle->byte_buffer, IB_PROFILE_SRGB, IB_PROFILE_SRGB, + FALSE, width, height, width, width); + } } + else { + float *linear_buffer = display_buffer_apply_get_linear_buffer(handle); - if (display_buffer) - memcpy(display_buffer, linear_buffer, width * height * channels * sizeof(float)); + if (is_data) { + /* special case for data buffers - no color space conversions, + * only generate byte buffers + */ + } + else { + /* apply processor */ + IMB_colormanagement_processor_apply(cm_processor, linear_buffer, width, height, channels, predivide); + } + + /* copy result to output buffers */ + if (display_buffer_byte) { + /* do conversion */ + IMB_buffer_byte_from_float(display_buffer_byte, linear_buffer, + channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, + predivide, width, height, width, width); + } + + if (display_buffer) + memcpy(display_buffer, linear_buffer, width * height * channels * sizeof(float)); - if (linear_buffer != buffer) MEM_freeN(linear_buffer); + } return NULL; } @@ -1235,14 +1359,35 @@ static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_bu const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { - ColormanageProcessor *cm_processor; + ColormanageProcessor *cm_processor = NULL; + int skip_transform = FALSE; - cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); + /* if we're going to transform byte buffer, check whether transformation would + * happen to the same color space as byte buffer itself is + * this would save byte -> float -> byte conversions making display buffer + * computation noticeable faster + */ + if (ibuf->rect_float == NULL && ibuf->rect_colorspace) { + if ((view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) == 0 && + view_settings->exposure == 0.0f && + view_settings->gamma == 1.0f) + { + const char *from_colorspace = ibuf->rect_colorspace->name; + const char *to_colorspace = display_transform_get_colorspace_name(view_settings, display_settings); + + if (to_colorspace && !strcmp(from_colorspace, to_colorspace)) + skip_transform = TRUE; + } + } + + if (skip_transform == FALSE) + cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); display_buffer_apply_threaded(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect, display_buffer, display_buffer_byte, cm_processor); - IMB_colormanagement_processor_free(cm_processor); + if (cm_processor) + IMB_colormanagement_processor_free(cm_processor); } static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *display_buffer, @@ -1401,13 +1546,11 @@ void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspac */ void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], ColorSpace *colorspace) { - ConstProcessorRcPtr *processor; + OCIO_ConstProcessorRcPtr *processor; if (!colorspace) { - /* OCIO_TODO: make sure it never happens */ - + /* should never happen */ printf("%s: perform conversion from unknown color space\n", __func__); - return; } @@ -1420,13 +1563,11 @@ void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], ColorSpac /* same as above, but converts colors in opposite direction */ void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], ColorSpace *colorspace) { - ConstProcessorRcPtr *processor; + OCIO_ConstProcessorRcPtr *processor; if (!colorspace) { - /* OCIO_TODO: make sure it never happens */ - + /* should never happen */ printf("%s: perform conversion from unknown color space\n", __func__); - return; } @@ -1438,22 +1579,20 @@ void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], ColorSpac void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, int predivide) { - ConstProcessorRcPtr *processor; + OCIO_ConstProcessorRcPtr *processor; if (!colorspace) { - /* OCIO_TODO: make sure it never happens */ - + /* should never happen */ printf("%s: perform conversion from unknown color space\n", __func__); - return; } processor = colorspace_to_scene_linear_processor(colorspace); if (processor) { - PackedImageDesc *img; + OCIO_PackedImageDesc *img; - img = OCIO_createPackedImageDesc(buffer, width, height, channels, sizeof(float), + img = OCIO_createOCIO_PackedImageDesc(buffer, width, height, channels, sizeof(float), channels * sizeof(float), channels * sizeof(float) * width); if (predivide) @@ -1461,7 +1600,7 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, in else OCIO_processorApply(processor, img); - OCIO_packedImageDescRelease(img); + OCIO_OCIO_PackedImageDescRelease(img); } } @@ -1471,7 +1610,7 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, in */ void IMB_colormanagement_scene_linear_to_display_v3(float pixel[3], ColorManagedDisplay *display) { - ConstProcessorRcPtr *processor; + OCIO_ConstProcessorRcPtr *processor; processor = display_from_scene_linear_processor(display); @@ -1482,7 +1621,7 @@ void IMB_colormanagement_scene_linear_to_display_v3(float pixel[3], ColorManaged /* same as above, but converts color in opposite direction */ void IMB_colormanagement_display_to_scene_linear_v3(float pixel[3], ColorManagedDisplay *display) { - ConstProcessorRcPtr *processor; + OCIO_ConstProcessorRcPtr *processor; processor = display_to_scene_linear_processor(display); @@ -1516,27 +1655,106 @@ void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float IMB_colormanagement_processor_free(cm_processor); } -void IMB_colormanagement_imbuf_assign_float_space(ImBuf *ibuf, ColorManagedColorspaceSettings *colorspace_settings) +static void colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, int make_byte) { - ibuf->float_colorspace = colormanage_colorspace_get_named(colorspace_settings->name); -} - -void IMB_colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) -{ - /* OCIO_TODO: byte buffer management is not supported here yet */ - if (!ibuf->rect_float) - return; + if (!ibuf->rect && make_byte) + imb_addrectImBuf(ibuf); if (global_tot_display == 0 || global_tot_view == 0) { IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float, ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x); } else { - colormanage_display_buffer_process_ex(ibuf, ibuf->rect_float, NULL, view_settings, display_settings); + colormanage_display_buffer_process_ex(ibuf, ibuf->rect_float, (unsigned char *)ibuf->rect, + view_settings, display_settings); } } +void IMB_colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) +{ + colormanagement_imbuf_make_display_space(ibuf, view_settings, display_settings, FALSE); +} + +/* prepare image buffer to be saved on disk, applying color management if needed + * color management would be applied if image is saving as render result and if + * file format is not expecting float buffer to be in linear space (currently + * JPEG2000 and TIFF are such formats -- they're storing image as float but + * file itself stores applied color space). + * + * Both byte and float buffers would contain applied color space, and result's + * float_colorspace would be set to display color space. This should be checked + * in image format write callback and if float_colorspace is not NULL, no color + * space transformation should be applied on this buffer. + */ +ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, int save_as_render, int allocate_result, const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, ImageFormatData *image_format_data) +{ + ImBuf *colormanaged_ibuf = ibuf; + int do_colormanagement; + int is_movie = BKE_imtype_is_movie(image_format_data->imtype); + int requires_linear_float = BKE_imtype_requires_linear_float(image_format_data->imtype); + + do_colormanagement = save_as_render && (is_movie || !requires_linear_float); + + if (do_colormanagement) { + int make_byte = FALSE; + ImFileType *type; + + if (allocate_result) { + colormanaged_ibuf = IMB_dupImBuf(ibuf); + } + else { + /* render pipeline is constructing image buffer itself, but it's re-using byte and float buffers from render result + * make copy of this buffers here sine this buffers would be transformed to other color space here + */ + + if (ibuf->rect && (ibuf->mall & IB_rect) == 0) { + ibuf->rect = MEM_dupallocN(ibuf->rect); + ibuf->mall |= IB_rect; + } + + if (ibuf->rect_float && (ibuf->mall & IB_rectfloat) == 0) { + ibuf->rect_float = MEM_dupallocN(ibuf->rect_float); + ibuf->mall |= IB_rectfloat; + } + } + + /* for proper check whether byte buffer is required by a format or not + * should be pretty safe since this image buffer is supposed to be used for + * saving only and ftype would be overwritten a bit later by BKE_imbuf_write + */ + colormanaged_ibuf->ftype = BKE_imtype_to_ftype(image_format_data->imtype); + + /* if file format isn't able to handle float buffer itself, + * we need to allocate byte buffer and store color managed + * image there + */ + for (type = IMB_FILE_TYPES; type->is_a; type++) { + if (type->save && type->ftype(type, colormanaged_ibuf)) { + if ((type->flag & IM_FTYPE_FLOAT) == 0) + make_byte = TRUE; + + break; + } + } + + /* perform color space conversions */ + colormanagement_imbuf_make_display_space(colormanaged_ibuf, view_settings, display_settings, make_byte); + + if (colormanaged_ibuf->rect_float) { + /* float buffer isn't linear anymore, + * image format write callback should check for this flag and assume + * no space conversion should happen if ibuf->float_colorspace != NULL + */ + colormanaged_ibuf->float_colorspace = display_transform_get_colorspace(view_settings, display_settings); + } + } + + return colormanaged_ibuf; +} + static void imbuf_verify_float(ImBuf *ibuf) { /* multiple threads could request for display buffer at once and in case @@ -1606,7 +1824,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet if (global_tot_display) ibuf->display_buffer_flags = MEM_callocN(sizeof(unsigned int) * global_tot_display, "imbuf display_buffer_flags"); } - else if (ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) { + else if (ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) { /* all display buffers were marked as invalid from other areas, * now propagate this flag to internal color management routines */ @@ -1622,7 +1840,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet return display_buffer; } - buffer_size = ibuf->channels * ibuf->x * ibuf->y * sizeof(float); + buffer_size = DISPLAY_BUFFER_CHANNELS * ibuf->x * ibuf->y * sizeof(char); display_buffer = MEM_callocN(buffer_size, "imbuf display buffer"); colormanage_display_buffer_process(ibuf, display_buffer, applied_view_settings, display_settings); @@ -1646,28 +1864,12 @@ unsigned char *IMB_display_buffer_acquire_ctx(const bContext *C, ImBuf *ibuf, vo return IMB_display_buffer_acquire(ibuf, view_settings, display_settings, cache_handle); } -/* covert float buffer to display space and store it in image buffer's byte array */ -void IMB_display_buffer_to_imbuf_rect(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) -{ - if (global_tot_display == 0 || global_tot_view == 0) { - imbuf_verify_float(ibuf); - } - else { - if (!ibuf->rect) { - imb_addrectImBuf(ibuf); - } - - colormanage_display_buffer_process(ibuf, (unsigned char *) ibuf->rect, view_settings, display_settings); - } -} - void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *linear_buffer, int width, int height, int channels, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, int predivide) { if (global_tot_display == 0 || global_tot_view == 0) { - IMB_buffer_byte_from_float(display_buffer, linear_buffer, 4, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, FALSE, + IMB_buffer_byte_from_float(display_buffer, linear_buffer, channels, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, FALSE, width, height, width, width); } else { @@ -1701,25 +1903,26 @@ void IMB_display_buffer_release(void *cache_handle) /*********************** Display functions *************************/ -ColorManagedDisplay *colormanage_display_get_default(void) +const char *colormanage_display_get_default_name(void) { - ConstConfigRcPtr *config = OCIO_getCurrentConfig(); - const char *display; + OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + const char *display_name; - if (!config) { - /* no valid OCIO configuration, can't get default display */ - - return NULL; - } - - display = OCIO_configGetDefaultDisplay(config); + display_name = OCIO_configGetDefaultDisplay(config); OCIO_configRelease(config); - if (display[0] == '\0') + return display_name; +} + +ColorManagedDisplay *colormanage_display_get_default(void) +{ + const char *display_name = colormanage_display_get_default_name(); + + if (display_name[0] == '\0') return NULL; - return colormanage_display_get_named(display); + return colormanage_display_get_named(display_name); } ColorManagedDisplay *colormanage_display_add(const char *name) @@ -1801,19 +2004,21 @@ ColorManagedDisplay *IMB_colormanagement_display_get_named(const char *name) return colormanage_display_get_named(name); } +const char *IMB_colormanagement_display_get_none_name(void) +{ + if (colormanage_display_get_named("None") != NULL) + return "None"; + + return colormanage_display_get_default_name(); +} + /*********************** View functions *************************/ const char *colormanage_view_get_default_name(const ColorManagedDisplay *display) { - ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); const char *name; - if (!config) { - /* no valid OCIO configuration, can't get default view */ - - return NULL; - } - name = OCIO_configGetDefaultView(config, display->name); OCIO_configRelease(config); @@ -1890,11 +2095,13 @@ const char *IMB_colormanagement_view_get_indexed_name(int index) const char *IMB_colormanagement_view_get_default_name(const char *display_name) { ColorManagedDisplay *display = colormanage_display_get_named(display_name); - ColorManagedView *view = colormanage_view_get_default(display); + ColorManagedView *view = NULL; + + if (display) + view = colormanage_view_get_default(display); - if (view) { + if (view) return view->name; - } return NULL; } @@ -1921,7 +2128,7 @@ static void colormanage_description_strip(char *description) } } -ColorSpace *colormanage_colorspace_add(const char *name, const char *description, int is_invertible) +ColorSpace *colormanage_colorspace_add(const char *name, const char *description, int is_invertible, int is_data) { ColorSpace *colorspace, *prev_space; int counter = 1; @@ -1937,6 +2144,7 @@ ColorSpace *colormanage_colorspace_add(const char *name, const char *description } colorspace->is_invertible = is_invertible; + colorspace->is_data = is_data; for (prev_space = global_colorspaces.first; prev_space; prev_space = prev_space->next) { if (BLI_strcasecmp(prev_space->name, colorspace->name) > 0) @@ -2124,6 +2332,7 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe float *display_buffer_float = NULL; int width = xmax - xmin; int height = ymax - ymin; + int is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA; if (dither != 0.0f) { display_buffer_float = MEM_callocN(channels * width * height * sizeof(float), "display buffer for dither"); @@ -2140,14 +2349,15 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe } else if (byte_buffer) { rgba_uchar_to_float(pixel, byte_buffer + linear_index); - IMB_colormanagement_colorspace_to_scene_linear_v3(pixel, rect_colorspace); } - if (predivide) - IMB_colormanagement_processor_apply_v4(cm_processor, pixel); - else - IMB_colormanagement_processor_apply_v4(cm_processor, pixel); + if (!is_data) { + if (predivide) + IMB_colormanagement_processor_apply_v4(cm_processor, pixel); + else + IMB_colormanagement_processor_apply_v4(cm_processor, pixel); + } if (display_buffer_float) { int index = ((y - ymin) * width + (x - xmin)) * channels; @@ -2173,9 +2383,9 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, const unsigned char *byte_buffer, int stride, int offset_x, int offset_y, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, - int xmin, int ymin, int xmax, int ymax) + int xmin, int ymin, int xmax, int ymax, int update_orig_byte_buffer) { - if (ibuf->rect && ibuf->rect_float) { + if ((ibuf->rect && ibuf->rect_float) || update_orig_byte_buffer) { /* update byte buffer created by legacy color management */ unsigned char *rect = (unsigned char *) ibuf->rect; @@ -2240,28 +2450,29 @@ ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManag const ColorManagedDisplaySettings *display_settings) { ColormanageProcessor *cm_processor; + ColorManagedViewSettings default_view_settings; + const ColorManagedViewSettings *applied_view_settings; + ColorSpace *display_space; cm_processor = MEM_callocN(sizeof(ColormanageProcessor), "colormanagement processor"); - { - ColorManagedViewSettings default_view_settings; - const ColorManagedViewSettings *applied_view_settings; + if (view_settings) { + applied_view_settings = view_settings; + } + else { + init_default_view_settings(display_settings, &default_view_settings); + applied_view_settings = &default_view_settings; + } - if (view_settings) { - applied_view_settings = view_settings; - } - else { - init_default_view_settings(display_settings, &default_view_settings); - applied_view_settings = &default_view_settings; - } + display_space = display_transform_get_colorspace(applied_view_settings, display_settings); + 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); + cm_processor->processor = create_display_buffer_processor(applied_view_settings->view_transform, display_settings->display_device, + applied_view_settings->exposure, applied_view_settings->gamma); - if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) { - cm_processor->curve_mapping = curvemapping_copy(applied_view_settings->curve_mapping); - curvemapping_premultiply(cm_processor->curve_mapping, FALSE); - } + if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) { + cm_processor->curve_mapping = curvemapping_copy(applied_view_settings->curve_mapping); + curvemapping_premultiply(cm_processor->curve_mapping, FALSE); } return cm_processor; @@ -2270,9 +2481,13 @@ ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManag ColormanageProcessor *IMB_colormanagement_colorspace_processor_new(const char *from_colorspace, const char *to_colorspace) { ColormanageProcessor *cm_processor; + ColorSpace *color_space; cm_processor = MEM_callocN(sizeof(ColormanageProcessor), "colormanagement processor"); + color_space = colormanage_colorspace_get_named(to_colorspace); + cm_processor->is_data_result = color_space->is_data; + cm_processor->processor = create_colorspace_transform_processor(from_colorspace, to_colorspace); return cm_processor; @@ -2283,7 +2498,8 @@ void IMB_colormanagement_processor_apply_v4(ColormanageProcessor *cm_processor, if (cm_processor->curve_mapping) curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel); - OCIO_processorApplyRGBA(cm_processor->processor, pixel); + if (cm_processor->processor) + OCIO_processorApplyRGBA(cm_processor->processor, pixel); } void IMB_colormanagement_processor_apply_v3(ColormanageProcessor *cm_processor, float pixel[3]) @@ -2291,7 +2507,8 @@ void IMB_colormanagement_processor_apply_v3(ColormanageProcessor *cm_processor, if (cm_processor->curve_mapping) curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel); - OCIO_processorApplyRGB(cm_processor->processor, pixel); + if (cm_processor->processor) + OCIO_processorApplyRGB(cm_processor->processor, pixel); } void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, float *buffer, int width, int height, @@ -2310,11 +2527,11 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, flo } } - { - PackedImageDesc *img; + if (cm_processor->processor && channels >= 3) { + OCIO_PackedImageDesc *img; /* apply OCIO processor */ - img = OCIO_createPackedImageDesc(buffer, width, height, channels, sizeof(float), + img = OCIO_createOCIO_PackedImageDesc(buffer, width, height, channels, sizeof(float), channels * sizeof(float), channels * sizeof(float) * width); if (predivide) @@ -2322,7 +2539,7 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, flo else OCIO_processorApply(cm_processor->processor, img); - OCIO_packedImageDescRelease(img); + OCIO_OCIO_PackedImageDescRelease(img); } } @@ -2330,8 +2547,8 @@ void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor) { if (cm_processor->curve_mapping) curvemapping_free(cm_processor->curve_mapping); - - OCIO_processorRelease(cm_processor->processor); + if (cm_processor->processor) + OCIO_processorRelease(cm_processor->processor); MEM_freeN(cm_processor); } diff --git a/source/blender/imbuf/intern/dds/BlockDXT.cpp b/source/blender/imbuf/intern/dds/BlockDXT.cpp index f5e9e536e41..db2ca5969ec 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.cpp +++ b/source/blender/imbuf/intern/dds/BlockDXT.cpp @@ -232,7 +232,7 @@ void BlockDXT1::decodeBlock(ColorBlock * block) const uint idx = (row[j] >> (2 * i)) & 3; block->color(i, j) = color_array[idx]; } - } + } } void BlockDXT1::decodeBlockNV5x(ColorBlock * block) const @@ -592,7 +592,7 @@ void BlockCTX1::decodeBlock(ColorBlock * block) const uint idx = (row[j] >> (2 * i)) & 3; block->color(i, j) = color_array[idx]; } - } + } } void BlockCTX1::setIndices(int * idx) diff --git a/source/blender/imbuf/intern/dds/BlockDXT.h b/source/blender/imbuf/intern/dds/BlockDXT.h index c6712f4f058..9b90b744b67 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.h +++ b/source/blender/imbuf/intern/dds/BlockDXT.h @@ -271,4 +271,4 @@ void mem_read(Stream & mem, BlockATI1 & block); void mem_read(Stream & mem, BlockATI2 & block); void mem_read(Stream & mem, BlockCTX1 & block); -#endif // __BLOCKDXT_H__ +#endif /* __BLOCKDXT_H__ */ diff --git a/source/blender/imbuf/intern/dds/CMakeLists.txt b/source/blender/imbuf/intern/dds/CMakeLists.txt index e514b7ab6f9..57603725ce1 100644 --- a/source/blender/imbuf/intern/dds/CMakeLists.txt +++ b/source/blender/imbuf/intern/dds/CMakeLists.txt @@ -39,9 +39,21 @@ set(INC_SYS ) set(SRC + BlockDXT.h + Color.h + ColorBlock.h + Common.h + DirectDrawSurface.h + FlipDXT.h + Image.h + PixelFormat.h + Stream.h + dds_api.h + BlockDXT.cpp ColorBlock.cpp DirectDrawSurface.cpp + FlipDXT.cpp Image.cpp Stream.cpp dds_api.cpp @@ -51,4 +63,4 @@ if(WITH_IMAGE_DDS) add_definitions(-DWITH_DDS) endif() -blender_add_lib(bf_imbuf_dds "${SRC}" "${INC}" "${INC_SYS}") +blender_add_lib(bf_imbuf_dds "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/imbuf/intern/dds/Color.h b/source/blender/imbuf/intern/dds/Color.h index 17de0a596c6..6676057d710 100644 --- a/source/blender/imbuf/intern/dds/Color.h +++ b/source/blender/imbuf/intern/dds/Color.h @@ -96,4 +96,4 @@ public: }; }; -#endif // __COLOR_H__ +#endif /* __COLOR_H__ */ diff --git a/source/blender/imbuf/intern/dds/ColorBlock.cpp b/source/blender/imbuf/intern/dds/ColorBlock.cpp index 0b9f5c163fb..dbd87bf1426 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.cpp +++ b/source/blender/imbuf/intern/dds/ColorBlock.cpp @@ -393,7 +393,7 @@ void ColorBlock::computeRange(Vector3::Arg axis, Color32 * start, Color32 * end) int mini, maxi; mini = maxi = 0; - float min, max; + float min, max; min = max = dot(Vector3(m_color[0].r, m_color[0].g, m_color[0].b), axis); for (uint i = 1; i < 16; i++) diff --git a/source/blender/imbuf/intern/dds/ColorBlock.h b/source/blender/imbuf/intern/dds/ColorBlock.h index 2bf362f2780..f0864f06e6f 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.h +++ b/source/blender/imbuf/intern/dds/ColorBlock.h @@ -104,4 +104,4 @@ inline Color32 & ColorBlock::color(uint x, uint y) return m_color[y * 4 + x]; } -#endif // __COLORBLOCK_H__ +#endif /* __COLORBLOCK_H__ */ diff --git a/source/blender/imbuf/intern/dds/Common.h b/source/blender/imbuf/intern/dds/Common.h index 4e3e3e024f7..ab929b82264 100644 --- a/source/blender/imbuf/intern/dds/Common.h +++ b/source/blender/imbuf/intern/dds/Common.h @@ -42,9 +42,9 @@ template inline void swap(T & a, T & b) { - T tmp = a; - a = b; - b = tmp; + T tmp = a; + a = b; + b = tmp; } typedef unsigned char uint8; diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp index 82f355e1bb2..ccf72f9af86 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp @@ -280,19 +280,19 @@ static const uint DDPF_SRGB = 0x40000000U; DXGI_FORMAT_B8G8R8A8_UNORM = 87, DXGI_FORMAT_B8G8R8X8_UNORM = 88, - DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89, - DXGI_FORMAT_B8G8R8A8_TYPELESS = 90, - DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91, - DXGI_FORMAT_B8G8R8X8_TYPELESS = 92, - DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93, + DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89, + DXGI_FORMAT_B8G8R8A8_TYPELESS = 90, + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91, + DXGI_FORMAT_B8G8R8X8_TYPELESS = 92, + DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93, - DXGI_FORMAT_BC6H_TYPELESS = 94, - DXGI_FORMAT_BC6H_UF16 = 95, - DXGI_FORMAT_BC6H_SF16 = 96, + DXGI_FORMAT_BC6H_TYPELESS = 94, + DXGI_FORMAT_BC6H_UF16 = 95, + DXGI_FORMAT_BC6H_SF16 = 96, - DXGI_FORMAT_BC7_TYPELESS = 97, - DXGI_FORMAT_BC7_UNORM = 98, - DXGI_FORMAT_BC7_UNORM_SRGB = 99, + DXGI_FORMAT_BC7_TYPELESS = 97, + DXGI_FORMAT_BC7_UNORM = 98, + DXGI_FORMAT_BC7_UNORM_SRGB = 99, }; enum D3D10_RESOURCE_DIMENSION @@ -305,7 +305,7 @@ static const uint DDPF_SRGB = 0x40000000U; }; - const char * getDxgiFormatString(DXGI_FORMAT dxgiFormat) + static const char * getDxgiFormatString(DXGI_FORMAT dxgiFormat) { #define CASE(format) case DXGI_FORMAT_##format: return #format switch (dxgiFormat) @@ -429,7 +429,7 @@ static const uint DDPF_SRGB = 0x40000000U; #undef CASE } - const char * getD3d10ResourceDimensionString(D3D10_RESOURCE_DIMENSION resourceDimension) + static const char * getD3d10ResourceDimensionString(D3D10_RESOURCE_DIMENSION resourceDimension) { switch (resourceDimension) { @@ -496,60 +496,60 @@ void mem_read(Stream & mem, DDSHeader & header) namespace { - struct FormatDescriptor - { - uint format; - uint bitcount; - uint rmask; - uint gmask; - uint bmask; - uint amask; - }; +struct FormatDescriptor +{ + uint format; + uint bitcount; + uint rmask; + uint gmask; + uint bmask; + uint amask; +}; - static const FormatDescriptor s_d3dFormats[] = - { - { D3DFMT_R8G8B8, 24, 0xFF0000, 0xFF00, 0xFF, 0 }, - { D3DFMT_A8R8G8B8, 32, 0xFF0000, 0xFF00, 0xFF, 0xFF000000 }, // DXGI_FORMAT_B8G8R8A8_UNORM - { D3DFMT_X8R8G8B8, 32, 0xFF0000, 0xFF00, 0xFF, 0 }, // DXGI_FORMAT_B8G8R8X8_UNORM - { D3DFMT_R5G6B5, 16, 0xF800, 0x7E0, 0x1F, 0 }, // DXGI_FORMAT_B5G6R5_UNORM - { D3DFMT_X1R5G5B5, 16, 0x7C00, 0x3E0, 0x1F, 0 }, - { D3DFMT_A1R5G5B5, 16, 0x7C00, 0x3E0, 0x1F, 0x8000 }, // DXGI_FORMAT_B5G5R5A1_UNORM - { D3DFMT_A4R4G4B4, 16, 0xF00, 0xF0, 0xF, 0xF000 }, - { D3DFMT_R3G3B2, 8, 0xE0, 0x1C, 0x3, 0 }, - { D3DFMT_A8, 8, 0, 0, 0, 8 }, // DXGI_FORMAT_A8_UNORM - { D3DFMT_A8R3G3B2, 16, 0xE0, 0x1C, 0x3, 0xFF00 }, - { D3DFMT_X4R4G4B4, 16, 0xF00, 0xF0, 0xF, 0 }, - { D3DFMT_A2B10G10R10, 32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000 }, // DXGI_FORMAT_R10G10B10A2 - { D3DFMT_A8B8G8R8, 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000 }, // DXGI_FORMAT_R8G8B8A8_UNORM - { D3DFMT_X8B8G8R8, 32, 0xFF, 0xFF00, 0xFF0000, 0 }, - { D3DFMT_G16R16, 32, 0xFFFF, 0xFFFF0000, 0, 0 }, // DXGI_FORMAT_R16G16_UNORM - { D3DFMT_A2R10G10B10, 32, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000 }, - { D3DFMT_A2B10G10R10, 32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000 }, +static const FormatDescriptor s_d3dFormats[] = +{ + { D3DFMT_R8G8B8, 24, 0xFF0000, 0xFF00, 0xFF, 0 }, + { D3DFMT_A8R8G8B8, 32, 0xFF0000, 0xFF00, 0xFF, 0xFF000000 }, /* DXGI_FORMAT_B8G8R8A8_UNORM */ + { D3DFMT_X8R8G8B8, 32, 0xFF0000, 0xFF00, 0xFF, 0 }, /* DXGI_FORMAT_B8G8R8X8_UNORM */ + { D3DFMT_R5G6B5, 16, 0xF800, 0x7E0, 0x1F, 0 }, /* DXGI_FORMAT_B5G6R5_UNORM */ + { D3DFMT_X1R5G5B5, 16, 0x7C00, 0x3E0, 0x1F, 0 }, + { D3DFMT_A1R5G5B5, 16, 0x7C00, 0x3E0, 0x1F, 0x8000 }, /* DXGI_FORMAT_B5G5R5A1_UNORM */ + { D3DFMT_A4R4G4B4, 16, 0xF00, 0xF0, 0xF, 0xF000 }, + { D3DFMT_R3G3B2, 8, 0xE0, 0x1C, 0x3, 0 }, + { D3DFMT_A8, 8, 0, 0, 0, 8 }, /* DXGI_FORMAT_A8_UNORM */ + { D3DFMT_A8R3G3B2, 16, 0xE0, 0x1C, 0x3, 0xFF00 }, + { D3DFMT_X4R4G4B4, 16, 0xF00, 0xF0, 0xF, 0 }, + { D3DFMT_A2B10G10R10, 32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000 }, /* DXGI_FORMAT_R10G10B10A2 */ + { D3DFMT_A8B8G8R8, 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000 }, /* DXGI_FORMAT_R8G8B8A8_UNORM */ + { D3DFMT_X8B8G8R8, 32, 0xFF, 0xFF00, 0xFF0000, 0 }, + { D3DFMT_G16R16, 32, 0xFFFF, 0xFFFF0000, 0, 0 }, /* DXGI_FORMAT_R16G16_UNORM */ + { D3DFMT_A2R10G10B10, 32, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000 }, + { D3DFMT_A2B10G10R10, 32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000 }, - { D3DFMT_L8, 8, 8, 0, 0, 0 }, // DXGI_FORMAT_R8_UNORM - { D3DFMT_L16, 16, 16, 0, 0, 0 }, // DXGI_FORMAT_R16_UNORM - }; + { D3DFMT_L8, 8, 8, 0, 0, 0 }, /* DXGI_FORMAT_R8_UNORM */ + { D3DFMT_L16, 16, 16, 0, 0, 0 }, /* DXGI_FORMAT_R16_UNORM */ +}; - static const uint s_d3dFormatCount = sizeof(s_d3dFormats) / sizeof(s_d3dFormats[0]); +static const uint s_d3dFormatCount = sizeof(s_d3dFormats) / sizeof(s_d3dFormats[0]); } // namespace -uint findD3D9Format(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask) +static uint findD3D9Format(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask) { - for (int i = 0; i < s_d3dFormatCount; i++) - { - if (s_d3dFormats[i].bitcount == bitcount && - s_d3dFormats[i].rmask == rmask && - s_d3dFormats[i].gmask == gmask && - s_d3dFormats[i].bmask == bmask && - s_d3dFormats[i].amask == amask) - { - return s_d3dFormats[i].format; - } - } + for (int i = 0; i < s_d3dFormatCount; i++) + { + if (s_d3dFormats[i].bitcount == bitcount && + s_d3dFormats[i].rmask == rmask && + s_d3dFormats[i].gmask == gmask && + s_d3dFormats[i].bmask == bmask && + s_d3dFormats[i].amask == amask) + { + return s_d3dFormats[i].format; + } + } - return 0; - } + return 0; +} @@ -566,7 +566,7 @@ DDSHeader::DDSHeader() for (uint i = 0; i < 11; i++) this->reserved[i] = 0; // Store version information on the reserved header attributes. - this->reserved[9] = FOURCC_NVTT; + this->reserved[9] = FOURCC_NVTT; this->reserved[10] = (2 << 16) | (1 << 8) | (0); // major.minor.revision this->pf.size = 32; @@ -613,7 +613,7 @@ void DDSHeader::setMipmapCount(uint count) if (count == 0 || count == 1) { this->flags &= ~DDSD_MIPMAPCOUNT; - this->mipmapcount = 1; + this->mipmapcount = 1; if (this->caps.caps2 == 0) { this->caps.caps1 = DDSCAPS_TEXTURE; @@ -715,14 +715,14 @@ void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask if (rmask != 0 || gmask != 0 || bmask != 0) { - if (gmask == 0 && bmask == 0) - { - this->pf.flags = DDPF_LUMINANCE; - } - else - { - this->pf.flags = DDPF_RGB; - } + if (gmask == 0 && bmask == 0) + { + this->pf.flags = DDPF_LUMINANCE; + } + else + { + this->pf.flags = DDPF_RGB; + } if (amask != 0) { this->pf.flags |= DDPF_ALPHAPIXELS; @@ -737,17 +737,17 @@ void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask { // Compute bit count from the masks. uint total = rmask | gmask | bmask | amask; - while(total != 0) { + while (total != 0) { bitcount++; total >>= 1; } } - // D3DX functions do not like this: + // D3DX functions do not like this: this->pf.fourcc = 0; //findD3D9Format(bitcount, rmask, gmask, bmask, amask); - /*if (this->pf.fourcc) { - this->pf.flags |= DDPF_FOURCC; - }*/ + /*if (this->pf.fourcc) { + this->pf.flags |= DDPF_FOURCC; + }*/ if (!(bitcount > 0 && bitcount <= 32)) { printf("DDS: bad bit count, pixel format not set\n"); @@ -775,8 +775,8 @@ void DDSHeader::setNormalFlag(bool b) void DDSHeader::setSrgbFlag(bool b) { - if (b) this->pf.flags |= DDPF_SRGB; - else this->pf.flags &= ~DDPF_SRGB; + if (b) this->pf.flags |= DDPF_SRGB; + else this->pf.flags &= ~DDPF_SRGB; } void DDSHeader::setHasAlphaFlag(bool b) @@ -787,8 +787,8 @@ void DDSHeader::setHasAlphaFlag(bool b) void DDSHeader::setUserVersion(int version) { - this->reserved[7] = FOURCC_UVER; - this->reserved[8] = version; + this->reserved[7] = FOURCC_UVER; + this->reserved[8] = version; } /* @@ -836,45 +836,45 @@ bool DDSHeader::hasDX10Header() const uint DDSHeader::signature() const { - return this->reserved[9]; + return this->reserved[9]; } uint DDSHeader::toolVersion() const { - return this->reserved[10]; + return this->reserved[10]; } uint DDSHeader::userVersion() const { - if (this->reserved[7] == FOURCC_UVER) { - return this->reserved[8]; - } - return 0; + if (this->reserved[7] == FOURCC_UVER) { + return this->reserved[8]; + } + return 0; } bool DDSHeader::isNormalMap() const { - return (pf.flags & DDPF_NORMAL) != 0; + return (pf.flags & DDPF_NORMAL) != 0; } bool DDSHeader::isSrgb() const { - return (pf.flags & DDPF_SRGB) != 0; + return (pf.flags & DDPF_SRGB) != 0; } bool DDSHeader::hasAlpha() const { - return (pf.flags & DDPF_ALPHAPIXELS) != 0; + return (pf.flags & DDPF_ALPHAPIXELS) != 0; } uint DDSHeader::d3d9Format() const { - if (pf.flags & DDPF_FOURCC) { - return pf.fourcc; - } - else { - return findD3D9Format(pf.bitcount, pf.rmask, pf.gmask, pf.bmask, pf.amask); - } + if (pf.flags & DDPF_FOURCC) { + return pf.fourcc; + } + else { + return findD3D9Format(pf.bitcount, pf.rmask, pf.gmask, pf.bmask, pf.amask); + } } DirectDrawSurface::DirectDrawSurface(unsigned char *mem, uint size) : stream(mem, size), header() @@ -949,9 +949,9 @@ bool DirectDrawSurface::isSupported() const return false; } } - else if ((header.pf.flags & DDPF_RGB) || (header.pf.flags & DDPF_LUMINANCE)) - { - // All RGB and luminance formats are supported now. + else if ((header.pf.flags & DDPF_RGB) || (header.pf.flags & DDPF_LUMINANCE)) + { + // All RGB and luminance formats are supported now. } else { @@ -1001,7 +1001,7 @@ bool DirectDrawSurface::hasAlpha() const } else { - // @@ Here we could check the ALPHA_PIXELS flag, but nobody sets it. (except us?) + // @@ Here we could check the ALPHA_PIXELS flag, but nobody sets it. (except us?) return true; } } @@ -1089,7 +1089,7 @@ void DirectDrawSurface::setHasAlphaFlag(bool b) void DirectDrawSurface::setUserVersion(int version) { - header.setUserVersion(version); + header.setUserVersion(version); } void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap) @@ -1268,15 +1268,15 @@ void DirectDrawSurface::readBlock(ColorBlock * rgba) block.decodeBlock(rgba); } else if (fourcc == FOURCC_DXT2 || - header.pf.fourcc == FOURCC_DXT3) + header.pf.fourcc == FOURCC_DXT3) { BlockDXT3 block; mem_read(stream, block); block.decodeBlock(rgba); } else if (fourcc == FOURCC_DXT4 || - header.pf.fourcc == FOURCC_DXT5 || - header.pf.fourcc == FOURCC_RXGB) + header.pf.fourcc == FOURCC_DXT5 || + header.pf.fourcc == FOURCC_RXGB) { BlockDXT5 block; mem_read(stream, block); @@ -1393,8 +1393,8 @@ uint DirectDrawSurface::mipmapSize(uint mipmap) const } else if (header.pf.flags & DDPF_RGB || (header.pf.flags & DDPF_LUMINANCE)) { - uint pitch = computePitch(w, header.pf.bitcount, 8); // Asuming 8 bit alignment, which is the same D3DX expects. - + uint pitch = computePitch(w, header.pf.bitcount, 8); // Asuming 8 bit alignment, which is the same D3DX expects. + return pitch * h * d; } else { @@ -1461,7 +1461,7 @@ void DirectDrawSurface::printInfo() const printf("Pixel Format:\n"); printf("\tFlags: 0x%.8X\n", header.pf.flags); if (header.pf.flags & DDPF_RGB) printf("\t\tDDPF_RGB\n"); - if (header.pf.flags & DDPF_LUMINANCE) printf("\t\tDDPF_LUMINANCE\n"); + if (header.pf.flags & DDPF_LUMINANCE) printf("\t\tDDPF_LUMINANCE\n"); if (header.pf.flags & DDPF_FOURCC) printf("\t\tDDPF_FOURCC\n"); if (header.pf.flags & DDPF_ALPHAPIXELS) printf("\t\tDDPF_ALPHAPIXELS\n"); if (header.pf.flags & DDPF_ALPHA) printf("\t\tDDPF_ALPHA\n"); @@ -1472,24 +1472,24 @@ void DirectDrawSurface::printInfo() const if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n"); if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n"); - if (header.pf.fourcc != 0) { - // Display fourcc code even when DDPF_FOURCC flag not set. - printf("\tFourCC: '%c%c%c%c' (0x%.8X)\n", - ((header.pf.fourcc >> 0) & 0xFF), - ((header.pf.fourcc >> 8) & 0xFF), - ((header.pf.fourcc >> 16) & 0xFF), - ((header.pf.fourcc >> 24) & 0xFF), - header.pf.fourcc); - } + if (header.pf.fourcc != 0) { + // Display fourcc code even when DDPF_FOURCC flag not set. + printf("\tFourCC: '%c%c%c%c' (0x%.8X)\n", + ((header.pf.fourcc >> 0) & 0xFF), + ((header.pf.fourcc >> 8) & 0xFF), + ((header.pf.fourcc >> 16) & 0xFF), + ((header.pf.fourcc >> 24) & 0xFF), + header.pf.fourcc); + } - if ((header.pf.flags & DDPF_FOURCC) && (header.pf.bitcount != 0)) + if ((header.pf.flags & DDPF_FOURCC) && (header.pf.bitcount != 0)) { - printf("\tSwizzle: '%c%c%c%c' (0x%.8X)\n", - (header.pf.bitcount >> 0) & 0xFF, - (header.pf.bitcount >> 8) & 0xFF, - (header.pf.bitcount >> 16) & 0xFF, - (header.pf.bitcount >> 24) & 0xFF, - header.pf.bitcount); + printf("\tSwizzle: '%c%c%c%c' (0x%.8X)\n", + (header.pf.bitcount >> 0) & 0xFF, + (header.pf.bitcount >> 8) & 0xFF, + (header.pf.bitcount >> 16) & 0xFF, + (header.pf.bitcount >> 24) & 0xFF, + header.pf.bitcount); } else { @@ -1535,7 +1535,7 @@ void DirectDrawSurface::printInfo() const printf("\tArray size: %u\n", header.header10.arraySize); } - if (header.reserved[9] == FOURCC_NVTT) + if (header.reserved[9] == FOURCC_NVTT) { int major = (header.reserved[10] >> 16) & 0xFF; int minor = (header.reserved[10] >> 8) & 0xFF; @@ -1545,9 +1545,9 @@ void DirectDrawSurface::printInfo() const printf("\tNVIDIA Texture Tools %d.%d.%d\n", major, minor, revision); } - if (header.reserved[7] == FOURCC_UVER) - { - printf("User Version: %u\n", header.reserved[8]); - } + if (header.reserved[7] == FOURCC_UVER) + { + printf("User Version: %u\n", header.reserved[8]); + } } diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.h b/source/blender/imbuf/intern/dds/DirectDrawSurface.h index a851533b1f3..72a524daba2 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.h +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.h @@ -169,7 +169,7 @@ public: void setNormalFlag(bool b); void setHasAlphaFlag(bool b); - void setUserVersion(int version); + void setUserVersion(int version); void mipmap(Image * img, uint f, uint m); void* readData(uint &size); @@ -200,4 +200,4 @@ void mem_read(Stream & mem, DDSCaps & caps); void mem_read(Stream & mem, DDSHeader & header); void mem_read(Stream & mem, DDSHeader10 & header); -#endif // __DIRECTDRAWSURFACE_H__ +#endif /* __DIRECTDRAWSURFACE_H__ */ diff --git a/source/blender/imbuf/intern/dds/FlipDXT.cpp b/source/blender/imbuf/intern/dds/FlipDXT.cpp new file mode 100644 index 00000000000..ee7a0ebb2f7 --- /dev/null +++ b/source/blender/imbuf/intern/dds/FlipDXT.cpp @@ -0,0 +1,255 @@ +/* + * Copyright 2009, Google Inc. + * All rights reserved. + * + * 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 Google Inc. 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. + */ + +// This file comes from the chromium project, adapted to Blender to add DDS +// flipping to OpenGL convention for Blender + +#include "IMB_imbuf_types.h" + +#include + +#include +#include +#include +#include +#include + +// A function that flips a DXTC block. +typedef void (*FlipBlockFunction)(uint8_t *block); + +// Flips a full DXT1 block in the y direction. +static void FlipDXT1BlockFull(uint8_t *block) +{ + // A DXT1 block layout is: + // [0-1] color0. + // [2-3] color1. + // [4-7] color bitmap, 2 bits per pixel. + // So each of the 4-7 bytes represents one line, flipping a block is just + // flipping those bytes. + uint8_t tmp = block[4]; + block[4] = block[7]; + block[7] = tmp; + tmp = block[5]; + block[5] = block[6]; + block[6] = tmp; +} + +// Flips the first 2 lines of a DXT1 block in the y direction. +static void FlipDXT1BlockHalf(uint8_t *block) +{ + // See layout above. + uint8_t tmp = block[4]; + block[4] = block[5]; + block[5] = tmp; +} + +// Flips a full DXT3 block in the y direction. +static void FlipDXT3BlockFull(uint8_t *block) +{ + // A DXT3 block layout is: + // [0-7] alpha bitmap, 4 bits per pixel. + // [8-15] a DXT1 block. + + // We can flip the alpha bits at the byte level (2 bytes per line). + uint8_t tmp = block[0]; + + block[0] = block[6]; + block[6] = tmp; + tmp = block[1]; + block[1] = block[7]; + block[7] = tmp; + tmp = block[2]; + block[2] = block[4]; + block[4] = tmp; + tmp = block[3]; + block[3] = block[5]; + block[5] = tmp; + + // And flip the DXT1 block using the above function. + FlipDXT1BlockFull(block + 8); +} + +// Flips the first 2 lines of a DXT3 block in the y direction. +static void FlipDXT3BlockHalf(uint8_t *block) +{ + // See layout above. + uint8_t tmp = block[0]; + + block[0] = block[2]; + block[2] = tmp; + tmp = block[1]; + block[1] = block[3]; + block[3] = tmp; + FlipDXT1BlockHalf(block + 8); +} + +// Flips a full DXT5 block in the y direction. +static void FlipDXT5BlockFull(uint8_t *block) +{ + // A DXT5 block layout is: + // [0] alpha0. + // [1] alpha1. + // [2-7] alpha bitmap, 3 bits per pixel. + // [8-15] a DXT1 block. + + // The alpha bitmap doesn't easily map lines to bytes, so we have to + // interpret it correctly. Extracted from + // http://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt : + // + // The 6 "bits" bytes of the block are decoded into one 48-bit integer: + // + // bits = bits_0 + 256 * (bits_1 + 256 * (bits_2 + 256 * (bits_3 + + // 256 * (bits_4 + 256 * bits_5)))) + // + // bits is a 48-bit unsigned integer, from which a three-bit control code + // is extracted for a texel at location (x,y) in the block using: + // + // code(x,y) = bits[3*(4*y+x)+1..3*(4*y+x)+0] + // + // where bit 47 is the most significant and bit 0 is the least + // significant bit. + unsigned int line_0_1 = block[2] + 256 * (block[3] + 256 * block[4]); + unsigned int line_2_3 = block[5] + 256 * (block[6] + 256 * block[7]); + // swap lines 0 and 1 in line_0_1. + unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) | + ((line_0_1 & 0xfff000) >> 12); + // swap lines 2 and 3 in line_2_3. + unsigned int line_3_2 = ((line_2_3 & 0x000fff) << 12) | + ((line_2_3 & 0xfff000) >> 12); + + block[2] = line_3_2 & 0xff; + block[3] = (line_3_2 & 0xff00) >> 8; + block[4] = (line_3_2 & 0xff0000) >> 8; + block[5] = line_1_0 & 0xff; + block[6] = (line_1_0 & 0xff00) >> 8; + block[7] = (line_1_0 & 0xff0000) >> 8; + + // And flip the DXT1 block using the above function. + FlipDXT1BlockFull(block + 8); +} + +// Flips the first 2 lines of a DXT5 block in the y direction. +static void FlipDXT5BlockHalf(uint8_t *block) +{ + // See layout above. + unsigned int line_0_1 = block[2] + 256 * (block[3] + 256 * block[4]); + unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) | + ((line_0_1 & 0xfff000) >> 12); + block[2] = line_1_0 & 0xff; + block[3] = (line_1_0 & 0xff00) >> 8; + block[4] = (line_1_0 & 0xff0000) >> 8; + FlipDXT1BlockHalf(block + 8); +} + +// Flips a DXTC image, by flipping and swapping DXTC blocks as appropriate. +int FlipDXTCImage(unsigned int width, unsigned int height, unsigned int levels, int fourcc, uint8_t *data) +{ + // must have valid dimensions + if (width == 0 || height == 0) + return 0; + // height must be a power-of-two + if ((height & (height - 1)) != 0) + return 0; + + FlipBlockFunction full_block_function; + FlipBlockFunction half_block_function; + unsigned int block_bytes = 0; + + switch (fourcc) { + case FOURCC_DXT1: + full_block_function = FlipDXT1BlockFull; + half_block_function = FlipDXT1BlockHalf; + block_bytes = 8; + break; + case FOURCC_DXT3: + full_block_function = FlipDXT3BlockFull; + half_block_function = FlipDXT3BlockHalf; + block_bytes = 16; + break; + case FOURCC_DXT5: + full_block_function = FlipDXT5BlockFull; + half_block_function = FlipDXT5BlockHalf; + block_bytes = 16; + break; + default: + return 0; + } + + unsigned int mip_width = width; + unsigned int mip_height = height; + + for (unsigned int i = 0; i < levels; ++i) { + unsigned int blocks_per_row = (mip_width + 3) / 4; + unsigned int blocks_per_col = (mip_height + 3) / 4; + unsigned int blocks = blocks_per_row * blocks_per_col; + + if (mip_height == 1) { + // no flip to do, and we're done. + break; + } + else if (mip_height == 2) { + // flip the first 2 lines in each block. + for (unsigned int i = 0; i < blocks_per_row; ++i) { + half_block_function(data + i * block_bytes); + } + } + else { + // flip each block. + for (unsigned int i = 0; i < blocks; ++i) + full_block_function(data + i * block_bytes); + + // swap each block line in the first half of the image with the + // corresponding one in the second half. + // note that this is a no-op if mip_height is 4. + unsigned int row_bytes = block_bytes * blocks_per_row; + uint8_t *temp_line = new uint8_t[row_bytes]; + + for (unsigned int y = 0; y < blocks_per_col / 2; ++y) { + uint8_t *line1 = data + y * row_bytes; + uint8_t *line2 = data + (blocks_per_col - y - 1) * row_bytes; + + memcpy(temp_line, line1, row_bytes); + memcpy(line1, line2, row_bytes); + memcpy(line2, temp_line, row_bytes); + } + + delete temp_line; + } + + // mip levels are contiguous. + data += block_bytes * blocks; + mip_width = max(1U, mip_width >> 1); + mip_height = max(1U, mip_height >> 1); + } + + return 1; +} + diff --git a/source/blender/imbuf/intern/dds/FlipDXT.h b/source/blender/imbuf/intern/dds/FlipDXT.h new file mode 100644 index 00000000000..8d0ae8139a1 --- /dev/null +++ b/source/blender/imbuf/intern/dds/FlipDXT.h @@ -0,0 +1,32 @@ +/* + * ***** 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. + * + * Contributors: Amorilia (amorilia@users.sourceforge.net) + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FLIPDXT_H__ +#define __FLIPDXT_H__ + +#include "MEM_sys_types.h" + +/* flip compressed DXT image vertically to fit OpenGL convention */ +int FlipDXTCImage(unsigned int width, unsigned int height, unsigned int levels, int fourcc, uint8_t *data); + +#endif + diff --git a/source/blender/imbuf/intern/dds/Image.h b/source/blender/imbuf/intern/dds/Image.h index 5dcf3011c76..81074fba6b7 100644 --- a/source/blender/imbuf/intern/dds/Image.h +++ b/source/blender/imbuf/intern/dds/Image.h @@ -101,4 +101,4 @@ inline Color32 & Image::pixel(uint x, uint y) return pixel(y * width() + x); } -#endif // __IMAGE_H__ +#endif /* __IMAGE_H__ */ diff --git a/source/blender/imbuf/intern/dds/PixelFormat.h b/source/blender/imbuf/intern/dds/PixelFormat.h index 308ea810f03..2bb1864e49d 100644 --- a/source/blender/imbuf/intern/dds/PixelFormat.h +++ b/source/blender/imbuf/intern/dds/PixelFormat.h @@ -101,38 +101,38 @@ } } - inline float quantizeCeil(float f, int inbits, int outbits) - { - //uint i = f * (float(1 << inbits) - 1); - //i = convert(i, inbits, outbits); - //float result = float(i) / (float(1 << outbits) - 1); - //nvCheck(result >= f); - float result; - int offset = 0; - do { - uint i = offset + uint(f * (float(1 << inbits) - 1)); - i = convert(i, inbits, outbits); - result = float(i) / (float(1 << outbits) - 1); - offset++; - } while (result < f); + inline float quantizeCeil(float f, int inbits, int outbits) + { + //uint i = f * (float(1 << inbits) - 1); + //i = convert(i, inbits, outbits); + //float result = float(i) / (float(1 << outbits) - 1); + //nvCheck(result >= f); + float result; + int offset = 0; + do { + uint i = offset + uint(f * (float(1 << inbits) - 1)); + i = convert(i, inbits, outbits); + result = float(i) / (float(1 << outbits) - 1); + offset++; + } while (result < f); - return result; - } + return result; + } - /* - inline float quantizeRound(float f, int bits) - { - float scale = float(1 << bits); - return fround(f * scale) / scale; - } +#if 0 + inline float quantizeRound(float f, int bits) + { + float scale = float(1 << bits); + return fround(f * scale) / scale; + } - inline float quantizeFloor(float f, int bits) - { - float scale = float(1 << bits); - return floor(f * scale) / scale; - } - */ + inline float quantizeFloor(float f, int bits) + { + float scale = float(1 << bits); + return floor(f * scale) / scale; + } +#endif } // PixelFormat namespace -#endif // _DDS_IMAGE_PIXELFORMAT_H +#endif /* __PIXELFORMAT_H__ */ diff --git a/source/blender/imbuf/intern/dds/SConscript b/source/blender/imbuf/intern/dds/SConscript index 4245f5001b9..d5a613f5981 100644 --- a/source/blender/imbuf/intern/dds/SConscript +++ b/source/blender/imbuf/intern/dds/SConscript @@ -1,7 +1,7 @@ #!/usr/bin/python Import ('env') -source_files = ['dds_api.cpp', 'DirectDrawSurface.cpp', 'Stream.cpp', 'BlockDXT.cpp', 'ColorBlock.cpp', 'Image.cpp'] +source_files = ['dds_api.cpp', 'DirectDrawSurface.cpp', 'Stream.cpp', 'BlockDXT.cpp', 'ColorBlock.cpp', 'Image.cpp', 'FlipDXT.cpp'] incs = ['.', '../../', diff --git a/source/blender/imbuf/intern/dds/Stream.h b/source/blender/imbuf/intern/dds/Stream.h index 9f513ca8aba..7fed4ca89e7 100644 --- a/source/blender/imbuf/intern/dds/Stream.h +++ b/source/blender/imbuf/intern/dds/Stream.h @@ -45,5 +45,4 @@ unsigned int mem_read(Stream & mem, unsigned short & i); unsigned int mem_read(Stream & mem, unsigned char & i); unsigned int mem_read(Stream & mem, unsigned char *i, unsigned int cnt); -#endif // __STREAM_H__ - +#endif /* __STREAM_H__ */ diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index 7aacbf20bae..5459cffe590 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include // printf #include @@ -162,13 +163,18 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags, char colo rect[i] = col; } - if (ibuf->dds_data.fourcc != FOURCC_DDS) + if (ibuf->dds_data.fourcc != FOURCC_DDS) { ibuf->dds_data.data = (unsigned char*)dds.readData(ibuf->dds_data.size); + + /* flip compressed texture */ + FlipDXTCImage(dds.width(), dds.height(), dds.mipmapCount(), dds.fourCC(), ibuf->dds_data.data); + } else { ibuf->dds_data.data = NULL; ibuf->dds_data.size = 0; } + /* flip uncompressed texture */ IMB_flipy(ibuf); } diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 9ce5d0e30da..55c1b02e90b 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -43,6 +43,8 @@ #include "IMB_colormanagement.h" #include "IMB_colormanagement_intern.h" +#include "BLI_threads.h" + #include "MEM_guardedalloc.h" /**************************** Interlace/Deinterlace **************************/ @@ -60,7 +62,7 @@ void IMB_de_interlace(ImBuf *ibuf) tbuf1 = IMB_allocImBuf(ibuf->x, ibuf->y / 2, 32, IB_rect); tbuf2 = IMB_allocImBuf(ibuf->x, ibuf->y / 2, 32, IB_rect); - ibuf->x *= 2; + ibuf->x *= 2; IMB_rectcpy(tbuf1, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y); IMB_rectcpy(tbuf2, ibuf, 0, 0, tbuf2->x, 0, ibuf->x, ibuf->y); @@ -559,7 +561,7 @@ void IMB_rect_from_float(ImBuf *ibuf) } /* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */ -void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w, int h) +void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w, int h, int is_data) { float *rect_float; uchar *rect_byte; @@ -578,14 +580,27 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w rect_float = ibuf->rect_float + (x + y * ibuf->x) * ibuf->channels; rect_byte = (uchar *)ibuf->rect + (x + y * ibuf->x) * 4; - IMB_buffer_float_from_float(buffer, rect_float, - ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide, - w, h, w, ibuf->x); + if (is_data) { + /* exception for non-color data, just copy float */ + IMB_buffer_float_from_float(buffer, rect_float, + ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, 0, + w, h, w, ibuf->x); - /* XXX: need to convert to image buffer's rect space */ - IMB_buffer_byte_from_float(rect_byte, buffer, - 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0, - w, h, ibuf->x, w); + /* and do color space conversion to byte */ + IMB_buffer_byte_from_float(rect_byte, rect_float, + 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide, + w, h, ibuf->x, w); + } + else { + IMB_buffer_float_from_float(buffer, rect_float, + ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide, + w, h, w, ibuf->x); + + /* XXX: need to convert to image buffer's rect space */ + IMB_buffer_byte_from_float(rect_byte, buffer, + 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0, + w, h, ibuf->x, w); + } /* ensure user flag is reset */ ibuf->userflags &= ~IB_RECT_INVALID; @@ -599,9 +614,18 @@ void IMB_float_from_rect(ImBuf *ibuf) if (ibuf->rect == NULL) return; + /* lock the color management thread + * need this because allocated but not filled float buffer will confuse + * display transform which lead to black areas across the frame + */ + BLI_lock_thread(LOCK_COLORMANAGE); + if (ibuf->rect_float == NULL) { - if (imb_addrectfloatImBuf(ibuf) == 0) + if (imb_addrectfloatImBuf(ibuf) == 0) { + BLI_unlock_thread(LOCK_COLORMANAGE); + return; + } } /* first, create float buffer in non-linear space */ @@ -611,6 +635,8 @@ void IMB_float_from_rect(ImBuf *ibuf) /* then make float be in linear space */ IMB_colormanagement_colorspace_to_scene_linear(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, ibuf->rect_colorspace, predivide); + + BLI_unlock_thread(LOCK_COLORMANAGE); } /* no profile conversion */ @@ -697,7 +723,7 @@ void IMB_buffer_float_clamp(float *buf, int width, int height) { int i, total = width * height * 4; for (i = 0; i < total; i++) { - buf[i] = minf(1.0, buf[i]); + buf[i] = min_ff(1.0, buf[i]); } } diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c index ed4db50035d..5c2dc0c7df9 100644 --- a/source/blender/imbuf/intern/filetype.c +++ b/source/blender/imbuf/intern/filetype.c @@ -74,8 +74,8 @@ ImFileType IMB_FILE_TYPES[] = { {NULL, NULL, imb_is_a_targa, imb_ftype_default, imb_loadtarga, imb_savetarga, NULL, 0, TGA, COLOR_ROLE_DEFAULT_BYTE}, {NULL, NULL, imb_is_a_iris, imb_ftype_iris, imb_loadiris, imb_saveiris, NULL, 0, IMAGIC, COLOR_ROLE_DEFAULT_BYTE}, #ifdef WITH_CINEON - {NULL, NULL, imb_is_dpx, imb_ftype_default, imb_loaddpx, imb_save_dpx, NULL, IM_FTYPE_FLOAT, DPX, COLOR_ROLE_DEFAULT_FLOAT}, - {NULL, NULL, imb_is_cineon, imb_ftype_default, imb_loadcineon, imb_savecineon, NULL, IM_FTYPE_FLOAT, CINEON, COLOR_ROLE_DEFAULT_FLOAT}, + {NULL, NULL, imb_is_dpx, imb_ftype_default, imb_load_dpx, imb_save_dpx, NULL, IM_FTYPE_FLOAT, DPX, COLOR_ROLE_DEFAULT_FLOAT}, + {NULL, NULL, imb_is_cineon, imb_ftype_default, imb_load_cineon, imb_save_cineon, NULL, IM_FTYPE_FLOAT, CINEON, COLOR_ROLE_DEFAULT_FLOAT}, #endif #ifdef WITH_TIFF {imb_inittiff, NULL, imb_is_a_tiff, imb_ftype_default, imb_loadtiff, imb_savetiff, imb_loadtiletiff, 0, TIF, COLOR_ROLE_DEFAULT_BYTE}, diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c index 3fd06a7c34d..57fbce710a1 100644 --- a/source/blender/imbuf/intern/imageprocess.c +++ b/source/blender/imbuf/intern/imageprocess.c @@ -125,15 +125,16 @@ static float P(float k) } #endif -void bicubic_interpolation_color(struct ImBuf *in, unsigned char *outI, float *outF, float u, float v) +void bicubic_interpolation_color(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) { int i, j, n, m, x1, y1; unsigned char *dataI; float a, b, w, wx, wy[4], outR, outG, outB, outA, *dataF; /* sample area entirely outside image? */ - if (ceil(u) < 0 || floor(u) > in->x - 1 || ceil(v) < 0 || floor(v) > in->y - 1) + if (ceil(u) < 0 || floor(u) > in->x - 1 || ceil(v) < 0 || floor(v) > in->y - 1) { return; + } /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ @@ -226,11 +227,12 @@ void bicubic_interpolation_color(struct ImBuf *in, unsigned char *outI, float *o void bicubic_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, int yout) { - unsigned char *outI = NULL; float *outF = NULL; - if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) return; + if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) { + return; + } pixel_from_buffer(out, &outI, &outF, xout, yout); /* gcc warns these could be uninitialized, but its ok */ @@ -239,7 +241,7 @@ void bicubic_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, in /* function assumes out to be zero'ed, only does RGBA */ /* BILINEAR INTERPOLATION */ -void bilinear_interpolation_color(struct ImBuf *in, unsigned char *outI, float *outF, float u, float v) +void bilinear_interpolation_color(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) { float *row1, *row2, *row3, *row4, a, b; unsigned char *row1I, *row2I, *row3I, *row4I; @@ -257,7 +259,9 @@ void bilinear_interpolation_color(struct ImBuf *in, unsigned char *outI, float * y2 = (int)ceil(v); /* sample area entirely outside image? */ - if (x2 < 0 || x1 > in->x - 1 || y2 < 0 || y1 > in->y - 1) return; + if (x2 < 0 || x1 > in->x - 1 || y2 < 0 || y1 > in->y - 1) { + return; + } if (outF) { /* sample including outside of edges of image */ @@ -315,7 +319,7 @@ void bilinear_interpolation_color(struct ImBuf *in, unsigned char *outI, float * /* Note about wrapping, the u/v still needs to be within the image bounds, * just the interpolation is wrapped. * This the same as bilinear_interpolation_color except it wraps rather than using empty and emptyI */ -void bilinear_interpolation_color_wrap(struct ImBuf *in, unsigned char *outI, float *outF, float u, float v) +void bilinear_interpolation_color_wrap(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) { float *row1, *row2, *row3, *row4, a, b; unsigned char *row1I, *row2I, *row3I, *row4I; @@ -331,7 +335,9 @@ void bilinear_interpolation_color_wrap(struct ImBuf *in, unsigned char *outI, fl y2 = (int)ceil(v); /* sample area entirely outside image? */ - if (x2 < 0 || x1 > in->x - 1 || y2 < 0 || y1 > in->y - 1) return; + if (x2 < 0 || x1 > in->x - 1 || y2 < 0 || y1 > in->y - 1) { + return; + } /* wrap interpolation pixels - main difference from bilinear_interpolation_color */ if (x1 < 0) x1 = in->x + x1; @@ -378,11 +384,12 @@ void bilinear_interpolation_color_wrap(struct ImBuf *in, unsigned char *outI, fl void bilinear_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, int yout) { - unsigned char *outI = NULL; float *outF = NULL; - if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) return; + if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) { + return; + } pixel_from_buffer(out, &outI, &outF, xout, yout); /* gcc warns these could be uninitialized, but its ok */ @@ -391,7 +398,7 @@ void bilinear_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, i /* function assumes out to be zero'ed, only does RGBA */ /* NEAREST INTERPOLATION */ -void neareast_interpolation_color(struct ImBuf *in, unsigned char *outI, float *outF, float u, float v) +void neareast_interpolation_color(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) { float *dataF; unsigned char *dataI; @@ -403,7 +410,9 @@ void neareast_interpolation_color(struct ImBuf *in, unsigned char *outI, float * y1 = (int)(v); /* sample area entirely outside image? */ - if (x1 < 0 || x1 > in->x - 1 || y1 < 0 || y1 > in->y - 1) return; + if (x1 < 0 || x1 > in->x - 1 || y1 < 0 || y1 > in->y - 1) { + return; + } /* sample including outside of edges of image */ if (x1 < 0 || y1 < 0) { @@ -435,16 +444,17 @@ void neareast_interpolation_color(struct ImBuf *in, unsigned char *outI, float * outF[2] = dataF[2]; outF[3] = dataF[3]; } - } + } } void neareast_interpolation(ImBuf *in, ImBuf *out, float x, float y, int xout, int yout) { - unsigned char *outI = NULL; float *outF = NULL; - if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) return; + if (in == NULL || (in->rect == NULL && in->rect_float == NULL)) { + return; + } pixel_from_buffer(out, &outI, &outF, xout, yout); /* gcc warns these could be uninitialized, but its ok */ diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index 97316c48621..5dda33dfd62 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -36,18 +36,19 @@ #include "IMB_indexer.h" #include "IMB_anim.h" -#include "AVI_avi.h" #include "imbuf.h" #include "MEM_guardedalloc.h" #include "DNA_userdef_types.h" #include "BKE_global.h" +#ifdef WITH_AVI +# include "AVI_avi.h" +#endif + #ifdef WITH_FFMPEG - -#include "ffmpeg_compat.h" - -#endif //WITH_FFMPEG +# include "ffmpeg_compat.h" +#endif static char magic[] = "BlenMIdx"; @@ -869,9 +870,9 @@ static void index_rebuild_ffmpeg_proc_decoded_frame( context->start_pts_set = TRUE; } - context->frameno = floor((pts - context->start_pts) - * context->pts_time_base - * context->frame_rate + 0.5f); + context->frameno = floor((pts - context->start_pts) * + context->pts_time_base * + context->frame_rate + 0.5f); /* decoding starts *always* on I-Frames, * so: P-Frames won't work, even if all the @@ -955,9 +956,9 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context, } /* process pictures still stuck in decoder engine after EOF - according to ffmpeg docs using 0-size packets. - - At least, if we haven't already stopped... */ + * according to ffmpeg docs using 0-size packets. + * + * At least, if we haven't already stopped... */ if (!*stop) { int frame_finished; @@ -989,6 +990,7 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context, * - internal AVI (fallback) rebuilder * ---------------------------------------------------------------------- */ +#ifdef WITH_AVI typedef struct FallbackIndexBuilderContext { int anim_type; @@ -1149,6 +1151,8 @@ static void index_rebuild_fallback(FallbackIndexBuilderContext *context, } } +#endif /* WITH_AVI */ + /* ---------------------------------------------------------------------- * - public API * ---------------------------------------------------------------------- */ @@ -1164,15 +1168,19 @@ IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim, IMB_Timecod context = index_ffmpeg_create_context(anim, tcs_in_use, proxy_sizes_in_use, quality); break; #endif +#ifdef WITH_AVI default: context = index_fallback_create_context(anim, tcs_in_use, proxy_sizes_in_use, quality); break; +#endif } if (context) context->anim_type = anim->curtype; return context; + + (void)tcs_in_use, (void)proxy_sizes_in_use, (void)quality; } void IMB_anim_index_rebuild(struct IndexBuildContext *context, @@ -1184,10 +1192,14 @@ void IMB_anim_index_rebuild(struct IndexBuildContext *context, index_rebuild_ffmpeg((FFmpegIndexBuilderContext *)context, stop, do_update, progress); break; #endif +#ifdef WITH_AVI default: index_rebuild_fallback((FallbackIndexBuilderContext *)context, stop, do_update, progress); break; +#endif } + + (void)stop, (void)do_update, (void)progress; } void IMB_anim_index_rebuild_finish(IndexBuildContext *context, short stop) @@ -1198,10 +1210,15 @@ void IMB_anim_index_rebuild_finish(IndexBuildContext *context, short stop) index_rebuild_ffmpeg_finish((FFmpegIndexBuilderContext *)context, stop); break; #endif +#ifdef WITH_AVI default: index_rebuild_fallback_finish((FallbackIndexBuilderContext *)context, stop); break; +#endif } + + (void)stop; + (void)proxy_sizes; /* static defined at top of the file */ } diff --git a/source/blender/imbuf/intern/iris.c b/source/blender/imbuf/intern/iris.c index 3fd25fff92f..dec5f6fb39e 100644 --- a/source/blender/imbuf/intern/iris.c +++ b/source/blender/imbuf/intern/iris.c @@ -83,21 +83,21 @@ typedef struct { #define OFFSET_R 0 /* this is byte order dependent */ #define OFFSET_G 1 #define OFFSET_B 2 -#define OFFSET_A 3 +// #define OFFSET_A 3 #define CHANOFFSET(z) (3 - (z)) /* this is byte order dependent */ -#define TYPEMASK 0xff00 +// #define TYPEMASK 0xff00 #define BPPMASK 0x00ff -#define ITYPE_VERBATIM 0x0000 +// #define ITYPE_VERBATIM 0x0000 // UNUSED #define ITYPE_RLE 0x0100 #define ISRLE(type) (((type) & 0xff00) == ITYPE_RLE) -#define ISVERBATIM(type) (((type) & 0xff00) == ITYPE_VERBATIM) +// #define ISVERBATIM(type) (((type) & 0xff00) == ITYPE_VERBATIM) #define BPP(type) ((type) & BPPMASK) #define RLE(bpp) (ITYPE_RLE | (bpp)) -#define VERBATIM(bpp) (ITYPE_VERBATIM | (bpp)) -#define IBUFSIZE(pixels) ((pixels + (pixels >> 6)) << 2) -#define RLE_NOP 0x00 +// #define VERBATIM(bpp) (ITYPE_VERBATIM | (bpp)) // UNUSED +// #define IBUFSIZE(pixels) ((pixels + (pixels >> 6)) << 2) // UNUSED +// #define RLE_NOP 0x00 /* funcs */ static void readheader(FILE *inf, IMAGE *image); @@ -408,7 +408,7 @@ struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colo } MEM_freeN(starttab); - MEM_freeN(lengthtab); + MEM_freeN(lengthtab); } else { @@ -613,7 +613,7 @@ static void expandrow2(float *optr, unsigned char *iptr, int z) optr += 4; } } - } + } } static void expandrow(unsigned char *optr, unsigned char *iptr, int z) diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c index dd559c55402..692ba3c49ea 100644 --- a/source/blender/imbuf/intern/jp2.c +++ b/source/blender/imbuf/intern/jp2.c @@ -436,7 +436,7 @@ static void cinema_parameters(opj_cparameters_t *parameters) parameters->image_offset_y0 = 0; /*Codeblock size = 32 * 32*/ - parameters->cblockw_init = 32; + parameters->cblockw_init = 32; parameters->cblockh_init = 32; parameters->csty |= 0x01; @@ -544,6 +544,10 @@ static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *ima parameters->cp_disto_alloc = 1; } +static float channel_colormanage_noop(float value) +{ + return value; +} static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) { @@ -560,9 +564,20 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) opj_image_cmptparm_t cmptparm[4]; /* maximum of 4 components */ opj_image_t *image = NULL; + float (*chanel_colormanage_cb)(float); + img_fol_t img_fol; /* only needed for cinema presets */ memset(&img_fol, 0, sizeof(img_fol_t)); + if (ibuf->float_colorspace) { + /* float buffer was managed already, no need in color space conversion */ + chanel_colormanage_cb = channel_colormanage_noop; + } + else { + /* standard linear-to-srgb conversion if float buffer wasn't managed */ + chanel_colormanage_cb = linearrgb_to_srgb; + } + if (ibuf->ftype & JP2_CINE) { if (ibuf->x == 4096 || ibuf->y == 2160) @@ -587,7 +602,7 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) prec = 12; numcomps = 3; } - else { + else { /* Get settings from the imbuf */ color_space = (ibuf->ftype & JP2_YCC) ? CLRSPC_SYCC : CLRSPC_SRGB; @@ -649,9 +664,9 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) if (numcomps == 4) { PIXEL_LOOPER_BEGIN(rect_float) { - r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[2])); + r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[2])); a[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[3]); } PIXEL_LOOPER_END; @@ -659,9 +674,9 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) else { PIXEL_LOOPER_BEGIN(rect_float) { - r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[2])); + r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[2])); } PIXEL_LOOPER_END; } @@ -671,9 +686,9 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) if (numcomps == 4) { PIXEL_LOOPER_BEGIN(rect_float) { - r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[2])); + r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[2])); a[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[3]); } PIXEL_LOOPER_END; @@ -681,9 +696,9 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) else { PIXEL_LOOPER_BEGIN(rect_float) { - r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[2])); + r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[2])); } PIXEL_LOOPER_END; } @@ -693,9 +708,9 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) if (numcomps == 4) { PIXEL_LOOPER_BEGIN(rect_float) { - r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[2])); + r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[2])); a[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[3]); } PIXEL_LOOPER_END; @@ -703,9 +718,9 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) else { PIXEL_LOOPER_BEGIN(rect_float) { - r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[2])); + r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[2])); } PIXEL_LOOPER_END; } diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c index 691db96989d..61275a8937c 100644 --- a/source/blender/imbuf/intern/jpeg.c +++ b/source/blender/imbuf/intern/jpeg.c @@ -51,9 +51,9 @@ #include "IMB_colormanagement.h" #include "IMB_colormanagement_intern.h" -#define IS_jpg(x) (x->ftype & JPG) +// #define IS_jpg(x) (x->ftype & JPG) // UNUSED #define IS_stdjpg(x) ((x->ftype & JPG_MSK) == JPG_STD) -#define IS_vidjpg(x) ((x->ftype & JPG_MSK) == JPG_VID) +// #define IS_vidjpg(x) ((x->ftype & JPG_MSK) == JPG_VID) // UNUSED #define IS_jstjpg(x) ((x->ftype & JPG_MSK) == JPG_JST) #define IS_maxjpg(x) ((x->ftype & JPG_MSK) == JPG_MAX) diff --git a/source/blender/imbuf/intern/module.c b/source/blender/imbuf/intern/module.c index 55a29333620..9141dad6f9c 100644 --- a/source/blender/imbuf/intern/module.c +++ b/source/blender/imbuf/intern/module.c @@ -28,16 +28,19 @@ #include #include "IMB_imbuf.h" #include "IMB_filetype.h" +#include "IMB_colormanagement_intern.h" void IMB_init(void) { imb_filetypes_init(); imb_tile_cache_init(); + colormanagement_init(); } void IMB_exit(void) { imb_tile_cache_exit(); imb_filetypes_exit(); + colormanagement_exit(); } diff --git a/source/blender/imbuf/intern/moviecache.c b/source/blender/imbuf/intern/moviecache.c index 78a989ad48f..d5aa635f548 100644 --- a/source/blender/imbuf/intern/moviecache.c +++ b/source/blender/imbuf/intern/moviecache.c @@ -386,7 +386,7 @@ ImBuf *IMB_moviecache_get(MovieCache *cache, void *userkey) void IMB_moviecache_free(MovieCache *cache) { - PRINT("%s: create '%s' free\n", __func__, cache->name); + PRINT("%s: cache '%s' free\n", __func__, cache->name); BLI_ghash_free(cache->hash, moviecache_keyfree, moviecache_valfree); diff --git a/source/blender/imbuf/intern/openexr/CMakeLists.txt b/source/blender/imbuf/intern/openexr/CMakeLists.txt index a5afc1abdc6..d5cb8e8a3b6 100644 --- a/source/blender/imbuf/intern/openexr/CMakeLists.txt +++ b/source/blender/imbuf/intern/openexr/CMakeLists.txt @@ -39,6 +39,9 @@ set(INC_SYS ) set(SRC + openexr_api.h + openexr_multi.h + openexr_api.cpp ) @@ -49,4 +52,4 @@ if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) endif() -blender_add_lib(bf_imbuf_openexr "${SRC}" "${INC}" "${INC_SYS}") +blender_add_lib(bf_imbuf_openexr "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 13078921d1c..60c6e184070 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -238,19 +238,19 @@ public: Iex::throwErrnoExc(); } - virtual void write(const char c[], int n) + virtual void write(const char c[], int n) { errno = 0; ofs.write(c, n); check_error(); } - virtual Int64 tellp() + virtual Int64 tellp() { return std::streamoff(ofs.tellp()); } - virtual void seekp(Int64 pos) + virtual void seekp(Int64 pos) { ofs.seekp(pos); check_error(); @@ -372,10 +372,10 @@ static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags for (int j = ibuf->x; j > 0; j--) { to->r = from[0]; - to->g = from[1]; - to->b = from[2]; + to->g = (channels >= 2) ? from[1] : from[0]; + to->b = (channels >= 3) ? from[2] : from[0]; to->a = (channels >= 4) ? from[3] : 1.0f; - to++; from += 4; + to++; from += channels; } } } @@ -383,7 +383,7 @@ static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags unsigned char *from; for (int i = ibuf->y - 1; i >= 0; i--) { - from = (unsigned char *)ibuf->rect + channels * i * width; + from = (unsigned char *)ibuf->rect + 4 * i * width; for (int j = ibuf->x; j > 0; j--) { to->r = srgb_to_linearrgb((float)from[0] / 255.0f); @@ -448,8 +448,8 @@ static int imb_save_openexr_float(struct ImBuf *ibuf, const char *name, int flag /* last scanline, stride negative */ rect[0] = ibuf->rect_float + channels * (height - 1) * width; - rect[1] = rect[0] + 1; - rect[2] = rect[0] + 2; + rect[1] = (channels >= 2) ? rect[0] + 1 : rect[0]; + rect[2] = (channels >= 3) ? rect[0] + 2 : rect[0]; rect[3] = (channels >= 4) ? rect[0] + 3 : rect[0]; /* red as alpha, is this needed since alpha isn't written? */ frameBuffer.insert("R", Slice(Imf::FLOAT, (char *)rect[0], xstride, ystride)); diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c index 6310d8e105f..dcfebb95b87 100644 --- a/source/blender/imbuf/intern/png.c +++ b/source/blender/imbuf/intern/png.c @@ -558,7 +558,8 @@ ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[I MEM_freeN(pixels); if (pixels16) MEM_freeN(pixels16); - MEM_freeN(row_pointers); + if (row_pointers) + MEM_freeN(row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return(ibuf); diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c index 5add372cd4e..72cec0e3749 100644 --- a/source/blender/imbuf/intern/radiance_hdr.c +++ b/source/blender/imbuf/intern/radiance_hdr.c @@ -154,7 +154,7 @@ static void FLOAT2RGBE(fCOLOR fcol, RGBE rgbe) if (d <= 1e-32f) rgbe[RED] = rgbe[GRN] = rgbe[BLU] = rgbe[EXP] = 0; else { - d = frexp(d, &e) * 256.f / d; + d = (float)frexp(d, &e) * 256.0f / d; rgbe[RED] = (unsigned char)(fcol[RED] * d); rgbe[GRN] = (unsigned char)(fcol[GRN] * d); rgbe[BLU] = (unsigned char)(fcol[BLU] * d); @@ -168,9 +168,9 @@ int imb_is_a_hdr(unsigned char *buf) { /* For recognition, Blender only loads first 32 bytes, so use #?RADIANCE id instead */ /* update: actually, the 'RADIANCE' part is just an optional program name, the magic word is really only the '#?' part */ - //if (strstr((char*)buf, "#?RADIANCE")) return 1; + //if (strstr((char *)buf, "#?RADIANCE")) return 1; if (strstr((char *)buf, "#?")) return 1; - // if (strstr((char*)buf, "32-bit_rle_rgbe")) return 1; + // if (strstr((char *)buf, "32-bit_rle_rgbe")) return 1; return 0; } diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index a1fa05d1098..5669a4cc45d 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -100,7 +100,8 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char co } } - fprintf(stderr, "%s: unknown fileformat (%s)\n", __func__, descr); + if ((flags & IB_test) == 0) + fprintf(stderr, "%s: unknown fileformat (%s)\n", __func__, descr); return NULL; } @@ -170,11 +171,12 @@ ImBuf *IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_S return ibuf; } -ImBuf *IMB_testiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE]) +ImBuf *IMB_testiffname(const char *filepath, int flags) { ImBuf *ibuf; int file; char filepath_tx[IB_FILENAME_SIZE]; + char colorspace[IM_MAX_SPACE]; imb_cache_filename(filepath_tx, filepath, flags); diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c index a11f16d5669..8e072361583 100644 --- a/source/blender/imbuf/intern/rectop.c +++ b/source/blender/imbuf/intern/rectop.c @@ -447,7 +447,7 @@ void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx, drectf += destskip * 4; srectf += srcskip * 4; - } + } } } } @@ -482,13 +482,13 @@ void IMB_rectfill(struct ImBuf *drect, const float col[4]) *rrectf++ = col[2]; *rrectf++ = col[3]; } - } + } } void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, - const float col[4], struct ColorManagedDisplay *display, - int x1, int y1, int x2, int y2) + const float col[4], struct ColorManagedDisplay *display, + int x1, int y1, int x2, int y2) { int i, j; float a; /* alpha */ diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c index 389c3c42b6d..527f334d6a4 100644 --- a/source/blender/imbuf/intern/scaling.c +++ b/source/blender/imbuf/intern/scaling.c @@ -1051,7 +1051,7 @@ static ImBuf *scaledowny(struct ImBuf *ibuf, int newy) sample -= 1.0f; } - } + } if (do_rect) { // printf("%ld %ld\n", (uchar *)rect - ((uchar *)ibuf->rect), rect_size); diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c index 253680e4bea..eaad77f1ff9 100644 --- a/source/blender/imbuf/intern/targa.c +++ b/source/blender/imbuf/intern/targa.c @@ -55,9 +55,9 @@ /***/ typedef struct TARGA { - unsigned char numid; + unsigned char numid; unsigned char maptyp; - unsigned char imgtyp; + unsigned char imgtyp; short maporig; short mapsize; unsigned char mapbits; diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index ff7218d649c..a3ce332b609 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -175,7 +175,7 @@ static void to_hex_char(char *hexbytes, const unsigned char *bytes, int len) static int uri_from_filename(const char *path, char *uri) { - char orig_uri[URI_MAX]; + char orig_uri[URI_MAX]; const char *dirstart = path; #ifdef WIN32 @@ -265,7 +265,7 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im char thumb[40]; short tsize = 128; short ex, ey; - float scaledx, scaledy; + float scaledx, scaledy; struct stat info; switch (size) { @@ -334,7 +334,7 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im } else { IMB_freeImBuf(img); - img = IMB_anim_previewframe(anim); + img = IMB_anim_previewframe(anim); } IMB_free_anim(anim); } @@ -401,7 +401,7 @@ ImBuf *IMB_thumb_read(const char *path, ThumbSize size) if (!uri_from_filename(path, uri)) { return NULL; } - if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) { + if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) { img = IMB_loadiffname(thumb, IB_rect | IB_metadata, NULL); } @@ -438,7 +438,7 @@ ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source) if (stat(path, &st)) { return NULL; - } + } if (!uri_from_filename(path, uri)) { return NULL; } diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c index cfc49d8cef5..73ced4095f9 100644 --- a/source/blender/imbuf/intern/thumbs_blend.c +++ b/source/blender/imbuf/intern/thumbs_blend.c @@ -166,7 +166,7 @@ void IMB_overlayblend_thumb(unsigned int *thumb, int width, int height, float as margin_t = height - margin_b; } - { + { int x, y; int stride_x = (margin_r - margin_l) - 2; diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c index 932a4941a0a..83830f260e1 100644 --- a/source/blender/imbuf/intern/tiff.c +++ b/source/blender/imbuf/intern/tiff.c @@ -114,7 +114,7 @@ static int imb_tiff_DummyMapProc(thandle_t fd, tdata_t *pbase, toff_t *psize) * Reads data from an in-memory TIFF file. * * \param handle: Handle of the TIFF file (pointer to ImbTIFFMemFile). - * \param data: Buffer to contain data (treat as void*). + * \param data: Buffer to contain data (treat as (void *)). * \param n: Number of bytes to read. * * \return: Number of bytes actually read. @@ -790,7 +790,14 @@ int imb_savetiff(ImBuf *ibuf, const char *name, int flags) /* convert from float source */ float rgb[4]; - linearrgb_to_srgb_v3_v3(rgb, &fromf[from_i]); + if (ibuf->float_colorspace) { + /* float buffer was managed already, no need in color space conversion */ + copy_v3_v3(rgb, &fromf[from_i]); + } + else { + /* standard linear-to-srgb conversion if float buffer wasn't managed */ + linearrgb_to_srgb_v3_v3(rgb, &fromf[from_i]); + } rgb[3] = fromf[from_i + 3]; diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index 833671e3f2f..fe138a71a4a 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -211,7 +211,12 @@ int IMB_ispic(const char *filename) static int isavi(const char *name) { +#ifdef WITH_AVI return AVI_is_avi(name); +#else + (void)name; + return FALSE; +#endif } #ifdef WITH_QUICKTIME @@ -223,6 +228,10 @@ static int isqtime(const char *name) #ifdef WITH_FFMPEG +/* BLI_vsnprintf in ffmpeg_log_callback() causes invalid warning */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-format-attribute" + static char ffmpeg_last_error[1024]; static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_list arg) @@ -240,6 +249,8 @@ static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_lis } } +#pragma GCC diagnostic pop + void IMB_ffmpeg_init(void) { av_register_all(); @@ -405,7 +416,7 @@ int IMB_isanim(const char *filename) type = imb_get_anim_type(filename); } else { - return(FALSE); + return(FALSE); } } else { /* no quicktime */ diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index ffe25a7b1ec..d8d1ad78451 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -563,6 +563,7 @@ typedef enum eDopeSheet_FilterFlag { /* general filtering 3 */ ADS_FILTER_INCL_HIDDEN = (1 << 26), /* include 'hidden' channels too (i.e. those from hidden Objects/Bones) */ ADS_FILTER_BY_FCU_NAME = (1 << 27), /* for F-Curves, filter by the displayed name (i.e. to isolate all Location curves only) */ + ADS_FILTER_ONLY_ERRORS = (1 << 28), /* show only F-Curves which are disabled/have errors - for debugging drivers */ /* combination filters (some only used at runtime) */ ADS_FILTER_NOOBDATA = (ADS_FILTER_NOCAM | ADS_FILTER_NOMAT | ADS_FILTER_NOLAM | ADS_FILTER_NOCUR | ADS_FILTER_NOPART | ADS_FILTER_NOARM | ADS_FILTER_NOSPK) @@ -604,11 +605,11 @@ typedef enum eSAction_Flag { /* draw time in seconds instead of time in frames */ SACTION_DRAWTIME = (1 << 2), /* don't filter action channels according to visibility */ - //SACTION_NOHIDE = (1<<3), // XXX depreceated... old animation system + //SACTION_NOHIDE = (1<<3), // XXX deprecated... old animation system /* don't kill overlapping keyframes after transform */ SACTION_NOTRANSKEYCULL = (1 << 4), /* don't include keyframes that are out of view */ - //SACTION_HORIZOPTIMISEON = (1<<5), // XXX depreceated... old irrelevant trick + //SACTION_HORIZOPTIMISEON = (1<<5), // XXX deprecated... old irrelevant trick /* show pose-markers (local to action) in Action Editor mode */ SACTION_POSEMARKERS_SHOW = (1 << 6), /* don't draw action channels using group colors (where applicable) */ @@ -653,7 +654,7 @@ typedef enum eAnimEdit_AutoSnap { /* ************************************************ */ /* Legacy Data */ -/* WARNING: Action Channels are now depreceated... they were part of the old animation system! +/* WARNING: Action Channels are now deprecated... they were part of the old animation system! * (ONLY USED FOR DO_VERSIONS...) * * Action Channels belong to Actions. They are linked with an IPO block, and can also own diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index 4a5ad69cb91..b445d59db2c 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -46,21 +46,21 @@ typedef struct bAddObjectActuator { struct Object *ob; } bAddObjectActuator; -typedef struct bActionActuator { - struct bAction *act; /* Pointer to action */ - short type, flag; /* Playback type */ // not in use - float sta, end; /* Start & End frames */ - char name[64]; /* For property-driven playback, MAX_NAME */ - char frameProp[64]; /* Set this property to the actions current frame, MAX_NAME */ - short blendin; /* Number of frames of blending */ - short priority; /* Execution priority */ - short layer; /* Animation layer */ - short end_reset; /* Ending the actuator (negative pulse) wont reset the the action to its starting frame */ - short strideaxis; /* Displacement axis */ - short pad; - float stridelength; /* Displacement incurred by cycle */ // not in use - float layer_weight; /* How much of the previous layer to use for blending. (<0 = disable, 0 = add mode) */ -} bActionActuator; +typedef struct bActionActuator { + struct bAction *act; /* Pointer to action */ + short type, flag; /* Playback type */ // not in use + float sta, end; /* Start & End frames */ + char name[64]; /* For property-driven playback, MAX_NAME */ + char frameProp[64]; /* Set this property to the actions current frame, MAX_NAME */ + short blendin; /* Number of frames of blending */ + short priority; /* Execution priority */ + short layer; /* Animation layer */ + short end_reset; /* Ending the actuator (negative pulse) wont reset the the action to its starting frame */ + short strideaxis; /* Displacement axis */ + short pad; + float stridelength; /* Displacement incurred by cycle */ // not in use + float layer_weight; /* How much of the previous layer to use for blending. (<0 = disable, 0 = add mode) */ +} bActionActuator; typedef struct Sound3D { float min_gain; @@ -261,7 +261,7 @@ typedef struct bActuator { /** * For ipo's and props: to find out which object the actuator * belongs to */ - struct Object *ob; + struct Object *ob; } bActuator; diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index 7cf0d588710..1ac6e6db94b 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -246,13 +246,13 @@ typedef enum eFMod_Noise_Modifications { /* stepped modifier data */ typedef struct FMod_Stepped { - float step_size; /* Number of frames each interpolated value should be held */ - float offset; /* Reference frame number that stepping starts from */ - - float start_frame; /* start frame of the frame range that modifier works in */ - float end_frame; /* end frame of the frame range that modifier works in */ - - int flag; /* various settings */ + float step_size; /* Number of frames each interpolated value should be held */ + float offset; /* Reference frame number that stepping starts from */ + + float start_frame; /* start frame of the frame range that modifier works in */ + float end_frame; /* end frame of the frame range that modifier works in */ + + int flag; /* various settings */ } FMod_Stepped; /* stepped modifier range flags */ @@ -325,14 +325,14 @@ typedef enum eDriverTarget_TransformChannels { */ typedef struct DriverVar { struct DriverVar *next, *prev; - - char name[64]; /* name of the variable to use in py-expression (must be valid python identifier) */ - - DriverTarget targets[8]; /* MAX_DRIVER_TARGETS, target slots */ - short num_targets; /* number of targets actually used by this variable */ - - short type; /* type of driver target (eDriverTarget_Types) */ - float curval; /* result of previous evaluation */ + + char name[64]; /* name of the variable to use in py-expression (must be valid python identifier) */ + + DriverTarget targets[8]; /* MAX_DRIVER_TARGETS, target slots */ + short num_targets; /* number of targets actually used by this variable */ + + short type; /* type of driver target (eDriverTarget_Types) */ + float curval; /* result of previous evaluation */ } DriverVar; /* Driver Variable Types */ @@ -556,36 +556,36 @@ typedef struct AnimMapper { */ typedef struct NlaStrip { struct NlaStrip *next, *prev; - - ListBase strips; /* 'Child' strips (used for 'meta' strips) */ - bAction *act; /* Action that is referenced by this strip (strip is 'user' of the action) */ - AnimMapper *remap; /* Remapping info this strip (for tweaking correspondence of action with context) */ - - ListBase fcurves; /* F-Curves for controlling this strip's influence and timing */ // TODO: move out? - ListBase modifiers; /* F-Curve modifiers to be applied to the entire strip's referenced F-Curves */ - - char name[64]; /* User-Visible Identifier for Strip */ - - float influence; /* Influence of strip */ - float strip_time; /* Current 'time' within action being used (automatically evaluated, but can be overridden) */ - - float start, end; /* extents of the strip */ - float actstart, actend; /* range of the action to use */ - - float repeat; /* The number of times to repeat the action range (only when no F-Curves) */ - float scale; /* The amount the action range is scaled by (only when no F-Curves) */ - - float blendin, blendout; /* strip blending length (only used when there are no F-Curves) */ - short blendmode; /* strip blending mode (layer-based mixing) */ - - short extendmode; /* strip extrapolation mode (time-based mixing) */ + + ListBase strips; /* 'Child' strips (used for 'meta' strips) */ + bAction *act; /* Action that is referenced by this strip (strip is 'user' of the action) */ + AnimMapper *remap; /* Remapping info this strip (for tweaking correspondence of action with context) */ + + ListBase fcurves; /* F-Curves for controlling this strip's influence and timing */ // TODO: move out? + ListBase modifiers; /* F-Curve modifiers to be applied to the entire strip's referenced F-Curves */ + + char name[64]; /* User-Visible Identifier for Strip */ + + float influence; /* Influence of strip */ + float strip_time; /* Current 'time' within action being used (automatically evaluated, but can be overridden) */ + + float start, end; /* extents of the strip */ + float actstart, actend; /* range of the action to use */ + + float repeat; /* The number of times to repeat the action range (only when no F-Curves) */ + float scale; /* The amount the action range is scaled by (only when no F-Curves) */ + + float blendin, blendout; /* strip blending length (only used when there are no F-Curves) */ + short blendmode; /* strip blending mode (layer-based mixing) */ + + short extendmode; /* strip extrapolation mode (time-based mixing) */ short pad1; - - short type; /* type of NLA strip */ - - void *speaker_handle; /* handle for speaker objects */ - - int flag; /* settings */ + + short type; /* type of NLA strip */ + + void *speaker_handle; /* handle for speaker objects */ + + int flag; /* settings */ int pad2; } NlaStrip; @@ -600,48 +600,48 @@ typedef enum eNlaStrip_Blend_Mode { /* NLA Strip Extrpolation Mode */ typedef enum eNlaStrip_Extrapolate_Mode { /* extend before first frame if no previous strips in track, and always hold+extend last frame */ - NLASTRIP_EXTEND_HOLD = 0, + NLASTRIP_EXTEND_HOLD = 0, /* only hold+extend last frame */ - NLASTRIP_EXTEND_HOLD_FORWARD, + NLASTRIP_EXTEND_HOLD_FORWARD = 1, /* don't contribute at all */ - NLASTRIP_EXTEND_NOTHING + NLASTRIP_EXTEND_NOTHING = 2 } eNlaStrip_Extrapolate_Mode; /* NLA Strip Settings */ typedef enum eNlaStrip_Flag { /* UI selection flags */ /* NLA strip is the active one in the track (also indicates if strip is being tweaked) */ - NLASTRIP_FLAG_ACTIVE = (1<<0), + NLASTRIP_FLAG_ACTIVE = (1<<0), /* NLA strip is selected for editing */ - NLASTRIP_FLAG_SELECT = (1<<1), -// NLASTRIP_FLAG_SELECT_L = (1<<2), // left handle selected -// NLASTRIP_FLAG_SELECT_R = (1<<3), // right handle selected + NLASTRIP_FLAG_SELECT = (1<<1), +// NLASTRIP_FLAG_SELECT_L = (1<<2), // left handle selected +// NLASTRIP_FLAG_SELECT_R = (1<<3), // right handle selected /* NLA strip uses the same action that the action being tweaked uses (not set for the twaking one though) */ - NLASTRIP_FLAG_TWEAKUSER = (1<<4), - + NLASTRIP_FLAG_TWEAKUSER = (1<<4), + /* controls driven by local F-Curves */ /* strip influence is controlled by local F-Curve */ - NLASTRIP_FLAG_USR_INFLUENCE = (1<<5), - NLASTRIP_FLAG_USR_TIME = (1<<6), + NLASTRIP_FLAG_USR_INFLUENCE = (1<<5), + NLASTRIP_FLAG_USR_TIME = (1<<6), NLASTRIP_FLAG_USR_TIME_CYCLIC = (1<<7), - + /* NLA strip length is synced to the length of the referenced action */ - NLASTRIP_FLAG_SYNC_LENGTH = (1<<9), - + NLASTRIP_FLAG_SYNC_LENGTH = (1<<9), + /* playback flags (may be overridden by F-Curves) */ /* NLA strip blendin/out values are set automatically based on overlaps */ - NLASTRIP_FLAG_AUTO_BLENDS = (1<<10), + NLASTRIP_FLAG_AUTO_BLENDS = (1<<10), /* NLA strip is played back in reverse order */ - NLASTRIP_FLAG_REVERSE = (1<<11), + NLASTRIP_FLAG_REVERSE = (1<<11), /* NLA strip is muted (i.e. doesn't contribute in any way) */ - NLASTRIP_FLAG_MUTED = (1<<12), + NLASTRIP_FLAG_MUTED = (1<<12), /* NLA Strip is played back in 'ping-pong' style */ - NLASTRIP_FLAG_MIRROR = (1<<13), - + NLASTRIP_FLAG_MIRROR = (1<<13), + /* temporary editing flags */ /* NLA-Strip is really just a temporary meta used to facilitate easier transform code */ - NLASTRIP_FLAG_TEMP_META = (1<<30), - NLASTRIP_FLAG_EDIT_TOUCHED = (1<<31) + NLASTRIP_FLAG_TEMP_META = (1<<30), + NLASTRIP_FLAG_EDIT_TOUCHED = (1<<31) } eNlaStrip_Flag; /* NLA Strip Type */ @@ -651,7 +651,7 @@ typedef enum eNlaStrip_Type { /* 'transition' - blends between the adjacent strips */ NLASTRIP_TYPE_TRANSITION, /* 'meta' - a strip which acts as a container for a few others */ - NLASTRIP_TYPE_META, + NLASTRIP_TYPE_META, /* 'emit sound' - a strip which is used for timing when speaker emits sounds */ NLASTRIP_TYPE_SOUND @@ -827,71 +827,71 @@ typedef struct AnimOverride { * This datablock should be placed immediately after the ID block where it is used, so that * the code which retrieves this data can do so in an easier manner. See blenkernel/intern/anim_sys.c for details. */ -typedef struct AnimData { +typedef struct AnimData { /* active action - acts as the 'tweaking track' for the NLA */ - bAction *action; - /* temp-storage for the 'real' active action (i.e. the one used before the tweaking-action - * took over to be edited in the Animation Editors) + bAction *action; + /* temp-storage for the 'real' active action (i.e. the one used before the tweaking-action + * took over to be edited in the Animation Editors) */ - bAction *tmpact; - /* remapping-info for active action - should only be used if needed - * (for 'foreign' actions that aren't working correctly) + bAction *tmpact; + /* remapping-info for active action - should only be used if needed + * (for 'foreign' actions that aren't working correctly) */ - AnimMapper *remap; - + AnimMapper *remap; + /* nla-tracks */ - ListBase nla_tracks; + ListBase nla_tracks; /* active NLA-strip (only set/used during tweaking, so no need to worry about dangling pointers) */ - NlaStrip *actstrip; - - /* 'drivers' for this ID-block's settings - FCurves, but are completely - * separate from those for animation data + NlaStrip *actstrip; + + /* 'drivers' for this ID-block's settings - FCurves, but are completely + * separate from those for animation data */ - ListBase drivers; /* standard user-created Drivers/Expressions (used as part of a rig) */ - ListBase overrides; /* temp storage (AnimOverride) of values for settings that are animated (but the value hasn't been keyframed) */ - + ListBase drivers; /* standard user-created Drivers/Expressions (used as part of a rig) */ + ListBase overrides; /* temp storage (AnimOverride) of values for settings that are animated (but the value hasn't been keyframed) */ + /* settings for animation evaluation */ - int flag; /* user-defined settings */ - int recalc; /* depsgraph recalculation flags */ - + int flag; /* user-defined settings */ + int recalc; /* depsgraph recalculation flags */ + /* settings for active action evaluation (based on NLA strip settings) */ - short act_blendmode; /* accumulation mode for active action */ - short act_extendmode; /* extrapolation mode for active action */ - float act_influence; /* influence for active action */ + short act_blendmode; /* accumulation mode for active action */ + short act_extendmode; /* extrapolation mode for active action */ + float act_influence; /* influence for active action */ } AnimData; /* Animation Data settings (mostly for NLA) */ typedef enum eAnimData_Flag { /* only evaluate a single track in the NLA */ - ADT_NLA_SOLO_TRACK = (1<<0), + ADT_NLA_SOLO_TRACK = (1<<0), /* don't use NLA */ - ADT_NLA_EVAL_OFF = (1<<1), + ADT_NLA_EVAL_OFF = (1<<1), /* NLA is being 'tweaked' (i.e. in EditMode) */ - ADT_NLA_EDIT_ON = (1<<2), + ADT_NLA_EDIT_ON = (1<<2), /* active Action for 'tweaking' does not have mapping applied for editing */ - ADT_NLA_EDIT_NOMAP = (1<<3), + ADT_NLA_EDIT_NOMAP = (1<<3), /* NLA-Strip F-Curves are expanded in UI */ - ADT_NLA_SKEYS_COLLAPSED = (1<<4), - + ADT_NLA_SKEYS_COLLAPSED = (1<<4), + /* drivers expanded in UI */ - ADT_DRIVERS_COLLAPSED = (1<<10), + ADT_DRIVERS_COLLAPSED = (1<<10), /* don't execute drivers */ - ADT_DRIVERS_DISABLED = (1<<11), - + ADT_DRIVERS_DISABLED = (1<<11), + /* AnimData block is selected in UI */ - ADT_UI_SELECTED = (1<<14), + ADT_UI_SELECTED = (1<<14), /* AnimData block is active in UI */ - ADT_UI_ACTIVE = (1<<15), - + ADT_UI_ACTIVE = (1<<15), + /* F-Curves from this AnimData block are not visible in the Graph Editor */ - ADT_CURVES_NOT_VISIBLE = (1<<16) + ADT_CURVES_NOT_VISIBLE = (1<<16) } eAnimData_Flag; /* Animation Data recalculation settings (to be set by depsgraph) */ typedef enum eAnimData_Recalc { - ADT_RECALC_DRIVERS = (1<<0), - ADT_RECALC_ANIM = (1<<1), - ADT_RECALC_ALL = (ADT_RECALC_DRIVERS | ADT_RECALC_ANIM) + ADT_RECALC_DRIVERS = (1 << 0), + ADT_RECALC_ANIM = (1 << 1), + ADT_RECALC_ALL = (ADT_RECALC_DRIVERS | ADT_RECALC_ANIM) } eAnimData_Recalc; /* Base Struct for Anim ------------------------------------- */ diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index 0afe3773c94..fd68a6d9a27 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -45,91 +45,91 @@ struct AnimData; */ typedef struct Bone { - struct Bone *next, *prev; /* Next/prev elements within this list */ - IDProperty *prop; /* User-Defined Properties on this Bone */ - struct Bone *parent; /* Parent (ik parent if appropriate flag is set */ - ListBase childbase; /* Children */ - char name[64]; /* Name of the bone - must be unique within the armature, MAXBONENAME */ + struct Bone *next, *prev; /* Next/prev elements within this list */ + IDProperty *prop; /* User-Defined Properties on this Bone */ + struct Bone *parent; /* Parent (ik parent if appropriate flag is set */ + ListBase childbase; /* Children */ + char name[64]; /* Name of the bone - must be unique within the armature, MAXBONENAME */ - float roll; /* roll is input for editmode, length calculated */ - float head[3]; - float tail[3]; /* head/tail and roll in Bone Space */ - float bone_mat[3][3]; /* rotation derived from head/tail/roll */ - - int flag; - - float arm_head[3]; - float arm_tail[3]; /* head/tail in Armature Space (rest pos) */ - float arm_mat[4][4]; /* matrix: (bonemat(b)+head(b))*arm_mat(b-1), rest pos*/ - float arm_roll; /* roll in Armature Space (rest pos) */ - - float dist, weight; /* dist, weight: for non-deformgroup deforms */ - float xwidth, length, zwidth; /* width: for block bones. keep in this order, transform! */ - float ease1, ease2; /* length of bezier handles */ - float rad_head, rad_tail; /* radius for head/tail sphere, defining deform as well, parent->rad_tip overrides rad_head*/ - - float size[3]; /* patch for upward compat, UNUSED! */ - int layer; /* layers that bone appears on */ - short segments; /* for B-bones */ - short pad[1]; + float roll; /* roll is input for editmode, length calculated */ + float head[3]; + float tail[3]; /* head/tail and roll in Bone Space */ + float bone_mat[3][3]; /* rotation derived from head/tail/roll */ + + int flag; + + float arm_head[3]; + float arm_tail[3]; /* head/tail in Armature Space (rest pos) */ + float arm_mat[4][4]; /* matrix: (bonemat(b)+head(b))*arm_mat(b-1), rest pos*/ + float arm_roll; /* roll in Armature Space (rest pos) */ + + float dist, weight; /* dist, weight: for non-deformgroup deforms */ + float xwidth, length, zwidth; /* width: for block bones. keep in this order, transform! */ + float ease1, ease2; /* length of bezier handles */ + float rad_head, rad_tail; /* radius for head/tail sphere, defining deform as well, parent->rad_tip overrides rad_head */ + + float size[3]; /* patch for upward compat, UNUSED! */ + int layer; /* layers that bone appears on */ + short segments; /* for B-bones */ + short pad[1]; } Bone; typedef struct bArmature { - ID id; + ID id; struct AnimData *adt; - - ListBase bonebase; - ListBase chainbase; - ListBase *edbo; /* editbone listbase, we use pointer so we can check state */ - + + ListBase bonebase; + ListBase chainbase; + ListBase *edbo; /* editbone listbase, we use pointer so we can check state */ + /* active bones should work like active object where possible * - active and selection are unrelated - * - active & hidden is not allowed + * - active & hidden is not allowed * - from the user perspective active == last selected * - active should be ignored when not visible (hidden layer) */ - Bone *act_bone; /* active bone (when not in editmode) */ - void *act_edbone; /* active editbone (in editmode) */ + Bone *act_bone; /* active bone (when not in editmode) */ + void *act_edbone; /* active editbone (in editmode) */ - void *sketch; /* sketch struct for etch-a-ton */ - - int flag; - int drawtype; - int gevertdeformer; /* how vertex deformation is handled in the ge */ - int pad; - short deformflag; - short pathflag; - - unsigned int layer_used; /* for UI, to show which layers are there */ - unsigned int layer, layer_protected; /* for buttons to work, both variables in this order together */ - -// XXX depreceated... old animaton system (armature only viz) --- - short ghostep, ghostsize; /* number of frames to ghosts to show, and step between them */ - short ghosttype, pathsize; /* ghost drawing options and number of frames between points of path */ - int ghostsf, ghostef; /* start and end frames of ghost-drawing range */ - int pathsf, pathef; /* start and end frames of path-calculation range for all bones */ - int pathbc, pathac; /* number of frames before/after current frame of path-calculation for all bones */ -// XXX end of depreceated code ---------------------------------- + void *sketch; /* sketch struct for etch-a-ton */ + + int flag; + int drawtype; + int gevertdeformer; /* how vertex deformation is handled in the ge */ + int pad; + short deformflag; + short pathflag; + + unsigned int layer_used; /* for UI, to show which layers are there */ + unsigned int layer, layer_protected; /* for buttons to work, both variables in this order together */ + +// XXX deprecated... old animaton system (armature only viz) --- + short ghostep, ghostsize; /* number of frames to ghosts to show, and step between them */ + short ghosttype, pathsize; /* ghost drawing options and number of frames between points of path */ + int ghostsf, ghostef; /* start and end frames of ghost-drawing range */ + int pathsf, pathef; /* start and end frames of path-calculation range for all bones */ + int pathbc, pathac; /* number of frames before/after current frame of path-calculation for all bones */ +// XXX end of deprecated code ---------------------------------- } bArmature; /* armature->flag */ /* don't use bit 7, was saved in files to disable stuff */ typedef enum eArmature_Flag { - ARM_RESTPOS = (1<<0), - ARM_DRAWXRAY = (1<<1), /* XRAY is here only for backwards converting */ - ARM_DRAWAXES = (1<<2), - ARM_DRAWNAMES = (1<<3), - ARM_POSEMODE = (1<<4), - ARM_EDITMODE = (1<<5), - ARM_DELAYDEFORM = (1<<6), - ARM_DONT_USE = (1<<7), - ARM_MIRROR_EDIT = (1<<8), - ARM_AUTO_IK = (1<<9), - ARM_NO_CUSTOM = (1<<10), /* made option negative, for backwards compat */ - ARM_COL_CUSTOM = (1<<11), /* draw custom colors */ - ARM_GHOST_ONLYSEL = (1<<12), /* when ghosting, only show selected bones (this should belong to ghostflag instead) */ /* XXX depreceated */ - ARM_DS_EXPAND = (1<<13), /* dopesheet channel is expanded */ - ARM_HAS_VIZ_DEPS = (1<<14), /* other objects are used for visualizing various states (hack for efficient updates) */ + ARM_RESTPOS = (1<<0), + ARM_DRAWXRAY = (1<<1), /* XRAY is here only for backwards converting */ + ARM_DRAWAXES = (1<<2), + ARM_DRAWNAMES = (1<<3), + ARM_POSEMODE = (1<<4), + ARM_EDITMODE = (1<<5), + ARM_DELAYDEFORM = (1<<6), + ARM_DONT_USE = (1<<7), + ARM_MIRROR_EDIT = (1<<8), + ARM_AUTO_IK = (1<<9), + ARM_NO_CUSTOM = (1<<10), /* made option negative, for backwards compat */ + ARM_COL_CUSTOM = (1<<11), /* draw custom colors */ + ARM_GHOST_ONLYSEL = (1<<12), /* when ghosting, only show selected bones (this should belong to ghostflag instead) */ /* XXX deprecated */ + ARM_DS_EXPAND = (1<<13), /* dopesheet channel is expanded */ + ARM_HAS_VIZ_DEPS = (1<<14), /* other objects are used for visualizing various states (hack for efficient updates) */ } eArmature_Flag; /* armature->drawtype */ @@ -157,7 +157,7 @@ typedef enum eArmature_DeformFlag { } eArmature_DeformFlag; /* armature->pathflag */ -// XXX depreceated... old animation system (armature only viz) +// XXX deprecated... old animation system (armature only viz) typedef enum eArmature_PathFlag { ARM_PATH_FNUMS = (1<<0), ARM_PATH_KFRAS = (1<<1), @@ -167,7 +167,7 @@ typedef enum eArmature_PathFlag { } eArmature_PathFlag; /* armature->ghosttype */ -// XXX depreceated... old animation system (armature only viz) +// XXX deprecated... old animation system (armature only viz) typedef enum eArmature_GhostType { ARM_GHOST_CUR = 0, ARM_GHOST_RANGE = 1, @@ -176,29 +176,29 @@ typedef enum eArmature_GhostType { /* bone->flag */ typedef enum eBone_Flag { - BONE_SELECTED = (1<<0), - BONE_ROOTSEL = (1<<1), - BONE_TIPSEL = (1<<2), - BONE_TRANSFORM = (1<<3), /* Used instead of BONE_SELECTED during transform */ - BONE_CONNECTED = (1<<4), /* when bone has a parent, connect head of bone to parent's tail*/ - /* 32 used to be quatrot, was always set in files, do not reuse unless you clear it always */ - BONE_HIDDEN_P = (1<<6), /* hidden Bones when drawing PoseChannels */ - BONE_DONE = (1<<7), /* For detecting cyclic dependencies */ - BONE_DRAW_ACTIVE = (1<<8), /* active is on mouse clicks only - deprecated, ONLY USE FOR DRAWING */ - BONE_HINGE = (1<<9), /* No parent rotation or scale */ - BONE_HIDDEN_A = (1<<10), /* hidden Bones when drawing Armature Editmode */ - BONE_MULT_VG_ENV = (1<<11), /* multiplies vgroup with envelope */ - BONE_NO_DEFORM = (1<<12), /* bone doesn't deform geometry */ - BONE_UNKEYED = (1<<13), /* set to prevent destruction of its unkeyframed pose (after transform) */ - BONE_HINGE_CHILD_TRANSFORM = (1<<14), /* set to prevent hinge child bones from influencing the transform center */ - BONE_NO_SCALE = (1<<15), /* No parent scale */ - BONE_HIDDEN_PG = (1<<16), /* hidden bone when drawing PoseChannels (for ghost drawing) */ - BONE_DRAWWIRE = (1<<17), /* bone should be drawn as OB_WIRE, regardless of draw-types of view+armature */ - BONE_NO_CYCLICOFFSET = (1<<18), /* when no parent, bone will not get cyclic offset */ - BONE_EDITMODE_LOCKED = (1<<19), /* bone transforms are locked in EditMode */ - BONE_TRANSFORM_CHILD = (1<<20), /* Indicates that a parent is also being transformed */ - BONE_UNSELECTABLE = (1<<21), /* bone cannot be selected */ - BONE_NO_LOCAL_LOCATION = (1<<22) /* bone location is in armature space */ + BONE_SELECTED = (1 << 0), + BONE_ROOTSEL = (1 << 1), + BONE_TIPSEL = (1 << 2), + BONE_TRANSFORM = (1 << 3), /* Used instead of BONE_SELECTED during transform */ + BONE_CONNECTED = (1 << 4), /* when bone has a parent, connect head of bone to parent's tail*/ + /* 32 used to be quatrot, was always set in files, do not reuse unless you clear it always */ + BONE_HIDDEN_P = (1 << 6), /* hidden Bones when drawing PoseChannels */ + BONE_DONE = (1 << 7), /* For detecting cyclic dependencies */ + BONE_DRAW_ACTIVE = (1 << 8), /* active is on mouse clicks only - deprecated, ONLY USE FOR DRAWING */ + BONE_HINGE = (1 << 9), /* No parent rotation or scale */ + BONE_HIDDEN_A = (1 << 10), /* hidden Bones when drawing Armature Editmode */ + BONE_MULT_VG_ENV = (1 << 11), /* multiplies vgroup with envelope */ + BONE_NO_DEFORM = (1 << 12), /* bone doesn't deform geometry */ + BONE_UNKEYED = (1 << 13), /* set to prevent destruction of its unkeyframed pose (after transform) */ + BONE_HINGE_CHILD_TRANSFORM = (1 << 14), /* set to prevent hinge child bones from influencing the transform center */ + BONE_NO_SCALE = (1 << 15), /* No parent scale */ + BONE_HIDDEN_PG = (1 << 16), /* hidden bone when drawing PoseChannels (for ghost drawing) */ + BONE_DRAWWIRE = (1 << 17), /* bone should be drawn as OB_WIRE, regardless of draw-types of view+armature */ + BONE_NO_CYCLICOFFSET = (1 << 18), /* when no parent, bone will not get cyclic offset */ + BONE_EDITMODE_LOCKED = (1 << 19), /* bone transforms are locked in EditMode */ + BONE_TRANSFORM_CHILD = (1 << 20), /* Indicates that a parent is also being transformed */ + BONE_UNSELECTABLE = (1 << 21), /* bone cannot be selected */ + BONE_NO_LOCAL_LOCATION = (1 << 22) /* bone location is in armature space */ } eBone_Flag; #define MAXBONENAME 64 diff --git a/source/blender/makesdna/DNA_boid_types.h b/source/blender/makesdna/DNA_boid_types.h index ce5fc4b0c3c..f1930ffd643 100644 --- a/source/blender/makesdna/DNA_boid_types.h +++ b/source/blender/makesdna/DNA_boid_types.h @@ -36,18 +36,18 @@ typedef enum BoidRuleType { eBoidRuleType_None = 0, - eBoidRuleType_Goal = 1, /* go to goal assigned object or loudest assigned signal source */ - eBoidRuleType_Avoid = 2, /* get away from assigned object or loudest assigned signal source */ - eBoidRuleType_AvoidCollision = 3, /* manoeuver to avoid collisions with other boids and deflector object in near future */ - eBoidRuleType_Separate = 4, /* keep from going through other boids */ - eBoidRuleType_Flock = 5, /* move to center of neighbors and match their velocity */ - eBoidRuleType_FollowLeader = 6, /* follow a boid or assigned object */ - eBoidRuleType_AverageSpeed = 7, /* maintain speed, flight level or wander*/ - eBoidRuleType_Fight = 8, /* go to closest enemy and attack when in range */ - //eBoidRuleType_Protect = 9, /* go to enemy closest to target and attack when in range */ - //eBoidRuleType_Hide = 10, /* find a deflector move to it's other side from closest enemy */ - //eBoidRuleType_FollowPath = 11, /* move along a assigned curve or closest curve in a group */ - //eBoidRuleType_FollowWall = 12, /* move next to a deflector object's in direction of it's tangent */ + eBoidRuleType_Goal = 1, /* go to goal assigned object or loudest assigned signal source */ + eBoidRuleType_Avoid = 2, /* get away from assigned object or loudest assigned signal source */ + eBoidRuleType_AvoidCollision = 3, /* manoeuver to avoid collisions with other boids and deflector object in near future */ + eBoidRuleType_Separate = 4, /* keep from going through other boids */ + eBoidRuleType_Flock = 5, /* move to center of neighbors and match their velocity */ + eBoidRuleType_FollowLeader = 6, /* follow a boid or assigned object */ + eBoidRuleType_AverageSpeed = 7, /* maintain speed, flight level or wander*/ + eBoidRuleType_Fight = 8, /* go to closest enemy and attack when in range */ + //eBoidRuleType_Protect = 9, /* go to enemy closest to target and attack when in range */ + //eBoidRuleType_Hide = 10, /* find a deflector move to it's other side from closest enemy */ + //eBoidRuleType_FollowPath = 11, /* move along a assigned curve or closest curve in a group */ + //eBoidRuleType_FollowWall = 12, /* move next to a deflector object's in direction of it's tangent */ NUM_BOID_RULE_TYPES } BoidRuleType; @@ -67,7 +67,7 @@ typedef struct BoidRuleGoalAvoid { BoidRule rule; struct Object *ob; int options; - float fear_factor; + float fear_factor; /* signals */ int signal_id, channels; diff --git a/source/blender/makesdna/DNA_camera_types.h b/source/blender/makesdna/DNA_camera_types.h index 73cebfb3d9f..1ece25c9f70 100644 --- a/source/blender/makesdna/DNA_camera_types.h +++ b/source/blender/makesdna/DNA_camera_types.h @@ -99,7 +99,7 @@ typedef struct Camera { #define CAM_SHOWSENSOR 256 /* yafray: dof sampling switch */ -/* #define CAM_YF_NO_QMC 512 */ /* depreceated */ +/* #define CAM_YF_NO_QMC 512 */ /* deprecated */ /* Sensor fit */ #define CAMERA_SENSOR_FIT_AUTO 0 diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 4928a88b33e..df1cba6a44d 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -45,7 +45,7 @@ */ typedef struct ClothSimSettings { - struct LinkNode *cache; /* UNUSED atm */ + struct LinkNode *cache; /* UNUSED atm */ float mingoal; /* see SB */ float Cdis; /* Mechanical damping of springs. */ float Cvi; /* Viscous/fluid damping. */ diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index ad3284d430d..f1b7a7c3cc3 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -42,7 +42,7 @@ struct Text; struct Ipo; /* channels reside in Object or Action (ListBase) constraintChannels */ -// XXX depreceated... old AnimSys +// XXX deprecated... old AnimSys typedef struct bConstraintChannel { struct bConstraintChannel *next, *prev; struct Ipo *ipo; @@ -170,7 +170,7 @@ typedef struct bSplineIKConstraint { short numpoints; /* number of points to bound in points array */ short chainlen; /* number of bones ('n') that are in the chain */ - /* settings */ + /* settings */ short flag; /* general settings for constraint */ short xzScaleMode; /* method used for determining the x & z scaling of the bones */ } bSplineIKConstraint; @@ -182,7 +182,7 @@ typedef struct bSplineIKConstraint { typedef struct bTrackToConstraint { struct Object *tar; int reserved1; /* I'll be using reserved1 and reserved2 as Track and Up flags, - * not sure if that's what they were intented for anyway. + * not sure if that's what they were intended for anyway. * Not sure either if it would create backward incompatibility if I were to rename them. * - theeth*/ int reserved2; @@ -340,7 +340,7 @@ typedef struct bTransformConstraint { float from_max[3]; /* to map on to to_min/max range. */ float to_min[3]; /* range of motion on owner caused by target */ - float to_max[3]; + float to_max[3]; } bTransformConstraint; /* Pivot Constraint */ @@ -486,7 +486,7 @@ typedef enum eBConstraint_Flags { CONSTRAINT_EXPAND = (1<<0), /* pre-check for illegal object name or bone name */ CONSTRAINT_DISABLE = (1<<2), - /* to indicate which Ipo should be shown, maybe for 3d access later too */ + /* to indicate which Ipo should be shown, maybe for 3d access later too */ CONSTRAINT_ACTIVE = (1<<4), /* to indicate that the owner's space should only be changed into ownspace, but not out of it */ CONSTRAINT_SPACEONCE = (1<<6), @@ -515,7 +515,7 @@ typedef enum eBConstraint_SpaceTypes { } eBConstraint_SpaceTypes; /* bConstraintChannel.flag */ -// XXX depreceated... old AnimSys +// XXX deprecated... old AnimSys typedef enum eConstraintChannel_Flags { CONSTRAINT_CHANNEL_SELECT = (1<<0), CONSTRAINT_CHANNEL_PROTECTED = (1<<1) @@ -539,7 +539,7 @@ typedef enum eCopyLocation_Flags { LOCLIKE_X = (1<<0), LOCLIKE_Y = (1<<1), LOCLIKE_Z = (1<<2), - /* LOCLIKE_TIP is a depreceated option... use headtail=1.0f instead */ + /* LOCLIKE_TIP is a deprecated option... use headtail=1.0f instead */ LOCLIKE_TIP = (1<<3), LOCLIKE_X_INVERT = (1<<4), LOCLIKE_Y_INVERT = (1<<5), @@ -664,7 +664,7 @@ typedef enum eSplineIK_Flags { /* bones in the chain should not scale to fit the curve */ CONSTRAINT_SPLINEIK_SCALE_LIMITED = (1<<2), /* evenly distribute the bones along the path regardless of length */ - CONSTRAINT_SPLINEIK_EVENSPLITS = (1<<3), + CONSTRAINT_SPLINEIK_EVENSPLITS = (1<<3), /* don't adjust the x and z scaling of the bones by the curve radius */ CONSTRAINT_SPLINEIK_NO_CURVERAD = (1<<4) } eSplineIK_Flags; @@ -751,7 +751,7 @@ typedef enum eChildOf_Flags { /* Restrictions for Pivot Constraint axis to consider for enabling constraint */ typedef enum ePivotConstraint_Axis { /* do not consider this activity-clamping */ - PIVOTCON_AXIS_NONE = -1, + PIVOTCON_AXIS_NONE = -1, /* consider -ve x-axis rotations */ PIVOTCON_AXIS_X_NEG = 0, diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 284694f2b48..3cf84648ea6 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -74,7 +74,7 @@ typedef struct Path { typedef struct BevList { struct BevList *next, *prev; int nr, dupe_nr; - short poly, hole; + int poly, hole; } BevList; /* These two Lines with # tell makesdna this struct can be excluded. */ @@ -234,11 +234,11 @@ typedef struct Curve { float ctime; /* current evaltime - for use by Objects parented to curves */ int totbox, actbox; - struct TextBox *tb; + struct TextBox *tb; - int selstart, selend; + int selstart, selend; - struct CharInfo *strinfo; + struct CharInfo *strinfo; struct CharInfo curinfo; float bevfac1, bevfac2; diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 377af042922..6f7bb5a723e 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -36,8 +36,6 @@ extern "C" { #endif -#include "DNA_defs.h" /* USE_BMESH_FORWARD_COMPAT */ - /** descriptor and storage for a custom data layer */ typedef struct CustomDataLayer { int type; /* type of data in layer */ @@ -74,7 +72,7 @@ typedef struct CustomData { /* CustomData.type */ #define CD_MVERT 0 -#define CD_MSTICKY 1 +#define CD_MSTICKY 1 /* DEPRECATED */ #define CD_MDEFORMVERT 2 #define CD_MEDGE 3 #define CD_MFACE 4 @@ -82,7 +80,7 @@ typedef struct CustomData { #define CD_MCOL 6 #define CD_ORIGINDEX 7 #define CD_NORMAL 8 -#define CD_POLYINDEX 9 +//#define CD_POLYINDEX 9 #define CD_PROP_FLT 10 #define CD_PROP_INT 11 #define CD_PROP_STR 12 @@ -118,7 +116,7 @@ typedef struct CustomData { /* Bits for CustomDataMask */ #define CD_MASK_MVERT (1 << CD_MVERT) -#define CD_MASK_MSTICKY (1 << CD_MSTICKY) +#define CD_MASK_MSTICKY (1 << CD_MSTICKY) /* DEPRECATED */ #define CD_MASK_MDEFORMVERT (1 << CD_MDEFORMVERT) #define CD_MASK_MEDGE (1 << CD_MEDGE) #define CD_MASK_MFACE (1 << CD_MFACE) @@ -126,7 +124,7 @@ typedef struct CustomData { #define CD_MASK_MCOL (1 << CD_MCOL) #define CD_MASK_ORIGINDEX (1 << CD_ORIGINDEX) #define CD_MASK_NORMAL (1 << CD_NORMAL) -#define CD_MASK_POLYINDEX (1 << CD_POLYINDEX) +// #define CD_MASK_POLYINDEX (1 << CD_POLYINDEX) #define CD_MASK_PROP_FLT (1 << CD_PROP_FLT) #define CD_MASK_PROP_INT (1 << CD_PROP_INT) #define CD_MASK_PROP_STR (1 << CD_PROP_STR) diff --git a/source/blender/makesdna/DNA_defs.h b/source/blender/makesdna/DNA_defs.h index 762e027f934..774fbcf081a 100644 --- a/source/blender/makesdna/DNA_defs.h +++ b/source/blender/makesdna/DNA_defs.h @@ -45,9 +45,6 @@ /* hrmf, we need a better include then this */ #include "../blenloader/BLO_sys_types.h" /* needed for int64_t only! */ -/* Must not be defined for BMesh, as this guards code for pre-BMesh code to load BMesh .blend files */ -/* #define USE_BMESH_FORWARD_COMPAT */ - /* non-id name variables should use this length */ #define MAX_NAME 64 diff --git a/source/blender/makesdna/DNA_dynamicpaint_types.h b/source/blender/makesdna/DNA_dynamicpaint_types.h index ca1b1bf1725..1f2a589dc27 100644 --- a/source/blender/makesdna/DNA_dynamicpaint_types.h +++ b/source/blender/makesdna/DNA_dynamicpaint_types.h @@ -136,7 +136,7 @@ typedef struct DynamicPaintSurface { /* canvas flags */ #if 0 /* This should not be needed, having a valid WEIGHT_MCOL layer should be enough. - * And if not, should be a general flag. But seems unecessary for now... */ + * And if not, should be a general flag. But seems unnecessary for now... */ #define MOD_DPAINT_PREVIEW_READY (1<<0) /* if viewport preview is ready */ #endif #define MOD_DPAINT_BAKING (1<<1) /* surface is already baking, so it wont get updated (loop) */ diff --git a/source/blender/makesdna/DNA_genfile.h b/source/blender/makesdna/DNA_genfile.h index 20f7bb44e92..2d1549ff487 100644 --- a/source/blender/makesdna/DNA_genfile.h +++ b/source/blender/makesdna/DNA_genfile.h @@ -35,8 +35,8 @@ struct SDNA; -extern unsigned char DNAstr[]; /* DNA.c */ -extern int DNAlen; +extern const unsigned char DNAstr[]; /* DNA.c */ +extern const int DNAlen; typedef enum eSDNA_Type { SDNA_TYPE_CHAR = 0, @@ -56,7 +56,7 @@ typedef enum eSDNA_Type { /* define so switch statements don't complain */ #define SDNA_TYPE_VOID 9 -struct SDNA *DNA_sdna_from_data(void *data, int datalen, int do_endian_swap); +struct SDNA *DNA_sdna_from_data(const void *data, const int datalen, int do_endian_swap); void DNA_sdna_free(struct SDNA *sdna); int DNA_struct_find_nr(struct SDNA *sdna, const char *str); diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 3de5372d848..100968e7257 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -39,7 +39,7 @@ * This assumes that the bottom-left corner is (0,0) */ typedef struct bGPDspoint { - float x, y, z; /* co-ordinates of point (usually 2d, but can be 3d as well) */ + float x, y, z; /* co-ordinates of point (usually 2d, but can be 3d as well) */ float pressure; /* pressure of input device (from 0 to 1) at this point */ } bGPDspoint; @@ -53,7 +53,7 @@ typedef struct bGPDstroke { bGPDspoint *points; /* array of data-points for stroke */ int totpoints; /* number of data-points in array */ - short thickness; /* thickness of stroke (currently not used) */ + short thickness; /* thickness of stroke (currently not used) */ short flag; /* various settings about this stroke */ } bGPDstroke; @@ -94,7 +94,7 @@ typedef struct bGPDlayer { ListBase frames; /* list of annotations to display for frames (bGPDframe list) */ bGPDframe *actframe; /* active frame (should be the frame that is currently being displayed) */ - int flag; /* settings for layer */ + int flag; /* settings for layer */ short thickness; /* current thickness to apply to strokes */ short gstep; /* max number of frames between active and ghost to show (0=only those on either side) */ @@ -141,16 +141,16 @@ typedef struct bGPdata { } bGPdata; /* bGPdata->flag */ -// XXX many of these flags should be depreceated for more general ideas in 2.5 +// XXX many of these flags should be deprecated for more general ideas in 2.5 /* don't allow painting to occur at all */ - // XXX is depreceated - not well understood + // XXX is deprecated - not well understood #define GP_DATA_LMBPLOCK (1<<0) /* show debugging info in viewport (i.e. status print) */ #define GP_DATA_DISPINFO (1<<1) /* in Action Editor, show as expanded channel */ #define GP_DATA_EXPAND (1<<2) /* is the block overriding all clicks? */ - // XXX is depreceated - nasty old concept + // XXX is deprecated - nasty old concept #define GP_DATA_EDITPAINT (1<<3) /* new strokes are added in viewport space */ #define GP_DATA_VIEWALIGN (1<<4) diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index 38058dbb699..fe3550327f7 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -137,6 +137,7 @@ typedef struct Image { #define IMA_CLAMP_U 16 #define IMA_CLAMP_V 32 #define IMA_TPAGE_REFRESH 64 +#define IMA_GLBIND_IS_DATA 128 /* opengl image texture bound as non-color data */ /* ima->type and ima->source moved to BKE_image.h, for API */ diff --git a/source/blender/makesdna/DNA_ipo_types.h b/source/blender/makesdna/DNA_ipo_types.h index 6bf8dbbe73a..3e641fba1ac 100644 --- a/source/blender/makesdna/DNA_ipo_types.h +++ b/source/blender/makesdna/DNA_ipo_types.h @@ -28,7 +28,7 @@ /** \file DNA_ipo_types.h * \ingroup DNA * \deprecated - * The contents of this file are now officially depreceated. They were used for the 'old' animation system, + * The contents of this file are now officially deprecated. They were used for the 'old' animation system, * which has (as of 2.50) been replaced with a completely new system by Joshua Leung (aligorith). All defines, * etc. are only still maintained to provide backwards compatibility for old files. */ @@ -93,7 +93,7 @@ typedef struct Ipo { rctf cur; /* Rect defining extents of keyframes? */ short blocktype, showkey; /* blocktype: self-explanatory; showkey: either 0 or 1 (show vertical yellow lines for editing) */ - short muteipo, pad; /* muteipo: either 0 or 1 (whether ipo block is muted) */ + short muteipo, pad; /* muteipo: either 0 or 1 (whether ipo block is muted) */ } Ipo; /* ----------- adrcodes (for matching ipo-curves to data) ------------- */ diff --git a/source/blender/makesdna/DNA_key_types.h b/source/blender/makesdna/DNA_key_types.h index 8494e663fbe..6e5861043c1 100644 --- a/source/blender/makesdna/DNA_key_types.h +++ b/source/blender/makesdna/DNA_key_types.h @@ -105,7 +105,7 @@ typedef struct Key { /* Key->type: KeyBlocks are interpreted as... */ enum { - /* Sequencial positions over time (using KeyBlock->pos and Key->ctime) */ + /* Sequential positions over time (using KeyBlock->pos and Key->ctime) */ KEY_NORMAL = 0, /* States to blend between (default) */ diff --git a/source/blender/makesdna/DNA_lamp_types.h b/source/blender/makesdna/DNA_lamp_types.h index 4884db14c57..f36e65085c9 100644 --- a/source/blender/makesdna/DNA_lamp_types.h +++ b/source/blender/makesdna/DNA_lamp_types.h @@ -109,7 +109,7 @@ typedef struct Lamp { struct PreviewImage *preview; /* nodes */ - struct bNodeTree *nodetree; + struct bNodeTree *nodetree; } Lamp; /* **************** LAMP ********************* */ diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index bf388d8c018..5b25d1a072c 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -211,4 +211,4 @@ enum { MASK_ANIMF_EXPAND = (1 << 4) }; -#endif // __DNA_MASK_TYPES_H__ +#endif /* __DNA_MASK_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 940c5c5f30b..9a8d3bf981c 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -86,7 +86,7 @@ typedef struct Material { ID id; struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */ - short material_type, flag; + short material_type, flag; /* note, keep this below synced with render_types.h */ float r, g, b; float specr, specg, specb; @@ -130,8 +130,11 @@ typedef struct Material { /* for buttons and render*/ char rgbsel, texact, pr_type, use_nodes; - short pr_back, pr_lamp, pr_texture, ml_flag; /* ml_flag is for disable base material */ + short pr_lamp, pr_texture, ml_flag; /* ml_flag is for disable base material */ + /* mapping */ + char mapflag, pad; + /* shaders */ short diff_shader, spec_shader; float roughness, refrac; @@ -140,6 +143,8 @@ typedef struct Material { float param[4]; /* size, smooth, size, smooth, for toonshader, 0 (fac) and 1 (fresnel) also for fresnel shader */ float rms; float darkness; + + /* runtime - OR'd from 'mtex' */ short texco, mapto; /* ramp colors */ @@ -151,7 +156,7 @@ typedef struct Material { float rampfac_col, rampfac_spec; struct MTex *mtex[18]; /* MAX_MTEX */ - struct bNodeTree *nodetree; + struct bNodeTree *nodetree; struct Ipo *ipo DNA_DEPRECATED; /* old animation system, deprecated for 2.5 */ struct Group *group; /* light group */ struct PreviewImage *preview; @@ -271,6 +276,9 @@ typedef struct Material { #define MA_MODE_MASK 0x6fffffff /* all valid mode bits */ +/* mapflag */ +#define MA_MAPFLAG_UVPROJECT (1 << 0) + /* ray mirror fadeout */ #define MA_RAYMIR_FADETOSKY 0 #define MA_RAYMIR_FADETOMAT 1 @@ -284,6 +292,7 @@ typedef struct Material { #define MA_CUBIC 1 #define MA_OBCOLOR 2 #define MA_APPROX_OCCLUSION 4 +#define MA_GROUP_LOCAL 8 /* diff_shader */ #define MA_DIFF_LAMBERT 0 @@ -337,7 +346,7 @@ typedef struct Material { #define TEXCO_OBJECT 32 #define TEXCO_LAVECTOR 64 #define TEXCO_VIEW 128 -#define TEXCO_STICKY 256 +#define TEXCO_STICKY_ 256 // DEPRECATED #define TEXCO_OSA 512 #define TEXCO_WINDOW 1024 #define NEED_UV 2048 diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index e584cfd76ac..dd0845dbf1e 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -37,8 +37,6 @@ #include "DNA_ID.h" #include "DNA_customdata_types.h" -#include "DNA_defs.h" /* USE_BMESH_FORWARD_COMPAT */ - struct AnimData; struct DerivedMesh; struct Ipo; @@ -89,8 +87,7 @@ typedef struct Mesh { /* array of colors for the tessellated faces, must be number of tessellated * faces * 4 in length */ - struct MCol *mcol; - struct MSticky *msticky; + struct MCol *mcol; struct Mesh *texcomesh; /* When the object is available, the preferred access method is: BMEdit_FromObject(ob) */ diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 54e1e762f8b..0c193e9be21 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -72,7 +72,7 @@ typedef struct MVert { * at the moment alpha is abused for vertex painting * and not used for transparency, note that red and blue are swapped */ typedef struct MCol { - char a, r, g, b; + char a, r, g, b; } MCol; /* new face structure, replaces MFace, which is now @@ -146,13 +146,9 @@ typedef struct MLoopCol { mcol__tmp->a = mloopcol__tmp->a; \ } (void)0 -typedef struct MSticky { - float co[2]; -} MSticky; - typedef struct MSelect { int index; - int type; /* EDITVERT/EDITEDGE/EDITFACE */ + int type; /* ME_VSEL/ME_ESEL/ME_FSEL */ } MSelect; /*tessellation uv face data*/ diff --git a/source/blender/makesdna/DNA_meta_types.h b/source/blender/makesdna/DNA_meta_types.h index 2912650c77c..5b37ff523cb 100644 --- a/source/blender/makesdna/DNA_meta_types.h +++ b/source/blender/makesdna/DNA_meta_types.h @@ -93,7 +93,7 @@ typedef struct MetaBall { /* used in editmode */ /*ListBase edit_elems;*/ - MetaElem *lastelem; + MetaElem *lastelem; } MetaBall; /* **************** METABALL ********************* */ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 4172db90c05..c9e929ce41b 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -28,9 +28,6 @@ #include "DNA_defs.h" #include "DNA_listBase.h" - -#define MODSTACK_DEBUG 1 - /* WARNING ALERT! TYPEDEF VALUES ARE WRITTEN IN FILES! SO DO NOT CHANGE! * (ONLY ADD NEW ITEMS AT THE END) */ @@ -78,6 +75,7 @@ typedef enum ModifierType { eModifierType_DynamicPaint = 40, eModifierType_Remesh = 41, eModifierType_Skin = 42, + eModifierType_LaplacianSmooth = 43, NUM_MODIFIER_TYPES } ModifierType; @@ -351,7 +349,7 @@ typedef struct UVProjectModifierData { int flags; int num_projectors; float aspectx, aspecty; - float scalex, scaley; + float scalex, scaley; char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ int uvlayer_tmp, pad; } UVProjectModifierData; @@ -364,10 +362,30 @@ typedef struct UVProjectModifierData { typedef struct DecimateModifierData { ModifierData modifier; - float percent; - int faceCount; + float percent; /* (mode == MOD_DECIM_MODE_COLLAPSE) */ + short iter; /* (mode == MOD_DECIM_MODE_UNSUBDIV) */ + short pad; + float angle; /* (mode == MOD_DECIM_MODE_DISSOLVE) */ + + char defgrp_name[64]; /* MAX_VGROUP_NAME */ + short flag, mode; + + /* runtime only */ + int face_count, pad2; } DecimateModifierData; +enum { + MOD_DECIM_FLAG_INVERT_VGROUP = (1 << 0), + MOD_DECIM_FLAG_TRIANGULATE = (1 << 1), /* for collapse only. dont convert tri pairs back to quads */ + MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS = (1 << 2) /* for dissolve only. collapse all verts between 2 faces */ +}; + +enum { + MOD_DECIM_MODE_COLLAPSE, + MOD_DECIM_MODE_UNSUBDIV, + MOD_DECIM_MODE_DISSOLVE /* called planar in the UI */ +}; + /* Smooth modifier flags */ #define MOD_SMOOTH_X (1<<1) #define MOD_SMOOTH_Y (1<<2) @@ -686,7 +704,7 @@ typedef struct SimpleDeformModifierData { struct Object *origin; /* object to control the origin of modifier space coordinates */ char vgroup_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */ float factor; /* factors to control simple deforms */ - float limit[2]; /* lower and upper limit */ + float limit[2]; /* lower and upper limit */ char mode; /* deform function */ char axis; /* lock axis (for taper and strech) */ @@ -705,6 +723,8 @@ typedef struct SimpleDeformModifierData { /* indicates whether simple deform should use the local * coordinates or global coordinates of origin */ +/* XXX, this should have never been an option, all other modifiers work relatively + * (so moving both objects makes no change!) - Campbell */ #define MOD_SIMPLEDEFORM_ORIGIN_LOCAL (1<<0) #define MOD_UVPROJECT_MAX 10 @@ -1093,4 +1113,17 @@ enum { MOD_SKIN_SMOOTH_SHADING = 1 }; +/* Smooth modifier flags */ +#define MOD_LAPLACIANSMOOTH_X (1<<1) +#define MOD_LAPLACIANSMOOTH_Y (1<<2) +#define MOD_LAPLACIANSMOOTH_Z (1<<3) +#define MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION (1<<4) + +typedef struct LaplacianSmoothModifierData { + ModifierData modifier; + float lambda, lambda_border, pad1; + char defgrp_name[64]; /* MAX_VGROUP_NAME */ + short flag, repeat; +} LaplacianSmoothModifierData; + #endif diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h index cda51779528..499f1c50155 100644 --- a/source/blender/makesdna/DNA_movieclip_types.h +++ b/source/blender/makesdna/DNA_movieclip_types.h @@ -118,38 +118,50 @@ typedef struct MovieClipScopes { } MovieClipScopes; /* MovieClipProxy->build_size_flag */ -#define MCLIP_PROXY_SIZE_25 (1 << 0) -#define MCLIP_PROXY_SIZE_50 (1 << 1) -#define MCLIP_PROXY_SIZE_75 (1 << 2) -#define MCLIP_PROXY_SIZE_100 (1 << 3) -#define MCLIP_PROXY_UNDISTORTED_SIZE_25 (1 << 4) -#define MCLIP_PROXY_UNDISTORTED_SIZE_50 (1 << 5) -#define MCLIP_PROXY_UNDISTORTED_SIZE_75 (1 << 6) -#define MCLIP_PROXY_UNDISTORTED_SIZE_100 (1 << 7) +enum { + MCLIP_PROXY_SIZE_25 = (1 << 0), + MCLIP_PROXY_SIZE_50 = (1 << 1), + MCLIP_PROXY_SIZE_75 = (1 << 2), + MCLIP_PROXY_SIZE_100 = (1 << 3), + MCLIP_PROXY_UNDISTORTED_SIZE_25 = (1 << 4), + MCLIP_PROXY_UNDISTORTED_SIZE_50 = (1 << 5), + MCLIP_PROXY_UNDISTORTED_SIZE_75 = (1 << 6), + MCLIP_PROXY_UNDISTORTED_SIZE_100 = (1 << 7) +}; /* MovieClip->source */ -#define MCLIP_SRC_SEQUENCE 1 -#define MCLIP_SRC_MOVIE 2 +enum { + MCLIP_SRC_SEQUENCE = 1, + MCLIP_SRC_MOVIE = 2 +}; /* MovieClip->selection types */ -#define MCLIP_SEL_NONE 0 -#define MCLIP_SEL_TRACK 1 +enum { + MCLIP_SEL_NONE = 0, + MCLIP_SEL_TRACK = 1 +}; /* MovieClip->flag */ -#define MCLIP_USE_PROXY (1 << 0) -#define MCLIP_USE_PROXY_CUSTOM_DIR (1 << 1) -/*#define MCLIP_CUSTOM_START_FRAME (1<<2)*/ /* UNUSED */ +enum { + MCLIP_USE_PROXY = (1 << 0), + MCLIP_USE_PROXY_CUSTOM_DIR = (1 << 1), + /* MCLIP_CUSTOM_START_FRAME = (1<<2), */ /* UNUSED */ -#define MCLIP_TIMECODE_FLAGS (MCLIP_USE_PROXY | MCLIP_USE_PROXY_CUSTOM_DIR) + MCLIP_TIMECODE_FLAGS = (MCLIP_USE_PROXY | MCLIP_USE_PROXY_CUSTOM_DIR) +}; /* MovieClip->render_size */ -#define MCLIP_PROXY_RENDER_SIZE_FULL 0 -#define MCLIP_PROXY_RENDER_SIZE_25 1 -#define MCLIP_PROXY_RENDER_SIZE_50 2 -#define MCLIP_PROXY_RENDER_SIZE_75 3 -#define MCLIP_PROXY_RENDER_SIZE_100 4 +enum { + MCLIP_PROXY_RENDER_SIZE_FULL = 0, + MCLIP_PROXY_RENDER_SIZE_25 = 1, + MCLIP_PROXY_RENDER_SIZE_50 = 2, + MCLIP_PROXY_RENDER_SIZE_75 = 3, + MCLIP_PROXY_RENDER_SIZE_100 = 4 +}; /* MovieClip->render_flag */ -#define MCLIP_PROXY_RENDER_UNDISTORT 1 +enum { + MCLIP_PROXY_RENDER_UNDISTORT = 1 +}; #endif diff --git a/source/blender/makesdna/DNA_nla_types.h b/source/blender/makesdna/DNA_nla_types.h index 43b52ed65eb..5837f891ae0 100644 --- a/source/blender/makesdna/DNA_nla_types.h +++ b/source/blender/makesdna/DNA_nla_types.h @@ -50,7 +50,7 @@ typedef struct bActionModifier { /* path deform modifier */ short no_rot_axis; - struct Object *ob; + struct Object *ob; } bActionModifier; /* NLA-Modifier Types */ diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 3f1f4933585..c73ba87754f 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -167,6 +167,7 @@ typedef struct bNode { struct ID *id; /* optional link to libdata */ void *storage; /* custom data, must be struct, for storage in file */ struct bNode *original; /* the original node in the tree (for localized tree) */ + ListBase internal_links; /* list of cached internal links (input to output), for muted nodes and operators */ float locx, locy; /* root offset for drawing (parent space) */ float width, height; /* node custom width and height */ @@ -240,6 +241,7 @@ typedef struct bNodeLink { /* link->flag */ #define NODE_LINKFLAG_HILITE 1 /* link has been successfully validated */ #define NODE_LINK_VALID 2 +#define NODE_LINK_TEST 4 /* free test flag, undefined */ /* tree->edit_quality/tree->render_quality */ #define NTREE_QUALITY_HIGH 0 @@ -702,6 +704,26 @@ typedef struct NodeTrackPosData { char track_name[64]; } NodeTrackPosData; +typedef struct NodeShaderScript { + int mode; + int flag; + + char filepath[1024]; /* 1024 = FILE_MAX */ + + char bytecode_hash[64]; + char *bytecode; + + IDProperty *prop; +} NodeShaderScript; + +/* script node mode */ +#define NODE_SCRIPT_INTERNAL 0 +#define NODE_SCRIPT_EXTERNAL 1 + +/* script node flag */ +#define NODE_SCRIPT_AUTO_UPDATE 1 + + /* frame node flags */ #define NODE_FRAME_SHRINK 1 /* keep the bounding box minimal */ #define NODE_FRAME_RESIZEABLE 2 /* test flag, if frame can be resized by user */ diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h index 1dd2aa6c59b..5cc56d861a3 100644 --- a/source/blender/makesdna/DNA_object_force.h +++ b/source/blender/makesdna/DNA_object_force.h @@ -54,6 +54,7 @@ typedef enum PFieldType { PFIELD_BOID = 10, /* Defines predator / goal for boids */ PFIELD_TURBULENCE = 11, /* Force defined by BLI_gTurbulence */ PFIELD_DRAG = 12, /* Linear & quadratic drag */ + PFIELD_SMOKEFLOW = 13, /* Force based on smoke simulation air flow */ NUM_PFIELD_TYPES } PFieldType; @@ -110,14 +111,17 @@ typedef struct PartDeflect { struct RNG *rng; /* random noise generator for e.g. wind */ float f_noise; /* noise of force */ int seed; /* noise random seed */ + + struct Object *f_source; /* force source object */ } PartDeflect; typedef struct EffectorWeights { struct Group *group; /* only use effectors from this group of objects */ - float weight[13]; /* effector type specific weights */ + float weight[14]; /* effector type specific weights */ float global_gravity; short flag, rt[3]; + int pad; } EffectorWeights; /* EffectorWeights->flag */ @@ -276,7 +280,7 @@ typedef struct SoftBody { float nodemass; /* softbody mass of *vertex* */ char namedVG_Mass[64]; /* MAX_VGROUP_NAME */ /* along with it introduce mass painting - * starting to fix old bug .. nastyness that VG are indexes + * starting to fix old bug .. nastiness that VG are indexes * rather find them by name tag to find it -> jow20090613 */ float grav; /* softbody amount of gravitaion to apply */ float mediafrict; /* friction to env */ @@ -291,7 +295,7 @@ typedef struct SoftBody { float defgoal; /* default goal for vertices without vgroup */ short vertgroup; /* index starting at 1 */ char namedVG_Softgoal[64]; /* MAX_VGROUP_NAME */ - /* starting to fix old bug .. nastyness that VG are indexes + /* starting to fix old bug .. nastiness that VG are indexes * rather find them by name tag to find it -> jow20090613 */ short fuzzyness; /* */ @@ -301,7 +305,7 @@ typedef struct SoftBody { float infrict; /* softbody inner springs friction */ char namedVG_Spring_K[64]; /* MAX_VGROUP_NAME */ /* along with it introduce Spring_K painting - * starting to fix old bug .. nastyness that VG are indexes + * starting to fix old bug .. nastiness that VG are indexes * rather find them by name tag to find it -> jow20090613 */ /* baking */ @@ -365,6 +369,7 @@ typedef struct SoftBody { #define PFIELD_DO_LOCATION (1<<14) #define PFIELD_DO_ROTATION (1<<15) #define PFIELD_GUIDE_PATH_WEIGHT (1<<16) /* apply curve weights */ +#define PFIELD_SMOKE_DENSITY (1<<17) /* multiply smoke force by density */ /* pd->falloff */ #define PFIELD_FALL_SPHERE 0 @@ -395,7 +400,7 @@ typedef struct SoftBody { //#define PTCACHE_BAKE_EDIT 16 //#define PTCACHE_BAKE_EDIT_ACTIVE 32 #define PTCACHE_DISK_CACHE 64 -#define PTCACHE_QUICK_CACHE 128 +//#define PTCACHE_QUICK_CACHE 128 /* removed since 2.64 - [#30974], could be added back in a more useful way */ #define PTCACHE_FRAMES_SKIPPED 256 #define PTCACHE_EXTERNAL 512 #define PTCACHE_READ_INFO 1024 diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index af44db3896a..29f6499986c 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -117,7 +117,7 @@ typedef struct Object { struct Ipo *ipo DNA_DEPRECATED; /* old animation system, deprecated for 2.5 */ /* struct Path *path; */ struct BoundBox *bb; - struct bAction *action DNA_DEPRECATED; // XXX depreceated... old animation system + struct bAction *action DNA_DEPRECATED; // XXX deprecated... old animation system struct bAction *poselib; struct bPose *pose; /* pose data, armature objects only */ void *data; /* pointer to objects data - an 'ID' or NULL */ @@ -127,8 +127,8 @@ typedef struct Object { bAnimVizSettings avs; /* settings for visualization of object-transform animation */ bMotionPath *mpath; /* motion path cache for this object */ - ListBase constraintChannels DNA_DEPRECATED; // XXX depreceated... old animation system - ListBase effect DNA_DEPRECATED; // XXX depreceated... keep for readfile + ListBase constraintChannels DNA_DEPRECATED; // XXX deprecated... old animation system + ListBase effect DNA_DEPRECATED; // XXX deprecated... keep for readfile ListBase disp; /* list of DispList, used by lattice, metaballs curve & surfaces */ ListBase defbase; /* list of bDeformGroup (vertex groups) names and flag only */ ListBase modifiers; /* list of ModifierData structures */ @@ -175,7 +175,7 @@ typedef struct Object { short transflag, protectflag; /* transformation settings and transform locks */ short trackflag, upflag; short nlaflag; /* used for DopeSheet filtering settings (expanded/collapsed) */ - short ipoflag; // xxx depreceated... old animation system + short ipoflag; // xxx deprecated... old animation system short scaflag; /* ui state for game logic */ char scavisflag; /* more display settings for game logic */ char pad5; @@ -209,7 +209,9 @@ typedef struct Object { float step_height; float jump_speed; float fall_speed; - char pad1[4]; + + /** Collision mask settings */ + unsigned short col_group, col_mask; short rotmode; /* rotation mode - uses defines set out in DNA_action_types.h for PoseChannel rotations... */ @@ -244,8 +246,8 @@ typedef struct Object { float anisotropicFriction[3]; ListBase constraints; /* object constraints */ - ListBase nlastrips DNA_DEPRECATED; // XXX depreceated... old animation system - ListBase hooks DNA_DEPRECATED; // XXX depreceated... old animation system + ListBase nlastrips DNA_DEPRECATED; // XXX deprecated... old animation system + ListBase hooks DNA_DEPRECATED; // XXX deprecated... old animation system ListBase particlesystem; /* particle systems */ struct PartDeflect *pd; /* particle deflector/attractor/collision data */ @@ -378,6 +380,7 @@ typedef struct DupliObject { #define OB_DUPLIPARTS 2048 #define OB_RENDER_DUPLI 4096 #define OB_NO_CONSTRAINTS 8192 /* runtime constraints disable */ +#define OB_NO_PSYS_UPDATE 16384 /* hack to work around particle issue */ /* (short) ipoflag */ /* XXX: many old flags for features removed due to incompatibility @@ -478,6 +481,9 @@ typedef struct DupliObject { /* controller state */ #define OB_MAX_STATES 30 +/* collision masks */ +#define OB_MAX_COL_MASKS 8 + /* ob->gameflag */ #define OB_DYNAMIC 1 #define OB_CHILD 2 diff --git a/source/blender/makesdna/DNA_packedFile_types.h b/source/blender/makesdna/DNA_packedFile_types.h index f01e89d18c9..ef0a0f642d6 100644 --- a/source/blender/makesdna/DNA_packedFile_types.h +++ b/source/blender/makesdna/DNA_packedFile_types.h @@ -35,9 +35,9 @@ #define __DNA_PACKEDFILE_TYPES_H__ typedef struct PackedFile { - int size; - int seek; - void * data; + int size; + int seek; + void *data; } PackedFile; enum PF_FileStatus @@ -45,7 +45,7 @@ enum PF_FileStatus PF_EQUAL = 0, PF_DIFFERS = 1, PF_NOFILE = 2, - + PF_WRITE_ORIGINAL = 3, PF_WRITE_LOCAL = 4, PF_USE_LOCAL = 5, @@ -53,7 +53,7 @@ enum PF_FileStatus PF_KEEP = 7, PF_REMOVE = 8, PF_NOOP = 9, - + PF_ASK = 10 }; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index e3a8863714a..1479d5268ed 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -318,10 +318,11 @@ typedef struct ImageFormatData { /* return values from BKE_imtype_valid_depths, note this is depts per channel */ #define R_IMF_CHAN_DEPTH_1 (1<<0) /* 1bits (unused) */ #define R_IMF_CHAN_DEPTH_8 (1<<1) /* 8bits (default) */ -#define R_IMF_CHAN_DEPTH_12 (1<<2) /* 12bits (uncommon, jp2 supports) */ -#define R_IMF_CHAN_DEPTH_16 (1<<3) /* 16bits (tiff, halff float exr) */ -#define R_IMF_CHAN_DEPTH_24 (1<<4) /* 24bits (unused) */ -#define R_IMF_CHAN_DEPTH_32 (1<<5) /* 32bits (full float exr) */ +#define R_IMF_CHAN_DEPTH_10 (1<<2) /* 10bits (uncommon, Cineon/DPX support) */ +#define R_IMF_CHAN_DEPTH_12 (1<<3) /* 12bits (uncommon, jp2/DPX support) */ +#define R_IMF_CHAN_DEPTH_16 (1<<4) /* 16bits (tiff, halff float exr) */ +#define R_IMF_CHAN_DEPTH_24 (1<<5) /* 24bits (unused) */ +#define R_IMF_CHAN_DEPTH_32 (1<<6) /* 32bits (full float exr) */ /* ImageFormatData.planes */ #define R_IMF_PLANES_RGB 24 @@ -395,11 +396,16 @@ typedef struct RenderData { /** * The number of part to use in the x direction */ - short xparts; + short xparts DNA_DEPRECATED; /** * The number of part to use in the y direction */ - short yparts; + short yparts DNA_DEPRECATED; + + /** + * render tile dimensions + */ + short tilex, tiley; short planes DNA_DEPRECATED, imtype DNA_DEPRECATED, subimtype DNA_DEPRECATED, quality DNA_DEPRECATED; /*deprecated!*/ @@ -447,6 +453,8 @@ typedef struct RenderData { short frs_sec, edgeint; + int pad; + /* safety, border and display rect */ rctf safety, border; @@ -475,7 +483,7 @@ typedef struct RenderData { int color_mgt_flag; /** post-production settings. deprecated, but here for upwards compat (initialized to 1) */ - float postgamma, posthue, postsat; + float postgamma, posthue, postsat; /* Dither noise intensity */ float dither_intensity; @@ -829,14 +837,15 @@ typedef struct VPaint { void *paintcursor; /* wm handle */ } VPaint; -/* VPaint flag */ -#define VP_COLINDEX 1 -#define VP_AREA 2 /* vertex paint only */ - -#define VP_NORMALS 8 -#define VP_SPRAY 16 -// #define VP_MIRROR_X 32 // deprecated in 2.5x use (me->editflag & ME_EDIT_MIRROR_X) -#define VP_ONLYVGROUP 128 /* weight paint only */ +/* VPaint.flag */ +enum { + // VP_COLINDEX = (1 << 0), /* only paint onto active material*/ /* deprecated since before 2.49 */ + VP_AREA = (1 << 1), + VP_NORMALS = (1 << 3), + VP_SPRAY = (1 << 4), + // VP_MIRROR_X = (1 << 5), /* deprecated in 2.5x use (me->editflag & ME_EDIT_MIRROR_X) */ + VP_ONLYVGROUP = (1 << 7) /* weight paint only */ +}; /* *************************************************************** */ /* Transform Orientations */ @@ -1045,7 +1054,7 @@ typedef struct UnitSettings { /* Display/Editing unit options for each scene */ float scale_length; /* maybe have other unit conversions? */ char system; /* imperial, metric etc */ - char system_rotation; /* not implemented as a propper unit system yet */ + char system_rotation; /* not implemented as a proper unit system yet */ short flag; } UnitSettings; @@ -1085,7 +1094,7 @@ typedef struct Scene { short use_nodes; - struct bNodeTree *nodetree; + struct bNodeTree *nodetree; struct Editing *ed; /* sequence editor data is allocated here */ @@ -1186,7 +1195,7 @@ typedef struct Scene { /* seq_flag */ #define R_SEQ_GL_PREV 1 -#define R_SEQ_GL_REND 2 +// #define R_SEQ_GL_REND 2 // UNUSED, opengl render has its own operator now. /* displaymode */ @@ -1300,6 +1309,7 @@ typedef struct Scene { /* sequencer seq_prev_type seq_rend_type */ + /* **************** SCENE ********************* */ /* for general use */ @@ -1352,8 +1362,8 @@ typedef struct Scene { #define SFRA (scene->r.sfra) #define EFRA (scene->r.efra) #define PRVRANGEON (scene->r.flag & SCER_PRV_RANGE) -#define PSFRA ((PRVRANGEON)? (scene->r.psfra): (scene->r.sfra)) -#define PEFRA ((PRVRANGEON)? (scene->r.pefra): (scene->r.efra)) +#define PSFRA ((PRVRANGEON) ? (scene->r.psfra) : (scene->r.sfra)) +#define PEFRA ((PRVRANGEON) ? (scene->r.pefra) : (scene->r.efra)) #define FRA2TIME(a) ((((double) scene->r.frs_sec_base) * (double)(a)) / (double)scene->r.frs_sec) #define TIME2FRA(a) ((((double) scene->r.frs_sec) * (double)(a)) / (double)scene->r.frs_sec_base) #define FPS (((double) scene->r.frs_sec) / (double)scene->r.frs_sec_base) @@ -1451,6 +1461,7 @@ typedef enum SculptFlags { SCULPT_SYMMETRY_FEATHER = (1<<6), SCULPT_USE_OPENMP = (1<<7), SCULPT_ONLY_DEFORM = (1<<8), + SCULPT_SHOW_DIFFUSE = (1<<9), } SculptFlags; /* ImagePaintSettings.flag */ diff --git a/source/blender/makesdna/DNA_sdna_types.h b/source/blender/makesdna/DNA_sdna_types.h index 8b2e7645823..28204ebeb88 100644 --- a/source/blender/makesdna/DNA_sdna_types.h +++ b/source/blender/makesdna/DNA_sdna_types.h @@ -48,7 +48,7 @@ typedef struct SDNA { short *typelens; /* type lengths */ int nr_structs; /* number of struct types */ - short **structs; /* sp = structs[a] is the address of a struct definintion + short **structs; /* sp = structs[a] is the address of a struct definition * sp[0] is struct type number, sp[1] amount of members * * (sp[2], sp[3]), (sp[4], sp[5]), .. are the member diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h index cceb7333478..76ba3fcf7f8 100644 --- a/source/blender/makesdna/DNA_smoke_types.h +++ b/source/blender/makesdna/DNA_smoke_types.h @@ -39,6 +39,7 @@ #define MOD_SMOKE_HIGH_SMOOTH (1<<5) /* smoothens high res emission*/ #define MOD_SMOKE_FILE_LOAD (1<<6) /* flag for file load */ +#define MOD_SMOKE_ADAPTIVE_DOMAIN (1<<7) /* noise */ #define MOD_SMOKE_NOISEWAVE (1<<0) @@ -61,6 +62,12 @@ #define SM_COLL_RIGID 1 #define SM_COLL_ANIMATED 2 +/* smoke data fileds (active_fields) */ +#define SM_ACTIVE_HEAT (1<<0) +#define SM_ACTIVE_FIRE (1<<1) +#define SM_ACTIVE_COLORS (1<<2) +#define SM_ACTIVE_COLOR_SET (1<<3) + typedef struct SmokeDomainSettings { struct SmokeModifierData *smd; /* for fast RNA access */ struct FLUID_3D *fluid; @@ -71,17 +78,37 @@ typedef struct SmokeDomainSettings { struct GPUTexture *tex; struct GPUTexture *tex_wt; struct GPUTexture *tex_shadow; + struct GPUTexture *tex_flame; float *shadow; - float p0[3]; /* start point of BB */ - float p1[3]; /* end point of BB */ - float dx; /* edge length of one cell */ - float omega; /* smoke color - from 0 to 1 */ - float temp; /* fluid temperature */ - float tempAmb; /* ambient temperature */ + + /* simulation data */ + float p0[3]; /* start point of BB in local space (includes sub-cell shift for adaptive domain)*/ + float p1[3]; /* end point of BB in local space */ + float dp0[3]; /* difference from object center to grid start point */ + float cell_size[3]; /* size of simulation cell in local space */ + float global_size[3]; /* global size of domain axises */ + float prev_loc[3]; + int shift[3]; /* current domain shift in simulation cells */ + float shift_f[3]; /* exact domain shift */ + float obj_shift_f[3]; /* how much object has shifted since previous smoke frame (used to "lock" domain while drawing) */ + float imat[4][4]; /* domain object imat */ + float obmat[4][4]; /* domain obmat */ + + int base_res[3]; /* initial "non-adapted" resolution */ + int res_min[3]; /* cell min */ + int res_max[3]; /* cell max */ + int res[3]; /* data resolution (res_max-res_min) */ + int total_cells; + float dx; /* 1.0f / res */ + float scale; /* largest domain size */ + + /* user settings */ + int adapt_margin; + int adapt_res; + float adapt_threshold; + float alpha; float beta; - float scale; /* largest domain size */ - int res[3]; /* domain resolution */ int amplify; /* wavelet amplification */ int maxres; /* longest axis on the BB gets this resolution assigned */ int flags; /* show up-res or low res, etc */ @@ -92,7 +119,6 @@ typedef struct SmokeDomainSettings { float strength; int res_wt[3]; float dx_wt; - int v3dnum; int cache_comp; int cache_high_comp; @@ -103,31 +129,67 @@ typedef struct SmokeDomainSettings { int border_collisions; /* How domain border collisions are handled */ float time_scale; float vorticity; - int pad2; + int active_fields; + float active_color[3]; /* monitor color situation of simulation */ + int pad; + + /* flame parameters */ + float burning_rate, flame_smoke, flame_vorticity; + float flame_ignition, flame_max_temp; + float flame_smoke_color[3]; } SmokeDomainSettings; /* inflow / outflow */ /* type */ -#define MOD_SMOKE_FLOW_TYPE_OUTFLOW (1<<1) +#define MOD_SMOKE_FLOW_TYPE_SMOKE 0 +#define MOD_SMOKE_FLOW_TYPE_FIRE 1 +#define MOD_SMOKE_FLOW_TYPE_OUTFLOW 2 +#define MOD_SMOKE_FLOW_TYPE_SMOKEFIRE 3 + +/* flow source */ +#define MOD_SMOKE_FLOW_SOURCE_PARTICLES 0 +#define MOD_SMOKE_FLOW_SOURCE_MESH 1 + +/* flow texture type */ +#define MOD_SMOKE_FLOW_TEXTURE_MAP_AUTO 0 +#define MOD_SMOKE_FLOW_TEXTURE_MAP_UV 1 /* flags */ #define MOD_SMOKE_FLOW_ABSOLUTE (1<<1) /*old style emission*/ #define MOD_SMOKE_FLOW_INITVELOCITY (1<<2) /* passes particles speed to the smoke */ +#define MOD_SMOKE_FLOW_TEXTUREEMIT (1<<3) /* use texture to control emission speed */ typedef struct SmokeFlowSettings { struct SmokeModifierData *smd; /* for fast RNA access */ + struct DerivedMesh *dm; struct ParticleSystem *psys; + struct Tex *noise_texture; + + /* initial velocity */ + float *verts_old; /* previous vertex positions in domain space */ + int numverts; + float vel_multi; // Multiplier for inherited velocity + float vel_normal; + float vel_random; + /* emission */ float density; + float color[3]; + float fuel_amount; float temp; /* delta temperature (temp - ambient temp) */ - float velocity[2]; /* UNUSED, velocity taken from particles */ - float vel_multi; // Multiplier for particle velocity - float vgrp_heat_scale[2]; /* min and max scaling for vgroup_heat */ - short vgroup_flow; /* where inflow/outflow happens - red=1=action */ + float volume_density; /* density emitted within mesh volume */ + float surface_distance; /* maximum emission distance from mesh surface */ + /* texture control */ + float texture_size; + float texture_offset; + int pad; + char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ short vgroup_density; - short vgroup_heat; - short type; /* inflow =0 or outflow = 1 */ + + short type; /* smoke, flames, both, outflow */ + short source; + short texture_type; int flags; /* absolute emission etc*/ } SmokeFlowSettings; @@ -139,20 +201,11 @@ typedef struct SmokeFlowSettings { /* collision objects (filled with smoke) */ typedef struct SmokeCollSettings { struct SmokeModifierData *smd; /* for fast RNA access */ - struct BVHTree *bvhtree; /* bounding volume hierarchy for this cloth object */ - float *points; - float *points_old; - float *vel; // UNUSED - int *tridivs; - float mat[4][4]; - float mat_old[4][4]; - int numpoints; - int numverts; // check if mesh changed - int numtris; - float dx; /* global domain cell length taken from (scale / resolution) */ + struct DerivedMesh *dm; + float *verts_old; + int numverts; short type; // static = 0, rigid = 1, dynamic = 2 short pad; - int pad2; } SmokeCollSettings; #endif diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 6cc4541f19e..be6464778e5 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -264,8 +264,8 @@ typedef enum eSpaceOutliner_Mode { SO_SAME_TYPE = 5, SO_GROUPS = 6, SO_LIBRARIES = 7, - SO_VERSE_SESSION = 8, - SO_VERSE_MS = 9, + /* SO_VERSE_SESSION = 8, */ /* deprecated! */ + /* SO_VERSE_MS = 9, */ /* deprecated!*/ SO_SEQUENCE = 10, SO_DATABLOCKS = 11, SO_USERDEF = 12, @@ -376,7 +376,7 @@ typedef struct SpaceNla { /* nla->flag */ typedef enum eSpaceNla_Flag { - /* flags (1<<0), (1<<1), and (1<<3) are depreceated flags from old verisons */ + /* flags (1<<0), (1<<1), and (1<<3) are deprecated flags from old verisons */ /* draw timing in seconds instead of frames */ SNLA_DRAWTIME = (1 << 2), @@ -618,7 +618,7 @@ enum FileSortTypeE { #define FILE_MAXFILE 256 #define FILE_MAX 1024 -#define FILE_MAX_LIBEXTRA (FILE_MAX + 32) +#define FILE_MAX_LIBEXTRA (FILE_MAX + MAX_ID_NAME) /* filesel types */ #define FILE_UNIX 8 @@ -792,10 +792,10 @@ typedef struct SpaceText { float blockscale DNA_DEPRECATED; short blockhandler[8] DNA_DEPRECATED; - struct Text *text; + struct Text *text; int top, viewlines; - short flags, menunr; + short flags, menunr; short lheight; /* user preference */ char cwidth, linenrs_tot; /* runtime computed, character width and the number of chars to use when showing line numbers */ diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h index 9fdd9216549..dd63e6aad59 100644 --- a/source/blender/makesdna/DNA_texture_types.h +++ b/source/blender/makesdna/DNA_texture_types.h @@ -161,7 +161,7 @@ typedef struct PointDensity { float speed_scale, falloff_speed_scale, pdpad2; struct ColorBand *coba; /* for time -> color */ - struct CurveMapping *falloff_curve; /* falloff density curve */ + struct CurveMapping *falloff_curve; /* falloff density curve */ } PointDensity; typedef struct VoxelData { @@ -171,9 +171,12 @@ typedef struct VoxelData { short flag; short extend; short smoked_type; + short data_type; + short pad; + int _pad; struct Object *object; /* for rendering smoke sims */ - float int_multiplier; + float int_multiplier; int still_frame; char source_path[1024]; /* 1024 = FILE_MAX */ @@ -470,6 +473,7 @@ typedef struct ColorMapping { #define MTEX_BUMP_TEXTURESPACE 2048 /* #define MTEX_BUMP_FLIPPED 4096 */ /* UNUSED */ #define MTEX_BICUBIC_BUMP 8192 +#define MTEX_MAPTO_BOUNDS 16384 /* blendtype */ #define MTEX_BLEND 0 @@ -577,6 +581,11 @@ typedef struct ColorMapping { #define TEX_VD_SMOKEDENSITY 0 #define TEX_VD_SMOKEHEAT 1 #define TEX_VD_SMOKEVEL 2 +#define TEX_VD_SMOKEFLAME 3 + +/* data_type */ +#define TEX_VD_INTENSITY 0 +#define TEX_VD_RGBA_PREMUL 1 /******************** Ocean *****************************/ /* output */ diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 1ab64ed1cc1..9c80d30bca4 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -162,7 +162,13 @@ typedef struct MovieTrackingSettings { short speed; /* speed of tracking */ /* ** reconstruction settings ** */ - int keyframe1, keyframe2; /* two keyframes for reconstrution initialization */ + int keyframe1 DNA_DEPRECATED, + keyframe2 DNA_DEPRECATED; /* two keyframes for reconstrution initialization + * were moved to per-tracking object settings + */ + + float reconstruction_success_threshold; + int reconstruction_flag; /* which camera intrinsics to refine. uses on the REFINE_* flags */ short refine_camera_intrinsics, pad2; @@ -220,6 +226,9 @@ typedef struct MovieTrackingObject { ListBase tracks; /* list of tracks use to tracking this object */ MovieTrackingReconstruction reconstruction; /* reconstruction data for this object */ + + /* reconstruction options */ + int keyframe1, keyframe2; /* two keyframes for reconstrution initialization */ } MovieTrackingObject; typedef struct MovieTrackingStats { @@ -275,92 +284,129 @@ enum { }; /* MovieTrackingMarker->flag */ -#define MARKER_DISABLED (1 << 0) -#define MARKER_TRACKED (1 << 1) -#define MARKER_GRAPH_SEL_X (1 << 2) -#define MARKER_GRAPH_SEL_Y (1 << 3) -#define MARKER_GRAPH_SEL (MARKER_GRAPH_SEL_X | MARKER_GRAPH_SEL_Y) +enum { + MARKER_DISABLED = (1 << 0), + MARKER_TRACKED = (1 << 1), + MARKER_GRAPH_SEL_X = (1 << 2), + MARKER_GRAPH_SEL_Y = (1 << 3), + MARKER_GRAPH_SEL = (MARKER_GRAPH_SEL_X | MARKER_GRAPH_SEL_Y) +}; /* MovieTrackingTrack->flag */ -#define TRACK_HAS_BUNDLE (1 << 1) -#define TRACK_DISABLE_RED (1 << 2) -#define TRACK_DISABLE_GREEN (1 << 3) -#define TRACK_DISABLE_BLUE (1 << 4) -#define TRACK_HIDDEN (1 << 5) -#define TRACK_LOCKED (1 << 6) -#define TRACK_CUSTOMCOLOR (1 << 7) -#define TRACK_USE_2D_STAB (1 << 8) -#define TRACK_PREVIEW_GRAYSCALE (1 << 9) -#define TRACK_DOPE_SEL (1 << 10) -#define TRACK_PREVIEW_ALPHA (1 << 11) +enum { + TRACK_HAS_BUNDLE = (1 << 1), + TRACK_DISABLE_RED = (1 << 2), + TRACK_DISABLE_GREEN = (1 << 3), + TRACK_DISABLE_BLUE = (1 << 4), + TRACK_HIDDEN = (1 << 5), + TRACK_LOCKED = (1 << 6), + TRACK_CUSTOMCOLOR = (1 << 7), + TRACK_USE_2D_STAB = (1 << 8), + TRACK_PREVIEW_GRAYSCALE = (1 << 9), + TRACK_DOPE_SEL = (1 << 10), + TRACK_PREVIEW_ALPHA = (1 << 11) +}; /* MovieTrackingTrack->motion_model */ -#define TRACK_MOTION_MODEL_TRANSLATION 0 -#define TRACK_MOTION_MODEL_TRANSLATION_ROTATION 1 -#define TRACK_MOTION_MODEL_TRANSLATION_SCALE 2 -#define TRACK_MOTION_MODEL_TRANSLATION_ROTATION_SCALE 3 -#define TRACK_MOTION_MODEL_AFFINE 4 -#define TRACK_MOTION_MODEL_HOMOGRAPHY 5 +enum { + TRACK_MOTION_MODEL_TRANSLATION = 0, + TRACK_MOTION_MODEL_TRANSLATION_ROTATION = 1, + TRACK_MOTION_MODEL_TRANSLATION_SCALE = 2, + TRACK_MOTION_MODEL_TRANSLATION_ROTATION_SCALE = 3, + TRACK_MOTION_MODEL_AFFINE = 4, + TRACK_MOTION_MODEL_HOMOGRAPHY = 5 +}; /* MovieTrackingTrack->algorithm_flag */ -#define TRACK_ALGORITHM_FLAG_USE_BRUTE (1 << 0) -#define TRACK_ALGORITHM_FLAG_USE_NORMALIZATION (1 << 2) -#define TRACK_ALGORITHM_FLAG_USE_MASK (1 << 3) +enum { + TRACK_ALGORITHM_FLAG_USE_BRUTE = (1 << 0), + TRACK_ALGORITHM_FLAG_USE_NORMALIZATION = (1 << 2), + TRACK_ALGORITHM_FLAG_USE_MASK = (1 << 3) +}; /* MovieTrackingTrack->adjframes */ -#define TRACK_MATCH_KEYFRAME 0 -#define TRACK_MATCH_PREVFRAME 1 +enum { + TRACK_MATCH_KEYFRAME = 0, + TRACK_MATCH_PREVFRAME = 1 +}; /* MovieTrackingSettings->flag */ -#define TRACKING_SETTINGS_SHOW_DEFAULT_EXPANDED (1 << 0) +enum { + TRACKING_SETTINGS_SHOW_DEFAULT_EXPANDED = (1 << 0) +}; /* MovieTrackingSettings->motion_flag */ -#define TRACKING_MOTION_TRIPOD (1 << 0) +enum { + TRACKING_MOTION_TRIPOD = (1 << 0), -#define TRACKING_MOTION_MODAL (TRACKING_MOTION_TRIPOD) + TRACKING_MOTION_MODAL = (TRACKING_MOTION_TRIPOD) +}; /* MovieTrackingSettings->speed */ -#define TRACKING_SPEED_FASTEST 0 -#define TRACKING_SPEED_REALTIME 1 -#define TRACKING_SPEED_HALF 2 -#define TRACKING_SPEED_QUARTER 4 -#define TRACKING_SPEED_DOUBLE 5 +enum { + TRACKING_SPEED_FASTEST = 0, + TRACKING_SPEED_REALTIME = 1, + TRACKING_SPEED_HALF = 2, + TRACKING_SPEED_QUARTER = 4, + TRACKING_SPEED_DOUBLE = 5 +}; + +/* MovieTrackingObject->reconstruction_flag */ +enum { + TRACKING_USE_FALLBACK_RECONSTRUCTION = (1 << 0) +}; /* MovieTrackingSettings->refine_camera_intrinsics */ -#define REFINE_FOCAL_LENGTH (1 << 0) -#define REFINE_PRINCIPAL_POINT (1 << 1) -#define REFINE_RADIAL_DISTORTION_K1 (1 << 2) -#define REFINE_RADIAL_DISTORTION_K2 (1 << 4) +enum { + REFINE_FOCAL_LENGTH = (1 << 0), + REFINE_PRINCIPAL_POINT = (1 << 1), + REFINE_RADIAL_DISTORTION_K1 = (1 << 2), + REFINE_RADIAL_DISTORTION_K2 = (1 << 4) +}; /* MovieTrackingStrabilization->flag */ -#define TRACKING_2D_STABILIZATION (1 << 0) -#define TRACKING_AUTOSCALE (1 << 1) -#define TRACKING_STABILIZE_ROTATION (1 << 2) +enum { + TRACKING_2D_STABILIZATION = (1 << 0), + TRACKING_AUTOSCALE = (1 << 1), + TRACKING_STABILIZE_ROTATION = (1 << 2) +}; /* MovieTrackingStrabilization->filter */ -#define TRACKING_FILTER_NEAREAST 0 -#define TRACKING_FILTER_BILINEAR 1 -#define TRACKING_FILTER_BICUBIC 2 +enum { + TRACKING_FILTER_NEAREAST = 0, + TRACKING_FILTER_BILINEAR = 1, + TRACKING_FILTER_BICUBIC = 2 +}; /* MovieTrackingReconstruction->flag */ -#define TRACKING_RECONSTRUCTED (1 << 0) +enum { + TRACKING_RECONSTRUCTED = (1 << 0) +}; /* MovieTrackingObject->flag */ -#define TRACKING_OBJECT_CAMERA (1 << 0) +enum { + TRACKING_OBJECT_CAMERA = (1 << 0) +}; -#define TRACKING_CLEAN_SELECT 0 -#define TRACKING_CLEAN_DELETE_TRACK 1 -#define TRACKING_CLEAN_DELETE_SEGMENT 2 +enum { + TRACKING_CLEAN_SELECT = 0, + TRACKING_CLEAN_DELETE_TRACK = 1, + TRACKING_CLEAN_DELETE_SEGMENT = 2 +}; /* MovieTrackingDopesheet->sort_method */ -#define TRACKING_DOPE_SORT_NAME 0 -#define TRACKING_DOPE_SORT_LONGEST 1 -#define TRACKING_DOPE_SORT_TOTAL 2 -#define TRACKING_DOPE_SORT_AVERAGE_ERROR 3 +enum { + TRACKING_DOPE_SORT_NAME = 0, + TRACKING_DOPE_SORT_LONGEST = 1, + TRACKING_DOPE_SORT_TOTAL = 2, + TRACKING_DOPE_SORT_AVERAGE_ERROR = 3 +}; /* MovieTrackingDopesheet->flag */ -#define TRACKING_DOPE_SORT_INVERSE (1 << 0) -#define TRACKING_DOPE_SELECTED_ONLY (1 << 1) -#define TRACKING_DOPE_SHOW_HIDDEN (1 << 2) +enum { + TRACKING_DOPE_SORT_INVERSE = (1 << 0), + TRACKING_DOPE_SELECTED_ONLY = (1 << 1), + TRACKING_DOPE_SHOW_HIDDEN = (1 << 2) +}; #endif diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 218027209a8..2256968da56 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -49,11 +49,14 @@ struct ColorBand; #define MAX_STYLE_NAME 64 /* default uifont_id offered by Blender */ -#define UIFONT_DEFAULT 0 -/*#define UIFONT_BITMAP 1*/ /*UNUSED*/ -/* free slots */ -#define UIFONT_CUSTOM1 2 -#define UIFONT_CUSTOM2 3 +typedef enum eUIFont_ID { + UIFONT_DEFAULT = 0, +/* UIFONT_BITMAP = 1 */ /* UNUSED */ + + /* free slots */ + UIFONT_CUSTOM1 = 2, + UIFONT_CUSTOM2 = 3 +} eUIFont_ID; /* default fonts to load/initalize */ /* first font is the default (index 0), others optional */ @@ -64,7 +67,6 @@ typedef struct uiFont { short uifont_id; /* own id */ short r_to_l; /* fonts that read from left to right */ short pad; - } uiFont; /* this state defines appearance of text */ @@ -79,13 +81,14 @@ typedef struct uiFontStyle { short align; /* text align hint */ float shadowalpha; /* total alpha */ float shadowcolor; /* 1 value, typically white or black anyway */ - } uiFontStyle; /* uiFontStyle->align */ -#define UI_STYLE_TEXT_LEFT 0 -#define UI_STYLE_TEXT_CENTER 1 -#define UI_STYLE_TEXT_RIGHT 2 +typedef enum eFontStyle_Align { + UI_STYLE_TEXT_LEFT = 0, + UI_STYLE_TEXT_CENTER = 1, + UI_STYLE_TEXT_RIGHT = 2 +} eFontStyle_Align; /* this is fed to the layout engine and widget code */ @@ -145,7 +148,6 @@ typedef struct uiPanelColors { } uiPanelColors; typedef struct ThemeUI { - /* Interface Elements (buttons, menus, icons) */ uiWidgetColors wcol_regular, wcol_tool, wcol_text; uiWidgetColors wcol_radio, wcol_option, wcol_toggle; @@ -182,7 +184,7 @@ typedef struct ThemeSpace { /* button/tool regions */ char button[4]; char button_title[4]; - char button_text[4]; + char button_text[4]; char button_text_hi[4]; /* listview regions */ @@ -193,8 +195,8 @@ typedef struct ThemeSpace { /* float panel */ char panel[4]; - char panel_title[4]; - char panel_text[4]; + char panel_title[4]; + char panel_text[4]; char panel_text_hi[4]; char shade1[4]; @@ -209,8 +211,8 @@ typedef struct ThemeSpace { char vertex[4], vertex_select[4]; char edge[4], edge_select[4]; char edge_seam[4], edge_sharp[4], edge_facesel[4], edge_crease[4]; - char face[4], face_select[4]; // solid faces - char face_dot[4]; // selected color + char face[4], face_select[4]; /* solid faces */ + char face_dot[4]; /* selected color */ char extra_edge_len[4], extra_face_angle[4], extra_face_area[4], pad3[4]; char normal[4]; char vertex_normal[4]; @@ -224,7 +226,7 @@ typedef struct ThemeSpace { char handle_free[4], handle_auto[4], handle_vect[4], handle_align[4], handle_auto_clamped[4]; char handle_sel_free[4], handle_sel_auto[4], handle_sel_vect[4], handle_sel_align[4], handle_sel_auto_clamped[4]; - char ds_channel[4], ds_subchannel[4]; // dopesheet + char ds_channel[4], ds_subchannel[4]; /* dopesheet */ char console_output[4], console_input[4], console_info[4], console_error[4]; char console_cursor[4]; @@ -232,10 +234,10 @@ typedef struct ThemeSpace { char vertex_size, outline_width, facedot_size; char noodle_curving; - char syntaxl[4], syntaxn[4], syntaxb[4]; // syntax for textwindow and nodes + char syntaxl[4], syntaxn[4], syntaxb[4]; /* syntax for textwindow and nodes */ char syntaxv[4], syntaxc[4]; - char movie[4], movieclip[4], mask[4], image[4], scene[4], audio[4]; // for sequence editor + char movie[4], movieclip[4], mask[4], image[4], scene[4], audio[4]; /* for sequence editor */ char effect[4], hpad0[4], transition[4], meta[4]; char editmesh_active[4]; @@ -287,8 +289,10 @@ typedef struct ThemeWireColor { } ThemeWireColor; /* flags for ThemeWireColor */ -#define TH_WIRECOLOR_CONSTCOLS (1<<0) -#define TH_WIRECOLOR_TEXTCOLS (1<<1) +typedef enum eWireColor_Flags { + TH_WIRECOLOR_CONSTCOLS = (1 << 0), + TH_WIRECOLOR_TEXTCOLS = (1 << 1), +} eWireColor_Flags; /* A theme */ typedef struct bTheme { @@ -298,7 +302,7 @@ typedef struct bTheme { ThemeUI tui; /* Individual Spacetypes */ - ThemeSpace tbuts; + ThemeSpace tbuts; ThemeSpace tv3d; ThemeSpace tfile; ThemeSpace tipo; @@ -312,7 +316,7 @@ typedef struct bTheme { ThemeSpace ttime; ThemeSpace tnode; ThemeSpace tlogic; - ThemeSpace tuserpref; + ThemeSpace tuserpref; ThemeSpace tconsole; ThemeSpace tclip; @@ -321,7 +325,6 @@ typedef struct bTheme { /*ThemeWireColor tobj[20];*/ int active_theme_area, pad; - } bTheme; /* for the moment only the name. may want to store options with this later */ @@ -345,8 +348,8 @@ typedef struct UserDef { char pythondir[768]; char sounddir[768]; char i18ndir[768]; - char image_editor[1024]; /* 1024 = FILE_MAX */ - char anim_player[1024]; /* 1024 = FILE_MAX */ + char image_editor[1024]; /* 1024 = FILE_MAX */ + char anim_player[1024]; /* 1024 = FILE_MAX */ int anim_player_preset; short v2d_min_gridsize; /* minimum spacing between gridlines in View2D grids */ @@ -393,7 +396,7 @@ typedef struct UserDef { int memcachelimit; int prefetchframes; short frameserverport; - short pad_rot_angle; /*control the rotation step of the view when PAD2, PAD4, PAD6&PAD8 is use*/ + short pad_rot_angle; /* control the rotation step of the view when PAD2, PAD4, PAD6&PAD8 is use */ short obcenter_dia; short rvisize; /* rotating view icon size */ short rvibright; /* rotating view icon brightness */ @@ -422,7 +425,7 @@ typedef struct UserDef { short autokey_mode; /* autokeying mode */ short autokey_flag; /* flags for autokeying */ - short text_render, pad9; /*options for text rendering*/ + short text_render, pad9; /* options for text rendering */ struct ColorBand coba_weight; /* from texture.h */ @@ -445,217 +448,259 @@ extern UserDef U; /* from blenkernel blender.c */ /* ***************** USERDEF ****************** */ /* userpref/section */ -#define USER_SECTION_INTERFACE 0 -#define USER_SECTION_EDIT 1 -#define USER_SECTION_FILE 2 -#define USER_SECTION_SYSTEM 3 -#define USER_SECTION_THEME 4 -#define USER_SECTION_INPUT 5 -#define USER_SECTION_ADDONS 6 +typedef enum eUserPref_Section { + USER_SECTION_INTERFACE = 0, + USER_SECTION_EDIT = 1, + USER_SECTION_FILE = 2, + USER_SECTION_SYSTEM = 3, + USER_SECTION_THEME = 4, + USER_SECTION_INPUT = 5, + USER_SECTION_ADDONS = 6, +} eUserPref_Section; /* flag */ -#define USER_AUTOSAVE (1 << 0) -/*#define USER_AUTOGRABGRID (1 << 1) deprecated */ -/*#define USER_AUTOROTGRID (1 << 2) deprecated */ -/*#define USER_AUTOSIZEGRID (1 << 3) deprecated */ -#define USER_SCENEGLOBAL (1 << 4) -#define USER_TRACKBALL (1 << 5) -/*#define USER_DUPLILINK (1 << 6) deprecated */ -/*#define USER_FSCOLLUM (1 << 7) deprecated */ -#define USER_MAT_ON_OB (1 << 8) -/*#define USER_NO_CAPSLOCK (1 << 9)*/ /* not used anywhere */ -/*#define USER_VIEWMOVE (1 << 10)*/ /* not used anywhere */ -#define USER_TOOLTIPS (1 << 11) -#define USER_TWOBUTTONMOUSE (1 << 12) -#define USER_NONUMPAD (1 << 13) -#define USER_LMOUSESELECT (1 << 14) -#define USER_FILECOMPRESS (1 << 15) -#define USER_SAVE_PREVIEWS (1 << 16) -#define USER_CUSTOM_RANGE (1 << 17) -#define USER_ADD_EDITMODE (1 << 18) -#define USER_ADD_VIEWALIGNED (1 << 19) -#define USER_RELPATHS (1 << 20) -#define USER_RELEASECONFIRM (1 << 21) -#define USER_SCRIPT_AUTOEXEC_DISABLE (1 << 22) -#define USER_FILENOUI (1 << 23) -#define USER_NONEGFRAMES (1 << 24) -#define USER_TXT_TABSTOSPACES_DISABLE (1 << 25) -#define USER_TOOLTIPS_PYTHON (1 << 26) - +typedef enum eUserPref_Flag { + USER_AUTOSAVE = (1 << 0), +/* USER_AUTOGRABGRID = (1 << 1), deprecated */ +/* USER_AUTOROTGRID = (1 << 2), deprecated */ +/* USER_AUTOSIZEGRID = (1 << 3), deprecated */ + USER_SCENEGLOBAL = (1 << 4), + USER_TRACKBALL = (1 << 5), +/* USER_DUPLILINK = (1 << 6), deprecated */ +/* USER_FSCOLLUM = (1 << 7), deprecated */ + USER_MAT_ON_OB = (1 << 8), +/* USER_NO_CAPSLOCK = (1 << 9), */ /* not used anywhere */ +/* USER_VIEWMOVE = (1 << 10), */ /* not used anywhere */ + USER_TOOLTIPS = (1 << 11), + USER_TWOBUTTONMOUSE = (1 << 12), + USER_NONUMPAD = (1 << 13), + USER_LMOUSESELECT = (1 << 14), + USER_FILECOMPRESS = (1 << 15), + USER_SAVE_PREVIEWS = (1 << 16), + USER_CUSTOM_RANGE = (1 << 17), + USER_ADD_EDITMODE = (1 << 18), + USER_ADD_VIEWALIGNED = (1 << 19), + USER_RELPATHS = (1 << 20), + USER_RELEASECONFIRM = (1 << 21), + USER_SCRIPT_AUTOEXEC_DISABLE = (1 << 22), + USER_FILENOUI = (1 << 23), + USER_NONEGFRAMES = (1 << 24), + USER_TXT_TABSTOSPACES_DISABLE = (1 << 25), + USER_TOOLTIPS_PYTHON = (1 << 26), +} eUserPref_Flag; + /* helper macro for checking frame clamping */ #define FRAMENUMBER_MIN_CLAMP(cfra) { \ if ((U.flag & USER_NONEGFRAMES) && (cfra < 0)) \ cfra = 0; \ } (void)0 -/* viewzom */ -#define USER_ZOOM_CONT 0 -#define USER_ZOOM_SCALE 1 -#define USER_ZOOM_DOLLY 2 +/* viewzoom */ +typedef enum eViewZoom_Style { + USER_ZOOM_CONT = 0, + USER_ZOOM_SCALE = 1, + USER_ZOOM_DOLLY = 2 +} eViewZoom_Style; /* uiflag */ -// old flag for #define USER_KEYINSERTACT (1 << 0) -// old flag for #define USER_KEYINSERTOBJ (1 << 1) -#define USER_WHEELZOOMDIR (1 << 2) -#define USER_FILTERFILEEXTS (1 << 3) -#define USER_DRAWVIEWINFO (1 << 4) -#define USER_PLAINMENUS (1 << 5) // old EVTTOCONSOLE print ghost events, here for tuhopuu compat. --phase - // old flag for hide pulldown was here -/*#define USER_FLIPFULLSCREEN (1 << 7)*/ /* deprecated */ -#define USER_ALLWINCODECS (1 << 8) -#define USER_MENUOPENAUTO (1 << 9) -#define USER_ZBUF_CURSOR (1 << 10) -#define USER_AUTOPERSP (1 << 11) -#define USER_LOCKAROUND (1 << 12) -#define USER_GLOBALUNDO (1 << 13) -#define USER_ORBIT_SELECTION (1 << 14) -#define USER_ZBUF_ORBIT (1 << 15) -#define USER_HIDE_DOT (1 << 16) -#define USER_SHOW_ROTVIEWICON (1 << 17) -#define USER_SHOW_VIEWPORTNAME (1 << 18) -#define USER_CAM_LOCK_NO_PARENT (1 << 19) -#define USER_ZOOM_TO_MOUSEPOS (1 << 20) -#define USER_SHOW_FPS (1 << 21) -#define USER_MMB_PASTE (1 << 22) -#define USER_MENUFIXEDORDER (1 << 23) -#define USER_CONTINUOUS_MOUSE (1 << 24) -#define USER_ZOOM_INVERT (1 << 25) -#define USER_ZOOM_HORIZ (1 << 26) /* for CONTINUE and DOLLY zoom */ -#define USER_SPLASH_DISABLE (1 << 27) -#define USER_HIDE_RECENT (1 << 28) -#define USER_SHOW_THUMBNAILS (1 << 29) -#define USER_QUIT_PROMPT (1 << 30) +typedef enum eUserpref_UI_Flag { + /* flags 0 and 1 were old flags (for autokeying) that aren't used anymore */ + USER_WHEELZOOMDIR = (1 << 2), + USER_FILTERFILEEXTS = (1 << 3), + USER_DRAWVIEWINFO = (1 << 4), + USER_PLAINMENUS = (1 << 5), + /* flags 6 and 7 were old flags that are no-longer used */ + USER_ALLWINCODECS = (1 << 8), + USER_MENUOPENAUTO = (1 << 9), + USER_ZBUF_CURSOR = (1 << 10), + USER_AUTOPERSP = (1 << 11), + USER_LOCKAROUND = (1 << 12), + USER_GLOBALUNDO = (1 << 13), + USER_ORBIT_SELECTION = (1 << 14), + USER_ZBUF_ORBIT = (1 << 15), + USER_HIDE_DOT = (1 << 16), + USER_SHOW_ROTVIEWICON = (1 << 17), + USER_SHOW_VIEWPORTNAME = (1 << 18), + USER_CAM_LOCK_NO_PARENT = (1 << 19), + USER_ZOOM_TO_MOUSEPOS = (1 << 20), + USER_SHOW_FPS = (1 << 21), + USER_MMB_PASTE = (1 << 22), + USER_MENUFIXEDORDER = (1 << 23), + USER_CONTINUOUS_MOUSE = (1 << 24), + USER_ZOOM_INVERT = (1 << 25), + USER_ZOOM_HORIZ = (1 << 26), /* for CONTINUE and DOLLY zoom */ + USER_SPLASH_DISABLE = (1 << 27), + USER_HIDE_RECENT = (1 << 28), + USER_SHOW_THUMBNAILS = (1 << 29), + USER_QUIT_PROMPT = (1 << 30), + USER_HIDE_SYSTEM_BOOKMARKS = (1 << 31) +} eUserpref_UI_Flag; /* Auto-Keying mode */ +typedef enum eAutokey_Mode { /* AUTOKEY_ON is a bitflag */ -#define AUTOKEY_ON 1 + AUTOKEY_ON = 1, + /* AUTOKEY_ON + 2**n... (i.e. AUTOKEY_MODE_NORMAL = AUTOKEY_ON + 2) to preserve setting, even when autokey turned off */ -#define AUTOKEY_MODE_NORMAL 3 -#define AUTOKEY_MODE_EDITKEYS 5 + AUTOKEY_MODE_NORMAL = 3, + AUTOKEY_MODE_EDITKEYS = 5 +} eAutokey_Mode; /* Auto-Keying flag * U.autokey_flag (not strictly used when autokeying only - is also used when keyframing these days) * note: AUTOKEY_FLAG_* is used with a macro, search for lines like IS_AUTOKEY_FLAG(INSERTAVAIL) */ -#define AUTOKEY_FLAG_INSERTAVAIL (1<<0) -#define AUTOKEY_FLAG_INSERTNEEDED (1<<1) -#define AUTOKEY_FLAG_AUTOMATKEY (1<<2) -#define AUTOKEY_FLAG_XYZ2RGB (1<<3) - -/* toolsettings->autokey_flag */ -#define AUTOKEY_FLAG_ONLYKEYINGSET (1<<6) -#define ANIMRECORD_FLAG_WITHNLA (1<<10) +typedef enum eAutokey_Flag { + AUTOKEY_FLAG_INSERTAVAIL = (1 << 0), + AUTOKEY_FLAG_INSERTNEEDED = (1 << 1), + AUTOKEY_FLAG_AUTOMATKEY = (1 << 2), + AUTOKEY_FLAG_XYZ2RGB = (1 << 3), + + /* toolsettings->autokey_flag */ + AUTOKEY_FLAG_ONLYKEYINGSET = (1 << 6), + AUTOKEY_FLAG_NOWARNING = (1 << 7), + ANIMRECORD_FLAG_WITHNLA = (1 << 10), +} eAutokey_Flag; /* transopts */ -#define USER_TR_TOOLTIPS (1 << 0) -#define USER_TR_IFACE (1 << 1) -/*#define USER_TR_MENUS (1 << 2) deprecated*/ -/*#define USER_TR_FILESELECT (1 << 3) deprecated*/ -/*#define USER_TR_TEXTEDIT (1 << 4) deprecated*/ -#define USER_DOTRANSLATE (1 << 5) -#define USER_USETEXTUREFONT (1 << 6) -/*#define CONVERT_TO_UTF8 (1 << 7) deprecated*/ +typedef enum eUserpref_Translation_Flags { + USER_TR_TOOLTIPS = (1 << 0), + USER_TR_IFACE = (1 << 1), +/* USER_TR_MENUS = (1 << 2) deprecated */ +/* USER_TR_FILESELECT = (1 << 3) deprecated */ +/* USER_TR_TEXTEDIT = (1 << 4) deprecated */ + USER_DOTRANSLATE = (1 << 5), + USER_USETEXTUREFONT = (1 << 6), +/* CONVERT_TO_UTF8 = (1 << 7) deprecated */ +} eUserpref_Translation_Flags; /* dupflag */ -#define USER_DUP_MESH (1 << 0) -#define USER_DUP_CURVE (1 << 1) -#define USER_DUP_SURF (1 << 2) -#define USER_DUP_FONT (1 << 3) -#define USER_DUP_MBALL (1 << 4) -#define USER_DUP_LAMP (1 << 5) -#define USER_DUP_IPO (1 << 6) -#define USER_DUP_MAT (1 << 7) -#define USER_DUP_TEX (1 << 8) -#define USER_DUP_ARM (1 << 9) -#define USER_DUP_ACT (1 << 10) -#define USER_DUP_PSYS (1 << 11) +typedef enum eDupli_ID_Flags { + USER_DUP_MESH = (1 << 0), + USER_DUP_CURVE = (1 << 1), + USER_DUP_SURF = (1 << 2), + USER_DUP_FONT = (1 << 3), + USER_DUP_MBALL = (1 << 4), + USER_DUP_LAMP = (1 << 5), + USER_DUP_IPO = (1 << 6), + USER_DUP_MAT = (1 << 7), + USER_DUP_TEX = (1 << 8), + USER_DUP_ARM = (1 << 9), + USER_DUP_ACT = (1 << 10), + USER_DUP_PSYS = (1 << 11) +} eDupli_ID_Flags; /* gameflags */ -// #define USER_DEPRECATED_FLAG 1 -// #define USER_DISABLE_SOUND 2 deprecated, don't use without checking for -// backwards compatibilty in do_versions! -#define USER_DISABLE_MIPMAP 4 -#define USER_DISABLE_VBO 8 -#define USER_DISABLE_AA 16 +typedef enum eOpenGL_RenderingOptions { + /* USER_DEPRECATED_FLAG = (1 << 0), */ + /* USER_DISABLE_SOUND = (1 << 1), */ /* deprecated, don't use without checking for */ + /* backwards compatibilty in do_versions! */ + USER_DISABLE_MIPMAP = (1 << 2), + USER_DISABLE_VBO = (1 << 3), + USER_DISABLE_AA = (1 << 4), +} eOpenGL_RenderingOptions; /* wm draw method */ -#define USER_DRAW_TRIPLE 0 -#define USER_DRAW_OVERLAP 1 -#define USER_DRAW_FULL 2 -#define USER_DRAW_AUTOMATIC 3 -#define USER_DRAW_OVERLAP_FLIP 4 +typedef enum eWM_DrawMethod { + USER_DRAW_TRIPLE = 0, + USER_DRAW_OVERLAP = 1, + USER_DRAW_FULL = 2, + USER_DRAW_AUTOMATIC = 3, + USER_DRAW_OVERLAP_FLIP = 4, +} eWM_DrawMethod; -/* text draw options*/ -#define USER_TEXT_DISABLE_AA (1 << 0) +/* text draw options */ +typedef enum eText_Draw_Options { + USER_TEXT_DISABLE_AA = (1 << 0), +} eText_Draw_Options; /* tw_flag (transform widget) */ /* gp_settings (Grease Pencil Settings) */ -#define GP_PAINT_DOSMOOTH (1<<0) -#define GP_PAINT_DOSIMPLIFY (1<<1) +typedef enum eGP_UserdefSettings { + GP_PAINT_DOSMOOTH = (1 << 0), + GP_PAINT_DOSIMPLIFY = (1 << 1), +} eGP_UserdefSettings; /* color picker types */ -#define USER_CP_CIRCLE 0 -#define USER_CP_SQUARE_SV 1 -#define USER_CP_SQUARE_HS 2 -#define USER_CP_SQUARE_HV 3 +typedef enum eColorPicker_Types { + USER_CP_CIRCLE = 0, + USER_CP_SQUARE_SV = 1, + USER_CP_SQUARE_HS = 2, + USER_CP_SQUARE_HV = 3, +} eColorPicker_Types; /* timecode display styles */ +typedef enum eTimecodeStyles { /* as little info as is necessary to show relevant info * with '+' to denote the frames * i.e. HH:MM:SS+FF, MM:SS+FF, SS+FF, or MM:SS */ -#define USER_TIMECODE_MINIMAL 0 + USER_TIMECODE_MINIMAL = 0, + /* reduced SMPTE - (HH:)MM:SS:FF */ -#define USER_TIMECODE_SMPTE_MSF 1 + USER_TIMECODE_SMPTE_MSF = 1, + /* full SMPTE - HH:MM:SS:FF */ -#define USER_TIMECODE_SMPTE_FULL 2 + USER_TIMECODE_SMPTE_FULL = 2, + /* milliseconds for sub-frames - HH:MM:SS.sss */ -#define USER_TIMECODE_MILLISECONDS 3 + USER_TIMECODE_MILLISECONDS = 3, + /* seconds only */ -#define USER_TIMECODE_SECONDS_ONLY 4 + USER_TIMECODE_SECONDS_ONLY = 4, +} eTimecodeStyles; /* theme drawtypes */ -#define TH_MINIMAL 0 -#define TH_ROUNDSHADED 1 -#define TH_ROUNDED 2 -#define TH_OLDSKOOL 3 -#define TH_SHADED 4 +/* XXX: These are probably only for the old UI engine? */ +typedef enum eTheme_DrawTypes { + TH_MINIMAL = 0, + TH_ROUNDSHADED = 1, + TH_ROUNDED = 2, + TH_OLDSKOOL = 3, + TH_SHADED = 4 +} eTheme_DrawTypes; /* ndof_flag (3D mouse options) */ -#define NDOF_SHOW_GUIDE (1 << 0) -#define NDOF_FLY_HELICOPTER (1 << 1) -#define NDOF_LOCK_HORIZON (1 << 2) -/* the following might not need to be saved between sessions, - * but they do need to live somewhere accessible... */ -#define NDOF_SHOULD_PAN (1 << 3) -#define NDOF_SHOULD_ZOOM (1 << 4) -#define NDOF_SHOULD_ROTATE (1 << 5) -/* orbit navigation modes - * only two options, so it's sort of a hybrid bool/enum - * if ((U.ndof_flag & NDOF_ORBIT_MODE) == NDOF_OM_OBJECT)... */ +typedef enum eNdof_Flag { + NDOF_SHOW_GUIDE = (1 << 0), + NDOF_FLY_HELICOPTER = (1 << 1), + NDOF_LOCK_HORIZON = (1 << 2), -// #define NDOF_ORBIT_MODE (1 << 6) -// #define NDOF_OM_TARGETCAMERA 0 -// #define NDOF_OM_OBJECT NDOF_ORBIT_MODE + /* the following might not need to be saved between sessions, + * but they do need to live somewhere accessible... */ + NDOF_SHOULD_PAN = (1 << 3), + NDOF_SHOULD_ZOOM = (1 << 4), + NDOF_SHOULD_ROTATE = (1 << 5), -/* actually... users probably don't care about what the mode - * is called, just that it feels right */ -/* zoom is up/down if this flag is set (otherwise forward/backward) */ -#define NDOF_ZOOM_UPDOWN (1 << 7) -#define NDOF_ZOOM_INVERT (1 << 8) -#define NDOF_ROTATE_INVERT_AXIS (1 << 9) -#define NDOF_TILT_INVERT_AXIS (1 << 10) -#define NDOF_ROLL_INVERT_AXIS (1 << 11) -#define NDOF_PANX_INVERT_AXIS (1 << 12) -#define NDOF_PANY_INVERT_AXIS (1 << 13) -#define NDOF_PANZ_INVERT_AXIS (1 << 14) -#define NDOF_TURNTABLE (1 << 15) + /* orbit navigation modes + * only two options, so it's sort of a hybrid bool/enum + * if ((U.ndof_flag & NDOF_ORBIT_MODE) == NDOF_OM_OBJECT)... */ + + // NDOF_ORBIT_MODE = (1 << 6), + // #define NDOF_OM_TARGETCAMERA 0 + // #define NDOF_OM_OBJECT NDOF_ORBIT_MODE + + /* actually... users probably don't care about what the mode + * is called, just that it feels right */ + /* zoom is up/down if this flag is set (otherwise forward/backward) */ + NDOF_ZOOM_UPDOWN = (1 << 7), + NDOF_ZOOM_INVERT = (1 << 8), + NDOF_ROTATE_INVERT_AXIS = (1 << 9), + NDOF_TILT_INVERT_AXIS = (1 << 10), + NDOF_ROLL_INVERT_AXIS = (1 << 11), + NDOF_PANX_INVERT_AXIS = (1 << 12), + NDOF_PANY_INVERT_AXIS = (1 << 13), + NDOF_PANZ_INVERT_AXIS = (1 << 14), + NDOF_TURNTABLE = (1 << 15), +} eNdof_Flag; /* compute_device_type */ -#define USER_COMPUTE_DEVICE_NONE 0 -#define USER_COMPUTE_DEVICE_OPENCL 1 -#define USER_COMPUTE_DEVICE_CUDA 2 +typedef enum eCompute_Device_Type { + USER_COMPUTE_DEVICE_NONE = 0, + USER_COMPUTE_DEVICE_OPENCL = 1, + USER_COMPUTE_DEVICE_CUDA = 2, +} eCompute_Device_Type; #ifdef __cplusplus } diff --git a/source/blender/makesdna/DNA_view2d_types.h b/source/blender/makesdna/DNA_view2d_types.h index a3f4b362672..084496871bf 100644 --- a/source/blender/makesdna/DNA_view2d_types.h +++ b/source/blender/makesdna/DNA_view2d_types.h @@ -128,7 +128,7 @@ typedef struct View2D { #define V2D_SCROLL_HORIZONTAL (V2D_SCROLL_TOP|V2D_SCROLL_BOTTOM|V2D_SCROLL_BOTTOM_O) /* scale markings - vertical */ #define V2D_SCROLL_SCALE_VERTICAL (1<<5) - /* scale markings - horizontal */ + /* scale markings - horizontal */ #define V2D_SCROLL_SCALE_HORIZONTAL (1<<6) /* induce hiding of scrollbars - set by region drawing in response to size of region */ #define V2D_SCROLL_VERTICAL_HIDE (1<<7) diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 9da10381af0..c83b0bc366f 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -169,6 +169,7 @@ typedef struct View3D { short view DNA_DEPRECATED; struct Object *camera, *ob_centre; + rctf render_border; struct ListBase bgpicbase; struct BGpic *bgpic DNA_DEPRECATED; /* deprecated, use bgpicbase, only kept for do_versions(...) */ @@ -267,6 +268,7 @@ typedef struct View3D { #define V3D_SHOW_CAMERAPATH 256 #define V3D_SHOW_BUNDLENAME 512 #define V3D_BACKFACE_CULLING 1024 +#define V3D_RENDER_BORDER 2048 /* View3D->around */ #define V3D_CENTER 0 diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 780ca0b5878..2294abc0735 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -334,7 +334,7 @@ typedef struct wmOperator { #define OPERATOR_FLAGS_ALL ((1<<5)-1) /* sanity checks for debug mode only */ -#define OPERATOR_RETVAL_CHECK(ret) BLI_assert(ret != 0 && (ret & OPERATOR_FLAGS_ALL) == ret) +#define OPERATOR_RETVAL_CHECK(ret) (void)ret, BLI_assert(ret != 0 && (ret & OPERATOR_FLAGS_ALL) == ret) /* wmOperator flag */ #define OP_GRAB_POINTER 1 diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h index b3c10406d4c..8a14564f8a4 100644 --- a/source/blender/makesdna/DNA_world_types.h +++ b/source/blender/makesdna/DNA_world_types.h @@ -61,14 +61,14 @@ typedef struct World { float ambr, ambg, ambb; float pad2; - unsigned int fastcol; + unsigned int fastcol; /** * Exposure= mult factor. unused now, but maybe back later. Kept in to be upward compat. * New is exp/range control. linfac & logfac are constants... don't belong in * file, but allocating 8 bytes for temp mem isn't useful either. */ - float exposure, exp, range; + float exposure, exp, range; float linfac, logfac; /** @@ -129,7 +129,7 @@ typedef struct World { struct PreviewImage *preview; /* nodes */ - struct bNodeTree *nodetree; + struct bNodeTree *nodetree; } World; diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c index f5cf7e3ea3b..10c3b0bbee4 100644 --- a/source/blender/makesdna/intern/dna_genfile.c +++ b/source/blender/makesdna/intern/dna_genfile.c @@ -62,7 +62,7 @@ typedef long long __int64; * - if you want a struct not to be in DNA file: add two hash marks above it (##) * * Structure DNA data is added to each blender file and to each executable, this to detect - * in .blend files new veriables in structs, changed array sizes, etc. It's also used for + * in .blend files new variables in structs, changed array sizes, etc. It's also used for * converting endian and pointer size (32-64 bits) * As an extra, Python uses a call to detect run-time the contents of a blender struct. * @@ -506,7 +506,7 @@ static void init_structDNA(SDNA *sdna, int do_endian_swap) } } -SDNA *DNA_sdna_from_data(void *data, int datalen, int do_endian_swap) +SDNA *DNA_sdna_from_data(const void *data, const int datalen, int do_endian_swap) { SDNA *sdna = MEM_mallocN(sizeof(*sdna), "sdna"); diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index fec3aa22e92..bef5e5cc161 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -87,14 +87,14 @@ static const char *includefiles[] = { "DNA_mesh_types.h", "DNA_meshdata_types.h", "DNA_modifier_types.h", - "DNA_lattice_types.h", + "DNA_lattice_types.h", "DNA_object_types.h", "DNA_object_force.h", "DNA_object_fluidsim.h", "DNA_world_types.h", "DNA_scene_types.h", "DNA_view3d_types.h", - "DNA_view2d_types.h", + "DNA_view2d_types.h", "DNA_space_types.h", "DNA_userdef_types.h", "DNA_screen_types.h", @@ -485,11 +485,15 @@ static int preprocess_include(char *maindata, int len) } /* do not copy when: */ - if (comment) ; - else if (cp[0] == ' ' && cp[1] == ' ') ; - else if (cp[-1] == '*' && cp[0] == ' ') ; /* pointers with a space */ - - /* skip special keywords */ + if (comment) { + /* pass */ + } + else if (cp[0] == ' ' && cp[1] == ' ') { + /* pass */ + } + else if (cp[-1] == '*' && cp[0] == ' ') { + /* pointers with a space */ + } /* skip special keywords */ else if (strncmp("DNA_DEPRECATED", cp, 14) == 0) { /* single values are skipped already, so decrement 1 less */ a -= 13; @@ -1028,7 +1032,9 @@ static int make_structDNA(char *baseDirectory, FILE *file) if (debugSDNA > -1) printf("Writing file ... "); - if (nr_names == 0 || nr_structs == 0) ; + if (nr_names == 0 || nr_structs == 0) { + /* pass */ + } else { strcpy(str, "SDNA"); dna_write(file, str, 4); @@ -1088,7 +1094,9 @@ static int make_structDNA(char *baseDirectory, FILE *file) int a; fp = fopen("padding.c", "w"); - if (fp == NULL) ; + if (fp == NULL) { + /* pass */ + } else { /* add all include files defined in the global array */ @@ -1166,7 +1174,7 @@ int main(int argc, char **argv) strcpy(baseDirectory, BASE_HEADER); } - fprintf(file, "unsigned char DNAstr[]= {\n"); + fprintf(file, "const unsigned char DNAstr[] = {\n"); if (make_structDNA(baseDirectory, file)) { /* error */ fclose(file); @@ -1175,7 +1183,7 @@ int main(int argc, char **argv) } else { fprintf(file, "};\n"); - fprintf(file, "int DNAlen = sizeof(DNAstr);\n"); + fprintf(file, "const int DNAlen = sizeof(DNAstr);\n"); fclose(file); } @@ -1186,7 +1194,19 @@ int main(int argc, char **argv) return(return_status); } +/* handy but fails on struct bounds which makesdna doesnt care about + * with quite the same strictness as GCC does */ +#if 0 /* include files for automatic dependencies */ + +/* extra safety check that we are aligned, + * warnings here are easier to fix the makesdna's */ +#ifdef __GNUC__ +# pragma GCC diagnostic error "-Wpadded" +#endif + +#endif /* if 0 */ + #include "DNA_listBase.h" #include "DNA_vec_types.h" #include "DNA_ID.h" diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 8e387dd4eba..5f667db4425 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -286,6 +286,7 @@ extern StructRNA RNA_KinematicConstraint; extern StructRNA RNA_Lamp; extern StructRNA RNA_LampSkySettings; extern StructRNA RNA_LampTextureSlot; +extern StructRNA RNA_LaplacianSmoothModifier; extern StructRNA RNA_Lattice; extern StructRNA RNA_LatticeModifier; extern StructRNA RNA_LatticePoint; @@ -456,6 +457,7 @@ extern StructRNA RNA_ShaderNodeMath; extern StructRNA RNA_ShaderNodeMixRGB; extern StructRNA RNA_ShaderNodeNormal; extern StructRNA RNA_ShaderNodeOutput; +extern StructRNA RNA_ShaderNodeScript; extern StructRNA RNA_ShaderNodeRGB; extern StructRNA RNA_ShaderNodeRGBCurve; extern StructRNA RNA_ShaderNodeRGBToBW; @@ -960,7 +962,9 @@ void RNA_collection_clear(PointerRNA *ptr, const char *name); } /* check if the idproperty exists, for operators */ +int RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, int use_ghost); int RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop); +int RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, int use_ghost); int RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier); int RNA_property_is_idprop(PropertyRNA *prop); @@ -1029,6 +1033,13 @@ short RNA_type_to_ID_code(StructRNA *type); StructRNA *ID_code_to_RNA_type(short idcode); +#define RNA_POINTER_INVALIDATE(ptr) { \ + /* this is checked for validity */ \ + (ptr)->type = \ + /* should not be needed but prevent bad pointer access, just in case */ \ + (ptr)->id.data = NULL; \ +} (void)0 + /* macro which inserts the function name */ #if defined __GNUC__ || defined __sun # define RNA_warning(format, args ...) _RNA_warning("%s: " format "\n", __func__, ##args) diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index b651d4d5e5c..0f9a00de7b6 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -38,6 +38,7 @@ extern EnumPropertyItem DummyRNA_NULL_items[]; extern EnumPropertyItem DummyRNA_DEFAULT_items[]; extern EnumPropertyItem object_mode_items[]; +extern EnumPropertyItem object_empty_drawtype_items[]; extern EnumPropertyItem metaelem_type_items[]; extern EnumPropertyItem proportional_falloff_items[]; diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index 511999dfa37..87504dc6eb7 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -113,6 +113,7 @@ typedef enum PropertySubType { PROP_BYTESTRING = 4, /* a string which should be represented as bytes * in python, still NULL terminated though. */ PROP_TRANSLATE = 5, /* a string which should be translated */ + PROP_PASSWORD = 6, /* a string which should not be displayed in UI */ /* numbers */ PROP_UNSIGNED = 13, @@ -312,6 +313,7 @@ typedef enum FunctionFlag { FUNC_USE_CONTEXT = 4, FUNC_USE_REPORTS = 8, FUNC_USE_SELF_ID = 2048, + FUNC_ALLOW_WRITE = 4096, /* registering */ FUNC_REGISTER = 16, diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index ef3c7f42e96..7c4ce3d18d7 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -61,7 +61,6 @@ /* Replace if different */ #define TMP_EXT ".tmp" - /* copied from BLI_file_older */ #include static int file_older(const char *file1, const char *file2) @@ -76,6 +75,22 @@ static int file_older(const char *file1, const char *file2) } static const char *makesrna_path = NULL; +/* forward declarations */ +static void rna_generate_static_parameter_prototypes(FILE *f, StructRNA *srna, FunctionDefRNA *dfunc, + const char *name_override, int close_prototype); + +/* helpers */ +#define WRITE_COMMA { \ + if (!first) \ + fprintf(f, ", "); \ + first = 0; \ + } (void)0 + +#define WRITE_PARAM(param) { \ + WRITE_COMMA; \ + fprintf(f, param); \ + } + static int replace_if_different(char *tmpfile, const char *dep_files[]) { /* return 0; *//* use for testing had edited rna */ @@ -212,6 +227,8 @@ static const char *rna_safe_id(const char *id) return "default_value"; else if (strcmp(id, "operator") == 0) return "operator_value"; + else if (strcmp(id, "new") == 0) + return "create"; return id; } @@ -322,13 +339,26 @@ static void rna_print_id_get(FILE *f, PropertyDefRNA *UNUSED(dp)) fprintf(f, " ID *id= ptr->id.data;\n"); } +static void rna_construct_function_name(char *buffer, int size, const char *structname, const char *propname, const char *type) +{ + snprintf(buffer, size, "%s_%s_%s", structname, propname, type); +} + +static void rna_construct_wrapper_function_name(char *buffer, int size, const char *structname, const char *propname, const char *type) +{ + if (type == NULL || type[0] == '\0') + snprintf(buffer, size, "%s_%s", structname, propname); + else + snprintf(buffer, size, "%s_%s_%s", structname, propname, type); +} + static char *rna_alloc_function_name(const char *structname, const char *propname, const char *type) { AllocDefRNA *alloc; char buffer[2048]; char *result; - snprintf(buffer, sizeof(buffer), "%s_%s_%s", structname, propname, type); + rna_construct_function_name(buffer, sizeof(buffer), structname, propname, type); result = MEM_callocN(sizeof(char) * strlen(buffer) + 1, "rna_alloc_function_name"); strcpy(result, buffer); @@ -627,17 +657,17 @@ static char *rna_def_property_get_func(FILE *f, StructRNA *srna, PropertyRNA *pr "get_length"); fprintf(f, " int i, arraylen[RNA_MAX_ARRAY_DIMENSION];\n"); fprintf(f, " int len= %s(ptr, arraylen);\n\n", lenfunc); - fprintf(f, " for (i=0; itotarraylength); + fprintf(f, " for (i=0; i < %u; i++) {\n", prop->totarraylength); } if (dp->dnaarraylength == 1) { if (prop->type == PROP_BOOLEAN && dp->booleanbit) { - fprintf(f, " values[i] = %s((data->%s & (%d<%s & (%d << i)) != 0);\n", (dp->booleannegative) ? "!" : "", dp->dnaname, dp->booleanbit); } else { @@ -653,7 +683,7 @@ static char *rna_def_property_get_func(FILE *f, StructRNA *srna, PropertyRNA *pr fprintf(f, ") != 0);\n"); } else if (rna_color_quantize(prop, dp)) { - fprintf(f, " values[i] = (%s)(data->%s[i]*(1.0f/255.0f));\n", + fprintf(f, " values[i] = (%s)(data->%s[i]*(1.0f / 255.0f));\n", rna_type_type(prop), dp->dnaname); } else if (dp->dnatype) { @@ -878,20 +908,20 @@ static char *rna_def_property_set_func(FILE *f, StructRNA *srna, PropertyRNA *pr fprintf(f, " int i, arraylen[RNA_MAX_ARRAY_DIMENSION];\n"); fprintf(f, " int len= %s(ptr, arraylen);\n\n", lenfunc); rna_clamp_value_range(f, prop); - fprintf(f, " for (i=0; itotarraylength); + fprintf(f, " for (i=0; i < %u; i++) {\n", prop->totarraylength); } if (dp->dnaarraylength == 1) { if (prop->type == PROP_BOOLEAN && dp->booleanbit) { fprintf(f, " if (%svalues[i]) data->%s |= (%d<booleannegative) ? "!" : "", dp->dnaname, dp->booleanbit); - fprintf(f, " else data->%s &= ~(%d<dnaname, dp->booleanbit); + fprintf(f, " else data->%s &= ~(%d << i);\n", dp->dnaname, dp->booleanbit); } else { fprintf(f, " (&data->%s)[i] = %s", dp->dnaname, (dp->booleannegative) ? "!" : ""); @@ -1015,9 +1045,9 @@ static char *rna_def_property_length_func(FILE *f, StructRNA *srna, PropertyRNA else { rna_print_data_get(f, dp); if (dp->dnalengthname) - fprintf(f, " return (data->%s == NULL)? 0: data->%s;\n", dp->dnaname, dp->dnalengthname); + fprintf(f, " return (data->%s == NULL) ? 0 : data->%s;\n", dp->dnaname, dp->dnalengthname); else - fprintf(f, " return (data->%s == NULL)? 0: %d;\n", dp->dnaname, dp->dnalengthfixed); + fprintf(f, " return (data->%s == NULL) ? 0 : %d;\n", dp->dnaname, dp->dnalengthfixed); } fprintf(f, "}\n\n"); } @@ -1091,7 +1121,7 @@ static char *rna_def_property_lookup_int_func(FILE *f, StructRNA *srna, Property const char *manualfunc, const char *nextfunc) { /* note on indices, this is for external functions and ignores skipped values. - * so the the index can only be checked against the length when there is no 'skip' funcion. */ + * so the the index can only be checked against the length when there is no 'skip' function. */ char *func; if (prop->flag & PROP_IDPROPERTY && manualfunc == NULL) @@ -1102,8 +1132,8 @@ static char *rna_def_property_lookup_int_func(FILE *f, StructRNA *srna, Property return NULL; /* only supported in case of standard next functions */ - if (strcmp(nextfunc, "rna_iterator_array_next") == 0) ; - else if (strcmp(nextfunc, "rna_iterator_listbase_next") == 0) ; + if (strcmp(nextfunc, "rna_iterator_array_next") == 0) {} + else if (strcmp(nextfunc, "rna_iterator_listbase_next") == 0) {} else return NULL; } @@ -1372,9 +1402,12 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; const char *nextfunc = (const char *)cprop->next; - if (dp->dnatype && strcmp(dp->dnatype, "ListBase") == 0) ; - else if (dp->dnalengthname || dp->dnalengthfixed) + if (dp->dnatype && strcmp(dp->dnatype, "ListBase") == 0) { + /* pass */ + } + else if (dp->dnalengthname || dp->dnalengthfixed) { cprop->length = (void *)rna_def_property_length_func(f, srna, prop, dp, (const char *)cprop->length); + } /* test if we can allow raw array access, if it is using our standard * array get/next function, we can be sure it is an actual array */ @@ -1437,15 +1470,15 @@ static void rna_def_property_funcs_header(FILE *f, StructRNA *srna, PropertyDefR { if (!prop->arraydimension) { fprintf(f, "int %sget(PointerRNA *ptr);\n", func); - /*fprintf(f, "void %sset(PointerRNA *ptr, int value);\n", func); */ + fprintf(f, "void %sset(PointerRNA *ptr, int value);\n", func); } else if (prop->arraydimension && prop->totarraylength) { fprintf(f, "void %sget(PointerRNA *ptr, int values[%u]);\n", func, prop->totarraylength); - /*fprintf(f, "void %sset(PointerRNA *ptr, const int values[%d]);\n", func, prop->arraylength); */ + fprintf(f, "void %sset(PointerRNA *ptr, const int values[%d]);\n", func, prop->totarraylength); } else { fprintf(f, "void %sget(PointerRNA *ptr, int values[]);\n", func); - /*fprintf(f, "void %sset(PointerRNA *ptr, const int values[]);\n", func); */ + fprintf(f, "void %sset(PointerRNA *ptr, const int values[]);\n", func); } break; } @@ -1453,15 +1486,15 @@ static void rna_def_property_funcs_header(FILE *f, StructRNA *srna, PropertyDefR { if (!prop->arraydimension) { fprintf(f, "float %sget(PointerRNA *ptr);\n", func); - /*fprintf(f, "void %sset(PointerRNA *ptr, float value);\n", func); */ + fprintf(f, "void %sset(PointerRNA *ptr, float value);\n", func); } else if (prop->arraydimension && prop->totarraylength) { fprintf(f, "void %sget(PointerRNA *ptr, float values[%u]);\n", func, prop->totarraylength); - /*fprintf(f, "void %sset(PointerRNA *ptr, const float values[%d]);\n", func, prop->arraylength); */ + fprintf(f, "void %sset(PointerRNA *ptr, const float values[%d]);\n", func, prop->totarraylength); } else { fprintf(f, "void %sget(PointerRNA *ptr, float values[]);\n", func); - /*fprintf(f, "void %sset(PointerRNA *ptr, const float values[]);\n", func); */ + fprintf(f, "void %sset(PointerRNA *ptr, const float values[]);", func); } break; } @@ -1482,7 +1515,7 @@ static void rna_def_property_funcs_header(FILE *f, StructRNA *srna, PropertyDefR } fprintf(f, "int %sget(PointerRNA *ptr);\n", func); - /*fprintf(f, "void %sset(PointerRNA *ptr, int value);\n", func); */ + fprintf(f, "void %sset(PointerRNA *ptr, int value);\n", func); break; } @@ -1496,7 +1529,7 @@ static void rna_def_property_funcs_header(FILE *f, StructRNA *srna, PropertyDefR fprintf(f, "void %sget(PointerRNA *ptr, char *value);\n", func); fprintf(f, "int %slength(PointerRNA *ptr);\n", func); - /*fprintf(f, "void %sset(PointerRNA *ptr, const char *value);\n", func); */ + fprintf(f, "void %sset(PointerRNA *ptr, const char *value);\n", func); break; } @@ -1508,19 +1541,38 @@ static void rna_def_property_funcs_header(FILE *f, StructRNA *srna, PropertyDefR } case PROP_COLLECTION: { + CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; fprintf(f, "void %sbegin(CollectionPropertyIterator *iter, PointerRNA *ptr);\n", func); fprintf(f, "void %snext(CollectionPropertyIterator *iter);\n", func); fprintf(f, "void %send(CollectionPropertyIterator *iter);\n", func); - /*fprintf(f, "int %slength(PointerRNA *ptr);\n", func); */ - /*fprintf(f, "void %slookup_int(PointerRNA *ptr, int key, StructRNA **type);\n", func); */ - /*fprintf(f, "void %slookup_string(PointerRNA *ptr, const char *key, StructRNA **type);\n", func); */ + if (cprop->length) + fprintf(f, "int %slength(PointerRNA *ptr);\n", func); + if (cprop->lookupint) + fprintf(f, "int %slookup_int(PointerRNA *ptr, int key, PointerRNA *r_ptr);\n", func); + if (cprop->lookupstring) + fprintf(f, "int %slookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr);\n", func); break; } } + if (prop->getlength) { + char funcname[2048]; + rna_construct_wrapper_function_name(funcname, sizeof(funcname), srna->identifier, prop->identifier, "get_length"); + fprintf(f, "int %s(PointerRNA *ptr, int *arraylen);\n", funcname); + } + fprintf(f, "\n"); } +static void rna_def_function_funcs_header(FILE *f, StructRNA *srna, FunctionDefRNA *dfunc) +{ + FunctionRNA *func = dfunc->func; + char funcname[2048]; + + rna_construct_wrapper_function_name(funcname, sizeof(funcname), srna->identifier, func->identifier, NULL); + rna_generate_static_parameter_prototypes(f, srna, dfunc, funcname, 1); +} + static void rna_def_property_funcs_header_cpp(FILE *f, StructRNA *srna, PropertyDefRNA *dp) { PropertyRNA *prop; @@ -1540,26 +1592,50 @@ static void rna_def_property_funcs_header_cpp(FILE *f, StructRNA *srna, Property switch (prop->type) { case PROP_BOOLEAN: { - if (!prop->arraydimension) - fprintf(f, "\tinline bool %s(void);", rna_safe_id(prop->identifier)); - else if (prop->totarraylength) - fprintf(f, "\tinline Array %s(void);", prop->totarraylength, rna_safe_id(prop->identifier)); + if (!prop->arraydimension) { + fprintf(f, "\tinline bool %s(void);\n", rna_safe_id(prop->identifier)); + fprintf(f, "\tinline void %s(int value);", rna_safe_id(prop->identifier)); + } + else if (prop->totarraylength) { + fprintf(f, "\tinline Array %s(void);\n", prop->totarraylength, rna_safe_id(prop->identifier)); + fprintf(f, "\tinline void %s(int values[%u]);", rna_safe_id(prop->identifier), prop->totarraylength); + } + else if (prop->getlength) { + fprintf(f, "\tinline DynamicArray %s(void);\n", rna_safe_id(prop->identifier)); + fprintf(f, "\tinline void %s(int values[]);", rna_safe_id(prop->identifier)); + } break; } case PROP_INT: { - if (!prop->arraydimension) - fprintf(f, "\tinline int %s(void);", rna_safe_id(prop->identifier)); - else if (prop->totarraylength) - fprintf(f, "\tinline Array %s(void);", prop->totarraylength, rna_safe_id(prop->identifier)); + if (!prop->arraydimension) { + fprintf(f, "\tinline int %s(void);\n", rna_safe_id(prop->identifier)); + fprintf(f, "\tinline void %s(int value);", rna_safe_id(prop->identifier)); + } + else if (prop->totarraylength) { + fprintf(f, "\tinline Array %s(void);\n", prop->totarraylength, rna_safe_id(prop->identifier)); + fprintf(f, "\tinline void %s(int values[%u]);", rna_safe_id(prop->identifier), prop->totarraylength); + } + else if (prop->getlength) { + fprintf(f, "\tinline DynamicArray %s(void);\n", rna_safe_id(prop->identifier)); + fprintf(f, "\tinline void %s(int values[]);", rna_safe_id(prop->identifier)); + } break; } case PROP_FLOAT: { - if (!prop->arraydimension) - fprintf(f, "\tinline float %s(void);", rna_safe_id(prop->identifier)); - else if (prop->totarraylength) - fprintf(f, "\tinline Array %s(void);", prop->totarraylength, rna_safe_id(prop->identifier)); + if (!prop->arraydimension) { + fprintf(f, "\tinline float %s(void);\n", rna_safe_id(prop->identifier)); + fprintf(f, "\tinline void %s(float value);", rna_safe_id(prop->identifier)); + } + else if (prop->totarraylength) { + fprintf(f, "\tinline Array %s(void);\n", prop->totarraylength, rna_safe_id(prop->identifier)); + fprintf(f, "\tinline void %s(float values[%u]);", rna_safe_id(prop->identifier), prop->totarraylength); + } + else if (prop->getlength) { + fprintf(f, "\tinline DynamicArray %s(void);\n", rna_safe_id(prop->identifier)); + fprintf(f, "\tinline void %s(float values[]);", rna_safe_id(prop->identifier)); + } break; } case PROP_ENUM: @@ -1578,12 +1654,14 @@ static void rna_def_property_funcs_header_cpp(FILE *f, StructRNA *srna, Property fprintf(f, "\t};\n"); } - fprintf(f, "\tinline %s_enum %s(void);", rna_safe_id(prop->identifier), rna_safe_id(prop->identifier)); + fprintf(f, "\tinline %s_enum %s(void);\n", rna_safe_id(prop->identifier), rna_safe_id(prop->identifier)); + fprintf(f, "\tinline void %s(%s_enum value);", rna_safe_id(prop->identifier), rna_safe_id(prop->identifier)); break; } case PROP_STRING: { fprintf(f, "\tinline std::string %s(void);", rna_safe_id(prop->identifier)); + fprintf(f, "\tinline void %s(const std::string& value);", rna_safe_id(prop->identifier)); break; } case PROP_POINTER: @@ -1599,13 +1677,19 @@ static void rna_def_property_funcs_header_cpp(FILE *f, StructRNA *srna, Property case PROP_COLLECTION: { CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)dp->prop; + const char *collection_funcs = "DefaultCollectionFunctions"; + + if (!(dp->prop->flag & (PROP_IDPROPERTY | PROP_BUILTIN)) && cprop->property.srna) + collection_funcs = (char*)cprop->property.srna; if (cprop->item_type) - fprintf(f, "\tCOLLECTION_PROPERTY(%s, %s, %s)", (const char *)cprop->item_type, srna->identifier, - rna_safe_id(prop->identifier)); + fprintf(f, "\tCOLLECTION_PROPERTY(%s, %s, %s, %s, %s, %s, %s)", collection_funcs, (const char *)cprop->item_type, srna->identifier, + rna_safe_id(prop->identifier), (cprop->length ? "TRUE" : "FALSE"), + (cprop->lookupint ? "TRUE" : "FALSE"), (cprop->lookupstring ? "TRUE" : "FALSE")); else - fprintf(f, "\tCOLLECTION_PROPERTY(%s, %s, %s)", "UnknownType", srna->identifier, - rna_safe_id(prop->identifier)); + fprintf(f, "\tCOLLECTION_PROPERTY(%s, %s, %s, %s, %s, %s, %s)", collection_funcs, "UnknownType", srna->identifier, + rna_safe_id(prop->identifier), (cprop->length ? "TRUE" : "FALSE"), + (cprop->lookupint ? "TRUE" : "FALSE"), (cprop->lookupstring ? "TRUE" : "FALSE")); break; } } @@ -1613,6 +1697,96 @@ static void rna_def_property_funcs_header_cpp(FILE *f, StructRNA *srna, Property fprintf(f, "\n"); } +static const char *rna_parameter_type_cpp_name(PropertyRNA *prop) +{ + if (prop->type == PROP_POINTER) { + /* for cpp api we need to use RNA structures names for pointers */ + PointerPropertyRNA *pprop = (PointerPropertyRNA *) prop; + + return (const char *) pprop->type; + } + else { + return rna_parameter_type_name(prop); + } +} + +static void rna_def_struct_function_prototype_cpp(FILE *f, StructRNA *srna, FunctionDefRNA *dfunc, + const char *namespace, int close_prototype) +{ + PropertyDefRNA *dp; + FunctionRNA *func = dfunc->func; + + int first = 1; + const char *retval_type = "void"; + + if (func->c_ret) { + dp = rna_find_parameter_def(func->c_ret); + retval_type = rna_parameter_type_cpp_name(dp->prop); + } + + if (namespace && namespace[0]) + fprintf(f, "\tinline %s %s::%s(", retval_type, namespace, rna_safe_id(func->identifier)); + else + fprintf(f, "\tinline %s %s(", retval_type, rna_safe_id(func->identifier)); + + if (func->flag & FUNC_USE_MAIN) + WRITE_PARAM("void *main"); + + if (func->flag & FUNC_USE_CONTEXT) + WRITE_PARAM("Context C"); + + for (dp = dfunc->cont.properties.first; dp; dp = dp->next) { + int type, flag, pout; + const char *ptrstr; + + if (dp->prop == func->c_ret) + continue; + + type = dp->prop->type; + flag = dp->prop->flag; + pout = (flag & PROP_OUTPUT); + + if (type == PROP_POINTER) + ptrstr = ""; + else if ((type == PROP_POINTER) && (flag & PROP_RNAPTR) && !(flag & PROP_THICK_WRAP)) + ptrstr = "*"; + else if (type == PROP_POINTER || dp->prop->arraydimension) + ptrstr = "*"; + else if (type == PROP_STRING && (flag & PROP_THICK_WRAP)) + ptrstr = ""; + else + ptrstr = pout ? "*" : ""; + + WRITE_COMMA; + + if (flag & PROP_DYNAMIC) + fprintf(f, "int %s%s_len, ", (flag & PROP_OUTPUT) ? "*" : "", dp->prop->identifier); + + if (!(flag & PROP_DYNAMIC) && dp->prop->arraydimension) + fprintf(f, "%s %s[%u]", rna_parameter_type_cpp_name(dp->prop), + rna_safe_id(dp->prop->identifier), dp->prop->totarraylength); + else + fprintf(f, "%s %s%s", rna_parameter_type_cpp_name(dp->prop), + ptrstr, rna_safe_id(dp->prop->identifier)); + } + + fprintf(f, ")"); + if (close_prototype) + fprintf(f, ";\n"); +} + +static void rna_def_struct_function_header_cpp(FILE *f, StructRNA *srna, FunctionDefRNA *dfunc) +{ + FunctionRNA *func = dfunc->func; + + if (!dfunc->call) + return; + + fprintf(f, "\n\t/* %s */\n", func->description); + + rna_def_struct_function_prototype_cpp(f, srna, dfunc, NULL, 1); +} + static void rna_def_property_funcs_impl_cpp(FILE *f, StructRNA *srna, PropertyDefRNA *dp) { PropertyRNA *prop; @@ -1630,6 +1804,9 @@ static void rna_def_property_funcs_impl_cpp(FILE *f, StructRNA *srna, PropertyDe else if (prop->totarraylength) fprintf(f, "\tBOOLEAN_ARRAY_PROPERTY(%s, %u, %s)", srna->identifier, prop->totarraylength, rna_safe_id(prop->identifier)); + else if (prop->getlength) + fprintf(f, "\tBOOLEAN_DYNAMIC_ARRAY_PROPERTY(%s, %s)", srna->identifier, + rna_safe_id(prop->identifier)); break; } case PROP_INT: @@ -1639,6 +1816,9 @@ static void rna_def_property_funcs_impl_cpp(FILE *f, StructRNA *srna, PropertyDe else if (prop->totarraylength) fprintf(f, "\tINT_ARRAY_PROPERTY(%s, %u, %s)", srna->identifier, prop->totarraylength, rna_safe_id(prop->identifier)); + else if (prop->getlength) + fprintf(f, "\tINT_DYNAMIC_ARRAY_PROPERTY(%s, %s)", srna->identifier, + rna_safe_id(prop->identifier)); break; } case PROP_FLOAT: @@ -1648,6 +1828,9 @@ static void rna_def_property_funcs_impl_cpp(FILE *f, StructRNA *srna, PropertyDe else if (prop->totarraylength) fprintf(f, "\tFLOAT_ARRAY_PROPERTY(%s, %u, %s)", srna->identifier, prop->totarraylength, rna_safe_id(prop->identifier)); + else if (prop->getlength) + fprintf(f, "\tFLOAT_DYNAMIC_ARRAY_PROPERTY(%s, %s)", srna->identifier, + rna_safe_id(prop->identifier)); break; } case PROP_ENUM: @@ -1680,10 +1863,13 @@ static void rna_def_property_funcs_impl_cpp(FILE *f, StructRNA *srna, PropertyDe CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)dp->prop; if (cprop->type) - fprintf(f, "\tCOLLECTION_PROPERTY(%s, %s, %s)", (const char *)cprop->type, srna->identifier, - prop->identifier); + fprintf(f, "\tCOLLECTION_PROPERTY(%s, %s, %s, %s, %s, %s)", (const char *)cprop->type, srna->identifier, + prop->identifier, (cprop->length ? "TRUE" : "FALSE"), + (cprop->lookupint ? "TRUE" : "FALSE"), (cprop->lookupstring ? "TRUE" : "FALSE")); else - fprintf(f, "\tCOLLECTION_PROPERTY(%s, %s, %s)", "UnknownType", srna->identifier, prop->identifier); + fprintf(f, "\tCOLLECTION_PROPERTY(%s, %s, %s, %s, %s, %s)", "UnknownType", srna->identifier, + prop->identifier, (cprop->length ? "TRUE" : "FALSE"), + (cprop->lookupint ? "TRUE" : "FALSE"), (cprop->lookupstring ? "TRUE" : "FALSE")); #endif break; } @@ -1692,6 +1878,181 @@ static void rna_def_property_funcs_impl_cpp(FILE *f, StructRNA *srna, PropertyDe fprintf(f, "\n"); } +static void rna_def_struct_function_call_impl_cpp(FILE *f, StructRNA *srna, FunctionDefRNA *dfunc) +{ + PropertyDefRNA *dp; + StructDefRNA *dsrna; + FunctionRNA *func = dfunc->func; + char funcname[2048]; + + int first = 1; + + rna_construct_wrapper_function_name(funcname, sizeof(funcname), srna->identifier, func->identifier, NULL); + + fprintf(f, "%s(", funcname); + + dsrna = rna_find_struct_def(srna); + + if (func->flag & FUNC_USE_SELF_ID) + WRITE_PARAM("(::ID *) ptr.id.data"); + + if ((func->flag & FUNC_NO_SELF) == 0) { + WRITE_COMMA; + if (dsrna->dnaname) fprintf(f, "(::%s *) this->ptr.data", dsrna->dnaname); + else fprintf(f, "(::%s *) this->ptr.data", srna->identifier); + } + + if (func->flag & FUNC_USE_MAIN) + WRITE_PARAM("(::Main *) main"); + + if (func->flag & FUNC_USE_CONTEXT) + WRITE_PARAM("(::bContext *) C.ptr.data"); + + if (func->flag & FUNC_USE_REPORTS) + WRITE_PARAM("NULL"); + + dp = dfunc->cont.properties.first; + for (; dp; dp = dp->next) { + if (dp->prop == func->c_ret) + continue; + + WRITE_COMMA; + + if (dp->prop->flag & PROP_DYNAMIC) + fprintf(f, "%s_len, ", dp->prop->identifier); + + if (dp->prop->type == PROP_POINTER) + if ((dp->prop->flag & PROP_RNAPTR) && !(dp->prop->flag & PROP_THICK_WRAP)) + fprintf(f, "(::%s *) &%s.ptr", rna_parameter_type_name(dp->prop), rna_safe_id(dp->prop->identifier)); + else + fprintf(f, "(::%s *) %s.ptr.data", rna_parameter_type_name(dp->prop), rna_safe_id(dp->prop->identifier)); + else + fprintf(f, "%s", rna_safe_id(dp->prop->identifier)); + } + + fprintf(f, ");\n"); +} + +static void rna_def_struct_function_impl_cpp(FILE *f, StructRNA *srna, FunctionDefRNA *dfunc) +{ + PropertyDefRNA *dp; + PointerPropertyRNA *pprop; + + FunctionRNA *func = dfunc->func; + + if (!dfunc->call) + return; + + rna_def_struct_function_prototype_cpp(f, srna, dfunc, srna->identifier, 0); + + fprintf(f, " {\n"); + + if (func->c_ret) { + dp = rna_find_parameter_def(func->c_ret); + + if (dp->prop->type == PROP_POINTER) { + pprop = (PointerPropertyRNA *) dp->prop; + + fprintf(f, "\t\tPointerRNA result;\n"); + + if ((dp->prop->flag & PROP_RNAPTR) == 0) { + StructRNA *ret_srna = rna_find_struct((const char *) pprop->type); + fprintf(f, "\t\t::%s *retdata = ", rna_parameter_type_name(dp->prop)); + rna_def_struct_function_call_impl_cpp(f, srna, dfunc); + if (ret_srna->flag & STRUCT_ID) + fprintf(f, "\t\tRNA_id_pointer_create((::ID *) retdata, &result);\n"); + else + fprintf(f, "\t\tRNA_pointer_create((::ID *) ptr.id.data, &RNA_%s, retdata, &result);\n", (const char *) pprop->type); + } + else { + fprintf(f, "\t\tresult = "); + rna_def_struct_function_call_impl_cpp(f, srna, dfunc); + } + + fprintf(f, "\t\treturn %s(result);\n", (const char *) pprop->type); + } + else { + fprintf(f, "\t\treturn "); + rna_def_struct_function_call_impl_cpp(f, srna, dfunc); + } + } + else { + fprintf(f, "\t\t"); + rna_def_struct_function_call_impl_cpp(f, srna, dfunc); + } + + fprintf(f, "\t}\n\n"); +} + +static void rna_def_property_wrapper_funcs(FILE *f, StructDefRNA *dsrna, PropertyDefRNA *dp) +{ + if (dp->prop->getlength) { + char funcname[2048]; + rna_construct_wrapper_function_name(funcname, sizeof(funcname), dsrna->srna->identifier, dp->prop->identifier, "get_length"); + fprintf(f, "int %s(PointerRNA *ptr, int *arraylen)\n", funcname); + fprintf(f, "{\n"); + fprintf(f, "\treturn %s(ptr, arraylen);\n", rna_function_string(dp->prop->getlength)); + fprintf(f, "}\n\n"); + } +} + +static void rna_def_function_wrapper_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA *dfunc) +{ + StructRNA *srna = dsrna->srna; + FunctionRNA *func = dfunc->func; + PropertyDefRNA *dparm; + + int first; + char funcname[2048]; + + if (!dfunc->call) + return; + + rna_construct_wrapper_function_name(funcname, sizeof(funcname), srna->identifier, func->identifier, NULL); + + rna_generate_static_parameter_prototypes(f, srna, dfunc, funcname, 0); + + fprintf(f, "\n{\n"); + + if (func->c_ret) + fprintf(f, "\treturn %s(", dfunc->call); + else + fprintf(f, "\t%s(", dfunc->call); + + first = 1; + + if (func->flag & FUNC_USE_SELF_ID) + WRITE_PARAM("_selfid"); + + if ((func->flag & FUNC_NO_SELF) == 0) + WRITE_PARAM("_self"); + + if (func->flag & FUNC_USE_MAIN) + WRITE_PARAM("bmain"); + + if (func->flag & FUNC_USE_CONTEXT) + WRITE_PARAM("C"); + + if (func->flag & FUNC_USE_REPORTS) + WRITE_PARAM("reports"); + + dparm = dfunc->cont.properties.first; + for (; dparm; dparm = dparm->next) { + if (dparm->prop == func->c_ret) + continue; + + WRITE_COMMA; + + if (dparm->prop->flag & PROP_DYNAMIC) + fprintf(f, "%s_len, %s", dparm->prop->identifier, dparm->prop->identifier); + else + fprintf(f, "%s", rna_safe_id(dparm->prop->identifier)); + } + + fprintf(f, ");\n"); + fprintf(f, "}\n\n"); +} + static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA *dfunc) { StructRNA *srna; @@ -1741,6 +2102,8 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA /* fixed size arrays and RNA pointers are pre-allocated on the ParameterList stack, pass a pointer to it */ else if (type == PROP_POINTER || dparm->prop->arraydimension) ptrstr = "*"; + else if ((type == PROP_POINTER) && (flag & PROP_RNAPTR) && !(flag & PROP_THICK_WRAP)) + ptrstr = "*"; /* PROP_THICK_WRAP strings are pre-allocated on the ParameterList stack, * but type name for string props is already char*, so leave empty */ else if (type == PROP_STRING && (flag & PROP_THICK_WRAP)) @@ -1792,6 +2155,10 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA ptrstr = "**"; valstr = "*"; } + else if ((type == PROP_POINTER) && !(flag & PROP_THICK_WRAP)) { + ptrstr = "**"; + valstr = "*"; + } else if (type == PROP_POINTER || dparm->prop->arraydimension) { ptrstr = "*"; valstr = ""; @@ -1991,6 +2358,7 @@ static const char *rna_property_subtypename(PropertySubType type) case PROP_COORDS: return "PROP_COORDS"; case PROP_LAYER: return "PROP_LAYER"; case PROP_LAYER_MEMBER: return "PROP_LAYER_MEMBER"; + case PROP_PASSWORD: return "PROP_PASSWORD"; default: { /* in case we don't have a type preset that includes the subtype */ if (RNA_SUBTYPE_UNIT(type)) { @@ -2107,7 +2475,7 @@ static void rna_generate_function_prototypes(BlenderRNA *brna, StructRNA *srna, fprintf(f, "\n"); } -static void rna_generate_static_parameter_prototypes(BlenderRNA *UNUSED(brna), StructRNA *srna, FunctionDefRNA *dfunc, FILE *f) +static void rna_generate_static_parameter_prototypes(FILE *f, StructRNA *srna, FunctionDefRNA *dfunc, const char *name_override, int close_prototype) { FunctionRNA *func; PropertyDefRNA *dparm; @@ -2138,7 +2506,10 @@ static void rna_generate_static_parameter_prototypes(BlenderRNA *UNUSED(brna), S fprintf(f, "void "); /* function name */ - fprintf(f, "%s(", dfunc->call); + if (name_override == NULL || name_override[0] == '\0') + fprintf(f, "%s(", dfunc->call); + else + fprintf(f, "%s(", name_override); first = 1; @@ -2147,7 +2518,7 @@ static void rna_generate_static_parameter_prototypes(BlenderRNA *UNUSED(brna), S fprintf(f, "struct ID *_selfid"); first = 0; } - + if ((func->flag & FUNC_NO_SELF) == 0) { if (!first) fprintf(f, ", "); if (dsrna->dnaname) fprintf(f, "struct %s *_self", dsrna->dnaname); @@ -2200,17 +2571,19 @@ static void rna_generate_static_parameter_prototypes(BlenderRNA *UNUSED(brna), S if (!(flag & PROP_DYNAMIC) && dparm->prop->arraydimension) fprintf(f, "%s%s %s[%u]", rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop), - dparm->prop->identifier, dparm->prop->totarraylength); + rna_safe_id(dparm->prop->identifier), dparm->prop->totarraylength); else fprintf(f, "%s%s %s%s", rna_type_struct(dparm->prop), rna_parameter_type_name(dparm->prop), - ptrstr, dparm->prop->identifier); + ptrstr, rna_safe_id(dparm->prop->identifier)); } - fprintf(f, ");\n"); + fprintf(f, ")"); + if (close_prototype) + fprintf(f, ";\n"); } -static void rna_generate_static_function_prototypes(BlenderRNA *brna, StructRNA *srna, FILE *f) +static void rna_generate_static_function_prototypes(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE *f) { FunctionRNA *func; FunctionDefRNA *dfunc; @@ -2225,7 +2598,50 @@ static void rna_generate_static_function_prototypes(BlenderRNA *brna, StructRNA first = 0; } - rna_generate_static_parameter_prototypes(brna, srna, dfunc, f); + rna_generate_static_parameter_prototypes(f, srna, dfunc, NULL, 1); + } + } + + fprintf(f, "\n"); +} + +static void rna_generate_struct_prototypes(FILE *f) +{ + StructDefRNA *ds; + PropertyDefRNA *dp; + FunctionDefRNA *dfunc; + const char *structures[2048]; + int all_structures = 0; + + /* structures definitions */ + for (ds = DefRNA.structs.first; ds; ds = ds->cont.next) { + for (dfunc = ds->functions.first; dfunc; dfunc = dfunc->cont.next) { + if (dfunc->call) { + for (dp = dfunc->cont.properties.first; dp; dp = dp->next) { + if (dp->prop->type == PROP_POINTER) { + int a, found = 0; + const char *struct_name = rna_parameter_type_name(dp->prop); + + for (a = 0; a < all_structures; a++) { + if (strcmp(struct_name, structures[a]) == 0) { + found = 1; + break; + } + } + + if (found == 0) { + fprintf(f, "struct %s;\n", struct_name); + + if (all_structures >= sizeof(structures) / sizeof(structures[0])) { + printf("Array size to store all structures names is too small\n"); + exit(1); + } + + structures[all_structures++] = struct_name; + } + } + } + } } } @@ -2791,8 +3207,13 @@ static void rna_generate(BlenderRNA *brna, FILE *f, const char *filename, const for (ds = DefRNA.structs.first; ds; ds = ds->cont.next) { if (!filename || ds->filename == filename) { - for (dfunc = ds->functions.first; dfunc; dfunc = dfunc->cont.next) + for (dp = ds->cont.properties.first; dp; dp = dp->next) + rna_def_property_wrapper_funcs(f, ds, dp); + + for (dfunc = ds->functions.first; dfunc; dfunc = dfunc->cont.next) { + rna_def_function_wrapper_funcs(f, ds, dfunc); rna_def_function_funcs(f, ds, dfunc); + } rna_generate_static_function_prototypes(brna, ds->srna, f); } @@ -2816,6 +3237,7 @@ static void rna_generate_header(BlenderRNA *UNUSED(brna), FILE *f) StructDefRNA *ds; PropertyDefRNA *dp; StructRNA *srna; + FunctionDefRNA *dfunc; fprintf(f, "\n#ifndef __RNA_BLENDER_H__\n"); fprintf(f, "#define __RNA_BLENDER_H__\n\n"); @@ -2853,6 +3275,9 @@ static void rna_generate_header(BlenderRNA *UNUSED(brna), FILE *f) for (dp = ds->cont.properties.first; dp; dp = dp->next) rna_def_property_funcs_header(f, ds->srna, dp); + + for (dfunc = ds->functions.first; dfunc; dfunc = dfunc->cont.next) + rna_def_function_funcs_header(f, ds->srna, dfunc); } fprintf(f, "#ifdef __cplusplus\n}\n#endif\n\n"); @@ -2868,43 +3293,141 @@ static const char *cpp_classes = "" "namespace BL {\n" "\n" "#define BOOLEAN_PROPERTY(sname, identifier) \\\n" -" inline bool sname::identifier(void) { return sname##_##identifier##_get(&ptr)? true: false; }\n" +" inline bool sname::identifier(void) { return sname##_##identifier##_get(&ptr)? true: false; } \\\n" +" inline void sname::identifier(int value) { sname##_##identifier##_set(&ptr, value); }\n" "\n" "#define BOOLEAN_ARRAY_PROPERTY(sname, size, identifier) \\\n" " inline Array sname::identifier(void) \\\n" -" { Array ar; sname##_##identifier##_get(&ptr, ar.data); return ar; }\n" +" { Array ar; sname##_##identifier##_get(&ptr, ar.data); return ar; } \\\n" +" inline void sname::identifier(int values[size]) \\\n" +" { sname##_##identifier##_set(&ptr, values); } \\\n" +"\n" +"#define BOOLEAN_DYNAMIC_ARRAY_PROPERTY(sname, identifier) \\\n" +" inline DynamicArray sname::identifier(void) { \\\n" +" int arraylen[3]; \\\n" +" int len = sname##_##identifier##_get_length(&ptr, arraylen); \\\n" +" DynamicArray ar(len); \\\n" +" sname##_##identifier##_get(&ptr, ar.data); \\\n" +" return ar; } \\\n" +" inline void sname::identifier(int values[]) \\\n" +" { sname##_##identifier##_set(&ptr, values); } \\\n" "\n" "#define INT_PROPERTY(sname, identifier) \\\n" -" inline int sname::identifier(void) { return sname##_##identifier##_get(&ptr); }\n" +" inline int sname::identifier(void) { return sname##_##identifier##_get(&ptr); } \\\n" +" inline void sname::identifier(int value) { sname##_##identifier##_set(&ptr, value); }\n" "\n" "#define INT_ARRAY_PROPERTY(sname, size, identifier) \\\n" " inline Array sname::identifier(void) \\\n" -" { Array ar; sname##_##identifier##_get(&ptr, ar.data); return ar; }\n" +" { Array ar; sname##_##identifier##_get(&ptr, ar.data); return ar; } \\\n" +" inline void sname::identifier(int values[size]) \\\n" +" { sname##_##identifier##_set(&ptr, values); } \\\n" +"\n" +"#define INT_DYNAMIC_ARRAY_PROPERTY(sname, identifier) \\\n" +" inline DynamicArray sname::identifier(void) { \\\n" +" int arraylen[3]; \\\n" +" int len = sname##_##identifier##_get_length(&ptr, arraylen); \\\n" +" DynamicArray ar(len); \\\n" +" sname##_##identifier##_get(&ptr, ar.data); \\\n" +" return ar; } \\\n" +" inline void sname::identifier(int values[]) \\\n" +" { sname##_##identifier##_set(&ptr, values); } \\\n" "\n" "#define FLOAT_PROPERTY(sname, identifier) \\\n" -" inline float sname::identifier(void) { return sname##_##identifier##_get(&ptr); }\n" +" inline float sname::identifier(void) { return sname##_##identifier##_get(&ptr); } \\\n" +" inline void sname::identifier(float value) { sname##_##identifier##_set(&ptr, value); }\n" "\n" "#define FLOAT_ARRAY_PROPERTY(sname, size, identifier) \\\n" " inline Array sname::identifier(void) \\\n" -" { Array ar; sname##_##identifier##_get(&ptr, ar.data); return ar; }\n" +" { Array ar; sname##_##identifier##_get(&ptr, ar.data); return ar; } \\\n" +" inline void sname::identifier(float values[size]) \\\n" +" { sname##_##identifier##_set(&ptr, values); } \\\n" +"\n" +"#define FLOAT_DYNAMIC_ARRAY_PROPERTY(sname, identifier) \\\n" +" inline DynamicArray sname::identifier(void) { \\\n" +" int arraylen[3]; \\\n" +" int len = sname##_##identifier##_get_length(&ptr, arraylen); \\\n" +" DynamicArray ar(len); \\\n" +" sname##_##identifier##_get(&ptr, ar.data); \\\n" +" return ar; } \\\n" +" inline void sname::identifier(float values[]) \\\n" +" { sname##_##identifier##_set(&ptr, values); } \\\n" "\n" "#define ENUM_PROPERTY(type, sname, identifier) \\\n" -" inline sname::type sname::identifier(void) { return (type)sname##_##identifier##_get(&ptr); }\n" +" inline sname::type sname::identifier(void) { return (type)sname##_##identifier##_get(&ptr); } \\\n" +" inline void sname::identifier(sname::type value) { sname##_##identifier##_set(&ptr, value); }\n" "\n" "#define STRING_PROPERTY(sname, identifier) \\\n" " inline std::string sname::identifier(void) { \\\n" " int len= sname##_##identifier##_length(&ptr); \\\n" " std::string str; str.resize(len); \\\n" " sname##_##identifier##_get(&ptr, &str[0]); return str; } \\\n" +" inline void sname::identifier(const std::string& value) { \\\n" +" sname##_##identifier##_set(&ptr, value.c_str()); } \\\n" "\n" "#define POINTER_PROPERTY(type, sname, identifier) \\\n" " inline type sname::identifier(void) { return type(sname##_##identifier##_get(&ptr)); }\n" "\n" -"#define COLLECTION_PROPERTY(type, sname, identifier) \\\n" +"#define COLLECTION_PROPERTY_LENGTH_FALSE(sname, identifier) \\\n" +" inline static int sname##_##identifier##_length_wrap(PointerRNA *ptr) \\\n" +" { \\\n" +" CollectionPropertyIterator iter; \\\n" +" int length = 0; \\\n" +" sname##_##identifier##_begin(&iter, ptr); \\\n" +" while (iter.valid) { \\\n" +" sname##_##identifier##_next(&iter); \\\n" +" ++length; \\\n" +" } \\\n" +" sname##_##identifier##_end(&iter); \\\n" +" return length; \\\n" +" } \n" +"#define COLLECTION_PROPERTY_LENGTH_TRUE(sname, identifier) \\\n" +" inline static int sname##_##identifier##_length_wrap(PointerRNA *ptr) \\\n" +" { return sname##_##identifier##_length(ptr); } \n" +"\n" +"#define COLLECTION_PROPERTY_LOOKUP_INT_FALSE(sname, identifier) \\\n" +" inline static int sname##_##identifier##_lookup_int_wrap(PointerRNA *ptr, int key, PointerRNA *r_ptr) \\\n" +" { \\\n" +" CollectionPropertyIterator iter; \\\n" +" int i = 0, found = 0; \\\n" +" sname##_##identifier##_begin(&iter, ptr); \\\n" +" while (iter.valid) { \\\n" +" if (i == key) { \\\n" +" *r_ptr = iter.ptr; \\\n" +" found = 1; \\\n" +" break; \\\n" +" } \\\n" +" sname##_##identifier##_next(&iter); \\\n" +" ++i; \\\n" +" } \\\n" +" sname##_##identifier##_end(&iter); \\\n" +" if (!found) \\\n" +" memset(r_ptr, 0, sizeof(*r_ptr)); \\\n" +" return found; \\\n" +" } \n" +"#define COLLECTION_PROPERTY_LOOKUP_INT_TRUE(sname, identifier) \\\n" +" inline static int sname##_##identifier##_lookup_int_wrap(PointerRNA *ptr, int key, PointerRNA *r_ptr) \\\n" +" { return sname##_##identifier##_lookup_int(ptr, key, r_ptr); } \n" +"\n" +"#define COLLECTION_PROPERTY_LOOKUP_STRING_FALSE(sname, identifier) \\\n" +" inline static int sname##_##identifier##_lookup_string_wrap(PointerRNA *ptr, const char *key, PointerRNA *r_ptr) \\\n" +" { \\\n" +" memset(r_ptr, 0, sizeof(*r_ptr)); \\\n" +" return 0; \\\n" +" } \n" +"#define COLLECTION_PROPERTY_LOOKUP_STRING_TRUE(sname, identifier) \\\n" +" inline static int sname##_##identifier##_lookup_string_wrap(PointerRNA *ptr, const char *key, PointerRNA *r_ptr) \\\n" +" { return sname##_##identifier##_lookup_string(ptr, key, r_ptr); } \n" +"\n" +"#define COLLECTION_PROPERTY(collection_funcs, type, sname, identifier, has_length, has_lookup_int, has_lookup_string) \\\n" " typedef CollectionIterator identifier##_iterator; \\\n" +" COLLECTION_PROPERTY_LENGTH_##has_length(sname, identifier) \\\n" +" COLLECTION_PROPERTY_LOOKUP_INT_##has_lookup_int(sname, identifier) \\\n" +" COLLECTION_PROPERTY_LOOKUP_STRING_##has_lookup_string(sname, identifier) \\\n" " Collection identifier;\n" +" sname##_##identifier##_next, sname##_##identifier##_end, \\\n" +" sname##_##identifier##_length_wrap, \\\n" +" sname##_##identifier##_lookup_int_wrap, sname##_##identifier##_lookup_string_wrap, collection_funcs> identifier;\n" "\n" "class Pointer {\n" "public:\n" @@ -2923,7 +3446,7 @@ static const char *cpp_classes = "" "public:\n" " T data[Tsize];\n" "\n" -" Array() {}\n" +" Array() {}\n" " Array(const Array& other) { memcpy(data, other.data, sizeof(T) * Tsize); }\n" " const Array& operator=(const Array& other) { memcpy(data, other.data, sizeof(T) * Tsize); " "return *this; }\n" @@ -2931,9 +3454,36 @@ static const char *cpp_classes = "" " operator T*() { return data; }\n" "};\n" "\n" +"template\n" +"class DynamicArray {\n" +"public:\n" +" T *data;\n" +" int length;\n" +"\n" +" DynamicArray() : data(NULL), length(0) {}\n" +" DynamicArray(int new_length) : data(NULL), length(new_length) { data = (float*)malloc(sizeof(T) * new_length); }\n" +" DynamicArray(const DynamicArray& other) { copy_from(other); }\n" +" const DynamicArray& operator=(const DynamicArray& other) { copy_from(other); return *this; }\n" +"\n" +" ~DynamicArray() { if (data) free(data); }\n" +"\n" +" operator T*() { return data; }\n" +"\n" +"protected:\n" +" void copy_from(const DynamicArray& other) {\n" +" if (data) free(data);\n" +" data = (float*)malloc(sizeof(T) * other.length);\n" +" memcpy(data, other.data, sizeof(T) * other.length);\n" +" length = other.length;\n" +" }\n" +"};\n" +"\n" "typedef void (*TBeginFunc)(CollectionPropertyIterator *iter, PointerRNA *ptr);\n" "typedef void (*TNextFunc)(CollectionPropertyIterator *iter);\n" "typedef void (*TEndFunc)(CollectionPropertyIterator *iter);\n" +"typedef int (*TLengthFunc)(PointerRNA *ptr);\n" +"typedef int (*TLookupIntFunc)(PointerRNA *ptr, int key, PointerRNA *r_ptr);\n" +"typedef int (*TLookupStringFunc)(PointerRNA *ptr, const char *key, PointerRNA *r_ptr);\n" "\n" "template\n" "class CollectionIterator {\n" @@ -2964,26 +3514,97 @@ static const char *cpp_classes = "" " bool init;\n" "};\n" "\n" -"template\n" -"class Collection {\n" +"template\n" +"class Collection : public Tcollection_funcs {\n" "public:\n" -" Collection(const PointerRNA &p) : ptr(p) {}\n" +" Collection(const PointerRNA &p) : Tcollection_funcs(p), ptr(p) {}\n" "\n" " void begin(CollectionIterator& iter)\n" " { iter.begin(ptr); }\n" " CollectionIterator end()\n" " { return CollectionIterator(); } /* test */ \n" +"" +" int length()\n" +" { return Tlength(&ptr); }\n" +" T operator[](int key)\n" +" { PointerRNA r_ptr; Tlookup_int(&ptr, key, &r_ptr); return T(r_ptr); }\n" +" T operator[](const std::string &key)\n" +" { PointerRNA r_ptr; Tlookup_string(&ptr, key.c_str(), &r_ptr); return T(r_ptr); }\n" "\n" "private:\n" " PointerRNA ptr;\n" "};\n" +"\n" +"class DefaultCollectionFunctions {\n" +"public:\n" +" DefaultCollectionFunctions(const PointerRNA &p) {}\n" +"};\n" +"\n" "\n"; +static int rna_is_collection_prop(PropertyRNA *prop) +{ + if (!(prop->flag & (PROP_IDPROPERTY | PROP_BUILTIN))) + if (prop->type == PROP_COLLECTION) + return 1; + + return 0; +} + +static int rna_is_collection_functions_struct(const char **collection_structs, const char *struct_name) +{ + int a = 0, found = 0; + + while (collection_structs[a]) { + if (!strcmp(collection_structs[a], struct_name)) { + found = 1; + break; + } + a++; + } + + return found; +} + +static void rna_generate_header_class_cpp(StructDefRNA *ds, FILE *f) +{ + StructRNA *srna = ds->srna; + PropertyDefRNA *dp; + FunctionDefRNA *dfunc; + + fprintf(f, "/**************** %s ****************/\n\n", srna->name); + + fprintf(f, "class %s : public %s {\n", srna->identifier, (srna->base) ? srna->base->identifier : "Pointer"); + fprintf(f, "public:\n"); + fprintf(f, "\t%s(const PointerRNA &ptr_arg) :\n\t\t%s(ptr_arg)", srna->identifier, + (srna->base) ? srna->base->identifier : "Pointer"); + for (dp = ds->cont.properties.first; dp; dp = dp->next) + if (rna_is_collection_prop(dp->prop)) + fprintf(f, ",\n\t\t%s(ptr_arg)", dp->prop->identifier); + fprintf(f, "\n\t\t{}\n\n"); + + for (dp = ds->cont.properties.first; dp; dp = dp->next) + rna_def_property_funcs_header_cpp(f, ds->srna, dp); + + fprintf(f, "\n"); + for (dfunc = ds->functions.first; dfunc; dfunc = dfunc->cont.next) + rna_def_struct_function_header_cpp(f, srna, dfunc); + + fprintf(f, "};\n\n"); +} + static void rna_generate_header_cpp(BlenderRNA *UNUSED(brna), FILE *f) { StructDefRNA *ds; PropertyDefRNA *dp; StructRNA *srna; + FunctionDefRNA *dfunc; + const char *first_collection_func_struct = NULL; + const char *collection_func_structs[256] = {NULL}; + int all_collection_func_structs = 0; + int max_collection_func_structs = sizeof(collection_func_structs) / sizeof(collection_func_structs[0]) - 1; fprintf(f, "\n#ifndef __RNA_BLENDER_CPP_H__\n"); fprintf(f, "#define __RNA_BLENDER_CPP_H__\n\n"); @@ -3000,38 +3621,86 @@ static void rna_generate_header_cpp(BlenderRNA *UNUSED(brna), FILE *f) fprintf(f, "/**************** Declarations ****************/\n\n"); - for (ds = DefRNA.structs.first; ds; ds = ds->cont.next) + for (ds = DefRNA.structs.first; ds; ds = ds->cont.next) { fprintf(f, "class %s;\n", ds->srna->identifier); + } fprintf(f, "\n"); + /* first get list of all structures used as collection functions, so they'll be declared first */ + for (ds = DefRNA.structs.first; ds; ds = ds->cont.next) { + for (dp = ds->cont.properties.first; dp; dp = dp->next) { + if (rna_is_collection_prop(dp->prop)) { + PropertyRNA *prop = dp->prop; + + if (prop->srna) { + /* store name of structure which first uses custom functions for collections */ + if (first_collection_func_struct == NULL) + first_collection_func_struct = ds->srna->identifier; + + if (!rna_is_collection_functions_struct(collection_func_structs, (char*)prop->srna)) { + if (all_collection_func_structs >= max_collection_func_structs) { + printf("Array size to store all collection structures names is too small\n"); + exit(1); + } + + collection_func_structs[all_collection_func_structs++] = (char*)prop->srna; + } + } + } + } + } + + /* declare all structures in such order: + * - first N structures which doesn't use custom functions for collections + * - all structures used for custom functions in collections + * - all the rest structures + * such an order prevents usage of non-declared classes + */ + for (ds = DefRNA.structs.first; ds; ds = ds->cont.next) { + srna = ds->srna; + + if (!strcmp(srna->identifier, first_collection_func_struct)) { + StructDefRNA *ds2; + StructRNA *srna2; + + for (ds2 = DefRNA.structs.first; ds2; ds2 = ds2->cont.next) { + srna2 = ds2->srna; + + if (rna_is_collection_functions_struct(collection_func_structs, srna2->identifier)) { + rna_generate_header_class_cpp(ds2, f); + } + } + } + + if (!rna_is_collection_functions_struct(collection_func_structs, srna->identifier)) + rna_generate_header_class_cpp(ds, f); + } + + fprintf(f, "} /* namespace BL */\n"); + + fprintf(f, "\n"); + fprintf(f, "/**************** Implementation ****************/\n"); + fprintf(f, "\n"); + + fprintf(f, "/* Structure prototypes */\n\n"); + fprintf(f, "extern \"C\" {\n"); + rna_generate_struct_prototypes(f); + fprintf(f, "}\n\n"); + + fprintf(f, "namespace BL {\n"); + for (ds = DefRNA.structs.first; ds; ds = ds->cont.next) { srna = ds->srna; - fprintf(f, "/**************** %s ****************/\n\n", srna->name); - - fprintf(f, "class %s : public %s {\n", srna->identifier, (srna->base) ? srna->base->identifier : "Pointer"); - fprintf(f, "public:\n"); - fprintf(f, "\t%s(const PointerRNA &ptr_arg) :\n\t\t%s(ptr_arg)", srna->identifier, - (srna->base) ? srna->base->identifier : "Pointer"); - for (dp = ds->cont.properties.first; dp; dp = dp->next) - if (!(dp->prop->flag & (PROP_IDPROPERTY | PROP_BUILTIN))) - if (dp->prop->type == PROP_COLLECTION) - fprintf(f, ",\n\t\t%s(ptr_arg)", dp->prop->identifier); - fprintf(f, "\n\t\t{}\n\n"); - - for (dp = ds->cont.properties.first; dp; dp = dp->next) - rna_def_property_funcs_header_cpp(f, ds->srna, dp); - fprintf(f, "};\n\n"); - } - - - fprintf(f, "/**************** Implementation ****************/\n"); - - for (ds = DefRNA.structs.first; ds; ds = ds->cont.next) { for (dp = ds->cont.properties.first; dp; dp = dp->next) rna_def_property_funcs_impl_cpp(f, ds->srna, dp); fprintf(f, "\n"); + + for (dfunc = ds->functions.first; dfunc; dfunc = dfunc->cont.next) + rna_def_struct_function_impl_cpp(f, srna, dfunc); + + fprintf(f, "\n"); } fprintf(f, "}\n\n#endif /* __RNA_BLENDER_CPP_H__ */\n\n"); @@ -3068,34 +3737,8 @@ static int rna_preprocess(const char *outfile) rna_auto_types(); - - /* create RNA_blender_cpp.h */ - strcpy(deffile, outfile); - strcat(deffile, "RNA_blender_cpp.h" TMP_EXT); - status = (DefRNA.error != 0); - if (status) { - make_bad_file(deffile, __LINE__); - } - else { - file = fopen(deffile, "w"); - - if (!file) { - fprintf(stderr, "Unable to open file: %s\n", deffile); - status = 1; - } - else { - rna_generate_header_cpp(brna, file); - fclose(file); - status = (DefRNA.error != 0); - } - } - - replace_if_different(deffile, NULL); - - rna_sort(brna); - /* create rna_gen_*.c files */ for (i = 0; PROCESS_ITEMS[i].filename; i++) { strcpy(deffile, outfile); @@ -3128,6 +3771,31 @@ static int rna_preprocess(const char *outfile) replace_if_different(deffile, deps); } + /* create RNA_blender_cpp.h */ + strcpy(deffile, outfile); + strcat(deffile, "RNA_blender_cpp.h" TMP_EXT); + + if (status) { + make_bad_file(deffile, __LINE__); + } + else { + file = fopen(deffile, "w"); + + if (!file) { + fprintf(stderr, "Unable to open file: %s\n", deffile); + status = 1; + } + else { + rna_generate_header_cpp(brna, file); + fclose(file); + status = (DefRNA.error != 0); + } + } + + replace_if_different(deffile, NULL); + + rna_sort(brna); + /* create RNA_blender.h */ strcpy(deffile, outfile); strcat(deffile, "RNA_blender.h" TMP_EXT); diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 897e784c8e4..11ce7345e41 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -243,8 +243,8 @@ StructRNA *rna_PropertyGroup_register(Main *UNUSED(bmain), ReportList *reports, * owns the string pointer which it could potentially free while blender * is running. */ if (BLI_strnlen(identifier, MAX_IDPROP_NAME) == MAX_IDPROP_NAME) { - BKE_reportf(reports, RPT_ERROR, "registering id property class: '%s' is too long, maximum length is " - STRINGIFY(MAX_IDPROP_NAME), identifier); + BKE_reportf(reports, RPT_ERROR, "Registering id property class: '%s' is too long, maximum length is %d", + identifier, MAX_IDPROP_NAME); return NULL; } @@ -256,7 +256,7 @@ StructRNA *rna_PropertyGroup_refine(PointerRNA *ptr) return ptr->type; } -ID *rna_ID_copy(ID *id) +static ID *rna_ID_copy(ID *id) { ID *newid; @@ -287,7 +287,7 @@ static void rna_ID_update_tag(ID *id, ReportList *reports, int flag) switch (GS(id->name)) { case ID_OB: if (flag & ~(OB_RECALC_ALL)) { - BKE_report(reports, RPT_ERROR, "'refresh' incompatible with Object ID type"); + BKE_report(reports, RPT_ERROR, "'Refresh' incompatible with Object ID type"); return; } break; @@ -295,7 +295,7 @@ static void rna_ID_update_tag(ID *id, ReportList *reports, int flag) #if 0 case ID_PA: if (flag & ~(OB_RECALC_ALL | PSYS_RECALC)) { - BKE_report(reports, RPT_ERROR, "'refresh' incompatible with ParticleSettings ID type"); + BKE_report(reports, RPT_ERROR, "'Refresh' incompatible with ParticleSettings ID type"); return; } break; @@ -309,7 +309,7 @@ static void rna_ID_update_tag(ID *id, ReportList *reports, int flag) DAG_id_tag_update(id, flag); } -void rna_ID_user_clear(ID *id) +static void rna_ID_user_clear(ID *id) { id->us = 0; /* don't save */ id->flag &= ~LIB_FAKEUSER; @@ -341,7 +341,7 @@ int rna_IDMaterials_assign_int(PointerRNA *ptr, int key, const PointerRNA *assig } } -void rna_IDMaterials_append_id(ID *id, Material *ma) +static void rna_IDMaterials_append_id(ID *id, Material *ma) { material_append_id(id, ma); @@ -349,7 +349,7 @@ void rna_IDMaterials_append_id(ID *id, Material *ma) WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, id); } -Material *rna_IDMaterials_pop_id(ID *id, int index_i, int remove_material_slot) +static Material *rna_IDMaterials_pop_id(ID *id, int index_i, int remove_material_slot) { Material *ma = material_pop_id(id, index_i, remove_material_slot); @@ -360,7 +360,7 @@ Material *rna_IDMaterials_pop_id(ID *id, int index_i, int remove_material_slot) return ma; } -void rna_Library_filepath_set(PointerRNA *ptr, const char *value) +static void rna_Library_filepath_set(PointerRNA *ptr, const char *value) { Library *lib = (Library *)ptr->data; BKE_library_filepath_set(lib, value); diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 4c1c377cb9f..1fe46342819 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -233,7 +233,7 @@ static void rna_idproperty_touch(IDProperty *idprop) } /* return a UI local ID prop definition for this prop */ -IDProperty *rna_idproperty_ui(PropertyRNA *prop) +static IDProperty *rna_idproperty_ui(PropertyRNA *prop) { IDProperty *idprop; @@ -618,7 +618,7 @@ PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier) } /* Find the property which uses the given nested struct */ -PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna) +static PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna) { PropertyRNA *prop = NULL; @@ -996,7 +996,7 @@ void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin IDProperty *item; item = IDP_GetPropertyTypeFromGroup(idp_ui, "min", IDP_DOUBLE); - *hardmin = item ? (float)IDP_Double(item) : FLT_MIN; + *hardmin = item ? (float)IDP_Double(item) : -FLT_MAX; item = IDP_GetPropertyTypeFromGroup(idp_ui, "max", IDP_DOUBLE); *hardmax = item ? (float)IDP_Double(item) : FLT_MAX; @@ -3169,7 +3169,7 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro itemtype = RNA_property_type(iprop); } else { - BKE_reportf(reports, RPT_ERROR, "Property named %s not found", propname); + BKE_reportf(reports, RPT_ERROR, "Property named '%s' not found", propname); err = 1; break; } @@ -3606,7 +3606,7 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int /* copy string, taking into account escaped ] */ if (bracket) { for (p = *path, i = 0, j = 0; i < len; i++, p++) { - if (*p == '\\' && *(p + 1) == quote) ; + if (*p == '\\' && *(p + 1) == quote) {} else buf[j++] = *p; } @@ -3647,7 +3647,8 @@ int RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, Prope int RNA_path_resolve_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *index) { PropertyRNA *prop; - PointerRNA curptr, nextptr; + PointerRNA curptr; + PointerRNA nextptr; /* keep uninitialized, helps expose bugs in collection accessor functions */ char fixedbuf[256], *token; int type, intkey; @@ -3713,7 +3714,12 @@ int RNA_path_resolve_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, /* check for "" to see if it is a string */ if (rna_token_strip_quotes(token)) { - RNA_property_collection_lookup_string(&curptr, prop, token + 1, &nextptr); + if (RNA_property_collection_lookup_string(&curptr, prop, token + 1, &nextptr)) { + /* pass */ + } + else { + nextptr.data = NULL; + } } else { /* otherwise do int lookup */ @@ -3721,7 +3727,12 @@ int RNA_path_resolve_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, if (intkey == 0 && (token[0] != '0' || token[1] != '\0')) { return 0; /* we can be sure the fixedbuf was used in this case */ } - RNA_property_collection_lookup_int(&curptr, prop, intkey, &nextptr); + if (RNA_property_collection_lookup_int(&curptr, prop, intkey, &nextptr)) { + /* pass */ + } + else { + nextptr.data = NULL; + } } if (token != fixedbuf) { @@ -3730,13 +3741,14 @@ int RNA_path_resolve_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, } else { PointerRNA c_ptr; - - /* ensure we quit on invalid values */ - nextptr.data = NULL; if (RNA_property_collection_type_get(&curptr, prop, &c_ptr)) { nextptr = c_ptr; } + else { + /* ensure we quit on invalid values */ + nextptr.data = NULL; + } } if (nextptr.data) { @@ -4512,6 +4524,17 @@ int RNA_collection_length(PointerRNA *ptr, const char *name) } } +int RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, int use_ghost) +{ + if (prop->flag & PROP_IDPROPERTY) { + IDProperty *idprop = rna_idproperty_find(ptr, prop->identifier); + return ((idprop != NULL) && (use_ghost == FALSE || !(idprop->flag & IDP_FLAG_GHOST))); + } + else { + return 1; + } +} + int RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop) { if (prop->flag & PROP_IDPROPERTY) { @@ -4523,6 +4546,20 @@ int RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop) } } +int RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, int use_ghost) +{ + PropertyRNA *prop = RNA_struct_find_property(ptr, identifier); + + if (prop) { + return RNA_property_is_set_ex(ptr, prop, use_ghost); + } + else { + /* python raises an error */ + /* printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name); */ + return 0; + } +} + int RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier) { PropertyRNA *prop = RNA_struct_find_property(ptr, identifier); @@ -5219,7 +5256,7 @@ static int rna_function_format_array_length(const char *format, int ofs, int fle lenbuf[idx] = format[ofs]; if (ofs < flen && format[ofs + 1] == ']') { - /* XXX put better error reporting for ofs>=flen or idx over lenbuf capacity */ + /* XXX put better error reporting for (ofs >= flen) or idx over lenbuf capacity */ lenbuf[idx] = '\0'; return atoi(lenbuf); } diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index 00a257ab4f9..ba1aca2baba 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -27,6 +27,7 @@ #include +#include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -68,29 +69,30 @@ static bActionGroup *rna_Action_groups_new(bAction *act, const char name[]) return action_groups_add_new(act, name); } -static void rna_Action_groups_remove(bAction *act, ReportList *reports, bActionGroup *agrp) +static void rna_Action_groups_remove(bAction *act, ReportList *reports, PointerRNA *agrp_ptr) { + bActionGroup *agrp = agrp_ptr->data; FCurve *fcu, *fcn; /* try to remove the F-Curve from the action */ - if (!BLI_remlink_safe(&act->groups, agrp)) { - BKE_reportf(reports, RPT_ERROR, "ActionGroup '%s' not found in action '%s'", agrp->name, act->id.name + 2); + if (BLI_remlink_safe(&act->groups, agrp) == FALSE) { + BKE_reportf(reports, RPT_ERROR, "Action group '%s' not found in action '%s'", agrp->name, act->id.name + 2); return; } /* move every one one of the group's F-Curves out into the Action again */ for (fcu = agrp->channels.first; (fcu) && (fcu->grp == agrp); fcu = fcn) { fcn = fcu->next; - + /* remove from group */ action_groups_remove_channel(act, fcu); - + /* tack onto the end */ BLI_addtail(&act->curves, fcu); } - - /* XXX, invalidates PyObject */ + MEM_freeN(agrp); + RNA_POINTER_INVALIDATE(agrp_ptr); } static FCurve *rna_Action_fcurve_new(bAction *act, ReportList *reports, const char *data_path, @@ -112,17 +114,19 @@ static FCurve *rna_Action_fcurve_new(bAction *act, ReportList *reports, const ch return verify_fcurve(act, group, NULL, data_path, index, 1); } -static void rna_Action_fcurve_remove(bAction *act, ReportList *reports, FCurve *fcu) +static void rna_Action_fcurve_remove(bAction *act, ReportList *reports, PointerRNA *fcu_ptr) { + FCurve *fcu = fcu_ptr->data; if (fcu->grp) { if (BLI_findindex(&act->groups, fcu->grp) == -1) { - BKE_reportf(reports, RPT_ERROR, "F-Curve's ActionGroup '%s' not found in action '%s'", + BKE_reportf(reports, RPT_ERROR, "F-Curve's action group '%s' not found in action '%s'", fcu->grp->name, act->id.name + 2); return; } action_groups_remove_channel(act, fcu); free_fcurve(fcu); + RNA_POINTER_INVALIDATE(fcu_ptr); } else { if (BLI_findindex(&act->curves, fcu) == -1) { @@ -132,6 +136,7 @@ static void rna_Action_fcurve_remove(bAction *act, ReportList *reports, FCurve * BLI_remlink(&act->curves, fcu); free_fcurve(fcu); + RNA_POINTER_INVALIDATE(fcu_ptr); } } @@ -145,15 +150,16 @@ static TimeMarker *rna_Action_pose_markers_new(bAction *act, const char name[]) return marker; } -static void rna_Action_pose_markers_remove(bAction *act, ReportList *reports, TimeMarker *marker) +static void rna_Action_pose_markers_remove(bAction *act, ReportList *reports, PointerRNA *marker_ptr) { - if (!BLI_remlink_safe(&act->markers, marker)) { - BKE_reportf(reports, RPT_ERROR, "TimelineMarker '%s' not found in Action '%s'", marker->name, act->id.name + 2); + TimeMarker *marker = marker_ptr->data; + if (BLI_remlink_safe(&act->markers, marker) == FALSE) { + BKE_reportf(reports, RPT_ERROR, "Timeline marker '%s' not found in action '%s'", marker->name, act->id.name + 2); return; } - /* XXX, invalidates PyObject */ MEM_freeN(marker); + RNA_POINTER_INVALIDATE(marker_ptr); } static PointerRNA rna_Action_active_pose_marker_get(PointerRNA *ptr) @@ -256,15 +262,14 @@ static void rna_def_dopesheet(BlenderRNA *brna) srna = RNA_def_struct(brna, "DopeSheet", NULL); RNA_def_struct_sdna(srna, "bDopeSheet"); - RNA_def_struct_ui_text(srna, "DopeSheet", "Settings for filtering the channels shown in Animation Editors"); + RNA_def_struct_ui_text(srna, "DopeSheet", "Settings for filtering the channels shown in animation editors"); /* Source of DopeSheet data */ /* XXX: make this obsolete? */ prop = RNA_def_property(srna, "source", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "ID"); RNA_def_property_ui_text(prop, "Source", - "ID-Block representing source data, currently ID_SCE (for Dopesheet), " - "and ID_SC (for Grease Pencil)"); + "ID-Block representing source data, usually ID_SCE (i.e. Scene)"); /* Show datablock filters */ prop = RNA_def_property(srna, "show_datablock_filters", PROP_BOOLEAN, PROP_NONE); @@ -283,22 +288,29 @@ static void rna_def_dopesheet(BlenderRNA *brna) prop = RNA_def_property(srna, "show_hidden", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_INCL_HIDDEN); - RNA_def_property_ui_text(prop, "Display Hidden", "Include channels from objects/bone that aren't visible"); + RNA_def_property_ui_text(prop, "Display Hidden", "Include channels from objects/bone that are not visible"); RNA_def_property_ui_icon(prop, ICON_GHOST_ENABLED, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + /* Debug Filtering Settings */ + prop = RNA_def_property(srna, "show_only_errors", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_ONLY_ERRORS); + RNA_def_property_ui_text(prop, "Show Errors", "Only include F-Curves and drivers that are disabled or have errors"); + RNA_def_property_ui_icon(prop, ICON_HELP, 0); /* XXX: this doesn't quite fit */ + RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + /* Object Group Filtering Settings */ prop = RNA_def_property(srna, "show_only_group_objects", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_ONLYOBGROUP); RNA_def_property_ui_text(prop, "Only Objects in Group", - "Only include channels from Objects in the specified Group"); + "Only include channels from objects in the specified group"); RNA_def_property_ui_icon(prop, ICON_GROUP, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "filter_group", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "filter_grp"); RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Filtering Group", "Group that included Object should be a member of"); + RNA_def_property_ui_text(prop, "Filtering Group", "Group that included object should be a member of"); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); /* FCurve Display Name Search Settings */ @@ -318,21 +330,21 @@ static void rna_def_dopesheet(BlenderRNA *brna) prop = RNA_def_property(srna, "show_missing_nla", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NLA_NOACT); RNA_def_property_ui_text(prop, "Include Missing NLA", - "Include Animation Data blocks with no NLA data (NLA Editor only)"); + "Include animation data blocks with no NLA data (NLA editor only)"); RNA_def_property_ui_icon(prop, ICON_ACTION, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); /* Summary Settings (DopeSheet editors only) */ prop = RNA_def_property(srna, "show_summary", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_SUMMARY); - RNA_def_property_ui_text(prop, "Display Summary", "Display an additional 'summary' line (DopeSheet Editors only)"); + RNA_def_property_ui_text(prop, "Display Summary", "Display an additional 'summary' line (DopeSheet editors only)"); RNA_def_property_ui_icon(prop, ICON_BORDERMOVE, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "show_expanded_summary", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", ADS_FLAG_SUMMARY_COLLAPSED); RNA_def_property_ui_text(prop, "Collapse Summary", - "Collapse summary when shown, so all other channels get hidden (DopeSheet Editors Only)"); + "Collapse summary when shown, so all other channels get hidden (DopeSheet editors only)"); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); @@ -340,97 +352,97 @@ static void rna_def_dopesheet(BlenderRNA *brna) prop = RNA_def_property(srna, "show_transforms", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOOBJ); RNA_def_property_ui_text(prop, "Display Transforms", - "Include visualization of Object-level Animation data (mostly Transforms)"); + "Include visualization of object-level animation data (mostly transforms)"); RNA_def_property_ui_icon(prop, ICON_MANIPUL, 0); /* XXX? */ RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "show_shapekeys", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOSHAPEKEYS); - RNA_def_property_ui_text(prop, "Display Shapekeys", "Include visualization of ShapeKey related Animation data"); + RNA_def_property_ui_text(prop, "Display Shapekeys", "Include visualization of shape key related animation data"); RNA_def_property_ui_icon(prop, ICON_SHAPEKEY_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "show_meshes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOMESH); - RNA_def_property_ui_text(prop, "Display Meshes", "Include visualization of Mesh related Animation data"); + RNA_def_property_ui_text(prop, "Display Meshes", "Include visualization of mesh related animation data"); RNA_def_property_ui_icon(prop, ICON_MESH_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "show_lattices", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOLAT); - RNA_def_property_ui_text(prop, "Display Lattices", "Include visualization of Lattice related Animation data"); + RNA_def_property_ui_text(prop, "Display Lattices", "Include visualization of lattice related animation data"); RNA_def_property_ui_icon(prop, ICON_LATTICE_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "show_cameras", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOCAM); - RNA_def_property_ui_text(prop, "Display Camera", "Include visualization of Camera related Animation data"); + RNA_def_property_ui_text(prop, "Display Camera", "Include visualization of camera related animation data"); RNA_def_property_ui_icon(prop, ICON_CAMERA_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "show_materials", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOMAT); - RNA_def_property_ui_text(prop, "Display Material", "Include visualization of Material related Animation data"); + RNA_def_property_ui_text(prop, "Display Material", "Include visualization of material related animation data"); RNA_def_property_ui_icon(prop, ICON_MATERIAL_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "show_lamps", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOLAM); - RNA_def_property_ui_text(prop, "Display Lamp", "Include visualization of Lamp related Animation data"); + RNA_def_property_ui_text(prop, "Display Lamp", "Include visualization of lamp related animation data"); RNA_def_property_ui_icon(prop, ICON_LAMP_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "show_textures", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOTEX); - RNA_def_property_ui_text(prop, "Display Texture", "Include visualization of Texture related Animation data"); + RNA_def_property_ui_text(prop, "Display Texture", "Include visualization of texture related animation data"); RNA_def_property_ui_icon(prop, ICON_TEXTURE_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "show_curves", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOCUR); - RNA_def_property_ui_text(prop, "Display Curve", "Include visualization of Curve related Animation data"); + RNA_def_property_ui_text(prop, "Display Curve", "Include visualization of curve related animation data"); RNA_def_property_ui_icon(prop, ICON_CURVE_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "show_worlds", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOWOR); - RNA_def_property_ui_text(prop, "Display World", "Include visualization of World related Animation data"); + RNA_def_property_ui_text(prop, "Display World", "Include visualization of world related animation data"); RNA_def_property_ui_icon(prop, ICON_WORLD_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "show_scenes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOSCE); - RNA_def_property_ui_text(prop, "Display Scene", "Include visualization of Scene related Animation data"); + RNA_def_property_ui_text(prop, "Display Scene", "Include visualization of scene related animation data"); RNA_def_property_ui_icon(prop, ICON_SCENE_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "show_particles", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOPART); - RNA_def_property_ui_text(prop, "Display Particle", "Include visualization of Particle related Animation data"); + RNA_def_property_ui_text(prop, "Display Particle", "Include visualization of particle related animation data"); RNA_def_property_ui_icon(prop, ICON_PARTICLE_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "show_metaballs", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOMBA); - RNA_def_property_ui_text(prop, "Display Metaball", "Include visualization of Metaball related Animation data"); + RNA_def_property_ui_text(prop, "Display Metaball", "Include visualization of metaball related animation data"); RNA_def_property_ui_icon(prop, ICON_META_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "show_armatures", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOARM); - RNA_def_property_ui_text(prop, "Display Armature", "Include visualization of Armature related Animation data"); + RNA_def_property_ui_text(prop, "Display Armature", "Include visualization of armature related animation data"); RNA_def_property_ui_icon(prop, ICON_ARMATURE_DATA, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "show_nodes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NONTREE); - RNA_def_property_ui_text(prop, "Display Node", "Include visualization of Node related Animation data"); + RNA_def_property_ui_text(prop, "Display Node", "Include visualization of node related animation data"); RNA_def_property_ui_icon(prop, ICON_NODETREE, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "show_speakers", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag", ADS_FILTER_NOSPK); - RNA_def_property_ui_text(prop, "Display Speaker", "Include visualization of Speaker related Animation data"); + RNA_def_property_ui_text(prop, "Display Speaker", "Include visualization of speaker related animation data"); RNA_def_property_ui_icon(prop, ICON_SPEAKER, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); } @@ -467,17 +479,17 @@ static void rna_def_action_group(BlenderRNA *brna) prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", AGRP_SELECTED); - RNA_def_property_ui_text(prop, "Select", "Action Group is selected"); + RNA_def_property_ui_text(prop, "Select", "Action group is selected"); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL); prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", AGRP_PROTECTED); - RNA_def_property_ui_text(prop, "Lock", "Action Group is locked"); + RNA_def_property_ui_text(prop, "Lock", "Action group is locked"); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", AGRP_EXPANDED); - RNA_def_property_ui_text(prop, "Expanded", "Action Group is expanded"); + RNA_def_property_ui_text(prop, "Expanded", "Action group is expanded"); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); /* color set */ @@ -510,7 +522,8 @@ static void rna_def_action_groups(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove action group"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "action_group", "ActionGroup", "", "Action group to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } static void rna_def_action_fcurves(BlenderRNA *brna, PropertyRNA *cprop) @@ -541,7 +554,8 @@ static void rna_def_action_fcurves(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove action group"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "fcurve", "FCurve", "", "F-Curve to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } static void rna_def_action_pose_markers(BlenderRNA *brna, PropertyRNA *cprop) @@ -569,14 +583,15 @@ static void rna_def_action_pose_markers(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove a timeline marker"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "marker", "TimelineMarker", "", "Timeline marker to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "TimelineMarker"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_pointer_funcs(prop, "rna_Action_active_pose_marker_get", "rna_Action_active_pose_marker_set", NULL, NULL); - RNA_def_property_ui_text(prop, "Active Pose Marker", "Active pose marker for this Action"); + RNA_def_property_ui_text(prop, "Active Pose Marker", "Active pose marker for this action"); prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "active_marker"); @@ -599,7 +614,7 @@ static void rna_def_action(BlenderRNA *brna) prop = RNA_def_property(srna, "fcurves", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "curves", NULL); RNA_def_property_struct_type(prop, "FCurve"); - RNA_def_property_ui_text(prop, "F-Curves", "The individual F-Curves that make up the Action"); + RNA_def_property_ui_text(prop, "F-Curves", "The individual F-Curves that make up the action"); rna_def_action_fcurves(brna, prop); prop = RNA_def_property(srna, "groups", PROP_COLLECTION, PROP_NONE); @@ -611,7 +626,7 @@ static void rna_def_action(BlenderRNA *brna) prop = RNA_def_property(srna, "pose_markers", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "markers", NULL); RNA_def_property_struct_type(prop, "TimelineMarker"); - RNA_def_property_ui_text(prop, "Pose Markers", "Markers specific to this Action, for labeling poses"); + RNA_def_property_ui_text(prop, "Pose Markers", "Markers specific to this action, for labeling poses"); rna_def_action_pose_markers(brna, prop); /* properties */ @@ -626,8 +641,8 @@ static void rna_def_action(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "idroot"); RNA_def_property_enum_items(prop, id_type_items); RNA_def_property_ui_text(prop, "ID Root Type", - "Type of ID-block that action can be used on - " - "DO NOT CHANGE UNLESS YOU KNOW WHAT YOU'RE DOING"); + "Type of ID block that action can be used on - " + "DO NOT CHANGE UNLESS YOU KNOW WHAT YOU ARE DOING"); /* API calls */ RNA_api_action(srna); diff --git a/source/blender/makesrna/intern/rna_action_api.c b/source/blender/makesrna/intern/rna_action_api.c index 7e95aaab31b..fe429d8698b 100644 --- a/source/blender/makesrna/intern/rna_action_api.c +++ b/source/blender/makesrna/intern/rna_action_api.c @@ -34,10 +34,14 @@ #include #include +#include "BLI_utildefines.h" + #include "RNA_define.h" #include "DNA_action_types.h" +#include "rna_internal.h" /* own include */ + #ifdef RNA_RUNTIME #include "BKE_action.h" @@ -47,7 +51,7 @@ #else -void RNA_api_action(StructRNA *srna) +void RNA_api_action(StructRNA *UNUSED(srna)) { } diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c index bb714043002..b1fdfccd0be 100644 --- a/source/blender/makesrna/intern/rna_actuator.c +++ b/source/blender/makesrna/intern/rna_actuator.c @@ -29,6 +29,7 @@ #include "RNA_define.h" #include "RNA_access.h" +#include "RNA_enum_types.h" #include "rna_internal.h" #include "DNA_constraint_types.h" @@ -40,6 +41,8 @@ #include "BLI_utildefines.h" +#include "BLF_translation.h" + /* Always keep in alphabetical order */ EnumPropertyItem actuator_type_items[] = { {ACT_ACTION, "ACTION", 0, "Action", ""}, @@ -110,7 +113,7 @@ static StructRNA *rna_Actuator_refine(struct PointerRNA *ptr) } } -void rna_Actuator_name_set(PointerRNA *ptr, const char *value) +static void rna_Actuator_name_set(PointerRNA *ptr, const char *value) { bActuator *act = (bActuator *)ptr->data; @@ -530,7 +533,7 @@ static void rna_Actuator_action_action_set(PointerRNA *ptr, PointerRNA value) #else -void rna_def_actuator(BlenderRNA *brna) +static void rna_def_actuator(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; @@ -970,11 +973,13 @@ static void rna_def_sound_actuator(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.0, 1.0, 1, 2); RNA_def_property_range(prop, 0.0, 2.0); RNA_def_property_ui_text(prop, "Volume", "Initial volume of the sound"); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); RNA_def_property_update(prop, NC_LOGIC, NULL); prop = RNA_def_property(srna, "pitch", PROP_FLOAT, PROP_NONE); RNA_def_property_ui_range(prop, -12.0, 12.0, 1, 2); RNA_def_property_ui_text(prop, "Pitch", "Pitch of the sound"); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); RNA_def_property_update(prop, NC_LOGIC, NULL); /* floats - 3D Parameters */ diff --git a/source/blender/makesrna/intern/rna_actuator_api.c b/source/blender/makesrna/intern/rna_actuator_api.c index 68b2c4f8b52..4a34961964d 100644 --- a/source/blender/makesrna/intern/rna_actuator_api.c +++ b/source/blender/makesrna/intern/rna_actuator_api.c @@ -35,6 +35,8 @@ #include "WM_types.h" #include "RNA_define.h" +#include "rna_internal.h" /* own include */ + #ifdef RNA_RUNTIME #include "BKE_sca.h" diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index 69f785c32de..ce884fa4ecc 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -369,27 +369,30 @@ static KS_Path *rna_KeyingSet_paths_add(KeyingSet *keyingset, ReportList *report keyingset->active_path = BLI_countlist(&keyingset->paths); } else { - BKE_report(reports, RPT_ERROR, "Keying Set Path could not be added"); + BKE_report(reports, RPT_ERROR, "Keying set path could not be added"); } /* return added path */ return ksp; } -static void rna_KeyingSet_paths_remove(KeyingSet *keyingset, ReportList *reports, KS_Path *ksp) +static void rna_KeyingSet_paths_remove(KeyingSet *keyingset, ReportList *reports, PointerRNA *ksp_ptr) { + KS_Path *ksp = ksp_ptr->data; + /* if data is valid, call the API function for this */ - if (keyingset && ksp) { - /* remove the active path from the KeyingSet */ - BKE_keyingset_free_path(keyingset, ksp); - - /* the active path number will most likely have changed */ - /* TODO: we should get more fancy and actually check if it was removed, but this will do for now */ - keyingset->active_path = 0; - } - else { - BKE_report(reports, RPT_ERROR, "Keying Set Path could not be removed"); + if ((keyingset && ksp) == FALSE) { + BKE_report(reports, RPT_ERROR, "Keying set path could not be removed"); + return; } + + /* remove the active path from the KeyingSet */ + BKE_keyingset_free_path(keyingset, ksp); + RNA_POINTER_INVALIDATE(ksp_ptr); + + /* the active path number will most likely have changed */ + /* TODO: we should get more fancy and actually check if it was removed, but this will do for now */ + keyingset->active_path = 0; } static void rna_KeyingSet_paths_clear(KeyingSet *keyingset, ReportList *reports) @@ -408,7 +411,7 @@ static void rna_KeyingSet_paths_clear(KeyingSet *keyingset, ReportList *reports) keyingset->active_path = 0; } else { - BKE_report(reports, RPT_ERROR, "Keying Set Paths could not be removed"); + BKE_report(reports, RPT_ERROR, "Keying set paths could not be removed"); } } @@ -422,9 +425,17 @@ static NlaTrack *rna_NlaTrack_new(AnimData *adt, bContext *C, NlaTrack *track) return new_track; } -static void rna_NlaTrack_remove(AnimData *adt, bContext *C, NlaTrack *track) +static void rna_NlaTrack_remove(AnimData *adt, bContext *C, ReportList *reports, PointerRNA *track_ptr) { + NlaTrack *track = track_ptr->data; + + if (BLI_findindex(&adt->nla_tracks, track) == -1) { + BKE_reportf(reports, RPT_ERROR, "NlaTrack '%s' can't be removed", track->name); + return; + } + free_nlatrack(&adt->nla_tracks, track); + RNA_POINTER_INVALIDATE(track_ptr); WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_REMOVED, NULL); } @@ -448,7 +459,7 @@ static FCurve *rna_Driver_from_existing(AnimData *adt, bContext *C, FCurve *src_ { /* verify that we've got a driver to duplicate */ if (ELEM(NULL, src_driver, src_driver->driver)) { - BKE_reportf(CTX_wm_reports(C), RPT_ERROR, "No valid driver data to create copy of"); + BKE_report(CTX_wm_reports(C), RPT_ERROR, "No valid driver data to create copy of"); return NULL; } else { @@ -678,7 +689,8 @@ static void rna_def_keyingset_paths(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); /* path to remove */ parm = RNA_def_pointer(func, "path", "KeyingSetPath", "Path", ""); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); /* Remove All Paths */ @@ -783,10 +795,11 @@ static void rna_api_animdata_nla_tracks(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_return(func, parm); func = RNA_def_function(srna, "remove", "rna_NlaTrack_remove"); - RNA_def_function_flag(func, FUNC_USE_CONTEXT); + RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_CONTEXT); RNA_def_function_ui_description(func, "Remove a NLA Track"); parm = RNA_def_pointer(func, "track", "NlaTrack", "", "NLA Track to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "NlaTrack"); @@ -829,7 +842,7 @@ void rna_def_animdata_common(StructRNA *srna) RNA_def_property_ui_text(prop, "Animation Data", "Animation data for this datablock"); } -void rna_def_animdata(BlenderRNA *brna) +static void rna_def_animdata(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; diff --git a/source/blender/makesrna/intern/rna_animation_api.c b/source/blender/makesrna/intern/rna_animation_api.c index 32472c8d415..492659fdc2e 100644 --- a/source/blender/makesrna/intern/rna_animation_api.c +++ b/source/blender/makesrna/intern/rna_animation_api.c @@ -39,6 +39,7 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "rna_internal.h" /* own include */ #ifdef RNA_RUNTIME @@ -55,11 +56,11 @@ static void rna_KeyingSet_context_refresh(KeyingSet *ks, bContext *C, ReportList if (success != 0) { switch (success) { case MODIFYKEY_INVALID_CONTEXT: - BKE_report(reports, RPT_ERROR, "Invalid context for Keying Set"); + BKE_report(reports, RPT_ERROR, "Invalid context for keying set"); break; case MODIFYKEY_MISSING_TYPEINFO: - BKE_report(reports, RPT_ERROR, "Incomplete built-in Keying Set. Appears to be missing type info"); + BKE_report(reports, RPT_ERROR, "Incomplete built-in keying set, appears to be missing type info"); break; } } diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index be70405d165..4c566d71981 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -29,6 +29,7 @@ #include "BLI_math.h" +#include "RNA_access.h" #include "RNA_define.h" #include "rna_internal.h" @@ -100,28 +101,30 @@ static void rna_Armature_act_edit_bone_set(PointerRNA *ptr, PointerRNA value) } } -EditBone *rna_Armature_edit_bone_new(bArmature *arm, ReportList *reports, const char *name) +static EditBone *rna_Armature_edit_bone_new(bArmature *arm, ReportList *reports, const char *name) { if (arm->edbo == NULL) { - BKE_reportf(reports, RPT_ERROR, "Armature '%s' not in editmode, cant add an editbone", arm->id.name + 2); + BKE_reportf(reports, RPT_ERROR, "Armature '%s' not in edit mode, cannot add an editbone", arm->id.name + 2); return NULL; } return ED_armature_edit_bone_add(arm, name); } -void rna_Armature_edit_bone_remove(bArmature *arm, ReportList *reports, EditBone *ebone) +static void rna_Armature_edit_bone_remove(bArmature *arm, ReportList *reports, PointerRNA *ebone_ptr) { + EditBone *ebone = ebone_ptr->data; if (arm->edbo == NULL) { - BKE_reportf(reports, RPT_ERROR, "Armature '%s' not in editmode, cant remove an editbone", arm->id.name + 2); + BKE_reportf(reports, RPT_ERROR, "Armature '%s' not in edit mode, cannot remove an editbone", arm->id.name + 2); return; } if (BLI_findindex(arm->edbo, ebone) == -1) { - BKE_reportf(reports, RPT_ERROR, "Armature '%s' doesn't contain bone '%s'", arm->id.name + 2, ebone->name); + BKE_reportf(reports, RPT_ERROR, "Armature '%s' does not contain bone '%s'", arm->id.name + 2, ebone->name); return; } ED_armature_edit_bone_remove(arm, ebone); + RNA_POINTER_INVALIDATE(ebone_ptr); } static void rna_Armature_update_layers(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) @@ -271,7 +274,7 @@ static void rna_Armature_layer_set(PointerRNA *ptr, const int *values) } } -/* XXX depreceated.... old armature only animviz */ +/* XXX deprecated.... old armature only animviz */ static void rna_Armature_ghost_start_frame_set(PointerRNA *ptr, int value) { bArmature *data = (bArmature *)ptr->data; @@ -293,7 +296,7 @@ static void rna_Armature_ghost_end_frame_set(PointerRNA *ptr, int value) data->ghostsf = MAX2(data->ghostef, 1); } } -/* XXX depreceated... old armature only animviz */ +/* XXX deprecated... old armature only animviz */ static void rna_EditBone_name_set(PointerRNA *ptr, const char *value) { @@ -564,7 +567,7 @@ static void rna_def_bone_common(StructRNA *srna, int editbone) if (editbone) RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update"); else RNA_def_property_update(prop, 0, "rna_Armature_update_data"); RNA_def_property_float_sdna(prop, NULL, "rad_head"); - /* XXX range is 0 to lim, where lim= 10000.0f*MAX2(1.0, view3d->grid); */ + /* XXX range is 0 to lim, where lim = 10000.0f * MAX2(1.0, view3d->grid); */ /*RNA_def_property_range(prop, 0, 1000); */ RNA_def_property_ui_range(prop, 0.01, 100, 0.1, 3); RNA_def_property_ui_text(prop, "Envelope Head Radius", "Radius of head of bone (for Envelope deform only)"); @@ -573,7 +576,7 @@ static void rna_def_bone_common(StructRNA *srna, int editbone) if (editbone) RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update"); else RNA_def_property_update(prop, 0, "rna_Armature_update_data"); RNA_def_property_float_sdna(prop, NULL, "rad_tail"); - /* XXX range is 0 to lim, where lim= 10000.0f*MAX2(1.0, view3d->grid); */ + /* XXX range is 0 to lim, where lim = 10000.0f * MAX2(1.0, view3d->grid); */ /*RNA_def_property_range(prop, 0, 1000); */ RNA_def_property_ui_range(prop, 0.01, 100, 0.1, 3); RNA_def_property_ui_text(prop, "Envelope Tail Radius", "Radius of tail of bone (for Envelope deform only)"); @@ -865,7 +868,8 @@ static void rna_def_armature_edit_bones(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove an existing bone from the armature"); /* target to remove*/ parm = RNA_def_pointer(func, "bone", "EditBone", "", "EditBone to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } static void rna_def_armature(BlenderRNA *brna) @@ -945,14 +949,14 @@ static void rna_def_armature(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); -/* XXX depreceated ....... old animviz for armatures only */ +/* XXX deprecated ....... old animviz for armatures only */ prop = RNA_def_property(srna, "ghost_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "ghosttype"); RNA_def_property_enum_items(prop, prop_ghost_type_items); RNA_def_property_ui_text(prop, "Ghost Type", "Method of Onion-skinning for active Action"); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); -/* XXX depreceated ....... old animviz for armatures only */ +/* XXX deprecated ....... old animviz for armatures only */ /* Boolean values */ /* layer */ @@ -1013,16 +1017,16 @@ static void rna_def_armature(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Draw Bone Group Colors", "Draw bone group colors"); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); -/* XXX depreceated ....... old animviz for armatures only */ +/* XXX deprecated ....... old animviz for armatures only */ prop = RNA_def_property(srna, "show_only_ghost_selected", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ARM_GHOST_ONLYSEL); RNA_def_property_ui_text(prop, "Draw Ghosts on Selected Bones Only", ""); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); -/* XXX depreceated ....... old animviz for armatures only */ +/* XXX deprecated ....... old animviz for armatures only */ /* Number fields */ -/* XXX depreceated ....... old animviz for armatures only */ +/* XXX deprecated ....... old animviz for armatures only */ /* ghost/onionskining settings */ prop = RNA_def_property(srna, "ghost_step", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "ghostep"); @@ -1058,7 +1062,7 @@ static void rna_def_armature(BlenderRNA *brna) "(not for 'Around Current Frame' Onion-skinning method)"); RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); -/* XXX depreceated ....... old animviz for armatures only */ +/* XXX deprecated ....... old animviz for armatures only */ } void RNA_def_armature(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_armature_api.c b/source/blender/makesrna/intern/rna_armature_api.c index 29dc23b7bef..96c5350e5b7 100644 --- a/source/blender/makesrna/intern/rna_armature_api.c +++ b/source/blender/makesrna/intern/rna_armature_api.c @@ -36,18 +36,20 @@ #include "RNA_define.h" +#include "rna_internal.h" /* own include */ + #ifdef RNA_RUNTIME #include #include "BKE_armature.h" -void rna_EditBone_align_roll(EditBone *ebo, float no[3]) +static void rna_EditBone_align_roll(EditBone *ebo, float no[3]) { ebo->roll = ED_rollBoneToVector(ebo, no, FALSE); } -float rna_Bone_do_envelope(Bone *bone, float *vec) +static float rna_Bone_do_envelope(Bone *bone, float *vec) { float scale = (bone->flag & BONE_MULT_VG_ENV) == BONE_MULT_VG_ENV ? bone->weight : 1.0f; return distfactor_to_bone(vec, bone->arm_head, bone->arm_tail, bone->rad_head * scale, diff --git a/source/blender/makesrna/intern/rna_boid.c b/source/blender/makesrna/intern/rna_boid.c index 2a6ea2994fa..8e45da50e9b 100644 --- a/source/blender/makesrna/intern/rna_boid.c +++ b/source/blender/makesrna/intern/rna_boid.c @@ -436,7 +436,7 @@ static void rna_def_boidrule(BlenderRNA *brna) RNA_def_property_ui_text(prop, "On Land", "Use rule when boid is on land"); RNA_def_property_update(prop, 0, "rna_Boids_reset"); - /*prop= RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE); */ + /*prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE); */ /*RNA_def_property_boolean_sdna(prop, NULL, "mode", eModifierMode_Expanded); */ /*RNA_def_property_ui_text(prop, "Expanded", "Set modifier expanded in the user interface"); */ diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c index ad926d6a08e..b72bba0422a 100644 --- a/source/blender/makesrna/intern/rna_camera.c +++ b/source/blender/makesrna/intern/rna_camera.c @@ -258,7 +258,7 @@ void RNA_def_camera(BlenderRNA *brna) prop = RNA_def_property(srna, "show_title_safe", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_SHOWTITLESAFE); - RNA_def_property_ui_text(prop, "Show Title Safe", "Show indicators for the title safe zone in Camera view"); + RNA_def_property_ui_text(prop, "Show Safe Areas", "Show TV title safe and action safe zones in Camera view"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); prop = RNA_def_property(srna, "show_name", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_camera_api.c b/source/blender/makesrna/intern/rna_camera_api.c index 75941fa224f..bf916806e40 100644 --- a/source/blender/makesrna/intern/rna_camera_api.c +++ b/source/blender/makesrna/intern/rna_camera_api.c @@ -31,6 +31,8 @@ #include "RNA_define.h" +#include "rna_internal.h" /* own include */ + #ifdef RNA_RUNTIME #include "DNA_scene_types.h" @@ -39,8 +41,8 @@ #include "BKE_context.h" #include "BKE_object.h" -void rna_camera_view_frame(struct Camera *camera, struct Scene *scene, - float vec1_r[3], float vec2_r[3], float vec3_r[3], float vec4_r[3]) +static void rna_camera_view_frame(struct Camera *camera, struct Scene *scene, + float vec1_r[3], float vec2_r[3], float vec3_r[3], float vec4_r[3]) { float vec[4][3]; diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index 5f1ce4f2773..b9e86e116a2 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -419,41 +419,41 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna) /* unused still */ #if 0 - prop= RNA_def_property(srna, "shear_stiffness", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "shear_stiffness", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "shear"); RNA_def_property_range(prop, 0.0f, 1000.0f); RNA_def_property_ui_text(prop, "Shear Stiffness", "Shear spring stiffness"); #endif /* unused still */ #if 0 - prop= RNA_def_property(srna, "shear_stiffness_max", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "shear_stiffness_max", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "max_shear"); RNA_def_property_range(prop, 0.0f, upperLimitf); RNA_def_property_ui_text(prop, "Shear Stiffness Maximum", "Maximum shear scaling value"); #endif /* unused still */ #if 0 - prop= RNA_def_property(srna, "effector_force_scale", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "effector_force_scale", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "eff_force_scale"); RNA_def_property_range(prop, 0.0f, 100.0f); RNA_def_property_ui_text(prop, "Effector Force Scale", ""); #endif /* unused still */ #if 0 - prop= RNA_def_property(srna, "effector_wind_scale", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "effector_wind_scale", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "eff_wind_scale"); RNA_def_property_range(prop, 0.0f, 100.0f); RNA_def_property_ui_text(prop, "Effector Wind Scale", ""); #endif /* unused still */ #if 0 - prop= RNA_def_property(srna, "tearing", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "tearing", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_TEARING); RNA_def_property_ui_text(prop, "Tearing", ""); #endif /* unused still */ #if 0 - prop= RNA_def_property(srna, "max_spring_extensions", PROP_INT, PROP_NONE); + prop = RNA_def_property(srna, "max_spring_extensions", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "maxspringlen"); RNA_def_property_range(prop, 1.0, 1000.0); RNA_def_property_ui_text(prop, "Maximum Spring Extension", "Maximum extension before spring gets cut"); diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 0edcad59577..c93d2ef15cf 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -314,7 +314,7 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA * } } -void rna_ColorRamp_eval(struct ColorBand *coba, float position, float color[4]) +static void rna_ColorRamp_eval(struct ColorBand *coba, float position, float color[4]) { do_colorband(coba, position, color); } @@ -329,12 +329,27 @@ static CBData *rna_ColorRampElement_new(struct ColorBand *coba, ReportList *repo return element; } -static void rna_ColorRampElement_remove(struct ColorBand *coba, ReportList *reports, CBData *element) +static void rna_ColorRampElement_remove(struct ColorBand *coba, ReportList *reports, PointerRNA *element_ptr) { + CBData *element = element_ptr->data; int index = (int)(element - coba->data); - if (colorband_element_remove(coba, index) == 0) + if (colorband_element_remove(coba, index) == FALSE) { BKE_report(reports, RPT_ERROR, "Element not found in element collection or last element"); + return; + } + RNA_POINTER_INVALIDATE(element_ptr); +} + +void rna_CurveMap_remove_point(CurveMap *cuma, ReportList *reports, PointerRNA *point_ptr) +{ + CurveMapPoint *point = point_ptr->data; + if (curvemap_remove_point(cuma, point) == FALSE) { + BKE_report(reports, RPT_ERROR, "Unable to remove curve point"); + return; + } + + RNA_POINTER_INVALIDATE(point_ptr); } static void rna_Scopes_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) @@ -377,6 +392,9 @@ static void rna_ColorManagedDisplaySettings_display_device_update(Main *UNUSED(b { ID *id = ptr->id.data; + if (!id) + return; + if (GS(id->name) == ID_SCE) { Scene *scene = (Scene *) id; @@ -471,14 +489,20 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *UNUSED(bmain) if (GS(id->name) == ID_IM) { Image *ima = (Image *) id; - BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); + DAG_id_tag_update(&ima->id, 0); + + BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE); + WM_main_add_notifier(NC_IMAGE | ND_DISPLAY, &ima->id); + WM_main_add_notifier(NC_IMAGE | NA_EDITED, &ima->id); } else if (GS(id->name) == ID_MC) { MovieClip *clip = (MovieClip *) id; BKE_movieclip_reload(clip); + WM_main_add_notifier(NC_MOVIECLIP | ND_DISPLAY, &clip->id); + WM_main_add_notifier(NC_MOVIECLIP | NA_EDITED, &clip->id); } } @@ -486,13 +510,16 @@ static void rna_ColorManagement_update(Main *UNUSED(bmain), Scene *UNUSED(scene) { ID *id = ptr->id.data; + if (!id) + return; + if (GS(id->name) == ID_SCE) { WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); } } /* this function only exists because #curvemap_evaluateF uses a 'const' qualifier */ -float rna_CurveMap_evaluateF(struct CurveMap *cuma, float value) +static float rna_CurveMap_evaluateF(struct CurveMap *cuma, float value) { return curvemap_evaluateF(cuma, value); } @@ -547,10 +574,12 @@ static void rna_def_curvemap_points_api(BlenderRNA *brna, PropertyRNA *cprop) parm = RNA_def_pointer(func, "point", "CurveMapPoint", "", "New point"); RNA_def_function_return(func, parm); - func = RNA_def_function(srna, "remove", "curvemap_remove_point"); + func = RNA_def_function(srna, "remove", "rna_CurveMap_remove_point"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Delete point from CurveMap"); parm = RNA_def_pointer(func, "point", "CurveMapPoint", "", "PointElement to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } static void rna_def_curvemap(BlenderRNA *brna) @@ -699,7 +728,8 @@ static void rna_def_color_ramp_element_api(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Delete element from ColorRamp"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "element", "ColorRampElement", "", "Element to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } static void rna_def_color_ramp(BlenderRNA *brna) @@ -860,7 +890,7 @@ static void rna_def_colormanage(BlenderRNA *brna) srna = RNA_def_struct(brna, "ColorManagedDisplaySettings", NULL); RNA_def_struct_ui_text(srna, "ColorManagedDisplaySettings", "Color management specific to display device"); - prop= RNA_def_property(srna, "display_device", PROP_ENUM, PROP_NONE); + prop = RNA_def_property(srna, "display_device", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, display_device_items); RNA_def_property_enum_funcs(prop, "rna_ColorManagedDisplaySettings_display_device_get", "rna_ColorManagedDisplaySettings_display_device_set", @@ -872,7 +902,7 @@ static void rna_def_colormanage(BlenderRNA *brna) srna = RNA_def_struct(brna, "ColorManagedViewSettings", NULL); RNA_def_struct_ui_text(srna, "ColorManagedViewSettings", "Color management settings used for displaying images on the display"); - prop= RNA_def_property(srna, "view_transform", PROP_ENUM, PROP_NONE); + prop = RNA_def_property(srna, "view_transform", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, view_transform_items); RNA_def_property_enum_funcs(prop, "rna_ColorManagedViewSettings_view_transform_get", "rna_ColorManagedViewSettings_view_transform_set", @@ -909,7 +939,7 @@ static void rna_def_colormanage(BlenderRNA *brna) srna = RNA_def_struct(brna, "ColorManagedColorspaceSettings", NULL); RNA_def_struct_ui_text(srna, "ColorManagedColorspaceSettings", "Input color space settings"); - prop= RNA_def_property(srna, "name", PROP_ENUM, PROP_NONE); + prop = RNA_def_property(srna, "name", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, color_space_items); RNA_def_property_enum_funcs(prop, "rna_ColorManagedColorspaceSettings_colorspace_get", "rna_ColorManagedColorspaceSettings_colorspace_set", diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 770bdb68e38..7b6b629ca82 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -703,11 +703,6 @@ static void rna_def_constraint_kinematic(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Lock Z Rot", "Constraint rotation along Z axis"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Constraint_dependency_update"); - prop = RNA_def_property(srna, "use_target", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_IK_AUTO); - RNA_def_property_ui_text(prop, "Target", "Disable for targetless IK"); - RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update"); - prop = RNA_def_property(srna, "use_stretch", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_IK_STRETCH); RNA_def_property_ui_text(prop, "Stretch", "Enable IK Stretching"); @@ -1243,7 +1238,7 @@ static void rna_def_constraint_follow_path(BlenderRNA *brna) prop = RNA_def_property(srna, "offset_factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "offset_fac"); RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_text(prop, "Offset Factor", "Percentage value defining target position along length of bone"); + RNA_def_property_ui_text(prop, "Offset Factor", "Percentage value defining target position along length of curve"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); prop = RNA_def_property(srna, "forward_axis", PROP_ENUM, PROP_NONE); @@ -2422,7 +2417,7 @@ void RNA_def_constraint(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "rot_error"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Rot error", - "Amount of residual error in radiant for constraints that work on orientation"); + "Amount of residual error in radians for constraints that work on orientation"); /* pointers */ rna_def_constrainttarget(brna); diff --git a/source/blender/makesrna/intern/rna_controller.c b/source/blender/makesrna/intern/rna_controller.c index 44c8a2b412b..c59e376da82 100644 --- a/source/blender/makesrna/intern/rna_controller.c +++ b/source/blender/makesrna/intern/rna_controller.c @@ -77,7 +77,7 @@ static StructRNA *rna_Controller_refine(struct PointerRNA *ptr) } } -void rna_Constroller_name_set(PointerRNA *ptr, const char *value) +static void rna_Constroller_name_set(PointerRNA *ptr, const char *value) { bController *cont = (bController *)ptr->data; @@ -240,7 +240,7 @@ void RNA_def_controller(BlenderRNA *brna) /* State */ /* array of OB_MAX_STATES */ - /*prop= RNA_def_property(srna, "states", PROP_BOOLEAN, PROP_LAYER_MEMBER); */ + /*prop = RNA_def_property(srna, "states", PROP_BOOLEAN, PROP_LAYER_MEMBER); */ /*RNA_def_property_array(prop, OB_MAX_STATES); */ /*RNA_def_property_clear_flag(prop, PROP_EDITABLE); */ /*RNA_def_property_ui_text(prop, "", "Set Controller state index (1 to 30)"); */ diff --git a/source/blender/makesrna/intern/rna_controller_api.c b/source/blender/makesrna/intern/rna_controller_api.c index 6fe90e1721b..639d6a330a5 100644 --- a/source/blender/makesrna/intern/rna_controller_api.c +++ b/source/blender/makesrna/intern/rna_controller_api.c @@ -35,6 +35,8 @@ #include "WM_types.h" #include "RNA_define.h" +#include "rna_internal.h" /* own include */ + #ifdef RNA_RUNTIME #include "BKE_sca.h" diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index b2a2bab0f4b..35699c6ef3f 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -26,6 +26,7 @@ #include +#include "RNA_access.h" #include "RNA_define.h" #include "rna_internal.h" @@ -62,9 +63,9 @@ EnumPropertyItem keyframe_handle_type_items[] = { }; EnumPropertyItem beztriple_interpolation_mode_items[] = { - {BEZT_IPO_CONST, "CONSTANT", 0, "Constant", ""}, - {BEZT_IPO_LIN, "LINEAR", 0, "Linear", ""}, - {BEZT_IPO_BEZ, "BEZIER", 0, "Bezier", ""}, + {BEZT_IPO_CONST, "CONSTANT", 0, "Constant", "No interpolation, value of A gets held until B is encountered"}, + {BEZT_IPO_LIN, "LINEAR", 0, "Linear", "Straight-line interpolation between A and B (i.e. no ease in/out)"}, + {BEZT_IPO_BEZ, "BEZIER", 0, "Bezier", "Smooth interpolation between A and B, with some control over curve shape"}, {0, NULL, 0, NULL, NULL} }; @@ -432,20 +433,20 @@ static void rna_Curve_offset_set(PointerRNA *ptr, float value) } /* name functions that ignore the first two ID characters */ -void rna_Curve_body_get(PointerRNA *ptr, char *value) +static void rna_Curve_body_get(PointerRNA *ptr, char *value) { Curve *cu = (Curve *)ptr->id.data; BLI_strncpy(value, cu->str, cu->len + 1); } -int rna_Curve_body_length(PointerRNA *ptr) +static int rna_Curve_body_length(PointerRNA *ptr) { Curve *cu = (Curve *)ptr->id.data; return cu->len; } /* TODO - check UTF & python play nice */ -void rna_Curve_body_set(PointerRNA *ptr, const char *value) +static void rna_Curve_body_set(PointerRNA *ptr, const char *value) { int len = strlen(value); Curve *cu = (Curve *)ptr->id.data; @@ -511,7 +512,7 @@ static void rna_Nurb_update_knot_v(Main *bmain, Scene *scene, PointerRNA *ptr) static void rna_Curve_spline_points_add(ID *id, Nurb *nu, ReportList *reports, int number) { if (nu->type == CU_BEZIER) { - BKE_report(reports, RPT_ERROR, "Bezier spline can't have points added"); + BKE_report(reports, RPT_ERROR, "Bezier spline cannot have points added"); } else if (number == 0) { /* do nothing */ @@ -573,20 +574,18 @@ static Nurb *rna_Curve_spline_new(Curve *cu, int type) return nu; } -static void rna_Curve_spline_remove(Curve *cu, ReportList *reports, Nurb *nu) +static void rna_Curve_spline_remove(Curve *cu, ReportList *reports, PointerRNA *nu_ptr) { - int found = 0; + Nurb *nu = nu_ptr->data; ListBase *nurbs = BKE_curve_nurbs_get(cu); - found = BLI_remlink_safe(nurbs, nu); - - if (!found) { - BKE_reportf(reports, RPT_ERROR, "Curve \"%s\" does not contain spline given", cu->id.name + 2); + if (BLI_remlink_safe(nurbs, nu) == FALSE) { + BKE_reportf(reports, RPT_ERROR, "Curve '%s' does not contain spline given", cu->id.name + 2); return; } BKE_nurb_free(nu); - /* invalidate pointer!, no can do */ + RNA_POINTER_INVALIDATE(nu_ptr); DAG_id_tag_update(&cu->id, OB_RECALC_DATA); WM_main_add_notifier(NC_GEOM | ND_DATA, NULL); @@ -721,7 +720,7 @@ static void rna_def_bpoint(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Curve_update_data"); /* Number values */ - prop = RNA_def_property(srna, "tilt", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "tilt", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "alfa"); /*RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);*/ RNA_def_property_ui_text(prop, "Tilt", "Tilt in 3D View"); @@ -808,13 +807,14 @@ static void rna_def_beztriple(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Curve_update_points"); /* Number values */ - prop = RNA_def_property(srna, "tilt", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "tilt", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "alfa"); /*RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);*/ RNA_def_property_ui_text(prop, "Tilt", "Tilt in 3D View"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); - prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "weight_softbody", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "weight"); RNA_def_property_range(prop, 0.01f, 100.0f); RNA_def_property_ui_text(prop, "Weight", "Softbody goal weight"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); @@ -1108,7 +1108,7 @@ static void rna_def_charinfo(BlenderRNA *brna) /* probably there is no reason to expose this */ #if 0 - prop= RNA_def_property(srna, "wrap", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "wrap", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_CHINFO_WRAP); RNA_def_property_ui_text(prop, "Wrap", ""); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); */ @@ -1163,14 +1163,15 @@ static void rna_def_curve_spline_points(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "add", "rna_Curve_spline_points_add"); RNA_def_function_ui_description(func, "Add a number of points to this spline"); RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS); - RNA_def_int(func, "count", 1, 1, INT_MAX, "Number", "Number of points to add to the spline", 1, INT_MAX); + RNA_def_int(func, "count", 1, 0, INT_MAX, "Number", "Number of points to add to the spline", 0, INT_MAX); #if 0 - func= RNA_def_function(srna, "remove", "rna_Curve_spline_remove"); + func = RNA_def_function(srna, "remove", "rna_Curve_spline_remove"); RNA_def_function_ui_description(func, "Remove a spline from a curve"); RNA_def_function_flag(func, FUNC_USE_REPORTS); - parm= RNA_def_pointer(func, "spline", "Spline", "", "The spline to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + parm = RNA_def_pointer(func, "spline", "Spline", "", "The spline to remove"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); #endif } @@ -1190,14 +1191,15 @@ static void rna_def_curve_spline_bezpoints(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "add", "rna_Curve_spline_bezpoints_add"); RNA_def_function_ui_description(func, "Add a number of points to this spline"); RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS); - RNA_def_int(func, "count", 1, INT_MIN, INT_MAX, "Number", "Number of points to add to the spline", 0, INT_MAX); + RNA_def_int(func, "count", 1, 0, INT_MAX, "Number", "Number of points to add to the spline", 0, INT_MAX); #if 0 func = RNA_def_function(srna, "remove", "rna_Curve_spline_remove"); RNA_def_function_ui_description(func, "Remove a spline from a curve"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "spline", "Spline", "", "The spline to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); #endif } @@ -1226,7 +1228,8 @@ static void rna_def_curve_splines(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove a spline from a curve"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "spline", "Spline", "", "The spline to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "clear", "rna_Curve_spline_clear"); RNA_def_function_ui_description(func, "Remove all spline from a curve"); diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index 45092d09ce1..bb1ecea6a24 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -42,10 +42,23 @@ #include "BLI_listbase.h" #include "BLI_ghash.h" +#include "BLF_translation.h" + #include "RNA_define.h" #include "rna_internal.h" + +#ifdef DEBUG +# define ASSERT_SOFT_HARD_LIMITS \ + if (softmin < hardmin || softmax > hardmax) { \ + fprintf(stderr, "Error with soft/hard limits: %s.%s\n", CONTAINER_RNA_ID(cont), identifier); \ + BLI_assert(!"invalid soft/hard limits"); \ + } (void)0 +#else +# define ASSERT_SOFT_HARD_LIMITS (void)0 +#endif + /* Global used during defining */ BlenderDefRNA DefRNA = {NULL, {NULL, NULL}, {NULL, NULL}, NULL, 0, 0, 0, 1}; @@ -887,7 +900,7 @@ void RNA_def_struct_translation_context(StructRNA *srna, const char *context) PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier, int type, int subtype) { - /*StructRNA *srna= DefRNA.laststruct;*/ /* invalid for python defined props */ + /*StructRNA *srna = DefRNA.laststruct;*/ /* invalid for python defined props */ ContainerRNA *cont = cont_; ContainerDefRNA *dcont; PropertyDefRNA *dprop = NULL; @@ -968,8 +981,10 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier sprop->defaultvalue = ""; break; } - case PROP_ENUM: case PROP_POINTER: + prop->flag |= PROP_THICK_WRAP; /* needed for default behavior when PROP_RNAPTR is set */ + break; + case PROP_ENUM: case PROP_COLLECTION: break; default: @@ -2248,12 +2263,15 @@ PropertyRNA *RNA_def_boolean_vector(StructOrFunctionRNA *cont_, const char *iden return prop; } -PropertyRNA *RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int default_value, int hardmin, - int hardmax, const char *ui_name, const char *ui_description, int softmin, int softmax) +PropertyRNA *RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int default_value, + int hardmin, int hardmax, const char *ui_name, const char *ui_description, + int softmin, int softmax) { ContainerRNA *cont = cont_; PropertyRNA *prop; + ASSERT_SOFT_HARD_LIMITS; + prop = RNA_def_property(cont, identifier, PROP_INT, PROP_NONE); RNA_def_property_int_default(prop, default_value); if (hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax); @@ -2270,6 +2288,8 @@ PropertyRNA *RNA_def_int_vector(StructOrFunctionRNA *cont_, const char *identifi ContainerRNA *cont = cont_; PropertyRNA *prop; + ASSERT_SOFT_HARD_LIMITS; + prop = RNA_def_property(cont, identifier, PROP_INT, PROP_XYZ); /* XXX */ if (len != 0) RNA_def_property_array(prop, len); if (default_value) RNA_def_property_int_array_default(prop, default_value); @@ -2287,6 +2307,8 @@ PropertyRNA *RNA_def_int_array(StructOrFunctionRNA *cont_, const char *identifie ContainerRNA *cont = cont_; PropertyRNA *prop; + ASSERT_SOFT_HARD_LIMITS; + prop = RNA_def_property(cont, identifier, PROP_INT, PROP_NONE); if (len != 0) RNA_def_property_array(prop, len); if (default_value) RNA_def_property_int_array_default(prop, default_value); @@ -2426,6 +2448,8 @@ PropertyRNA *RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, f ContainerRNA *cont = cont_; PropertyRNA *prop; + ASSERT_SOFT_HARD_LIMITS; + prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_NONE); RNA_def_property_float_default(prop, default_value); if (hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax); @@ -2442,6 +2466,8 @@ PropertyRNA *RNA_def_float_vector(StructOrFunctionRNA *cont_, const char *identi ContainerRNA *cont = cont_; PropertyRNA *prop; + ASSERT_SOFT_HARD_LIMITS; + prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_XYZ); if (len != 0) RNA_def_property_array(prop, len); if (default_value) RNA_def_property_float_array_default(prop, default_value); @@ -2472,6 +2498,8 @@ PropertyRNA *RNA_def_float_color(StructOrFunctionRNA *cont_, const char *identif ContainerRNA *cont = cont_; PropertyRNA *prop; + ASSERT_SOFT_HARD_LIMITS; + prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_COLOR); if (len != 0) RNA_def_property_array(prop, len); if (default_value) RNA_def_property_float_array_default(prop, default_value); @@ -2489,10 +2517,9 @@ PropertyRNA *RNA_def_float_matrix(StructOrFunctionRNA *cont_, const char *identi { ContainerRNA *cont = cont_; PropertyRNA *prop; - int length[2]; + const int length[2] = {rows, columns}; - length[0] = rows; - length[1] = columns; + ASSERT_SOFT_HARD_LIMITS; prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_MATRIX); RNA_def_property_multi_array(prop, 2, length); @@ -2510,7 +2537,9 @@ PropertyRNA *RNA_def_float_rotation(StructOrFunctionRNA *cont_, const char *iden { ContainerRNA *cont = cont_; PropertyRNA *prop; - + + ASSERT_SOFT_HARD_LIMITS; + prop = RNA_def_property(cont, identifier, PROP_FLOAT, (len != 0) ? PROP_EULER : PROP_ANGLE); if (len != 0) { RNA_def_property_array(prop, len); @@ -2534,6 +2563,8 @@ PropertyRNA *RNA_def_float_array(StructOrFunctionRNA *cont_, const char *identif ContainerRNA *cont = cont_; PropertyRNA *prop; + ASSERT_SOFT_HARD_LIMITS; + prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_NONE); if (len != 0) RNA_def_property_array(prop, len); if (default_value) RNA_def_property_float_array_default(prop, default_value); @@ -2551,6 +2582,8 @@ PropertyRNA *RNA_def_float_percentage(StructOrFunctionRNA *cont_, const char *id ContainerRNA *cont = cont_; PropertyRNA *prop; + ASSERT_SOFT_HARD_LIMITS; + prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_PERCENTAGE); RNA_def_property_float_default(prop, default_value); if (hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax); @@ -2567,6 +2600,8 @@ PropertyRNA *RNA_def_float_factor(StructOrFunctionRNA *cont_, const char *identi ContainerRNA *cont = cont_; PropertyRNA *prop; + ASSERT_SOFT_HARD_LIMITS; + prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_default(prop, default_value); if (hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax); @@ -2777,14 +2812,26 @@ int rna_parameter_size(PropertyRNA *parm) { #ifdef RNA_RUNTIME if (parm->flag & PROP_RNAPTR) - return sizeof(PointerRNA); + if (parm->flag & PROP_THICK_WRAP) { + return sizeof(PointerRNA); + } + else { + return sizeof(PointerRNA *); + } else return sizeof(void *); #else - if (parm->flag & PROP_RNAPTR) - return sizeof(PointerRNA); - else + if (parm->flag & PROP_RNAPTR) { + if (parm->flag & PROP_THICK_WRAP) { + return sizeof(PointerRNA); + } + else { + return sizeof(PointerRNA *); + } + } + else { return sizeof(void *); + } #endif } case PROP_COLLECTION: diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index a0d64723a5c..4250acf5848 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -403,20 +403,22 @@ static void rna_FCurve_group_set(PointerRNA *ptr, PointerRNA value) } } -DriverVar *rna_Driver_new_variable(ChannelDriver *driver) +static DriverVar *rna_Driver_new_variable(ChannelDriver *driver) { /* call the API function for this */ return driver_add_new_variable(driver); } -void rna_Driver_remove_variable(ChannelDriver *driver, ReportList *reports, DriverVar *dvar) +static void rna_Driver_remove_variable(ChannelDriver *driver, ReportList *reports, PointerRNA *dvar_ptr) { + DriverVar *dvar = dvar_ptr->data; if (BLI_findindex(&driver->variables, dvar) == -1) { BKE_report(reports, RPT_ERROR, "Variable does not exist in this driver"); return; } driver_free_variable(driver, dvar); + RNA_POINTER_INVALIDATE(dvar_ptr); } @@ -438,13 +440,16 @@ static FModifier *rna_FCurve_modifiers_new(FCurve *fcu, int type) return add_fmodifier(&fcu->modifiers, type); } -static void rna_FCurve_modifiers_remove(FCurve *fcu, ReportList *reports, FModifier *fcm) +static void rna_FCurve_modifiers_remove(FCurve *fcu, ReportList *reports, PointerRNA *fcm_ptr) { + FModifier *fcm = fcm_ptr->data; if (BLI_findindex(&fcu->modifiers, fcm) == -1) { BKE_reportf(reports, RPT_ERROR, "F-Curve modifier '%s' not found in F-Curve", fcm->name); return; } + remove_fmodifier(&fcu->modifiers, fcm); + RNA_POINTER_INVALIDATE(fcm_ptr); } static void rna_FModifier_active_set(PointerRNA *ptr, int UNUSED(value)) @@ -610,8 +615,9 @@ static void rna_FKeyframe_points_add(FCurve *fcu, int tot) } } -static void rna_FKeyframe_points_remove(FCurve *fcu, ReportList *reports, BezTriple *bezt, int do_fast) +static void rna_FKeyframe_points_remove(FCurve *fcu, ReportList *reports, PointerRNA *bezt_ptr, int do_fast) { + BezTriple *bezt = bezt_ptr->data; int index = (int)(bezt - fcu->bezt); if (index < 0 || index >= fcu->totvert) { BKE_report(reports, RPT_ERROR, "Keyframe not in F-Curve"); @@ -619,6 +625,7 @@ static void rna_FKeyframe_points_remove(FCurve *fcu, ReportList *reports, BezTri } delete_fcurve_key(fcu, index, !do_fast); + RNA_POINTER_INVALIDATE(bezt_ptr); } static void rna_fcurve_range(FCurve *fcu, float range[2]) @@ -1263,7 +1270,8 @@ static void rna_def_channeldriver_variables(BlenderRNA *brna, PropertyRNA *cprop RNA_def_function_flag(func, FUNC_USE_REPORTS); /* target to remove */ parm = RNA_def_pointer(func, "variable", "DriverVariable", "", "Variable to remove from the driver"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } static void rna_def_channeldriver(BlenderRNA *brna) @@ -1458,7 +1466,8 @@ static void rna_def_fcurve_modifiers(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove a modifier from this F-Curve"); /* modifier to remove */ parm = RNA_def_pointer(func, "modifier", "FModifier", "", "Removed modifier"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } /* fcurve.keyframe_points */ @@ -1497,13 +1506,14 @@ static void rna_def_fcurve_keyframe_points(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "add", "rna_FKeyframe_points_add"); RNA_def_function_ui_description(func, "Add a keyframe point to a F-Curve"); - RNA_def_int(func, "count", 1, 1, INT_MAX, "Number", "Number of points to add to the spline", 1, INT_MAX); + RNA_def_int(func, "count", 1, 0, INT_MAX, "Number", "Number of points to add to the spline", 0, INT_MAX); func = RNA_def_function(srna, "remove", "rna_FKeyframe_points_remove"); RNA_def_function_ui_description(func, "Remove keyframe from an F-Curve"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "keyframe", "Keyframe", "", "Keyframe to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); /* optional */ RNA_def_boolean(func, "fast", 0, "Fast", "Fast keyframe removal to avoid recalculating the curve each time"); } diff --git a/source/blender/makesrna/intern/rna_fcurve_api.c b/source/blender/makesrna/intern/rna_fcurve_api.c index 1f8b827f320..ab96f6f384d 100644 --- a/source/blender/makesrna/intern/rna_fcurve_api.c +++ b/source/blender/makesrna/intern/rna_fcurve_api.c @@ -34,10 +34,14 @@ #include #include +#include "BLI_utildefines.h" + #include "RNA_define.h" #include "DNA_anim_types.h" +#include "rna_internal.h" /* own include */ + #ifdef RNA_RUNTIME #include @@ -47,7 +51,7 @@ #else -void RNA_api_drivers(StructRNA *srna) +void RNA_api_drivers(StructRNA *UNUSED(srna)) { /* FunctionRNA *func; */ /* PropertyRNA *parm; */ diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c index daa661175a1..84ff53ee68f 100644 --- a/source/blender/makesrna/intern/rna_fluidsim.c +++ b/source/blender/makesrna/intern/rna_fluidsim.c @@ -699,7 +699,7 @@ void RNA_def_fluidsim(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Type", "Type of participation in the fluid simulation"); RNA_def_property_update(prop, 0, "rna_FluidSettings_update_type"); - /*prop= RNA_def_property(srna, "ipo", PROP_POINTER, PROP_NONE); */ + /*prop = RNA_def_property(srna, "ipo", PROP_POINTER, PROP_NONE); */ /*RNA_def_property_ui_text(prop, "IPO Curves", "IPO curves used by fluid simulation settings"); */ /* types */ diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index eb12a02aa99..b3c1f4dd505 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -27,6 +27,7 @@ #include +#include "RNA_access.h" #include "RNA_define.h" #include "rna_internal.h" @@ -40,6 +41,15 @@ #ifdef RNA_RUNTIME +#include "WM_api.h" + +#include "BKE_gpencil.h" + +static void rna_GPencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) +{ + WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); +} + static int rna_GPencilLayer_active_frame_editable(PointerRNA *ptr) { bGPDlayer *gpl = (bGPDlayer *)ptr->data; @@ -53,6 +63,7 @@ static int rna_GPencilLayer_active_frame_editable(PointerRNA *ptr) static PointerRNA rna_GPencil_active_layer_get(PointerRNA *ptr) { + bGPdata *gpd = ptr->id.data; if (GS(gpd->id.name) == ID_GD) { /* why would this ever be not GD */ @@ -90,7 +101,7 @@ static void rna_GPencil_active_layer_set(PointerRNA *ptr, PointerRNA value) } } -void rna_GPencilLayer_info_set(PointerRNA *ptr, const char *value) +static void rna_GPencilLayer_info_set(PointerRNA *ptr, const char *value) { bGPdata *gpd = ptr->id.data; bGPDlayer *gpl = ptr->data; @@ -101,6 +112,160 @@ void rna_GPencilLayer_info_set(PointerRNA *ptr, const char *value) BLI_uniquename(&gpd->layers, gpl, "GP_Layer", '.', offsetof(bGPDlayer, info), sizeof(gpl->info)); } +static void rna_GPencil_stroke_point_add(bGPDstroke *stroke, int count) +{ + if (count > 0) { + if (stroke->points == NULL) + stroke->points = MEM_callocN(sizeof(bGPDspoint) * count, "gp_stroke_points"); + else + stroke->points = MEM_reallocN(stroke->points, sizeof(bGPDspoint) * (stroke->totpoints + count)); + + stroke->totpoints += count; + } +} + +static void rna_GPencil_stroke_point_pop(bGPDstroke *stroke, ReportList *reports, int index) +{ + bGPDspoint *pt_tmp = stroke->points; + + /* python style negative indexing */ + if (index < 0) { + index += stroke->totpoints; + } + + if (stroke->totpoints <= index || index < 0) { + BKE_report(reports, RPT_ERROR, "GPencilStrokePoints.pop: index out of range"); + return; + } + + stroke->totpoints--; + + stroke->points = MEM_callocN(sizeof(bGPDspoint) * stroke->totpoints, "gp_stroke_points"); + + if (index > 0) + memcpy(stroke->points, pt_tmp, sizeof(bGPDspoint) * index); + + if (index < stroke->totpoints) + memcpy(&stroke->points[index], &pt_tmp[index + 1], sizeof(bGPDspoint) * (stroke->totpoints - index)); + + /* free temp buffer */ + MEM_freeN(pt_tmp); + + WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); +} + +static bGPDstroke *rna_GPencil_stroke_new(bGPDframe *frame) +{ + bGPDstroke *stroke = MEM_callocN(sizeof(bGPDstroke), "gp_stroke"); + + BLI_addtail(&frame->strokes, stroke); + + return stroke; +} + +static void rna_GPencil_stroke_remove(bGPDframe *frame, ReportList *reports, PointerRNA *stroke_ptr) +{ + bGPDstroke *stroke = stroke_ptr->data; + if (BLI_findindex(&frame->strokes, stroke) == -1) { + BKE_report(reports, RPT_ERROR, "Stroke not found in grease pencil frame"); + return; + } + + BLI_freelinkN(&frame->strokes, stroke); + RNA_POINTER_INVALIDATE(stroke_ptr); + + WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); +} + +static bGPDframe *rna_GPencil_frame_new(bGPDlayer *layer, ReportList *reports, int frame_number) +{ + bGPDframe *frame; + + if (BKE_gpencil_layer_find_frame(layer, frame_number)) { + BKE_reportf(reports, RPT_ERROR, "Frame already exists on this frame number %d", frame_number); + return NULL; + } + + frame = gpencil_frame_addnew(layer, frame_number); + + WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); + + return frame; +} + +static void rna_GPencil_frame_remove(bGPDlayer *layer, ReportList *reports, PointerRNA *frame_ptr) +{ + bGPDframe *frame = frame_ptr->data; + if (BLI_findindex(&layer->frames, frame) == -1) { + BKE_report(reports, RPT_ERROR, "Frame not found in grease pencil layer"); + return; + } + + gpencil_layer_delframe(layer, frame); + RNA_POINTER_INVALIDATE(frame_ptr); + + WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); +} + +static bGPDframe *rna_GPencil_frame_copy(bGPDlayer *layer, bGPDframe *src) +{ + bGPDframe *frame = gpencil_frame_duplicate(src); + + while (BKE_gpencil_layer_find_frame(layer, frame->framenum)) { + frame->framenum++; + } + + BLI_addtail(&layer->frames, frame); + + WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); + + return frame; +} + +static bGPDlayer *rna_GPencil_layer_new(bGPdata *gpd, const char *name, int setactive) +{ + bGPDlayer *gl = gpencil_layer_addnew(gpd, name, setactive); + + WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + + return gl; +} + +static void rna_GPencil_layer_remove(bGPdata *gpd, ReportList *reports, PointerRNA *layer_ptr) +{ + bGPDlayer *layer = layer_ptr->data; + if (BLI_findindex(&gpd->layers, layer) == -1) { + BKE_report(reports, RPT_ERROR, "Layer not found in grease pencil data"); + return; + } + + gpencil_layer_delete(gpd, layer); + RNA_POINTER_INVALIDATE(layer_ptr); + + WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); +} + +static void rna_GPencil_frame_clear(bGPDframe *frame) +{ + free_gpencil_strokes(frame); + + WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); +} + +static void rna_GPencil_layer_clear(bGPDlayer *layer) +{ + free_gpencil_frames(layer); + + WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); +} + +static void rna_GPencil_clear(bGPdata *gpd) +{ + free_gpencil_layers(&gpd->layers); + + WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); +} + #else static void rna_def_gpencil_stroke_point(BlenderRNA *brna) @@ -116,19 +281,49 @@ static void rna_def_gpencil_stroke_point(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "x"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Coordinates", ""); - RNA_def_property_update(prop, NC_SCREEN | ND_GPENCIL, NULL); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); prop = RNA_def_property(srna, "pressure", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "pressure"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Pressure", "Pressure of tablet at point when drawing it"); - RNA_def_property_update(prop, NC_SCREEN | ND_GPENCIL, NULL); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); +} + +static void rna_def_gpencil_stroke_points_api(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + + FunctionRNA *func; + /* PropertyRNA *parm; */ + + RNA_def_property_srna(cprop, "GPencilStrokePoints"); + srna = RNA_def_struct(brna, "GPencilStrokePoints", NULL); + RNA_def_struct_sdna(srna, "bGPDstroke"); + RNA_def_struct_ui_text(srna, "Grease Pencil Stroke Points", "Collection of grease pencil stroke points"); + + func = RNA_def_function(srna, "add", "rna_GPencil_stroke_point_add"); + RNA_def_function_ui_description(func, "Add a new grease pencil stroke point"); + RNA_def_int(func, "count", 1, 0, INT_MAX, "Number", "Number of points to add to the stroke", 0, INT_MAX); + + func = RNA_def_function(srna, "pop", "rna_GPencil_stroke_point_pop"); + RNA_def_function_ui_description(func, "Remove a grease pencil stroke point"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_int(func, "index", -1, INT_MIN, INT_MAX, "Index", "point index", INT_MIN, INT_MAX); } static void rna_def_gpencil_stroke(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; + + static EnumPropertyItem stroke_draw_mode_items[] = { + {0, "SCREEN", 0, "Screen", "Stroke is in screen-space"}, + {GP_STROKE_3DSPACE, "3DSPACE", 0, "3D Space", "Stroke is in 3D-space"}, + {GP_STROKE_2DSPACE, "2DSPACE", 0, "2D Space", "Stroke is in 2D-space"}, + {GP_STROKE_2DIMAGE, "2DIMAGE", 0, "2D Image", "Stroke is in 2D-space (but with special 'image' scaling)"}, + {0, NULL, 0, NULL, NULL} + }; srna = RNA_def_struct(brna, "GPencilStroke", NULL); RNA_def_struct_sdna(srna, "bGPDstroke"); @@ -139,15 +334,46 @@ static void rna_def_gpencil_stroke(BlenderRNA *brna) RNA_def_property_collection_sdna(prop, NULL, "points", "totpoints"); RNA_def_property_struct_type(prop, "GPencilStrokePoint"); RNA_def_property_ui_text(prop, "Stroke Points", "Stroke data points"); - - /* Flags - Readonly type-info really... */ - /* TODO... */ + rna_def_gpencil_stroke_points_api(brna, prop); + + prop = RNA_def_property(srna, "draw_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); + RNA_def_property_enum_items(prop, stroke_draw_mode_items); + RNA_def_property_ui_text(prop, "Draw Mode", ""); + RNA_def_property_update(prop, 0, "rna_GPencil_update"); +} + +static void rna_def_gpencil_strokes_api(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "GPencilStrokes"); + srna = RNA_def_struct(brna, "GPencilStrokes", NULL); + RNA_def_struct_sdna(srna, "bGPDframe"); + RNA_def_struct_ui_text(srna, "Grease Pencil Frames", "Collection of grease pencil frames"); + + func = RNA_def_function(srna, "new", "rna_GPencil_stroke_new"); + RNA_def_function_ui_description(func, "Add a new grease pencil frame"); + parm = RNA_def_pointer(func, "stroke", "GPencilStroke", "", "The newly created stroke"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_GPencil_stroke_remove"); + RNA_def_function_ui_description(func, "Remove a grease pencil frame"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "stroke", "GPencilStroke", "Stroke", "The stroke to remove"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } static void rna_def_gpencil_frame(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; + + FunctionRNA *func; srna = RNA_def_struct(brna, "GPencilFrame", NULL); RNA_def_struct_sdna(srna, "bGPDframe"); @@ -158,7 +384,8 @@ static void rna_def_gpencil_frame(BlenderRNA *brna) RNA_def_property_collection_sdna(prop, NULL, "strokes", NULL); RNA_def_property_struct_type(prop, "GPencilStroke"); RNA_def_property_ui_text(prop, "Strokes", "Freehand curves defining the sketch on this frame"); - + rna_def_gpencil_strokes_api(brna, prop); + /* Frame Number */ prop = RNA_def_property(srna, "frame_number", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "framenum"); @@ -173,12 +400,52 @@ static void rna_def_gpencil_frame(BlenderRNA *brna) prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_FRAME_SELECT); RNA_def_property_ui_text(prop, "Select", "Frame is selected for editing in the DopeSheet"); + + func = RNA_def_function(srna, "clear", "rna_GPencil_frame_clear"); + RNA_def_function_ui_description(func, "Remove all the grease pencil frame data"); +} + +static void rna_def_gpencil_frames_api(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "GPencilFrames"); + srna = RNA_def_struct(brna, "GPencilFrames", NULL); + RNA_def_struct_sdna(srna, "bGPDlayer"); + RNA_def_struct_ui_text(srna, "Grease Pencil Frames", "Collection of grease pencil frames"); + + func = RNA_def_function(srna, "new", "rna_GPencil_frame_new"); + RNA_def_function_ui_description(func, "Add a new grease pencil frame"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_int(func, "frame_number", 1, MINFRAME, MAXFRAME, "Frame Number", "The frame on which this sketch appears", MINFRAME, MAXFRAME); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm = RNA_def_pointer(func, "frame", "GPencilFrame", "", "The newly created frame"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_GPencil_frame_remove"); + RNA_def_function_ui_description(func, "Remove a grease pencil frame"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "frame", "GPencilFrame", "Frame", "The frame to remove"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); + + func = RNA_def_function(srna, "copy", "rna_GPencil_frame_copy"); + RNA_def_function_ui_description(func, "Copy a grease pencil frame"); + parm = RNA_def_pointer(func, "source", "GPencilFrame", "Source", "The source frame"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + parm = RNA_def_pointer(func, "copy", "GPencilFrame", "", "The newly copied frame"); + RNA_def_function_return(func, parm); } static void rna_def_gpencil_layer(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; + + FunctionRNA *func; srna = RNA_def_struct(brna, "GPencilLayer", NULL); RNA_def_struct_sdna(srna, "bGPDlayer"); @@ -189,44 +456,47 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Info", "Layer name"); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_GPencilLayer_info_set"); RNA_def_struct_name_property(srna, prop); - + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + /* Frames */ prop = RNA_def_property(srna, "frames", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "frames", NULL); RNA_def_property_struct_type(prop, "GPencilFrame"); RNA_def_property_ui_text(prop, "Frames", "Sketches for this layer on different frames"); - + rna_def_gpencil_frames_api(brna, prop); + /* Active Frame */ prop = RNA_def_property(srna, "active_frame", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "actframe"); RNA_def_property_ui_text(prop, "Active Frame", "Frame currently being displayed for this layer"); RNA_def_property_editable_func(prop, "rna_GPencilLayer_active_frame_editable"); - + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + /* Drawing Color */ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Color", "Color for all strokes in this layer"); - RNA_def_property_update(prop, NC_SCREEN | ND_GPENCIL, NULL); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); prop = RNA_def_property(srna, "alpha", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "color[3]"); RNA_def_property_range(prop, 0.3, 1.0f); RNA_def_property_ui_text(prop, "Opacity", "Layer Opacity"); - RNA_def_property_update(prop, NC_SCREEN | ND_GPENCIL, NULL); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); /* Line Thickness */ prop = RNA_def_property(srna, "line_width", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "thickness"); RNA_def_property_range(prop, 1, 10); RNA_def_property_ui_text(prop, "Thickness", "Thickness of strokes (in pixels)"); - RNA_def_property_update(prop, NC_SCREEN | ND_GPENCIL, NULL); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); /* Onion-Skinning */ prop = RNA_def_property(srna, "use_onion_skinning", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_ONIONSKIN); RNA_def_property_ui_text(prop, "Onion Skinning", "Ghost frames on either side of frame"); - RNA_def_property_update(prop, NC_SCREEN | ND_GPENCIL, NULL); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); prop = RNA_def_property(srna, "ghost_range_max", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "gstep"); @@ -234,23 +504,23 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Max Ghost Range", "Maximum number of frames on either side of the active frame to show " "(0 = show the 'first' available sketch on either side)"); - RNA_def_property_update(prop, NC_SCREEN | ND_GPENCIL, NULL); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); /* Flags */ prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_HIDE); RNA_def_property_ui_text(prop, "Hide", "Set layer Visibility"); - RNA_def_property_update(prop, NC_SCREEN | ND_GPENCIL, NULL); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_LOCKED); RNA_def_property_ui_text(prop, "Locked", "Protect layer from further editing and/or frame changes"); - RNA_def_property_update(prop, NC_SCREEN | ND_GPENCIL, NULL); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); prop = RNA_def_property(srna, "lock_frame", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_FRAMELOCK); RNA_def_property_ui_text(prop, "Frame Locked", "Lock current frame displayed by layer"); - RNA_def_property_update(prop, NC_SCREEN | ND_GPENCIL, NULL); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); /* expose as layers.active */ #if 0 @@ -258,54 +528,57 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_ACTIVE); RNA_def_property_boolean_funcs(prop, NULL, "rna_GPencilLayer_active_set"); RNA_def_property_ui_text(prop, "Active", "Set active layer for editing"); - RNA_def_property_update(prop, NC_SCREEN | ND_GPENCIL, NULL); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); #endif prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_SELECT); RNA_def_property_ui_text(prop, "Select", "Layer is selected for editing in the DopeSheet"); - RNA_def_property_update(prop, NC_SCREEN | ND_GPENCIL, NULL); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); /* XXX keep this option? */ prop = RNA_def_property(srna, "show_points", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_DRAWDEBUG); RNA_def_property_ui_text(prop, "Show Points", "Draw the points which make up the strokes (for debugging purposes)"); - RNA_def_property_update(prop, NC_SCREEN | ND_GPENCIL, NULL); + RNA_def_property_update_runtime(prop, "rna_GPencil_update"); /* X-Ray */ prop = RNA_def_property(srna, "show_x_ray", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GP_LAYER_NO_XRAY); RNA_def_property_ui_text(prop, "X Ray", "Make the layer draw in front of objects"); - RNA_def_property_update(prop, NC_SCREEN | ND_GPENCIL, NULL); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); + + func = RNA_def_function(srna, "clear", "rna_GPencil_layer_clear"); + RNA_def_function_ui_description(func, "Remove all the grease pencil layer data"); } -static void rna_def_gpencil_layers(BlenderRNA *brna, PropertyRNA *cprop) +static void rna_def_gpencil_layers_api(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; PropertyRNA *prop; -/* FunctionRNA *func; */ -/* PropertyRNA *parm; */ + FunctionRNA *func; + PropertyRNA *parm; RNA_def_property_srna(cprop, "GreasePencilLayers"); srna = RNA_def_struct(brna, "GreasePencilLayers", NULL); RNA_def_struct_sdna(srna, "bGPdata"); RNA_def_struct_ui_text(srna, "Grease Pencil Layers", "Collection of grease pencil layers"); -#if 0 func = RNA_def_function(srna, "new", "rna_GPencil_layer_new"); - RNA_def_function_ui_description(func, "Add a new spline to the curve"); - parm = RNA_def_enum(func, "type", curve_type_items, CU_POLY, "", "type for the new spline"); + RNA_def_function_ui_description(func, "Add a new grease pencil layer"); + parm = RNA_def_string(func, "name", "GPencilLayer", MAX_NAME, "Name", "Name of the layer"); RNA_def_property_flag(parm, PROP_REQUIRED); - parm = RNA_def_pointer(func, "spline", "Spline", "", "The newly created spline"); + RNA_def_boolean(func, "set_active", 0, "Set Active", "Set the newly created layer to the active layer"); + parm = RNA_def_pointer(func, "layer", "GPencilLayer", "", "The newly created layer"); RNA_def_function_return(func, parm); func = RNA_def_function(srna, "remove", "rna_GPencil_layer_remove"); - RNA_def_function_ui_description(func, "Remove a spline from a curve"); + RNA_def_function_ui_description(func, "Remove a grease pencil layer"); RNA_def_function_flag(func, FUNC_USE_REPORTS); - parm = RNA_def_pointer(func, "spline", "Spline", "", "The spline to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); -#endif + parm = RNA_def_pointer(func, "layer", "GPencilLayer", "", "The layer to remove"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "GreasePencil"); @@ -318,7 +591,8 @@ static void rna_def_gpencil_data(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + FunctionRNA *func; + static EnumPropertyItem draw_mode_items[] = { {GP_DATA_VIEWALIGN, "CURSOR", 0, "Cursor", "Draw stroke at the 3D cursor"}, {0, "VIEW", 0, "View", "Stick stroke to the view "}, /* weird, GP_DATA_VIEWALIGN is inverted */ @@ -337,19 +611,22 @@ static void rna_def_gpencil_data(BlenderRNA *brna) RNA_def_property_collection_sdna(prop, NULL, "layers", NULL); RNA_def_property_struct_type(prop, "GPencilLayer"); RNA_def_property_ui_text(prop, "Layers", ""); - rna_def_gpencil_layers(brna, prop); + rna_def_gpencil_layers_api(brna, prop); /* Flags */ prop = RNA_def_property(srna, "draw_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); RNA_def_property_enum_items(prop, draw_mode_items); RNA_def_property_ui_text(prop, "Draw Mode", ""); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); prop = RNA_def_property(srna, "use_stroke_endpoints", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_DATA_DEPTH_STROKE_ENDPOINTS); RNA_def_property_ui_text(prop, "Only Endpoints", "Only use the first and last parts of the stroke for snapping"); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); - + func = RNA_def_function(srna, "clear", "rna_GPencil_clear"); + RNA_def_function_ui_description(func, "Remove all the grease pencil data"); } /* --- */ diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c index 586b71aa2da..4baf46fd0b5 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)) { - BKE_reportf(reports, RPT_ERROR, "Object \"%s\" already in group \"%s\"", object->id.name + 2, group->id.name + 2); + 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)) { - BKE_reportf(reports, RPT_ERROR, "Object \"%s\" not in group \"%s\"", object->id.name + 2, group->id.name + 2); + 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_image.c b/source/blender/makesrna/intern/rna_image.c index 495d60df49c..f8af2427827 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -147,10 +147,10 @@ static void rna_ImageUser_update(Main *UNUSED(bmain), Scene *scene, PointerRNA * } -char *rna_ImageUser_path(PointerRNA *ptr) +static char *rna_ImageUser_path(PointerRNA *ptr) { if (ptr->id.data) { - /* ImageUser *iuser= ptr->data; */ + /* ImageUser *iuser = ptr->data; */ switch (GS(((ID *)ptr->id.data)->name)) { case ID_TE: @@ -366,7 +366,7 @@ static void rna_Image_pixels_set(PointerRNA *ptr, const float *values) ((unsigned char *)ibuf->rect)[i] = FTOCHAR(values[i]); } - ibuf->userflags |= IB_BITMAPDIRTY; + ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID; } BKE_image_release_ibuf(ima, lock); @@ -388,24 +388,27 @@ static void rna_def_imageuser(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_ANIM_ALWAYS); RNA_def_property_ui_text(prop, "Auto Refresh", "Always refresh image on frame changes"); RNA_def_property_update(prop, 0, "rna_ImageUser_update"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* animation */ prop = RNA_def_property(srna, "use_cyclic", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cycl", 0); RNA_def_property_ui_text(prop, "Cyclic", "Cycle the images in the movie"); RNA_def_property_update(prop, 0, "rna_ImageUser_update"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); prop = RNA_def_property(srna, "frame_duration", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "frames"); RNA_def_property_range(prop, 0, MAXFRAMEF); RNA_def_property_ui_text(prop, "Frames", "Number of images of a movie to use"); RNA_def_property_update(prop, 0, "rna_ImageUser_update"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); prop = RNA_def_property(srna, "frame_offset", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "offset"); - RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF); RNA_def_property_ui_text(prop, "Offset", "Offset the number of the frame to use in the animation"); RNA_def_property_update(prop, 0, "rna_ImageUser_update"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "sfra"); @@ -413,12 +416,14 @@ static void rna_def_imageuser(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Start Frame", "Global starting frame of the movie/sequence, assuming first picture has a #1"); RNA_def_property_update(prop, 0, "rna_ImageUser_update"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); prop = RNA_def_property(srna, "fields_per_frame", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "fie_ima"); RNA_def_property_range(prop, 1, 200); RNA_def_property_ui_text(prop, "Fields per Frame", "Number of fields per rendered frame (2 fields is 1 image)"); RNA_def_property_update(prop, 0, "rna_ImageUser_update"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); prop = RNA_def_property(srna, "multilayer_layer", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "layer"); @@ -500,7 +505,8 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_FIELDS); RNA_def_property_ui_text(prop, "Fields", "Use fields of the image"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_fields_update"); - + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + prop = RNA_def_property(srna, "use_premultiply", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_DO_PREMUL); RNA_def_property_ui_text(prop, "Premultiply", "Convert RGB from key alpha to premultiplied alpha"); @@ -529,23 +535,27 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_enum_items(prop, image_generated_type_items); RNA_def_property_ui_text(prop, "Generated Type", "Generated image type"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update"); - + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + prop = RNA_def_property(srna, "generated_width", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "gen_x"); RNA_def_property_range(prop, 1, 16384); RNA_def_property_ui_text(prop, "Generated Width", "Generated image width"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update"); - + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + prop = RNA_def_property(srna, "generated_height", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "gen_y"); RNA_def_property_range(prop, 1, 16384); RNA_def_property_ui_text(prop, "Generated Height", "Generated image height"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update"); - + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + prop = RNA_def_property(srna, "use_generated_float", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "gen_flag", IMA_GEN_FLOAT); RNA_def_property_ui_text(prop, "Float Buffer", "Generate floating point buffer"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* realtime properties */ prop = RNA_def_property(srna, "mapping", PROP_ENUM, PROP_NONE); @@ -660,7 +670,7 @@ static void rna_def_image(BlenderRNA *brna) prop = RNA_def_property(srna, "colorspace_settings", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "colorspace_settings"); RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings"); - RNA_def_property_ui_text(prop, "Colorspace Settings", "Input color space settings"); + RNA_def_property_ui_text(prop, "Color Space Settings", "Input color space settings"); RNA_api_image(srna); } diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index c66c0085763..cb5c515ce1f 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -41,6 +41,8 @@ #include "BIF_gl.h" +#include "rna_internal.h" /* own include */ + #ifdef RNA_RUNTIME #include "BKE_image.h" @@ -78,26 +80,29 @@ static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); if (ibuf == NULL) { - BKE_reportf(reports, RPT_ERROR, "Couldn't acquire buffer from image"); + BKE_report(reports, RPT_ERROR, "Could not acquire buffer from image"); } else { - ImBuf *write_ibuf = IMB_dupImBuf(ibuf); + ImBuf *write_ibuf; - IMB_display_buffer_to_imbuf_rect(write_ibuf, &scene->view_settings, &scene->display_settings); + write_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, TRUE, TRUE, &scene->view_settings, + &scene->display_settings, &scene->r.im_format); write_ibuf->planes = scene->r.im_format.planes; write_ibuf->dither = scene->r.dither_intensity; if (!BKE_imbuf_write(write_ibuf, path, &scene->r.im_format)) { - BKE_reportf(reports, RPT_ERROR, "Couldn't write image: %s", path); + BKE_reportf(reports, RPT_ERROR, "Could not write image '%s'", path); } - IMB_freeImBuf(write_ibuf); + + if (write_ibuf != ibuf) + IMB_freeImBuf(write_ibuf); } BKE_image_release_ibuf(image, lock); } else { - BKE_reportf(reports, RPT_ERROR, "Scene not in context, couldn't get save parameters"); + BKE_report(reports, RPT_ERROR, "Scene not in context, could not get save parameters"); } } @@ -111,7 +116,7 @@ static void rna_Image_save(Image *image, ReportList *reports) if (image->packedfile) { if (writePackedFile(reports, image->name, image->packedfile, 0) != RET_OK) { - BKE_reportf(reports, RPT_ERROR, "Image \"%s\" could saved packed file to \"%s\"", image->id.name + 2, image->name); + BKE_reportf(reports, RPT_ERROR, "Image '%s' could not save packed file to '%s'", image->id.name + 2, image->name); } } else if (IMB_saveiff(ibuf, filename, ibuf->flags)) { @@ -125,11 +130,11 @@ static void rna_Image_save(Image *image, ReportList *reports) ibuf->userflags &= ~IB_BITMAPDIRTY; } else { - BKE_reportf(reports, RPT_ERROR, "Image \"%s\" could not be saved to \"%s\"", image->id.name + 2, image->name); + BKE_reportf(reports, RPT_ERROR, "Image '%s' could not be saved to '%s'", image->id.name + 2, image->name); } } else { - BKE_reportf(reports, RPT_ERROR, "Image \"%s\" does not have any image data", image->id.name + 2); + BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2); } } @@ -138,7 +143,7 @@ static void rna_Image_pack(Image *image, ReportList *reports, int as_png) ImBuf *ibuf = BKE_image_get_ibuf(image, NULL); if (!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) { - BKE_reportf(reports, RPT_ERROR, "Can't pack edited image from disk, only as internal PNG"); + BKE_report(reports, RPT_ERROR, "Cannot pack edited image from disk, only as internal PNG"); } else { if (as_png) { @@ -175,17 +180,20 @@ static void rna_Image_update(Image *image, ReportList *reports) ImBuf *ibuf = BKE_image_get_ibuf(image, NULL); if (ibuf == NULL) { - BKE_reportf(reports, RPT_ERROR, "Image \"%s\" does not have any image data", image->id.name + 2); + BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2); return; } - IMB_rect_from_float(ibuf); + if (ibuf->rect) + IMB_rect_from_float(ibuf); + + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; } static void rna_Image_scale(Image *image, ReportList *reports, int width, int height) { if (!BKE_image_scale(image, width, height)) { - BKE_reportf(reports, RPT_ERROR, "Image \"%s\" does not have any image data", image->id.name + 2); + BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2); } } @@ -201,7 +209,7 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int filter, int ibuf = BKE_image_get_ibuf(image, NULL); if (ibuf == NULL || ibuf->rect == NULL) { - BKE_reportf(reports, RPT_ERROR, "Image \"%s\" does not have any image data", image->id.name + 2); + BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2); return (int)GL_INVALID_OPERATION; } @@ -292,9 +300,9 @@ void RNA_api_image(StructRNA *srna) func = RNA_def_function(srna, "scale", "rna_Image_scale"); RNA_def_function_ui_description(func, "Scale the image in pixels"); RNA_def_function_flag(func, FUNC_USE_REPORTS); - parm = RNA_def_int(func, "width", 0, 1, 10000, "", "Width", 1, 10000); + parm = RNA_def_int(func, "width", 1, 1, 10000, "", "Width", 1, 10000); RNA_def_property_flag(parm, PROP_REQUIRED); - parm = RNA_def_int(func, "height", 0, 1, 10000, "", "Height", 1, 10000); + parm = RNA_def_int(func, "height", 1, 1, 10000, "", "Height", 1, 10000); RNA_def_property_flag(parm, PROP_REQUIRED); func = RNA_def_function(srna, "gl_touch", "rna_Image_gl_touch"); diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index e8e40d307fb..6520f22fbf5 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -34,8 +34,14 @@ #define RNA_MAGIC ((int)~0) +struct ColorBand; struct ID; struct IDProperty; +struct Main; +struct Mesh; +struct Object; +struct RenderEngine; +struct ReportList; struct SDNA; struct Sequence; @@ -259,6 +265,7 @@ void RNA_api_material(StructRNA *srna); void RNA_api_mesh(struct StructRNA *srna); void RNA_api_object(struct StructRNA *srna); void RNA_api_object_base(struct StructRNA *srna); +void RNA_api_pose(struct StructRNA *srna); void RNA_api_pose_channel(struct StructRNA *srna); void RNA_api_scene(struct StructRNA *srna); void RNA_api_scene_render(struct StructRNA *srna); @@ -352,7 +359,7 @@ typedef struct ArrayIterator { void *free_ptr; /* will be freed if set */ int itemsize; - /* array length with no skip functins applied, take care not to compare against index from animsys + /* array length with no skip functions applied, take care not to compare against index from animsys * or python indices */ int length; @@ -398,6 +405,11 @@ void rna_mtex_texture_slots_clear(struct ID *self, struct bContext *C, struct Re int rna_IDMaterials_assign_int(struct PointerRNA *ptr, int key, const struct PointerRNA *assign_ptr); + +/* Internal functions that cycles uses so we need to declare (tsk tsk) */ +void rna_RenderLayer_rect_set(PointerRNA *ptr, const float *values); +void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values); + #endif /* __RNA_INTERNAL_H__ */ diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c index 5334c10c4c6..33bbaeec282 100644 --- a/source/blender/makesrna/intern/rna_key.c +++ b/source/blender/makesrna/intern/rna_key.c @@ -61,12 +61,12 @@ static Key *rna_ShapeKey_find_key(ID *id) case ID_KE: return (Key *)id; case ID_LT: return ((Lattice *)id)->key; case ID_ME: return ((Mesh *)id)->key; - case ID_OB: return ob_get_key((Object *)id); + case ID_OB: return BKE_key_from_object((Object *)id); default: return NULL; } } -void rna_ShapeKey_name_set(PointerRNA *ptr, const char *value) +static void rna_ShapeKey_name_set(PointerRNA *ptr, const char *value) { KeyBlock *kb = ptr->data; char oldname[sizeof(kb->name)]; @@ -360,7 +360,7 @@ static void rna_Key_update_data(Main *bmain, Scene *UNUSED(scene), PointerRNA *p Object *ob; for (ob = bmain->object.first; ob; ob = ob->id.next) { - if (ob_get_key(ob) == key) { + if (BKE_key_from_object(ob) == key) { DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob); } diff --git a/source/blender/makesrna/intern/rna_lattice.c b/source/blender/makesrna/intern/rna_lattice.c index d4082cf3d9f..e4a29d9c674 100644 --- a/source/blender/makesrna/intern/rna_lattice.c +++ b/source/blender/makesrna/intern/rna_lattice.c @@ -240,6 +240,12 @@ static void rna_def_latticepoint(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Deformed Location", ""); RNA_def_property_update(prop, 0, "rna_Lattice_update_data"); + prop = RNA_def_property(srna, "weight_softbody", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "weight"); + RNA_def_property_range(prop, 0.01f, 100.0f); + RNA_def_property_ui_text(prop, "Weight", "Softbody goal weight"); + RNA_def_property_update(prop, 0, "rna_Lattice_update_data"); + prop = RNA_def_property(srna, "groups", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_funcs(prop, "rna_LatticePoint_groups_begin", "rna_iterator_array_next", "rna_iterator_array_end", "rna_iterator_array_get", @@ -320,7 +326,7 @@ static void rna_def_lattice(BlenderRNA *brna) RNA_def_property_collection_funcs(prop, "rna_Lattice_points_begin", "rna_iterator_array_next", "rna_iterator_array_end", "rna_iterator_array_get", NULL, NULL, NULL, NULL); RNA_def_property_ui_text(prop, "Points", "Points of the lattice"); - + /* pointers */ rna_def_animdata_common(srna); } diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c index 74b3c431183..04b8d2fa3df 100644 --- a/source/blender/makesrna/intern/rna_main.c +++ b/source/blender/makesrna/intern/rna_main.c @@ -51,7 +51,7 @@ static int rna_Main_is_dirty_get(PointerRNA *ptr) /* XXX, not totally nice to do it this way, should store in main ? */ Main *bmain = (Main *)ptr->data; wmWindowManager *wm; - for (wm = bmain->wm.first; wm; wm = wm->id.next) { + if ((wm = bmain->wm.first)) { return !wm->file_saved; } diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 307982e4bb1..cf9415a75e7 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -71,6 +71,7 @@ #include "BKE_speaker.h" #include "BKE_movieclip.h" #include "BKE_mask.h" +#include "BKE_gpencil.h" #include "DNA_armature_types.h" #include "DNA_camera_types.h" @@ -92,51 +93,58 @@ #include "DNA_node_types.h" #include "DNA_movieclip_types.h" #include "DNA_mask_types.h" +#include "DNA_gpencil_types.h" #include "ED_screen.h" -Camera *rna_Main_cameras_new(Main *UNUSED(bmain), const char *name) +#include "BLF_translation.h" + +static Camera *rna_Main_cameras_new(Main *UNUSED(bmain), const char *name) { ID *id = BKE_camera_add(name); id_us_min(id); return (Camera *)id; } -void rna_Main_cameras_remove(Main *bmain, ReportList *reports, struct Camera *camera) +static void rna_Main_cameras_remove(Main *bmain, ReportList *reports, PointerRNA *camera_ptr) { - if (ID_REAL_USERS(camera) <= 0) + Camera *camera = camera_ptr->data; + if (ID_REAL_USERS(camera) <= 0) { BKE_libblock_free(&bmain->camera, camera); - else - BKE_reportf(reports, RPT_ERROR, "Camera \"%s\" must have zero users to be removed, found %d", + RNA_POINTER_INVALIDATE(camera_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Camera '%s' must have zero users to be removed, found %d", camera->id.name + 2, ID_REAL_USERS(camera)); - - /* XXX python now has invalid pointer? */ + } } -Scene *rna_Main_scenes_new(Main *UNUSED(bmain), const char *name) +static Scene *rna_Main_scenes_new(Main *UNUSED(bmain), const char *name) { return BKE_scene_add(name); } -void rna_Main_scenes_remove(Main *bmain, bContext *C, ReportList *reports, struct Scene *scene) +static void rna_Main_scenes_remove(Main *bmain, bContext *C, ReportList *reports, PointerRNA *scene_ptr) { /* don't call BKE_libblock_free(...) directly */ - Scene *newscene; + Scene *scene = scene_ptr->data; + Scene *scene_new; - if (scene->id.prev) - newscene = scene->id.prev; - else if (scene->id.next) - newscene = scene->id.next; - else { - BKE_reportf(reports, RPT_ERROR, "Scene \"%s\" is the last, cant ve removed", scene->id.name + 2); - return; + if ((scene_new = scene->id.prev) || + (scene_new = scene->id.next)) + { + bScreen *sc = CTX_wm_screen(C); + if (sc->scene == scene) { + ED_screen_set_scene(C, sc, scene_new); + } + + BKE_scene_unlink(bmain, scene, scene_new); + RNA_POINTER_INVALIDATE(scene_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Scene '%s' is the last, cannot be removed", scene->id.name + 2); } - - if (CTX_wm_screen(C)->scene == scene) - ED_screen_set_scene(C, CTX_wm_screen(C), newscene); - - BKE_scene_unlink(bmain, scene, newscene); } -Object *rna_Main_objects_new(Main *UNUSED(bmain), ReportList *reports, const char *name, ID *data) +static Object *rna_Main_objects_new(Main *UNUSED(bmain), ReportList *reports, const char *name, ID *data) { Object *ob; int type = OB_EMPTY; @@ -147,7 +155,7 @@ Object *rna_Main_objects_new(Main *UNUSED(bmain), ReportList *reports, const cha type = OB_MESH; break; case ID_CU: - type = BKE_curve_type_get((struct Curve *)data); + type = BKE_curve_type_get((Curve *)data); break; case ID_MB: type = OB_MBALL; @@ -173,7 +181,7 @@ Object *rna_Main_objects_new(Main *UNUSED(bmain), ReportList *reports, const cha if (RNA_enum_id_from_value(id_type_items, GS(data->name), &idname) == 0) idname = "UNKNOWN"; - BKE_reportf(reports, RPT_ERROR, "ID type '%s' is not valid for a object", idname); + BKE_reportf(reports, RPT_ERROR, "ID type '%s' is not valid for an object", idname); return NULL; } } @@ -190,165 +198,190 @@ Object *rna_Main_objects_new(Main *UNUSED(bmain), ReportList *reports, const cha return ob; } -void rna_Main_objects_remove(Main *bmain, ReportList *reports, struct Object *object) +static void rna_Main_objects_remove(Main *bmain, ReportList *reports, PointerRNA *object_ptr) { + Object *object = object_ptr->data; if (ID_REAL_USERS(object) <= 0) { BKE_object_unlink(object); /* needed or ID pointers to this are not cleared */ BKE_libblock_free(&bmain->object, object); + RNA_POINTER_INVALIDATE(object_ptr); } else { - BKE_reportf(reports, RPT_ERROR, "Object \"%s\" must have zero users to be removed, found %d", + BKE_reportf(reports, RPT_ERROR, "Object '%s' must have zero users to be removed, found %d", object->id.name + 2, ID_REAL_USERS(object)); } } -Material *rna_Main_materials_new(Main *UNUSED(bmain), const char *name) +static Material *rna_Main_materials_new(Main *UNUSED(bmain), const char *name) { ID *id = (ID *)BKE_material_add(name); id_us_min(id); return (Material *)id; } -void rna_Main_materials_remove(Main *bmain, ReportList *reports, struct Material *material) +static void rna_Main_materials_remove(Main *bmain, ReportList *reports, PointerRNA *material_ptr) { - if (ID_REAL_USERS(material) <= 0) + Material *material = material_ptr->data; + if (ID_REAL_USERS(material) <= 0) { BKE_libblock_free(&bmain->mat, material); - else - BKE_reportf(reports, RPT_ERROR, "Material \"%s\" must have zero users to be removed, found %d", + RNA_POINTER_INVALIDATE(material_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Material '%s' must have zero users to be removed, found %d", material->id.name + 2, ID_REAL_USERS(material)); - - /* XXX python now has invalid pointer? */ + } } -bNodeTree *rna_Main_nodetree_new(Main *UNUSED(bmain), const char *name, int type) +static bNodeTree *rna_Main_nodetree_new(Main *UNUSED(bmain), const char *name, int type) { bNodeTree *tree = ntreeAddTree(name, type, NODE_GROUP); id_us_min(&tree->id); return tree; } -void rna_Main_nodetree_remove(Main *bmain, ReportList *reports, struct bNodeTree *tree) +static void rna_Main_nodetree_remove(Main *bmain, ReportList *reports, PointerRNA *tree_ptr) { - if (ID_REAL_USERS(tree) <= 0) + bNodeTree *tree = tree_ptr->data; + if (ID_REAL_USERS(tree) <= 0) { BKE_libblock_free(&bmain->nodetree, tree); - else - BKE_reportf(reports, RPT_ERROR, "Node Tree \"%s\" must have zero users to be removed, found %d", + RNA_POINTER_INVALIDATE(tree_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Node tree '%s' must have zero users to be removed, found %d", tree->id.name + 2, ID_REAL_USERS(tree)); - - /* XXX python now has invalid pointer? */ + } } -Mesh *rna_Main_meshes_new(Main *UNUSED(bmain), const char *name) +static Mesh *rna_Main_meshes_new(Main *UNUSED(bmain), const char *name) { Mesh *me = BKE_mesh_add(name); id_us_min(&me->id); return me; } -void rna_Main_meshes_remove(Main *bmain, ReportList *reports, Mesh *mesh) +static void rna_Main_meshes_remove(Main *bmain, ReportList *reports, PointerRNA *mesh_ptr) { - if (ID_REAL_USERS(mesh) <= 0) + Mesh *mesh = mesh_ptr->data; + if (ID_REAL_USERS(mesh) <= 0) { BKE_libblock_free(&bmain->mesh, mesh); - else - BKE_reportf(reports, RPT_ERROR, "Mesh \"%s\" must have zero users to be removed, found %d", + RNA_POINTER_INVALIDATE(mesh_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Mesh '%s' must have zero users to be removed, found %d", mesh->id.name + 2, ID_REAL_USERS(mesh)); - - /* XXX python now has invalid pointer? */ + } } -Lamp *rna_Main_lamps_new(Main *UNUSED(bmain), const char *name, int type) +static Lamp *rna_Main_lamps_new(Main *UNUSED(bmain), const char *name, int type) { Lamp *lamp = BKE_lamp_add(name); lamp->type = type; id_us_min(&lamp->id); return lamp; } -void rna_Main_lamps_remove(Main *bmain, ReportList *reports, Lamp *lamp) +static void rna_Main_lamps_remove(Main *bmain, ReportList *reports, PointerRNA *lamp_ptr) { - if (ID_REAL_USERS(lamp) <= 0) + Lamp *lamp = lamp_ptr->data; + if (ID_REAL_USERS(lamp) <= 0) { BKE_libblock_free(&bmain->lamp, lamp); - else - BKE_reportf(reports, RPT_ERROR, "Lamp \"%s\" must have zero users to be removed, found %d", + RNA_POINTER_INVALIDATE(lamp_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Lamp '%s' must have zero users to be removed, found %d", lamp->id.name + 2, ID_REAL_USERS(lamp)); - - /* XXX python now has invalid pointer? */ + } } -Image *rna_Main_images_new(Main *UNUSED(bmain), const char *name, int width, int height, int alpha, int float_buffer) +static Image *rna_Main_images_new(Main *UNUSED(bmain), const char *name, int width, int height, int alpha, int float_buffer) { float color[4] = {0.0, 0.0, 0.0, 1.0}; Image *image = BKE_image_add_generated(width, height, name, alpha ? 32 : 24, float_buffer, 0, color); id_us_min(&image->id); return image; } -Image *rna_Main_images_load(Main *UNUSED(bmain), ReportList *reports, const char *filepath) +static Image *rna_Main_images_load(Main *UNUSED(bmain), ReportList *reports, const char *filepath) { Image *ima; errno = 0; ima = BKE_image_load(filepath); - if (!ima) - BKE_reportf(reports, RPT_ERROR, "Can't read: \"%s\", %s", filepath, - errno ? strerror(errno) : "Unsupported image format"); + if (!ima) { + BKE_reportf(reports, RPT_ERROR, "Cannot read '%s': %s", filepath, + errno ? strerror(errno) : TIP_("unsupported image format")); + } return ima; } -void rna_Main_images_remove(Main *bmain, ReportList *reports, Image *image) +static void rna_Main_images_remove(Main *bmain, ReportList *reports, PointerRNA *image_ptr) { - if (ID_REAL_USERS(image) <= 0) + Image *image = image_ptr->data; + if (ID_REAL_USERS(image) <= 0) { BKE_libblock_free(&bmain->image, image); - else - BKE_reportf(reports, RPT_ERROR, "Image \"%s\" must have zero users to be removed, found %d", + RNA_POINTER_INVALIDATE(image_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Image '%s' must have zero users to be removed, found %d", image->id.name + 2, ID_REAL_USERS(image)); - - /* XXX python now has invalid pointer? */ + } } -Lattice *rna_Main_lattices_new(Main *UNUSED(bmain), const char *name) +static Lattice *rna_Main_lattices_new(Main *UNUSED(bmain), const char *name) { Lattice *lt = BKE_lattice_add(name); id_us_min(<->id); return lt; } -void rna_Main_lattices_remove(Main *bmain, ReportList *reports, struct Lattice *lt) +static void rna_Main_lattices_remove(Main *bmain, ReportList *reports, PointerRNA *lt_ptr) { - if (ID_REAL_USERS(lt) <= 0) + Lattice *lt = lt_ptr->data; + if (ID_REAL_USERS(lt) <= 0) { BKE_libblock_free(&bmain->latt, lt); - else - BKE_reportf(reports, RPT_ERROR, "Lattice \"%s\" must have zero users to be removed, found %d", + RNA_POINTER_INVALIDATE(lt_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Lattice '%s' must have zero users to be removed, found %d", lt->id.name + 2, ID_REAL_USERS(lt)); + } } -Curve *rna_Main_curves_new(Main *UNUSED(bmain), const char *name, int type) +static Curve *rna_Main_curves_new(Main *UNUSED(bmain), const char *name, int type) { Curve *cu = BKE_curve_add(name, type); id_us_min(&cu->id); return cu; } -void rna_Main_curves_remove(Main *bmain, ReportList *reports, struct Curve *cu) +static void rna_Main_curves_remove(Main *bmain, ReportList *reports, PointerRNA *cu_ptr) { - if (ID_REAL_USERS(cu) <= 0) + Curve *cu = cu_ptr->data; + if (ID_REAL_USERS(cu) <= 0) { BKE_libblock_free(&bmain->curve, cu); - else - BKE_reportf(reports, RPT_ERROR, "Curve \"%s\" must have zero users to be removed, found %d", + RNA_POINTER_INVALIDATE(cu_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Curve '%s' must have zero users to be removed, found %d", cu->id.name + 2, ID_REAL_USERS(cu)); + } } -MetaBall *rna_Main_metaballs_new(Main *UNUSED(bmain), const char *name) +static MetaBall *rna_Main_metaballs_new(Main *UNUSED(bmain), const char *name) { MetaBall *mb = BKE_mball_add(name); id_us_min(&mb->id); return mb; } -void rna_Main_metaballs_remove(Main *bmain, ReportList *reports, struct MetaBall *mb) +static void rna_Main_metaballs_remove(Main *bmain, ReportList *reports, PointerRNA *mb_ptr) { - if (ID_REAL_USERS(mb) <= 0) + MetaBall *mb = mb_ptr->data; + if (ID_REAL_USERS(mb) <= 0) { BKE_libblock_free(&bmain->mball, mb); - else - BKE_reportf(reports, RPT_ERROR, "Metaball \"%s\" must have zero users to be removed, found %d", + RNA_POINTER_INVALIDATE(mb_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Metaball '%s' must have zero users to be removed, found %d", mb->id.name + 2, ID_REAL_USERS(mb)); + } } -VFont *rna_Main_fonts_load(Main *bmain, ReportList *reports, const char *filepath) +static VFont *rna_Main_fonts_load(Main *bmain, ReportList *reports, const char *filepath) { VFont *font; @@ -356,109 +389,127 @@ VFont *rna_Main_fonts_load(Main *bmain, ReportList *reports, const char *filepat font = BKE_vfont_load(bmain, filepath); if (!font) - BKE_reportf(reports, RPT_ERROR, "Can't read: \"%s\", %s", filepath, - errno ? strerror(errno) : "Unsupported font format"); + BKE_reportf(reports, RPT_ERROR, "Cannot read '%s': %s", filepath, + errno ? strerror(errno) : TIP_("unsupported font format")); return font; } -void rna_Main_fonts_remove(Main *bmain, ReportList *reports, VFont *vfont) +static void rna_Main_fonts_remove(Main *bmain, ReportList *reports, PointerRNA *vfont_ptr) { - if (ID_REAL_USERS(vfont) <= 0) + VFont *vfont = vfont_ptr->data; + if (ID_REAL_USERS(vfont) <= 0) { BKE_libblock_free(&bmain->vfont, vfont); - else - BKE_reportf(reports, RPT_ERROR, "Font \"%s\" must have zero users to be removed, found %d", + RNA_POINTER_INVALIDATE(vfont_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Font '%s' must have zero users to be removed, found %d", vfont->id.name + 2, ID_REAL_USERS(vfont)); - - /* XXX python now has invalid pointer? */ + } } -Tex *rna_Main_textures_new(Main *UNUSED(bmain), const char *name, int type) +static Tex *rna_Main_textures_new(Main *UNUSED(bmain), const char *name, int type) { Tex *tex = add_texture(name); tex_set_type(tex, type); id_us_min(&tex->id); return tex; } -void rna_Main_textures_remove(Main *bmain, ReportList *reports, struct Tex *tex) +static void rna_Main_textures_remove(Main *bmain, ReportList *reports, PointerRNA *tex_ptr) { - if (ID_REAL_USERS(tex) <= 0) + Tex *tex = tex_ptr->data; + if (ID_REAL_USERS(tex) <= 0) { BKE_libblock_free(&bmain->tex, tex); - else - BKE_reportf(reports, RPT_ERROR, "Texture \"%s\" must have zero users to be removed, found %d", + RNA_POINTER_INVALIDATE(tex_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Texture '%s' must have zero users to be removed, found %d", tex->id.name + 2, ID_REAL_USERS(tex)); + } } -Brush *rna_Main_brushes_new(Main *UNUSED(bmain), const char *name) +static Brush *rna_Main_brushes_new(Main *UNUSED(bmain), const char *name) { Brush *brush = BKE_brush_add(name); id_us_min(&brush->id); return brush; } -void rna_Main_brushes_remove(Main *bmain, ReportList *reports, struct Brush *brush) +static void rna_Main_brushes_remove(Main *bmain, ReportList *reports, PointerRNA *brush_ptr) { - if (ID_REAL_USERS(brush) <= 0) + Brush *brush = brush_ptr->data; + if (ID_REAL_USERS(brush) <= 0) { BKE_libblock_free(&bmain->brush, brush); - else - BKE_reportf(reports, RPT_ERROR, "Brush \"%s\" must have zero users to be removed, found %d", + RNA_POINTER_INVALIDATE(brush_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Brush '%s' must have zero users to be removed, found %d", brush->id.name + 2, ID_REAL_USERS(brush)); + } } -World *rna_Main_worlds_new(Main *UNUSED(bmain), const char *name) +static World *rna_Main_worlds_new(Main *UNUSED(bmain), const char *name) { World *world = add_world(name); id_us_min(&world->id); return world; } -void rna_Main_worlds_remove(Main *bmain, ReportList *reports, struct World *world) +static void rna_Main_worlds_remove(Main *bmain, ReportList *reports, PointerRNA *world_ptr) { - if (ID_REAL_USERS(world) <= 0) + Group *world = world_ptr->data; + if (ID_REAL_USERS(world) <= 0) { BKE_libblock_free(&bmain->world, world); - else - BKE_reportf(reports, RPT_ERROR, "World \"%s\" must have zero users to be removed, found %d", + RNA_POINTER_INVALIDATE(world_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "World '%s' must have zero users to be removed, found %d", world->id.name + 2, ID_REAL_USERS(world)); + } } -Group *rna_Main_groups_new(Main *UNUSED(bmain), const char *name) +static Group *rna_Main_groups_new(Main *UNUSED(bmain), const char *name) { return add_group(name); } -void rna_Main_groups_remove(Main *bmain, Group *group) +static void rna_Main_groups_remove(Main *bmain, PointerRNA *group_ptr) { + Group *group = group_ptr->data; BKE_group_unlink(group); BKE_libblock_free(&bmain->group, group); - /* XXX python now has invalid pointer? */ + RNA_POINTER_INVALIDATE(group_ptr); } -Speaker *rna_Main_speakers_new(Main *UNUSED(bmain), const char *name) +static Speaker *rna_Main_speakers_new(Main *UNUSED(bmain), const char *name) { Speaker *speaker = BKE_speaker_add(name); id_us_min(&speaker->id); return speaker; } -void rna_Main_speakers_remove(Main *bmain, ReportList *reports, Speaker *speaker) +static void rna_Main_speakers_remove(Main *bmain, ReportList *reports, PointerRNA *speaker_ptr) { - if (ID_REAL_USERS(speaker) <= 0) + Speaker *speaker = speaker_ptr->data; + if (ID_REAL_USERS(speaker) <= 0) { BKE_libblock_free(&bmain->speaker, speaker); - else - BKE_reportf(reports, RPT_ERROR, "Speaker \"%s\" must have zero users to be removed, found %d", + RNA_POINTER_INVALIDATE(speaker_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Speaker '%s' must have zero users to be removed, found %d", speaker->id.name + 2, ID_REAL_USERS(speaker)); - - /* XXX python now has invalid pointer? */ + } } -Text *rna_Main_texts_new(Main *UNUSED(bmain), const char *name) +static Text *rna_Main_texts_new(Main *UNUSED(bmain), const char *name) { return BKE_text_add(name); } -void rna_Main_texts_remove(Main *bmain, Text *text) +static void rna_Main_texts_remove(Main *bmain, PointerRNA *text_ptr) { + Text *text = text_ptr->data; BKE_text_unlink(bmain, text); BKE_libblock_free(&bmain->text, text); - /* XXX python now has invalid pointer? */ + RNA_POINTER_INVALIDATE(text_ptr); } -Text *rna_Main_texts_load(Main *bmain, ReportList *reports, const char *filepath) +static Text *rna_Main_texts_load(Main *bmain, ReportList *reports, const char *filepath) { Text *txt; @@ -466,65 +517,71 @@ Text *rna_Main_texts_load(Main *bmain, ReportList *reports, const char *filepath txt = BKE_text_load(filepath, bmain->name); if (!txt) - BKE_reportf(reports, RPT_ERROR, "Can't read: \"%s\", %s", filepath, - errno ? strerror(errno) : "Unable to load text"); + BKE_reportf(reports, RPT_ERROR, "Cannot read '%s': %s", filepath, + errno ? strerror(errno) : TIP_("unable to load text")); return txt; } -bArmature *rna_Main_armatures_new(Main *UNUSED(bmain), const char *name) +static bArmature *rna_Main_armatures_new(Main *UNUSED(bmain), const char *name) { bArmature *arm = BKE_armature_add(name); id_us_min(&arm->id); return arm; } -void rna_Main_armatures_remove(Main *bmain, ReportList *reports, bArmature *arm) +static void rna_Main_armatures_remove(Main *bmain, ReportList *reports, PointerRNA *arm_ptr) { - if (ID_REAL_USERS(arm) <= 0) + bArmature *arm = arm_ptr->data; + if (ID_REAL_USERS(arm) <= 0) { BKE_libblock_free(&bmain->armature, arm); - else - BKE_reportf(reports, RPT_ERROR, "Armature \"%s\" must have zero users to be removed, found %d", + RNA_POINTER_INVALIDATE(arm_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Armature '%s' must have zero users to be removed, found %d", arm->id.name + 2, ID_REAL_USERS(arm)); - - /* XXX python now has invalid pointer? */ + } } -bAction *rna_Main_actions_new(Main *UNUSED(bmain), const char *name) +static bAction *rna_Main_actions_new(Main *UNUSED(bmain), const char *name) { bAction *act = add_empty_action(name); id_us_min(&act->id); act->id.flag &= ~LIB_FAKEUSER; return act; } -void rna_Main_actions_remove(Main *bmain, ReportList *reports, bAction *act) +static void rna_Main_actions_remove(Main *bmain, ReportList *reports, PointerRNA *act_ptr) { - if (ID_REAL_USERS(act) <= 0) + bAction *act = act_ptr->data; + if (ID_REAL_USERS(act) <= 0) { BKE_libblock_free(&bmain->action, act); - else - BKE_reportf(reports, RPT_ERROR, "Action \"%s\" must have zero users to be removed, found %d", + RNA_POINTER_INVALIDATE(act_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Action '%s' must have zero users to be removed, found %d", act->id.name + 2, ID_REAL_USERS(act)); - - /* XXX python now has invalid pointer? */ + } } -ParticleSettings *rna_Main_particles_new(Main *bmain, const char *name) +static ParticleSettings *rna_Main_particles_new(Main *bmain, const char *name) { ParticleSettings *part = psys_new_settings(name, bmain); id_us_min(&part->id); return part; } -void rna_Main_particles_remove(Main *bmain, ReportList *reports, ParticleSettings *part) +static void rna_Main_particles_remove(Main *bmain, ReportList *reports, PointerRNA *part_ptr) { - if (ID_REAL_USERS(part) <= 0) + ParticleSettings *part = part_ptr->data; + if (ID_REAL_USERS(part) <= 0) { BKE_libblock_free(&bmain->particle, part); - else - BKE_reportf(reports, RPT_ERROR, "Particle Settings \"%s\" must have zero users to be removed, found %d", + RNA_POINTER_INVALIDATE(part_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Particle settings '%s' must have zero users to be removed, found %d", part->id.name + 2, ID_REAL_USERS(part)); - - /* XXX python now has invalid pointer? */ + } } -MovieClip *rna_Main_movieclip_load(Main *UNUSED(bmain), ReportList *reports, const char *filepath) +static MovieClip *rna_Main_movieclip_load(Main *UNUSED(bmain), ReportList *reports, const char *filepath) { MovieClip *clip; @@ -532,20 +589,21 @@ MovieClip *rna_Main_movieclip_load(Main *UNUSED(bmain), ReportList *reports, con clip = BKE_movieclip_file_add(filepath); if (!clip) - BKE_reportf(reports, RPT_ERROR, "Can't read: \"%s\", %s.", filepath, - errno ? strerror(errno) : "Unable to load movie clip"); + BKE_reportf(reports, RPT_ERROR, "Cannot read '%s': %s", filepath, + errno ? strerror(errno) : TIP_("unable to load movie clip")); return clip; } -void rna_Main_movieclips_remove(Main *bmain, MovieClip *clip) +static void rna_Main_movieclips_remove(Main *bmain, PointerRNA *clip_ptr) { + MovieClip *clip = clip_ptr->data; BKE_movieclip_unlink(bmain, clip); BKE_libblock_free(&bmain->movieclip, clip); - /* XXX python now has invalid pointer? */ + RNA_POINTER_INVALIDATE(clip_ptr); } -Mask *rna_Main_mask_new(Main *UNUSED(bmain), const char *name) +static Mask *rna_Main_mask_new(Main *UNUSED(bmain), const char *name) { Mask *mask; @@ -554,44 +612,58 @@ Mask *rna_Main_mask_new(Main *UNUSED(bmain), const char *name) return mask; } -void rna_Main_masks_remove(Main *bmain, Mask *mask) +static void rna_Main_masks_remove(Main *bmain, PointerRNA *mask_ptr) { + Mask *mask = mask_ptr->data; BKE_mask_free(bmain, mask); BKE_libblock_free(&bmain->mask, mask); - /* XXX python now has invalid pointer? */ + RNA_POINTER_INVALIDATE(mask_ptr); +} + +static void rna_Main_grease_pencil_remove(Main *bmain, ReportList *reports, PointerRNA *gpd_ptr) +{ + bGPdata *gpd = gpd_ptr->data; + if (ID_REAL_USERS(gpd) <= 0) { + BKE_gpencil_free(gpd); + BKE_libblock_free(&bmain->gpencil, gpd); + RNA_POINTER_INVALIDATE(gpd_ptr); + } + else + BKE_reportf(reports, RPT_ERROR, "Grease pencil '%s' must have zero users to be removed, found %d", + gpd->id.name + 2, ID_REAL_USERS(gpd)); } /* tag functions, all the same */ -void rna_Main_cameras_tag(Main *bmain, int value) { tag_main_lb(&bmain->camera, value); } -void rna_Main_scenes_tag(Main *bmain, int value) { tag_main_lb(&bmain->scene, value); } -void rna_Main_objects_tag(Main *bmain, int value) { tag_main_lb(&bmain->object, value); } -void rna_Main_materials_tag(Main *bmain, int value) { tag_main_lb(&bmain->mat, value); } -void rna_Main_node_groups_tag(Main *bmain, int value) { tag_main_lb(&bmain->nodetree, value); } -void rna_Main_meshes_tag(Main *bmain, int value) { tag_main_lb(&bmain->mesh, value); } -void rna_Main_lamps_tag(Main *bmain, int value) { tag_main_lb(&bmain->lamp, value); } -void rna_Main_libraries_tag(Main *bmain, int value) { tag_main_lb(&bmain->library, value); } -void rna_Main_screens_tag(Main *bmain, int value) { tag_main_lb(&bmain->screen, value); } -void rna_Main_window_managers_tag(Main *bmain, int value) { tag_main_lb(&bmain->wm, value); } -void rna_Main_images_tag(Main *bmain, int value) { tag_main_lb(&bmain->image, value); } -void rna_Main_lattices_tag(Main *bmain, int value) { tag_main_lb(&bmain->latt, value); } -void rna_Main_curves_tag(Main *bmain, int value) { tag_main_lb(&bmain->curve, value); } -void rna_Main_metaballs_tag(Main *bmain, int value) { tag_main_lb(&bmain->mball, value); } -void rna_Main_fonts_tag(Main *bmain, int value) { tag_main_lb(&bmain->vfont, value); } -void rna_Main_textures_tag(Main *bmain, int value) { tag_main_lb(&bmain->tex, value); } -void rna_Main_brushes_tag(Main *bmain, int value) { tag_main_lb(&bmain->brush, value); } -void rna_Main_worlds_tag(Main *bmain, int value) { tag_main_lb(&bmain->world, value); } -void rna_Main_groups_tag(Main *bmain, int value) { tag_main_lb(&bmain->group, value); } -void rna_Main_shape_keys_tag(Main *bmain, int value) { tag_main_lb(&bmain->key, value); } -void rna_Main_scripts_tag(Main *bmain, int value) { tag_main_lb(&bmain->script, value); } -void rna_Main_texts_tag(Main *bmain, int value) { tag_main_lb(&bmain->text, value); } -void rna_Main_speakers_tag(Main *bmain, int value) { tag_main_lb(&bmain->speaker, value); } -void rna_Main_sounds_tag(Main *bmain, int value) { tag_main_lb(&bmain->sound, value); } -void rna_Main_armatures_tag(Main *bmain, int value) { tag_main_lb(&bmain->armature, value); } -void rna_Main_actions_tag(Main *bmain, int value) { tag_main_lb(&bmain->action, value); } -void rna_Main_particles_tag(Main *bmain, int value) { tag_main_lb(&bmain->particle, value); } -void rna_Main_gpencil_tag(Main *bmain, int value) { tag_main_lb(&bmain->gpencil, value); } -void rna_Main_movieclips_tag(Main *bmain, int value) { tag_main_lb(&bmain->movieclip, value); } -void rna_Main_masks_tag(Main *bmain, int value) { tag_main_lb(&bmain->mask, value); } +static void rna_Main_cameras_tag(Main *bmain, int value) { tag_main_lb(&bmain->camera, value); } +static void rna_Main_scenes_tag(Main *bmain, int value) { tag_main_lb(&bmain->scene, value); } +static void rna_Main_objects_tag(Main *bmain, int value) { tag_main_lb(&bmain->object, value); } +static void rna_Main_materials_tag(Main *bmain, int value) { tag_main_lb(&bmain->mat, value); } +static void rna_Main_node_groups_tag(Main *bmain, int value) { tag_main_lb(&bmain->nodetree, value); } +static void rna_Main_meshes_tag(Main *bmain, int value) { tag_main_lb(&bmain->mesh, value); } +static void rna_Main_lamps_tag(Main *bmain, int value) { tag_main_lb(&bmain->lamp, value); } +static void rna_Main_libraries_tag(Main *bmain, int value) { tag_main_lb(&bmain->library, value); } +static void rna_Main_screens_tag(Main *bmain, int value) { tag_main_lb(&bmain->screen, value); } +static void rna_Main_window_managers_tag(Main *bmain, int value) { tag_main_lb(&bmain->wm, value); } +static void rna_Main_images_tag(Main *bmain, int value) { tag_main_lb(&bmain->image, value); } +static void rna_Main_lattices_tag(Main *bmain, int value) { tag_main_lb(&bmain->latt, value); } +static void rna_Main_curves_tag(Main *bmain, int value) { tag_main_lb(&bmain->curve, value); } +static void rna_Main_metaballs_tag(Main *bmain, int value) { tag_main_lb(&bmain->mball, value); } +static void rna_Main_fonts_tag(Main *bmain, int value) { tag_main_lb(&bmain->vfont, value); } +static void rna_Main_textures_tag(Main *bmain, int value) { tag_main_lb(&bmain->tex, value); } +static void rna_Main_brushes_tag(Main *bmain, int value) { tag_main_lb(&bmain->brush, value); } +static void rna_Main_worlds_tag(Main *bmain, int value) { tag_main_lb(&bmain->world, value); } +static void rna_Main_groups_tag(Main *bmain, int value) { tag_main_lb(&bmain->group, value); } +// static void rna_Main_shape_keys_tag(Main *bmain, int value) { tag_main_lb(&bmain->key, value); } +// static void rna_Main_scripts_tag(Main *bmain, int value) { tag_main_lb(&bmain->script, value); } +static void rna_Main_texts_tag(Main *bmain, int value) { tag_main_lb(&bmain->text, value); } +static void rna_Main_speakers_tag(Main *bmain, int value) { tag_main_lb(&bmain->speaker, value); } +static void rna_Main_sounds_tag(Main *bmain, int value) { tag_main_lb(&bmain->sound, value); } +static void rna_Main_armatures_tag(Main *bmain, int value) { tag_main_lb(&bmain->armature, value); } +static void rna_Main_actions_tag(Main *bmain, int value) { tag_main_lb(&bmain->action, value); } +static void rna_Main_particles_tag(Main *bmain, int value) { tag_main_lb(&bmain->particle, value); } +static void rna_Main_gpencil_tag(Main *bmain, int value) { tag_main_lb(&bmain->gpencil, value); } +static void rna_Main_movieclips_tag(Main *bmain, int value) { tag_main_lb(&bmain->movieclip, value); } +static void rna_Main_masks_tag(Main *bmain, int value) { tag_main_lb(&bmain->mask, value); } static int rna_Main_cameras_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_CA); } static int rna_Main_scenes_is_updated_get(PointerRNA *ptr) { return DAG_id_type_tagged(ptr->data, ID_SCE); } @@ -635,6 +707,8 @@ void RNA_api_main(StructRNA *srna) RNA_def_property_flag(parm, PROP_REQUIRED); parm = RNA_def_pointer(func, "image", "Image", "", "New image"); RNA_def_function_return(func, parm); +#else + (void)srna; #endif } @@ -662,7 +736,8 @@ void RNA_def_main_cameras(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a camera from the current blendfile"); parm = RNA_def_pointer(func, "camera", "Camera", "", "Camera to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_cameras_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -697,7 +772,8 @@ void RNA_def_main_scenes(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a scene from the current blendfile"); parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_scenes_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -736,7 +812,8 @@ void RNA_def_main_objects(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove a object from the current blendfile"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "object", "Object", "", "Object to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_objects_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -771,7 +848,8 @@ void RNA_def_main_materials(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a material from the current blendfile"); parm = RNA_def_pointer(func, "material", "Material", "", "Material to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_materials_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -814,7 +892,8 @@ void RNA_def_main_node_groups(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a node tree from the current blendfile"); parm = RNA_def_pointer(func, "tree", "NodeTree", "", "Node tree to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_node_groups_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -848,7 +927,8 @@ void RNA_def_main_meshes(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a mesh from the current blendfile"); parm = RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_meshes_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -884,7 +964,8 @@ void RNA_def_main_lamps(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a lamp from the current blendfile"); parm = RNA_def_pointer(func, "lamp", "Lamp", "", "Lamp to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_lamps_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -973,9 +1054,9 @@ void RNA_def_main_images(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Add a new image to the main database"); parm = RNA_def_string(func, "name", "Image", 0, "", "New name for the datablock"); RNA_def_property_flag(parm, PROP_REQUIRED); - parm = RNA_def_int(func, "width", 1024, 1, INT_MAX, "", "Width of the image", 0, INT_MAX); + parm = RNA_def_int(func, "width", 1024, 1, INT_MAX, "", "Width of the image", 1, INT_MAX); RNA_def_property_flag(parm, PROP_REQUIRED); - parm = RNA_def_int(func, "height", 1024, 1, INT_MAX, "", "Height of the image", 0, INT_MAX); + parm = RNA_def_int(func, "height", 1024, 1, INT_MAX, "", "Height of the image", 1, INT_MAX); RNA_def_property_flag(parm, PROP_REQUIRED); RNA_def_boolean(func, "alpha", 0, "Alpha", "Use alpha channel"); RNA_def_boolean(func, "float_buffer", 0, "Float Buffer", "Create an image with floating point color"); @@ -996,7 +1077,8 @@ void RNA_def_main_images(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove an image from the current blendfile"); parm = RNA_def_pointer(func, "image", "Image", "", "Image to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_images_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -1031,7 +1113,8 @@ void RNA_def_main_lattices(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a lattice from the current blendfile"); parm = RNA_def_pointer(func, "lattice", "Lattice", "", "Lattice to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_lattices_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -1067,7 +1150,8 @@ void RNA_def_main_curves(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a curve from the current blendfile"); parm = RNA_def_pointer(func, "curve", "Curve", "", "Curve to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_curves_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -1101,7 +1185,8 @@ void RNA_def_main_metaballs(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a metaball from the current blendfile"); parm = RNA_def_pointer(func, "metaball", "MetaBall", "", "Metaball to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_metaballs_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -1136,7 +1221,8 @@ void RNA_def_main_fonts(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a font from the current blendfile"); parm = RNA_def_pointer(func, "vfont", "VectorFont", "", "Font to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_fonts_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -1172,7 +1258,8 @@ void RNA_def_main_textures(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a texture from the current blendfile"); parm = RNA_def_pointer(func, "texture", "Texture", "", "Texture to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_textures_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -1206,7 +1293,8 @@ void RNA_def_main_brushes(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a brush from the current blendfile"); parm = RNA_def_pointer(func, "brush", "Brush", "", "Brush to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_brushes_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -1241,7 +1329,8 @@ void RNA_def_main_worlds(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a world from the current blendfile"); parm = RNA_def_pointer(func, "world", "World", "", "World to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_worlds_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -1275,7 +1364,8 @@ void RNA_def_main_groups(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "remove", "rna_Main_groups_remove"); RNA_def_function_ui_description(func, "Remove a group from the current blendfile"); parm = RNA_def_pointer(func, "group", "Group", "", "Group to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_groups_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -1310,7 +1400,8 @@ void RNA_def_main_speakers(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a speaker from the current blendfile"); parm = RNA_def_pointer(func, "speaker", "Speaker", "", "Speaker to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_speakers_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -1344,7 +1435,8 @@ void RNA_def_main_texts(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "remove", "rna_Main_texts_remove"); RNA_def_function_ui_description(func, "Remove a text from the current blendfile"); parm = RNA_def_pointer(func, "text", "Text", "", "Text to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); /* load func */ func = RNA_def_function(srna, "load", "rna_Main_texts_load"); @@ -1412,7 +1504,8 @@ void RNA_def_main_armatures(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a armature from the current blendfile"); parm = RNA_def_pointer(func, "armature", "Armature", "", "Armature to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_armatures_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -1446,7 +1539,8 @@ void RNA_def_main_actions(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a action from the current blendfile"); parm = RNA_def_pointer(func, "action", "Action", "", "Action to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_actions_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -1480,7 +1574,8 @@ void RNA_def_main_particles(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a particle settings instance from the current blendfile"); parm = RNA_def_pointer(func, "particle", "ParticleSettings", "", "Particle Settings to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_particles_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); @@ -1507,6 +1602,21 @@ void RNA_def_main_gpencil(BlenderRNA *brna, PropertyRNA *cprop) parm = RNA_def_boolean(func, "value", 0, "Value", ""); RNA_def_property_flag(parm, PROP_REQUIRED); + func = RNA_def_function(srna, "new", "gpencil_data_addnew"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_string(func, "name", "GreasePencil", 0, "", "New name for the datablock"); + RNA_def_property_flag(parm, PROP_REQUIRED); + /* return type */ + parm = RNA_def_pointer(func, "grease_pencil", "GreasePencil", "", "New grease pencil datablock"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_Main_grease_pencil_remove"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, "Remove a grease pencil instance from the current blendfile"); + parm = RNA_def_pointer(func, "grease_pencil", "GreasePencil", "", "Grease Pencil to remove"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); + prop = RNA_def_property(srna, "is_updated", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_boolean_funcs(prop, "rna_Main_gpencil_is_updated_get", NULL); @@ -1530,7 +1640,8 @@ void RNA_def_main_movieclips(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "remove", "rna_Main_movieclips_remove"); RNA_def_function_ui_description(func, "Remove a movie clip from the current blendfile."); parm = RNA_def_pointer(func, "clip", "MovieClip", "", "Movie clip to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); /* load func */ func = RNA_def_function(srna, "load", "rna_Main_movieclip_load"); @@ -1561,7 +1672,7 @@ void RNA_def_main_masks(BlenderRNA *brna, PropertyRNA *cprop) /* new func */ func = RNA_def_function(srna, "new", "rna_Main_mask_new"); RNA_def_function_ui_description(func, "Add a new mask with a given name to the main database"); - parm = RNA_def_string_file_path(func, "name", "", MAX_ID_NAME - 2, "Mask", "Name of new mask datablock"); + RNA_def_string_file_path(func, "name", "", MAX_ID_NAME - 2, "Mask", "Name of new mask datablock"); /* return type */ parm = RNA_def_pointer(func, "mask", "Mask", "", "New mask datablock"); RNA_def_function_return(func, parm); @@ -1570,7 +1681,8 @@ void RNA_def_main_masks(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "remove", "rna_Main_masks_remove"); RNA_def_function_ui_description(func, "Remove a masks from the current blendfile."); parm = RNA_def_pointer(func, "mask", "Mask", "", "Mask to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } #endif diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index 719baed8edb..56caa254a59 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -193,7 +193,7 @@ static void rna_MaskLayer_splines_begin(CollectionPropertyIterator *iter, Pointe rna_iterator_listbase_begin(iter, &masklay->splines, NULL); } -void rna_MaskLayer_name_set(PointerRNA *ptr, const char *value) +static void rna_MaskLayer_name_set(PointerRNA *ptr, const char *value) { Mask *mask = (Mask *)ptr->id.data; MaskLayer *masklay = (MaskLayer *)ptr->data; @@ -315,14 +315,16 @@ static MaskLayer *rna_Mask_layers_new(Mask *mask, const char *name) return masklay; } -void rna_Mask_layers_remove(Mask *mask, ReportList *reports, MaskLayer *masklay) +static void rna_Mask_layers_remove(Mask *mask, ReportList *reports, PointerRNA *masklay_ptr) { + MaskLayer *masklay = masklay_ptr->data; if (BLI_findindex(&mask->masklayers, masklay) == -1) { - BKE_reportf(reports, RPT_ERROR, "MaskLayer '%s' not found in mask '%s'", masklay->name, mask->id.name + 2); + BKE_reportf(reports, RPT_ERROR, "Mask layer '%s' not found in mask '%s'", masklay->name, mask->id.name + 2); return; } BKE_mask_layer_remove(mask, masklay); + RNA_POINTER_INVALIDATE(masklay_ptr); WM_main_add_notifier(NC_MASK | NA_EDITED, mask); } @@ -705,7 +707,9 @@ static void rna_def_masklayers(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "remove", "rna_Mask_layers_remove"); RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove layer from this mask"); - RNA_def_pointer(func, "layer", "MaskLayer", "", "Shape to be removed"); + parm = RNA_def_pointer(func, "layer", "MaskLayer", "", "Shape to be removed"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); /* clear all layers */ func = RNA_def_function(srna, "clear", "rna_Mask_layers_clear"); diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 4523858d639..9232ae098ea 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -45,7 +45,6 @@ static EnumPropertyItem prop_texture_coordinates_items[] = { {TEXCO_ORCO, "ORCO", 0, "Generated", "Use the original undeformed coordinates of the object"}, {TEXCO_STRAND, "STRAND", 0, "Strand / Particle", "Use normalized strand texture coordinate (1D) or particle age (X) and trail position (Y)"}, - {TEXCO_STICKY, "STICKY", 0, "Sticky", "Use mesh's sticky coordinates for the texture coordinates"}, {TEXCO_WINDOW, "WINDOW", 0, "Window", "Use screen coordinates as texture coordinates"}, {TEXCO_NORM, "NORMAL", 0, "Normal", "Use normal vector as texture coordinates"}, {TEXCO_REFL, "REFLECTION", 0, "Reflection", "Use reflection vector as texture coordinates"}, @@ -82,12 +81,14 @@ EnumPropertyItem ramp_blend_items[] = { #include "MEM_guardedalloc.h" #include "DNA_node_types.h" +#include "DNA_object_types.h" #include "BKE_depsgraph.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_texture.h" #include "BKE_node.h" +#include "BKE_paint.h" #include "ED_node.h" @@ -106,7 +107,18 @@ static void rna_Material_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *p } } -static void rna_Material_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_Material_update_previews(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + Material *ma = ptr->id.data; + + if (ma->nodetree) + ntreeClearPreview(ma->nodetree); + + rna_Material_update(bmain, scene, ptr); +} + + +static void rna_Material_draw_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) { Material *ma = ptr->id.data; @@ -303,7 +315,6 @@ static EnumPropertyItem *rna_Material_texture_coordinates_itemf(bContext *UNUSED else if (ELEM3(ma->material_type, MA_TYPE_SURFACE, MA_TYPE_HALO, MA_TYPE_WIRE)) { RNA_enum_items_add_value(&item, &totitem, prop_texture_coordinates_items, TEXCO_UV); RNA_enum_items_add_value(&item, &totitem, prop_texture_coordinates_items, TEXCO_STRAND); - RNA_enum_items_add_value(&item, &totitem, prop_texture_coordinates_items, TEXCO_STICKY); RNA_enum_items_add_value(&item, &totitem, prop_texture_coordinates_items, TEXCO_WINDOW); RNA_enum_items_add_value(&item, &totitem, prop_texture_coordinates_items, TEXCO_NORM); RNA_enum_items_add_value(&item, &totitem, prop_texture_coordinates_items, TEXCO_REFL); @@ -321,7 +332,7 @@ MTex *rna_mtex_texture_slots_add(ID *self_id, struct bContext *C, ReportList *re { MTex *mtex = add_mtex_id(self_id, -1); if (mtex == NULL) { - BKE_reportf(reports, RPT_ERROR, "maximum number of textures added %d", MAX_MTEX); + BKE_reportf(reports, RPT_ERROR, "Maximum number of textures added %d", MAX_MTEX); return NULL; } @@ -336,7 +347,7 @@ MTex *rna_mtex_texture_slots_create(ID *self_id, struct bContext *C, ReportList MTex *mtex; if (index < 0 || index >= MAX_MTEX) { - BKE_reportf(reports, RPT_ERROR, "index %d is invalid", index); + BKE_reportf(reports, RPT_ERROR, "Index %d is invalid", index); return NULL; } @@ -356,12 +367,12 @@ void rna_mtex_texture_slots_clear(ID *self_id, struct bContext *C, ReportList *r give_active_mtex(self_id, &mtex_ar, &act); if (mtex_ar == NULL) { - BKE_report(reports, RPT_ERROR, "mtex not found for this type"); + BKE_report(reports, RPT_ERROR, "Mtex not found for this type"); return; } if (index < 0 || index >= MAX_MTEX) { - BKE_reportf(reports, RPT_ERROR, "index %d is invalid", index); + BKE_reportf(reports, RPT_ERROR, "Index %d is invalid", index); return; } @@ -470,6 +481,12 @@ static void rna_def_material_mtex(BlenderRNA *brna) "from their parent"); RNA_def_property_update(prop, 0, "rna_Material_update"); + prop = RNA_def_property(srna, "use_map_to_bounds", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_MAPTO_BOUNDS); + RNA_def_property_ui_text(prop, "Map to Bounds", + "Map coordinates in object bounds"); + RNA_def_property_update(prop, 0, "rna_Material_update"); + prop = RNA_def_property(srna, "use_from_original", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_OB_DUPLI_ORIG); RNA_def_property_ui_text(prop, "From Original", @@ -1751,7 +1768,7 @@ void RNA_def_material(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "pr_type"); RNA_def_property_enum_items(prop, preview_type_items); RNA_def_property_ui_text(prop, "Preview render type", "Type of preview render"); - RNA_def_property_update(prop, 0, "rna_Material_update"); + RNA_def_property_update(prop, 0, "rna_Material_update_previews"); prop = RNA_def_property(srna, "ambient", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "amb"); @@ -1819,7 +1836,12 @@ void RNA_def_material(BlenderRNA *brna) "Material uses the light group exclusively - these lamps are excluded " "from other scene lighting"); RNA_def_property_update(prop, 0, "rna_Material_update"); - + + prop = RNA_def_property(srna, "use_light_group_local", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "shade_flag", MA_GROUP_LOCAL); + RNA_def_property_ui_text(prop, "Light Group Local", "When linked in, material uses local light group with the same name"); + RNA_def_property_update(prop, 0, "rna_Material_update"); + prop = RNA_def_property(srna, "use_raytrace", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", MA_TRACEBLE); RNA_def_property_ui_text(prop, "Traceable", @@ -1939,6 +1961,12 @@ void RNA_def_material(BlenderRNA *brna) "- for anisotropic shading effects"); RNA_def_property_update(prop, 0, "rna_Material_update"); + prop = RNA_def_property(srna, "use_uv_project", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "mapflag", MA_MAPFLAG_UVPROJECT); + RNA_def_property_ui_text(prop, "UV Project", + "Use to ensure UV interpolation is correct for camera projections (use with UV project modifier)"); + RNA_def_property_update(prop, 0, "rna_Material_update"); + /* nested structs */ prop = RNA_def_property(srna, "raytrace_mirror", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); diff --git a/source/blender/makesrna/intern/rna_material_api.c b/source/blender/makesrna/intern/rna_material_api.c index 538a4c99df4..c7441f92c33 100644 --- a/source/blender/makesrna/intern/rna_material_api.c +++ b/source/blender/makesrna/intern/rna_material_api.c @@ -31,15 +31,19 @@ #include #include +#include "BLI_utildefines.h" + #include "RNA_define.h" #include "DNA_material_types.h" +#include "rna_internal.h" /* own include */ + #ifdef RNA_RUNTIME #else -void RNA_api_material(StructRNA *srna) +void RNA_api_material(StructRNA *UNUSED(srna)) { /* FunctionRNA *func; */ /* PropertyRNA *parm; */ diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index fe5f8e574a0..f0b84332d07 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -149,7 +149,7 @@ void rna_Mesh_update_draw(Main *bmain, Scene *scene, PointerRNA *ptr) } -void rna_Mesh_update_vertmask(Main *bmain, Scene *scene, PointerRNA *ptr) +static void rna_Mesh_update_vertmask(Main *bmain, Scene *scene, PointerRNA *ptr) { Mesh *me = ptr->data; if ((me->editflag & ME_EDIT_VERT_SEL) && (me->editflag & ME_EDIT_PAINT_MASK)) { @@ -158,7 +158,7 @@ void rna_Mesh_update_vertmask(Main *bmain, Scene *scene, PointerRNA *ptr) rna_Mesh_update_draw(bmain, scene, ptr); } -void rna_Mesh_update_facemask(Main *bmain, Scene *scene, PointerRNA *ptr) +static void rna_Mesh_update_facemask(Main *bmain, Scene *scene, PointerRNA *ptr) { Mesh *me = ptr->data; if ((me->editflag & ME_EDIT_VERT_SEL) && (me->editflag & ME_EDIT_PAINT_MASK)) { @@ -224,7 +224,7 @@ static void rna_MeshPolygon_normal_get(PointerRNA *ptr, float *values) MPoly *mp = (MPoly *)ptr->data; /* BMESH_TODO: might be faster to look for a CD_NORMALS layer and use that */ - mesh_calc_poly_normal(mp, me->mloop + mp->loopstart, me->mvert, values); + BKE_mesh_calc_poly_normal(mp, me->mloop + mp->loopstart, me->mvert, values); } static float rna_MeshPolygon_area_get(PointerRNA *ptr) @@ -1204,11 +1204,6 @@ static char *rna_MeshColor_path(PointerRNA *ptr) return rna_LoopCustomData_data_path(ptr, "vertex_colors", CD_MLOOPCOL); } -static char *rna_MeshSticky_path(PointerRNA *ptr) -{ - return BLI_sprintfN("sticky[%d]", (int)((MSticky *)ptr->data - rna_mesh(ptr)->msticky)); -} - static char *rna_MeshIntPropertyLayer_path(PointerRNA *ptr) { return BLI_sprintfN("int_layers[\"%s\"]", ((CustomDataLayer *)ptr->data)->name); @@ -1280,12 +1275,12 @@ static PointerRNA rna_Mesh_tessface_vertex_color_new(struct Mesh *me, struct bCo int index; if (me->edit_btmesh) { - BKE_report(reports, RPT_ERROR, "Can't add tessface colors's in editmode"); + BKE_report(reports, RPT_ERROR, "Cannot add tessface colors in edit mode"); return PointerRNA_NULL; } if (me->mpoly) { - BKE_report(reports, RPT_ERROR, "Can't add tessface colors's when MPoly's exist"); + BKE_report(reports, RPT_ERROR, "Cannot add tessface colors when MPoly's exist"); return PointerRNA_NULL; } @@ -1373,12 +1368,12 @@ static PointerRNA rna_Mesh_tessface_uv_texture_new(struct Mesh *me, struct bCont int index; if (me->edit_btmesh) { - BKE_report(reports, RPT_ERROR, "Can't add tessface uv's in editmode"); + BKE_report(reports, RPT_ERROR, "Cannot add tessface uv's in edit mode"); return PointerRNA_NULL; } if (me->mpoly) { - BKE_report(reports, RPT_ERROR, "Can't add tessface uv's when MPoly's exist"); + BKE_report(reports, RPT_ERROR, "Cannot add tessface uv's when MPoly's exist"); return PointerRNA_NULL; } @@ -1957,21 +1952,6 @@ static void rna_def_mtexpoly(BlenderRNA *brna) #endif } -static void rna_def_msticky(BlenderRNA *brna) -{ - StructRNA *srna; - PropertyRNA *prop; - - srna = RNA_def_struct(brna, "MeshSticky", NULL); - RNA_def_struct_sdna(srna, "MSticky"); - RNA_def_struct_ui_text(srna, "Mesh Vertex Sticky Texture Coordinate", "Sticky texture coordinate"); - RNA_def_struct_path_func(srna, "rna_MeshSticky_path"); - - prop = RNA_def_property(srna, "co", PROP_FLOAT, PROP_XYZ); - RNA_def_property_ui_text(prop, "Location", "Sticky texture coordinate location"); - RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); -} - static void rna_def_mcol(BlenderRNA *brna) { StructRNA *srna; @@ -2414,7 +2394,8 @@ static void rna_def_loop_colors(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove a vertex color layer"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "layer", "Layer", "", "The layer to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); #endif prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_UNSIGNED); @@ -2591,7 +2572,8 @@ static void rna_def_uv_textures(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove a vertex color layer"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "layer", "Layer", "", "The layer to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); #endif prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_UNSIGNED); @@ -2609,7 +2591,7 @@ static void rna_def_uv_textures(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); } -static void rna_def_skin_vertices(BlenderRNA *brna, PropertyRNA *cprop) +static void rna_def_skin_vertices(BlenderRNA *brna, PropertyRNA *UNUSED(cprop)) { StructRNA *srna; PropertyRNA *prop; @@ -2696,11 +2678,6 @@ static void rna_def_mesh(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Polygons", "Polygons of the mesh"); rna_def_mesh_polygons(brna, prop); - prop = RNA_def_property(srna, "sticky", PROP_COLLECTION, PROP_NONE); - RNA_def_property_collection_sdna(prop, NULL, "msticky", "totvert"); - RNA_def_property_struct_type(prop, "MeshSticky"); - RNA_def_property_ui_text(prop, "Sticky", "Sticky texture coordinates"); - /* TODO, should this be allowed to be its self? */ prop = RNA_def_property(srna, "texture_mesh", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "texcomesh"); @@ -3036,7 +3013,6 @@ void RNA_def_mesh(BlenderRNA *brna) rna_def_mloopuv(brna); rna_def_mtface(brna); rna_def_mtexpoly(brna); - rna_def_msticky(brna); rna_def_mcol(brna); rna_def_mloopcol(brna); rna_def_mproperties(brna); diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index fe18e6254d0..1e75569c841 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -41,8 +41,10 @@ #include "BKE_mesh.h" #include "ED_mesh.h" +#include "rna_internal.h" /* own include */ + #ifdef RNA_RUNTIME -const char *rna_Mesh_unit_test_compare(struct Mesh *mesh, bContext *C, struct Mesh *mesh2) +static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh, bContext *C, struct Mesh *mesh2) { const char *ret = BKE_mesh_cmp(mesh, mesh2, FLT_EPSILON * 60); @@ -76,7 +78,7 @@ void RNA_api_mesh(StructRNA *srna) RNA_def_function_flag(func, FUNC_USE_CONTEXT); func = RNA_def_function(srna, "unit_test_compare", "rna_Mesh_unit_test_compare"); - parm = RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh to compare to"); + RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh to compare to"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); /* return value */ parm = RNA_def_string(func, "result", "nothing", 64, "Return value", "String description of result of comparison"); diff --git a/source/blender/makesrna/intern/rna_meta.c b/source/blender/makesrna/intern/rna_meta.c index c8b52b45604..08eefc082bf 100644 --- a/source/blender/makesrna/intern/rna_meta.c +++ b/source/blender/makesrna/intern/rna_meta.c @@ -27,6 +27,7 @@ #include +#include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -126,19 +127,17 @@ static MetaElem *rna_MetaBall_elements_new(MetaBall *mb, int type) return ml; } -static void rna_MetaBall_elements_remove(MetaBall *mb, ReportList *reports, MetaElem *ml) +static void rna_MetaBall_elements_remove(MetaBall *mb, ReportList *reports, PointerRNA *ml_ptr) { - int found = 0; + MetaElem *ml = ml_ptr->data; - found = BLI_remlink_safe(&mb->elems, ml); - - if (!found) { - BKE_reportf(reports, RPT_ERROR, "Metaball \"%s\" does not contain spline given", mb->id.name + 2); + if (BLI_remlink_safe(&mb->elems, ml) == FALSE) { + BKE_reportf(reports, RPT_ERROR, "Metaball '%s' does not contain spline given", mb->id.name + 2); return; } MEM_freeN(ml); - /* invalidate pointer!, no can do */ + RNA_POINTER_INVALIDATE(ml_ptr); /* cheating way for importers to avoid slow updates */ if (mb->id.us > 0) { @@ -254,7 +253,8 @@ static void rna_def_metaball_elements(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove an element from the metaball"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "element", "MetaElement", "", "The element to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "clear", "rna_MetaBall_elements_clear"); RNA_def_function_ui_description(func, "Remove all elements from the metaball"); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 084cda87507..8eca7162d39 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -84,6 +84,7 @@ EnumPropertyItem modifier_type_items[] = { {eModifierType_Curve, "CURVE", ICON_MOD_CURVE, "Curve", ""}, {eModifierType_Displace, "DISPLACE", ICON_MOD_DISPLACE, "Displace", ""}, {eModifierType_Hook, "HOOK", ICON_HOOK, "Hook", ""}, + {eModifierType_LaplacianSmooth, "LAPLACIANSMOOTH", ICON_MOD_SMOOTH, "Laplacian Smooth", ""}, {eModifierType_Lattice, "LATTICE", ICON_MOD_LATTICE, "Lattice", ""}, {eModifierType_MeshDeform, "MESH_DEFORM", ICON_MOD_MESHDEFORM, "Mesh Deform", ""}, {eModifierType_Shrinkwrap, "SHRINKWRAP", ICON_MOD_SHRINKWRAP, "Shrinkwrap", ""}, @@ -210,12 +211,14 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr) return &RNA_RemeshModifier; case eModifierType_Skin: return &RNA_SkinModifier; + case eModifierType_LaplacianSmooth: + return &RNA_LaplacianSmoothModifier; default: return &RNA_Modifier; } } -void rna_Modifier_name_set(PointerRNA *ptr, const char *value) +static void rna_Modifier_name_set(PointerRNA *ptr, const char *value) { ModifierData *md = ptr->data; char oldname[sizeof(md->name)]; @@ -257,9 +260,6 @@ static void rna_Smoke_set_type(Main *bmain, Scene *scene, PointerRNA *ptr) { SmokeModifierData *smd = (SmokeModifierData *)ptr->data; Object *ob = (Object *)ptr->id.data; - ParticleSystemModifierData *psmd = NULL; - ParticleSystem *psys = NULL; - ParticleSettings *part = NULL; /* nothing changed */ if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) @@ -273,28 +273,6 @@ static void rna_Smoke_set_type(Main *bmain, Scene *scene, PointerRNA *ptr) ob->dt = OB_WIRE; break; case MOD_SMOKE_TYPE_FLOW: - for (psys = ob->particlesystem.first; psys; psys = psys->next) - if (psys->part->type == PART_EMITTER) - break; - if (ob->type == OB_MESH && !psys) { - /* add particle system */ - psmd = (ParticleSystemModifierData *)object_add_particle_system(scene, ob, NULL); - if (psmd) { - psys = psmd->psys; - part = psys->part; - part->lifetime = 1.0f; - part->sta = 1.0f; - part->end = 250.0f; - part->ren_as = PART_DRAW_NOT; - part->flag |= PART_UNBORN; - part->draw_as = PART_DRAW_DOT; - BLI_strncpy(psys->name, "SmokeParticles", sizeof(psys->name)); - psys->recalc |= (PSYS_RECALC_RESET | PSYS_RECALC_PHYS); - DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA); - } - } - if (smd->flow) - smd->flow->psys = psys; case MOD_SMOKE_TYPE_COLL: case 0: default: @@ -384,6 +362,12 @@ static void rna_SmoothModifier_vgroup_set(PointerRNA *ptr, const char *value) rna_object_vgroup_name_set(ptr, value, lmd->defgrp_name, sizeof(lmd->defgrp_name)); } +static void rna_LaplacianSmoothModifier_vgroup_set(PointerRNA *ptr, const char *value) +{ + LaplacianSmoothModifierData *lmd = (LaplacianSmoothModifierData *)ptr->data; + rna_object_vgroup_name_set(ptr, value, lmd->defgrp_name, sizeof(lmd->defgrp_name)); +} + static void rna_WaveModifier_vgroup_set(PointerRNA *ptr, const char *value) { WaveModifierData *lmd = (WaveModifierData *)ptr->data; @@ -402,6 +386,12 @@ static void rna_SolidifyModifier_vgroup_set(PointerRNA *ptr, const char *value) rna_object_vgroup_name_set(ptr, value, smd->defgrp_name, sizeof(smd->defgrp_name)); } +static void rna_DecimateModifier_vgroup_set(PointerRNA *ptr, const char *value) +{ + DecimateModifierData *dmd = (DecimateModifierData *)ptr->data; + rna_object_vgroup_name_set(ptr, value, dmd->defgrp_name, sizeof(dmd->defgrp_name)); +} + static void rna_WeightVGModifier_vgroup_set(PointerRNA *ptr, const char *value) { ModifierData *md = (ModifierData *)ptr->data; @@ -1129,6 +1119,13 @@ static void rna_def_modifier_mirror(BlenderRNA *brna) static void rna_def_modifier_decimate(BlenderRNA *brna) { + static EnumPropertyItem modifier_decim_mode_items[] = { + {MOD_DECIM_MODE_COLLAPSE, "COLLAPSE", 0, "Collapse", "Use edge collapsing"}, + {MOD_DECIM_MODE_UNSUBDIV, "UNSUBDIV", 0, "Un-Subdivide", "Use un-subdivide face reduction"}, + {MOD_DECIM_MODE_DISSOLVE, "DISSOLVE", 0, "Planar", "Dissolve geometry to form planar polygons"}, + {0, NULL, 0, NULL, NULL} + }; + StructRNA *srna; PropertyRNA *prop; @@ -1137,15 +1134,65 @@ static void rna_def_modifier_decimate(BlenderRNA *brna) RNA_def_struct_sdna(srna, "DecimateModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_DECIM); + prop = RNA_def_property(srna, "decimate_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "mode"); + RNA_def_property_enum_items(prop, modifier_decim_mode_items); + RNA_def_property_ui_text(prop, "Mode", ""); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + /* (mode == MOD_DECIM_MODE_COLLAPSE) */ prop = RNA_def_property(srna, "ratio", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "percent"); RNA_def_property_range(prop, 0, 1); - RNA_def_property_ui_range(prop, 0, 1, 1, 2); - RNA_def_property_ui_text(prop, "Ratio", "Ratio of triangles to reduce to"); + RNA_def_property_ui_range(prop, 0, 1, 1, 4); + RNA_def_property_ui_text(prop, "Ratio", "Ratio of triangles to reduce to (collapse only)"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + /* (mode == MOD_DECIM_MODE_UNSUBDIV) */ + prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "iter"); + RNA_def_property_range(prop, 0, SHRT_MAX); + RNA_def_property_ui_range(prop, 0, 100, 1, 0); + RNA_def_property_ui_text(prop, "Iterations", "Number of times reduce the geometry (unsubdivide only)"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + /* (mode == MOD_DECIM_MODE_DISSOLVE) */ + prop = RNA_def_property(srna, "angle_limit", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "angle"); + RNA_def_property_range(prop, 0, DEG2RAD(180)); + RNA_def_property_ui_range(prop, 0, DEG2RAD(180), 100, 2); + RNA_def_property_ui_text(prop, "Angle Limit", "Only dissolve angles below this (planar only)"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + /* (mode == MOD_DECIM_MODE_COLLAPSE) */ + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "defgrp_name"); + RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name (collapse only)"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_DecimateModifier_vgroup_set"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "invert_vertex_group", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_DECIM_FLAG_INVERT_VGROUP); + RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence (collapse only)"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "use_collapse_triangulate", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_DECIM_FLAG_TRIANGULATE); + RNA_def_property_ui_text(prop, "Triangulate", "Keep triangulated faces resulting from decimation (collapse only)"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + /* end collapse-only option */ + + /* (mode == MOD_DECIM_MODE_DISSOLVE) */ + prop = RNA_def_property(srna, "use_dissolve_boundaries", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS); + RNA_def_property_ui_text(prop, "All Boundaries", "Dissolve all vertices inbetween face boundaries (planar only)"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + /* end dissolve-only option */ + + + + /* all modes use this */ prop = RNA_def_property(srna, "face_count", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "faceCount"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Face Count", "The current number of faces in the decimated mesh"); } @@ -1742,6 +1789,64 @@ static void rna_def_modifier_smooth(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Modifier_update"); } +static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "LaplacianSmoothModifier", "Modifier"); + RNA_def_struct_ui_text(srna, "Laplacian Smooth Modifier", "Smoothing effect modifier"); + RNA_def_struct_sdna(srna, "LaplacianSmoothModifierData"); + RNA_def_struct_ui_icon(srna, ICON_MOD_SMOOTH); + + prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_X); + RNA_def_property_ui_text(prop, "X", "Smooth object along X axis"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "use_y", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_Y); + RNA_def_property_ui_text(prop, "Y", "Smooth object along Y axis"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "use_z", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_Z); + RNA_def_property_ui_text(prop, "Z", "Smooth object along Z axis"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "use_volume_preserve", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION); + RNA_def_property_ui_text(prop, "Preserve Volume", "Apply volume preservation after smooth"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "lambda_factor", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "lambda"); + RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0000001, 1000.0, 0.0000001, 8); + RNA_def_property_ui_text(prop, "Lambda Factor", "Smooth factor effect"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "lambda_border", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "lambda_border"); + RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0000001, 1000.0, 0.0000001, 8); + RNA_def_property_ui_text(prop, "Lambda Border", "Lambda factor in border"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "repeat"); + RNA_def_property_ui_range(prop, 0, 200, 1, 0); + RNA_def_property_ui_text(prop, "Repeat", ""); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "defgrp_name"); + RNA_def_property_ui_text(prop, "Vertex Group", + "Name of Vertex Group which determines influence of modifier per point"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_LaplacianSmoothModifier_vgroup_set"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); +} + static void rna_def_modifier_cast(BlenderRNA *brna) { StructRNA *srna; @@ -2658,7 +2763,7 @@ static void rna_def_modifier_screw(BlenderRNA *brna) #endif } -static void rna_def_modifier_weightvg_mask(BlenderRNA *brna, StructRNA *srna) +static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna), StructRNA *srna) { static EnumPropertyItem weightvg_mask_tex_map_items[] = { {MOD_DISP_MAP_LOCAL, "LOCAL", 0, "Local", "Use local generated coordinates"}, @@ -3007,7 +3112,7 @@ static void rna_def_modifier_remesh(BlenderRNA *brna) prop = RNA_def_property(srna, "octree_depth", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "depth"); - RNA_def_property_range(prop, 1, 10); + RNA_def_property_range(prop, 1, 12); RNA_def_property_ui_text(prop, "Octree Depth", "Resolution of the octree; higher values give finer details"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); @@ -3356,6 +3461,7 @@ void RNA_def_modifier(BlenderRNA *brna) rna_def_modifier_ocean(brna); rna_def_modifier_remesh(brna); rna_def_modifier_skin(brna); + rna_def_modifier_laplaciansmooth(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c index 8d1105fd620..99effc990a8 100644 --- a/source/blender/makesrna/intern/rna_movieclip.c +++ b/source/blender/makesrna/intern/rna_movieclip.c @@ -187,8 +187,7 @@ static void rna_def_moviecliUser(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Movie Clip User", "Parameters defining how a MovieClip datablock is used by another datablock"); - prop = RNA_def_property(srna, "current_frame", PROP_INT, PROP_TIME); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); + prop = RNA_def_property(srna, "frame_current", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "framenr"); RNA_def_property_range(prop, MINAFRAME, MAXFRAME); RNA_def_property_ui_text(prop, "Current Frame", "Current frame number in movie or image sequence"); @@ -300,11 +299,17 @@ static void rna_def_movieclip(BlenderRNA *brna) "(affects only how footage is loading, does not change data associated with a clip)"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_MovieClip_reload_update"); + /* length */ + prop = RNA_def_property(srna, "frame_duration", PROP_INT, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_int_sdna(prop, NULL, "len"); + RNA_def_property_ui_text(prop, "Duration", "Detected duration of movie clip in frames"); + /* color management */ prop = RNA_def_property(srna, "colorspace_settings", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "colorspace_settings"); RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings"); - RNA_def_property_ui_text(prop, "Colorspace Settings", "Input color space settings"); + RNA_def_property_ui_text(prop, "Color Space Settings", "Input color space settings"); } void RNA_def_movieclip(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index 16753961852..574f06e9107 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -27,6 +27,7 @@ #include +#include "RNA_access.h" #include "RNA_define.h" #include "rna_internal.h" @@ -302,7 +303,7 @@ static NlaStrip *rna_NlaStrip_new(NlaTrack *track, bContext *C, ReportList *repo NlaStrip *strip = add_nlastrip(action); if (strip == NULL) { - BKE_reportf(reports, RPT_ERROR, "Unable to create new strip"); + BKE_report(reports, RPT_ERROR, "Unable to create new strip"); return NULL; } @@ -310,8 +311,8 @@ static NlaStrip *rna_NlaStrip_new(NlaTrack *track, bContext *C, ReportList *repo strip->start = start; if (BKE_nlastrips_add_strip(&track->strips, strip) == 0) { - BKE_reportf(reports, RPT_ERROR, - "Unable to add strip. Track doesn't have any space to accommodate this new strip"); + BKE_report(reports, RPT_ERROR, + "Unable to add strip (the track does not have any space to accommodate this new strip)"); free_nlastrip(NULL, strip); return NULL; } @@ -345,22 +346,24 @@ static NlaStrip *rna_NlaStrip_new(NlaTrack *track, bContext *C, ReportList *repo return strip; } -static void rna_NlaStrip_remove(NlaTrack *track, bContext *C, ReportList *reports, NlaStrip *strip) +static void rna_NlaStrip_remove(NlaTrack *track, bContext *C, ReportList *reports, PointerRNA *strip_ptr) { + NlaStrip *strip = strip_ptr->data; if (BLI_findindex(&track->strips, strip) == -1) { - BKE_reportf(reports, RPT_ERROR, "NLA's Strip '%s' not found in track '%s'", strip->name, track->name); + BKE_reportf(reports, RPT_ERROR, "NLA strip '%s' not found in track '%s'", strip->name, track->name); return; } - else { - free_nlastrip(&track->strips, strip); - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_REMOVED, NULL); - } + + free_nlastrip(&track->strips, strip); + RNA_POINTER_INVALIDATE(strip_ptr); + + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_REMOVED, NULL); } /* Set the 'solo' setting for the given NLA-track, making sure that it is the only one * that has this status in its AnimData block. */ -void rna_NlaTrack_solo_set(PointerRNA *ptr, int value) +static void rna_NlaTrack_solo_set(PointerRNA *ptr, int value) { NlaTrack *data = (NlaTrack *)ptr->data; AnimData *adt = BKE_animdata_from_id(ptr->id.data); @@ -520,7 +523,7 @@ static void rna_def_nlastrip(BlenderRNA *brna) prop = RNA_def_property(srna, "repeat", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "repeat"); RNA_def_property_float_funcs(prop, NULL, "rna_NlaStrip_repeat_set", NULL); - /* these limits have currently be chosen arbitarily, but could be extended + /* these limits have currently be chosen arbitrarily, but could be extended * (minimum should still be > 0 though) if needed... */ RNA_def_property_range(prop, 0.1f, 1000.0f); RNA_def_property_ui_text(prop, "Repeat", "Number of times to repeat the action range"); @@ -639,7 +642,8 @@ static void rna_api_nlatrack_strips(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a NLA Strip"); parm = RNA_def_pointer(func, "strip", "NlaStrip", "", "NLA Strip to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } static void rna_def_nlatrack(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 55dda3fc315..ece5c82f747 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -35,12 +35,16 @@ #include "rna_internal_types.h" #include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_text_types.h" #include "DNA_texture_types.h" #include "BKE_animsys.h" @@ -48,9 +52,9 @@ #include "BKE_node.h" #include "BKE_image.h" #include "BKE_texture.h" +#include "BKE_idprop.h" -#include "BLI_math.h" -#include "BLI_utildefines.h" +#include "IMB_imbuf.h" #include "WM_types.h" @@ -71,12 +75,12 @@ EnumPropertyItem node_quality_items[] = { }; EnumPropertyItem node_chunksize_items[] = { - {NTREE_CHUNCKSIZE_32, "32", 0, "32x32", "Chunksize of 32x32"}, - {NTREE_CHUNCKSIZE_64, "64", 0, "64x64", "Chunksize of 64x64"}, - {NTREE_CHUNCKSIZE_128, "128", 0, "128x128", "Chunksize of 128x128"}, - {NTREE_CHUNCKSIZE_256, "256", 0, "256x256", "Chunksize of 256x256"}, - {NTREE_CHUNCKSIZE_512, "512", 0, "512x512", "Chunksize of 512x512"}, - {NTREE_CHUNCKSIZE_1024, "1024", 0, "1024x1024", "Chunksize of 1024x1024"}, + {NTREE_CHUNCKSIZE_32, "32", 0, "32x32", "Chunksize of 32x32"}, + {NTREE_CHUNCKSIZE_64, "64", 0, "64x64", "Chunksize of 64x64"}, + {NTREE_CHUNCKSIZE_128, "128", 0, "128x128", "Chunksize of 128x128"}, + {NTREE_CHUNCKSIZE_256, "256", 0, "256x256", "Chunksize of 256x256"}, + {NTREE_CHUNCKSIZE_512, "512", 0, "512x512", "Chunksize of 512x512"}, + {NTREE_CHUNCKSIZE_1024, "1024", 0, "1024x1024", "Chunksize of 1024x1024"}, {0, NULL, 0, NULL, NULL} }; @@ -206,6 +210,8 @@ EnumPropertyItem prop_wave_items[] = { #include "BLI_linklist.h" +#include "BKE_global.h" + #include "ED_node.h" #include "RE_pipeline.h" @@ -226,10 +232,6 @@ static StructRNA *rna_Node_refine(struct PointerRNA *ptr) case NODE_GROUP: return &RNA_NodeGroup; - case NODE_FORLOOP: - return &RNA_NodeForLoop; - case NODE_WHILELOOP: - return &RNA_NodeWhileLoop; case NODE_FRAME: return &RNA_NodeFrame; case NODE_REROUTE: @@ -689,7 +691,7 @@ static bNode *rna_NodeTree_node_new(bNodeTree *ntree, bContext *C, ReportList *r bNodeTemplate ntemp; if (type == NODE_GROUP && group == NULL) { - BKE_reportf(reports, RPT_ERROR, "node type \'GROUP\' missing group argument"); + BKE_report(reports, RPT_ERROR, "Node type 'GROUP' missing group argument"); return NULL; } @@ -700,7 +702,7 @@ static bNode *rna_NodeTree_node_new(bNodeTree *ntree, bContext *C, ReportList *r node = nodeAddNode(ntree, &ntemp); if (node == NULL) { - BKE_reportf(reports, RPT_ERROR, "Unable to create node"); + BKE_report(reports, RPT_ERROR, "Unable to create node"); } else { ntreeUpdateTree(ntree); /* update group node socket links*/ @@ -753,20 +755,20 @@ static bNode *rna_NodeTree_node_texture_new(bNodeTree *ntree, bContext *C, Repor return node; } -static void rna_NodeTree_node_remove(bNodeTree *ntree, ReportList *reports, bNode *node) +static void rna_NodeTree_node_remove(bNodeTree *ntree, ReportList *reports, PointerRNA *node_ptr) { + bNode *node = node_ptr->data; if (BLI_findindex(&ntree->nodes, node) == -1) { - BKE_reportf(reports, RPT_ERROR, "Unable to locate node '%s' in nodetree", node->name); + BKE_reportf(reports, RPT_ERROR, "Unable to locate node '%s' in node tree", node->name); + return; } - else { - if (node->id) - id_us_min(node->id); - nodeFreeNode(ntree, node); - ntreeUpdateTree(ntree); /* update group node socket links*/ + id_us_min(node->id); + nodeFreeNode(ntree, node); + RNA_POINTER_INVALIDATE(node_ptr); - WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); - } + ntreeUpdateTree(ntree); /* update group node socket links */ + WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } static void rna_NodeTree_node_clear(bNodeTree *ntree) @@ -800,7 +802,7 @@ static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, ReportList *reports, nodeFindNode(ntree, tosock, &tonode, NULL, &to_in_out); if (&from_in_out == &to_in_out) { - BKE_reportf(reports, RPT_ERROR, "Same input/output direction of sockets"); + BKE_report(reports, RPT_ERROR, "Same input/output direction of sockets"); return NULL; } @@ -824,17 +826,19 @@ static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, ReportList *reports, return ret; } -static void rna_NodeTree_link_remove(bNodeTree *ntree, ReportList *reports, bNodeLink *link) +static void rna_NodeTree_link_remove(bNodeTree *ntree, ReportList *reports, PointerRNA *link_ptr) { + bNodeLink *link = link_ptr->data; if (BLI_findindex(&ntree->links, link) == -1) { - BKE_reportf(reports, RPT_ERROR, "Unable to locate link in nodetree"); + BKE_report(reports, RPT_ERROR, "Unable to locate link in node tree"); + return; } - else { - nodeRemLink(ntree, link); - ntreeUpdateTree(ntree); - WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); - } + nodeRemLink(ntree, link); + RNA_POINTER_INVALIDATE(link_ptr); + + ntreeUpdateTree(ntree); + WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } static void rna_NodeTree_link_clear(bNodeTree *ntree) @@ -882,9 +886,9 @@ static bNodeSocket *rna_NodeTree_input_expose(bNodeTree *ntree, ReportList *repo int index, in_out; if (!nodeFindNode(ntree, sock, &node, &index, &in_out)) - BKE_reportf(reports, RPT_ERROR, "Unable to locate socket in nodetree"); + BKE_report(reports, RPT_ERROR, "Unable to locate socket in node tree"); else if (in_out != SOCK_IN) - BKE_reportf(reports, RPT_ERROR, "Socket is not an input"); + BKE_report(reports, RPT_ERROR, "Socket is not an input"); else { /* XXX should check if tree is a group here! no good way to do this currently. */ gsock = node_group_add_socket(ntree, sock->name, sock->type, SOCK_IN); @@ -906,9 +910,9 @@ static bNodeSocket *rna_NodeTree_output_expose(bNodeTree *ntree, ReportList *rep int index, in_out; if (!nodeFindNode(ntree, sock, &node, &index, &in_out)) - BKE_reportf(reports, RPT_ERROR, "Unable to locate socket in nodetree"); + BKE_report(reports, RPT_ERROR, "Unable to locate socket in node tree"); else if (in_out != SOCK_OUT) - BKE_reportf(reports, RPT_ERROR, "Socket is not an output"); + BKE_report(reports, RPT_ERROR, "Socket is not an output"); else { /* XXX should check if tree is a group here! no good way to do this currently. */ gsock = node_group_add_socket(ntree, sock->name, sock->type, SOCK_OUT); @@ -997,6 +1001,129 @@ static void rna_NodeOutputFileSlotLayer_name_set(PointerRNA *ptr, const char *va } } +static bNodeSocket *rna_ShaderNodeScript_find_socket(bNode *node, const char *name, int is_output) +{ + bNodeSocket *sock; + + if (is_output) { + for (sock = node->outputs.first; sock; sock = sock->next) { + if (strcmp(sock->name, name) == 0) { + return sock; + } + } + } + else { + for (sock = node->inputs.first; sock; sock = sock->next) { + if (strcmp(sock->name, name) == 0) { + return sock; + } + } + } + + return NULL; +} + +static void rna_ShaderNodeScript_remove_socket(ID *id, bNode *node, bNodeSocket *sock) +{ + bNodeTree *ntree = (bNodeTree *)id; + + nodeRemoveSocket(ntree, node, sock); + + ED_node_generic_update(G.main, ntree, node); +} + +static bNodeSocket *rna_ShaderNodeScript_add_socket(ID *id, bNode *node, const char *name, int type, int is_output) +{ + bNodeTree *ntree = (bNodeTree *)id; + bNodeSocket *sock; + + /* replace existing socket with the same name, to keep it unique */ + sock = rna_ShaderNodeScript_find_socket(node, name, is_output); + if (sock) + nodeRemoveSocket(ntree, node, sock); + sock = nodeAddSocket(ntree, node, (is_output ? SOCK_OUT : SOCK_IN), name, type); + + ED_node_generic_update(G.main, ntree, node); + + return sock; +} + +static void rna_ShaderNodeScript_mode_set(PointerRNA *ptr, int value) +{ + bNode *node = (bNode *)ptr->data; + NodeShaderScript *nss = node->storage; + + if (nss->mode != value) { + nss->mode = value; + nss->filepath[0] = '\0'; + nss->flag &= ~NODE_SCRIPT_AUTO_UPDATE; + + /* replace text datablock by filepath */ + if (node->id) { + Text *text = (Text*)node->id; + + if (value == NODE_SCRIPT_EXTERNAL && text->name) { + BLI_strncpy(nss->filepath, text->name, sizeof(nss->filepath)); + BLI_path_rel(nss->filepath, G.main->name); + } + + id_us_min(node->id); + node->id = NULL; + } + + /* remove any bytecode */ + if (nss->bytecode) { + MEM_freeN(nss->bytecode); + nss->bytecode = NULL; + } + + nss->bytecode_hash[0] = '\0'; + } +} + +static void rna_ShaderNodeScript_bytecode_get(PointerRNA *ptr, char *value) +{ + bNode *node = (bNode *)ptr->data; + NodeShaderScript *nss = node->storage; + + strcpy(value, (nss->bytecode)? nss->bytecode: ""); +} + +static int rna_ShaderNodeScript_bytecode_length(PointerRNA *ptr) +{ + bNode *node = (bNode *)ptr->data; + NodeShaderScript *nss = node->storage; + + return (nss->bytecode) ? strlen(nss->bytecode) : 0; +} + +static void rna_ShaderNodeScript_bytecode_set(PointerRNA *ptr, const char *value) +{ + bNode *node = (bNode *)ptr->data; + NodeShaderScript *nss = node->storage; + + if (nss->bytecode) + MEM_freeN(nss->bytecode); + + if (value && value[0]) + nss->bytecode = BLI_strdup(value); + else + nss->bytecode = NULL; +} + +static IDProperty *rna_ShaderNodeScript_idprops(PointerRNA *ptr, int create) +{ + bNode *node = (bNode *)ptr->data; + NodeShaderScript *nss = node->storage; + + if (create && !nss->prop) { + IDPropertyTemplate val = {0}; + nss->prop = IDP_New(IDP_GROUP, &val, "RNA_ShaderNodeScript ID properties"); + } + + return nss->prop; +} + #else static EnumPropertyItem prop_image_layer_items[] = { @@ -1037,12 +1164,17 @@ static EnumPropertyItem node_glossy_items[] = { {0, NULL, 0, NULL, NULL} }; +static EnumPropertyItem node_script_mode_items[] = { + {NODE_SCRIPT_INTERNAL, "INTERNAL", 0, "Internal", "Use internal text datablock"}, + {NODE_SCRIPT_EXTERNAL, "EXTERNAL", 0, "External", "Use external .osl or oso file"}, + {0, NULL, 0, NULL, NULL} +}; + #define MaxNodes 50000 enum { Category_GroupNode, - Category_LoopNode, Category_LayoutNode, Category_ShaderNode, Category_CompositorNode, @@ -1086,8 +1218,6 @@ static void init(void) #include "rna_nodetree_types.h" reg_node(NODE_GROUP, Category_GroupNode, "GROUP", "NodeGroup", "SpecialNode", "Group", ""); - reg_node(NODE_FORLOOP, Category_LoopNode, "FORLOOP", "NodeForLoop", "SpecialNode", "ForLoop", ""); - reg_node(NODE_WHILELOOP, Category_LoopNode, "WHILELOOP", "NodeWhileLoop", "SpecialNode", "WhileLoop", ""); reg_node(NODE_FRAME, Category_LayoutNode, "FRAME", "NodeFrame", "SpecialNode", "Frame", ""); reg_node(NODE_REROUTE, Category_LayoutNode, "REROUTE", "NodeReroute", "SpecialNode", "Reroute", ""); } @@ -1166,36 +1296,6 @@ static void def_group(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeGroup_update"); } -static void def_forloop(StructRNA *srna) -{ - PropertyRNA *prop; - - prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "id"); - RNA_def_property_struct_type(prop, "NodeTree"); - RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Node Tree", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeGroup_update"); -} - -static void def_whileloop(StructRNA *srna) -{ - PropertyRNA *prop; - - prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "id"); - RNA_def_property_struct_type(prop, "NodeTree"); - RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Node Tree", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeGroup_update"); - - prop = RNA_def_property(srna, "max_iterations", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "custom1"); - RNA_def_property_range(prop, 0.0f, SHRT_MAX); - RNA_def_property_ui_text(prop, "Max. Iterations", "Limit for number of iterations"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeGroup_update"); -} - static void def_frame(StructRNA *srna) { PropertyRNA *prop; @@ -1462,7 +1562,8 @@ static void def_sh_tex_sky(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); prop = RNA_def_property(srna, "turbidity", PROP_FLOAT, PROP_NONE); - RNA_def_property_ui_text(prop, "Turbidity", ""); + RNA_def_property_range(prop, 1.0f, 30.0f); + RNA_def_property_ui_text(prop, "Turbidity", "Atmospheric turbidity"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } @@ -1720,6 +1821,16 @@ static void def_sh_tex_wave(StructRNA *srna) RNA_def_property_update(prop, 0, "rna_Node_update"); } +static void def_sh_tex_coord(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "from_dupli", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1); + RNA_def_property_ui_text(prop, "From Dupli", "Use the parent of the dupli object if possible"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + static void def_glossy(StructRNA *srna) { PropertyRNA *prop; @@ -1731,6 +1842,76 @@ static void def_glossy(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_sh_script(StructRNA *srna) +{ + FunctionRNA *func; + PropertyRNA *prop, *parm; + + prop = RNA_def_property(srna, "script", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "id"); + RNA_def_property_struct_type(prop, "Text"); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); + RNA_def_property_ui_text(prop, "Script", "Internal shader script to define the shader"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + RNA_def_struct_sdna_from(srna, "NodeShaderScript", "storage"); + RNA_def_struct_idprops_func(srna, "rna_ShaderNodeScript_idprops"); + + prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH); + RNA_def_property_ui_text(prop, "File Path", "Shader script path"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_funcs(prop, NULL, "rna_ShaderNodeScript_mode_set", NULL); + RNA_def_property_enum_items(prop, node_script_mode_items); + RNA_def_property_ui_text(prop, "Script Source", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "use_auto_update", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_SCRIPT_AUTO_UPDATE); + RNA_def_property_ui_text(prop, "Auto Update", "Automatically updates the shader when the .osl file changes - external scripts only"); + + prop = RNA_def_property(srna, "bytecode", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, "rna_ShaderNodeScript_bytecode_get", + "rna_ShaderNodeScript_bytecode_length", "rna_ShaderNodeScript_bytecode_set"); + RNA_def_property_ui_text(prop, "Bytecode", "Compile bytecode for shader script node"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "bytecode_hash", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Bytecode Hash", "Hash of compile bytecode, for quick equality checking"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + /* needs to be reset to avoid bad pointer type in API functions below */ + RNA_def_struct_sdna_from(srna, "bNode", NULL); + + /* API functions */ + + func = RNA_def_function(srna, "find_socket", "rna_ShaderNodeScript_find_socket"); + RNA_def_function_ui_description(func, "Find a socket by name"); + parm = RNA_def_string(func, "name", "", 0, "Socket name", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + /*parm =*/ RNA_def_boolean(func, "is_output", FALSE, "Output", "Whether the socket is an output"); + parm = RNA_def_pointer(func, "result", "NodeSocket", "", ""); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "add_socket", "rna_ShaderNodeScript_add_socket"); + RNA_def_function_ui_description(func, "Add a socket socket"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); + parm = RNA_def_string(func, "name", "", 0, "Name", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm = RNA_def_enum(func, "type", node_socket_type_items, SOCK_FLOAT, "Type", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + /*parm =*/ RNA_def_boolean(func, "is_output", FALSE, "Output", "Whether the socket is an output"); + parm = RNA_def_pointer(func, "result", "NodeSocket", "", ""); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove_socket", "rna_ShaderNodeScript_remove_socket"); + RNA_def_function_ui_description(func, "Remove a socket socket"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); + parm = RNA_def_pointer(func, "sock", "NodeSocket", "Socket", ""); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); +} + /* -- Compositor Nodes ------------------------------------------------------ */ static void def_cmp_alpha_over(StructRNA *srna) @@ -1803,7 +1984,7 @@ static void def_cmp_blur(StructRNA *srna) /* duplicated in def_cmp_bokehblur */ prop = RNA_def_property(srna, "use_variable_size", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", CMP_NODEFLAG_BLUR_VARIABLE_SIZE); - RNA_def_property_ui_text(prop, "Variable Size", "Support variable blue per-pixel when using an image for size input"); + RNA_def_property_ui_text(prop, "Variable Size", "Support variable blur per-pixel when using an image for size input"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); RNA_def_struct_sdna_from(srna, "NodeBlurData", "storage"); @@ -2195,14 +2376,14 @@ static void def_cmp_inpaint(StructRNA *srna) { PropertyRNA *prop; -/* +#if 0 prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, type_items); RNA_def_property_ui_text(prop, "Type", "Type of inpaint algorithm"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); -*/ +#endif prop = RNA_def_property(srna, "distance", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom2"); @@ -3839,7 +4020,7 @@ static void def_cmp_trackpos(StructRNA *srna) RNA_def_property_ui_text(prop, "Position", "Which marker position to use for output"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - prop = RNA_def_property(srna, "relative_frame", PROP_INT, PROP_NONE); + prop = RNA_def_property(srna, "frame_relative", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom2"); RNA_def_property_ui_text(prop, "Frame", "Frame to be used for relative position"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); @@ -3984,8 +4165,6 @@ static void rna_def_special_node(BlenderRNA *brna) static EnumPropertyItem specific_node_type_items[] = { {NODE_GROUP, "GROUP", ICON_NODE, "Group", ""}, - {NODE_FORLOOP, "FORLOOP", ICON_NODE, "For Loop", ""}, - {NODE_WHILELOOP, "WHILELOOP", ICON_NODE, "While Loop", ""}, {NODE_FRAME, "FRAME", ICON_NODE, "Frame", ""}, {NODE_REROUTE, "REROUTE", ICON_NODE, "Reroute", ""}, {0, NULL, 0, NULL, NULL} @@ -4029,14 +4208,15 @@ static void rna_def_nodetree_link_api(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "remove a node link from the node tree"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "link", "NodeLink", "", "The node link to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "clear", "rna_NodeTree_link_clear"); RNA_def_function_ui_description(func, "remove all node links from the node tree"); } /* shared between all note tree types*/ -static void rna_def_nodetree_active_api(StructRNA *srna, PropertyRNA *cprop) +static void rna_def_nodetree_active_api(StructRNA *srna, PropertyRNA *UNUSED(cprop)) { PropertyRNA *prop; @@ -4073,7 +4253,8 @@ static void rna_def_composite_nodetree_api(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove a node from this node tree"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "node", "Node", "", "The node to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "clear", "rna_NodeTree_node_clear"); RNA_def_function_ui_description(func, "Remove all nodes from this node tree"); @@ -4106,7 +4287,8 @@ static void rna_def_shader_nodetree_api(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove a node from this node tree"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "node", "Node", "", "The node to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "clear", "rna_NodeTree_node_clear"); RNA_def_function_ui_description(func, "Remove all nodes from this node tree"); @@ -4139,7 +4321,8 @@ static void rna_def_texture_nodetree_api(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove a node from this node tree"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "node", "Node", "", "The node to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "clear", "rna_NodeTree_node_clear"); RNA_def_function_ui_description(func, "Remove all nodes from this node tree"); @@ -4315,7 +4498,7 @@ static void rna_def_node(BlenderRNA *brna) prop = RNA_def_property(srna, "label", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "label"); RNA_def_property_ui_text(prop, "Label", "Optional custom node label"); - RNA_def_property_update(prop, NC_NODE, "rna_Node_update"); + RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL); prop = RNA_def_property(srna, "inputs", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "inputs", NULL); @@ -4608,8 +4791,6 @@ void RNA_def_nodetree(BlenderRNA *brna) #include "rna_nodetree_types.h" define_specific_node(brna, NODE_GROUP, def_group); - define_specific_node(brna, NODE_FORLOOP, def_forloop); - define_specific_node(brna, NODE_WHILELOOP, def_whileloop); define_specific_node(brna, NODE_FRAME, def_frame); define_specific_node(brna, NODE_REROUTE, 0); diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index 0baa4cc0838..c45c9b71442 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -67,6 +67,7 @@ DefNode( ShaderNode, SH_NODE_ADD_SHADER, 0, "AD DefNode( ShaderNode, SH_NODE_ATTRIBUTE, def_sh_attribute, "ATTRIBUTE", Attribute, "Attribute", "" ) DefNode( ShaderNode, SH_NODE_BACKGROUND, 0, "BACKGROUND", Background, "Background", "" ) DefNode( ShaderNode, SH_NODE_HOLDOUT, 0, "HOLDOUT", Holdout, "Holdout", "" ) +DefNode( ShaderNode, SH_NODE_BSDF_ANISOTROPIC, 0, "BSDF_ANISOTROPIC", BsdfAnisotropic, "Anisotropic Bsdf", "" ) DefNode( ShaderNode, SH_NODE_BSDF_DIFFUSE, 0, "BSDF_DIFFUSE", BsdfDiffuse, "Diffuse Bsdf", "" ) DefNode( ShaderNode, SH_NODE_BSDF_GLOSSY, def_glossy, "BSDF_GLOSSY", BsdfGlossy, "Glossy Bsdf", "" ) DefNode( ShaderNode, SH_NODE_BSDF_GLASS, def_glossy, "BSDF_GLASS", BsdfGlass, "Glass Bsdf", "" ) @@ -81,6 +82,8 @@ DefNode( ShaderNode, SH_NODE_LIGHT_PATH, 0, "LI DefNode( ShaderNode, SH_NODE_LIGHT_FALLOFF, 0, "LIGHT_FALLOFF", LightFalloff, "Light Falloff", "" ) DefNode( ShaderNode, SH_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "" ) DefNode( ShaderNode, SH_NODE_PARTICLE_INFO, 0, "PARTICLE_INFO", ParticleInfo, "Particle Info", "" ) +DefNode( ShaderNode, SH_NODE_BUMP, 0, "BUMP", BumpNode, "Bump", "" ) +DefNode( ShaderNode, SH_NODE_SCRIPT, def_sh_script, "SCRIPT", Script, "Script", "" ) DefNode( ShaderNode, SH_NODE_TEX_IMAGE, def_sh_tex_image, "TEX_IMAGE", TexImage, "Image Texture", "" ) DefNode( ShaderNode, SH_NODE_TEX_ENVIRONMENT, def_sh_tex_environment, "TEX_ENVIRONMENT", TexEnvironment, "Environment Texture","" ) DefNode( ShaderNode, SH_NODE_TEX_SKY, def_sh_tex_sky, "TEX_SKY", TexSky, "Sky Texture", "" ) @@ -91,8 +94,8 @@ DefNode( ShaderNode, SH_NODE_TEX_WAVE, def_sh_tex_wave, "TE DefNode( ShaderNode, SH_NODE_TEX_MUSGRAVE, def_sh_tex_musgrave, "TEX_MUSGRAVE", TexMusgrave, "Musgrave Texture", "" ) DefNode( ShaderNode, SH_NODE_TEX_VORONOI, def_sh_tex_voronoi, "TEX_VORONOI", TexVoronoi, "Voronoi Texture", "" ) DefNode( ShaderNode, SH_NODE_TEX_CHECKER, def_sh_tex_checker, "TEX_CHECKER", TexChecker, "Checker Texture", "" ) -DefNode( ShaderNode, SH_NODE_TEX_BRICK, def_sh_tex_brick, "TEX_BRICK", TexBrick, "Brick Texture", "" ) -DefNode( ShaderNode, SH_NODE_TEX_COORD, 0, "TEX_COORD", TexCoord, "Texture Coordinate","" ) +DefNode( ShaderNode, SH_NODE_TEX_BRICK, def_sh_tex_brick, "TEX_BRICK", TexBrick, "Brick Texture", "" ) +DefNode( ShaderNode, SH_NODE_TEX_COORD, def_sh_tex_coord, "TEX_COORD", TexCoord, "Texture Coordinate","" ) DefNode( CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" ) DefNode( CompositorNode, CMP_NODE_RGB, 0, "RGB", RGB, "RGB", "" ) diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index e69d313b23b..10f361ef1bd 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -69,6 +69,19 @@ EnumPropertyItem object_mode_items[] = { {0, NULL, 0, NULL, NULL} }; +EnumPropertyItem object_empty_drawtype_items[] = { + {OB_PLAINAXES, "PLAIN_AXES", 0, "Plain Axes", ""}, + {OB_ARROWS, "ARROWS", 0, "Arrows", ""}, + {OB_SINGLE_ARROW, "SINGLE_ARROW", 0, "Single Arrow", ""}, + {OB_CIRCLE, "CIRCLE", 0, "Circle", ""}, + {OB_CUBE, "CUBE", 0, "Cube", ""}, + {OB_EMPTY_SPHERE, "SPHERE", 0, "Sphere", ""}, + {OB_EMPTY_CONE, "CONE", 0, "Cone", ""}, + {OB_EMPTY_IMAGE, "IMAGE", 0, "Image", ""}, + {0, NULL, 0, NULL, NULL} +}; + + static EnumPropertyItem parent_type_items[] = { {PAROBJECT, "OBJECT", 0, "Object", "The object is parented to an object"}, {PARCURVE, "CURVE", 0, "Curve", "The object is parented to a curve"}, @@ -80,7 +93,7 @@ static EnumPropertyItem parent_type_items[] = { {PARBONE, "BONE", 0, "Bone", "The object is parented to a bone"}, {0, NULL, 0, NULL, NULL} }; - + static EnumPropertyItem collision_bounds_items[] = { {OB_BOUND_BOX, "BOX", 0, "Box", ""}, {OB_BOUND_SPHERE, "SPHERE", 0, "Sphere", ""}, @@ -231,7 +244,7 @@ void rna_Object_internal_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), WM_main_add_notifier(NC_OBJECT | ND_DRAW, ptr->id.data); } -void rna_Object_active_shape_update(Main *bmain, Scene *scene, PointerRNA *ptr) +static void rna_Object_active_shape_update(Main *bmain, Scene *scene, PointerRNA *ptr) { Object *ob = ptr->id.data; @@ -493,10 +506,10 @@ static void rna_Object_dup_group_set(PointerRNA *ptr, PointerRNA value) ob->dup_group = grp; else BKE_report(NULL, RPT_ERROR, - "Cannot set dupli-group as object belongs in group being instanced thus causing a cycle"); + "Cannot set dupli-group as object belongs in group being instanced, thus causing a cycle"); } -void rna_VertexGroup_name_set(PointerRNA *ptr, const char *value) +static void rna_VertexGroup_name_set(PointerRNA *ptr, const char *value) { Object *ob = (Object *)ptr->id.data; bDeformGroup *dg = (bDeformGroup *)ptr->data; @@ -838,11 +851,11 @@ static void rna_MaterialSlot_link_set(PointerRNA *ptr, int value) if (value) { ob->matbits[index] = 1; - /* ob->colbits |= (1<colbits |= (1 << index); */ /* DEPRECATED */ } else { ob->matbits[index] = 0; - /* ob->colbits &= ~(1<colbits &= ~(1 << index); */ /* DEPRECATED */ } } @@ -1023,8 +1036,8 @@ static unsigned int rna_Object_layer_validate__internal(const int *values, unsig return 0; for (i = 0; i < 20; i++) { - if (values[i]) lay |= (1 << i); - else lay &= ~(1 << i); + if (values[i]) lay |= (1 << i); + else lay &= ~(1 << i); } return lay; @@ -1059,8 +1072,9 @@ static void rna_GameObjectSettings_state_get(PointerRNA *ptr, int *values) int all_states = (ob->scaflag & OB_ALLSTATE ? 1 : 0); memset(values, 0, sizeof(int) * OB_MAX_STATES); - for (i = 0; i < OB_MAX_STATES; i++) + for (i = 0; i < OB_MAX_STATES; i++) { values[i] = (ob->state & (1 << i)) | all_states; + } } static void rna_GameObjectSettings_state_set(PointerRNA *ptr, const int *values) @@ -1098,10 +1112,69 @@ static void rna_GameObjectSettings_used_state_get(PointerRNA *ptr, int *values) } } +static void rna_GameObjectSettings_col_group_get(PointerRNA *ptr, int *values) +{ + Object *ob = (Object*)ptr->data; + int i; + + for (i = 0; i < OB_MAX_COL_MASKS; i++) { + values[i] = (ob->col_group & (1 << i)); + } +} + +static void rna_GameObjectSettings_col_group_set(PointerRNA *ptr, const int *values) +{ + Object *ob = (Object*)ptr->data; + int i, tot = 0; + + /* ensure we always have some group selected */ + for (i = 0; i < OB_MAX_COL_MASKS; i++) + if (values[i]) + tot++; + + if (tot == 0) + return; + + for (i = 0; i < OB_MAX_COL_MASKS; i++) { + if (values[i]) ob->col_group |= (1 << i); + else ob->col_group &= ~(1 << i); + } +} + +static void rna_GameObjectSettings_col_mask_get(PointerRNA *ptr, int *values) +{ + Object *ob = (Object*)ptr->data; + int i; + + for (i = 0; i < OB_MAX_COL_MASKS; i++) { + values[i] = (ob->col_mask & (1 << i)); + } +} + +static void rna_GameObjectSettings_col_mask_set(PointerRNA *ptr, const int *values) +{ + Object *ob = (Object*)ptr->data; + int i, tot = 0; + + /* ensure we always have some mask selected */ + for (i = 0; i < OB_MAX_COL_MASKS; i++) + if (values[i]) + tot++; + + if (tot == 0) + return; + + for (i = 0; i < OB_MAX_COL_MASKS; i++) { + if (values[i]) ob->col_mask |= (1 << i); + else ob->col_mask &= ~(1 << i); + } +} + + static void rna_Object_active_shape_key_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax) { Object *ob = (Object *)ptr->id.data; - Key *key = ob_get_key(ob); + Key *key = BKE_key_from_object(ob); *min = 0; if (key) { @@ -1130,7 +1203,7 @@ static void rna_Object_active_shape_key_index_set(PointerRNA *ptr, int value) static PointerRNA rna_Object_active_shape_key_get(PointerRNA *ptr) { Object *ob = (Object *)ptr->id.data; - Key *key = ob_get_key(ob); + Key *key = BKE_key_from_object(ob); KeyBlock *kb; PointerRNA keyptr; @@ -1186,14 +1259,17 @@ static bConstraint *rna_Object_constraints_new(Object *object, int type) return add_ob_constraint(object, NULL, type); } -static void rna_Object_constraints_remove(Object *object, ReportList *reports, bConstraint *con) +static void rna_Object_constraints_remove(Object *object, ReportList *reports, PointerRNA *con_ptr) { + bConstraint *con = con_ptr->data; if (BLI_findindex(&object->constraints, con) == -1) { BKE_reportf(reports, RPT_ERROR, "Constraint '%s' not found in object '%s'", con->name, object->id.name + 2); return; } remove_constraint(&object->constraints, con); + RNA_POINTER_INVALIDATE(con_ptr); + ED_object_constraint_update(object); ED_object_constraint_set_active(object, NULL); WM_main_add_notifier(NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, object); @@ -1215,9 +1291,15 @@ static ModifierData *rna_Object_modifier_new(Object *object, bContext *C, Report return ED_object_modifier_add(reports, CTX_data_main(C), CTX_data_scene(C), object, name, type); } -static void rna_Object_modifier_remove(Object *object, bContext *C, ReportList *reports, ModifierData *md) +static void rna_Object_modifier_remove(Object *object, bContext *C, ReportList *reports, PointerRNA *md_ptr) { - ED_object_modifier_remove(reports, CTX_data_main(C), CTX_data_scene(C), object, md); + ModifierData *md = md_ptr->data; + if (ED_object_modifier_remove(reports, CTX_data_main(C), CTX_data_scene(C), object, md) == FALSE) { + /* error is already set */ + return; + } + + RNA_POINTER_INVALIDATE(md_ptr); WM_main_add_notifier(NC_OBJECT | ND_MODIFIER | NA_REMOVED, object); } @@ -1251,9 +1333,16 @@ static bDeformGroup *rna_Object_vgroup_new(Object *ob, const char *name) return defgroup; } -static void rna_Object_vgroup_remove(Object *ob, bDeformGroup *defgroup) +static void rna_Object_vgroup_remove(Object *ob, ReportList *reports, PointerRNA *defgroup_ptr) { + bDeformGroup *defgroup = defgroup_ptr->data; + if (BLI_findindex(&ob->defbase, defgroup) == -1) { + BKE_reportf(reports, RPT_ERROR, "DeformGroup '%s' not in object '%s'", defgroup->name, ob->id.name + 2); + return; + } + ED_vgroup_delete(ob, defgroup); + RNA_POINTER_INVALIDATE(defgroup_ptr); WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob); } @@ -1271,7 +1360,7 @@ static void rna_VertexGroup_vertex_add(ID *id, bDeformGroup *def, ReportList *re Object *ob = (Object *)id; if (ED_vgroup_object_is_edit_mode(ob)) { - BKE_reportf(reports, RPT_ERROR, "VertexGroup.add(): Can't be called while object is in edit mode"); + BKE_report(reports, RPT_ERROR, "VertexGroup.add(): cannot be called while object is in edit mode"); return; } @@ -1286,7 +1375,7 @@ static void rna_VertexGroup_vertex_remove(ID *id, bDeformGroup *dg, ReportList * Object *ob = (Object *)id; if (ED_vgroup_object_is_edit_mode(ob)) { - BKE_reportf(reports, RPT_ERROR, "VertexGroup.remove(): Can't be called while object is in edit mode"); + BKE_report(reports, RPT_ERROR, "VertexGroup.remove(): cannot be called while object is in edit mode"); return; } @@ -1301,7 +1390,7 @@ static float rna_VertexGroup_weight(ID *id, bDeformGroup *dg, ReportList *report float weight = ED_vgroup_vert_weight((Object *)id, dg, index); if (weight < 0) { - BKE_reportf(reports, RPT_ERROR, "Vertex not in group"); + BKE_report(reports, RPT_ERROR, "Vertex not in group"); } return weight; } @@ -1565,6 +1654,17 @@ static void rna_def_object_game_settings(BlenderRNA *brna) RNA_def_property_range(prop, 0.0, 1000.0); RNA_def_property_ui_text(prop, "Fall Speed Max", "Maximum speed at which the character will fall"); + prop = RNA_def_property(srna, "collision_group", PROP_BOOLEAN, PROP_LAYER_MEMBER); + RNA_def_property_boolean_sdna(prop, NULL, "col_group", 1); + RNA_def_property_array(prop, OB_MAX_COL_MASKS); + RNA_def_property_ui_text(prop, "Collision Group", "The collision group of the object"); + RNA_def_property_boolean_funcs(prop, "rna_GameObjectSettings_col_group_get", "rna_GameObjectSettings_col_group_set"); + + prop = RNA_def_property(srna, "collision_mask", PROP_BOOLEAN, PROP_LAYER_MEMBER); + RNA_def_property_boolean_sdna(prop, NULL, "col_mask", 1); + RNA_def_property_array(prop, OB_MAX_COL_MASKS); + RNA_def_property_ui_text(prop, "Collision Mask", "The groups this object can collide with"); + RNA_def_property_boolean_funcs(prop, "rna_GameObjectSettings_col_mask_get", "rna_GameObjectSettings_col_mask_set"); /* lock position */ prop = RNA_def_property(srna, "lock_location_x", PROP_BOOLEAN, PROP_NONE); @@ -1732,7 +1832,8 @@ static void rna_def_object_constraints(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); /* constraint to remove */ parm = RNA_def_pointer(func, "constraint", "Constraint", "", "Removed constraint"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "clear", "rna_Object_constraints_clear"); RNA_def_function_ui_description(func, "Remove all constraint from this object"); @@ -1783,7 +1884,8 @@ static void rna_def_object_modifiers(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove an existing modifier from the object"); /* modifier to remove */ parm = RNA_def_pointer(func, "modifier", "Modifier", "", "Modifier to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); /* clear all modifiers */ func = RNA_def_function(srna, "clear", "rna_Object_modifier_clear"); @@ -1861,9 +1963,11 @@ static void rna_def_object_vertex_groups(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_return(func, parm); func = RNA_def_function(srna, "remove", "rna_Object_vgroup_remove"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Delete vertex group from object"); parm = RNA_def_pointer(func, "group", "VertexGroup", "", "Vertex group to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "clear", "rna_Object_vgroup_clear"); RNA_def_function_ui_description(func, "Delete all vertex groups from object"); @@ -1874,18 +1978,6 @@ static void rna_def_object(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - - static EnumPropertyItem empty_drawtype_items[] = { - {OB_PLAINAXES, "PLAIN_AXES", 0, "Plain Axes", ""}, - {OB_ARROWS, "ARROWS", 0, "Arrows", ""}, - {OB_SINGLE_ARROW, "SINGLE_ARROW", 0, "Single Arrow", ""}, - {OB_CIRCLE, "CIRCLE", 0, "Circle", ""}, - {OB_CUBE, "CUBE", 0, "Cube", ""}, - {OB_EMPTY_SPHERE, "SPHERE", 0, "Sphere", ""}, - {OB_EMPTY_CONE, "CONE", 0, "Cone", ""}, - {OB_EMPTY_IMAGE, "IMAGE", 0, "Image", ""}, - {0, NULL, 0, NULL, NULL} - }; static EnumPropertyItem track_items[] = { {OB_POSX, "POS_X", 0, "+X", ""}, @@ -2267,7 +2359,7 @@ static void rna_def_object(BlenderRNA *brna) /* empty */ prop = RNA_def_property(srna, "empty_draw_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "empty_drawtype"); - RNA_def_property_enum_items(prop, empty_drawtype_items); + RNA_def_property_enum_items(prop, object_empty_drawtype_items); RNA_def_property_ui_text(prop, "Empty Display Type", "Viewport display style for empties"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); @@ -2572,7 +2664,16 @@ static void rna_def_dupli_object(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); RNA_def_property_ui_text(prop, "Particle Index", "Index in the lowest-level particle dupli list"); - /* TODO: DupliObject has more properties that can be wrapped */ + prop = RNA_def_property(srna, "orco", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_float_sdna(prop, NULL, "orco"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Generated Coordinates", "Generated coordinates in parent object space"); + + prop = RNA_def_property(srna, "uv", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "uv"); + RNA_def_property_array(prop, 2); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); + RNA_def_property_ui_text(prop, "UV Coordinates", "UV coordinates in parent object space"); } static void rna_def_object_base(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 5bf1cc281ad..87fc3be28a2 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -39,6 +39,8 @@ #include "DNA_object_types.h" #include "DNA_modifier_types.h" +#include "rna_internal.h" /* own include */ + #ifdef RNA_RUNTIME #include "BLI_math.h" @@ -72,7 +74,7 @@ /* copied from Mesh_getFromObject and adapted to RNA interface */ /* settings: 0 - preview, 1 - render */ -Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_modifiers, int settings) +static Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_modifiers, int settings) { Mesh *tmpmesh; Curve *tmpcu = NULL, *copycu; @@ -94,7 +96,7 @@ Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_ float (*orco)[3] = NULL; /* copies object and modifiers (but not the data) */ - tmpobj = BKE_object_copy(ob); + tmpobj = BKE_object_copy_with_caches(ob); tmpcu = (Curve *)tmpobj->data; tmpcu->id.us--; @@ -156,7 +158,7 @@ Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_ /* BKE_mesh_from_nurbs changes the type to a mesh, check it worked */ if (tmpobj->type != OB_MESH) { BKE_libblock_free_us(&(G.main->object), tmpobj); - BKE_report(reports, RPT_ERROR, "cant convert curve to mesh. Does the curve have any segments?"); + BKE_report(reports, RPT_ERROR, "Cannot convert curve to mesh (does the curve have any segments?)"); return NULL; } @@ -175,6 +177,8 @@ Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_ return NULL; /* only do basis metaball */ tmpmesh = BKE_mesh_add("Mesh"); + /* BKE_mesh_add gives us a user count we don't need */ + tmpmesh->id.us--; if (render) { ListBase disp = {NULL, NULL}; @@ -184,6 +188,7 @@ Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_ } else BKE_mesh_from_metaball(&ob->disp, tmpmesh); + break; } @@ -212,6 +217,9 @@ Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_ dm->release(dm); } + /* BKE_mesh_add/copy gives us a user count we don't need */ + tmpmesh->id.us--; + break; default: BKE_report(reports, RPT_ERROR, "Object does not have geometry data"); @@ -281,9 +289,6 @@ Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_ /* cycles and exporters rely on this still */ BKE_mesh_tessface_ensure(tmpmesh); - /* we don't assign it to anything */ - tmpmesh->id.us--; - /* make sure materials get updated in objects */ test_object_materials(&tmpmesh->id); @@ -316,7 +321,7 @@ static void dupli_render_particle_set(Scene *scene, Object *ob, int level, int e } } - if (level == 0 && enable) { + if (enable) { /* this is to make sure we get render level duplis in groups: * the derivedmesh must be created before init_render_mesh, * since object_duplilist does dupliparticles before that */ @@ -335,8 +340,10 @@ static void dupli_render_particle_set(Scene *scene, Object *ob, int level, int e dupli_render_particle_set(scene, go->ob, level + 1, enable); } /* When no longer needed, duplilist should be freed with Object.free_duplilist */ -void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *sce) +static void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *sce, int settings) { + int for_render = settings == eModifierMode_Render; + if (!(ob->transflag & OB_DUPLI)) { BKE_report(reports, RPT_ERROR, "Object does not have duplis"); return; @@ -344,20 +351,20 @@ void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *sce) /* free duplilist if a user forgets to */ if (ob->duplilist) { - BKE_reportf(reports, RPT_WARNING, "Object.dupli_list has not been freed"); + BKE_report(reports, RPT_WARNING, "Object.dupli_list has not been freed"); free_object_duplilist(ob->duplilist); ob->duplilist = NULL; } if (G.is_rendering) dupli_render_particle_set(sce, ob, 0, 1); - ob->duplilist = object_duplilist(sce, ob); + ob->duplilist = object_duplilist(sce, ob, for_render); if (G.is_rendering) dupli_render_particle_set(sce, ob, 0, 0); /* ob->duplilist should now be freed with Object.free_duplilist */ } -void rna_Object_free_duplilist(Object *ob) +static void rna_Object_free_duplilist(Object *ob) { if (ob->duplilist) { free_object_duplilist(ob->duplilist); @@ -380,12 +387,12 @@ static PointerRNA rna_Object_shape_key_add(Object *ob, bContext *C, ReportList * return keyptr; } else { - BKE_reportf(reports, RPT_ERROR, "Object \"%s\"does not support shapes", ob->id.name + 2); + BKE_reportf(reports, RPT_ERROR, "Object '%s' does not support shapes", ob->id.name + 2); return PointerRNA_NULL; } } -int rna_Object_is_visible(Object *ob, Scene *sce) +static int rna_Object_is_visible(Object *ob, Scene *sce) { return !(ob->restrictflag & OB_RESTRICT_VIEW) && (ob->lay & sce->lay); } @@ -395,14 +402,14 @@ static void rna_Mesh_assign_verts_to_group(Object *ob, bDeformGroup *group, int float weight, int assignmode) { if (ob->type != OB_MESH) { - BKE_report(reports, RPT_ERROR, "Object should be of MESH type"); + BKE_report(reports, RPT_ERROR, "Object should be of mesh type"); return; } Mesh *me = (Mesh *)ob->data; int group_index = BLI_findlink(&ob->defbase, group); if (group_index == -1) { - BKE_report(reports, RPT_ERROR, "No deform groups assigned to mesh"); + BKE_report(reports, RPT_ERROR, "No vertex groups assigned to mesh"); return; } @@ -428,13 +435,13 @@ static void rna_Mesh_assign_verts_to_group(Object *ob, bDeformGroup *group, int #endif /* BMESH_TODO, return polygon index, not tessface */ -void rna_Object_ray_cast(Object *ob, ReportList *reports, float ray_start[3], float ray_end[3], - float r_location[3], float r_normal[3], int *index) +static void rna_Object_ray_cast(Object *ob, ReportList *reports, float ray_start[3], float ray_end[3], + float r_location[3], float r_normal[3], int *index) { BVHTreeFromMesh treeData = {NULL}; if (ob->derivedFinal == NULL) { - BKE_reportf(reports, RPT_ERROR, "object \"%s\" has no mesh data to be used for ray casting", ob->id.name + 2); + BKE_reportf(reports, RPT_ERROR, "Object '%s' has no mesh data to be used for ray casting", ob->id.name + 2); return; } @@ -442,7 +449,7 @@ void rna_Object_ray_cast(Object *ob, ReportList *reports, float ray_start[3], fl bvhtree_from_mesh_faces(&treeData, ob->derivedFinal, 0.0f, 4, 6); if (treeData.tree == NULL) { - BKE_reportf(reports, RPT_ERROR, "object \"%s\" could not create internal data for ray casting", ob->id.name + 2); + BKE_reportf(reports, RPT_ERROR, "Object '%s' could not create internal data for ray casting", ob->id.name + 2); return; } else { @@ -470,13 +477,13 @@ void rna_Object_ray_cast(Object *ob, ReportList *reports, float ray_start[3], fl *index = -1; } -void rna_Object_closest_point_on_mesh(Object *ob, ReportList *reports, float point_co[3], float max_dist, - float n_location[3], float n_normal[3], int *index) +static void rna_Object_closest_point_on_mesh(Object *ob, ReportList *reports, float point_co[3], float max_dist, + float n_location[3], float n_normal[3], int *index) { BVHTreeFromMesh treeData = {NULL}; if (ob->derivedFinal == NULL) { - BKE_reportf(reports, RPT_ERROR, "object \"%s\" has no mesh data to be used for finding nearest point", + BKE_reportf(reports, RPT_ERROR, "Object '%s' has no mesh data to be used for finding nearest point", ob->id.name + 2); return; } @@ -485,7 +492,7 @@ void rna_Object_closest_point_on_mesh(Object *ob, ReportList *reports, float poi bvhtree_from_mesh_faces(&treeData, ob->derivedFinal, 0.0f, 4, 6); if (treeData.tree == NULL) { - BKE_reportf(reports, RPT_ERROR, "object \"%s\" could not create internal data for finding nearest point", + BKE_reportf(reports, RPT_ERROR, "Object '%s' could not create internal data for finding nearest point", ob->id.name + 2); return; } @@ -510,17 +517,17 @@ void rna_Object_closest_point_on_mesh(Object *ob, ReportList *reports, float poi /* ObjectBase */ -void rna_ObjectBase_layers_from_view(Base *base, View3D *v3d) +static void rna_ObjectBase_layers_from_view(Base *base, View3D *v3d) { base->lay = base->object->lay = v3d->lay; } -int rna_Object_is_modified(Object *ob, Scene *scene, int settings) +static int rna_Object_is_modified(Object *ob, Scene *scene, int settings) { return BKE_object_is_modified(scene, ob) & settings; } -int rna_Object_is_deform_modified(Object *ob, Scene *scene, int settings) +static int rna_Object_is_deform_modified(Object *ob, Scene *scene, int settings) { return BKE_object_is_deform_modified(scene, ob) & settings; } @@ -606,6 +613,7 @@ void RNA_api_object(StructRNA *srna) "objects real matrix and layers"); parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene within which to evaluate duplis"); RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_enum(func, "settings", mesh_type_items, 0, "", "Generate texture coordinates for rendering"); RNA_def_function_flag(func, FUNC_USE_REPORTS); func = RNA_def_function(srna, "dupli_list_clear", "rna_Object_free_duplilist"); diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 1c896133408..f47b864d25a 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -820,10 +820,13 @@ static void rna_def_pointcache(BlenderRNA *brna) RNA_def_property_ui_text(prop, "File Path", "Cache file path"); RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change"); + /* removed, see PTCACHE_QUICK_CACHE */ +#if 0 prop = RNA_def_property(srna, "use_quick_cache", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_QUICK_CACHE); RNA_def_property_ui_text(prop, "Quick Cache", "Update simulation with cache steps"); RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change"); +#endif prop = RNA_def_property(srna, "info", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "info"); @@ -1056,6 +1059,13 @@ static void rna_def_effector_weight(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); RNA_def_property_ui_text(prop, "Drag", "Drag effector weight"); RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); + + prop = RNA_def_property(srna, "smokeflow", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "weight[13]"); + RNA_def_property_range(prop, -200.0f, 200.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); + RNA_def_property_ui_text(prop, "Smoke Flow", "Smoke Flow effector weight"); + RNA_def_property_update(prop, 0, "rna_EffectorWeight_update"); } static void rna_def_field(BlenderRNA *brna) @@ -1082,6 +1092,7 @@ static void rna_def_field(BlenderRNA *brna) {PFIELD_BOID, "BOID", ICON_FORCE_BOID, "Boid", ""}, {PFIELD_TURBULENCE, "TURBULENCE", ICON_FORCE_TURBULENCE, "Turbulence", "Create turbulence with a noise field"}, {PFIELD_DRAG, "DRAG", ICON_FORCE_DRAG, "Drag", "Create a force that dampens motion"}, + {PFIELD_SMOKEFLOW, "SMOKE_FLOW", ICON_FORCE_SMOKEFLOW, "Smoke Flow", "Create a force based on smoke simulation air flow"}, {0, NULL, 0, NULL, NULL} }; @@ -1307,7 +1318,7 @@ static void rna_def_field(BlenderRNA *brna) prop = RNA_def_property(srna, "use_2d_force", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_TEX_2D); - RNA_def_property_ui_text(prop, "2D", "Apply force only in 2d"); + RNA_def_property_ui_text(prop, "2D", "Apply force only in 2D"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); prop = RNA_def_property(srna, "use_root_coords", PROP_BOOLEAN, PROP_NONE); @@ -1334,6 +1345,11 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_MULTIPLE_SPRINGS); RNA_def_property_ui_text(prop, "Multiple Springs", "Every point is effected by multiple springs"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); + + prop = RNA_def_property(srna, "use_smoke_density", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_SMOKE_DENSITY); + RNA_def_property_ui_text(prop, "Apply Density", "Adjust force strength based on smoke density"); + RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); /* Pointer */ @@ -1342,6 +1358,12 @@ static void rna_def_field(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Texture", "Texture to use as force"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); + + prop = RNA_def_property(srna, "source_object", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "f_source"); + RNA_def_property_ui_text(prop, "Domain Object", "Select domain object of the smoke simulation"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); /********** Curve Guide Field Settings **********/ diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index fc3dfafe133..9ba2a062791 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -502,7 +502,7 @@ static int rna_PartSettings_is_fluid_get(PointerRNA *ptr) return part->type == PART_FLUID; } -void rna_ParticleSystem_name_set(PointerRNA *ptr, const char *value) +static void rna_ParticleSystem_name_set(PointerRNA *ptr, const char *value) { Object *ob = ptr->id.data; ParticleSystem *part = (ParticleSystem *)ptr->data; @@ -823,12 +823,12 @@ static void psys_vg_name_set__internal(PointerRNA *ptr, const char *value, int i psys->vgroup[index] = 0; } else { - int vgroup_num = defgroup_name_index(ob, value); + int defgrp_index = defgroup_name_index(ob, value); - if (vgroup_num == -1) + if (defgrp_index == -1) return; - psys->vgroup[index] = vgroup_num + 1; + psys->vgroup[index] = defgrp_index + 1; } } diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 739f302fcbe..c29537378dd 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -148,7 +148,7 @@ void rna_ActionGroup_colorset_set(PointerRNA *ptr, int value) } } -void rna_BoneGroup_name_set(PointerRNA *ptr, const char *value) +static void rna_BoneGroup_name_set(PointerRNA *ptr, const char *value) { Object *ob = ptr->id.data; bActionGroup *agrp = ptr->data; @@ -257,7 +257,7 @@ static int rna_PoseChannel_has_ik_get(PointerRNA *ptr) return ED_pose_channel_in_IK_chain(ob, pchan); } -StructRNA *rna_IKParam_refine(PointerRNA *ptr) +static StructRNA *rna_IKParam_refine(PointerRNA *ptr) { bIKParam *param = (bIKParam *)ptr->data; @@ -269,7 +269,7 @@ StructRNA *rna_IKParam_refine(PointerRNA *ptr) } } -PointerRNA rna_Pose_ikparam_get(struct PointerRNA *ptr) +static PointerRNA rna_Pose_ikparam_get(struct PointerRNA *ptr) { bPose *pose = (bPose *)ptr->data; return rna_pointer_inherit_refine(ptr, &RNA_IKParam, pose->ikparam); @@ -497,24 +497,28 @@ static bConstraint *rna_PoseChannel_constraints_new(bPoseChannel *pchan, int typ return add_pose_constraint(NULL, pchan, NULL, type); } -static void rna_PoseChannel_constraints_remove(ID *id, bPoseChannel *pchan, ReportList *reports, bConstraint *con) +static void rna_PoseChannel_constraints_remove(ID *id, bPoseChannel *pchan, ReportList *reports, PointerRNA *con_ptr) { + bConstraint *con = con_ptr->data; + const short is_ik = ELEM(con->type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK); + Object *ob = (Object *)id; + if (BLI_findindex(&pchan->constraints, con) == -1) { BKE_reportf(reports, RPT_ERROR, "Constraint '%s' not found in pose bone '%s'", con->name, pchan->name); return; } - else { - Object *ob = (Object *)id; - const short is_ik = ELEM(con->type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK); - remove_constraint(&pchan->constraints, con); - ED_object_constraint_update(ob); - constraints_set_active(&pchan->constraints, NULL); - WM_main_add_notifier(NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, id); + remove_constraint(&pchan->constraints, con); + RNA_POINTER_INVALIDATE(con_ptr); - if (is_ik) { - BIK_clear_data(ob->pose); - } + ED_object_constraint_update(ob); + + constraints_set_active(&pchan->constraints, NULL); /* XXX, is this really needed? - Campbell */ + + WM_main_add_notifier(NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, id); + + if (is_ik) { + BIK_clear_data(ob->pose); } } @@ -593,7 +597,7 @@ static int rna_PoseChannel_rotation_4d_editable(PointerRNA *ptr, int index) } /* not essential, but much faster then the default lookup function */ -int rna_PoseBones_lookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr) +static int rna_PoseBones_lookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr) { bPose *pose = (bPose *)ptr->data; bPoseChannel *pchan = BKE_pose_channel_find_name(pose, key); @@ -727,7 +731,8 @@ static void rna_def_pose_channel_constraints(BlenderRNA *brna, PropertyRNA *cpro RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); /* ID needed for refresh */ /* constraint to remove */ parm = RNA_def_pointer(func, "constraint", "Constraint", "", "Removed constraint"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } static void rna_def_pose_channel(BlenderRNA *brna) @@ -788,8 +793,6 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_editable_array_func(prop, "rna_PoseChannel_location_editable"); RNA_def_property_ui_text(prop, "Location", ""); RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); - /* XXX... disabled, since proxy-locked layers are currently used for ensuring proxy-syncing too */ - RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ); @@ -797,8 +800,6 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_editable_array_func(prop, "rna_PoseChannel_scale_editable"); RNA_def_property_float_array_default(prop, default_scale); RNA_def_property_ui_text(prop, "Scale", ""); - /* XXX... disabled, since proxy-locked layers are currently used for ensuring proxy-syncing too */ - RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); prop = RNA_def_property(srna, "rotation_quaternion", PROP_FLOAT, PROP_QUATERNION); @@ -806,8 +807,6 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_editable_array_func(prop, "rna_PoseChannel_rotation_4d_editable"); RNA_def_property_float_array_default(prop, default_quat); RNA_def_property_ui_text(prop, "Quaternion Rotation", "Rotation in Quaternions"); - /* XXX... disabled, since proxy-locked layers are currently used for ensuring proxy-syncing too */ - RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); /* XXX: for axis-angle, it would have been nice to have 2 separate fields for UI purposes, but @@ -820,15 +819,11 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_editable_array_func(prop, "rna_PoseChannel_rotation_4d_editable"); RNA_def_property_float_array_default(prop, default_axisAngle); RNA_def_property_ui_text(prop, "Axis-Angle Rotation", "Angle of Rotation for Axis-Angle rotation representation"); - /* XXX... disabled, since proxy-locked layers are currently used for ensuring proxy-syncing too */ - RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); prop = RNA_def_property(srna, "rotation_euler", PROP_FLOAT, PROP_EULER); RNA_def_property_float_sdna(prop, NULL, "eul"); RNA_def_property_editable_array_func(prop, "rna_PoseChannel_rotation_euler_editable"); - /* XXX... disabled, since proxy-locked layers are currently used for ensuring proxy-syncing too */ - RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable"); RNA_def_property_ui_text(prop, "Euler Rotation", "Rotation in Eulers"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); @@ -1310,7 +1305,7 @@ static void rna_def_pose(BlenderRNA *brna) /* animviz */ rna_def_animviz_common(srna); - /* RNA_api_pose(srna); */ + RNA_api_pose(srna); } void RNA_def_pose(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_pose_api.c b/source/blender/makesrna/intern/rna_pose_api.c index ed4690ac6a7..29d7c616d25 100644 --- a/source/blender/makesrna/intern/rna_pose_api.c +++ b/source/blender/makesrna/intern/rna_pose_api.c @@ -34,12 +34,16 @@ #include #include +#include "BLI_utildefines.h" + #include "RNA_define.h" #include "DNA_object_types.h" /* #include "BLO_sys_types.h" */ +#include "rna_internal.h" /* own include */ + #ifdef RNA_RUNTIME /* #include "DNA_anim_types.h" */ @@ -57,7 +61,7 @@ static float rna_PoseBone_do_envelope(bPoseChannel *chan, float *vec) } #else -void RNA_api_pose(StructRNA *srna) +void RNA_api_pose(StructRNA *UNUSED(srna)) { /* FunctionRNA *func; */ /* PropertyRNA *parm; */ diff --git a/source/blender/makesrna/intern/rna_property.c b/source/blender/makesrna/intern/rna_property.c index bf9f924489b..fc3697633a4 100644 --- a/source/blender/makesrna/intern/rna_property.c +++ b/source/blender/makesrna/intern/rna_property.c @@ -89,7 +89,7 @@ static void rna_GameProperty_type_set(PointerRNA *ptr, int value) if (prop->type != value) { prop->type = value; - init_property(prop); + BKE_bproperty_init(prop); } } @@ -97,7 +97,7 @@ static void rna_GameProperty_name_set(PointerRNA *ptr, const char *value) { bProperty *prop = (bProperty *)(ptr->data); BLI_strncpy_utf8(prop->name, value, sizeof(prop->name)); - unique_property(NULL, prop, 1); + BKE_bproperty_unique(NULL, prop, 1); } diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index d2e4e8edbfb..46b22cd0963 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -50,12 +50,12 @@ /* RenderEngine Callbacks */ -void engine_tag_redraw(RenderEngine *engine) +static void engine_tag_redraw(RenderEngine *engine) { engine->flag |= RE_ENGINE_DO_DRAW; } -void engine_tag_update(RenderEngine *engine) +static void engine_tag_update(RenderEngine *engine) { engine->flag |= RE_ENGINE_DO_UPDATE; } @@ -129,6 +129,24 @@ static void engine_view_draw(RenderEngine *engine, const struct bContext *contex RNA_parameter_list_free(&list); } +static void engine_update_script_node(RenderEngine *engine, struct bNodeTree *ntree, struct bNode *node) +{ + extern FunctionRNA rna_RenderEngine_update_script_node_func; + PointerRNA ptr, nodeptr; + ParameterList list; + FunctionRNA *func; + + RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr); + RNA_pointer_create((ID*)ntree, &RNA_Node, node, &nodeptr); + func = &rna_RenderEngine_update_script_node_func; + + RNA_parameter_list_create(&list, &ptr, func); + RNA_parameter_set_lookup(&list, "node", &nodeptr); + engine->type->ext.call(NULL, &ptr, func, &list); + + RNA_parameter_list_free(&list); +} + /* RenderEngine registration */ static void rna_RenderEngine_unregister(Main *UNUSED(bmain), StructRNA *type) @@ -149,7 +167,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo RenderEngineType *et, dummyet = {NULL}; RenderEngine dummyengine = {NULL}; PointerRNA dummyptr; - int have_function[4]; + int have_function[5]; /* setup dummy engine & engine type to store static properties in */ dummyengine.type = &dummyet; @@ -160,7 +178,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo return NULL; if (strlen(identifier) >= sizeof(dummyet.idname)) { - BKE_reportf(reports, RPT_ERROR, "registering render engine class: '%s' is too long, maximum length is %d", + BKE_reportf(reports, RPT_ERROR, "Registering render engine class: '%s' is too long, maximum length is %d", identifier, (int)sizeof(dummyet.idname)); return NULL; } @@ -188,6 +206,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo et->render = (have_function[1]) ? engine_render : NULL; et->view_update = (have_function[2]) ? engine_view_update : NULL; et->view_draw = (have_function[3]) ? engine_view_draw : NULL; + et->update_script_node = (have_function[4]) ? engine_update_script_node : NULL; BLI_addtail(&R_engines, et); @@ -300,6 +319,13 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL); RNA_def_pointer(func, "context", "Context", "", ""); + /* shader script callbacks */ + func = RNA_def_function(srna, "update_script_node", NULL); + RNA_def_function_ui_description(func, "Compile shader script node"); + RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE); + prop = RNA_def_pointer(func, "node", "Node", "", ""); + RNA_def_property_flag(prop, PROP_RNAPTR); + /* tag for redraw */ RNA_def_function(srna, "tag_redraw", "engine_tag_redraw"); RNA_def_function_ui_description(func, "Request redraw for viewport rendering"); @@ -328,8 +354,7 @@ static void rna_def_render_engine(BlenderRNA *brna) func = RNA_def_function(srna, "end_result", "RE_engine_end_result"); prop = RNA_def_pointer(func, "result", "RenderResult", "Result", ""); RNA_def_property_flag(prop, PROP_REQUIRED); - prop = RNA_def_boolean(func, "cancel", 0, "Cancel", "Don't merge back results"); - RNA_def_property_flag(prop, PROP_REQUIRED); + RNA_def_boolean(func, "cancel", 0, "Cancel", "Don't merge back results"); func = RNA_def_function(srna, "test_break", "RE_engine_test_break"); prop = RNA_def_boolean(func, "do_break", 0, "Break", ""); @@ -345,6 +370,11 @@ static void rna_def_render_engine(BlenderRNA *brna) prop = RNA_def_float(func, "progress", 0, 0.0f, 1.0f, "", "Percentage of render that's done", 0.0f, 1.0f); RNA_def_property_flag(prop, PROP_REQUIRED); + func = RNA_def_function(srna, "update_memory_stats", "RE_engine_update_memory_stats"); + RNA_def_float(func, "memory_used", 0, 0.0f, FLT_MAX, "", "Current memory usage in megabytes", 0.0f, FLT_MAX); + RNA_def_float(func, "memory_peak", 0, 0.0f, FLT_MAX, "", "Peak memory usage in megabytes", 0.0f, FLT_MAX); + RNA_def_property_flag(prop, PROP_REQUIRED); + func = RNA_def_function(srna, "report", "RE_engine_report"); prop = RNA_def_enum_flag(func, "type", wm_report_items, 0, "Type", ""); RNA_def_property_flag(prop, PROP_REQUIRED); diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index db309ed8f1f..7355e464fc3 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -829,7 +829,7 @@ static void rna_EnumProperty_items_begin(CollectionPropertyIterator *iter, Point int totitem, free = 0; rna_idproperty_check(&prop, ptr); - /* eprop= (EnumPropertyRNA *)prop; */ + /* eprop = (EnumPropertyRNA *)prop; */ RNA_property_enum_items(NULL, ptr, prop, &item, &totitem, &free); rna_iterator_array_begin(iter, (void *)item, sizeof(EnumPropertyItem), totitem, free, rna_enum_check_separator); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 0227d9c1554..69bb1cc98ff 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -159,12 +159,13 @@ EnumPropertyItem snap_node_element_items[] = { #define R_IMF_ENUM_TAGA_RAW {R_IMF_IMTYPE_RAWTGA, "TARGA_RAW", ICON_FILE_IMAGE, "Targa Raw", \ "Output image in uncompressed Targa format"}, - +#if 0 /* UNUSED (so far) */ #ifdef WITH_DDS # define R_IMF_ENUM_DDS {R_IMF_IMTYPE_DDS, "DDS", ICON_FILE_IMAGE, "DDS", "Output image in DDS format"}, #else # define R_IMF_ENUM_DDS #endif +#endif #ifdef WITH_OPENJPEG # define R_IMF_ENUM_JPEG2K {R_IMF_IMTYPE_JP2, "JPEG2000", ICON_FILE_IMAGE, "JPEG 2000", \ @@ -275,6 +276,7 @@ EnumPropertyItem image_color_mode_items[] = { EnumPropertyItem image_color_depth_items[] = { /* 1 (monochrome) not used */ {R_IMF_CHAN_DEPTH_8, "8", 0, "8", "8 bit color channels"}, + {R_IMF_CHAN_DEPTH_10, "10", 0, "10", "10 bit color channels"}, {R_IMF_CHAN_DEPTH_12, "12", 0, "12", "12 bit color channels"}, {R_IMF_CHAN_DEPTH_16, "16", 0, "16", "16 bit color channels"}, /* 24 not used */ @@ -356,7 +358,7 @@ static Base *rna_Scene_object_link(Scene *scene, bContext *C, ReportList *report Base *base; if (BKE_scene_base_find(scene, ob)) { - BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is already in scene \"%s\"", ob->id.name + 2, scene->id.name + 2); + BKE_reportf(reports, RPT_ERROR, "Object '%s' is already in scene '%s'", ob->id.name + 2, scene->id.name + 2); return NULL; } @@ -388,7 +390,7 @@ static void rna_Scene_object_unlink(Scene *scene, ReportList *reports, Object *o return; } if (base == scene->basact && ob->mode != OB_MODE_OBJECT) { - BKE_reportf(reports, RPT_ERROR, "Object '%s' must be in 'Object Mode' to unlink", ob->id.name + 2); + BKE_reportf(reports, RPT_ERROR, "Object '%s' must be in object mode to unlink", ob->id.name + 2); return; } if (scene->basact == base) { @@ -498,7 +500,7 @@ static void rna_Scene_framelen_update(Main *UNUSED(bmain), Scene *scene, Pointer } -static void rna_Scene_current_frame_set(PointerRNA *ptr, int value) +static void rna_Scene_frame_current_set(PointerRNA *ptr, int value) { Scene *data = (Scene *)ptr->data; @@ -713,6 +715,7 @@ static void rna_ImageFormatSettings_file_format_set(PointerRNA *ptr, int value) R_IMF_CHAN_DEPTH_24, R_IMF_CHAN_DEPTH_16, R_IMF_CHAN_DEPTH_12, + R_IMF_CHAN_DEPTH_10, R_IMF_CHAN_DEPTH_8, R_IMF_CHAN_DEPTH_1, 0}; @@ -810,9 +813,10 @@ static EnumPropertyItem *rna_ImageFormatSettings_color_depth_itemf(bContext *C, const int is_float = ELEM3(imf->imtype, R_IMF_IMTYPE_RADHDR, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER); EnumPropertyItem *item_8bit = &image_color_depth_items[0]; - EnumPropertyItem *item_12bit = &image_color_depth_items[1]; - EnumPropertyItem *item_16bit = &image_color_depth_items[2]; - EnumPropertyItem *item_32bit = &image_color_depth_items[3]; + EnumPropertyItem *item_10bit = &image_color_depth_items[1]; + EnumPropertyItem *item_12bit = &image_color_depth_items[2]; + EnumPropertyItem *item_16bit = &image_color_depth_items[3]; + EnumPropertyItem *item_32bit = &image_color_depth_items[4]; int totitem = 0; EnumPropertyItem *item = NULL; @@ -822,6 +826,10 @@ static EnumPropertyItem *rna_ImageFormatSettings_color_depth_itemf(bContext *C, RNA_enum_item_add(&item, &totitem, item_8bit); } + if (depth_ok & R_IMF_CHAN_DEPTH_10) { + RNA_enum_item_add(&item, &totitem, item_10bit); + } + if (depth_ok & R_IMF_CHAN_DEPTH_12) { RNA_enum_item_add(&item, &totitem, item_12bit); } @@ -1025,17 +1033,20 @@ static SceneRenderLayer *rna_RenderLayer_new(ID *id, RenderData *UNUSED(rd), con } static void rna_RenderLayer_remove(ID *id, RenderData *UNUSED(rd), Main *bmain, ReportList *reports, - SceneRenderLayer *srl) + PointerRNA *srl_ptr) { + SceneRenderLayer *srl = srl_ptr->data; Scene *scene = (Scene *)id; if (!BKE_scene_remove_render_layer(bmain, scene, srl)) { - BKE_reportf(reports, RPT_ERROR, "RenderLayer '%s' could not be removed from scene '%s'", + BKE_reportf(reports, RPT_ERROR, "Render layer '%s' could not be removed from scene '%s'", srl->name, scene->id.name + 2); + return; } - else { - WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL); - } + + RNA_POINTER_INVALIDATE(srl_ptr); + + WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL); } static void rna_RenderSettings_engine_set(PointerRNA *ptr, int value) @@ -1208,9 +1219,12 @@ static void object_simplify_update(Object *ob) ModifierData *md; ParticleSystem *psys; - for (md = ob->modifiers.first; md; md = md->next) - if (ELEM3(md->type, eModifierType_Subsurf, eModifierType_Multires, eModifierType_ParticleSystem)) - ob->recalc |= OB_RECALC_DATA | PSYS_RECALC_CHILD; + for (md = ob->modifiers.first; md; md = md->next) { + if (ELEM3(md->type, eModifierType_Subsurf, eModifierType_Multires, eModifierType_ParticleSystem)) { + ob->recalc |= PSYS_RECALC_CHILD; + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + } + } for (psys = ob->particlesystem.first; psys; psys = psys->next) psys->recalc |= PSYS_RECALC_CHILD; @@ -1322,15 +1336,16 @@ static TimeMarker *rna_TimeLine_add(Scene *scene, const char name[]) return marker; } -static void rna_TimeLine_remove(Scene *scene, ReportList *reports, TimeMarker *marker) +static void rna_TimeLine_remove(Scene *scene, ReportList *reports, PointerRNA *marker_ptr) { - if (!BLI_remlink_safe(&scene->markers, marker)) { - BKE_reportf(reports, RPT_ERROR, "TimelineMarker '%s' not found in scene '%s'", marker->name, scene->id.name + 2); + TimeMarker *marker = marker_ptr->data; + if (BLI_remlink_safe(&scene->markers, marker) == FALSE) { + BKE_reportf(reports, RPT_ERROR, "Timeline marker '%s' not found in scene '%s'", marker->name, scene->id.name + 2); return; } - /* XXX, invalidates PyObject */ MEM_freeN(marker); + RNA_POINTER_INVALIDATE(marker_ptr); WM_main_add_notifier(NC_SCENE | ND_MARKERS, NULL); WM_main_add_notifier(NC_ANIMATION | ND_MARKERS, NULL); @@ -1356,7 +1371,7 @@ static KeyingSet *rna_Scene_keying_set_new(Scene *sce, ReportList *reports, cons return ks; } else { - BKE_report(reports, RPT_ERROR, "Keying Set could not be added"); + BKE_report(reports, RPT_ERROR, "Keying set could not be added"); return NULL; } } @@ -1403,6 +1418,12 @@ static void rna_SceneCamera_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po DAG_id_tag_update(&camera->id, 0); } +static void rna_SceneSequencer_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) +{ + BKE_sequencer_cache_cleanup(); + BKE_sequencer_preprocessed_cache_cleanup(); +} + #else static void rna_def_transform_orientation(BlenderRNA *brna) @@ -2795,7 +2816,8 @@ static void rna_def_render_layers(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove a render layer"); RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS | FUNC_USE_SELF_ID); parm = RNA_def_pointer(func, "layer", "SceneRenderLayer", "", "Timeline marker to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } /* use for render output and image save operator, @@ -2887,7 +2909,6 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna) #endif - #ifdef WITH_OPENJPEG /* Jpeg 2000 */ prop = RNA_def_property(srna, "use_jpeg2k_ycc", PROP_BOOLEAN, PROP_NONE); @@ -2909,7 +2930,7 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna) /* Cineon and DPX */ prop = RNA_def_property(srna, "use_cineon_log", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "cineon_flag", R_CINEON_LOG); + RNA_def_property_boolean_sdna(prop, NULL, "cineon_flag", R_IMF_CINEON_FLAG_LOG); RNA_def_property_ui_text(prop, "Log", "Convert to logarithmic color space"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); @@ -3105,6 +3126,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Volume", "Audio volume"); + RNA_def_property_translation_context(prop, "Audio"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); #endif @@ -3373,16 +3395,16 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Resolution %", "Percentage scale for render resolution"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - prop = RNA_def_property(srna, "parts_x", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "xparts"); - RNA_def_property_range(prop, 1, 512); - RNA_def_property_ui_text(prop, "Parts X", "Number of horizontal tiles to use while rendering"); + prop = RNA_def_property(srna, "tile_x", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "tilex"); + RNA_def_property_range(prop, 8, 10000); + RNA_def_property_ui_text(prop, "Tile X", "Horizontal tile size to use while rendering"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - prop = RNA_def_property(srna, "parts_y", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "yparts"); - RNA_def_property_range(prop, 1, 512); - RNA_def_property_ui_text(prop, "Parts Y", "Number of vertical tiles to use while rendering"); + prop = RNA_def_property(srna, "tile_y", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "tiley"); + RNA_def_property_range(prop, 8, 10000); + RNA_def_property_ui_text(prop, "Tile Y", "Vertical tile size to use while rendering"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "pixel_aspect_x", PROP_FLOAT, PROP_NONE); @@ -3598,14 +3620,14 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "mode", R_MBLUR); RNA_def_property_ui_text(prop, "Motion Blur", "Use multi-sampled 3D scene motion blur"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update"); prop = RNA_def_property(srna, "motion_blur_samples", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "mblur_samples"); RNA_def_property_range(prop, 1, 32); RNA_def_property_ui_text(prop, "Motion Samples", "Number of scene samples to take with motion blur"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update"); prop = RNA_def_property(srna, "motion_blur_shutter", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "blurfac"); @@ -3613,7 +3635,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.01, 2.0f, 1, 0); RNA_def_property_ui_text(prop, "Shutter", "Time taken in frames between shutter open and close"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update"); /* border */ prop = RNA_def_property(srna, "use_border", PROP_BOOLEAN, PROP_NONE); @@ -3928,15 +3950,17 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "seq_flag", R_SEQ_GL_PREV); RNA_def_property_ui_text(prop, "Sequencer OpenGL", ""); +#if 0 /* see R_SEQ_GL_REND comment */ prop = RNA_def_property(srna, "use_sequencer_gl_render", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "seq_flag", R_SEQ_GL_REND); RNA_def_property_ui_text(prop, "Sequencer OpenGL", ""); - +#endif prop = RNA_def_property(srna, "sequencer_gl_preview", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "seq_prev_type"); RNA_def_property_enum_items(prop, viewport_shade_items); RNA_def_property_ui_text(prop, "Sequencer Preview Shading", "Method to draw in the sequencer view"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SceneSequencer_update"); prop = RNA_def_property(srna, "sequencer_gl_render", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "seq_rend_type"); @@ -3962,6 +3986,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_enum_items(prop, engine_items); RNA_def_property_enum_funcs(prop, "rna_RenderSettings_engine_get", "rna_RenderSettings_engine_set", "rna_RenderSettings_engine_itemf"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Engine", "Engine to use for rendering"); RNA_def_property_update(prop, NC_WINDOW, "rna_RenderSettings_engine_update"); @@ -4103,7 +4128,8 @@ static void rna_def_timeline_markers(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove a timeline marker"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "marker", "TimelineMarker", "", "Timeline marker to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "clear", "rna_TimeLine_clear"); RNA_def_function_ui_description(func, "Remove all timeline markers"); @@ -4299,7 +4325,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_int_sdna(prop, NULL, "r.cfra"); RNA_def_property_range(prop, MINAFRAME, MAXFRAME); - RNA_def_property_int_funcs(prop, NULL, "rna_Scene_current_frame_set", NULL); + RNA_def_property_int_funcs(prop, NULL, "rna_Scene_frame_current_set", NULL); RNA_def_property_ui_text(prop, "Current Frame", "Current Frame, to update animation data from python frame_set() instead"); RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_frame_update"); @@ -4515,6 +4541,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "audio.volume"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Volume", "Audio volume"); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); RNA_def_property_update(prop, NC_SCENE, NULL); RNA_def_property_float_funcs(prop, NULL, "rna_Scene_volume_set", NULL); @@ -4566,7 +4593,7 @@ void RNA_def_scene(BlenderRNA *brna) prop = RNA_def_property(srna, "sequencer_colorspace_settings", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "sequencer_colorspace_settings"); RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings"); - RNA_def_property_ui_text(prop, "Sequencer Colorspace Settings", "Settings of color space sequencer is working in"); + RNA_def_property_ui_text(prop, "Sequencer Color Space Settings", "Settings of color space sequencer is working in"); /* Nestled Data */ rna_def_tool_settings(brna); diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 69b61b47d8a..63253153699 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -40,6 +40,8 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "rna_internal.h" /* own include */ + #ifdef RNA_RUNTIME #include "BKE_animsys.h" @@ -51,7 +53,7 @@ -void rna_Scene_frame_set(Scene *scene, int frame, float subframe) +static void rna_Scene_frame_set(Scene *scene, int frame, float subframe) { scene->r.cfra = frame; scene->r.subframe = subframe; @@ -87,29 +89,29 @@ static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, char *name #include "../../collada/collada.h" static void rna_Scene_collada_export( - Scene *scene, - const char *filepath, - int apply_modifiers, - int export_mesh_type, + Scene *scene, + const char *filepath, + int apply_modifiers, + int export_mesh_type, - int selected, - int include_children, - int include_armatures, - int deform_bones_only, + int selected, + int include_children, + int include_armatures, + int deform_bones_only, - int active_uv_only, - int include_uv_textures, - int include_material_textures, - int use_texture_copies, + int active_uv_only, + int include_uv_textures, + int include_material_textures, + int use_texture_copies, - int use_object_instantiation, - int sort_by_name, - int second_life) + int use_object_instantiation, + int sort_by_name, + int second_life) { - collada_export(scene, filepath, apply_modifiers, export_mesh_type, selected, + collada_export(scene, filepath, apply_modifiers, export_mesh_type, selected, include_children, include_armatures, deform_bones_only, - active_uv_only, include_uv_textures, include_material_textures, - use_texture_copies, use_object_instantiation, sort_by_name, second_life); + active_uv_only, include_uv_textures, include_material_textures, + use_texture_copies, use_object_instantiation, sort_by_name, second_life); } #endif diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c index a6d4e473df4..32e388598f5 100644 --- a/source/blender/makesrna/intern/rna_screen.c +++ b/source/blender/makesrna/intern/rna_screen.c @@ -140,12 +140,12 @@ static void rna_Area_type_update(bContext *C, PointerRNA *ptr) } } -void rna_View2D_region_to_view(struct View2D *v2d, int x, int y, float result[2]) +static void rna_View2D_region_to_view(struct View2D *v2d, int x, int y, float result[2]) { UI_view2d_region_to_view(v2d, x, y, &result[0], &result[1]); } -void rna_View2D_view_to_region(struct View2D *v2d, float x, float y, int clip, int result[2]) +static void rna_View2D_view_to_region(struct View2D *v2d, float x, float y, int clip, int result[2]) { if (clip) UI_view2d_view_to_region(v2d, x, y, &result[0], &result[1]); diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index 58d676555c1..84e76fae896 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -60,6 +60,8 @@ static EnumPropertyItem particle_edit_hair_brush_items[] = { #include "BKE_particle.h" #include "BKE_depsgraph.h" +#include "BLI_pbvh.h" + #include "ED_particle.h" static EnumPropertyItem particle_edit_disconnected_hair_brush_items[] = { @@ -206,6 +208,21 @@ static void rna_Sculpt_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNU } } +static void rna_Sculpt_ShowDiffuseColor_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) +{ + Object *ob = (scene->basact) ? scene->basact->object : NULL; + + if (ob) { + Sculpt *sd = scene->toolsettings->sculpt; + ob->sculpt->show_diffuse_color = sd->flags & SCULPT_SHOW_DIFFUSE; + + if (ob->sculpt->pbvh) + pbvh_show_diffuse_color_set(ob->sculpt->pbvh, ob->sculpt->show_diffuse_color); + + WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob); + } +} + #else static void rna_def_paint(BlenderRNA *brna) @@ -297,6 +314,12 @@ static void rna_def_sculpt(BlenderRNA *brna) "Use only deformation modifiers (temporary disable all " "constructive modifiers except multi-resolution)"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Sculpt_update"); + + prop = RNA_def_property(srna, "show_diffuse_color", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_SHOW_DIFFUSE); + RNA_def_property_ui_text(prop, "Show Diffuse Color", + "Show diffuse color of object and overlay sculpt mask on top of it"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Sculpt_ShowDiffuseColor_update"); } diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c index 314082dfd02..6097fa2ae96 100644 --- a/source/blender/makesrna/intern/rna_sensor.c +++ b/source/blender/makesrna/intern/rna_sensor.c @@ -104,7 +104,7 @@ static StructRNA *rna_Sensor_refine(struct PointerRNA *ptr) } } -void rna_Sensor_name_set(PointerRNA *ptr, const char *value) +static void rna_Sensor_name_set(PointerRNA *ptr, const char *value) { bSensor *sens = (bSensor *)ptr->data; diff --git a/source/blender/makesrna/intern/rna_sensor_api.c b/source/blender/makesrna/intern/rna_sensor_api.c index fd0c6f622ff..d920cbef4a2 100644 --- a/source/blender/makesrna/intern/rna_sensor_api.c +++ b/source/blender/makesrna/intern/rna_sensor_api.c @@ -35,6 +35,8 @@ #include "WM_types.h" #include "RNA_define.h" +#include "rna_internal.h" /* own include */ + #ifdef RNA_RUNTIME #include "BKE_sca.h" diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index b27148e964d..054d0cc82c6 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -50,6 +50,8 @@ #include "WM_types.h" #include "BLI_math.h" +#include "BLF_translation.h" + typedef struct EffectInfo { const char *struct_name; const char *ui_name; @@ -405,7 +407,7 @@ static void rna_Sequence_name_set(PointerRNA *ptr, const char *value) BLI_strncpy_utf8(seq->name + 2, value, sizeof(seq->name) - 2); /* make sure the name is unique */ - BKE_seqence_base_unique_name_recursive(&scene->ed->seqbase, seq); + BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); /* fix all the animation data which may link to this */ @@ -699,12 +701,6 @@ static int colbalance_seq_cmp_cb(Sequence *seq, void *arg_pt) { SequenceSearchData *data = arg_pt; - if (seq->strip && seq->strip->color_balance == data->data) { - data->seq = seq; - data->smd = NULL; - return -1; /* done so bail out */ - } - if (seq->modifiers.first) { SequenceModifierData *smd = seq->modifiers.first; @@ -970,18 +966,20 @@ static SequenceModifierData *rna_Sequence_modifier_new(Sequence *seq, bContext * } } -static void rna_Sequence_modifier_remove(Sequence *seq, bContext *C, ReportList *reports, SequenceModifierData *smd) +static void rna_Sequence_modifier_remove(Sequence *seq, bContext *C, ReportList *reports, PointerRNA *smd_ptr) { + SequenceModifierData *smd = smd_ptr->data; Scene *scene = CTX_data_scene(C); - if (BKE_sequence_modifier_remove(seq, smd)) { - BKE_sequence_invalidate_cache_for_modifier(scene, seq); - - WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); - } - else { + if (BKE_sequence_modifier_remove(seq, smd) == FALSE) { BKE_report(reports, RPT_ERROR, "Modifier was not found in the stack"); + return; } + + RNA_POINTER_INVALIDATE(smd_ptr); + BKE_sequence_invalidate_cache_for_modifier(scene, seq); + + WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); } static void rna_Sequence_modifier_clear(Sequence *seq, bContext *C) @@ -1271,7 +1269,8 @@ static void rna_def_sequence_modifiers(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove an existing modifier from the sequence"); /* modifier to remove */ parm = RNA_def_pointer(func, "modifier", "SequenceModifier", "", "Modifier to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); /* clear all modifiers */ func = RNA_def_function(srna, "clear", "rna_Sequence_modifier_clear"); @@ -1679,14 +1678,14 @@ static void rna_def_effect_inputs(StructRNA *srna, int count) RNA_def_property_ui_text(prop, "Input 2", "Second input for the effect strip"); } - /* +#if 0 if (count == 3) { // not used by any effects (perhaps one day plugins?) prop = RNA_def_property(srna, "input_3", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "seq3"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_NULL); RNA_def_property_ui_text(prop, "Input 3", "Third input for the effect strip"); } - */ +#endif } static void rna_def_image(BlenderRNA *brna) @@ -1864,6 +1863,7 @@ static void rna_def_sound(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "volume"); RNA_def_property_range(prop, 0.0f, 100.0f); RNA_def_property_ui_text(prop, "Volume", "Playback volume of the sound"); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_volume_set", NULL); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); @@ -1871,6 +1871,7 @@ static void rna_def_sound(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "pitch"); RNA_def_property_range(prop, 0.1f, 10.0f); RNA_def_property_ui_text(prop, "Pitch", "Playback pitch of the sound"); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_pitch_set", NULL); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index ab1dfbf22b0..8ddb9d0a7e7 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -37,8 +37,6 @@ #include "DNA_scene_types.h" #include "DNA_sequence_types.h" -extern EnumPropertyItem blend_mode_items[]; - #ifdef RNA_RUNTIME //#include "DNA_anim_types.h" @@ -83,7 +81,7 @@ static Sequence *alloc_generic_sequence(Editing *ed, const char *name, int start seq->type = type; BLI_strncpy(seq->name + 2, name, sizeof(seq->name) - 2); - BKE_seqence_base_unique_name_recursive(&ed->seqbase, seq); + BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq); seq->strip = strip = MEM_callocN(sizeof(Strip), "strip"); seq->strip->us = 1; @@ -236,9 +234,10 @@ static Sequence *rna_Sequences_new_sound(ID *id, Editing *ed, Main *bmain, Repor } #else /* WITH_AUDASPACE */ static Sequence *rna_Sequences_new_sound(ID *UNUSED(id), Editing *UNUSED(ed), Main *UNUSED(bmain), ReportList *reports, - const char *UNUSED(name), const char *UNUSED(file), int UNUSED(channel), int UNUSED(start_frame)) + const char *UNUSED(name), const char *UNUSED(file), int UNUSED(channel), + int UNUSED(start_frame)) { - BKE_report(reports, RPT_ERROR, "Blender compiled without Audaspace support."); + BKE_report(reports, RPT_ERROR, "Blender compiled without Audaspace support"); return NULL; } #endif /* WITH_AUDASPACE */ @@ -251,39 +250,37 @@ static Sequence *rna_Sequences_new_effect(ID *id, Editing *ed, ReportList *repor Scene *scene = (Scene *)id; Sequence *seq; struct SeqEffectHandle sh; + int num_inputs = BKE_sequence_effect_get_num_inputs(type); - switch (BKE_sequence_effect_get_num_inputs(type)) { + switch (num_inputs) { case 0: if (end_frame <= start_frame) { - BKE_report(reports, RPT_ERROR, - "Sequences.new_effect: End frame not set"); + BKE_report(reports, RPT_ERROR, "Sequences.new_effect: end frame not set"); return NULL; } break; case 1: if (seq1 == NULL) { - BKE_report(reports, RPT_ERROR, - "Sequences.new_effect: Effect takes 1 input sequence"); + BKE_report(reports, RPT_ERROR, "Sequences.new_effect: effect takes 1 input sequence"); return NULL; } break; case 2: if (seq1 == NULL || seq2 == NULL) { - BKE_report(reports, RPT_ERROR, - "Sequences.new_effect: Effect takes 2 input sequences"); + BKE_report(reports, RPT_ERROR, "Sequences.new_effect: effect takes 2 input sequences"); return NULL; } break; case 3: if (seq1 == NULL || seq2 == NULL || seq3 == NULL) { - BKE_report(reports, RPT_ERROR, - "Sequences.new_effect: Effect takes 3 input sequences"); + BKE_report(reports, RPT_ERROR, "Sequences.new_effect: effect takes 3 input sequences"); return NULL; } break; default: - BKE_report(reports, RPT_ERROR, - "Sequences.new_effect: BKE_sequence_effect_get_num_inputs() > 3 (should never happen)"); + BKE_reportf(reports, RPT_ERROR, + "Sequences.new_effect: effect expects more than 3 inputs (%d, should never happen!)", + num_inputs); return NULL; } @@ -311,12 +308,18 @@ static Sequence *rna_Sequences_new_effect(ID *id, Editing *ed, ReportList *repor return seq; } -static void rna_Sequences_remove(ID *id, Editing *ed, Sequence *seq) +static void rna_Sequences_remove(ID *id, Editing *ed, ReportList *reports, PointerRNA *seq_ptr) { + Sequence *seq = seq_ptr->data; Scene *scene = (Scene *)id; - BLI_remlink(&ed->seqbase, seq); + if (BLI_remlink_safe(&ed->seqbase, seq) == FALSE) { + BKE_reportf(reports, RPT_ERROR, "Sequence '%s' not in scene '%s'", seq->name + 2, scene->id.name + 2); + return; + } + BKE_sequence_free(scene, seq); + RNA_POINTER_INVALIDATE(seq_ptr); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene); } @@ -344,7 +347,7 @@ static void rna_SequenceElements_pop(ID *id, Sequence *seq, ReportList *reports, StripElem *new_seq, *se; if (seq->len == 1) { - BKE_report(reports, RPT_ERROR, "SequenceElements.pop: can not pop the last element"); + BKE_report(reports, RPT_ERROR, "SequenceElements.pop: cannot pop the last element"); return; } @@ -458,7 +461,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "new_clip", "rna_Sequences_new_clip"); RNA_def_function_flag(func, FUNC_USE_SELF_ID); RNA_def_function_ui_description(func, "Add a new movie clip sequence"); - parm = RNA_def_string(func, "name", "Name", 0, "", "New name for the sequence"); + parm = RNA_def_string(func, "name", "Name", 0, "", "Name for the new sequence"); RNA_def_property_flag(parm, PROP_REQUIRED); parm = RNA_def_pointer(func, "clip", "MovieClip", "", "Movie clip to add"); RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); @@ -474,8 +477,8 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "new_mask", "rna_Sequences_new_mask"); RNA_def_function_flag(func, FUNC_USE_SELF_ID); - RNA_def_function_ui_description(func, "Add a new movie clip sequence"); - parm = RNA_def_string(func, "name", "Name", 0, "", "New name for the sequence"); + RNA_def_function_ui_description(func, "Add a new mask sequence"); + parm = RNA_def_string(func, "name", "Name", 0, "", "Name for the new sequence"); RNA_def_property_flag(parm, PROP_REQUIRED); parm = RNA_def_pointer(func, "mask", "Mask", "", "Mask to add"); RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); @@ -492,7 +495,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "new_scene", "rna_Sequences_new_scene"); RNA_def_function_flag(func, FUNC_USE_SELF_ID); RNA_def_function_ui_description(func, "Add a new scene sequence"); - parm = RNA_def_string(func, "name", "Name", 0, "", "New name for the sequence"); + parm = RNA_def_string(func, "name", "Name", 0, "", "Name for the new sequence"); RNA_def_property_flag(parm, PROP_REQUIRED); parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene to add"); RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); @@ -509,7 +512,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "new_image", "rna_Sequences_new_image"); RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); RNA_def_function_ui_description(func, "Add a new image sequence"); - parm = RNA_def_string(func, "name", "Name", 0, "", "New name for the sequence"); + parm = RNA_def_string(func, "name", "Name", 0, "", "Name for the new sequence"); RNA_def_property_flag(parm, PROP_REQUIRED); parm = RNA_def_string(func, "filepath", "File", 0, "", "Filepath to image"); RNA_def_property_flag(parm, PROP_REQUIRED); @@ -526,7 +529,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "new_movie", "rna_Sequences_new_movie"); RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); RNA_def_function_ui_description(func, "Add a new movie sequence"); - parm = RNA_def_string(func, "name", "Name", 0, "", "New name for the sequence"); + parm = RNA_def_string(func, "name", "Name", 0, "", "Name for the new sequence"); RNA_def_property_flag(parm, PROP_REQUIRED); parm = RNA_def_string(func, "filepath", "File", 0, "", "Filepath to movie"); RNA_def_property_flag(parm, PROP_REQUIRED); @@ -542,8 +545,8 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "new_sound", "rna_Sequences_new_sound"); RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID | FUNC_USE_MAIN); - RNA_def_function_ui_description(func, "Add a new movie clip sequence"); - parm = RNA_def_string(func, "name", "Name", 0, "", "New name for the sequence"); + RNA_def_function_ui_description(func, "Add a new sound sequence"); + parm = RNA_def_string(func, "name", "Name", 0, "", "Name for the new sequence"); RNA_def_property_flag(parm, PROP_REQUIRED); parm = RNA_def_string(func, "filepath", "File", 0, "", "Filepath to movie"); RNA_def_property_flag(parm, PROP_REQUIRED); @@ -560,7 +563,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "new_effect", "rna_Sequences_new_effect"); RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); RNA_def_function_ui_description(func, "Add a new effect sequence"); - parm = RNA_def_string(func, "name", "Name", 0, "", "New name for the sequence"); + parm = RNA_def_string(func, "name", "Name", 0, "", "Name for the new sequence"); RNA_def_property_flag(parm, PROP_REQUIRED); parm = RNA_def_enum(func, "type", seq_effect_items, 0, "Type", "type for the new sequence"); @@ -571,21 +574,22 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop) parm = RNA_def_int(func, "start_frame", 0, -MAXFRAME, MAXFRAME, "", "The start frame for the new sequence", -MAXFRAME, MAXFRAME); RNA_def_property_flag(parm, PROP_REQUIRED); - parm = RNA_def_int(func, "end_frame", 0, -MAXFRAME, MAXFRAME, "", - "The end frame for the new sequence", -MAXFRAME, MAXFRAME); - parm = RNA_def_pointer(func, "seq1", "Sequence", "", "Sequence 1 for effect"); - parm = RNA_def_pointer(func, "seq2", "Sequence", "", "Sequence 2 for effect"); - parm = RNA_def_pointer(func, "seq3", "Sequence", "", "Sequence 3 for effect"); + RNA_def_int(func, "end_frame", 0, -MAXFRAME, MAXFRAME, "", + "The end frame for the new sequence", -MAXFRAME, MAXFRAME); + RNA_def_pointer(func, "seq1", "Sequence", "", "Sequence 1 for effect"); + RNA_def_pointer(func, "seq2", "Sequence", "", "Sequence 2 for effect"); + RNA_def_pointer(func, "seq3", "Sequence", "", "Sequence 3 for effect"); /* return type */ parm = RNA_def_pointer(func, "sequence", "Sequence", "", "New Sequence"); RNA_def_function_return(func, parm); func = RNA_def_function(srna, "remove", "rna_Sequences_remove"); - RNA_def_function_flag(func, FUNC_USE_SELF_ID); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove a Sequence"); parm = RNA_def_pointer(func, "sequence", "Sequence", "", "Sequence to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c index e8818248609..bdcda79583e 100644 --- a/source/blender/makesrna/intern/rna_smoke.c +++ b/source/blender/makesrna/intern/rna_smoke.c @@ -65,14 +65,20 @@ static void rna_Smoke_dependency_update(Main *bmain, Scene *scene, PointerRNA *p DAG_scene_sort(bmain, scene); } +static void rna_Smoke_resetCache(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data; + if (settings->smd && settings->smd->domain) + settings->point_cache[0]->flag |= PTCACHE_OUTDATED; + DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA); +} + static void rna_Smoke_reset(Main *bmain, Scene *scene, PointerRNA *ptr) { SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data; smokeModifier_reset(settings->smd); - - if (settings->smd && settings->smd->domain) - settings->point_cache[0]->flag |= PTCACHE_OUTDATED; + rna_Smoke_resetCache(bmain, scene, ptr); rna_Smoke_update(bmain, scene, ptr); } @@ -142,6 +148,30 @@ static void rna_SmokeModifier_density_get(PointerRNA *ptr, float *values) memcpy(values, density, size * sizeof(float)); } +static void rna_SmokeFlow_density_vgroup_get(PointerRNA *ptr, char *value) +{ + SmokeFlowSettings *flow = (SmokeFlowSettings *)ptr->data; + rna_object_vgroup_name_index_get(ptr, value, flow->vgroup_density); +} + +static int rna_SmokeFlow_density_vgroup_length(PointerRNA *ptr) +{ + SmokeFlowSettings *flow = (SmokeFlowSettings *)ptr->data; + return rna_object_vgroup_name_index_length(ptr, flow->vgroup_density); +} + +static void rna_SmokeFlow_density_vgroup_set(PointerRNA *ptr, const char *value) +{ + SmokeFlowSettings *flow = (SmokeFlowSettings *)ptr->data; + rna_object_vgroup_name_index_set(ptr, value, &flow->vgroup_density); +} + +static void rna_SmokeFlow_uvlayer_set(PointerRNA *ptr, const char *value) +{ + SmokeFlowSettings *flow = (SmokeFlowSettings *)ptr->data; + rna_object_uvlayer_name_set(ptr, value, flow->uvlayer_name, sizeof(flow->uvlayer_name)); +} + #else static void rna_def_smoke_domain_settings(BlenderRNA *brna) @@ -217,7 +247,7 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) RNA_def_property_ui_range(prop, -5.0, 5.0, 0.02, 5); RNA_def_property_ui_text(prop, "Density", "How much density affects smoke motion (higher value results in faster rising smoke)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache"); prop = RNA_def_property(srna, "beta", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "beta"); @@ -225,7 +255,7 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) RNA_def_property_ui_range(prop, -5.0, 5.0, 0.02, 5); RNA_def_property_ui_text(prop, "Heat", "How much heat affects smoke motion (higher value results in faster rising smoke)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache"); prop = RNA_def_property(srna, "collision_group", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "coll_group"); @@ -253,24 +283,24 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) RNA_def_property_range(prop, 0.0, 10.0); RNA_def_property_ui_range(prop, 0.0, 10.0, 1, 2); RNA_def_property_ui_text(prop, "Strength", "Strength of noise"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache"); prop = RNA_def_property(srna, "dissolve_speed", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "diss_speed"); RNA_def_property_range(prop, 1.0, 10000.0); RNA_def_property_ui_range(prop, 1.0, 10000.0, 1, 0); RNA_def_property_ui_text(prop, "Dissolve Speed", "Dissolve Speed"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache"); prop = RNA_def_property(srna, "use_dissolve_smoke", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_DISSOLVE); RNA_def_property_ui_text(prop, "Dissolve Smoke", "Enable smoke to disappear over time"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache"); prop = RNA_def_property(srna, "use_dissolve_smoke_log", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_DISSOLVE_LOG); RNA_def_property_ui_text(prop, "Logarithmic dissolve", "Using 1/x "); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache"); prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); @@ -297,21 +327,21 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "smooth_emitter", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_HIGH_SMOOTH); RNA_def_property_ui_text(prop, "Smooth Emitter", "Smooth emitted smoke to avoid blockiness"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache"); prop = RNA_def_property(srna, "time_scale", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "time_scale"); RNA_def_property_range(prop, 0.2, 1.5); RNA_def_property_ui_range(prop, 0.2, 1.5, 0.02, 5); RNA_def_property_ui_text(prop, "Time Scale", "Adjust simulation speed"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache"); prop = RNA_def_property(srna, "vorticity", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "vorticity"); RNA_def_property_range(prop, 0.01, 4.0); RNA_def_property_ui_range(prop, 0.01, 4.0, 0.02, 5); RNA_def_property_ui_text(prop, "Vorticity", "Amount of turbulence/rotation in fluid"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache"); prop = RNA_def_property(srna, "density", PROP_FLOAT, PROP_NONE); RNA_def_property_array(prop, 32); @@ -321,25 +351,81 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) RNA_def_property_float_funcs(prop, "rna_SmokeModifier_density_get", NULL, NULL); RNA_def_property_ui_text(prop, "Density", "Smoke density"); - prop = RNA_def_property(srna, "cell_size", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "dx"); + prop = RNA_def_property(srna, "cell_size", PROP_FLOAT, PROP_XYZ); /* can change each frame when using adaptive domain */ RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "dx", "Cell Size"); + RNA_def_property_ui_text(prop, "cell_size", "Cell Size"); - prop = RNA_def_property(srna, "start_point", PROP_FLOAT, PROP_XYZ); + prop = RNA_def_property(srna, "start_point", PROP_FLOAT, PROP_XYZ); /* can change each frame when using adaptive domain */ RNA_def_property_float_sdna(prop, NULL, "p0"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "p0", "Start point"); - prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "scale"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "scale", "Domain scale factor"); - - prop = RNA_def_property(srna, "domain_resolution", PROP_INT, PROP_XYZ); + prop = RNA_def_property(srna, "domain_resolution", PROP_INT, PROP_XYZ); /* can change each frame when using adaptive domain */ RNA_def_property_int_sdna(prop, NULL, "res"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "res", "Smoke Grid Resolution"); + + prop = RNA_def_property(srna, "burning_rate", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.01, 4.0); + RNA_def_property_ui_range(prop, 0.01, 2.0, 1.0, 5); + RNA_def_property_ui_text(prop, "Speed", "Speed of the burning reaction (use larger values for smaller flame)"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache"); + + prop = RNA_def_property(srna, "flame_smoke", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.0, 8.0); + RNA_def_property_ui_range(prop, 0.0, 4.0, 1.0, 5); + RNA_def_property_ui_text(prop, "Smoke", "Amount of smoke created by burning fuel"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache"); + + prop = RNA_def_property(srna, "flame_vorticity", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.0, 2.0); + RNA_def_property_ui_range(prop, 0.0, 1.0, 1.0, 5); + RNA_def_property_ui_text(prop, "Vorticity", "Additional vorticity for the flames"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache"); + + prop = RNA_def_property(srna, "flame_ignition", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.5, 5.0); + RNA_def_property_ui_range(prop, 0.5, 2.5, 1.0, 5); + RNA_def_property_ui_text(prop, "Ignition", "Minimum temperature of flames"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache"); + + prop = RNA_def_property(srna, "flame_max_temp", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 1.0, 10.0); + RNA_def_property_ui_range(prop, 1.0, 5.0, 1.0, 5); + RNA_def_property_ui_text(prop, "Maximum", "Maximum temperature of flames"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache"); + + prop = RNA_def_property(srna, "flame_smoke_color", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Smoke Color", "Color of smoke emitted from burning fuel"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache"); + + prop = RNA_def_property(srna, "use_adaptive_domain", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_ADAPTIVE_DOMAIN); + RNA_def_property_ui_text(prop, "Adaptive Domain", "Adapt simulation resolution and size to fluid"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + + prop = RNA_def_property(srna, "additional_res", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "adapt_res"); + RNA_def_property_range(prop, 0, 512); + RNA_def_property_ui_range(prop, 0, 512, 2, 0); + RNA_def_property_ui_text(prop, "Additional", "Maximum number of additional cells"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache"); + + prop = RNA_def_property(srna, "adapt_margin", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "adapt_margin"); + RNA_def_property_range(prop, 2, 24); + RNA_def_property_ui_range(prop, 2, 24, 2, 0); + RNA_def_property_ui_text(prop, "Margin", "Margin added around fluid to minimize boundary interference"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache"); + + prop = RNA_def_property(srna, "adapt_threshold", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.01, 0.5); + RNA_def_property_ui_range(prop, 0.01, 0.5, 1.0, 5); + RNA_def_property_ui_text(prop, "Threshold", + "Maximum amount of fluid cell can contain before it is considered empty"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache"); } static void rna_def_smoke_flow_settings(BlenderRNA *brna) @@ -347,6 +433,26 @@ static void rna_def_smoke_flow_settings(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; + static EnumPropertyItem smoke_flow_types[] = { + {MOD_SMOKE_FLOW_TYPE_OUTFLOW, "OUTFLOW", 0, "Outflow", "Delete smoke from simulation"}, + {MOD_SMOKE_FLOW_TYPE_SMOKE, "SMOKE", 0, "Smoke", "Add smoke"}, + {MOD_SMOKE_FLOW_TYPE_SMOKEFIRE, "BOTH", 0, "Fire + Smoke", "Add fire and smoke"}, + {MOD_SMOKE_FLOW_TYPE_FIRE, "FIRE", 0, "Fire", "Add fire"}, + {0, NULL, 0, NULL, NULL} + }; + + static EnumPropertyItem smoke_flow_sources[] = { + {MOD_SMOKE_FLOW_SOURCE_PARTICLES, "PARTICLES", ICON_PARTICLES, "Particle System", "Emit smoke from particles"}, + {MOD_SMOKE_FLOW_SOURCE_MESH, "MESH", ICON_META_CUBE, "Mesh", "Emit smoke from mesh surface or volume"}, + {0, NULL, 0, NULL, NULL} + }; + + static EnumPropertyItem smoke_flow_texture_types[] = { + {MOD_SMOKE_FLOW_TEXTURE_MAP_AUTO, "AUTO", 0, "Generated", "Generated coordinates centered to flow object"}, + {MOD_SMOKE_FLOW_TEXTURE_MAP_UV, "UV", 0, "UV", "Use UV layer for texture coordinates"}, + {0, NULL, 0, NULL, NULL} + }; + srna = RNA_def_struct(brna, "SmokeFlowSettings", NULL); RNA_def_struct_ui_text(srna, "Flow Settings", "Smoke flow settings"); RNA_def_struct_sdna(srna, "SmokeFlowSettings"); @@ -354,11 +460,23 @@ static void rna_def_smoke_flow_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "density", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "density"); - RNA_def_property_range(prop, 0.001, 1); - RNA_def_property_ui_range(prop, 0.001, 1.0, 1.0, 4); + RNA_def_property_range(prop, 0.0, 1); + RNA_def_property_ui_range(prop, 0.0, 1.0, 1.0, 4); RNA_def_property_ui_text(prop, "Density", ""); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + prop = RNA_def_property(srna, "smoke_color", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "color"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Smoke Color", "Color of smoke"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + + prop = RNA_def_property(srna, "fuel_amount", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.0, 10); + RNA_def_property_ui_range(prop, 0.0, 5.0, 1.0, 4); + RNA_def_property_ui_text(prop, "Flame Rate", ""); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + prop = RNA_def_property(srna, "temperature", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "temp"); RNA_def_property_range(prop, -10, 10); @@ -373,9 +491,16 @@ static void rna_def_smoke_flow_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Particle Systems", "Particle systems emitted from the object"); RNA_def_property_update(prop, 0, "rna_Smoke_reset_dependancy"); - prop = RNA_def_property(srna, "use_outflow", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "type", MOD_SMOKE_FLOW_TYPE_OUTFLOW); - RNA_def_property_ui_text(prop, "Outflow", "Delete smoke from simulation"); + prop = RNA_def_property(srna, "smoke_flow_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "type"); + RNA_def_property_enum_items(prop, smoke_flow_types); + RNA_def_property_ui_text(prop, "Flow Type", "Change how flow affects the simulation"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + + prop = RNA_def_property(srna, "smoke_flow_source", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "source"); + RNA_def_property_enum_items(prop, smoke_flow_sources); + RNA_def_property_ui_text(prop, "Source", "Change how smoke is emitted"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); prop = RNA_def_property(srna, "use_absolute", PROP_BOOLEAN, PROP_NONE); @@ -385,14 +510,82 @@ static void rna_def_smoke_flow_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "initial_velocity", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_FLOW_INITVELOCITY); - RNA_def_property_ui_text(prop, "Initial Velocity", "Smoke inherits its velocity from the emitter particle"); + RNA_def_property_ui_text(prop, "Initial Velocity", "Smoke has some initial velocity when it is emitted"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); prop = RNA_def_property(srna, "velocity_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "vel_multi"); RNA_def_property_range(prop, -2.0, 2.0); RNA_def_property_ui_range(prop, -2.0, 2.0, 0.05, 5); - RNA_def_property_ui_text(prop, "Multiplier", "Multiplier to adjust velocity passed to smoke"); + RNA_def_property_ui_text(prop, "Source", "Multiplier of source velocity passed to smoke"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + + prop = RNA_def_property(srna, "velocity_normal", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "vel_normal"); + RNA_def_property_range(prop, -2.0, 2.0); + RNA_def_property_ui_range(prop, -2.0, 2.0, 0.05, 5); + RNA_def_property_ui_text(prop, "Normal", "Amount of normal directional velocity"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + + prop = RNA_def_property(srna, "velocity_random", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "vel_random"); + RNA_def_property_range(prop, 0.0, 2.0); + RNA_def_property_ui_range(prop, 0.0, 2.0, 0.05, 5); + RNA_def_property_ui_text(prop, "Random", "Amount of random velocity"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + + prop = RNA_def_property(srna, "volume_density", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_ui_range(prop, 0.0, 1.0, 0.05, 5); + RNA_def_property_ui_text(prop, "Volume", "Factor for smoke emitted from inside the mesh volume"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + + prop = RNA_def_property(srna, "surface_distance", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.5, 10.0); + RNA_def_property_ui_range(prop, 0.5, 5.0, 0.05, 5); + RNA_def_property_ui_text(prop, "Surface", "Maximum distance from mesh surface to emit smoke"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + + prop = RNA_def_property(srna, "density_vertex_group", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, "rna_SmokeFlow_density_vgroup_get", + "rna_SmokeFlow_density_vgroup_length", + "rna_SmokeFlow_density_vgroup_set"); + RNA_def_property_ui_text(prop, "Vertex Group", + "Name of vertex group which determines surface emission rate"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + + prop = RNA_def_property(srna, "use_texture", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SMOKE_FLOW_TEXTUREEMIT); + RNA_def_property_ui_text(prop, "Use Texture", "Use a texture to control emission strength"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + + prop = RNA_def_property(srna, "texture_map_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "texture_type"); + RNA_def_property_enum_items(prop, smoke_flow_texture_types); + RNA_def_property_ui_text(prop, "Mapping", "Texture mapping type"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + + prop = RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "uvlayer_name"); + RNA_def_property_ui_text(prop, "UV Map", "UV map name"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SmokeFlow_uvlayer_set"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + + prop = RNA_def_property(srna, "noise_texture", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Texture", "Texture that controls emission strength"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + + prop = RNA_def_property(srna, "texture_size", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.01, 10.0); + RNA_def_property_ui_range(prop, 0.1, 5.0, 0.05, 5); + RNA_def_property_ui_text(prop, "Size", "Size of texture mapping"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); + + prop = RNA_def_property(srna, "texture_offset", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.0, 200.0); + RNA_def_property_ui_range(prop, 0.0, 100.0, 0.05, 5); + RNA_def_property_ui_text(prop, "Offset", "Z-offset of texture mapping"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_reset"); } diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 246f9fef98a..962a92223eb 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -336,6 +336,15 @@ static void rna_View3D_CursorLocation_set(PointerRNA *ptr, const float *values) copy_v3_v3(cursor, values); } +static float rna_View3D_GridScaleUnit_get(PointerRNA *ptr) +{ + View3D *v3d = (View3D *)(ptr->data); + bScreen *sc = (bScreen *)ptr->id.data; + Scene *scene = (Scene *)sc->scene; + + return ED_view3d_grid_scale(scene, v3d, NULL); +} + static void rna_SpaceView3D_layer_set(PointerRNA *ptr, const int *values) { View3D *v3d = (View3D *)(ptr->data); @@ -478,7 +487,7 @@ static void rna_RegionView3D_view_matrix_set(PointerRNA *ptr, const float *value } /* api call */ -void rna_RegionView3D_update(ID *id, RegionView3D *rv3d) +static void rna_RegionView3D_update(ID *id, RegionView3D *rv3d) { bScreen *sc = (bScreen *)id; @@ -849,7 +858,7 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *UNUSED(bmain), Scene *s adt = BKE_id_add_animdata(&obact->id); /* this only adds if non-existant */ } else if (saction->mode == SACTCONT_SHAPEKEY) { - Key *key = ob_get_key(obact); + Key *key = BKE_key_from_object(obact); if (key) adt = BKE_id_add_animdata(&key->id); /* this only adds if non-existant */ } @@ -876,7 +885,7 @@ static void rna_SpaceDopeSheetEditor_mode_update(Main *UNUSED(bmain), Scene *sce /* special exceptions for ShapeKey Editor mode */ if (saction->mode == SACTCONT_SHAPEKEY) { - Key *key = ob_get_key(obact); + Key *key = BKE_key_from_object(obact); /* 1) update the action stored for the editor */ if (key) @@ -949,15 +958,17 @@ static BGpic *rna_BackgroundImage_new(View3D *v3d) return bgpic; } -static void rna_BackgroundImage_remove(View3D *v3d, ReportList *reports, BGpic *bgpic) +static void rna_BackgroundImage_remove(View3D *v3d, ReportList *reports, PointerRNA *bgpic_ptr) { + BGpic *bgpic = bgpic_ptr->data; if (BLI_findindex(&v3d->bgpicbase, bgpic) == -1) { - BKE_report(reports, RPT_ERROR, "BackgroundImage can't be removed"); - } - else { - ED_view3D_background_image_remove(v3d, bgpic); - WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, v3d); + BKE_report(reports, RPT_ERROR, "Background image cannot be removed"); } + + ED_view3D_background_image_remove(v3d, bgpic); + RNA_POINTER_INVALIDATE(bgpic_ptr); + + WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, v3d); } static void rna_BackgroundImage_clear(View3D *v3d) @@ -1102,7 +1113,7 @@ static void rna_def_space(BlenderRNA *brna) } /* for all spaces that use a mask */ -void rna_def_space_mask_info(StructRNA *srna, int noteflag, const char *mask_set_func) +static void rna_def_space_mask_info(StructRNA *srna, int noteflag, const char *mask_set_func) { PropertyRNA *prop; @@ -1324,7 +1335,7 @@ static void rna_def_background_image(BlenderRNA *brna) srna = RNA_def_struct(brna, "BackgroundImage", NULL); RNA_def_struct_sdna(srna, "BGpic"); - RNA_def_struct_ui_text(srna, "Background Image", "Image and settings for display in the 3d View background"); + RNA_def_struct_ui_text(srna, "Background Image", "Image and settings for display in the 3D View background"); prop = RNA_def_property(srna, "source", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "source"); @@ -1442,7 +1453,8 @@ static void rna_def_backgroundImages(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove background image"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "image", "BackgroundImage", "", "Image displayed as viewport background"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "clear", "rna_BackgroundImage_clear"); RNA_def_function_ui_description(func, "Remove all background images"); @@ -1494,7 +1506,39 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Camera", "Active camera used in this view (when unlocked from the scene's active camera)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + + /* render border */ + prop = RNA_def_property(srna, "use_render_border", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_RENDER_BORDER); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Render Border", + "Use a user-defined border region within the frame size for rendered viewport"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "render_border_min_x", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "render_border.xmin"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Border Minimum X", "Minimum X value to for the render border"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "render_border_min_y", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "render_border.ymin"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Border Minimum Y", "Minimum Y value for the render border"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "render_border_max_x", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "render_border.xmax"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Border Maximum X", "Maximum X value for the render border"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "render_border_max_y", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "render_border.ymax"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Border Maximum Y", "Maximum Y value for the render border"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "lock_object", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_pointer_sdna(prop, NULL, "ob_centre"); @@ -1533,7 +1577,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) prop = RNA_def_property(srna, "lens", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "lens"); - RNA_def_property_ui_text(prop, "Lens", "Lens angle (mm) in perspective view"); + RNA_def_property_ui_text(prop, "Lens", "Viewport lens angle (mm)"); RNA_def_property_range(prop, 1.0f, 250.0f); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); @@ -1571,7 +1615,12 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_range(prop, 1, 1024); RNA_def_property_int_default(prop, 10); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + + prop = RNA_def_property(srna, "grid_scale_unit", PROP_FLOAT, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_float_funcs(prop, "rna_View3D_GridScaleUnit_get", NULL, NULL); + RNA_def_property_ui_text(prop, "Grid Scale Unit", "Grid cell size scaled by scene unit system settings"); + prop = RNA_def_property(srna, "show_floor", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "gridflag", V3D_SHOW_FLOOR); RNA_def_property_ui_text(prop, "Display Grid Floor", "Show the ground plane grid in perspective view"); @@ -2780,6 +2829,12 @@ static void rna_def_fileselect_params(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_FILE_BLEND, 0); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); + prop = RNA_def_property(srna, "use_filter_backup", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "filter", BLENDERFILE_BACKUP); + RNA_def_property_ui_text(prop, "Filter BlenderBackup files", "Show .blend1, .blend2, etc. files"); + RNA_def_property_ui_icon(prop, ICON_FILE_BACKUP, 0); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); + prop = RNA_def_property(srna, "use_filter_movie", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "filter", MOVIEFILE); RNA_def_property_ui_text(prop, "Filter Movies", "Show movie files"); diff --git a/source/blender/makesrna/intern/rna_speaker.c b/source/blender/makesrna/intern/rna_speaker.c index 1e3c8df9273..a160aaf94e2 100644 --- a/source/blender/makesrna/intern/rna_speaker.c +++ b/source/blender/makesrna/intern/rna_speaker.c @@ -35,6 +35,8 @@ #include "DNA_speaker_types.h" #include "DNA_sound_types.h" +#include "BLF_translation.h" + #ifdef RNA_RUNTIME #include "MEM_guardedalloc.h" @@ -45,7 +47,6 @@ #include "WM_api.h" #include "WM_types.h" - #else static void rna_def_speaker(BlenderRNA *brna) @@ -151,6 +152,7 @@ static void rna_def_speaker(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "volume"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Volume", "How loud the sound is"); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_volume_set", NULL); */ /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */ @@ -158,6 +160,7 @@ static void rna_def_speaker(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "pitch"); RNA_def_property_range(prop, 0.1f, 10.0f); RNA_def_property_ui_text(prop, "Pitch", "Playback pitch of the sound"); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_pitch_set", NULL); */ /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */ diff --git a/source/blender/makesrna/intern/rna_text_api.c b/source/blender/makesrna/intern/rna_text_api.c index 0366012e260..5f67f367195 100644 --- a/source/blender/makesrna/intern/rna_text_api.c +++ b/source/blender/makesrna/intern/rna_text_api.c @@ -30,6 +30,8 @@ #include "RNA_define.h" +#include "rna_internal.h" /* own include */ + #ifdef RNA_RUNTIME #include "WM_api.h" diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index 483e3ab7f8a..e77c5d13a6b 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -71,7 +71,7 @@ EnumPropertyItem texture_type_items[] = { {TEX_POINTDENSITY, "POINT_DENSITY", ICON_TEXTURE, "Point Density", ""}, {TEX_STUCCI, "STUCCI", ICON_TEXTURE, "Stucci", "Procedural - create a fractal noise texture"}, {TEX_VORONOI, "VORONOI", ICON_TEXTURE, "Voronoi", "Procedural - create cell-like patterns based on Worley noise"}, - {TEX_VOXELDATA, "VOXEL_DATA", ICON_TEXTURE, "Voxel Data", "Create a 3d texture based on volumetric data"}, + {TEX_VOXELDATA, "VOXEL_DATA", ICON_TEXTURE, "Voxel Data", "Create a 3D texture based on volumetric data"}, {TEX_WOOD, "WOOD", ICON_TEXTURE, "Wood", "Procedural - wave generated bands or rings, with optional noise"}, {TEX_OCEAN, "OCEAN", ICON_TEXTURE, "Ocean", "Use a texture generated by an Ocean modifier"}, {0, NULL, 0, NULL, NULL} @@ -1733,6 +1733,7 @@ static void rna_def_texture_pointdensity(BlenderRNA *brna) prop = RNA_def_property(srna, "turbulence_strength", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "noise_fac"); RNA_def_property_range(prop, 0.01, FLT_MAX); + RNA_def_property_ui_text(prop, "Turbulence Strength", "Strength of the added turbulent noise"); RNA_def_property_update(prop, 0, "rna_Texture_update"); prop = RNA_def_property(srna, "turbulence_depth", PROP_INT, PROP_NONE); @@ -1799,7 +1800,8 @@ static void rna_def_texture_voxeldata(BlenderRNA *brna) }; static EnumPropertyItem smoked_type_items[] = { - {TEX_VD_SMOKEDENSITY, "SMOKEDENSITY", 0, "Density", "Use smoke density as texture data"}, + {TEX_VD_SMOKEDENSITY, "SMOKEDENSITY", 0, "Smoke", "Use smoke density and color as texture data"}, + {TEX_VD_SMOKEFLAME, "SMOKEFLAME", 0, "Flame", "Use flame temperature as texture data"}, {TEX_VD_SMOKEHEAT, "SMOKEHEAT", 0, "Heat", "Use smoke heat as texture data. Values from -2.0 to 2.0 are used"}, {TEX_VD_SMOKEVEL, "SMOKEVEL", 0, "Velocity", "Use smoke velocity as texture data"}, {0, NULL, 0, NULL, NULL} diff --git a/source/blender/makesrna/intern/rna_texture_api.c b/source/blender/makesrna/intern/rna_texture_api.c index e62b3ecd804..5be9d3a0dec 100644 --- a/source/blender/makesrna/intern/rna_texture_api.c +++ b/source/blender/makesrna/intern/rna_texture_api.c @@ -32,6 +32,8 @@ #include "RNA_define.h" +#include "rna_internal.h" /* own include */ + #ifdef RNA_RUNTIME #include "IMB_imbuf.h" @@ -42,8 +44,8 @@ #include "RE_pipeline.h" #include "RE_shader_ext.h" -void save_envmap(struct EnvMap *env, bContext *C, ReportList *reports, const char *filepath, - struct Scene *scene, float layout[12]) +static void save_envmap(struct EnvMap *env, bContext *C, ReportList *reports, const char *filepath, + struct Scene *scene, float layout[12]) { if (scene == NULL) { scene = CTX_data_scene(C); @@ -52,7 +54,7 @@ void save_envmap(struct EnvMap *env, bContext *C, ReportList *reports, const cha RE_WriteEnvmapResult(reports, scene, env, filepath, scene->r.im_format.imtype, layout); } -void clear_envmap(struct EnvMap *env, bContext *C) +static void clear_envmap(struct EnvMap *env, bContext *C) { Main *bmain = CTX_data_main(C); Tex *tex; @@ -66,7 +68,7 @@ void clear_envmap(struct EnvMap *env, bContext *C) } } -void texture_evaluate(struct Tex *tex, float value[3], float color_r[4]) +static void texture_evaluate(struct Tex *tex, float value[3], float color_r[4]) { TexResult texres = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; multitex_ext(tex, value, NULL, NULL, 1, &texres); @@ -118,10 +120,10 @@ void RNA_api_environment_map(StructRNA *srna) RNA_def_pointer(func, "scene", "Scene", "", "Overrides the scene from which image parameters are taken"); - RNA_def_float_array(func, "layout", 12, default_layout, 0.0f, 0.0f, "File layout", + RNA_def_float_array(func, "layout", 12, default_layout, 0.0f, 1000.0f, "File layout", "Flat array describing the X,Y position of each cube face in the " "output image, where 1 is the size of a face - order is [+Z -Z +Y -X -Y +X] " - "(use -1 to skip a face)", 0.0f, 0.0f); + "(use -1 to skip a face)", 0.0f, 1000.0f); } #endif diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 172a79970b5..51b50f78e66 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -35,6 +35,7 @@ #include "BKE_movieclip.h" #include "BKE_tracking.h" +#include "RNA_access.h" #include "RNA_define.h" #include "rna_internal.h" @@ -144,7 +145,7 @@ static void rna_tracking_active_track_set(PointerRNA *ptr, PointerRNA value) clip->tracking.act_track = NULL; } -void rna_trackingTrack_name_set(PointerRNA *ptr, const char *value) +static void rna_trackingTrack_name_set(PointerRNA *ptr, const char *value) { MovieClip *clip = (MovieClip *)ptr->id.data; MovieTracking *tracking = &clip->tracking; @@ -325,7 +326,7 @@ static void rna_tracking_active_object_set(PointerRNA *ptr, PointerRNA value) else clip->tracking.objectnr = 0; } -void rna_trackingObject_name_set(PointerRNA *ptr, const char *value) +static void rna_trackingObject_name_set(PointerRNA *ptr, const char *value) { MovieClip *clip = (MovieClip *)ptr->id.data; MovieTrackingObject *object = (MovieTrackingObject *)ptr->data; @@ -447,9 +448,15 @@ static MovieTrackingObject *rna_trackingObject_new(MovieTracking *tracking, cons return object; } -void rna_trackingObject_remove(MovieTracking *tracking, MovieTrackingObject *object) +static void rna_trackingObject_remove(MovieTracking *tracking, ReportList *reports, PointerRNA *object_ptr) { - BKE_tracking_object_delete(tracking, object); + MovieTrackingObject *object = object_ptr->data; + if (BKE_tracking_object_delete(tracking, object) == FALSE) { + BKE_reportf(reports, RPT_ERROR, "MovieTracking '%s' can't be removed", object->name); + return; + } + + RNA_POINTER_INVALIDATE(object_ptr); WM_main_add_notifier(NC_MOVIECLIP | NA_EDITED, NULL); } @@ -477,7 +484,7 @@ static MovieTrackingMarker *rna_trackingMarkers_insert_frame(MovieTrackingTrack return new_marker; } -void rna_trackingMarkers_delete_frame(MovieTrackingTrack *track, int framenr) +static void rna_trackingMarkers_delete_frame(MovieTrackingTrack *track, int framenr) { if (track->markersnr == 1) return; @@ -567,17 +574,18 @@ static void rna_def_trackingSettings(BlenderRNA *brna) "Limit speed of tracking to make visual feedback easier " "(this does not affect the tracking quality)"); - /* keyframe_a */ - prop = RNA_def_property(srna, "keyframe_a", PROP_INT, PROP_NONE); + /* reconstruction success_threshold */ + prop = RNA_def_property(srna, "reconstruction_success_threshold", PROP_FLOAT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_int_sdna(prop, NULL, "keyframe1"); - RNA_def_property_ui_text(prop, "Keyframe A", "First keyframe used for reconstruction initialization"); + RNA_def_property_float_default(prop, 0.001f); + RNA_def_property_range(prop, 0, FLT_MAX); + RNA_def_property_ui_text(prop, "Success Threshold", "Threshold value of reconstruction error which is still considered successful"); - /* keyframe_b */ - prop = RNA_def_property(srna, "keyframe_b", PROP_INT, PROP_NONE); + /* use fallback reconstruction */ + prop = RNA_def_property(srna, "use_fallback_reconstruction", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_int_sdna(prop, NULL, "keyframe2"); - RNA_def_property_ui_text(prop, "Keyframe B", "Second keyframe used for reconstruction initialization"); + RNA_def_property_boolean_sdna(prop, NULL, "reconstruction_flag", TRACKING_USE_FALLBACK_RECONSTRUCTION); + RNA_def_property_ui_text(prop, "Use Fallback", "Use fallback reconstruction algorithm in cases main reconstruction algorithm failed. Could give better solution with bad tracks"); /* intrinsics refinement during bundle adjustment */ prop = RNA_def_property(srna, "refine_intrinsics", PROP_ENUM, PROP_NONE); @@ -909,8 +917,8 @@ static void rna_def_trackingMarkers(BlenderRNA *brna, PropertyRNA *cprop) parm = RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame", "Frame number to find marker for", MINFRAME, MAXFRAME); RNA_def_property_flag(parm, PROP_REQUIRED); - parm = RNA_def_boolean(func, "exact", TRUE, "Exact", - "Get marker at exact frame number rather than get estimated marker"); + RNA_def_boolean(func, "exact", TRUE, "Exact", + "Get marker at exact frame number rather than get estimated marker"); parm = RNA_def_pointer(func, "marker", "MovieTrackingMarker", "", "Marker for specified frame"); RNA_def_function_return(func, parm); @@ -1393,6 +1401,18 @@ static void rna_def_trackingObject(BlenderRNA *brna) RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Scale", "Scale of object solution in camera space"); RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, "rna_trackingObject_flushUpdate"); + + /* keyframe_a */ + prop = RNA_def_property(srna, "keyframe_a", PROP_INT, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_int_sdna(prop, NULL, "keyframe1"); + RNA_def_property_ui_text(prop, "Keyframe A", "First keyframe used for reconstruction initialization"); + + /* keyframe_b */ + prop = RNA_def_property(srna, "keyframe_b", PROP_INT, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_int_sdna(prop, NULL, "keyframe2"); + RNA_def_property_ui_text(prop, "Keyframe B", "Second keyframe used for reconstruction initialization"); } static void rna_def_trackingObjects(BlenderRNA *brna, PropertyRNA *cprop) @@ -1416,8 +1436,11 @@ static void rna_def_trackingObjects(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_return(func, parm); func = RNA_def_function(srna, "remove", "rna_trackingObject_remove"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove tracking object from this movie clip"); - RNA_def_pointer(func, "object", "MovieTrackingObject", "", "Motion tracking object to be removed"); + parm = RNA_def_pointer(func, "object", "MovieTrackingObject", "", "Motion tracking object to be removed"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); /* active object */ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index 70d94bfc7ed..a0a9f6183af 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -85,7 +85,7 @@ static ARegionType *region_type_find(ReportList *reports, int space_type, int re /* region type not found? abort */ if (art == NULL) { - BKE_report(reports, RPT_ERROR, "Region not found in spacetype"); + BKE_report(reports, RPT_ERROR, "Region not found in space type"); return NULL; } @@ -192,7 +192,7 @@ static StructRNA *rna_Panel_register(Main *bmain, ReportList *reports, void *dat return NULL; if (strlen(identifier) >= sizeof(dummypt.idname)) { - BKE_reportf(reports, RPT_ERROR, "registering panel class: '%s' is too long, maximum length is %d", + BKE_reportf(reports, RPT_ERROR, "Registering panel class: '%s' is too long, maximum length is %d", identifier, (int)sizeof(dummypt.idname)); return NULL; } @@ -309,7 +309,7 @@ static StructRNA *rna_Header_register(Main *bmain, ReportList *reports, void *da return NULL; if (strlen(identifier) >= sizeof(dummyht.idname)) { - BKE_reportf(reports, RPT_ERROR, "registering header class: '%s' is too long, maximum length is %d", + BKE_reportf(reports, RPT_ERROR, "Registering header class: '%s' is too long, maximum length is %d", identifier, (int)sizeof(dummyht.idname)); return NULL; } @@ -438,7 +438,7 @@ static StructRNA *rna_Menu_register(Main *bmain, ReportList *reports, void *data return NULL; if (strlen(identifier) >= sizeof(dummymt.idname)) { - BKE_reportf(reports, RPT_ERROR, "registering menu class: '%s' is too long, maximum length is %d", + BKE_reportf(reports, RPT_ERROR, "Registering menu class: '%s' is too long, maximum length is %d", identifier, (int)sizeof(dummymt.idname)); return NULL; } diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index ea38b60b25f..2a8f1b90d4e 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -36,6 +36,8 @@ #include "UI_resources.h" +#include "rna_internal.h" + #ifdef RNA_RUNTIME static void rna_uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *name, int icon, @@ -234,41 +236,41 @@ void RNA_api_ui_layout(StructRNA *srna) /* useful in C but not in python */ #if 0 - func= RNA_def_function(srna, "operator_enum_single", "uiItemEnumO_string"); + func = RNA_def_function(srna, "operator_enum_single", "uiItemEnumO_string"); api_ui_item_op_common(func); - parm= RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator"); + parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator"); RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_string(func, "value", "", 0, "", "Enum property value"); + parm = RNA_def_string(func, "value", "", 0, "", "Enum property value"); RNA_def_property_flag(parm, PROP_REQUIRED); - func= RNA_def_function(srna, "operator_boolean", "uiItemBooleanO"); + func = RNA_def_function(srna, "operator_boolean", "uiItemBooleanO"); api_ui_item_op_common(func); - parm= RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator"); + parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator"); RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_boolean(func, "value", 0, "", "Value of the property to call the operator with"); + parm = RNA_def_boolean(func, "value", 0, "", "Value of the property to call the operator with"); RNA_def_property_flag(parm, PROP_REQUIRED); */ - func= RNA_def_function(srna, "operator_int", "uiItemIntO"); + func = RNA_def_function(srna, "operator_int", "uiItemIntO"); api_ui_item_op_common(func); - parm= RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator"); + parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator"); RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_int(func, "value", 0, INT_MIN, INT_MAX, "", + parm = RNA_def_int(func, "value", 0, INT_MIN, INT_MAX, "", "Value of the property to call the operator with", INT_MIN, INT_MAX); RNA_def_property_flag(parm, PROP_REQUIRED); */ - func= RNA_def_function(srna, "operator_float", "uiItemFloatO"); + func = RNA_def_function(srna, "operator_float", "uiItemFloatO"); api_ui_item_op_common(func); - parm= RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator"); + parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator"); RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_float(func, "value", 0, -FLT_MAX, FLT_MAX, "", + parm = RNA_def_float(func, "value", 0, -FLT_MAX, FLT_MAX, "", "Value of the property to call the operator with", -FLT_MAX, FLT_MAX); RNA_def_property_flag(parm, PROP_REQUIRED); */ - func= RNA_def_function(srna, "operator_string", "uiItemStringO"); + func = RNA_def_function(srna, "operator_string", "uiItemStringO"); api_ui_item_op_common(func); - parm= RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator"); + parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator"); RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_string(func, "value", "", 0, "", "Value of the property to call the operator with"); + parm = RNA_def_string(func, "value", "", 0, "", "Value of the property to call the operator with"); RNA_def_property_flag(parm, PROP_REQUIRED); #endif @@ -437,7 +439,8 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_boolean(func, "compact", 0, "", "Use more compact layout"); func = RNA_def_function(srna, "template_list", "uiTemplateList"); - RNA_def_function_ui_description(func, "Item. A list widget to display data. e.g. vertexgroups"); + RNA_def_function_ui_description(func, "Item. A list widget to display data, e.g. vertexgroups " + "(WARNING: only one per panel allowed!)."); RNA_def_function_flag(func, FUNC_USE_CONTEXT); parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property"); RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 666fa4d7b81..415d5308d85 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -24,9 +24,9 @@ * \ingroup RNA */ - #include +#include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -265,7 +265,7 @@ static void rna_UserDef_audio_update(Main *bmain, Scene *UNUSED(scene), PointerR static void rna_Userdef_memcache_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) { - MEM_CacheLimiter_set_maximum(U.memcachelimit * 1024 * 1024); + MEM_CacheLimiter_set_maximum(((size_t) U.memcachelimit) * 1024 * 1024); } static void rna_UserDef_weight_color_update(Main *bmain, Scene *scene, PointerRNA *ptr) @@ -311,9 +311,16 @@ static bAddon *rna_userdef_addon_new(void) return bext; } -static void rna_userdef_addon_remove(bAddon *bext) +static void rna_userdef_addon_remove(ReportList *reports, PointerRNA *bext_ptr) { + bAddon *bext = bext_ptr->data; + if (BLI_findindex(&U.addons, bext) == -1) { + BKE_report(reports, RPT_ERROR, "Addon is no longer valid"); + return; + } + BLI_freelinkN(&U.addons, bext); + RNA_POINTER_INVALIDATE(bext_ptr); } static void rna_userdef_temp_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) @@ -410,6 +417,15 @@ static EnumPropertyItem *rna_userdef_compute_device_itemf(bContext *UNUSED(C), P } #endif +#ifdef WITH_INTERNATIONAL +static EnumPropertyItem *rna_lang_enum_properties_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), int *free) +{ + *free = 0; /* These items are handled by BLF code! */ + return BLF_RNA_lang_enum_properties(); +} +#endif + #else static void rna_def_userdef_theme_ui_font_style(BlenderRNA *brna) @@ -481,7 +497,7 @@ static void rna_def_userdef_theme_ui_style(BlenderRNA *brna) /* (not used yet) */ #if 0 - prop= RNA_def_property(srna, "panelzoom", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "panelzoom", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.5, 2.0); RNA_def_property_ui_text(prop, "Panel Zoom", "Default zoom level for panel areas"); #endif @@ -2510,7 +2526,7 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Sub Level Menu Open Delay", "Time delay in 1/10 seconds before automatically opening sub level menus"); - prop = RNA_def_property(srna, "quit_dialog", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_quit_dialog", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_QUIT_PROMPT); RNA_def_property_ui_text(prop, "Prompt Quit", "Asks for confirmation when quitting through the window close button"); @@ -2745,6 +2761,11 @@ static void rna_def_userdef_edit(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "autokey_flag", AUTOKEY_FLAG_INSERTAVAIL); RNA_def_property_ui_text(prop, "Auto Keyframe Insert Available", "Automatic keyframe insertion in available F-Curves"); + + prop = RNA_def_property(srna, "use_auto_keying_warning", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "autokey_flag", AUTOKEY_FLAG_NOWARNING); + RNA_def_property_ui_text(prop, "Show Auto Keying Warning", + "Show warning indicators when transforming objects and bones if auto keying is enabled"); /* keyframing settings */ prop = RNA_def_property(srna, "use_keyframe_insert_needed", PROP_BOOLEAN, PROP_NONE); @@ -2778,7 +2799,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna) RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", USER_NONEGFRAMES); RNA_def_property_ui_text(prop, "Allow Negative Frames", "Current frame number can be manually set to a negative value"); - + /* fcurve opacity */ prop = RNA_def_property(srna, "fcurve_unselected_alpha", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "fcu_inactive_alpha"); @@ -2978,14 +2999,16 @@ static void rna_def_userdef_system(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; +#if 0 /* hardcoded here, could become dynamic somehow */ /* locale according to http://www.roseindia.net/tutorials/I18N/locales-list.shtml */ /* if you edit here, please also edit the source/blender/blenfont/intern/blf_lang.c 's locales */ /* Note: As this list is in alphabetical order, and not defined order, - * here is the highest define currently in use: 33 (Hebrew). */ + * here is the highest define currently in use: 35 (Esperanto). */ static EnumPropertyItem language_items[] = { - { 0, "", 0, N_("Nearly done"), ""}, + { 0, "", 0, N_("Nearly Done"), ""}, { 0, "DEFAULT", 0, "Default (Default)", ""}, + /* using the utf8 flipped form of Arabic (العربية) */ {21, "ARABIC", 0, "Arabic (ﺔﻴﺑﺮﻌﻟﺍ)", "ar_EG"}, {32, "BRAZILIANPORTUGUESE", 0, "Brazilian Portuguese (Português do Brasil)", "pt_BR"}, { 1, "ENGLISH", 0, "English (English)", "en_US"}, @@ -2998,32 +3021,40 @@ static void rna_def_userdef_system(BlenderRNA *brna) { 9, "SPANISH", 0, "Spanish (Español)", "es"}, {14, "TRADITIONAL_CHINESE", 0, "Traditional Chinese (繁體中文)", "zh_TW"}, {18, "UKRAINIAN", 0, "Ukrainian (Український)", "uk_UA"}, - { 0, "", 0, N_("In progress"), ""}, - /* using the utf8 flipped form of Arabic (العربية) */ - {22, "BULGARIAN", 0, "Bulgarian (Български)", "bg_BG"}, - {10, "CATALAN", 0, "Catalan (Català)", "ca_AD"}, + { 0, "", 0, N_("In Progress"), ""}, +/* {22, "BULGARIAN", 0, "Bulgarian (Български)", "bg_BG"},*/ /* XXX Not active nor enough translated. */ +/* {10, "CATALAN", 0, "Catalan (Català)", "ca_AD"},*/ /* XXX Not active nor enough translated. */ {16, "CROATIAN", 0, "Croatian (Hrvatski)", "hr_HR"}, {11, "CZECH", 0, "Czech (Český)", "cs_CZ"}, { 3, "DUTCH", 0, "Dutch (Nederlandse taal)", "nl_NL"}, - { 6, "FINNISH", 0, "Finnish (Suomi)", "fi_FI"}, + {35, "ESPERANTO", 0, "Esperanto (Esperanto)", "eo"}, + {34, "ESTONIAN", 0, "Estonian (Eestlane)", "et_EE"}, +/* { 6, "FINNISH", 0, "Finnish (Suomi)", "fi_FI"},*/ /* XXX Not active nor enough translated. */ { 5, "GERMAN", 0, "German (Deutsch)", "de_DE"}, - {23, "GREEK", 0, "Greek (Ελληνικά)", "el_GR"}, - {33, "HEBREW", 0, "Hebrew (עִבְרִית)", "he_IL"}, - {31, "HUNGARIAN", 0, "Hungarian (magyar)", "hu_HU"}, +/* {23, "GREEK", 0, "Greek (Ελληνικά)", "el_GR"},*/ /* XXX Not active nor enough translated. */ + /* using the utf8 flipped form of Hebrew (עִבְרִית)) */ + {33, "HEBREW", 0, "Hebrew (תירִבְעִ)", "he_IL"}, + {31, "HUNGARIAN", 0, "Hungarian (Magyar)", "hu_HU"}, {27, "INDONESIAN", 0, "Indonesian (Bahasa indonesia)", "id_ID"}, {29, "KYRGYZ", 0, "Kyrgyz (Кыргыз тили)", "ky_KG"}, -/* {24, "KOREAN", 0, "Korean (한국 언어)", "ko_KR"}, */ /* XXX No po's yet. */ - {25, "NEPALI", 0, "Nepali (नेपाली)", "ne_NP"}, +/* {24, "KOREAN", 0, "Korean (한국 언어)", "ko_KR"}, */ /* XXX Not active nor enough translated. */ +/* {25, "NEPALI", 0, "Nepali (नेपाली)", "ne_NP"},*/ /* XXX Not active nor enough translated. */ /* using the utf8 flipped form of Persian (فارسی) */ {26, "PERSIAN", 0, "Persian (ﯽﺳﺭﺎﻓ)", "fa_IR"}, - {19, "POLISH", 0, "Polish (Polski)", "pl_PL"}, -/* {20, "ROMANIAN", 0, "Romanian (Român)", "ro_RO"}, */ /* XXX No po's yet. */ +/* {19, "POLISH", 0, "Polish (Polski)", "pl_PL"},*/ /* XXX Not active nor enough translated. */ +/* {20, "ROMANIAN", 0, "Romanian (Român)", "ro_RO"}, */ /* XXX Not active nor enough translated. */ {17, "SERBIAN", 0, "Serbian (Српски)", "sr_RS"}, - {28, "SERBIAN_LATIN", 0, "Serbian latin (Srpski latinica)", "sr_RS@latin"}, + {28, "SERBIAN_LATIN", 0, "Serbian Latin (Srpski latinica)", "sr_RS@latin"}, { 7, "SWEDISH", 0, "Swedish (Svenska)", "sv_SE"}, {30, "TURKISH", 0, "Turkish (Türkçe)", "tr_TR"}, { 0, NULL, 0, NULL, NULL} }; +#else + static EnumPropertyItem language_items[] = { + { 0, "DEFAULT", 0, "Default (Default)", ""}, + { 0, NULL, 0, NULL, NULL} + }; +#endif #ifdef WITH_CYCLES static EnumPropertyItem compute_device_items[] = { @@ -3066,6 +3097,9 @@ static void rna_def_userdef_system(BlenderRNA *brna) prop = RNA_def_property(srna, "language", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, language_items); +#ifdef WITH_INTERNATIONAL + RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_lang_enum_properties_itemf"); +#endif RNA_def_property_ui_text(prop, "Language", "Language used for translation"); RNA_def_property_update(prop, NC_WINDOW, "rna_userdef_language_update"); @@ -3292,6 +3326,12 @@ static void rna_def_userdef_input(BlenderRNA *brna) {USER_TRACKBALL, "TRACKBALL", 0, "Trackball", "Use trackball style rotation in the viewport"}, {0, NULL, 0, NULL, NULL} }; + + static EnumPropertyItem ndof_view_rotation_items[] = { + {NDOF_TURNTABLE, "TURNTABLE", 0, "Turntable", "Use turntable style rotation in the viewport"}, + {0, "TRACKBALL", 0, "Trackball", "Use trackball style rotation in the viewport"}, + {0, NULL, 0, NULL, NULL} + }; static EnumPropertyItem view_zoom_styles[] = { {USER_ZOOM_CONT, "CONTINUE", 0, "Continue", "Old style zoom, continues while moving mouse up or down"}, @@ -3383,9 +3423,10 @@ static void rna_def_userdef_input(BlenderRNA *brna) /* TODO: update description when fly-mode visuals are in place ("projected position in fly mode")*/ /* 3D view */ - prop = RNA_def_property(srna, "ndof_turntable", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_TURNTABLE); - RNA_def_property_ui_text(prop, "Turntable", "Turntable for ndof rotation"); + prop = RNA_def_property(srna, "ndof_view_rotate_method", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); + RNA_def_property_enum_items(prop, ndof_view_rotation_items); + RNA_def_property_ui_text(prop, "NDOF View Rotation", "Rotation style in the viewport"); /* 3D view: roll */ prop = RNA_def_property(srna, "ndof_roll_invert_axis", PROP_BOOLEAN, PROP_NONE); @@ -3496,6 +3537,10 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_HIDE_RECENT); RNA_def_property_ui_text(prop, "Hide Recent Locations", "Hide recent locations in the file selector"); + prop = RNA_def_property(srna, "hide_system_bookmarks", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_HIDE_SYSTEM_BOOKMARKS); + RNA_def_property_ui_text(prop, "Hide System Bookmarks", "Hide system bookmarks in the file selector"); + prop = RNA_def_property(srna, "show_thumbnails", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_SHOW_THUMBNAILS); RNA_def_property_ui_text(prop, "Show Thumbnails", "Open in thumbnail view for images and movies"); @@ -3592,7 +3637,7 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) "Enables automatic saving of preview images in the .blend file"); } -void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cprop) +static void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; FunctionRNA *func; @@ -3611,10 +3656,11 @@ void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_return(func, parm); func = RNA_def_function(srna, "remove", "rna_userdef_addon_remove"); - RNA_def_function_flag(func, FUNC_NO_SELF); + RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Remove addon"); parm = RNA_def_pointer(func, "addon", "Addon", "", "Addon to remove"); - RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } void RNA_def_userdef(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 61c75e306cb..e5f44644f7a 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -122,6 +122,7 @@ EnumPropertyItem event_timer_type_items[] = { }; EnumPropertyItem event_ndof_type_items[] = { + {NDOF_MOTION, "NDOF_MOTION", 0, "Motion", ""}, /* buttons on all 3dconnexion devices */ {NDOF_BUTTON_MENU, "NDOF_BUTTON_MENU", 0, "Menu", ""}, {NDOF_BUTTON_FIT, "NDOF_BUTTON_FIT", 0, "Fit", ""}, @@ -622,13 +623,34 @@ static void rna_wmKeyMapItem_map_type_set(PointerRNA *ptr, int value) kmi->val = KM_NOTHING; break; case KMI_TYPE_NDOF: - kmi->type = NDOF_BUTTON_MENU; - kmi->val = KM_PRESS; + kmi->type = NDOF_MOTION; + kmi->val = KM_NOTHING; break; } } } +/* assumes value to be an enum from event_type_items */ +/* function makes sure keymodifiers are only valid keys, ESC keeps it unaltered */ +static void rna_wmKeyMapItem_keymodifier_set(PointerRNA *ptr, int value) +{ + wmKeyMapItem *kmi = ptr->data; + + /* XXX, this should really be managed in an _itemf function, + * giving a list of valid enums, then silently changing them when they are set is not + * a good precedent, don't do this unless you have a good reason! */ + if (value == ESCKEY) { + /* pass */ + } + else if (value >= AKEY) { + kmi->keymodifier = value; + } + else { + kmi->keymodifier = 0; + } +} + + static EnumPropertyItem *rna_KeyMapItem_type_itemf(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *UNUSED(free)) { @@ -765,14 +787,14 @@ static void rna_wmKeyMapItem_name_get(PointerRNA *ptr, char *value) { wmKeyMapItem *kmi = ptr->data; wmOperatorType *ot = WM_operatortype_find(kmi->idname, 1); - strcpy(value, ot ? ot->name : kmi->idname); + strcpy(value, ot ? RNA_struct_ui_name(ot->srna) : kmi->idname); } static int rna_wmKeyMapItem_name_length(PointerRNA *ptr) { wmKeyMapItem *kmi = ptr->data; wmOperatorType *ot = WM_operatortype_find(kmi->idname, 1); - return strlen(ot ? ot->name : kmi->idname); + return strlen(ot ? RNA_struct_ui_name(ot->srna) : kmi->idname); } static int rna_KeyMapItem_userdefined_get(PointerRNA *ptr) @@ -1062,7 +1084,7 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void * } else { BKE_reportf(reports, RPT_ERROR, - "registering operator class: '%s', invalid bl_idname '%s', at position %d", + "Registering operator class: '%s', invalid bl_idname '%s', at position %d", identifier, _operator_idname, i); return NULL; } @@ -1071,7 +1093,7 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void * } if (i > ((int)sizeof(dummyop.idname)) - 3) { - BKE_reportf(reports, RPT_ERROR, "registering operator class: '%s', invalid bl_idname '%s', " + BKE_reportf(reports, RPT_ERROR, "Registering operator class: '%s', invalid bl_idname '%s', " "is too long, maximum length is %d", identifier, _operator_idname, (int)sizeof(dummyop.idname) - 3); return NULL; @@ -1079,7 +1101,7 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void * if (dot != 1) { BKE_reportf(reports, RPT_ERROR, - "registering operator class: '%s', invalid bl_idname '%s', must contain 1 '.' character", + "Registering operator class: '%s', invalid bl_idname '%s', must contain 1 '.' character", identifier, _operator_idname); return NULL; } @@ -1136,7 +1158,7 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void * return dummyot.ext.srna; } -void **rna_Operator_instance(PointerRNA *ptr) +static void **rna_Operator_instance(PointerRNA *ptr) { wmOperator *op = ptr->data; return &op->py_instance; @@ -1180,7 +1202,7 @@ static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, v } if (strlen(identifier) >= sizeof(dummyop.idname)) { - BKE_reportf(reports, RPT_ERROR, "registering operator class: '%s' is too long, maximum length is %d", + BKE_reportf(reports, RPT_ERROR, "Registering operator class: '%s' is too long, maximum length is %d", identifier, (int)sizeof(dummyop.idname)); return NULL; } @@ -1230,24 +1252,30 @@ static void rna_Operator_bl_idname_set(PointerRNA *ptr, const char *value) { wmOperator *data = (wmOperator *)(ptr->data); char *str = (char *)data->type->idname; - if (!str[0]) BLI_strncpy(str, value, RNA_DYN_DESCR_MAX); /* utf8 already ensured */ - else assert(!"setting the bl_idname on a non-builtin operator"); + if (!str[0]) + BLI_strncpy(str, value, OP_MAX_TYPENAME); /* utf8 already ensured */ + else + assert(!"setting the bl_idname on a non-builtin operator"); } static void rna_Operator_bl_label_set(PointerRNA *ptr, const char *value) { wmOperator *data = (wmOperator *)(ptr->data); char *str = (char *)data->type->name; - if (!str[0]) BLI_strncpy(str, value, RNA_DYN_DESCR_MAX); /* utf8 already ensured */ - else assert(!"setting the bl_label on a non-builtin operator"); + if (!str[0]) + BLI_strncpy(str, value, OP_MAX_TYPENAME); /* utf8 already ensured */ + else + assert(!"setting the bl_label on a non-builtin operator"); } static void rna_Operator_bl_description_set(PointerRNA *ptr, const char *value) { wmOperator *data = (wmOperator *)(ptr->data); char *str = (char *)data->type->description; - if (!str[0]) BLI_strncpy(str, value, RNA_DYN_DESCR_MAX); /* utf8 already ensured */ - else assert(!"setting the bl_description on a non-builtin operator"); + if (!str[0]) + BLI_strncpy(str, value, RNA_DYN_DESCR_MAX); /* utf8 already ensured */ + else + assert(!"setting the bl_description on a non-builtin operator"); } static void rna_KeyMapItem_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) @@ -1404,7 +1432,7 @@ static void rna_def_operator_type_macro(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Operator Macro", "Storage of a sub operator in a macro after it has been added"); RNA_def_struct_sdna(srna, "wmOperatorTypeMacro"); -/* prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); */ +/* prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); */ /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */ /* RNA_def_property_string_sdna(prop, NULL, "idname"); */ /* RNA_def_property_ui_text(prop, "Name", "Name of the sub operator"); */ @@ -1793,7 +1821,7 @@ static void rna_def_keyconfig(BlenderRNA *brna) * fallback on the operator ID */ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Name", "Name of operator to call on input event"); + RNA_def_property_ui_text(prop, "Name", "Name of operator (translated) to call on input event"); RNA_def_property_string_funcs(prop, "rna_wmKeyMapItem_name_get", "rna_wmKeyMapItem_name_length", NULL); prop = RNA_def_property(srna, "properties", PROP_POINTER, PROP_NONE); @@ -1865,6 +1893,7 @@ static void rna_def_keyconfig(BlenderRNA *brna) prop = RNA_def_property(srna, "key_modifier", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "keymodifier"); RNA_def_property_enum_items(prop, event_type_items); + RNA_def_property_enum_funcs(prop, NULL, "rna_wmKeyMapItem_keymodifier_set", NULL); RNA_def_property_ui_text(prop, "Key Modifier", "Regular key pressed as a modifier"); RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index ae4d5dc493e..116e07073cd 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -32,6 +32,8 @@ #include #include +#include "BLI_utildefines.h" + #include "RNA_define.h" #include "RNA_enum_types.h" @@ -39,6 +41,8 @@ #include "DNA_space_types.h" #include "DNA_windowmanager_types.h" +#include "rna_internal.h" /* own include */ + #ifdef RNA_RUNTIME #include "BKE_context.h" @@ -72,12 +76,12 @@ static int rna_event_modal_handler_add(struct bContext *C, struct wmOperator *op } /* XXX, need a way for python to know event types, 0x0110 is hard coded */ -wmTimer *rna_event_timer_add(struct wmWindowManager *wm, float time_step, wmWindow *win) +static wmTimer *rna_event_timer_add(struct wmWindowManager *wm, float time_step, wmWindow *win) { return WM_event_add_timer(wm, win, 0x0110, time_step); } -void rna_event_timer_remove(struct wmWindowManager *wm, wmTimer *timer) +static void rna_event_timer_remove(struct wmWindowManager *wm, wmTimer *timer) { WM_event_remove_timer(wm, timer->win, timer); } @@ -149,6 +153,18 @@ static wmKeyMapItem *rna_KeyMap_item_new_modal(wmKeyMap *km, ReportList *reports return WM_modalkeymap_add_item(km, type, value, modifier, keymodifier, propvalue); } +static void rna_KeyMap_item_remove(wmKeyMap *km, ReportList *reports, PointerRNA *kmi_ptr) +{ + wmKeyMapItem *kmi = kmi_ptr->data; + + if (WM_keymap_remove_item(km, kmi) == FALSE) { + BKE_reportf(reports, RPT_ERROR, "KeyMapItem '%s' can't be removed from '%s'", kmi->idname, km->idname); + return; + } + + RNA_POINTER_INVALIDATE(kmi_ptr); +} + static wmKeyMap *rna_keymap_new(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid, int modal) { if (modal == 0) { @@ -174,6 +190,18 @@ static wmKeyMap *rna_keymap_find_modal(wmKeyConfig *UNUSED(keyconf), const char return ot->modalkeymap; } +static void rna_KeyConfig_remove(wmWindowManager *wm, ReportList *reports, PointerRNA *keyconf_ptr) +{ + wmKeyConfig *keyconf = keyconf_ptr->data; + + if (WM_keyconfig_remove(wm, keyconf) == FALSE) { + BKE_reportf(reports, RPT_ERROR, "KeyConfig '%s' can't be removed", keyconf->idname); + return; + } + + RNA_POINTER_INVALIDATE(keyconf_ptr); +} + #else #define WM_GEN_INVOKE_EVENT (1 << 0) @@ -288,7 +316,7 @@ void RNA_api_operator(StructRNA *srna) /* exec */ func = RNA_def_function(srna, "execute", NULL); RNA_def_function_ui_description(func, "Execute the operator"); - RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL); + RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE); parm = RNA_def_pointer(func, "context", "Context", "", ""); RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); @@ -299,7 +327,7 @@ void RNA_api_operator(StructRNA *srna) /* check */ func = RNA_def_function(srna, "check", NULL); RNA_def_function_ui_description(func, "Check the operator settings, return True to signal a change to redraw"); - RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL); + RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE); parm = RNA_def_pointer(func, "context", "Context", "", ""); RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); @@ -309,7 +337,7 @@ void RNA_api_operator(StructRNA *srna) /* invoke */ func = RNA_def_function(srna, "invoke", NULL); RNA_def_function_ui_description(func, "Invoke the operator"); - RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL); + RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE); parm = RNA_def_pointer(func, "context", "Context", "", ""); RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); parm = RNA_def_pointer(func, "event", "Event", "", ""); @@ -321,7 +349,7 @@ void RNA_api_operator(StructRNA *srna) func = RNA_def_function(srna, "modal", NULL); /* same as invoke */ RNA_def_function_ui_description(func, "Modal operator function"); - RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL); + RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE); parm = RNA_def_pointer(func, "context", "Context", "", ""); RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); parm = RNA_def_pointer(func, "event", "Event", "", ""); @@ -341,7 +369,7 @@ void RNA_api_operator(StructRNA *srna) /* cancel */ func = RNA_def_function(srna, "cancel", NULL); RNA_def_function_ui_description(func, "Called when the operator is canceled"); - RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL); + RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE); parm = RNA_def_pointer(func, "context", "Context", "", ""); RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); @@ -381,7 +409,7 @@ void RNA_api_macro(StructRNA *srna) RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); } -void RNA_api_keyconfig(StructRNA *srna) +void RNA_api_keyconfig(StructRNA *UNUSED(srna)) { /* FunctionRNA *func; */ /* PropertyRNA *parm; */ @@ -460,9 +488,11 @@ void RNA_api_keymapitems(StructRNA *srna) parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", "Added key map item"); RNA_def_function_return(func, parm); - func = RNA_def_function(srna, "remove", "WM_keymap_remove_item"); + func = RNA_def_function(srna, "remove", "rna_KeyMap_item_remove"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "from_id", "WM_keymap_item_find_id"); parm = RNA_def_property(func, "id", PROP_INT, PROP_NONE); @@ -512,10 +542,11 @@ void RNA_api_keyconfigs(StructRNA *srna) parm = RNA_def_pointer(func, "keyconfig", "KeyConfig", "Key Configuration", "Added key configuration"); RNA_def_function_return(func, parm); - func = RNA_def_function(srna, "remove", "WM_keyconfig_remove"); /* remove_keyconfig */ + func = RNA_def_function(srna, "remove", "rna_KeyConfig_remove"); /* remove_keyconfig */ + RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "keyconfig", "KeyConfig", "Key Configuration", "Removed key configuration"); - RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); } #endif - diff --git a/source/blender/makesrna/rna_cleanup/rna_cleaner.py b/source/blender/makesrna/rna_cleanup/rna_cleaner.py index e3359fbae59..0231e57fcfd 100755 --- a/source/blender/makesrna/rna_cleanup/rna_cleaner.py +++ b/source/blender/makesrna/rna_cleanup/rna_cleaner.py @@ -130,11 +130,11 @@ def get_props_from_txt(input_filename): line = line[1:] # class - [bclass, tail] = [x.strip() for x in line.split('.', 1)] + bclass, tail = [x.strip() for x in line.split('.', 1)] # comment if '*' in bclass: - [comment, bclass] = [x.strip() for x in bclass.split('*', 1)] + comment, bclass = [x.strip() for x in bclass.split('*', 1)] else: comment= '' @@ -144,18 +144,18 @@ def get_props_from_txt(input_filename): continue # from - [bfrom, tail] = [x.strip() for x in tail.split('->', 1)] + bfrom, tail = [x.strip() for x in tail.split('->', 1)] # to - [bto, tail] = [x.strip() for x in tail.split(':', 1)] + bto, tail = [x.strip() for x in tail.split(':', 1)] # type, description try: - [btype, description] = tail.split(None, 1) + btype, description = tail.split(None, 1) # make life easy and strip quotes description = description.replace("'", "").replace('"', "").replace("\\", "").strip() except ValueError: - [btype, description] = [tail,'NO DESCRIPTION'] + btype, description = [tail,'NO DESCRIPTION'] # keyword-check kwcheck = check_prefix(bto, btype) diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 83e7ea81ca5..3a7066ff41a 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -38,6 +38,7 @@ set(INC ../render/extern/include ../../../intern/elbeem/extern ../../../intern/guardedalloc + ../../../intern/opennl/extern ) set(INC_SYS @@ -64,6 +65,7 @@ set(SRC intern/MOD_fluidsim_util.c intern/MOD_hook.c intern/MOD_lattice.c + intern/MOD_laplaciansmooth.c intern/MOD_mask.c intern/MOD_meshdeform.c intern/MOD_mirror.c @@ -117,13 +119,6 @@ if(WITH_MOD_REMESH) ) endif() -if(WITH_MOD_DECIMATE) - add_definitions(-DWITH_MOD_DECIMATE) - list(APPEND INC - ../../../intern/decimation/extern - ) -endif() - if(WITH_MOD_FLUID) add_definitions(-DWITH_MOD_FLUID) endif() diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h index bf411c3b2fc..a4817ff775d 100644 --- a/source/blender/modifiers/MOD_modifiertypes.h +++ b/source/blender/modifiers/MOD_modifiertypes.h @@ -75,8 +75,9 @@ extern ModifierTypeInfo modifierType_WeightVGProximity; extern ModifierTypeInfo modifierType_DynamicPaint; extern ModifierTypeInfo modifierType_Remesh; extern ModifierTypeInfo modifierType_Skin; +extern ModifierTypeInfo modifierType_LaplacianSmooth; /* MOD_util.c */ void modifier_type_init(ModifierTypeInfo *types[]); -#endif //__MOD_MODIFIERTYPES_H__ +#endif /* __MOD_MODIFIERTYPES_H__ */ diff --git a/source/blender/modifiers/SConscript b/source/blender/modifiers/SConscript index 2b506cce2cf..62fd9ba2de1 100644 --- a/source/blender/modifiers/SConscript +++ b/source/blender/modifiers/SConscript @@ -4,7 +4,7 @@ Import ('env') sources = env.Glob('intern/*.c') incs = '. ./intern' -incs += ' #/intern/guardedalloc #/intern/decimation/extern #/intern/bsp/extern #/intern/elbeem/extern #/extern/glew/include' +incs += ' #/intern/guardedalloc #/intern/bsp/extern #/intern/elbeem/extern #/extern/glew/include #/intern/opennl/extern' incs += ' ../render/extern/include ../blenloader ../bmesh' incs += ' ../include ../blenlib ../blenfont ../makesdna ../makesrna ../blenkernel ../blenkernel/intern' incs += ' ../gpu' @@ -20,9 +20,6 @@ if env['WITH_BF_REMESH']: incs += ' #/intern/dualcon' defs.append('WITH_MOD_REMESH') -if env ['WITH_BF_DECIMATE']: - defs.append('WITH_MOD_DECIMATE') - if env['WITH_BF_FLUID']: defs.append('WITH_MOD_FLUID') diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index e6d86de45b4..7219038b087 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -135,13 +135,13 @@ static void deformVerts(ModifierData *md, Object *ob, } static void deformVertsEM( - ModifierData *md, Object *ob, struct BMEditMesh *editData, + ModifierData *md, Object *ob, struct BMEditMesh *em, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { ArmatureModifierData *amd = (ArmatureModifierData *) md; DerivedMesh *dm = derivedData; - if (!derivedData) dm = CDDM_from_BMEditMesh(editData, ob->data, FALSE, FALSE); + if (!derivedData) dm = CDDM_from_editbmesh(em, FALSE, FALSE); modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */ @@ -158,14 +158,14 @@ static void deformVertsEM( } static void deformMatricesEM( - ModifierData *md, Object *ob, struct BMEditMesh *editData, + ModifierData *md, Object *ob, struct BMEditMesh *em, DerivedMesh *derivedData, float (*vertexCos)[3], float (*defMats)[3][3], int numVerts) { ArmatureModifierData *amd = (ArmatureModifierData *) md; DerivedMesh *dm = derivedData; - if (!derivedData) dm = CDDM_from_BMEditMesh(editData, ob->data, FALSE, FALSE); + if (!derivedData) dm = CDDM_from_editbmesh(em, FALSE, FALSE); armature_deform_verts(amd->object, ob, dm, vertexCos, defMats, numVerts, amd->deformflag, NULL, amd->defgrp_name); diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 26682e30841..b9dd37ac50c 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -53,7 +53,8 @@ #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_object.h" -#include "BKE_tessmesh.h" + +#include "bmesh.h" #include "depsgraph_private.h" @@ -310,10 +311,11 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, int UNUSED(initFlags)) { DerivedMesh *result; - BMEditMesh *em = DM_to_editbmesh(dm, NULL, FALSE); + BMesh *bm = DM_to_bmesh(dm); BMOperator first_dupe_op, dupe_op, old_dupe_op, weld_op; BMVert **first_geom = NULL; - int i, j, indexLen; + int i, j; + int index_len = -1; /* initialize to an invalid value */ /* offset matrix */ float offset[4][4]; float final_offset[4][4]; @@ -406,14 +408,14 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, * cleaner way to do this. One possibility: a "mirror" BMOp would * certainly help by compressing it all into one top-level BMOp that * executes a lot of second-level BMOps. */ - BMO_push(em->bm, NULL); - bmesh_edit_begin(em->bm, 0); + BMO_push(bm, NULL); + bmesh_edit_begin(bm, 0); if (amd->flags & MOD_ARR_MERGE) - BMO_op_init(em->bm, &weld_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), + BMO_op_init(bm, &weld_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "weld_verts"); - BMO_op_initf(em->bm, &dupe_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), + BMO_op_initf(bm, &dupe_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "duplicate geom=%avef"); first_dupe_op = dupe_op; @@ -424,11 +426,11 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, BMOIter oiter; if (j != 0) { - BMO_op_initf(em->bm, &dupe_op, + BMO_op_initf(bm, &dupe_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "duplicate geom=%s", &old_dupe_op, "newout"); } - BMO_op_exec(em->bm, &dupe_op); + BMO_op_exec(bm, &dupe_op); geom_slot = BMO_slot_get(&dupe_op, "geom"); newout_slot = BMO_slot_get(&dupe_op, "newout"); @@ -443,20 +445,23 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, } /* apply transformation matrix */ - BMO_ITER (v, &oiter, em->bm, &dupe_op, "newout", BM_VERT) { + BMO_ITER (v, &oiter, bm, &dupe_op, "newout", BM_VERT) { mul_m4_v3(offset, v->co); } if (amd->flags & MOD_ARR_MERGE) { /*calculate merge mapping*/ if (j == 0) { - indexMap = find_doubles_index_map(em->bm, &dupe_op, - amd, &indexLen); + indexMap = find_doubles_index_map(bm, &dupe_op, + amd, &index_len); } #define _E(s, i) ((BMVert **)(s)->data.buf)[i] - for (i = 0; i < indexLen; i++) { + /* ensure this is set */ + BLI_assert(index_len != -1); + + for (i = 0; i < index_len; i++) { if (!indexMap[i]) continue; /* merge v (from 'newout') into v2 (from old 'geom') */ @@ -465,11 +470,11 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, /* check in case the target vertex (v2) is already marked * for merging */ - while ((v3 = BMO_slot_map_ptr_get(em->bm, &weld_op, "targetmap", v2))) { + while ((v3 = BMO_slot_map_ptr_get(bm, &weld_op, "targetmap", v2))) { v2 = v3; } - BMO_slot_map_ptr_insert(em->bm, &weld_op, "targetmap", v, v2); + BMO_slot_map_ptr_insert(bm, &weld_op, "targetmap", v, v2); } #undef _E @@ -481,7 +486,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, first_dupe_op = dupe_op; if (j >= 2) - BMO_op_finish(em->bm, &old_dupe_op); + BMO_op_finish(bm, &old_dupe_op); old_dupe_op = dupe_op; } @@ -494,45 +499,44 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, * loop) the offset between first and last is different from * dupe X to dupe X+1. */ - merge_first_last(em->bm, amd, &first_dupe_op, &dupe_op, &weld_op); + merge_first_last(bm, amd, &first_dupe_op, &dupe_op, &weld_op); } /* start capping */ if (start_cap || end_cap) { - BM_mesh_elem_hflag_enable_all(em->bm, BM_VERT, BM_ELEM_TAG, FALSE); + BM_mesh_elem_hflag_enable_all(bm, BM_VERT, BM_ELEM_TAG, FALSE); if (start_cap) { float startoffset[4][4]; invert_m4_m4(startoffset, offset); - bm_merge_dm_transform(em->bm, start_cap, startoffset, amd, + bm_merge_dm_transform(bm, start_cap, startoffset, amd, &first_dupe_op, "geom", &weld_op); } if (end_cap) { float endoffset[4][4]; mult_m4_m4m4(endoffset, offset, final_offset); - bm_merge_dm_transform(em->bm, end_cap, endoffset, amd, + bm_merge_dm_transform(bm, end_cap, endoffset, amd, &dupe_op, count == 1 ? "geom" : "newout", &weld_op); } } /* done capping */ /* free remaining dupe operators */ - BMO_op_finish(em->bm, &first_dupe_op); + BMO_op_finish(bm, &first_dupe_op); if (count > 2) - BMO_op_finish(em->bm, &dupe_op); + BMO_op_finish(bm, &dupe_op); /* run merge operator */ if (amd->flags & MOD_ARR_MERGE) { - BMO_op_exec(em->bm, &weld_op); - BMO_op_finish(em->bm, &weld_op); + BMO_op_exec(bm, &weld_op); + BMO_op_finish(bm, &weld_op); } /* Bump the stack level back down to match the adjustment up above */ - BMO_pop(em->bm); + BMO_pop(bm); - BLI_assert(em->looptris == NULL); - result = CDDM_from_BMEditMesh(em, NULL, FALSE, FALSE); + result = CDDM_from_bmesh(bm, FALSE); if ((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) { /* Update normals in case offset object has rotation. */ @@ -543,8 +547,8 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, CDDM_calc_normals(result); } - BMEdit_Free(em); - MEM_freeN(em); + BM_mesh_free(bm); + if (indexMap) MEM_freeN(indexMap); if (first_geom) diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index cdb200ff180..3e3bcb73491 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -38,11 +38,11 @@ #include "BKE_cdderivedmesh.h" #include "BKE_modifier.h" -#include "BKE_tessmesh.h" #include "BKE_mesh.h" - #include "BKE_bmesh.h" /* only for defines */ +#include "bmesh.h" + #include "DNA_object_types.h" #include "MEM_guardedalloc.h" @@ -88,10 +88,12 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) return dataMask; } -#define EDGE_MARK 1 +// #define USE_BM_BEVEL_OP_AS_MOD #ifdef USE_BM_BEVEL_OP_AS_MOD +#define EDGE_MARK 1 + /* BMESH_TODO * * this bevel calls the operator which is missing many of the options @@ -111,14 +113,12 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *UNUSED(ob), { DerivedMesh *result; BMesh *bm; - BMEditMesh *em; BMIter iter; BMEdge *e; BevelModifierData *bmd = (BevelModifierData *) md; - float threshold = cos((bmd->bevel_angle + 0.00001) * M_PI / 180.0); + float threshold = cos((bmd->bevel_angle + 0.00001f) * M_PI / 180.0f); - em = DM_to_editbmesh(dm, NULL, FALSE); - bm = em->bm; + bm = DM_to_bmesh(dm); BM_mesh_normals_update(bm, FALSE); BMO_push(bm, NULL); @@ -148,10 +148,8 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *UNUSED(ob), EDGE_MARK, bmd->value, (bmd->flags & BME_BEVEL_EVEN) != 0, (bmd->flags & BME_BEVEL_DIST) != 0); BMO_pop(bm); - BLI_assert(em->looptris == NULL); - result = CDDM_from_BMEditMesh(em, NULL, TRUE, FALSE); - BMEdit_Free(em); - MEM_freeN(em); + result = CDDM_from_bmesh(bm, TRUE); + BM_mesh_free(bm); return result; } @@ -164,7 +162,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob), ModifierApplyFlag UNUSED(flag)) { DerivedMesh *result; - BMEditMesh *em; + BMesh *bm; /*bDeformGroup *def;*/ int /*i,*/ options, defgrp_index = -1; @@ -175,18 +173,16 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob), #if 0 if ((options & BME_BEVEL_VWEIGHT) && bmd->defgrp_name[0]) { defgrp_index = defgroup_name_index(ob, bmd->defgrp_name); - if (defgrp_index < 0) { + if (defgrp_index == -1) { options &= ~BME_BEVEL_VWEIGHT; } } #endif - em = DM_to_editbmesh(derivedData, NULL, FALSE); - BME_bevel(em, bmd->value, bmd->res, options, defgrp_index, DEG2RADF(bmd->bevel_angle), NULL, FALSE); - BLI_assert(em->looptris == NULL); - result = CDDM_from_BMEditMesh(em, NULL, TRUE, FALSE); - BMEdit_Free(em); - MEM_freeN(em); + bm = DM_to_bmesh(derivedData); + BME_bevel(bm, bmd->value, bmd->res, options, defgrp_index, DEG2RADF(bmd->bevel_angle), NULL); + result = CDDM_from_bmesh(bm, TRUE); + BM_mesh_free(bm); /* until we allow for dirty normal flag, always calc, * note: calculating on the CDDM is faster then the BMesh equivalent */ @@ -206,29 +202,29 @@ static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob, ModifierTypeInfo modifierType_Bevel = { - /* name */ "Bevel", - /* structName */ "BevelModifierData", - /* structSize */ sizeof(BevelModifierData), - /* type */ eModifierTypeType_Constructive, - /* flags */ eModifierTypeFlag_AcceptsMesh | - eModifierTypeFlag_SupportsEditmode | - eModifierTypeFlag_EnableInEditmode, + /* name */ "Bevel", + /* structName */ "BevelModifierData", + /* structSize */ sizeof(BevelModifierData), + /* type */ eModifierTypeType_Constructive, + /* flags */ eModifierTypeFlag_AcceptsMesh | + eModifierTypeFlag_SupportsEditmode | + eModifierTypeFlag_EnableInEditmode, - /* copyData */ copyData, - /* deformVerts */ NULL, - /* deformMatrices */ NULL, - /* deformVertsEM */ NULL, - /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, - /* applyModifierEM */ applyModifierEM, - /* initData */ initData, - /* requiredDataMask */ requiredDataMask, - /* freeData */ NULL, - /* isDisabled */ NULL, - /* updateDepgraph */ NULL, - /* dependsOnTime */ NULL, - /* dependsOnNormals */ NULL, + /* copyData */ copyData, + /* deformVerts */ NULL, + /* deformMatrices */ NULL, + /* deformVertsEM */ NULL, + /* deformMatricesEM */ NULL, + /* applyModifier */ applyModifier, + /* applyModifierEM */ applyModifierEM, + /* initData */ initData, + /* requiredDataMask */ requiredDataMask, + /* freeData */ NULL, + /* isDisabled */ NULL, + /* updateDepgraph */ NULL, + /* dependsOnTime */ NULL, + /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, - /* foreachTexLink */ NULL, + /* foreachIDLink */ NULL, + /* foreachTexLink */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c index 5c78a8efe23..0a48003fc81 100644 --- a/source/blender/modifiers/intern/MOD_boolean.c +++ b/source/blender/modifiers/intern/MOD_boolean.c @@ -167,7 +167,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, if (result) return result; else - modifier_setError(md, "%s", TIP_("Can't execute boolean operation.")); + modifier_setError(md, "Cannot execute boolean operation"); } return derivedData; @@ -192,28 +192,28 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED( ModifierTypeInfo modifierType_Boolean = { - /* name */ "Boolean", - /* structName */ "BooleanModifierData", - /* structSize */ sizeof(BooleanModifierData), - /* type */ eModifierTypeType_Nonconstructive, - /* flags */ eModifierTypeFlag_AcceptsMesh | - eModifierTypeFlag_UsesPointCache, + /* name */ "Boolean", + /* structName */ "BooleanModifierData", + /* structSize */ sizeof(BooleanModifierData), + /* type */ eModifierTypeType_Nonconstructive, + /* flags */ eModifierTypeFlag_AcceptsMesh | + eModifierTypeFlag_UsesPointCache, - /* copyData */ copyData, - /* deformVerts */ NULL, - /* deformMatrices */ NULL, - /* deformVertsEM */ NULL, - /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, - /* applyModifierEM */ NULL, - /* initData */ NULL, - /* requiredDataMask */ requiredDataMask, - /* freeData */ NULL, - /* isDisabled */ isDisabled, - /* updateDepgraph */ updateDepgraph, - /* dependsOnTime */ NULL, - /* dependsOnNormals */ NULL, + /* copyData */ copyData, + /* deformVerts */ NULL, + /* deformMatrices */ NULL, + /* deformVertsEM */ NULL, + /* deformMatricesEM */ NULL, + /* applyModifier */ applyModifier, + /* applyModifierEM */ NULL, + /* initData */ NULL, + /* requiredDataMask */ requiredDataMask, + /* freeData */ NULL, + /* isDisabled */ isDisabled, + /* updateDepgraph */ updateDepgraph, + /* dependsOnTime */ NULL, + /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, - /* foreachTexLink */ NULL, + /* foreachIDLink */ NULL, + /* foreachTexLink */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_boolean_util.c b/source/blender/modifiers/intern/MOD_boolean_util.c index bded11ddfa7..2ff93532d14 100644 --- a/source/blender/modifiers/intern/MOD_boolean_util.c +++ b/source/blender/modifiers/intern/MOD_boolean_util.c @@ -361,9 +361,9 @@ static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh( /* create a new DerivedMesh */ result = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements, 0, 0); - CustomData_merge(&dm1->faceData, &result->faceData, CD_MASK_DERIVEDMESH & ~(CD_MASK_NORMAL | CD_MASK_POLYINDEX | CD_MASK_ORIGINDEX), + CustomData_merge(&dm1->faceData, &result->faceData, CD_MASK_DERIVEDMESH & ~(CD_MASK_NORMAL | CD_MASK_ORIGINDEX), CD_DEFAULT, face_it->num_elements); - CustomData_merge(&dm2->faceData, &result->faceData, CD_MASK_DERIVEDMESH & ~(CD_MASK_NORMAL | CD_MASK_POLYINDEX | CD_MASK_ORIGINDEX), + CustomData_merge(&dm2->faceData, &result->faceData, CD_MASK_DERIVEDMESH & ~(CD_MASK_NORMAL | CD_MASK_ORIGINDEX), CD_DEFAULT, face_it->num_elements); /* step through the vertex iterators: */ diff --git a/source/blender/modifiers/intern/MOD_boolean_util.h b/source/blender/modifiers/intern/MOD_boolean_util.h index b996dc6d6ba..209db60f0c9 100644 --- a/source/blender/modifiers/intern/MOD_boolean_util.h +++ b/source/blender/modifiers/intern/MOD_boolean_util.h @@ -51,4 +51,4 @@ int NewBooleanMesh(struct Scene *scene, struct Base *base, struct Base *base_sel struct DerivedMesh *NewBooleanDerivedMesh(struct DerivedMesh *dm, struct Object *ob, struct DerivedMesh *dm_select, struct Object *ob_select, int int_op_type); -#endif // MOD_BOOLEAN_UTILS +#endif /* MOD_BOOLEAN_UTILS */ diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c index 121b0ee89e3..2105a6efd21 100644 --- a/source/blender/modifiers/intern/MOD_build.c +++ b/source/blender/modifiers/intern/MOD_build.c @@ -293,27 +293,27 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob), ModifierTypeInfo modifierType_Build = { - /* name */ "Build", - /* structName */ "BuildModifierData", - /* structSize */ sizeof(BuildModifierData), - /* type */ eModifierTypeType_Nonconstructive, - /* flags */ eModifierTypeFlag_AcceptsMesh | - eModifierTypeFlag_AcceptsCVs, - /* copyData */ copyData, - /* deformVerts */ NULL, - /* deformMatrices */ NULL, - /* deformVertsEM */ NULL, - /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, - /* applyModifierEM */ NULL, - /* initData */ initData, - /* requiredDataMask */ NULL, - /* freeData */ NULL, - /* isDisabled */ NULL, - /* updateDepgraph */ NULL, - /* dependsOnTime */ dependsOnTime, - /* dependsOnNormals */ NULL, + /* name */ "Build", + /* structName */ "BuildModifierData", + /* structSize */ sizeof(BuildModifierData), + /* type */ eModifierTypeType_Nonconstructive, + /* flags */ eModifierTypeFlag_AcceptsMesh | + eModifierTypeFlag_AcceptsCVs, + /* copyData */ copyData, + /* deformVerts */ NULL, + /* deformMatrices */ NULL, + /* deformVertsEM */ NULL, + /* deformMatricesEM */ NULL, + /* applyModifier */ applyModifier, + /* applyModifierEM */ NULL, + /* initData */ initData, + /* requiredDataMask */ NULL, + /* freeData */ NULL, + /* isDisabled */ NULL, + /* updateDepgraph */ NULL, + /* dependsOnTime */ dependsOnTime, + /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, - /* foreachTexLink */ NULL, + /* foreachIDLink */ NULL, + /* foreachTexLink */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index dc6fef9b617..54f3efcc84c 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -155,7 +155,7 @@ static void copyData(ModifierData *md, ModifierData *target) if (clmd->sim_parms->effector_weights) tclmd->sim_parms->effector_weights = MEM_dupallocN(clmd->sim_parms->effector_weights); tclmd->coll_parms = MEM_dupallocN(clmd->coll_parms); - tclmd->point_cache = BKE_ptcache_copy_list(&tclmd->ptcaches, &clmd->ptcaches); + tclmd->point_cache = BKE_ptcache_copy_list(&tclmd->ptcaches, &clmd->ptcaches, FALSE); tclmd->clothObject = NULL; } @@ -180,7 +180,7 @@ static void freeData(ModifierData *md) MEM_freeN(clmd->sim_parms); } if (clmd->coll_parms) - MEM_freeN(clmd->coll_parms); + MEM_freeN(clmd->coll_parms); BKE_ptcache_free_list(&clmd->ptcaches); clmd->point_cache = NULL; diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c index 0ce4d74aebb..3ef6b9bfcb8 100644 --- a/source/blender/modifiers/intern/MOD_curve.c +++ b/source/blender/modifiers/intern/MOD_curve.c @@ -125,12 +125,12 @@ static void deformVerts(ModifierData *md, Object *ob, } static void deformVertsEM( - ModifierData *md, Object *ob, struct BMEditMesh *editData, + ModifierData *md, Object *ob, struct BMEditMesh *em, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm = derivedData; - if (!derivedData) dm = CDDM_from_BMEditMesh(editData, ob->data, FALSE, FALSE); + if (!derivedData) dm = CDDM_from_editbmesh(em, FALSE, FALSE); deformVerts(md, ob, dm, vertexCos, numVerts, 0); diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index cb6681bfa68..dc29e59d549 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -32,10 +32,10 @@ * \ingroup modifiers */ - -#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" #include "BLI_math.h" +#include "BLI_string.h" #include "BLI_utildefines.h" #include "BLF_translation.h" @@ -44,12 +44,16 @@ #include "BKE_mesh.h" #include "BKE_modifier.h" +#include "BKE_deform.h" #include "BKE_particle.h" #include "BKE_cdderivedmesh.h" +#include "bmesh.h" -#ifdef WITH_MOD_DECIMATE -#include "LOD_decimation.h" +// #define USE_TIMEIT + +#ifdef USE_TIMEIT +# include "PIL_time.h" #endif #include "MOD_util.h" @@ -59,6 +63,7 @@ static void initData(ModifierData *md) DecimateModifierData *dmd = (DecimateModifierData *) md; dmd->percent = 1.0; + dmd->angle = DEG2RADF(15.0f); } static void copyData(ModifierData *md, ModifierData *target) @@ -67,146 +72,136 @@ static void copyData(ModifierData *md, ModifierData *target) DecimateModifierData *tdmd = (DecimateModifierData *) target; tdmd->percent = dmd->percent; + tdmd->iter = dmd->iter; + tdmd->angle = dmd->angle; + BLI_strncpy(tdmd->defgrp_name, dmd->defgrp_name, sizeof(tdmd->defgrp_name)); + tdmd->flag = dmd->flag; + tdmd->mode = dmd->mode; } -#ifdef WITH_MOD_DECIMATE -static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob), +static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) +{ + DecimateModifierData *dmd = (DecimateModifierData *) md; + CustomDataMask dataMask = 0; + + /* ask for vertexgroups if we need them */ + if (dmd->defgrp_name[0]) dataMask |= CD_MASK_MDEFORMVERT; + + return dataMask; +} + +static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, ModifierApplyFlag UNUSED(flag)) { DecimateModifierData *dmd = (DecimateModifierData *) md; DerivedMesh *dm = derivedData, *result = NULL; - MVert *mvert; - MFace *mface; - LOD_Decimation_Info lod; - int totvert, totface; - int a, numTris; + BMesh *bm; - DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */ + float *vweights = NULL; - mvert = dm->getVertArray(dm); - mface = dm->getTessFaceArray(dm); - totvert = dm->getNumVerts(dm); - totface = dm->getNumTessFaces(dm); +#ifdef USE_TIMEIT + TIMEIT_START(decim); +#endif - numTris = 0; - for (a = 0; a < totface; a++) { - MFace *mf = &mface[a]; - numTris++; - if (mf->v4) numTris++; + /* set up front so we dont show invalid info in the UI */ + dmd->face_count = dm->getNumPolys(dm); + + switch (dmd->mode) { + case MOD_DECIM_MODE_COLLAPSE: + if (dmd->percent == 1.0f) { + return dm; + } + break; + case MOD_DECIM_MODE_UNSUBDIV: + if (dmd->iter == 0) { + return dm; + } + break; + case MOD_DECIM_MODE_DISSOLVE: + if (dmd->angle == 0.0f) { + return dm; + } + break; } - if (numTris < 3) { - modifier_setError(md, "%s", TIP_("Modifier requires more than 3 input faces (triangles).")); - dm = CDDM_copy(dm); + if (dmd->face_count <= 3) { + modifier_setError(md, "Modifier requires more than 3 input faces"); return dm; } - lod.vertex_buffer = MEM_mallocN(3 * sizeof(float) * totvert, "vertices"); - lod.vertex_normal_buffer = MEM_mallocN(3 * sizeof(float) * totvert, "normals"); - lod.triangle_index_buffer = MEM_mallocN(3 * sizeof(int) * numTris, "trias"); - lod.vertex_num = totvert; - lod.face_num = numTris; + if (dmd->mode == MOD_DECIM_MODE_COLLAPSE) { + if (dmd->defgrp_name[0]) { + MDeformVert *dvert; + int defgrp_index; - for (a = 0; a < totvert; a++) { - MVert *mv = &mvert[a]; - float *vbCo = &lod.vertex_buffer[a * 3]; - float *vbNo = &lod.vertex_normal_buffer[a * 3]; + modifier_get_vgroup(ob, dm, dmd->defgrp_name, &dvert, &defgrp_index); - copy_v3_v3(vbCo, mv->co); - normal_short_to_float_v3(vbNo, mv->no); - } + if (dvert) { + const unsigned int vert_tot = dm->getNumVerts(dm); + unsigned int i; - numTris = 0; - for (a = 0; a < totface; a++) { - MFace *mf = &mface[a]; - int *tri = &lod.triangle_index_buffer[3 * numTris++]; - tri[0] = mf->v1; - tri[1] = mf->v2; - tri[2] = mf->v3; + vweights = MEM_mallocN(vert_tot * sizeof(float), __func__); - if (mf->v4) { - tri = &lod.triangle_index_buffer[3 * numTris++]; - tri[0] = mf->v1; - tri[1] = mf->v3; - tri[2] = mf->v4; - } - } - - dmd->faceCount = 0; - if (LOD_LoadMesh(&lod) ) { - if (LOD_PreprocessMesh(&lod) ) { - /* we assume the decim_faces tells how much to reduce */ - - while (lod.face_num > numTris * dmd->percent) { - if (LOD_CollapseEdge(&lod) == 0) break; - } - - if (lod.vertex_num > 2) { - result = CDDM_new(lod.vertex_num, 0, lod.face_num, 0, 0); - dmd->faceCount = lod.face_num; - } - else - result = CDDM_new(lod.vertex_num, 0, 0, 0, 0); - - mvert = CDDM_get_verts(result); - for (a = 0; a < lod.vertex_num; a++) { - MVert *mv = &mvert[a]; - float *vbCo = &lod.vertex_buffer[a * 3]; - - copy_v3_v3(mv->co, vbCo); - } - - if (lod.vertex_num > 2) { - mface = CDDM_get_tessfaces(result); - for (a = 0; a < lod.face_num; a++) { - MFace *mf = &mface[a]; - int *tri = &lod.triangle_index_buffer[a * 3]; - mf->v1 = tri[0]; - mf->v2 = tri[1]; - mf->v3 = tri[2]; - test_index_face(mf, NULL, 0, 3); + if (dmd->flag & MOD_DECIM_FLAG_INVERT_VGROUP) { + for (i = 0; i < vert_tot; i++) { + vweights[i] = 1.0f - defvert_find_weight(&dvert[i], defgrp_index); + } + } + else { + for (i = 0; i < vert_tot; i++) { + vweights[i] = defvert_find_weight(&dvert[i], defgrp_index); + } } } - - CDDM_calc_edges_tessface(result); } - else - modifier_setError(md, "%s", TIP_("Out of memory.")); - - LOD_FreeDecimationData(&lod); } - else - modifier_setError(md, "%s", TIP_("Non-manifold mesh as input.")); - MEM_freeN(lod.vertex_buffer); - MEM_freeN(lod.vertex_normal_buffer); - MEM_freeN(lod.triangle_index_buffer); + bm = DM_to_bmesh(dm); - if (result) { - CDDM_tessfaces_to_faces(result); /*builds ngon faces from tess (mface) faces*/ - - return result; + switch (dmd->mode) { + case MOD_DECIM_MODE_COLLAPSE: + { + const int do_triangulate = (dmd->flag & MOD_DECIM_FLAG_TRIANGULATE) != 0; + BM_mesh_decimate_collapse(bm, dmd->percent, vweights, do_triangulate); + break; + } + case MOD_DECIM_MODE_UNSUBDIV: + { + BM_mesh_decimate_unsubdivide(bm, dmd->iter); + break; + } + case MOD_DECIM_MODE_DISSOLVE: + { + const int do_dissolve_boundaries = (dmd->flag & MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS) != 0; + BM_mesh_decimate_dissolve(bm, dmd->angle, do_dissolve_boundaries); + break; + } } - else { - return dm; + + if (vweights) { + MEM_freeN(vweights); } + + /* update for display only */ + dmd->face_count = bm->totface; + result = CDDM_from_bmesh(bm, FALSE); + BM_mesh_free(bm); + +#ifdef USE_TIMEIT + TIMEIT_END(decim); +#endif + + return result; } -#else // WITH_MOD_DECIMATE -static DerivedMesh *applyModifier(ModifierData *UNUSED(md), Object *UNUSED(ob), - DerivedMesh *derivedData, - ModifierApplyFlag UNUSED(flag)) -{ - return derivedData; -} -#endif // WITH_MOD_DECIMATE ModifierTypeInfo modifierType_Decimate = { /* name */ "Decimate", /* structName */ "DecimateModifierData", /* structSize */ sizeof(DecimateModifierData), /* type */ eModifierTypeType_Nonconstructive, - /* flags */ eModifierTypeFlag_AcceptsMesh, + /* flags */ eModifierTypeFlag_AcceptsMesh | + eModifierTypeFlag_AcceptsCVs, /* copyData */ copyData, /* deformVerts */ NULL, /* deformMatrices */ NULL, @@ -215,7 +210,7 @@ ModifierTypeInfo modifierType_Decimate = { /* applyModifier */ applyModifier, /* applyModifierEM */ NULL, /* initData */ initData, - /* requiredDataMask */ NULL, + /* requiredDataMask */ requiredDataMask, /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ NULL, diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c index 7d7bfade9b7..80866a7c435 100644 --- a/source/blender/modifiers/intern/MOD_dynamicpaint.c +++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c @@ -170,10 +170,10 @@ ModifierTypeInfo modifierType_DynamicPaint = { /* structSize */ sizeof(DynamicPaintModifierData), /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | -/* eModifierTypeFlag_SupportsMapping |*/ - eModifierTypeFlag_UsesPointCache | - eModifierTypeFlag_Single | - eModifierTypeFlag_UsesPreview, +/* eModifierTypeFlag_SupportsMapping |*/ + eModifierTypeFlag_UsesPointCache | + eModifierTypeFlag_Single | + eModifierTypeFlag_UsesPreview, /* copyData */ copyData, /* deformVerts */ NULL, diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index b1c3459bf51..21717d07fef 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -43,9 +43,10 @@ #include "BKE_cdderivedmesh.h" #include "BKE_modifier.h" -#include "BKE_tessmesh.h" #include "BKE_mesh.h" +#include "bmesh.h" + #include "DNA_object_types.h" /* EdgeSplit */ @@ -61,15 +62,12 @@ static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Obj { DerivedMesh *result; BMesh *bm; - BMEditMesh *em; BMIter iter; BMEdge *e; float threshold = cosf((emd->split_angle + 0.00001f) * (float)M_PI / 180.0f); - em = DM_to_editbmesh(dm, NULL, FALSE); - bm = em->bm; + bm = DM_to_bmesh(dm); - BM_mesh_normals_update(bm, FALSE); BMO_push(bm, NULL); if (emd->flags & MOD_EDGESPLIT_FROMANGLE) { @@ -110,10 +108,8 @@ static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Obj /* BM_mesh_validate(bm); */ /* for troubleshooting */ - BLI_assert(em->looptris == NULL); - result = CDDM_from_BMEditMesh(em, NULL, TRUE, FALSE); - BMEdit_Free(em); - MEM_freeN(em); + result = CDDM_from_bmesh(bm, TRUE); + BM_mesh_free(bm); return result; } diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index b9593353288..92ad6faa3ce 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -206,11 +206,11 @@ static MFace *get_dface(DerivedMesh *dm, DerivedMesh *split, int cur, int i, MFa } #define SET_VERTS(a, b, c, d) { \ - v[0] = mf->v##a; uv[0] = a - 1; \ - v[1] = mf->v##b; uv[1] = b - 1; \ - v[2] = mf->v##c; uv[2] = c - 1; \ - v[3] = mf->v##d; uv[3] = d - 1; \ - } (void)0 + v[0] = mf->v##a; uv[0] = a - 1; \ + v[1] = mf->v##b; uv[1] = b - 1; \ + v[2] = mf->v##c; uv[2] = c - 1; \ + v[3] = mf->v##d; uv[3] = d - 1; \ + } (void)0 #define GET_ES(v1, v2) edgecut_get(eh, v1, v2) #define INT_UV(uvf, c0, c1) interp_v2_v2v2(uvf, mf->uv[c0], mf->uv[c1], 0.5f) @@ -669,8 +669,7 @@ static DerivedMesh *cutEdges(ExplodeModifierData *emd, DerivedMesh *dm) mv = CDDM_get_vert(splitdm, ed_v1); - add_v3_v3(dupve->co, mv->co); - mul_v3_fl(dupve->co, 0.5f); + mid_v3_v3v3(dupve->co, dupve->co, mv->co); } BLI_edgehashIterator_free(ehi); @@ -813,7 +812,7 @@ static DerivedMesh *explodeMesh(ExplodeModifierData *emd, sim.psys = psmd->psys; sim.psmd = psmd; - /* timestep= psys_get_timestep(&sim); */ + /* timestep = psys_get_timestep(&sim); */ cfra = BKE_scene_frame_get(scene); @@ -861,7 +860,7 @@ static DerivedMesh *explodeMesh(ExplodeModifierData *emd, /* the final duplicated vertices */ explode = CDDM_from_template(dm, totdup, 0, totface - delface, 0, 0); mtface = CustomData_get_layer_named(&explode->faceData, CD_MTFACE, emd->uvname); - /*dupvert= CDDM_get_verts(explode);*/ + /*dupvert = CDDM_get_verts(explode);*/ /* getting back to object space */ invert_m4_m4(imat, ob->obmat); @@ -1039,26 +1038,26 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, ModifierTypeInfo modifierType_Explode = { - /* name */ "Explode", - /* structName */ "ExplodeModifierData", - /* structSize */ sizeof(ExplodeModifierData), - /* type */ eModifierTypeType_Constructive, - /* flags */ eModifierTypeFlag_AcceptsMesh, - /* copyData */ copyData, - /* deformVerts */ NULL, - /* deformMatrices */ NULL, - /* deformVertsEM */ NULL, - /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, - /* applyModifierEM */ NULL, - /* initData */ initData, - /* requiredDataMask */ requiredDataMask, - /* freeData */ freeData, - /* isDisabled */ NULL, - /* updateDepgraph */ NULL, - /* dependsOnTime */ dependsOnTime, - /* dependsOnNormals */ NULL, + /* name */ "Explode", + /* structName */ "ExplodeModifierData", + /* structSize */ sizeof(ExplodeModifierData), + /* type */ eModifierTypeType_Constructive, + /* flags */ eModifierTypeFlag_AcceptsMesh, + /* copyData */ copyData, + /* deformVerts */ NULL, + /* deformMatrices */ NULL, + /* deformVertsEM */ NULL, + /* deformMatricesEM */ NULL, + /* applyModifier */ applyModifier, + /* applyModifierEM */ NULL, + /* initData */ initData, + /* requiredDataMask */ requiredDataMask, + /* freeData */ freeData, + /* isDisabled */ NULL, + /* updateDepgraph */ NULL, + /* dependsOnTime */ dependsOnTime, + /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, - /* foreachTexLink */ NULL, + /* foreachIDLink */ NULL, + /* foreachTexLink */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.c b/source/blender/modifiers/intern/MOD_fluidsim_util.c index 9acac6d00cd..47523286229 100644 --- a/source/blender/modifiers/intern/MOD_fluidsim_util.c +++ b/source/blender/modifiers/intern/MOD_fluidsim_util.c @@ -529,7 +529,7 @@ DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, Scene *scene, fss = fluidmd->fss; /* timescale not supported yet - * clmd->sim_parms->timescale= timescale; */ + * clmd->sim_parms->timescale = timescale; */ /* support reversing of baked fluid frames here */ if ((fss->flag & OB_FLUIDSIM_REVERSE) && (fss->lastgoodframe >= 0)) { diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c new file mode 100644 index 00000000000..6f6589d4d14 --- /dev/null +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -0,0 +1,703 @@ +/* + * ***** 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 by the Blender Foundation. + * All rights reserved. + * + * Contributor(s): Alexander Pinzon + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +/** \file blender/modifiers/intern/MOD_laplaciansmooth.c + * \ingroup modifiers + */ + + +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" + +#include "BLI_math.h" +#include "BLI_utildefines.h" +#include "BLI_string.h" + +#include "MEM_guardedalloc.h" + +#include "BKE_cdderivedmesh.h" +#include "BKE_deform.h" +#include "BKE_displist.h" +#include "BKE_mesh.h" +#include "BKE_modifier.h" +#include "BKE_object.h" +#include "BKE_particle.h" +#include "BKE_tessmesh.h" + +#include "MOD_modifiertypes.h" +#include "MOD_util.h" + +#include "ONL_opennl.h" + +#define MOD_LAPLACIANSMOOTH_MAX_EDGE_PERCENTAGE 1.8f +#define MOD_LAPLACIANSMOOTH_MIN_EDGE_PERCENTAGE 0.02f + +struct BLaplacianSystem { + float *eweights; /* Length weights per Edge */ + float (*fweights)[3]; /* Cotangent weights per face */ + float *ring_areas; /* Total area per ring*/ + float *vlengths; /* Total sum of lengths(edges) per vertice*/ + float *vweights; /* Total sum of weights per vertice*/ + int numEdges; /* Number of edges*/ + int numFaces; /* Number of faces*/ + int numVerts; /* Number of verts*/ + short *numNeFa; /* Number of neighboors faces around vertice*/ + short *numNeEd; /* Number of neighboors Edges around vertice*/ + short *zerola; /* Is zero area or length*/ + + /* Pointers to data*/ + float (*vertexCos)[3]; + MFace *mfaces; + MEdge *medges; + NLContext *context; + + /*Data*/ + float min_area; + float vert_centroid[3]; +}; +typedef struct BLaplacianSystem LaplacianSystem; + +static CustomDataMask required_data_mask(Object *UNUSED(ob), ModifierData *md); +static int is_disabled(ModifierData *md, int UNUSED(useRenderParams)); +static float compute_volume(float (*vertexCos)[3], MFace *mfaces, int numFaces); +static float cotan_weight(float *v1, float *v2, float *v3); +static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts); +static void copy_data(ModifierData *md, ModifierData *target); +static void delete_laplacian_system(LaplacianSystem *sys); +static void delete_void_pointer(void *data); +static void fill_laplacian_matrix(LaplacianSystem *sys); +static void init_data(ModifierData *md); +static void init_laplacian_matrix(LaplacianSystem *sys); +static void memset_laplacian_system(LaplacianSystem *sys, int val); +static void volume_preservation(LaplacianSystem *sys, float vini, float vend, short flag); +static void validate_solution(LaplacianSystem *sys, short flag); + +static void delete_void_pointer(void *data) +{ + if (data) { + MEM_freeN(data); + data = NULL; + } +} + +static void delete_laplacian_system(LaplacianSystem *sys) +{ + delete_void_pointer(sys->eweights); + delete_void_pointer(sys->fweights); + delete_void_pointer(sys->numNeEd); + delete_void_pointer(sys->numNeFa); + delete_void_pointer(sys->ring_areas); + delete_void_pointer(sys->vlengths); + delete_void_pointer(sys->vweights); + delete_void_pointer(sys->zerola); + if (sys->context) { + nlDeleteContext(sys->context); + } + sys->vertexCos = NULL; + sys->mfaces = NULL; + sys->medges = NULL; + MEM_freeN(sys); +} + +static void memset_laplacian_system(LaplacianSystem *sys, int val) +{ + memset(sys->eweights, val, sizeof(float) * sys->numEdges); + memset(sys->fweights, val, sizeof(float) * sys->numFaces * 3); + memset(sys->numNeEd, val, sizeof(short) * sys->numVerts); + memset(sys->numNeFa, val, sizeof(short) * sys->numVerts); + memset(sys->ring_areas, val, sizeof(float) * sys->numVerts); + memset(sys->vlengths, val, sizeof(float) * sys->numVerts); + memset(sys->vweights, val, sizeof(float) * sys->numVerts); + memset(sys->zerola, val, sizeof(short) * sys->numVerts); +} + +static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts) +{ + LaplacianSystem *sys; + sys = MEM_callocN(sizeof(LaplacianSystem), "ModLaplSmoothSystem"); + sys->numEdges = a_numEdges; + sys->numFaces = a_numFaces; + sys->numVerts = a_numVerts; + + sys->eweights = MEM_callocN(sizeof(float) * sys->numEdges, "ModLaplSmoothEWeight"); + if (!sys->eweights) { + delete_laplacian_system(sys); + return NULL; + } + + sys->fweights = MEM_callocN(sizeof(float) * 3 * sys->numFaces, "ModLaplSmoothFWeight"); + if (!sys->fweights) { + delete_laplacian_system(sys); + return NULL; + } + + sys->numNeEd = MEM_callocN(sizeof(short) * sys->numVerts, "ModLaplSmoothNumNeEd"); + if (!sys->numNeEd) { + delete_laplacian_system(sys); + return NULL; + } + + sys->numNeFa = MEM_callocN(sizeof(short) * sys->numVerts, "ModLaplSmoothNumNeFa"); + if (!sys->numNeFa) { + delete_laplacian_system(sys); + return NULL; + } + + sys->ring_areas = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothRingAreas"); + if (!sys->ring_areas) { + delete_laplacian_system(sys); + return NULL; + } + + sys->vlengths = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothVlengths"); + if (!sys->vlengths) { + delete_laplacian_system(sys); + return NULL; + } + + sys->vweights = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothVweights"); + if (!sys->vweights) { + delete_laplacian_system(sys); + return NULL; + } + + sys->zerola = MEM_callocN(sizeof(short) * sys->numVerts, "ModLaplSmoothZeloa"); + if (!sys->zerola) { + delete_laplacian_system(sys); + return NULL; + } + + return sys; +} + +static void init_data(ModifierData *md) +{ + LaplacianSmoothModifierData *smd = (LaplacianSmoothModifierData *) md; + smd->lambda = 0.00001f; + smd->lambda_border = 0.00005f; + smd->repeat = 1; + smd->flag = MOD_LAPLACIANSMOOTH_X | MOD_LAPLACIANSMOOTH_Y | MOD_LAPLACIANSMOOTH_Z | MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION; + smd->defgrp_name[0] = '\0'; +} + +static void copy_data(ModifierData *md, ModifierData *target) +{ + LaplacianSmoothModifierData *smd = (LaplacianSmoothModifierData *) md; + LaplacianSmoothModifierData *tsmd = (LaplacianSmoothModifierData *) target; + + tsmd->lambda = smd->lambda; + tsmd->lambda_border = smd->lambda_border; + tsmd->repeat = smd->repeat; + tsmd->flag = smd->flag; + BLI_strncpy(tsmd->defgrp_name, smd->defgrp_name, sizeof(tsmd->defgrp_name)); +} + +static int is_disabled(ModifierData *md, int UNUSED(useRenderParams)) +{ + LaplacianSmoothModifierData *smd = (LaplacianSmoothModifierData *) md; + short flag; + + flag = smd->flag & (MOD_LAPLACIANSMOOTH_X | MOD_LAPLACIANSMOOTH_Y | MOD_LAPLACIANSMOOTH_Z); + + /* disable if modifier is off for X, Y and Z or if factor is 0 */ + if (flag == 0) return 1; + + return 0; +} + +static CustomDataMask required_data_mask(Object *UNUSED(ob), ModifierData *md) +{ + LaplacianSmoothModifierData *smd = (LaplacianSmoothModifierData *)md; + CustomDataMask dataMask = 0; + + /* ask for vertexgroups if we need them */ + if (smd->defgrp_name[0]) dataMask |= CD_MASK_MDEFORMVERT; + + return dataMask; +} + +static float cotan_weight(float *v1, float *v2, float *v3) +{ + float a[3], b[3], c[3], clen; + + sub_v3_v3v3(a, v2, v1); + sub_v3_v3v3(b, v3, v1); + cross_v3_v3v3(c, a, b); + + clen = len_v3(c); + + if (clen == 0.0f) + return 0.0f; + + return dot_v3v3(a, b) / clen; +} + +static float compute_volume(float (*vertexCos)[3], MFace *mfaces, int numFaces) +{ + float vol = 0.0f; + float x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4; + int i; + float *vf[4]; + for (i = 0; i < numFaces; i++) { + vf[0] = vertexCos[mfaces[i].v1]; + vf[1] = vertexCos[mfaces[i].v2]; + vf[2] = vertexCos[mfaces[i].v3]; + + x1 = vf[0][0]; + y1 = vf[0][1]; + z1 = vf[0][2]; + + x2 = vf[1][0]; + y2 = vf[1][1]; + z2 = vf[1][2]; + + x3 = vf[2][0]; + y3 = vf[2][1]; + z3 = vf[2][2]; + + + vol += (1.0f / 6.0f) * (x2 * y3 * z1 + x3 * y1 * z2 - x1 * y3 * z2 - x2 * y1 * z3 + x1 * y2 * z3 - x3 * y2 * z1); + if ((&mfaces[i])->v4) { + vf[3] = vertexCos[mfaces[i].v4]; + x4 = vf[3][0]; + y4 = vf[3][1]; + z4 = vf[3][2]; + vol += (1.0f / 6.0f) * (x1 * y3 * z4 - x1 * y4 * z3 - x3 * y1 * z4 + x3 * z1 * y4 + y1 * x4 * z3 - x4 * y3 * z1); + } + } + return fabsf(vol); +} + +static void volume_preservation(LaplacianSystem *sys, float vini, float vend, short flag) +{ + float beta; + int i; + + if (vend != 0.0f) { + beta = pow(vini / vend, 1.0f / 3.0f); + for (i = 0; i < sys->numVerts; i++) { + if (flag & MOD_LAPLACIANSMOOTH_X) { + sys->vertexCos[i][0] = (sys->vertexCos[i][0] - sys->vert_centroid[0]) * beta + sys->vert_centroid[0]; + } + if (flag & MOD_LAPLACIANSMOOTH_Y) { + sys->vertexCos[i][1] = (sys->vertexCos[i][1] - sys->vert_centroid[1]) * beta + sys->vert_centroid[1]; + } + if (flag & MOD_LAPLACIANSMOOTH_Z) { + sys->vertexCos[i][2] = (sys->vertexCos[i][2] - sys->vert_centroid[2]) * beta + sys->vert_centroid[2]; + } + + } + } +} + +static void init_laplacian_matrix(LaplacianSystem *sys) +{ + float *v1, *v2, *v3, *v4; + float w1, w2, w3, w4; + float areaf; + int i, j; + unsigned int idv1, idv2, idv3, idv4, idv[4]; + int has_4_vert; + for (i = 0; i < sys->numEdges; i++) { + idv1 = sys->medges[i].v1; + idv2 = sys->medges[i].v2; + + v1 = sys->vertexCos[idv1]; + v2 = sys->vertexCos[idv2]; + + sys->numNeEd[idv1] = sys->numNeEd[idv1] + 1; + sys->numNeEd[idv2] = sys->numNeEd[idv2] + 1; + w1 = len_v3v3(v1, v2); + if (w1 < sys->min_area) { + sys->zerola[idv1] = 1; + sys->zerola[idv2] = 1; + } + else { + w1 = 1.0f / w1; + } + + sys->eweights[i] = w1; + } + for (i = 0; i < sys->numFaces; i++) { + has_4_vert = ((&sys->mfaces[i])->v4) ? 1 : 0; + + idv1 = sys->mfaces[i].v1; + idv2 = sys->mfaces[i].v2; + idv3 = sys->mfaces[i].v3; + idv4 = has_4_vert ? sys->mfaces[i].v4 : 0; + + sys->numNeFa[idv1] += 1; + sys->numNeFa[idv2] += 1; + sys->numNeFa[idv3] += 1; + if (has_4_vert) sys->numNeFa[idv4] += 1; + + v1 = sys->vertexCos[idv1]; + v2 = sys->vertexCos[idv2]; + v3 = sys->vertexCos[idv3]; + v4 = has_4_vert ? sys->vertexCos[idv4] : 0; + + if (has_4_vert) { + areaf = area_quad_v3(v1, v2, v3, sys->vertexCos[sys->mfaces[i].v4]); + } + else { + areaf = area_tri_v3(v1, v2, v3); + } + if (fabsf(areaf) < sys->min_area) { + sys->zerola[idv1] = 1; + sys->zerola[idv2] = 1; + sys->zerola[idv3] = 1; + if (has_4_vert) sys->zerola[idv4] = 1; + } + + sys->ring_areas[idv1] += areaf; + sys->ring_areas[idv2] += areaf; + sys->ring_areas[idv3] += areaf; + if (has_4_vert) sys->ring_areas[idv4] += areaf; + + if (has_4_vert) { + + idv[0] = idv1; + idv[1] = idv2; + idv[2] = idv3; + idv[3] = idv4; + + for (j = 0; j < 4; j++) { + idv1 = idv[j]; + idv2 = idv[(j + 1) % 4]; + idv3 = idv[(j + 2) % 4]; + idv4 = idv[(j + 3) % 4]; + + v1 = sys->vertexCos[idv1]; + v2 = sys->vertexCos[idv2]; + v3 = sys->vertexCos[idv3]; + v4 = sys->vertexCos[idv4]; + + w2 = cotan_weight(v4, v1, v2) + cotan_weight(v3, v1, v2); + w3 = cotan_weight(v2, v3, v1) + cotan_weight(v4, v1, v3); + w4 = cotan_weight(v2, v4, v1) + cotan_weight(v3, v4, v1); + + sys->vweights[idv1] += (w2 + w3 + w4) / 4.0f; + } + } + else { + w1 = cotan_weight(v1, v2, v3); + w2 = cotan_weight(v2, v3, v1); + w3 = cotan_weight(v3, v1, v2); + + sys->fweights[i][0] = sys->fweights[i][0] + w1; + sys->fweights[i][1] = sys->fweights[i][1] + w2; + sys->fweights[i][2] = sys->fweights[i][2] + w3; + + sys->vweights[idv1] = sys->vweights[idv1] + w2 + w3; + sys->vweights[idv2] = sys->vweights[idv2] + w1 + w3; + sys->vweights[idv3] = sys->vweights[idv3] + w1 + w2; + } + } + for (i = 0; i < sys->numEdges; i++) { + idv1 = sys->medges[i].v1; + idv2 = sys->medges[i].v2; + /* if is boundary, apply scale-dependent umbrella operator only with neighboors in boundary */ + if (sys->numNeEd[idv1] != sys->numNeFa[idv1] && sys->numNeEd[idv2] != sys->numNeFa[idv2]) { + sys->vlengths[idv1] += sys->eweights[i]; + sys->vlengths[idv2] += sys->eweights[i]; + } + } + +} + +static void fill_laplacian_matrix(LaplacianSystem *sys) +{ + float *v1, *v2, *v3, *v4; + float w2, w3, w4; + int i, j; + int has_4_vert; + unsigned int idv1, idv2, idv3, idv4, idv[4]; + + for (i = 0; i < sys->numFaces; i++) { + idv1 = sys->mfaces[i].v1; + idv2 = sys->mfaces[i].v2; + idv3 = sys->mfaces[i].v3; + has_4_vert = ((&sys->mfaces[i])->v4) ? 1 : 0; + + if (has_4_vert) { + idv[0] = sys->mfaces[i].v1; + idv[1] = sys->mfaces[i].v2; + idv[2] = sys->mfaces[i].v3; + idv[3] = sys->mfaces[i].v4; + for (j = 0; j < 4; j++) { + idv1 = idv[j]; + idv2 = idv[(j + 1) % 4]; + idv3 = idv[(j + 2) % 4]; + idv4 = idv[(j + 3) % 4]; + + v1 = sys->vertexCos[idv1]; + v2 = sys->vertexCos[idv2]; + v3 = sys->vertexCos[idv3]; + v4 = sys->vertexCos[idv4]; + + w2 = cotan_weight(v4, v1, v2) + cotan_weight(v3, v1, v2); + w3 = cotan_weight(v2, v3, v1) + cotan_weight(v4, v1, v3); + w4 = cotan_weight(v2, v4, v1) + cotan_weight(v3, v4, v1); + + w2 = w2 / 4.0f; + w3 = w3 / 4.0f; + w4 = w4 / 4.0f; + + if (sys->numNeEd[idv1] == sys->numNeFa[idv1] && sys->zerola[idv1] == 0) { + nlMatrixAdd(idv1, idv2, w2 * sys->vweights[idv1]); + nlMatrixAdd(idv1, idv3, w3 * sys->vweights[idv1]); + nlMatrixAdd(idv1, idv4, w4 * sys->vweights[idv1]); + } + } + } + else { + /* Is ring if number of faces == number of edges around vertice*/ + if (sys->numNeEd[idv1] == sys->numNeFa[idv1] && sys->zerola[idv1] == 0) { + nlMatrixAdd(idv1, idv2, sys->fweights[i][2] * sys->vweights[idv1]); + nlMatrixAdd(idv1, idv3, sys->fweights[i][1] * sys->vweights[idv1]); + } + if (sys->numNeEd[idv2] == sys->numNeFa[idv2] && sys->zerola[idv2] == 0) { + nlMatrixAdd(idv2, idv1, sys->fweights[i][2] * sys->vweights[idv2]); + nlMatrixAdd(idv2, idv3, sys->fweights[i][0] * sys->vweights[idv2]); + } + if (sys->numNeEd[idv3] == sys->numNeFa[idv3] && sys->zerola[idv3] == 0) { + nlMatrixAdd(idv3, idv1, sys->fweights[i][1] * sys->vweights[idv3]); + nlMatrixAdd(idv3, idv2, sys->fweights[i][0] * sys->vweights[idv3]); + } + } + } + + for (i = 0; i < sys->numEdges; i++) { + idv1 = sys->medges[i].v1; + idv2 = sys->medges[i].v2; + /* Is boundary */ + if (sys->numNeEd[idv1] != sys->numNeFa[idv1] && + sys->numNeEd[idv2] != sys->numNeFa[idv2] && + sys->zerola[idv1] == 0 && + sys->zerola[idv2] == 0) + { + nlMatrixAdd(idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]); + nlMatrixAdd(idv2, idv1, sys->eweights[i] * sys->vlengths[idv2]); + } + } +} + +static void validate_solution(LaplacianSystem *sys, short flag) +{ + int i, idv1, idv2; + float leni, lene; + float vini, vend; + float *vi1, *vi2, ve1[3], ve2[3]; + if (flag & MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION) { + vini = compute_volume(sys->vertexCos, sys->mfaces, sys->numFaces); + } + for (i = 0; i < sys->numEdges; i++) { + idv1 = sys->medges[i].v1; + idv2 = sys->medges[i].v2; + vi1 = sys->vertexCos[idv1]; + vi2 = sys->vertexCos[idv2]; + ve1[0] = nlGetVariable(0, idv1); + ve1[1] = nlGetVariable(1, idv1); + ve1[2] = nlGetVariable(2, idv1); + ve2[0] = nlGetVariable(0, idv2); + ve2[1] = nlGetVariable(1, idv2); + ve2[2] = nlGetVariable(2, idv2); + leni = len_v3v3(vi1, vi2); + lene = len_v3v3(ve1, ve2); + if (lene > leni * MOD_LAPLACIANSMOOTH_MAX_EDGE_PERCENTAGE || lene < leni * MOD_LAPLACIANSMOOTH_MIN_EDGE_PERCENTAGE) { + sys->zerola[idv1] = 1; + sys->zerola[idv2] = 1; + } + } + for (i = 0; i < sys->numVerts; i++) { + if (sys->zerola[i] == 0) { + if (flag & MOD_LAPLACIANSMOOTH_X) { + sys->vertexCos[i][0] = nlGetVariable(0, i); + } + if (flag & MOD_LAPLACIANSMOOTH_Y) { + sys->vertexCos[i][1] = nlGetVariable(1, i); + } + if (flag & MOD_LAPLACIANSMOOTH_Z) { + sys->vertexCos[i][2] = nlGetVariable(2, i); + } + } + } + if (flag & MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION) { + vend = compute_volume(sys->vertexCos, sys->mfaces, sys->numFaces); + volume_preservation(sys, vini, vend, flag); + } +} + +static void laplaciansmoothModifier_do( + LaplacianSmoothModifierData *smd, Object *ob, DerivedMesh *dm, + float (*vertexCos)[3], int numVerts) +{ + LaplacianSystem *sys; + MDeformVert *dvert = NULL; + MDeformVert *dv = NULL; + float w, wpaint; + int i, iter; + int defgrp_index; + + DM_ensure_tessface(dm); + + sys = init_laplacian_system(dm->getNumEdges(dm), dm->getNumTessFaces(dm), numVerts); + if (!sys) { + return; + } + + sys->mfaces = dm->getTessFaceArray(dm); + sys->medges = dm->getEdgeArray(dm); + sys->vertexCos = vertexCos; + sys->min_area = 0.00001f; + modifier_get_vgroup(ob, dm, smd->defgrp_name, &dvert, &defgrp_index); + + sys->vert_centroid[0] = 0.0f; + sys->vert_centroid[1] = 0.0f; + sys->vert_centroid[2] = 0.0f; + for (iter = 0; iter < smd->repeat; iter++) { + memset_laplacian_system(sys, 0); + nlNewContext(); + sys->context = nlGetCurrent(); + nlSolverParameteri(NL_NB_VARIABLES, numVerts); + nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); + nlSolverParameteri(NL_NB_ROWS, numVerts); + nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 3); + + init_laplacian_matrix(sys); + + nlBegin(NL_SYSTEM); + for (i = 0; i < numVerts; i++) { + nlSetVariable(0, i, vertexCos[i][0]); + nlSetVariable(1, i, vertexCos[i][1]); + nlSetVariable(2, i, vertexCos[i][2]); + if (iter == 0) { + add_v3_v3(sys->vert_centroid, vertexCos[i]); + } + } + if (iter == 0 && numVerts > 0) { + mul_v3_fl(sys->vert_centroid, 1.0f / (float)numVerts); + } + + nlBegin(NL_MATRIX); + dv = dvert; + for (i = 0; i < numVerts; i++) { + nlRightHandSideAdd(0, i, vertexCos[i][0]); + nlRightHandSideAdd(1, i, vertexCos[i][1]); + nlRightHandSideAdd(2, i, vertexCos[i][2]); + if (dv) { + wpaint = defvert_find_weight(dv, defgrp_index); + dv++; + } + else { + wpaint = 1.0f; + } + + if (sys->zerola[i] == 0) { + w = sys->vweights[i] * sys->ring_areas[i]; + sys->vweights[i] = (w == 0.0f) ? 0.0f : -smd->lambda * wpaint / (4.0f * w); + w = sys->vlengths[i]; + sys->vlengths[i] = (w == 0.0f) ? 0.0f : -smd->lambda_border * wpaint * 2.0f / w; + + if (sys->numNeEd[i] == sys->numNeFa[i]) { + nlMatrixAdd(i, i, 1.0f + smd->lambda * wpaint / (4.0f * sys->ring_areas[i])); + } + else { + nlMatrixAdd(i, i, 1.0f + smd->lambda_border * wpaint * 2.0f); + } + } + else { + nlMatrixAdd(i, i, 1.0f); + } + } + + fill_laplacian_matrix(sys); + + nlEnd(NL_MATRIX); + nlEnd(NL_SYSTEM); + + if (nlSolveAdvanced(NULL, NL_TRUE)) { + validate_solution(sys, smd->flag); + } + nlDeleteContext(sys->context); + sys->context = NULL; + } + delete_laplacian_system(sys); + +} + +static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts, ModifierApplyFlag UNUSED(flag)) +{ + DerivedMesh *dm = get_dm(ob, NULL, derivedData, NULL, 0); + + laplaciansmoothModifier_do((LaplacianSmoothModifierData *)md, ob, dm, + vertexCos, numVerts); + + if (dm != derivedData) + dm->release(dm); +} + +static void deformVertsEM( + ModifierData *md, Object *ob, struct BMEditMesh *editData, + DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) +{ + DerivedMesh *dm = get_dm(ob, editData, derivedData, NULL, 0); + + laplaciansmoothModifier_do((LaplacianSmoothModifierData *)md, ob, dm, + vertexCos, numVerts); + + if (dm != derivedData) + dm->release(dm); +} + + +ModifierTypeInfo modifierType_LaplacianSmooth = { + /* name */ "Laplacian Smooth", + /* structName */ "LaplacianSmoothModifierData", + /* structSize */ sizeof(LaplacianSmoothModifierData), + /* type */ eModifierTypeType_OnlyDeform, + /* flags */ eModifierTypeFlag_AcceptsMesh | + eModifierTypeFlag_SupportsEditmode, + + /* copy_data */ copy_data, + /* deformVerts */ deformVerts, + /* deformMatrices */ NULL, + /* deformVertsEM */ deformVertsEM, + /* deformMatricesEM */ NULL, + /* applyModifier */ NULL, + /* applyModifierEM */ NULL, + /* initData */ init_data, + /* requiredDataMask */ required_data_mask, + /* freeData */ NULL, + /* isDisabled */ is_disabled, + /* updateDepgraph */ NULL, + /* dependsOnTime */ NULL, + /* dependsOnNormals */ NULL, + /* foreachObjectLink */ NULL, + /* foreachIDLink */ NULL, + /* foreachTexLink */ NULL, +}; diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c index d64ccf750b2..a5c52c6c76a 100644 --- a/source/blender/modifiers/intern/MOD_lattice.c +++ b/source/blender/modifiers/intern/MOD_lattice.c @@ -122,12 +122,12 @@ static void deformVerts(ModifierData *md, Object *ob, } static void deformVertsEM( - ModifierData *md, Object *ob, struct BMEditMesh *editData, + ModifierData *md, Object *ob, struct BMEditMesh *em, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm = derivedData; - if (!derivedData) dm = CDDM_from_BMEditMesh(editData, ob->data, FALSE, FALSE); + if (!derivedData) dm = CDDM_from_editbmesh(em, FALSE, FALSE); deformVerts(md, ob, dm, vertexCos, numVerts, 0); diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c index ab7263a1b53..23ce8cdeb21 100644 --- a/source/blender/modifiers/intern/MOD_mask.c +++ b/source/blender/modifiers/intern/MOD_mask.c @@ -179,7 +179,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, } /* verthash gives mapping from original vertex indices to the new indices (including selected matches only) - * key=oldindex, value=newindex + * key = oldindex, value = newindex */ vertHash = BLI_ghash_int_new("mask vert gh"); @@ -226,11 +226,11 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, int defgrp_index = defgroup_name_index(ob, mmd->vgroup); /* get dverts */ - if (defgrp_index >= 0) + if (defgrp_index != -1) dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); /* if no vgroup (i.e. dverts) found, return the initial mesh */ - if ((defgrp_index < 0) || (dvert == NULL)) + if ((defgrp_index == -1) || (dvert == NULL)) return dm; /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index f0bdf1bb737..f4d9b7270e6 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -218,7 +218,7 @@ static void meshdeformModifier_do( } if (!cagedm) { - modifier_setError(md, "%s", TIP_("Can't get mesh from cage object.")); + modifier_setError(md, "Cannot get mesh from cage object"); return; } @@ -246,17 +246,17 @@ static void meshdeformModifier_do( totcagevert = cagedm->getNumVerts(cagedm); if (mmd->totvert != totvert) { - modifier_setError(md, TIP_("Verts changed from %d to %d."), mmd->totvert, totvert); + modifier_setError(md, "Verts changed from %d to %d", mmd->totvert, totvert); cagedm->release(cagedm); return; } else if (mmd->totcagevert != totcagevert) { - modifier_setError(md, TIP_("Cage verts changed from %d to %d."), mmd->totcagevert, totcagevert); + modifier_setError(md, "Cage verts changed from %d to %d", mmd->totcagevert, totcagevert); cagedm->release(cagedm); return; } else if (mmd->bindcagecos == NULL) { - modifier_setError(md, "%s", TIP_("Bind data missing.")); + modifier_setError(md, "Bind data missing"); cagedm->release(cagedm); return; } @@ -431,28 +431,28 @@ void modifier_mdef_compact_influences(ModifierData *md) } ModifierTypeInfo modifierType_MeshDeform = { - /* name */ "MeshDeform", - /* structName */ "MeshDeformModifierData", - /* structSize */ sizeof(MeshDeformModifierData), - /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | - eModifierTypeFlag_SupportsEditmode, + /* name */ "MeshDeform", + /* structName */ "MeshDeformModifierData", + /* structSize */ sizeof(MeshDeformModifierData), + /* type */ eModifierTypeType_OnlyDeform, + /* flags */ eModifierTypeFlag_AcceptsCVs | + eModifierTypeFlag_SupportsEditmode, - /* copyData */ copyData, - /* deformVerts */ deformVerts, - /* deformMatrices */ NULL, - /* deformVertsEM */ deformVertsEM, - /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, - /* applyModifierEM */ NULL, - /* initData */ initData, - /* requiredDataMask */ requiredDataMask, - /* freeData */ freeData, - /* isDisabled */ isDisabled, - /* updateDepgraph */ updateDepgraph, - /* dependsOnTime */ NULL, - /* dependsOnNormals */ NULL, + /* copyData */ copyData, + /* deformVerts */ deformVerts, + /* deformMatrices */ NULL, + /* deformVertsEM */ deformVertsEM, + /* deformMatricesEM */ NULL, + /* applyModifier */ NULL, + /* applyModifierEM */ NULL, + /* initData */ initData, + /* requiredDataMask */ requiredDataMask, + /* freeData */ freeData, + /* isDisabled */ isDisabled, + /* updateDepgraph */ updateDepgraph, + /* dependsOnTime */ NULL, + /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, - /* foreachTexLink */ NULL, + /* foreachIDLink */ NULL, + /* foreachTexLink */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c index febc4190fdf..83c678db7b3 100644 --- a/source/blender/modifiers/intern/MOD_mirror.c +++ b/source/blender/modifiers/intern/MOD_mirror.c @@ -43,7 +43,8 @@ #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_deform.h" -#include "BKE_tessmesh.h" + +#include "bmesh.h" #include "MEM_guardedalloc.h" #include "depsgraph_private.h" diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c index afc85a8144e..4292246d8cc 100644 --- a/source/blender/modifiers/intern/MOD_multires.c +++ b/source/blender/modifiers/intern/MOD_multires.c @@ -80,6 +80,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, Mesh *me = (Mesh *)ob->data; const int useRenderParams = flag & MOD_APPLY_RENDER; MultiresFlags flags = 0; + int has_mask = CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK); if (mmd->totlvl) { if (!CustomData_get_layer(&me->ldata, CD_MDISPS)) { @@ -88,7 +89,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, } } - flags = MULTIRES_ALLOC_PAINT_MASK; + if (has_mask) + flags |= MULTIRES_ALLOC_PAINT_MASK; + if (useRenderParams) flags |= MULTIRES_USE_RENDER_PARAMS; diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index 3bf8b9ffacc..564fa696c2a 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -33,17 +33,17 @@ #include "DNA_modifier_types.h" #include "DNA_scene_types.h" -#include "BKE_cdderivedmesh.h" -#include "BKE_global.h" -#include "BKE_modifier.h" -#include "BKE_ocean.h" - #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_math_inline.h" #include "BLI_utildefines.h" #include "BLI_string.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_global.h" +#include "BKE_modifier.h" +#include "BKE_ocean.h" + #include "MOD_util.h" #ifdef WITH_OCEANSIM @@ -241,13 +241,13 @@ static void dm_get_bounds(DerivedMesh *dm, float *sx, float *sy, float *ox, floa copy_v3_v3(max, mvert->co); for (v = 1; v < totvert; v++, mvert++) { - min[0] = minf(min[0], mvert->co[0]); - min[1] = minf(min[1], mvert->co[1]); - min[2] = minf(min[2], mvert->co[2]); + min[0] = min_ff(min[0], mvert->co[0]); + min[1] = min_ff(min[1], mvert->co[1]); + min[2] = min_ff(min[2], mvert->co[2]); - max[0] = maxf(max[0], mvert->co[0]); - max[1] = maxf(max[1], mvert->co[1]); - max[2] = maxf(max[2], mvert->co[2]); + max[0] = max_ff(max[0], mvert->co[0]); + max[1] = max_ff(max[1], mvert->co[1]); + max[2] = max_ff(max[2], mvert->co[2]); } sub_v3_v3v3(delta, max, min); diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index e64e80efde3..4984682455a 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -81,6 +81,44 @@ static int dependsOnTime(ModifierData *UNUSED(md)) { return 0; } + +static int isDisabled(ModifierData *md, int useRenderParams) +{ + ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md; + ParticleSystem *psys; + ModifierData *ob_md; + + if (!pimd->ob) + return TRUE; + + psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1); + if (psys == NULL) + return TRUE; + + /* If the psys modifier is disabled we cannot use its data. + * First look up the psys modifier from the object, then check if it is enabled. + */ + for (ob_md = pimd->ob->modifiers.first; ob_md; ob_md = ob_md->next) { + if (ob_md->type == eModifierType_ParticleSystem) { + ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)ob_md; + if (psmd->psys == psys) { + int required_mode; + + if (useRenderParams) required_mode = eModifierMode_Render; + else required_mode = eModifierMode_Realtime; + + if (!modifier_isEnabled(md->scene, ob_md, required_mode)) + return TRUE; + + break; + } + } + } + + return FALSE; +} + + static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene), Object *UNUSED(ob), @@ -363,32 +401,31 @@ static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob, return applyModifier(md, ob, derivedData, MOD_APPLY_USECACHE); } - ModifierTypeInfo modifierType_ParticleInstance = { - /* name */ "ParticleInstance", - /* structName */ "ParticleInstanceModifierData", - /* structSize */ sizeof(ParticleInstanceModifierData), - /* type */ eModifierTypeType_Constructive, - /* flags */ eModifierTypeFlag_AcceptsMesh | - eModifierTypeFlag_SupportsMapping | - eModifierTypeFlag_SupportsEditmode | - eModifierTypeFlag_EnableInEditmode, + /* name */ "ParticleInstance", + /* structName */ "ParticleInstanceModifierData", + /* structSize */ sizeof(ParticleInstanceModifierData), + /* type */ eModifierTypeType_Constructive, + /* flags */ eModifierTypeFlag_AcceptsMesh | + eModifierTypeFlag_SupportsMapping | + eModifierTypeFlag_SupportsEditmode | + eModifierTypeFlag_EnableInEditmode, - /* copyData */ copyData, - /* deformVerts */ NULL, - /* deformMatrices */ NULL, - /* deformVertsEM */ NULL, - /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, - /* applyModifierEM */ applyModifierEM, - /* initData */ initData, - /* requiredDataMask */ NULL, - /* freeData */ NULL, - /* isDisabled */ NULL, - /* updateDepgraph */ updateDepgraph, - /* dependsOnTime */ dependsOnTime, - /* dependsOnNormals */ NULL, + /* copyData */ copyData, + /* deformVerts */ NULL, + /* deformMatrices */ NULL, + /* deformVertsEM */ NULL, + /* deformMatricesEM */ NULL, + /* applyModifier */ applyModifier, + /* applyModifierEM */ applyModifierEM, + /* initData */ initData, + /* requiredDataMask */ NULL, + /* freeData */ NULL, + /* isDisabled */ isDisabled, + /* updateDepgraph */ updateDepgraph, + /* dependsOnTime */ dependsOnTime, + /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, - /* foreachTexLink */ NULL, + /* foreachIDLink */ NULL, + /* foreachTexLink */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index 254c02b7672..cd2ef5957cd 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -44,6 +44,7 @@ #include "BKE_material.h" #include "BKE_modifier.h" #include "BKE_particle.h" +#include "BKE_scene.h" #include "MOD_util.h" @@ -130,6 +131,7 @@ static void deformVerts(ModifierData *md, Object *ob, ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md; ParticleSystem *psys = NULL; int needsFree = 0; + /* float cfra = BKE_scene_frame_get(md->scene); */ /* UNUSED */ if (ob->particlesystem.first) psys = psmd->psys; @@ -188,9 +190,11 @@ static void deformVerts(ModifierData *md, Object *ob, psmd->totdmface = psmd->dm->getNumTessFaces(psmd->dm); } - psmd->flag &= ~eParticleSystemFlag_psys_updated; - particle_system_update(md->scene, ob, psys); - psmd->flag |= eParticleSystemFlag_psys_updated; + if (!(ob->transflag & OB_NO_PSYS_UPDATE)) { + psmd->flag &= ~eParticleSystemFlag_psys_updated; + particle_system_update(md->scene, ob, psys); + psmd->flag |= eParticleSystemFlag_psys_updated; + } } /* disabled particles in editmode for now, until support for proper derivedmesh diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c index 2b55471be3d..746cad10a01 100644 --- a/source/blender/modifiers/intern/MOD_remesh.c +++ b/source/blender/modifiers/intern/MOD_remesh.c @@ -223,7 +223,7 @@ ModifierTypeInfo modifierType_Remesh = { /* structSize */ sizeof(RemeshModifierData), /* type */ eModifierTypeType_Nonconstructive, /* flags */ eModifierTypeFlag_AcceptsMesh | - eModifierTypeFlag_AcceptsCVs | + eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode, /* copyData */ copyData, /* deformVerts */ NULL, diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index 4fd2c658380..93b5e36e5a4 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -215,7 +215,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, if (totlen != 0.0f) { float zero[3] = {0.0f, 0.0f, 0.0f}; - float cp[3]; + float cp[3]; screw_ofs = closest_to_line_v3(cp, mtx_tx[3], zero, axis_vec); } else { @@ -363,7 +363,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, */ vert_connect = MEM_mallocN(sizeof(ScrewVertConnect) * totvert, "ScrewVertConnect"); - //vert_connect= (ScrewVertConnect *) &medge_new[totvert]; /* skip the first slice of verts */ + //vert_connect = (ScrewVertConnect *) &medge_new[totvert]; /* skip the first slice of verts */ vc = vert_connect; /* Copy Vert Locations */ @@ -393,7 +393,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, mul_m4_v3(mtx_tx, vc->co); /* length in 2d, don't sqrt because this is only for comparison */ - vc->dist = vc->co[other_axis_1] * vc->co[other_axis_1] + + vc->dist = vc->co[other_axis_1] * vc->co[other_axis_1] + vc->co[other_axis_2] * vc->co[other_axis_2]; /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/ @@ -410,7 +410,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, vc->v[0] = vc->v[1] = -1; /* length in 2d, don't sqrt because this is only for comparison */ - vc->dist = vc->co[other_axis_1] * vc->co[other_axis_1] + + vc->dist = vc->co[other_axis_1] * vc->co[other_axis_1] + vc->co[other_axis_2] * vc->co[other_axis_2]; /* printf("location %f %f %f -- %f\n", vc->co[0], vc->co[1], vc->co[2], vc->dist);*/ @@ -430,7 +430,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, vc->e[1] = med_new; } else { - vc->v[0] = vc->v[1] = -2; /* erro value - don't use, 3 edges on vert */ + vc->v[0] = vc->v[1] = -2; /* error value - don't use, 3 edges on vert */ } vc = &vert_connect[med_new->v2]; @@ -445,7 +445,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, vc->e[1] = med_new; } else { - vc->v[0] = vc->v[1] = -2; /* erro value - don't use, 3 edges on vert */ + vc->v[0] = vc->v[1] = -2; /* error value - don't use, 3 edges on vert */ } } @@ -475,7 +475,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, /*printf("\t\tVERT: %i\n", lt_iter.v);*/ if (lt_iter.v_poin->flag) { /*printf("\t\t\tBreaking Found end\n");*/ - //endpoints[0]= endpoints[1]= -1; + //endpoints[0] = endpoints[1] = -1; ed_loop_closed = 1; /* circle */ break; } @@ -490,7 +490,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, screwvert_iter_step(<_iter); if (!lt_iter.v_poin) { /*printf("\t\t\tFound End Also Num %i\n", j);*/ - /*endpoints[j]= lt_iter.v_other;*/ /* other is still valid */ + /*endpoints[j] = lt_iter.v_other;*/ /* other is still valid */ break; } } @@ -732,7 +732,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, copy_v3_v3(mv_new->co, mv_new_base->co); /* only need to set these if using non cleared memory */ - /*mv_new->mat_nr= mv_new->flag= 0;*/ + /*mv_new->mat_nr = mv_new->flag = 0;*/ if (ltmd->ob_axis) { sub_v3_v3(mv_new->co, mtx_tx[3]); @@ -831,7 +831,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, } /* close the loop*/ - if (close) { + if (close) { if (do_flip) { ml_new[3].v = i1; ml_new[2].v = i2; diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c index 3353382fa3d..7fe8dc69790 100644 --- a/source/blender/modifiers/intern/MOD_shapekey.c +++ b/source/blender/modifiers/intern/MOD_shapekey.c @@ -54,7 +54,7 @@ static void deformVerts(ModifierData *md, Object *ob, int numVerts, ModifierApplyFlag UNUSED(flag)) { - KeyBlock *kb = ob_get_keyblock(ob); + KeyBlock *kb = BKE_keyblock_from_object(ob); float (*deformedVerts)[3]; if (kb && kb->totelem == numVerts) { @@ -69,8 +69,8 @@ static void deformVerts(ModifierData *md, Object *ob, static void deformMatrices(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], float (*defMats)[3][3], int numVerts) { - Key *key = ob_get_key(ob); - KeyBlock *kb = ob_get_keyblock(ob); + Key *key = BKE_key_from_object(ob); + KeyBlock *kb = BKE_keyblock_from_object(ob); float scale[3][3]; (void)vertexCos; /* unused */ @@ -94,7 +94,7 @@ static void deformVertsEM(ModifierData *md, Object *ob, float (*vertexCos)[3], int numVerts) { - Key *key = ob_get_key(ob); + Key *key = BKE_key_from_object(ob); if (key && key->type == KEY_RELATIVE) deformVerts(md, ob, derivedData, vertexCos, numVerts, 0); @@ -107,8 +107,8 @@ static void deformMatricesEM(ModifierData *UNUSED(md), Object *ob, float (*defMats)[3][3], int numVerts) { - Key *key = ob_get_key(ob); - KeyBlock *kb = ob_get_keyblock(ob); + Key *key = BKE_key_from_object(ob); + KeyBlock *kb = BKE_keyblock_from_object(ob); float scale[3][3]; (void)vertexCos; /* unused */ @@ -122,6 +122,7 @@ static void deformMatricesEM(ModifierData *UNUSED(md), Object *ob, } } + ModifierTypeInfo modifierType_ShapeKey = { /* name */ "ShapeKey", /* structName */ "ShapeKeyModifierData", diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c index 45cd33efea8..d3a03614d7c 100644 --- a/source/blender/modifiers/intern/MOD_shrinkwrap.c +++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c @@ -163,30 +163,30 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, ModifierTypeInfo modifierType_Shrinkwrap = { - /* name */ "Shrinkwrap", - /* structName */ "ShrinkwrapModifierData", - /* structSize */ sizeof(ShrinkwrapModifierData), - /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsMesh | - eModifierTypeFlag_AcceptsCVs | - eModifierTypeFlag_SupportsEditmode | - eModifierTypeFlag_EnableInEditmode, + /* name */ "Shrinkwrap", + /* structName */ "ShrinkwrapModifierData", + /* structSize */ sizeof(ShrinkwrapModifierData), + /* type */ eModifierTypeType_OnlyDeform, + /* flags */ eModifierTypeFlag_AcceptsMesh | + eModifierTypeFlag_AcceptsCVs | + eModifierTypeFlag_SupportsEditmode | + eModifierTypeFlag_EnableInEditmode, - /* copyData */ copyData, - /* deformVerts */ deformVerts, - /* deformMatrices */ NULL, - /* deformVertsEM */ deformVertsEM, - /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, - /* applyModifierEM */ NULL, - /* initData */ initData, - /* requiredDataMask */ requiredDataMask, - /* freeData */ NULL, - /* isDisabled */ isDisabled, - /* updateDepgraph */ updateDepgraph, - /* dependsOnTime */ NULL, - /* dependsOnNormals */ NULL, + /* copyData */ copyData, + /* deformVerts */ deformVerts, + /* deformMatrices */ NULL, + /* deformVertsEM */ deformVertsEM, + /* deformMatricesEM */ NULL, + /* applyModifier */ NULL, + /* applyModifierEM */ NULL, + /* initData */ initData, + /* requiredDataMask */ requiredDataMask, + /* freeData */ NULL, + /* isDisabled */ isDisabled, + /* updateDepgraph */ updateDepgraph, + /* dependsOnTime */ NULL, + /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, - /* foreachTexLink */ NULL, + /* foreachIDLink */ NULL, + /* foreachTexLink */ NULL, }; diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c index bf5f6cd095e..5267c0d9ccb 100644 --- a/source/blender/modifiers/intern/MOD_simpledeform.c +++ b/source/blender/modifiers/intern/MOD_simpledeform.c @@ -72,7 +72,7 @@ static void simpleDeform_taper(const float factor, const float dcut[3], float r_ r_co[1] = y + y * scale; r_co[2] = z; - if (dcut) { + { r_co[0] += dcut[0]; r_co[1] += dcut[1]; r_co[2] += dcut[2]; @@ -90,7 +90,7 @@ static void simpleDeform_stretch(const float factor, const float dcut[3], float r_co[1] = y * scale; r_co[2] = z * (1.0f + factor); - if (dcut) { + { r_co[0] += dcut[0]; r_co[1] += dcut[1]; r_co[2] += dcut[2]; @@ -110,7 +110,7 @@ static void simpleDeform_twist(const float factor, const float *dcut, float r_co r_co[1] = x * sint + y * cost; r_co[2] = z; - if (dcut) { + { r_co[0] += dcut[0]; r_co[1] += dcut[1]; r_co[2] += dcut[2]; @@ -132,7 +132,7 @@ static void simpleDeform_bend(const float factor, const float dcut[3], float r_c r_co[2] = z; } - if (dcut) { + { r_co[0] += cost * dcut[0]; r_co[1] += sint * dcut[0]; r_co[2] += dcut[2]; @@ -161,9 +161,9 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object if (smd->limit[0] < 0.0f) smd->limit[0] = 0.0f; if (smd->limit[0] > 1.0f) smd->limit[0] = 1.0f; - smd->limit[0] = minf(smd->limit[0], smd->limit[1]); /* Upper limit >= than lower limit */ + smd->limit[0] = min_ff(smd->limit[0], smd->limit[1]); /* Upper limit >= than lower limit */ - //Calculate matrixs do convert between coordinate spaces + /* Calculate matrixs do convert between coordinate spaces */ if (smd->origin) { transf = &tmp_transf; @@ -176,10 +176,11 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object } } - //Setup vars - limit_axis = (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) ? 0 : 2; //Bend limits on X.. all other modes limit on Z + /* Setup vars, + * Bend limits on X.. all other modes limit on Z */ + limit_axis = (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) ? 0 : 2; - //Update limits if needed + /* Update limits if needed */ { float lower = FLT_MAX; float upper = -FLT_MAX; @@ -190,8 +191,8 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object if (transf) space_transform_apply(transf, tmp); - lower = minf(lower, tmp[limit_axis]); - upper = maxf(upper, tmp[limit_axis]); + lower = min_ff(lower, tmp[limit_axis]); + upper = max_ff(upper, tmp[limit_axis]); } @@ -199,7 +200,7 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object smd_limit[1] = lower + (upper - lower) * smd->limit[1]; smd_limit[0] = lower + (upper - lower) * smd->limit[0]; - smd_factor = smd->factor / MAX2(FLT_EPSILON, smd_limit[1] - smd_limit[0]); + smd_factor = smd->factor / max_ff(FLT_EPSILON, smd_limit[1] - smd_limit[0]); } modifier_get_vgroup(ob, dm, smd->vgroup_name, &dvert, &vgroup); @@ -235,7 +236,9 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object simpleDeform_callback(smd_factor, dcut, co); /* apply deform */ interp_v3_v3v3(vertexCos[i], vertexCos[i], co, weight); /* Use vertex weight has coef of linear interpolation */ - if (transf) space_transform_invert(transf, vertexCos[i]); + if (transf) { + space_transform_invert(transf, vertexCos[i]); + } } } } @@ -249,6 +252,7 @@ static void initData(ModifierData *md) SimpleDeformModifierData *smd = (SimpleDeformModifierData *) md; smd->mode = MOD_SIMPLEDEFORM_MODE_TWIST; + smd->originOpts = MOD_SIMPLEDEFORM_ORIGIN_LOCAL; smd->axis = 0; smd->origin = NULL; @@ -349,9 +353,9 @@ ModifierTypeInfo modifierType_SimpleDeform = { /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | - eModifierTypeFlag_AcceptsCVs | - eModifierTypeFlag_SupportsEditmode | - eModifierTypeFlag_EnableInEditmode, + eModifierTypeFlag_AcceptsCVs | + eModifierTypeFlag_SupportsEditmode | + eModifierTypeFlag_EnableInEditmode, /* copyData */ copyData, /* deformVerts */ deformVerts, diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 222f13185ea..8a4d70da6e8 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -77,7 +77,8 @@ #include "BKE_DerivedMesh.h" #include "BKE_mesh.h" #include "BKE_modifier.h" -#include "BKE_tessmesh.h" + +#include "bmesh.h" #include "MOD_util.h" @@ -143,6 +144,7 @@ static int is_quad_symmetric(BMVert *quad[4], const SkinModifierData *smd) { const float threshold = 0.0001f; + const float threshold_squared = threshold * threshold; int axis; for (axis = 0; axis < 3; axis++) { @@ -152,16 +154,16 @@ static int is_quad_symmetric(BMVert *quad[4], copy_v3_v3(a, quad[0]->co); a[axis] = -a[axis]; - if (len_v3v3(a, quad[1]->co) < threshold) { + if (len_squared_v3v3(a, quad[1]->co) < threshold_squared) { copy_v3_v3(a, quad[2]->co); a[axis] = -a[axis]; - if (len_v3v3(a, quad[3]->co) < threshold) + if (len_squared_v3v3(a, quad[3]->co) < threshold_squared) return 1; } - else if (len_v3v3(a, quad[3]->co) < threshold) { + else if (len_squared_v3v3(a, quad[3]->co) < threshold_squared) { copy_v3_v3(a, quad[2]->co); a[axis] = -a[axis]; - if (len_v3v3(a, quad[1]->co) < threshold) + if (len_squared_v3v3(a, quad[1]->co) < threshold_squared) return 1; } } @@ -178,13 +180,13 @@ static int quad_crosses_symmetry_plane(BMVert *quad[4], for (axis = 0; axis < 3; axis++) { if (smd->symmetry_axes & (1 << axis)) { - int i, left = 0, right = 0; + int i, left = FALSE, right = FALSE; for (i = 0; i < 4; i++) { - if (quad[i]->co[axis] < 0) - left = 1; - else if (quad[i]->co[axis] > 0) - right = 1; + if (quad[i]->co[axis] < 0.0f) + left = TRUE; + else if (quad[i]->co[axis] > 0.0f) + right = TRUE; if (left && right) return TRUE; @@ -355,7 +357,7 @@ static void merge_frame_corners(Frame **frames, int totframe) BLI_assert(frames[i] != frames[k]); side_b = frame_len(frames[k]); - thresh = minf(side_a, side_b) / 2.0f; + thresh = min_ff(side_a, side_b) / 2.0f; /* Compare with each corner of all other frames... */ for (l = 0; l < 4; l++) { @@ -695,11 +697,11 @@ static void build_emats_stack(BLI_Stack *stack, int *visited_e, EMat *emat, } static EMat *build_edge_mats(const MVertSkin *vs, - const MVert *mvert, - int totvert, + const MVert *mvert, + int totvert, const MEdge *medge, - const MeshElemMap *emap, - int totedge) + const MeshElemMap *emap, + int totedge) { BLI_Stack *stack; EMat *emat; @@ -1422,7 +1424,7 @@ static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd) } } - while (!BLI_heap_empty(heap)) { + while (!BLI_heap_is_empty(heap)) { BMFace *adj[2]; e = BLI_heap_popmin(heap); @@ -1544,23 +1546,23 @@ static void skin_output_end_nodes(SkinOutput *so, SkinNode *skin_nodes, if (sn->flag & CAP_START) { if (sn->flag & ROOT) { add_poly(so, - sn->frames[0].verts[0], - sn->frames[0].verts[1], - sn->frames[0].verts[2], - sn->frames[0].verts[3]); + sn->frames[0].verts[0], + sn->frames[0].verts[1], + sn->frames[0].verts[2], + sn->frames[0].verts[3]); } else { add_poly(so, - sn->frames[0].verts[3], - sn->frames[0].verts[2], - sn->frames[0].verts[1], - sn->frames[0].verts[0]); + sn->frames[0].verts[3], + sn->frames[0].verts[2], + sn->frames[0].verts[1], + sn->frames[0].verts[0]); } } if (sn->flag & CAP_END) { add_poly(so, sn->frames[1].verts[0], - sn->frames[1].verts[1], + sn->frames[1].verts[1], sn->frames[1].verts[2], sn->frames[1].verts[3]); } @@ -1770,7 +1772,6 @@ static void skin_set_orig_indices(DerivedMesh *dm) static DerivedMesh *base_skin(DerivedMesh *origdm, SkinModifierData *smd) { - BMEditMesh fake_em; DerivedMesh *result; MVertSkin *nodes; BMesh *bm; @@ -1807,8 +1808,7 @@ static DerivedMesh *base_skin(DerivedMesh *origdm, if (!bm) return NULL; - fake_em.bm = bm; - result = CDDM_from_BMEditMesh(&fake_em, NULL, FALSE, FALSE); + result = CDDM_from_bmesh(bm, FALSE); BM_mesh_free(bm); CDDM_calc_edges(result); @@ -1861,7 +1861,7 @@ static void copyData(ModifierData *md, ModifierData *target) static DerivedMesh *applyModifierEM(ModifierData *md, Object *UNUSED(ob), - BMEditMesh *UNUSED(em), + struct BMEditMesh *UNUSED(em), DerivedMesh *dm) { DerivedMesh *result; diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c index b9b3b89e06d..4b2ce47b8d9 100644 --- a/source/blender/modifiers/intern/MOD_smoke.c +++ b/source/blender/modifiers/intern/MOD_smoke.c @@ -81,19 +81,31 @@ static void freeData(ModifierData *md) smokeModifier_free(smd); } -static void deformVerts(ModifierData *md, Object *ob, - DerivedMesh *derivedData, - float (*vertexCos)[3], - int UNUSED(numVerts), - ModifierApplyFlag UNUSED(flag)) +static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) +{ + SmokeModifierData *smd = (SmokeModifierData *)md; + CustomDataMask dataMask = 0; + + if (smd && (smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) { + if (smd->flow->source == MOD_SMOKE_FLOW_SOURCE_MESH) { + /* vertex groups */ + if (smd->flow->vgroup_density) + dataMask |= CD_MASK_MDEFORMVERT; + /* uv layer */ + if (smd->flow->texture_type == MOD_SMOKE_FLOW_TEXTURE_MAP_UV) + dataMask |= CD_MASK_MTFACE; + } + } + return dataMask; +} + +static DerivedMesh *applyModifier(ModifierData *md, Object *ob, + DerivedMesh *dm, + ModifierApplyFlag UNUSED(flag)) { SmokeModifierData *smd = (SmokeModifierData *) md; - DerivedMesh *dm = get_cddm(ob, NULL, derivedData, vertexCos); - smokeModifier_do(smd, md->scene, ob, dm); - - if (dm != derivedData) - dm->release(dm); + return smokeModifier_do(smd, md->scene, ob, dm); } static int dependsOnTime(ModifierData *UNUSED(md)) @@ -102,11 +114,11 @@ static int dependsOnTime(ModifierData *UNUSED(md)) } static void updateDepgraph(ModifierData *md, DagForest *forest, - struct Scene *scene, - Object *UNUSED(ob), + struct Scene *scene, struct Object *ob, DagNode *obNode) { SmokeModifierData *smd = (SmokeModifierData *) md; + Base *base; if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) { if (smd->domain->fluid_group || smd->domain->coll_group) { @@ -139,8 +151,7 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } else { - Base *base = scene->base.first; - + base = scene->base.first; for (; base; base = base->next) { SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(base->object, eModifierType_Smoke); @@ -150,6 +161,14 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, } } } + /* add relation to all "smoke flow" force fields */ + base = scene->base.first; + for (; base; base = base->next) { + if (base->object->pd && base->object->pd->forcefield == PFIELD_SMOKEFLOW && base->object->pd->f_source == ob) { + DagNode *node2 = dag_get_node(forest, base->object); + dag_add_relation(forest, obNode, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Field Source Object"); + } + } } } @@ -167,26 +186,30 @@ static void foreachIDLink(ModifierData *md, Object *ob, walk(userData, ob, (ID **)&smd->domain->effector_weights->group); } } + + if (smd->type == MOD_SMOKE_TYPE_FLOW && smd->flow) { + walk(userData, ob, (ID **)&smd->flow->noise_texture); + } } ModifierTypeInfo modifierType_Smoke = { /* name */ "Smoke", /* structName */ "SmokeModifierData", /* structSize */ sizeof(SmokeModifierData), - /* type */ eModifierTypeType_OnlyDeform, + /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_UsesPointCache | eModifierTypeFlag_Single, /* copyData */ copyData, - /* deformVerts */ deformVerts, + /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* applyModifier */ applyModifier, /* applyModifierEM */ NULL, /* initData */ initData, - /* requiredDataMask */ NULL, + /* requiredDataMask */ requiredDataMask, /* freeData */ freeData, /* isDisabled */ NULL, /* updateDepgraph */ updateDepgraph, diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c index 545e2135344..1d35d8f55bf 100644 --- a/source/blender/modifiers/intern/MOD_smooth.c +++ b/source/blender/modifiers/intern/MOD_smooth.c @@ -250,7 +250,7 @@ ModifierTypeInfo modifierType_Smooth = { /* structSize */ sizeof(SmoothModifierData), /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | - eModifierTypeFlag_AcceptsCVs | + eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode, /* copyData */ copyData, diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index fc74b446762..cc77d73a736 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -107,7 +107,7 @@ static void dm_calc_normal(DerivedMesh *dm, float (*temp_nors)[3]) f_no = face_nors[i]; if (calc_face_nors) - mesh_calc_poly_normal(mp, mloop + mp->loopstart, mvert, f_no); + BKE_mesh_calc_poly_normal(mp, mloop + mp->loopstart, mvert, f_no); ml = mloop + mp->loopstart; @@ -223,7 +223,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, const int numEdges = dm->getNumEdges(dm); const int numFaces = dm->getNumPolys(dm); int numLoops = 0, newLoops = 0, newFaces = 0, newEdges = 0; - int j; /* only use material offsets if we have 2 or more materials */ const short mat_nr_max = ob->totcol > 1 ? ob->totcol - 1 : 0; @@ -292,9 +291,11 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, } for (i = 0, mp = orig_mpoly; i < numFaces; i++, mp++) { - MLoop *ml = orig_mloop + mp->loopstart; unsigned int ml_v1; unsigned int ml_v2; + int j; + + ml = orig_mloop + mp->loopstart; for (j = 0, ml_v1 = ml->v, ml_v2 = ml[mp->totloop - 1].v; j < mp->totloop; @@ -376,6 +377,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, for (i = 0; i < dm->numPolyData; i++, mp++) { MLoop *ml2; int e; + int j; ml2 = mloop + mp->loopstart + dm->numLoopData; for (j = 0; j < mp->totloop; j++) { @@ -483,7 +485,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, /* --- not related to angle calc --- */ if (face_nors_calc) - mesh_calc_poly_normal(mp, ml, mvert, face_nors[i]); + BKE_mesh_calc_poly_normal(mp, ml, mvert, face_nors[i]); /* --- end non-angle-calc section --- */ sub_v3_v3v3(nor_prev, mvert[ml[i_this - 1].v].co, mvert[ml[i_this].v].co); @@ -591,6 +593,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, int *origindex_edge; int *orig_ed; + int j; /* add faces & edges */ origindex_edge = result->getEdgeDataArray(result, CD_ORIGINDEX); @@ -635,15 +638,15 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, /* notice we use 'mp->totloop' which is later overwritten, * we could lookup the original face but theres no point since this is a copy * and will have the same value, just take care when changing order of assignment */ - k1 = mpoly[fidx].loopstart + ((edge_order[eidx] + 1) % mp->totloop); + k1 = mpoly[fidx].loopstart + (((edge_order[eidx] - 1) + mp->totloop) % mp->totloop); /* prev loop */ k2 = mpoly[fidx].loopstart + (edge_order[eidx]); mp->totloop = 4; - CustomData_copy_data(&dm->loopData, &result->loopData, k1, numLoops * 2 + j + 0, 1); - CustomData_copy_data(&dm->loopData, &result->loopData, k2, numLoops * 2 + j + 1, 1); - CustomData_copy_data(&dm->loopData, &result->loopData, k2, numLoops * 2 + j + 2, 1); - CustomData_copy_data(&dm->loopData, &result->loopData, k1, numLoops * 2 + j + 3, 1); + CustomData_copy_data(&dm->loopData, &result->loopData, k2, numLoops * 2 + j + 0, 1); + CustomData_copy_data(&dm->loopData, &result->loopData, k1, numLoops * 2 + j + 1, 1); + CustomData_copy_data(&dm->loopData, &result->loopData, k1, numLoops * 2 + j + 2, 1); + CustomData_copy_data(&dm->loopData, &result->loopData, k2, numLoops * 2 + j + 3, 1); if (flip == FALSE) { ml[j].v = ed->v1; @@ -715,13 +718,13 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, for (i = 0; i < newEdges; i++, ed++) { float nor_cpy[3]; short *nor_short; - int j; + int k; /* note, only the first vertex (lower half of the index) is calculated */ normalize_v3_v3(nor_cpy, edge_vert_nos[ed->v1]); - for (j = 0; j < 2; j++) { /* loop over both verts of the edge */ - nor_short = mvert[*(&ed->v1 + j)].no; + for (k = 0; k < 2; k++) { /* loop over both verts of the edge */ + nor_short = mvert[*(&ed->v1 + k)].no; normal_short_to_float_v3(nor, nor_short); add_v3_v3(nor, nor_cpy); normalize_v3(nor); diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index 1dbbe14e643..3b769a30994 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -199,7 +199,7 @@ DerivedMesh *get_dm(Object *ob, struct BMEditMesh *em, DerivedMesh *dm, float (* return dm; if (ob->type == OB_MESH) { - if (em) dm = CDDM_from_BMEditMesh(em, ob->data, FALSE, FALSE); + if (em) dm = CDDM_from_editbmesh(em, FALSE, FALSE); else dm = CDDM_from_mesh((struct Mesh *)(ob->data), ob); if (vertexCos) { @@ -222,7 +222,7 @@ void modifier_get_vgroup(Object *ob, DerivedMesh *dm, const char *name, MDeformV *defgrp_index = defgroup_name_index(ob, name); *dvert = NULL; - if (*defgrp_index >= 0) { + if (*defgrp_index != -1) { if (ob->type == OB_LATTICE) *dvert = BKE_lattice_deform_verts_get(ob); else if (dm) @@ -277,5 +277,6 @@ void modifier_type_init(ModifierTypeInfo *types[]) INIT_TYPE(DynamicPaint); INIT_TYPE(Remesh); INIT_TYPE(Skin); + INIT_TYPE(LaplacianSmooth); #undef INIT_TYPE } diff --git a/source/blender/modifiers/intern/MOD_util.h b/source/blender/modifiers/intern/MOD_util.h index eadf7af553b..6f05c9a957a 100644 --- a/source/blender/modifiers/intern/MOD_util.h +++ b/source/blender/modifiers/intern/MOD_util.h @@ -42,10 +42,14 @@ struct TexResult; void modifier_init_texture(struct Scene *scene, struct Tex *texture); void get_texture_value(struct Tex *texture, float *tex_co, struct TexResult *texres); -void get_texture_coords(struct MappingInfoModifierData *dmd, struct Object *ob, struct DerivedMesh *dm, float (*co)[3], float (*texco)[3], int numVerts); +void get_texture_coords(struct MappingInfoModifierData *dmd, struct Object *ob, struct DerivedMesh *dm, + float (*co)[3], float (*texco)[3], int numVerts); void modifier_vgroup_cache(struct ModifierData *md, float (*vertexCos)[3]); -struct DerivedMesh *get_cddm(struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm, float (*vertexCos)[3]); -struct DerivedMesh *get_dm(struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm, float (*vertexCos)[3], int orco); -void modifier_get_vgroup(struct Object *ob, struct DerivedMesh *dm, const char *name, struct MDeformVert **dvert, int *defgrp_index); +struct DerivedMesh *get_cddm(struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm, + float (*vertexCos)[3]); +struct DerivedMesh *get_dm(struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm, + float (*vertexCos)[3], int orco); +void modifier_get_vgroup(struct Object *ob, struct DerivedMesh *dm, + const char *name, struct MDeformVert **dvert, int *defgrp_index); #endif /* __MOD_UTIL_H__ */ diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index eb5a74f0dcc..88951919272 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -157,7 +157,6 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, int override_image = ((umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0); Projector projectors[MOD_UVPROJECT_MAXPROJECTORS]; int num_projectors = 0; - float aspect; char uvname[MAX_CUSTOMDATA_LAYER_NAME]; float aspx = umd->aspectx ? umd->aspectx : 1.0f; float aspy = umd->aspecty ? umd->aspecty : 1.0f; @@ -165,8 +164,6 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, float scay = umd->scaley ? umd->scaley : 1.0f; int free_uci = 0; - aspect = aspx / aspy; - for (i = 0; i < umd->num_projectors; ++i) if (umd->projectors[i]) projectors[num_projectors++].ob = umd->projectors[i]; @@ -199,39 +196,23 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, free_uci = 1; } else { - float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y); - int sensor_fit = BKE_camera_sensor_fit(cam->sensor_fit, aspx, aspy); - float scale = (cam->type == CAM_PERSP) ? cam->clipsta * sensor / cam->lens : cam->ortho_scale; - float xmax, xmin, ymax, ymin; + CameraParams params; - if (sensor_fit == CAMERA_SENSOR_FIT_HOR) { - xmax = 0.5f * scale; - ymax = xmax / aspect; - } - else { - ymax = 0.5f * scale; - xmax = ymax * aspect; - } + /* setup parameters */ + BKE_camera_params_init(¶ms); + BKE_camera_params_from_object(¶ms, projectors[i].ob); - xmin = -xmax; - ymin = -ymax; + /* compute matrix, viewplane, .. */ + BKE_camera_params_compute_viewplane(¶ms, 1, 1, aspx, aspy); - /* scale the matrix */ - xmin *= scax; - xmax *= scax; - ymin *= scay; - ymax *= scay; + /* scale the view-plane */ + params.viewplane.xmin *= scax; + params.viewplane.xmax *= scax; + params.viewplane.ymin *= scay; + params.viewplane.ymax *= scay; - if (cam->type == CAM_PERSP) { - float perspmat[4][4]; - perspective_m4(perspmat, xmin, xmax, ymin, ymax, cam->clipsta, cam->clipend); - mult_m4_m4m4(tmpmat, perspmat, projectors[i].projmat); - } - else { /* if (cam->type == CAM_ORTHO) */ - float orthomat[4][4]; - orthographic_m4(orthomat, xmin, xmax, ymin, ymax, cam->clipsta, cam->clipend); - mult_m4_m4m4(tmpmat, orthomat, projectors[i].projmat); - } + BKE_camera_params_compute_matrix(¶ms); + mult_m4_m4m4(tmpmat, params.winmat, projectors[i].projmat); } } else { @@ -241,22 +222,7 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, unit_m4(offsetmat); mul_mat3_m4_fl(offsetmat, 0.5); offsetmat[3][0] = offsetmat[3][1] = offsetmat[3][2] = 0.5; - - if (cam) { - if (aspx == aspy) { - offsetmat[3][0] -= cam->shiftx; - offsetmat[3][1] -= cam->shifty; - } - else if (aspx < aspy) { - offsetmat[3][0] -= (cam->shiftx * aspy / aspx); - offsetmat[3][1] -= cam->shifty; - } - else { - offsetmat[3][0] -= cam->shiftx; - offsetmat[3][1] -= (cam->shifty * aspx / aspy); - } - } - + mult_m4_m4m4(projectors[i].projmat, offsetmat, tmpmat); /* calculate worldspace projector normal (for best projector test) */ diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c index 95f6ef60665..c2a62231529 100644 --- a/source/blender/modifiers/intern/MOD_warp.c +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -238,7 +238,7 @@ static void warpModifier_do(WarpModifierData *wmd, Object *ob, (fac = (wmd->falloff_radius - fac) / wmd->falloff_radius))) { /* skip if no vert group found */ - if (dvert && defgrp_index >= 0) { + if (dvert && defgrp_index != -1) { dv = &dvert[i]; if (dv) { @@ -337,7 +337,7 @@ static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, } } -static void deformVertsEM(ModifierData *md, Object *ob, struct BMEditMesh *editData, +static void deformVertsEM(ModifierData *md, Object *ob, struct BMEditMesh *em, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm = derivedData; @@ -345,7 +345,7 @@ static void deformVertsEM(ModifierData *md, Object *ob, struct BMEditMesh *editD if (use_dm) { if (!derivedData) - dm = CDDM_from_BMEditMesh(editData, ob->data, FALSE, FALSE); + dm = CDDM_from_editbmesh(em, FALSE, FALSE); } deformVerts(md, ob, dm, vertexCos, numVerts, 0); @@ -357,27 +357,27 @@ static void deformVertsEM(ModifierData *md, Object *ob, struct BMEditMesh *editD ModifierTypeInfo modifierType_Warp = { - /* name */ "Warp", - /* structName */ "WarpModifierData", - /* structSize */ sizeof(WarpModifierData), - /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | - eModifierTypeFlag_SupportsEditmode, - /* copyData */ copyData, - /* deformVerts */ deformVerts, - /* deformMatrices */ NULL, - /* deformVertsEM */ deformVertsEM, - /* deformMatricesEM */ NULL, - /* applyModifier */ 0, - /* applyModifierEM */ 0, - /* initData */ initData, - /* requiredDataMask */ requiredDataMask, - /* freeData */ freeData, - /* isDisabled */ isDisabled, - /* updateDepgraph */ updateDepgraph, - /* dependsOnTime */ dependsOnTime, - /* dependsOnNormals */ NULL, + /* name */ "Warp", + /* structName */ "WarpModifierData", + /* structSize */ sizeof(WarpModifierData), + /* type */ eModifierTypeType_OnlyDeform, + /* flags */ eModifierTypeFlag_AcceptsCVs | + eModifierTypeFlag_SupportsEditmode, + /* copyData */ copyData, + /* deformVerts */ deformVerts, + /* deformMatrices */ NULL, + /* deformVertsEM */ deformVertsEM, + /* deformMatricesEM */ NULL, + /* applyModifier */ 0, + /* applyModifierEM */ 0, + /* initData */ initData, + /* requiredDataMask */ requiredDataMask, + /* freeData */ freeData, + /* isDisabled */ isDisabled, + /* updateDepgraph */ updateDepgraph, + /* dependsOnTime */ dependsOnTime, + /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ foreachIDLink, - /* foreachTexLink */ foreachTexLink, + /* foreachIDLink */ foreachIDLink, + /* foreachTexLink */ foreachTexLink, }; diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c index 440d2c157fe..b713f56a4c2 100644 --- a/source/blender/modifiers/intern/MOD_wave.c +++ b/source/blender/modifiers/intern/MOD_wave.c @@ -186,7 +186,7 @@ static void waveModifier_do(WaveModifierData *md, const float falloff = wmd->falloff; float falloff_fac = 1.0f; /* when falloff == 0.0f this stays at 1.0f */ - if (wmd->flag & MOD_WAVE_NORM && ob->type == OB_MESH) + if ((wmd->flag & MOD_WAVE_NORM) && (ob->type == OB_MESH)) mvert = dm->getVertArray(dm); if (wmd->objectcenter) { diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index ce6295e30cf..779ac6b5ecf 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -185,7 +185,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der float *org_w; /* Array original weights. */ float *new_w; /* Array new weights. */ int numVerts; - int defgrp_idx; + int defgrp_index; int i; /* Flags. */ int do_add = (wmd->edit_flags & MOD_WVG_EDIT_ADD2VG) != 0; @@ -205,8 +205,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der return dm; /* Get vgroup idx from its name. */ - defgrp_idx = defgroup_name_index(ob, wmd->defgrp_name); - if (defgrp_idx < 0) + defgrp_index = defgroup_name_index(ob, wmd->defgrp_name); + if (defgrp_index == -1) return dm; dvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MDEFORMVERT, numVerts); @@ -228,7 +228,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der new_w = MEM_mallocN(sizeof(float) * numVerts, "WeightVGEdit Modifier, new_w"); dw = MEM_mallocN(sizeof(MDeformWeight *) * numVerts, "WeightVGEdit Modifier, dw"); for (i = 0; i < numVerts; i++) { - dw[i] = defvert_find_index(&dvert[i], defgrp_idx); + dw[i] = defvert_find_index(&dvert[i], defgrp_index); if (dw[i]) { org_w[i] = new_w[i] = dw[i]->weight; } @@ -249,7 +249,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name); /* Update/add/remove from vgroup. */ - weightvg_update_vg(dvert, defgrp_idx, dw, numVerts, NULL, org_w, do_add, wmd->add_threshold, + weightvg_update_vg(dvert, defgrp_index, dw, numVerts, NULL, org_w, do_add, wmd->add_threshold, do_rem, wmd->rem_threshold); /* If weight preview enabled... */ diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index 2961082b448..5883b176317 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -225,7 +225,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der MDeformVert *dvert = NULL; MDeformWeight **dw1, **tdw1, **dw2, **tdw2; int numVerts; - int defgrp_idx, defgrp_idx2 = -1; + int defgrp_index, defgrp_index_other = -1; float *org_w; float *new_w; int *tidx, *indices = NULL; @@ -246,13 +246,13 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der return dm; /* Get vgroup idx from its name. */ - defgrp_idx = defgroup_name_index(ob, wmd->defgrp_name_a); - if (defgrp_idx < 0) + defgrp_index = defgroup_name_index(ob, wmd->defgrp_name_a); + if (defgrp_index == -1) return dm; /* Get seconf vgroup idx from its name, if given. */ if (wmd->defgrp_name_b[0] != (char)0) { - defgrp_idx2 = defgroup_name_index(ob, wmd->defgrp_name_b); - if (defgrp_idx2 < 0) + defgrp_index_other = defgroup_name_index(ob, wmd->defgrp_name_b); + if (defgrp_index_other == -1) return dm; } @@ -277,10 +277,10 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der case MOD_WVG_SET_A: /* All vertices in first vgroup. */ for (i = 0; i < numVerts; i++) { - MDeformWeight *dw = defvert_find_index(&dvert[i], defgrp_idx); + MDeformWeight *dw = defvert_find_index(&dvert[i], defgrp_index); if (dw) { tdw1[numIdx] = dw; - tdw2[numIdx] = defvert_find_index(&dvert[i], defgrp_idx2); + tdw2[numIdx] = defvert_find_index(&dvert[i], defgrp_index_other); tidx[numIdx++] = i; } } @@ -288,9 +288,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der case MOD_WVG_SET_B: /* All vertices in second vgroup. */ for (i = 0; i < numVerts; i++) { - MDeformWeight *dw = defvert_find_index(&dvert[i], defgrp_idx2); + MDeformWeight *dw = defvert_find_index(&dvert[i], defgrp_index_other); if (dw) { - tdw1[numIdx] = defvert_find_index(&dvert[i], defgrp_idx); + tdw1[numIdx] = defvert_find_index(&dvert[i], defgrp_index); tdw2[numIdx] = dw; tidx[numIdx++] = i; } @@ -299,8 +299,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der case MOD_WVG_SET_OR: /* All vertices in one vgroup or the other. */ for (i = 0; i < numVerts; i++) { - MDeformWeight *adw = defvert_find_index(&dvert[i], defgrp_idx); - MDeformWeight *bdw = defvert_find_index(&dvert[i], defgrp_idx2); + MDeformWeight *adw = defvert_find_index(&dvert[i], defgrp_index); + MDeformWeight *bdw = defvert_find_index(&dvert[i], defgrp_index_other); if (adw || bdw) { tdw1[numIdx] = adw; tdw2[numIdx] = bdw; @@ -311,8 +311,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der case MOD_WVG_SET_AND: /* All vertices in both vgroups. */ for (i = 0; i < numVerts; i++) { - MDeformWeight *adw = defvert_find_index(&dvert[i], defgrp_idx); - MDeformWeight *bdw = defvert_find_index(&dvert[i], defgrp_idx2); + MDeformWeight *adw = defvert_find_index(&dvert[i], defgrp_index); + MDeformWeight *bdw = defvert_find_index(&dvert[i], defgrp_index_other); if (adw && bdw) { tdw1[numIdx] = adw; tdw2[numIdx] = bdw; @@ -324,8 +324,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der default: /* Use all vertices. */ for (i = 0; i < numVerts; i++) { - tdw1[i] = defvert_find_index(&dvert[i], defgrp_idx); - tdw2[i] = defvert_find_index(&dvert[i], defgrp_idx2); + tdw1[i] = defvert_find_index(&dvert[i], defgrp_index); + tdw2[i] = defvert_find_index(&dvert[i], defgrp_index_other); } numIdx = -1; break; @@ -377,7 +377,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der /* Update (add to) vgroup. * XXX Depending on the MOD_WVG_SET_xxx option chosen, we might have to add vertices to vgroup. */ - weightvg_update_vg(dvert, defgrp_idx, dw1, numIdx, indices, org_w, TRUE, -FLT_MAX, FALSE, 0.0f); + weightvg_update_vg(dvert, defgrp_index, dw1, numIdx, indices, org_w, TRUE, -FLT_MAX, FALSE, 0.0f); /* If weight preview enabled... */ #if 0 /* XXX Currently done in mod stack :/ */ diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 25a2a61d8e3..e936e571a5b 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -347,7 +347,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der int numVerts; float (*v_cos)[3] = NULL; /* The vertices coordinates. */ Object *obr = NULL; /* Our target object. */ - int defgrp_idx; + int defgrp_index; float *tw = NULL; float *org_w = NULL; float *new_w = NULL; @@ -378,8 +378,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der return dm; /* Get vgroup idx from its name. */ - defgrp_idx = defgroup_name_index(ob, wmd->defgrp_name); - if (defgrp_idx < 0) + defgrp_index = defgroup_name_index(ob, wmd->defgrp_name); + if (defgrp_index == -1) return dm; dvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MDEFORMVERT, numVerts); @@ -394,7 +394,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der tw = MEM_mallocN(sizeof(float) * numVerts, "WeightVGProximity Modifier, tw"); tdw = MEM_mallocN(sizeof(MDeformWeight *) * numVerts, "WeightVGProximity Modifier, tdw"); for (i = 0; i < numVerts; i++) { - MDeformWeight *_dw = defvert_find_index(&dvert[i], defgrp_idx); + MDeformWeight *_dw = defvert_find_index(&dvert[i], defgrp_index); if (_dw) { tidx[numIdx] = i; tw[numIdx] = _dw->weight; @@ -460,7 +460,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der else if (obr->type == OB_MESH) { Mesh *me = (Mesh *)obr->data; if (me->edit_btmesh) - target_dm = CDDM_from_BMEditMesh(me->edit_btmesh, me, FALSE, FALSE); + target_dm = CDDM_from_editbmesh(me->edit_btmesh, FALSE, FALSE); else target_dm = CDDM_from_mesh(me, obr); } @@ -480,9 +480,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der for (i = 0; i < numIdx; i++) { new_w[i] = dists_v ? dists_v[i] : FLT_MAX; if (dists_e) - new_w[i] = minf(dists_e[i], new_w[i]); + new_w[i] = min_ff(dists_e[i], new_w[i]); if (dists_f) - new_w[i] = minf(dists_f[i], new_w[i]); + new_w[i] = min_ff(dists_f[i], new_w[i]); } if (free_target_dm) target_dm->release(target_dm); if (dists_v) MEM_freeN(dists_v); @@ -509,7 +509,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der wmd->mask_tex_map_obj, wmd->mask_tex_uvlayer_name); /* Update vgroup. Note we never add nor remove vertices from vgroup here. */ - weightvg_update_vg(dvert, defgrp_idx, dw, numIdx, indices, org_w, FALSE, 0.0f, FALSE, 0.0f); + weightvg_update_vg(dvert, defgrp_index, dw, numIdx, indices, org_w, FALSE, 0.0f, FALSE, 0.0f); /* If weight preview enabled... */ #if 0 /* XXX Currently done in mod stack :/ */ diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 08e0e7b0f93..323a534c989 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -23,8 +23,12 @@ # # ***** END GPL LICENSE BLOCK ***** -set(INC +set(INC . + composite + intern + shader + texture ../blenfont ../blenkernel ../blenlib @@ -39,10 +43,6 @@ set(INC set(INC_SYS ${GLEW_INCLUDE_PATH} - intern - composite - shader - texture ) set(SRC @@ -119,7 +119,8 @@ set(SRC composite/nodes/node_composite_ellipsemask.c composite/nodes/node_composite_switch.c composite/nodes/node_composite_colorcorrection.c - + composite/nodes/node_composite_pixelate.c + composite/node_composite_tree.c composite/node_composite_util.c @@ -146,13 +147,14 @@ set(SRC shader/nodes/node_shader_vectMath.c shader/nodes/node_shader_attribute.c shader/nodes/node_shader_background.c - # shader/nodes/node_shader_bsdf_anisotropic.c # XXX, why not included? + shader/nodes/node_shader_bsdf_anisotropic.c shader/nodes/node_shader_bsdf_diffuse.c shader/nodes/node_shader_bsdf_glossy.c shader/nodes/node_shader_bsdf_glass.c shader/nodes/node_shader_bsdf_translucent.c shader/nodes/node_shader_bsdf_transparent.c shader/nodes/node_shader_bsdf_velvet.c + shader/nodes/node_shader_bump.c shader/nodes/node_shader_emission.c shader/nodes/node_shader_fresnel.c shader/nodes/node_shader_layer_weight.c @@ -163,6 +165,7 @@ set(SRC shader/nodes/node_shader_light_path.c shader/nodes/node_shader_light_falloff.c shader/nodes/node_shader_object_info.c + shader/nodes/node_shader_script.c shader/nodes/node_shader_particle_info.c shader/nodes/node_shader_mix_shader.c shader/nodes/node_shader_add_shader.c diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index bcef230e1d0..ee67ac88085 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -96,7 +96,7 @@ void register_node_type_cmp_combhsva(struct bNodeTreeType *ttype); void register_node_type_cmp_sepyuva(struct bNodeTreeType *ttype); void register_node_type_cmp_combyuva(struct bNodeTreeType *ttype); void register_node_type_cmp_sepycca(struct bNodeTreeType *ttype); -void register_node_type_cmp_combycca(struct bNodeTreeType *ttype); +void register_node_type_cmp_combycca(struct bNodeTreeType *ttype); void register_node_type_cmp_premulkey(struct bNodeTreeType *ttype); void register_node_type_cmp_diff_matte(struct bNodeTreeType *ttype); @@ -105,7 +105,7 @@ void register_node_type_cmp_chroma_matte(struct bNodeTreeType *ttype); void register_node_type_cmp_color_matte(struct bNodeTreeType *ttype); void register_node_type_cmp_channel_matte(struct bNodeTreeType *ttype); void register_node_type_cmp_color_spill(struct bNodeTreeType *ttype); -void register_node_type_cmp_luma_matte(struct bNodeTreeType *ttype); +void register_node_type_cmp_luma_matte(struct bNodeTreeType *ttype); void register_node_type_cmp_doubleedgemask(struct bNodeTreeType *ttype); void register_node_type_cmp_keyingscreen(struct bNodeTreeType *ttype); void register_node_type_cmp_keying(struct bNodeTreeType *ttype); @@ -133,7 +133,7 @@ void register_node_type_cmp_ellipsemask(struct bNodeTreeType *ttype); void register_node_type_cmp_bokehimage(struct bNodeTreeType *ttype); void register_node_type_cmp_bokehblur(struct bNodeTreeType *ttype); void register_node_type_cmp_switch(struct bNodeTreeType *ttype); - +void register_node_type_cmp_pixelate(struct bNodeTreeType *ttype); void register_node_type_cmp_trackpos(struct bNodeTreeType *ttype); #endif diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 49428c06e5f..66ab15ce29f 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -80,6 +80,7 @@ void register_node_type_sh_fresnel(struct bNodeTreeType *ttype); void register_node_type_sh_layer_weight(struct bNodeTreeType *ttype); void register_node_type_sh_tex_coord(struct bNodeTreeType *ttype); void register_node_type_sh_particle_info(struct bNodeTreeType *ttype); +void register_node_type_sh_script(struct bNodeTreeType *ttype); void register_node_type_sh_background(struct bNodeTreeType *ttype); void register_node_type_sh_bsdf_diffuse(struct bNodeTreeType *ttype); @@ -88,6 +89,7 @@ void register_node_type_sh_bsdf_glass(struct bNodeTreeType *ttype); void register_node_type_sh_bsdf_translucent(struct bNodeTreeType *ttype); void register_node_type_sh_bsdf_transparent(struct bNodeTreeType *ttype); void register_node_type_sh_bsdf_velvet(struct bNodeTreeType *ttype); +void register_node_type_sh_bsdf_anisotropic(struct bNodeTreeType *ttype); void register_node_type_sh_emission(struct bNodeTreeType *ttype); void register_node_type_sh_holdout(struct bNodeTreeType *ttype); void register_node_type_sh_volume_transparent(struct bNodeTreeType *ttype); @@ -109,6 +111,7 @@ void register_node_type_sh_tex_wave(struct bNodeTreeType *ttype); void register_node_type_sh_tex_musgrave(struct bNodeTreeType *ttype); void register_node_type_sh_tex_noise(struct bNodeTreeType *ttype); void register_node_type_sh_tex_checker(struct bNodeTreeType *ttype); +void register_node_type_sh_bump(struct bNodeTreeType *ttype); #endif diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index c9960df1345..9a7e587ff56 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -226,7 +226,7 @@ static void local_merge(bNodeTree *localtree, bNodeTree *ntree) } else if (lnode->type==CMP_NODE_MOVIEDISTORTION) { /* special case for distortion node: distortion context is allocating in exec function - * and to achive much better performance on further calls this context should be + * and to achieve much better performance on further calls this context should be * copied back to original node */ if (lnode->storage) { if (lnode->new_node->storage) @@ -273,7 +273,7 @@ bNodeTreeType ntreeType_Composite = { /* update */ update, /* update_node */ update_node, /* validate_link */ NULL, - /* internal_connect */ node_internal_connect_default + /* update_internal_links */ node_update_internal_links_default }; @@ -301,7 +301,7 @@ struct bNodeTreeExec *ntreeCompositBeginExecTree(bNodeTree *ntree, int use_tree_ for (node= exec->nodetree->nodes.first; node; node= node->next) { /* initialize needed for groups */ - node->exec= 0; + node->exec= 0; for (sock= node->outputs.first; sock; sock= sock->next) { bNodeStack *ns= node_get_socket_stack(exec->stack, sock); @@ -515,9 +515,9 @@ static int setExecutableNodes(bNodeTreeExec *exec, ThreadData *thd) static void freeExecutableNode(bNodeTreeExec *exec) { /* node outputs can be freed when: - - not a render result or image node - - when node outputs go to nodes all being set NODE_FINISHED - */ + * - not a render result or image node + * - when node outputs go to nodes all being set NODE_FINISHED + */ bNodeTree *ntree = exec->nodetree; bNodeExec *nodeexec; bNode *node; diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c index fe4eebc9492..57eb99021f6 100644 --- a/source/blender/nodes/composite/node_composite_util.c +++ b/source/blender/nodes/composite/node_composite_util.c @@ -72,7 +72,7 @@ CompBuf *dupalloc_compbuf(CompBuf *cbuf) dupbuf->xof= cbuf->xof; dupbuf->yof= cbuf->yof; - } + } return dupbuf; } @@ -94,7 +94,7 @@ CompBuf *pass_on_compbuf(CompBuf *cbuf) break; lastbuf->next= dupbuf; dupbuf->prev= lastbuf; - } + } return dupbuf; } @@ -146,7 +146,7 @@ CompBuf *get_cropped_compbuf(rcti *drect, float *rectf, int rectx, int recty, in if (disprect.xmin>= disprect.xmax) return NULL; if (disprect.ymin>= disprect.ymax) return NULL; - cbuf= alloc_compbuf(BLI_RCT_SIZE_X(&disprect), BLI_RCT_SIZE_Y(&disprect), type, 1); + cbuf= alloc_compbuf(BLI_rcti_size_x(&disprect), BLI_rcti_size_y(&disprect), type, 1); outfp= cbuf->rect; rectf += type*(disprect.ymin*rectx + disprect.xmin); dx= type*cbuf->x; @@ -213,53 +213,53 @@ void typecheck_compbuf_color(float *out, float *in, int outtype, int intype) } else if (outtype==CB_VEC2) { if (intype==CB_VAL) { - out[0]= in[0]; - out[1]= in[0]; + out[0] = in[0]; + out[1] = in[0]; } else if (intype==CB_VEC3) { - out[0]= in[0]; - out[1]= in[1]; + out[0] = in[0]; + out[1] = in[1]; } else if (intype==CB_RGBA) { - out[0]= in[0]; - out[1]= in[1]; + out[0] = in[0]; + out[1] = in[1]; } } else if (outtype==CB_VEC3) { if (intype==CB_VAL) { - out[0]= in[0]; - out[1]= in[0]; - out[2]= in[0]; + out[0] = in[0]; + out[1] = in[0]; + out[2] = in[0]; } else if (intype==CB_VEC2) { - out[0]= in[0]; - out[1]= in[1]; - out[2]= 0.0f; + out[0] = in[0]; + out[1] = in[1]; + out[2] = 0.0f; } else if (intype==CB_RGBA) { - out[0]= in[0]; - out[1]= in[1]; - out[2]= in[2]; + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; } } else if (outtype==CB_RGBA) { if (intype==CB_VAL) { - out[0]= in[0]; - out[1]= in[0]; - out[2]= in[0]; - out[3]= 1.0f; + out[0] = in[0]; + out[1] = in[0]; + out[2] = in[0]; + out[3] = 1.0f; } else if (intype==CB_VEC2) { - out[0]= in[0]; - out[1]= in[1]; - out[2]= 0.0f; - out[3]= 1.0f; + out[0] = in[0]; + out[1] = in[1]; + out[2] = 0.0f; + out[3] = 1.0f; } else if (intype==CB_VEC3) { - out[0]= in[0]; - out[1]= in[1]; - out[2]= in[2]; - out[3]= 1.0f; + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = 1.0f; } } } @@ -307,69 +307,69 @@ CompBuf *typecheck_compbuf(CompBuf *inbuf, int type) else if (type==CB_VEC2) { if (inbuf->type==CB_VAL) { for (; x>0; x--, outrf+= 2, inrf+= 1) { - outrf[0]= inrf[0]; - outrf[1]= inrf[0]; + outrf[0] = inrf[0]; + outrf[1] = inrf[0]; } } else if (inbuf->type==CB_VEC3) { for (; x>0; x--, outrf+= 2, inrf+= 3) { - outrf[0]= inrf[0]; - outrf[1]= inrf[1]; + outrf[0] = inrf[0]; + outrf[1] = inrf[1]; } } else if (inbuf->type==CB_RGBA) { for (; x>0; x--, outrf+= 2, inrf+= 4) { - outrf[0]= inrf[0]; - outrf[1]= inrf[1]; + outrf[0] = inrf[0]; + outrf[1] = inrf[1]; } } } else if (type==CB_VEC3) { if (inbuf->type==CB_VAL) { for (; x>0; x--, outrf+= 3, inrf+= 1) { - outrf[0]= inrf[0]; - outrf[1]= inrf[0]; - outrf[2]= inrf[0]; + outrf[0] = inrf[0]; + outrf[1] = inrf[0]; + outrf[2] = inrf[0]; } } else if (inbuf->type==CB_VEC2) { for (; x>0; x--, outrf+= 3, inrf+= 2) { - outrf[0]= inrf[0]; - outrf[1]= inrf[1]; - outrf[2]= 0.0f; + outrf[0] = inrf[0]; + outrf[1] = inrf[1]; + outrf[2] = 0.0f; } } else if (inbuf->type==CB_RGBA) { for (; x>0; x--, outrf+= 3, inrf+= 4) { - outrf[0]= inrf[0]; - outrf[1]= inrf[1]; - outrf[2]= inrf[2]; + outrf[0] = inrf[0]; + outrf[1] = inrf[1]; + outrf[2] = inrf[2]; } } } else if (type==CB_RGBA) { if (inbuf->type==CB_VAL) { for (; x>0; x--, outrf+= 4, inrf+= 1) { - outrf[0]= inrf[0]; - outrf[1]= inrf[0]; - outrf[2]= inrf[0]; - outrf[3]= 1.0f; + outrf[0] = inrf[0]; + outrf[1] = inrf[0]; + outrf[2] = inrf[0]; + outrf[3] = 1.0f; } } else if (inbuf->type==CB_VEC2) { for (; x>0; x--, outrf+= 4, inrf+= 2) { - outrf[0]= inrf[0]; - outrf[1]= inrf[1]; - outrf[2]= 0.0f; - outrf[3]= 1.0f; + outrf[0] = inrf[0]; + outrf[1] = inrf[1]; + outrf[2] = 0.0f; + outrf[3] = 1.0f; } } else if (inbuf->type==CB_VEC3) { for (; x>0; x--, outrf+= 4, inrf+= 3) { - outrf[0]= inrf[0]; - outrf[1]= inrf[1]; - outrf[2]= inrf[2]; - outrf[3]= 1.0f; + outrf[0] = inrf[0]; + outrf[1] = inrf[1]; + outrf[2] = inrf[2]; + outrf[3] = 1.0f; } } } @@ -387,7 +387,7 @@ float *compbuf_get_pixel(CompBuf *cbuf, float *defcol, float *use, int x, int y, return use; } else { - static float col[4]= {0.0f, 0.0f, 0.0f, 0.0f}; + static float col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; /* map coords */ x-= cbuf->xof; @@ -707,18 +707,18 @@ void do_copy_rgba(bNode *UNUSED(node), float *out, float *in) void do_copy_rgb(bNode *UNUSED(node), float *out, float *in) { copy_v3_v3(out, in); - out[3]= 1.0f; + out[3] = 1.0f; } void do_copy_value(bNode *UNUSED(node), float *out, float *in) { - out[0]= in[0]; + out[0] = in[0]; } void do_copy_a_rgba(bNode *UNUSED(node), float *out, float *in, float *fac) { copy_v3_v3(out, in); - out[3]= *fac; + out[3] = *fac; } /* only accepts RGBA buffers */ @@ -732,16 +732,16 @@ void gamma_correct_compbuf(CompBuf *img, int inversed) drect= img->rect; if (inversed) { for (x=img->x*img->y; x>0; x--, drect+=4) { - if (drect[0]>0.0f) drect[0]= sqrt(drect[0]); else drect[0]= 0.0f; - if (drect[1]>0.0f) drect[1]= sqrt(drect[1]); else drect[1]= 0.0f; - if (drect[2]>0.0f) drect[2]= sqrt(drect[2]); else drect[2]= 0.0f; + if (drect[0]>0.0f) drect[0] = sqrt(drect[0]); else drect[0] = 0.0f; + if (drect[1]>0.0f) drect[1] = sqrt(drect[1]); else drect[1] = 0.0f; + if (drect[2]>0.0f) drect[2] = sqrt(drect[2]); else drect[2] = 0.0f; } } else { for (x=img->x*img->y; x>0; x--, drect+=4) { - if (drect[0]>0.0f) drect[0]*= drect[0]; else drect[0]= 0.0f; - if (drect[1]>0.0f) drect[1]*= drect[1]; else drect[1]= 0.0f; - if (drect[2]>0.0f) drect[2]*= drect[2]; else drect[2]= 0.0f; + if (drect[0]>0.0f) drect[0]*= drect[0]; else drect[0] = 0.0f; + if (drect[1]>0.0f) drect[1]*= drect[1]; else drect[1] = 0.0f; + if (drect[2]>0.0f) drect[2]*= drect[2]; else drect[2] = 0.0f; } } } @@ -757,9 +757,9 @@ void premul_compbuf(CompBuf *img, int inversed) if (inversed) { for (x=img->x*img->y; x>0; x--, drect+=4) { if (fabsf(drect[3]) < 1e-5f) { - drect[0]= 0.0f; - drect[1]= 0.0f; - drect[2]= 0.0f; + drect[0] = 0.0f; + drect[1] = 0.0f; + drect[2] = 0.0f; } else { drect[0] /= drect[3]; @@ -1121,7 +1121,7 @@ void convolve(CompBuf* dst, CompBuf* in1, CompBuf* in2) /* * - * Utility functions qd_* should probably be intergrated better with other functions here. + * Utility functions qd_* should probably be integrated better with other functions here. * */ // sets fcol to pixelcolor at (x, y) diff --git a/source/blender/nodes/composite/nodes/node_composite_alphaOver.c b/source/blender/nodes/composite/nodes/node_composite_alphaOver.c index 86eb0aa2c83..72c2204d8c5 100644 --- a/source/blender/nodes/composite/nodes/node_composite_alphaOver.c +++ b/source/blender/nodes/composite/nodes/node_composite_alphaOver.c @@ -32,13 +32,13 @@ #include "node_composite_util.h" /* **************** ALPHAOVER ******************** */ -static bNodeSocketTemplate cmp_node_alphaover_in[]= { +static bNodeSocketTemplate cmp_node_alphaover_in[] = { { SOCK_FLOAT, 1, N_("Fac"), 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_alphaover_out[]= { +static bNodeSocketTemplate cmp_node_alphaover_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; @@ -48,7 +48,7 @@ static bNodeSocketTemplate cmp_node_alphaover_out[]= { static void do_alphaover_premul(bNode *UNUSED(node), float *out, float *src, float *over, float *fac) { - /* Zero alpha values should still permit an add of RGB data */ + /* Zero alpha values should still permit an add of RGB data */ if (over[3]<0.0f) { copy_v4_v4(out, src); } @@ -58,11 +58,11 @@ static void do_alphaover_premul(bNode *UNUSED(node), float *out, float *src, flo else { float mul= 1.0f - fac[0]*over[3]; - out[0]= (mul*src[0]) + fac[0]*over[0]; - out[1]= (mul*src[1]) + fac[0]*over[1]; - out[2]= (mul*src[2]) + fac[0]*over[2]; - out[3]= (mul*src[3]) + fac[0]*over[3]; - } + out[0] = (mul*src[0]) + fac[0]*over[0]; + out[1] = (mul*src[1]) + fac[0]*over[1]; + out[2] = (mul*src[2]) + fac[0]*over[2]; + out[3] = (mul*src[3]) + fac[0]*over[3]; + } } /* result will be still premul, but the over part is premulled */ @@ -79,10 +79,10 @@ static void do_alphaover_key(bNode *UNUSED(node), float *out, float *src, float float premul= fac[0]*over[3]; float mul= 1.0f - premul; - out[0]= (mul*src[0]) + premul*over[0]; - out[1]= (mul*src[1]) + premul*over[1]; - out[2]= (mul*src[2]) + premul*over[2]; - out[3]= (mul*src[3]) + fac[0]*over[3]; + out[0] = (mul*src[0]) + premul*over[0]; + out[1] = (mul*src[1]) + premul*over[1]; + out[2] = (mul*src[2]) + premul*over[2]; + out[3] = (mul*src[3]) + fac[0]*over[3]; } } @@ -102,10 +102,10 @@ static void do_alphaover_mixed(bNode *node, float *out, float *src, float *over, float premul= fac[0]*addfac; float mul= 1.0f - fac[0]*over[3]; - out[0]= (mul*src[0]) + premul*over[0]; - out[1]= (mul*src[1]) + premul*over[1]; - out[2]= (mul*src[2]) + premul*over[2]; - out[3]= (mul*src[3]) + fac[0]*over[3]; + out[0] = (mul*src[0]) + premul*over[0]; + out[1] = (mul*src[1]) + premul*over[1]; + out[2] = (mul*src[2]) + premul*over[2]; + out[3] = (mul*src[3]) + fac[0]*over[3]; } } diff --git a/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c b/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c index e05ef1ea5a5..7674ace42a3 100644 --- a/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c +++ b/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c @@ -33,14 +33,14 @@ /* **************** BILATERALBLUR ******************** */ static bNodeSocketTemplate cmp_node_bilateralblur_in[] = { - { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, - { SOCK_RGBA, 1, N_("Determinator"), 1.0f, 1.0f, 1.0f, 1.0f}, - { -1, 0, "" } + { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, + { SOCK_RGBA, 1, N_("Determinator"), 1.0f, 1.0f, 1.0f, 1.0f}, + { -1, 0, "" } }; static bNodeSocketTemplate cmp_node_bilateralblur_out[] = { - { SOCK_RGBA, 0, N_("Image")}, - { -1, 0, "" } + { SOCK_RGBA, 0, N_("Image")}, + { -1, 0, "" } }; #ifdef WITH_COMPOSITOR_LEGACY diff --git a/source/blender/nodes/composite/nodes/node_composite_bokehimage.c b/source/blender/nodes/composite/nodes/node_composite_bokehimage.c index c5697679f90..8324b77b2d1 100644 --- a/source/blender/nodes/composite/nodes/node_composite_bokehimage.c +++ b/source/blender/nodes/composite/nodes/node_composite_bokehimage.c @@ -37,7 +37,7 @@ /* **************** Bokeh image Tools ******************** */ -static bNodeSocketTemplate cmp_node_bokehimage_out[]= { +static bNodeSocketTemplate cmp_node_bokehimage_out[] = { { SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { -1, 0, "" } }; diff --git a/source/blender/nodes/composite/nodes/node_composite_boxmask.c b/source/blender/nodes/composite/nodes/node_composite_boxmask.c index 1ba522c0e5f..d3c6b2ccef0 100644 --- a/source/blender/nodes/composite/nodes/node_composite_boxmask.c +++ b/source/blender/nodes/composite/nodes/node_composite_boxmask.c @@ -1,6 +1,4 @@ /* - * $Id: CMP_math.c 36271 2011-04-21 13:11:51Z campbellbarton $ - * * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -35,15 +33,15 @@ #include "../node_composite_util.h" /* **************** SCALAR MATH ******************** */ -static bNodeSocketTemplate cmp_node_boxmask_in[]= { +static bNodeSocketTemplate cmp_node_boxmask_in[] = { { SOCK_FLOAT, 1, N_("Mask"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Value"), 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, - { -1, 0, "" } + { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_boxmask_out[]= { +static bNodeSocketTemplate cmp_node_boxmask_out[] = { { SOCK_FLOAT, 0, N_("Mask"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, - { -1, 0, "" } + { -1, 0, "" } }; static void node_composit_init_boxmask(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) diff --git a/source/blender/nodes/composite/nodes/node_composite_brightness.c b/source/blender/nodes/composite/nodes/node_composite_brightness.c index 2b8a394d6f2..ecf572f59c7 100644 --- a/source/blender/nodes/composite/nodes/node_composite_brightness.c +++ b/source/blender/nodes/composite/nodes/node_composite_brightness.c @@ -36,13 +36,13 @@ /* **************** Brigh and contrsast ******************** */ -static bNodeSocketTemplate cmp_node_brightcontrast_in[]= { +static bNodeSocketTemplate cmp_node_brightcontrast_in[] = { { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Bright"), 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f, PROP_NONE}, { SOCK_FLOAT, 1, N_("Contrast"), 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f, PROP_NONE}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_brightcontrast_out[]= { +static bNodeSocketTemplate cmp_node_brightcontrast_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; @@ -72,7 +72,7 @@ static void do_brightnesscontrast(bNode *UNUSED(node), float *out, float *in, fl b = a * (brightness + delta); } - for (c=0; c<3; c++) { + for (c=0; c<3; c++) { i = in[c]; v = a*i + b; out[c] = v; diff --git a/source/blender/nodes/composite/nodes/node_composite_channelMatte.c b/source/blender/nodes/composite/nodes/node_composite_channelMatte.c index 06b77de463b..40dbbbb8dca 100644 --- a/source/blender/nodes/composite/nodes/node_composite_channelMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_channelMatte.c @@ -34,12 +34,12 @@ /* ******************* Channel Matte Node ********************************* */ -static bNodeSocketTemplate cmp_node_channel_matte_in[]={ +static bNodeSocketTemplate cmp_node_channel_matte_in[] ={ {SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, {-1, 0, ""} }; -static bNodeSocketTemplate cmp_node_channel_matte_out[]={ +static bNodeSocketTemplate cmp_node_channel_matte_out[] ={ {SOCK_RGBA, 0, N_("Image")}, {SOCK_FLOAT, 0, N_("Matte")}, {-1, 0, ""} @@ -71,7 +71,7 @@ static void do_normalized_ycca_to_rgba2(bNode *UNUSED(node), float *out, float * static void do_channel_matte(bNode *node, float *out, float *in) { NodeChroma *c=(NodeChroma *)node->storage; - float alpha=0.0; + float alpha=0.0; switch (c->algorithm) { case 0: { /* Alpha=key_channel-limit channel */ diff --git a/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c b/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c index 55ee1b090bb..f343f806d57 100644 --- a/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c @@ -33,13 +33,13 @@ #include "node_composite_util.h" /* ******************* Chroma Key ********************************************************** */ -static bNodeSocketTemplate cmp_node_chroma_in[]={ +static bNodeSocketTemplate cmp_node_chroma_in[] = { {SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, {SOCK_RGBA, 1, N_("Key Color"), 1.0f, 1.0f, 1.0f, 1.0f}, {-1, 0, ""} }; -static bNodeSocketTemplate cmp_node_chroma_out[]={ +static bNodeSocketTemplate cmp_node_chroma_out[] = { {SOCK_RGBA, 0, N_("Image")}, {SOCK_FLOAT, 0, N_("Matte")}, {-1, 0, ""} diff --git a/source/blender/nodes/composite/nodes/node_composite_colorMatte.c b/source/blender/nodes/composite/nodes/node_composite_colorMatte.c index 37fb29811ba..07a6647d976 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_colorMatte.c @@ -33,13 +33,13 @@ #include "node_composite_util.h" /* ******************* Color Key ********************************************************** */ -static bNodeSocketTemplate cmp_node_color_in[]={ +static bNodeSocketTemplate cmp_node_color_in[] = { {SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, {SOCK_RGBA, 1, N_("Key Color"), 1.0f, 1.0f, 1.0f, 1.0f}, {-1, 0, ""} }; -static bNodeSocketTemplate cmp_node_color_out[]={ +static bNodeSocketTemplate cmp_node_color_out[] = { {SOCK_RGBA, 0, N_("Image")}, {SOCK_FLOAT, 0, N_("Matte")}, {-1, 0, ""} diff --git a/source/blender/nodes/composite/nodes/node_composite_colorSpill.c b/source/blender/nodes/composite/nodes/node_composite_colorSpill.c index c4120ab22c6..e8965d50b47 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorSpill.c +++ b/source/blender/nodes/composite/nodes/node_composite_colorSpill.c @@ -36,13 +36,13 @@ #define AVG(a, b) ((a + b) / 2) /* ******************* Color Spill Supression ********************************* */ -static bNodeSocketTemplate cmp_node_color_spill_in[]={ +static bNodeSocketTemplate cmp_node_color_spill_in[] = { {SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, {SOCK_FLOAT, 1, N_("Fac"), 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, {-1, 0, ""} }; -static bNodeSocketTemplate cmp_node_color_spill_out[]={ +static bNodeSocketTemplate cmp_node_color_spill_out[] = { {SOCK_RGBA, 0, N_("Image")}, {-1, 0, ""} }; diff --git a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c index 0868c9467e5..e9d26ebebbc 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c +++ b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c @@ -35,13 +35,13 @@ /* ******************* Color Balance ********************************* */ -static bNodeSocketTemplate cmp_node_colorbalance_in[]={ +static bNodeSocketTemplate cmp_node_colorbalance_in[] = { {SOCK_FLOAT, 1, N_("Fac"), 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, {SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, {-1, 0, ""} }; -static bNodeSocketTemplate cmp_node_colorbalance_out[]={ +static bNodeSocketTemplate cmp_node_colorbalance_out[] = { {SOCK_RGBA, 0, N_("Image")}, {-1, 0, ""} }; @@ -71,8 +71,8 @@ DO_INLINE float colorbalance_cdl(float in, float offset, float power, float slop /* note: lift_lgg is just 2-lift, gamma_inv is 1.0/gamma */ DO_INLINE float colorbalance_lgg(float in, float lift_lgg, float gamma_inv, float gain) { - /* 1:1 match with the sequencer with linear/srgb conversions, the conversion isn'tisn't pretty - * but best keep it this way, sice testing for durian shows a similar calculation + /* 1:1 match with the sequencer with linear/srgb conversions, the conversion isn't pretty + * but best keep it this way, since testing for durian shows a similar calculation * without lin/srgb conversions gives bad results (over-saturated shadows) with colors * slightly below 1.0. some correction can be done but it ends up looking bad for shadows or lighter tones - campbell */ float x= (((linearrgb_to_srgb(in) - 1.0f) * lift_lgg) + 1.0f) * gain; diff --git a/source/blender/nodes/composite/nodes/node_composite_colorcorrection.c b/source/blender/nodes/composite/nodes/node_composite_colorcorrection.c index ce43b2f0f2b..526f8472992 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorcorrection.c +++ b/source/blender/nodes/composite/nodes/node_composite_colorcorrection.c @@ -36,13 +36,13 @@ /* ******************* Color Balance ********************************* */ -static bNodeSocketTemplate cmp_node_colorcorrection_in[]={ +static bNodeSocketTemplate cmp_node_colorcorrection_in[] = { { SOCK_RGBA,1,N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Mask"), 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, { -1,0,""} }; -static bNodeSocketTemplate cmp_node_colorcorrection_out[]={ +static bNodeSocketTemplate cmp_node_colorcorrection_out[] = { { SOCK_RGBA,0,N_("Image")}, { -1,0,""} }; diff --git a/source/blender/nodes/composite/nodes/node_composite_common.c b/source/blender/nodes/composite/nodes/node_composite_common.c index 2596248d696..10b81cdaaa0 100644 --- a/source/blender/nodes/composite/nodes/node_composite_common.c +++ b/source/blender/nodes/composite/nodes/node_composite_common.c @@ -231,153 +231,3 @@ void register_node_type_cmp_group(bNodeTreeType *ttype) nodeRegisterType(ttype, &ntype); } - -#ifdef WITH_COMPOSITOR_LEGACY - -/**** FOR LOOP ****/ - -#if 0 /* XXX loop nodes don't work nicely with current trees */ -/* Move the results from the previous iteration back to the input sockets. */ -static void loop_iteration_reset(bNodeTree *ngroup, bNodeStack *gstack) -{ - bNodeSocket *gin, *gout; - bNodeStack *nsin, *nsout; - - gin = ngroup->inputs.first; - gout = ngroup->outputs.first; - - while (gin && gout) { - /* skip static (non-looping) sockets */ - while (gin && !(gin->flag & SOCK_DYNAMIC)) - gin=gin->next; - while (gout && !(gout->flag & SOCK_DYNAMIC)) - gout=gout->next; - - if (gin && gout) { - nsin = node_get_socket_stack(gstack, gin); - nsout = node_get_socket_stack(gstack, gout); - - move_stack(nsin, nsout); - - gin=gin->next; - gout=gout->next; - } - } -} - -static void forloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out) -{ - bNodeTreeExec *exec= (bNodeTreeExec *)nodedata; - int totiterations= (int)in[0]->vec[0]; - bNodeSocket *sock; - bNodeStack *ns; - int iteration; - - /* XXX same behavior as trunk: all nodes inside group are executed. - * it's stupid, but just makes it work. compo redesign will do this better. - */ - { - bNode *inode; - for (inode=exec->nodetree->nodes.first; inode; inode=inode->next) - inode->need_exec = 1; - } - - /* "Iteration" socket */ - sock = exec->nodetree->inputs.first; - ns = node_get_socket_stack(exec->stack, sock); - - group_copy_inputs(node, in, exec->stack); - for (iteration=0; iteration < totiterations; ++iteration) { - /* first input contains current iteration counter */ - ns->vec[0] = (float)iteration; - - if (iteration > 0) - loop_iteration_reset(exec->nodetree, exec->stack); - ntreeExecNodes(exec, data, thread); - group_free_internal(exec); - } - group_move_outputs(node, out, exec->stack); -} - -void register_node_type_cmp_forloop(bNodeTreeType *ttype) -{ - static bNodeType ntype; - - node_type_base(ttype, &ntype, NODE_FORLOOP, "For", NODE_CLASS_GROUP, NODE_OPTIONS); - node_type_socket_templates(&ntype, NULL, NULL); - node_type_size(&ntype, 120, 60, 200); - node_type_label(&ntype, node_group_label); - node_type_init(&ntype, node_forloop_init); - node_type_valid(&ntype, node_group_valid); - node_type_template(&ntype, node_forloop_template); - node_type_update(&ntype, NULL, node_group_verify); - node_type_tree(&ntype, node_forloop_init_tree, node_loop_update_tree); - node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); - node_type_exec_new(&ntype, group_initexec, group_freeexec, forloop_execute); - - nodeRegisterType(ttype, &ntype); -} -#endif - - -/**** WHILE LOOP ****/ - -#if 0 /* XXX loop nodes don't work nicely with current trees */ -static void whileloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out) -{ - bNodeTreeExec *exec= (bNodeTreeExec *)nodedata; - int condition= (in[0]->vec[0] > 0.0f); - bNodeSocket *sock; - bNodeStack *ns; - int iteration; - - /* XXX same behavior as trunk: all nodes inside group are executed. - * it's stupid, but just makes it work. compo redesign will do this better. - */ - { - bNode *inode; - for (inode=exec->nodetree->nodes.first; inode; inode=inode->next) - inode->need_exec = 1; - } - - /* "Condition" socket */ - sock = exec->nodetree->outputs.first; - ns = node_get_socket_stack(exec->stack, sock); - - iteration = 0; - group_copy_inputs(node, in, exec->stack); - while (condition && iteration < node->custom1) { - if (iteration > 0) - loop_iteration_reset(exec->nodetree, exec->stack); - ntreeExecNodes(exec, data, thread); - group_free_internal(exec); - -// PRINT_BUFFERS(exec); - - condition = (ns->vec[0] > 0.0f); - ++iteration; - } - group_move_outputs(node, out, exec->stack); -} - -void register_node_type_cmp_whileloop(bNodeTreeType *ttype) -{ - static bNodeType ntype; - - node_type_base(ttype, &ntype, NODE_WHILELOOP, "While", NODE_CLASS_GROUP, NODE_OPTIONS); - node_type_socket_templates(&ntype, NULL, NULL); - node_type_size(&ntype, 120, 60, 200); - node_type_label(&ntype, node_group_label); - node_type_init(&ntype, node_whileloop_init); - node_type_valid(&ntype, node_group_valid); - node_type_template(&ntype, node_whileloop_template); - node_type_update(&ntype, NULL, node_group_verify); - node_type_tree(&ntype, node_whileloop_init_tree, node_loop_update_tree); - node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); - node_type_exec_new(&ntype, group_initexec, group_freeexec, whileloop_execute); - - nodeRegisterType(ttype, &ntype); -} -#endif - -#endif /* WITH_COMPOSITOR_LEGACY */ diff --git a/source/blender/nodes/composite/nodes/node_composite_composite.c b/source/blender/nodes/composite/nodes/node_composite_composite.c index dadc863873d..cb932b6a8de 100644 --- a/source/blender/nodes/composite/nodes/node_composite_composite.c +++ b/source/blender/nodes/composite/nodes/node_composite_composite.c @@ -32,7 +32,7 @@ #include "node_composite_util.h" /* **************** COMPOSITE ******************** */ -static bNodeSocketTemplate cmp_node_composite_in[]= { +static bNodeSocketTemplate cmp_node_composite_in[] = { { SOCK_RGBA, 1, N_("Image"), 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, { SOCK_FLOAT, 1, N_("Z"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, @@ -110,7 +110,7 @@ void register_node_type_cmp_composite(bNodeTreeType *ttype) #endif /* Do not allow muting for this node. */ - node_type_internal_connect(&ntype, NULL); + node_type_internal_links(&ntype, NULL); nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_crop.c b/source/blender/nodes/composite/nodes/node_composite_crop.c index 9b1483d95cf..ad51fae1998 100644 --- a/source/blender/nodes/composite/nodes/node_composite_crop.c +++ b/source/blender/nodes/composite/nodes/node_composite_crop.c @@ -34,11 +34,11 @@ /* **************** Crop ******************** */ -static bNodeSocketTemplate cmp_node_crop_in[]= { +static bNodeSocketTemplate cmp_node_crop_in[] = { { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_crop_out[]= { +static bNodeSocketTemplate cmp_node_crop_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; @@ -82,7 +82,7 @@ static void node_composit_exec_crop(void *UNUSED(data), bNode *node, bNodeStack outputrect.ymin=MIN2(ntxy->y1, ntxy->y2); if (node->custom1) { - /* this option crops the image size too */ + /* this option crops the image size too */ stackbuf= get_cropped_compbuf(&outputrect, cbuf->rect, cbuf->x, cbuf->y, cbuf->type); } else { diff --git a/source/blender/nodes/composite/nodes/node_composite_curves.c b/source/blender/nodes/composite/nodes/node_composite_curves.c index 1948709ec84..a1999ec8887 100644 --- a/source/blender/nodes/composite/nodes/node_composite_curves.c +++ b/source/blender/nodes/composite/nodes/node_composite_curves.c @@ -36,7 +36,7 @@ /* **************** CURVE Time ******************** */ /* custom1 = sfra, custom2 = efra */ -static bNodeSocketTemplate cmp_node_time_out[]= { +static bNodeSocketTemplate cmp_node_time_out[] = { { SOCK_FLOAT, 0, N_("Fac")}, { -1, 0, "" } }; @@ -55,7 +55,7 @@ static void node_composit_exec_curves_time(void *data, bNode *node, bNodeStack * curvemapping_initialize(node->storage); fac = curvemapping_evaluateF(node->storage, 0, fac); - out[0]->vec[0]= CLAMPIS(fac, 0.0f, 1.0f); + out[0]->vec[0] = CLAMPIS(fac, 0.0f, 1.0f); } #endif /* WITH_COMPOSITOR_LEGACY */ @@ -86,12 +86,12 @@ void register_node_type_cmp_curve_time(bNodeTreeType *ttype) /* **************** CURVE VEC ******************** */ -static bNodeSocketTemplate cmp_node_curve_vec_in[]= { +static bNodeSocketTemplate cmp_node_curve_vec_in[] = { { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_curve_vec_out[]= { +static bNodeSocketTemplate cmp_node_curve_vec_out[] = { { SOCK_VECTOR, 0, N_("Vector")}, { -1, 0, "" } }; @@ -132,7 +132,7 @@ void register_node_type_cmp_curve_vec(bNodeTreeType *ttype) /* **************** CURVE RGB ******************** */ -static bNodeSocketTemplate cmp_node_curve_rgb_in[]= { +static bNodeSocketTemplate cmp_node_curve_rgb_in[] = { { SOCK_FLOAT, 1, N_("Fac"), 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_FACTOR}, { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { SOCK_RGBA, 1, N_("Black Level"), 0.0f, 0.0f, 0.0f, 1.0f}, @@ -140,7 +140,7 @@ static bNodeSocketTemplate cmp_node_curve_rgb_in[]= { { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_curve_rgb_out[]= { +static bNodeSocketTemplate cmp_node_curve_rgb_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; @@ -151,7 +151,7 @@ static void do_curves(bNode *node, float *out, float *in) { curvemapping_initialize(node->storage); curvemapping_evaluate_premulRGBF(node->storage, out, in); - out[3]= in[3]; + out[3] = in[3]; } static void do_curves_fac(bNode *node, float *out, float *in, float *fac) @@ -166,11 +166,11 @@ static void do_curves_fac(bNode *node, float *out, float *in, float *fac) else { float col[4], mfac= 1.0f-*fac; curvemapping_evaluate_premulRGBF(node->storage, col, in); - out[0]= mfac*in[0] + *fac*col[0]; - out[1]= mfac*in[1] + *fac*col[1]; - out[2]= mfac*in[2] + *fac*col[2]; + out[0] = mfac*in[0] + *fac*col[0]; + out[1] = mfac*in[1] + *fac*col[1]; + out[2] = mfac*in[2] + *fac*col[2]; } - out[3]= in[3]; + out[3] = in[3]; } static void node_composit_exec_curve_rgb(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) diff --git a/source/blender/nodes/composite/nodes/node_composite_defocus.c b/source/blender/nodes/composite/nodes/node_composite_defocus.c index 1a9852264bf..27ce0f7c4a7 100644 --- a/source/blender/nodes/composite/nodes/node_composite_defocus.c +++ b/source/blender/nodes/composite/nodes/node_composite_defocus.c @@ -34,12 +34,12 @@ #include /* ************ qdn: Defocus node ****************** */ -static bNodeSocketTemplate cmp_node_defocus_in[]= { +static bNodeSocketTemplate cmp_node_defocus_in[] = { { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Z"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_defocus_out[]= { +static bNodeSocketTemplate cmp_node_defocus_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; @@ -338,7 +338,7 @@ static void defocus_blur(bNode *node, CompBuf *new, CompBuf *img, CompBuf *zbuf, // fast blur... // bug #6656 part 1, probably when previous node_composite.c was split into separate files, it was not properly updated // to include recent cvs commits (well, at least not defocus node), so this part was missing... - wt = minf(nqd->maxblur, aperture * 128.0f); + wt = min_ff(nqd->maxblur, aperture * 128.0f); IIR_gauss_single(crad, wt); IIR_gauss_single(wts, wt); @@ -589,8 +589,8 @@ static void defocus_blur(bNode *node, CompBuf *new, CompBuf *img, CompBuf *zbuf, // n-agonal int ov, nv; float mind, maxd, lwt; - ys = maxi((int)floor(bkh_b[2] * ct_crad + y), 0); - ye = mini((int)ceil(bkh_b[3] * ct_crad + y), new->y - 1); + ys = max_ii((int)floor(bkh_b[2] * ct_crad + y), 0); + ye = min_ii((int)ceil(bkh_b[3] * ct_crad + y), new->y - 1); for (sy=ys; sy<=ye; sy++) { float fxs = 1e10f, fxe = -1e10f; float yf = (sy - y)/ct_crad; @@ -861,7 +861,7 @@ static void node_composit_exec_defocus(void *UNUSED(data), bNode *node, bNodeSta if (node->exec & NODE_BREAK) { free_compbuf(new); new= NULL; - } + } out[0]->data = new; if (zbuf_use && (zbuf_use != zbuf)) free_compbuf(zbuf_use); } diff --git a/source/blender/nodes/composite/nodes/node_composite_despeckle.c b/source/blender/nodes/composite/nodes/node_composite_despeckle.c index 21b703dc9a8..9d47e4bc276 100644 --- a/source/blender/nodes/composite/nodes/node_composite_despeckle.c +++ b/source/blender/nodes/composite/nodes/node_composite_despeckle.c @@ -32,12 +32,12 @@ #include "node_composite_util.h" /* **************** FILTER ******************** */ -static bNodeSocketTemplate cmp_node_despeckle_in[]= { +static bNodeSocketTemplate cmp_node_despeckle_in[] = { { SOCK_FLOAT, 1, N_("Fac"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_despeckle_out[]= { +static bNodeSocketTemplate cmp_node_despeckle_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/composite/nodes/node_composite_diffMatte.c b/source/blender/nodes/composite/nodes/node_composite_diffMatte.c index ed43baef420..014b72d3c60 100644 --- a/source/blender/nodes/composite/nodes/node_composite_diffMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_diffMatte.c @@ -33,13 +33,13 @@ #include "node_composite_util.h" /* ******************* channel Difference Matte ********************************* */ -static bNodeSocketTemplate cmp_node_diff_matte_in[]={ +static bNodeSocketTemplate cmp_node_diff_matte_in[] = { {SOCK_RGBA, 1, N_("Image 1"), 1.0f, 1.0f, 1.0f, 1.0f}, {SOCK_RGBA, 1, N_("Image 2"), 1.0f, 1.0f, 1.0f, 1.0f}, {-1, 0, ""} }; -static bNodeSocketTemplate cmp_node_diff_matte_out[]={ +static bNodeSocketTemplate cmp_node_diff_matte_out[] = { {SOCK_RGBA, 0, N_("Image")}, {SOCK_FLOAT, 0, N_("Matte")}, {-1, 0, ""} @@ -76,7 +76,7 @@ static void do_diff_matte(bNode *node, float *outColor, float *inColor1, float * } /*only change if more transparent than either image */ - maxInputAlpha=maxf(inColor1[3], inColor2[3]); + maxInputAlpha=max_ff(inColor1[3], inColor2[3]); if (alpha < maxInputAlpha) { /*clamp*/ if (alpha < 0.0f) alpha = 0.0f; diff --git a/source/blender/nodes/composite/nodes/node_composite_dilate.c b/source/blender/nodes/composite/nodes/node_composite_dilate.c index f53c64b990a..9787c9f7145 100644 --- a/source/blender/nodes/composite/nodes/node_composite_dilate.c +++ b/source/blender/nodes/composite/nodes/node_composite_dilate.c @@ -54,28 +54,28 @@ static void morpho_dilate(CompBuf *cbuf) for (y = 0; y < cbuf->y; y++) { for (x = 0; x < cbuf->x - 1; x++) { p = rectf + cbuf->x * y + x; - *p = maxf(*p, *(p + 1)); + *p = max_ff(*p, *(p + 1)); } } for (y = 0; y < cbuf->y; y++) { for (x = cbuf->x - 1; x >= 1; x--) { p = rectf + cbuf->x * y + x; - *p = maxf(*p, *(p - 1)); + *p = max_ff(*p, *(p - 1)); } } for (x = 0; x < cbuf->x; x++) { for (y = 0; y < cbuf->y - 1; y++) { p = rectf + cbuf->x * y + x; - *p = maxf(*p, *(p + cbuf->x)); + *p = max_ff(*p, *(p + cbuf->x)); } } for (x = 0; x < cbuf->x; x++) { for (y = cbuf->y - 1; y >= 1; y--) { p = rectf + cbuf->x * y + x; - *p = maxf(*p, *(p - cbuf->x)); + *p = max_ff(*p, *(p - cbuf->x)); } } } @@ -88,28 +88,28 @@ static void morpho_erode(CompBuf *cbuf) for (y = 0; y < cbuf->y; y++) { for (x = 0; x < cbuf->x - 1; x++) { p = rectf + cbuf->x * y + x; - *p = minf(*p, *(p + 1)); + *p = min_ff(*p, *(p + 1)); } } for (y = 0; y < cbuf->y; y++) { for (x = cbuf->x - 1; x >= 1; x--) { p = rectf + cbuf->x * y + x; - *p = minf(*p, *(p - 1)); + *p = min_ff(*p, *(p - 1)); } } for (x = 0; x < cbuf->x; x++) { for (y = 0; y < cbuf->y - 1; y++) { p = rectf + cbuf->x * y + x; - *p = minf(*p, *(p + cbuf->x)); + *p = min_ff(*p, *(p + cbuf->x)); } } for (x = 0; x < cbuf->x; x++) { for (y = cbuf->y - 1; y >= 1; y--) { p = rectf + cbuf->x * y + x; - *p = minf(*p, *(p - cbuf->x)); + *p = min_ff(*p, *(p - cbuf->x)); } } diff --git a/source/blender/nodes/composite/nodes/node_composite_directionalblur.c b/source/blender/nodes/composite/nodes/node_composite_directionalblur.c index 2878d303632..a343315264d 100644 --- a/source/blender/nodes/composite/nodes/node_composite_directionalblur.c +++ b/source/blender/nodes/composite/nodes/node_composite_directionalblur.c @@ -65,7 +65,7 @@ static CompBuf *dblur(bNode *node, CompBuf *img, int iterations, int wrap, center_y_pix = center_y * img->y; tx = itsc * D * cosf(a); - ty = -itsc *D *sinf(a); + ty = -itsc * D * sinf(a); sc = itsc * zoom; rot = itsc * spin; diff --git a/source/blender/nodes/composite/nodes/node_composite_displace.c b/source/blender/nodes/composite/nodes/node_composite_displace.c index 51ccc2a4d39..c07ad0a0c97 100644 --- a/source/blender/nodes/composite/nodes/node_composite_displace.c +++ b/source/blender/nodes/composite/nodes/node_composite_displace.c @@ -35,14 +35,14 @@ /* **************** Displace ******************** */ -static bNodeSocketTemplate cmp_node_displace_in[]= { +static bNodeSocketTemplate cmp_node_displace_in[] = { { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { SOCK_VECTOR, 1, N_("Vector"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_TRANSLATION}, { SOCK_FLOAT, 1, N_("X Scale"), 0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f, PROP_FACTOR}, { SOCK_FLOAT, 1, N_("Y Scale"), 0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f, PROP_FACTOR}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_displace_out[]= { +static bNodeSocketTemplate cmp_node_displace_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; @@ -113,8 +113,8 @@ static void do_displace(bNode *node, CompBuf *stackbuf, CompBuf *cbuf, CompBuf * dxt = p_dx - d_dx; dyt = p_dy - d_dy; - dxt = signf(dxt)*maxf(fabsf(dxt), DISPLACE_EPSILON)/(float)stackbuf->x; - dyt = signf(dyt)*maxf(fabsf(dyt), DISPLACE_EPSILON)/(float)stackbuf->y; + dxt = signf(dxt)*max_ff(fabsf(dxt), DISPLACE_EPSILON)/(float)stackbuf->x; + dyt = signf(dyt)*max_ff(fabsf(dyt), DISPLACE_EPSILON)/(float)stackbuf->y; ibuf_sample(ibuf, u, v, dxt, dyt, col); qd_setPixel(stackbuf, x, y, col); diff --git a/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c b/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c index 7a101ff43b5..7e605865cd2 100644 --- a/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c @@ -33,13 +33,13 @@ #include "node_composite_util.h" /* ******************* channel Distance Matte ********************************* */ -static bNodeSocketTemplate cmp_node_distance_matte_in[]={ +static bNodeSocketTemplate cmp_node_distance_matte_in[] = { {SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, {SOCK_RGBA, 1, N_("Key Color"), 1.0f, 1.0f, 1.0f, 1.0f}, {-1, 0, ""} }; -static bNodeSocketTemplate cmp_node_distance_matte_out[]={ +static bNodeSocketTemplate cmp_node_distance_matte_out[] = { {SOCK_RGBA, 0, N_("Image")}, {SOCK_FLOAT, 0, N_("Matte")}, {-1, 0, ""} @@ -159,9 +159,9 @@ static void node_composit_exec_distance_matte(void *data, bNode *node, bNodeStac workbuf=dupalloc_compbuf(inbuf); /*use the input color*/ - c->key[0]= in[1]->vec[0]; - c->key[1]= in[1]->vec[1]; - c->key[2]= in[1]->vec[2]; + c->key[0] = in[1]->vec[0]; + c->key[1] = in[1]->vec[1]; + c->key[2] = in[1]->vec[2]; /* work in RGB color space */ if (c->channel == 1) { diff --git a/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c b/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c index 63a54efea74..3c1e3ee443e 100644 --- a/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c +++ b/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c @@ -32,12 +32,12 @@ /* **************** Double Edge Mask ******************** */ -static bNodeSocketTemplate cmp_node_doubleedgemask_in[]= { +static bNodeSocketTemplate cmp_node_doubleedgemask_in[] = { { SOCK_FLOAT, 1, "Inner Mask", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f, PROP_NONE}, // inner mask socket definition { SOCK_FLOAT, 1, "Outer Mask", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f, PROP_NONE}, // outer mask socket definition { -1, 0, "" } // input socket array terminator }; -static bNodeSocketTemplate cmp_node_doubleedgemask_out[]= { +static bNodeSocketTemplate cmp_node_doubleedgemask_out[] = { { SOCK_FLOAT, 0, "Mask"}, // output socket definition { -1, 0, "" } // output socket array terminator }; diff --git a/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c b/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c index a97322a17c0..761b0b13f11 100644 --- a/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c +++ b/source/blender/nodes/composite/nodes/node_composite_ellipsemask.c @@ -1,6 +1,4 @@ /* - * $Id: CMP_math.c 36271 2011-04-21 13:11:51Z campbellbarton $ - * * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -35,15 +33,15 @@ #include "../node_composite_util.h" /* **************** SCALAR MATH ******************** */ -static bNodeSocketTemplate cmp_node_ellipsemask_in[]= { +static bNodeSocketTemplate cmp_node_ellipsemask_in[] = { { SOCK_FLOAT, 1, N_("Mask"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Value"), 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, - { -1, 0, "" } + { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_ellipsemask_out[]= { +static bNodeSocketTemplate cmp_node_ellipsemask_out[] = { { SOCK_FLOAT, 0, N_("Mask"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, - { -1, 0, "" } + { -1, 0, "" } }; static void node_composit_init_ellipsemask(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) diff --git a/source/blender/nodes/composite/nodes/node_composite_filter.c b/source/blender/nodes/composite/nodes/node_composite_filter.c index 0b12c03682b..a27116ab077 100644 --- a/source/blender/nodes/composite/nodes/node_composite_filter.c +++ b/source/blender/nodes/composite/nodes/node_composite_filter.c @@ -33,12 +33,12 @@ #include "node_composite_util.h" /* **************** FILTER ******************** */ -static bNodeSocketTemplate cmp_node_filter_in[]= { +static bNodeSocketTemplate cmp_node_filter_in[] = { { SOCK_FLOAT, 1, N_("Fac"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_filter_out[]= { +static bNodeSocketTemplate cmp_node_filter_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; @@ -73,10 +73,10 @@ static void do_filter_edge(CompBuf *out, CompBuf *in, float *filter, float fac) for (c=0; c<3; c++) { f1= filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8]; f2= filter[0]*row1[0] + filter[3]*row1[4] + filter[6]*row1[8] + filter[1]*row2[0] + filter[4]*row2[4] + filter[7]*row2[8] + filter[2]*row3[0] + filter[5]*row3[4] + filter[8]*row3[8]; - fp[0]= mfac*row2[4] + fac*sqrt(f1*f1 + f2*f2); + fp[0] = mfac*row2[4] + fac*sqrt(f1*f1 + f2*f2); fp++; row1++; row2++; row3++; } - fp[0]= row2[4]; + fp[0] = row2[4]; /* no alpha... will clear it completely */ fp++; row1++; row2++; row3++; } @@ -87,7 +87,7 @@ static void do_filter_edge(CompBuf *out, CompBuf *in, float *filter, float fac) for (x=2; xrect + pixlen*(y)*rowlen; if (pixlen==1) { - fp[0]= row2[0]; + fp[0] = row2[0]; fp+= 1; for (x=2; xhasoutput==0) return; diff --git a/source/blender/nodes/composite/nodes/node_composite_flip.c b/source/blender/nodes/composite/nodes/node_composite_flip.c index 147e7591af7..4aa98d173e7 100644 --- a/source/blender/nodes/composite/nodes/node_composite_flip.c +++ b/source/blender/nodes/composite/nodes/node_composite_flip.c @@ -33,12 +33,12 @@ #include "node_composite_util.h" /* **************** Flip ******************** */ -static bNodeSocketTemplate cmp_node_flip_in[]= { +static bNodeSocketTemplate cmp_node_flip_in[] = { { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_flip_out[]= { +static bNodeSocketTemplate cmp_node_flip_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; @@ -75,7 +75,7 @@ static void node_composit_exec_flip(void *UNUSED(data), bNode *node, bNodeStack outfp += (src_width-1)*src_pix; for (x=0; xval; hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col+1, col+2); - out[0]= mfac*in[0] + *fac*col[0]; - out[1]= mfac*in[1] + *fac*col[1]; - out[2]= mfac*in[2] + *fac*col[2]; - out[3]= in[3]; + out[0] = mfac*in[0] + *fac*col[0]; + out[1] = mfac*in[1] + *fac*col[1]; + out[2] = mfac*in[2] + *fac*col[2]; + out[3] = in[3]; } else { copy_v4_v4(out, in); @@ -89,7 +89,7 @@ static void node_composit_exec_hue_sat(void *UNUSED(data), bNode *node, bNodeSta out[0]->data= stackbuf; - /* get rid of intermediary cbuf if it's extra */ + /* get rid of intermediary cbuf if it's extra */ if (stackbuf!=cbuf) free_compbuf(cbuf); } diff --git a/source/blender/nodes/composite/nodes/node_composite_huecorrect.c b/source/blender/nodes/composite/nodes/node_composite_huecorrect.c index 42077cd5c06..f751dbea8d2 100644 --- a/source/blender/nodes/composite/nodes/node_composite_huecorrect.c +++ b/source/blender/nodes/composite/nodes/node_composite_huecorrect.c @@ -32,13 +32,13 @@ #include "node_composite_util.h" -static bNodeSocketTemplate cmp_node_huecorrect_in[]= { +static bNodeSocketTemplate cmp_node_huecorrect_in[] = { { SOCK_FLOAT, 1, N_("Fac"), 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_huecorrect_out[]= { +static bNodeSocketTemplate cmp_node_huecorrect_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; @@ -71,7 +71,7 @@ static void do_huecorrect(bNode *node, float *out, float *in) /* convert back to rgb */ hsv_to_rgb(hsv[0], hsv[1], hsv[2], out, out+1, out+2); - out[3]= in[3]; + out[3] = in[3]; } static void do_huecorrect_fac(bNode *node, float *out, float *in, float *fac) @@ -101,10 +101,10 @@ static void do_huecorrect_fac(bNode *node, float *out, float *in, float *fac) /* convert back to rgb */ hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2); - out[0]= mfac*in[0] + *fac*rgb[0]; - out[1]= mfac*in[1] + *fac*rgb[1]; - out[2]= mfac*in[2] + *fac*rgb[2]; - out[3]= in[3]; + out[0] = mfac*in[0] + *fac*rgb[0]; + out[1] = mfac*in[1] + *fac*rgb[1]; + out[2] = mfac*in[2] + *fac*rgb[2]; + out[3] = in[3]; } static void node_composit_exec_huecorrect(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) diff --git a/source/blender/nodes/composite/nodes/node_composite_idMask.c b/source/blender/nodes/composite/nodes/node_composite_idMask.c index 31a3a765ebe..ef0c5021192 100644 --- a/source/blender/nodes/composite/nodes/node_composite_idMask.c +++ b/source/blender/nodes/composite/nodes/node_composite_idMask.c @@ -35,11 +35,11 @@ /* **************** ID Mask ******************** */ -static bNodeSocketTemplate cmp_node_idmask_in[]= { +static bNodeSocketTemplate cmp_node_idmask_in[] = { { SOCK_FLOAT, 1, N_("ID value"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_idmask_out[]= { +static bNodeSocketTemplate cmp_node_idmask_out[] = { { SOCK_FLOAT, 0, N_("Alpha")}, { -1, 0, "" } }; @@ -56,14 +56,14 @@ static void do_idmask(CompBuf *stackbuf, CompBuf *cbuf, float idnr) rect= cbuf->rect; for (x= cbuf->x*cbuf->y - 1; x>=0; x--) if (rect[x]==idnr) - abuf[x]= 255; + abuf[x] = 255; antialias_tagbuf(cbuf->x, cbuf->y, abuf); rect= stackbuf->rect; for (x= cbuf->x*cbuf->y - 1; x>=0; x--) if (abuf[x]>1) - rect[x]= (1.0f/255.0f)*(float)abuf[x]; + rect[x] = (1.0f/255.0f)*(float)abuf[x]; MEM_freeN(abuf); } @@ -78,7 +78,7 @@ static void do_idmask_fsa(CompBuf *stackbuf, CompBuf *cbuf, float idnr) rs= stackbuf->rect; for (x= cbuf->x*cbuf->y - 1; x>=0; x--) if (rect[x]==idnr) - rs[x]= 1.0f; + rs[x] = 1.0f; } diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 9f3874560ac..150382c1f8f 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -34,7 +34,7 @@ /* **************** IMAGE (and RenderResult, multilayer image) ******************** */ -static bNodeSocketTemplate cmp_node_rlayers_out[]= { +static bNodeSocketTemplate cmp_node_rlayers_out[] = { { SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Z"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, @@ -505,7 +505,7 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSE generate_preview(data, node, stackbuf); } } - } + } } #endif /* WITH_COMPOSITOR_LEGACY */ diff --git a/source/blender/nodes/composite/nodes/node_composite_invert.c b/source/blender/nodes/composite/nodes/node_composite_invert.c index b0e656b173b..2db6e42f603 100644 --- a/source/blender/nodes/composite/nodes/node_composite_invert.c +++ b/source/blender/nodes/composite/nodes/node_composite_invert.c @@ -32,15 +32,15 @@ #include "node_composite_util.h" /* **************** INVERT ******************** */ -static bNodeSocketTemplate cmp_node_invert_in[]= { - { SOCK_FLOAT, 1, N_("Fac"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - { SOCK_RGBA, 1, N_("Color"), 1.0f, 1.0f, 1.0f, 1.0f}, - { -1, 0, "" } +static bNodeSocketTemplate cmp_node_invert_in[] = { + { SOCK_FLOAT, 1, N_("Fac"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_RGBA, 1, N_("Color"), 1.0f, 1.0f, 1.0f, 1.0f}, + { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_invert_out[]= { - { SOCK_RGBA, 0, N_("Color")}, - { -1, 0, "" } +static bNodeSocketTemplate cmp_node_invert_out[] = { + { SOCK_RGBA, 0, N_("Color")}, + { -1, 0, "" } }; #ifdef WITH_COMPOSITOR_LEGACY diff --git a/source/blender/nodes/composite/nodes/node_composite_lensdist.c b/source/blender/nodes/composite/nodes/node_composite_lensdist.c index a4983cce8b8..c3f64f0eacb 100644 --- a/source/blender/nodes/composite/nodes/node_composite_lensdist.c +++ b/source/blender/nodes/composite/nodes/node_composite_lensdist.c @@ -32,13 +32,13 @@ #include "node_composite_util.h" -static bNodeSocketTemplate cmp_node_lensdist_in[]= { +static bNodeSocketTemplate cmp_node_lensdist_in[] = { { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Distort"), 0.f, 0.f, 0.f, 0.f, -0.999f, 1.f, PROP_NONE}, { SOCK_FLOAT, 1, N_("Dispersion"), 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, PROP_NONE}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_lensdist_out[]= { +static bNodeSocketTemplate cmp_node_lensdist_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; @@ -74,7 +74,7 @@ static void lensDistort(CompBuf *dst, CompBuf *src, float kr, float kg, float kb qd_getPixelLerpChan(tsrc, (u*dst->x - kr) - 0.5f, v*dst->y - 0.5f, 2, colp[x]+2); /* set alpha */ - colp[x][3]= 1.0f; + colp[x][3] = 1.0f; } } free_compbuf(tsrc); @@ -159,7 +159,7 @@ static void lensDistort(CompBuf *dst, CompBuf *src, float kr, float kg, float kb if (db) colp[x][2] = 2.f*tc[2] / (float)db; /* set alpha */ - colp[x][3]= 1.0f; + colp[x][3] = 1.0f; } } } diff --git a/source/blender/nodes/composite/nodes/node_composite_levels.c b/source/blender/nodes/composite/nodes/node_composite_levels.c index 601516c5bb0..57d94d6cb4d 100644 --- a/source/blender/nodes/composite/nodes/node_composite_levels.c +++ b/source/blender/nodes/composite/nodes/node_composite_levels.c @@ -34,12 +34,12 @@ /* **************** LEVELS ******************** */ -static bNodeSocketTemplate cmp_node_view_levels_in[]= { +static bNodeSocketTemplate cmp_node_view_levels_in[] = { { SOCK_RGBA, 1, N_("Image"), 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_view_levels_out[]={ +static bNodeSocketTemplate cmp_node_view_levels_out[] = { {SOCK_FLOAT, 0, N_("Mean")}, {SOCK_FLOAT, 0, N_("Std Dev")}, {-1, 0, ""} @@ -101,7 +101,7 @@ static void fill_bins(bNode *node, CompBuf* in, int* bins) bins[ivalue]+=1; } /*end if alpha */ } - } + } } static float brightness_mean(bNode *node, CompBuf* in) @@ -275,8 +275,8 @@ static void node_composit_exec_view_levels(void *data, bNode *node, bNodeStack * if (in[0]->hasinput==0) return; if (in[0]->data==NULL) return; - histogram=alloc_compbuf(256, 256, CB_RGBA, 1); - cbuf=typecheck_compbuf(in[0]->data, CB_RGBA); + histogram=alloc_compbuf(256, 256, CB_RGBA, 1); + cbuf=typecheck_compbuf(in[0]->data, CB_RGBA); /*initalize bins*/ for (x=0; x<256; x++) { @@ -300,9 +300,9 @@ static void node_composit_exec_view_levels(void *data, bNode *node, bNodeStack * #endif if (out[0]->hasoutput) - out[0]->vec[0]= mean; + out[0]->vec[0] = mean; if (out[1]->hasoutput) - out[1]->vec[0]= std_dev; + out[1]->vec[0] = std_dev; generate_preview(data, node, histogram); diff --git a/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c b/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c index 61cd4493f39..ed232933139 100644 --- a/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c @@ -34,12 +34,12 @@ /* ******************* Luma Matte Node ********************************* */ -static bNodeSocketTemplate cmp_node_luma_matte_in[]={ +static bNodeSocketTemplate cmp_node_luma_matte_in[] = { {SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, {-1, 0, ""} }; -static bNodeSocketTemplate cmp_node_luma_matte_out[]={ +static bNodeSocketTemplate cmp_node_luma_matte_out[] = { {SOCK_RGBA, 0, N_("Image")}, {SOCK_FLOAT, 0, N_("Matte")}, {-1, 0, ""} diff --git a/source/blender/nodes/composite/nodes/node_composite_mapUV.c b/source/blender/nodes/composite/nodes/node_composite_mapUV.c index 04d2eaff4f4..40092a84367 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mapUV.c +++ b/source/blender/nodes/composite/nodes/node_composite_mapUV.c @@ -34,12 +34,12 @@ /* **************** Map UV ******************** */ -static bNodeSocketTemplate cmp_node_mapuv_in[]= { +static bNodeSocketTemplate cmp_node_mapuv_in[] = { { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { SOCK_VECTOR, 1, N_("UV"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_mapuv_out[]= { +static bNodeSocketTemplate cmp_node_mapuv_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; @@ -135,7 +135,7 @@ static void do_mapuv(CompBuf *stackbuf, CompBuf *cbuf, CompBuf *uvbuf, float thr } } - IMB_freeImBuf(ibuf); + IMB_freeImBuf(ibuf); } diff --git a/source/blender/nodes/composite/nodes/node_composite_mapValue.c b/source/blender/nodes/composite/nodes/node_composite_mapValue.c index be69c11b35f..677d5bd5013 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mapValue.c +++ b/source/blender/nodes/composite/nodes/node_composite_mapValue.c @@ -33,11 +33,11 @@ #include "node_composite_util.h" /* **************** MAP VALUE ******************** */ -static bNodeSocketTemplate cmp_node_map_value_in[]= { +static bNodeSocketTemplate cmp_node_map_value_in[] = { { SOCK_FLOAT, 1, N_("Value"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_map_value_out[]= { +static bNodeSocketTemplate cmp_node_map_value_out[] = { { SOCK_FLOAT, 0, N_("Value")}, { -1, 0, "" } }; @@ -48,13 +48,13 @@ static void do_map_value(bNode *node, float *out, float *src) { TexMapping *texmap= node->storage; - out[0]= (src[0] + texmap->loc[0])*texmap->size[0]; + out[0] = (src[0] + texmap->loc[0])*texmap->size[0]; if (texmap->flag & TEXMAP_CLIP_MIN) if (out[0]min[0]) - out[0]= texmap->min[0]; + out[0] = texmap->min[0]; if (texmap->flag & TEXMAP_CLIP_MAX) if (out[0]>texmap->max[0]) - out[0]= texmap->max[0]; + out[0] = texmap->max[0]; } static void node_composit_exec_map_value(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) diff --git a/source/blender/nodes/composite/nodes/node_composite_math.c b/source/blender/nodes/composite/nodes/node_composite_math.c index 1bddfe0852a..c99e12a95b9 100644 --- a/source/blender/nodes/composite/nodes/node_composite_math.c +++ b/source/blender/nodes/composite/nodes/node_composite_math.c @@ -33,15 +33,15 @@ #include "node_composite_util.h" /* **************** SCALAR MATH ******************** */ -static bNodeSocketTemplate cmp_node_math_in[]= { - { SOCK_FLOAT, 1, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, - { SOCK_FLOAT, 1, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, - { -1, 0, "" } +static bNodeSocketTemplate cmp_node_math_in[] = { + { SOCK_FLOAT, 1, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + { SOCK_FLOAT, 1, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_math_out[]= { - { SOCK_FLOAT, 0, N_("Value")}, - { -1, 0, "" } +static bNodeSocketTemplate cmp_node_math_out[] = { + { SOCK_FLOAT, 0, N_("Value")}, + { -1, 0, "" } }; #ifdef WITH_COMPOSITOR_LEGACY @@ -50,63 +50,63 @@ static void do_math(bNode *node, float *out, float *in, float *in2) { switch (node->custom1) { case 0: /* Add */ - out[0]= in[0] + in2[0]; + out[0] = in[0] + in2[0]; break; case 1: /* Subtract */ - out[0]= in[0] - in2[0]; + out[0] = in[0] - in2[0]; break; case 2: /* Multiply */ - out[0]= in[0] * in2[0]; + out[0] = in[0] * in2[0]; break; case 3: /* Divide */ { if (in2[0]==0) /* We don't want to divide by zero. */ - out[0]= 0.0; + out[0] = 0.0; else - out[0]= in[0] / in2[0]; + out[0] = in[0] / in2[0]; } break; case 4: /* Sine */ - out[0]= sin(in[0]); + out[0] = sin(in[0]); break; case 5: /* Cosine */ - out[0]= cos(in[0]); + out[0] = cos(in[0]); break; case 6: /* Tangent */ - out[0]= tan(in[0]); + out[0] = tan(in[0]); break; case 7: /* Arc-Sine */ { /* Can't do the impossible... */ if (in[0] <= 1 && in[0] >= -1 ) - out[0]= asin(in[0]); + out[0] = asin(in[0]); else - out[0]= 0.0; + out[0] = 0.0; } break; case 8: /* Arc-Cosine */ { /* Can't do the impossible... */ if ( in[0] <= 1 && in[0] >= -1 ) - out[0]= acos(in[0]); + out[0] = acos(in[0]); else - out[0]= 0.0; + out[0] = 0.0; } break; case 9: /* Arc-Tangent */ - out[0]= atan(in[0]); + out[0] = atan(in[0]); break; case 10: /* Power */ { /* Only raise negative numbers by full integers */ if ( in[0] >= 0 ) { - out[0]= pow(in[0], in2[0]); + out[0] = pow(in[0], in2[0]); } else { float y_mod_1 = fmod(in2[0], 1); /* if input value is not nearly an integer, fall back to zero, nicer than straight rounding */ if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) { - out[0]= powf(in[0], floorf(in2[0] + 0.5f)); + out[0] = powf(in[0], floorf(in2[0] + 0.5f)); } else { out[0] = 0.0f; @@ -118,50 +118,50 @@ static void do_math(bNode *node, float *out, float *in, float *in2) { /* Don't want any imaginary numbers... */ if ( in[0] > 0 && in2[0] > 0 ) - out[0]= log(in[0]) / log(in2[0]); + out[0] = log(in[0]) / log(in2[0]); else - out[0]= 0.0; + out[0] = 0.0; } break; case 12: /* Minimum */ { if ( in[0] < in2[0] ) - out[0]= in[0]; + out[0] = in[0]; else - out[0]= in2[0]; + out[0] = in2[0]; } break; case 13: /* Maximum */ { if ( in[0] > in2[0] ) - out[0]= in[0]; + out[0] = in[0]; else - out[0]= in2[0]; + out[0] = in2[0]; } break; case 14: /* Round */ { /* round by the second value */ if ( in2[0] != 0.0f ) - out[0]= floorf(in[0] / in2[0] + 0.5f) * in2[0]; + out[0] = floorf(in[0] / in2[0] + 0.5f) * in2[0]; else - out[0]= floorf(in[0] + 0.5f); + out[0] = floorf(in[0] + 0.5f); } break; case 15: /* Less Than */ { if ( in[0] < in2[0] ) - out[0]= 1.0f; + out[0] = 1.0f; else - out[0]= 0.0f; + out[0] = 0.0f; } break; case 16: /* Greater Than */ { if ( in[0] > in2[0] ) - out[0]= 1.0f; + out[0] = 1.0f; else - out[0]= 0.0f; + out[0] = 0.0f; } break; } diff --git a/source/blender/nodes/composite/nodes/node_composite_mixrgb.c b/source/blender/nodes/composite/nodes/node_composite_mixrgb.c index e2c9a5abcb1..5d3ee480612 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mixrgb.c +++ b/source/blender/nodes/composite/nodes/node_composite_mixrgb.c @@ -32,13 +32,13 @@ #include "node_composite_util.h" /* **************** MIX RGB ******************** */ -static bNodeSocketTemplate cmp_node_mix_rgb_in[]= { +static bNodeSocketTemplate cmp_node_mix_rgb_in[] = { { SOCK_FLOAT, 1, N_("Fac"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 5.0f, PROP_FACTOR}, { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_mix_rgb_out[]= { +static bNodeSocketTemplate cmp_node_mix_rgb_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; @@ -55,7 +55,7 @@ static void do_mix_rgb(bNode *node, float *out, float *in1, float *in2, float *f else ramp_blend(node->custom1, col, fac[0], in2); copy_v3_v3(out, col); - out[3]= in1[3]; + out[3] = in1[3]; } static void node_composit_exec_mix_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out) diff --git a/source/blender/nodes/composite/nodes/node_composite_normal.c b/source/blender/nodes/composite/nodes/node_composite_normal.c index 6f1e86e2760..93fd7ca1c1b 100644 --- a/source/blender/nodes/composite/nodes/node_composite_normal.c +++ b/source/blender/nodes/composite/nodes/node_composite_normal.c @@ -34,12 +34,12 @@ /* **************** NORMAL ******************** */ -static bNodeSocketTemplate cmp_node_normal_in[]= { +static bNodeSocketTemplate cmp_node_normal_in[] = { { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_normal_out[]= { +static bNodeSocketTemplate cmp_node_normal_out[] = { { SOCK_VECTOR, 0, N_("Normal")}, { SOCK_FLOAT, 0, N_("Dot")}, { -1, 0, "" } @@ -53,7 +53,7 @@ static void do_normal(bNode *node, float *out, float *in) float *nor= ((bNodeSocketValueVector*)sock->default_value)->value; /* render normals point inside... the widget points outside */ - out[0]= -dot_v3v3(nor, in); + out[0] = -dot_v3v3(nor, in); } /* generates normal, does dot product */ @@ -68,7 +68,7 @@ static void node_composit_exec_normal(void *UNUSED(data), bNode *node, bNodeStac if (in[0]->data==NULL) { copy_v3_v3(out[0]->vec, nor); /* render normals point inside... the widget points outside */ - out[1]->vec[0]= -dot_v3v3(out[0]->vec, in[0]->vec); + out[1]->vec[0] = -dot_v3v3(out[0]->vec, in[0]->vec); } else if (out[1]->hasoutput) { /* make output size of input image */ diff --git a/source/blender/nodes/composite/nodes/node_composite_normalize.c b/source/blender/nodes/composite/nodes/node_composite_normalize.c index 1d2312d8280..19b543dce5d 100644 --- a/source/blender/nodes/composite/nodes/node_composite_normalize.c +++ b/source/blender/nodes/composite/nodes/node_composite_normalize.c @@ -34,11 +34,11 @@ /* **************** NORMALIZE single channel, useful for Z buffer ******************** */ -static bNodeSocketTemplate cmp_node_normalize_in[]= { +static bNodeSocketTemplate cmp_node_normalize_in[] = { { SOCK_FLOAT, 1, N_("Value"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_normalize_out[]= { +static bNodeSocketTemplate cmp_node_normalize_out[] = { { SOCK_FLOAT, 0, N_("Value")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/composite/nodes/node_composite_pixelate.c b/source/blender/nodes/composite/nodes/node_composite_pixelate.c new file mode 100644 index 00000000000..5eac4867a23 --- /dev/null +++ b/source/blender/nodes/composite/nodes/node_composite_pixelate.c @@ -0,0 +1,57 @@ +/* + * ***** 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) 2006 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Jeroen Bakker + * Monique Dewanchand + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/composite/nodes/node_composite_pixelate.c + * \ingroup cmpnodes + */ + + +#include "node_composite_util.h" + + +/* **************** Pixelate ******************** */ + +static bNodeSocketTemplate cmp_node_pixelate_in[] = { + { SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, + { -1, 0, "" } +}; +static bNodeSocketTemplate cmp_node_pixelate_out[] = { + { SOCK_RGBA, 0, N_("Color")}, + { -1, 0, "" } +}; + +void register_node_type_cmp_pixelate(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, CMP_NODE_PIXELATE, "Pixelate", NODE_CLASS_OP_FILTER, NODE_OPTIONS); + node_type_socket_templates(&ntype, cmp_node_pixelate_in, cmp_node_pixelate_out); + node_type_size(&ntype, 130, 100, 130); + + nodeRegisterType(ttype, &ntype); +} diff --git a/source/blender/nodes/composite/nodes/node_composite_premulkey.c b/source/blender/nodes/composite/nodes/node_composite_premulkey.c index d791983b069..7f7b7692b02 100644 --- a/source/blender/nodes/composite/nodes/node_composite_premulkey.c +++ b/source/blender/nodes/composite/nodes/node_composite_premulkey.c @@ -35,11 +35,11 @@ /* **************** Premul and Key Alpha Convert ******************** */ -static bNodeSocketTemplate cmp_node_premulkey_in[]= { +static bNodeSocketTemplate cmp_node_premulkey_in[] = { { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_premulkey_out[]= { +static bNodeSocketTemplate cmp_node_premulkey_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/composite/nodes/node_composite_rgb.c b/source/blender/nodes/composite/nodes/node_composite_rgb.c index 65c1dcdb7bb..54fba650783 100644 --- a/source/blender/nodes/composite/nodes/node_composite_rgb.c +++ b/source/blender/nodes/composite/nodes/node_composite_rgb.c @@ -34,7 +34,7 @@ /* **************** RGB ******************** */ -static bNodeSocketTemplate cmp_node_rgb_out[]= { +static bNodeSocketTemplate cmp_node_rgb_out[] = { { SOCK_RGBA, 0, N_("RGBA"), 0.5f, 0.5f, 0.5f, 1.0f}, { -1, 0, "" } }; diff --git a/source/blender/nodes/composite/nodes/node_composite_rotate.c b/source/blender/nodes/composite/nodes/node_composite_rotate.c index 8968fd5fb3a..9a76764b97e 100644 --- a/source/blender/nodes/composite/nodes/node_composite_rotate.c +++ b/source/blender/nodes/composite/nodes/node_composite_rotate.c @@ -34,12 +34,12 @@ /* **************** Rotate ******************** */ -static bNodeSocketTemplate cmp_node_rotate_in[]= { +static bNodeSocketTemplate cmp_node_rotate_in[] = { { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Degr"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f, PROP_ANGLE}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_rotate_out[]= { +static bNodeSocketTemplate cmp_node_rotate_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c index ebc18cd19eb..f1a75493718 100644 --- a/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c +++ b/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c @@ -34,11 +34,11 @@ /* **************** SEPARATE HSVA ******************** */ -static bNodeSocketTemplate cmp_node_sephsva_in[]= { +static bNodeSocketTemplate cmp_node_sephsva_in[] = { { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_sephsva_out[]= { +static bNodeSocketTemplate cmp_node_sephsva_out[] = { { SOCK_FLOAT, 0, N_("H")}, { SOCK_FLOAT, 0, N_("S")}, { SOCK_FLOAT, 0, N_("V")}, @@ -54,10 +54,10 @@ static void do_sephsva(bNode *UNUSED(node), float *out, float *in) rgb_to_hsv(in[0], in[1], in[2], &h, &s, &v); - out[0]= h; - out[1]= s; - out[2]= v; - out[3]= in[3]; + out[0] = h; + out[1] = s; + out[2] = v; + out[3] = in[3]; } static void node_composit_exec_sephsva(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) @@ -97,7 +97,7 @@ static void node_composit_exec_sephsva(void *UNUSED(data), bNode *node, bNodeSta /*not used anymore */ if (cbuf2!=cbuf) free_compbuf(cbuf2); - free_compbuf(cbuf); + free_compbuf(cbuf); } } @@ -126,7 +126,7 @@ static bNodeSocketTemplate cmp_node_combhsva_in[] = { { SOCK_FLOAT, 1, N_("A"), 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_combhsva_out[]= { +static bNodeSocketTemplate cmp_node_combhsva_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c index 0c989ed3fc6..83b2c731020 100644 --- a/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c +++ b/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c @@ -33,11 +33,11 @@ #include "node_composite_util.h" /* **************** SEPARATE RGBA ******************** */ -static bNodeSocketTemplate cmp_node_seprgba_in[]= { +static bNodeSocketTemplate cmp_node_seprgba_in[] = { { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_seprgba_out[]= { +static bNodeSocketTemplate cmp_node_seprgba_out[] = { { SOCK_FLOAT, 0, N_("R")}, { SOCK_FLOAT, 0, N_("G")}, { SOCK_FLOAT, 0, N_("B")}, @@ -98,14 +98,14 @@ void register_node_type_cmp_seprgba(bNodeTreeType *ttype) /* **************** COMBINE RGBA ******************** */ -static bNodeSocketTemplate cmp_node_combrgba_in[]= { +static bNodeSocketTemplate cmp_node_combrgba_in[] = { { SOCK_FLOAT, 1, N_("R"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, { SOCK_FLOAT, 1, N_("G"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, { SOCK_FLOAT, 1, N_("B"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, { SOCK_FLOAT, 1, N_("A"), 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_combrgba_out[]= { +static bNodeSocketTemplate cmp_node_combrgba_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; @@ -150,7 +150,7 @@ static void node_composit_exec_combrgba(void *UNUSED(data), bNode *node, bNodeSt do_combrgba, CB_VAL, CB_VAL, CB_VAL, CB_VAL); out[0]->data= stackbuf; - } + } } #endif /* WITH_COMPOSITOR_LEGACY */ diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c index ccae7cfe57f..982d674708c 100644 --- a/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c +++ b/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c @@ -34,11 +34,11 @@ /* **************** SEPARATE YCCA ******************** */ -static bNodeSocketTemplate cmp_node_sepycca_in[]= { +static bNodeSocketTemplate cmp_node_sepycca_in[] = { { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_sepycca_out[]= { +static bNodeSocketTemplate cmp_node_sepycca_out[] = { { SOCK_FLOAT, 0, N_("Y")}, { SOCK_FLOAT, 0, N_("Cb")}, { SOCK_FLOAT, 0, N_("Cr")}, @@ -55,10 +55,10 @@ static void do_sepycca_601(bNode *UNUSED(node), float *out, float *in) rgb_to_ycc(in[0], in[1], in[2], &y, &cb, &cr, BLI_YCC_ITU_BT601); /*divided by 255 to normalize for viewing in */ - out[0]= y/255.0f; - out[1]= cb/255.0f; - out[2]= cr/255.0f; - out[3]= in[3]; + out[0] = y/255.0f; + out[1] = cb/255.0f; + out[2] = cr/255.0f; + out[3] = in[3]; } static void do_sepycca_709(bNode *UNUSED(node), float *out, float *in) @@ -68,10 +68,10 @@ static void do_sepycca_709(bNode *UNUSED(node), float *out, float *in) rgb_to_ycc(in[0], in[1], in[2], &y, &cb, &cr, BLI_YCC_ITU_BT709); /*divided by 255 to normalize for viewing in */ - out[0]= y/255.0f; - out[1]= cb/255.0f; - out[2]= cr/255.0f; - out[3]= in[3]; + out[0] = y/255.0f; + out[1] = cb/255.0f; + out[2] = cr/255.0f; + out[3] = in[3]; } static void do_sepycca_jfif(bNode *UNUSED(node), float *out, float *in) @@ -81,10 +81,10 @@ static void do_sepycca_jfif(bNode *UNUSED(node), float *out, float *in) rgb_to_ycc(in[0], in[1], in[2], &y, &cb, &cr, BLI_YCC_JFIF_0_255); /*divided by 255 to normalize for viewing in */ - out[0]= y/255.0f; - out[1]= cb/255.0f; - out[2]= cr/255.0f; - out[3]= in[3]; + out[0] = y/255.0f; + out[1] = cb/255.0f; + out[2] = cr/255.0f; + out[3] = in[3]; } static void node_composit_exec_sepycca(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) @@ -167,14 +167,14 @@ void register_node_type_cmp_sepycca(bNodeTreeType *ttype) /* **************** COMBINE YCCA ******************** */ -static bNodeSocketTemplate cmp_node_combycca_in[]= { +static bNodeSocketTemplate cmp_node_combycca_in[] = { { SOCK_FLOAT, 1, N_("Y"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, { SOCK_FLOAT, 1, N_("Cb"), 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, { SOCK_FLOAT, 1, N_("Cr"), 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, { SOCK_FLOAT, 1, N_("A"), 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_combycca_out[]= { +static bNodeSocketTemplate cmp_node_combycca_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; @@ -296,7 +296,7 @@ static void node_composit_exec_combycca(void *UNUSED(data), bNode *node, bNodeSt } out[0]->data= stackbuf; - } + } } #endif /* WITH_COMPOSITOR_LEGACY */ diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c index 9b8c805b0f0..0a9575971b4 100644 --- a/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c +++ b/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c @@ -34,11 +34,11 @@ /* **************** SEPARATE YUVA ******************** */ -static bNodeSocketTemplate cmp_node_sepyuva_in[]= { +static bNodeSocketTemplate cmp_node_sepyuva_in[] = { { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_sepyuva_out[]= { +static bNodeSocketTemplate cmp_node_sepyuva_out[] = { { SOCK_FLOAT, 0, N_("Y")}, { SOCK_FLOAT, 0, N_("U")}, { SOCK_FLOAT, 0, N_("V")}, @@ -54,10 +54,10 @@ static void do_sepyuva(bNode *UNUSED(node), float *out, float *in) rgb_to_yuv(in[0], in[1], in[2], &y, &u, &v); - out[0]= y; - out[1]= u; - out[2]= v; - out[3]= in[3]; + out[0] = y; + out[1] = u; + out[2] = v; + out[3] = in[3]; } static void node_composit_exec_sepyuva(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) @@ -121,14 +121,14 @@ void register_node_type_cmp_sepyuva(bNodeTreeType *ttype) /* **************** COMBINE YUVA ******************** */ -static bNodeSocketTemplate cmp_node_combyuva_in[]= { +static bNodeSocketTemplate cmp_node_combyuva_in[] = { { SOCK_FLOAT, 1, N_("Y"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, { SOCK_FLOAT, 1, N_("U"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, { SOCK_FLOAT, 1, N_("V"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, { SOCK_FLOAT, 1, N_("A"), 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_combyuva_out[]= { +static bNodeSocketTemplate cmp_node_combyuva_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/composite/nodes/node_composite_setalpha.c b/source/blender/nodes/composite/nodes/node_composite_setalpha.c index 503815b74a0..59c104869fe 100644 --- a/source/blender/nodes/composite/nodes/node_composite_setalpha.c +++ b/source/blender/nodes/composite/nodes/node_composite_setalpha.c @@ -33,12 +33,12 @@ #include "node_composite_util.h" /* **************** SET ALPHA ******************** */ -static bNodeSocketTemplate cmp_node_setalpha_in[]= { +static bNodeSocketTemplate cmp_node_setalpha_in[] = { { SOCK_RGBA, 1, N_("Image"), 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_setalpha_out[]= { +static bNodeSocketTemplate cmp_node_setalpha_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/composite/nodes/node_composite_splitViewer.c b/source/blender/nodes/composite/nodes/node_composite_splitViewer.c index f6811f526f7..73cf039c6df 100644 --- a/source/blender/nodes/composite/nodes/node_composite_splitViewer.c +++ b/source/blender/nodes/composite/nodes/node_composite_splitViewer.c @@ -33,7 +33,7 @@ #include "node_composite_util.h" /* **************** SPLIT VIEWER ******************** */ -static bNodeSocketTemplate cmp_node_splitviewer_in[]= { +static bNodeSocketTemplate cmp_node_splitviewer_in[] = { { SOCK_RGBA, 1, N_("Image"), 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_RGBA, 1, N_("Image"), 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } @@ -167,7 +167,7 @@ void register_node_type_cmp_splitviewer(bNodeTreeType *ttype) #endif /* Do not allow muting for this node. */ - node_type_internal_connect(&ntype, NULL); + node_type_internal_links(&ntype, NULL); nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c index fdf0b38e844..1787e075a14 100644 --- a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c +++ b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c @@ -35,12 +35,12 @@ /* **************** Translate ******************** */ -static bNodeSocketTemplate cmp_node_stabilize2d_in[]= { +static bNodeSocketTemplate cmp_node_stabilize2d_in[] = { { SOCK_RGBA, 1, N_("Image"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_stabilize2d_out[]= { +static bNodeSocketTemplate cmp_node_stabilize2d_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/composite/nodes/node_composite_switch.c b/source/blender/nodes/composite/nodes/node_composite_switch.c index 258fac18c11..7f9127c969f 100644 --- a/source/blender/nodes/composite/nodes/node_composite_switch.c +++ b/source/blender/nodes/composite/nodes/node_composite_switch.c @@ -34,13 +34,13 @@ #include "../node_composite_util.h" /* **************** MIX RGB ******************** */ -static bNodeSocketTemplate cmp_node_switch_in[]= { +static bNodeSocketTemplate cmp_node_switch_in[] = { { SOCK_RGBA, 1, N_("Off"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_RGBA, 1, N_("On"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_switch_out[]= { +static bNodeSocketTemplate cmp_node_switch_out[] = { { SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { -1, 0, "" } }; diff --git a/source/blender/nodes/composite/nodes/node_composite_texture.c b/source/blender/nodes/composite/nodes/node_composite_texture.c index 3fedccd7d12..b6518c48638 100644 --- a/source/blender/nodes/composite/nodes/node_composite_texture.c +++ b/source/blender/nodes/composite/nodes/node_composite_texture.c @@ -33,12 +33,12 @@ #include "node_composite_util.h" /* **************** TEXTURE ******************** */ -static bNodeSocketTemplate cmp_node_texture_in[]= { +static bNodeSocketTemplate cmp_node_texture_in[] = { { SOCK_VECTOR, 1, N_("Offset"), 0.0f, 0.0f, 0.0f, 0.0f, -2.0f, 2.0f, PROP_TRANSLATION}, { SOCK_VECTOR, 1, N_("Scale"), 1.0f, 1.0f, 1.0f, 1.0f, -10.0f, 10.0f, PROP_XYZ}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_texture_out[]= { +static bNodeSocketTemplate cmp_node_texture_out[] = { { SOCK_FLOAT, 0, N_("Value")}, { SOCK_RGBA, 0, N_("Color")}, { -1, 0, "" } @@ -51,28 +51,28 @@ static void texture_procedural(CompBuf *cbuf, float *out, float xco, float yco) { bNode *node= cbuf->node; TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; - float vec[3], *size, nor[3]={0.0f, 0.0f, 0.0f}, col[4]; + float vec[3], *size, nor[3] = {0.0f, 0.0f, 0.0f}, col[4]; int retval, type= cbuf->procedural_type; size= cbuf->procedural_size; - vec[0]= size[0]*(xco + cbuf->procedural_offset[0]); - vec[1]= size[1]*(yco + cbuf->procedural_offset[1]); - vec[2]= size[2]*cbuf->procedural_offset[2]; + vec[0] = size[0]*(xco + cbuf->procedural_offset[0]); + vec[1] = size[1]*(yco + cbuf->procedural_offset[1]); + vec[2] = size[2]*cbuf->procedural_offset[2]; retval= multitex_ext((Tex *)node->id, vec, NULL, NULL, 0, &texres); if (type==CB_VAL) { if (texres.talpha) - col[0]= texres.ta; + col[0] = texres.ta; else - col[0]= texres.tin; + col[0] = texres.tin; } else if (type==CB_RGBA) { if (texres.talpha) - col[3]= texres.ta; + col[3] = texres.ta; else - col[3]= texres.tin; + col[3] = texres.tin; if ((retval & TEX_RGB)) { copy_v3_v3(col, &texres.tr); @@ -81,7 +81,7 @@ static void texture_procedural(CompBuf *cbuf, float *out, float xco, float yco) copy_v3_fl(col, col[3]); } } - else { + else { copy_v3_v3(col, nor); } diff --git a/source/blender/nodes/composite/nodes/node_composite_tonemap.c b/source/blender/nodes/composite/nodes/node_composite_tonemap.c index 5e4efe2f3b1..00b1a5514dc 100644 --- a/source/blender/nodes/composite/nodes/node_composite_tonemap.c +++ b/source/blender/nodes/composite/nodes/node_composite_tonemap.c @@ -32,11 +32,11 @@ #include "node_composite_util.h" -static bNodeSocketTemplate cmp_node_tonemap_in[]= { +static bNodeSocketTemplate cmp_node_tonemap_in[] = { { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_tonemap_out[]= { +static bNodeSocketTemplate cmp_node_tonemap_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/composite/nodes/node_composite_translate.c b/source/blender/nodes/composite/nodes/node_composite_translate.c index 649902ff908..1c2963a2f08 100644 --- a/source/blender/nodes/composite/nodes/node_composite_translate.c +++ b/source/blender/nodes/composite/nodes/node_composite_translate.c @@ -35,13 +35,13 @@ /* **************** Translate ******************** */ -static bNodeSocketTemplate cmp_node_translate_in[]= { +static bNodeSocketTemplate cmp_node_translate_in[] = { { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { SOCK_FLOAT, 1, N_("X"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f, PROP_NONE}, { SOCK_FLOAT, 1, N_("Y"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f, PROP_NONE}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_translate_out[]= { +static bNodeSocketTemplate cmp_node_translate_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/composite/nodes/node_composite_valToRgb.c b/source/blender/nodes/composite/nodes/node_composite_valToRgb.c index 87a776c7bea..5c111998b18 100644 --- a/source/blender/nodes/composite/nodes/node_composite_valToRgb.c +++ b/source/blender/nodes/composite/nodes/node_composite_valToRgb.c @@ -34,11 +34,11 @@ /* **************** VALTORGB ******************** */ -static bNodeSocketTemplate cmp_node_valtorgb_in[]= { +static bNodeSocketTemplate cmp_node_valtorgb_in[] = { { SOCK_FLOAT, 1, N_("Fac"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_valtorgb_out[]= { +static bNodeSocketTemplate cmp_node_valtorgb_out[] = { { SOCK_RGBA, 0, N_("Image")}, { SOCK_FLOAT, 0, N_("Alpha")}, { -1, 0, "" } @@ -106,11 +106,11 @@ void register_node_type_cmp_valtorgb(bNodeTreeType *ttype) /* **************** RGBTOBW ******************** */ -static bNodeSocketTemplate cmp_node_rgbtobw_in[]= { +static bNodeSocketTemplate cmp_node_rgbtobw_in[] = { { SOCK_RGBA, 1, N_("Image"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_rgbtobw_out[]= { +static bNodeSocketTemplate cmp_node_rgbtobw_out[] = { { SOCK_FLOAT, 0, N_("Val"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { -1, 0, "" } }; diff --git a/source/blender/nodes/composite/nodes/node_composite_value.c b/source/blender/nodes/composite/nodes/node_composite_value.c index 63ab4fcb58f..2c65fe6be19 100644 --- a/source/blender/nodes/composite/nodes/node_composite_value.c +++ b/source/blender/nodes/composite/nodes/node_composite_value.c @@ -33,7 +33,7 @@ #include "node_composite_util.h" /* **************** VALUE ******************** */ -static bNodeSocketTemplate cmp_node_value_out[]= { +static bNodeSocketTemplate cmp_node_value_out[] = { /* XXX value nodes use the output sockets for buttons, so we need explicit limits here! */ { SOCK_FLOAT, 0, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, { -1, 0, "" } @@ -56,7 +56,7 @@ static void node_composit_exec_value(void *UNUSED(data), bNode *node, bNodeStack bNodeSocket *sock= node->outputs.first; float val= ((bNodeSocketValueFloat*)sock->default_value)->value; - out[0]->vec[0]= val; + out[0]->vec[0] = val; } #endif /* WITH_COMPOSITOR_LEGACY */ diff --git a/source/blender/nodes/composite/nodes/node_composite_viewer.c b/source/blender/nodes/composite/nodes/node_composite_viewer.c index 6321b1def4d..938f75cf3f5 100644 --- a/source/blender/nodes/composite/nodes/node_composite_viewer.c +++ b/source/blender/nodes/composite/nodes/node_composite_viewer.c @@ -149,7 +149,7 @@ void register_node_type_cmp_viewer(bNodeTreeType *ttype) node_type_exec(&ntype, node_composit_exec_viewer); #endif - node_type_internal_connect(&ntype, NULL); + node_type_internal_links(&ntype, NULL); nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_zcombine.c b/source/blender/nodes/composite/nodes/node_composite_zcombine.c index 3decbe8d230..8e639aaa357 100644 --- a/source/blender/nodes/composite/nodes/node_composite_zcombine.c +++ b/source/blender/nodes/composite/nodes/node_composite_zcombine.c @@ -35,14 +35,14 @@ /* **************** Z COMBINE ******************** */ /* lazy coder note: node->custom2 is abused to send signal */ -static bNodeSocketTemplate cmp_node_zcombine_in[]= { +static bNodeSocketTemplate cmp_node_zcombine_in[] = { { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Z"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 10000.0f, PROP_NONE}, { SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Z"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 10000.0f, PROP_NONE}, { -1, 0, "" } }; -static bNodeSocketTemplate cmp_node_zcombine_out[]= { +static bNodeSocketTemplate cmp_node_zcombine_out[] = { { SOCK_RGBA, 0, N_("Image")}, { SOCK_FLOAT, 0, N_("Z")}, { -1, 0, "" } @@ -60,10 +60,10 @@ static void do_zcombine(bNode *node, float *out, float *src1, float *z1, float * // use alpha in combine operation alpha= src1[3]; malpha= 1.0f - alpha; - out[0]= malpha*src2[0] + alpha*src1[0]; - out[1]= malpha*src2[1] + alpha*src1[1]; - out[2]= malpha*src2[2] + alpha*src1[2]; - out[3]= malpha*src2[3] + alpha*src1[3]; + out[0] = malpha*src2[0] + alpha*src1[0]; + out[1] = malpha*src2[1] + alpha*src1[1]; + out[2] = malpha*src2[2] + alpha*src1[2]; + out[3] = malpha*src2[3] + alpha*src1[3]; } else { // do combination based solely on z value @@ -75,10 +75,10 @@ static void do_zcombine(bNode *node, float *out, float *src1, float *z1, float * // use alpha in combine operation alpha= src2[3]; malpha= 1.0f - alpha; - out[0]= malpha*src1[0] + alpha*src2[0]; - out[1]= malpha*src1[1] + alpha*src2[1]; - out[2]= malpha*src1[2] + alpha*src2[2]; - out[3]= malpha*src1[3] + alpha*src2[3]; + out[0] = malpha*src1[0] + alpha*src2[0]; + out[1] = malpha*src1[1] + alpha*src2[1]; + out[2] = malpha*src1[2] + alpha*src2[2]; + out[3] = malpha*src1[3] + alpha*src2[3]; } else { // do combination based solely on z value @@ -111,20 +111,20 @@ static void do_zcombine_add(bNode *node, float *out, float *col1, float *col2, f malpha= 1.0f - alpha; - out[0]= malpha*col1[0] + alpha*col2[0]; - out[1]= malpha*col1[1] + alpha*col2[1]; - out[2]= malpha*col1[2] + alpha*col2[2]; - out[3]= malpha*col1[3] + alpha*col2[3]; + out[0] = malpha*col1[0] + alpha*col2[0]; + out[1] = malpha*col1[1] + alpha*col2[1]; + out[2] = malpha*col1[2] + alpha*col2[2]; + out[3] = malpha*col1[3] + alpha*col2[3]; } else { alpha= col1[3]; malpha= 1.0f - alpha; - out[0]= malpha*col2[0] + alpha*col1[0]; - out[1]= malpha*col2[1] + alpha*col1[1]; - out[2]= malpha*col2[2] + alpha*col1[2]; - out[3]= malpha*col2[3] + alpha*col1[3]; + out[0] = malpha*col2[0] + alpha*col1[0]; + out[1] = malpha*col2[1] + alpha*col1[1]; + out[2] = malpha*col2[2] + alpha*col1[2]; + out[3] = malpha*col2[3] + alpha*col1[3]; } } else { @@ -132,10 +132,10 @@ static void do_zcombine_add(bNode *node, float *out, float *col1, float *col2, f alpha = *acol; malpha= 1.0f - alpha; - out[0]= malpha*col1[0] + alpha*col2[0]; - out[1]= malpha*col1[1] + alpha*col2[1]; - out[2]= malpha*col1[2] + alpha*col2[2]; - out[3]= malpha*col1[3] + alpha*col2[3]; + out[0] = malpha*col1[0] + alpha*col2[0]; + out[1] = malpha*col1[1] + alpha*col2[1]; + out[2] = malpha*col1[2] + alpha*col2[2]; + out[3] = malpha*col1[3] + alpha*col2[3]; } } @@ -202,8 +202,8 @@ static void node_composit_exec_zcombine(void *data, bNode *node, bNodeStack **in aabuf= MEM_mallocN(cbuf->x*cbuf->y, "aa buf"); fp= mbuf->rect; for (x= cbuf->x*cbuf->y-1; x>=0; x--) - if (fp[x]==0.0f) aabuf[x]= 0; - else aabuf[x]= 255; + if (fp[x]==0.0f) aabuf[x] = 0; + else aabuf[x] = 255; antialias_tagbuf(cbuf->x, cbuf->y, aabuf); @@ -211,7 +211,7 @@ static void node_composit_exec_zcombine(void *data, bNode *node, bNodeStack **in fp= mbuf->rect; for (x= cbuf->x*cbuf->y-1; x>=0; x--) if (aabuf[x]>1) - fp[x]= (1.0f/255.0f)*(float)aabuf[x]; + fp[x] = (1.0f/255.0f)*(float)aabuf[x]; composit3_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[2]->data, in[2]->vec, mbuf, NULL, do_zcombine_add, CB_RGBA, CB_RGBA, CB_VAL); diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c index 59a4d6818c8..86ef8a14c12 100644 --- a/source/blender/nodes/intern/node_common.c +++ b/source/blender/nodes/intern/node_common.c @@ -92,7 +92,7 @@ bNodeSocket *node_group_add_extern_socket(bNodeTree *UNUSED(ntree), ListBase *lb sock->new_sock = NULL; /* group sockets are dynamically added */ - sock->flag |= SOCK_DYNAMIC; + sock->flag |= SOCK_DYNAMIC|SOCK_COLLAPSED; sock->own_index = gsock->own_index; sock->groupsock = gsock; @@ -115,7 +115,7 @@ bNodeSocket *node_group_add_socket(bNodeTree *ngroup, const char *name, int type BLI_strncpy(gsock->name, name, sizeof(gsock->name)); gsock->type = type; /* group sockets are dynamically added */ - gsock->flag |= SOCK_DYNAMIC; + gsock->flag |= SOCK_DYNAMIC|SOCK_COLLAPSED; gsock->next = gsock->prev = NULL; gsock->new_sock = NULL; @@ -223,13 +223,13 @@ bNodeTemplate node_group_template(bNode *node) { bNodeTemplate ntemp; ntemp.type = NODE_GROUP; - ntemp.ngroup = (bNodeTree*)node->id; + ntemp.ngroup = (bNodeTree *)node->id; return ntemp; } void node_group_init(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp) { - node->id = (ID*)ntemp->ngroup; + node->id = (ID *)ntemp->ngroup; /* NB: group socket input/output roles are inverted internally! * Group "inputs" work as outputs in links and vice versa. @@ -354,168 +354,6 @@ static void UNUSED_FUNCTION(node_group_link)(bNodeTree *ntree, bNodeSocket *sock node_group_expose_socket(ntree, sock, in_out); } -/**** For Loop ****/ - -/* Essentially a group node with slightly different behavior. - * The internal tree is executed several times, with each output being re-used - * as an input in the next iteration. For this purpose, input and output socket - * lists are kept identical! - */ - -bNodeTemplate node_forloop_template(bNode *node) -{ - bNodeTemplate ntemp; - ntemp.type = NODE_FORLOOP; - ntemp.ngroup = (bNodeTree*)node->id; - return ntemp; -} - -void node_forloop_init(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp) -{ - bNodeSocket *sock; - - node->id = (ID*)ntemp->ngroup; - - sock = nodeAddSocket(ntree, node, SOCK_IN, "Iterations", SOCK_FLOAT); - node_socket_set_default_value_float(sock->default_value, PROP_UNSIGNED, 1, 0, 10000); - - /* NB: group socket input/output roles are inverted internally! - * Group "inputs" work as outputs in links and vice versa. - */ - if (ntemp->ngroup) { - bNodeSocket *gsock; - for (gsock=ntemp->ngroup->inputs.first; gsock; gsock=gsock->next) - node_group_add_extern_socket(ntree, &node->inputs, SOCK_IN, gsock); - for (gsock=ntemp->ngroup->outputs.first; gsock; gsock=gsock->next) - node_group_add_extern_socket(ntree, &node->outputs, SOCK_OUT, gsock); - } -} - -void node_forloop_init_tree(bNodeTree *ntree) -{ - bNodeSocket *sock; - sock = node_group_add_socket(ntree, "Iteration", SOCK_FLOAT, SOCK_IN); - sock->flag |= SOCK_INTERNAL; -} - -static void loop_sync(bNodeTree *ntree, int sync_in_out) -{ - bNodeSocket *sock, *sync, *nsync, *mirror; - ListBase *sync_lb; - - if (sync_in_out==SOCK_IN) { - sock = ntree->outputs.first; - - sync = ntree->inputs.first; - sync_lb = &ntree->inputs; - } - else { - sock = ntree->inputs.first; - - sync = ntree->outputs.first; - sync_lb = &ntree->outputs; - } - - /* NB: the sock->storage pointer is used here directly to store the own_index int - * out the mirrored socket counterpart! - */ - - while (sock) { - /* skip static and internal sockets on the sync side (preserves socket order!) */ - while (sync && ((sync->flag & SOCK_INTERNAL) || !(sync->flag & SOCK_DYNAMIC))) - sync = sync->next; - - if (sync && !(sync->flag & SOCK_INTERNAL) && (sync->flag & SOCK_DYNAMIC)) { - if (sock->storage==NULL) { - /* if mirror index is 0, the sockets is newly added and a new mirror must be created. */ - mirror = node_group_expose_socket(ntree, sock, sync_in_out); - /* store the mirror index */ - sock->storage = SET_INT_IN_POINTER(mirror->own_index); - mirror->storage = SET_INT_IN_POINTER(sock->own_index); - /* move mirror to the right place */ - BLI_remlink(sync_lb, mirror); - if (sync) - BLI_insertlinkbefore(sync_lb, sync, mirror); - else - BLI_addtail(sync_lb, mirror); - } - else { - /* look up the mirror socket */ - for (mirror=sync; mirror; mirror=mirror->next) - if (mirror->own_index == GET_INT_FROM_POINTER(sock->storage)) - break; - /* make sure the name is the same (only for identification by user, no deeper meaning) */ - BLI_strncpy(mirror->name, sock->name, sizeof(mirror->name)); - /* fix the socket order if necessary */ - if (mirror != sync) { - BLI_remlink(sync_lb, mirror); - BLI_insertlinkbefore(sync_lb, sync, mirror); - } - else - sync = sync->next; - } - } - - sock = sock->next; - } - - /* remaining sockets in sync_lb are leftovers from deleted sockets, remove them */ - while (sync) { - nsync = sync->next; - if (!(sync->flag & SOCK_INTERNAL) && (sync->flag & SOCK_DYNAMIC)) - node_group_remove_socket(ntree, sync, sync_in_out); - sync = nsync; - } -} - -void node_loop_update_tree(bNodeTree *ngroup) -{ - /* make sure inputs & outputs are identical */ - if (ngroup->update & NTREE_UPDATE_GROUP_IN) - loop_sync(ngroup, SOCK_OUT); - if (ngroup->update & NTREE_UPDATE_GROUP_OUT) - loop_sync(ngroup, SOCK_IN); -} - -void node_whileloop_init(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp) -{ - bNodeSocket *sock; - - node->id = (ID*)ntemp->ngroup; - - sock = nodeAddSocket(ntree, node, SOCK_IN, "Condition", SOCK_FLOAT); - node_socket_set_default_value_float(sock->default_value, PROP_NONE, 1, 0, 1); - - /* max iterations */ - node->custom1 = 10000; - - /* NB: group socket input/output roles are inverted internally! - * Group "inputs" work as outputs in links and vice versa. - */ - if (ntemp->ngroup) { - bNodeSocket *gsock; - for (gsock=ntemp->ngroup->inputs.first; gsock; gsock=gsock->next) - node_group_add_extern_socket(ntree, &node->inputs, SOCK_IN, gsock); - for (gsock=ntemp->ngroup->outputs.first; gsock; gsock=gsock->next) - node_group_add_extern_socket(ntree, &node->outputs, SOCK_OUT, gsock); - } -} - -void node_whileloop_init_tree(bNodeTree *ntree) -{ - bNodeSocket *sock; - sock = node_group_add_socket(ntree, "Condition", SOCK_FLOAT, SOCK_OUT); - sock->flag |= SOCK_INTERNAL; -} - -bNodeTemplate node_whileloop_template(bNode *node) -{ - bNodeTemplate ntemp; - ntemp.type = NODE_WHILELOOP; - ntemp.ngroup = (bNodeTree*)node->id; - return ntemp; -} - /**** FRAME ****/ static void node_frame_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) @@ -547,16 +385,13 @@ void register_node_type_frame(bNodeTreeType *ttype) /* **************** REROUTE ******************** */ /* simple, only a single input and output here */ -static ListBase node_reroute_internal_connect(bNodeTree *ntree, bNode *node) +static void node_reroute_update_internal_links(bNodeTree *ntree, bNode *node) { bNodeLink *link; - ListBase ret; - - ret.first = ret.last = NULL; /* Security check! */ if (!ntree) - return ret; + return; link = MEM_callocN(sizeof(bNodeLink), "internal node link"); link->fromnode = node; @@ -565,9 +400,7 @@ static ListBase node_reroute_internal_connect(bNodeTree *ntree, bNode *node) link->tosock = node->outputs.first; /* internal link is always valid */ link->flag |= NODE_LINK_VALID; - BLI_addtail(&ret, link); - - return ret; + BLI_addtail(&node->internal_links, link); } static void node_reroute_init(bNodeTree *ntree, bNode *node, bNodeTemplate *UNUSED(ntemp)) @@ -586,7 +419,7 @@ void register_node_type_reroute(bNodeTreeType *ttype) node_type_base(ttype, ntype, NODE_REROUTE, "Reroute", NODE_CLASS_LAYOUT, 0); node_type_init(ntype, node_reroute_init); - node_type_internal_connect(ntype, node_reroute_internal_connect); + node_type_internal_links(ntype, node_reroute_update_internal_links); ntype->needs_free = 1; nodeRegisterType(ttype, ntype); @@ -650,3 +483,15 @@ void ntree_update_reroute_nodes(bNodeTree *ntree) if (node->type == NODE_REROUTE && !node->done) node_reroute_inherit_type_recursive(ntree, node); } + +void BKE_node_tree_unlink_id_cb(void *calldata, struct ID *UNUSED(owner_id), struct bNodeTree *ntree) +{ + ID *id = (ID *)calldata; + bNode *node; + + for (node = ntree->nodes.first; node; node = node->next) { + if (node->id == id) { + node->id = NULL; + } + } +} diff --git a/source/blender/nodes/intern/node_common.h b/source/blender/nodes/intern/node_common.h index 00f72469b0f..9e04a9e05f8 100644 --- a/source/blender/nodes/intern/node_common.h +++ b/source/blender/nodes/intern/node_common.h @@ -38,18 +38,8 @@ struct bNodeTree; void node_group_init(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp); -void node_forloop_init(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp); -void node_whileloop_init(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp); - -void node_forloop_init_tree(struct bNodeTree *ntree); -void node_whileloop_init_tree(struct bNodeTree *ntree); - const char *node_group_label(struct bNode *node); - struct bNodeTemplate node_group_template(struct bNode *node); -struct bNodeTemplate node_forloop_template(struct bNode *node); -struct bNodeTemplate node_whileloop_template(struct bNode *node); - int node_group_valid(struct bNodeTree *ntree, struct bNodeTemplate *ntemp); void node_group_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id); @@ -57,8 +47,6 @@ struct bNodeTree *node_group_edit_get(struct bNode *node); struct bNodeTree *node_group_edit_set(struct bNode *node, int edit); void node_group_edit_clear(bNode *node); -void node_loop_update_tree(struct bNodeTree *ngroup); - void ntree_update_reroute_nodes(struct bNodeTree *ntree); #endif diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c index d01ef2e2d52..3cc7ebf9337 100644 --- a/source/blender/nodes/intern/node_exec.c +++ b/source/blender/nodes/intern/node_exec.c @@ -69,7 +69,7 @@ void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack } } -void node_init_input_index(bNodeSocket *sock, int *index) +static void node_init_input_index(bNodeSocket *sock, int *index) { if (sock->link && sock->link->fromsock) { sock->stack_index = sock->link->fromsock->stack_index; @@ -79,16 +79,31 @@ void node_init_input_index(bNodeSocket *sock, int *index) } } -void node_init_output_index(bNodeSocket *sock, int *index) +static void node_init_output_index(bNodeSocket *sock, int *index, ListBase *internal_links) { - sock->stack_index = (*index)++; + if (internal_links) { + bNodeLink *link; + /* copy the stack index from internally connected input to skip the node */ + for (link = internal_links->first; link; link = link->next) { + if (link->tosock == sock) { + sock->stack_index = link->fromsock->stack_index; + break; + } + } + /* if not internally connected, assign a new stack index anyway to avoid bad stack access */ + if (!link) + sock->stack_index = (*index)++; + } + else { + sock->stack_index = (*index)++; + } } /* basic preparation of socket stacks */ static struct bNodeStack *setup_stack(bNodeStack *stack, bNodeSocket *sock) { bNodeStack *ns = node_get_socket_stack(stack, sock); - float null_value[4]= {0.0f, 0.0f, 0.0f, 0.0f}; + float null_value[4] = {0.0f, 0.0f, 0.0f, 0.0f}; /* don't mess with remote socket stacks, these are initialized by other nodes! */ if (sock->link) @@ -133,7 +148,7 @@ bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree) bNodeExec *nodeexec; bNodeSocket *sock, *gsock; bNodeStack *ns; - int index= 0; + int index; bNode **nodelist; int totnodes, n; @@ -148,10 +163,11 @@ bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree) /* backpointer to node tree */ exec->nodetree = ntree; + /* set stack indices */ + index = 0; /* group inputs essentially work as outputs */ for (gsock=ntree->inputs.first; gsock; gsock = gsock->next) - node_init_output_index(gsock, &index); - /* set stack indexes */ + node_init_output_index(gsock, &index, NULL); for (n=0; n < totnodes; ++n) { node = nodelist[n]; @@ -160,8 +176,15 @@ bNodeTreeExec *ntree_exec_begin(bNodeTree *ntree) /* init node socket stack indexes */ for (sock=node->inputs.first; sock; sock=sock->next) node_init_input_index(sock, &index); - for (sock=node->outputs.first; sock; sock=sock->next) - node_init_output_index(sock, &index); + + if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) { + for (sock=node->outputs.first; sock; sock=sock->next) + node_init_output_index(sock, &index, &node->internal_links); + } + else { + for (sock=node->outputs.first; sock; sock=sock->next) + node_init_output_index(sock, &index, NULL); + } } /* group outputs essentially work as inputs */ for (gsock=ntree->outputs.first; gsock; gsock = gsock->next) diff --git a/source/blender/nodes/intern/node_exec.h b/source/blender/nodes/intern/node_exec.h index 1003206e96a..e985795de71 100644 --- a/source/blender/nodes/intern/node_exec.h +++ b/source/blender/nodes/intern/node_exec.h @@ -73,8 +73,6 @@ typedef struct bNodeThreadStack { struct bNodeStack *node_get_socket_stack(struct bNodeStack *stack, struct bNodeSocket *sock); void node_get_stack(struct bNode *node, struct bNodeStack *stack, struct bNodeStack **in, struct bNodeStack **out); -void node_init_input_index(struct bNodeSocket *sock, int *index); -void node_init_output_index(struct bNodeSocket *sock, int *index); struct bNodeTreeExec *ntree_exec_begin(struct bNodeTree *ntree); void ntree_exec_end(struct bNodeTreeExec *exec); diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c index 8b393dd740a..8e49484d1eb 100644 --- a/source/blender/nodes/intern/node_socket.c +++ b/source/blender/nodes/intern/node_socket.c @@ -490,39 +490,39 @@ static bNodeSocket *verify_socket_template(bNodeTree *ntree, bNode *node, int in break; } if (sock) { - sock->type= stemp->type; /* in future, read this from tydefs! */ - if (stemp->limit==0) sock->limit= 0xFFF; - else sock->limit= stemp->limit; + sock->type = stemp->type; /* in future, read this from tydefs! */ + if (stemp->limit == 0) sock->limit= 0xFFF; + else sock->limit = stemp->limit; sock->flag |= stemp->flag; /* Copy the property range and subtype parameters in case the template changed. * NOT copying the actual value here, only button behavior changes! */ switch (sock->type) { - case SOCK_FLOAT: + case SOCK_FLOAT: { bNodeSocketValueFloat *dval= sock->default_value; dval->min = stemp->min; dval->max = stemp->max; dval->subtype = stemp->subtype; + break; } - break; - case SOCK_INT: + case SOCK_INT: { bNodeSocketValueInt *dval= sock->default_value; dval->min = stemp->min; dval->max = stemp->max; dval->subtype = stemp->subtype; + break; } - break; - case SOCK_VECTOR: + case SOCK_VECTOR: { bNodeSocketValueVector *dval= sock->default_value; dval->min = stemp->min; dval->max = stemp->max; dval->subtype = stemp->subtype; + break; } - break; } BLI_remlink(socklist, sock); @@ -600,7 +600,9 @@ void node_verify_socket_templates(bNodeTree *ntree, bNode *node) * This also prevents group node sockets from being removed, without the need to explicitly * check the node type here. */ - if (ntype && ((ntype->inputs && ntype->inputs[0].type>=0) || (ntype->outputs && ntype->outputs[0].type>=0))) { + if (ntype && ((ntype->inputs && ntype->inputs[0].type >= 0) || + (ntype->outputs && ntype->outputs[0].type >= 0))) + { verify_socket_template_list(ntree, node, SOCK_IN, &node->inputs, ntype->inputs); verify_socket_template_list(ntree, node, SOCK_OUT, &node->outputs, ntype->outputs); } diff --git a/source/blender/nodes/intern/node_util.c b/source/blender/nodes/intern/node_util.c index 27258c45fe5..09e6ddd18a5 100644 --- a/source/blender/nodes/intern/node_util.c +++ b/source/blender/nodes/intern/node_util.c @@ -65,12 +65,12 @@ void node_free_standard_storage(bNode *node) void node_copy_curves(bNode *orig_node, bNode *new_node) { - new_node->storage= curvemapping_copy(orig_node->storage); + new_node->storage = curvemapping_copy(orig_node->storage); } void node_copy_standard_storage(bNode *orig_node, bNode *new_node) { - new_node->storage= MEM_dupallocN(orig_node->storage); + new_node->storage = MEM_dupallocN(orig_node->storage); } void *node_initexec_curves(bNode *node) @@ -109,18 +109,15 @@ const char *node_filter_label(bNode *node) return IFACE_(name); } -ListBase node_internal_connect_default(bNodeTree *ntree, bNode *node) +void node_update_internal_links_default(bNodeTree *ntree, bNode *node) { - ListBase ret; bNodeSocket *fromsock_first=NULL, *tosock_first=NULL; /* used for fallback link if no other reconnections are found */ int datatype; int num_links_in = 0, num_links_out = 0, num_reconnect = 0; - ret.first = ret.last = NULL; - /* Security check! */ if (!ntree) - return ret; + return; for (datatype=0; datatype < NUM_SOCKET_TYPES; ++datatype) { bNodeSocket *fromsock, *tosock; @@ -170,7 +167,7 @@ ListBase node_internal_connect_default(bNodeTree *ntree, bNode *node) ilink->tosock = tosock; /* internal link is always valid */ ilink->flag |= NODE_LINK_VALID; - BLI_addtail(&ret, ilink); + BLI_addtail(&node->internal_links, ilink); ++num_reconnect; } @@ -188,8 +185,6 @@ ListBase node_internal_connect_default(bNodeTree *ntree, bNode *node) ilink->tosock = tosock_first; /* internal link is always valid */ ilink->flag |= NODE_LINK_VALID; - BLI_addtail(&ret, ilink); + BLI_addtail(&node->internal_links, ilink); } - - return ret; } diff --git a/source/blender/nodes/intern/node_util.h b/source/blender/nodes/intern/node_util.h index 95104df5fed..3134baa283c 100644 --- a/source/blender/nodes/intern/node_util.h +++ b/source/blender/nodes/intern/node_util.h @@ -62,7 +62,7 @@ const char *node_math_label(struct bNode *node); const char *node_vect_math_label(struct bNode *node); const char *node_filter_label(struct bNode *node); -ListBase node_internal_connect_default(struct bNodeTree *ntree, struct bNode *node); +void node_update_internal_links_default(struct bNodeTree *ntree, struct bNode *node); #endif diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index ad907c317f8..b7dc83d7d79 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -87,10 +87,11 @@ static void foreach_nodeclass(Scene *scene, void *calldata, bNodeClassCallback f func(calldata, NODE_CLASS_SHADER, N_("Shader")); func(calldata, NODE_CLASS_TEXTURE, N_("Texture")); } - + func(calldata, NODE_CLASS_OP_COLOR, N_("Color")); func(calldata, NODE_CLASS_OP_VECTOR, N_("Vector")); func(calldata, NODE_CLASS_CONVERTOR, N_("Convertor")); + func(calldata, NODE_CLASS_SCRIPT, N_("Script")); func(calldata, NODE_CLASS_GROUP, N_("Group")); func(calldata, NODE_CLASS_LAYOUT, N_("Layout")); } @@ -153,7 +154,7 @@ bNodeTreeType ntreeType_Shader = { /* update */ update, /* update_node */ NULL, /* validate_link */ NULL, - /* internal_connect */ node_internal_connect_default + /* update_internal_links */ node_update_internal_links_default }; /* GPU material from shader nodes */ diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c index 56704b981be..6130fe72af3 100644 --- a/source/blender/nodes/shader/node_shader_util.c +++ b/source/blender/nodes/shader/node_shader_util.c @@ -50,9 +50,9 @@ void nodestack_get_vec(float *in, short type_in, bNodeStack *ns) } else if (type_in==SOCK_VECTOR) { if (ns->sockettype==SOCK_FLOAT) { - in[0]= from[0]; - in[1]= from[0]; - in[2]= from[0]; + in[0] = from[0]; + in[1] = from[0]; + in[2] = from[0]; } else { copy_v3_v3(in, from); @@ -63,14 +63,14 @@ void nodestack_get_vec(float *in, short type_in, bNodeStack *ns) copy_v4_v4(in, from); } else if (ns->sockettype==SOCK_FLOAT) { - in[0]= from[0]; - in[1]= from[0]; - in[2]= from[0]; - in[3]= 1.0f; + in[0] = from[0]; + in[1] = from[0]; + in[2] = from[0]; + in[3] = 1.0f; } else { copy_v3_v3(in, from); - in[3]= 1.0f; + in[3] = 1.0f; } } } diff --git a/source/blender/nodes/shader/nodes/node_shader_add_shader.c b/source/blender/nodes/shader/nodes/node_shader_add_shader.c index ee8513a4119..ec868b2cc38 100644 --- a/source/blender/nodes/shader/nodes/node_shader_add_shader.c +++ b/source/blender/nodes/shader/nodes/node_shader_add_shader.c @@ -29,13 +29,13 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_add_shader_in[]= { +static bNodeSocketTemplate sh_node_add_shader_in[] = { { SOCK_SHADER, 1, N_("Shader")}, { SOCK_SHADER, 1, N_("Shader")}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_add_shader_out[]= { +static bNodeSocketTemplate sh_node_add_shader_out[] = { { SOCK_SHADER, 0, N_("Shader")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_attribute.c b/source/blender/nodes/shader/nodes/node_shader_attribute.c index 9c65323337e..9b2ed2f14f0 100644 --- a/source/blender/nodes/shader/nodes/node_shader_attribute.c +++ b/source/blender/nodes/shader/nodes/node_shader_attribute.c @@ -29,7 +29,7 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_attribute_out[]= { +static bNodeSocketTemplate sh_node_attribute_out[] = { { SOCK_RGBA, 0, N_("Color")}, { SOCK_VECTOR, 0, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, diff --git a/source/blender/nodes/shader/nodes/node_shader_background.c b/source/blender/nodes/shader/nodes/node_shader_background.c index 7d13c359a2b..d82c513540c 100644 --- a/source/blender/nodes/shader/nodes/node_shader_background.c +++ b/source/blender/nodes/shader/nodes/node_shader_background.c @@ -29,13 +29,13 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_background_in[]= { +static bNodeSocketTemplate sh_node_background_in[] = { { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000000.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_background_out[]= { +static bNodeSocketTemplate sh_node_background_out[] = { { SOCK_SHADER, 0, N_("Background")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_brightness.c b/source/blender/nodes/shader/nodes/node_shader_brightness.c index 2735553cdad..9c23a29cae9 100644 --- a/source/blender/nodes/shader/nodes/node_shader_brightness.c +++ b/source/blender/nodes/shader/nodes/node_shader_brightness.c @@ -31,14 +31,14 @@ /* **************** Brigh and contrsast ******************** */ -static bNodeSocketTemplate sh_node_brightcontrast_in[]= { +static bNodeSocketTemplate sh_node_brightcontrast_in[] = { { SOCK_RGBA, 1, N_("Color"), 1.0f, 1.0f, 1.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Bright"), 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f, PROP_NONE}, { SOCK_FLOAT, 1, N_("Contrast"), 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f, PROP_NONE}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_brightcontrast_out[]= { +static bNodeSocketTemplate sh_node_brightcontrast_out[] = { { SOCK_RGBA, 0, N_("Color")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c index 9157728b546..71780e9316e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_anisotropic.c @@ -29,21 +29,27 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_bsdf_anisotropic_in[]= { +static bNodeSocketTemplate sh_node_bsdf_anisotropic_in[] = { { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 1, N_("Roughness U"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 1, N_("Roughness V"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Roughness"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Anisotropy"), 0.5f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Rotation"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, + { SOCK_VECTOR, 1, N_("Tangent"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_bsdf_anisotropic_out[]= { +static bNodeSocketTemplate sh_node_bsdf_anisotropic_out[] = { { SOCK_SHADER, 0, N_("BSDF")}, { -1, 0, "" } }; static int node_shader_gpu_bsdf_anisotropic(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) { - return GPU_stack_link(mat, "node_bsdf_anisotropic", in, out, GPU_builtin(GPU_VIEW_NORMAL), GPU_builtin(GPU_VIEW_POSITION)); + if (!in[3].link) + in[3].link = GPU_builtin(GPU_VIEW_NORMAL); + + return GPU_stack_link(mat, "node_bsdf_anisotropic", in, out); } /* node type definition */ @@ -51,7 +57,7 @@ void register_node_type_sh_bsdf_anisotropic(bNodeTreeType *ttype) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_BSDF_ANISOTROPIC, "Glossy Anisotropic BSDF", NODE_CLASS_SHADER, 0); + node_type_base(ttype, &ntype, SH_NODE_BSDF_ANISOTROPIC, "Anisotropic BSDF", NODE_CLASS_SHADER, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_bsdf_anisotropic_in, sh_node_bsdf_anisotropic_out); node_type_size(&ntype, 150, 60, 200); diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c index d2e2db3e78a..ad9f197afb8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_diffuse.c @@ -29,20 +29,24 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_bsdf_diffuse_in[]= { +static bNodeSocketTemplate sh_node_bsdf_diffuse_in[] = { { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.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_bsdf_diffuse_out[]= { +static bNodeSocketTemplate sh_node_bsdf_diffuse_out[] = { { SOCK_SHADER, 0, N_("BSDF")}, { -1, 0, "" } }; static int node_shader_gpu_bsdf_diffuse(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) { - return GPU_stack_link(mat, "node_bsdf_diffuse", in, out, GPU_builtin(GPU_VIEW_NORMAL)); + if (!in[2].link) + in[2].link = GPU_builtin(GPU_VIEW_NORMAL); + + return GPU_stack_link(mat, "node_bsdf_diffuse", in, out); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c index 8ff0ad57742..9e188092570 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glass.c @@ -29,21 +29,25 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_bsdf_glass_in[]= { +static bNodeSocketTemplate sh_node_bsdf_glass_in[] = { { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("IOR"), 1.45f, 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_bsdf_glass_out[]= { +static bNodeSocketTemplate sh_node_bsdf_glass_out[] = { { SOCK_SHADER, 0, N_("BSDF")}, { -1, 0, "" } }; static int node_shader_gpu_bsdf_glass(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) { - return GPU_stack_link(mat, "node_bsdf_glass", in, out, GPU_builtin(GPU_VIEW_NORMAL), GPU_builtin(GPU_VIEW_POSITION)); + if (!in[3].link) + in[3].link = GPU_builtin(GPU_VIEW_NORMAL); + + return GPU_stack_link(mat, "node_bsdf_glass", in, out); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c index d28b3454f02..5e32930b707 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_glossy.c @@ -29,21 +29,24 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_bsdf_glossy_in[]= { +static bNodeSocketTemplate sh_node_bsdf_glossy_in[] = { { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Roughness"), 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 1.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_bsdf_glossy_out[]= { +static bNodeSocketTemplate sh_node_bsdf_glossy_out[] = { { SOCK_SHADER, 0, N_("BSDF")}, { -1, 0, "" } }; static int node_shader_gpu_bsdf_glossy(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) { - /* todo: is incoming vector normalized? */ - return GPU_stack_link(mat, "node_bsdf_glossy", in, out, GPU_builtin(GPU_VIEW_NORMAL), GPU_builtin(GPU_VIEW_POSITION)); + if (!in[2].link) + in[2].link = GPU_builtin(GPU_VIEW_NORMAL); + + return GPU_stack_link(mat, "node_bsdf_glossy", in, out); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c index a3ba3ac7ff3..3c7084886b7 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_translucent.c @@ -29,19 +29,23 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_bsdf_translucent_in[]= { +static bNodeSocketTemplate sh_node_bsdf_translucent_in[] = { { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.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_bsdf_translucent_out[]= { +static bNodeSocketTemplate sh_node_bsdf_translucent_out[] = { { SOCK_SHADER, 0, N_("BSDF")}, { -1, 0, "" } }; static int node_shader_gpu_bsdf_translucent(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) { - return GPU_stack_link(mat, "node_bsdf_translucent", in, out, GPU_builtin(GPU_VIEW_NORMAL)); + if (!in[1].link) + in[1].link = GPU_builtin(GPU_VIEW_NORMAL); + + return GPU_stack_link(mat, "node_bsdf_translucent", in, out); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c index 8c945abdd0d..7fb452ad78d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_transparent.c @@ -29,12 +29,12 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_bsdf_transparent_in[]= { +static bNodeSocketTemplate sh_node_bsdf_transparent_in[] = { { SOCK_RGBA, 1, N_("Color"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_bsdf_transparent_out[]= { +static bNodeSocketTemplate sh_node_bsdf_transparent_out[] = { { SOCK_SHADER, 0, N_("BSDF")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c index 04a1c1b32df..a4d25d42d4e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_velvet.c @@ -29,20 +29,24 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_bsdf_velvet_in[]= { +static bNodeSocketTemplate sh_node_bsdf_velvet_in[] = { { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Sigma"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.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_bsdf_velvet_out[]= { +static bNodeSocketTemplate sh_node_bsdf_velvet_out[] = { { SOCK_SHADER, 0, N_("BSDF")}, { -1, 0, "" } }; static int node_shader_gpu_bsdf_velvet(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) { - return GPU_stack_link(mat, "node_bsdf_velvet", in, out, GPU_builtin(GPU_VIEW_NORMAL)); + if (!in[2].link) + in[2].link = GPU_builtin(GPU_VIEW_NORMAL); + + return GPU_stack_link(mat, "node_bsdf_velvet", in, out); } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.c b/source/blender/nodes/shader/nodes/node_shader_bump.c new file mode 100644 index 00000000000..24ed825c36e --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_bump.c @@ -0,0 +1,68 @@ +/* + * ***** 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 ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_bump.c + * \ingroup shdnodes + */ + + + +#include "node_shader_util.h" + + +/* **************** BUMP ******************** */ +static bNodeSocketTemplate sh_node_bump_in[] = { + { SOCK_FLOAT, 1, "Strength", 0.1f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, + { SOCK_FLOAT, 1, "Height", 1.0f, 1.0f, 1.0f, 1.0f, -1000.0f, 1000.0f, PROP_NONE, SOCK_HIDE_VALUE}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_bump_out[] = { + { SOCK_VECTOR, 0, "Normal"}, + { -1, 0, "" } +}; + +static int gpu_shader_bump(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "node_bump", in, out, GPU_builtin(GPU_VIEW_NORMAL)); +} + +/* node type definition */ +void register_node_type_sh_bump(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, SH_NODE_BUMP, "Bump", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, sh_node_bump_in, sh_node_bump_out); + node_type_size(&ntype, 150, 60, 200); + node_type_storage(&ntype, "BumpNode", node_free_standard_storage, node_copy_standard_storage); + node_type_exec(&ntype, NULL); + node_type_gpu(&ntype, gpu_shader_bump); + + nodeRegisterType(ttype, &ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_camera.c b/source/blender/nodes/shader/nodes/node_shader_camera.c index 17cec8196e8..fd36a94516e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_camera.c +++ b/source/blender/nodes/shader/nodes/node_shader_camera.c @@ -33,7 +33,7 @@ #include "node_shader_util.h" /* **************** CAMERA INFO ******************** */ -static bNodeSocketTemplate sh_node_camera_out[]= { +static bNodeSocketTemplate sh_node_camera_out[] = { { SOCK_VECTOR, 0, N_("View Vector")}, { SOCK_FLOAT, 0, N_("View Z Depth")}, { SOCK_FLOAT, 0, N_("View Distance")}, @@ -47,8 +47,8 @@ static void node_shader_exec_camera(void *data, bNode *UNUSED(node), bNodeStack ShadeInput *shi= ((ShaderCallData *)data)->shi; /* Data we need for shading. */ copy_v3_v3(out[0]->vec, shi->co); /* get view vector */ - out[1]->vec[0]= fabs(shi->co[2]); /* get view z-depth */ - out[2]->vec[0]= normalize_v3(out[0]->vec); /* get view distance */ + out[1]->vec[0] = fabs(shi->co[2]); /* get view z-depth */ + out[2]->vec[0] = normalize_v3(out[0]->vec); /* get view distance */ } } diff --git a/source/blender/nodes/shader/nodes/node_shader_common.c b/source/blender/nodes/shader/nodes/node_shader_common.c index df369482a2e..688d77d8350 100644 --- a/source/blender/nodes/shader/nodes/node_shader_common.c +++ b/source/blender/nodes/shader/nodes/node_shader_common.c @@ -204,128 +204,3 @@ void register_node_type_sh_group(bNodeTreeType *ttype) nodeRegisterType(ttype, &ntype); } - - -/**** FOR LOOP ****/ - -#if 0 /* XXX loop nodes don't work nicely with current trees */ -static void forloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out) -{ - bNodeTreeExec *exec= (bNodeTreeExec*)nodedata; - bNodeThreadStack *nts; - int iterations= (int)in[0]->vec[0]; - bNodeSocket *sock; - bNodeStack *ns; - int iteration; - - /* XXX same behavior as trunk: all nodes inside group are executed. - * it's stupid, but just makes it work. compo redesign will do this better. - */ - { - bNode *inode; - for (inode=exec->nodetree->nodes.first; inode; inode=inode->next) - inode->need_exec = 1; - } - - nts = ntreeGetThreadStack(exec, thread); - - /* "Iteration" socket */ - sock = exec->nodetree->inputs.first; - ns = node_get_socket_stack(nts->stack, sock); - -// group_copy_inputs(node, in, nts->stack); - for (iteration=0; iteration < iterations; ++iteration) { - /* first input contains current iteration counter */ - ns->vec[0] = (float)iteration; - ns->vec[1]=ns->vec[2]=ns->vec[3] = 0.0f; - -// if (iteration > 0) -// loop_init_iteration(exec->nodetree, nts->stack); -// ntreeExecThreadNodes(exec, nts, data, thread); - } -// loop_copy_outputs(node, in, out, exec->stack); - - ntreeReleaseThreadStack(nts); -} - -void register_node_type_sh_forloop(bNodeTreeType *ttype) -{ - static bNodeType ntype; - - node_type_base(ttype, &ntype, NODE_FORLOOP, "For", NODE_CLASS_GROUP, NODE_OPTIONS); - node_type_socket_templates(&ntype, NULL, NULL); - node_type_size(&ntype, 120, 60, 200); - node_type_label(&ntype, node_group_label); - node_type_init(&ntype, node_forloop_init); - node_type_valid(&ntype, node_group_valid); - node_type_template(&ntype, node_forloop_template); - node_type_update(&ntype, NULL, node_group_verify); - node_type_tree(&ntype, node_forloop_init_tree, node_loop_update_tree); - node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); - node_type_exec_new(&ntype, group_initexec, group_freeexec, forloop_execute); - - nodeRegisterType(ttype, &ntype); -} -#endif - -/**** WHILE LOOP ****/ - -#if 0 /* XXX loop nodes don't work nicely with current trees */ -static void whileloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out) -{ - bNodeTreeExec *exec= (bNodeTreeExec*)nodedata; - bNodeThreadStack *nts; - int condition= (in[0]->vec[0] > 0.0f); - bNodeSocket *sock; - bNodeStack *ns; - int iteration; - - /* XXX same behavior as trunk: all nodes inside group are executed. - * it's stupid, but just makes it work. compo redesign will do this better. - */ - { - bNode *inode; - for (inode=exec->nodetree->nodes.first; inode; inode=inode->next) - inode->need_exec = 1; - } - - nts = ntreeGetThreadStack(exec, thread); - - /* "Condition" socket */ - sock = exec->nodetree->outputs.first; - ns = node_get_socket_stack(nts->stack, sock); - - iteration = 0; -// group_copy_inputs(node, in, nts->stack); - while (condition && iteration < node->custom1) { -// if (iteration > 0) -// loop_init_iteration(exec->nodetree, nts->stack); -// ntreeExecThreadNodes(exec, nts, data, thread); - - condition = (ns->vec[0] > 0.0f); - ++iteration; - } -// loop_copy_outputs(node, in, out, exec->stack); - - ntreeReleaseThreadStack(nts); -} - -void register_node_type_sh_whileloop(bNodeTreeType *ttype) -{ - static bNodeType ntype; - - node_type_base(ttype, &ntype, NODE_WHILELOOP, "While", NODE_CLASS_GROUP, NODE_OPTIONS); - node_type_socket_templates(&ntype, NULL, NULL); - node_type_size(&ntype, 120, 60, 200); - node_type_label(&ntype, node_group_label); - node_type_init(&ntype, node_whileloop_init); - node_type_valid(&ntype, node_group_valid); - node_type_template(&ntype, node_whileloop_template); - node_type_update(&ntype, NULL, node_group_verify); - node_type_tree(&ntype, node_whileloop_init_tree, node_loop_update_tree); - node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); - node_type_exec_new(&ntype, group_initexec, group_freeexec, whileloop_execute); - - nodeRegisterType(ttype, &ntype); -} -#endif diff --git a/source/blender/nodes/shader/nodes/node_shader_curves.c b/source/blender/nodes/shader/nodes/node_shader_curves.c index 83cb1d33628..9fa654c9740 100644 --- a/source/blender/nodes/shader/nodes/node_shader_curves.c +++ b/source/blender/nodes/shader/nodes/node_shader_curves.c @@ -34,13 +34,13 @@ /* **************** CURVE VEC ******************** */ -static bNodeSocketTemplate sh_node_curve_vec_in[]= { +static bNodeSocketTemplate sh_node_curve_vec_in[] = { { SOCK_FLOAT, 0, N_("Fac"), 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_curve_vec_out[]= { +static bNodeSocketTemplate sh_node_curve_vec_out[] = { { SOCK_VECTOR, 0, N_("Vector")}, { -1, 0, "" } }; @@ -88,13 +88,13 @@ void register_node_type_sh_curve_vec(bNodeTreeType *ttype) /* **************** CURVE RGB ******************** */ -static bNodeSocketTemplate sh_node_curve_rgb_in[]= { +static bNodeSocketTemplate sh_node_curve_rgb_in[] = { { SOCK_FLOAT, 1, N_("Fac"), 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_FACTOR}, { SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_curve_rgb_out[]= { +static bNodeSocketTemplate sh_node_curve_rgb_out[] = { { SOCK_RGBA, 0, N_("Color")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_emission.c b/source/blender/nodes/shader/nodes/node_shader_emission.c index 4854d887592..0c4cb7ed51c 100644 --- a/source/blender/nodes/shader/nodes/node_shader_emission.c +++ b/source/blender/nodes/shader/nodes/node_shader_emission.c @@ -29,13 +29,13 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_emission_in[]= { +static bNodeSocketTemplate sh_node_emission_in[] = { { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000000.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_emission_out[]= { +static bNodeSocketTemplate sh_node_emission_out[] = { { SOCK_SHADER, 0, N_("Emission")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_fresnel.c b/source/blender/nodes/shader/nodes/node_shader_fresnel.c index 610a2149011..80913e6b07a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_fresnel.c +++ b/source/blender/nodes/shader/nodes/node_shader_fresnel.c @@ -28,12 +28,12 @@ #include "../node_shader_util.h" /* **************** Fresnel ******************** */ -static bNodeSocketTemplate sh_node_fresnel_in[]= { +static bNodeSocketTemplate sh_node_fresnel_in[] = { { SOCK_FLOAT, 1, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 1.0f, 1000.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_fresnel_out[]= { +static bNodeSocketTemplate sh_node_fresnel_out[] = { { SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_gamma.c b/source/blender/nodes/shader/nodes/node_shader_gamma.c index 526868f73d3..c49554c44be 100644 --- a/source/blender/nodes/shader/nodes/node_shader_gamma.c +++ b/source/blender/nodes/shader/nodes/node_shader_gamma.c @@ -30,13 +30,13 @@ /* **************** Gamma Tools ******************** */ -static bNodeSocketTemplate sh_node_gamma_in[]= { +static bNodeSocketTemplate sh_node_gamma_in[] = { { SOCK_RGBA, 1, N_("Color"), 1.0f, 1.0f, 1.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Gamma"), 1.0f, 0.0f, 0.0f, 0.0f, 0.001f, 10.0f, PROP_UNSIGNED}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_gamma_out[]= { +static bNodeSocketTemplate sh_node_gamma_out[] = { { SOCK_RGBA, 0, N_("Color")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_geom.c b/source/blender/nodes/shader/nodes/node_shader_geom.c index f23158ab5d4..eb3d462d616 100644 --- a/source/blender/nodes/shader/nodes/node_shader_geom.c +++ b/source/blender/nodes/shader/nodes/node_shader_geom.c @@ -37,7 +37,7 @@ /* **************** GEOMETRY ******************** */ /* output socket type definition */ -static bNodeSocketTemplate sh_node_geom_out[]= { +static bNodeSocketTemplate sh_node_geom_out[] = { { SOCK_VECTOR, 0, N_("Global")}, { SOCK_VECTOR, 0, N_("Local")}, { SOCK_VECTOR, 0, N_("View")}, @@ -92,12 +92,12 @@ static void node_shader_exec_geom(void *data, bNode *node, bNodeStack **UNUSED(i } copy_v3_v3(out[GEOM_OUT_VCOL]->vec, scol->col); - out[GEOM_OUT_VCOL]->vec[3]= scol->col[3]; - out[GEOM_OUT_VCOL_ALPHA]->vec[0]= scol->col[3]; + out[GEOM_OUT_VCOL]->vec[3] = scol->col[3]; + out[GEOM_OUT_VCOL_ALPHA]->vec[0] = scol->col[3]; } else { memcpy(out[GEOM_OUT_VCOL]->vec, defaultvcol, sizeof(defaultvcol)); - out[GEOM_OUT_VCOL_ALPHA]->vec[0]= 1.0f; + out[GEOM_OUT_VCOL_ALPHA]->vec[0] = 1.0f; } if (shi->osatex) { @@ -116,7 +116,7 @@ static void node_shader_exec_geom(void *data, bNode *node, bNodeStack **UNUSED(i } /* front/back, normal flipping was stored */ - out[GEOM_OUT_FRONTBACK]->vec[0]= (shi->flippednor)? 0.0f: 1.0f; + out[GEOM_OUT_FRONTBACK]->vec[0] = (shi->flippednor)? 0.0f: 1.0f; } } diff --git a/source/blender/nodes/shader/nodes/node_shader_geometry.c b/source/blender/nodes/shader/nodes/node_shader_geometry.c index 2ebd93218d6..acef885d2d4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_geometry.c +++ b/source/blender/nodes/shader/nodes/node_shader_geometry.c @@ -29,7 +29,7 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_geometry_out[]= { +static bNodeSocketTemplate sh_node_geometry_out[] = { { SOCK_VECTOR, 0, N_("Position"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_VECTOR, 0, N_("Tangent"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, diff --git a/source/blender/nodes/shader/nodes/node_shader_holdout.c b/source/blender/nodes/shader/nodes/node_shader_holdout.c index dbd4ed8ab67..18ad4994c9b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_holdout.c +++ b/source/blender/nodes/shader/nodes/node_shader_holdout.c @@ -29,11 +29,11 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_holdout_in[]= { +static bNodeSocketTemplate sh_node_holdout_in[] = { { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_holdout_out[]= { +static bNodeSocketTemplate sh_node_holdout_out[] = { { SOCK_SHADER, 0, N_("Holdout")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c index b07650e33c0..b635ad1edd9 100644 --- a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c +++ b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c @@ -34,7 +34,7 @@ /* **************** Hue Saturation ******************** */ -static bNodeSocketTemplate sh_node_hue_sat_in[]= { +static bNodeSocketTemplate sh_node_hue_sat_in[] = { { SOCK_FLOAT, 1, N_("Hue"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE}, { SOCK_FLOAT, 1, N_("Saturation"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, PROP_FACTOR}, { SOCK_FLOAT, 1, N_("Value"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, PROP_FACTOR}, @@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_hue_sat_in[]= { { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_hue_sat_out[]= { +static bNodeSocketTemplate sh_node_hue_sat_out[] = { { SOCK_RGBA, 0, N_("Color")}, { -1, 0, "" } }; @@ -60,9 +60,9 @@ static void do_hue_sat_fac(bNode *UNUSED(node), float *out, float *hue, float *s hsv[2]*= *val; hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col+1, col+2); - out[0]= mfac*in[0] + *fac*col[0]; - out[1]= mfac*in[1] + *fac*col[1]; - out[2]= mfac*in[2] + *fac*col[2]; + out[0] = mfac*in[0] + *fac*col[0]; + out[1] = mfac*in[1] + *fac*col[1]; + out[2] = mfac*in[2] + *fac*col[2]; } else { copy_v4_v4(out, in); diff --git a/source/blender/nodes/shader/nodes/node_shader_invert.c b/source/blender/nodes/shader/nodes/node_shader_invert.c index ef592a7e2ec..2ea858f4e34 100644 --- a/source/blender/nodes/shader/nodes/node_shader_invert.c +++ b/source/blender/nodes/shader/nodes/node_shader_invert.c @@ -35,15 +35,15 @@ /* **************** INVERT ******************** */ -static bNodeSocketTemplate sh_node_invert_in[]= { - { SOCK_FLOAT, 1, N_("Fac"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, - { SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f}, - { -1, 0, "" } +static bNodeSocketTemplate sh_node_invert_in[] = { + { SOCK_FLOAT, 1, N_("Fac"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_invert_out[]= { - { SOCK_RGBA, 0, N_("Color")}, - { -1, 0, "" } +static bNodeSocketTemplate sh_node_invert_out[] = { + { SOCK_RGBA, 0, N_("Color")}, + { -1, 0, "" } }; static void node_shader_exec_invert(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, diff --git a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c index 6eacea10b5b..3058483ebef 100644 --- a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c +++ b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c @@ -29,12 +29,12 @@ /* **************** Layer Weight ******************** */ -static bNodeSocketTemplate sh_node_layer_weight_in[]= { +static bNodeSocketTemplate sh_node_layer_weight_in[] = { { SOCK_FLOAT, 1, N_("Blend"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_layer_weight_out[]= { +static bNodeSocketTemplate sh_node_layer_weight_out[] = { { SOCK_FLOAT, 0, N_("Fresnel"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Facing"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } diff --git a/source/blender/nodes/shader/nodes/node_shader_light_falloff.c b/source/blender/nodes/shader/nodes/node_shader_light_falloff.c index aab5fa8060d..2dec244ae3a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_light_falloff.c +++ b/source/blender/nodes/shader/nodes/node_shader_light_falloff.c @@ -29,7 +29,7 @@ /* **************** INPUT ********************* */ -static bNodeSocketTemplate sh_node_light_falloff_in[]= { +static bNodeSocketTemplate sh_node_light_falloff_in[] = { { SOCK_FLOAT, 0, N_("Strength"), 100.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000000.0f}, { SOCK_FLOAT, 0, N_("Smooth"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, { -1, 0, "" } @@ -37,7 +37,7 @@ static bNodeSocketTemplate sh_node_light_falloff_in[]= { /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_light_falloff_out[]= { +static bNodeSocketTemplate sh_node_light_falloff_out[] = { { SOCK_FLOAT, 0, N_("Quadratic"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Linear"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Constant"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, diff --git a/source/blender/nodes/shader/nodes/node_shader_light_path.c b/source/blender/nodes/shader/nodes/node_shader_light_path.c index 264b1390688..b4a3d4e01e1 100644 --- a/source/blender/nodes/shader/nodes/node_shader_light_path.c +++ b/source/blender/nodes/shader/nodes/node_shader_light_path.c @@ -29,7 +29,7 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_light_path_out[]= { +static bNodeSocketTemplate sh_node_light_path_out[] = { { SOCK_FLOAT, 0, N_("Is Camera Ray"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Is Shadow Ray"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Is Diffuse Ray"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c index 4508f66543e..cedd3a4910c 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mapping.c +++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c @@ -33,12 +33,12 @@ #include "node_shader_util.h" /* **************** MAPPING ******************** */ -static bNodeSocketTemplate sh_node_mapping_in[]= { +static bNodeSocketTemplate sh_node_mapping_in[] = { { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_mapping_out[]= { +static bNodeSocketTemplate sh_node_mapping_out[] = { { SOCK_VECTOR, 0, N_("Vector")}, { -1, 0, "" } }; @@ -55,14 +55,14 @@ static void node_shader_exec_mapping(void *UNUSED(data), bNode *node, bNodeStack mul_m4_v3(texmap->mat, vec); if (texmap->flag & TEXMAP_CLIP_MIN) { - if (vec[0]min[0]) vec[0]= texmap->min[0]; - if (vec[1]min[1]) vec[1]= texmap->min[1]; - if (vec[2]min[2]) vec[2]= texmap->min[2]; + if (vec[0]min[0]) vec[0] = texmap->min[0]; + if (vec[1]min[1]) vec[1] = texmap->min[1]; + if (vec[2]min[2]) vec[2] = texmap->min[2]; } if (texmap->flag & TEXMAP_CLIP_MAX) { - if (vec[0]>texmap->max[0]) vec[0]= texmap->max[0]; - if (vec[1]>texmap->max[1]) vec[1]= texmap->max[1]; - if (vec[2]>texmap->max[2]) vec[2]= texmap->max[2]; + if (vec[0]>texmap->max[0]) vec[0] = texmap->max[0]; + if (vec[1]>texmap->max[1]) vec[1] = texmap->max[1]; + if (vec[2]>texmap->max[2]) vec[2] = texmap->max[2]; } } diff --git a/source/blender/nodes/shader/nodes/node_shader_material.c b/source/blender/nodes/shader/nodes/node_shader_material.c index 57865e072e7..bccf6d349cf 100644 --- a/source/blender/nodes/shader/nodes/node_shader_material.c +++ b/source/blender/nodes/shader/nodes/node_shader_material.c @@ -34,7 +34,7 @@ /* **************** MATERIAL ******************** */ -static bNodeSocketTemplate sh_node_material_in[]= { +static bNodeSocketTemplate sh_node_material_in[] = { { SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_RGBA, 1, N_("Spec"), 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Refl"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, @@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_material_in[]= { { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_material_out[]= { +static bNodeSocketTemplate sh_node_material_out[] = { { SOCK_RGBA, 0, N_("Color")}, { SOCK_FLOAT, 0, N_("Alpha")}, { SOCK_VECTOR, 0, N_("Normal")}, @@ -51,7 +51,7 @@ static bNodeSocketTemplate sh_node_material_out[]= { /* **************** EXTENDED MATERIAL ******************** */ -static bNodeSocketTemplate sh_node_material_ext_in[]= { +static bNodeSocketTemplate sh_node_material_ext_in[] = { { SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_RGBA, 1, N_("Spec"), 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Refl"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_FACTOR}, @@ -66,7 +66,7 @@ static bNodeSocketTemplate sh_node_material_ext_in[]= { { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_material_ext_out[]= { +static bNodeSocketTemplate sh_node_material_ext_out[] = { { SOCK_RGBA, 0, N_("Color")}, { SOCK_FLOAT, 0, N_("Alpha")}, { SOCK_VECTOR, 0, N_("Normal")}, @@ -84,7 +84,7 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, ShaderCallData *shcd= data; float col[4]; bNodeSocket *sock; - char hasinput[NUM_MAT_IN]= {'\0'}; + char hasinput[NUM_MAT_IN] = {'\0'}; int i; /* note: cannot use the in[]->hasinput flags directly, as these are not necessarily @@ -139,7 +139,7 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, if (hasinput[MAT_IN_ALPHA]) nodestack_get_vec(&shi->alpha, SOCK_FLOAT, in[MAT_IN_ALPHA]); if (hasinput[MAT_IN_TRANSLUCENCY]) - nodestack_get_vec(&shi->translucency, SOCK_FLOAT, in[MAT_IN_TRANSLUCENCY]); + nodestack_get_vec(&shi->translucency, SOCK_FLOAT, in[MAT_IN_TRANSLUCENCY]); } shi->nodes= 1; /* temp hack to prevent trashadow recursion */ @@ -157,20 +157,20 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, copy_v3_v3(col, shrnode.spec); } else - col[0]= col[1]= col[2]= 0.0f; + col[0] = col[1] = col[2] = 0.0f; - col[3]= shrnode.alpha; + col[3] = shrnode.alpha; if (shi->do_preview) nodeAddToPreview(node, col, shi->xs, shi->ys, shi->do_manage); copy_v3_v3(out[MAT_OUT_COLOR]->vec, col); - out[MAT_OUT_ALPHA]->vec[0]= shrnode.alpha; + out[MAT_OUT_ALPHA]->vec[0] = shrnode.alpha; if (node->custom1 & SH_NODE_MAT_NEG) { - shi->vn[0]= -shi->vn[0]; - shi->vn[1]= -shi->vn[1]; - shi->vn[2]= -shi->vn[2]; + shi->vn[0] = -shi->vn[0]; + shi->vn[1] = -shi->vn[1]; + shi->vn[2] = -shi->vn[2]; } copy_v3_v3(out[MAT_OUT_NORMAL]->vec, shi->vn); @@ -222,7 +222,7 @@ static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUShadeInput shi; GPUShadeResult shr; bNodeSocket *sock; - char hasinput[NUM_MAT_IN]= {'\0'}; + char hasinput[NUM_MAT_IN] = {'\0'}; int i; /* note: cannot use the in[]->hasinput flags directly, as these are not necessarily diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c index c112ae1d448..a70134b2325 100644 --- a/source/blender/nodes/shader/nodes/node_shader_math.c +++ b/source/blender/nodes/shader/nodes/node_shader_math.c @@ -34,61 +34,61 @@ /* **************** SCALAR MATH ******************** */ -static bNodeSocketTemplate sh_node_math_in[]= { - { SOCK_FLOAT, 1, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, - { SOCK_FLOAT, 1, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, - { -1, 0, "" } +static bNodeSocketTemplate sh_node_math_in[] = { + { SOCK_FLOAT, 1, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + { SOCK_FLOAT, 1, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_math_out[]= { - { SOCK_FLOAT, 0, N_("Value")}, - { -1, 0, "" } +static bNodeSocketTemplate sh_node_math_out[] = { + { SOCK_FLOAT, 0, N_("Value")}, + { -1, 0, "" } }; static void node_shader_exec_math(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) { - switch (node->custom1) { + switch (node->custom1) { case 0: /* Add */ - out[0]->vec[0]= in[0]->vec[0] + in[1]->vec[0]; + out[0]->vec[0] = in[0]->vec[0] + in[1]->vec[0]; break; case 1: /* Subtract */ - out[0]->vec[0]= in[0]->vec[0] - in[1]->vec[0]; + out[0]->vec[0] = in[0]->vec[0] - in[1]->vec[0]; break; case 2: /* Multiply */ - out[0]->vec[0]= in[0]->vec[0] * in[1]->vec[0]; + out[0]->vec[0] = in[0]->vec[0] * in[1]->vec[0]; break; case 3: /* Divide */ { if (in[1]->vec[0]==0) /* We don't want to divide by zero. */ - out[0]->vec[0]= 0.0; + out[0]->vec[0] = 0.0; else - out[0]->vec[0]= in[0]->vec[0] / in[1]->vec[0]; + out[0]->vec[0] = in[0]->vec[0] / in[1]->vec[0]; } break; case 4: /* Sine */ { if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */ - out[0]->vec[0]= sin(in[0]->vec[0]); + out[0]->vec[0] = sin(in[0]->vec[0]); else - out[0]->vec[0]= sin(in[1]->vec[0]); + out[0]->vec[0] = sin(in[1]->vec[0]); } break; case 5: /* Cosine */ { - if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */ - out[0]->vec[0]= cos(in[0]->vec[0]); + if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */ + out[0]->vec[0] = cos(in[0]->vec[0]); else - out[0]->vec[0]= cos(in[1]->vec[0]); + out[0]->vec[0] = cos(in[1]->vec[0]); } break; case 6: /* Tangent */ { - if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */ - out[0]->vec[0]= tan(in[0]->vec[0]); + if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */ + out[0]->vec[0] = tan(in[0]->vec[0]); else - out[0]->vec[0]= tan(in[1]->vec[0]); + out[0]->vec[0] = tan(in[1]->vec[0]); } break; case 7: /* Arc-Sine */ @@ -96,16 +96,16 @@ bNodeStack **out) if (in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */ /* Can't do the impossible... */ if ( in[0]->vec[0] <= 1 && in[0]->vec[0] >= -1 ) - out[0]->vec[0]= asin(in[0]->vec[0]); + out[0]->vec[0] = asin(in[0]->vec[0]); else - out[0]->vec[0]= 0.0; + out[0]->vec[0] = 0.0; } else { /* Can't do the impossible... */ if ( in[1]->vec[0] <= 1 && in[1]->vec[0] >= -1 ) - out[0]->vec[0]= asin(in[1]->vec[0]); + out[0]->vec[0] = asin(in[1]->vec[0]); else - out[0]->vec[0]= 0.0; + out[0]->vec[0] = 0.0; } } break; @@ -114,86 +114,86 @@ bNodeStack **out) if (in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */ /* Can't do the impossible... */ if ( in[0]->vec[0] <= 1 && in[0]->vec[0] >= -1 ) - out[0]->vec[0]= acos(in[0]->vec[0]); + out[0]->vec[0] = acos(in[0]->vec[0]); else - out[0]->vec[0]= 0.0; + out[0]->vec[0] = 0.0; } else { /* Can't do the impossible... */ if ( in[1]->vec[0] <= 1 && in[1]->vec[0] >= -1 ) - out[0]->vec[0]= acos(in[1]->vec[0]); + out[0]->vec[0] = acos(in[1]->vec[0]); else - out[0]->vec[0]= 0.0; + out[0]->vec[0] = 0.0; } } break; case 9: /* Arc-Tangent */ { if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */ - out[0]->vec[0]= atan(in[0]->vec[0]); + out[0]->vec[0] = atan(in[0]->vec[0]); else - out[0]->vec[0]= atan(in[1]->vec[0]); + out[0]->vec[0] = atan(in[1]->vec[0]); } break; case 10: /* Power */ { /* Don't want any imaginary numbers... */ if ( in[0]->vec[0] >= 0 ) - out[0]->vec[0]= pow(in[0]->vec[0], in[1]->vec[0]); + out[0]->vec[0] = pow(in[0]->vec[0], in[1]->vec[0]); else - out[0]->vec[0]= 0.0; + out[0]->vec[0] = 0.0; } break; case 11: /* Logarithm */ { /* Don't want any imaginary numbers... */ if ( in[0]->vec[0] > 0 && in[1]->vec[0] > 0 ) - out[0]->vec[0]= log(in[0]->vec[0]) / log(in[1]->vec[0]); + out[0]->vec[0] = log(in[0]->vec[0]) / log(in[1]->vec[0]); else - out[0]->vec[0]= 0.0; + out[0]->vec[0] = 0.0; } break; case 12: /* Minimum */ { if ( in[0]->vec[0] < in[1]->vec[0] ) - out[0]->vec[0]= in[0]->vec[0]; + out[0]->vec[0] = in[0]->vec[0]; else - out[0]->vec[0]= in[1]->vec[0]; + out[0]->vec[0] = in[1]->vec[0]; } break; case 13: /* Maximum */ { if ( in[0]->vec[0] > in[1]->vec[0] ) - out[0]->vec[0]= in[0]->vec[0]; + out[0]->vec[0] = in[0]->vec[0]; else - out[0]->vec[0]= in[1]->vec[0]; + out[0]->vec[0] = in[1]->vec[0]; } break; case 14: /* Round */ { if (in[0]->hasinput || !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */ - out[0]->vec[0]= (in[0]->vec[0]<0)?(int)(in[0]->vec[0] - 0.5f):(int)(in[0]->vec[0] + 0.5f); + out[0]->vec[0] = (in[0]->vec[0]<0)?(int)(in[0]->vec[0] - 0.5f):(int)(in[0]->vec[0] + 0.5f); else - out[0]->vec[0]= (in[1]->vec[0]<0)?(int)(in[1]->vec[0] - 0.5f):(int)(in[1]->vec[0] + 0.5f); + out[0]->vec[0] = (in[1]->vec[0]<0)?(int)(in[1]->vec[0] - 0.5f):(int)(in[1]->vec[0] + 0.5f); } break; case 15: /* Less Than */ { if ( in[0]->vec[0] < in[1]->vec[0] ) - out[0]->vec[0]= 1.0f; + out[0]->vec[0] = 1.0f; else - out[0]->vec[0]= 0.0f; + out[0]->vec[0] = 0.0f; } break; case 16: /* Greater Than */ { if ( in[0]->vec[0] > in[1]->vec[0] ) - out[0]->vec[0]= 1.0f; + out[0]->vec[0] = 1.0f; else - out[0]->vec[0]= 0.0f; + out[0]->vec[0] = 0.0f; } break; - } + } } static int gpu_shader_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) diff --git a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c index 53c1387ca1a..18dcc8f7fef 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c +++ b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c @@ -33,13 +33,13 @@ #include "node_shader_util.h" /* **************** MIX RGB ******************** */ -static bNodeSocketTemplate sh_node_mix_rgb_in[]= { +static bNodeSocketTemplate sh_node_mix_rgb_in[] = { { SOCK_FLOAT, 1, N_("Fac"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, { SOCK_RGBA, 1, N_("Color1"), 0.5f, 0.5f, 0.5f, 1.0f}, { SOCK_RGBA, 1, N_("Color2"), 0.5f, 0.5f, 0.5f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_mix_rgb_out[]= { +static bNodeSocketTemplate sh_node_mix_rgb_out[] = { { SOCK_RGBA, 0, N_("Color")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_mix_shader.c b/source/blender/nodes/shader/nodes/node_shader_mix_shader.c index 80ee1a8499d..039e63a4dea 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mix_shader.c +++ b/source/blender/nodes/shader/nodes/node_shader_mix_shader.c @@ -29,14 +29,14 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_mix_shader_in[]= { +static bNodeSocketTemplate sh_node_mix_shader_in[] = { { SOCK_FLOAT, 1, N_("Fac"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_SHADER, 1, N_("Shader")}, { SOCK_SHADER, 1, N_("Shader")}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_mix_shader_out[]= { +static bNodeSocketTemplate sh_node_mix_shader_out[] = { { SOCK_SHADER, 0, N_("Shader")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_normal.c b/source/blender/nodes/shader/nodes/node_shader_normal.c index bb0a85417d9..98a56c85279 100644 --- a/source/blender/nodes/shader/nodes/node_shader_normal.c +++ b/source/blender/nodes/shader/nodes/node_shader_normal.c @@ -33,12 +33,12 @@ #include "node_shader_util.h" /* **************** NORMAL ******************** */ -static bNodeSocketTemplate sh_node_normal_in[]= { +static bNodeSocketTemplate sh_node_normal_in[] = { { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_normal_out[]= { +static bNodeSocketTemplate sh_node_normal_out[] = { { SOCK_VECTOR, 0, N_("Normal")}, { SOCK_FLOAT, 0, N_("Dot")}, { -1, 0, "" } @@ -68,7 +68,7 @@ static void node_shader_exec_normal(void *UNUSED(data), bNode *node, bNodeStack copy_v3_v3(out[0]->vec, ((bNodeSocketValueVector*)sock->default_value)->value); /* render normals point inside... the widget points outside */ - out[1]->vec[0]= -dot_v3v3(out[0]->vec, vec); + out[1]->vec[0] = -dot_v3v3(out[0]->vec, vec); } static int gpu_shader_normal(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) diff --git a/source/blender/nodes/shader/nodes/node_shader_object_info.c b/source/blender/nodes/shader/nodes/node_shader_object_info.c index 1cafa01ecec..ef283004d46 100644 --- a/source/blender/nodes/shader/nodes/node_shader_object_info.c +++ b/source/blender/nodes/shader/nodes/node_shader_object_info.c @@ -29,7 +29,7 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_object_info_out[]= { +static bNodeSocketTemplate sh_node_object_info_out[] = { { SOCK_VECTOR, 0, N_("Location"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Object Index"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Material Index"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, diff --git a/source/blender/nodes/shader/nodes/node_shader_output.c b/source/blender/nodes/shader/nodes/node_shader_output.c index 4434054abae..6f7f900aecd 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output.c +++ b/source/blender/nodes/shader/nodes/node_shader_output.c @@ -33,7 +33,7 @@ #include "node_shader_util.h" /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_output_in[]= { +static bNodeSocketTemplate sh_node_output_in[] = { { SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, { -1, 0, "" } @@ -62,7 +62,7 @@ static void node_shader_exec_output(void *data, bNode *node, bNodeStack **in, bN // copy_v3_v3(shr->nor, in[3]->vec); } - } + } } static int gpu_shader_output(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) @@ -92,7 +92,7 @@ void register_node_type_sh_output(bNodeTreeType *ttype) node_type_gpu(&ntype, gpu_shader_output); /* Do not allow muting output node. */ - node_type_internal_connect(&ntype, NULL); + node_type_internal_links(&ntype, NULL); nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_output_lamp.c b/source/blender/nodes/shader/nodes/node_shader_output_lamp.c index eb7208302fe..ce406a8f5a1 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output_lamp.c +++ b/source/blender/nodes/shader/nodes/node_shader_output_lamp.c @@ -29,7 +29,7 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_output_lamp_in[]= { +static bNodeSocketTemplate sh_node_output_lamp_in[] = { { SOCK_SHADER, 1, N_("Surface"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } }; @@ -49,7 +49,7 @@ void register_node_type_sh_output_lamp(bNodeTreeType *ttype) node_type_gpu(&ntype, NULL); /* Do not allow muting output node. */ - node_type_internal_connect(&ntype, NULL); + node_type_internal_links(&ntype, NULL); nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_output_material.c b/source/blender/nodes/shader/nodes/node_shader_output_material.c index e81744c44bd..f185e13010b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output_material.c +++ b/source/blender/nodes/shader/nodes/node_shader_output_material.c @@ -29,7 +29,7 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_output_material_in[]= { +static bNodeSocketTemplate sh_node_output_material_in[] = { { SOCK_SHADER, 1, N_("Surface")}, { SOCK_SHADER, 1, N_("Volume")}, { SOCK_FLOAT, 1, N_("Displacement"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, @@ -62,7 +62,7 @@ void register_node_type_sh_output_material(bNodeTreeType *ttype) node_type_gpu(&ntype, node_shader_gpu_output_material); /* Do not allow muting output node. */ - node_type_internal_connect(&ntype, NULL); + node_type_internal_links(&ntype, NULL); nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_output_world.c b/source/blender/nodes/shader/nodes/node_shader_output_world.c index 3a931c2af53..953197ab2cd 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output_world.c +++ b/source/blender/nodes/shader/nodes/node_shader_output_world.c @@ -29,7 +29,7 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_output_world_in[]= { +static bNodeSocketTemplate sh_node_output_world_in[] = { { SOCK_SHADER, 1, N_("Surface"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_SHADER, 1, N_("Volume"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } @@ -50,7 +50,7 @@ void register_node_type_sh_output_world(bNodeTreeType *ttype) node_type_gpu(&ntype, NULL); /* Do not allow muting output node. */ - node_type_internal_connect(&ntype, NULL); + node_type_internal_links(&ntype, NULL); nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_particle_info.c b/source/blender/nodes/shader/nodes/node_shader_particle_info.c index ddfcb9476f4..c7e31d117cc 100644 --- a/source/blender/nodes/shader/nodes/node_shader_particle_info.c +++ b/source/blender/nodes/shader/nodes/node_shader_particle_info.c @@ -28,18 +28,18 @@ #include "../node_shader_util.h" static bNodeSocketTemplate outputs[] = { - { SOCK_FLOAT, 0, "Index" }, - { SOCK_FLOAT, 0, "Age" }, - { SOCK_FLOAT, 0, "Lifetime" }, - { SOCK_VECTOR, 0, "Location" }, - #if 0 /* quaternion sockets not yet supported */ - { SOCK_QUATERNION, 0, "Rotation" }, - #endif - { SOCK_FLOAT, 0, "Size" }, - { SOCK_VECTOR, 0, "Velocity" }, - { SOCK_VECTOR, 0, "Angular Velocity" }, - { -1, 0, "" } -}; + { SOCK_FLOAT, 0, "Index" }, + { SOCK_FLOAT, 0, "Age" }, + { SOCK_FLOAT, 0, "Lifetime" }, + { SOCK_VECTOR, 0, "Location" }, +#if 0 /* quaternion sockets not yet supported */ + { SOCK_QUATERNION, 0, "Rotation" }, +#endif + { SOCK_FLOAT, 0, "Size" }, + { SOCK_VECTOR, 0, "Velocity" }, + { SOCK_VECTOR, 0, "Angular Velocity" }, + { -1, 0, "" } + }; /* node type definition */ void register_node_type_sh_particle_info(bNodeTreeType *ttype) diff --git a/source/blender/nodes/shader/nodes/node_shader_rgb.c b/source/blender/nodes/shader/nodes/node_shader_rgb.c index 5a19c61fe92..f37ff1d511b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_rgb.c +++ b/source/blender/nodes/shader/nodes/node_shader_rgb.c @@ -33,7 +33,7 @@ #include "node_shader_util.h" /* **************** RGB ******************** */ -static bNodeSocketTemplate sh_node_rgb_out[]= { +static bNodeSocketTemplate sh_node_rgb_out[] = { { SOCK_RGBA, 0, N_("Color")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_script.c b/source/blender/nodes/shader/nodes/node_shader_script.c new file mode 100644 index 00000000000..52d39363de6 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_script.c @@ -0,0 +1,85 @@ +/* + * ***** 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 ***** + */ + +/** \file blender/nodes/shader/nodes/node_shader_script.c + * \ingroup shdnodes + */ + +#include "BKE_idprop.h" + +#include "node_shader_util.h" + +/* **************** Script ******************** */ + +static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +{ + NodeShaderScript *nss = MEM_callocN(sizeof(NodeShaderScript), "shader script node"); + node->storage = nss; +} + +static void node_free_script(bNode *node) +{ + NodeShaderScript *nss = node->storage; + + if (nss) { + if (nss->bytecode) + MEM_freeN(nss->bytecode); + + MEM_freeN(nss); + } + + if (nss->prop) { + IDP_FreeProperty(nss->prop); + MEM_freeN(nss->prop); + } +} + +static void node_copy_script(bNode *orig_node, bNode *new_node) +{ + NodeShaderScript *orig_nss = orig_node->storage; + NodeShaderScript *new_nss = MEM_dupallocN(orig_nss); + + if(orig_nss->bytecode) + new_nss->bytecode = MEM_dupallocN(orig_nss->bytecode); + + if (orig_nss->prop) + new_nss->prop = IDP_CopyProperty(orig_nss->prop); + + new_node->storage = new_nss; +} + +void register_node_type_sh_script(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, SH_NODE_SCRIPT, "Script", NODE_CLASS_SCRIPT, NODE_OPTIONS); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_init(&ntype, init); + node_type_storage(&ntype, "NodeShaderScript", node_free_script, node_copy_script); + + nodeRegisterType(ttype, &ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c index 55f37b666e7..70fba161de9 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c +++ b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c @@ -33,11 +33,11 @@ #include "node_shader_util.h" /* **************** SEPARATE RGBA ******************** */ -static bNodeSocketTemplate sh_node_seprgb_in[]= { +static bNodeSocketTemplate sh_node_seprgb_in[] = { { SOCK_RGBA, 1, N_("Image"), 0.8f, 0.8f, 0.8f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_seprgb_out[]= { +static bNodeSocketTemplate sh_node_seprgb_out[] = { { SOCK_FLOAT, 0, N_("R")}, { SOCK_FLOAT, 0, N_("G")}, { SOCK_FLOAT, 0, N_("B")}, @@ -73,13 +73,13 @@ void register_node_type_sh_seprgb(bNodeTreeType *ttype) /* **************** COMBINE RGB ******************** */ -static bNodeSocketTemplate sh_node_combrgb_in[]= { +static bNodeSocketTemplate sh_node_combrgb_in[] = { { SOCK_FLOAT, 1, N_("R"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_UNSIGNED}, { SOCK_FLOAT, 1, N_("G"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_UNSIGNED}, { SOCK_FLOAT, 1, N_("B"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_UNSIGNED}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_combrgb_out[]= { +static bNodeSocketTemplate sh_node_combrgb_out[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_squeeze.c b/source/blender/nodes/shader/nodes/node_shader_squeeze.c index adab396be02..8073f4b01d2 100644 --- a/source/blender/nodes/shader/nodes/node_shader_squeeze.c +++ b/source/blender/nodes/shader/nodes/node_shader_squeeze.c @@ -33,20 +33,19 @@ #include "node_shader_util.h" /* **************** VALUE SQUEEZE ******************** */ -static bNodeSocketTemplate sh_node_squeeze_in[]= { - { SOCK_FLOAT, 1, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f, PROP_NONE}, - { SOCK_FLOAT, 1, N_("Width"), 1.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f, PROP_NONE}, - { SOCK_FLOAT, 1, N_("Center"), 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f, PROP_NONE}, - { -1, 0, "" } +static bNodeSocketTemplate sh_node_squeeze_in[] = { + { SOCK_FLOAT, 1, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f, PROP_NONE}, + { SOCK_FLOAT, 1, N_("Width"), 1.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f, PROP_NONE}, + { SOCK_FLOAT, 1, N_("Center"), 0.0f, 0.0f, 0.0f, 0.0f, -100.0f, 100.0f, PROP_NONE}, + { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_squeeze_out[]= { - { SOCK_FLOAT, 0, N_("Value")}, - { -1, 0, "" } +static bNodeSocketTemplate sh_node_squeeze_out[] = { + { SOCK_FLOAT, 0, N_("Value")}, + { -1, 0, "" } }; -static void node_shader_exec_squeeze(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, -bNodeStack **out) +static void node_shader_exec_squeeze(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out) { float vec[3]; @@ -54,7 +53,7 @@ bNodeStack **out) nodestack_get_vec(vec+1, SOCK_FLOAT, in[1]); nodestack_get_vec(vec+2, SOCK_FLOAT, in[2]); - out[0]->vec[0] = 1.0f / (1.0f + pow(M_E, -((vec[0] - vec[2]) * vec[1]))); + out[0]->vec[0] = 1.0f / (1.0f + powf(M_E, -((vec[0] - vec[2]) * vec[1]))); } static int gpu_shader_squeeze(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c index 11f7fb94ae0..66bf0267586 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c @@ -29,7 +29,7 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_tex_brick_in[]= { +static bNodeSocketTemplate sh_node_tex_brick_in[] = { { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, { SOCK_RGBA, 1, N_("Color1"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_RGBA, 1, N_("Color2"), 0.2f, 0.2f, 0.2f, 1.0f, 0.0f, 1.0f}, @@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_tex_brick_in[]= { { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_tex_brick_out[]= { +static bNodeSocketTemplate sh_node_tex_brick_out[] = { { SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c index 0c1e7dcb995..8a2ae2d40dc 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c @@ -29,7 +29,7 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_tex_checker_in[]= { +static bNodeSocketTemplate sh_node_tex_checker_in[] = { { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, { SOCK_RGBA, 1, N_("Color1"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_RGBA, 1, N_("Color2"), 0.2f, 0.2f, 0.2f, 1.0f, 0.0f, 1.0f}, @@ -37,7 +37,7 @@ static bNodeSocketTemplate sh_node_tex_checker_in[]= { { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_tex_checker_out[]= { +static bNodeSocketTemplate sh_node_tex_checker_out[] = { { SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c index 86f71f6f05b..dd717874951 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c @@ -31,7 +31,7 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_tex_coord_out[]= { +static bNodeSocketTemplate sh_node_tex_coord_out[] = { { SOCK_VECTOR, 0, N_("Generated"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_VECTOR, 0, N_("UV"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, @@ -57,7 +57,7 @@ void register_node_type_sh_tex_coord(bNodeTreeType *ttype) { static bNodeType ntype; - node_type_base(ttype, &ntype, SH_NODE_TEX_COORD, "Texture Coordinate", NODE_CLASS_INPUT, 0); + node_type_base(ttype, &ntype, SH_NODE_TEX_COORD, "Texture Coordinate", NODE_CLASS_INPUT, NODE_OPTIONS); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, NULL, sh_node_tex_coord_out); node_type_size(&ntype, 150, 60, 200); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c index ace0f0c8774..abe8e0190c8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -27,14 +27,16 @@ #include "../node_shader_util.h" +#include "IMB_colormanagement.h" + /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_tex_environment_in[]= { +static bNodeSocketTemplate sh_node_tex_environment_in[] = { { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_tex_environment_out[]= { +static bNodeSocketTemplate sh_node_tex_environment_out[] = { { SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } }; @@ -59,7 +61,8 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, GPUNod Image *ima= (Image*)node->id; ImageUser *iuser= NULL; NodeTexImage *tex = node->storage; - int ncd = tex->color_space == SHD_COLORSPACE_NONE; + int isdata = tex->color_space == SHD_COLORSPACE_NONE; + int ret; if (!ima) return GPU_stack_link(mat, "node_tex_environment_empty", in, out); @@ -69,10 +72,18 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, GPUNod node_shader_gpu_tex_mapping(mat, node, in, out); - if (out[0].link && GPU_material_do_color_management(mat)) - GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); + ret = GPU_stack_link(mat, "node_tex_environment", in, out, GPU_image(ima, iuser, isdata)); - return GPU_stack_link(mat, "node_tex_environment", in, out, GPU_image(ima, iuser, ncd)); + if (ret) { + ImBuf *ibuf = BKE_image_get_ibuf(ima, iuser); + if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && + GPU_material_do_color_management(mat)) + { + GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); + } + } + + return ret; } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c index a7f869155fa..0802ecdea1d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c @@ -29,12 +29,12 @@ /* **************** BLEND ******************** */ -static bNodeSocketTemplate sh_node_tex_gradient_in[]= { +static bNodeSocketTemplate sh_node_tex_gradient_in[] = { { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_tex_gradient_out[]= { +static bNodeSocketTemplate sh_node_tex_gradient_out[] = { { SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index d6c757222b9..9b17f76bd47 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -27,14 +27,16 @@ #include "../node_shader_util.h" +#include "IMB_colormanagement.h" + /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_tex_image_in[]= { +static bNodeSocketTemplate sh_node_tex_image_in[] = { { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_tex_image_out[]= { +static bNodeSocketTemplate sh_node_tex_image_out[] = { { SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Alpha"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } @@ -59,7 +61,8 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, GPUNodeStack Image *ima= (Image*)node->id; ImageUser *iuser= NULL; NodeTexImage *tex = node->storage; - int ncd = tex->color_space == SHD_COLORSPACE_NONE; + int isdata = tex->color_space == SHD_COLORSPACE_NONE; + int ret; if (!ima) return GPU_stack_link(mat, "node_tex_image_empty", in, out); @@ -69,10 +72,18 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, GPUNodeStack node_shader_gpu_tex_mapping(mat, node, in, out); - if (out[0].link && GPU_material_do_color_management(mat)) - GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); + ret = GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata)); - return GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, ncd)); + if (ret) { + ImBuf *ibuf = BKE_image_get_ibuf(ima, iuser); + if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && + GPU_material_do_color_management(mat)) + { + GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); + } + } + + return ret; } /* node type definition */ diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c index b9f1b5c1d21..86feabbcc2b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c @@ -29,14 +29,14 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_tex_magic_in[]= { +static bNodeSocketTemplate sh_node_tex_magic_in[] = { { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, { SOCK_FLOAT, 1, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, { SOCK_FLOAT, 1, N_("Distortion"), 1.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_tex_magic_out[]= { +static bNodeSocketTemplate sh_node_tex_magic_out[] = { { SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c index 60b4f65f0b4..cd4b5743e14 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c @@ -29,7 +29,7 @@ /* **************** MUSGRAVE ******************** */ -static bNodeSocketTemplate sh_node_tex_musgrave_in[]= { +static bNodeSocketTemplate sh_node_tex_musgrave_in[] = { { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, { SOCK_FLOAT, 1, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, { SOCK_FLOAT, 1, N_("Detail"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 16.0f}, @@ -40,7 +40,7 @@ static bNodeSocketTemplate sh_node_tex_musgrave_in[]= { { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_tex_musgrave_out[]= { +static bNodeSocketTemplate sh_node_tex_musgrave_out[] = { { SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c index bd049300048..18788f9e72c 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c @@ -29,7 +29,7 @@ /* **************** NOISE ******************** */ -static bNodeSocketTemplate sh_node_tex_noise_in[]= { +static bNodeSocketTemplate sh_node_tex_noise_in[] = { { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, { SOCK_FLOAT, 1, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, { SOCK_FLOAT, 1, N_("Detail"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 16.0f}, @@ -37,7 +37,7 @@ static bNodeSocketTemplate sh_node_tex_noise_in[]= { { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_tex_noise_out[]= { +static bNodeSocketTemplate sh_node_tex_noise_out[] = { { SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c index 977d689ace6..7a1b853a7f4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c @@ -29,12 +29,12 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_tex_sky_in[]= { +static bNodeSocketTemplate sh_node_tex_sky_in[] = { { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_tex_sky_out[]= { +static bNodeSocketTemplate sh_node_tex_sky_out[] = { { SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c index 22baa3853ac..d4cc24687b3 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c @@ -29,13 +29,13 @@ /* **************** VORONOI ******************** */ -static bNodeSocketTemplate sh_node_tex_voronoi_in[]= { +static bNodeSocketTemplate sh_node_tex_voronoi_in[] = { { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, { SOCK_FLOAT, 1, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_tex_voronoi_out[]= { +static bNodeSocketTemplate sh_node_tex_voronoi_out[] = { { SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c index 8a099521ee9..8b23de0310c 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c @@ -29,7 +29,7 @@ /* **************** WAVE ******************** */ -static bNodeSocketTemplate sh_node_tex_wave_in[]= { +static bNodeSocketTemplate sh_node_tex_wave_in[] = { { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, { SOCK_FLOAT, 1, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, { SOCK_FLOAT, 1, N_("Distortion"), 0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, @@ -38,7 +38,7 @@ static bNodeSocketTemplate sh_node_tex_wave_in[]= { { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_tex_wave_out[]= { +static bNodeSocketTemplate sh_node_tex_wave_out[] = { { SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 0, N_("Fac"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } diff --git a/source/blender/nodes/shader/nodes/node_shader_texture.c b/source/blender/nodes/shader/nodes/node_shader_texture.c index 73c3b846fe3..6d1b3ff6dba 100644 --- a/source/blender/nodes/shader/nodes/node_shader_texture.c +++ b/source/blender/nodes/shader/nodes/node_shader_texture.c @@ -32,14 +32,16 @@ #include "DNA_texture_types.h" +#include "IMB_colormanagement.h" + #include "node_shader_util.h" /* **************** TEXTURE ******************** */ -static bNodeSocketTemplate sh_node_texture_in[]= { +static bNodeSocketTemplate sh_node_texture_in[] = { { SOCK_VECTOR, 1, "Vector", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, /* no limit */ { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_texture_out[]= { +static bNodeSocketTemplate sh_node_texture_out[] = { { SOCK_FLOAT, 0, N_("Value")}, { SOCK_RGBA, 0, N_("Color")}, { SOCK_VECTOR, 0, N_("Normal")}, @@ -52,7 +54,7 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b ShadeInput *shi= ((ShaderCallData *)data)->shi; TexResult texres; bNodeSocket *sock_vector= node->inputs.first; - float vec[3], nor[3]={0.0f, 0.0f, 0.0f}; + float vec[3], nor[3] = {0.0f, 0.0f, 0.0f}; int retval; short which_output = node->custom1; @@ -76,8 +78,8 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b float *fp= in[0]->data; float dxt[3], dyt[3]; - dxt[0]= fp[0]; dxt[1]= dxt[2]= 0.0f; - dyt[0]= fp[1]; dyt[1]= dyt[2]= 0.0f; + dxt[0] = fp[0]; dxt[1] = dxt[2] = 0.0f; + dyt[0] = fp[1]; dyt[1] = dyt[2] = 0.0f; retval= multitex_nodes((Tex *)node->id, vec, dxt, dyt, shi->osatex, &texres, thread, which_output, NULL, NULL); } else @@ -96,9 +98,9 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b /* intensity and color need some handling */ if (texres.talpha) - out[0]->vec[0]= texres.ta; + out[0]->vec[0] = texres.ta; else - out[0]->vec[0]= texres.tin; + out[0]->vec[0] = texres.tin; if ((retval & TEX_RGB) == 0) { copy_v3_fl(out[1]->vec, out[0]->vec[0]); @@ -122,8 +124,19 @@ static int gpu_shader_texture(GPUMaterial *mat, bNode *node, GPUNodeStack *in, G Tex *tex = (Tex*)node->id; if (tex && tex->type == TEX_IMAGE && tex->ima) { - GPUNodeLink *texlink = GPU_image(tex->ima, NULL, FALSE); - return GPU_stack_link(mat, "texture_image", in, out, texlink); + GPUNodeLink *texlink = GPU_image(tex->ima, &tex->iuser, FALSE); + int ret = GPU_stack_link(mat, "texture_image", in, out, texlink); + + if (ret) { + ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); + if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) ==0 && + GPU_material_do_color_management(mat)) + { + GPU_link(mat, "srgb_to_linearrgb", out[1].link, &out[1].link); + } + } + + return ret; } else return 0; diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c index d3094200f83..182487d343e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c +++ b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c @@ -33,11 +33,11 @@ #include "node_shader_util.h" /* **************** VALTORGB ******************** */ -static bNodeSocketTemplate sh_node_valtorgb_in[]= { +static bNodeSocketTemplate sh_node_valtorgb_in[] = { { SOCK_FLOAT, 1, N_("Fac"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_valtorgb_out[]= { +static bNodeSocketTemplate sh_node_valtorgb_out[] = { { SOCK_RGBA, 0, N_("Color")}, { SOCK_FLOAT, 0, N_("Alpha")}, { -1, 0, "" } @@ -53,7 +53,7 @@ static void node_shader_exec_valtorgb(void *UNUSED(data), bNode *node, bNodeStac nodestack_get_vec(&fac, SOCK_FLOAT, in[0]); do_colorband(node->storage, fac, out[0]->vec); - out[1]->vec[0]= out[0]->vec[3]; + out[1]->vec[0] = out[0]->vec[3]; } } @@ -89,11 +89,11 @@ void register_node_type_sh_valtorgb(bNodeTreeType *ttype) /* **************** RGBTOBW ******************** */ -static bNodeSocketTemplate sh_node_rgbtobw_in[]= { +static bNodeSocketTemplate sh_node_rgbtobw_in[] = { { SOCK_RGBA, 1, N_("Color"), 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_rgbtobw_out[]= { +static bNodeSocketTemplate sh_node_rgbtobw_out[] = { { SOCK_FLOAT, 0, N_("Val"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_value.c b/source/blender/nodes/shader/nodes/node_shader_value.c index 8a6c3c87e0d..a3d1e5afec2 100644 --- a/source/blender/nodes/shader/nodes/node_shader_value.c +++ b/source/blender/nodes/shader/nodes/node_shader_value.c @@ -33,7 +33,7 @@ #include "node_shader_util.h" /* **************** VALUE ******************** */ -static bNodeSocketTemplate sh_node_value_out[]= { +static bNodeSocketTemplate sh_node_value_out[] = { /* XXX value nodes use the output sockets for buttons, so we need explicit limits here! */ { SOCK_FLOAT, 0, N_("Value"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, { -1, 0, "" } @@ -54,7 +54,7 @@ static void node_shader_exec_value(void *UNUSED(data), bNode *node, bNodeStack * bNodeSocket *sock= node->outputs.first; float val= ((bNodeSocketValueFloat*)sock->default_value)->value; - out[0]->vec[0]= val; + out[0]->vec[0] = val; } static int gpu_shader_value(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) diff --git a/source/blender/nodes/shader/nodes/node_shader_vectMath.c b/source/blender/nodes/shader/nodes/node_shader_vectMath.c index 007366c6082..2d9f1903c5b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vectMath.c +++ b/source/blender/nodes/shader/nodes/node_shader_vectMath.c @@ -35,16 +35,16 @@ /* **************** VECTOR MATH ******************** */ -static bNodeSocketTemplate sh_node_vect_math_in[]= { - { SOCK_VECTOR, 1, N_("Vector"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, - { SOCK_VECTOR, 1, N_("Vector"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, - { -1, 0, "" } +static bNodeSocketTemplate sh_node_vect_math_in[] = { + { SOCK_VECTOR, 1, N_("Vector"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + { SOCK_VECTOR, 1, N_("Vector"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_vect_math_out[]= { - { SOCK_VECTOR, 0, N_("Vector")}, +static bNodeSocketTemplate sh_node_vect_math_out[] = { + { SOCK_VECTOR, 0, N_("Vector")}, { SOCK_FLOAT, 0, N_("Value")}, - { -1, 0, "" } + { -1, 0, "" } }; static void node_shader_exec_vect_math(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) @@ -55,46 +55,46 @@ static void node_shader_exec_vect_math(void *UNUSED(data), bNode *node, bNodeSta nodestack_get_vec(vec2, SOCK_VECTOR, in[1]); if (node->custom1 == 0) { /* Add */ - out[0]->vec[0]= vec1[0] + vec2[0]; - out[0]->vec[1]= vec1[1] + vec2[1]; - out[0]->vec[2]= vec1[2] + vec2[2]; + out[0]->vec[0] = vec1[0] + vec2[0]; + out[0]->vec[1] = vec1[1] + vec2[1]; + out[0]->vec[2] = vec1[2] + vec2[2]; - out[1]->vec[0]= (fabs(out[0]->vec[0]) + fabs(out[0]->vec[0]) + fabs(out[0]->vec[0])) / 3; + out[1]->vec[0] = (fabs(out[0]->vec[0]) + fabs(out[0]->vec[0]) + fabs(out[0]->vec[0])) / 3; } else if (node->custom1 == 1) { /* Subtract */ - out[0]->vec[0]= vec1[0] - vec2[0]; - out[0]->vec[1]= vec1[1] - vec2[1]; - out[0]->vec[2]= vec1[2] - vec2[2]; + out[0]->vec[0] = vec1[0] - vec2[0]; + out[0]->vec[1] = vec1[1] - vec2[1]; + out[0]->vec[2] = vec1[2] - vec2[2]; - out[1]->vec[0]= (fabs(out[0]->vec[0]) + fabs(out[0]->vec[0]) + fabs(out[0]->vec[0])) / 3; + out[1]->vec[0] = (fabs(out[0]->vec[0]) + fabs(out[0]->vec[0]) + fabs(out[0]->vec[0])) / 3; } else if (node->custom1 == 2) { /* Average */ - out[0]->vec[0]= vec1[0] + vec2[0]; - out[0]->vec[1]= vec1[1] + vec2[1]; - out[0]->vec[2]= vec1[2] + vec2[2]; + out[0]->vec[0] = vec1[0] + vec2[0]; + out[0]->vec[1] = vec1[1] + vec2[1]; + out[0]->vec[2] = vec1[2] + vec2[2]; out[1]->vec[0] = normalize_v3(out[0]->vec ); } else if (node->custom1 == 3) { /* Dot product */ - out[1]->vec[0]= (vec1[0] * vec2[0]) + (vec1[1] * vec2[1]) + (vec1[2] * vec2[2]); + out[1]->vec[0] = (vec1[0] * vec2[0]) + (vec1[1] * vec2[1]) + (vec1[2] * vec2[2]); } else if (node->custom1 == 4) { /* Cross product */ - out[0]->vec[0]= (vec1[1] * vec2[2]) - (vec1[2] * vec2[1]); - out[0]->vec[1]= (vec1[2] * vec2[0]) - (vec1[0] * vec2[2]); - out[0]->vec[2]= (vec1[0] * vec2[1]) - (vec1[1] * vec2[0]); + out[0]->vec[0] = (vec1[1] * vec2[2]) - (vec1[2] * vec2[1]); + out[0]->vec[1] = (vec1[2] * vec2[0]) - (vec1[0] * vec2[2]); + out[0]->vec[2] = (vec1[0] * vec2[1]) - (vec1[1] * vec2[0]); out[1]->vec[0] = normalize_v3(out[0]->vec ); } else if (node->custom1 == 5) { /* Normalize */ if (in[0]->hasinput || !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */ - out[0]->vec[0]= vec1[0]; - out[0]->vec[1]= vec1[1]; - out[0]->vec[2]= vec1[2]; + out[0]->vec[0] = vec1[0]; + out[0]->vec[1] = vec1[1]; + out[0]->vec[2] = vec1[2]; } else { - out[0]->vec[0]= vec2[0]; - out[0]->vec[1]= vec2[1]; - out[0]->vec[2]= vec2[2]; + out[0]->vec[0] = vec2[0]; + out[0]->vec[1] = vec2[1]; + out[0]->vec[2] = vec2[2]; } out[1]->vec[0] = normalize_v3(out[0]->vec ); diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c b/source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c index 366f50ab4fc..5451eb303cc 100644 --- a/source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c +++ b/source/blender/nodes/shader/nodes/node_shader_volume_isotropic.c @@ -29,13 +29,13 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_volume_isotropic_in[]= { +static bNodeSocketTemplate sh_node_volume_isotropic_in[] = { { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Density"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_volume_isotropic_out[]= { +static bNodeSocketTemplate sh_node_volume_isotropic_out[] = { { SOCK_SHADER, 0, N_("Volume")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_transparent.c b/source/blender/nodes/shader/nodes/node_shader_volume_transparent.c index 9d48f613d34..ad7d7fceda3 100644 --- a/source/blender/nodes/shader/nodes/node_shader_volume_transparent.c +++ b/source/blender/nodes/shader/nodes/node_shader_volume_transparent.c @@ -29,13 +29,13 @@ /* **************** OUTPUT ******************** */ -static bNodeSocketTemplate sh_node_volume_transparent_in[]= { +static bNodeSocketTemplate sh_node_volume_transparent_in[] = { { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Density"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate sh_node_volume_transparent_out[]= { +static bNodeSocketTemplate sh_node_volume_transparent_out[] = { { SOCK_SHADER, 0, N_("Volume")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c index 9656d93f1b0..ba94531c259 100644 --- a/source/blender/nodes/texture/node_texture_tree.c +++ b/source/blender/nodes/texture/node_texture_tree.c @@ -4,7 +4,7 @@ * 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. + * 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 @@ -134,7 +134,7 @@ bNodeTreeType ntreeType_Texture = { /* update */ update, /* update_node */ NULL, /* validate_link */ NULL, - /* internal_connect */ node_internal_connect_default + /* update_internal_links */ node_update_internal_links_default }; int ntreeTexTagAnimated(bNodeTree *ntree) @@ -240,19 +240,19 @@ void ntreeTexEndExecTree(bNodeTreeExec *exec, int use_tree_data) } int ntreeTexExecTree( - bNodeTree *nodes, - TexResult *texres, - float *co, - float *dxt, float *dyt, - int osatex, - short thread, - Tex *UNUSED(tex), - short which_output, - int cfra, - int preview, - ShadeInput *shi, - MTex *mtex -) { + bNodeTree *nodes, + TexResult *texres, + float co[3], + float dxt[3], float dyt[3], + int osatex, + const short thread, + Tex *UNUSED(tex), + short which_output, + int cfra, + int preview, + ShadeInput *shi, + MTex *mtex) +{ TexCallData data; float *nor = texres->nor; int retval = TEX_INT; diff --git a/source/blender/nodes/texture/node_texture_util.c b/source/blender/nodes/texture/node_texture_util.c index 53f1aa82f60..06473d800d0 100644 --- a/source/blender/nodes/texture/node_texture_util.c +++ b/source/blender/nodes/texture/node_texture_util.c @@ -4,7 +4,7 @@ * 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. + * 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 @@ -29,7 +29,7 @@ * \ingroup nodes */ - + /* * HOW TEXTURE NODES WORK * @@ -49,8 +49,6 @@ #include #include "node_texture_util.h" -#define PREV_RES 128 /* default preview resolution */ - static void tex_call_delegate(TexDelegate *dg, float *out, TexParams *params, short thread) { if (dg->node->need_exec) { @@ -114,13 +112,13 @@ void params_from_cdata(TexParams *out, TexCallData *in) out->mtex = in->mtex; } -void tex_do_preview(bNode *node, float *co, float *col) +void tex_do_preview(bNode *node, const float coord[2], const float col[4]) { - bNodePreview *preview= node->preview; + bNodePreview *preview = node->preview; if (preview) { - int xs= ((co[0] + 1.0f)*0.5f)*preview->xsize; - int ys= ((co[1] + 1.0f)*0.5f)*preview->ysize; + int xs = ((coord[0] + 1.0f) * 0.5f) * preview->xsize; + int ys = ((coord[1] + 1.0f) * 0.5f) * preview->ysize; nodeAddToPreview(node, col, xs, ys, 0); /* 0 = no color management */ } @@ -134,19 +132,19 @@ void tex_output(bNode *node, bNodeStack **in, bNodeStack *out, TexFn texfn, TexC dg = out->data = MEM_mallocN(sizeof(TexDelegate), "tex delegate"); else dg = out->data; - - dg->cdata= cdata; + + dg->cdata = cdata; dg->fn = texfn; dg->node = node; - memcpy(dg->in, in, MAX_SOCKET * sizeof(bNodeStack*)); + memcpy(dg->in, in, MAX_SOCKET * sizeof(bNodeStack *)); dg->type = out->sockettype; } void ntreeTexCheckCyclics(struct bNodeTree *ntree) { bNode *node; - for (node= ntree->nodes.first; node; node= node->next) { - + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == TEX_NODE_TEXTURE && node->id) { /* custom2 stops the node from rendering */ if (node->custom1) { diff --git a/source/blender/nodes/texture/node_texture_util.h b/source/blender/nodes/texture/node_texture_util.h index e938e6fc419..16dbc2f7bfb 100644 --- a/source/blender/nodes/texture/node_texture_util.h +++ b/source/blender/nodes/texture/node_texture_util.h @@ -79,8 +79,10 @@ typedef struct TexCallData { TexResult *target; + /* all float[3] */ float *co; float *dxt, *dyt; + int osatex; char do_preview; short thread; @@ -94,7 +96,7 @@ typedef struct TexCallData { typedef struct TexParams { float *co; float *dxt, *dyt; - float *previewco; + const float *previewco; int cfra; int osatex; @@ -119,7 +121,7 @@ void tex_input_vec(float *out, bNodeStack *in, TexParams *params, short thread); float tex_input_value(bNodeStack *in, TexParams *params, short thread); void tex_output(bNode *node, bNodeStack **in, bNodeStack *out, TexFn texfn, TexCallData *data); -void tex_do_preview(bNode *node, float *coord, float *col); +void tex_do_preview(bNode *node, const float coord[2], const float col[4]); void params_from_cdata(TexParams *out, TexCallData *in); diff --git a/source/blender/nodes/texture/nodes/node_texture_at.c b/source/blender/nodes/texture/nodes/node_texture_at.c index 9e557705b3f..4c2d276b902 100644 --- a/source/blender/nodes/texture/nodes/node_texture_at.c +++ b/source/blender/nodes/texture/nodes/node_texture_at.c @@ -33,12 +33,12 @@ #include "node_texture_util.h" #include "NOD_texture.h" -static bNodeSocketTemplate inputs[]= { +static bNodeSocketTemplate inputs[] = { { SOCK_RGBA, 1, N_("Texture"), 0.0f, 0.0f, 0.0f, 1.0f }, { SOCK_VECTOR, 1, N_("Coordinates"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_NONE }, { -1, 0, "" } }; -static bNodeSocketTemplate outputs[]= { +static bNodeSocketTemplate outputs[] = { { SOCK_RGBA, 0, N_("Texture") }, { -1, 0, "" } }; diff --git a/source/blender/nodes/texture/nodes/node_texture_bricks.c b/source/blender/nodes/texture/nodes/node_texture_bricks.c index f6259962529..b4f81f08e43 100644 --- a/source/blender/nodes/texture/nodes/node_texture_bricks.c +++ b/source/blender/nodes/texture/nodes/node_texture_bricks.c @@ -35,7 +35,7 @@ #include -static bNodeSocketTemplate inputs[]= { +static bNodeSocketTemplate inputs[] = { { SOCK_RGBA, 1, N_("Bricks 1"), 0.596f, 0.282f, 0.0f, 1.0f }, { SOCK_RGBA, 1, N_("Bricks 2"), 0.632f, 0.504f, 0.05f, 1.0f }, { SOCK_RGBA, 1, N_("Mortar"), 0.0f, 0.0f, 0.0f, 1.0f }, @@ -45,7 +45,7 @@ static bNodeSocketTemplate inputs[]= { { SOCK_FLOAT, 1, N_("Row Height"), 0.25f, 0.0f, 0.0f, 0.0f, 0.001f, 99.0f, PROP_UNSIGNED }, { -1, 0, "" } }; -static bNodeSocketTemplate outputs[]= { +static bNodeSocketTemplate outputs[] = { { SOCK_RGBA, 0, N_("Color")}, { -1, 0, "" } }; @@ -66,7 +66,7 @@ static float noise(int n) /* fast integer noise */ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread) { - float *co = p->co; + const float *co = p->co; float x = co[0]; float y = co[1]; diff --git a/source/blender/nodes/texture/nodes/node_texture_checker.c b/source/blender/nodes/texture/nodes/node_texture_checker.c index cd9c3170cf7..1f653d1f7b9 100644 --- a/source/blender/nodes/texture/nodes/node_texture_checker.c +++ b/source/blender/nodes/texture/nodes/node_texture_checker.c @@ -34,13 +34,13 @@ #include "NOD_texture.h" #include -static bNodeSocketTemplate inputs[]= { +static bNodeSocketTemplate inputs[] = { { SOCK_RGBA, 1, N_("Color1"), 1.0f, 0.0f, 0.0f, 1.0f }, { SOCK_RGBA, 1, N_("Color2"), 1.0f, 1.0f, 1.0f, 1.0f }, { SOCK_FLOAT, 1, N_("Size"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 100.0f, PROP_UNSIGNED }, { -1, 0, "" } }; -static bNodeSocketTemplate outputs[]= { +static bNodeSocketTemplate outputs[] = { { SOCK_RGBA, 0, N_("Color") }, { -1, 0, "" } }; @@ -62,7 +62,7 @@ static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack ** } else { tex_input_rgba(out, in[1], p, thread); - } + } } static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) diff --git a/source/blender/nodes/texture/nodes/node_texture_common.c b/source/blender/nodes/texture/nodes/node_texture_common.c index 1eaf9b2b0fe..41bfd0ae00a 100644 --- a/source/blender/nodes/texture/nodes/node_texture_common.c +++ b/source/blender/nodes/texture/nodes/node_texture_common.c @@ -148,128 +148,3 @@ void register_node_type_tex_group(bNodeTreeType *ttype) nodeRegisterType(ttype, &ntype); } - - -/**** FOR LOOP ****/ - -#if 0 /* XXX loop nodes don't work nicely with current trees */ -static void forloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out) -{ - bNodeTreeExec *exec= (bNodeTreeExec*)nodedata; - bNodeThreadStack *nts; - int iterations= (int)in[0]->vec[0]; - bNodeSocket *sock; - bNodeStack *ns; - int iteration; - - /* XXX same behavior as trunk: all nodes inside group are executed. - * it's stupid, but just makes it work. compo redesign will do this better. - */ - { - bNode *inode; - for (inode=exec->nodetree->nodes.first; inode; inode=inode->next) - inode->need_exec = 1; - } - - nts = ntreeGetThreadStack(exec, thread); - - /* "Iteration" socket */ - sock = exec->nodetree->inputs.first; - ns = node_get_socket_stack(nts->stack, sock); - -// group_copy_inputs(node, in, nts->stack); - for (iteration=0; iteration < iterations; ++iteration) { - /* first input contains current iteration counter */ - ns->vec[0] = (float)iteration; - ns->vec[1]=ns->vec[2]=ns->vec[3] = 0.0f; - -// if (iteration > 0) -// loop_init_iteration(exec->nodetree, nts->stack); -// ntreeExecThreadNodes(exec, nts, data, thread); - } -// loop_copy_outputs(node, in, out, exec->stack); - - ntreeReleaseThreadStack(nts); -} - -void register_node_type_tex_forloop(bNodeTreeType *ttype) -{ - static bNodeType ntype; - - node_type_base(ttype, &ntype, NODE_FORLOOP, "For", NODE_CLASS_GROUP, NODE_OPTIONS); - node_type_socket_templates(&ntype, NULL, NULL); - node_type_size(&ntype, 120, 60, 200); - node_type_label(&ntype, node_group_label); - node_type_init(&ntype, node_forloop_init); - node_type_valid(&ntype, node_group_valid); - node_type_template(&ntype, node_forloop_template); - node_type_update(&ntype, NULL, node_group_verify); - node_type_tree(&ntype, node_forloop_init_tree, node_loop_update_tree); - node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); - node_type_exec_new(&ntype, group_initexec, group_freeexec, forloop_execute); - - nodeRegisterType(ttype, &ntype); -} -#endif - -/**** WHILE LOOP ****/ - -#if 0 /* XXX loop nodes don't work nicely with current trees */ -static void whileloop_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out) -{ - bNodeTreeExec *exec= (bNodeTreeExec*)nodedata; - bNodeThreadStack *nts; - int condition= (in[0]->vec[0] > 0.0f); - bNodeSocket *sock; - bNodeStack *ns; - int iteration; - - /* XXX same behavior as trunk: all nodes inside group are executed. - * it's stupid, but just makes it work. compo redesign will do this better. - */ - { - bNode *inode; - for (inode=exec->nodetree->nodes.first; inode; inode=inode->next) - inode->need_exec = 1; - } - - nts = ntreeGetThreadStack(exec, thread); - - /* "Condition" socket */ - sock = exec->nodetree->outputs.first; - ns = node_get_socket_stack(nts->stack, sock); - - iteration = 0; -// group_copy_inputs(node, in, nts->stack); - while (condition && iteration < node->custom1) { -// if (iteration > 0) -// loop_init_iteration(exec->nodetree, nts->stack); -// ntreeExecThreadNodes(exec, nts, data, thread); - - condition = (ns->vec[0] > 0.0f); - ++iteration; - } -// loop_copy_outputs(node, in, out, exec->stack); - - ntreeReleaseThreadStack(nts); -} - -void register_node_type_tex_whileloop(bNodeTreeType *ttype) -{ - static bNodeType ntype; - - node_type_base(ttype, &ntype, NODE_WHILELOOP, "While", NODE_CLASS_GROUP, NODE_OPTIONS); - node_type_socket_templates(&ntype, NULL, NULL); - node_type_size(&ntype, 120, 60, 200); - node_type_label(&ntype, node_group_label); - node_type_init(&ntype, node_whileloop_init); - node_type_valid(&ntype, node_group_valid); - node_type_template(&ntype, node_whileloop_template); - node_type_update(&ntype, NULL, node_group_verify); - node_type_tree(&ntype, node_whileloop_init_tree, node_loop_update_tree); - node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); - node_type_exec_new(&ntype, group_initexec, group_freeexec, whileloop_execute); - - nodeRegisterType(ttype, &ntype); -} -#endif diff --git a/source/blender/nodes/texture/nodes/node_texture_compose.c b/source/blender/nodes/texture/nodes/node_texture_compose.c index 77521190590..25da4f19e52 100644 --- a/source/blender/nodes/texture/nodes/node_texture_compose.c +++ b/source/blender/nodes/texture/nodes/node_texture_compose.c @@ -33,14 +33,14 @@ #include "node_texture_util.h" #include "NOD_texture.h" -static bNodeSocketTemplate inputs[]= { +static bNodeSocketTemplate inputs[] = { { SOCK_FLOAT, 1, N_("Red"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_UNSIGNED }, { SOCK_FLOAT, 1, N_("Green"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_UNSIGNED }, { SOCK_FLOAT, 1, N_("Blue"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_UNSIGNED }, { SOCK_FLOAT, 1, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_UNSIGNED }, { -1, 0, "" } }; -static bNodeSocketTemplate outputs[]= { +static bNodeSocketTemplate outputs[] = { { SOCK_RGBA, 0, N_("Color") }, { -1, 0, "" } }; diff --git a/source/blender/nodes/texture/nodes/node_texture_coord.c b/source/blender/nodes/texture/nodes/node_texture_coord.c index 2add5c820eb..971520ebc38 100644 --- a/source/blender/nodes/texture/nodes/node_texture_coord.c +++ b/source/blender/nodes/texture/nodes/node_texture_coord.c @@ -33,7 +33,7 @@ #include "node_texture_util.h" #include "NOD_texture.h" -static bNodeSocketTemplate outputs[]= { +static bNodeSocketTemplate outputs[] = { { SOCK_VECTOR, 0, N_("Coordinates") }, { -1, 0, "" } }; diff --git a/source/blender/nodes/texture/nodes/node_texture_curves.c b/source/blender/nodes/texture/nodes/node_texture_curves.c index 6ccb5e1e83f..5980f938938 100644 --- a/source/blender/nodes/texture/nodes/node_texture_curves.c +++ b/source/blender/nodes/texture/nodes/node_texture_curves.c @@ -36,7 +36,7 @@ /* **************** CURVE Time ******************** */ /* custom1 = sfra, custom2 = efra */ -static bNodeSocketTemplate time_outputs[]= { +static bNodeSocketTemplate time_outputs[] = { { SOCK_FLOAT, 0, N_("Value") }, { -1, 0, "" } }; @@ -83,12 +83,12 @@ void register_node_type_tex_curve_time(bNodeTreeType *ttype) } /* **************** CURVE RGB ******************** */ -static bNodeSocketTemplate rgb_inputs[]= { +static bNodeSocketTemplate rgb_inputs[] = { { SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate rgb_outputs[]= { +static bNodeSocketTemplate rgb_outputs[] = { { SOCK_RGBA, 0, N_("Color")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/texture/nodes/node_texture_decompose.c b/source/blender/nodes/texture/nodes/node_texture_decompose.c index eae34e2ce47..a2875c31d9e 100644 --- a/source/blender/nodes/texture/nodes/node_texture_decompose.c +++ b/source/blender/nodes/texture/nodes/node_texture_decompose.c @@ -34,11 +34,11 @@ #include "NOD_texture.h" #include -static bNodeSocketTemplate inputs[]= { +static bNodeSocketTemplate inputs[] = { { SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f }, { -1, 0, "" } }; -static bNodeSocketTemplate outputs[]= { +static bNodeSocketTemplate outputs[] = { { SOCK_FLOAT, 0, N_("Red") }, { SOCK_FLOAT, 0, N_("Green") }, { SOCK_FLOAT, 0, N_("Blue") }, diff --git a/source/blender/nodes/texture/nodes/node_texture_distance.c b/source/blender/nodes/texture/nodes/node_texture_distance.c index 29f08a0ded0..8c3b1555d5d 100644 --- a/source/blender/nodes/texture/nodes/node_texture_distance.c +++ b/source/blender/nodes/texture/nodes/node_texture_distance.c @@ -35,13 +35,13 @@ #include "node_texture_util.h" #include "NOD_texture.h" -static bNodeSocketTemplate inputs[]= { +static bNodeSocketTemplate inputs[] = { { SOCK_VECTOR, 1, N_("Coordinate 1"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_NONE }, { SOCK_VECTOR, 1, N_("Coordinate 2"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_NONE }, - { -1, 0, "" } + { -1, 0, "" } }; -static bNodeSocketTemplate outputs[]= { +static bNodeSocketTemplate outputs[] = { { SOCK_FLOAT, 0, N_("Value") }, { -1, 0, "" } }; diff --git a/source/blender/nodes/texture/nodes/node_texture_hueSatVal.c b/source/blender/nodes/texture/nodes/node_texture_hueSatVal.c index 6863eab9150..b5e9969a830 100644 --- a/source/blender/nodes/texture/nodes/node_texture_hueSatVal.c +++ b/source/blender/nodes/texture/nodes/node_texture_hueSatVal.c @@ -34,7 +34,7 @@ #include "NOD_texture.h" -static bNodeSocketTemplate inputs[]= { +static bNodeSocketTemplate inputs[] = { { SOCK_FLOAT, 1, N_("Hue"), 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.5f, PROP_NONE }, { SOCK_FLOAT, 1, N_("Saturation"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, PROP_FACTOR }, { SOCK_FLOAT, 1, N_("Value"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, PROP_FACTOR }, @@ -42,7 +42,7 @@ static bNodeSocketTemplate inputs[]= { { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f }, { -1, 0, "" } }; -static bNodeSocketTemplate outputs[]= { +static bNodeSocketTemplate outputs[] = { { SOCK_RGBA, 0, N_("Color") }, { -1, 0, "" } }; @@ -56,14 +56,14 @@ static void do_hue_sat_fac(bNode *UNUSED(node), float *out, float hue, float sat hsv[0]+= (hue - 0.5f); if (hsv[0]>1.0f) hsv[0]-=1.0f; else if (hsv[0]<0.0f) hsv[0]+= 1.0f; hsv[1]*= sat; - if (hsv[1]>1.0f) hsv[1]= 1.0f; else if (hsv[1]<0.0f) hsv[1]= 0.0f; + if (hsv[1]>1.0f) hsv[1] = 1.0f; else if (hsv[1]<0.0f) hsv[1] = 0.0f; hsv[2]*= val; - if (hsv[2]>1.0f) hsv[2]= 1.0f; else if (hsv[2]<0.0f) hsv[2]= 0.0f; + if (hsv[2]>1.0f) hsv[2] = 1.0f; else if (hsv[2]<0.0f) hsv[2] = 0.0f; hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col+1, col+2); - out[0]= mfac*in[0] + fac*col[0]; - out[1]= mfac*in[1] + fac*col[1]; - out[2]= mfac*in[2] + fac*col[2]; + out[0] = mfac*in[0] + fac*col[0]; + out[1] = mfac*in[1] + fac*col[1]; + out[2] = mfac*in[2] + fac*col[2]; } else { copy_v4_v4(out, in); diff --git a/source/blender/nodes/texture/nodes/node_texture_image.c b/source/blender/nodes/texture/nodes/node_texture_image.c index 7ce91c37295..f3fdaf0bb64 100644 --- a/source/blender/nodes/texture/nodes/node_texture_image.c +++ b/source/blender/nodes/texture/nodes/node_texture_image.c @@ -33,7 +33,7 @@ #include "node_texture_util.h" #include "NOD_texture.h" -static bNodeSocketTemplate outputs[]= { +static bNodeSocketTemplate outputs[] = { { SOCK_RGBA, 0, N_("Image")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/texture/nodes/node_texture_invert.c b/source/blender/nodes/texture/nodes/node_texture_invert.c index 0339c3f0cf2..9c2963d2dc2 100644 --- a/source/blender/nodes/texture/nodes/node_texture_invert.c +++ b/source/blender/nodes/texture/nodes/node_texture_invert.c @@ -34,14 +34,14 @@ #include "NOD_texture.h" /* **************** INVERT ******************** */ -static bNodeSocketTemplate inputs[]= { - { SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f}, - { -1, 0, "" } +static bNodeSocketTemplate inputs[] = { + { SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } }; -static bNodeSocketTemplate outputs[]= { - { SOCK_RGBA, 0, N_("Color")}, - { -1, 0, "" } +static bNodeSocketTemplate outputs[] = { + { SOCK_RGBA, 0, N_("Color")}, + { -1, 0, "" } }; static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **in, short thread) diff --git a/source/blender/nodes/texture/nodes/node_texture_math.c b/source/blender/nodes/texture/nodes/node_texture_math.c index 36e9cac0827..95d70ccc7d6 100644 --- a/source/blender/nodes/texture/nodes/node_texture_math.c +++ b/source/blender/nodes/texture/nodes/node_texture_math.c @@ -35,15 +35,15 @@ /* **************** SCALAR MATH ******************** */ -static bNodeSocketTemplate inputs[]= { - { SOCK_FLOAT, 1, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -100.0f, 100.0f, PROP_NONE}, - { SOCK_FLOAT, 1, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -100.0f, 100.0f, PROP_NONE}, - { -1, 0, "" } +static bNodeSocketTemplate inputs[] = { + { SOCK_FLOAT, 1, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -100.0f, 100.0f, PROP_NONE}, + { SOCK_FLOAT, 1, N_("Value"), 0.5f, 0.5f, 0.5f, 1.0f, -100.0f, 100.0f, PROP_NONE}, + { -1, 0, "" } }; -static bNodeSocketTemplate outputs[]= { - { SOCK_FLOAT, 0, N_("Value")}, - { -1, 0, "" } +static bNodeSocketTemplate outputs[] = { + { SOCK_FLOAT, 0, N_("Value")}, + { -1, 0, "" } }; static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, short thread) @@ -112,7 +112,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor { /* Only raise negative numbers by full integers */ if ( in0 >= 0 ) { - out[0]= pow(in0, in1); + out[0] = pow(in0, in1); } else { float y_mod_1 = fmod(in1, 1); @@ -178,7 +178,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor fprintf(stderr, "%s:%d: unhandeld value in switch statement: %d\n", __FILE__, __LINE__, node->custom1); - } + } } static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) diff --git a/source/blender/nodes/texture/nodes/node_texture_mixRgb.c b/source/blender/nodes/texture/nodes/node_texture_mixRgb.c index bf6cb7a3262..fe04854c734 100644 --- a/source/blender/nodes/texture/nodes/node_texture_mixRgb.c +++ b/source/blender/nodes/texture/nodes/node_texture_mixRgb.c @@ -34,13 +34,13 @@ #include "NOD_texture.h" /* **************** MIX RGB ******************** */ -static bNodeSocketTemplate inputs[]= { +static bNodeSocketTemplate inputs[] = { { SOCK_FLOAT, 1, N_("Factor"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR }, { SOCK_RGBA, 1, N_("Color1"), 0.5f, 0.5f, 0.5f, 1.0f }, { SOCK_RGBA, 1, N_("Color2"), 0.5f, 0.5f, 0.5f, 1.0f }, { -1, 0, "" } }; -static bNodeSocketTemplate outputs[]= { +static bNodeSocketTemplate outputs[] = { { SOCK_RGBA, 0, N_("Color") }, { -1, 0, "" } }; diff --git a/source/blender/nodes/texture/nodes/node_texture_output.c b/source/blender/nodes/texture/nodes/node_texture_output.c index ce22bc00a55..2f5efe8c45e 100644 --- a/source/blender/nodes/texture/nodes/node_texture_output.c +++ b/source/blender/nodes/texture/nodes/node_texture_output.c @@ -34,7 +34,7 @@ #include "NOD_texture.h" /* **************** COMPOSITE ******************** */ -static bNodeSocketTemplate inputs[]= { +static bNodeSocketTemplate inputs[] = { { SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, PROP_DIRECTION}, { -1, 0, "" } @@ -65,7 +65,7 @@ static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(o tex_input_rgba(&target->tr, in[0], ¶ms, cdata->thread); target->tin = (target->tr + target->tg + target->tb) / 3.0f; - target->talpha = 1; + target->talpha = TRUE; if (target->nor) { if (in[1] && in[1]->hasinput) @@ -170,7 +170,7 @@ void register_node_type_tex_output(bNodeTreeType *ttype) node_type_exec(&ntype, exec); /* Do not allow muting output. */ - node_type_internal_connect(&ntype, NULL); + node_type_internal_links(&ntype, NULL); nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/texture/nodes/node_texture_proc.c b/source/blender/nodes/texture/nodes/node_texture_proc.c index 102f6e1c428..8876d98b9b2 100644 --- a/source/blender/nodes/texture/nodes/node_texture_proc.c +++ b/source/blender/nodes/texture/nodes/node_texture_proc.c @@ -40,12 +40,12 @@ */ -static bNodeSocketTemplate outputs_both[]= { +static bNodeSocketTemplate outputs_both[] = { { SOCK_RGBA, 0, N_("Color"), 1.0f, 0.0f, 0.0f, 1.0f }, { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, PROP_DIRECTION }, { -1, 0, "" } }; -static bNodeSocketTemplate outputs_color_only[]= { +static bNodeSocketTemplate outputs_color_only[] = { { SOCK_RGBA, 0, N_("Color") }, { -1, 0, "" } }; @@ -57,7 +57,7 @@ static bNodeSocketTemplate outputs_color_only[]= { { SOCK_RGBA, 1, "Color 2", 1.0f, 1.0f, 1.0f, 1.0f } /* Calls multitex and copies the result to the outputs. Called by xxx_exec, which handles inputs. */ -static void do_proc(float *result, TexParams *p, float *col1, float *col2, char is_normal, Tex *tex, short thread) +static void do_proc(float *result, TexParams *p, const float col1[4], const float col2[4], char is_normal, Tex *tex, const short thread) { TexResult texres; int textype; @@ -69,7 +69,7 @@ static void do_proc(float *result, TexParams *p, float *col1, float *col2, char texres.nor = NULL; textype = multitex_nodes(tex, p->co, p->dxt, p->dyt, p->osatex, - &texres, thread, 0, p->shi, p->mtex); + &texres, thread, 0, p->shi, p->mtex); if (is_normal) return; @@ -83,7 +83,7 @@ static void do_proc(float *result, TexParams *p, float *col1, float *col2, char } } -typedef void (*MapFn) (Tex *tex, bNodeStack **in, TexParams *p, short thread); +typedef void (*MapFn) (Tex *tex, bNodeStack **in, TexParams *p, const short thread); static void texfn( float *result, @@ -138,7 +138,7 @@ static int count_outputs(bNode *node) /* --- VORONOI -- */ -static bNodeSocketTemplate voronoi_inputs[]= { +static bNodeSocketTemplate voronoi_inputs[] = { COMMON_INPUTS, { SOCK_FLOAT, 1, N_("W1"), 1.0f, 0.0f, 0.0f, 0.0f, -2.0f, 2.0f, PROP_NONE }, { SOCK_FLOAT, 1, N_("W2"), 0.0f, 0.0f, 0.0f, 0.0f, -2.0f, 2.0f, PROP_NONE }, @@ -163,7 +163,7 @@ static void voronoi_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short th ProcDef(voronoi) /* --- BLEND -- */ -static bNodeSocketTemplate blend_inputs[]= { +static bNodeSocketTemplate blend_inputs[] = { COMMON_INPUTS, { -1, 0, "" } }; @@ -171,7 +171,7 @@ ProcNoInputs(blend) ProcDef(blend) /* -- MAGIC -- */ -static bNodeSocketTemplate magic_inputs[]= { +static bNodeSocketTemplate magic_inputs[] = { COMMON_INPUTS, { SOCK_FLOAT, 1, N_("Turbulence"), 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 200.0f, PROP_UNSIGNED }, { -1, 0, "" } @@ -183,7 +183,7 @@ static void magic_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thre ProcDef(magic) /* --- MARBLE --- */ -static bNodeSocketTemplate marble_inputs[]= { +static bNodeSocketTemplate marble_inputs[] = { COMMON_INPUTS, { SOCK_FLOAT, 1, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED }, { SOCK_FLOAT, 1, N_("Turbulence"), 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 200.0f, PROP_UNSIGNED }, @@ -197,7 +197,7 @@ static void marble_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thr ProcDef(marble) /* --- CLOUDS --- */ -static bNodeSocketTemplate clouds_inputs[]= { +static bNodeSocketTemplate clouds_inputs[] = { COMMON_INPUTS, { SOCK_FLOAT, 1, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED }, { -1, 0, "" } @@ -209,7 +209,7 @@ static void clouds_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short thr ProcDef(clouds) /* --- DISTORTED NOISE --- */ -static bNodeSocketTemplate distnoise_inputs[]= { +static bNodeSocketTemplate distnoise_inputs[] = { COMMON_INPUTS, { SOCK_FLOAT, 1, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED }, { SOCK_FLOAT, 1, N_("Distortion"), 1.00f, 0.0f, 0.0f, 0.0f, 0.0000f, 10.0f, PROP_UNSIGNED }, @@ -223,7 +223,7 @@ static void distnoise_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short ProcDef(distnoise) /* --- WOOD --- */ -static bNodeSocketTemplate wood_inputs[]= { +static bNodeSocketTemplate wood_inputs[] = { COMMON_INPUTS, { SOCK_FLOAT, 1, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED }, { SOCK_FLOAT, 1, N_("Turbulence"), 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 200.0f, PROP_UNSIGNED }, @@ -237,7 +237,7 @@ static void wood_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short threa ProcDef(wood) /* --- MUSGRAVE --- */ -static bNodeSocketTemplate musgrave_inputs[]= { +static bNodeSocketTemplate musgrave_inputs[] = { COMMON_INPUTS, { SOCK_FLOAT, 1, N_("H"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED }, { SOCK_FLOAT, 1, N_("Lacunarity"), 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 6.0f, PROP_UNSIGNED }, @@ -258,7 +258,7 @@ static void musgrave_map_inputs(Tex *tex, bNodeStack **in, TexParams *p, short t ProcDef(musgrave) /* --- NOISE --- */ -static bNodeSocketTemplate noise_inputs[]= { +static bNodeSocketTemplate noise_inputs[] = { COMMON_INPUTS, { -1, 0, "" } }; @@ -266,7 +266,7 @@ ProcNoInputs(noise) ProcDef(noise) /* --- STUCCI --- */ -static bNodeSocketTemplate stucci_inputs[]= { +static bNodeSocketTemplate stucci_inputs[] = { COMMON_INPUTS, { SOCK_FLOAT, 1, N_("Size"), 0.25f, 0.0f, 0.0f, 0.0f, 0.0001f, 2.0f, PROP_UNSIGNED }, { SOCK_FLOAT, 1, N_("Turbulence"), 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 200.0f, PROP_UNSIGNED }, diff --git a/source/blender/nodes/texture/nodes/node_texture_rotate.c b/source/blender/nodes/texture/nodes/node_texture_rotate.c index a7832c8c180..1b1d57044a3 100644 --- a/source/blender/nodes/texture/nodes/node_texture_rotate.c +++ b/source/blender/nodes/texture/nodes/node_texture_rotate.c @@ -35,19 +35,19 @@ #include "node_texture_util.h" #include "NOD_texture.h" -static bNodeSocketTemplate inputs[]= { +static bNodeSocketTemplate inputs[] = { { SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_FLOAT, 1, N_("Turns"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_NONE }, { SOCK_VECTOR, 1, N_("Axis"), 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, PROP_DIRECTION }, - { -1, 0, "" } + { -1, 0, "" } }; -static bNodeSocketTemplate outputs[]= { - { SOCK_RGBA, 0, N_("Color")}, - { -1, 0, "" } +static bNodeSocketTemplate outputs[] = { + { SOCK_RGBA, 0, N_("Color")}, + { -1, 0, "" } }; -static void rotate(float new_co[3], float a, float ax[3], float co[3]) +static void rotate(float new_co[3], float a, float ax[3], const float co[3]) { float para[3]; float perp[3]; diff --git a/source/blender/nodes/texture/nodes/node_texture_scale.c b/source/blender/nodes/texture/nodes/node_texture_scale.c index 130a21ba84d..56562724fb9 100644 --- a/source/blender/nodes/texture/nodes/node_texture_scale.c +++ b/source/blender/nodes/texture/nodes/node_texture_scale.c @@ -33,15 +33,15 @@ #include #include "node_texture_util.h" -static bNodeSocketTemplate inputs[]= { +static bNodeSocketTemplate inputs[] = { { SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f }, { SOCK_VECTOR, 1, N_("Scale"), 1.0f, 1.0f, 1.0f, 0.0f, -10.0f, 10.0f, PROP_XYZ }, - { -1, 0, "" } + { -1, 0, "" } }; -static bNodeSocketTemplate outputs[]= { - { SOCK_RGBA, 0, N_("Color")}, - { -1, 0, "" } +static bNodeSocketTemplate outputs[] = { + { SOCK_RGBA, 0, N_("Color")}, + { -1, 0, "" } }; static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **in, short thread) diff --git a/source/blender/nodes/texture/nodes/node_texture_texture.c b/source/blender/nodes/texture/nodes/node_texture_texture.c index 4832f19f2c7..cc7367a7632 100644 --- a/source/blender/nodes/texture/nodes/node_texture_texture.c +++ b/source/blender/nodes/texture/nodes/node_texture_texture.c @@ -35,13 +35,13 @@ #include "RE_shader_ext.h" -static bNodeSocketTemplate inputs[]= { +static bNodeSocketTemplate inputs[] = { { SOCK_RGBA, 1, N_("Color1"), 1.0f, 1.0f, 1.0f, 1.0f }, { SOCK_RGBA, 1, N_("Color2"), 0.0f, 0.0f, 0.0f, 1.0f }, { -1, 0, "" } }; -static bNodeSocketTemplate outputs[]= { +static bNodeSocketTemplate outputs[] = { { SOCK_RGBA, 0, N_("Color") }, { -1, 0, "" } }; diff --git a/source/blender/nodes/texture/nodes/node_texture_translate.c b/source/blender/nodes/texture/nodes/node_texture_translate.c index 85f857ca2be..a95cb00a47d 100644 --- a/source/blender/nodes/texture/nodes/node_texture_translate.c +++ b/source/blender/nodes/texture/nodes/node_texture_translate.c @@ -34,15 +34,15 @@ #include "node_texture_util.h" #include "NOD_texture.h" -static bNodeSocketTemplate inputs[]= { +static bNodeSocketTemplate inputs[] = { { SOCK_RGBA, 1, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_VECTOR, 1, N_("Offset"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f, PROP_TRANSLATION }, - { -1, 0, "" } + { -1, 0, "" } }; -static bNodeSocketTemplate outputs[]= { - { SOCK_RGBA, 0, N_("Color")}, - { -1, 0, "" } +static bNodeSocketTemplate outputs[] = { + { SOCK_RGBA, 0, N_("Color")}, + { -1, 0, "" } }; static void colorfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **in, short thread) diff --git a/source/blender/nodes/texture/nodes/node_texture_valToNor.c b/source/blender/nodes/texture/nodes/node_texture_valToNor.c index 2d107b87578..bbfc1fa616b 100644 --- a/source/blender/nodes/texture/nodes/node_texture_valToNor.c +++ b/source/blender/nodes/texture/nodes/node_texture_valToNor.c @@ -33,23 +33,23 @@ #include "node_texture_util.h" #include "NOD_texture.h" -static bNodeSocketTemplate inputs[]= { +static bNodeSocketTemplate inputs[] = { { SOCK_FLOAT, 1, N_("Val"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE }, { SOCK_FLOAT, 1, N_("Nabla"), 0.025f, 0.0f, 0.0f, 0.0f, 0.001f, 0.1f, PROP_UNSIGNED }, - { -1, 0, "" } + { -1, 0, "" } }; -static bNodeSocketTemplate outputs[]= { - { SOCK_VECTOR, 0, N_("Normal") }, - { -1, 0, "" } +static bNodeSocketTemplate outputs[] = { + { SOCK_VECTOR, 0, N_("Normal") }, + { -1, 0, "" } }; static void normalfn(float *out, TexParams *p, bNode *UNUSED(node), bNodeStack **in, short thread) { float new_co[3]; - float *co = p->co; + const float *co = p->co; - float nabla = tex_input_value(in[1], p, thread); + float nabla = tex_input_value(in[1], p, thread); float val; float nor[3]; diff --git a/source/blender/nodes/texture/nodes/node_texture_valToRgb.c b/source/blender/nodes/texture/nodes/node_texture_valToRgb.c index 515613509f6..78635453fc1 100644 --- a/source/blender/nodes/texture/nodes/node_texture_valToRgb.c +++ b/source/blender/nodes/texture/nodes/node_texture_valToRgb.c @@ -34,11 +34,11 @@ #include "NOD_texture.h" /* **************** VALTORGB ******************** */ -static bNodeSocketTemplate valtorgb_in[]= { +static bNodeSocketTemplate valtorgb_in[] = { { SOCK_FLOAT, 1, N_("Fac"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, { -1, 0, "" } }; -static bNodeSocketTemplate valtorgb_out[]= { +static bNodeSocketTemplate valtorgb_out[] = { { SOCK_RGBA, 0, N_("Color")}, { -1, 0, "" } }; @@ -77,11 +77,11 @@ void register_node_type_tex_valtorgb(bNodeTreeType *ttype) } /* **************** RGBTOBW ******************** */ -static bNodeSocketTemplate rgbtobw_in[]= { +static bNodeSocketTemplate rgbtobw_in[] = { { SOCK_RGBA, 1, N_("Color"), 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocketTemplate rgbtobw_out[]= { +static bNodeSocketTemplate rgbtobw_out[] = { { SOCK_FLOAT, 0, N_("Val"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { -1, 0, "" } }; diff --git a/source/blender/nodes/texture/nodes/node_texture_viewer.c b/source/blender/nodes/texture/nodes/node_texture_viewer.c index bc31bef59d8..5cb8d8c438c 100644 --- a/source/blender/nodes/texture/nodes/node_texture_viewer.c +++ b/source/blender/nodes/texture/nodes/node_texture_viewer.c @@ -66,7 +66,7 @@ void register_node_type_tex_viewer(bNodeTreeType *ttype) node_type_exec(&ntype, exec); /* Do not allow muting viewer node. */ - node_type_internal_connect(&ntype, NULL); + node_type_internal_links(&ntype, NULL); nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/opencl/CMakeLists.txt b/source/blender/opencl/CMakeLists.txt index 20dcf33d363..b3c76db1bca 100644 --- a/source/blender/opencl/CMakeLists.txt +++ b/source/blender/opencl/CMakeLists.txt @@ -1,4 +1,3 @@ -# $Id: CMakeLists.txt 14444 2008-04-16 22:40:48Z hos $ # ***** BEGIN GPL LICENSE BLOCK ***** # # This program is free software; you can redistribute it and/or diff --git a/source/blender/opencl/intern/OCL_opencl.c b/source/blender/opencl/intern/OCL_opencl.c index fa22acbc1a2..e3130e16bde 100644 --- a/source/blender/opencl/intern/OCL_opencl.c +++ b/source/blender/opencl/intern/OCL_opencl.c @@ -22,14 +22,14 @@ #include "OCL_opencl.h" -void OCL_init() +void OCL_init(void) { #ifdef _WIN32 - const char *path = "OpenCL.dll"; + const char *path = "OpenCL.dll"; #elif defined(__APPLE__) - const char *path = "/Library/Frameworks/OpenCL.framework/OpenCL"; + const char *path = "/Library/Frameworks/OpenCL.framework/OpenCL"; #else - const char *path = "libOpenCL.so"; + const char *path = "libOpenCL.so"; #endif clewInit(path); diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index 83a40ecc068..9bd45d2b759 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -80,6 +80,7 @@ int BPY_button_exec(struct bContext *C, const char *expr, double *value, const int BPY_string_exec(struct bContext *C, const char *expr); void BPY_DECREF(void *pyob_ptr); /* Py_DECREF() */ +void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr); int BPY_context_member_get(struct bContext *C, const char *member, struct bContextDataResult *result); void BPY_context_set(struct bContext *C); void BPY_context_update(struct bContext *C); diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index d7d9baf35ed..2cae10101d1 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -189,7 +189,7 @@ static int bpy_bm_elem_index_set(BPy_BMElem *self, PyObject *value, void *UNUSED /* Mesh * ^^^^ */ -/* doc-strings for all uses of this funcion */ +/* doc-strings for all uses of this function */ PyDoc_STRVAR(bpy_bmvertseq_doc, "This meshes vert sequence (read-only).\n\n:type: :class:`BMVertSeq`" @@ -645,7 +645,7 @@ static PyGetSetDef bpy_bmface_getseters[] = { static PyGetSetDef bpy_bmloop_getseters[] = { /* generic */ - // flags are available but not used for loops. + /* flags are available but not used for loops. */ // {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT}, // {(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_HIDDEN}, {(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG}, @@ -1808,7 +1808,7 @@ static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args) f_new = BM_face_create(bm, vert_array, edge_array, vert_seq_len, FALSE); - if (f_new == NULL) { + if (UNLIKELY(f_new == NULL)) { PyErr_SetString(PyExc_ValueError, "faces.new(verts): couldn't create the new face, internal error"); goto cleanup; @@ -2581,7 +2581,7 @@ static PyObject *bpy_bmelemseq_subscript(BPy_BMElemSeq *self, PyObject *key) /* only get the length for negative values */ Py_ssize_t len = bpy_bmelemseq_length(self); if (start < 0) start += len; - if (stop < 0) start += len; + if (stop < 0) stop += len; } if (stop - start <= 0) { diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h index 947e66bf24e..df5231a4b1b 100644 --- a/source/blender/python/bmesh/bmesh_py_types.h +++ b/source/blender/python/bmesh/bmesh_py_types.h @@ -116,7 +116,7 @@ typedef struct BPy_BMElemSeq { /* if this is a sequence on an existing element, * loops of faces for eg. - * If this veriable is set, it will be used */ + * If this variable is set, it will be used */ /* we hold a reference to this. * check in case the owner becomes invalid on access */ diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c index e45a39a0643..1fea12d105c 100644 --- a/source/blender/python/bmesh/bmesh_py_types_customdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c @@ -685,7 +685,7 @@ static PyObject *bpy_bmlayercollection_subscript(BPy_BMLayerCollection *self, Py /* only get the length for negative values */ Py_ssize_t len = bpy_bmlayercollection_length(self); if (start < 0) start += len; - if (stop < 0) start += len; + if (stop < 0) stop += len; } if (stop - start <= 0) { @@ -1079,7 +1079,7 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj ret = -1; } else { - BLI_strncpy(mstring->s, tmp_val, sizeof(mstring->s)); + BLI_strncpy(mstring->s, tmp_val, min_ii(PyBytes_Size(py_value), sizeof(mstring->s))); } break; } diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c index b5fee2a3e8e..8316d33ea38 100644 --- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c @@ -251,7 +251,7 @@ PyObject *BPy_BMLoopUV_CreatePyObject(struct MLoopUV *mloopuv) /* Mesh Loop Color * *************** */ -/* This simply provices a color wrapper for +/* This simply provides a color wrapper for * color which uses mathutils callbacks for mathutils.Color */ diff --git a/source/blender/python/bmesh/bmesh_py_types_select.c b/source/blender/python/bmesh/bmesh_py_types_select.c index c3adc8366bd..2ff731559d1 100644 --- a/source/blender/python/bmesh/bmesh_py_types_select.c +++ b/source/blender/python/bmesh/bmesh_py_types_select.c @@ -280,7 +280,7 @@ static PyObject *bpy_bmeditselseq_subscript(BPy_BMEditSelSeq *self, PyObject *ke /* only get the length for negative values */ Py_ssize_t len = bpy_bmeditselseq_length(self); if (start < 0) start += len; - if (stop < 0) start += len; + if (stop < 0) stop += len; } if (stop - start <= 0) { @@ -387,7 +387,7 @@ void BPy_BM_init_types_select(void) BPy_BMEditSelSeq_Type.tp_name = "BMEditSelSeq"; BPy_BMEditSelIter_Type.tp_name = "BMEditSelIter"; - BPy_BMEditSelSeq_Type.tp_doc = NULL; // todo + BPy_BMEditSelSeq_Type.tp_doc = NULL; /* todo */ BPy_BMEditSelIter_Type.tp_doc = NULL; BPy_BMEditSelSeq_Type.tp_repr = (reprfunc)NULL; diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index 06b6192a091..d2890bc046e 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -43,43 +43,39 @@ #include "py_capi_utils.h" #endif -extern PyTypeObject BPy_IDArray_Type; -extern PyTypeObject BPy_IDGroup_Iter_Type; -extern PyTypeObject BPy_IDGroup_Type; - /*********************** ID Property Main Wrapper Stuff ***************/ /* ---------------------------------------------------------------------------- * static conversion functions to avoid duplicate code, no type checking. */ -static PyObject *idprop_py_from_idp_string(IDProperty *prop) +static PyObject *idprop_py_from_idp_string(const IDProperty *prop) { if (prop->subtype == IDP_STRING_SUB_BYTE) { - return PyBytes_FromStringAndSize(IDP_Array(prop), prop->len); + return PyBytes_FromStringAndSize(IDP_String(prop), prop->len); } else { #ifdef USE_STRING_COERCE return PyC_UnicodeFromByteAndSize(IDP_Array(prop), prop->len - 1); #else - return PyUnicode_FromStringAndSize(IDP_Array(prop), prop->len - 1); + return PyUnicode_FromStringAndSize(IDP_String(prop), prop->len - 1); #endif } } -static PyObject *idprop_py_from_idp_int(IDProperty *prop) +static PyObject *idprop_py_from_idp_int(const IDProperty *prop) { - return PyLong_FromLong((long)prop->data.val); + return PyLong_FromLong((long)IDP_Int(prop)); } -static PyObject *idprop_py_from_idp_float(IDProperty *prop) +static PyObject *idprop_py_from_idp_float(const IDProperty *prop) { - return PyFloat_FromDouble((double)(*(float *)(&prop->data.val))); + return PyFloat_FromDouble((double)IDP_Float(prop)); } -static PyObject *idprop_py_from_idp_double(IDProperty *prop) +static PyObject *idprop_py_from_idp_double(const IDProperty *prop) { - return PyFloat_FromDouble((*(double *)(&prop->data.val))); + return PyFloat_FromDouble(IDP_Double(prop)); } static PyObject *idprop_py_from_idp_group(ID *id, IDProperty *prop, IDProperty *parent) @@ -193,7 +189,7 @@ static int BPy_IDGroup_SetData(BPy_IDProperty *self, IDProperty *prop, PyObject PyErr_SetString(PyExc_TypeError, "expected an int type"); return -1; } - prop->data.val = ivalue; + IDP_Int(prop) = ivalue; break; } case IDP_FLOAT: @@ -203,7 +199,7 @@ static int BPy_IDGroup_SetData(BPy_IDProperty *self, IDProperty *prop, PyObject PyErr_SetString(PyExc_TypeError, "expected a float"); return -1; } - *(float *)&self->prop->data.val = fvalue; + IDP_Float(self->prop) = fvalue; break; } case IDP_DOUBLE: @@ -213,7 +209,7 @@ static int BPy_IDGroup_SetData(BPy_IDProperty *self, IDProperty *prop, PyObject PyErr_SetString(PyExc_TypeError, "expected a float"); return -1; } - *(double *)&self->prop->data.val = dvalue; + IDP_Double(self->prop) = dvalue; break; } default: @@ -300,40 +296,34 @@ static PyObject *BPy_IDGroup_Map_GetItem(BPy_IDProperty *self, PyObject *item) } /* returns NULL on success, error string on failure */ -static int idp_sequence_type(PyObject *seq) +static int idp_sequence_type(PyObject *seq_fast) { PyObject *item; int type = IDP_INT; - Py_ssize_t i, len = PySequence_Size(seq); + Py_ssize_t i, len = PySequence_Fast_GET_SIZE(seq_fast); for (i = 0; i < len; i++) { - item = PySequence_GetItem(seq, i); + item = PySequence_Fast_GET_ITEM(seq_fast, i); if (PyFloat_Check(item)) { if (type == IDP_IDPARRAY) { /* mixed dict/int */ - Py_DECREF(item); return -1; } type = IDP_DOUBLE; } else if (PyLong_Check(item)) { if (type == IDP_IDPARRAY) { /* mixed dict/int */ - Py_DECREF(item); return -1; } } else if (PyMapping_Check(item)) { if (i != 0 && (type != IDP_IDPARRAY)) { /* mixed dict/int */ - Py_DECREF(item); return -1; } type = IDP_IDPARRAY; } else { - Py_XDECREF(item); return -1; } - - Py_DECREF(item); } return type; @@ -386,48 +376,61 @@ const char *BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty //prop->subtype = IDP_STRING_SUB_BYTE; } else if (PySequence_Check(ob)) { + PyObject *ob_seq_fast = PySequence_Fast(ob, "py -> idprop"); PyObject *item; int i; - if ((val.array.type = idp_sequence_type(ob)) == -1) + if (ob_seq_fast == NULL) { + PyErr_Print(); + PyErr_Clear(); + return "error converting the sequence"; + } + + if ((val.array.type = idp_sequence_type(ob_seq_fast)) == -1) { + Py_DECREF(ob_seq_fast); return "only floats, ints and dicts are allowed in ID property arrays"; + } /* validate sequence and derive type. * we assume IDP_INT unless we hit a float * number; then we assume it's */ - val.array.len = PySequence_Size(ob); + val.array.len = PySequence_Fast_GET_SIZE(ob_seq_fast); switch (val.array.type) { case IDP_DOUBLE: prop = IDP_New(IDP_ARRAY, &val, name); for (i = 0; i < val.array.len; i++) { - item = PySequence_GetItem(ob, i); + item = PySequence_Fast_GET_ITEM(ob_seq_fast, i); ((double *)IDP_Array(prop))[i] = (float)PyFloat_AsDouble(item); - Py_DECREF(item); } break; case IDP_INT: prop = IDP_New(IDP_ARRAY, &val, name); for (i = 0; i < val.array.len; i++) { - item = PySequence_GetItem(ob, i); + item = PySequence_Fast_GET_ITEM(ob_seq_fast, i); ((int *)IDP_Array(prop))[i] = (int)PyLong_AsSsize_t(item); - Py_DECREF(item); } break; case IDP_IDPARRAY: prop = IDP_NewIDPArray(name); for (i = 0; i < val.array.len; i++) { const char *error; - item = PySequence_GetItem(ob, i); + item = PySequence_Fast_GET_ITEM(ob_seq_fast, i); error = BPy_IDProperty_Map_ValidateAndCreate(NULL, prop, item); - Py_DECREF(item); - if (error) + if (error) { + Py_DECREF(ob_seq_fast); return error; + } } break; + default: + Py_DECREF(ob_seq_fast); + return "internal error with idp array.type"; } + + Py_DECREF(ob_seq_fast); } else if (PyMapping_Check(ob)) { PyObject *keys, *vals, *key, *pval; @@ -471,7 +474,7 @@ const char *BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty if (group->type == IDP_IDPARRAY) { IDP_AppendArray(group, prop); - // IDP_FreeProperty(item); // IDP_AppendArray does a shallow copy (memcpy), only free memory + // IDP_FreeProperty(item); /* IDP_AppendArray does a shallow copy (memcpy), only free memory */ MEM_freeN(prop); } else { @@ -802,17 +805,28 @@ static PyObject *BPy_IDGroup_Update(BPy_IDProperty *self, PyObject *value) PyObject *pkey, *pval; Py_ssize_t i = 0; - if (!PyDict_Check(value)) { + if (BPy_IDGroup_Check(value)) { + BPy_IDProperty *other = (BPy_IDProperty *)value; + if (UNLIKELY(self->prop == other->prop)) { + Py_RETURN_NONE; + } + + /* XXX, possible one is inside the other */ + IDP_MergeGroup(self->prop, other->prop, TRUE); + } + else if (PyDict_Check(value)) { + while (PyDict_Next(value, &i, &pkey, &pval)) { + BPy_IDGroup_Map_SetItem(self, pkey, pval); + if (PyErr_Occurred()) return NULL; + } + } + else { PyErr_Format(PyExc_TypeError, - "expected a dict not a %.200s", + "expected a dict or an IDPropertyGroup type, not a %.200s", Py_TYPE(value)->tp_name); return NULL; } - while (PyDict_Next(value, &i, &pkey, &pval)) { - BPy_IDGroup_Map_SetItem(self, pkey, pval); - if (PyErr_Occurred()) return NULL; - } Py_RETURN_NONE; } @@ -1416,15 +1430,15 @@ void IDProp_Init_Types(void) /* --- */ static struct PyModuleDef IDProp_types_module_def = { - PyModuleDef_HEAD_INIT, - "idprop.types", /* m_name */ - NULL, /* m_doc */ - 0, /* m_size */ - NULL, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ + PyModuleDef_HEAD_INIT, + "idprop.types", /* m_name */ + NULL, /* m_doc */ + 0, /* m_size */ + NULL, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ }; static PyObject *BPyInit_idprop_types(void) @@ -1483,3 +1497,40 @@ PyObject *BPyInit_idprop(void) return mod; } + + +#ifdef DEBUG +/* -------------------------------------------------------------------- */ +/* debug only function */ + +void IDP_spit(IDProperty *prop) +{ + if (prop) { + PyGILState_STATE gilstate; + int use_gil = TRUE; /* !PYC_INTERPRETER_ACTIVE; */ + PyObject *ret_dict; + PyObject *ret_str; + + if (use_gil) { + gilstate = PyGILState_Ensure(); + } + + /* to_dict() */ + ret_dict = BPy_IDGroup_MapDataToPy(prop); + ret_str = PyObject_Repr(ret_dict); + Py_DECREF(ret_dict); + + printf("IDProperty: %s\n", _PyUnicode_AsString(ret_str)); + + Py_DECREF(ret_str); + + if (use_gil) { + PyGILState_Release(gilstate); + } + } + else { + printf("IDProperty: \n"); + } +} + +#endif diff --git a/source/blender/python/generic/idprop_py_api.h b/source/blender/python/generic/idprop_py_api.h index 99e291f69c0..cb82676c4d9 100644 --- a/source/blender/python/generic/idprop_py_api.h +++ b/source/blender/python/generic/idprop_py_api.h @@ -32,6 +32,17 @@ struct ID; struct IDProperty; struct BPy_IDGroup_Iter; +extern PyTypeObject BPy_IDArray_Type; +extern PyTypeObject BPy_IDGroup_Iter_Type; +extern PyTypeObject BPy_IDGroup_Type; + +#define BPy_IDArray_Check(v) (PyObject_TypeCheck(v, &BPy_IDArray_Type)) +#define BPy_IDArray_CheckExact(v) (Py_TYPE(v) == &BPy_IDArray_Type) +#define BPy_IDGroup_Iter_Check(v) (PyObject_TypeCheck(v, &BPy_IDGroup_Iter_Type)) +#define BPy_IDGroup_Iter_CheckExact(v) (Py_TYPE(v) == &BPy_IDGroup_Iter_Type) +#define BPy_IDGroup_Check(v) (PyObject_TypeCheck(v, &BPy_IDGroup_Type)) +#define BPy_IDGroup_CheckExact(v) (Py_TYPE(v) == &BPy_IDGroup_Type) + typedef struct BPy_IDProperty { PyObject_VAR_HEAD struct ID *id; /* can be NULL */ diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 2e4d4e870b8..3b8193c422d 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -450,7 +450,7 @@ PyObject *PyC_UnicodeFromByte(const char *str) * >> foo = 10 * >> print(__import__("__main__").foo) * - * note: this overwrites __main__ which gives problems with nested calles. + * note: this overwrites __main__ which gives problems with nested calls. * be sure to run PyC_MainModule_Backup & PyC_MainModule_Restore if there is * any chance that python is in the call stack. ****************************************************************************/ @@ -542,7 +542,7 @@ void PyC_RunQuicky(const char *filepath, int n, ...) if (fp) { PyGILState_STATE gilstate = PyGILState_Ensure(); - va_list vargs; + va_list vargs; int *sizes = PyMem_MALLOC(sizeof(int) * (n / 2)); int i; @@ -760,7 +760,6 @@ int PyC_FlagSet_ValueFromID(PyC_FlagSet *item, const char *identifier, int *valu return 0; } -/* 'value' _must_ be a set type, error check before calling */ int PyC_FlagSet_ToBitfield(PyC_FlagSet *items, PyObject *value, int *r_value, const char *error_prefix) { /* set of enum items, concatenate all values with OR */ @@ -771,6 +770,13 @@ int PyC_FlagSet_ToBitfield(PyC_FlagSet *items, PyObject *value, int *r_value, co Py_ssize_t hash = 0; PyObject *key; + if (!PySet_Check(value)) { + PyErr_Format(PyExc_TypeError, + "%.200s expected a set, not %.200s", + error_prefix, Py_TYPE(value)->tp_name); + return -1; + } + *r_value = 0; while (_PySet_NextEntry(value, &pos, &key, &hash)) { @@ -778,7 +784,7 @@ int PyC_FlagSet_ToBitfield(PyC_FlagSet *items, PyObject *value, int *r_value, co if (param == NULL) { PyErr_Format(PyExc_TypeError, - "%.200s expected a string, not %.200s", + "%.200s set must contain strings, not %.200s", error_prefix, Py_TYPE(key)->tp_name); return -1; } diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h index 481cfb17c7a..935a5f9030b 100644 --- a/source/blender/python/generic/py_capi_utils.h +++ b/source/blender/python/generic/py_capi_utils.h @@ -69,4 +69,4 @@ int PyC_FlagSet_ValueFromID(PyC_FlagSet *item, const char *identifier, int int PyC_FlagSet_ToBitfield(PyC_FlagSet *items, PyObject *value, int *r_value, const char *error_prefix); PyObject *PyC_FlagSet_FromBitfield(PyC_FlagSet *items, int flag); -#endif // __PY_CAPI_UTILS_H__ +#endif /* __PY_CAPI_UTILS_H__ */ diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index 604166eed3c..61c49027d9a 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -30,12 +30,12 @@ set(INC ../../blenlib ../../blenloader ../../editors/include + ../../gpu ../../makesdna ../../makesrna ../../windowmanager - ../../gpu - ../../../../intern/guardedalloc ../../../../intern/cycles/blender + ../../../../intern/guardedalloc ) set(INC_SYS diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index f2222825c42..ad900343704 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -171,7 +171,7 @@ static PyObject *bpy_user_resource(PyObject *UNUSED(self), PyObject *args, PyObj } PyDoc_STRVAR(bpy_resource_path_doc, -".. function:: resource_path(type, major=2, minor=57)\n" +".. function:: resource_path(type, major=bpy.app.version[0], minor=bpy.app.version[1])\n" "\n" " Return the base path for storing system files.\n" "\n" @@ -278,7 +278,7 @@ void BPy_init_modules(void) bpy_import_test("bpy_types"); PyModule_AddObject(mod, "data", BPY_rna_module()); /* imports bpy_types by running this */ bpy_import_test("bpy_types"); - PyModule_AddObject(mod, "props", BPY_rna_props()); + PyModule_AddObject(mod, "props", BPY_rna_props()); /* ops is now a python module that does the conversion from SOME_OT_foo -> some.foo */ PyModule_AddObject(mod, "ops", BPY_operator_module()); PyModule_AddObject(mod, "app", BPY_app_struct()); diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index ccce0d8c5ae..a8aa7269b72 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -242,6 +242,7 @@ static PyGetSetDef bpy_app_getsets[] = { {(char *)"debug_ffmpeg", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_FFMPEG}, {(char *)"debug_python", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_PYTHON}, {(char *)"debug_events", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_EVENTS}, + {(char *)"debug_handlers", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_HANDLERS}, {(char *)"debug_wm", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_WM}, {(char *)"debug_value", bpy_app_debug_value_get, bpy_app_debug_value_set, (char *)bpy_app_debug_value_doc, NULL}, diff --git a/source/blender/python/intern/bpy_app.h b/source/blender/python/intern/bpy_app.h index 5bf36f04ba0..226bf44a493 100644 --- a/source/blender/python/intern/bpy_app.h +++ b/source/blender/python/intern/bpy_app.h @@ -29,4 +29,4 @@ PyObject *BPY_app_struct(void); -#endif // __BPY_APP_H__ +#endif /* __BPY_APP_H__ */ diff --git a/source/blender/python/intern/bpy_app_ffmpeg.c b/source/blender/python/intern/bpy_app_ffmpeg.c index 68fd9a99712..5ae2a11710a 100644 --- a/source/blender/python/intern/bpy_app_ffmpeg.c +++ b/source/blender/python/intern/bpy_app_ffmpeg.c @@ -77,8 +77,10 @@ static PyObject *make_ffmpeg_info(void) return NULL; } +#if 0 // UNUSED #define SetIntItem(flag) \ PyStructSequence_SET_ITEM(ffmpeg_info, pos++, PyLong_FromLong(flag)) +#endif #define SetStrItem(str) \ PyStructSequence_SET_ITEM(ffmpeg_info, pos++, PyUnicode_FromString(str)) #define SetObjItem(obj) \ @@ -118,7 +120,7 @@ static PyObject *make_ffmpeg_info(void) return NULL; } -#undef SetIntItem +// #undef SetIntItem #undef SetStrItem #undef SetObjItem diff --git a/source/blender/python/intern/bpy_app_ffmpeg.h b/source/blender/python/intern/bpy_app_ffmpeg.h index cadbb021d31..26d6e13f8f4 100644 --- a/source/blender/python/intern/bpy_app_ffmpeg.h +++ b/source/blender/python/intern/bpy_app_ffmpeg.h @@ -29,4 +29,4 @@ PyObject *BPY_app_ffmpeg_struct(void); -#endif // __BPY_APP_FFMPEG_H__ +#endif /* __BPY_APP_FFMPEG_H__ */ diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index 4d7f2080bbc..90a0444ceae 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -284,7 +284,7 @@ void bpy_app_generic_callback(struct Main *UNUSED(main), struct ID *id, void *ar if (PyList_GET_SIZE(cb_list) > 0) { PyGILState_STATE gilstate = PyGILState_Ensure(); - PyObject *args = PyTuple_New(1); // save python creating each call + PyObject *args = PyTuple_New(1); /* save python creating each call */ PyObject *func; PyObject *ret; Py_ssize_t pos; diff --git a/source/blender/python/intern/bpy_app_handlers.h b/source/blender/python/intern/bpy_app_handlers.h index 1f1eaf04a8b..40ca43909ed 100644 --- a/source/blender/python/intern/bpy_app_handlers.h +++ b/source/blender/python/intern/bpy_app_handlers.h @@ -29,4 +29,4 @@ PyObject *BPY_app_handlers_struct(void); -#endif // __BPY_APP_HANDLERS_H__ +#endif /* __BPY_APP_HANDLERS_H__ */ diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index de23b3bf109..9a79616c23b 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -280,7 +280,7 @@ float BPY_driver_exec(ChannelDriver *driver, const float evaltime) } -#if 0 // slow, with this can avoid all Py_CompileString above. +#if 0 /* slow, with this can avoid all Py_CompileString above. */ /* execute expression to get a value */ retval = PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars); #else diff --git a/source/blender/python/intern/bpy_driver.h b/source/blender/python/intern/bpy_driver.h index 6d1696d6cdc..1fccec7e1b2 100644 --- a/source/blender/python/intern/bpy_driver.h +++ b/source/blender/python/intern/bpy_driver.h @@ -36,4 +36,4 @@ extern PyObject *bpy_pydriver_Dict; float BPY_driver_exec(struct ChannelDriver *driver, const float evaltime); void BPY_driver_reset(void); -#endif // __BPY_DRIVER_H__ +#endif /* __BPY_DRIVER_H__ */ diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 9cd0bdd090a..94cbee383ea 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -53,6 +53,7 @@ #include "BLI_path_util.h" #include "BLI_fileops.h" +#include "BLI_listbase.h" #include "BLI_math_base.h" #include "BLI_string.h" #include "BLI_string_utf8.h" @@ -68,7 +69,7 @@ #include "BPY_extern.h" -#include "../generic/bpy_internal_import.h" // our own imports +#include "../generic/bpy_internal_import.h" /* our own imports */ #include "../generic/py_capi_utils.h" /* inittab initialization functions */ @@ -179,10 +180,10 @@ void BPY_text_free_code(Text *text) void BPY_modules_update(bContext *C) { -#if 0 // slow, this runs all the time poll, draw etc 100's of time a sec. +#if 0 /* slow, this runs all the time poll, draw etc 100's of time a sec. */ PyObject *mod = PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0); PyModule_AddObject(mod, "data", BPY_rna_module()); - PyModule_AddObject(mod, "types", BPY_rna_types()); // atm this does not need updating + PyModule_AddObject(mod, "types", BPY_rna_types()); /* atm this does not need updating */ #endif /* refreshes the main struct */ @@ -250,6 +251,10 @@ void BPY_python_start(int argc, const char **argv) * an error, this is highly annoying, another stumbling block for devs, * so use a more relaxed error handler and enforce utf-8 since the rest of * blender is utf-8 too - campbell */ + + /* XXX, update: this is unreliable! 'PYTHONIOENCODING' is ignored in MS-Windows + * when dynamically linked, see: [#31555] for details. + * Python doesn't expose a good way to set this. */ BLI_setenv("PYTHONIOENCODING", "utf-8:surrogateescape"); /* Python 3.2 now looks for '2.xx/python/include/python3.2d/pyconfig.h' to @@ -263,16 +268,7 @@ void BPY_python_start(int argc, const char **argv) Py_Initialize(); -#ifdef WIN32 - /* this is disappointing, its likely a bug in python? - * for some reason 'PYTHONIOENCODING' is ignored in windows - * see: [#31555] for details. */ - PyRun_SimpleString("import sys, io\n" - "sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='surrogateescape', line_buffering=True)\n" - "sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='surrogateescape', line_buffering=True)\n"); -#endif /* WIN32 */ - - // PySys_SetArgv(argc, argv); // broken in py3, not a huge deal + // PySys_SetArgv(argc, argv); /* broken in py3, not a huge deal */ /* sigh, why do python guys not have a (char **) version anymore? */ { int i; @@ -383,6 +379,7 @@ typedef struct { static int python_script_exec(bContext *C, const char *fn, struct Text *text, struct ReportList *reports, const short do_jump) { + Main *bmain_old = CTX_data_main(C); PyObject *main_mod = NULL; PyObject *py_dict = NULL, *py_result = NULL; PyGILState_STATE gilstate; @@ -461,7 +458,11 @@ static int python_script_exec(bContext *C, const char *fn, struct Text *text, if (!py_result) { if (text) { if (do_jump) { - python_script_error_jump_text(text); + /* ensure text is valid before use, the script may have freed its self */ + Main *bmain_new = CTX_data_main(C); + if ((bmain_old == bmain_new) && (BLI_findindex(&bmain_new->text, text) != -1)) { + python_script_error_jump_text(text); + } } } BPy_errors_to_report(reports); @@ -509,6 +510,18 @@ void BPY_DECREF(void *pyob_ptr) PyGILState_Release(gilstate); } +void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr) +{ + PyGILState_STATE gilstate = PyGILState_Ensure(); + const int do_invalidate = (Py_REFCNT((PyObject *)pyob_ptr) > 1); + Py_DECREF((PyObject *)pyob_ptr); + if (do_invalidate) { + pyrna_invalidate(pyob_ptr); + } + PyGILState_Release(gilstate); +} + + /* return -1 on error, else 0 */ int BPY_button_exec(bContext *C, const char *expr, double *value, const short verbose) { @@ -672,6 +685,11 @@ void BPY_modules_load_user(bContext *C) else { Py_DECREF(module); } + + /* check if the script loaded a new file */ + if (bmain != CTX_data_main(C)) { + break; + } } } } @@ -680,11 +698,20 @@ void BPY_modules_load_user(bContext *C) int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *result) { - PyObject *pyctx = (PyObject *)CTX_py_dict_get(C); - PyObject *item = PyDict_GetItemString(pyctx, member); + PyGILState_STATE gilstate; + int use_gil = !PYC_INTERPRETER_ACTIVE; + + PyObject *pyctx; + PyObject *item; PointerRNA *ptr = NULL; int done = FALSE; + if (use_gil) + gilstate = PyGILState_Ensure(); + + pyctx = (PyObject *)CTX_py_dict_get(C); + item = PyDict_GetItemString(pyctx, member); + if (item == NULL) { /* pass */ } @@ -720,7 +747,8 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult * CTX_data_list_add(result, ptr->id.data, ptr->type, ptr->data); } else { - printf("List item not a valid type\n"); + printf("PyContext: '%s' list item not a valid type in sequece type '%s'\n", + member, Py_TYPE(item)->tp_name); } } @@ -740,6 +768,9 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult * } } + if (use_gil) + PyGILState_Release(gilstate); + return done; } diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index abf609cd235..bd033736865 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -75,9 +75,10 @@ static EnumPropertyItem property_flag_enum_items[] = { static EnumPropertyItem property_subtype_string_items[] = { {PROP_FILEPATH, "FILE_PATH", 0, "File Path", ""}, {PROP_DIRPATH, "DIR_PATH", 0, "Directory Path", ""}, - {PROP_FILENAME, "FILENAME", 0, "Filename", ""}, + {PROP_FILENAME, "FILE_NAME", 0, "Filename", ""}, {PROP_BYTESTRING, "BYTE_STRING", 0, "Byte String", ""}, {PROP_TRANSLATE, "TRANSLATE", 0, "Translate", ""}, + {PROP_PASSWORD, "PASSWORD", 0, "Password", 0}, {PROP_NONE, "NONE", 0, "None", ""}, {0, NULL, 0, NULL, NULL}}; @@ -260,7 +261,7 @@ static int bpy_prop_callback_check(PyObject *py_func, int argcount) static int bpy_prop_callback_assign(struct PropertyRNA *prop, PyObject *update_cb) { /* assume this is already checked for type and arg length */ - if (update_cb) { + if (update_cb && update_cb != Py_None) { PyObject **py_data = MEM_callocN(sizeof(PyObject *) * BPY_DATA_CB_SLOT_SIZE, __func__); RNA_def_property_update_runtime(prop, (void *)bpy_prop_update_cb); py_data[BPY_DATA_CB_SLOT_UPDATE] = update_cb; @@ -309,35 +310,38 @@ static int py_long_as_int(PyObject *py_long, int *r_int) /* terse macros for error checks shared between all funcs cant use function * calls because of static strings passed to pyrna_set_to_enum_bitfield */ #define BPY_PROPDEF_CHECK(_func, _property_flag_items) \ - if (id_len >= MAX_IDPROP_NAME) { \ + if (UNLIKELY(id_len >= MAX_IDPROP_NAME)) { \ PyErr_Format(PyExc_TypeError, \ #_func"(): '%.200s' too long, max length is %d", \ id, MAX_IDPROP_NAME - 1); \ return NULL; \ } \ - if (RNA_def_property_free_identifier(srna, id) == -1) { \ + if (UNLIKELY(RNA_def_property_free_identifier(srna, id) == -1)) { \ PyErr_Format(PyExc_TypeError, \ #_func"(): '%s' is defined as a non-dynamic type", \ id); \ return NULL; \ } \ - if (pyopts && pyrna_set_to_enum_bitfield(_property_flag_items, \ + if (UNLIKELY(pyopts && pyrna_set_to_enum_bitfield(_property_flag_items, \ pyopts, \ &opts, \ - #_func"(options={ ...}):")) \ + #_func"(options={ ...}):"))) \ { \ return NULL; \ } (void)0 #define BPY_PROPDEF_SUBTYPE_CHECK(_func, _property_flag_items, _subtype) \ BPY_PROPDEF_CHECK(_func, _property_flag_items); \ - if (pysubtype && RNA_enum_value_from_id(_subtype, \ + if (UNLIKELY(pysubtype && RNA_enum_value_from_id(_subtype, \ pysubtype, \ - &subtype) == 0) \ + &subtype) == 0)) \ { \ + const char *enum_str = BPy_enum_as_string(_subtype); \ PyErr_Format(PyExc_TypeError, \ - #_func"(subtype='%s'): invalid subtype", \ - pysubtype); \ + #_func"(subtype='%s'): " \ + "subtype not found in (%s)", \ + pysubtype, enum_str); \ + MEM_freeN((void *)enum_str); \ return NULL; \ } (void)0 @@ -360,6 +364,7 @@ static int py_long_as_int(PyObject *py_long, int *r_int) #define BPY_PROPDEF_UPDATE_DOC \ " :arg update: function to be called when this value is modified,\n" \ " This function must take 2 values (self, context) and return None.\n" \ +" *Warning* there are no safety checks to avoid infinite recursion.\n" \ " :type update: function\n" \ #if 0 @@ -920,7 +925,7 @@ BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC " :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE', 'LIBRARY_EDITABLE'].\n" " :type options: set\n" -" :arg subtype: Enumerator in ['FILE_PATH', 'DIR_PATH', 'FILENAME', 'NONE'].\n" +" :arg subtype: Enumerator in ['FILE_PATH', 'DIR_PATH', 'FILE_NAME', 'NONE'].\n" " :type subtype: string\n" BPY_PROPDEF_UPDATE_DOC ); @@ -1510,7 +1515,7 @@ static PyObject *BPy_RemoveProperty(PyObject *self, PyObject *args, PyObject *kw args = PyTuple_New(0); ret = BPy_RemoveProperty(self, args, kw); Py_DECREF(args); - return ret; + return ret; } else if (PyTuple_GET_SIZE(args) > 1) { PyErr_SetString(PyExc_ValueError, "all args must be keywords"); diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 8ec8c4c41ba..68b6baadd71 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -119,13 +119,10 @@ int pyrna_prop_validity_check(BPy_PropertyRNA *self) return -1; } -#if defined(USE_PYRNA_INVALIDATE_GC) || defined(USE_PYRNA_INVALIDATE_WEAKREF) -static void pyrna_invalidate(BPy_DummyPointerRNA *self) +void pyrna_invalidate(BPy_DummyPointerRNA *self) { - self->ptr.type = NULL; /* this is checked for validity */ - self->ptr.id.data = NULL; /* should not be needed but prevent bad pointer access, just in case */ + RNA_POINTER_INVALIDATE(&self->ptr); } -#endif #ifdef USE_PYRNA_INVALIDATE_GC #define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g) + 1)) @@ -337,7 +334,7 @@ static int rna_id_write_error(PointerRNA *ptr, PyObject *key) } return FALSE; } -#endif // USE_PEDANTIC_WRITE +#endif /* USE_PEDANTIC_WRITE */ #ifdef USE_PEDANTIC_WRITE @@ -350,7 +347,7 @@ void pyrna_write_set(int val) { rna_disallow_writes = !val; } -#else // USE_PEDANTIC_WRITE +#else /* USE_PEDANTIC_WRITE */ int pyrna_write_check(void) { return TRUE; @@ -359,7 +356,7 @@ void pyrna_write_set(int UNUSED(val)) { /* nothing */ } -#endif // USE_PEDANTIC_WRITE +#endif /* USE_PEDANTIC_WRITE */ static Py_ssize_t pyrna_prop_collection_length(BPy_PropertyRNA *self); static Py_ssize_t pyrna_prop_array_length(BPy_PropertyArrayRNA *self); @@ -426,7 +423,7 @@ static int mathutils_rna_vector_set(BaseMathObject *bmo, int subtype) if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { return -1; } -#endif // USE_PEDANTIC_WRITE +#endif /* USE_PEDANTIC_WRITE */ if (!RNA_property_editable_flag(&self->ptr, self->prop)) { PyErr_Format(PyExc_AttributeError, @@ -490,7 +487,7 @@ static int mathutils_rna_vector_set_index(BaseMathObject *bmo, int UNUSED(subtyp if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { return -1; } -#endif // USE_PEDANTIC_WRITE +#endif /* USE_PEDANTIC_WRITE */ if (!RNA_property_editable_flag(&self->ptr, self->prop)) { PyErr_Format(PyExc_AttributeError, @@ -547,7 +544,7 @@ static int mathutils_rna_matrix_set(BaseMathObject *bmo, int UNUSED(subtype)) if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { return -1; } -#endif // USE_PEDANTIC_WRITE +#endif /* USE_PEDANTIC_WRITE */ if (!RNA_property_editable_flag(&self->ptr, self->prop)) { PyErr_Format(PyExc_AttributeError, @@ -588,7 +585,7 @@ static short pyrna_rotation_euler_order_get(PointerRNA *ptr, PropertyRNA **prop_ return order_fallback; } -#endif // USE_MATHUTILS +#endif /* USE_MATHUTILS */ /* note that PROP_NONE is included as a vector subtype. this is because its handy to * have x/y access to fcurve keyframes and other fixed size float arrays of length 2-4. */ @@ -672,7 +669,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) PropertyRNA *prop_eul_order = NULL; short order = pyrna_rotation_euler_order_get(ptr, &prop_eul_order, EULER_ORDER_XYZ); - ret = Euler_CreatePyObject(NULL, order, Py_NEW, NULL); // TODO, get order from RNA + ret = Euler_CreatePyObject(NULL, order, Py_NEW, NULL); /* TODO, get order from RNA */ RNA_property_float_get_array(ptr, prop, ((EulerObject *)ret)->eul); } else { @@ -698,7 +695,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) case PROP_COLOR_GAMMA: if (len == 3) { /* color */ if (is_thick) { - ret = Color_CreatePyObject(NULL, Py_NEW, NULL); // TODO, get order from RNA + ret = Color_CreatePyObject(NULL, Py_NEW, NULL); RNA_property_float_get_array(ptr, prop, ((ColorObject *)ret)->col); } else { @@ -722,10 +719,10 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) ret = pyrna_prop_CreatePyObject(ptr, prop); /* owned by the mathutils PyObject */ } } -#else // USE_MATHUTILS +#else /* USE_MATHUTILS */ (void)ptr; (void)prop; -#endif // USE_MATHUTILS +#endif /* USE_MATHUTILS */ return ret; } @@ -834,7 +831,7 @@ static PyObject *pyrna_struct_str(BPy_StructRNA *self) const char *name; if (!PYRNA_STRUCT_IS_VALID(self)) { - return PyUnicode_FromFormat("", + return PyUnicode_FromFormat("", Py_TYPE(self)->tp_name); } @@ -1302,7 +1299,7 @@ static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val) val, RNA_struct_identifier(ptr->type), ptr_name, RNA_property_identifier(prop)); -#if 0 // gives python decoding errors while generating docs :( +#if 0 /* gives python decoding errors while generating docs :( */ char error_str[256]; BLI_snprintf(error_str, sizeof(error_str), "RNA Warning: Current value \"%d\" " @@ -1371,14 +1368,14 @@ PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) else { ret = PyUnicode_FromStringAndSize(buf, buf_len); } -#else // USE_STRING_COERCE +#else /* USE_STRING_COERCE */ if (subtype == PROP_BYTESTRING) { ret = PyBytes_FromStringAndSize(buf, buf_len); } else { ret = PyUnicode_FromStringAndSize(buf, buf_len); } -#endif // USE_STRING_COERCE +#endif /* USE_STRING_COERCE */ if (buf_fixed != buf) { MEM_freeN((void *)buf); } @@ -1635,12 +1632,12 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb if (subtype == PROP_TRANSLATE) { param = IFACE_(param); } -#endif // WITH_INTERNATIONAL +#endif /* WITH_INTERNATIONAL */ } -#else // USE_STRING_COERCE +#else /* USE_STRING_COERCE */ param = _PyUnicode_AsString(value); -#endif // USE_STRING_COERCE +#endif /* USE_STRING_COERCE */ if (param == NULL) { if (PyUnicode_Check(value)) { @@ -1668,7 +1665,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb } #ifdef USE_STRING_COERCE Py_XDECREF(value_coerce); -#endif // USE_STRING_COERCE +#endif /* USE_STRING_COERCE */ } break; } @@ -1778,10 +1775,21 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb if (data) { if (flag & PROP_RNAPTR) { - if (value == Py_None) - memset(data, 0, sizeof(PointerRNA)); - else - *((PointerRNA *)data) = param->ptr; + if (flag & PROP_THICK_WRAP) { + if (value == Py_None) + memset(data, 0, sizeof(PointerRNA)); + else + *((PointerRNA *)data) = param->ptr; + } + else { + /* for function calls, we sometimes want to pass the 'ptr' directly, + * watch out that it remains valid!, possibly we could support this later if needed */ + BLI_assert(value_new == NULL); + if (value == Py_None) + *((void **)data) = NULL; + else + *((PointerRNA **)data) = ¶m->ptr; + } } else if (value == Py_None) { *((void **)data) = NULL; @@ -1995,7 +2003,7 @@ static int pyrna_py_to_prop_array_index(BPy_PropertyArrayRNA *self, int index, P return ret; } -//---------------sequence------------------------------------------- +/* ---------------sequence------------------------------------------- */ static Py_ssize_t pyrna_prop_array_length(BPy_PropertyArrayRNA *self) { PYRNA_PROP_CHECK_INT((BPy_PropertyRNA *)self); @@ -2211,7 +2219,7 @@ static int pyrna_prop_collection_subscript_str_lib_pair_ptr(BPy_PropertyRNA *sel return -1; } - /* lib is either a valid poniter or NULL, + /* lib is either a valid pointer or NULL, * either way can do direct comparison with id.lib */ RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) @@ -2420,7 +2428,7 @@ static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject /* only get the length for negative values */ Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop); if (start < 0) start += len; - if (stop < 0) start += len; + if (stop < 0) stop += len; } if (stop - start <= 0) { @@ -2546,7 +2554,7 @@ static int pyrna_prop_collection_ass_subscript(BPy_PropertyRNA *self, PyObject * /* only get the length for negative values */ Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop); if (start < 0) start += len; - if (stop < 0) start += len; + if (stop < 0) stop += len; } if (stop - start <= 0) { @@ -2982,7 +2990,7 @@ static int pyrna_struct_ass_subscript(BPy_StructRNA *self, PyObject *key, PyObje if (rna_disallow_writes && rna_id_write_error(&self->ptr, key)) { return -1; } -#endif // USE_PEDANTIC_WRITE +#endif /* USE_PEDANTIC_WRITE */ if (group == NULL) { PyErr_SetString(PyExc_TypeError, "bpy_struct[key] = val: id properties not supported for this type"); @@ -3441,7 +3449,7 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA *self) return ret; } -//---------------getattr-------------------------------------------- +/* ---------------getattr-------------------------------------------- */ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) { const char *name = _PyUnicode_AsString(pyname); @@ -3455,7 +3463,7 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) PyErr_SetString(PyExc_AttributeError, "bpy_struct: __getattr__ must be a string"); ret = NULL; } - else if (name[0] == '_') { // rna can't start with a "_", so for __dict__ and similar we can skip using rna lookups + else if (name[0] == '_') { /* rna can't start with a "_", so for __dict__ and similar we can skip using rna lookups */ /* annoying exception, maybe we need to have different types for this... */ if ((strcmp(name, "__getitem__") == 0 || strcmp(name, "__setitem__") == 0) && !RNA_struct_idprops_check(self->ptr.type)) { PyErr_SetString(PyExc_AttributeError, "bpy_struct: no __getitem__ support for this type"); @@ -3565,7 +3573,7 @@ static int pyrna_struct_pydict_contains(PyObject *self, PyObject *pyname) } #endif -//--------------- setattr------------------------------------------- +/* --------------- setattr------------------------------------------- */ static int pyrna_is_deferred_prop(const PyObject *value) { return PyTuple_CheckExact(value) && @@ -3678,7 +3686,7 @@ static int pyrna_struct_setattro(BPy_StructRNA *self, PyObject *pyname, PyObject if (rna_disallow_writes && rna_id_write_error(&self->ptr, pyname)) { return -1; } -#endif // USE_PEDANTIC_WRITE +#endif /* USE_PEDANTIC_WRITE */ if (name == NULL) { PyErr_SetString(PyExc_AttributeError, "bpy_struct: __setattr__ must be a string"); @@ -3829,7 +3837,7 @@ static PyObject *pyrna_prop_collection_getattro(BPy_PropertyRNA *self, PyObject #endif } -//--------------- setattr------------------------------------------- +/* --------------- setattr------------------------------------------- */ static int pyrna_prop_collection_setattro(BPy_PropertyRNA *self, PyObject *pyname, PyObject *value) { const char *name = _PyUnicode_AsString(pyname); @@ -3840,7 +3848,7 @@ static int pyrna_prop_collection_setattro(BPy_PropertyRNA *self, PyObject *pynam if (rna_disallow_writes && rna_id_write_error(&self->ptr, pyname)) { return -1; } -#endif // USE_PEDANTIC_WRITE +#endif /* USE_PEDANTIC_WRITE */ if (name == NULL) { PyErr_SetString(PyExc_AttributeError, "bpy_prop: __setattr__ must be a string"); @@ -3868,6 +3876,12 @@ static PyObject *pyrna_prop_collection_idprop_add(BPy_PropertyRNA *self) { PointerRNA r_ptr; +#ifdef USE_PEDANTIC_WRITE + if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return NULL; + } +#endif /* USE_PEDANTIC_WRITE */ + RNA_property_collection_add(&self->ptr, self->prop, &r_ptr); if (!r_ptr.data) { PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.add(): not supported for this collection"); @@ -3882,6 +3896,12 @@ static PyObject *pyrna_prop_collection_idprop_remove(BPy_PropertyRNA *self, PyOb { int key = PyLong_AsLong(value); +#ifdef USE_PEDANTIC_WRITE + if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return NULL; + } +#endif /* USE_PEDANTIC_WRITE */ + if (key == -1 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.remove(): expected one int argument"); return NULL; @@ -3897,6 +3917,12 @@ static PyObject *pyrna_prop_collection_idprop_remove(BPy_PropertyRNA *self, PyOb static PyObject *pyrna_prop_collection_idprop_clear(BPy_PropertyRNA *self) { +#ifdef USE_PEDANTIC_WRITE + if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return NULL; + } +#endif /* USE_PEDANTIC_WRITE */ + RNA_property_collection_clear(&self->ptr, self->prop); Py_RETURN_NONE; @@ -3906,6 +3932,12 @@ static PyObject *pyrna_prop_collection_idprop_move(BPy_PropertyRNA *self, PyObje { int key = 0, pos = 0; +#ifdef USE_PEDANTIC_WRITE + if (rna_disallow_writes && rna_id_write_error(&self->ptr, NULL)) { + return NULL; + } +#endif /* USE_PEDANTIC_WRITE */ + if (!PyArg_ParseTuple(args, "ii", &key, &pos)) { PyErr_SetString(PyExc_TypeError, "bpy_prop_collection.move(): expected two ints as arguments"); return NULL; @@ -4275,7 +4307,7 @@ static int foreach_parse_args(BPy_PropertyRNA *self, PyObject *args, foreach_attr_type(self, *attr, raw_type, attr_tot, attr_signed); *size = RNA_raw_type_sizeof(*raw_type); -#if 0 // works fine but not strictly needed, we could allow RNA_property_collection_raw_* to do the checks +#if 0 /* works fine but not strictly needed, we could allow RNA_property_collection_raw_* to do the checks */ if ((*attr_tot) < 1) *attr_tot = 1; @@ -4617,7 +4649,7 @@ static struct PyMethodDef pyrna_prop_collection_methods[] = { static struct PyMethodDef pyrna_prop_collection_idprop_methods[] = { {"add", (PyCFunction)pyrna_prop_collection_idprop_add, METH_NOARGS, NULL}, {"remove", (PyCFunction)pyrna_prop_collection_idprop_remove, METH_O, NULL}, - {"clear", (PyCFunction)pyrna_prop_collection_idprop_clear, METH_NOARGS, NULL}, + {"clear", (PyCFunction)pyrna_prop_collection_idprop_clear, METH_NOARGS, NULL}, {"move", (PyCFunction)pyrna_prop_collection_idprop_move, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} }; @@ -5564,7 +5596,7 @@ PyTypeObject pyrna_prop_collection_Type = { NULL, /* getattrfunc tp_getattr; */ NULL, /* setattrfunc tp_setattr; */ NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - NULL, /* subclassed */ /* tp_repr */ + NULL, /* subclassed */ /* tp_repr */ /* Method suites for standard classes */ @@ -5598,7 +5630,7 @@ PyTypeObject pyrna_prop_collection_Type = { /*** Assigned meaning in release 2.1 ***/ /*** rich comparisons ***/ - NULL, /* subclassed */ /* richcmpfunc tp_richcompare; */ + NULL, /* subclassed */ /* richcmpfunc tp_richcompare; */ /*** weak reference enabler ***/ #ifdef USE_WEAKREFS @@ -5683,7 +5715,7 @@ static PyTypeObject pyrna_prop_collection_idprop_Type = { /*** Assigned meaning in release 2.1 ***/ /*** rich comparisons ***/ - NULL, /* subclassed */ /* richcmpfunc tp_richcompare; */ + NULL, /* subclassed */ /* richcmpfunc tp_richcompare; */ /*** weak reference enabler ***/ #ifdef USE_WEAKREFS @@ -5830,7 +5862,7 @@ PyTypeObject pyrna_prop_collection_iter_Type = { NULL, /* getattrfunc tp_getattr; */ NULL, /* setattrfunc tp_setattr; */ NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ - NULL, /* subclassed */ /* tp_repr */ + NULL, /* subclassed */ /* tp_repr */ /* Method suites for standard classes */ @@ -5868,7 +5900,7 @@ PyTypeObject pyrna_prop_collection_iter_Type = { /*** Assigned meaning in release 2.1 ***/ /*** rich comparisons ***/ - NULL, /* subclassed */ /* richcmpfunc tp_richcompare; */ + NULL, /* subclassed */ /* richcmpfunc tp_richcompare; */ /*** weak reference enabler ***/ #ifdef USE_WEAKREFS @@ -6044,8 +6076,8 @@ static PyObject *pyrna_srna_ExternalType(StructRNA *srna) fprintf(stderr, "%s: failed to find 'bpy_types' module\n", __func__); return NULL; } - bpy_types_dict = PyModule_GetDict(bpy_types); // borrow - Py_DECREF(bpy_types); // fairly safe to assume the dict is kept + bpy_types_dict = PyModule_GetDict(bpy_types); /* borrow */ + Py_DECREF(bpy_types); /* fairly safe to assume the dict is kept */ } newclass = PyDict_GetItemString(bpy_types_dict, idname); @@ -6134,7 +6166,7 @@ static PyObject *pyrna_srna_Subtype(StructRNA *srna) /* srna owns one, and the other is owned by the caller */ pyrna_subtype_set_rna(newclass, srna); - // XXX, adding this back segfaults blender on load. + /* XXX, adding this back segfaults blender on load. */ // Py_DECREF(newclass); /* let srna own */ } else { @@ -6291,7 +6323,7 @@ int pyrna_id_FromPyObject(PyObject *obj, ID **id) void BPY_rna_init(void) { -#ifdef USE_MATHUTILS // register mathutils callbacks, ok to run more then once. +#ifdef USE_MATHUTILS /* register mathutils callbacks, ok to run more then once. */ mathutils_rna_array_cb_index = Mathutils_RegisterCallback(&mathutils_rna_array_cb); mathutils_rna_matrix_cb_index = Mathutils_RegisterCallback(&mathutils_rna_matrix_cb); #endif @@ -6375,7 +6407,7 @@ PyObject *BPY_rna_doc(void) /* pyrna_basetype_* - BPy_BaseTypeRNA is just a BPy_PropertyRNA struct with a different type * the self->ptr and self->prop are always set to the "structs" collection */ -//---------------getattr-------------------------------------------- +/* ---------------getattr-------------------------------------------- */ static PyObject *pyrna_basetype_getattro(BPy_BaseTypeRNA *self, PyObject *pyname) { PointerRNA newptr; @@ -6750,7 +6782,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v PyObject *base_class = RNA_struct_py_type_get(srna); PyObject *item; int i, flag, arg_count, func_arg_count; - const char *py_class_name = ((PyTypeObject *)py_class)->tp_name; // __name__ + const char *py_class_name = ((PyTypeObject *)py_class)->tp_name; /* __name__ */ if (srna_base) { if (bpy_class_validate_recursive(dummyptr, srna_base, py_data, have_function) != 0) @@ -6919,11 +6951,9 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param #ifdef USE_PEDANTIC_WRITE const int is_operator = RNA_struct_is_a(ptr->type, &RNA_Operator); - const char *func_id = RNA_function_identifier(func); + // const char *func_id = RNA_function_identifier(func); /* UNUSED */ /* testing, for correctness, not operator and not draw function */ - const short is_readonly = ((strncmp("draw", func_id, 4) == 0) || /* draw or draw_header */ - /*strstr("render", func_id) ||*/ - !is_operator); + const short is_readonly = !(RNA_function_flag(func) & FUNC_ALLOW_WRITE); #endif py_class = RNA_struct_py_type_get(ptr->type); @@ -7211,10 +7241,10 @@ static void bpy_class_free(void *pyob_ptr) gilstate = PyGILState_Ensure(); - // breaks re-registering classes + /* breaks re-registering classes */ // PyDict_Clear(((PyTypeObject *)self)->tp_dict); - // - // remove the rna attribute instead. + + /* remove the rna attribute instead. */ PyDict_DelItem(((PyTypeObject *)self)->tp_dict, bpy_intern_str_bl_rna); if (PyErr_Occurred()) PyErr_Clear(); @@ -7279,7 +7309,7 @@ void pyrna_free_types(void) void *py_ptr = RNA_struct_py_type_get(srna); if (py_ptr) { -#if 0 // XXX - should be able to do this but makes python crash on exit +#if 0 /* XXX - should be able to do this but makes python crash on exit */ bpy_class_free(py_ptr); #endif RNA_struct_py_type_set(srna, NULL); diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index 1fb4b116872..880ef4c2185 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -207,6 +207,7 @@ int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value) int pyrna_write_check(void); void pyrna_write_set(int val); +void pyrna_invalidate(BPy_DummyPointerRNA *self); int pyrna_struct_validity_check(BPy_StructRNA *pysrna); int pyrna_prop_validity_check(BPy_PropertyRNA *self); diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c index b7a45897668..69839514a12 100644 --- a/source/blender/python/intern/bpy_rna_anim.c +++ b/source/blender/python/intern/bpy_rna_anim.c @@ -52,9 +52,6 @@ #include "bpy_util.h" #include "bpy_rna_anim.h" -#define TRUE 1 -#define FALSE 0 - /* for keyframes and drivers */ static int pyrna_struct_anim_args_parse( PointerRNA *ptr, const char *error_prefix, const char *path, diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c index 70815d9f8bf..e66d8f05309 100644 --- a/source/blender/python/intern/bpy_rna_array.c +++ b/source/blender/python/intern/bpy_rna_array.c @@ -30,6 +30,8 @@ #include "RNA_types.h" +#include "BLI_utildefines.h" + #include "bpy_rna.h" #include "BKE_global.h" #include "MEM_guardedalloc.h" @@ -664,7 +666,8 @@ PyObject *pyrna_py_from_array_index(BPy_PropertyArrayRNA *self, PointerRNA *ptr, len = RNA_property_multi_array_length(ptr, prop, arraydim); if (index >= len || index < 0) { /* this shouldn't happen because higher level funcs must check for invalid index */ - if (G.debug & G_DEBUG_PYTHON) printf("pyrna_py_from_array_index: invalid index %d for array with length=%d\n", index, len); + if (G.debug & G_DEBUG_PYTHON) + printf("%s: invalid index %d for array with length=%d\n", __func__, index, len); PyErr_SetString(PyExc_IndexError, "out of range"); return NULL; diff --git a/source/blender/python/intern/bpy_traceback.h b/source/blender/python/intern/bpy_traceback.h index 575f9824379..9ac49c370e4 100644 --- a/source/blender/python/intern/bpy_traceback.h +++ b/source/blender/python/intern/bpy_traceback.h @@ -28,4 +28,4 @@ void python_script_error_jump(const char *filepath, int *lineno, int *offset); -#endif // __BPY_TRACEBACK_H__ +#endif /* __BPY_TRACEBACK_H__ */ diff --git a/source/blender/python/intern/bpy_util.c b/source/blender/python/intern/bpy_util.c index 01495c793a8..b7994eeccdc 100644 --- a/source/blender/python/intern/bpy_util.c +++ b/source/blender/python/intern/bpy_util.c @@ -35,9 +35,11 @@ #include "BKE_report.h" #include "BKE_context.h" +#include "BLF_translation.h" + #include "../generic/py_capi_utils.h" -static bContext* __py_context = NULL; +static bContext *__py_context = NULL; bContext *BPy_GetContext(void) { return __py_context; } void BPy_SetContext(bContext *C) { __py_context = C; } @@ -79,7 +81,7 @@ short BPy_reports_to_error(ReportList *reports, PyObject *exception, const short short BPy_errors_to_report(ReportList *reports) { PyObject *pystring; - PyObject *pystring_format = NULL; // workaround, see below + PyObject *pystring_format = NULL; /* workaround, see below */ char *cstring; const char *filename; @@ -98,7 +100,7 @@ short BPy_errors_to_report(ReportList *reports) pystring = PyC_ExceptionBuffer(); if (pystring == NULL) { - BKE_report(reports, RPT_ERROR, "unknown py-exception, couldn't convert"); + BKE_report(reports, RPT_ERROR, "Unknown py-exception, could not convert"); return 0; } @@ -108,17 +110,18 @@ short BPy_errors_to_report(ReportList *reports) cstring = _PyUnicode_AsString(pystring); -#if 0 // ARG!. workaround for a bug in blenders use of vsnprintf - BKE_reportf(reports, RPT_ERROR, "%s\nlocation:%s:%d\n", cstring, filename, lineno); +#if 0 /* ARG!. workaround for a bug in blenders use of vsnprintf */ + BKE_reportf(reports, RPT_ERROR, "%s\nlocation: %s:%d\n", cstring, filename, lineno); #else - pystring_format = PyUnicode_FromFormat("%s\nlocation:%s:%d\n", cstring, filename, lineno); + pystring_format = PyUnicode_FromFormat(TIP_("%s\nlocation: %s:%d\n"), cstring, filename, lineno); cstring = _PyUnicode_AsString(pystring_format); BKE_report(reports, RPT_ERROR, cstring); #endif - - fprintf(stderr, "%s\nlocation:%s:%d\n", cstring, filename, lineno); // not exactly needed. just for testing - + + /* not exactly needed. just for testing */ + fprintf(stderr, TIP_("%s\nlocation: %s:%d\n"), cstring, filename, lineno); + Py_DECREF(pystring); - Py_DECREF(pystring_format); // workaround + Py_DECREF(pystring_format); /* workaround */ return 1; } diff --git a/source/blender/python/intern/gpu.h b/source/blender/python/intern/gpu.h index 68e7fa4aa9e..f8c751f7f94 100644 --- a/source/blender/python/intern/gpu.h +++ b/source/blender/python/intern/gpu.h @@ -30,7 +30,7 @@ */ /** - * Initalizes the gpu Python module. + * Initializes the gpu Python module. */ PyObject *GPU_initPython(void); diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c index c08165f9850..a4a4010005a 100644 --- a/source/blender/python/mathutils/mathutils.c +++ b/source/blender/python/mathutils/mathutils.c @@ -276,12 +276,12 @@ int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error } -//----------------------------------MATRIX FUNCTIONS-------------------- +/* ----------------------------------MATRIX FUNCTIONS-------------------- */ /* Utility functions */ -// LomontRRDCompare4, Ever Faster Float Comparisons by Randy Dillon +/* LomontRRDCompare4, Ever Faster Float Comparisons by Randy Dillon */ #define SIGNMASK(i) (-(int)(((unsigned int)(i)) >> 31)) int EXPP_FloatsAreEqual(float af, float bf, int maxDiff) diff --git a/source/blender/python/mathutils/mathutils_Color.c b/source/blender/python/mathutils/mathutils_Color.c index 05fc84eaa87..747a23a719d 100644 --- a/source/blender/python/mathutils/mathutils_Color.c +++ b/source/blender/python/mathutils/mathutils_Color.c @@ -35,8 +35,8 @@ #define COLOR_SIZE 3 -//----------------------------------mathutils.Color() ------------------- -//makes a new color for you to play with +/* ----------------------------------mathutils.Color() ------------------- */ +/* makes a new color for you to play with */ static PyObject *Color_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { float col[3] = {0.0f, 0.0f, 0.0f}; @@ -64,7 +64,7 @@ static PyObject *Color_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return Color_CreatePyObject(col, Py_NEW, type); } -//-----------------------------METHODS---------------------------- +/* -----------------------------METHODS---------------------------- */ /* note: BaseMath_ReadCallback must be called beforehand */ static PyObject *Color_ToTupleExt(ColorObject *self, int ndigits) @@ -113,8 +113,8 @@ static PyObject *Color_deepcopy(ColorObject *self, PyObject *args) return Color_copy(self); } -//----------------------------print object (internal)-------------- -//print the object to screen +/* ----------------------------print object (internal)-------------- */ +/* print the object to screen */ static PyObject *Color_repr(ColorObject *self) { @@ -146,8 +146,8 @@ static PyObject *Color_str(ColorObject *self) return mathutils_dynstr_to_py(ds); /* frees ds */ } -//------------------------tp_richcmpr -//returns -1 exception, 0 false, 1 true +/* ------------------------tp_richcmpr */ +/* returns -1 exception, 0 false, 1 true */ static PyObject *Color_richcmpr(PyObject *a, PyObject *b, int op) { PyObject *res; @@ -184,15 +184,15 @@ static PyObject *Color_richcmpr(PyObject *a, PyObject *b, int op) return Py_INCREF(res), res; } -//---------------------SEQUENCE PROTOCOLS------------------------ -//----------------------------len(object)------------------------ -//sequence length +/* ---------------------SEQUENCE PROTOCOLS------------------------ */ +/* ----------------------------len(object)------------------------ */ +/* sequence length */ static int Color_len(ColorObject *UNUSED(self)) { return COLOR_SIZE; } -//----------------------------object[]--------------------------- -//sequence accessor (get) +/* ----------------------------object[]--------------------------- */ +/* sequence accessor (get) */ static PyObject *Color_item(ColorObject *self, int i) { if (i < 0) i = COLOR_SIZE - i; @@ -210,13 +210,13 @@ static PyObject *Color_item(ColorObject *self, int i) return PyFloat_FromDouble(self->col[i]); } -//----------------------------object[]------------------------- -//sequence accessor (set) +/* ----------------------------object[]------------------------- */ +/* sequence accessor (set) */ static int Color_ass_item(ColorObject *self, int i, PyObject *value) { float f = PyFloat_AsDouble(value); - if (f == -1 && PyErr_Occurred()) { // parsed item not a number + if (f == -1 && PyErr_Occurred()) { /* parsed item not a number */ PyErr_SetString(PyExc_TypeError, "color[item] = x: " "argument not a number"); @@ -238,8 +238,8 @@ static int Color_ass_item(ColorObject *self, int i, PyObject *value) return 0; } -//----------------------------object[z:y]------------------------ -//sequence slice (get) +/* ----------------------------object[z:y]------------------------ */ +/* sequence slice (get) */ static PyObject *Color_slice(ColorObject *self, int begin, int end) { PyObject *tuple; @@ -260,8 +260,8 @@ static PyObject *Color_slice(ColorObject *self, int begin, int end) return tuple; } -//----------------------------object[z:y]------------------------ -//sequence slice (set) +/* ----------------------------object[z:y]------------------------ */ +/* sequence slice (set) */ static int Color_ass_slice(ColorObject *self, int begin, int end, PyObject *seq) { int i, size; @@ -361,7 +361,7 @@ static int Color_ass_subscript(ColorObject *self, PyObject *item, PyObject *valu } } -//-----------------PROTCOL DECLARATIONS-------------------------- +/* -----------------PROTCOL DECLARATIONS-------------------------- */ static PySequenceMethods Color_SeqMethods = { (lenfunc) Color_len, /* sq_length */ (binaryfunc) NULL, /* sq_concat */ @@ -565,7 +565,7 @@ static PyObject *Color_div(PyObject *v1, PyObject *v2) return NULL; } -/* mulplication in-place: obj *= obj */ +/* multiplication in-place: obj *= obj */ static PyObject *Color_imul(PyObject *v1, PyObject *v2) { ColorObject *color = (ColorObject *)v1; @@ -591,7 +591,7 @@ static PyObject *Color_imul(PyObject *v1, PyObject *v2) return v1; } -/* mulplication in-place: obj *= obj */ +/* multiplication in-place: obj *= obj */ static PyObject *Color_idiv(PyObject *v1, PyObject *v2) { ColorObject *color = (ColorObject *)v1; @@ -792,7 +792,7 @@ static PyGetSetDef Color_getseters[] = { }; -//-----------------------METHOD DEFINITIONS ---------------------- +/* -----------------------METHOD DEFINITIONS ---------------------- */ static struct PyMethodDef Color_methods[] = { {"copy", (PyCFunction) Color_copy, METH_NOARGS, Color_copy_doc}, {"__copy__", (PyCFunction) Color_copy, METH_NOARGS, Color_copy_doc}, @@ -800,65 +800,65 @@ static struct PyMethodDef Color_methods[] = { {NULL, NULL, 0, NULL} }; -//------------------PY_OBECT DEFINITION-------------------------- +/* ------------------PY_OBECT DEFINITION-------------------------- */ PyDoc_STRVAR(color_doc, "This object gives access to Colors in Blender." ); PyTypeObject color_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "Color", //tp_name - sizeof(ColorObject), //tp_basicsize - 0, //tp_itemsize - (destructor)BaseMathObject_dealloc, //tp_dealloc - NULL, //tp_print - NULL, //tp_getattr - NULL, //tp_setattr - NULL, //tp_compare - (reprfunc) Color_repr, //tp_repr - &Color_NumMethods, //tp_as_number - &Color_SeqMethods, //tp_as_sequence - &Color_AsMapping, //tp_as_mapping - NULL, //tp_hash - NULL, //tp_call - (reprfunc) Color_str, //tp_str - NULL, //tp_getattro - NULL, //tp_setattro - NULL, //tp_as_buffer - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, //tp_flags - color_doc, //tp_doc - (traverseproc)BaseMathObject_traverse, //tp_traverse - (inquiry)BaseMathObject_clear, //tp_clear - (richcmpfunc)Color_richcmpr, //tp_richcompare - 0, //tp_weaklistoffset - NULL, //tp_iter - NULL, //tp_iternext - Color_methods, //tp_methods - NULL, //tp_members - Color_getseters, //tp_getset - NULL, //tp_base - NULL, //tp_dict - NULL, //tp_descr_get - NULL, //tp_descr_set - 0, //tp_dictoffset - NULL, //tp_init - NULL, //tp_alloc - Color_new, //tp_new - NULL, //tp_free - NULL, //tp_is_gc - NULL, //tp_bases - NULL, //tp_mro - NULL, //tp_cache - NULL, //tp_subclasses - NULL, //tp_weaklist - NULL //tp_del + "Color", /* tp_name */ + sizeof(ColorObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)BaseMathObject_dealloc, /* tp_dealloc */ + NULL, /* tp_print */ + NULL, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ + (reprfunc) Color_repr, /* tp_repr */ + &Color_NumMethods, /* tp_as_number */ + &Color_SeqMethods, /* tp_as_sequence */ + &Color_AsMapping, /* tp_as_mapping */ + NULL, /* tp_hash */ + NULL, /* tp_call */ + (reprfunc) Color_str, /* tp_str */ + NULL, /* tp_getattro */ + NULL, /* tp_setattro */ + NULL, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ + color_doc, /* tp_doc */ + (traverseproc)BaseMathObject_traverse, /* tp_traverse */ + (inquiry)BaseMathObject_clear, /* tp_clear */ + (richcmpfunc)Color_richcmpr, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + NULL, /* tp_iter */ + NULL, /* tp_iternext */ + Color_methods, /* tp_methods */ + NULL, /* tp_members */ + Color_getseters, /* tp_getset */ + NULL, /* tp_base */ + NULL, /* tp_dict */ + NULL, /* tp_descr_get */ + NULL, /* tp_descr_set */ + 0, /* tp_dictoffset */ + NULL, /* tp_init */ + NULL, /* tp_alloc */ + Color_new, /* tp_new */ + NULL, /* tp_free */ + NULL, /* tp_is_gc */ + NULL, /* tp_bases */ + NULL, /* tp_mro */ + NULL, /* tp_cache */ + NULL, /* tp_subclasses */ + NULL, /* tp_weaklist */ + NULL /* tp_del */ }; -//------------------------Color_CreatePyObject (internal)------------- -//creates a new color object +/* ------------------------Color_CreatePyObject (internal)------------- */ +/* creates a new color object */ /* pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER * (i.e. it was allocated elsewhere by MEM_mallocN()) * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON * (i.e. it must be created here with PyMEM_malloc())*/ -PyObject *Color_CreatePyObject(float *col, int type, PyTypeObject *base_type) +PyObject *Color_CreatePyObject(float col[3], int type, PyTypeObject *base_type) { ColorObject *self; diff --git a/source/blender/python/mathutils/mathutils_Color.h b/source/blender/python/mathutils/mathutils_Color.h index eff09c25a99..1c75766c2a9 100644 --- a/source/blender/python/mathutils/mathutils_Color.h +++ b/source/blender/python/mathutils/mathutils_Color.h @@ -46,8 +46,8 @@ typedef struct { * be stored in py_data) or be a wrapper for data allocated through * blender (stored in blend_data). This is an either/or struct not both*/ -//prototypes -PyObject *Color_CreatePyObject(float *col, int type, PyTypeObject *base_type); +/* prototypes */ +PyObject *Color_CreatePyObject(float col[3], int type, PyTypeObject *base_type); PyObject *Color_CreatePyObject_cb(PyObject *cb_user, unsigned char cb_type, unsigned char cb_subtype); diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c index 468ef3788c1..3592e1084fb 100644 --- a/source/blender/python/mathutils/mathutils_Euler.c +++ b/source/blender/python/mathutils/mathutils_Euler.c @@ -39,8 +39,8 @@ #define EULER_SIZE 3 -//----------------------------------mathutils.Euler() ------------------- -//makes a new euler for you to play with +/* ----------------------------------mathutils.Euler() ------------------- */ +/* makes a new euler for you to play with */ static PyObject *Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *seq = NULL; @@ -122,8 +122,8 @@ static PyObject *Euler_ToTupleExt(EulerObject *self, int ndigits) return ret; } -//-----------------------------METHODS---------------------------- -//return a quaternion representation of the euler +/* -----------------------------METHODS---------------------------- + * return a quaternion representation of the euler */ PyDoc_STRVAR(Euler_to_quaternion_doc, ".. method:: to_quaternion()\n" @@ -145,7 +145,7 @@ static PyObject *Euler_to_quaternion(EulerObject *self) return Quaternion_CreatePyObject(quat, Py_NEW, NULL); } -//return a matrix representation of the euler +/* return a matrix representation of the euler */ PyDoc_STRVAR(Euler_to_matrix_doc, ".. method:: to_matrix()\n" "\n" @@ -277,8 +277,8 @@ static PyObject *Euler_make_compatible(EulerObject *self, PyObject *value) Py_RETURN_NONE; } -//----------------------------Euler.rotate()----------------------- -// return a copy of the euler +/* ----------------------------Euler.rotate()----------------------- + * return a copy of the euler */ PyDoc_STRVAR(Euler_copy_doc, ".. function:: copy()\n" @@ -305,8 +305,8 @@ static PyObject *Euler_deepcopy(EulerObject *self, PyObject *args) return Euler_copy(self); } -//----------------------------print object (internal)-------------- -//print the object to screen +/* ----------------------------print object (internal)-------------- + * print the object to screen */ static PyObject *Euler_repr(EulerObject *self) { @@ -374,15 +374,15 @@ static PyObject *Euler_richcmpr(PyObject *a, PyObject *b, int op) return Py_INCREF(res), res; } -//---------------------SEQUENCE PROTOCOLS------------------------ -//----------------------------len(object)------------------------ -//sequence length +/* ---------------------SEQUENCE PROTOCOLS------------------------ */ +/* ----------------------------len(object)------------------------ */ +/* sequence length */ static int Euler_len(EulerObject *UNUSED(self)) { return EULER_SIZE; } -//----------------------------object[]--------------------------- -//sequence accessor (get) +/* ----------------------------object[]--------------------------- */ +/* sequence accessor (get) */ static PyObject *Euler_item(EulerObject *self, int i) { if (i < 0) i = EULER_SIZE - i; @@ -400,13 +400,13 @@ static PyObject *Euler_item(EulerObject *self, int i) return PyFloat_FromDouble(self->eul[i]); } -//----------------------------object[]------------------------- -//sequence accessor (set) +/* ----------------------------object[]------------------------- */ +/* sequence accessor (set) */ static int Euler_ass_item(EulerObject *self, int i, PyObject *value) { float f = PyFloat_AsDouble(value); - if (f == -1 && PyErr_Occurred()) { // parsed item not a number + if (f == -1 && PyErr_Occurred()) { /* parsed item not a number */ PyErr_SetString(PyExc_TypeError, "euler[attribute] = x: " "argument not a number"); @@ -429,8 +429,8 @@ static int Euler_ass_item(EulerObject *self, int i, PyObject *value) return 0; } -//----------------------------object[z:y]------------------------ -//sequence slice (get) +/* ----------------------------object[z:y]------------------------ */ +/* sequence slice (get) */ static PyObject *Euler_slice(EulerObject *self, int begin, int end) { PyObject *tuple; @@ -451,8 +451,8 @@ static PyObject *Euler_slice(EulerObject *self, int begin, int end) return tuple; } -//----------------------------object[z:y]------------------------ -//sequence slice (set) +/* ----------------------------object[z:y]------------------------ */ +/* sequence slice (set) */ static int Euler_ass_slice(EulerObject *self, int begin, int end, PyObject *seq) { int i, size; @@ -553,7 +553,7 @@ static int Euler_ass_subscript(EulerObject *self, PyObject *item, PyObject *valu } } -//-----------------PROTCOL DECLARATIONS-------------------------- +/* -----------------PROTCOL DECLARATIONS-------------------------- */ static PySequenceMethods Euler_SeqMethods = { (lenfunc) Euler_len, /* sq_length */ (binaryfunc) NULL, /* sq_concat */ @@ -629,7 +629,7 @@ static PyGetSetDef Euler_getseters[] = { }; -//-----------------------METHOD DEFINITIONS ---------------------- +/* -----------------------METHOD DEFINITIONS ---------------------- */ static struct PyMethodDef Euler_methods[] = { {"zero", (PyCFunction) Euler_zero, METH_NOARGS, Euler_zero_doc}, {"to_matrix", (PyCFunction) Euler_to_matrix, METH_NOARGS, Euler_to_matrix_doc}, @@ -643,60 +643,60 @@ static struct PyMethodDef Euler_methods[] = { {NULL, NULL, 0, NULL} }; -//------------------PY_OBECT DEFINITION-------------------------- +/* ------------------PY_OBECT DEFINITION-------------------------- */ PyDoc_STRVAR(euler_doc, "This object gives access to Eulers in Blender." ); PyTypeObject euler_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "Euler", //tp_name - sizeof(EulerObject), //tp_basicsize - 0, //tp_itemsize - (destructor)BaseMathObject_dealloc, //tp_dealloc - NULL, //tp_print - NULL, //tp_getattr - NULL, //tp_setattr - NULL, //tp_compare - (reprfunc) Euler_repr, //tp_repr - NULL, //tp_as_number - &Euler_SeqMethods, //tp_as_sequence - &Euler_AsMapping, //tp_as_mapping - NULL, //tp_hash - NULL, //tp_call - (reprfunc) Euler_str, //tp_str - NULL, //tp_getattro - NULL, //tp_setattro - NULL, //tp_as_buffer - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, //tp_flags - euler_doc, //tp_doc - (traverseproc)BaseMathObject_traverse, //tp_traverse - (inquiry)BaseMathObject_clear, //tp_clear - (richcmpfunc)Euler_richcmpr, //tp_richcompare - 0, //tp_weaklistoffset - NULL, //tp_iter - NULL, //tp_iternext - Euler_methods, //tp_methods - NULL, //tp_members - Euler_getseters, //tp_getset - NULL, //tp_base - NULL, //tp_dict - NULL, //tp_descr_get - NULL, //tp_descr_set - 0, //tp_dictoffset - NULL, //tp_init - NULL, //tp_alloc - Euler_new, //tp_new - NULL, //tp_free - NULL, //tp_is_gc - NULL, //tp_bases - NULL, //tp_mro - NULL, //tp_cache - NULL, //tp_subclasses - NULL, //tp_weaklist - NULL //tp_del + "Euler", /* tp_name */ + sizeof(EulerObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)BaseMathObject_dealloc, /* tp_dealloc */ + NULL, /* tp_print */ + NULL, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ + (reprfunc) Euler_repr, /* tp_repr */ + NULL, /* tp_as_number */ + &Euler_SeqMethods, /* tp_as_sequence */ + &Euler_AsMapping, /* tp_as_mapping */ + NULL, /* tp_hash */ + NULL, /* tp_call */ + (reprfunc) Euler_str, /* tp_str */ + NULL, /* tp_getattro */ + NULL, /* tp_setattro */ + NULL, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ + euler_doc, /* tp_doc */ + (traverseproc)BaseMathObject_traverse, /* tp_traverse */ + (inquiry)BaseMathObject_clear, /* tp_clear */ + (richcmpfunc)Euler_richcmpr, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + NULL, /* tp_iter */ + NULL, /* tp_iternext */ + Euler_methods, /* tp_methods */ + NULL, /* tp_members */ + Euler_getseters, /* tp_getset */ + NULL, /* tp_base */ + NULL, /* tp_dict */ + NULL, /* tp_descr_get */ + NULL, /* tp_descr_set */ + 0, /* tp_dictoffset */ + NULL, /* tp_init */ + NULL, /* tp_alloc */ + Euler_new, /* tp_new */ + NULL, /* tp_free */ + NULL, /* tp_is_gc */ + NULL, /* tp_bases */ + NULL, /* tp_mro */ + NULL, /* tp_cache */ + NULL, /* tp_subclasses */ + NULL, /* tp_weaklist */ + NULL /* tp_del */ }; -//------------------------Euler_CreatePyObject (internal)------------- -//creates a new euler object +/* ------------------------Euler_CreatePyObject (internal)------------- */ +/* creates a new euler object */ /* pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER * (i.e. it was allocated elsewhere by MEM_mallocN()) * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON diff --git a/source/blender/python/mathutils/mathutils_Euler.h b/source/blender/python/mathutils/mathutils_Euler.h index e04d45e4630..69e4c086d03 100644 --- a/source/blender/python/mathutils/mathutils_Euler.h +++ b/source/blender/python/mathutils/mathutils_Euler.h @@ -47,7 +47,7 @@ typedef struct { * be stored in py_data) or be a wrapper for data allocated through * blender (stored in blend_data). This is an either/or struct not both */ -//prototypes +/* prototypes */ PyObject *Euler_CreatePyObject(float *eul, const short order, int type, PyTypeObject *base_type); PyObject *Euler_CreatePyObject_cb(PyObject *cb_user, const short order, unsigned char cb_type, unsigned char cb_subtype); diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index be519ded88e..b9f0ce9ad96 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -182,7 +182,7 @@ static int mathutils_matrix_col_get(BaseMathObject *bmo, int col) return -1; /* for 'translation' size will always be '3' even on 4x4 vec */ - num_row = MIN2(self->num_row, ((VectorObject *)bmo)->size); + num_row = min_ii(self->num_row, ((VectorObject *)bmo)->size); for (row = 0; row < num_row; row++) { bmo->data[row] = MATRIX_ITEM(self, row, col); @@ -203,7 +203,7 @@ static int mathutils_matrix_col_set(BaseMathObject *bmo, int col) return -1; /* for 'translation' size will always be '3' even on 4x4 vec */ - num_row = MIN2(self->num_row, ((VectorObject *)bmo)->size); + num_row = min_ii(self->num_row, ((VectorObject *)bmo)->size); for (row = 0; row < num_row; row++) { MATRIX_ITEM(self, row, col) = bmo->data[row]; @@ -329,9 +329,9 @@ Mathutils_Callback mathutils_matrix_translation_cb = { /* matrix column callbacks, this is so you can do matrix.translation = Vector() */ -//----------------------------------mathutils.Matrix() ----------------- -//mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. -//create a new matrix type +/* ----------------------------------mathutils.Matrix() ----------------- */ +/* mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. */ +/* create a new matrix type */ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { if (kwds && PyDict_Size(kwds)) { @@ -384,13 +384,19 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static PyObject *matrix__apply_to_copy(PyNoArgsFunction matrix_func, MatrixObject *self) { PyObject *ret = Matrix_copy(self); - PyObject *ret_dummy = matrix_func(ret); - if (ret_dummy) { - Py_DECREF(ret_dummy); - return (PyObject *)ret; + if (ret) { + PyObject *ret_dummy = matrix_func(ret); + if (ret_dummy) { + Py_DECREF(ret_dummy); + return (PyObject *)ret; + } + else { /* error */ + Py_DECREF(ret); + return NULL; + } } - else { /* error */ - Py_DECREF(ret); + else { + /* copy may fail if the read callback errors out */ return NULL; } } @@ -410,7 +416,7 @@ static void matrix_3x3_as_4x4(float mat[16]) /*-----------------------CLASS-METHODS----------------------------*/ -//mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. +/* mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. */ PyDoc_STRVAR(C_Matrix_Identity_doc, ".. classmethod:: Identity(size)\n" "\n" @@ -518,7 +524,7 @@ static PyObject *C_Matrix_Rotation(PyObject *cls, PyObject *args) const float angle_cos = cosf(angle); const float angle_sin = sinf(angle); - //2D rotation matrix + /* 2D rotation matrix */ mat[0] = angle_cos; mat[1] = angle_sin; mat[2] = -angle_sin; @@ -532,7 +538,7 @@ static PyObject *C_Matrix_Rotation(PyObject *cls, PyObject *args) if (matSize == 4) { matrix_3x3_as_4x4(mat); } - //pass to matrix creation + /* pass to matrix creation */ return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls); } @@ -556,8 +562,8 @@ static PyObject *C_Matrix_Translation(PyObject *cls, PyObject *value) return Matrix_CreatePyObject(&mat[0][0], 4, 4, Py_NEW, (PyTypeObject *)cls); } -//----------------------------------mathutils.Matrix.Scale() ------------- -//mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. +/* ----------------------------------mathutils.Matrix.Scale() ------------- */ +/* mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. */ PyDoc_STRVAR(C_Matrix_Scale_doc, ".. classmethod:: Scale(factor, size, axis)\n" "\n" @@ -601,7 +607,7 @@ static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args) return NULL; } } - if (vec == NULL) { //scaling along axis + if (vec == NULL) { /* scaling along axis */ if (matSize == 2) { mat[0] = factor; mat[3] = factor; @@ -645,11 +651,11 @@ static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args) if (matSize == 4) { matrix_3x3_as_4x4(mat); } - //pass to matrix creation + /* pass to matrix creation */ return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls); } -//----------------------------------mathutils.Matrix.OrthoProjection() --- -//mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. +/* ----------------------------------mathutils.Matrix.OrthoProjection() --- */ +/* mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. */ PyDoc_STRVAR(C_Matrix_OrthoProjection_doc, ".. classmethod:: OrthoProjection(axis, size)\n" "\n" @@ -685,7 +691,7 @@ static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args) return NULL; } - if (PyUnicode_Check(axis)) { //ortho projection onto cardinal plane + if (PyUnicode_Check(axis)) { /* ortho projection onto cardinal plane */ Py_ssize_t plane_len; const char *plane = _PyUnicode_AsStringAndSize(axis, &plane_len); if (matSize == 2) { @@ -726,7 +732,7 @@ static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args) } } else { - //arbitrary plane + /* arbitrary plane */ int vec_size = (matSize == 2 ? 2 : 3); float tvec[4]; @@ -737,7 +743,7 @@ static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args) return NULL; } - //normalize arbitrary axis + /* normalize arbitrary axis */ for (x = 0; x < vec_size; x++) { norm += tvec[x] * tvec[x]; } @@ -766,7 +772,7 @@ static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args) if (matSize == 4) { matrix_3x3_as_4x4(mat); } - //pass to matrix creation + /* pass to matrix creation */ return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls); } @@ -869,7 +875,7 @@ static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args) if (matSize == 4) { matrix_3x3_as_4x4(mat); } - //pass to matrix creation + /* pass to matrix creation */ return Matrix_CreatePyObject(mat, matSize, matSize, Py_NEW, (PyTypeObject *)cls); } @@ -1196,17 +1202,27 @@ static PyObject *Matrix_invert(MatrixObject *self) if (det != 0) { /* calculate the classical adjoint */ - if (self->num_col == 2) { - mat[0] = MATRIX_ITEM(self, 1, 1); - mat[1] = -MATRIX_ITEM(self, 0, 1); - mat[2] = -MATRIX_ITEM(self, 1, 0); - mat[3] = MATRIX_ITEM(self, 0, 0); - } - else if (self->num_col == 3) { - adjoint_m3_m3((float (*)[3])mat, (float (*)[3])self->matrix); - } - else if (self->num_col == 4) { - adjoint_m4_m4((float (*)[4])mat, (float (*)[4])self->matrix); + switch (self->num_col) { + case 2: + { + adjoint_m2_m2((float (*)[2])mat, (float (*)[2])self->matrix); + break; + } + case 3: + { + adjoint_m3_m3((float (*)[3])mat, (float (*)[3])self->matrix); + break; + } + case 4: + { + adjoint_m4_m4((float (*)[4])mat, (float (*)[4])self->matrix); + break; + } + default: + PyErr_Format(PyExc_TypeError, + "Matrix invert(ed): size (%d) unsupported", + (int)self->num_col); + return NULL; } /* divide by determinate */ for (x = 0; x < (self->num_col * self->num_row); x++) { @@ -1236,7 +1252,7 @@ PyDoc_STRVAR(Matrix_inverted_doc, "\n" " Return an inverted copy of the matrix.\n" "\n" -" :return: the inverted matrix.\n" +" :return: the inverted matrix.\n" " :rtype: :class:`Matrix`\n" "\n" " .. note:: When the matrix cant be inverted a :exc:`ValueError` exception is raised.\n" @@ -1246,6 +1262,77 @@ static PyObject *Matrix_inverted(MatrixObject *self) return matrix__apply_to_copy((PyNoArgsFunction)Matrix_invert, self); } +/*---------------------------matrix.adjugate() ---------------------*/ +PyDoc_STRVAR(Matrix_adjugate_doc, +".. method:: adjugate()\n" +"\n" +" Set the matrix to its adjugate.\n" +"\n" +" .. note:: When the matrix cant be adjugated a :exc:`ValueError` exception is raised.\n" +"\n" +" .. seealso:: \n" +); +static PyObject *Matrix_adjugate(MatrixObject *self) +{ + if (BaseMath_ReadCallback(self) == -1) + return NULL; + + if (self->num_col != self->num_row) { + PyErr_SetString(PyExc_TypeError, + "Matrix.adjugate(d): " + "only square matrices are supported"); + return NULL; + } + + /* calculate the classical adjoint */ + switch (self->num_col) { + case 2: + { + float mat[2][2]; + adjoint_m2_m2(mat, (float (*)[2])self->matrix); + copy_v4_v4((float *)self->matrix, (float *)mat); + break; + } + case 3: + { + float mat[3][3]; + adjoint_m3_m3(mat, (float (*)[3])self->matrix); + copy_m3_m3((float (*)[3])self->matrix, mat); + break; + } + case 4: + { + float mat[4][4]; + adjoint_m4_m4(mat, (float (*)[4])self->matrix); + copy_m4_m4((float (*)[4])self->matrix, mat); + break; + } + default: + PyErr_Format(PyExc_TypeError, + "Matrix adjugate(d): size (%d) unsupported", + (int)self->num_col); + return NULL; + } + + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Matrix_adjugated_doc, +".. method:: adjugated()\n" +"\n" +" Return an adjugated copy of the matrix.\n" +"\n" +" :return: the adjugated matrix.\n" +" :rtype: :class:`Matrix`\n" +"\n" +" .. note:: When the matrix cant be adjugated a :exc:`ValueError` exception is raised.\n" +); +static PyObject *Matrix_adjugated(MatrixObject *self) +{ + return matrix__apply_to_copy((PyNoArgsFunction)Matrix_adjugate, self); +} + PyDoc_STRVAR(Matrix_rotate_doc, ".. method:: rotate(other)\n" "\n" @@ -1579,7 +1666,7 @@ static PyObject *Matrix_str(MatrixObject *self) maxsize[col] = 0; for (row = 0; row < self->num_row; row++) { int size = BLI_snprintf(dummy_buf, sizeof(dummy_buf), "%.4f", MATRIX_ITEM(self, row, col)); - maxsize[col] = MAX2(maxsize[col], size); + maxsize[col] = max_ii(maxsize[col], size); } } @@ -1875,7 +1962,7 @@ static PyObject *Matrix_sub(PyObject *m1, PyObject *m2) return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_NEW, Py_TYPE(mat1)); } /*------------------------obj * obj------------------------------ - * mulplication */ + * multiplication */ static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar) { float tmat[16]; @@ -1921,7 +2008,7 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2) for (row = 0; row < mat1->num_row; row++) { double dot = 0.0f; for (item = 0; item < mat1->num_col; item++) { - dot += MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col); + dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col)); } mat[(col * mat1->num_row) + row] = (float)dot; } @@ -2281,6 +2368,8 @@ static struct PyMethodDef Matrix_methods[] = { {"transposed", (PyCFunction) Matrix_transposed, METH_NOARGS, Matrix_transposed_doc}, {"invert", (PyCFunction) Matrix_invert, METH_NOARGS, Matrix_invert_doc}, {"inverted", (PyCFunction) Matrix_inverted, METH_NOARGS, Matrix_inverted_doc}, + {"adjugate", (PyCFunction) Matrix_adjugate, METH_NOARGS, Matrix_adjugate_doc}, + {"adjugated", (PyCFunction) Matrix_adjugated, METH_NOARGS, Matrix_adjugated_doc}, {"to_3x3", (PyCFunction) Matrix_to_3x3, METH_NOARGS, Matrix_to_3x3_doc}, /* TODO. {"resize_3x3", (PyCFunction) Matrix_resize3x3, METH_NOARGS, Matrix_resize3x3_doc}, */ {"to_4x4", (PyCFunction) Matrix_to_4x4, METH_NOARGS, Matrix_to_4x4_doc}, @@ -2335,8 +2424,8 @@ PyTypeObject matrix_Type = { NULL, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ matrix_doc, /*tp_doc*/ - (traverseproc)BaseMathObject_traverse, //tp_traverse - (inquiry)BaseMathObject_clear, //tp_clear + (traverseproc)BaseMathObject_traverse, /* tp_traverse */ + (inquiry)BaseMathObject_clear, /*tp_clear*/ (richcmpfunc)Matrix_richcmpr, /*tp_richcompare*/ 0, /*tp_weaklistoffset*/ NULL, /*tp_iter*/ @@ -2635,8 +2724,8 @@ PyTypeObject matrix_access_Type = { NULL, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ NULL, /*tp_doc*/ - (traverseproc)MatrixAccess_traverse, //tp_traverse - (inquiry)MatrixAccess_clear, //tp_clear + (traverseproc)MatrixAccess_traverse,/*tp_traverse*/ + (inquiry)MatrixAccess_clear, /*tp_clear*/ NULL /* (richcmpfunc)MatrixAccess_richcmpr */ /* TODO*/, /*tp_richcompare*/ 0, /*tp_weaklistoffset*/ (getiterfunc)MatrixAccess_iter, /* getiterfunc tp_iter; */ diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index b595dab494d..b9aba995973 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -44,7 +44,7 @@ static void quat__axis_angle_sanitize(float axis[3], float *angle); static PyObject *Quaternion_copy(QuaternionObject *self); static PyObject *Quaternion_deepcopy(QuaternionObject *self, PyObject *args); -//-----------------------------METHODS------------------------------ +/* -----------------------------METHODS------------------------------ */ /* note: BaseMath_ReadCallback must be called beforehand */ static PyObject *Quaternion_to_tuple_ext(QuaternionObject *self, int ndigits) @@ -124,7 +124,7 @@ static PyObject *Quaternion_to_euler(QuaternionObject *self, PyObject *args) return Euler_CreatePyObject(eul, order, Py_NEW, NULL); } -//----------------------------Quaternion.toMatrix()------------------ + PyDoc_STRVAR(Quaternion_to_matrix_doc, ".. method:: to_matrix()\n" "\n" @@ -144,7 +144,6 @@ static PyObject *Quaternion_to_matrix(QuaternionObject *self) return Matrix_CreatePyObject(mat, 3, 3, Py_NEW, NULL); } -//----------------------------Quaternion.toMatrix()------------------ PyDoc_STRVAR(Quaternion_to_axis_angle_doc, ".. method:: to_axis_angle()\n" "\n" @@ -176,8 +175,6 @@ static PyObject *Quaternion_to_axis_angle(QuaternionObject *self) return ret; } - -//----------------------------Quaternion.cross(other)------------------ PyDoc_STRVAR(Quaternion_cross_doc, ".. method:: cross(other)\n" "\n" @@ -205,7 +202,6 @@ static PyObject *Quaternion_cross(QuaternionObject *self, PyObject *value) return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(self)); } -//----------------------------Quaternion.dot(other)------------------ PyDoc_STRVAR(Quaternion_dot_doc, ".. method:: dot(other)\n" "\n" @@ -335,8 +331,8 @@ static PyObject *Quaternion_rotate(QuaternionObject *self, PyObject *value) Py_RETURN_NONE; } -//----------------------------Quaternion.normalize()---------------- -//normalize the axis of rotation of [theta, vector] +/* ----------------------------Quaternion.normalize()---------------- */ +/* normalize the axis of rotation of [theta, vector] */ PyDoc_STRVAR(Quaternion_normalize_doc, ".. function:: normalize()\n" "\n" @@ -365,7 +361,6 @@ static PyObject *Quaternion_normalized(QuaternionObject *self) return quat__apply_to_copy((PyNoArgsFunction)Quaternion_normalize, self); } -//----------------------------Quaternion.invert()------------------ PyDoc_STRVAR(Quaternion_invert_doc, ".. function:: invert()\n" "\n" @@ -394,7 +389,6 @@ static PyObject *Quaternion_inverted(QuaternionObject *self) return quat__apply_to_copy((PyNoArgsFunction)Quaternion_invert, self); } -//----------------------------Quaternion.identity()----------------- PyDoc_STRVAR(Quaternion_identity_doc, ".. function:: identity()\n" "\n" @@ -413,7 +407,7 @@ static PyObject *Quaternion_identity(QuaternionObject *self) (void)BaseMath_WriteCallback(self); Py_RETURN_NONE; } -//----------------------------Quaternion.negate()------------------- + PyDoc_STRVAR(Quaternion_negate_doc, ".. function:: negate()\n" "\n" @@ -432,7 +426,7 @@ static PyObject *Quaternion_negate(QuaternionObject *self) (void)BaseMath_WriteCallback(self); Py_RETURN_NONE; } -//----------------------------Quaternion.conjugate()---------------- + PyDoc_STRVAR(Quaternion_conjugate_doc, ".. function:: conjugate()\n" "\n" @@ -461,7 +455,6 @@ static PyObject *Quaternion_conjugated(QuaternionObject *self) return quat__apply_to_copy((PyNoArgsFunction)Quaternion_conjugate, self); } -//----------------------------Quaternion.copy()---------------- PyDoc_STRVAR(Quaternion_copy_doc, ".. function:: copy()\n" "\n" @@ -487,8 +480,7 @@ static PyObject *Quaternion_deepcopy(QuaternionObject *self, PyObject *args) return Quaternion_copy(self); } -//----------------------------print object (internal)-------------- -//print the object to screen +/* print the object to screen */ static PyObject *Quaternion_repr(QuaternionObject *self) { PyObject *ret, *tuple; @@ -555,15 +547,15 @@ static PyObject *Quaternion_richcmpr(PyObject *a, PyObject *b, int op) return Py_INCREF(res), res; } -//---------------------SEQUENCE PROTOCOLS------------------------ -//----------------------------len(object)------------------------ -//sequence length +/* ---------------------SEQUENCE PROTOCOLS------------------------ */ +/* ----------------------------len(object)------------------------ */ +/* sequence length */ static int Quaternion_len(QuaternionObject *UNUSED(self)) { return QUAT_SIZE; } -//----------------------------object[]--------------------------- -//sequence accessor (get) +/* ----------------------------object[]--------------------------- */ +/* sequence accessor (get) */ static PyObject *Quaternion_item(QuaternionObject *self, int i) { if (i < 0) i = QUAT_SIZE - i; @@ -581,8 +573,8 @@ static PyObject *Quaternion_item(QuaternionObject *self, int i) return PyFloat_FromDouble(self->quat[i]); } -//----------------------------object[]------------------------- -//sequence accessor (set) +/* ----------------------------object[]------------------------- */ +/* sequence accessor (set) */ static int Quaternion_ass_item(QuaternionObject *self, int i, PyObject *ob) { float scalar = (float)PyFloat_AsDouble(ob); @@ -608,8 +600,8 @@ static int Quaternion_ass_item(QuaternionObject *self, int i, PyObject *ob) return 0; } -//----------------------------object[z:y]------------------------ -//sequence slice (get) +/* ----------------------------object[z:y]------------------------ */ +/* sequence slice (get) */ static PyObject *Quaternion_slice(QuaternionObject *self, int begin, int end) { PyObject *tuple; @@ -630,8 +622,8 @@ static PyObject *Quaternion_slice(QuaternionObject *self, int begin, int end) return tuple; } -//----------------------------object[z:y]------------------------ -//sequence slice (set) +/* ----------------------------object[z:y]------------------------ */ +/* sequence slice (set) */ static int Quaternion_ass_slice(QuaternionObject *self, int begin, int end, PyObject *seq) { int i, size; @@ -734,9 +726,9 @@ static int Quaternion_ass_subscript(QuaternionObject *self, PyObject *item, PyOb } } -//------------------------NUMERIC PROTOCOLS---------------------- -//------------------------obj + obj------------------------------ -//addition +/* ------------------------NUMERIC PROTOCOLS---------------------- */ +/* ------------------------obj + obj------------------------------ */ +/* addition */ static PyObject *Quaternion_add(PyObject *q1, PyObject *q2) { float quat[QUAT_SIZE]; @@ -758,8 +750,8 @@ static PyObject *Quaternion_add(PyObject *q1, PyObject *q2) add_qt_qtqt(quat, quat1->quat, quat2->quat, 1.0f); return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(q1)); } -//------------------------obj - obj------------------------------ -//subtraction +/* ------------------------obj - obj------------------------------ */ +/* subtraction */ static PyObject *Quaternion_sub(PyObject *q1, PyObject *q2) { int x; @@ -795,8 +787,8 @@ static PyObject *quat_mul_float(QuaternionObject *quat, const float scalar) return Quaternion_CreatePyObject(tquat, Py_NEW, Py_TYPE(quat)); } -//------------------------obj * obj------------------------------ -//mulplication +/*------------------------obj * obj------------------------------ + * multiplication */ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2) { float quat[QUAT_SIZE], scalar; @@ -875,7 +867,7 @@ static PyObject *Quaternion_neg(QuaternionObject *self) } -//-----------------PROTOCOL DECLARATIONS-------------------------- +/* -----------------PROTOCOL DECLARATIONS-------------------------- */ static PySequenceMethods Quaternion_SeqMethods = { (lenfunc) Quaternion_len, /* sq_length */ (binaryfunc) NULL, /* sq_concat */ @@ -1060,7 +1052,7 @@ static int Quaternion_axis_vector_set(QuaternionObject *self, PyObject *value, v return 0; } -//----------------------------------mathutils.Quaternion() -------------- +/* ----------------------------------mathutils.Quaternion() -------------- */ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *seq = NULL; @@ -1140,7 +1132,7 @@ static void quat__axis_angle_sanitize(float axis[3], float *angle) } } -//-----------------------METHOD DEFINITIONS ---------------------- +/* -----------------------METHOD DEFINITIONS ---------------------- */ static struct PyMethodDef Quaternion_methods[] = { /* in place only */ {"identity", (PyCFunction) Quaternion_identity, METH_NOARGS, Quaternion_identity_doc}, @@ -1190,60 +1182,60 @@ static PyGetSetDef Quaternion_getseters[] = { {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; -//------------------PY_OBECT DEFINITION-------------------------- +/* ------------------PY_OBECT DEFINITION-------------------------- */ PyDoc_STRVAR(quaternion_doc, "This object gives access to Quaternions in Blender." ); PyTypeObject quaternion_Type = { PyVarObject_HEAD_INIT(NULL, 0) - "Quaternion", //tp_name - sizeof(QuaternionObject), //tp_basicsize - 0, //tp_itemsize - (destructor)BaseMathObject_dealloc, //tp_dealloc - NULL, //tp_print - NULL, //tp_getattr - NULL, //tp_setattr - NULL, //tp_compare - (reprfunc) Quaternion_repr, //tp_repr - &Quaternion_NumMethods, //tp_as_number - &Quaternion_SeqMethods, //tp_as_sequence - &Quaternion_AsMapping, //tp_as_mapping - NULL, //tp_hash - NULL, //tp_call - (reprfunc) Quaternion_str, //tp_str - NULL, //tp_getattro - NULL, //tp_setattro - NULL, //tp_as_buffer - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, //tp_flags - quaternion_doc, //tp_doc - (traverseproc)BaseMathObject_traverse, //tp_traverse - (inquiry)BaseMathObject_clear, //tp_clear - (richcmpfunc)Quaternion_richcmpr, //tp_richcompare - 0, //tp_weaklistoffset - NULL, //tp_iter - NULL, //tp_iternext - Quaternion_methods, //tp_methods - NULL, //tp_members - Quaternion_getseters, //tp_getset - NULL, //tp_base - NULL, //tp_dict - NULL, //tp_descr_get - NULL, //tp_descr_set - 0, //tp_dictoffset - NULL, //tp_init - NULL, //tp_alloc - Quaternion_new, //tp_new - NULL, //tp_free - NULL, //tp_is_gc - NULL, //tp_bases - NULL, //tp_mro - NULL, //tp_cache - NULL, //tp_subclasses - NULL, //tp_weaklist - NULL, //tp_del + "Quaternion", /* tp_name */ + sizeof(QuaternionObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)BaseMathObject_dealloc, /* tp_dealloc */ + NULL, /* tp_print */ + NULL, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ + (reprfunc) Quaternion_repr, /* tp_repr */ + &Quaternion_NumMethods, /* tp_as_number */ + &Quaternion_SeqMethods, /* tp_as_sequence */ + &Quaternion_AsMapping, /* tp_as_mapping */ + NULL, /* tp_hash */ + NULL, /* tp_call */ + (reprfunc) Quaternion_str, /* tp_str */ + NULL, /* tp_getattro */ + NULL, /* tp_setattro */ + NULL, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ + quaternion_doc, /* tp_doc */ + (traverseproc)BaseMathObject_traverse, /* tp_traverse */ + (inquiry)BaseMathObject_clear, /* tp_clear */ + (richcmpfunc)Quaternion_richcmpr, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + NULL, /* tp_iter */ + NULL, /* tp_iternext */ + Quaternion_methods, /* tp_methods */ + NULL, /* tp_members */ + Quaternion_getseters, /* tp_getset */ + NULL, /* tp_base */ + NULL, /* tp_dict */ + NULL, /* tp_descr_get */ + NULL, /* tp_descr_set */ + 0, /* tp_dictoffset */ + NULL, /* tp_init */ + NULL, /* tp_alloc */ + Quaternion_new, /* tp_new */ + NULL, /* tp_free */ + NULL, /* tp_is_gc */ + NULL, /* tp_bases */ + NULL, /* tp_mro */ + NULL, /* tp_cache */ + NULL, /* tp_subclasses */ + NULL, /* tp_weaklist */ + NULL, /* tp_del */ }; -//------------------------Quaternion_CreatePyObject (internal)------------- -//creates a new quaternion object +/* ------------------------Quaternion_CreatePyObject (internal)------------- */ +/* creates a new quaternion object */ /*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER * (i.e. it was allocated elsewhere by MEM_mallocN()) * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON @@ -1266,7 +1258,7 @@ PyObject *Quaternion_CreatePyObject(float *quat, int type, PyTypeObject *base_ty } else if (type == Py_NEW) { self->quat = PyMem_Malloc(QUAT_SIZE * sizeof(float)); - if (!quat) { //new empty + if (!quat) { /* new empty */ unit_qt(self->quat); } else { diff --git a/source/blender/python/mathutils/mathutils_Quaternion.h b/source/blender/python/mathutils/mathutils_Quaternion.h index 4ffe8488843..b88715096bf 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.h +++ b/source/blender/python/mathutils/mathutils_Quaternion.h @@ -44,7 +44,7 @@ typedef struct { * be stored in py_data) or be a wrapper for data allocated through * blender (stored in blend_data). This is an either/or struct not both */ -//prototypes +/* prototypes */ PyObject *Quaternion_CreatePyObject(float *quat, int type, PyTypeObject *base_type); PyObject *Quaternion_CreatePyObject_cb(PyObject *cb_user, unsigned char cb_type, unsigned char cb_subtype); diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index 74a4cd838d0..06d7f3fec51 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -1100,12 +1100,12 @@ static PyObject *Vector_project(VectorObject *self, PyObject *value) if (BaseMath_ReadCallback(self) == -1) return NULL; - //get dot products + /* get dot products */ for (x = 0; x < size; x++) { dot += (double)(self->vec[x] * tvec[x]); dot2 += (double)(tvec[x] * tvec[x]); } - //projection + /* projection */ dot /= dot2; for (x = 0; x < size; x++) { vec[x] = (float)dot * tvec[x]; @@ -1530,7 +1530,7 @@ static PyObject *Vector_isub(PyObject *v1, PyObject *v2) } /*------------------------obj * obj------------------------------ - * mulplication*/ + * multiplication */ /* COLUMN VECTOR Multiplication (Matrix X Vector) @@ -1687,7 +1687,7 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2) return NULL; } -/* mulplication in-place: obj *= obj */ +/* multiplication in-place: obj *= obj */ static PyObject *Vector_imul(PyObject *v1, PyObject *v2) { VectorObject *vec = (VectorObject *)v1; @@ -2709,11 +2709,11 @@ static int row_vector_multiplication(float r_vec[MAX_DIMENSIONS], VectorObject * memcpy(vec_cpy, vec->vec, vec_size * sizeof(float)); r_vec[3] = 1.0f; - //muliplication + /* muliplication */ for (col = 0; col < mat->num_col; col++) { double dot = 0.0; for (row = 0; row < mat->num_row; row++) { - dot += MATRIX_ITEM(mat, row, col) * vec_cpy[row]; + dot += (double)(MATRIX_ITEM(mat, row, col) * vec_cpy[row]); } r_vec[z++] = (float)dot; } @@ -2733,7 +2733,7 @@ static PyObject *Vector_negate(VectorObject *self) negate_vn(self->vec, self->size); - (void)BaseMath_WriteCallback(self); // already checked for error + (void)BaseMath_WriteCallback(self); /* already checked for error */ Py_RETURN_NONE; } @@ -2829,10 +2829,10 @@ PyTypeObject vector_Type = { /*** Assigned meaning in release 2.0 ***/ /* call function for all accessible objects */ - (traverseproc)BaseMathObject_traverse, //tp_traverse + (traverseproc)BaseMathObject_traverse, /* tp_traverse */ /* delete references to contained objects */ - (inquiry)BaseMathObject_clear, //tp_clear + (inquiry)BaseMathObject_clear, /* tp_clear */ /*** Assigned meaning in release 2.1 ***/ /*** rich comparisons ***/ diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c index 19f9aa2dc88..22317636faa 100644 --- a/source/blender/python/mathutils/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -46,14 +46,12 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -#define SWAP_FLOAT(a, b, tmp) tmp = a; a = b; b = tmp - /*-------------------------DOC STRINGS ---------------------------*/ PyDoc_STRVAR(M_Geometry_doc, "The Blender geometry module" ); -//---------------------------------INTERSECTION FUNCTIONS-------------------- +/* ---------------------------------INTERSECTION FUNCTIONS-------------------- */ PyDoc_STRVAR(M_Geometry_intersect_ray_tri_doc, ".. function:: intersect_ray_tri(v1, v2, v3, ray, orig, clip=True)\n" @@ -253,10 +251,6 @@ static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject } } - - - -//----------------------------geometry.normal() ------------------- PyDoc_STRVAR(M_Geometry_normal_doc, ".. function:: normal(v1, v2, v3, v4=None)\n" "\n" @@ -340,7 +334,7 @@ static PyObject *M_Geometry_normal(PyObject *UNUSED(self), PyObject *args) return Vector_CreatePyObject(n, 3, Py_NEW, NULL); } -//--------------------------------- AREA FUNCTIONS-------------------- +/* --------------------------------- AREA FUNCTIONS-------------------- */ PyDoc_STRVAR(M_Geometry_area_tri_doc, ".. function:: area_tri(v1, v2, v3)\n" diff --git a/source/blender/python/mathutils/mathutils_noise.c b/source/blender/python/mathutils/mathutils_noise.c index da32e36dc02..4977663038d 100644 --- a/source/blender/python/mathutils/mathutils_noise.c +++ b/source/blender/python/mathutils/mathutils_noise.c @@ -43,6 +43,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_noise.h" #include "BLI_utildefines.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/python/mathutils/mathutils_noise.h b/source/blender/python/mathutils/mathutils_noise.h index f4bec88e59a..2ed3e32f4f1 100644 --- a/source/blender/python/mathutils/mathutils_noise.h +++ b/source/blender/python/mathutils/mathutils_noise.h @@ -33,4 +33,4 @@ PyMODINIT_FUNC PyInit_mathutils_noise(void); PyMODINIT_FUNC PyInit_mathutils_noise_types(void); PyMODINIT_FUNC PyInit_mathutils_noise_metrics(void); -#endif // __MATHUTILS_NOISE_H__ +#endif /* __MATHUTILS_NOISE_H__ */ diff --git a/source/blender/python/rna_dump.py b/source/blender/python/rna_dump.py index 489f011e693..15cc60d997e 100644 --- a/source/blender/python/rna_dump.py +++ b/source/blender/python/rna_dump.py @@ -95,7 +95,7 @@ def seek(r, txt, recurs): if GEN_PATH: newtxt = txt + '.' + item - if item == 'rna_type' and VERBOSE_TYPE == False: # just avoid because it spits out loads of data + if item == 'rna_type' and VERBOSE_TYPE is False: # just avoid because it spits out loads of data continue value = getattr(r, item, None) @@ -114,7 +114,7 @@ def seek(r, txt, recurs): except: length = 0 - if VERBOSE == False and length >= 4: + if VERBOSE is False and length >= 4: for i in (0, length - 1): if i > 0: if PRINT_DATA: diff --git a/source/blender/quicktime/apple/qtkit_export.m b/source/blender/quicktime/apple/qtkit_export.m index bb87fe21c49..e0858cd5ec2 100644 --- a/source/blender/quicktime/apple/qtkit_export.m +++ b/source/blender/quicktime/apple/qtkit_export.m @@ -143,7 +143,7 @@ QuicktimeCodecTypeDesc* quicktime_get_videocodecType_desc(int indexValue) int quicktime_rnatmpvalue_from_videocodectype(int codecType) { int i; - for (i=0;ipic); BLI_path_abs(string, G.main->name); @@ -313,8 +313,8 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSError *error; char name[1024]; - int success= 1; - OSStatus err=noErr; + int success = 1; + OSStatus err = noErr; if(qtexport == NULL) qtexport = MEM_callocN(sizeof(QuicktimeExport), "QuicktimeExport"); @@ -323,7 +323,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R /* Check first if the QuickTime 7.2.1 initToWritableFile: method is available */ if ([[[[QTMovie alloc] init] autorelease] respondsToSelector:@selector(initToWritableFile:error:)] != YES) { BKE_report(reports, RPT_ERROR, "\nUnable to create quicktime movie, need Quicktime rev 7.2.1 or later"); - success= 0; + success = 0; } else { makeqtstring(rd, name); @@ -543,7 +543,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R if(qtexport->movie == nil) { BKE_report(reports, RPT_ERROR, "Unable to create quicktime movie."); - success= 0; + success = 0; if (qtexport->filename) [qtexport->filename release]; qtexport->filename = nil; if (qtexport->audioFileName) [qtexport->audioFileName release]; @@ -561,19 +561,21 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R /* specifying the codec attributes : try to retrieve them from render data first*/ if (rd->qtcodecsettings.codecType) { - qtexport->frameAttributes = [NSDictionary dictionaryWithObjectsAndKeys: - stringWithCodecType(rd->qtcodecsettings.codecType), - QTAddImageCodecType, - [NSNumber numberWithLong:((rd->qtcodecsettings.codecSpatialQuality)*codecLosslessQuality)/100], - QTAddImageCodecQuality, - nil]; + qtexport->frameAttributes = [ + NSDictionary dictionaryWithObjectsAndKeys: + stringWithCodecType(rd->qtcodecsettings.codecType), + QTAddImageCodecType, + [NSNumber numberWithLong:((rd->qtcodecsettings.codecSpatialQuality)*codecLosslessQuality)/100], + QTAddImageCodecQuality, + nil]; } else { - qtexport->frameAttributes = [NSDictionary dictionaryWithObjectsAndKeys:@"jpeg", - QTAddImageCodecType, - [NSNumber numberWithLong:codecHighQuality], - QTAddImageCodecQuality, - nil]; + qtexport->frameAttributes = [ + NSDictionary dictionaryWithObjectsAndKeys:@"jpeg", + QTAddImageCodecType, + [NSNumber numberWithLong:codecHighQuality], + QTAddImageCodecQuality, + nil]; } [qtexport->frameAttributes retain]; @@ -624,8 +626,8 @@ int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, in return 0; } - from_Ptr = (unsigned char*)pixels; - to_Ptr = (unsigned char*)[blBitmapFormatImage bitmapData]; + from_Ptr = (unsigned char *)pixels; + to_Ptr = (unsigned char *)[blBitmapFormatImage bitmapData]; for (y = 0; y < recty; y++) { to_i = (recty-y-1)*rectx; from_i = y*rectx; @@ -647,7 +649,7 @@ int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, in if (qtexport->audioFile) { UInt32 audioPacketsConverted; /* Append audio */ - while (qtexport->audioTotalExportedFrames < qtexport->audioLastFrame) { + while (qtexport->audioTotalExportedFrames < qtexport->audioLastFrame) { qtexport->audioBufferList.mNumberBuffers = 1; qtexport->audioBufferList.mBuffers[0].mNumberChannels = qtexport->audioOutputFormat.mChannelsPerFrame; @@ -683,7 +685,7 @@ int append_qt(struct RenderData *rd, int start_frame, int frame, int *pixels, in } } - [pool drain]; + [pool drain]; return 1; } diff --git a/source/blender/quicktime/apple/qtkit_import.m b/source/blender/quicktime/apple/qtkit_import.m index 75b9056de1b..2e910e38871 100644 --- a/source/blender/quicktime/apple/qtkit_import.m +++ b/source/blender/quicktime/apple/qtkit_import.m @@ -71,7 +71,7 @@ void quicktime_init(void) void quicktime_exit(void) { - if(G.have_quicktime) { + if (G.have_quicktime) { free_qtcomponentdata(); } } @@ -82,27 +82,30 @@ int anim_is_quicktime (const char *name) NSAutoreleasePool *pool; // don't let quicktime movie import handle these - if( BLI_testextensie(name, ".swf") || - BLI_testextensie(name, ".txt") || - BLI_testextensie(name, ".mpg") || - BLI_testextensie(name, ".avi") || // wouldn't be appropriate ;) - BLI_testextensie(name, ".mov") || // disabled, suboptimal decoding speed - BLI_testextensie(name, ".mp4") || // disabled, suboptimal decoding speed - BLI_testextensie(name, ".m4v") || // disabled, suboptimal decoding speed - BLI_testextensie(name, ".tga") || - BLI_testextensie(name, ".png") || - BLI_testextensie(name, ".bmp") || - BLI_testextensie(name, ".jpg") || - BLI_testextensie(name, ".wav") || - BLI_testextensie(name, ".zip") || - BLI_testextensie(name, ".mp3")) return 0; + if (BLI_testextensie(name, ".swf") || + BLI_testextensie(name, ".txt") || + BLI_testextensie(name, ".mpg") || + BLI_testextensie(name, ".avi") || // wouldn't be appropriate ;) + BLI_testextensie(name, ".mov") || // disabled, suboptimal decoding speed + BLI_testextensie(name, ".mp4") || // disabled, suboptimal decoding speed + BLI_testextensie(name, ".m4v") || // disabled, suboptimal decoding speed + BLI_testextensie(name, ".tga") || + BLI_testextensie(name, ".png") || + BLI_testextensie(name, ".bmp") || + BLI_testextensie(name, ".jpg") || + BLI_testextensie(name, ".wav") || + BLI_testextensie(name, ".zip") || + BLI_testextensie(name, ".mp3")) + { + return 0; + } - if(QTIME_DEBUG) printf("qt: checking as movie: %s\n", name); + if (QTIME_DEBUG) printf("qt: checking as movie: %s\n", name); pool = [[NSAutoreleasePool alloc] init]; - if([QTMovie canInitWithFile:[NSString stringWithCString:name - encoding:[NSString defaultCStringEncoding]]]) + if ([QTMovie canInitWithFile:[NSString stringWithCString:name + encoding:[NSString defaultCStringEncoding]]]) { [pool drain]; return true; @@ -147,7 +150,7 @@ static ImBuf * nsImageToiBuf(NSImage *sourceImage, int width, int height) uchar *toIBuf = NULL; int x, y, to_i, from_i; NSSize bitmapSize; - NSBitmapImageRep *blBitmapFormatImageRGB,*blBitmapFormatImageRGBA,*bitmapImage=nil; + NSBitmapImageRep *blBitmapFormatImageRGB,*blBitmapFormatImageRGBA, *bitmapImage = nil; NSEnumerator *enumerator; NSImageRep *representation; @@ -162,18 +165,18 @@ static ImBuf * nsImageToiBuf(NSImage *sourceImage, int width, int height) /*Get the bitmap of the image*/ enumerator = [[sourceImage representations] objectEnumerator]; while ((representation = [enumerator nextObject])) { - if ([representation isKindOfClass:[NSBitmapImageRep class]]) { - bitmapImage = (NSBitmapImageRep *)representation; + if ([representation isKindOfClass:[NSBitmapImageRep class]]) { + bitmapImage = (NSBitmapImageRep *)representation; break; - } - } + } + } if (bitmapImage == nil) return NULL; if (([bitmapImage bitsPerPixel] == 32) && (([bitmapImage bitmapFormat] & 0x5) == 0) && ![bitmapImage isPlanar]) { /* Try a fast copy if the image is a meshed RGBA 32bit bitmap*/ - toIBuf = (uchar*)ibuf->rect; - rasterRGB = (uchar*)[bitmapImage bitmapData]; + toIBuf = (uchar *)ibuf->rect; + rasterRGB = (uchar *)[bitmapImage bitmapData]; for (y = 0; y < height; y++) { to_i = (height-y-1)*width; from_i = y*width; @@ -207,7 +210,7 @@ static ImBuf * nsImageToiBuf(NSImage *sourceImage, int width, int height) [bitmapImage draw]; [NSGraphicsContext restoreGraphicsState]; - rasterRGB = (uchar*)[blBitmapFormatImageRGB bitmapData]; + rasterRGB = (uchar *)[blBitmapFormatImageRGB bitmapData]; if (rasterRGB == NULL) { [blBitmapFormatImageRGB release]; return NULL; @@ -228,7 +231,7 @@ static ImBuf * nsImageToiBuf(NSImage *sourceImage, int width, int height) [bitmapImage draw]; [NSGraphicsContext restoreGraphicsState]; - rasterRGBA = (uchar*)[blBitmapFormatImageRGBA bitmapData]; + rasterRGBA = (uchar *)[blBitmapFormatImageRGBA bitmapData]; if (rasterRGBA == NULL) { [blBitmapFormatImageRGB release]; [blBitmapFormatImageRGBA release]; @@ -236,7 +239,7 @@ static ImBuf * nsImageToiBuf(NSImage *sourceImage, int width, int height) } /*Copy the image to ibuf, flipping it vertically*/ - toIBuf = (uchar*)ibuf->rect; + toIBuf = (uchar *)ibuf->rect; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { to_i = (height-y-1)*width + x; @@ -312,7 +315,7 @@ int startquicktime (struct anim *anim) pool = [[NSAutoreleasePool alloc] init]; - [QTMovie enterQTKitOnThread]; + [QTMovie enterQTKitOnThread]; attributes = [NSDictionary dictionaryWithObjectsAndKeys: [NSString stringWithCString:anim->name @@ -382,7 +385,7 @@ int startquicktime (struct anim *anim) anim->curposition = 0; [pool drain]; - + return 0; } @@ -486,7 +489,7 @@ ImBuf *imb_quicktime_decode(unsigned char *mem, int size, int flags) [bitmapImage draw]; [NSGraphicsContext restoreGraphicsState]; - rasterRGB = (uchar*)[blBitmapFormatImageRGB bitmapData]; + rasterRGB = (uchar *)[blBitmapFormatImageRGB bitmapData]; if (rasterRGB == NULL) { [bitmapImage release]; [blBitmapFormatImageRGB release]; @@ -509,7 +512,7 @@ ImBuf *imb_quicktime_decode(unsigned char *mem, int size, int flags) [bitmapImage draw]; [NSGraphicsContext restoreGraphicsState]; - rasterRGBA = (uchar*)[blBitmapFormatImageRGBA bitmapData]; + rasterRGBA = (uchar *)[blBitmapFormatImageRGBA bitmapData]; if (rasterRGBA == NULL) { [bitmapImage release]; [blBitmapFormatImageRGB release]; @@ -519,7 +522,7 @@ ImBuf *imb_quicktime_decode(unsigned char *mem, int size, int flags) } /*Copy the image to ibuf, flipping it vertically*/ - toIBuf = (uchar*)ibuf->rect; + toIBuf = (uchar *)ibuf->rect; for (x = 0; x < bitmapSize.width; x++) { for (y = 0; y < bitmapSize.height; y++) { to_i = (bitmapSize.height-y-1)*bitmapSize.width + x; @@ -543,7 +546,7 @@ ImBuf *imb_quicktime_decode(unsigned char *mem, int size, int flags) if (ENDIAN_ORDER == B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf); /* return successfully */ - return (ibuf); + return (ibuf); } diff --git a/source/blender/quicktime/apple/quicktime_export.c b/source/blender/quicktime/apple/quicktime_export.c index 659fd997c1f..1c4ab5a4b0e 100644 --- a/source/blender/quicktime/apple/quicktime_export.c +++ b/source/blender/quicktime/apple/quicktime_export.c @@ -105,8 +105,8 @@ typedef struct QuicktimeExport { PixMapHandle thePixMap; ImageDescription **anImageDescription; - ImBuf *ibuf; //imagedata for Quicktime's Gworld - ImBuf *ibuf2; //copy of renderdata, to be Y-flipped + ImBuf *ibuf; /* imagedata for Quicktime's Gworld */ + ImBuf *ibuf2; /* copy of renderdata, to be Y-flipped */ } QuicktimeExport; @@ -178,7 +178,7 @@ int quicktime_videocodecType_from_rnatmpvalue(int rnatmpvalue) return qtVideoCodecList[i].codecType; } - return 0; + return 0; } @@ -218,7 +218,7 @@ static OSErr QT_SaveCodecSettingsToScene(RenderData *rd, ReportList *reports) /* retreive codecdata from quicktime in a atomcontainer */ myErr = SCGetSettingsAsAtomContainer(qtdata->theComponent, &myContainer); if (myErr != noErr) { - BKE_reportf(reports, RPT_ERROR, "Quicktime: SCGetSettingsAsAtomContainer failed\n"); + BKE_report(reports, RPT_ERROR, "Quicktime: SCGetSettingsAsAtomContainer failed"); goto bail; } @@ -238,7 +238,7 @@ static OSErr QT_SaveCodecSettingsToScene(RenderData *rd, ReportList *reports) GetCodecInfo(&ci, qtdata->gSpatialSettings.codecType, 0); } else { - BKE_reportf(reports, RPT_ERROR, "Quicktime: QT_SaveCodecSettingsToScene failed\n"); + BKE_report(reports, RPT_ERROR, "Quicktime: QT_SaveCodecSettingsToScene failed"); } QTUnlockContainer(myContainer); @@ -268,7 +268,7 @@ static OSErr QT_GetCodecSettingsFromScene(RenderData *rd, ReportList *reports) if (qcd->cdParms && qcd->cdSize) { myErr = SCSetSettingsFromAtomContainer((GraphicsExportComponent)qtdata->theComponent, (QTAtomContainer)myHandle); if (myErr != noErr) { - BKE_reportf(reports, RPT_ERROR, "Quicktime: SCSetSettingsFromAtomContainer failed\n"); + BKE_report(reports, RPT_ERROR, "Quicktime: SCSetSettingsFromAtomContainer failed"); goto bail; } @@ -278,9 +278,9 @@ static OSErr QT_GetCodecSettingsFromScene(RenderData *rd, ReportList *reports) SCGetInfo(qtdata->theComponent, scTemporalSettingsType, &qtdata->gTemporalSettings); - //Fill the render QuicktimeCodecSettigns struct + /* Fill the render QuicktimeCodecSettigns struct */ rd->qtcodecsettings.codecTemporalQuality = (qtdata->gTemporalSettings.temporalQuality * 100) / codecLosslessQuality; - //Do not override scene frame rate (qtdata->gTemporalSettings.framerate) + /* Do not override scene frame rate (qtdata->gTemporalSettings.framerate) */ rd->qtcodecsettings.keyFrameRate = qtdata->gTemporalSettings.keyFrameRate; rd->qtcodecsettings.codecType = qtdata->gSpatialSettings.codecType; @@ -291,11 +291,11 @@ static OSErr QT_GetCodecSettingsFromScene(RenderData *rd, ReportList *reports) rd->qtcodecsettings.bitRate = qtdata->aDataRateSetting.dataRate; rd->qtcodecsettings.minSpatialQuality = (qtdata->aDataRateSetting.minSpatialQuality * 100) / codecLosslessQuality; rd->qtcodecsettings.minTemporalQuality = (qtdata->aDataRateSetting.minTemporalQuality * 100) / codecLosslessQuality; - //Frame duration is already known (qtdata->aDataRateSetting.frameDuration) + /* Frame duration is already known (qtdata->aDataRateSetting.frameDuration) */ } else { - BKE_reportf(reports, RPT_ERROR, "Quicktime: QT_GetCodecSettingsFromScene failed\n"); + BKE_report(reports, RPT_ERROR, "Quicktime: QT_GetCodecSettingsFromScene failed"); } bail: if (myHandle != NULL) @@ -414,7 +414,7 @@ static void QT_StartAddVideoSamplesToMedia(const Rect *trackFrame, int rectx, in gTemporalSettings = qtdata->gTemporalSettings; if (qtdata->gSpatialSettings.codecType == kH264CodecType) { if (gTemporalSettings.temporalQuality != codecMinQuality) { - BKE_reportf(reports, RPT_WARNING, "Only minimum quality compression supported for QuickTime H.264.\n"); + BKE_report(reports, RPT_WARNING, "Only minimum quality compression supported for Quicktime H.264"); gTemporalSettings.temporalQuality = codecMinQuality; } } @@ -443,18 +443,18 @@ static void QT_DoAddVideoSamplesToMedia(int frame, int *pixels, int rectx, int r Ptr myPtr; - //copy and flip renderdata + /* copy and flip renderdata */ memcpy(qtexport->ibuf2->rect, pixels, 4 * rectx * recty); IMB_flipy(qtexport->ibuf2); - //get pointers to parse bitmapdata + /* get pointers to parse bitmapdata */ myPtr = GetPixBaseAddr(qtexport->thePixMap); imageRect = (**qtexport->thePixMap).bounds; from = (unsigned char *) qtexport->ibuf2->rect; to = (unsigned char *) myPtr; - //parse RGBA bitmap into Quicktime's ARGB GWorld + /* parse RGBA bitmap into Quicktime's ARGB GWorld */ boxsize = rectx * recty; for (index = 0; index < boxsize; index++) { to[0] = from[3]; @@ -564,7 +564,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R /* hack: create an empty file to make FSPathMakeRef() happy */ myFile = open(theFullPath, O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRUSR | S_IWUSR); if (myFile < 0) { - BKE_reportf(reports, RPT_ERROR, "error while creating movie file!\n"); + BKE_report(reports, RPT_ERROR, "Error while creating movie file!"); /* do something? */ } close(myFile); @@ -599,7 +599,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R #endif } else { - //printf("Created QuickTime movie: %s\n", name); + /* printf("Created QuickTime movie: %s\n", name); */ QT_CreateMyVideoTrack(rectx, recty, reports); } @@ -636,7 +636,7 @@ void end_qt(void) DisposeMovie(qtexport->theMovie); - //printf("Finished QuickTime movie.\n"); + /* printf("Finished QuickTime movie.\n"); */ } #ifdef __APPLE__ @@ -684,15 +684,15 @@ static void check_renderbutton_framerate(RenderData *rd, ReportList *reports) err = SCSetInfo(qtdata->theComponent, scTemporalSettingsType, &qtdata->gTemporalSettings); CheckError(err, "SCSetInfo error", reports); - if (qtdata->gTemporalSettings.frameRate == 1571553) { // 23.98 fps + if (qtdata->gTemporalSettings.frameRate == 1571553) { /* 23.98 fps */ qtdata->kVideoTimeScale = 24000; qtdata->duration = 1001; } - else if (qtdata->gTemporalSettings.frameRate == 1964113) { // 29.97 fps + else if (qtdata->gTemporalSettings.frameRate == 1964113) { /* 29.97 fps */ qtdata->kVideoTimeScale = 30000; qtdata->duration = 1001; } - else if (qtdata->gTemporalSettings.frameRate == 3928227) { // 59.94 fps + else if (qtdata->gTemporalSettings.frameRate == 3928227) { /* 59.94 fps */ qtdata->kVideoTimeScale = 60000; qtdata->duration = 1001; } @@ -714,7 +714,7 @@ void quicktime_verify_image_type(RenderData *rd, ImageFormatData *imf) rd->qtcodecsettings.codecSpatialQuality = (codecHighQuality * 100) / codecLosslessQuality; rd->qtcodecsettings.codecTemporalQuality = (codecHighQuality * 100) / codecLosslessQuality; rd->qtcodecsettings.keyFrameRate = 25; - rd->qtcodecsettings.bitRate = 5000000; //5 Mbps + rd->qtcodecsettings.bitRate = 5000000; /* 5 Mbps */ } } } @@ -804,7 +804,7 @@ static int request_qtcodec_settings(bContext *C, wmOperator *op) qtdata->aDataRateSetting.minSpatialQuality = (rd->qtcodecsettings.minSpatialQuality * codecLosslessQuality) / 100; qtdata->aDataRateSetting.minTemporalQuality = (rd->qtcodecsettings.minTemporalQuality * codecLosslessQuality) / 100; - qtdata->aDataRateSetting.frameDuration = rd->frs_sec; + qtdata->aDataRateSetting.frameDuration = rd->frs_sec; err = SCSetInfo(qtdata->theComponent, scTemporalSettingsType, &qtdata->gTemporalSettings); CheckError(err, "SCSetInfo1 error", op->reports); @@ -826,9 +826,9 @@ static int request_qtcodec_settings(bContext *C, wmOperator *op) SCGetInfo(qtdata->theComponent, scTemporalSettingsType, &qtdata->gTemporalSettings); - //Fill the render QuicktimeCodecSettings struct + /* Fill the render QuicktimeCodecSettings struct */ rd->qtcodecsettings.codecTemporalQuality = (qtdata->gTemporalSettings.temporalQuality * 100) / codecLosslessQuality; - //Do not override scene frame rate (qtdata->gTemporalSettings.framerate) + /* Do not override scene frame rate (qtdata->gTemporalSettings.framerate) */ rd->qtcodecsettings.keyFrameRate = qtdata->gTemporalSettings.keyFrameRate; rd->qtcodecsettings.codecType = qtdata->gSpatialSettings.codecType; @@ -839,26 +839,26 @@ static int request_qtcodec_settings(bContext *C, wmOperator *op) rd->qtcodecsettings.bitRate = qtdata->aDataRateSetting.dataRate; rd->qtcodecsettings.minSpatialQuality = (qtdata->aDataRateSetting.minSpatialQuality * 100) / codecLosslessQuality; rd->qtcodecsettings.minTemporalQuality = (qtdata->aDataRateSetting.minTemporalQuality * 100) / codecLosslessQuality; - //Frame duration is already known (qtdata->aDataRateSetting.frameDuration) + /* Frame duration is already known (qtdata->aDataRateSetting.frameDuration) */ QT_SaveCodecSettingsToScene(rd, op->reports); /* framerate jugglin' */ - if (qtdata->gTemporalSettings.frameRate == 1571553) { // 23.98 fps + if (qtdata->gTemporalSettings.frameRate == 1571553) { /* 23.98 fps */ qtdata->kVideoTimeScale = 24000; qtdata->duration = 1001; rd->frs_sec = 24; rd->frs_sec_base = 1.001; } - else if (qtdata->gTemporalSettings.frameRate == 1964113) { // 29.97 fps + else if (qtdata->gTemporalSettings.frameRate == 1964113) { /* 29.97 fps */ qtdata->kVideoTimeScale = 30000; qtdata->duration = 1001; rd->frs_sec = 30; rd->frs_sec_base = 1.001; } - else if (qtdata->gTemporalSettings.frameRate == 3928227) { // 59.94 fps + else if (qtdata->gTemporalSettings.frameRate == 3928227) { /* 59.94 fps */ qtdata->kVideoTimeScale = 60000; qtdata->duration = 1001; @@ -891,8 +891,8 @@ static int ED_operator_setqtcodec(bContext *C) } #if defined(__APPLE__) && defined(GHOST_COCOA) -//Need to set up a Cocoa NSAutoReleasePool to avoid memory leak -//And it must be done in an objC file, so use a GHOST_SystemCocoa.mm function for that +/* Need to set up a Cocoa NSAutoReleasePool to avoid memory leak + * And it must be done in an objC file, so use a GHOST_SystemCocoa.mm function for that */ extern int cocoa_request_qtcodec_settings(bContext *C, wmOperator *op); int fromcocoa_request_qtcodec_settings(bContext *C, wmOperator *op) diff --git a/source/blender/quicktime/quicktime_export.h b/source/blender/quicktime/quicktime_export.h index ed896357c90..cef4cb8c2a6 100644 --- a/source/blender/quicktime/quicktime_export.h +++ b/source/blender/quicktime/quicktime_export.h @@ -164,6 +164,6 @@ enum { }; #endif -#endif //(_WIN32) || (__APPLE__) +#endif /* (_WIN32) || (__APPLE__) */ -#endif // __QUICKTIME_IMP_H__ +#endif /* __QUICKTIME_IMP_H__ */ diff --git a/source/blender/quicktime/quicktime_import.h b/source/blender/quicktime/quicktime_import.h index 19bdbb4814c..8fd016a3d74 100644 --- a/source/blender/quicktime/quicktime_import.h +++ b/source/blender/quicktime/quicktime_import.h @@ -43,37 +43,35 @@ #include "../imbuf/IMB_imbuf_types.h" #ifndef USE_QTKIT -#ifndef __MOVIES__ -#ifdef _WIN32 -#include -#elif defined(__APPLE__) -#define __CARBONSOUND__ -#import -#include -#endif -#endif //__MOVIES__ -#endif //USE_QTKIT +# ifndef __MOVIES__ +# ifdef _WIN32 +# include +# elif defined(__APPLE__) +# define __CARBONSOUND__ +# import +# include +# endif +# endif /* __MOVIES__ */ +#endif /* USE_QTKIT */ #ifdef _WIN32 -#ifndef __FIXMATH__ -#include -#endif /* __FIXMATH__ */ +# ifndef __FIXMATH__ +# include +# endif /* __FIXMATH__ */ #endif /* _WIN32 _ */ - char *get_valid_qtname(const char *name); - -// quicktime movie import functions +/* quicktime movie import functions */ int anim_is_quicktime (const char *name); int startquicktime (struct anim *anim); void free_anim_quicktime (struct anim *anim); ImBuf *qtime_fetchibuf (struct anim *anim, int position); -// quicktime image import functions +/* quicktime image import functions */ int imb_is_a_quicktime (char *name); ImBuf *imb_quicktime_decode(unsigned char *mem, int size, int flags); -#endif // __QUICKTIME_IMPORT_H__ +#endif /* __QUICKTIME_IMPORT_H__ */ diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index 2376aeca55e..1331c287d7c 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -35,6 +35,8 @@ #include "DNA_listBase.h" #include "RNA_types.h" +struct bNode; +struct bNodeTree; struct Object; struct Render; struct RenderEngine; @@ -75,6 +77,8 @@ typedef struct RenderEngineType { void (*view_update)(struct RenderEngine *engine, const struct bContext *context); void (*view_draw)(struct RenderEngine *engine, const struct bContext *context); + void (*update_script_node)(struct RenderEngine *engine, struct bNodeTree *ntree, struct bNode *node); + /* RNA integration */ ExtensionRNA ext; } RenderEngineType; @@ -94,6 +98,8 @@ typedef struct RenderEngine { char *text; int resolution_x, resolution_y; + + struct ReportList *reports; } RenderEngine; RenderEngine *RE_engine_create(RenderEngineType *type); @@ -109,6 +115,7 @@ void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int int RE_engine_test_break(RenderEngine *engine); void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info); void RE_engine_update_progress(RenderEngine *engine, float progress); +void RE_engine_update_memory_stats(RenderEngine *engine, float mem_used, float mem_peak); void RE_engine_report(RenderEngine *engine, int type, const char *msg); int RE_engine_render(struct Render *re, int do_all); diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index b43824d6d5e..984b1a8e651 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -83,7 +83,7 @@ typedef struct RenderLayer { /* copy of RenderData */ char name[RE_MAXNAME]; unsigned int lay, lay_zmask, lay_exclude; - int layflag, passflag, pass_xor; + int layflag, passflag, pass_xor; struct Material *mat_override; struct Group *light_override; @@ -148,6 +148,7 @@ typedef struct RenderStats { double starttime, lastframetime; const char *infostr, *statstr; char scene_name[MAX_ID_NAME - 2]; + float mem_used, mem_peak; } RenderStats; /* *********************** API ******************** */ @@ -225,7 +226,7 @@ void RE_PreviewRender(struct Render *re, struct Main *bmain, struct Scene *scene int RE_ReadRenderResult(struct Scene *scene, struct Scene *scenode); int RE_WriteRenderResult(struct ReportList *reports, RenderResult *rr, const char *filename, int compress); -struct RenderResult *RE_MultilayerConvert(void *exrhandle, int rectx, int recty); +struct RenderResult *RE_MultilayerConvert(void *exrhandle, const char *colorspace, int predivide, int rectx, int recty); extern const float default_envmap_layout[]; int RE_WriteEnvmapResult(struct ReportList *reports, struct Scene *scene, struct EnvMap *env, const char *relpath, const char imtype, float layout[12]); @@ -235,7 +236,7 @@ void RE_MergeFullSample(struct Render *re, struct Main *bmain, struct Scene *sce /* ancient stars function... go away! */ void RE_make_stars(struct Render *re, struct Scene *scenev3d, void (*initfunc)(void), - void (*vertexfunc)(float*), void (*termfunc)(void)); + void (*vertexfunc)(float *), void (*termfunc)(void)); /* display and event callbacks */ void RE_display_init_cb (struct Render *re, void *handle, void (*f)(void *handle, RenderResult *rr)); diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h index c07ed42332f..2a9a1becc42 100644 --- a/source/blender/render/extern/include/RE_render_ext.h +++ b/source/blender/render/extern/include/RE_render_ext.h @@ -39,10 +39,11 @@ /* called by meshtools */ struct View3D; struct Scene; +struct LinkNode; -void RE_make_sticky(struct Scene *scene, struct View3D *v3d); - -/* for radiosity module */ +void RE_make_sticky(struct Scene *scene, struct Object *camera, struct LinkNode *objects); + +/* for radiosity module */ struct RadView; struct RNode; struct Render; diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 26a1b9908b3..10045a8f7e1 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -134,7 +134,7 @@ typedef struct ShadeInput { int har; /* hardness */ /* texture coordinates */ - float lo[3], gl[3], ref[3], orn[3], winco[3], sticky[3], vcol[4]; + float lo[3], gl[3], ref[3], orn[3], winco[3], vcol[4]; float refcol[4], displace[3]; float strandco, tang[3], nmapnorm[3], nmaptang[4], stress, winspeed[4]; float duplilo[3], dupliuv[3]; @@ -150,7 +150,6 @@ typedef struct ShadeInput { float dxno[3], dyno[3], dxview, dyview; float dxlv[3], dylv[3]; float dxwin[3], dywin[3]; - float dxsticky[3], dysticky[3]; float dxrefract[3], dyrefract[3]; float dxstrand, dystrand; @@ -192,12 +191,12 @@ struct MTex; struct ImBuf; /* this one uses nodes */ -int multitex_ext(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, struct TexResult *texres); +int multitex_ext(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres); /* nodes disabled */ -int multitex_ext_safe(struct Tex *tex, float *texvec, struct TexResult *texres); +int multitex_ext_safe(struct Tex *tex, float texvec[3], struct TexResult *texres); /* only for internal node usage */ -int multitex_nodes(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, struct TexResult *texres, - short thread, short which_output, struct ShadeInput *shi, struct MTex *mtex); +int multitex_nodes(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, + const short thread, short which_output, struct ShadeInput *shi, struct MTex *mtex); /* shaded view and bake */ struct Render; diff --git a/source/blender/render/intern/include/envmap.h b/source/blender/render/intern/include/envmap.h index 24138884cd2..d0f346f7402 100644 --- a/source/blender/render/intern/include/envmap.h +++ b/source/blender/render/intern/include/envmap.h @@ -46,7 +46,7 @@ struct Render; struct TexResult; void make_envmaps(struct Render *re); -int envmaptex(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, struct TexResult *texres); +int envmaptex(struct Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres); #endif /* __ENVMAP_H__ */ diff --git a/source/blender/render/intern/include/pointdensity.h b/source/blender/render/intern/include/pointdensity.h index cc8fabda49c..e0c293e2473 100644 --- a/source/blender/render/intern/include/pointdensity.h +++ b/source/blender/render/intern/include/pointdensity.h @@ -43,7 +43,7 @@ struct TexResult; void cache_pointdensity(struct Render *re, struct Tex *tex); void make_pointdensities(struct Render *re); void free_pointdensities(struct Render *re); -int pointdensitytex(struct Tex *tex, float *texvec, struct TexResult *texres); +int pointdensitytex(struct Tex *tex, const float texvec[3], struct TexResult *texres); #endif /* __POINTDENSITY_H__ */ diff --git a/source/blender/render/intern/include/rayobject.h b/source/blender/render/intern/include/rayobject.h index 7752baadff4..07fc7d7a6ed 100644 --- a/source/blender/render/intern/include/rayobject.h +++ b/source/blender/render/intern/include/rayobject.h @@ -104,7 +104,7 @@ RayObject *RE_vlakprimitive_from_vlak(VlakPrimitive *face, struct ObjectInstance void RE_rayobject_merge_bb(RayObject *ob, float *min, float *max); /* initializes an hint for optimizing raycast where it is know that a ray will pass by the given BB often the origin point */ -void RE_rayobject_hint_bb(RayObject *r, struct RayHint *hint, float *min, float *max); +void RE_rayobject_hint_bb(RayObject *r, struct RayHint *hint, float min[3], float max[3]); /* initializes an hint for optimizing raycast where it is know that a ray will be contained inside the given cone*/ /* void RE_rayobject_hint_cone(RayObject *r, struct RayHint *hint, float *); */ diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h index 999fb24ba32..5d61417cbaf 100644 --- a/source/blender/render/intern/include/render_result.h +++ b/source/blender/render/intern/include/render_result.h @@ -57,7 +57,7 @@ struct RenderResult *render_result_new(struct Render *re, struct RenderResult *render_result_new_full_sample(struct Render *re, struct ListBase *lb, struct rcti *partrct, int crop, int savebuffers); -struct RenderResult *render_result_new_from_exr(void *exrhandle, int rectx, int recty); +struct RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace, int predivide, int rectx, int recty); /* Merge */ diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 85dbd9356f4..825fe2ff4d0 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -120,12 +120,15 @@ struct Render /* state settings */ short flag, osa, ok, result_ok; + /* due to performance issues, getting initialized from color management settings once on Render initialization */ + short scene_color_manage; + /* result of rendering */ RenderResult *result; /* if render with single-layer option, other rendered layers are stored here */ RenderResult *pushedresult; /* a list of RenderResults, for fullsample */ - ListBase fullresult; + ListBase fullresult; /* read/write mutex, all internal code that writes to re->result must use a * write lock, all external code must use a read lock. internal code is assumed * to not conflict with writes, so no lock used for that */ @@ -142,8 +145,6 @@ struct Render /* final picture width and height (within disprect) */ int rectx, recty; - /* real maximum amount of xparts/yparts after correction for minimum */ - int xparts, yparts; /* real maximum size of parts after correction for minimum * partx*xparts can be larger than rectx, in that case last part is smaller */ int partx, party; diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h index 0fbbf52e613..30712250440 100644 --- a/source/blender/render/intern/include/rendercore.h +++ b/source/blender/render/intern/include/rendercore.h @@ -62,7 +62,7 @@ typedef struct PixStrMain { /* ------------------------------------------------------------------------- */ -void calc_view_vector(float *view, float x, float y); +void calc_view_vector(float view[3], float x, float y); float mistfactor(float zcor, const float co[3]); /* dist and height, return alpha */ void renderspothalo(struct ShadeInput *shi, float col[4], float alpha); @@ -95,5 +95,4 @@ extern void init_ao_sphere(struct World *wrld); extern void init_render_qmcsampler(Render *re); extern void free_render_qmcsampler(Render *re); -#endif /* RENDER_EXT_H */ - +#endif /* __RENDERCORE_H__ */ diff --git a/source/blender/render/intern/include/renderdatabase.h b/source/blender/render/intern/include/renderdatabase.h index 584e56836fa..5213f14d773 100644 --- a/source/blender/render/intern/include/renderdatabase.h +++ b/source/blender/render/intern/include/renderdatabase.h @@ -55,7 +55,6 @@ struct RadFace; typedef struct VertTableNode { struct VertRen *vert; float *rad; - float *sticky; float *strand; float *tangent; float *stress; @@ -89,7 +88,7 @@ void free_renderdata_vertnodes(struct VertTableNode *vertnodes); void free_renderdata_vlaknodes(struct VlakTableNode *vlaknodes); void project_renderdata(struct Render *re, void (*projectfunc)(const float *, float mat[][4], float *), int do_pano, float xoffs, int do_buckets); -int clip_render_object(float boundbox[][3], float *bounds, float mat[][4]); +int clip_render_object(float boundbox[][3], float bounds[4], float mat[][4]); /* functions are not exported... so wrong names */ @@ -110,7 +109,6 @@ struct ObjectRen *RE_addRenderObject(struct Render *re, struct Object *ob, struc struct ObjectInstanceRen *RE_addRenderInstance(struct Render *re, struct ObjectRen *obr, struct Object *ob, struct Object *par, int index, int psysindex, float mat[][4], int lay); void RE_makeRenderInstances(struct Render *re); -float *RE_vertren_get_sticky(struct ObjectRen *obr, struct VertRen *ver, int verify); float *RE_vertren_get_stress(struct ObjectRen *obr, struct VertRen *ver, int verify); float *RE_vertren_get_rad(struct ObjectRen *obr, struct VertRen *ver, int verify); float *RE_vertren_get_strand(struct ObjectRen *obr, struct VertRen *ver, int verify); diff --git a/source/blender/render/intern/include/shadbuf.h b/source/blender/render/intern/include/shadbuf.h index 5cde8e5106a..7c168baada7 100644 --- a/source/blender/render/intern/include/shadbuf.h +++ b/source/blender/render/intern/include/shadbuf.h @@ -79,19 +79,19 @@ float ISB_getshadow(ShadeInput *shi, ShadBuf *shb); /* buffer samples, allocated in camera buffer and pointed to in lampbuffer nodes */ typedef struct ISBSample { - float zco[3]; /* coordinate in lampview projection */ - short *shadfac; /* initialized zero = full lighted */ - int obi; /* object for face lookup */ - int facenr; /* index in faces list */ + float zco[3]; /* coordinate in lampview projection */ + short *shadfac; /* initialized zero = full lighted */ + int obi; /* object for face lookup */ + int facenr; /* index in faces list */ } ISBSample; /* transparent version of buffer sample */ typedef struct ISBSampleA { - float zco[3]; /* coordinate in lampview projection */ - short *shadfac; /* NULL = full lighted */ - int obi; /* object for face lookup */ - int facenr; /* index in faces list */ - struct ISBSampleA *next; /* in end, we want the first items to align with ISBSample */ + float zco[3]; /* coordinate in lampview projection */ + short *shadfac; /* NULL = full lighted */ + int obi; /* object for face lookup */ + int facenr; /* index in faces list */ + struct ISBSampleA *next; /* in end, we want the first items to align with ISBSample */ } ISBSampleA; /* used for transparent storage only */ diff --git a/source/blender/render/intern/include/shading.h b/source/blender/render/intern/include/shading.h index a8519d8a7fb..4f6e005d742 100644 --- a/source/blender/render/intern/include/shading.h +++ b/source/blender/render/intern/include/shading.h @@ -60,7 +60,7 @@ void shade_material_loop(struct ShadeInput *shi, struct ShadeResult *shr); void shade_input_set_triangle_i(struct ShadeInput *shi, struct ObjectInstanceRen *obi, struct VlakRen *vlr, short i1, short i2, short i3); void shade_input_set_triangle(struct ShadeInput *shi, volatile int obi, volatile int facenr, int normal_flip); void shade_input_copy_triangle(struct ShadeInput *shi, struct ShadeInput *from); -void shade_input_calc_viewco(struct ShadeInput *shi, float x, float y, float z, float view[3], float *dxyview, float *co, float *dxco, float *dyco); +void shade_input_calc_viewco(struct ShadeInput *shi, float x, float y, float z, float view[3], float dxyview[2], float co[3], float dxco[3], float dyco[3]); void shade_input_set_viewco(struct ShadeInput *shi, float x, float y, float sx, float sy, float z); void shade_input_set_uv(struct ShadeInput *shi); void shade_input_set_normals(struct ShadeInput *shi); diff --git a/source/blender/render/intern/include/sunsky.h b/source/blender/render/intern/include/sunsky.h index 74e42109be5..60fa8aa51ba 100644 --- a/source/blender/render/intern/include/sunsky.h +++ b/source/blender/render/intern/include/sunsky.h @@ -43,8 +43,7 @@ typedef struct SunSky { float perez_Y[5], perez_x[5], perez_y[5]; - /* suggested by glome in - * http://projects.blender.org/tracker/?func=detail&atid=127&aid=8063&group_id=9*/ + /* suggested by glome in patch [#8063] */ float horizon_brightness; float spread; float sun_brightness; @@ -69,7 +68,7 @@ typedef struct SunSky { float atm_BetaRM[3]; } SunSky; -void InitSunSky(struct SunSky *sunsky, float turb, float *toSun, float horizon_brightness, +void InitSunSky(struct SunSky *sunsky, float turb, const float toSun[3], float horizon_brightness, float spread, float sun_brightness, float sun_size, float back_scatter, float skyblendfac, short skyblendtype, float sky_exposure, float sky_colorspace); diff --git a/source/blender/render/intern/include/texture.h b/source/blender/render/intern/include/texture.h index e8f171fe383..4b9fa2d2042 100644 --- a/source/blender/render/intern/include/texture.h +++ b/source/blender/render/intern/include/texture.h @@ -76,7 +76,7 @@ void render_realtime_texture(struct ShadeInput *shi, struct Image *ima); /* imagetexture.h */ -int imagewraposa(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], const float dxt[3], const float dyt[3], struct TexResult *texres); +int imagewraposa(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], const float dxt[2], const float dyt[2], struct TexResult *texres); int imagewrap(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], struct TexResult *texres); void image_sample(struct Image *ima, float fx, float fy, float dx, float dy, float result[4]); diff --git a/source/blender/render/intern/include/texture_ocean.h b/source/blender/render/intern/include/texture_ocean.h index 7d4110aadf3..121142aa0b0 100644 --- a/source/blender/render/intern/include/texture_ocean.h +++ b/source/blender/render/intern/include/texture_ocean.h @@ -23,4 +23,9 @@ * ***** END GPL LICENSE BLOCK ***** */ -int ocean_texture(struct Tex *tex, float *texvec, struct TexResult *texres); +#ifndef __TEXTURE_OCEAN_H__ +#define __TEXTURE_OCEAN_H__ + +int ocean_texture(struct Tex *tex, const float texvec[2], struct TexResult *texres); + +#endif /* __TEXTURE_OCEAN_H__ */ diff --git a/source/blender/render/intern/include/volume_precache.h b/source/blender/render/intern/include/volume_precache.h index 8e402bc5418..9aa280d8276 100644 --- a/source/blender/render/intern/include/volume_precache.h +++ b/source/blender/render/intern/include/volume_precache.h @@ -30,8 +30,8 @@ */ -void global_bounds_obi(Render *re, ObjectInstanceRen *obi, float *bbmin, float *bbmax); -int point_inside_volume_objectinstance(Render *re, ObjectInstanceRen *obi, float *co); +void global_bounds_obi(Render *re, ObjectInstanceRen *obi, float bbmin[3], float bbmax[3]); +int point_inside_volume_objectinstance(Render *re, ObjectInstanceRen *obi, const float co[3]); void volume_precache(Render *re); void free_volume_precache(Render *re); diff --git a/source/blender/render/intern/raytrace/bvh.h b/source/blender/render/intern/raytrace/bvh.h index 103c04a590f..47d3a892e84 100644 --- a/source/blender/render/intern/raytrace/bvh.h +++ b/source/blender/render/intern/raytrace/bvh.h @@ -91,7 +91,7 @@ static inline int rayobject_bb_intersect_test(const Isect *isec, const float *_b if (t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) return 0; if (t2x < 0.0f || t2y < 0.0f || t2z < 0.0f) return 0; if (t1x > isec->dist || t1y > isec->dist || t1z > isec->dist) return 0; - RE_RC_COUNT(isec->raycounter->bb.hit); + RE_RC_COUNT(isec->raycounter->bb.hit); return 1; } diff --git a/source/blender/render/intern/raytrace/rayobject.cpp b/source/blender/render/intern/raytrace/rayobject.cpp index 6f14c6153f9..c3babf99d51 100644 --- a/source/blender/render/intern/raytrace/rayobject.cpp +++ b/source/blender/render/intern/raytrace/rayobject.cpp @@ -467,7 +467,7 @@ float RE_rayobject_cost(RayObject *r) /* Bounding Boxes */ -void RE_rayobject_merge_bb(RayObject *r, float *min, float *max) +void RE_rayobject_merge_bb(RayObject *r, float min[3], float max[3]) { if (RE_rayobject_isRayFace(r)) { RayFace *face = (RayFace *) RE_rayobject_align(r); diff --git a/source/blender/render/intern/raytrace/rayobject_blibvh.cpp b/source/blender/render/intern/raytrace/rayobject_blibvh.cpp index 2d642a0a0d8..198577f61c6 100644 --- a/source/blender/render/intern/raytrace/rayobject_blibvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_blibvh.cpp @@ -79,7 +79,7 @@ typedef struct BVHObject { RayObject *RE_rayobject_blibvh_create(int size) { BVHObject *obj = (BVHObject *)MEM_callocN(sizeof(BVHObject), "BVHObject"); - assert(RE_rayobject_isAligned(obj)); /* RayObject API assumes real data to be 4-byte aligned */ + assert(RE_rayobject_isAligned(obj)); /* RayObject API assumes real data to be 4-byte aligned */ obj->rayobj.api = &bvh_api; obj->bvh = BLI_bvhtree_new(size, 0.0, 4, 6); @@ -137,7 +137,7 @@ static void RE_rayobject_blibvh_add(RayObject *o, RayObject *ob) DO_MIN(min_max, obj->bb[0]); DO_MAX(min_max + 3, obj->bb[1]); - BLI_bvhtree_insert(obj->bvh, obj->next_leaf - obj->leafs, min_max, 2); + BLI_bvhtree_insert(obj->bvh, obj->next_leaf - obj->leafs, min_max, 2); *(obj->next_leaf++) = ob; } diff --git a/source/blender/render/intern/raytrace/rayobject_instance.cpp b/source/blender/render/intern/raytrace/rayobject_instance.cpp index c3e761ae069..f797f7a4311 100644 --- a/source/blender/render/intern/raytrace/rayobject_instance.cpp +++ b/source/blender/render/intern/raytrace/rayobject_instance.cpp @@ -59,7 +59,7 @@ static RayObjectAPI instance_api = RE_rayobject_instance_free, RE_rayobject_instance_bb, RE_rayobject_instance_cost, - RE_rayobject_instance_hint_bb + RE_rayobject_instance_hint_bb }; typedef struct InstanceRayObject { diff --git a/source/blender/render/intern/raytrace/rayobject_internal.h b/source/blender/render/intern/raytrace/rayobject_internal.h index 3f768e5adcb..92ac39909a8 100644 --- a/source/blender/render/intern/raytrace/rayobject_internal.h +++ b/source/blender/render/intern/raytrace/rayobject_internal.h @@ -50,7 +50,7 @@ typedef int (*RE_rayobjectcontrol_test_break_callback)(void *data); typedef struct RayObjectControl { void *data; - RE_rayobjectcontrol_test_break_callback test_break; + RE_rayobjectcontrol_test_break_callback test_break; } RayObjectControl; /* Returns true if for some reason a heavy processing function should stop @@ -124,9 +124,9 @@ typedef int (*RE_rayobject_raycast_callback)(RayObject *, struct Isect *); typedef void (*RE_rayobject_add_callback)(RayObject *raytree, RayObject *rayobject); typedef void (*RE_rayobject_done_callback)(RayObject *); typedef void (*RE_rayobject_free_callback)(RayObject *); -typedef void (*RE_rayobject_merge_bb_callback)(RayObject *, float *min, float *max); +typedef void (*RE_rayobject_merge_bb_callback)(RayObject *, float min[3], float max[3]); typedef float (*RE_rayobject_cost_callback)(RayObject *); -typedef void (*RE_rayobject_hint_bb_callback)(RayObject *, struct RayHint *, float *, float *); +typedef void (*RE_rayobject_hint_bb_callback)(RayObject *, struct RayHint *, float min[3], float max[3]); typedef struct RayObjectAPI { RE_rayobject_raycast_callback raycast; @@ -154,5 +154,4 @@ int RE_rayobject_intersect(RayObject *r, struct Isect *i); } #endif -#endif - +#endif /* __RAYOBJECT_INTERNAL_H__ */ diff --git a/source/blender/render/intern/raytrace/rayobject_octree.cpp b/source/blender/render/intern/raytrace/rayobject_octree.cpp index 5ae716ac942..77e9dc9d8fd 100644 --- a/source/blender/render/intern/raytrace/rayobject_octree.cpp +++ b/source/blender/render/intern/raytrace/rayobject_octree.cpp @@ -382,8 +382,12 @@ static void d2dda(Octree *oc, short b1, short b2, short c1, short c2, char *ocfa while (TRUE) { - if (x < 0 || y < 0 || x >= oc->ocres || y >= oc->ocres) ; - else ocface[oc->ocres * x + y] = 1; + if (x < 0 || y < 0 || x >= oc->ocres || y >= oc->ocres) { + /* pass*/ + } + else { + ocface[oc->ocres * x + y] = 1; + } labdao = labda; if (labdax == labday) { diff --git a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp index 16d70297a34..33ce3bd33d5 100644 --- a/source/blender/render/intern/raytrace/rayobject_qbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_qbvh.cpp @@ -68,7 +68,7 @@ void bvh_done(QBVHTree *obj) //Build and optimize the tree //TODO do this in 1 pass (half memory usage during building) - VBVHNode *root = BuildBinaryVBVH(arena1, &obj->rayobj.control).transform(obj->builder); + VBVHNode *root = BuildBinaryVBVH(arena1, &obj->rayobj.control).transform(obj->builder); if (RE_rayobjectcontrol_test_break(&obj->rayobj.control)) { BLI_memarena_free(arena1); diff --git a/source/blender/render/intern/raytrace/rayobject_raycounter.cpp b/source/blender/render/intern/raytrace/rayobject_raycounter.cpp index 7d86b6cf8cb..5335bf50cbc 100644 --- a/source/blender/render/intern/raytrace/rayobject_raycounter.cpp +++ b/source/blender/render/intern/raytrace/rayobject_raycounter.cpp @@ -43,10 +43,10 @@ void RE_RC_INFO(RayCounter *info) printf("\n"); printf("BB tests: %llu\n", info->bb.test ); printf("BB hits: %llu\n", info->bb.hit ); - printf("\n"); + printf("\n"); printf("SIMD BB tests: %llu\n", info->simd_bb.test ); printf("SIMD BB hits: %llu\n", info->simd_bb.hit ); - printf("\n"); + printf("\n"); printf("Primitives tests: %llu\n", info->faces.test ); printf("Primitives hits: %llu\n", info->faces.hit ); printf("------------------------------------\n"); diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp index ddc84408e26..bae65c492f4 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp @@ -77,7 +77,7 @@ RTBuilder *rtbuild_create(int size) for (int i = 0; i < 3; i++) { builder->sorted_begin[i] = (RTBuilder::Object **)MEM_mallocN(sizeof(RTBuilder::Object *) * size, "RTBuilder.sorted_objects"); builder->sorted_end[i] = builder->sorted_begin[i]; - } + } return builder; @@ -185,7 +185,7 @@ RTBuilder *rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp) return tmp; } -void rtbuild_calc_bb(RTBuilder *b) +static void rtbuild_calc_bb(RTBuilder *b) { if (b->bb[0] == 1.0e30f) { for (RTBuilder::Object **index = b->sorted_begin[0]; index != b->sorted_end[0]; index++) @@ -193,7 +193,7 @@ void rtbuild_calc_bb(RTBuilder *b) } } -void rtbuild_merge_bb(RTBuilder *b, float *min, float *max) +void rtbuild_merge_bb(RTBuilder *b, float min[3], float max[3]) { rtbuild_calc_bb(b); DO_MIN(b->bb, min); @@ -224,7 +224,7 @@ int rtbuild_mean_split(RTBuilder *b, int nchilds, int axis) Mleafs_per_child = s / nchilds; mleafs_per_child = Mleafs_per_child / nchilds; - //split min leafs per child + //split min leafs per child b->child_offset[0] = 0; for (i = 1; i <= nchilds; i++) b->child_offset[i] = mleafs_per_child; @@ -295,7 +295,7 @@ int rtbuild_median_split(RTBuilder *b, float *separators, int nchilds, int axis) return rtbuild_mean_split(b, nchilds, axis); return nchilds; - } + } } int rtbuild_median_split_largest_axis(RTBuilder *b, int nchilds) @@ -324,7 +324,7 @@ struct SweepCost { /* Object Surface Area Heuristic splitter */ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) { - int size = rtbuild_size(b); + int size = rtbuild_size(b); assert(nchilds == 2); assert(size > 1); int baxis = -1, boffset = 0; @@ -348,12 +348,12 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) sweep[i].cost = obj[i]->cost; } else { - sweep[i].bb[0] = MIN2(obj[i]->bb[0], sweep[i + 1].bb[0]); - sweep[i].bb[1] = MIN2(obj[i]->bb[1], sweep[i + 1].bb[1]); - sweep[i].bb[2] = MIN2(obj[i]->bb[2], sweep[i + 1].bb[2]); - sweep[i].bb[3] = MAX2(obj[i]->bb[3], sweep[i + 1].bb[3]); - sweep[i].bb[4] = MAX2(obj[i]->bb[4], sweep[i + 1].bb[4]); - sweep[i].bb[5] = MAX2(obj[i]->bb[5], sweep[i + 1].bb[5]); + sweep[i].bb[0] = min_ff(obj[i]->bb[0], sweep[i + 1].bb[0]); + sweep[i].bb[1] = min_ff(obj[i]->bb[1], sweep[i + 1].bb[1]); + sweep[i].bb[2] = min_ff(obj[i]->bb[2], sweep[i + 1].bb[2]); + sweep[i].bb[3] = max_ff(obj[i]->bb[3], sweep[i + 1].bb[3]); + sweep[i].bb[4] = max_ff(obj[i]->bb[4], sweep[i + 1].bb[4]); + sweep[i].bb[5] = max_ff(obj[i]->bb[5], sweep[i + 1].bb[5]); sweep[i].cost = obj[i]->cost + sweep[i + 1].cost; } // right_cost += obj[i]->cost; @@ -375,8 +375,8 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) // not using log seems to have no impact on raytracing perf, but // makes tree construction quicker, left out for now to test (brecht) - // left_side = bb_area(sweep_left.bb, sweep_left.bb+3)*(sweep_left.cost+logf((float)i)); - // right_side= bb_area(sweep[i].bb, sweep[i].bb+3)*(sweep[i].cost+logf((float)size-i)); + // left_side = bb_area(sweep_left.bb, sweep_left.bb + 3) * (sweep_left.cost + logf((float)i)); + // right_side = bb_area(sweep[i].bb, sweep[i].bb + 3) * (sweep[i].cost + logf((float)size - i)); left_side = bb_area(sweep_left.bb, sweep_left.bb + 3) * (sweep_left.cost); right_side = bb_area(sweep[i].bb, sweep[i].bb + 3) * (sweep[i].cost); hcost = left_side + right_side; @@ -429,7 +429,7 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) for (int i = 0; i < 3; i++) std::stable_partition(b->sorted_begin[i], b->sorted_end[i], selected_node); - return nchilds; + return nchilds; } /* @@ -457,26 +457,26 @@ static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis) /* * Bounding Box utils */ -float bb_volume(float *min, float *max) +float bb_volume(const float min[3], const float max[3]) { return (max[0] - min[0]) * (max[1] - min[1]) * (max[2] - min[2]); } -float bb_area(float *min, float *max) +float bb_area(const float min[3], const float max[3]) { float sub[3], a; sub[0] = max[0] - min[0]; sub[1] = max[1] - min[1]; sub[2] = max[2] - min[2]; - a = (sub[0] * sub[1] + sub[0] * sub[2] + sub[1] * sub[2]) * 2; + a = (sub[0] * sub[1] + sub[0] * sub[2] + sub[1] * sub[2]) * 2.0f; /* used to have an assert() here on negative results * however, in this case its likely some overflow or ffast math error. * so just return 0.0f instead. */ return a < 0.0f ? 0.0f : a; } -int bb_largest_axis(float *min, float *max) +int bb_largest_axis(const float min[3], const float max[3]) { float sub[3]; @@ -494,10 +494,12 @@ int bb_largest_axis(float *min, float *max) return 1; else return 2; - } + } } -int bb_fits_inside(float *outer_min, float *outer_max, float *inner_min, float *inner_max) +/* only returns 0 if merging inner and outerbox would create a box larger than outer box */ +int bb_fits_inside(const float outer_min[3], const float outer_max[3], + const float inner_min[3], const float inner_max[3]) { int i; for (i = 0; i < 3; i++) @@ -506,5 +508,5 @@ int bb_fits_inside(float *outer_min, float *outer_max, float *inner_min, float * for (i = 0; i < 3; i++) if (outer_max[i] < inner_max[i]) return 0; - return 1; + return 1; } diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.h b/source/blender/render/intern/raytrace/rayobject_rtbuild.h index 22e3d009c07..9e296da144b 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.h +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.h @@ -86,7 +86,7 @@ RTBuilder *rtbuild_create(int size); void rtbuild_free(RTBuilder *b); void rtbuild_add(RTBuilder *b, RayObject *o); void rtbuild_done(RTBuilder *b, RayObjectControl *c); -void rtbuild_merge_bb(RTBuilder *b, float *min, float *max); +void rtbuild_merge_bb(RTBuilder *b, float min[3], float max[3]); int rtbuild_size(RTBuilder *b); RayObject *rtbuild_get_primitive(RTBuilder *b, int offset); @@ -109,13 +109,14 @@ int rtbuild_median_split_largest_axis(RTBuilder *b, int nchilds); /* bb utils */ -float bb_area(float *min, float *max); -float bb_volume(float *min, float *max); -int bb_largest_axis(float *min, float *max); -int bb_fits_inside(float *outer_min, float *outer_max, float *inner_min, float *inner_max); /* only returns 0 if merging inner and outerbox would create a box larger than outer box */ +float bb_area(const float min[3], const float max[3]); +float bb_volume(const float min[3], const float max[3]); +int bb_largest_axis(const float min[3], const float max[3]); +int bb_fits_inside(const float outer_min[3], const float outer_max[3], + const float inner_min[3], const float inner_max[3]); #ifdef __cplusplus } #endif -#endif +#endif /* __RAYOBJECT_RTBUILD_H__ */ diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index 9e7075438cb..d03bdb74407 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -112,7 +112,7 @@ void bvh_done(VBVHTree *obj) //Finds the optimal packing of this tree using a given cost model //TODO this uses quite a lot of memory, find ways to reduce memory usage during building - OVBVHNode *root = BuildBinaryVBVH(arena2).transform(obj->builder); + OVBVHNode *root = BuildBinaryVBVH(arena2).transform(obj->builder); VBVH_optimalPackSIMD(PackCost()).transform(root); obj->root = Reorganize_VBVH(arena1).transform(root); @@ -125,7 +125,7 @@ void bvh_done(VBVHTree *obj) obj->builder = NULL; obj->node_arena = arena1; - obj->cost = 1.0; + obj->cost = 1.0; } template @@ -152,7 +152,8 @@ void bvh_hint_bb(Tree *tree, LCTSHint *hint, float *UNUSED(min), float *UNUSED(m } } -void bfree(VBVHTree *tree) +#if 0 /* UNUSED */ +static void bfree(VBVHTree *tree) { if (tot_pushup + tot_pushdown + tot_hints + tot_moves) { if (G.debug & G_DEBUG) { @@ -169,6 +170,7 @@ void bfree(VBVHTree *tree) } bvh_free(tree); } +#endif /* the cast to pointer function is needed to workarround gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11407 */ template diff --git a/source/blender/render/intern/raytrace/reorganize.h b/source/blender/render/intern/raytrace/reorganize.h index a9ed71a76bc..9d9711eee56 100644 --- a/source/blender/render/intern/raytrace/reorganize.h +++ b/source/blender/render/intern/raytrace/reorganize.h @@ -75,7 +75,7 @@ void reorganize_find_fittest_parent(Node *tree, Node *node, std::pairbb, parent->bb + 3); cost = std::min(cost, std::make_pair(pcost, parent) ); for (Node *child = parent->child; child; child = child->sibling) - q.push(child); + q.push(child); } } } @@ -140,7 +140,7 @@ void remove_useless(Node *node, Node **new_node) (*prev)->sibling = next; prev = &((*prev)->sibling); } - } + } } if (node->child) { if (RE_rayobject_isAligned(node->child) && node->child->sibling == 0) @@ -181,7 +181,7 @@ void pushup(Node *parent) *prev = child; prev = &(*prev)->sibling; child = *prev; - } + } } for (Node *child = parent->child; RE_rayobject_isAligned(child) && child; child = child->sibling) @@ -205,13 +205,13 @@ void pushup_simd(Node *parent) n += (cn - 1); append_sibling(child, child->child); child = child->sibling; - *prev = child; + *prev = child; } else { *prev = child; prev = &(*prev)->sibling; child = *prev; - } + } } for (Node *child = parent->child; RE_rayobject_isAligned(child) && child; child = child->sibling) @@ -320,7 +320,7 @@ struct OVBVHNode { /* * Reorganize the node based on calculated cut costs - */ + */ int best_cutsize; void set_cut(int cutsize, OVBVHNode ***cut) { @@ -357,7 +357,7 @@ struct OVBVHNode { //Optimize new childs for (OVBVHNode *child = this->child; child && RE_rayobject_isAligned(child); child = child->sibling) child->optimize(); - } + } } }; @@ -431,7 +431,7 @@ struct VBVH_optimalPackSIMD { current_size -= bt[j][current_size]; } } - } + } } }; @@ -493,6 +493,6 @@ struct VBVH_optimalPackSIMD { if ((G.debug & G_DEBUG) && first) printf("expected cost = %f (%d)\n", node->cut_cost[0], node->best_cutsize); node->optimize(); } - return node; - } + return node; + } }; diff --git a/source/blender/render/intern/raytrace/svbvh.h b/source/blender/render/intern/raytrace/svbvh.h index a58094e5021..6ec75ebb527 100644 --- a/source/blender/render/intern/raytrace/svbvh.h +++ b/source/blender/render/intern/raytrace/svbvh.h @@ -29,12 +29,11 @@ * \ingroup render */ - -#ifdef __SSE__ - #ifndef __SVBVH_H__ #define __SVBVH_H__ +#ifdef __SSE__ + #include "bvh.h" #include "BLI_memarena.h" #include "BKE_global.h" @@ -94,10 +93,10 @@ static int svbvh_bb_intersect_test(const Isect *isec, const float *_bb) RE_RC_COUNT(isec->raycounter->bb.test); if (t1x > t2y || t2x < t1y || t1x > t2z || t2x < t1z || t1y > t2z || t2y < t1z) return 0; - if (t2x < 0.0 || t2y < 0.0 || t2z < 0.0) return 0; + if (t2x < 0.0f || t2y < 0.0f || t2z < 0.0f) return 0; if (t1x > isec->dist || t1y > isec->dist || t1z > isec->dist) return 0; - RE_RC_COUNT(isec->raycounter->bb.hit); + RE_RC_COUNT(isec->raycounter->bb.hit); return 1; } @@ -166,16 +165,16 @@ inline void bvh_node_merge_bb(SVBVHNode *node, float min[3], float ma for (i = 0; i + 4 <= node->nchilds; i += 4) { float *res = node->child_bb + 6 * i; for (int j = 0; j < 3; j++) { - min[j] = minf(res[4 * j + 0], - minf(res[4 * j + 1], - minf(res[4 * j + 2], - minf(res[4 * j + 3], min[j])))); + min[j] = min_ff(res[4 * j + 0], + min_ff(res[4 * j + 1], + min_ff(res[4 * j + 2], + min_ff(res[4 * j + 3], min[j])))); } for (int j = 0; j < 3; j++) { - max[j] = maxf(res[4 * (j + 3) + 0], - maxf(res[4 * (j + 3) + 1], - maxf(res[4 * (j + 3) + 2], - maxf(res[4 * (j + 3) + 3], max[j])))); + max[j] = max_ff(res[4 * (j + 3) + 0], + max_ff(res[4 * (j + 3) + 1], + max_ff(res[4 * (j + 3) + 2], + max_ff(res[4 * (j + 3) + 3], max[j])))); } } @@ -231,7 +230,7 @@ struct Reorganize_SVBVH { return node; } - void copy_bb(float *bb, const float *old_bb) + void copy_bb(float bb[6], const float old_bb[6]) { std::copy(old_bb, old_bb + 6, bb); } @@ -282,7 +281,7 @@ struct Reorganize_SVBVH { useless_bb += alloc_childs - nchilds; while (alloc_childs > nchilds) { - const static float def_bb[6] = { FLT_MAX, FLT_MAX, FLT_MAX, FLT_MIN, FLT_MIN, FLT_MIN }; + const static float def_bb[6] = {FLT_MAX, FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX}; alloc_childs--; node->child[alloc_childs] = NULL; copy_bb(node->child_bb + alloc_childs * 6, def_bb); @@ -308,10 +307,9 @@ struct Reorganize_SVBVH { prepare_for_simd(node); return node; - } + } }; -#endif - -#endif //__SSE__ +#endif /* __SSE__ */ +#endif /* __SVBVH_H__ */ diff --git a/source/blender/render/intern/raytrace/vbvh.h b/source/blender/render/intern/raytrace/vbvh.h index ec671f95c76..9755bf89668 100644 --- a/source/blender/render/intern/raytrace/vbvh.h +++ b/source/blender/render/intern/raytrace/vbvh.h @@ -233,6 +233,6 @@ struct Reorganize_VBVH { *child_ptr = 0; return node; - } + } }; #endif diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 51e5b30a31c..e305f434ebb 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -41,6 +41,7 @@ #include "BLI_rand.h" #include "BLI_memarena.h" #include "BLI_ghash.h" +#include "BLI_linklist.h" #include "DNA_armature_types.h" #include "DNA_camera_types.h" @@ -123,6 +124,9 @@ /* or for checking vertex normal flips */ #define FLT_EPSILON10 1.19209290e-06F +/* could enable at some point but for now there are far too many conversions */ +#pragma GCC diagnostic ignored "-Wdouble-promotion" + /* ------------------------------------------------------------------------- */ /* Stuff for stars. This sits here because it uses gl-things. Part of @@ -155,7 +159,7 @@ static HaloRen *initstar(Render *re, ObjectRen *obr, const float vec[3], float h */ void RE_make_stars(Render *re, Scene *scenev3d, void (*initfunc)(void), - void (*vertexfunc)(float*), void (*termfunc)(void)) + void (*vertexfunc)(float*), void (*termfunc)(void)) { extern unsigned char hash[512]; ObjectRen *obr= NULL; @@ -226,7 +230,7 @@ void RE_make_stars(Render *re, Scene *scenev3d, void (*initfunc)(void), hlfrand = 2.0 * dblrand; if (initfunc) { - initfunc(); + initfunc(); } if (re) /* add render object for stars */ @@ -363,7 +367,7 @@ static void split_v_renderfaces(ObjectRen *obr, int startvlak, int UNUSED(startv if (v==0) { vlr->v1 = RE_vertren_copy(obr, vlr->v1); - } + } } } } @@ -445,7 +449,7 @@ static void calc_edge_stress(Render *UNUSED(re), ObjectRen *obr, Mesh *me) } /* gets tangent from tface or orco */ -static void calc_tangent_vector(ObjectRen *obr, VertexTangent **vtangents, MemArena *arena, VlakRen *vlr, int do_nmap_tangent, int do_tangent) +static void calc_tangent_vector(ObjectRen *obr, VlakRen *vlr, int do_tangent) { MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); VertRen *v1=vlr->v1, *v2=vlr->v2, *v3=vlr->v3, *v4=vlr->v4; @@ -480,12 +484,6 @@ static void calc_tangent_vector(ObjectRen *obr, VertexTangent **vtangents, MemAr add_v3_v3(tav, tang); } - if (do_nmap_tangent) { - sum_or_add_vertex_tangent(arena, &vtangents[v1->index], tang, uv1); - sum_or_add_vertex_tangent(arena, &vtangents[v2->index], tang, uv2); - sum_or_add_vertex_tangent(arena, &vtangents[v3->index], tang, uv3); - } - if (v4) { tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, vlr->n, tang); @@ -497,12 +495,6 @@ static void calc_tangent_vector(ObjectRen *obr, VertexTangent **vtangents, MemAr tav= RE_vertren_get_tangent(obr, v4, 1); add_v3_v3(tav, tang); } - - if (do_nmap_tangent) { - sum_or_add_vertex_tangent(arena, &vtangents[v1->index], tang, uv1); - sum_or_add_vertex_tangent(arena, &vtangents[v3->index], tang, uv3); - sum_or_add_vertex_tangent(arena, &vtangents[v4->index], tang, uv4); - } } } @@ -567,8 +559,14 @@ static void GetNormal(const SMikkTSpaceContext * pContext, float fNorm[], const //assert(vert_index>=0 && vert_index<4); SRenderMeshToTangent * pMesh = (SRenderMeshToTangent *) pContext->m_pUserData; VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num); - const float *n= (&vlr->v1)[vert_index]->n; - copy_v3_v3(fNorm, n); + + if (vlr->flag & ME_SMOOTH) { + const float *n = (&vlr->v1)[vert_index]->n; + copy_v3_v3(fNorm, n); + } + else { + negate_v3_v3(fNorm, vlr->n); + } } static void SetTSpace(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int face_num, const int iVert) { @@ -584,17 +582,8 @@ static void SetTSpace(const SMikkTSpaceContext * pContext, const float fvTangent static void calc_vertexnormals(Render *UNUSED(re), ObjectRen *obr, int do_tangent, int do_nmap_tangent) { - MemArena *arena= NULL; - VertexTangent **vtangents= NULL; int a; - if (do_nmap_tangent) { - arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "nmap tangent arena"); - BLI_memarena_use_calloc(arena); - - vtangents= MEM_callocN(sizeof(VertexTangent*)*obr->totvert, "VertexTangent"); - } - /* clear all vertex normals */ for (a=0; atotvert; a++) { VertRen *ver= RE_findOrAddVert(obr, a); @@ -612,10 +601,10 @@ static void calc_vertexnormals(Render *UNUSED(re), ObjectRen *obr, int do_tangen accumulate_vertex_normals(vlr->v1->n, vlr->v2->n, vlr->v3->n, n4, vlr->n, vlr->v1->co, vlr->v2->co, vlr->v3->co, c4); } - if (do_nmap_tangent || do_tangent) { + if (do_tangent) { /* tangents still need to be calculated for flat faces too */ /* weighting removed, they are not vertexnormals */ - calc_tangent_vector(obr, vtangents, arena, vlr, do_nmap_tangent, do_tangent); + calc_tangent_vector(obr, vlr, do_tangent); } } @@ -629,32 +618,6 @@ static void calc_vertexnormals(Render *UNUSED(re), ObjectRen *obr, int do_tangen if (is_zero_v3(vlr->v3->n)) copy_v3_v3(vlr->v3->n, vlr->n); if (vlr->v4 && is_zero_v3(vlr->v4->n)) copy_v3_v3(vlr->v4->n, vlr->n); } - - if (do_nmap_tangent) { - VertRen *v1=vlr->v1, *v2=vlr->v2, *v3=vlr->v3, *v4=vlr->v4; - MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); - - if (tface) { - int k=0; - float *vtang, *ftang= RE_vlakren_get_nmap_tangent(obr, vlr, 1); - - vtang= find_vertex_tangent(vtangents[v1->index], tface->uv[0]); - copy_v3_v3(ftang, vtang); - normalize_v3(ftang); - vtang= find_vertex_tangent(vtangents[v2->index], tface->uv[1]); - copy_v3_v3(ftang+4, vtang); - normalize_v3(ftang+4); - vtang= find_vertex_tangent(vtangents[v3->index], tface->uv[2]); - copy_v3_v3(ftang+8, vtang); - normalize_v3(ftang+8); - if (v4) { - vtang= find_vertex_tangent(vtangents[v4->index], tface->uv[3]); - copy_v3_v3(ftang+12, vtang); - normalize_v3(ftang+12); - } - for (k=0; k<4; k++) ftang[4*k+3]=1; - } - } } /* normalize vertex normals */ @@ -674,6 +637,7 @@ static void calc_vertexnormals(Render *UNUSED(re), ObjectRen *obr, int do_tangen } } + /* normal mapping tangent with mikktspace */ if (do_nmap_tangent != FALSE) { SRenderMeshToTangent mesh2tangent; SMikkTSpaceContext sContext; @@ -695,11 +659,6 @@ static void calc_vertexnormals(Render *UNUSED(re), ObjectRen *obr, int do_tangen genTangSpaceDefault(&sContext); } - - if (arena) - BLI_memarena_free(arena); - if (vtangents) - MEM_freeN(vtangents); } /* ------------------------------------------------------------------------- */ @@ -881,7 +840,7 @@ static void autosmooth(Render *UNUSED(re), ObjectRen *obr, float mat[][4], int d else normal_tri_v3(vlr->n, vlr->v3->co, vlr->v2->co, vlr->v1->co); } - } + } } /* ------------------------------------------------------------------------- */ @@ -1569,9 +1528,12 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem int i, a, k, max_k=0, totpart, do_simplify = FALSE, do_surfacecache = FALSE, use_duplimat = FALSE; int totchild=0; int seed, path_nbr=0, orco1=0, num; - int totface, *origindex = 0; + int totface; char **uv_name=0; + const int *index_mf_to_mpoly = NULL; + const int *index_mp_to_orig = NULL; + /* 1. check that everything is ok & updated */ if (psys==NULL) return 0; @@ -1612,7 +1574,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem psys->flag |= PSYS_DRAWING; - rng= rng_new(psys->seed); + rng= BLI_rng_new(psys->seed); totpart=psys->totpart; @@ -1741,9 +1703,13 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem do_surfacecache = TRUE; totface= psmd->dm->getNumTessFaces(psmd->dm); - origindex= psmd->dm->getTessFaceDataArray(psmd->dm, CD_ORIGINDEX); + index_mf_to_mpoly = psmd->dm->getTessFaceDataArray(psmd->dm, CD_ORIGINDEX); + index_mp_to_orig = psmd->dm->getPolyDataArray(psmd->dm, CD_ORIGINDEX); + if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { + index_mf_to_mpoly = index_mp_to_orig = NULL; + } for (a=0; atotbound= MAX2(strandbuf->totbound, (origindex)? origindex[a]: a); + strandbuf->totbound = max_ii(strandbuf->totbound, (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a): a); strandbuf->totbound++; strandbuf->bound= MEM_callocN(sizeof(StrandBound)*strandbuf->totbound, "StrandBound"); @@ -1762,7 +1728,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem /* 3. start creating renderable things */ for (a=0, pa=pars; aflag & PARS_UNEXIST) continue; @@ -1854,7 +1820,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem do_simplify = psys_render_simplify_params(psys, cpa, simplify); if (strandbuf) { - int orignum= (origindex)? origindex[cpa->num]: cpa->num; + int orignum = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, cpa->num) : cpa->num; if (orignum > sbound - strandbuf->bound) { sbound= strandbuf->bound + orignum; @@ -1938,7 +1904,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem copy_v3_v3(state.vel, (cache+k)->vel); } else - continue; + continue; if (k > 0) curlen += len_v3v3((cache+k-1)->co, (cache+k)->co); @@ -2098,7 +2064,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem if (states) MEM_freeN(states); - rng_free(rng); + BLI_rng_free(rng); psys->flag &= ~PSYS_DRAWING; @@ -2260,14 +2226,6 @@ static void displace_render_vert(Render *re, ObjectRen *obr, ShadeInput *shi, Ve if ((texco & TEXCO_ORCO) && (vr->orco)) { copy_v3_v3(shi->lo, vr->orco); } - if (texco & TEXCO_STICKY) { - float *sticky= RE_vertren_get_sticky(obr, vr, 0); - if (sticky) { - shi->sticky[0]= sticky[0]; - shi->sticky[1]= sticky[1]; - shi->sticky[2]= 0.0f; - } - } if (texco & TEXCO_GLOB) { copy_v3_v3(shi->gl, shi->co); mul_m4_v3(re->viewinv, shi->gl); @@ -2374,7 +2332,7 @@ static void displace_render_face(Render *re, ObjectRen *obr, VlakRen *vlr, float /* Recalculate the face normal - if flipped before, flip now */ if (vlr->v4) { normal_quad_v3(vlr->n, vlr->v4->co, vlr->v3->co, vlr->v2->co, vlr->v1->co); - } + } else { normal_tri_v3(vlr->n, vlr->v3->co, vlr->v2->co, vlr->v1->co); } @@ -2543,7 +2501,7 @@ static int dl_surf_to_renderdata(ObjectRen *obr, DispList *dl, Material **matar, copy_v3_v3(v1->co, data); data += 3; if (orco) { v1->orco= orco; orco+= 3; orcoret++; - } + } mul_m4_v3(mat, v1->co); for (v = 1; v < sizev; v++) { @@ -2551,7 +2509,7 @@ static int dl_surf_to_renderdata(ObjectRen *obr, DispList *dl, Material **matar, copy_v3_v3(ver->co, data); data += 3; if (orco) { ver->orco= orco; orco+= 3; orcoret++; - } + } mul_m4_v3(mat, ver->co); } /* if V-cyclic, add extra vertices at end of the row */ @@ -2561,8 +2519,8 @@ static int dl_surf_to_renderdata(ObjectRen *obr, DispList *dl, Material **matar, if (orco) { ver->orco= orco; orco+=3; orcoret++; //orcobase + 3*(u*sizev + 0); } - } - } + } + } /* Done before next loop to get corner vert */ if (dl->flag & DL_CYCL_U) nsizev++; @@ -2615,7 +2573,7 @@ static int dl_surf_to_renderdata(ObjectRen *obr, DispList *dl, Material **matar, p1++; p2++; p3++; p4++; } - } + } /* fix normals for U resp. V cyclic faces */ sizeu--; sizev--; /* dec size for face array */ if (dl->flag & DL_CYCL_V) { @@ -2936,8 +2894,7 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset) vlr->v2= RE_findOrAddVert(obr, startvert+index[1]); vlr->v3= RE_findOrAddVert(obr, startvert+index[2]); vlr->v4= NULL; - - if (area_tri_v3(vlr->v3->co, vlr->v2->co, vlr->v1->co)>FLT_EPSILON) { + if (area_tri_v3(vlr->v3->co, vlr->v2->co, vlr->v1->co)>FLT_EPSILON10) { normal_tri_v3(tmp, vlr->v3->co, vlr->v2->co, vlr->v1->co); add_v3_v3(n, tmp); } @@ -3249,7 +3206,6 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) VlakRen *vlr; //, *vlr1; VertRen *ver; Material *ma; - MSticky *ms = NULL; DerivedMesh *dm; CustomDataMask mask; float xn, yn, zn, imat[3][3], mat[4][4]; //nor[3], @@ -3282,11 +3238,11 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) /* normalmaps, test if tangents needed, separated from shading */ if (ma->mode_l & MA_TANGENT_V) { need_tangent= 1; - if (me->mtface==NULL) + if (me->mtpoly==NULL) need_orco= 1; } if (ma->mode_l & MA_NORMAP_TANG) { - if (me->mtface==NULL) { + if (me->mtpoly==NULL) { need_orco= 1; need_tangent= 1; } @@ -3297,7 +3253,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) if (re->flag & R_NEED_TANGENT) { /* exception for tangent space baking */ - if (me->mtface==NULL) { + if (me->mtpoly==NULL) { need_orco= 1; need_tangent= 1; } @@ -3334,8 +3290,6 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) if (do_autosmooth && me->totvert==totvert && me->totface==dm->getNumTessFaces(dm)) use_original_normals= TRUE; - ms = (totvert==me->totvert)?me->msticky:NULL; - ma= give_render_material(re, ob, 1); @@ -3354,16 +3308,11 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) normalize_v3(ver->n); negate_v3(ver->n); } - + if (orco) { ver->orco= orco; orco+=3; } - if (ms) { - float *sticky= RE_vertren_get_sticky(obr, ver, 1); - copy_v2_v2(sticky, ms->co); - ms++; - } } if (!timeoffset) { @@ -3631,22 +3580,22 @@ static void area_lamp_vectors(LampRen *lar) /* corner vectors */ lar->area[0][0]= lar->co[0] - xsize*lar->mat[0][0] - ysize*lar->mat[1][0]; lar->area[0][1]= lar->co[1] - xsize*lar->mat[0][1] - ysize*lar->mat[1][1]; - lar->area[0][2]= lar->co[2] - xsize*lar->mat[0][2] - ysize*lar->mat[1][2]; + lar->area[0][2]= lar->co[2] - xsize*lar->mat[0][2] - ysize*lar->mat[1][2]; /* corner vectors */ lar->area[1][0]= lar->co[0] - xsize*lar->mat[0][0] + ysize*lar->mat[1][0]; lar->area[1][1]= lar->co[1] - xsize*lar->mat[0][1] + ysize*lar->mat[1][1]; - lar->area[1][2]= lar->co[2] - xsize*lar->mat[0][2] + ysize*lar->mat[1][2]; + lar->area[1][2]= lar->co[2] - xsize*lar->mat[0][2] + ysize*lar->mat[1][2]; /* corner vectors */ lar->area[2][0]= lar->co[0] + xsize*lar->mat[0][0] + ysize*lar->mat[1][0]; lar->area[2][1]= lar->co[1] + xsize*lar->mat[0][1] + ysize*lar->mat[1][1]; - lar->area[2][2]= lar->co[2] + xsize*lar->mat[0][2] + ysize*lar->mat[1][2]; + lar->area[2][2]= lar->co[2] + xsize*lar->mat[0][2] + ysize*lar->mat[1][2]; /* corner vectors */ lar->area[3][0]= lar->co[0] + xsize*lar->mat[0][0] - ysize*lar->mat[1][0]; lar->area[3][1]= lar->co[1] + xsize*lar->mat[0][1] - ysize*lar->mat[1][1]; - lar->area[3][2]= lar->co[2] + xsize*lar->mat[0][2] - ysize*lar->mat[1][2]; + lar->area[3][2]= lar->co[2] + xsize*lar->mat[0][2] - ysize*lar->mat[1][2]; /* only for correction button size, matrix size works on energy */ lar->areasize= lar->dist*lar->dist/(4.0f*xsize*ysize); } @@ -3944,6 +3893,9 @@ static void add_lightgroup(Render *re, Group *group, int exclusive) /* note that 'exclusive' will remove it from the global list */ for (go= group->gobject.first; go; go= go->next) { go->lampren= NULL; + + if (go->ob->restrictflag & OB_RESTRICT_RENDER) + continue; if (go->ob->lay & re->lay) { if (go->ob && go->ob->type==OB_LAMP) { @@ -4118,8 +4070,12 @@ static void set_fullsample_trace_flag(Render *re, ObjectRen *obr) vlr->flag |= R_FULL_OSA; } else if (trace) { - if (mode & MA_SHLESS); - else if (vlr->mat->material_type == MA_TYPE_VOLUME); + if (mode & MA_SHLESS) { + /* pass */ + } + else if (vlr->mat->material_type == MA_TYPE_VOLUME) { + /* pass */ + } else if ((mode & MA_RAYMIRROR) || ((mode & MA_TRANSP) && (mode & MA_RAYTRANSP))) { /* for blurry reflect/refract, better to take more samples * inside the raytrace than as OSA samples */ @@ -4720,10 +4676,12 @@ void RE_Database_Free(Render *re) static int allow_render_object(Render *re, Object *ob, int nolamps, int onlyselected, Object *actob) { /* override not showing object when duplis are used with particles */ - if (ob->transflag & OB_DUPLIPARTS) - ; /* let particle system(s) handle showing vs. not showing */ - else if ((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES)) + if (ob->transflag & OB_DUPLIPARTS) { + /* pass */ /* let particle system(s) handle showing vs. not showing */ + } + else if ((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES)) { return 0; + } /* don't add non-basic meta objects, ends up having renderobjects with no geometry */ if (ob->type == OB_MBALL && ob!=BKE_mball_basis_find(re->scene, ob)) @@ -4907,7 +4865,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp /* create list of duplis generated by this object, particle * system need to have render settings set for dupli particles */ dupli_render_particle_set(re, ob, timeoffset, 0, 1); - lb= object_duplilist(re->scene, ob); + lb= object_duplilist(re->scene, ob, TRUE); dupli_render_particle_set(re, ob, timeoffset, 0, 0); for (dob= lb->first; dob; dob= dob->next) { @@ -4941,7 +4899,8 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp * a dupligroup that has already been created before */ if (dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, 0))) { mult_m4_m4m4(mat, re->viewmat, dob->mat); - obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, 0, mat, obd->lay); + /* ob = particle system, use that layer */ + obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, 0, mat, ob->lay); /* fill in instance variables for texturing */ set_dupli_tex_mat(re, obi, dob); @@ -5242,11 +5201,11 @@ static void speedvector_project(Render *re, float zco[2], const float co[3], con /* size of 1 pixel mapped to viewplane coords */ float psize; - psize = BLI_RCT_SIZE_X(&re->viewplane) / (float)re->winx; + psize = BLI_rctf_size_x(&re->viewplane) / (float)re->winx; /* x angle of a pixel */ pixelphix = atan(psize / re->clipsta); - psize = BLI_RCT_SIZE_Y(&re->viewplane) / (float)re->winy; + psize = BLI_rctf_size_y(&re->viewplane) / (float)re->winy; /* y angle of a pixel */ pixelphiy = atan(psize / re->clipsta); } @@ -5342,7 +5301,7 @@ static float *calculate_strandsurface_speedvectors(Render *re, ObjectInstanceRen calculate_speedvector(vec, 1, winsq, winroot, mesh->co[a], ho, winspeed[a]); } - return (float*)winspeed; + return (float *)winspeed; } return NULL; @@ -5600,7 +5559,7 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned re->i.infostr= "Calculating next frame vectors"; database_fromscene_vectors(re, sce, lay, +1); - } + } /* copy away vertex info */ copy_dbase_object_vectors(re, &newtable); @@ -5814,76 +5773,3 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay, if (re->r.mode & R_SHADOW) make_occ_tree(re); } - -/* ------------------------------------------------------------------------- */ -/* Sticky texture coords */ -/* ------------------------------------------------------------------------- */ - -void RE_make_sticky(Scene *scene, View3D *v3d) -{ - Object *ob; - Base *base; - MVert *mvert; - Mesh *me; - MSticky *ms; - Render *re; - float ho[4], mat[4][4]; - int a; - Object *camera= NULL; - - if (v3d==NULL) { - printf("Need a 3d view to make sticky\n"); - return; - } - - if (v3d) camera= V3D_CAMERA_LOCAL(v3d); - if (camera == NULL) camera= scene->camera; - - if (camera==NULL) { - printf("Need camera to make sticky\n"); - return; - } - if (scene->obedit) { - printf("Unable to make sticky in Edit Mode\n"); - return; - } - - re= RE_NewRender("_make sticky_"); - RE_InitState(re, NULL, &scene->r, NULL, scene->r.xsch, scene->r.ysch, NULL); - - /* use renderdata and camera to set viewplane */ - RE_SetCamera(re, camera); - - /* and set view matrix */ - normalize_m4(camera->obmat); - invert_m4_m4(mat, camera->obmat); - RE_SetView(re, mat); - - for (base= FIRSTBASE; base; base= base->next) { - if (TESTBASELIB(v3d, base)) { - if (base->object->type==OB_MESH) { - ob= base->object; - - me= ob->data; - mvert= me->mvert; - if (me->msticky) - CustomData_free_layer_active(&me->vdata, CD_MSTICKY, me->totvert); - me->msticky= CustomData_add_layer(&me->vdata, CD_MSTICKY, - CD_CALLOC, NULL, me->totvert); - - BKE_object_where_is_calc(scene, ob); - mult_m4_m4m4(mat, re->viewmat, ob->obmat); - - ms= me->msticky; - for (a=0; atotvert; a++, ms++, mvert++) { - copy_v3_v3(ho, mvert->co); - mul_m4_v3(mat, ho); - projectverto(ho, re->winmat, ho); - ms->co[0]= ho[0]/ho[3]; - ms->co[1]= ho[1]/ho[3]; - } - } - } - } -} - diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index 03eb21dfa23..28f70211a9c 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -76,7 +76,7 @@ static void envmap_split_ima(EnvMap *env, ImBuf *ibuf) BLI_lock_thread(LOCK_IMAGE); if (env->cube[1] == NULL) { - BKE_free_envmapdata(env); + BKE_free_envmapdata(env); dx = ibuf->y; dx /= 2; @@ -120,7 +120,7 @@ static void envmap_split_ima(EnvMap *env, ImBuf *ibuf) IMB_float_from_rect(env->cube[1]); } } - } + } BLI_unlock_thread(LOCK_IMAGE); } @@ -148,12 +148,14 @@ static Render *envmap_render_copy(Render *re, EnvMap *env) envre->r.mode &= ~(R_BORDER | R_PANORAMA | R_ORTHO | R_MBLUR); envre->r.layers.first = envre->r.layers.last = NULL; envre->r.filtertype = 0; - envre->r.xparts = envre->r.yparts = 2; + envre->r.tilex = envre->r.xsch / 2; + envre->r.tiley = envre->r.ysch / 2; envre->r.size = 100; envre->r.yasp = envre->r.xasp = 1; RE_InitState(envre, NULL, &envre->r, NULL, cuberes, cuberes, NULL); envre->scene = re->scene; /* unsure about this... */ + envre->scene_color_manage = re->scene_color_manage; envre->lay = re->lay; /* view stuff in env render */ @@ -215,7 +217,7 @@ static void envmap_transmatrix(float mat[][4], int part) eul[0] = eul[1] = eul[2] = 0.0; if (part == 0) { /* neg z */ - ; + /* pass */ } else if (part == 1) { /* pos z */ eul[0] = M_PI; @@ -575,7 +577,7 @@ void make_envmaps(Render *re) re->display_init(re->dih, re->result); re->display_clear(re->dch, re->result); // re->flag |= R_REDRAW_PRV; - } + } /* restore */ re->r.mode |= trace; @@ -642,31 +644,31 @@ static int envcube_isect(EnvMap *env, const float vec[3], float answ[2]) /* ------------------------------------------------------------------------- */ -static void set_dxtdyt(float *dxts, float *dyts, float *dxt, float *dyt, int face) +static void set_dxtdyt(float r_dxt[3], float r_dyt[3], const float dxt[3], const float dyt[3], int face) { if (face == 2 || face == 4) { - dxts[0] = dxt[0]; - dyts[0] = dyt[0]; - dxts[1] = dxt[2]; - dyts[1] = dyt[2]; + r_dxt[0] = dxt[0]; + r_dyt[0] = dyt[0]; + r_dxt[1] = dxt[2]; + r_dyt[1] = dyt[2]; } else if (face == 3 || face == 5) { - dxts[0] = dxt[1]; - dxts[1] = dxt[2]; - dyts[0] = dyt[1]; - dyts[1] = dyt[2]; + r_dxt[0] = dxt[1]; + r_dxt[1] = dxt[2]; + r_dyt[0] = dyt[1]; + r_dyt[1] = dyt[2]; } else { - dxts[0] = dxt[0]; - dyts[0] = dyt[0]; - dxts[1] = dxt[1]; - dyts[1] = dyt[1]; + r_dxt[0] = dxt[0]; + r_dyt[0] = dyt[0]; + r_dxt[1] = dxt[1]; + r_dyt[1] = dyt[1]; } } /* ------------------------------------------------------------------------- */ -int envmaptex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres) +int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres) { extern Render R; /* only in this call */ /* texvec should be the already reflected normal */ diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 636b3205b23..4ec19fa729f 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -64,7 +64,7 @@ static RenderEngineType internal_render_type = { NULL, NULL, "BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, {NULL, NULL, NULL} }; @@ -73,7 +73,7 @@ static RenderEngineType internal_render_type = { static RenderEngineType internal_game_type = { NULL, NULL, "BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME, - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, {NULL, NULL, NULL} }; @@ -138,7 +138,7 @@ void RE_engine_free(RenderEngine *engine) { #ifdef WITH_PYTHON if (engine->py_instance) { - BPY_DECREF(engine->py_instance); + BPY_DECREF_RNA_INVALIDATE(engine->py_instance); } #endif @@ -290,9 +290,24 @@ void RE_engine_update_progress(RenderEngine *engine, float progress) } } +void RE_engine_update_memory_stats(RenderEngine *engine, float mem_used, float mem_peak) +{ + Render *re = engine->re; + + if (re) { + re->i.mem_used = mem_used; + re->i.mem_peak = mem_peak; + } +} + void RE_engine_report(RenderEngine *engine, int type, const char *msg) { - BKE_report(engine->re->reports, type, msg); + Render *re = engine->re; + + if (re) + BKE_report(engine->re->reports, type, msg); + else if(engine->reports) + BKE_report(engine->reports, type, msg); } /* Render */ diff --git a/source/blender/render/intern/source/gammaCorrectionTables.c b/source/blender/render/intern/source/gammaCorrectionTables.c index 64925e16ae2..8efdf472232 100644 --- a/source/blender/render/intern/source/gammaCorrectionTables.c +++ b/source/blender/render/intern/source/gammaCorrectionTables.c @@ -38,7 +38,7 @@ /* result remain identical (ton) */ /* gamma is only used here for correcting adding colors or alpha */ -#define RE_DEFAULT_GAMMA 2.0 +// #define RE_DEFAULT_GAMMA 2.0 // UNUSED /* This 400 is sort of based on the number of intensity levels needed for */ /* the typical dynamic range of a medium, in this case CRTs. (Foley) */ @@ -107,13 +107,13 @@ void makeGammaTables(float gamma) color_step = 1.0 / RE_GAMMA_TABLE_SIZE; inv_color_step = (float) RE_GAMMA_TABLE_SIZE; - /* We could squeeze out the two range tables to gain some memory. */ + /* We could squeeze out the two range tables to gain some memory. */ for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) { - color_domain_table[i] = i * color_step; + color_domain_table[i] = i * color_step; gamma_range_table[i] = pow(color_domain_table[i], - valid_gamma); + valid_gamma); inv_gamma_range_table[i] = pow(color_domain_table[i], - valid_inv_gamma); + valid_inv_gamma); } /* The end of the table should match 1.0 carefully. In order to avoid */ diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index 7f0484c8ee6..db1454fd82f 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -102,7 +102,7 @@ static void ibuf_get_color(float col[4], struct ImBuf *ibuf, int x, int y) col[1] = ((float)rect[1])*(1.0f/255.0f); col[2] = ((float)rect[2])*(1.0f/255.0f); col[3] = ((float)rect[3])*(1.0f/255.0f); - } + } } int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResult *texres) @@ -150,8 +150,13 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul fx-= xs; fy-= ys; - if ( (tex->flag & TEX_CHECKER_ODD)==0) { - if ((xs+ys) & 1);else return retval; + if ( (tex->flag & TEX_CHECKER_ODD) == 0) { + if ((xs + ys) & 1) { + /* pass */ + } + else { + return retval; + } } if ( (tex->flag & TEX_CHECKER_EVEN)==0) { if ((xs+ys) & 1) return retval; @@ -204,7 +209,7 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul if (tex->imaflag & TEX_USEALPHA) { if ((tex->imaflag & TEX_CALCALPHA) == 0) { texres->talpha = TRUE; - } + } } /* interpolate */ @@ -396,8 +401,8 @@ static float square_rctf(rctf *rf) { float x, y; - x = BLI_RCT_SIZE_X(rf); - y = BLI_RCT_SIZE_Y(rf); + x = BLI_rctf_size_x(rf); + y = BLI_rctf_size_y(rf); return x * y; } @@ -405,7 +410,7 @@ static float clipx_rctf(rctf *rf, float x1, float x2) { float size; - size = BLI_RCT_SIZE_X(rf); + size = BLI_rctf_size_x(rf); if (rf->xminxmin = x1; @@ -417,8 +422,8 @@ static float clipx_rctf(rctf *rf, float x1, float x2) rf->xmin = rf->xmax; return 0.0; } - else if (size!=0.0f) { - return BLI_RCT_SIZE_X(rf) / size; + else if (size != 0.0f) { + return BLI_rctf_size_x(rf) / size; } return 1.0; } @@ -427,7 +432,7 @@ static float clipy_rctf(rctf *rf, float y1, float y2) { float size; - size = BLI_RCT_SIZE_Y(rf); + size = BLI_rctf_size_y(rf); if (rf->yminymin = y1; @@ -441,7 +446,7 @@ static float clipy_rctf(rctf *rf, float y1, float y2) return 0.0; } else if (size != 0.0f) { - return BLI_RCT_SIZE_Y(rf) / size; + return BLI_rctf_size_y(rf) / size; } return 1.0; @@ -474,7 +479,9 @@ static void boxsampleclip(struct ImBuf *ibuf, rctf *rf, TexResult *texres) muly= 1.0; - if (starty==endy); + if (starty==endy) { + /* pass */ + } else { if (y==starty) muly= 1.0f-(rf->ymin - y); if (y==endy) muly= (rf->ymax - y); @@ -686,7 +693,7 @@ static int ibuf_get_color_clip(float col[4], ImBuf *ibuf, int x, int y, int extf } } else { - char* rect = (char*)(ibuf->rect + x + y*ibuf->x); + char *rect = (char *)(ibuf->rect + x + y*ibuf->x); col[0] = rect[0]*(1.f/255.f); col[1] = rect[1]*(1.f/255.f); col[2] = rect[2]*(1.f/255.f); @@ -757,39 +764,39 @@ static void area_sample(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata /* table of (exp(ar) - exp(a)) / (1 - exp(a)) for r in range [0, 1] and a = -2 * used instead of actual gaussian, otherwise at high texture magnifications circular artifacts are visible */ #define EWA_MAXIDX 255 -static float EWA_WTS[EWA_MAXIDX + 1] = -{ 1.f, 0.990965f, 0.982f, 0.973105f, 0.96428f, 0.955524f, 0.946836f, 0.938216f, 0.929664f, - 0.921178f, 0.912759f, 0.904405f, 0.896117f, 0.887893f, 0.879734f, 0.871638f, 0.863605f, - 0.855636f, 0.847728f, 0.839883f, 0.832098f, 0.824375f, 0.816712f, 0.809108f, 0.801564f, - 0.794079f, 0.786653f, 0.779284f, 0.771974f, 0.76472f, 0.757523f, 0.750382f, 0.743297f, - 0.736267f, 0.729292f, 0.722372f, 0.715505f, 0.708693f, 0.701933f, 0.695227f, 0.688572f, - 0.68197f, 0.67542f, 0.66892f, 0.662471f, 0.656073f, 0.649725f, 0.643426f, 0.637176f, - 0.630976f, 0.624824f, 0.618719f, 0.612663f, 0.606654f, 0.600691f, 0.594776f, 0.588906f, - 0.583083f, 0.577305f, 0.571572f, 0.565883f, 0.56024f, 0.55464f, 0.549084f, 0.543572f, - 0.538102f, 0.532676f, 0.527291f, 0.521949f, 0.516649f, 0.511389f, 0.506171f, 0.500994f, - 0.495857f, 0.490761f, 0.485704f, 0.480687f, 0.475709f, 0.470769f, 0.465869f, 0.461006f, - 0.456182f, 0.451395f, 0.446646f, 0.441934f, 0.437258f, 0.432619f, 0.428017f, 0.42345f, - 0.418919f, 0.414424f, 0.409963f, 0.405538f, 0.401147f, 0.39679f, 0.392467f, 0.388178f, - 0.383923f, 0.379701f, 0.375511f, 0.371355f, 0.367231f, 0.363139f, 0.359079f, 0.355051f, - 0.351055f, 0.347089f, 0.343155f, 0.339251f, 0.335378f, 0.331535f, 0.327722f, 0.323939f, - 0.320186f, 0.316461f, 0.312766f, 0.3091f, 0.305462f, 0.301853f, 0.298272f, 0.294719f, - 0.291194f, 0.287696f, 0.284226f, 0.280782f, 0.277366f, 0.273976f, 0.270613f, 0.267276f, - 0.263965f, 0.26068f, 0.257421f, 0.254187f, 0.250979f, 0.247795f, 0.244636f, 0.241502f, - 0.238393f, 0.235308f, 0.232246f, 0.229209f, 0.226196f, 0.223206f, 0.220239f, 0.217296f, - 0.214375f, 0.211478f, 0.208603f, 0.20575f, 0.20292f, 0.200112f, 0.197326f, 0.194562f, - 0.191819f, 0.189097f, 0.186397f, 0.183718f, 0.18106f, 0.178423f, 0.175806f, 0.17321f, - 0.170634f, 0.168078f, 0.165542f, 0.163026f, 0.16053f, 0.158053f, 0.155595f, 0.153157f, - 0.150738f, 0.148337f, 0.145955f, 0.143592f, 0.141248f, 0.138921f, 0.136613f, 0.134323f, - 0.132051f, 0.129797f, 0.12756f, 0.125341f, 0.123139f, 0.120954f, 0.118786f, 0.116635f, - 0.114501f, 0.112384f, 0.110283f, 0.108199f, 0.106131f, 0.104079f, 0.102043f, 0.100023f, - 0.0980186f, 0.09603f, 0.094057f, 0.0920994f, 0.0901571f, 0.08823f, 0.0863179f, 0.0844208f, - 0.0825384f, 0.0806708f, 0.0788178f, 0.0769792f, 0.0751551f, 0.0733451f, 0.0715493f, 0.0697676f, - 0.0679997f, 0.0662457f, 0.0645054f, 0.0627786f, 0.0610654f, 0.0593655f, 0.0576789f, 0.0560055f, - 0.0543452f, 0.0526979f, 0.0510634f, 0.0494416f, 0.0478326f, 0.0462361f, 0.0446521f, 0.0430805f, - 0.0415211f, 0.039974f, 0.0384389f, 0.0369158f, 0.0354046f, 0.0339052f, 0.0324175f, 0.0309415f, - 0.029477f, 0.0280239f, 0.0265822f, 0.0251517f, 0.0237324f, 0.0223242f, 0.020927f, 0.0195408f, - 0.0181653f, 0.0168006f, 0.0154466f, 0.0141031f, 0.0127701f, 0.0114476f, 0.0101354f, 0.00883339f, - 0.00754159f, 0.00625989f, 0.00498819f, 0.00372644f, 0.00247454f, 0.00123242f, 0.f +static float EWA_WTS[EWA_MAXIDX + 1] = { + 1.f, 0.990965f, 0.982f, 0.973105f, 0.96428f, 0.955524f, 0.946836f, 0.938216f, 0.929664f, + 0.921178f, 0.912759f, 0.904405f, 0.896117f, 0.887893f, 0.879734f, 0.871638f, 0.863605f, + 0.855636f, 0.847728f, 0.839883f, 0.832098f, 0.824375f, 0.816712f, 0.809108f, 0.801564f, + 0.794079f, 0.786653f, 0.779284f, 0.771974f, 0.76472f, 0.757523f, 0.750382f, 0.743297f, + 0.736267f, 0.729292f, 0.722372f, 0.715505f, 0.708693f, 0.701933f, 0.695227f, 0.688572f, + 0.68197f, 0.67542f, 0.66892f, 0.662471f, 0.656073f, 0.649725f, 0.643426f, 0.637176f, + 0.630976f, 0.624824f, 0.618719f, 0.612663f, 0.606654f, 0.600691f, 0.594776f, 0.588906f, + 0.583083f, 0.577305f, 0.571572f, 0.565883f, 0.56024f, 0.55464f, 0.549084f, 0.543572f, + 0.538102f, 0.532676f, 0.527291f, 0.521949f, 0.516649f, 0.511389f, 0.506171f, 0.500994f, + 0.495857f, 0.490761f, 0.485704f, 0.480687f, 0.475709f, 0.470769f, 0.465869f, 0.461006f, + 0.456182f, 0.451395f, 0.446646f, 0.441934f, 0.437258f, 0.432619f, 0.428017f, 0.42345f, + 0.418919f, 0.414424f, 0.409963f, 0.405538f, 0.401147f, 0.39679f, 0.392467f, 0.388178f, + 0.383923f, 0.379701f, 0.375511f, 0.371355f, 0.367231f, 0.363139f, 0.359079f, 0.355051f, + 0.351055f, 0.347089f, 0.343155f, 0.339251f, 0.335378f, 0.331535f, 0.327722f, 0.323939f, + 0.320186f, 0.316461f, 0.312766f, 0.3091f, 0.305462f, 0.301853f, 0.298272f, 0.294719f, + 0.291194f, 0.287696f, 0.284226f, 0.280782f, 0.277366f, 0.273976f, 0.270613f, 0.267276f, + 0.263965f, 0.26068f, 0.257421f, 0.254187f, 0.250979f, 0.247795f, 0.244636f, 0.241502f, + 0.238393f, 0.235308f, 0.232246f, 0.229209f, 0.226196f, 0.223206f, 0.220239f, 0.217296f, + 0.214375f, 0.211478f, 0.208603f, 0.20575f, 0.20292f, 0.200112f, 0.197326f, 0.194562f, + 0.191819f, 0.189097f, 0.186397f, 0.183718f, 0.18106f, 0.178423f, 0.175806f, 0.17321f, + 0.170634f, 0.168078f, 0.165542f, 0.163026f, 0.16053f, 0.158053f, 0.155595f, 0.153157f, + 0.150738f, 0.148337f, 0.145955f, 0.143592f, 0.141248f, 0.138921f, 0.136613f, 0.134323f, + 0.132051f, 0.129797f, 0.12756f, 0.125341f, 0.123139f, 0.120954f, 0.118786f, 0.116635f, + 0.114501f, 0.112384f, 0.110283f, 0.108199f, 0.106131f, 0.104079f, 0.102043f, 0.100023f, + 0.0980186f, 0.09603f, 0.094057f, 0.0920994f, 0.0901571f, 0.08823f, 0.0863179f, 0.0844208f, + 0.0825384f, 0.0806708f, 0.0788178f, 0.0769792f, 0.0751551f, 0.0733451f, 0.0715493f, 0.0697676f, + 0.0679997f, 0.0662457f, 0.0645054f, 0.0627786f, 0.0610654f, 0.0593655f, 0.0576789f, 0.0560055f, + 0.0543452f, 0.0526979f, 0.0510634f, 0.0494416f, 0.0478326f, 0.0462361f, 0.0446521f, 0.0430805f, + 0.0415211f, 0.039974f, 0.0384389f, 0.0369158f, 0.0354046f, 0.0339052f, 0.0324175f, 0.0309415f, + 0.029477f, 0.0280239f, 0.0265822f, 0.0251517f, 0.0237324f, 0.0223242f, 0.020927f, 0.0195408f, + 0.0181653f, 0.0168006f, 0.0154466f, 0.0141031f, 0.0127701f, 0.0114476f, 0.0101354f, 0.00883339f, + 0.00754159f, 0.00625989f, 0.00498819f, 0.00372644f, 0.00247454f, 0.00123242f, 0.f }; /* test if a float value is 'nan' @@ -982,7 +989,7 @@ static void alpha_clip_aniso(ImBuf *ibuf, float minx, float miny, float maxx, fl alphaclip = clipx_rctf(&rf, 0.0, (float)(ibuf->x)); alphaclip *= clipy_rctf(&rf, 0.0, (float)(ibuf->y)); - alphaclip = maxf(alphaclip, 0.0f); + alphaclip = max_ff(alphaclip, 0.0f); if (alphaclip!=1.0f) { /* premul it all */ @@ -1004,7 +1011,7 @@ static void image_mipmap_test(Tex *tex, ImBuf *ibuf) if (ibuf->userflags & IB_MIPMAP_INVALID) { IMB_remakemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP); ibuf->userflags &= ~IB_MIPMAP_INVALID; - } + } BLI_unlock_thread(LOCK_IMAGE); } if (ibuf->mipmap[0] == NULL) { @@ -1018,7 +1025,7 @@ static void image_mipmap_test(Tex *tex, ImBuf *ibuf) } -static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], float dxt[3], float dyt[3], TexResult *texres) +static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], float dxt[2], float dyt[2], TexResult *texres) { TexResult texr; float fx, fy, minx, maxx, miny, maxy; @@ -1054,7 +1061,9 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) return retval; - ima->flag |= IMA_USED_FOR_RENDER; + if (ima) { + ima->flag |= IMA_USED_FOR_RENDER; + } /* mipmap test */ image_mipmap_test(tex, ibuf); @@ -1238,8 +1247,8 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex float fProbes; a *= ff; b *= ff; - a = maxf(a, 1.0f); - b = maxf(b, 1.0f); + a = max_ff(a, 1.0f); + b = max_ff(b, 1.0f); fProbes = 2.f*(a / b) - 1.f; AFD.iProbes = (int)floorf(fProbes + 0.5f); AFD.iProbes = MIN2(AFD.iProbes, tex->afmax); @@ -1255,7 +1264,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex if (ecc > (float)tex->afmax) b = a / (float)tex->afmax; b *= ff; } - maxd = maxf(b, 1e-8f); + maxd = max_ff(b, 1e-8f); levf = ((float)M_LOG2E) * logf(maxd); curmap = 0; @@ -1340,8 +1349,8 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex imp2radangle(A, B, C, F, &a, &b, &th, &ecc); a *= ff; b *= ff; - a = maxf(a, 1.0f); - b = maxf(b, 1.0f); + a = max_ff(a, 1.0f); + b = max_ff(b, 1.0f); fProbes = 2.f*(a / b) - 1.f; /* no limit to number of Probes here */ AFD.iProbes = (int)floorf(fProbes + 0.5f); @@ -1410,17 +1419,17 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex } -int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const float DXT[3], const float DYT[3], TexResult *texres) +int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const float DXT[2], const float DYT[2], TexResult *texres) { TexResult texr; - float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[3], dyt[3]; + float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[2], dyt[2]; float maxd, pixsize, val1, val2, val3; int curmap, retval, imaprepeat, imapextend; /* TXF: since dxt/dyt might be modified here and since they might be needed after imagewraposa() call, * make a local copy here so that original vecs remain untouched */ - copy_v3_v3(dxt, DXT); - copy_v3_v3(dyt, DYT); + copy_v2_v2(dxt, DXT); + copy_v2_v2(dyt, DYT); /* anisotropic filtering */ if (tex->texfilter != TXF_BOX) @@ -1451,8 +1460,12 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const image_mipmap_test(tex, ibuf); if (tex->imaflag & TEX_USEALPHA) { - if (tex->imaflag & TEX_CALCALPHA); - else texres->talpha= 1; + if (tex->imaflag & TEX_CALCALPHA) { + /* pass */ + } + else { + texres->talpha = TRUE; + } } texr.talpha= texres->talpha; @@ -1548,11 +1561,17 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const if (boundary==0) { if ( (tex->flag & TEX_CHECKER_ODD)==0) { - if ((xs+ys) & 1); - else return retval; + if ((xs + ys) & 1) { + /* pass */ + } + else { + return retval; + } } if ( (tex->flag & TEX_CHECKER_EVEN)==0) { - if ((xs+ys) & 1) return retval; + if ((xs + ys) & 1) { + return retval; + } } fx-= xs; fy-= ys; @@ -1626,7 +1645,7 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const dx = minx; dy = miny; - maxd = maxf(dx, dy); + maxd = max_ff(dx, dy); if (maxd > 0.5f) maxd = 0.5f; pixsize = 1.0f / (float) MIN2(ibuf->x, ibuf->y); diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c index 66f230a40f5..b2cf8db7995 100644 --- a/source/blender/render/intern/source/initrender.c +++ b/source/blender/render/intern/source/initrender.c @@ -555,32 +555,17 @@ void initparts(Render *re, int do_crop) xmaxb = re->disprect.xmax; ymaxb = re->disprect.ymax; - xparts = re->r.xparts; - yparts = re->r.yparts; - - /* mininum part size, but for exr tile saving it was checked already */ - if (!(re->r.scemode & (R_EXR_TILE_FILE | R_FULL_SAMPLE))) { - if (re->r.mode & R_PANORAMA) { - if (ceil(re->rectx / (float)xparts) < 8) - xparts = 1 + re->rectx / 8; - } - else - if (ceil(re->rectx / (float)xparts) < 64) - xparts = 1 + re->rectx / 64; - - if (ceil(re->recty / (float)yparts) < 64) - yparts = 1 + re->recty / 64; - } - /* part size */ - partx = ceil(re->rectx / (float)xparts); - party = ceil(re->recty / (float)yparts); + partx = min_ii(re->r.tilex, re->rectx); + party = min_ii(re->r.tiley, re->recty); - re->xparts = xparts; - re->yparts = yparts; re->partx = partx; re->party = party; + /* part count */ + xparts = (re->rectx + partx - 1) / partx; + yparts = (re->recty + party - 1) / party; + /* calculate rotation factor of 1 pixel */ if (re->r.mode & R_PANORAMA) re->panophi = panorama_pixel_rot(re); @@ -610,8 +595,8 @@ void initparts(Render *re, int do_crop) } else disprect.ymax = ymaxb; - rectx = BLI_RCT_SIZE_X(&disprect); - recty = BLI_RCT_SIZE_Y(&disprect); + rectx = BLI_rcti_size_x(&disprect); + recty = BLI_rcti_size_y(&disprect); /* so, now can we add this part? */ if (rectx > 0 && recty > 0) { diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c index 485dd005be7..a7308821843 100644 --- a/source/blender/render/intern/source/occlusion.c +++ b/source/blender/render/intern/source/occlusion.c @@ -61,7 +61,6 @@ /* ------------------------- Declarations --------------------------- */ -#define INVALID_INDEX ((int)(~0)) #define INVPI ((float)M_1_PI) #define TOTCHILD 8 #define CACHE_STEP 3 @@ -185,7 +184,7 @@ static void occ_shade(ShadeSample *ssamp, ObjectInstanceRen *obi, VlakRen *vlr, if (shi->flippednor) shade_input_flip_normals(shi); - madd_v3_v3fl(shi->co, shi->vn, 0.0001f); /* ugly.. */ + madd_v3_v3fl(shi->co, shi->facenor, -0.0001f); /* ugly.. */ /* not a pretty solution, but fixes common cases */ if (shi->obr->ob && shi->obr->ob->transflag & OB_NEG_SCALE) { @@ -233,9 +232,9 @@ static void occ_build_shade(Render *re, OcclusionTree *tree) /* ------------------------- Spherical Harmonics --------------------------- */ /* Use 2nd order SH => 9 coefficients, stored in this order: -* 0 = (0,0), -* 1 = (1,-1), 2 = (1,0), 3 = (1,1), -* 4 = (2,-2), 5 = (2,-1), 6 = (2,0), 7 = (2,1), 8 = (2,2) */ + * 0 = (0,0), + * 1 = (1,-1), 2 = (1,0), 3 = (1,1), + * 4 = (2,-2), 5 = (2,-1), 6 = (2,0), 7 = (2,1), 8 = (2,2) */ static void sh_copy(float *shresult, float *sh) { @@ -626,9 +625,12 @@ static void occ_build_sh_normalize(OccNode *node) sh_mul(node->sh, 1.0f / node->area); for (b = 0; b < TOTCHILD; b++) { - if (node->childflag & (1 << b)) ; - else if (node->child[b].node) + if (node->childflag & (1 << b)) { + /* pass */ + } + else if (node->child[b].node) { occ_build_sh_normalize(node->child[b].node); + } } } @@ -1057,8 +1059,8 @@ static float occ_quad_form_factor(float *p, float *n, float *q0, float *q1, floa static __m128 sse_approx_acos(__m128 x) { /* needs a better approximation than taylor expansion of acos, since that - * gives big erros for near 1.0 values, sqrt(2*x)*acos(1-x) should work - * better, see http://www.tom.womack.net/projects/sse-fast-arctrig.html */ + * gives big erros for near 1.0 values, sqrt(2*x)*acos(1-x) should work + * better, see http://www.tom.womack.net/projects/sse-fast-arctrig.html */ return _mm_set_ps1(1.0f); } @@ -1128,7 +1130,7 @@ static void normalizef(float *n) n[0] *= d; n[1] *= d; n[2] *= d; - } + } } /* TODO: exact duplicate of ff_quad_form_factor() in math_geom.c @@ -1545,7 +1547,7 @@ static int sample_occ_cache(OcclusionTree *tree, float *co, float *n, int x, int for (i = 0; i < 4; i++) { sub_v3_v3v3(d, samples[i]->co, co); - //dist2= dot_v3v3(d, d); + //dist2 = dot_v3v3(d, d); wz[i] = 1.0f; //(samples[i]->dist2/(1e-4f + dist2)); wn[i] = pow(dot_v3v3(samples[i]->n, n), 32.0f); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 599d91333e6..7ef3aecad08 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -203,9 +203,9 @@ RenderLayer *RE_GetRenderLayer(RenderResult *rr, const char *name) } } -RenderResult *RE_MultilayerConvert(void *exrhandle, int rectx, int recty) +RenderResult *RE_MultilayerConvert(void *exrhandle, const char *colorspace, int predivide, int rectx, int recty) { - return render_result_new_from_exr(exrhandle, rectx, recty); + return render_result_new_from_exr(exrhandle, colorspace, predivide, rectx, recty); } RenderLayer *render_get_active_layer(Render *re, RenderResult *rr) @@ -437,8 +437,8 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer * re->winy = winy; if (disprect) { re->disprect = *disprect; - re->rectx = BLI_RCT_SIZE_X(disprect); - re->recty = BLI_RCT_SIZE_Y(disprect); + re->rectx = BLI_rcti_size_x(disprect); + re->recty = BLI_rcti_size_y(disprect); } else { re->disprect.xmin = re->disprect.ymin = 0; @@ -499,13 +499,15 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer * } /* always call, checks for gamma, gamma tables and jitter too */ - make_sample_tables(re); + make_sample_tables(re); /* if preview render, we try to keep old result */ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if (re->r.scemode & R_PREVIEWBUTS) { - if (re->result && re->result->rectx == re->rectx && re->result->recty == re->recty) ; + if (re->result && re->result->rectx == re->rectx && re->result->recty == re->recty) { + /* pass */ + } else { render_result_free(re->result); re->result = NULL; @@ -654,8 +656,12 @@ static void *do_part_thread(void *pa_v) } else if (render_display_draw_enabled(&R)) { /* on break, don't merge in result for preview renders, looks nicer */ - if (R.test_break(R.tbh) && (R.r.scemode & R_PREVIEWBUTS)) ; - else render_result_merge(R.result, pa->result); + if (R.test_break(R.tbh) && (R.r.scemode & R_PREVIEWBUTS)) { + /* pass */ + } + else { + render_result_merge(R.result, pa->result); + } } } @@ -670,15 +676,16 @@ static void *do_part_thread(void *pa_v) float panorama_pixel_rot(Render *re) { float psize, phi, xfac; - float borderfac = (float)BLI_RCT_SIZE_X(&re->disprect) / (float)re->winx; + float borderfac = (float)BLI_rcti_size_x(&re->disprect) / (float)re->winx; + int xparts = (re->rectx + re->partx - 1) / re->partx; /* size of 1 pixel mapped to viewplane coords */ - psize = BLI_RCT_SIZE_X(&re->viewplane) / (float)re->winx; + psize = BLI_rctf_size_x(&re->viewplane) / (float)re->winx; /* angle of a pixel */ phi = atan(psize / re->clipsta); /* correction factor for viewplane shifting, first calculate how much the viewplane angle is */ - xfac = borderfac * BLI_RCT_SIZE_X(&re->viewplane) / (float)re->xparts; + xfac = borderfac * BLI_rctf_size_x(&re->viewplane) / (float)xparts; xfac = atan(0.5f * xfac / re->clipsta); /* and how much the same viewplane angle is wrapped */ psize = 0.5f * phi * ((float)re->partx); @@ -711,7 +718,7 @@ static RenderPart *find_next_pano_slice(Render *re, int *minx, rctf *viewplane) float phi = panorama_pixel_rot(re); R.panodxp = (re->winx - (best->disprect.xmin + best->disprect.xmax) ) / 2; - R.panodxv = (BLI_RCT_SIZE_X(viewplane) * R.panodxp) / (float)(re->winx); + R.panodxv = (BLI_rctf_size_x(viewplane) * R.panodxp) / (float)(re->winx); /* shift viewplane */ R.viewplane.xmin = viewplane->xmin + R.panodxv; @@ -738,8 +745,8 @@ static RenderPart *find_next_part(Render *re, int minx) /* find center of rendered parts, image center counts for 1 too */ for (pa = re->parts.first; pa; pa = pa->next) { if (pa->ready) { - centx += BLI_RCT_CENTER_X(&pa->disprect); - centy += BLI_RCT_CENTER_Y(&pa->disprect); + centx += BLI_rcti_cent_x(&pa->disprect); + centy += BLI_rcti_cent_y(&pa->disprect); tot++; } } @@ -749,8 +756,8 @@ static RenderPart *find_next_part(Render *re, int minx) /* closest of the non-rendering parts */ for (pa = re->parts.first; pa; pa = pa->next) { if (pa->ready == 0 && pa->nr == 0) { - long long int distx = centx - BLI_RCT_CENTER_X(&pa->disprect); - long long int disty = centy - BLI_RCT_CENTER_Y(&pa->disprect); + long long int distx = centx - BLI_rcti_cent_x(&pa->disprect); + long long int disty = centy - BLI_rcti_cent_y(&pa->disprect); distx = (long long int)sqrt(distx * distx + disty * disty); if (distx < mindist) { if (re->r.mode & R_PANORAMA) { @@ -978,7 +985,7 @@ static void addblur_rect_key(RenderResult *rr, float *rectf, float *rectf1, floa rf[1] = mfac * rf[1] + blurfac * rf1[1]; rf[2] = mfac * rf[2] + blurfac * rf1[2]; rf[3] = mfac * rf[3] + blurfac * rf1[3]; - } + } } } rectf += stride; @@ -1070,7 +1077,7 @@ static void do_render_blur_3d(Render *re) /* weak... the display callback wants an active renderlayer pointer... */ re->result->renlay = render_get_active_layer(re, re->result); - re->display_draw(re->ddh, re->result, NULL); + re->display_draw(re->ddh, re->result, NULL); } @@ -1387,7 +1394,7 @@ static void render_composit_stats(void *UNUSED(arg), char *str) static void do_merge_fullsample(Render *re, bNodeTree *ntree) { float *rectf, filt[3][3]; - int sample; + int x, y, sample; /* interaction callbacks */ if (ntree) { @@ -1408,7 +1415,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) for (sample = 0; sample < re->r.osa; sample++) { Render *re1; RenderResult rres; - int x, y, mask; + int mask; /* enable full sample print */ R.i.curfsa = sample + 1; @@ -1471,6 +1478,18 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) if (re->test_break(re->tbh)) break; } + + /* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */ + for (y = 0; y < re->recty; y++) { + float *rf = rectf + 4 * y * re->rectx; + + for (x = 0; x < re->rectx; x++, rf += 4) { + rf[0] = MAX2(rf[0], 0.0f); + rf[1] = MAX2(rf[1], 0.0f); + rf[2] = MAX2(rf[2], 0.0f); + CLAMP(rf[3], 0.0f, 1.0f); + } + } /* clear interaction callbacks */ if (ntree) { @@ -1501,6 +1520,7 @@ void RE_MergeFullSample(Render *re, Main *bmain, Scene *sce, bNodeTree *ntree) re->main = bmain; re->scene = sce; + re->scene_color_manage = BKE_scene_check_color_management_enabled(sce); /* first call RE_ReadRenderResult on every renderlayer scene. this creates Render structs */ @@ -1548,7 +1568,7 @@ static void do_render_composite_fields_blur_3d(Render *re) ntreeFreeCache(ntree); do_render_fields_blur_3d(re); - } + } else { /* ensure new result gets added, like for regular renders */ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); @@ -1677,9 +1697,14 @@ static void do_render_seq(Render *re) out = BKE_sequencer_give_ibuf(context, cfra, 0); - ibuf = IMB_dupImBuf(out); - IMB_freeImBuf(out); - BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf); + if (out) { + ibuf = IMB_dupImBuf(out); + IMB_freeImBuf(out); + BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf); + } + else { + ibuf = NULL; + } recurs_depth--; @@ -1713,6 +1738,9 @@ static void do_render_seq(Render *re) re->progress(re->prh, (float)(cfra - re->r.sfra) / (re->r.efra - re->r.sfra)); else re->progress(re->prh, 1.0f); + + /* would mark display buffers as invalid */ + re->display_draw(re->ddh, re->result, NULL); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -1845,7 +1873,7 @@ int RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *r if (scene->r.border.xmax <= scene->r.border.xmin || scene->r.border.ymax <= scene->r.border.ymin) { - BKE_report(reports, RPT_ERROR, "No border area selected."); + BKE_report(reports, RPT_ERROR, "No border area selected"); return 0; } } @@ -1856,13 +1884,13 @@ int RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *r render_result_exr_file_path(scene, "", 0, str); if (BLI_file_is_writable(str) == 0) { - BKE_report(reports, RPT_ERROR, "Can not save render buffers, check the temp default path"); + BKE_report(reports, RPT_ERROR, "Cannot save render buffers, check the temp default path"); return 0; } /* no fullsample and edge */ if ((scene->r.scemode & R_FULL_SAMPLE) && (scene->r.mode & R_EDGE)) { - BKE_report(reports, RPT_ERROR, "Full Sample doesn't support Edge Enhance"); + BKE_report(reports, RPT_ERROR, "Full sample does not support edge enhance"); return 0; } @@ -1873,18 +1901,18 @@ int RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *r if (scene->r.scemode & R_DOCOMP) { if (scene->use_nodes) { if (!scene->nodetree) { - BKE_report(reports, RPT_ERROR, "No Nodetree in Scene"); + BKE_report(reports, RPT_ERROR, "No node tree in scene"); return 0; } if (!check_composite_output(scene)) { - BKE_report(reports, RPT_ERROR, "No Render Output Node in Scene"); + BKE_report(reports, RPT_ERROR, "No render output node in scene"); return 0; } if (scene->r.scemode & R_FULL_SAMPLE) { if (composite_needs_render(scene, 0) == 0) { - BKE_report(reports, RPT_ERROR, "Full Sample AA not supported without 3d rendering"); + BKE_report(reports, RPT_ERROR, "Full sample AA not supported without 3D rendering"); return 0; } } @@ -1903,7 +1931,7 @@ int RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *r /* forbidden combinations */ if (scene->r.mode & R_PANORAMA) { if (scene->r.mode & R_ORTHO) { - BKE_report(reports, RPT_ERROR, "No Ortho render possible for Panorama"); + BKE_report(reports, RPT_ERROR, "No ortho render possible for panorama"); return 0; } } @@ -1919,7 +1947,7 @@ int RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *r if (!(srl->layflag & SCE_LAY_DISABLE)) break; if (srl == NULL) { - BKE_report(reports, RPT_ERROR, "All RenderLayers are disabled"); + BKE_report(reports, RPT_ERROR, "All render layers are disabled"); return 0; } @@ -1988,6 +2016,7 @@ static int render_initialize_from_main(Render *re, Main *bmain, Scene *scene, Sc re->main = bmain; re->scene = scene; + re->scene_color_manage = BKE_scene_check_color_management_enabled(scene); re->camera_override = camera_override; re->lay = lay; @@ -2074,14 +2103,6 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr G.is_rendering = FALSE; } -static void colormanage_image_for_write(Scene *scene, ImBuf *ibuf) -{ - IMB_display_buffer_to_imbuf_rect(ibuf, &scene->view_settings, &scene->display_settings); - - if (ibuf) - imb_freerectfloatImBuf(ibuf); -} - static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const char *name_override) { char name[FILE_MAX]; @@ -2099,24 +2120,28 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie /* note; the way it gets 32 bits rects is weak... */ if (ibuf->rect == NULL) { ibuf->rect = MEM_mapallocN(sizeof(int) * rres.rectx * rres.recty, "temp 32 bits rect"); + ibuf->mall |= IB_rect; RE_ResultGet32(re, ibuf->rect); do_free = TRUE; } - colormanage_image_for_write(scene, ibuf); + + IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings, + &scene->display_settings, &scene->r.im_format); ok = mh->append_movie(&re->r, scene->r.sfra, scene->r.cfra, (int *) ibuf->rect, ibuf->x, ibuf->y, re->reports); if (do_free) { MEM_freeN(ibuf->rect); ibuf->rect = NULL; + ibuf->mall &= ~IB_rect; } /* imbuf knows which rects are not part of ibuf */ IMB_freeImBuf(ibuf); printf("Append frame %d", scene->r.cfra); - } + } else { if (name_override) BLI_strncpy(name, name_override, sizeof(name)); @@ -2131,12 +2156,9 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie } else { ImBuf *ibuf = render_result_rect_to_ibuf(&rres, &scene->r); - int do_colormanagement; - do_colormanagement = !BKE_imtype_supports_float(scene->r.im_format.imtype); - - if (do_colormanagement) - colormanage_image_for_write(scene, ibuf); + IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings, + &scene->display_settings, &scene->r.im_format); ok = BKE_imbuf_write_stamp(scene, camera, ibuf, name, &scene->r.im_format); @@ -2155,7 +2177,8 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie BKE_add_image_extension(name, R_IMF_IMTYPE_JPEG90); ibuf->planes = 24; - colormanage_image_for_write(scene, ibuf); + IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings, + &scene->display_settings, &imf); BKE_imbuf_write_stamp(scene, camera, ibuf, name, &imf); printf("\nSaved: %s", name); @@ -2332,6 +2355,7 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce) re->main = bmain; re->scene = sce; + re->scene_color_manage = BKE_scene_check_color_management_enabled(sce); re->lay = sce->lay; camera = RE_GetCamera(re); @@ -2376,6 +2400,7 @@ int RE_ReadRenderResult(Scene *scene, Scene *scenode) re = RE_NewRender(scene->id.name); RE_InitState(re, NULL, &scene->r, NULL, winx, winy, &disprect); re->scene = scene; + re->scene_color_manage = BKE_scene_check_color_management_enabled(scene); BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); success = render_result_exr_file_read(re, 0); @@ -2436,25 +2461,25 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char IMB_freeImBuf(ibuf_clip); } else { - BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to allocate clip buffer '%s'\n", filename); + BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to allocate clip buffer '%s'", filename); } } else { - BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: incorrect dimensions for partial copy '%s'\n", filename); + BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: incorrect dimensions for partial copy '%s'", filename); } } IMB_freeImBuf(ibuf); } else { - BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'\n", filename); + BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'", filename); } } void RE_result_load_from_file(RenderResult *result, ReportList *reports, const char *filename) { if (!render_result_exr_file_read_path(result, NULL, filename)) { - BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'\n", filename); + BKE_reportf(reports, RPT_ERROR, "RE_result_rect_from_file: failed to load '%s'", filename); return; } } @@ -2501,7 +2526,7 @@ int RE_WriteEnvmapResult(struct ReportList *reports, Scene *scene, EnvMap *env, return 0; } - IMB_display_buffer_to_imbuf_rect(ibuf, &scene->view_settings, &scene->display_settings); + IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings, &scene->display_settings, &imf); /* to save, we first get absolute path */ BLI_strncpy(filepath, relpath, sizeof(filepath)); @@ -2515,7 +2540,7 @@ int RE_WriteEnvmapResult(struct ReportList *reports, Scene *scene, EnvMap *env, return TRUE; } else { - BKE_report(reports, RPT_ERROR, "Error writing environment map."); + BKE_report(reports, RPT_ERROR, "Error writing environment map"); return FALSE; } } diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c index 8e6078b18e0..3420648cb52 100644 --- a/source/blender/render/intern/source/pixelshading.c +++ b/source/blender/render/intern/source/pixelshading.c @@ -162,7 +162,7 @@ static void render_lighting_halo(HaloRen *har, float col_r[3]) copy_v3_v3(lvrot, lv); mul_m3_v3(lar->imat, lvrot); - x = maxf(fabsf(lvrot[0]/lvrot[2]), fabsf(lvrot[1]/lvrot[2])); + x = max_ff(fabsf(lvrot[0]/lvrot[2]), fabsf(lvrot[1]/lvrot[2])); /* 1.0/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */ inpr= 1.0/(sqrt(1.0f+x*x)); @@ -614,7 +614,7 @@ void shadeSkyPixel(float collector[4], float fx, float fy, short thread) copy_v3_v3(collector, &R.wrld.horr); collector[3] = 0.0f; - } + } else { /* 2. */ diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c index 49c2bf1d053..a540cdb85d5 100644 --- a/source/blender/render/intern/source/pointdensity.c +++ b/source/blender/render/intern/source/pointdensity.c @@ -36,6 +36,7 @@ #include "BLI_math.h" #include "BLI_blenlib.h" +#include "BLI_noise.h" #include "BLI_kdopbvh.h" #include "BLI_utildefines.h" @@ -170,7 +171,7 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa pd->point_data[i*3 + 0] = state.vel[0]; pd->point_data[i*3 + 1] = state.vel[1]; pd->point_data[i*3 + 2] = state.vel[2]; - } + } if (data_used & POINT_DATA_LIFE) { float pa_time; @@ -405,7 +406,7 @@ static void init_pointdensityrangedata(PointDensity *pd, PointDensityRangeData * } -int pointdensitytex(Tex *tex, float *texvec, TexResult *texres) +int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres) { int retval = TEX_INT; PointDensity *pd = tex->pd; @@ -418,7 +419,7 @@ int pointdensitytex(Tex *tex, float *texvec, TexResult *texres) texres->tin = 0.0f; - if ((!pd) || (!pd->point_tree)) + if ((!pd) || (!pd->point_tree)) return 0; init_pointdensityrangedata(pd, &pdr, &density, vec, &age, @@ -481,7 +482,7 @@ int pointdensitytex(Tex *tex, float *texvec, TexResult *texres) case TEX_PD_COLOR_PARTAGE: if (pd->coba) { if (do_colorband(pd->coba, age, col)) { - texres->talpha= 1; + texres->talpha = TRUE; copy_v3_v3(&texres->tr, col); texres->tin *= col[3]; texres->ta = texres->tin; @@ -494,7 +495,7 @@ int pointdensitytex(Tex *tex, float *texvec, TexResult *texres) if (pd->coba) { if (do_colorband(pd->coba, speed, col)) { - texres->talpha= 1; + texres->talpha = TRUE; copy_v3_v3(&texres->tr, col); texres->tin *= col[3]; texres->ta = texres->tin; @@ -503,7 +504,7 @@ int pointdensitytex(Tex *tex, float *texvec, TexResult *texres) break; } case TEX_PD_COLOR_PARTVEL: - texres->talpha= 1; + texres->talpha = TRUE; mul_v3_fl(vec, pd->speed_scale); copy_v3_v3(&texres->tr, vec); texres->ta = texres->tin; diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index aa35d73f3b5..127e0bc07b9 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -239,7 +239,7 @@ RayObject* makeraytree_object(Render *re, ObjectInstanceRen *obi) if (faces == 0) return NULL; - //Create Ray cast accelaration structure + //Create Ray cast accelaration structure raytree = RE_rayobject_create( re, re->r.raytrace_structure, faces ); if ( (re->r.raytrace_options & R_RAYTRACE_USE_LOCAL_COORDS) ) vlakprimitive = obr->rayprimitives = (VlakPrimitive*)MEM_callocN(faces*sizeof(VlakPrimitive), "ObjectRen primitives"); @@ -549,7 +549,7 @@ void shade_ray(Isect *is, ShadeInput *shi, ShadeResult *shr) /* raytrace likes to separate the spec color */ sub_v3_v3v3(shr->diff, shr->combined, shr->spec); - } + } } @@ -564,12 +564,12 @@ static int refraction(float refract[3], const float n[3], const float view[3], f if (dot>0.0f) { index = 1.0f/index; fac= 1.0f - (1.0f - dot*dot)*index*index; - if (fac<= 0.0f) return 0; + if (fac <= 0.0f) return 0; fac= -dot*index + sqrtf(fac); } else { fac= 1.0f - (1.0f - dot*dot)*index*index; - if (fac<= 0.0f) return 0; + if (fac <= 0.0f) return 0; fac= -dot*index - sqrtf(fac); } @@ -632,7 +632,7 @@ static float shade_by_transmission(Isect *is, ShadeInput *shi, ShadeResult *shr) if (shi->mat->tx_limit <= 0.0f) { d= 1.0f; - } + } else { float p; @@ -733,7 +733,7 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, con if (depth>0) { float fr, fg, fb, f, f1; - if ((shi.mat->mode_l & MA_TRANSP) && shr.alpha < 1.0f && (shi.mat->mode_l & (MA_ZTRANSP | MA_RAYTRANSP))) { + if ((shi.mat->mode_l & MA_TRANSP) && shr.alpha < 1.0f && (shi.mat->mode_l & (MA_ZTRANSP | MA_RAYTRANSP))) { float nf, f, refract[3], tracol[4]; tracol[0]= shi.r; @@ -938,7 +938,7 @@ void init_jitter_plane(LampRen *lar) DP_energy(lar->jitter, fp, tot, lar->area_size, lar->area_sizey); } } - } + } /* create the dithered tables (could just check lamp type!) */ jitter_plane_offset(lar->jitter, lar->jitter+2*tot, tot, lar->area_size, lar->area_sizey, 0.5f, 0.0f); jitter_plane_offset(lar->jitter, lar->jitter+4*tot, tot, lar->area_size, lar->area_sizey, 0.5f, 0.5f); @@ -1151,7 +1151,7 @@ static void QMC_sampleHemiCosine(float vec[3], QMCSampler *qsa, int thread, int QMC_getSample(s, qsa, thread, num); - phi = s[0]*2.f*M_PI; + phi = s[0]*2.f*M_PI; sqr = s[1]*sqrt(2-s[1]*s[1]); vec[0] = cos(phi)*sqr; @@ -1295,7 +1295,7 @@ static void trace_refract(float col[4], ShadeInput *shi, ShadeResult *shr) max_samples = 1; - while (samples < max_samples) { + while (samples < max_samples) { if (refraction(v_refract, shi->vn, shi->view, shi->ang)) { traflag |= RAY_INSIDE; } @@ -1515,7 +1515,7 @@ void ray_trace(ShadeInput *shi, ShadeResult *shr) if (!(shi->combinedflag & SCE_PASS_REFRACT)) sub_v3_v3v3(diff, diff, shr->refr); - shr->alpha = minf(1.0f, tracol[3]); + shr->alpha = min_ff(1.0f, tracol[3]); } if (do_mir) { @@ -1822,7 +1822,7 @@ static float *sphere_sampler(int type, int resol, int thread, int xs, int ys, in } return sphere; - } + } else { float *sphere; float *vec1; @@ -1847,7 +1847,7 @@ static float *sphere_sampler(int type, int resol, int thread, int xs, int ys, in for (a=0; atype == SAMP_TYPE_HALTON) { - /* adaptive sampling - consider samples below threshold as in shadow (or vice versa) and exit early */ + /* adaptive sampling - consider samples below threshold as in shadow (or vice versa) and exit early */ if (adapt_thresh > 0.0f && (samples > max_samples/2) ) { if (adaptive_sample_contrast_val(samples, prev, fac, adapt_thresh)) { @@ -2532,7 +2532,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float shadfac[4]) #if 0 /* only when face points away from lamp, in direction of lamp, trace ray and find first exit point */ -static void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float *co) +static void ray_translucent(ShadeInput *shi, LampRen *lar, float *distfac, float co[3]) { Isect isec; float lampco[3]; diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index f11f84c9d3b..f8281586038 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -422,8 +422,8 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf SceneRenderLayer *srl; int rectx, recty, nr; - rectx = BLI_RCT_SIZE_X(partrct); - recty = BLI_RCT_SIZE_Y(partrct); + rectx = BLI_rcti_size_x(partrct); + recty = BLI_rcti_size_y(partrct); if (rectx <= 0 || recty <= 0) return NULL; @@ -569,8 +569,8 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf } /* border render; calculate offset for use in compositor. compo is centralized coords */ - rr->xof = re->disprect.xmin + BLI_RCT_CENTER_X(&re->disprect) - (re->winx / 2); - rr->yof = re->disprect.ymin + BLI_RCT_CENTER_Y(&re->disprect) - (re->winy / 2); + rr->xof = re->disprect.xmin + BLI_rcti_cent_x(&re->disprect) - (re->winx / 2); + rr->yof = re->disprect.ymin + BLI_rcti_cent_y(&re->disprect) - (re->winy / 2); return rr; } @@ -627,12 +627,13 @@ static void ml_addpass_cb(void *UNUSED(base), void *lay, const char *str, float } /* from imbuf, if a handle was returned we convert this to render result */ -RenderResult *render_result_new_from_exr(void *exrhandle, int rectx, int recty) +RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace, int predivide, int rectx, int recty) { RenderResult *rr = MEM_callocN(sizeof(RenderResult), __func__); RenderLayer *rl; RenderPass *rpass; - + const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); + rr->rectx = rectx; rr->recty = recty; @@ -645,6 +646,11 @@ RenderResult *render_result_new_from_exr(void *exrhandle, int rectx, int recty) for (rpass = rl->passes.first; rpass; rpass = rpass->next) { rpass->rectx = rectx; rpass->recty = recty; + + if (rpass->channels >= 3) { + IMB_colormanagement_transform(rpass->rect, rpass->rectx, rpass->recty, rpass->channels, + colorspace, to_colorspace, predivide); + } } } @@ -780,7 +786,7 @@ int RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *file } else { /* TODO, get the error from openexr's exception */ - BKE_report(reports, RPT_ERROR, "Error Writing Render Result, see console"); + BKE_report(reports, RPT_ERROR, "Error writing render result (see console)"); success = FALSE; } IMB_exr_close(exrhandle); diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index 6d22d8991b4..c507d6595e0 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -35,6 +35,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_noise.h" #include "BLI_rand.h" #include "BLI_utildefines.h" @@ -98,7 +99,7 @@ static void init_render_texture(Render *re, Tex *tex) { /* imap test */ if (tex->ima && ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { - BKE_image_user_frame_calc(&tex->iuser, re->r.cfra, re?re->flag & R_SEC_FIELD:0); + BKE_image_user_frame_calc(&tex->iuser, re ? re->r.cfra : 0, re ? re->flag & R_SEC_FIELD:0); } else if (tex->type==TEX_ENVMAP) { @@ -184,7 +185,7 @@ static void tex_normal_derivate(Tex *tex, TexResult *texres) -static int blend(Tex *tex, float *texvec, TexResult *texres) +static int blend(Tex *tex, const float texvec[3], TexResult *texres) { float x, y, t; @@ -236,7 +237,7 @@ static int blend(Tex *tex, float *texvec, TexResult *texres) /* newnoise: all noisebased types now have different noisebases to choose from */ -static int clouds(Tex *tex, float *texvec, TexResult *texres) +static int clouds(Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; @@ -302,7 +303,7 @@ static float tex_tri(float a) /* computes basic wood intensity value at x,y,z */ static float wood_int(Tex *tex, float x, float y, float z) { - float wi=0; + float wi = 0; short wf = tex->noisebasis2; /* wave form: TEX_SIN=0, TEX_SAW=1, TEX_TRI=2 */ short wt = tex->stype; /* wood type: TEX_BAND=0, TEX_RING=1, TEX_BANDNOISE=2, TEX_RINGNOISE=3 */ @@ -331,7 +332,7 @@ static float wood_int(Tex *tex, float x, float y, float z) return wi; } -static int wood(Tex *tex, float *texvec, TexResult *texres) +static int wood(Tex *tex, const float texvec[3], TexResult *texres) { int rv=TEX_INT; @@ -373,7 +374,7 @@ static float marble_int(Tex *tex, float x, float y, float z) mi = waveform[wf](mi); if (mt==TEX_SHARP) { mi = sqrt(mi); - } + } else if (mt==TEX_SHARPER) { mi = sqrt(sqrt(mi)); } @@ -382,7 +383,7 @@ static float marble_int(Tex *tex, float x, float y, float z) return mi; } -static int marble(Tex *tex, float *texvec, TexResult *texres) +static int marble(Tex *tex, const float texvec[3], TexResult *texres) { int rv=TEX_INT; @@ -406,7 +407,7 @@ static int marble(Tex *tex, float *texvec, TexResult *texres) /* ------------------------------------------------------------------------- */ -static int magic(Tex *tex, float *texvec, TexResult *texres) +static int magic(Tex *tex, const float texvec[3], TexResult *texres) { float x, y, z, turb=1.0; int n; @@ -482,7 +483,7 @@ static int magic(Tex *tex, float *texvec, TexResult *texres) /* ------------------------------------------------------------------------- */ /* newnoise: stucci also modified to use different noisebasis */ -static int stucci(Tex *tex, float *texvec, TexResult *texres) +static int stucci(Tex *tex, const float texvec[3], TexResult *texres) { float nor[3], b2, ofs; int retval= TEX_INT; @@ -493,7 +494,7 @@ static int stucci(Tex *tex, float *texvec, TexResult *texres) if (tex->stype) ofs*=(b2*b2); nor[0] = BLI_gNoise(tex->noisesize, texvec[0]+ofs, texvec[1], texvec[2], (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); - nor[1] = BLI_gNoise(tex->noisesize, texvec[0], texvec[1]+ofs, texvec[2], (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); + nor[1] = BLI_gNoise(tex->noisesize, texvec[0], texvec[1]+ofs, texvec[2], (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); nor[2] = BLI_gNoise(tex->noisesize, texvec[0], texvec[1], texvec[2]+ofs, (tex->noisetype!=TEX_NOISESOFT), tex->noisebasis); texres->tin= nor[2]; @@ -524,7 +525,7 @@ static int stucci(Tex *tex, float *texvec, TexResult *texres) /* ------------------------------------------------------------------------- */ /* newnoise: musgrave terrain noise types */ -static float mg_mFractalOrfBmTex(Tex *tex, float *texvec, TexResult *texres) +static float mg_mFractalOrfBmTex(Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; float (*mgravefunc)(float, float, float, float, float, float, int); @@ -554,7 +555,7 @@ static float mg_mFractalOrfBmTex(Tex *tex, float *texvec, TexResult *texres) } -static float mg_ridgedOrHybridMFTex(Tex *tex, float *texvec, TexResult *texres) +static float mg_ridgedOrHybridMFTex(Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; float (*mgravefunc)(float, float, float, float, float, float, float, float, int); @@ -585,7 +586,7 @@ static float mg_ridgedOrHybridMFTex(Tex *tex, float *texvec, TexResult *texres) } -static float mg_HTerrainTex(Tex *tex, float *texvec, TexResult *texres) +static float mg_HTerrainTex(Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; @@ -610,7 +611,7 @@ static float mg_HTerrainTex(Tex *tex, float *texvec, TexResult *texres) } -static float mg_distNoiseTex(Tex *tex, float *texvec, TexResult *texres) +static float mg_distNoiseTex(Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; @@ -639,7 +640,7 @@ static float mg_distNoiseTex(Tex *tex, float *texvec, TexResult *texres) /* ------------------------------------------------------------------------- */ /* newnoise: Voronoi texture type, probably the slowest, especially with minkovsky, bumpmapping, could be done another way */ -static float voronoiTex(Tex *tex, float *texvec, TexResult *texres) +static float voronoiTex(Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; float da[4], pa[12]; /* distance and point coordinate arrays of 4 nearest neighbors */ @@ -768,7 +769,7 @@ static int cubemap_glob(const float n[3], float x, float y, float z, float *adr1 else { *adr1 = (y + 1.0f) / 2.0f; *adr2 = (z + 1.0f) / 2.0f; - ret= 2; + ret= 2; } return ret; } @@ -823,8 +824,8 @@ static int cubemap(MTex *mtex, VlakRen *vlr, const float n[3], float x, float y, *adr1 = (y + 1.0f) / 2.0f; *adr2 = (z + 1.0f) / 2.0f; ret= 2; - } - } + } + } else { return cubemap_glob(n, x, y, z, adr1, adr2); } @@ -861,14 +862,14 @@ static int cubemap_ob(Object *ob, const float n[3], float x, float y, float z, f else { *adr1 = (y + 1.0f) / 2.0f; *adr2 = (z + 1.0f) / 2.0f; - ret= 2; + ret= 2; } return ret; } /* ------------------------------------------------------------------------- */ -static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, const float n[3], float *dxt, float *dyt) +static void do_2d_mapping(MTex *mtex, float texvec[3], VlakRen *vlr, const float n[3], float dxt[3], float dyt[3]) { Tex *tex; Object *ob= NULL; @@ -884,15 +885,15 @@ static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, const float n[3], if (R.osa==0) { if (wrap==MTEX_FLAT) { - fx = (t[0] + 1.0f) / 2.0f; - fy = (t[1] + 1.0f) / 2.0f; + fx = (texvec[0] + 1.0f) / 2.0f; + fy = (texvec[1] + 1.0f) / 2.0f; } - else if (wrap==MTEX_TUBE) map_to_tube( &fx, &fy, t[0], t[1], t[2]); - else if (wrap==MTEX_SPHERE) map_to_sphere(&fx, &fy, t[0], t[1], t[2]); + else if (wrap == MTEX_TUBE) map_to_tube( &fx, &fy, texvec[0], texvec[1], texvec[2]); + else if (wrap == MTEX_SPHERE) map_to_sphere(&fx, &fy, texvec[0], texvec[1], texvec[2]); else { - if (texco==TEXCO_OBJECT) cubemap_ob(ob, n, t[0], t[1], t[2], &fx, &fy); - else if (texco==TEXCO_GLOB) cubemap_glob(n, t[0], t[1], t[2], &fx, &fy); - else cubemap(mtex, vlr, n, t[0], t[1], t[2], &fx, &fy); + if (texco == TEXCO_OBJECT) cubemap_ob(ob, n, texvec[0], texvec[1], texvec[2], &fx, &fy); + else if (texco == TEXCO_GLOB) cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy); + else cubemap(mtex, vlr, n, texvec[0], texvec[1], texvec[2], &fx, &fy); } /* repeat */ @@ -932,14 +933,14 @@ static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, const float n[3], fy= tex->cropymin+ fy*fac1; } - t[0]= fx; - t[1]= fy; + texvec[0]= fx; + texvec[1]= fy; } else { if (wrap==MTEX_FLAT) { - fx= (t[0] + 1.0f) / 2.0f; - fy= (t[1] + 1.0f) / 2.0f; + fx= (texvec[0] + 1.0f) / 2.0f; + fy= (texvec[1] + 1.0f) / 2.0f; dxt[0]/= 2.0f; dxt[1]/= 2.0f; dxt[2]/= 2.0f; @@ -950,29 +951,36 @@ static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, const float n[3], else if (ELEM(wrap, MTEX_TUBE, MTEX_SPHERE)) { /* exception: the seam behind (y<0.0) */ ok= 1; - if (t[1]<=0.0f) { - fx= t[0]+dxt[0]; - fy= t[0]+dyt[0]; - if (fx>=0.0f && fy>=0.0f && t[0]>=0.0f); - else if (fx<=0.0f && fy<=0.0f && t[0]<=0.0f); - else ok= 0; + if (texvec[1]<=0.0f) { + fx= texvec[0]+dxt[0]; + fy= texvec[0]+dyt[0]; + if (fx>=0.0f && fy>=0.0f && texvec[0]>=0.0f) { + /* pass */ + } + else if (fx<=0.0f && fy<=0.0f && texvec[0]<=0.0f) { + /* pass */ + } + else { + ok = 0; + } } + if (ok) { if (wrap==MTEX_TUBE) { - map_to_tube(area, area+1, t[0], t[1], t[2]); - map_to_tube(area + 2, area + 3, t[0] + dxt[0], t[1] + dxt[1], t[2] + dxt[2]); - map_to_tube(area + 4, area + 5, t[0] + dyt[0], t[1] + dyt[1], t[2] + dyt[2]); + map_to_tube(area, area+1, texvec[0], texvec[1], texvec[2]); + map_to_tube(area + 2, area + 3, texvec[0] + dxt[0], texvec[1] + dxt[1], texvec[2] + dxt[2]); + map_to_tube(area + 4, area + 5, texvec[0] + dyt[0], texvec[1] + dyt[1], texvec[2] + dyt[2]); } - else { - map_to_sphere(area, area+1, t[0], t[1], t[2]); - map_to_sphere(area + 2, area + 3, t[0] + dxt[0], t[1] + dxt[1], t[2] + dxt[2]); - map_to_sphere(area + 4, area + 5, t[0] + dyt[0], t[1] + dyt[1], t[2] + dyt[2]); + else { + map_to_sphere(area, area+1, texvec[0], texvec[1], texvec[2]); + map_to_sphere(area + 2, area + 3, texvec[0] + dxt[0], texvec[1] + dxt[1], texvec[2] + dxt[2]); + map_to_sphere(area + 4, area + 5, texvec[0] + dyt[0], texvec[1] + dyt[1], texvec[2] + dyt[2]); } areaflag= 1; } else { - if (wrap==MTEX_TUBE) map_to_tube( &fx, &fy, t[0], t[1], t[2]); - else map_to_sphere(&fx, &fy, t[0], t[1], t[2]); + if (wrap==MTEX_TUBE) map_to_tube( &fx, &fy, texvec[0], texvec[1], texvec[2]); + else map_to_sphere(&fx, &fy, texvec[0], texvec[1], texvec[2]); dxt[0]/= 2.0f; dxt[1]/= 2.0f; dyt[0]/= 2.0f; @@ -981,9 +989,9 @@ static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, const float n[3], } else { - if (texco==TEXCO_OBJECT) proj = cubemap_ob(ob, n, t[0], t[1], t[2], &fx, &fy); - else if (texco==TEXCO_GLOB) proj = cubemap_glob(n, t[0], t[1], t[2], &fx, &fy); - else proj = cubemap(mtex, vlr, n, t[0], t[1], t[2], &fx, &fy); + if (texco==TEXCO_OBJECT) proj = cubemap_ob(ob, n, texvec[0], texvec[1], texvec[2], &fx, &fy); + else if (texco==TEXCO_GLOB) proj = cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy); + else proj = cubemap(mtex, vlr, n, texvec[0], texvec[1], texvec[2], &fx, &fy); if (proj==1) { SWAP(float, dxt[1], dxt[2]); @@ -1083,117 +1091,117 @@ static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, const float n[3], dyt[1]*= fac1; } - t[0]= fx; - t[1]= fy; + texvec[0]= fx; + texvec[1]= fy; } } /* ************************************** */ -static int multitex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres, short thread, short which_output) +static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, const short thread, short which_output) { float tmpvec[3]; - int retval=0; /* return value, int:0, col:1, nor:2, everything:3 */ + int retval = 0; /* return value, int:0, col:1, nor:2, everything:3 */ - texres->talpha= 0; /* is set when image texture returns alpha (considered premul) */ + texres->talpha = FALSE; /* is set when image texture returns alpha (considered premul) */ if (tex->use_nodes && tex->nodetree) { retval = ntreeTexExecTree(tex->nodetree, texres, texvec, dxt, dyt, osatex, thread, - tex, which_output, R.r.cfra, (R.r.scemode & R_TEXNODE_PREVIEW) != 0, NULL, NULL); + tex, which_output, R.r.cfra, (R.r.scemode & R_TEXNODE_PREVIEW) != 0, NULL, NULL); } - else - switch (tex->type) { - - case 0: - texres->tin= 0.0f; - return 0; - case TEX_CLOUDS: - retval= clouds(tex, texvec, texres); - break; - case TEX_WOOD: - retval= wood(tex, texvec, texres); - break; - case TEX_MARBLE: - retval= marble(tex, texvec, texres); - break; - case TEX_MAGIC: - retval= magic(tex, texvec, texres); - break; - case TEX_BLEND: - retval= blend(tex, texvec, texres); - break; - case TEX_STUCCI: - retval= stucci(tex, texvec, texres); - break; - case TEX_NOISE: - retval= texnoise(tex, texres); - break; - case TEX_IMAGE: - if (osatex) retval= imagewraposa(tex, tex->ima, NULL, texvec, dxt, dyt, texres); - else retval= imagewrap(tex, tex->ima, NULL, texvec, texres); - BKE_image_tag_time(tex->ima); /* tag image as having being used */ - break; - case TEX_ENVMAP: - retval= envmaptex(tex, texvec, dxt, dyt, osatex, texres); - break; - case TEX_MUSGRAVE: - /* newnoise: musgrave types */ - - /* ton: added this, for Blender convention reason. - * artificer: added the use of tmpvec to avoid scaling texvec - */ - copy_v3_v3(tmpvec, texvec); - mul_v3_fl(tmpvec, 1.0f/tex->noisesize); - - switch (tex->stype) { - case TEX_MFRACTAL: - case TEX_FBM: - retval= mg_mFractalOrfBmTex(tex, tmpvec, texres); - break; - case TEX_RIDGEDMF: - case TEX_HYBRIDMF: - retval= mg_ridgedOrHybridMFTex(tex, tmpvec, texres); - break; - case TEX_HTERRAIN: - retval= mg_HTerrainTex(tex, tmpvec, texres); - break; + else { + switch (tex->type) { + case 0: + texres->tin= 0.0f; + return 0; + case TEX_CLOUDS: + retval = clouds(tex, texvec, texres); + break; + case TEX_WOOD: + retval = wood(tex, texvec, texres); + break; + case TEX_MARBLE: + retval = marble(tex, texvec, texres); + break; + case TEX_MAGIC: + retval = magic(tex, texvec, texres); + break; + case TEX_BLEND: + retval = blend(tex, texvec, texres); + break; + case TEX_STUCCI: + retval = stucci(tex, texvec, texres); + break; + case TEX_NOISE: + retval = texnoise(tex, texres); + break; + case TEX_IMAGE: + if (osatex) retval = imagewraposa(tex, tex->ima, NULL, texvec, dxt, dyt, texres); + else retval = imagewrap(tex, tex->ima, NULL, texvec, texres); + BKE_image_tag_time(tex->ima); /* tag image as having being used */ + break; + case TEX_ENVMAP: + retval = envmaptex(tex, texvec, dxt, dyt, osatex, texres); + break; + case TEX_MUSGRAVE: + /* newnoise: musgrave types */ + + /* ton: added this, for Blender convention reason. + * artificer: added the use of tmpvec to avoid scaling texvec + */ + copy_v3_v3(tmpvec, texvec); + mul_v3_fl(tmpvec, 1.0f / tex->noisesize); + + switch (tex->stype) { + case TEX_MFRACTAL: + case TEX_FBM: + retval = mg_mFractalOrfBmTex(tex, tmpvec, texres); + break; + case TEX_RIDGEDMF: + case TEX_HYBRIDMF: + retval = mg_ridgedOrHybridMFTex(tex, tmpvec, texres); + break; + case TEX_HTERRAIN: + retval = mg_HTerrainTex(tex, tmpvec, texres); + break; + } + break; + /* newnoise: voronoi type */ + case TEX_VORONOI: + /* ton: added this, for Blender convention reason. + * artificer: added the use of tmpvec to avoid scaling texvec + */ + copy_v3_v3(tmpvec, texvec); + mul_v3_fl(tmpvec, 1.0f / tex->noisesize); + + retval = voronoiTex(tex, tmpvec, texres); + break; + case TEX_DISTNOISE: + /* ton: added this, for Blender convention reason. + * artificer: added the use of tmpvec to avoid scaling texvec + */ + copy_v3_v3(tmpvec, texvec); + mul_v3_fl(tmpvec, 1.0f / tex->noisesize); + + retval = mg_distNoiseTex(tex, tmpvec, texres); + break; + case TEX_POINTDENSITY: + retval = pointdensitytex(tex, texvec, texres); + break; + case TEX_VOXELDATA: + retval = voxeldatatex(tex, texvec, texres); + break; + case TEX_OCEAN: + retval = ocean_texture(tex, texvec, texres); + break; } - break; - /* newnoise: voronoi type */ - case TEX_VORONOI: - /* ton: added this, for Blender convention reason. - * artificer: added the use of tmpvec to avoid scaling texvec - */ - copy_v3_v3(tmpvec, texvec); - mul_v3_fl(tmpvec, 1.0f/tex->noisesize); - - retval= voronoiTex(tex, tmpvec, texres); - break; - case TEX_DISTNOISE: - /* ton: added this, for Blender convention reason. - * artificer: added the use of tmpvec to avoid scaling texvec - */ - copy_v3_v3(tmpvec, texvec); - mul_v3_fl(tmpvec, 1.0f/tex->noisesize); - - retval= mg_distNoiseTex(tex, tmpvec, texres); - break; - case TEX_POINTDENSITY: - retval= pointdensitytex(tex, texvec, texres); - break; - case TEX_VOXELDATA: - retval= voxeldatatex(tex, texvec, texres); - break; - case TEX_OCEAN: - retval= ocean_texture(tex, texvec, texres); - break; } if (tex->flag & TEX_COLORBAND) { float col[4]; if (do_colorband(tex->coba, texres->tin, col)) { - texres->talpha= 1; + texres->talpha = TRUE; texres->tr= col[0]; texres->tg= col[1]; texres->tb= col[2]; @@ -1205,7 +1213,8 @@ static int multitex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, } /* this is called from the shader and texture nodes */ -int multitex_nodes(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres, short thread, short which_output, ShadeInput *shi, MTex *mtex) +int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, + const short thread, short which_output, ShadeInput *shi, MTex *mtex) { if (tex==NULL) { memset(texres, 0, sizeof(TexResult)); @@ -1221,13 +1230,13 @@ int multitex_nodes(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, if (mtex) { /* we have mtex, use it for 2d mapping images only */ do_2d_mapping(mtex, texvec, shi->vlr, shi->facenor, dxt, dyt); - rgbnor= multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output); + rgbnor = multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output); if (mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) { ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); /* don't linearize float buffers, assumed to be linear */ - if (ibuf && !(ibuf->rect_float)) + if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace); } } @@ -1253,16 +1262,25 @@ int multitex_nodes(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, do_2d_mapping(&localmtex, texvec_l, NULL, NULL, dxt_l, dyt_l); rgbnor= multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres, thread, which_output); + + { + ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); + + /* don't linearize float buffers, assumed to be linear */ + if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) + IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace); + } } return rgbnor; } - else + else { return multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output); + } } /* this is called for surface shading */ -static int multitex_mtex(ShadeInput *shi, MTex *mtex, float *texvec, float *dxt, float *dyt, TexResult *texres) +static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt[3], float dyt[3], TexResult *texres) { Tex *tex = mtex->tex; @@ -1279,13 +1297,13 @@ static int multitex_mtex(ShadeInput *shi, MTex *mtex, float *texvec, float *dxt, /* Warning, if the texres's values are not declared zero, check the return value to be sure * the color values are set before using the r/g/b values, otherwise you may use uninitialized values - Campbell */ -int multitex_ext(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres) +int multitex_ext(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres) { return multitex_nodes(tex, texvec, dxt, dyt, osatex, texres, 0, 0, NULL, NULL); } /* extern-tex doesn't support nodes (ntreeBeginExec() can't be called when rendering is going on) */ -int multitex_ext_safe(Tex *tex, float *texvec, TexResult *texres) +int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres) { int use_nodes= tex->use_nodes, retval; @@ -1510,7 +1528,8 @@ float texture_value_blend(float tex, float out, float fact, float facg, int blen return in; } -static void texco_mapping(ShadeInput* shi, Tex* tex, MTex* mtex, float* co, float* dx, float* dy, float* texvec, float* dxt, float* dyt) +static void texco_mapping(ShadeInput* shi, Tex* tex, MTex* mtex, + const float co[3], const float dx[3], const float dy[3], float texvec[3], float dxt[3], float dyt[3]) { /* new: first swap coords, then map, then trans/scale */ if (tex->type == TEX_IMAGE) { @@ -1542,10 +1561,10 @@ static void texco_mapping(ShadeInput* shi, Tex* tex, MTex* mtex, float* co, floa texvec[0] = mtex->size[0]*(texvec[0] - 0.5f) + mtex->ofs[0] + 0.5f; texvec[1] = mtex->size[1]*(texvec[1] - 0.5f) + mtex->ofs[1] + 0.5f; if (shi->osatex) { - dxt[0] = mtex->size[0]*dxt[0]; - dxt[1] = mtex->size[1]*dxt[1]; - dyt[0] = mtex->size[0]*dyt[0]; - dyt[1] = mtex->size[1]*dyt[1]; + dxt[0] = mtex->size[0] * dxt[0]; + dxt[1] = mtex->size[1] * dxt[1]; + dyt[0] = mtex->size[0] * dyt[0]; + dyt[1] = mtex->size[1] * dyt[1]; } /* problem: repeat-mirror is not a 'repeat' but 'extend' in imagetexture.c */ @@ -1675,7 +1694,8 @@ static void compatible_bump_uv_derivs(CompatibleBump *compat_bump, ShadeInput *s } } -static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres, float Tnor, float *co, float *dx, float *dy, float *texvec, float *dxt, float *dyt) +static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres, + float Tnor, const float co[3], const float dx[3], const float dy[3], float texvec[3], float dxt[3], float dyt[3]) { TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL}; /* temp TexResult */ float tco[3], texv[3], cd, ud, vd, du, dv, idu, idv; @@ -1733,7 +1753,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, if (mtex->texco == TEXCO_UV) { /* for the uv case, use the same value for both du/dv, * since individually scaling the normal derivatives makes them useless... */ - du = minf(du, dv); + du = min_ff(du, dv); idu = (du < 1e-5f) ? bf : (bf/du); /* +u val */ @@ -1831,7 +1851,9 @@ static void ntap_bump_init(NTapBump *ntap_bump) memset(ntap_bump, 0, sizeof(*ntap_bump)); } -static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres, float Tnor, float *co, float *dx, float *dy, float *texvec, float *dxt, float *dyt) +static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres, + float Tnor, const float co[3], const float dx[3], const float dy[3], + float texvec[3], float dxt[3], float dyt[3]) { TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL}; /* temp TexResult */ @@ -2153,9 +2175,6 @@ void do_material_tex(ShadeInput *shi, Render *re) co= shi->lo; dx= shi->dxlo; dy= shi->dylo; } } - else if (mtex->texco==TEXCO_STICKY) { - co= shi->sticky; dx= shi->dxsticky; dy= shi->dysticky; - } else if (mtex->texco==TEXCO_OBJECT) { Object *ob= mtex->object; if (ob) { @@ -2260,11 +2279,11 @@ void do_material_tex(ShadeInput *shi, Render *re) if (texres.nor && !((tex->type==TEX_IMAGE) && (tex->imaflag & TEX_NORMALMAP))) { if (use_compat_bump) { rgbnor = compatible_bump_compute(&compat_bump, shi, mtex, tex, - &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt); + &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt); } else if (use_ntap_bump) { rgbnor = ntap_bump_compute(&ntap_bump, shi, mtex, tex, - &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt); + &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt); } else { texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt); @@ -2380,7 +2399,7 @@ void do_material_tex(ShadeInput *shi, Render *re) ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser); /* don't linearize float buffers, assumed to be linear */ - if (ibuf && !(ibuf->rect_float)) + if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace); } @@ -2448,7 +2467,9 @@ void do_material_tex(ShadeInput *shi, Render *re) copy_v3_v3(nor, texres.nor); - if (mtex->normapspace == MTEX_NSPACE_CAMERA); + if (mtex->normapspace == MTEX_NSPACE_CAMERA) { + /* pass */ + } else if (mtex->normapspace == MTEX_NSPACE_WORLD) { mul_mat3_m4_v3(re->viewmat, nor); } @@ -2651,9 +2672,16 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_ copy_v3_v3(co, xyz); if (mtex->texflag & MTEX_OB_DUPLI_ORIG) { if (shi->obi && shi->obi->duplitexmat) - mul_m4_v3(shi->obi->duplitexmat, co); - } + mul_m4_v3(shi->obi->duplitexmat, co); + } mul_m4_v3(ob->imat_ren, co); + + if (mtex->texflag & MTEX_MAPTO_BOUNDS && ob->bb) { + /* use bb vec[0] as min and bb vec[6] as max */ + co[0] = (co[0] - ob->bb->vec[0][0]) / (ob->bb->vec[6][0]-ob->bb->vec[0][0]) * 2.0f - 1.0f; + co[1] = (co[1] - ob->bb->vec[0][1]) / (ob->bb->vec[6][1]-ob->bb->vec[0][1]) * 2.0f - 1.0f; + co[2] = (co[2] - ob->bb->vec[0][2]) / (ob->bb->vec[6][2]-ob->bb->vec[0][2]) * 2.0f - 1.0f; + } } } /* not really orco, but 'local' */ @@ -2666,6 +2694,13 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_ Object *ob= shi->obi->ob; copy_v3_v3(co, xyz); mul_m4_v3(ob->imat_ren, co); + + if (mtex->texflag & MTEX_MAPTO_BOUNDS && ob->bb) { + /* use bb vec[0] as min and bb vec[6] as max */ + co[0] = (co[0] - ob->bb->vec[0][0]) / (ob->bb->vec[6][0]-ob->bb->vec[0][0]) * 2.0f - 1.0f; + co[1] = (co[1] - ob->bb->vec[0][1]) / (ob->bb->vec[6][1]-ob->bb->vec[0][1]) * 2.0f - 1.0f; + co[2] = (co[2] - ob->bb->vec[0][2]) / (ob->bb->vec[6][2]-ob->bb->vec[0][2]) * 2.0f - 1.0f; + } } } else if (mtex->texco==TEXCO_GLOB) { @@ -2732,6 +2767,12 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_ if ((rgbnor & TEX_RGB) == 0) { copy_v3_v3(tcol, &mtex->r); } + else if (mtex->mapto & MAP_DENSITY) { + copy_v3_v3(tcol, &texres.tr); + if (texres.talpha) { + texres.tin = stencilTin; + } + } else { copy_v3_v3(tcol, &texres.tr); if (texres.talpha) { @@ -2760,11 +2801,9 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_ /* stencil maps on the texture control slider, not texture intensity value */ /* convert RGB to intensity if intensity info isn't provided */ - if (!(rgbnor & TEX_INT)) { - if (rgbnor & TEX_RGB) { - if (texres.talpha) texres.tin = texres.ta; - else texres.tin = rgb_to_grayscale(&texres.tr); - } + if (rgbnor & TEX_RGB) { + if (texres.talpha) texres.tin = texres.ta; + else texres.tin = rgb_to_grayscale(&texres.tr); } if ((mapto_flag & MAP_EMISSION) && (mtex->mapto & MAP_EMISSION)) { @@ -2892,7 +2931,7 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4]) ImBuf *ibuf = BKE_image_get_ibuf(ima, &mtex->tex->iuser); /* don't linearize float buffers, assumed to be linear */ - if (ibuf && !(ibuf->rect_float)) + if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace); } @@ -2927,10 +2966,14 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4]) } if (mtex->mapto & MAP_ALPHA) { if (rgb) { - if (texres.talpha) texres.tin= texres.ta; - else texres.tin = rgb_to_bw(&texres.tr); + if (texres.talpha) { + texres.tin = texres.ta; + } + else { + texres.tin = rgb_to_bw(&texres.tr); + } } - + col_r[3]*= texres.tin; } } @@ -3043,7 +3086,7 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h break; } - /* placement */ + /* placement */ if (mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]); else texvec[0]= mtex->size[0]*(mtex->ofs[0]); @@ -3107,7 +3150,7 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser); /* don't linearize float buffers, assumed to be linear */ - if (ibuf && !(ibuf->rect_float)) + if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace); } @@ -3206,7 +3249,7 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r } co= tempvec; - dx= dxt; dy= dyt; + dx= dxt; dy= dyt; if (shi->osatex) { copy_v3_v3(dxt, shi->dxlv); copy_v3_v3(dyt, shi->dylv); @@ -3321,7 +3364,7 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser); /* don't linearize float buffers, assumed to be linear */ - if (ibuf && !(ibuf->rect_float)) + if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace); } diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 97a05e6a4c9..9fe2620747c 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -59,6 +59,7 @@ #include "BKE_main.h" #include "BKE_node.h" #include "BKE_texture.h" +#include "BKE_scene.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -93,7 +94,7 @@ extern struct Render R; /* x and y are current pixels in rect to be rendered */ /* do not normalize! */ -void calc_view_vector(float *view, float x, float y) +void calc_view_vector(float view[3], float x, float y) { view[2]= -ABS(R.clipsta); @@ -109,10 +110,10 @@ void calc_view_vector(float *view, float x, float y) /* move x and y to real viewplane coords */ x = (x / (float)R.winx); - view[0] = R.viewplane.xmin + x * BLI_RCT_SIZE_X(&R.viewplane); + view[0] = R.viewplane.xmin + x * BLI_rctf_size_x(&R.viewplane); y = (y / (float)R.winy); - view[1] = R.viewplane.ymin + y * BLI_RCT_SIZE_Y(&R.viewplane); + view[1] = R.viewplane.ymin + y * BLI_rctf_size_y(&R.viewplane); // if (R.flag & R_SEC_FIELD) { // if (R.r.mode & R_ODDFIELD) view[1]= (y+R.ystart)*R.ycor; @@ -184,7 +185,8 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in fullsample= (totsample > 1); amount= 0; - accol[0]=accol[1]=accol[2]=accol[3]= 0.0f; + accol[0] = accol[1] = accol[2] = accol[3]= 0.0f; + col[0] = col[1] = col[2] = col[3]= 0.0f; flarec= har->flarec; while (ps) { @@ -271,23 +273,33 @@ static void halo_tile(RenderPart *pa, RenderLayer *rl) har= R.sortedhalos[a]; /* layer test, clip halo with y */ - if ((har->lay & lay)==0); - else if (testrect.ymin > har->maxy); - else if (testrect.ymax < har->miny); + if ((har->lay & lay) == 0) { + /* pass */ + } + else if (testrect.ymin > har->maxy) { + /* pass */ + } + else if (testrect.ymax < har->miny) { + /* pass */ + } else { minx= floor(har->xs-har->rad); maxx= ceil(har->xs+har->rad); - if (testrect.xmin > maxx); - else if (testrect.xmax < minx); + if (testrect.xmin > maxx) { + /* pass */ + } + else if (testrect.xmax < minx) { + /* pass */ + } else { - minx= MAX2(minx, testrect.xmin); - maxx= MIN2(maxx, testrect.xmax); + minx = max_ii(minx, testrect.xmin); + maxx = min_ii(maxx, testrect.xmax); - miny= MAX2(har->miny, testrect.ymin); - maxy= MIN2(har->maxy, testrect.ymax); + miny = max_ii(har->miny, testrect.ymin); + maxy = min_ii(har->maxy, testrect.ymax); for (y=miny; yrectx + (minx - disprect.xmin); @@ -660,7 +672,7 @@ int get_sample_layers(RenderPart *pa, RenderLayer *rl, RenderLayer **rlpp) RenderResult *rr= BLI_findlink(&pa->fullresult, sample); rlpp[sample]= BLI_findlink(&rr->layers, nr); - } + } return R.osa; } else { @@ -703,7 +715,7 @@ static void sky_tile(RenderPart *pa, RenderLayer *rl) addAlphaUnderFloat(pass, col); } } - } + } } if (y&1) @@ -761,8 +773,8 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl) if (*zrect >= 9.9e10f || rgbrect[3]==0.0f) { continue; } - - if ((lar->sunsky->effect_type & LA_SUN_EFFECT_AP)) { + + if ((lar->sunsky->effect_type & LA_SUN_EFFECT_AP)) { float tmp_rgb[3]; /* skip if worldspace lamp vector is below horizon */ @@ -917,7 +929,7 @@ static void addps(ListBase *lb, intptr_t *rd, int obi, int facenr, int z, int ma PixStrMain *psm; PixStr *ps, *last= NULL; - if (*rd) { + if (*rd) { ps= (PixStr *)(*rd); while (ps) { @@ -980,7 +992,9 @@ static void convert_to_key_alpha(RenderPart *pa, RenderLayer *rl) float *rectf= rlpp[sample]->rectf; for (y= pa->rectx*pa->recty; y>0; y--, rectf+=4) { - if (rectf[3] >= 1.0f); + if (rectf[3] >= 1.0f) { + /* pass */ + } else if (rectf[3] > 0.0f) { rectf[0] /= rectf[3]; rectf[1] /= rectf[3]; @@ -990,6 +1004,30 @@ static void convert_to_key_alpha(RenderPart *pa, RenderLayer *rl) } } +/* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */ +static void clamp_alpha_rgb_range(RenderPart *pa, RenderLayer *rl) +{ + RenderLayer *rlpp[RE_MAX_OSA]; + int y, sample, totsample; + + totsample= get_sample_layers(pa, rl, rlpp); + + /* not for full sample, there we clamp after compositing */ + if (totsample > 1) + return; + + for (sample= 0; samplerectf; + + for (y= pa->rectx*pa->recty; y>0; y--, rectf+=4) { + rectf[0] = MAX2(rectf[0], 0.0f); + rectf[1] = MAX2(rectf[1], 0.0f); + rectf[2] = MAX2(rectf[2], 0.0f); + CLAMP(rectf[3], 0.0f, 1.0f); + } + } +} + /* adds only alpha values */ static void edge_enhance_tile(RenderPart *pa, float *rectf, int *rectz) { @@ -1270,6 +1308,9 @@ void zbufshadeDA_tile(RenderPart *pa) if (rl->passflag & SCE_PASS_VECTOR) reset_sky_speed(pa, rl); + + /* clamp alpha to 0..1 range, can go outside due to filter */ + clamp_alpha_rgb_range(pa, rl); /* de-premul alpha */ if (R.r.alphamode & R_ALPHAKEY) @@ -1542,7 +1583,7 @@ static void shade_sample_sss(ShadeSample *ssamp, Material *mat, ObjectInstanceRe copy_v3_v3(shi->facenor, nor); shade_input_set_viewco(shi, x, y, sx, sy, z); - *area = minf(len_v3(shi->dxco) * len_v3(shi->dyco), 2.0f * orthoarea); + *area = min_ff(len_v3(shi->dxco) * len_v3(shi->dyco), 2.0f * orthoarea); shade_input_set_uv(shi); shade_input_set_normals(shi); @@ -1806,16 +1847,23 @@ static void renderhalo_post(RenderResult *rr, float *rectf, HaloRen *har) /* pos har->miny= miny= haloys - har->rad/R.ycor; har->maxy= maxy= haloys + har->rad/R.ycor; - if (maxy<0); - else if (rr->rectyrecty < miny) { + /* pass */ + } else { - minx= floor(haloxs-har->rad); - maxx= ceil(haloxs+har->rad); + minx = floor(haloxs - har->rad); + maxx = ceil(haloxs + har->rad); - if (maxx<0); - else if (rr->rectxrectx < minx) { + /* pass */ + } else { - if (minx<0) minx= 0; if (maxx>=rr->rectx) maxx= rr->rectx-1; if (miny<0) miny= 0; @@ -1965,7 +2013,7 @@ void add_halo_flare(Render *re) re->display_draw(re->ddh, rr, NULL); } - R.r.mode= mode; + R.r.mode= mode; } /* ************************* bake ************************ */ @@ -2072,7 +2120,9 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua copy_v3_v3(nor, shi->vn); - if (R.r.bake_normal_space == R_BAKE_SPACE_CAMERA); + if (R.r.bake_normal_space == R_BAKE_SPACE_CAMERA) { + /* pass */ + } else if (R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) { float mat[3][3], imat[3][3]; @@ -2175,7 +2225,8 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua float rgb[3]; copy_v3_v3(rgb, shr.combined); - IMB_colormanagement_scene_linear_to_colorspace_v3(rgb, bs->rect_colorspace); + if (R.scene_color_manage) + IMB_colormanagement_scene_linear_to_colorspace_v3(rgb, bs->rect_colorspace); rgb_float_to_uchar(col, rgb); } else { @@ -2325,10 +2376,28 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) v2= vlr->v2->co; v3= vlr->v3->co; } + + l= 1.0f-u-v; + + /* shrink barycentric coordinates inwards slightly to avoid some issues + * where baking selected to active might just miss the other face at the + * near the edge of a face */ + if (bs->actob) { + const float eps = 1.0f - 1e-4f; + float invsum; + + u = (u - 0.5f)*eps + 0.5f; + v = (v - 0.5f)*eps + 0.5f; + l = (l - 0.5f)*eps + 0.5f; + + invsum = 1.0f/(u + v + l); + + u *= invsum; + v *= invsum; + l *= invsum; + } /* renderco */ - l= 1.0f-u-v; - shi->co[0]= l*v3[0]+u*v1[0]+v*v2[0]; shi->co[1]= l*v3[1]+u*v1[1]+v*v2[1]; shi->co[2]= l*v3[2]+u*v1[2]+v*v2[2]; @@ -2424,7 +2493,7 @@ static int get_next_bake_face(BakeShade *bs) return 0; } - BLI_lock_thread(LOCK_CUSTOM1); + BLI_lock_thread(LOCK_CUSTOM1); for (; obi; obi=obi->next, v=0) { obr= obi->obr; @@ -2465,11 +2534,13 @@ static int get_next_bake_face(BakeShade *bs) /* clear image */ if (R.r.bake_flag & R_BAKE_CLEAR) IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid); - + /* might be read by UI to set active image for display */ R.bakebuf= ima; - } - + } + + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + bs->obi= obi; bs->vlr= vlr; @@ -2505,7 +2576,7 @@ static void shade_tface(BakeShade *bs) /* note, these calls only free/fill contents of zspan struct, not zspan itself */ zbuf_free_span(bs->zspan); zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y, R.clipcrop); - } + } bs->rectx= bs->ibuf->x; bs->recty= bs->ibuf->y; @@ -2603,6 +2674,8 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up Image *ima; int a, vdone = FALSE, use_mask = FALSE, result = BAKE_RESULT_OK; + re->scene_color_manage = BKE_scene_check_color_management_enabled(re->scene); + /* initialize render global */ R= *re; R.bakebuf= NULL; @@ -2685,7 +2758,6 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, re->r.bake_filter); ibuf->userflags |= IB_BITMAPDIRTY; - if (ibuf->rect_float) IMB_rect_from_float(ibuf); } } diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index db045284d5b..7a7602dcce2 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -97,13 +97,10 @@ * the index */ /* NOTE! the hardcoded table size 256 is used still in code for going quickly over vertices/faces */ - -#define RE_STICKY_ELEMS 2 #define RE_STRESS_ELEMS 1 #define RE_RAD_ELEMS 4 #define RE_STRAND_ELEMS 1 #define RE_TANGENT_ELEMS 3 -#define RE_STRESS_ELEMS 1 #define RE_WINSPEED_ELEMS 4 #define RE_MTFACE_ELEMS 1 #define RE_MCOL_ELEMS 4 @@ -114,21 +111,6 @@ #define RE_FACE_ELEMS 1 #define RE_NMAP_TANGENT_ELEMS 16 -float *RE_vertren_get_sticky(ObjectRen *obr, VertRen *ver, int verify) -{ - float *sticky; - int nr= ver->index>>8; - - sticky= obr->vertnodes[nr].sticky; - if (sticky==NULL) { - if (verify) - sticky= obr->vertnodes[nr].sticky= MEM_mallocN(256*RE_STICKY_ELEMS*sizeof(float), "sticky table"); - else - return NULL; - } - return sticky + (ver->index & 255)*RE_STICKY_ELEMS; -} - float *RE_vertren_get_stress(ObjectRen *obr, VertRen *ver, int verify) { float *stress; @@ -218,12 +200,7 @@ VertRen *RE_vertren_copy(ObjectRen *obr, VertRen *ver) *v1= *ver; v1->index= index; - - fp1= RE_vertren_get_sticky(obr, ver, 0); - if (fp1) { - fp2= RE_vertren_get_sticky(obr, v1, 1); - memcpy(fp2, fp1, RE_STICKY_ELEMS*sizeof(float)); - } + fp1= RE_vertren_get_stress(obr, ver, 0); if (fp1) { fp2= RE_vertren_get_stress(obr, v1, 1); @@ -267,7 +244,7 @@ VertRen *RE_findOrAddVert(ObjectRen *obr, int nr) memset(obr->vertnodes+obr->vertnodeslen, 0, TABLEINITSIZE*sizeof(VertTableNode)); obr->vertnodeslen+=TABLEINITSIZE; - if (temp) MEM_freeN(temp); + if (temp) MEM_freeN(temp); } v= obr->vertnodes[a].vert; @@ -510,7 +487,7 @@ VlakRen *RE_findOrAddVlak(ObjectRen *obr, int nr) memset(obr->vlaknodes+obr->vlaknodeslen, 0, TABLEINITSIZE*sizeof(VlakTableNode)); obr->vlaknodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/ - if (temp) MEM_freeN(temp); + if (temp) MEM_freeN(temp); } v= obr->vlaknodes[a].vlak; @@ -681,7 +658,7 @@ StrandRen *RE_findOrAddStrand(ObjectRen *obr, int nr) memset(obr->strandnodes+obr->strandnodeslen, 0, TABLEINITSIZE*sizeof(StrandTableNode)); obr->strandnodeslen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/ - if (temp) MEM_freeN(temp); + if (temp) MEM_freeN(temp); } v= obr->strandnodes[a].strand; @@ -740,8 +717,6 @@ void free_renderdata_vertnodes(VertTableNode *vertnodes) if (vertnodes[a].rad) MEM_freeN(vertnodes[a].rad); - if (vertnodes[a].sticky) - MEM_freeN(vertnodes[a].sticky); if (vertnodes[a].strand) MEM_freeN(vertnodes[a].strand); if (vertnodes[a].tangent) @@ -917,7 +892,7 @@ HaloRen *RE_findOrAddHalo(ObjectRen *obr, int nr) if (temp) memcpy(obr->bloha, temp, obr->blohalen*sizeof(void*)); memset(&(obr->bloha[obr->blohalen]), 0, TABLEINITSIZE*sizeof(void*)); obr->blohalen+=TABLEINITSIZE; /*Does this really need to be power of 2?*/ - if (temp) MEM_freeN(temp); + if (temp) MEM_freeN(temp); } h= obr->bloha[a]; @@ -1001,10 +976,13 @@ HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma, if (ma->mtex[0]) { - if ( (ma->mode & MA_HALOTEX) ) har->tex= 1; - else if (har->mat->septex & (1<<0)); /* only 1 level textures */ + if (ma->mode & MA_HALOTEX) { + har->tex = 1; + } + else if (har->mat->septex & (1 << 0)) { + /* only 1 level textures */ + } else { - mtex= ma->mtex[0]; copy_v3_v3(texvec, vec); @@ -1206,6 +1184,7 @@ static int panotestclip(Render *re, int do_pano, float *v) /* to be used for halos en infos */ float abs4; short c=0; + int xparts = (re->rectx + re->partx - 1) / re->partx; if (do_pano == FALSE) { return testclip(v); @@ -1219,7 +1198,7 @@ static int panotestclip(Render *re, int do_pano, float *v) if ( v[1]>abs4) c+=4; else if ( v[1]< -abs4) c+=8; - abs4*= re->xparts; + abs4*= xparts; if ( v[0]>abs4) c+=2; else if ( v[0]< -abs4) c+=1; @@ -1378,40 +1357,42 @@ void RE_makeRenderInstances(Render *re) re->instancetable= newlist; } -int clip_render_object(float boundbox[][3], float *bounds, float winmat[][4]) +int clip_render_object(float boundbox[][3], float bounds[4], float winmat[][4]) { float mat[4][4], vec[4]; - int a, fl, flag= -1; + int a, fl, flag = -1; copy_m4_m4(mat, winmat); - for (a=0; a<8; a++) { + for (a=0; a < 8; a++) { vec[0]= (a & 1)? boundbox[0][0]: boundbox[1][0]; vec[1]= (a & 2)? boundbox[0][1]: boundbox[1][1]; vec[2]= (a & 4)? boundbox[0][2]: boundbox[1][2]; vec[3]= 1.0; mul_m4_v4(mat, vec); - fl= 0; + fl = 0; if (bounds) { - if (vec[0] < bounds[0]*vec[3]) fl |= 1; - else if (vec[0] > bounds[1]*vec[3]) fl |= 2; + if (vec[0] < bounds[0] * vec[3]) fl |= 1; + else if (vec[0] > bounds[1] * vec[3]) fl |= 2; - if (vec[1] > bounds[3]*vec[3]) fl |= 4; - else if (vec[1]< bounds[2]*vec[3]) fl |= 8; + if (vec[1] > bounds[3] * vec[3]) fl |= 4; + else if (vec[1] < bounds[2] * vec[3]) fl |= 8; } else { - if (vec[0] < -vec[3]) fl |= 1; - else if (vec[0] > vec[3]) fl |= 2; + if (vec[0] < -vec[3]) fl |= 1; + else if (vec[0] > vec[3]) fl |= 2; - if (vec[1] > vec[3]) fl |= 4; + if (vec[1] > vec[3]) fl |= 4; else if (vec[1] < -vec[3]) fl |= 8; } - if (vec[2] < -vec[3]) fl |= 16; - else if (vec[2] > vec[3]) fl |= 32; + if (vec[2] < -vec[3]) fl |= 16; + else if (vec[2] > vec[3]) fl |= 32; flag &= fl; - if (flag==0) return 0; + if (flag == 0) { + return 0; + } } return flag; diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c index 2d7a64bad04..c37f48bc329 100644 --- a/source/blender/render/intern/source/shadbuf.c +++ b/source/blender/render/intern/source/shadbuf.c @@ -72,6 +72,9 @@ # define ACOMP 3 #endif +#define RCT_SIZE_X(rct) ((rct)->xmax - (rct)->xmin) +#define RCT_SIZE_Y(rct) ((rct)->ymax - (rct)->ymin) + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ /* only to be used here in this file, it's for speed */ @@ -86,7 +89,7 @@ extern struct Render R; static void copy_to_ztile(int *rectz, int size, int x1, int y1, int tile, char *r1) { - int len4, *rz; + int len4, *rz; int x2, y2; x2= x1+tile; @@ -156,9 +159,9 @@ static void make_jitter_weight_tab(Render *re, ShadBuf *shb, short filtertype) for (jit= shb->jit, a=0; aweight[a]= 0.71f - sqrt(jit[0]*jit[0] + jit[1]*jit[1]); + shb->weight[a] = 0.71f - sqrtf(jit[0] * jit[0] + jit[1] * jit[1]); else if (filtertype==LA_SHADBUF_GAUSS) - shb->weight[a]= RE_filter_value(R_FILTER_GAUSS, 1.8f*sqrt(jit[0]*jit[0] + jit[1]*jit[1])); + shb->weight[a] = RE_filter_value(R_FILTER_GAUSS, 1.8f * sqrtf(jit[0] * jit[0] + jit[1] * jit[1])); else shb->weight[a]= 1.0f; @@ -214,15 +217,15 @@ static int compress_deepsamples(DeepSample *dsample, int tot, float epsilon) if (ds->z == newds->z) { /* still in same z position, simply check * visibility difference against epsilon */ - if (!(fabs(newds->v - ds->v) <= epsilon)) { + if (!(fabsf(newds->v - ds->v) <= epsilon)) { break; } } else { /* compute slopes */ - div= (double)0x7FFFFFFF/((double)ds->z - (double)newds->z); - min= ((ds->v - epsilon) - newds->v)*div; - max= ((ds->v + epsilon) - newds->v)*div; + div= (double)0x7FFFFFFF / ((double)ds->z - (double)newds->z); + min= (double)((ds->v - epsilon) - newds->v) * div; + max= (double)((ds->v + epsilon) - newds->v) * div; /* adapt existing slopes */ if (first) { @@ -261,8 +264,8 @@ static int compress_deepsamples(DeepSample *dsample, int tot, float epsilon) } else { /* compute visibility at center between slopes at z */ - slope= (slopemin+slopemax)*0.5f; - v= newds->v + slope*((z - newds->z)/(double)0x7FFFFFFF); + slope = (slopemin + slopemax) * 0.5; + v = (double)newds->v + slope * ((double)(z - newds->z) / (double)0x7FFFFFFF); } newds++; @@ -525,21 +528,21 @@ static void compress_shadowbuf(ShadBuf *shb, int *rectz, int square) for (y=0; y(float)(a+12)) { /* 12, tested with a onlyshadow lamp */ a= 256; verg= 0; /* 0x80000000; */ /* 0x7FFFFFFF; */ rz1= (&verg)+1; - } + } else { copy_to_ztile(rectz, size, x, y, 16, rcline); rz1= (int *)rcline; @@ -666,8 +669,8 @@ static void shadowbuf_autoclip(Render *re, LampRen *lar) clipflag[vlr->v2->index]= 1; clipflag[vlr->v3->index]= 1; if (vlr->v4) clipflag[vlr->v4->index]= 1; - } - } + } + } /* calculate min and max */ for (a=0; a< obr->totvert;a++) { @@ -775,7 +778,7 @@ void makeshadowbuf(Render *re, LampRen *lar) * transforming from observer view to lamp view, including lamp window matrix */ angle= saacos(lar->spotsi); - temp= 0.5f*shb->size*cos(angle)/sin(angle); + temp = 0.5f * shb->size * cosf(angle) / sinf(angle); shb->pixsize= (shb->d)/temp; wsize= shb->pixsize*(shb->size/2.0f); @@ -853,10 +856,10 @@ void threaded_makeshadowbufs(Render *re) if (lar->shb) totthread++; - totthread= MIN2(totthread, re->r.threads); + totthread = min_ii(totthread, re->r.threads); } else - totthread= 1; /* preview render */ + totthread = 1; /* preview render */ if (totthread <= 1) { for (lar=re->lampren.first; lar; lar= lar->next) { @@ -1391,7 +1394,7 @@ float shadow_halo(LampRen *lar, const float p1[3], const float p2[3]) } } - labda = minf(labdax, labday); + labda = min_ff(labdax, labday); if (labda==labdao || labda>=1.0f) break; zf= zf1 + labda*(zf2-zf1); @@ -1506,7 +1509,7 @@ static void isb_bsp_split_init(ISBBranch *root, MemArena *mem, int level) root->divider[1]= 0.5f*(root->box.ymin+root->box.ymax); /* find best splitpoint */ - if (BLI_RCT_SIZE_X(&root->box) > BLI_RCT_SIZE_Y(&root->box)) + if (RCT_SIZE_X(&root->box) > RCT_SIZE_Y(&root->box)) i = root->index = 0; else i = root->index = 1; @@ -1551,7 +1554,7 @@ static void isb_bsp_split(ISBBranch *root, MemArena *mem) root->divider[1]/= BSPMAX_SAMPLE; /* find best splitpoint */ - if (BLI_RCT_SIZE_X(&root->box) > BLI_RCT_SIZE_Y(&root->box)) + if (RCT_SIZE_X(&root->box) > RCT_SIZE_Y(&root->box)) i = root->index = 0; else i = root->index = 1; @@ -1660,9 +1663,9 @@ static void bspface_init_strand(BSPFace *face) face->len= face->rc[0]*face->rc[0]+ face->rc[1]*face->rc[1]; - if (face->len!=0.0f) { - face->radline_end= face->radline/sqrt(face->len); - face->len= 1.0f/face->len; + if (face->len != 0.0f) { + face->radline_end = face->radline / sqrtf(face->len); + face->len = 1.0f / face->len; } } @@ -1864,7 +1867,7 @@ static void isb_bsp_recalc_box(ISBBranch *root) init_box(&root->box); for (a=root->totsamp-1; a>=0; a--) bound_boxf(&root->box, root->samples[a]->zco); - } + } } /* callback function for zbuf clip */ @@ -2037,7 +2040,7 @@ static void isb_bsp_fillfaces(Render *re, LampRen *lar, ISBBranch *root) if (vlr->v4) c4= testclip(hoco[3]); - /* ***** NO WIRE YET */ + /* ***** NO WIRE YET */ if (ma->material_type == MA_TYPE_WIRE) { if (vlr->v4) zbufclipwire(&zspan, i, a+1, vlr->ec, hoco[0], hoco[1], hoco[2], hoco[3], c1, c2, c3, c4); @@ -2184,7 +2187,7 @@ static int isb_add_samples(RenderPart *pa, ISBBranch *root, MemArena *memarena, } if (bsp_err) break; } - } + } MEM_freeN(xcos); MEM_freeN(ycos); @@ -2391,7 +2394,7 @@ static int isb_add_samples_transp(RenderPart *pa, ISBBranch *root, MemArena *mem } if (bsp_err) break; } - } + } MEM_freeN(xcos); MEM_freeN(ycos); diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index d1d2c66985e..db93a21de2d 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -44,6 +44,7 @@ #include "DNA_material_types.h" #include "BKE_colortools.h" +#include "BKE_scene.h" #include "BKE_node.h" @@ -86,12 +87,6 @@ extern struct Render R; * */ -#define VECADDISFAC(v1,v3,fac) { \ - *(v1 + 0) += *(v3 + 0) * (fac); \ - *(v1 + 1) += *(v3 + 1) * (fac); \ - *(v1 + 2) += *(v3 + 2) * (fac); \ -} (void)0 - /* initialize material variables in shadeinput, * doing inverse gamma correction where applicable */ void shade_input_init_material(ShadeInput *shi) @@ -120,13 +115,13 @@ void shade_material_loop(ShadeInput *shi, ShadeResult *shr) shi->depth--; /* a couple of passes */ - VECADDISFAC(shr->combined, shr_t.combined, fac); + madd_v3_v3fl(shr->combined, shr_t.combined, fac); if (shi->passflag & SCE_PASS_SPEC) - VECADDISFAC(shr->spec, shr_t.spec, fac); + madd_v3_v3fl(shr->spec, shr_t.spec, fac); if (shi->passflag & SCE_PASS_DIFFUSE) - VECADDISFAC(shr->diff, shr_t.diff, fac); + madd_v3_v3fl(shr->diff, shr_t.diff, fac); if (shi->passflag & SCE_PASS_SHADOW) - VECADDISFAC(shr->shad, shr_t.shad, fac); + madd_v3_v3fl(shr->shad, shr_t.shad, fac); negate_v3(shi->vn); negate_v3(shi->facenor); @@ -241,7 +236,7 @@ void vlr_set_uv_indices(VlakRen *vlr, int *i1, int *i2, int *i3) /* 1---2 1---2 0 = orig face, 1 = new face */ /* Update vert nums to point to correct verts of original face */ - if (vlr->flag & R_DIVIDE_24) { + if (vlr->flag & R_DIVIDE_24) { if (vlr->flag & R_FACE_SPLIT) { (*i1)++; (*i2)++; (*i3)++; } @@ -574,10 +569,6 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert shi->dywin[1] = 0.0f; } } - - if (texco & TEXCO_STICKY) { - /* not supported */ - } } if (shi->do_manage) { @@ -786,7 +777,7 @@ void shade_input_set_uv(ShadeInput *shi) CLAMP(shi->u, -2.0f, 1.0f); CLAMP(shi->v, -2.0f, 1.0f); } - } + } } void shade_input_set_normals(ShadeInput *shi) @@ -1124,50 +1115,113 @@ void shade_input_set_shade_texco(ShadeInput *shi) for (i = 0; (tface = RE_vlakren_get_tface(obr, vlr, i, &name, 0)); i++) { ShadeInputUV *suv = &shi->uv[i]; - float *uv1, *uv2, *uv3; + const float *uv1 = tface->uv[j1]; + const float *uv2 = tface->uv[j2]; + const float *uv3 = tface->uv[j3]; shi->totuv++; suv->name = name; - - uv1 = tface->uv[j1]; - uv2 = tface->uv[j2]; - uv3 = tface->uv[j3]; - suv->uv[0] = -1.0f + 2.0f * (l * uv3[0] - u * uv1[0] - v * uv2[0]); - suv->uv[1] = -1.0f + 2.0f * (l * uv3[1] - u * uv1[1] - v * uv2[1]); - suv->uv[2] = 0.0f; /* texture.c assumes there are 3 coords */ + if ((shi->mat->mapflag & MA_MAPFLAG_UVPROJECT) && (shi->depth == 0)) { + float x = shi->xs; + float y = shi->ys; - if (shi->osatex) { - float duv[2]; - - dl = shi->dx_u + shi->dx_v; - duv[0] = shi->dx_u; - duv[1] = shi->dx_v; + float s1[2] = {-1.0f + 2.0f * uv1[0], -1.0f + 2.0f * uv1[1]}; + float s2[2] = {-1.0f + 2.0f * uv2[0], -1.0f + 2.0f * uv2[1]}; + float s3[2] = {-1.0f + 2.0f * uv3[0], -1.0f + 2.0f * uv3[1]}; - suv->dxuv[0] = 2.0f * (dl * uv3[0] - duv[0] * uv1[0] - duv[1] * uv2[0]); - suv->dxuv[1] = 2.0f * (dl * uv3[1] - duv[0] * uv1[1] - duv[1] * uv2[1]); - dl = shi->dy_u + shi->dy_v; - duv[0] = shi->dy_u; - duv[1] = shi->dy_v; + float obwinmat[4][4], winmat[4][4], ho1[4], ho2[4], ho3[4]; + float Zmulx, Zmuly; + float hox, hoy, l, dl, u, v; + float s00, s01, s10, s11, detsh; - suv->dyuv[0] = 2.0f * (dl * uv3[0] - duv[0] * uv1[0] - duv[1] * uv2[0]); - suv->dyuv[1] = 2.0f * (dl * uv3[1] - duv[0] * uv1[1] - duv[1] * uv2[1]); - } + /* old globals, localized now */ + Zmulx = ((float)R.winx) / 2.0f; + Zmuly = ((float)R.winy) / 2.0f; - if ((mode & MA_FACETEXTURE) && i == obr->actmtface) { - if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) == 0) { - shi->vcol[0] = 1.0f; - shi->vcol[1] = 1.0f; - shi->vcol[2] = 1.0f; - shi->vcol[3] = 1.0f; - } - if (tface->tpage) { - render_realtime_texture(shi, tface->tpage); + zbuf_make_winmat(&R, winmat); + if (shi->obi->flag & R_TRANSFORMED) + mult_m4_m4m4(obwinmat, winmat, obi->mat); + else + copy_m4_m4(obwinmat, winmat); + + zbuf_render_project(obwinmat, v1->co, ho1); + zbuf_render_project(obwinmat, v2->co, ho2); + zbuf_render_project(obwinmat, v3->co, ho3); + + s00 = ho3[0] / ho3[3] - ho1[0] / ho1[3]; + s01 = ho3[1] / ho3[3] - ho1[1] / ho1[3]; + s10 = ho3[0] / ho3[3] - ho2[0] / ho2[3]; + s11 = ho3[1] / ho3[3] - ho2[1] / ho2[3]; + + detsh = s00 * s11 - s10 * s01; + detsh = (detsh != 0.0f) ? 1.0f / detsh : 0.0f; + s00 *= detsh; s01 *= detsh; + s10 *= detsh; s11 *= detsh; + + /* recalc u and v again */ + hox = x / Zmulx - 1.0f; + hoy = y / Zmuly - 1.0f; + u = (hox - ho3[0] / ho3[3]) * s11 - (hoy - ho3[1] / ho3[3]) * s10; + v = (hoy - ho3[1] / ho3[3]) * s00 - (hox - ho3[0] / ho3[3]) * s01; + l = 1.0f + u + v; + + suv->uv[0] = l * s3[0] - u * s1[0] - v * s2[0]; + suv->uv[1] = l * s3[1] - u * s1[1] - v * s2[1]; + suv->uv[2] = 0.0f; + + if (shi->osatex) { + float dxuv[2], dyuv[2]; + dxuv[0] = s11 / Zmulx; + dxuv[1] = -s01 / Zmulx; + dyuv[0] = -s10 / Zmuly; + dyuv[1] = s00 / Zmuly; + + dl = dxuv[0] + dxuv[1]; + suv->dxuv[0] = dl * s3[0] - dxuv[0] * s1[0] - dxuv[1] * s2[0]; + suv->dxuv[1] = dl * s3[1] - dxuv[0] * s1[1] - dxuv[1] * s2[1]; + dl = dyuv[0] + dyuv[1]; + suv->dyuv[0] = dl * s3[0] - dyuv[0] * s1[0] - dyuv[1] * s2[0]; + suv->dyuv[1] = dl * s3[1] - dyuv[0] * s1[1] - dyuv[1] * s2[1]; } } + else { + suv->uv[0] = -1.0f + 2.0f * (l * uv3[0] - u * uv1[0] - v * uv2[0]); + suv->uv[1] = -1.0f + 2.0f * (l * uv3[1] - u * uv1[1] - v * uv2[1]); + suv->uv[2] = 0.0f; /* texture.c assumes there are 3 coords */ + if (shi->osatex) { + float duv[2]; + + dl = shi->dx_u + shi->dx_v; + duv[0] = shi->dx_u; + duv[1] = shi->dx_v; + + suv->dxuv[0] = 2.0f * (dl * uv3[0] - duv[0] * uv1[0] - duv[1] * uv2[0]); + suv->dxuv[1] = 2.0f * (dl * uv3[1] - duv[0] * uv1[1] - duv[1] * uv2[1]); + + dl = shi->dy_u + shi->dy_v; + duv[0] = shi->dy_u; + duv[1] = shi->dy_v; + + suv->dyuv[0] = 2.0f * (dl * uv3[0] - duv[0] * uv1[0] - duv[1] * uv2[0]); + suv->dyuv[1] = 2.0f * (dl * uv3[1] - duv[0] * uv1[1] - duv[1] * uv2[1]); + } + + if ((mode & MA_FACETEXTURE) && i == obr->actmtface) { + if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) == 0) { + shi->vcol[0] = 1.0f; + shi->vcol[1] = 1.0f; + shi->vcol[2] = 1.0f; + shi->vcol[3] = 1.0f; + } + if (tface->tpage) { + render_realtime_texture(shi, tface->tpage); + } + } + } } shi->dupliuv[0] = -1.0f + 2.0f * obi->dupliuv[0]; @@ -1236,70 +1290,6 @@ void shade_input_set_shade_texco(ShadeInput *shi) shi->dywin[0] = shi->dywin[2] = 0.0f; } } - - if (texco & TEXCO_STICKY) { - float *s1, *s2, *s3; - - s1 = RE_vertren_get_sticky(obr, v1, 0); - s2 = RE_vertren_get_sticky(obr, v2, 0); - s3 = RE_vertren_get_sticky(obr, v3, 0); - - if (s1 && s2 && s3) { - float obwinmat[4][4], winmat[4][4], ho1[4], ho2[4], ho3[4]; - float Zmulx, Zmuly; - float hox, hoy, l, dl, u, v; - float s00, s01, s10, s11, detsh; - - /* old globals, localized now */ - Zmulx = ((float)R.winx) / 2.0f; Zmuly = ((float)R.winy) / 2.0f; - - zbuf_make_winmat(&R, winmat); - if (shi->obi->flag & R_TRANSFORMED) - mult_m4_m4m4(obwinmat, winmat, obi->mat); - else - copy_m4_m4(obwinmat, winmat); - - zbuf_render_project(obwinmat, v1->co, ho1); - zbuf_render_project(obwinmat, v2->co, ho2); - zbuf_render_project(obwinmat, v3->co, ho3); - - s00 = ho3[0] / ho3[3] - ho1[0] / ho1[3]; - s01 = ho3[1] / ho3[3] - ho1[1] / ho1[3]; - s10 = ho3[0] / ho3[3] - ho2[0] / ho2[3]; - s11 = ho3[1] / ho3[3] - ho2[1] / ho2[3]; - - detsh = s00 * s11 - s10 * s01; - detsh = (detsh != 0.0f) ? 1.0f / detsh : 0.0f; - s00 *= detsh; s01 *= detsh; - s10 *= detsh; s11 *= detsh; - - /* recalc u and v again */ - hox = x / Zmulx - 1.0f; - hoy = y / Zmuly - 1.0f; - u = (hox - ho3[0] / ho3[3]) * s11 - (hoy - ho3[1] / ho3[3]) * s10; - v = (hoy - ho3[1] / ho3[3]) * s00 - (hox - ho3[0] / ho3[3]) * s01; - l = 1.0f + u + v; - - shi->sticky[0] = l * s3[0] - u * s1[0] - v * s2[0]; - shi->sticky[1] = l * s3[1] - u * s1[1] - v * s2[1]; - shi->sticky[2] = 0.0f; - - if (shi->osatex) { - float dxuv[2], dyuv[2]; - dxuv[0] = s11 / Zmulx; - dxuv[1] = -s01 / Zmulx; - dyuv[0] = -s10 / Zmuly; - dyuv[1] = s00 / Zmuly; - - dl = dxuv[0] + dxuv[1]; - shi->dxsticky[0] = dl * s3[0] - dxuv[0] * s1[0] - dxuv[1] * s2[0]; - shi->dxsticky[1] = dl * s3[1] - dxuv[0] * s1[1] - dxuv[1] * s2[1]; - dl = dyuv[0] + dyuv[1]; - shi->dysticky[0] = dl * s3[0] - dyuv[0] * s1[0] - dyuv[1] * s2[0]; - shi->dysticky[1] = dl * s3[1] - dyuv[0] * s1[1] - dyuv[1] * s2[1]; - } - } - } } /* else { * Note! For raytracing winco is not set, @@ -1326,12 +1316,7 @@ void shade_input_initialize(ShadeInput *shi, RenderPart *pa, RenderLayer *rl, in shi->thread = pa->thread; shi->do_preview = (R.r.scemode & R_MATNODE_PREVIEW) != 0; - /* OCIO_TODO: for now assume color management is always enabled and vertes colors are in sRGB space - * probably would be nice to have this things configurable, but for now it should work - * also probably this flag could be removed (in separated commit) before the release - * since it's not actually meaningful anymore - */ - shi->do_manage = TRUE; + shi->do_manage = BKE_scene_check_color_management_enabled(R.scene); shi->lay = rl->lay; shi->layflag = rl->layflag; diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 6883710d1be..77602edf955 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -57,6 +57,9 @@ #include "shading.h" /* own include */ +/* could enable at some point but for now there are far too many conversions */ +#pragma GCC diagnostic ignored "-Wdouble-promotion" + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ /* only to be used here in this file, it's for speed */ @@ -114,7 +117,7 @@ static void fogcolor(const float colf[3], float *rco, float *view) addAlphaOverFloat(colf, hor); sub_v3_v3(vec, dview); - } + } } #endif @@ -123,37 +126,52 @@ float mistfactor(float zcor, float const co[3]) { float fac, hi; - fac= zcor - R.wrld.miststa; /* zcor is calculated per pixel */ + fac = zcor - R.wrld.miststa; /* zcor is calculated per pixel */ /* fac= -co[2]-R.wrld.miststa; */ - if (fac>0.0f) { - if (fac< R.wrld.mistdist) { + if (fac > 0.0f) { + if (fac < R.wrld.mistdist) { - fac= (fac/(R.wrld.mistdist)); + fac = (fac / R.wrld.mistdist); - if (R.wrld.mistype==0) fac*= fac; - else if (R.wrld.mistype==1); - else fac= sqrt(fac); + if (R.wrld.mistype == 0) { + fac *= fac; + } + else if (R.wrld.mistype == 1) { + /* pass */ + } + else { + fac = sqrt(fac); + } + } + else { + fac = 1.0f; } - else fac= 1.0f; } - else fac= 0.0f; + else { + fac = 0.0f; + } /* height switched off mist */ if (R.wrld.misthi!=0.0f && fac!=0.0f) { /* at height misthi the mist is completely gone */ - hi= R.viewinv[0][2]*co[0]+R.viewinv[1][2]*co[1]+R.viewinv[2][2]*co[2]+R.viewinv[3][2]; + hi = R.viewinv[0][2] * co[0] + + R.viewinv[1][2] * co[1] + + R.viewinv[2][2] * co[2] + + R.viewinv[3][2]; - if (hi>R.wrld.misthi) fac= 0.0f; + if (hi > R.wrld.misthi) { + fac = 0.0f; + } else if (hi>0.0f) { hi= (R.wrld.misthi-hi)/R.wrld.misthi; fac*= hi*hi; } } - return (1.0f-fac)* (1.0f-R.wrld.misi); + return (1.0f-fac)* (1.0f-R.wrld.misi); } static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens) @@ -213,7 +231,7 @@ static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens) } } - /* scale z to make sure volume is normalized */ + /* scale z to make sure volume is normalized */ nray[2] *= (double)lar->sh_zfac; /* nray does not need normalization */ @@ -299,8 +317,8 @@ static void spothalo(struct LampRen *lar, ShadeInput *shi, float *intens) /* calculate t0: is the maximum visible z (when halo is intersected by face) */ if (do_clip) { - if (use_yco == FALSE) t0 = (maxz - npos[2]) / nray[2]; - else t0 = (maxy - npos[1]) / nray[1]; + if (use_yco == FALSE) t0 = ((double)maxz - npos[2]) / nray[2]; + else t0 = ((double)maxy - npos[1]) / nray[1]; if (t0 < t1) return; if (t0 < t2) t2= t0; @@ -453,9 +471,10 @@ static float area_lamp_energy(float (*area)[3], const float co[3], const float v /* cross product */ #define CROSS(dest, a, b) \ - { dest[0]= a[1] * b[2] - a[2] * b[1]; \ - dest[1]= a[2] * b[0] - a[0] * b[2]; \ - dest[2]= a[0] * b[1] - a[1] * b[0]; \ + { \ + dest[0]= a[1] * b[2] - a[2] * b[1]; \ + dest[1]= a[2] * b[0] - a[0] * b[2]; \ + dest[2]= a[0] * b[1] - a[1] * b[0]; \ } (void)0 CROSS(cross[0], vec[0], vec[1]); @@ -532,7 +551,7 @@ static float spec(float inp, int hard) b1= inp*inp; /* avoid FPE */ - if (b1<0.01f) b1= 0.01f; + if (b1<0.01f) b1= 0.01f; if ((hard & 1)==0) inp= 1.0f; if (hard & 2) inp*= b1; @@ -545,7 +564,7 @@ static float spec(float inp, int hard) b1*= b1; /* avoid FPE */ - if (b1<0.001f) b1= 0.0f; + if (b1<0.001f) b1= 0.0f; if (hard & 32) inp*= b1; b1*= b1; @@ -553,7 +572,7 @@ static float spec(float inp, int hard) b1*= b1; if (hard & 128) inp*=b1; - if (b1<0.001f) b1= 0.0f; + if (b1<0.001f) b1= 0.0f; if (hard & 256) { b1*= b1; @@ -811,7 +830,7 @@ static float Minnaert_Diff(float nl, const float n[3], const float v[3], float d nv = 0.0f; if (darkness <= 1.0f) - i = nl * pow(maxf(nv * nl, 0.1f), (darkness - 1.0f) ); /*The Real model*/ + i = nl * pow(max_ff(nv * nl, 0.1f), (darkness - 1.0f) ); /*The Real model*/ else i = nl * pow( (1.001f - nv), (darkness - 1.0f) ); /*Nvidia model*/ @@ -1217,7 +1236,7 @@ float lamp_get_visibility(LampRen *lar, const float co[3], float lv[3], float *d copy_v3_v3(lvrot, lv); mul_m3_v3(lar->imat, lvrot); - x = maxf(fabsf(lvrot[0]/lvrot[2]), fabsf(lvrot[1]/lvrot[2])); + x = max_ff(fabsf(lvrot[0]/lvrot[2]), fabsf(lvrot[1]/lvrot[2])); /* 1.0f/(sqrt(1+x*x)) is equivalent to cos(atan(x)) */ inpr= 1.0f/(sqrt(1.0f+x*x)); @@ -1301,7 +1320,7 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int if (lar->mode & LA_TEXTURE) do_lamp_tex(lar, lv, shi, lacol, LA_TEXTURE); if (lar->mode & LA_SHAD_TEX) do_lamp_tex(lar, lv, shi, lashdw, LA_SHAD_TEX); - /* tangent case; calculate fake face normal, aligned with lampvector */ + /* tangent case; calculate fake face normal, aligned with lampvector */ /* note, vnor==vn is used as tangent trigger for buffer shadow */ if (vlr->flag & R_TANGENT) { float cross[3], nstrand[3], blend; @@ -1347,11 +1366,13 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int /* inp = dotproduct, is = shader result, i = lamp energy (with shadow), i_noshad = i without shadow */ inp= dot_v3v3(vn, lv); - /* phong threshold to prevent backfacing faces having artefacts on ray shadow (terminator problem) */ + /* phong threshold to prevent backfacing faces having artifacts on ray shadow (terminator problem) */ /* this complex construction screams for a nicer implementation! (ton) */ if (R.r.mode & R_SHADOW) { if (ma->mode & MA_SHADOW) { - if (lar->type==LA_HEMI || lar->type==LA_AREA); + if (lar->type == LA_HEMI || lar->type == LA_AREA) { + /* pass */ + } else if ((ma->mode & MA_RAYBIAS) && (lar->mode & LA_SHAD_RAY) && (vlr->flag & R_SMOOTH)) { float thresh= shi->obr->ob->smoothresh; if (inp>thresh) @@ -1466,8 +1487,10 @@ static void shade_one_light(LampRen *lar, ShadeInput *shi, ShadeResult *shr, int if (shadfac[3]>0.0f && shi->spec!=0.0f && !(lar->mode & LA_NO_SPEC) && !(lar->mode & LA_ONLYSHADOW)) { - if (!(passflag & (SCE_PASS_COMBINED|SCE_PASS_SPEC))); - else if (lar->type==LA_HEMI) { + if (!(passflag & (SCE_PASS_COMBINED | SCE_PASS_SPEC))) { + /* pass */ + } + else if (lar->type == LA_HEMI) { float t; /* hemi uses no spec shaders (yet) */ @@ -1617,7 +1640,7 @@ static void shade_lamp_loop_only_shadow(ShadeInput *shi, ShadeResult *shr) } } - /* quite disputable this... also note it doesn't mirror-raytrace */ + /* quite disputable this... also note it doesn't mirror-raytrace */ if ((R.wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT)) && shi->amb!=0.0f) { float f; @@ -1825,7 +1848,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) } } - if (shi->combinedflag & SCE_PASS_SHADOW) + if (shi->combinedflag & SCE_PASS_SHADOW) copy_v3_v3(shr->combined, shr->shad); /* note, no ';' ! */ else copy_v3_v3(shr->combined, shr->diff); diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c index 69e738e840d..6d0e15ea46e 100644 --- a/source/blender/render/intern/source/sss.c +++ b/source/blender/render/intern/source/sss.c @@ -238,7 +238,9 @@ static void approximate_Rd_rgb(ScatterSettings **ss, float rr, float *rd) float indexf, t, idxf; int index; - if (rr > (RD_TABLE_RANGE_2*RD_TABLE_RANGE_2)); + if (rr > (RD_TABLE_RANGE_2 * RD_TABLE_RANGE_2)) { + /* pass */ + } else if (rr > RD_TABLE_RANGE) { rr= sqrt(rr); indexf= rr*(RD_TABLE_SIZE/RD_TABLE_RANGE_2); @@ -305,7 +307,7 @@ ScatterSettings *scatter_settings_new(float refl, float radius, float ior, float 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= minf(refl, 0.999f); + ss->ro= min_ff(refl, 0.999f); ss->color= ss->ro*reflfac + (1.0f-reflfac); ss->alpha_= compute_reduced_albedo(ss); @@ -379,7 +381,7 @@ static void add_radiance(ScatterTree *tree, float *frontrad, float *backrad, flo } } -static void traverse_octree(ScatterTree *tree, ScatterNode *node, float *co, int self, ScatterResult *result) +static void traverse_octree(ScatterTree *tree, ScatterNode *node, const float co[3], int self, ScatterResult *result) { float sub[3], dist; int i, index = 0; @@ -430,7 +432,7 @@ static void traverse_octree(ScatterTree *tree, ScatterNode *node, float *co, int } } -static void compute_radiance(ScatterTree *tree, float *co, float *rad) +static void compute_radiance(ScatterTree *tree, const float co[3], float *rad) { ScatterResult result; float rdsum[3], backrad[3], backrdsum[3]; diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c index dc3225b7f09..2fe8adaa1ee 100644 --- a/source/blender/render/intern/source/strand.c +++ b/source/blender/render/intern/source/strand.c @@ -449,6 +449,7 @@ typedef struct StrandPart { int sample; int shadow; float (*jit)[2]; + int samples; StrandSegment *segment; float t[3], s[3]; @@ -545,7 +546,7 @@ static void do_strand_fillac(void *handle, int x, int y, float u, float v, float bufferz= 0x7FFFFFFF; if (spart->rectmask) maskz= 0x7FFFFFFF; - if (*rd) { + if (*rd) { for (ps= (PixStr *)(*rd); ps; ps= ps->next) { if (mask & ps->mask) { bufferz= ps->z; @@ -669,12 +670,8 @@ static void strand_render(Render *re, StrandSegment *sseg, float winmat[][4], St float dt= p2->t - p1->t; int a; - if (re->osa) { - for (a=0; aosa; a++) - do_scanconvert_strand(re, spart, zspan, t, dt, p1->zco2, p1->zco1, p2->zco1, p2->zco2, a); - } - else - do_scanconvert_strand(re, spart, zspan, t, dt, p1->zco2, p1->zco1, p2->zco1, p2->zco2, 0); + for (a=0; asamples; a++) + do_scanconvert_strand(re, spart, zspan, t, dt, p1->zco2, p1->zco1, p2->zco1, p2->zco2, a); } else { float hoco1[4], hoco2[4]; @@ -786,7 +783,7 @@ void render_strand_segment(Render *re, float winmat[][4], StrandPart *spart, ZSp } /* render call to fill in strands */ -int zbuffer_strands_abuf(Render *re, RenderPart *pa, APixstrand *apixbuf, ListBase *apsmbase, unsigned int lay, int UNUSED(negzmask), float winmat[][4], int winx, int winy, int UNUSED(sample), float (*jit)[2], float clipcrop, int shadow, StrandShadeCache *cache) +int zbuffer_strands_abuf(Render *re, RenderPart *pa, APixstrand *apixbuf, ListBase *apsmbase, unsigned int lay, int UNUSED(negzmask), float winmat[][4], int winx, int winy, int samples, float (*jit)[2], float clipcrop, int shadow, StrandShadeCache *cache) { ObjectRen *obr; ObjectInstanceRen *obi; @@ -820,6 +817,7 @@ int zbuffer_strands_abuf(Render *re, RenderPart *pa, APixstrand *apixbuf, ListBa spart.cache= cache; spart.shadow= shadow; spart.jit= jit; + spart.samples= samples; zbuf_alloc_span(&zspan, pa->rectx, pa->recty, clipcrop); diff --git a/source/blender/render/intern/source/sunsky.c b/source/blender/render/intern/source/sunsky.c index 6a1517e19fb..e4a42fcd675 100644 --- a/source/blender/render/intern/source/sunsky.c +++ b/source/blender/render/intern/source/sunsky.c @@ -146,7 +146,7 @@ static float PerezFunction(struct SunSky *sunsky, const float *lam, float theta, * sun_size, controls sun's size * back_scatter, controls back scatter light * */ -void InitSunSky(struct SunSky *sunsky, float turb, float *toSun, float horizon_brightness, +void InitSunSky(struct SunSky *sunsky, float turb, const float toSun[3], float horizon_brightness, float spread, float sun_brightness, float sun_size, float back_scatter, float skyblendfac, short skyblendtype, float sky_exposure, float sky_colorspace) { @@ -217,8 +217,7 @@ void InitSunSky(struct SunSky *sunsky, float turb, float *toSun, float horizon_b sunsky->perez_y[3] = -0.04405f * T - 1.65369f; sunsky->perez_y[4] = -0.01092f * T + 0.05291f; - /* suggested by glome in - * http://projects.blender.org/tracker/?func=detail&atid=127&aid=8063&group_id=9*/ + /* suggested by glome in patch [#8063] */ sunsky->perez_Y[0] *= sunsky->horizon_brightness; sunsky->perez_x[0] *= sunsky->horizon_brightness; sunsky->perez_y[0] *= sunsky->horizon_brightness; @@ -275,7 +274,7 @@ void GetSkyXYZRadiance(struct SunSky *sunsky, float theta, float phi, float colo /* Compute xyY values */ x = PerezFunction(sunsky, sunsky->perez_x, theta, gamma, sunsky->zenith_x); y = PerezFunction(sunsky, sunsky->perez_y, theta, gamma, sunsky->zenith_y); - Y = 6.666666667e-5f *nfade *hfade *PerezFunction(sunsky, sunsky->perez_Y, theta, gamma, sunsky->zenith_Y); + Y = 6.666666667e-5f * nfade * hfade * PerezFunction(sunsky, sunsky->perez_Y, theta, gamma, sunsky->zenith_Y); if (sunsky->sky_exposure != 0.0f) Y = 1.0 - exp(Y * sunsky->sky_exposure); @@ -330,8 +329,8 @@ static void ComputeAttenuatedSunlight(float theta, int turbidity, float fTau[3]) int i; float fLambda[3]; - fLambda[0] = 0.65f; - fLambda[1] = 0.57f; + fLambda[0] = 0.65f; + fLambda[1] = 0.57f; fLambda[2] = 0.475f; fAlpha = 1.3f; diff --git a/source/blender/render/intern/source/texture_ocean.c b/source/blender/render/intern/source/texture_ocean.c index b2bc635cba7..a7547479093 100644 --- a/source/blender/render/intern/source/texture_ocean.c +++ b/source/blender/render/intern/source/texture_ocean.c @@ -55,7 +55,7 @@ extern struct Render R; /* ***** actual texture sampling ***** */ -int ocean_texture(Tex *tex, float *texvec, TexResult *texres) +int ocean_texture(Tex *tex, const float texvec[2], TexResult *texres) { OceanTex *ot = tex->ot; ModifierData *md; diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c index 8a92695a15e..8757be740f3 100644 --- a/source/blender/render/intern/source/volume_precache.c +++ b/source/blender/render/intern/source/volume_precache.c @@ -92,7 +92,7 @@ static int intersect_outside_volume(RayObject *tree, Isect *isect, float *offset } /* Uses ray tracing to check if a point is inside or outside an ObjectInstanceRen */ -static int point_inside_obi(RayObject *tree, ObjectInstanceRen *UNUSED(obi), float *co) +static int point_inside_obi(RayObject *tree, ObjectInstanceRen *UNUSED(obi), const float co[3]) { Isect isect= {{0}}; float dir[3] = {0.0f, 0.0f, 1.0f}; @@ -118,7 +118,7 @@ static int point_inside_obi(RayObject *tree, ObjectInstanceRen *UNUSED(obi), flo } /* find the bounding box of an objectinstance in global space */ -void global_bounds_obi(Render *re, ObjectInstanceRen *obi, float *bbmin, float *bbmax) +void global_bounds_obi(Render *re, ObjectInstanceRen *obi, float bbmin[3], float bbmax[3]) { ObjectRen *obr = obi->obr; VolumePrecache *vp = obi->volume_precache; @@ -270,7 +270,7 @@ BLI_INLINE int ms_I(int x, int y, int z, int *n) /* has a pad of 1 voxel surroun BLI_INLINE int v_I_pad(int x, int y, int z, int *n) /* has a pad of 1 voxel surrounding the core for boundary simulation */ { /* same ordering to light cache, with padding */ - return z*(n[1]+2)*(n[0]+2) + y*(n[0]+2) + x; + return z*(n[1]+2)*(n[0]+2) + y*(n[0]+2) + x; } BLI_INLINE int lc_to_ms_I(int x, int y, int z, int *n) @@ -389,7 +389,7 @@ static void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Materi const int j = ms_I(x, y, z, n); //ms index time= PIL_check_seconds_timer(); - c++; + c++; if (vp->data_r[i] > 0.0f) sr[j] += vp->data_r[i]; if (vp->data_g[i] > 0.0f) @@ -826,7 +826,7 @@ void free_volume_precache(Render *re) BLI_freelistN(&re->volumes); } -int point_inside_volume_objectinstance(Render *re, ObjectInstanceRen *obi, float *co) +int point_inside_volume_objectinstance(Render *re, ObjectInstanceRen *obi, const float co[3]) { RayObject *tree; int inside=0; diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c index 220fcd3e986..fe4cff76093 100644 --- a/source/blender/render/intern/source/volumetric.c +++ b/source/blender/render/intern/source/volumetric.c @@ -76,7 +76,7 @@ static float vol_get_shadow(ShadeInput *shi, LampRen *lar, const float co[3]) if (lar->shb) { float dxco[3] = {0.f, 0.f, 0.f}, dyco[3] = {0.f, 0.f, 0.f}; - visibility = testshadowbuf(&R, lar->shb, co, dxco, dyco, 1.0, 0.0); + visibility = testshadowbuf(&R, lar->shb, co, dxco, dyco, 1.0, 0.0); } else if (lar->mode & LA_SHAD_RAY) { /* trace shadow manually, no good lamp api atm */ @@ -205,7 +205,7 @@ static void vol_trace_behind(ShadeInput *shi, VlakRen *vlr, const float co[3], f else { shadeSkyView(col_r, co, shi->view, NULL, shi->thread); shadeSunView(col_r, shi->view); - } + } } @@ -221,7 +221,7 @@ static void vol_get_precached_scattering(Render *re, ShadeInput *shi, float scat /* find sample point in global space bounding box 0.0-1.0 */ global_bounds_obi(re, shi->obi, bbmin, bbmax); sub_v3_v3v3(dim, bbmax, bbmin); - mul_v3_m4v3(world_co, re->viewinv, co); + mul_v3_m4v3(world_co, re->viewinv, co); /* sample_co in 0.0-1.0 */ sample_co[0] = (world_co[0] - bbmin[0]) / dim[0]; diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c index d73171648fb..b486407c61c 100644 --- a/source/blender/render/intern/source/voxeldata.c +++ b/source/blender/render/intern/source/voxeldata.c @@ -227,69 +227,102 @@ static void init_frame_smoke(VoxelData *vd, float cfra) /* draw code for smoke */ if ((md = (ModifierData *)modifiers_findByType(ob, eModifierType_Smoke))) { SmokeModifierData *smd = (SmokeModifierData *)md; - + SmokeDomainSettings *sds = smd->domain; - if (smd->domain && smd->domain->fluid) { - if (cfra < smd->domain->point_cache[0]->startframe) + if (sds && sds->fluid) { + if (cfra < sds->point_cache[0]->startframe) ; /* don't show smoke before simulation starts, this could be made an option in the future */ else if (vd->smoked_type == TEX_VD_SMOKEHEAT) { size_t totRes; size_t i; float *heat; - copy_v3_v3_int(vd->resol, smd->domain->res); + if (!smoke_has_heat(sds->fluid)) return; + + copy_v3_v3_int(vd->resol, sds->res); totRes = vd_resol_size(vd); - - /* scaling heat values from -2.0-2.0 to 0.0-1.0 */ vd->dataset = MEM_mapallocN(sizeof(float) * (totRes), "smoke data"); + /* get heat data */ + heat = smoke_get_heat(sds->fluid); - - heat = smoke_get_heat(smd->domain->fluid); - + /* scale heat values from -2.0-2.0 to 0.0-1.0 */ for (i = 0; i < totRes; i++) { vd->dataset[i] = (heat[i] + 2.0f) / 4.0f; } - - /* vd->dataset = smoke_get_heat(smd->domain->fluid); */ } else if (vd->smoked_type == TEX_VD_SMOKEVEL) { size_t totRes; size_t i; float *xvel, *yvel, *zvel; - copy_v3_v3_int(vd->resol, smd->domain->res); + copy_v3_v3_int(vd->resol, sds->res); totRes = vd_resol_size(vd); - - /* scaling heat values from -2.0-2.0 to 0.0-1.0 */ vd->dataset = MEM_mapallocN(sizeof(float) * (totRes), "smoke data"); + /* get velocity data */ + xvel = smoke_get_velocity_x(sds->fluid); + yvel = smoke_get_velocity_y(sds->fluid); + zvel = smoke_get_velocity_z(sds->fluid); - xvel = smoke_get_velocity_x(smd->domain->fluid); - yvel = smoke_get_velocity_y(smd->domain->fluid); - zvel = smoke_get_velocity_z(smd->domain->fluid); - + /* map velocities between 0 and 0.3f */ for (i = 0; i < totRes; i++) { vd->dataset[i] = sqrt(xvel[i] * xvel[i] + yvel[i] * yvel[i] + zvel[i] * zvel[i]) * 3.0f; } } - else { + else if (vd->smoked_type == TEX_VD_SMOKEFLAME) { size_t totRes; - float *density; + float *flame; - if (smd->domain->flags & MOD_SMOKE_HIGHRES) { - smoke_turbulence_get_res(smd->domain->wt, vd->resol); - density = smoke_turbulence_get_density(smd->domain->wt); + if (sds->flags & MOD_SMOKE_HIGHRES) { + if (!smoke_turbulence_has_fuel(sds->wt)) return; + smoke_turbulence_get_res(sds->wt, vd->resol); + flame = smoke_turbulence_get_flame(sds->wt); } else { - copy_v3_v3_int(vd->resol, smd->domain->res); - density = smoke_get_density(smd->domain->fluid); + if (!smoke_has_fuel(sds->fluid)) return; + copy_v3_v3_int(vd->resol, sds->res); + flame = smoke_get_flame(sds->fluid); + } + + /* always store copy, as smoke internal data can change */ + totRes = vd_resol_size(vd); + vd->dataset = MEM_mapallocN(sizeof(float)*(totRes), "smoke data"); + memcpy(vd->dataset, flame, sizeof(float)*totRes); + } + else { + size_t totCells; + int depth = 4; + vd->data_type = TEX_VD_RGBA_PREMUL; + + /* data resolution */ + if (sds->flags & MOD_SMOKE_HIGHRES) { + smoke_turbulence_get_res(sds->wt, vd->resol); + } + else { + copy_v3_v3_int(vd->resol, sds->res); } /* TODO: is_vd_res_ok(rvd) doesnt check this resolution */ - totRes = vd_resol_size(vd); + totCells = vd_resol_size(vd) * depth; /* always store copy, as smoke internal data can change */ - vd->dataset = MEM_mapallocN(sizeof(float) * (totRes), "smoke data"); - memcpy(vd->dataset, density, sizeof(float) * totRes); + vd->dataset = MEM_mapallocN(sizeof(float) * totCells, "smoke data"); + + if (sds->flags & MOD_SMOKE_HIGHRES) { + if (smoke_turbulence_has_colors(sds->wt)) { + smoke_turbulence_get_rgba(sds->wt, vd->dataset, 1); + } + else { + smoke_turbulence_get_rgba_from_density(sds->wt, sds->active_color, vd->dataset, 1); + } + } + else { + if (smoke_has_colors(sds->fluid)) { + smoke_get_rgba(sds->fluid, vd->dataset, 1); + } + else { + smoke_get_rgba_from_density(sds->fluid, sds->active_color, vd->dataset, 1); + } + } } /* end of fluid condition */ } } @@ -320,6 +353,8 @@ void cache_voxeldata(Tex *tex, int scene_frame) MEM_freeN(vd->dataset); vd->dataset = NULL; } + /* reset data_type */ + vd->data_type = TEX_VD_INTENSITY; if (vd->flag & TEX_VD_STILL) curframe = vd->still_frame; @@ -379,9 +414,11 @@ void make_voxeldata(struct Render *re) int voxeldatatex(struct Tex *tex, const float texvec[3], struct TexResult *texres) { - int retval = TEX_INT; - VoxelData *vd = tex->vd; - float co[3], offset[3] = {0.5, 0.5, 0.5}; + VoxelData *vd = tex->vd; + float co[3], offset[3] = {0.5, 0.5, 0.5}, a; + int retval = (vd->data_type == TEX_VD_RGBA_PREMUL) ? TEX_RGB : TEX_INT; + int depth = (vd->data_type == TEX_VD_RGBA_PREMUL) ? 4 : 1; + int ch; if (vd->dataset == NULL) { texres->tin = 0.0f; @@ -420,31 +457,63 @@ int voxeldatatex(struct Tex *tex, const float texvec[3], struct TexResult *texre break; } } - - switch (vd->interp_type) { - case TEX_VD_NEARESTNEIGHBOR: - texres->tin = BLI_voxel_sample_nearest(vd->dataset, vd->resol, co); - break; - case TEX_VD_LINEAR: - texres->tin = BLI_voxel_sample_trilinear(vd->dataset, vd->resol, co); - break; - case TEX_VD_QUADRATIC: - texres->tin = BLI_voxel_sample_triquadratic(vd->dataset, vd->resol, co); - break; - case TEX_VD_TRICUBIC_CATROM: - case TEX_VD_TRICUBIC_BSPLINE: - texres->tin = BLI_voxel_sample_tricubic(vd->dataset, vd->resol, co, (vd->interp_type == TEX_VD_TRICUBIC_BSPLINE)); - break; + + for (ch = 0; ch < depth; ch++) { + float *dataset = vd->dataset + ch*vd->resol[0]*vd->resol[1]*vd->resol[2]; + float *result = &texres->tin; + + if (vd->data_type == TEX_VD_RGBA_PREMUL) { + switch (ch) { + case 0: + result = &texres->tr; + break; + case 1: + result = &texres->tg; + break; + case 2: + result = &texres->tb; + break; + } + } + + switch (vd->interp_type) { + case TEX_VD_NEARESTNEIGHBOR: + *result = BLI_voxel_sample_nearest(dataset, vd->resol, co); + break; + case TEX_VD_LINEAR: + *result = BLI_voxel_sample_trilinear(dataset, vd->resol, co); + break; + case TEX_VD_QUADRATIC: + *result = BLI_voxel_sample_triquadratic(dataset, vd->resol, co); + break; + case TEX_VD_TRICUBIC_CATROM: + case TEX_VD_TRICUBIC_BSPLINE: + *result = BLI_voxel_sample_tricubic(dataset, vd->resol, co, (vd->interp_type == TEX_VD_TRICUBIC_BSPLINE)); + break; + } } - + + a = texres->tin; texres->tin *= vd->int_multiplier; BRICONT; - texres->tr = texres->tin; - texres->tg = texres->tin; - texres->tb = texres->tin; + if (vd->data_type == TEX_VD_RGBA_PREMUL) { + /* unmultiply */ + if (a>0.001f) { + texres->tr /= a; + texres->tg /= a; + texres->tb /= a; + } + texres->talpha = 1; + } + else { + texres->tr = texres->tin; + texres->tg = texres->tin; + texres->tb = texres->tin; + } + texres->ta = texres->tin; BRICONTRGB; - return retval; + return retval; } diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index bf6962d0087..62bf9ac2005 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -76,6 +76,9 @@ /* own includes */ #include "zbuf.h" +/* could enable at some point but for now there are far too many conversions */ +#pragma GCC diagnostic ignored "-Wdouble-promotion" + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ /* only to be used here in this file, it's for speed */ @@ -150,7 +153,7 @@ static void zbuf_add_to_span(ZSpan *zspan, const float *v1, const float *v2) } else { dx0 = 0.0f; - xs0 = minf(minv[0], maxv[0]); + xs0 = min_ff(minv[0], maxv[0]); } /* empty span */ @@ -409,7 +412,7 @@ static void zbuffillAc4(ZSpan *zspan, int obi, int zvlnr, if (apn->p[3]==zvlnr && apn->obi[3]==obi) {apn->mask[3]|= mask; break; } if (apn->next==NULL) apn->next= addpsA(zspan); apn= apn->next; - } + } } } zverg+= zxd; @@ -501,7 +504,7 @@ static void zbuflineAc(ZSpan *zspan, int obi, int zvlnr, const float vec1[3], co if (apn->p[3]==zvlnr && apn->obi[3]==obi) {apn->mask[3]|= mask; break; } if (apn->next==0) apn->next= addpsA(zspan); apn= apn->next; - } + } } } } @@ -572,7 +575,7 @@ static void zbuflineAc(ZSpan *zspan, int obi, int zvlnr, const float vec1[3], co if (apn->p[3]==zvlnr) {apn->mask[3]|= mask; break; } if (apn->next==0) apn->next= addpsA(zspan); apn= apn->next; - } + } } } } @@ -1029,7 +1032,7 @@ void zbufsinglewire(ZSpan *zspan, int obi, int zvlnr, const float ho1[4], const /** * Fill the z buffer, but invert z order, and add the face index to - * the corresponing face buffer. + * the corresponding face buffer. * * This is one of the z buffer fill functions called in zbufclip() and * zbufwireclip(). @@ -1624,7 +1627,7 @@ static void clippyra(float *labda, float *v1, float *v2, int *b2, int *b3, int a else { dw= clipcrop*(v2[3]-v1[3]); v13= clipcrop*v1[3]; - } + } /* according the original article by Liang&Barsky, for clipping of * homogeneous coordinates with viewplane, the value of "0" is used instead of "-w" . * This differs from the other clipping cases (like left or top) and I considered @@ -1682,7 +1685,7 @@ static void makevertpyra(float *vez, float *labda, float **trias, float *v1, flo adr[1]= v1[1]+l1*(v2[1]-v1[1]); adr[2]= v1[2]+l1*(v2[2]-v1[2]); adr[3]= v1[3]+l1*(v2[3]-v1[3]); - } + } else trias[*b1]= v1; (*b1)++; @@ -2022,7 +2025,7 @@ static void zmask_rect(int *rectz, int *rectp, int xs, int ys, int neg) EXTEND_PIXEL(row1 + 2); EXTEND_PIXEL(row2 + 2); EXTEND_PIXEL(row3 + 2); - } + } if (tot) { len++; curz[0]= (int)(z/(float)tot); @@ -2038,14 +2041,16 @@ static void zmask_rect(int *rectz, int *rectp, int xs, int ys, int neg) MEM_freeN(temprectp); - if (neg); /* z values for negative are already correct */ + if (neg) { + /* z values for negative are already correct */ + } else { /* clear not filled z values */ for (len= xs*ys -1; len>=0; len--) { if (rectp[len]==0) { rectz[len] = -0x7FFFFFFF; rectp[len]= -1; /* env code */ - } + } } } } @@ -2730,7 +2735,7 @@ static void zbuf_fill_in_rgba(ZSpan *zspan, DrawBufPixel *col, float *v1, float x= sn2-sn1; while (x>=0) { - if ( zverg < *rz) { + if (zverg < (double)*rz) { *rz= zverg; *rp= *col; } @@ -3231,7 +3236,7 @@ static void copyto_abufz(RenderPart *pa, int *arectz, int *rectmask, int sample) *rza= 0x7FFFFFFF; if (rectmask) *rma= 0x7FFFFFFF; - if (*rd) { + if (*rd) { /* when there's a sky pixstruct, fill in sky-Z, otherwise solid Z */ for (ps= (PixStr *)(*rd); ps; ps= ps->next) { if (sample & ps->mask) { @@ -3515,7 +3520,7 @@ static void add_transp_obindex(RenderLayer *rl, int offset, Object *ob) RenderPass *rpass; for (rpass= rl->passes.first; rpass; rpass= rpass->next) { - if (rpass->passtype == SCE_PASS_INDEXOB||rpass->passtype == SCE_PASS_INDEXMA) { + if (rpass->passtype == SCE_PASS_INDEXOB) { float *fp= rpass->rect + offset; *fp= (float)ob->index; break; @@ -3523,6 +3528,19 @@ static void add_transp_obindex(RenderLayer *rl, int offset, Object *ob) } } +static void add_transp_material_index(RenderLayer *rl, int offset, Material *mat) +{ + RenderPass *rpass; + + for (rpass= rl->passes.first; rpass; rpass= rpass->next) { + if (rpass->passtype == SCE_PASS_INDEXMA) { + float *fp= rpass->rect + offset; + *fp= (float)mat->index; + break; + } + } +} + /* ONLY OSA! merge all shaderesult samples to one */ /* target should have been cleared */ static void merge_transp_passes(RenderLayer *rl, ShadeResult *shr) @@ -3874,7 +3892,7 @@ static int addtosamp_shr(ShadeResult *samp_shr, ShadeSample *ssamp, int addpassf addAlphaUnderFloat(samp_shr->combined, shr->combined); - samp_shr->z = minf(samp_shr->z, shr->z); + samp_shr->z = min_ff(samp_shr->z, shr->z); if (addpassflag & SCE_PASS_VECTOR) { copy_v4_v4(samp_shr->winspeed, shr->winspeed); @@ -4127,10 +4145,12 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas } } if (addpassflag & SCE_PASS_INDEXMA) { - ObjectRen *obr= R.objectinstance[zrow[totface-1].obi].obr; - if (obr->ob) { + ObjectRen *obr = R.objectinstance[zrow[totface-1].obi].obr; + VlakRen *vr = obr->vlaknodes->vlak; + Material *mat = vr->mat; + if (mat) { for (a= 0; aob); + add_transp_material_index(rlpp[a], od, mat); } } @@ -4241,7 +4261,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas MEM_freeN(APixbufstrand); if (sscache) strand_shade_cache_free(sscache); - freepsA(&apsmbase); + freepsA(&apsmbase); if (R.r.mode & R_SHADOW) ISB_free(pa); diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index e6782121b69..65a8945f82b 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -29,6 +29,7 @@ set(INC ../blenkernel ../blenlib ../blenloader + ../compositor ../editors/include ../editors/io ../gpu @@ -36,7 +37,6 @@ set(INC ../makesdna ../makesrna ../nodes - ../compositor ../render/extern/include ../../gameengine/BlenderRoutines ../../../intern/elbeem/extern diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 1d509a87ffe..b9a4e720230 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -71,8 +71,18 @@ void WM_init_state_normal_set(void); void WM_init (struct bContext *C, int argc, const char **argv); void WM_exit_ext (struct bContext *C, const short do_python); -void WM_exit (struct bContext *C); -void WM_main (struct bContext *C); + +void WM_exit (struct bContext *C) +#if defined(__GNUC__) || defined(__clang__) +__attribute__((noreturn)) +#endif +; + +void WM_main (struct bContext *C) +#if defined(__GNUC__) || defined(__clang__) +__attribute__((noreturn)) +#endif +; int WM_init_game (struct bContext *C); void WM_init_splash (struct bContext *C); @@ -104,8 +114,8 @@ 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_grab_enable(struct wmWindow *win, int wrap, int hide, int *bounds); -void WM_cursor_grab_disable(struct wmWindow *win); +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); void *WM_paint_cursor_activate(struct wmWindowManager *wm, @@ -145,6 +155,7 @@ struct wmEventHandler *WM_event_add_dropbox_handler(ListBase *handlers, ListBase /* mouse */ void WM_event_add_mousemove(struct bContext *C); +void WM_event_add_mousemove_window(struct wmWindow *window); int WM_modal_tweak_exit(struct wmEvent *evt, int tweak_event); /* notifiers */ @@ -203,6 +214,7 @@ int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, short c 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_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); @@ -262,7 +274,7 @@ int WM_gesture_lines_cancel(struct bContext *C, struct wmOperator *op); int WM_gesture_lasso_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_gesture_lasso_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_gesture_lasso_cancel(struct bContext *C, struct wmOperator *op); -int (*WM_gesture_lasso_path_to_array(struct bContext *C, struct wmOperator *op, int *mcords_tot))[2]; +const int (*WM_gesture_lasso_path_to_array(struct bContext *C, struct wmOperator *op, int *mcords_tot))[2]; int WM_gesture_straightline_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_gesture_straightline_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_gesture_straightline_cancel(struct bContext *C, struct wmOperator *op); @@ -346,8 +358,9 @@ void WM_jobs_callbacks(struct wmJob *, void WM_jobs_start(struct wmWindowManager *wm, struct wmJob *); void WM_jobs_stop(struct wmWindowManager *wm, void *owner, void *startjob); void WM_jobs_kill(struct wmWindowManager *wm, void *owner, void (*)(void *, short int *, short int *, float *)); -void WM_jobs_stop_all(struct wmWindowManager *wm); - +void WM_jobs_kill_all(struct wmWindowManager *wm); + void WM_jobs_kill_all_except(struct wmWindowManager *wm, void *owner); + int WM_jobs_has_running(struct wmWindowManager *wm); /* clipboard */ diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h index 5c88babfb47..43369154dbb 100644 --- a/source/blender/windowmanager/WM_keymap.h +++ b/source/blender/windowmanager/WM_keymap.h @@ -43,7 +43,7 @@ struct EnumPropertyItem; wmKeyConfig *WM_keyconfig_new (struct wmWindowManager *wm, const char *idname); wmKeyConfig *WM_keyconfig_new_user(struct wmWindowManager *wm, const char *idname); -void WM_keyconfig_remove (struct wmWindowManager *wm, struct wmKeyConfig *keyconf); +int WM_keyconfig_remove (struct wmWindowManager *wm, struct wmKeyConfig *keyconf); void WM_keyconfig_free (struct wmKeyConfig *keyconf); void WM_keyconfig_set_active(struct wmWindowManager *wm, const char *idname); @@ -63,8 +63,8 @@ wmKeyMapItem *WM_keymap_add_item(struct wmKeyMap *keymap, const char *idname, in wmKeyMapItem *WM_keymap_add_menu(struct wmKeyMap *keymap, const char *idname, int type, int val, int modifier, int keymodifier); -void WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi); -char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len); +int WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi); +char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len); wmKeyMap *WM_keymap_list_find(ListBase *lb, const char *idname, int spaceid, int regionid); wmKeyMap *WM_keymap_find(struct wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index f9b22331f37..094df73bbd9 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -238,6 +238,7 @@ typedef struct wmNotifier { #define NC_LOGIC (19<<24) #define NC_MOVIECLIP (20<<24) #define NC_MASK (21<<24) +#define NC_GPENCIL (22<<24) /* data type, 256 entries is enough, it can overlap */ #define NOTE_DATA 0x00FF0000 @@ -423,7 +424,7 @@ typedef struct wmEvent { char ascii; /* from ghost, fallback if utf8 isn't set */ char pad; - /* previous state */ + /* previous state, used for double click and the 'click' */ short prevtype; short prevval; int prevx, prevy; @@ -434,7 +435,8 @@ typedef struct wmEvent { short shift, ctrl, alt, oskey; /* oskey is apple or windowskey, value denotes order of pressed */ short keymodifier; /* rawkey modifier */ - short pad1; + /* set in case a KM_PRESS went by unhandled */ + short check_click; /* keymap item, set by handler (weak?) */ const char *keymap_idname; @@ -508,7 +510,11 @@ typedef struct wmOperatorType { * parameters may be provided through operator properties. cannot use * any interface code or input device state. * - see defines below for return values */ - int (*exec)(struct bContext *, struct wmOperator *); + int (*exec)(struct bContext *, struct wmOperator *) +#ifdef __GNUC__ + __attribute__((warn_unused_result)) +#endif + ; /* this callback executes on a running operator whenever as property * is changed. It can correct its own properties or report errors for @@ -520,13 +526,25 @@ typedef struct wmOperatorType { * any further events are handled in modal. if the operation is * canceled due to some external reason, cancel is called * - see defines below for return values */ - int (*invoke)(struct bContext *, struct wmOperator *, struct wmEvent *); + int (*invoke)(struct bContext *, struct wmOperator *, struct wmEvent *) +#ifdef __GNUC__ + __attribute__((warn_unused_result)) +#endif + ; int (*cancel)(struct bContext *, struct wmOperator *); - int (*modal)(struct bContext *, struct wmOperator *, struct wmEvent *); + int (*modal)(struct bContext *, struct wmOperator *, struct wmEvent *) +#ifdef __GNUC__ + __attribute__((warn_unused_result)) +#endif + ; /* verify if the operator can be executed in the current context, note * that the operator might still fail to execute even if this return true */ - int (*poll)(struct bContext *); + int (*poll)(struct bContext *) +#ifdef __GNUC__ + __attribute__((warn_unused_result)) +#endif + ; /* optional panel for redo and repeat, autogenerated if not set */ void (*ui)(struct bContext *, struct wmOperator *); @@ -537,8 +555,8 @@ typedef struct wmOperatorType { /* previous settings - for initializing on re-use */ struct IDProperty *last_properties; - /* rna property to use for generic invoke functions. - * menus, enum search... etc */ + /* Default rna property to use for generic invoke functions. + * menus, enum search... etc. Example: Enum 'type' for a Delete menu */ PropertyRNA *prop; /* struct wmOperatorTypeMacro */ @@ -550,7 +568,11 @@ typedef struct wmOperatorType { /* only used for operators defined with python * use to store pointers to python functions */ void *pyop_data; - int (*pyop_poll)(struct bContext *, struct wmOperatorType *ot); + int (*pyop_poll)(struct bContext *, struct wmOperatorType *ot) +#ifdef __GNUC__ + __attribute__((warn_unused_result)) +#endif + ; /* RNA integration */ ExtensionRNA ext; diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index a34d294461c..8fe387765ce 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -78,7 +78,7 @@ void WM_operator_free(wmOperator *op) if (op->py_instance) { /* do this first in case there are any __del__ functions or * similar that use properties */ - BPY_DECREF(op->py_instance); + BPY_DECREF_RNA_INVALIDATE(op->py_instance); } #endif diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c index 6fc6a57ade1..ebde6407a48 100644 --- a/source/blender/windowmanager/intern/wm_cursors.c +++ b/source/blender/windowmanager/intern/wm_cursors.c @@ -61,7 +61,7 @@ static GHOST_TStandardCursor convert_cursor(int curs) case CURSOR_FACESEL: return GHOST_kStandardCursorRightArrow; case CURSOR_WAIT: return GHOST_kStandardCursorWait; case CURSOR_EDIT: return GHOST_kStandardCursorCrosshair; - case CURSOR_HELP: + case CURSOR_HELP: #ifdef __APPLE__ return GHOST_kStandardCursorLeftRight; #else @@ -179,7 +179,10 @@ void WM_cursor_wait(int val) } } -void WM_cursor_grab_enable(wmWindow *win, int wrap, int hide, int *bounds) +/** + * \param bounds can be NULL + */ +void WM_cursor_grab_enable(wmWindow *win, int wrap, int hide, int bounds[4]) { /* Only grab cursor when not running debug. * It helps not to get a stuck WM when hitting a breakpoint @@ -193,20 +196,20 @@ void WM_cursor_grab_enable(wmWindow *win, int wrap, int hide, int *bounds) const GHOST_TabletData *tabletdata = GHOST_GetTabletData(win->ghostwin); /* Note: There is no tabletdata on Windows if no tablet device is connected. */ if (!tabletdata) - GHOST_SetCursorGrab(win->ghostwin, mode, bounds); + GHOST_SetCursorGrab(win->ghostwin, mode, bounds, NULL); else if (tabletdata->Active == GHOST_kTabletModeNone) - GHOST_SetCursorGrab(win->ghostwin, mode, bounds); + GHOST_SetCursorGrab(win->ghostwin, mode, bounds, NULL); win->grabcursor = mode; } } } -void WM_cursor_grab_disable(wmWindow *win) +void WM_cursor_grab_disable(wmWindow *win, int mouse_ungrab_xy[2]) { if ((G.debug & G_DEBUG) == 0) { if (win && win->ghostwin) { - GHOST_SetCursorGrab(win->ghostwin, GHOST_kGrabDisable, NULL); + GHOST_SetCursorGrab(win->ghostwin, GHOST_kGrabDisable, NULL, mouse_ungrab_xy); win->grabcursor = GHOST_kGrabDisable; } } @@ -314,7 +317,7 @@ void WM_cursor_time(wmWindow *win, int nr) /* Because defining a cursor mixes declarations and executable code * each cursor needs it's own scoping block or it would be split up * over several hundred lines of code. To enforce/document this better - * I define 2 pretty braindead macros so it's obvious what the extra "[]" + * I define 2 pretty brain-dead macros so it's obvious what the extra "[]" * are for */ #define BEGIN_CURSOR_BLOCK { @@ -557,7 +560,7 @@ BEGIN_CURSOR_BLOCK BlenderCursor[BC_CROSSCURSOR] = &CrossCursor; END_CURSOR_BLOCK - /********************** EditCross Cursor ***********************/ + /********************** EditCross Cursor ***********************/ BEGIN_CURSOR_BLOCK static char editcross_sbm[] = { 0x0e, 0x00, 0x11, 0x00, 0x1d, 0x00, 0x19, 0x03, @@ -772,7 +775,7 @@ BEGIN_CURSOR_BLOCK END_CURSOR_BLOCK - /********************** TextEdit Cursor ***********************/ + /********************** TextEdit Cursor ***********************/ BEGIN_CURSOR_BLOCK static char textedit_sbm[] = { 0xe0, 0x03, 0x10, 0x04, 0x60, 0x03, 0x40, 0x01, @@ -805,7 +808,7 @@ BEGIN_CURSOR_BLOCK END_CURSOR_BLOCK - /********************** Paintbrush Cursor ***********************/ + /********************** Paintbrush Cursor ***********************/ BEGIN_CURSOR_BLOCK static char paintbrush_sbm[] = { diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c index bbb2a54887e..0581000e07c 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.c +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -141,7 +141,7 @@ void wm_dropbox_free(void) BLI_freelistN(&dm->dropboxes); } - BLI_freelistN(&dropboxes); + BLI_freelistN(&dropboxes); } /* *********************************** */ diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 17f17baba0e..fee94b95a6a 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -255,8 +255,12 @@ void wm_event_do_notifiers(bContext *C) for (win = wm->windows.first; win; win = win->next) { /* filter out notifiers */ - if (note->category == NC_SCREEN && note->reference && note->reference != win->screen) ; - else if (note->category == NC_SCENE && note->reference && note->reference != win->screen->scene) ; + if (note->category == NC_SCREEN && note->reference && note->reference != win->screen) { + /* pass */ + } + else if (note->category == NC_SCENE && note->reference && note->reference != win->screen->scene) { + /* pass */ + } else { ScrArea *sa; ARegion *ar; @@ -335,6 +339,11 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve int is_wheel = ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE); int retval; + /* UI code doesn't handle return values - it just always returns break. + to make the DBL_CLICK conversion work, we just don't send this to UI */ + if (event->val == KM_DBL_CLICK) + return WM_HANDLER_CONTINUE; + /* UI is quite aggressive with swallowing events, like scrollwheel */ /* I realize this is not extremely nice code... when UI gets keymaps it can be maybe smarter */ if (do_wheel_ui == FALSE) { @@ -443,10 +452,10 @@ void WM_event_print(wmEvent *event) RNA_enum_identifier(event_type_items, event->type, &type_id); RNA_enum_identifier(event_value_items, event->val, &val_id); - printf("wmEvent - type:%d/%s, val:%d/%s, " - "shift:%d, ctrl:%d, alt:%d, oskey:%d, keymodifier:%d, " - "mouse:(%d,%d), ascii:'%c', utf8:'%.*s', " - "keymap_idname:%s, pointer:%p\n", + printf("wmEvent type:%d / %s, val:%d / %s, \n" + " shift:%d, ctrl:%d, alt:%d, oskey:%d, keymodifier:%d, \n" + " mouse:(%d,%d), ascii:'%c', utf8:'%.*s', " + " keymap_idname:%s, pointer:%p\n", event->type, type_id, event->val, val_id, event->shift, event->ctrl, event->alt, event->oskey, event->keymodifier, event->x, event->y, event->ascii, @@ -844,7 +853,7 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, WM_operator_last_properties_init(op); } - if ((G.debug & G_DEBUG_EVENTS) && event && event->type != MOUSEMOVE) { + if ((G.debug & G_DEBUG_HANDLERS) && event && event->type != MOUSEMOVE) { printf("%s: handle evt %d win %d op %s\n", __func__, event ? event->type : 0, CTX_wm_screen(C)->subwinactive, ot->idname); } @@ -883,8 +892,9 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, wm_operator_reports(C, op, retval, (reports != NULL)); } - if (retval & OPERATOR_HANDLED) - ; /* do nothing, wm_operator_exec() has been called somewhere */ + if (retval & OPERATOR_HANDLED) { + /* do nothing, wm_operator_exec() has been called somewhere */ + } else if (retval & OPERATOR_FINISHED) { if (!is_nested_call) { /* not called by py script */ WM_operator_last_properties_store(op); @@ -1202,7 +1212,7 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers) CTX_wm_region_set(C, region); } - WM_cursor_grab_disable(CTX_wm_window(C)); + WM_cursor_grab_disable(CTX_wm_window(C), NULL); WM_operator_free(handler->op); } else if (handler->ui_remove) { @@ -1271,25 +1281,50 @@ int WM_userdef_event_map(int kmitype) static void wm_eventemulation(wmEvent *event) { + /* Store last mmb event value to make emulation work when modifier keys are released first. */ static int mmb_emulated = 0; /* this should be in a data structure somwhere */ /* middlemouse emulation */ if (U.flag & USER_TWOBUTTONMOUSE) { - if (event->type == LEFTMOUSE && (event->alt || mmb_emulated == KM_PRESS)) { - event->type = MIDDLEMOUSE; - event->alt = 0; - mmb_emulated = event->val; + if (event->type == LEFTMOUSE) { + + if (event->val == KM_PRESS && event->alt) { + event->type = MIDDLEMOUSE; + event->alt = 0; + mmb_emulated = 1; + } + else if (event->val == KM_RELEASE) { + /* only send middle-mouse release if emulated */ + if (mmb_emulated) { + event->type = MIDDLEMOUSE; + event->alt = 0; + } + mmb_emulated = 0; + } } + } #ifdef __APPLE__ + /* rightmouse emulation */ if (U.flag & USER_TWOBUTTONMOUSE) { - if (event->type == LEFTMOUSE && (event->oskey || mmb_emulated == KM_PRESS)) { - event->type = RIGHTMOUSE; - event->oskey = 0; - mmb_emulated = event->val; + if (event->type == LEFTMOUSE) { + + if (event->val == KM_PRESS && event->oskey) { + event->type = RIGHTMOUSE; + event->oskey = 0; + mmb_emulated = 1; + } + else if (event->val == KM_RELEASE) { + if (mmb_emulated) { + event->oskey = RIGHTMOUSE; + event->alt = 0; + } + mmb_emulated = 0; + } } + } #endif @@ -1321,7 +1356,12 @@ static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) /* the matching rules */ if (kmitype == KM_TEXTINPUT) - if (ISTEXTINPUT(winevent->type) && (winevent->ascii || winevent->utf8_buf[0])) return 1; + if (winevent->val == KM_PRESS) { // prevent double clicks + /* NOT using ISTEXTINPUT anymore because (at least on Windows) some key codes above 255 + could have printable ascii keys - BUG [#30479] */ + if (ISKEYBOARD(winevent->type) && (winevent->ascii || winevent->utf8_buf[0])) return 1; + } + if (kmitype != KM_ANY) if (winevent->type != kmitype) return 0; @@ -1338,14 +1378,8 @@ static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) if (kmi->oskey != KM_ANY) if (winevent->oskey != kmi->oskey && !(winevent->oskey & kmi->oskey)) return 0; - if (kmi->keymodifier) - if (winevent->keymodifier != kmi->keymodifier) return 0; + if (winevent->keymodifier != kmi->keymodifier) return 0; - /* key modifiers always check when event has it */ - /* otherwise regular keypresses with keymodifier still work */ - if (winevent->keymodifier) - if (ISTEXTINPUT(winevent->type)) - if (winevent->keymodifier != kmi->keymodifier) return 0; return 1; } @@ -1365,13 +1399,30 @@ static void wm_event_modalkeymap(const bContext *C, wmOperator *op, wmEvent *eve for (kmi = keymap->items.first; kmi; kmi = kmi->next) { if (wm_eventmatch(event, kmi)) { + event->prevtype = event->type; + event->prevval = event->val; event->type = EVT_MODAL_MAP; event->val = kmi->propvalue; + + break; } } } } +/* bad hacking event system... better restore event type for checking of KM_CLICK for example */ +/* XXX modal maps could use different method (ton) */ +static void wm_event_modalmap_end(wmEvent *event) +{ + if (event->type == EVT_MODAL_MAP) { + event->type = event->prevtype; + event->prevtype = 0; + event->val = event->prevval; + event->prevval = 0; + } + +} + /* Warning: this function removes a modal handler, when finished */ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHandler *handler, wmEvent *event, PointerRNA *properties) @@ -1398,7 +1449,8 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand retval = ot->modal(C, op, event); OPERATOR_RETVAL_CHECK(retval); - + wm_event_modalmap_end(event); + /* when this is _not_ the case the modal modifier may have loaded * a new blend file (demo mode does this), so we have to assume * the event, operator etc have all been freed. - campbell */ @@ -1432,7 +1484,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand /* remove modal handler, operator itself should have been canceled and freed */ if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) { - WM_cursor_grab_disable(CTX_wm_window(C)); + WM_cursor_grab_disable(CTX_wm_window(C), NULL); BLI_remlink(handlers, handler); wm_event_free_handler(handler); @@ -1543,72 +1595,55 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa /* needed for uiPupMenuReports */ if (event->val == EVT_FILESELECT_EXEC) { -#if 0 // use REDALERT now + int retval; - /* a bit weak, might become arg for WM_event_fileselect? */ - /* XXX also extension code in image-save doesnt work for this yet */ - if (RNA_struct_find_property(handler->op->ptr, "check_existing") && - RNA_boolean_get(handler->op->ptr, "check_existing")) - { - char *path = RNA_string_get_alloc(handler->op->ptr, "filepath", NULL, 0); - /* this gives ownership to pupmenu */ - uiPupMenuSaveOver(C, handler->op, (path) ? path : ""); - if (path) - MEM_freeN(path); - } - else -#endif - { - int retval; - + if (handler->op->type->flag & OPTYPE_UNDO) + wm->op_undo_depth++; + + retval = handler->op->type->exec(C, handler->op); + + /* XXX check this carefully, CTX_wm_manager(C) == wm is a bit hackish */ + if (handler->op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) + wm->op_undo_depth--; + + if (retval & OPERATOR_FINISHED) + if (G.debug & G_DEBUG_WM) + wm_operator_print(C, handler->op); + + /* XXX check this carefully, CTX_wm_manager(C) == wm is a bit hackish */ + if (CTX_wm_manager(C) == wm && wm->op_undo_depth == 0) if (handler->op->type->flag & OPTYPE_UNDO) - wm->op_undo_depth++; - - retval = handler->op->type->exec(C, handler->op); + ED_undo_push_op(C, handler->op); - /* XXX check this carefully, CTX_wm_manager(C) == wm is a bit hackish */ - if (handler->op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) - wm->op_undo_depth--; + if (handler->op->reports->list.first) { - if (retval & OPERATOR_FINISHED) - if (G.debug & G_DEBUG_WM) - wm_operator_print(C, handler->op); - - /* XXX check this carefully, CTX_wm_manager(C) == wm is a bit hackish */ - if (CTX_wm_manager(C) == wm && wm->op_undo_depth == 0) - if (handler->op->type->flag & OPTYPE_UNDO) - ED_undo_push_op(C, handler->op); - - if (handler->op->reports->list.first) { - - /* FIXME, temp setting window, this is really bad! + /* FIXME, temp setting window, this is really bad! * only have because lib linking errors need to be seen by users :( * it can be removed without breaking anything but then no linking errors - campbell */ - wmWindow *win_prev = CTX_wm_window(C); - ScrArea *area_prev = CTX_wm_area(C); - ARegion *ar_prev = CTX_wm_region(C); + wmWindow *win_prev = CTX_wm_window(C); + ScrArea *area_prev = CTX_wm_area(C); + ARegion *ar_prev = CTX_wm_region(C); - if (win_prev == NULL) - CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first); + if (win_prev == NULL) + CTX_wm_window_set(C, CTX_wm_manager(C)->windows.first); - handler->op->reports->printlevel = RPT_WARNING; - uiPupMenuReports(C, handler->op->reports); + handler->op->reports->printlevel = RPT_WARNING; + uiPupMenuReports(C, handler->op->reports); - /* XXX - copied from 'wm_operator_finished()' */ - /* add reports to the global list, otherwise they are not seen */ - BLI_movelisttolist(&CTX_wm_reports(C)->list, &handler->op->reports->list); + /* XXX - copied from 'wm_operator_finished()' */ + /* add reports to the global list, otherwise they are not seen */ + BLI_movelisttolist(&CTX_wm_reports(C)->list, &handler->op->reports->list); - CTX_wm_window_set(C, win_prev); - CTX_wm_area_set(C, area_prev); - CTX_wm_region_set(C, ar_prev); - } - - if (retval & OPERATOR_FINISHED) { - WM_operator_last_properties_store(handler->op); - } - - WM_operator_free(handler->op); + CTX_wm_window_set(C, win_prev); + CTX_wm_area_set(C, area_prev); + CTX_wm_region_set(C, ar_prev); } + + if (retval & OPERATOR_FINISHED) { + WM_operator_last_properties_store(handler->op); + } + + WM_operator_free(handler->op); } else { if (handler->op->type->cancel) { @@ -1667,10 +1702,13 @@ static int wm_action_not_handled(int action) return action == WM_HANDLER_CONTINUE || action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL); } -static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) +static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers) { #ifndef NDEBUG - const int do_debug_handler = (G.debug & G_DEBUG_EVENTS); + const int do_debug_handler = (G.debug & G_DEBUG_HANDLERS) + /* comment this out to flood the console! (if you really want to test) */ + && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) + ; #endif wmWindowManager *wm = CTX_wm_manager(C); wmEventHandler *handler, *nexthandler; @@ -1681,13 +1719,6 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) return action; } -#ifndef NDEBUG - if (do_debug_handler) { - printf("%s: handling event\n", __func__); - WM_event_print(event); - } -#endif - /* modal handlers can get removed in this loop, we keep the loop this way * * note: check 'handlers->first' because in rare cases the handlers can be cleared @@ -1743,11 +1774,10 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) action |= wm_handler_operator_call(C, handlers, handler, event, kmi->ptr); if (action & WM_HANDLER_BREAK) { /* not always_pass here, it denotes removed handler */ -#ifndef NDEBUG - if (do_debug_handler) { - printf("%s: handled! '%s'...", __func__, kmi->idname); - } -#endif + + if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) + printf("%s: handled! '%s'\n", __func__, kmi->idname); + break; } else { @@ -1839,52 +1869,69 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) } } - /* test for CLICK event */ - if (wm_action_not_handled(action) && event->val == KM_RELEASE) { - wmWindow *win = CTX_wm_window(C); - - if (win && win->eventstate->prevtype == event->type && win->eventstate->prevval == KM_PRESS) { - /* test for double click first, - * note1: this can be problematic because single click operators can get the - * double click event but then with old mouse coords which is highly confusing, - * so check for mouse moves too. - * note2: the first click event will be handled but still used to create a - * double click event if clicking again quickly. - * If no double click events are found it will fallback to a single click. - * So a double click event can result in 2 successive single click calls - * if its not handled by the keymap - campbell */ - if ((ABS(event->x - win->eventstate->prevclickx)) <= 2 && - (ABS(event->y - win->eventstate->prevclicky)) <= 2 && - ((PIL_check_seconds_timer() - win->eventstate->prevclicktime) * 1000 < U.dbl_click_time)) - { - event->val = KM_DBL_CLICK; - /* removed this because in cases where we're this is used as a single click - * event, this will give old coords, - * since the distance is checked above, using new coords should be ok. */ - // event->x = win->eventstate->prevclickx; - // event->y = win->eventstate->prevclicky; - action |= wm_handlers_do(C, event, handlers); - } - - if (wm_action_not_handled(action)) { - event->val = KM_CLICK; - action |= wm_handlers_do(C, event, handlers); - } - - - /* revert value if not handled */ - if (wm_action_not_handled(action)) { - event->val = KM_RELEASE; - } - } - } - if (action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL)) wm_cursor_arrow_move(CTX_wm_window(C), event); return action; } +/* this calls handlers twice - to solve (double-)click events */ +static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) +{ + int action = wm_handlers_do_intern(C, event, handlers); + + /* fileread case */ + if (CTX_wm_window(C) == NULL) + return action; + + if (!ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) && !ISTIMER(event->type)) { + + /* test for CLICK events */ + if (wm_action_not_handled(action)) { + wmWindow *win = CTX_wm_window(C); + + /* eventstate stores if previous event was a KM_PRESS, in case that + * wasn't handled, the KM_RELEASE will become a KM_CLICK */ + + if (win && event->val == KM_PRESS) { + win->eventstate->check_click = TRUE; + } + + if (win && win->eventstate->prevtype == event->type) { + + if (event->val == KM_RELEASE && win->eventstate->prevval == KM_PRESS && win->eventstate->check_click == TRUE) { + event->val = KM_CLICK; + + if (G.debug & (G_DEBUG_HANDLERS)) { + printf("%s: handling CLICK\n", __func__); + } + + action |= wm_handlers_do_intern(C, event, handlers); + + event->val = KM_RELEASE; + } + else if (event->val == KM_DBL_CLICK) { + event->val = KM_PRESS; + action |= wm_handlers_do_intern(C, event, handlers); + + /* revert value if not handled */ + if (wm_action_not_handled(action)) { + event->val = KM_DBL_CLICK; + } + } + } + } + else { + wmWindow *win = CTX_wm_window(C); + + if (win) + win->eventstate->check_click = 0; + } + } + + return action; +} + static int wm_event_inside_i(wmEvent *event, rcti *rect) { if (wm_event_always_pass(event)) @@ -2021,23 +2068,26 @@ void wm_event_do_handlers(bContext *C) Scene *scene = win->screen->scene; if (scene) { - int playing = sound_scene_playing(win->screen->scene); + int is_playing_sound = sound_scene_playing(win->screen->scene); - if (playing != -1) { + if (is_playing_sound != -1) { + int is_playing_screen; CTX_wm_window_set(C, win); CTX_wm_screen_set(C, win->screen); CTX_data_scene_set(C, scene); - if (((playing == 1) && (!ED_screen_animation_playing(wm))) || - ((playing == 0) && (ED_screen_animation_playing(wm)))) + is_playing_screen = (ED_screen_animation_playing(wm) != NULL); + + if (((is_playing_sound == 1) && (is_playing_screen == 0)) || + ((is_playing_sound == 0) && (is_playing_screen == 1))) { ED_screen_animation_play(C, -1, 1); } - if (playing == 0) { - float time = sound_sync_scene(scene); + if (is_playing_sound == 0) { + const float time = sound_sync_scene(scene); if (finite(time)) { - int ncfra = sound_sync_scene(scene) * (float)FPS + 0.5f; + int ncfra = time * (float)FPS + 0.5f; if (ncfra != scene->r.cfra) { scene->r.cfra = ncfra; ED_update_for_newframe(CTX_data_main(C), scene, 1); @@ -2056,10 +2106,13 @@ void wm_event_do_handlers(bContext *C) while ( (event = win->queue.first) ) { int action = WM_HANDLER_CONTINUE; - if ((G.debug & G_DEBUG_EVENTS) && event && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { - printf("%s: pass on evt %d val %d\n", __func__, event->type, event->val); +#ifdef DEBUG + if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { + printf("\n%s: Handling event\n", __func__); + WM_event_print(event); } - +#endif + wm_eventemulation(event); CTX_wm_window_set(C, win); @@ -2172,40 +2225,6 @@ void wm_event_do_handlers(bContext *C) } } - /* store last event for this window */ - /* mousemove and timer events don't overwrite last type */ - if (!ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) && !ISTIMER(event->type)) { - if (wm_action_not_handled(action)) { - if (win->eventstate->prevtype == event->type) { - /* set click time on first click (press -> release) */ - if (win->eventstate->prevval == KM_PRESS && event->val == KM_RELEASE) { - win->eventstate->prevclicktime = PIL_check_seconds_timer(); - win->eventstate->prevclickx = event->x; - win->eventstate->prevclicky = event->y; - } - } - else { - /* reset click time if event type not the same */ - win->eventstate->prevclicktime = 0; - } - - win->eventstate->prevval = event->val; - win->eventstate->prevtype = event->type; - } - else if (event->val == KM_CLICK) { /* keep click for double click later */ - win->eventstate->prevtype = event->type; - win->eventstate->prevval = event->val; - win->eventstate->prevclicktime = PIL_check_seconds_timer(); - win->eventstate->prevclickx = event->x; - win->eventstate->prevclicky = event->y; - } - else { /* reset if not */ - win->eventstate->prevtype = -1; - win->eventstate->prevval = 0; - win->eventstate->prevclicktime = 0; - } - } - /* unlink and free here, blender-quit then frees all */ BLI_remlink(&win->queue, event); wm_event_free(event); @@ -2469,6 +2488,11 @@ void WM_event_add_mousemove(bContext *C) window->addmousemove = 1; } +void WM_event_add_mousemove_window(wmWindow *window) +{ + window->addmousemove = 1; +} + /* for modal callbacks, check configuration for how to interpret exit with tweaks */ int WM_modal_tweak_exit(wmEvent *evt, int tweak_event) { @@ -2609,7 +2633,7 @@ static void update_tablet_data(wmWindow *win, wmEvent *event) event->custom = EVT_DATA_TABLET; event->customdata = wmtab; event->customdatafree = 1; - } + } } /* adds customdata to event */ @@ -2732,8 +2756,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U update_tablet_data(win, &event); wm_event_add(win, &event); - - //printf("sending MOUSEMOVE %d %d\n", event.x, event.y); /* also add to other window if event is there, this makes overdraws disappear nicely */ /* it remaps mousecoord to other window in event */ @@ -2774,7 +2796,9 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U event.x = evt->x = cx; event.y = evt->y = (win->sizey - 1) - cy; } - + + event.val = 0; + /* Use prevx/prevy so we can calculate the delta later */ event.prevx = event.x - pd->deltaX; event.prevy = event.y - (-pd->deltaY); @@ -2788,7 +2812,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U case GHOST_kEventButtonUp: { GHOST_TEventButtonData *bd = customdata; - + + /* get value and type from ghost */ event.val = (type == GHOST_kEventButtonDown) ? KM_PRESS : KM_RELEASE; if (bd->button == GHOST_kButtonMaskLeft) @@ -2802,6 +2827,14 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U else event.type = MIDDLEMOUSE; + /* copy previous state to prev event state (two old!) */ + evt->prevval = evt->val; + evt->prevtype = evt->type; + + /* copy to event state */ + evt->val = event.val; + evt->type = event.type; + if (win->active == 0) { int cx, cy; @@ -2812,6 +2845,23 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U event.y = evt->y = cy; } + /* double click test */ + if (event.type == evt->prevtype && event.val == KM_PRESS) { + if ((ABS(event.x - evt->prevclickx)) <= 2 && + (ABS(event.y - evt->prevclicky)) <= 2 && + ((PIL_check_seconds_timer() - evt->prevclicktime) * 1000 < U.dbl_click_time)) + { + if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) ) + printf("%s Send double click\n", __func__); + event.val = KM_DBL_CLICK; + } + } + if (event.val == KM_PRESS) { + evt->prevclicktime = PIL_check_seconds_timer(); + evt->prevclickx = event.x; + evt->prevclicky = event.y; + } + /* add to other window if event is there (not to both!) */ owin = wm_event_cursor_other_windows(wm, win, &event); if (owin) { @@ -2842,6 +2892,14 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U memcpy(event.utf8_buf, kd->utf8_buf, sizeof(event.utf8_buf)); /* might be not null terminated*/ event.val = (type == GHOST_kEventKeyDown) ? KM_PRESS : KM_RELEASE; + /* copy previous state to prev event state (two old!) */ + evt->prevval = evt->val; + evt->prevtype = evt->type; + + /* copy to event state */ + evt->val = event.val; + evt->type = event.type; + /* exclude arrow keys, esc, etc from text input */ if (type == GHOST_kEventKeyUp) { event.ascii = '\0'; @@ -2867,28 +2925,28 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U } } - /* modifiers */ + /* modifiers assign to eventstate, so next event gets the modifer (makes modifier key events work) */ /* assigning both first and second is strange - campbell */ switch (event.type) { case LEFTSHIFTKEY: case RIGHTSHIFTKEY: - event.shift = evt->shift = (event.val == KM_PRESS) ? - ((evt->ctrl || evt->alt || evt->oskey) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) : - FALSE; + evt->shift = (event.val == KM_PRESS) ? + ((evt->ctrl || evt->alt || evt->oskey) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) : + FALSE; break; case LEFTCTRLKEY: case RIGHTCTRLKEY: - event.ctrl = evt->ctrl = (event.val == KM_PRESS) ? - ((evt->shift || evt->alt || evt->oskey) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) : - FALSE; + evt->ctrl = (event.val == KM_PRESS) ? + ((evt->shift || evt->alt || evt->oskey) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) : + FALSE; break; case LEFTALTKEY: case RIGHTALTKEY: - event.alt = evt->alt = (event.val == KM_PRESS) ? - ((evt->ctrl || evt->shift || evt->oskey) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) : - FALSE; + evt->alt = (event.val == KM_PRESS) ? + ((evt->ctrl || evt->shift || evt->oskey) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) : + FALSE; break; case OSKEY: - event.oskey = evt->oskey = (event.val == KM_PRESS) ? - ((evt->ctrl || evt->alt || evt->shift) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) : - FALSE; + evt->oskey = (event.val == KM_PRESS) ? + ((evt->ctrl || evt->alt || evt->shift) ? (KM_MOD_FIRST | KM_MOD_SECOND) : KM_MOD_FIRST) : + FALSE; break; default: if (event.val == KM_PRESS && event.keymodifier == 0) @@ -2898,12 +2956,24 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U break; } - /* this case happens on some systems that on holding a key pressed, - * generate press events without release, we still want to keep the - * modifier in win->eventstate, but for the press event of the same - * key we don't want the key modifier */ + /* double click test */ + /* if previous event was same type, and previous was release, and now it presses... */ + if (event.type == evt->prevtype && evt->prevval == KM_RELEASE && event.val == KM_PRESS) { + if ((ABS(event.x - evt->prevclickx)) <= 2 && + (ABS(event.y - evt->prevclicky)) <= 2 && + ((PIL_check_seconds_timer() - evt->prevclicktime) * 1000 < U.dbl_click_time)) + { + if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) ) + printf("%s Send double click\n", __func__); + evt->val = event.val = KM_DBL_CLICK; + } + } + + /* this case happens on holding a key pressed, it should not generate + * press events events with the same key as modifier */ if (event.keymodifier == event.type) event.keymodifier = 0; + /* this case happened with an external numpad, it's not really clear * why, but it's also impossible to map a key modifier to an unknwon * key, so it shouldn't harm */ @@ -2911,9 +2981,16 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U event.keymodifier = 0; /* if test_break set, it catches this. XXX Keep global for now? */ - if (event.type == ESCKEY) + if (event.type == ESCKEY && event.val == KM_PRESS) G.is_break = TRUE; + /* double click test - only for press */ + if (event.val == KM_PRESS) { + evt->prevclicktime = PIL_check_seconds_timer(); + evt->prevclickx = event.x; + evt->prevclicky = event.y; + } + wm_event_add(win, &event); break; @@ -2938,6 +3015,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U event.type = TIMER; event.custom = EVT_DATA_TIMER; event.customdata = customdata; + event.val = 0; + event.keymodifier = 0; wm_event_add(win, &event); break; @@ -2946,10 +3025,12 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U case GHOST_kEventNDOFMotion: { event.type = NDOF_MOTION; + event.val = 0; attach_ndof_data(&event, customdata); wm_event_add(win, &event); - //printf("sending NDOF_MOTION, prev = %d %d\n", event.x, event.y); + if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) ) + printf("%s sending NDOF_MOTION, prev = %d %d\n", __func__, event.x, event.y); break; } @@ -2991,7 +3072,4 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U } - /* Handy when debugging checking events */ - /* WM_event_print(&event); */ - } diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index eb6fabd03c6..6124b03778d 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -56,6 +56,7 @@ #include "BLI_blenlib.h" #include "BLI_linklist.h" #include "BLI_utildefines.h" +#include "BLI_threads.h" #include "BLI_callbacks.h" #include "BLF_translation.h" @@ -143,7 +144,7 @@ static void wm_window_match_init(bContext *C, ListBase *wmlist) /* code copied from wm_init_exit.c */ for (wm = wmlist->first; wm; wm = wm->id.next) { - WM_jobs_stop_all(wm); + WM_jobs_kill_all(wm); for (win = wm->windows.first; win; win = win->next) { @@ -189,9 +190,12 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist) /* cases 1 and 2 */ if (oldwmlist->first == NULL) { - if (G.main->wm.first) ; /* nothing todo */ - else + if (G.main->wm.first) { + /* nothing todo */ + } + else { wm_add_default(C); + } } else { /* cases 3 and 4 */ @@ -446,9 +450,8 @@ void WM_file_read(bContext *C, const char *filepath, ReportList *reports) if (sce->r.engine[0] && BLI_findstring(&R_engines, sce->r.engine, offsetof(RenderEngineType, idname)) == NULL) { - BKE_reportf(reports, RPT_WARNING, - "Engine not available: '%s' for scene: %s, " - "an addon may need to be installed or enabled", + BKE_reportf(reports, RPT_ERROR, "Engine '%s' not available for scene '%s' " + "(an addon may need to be installed or enabled)", sce->r.engine, sce->id.name + 2); } } @@ -461,17 +464,17 @@ void WM_file_read(bContext *C, const char *filepath, ReportList *reports) else if (retval == BKE_READ_EXOTIC_OK_OTHER) BKE_write_undo(C, "Import file"); else if (retval == BKE_READ_EXOTIC_FAIL_OPEN) { - BKE_reportf(reports, RPT_ERROR, IFACE_("Can't read file: \"%s\", %s."), filepath, - errno ? strerror(errno) : IFACE_("Unable to open the file")); + BKE_reportf(reports, RPT_ERROR, "Cannot read file '%s': %s", filepath, + errno ? strerror(errno) : TIP_("unable to open the file")); } else if (retval == BKE_READ_EXOTIC_FAIL_FORMAT) { - BKE_reportf(reports, RPT_ERROR, IFACE_("File format is not supported in file: \"%s\"."), filepath); + BKE_reportf(reports, RPT_ERROR, "File format is not supported in file '%s'", filepath); } else if (retval == BKE_READ_EXOTIC_FAIL_PATH) { - BKE_reportf(reports, RPT_ERROR, IFACE_("File path invalid: \"%s\"."), filepath); + BKE_reportf(reports, RPT_ERROR, "File path '%s' invalid", filepath); } else { - BKE_reportf(reports, RPT_ERROR, IFACE_("Unknown error loading: \"%s\"."), filepath); + BKE_reportf(reports, RPT_ERROR, "Unknown error loading '%s'", filepath); BLI_assert(!"invalid 'retval'"); } @@ -712,7 +715,7 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt) IB_rect, FALSE, FALSE, err_out); } - if (ibuf) { + if (ibuf) { float aspect = (scene->r.xsch * scene->r.xasp) / (scene->r.ysch * scene->r.yasp); /* dirty oversampling */ @@ -787,14 +790,14 @@ int WM_file_write(bContext *C, const char *target, int fileflags, ReportList *re /* send the OnSave event */ for (li = G.main->library.first; li; li = li->id.next) { if (BLI_path_cmp(li->filepath, filepath) == 0) { - BKE_reportf(reports, RPT_ERROR, "Can't overwrite used library '%.240s'", filepath); + BKE_reportf(reports, RPT_ERROR, "Cannot overwrite used library '%.240s'", filepath); return -1; } } /* blend file thumbnail */ /* save before exit_editmode, otherwise derivedmeshes for shared data corrupt #27765) */ - if (U.flag & USER_SAVE_PREVIEWS) { + if ((U.flag & USER_SAVE_PREVIEWS) && BLI_thread_is_main()) { ibuf_thumb = blend_file_thumb(CTX_data_scene(C), CTX_wm_screen(C), &thumb); } diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index 2928ba024e5..b3ffb80243a 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -130,8 +130,8 @@ int wm_gesture_evaluate(wmGesture *gesture) { if (gesture->type == WM_GESTURE_TWEAK) { rcti *rect = gesture->customdata; - int dx = BLI_RCT_SIZE_X(rect); - int dy = BLI_RCT_SIZE_Y(rect); + int dx = BLI_rcti_size_x(rect); + int dy = BLI_rcti_size_y(rect); if (ABS(dx) + ABS(dy) > U.tweak_threshold) { int theta = (int)floor(4.0f * atan2f((float)dy, (float)dx) / (float)M_PI + 0.5f); int val = EVT_GESTURE_W; diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 908f7e27f0b..c9f0bbffc63 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -32,8 +32,8 @@ #include #include -#if WIN32 -#include +#ifdef WIN32 +# include #endif #include "MEM_guardedalloc.h" @@ -47,6 +47,10 @@ #include "DNA_userdef_types.h" #include "DNA_windowmanager_types.h" +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + #include "BKE_blender.h" #include "BKE_context.h" #include "BKE_screen.h" @@ -66,10 +70,6 @@ #include "BKE_material.h" /* clear_matcopybuf */ #include "BKE_tracking.h" /* free tracking clipboard */ -#include "BLI_listbase.h" -#include "BLI_string.h" -#include "BLI_utildefines.h" - #include "RE_engine.h" #include "RE_pipeline.h" /* RE_ free stuff */ @@ -114,8 +114,6 @@ #include "BKE_sound.h" #include "COM_compositor.h" -#include "IMB_colormanagement.h" - static void wm_init_reports(bContext *C) { BKE_reports_init(CTX_wm_reports(C), RPT_STORE); @@ -150,9 +148,6 @@ void WM_init(bContext *C, int argc, const char **argv) BLF_init(11, U.dpi); /* Please update source/gamengine/GamePlayer/GPG_ghost.cpp if you change this */ BLF_lang_init(); - /* initialize color management stuff */ - IMB_colormanagement_init(); - /* get the default database, plus a wm */ WM_homefile_read(C, NULL, G.factory_startup); @@ -307,7 +302,7 @@ int WM_init_game(bContext *C) else { ReportTimerInfo *rti; - BKE_report(&wm->reports, RPT_ERROR, "No valid 3D View found. Game auto start is not possible."); + BKE_report(&wm->reports, RPT_ERROR, "No valid 3D View found, game auto start is not possible"); /* After adding the report to the global list, reset the report timer. */ WM_event_remove_timer(wm, NULL, wm->reports.reporttimer); @@ -340,7 +335,7 @@ extern void free_anim_copybuf(void); extern void free_anim_drivers_copybuf(void); extern void free_fmodifiers_copybuf(void); -#if WIN32 +#ifdef WIN32 /* Read console events until there is a key event. Also returns on any error. */ static void wait_for_console_key(void) { @@ -371,15 +366,13 @@ void WM_exit_ext(bContext *C, const short do_python) sound_exit(); - IMB_colormanagement_exit(); - /* first wrap up running stuff, we assume only the active WM is running */ /* modal handlers are on window level freed, others too? */ /* note; same code copied in wm_files.c */ if (C && wm) { wmWindow *win; - WM_jobs_stop_all(wm); + WM_jobs_kill_all(wm); for (win = wm->windows.first; win; win = win->next) { @@ -430,6 +423,7 @@ void WM_exit_ext(bContext *C, const short do_python) #ifdef WITH_INTERNATIONAL BLF_free_unifont(); + BLF_lang_free(); #endif ANIM_keyingset_infos_exit(); diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c index e3d6b0f73e1..42d721327b6 100644 --- a/source/blender/windowmanager/intern/wm_jobs.c +++ b/source/blender/windowmanager/intern/wm_jobs.c @@ -360,7 +360,7 @@ void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job) } } -/* stop job, free data completely */ +/* stop job, end thread, free data completely */ static void wm_jobs_kill_job(wmWindowManager *wm, wmJob *wm_job) { if (wm_job->running) { @@ -385,7 +385,8 @@ static void wm_jobs_kill_job(wmWindowManager *wm, wmJob *wm_job) } -void WM_jobs_stop_all(wmWindowManager *wm) +/* wait until every job ended */ +void WM_jobs_kill_all(wmWindowManager *wm) { wmJob *wm_job; @@ -394,6 +395,18 @@ void WM_jobs_stop_all(wmWindowManager *wm) } +/* wait until every job ended, except for one owner (used in undo to keep screen job alive) */ +void WM_jobs_kill_all_except(wmWindowManager *wm, void *owner) +{ + wmJob *wm_job; + + for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { + if (wm_job->owner != owner) + wm_jobs_kill_job(wm, wm_job); + } +} + + /* signal job(s) from this owner or callback to stop, timer is required to get handled */ void WM_jobs_stop(wmWindowManager *wm, void *owner, void *startjob) { @@ -466,7 +479,7 @@ void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt) if (wm_job->flag & WM_JOB_PROGRESS) WM_event_add_notifier(C, NC_WM | ND_JOB, NULL); wm_job->do_update = FALSE; - } + } if (wm_job->ready) { if (wm_job->endjob) @@ -492,7 +505,11 @@ void wm_jobs_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt) WM_event_add_notifier(C, wm_job->endnote, NULL); WM_event_add_notifier(C, NC_WM | ND_JOB, NULL); - + + /* so the info header updates on job end even if the mouse doesn't move. + * a rather annoying/obscure bug, see [#32537] (second reply) */ + WM_event_add_mousemove_window(wm_job->win); + /* new job added for wm_job? */ if (wm_job->customdata) { // printf("job restarted with new data %s\n", wm_job->name); diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index eb6da146a73..7aa2b403897 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -190,9 +190,9 @@ wmKeyConfig *WM_keyconfig_new_user(wmWindowManager *wm, const char *idname) return keyconf; } -void WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf) +int WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf) { - if (keyconf) { + if (BLI_findindex(&wm->keyconfigs, keyconf) != -1) { if (strncmp(U.keyconfigstr, keyconf->idname, sizeof(U.keyconfigstr)) == 0) { BLI_strncpy(U.keyconfigstr, wm->defaultconf->idname, sizeof(U.keyconfigstr)); WM_keyconfig_update_tag(NULL, NULL); @@ -200,6 +200,11 @@ void WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf) BLI_remlink(&wm->keyconfigs, keyconf); WM_keyconfig_free(keyconf); + + return TRUE; + } + else { + return FALSE; } } @@ -381,7 +386,7 @@ wmKeyMapItem *WM_keymap_add_menu(wmKeyMap *keymap, const char *idname, int type, return kmi; } -void WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi) +int WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi) { if (BLI_findindex(&keymap->items, kmi) != -1) { if (kmi->ptr) { @@ -391,6 +396,10 @@ void WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi) BLI_freelinkN(&keymap->items, kmi); WM_keyconfig_update_tag(keymap, kmi); + return TRUE; + } + else { + return FALSE; } } @@ -816,7 +825,7 @@ char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len) static wmKeyMapItem *wm_keymap_item_find_handlers( const bContext *C, ListBase *handlers, const char *opname, int UNUSED(opcontext), - IDProperty *properties, int compare_props, int hotkey, wmKeyMap **keymap_r) + IDProperty *properties, int is_strict, int hotkey, wmKeyMap **keymap_r) { wmWindowManager *wm = CTX_wm_manager(C); wmEventHandler *handler; @@ -834,9 +843,22 @@ static wmKeyMapItem *wm_keymap_item_find_handlers( if (hotkey) if (!ISHOTKEY(kmi->type)) continue; - - if (compare_props) { - if (kmi->ptr && IDP_EqualsProperties(properties, kmi->ptr->data)) { + + if (properties) { + + /* example of debugging keymaps */ +#if 0 + if (kmi->ptr) { + if (strcmp("MESH_OT_rip_move", opname) == 0) { + printf("OPERATOR\n"); + IDP_spit(properties); + printf("KEYMAP\n"); + IDP_spit(kmi->ptr->data); + } + } +#endif + + if (kmi->ptr && IDP_EqualsProperties_ex(properties, kmi->ptr->data, is_strict)) { if (keymap_r) *keymap_r = keymap; return kmi; } @@ -857,7 +879,7 @@ static wmKeyMapItem *wm_keymap_item_find_handlers( static wmKeyMapItem *wm_keymap_item_find_props( const bContext *C, const char *opname, int opcontext, - IDProperty *properties, int compare_props, int hotkey, wmKeyMap **keymap_r) + IDProperty *properties, int is_strict, int hotkey, wmKeyMap **keymap_r) { wmWindow *win = CTX_wm_window(C); ScrArea *sa = CTX_wm_area(C); @@ -866,11 +888,10 @@ static wmKeyMapItem *wm_keymap_item_find_props( /* look into multiple handler lists to find the item */ if (win) - found = wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r); - + found = wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, is_strict, hotkey, keymap_r); if (sa && found == NULL) - found = wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r); + found = wm_keymap_item_find_handlers(C, &sa->handlers, opname, opcontext, properties, is_strict, hotkey, keymap_r); if (found == NULL) { if (ELEM(opcontext, WM_OP_EXEC_REGION_WIN, WM_OP_INVOKE_REGION_WIN)) { @@ -879,7 +900,7 @@ static wmKeyMapItem *wm_keymap_item_find_props( ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); if (ar) - found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r); + found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, hotkey, keymap_r); } } else if (ELEM(opcontext, WM_OP_EXEC_REGION_CHANNELS, WM_OP_INVOKE_REGION_CHANNELS)) { @@ -887,32 +908,48 @@ static wmKeyMapItem *wm_keymap_item_find_props( ar = BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS); if (ar) - found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r); + found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, hotkey, keymap_r); } else if (ELEM(opcontext, WM_OP_EXEC_REGION_PREVIEW, WM_OP_INVOKE_REGION_PREVIEW)) { if (!(ar && ar->regiontype == RGN_TYPE_PREVIEW)) ar = BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW); if (ar) - found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r); + found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, hotkey, keymap_r); } else { if (ar) - found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r); + found = wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, is_strict, hotkey, keymap_r); } } - + return found; } static wmKeyMapItem *wm_keymap_item_find( const bContext *C, const char *opname, int opcontext, - IDProperty *properties, const short hotkey, const short sloppy, wmKeyMap **keymap_r) + IDProperty *properties, const short hotkey, const short UNUSED(sloppy), wmKeyMap **keymap_r) { wmKeyMapItem *found = wm_keymap_item_find_props(C, opname, opcontext, properties, 1, hotkey, keymap_r); - if (!found && sloppy) - found = wm_keymap_item_find_props(C, opname, opcontext, NULL, 0, hotkey, keymap_r); + if (!found && properties) { + wmOperatorType *ot = WM_operatortype_find(opname, TRUE); + if (ot) { + /* make a copy of the properties and set any unset props + * to their default values, so the ID property compare function succeeds */ + PointerRNA opptr; + IDProperty *properties_default = IDP_CopyProperty(properties); + + RNA_pointer_create(NULL, ot->srna, properties_default, &opptr); + + if (WM_operator_properties_default(&opptr, TRUE)) { + found = wm_keymap_item_find_props(C, opname, opcontext, properties_default, 0, hotkey, keymap_r); + } + + IDP_FreeProperty(properties_default); + MEM_freeN(properties_default); + } + } return found; } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 313fc0a819e..2ef33aa5964 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -79,6 +79,7 @@ #include "BIF_glutil.h" /* for paint cursor */ #include "BLF_api.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -618,6 +619,42 @@ void WM_operator_properties_sanitize(PointerRNA *ptr, const short no_context) RNA_STRUCT_END; } + +/** set all props to their default, + * \param do_update Only update un-initialized props. + * + * \note, theres nothing spesific to operators here. + * this could be made a general function. + */ +int WM_operator_properties_default(PointerRNA *ptr, const int do_update) +{ + int is_change = FALSE; + RNA_STRUCT_BEGIN(ptr, prop) + { + switch (RNA_property_type(prop)) { + case PROP_POINTER: + { + StructRNA *ptype = RNA_property_pointer_type(ptr, prop); + if (ptype != &RNA_Struct) { + PointerRNA opptr = RNA_property_pointer_get(ptr, prop); + is_change |= WM_operator_properties_default(&opptr, do_update); + } + break; + } + default: + if ((do_update == FALSE) || (RNA_property_is_set(ptr, prop) == FALSE)) { + if (RNA_property_reset(ptr, prop, -1)) { + is_change = 1; + } + } + break; + } + } + RNA_STRUCT_END; + + return is_change; +} + /* remove all props without PROP_SKIP_SAVE */ void WM_operator_properties_reset(wmOperator *op) { @@ -673,6 +710,8 @@ int WM_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) else { pup = uiPupMenuBegin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE); layout = uiPupMenuLayout(pup); + /* set this so the default execution context is the same as submenus */ + uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN); uiItemsFullEnumO(layout, op->type->idname, RNA_property_identifier(prop), op->ptr->data, WM_OP_EXEC_REGION_WIN, 0); uiPupMenuEnd(C, pup); } @@ -744,7 +783,7 @@ static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg_op) wmOperator *op = (wmOperator *)arg_op; block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS); - uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_RET_1 | UI_BLOCK_MOVEMOUSE_QUIT); + uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU); #if 0 /* ok, this isn't so easy... */ uiDefBut(block, LABEL, 0, RNA_struct_ui_name(op->type->srna), 10, 10, 180, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); @@ -806,7 +845,7 @@ int WM_operator_filesel(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { if (RNA_struct_property_is_set(op->ptr, "filepath")) { return WM_operator_call_notest(C, op); /* call exec direct */ - } + } else { WM_event_add_fileselect(C, op); return OPERATOR_RUNNING_MODAL; @@ -856,6 +895,8 @@ void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type, RNA_def_collection_runtime(ot->srna, "files", &RNA_OperatorFileListElement, "Files", ""); if (action == FILE_SAVE) { + /* note, this is only used to check if we should highlight the filename area red when the + * filepath is an existing file. */ prop = RNA_def_boolean(ot->srna, "check_existing", 1, "Check Existing", "Check and warn on overwriting existing files"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } @@ -992,7 +1033,7 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); uiBlockClearFlag(block, UI_BLOCK_LOOP); - uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_RET_1 | UI_BLOCK_MOVEMOUSE_QUIT); + uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT); /* if register is not enabled, the operator gets freed on OPERATOR_FINISHED * ui_apply_but_funcs_after calls ED_undo_operator_repeate_cb and crashes */ @@ -1070,7 +1111,7 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData) /* intentionally don't use 'UI_BLOCK_MOVEMOUSE_QUIT', some dialogs have many items * where quitting by accident is very annoying */ - uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_RET_1); + uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN); layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, style); @@ -1111,7 +1152,7 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData) block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); uiBlockClearFlag(block, UI_BLOCK_LOOP); - uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_RET_1 | UI_BLOCK_MOVEMOUSE_QUIT); + uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT); layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, style); @@ -1161,7 +1202,7 @@ int WM_operator_props_popup(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) if ((op->type->flag & OPTYPE_REGISTER) == 0) { BKE_reportf(op->reports, RPT_ERROR, - "Operator '%s' does not have register enabled, incorrect invoke function.", op->type->idname); + "Operator '%s' does not have register enabled, incorrect invoke function", op->type->idname); return OPERATOR_CANCELLED; } @@ -1192,11 +1233,12 @@ int WM_operator_redo_popup(bContext *C, wmOperator *op) { /* CTX_wm_reports(C) because operator is on stack, not active in event system */ if ((op->type->flag & OPTYPE_REGISTER) == 0) { - BKE_reportf(CTX_wm_reports(C), RPT_ERROR, "Operator redo '%s' does not have register enabled, incorrect invoke function.", op->type->idname); + BKE_reportf(CTX_wm_reports(C), RPT_ERROR, + "Operator redo '%s' does not have register enabled, incorrect invoke function", op->type->idname); return OPERATOR_CANCELLED; } if (op->type->poll && op->type->poll(C) == 0) { - BKE_reportf(CTX_wm_reports(C), RPT_ERROR, "Operator redo '%s': wrong context.", op->type->idname); + BKE_reportf(CTX_wm_reports(C), RPT_ERROR, "Operator redo '%s': wrong context", op->type->idname); return OPERATOR_CANCELLED; } @@ -1213,7 +1255,7 @@ static int wm_debug_menu_exec(bContext *C, wmOperator *op) ED_screen_refresh(CTX_wm_manager(C), CTX_wm_window(C)); WM_event_add_notifier(C, NC_WINDOW, NULL); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static int wm_debug_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) @@ -1232,7 +1274,7 @@ static void WM_OT_debug_menu(wmOperatorType *ot) ot->exec = wm_debug_menu_exec; ot->poll = WM_operator_winactive; - RNA_def_int(ot->srna, "debug_value", 0, -10000, 10000, "Debug Value", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "debug_value", 0, SHRT_MIN, SHRT_MAX, "Debug Value", "", -10000, 10000); } @@ -1315,10 +1357,14 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar BLF_size(style->widgetlabel.uifont_id, style->widgetlabel.points, U.dpi); ver_width = (int)BLF_width(style->widgetlabel.uifont_id, version_buf) + 5; rev_width = (int)BLF_width(style->widgetlabel.uifont_id, revision_buf) + 5; -#endif //WITH_BUILDINFO +#endif /* WITH_BUILDINFO */ block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS); - uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN); + + /* note on UI_BLOCK_NO_WIN_CLIP, the window size is not always synchronized + * with the OS when the splash shows, window clipping in this case gives + * ugly results and clipping the splash isn't useful anyway, just disable it [#32938] */ + uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_NO_WIN_CLIP); but = uiDefBut(block, BUT_IMAGE, 0, "", 0, 10, 501, 282, ibuf, 0.0, 0.0, 0, 0, ""); /* button owns the imbuf now */ uiButSetFunc(but, wm_block_splash_close, block, NULL); @@ -1327,7 +1373,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar #ifdef WITH_BUILDINFO uiDefBut(block, LABEL, 0, version_buf, 494 - ver_width, 282 - 24, ver_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); uiDefBut(block, LABEL, 0, revision_buf, 494 - rev_width, 282 - 36, rev_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); -#endif //WITH_BUILDINFO +#endif /* WITH_BUILDINFO */ layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 10, 2, 480, 110, style); @@ -1457,7 +1503,7 @@ static uiBlock *wm_block_search_menu(bContext *C, ARegion *ar, void *UNUSED(arg_ uiBut *but; block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS); - uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_RET_1 | UI_BLOCK_MOVEMOUSE_QUIT); + 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, operator_search_cb, NULL, operator_call_cb, NULL); @@ -1499,12 +1545,12 @@ static int wm_search_menu_poll(bContext *C) else { ScrArea *sa = CTX_wm_area(C); if (sa) { - if (sa->spacetype == SPACE_CONSOLE) return 0; // XXX - so we can use the shortcut in the console - if (sa->spacetype == SPACE_TEXT) return 0; // XXX - so we can use the spacebar in the text editor + if (sa->spacetype == SPACE_CONSOLE) return 0; /* XXX - so we can use the shortcut in the console */ + if (sa->spacetype == SPACE_TEXT) return 0; /* XXX - so we can use the spacebar in the text editor */ } else { Object *editob = CTX_data_edit_object(C); - if (editob && editob->type == OB_FONT) return 0; // XXX - so we can use the spacebar for entering text + if (editob && editob->type == OB_FONT) return 0; /* XXX - so we can use the spacebar for entering text */ } } return 1; @@ -1713,7 +1759,7 @@ static int wm_link_append_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(ev { if (RNA_struct_property_is_set(op->ptr, "filepath")) { return WM_operator_call_notest(C, op); - } + } else { /* XXX TODO solve where to get last linked library from */ if (G.lib[0] != '\0') { @@ -1838,6 +1884,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) /* mark all library linked objects to be updated */ recalc_all_library_objects(bmain); + IMB_colormanagement_check_file_config(bmain); /* append, rather than linking */ if ((flag & FILE_LINK) == 0) { @@ -2108,7 +2155,6 @@ static void WM_OT_save_as_mainfile(wmOperatorType *ot) static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { char name[FILE_MAX]; - int check_existing = 1; int ret; /* cancel if no active window */ @@ -2128,13 +2174,9 @@ static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED( untitled(name); RNA_string_set(op->ptr, "filepath", name); - - if (RNA_struct_find_property(op->ptr, "check_existing")) - if (RNA_boolean_get(op->ptr, "check_existing") == 0) - check_existing = 0; - + if (G.save_over) { - if (check_existing && BLI_exists(name)) { + if (BLI_exists(name)) { uiPupMenuSaveOver(C, op, name); ret = OPERATOR_RUNNING_MODAL; } @@ -2181,7 +2223,7 @@ static int wm_exit_blender_op(bContext *C, wmOperator *op) { WM_operator_free(op); - WM_exit(C); + WM_exit(C); return OPERATOR_FINISHED; } @@ -2279,16 +2321,18 @@ static int border_apply_rect(wmOperator *op) /* operator arguments and storage. */ - RNA_int_set(op->ptr, "xmin", MIN2(rect->xmin, rect->xmax)); - RNA_int_set(op->ptr, "ymin", MIN2(rect->ymin, rect->ymax)); - RNA_int_set(op->ptr, "xmax", MAX2(rect->xmin, rect->xmax)); - RNA_int_set(op->ptr, "ymax", MAX2(rect->ymin, rect->ymax)); + RNA_int_set(op->ptr, "xmin", min_ii(rect->xmin, rect->xmax)); + RNA_int_set(op->ptr, "ymin", min_ii(rect->ymin, rect->ymax)); + RNA_int_set(op->ptr, "xmax", max_ii(rect->xmin, rect->xmax)); + RNA_int_set(op->ptr, "ymax", max_ii(rect->ymin, rect->ymax)); return 1; } static int border_apply(bContext *C, wmOperator *op, int gesture_mode) { + int retval; + if (!border_apply_rect(op)) return 0; @@ -2296,7 +2340,9 @@ static int border_apply(bContext *C, wmOperator *op, int gesture_mode) if (RNA_struct_find_property(op->ptr, "gesture_mode") ) RNA_int_set(op->ptr, "gesture_mode", gesture_mode); - op->type->exec(C, op); + retval = op->type->exec(C, op); + OPERATOR_RETVAL_CHECK(retval); + return 1; } @@ -2422,8 +2468,11 @@ static void gesture_circle_apply(bContext *C, wmOperator *op) RNA_int_set(op->ptr, "y", rect->ymin); RNA_int_set(op->ptr, "radius", rect->xmax); - if (op->type->exec) - op->type->exec(C, op); + if (op->type->exec) { + int retval; + retval = op->type->exec(C, op); + OPERATOR_RETVAL_CHECK(retval); + } #ifdef GESTURE_MEMORY circle_select_size = rect->xmax; #endif @@ -2643,8 +2692,10 @@ static void gesture_lasso_apply(bContext *C, wmOperator *op) wm_gesture_end(C, op); - if (op->type->exec) - op->type->exec(C, op); + if (op->type->exec) { + int retval = op->type->exec(C, op); + OPERATOR_RETVAL_CHECK(retval); + } } int WM_gesture_lasso_modal(bContext *C, wmOperator *op, wmEvent *event) @@ -2727,7 +2778,7 @@ int WM_gesture_lines_cancel(bContext *C, wmOperator *op) * * caller must free. */ -int (*WM_gesture_lasso_path_to_array(bContext *UNUSED(C), wmOperator *op, int *mcords_tot))[2] +const int (*WM_gesture_lasso_path_to_array(bContext *UNUSED(C), wmOperator *op, int *mcords_tot))[2] { PropertyRNA *prop = RNA_struct_find_property(op->ptr, "path"); int (*mcords)[2] = NULL; @@ -2757,7 +2808,8 @@ int (*WM_gesture_lasso_path_to_array(bContext *UNUSED(C), wmOperator *op, int *m *mcords_tot = 0; } - return mcords; + /* cast for 'const' */ + return (const int (*)[2])mcords; } #if 0 @@ -2812,8 +2864,10 @@ static int straightline_apply(bContext *C, wmOperator *op) RNA_int_set(op->ptr, "xend", rect->xmax); RNA_int_set(op->ptr, "yend", rect->ymax); - if (op->type->exec) - op->type->exec(C, op); + if (op->type->exec) { + int retval = op->type->exec(C, op); + OPERATOR_RETVAL_CHECK(retval); + } return 1; } @@ -3115,7 +3169,7 @@ static int radial_control_get_path(PointerRNA *ctx_ptr, wmOperator *op, /* check flags */ if ((flags & RC_PROP_REQUIRE_BOOL) && (flags & RC_PROP_REQUIRE_FLOAT)) { - BKE_reportf(op->reports, RPT_ERROR, "Property can't be both boolean and float"); + BKE_report(op->reports, RPT_ERROR, "Property cannot be both boolean and float"); return 0; } @@ -3138,7 +3192,7 @@ static int radial_control_get_path(PointerRNA *ctx_ptr, wmOperator *op, if (flags & RC_PROP_ALLOW_MISSING) return 1; else { - BKE_reportf(op->reports, RPT_ERROR, "Couldn't resolve path %s", name); + BKE_reportf(op->reports, RPT_ERROR, "Could not resolve path '%s'", name); return 0; } } @@ -3151,8 +3205,7 @@ static int radial_control_get_path(PointerRNA *ctx_ptr, wmOperator *op, ((flags & RC_PROP_REQUIRE_FLOAT) && prop_type != PROP_FLOAT)) { MEM_freeN(str); - BKE_reportf(op->reports, RPT_ERROR, - "Property from path %s is not a float", name); + BKE_reportf(op->reports, RPT_ERROR, "Property from path '%s' is not a float", name); return 0; } } @@ -3160,8 +3213,7 @@ static int radial_control_get_path(PointerRNA *ctx_ptr, wmOperator *op, /* check property's array length */ if (*r_prop && (len = RNA_property_array_length(r_ptr, *r_prop)) != req_length) { MEM_freeN(str); - BKE_reportf(op->reports, RPT_ERROR, - "Property from path %s has length %d instead of %d", + BKE_reportf(op->reports, RPT_ERROR, "Property from path '%s' has length %d instead of %d", name, len, req_length); return 0; } @@ -3229,8 +3281,7 @@ static int radial_control_get_properties(bContext *C, wmOperator *op) else if (rc->image_id_ptr.data) { /* extra check, pointer must be to an ID */ if (!RNA_struct_is_ID(rc->image_id_ptr.type)) { - BKE_report(op->reports, RPT_ERROR, - "Pointer from path image_id is not an ID"); + BKE_report(op->reports, RPT_ERROR, "Pointer from path image_id is not an ID"); return 0; } } @@ -3471,7 +3522,7 @@ static int redraw_timer_exec(bContext *C, wmOperator *op) if (type == 0) { if (ar) ED_region_do_draw(C, ar); - } + } else if (type == 1) { wmWindow *win = CTX_wm_window(C); @@ -3844,7 +3895,7 @@ static void gesture_border_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_assign(keymap, "VIEW3D_OT_clip_border"); WM_modalkeymap_assign(keymap, "VIEW3D_OT_render_border"); WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_border"); - WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom_border"); // XXX TODO: zoom border should perhaps map rightmouse to zoom out instead of in+cancel + WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom_border"); /* XXX TODO: zoom border should perhaps map rightmouse to zoom out instead of in+cancel */ } /* zoom to border modal operators */ diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index bff40faf1d1..96bbedfee1b 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -89,6 +89,8 @@ typedef struct PlayState { short stopped; short go; + int fstep; + /* current picture */ struct PlayAnimPict *picture; @@ -213,7 +215,6 @@ typedef struct PlayAnimPict { static struct ListBase picsbase = {NULL, NULL}; static int fromdisk = FALSE; -static int fstep = 1; static float zoomx = 1.0, zoomy = 1.0; static double ptottime = 0.0, swaptime = 0.04; @@ -229,7 +230,7 @@ static int pupdate_time(void) return (ptottime < 0); } -static void playanim_toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fontid) +static void playanim_toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fontid, int fstep) { if (ibuf == NULL) { @@ -287,7 +288,7 @@ static void build_pict_list(char *first, int totframes, int fstep, int fontid) int pic; ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); if (ibuf) { - playanim_toscreen(NULL, ibuf, fontid); + playanim_toscreen(NULL, ibuf, fontid, fstep); IMB_freeImBuf(ibuf); } @@ -390,7 +391,7 @@ static void build_pict_list(char *first, int totframes, int fstep, int fontid) ibuf = IMB_loadiffname(picture->name, picture->IB_flags, NULL); } if (ibuf) { - playanim_toscreen(picture, ibuf, fontid); + playanim_toscreen(picture, ibuf, fontid, fstep); IMB_freeImBuf(ibuf); } pupdate_time(); @@ -446,34 +447,34 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) if (val) ps->pingpong = !ps->pingpong; break; case GHOST_kKeyNumpad1: - if (val) swaptime = fstep / 60.0; + if (val) swaptime = ps->fstep / 60.0; break; case GHOST_kKeyNumpad2: - if (val) swaptime = fstep / 50.0; + if (val) swaptime = ps->fstep / 50.0; break; case GHOST_kKeyNumpad3: - if (val) swaptime = fstep / 30.0; + if (val) swaptime = ps->fstep / 30.0; break; case GHOST_kKeyNumpad4: if (g_WS.qual & WS_QUAL_SHIFT) - swaptime = fstep / 24.0; + swaptime = ps->fstep / 24.0; else - swaptime = fstep / 25.0; + swaptime = ps->fstep / 25.0; break; case GHOST_kKeyNumpad5: - if (val) swaptime = fstep / 20.0; + if (val) swaptime = ps->fstep / 20.0; break; case GHOST_kKeyNumpad6: - if (val) swaptime = fstep / 15.0; + if (val) swaptime = ps->fstep / 15.0; break; case GHOST_kKeyNumpad7: - if (val) swaptime = fstep / 12.0; + if (val) swaptime = ps->fstep / 12.0; break; case GHOST_kKeyNumpad8: - if (val) swaptime = fstep / 10.0; + if (val) swaptime = ps->fstep / 10.0; break; case GHOST_kKeyNumpad9: - if (val) swaptime = fstep / 6.0; + if (val) swaptime = ps->fstep / 6.0; break; case GHOST_kKeyLeftArrow: if (val) { @@ -531,10 +532,10 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) if (val) { if (g_WS.qual & WS_QUAL_SHIFT) { if (ps->curframe_ibuf) - printf(" Name: %s | Speed: %.2f frames/s\n", ps->curframe_ibuf->name, fstep / swaptime); + printf(" Name: %s | Speed: %.2f frames/s\n", ps->curframe_ibuf->name, ps->fstep / swaptime); } else { - swaptime = fstep / 5.0; + swaptime = ps->fstep / 5.0; } } break; @@ -589,8 +590,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) break; case GHOST_kKeyNumpadPlus: if (val == 0) break; - zoomx += 2.0; - zoomy += 2.0; + zoomx += 2.0f; + zoomy += 2.0f; /* no break??? - is this intentional? - campbell XXX25 */ case GHOST_kKeyNumpadMinus: { @@ -598,8 +599,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) /* int ofsx, ofsy; */ /* UNUSED */ if (val == 0) break; - if (zoomx > 1.0) zoomx -= 1.0; - if (zoomy > 1.0) zoomy -= 1.0; + if (zoomx > 1.0f) zoomx -= 1.0f; + if (zoomy > 1.0f) zoomy -= 1.0f; // playanim_window_get_position(&ofsx, &ofsy); playanim_window_get_size(&sizex, &sizey); /* ofsx += sizex / 2; */ /* UNUSED */ @@ -664,10 +665,10 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) zoomx = (float) sizex / ps->ibufx; zoomy = (float) sizey / ps->ibufy; - zoomx = floor(zoomx + 0.5); - zoomy = floor(zoomy + 0.5); - if (zoomx < 1.0) zoomx = 1.0; - if (zoomy < 1.0) zoomy = 1.0; + zoomx = floor(zoomx + 0.5f); + zoomy = floor(zoomy + 0.5f); + if (zoomx < 1.0f) zoomx = 1.0f; + if (zoomy < 1.0f) zoomy = 1.0f; sizex = zoomx * ps->ibufx; sizey = zoomy * ps->ibufy; @@ -675,7 +676,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) glPixelZoom(zoomx, zoomy); glEnable(GL_DITHER); ptottime = 0.0; - playanim_toscreen(ps->picture, ps->curframe_ibuf, ps->fontid); + playanim_toscreen(ps->picture, ps->curframe_ibuf, ps->fontid, ps->fstep); break; } @@ -713,14 +714,6 @@ static void playanim_window_open(const char *title, int posx, int posy, int size inital_state, GHOST_kDrawingContextTypeOpenGL, FALSE /* no stereo */, FALSE); - - //if (ghostwin) { - //if (win) { - // GHOST_SetWindowUserData(ghostwin, win); - //} else { - // GHOST_DisposeWindow(g_WS.ghost_system, ghostwin); - //} - //} } @@ -755,6 +748,8 @@ void WM_main_playanim(int argc, const char **argv) ps.picture = NULL; /* resetmap = FALSE */ + ps.fstep = 1; + ps.fontid = -1; while (argc > 1) { @@ -802,8 +797,8 @@ void WM_main_playanim(int argc, const char **argv) argv++; break; case 'j': - fstep = MIN2(MAXFRAME, MAX2(1, atoi(argv[2]))); - swaptime *= fstep; + ps.fstep = MIN2(MAXFRAME, MAX2(1, atoi(argv[2]))); + swaptime *= ps.fstep; argc--; argv++; break; @@ -902,11 +897,11 @@ void WM_main_playanim(int argc, const char **argv) efra = MAXFRAME; } - build_pict_list(filepath, (efra - sfra) + 1, fstep, ps.fontid); + build_pict_list(filepath, (efra - sfra) + 1, ps.fstep, ps.fontid); for (i = 2; i < argc; i++) { BLI_strncpy(filepath, argv[i], sizeof(filepath)); - build_pict_list(filepath, (efra - sfra) + 1, fstep, ps.fontid); + build_pict_list(filepath, (efra - sfra) + 1, ps.fstep, ps.fontid); } IMB_freeImBuf(ibuf); @@ -978,7 +973,7 @@ void WM_main_playanim(int argc, const char **argv) while (pupdate_time()) PIL_sleep_ms(1); ptottime -= swaptime; - playanim_toscreen(ps.picture, ibuf, ps.fontid); + playanim_toscreen(ps.picture, ibuf, ps.fontid, ps.fstep); } /* else deleten */ else { printf("error: can't play this image type\n"); diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c index adf54af240b..8533494ae96 100644 --- a/source/blender/windowmanager/intern/wm_subwindow.c +++ b/source/blender/windowmanager/intern/wm_subwindow.c @@ -116,8 +116,8 @@ void wm_subwindow_getsize(wmWindow *win, int swinid, int *x, int *y) wmSubWindow *swin = swin_from_swinid(win, swinid); if (swin) { - *x = BLI_RCT_SIZE_X(&swin->winrct) + 1; - *y = BLI_RCT_SIZE_Y(&swin->winrct) + 1; + *x = BLI_rcti_size_x(&swin->winrct) + 1; + *y = BLI_rcti_size_y(&swin->winrct) + 1; } } @@ -163,10 +163,6 @@ int wm_subwindow_open(wmWindow *win, rcti *winrct) win->curswin = swin = MEM_callocN(sizeof(wmSubWindow), "swinopen"); BLI_addtail(&win->subwindows, swin); - if (G.debug & G_DEBUG_EVENTS) { - printf("%s: swin %d added\n", __func__, freewinid); - } - swin->swinid = freewinid; swin->winrct = *winrct; @@ -192,7 +188,7 @@ void wm_subwindow_close(wmWindow *win, int swinid) wm_subwindow_free(swin); BLI_remlink(&win->subwindows, swin); MEM_freeN(swin); - } + } else { printf("%s: Internal error, bad winid: %d\n", __func__, swinid); } @@ -256,13 +252,13 @@ void wmSubWindowScissorSet(wmWindow *win, int swinid, rcti *srct) win->curswin = _curswin; _curwindow = win; - width = BLI_RCT_SIZE_X(&_curswin->winrct) + 1; - height = BLI_RCT_SIZE_Y(&_curswin->winrct) + 1; + width = BLI_rcti_size_x(&_curswin->winrct) + 1; + height = BLI_rcti_size_y(&_curswin->winrct) + 1; glViewport(_curswin->winrct.xmin, _curswin->winrct.ymin, width, height); if (srct) { - width = BLI_RCT_SIZE_X(srct) + 1; - height = BLI_RCT_SIZE_Y(srct) + 1; + width = BLI_rcti_size_x(srct) + 1; + height = BLI_rcti_size_y(srct) + 1; glScissor(srct->xmin, srct->ymin, width, height); } else @@ -398,7 +394,7 @@ int WM_framebuffer_to_index(unsigned int col) return col & 0xFFFFFF; default: // 18 bits... return ((col & 0xFC0000) >> 6) + ((col & 0xFC00) >> 4) + ((col & 0xFC) >> 2); - } + } } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 59c8235faf0..616567e8184 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -164,7 +164,7 @@ void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win) if (CTX_wm_window(C) == win) CTX_wm_window_set(C, NULL); - } + } /* always set drawable and active to NULL, * prevents non-drawable state of main windows (bugs #22967 and #25071, possibly #22477 too) */ @@ -300,11 +300,9 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) void wm_window_title(wmWindowManager *wm, wmWindow *win) { - /* handle the 'temp' window, only set title when not set before */ if (win->screen && win->screen->temp) { - char *title = GHOST_GetTitle(win->ghostwin); - if (title == NULL || title[0] == 0) - GHOST_SetTitle(win->ghostwin, "Blender"); + /* nothing to do for 'temp' windows, + * because WM_window_open_temp always sets window title */ } else { @@ -416,6 +414,10 @@ void wm_window_add_ghostwindows(wmWindowManager *wm) win->posy = wm_init_state.start_y; win->sizex = wm_init_state.size_x; win->sizey = wm_init_state.size_y; + + /* we can't properly resize a maximized window */ + win->windowstate = GHOST_kWindowStateNormal; + wm_init_state.override_flag &= ~WIN_OVERRIDE_GEOM; } @@ -458,8 +460,8 @@ wmWindow *WM_window_open(bContext *C, rcti *rect) win->posx = rect->xmin; win->posy = rect->ymin; - win->sizex = BLI_RCT_SIZE_X(rect); - win->sizey = BLI_RCT_SIZE_Y(rect); + win->sizex = BLI_rcti_size_x(rect); + win->sizey = BLI_rcti_size_y(rect); win->drawmethod = -1; win->drawdata = NULL; @@ -494,8 +496,8 @@ void WM_window_open_temp(bContext *C, rcti *position, int type) win->posy = position->ymin; } - win->sizex = BLI_RCT_SIZE_X(position); - win->sizey = BLI_RCT_SIZE_Y(position); + win->sizex = BLI_rcti_size_x(position); + win->sizey = BLI_rcti_size_y(position); if (win->ghostwin) { wm_window_set_size(win, win->sizex, win->sizey); @@ -650,7 +652,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr else if (!GHOST_ValidWindow(g_system, ghostwin)) { /* XXX - should be checked, why are we getting an event here, and */ /* what is it? */ - puts(" event has invalid window"); + puts(" event has invalid window"); return 1; } else { @@ -933,7 +935,7 @@ static int wm_window_timer(const bContext *C) wt->delta = time - wt->ltime; wt->duration += wt->delta; wt->ltime = time; - wt->ntime = wt->stime + wt->timestep *ceil(wt->duration / wt->timestep); + wt->ntime = wt->stime + wt->timestep * ceil(wt->duration / wt->timestep); if (wt->event_type == TIMERJOBS) wm_jobs_timer(C, wm, wt); @@ -943,6 +945,8 @@ static int wm_window_timer(const bContext *C) wmEvent event = *(win->eventstate); event.type = wt->event_type; + event.val = 0; + event.keymodifier = 0; event.custom = EVT_DATA_TIMER; event.customdata = wt; wm_event_add(win, &event); @@ -1003,7 +1007,7 @@ void wm_ghost_init(bContext *C) g_system = GHOST_CreateSystem(); GHOST_AddEventConsumer(g_system, consumer); - } + } } void wm_ghost_exit(void) @@ -1078,7 +1082,7 @@ char *WM_clipboard_text_get(int selection) return NULL; /* always convert from \r\n to \n */ - newbuf = MEM_callocN(strlen(buf) + 1, "WM_clipboard_text_get"); + newbuf = MEM_callocN(strlen(buf) + 1, __func__); for (p = buf, p2 = newbuf; *p; p++) { if (*p != '\r') diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h index a33d37ac50e..2d0dd2ef911 100644 --- a/source/blender/windowmanager/wm_event_system.h +++ b/source/blender/windowmanager/wm_event_system.h @@ -32,10 +32,10 @@ #define __WM_EVENT_SYSTEM_H__ /* return value of handler-operator call */ -#define WM_HANDLER_CONTINUE 0 -#define WM_HANDLER_BREAK 1 -#define WM_HANDLER_HANDLED 2 -#define WM_HANDLER_MODAL 4 /* MODAL|BREAK means unhandled */ +#define WM_HANDLER_CONTINUE 0 +#define WM_HANDLER_BREAK 1 +#define WM_HANDLER_HANDLED 2 +#define WM_HANDLER_MODAL 4 /* MODAL|BREAK means unhandled */ struct ScrArea; struct ARegion; @@ -44,40 +44,40 @@ struct ARegion; typedef struct wmEventHandler { struct wmEventHandler *next, *prev; - - int type, flag; /* type default=0, rest is custom */ - + + int type, flag; /* type default=0, rest is custom */ + /* keymap handler */ - wmKeyMap *keymap; /* pointer to builtin/custom keymaps */ - rcti *bblocal, *bbwin; /* optional local and windowspace bb */ - + wmKeyMap *keymap; /* pointer to builtin/custom keymaps */ + rcti *bblocal, *bbwin; /* optional local and windowspace bb */ + /* modal operator handler */ - wmOperator *op; /* for derived/modal handlers */ - struct ScrArea *op_area; /* for derived/modal handlers */ - struct ARegion *op_region; /* for derived/modal handlers */ + wmOperator *op; /* for derived/modal handlers */ + struct ScrArea *op_area; /* for derived/modal handlers */ + struct ARegion *op_region; /* for derived/modal handlers */ /* ui handler */ - wmUIHandlerFunc ui_handle; /* callback receiving events */ - wmUIHandlerRemoveFunc ui_remove; /* callback when handler is removed */ - void *ui_userdata; /* user data pointer */ - struct ScrArea *ui_area; /* for derived/modal handlers */ - struct ARegion *ui_region; /* for derived/modal handlers */ - struct ARegion *ui_menu; /* for derived/modal handlers */ - + wmUIHandlerFunc ui_handle; /* callback receiving events */ + wmUIHandlerRemoveFunc ui_remove; /* callback when handler is removed */ + void *ui_userdata; /* user data pointer */ + struct ScrArea *ui_area; /* for derived/modal handlers */ + struct ARegion *ui_region; /* for derived/modal handlers */ + struct ARegion *ui_menu; /* for derived/modal handlers */ + /* fileselect handler re-uses modal operator data */ - struct bScreen *filescreen; /* screen it started in, to validate exec */ - + struct bScreen *filescreen; /* screen it started in, to validate exec */ + /* drop box handler */ ListBase *dropboxes; - + } wmEventHandler; /* handler flag */ /* after this handler all others are ignored */ -#define WM_HANDLER_BLOCKING 1 +#define WM_HANDLER_BLOCKING 1 /* handler tagged to be freed in wm_handlers_do() */ -#define WM_HANDLER_DO_FREE 2 +#define WM_HANDLER_DO_FREE 2 @@ -89,23 +89,23 @@ enum { /* wm_event_system.c */ -void wm_event_free_all (wmWindow *win); -void wm_event_free (wmEvent *event); -void wm_event_free_handler (wmEventHandler *handler); +void wm_event_free_all (wmWindow *win); +void wm_event_free (wmEvent *event); +void wm_event_free_handler (wmEventHandler *handler); - /* goes over entire hierarchy: events -> window -> screen -> area -> region */ -void wm_event_do_handlers (bContext *C); + /* goes over entire hierarchy: events -> window -> screen -> area -> region */ +void wm_event_do_handlers (bContext *C); -void wm_event_add_ghostevent (wmWindowManager *wm, wmWindow *win, int type, int time, void *customdata); +void wm_event_add_ghostevent (wmWindowManager *wm, wmWindow *win, int type, int time, void *customdata); -void wm_event_do_notifiers (bContext *C); +void wm_event_do_notifiers (bContext *C); /* wm_keymap.c */ /* wm_dropbox.c */ -void wm_dropbox_free(void); -void wm_drags_check_ops(bContext *C, wmEvent *event); -void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect); +void wm_dropbox_free(void); +void wm_drags_check_ops(bContext *C, wmEvent *event); +void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect); #endif /* __WM_EVENT_SYSTEM_H__ */ diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index 95a8a7db635..ca0e9659a22 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -285,8 +285,9 @@ enum { /* for event checks */ /* only used for KM_TEXTINPUT, so assume that we want all user-inputtable ascii codes included */ + /* UNUSED - see wm_eventmatch - BUG [#30479] #define ISTEXTINPUT(event) (event >= ' ' && event <= 255) - + */ /* test whether the event is a key on the keyboard */ #define ISKEYBOARD(event) (event >= ' ' && event <= 320) diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index 04d4be05034..828b7f5066c 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -148,6 +148,7 @@ endif() extern_recastnavigation bf_intern_raskter bf_intern_opencolorio + bf_intern_opennl ) if(WITH_MOD_CLOTH_ELTOPO) @@ -169,10 +170,6 @@ endif() list(APPEND BLENDER_SORTED_LIBS extern_colamd) - if(WITH_MOD_DECIMATE) - list(APPEND BLENDER_SORTED_LIBS bf_intern_decimate) - endif() - if(WITH_MOD_BOOLEAN) list(APPEND BLENDER_SORTED_LIBS bf_intern_bsp) list(APPEND BLENDER_SORTED_LIBS bf_intern_moto) diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index c6383b471f7..238f3468a41 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -60,7 +60,6 @@ struct Image; struct ImageUser; struct KeyingSet; struct KeyingSetInfo; -struct LOD_Decimation_Info; struct MCol; struct MTex; struct Main; @@ -76,6 +75,7 @@ struct Nurb; struct Object; struct PBVHNode; struct PyObject; +struct Quadric; struct Render; struct RenderEngine; struct RenderEngineType; @@ -134,6 +134,13 @@ int BLI_smallhash_count(struct SmallHash *hash) { return 0; } void *BLI_smallhash_iternext(struct SmallHashIter *iter, uintptr_t *key) { return NULL; } void *BLI_smallhash_iternew(struct SmallHash *hash, struct SmallHashIter *iter, uintptr_t *key) { return NULL; } +void BLI_quadric_from_v3_dist(struct Quadric *q, const float v[3], const float offset) {} +void BLI_quadric_add_qu_qu(struct Quadric *a, const struct Quadric *b) {} +void BLI_quadric_add_qu_ququ(struct Quadric *r, const struct Quadric *a, const struct Quadric *b) {} +void BLI_quadric_mul(struct Quadric *a, const float scalar) {} +float BLI_quadric_evaluate(const struct Quadric *q, const float v[3]) {return 0.0f;} +int BLI_quadric_optimize(const struct Quadric *q, float v[3]) {return 0;} + float *RE_RenderLayerGetPass(struct RenderLayer *rl, int passtype) {return (float *) NULL;} float RE_filter_value(int type, float x) {return 0.0f;} struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name) {return (struct RenderLayer *)NULL;} @@ -191,7 +198,7 @@ struct MenuType *WM_menutype_find(const char *idname, int quiet) {return (struct void WM_operator_stack_clear(struct bContext *C) {} void WM_autosave_init(struct bContext *C) {} -void WM_jobs_stop_all(struct wmWindowManager *wm) {} +void WM_jobs_kill_all_except(struct wmWindowManager *wm) {} char *WM_clipboard_text_get(int selection) {return (char*)0;} void WM_clipboard_text_set(char *buf, int selection) {} @@ -297,6 +304,7 @@ struct BGpic *ED_view3D_background_image_new(struct View3D *v3d) {return (struct void ED_view3D_background_image_remove(struct View3D *v3d, struct BGpic *bgpic) {} void ED_view3D_background_image_clear(struct View3D *v3d) {} void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[][4], float winmat[][4]) {} +float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit) {return 0.0f;} void view3d_apply_mat4(float mat[][4], float *ofs, float *quat, float *dist) {} int text_file_modified(struct Text *text) {return 0;} void ED_node_shader_default(struct Material *ma) {} diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 3356091b97f..c06669c3ac2 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -636,7 +636,7 @@ elseif(WIN32) if(WITH_OPENIMAGEIO) if(NOT MINGW) - set_lib_path(OIIOBIN "openimageio") + set(OIIOBIN ${LIBDIR}/openimageio) install( FILES ${OIIOBIN}/bin/OpenImageIO.dll @@ -646,13 +646,19 @@ elseif(WIN32) endif() if(WITH_OPENCOLORIO) + set(OCIOBIN ${LIBDIR}/opencolorio/bin) if(NOT MINGW) - set_lib_path(OCIOBIN "opencolorio/bin") install( FILES ${OCIOBIN}/OpenColorIO.dll DESTINATION ${TARGETDIR} ) + else() + install( + FILES + ${OCIOBIN}/libOpenColorIO.dll + DESTINATION ${TARGETDIR} + ) endif() endif() @@ -730,7 +736,7 @@ elseif(APPLE) ) endif() - + # install blenderplayer bundle - copy of blender.app above. re-using macros et al # note we are using OSX Bundle as base and copying Blender dummy bundle on top of it if(WITH_GAMEENGINE AND WITH_PLAYER) @@ -772,6 +778,7 @@ elseif(APPLE) endif() endif() + endif() # ----------------------------------------------------------------------------- @@ -883,7 +890,6 @@ endif() bf_imbuf_dds bf_collada bf_intern_bsp - bf_intern_decimate bf_intern_elbeem bf_intern_memutil bf_intern_guardedalloc diff --git a/source/creator/creator.c b/source/creator/creator.c index ab9541cf299..ca3deaf70a4 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -1128,6 +1128,7 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle) #endif BLI_argsAdd(ba, 1, NULL, "--debug-python", "\n\tEnable debug messages for python", debug_mode_generic, (void *)G_DEBUG_PYTHON); BLI_argsAdd(ba, 1, NULL, "--debug-events", "\n\tEnable debug messages for the event system", debug_mode_generic, (void *)G_DEBUG_EVENTS); + BLI_argsAdd(ba, 1, NULL, "--debug-handlers", "\n\tEnable debug messages for event handling", debug_mode_generic, (void *)G_DEBUG_HANDLERS); BLI_argsAdd(ba, 1, NULL, "--debug-wm", "\n\tEnable debug messages for the window manager", debug_mode_generic, (void *)G_DEBUG_WM); BLI_argsAdd(ba, 1, NULL, "--debug-all", "\n\tEnable all debug messages (excludes libmv)", debug_mode_generic, (void *)G_DEBUG_ALL); diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 3a06fe979e1..6807f531f0a 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -35,9 +35,9 @@ #include #include -#if defined(WIN32) && !defined(FREE_WINDOWS) -// don't show stl-warnings -#pragma warning (disable:4786) +#ifdef _MSC_VER + /* don't show stl-warnings */ +# pragma warning (disable:4786) #endif #include "GL/glew.h" @@ -69,37 +69,33 @@ #include "Value.h" - -#ifdef __cplusplus extern "C" { -#endif - /***/ -#include "DNA_view3d_types.h" -#include "DNA_screen_types.h" -#include "DNA_userdef_types.h" -#include "DNA_windowmanager_types.h" -#include "BKE_global.h" -#include "BKE_report.h" + #include "DNA_view3d_types.h" + #include "DNA_screen_types.h" + #include "DNA_userdef_types.h" + #include "DNA_scene_types.h" + #include "DNA_windowmanager_types.h" -#include "MEM_guardedalloc.h" + #include "BKE_global.h" + #include "BKE_report.h" + #include "BKE_ipo.h" + #include "BKE_main.h" + #include "BKE_context.h" -/* #include "BKE_screen.h" */ /* cant include this because of 'new' function name */ -extern float BKE_screen_view3d_zoom_to_fac(float camzoom); + /* avoid c++ conflict with 'new' */ + #define new _new + #include "BKE_screen.h" + #undef new -#include "BKE_main.h" -#include "BLI_blenlib.h" -#include "BLO_readfile.h" -#include "DNA_scene_types.h" -#include "BKE_ipo.h" - /***/ + #include "MEM_guardedalloc.h" -#include "BKE_context.h" -#include "../../blender/windowmanager/WM_types.h" -#include "../../blender/windowmanager/wm_window.h" -#include "../../blender/windowmanager/wm_event_system.h" -#ifdef __cplusplus + #include "BLI_blenlib.h" + #include "BLO_readfile.h" + + #include "../../blender/windowmanager/WM_types.h" + #include "../../blender/windowmanager/wm_window.h" + #include "../../blender/windowmanager/wm_event_system.h" } -#endif #ifdef WITH_AUDASPACE # include "AUD_C-API.h" @@ -125,8 +121,8 @@ static BlendFileData *load_game_data(char *filename) return bfd; } -int BL_KetsjiNextFrame(KX_KetsjiEngine *ketsjiengine, bContext *C, wmWindow *win, Scene *scene, ARegion *ar, - KX_BlenderKeyboardDevice* keyboarddevice, KX_BlenderMouseDevice* mousedevice, int draw_letterbox) +static int BL_KetsjiNextFrame(KX_KetsjiEngine *ketsjiengine, bContext *C, wmWindow *win, Scene *scene, ARegion *ar, + KX_BlenderKeyboardDevice* keyboarddevice, KX_BlenderMouseDevice* mousedevice, int draw_letterbox) { int exitrequested; @@ -143,7 +139,7 @@ int BL_KetsjiNextFrame(KX_KetsjiEngine *ketsjiengine, bContext *C, wmWindow *win // itself is unaware of the extra space, so we clear the whole region for it. glClearColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 1.0f); glViewport(ar->winrct.xmin, ar->winrct.ymin, - BLI_RCT_SIZE_X(&ar->winrct), BLI_RCT_SIZE_Y(&ar->winrct)); + BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct)); glClear(GL_COLOR_BUFFER_BIT); } @@ -198,7 +194,7 @@ struct BL_KetsjiNextFrameState { int draw_letterbox; } ketsjinextframestate; -int BL_KetsjiPyNextFrame(void *state0) +static int BL_KetsjiPyNextFrame(void *state0) { BL_KetsjiNextFrameState *state = (BL_KetsjiNextFrameState *) state0; return BL_KetsjiNextFrame( @@ -552,7 +548,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c ketsjinextframestate.draw_letterbox = draw_letterbox; pynextframestate.state = &ketsjinextframestate; - pynextframestate.func = &BL_KetsjiPyNextFrame; + pynextframestate.func = &BL_KetsjiPyNextFrame; printf("Yielding control to Python script '%s'...\n", python_main); PyRun_SimpleString(python_code); printf("Exit Python script '%s'\n", python_main); @@ -590,7 +586,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c const Py_ssize_t numitems= PyList_GET_SIZE(gameLogic_keys_new); Py_ssize_t listIndex; for (listIndex=0; listIndex < numitems; listIndex++) { - PyObject* item = PyList_GET_ITEM(gameLogic_keys_new, listIndex); + PyObject *item = PyList_GET_ITEM(gameLogic_keys_new, listIndex); if (!PySequence_Contains(gameLogic_keys, item)) { PyDict_DelItem( PyModule_GetDict(gameLogic), item); } diff --git a/source/gameengine/BlenderRoutines/CMakeLists.txt b/source/gameengine/BlenderRoutines/CMakeLists.txt index 96b56768b8f..a053e069153 100644 --- a/source/gameengine/BlenderRoutines/CMakeLists.txt +++ b/source/gameengine/BlenderRoutines/CMakeLists.txt @@ -23,16 +23,16 @@ set(INC ../../blender/makesdna ../../blender/makesrna ../../blender/windowmanager - ../../../extern/bullet2/src ../../../intern/container ../../../intern/guardedalloc ../../../intern/moto/include ../../../intern/string - ${GLEW_INCLUDE_PATH} ) set(INC_SYS + ../../../extern/bullet2/src ${PTHREADS_INCLUDE_DIRS} + ${GLEW_INCLUDE_PATH} ) set(SRC diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp index 6236923d973..346d2017ef0 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp @@ -33,6 +33,7 @@ #include "KX_BlenderCanvas.h" #include "DNA_screen_types.h" #include +#include KX_BlenderCanvas::KX_BlenderCanvas(struct wmWindow *win, RAS_Rect &rect, struct ARegion *ar) : @@ -44,6 +45,8 @@ m_frame_rect(rect) // area boundaries needed for mouse coordinates in Letterbox framing mode m_area_left = ar->winrct.xmin; m_area_top = ar->winrct.ymax; + + glGetIntegerv(GL_VIEWPORT, (GLint *)m_viewport); } KX_BlenderCanvas::~KX_BlenderCanvas() @@ -53,7 +56,7 @@ KX_BlenderCanvas::~KX_BlenderCanvas() void KX_BlenderCanvas::Init() { glDepthFunc(GL_LEQUAL); -} +} void KX_BlenderCanvas::SwapBuffers() @@ -116,14 +119,14 @@ int KX_BlenderCanvas::GetHeight( int KX_BlenderCanvas::GetMouseX(int x) { - float left = GetWindowArea().GetLeft(); - return float(x - (left - m_area_left)); + int left = GetWindowArea().GetLeft(); + return x - (left - m_area_left); } int KX_BlenderCanvas::GetMouseY(int y) { - float top = GetWindowArea().GetTop(); - return float(y - (m_area_top - top)); + int top = GetWindowArea().GetTop(); + return y - (m_area_top - top); } float KX_BlenderCanvas::GetMouseNormalizedX(int x) @@ -143,7 +146,7 @@ KX_BlenderCanvas:: GetWindowArea( ) { return m_area_rect; -} +} void KX_BlenderCanvas:: @@ -166,10 +169,31 @@ SetViewPort( m_area_rect.SetRight(minx + x2); m_area_rect.SetTop(miny + y2); + m_viewport[0] = minx+x1; + m_viewport[1] = miny+y1; + m_viewport[2] = vp_width; + m_viewport[3] = vp_height; + glViewport(minx + x1, miny + y1, vp_width, vp_height); glScissor(minx + x1, miny + y1, vp_width, vp_height); } + const int* +KX_BlenderCanvas:: +GetViewPort() { +#ifdef DEBUG + // If we're in a debug build, we might as well make sure our values don't differ + // from what the gpu thinks we have. This could lead to nasty, hard to find bugs. + int viewport[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + assert(viewport[0] == m_viewport[0]); + assert(viewport[1] == m_viewport[1]); + assert(viewport[2] == m_viewport[2]); + assert(viewport[3] == m_viewport[3]); +#endif + + return m_viewport; +} void KX_BlenderCanvas::SetMouseState(RAS_MouseState mousestate) { diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h index ee7997abb39..244394a115d 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h @@ -61,6 +61,7 @@ private: /** Rect that defines the area used for rendering, relative to the context */ RAS_Rect m_displayarea; + int m_viewport[4]; public: /* Construct a new canvas. @@ -150,6 +151,8 @@ public: int x1, int y1, int x2, int y2 ); + const int* + GetViewPort(); void SetMouseState( @@ -189,8 +192,8 @@ private: struct wmWindow* m_win; RAS_Rect m_frame_rect; RAS_Rect m_area_rect; - short m_area_left; - short m_area_top; + int m_area_left; + int m_area_top; #ifdef WITH_CXX_GUARDEDALLOC @@ -198,5 +201,4 @@ private: #endif }; -#endif // __KX_BLENDERCANVAS_H__ - +#endif /* __KX_BLENDERCANVAS_H__ */ diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp index 19a84acf027..7c4c759e361 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp @@ -91,7 +91,7 @@ void BL_SwapBuffers(wmWindow *win) wm_window_swap_buffers(win); } -void DisableForText() +static void DisableForText() { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); /* needed for texture fonts otherwise they render as wireframe */ @@ -153,7 +153,7 @@ void BL_print_game_line(int fontid, const char* text, int size, int dpi, float* } void BL_print_gamedebug_line(const char* text, int xco, int yco, int width, int height) -{ +{ /* gl prepping */ DisableForText(); glDisable(GL_DEPTH_TEST); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.h b/source/gameengine/BlenderRoutines/KX_BlenderGL.h index 3b89538df47..7ba612b19cf 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderGL.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.h @@ -34,7 +34,7 @@ #ifdef __cplusplus extern "C" { -#endif //__cplusplus +#endif /* __cplusplus */ struct wmWindow; struct ARegion; @@ -58,7 +58,6 @@ void BL_print_gamedebug_line_padded(const char* text, int xco, int yco, int widt #ifdef __cplusplus } -#endif //__cplusplus - -#endif //__KX_BLENDERGL_H__ +#endif /* __cplusplus */ +#endif /* __KX_BLENDERGL_H__ */ diff --git a/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h b/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h index 43870d9030d..2a96d4c5216 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h @@ -32,8 +32,8 @@ #ifndef __KX_BLENDERINPUTDEVICE_H__ #define __KX_BLENDERINPUTDEVICE_H__ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning(disable : 4786) // shut off 255 char limit debug template warning +#ifdef _MSC_VER +# pragma warning(disable:4786) // shut off 255 char limit debug template warning #endif #include @@ -48,8 +48,9 @@ #endif /** - Base Class for Blender specific inputdevices. Blender specific inputdevices are used when the gameengine is running in embedded mode instead of standalone mode. -*/ + * Base Class for Blender specific inputdevices. + * Blender specific inputdevices are used when the gameengine is running in embedded mode instead of standalone mode. + */ class BL_BlenderInputDevice : public SCA_IInputDevice { public: @@ -75,5 +76,5 @@ public: MEM_CXX_CLASS_ALLOC_FUNCS("GE:BL_BlenderInputDevice") #endif }; -#endif //__KX_BLENDERINPUTDEVICE_H__ +#endif /* __KX_BLENDERINPUTDEVICE_H__ */ diff --git a/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp b/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp index 54c60096812..f4e325eabb8 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.cpp @@ -30,9 +30,9 @@ */ -#if defined(WIN32) && !defined(FREE_WINDOWS) -// annoying warnings about truncated STL debug info -#pragma warning (disable :4786) +#ifdef _MSC_VER + /* annoying warnings about truncated STL debug info */ +# pragma warning (disable:4786) #endif #include "KX_BlenderKeyboardDevice.h" diff --git a/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.h b/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.h index e9140efce01..dec70203ecb 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderKeyboardDevice.h @@ -59,5 +59,4 @@ private: #endif }; -#endif //__KX_BLENDERKEYBOARDDEVICE_H__ - +#endif /* __KX_BLENDERKEYBOARDDEVICE_H__ */ diff --git a/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.cpp b/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.cpp index 5cd2038163c..aa2392ded08 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.cpp @@ -29,10 +29,9 @@ * \ingroup blroutines */ - -#if defined(WIN32) && !defined(FREE_WINDOWS) -// annoying warnings about truncated STL debug info -#pragma warning (disable :4786) +#ifdef _MSC_VER + /* annoying warnings about truncated STL debug info */ +# pragma warning (disable:4786) #endif #include "KX_BlenderMouseDevice.h" diff --git a/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.h b/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.h index 0571cafd7a1..8746da83a81 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderMouseDevice.h @@ -55,5 +55,4 @@ public: #endif }; -#endif //__KX_BLENDERMOUSEDEVICE_H__ - +#endif /* __KX_BLENDERMOUSEDEVICE_H__ */ diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp index c4daecc9958..e32239b148d 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp @@ -58,7 +58,7 @@ unsigned int KX_BlenderRenderTools::m_numgllights; KX_BlenderRenderTools::KX_BlenderRenderTools() { - glGetIntegerv(GL_MAX_LIGHTS, (GLint*) &m_numgllights); + glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &m_numgllights); if (m_numgllights < 8) m_numgllights = 8; } @@ -164,11 +164,11 @@ bool KX_BlenderRenderTools::RayHit(KX_ClientObjectInfo* client, KX_RayCast* resu left = (dir.cross(resultnormal)).safe_normalized(); // for the up vector, we take the 'resultnormal' returned by the physics - double maat[16]={ - left[0], left[1], left[2], 0, - dir[0], dir[1], dir[2], 0, - resultnormal[0],resultnormal[1],resultnormal[2], 0, - 0, 0, 0, 1}; + double maat[16] = {left[0], left[1], left[2], 0, + dir[0], dir[1], dir[2], 0, + resultnormal[0], resultnormal[1], resultnormal[2], 0, + 0, 0, 0, 1}; + glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]); //glMultMatrixd(oglmatrix); glMultMatrixd(maat); @@ -227,16 +227,17 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat left *= size[0]; dir *= size[1]; up *= size[2]; - double maat[16]={ - left[0], left[1],left[2], 0, - dir[0], dir[1],dir[2],0, - up[0],up[1],up[2],0, - 0,0,0,1}; - glTranslated(objpos[0],objpos[1],objpos[2]); - glMultMatrixd(maat); - - } else - { + + double maat[16] = {left[0], left[1], left[2], 0, + dir[0], dir[1], dir[2], 0, + up[0], up[1], up[2], 0, + 0, 0, 0, 1}; + + glTranslated(objpos[0],objpos[1],objpos[2]); + glMultMatrixd(maat); + + } + else { if (objectdrawmode & RAS_IPolyMaterial::SHADOW) { // shadow must be cast to the ground, physics system needed here! @@ -344,7 +345,7 @@ void KX_BlenderRenderTools::PopMatrix() int KX_BlenderRenderTools::applyLights(int objectlayer, const MT_Transform& viewmat) { - // taken from blender source, incompatibility between Blender Object / GameObject + // taken from blender source, incompatibility between Blender Object / GameObject KX_Scene* kxscene = (KX_Scene*)m_auxilaryClientInfo; float glviewmat[16]; unsigned int count; diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h index a229c9f34e6..7195524ceae 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h @@ -32,9 +32,9 @@ #ifndef __KX_BLENDERRENDERTOOLS_H__ #define __KX_BLENDERRENDERTOOLS_H__ -#if defined(WIN32) && !defined(FREE_WINDOWS) -// don't show stl-warnings -#pragma warning (disable:4786) +#ifdef _MSC_VER + /* don't show stl-warnings */ +# pragma warning (disable:4786) #endif #include "RAS_IRenderTools.h" @@ -62,7 +62,7 @@ class KX_BlenderRenderTools : public RAS_IRenderTools public: KX_BlenderRenderTools(); - virtual ~KX_BlenderRenderTools(); + virtual ~KX_BlenderRenderTools(); void EndFrame(RAS_IRasterizer* rasty); void BeginFrame(RAS_IRasterizer* rasty); @@ -72,26 +72,26 @@ public: void ProcessLighting(RAS_IRasterizer *rasty, bool uselights, const MT_Transform& viewmat); void RenderText3D(int fontid, - const char* text, - int size, - int dpi, - float* color, - double* mat, - float aspect); + const char* text, + int size, + int dpi, + float* color, + double* mat, + float aspect); void RenderText2D(RAS_TEXT_RENDER_MODE mode, - const char* text, - int xco, - int yco, - int width, - int height); + const char* text, + int xco, + int yco, + int width, + int height); void RenderText(int mode, - class RAS_IPolyMaterial* polymat, - float v1[3], - float v2[3], - float v3[3], - float v4[3], - int glattrib); + class RAS_IPolyMaterial* polymat, + float v1[3], + float v2[3], + float v3[3], + float v4[3], + int glattrib); void applyTransform(RAS_IRasterizer* rasty, double* oglmatrix, int objectdrawmode); int applyLights(int objectlayer, const MT_Transform& viewmat); @@ -112,7 +112,4 @@ public: #endif }; -#endif //__KX_BLENDERRENDERTOOLS_H__ - - - +#endif /* __KX_BLENDERRENDERTOOLS_H__ */ diff --git a/source/gameengine/BlenderRoutines/KX_BlenderSystem.cpp b/source/gameengine/BlenderRoutines/KX_BlenderSystem.cpp index d7d8c5121a2..0582e79d269 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderSystem.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderSystem.cpp @@ -32,9 +32,9 @@ #include "KX_ISystem.h" -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable :4786) -#endif //WIN32 +#ifdef _MSC_VER +# pragma warning (disable:4786) +#endif #ifdef WIN32 #include diff --git a/source/gameengine/BlenderRoutines/KX_BlenderSystem.h b/source/gameengine/BlenderRoutines/KX_BlenderSystem.h index a8e033ed47b..0867ef2421f 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderSystem.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderSystem.h @@ -53,5 +53,4 @@ public: #endif }; -#endif //__KX_BLENDERSYSTEM_H__ - +#endif /* __KX_BLENDERSYSTEM_H__ */ diff --git a/source/gameengine/CMakeLists.txt b/source/gameengine/CMakeLists.txt index a205ccbdc12..aae7e93cc91 100644 --- a/source/gameengine/CMakeLists.txt +++ b/source/gameengine/CMakeLists.txt @@ -25,7 +25,7 @@ # there are too many inter-includes so best define here if(WITH_PYTHON) - blender_include_dirs("${PYTHON_INCLUDE_DIRS}") + blender_include_dirs_sys("${PYTHON_INCLUDE_DIRS}") add_definitions(-DWITH_PYTHON) endif() diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index 92d04115f10..0bd09146f3a 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -96,7 +96,7 @@ BL_ActionActuator::BL_ActionActuator(SCA_IObject* gameobj, m_userpose(NULL), m_action(action), m_propname(propname), - m_framepropname(framepropname) + m_framepropname(framepropname) { if (!end_reset) m_flag |= ACT_FLAG_CONTINUE; @@ -140,8 +140,7 @@ void BL_ActionActuator::SetLocalTime(float curtime) // Handle wrap around if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe)) { - switch(m_playtype) - { + switch (m_playtype) { case ACT_ACTION_PLAY: // Clamp m_localtime = m_endframe; @@ -196,8 +195,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame) return false; // Convert our playtype to one that BL_Action likes - switch(m_playtype) - { + switch (m_playtype) { case ACT_ACTION_LOOP_END: case ACT_ACTION_LOOP_STOP: playtype = BL_Action::ACT_MODE_LOOP; @@ -299,7 +297,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame) m_flag |= ACT_FLAG_ATTEMPT_PLAY; } else if ((m_flag & ACT_FLAG_ACTIVE) && bNegativeEvent) - { + { m_flag &= ~ACT_FLAG_ATTEMPT_PLAY; m_localtime = obj->GetActionFrame(m_layer); bAction *curr_action = obj->GetCurrentAction(m_layer); @@ -312,8 +310,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame) return false; } - switch(m_playtype) - { + switch (m_playtype) { case ACT_ACTION_LOOP_STOP: obj->StopAction(m_layer); // Stop the action after getting the frame @@ -347,7 +344,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame) /* Python functions */ /* ------------------------------------------------------------------------- */ -PyObject* BL_ActionActuator::PyGetChannel(PyObject* value) +PyObject *BL_ActionActuator::PyGetChannel(PyObject *value) { PyErr_SetString(PyExc_NotImplementedError, "BL_ActionActuator.getChannel() no longer works, please use BL_ArmatureObject.channels instead"); return NULL; @@ -492,9 +489,9 @@ KX_PYMETHODDEF_DOC(BL_ActionActuator, setChannel, // for some reason loc.setValue(pchan->loc) fails if (pchan) { - pchan->loc[0]= loc[0]; pchan->loc[1]= loc[1]; pchan->loc[2]= loc[2]; - pchan->size[0]= size[0]; pchan->size[1]= size[1]; pchan->size[2]= size[2]; - pchan->quat[0]= quat[3]; pchan->quat[1]= quat[0]; pchan->quat[2]= quat[1]; pchan->quat[3]= quat[2]; /* notice xyzw -> wxyz is intentional */ + pchan->loc[0] = loc[0]; pchan->loc[1] = loc[1]; pchan->loc[2] = loc[2]; + pchan->size[0] = size[0]; pchan->size[1] = size[1]; pchan->size[2] = size[2]; + pchan->quat[0] = quat[3]; pchan->quat[1] = quat[0]; pchan->quat[2] = quat[1]; pchan->quat[3] = quat[2]; /* notice xyzw -> wxyz is intentional */ } } @@ -555,15 +552,15 @@ PyAttributeDef BL_ActionActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* BL_ActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *BL_ActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - BL_ActionActuator* self= static_cast(self_v); + BL_ActionActuator* self = static_cast(self_v); return PyUnicode_FromString(self->GetAction() ? self->GetAction()->id.name+2 : ""); } int BL_ActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - BL_ActionActuator* self= static_cast(self_v); + BL_ActionActuator* self = static_cast(self_v); if (!PyUnicode_Check(value)) { @@ -589,13 +586,13 @@ int BL_ActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF } -PyObject* BL_ActionActuator::pyattr_get_channel_names(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *BL_ActionActuator::pyattr_get_channel_names(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { PyErr_SetString(PyExc_NotImplementedError, "BL_ActionActuator.channelNames no longer works, please use BL_ArmatureObject.channels instead"); return NULL; #if 0 // XXX To be removed in a later version (first removed in 2.64) - BL_ActionActuator* self= static_cast(self_v); + BL_ActionActuator* self = static_cast(self_v); PyObject *ret= PyList_New(0); PyObject *item; @@ -620,15 +617,15 @@ PyObject* BL_ActionActuator::pyattr_get_channel_names(void *self_v, const KX_PYA #endif } -PyObject* BL_ActionActuator::pyattr_get_use_continue(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *BL_ActionActuator::pyattr_get_use_continue(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - BL_ActionActuator* self= static_cast(self_v); + BL_ActionActuator* self = static_cast(self_v); return PyBool_FromLong(self->m_flag & ACT_FLAG_CONTINUE); } int BL_ActionActuator::pyattr_set_use_continue(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - BL_ActionActuator* self= static_cast(self_v); + BL_ActionActuator* self = static_cast(self_v); if (PyObject_IsTrue(value)) self->m_flag |= ACT_FLAG_CONTINUE; @@ -638,15 +635,15 @@ int BL_ActionActuator::pyattr_set_use_continue(void *self_v, const KX_PYATTRIBUT return PY_SET_ATTR_SUCCESS; } -PyObject* BL_ActionActuator::pyattr_get_frame(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *BL_ActionActuator::pyattr_get_frame(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - BL_ActionActuator* self= static_cast(self_v); + BL_ActionActuator* self = static_cast(self_v); return PyFloat_FromDouble(((KX_GameObject*)self->m_gameobj)->GetActionFrame(self->m_layer)); } int BL_ActionActuator::pyattr_set_frame(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - BL_ActionActuator* self= static_cast(self_v); + BL_ActionActuator* self = static_cast(self_v); ((KX_GameObject*)self->m_gameobj)->SetActionFrame(self->m_layer, PyFloat_AsDouble(value)); diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h index 640a9a9ccb7..46075ea933d 100644 --- a/source/gameengine/Converter/BL_ActionActuator.h +++ b/source/gameengine/Converter/BL_ActionActuator.h @@ -108,7 +108,7 @@ public: return 1; } } -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ protected: MT_Point3 m_lastpos; diff --git a/source/gameengine/Converter/BL_ArmatureActuator.cpp b/source/gameengine/Converter/BL_ArmatureActuator.cpp index 3f4a261a972..f0c4b3d32bb 100644 --- a/source/gameengine/Converter/BL_ArmatureActuator.cpp +++ b/source/gameengine/Converter/BL_ArmatureActuator.cpp @@ -146,7 +146,7 @@ void BL_ArmatureActuator::FindConstraint() bool BL_ArmatureActuator::Update(double curtime, bool frame) { // the only role of this actuator is to ensure that the armature pose will be evaluated - bool result = false; + bool result = false; bool bNegativeEvent = IsNegativeEvent(); RemoveAllEvents(); @@ -227,11 +227,11 @@ PyAttributeDef BL_ArmatureActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* BL_ArmatureActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *BL_ArmatureActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { BL_ArmatureActuator* actuator = static_cast(self); KX_GameObject *target = (!strcmp(attrdef->m_name, "target")) ? actuator->m_gametarget : actuator->m_gamesubtarget; - if (!target) + if (!target) Py_RETURN_NONE; else return target->GetProxy(); @@ -247,7 +247,7 @@ int BL_ArmatureActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBU return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error if (target != NULL) - target->UnregisterActuator(actuator); + target->UnregisterActuator(actuator); target = gameobj; @@ -257,11 +257,11 @@ int BL_ArmatureActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBU return PY_SET_ATTR_SUCCESS; } -PyObject* BL_ArmatureActuator::pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *BL_ArmatureActuator::pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { BL_ArmatureActuator* actuator = static_cast(self); BL_ArmatureConstraint* constraint = actuator->m_constraint; - if (!constraint) + if (!constraint) Py_RETURN_NONE; else return constraint->GetProxy(); diff --git a/source/gameengine/Converter/BL_ArmatureActuator.h b/source/gameengine/Converter/BL_ArmatureActuator.h index 638640c27ce..ba02c5aa362 100644 --- a/source/gameengine/Converter/BL_ArmatureActuator.h +++ b/source/gameengine/Converter/BL_ArmatureActuator.h @@ -49,13 +49,13 @@ class BL_ArmatureActuator : public SCA_IActuator Py_Header public: BL_ArmatureActuator(SCA_IObject* gameobj, - int type, - const char *posechannel, - const char *constraintname, - KX_GameObject* targetobj, - KX_GameObject* subtargetobj, - float weight, - float influence); + int type, + const char *posechannel, + const char *constraintname, + KX_GameObject* targetobj, + KX_GameObject* subtargetobj, + float weight, + float influence); virtual ~BL_ArmatureActuator(); @@ -73,11 +73,11 @@ public: #ifdef WITH_PYTHON /* These are used to get and set m_target */ - static PyObject* pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ private: // identify the constraint that this actuator controls @@ -93,6 +93,4 @@ private: int m_type; }; -#endif //__BL_ARMATUREACTUATOR_H__ - - +#endif /* __BL_ARMATUREACTUATOR_H__ */ diff --git a/source/gameengine/Converter/BL_ArmatureChannel.cpp b/source/gameengine/Converter/BL_ArmatureChannel.cpp index 7344aa9378e..7cf895255ba 100644 --- a/source/gameengine/Converter/BL_ArmatureChannel.cpp +++ b/source/gameengine/Converter/BL_ArmatureChannel.cpp @@ -62,7 +62,7 @@ PyTypeObject BL_ArmatureChannel::Type = { py_base_new }; -PyObject* BL_ArmatureChannel::py_repr(void) +PyObject *BL_ArmatureChannel::py_repr(void) { return PyUnicode_FromString(m_posechannel->name); } @@ -104,8 +104,8 @@ PyMethodDef BL_ArmatureChannel::Methods[] = { PyAttributeDef BL_ArmatureChannel::Attributes[] = { // Keep these attributes in order of BCA_ defines!!! used by py_attr_getattr and py_attr_setattr - KX_PYATTRIBUTE_RO_FUNCTION("bone",BL_ArmatureChannel,py_attr_getattr), - KX_PYATTRIBUTE_RO_FUNCTION("parent",BL_ArmatureChannel,py_attr_getattr), + KX_PYATTRIBUTE_RO_FUNCTION("bone",BL_ArmatureChannel,py_attr_getattr), + KX_PYATTRIBUTE_RO_FUNCTION("parent",BL_ArmatureChannel,py_attr_getattr), { NULL } //Sentinel }; @@ -147,9 +147,9 @@ PyAttributeDef BL_ArmatureChannel::AttributesPtr[] = { { NULL } //Sentinel }; -PyObject* BL_ArmatureChannel::py_attr_getattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *BL_ArmatureChannel::py_attr_getattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef) { - BL_ArmatureChannel* self= static_cast(self_v); + BL_ArmatureChannel* self = static_cast(self_v); bPoseChannel* channel = self->m_posechannel; int attr_order = attrdef-Attributes; @@ -177,7 +177,7 @@ PyObject* BL_ArmatureChannel::py_attr_getattr(void *self_v, const struct KX_PYAT int BL_ArmatureChannel::py_attr_setattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - BL_ArmatureChannel* self= static_cast(self_v); + BL_ArmatureChannel* self = static_cast(self_v); bPoseChannel* channel = self->m_posechannel; int attr_order = attrdef-Attributes; @@ -200,7 +200,7 @@ int BL_ArmatureChannel::py_attr_setattr(void *self_v, const struct KX_PYATTRIBUT return PY_SET_ATTR_FAIL; } -PyObject* BL_ArmatureChannel::py_attr_get_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *BL_ArmatureChannel::py_attr_get_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef) { bPoseChannel* pchan = static_cast(self_v); // decompose the pose matrix in euler rotation @@ -223,7 +223,7 @@ PyObject* BL_ArmatureChannel::py_attr_get_joint_rotation(void *self_v, const str } // remove the rest pose to get the joint movement transpose_m3(rest_mat); - mul_m3_m3m3(joint_mat, rest_mat, pose_mat); + mul_m3_m3m3(joint_mat, rest_mat, pose_mat); joints[0] = joints[1] = joints[2] = 0.f; // returns a 3 element list that gives corresponding joint int flag = 0; @@ -300,7 +300,7 @@ PyObject* BL_ArmatureChannel::py_attr_get_joint_rotation(void *self_v, const str int BL_ArmatureChannel::py_attr_set_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - BL_ArmatureChannel* self= static_cast(self_v); + BL_ArmatureChannel* self = static_cast(self_v); bPoseChannel* pchan = self->m_posechannel; PyObject *item; float joints[3]; @@ -455,12 +455,12 @@ PyObject *BL_ArmatureBone::py_bone_get_children(void *self, const struct KX_PYAT Bone* bone = reinterpret_cast(self); Bone* child; int count = 0; - for (child=(Bone*)bone->childbase.first; child; child=(Bone*)child->next) + for (child = (Bone *)bone->childbase.first; child; child = child->next) count++; - PyObject* childrenlist = PyList_New(count); + PyObject *childrenlist = PyList_New(count); - for (count = 0, child=(Bone*)bone->childbase.first; child; child=(Bone*)child->next, ++count) + for (count = 0, child = (Bone *)bone->childbase.first; child; child = child->next, ++count) PyList_SET_ITEM(childrenlist,count,NewProxyPlus_Ext(NULL,&Type,child,false)); return childrenlist; diff --git a/source/gameengine/Converter/BL_ArmatureChannel.h b/source/gameengine/Converter/BL_ArmatureChannel.h index cd38ee2d531..51114c5df30 100644 --- a/source/gameengine/Converter/BL_ArmatureChannel.h +++ b/source/gameengine/Converter/BL_ArmatureChannel.h @@ -62,13 +62,13 @@ public: #ifdef WITH_PYTHON // Python access - virtual PyObject* py_repr(void); + virtual PyObject *py_repr(void); - static PyObject* py_attr_getattr(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *py_attr_getattr(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int py_attr_setattr(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); - static PyObject* py_attr_get_joint_rotation(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *py_attr_get_joint_rotation(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int py_attr_set_joint_rotation(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; /* this is a factory class to access bBone data field in the GE. @@ -93,6 +93,4 @@ public: }; - -#endif //__BL_ARMATURECHANNEL_H__ - +#endif /* __BL_ARMATURECHANNEL_H__ */ diff --git a/source/gameengine/Converter/BL_ArmatureConstraint.cpp b/source/gameengine/Converter/BL_ArmatureConstraint.cpp index 7939d6e9235..b8ad117a220 100644 --- a/source/gameengine/Converter/BL_ArmatureConstraint.cpp +++ b/source/gameengine/Converter/BL_ArmatureConstraint.cpp @@ -61,7 +61,7 @@ PyTypeObject BL_ArmatureConstraint::Type = { py_base_new }; -PyObject* BL_ArmatureConstraint::py_repr(void) +PyObject *BL_ArmatureConstraint::py_repr(void) { return PyUnicode_FromString(m_name); } @@ -267,8 +267,8 @@ PyMethodDef BL_ArmatureConstraint::Methods[] = { PyAttributeDef BL_ArmatureConstraint::Attributes[] = { // Keep these attributes in order of BCA_ defines!!! used by py_attr_getattr and py_attr_setattr - KX_PYATTRIBUTE_RO_FUNCTION("type",BL_ArmatureConstraint,py_attr_getattr), - KX_PYATTRIBUTE_RO_FUNCTION("name",BL_ArmatureConstraint,py_attr_getattr), + KX_PYATTRIBUTE_RO_FUNCTION("type",BL_ArmatureConstraint,py_attr_getattr), + KX_PYATTRIBUTE_RO_FUNCTION("name",BL_ArmatureConstraint,py_attr_getattr), KX_PYATTRIBUTE_RW_FUNCTION("enforce",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr), KX_PYATTRIBUTE_RW_FUNCTION("headtail",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr), KX_PYATTRIBUTE_RO_FUNCTION("lin_error",BL_ArmatureConstraint,py_attr_getattr), @@ -286,9 +286,9 @@ PyAttributeDef BL_ArmatureConstraint::Attributes[] = { }; -PyObject* BL_ArmatureConstraint::py_attr_getattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *BL_ArmatureConstraint::py_attr_getattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef) { - BL_ArmatureConstraint* self= static_cast(self_v); + BL_ArmatureConstraint* self = static_cast(self_v); bConstraint* constraint = self->m_constraint; bKinematicConstraint* ikconstraint = (constraint && constraint->type == CONSTRAINT_TYPE_KINEMATIC) ? (bKinematicConstraint*)constraint->data : NULL; int attr_order = attrdef-Attributes; @@ -312,12 +312,12 @@ PyObject* BL_ArmatureConstraint::py_attr_getattr(void *self_v, const struct KX_P case BCA_ROTERROR: return PyFloat_FromDouble(constraint->rot_error); case BCA_TARGET: - if (!self->m_target) + if (!self->m_target) Py_RETURN_NONE; else return self->m_target->GetProxy(); case BCA_SUBTARGET: - if (!self->m_subtarget) + if (!self->m_subtarget) Py_RETURN_NONE; else return self->m_subtarget->GetProxy(); @@ -353,7 +353,7 @@ PyObject* BL_ArmatureConstraint::py_attr_getattr(void *self_v, const struct KX_P int BL_ArmatureConstraint::py_attr_setattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - BL_ArmatureConstraint* self= static_cast(self_v); + BL_ArmatureConstraint* self = static_cast(self_v); bConstraint* constraint = self->m_constraint; bKinematicConstraint* ikconstraint = (constraint && constraint->type == CONSTRAINT_TYPE_KINEMATIC) ? (bKinematicConstraint*)constraint->data : NULL; int attr_order = attrdef-Attributes; diff --git a/source/gameengine/Converter/BL_ArmatureConstraint.h b/source/gameengine/Converter/BL_ArmatureConstraint.h index 0d79bb1cfa7..98c2954baf4 100644 --- a/source/gameengine/Converter/BL_ArmatureConstraint.h +++ b/source/gameengine/Converter/BL_ArmatureConstraint.h @@ -115,12 +115,11 @@ public: #ifdef WITH_PYTHON // Python access - virtual PyObject* py_repr(void); + virtual PyObject *py_repr(void); - static PyObject* py_attr_getattr(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *py_attr_getattr(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int py_attr_setattr(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; -#endif //__BL_ARMATURECONSTRAINT_H__ - +#endif /* __BL_ARMATURECONSTRAINT_H__ */ diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index 7174a563efa..ed97b9ff73f 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -105,7 +105,7 @@ void game_copy_pose(bPose **dst, bPose *src, int copy_constraint) for (; pchan; pchan=pchan->next, outpchan=outpchan->next) BLI_ghash_insert(ghash, pchan, outpchan); - for (pchan=(bPoseChannel*)out->chanbase.first; pchan; pchan=(bPoseChannel*)pchan->next) { + for (pchan = (bPoseChannel*)out->chanbase.first; pchan; pchan = pchan->next) { pchan->parent= (bPoseChannel*)BLI_ghash_lookup(ghash, pchan->parent); pchan->child= (bPoseChannel*)BLI_ghash_lookup(ghash, pchan->child); @@ -186,7 +186,10 @@ void game_blend_poses(bPose *dst, bPose *src, float srcweight/*, short mode*/) if (schan->rotmode) dchan->eul[i] = (dchan->eul[i]*dstweight) + (schan->eul[i]*srcweight); } - for (dcon= (bConstraint*)dchan->constraints.first, scon= (bConstraint*)schan->constraints.first; dcon && scon; dcon= (bConstraint*)dcon->next, scon= (bConstraint*)scon->next) { + for (dcon= (bConstraint *)dchan->constraints.first, scon= (bConstraint *)schan->constraints.first; + dcon && scon; + dcon = dcon->next, scon = scon->next) + { /* no 'add' option for constraint blending */ dcon->enforce= dcon->enforce*(1.0f-srcweight) + scon->enforce*srcweight; } @@ -282,8 +285,8 @@ void BL_ArmatureObject::LoadConstraints(KX_BlenderSceneConverter* converter) KX_GameObject* gamesubtarget; // and locate the constraint - for (pchan = (bPoseChannel*)m_pose->chanbase.first; pchan; pchan=(bPoseChannel*)pchan->next) { - for (pcon = (bConstraint*)pchan->constraints.first; pcon; pcon=(bConstraint*)pcon->next) { + for (pchan = (bPoseChannel *)m_pose->chanbase.first; pchan; pchan = pchan->next) { + for (pcon = (bConstraint *)pchan->constraints.first; pcon; pcon = pcon->next) { if (pcon->flag & CONSTRAINT_DISABLE) continue; // which constraint should we support? @@ -315,7 +318,7 @@ void BL_ArmatureObject::LoadConstraints(KX_BlenderSceneConverter* converter) } if (target->next != NULL) { // secondary target - target = (bConstraintTarget*)target->next; + target = target->next; if (target->tar && target->tar != m_objArma) { // only track external object blendtarget = target->tar; @@ -430,7 +433,7 @@ void BL_ArmatureObject::ProcessReplica() m_pose = NULL; m_framePose = NULL; - game_copy_pose(&m_pose, pose, 1); + game_copy_pose(&m_pose, pose, 1); } void BL_ArmatureObject::ReParentLogic() @@ -521,7 +524,7 @@ bool BL_ArmatureObject::SetActiveAction(BL_ActionActuator *act, short priority, SetPose(m_framePose); if (m_activeAct && (m_activeAct!=act)) /* Reset the blend timer since this new action cancels the old one */ - m_activeAct->SetBlendTime(0.0); + m_activeAct->SetBlendTime(0.0); } m_activeAct = act; m_activePriority = priority; @@ -648,12 +651,12 @@ PyAttributeDef BL_ArmatureObject::Attributes[] = { {NULL} //Sentinel }; -PyObject* BL_ArmatureObject::pyattr_get_constraints(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *BL_ArmatureObject::pyattr_get_constraints(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { return KX_PythonSeq_CreatePyObject((static_cast(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_CONSTRAINTS); } -PyObject* BL_ArmatureObject::pyattr_get_channels(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *BL_ArmatureObject::pyattr_get_channels(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { BL_ArmatureObject* self = static_cast(self_v); self->LoadChannels(); // make sure we have the channels diff --git a/source/gameengine/Converter/BL_ArmatureObject.h b/source/gameengine/Converter/BL_ArmatureObject.h index 6274e770409..445b9af1b10 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.h +++ b/source/gameengine/Converter/BL_ArmatureObject.h @@ -116,11 +116,11 @@ public: #ifdef WITH_PYTHON // PYTHON - static PyObject* pyattr_get_constraints(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_channels(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_constraints(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_channels(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); KX_PYMETHOD_DOC_NOARGS(BL_ArmatureObject, update); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ protected: /* list element: BL_ArmatureConstraint. Use SG_DListHead to have automatic list replication */ @@ -152,6 +152,4 @@ void game_blend_poses(struct bPose *dst, struct bPose *src, float srcweight/*, s void game_copy_pose(struct bPose **dst, struct bPose *src, int copy_con); void game_free_pose(struct bPose *pose); - -#endif - +#endif /* __BL_ARMATUREOBJECT_H__ */ diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 84ad12477d0..58ae415e9d3 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -30,8 +30,8 @@ * \ingroup bgeconv */ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable : 4786) +#ifdef _MSC_VER +# pragma warning (disable:4786) #endif #include @@ -216,7 +216,7 @@ static std::map create_translate_table() // SYSTEM -#if 0 +#if 0 /* **** XXX **** */ m[KEYBD ] = SCA_IInputDevice::KX_KEYBD; m[RAWKEYBD ] = SCA_IInputDevice::KX_RAWKEYBD; @@ -229,7 +229,7 @@ static std::map create_translate_table() m[WINQUIT ] = SCA_IInputDevice::KX_WINQUIT; m[Q_FIRSTTIME ] = SCA_IInputDevice::KX_Q_FIRSTTIME; /* **** XXX **** */ -#endif +#endif // standard keyboard @@ -433,8 +433,7 @@ static void GetRGB(short type, unsigned int &c3) { unsigned int color = 0xFFFFFFFFL; - switch(type) - { + switch (type) { case 0: // vertex colors { if (mmcol) { @@ -447,7 +446,7 @@ static void GetRGB(short type, else { // backup white c0 = KX_rgbaint2uint_new(color); c1 = KX_rgbaint2uint_new(color); - c2 = KX_rgbaint2uint_new(color); + c2 = KX_rgbaint2uint_new(color); if (mface->v4) c3 = KX_rgbaint2uint_new( color ); } @@ -469,7 +468,7 @@ static void GetRGB(short type, } c0 = KX_rgbaint2uint_new(color); c1 = KX_rgbaint2uint_new(color); - c2 = KX_rgbaint2uint_new(color); + c2 = KX_rgbaint2uint_new(color); if (mface->v4) c3 = KX_rgbaint2uint_new(color); } break; @@ -478,7 +477,7 @@ static void GetRGB(short type, { c0 = KX_rgbaint2uint_new(color); c1 = KX_rgbaint2uint_new(color); - c2 = KX_rgbaint2uint_new(color); + c2 = KX_rgbaint2uint_new(color); if (mface->v4) c3 = KX_rgbaint2uint_new(color); } break; @@ -491,7 +490,7 @@ typedef struct MTF_localLayer { } MTF_localLayer; // ------------------------------------ -bool ConvertMaterial( +static bool ConvertMaterial( BL_Material *material, Material *mat, MTFace* tface, @@ -627,7 +626,7 @@ bool ConvertMaterial( if (!material->cubemap[i]->cube[0]) BL_Texture::SplitEnvMap(material->cubemap[i]); - material->texname[i]= material->cubemap[i]->ima->id.name; + material->texname[i] = material->cubemap[i]->ima->id.name; material->mapping[i].mapping |= USEENV; } } @@ -677,7 +676,7 @@ bool ConvertMaterial( material->mapping[i].projplane[2] = mttmp->projz; /// -------------------------------- - switch( mttmp->blendtype ) { + switch (mttmp->blendtype) { case MTEX_BLEND: material->blend_mode[i] = BLEND_MIX; break; @@ -701,7 +700,7 @@ bool ConvertMaterial( // above one tex the switches here // are not used - switch(valid_index) { + switch (valid_index) { case 0: material->IdMode = DEFAULT_BLENDER; break; @@ -778,7 +777,7 @@ bool ConvertMaterial( const char *uvName = "", *uv2Name = ""; - uv2[0]= uv2[1]= uv2[2]= uv2[3]= MT_Point2(0.0f, 0.0f); + uv2[0] = uv2[1] = uv2[2] = uv2[3] = MT_Point2(0.0f, 0.0f); /* No material, what to do? let's see what is in the UV and set the material accordingly * light and visible is always on */ @@ -799,7 +798,7 @@ bool ConvertMaterial( material->alphablend = GEMAT_SOLID; material->tile = 0; - uv[0]= uv[1]= uv[2]= uv[3]= MT_Point2(0.0f, 0.0f); + uv[0] = uv[1] = uv[2] = uv[3] = MT_Point2(0.0f, 0.0f); } if (validmat && validface) { @@ -1150,7 +1149,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, rgb0 = KX_rgbaint2uint_new(color); rgb1 = KX_rgbaint2uint_new(color); - rgb2 = KX_rgbaint2uint_new(color); + rgb2 = KX_rgbaint2uint_new(color); if (mface->v4) rgb3 = KX_rgbaint2uint_new(color); @@ -1390,32 +1389,30 @@ static float my_boundbox_mesh(Mesh *me, float *loc, float *size) } if (me->totvert) { - loc[0]= (min[0]+max[0])/2.0f; - loc[1]= (min[1]+max[1])/2.0f; - loc[2]= (min[2]+max[2])/2.0f; + loc[0] = (min[0] + max[0]) / 2.0f; + loc[1] = (min[1] + max[1]) / 2.0f; + loc[2] = (min[2] + max[2]) / 2.0f; - size[0]= (max[0]-min[0])/2.0f; - size[1]= (max[1]-min[1])/2.0f; - size[2]= (max[2]-min[2])/2.0f; + size[0] = (max[0] - min[0]) / 2.0f; + size[1] = (max[1] - min[1]) / 2.0f; + size[2] = (max[2] - min[2]) / 2.0f; } else { - loc[0]= loc[1]= loc[2]= 0.0f; - size[0]= size[1]= size[2]= 0.0f; + loc[0] = loc[1] = loc[2] = 0.0f; + size[0] = size[1] = size[2] = 0.0f; } - bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= loc[0]-size[0]; - bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= loc[0]+size[0]; + bb->vec[0][0] = bb->vec[1][0] = bb->vec[2][0] = bb->vec[3][0] = loc[0]-size[0]; + bb->vec[4][0] = bb->vec[5][0] = bb->vec[6][0] = bb->vec[7][0] = loc[0]+size[0]; - bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= loc[1]-size[1]; - bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= loc[1]+size[1]; + bb->vec[0][1] = bb->vec[1][1] = bb->vec[4][1] = bb->vec[5][1] = loc[1]-size[1]; + bb->vec[2][1] = bb->vec[3][1] = bb->vec[6][1] = bb->vec[7][1] = loc[1]+size[1]; - bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= loc[2]-size[2]; - bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= loc[2]+size[2]; + bb->vec[0][2] = bb->vec[3][2] = bb->vec[4][2] = bb->vec[7][2] = loc[2]-size[2]; + bb->vec[1][2] = bb->vec[2][2] = bb->vec[5][2] = bb->vec[6][2] = loc[2]+size[2]; return sqrt(radius); } - - static void my_tex_space_mesh(Mesh *me) @@ -1438,12 +1435,12 @@ static void my_tex_space_mesh(Mesh *me) minmax_v3v3_v3(min, max, fp); } if (kb->totelem) { - loc[0]= (min[0]+max[0])/2.0f; loc[1]= (min[1]+max[1])/2.0f; loc[2]= (min[2]+max[2])/2.0f; - size[0]= (max[0]-min[0])/2.0f; size[1]= (max[1]-min[1])/2.0f; size[2]= (max[2]-min[2])/2.0f; + loc[0] = (min[0]+max[0])/2.0f; loc[1] = (min[1]+max[1])/2.0f; loc[2] = (min[2]+max[2])/2.0f; + size[0] = (max[0]-min[0])/2.0f; size[1] = (max[1]-min[1])/2.0f; size[2] = (max[2]-min[2])/2.0f; } else { - loc[0]= loc[1]= loc[2]= 0.0; - size[0]= size[1]= size[2]= 0.0; + loc[0] = loc[1] = loc[2] = 0.0; + size[0] = size[1] = size[2] = 0.0; } } @@ -1451,19 +1448,19 @@ static void my_tex_space_mesh(Mesh *me) copy_v3_v3(me->loc, loc); copy_v3_v3(me->size, size); - me->rot[0]= me->rot[1]= me->rot[2]= 0.0f; + me->rot[0] = me->rot[1] = me->rot[2] = 0.0f; if (me->size[0] == 0.0f) me->size[0] = 1.0f; - else if (me->size[0] > 0.0f && me->size[0]< 0.00001f) me->size[0]= 0.00001f; - else if (me->size[0] < 0.0f && me->size[0]> -0.00001f) me->size[0]= -0.00001f; + else if (me->size[0] > 0.0f && me->size[0]< 0.00001f) me->size[0] = 0.00001f; + else if (me->size[0] < 0.0f && me->size[0]> -0.00001f) me->size[0] = -0.00001f; - if (me->size[1] == 0.0f) me->size[1]= 1.0f; - else if (me->size[1] > 0.0f && me->size[1]< 0.00001f) me->size[1]= 0.00001f; - else if (me->size[1] < 0.0f && me->size[1]> -0.00001f) me->size[1]= -0.00001f; + if (me->size[1] == 0.0f) me->size[1] = 1.0f; + else if (me->size[1] > 0.0f && me->size[1]< 0.00001f) me->size[1] = 0.00001f; + else if (me->size[1] < 0.0f && me->size[1]> -0.00001f) me->size[1] = -0.00001f; - if (me->size[2] == 0.0f) me->size[2]= 1.0f; - else if (me->size[2] > 0.0f && me->size[2]< 0.00001f) me->size[2]= 0.00001f; - else if (me->size[2] < 0.0f && me->size[2]> -0.00001f) me->size[2]= -0.00001f; + if (me->size[2] == 0.0f) me->size[2] = 1.0f; + else if (me->size[2] > 0.0f && me->size[2]< 0.00001f) me->size[2] = 0.00001f; + else if (me->size[2] < 0.0f && me->size[2]> -0.00001f) me->size[2] = -0.00001f; } } @@ -1480,13 +1477,13 @@ static void my_get_local_bounds(Object *ob, DerivedMesh *dm, float *center, floa float min_r[3], max_r[3]; INIT_MINMAX(min_r, max_r); dm->getMinMax(dm, min_r, max_r); - size[0]= 0.5f*fabsf(max_r[0] - min_r[0]); - size[1]= 0.5f*fabsf(max_r[1] - min_r[1]); - size[2]= 0.5f*fabsf(max_r[2] - min_r[2]); + size[0] = 0.5f * fabsf(max_r[0] - min_r[0]); + size[1] = 0.5f * fabsf(max_r[1] - min_r[1]); + size[2] = 0.5f * fabsf(max_r[2] - min_r[2]); - center[0]= 0.5f*(max_r[0] + min_r[0]); - center[1]= 0.5f*(max_r[1] + min_r[1]); - center[2]= 0.5f*(max_r[2] + min_r[2]); + center[0] = 0.5f * (max_r[0] + min_r[0]); + center[1] = 0.5f * (max_r[1] + min_r[1]); + center[2] = 0.5f * (max_r[2] + min_r[2]); return; } else { @@ -1500,11 +1497,11 @@ static void my_get_local_bounds(Object *ob, DerivedMesh *dm, float *center, floa break; case OB_CURVE: case OB_SURF: - center[0]= center[1]= center[2]= 0.0; + center[0] = center[1] = center[2] = 0.0; size[0] = size[1]=size[2]=0.0; break; case OB_FONT: - center[0]= center[1]= center[2]= 0.0; + center[0] = center[1] = center[2] = 0.0; size[0] = size[1]=size[2]=1.0; break; case OB_MBALL: @@ -1514,15 +1511,15 @@ static void my_get_local_bounds(Object *ob, DerivedMesh *dm, float *center, floa if (bb==NULL) { - center[0]= center[1]= center[2]= 0.0; - size[0] = size[1]=size[2]=1.0; + center[0] = center[1] = center[2] = 0.0; + size[0] = size[1] = size[2] = 1.0; } else { size[0] = 0.5f * fabsf(bb->vec[0][0] - bb->vec[4][0]); size[1] = 0.5f * fabsf(bb->vec[0][1] - bb->vec[2][1]); size[2] = 0.5f * fabsf(bb->vec[0][2] - bb->vec[1][2]); - + center[0] = 0.5f * (bb->vec[0][0] + bb->vec[4][0]); center[1] = 0.5f * (bb->vec[0][1] + bb->vec[2][1]); center[2] = 0.5f * (bb->vec[0][2] + bb->vec[1][2]); @@ -1535,14 +1532,14 @@ static void my_get_local_bounds(Object *ob, DerivedMesh *dm, float *center, floa ////////////////////////////////////////////////////// -void BL_CreateGraphicObjectNew(KX_GameObject* gameobj, - const MT_Point3& localAabbMin, - const MT_Point3& localAabbMax, - KX_Scene* kxscene, - bool isActive, - e_PhysicsEngine physics_engine) +static void BL_CreateGraphicObjectNew(KX_GameObject* gameobj, + const MT_Point3& localAabbMin, + const MT_Point3& localAabbMax, + KX_Scene* kxscene, + bool isActive, + e_PhysicsEngine physics_engine) { - if (gameobj->GetMeshCount() > 0) + if (gameobj->GetMeshCount() > 0) { switch (physics_engine) { @@ -1574,28 +1571,36 @@ void BL_CreateGraphicObjectNew(KX_GameObject* gameobj, } } -void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, - struct Object* blenderobject, - RAS_MeshObject* meshobj, - KX_Scene* kxscene, - int activeLayerBitInfo, - e_PhysicsEngine physics_engine, - KX_BlenderSceneConverter *converter, - bool processCompoundChildren - ) - +static void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, + struct Object* blenderobject, + RAS_MeshObject* meshobj, + KX_Scene* kxscene, + int activeLayerBitInfo, + e_PhysicsEngine physics_engine, + KX_BlenderSceneConverter *converter, + bool processCompoundChildren + ) + { //SYS_SystemHandle syshandle = SYS_GetSystem(); /*unused*/ //int userigidbody = SYS_GetCommandLineInt(syshandle,"norigidbody",0); //bool bRigidBody = (userigidbody == 0); // object has physics representation? - if (!(blenderobject->gameflag & OB_COLLISION)) + if (!(blenderobject->gameflag & OB_COLLISION)) { + // Respond to all collisions so that Near sensors work on No Collision + // objects. + gameobj->SetUserCollisionGroup(0xff); + gameobj->SetUserCollisionMask(0xff); return; + } + + gameobj->SetUserCollisionGroup(blenderobject->col_group); + gameobj->SetUserCollisionMask(blenderobject->col_mask); // get Root Parent of blenderobject struct Object* parent= blenderobject->parent; - while(parent && parent->parent) { + while (parent && parent->parent) { parent= parent->parent; } @@ -1694,7 +1699,7 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, objprop.m_soft_numclusteriterations= blenderobject->bsoft->numclusteriterations; /* number of iterations to refine collision clusters*/ //objprop.m_soft_welding = blenderobject->bsoft->welding; /* welding */ /* disable welding: it doesn't bring any additional stability and it breaks the relation between soft body collision shape and graphic mesh */ - objprop.m_soft_welding = 0.f; + objprop.m_soft_welding = 0.f; objprop.m_margin = blenderobject->bsoft->margin; objprop.m_contactProcessingThreshold = 0.f; } else @@ -1929,8 +1934,7 @@ static KX_GameObject *gameobject_from_blenderobject( KX_GameObject *gameobj = NULL; Scene *blenderscene = kxscene->GetBlenderScene(); - switch(ob->type) - { + switch (ob->type) { case OB_LAMP: { KX_LightObject* gamelight = gamelight_from_blamp(ob, static_cast(ob->data), ob->lay, kxscene, rendertools, converter); @@ -2086,7 +2090,7 @@ struct parentChildLink { #include "DNA_constraint_types.h" //XXX #include "BIF_editconstraint.h" -bPoseChannel *get_active_posechannel2 (Object *ob) +static bPoseChannel *get_active_posechannel2 (Object *ob) { bArmature *arm= (bArmature*)ob->data; bPoseChannel *pchan; @@ -2100,7 +2104,7 @@ bPoseChannel *get_active_posechannel2 (Object *ob) return NULL; } -ListBase *get_active_constraints2(Object *ob) +static ListBase *get_active_constraints2(Object *ob) { if (!ob) return NULL; @@ -2119,8 +2123,7 @@ ListBase *get_active_constraints2(Object *ob) return NULL; } - -void RBJconstraints(Object *ob)//not used +static void UNUSED_FUNCTION(RBJconstraints)(Object *ob)//not used { ListBase *conlist; bConstraint *curcon; @@ -2141,7 +2144,8 @@ void RBJconstraints(Object *ob)//not used #include "KX_IPhysicsController.h" #include "PHY_DynamicTypes.h" -KX_IPhysicsController* getPhId(CListValue* sumolist,STR_String busc) {//not used +#if 0 /* UNUSED */ +static KX_IPhysicsController* getPhId(CListValue* sumolist,STR_String busc) {//not used for (int j=0;jGetCount();j++) { @@ -2151,10 +2155,10 @@ KX_IPhysicsController* getPhId(CListValue* sumolist,STR_String busc) {//not used } return 0; - } +#endif -KX_GameObject* getGameOb(STR_String busc,CListValue* sumolist) +static KX_GameObject* getGameOb(STR_String busc,CListValue* sumolist) { for (int j=0;jGetCount();j++) @@ -2617,7 +2621,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, KX_SlowParentRelation * slow_parent_relation = KX_SlowParentRelation::New(blenderchild->sf); pcit->m_gamechildnode->SetParentRelation(slow_parent_relation); break; - } + } case PARBONE: { // parent this to a bone @@ -2741,7 +2745,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, } - } + } // create physics joints for (i=0;iGetCount();i++) @@ -2825,7 +2829,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, kxscene->GetPhysicsEnvironment()->setConstraintParam(constraintId,dof,1,-1); } dofbit<<=1; - } + } } else if (dat->type == PHY_LINEHINGE_CONSTRAINT) { diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.h b/source/gameengine/Converter/BL_BlenderDataConversion.h index e6c35c20f4c..2a7efaac898 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.h +++ b/source/gameengine/Converter/BL_BlenderDataConversion.h @@ -52,5 +52,4 @@ void BL_ConvertBlenderObjects(struct Main* maggie, SCA_IInputDevice::KX_EnumInputs ConvertKeyCode(int key_code); -#endif // __BL_BLENDERDATACONVERSION_H__ - +#endif /* __BL_BLENDERDATACONVERSION_H__ */ diff --git a/source/gameengine/Converter/BL_DeformableGameObject.h b/source/gameengine/Converter/BL_DeformableGameObject.h index 61477fb1cac..95e3b7c517d 100644 --- a/source/gameengine/Converter/BL_DeformableGameObject.h +++ b/source/gameengine/Converter/BL_DeformableGameObject.h @@ -32,9 +32,9 @@ #ifndef __BL_DEFORMABLEGAMEOBJECT_H__ #define __BL_DEFORMABLEGAMEOBJECT_H__ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning -#endif //WIN32 +#ifdef _MSC_VER +# pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning +#endif #include "DNA_mesh_types.h" #include "KX_GameObject.h" @@ -89,7 +89,7 @@ public: public: -protected: +protected: RAS_Deformer *m_pDeformer; @@ -104,5 +104,4 @@ protected: #endif }; -#endif - +#endif /* __BL_DEFORMABLEGAMEOBJECT_H__ */ diff --git a/source/gameengine/Converter/BL_MeshDeformer.cpp b/source/gameengine/Converter/BL_MeshDeformer.cpp index c9371b9df50..911ff245ab4 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.cpp +++ b/source/gameengine/Converter/BL_MeshDeformer.cpp @@ -30,11 +30,10 @@ * \ingroup bgeconv */ - -#if defined(WIN32) && !defined(FREE_WINDOWS) -// This warning tells us about truncation of __long__ stl-generated names. -// It can occasionally cause DevStudio to have internal compiler warnings. -#pragma warning( disable : 4786 ) +#ifdef _MSC_VER + /* This warning tells us about truncation of __long__ stl-generated names. + * It can occasionally cause DevStudio to have internal compiler warnings. */ +# pragma warning( disable:4786 ) #endif #include "RAS_IPolygonMaterial.h" @@ -84,7 +83,7 @@ bool BL_MeshDeformer::Apply(RAS_IPolyMaterial*) } BL_MeshDeformer::~BL_MeshDeformer() -{ +{ if (m_transverts) delete [] m_transverts; if (m_transnors) @@ -155,27 +154,27 @@ void BL_MeshDeformer::RecalcNormals() v4 = &it.vertex[it.index[i+3]]; co4 = m_transverts[v4->getOrigIndex()]; - n1[0]= co1[0]-co3[0]; - n1[1]= co1[1]-co3[1]; - n1[2]= co1[2]-co3[2]; + n1[0] = co1[0] - co3[0]; + n1[1] = co1[1] - co3[1]; + n1[2] = co1[2] - co3[2]; - n2[0]= co2[0]-co4[0]; - n2[1]= co2[1]-co4[1]; - n2[2]= co2[2]-co4[2]; + n2[0] = co2[0] - co4[0]; + n2[1] = co2[1] - co4[1]; + n2[2] = co2[2] - co4[2]; } else { - n1[0]= co1[0]-co2[0]; - n2[0]= co2[0]-co3[0]; - n1[1]= co1[1]-co2[1]; + n1[0] = co1[0] - co2[0]; + n2[0] = co2[0] - co3[0]; + n1[1] = co1[1] - co2[1]; - n2[1]= co2[1]-co3[1]; - n1[2]= co1[2]-co2[2]; - n2[2]= co2[2]-co3[2]; + n2[1] = co2[1] - co3[1]; + n1[2] = co1[2] - co2[2]; + n2[2] = co2[2] - co3[2]; } - fnor[0]= n1[1]*n2[2] - n1[2]*n2[1]; - fnor[1]= n1[2]*n2[0] - n1[0]*n2[2]; - fnor[2]= n1[0]*n2[1] - n1[1]*n2[0]; + fnor[0] = n1[1] * n2[2] - n1[2] * n2[1]; + fnor[1] = n1[2] * n2[0] - n1[0] * n2[2]; + fnor[2] = n1[0] * n2[1] - n1[1] * n2[0]; normalize_v3(fnor); /* add to vertices for smooth normals */ diff --git a/source/gameengine/Converter/BL_MeshDeformer.h b/source/gameengine/Converter/BL_MeshDeformer.h index c84d31c72cd..6e84cdf03f8 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.h +++ b/source/gameengine/Converter/BL_MeshDeformer.h @@ -38,9 +38,9 @@ #include "MT_Point3.h" #include -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning -#endif //WIN32 +#ifdef _MSC_VER +# pragma warning (disable:4786) /* get rid of stupid stl-visual compiler debug warning */ +#endif class BL_DeformableGameObject; @@ -70,7 +70,7 @@ public: virtual RAS_Deformer* GetReplica() {return NULL;} virtual void ProcessReplica(); struct Mesh* GetMesh() { return m_bmesh; } - virtual class RAS_MeshObject* GetRasMesh() { return (RAS_MeshObject*)m_pMeshObject; } + virtual class RAS_MeshObject* GetRasMesh() { return m_pMeshObject; } virtual float (* GetTransVerts(int *tot))[3] { *tot= m_tvtot; return m_transverts; } // virtual void InitDeform(double time) {} diff --git a/source/gameengine/Converter/BL_ModifierDeformer.cpp b/source/gameengine/Converter/BL_ModifierDeformer.cpp index c1c94c25108..53755deefe1 100644 --- a/source/gameengine/Converter/BL_ModifierDeformer.cpp +++ b/source/gameengine/Converter/BL_ModifierDeformer.cpp @@ -29,10 +29,9 @@ * \ingroup bgeconv */ - -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable : 4786) -#endif //WIN32 +#ifdef _MSC_VER +# pragma warning (disable:4786) +#endif #include "MEM_guardedalloc.h" #include "BL_ModifierDeformer.h" @@ -42,7 +41,6 @@ #include "RAS_MeshObject.h" #include "PHY_IGraphicController.h" -//#include "BL_ArmatureController.h" #include "DNA_armature_types.h" #include "DNA_action_types.h" #include "DNA_key_types.h" @@ -65,7 +63,6 @@ extern "C"{ #include "BKE_lattice.h" #include "BKE_modifier.h" } - #include "BLI_blenlib.h" #include "BLI_math.h" @@ -113,7 +110,7 @@ bool BL_ModifierDeformer::HasCompatibleDeformer(Object *ob) if ((ob->gameflag & OB_SOFT_BODY) != 0) return false; ModifierData* md; - for (md = (ModifierData*)ob->modifiers.first; md; md = (ModifierData*)md->next) { + for (md = (ModifierData *)ob->modifiers.first; md; md = md->next) { if (modifier_dependsOnTime(md)) continue; if (!(md->mode & eModifierMode_Realtime)) @@ -175,7 +172,7 @@ bool BL_ModifierDeformer::Update(void) * It may not be the case here because of replace mesh actuator */ Mesh *oldmesh = (Mesh*)blendobj->data; blendobj->data = m_bmesh; - /* execute the modifiers */ + /* execute the modifiers */ DerivedMesh *dm = mesh_create_derived_no_virtual(m_scene, blendobj, m_transverts, CD_MASK_MESH); /* restore object data */ blendobj->data = oldmesh; diff --git a/source/gameengine/Converter/BL_ModifierDeformer.h b/source/gameengine/Converter/BL_ModifierDeformer.h index b4827b1bee4..4efe4ca5bfc 100644 --- a/source/gameengine/Converter/BL_ModifierDeformer.h +++ b/source/gameengine/Converter/BL_ModifierDeformer.h @@ -32,9 +32,9 @@ #ifndef __BL_MODIFIERDEFORMER_H__ #define __BL_MODIFIERDEFORMER_H__ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning -#endif //WIN32 +#ifdef _MSC_VER +# pragma warning (disable:4786) /* get rid of stupid stl-visual compiler debug warning */ +#endif #include "BL_ShapeDeformer.h" #include "BL_DeformableGameObject.h" @@ -51,33 +51,34 @@ public: BL_ModifierDeformer(BL_DeformableGameObject *gameobj, - Scene *scene, - Object *bmeshobj, - RAS_MeshObject *mesh) - : - BL_ShapeDeformer(gameobj,bmeshobj, mesh), - m_lastModifierUpdate(-1), - m_scene(scene), - m_dm(NULL) + Scene *scene, + Object *bmeshobj, + RAS_MeshObject *mesh) + : + BL_ShapeDeformer(gameobj,bmeshobj, mesh), + m_lastModifierUpdate(-1), + m_scene(scene), + m_dm(NULL) { m_recalcNormal = false; - }; + } /* this second constructor is needed for making a mesh deformable on the fly. */ BL_ModifierDeformer(BL_DeformableGameObject *gameobj, - struct Scene *scene, - struct Object *bmeshobj_old, - struct Object *bmeshobj_new, - class RAS_MeshObject *mesh, - bool release_object, - BL_ArmatureObject* arma = NULL) - : - BL_ShapeDeformer(gameobj, bmeshobj_old, bmeshobj_new, mesh, release_object, false, arma), - m_lastModifierUpdate(-1), - m_scene(scene), - m_dm(NULL) + struct Scene *scene, + struct Object *bmeshobj_old, + struct Object *bmeshobj_new, + class RAS_MeshObject *mesh, + bool release_object, + BL_ArmatureObject* arma = NULL) + : + BL_ShapeDeformer(gameobj, bmeshobj_old, bmeshobj_new, mesh, release_object, false, arma), + m_lastModifierUpdate(-1), + m_scene(scene), + m_dm(NULL) { - }; + /* pass */ + } virtual void ProcessReplica(); virtual RAS_Deformer *GetReplica(); @@ -111,5 +112,4 @@ protected: #endif }; -#endif - +#endif /* __BL_MODIFIERDEFORMER_H__ */ diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp index c339e10f673..d8b4f6aaf1c 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -83,7 +83,7 @@ BL_ShapeActionActuator::BL_ShapeActionActuator(SCA_IObject* gameobj, m_playtype(playtype), m_priority(priority), m_action(action), - m_framepropname(framepropname), + m_framepropname(framepropname), m_propname(propname) { m_idptr = new PointerRNA(); @@ -526,15 +526,15 @@ PyAttributeDef BL_ShapeActionActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* BL_ShapeActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *BL_ShapeActionActuator::pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - BL_ShapeActionActuator* self= static_cast(self_v); + BL_ShapeActionActuator* self = static_cast(self_v); return PyUnicode_FromString(self->GetAction() ? self->GetAction()->id.name+2 : ""); } int BL_ShapeActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - BL_ShapeActionActuator* self= static_cast(self_v); + BL_ShapeActionActuator* self = static_cast(self_v); /* exact copy of BL_ActionActuator's function from here down */ if (!PyUnicode_Check(value)) { diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h index b88631c89d6..f72275b79cf 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.h +++ b/source/gameengine/Converter/BL_ShapeActionActuator.h @@ -108,7 +108,7 @@ public: } -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ protected: @@ -141,5 +141,4 @@ protected: struct PointerRNA *m_idptr; }; -#endif - +#endif /* __BL_SHAPEACTIONACTUATOR_H__ */ diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp index b93d731c5e6..f262532e7e2 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.cpp +++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp @@ -29,10 +29,9 @@ * \ingroup bgeconv */ - -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable : 4786) -#endif //WIN32 +#ifdef _MSC_VER +# pragma warning (disable:4786) +#endif #include "MEM_guardedalloc.h" #include "BL_ShapeDeformer.h" @@ -41,7 +40,6 @@ #include "RAS_IPolygonMaterial.h" #include "RAS_MeshObject.h" -//#include "BL_ArmatureController.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_action_types.h" @@ -60,7 +58,6 @@ extern "C"{ #include "BKE_lattice.h" #include "BKE_animsys.h" } - #include "BLI_blenlib.h" #include "BLI_math.h" @@ -173,7 +170,7 @@ bool BL_ShapeDeformer::Update(void) /* store verts locally */ VerifyStorage(); - do_rel_key(0, m_bmesh->totvert, m_bmesh->totvert, (char *)(float *)m_transverts, m_bmesh->key, NULL, 0); /* last arg is ignored */ + BKE_key_evaluate_relative(0, m_bmesh->totvert, m_bmesh->totvert, (char *)(float *)m_transverts, m_bmesh->key, NULL, 0); /* last arg is ignored */ m_bDynamic = true; } diff --git a/source/gameengine/Converter/BL_ShapeDeformer.h b/source/gameengine/Converter/BL_ShapeDeformer.h index efc1b546666..60f27c85e4f 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.h +++ b/source/gameengine/Converter/BL_ShapeDeformer.h @@ -32,9 +32,9 @@ #ifndef __BL_SHAPEDEFORMER_H__ #define __BL_SHAPEDEFORMER_H__ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning -#endif //WIN32 +#ifdef _MSC_VER +# pragma warning (disable:4786) /* get rid of stupid stl-visual compiler debug warning */ +#endif #include "BL_SkinDeformer.h" #include "BL_DeformableGameObject.h" @@ -73,7 +73,7 @@ public: }; protected: - bool m_useShapeDrivers; + bool m_useShapeDrivers; double m_lastShapeUpdate; struct Key* m_key; diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index 47cba81798d..e068a91bf7e 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -29,10 +29,9 @@ * \ingroup bgeconv */ - -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable : 4786) -#endif //WIN32 +#ifdef _MSC_VER +# pragma warning (disable:4786) +#endif // Eigen3 stuff used for BGEDeformVerts #include @@ -67,12 +66,12 @@ extern "C"{ #define __NLA_DEFNORMALS //#undef __NLA_DEFNORMALS -short get_deformflags(struct Object *bmeshobj) +static short get_deformflags(struct Object *bmeshobj) { short flags = ARM_DEF_VGROUP; ModifierData *md; - for (md = (ModifierData*)bmeshobj->modifiers.first; md; md = (ModifierData*)md->next) + for (md = (ModifierData *)bmeshobj->modifiers.first; md; md = md->next) { if (md->type == eModifierType_Armature) { @@ -85,9 +84,9 @@ short get_deformflags(struct Object *bmeshobj) } BL_SkinDeformer::BL_SkinDeformer(BL_DeformableGameObject *gameobj, - struct Object *bmeshobj, - class RAS_MeshObject *mesh, - BL_ArmatureObject* arma) + struct Object *bmeshobj, + class RAS_MeshObject *mesh, + BL_ArmatureObject* arma) : // BL_MeshDeformer(gameobj, bmeshobj, mesh), m_armobj(arma), @@ -110,7 +109,7 @@ BL_SkinDeformer::BL_SkinDeformer( class RAS_MeshObject *mesh, bool release_object, bool recalc_normal, - BL_ArmatureObject* arma) : + BL_ArmatureObject* arma) : BL_MeshDeformer(gameobj, bmeshobj_old, mesh), m_armobj(arma), m_lastArmaUpdate(-1), @@ -249,7 +248,7 @@ void BL_SkinDeformer::BGEDeformVerts() int i; for (i=0, dg=(bDeformGroup*)m_objMesh->defbase.first; dg; - ++i, dg=(bDeformGroup*)dg->next) + ++i, dg = dg->next) { m_dfnrToPC[i] = BKE_pose_channel_find_name(par_arma->pose, dg->name); @@ -327,7 +326,7 @@ void BL_SkinDeformer::BGEDeformVerts() bool BL_SkinDeformer::UpdateInternal(bool shape_applied) { /* See if the armature has been updated for this frame */ - if (PoseUpdated()) { + if (PoseUpdated()) { if (!shape_applied) { /* store verts locally */ diff --git a/source/gameengine/Converter/BL_SkinDeformer.h b/source/gameengine/Converter/BL_SkinDeformer.h index 48c3c3e6186..7495deb2257 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.h +++ b/source/gameengine/Converter/BL_SkinDeformer.h @@ -32,9 +32,9 @@ #ifndef __BL_SKINDEFORMER_H__ #define __BL_SKINDEFORMER_H__ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning -#endif //WIN32 +#ifdef _MSC_VER +# pragma warning (disable:4786) /* get rid of stupid stl-visual compiler debug warning */ +#endif /* WIN32 */ #include "CTR_HashedPtr.h" #include "BL_MeshDeformer.h" @@ -56,18 +56,18 @@ public: void SetArmature (class BL_ArmatureObject *armobj); BL_SkinDeformer(BL_DeformableGameObject *gameobj, - struct Object *bmeshobj, - class RAS_MeshObject *mesh, - BL_ArmatureObject* arma = NULL); + struct Object *bmeshobj, + class RAS_MeshObject *mesh, + BL_ArmatureObject* arma = NULL); /* this second constructor is needed for making a mesh deformable on the fly. */ BL_SkinDeformer(BL_DeformableGameObject *gameobj, - struct Object *bmeshobj_old, - struct Object *bmeshobj_new, - class RAS_MeshObject *mesh, - bool release_object, - bool recalc_normal, - BL_ArmatureObject* arma = NULL); + struct Object *bmeshobj_old, + struct Object *bmeshobj_new, + class RAS_MeshObject *mesh, + bool release_object, + bool recalc_normal, + BL_ArmatureObject* arma = NULL); virtual RAS_Deformer *GetReplica(); virtual void ProcessReplica(); @@ -120,5 +120,4 @@ protected: #endif }; -#endif - +#endif /* __BL_SKINDEFORMER_H__ */ diff --git a/source/gameengine/Converter/BlenderWorldInfo.cpp b/source/gameengine/Converter/BlenderWorldInfo.cpp index fc3b75c49ad..25da8155867 100644 --- a/source/gameengine/Converter/BlenderWorldInfo.cpp +++ b/source/gameengine/Converter/BlenderWorldInfo.cpp @@ -199,7 +199,7 @@ void BlenderWorldInfo::setBackColor(float r, float g, float b) m_backgroundcolor[2] = b; } - void + void BlenderWorldInfo::setMistStart( float d ) { @@ -215,7 +215,7 @@ BlenderWorldInfo::setMistDistance( } - void + void BlenderWorldInfo::setMistColorRed( float d ) { @@ -231,7 +231,7 @@ BlenderWorldInfo::setMistColorGreen( } - void + void BlenderWorldInfo::setMistColorBlue( float d ) { diff --git a/source/gameengine/Converter/BlenderWorldInfo.h b/source/gameengine/Converter/BlenderWorldInfo.h index e00eb99e73f..30de5e89269 100644 --- a/source/gameengine/Converter/BlenderWorldInfo.h +++ b/source/gameengine/Converter/BlenderWorldInfo.h @@ -73,27 +73,27 @@ public: float g, float b ); - void + void setMistStart( float d ); - void + void setMistDistance( float d ); - void + void setMistColorRed( float d ); - void + void setMistColorGreen( float d ); - void + void setMistColorBlue( float d ); @@ -104,5 +104,4 @@ public: #endif }; -#endif //__BLENDERWORLDINFO_H__ - +#endif /* __BLENDERWORLDINFO_H__ */ diff --git a/source/gameengine/Converter/CMakeLists.txt b/source/gameengine/Converter/CMakeLists.txt index 1826f1ad25b..7b801fd4ffb 100644 --- a/source/gameengine/Converter/CMakeLists.txt +++ b/source/gameengine/Converter/CMakeLists.txt @@ -49,16 +49,15 @@ set(INC ../../blender/makesdna ../../blender/makesrna ../../blender/windowmanager - ../../../extern/bullet2/src - ../../../extern/Eigen3 ../../../intern/container ../../../intern/guardedalloc ../../../intern/moto/include ../../../intern/string - ../../../extern/recastnavigation/Detour/Include ) set(INC_SYS + ../../../extern/recastnavigation/Detour/Include + ../../../extern/Eigen3 ${PTHREADS_INCLUDE_DIRS} ) @@ -110,6 +109,9 @@ set(SRC ) if(WITH_BULLET) + list(APPEND INC_SYS + ../../../extern/bullet2/src + ) add_definitions(-DUSE_BULLET) endif() diff --git a/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp b/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp index f020aab4d50..1e1bc738301 100644 --- a/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp +++ b/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp @@ -52,7 +52,7 @@ BL_InterpolatorList::BL_InterpolatorList(bAction *action) if (action==NULL) return; - for (FCurve *fcu= (FCurve *)action->curves.first; fcu; fcu= (FCurve *)fcu->next) { + for (FCurve *fcu = (FCurve *)action->curves.first; fcu; fcu = fcu->next) { if (fcu->rna_path) { BL_ScalarInterpolator *new_ipo = new BL_ScalarInterpolator(fcu); //assert(new_ipo); @@ -78,5 +78,5 @@ KX_IScalarInterpolator *BL_InterpolatorList::GetScalarInterpolator(const char *r return *i; } return NULL; -} +} diff --git a/source/gameengine/Converter/KX_BlenderScalarInterpolator.h b/source/gameengine/Converter/KX_BlenderScalarInterpolator.h index bc5a6eeef85..d828910233f 100644 --- a/source/gameengine/Converter/KX_BlenderScalarInterpolator.h +++ b/source/gameengine/Converter/KX_BlenderScalarInterpolator.h @@ -65,7 +65,7 @@ public: BL_InterpolatorList(struct bAction *action); ~BL_InterpolatorList(); - KX_IScalarInterpolator *GetScalarInterpolator(const char *rna_path, int array_index); + KX_IScalarInterpolator *GetScalarInterpolator(const char *rna_path, int array_index); #ifdef WITH_CXX_GUARDEDALLOC @@ -73,5 +73,4 @@ public: #endif }; -#endif //__KX_BLENDERSCALARINTERPOLATOR_H__ - +#endif /* __KX_BLENDERSCALARINTERPOLATOR_H__ */ diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 1c3352454a2..30a4209965e 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -29,9 +29,8 @@ * \ingroup bgeconv */ - -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable:4786) // suppress stl-MSVC debug info warning +#ifdef _MSC_VER +# pragma warning (disable:4786) /* suppress stl-MSVC debug info warning */ #endif #include "KX_Scene.h" @@ -160,7 +159,7 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter() while (itmat != m_materials.end()) { delete (*itmat).second; itmat++; - } + } vector >::iterator itm = m_meshobjects.begin(); @@ -201,7 +200,7 @@ bool KX_BlenderSceneConverter::TryAndLoadNewFile() // if not, clear the newfilename else { - m_newfilename = ""; + m_newfilename = ""; } */ return result; @@ -335,7 +334,7 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, ccdPhysEnv->setDebugMode(btIDebugDraw::DBG_DrawWireframe|btIDebugDraw::DBG_DrawAabb|btIDebugDraw::DBG_DrawContactPoints|btIDebugDraw::DBG_DrawText|btIDebugDraw::DBG_DrawConstraintLimits|btIDebugDraw::DBG_DrawConstraints); //todo: get a button in blender ? - //disable / enable debug drawing (contact points, aabb's etc) + //disable / enable debug drawing (contact points, aabb's etc) //ccdPhysEnv->setDebugMode(1); destinationscene->SetPhysicsEnvironment(ccdPhysEnv); break; @@ -689,7 +688,7 @@ void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo) void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo() { - if (addInitFromFrame) { + if (addInitFromFrame) { KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); if (numScenes>=0) { @@ -704,7 +703,7 @@ void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo() if (blenderobject->type==OB_ARMATURE) continue; float eu[3]; - mat4_to_eul(eu,blenderobject->obmat); + mat4_to_eul(eu,blenderobject->obmat); MT_Point3 pos = MT_Point3( blenderobject->obmat[3][0], blenderobject->obmat[3][1], @@ -779,8 +778,8 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation(); - float eulerAngles[3]; - float eulerAnglesOld[3] = {0.0f, 0.0f, 0.0f}; + float eulerAngles[3]; + float eulerAnglesOld[3] = {0.0f, 0.0f, 0.0f}; float tmat[3][3]; // XXX animato @@ -819,13 +818,13 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) if (icu_rz) icu_rz->ipo = IPO_LIN; } - if (icu_rx) eulerAnglesOld[0]= eval_icu( icu_rx, frameNumber - 1 ) / ((180 / 3.14159265f) / 10); - if (icu_ry) eulerAnglesOld[1]= eval_icu( icu_ry, frameNumber - 1 ) / ((180 / 3.14159265f) / 10); - if (icu_rz) eulerAnglesOld[2]= eval_icu( icu_rz, frameNumber - 1 ) / ((180 / 3.14159265f) / 10); + if (icu_rx) eulerAnglesOld[0] = eval_icu( icu_rx, frameNumber - 1 ) / ((180 / 3.14159265f) / 10); + if (icu_ry) eulerAnglesOld[1] = eval_icu( icu_ry, frameNumber - 1 ) / ((180 / 3.14159265f) / 10); + if (icu_rz) eulerAnglesOld[2] = eval_icu( icu_rz, frameNumber - 1 ) / ((180 / 3.14159265f) / 10); // orn.getValue((float *)tmat); // uses the wrong ordering, cant use this - for (int r=0;r<3;r++) - for (int c=0;c<3;c++) + for (int r = 0; r < 3; r++) + for (int c = 0; c < 3; c++) tmat[r][c] = orn[c][r]; // mat3_to_eul( eulerAngles,tmat); // better to use Mat3ToCompatibleEul @@ -945,7 +944,7 @@ static void load_datablocks(Main *main_newlib, BlendHandle *bpy_openlib, const c int i=0; LinkNode *n= names; - while(n) { + while (n) { BLO_library_append_named_part(main_tmp, &bpy_openlib, (char *)n->link, idcode); n= (LinkNode *)n->next; i++; @@ -984,7 +983,7 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha } main_newlib= (Main *)MEM_callocN( sizeof(Main), "BgeMain"); - BKE_reports_init(&reports, RPT_STORE); + BKE_reports_init(&reports, RPT_STORE); load_datablocks(main_newlib, bpy_openlib, path, idcode); @@ -1000,11 +999,11 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha BLO_blendhandle_close(bpy_openlib); BKE_reports_clear(&reports); - /* done linking */ + /* done linking */ /* needed for lookups*/ GetMainDynamic().push_back(main_newlib); - strncpy(main_newlib->name, path, sizeof(main_newlib->name)); + strncpy(main_newlib->name, path, sizeof(main_newlib->name)); if (idcode==ID_ME) { @@ -1028,7 +1027,7 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action); } } - else if (idcode==ID_SCE) { + else if (idcode==ID_SCE) { /* Merge all new linked in scene into the existing one */ ID *scene; for (scene= (ID *)main_newlib->scene.first; scene; scene= (ID *)scene->next ) { @@ -1117,7 +1116,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) { RAS_MeshObject *meshobj= (RAS_MeshObject *) *mapStringToMeshes.at(i); if (meshobj && IS_TAGGED(meshobj->GetMesh())) - { + { STR_HashedString mn = meshobj->GetName(); mapStringToMeshes.remove(mn); m_map_mesh_to_gamemesh.remove(CHashedPtr(meshobj->GetMesh())); @@ -1171,7 +1170,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) else { /* free the mesh, we could be referecing a linked one! */ int mesh_index= gameobj->GetMeshCount(); - while(mesh_index--) { + while (mesh_index--) { mesh= gameobj->GetMesh(mesh_index); if (IS_TAGGED(mesh->GetMesh())) { gameobj->RemoveMeshes(); /* XXX - slack, should only remove meshes that are library items but mostly objects only have 1 mesh */ @@ -1255,7 +1254,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) RAS_IPolyMaterial *mat= (*polymit).second; Material *bmat= NULL; - /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */ + /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject *)? - Campbell */ if (mat->GetFlag() & RAS_BLENDERMAT) { KX_BlenderMaterial *bl_mat = static_cast(mat); bmat= bl_mat->GetBlenderMaterial(); @@ -1280,7 +1279,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) RAS_IPolyMaterial *mat= (*polymit).second; Material *bmat= NULL; - /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */ + /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject *)? - Campbell */ if (mat->GetFlag() & RAS_BLENDERMAT) { KX_BlenderMaterial *bl_mat = static_cast(mat); bmat= bl_mat->GetBlenderMaterial(); @@ -1451,14 +1450,12 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, BLI_remlink(&m_maggie->mat, mat_new); BLI_addtail(&maggie->mat, mat_new); - mesh->mat[i]= mat_new; + mesh->mat[i] = mat_new; /* the same material may be used twice */ - for (int j=i+1; jtotcol; j++) - { - if (mesh->mat[j]==mat_old) - { - mesh->mat[j]= mat_new; + for (int j = i + 1; j < mesh->totcol; j++) { + if (mesh->mat[j] == mat_old) { + mesh->mat[j] = mat_new; mat_new->id.us++; mat_old->id.us--; } diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.h b/source/gameengine/Converter/KX_BlenderSceneConverter.h index b51c2f21ca7..34a1117a0eb 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.h +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.h @@ -165,11 +165,11 @@ public: printf("\t m_materials: %d\n", (int)m_materials.size()); printf("\nMappings...\n"); - printf("\t m_map_blender_to_gameobject: %d\n", (int)m_map_blender_to_gameobject.size()); - printf("\t m_map_mesh_to_gamemesh: %d\n", (int)m_map_mesh_to_gamemesh.size()); - printf("\t m_map_blender_to_gameactuator: %d\n", (int)m_map_blender_to_gameactuator.size()); - printf("\t m_map_blender_to_gamecontroller: %d\n", (int)m_map_blender_to_gamecontroller.size()); - printf("\t m_map_blender_to_gameAdtList: %d\n", (int)m_map_blender_to_gameAdtList.size()); + printf("\t m_map_blender_to_gameobject: %d\n", m_map_blender_to_gameobject.size()); + printf("\t m_map_mesh_to_gamemesh: %d\n", m_map_mesh_to_gamemesh.size()); + printf("\t m_map_blender_to_gameactuator: %d\n", m_map_blender_to_gameactuator.size()); + printf("\t m_map_blender_to_gamecontroller: %d\n", m_map_blender_to_gamecontroller.size()); + printf("\t m_map_blender_to_gameAdtList: %d\n", m_map_blender_to_gameAdtList.size()); #ifdef WITH_CXX_GUARDEDALLOC MEM_printmemlist_pydict(); @@ -196,5 +196,4 @@ public: #endif }; -#endif //__KX_BLENDERSCENECONVERTER_H__ - +#endif /* __KX_BLENDERSCENECONVERTER_H__ */ diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 9caa6bbf579..24d321730eb 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -30,10 +30,9 @@ * \ingroup bgeconv */ - -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable : 4786) -#endif //WIN32 +#ifdef _MSC_VER +# pragma warning (disable:4786) +#endif #include @@ -105,22 +104,25 @@ #include "BL_BlenderDataConversion.h" /** - * KX_BLENDERTRUNC needed to round 'almost' zero values to zero, else velocities etc. are incorrectly set + * KX_flt_trunc needed to round 'almost' zero values to zero, else velocities etc. are incorrectly set */ -#define KX_BLENDERTRUNC(x) (( x < 0.0001f && x > -0.0001f ) ? 0.0f : x) +BLI_INLINE float KX_flt_trunc(const float x) +{ + return ( x < 0.0001f && x > -0.0001f ) ? 0.0f : x; +} void BL_ConvertActuators(const char* maggiename, - struct Object* blenderobject, - KX_GameObject* gameobj, - SCA_LogicManager* logicmgr, - KX_Scene* scene, - KX_KetsjiEngine* ketsjiEngine, - int activeLayerBitInfo, - bool isInActiveLayer, - RAS_IRenderTools* rendertools, - KX_BlenderSceneConverter* converter - ) + struct Object* blenderobject, + KX_GameObject* gameobj, + SCA_LogicManager* logicmgr, + KX_Scene* scene, + KX_KetsjiEngine* ketsjiEngine, + int activeLayerBitInfo, + bool isInActiveLayer, + RAS_IRenderTools* rendertools, + KX_BlenderSceneConverter* converter + ) { int uniqueint = 0; @@ -134,7 +136,7 @@ void BL_ConvertActuators(const char* maggiename, } gameobj->ReserveActuator(actcount); bact = (bActuator*) blenderobject->actuators.first; - while(bact) + while (bact) { STR_String uniquename = bact->name; STR_String& objectname = gameobj->GetName(); @@ -146,20 +148,23 @@ void BL_ConvertActuators(const char* maggiename, { bObjectActuator* obact = (bObjectActuator*) bact->data; KX_GameObject* obref = NULL; - MT_Vector3 forcevec(KX_BLENDERTRUNC(obact->forceloc[0]), - KX_BLENDERTRUNC(obact->forceloc[1]), - KX_BLENDERTRUNC(obact->forceloc[2])); - MT_Vector3 torquevec(obact->forcerot[0],obact->forcerot[1],obact->forcerot[2]); - MT_Vector3 dlocvec ( KX_BLENDERTRUNC(obact->dloc[0]), - KX_BLENDERTRUNC(obact->dloc[1]), - KX_BLENDERTRUNC(obact->dloc[2])); - MT_Vector3 drotvec ( KX_BLENDERTRUNC(obact->drot[0]),obact->drot[1],obact->drot[2]); - MT_Vector3 linvelvec ( KX_BLENDERTRUNC(obact->linearvelocity[0]), - KX_BLENDERTRUNC(obact->linearvelocity[1]), - KX_BLENDERTRUNC(obact->linearvelocity[2])); - MT_Vector3 angvelvec ( KX_BLENDERTRUNC(obact->angularvelocity[0]), - KX_BLENDERTRUNC(obact->angularvelocity[1]), - KX_BLENDERTRUNC(obact->angularvelocity[2])); + MT_Vector3 forcevec(KX_flt_trunc(obact->forceloc[0]), + KX_flt_trunc(obact->forceloc[1]), + KX_flt_trunc(obact->forceloc[2])); + MT_Vector3 torquevec(obact->forcerot[0], + obact->forcerot[1], + obact->forcerot[2]); + MT_Vector3 dlocvec(KX_flt_trunc(obact->dloc[0]), + KX_flt_trunc(obact->dloc[1]), + KX_flt_trunc(obact->dloc[2])); + MT_Vector3 drotvec(KX_flt_trunc(obact->drot[0]), + obact->drot[1],obact->drot[2]); + MT_Vector3 linvelvec(KX_flt_trunc(obact->linearvelocity[0]), + KX_flt_trunc(obact->linearvelocity[1]), + KX_flt_trunc(obact->linearvelocity[2])); + MT_Vector3 angvelvec(KX_flt_trunc(obact->angularvelocity[0]), + KX_flt_trunc(obact->angularvelocity[1]), + KX_flt_trunc(obact->angularvelocity[2])); short damping = obact->damping; /* Blender uses a bit vector internally for the local-flags. In */ @@ -181,17 +186,17 @@ void BL_ConvertActuators(const char* maggiename, obref = converter->FindGameObject(obact->reference); } - KX_ObjectActuator* tmpbaseact = new KX_ObjectActuator(gameobj, - obref, - forcevec.getValue(), - torquevec.getValue(), - dlocvec.getValue(), - drotvec.getValue(), - linvelvec.getValue(), - angvelvec.getValue(), - damping, - bitLocalFlag - ); + KX_ObjectActuator* tmpbaseact = new KX_ObjectActuator( + gameobj, + obref, + forcevec.getValue(), + torquevec.getValue(), + dlocvec.getValue(), + drotvec.getValue(), + linvelvec.getValue(), + angvelvec.getValue(), + damping, + bitLocalFlag); baseact = tmpbaseact; break; } @@ -210,22 +215,22 @@ void BL_ConvertActuators(const char* maggiename, if (actact->flag & ACT_IPOCHILD) ipo_flags |= BL_Action::ACT_IPOFLAG_CHILD; BL_ActionActuator* tmpbaseact = new BL_ActionActuator( - gameobj, - propname, - propframe, - actact->sta, - actact->end, - actact->act, - actact->type, // + 1, because Blender starts to count at zero, - actact->blendin, - actact->priority, - actact->layer, - actact->layer_weight, - ipo_flags, - actact->end_reset, - actact->stridelength - // Ketsji at 1, because zero is reserved for "NoDef" - ); + gameobj, + propname, + propframe, + actact->sta, + actact->end, + actact->act, + actact->type, // + 1, because Blender starts to count at zero, + actact->blendin, + actact->priority, + actact->layer, + actact->layer_weight, + ipo_flags, + actact->end_reset, + actact->stridelength + // Ketsji at 1, because zero is reserved for "NoDef" + ); baseact= tmpbaseact; break; } @@ -237,18 +242,17 @@ void BL_ConvertActuators(const char* maggiename, STR_String propframe = (actact->frameProp ? actact->frameProp : ""); BL_ShapeActionActuator* tmpbaseact = new BL_ShapeActionActuator( - gameobj, - propname, - propframe, - actact->sta, - actact->end, - actact->act, - actact->type, // + 1, because Blender starts to count at zero, - actact->blendin, - actact->priority, - actact->stridelength - // Ketsji at 1, because zero is reserved for "NoDef" - ); + gameobj, + propname, + propframe, + actact->sta, + actact->end, + actact->act, + actact->type, // + 1, because Blender starts to count at zero, + actact->blendin, + actact->priority, + actact->stridelength); + // Ketsji at 1, because zero is reserved for "NoDef" baseact= tmpbaseact; break; } @@ -267,17 +271,17 @@ void BL_ConvertActuators(const char* maggiename, bool ipo_add = (ipoact->flag & ACT_IPOADD); KX_IpoActuator* tmpbaseact = new KX_IpoActuator( - gameobj, - propname , - frameProp, - ipoact->sta, - ipoact->end, - ipochild, - ipoact->type + 1, // + 1, because Blender starts to count at zero, - // Ketsji at 1, because zero is reserved for "NoDef" - ipo_as_force, - ipo_add, - local); + gameobj, + propname , + frameProp, + ipoact->sta, + ipoact->end, + ipochild, + ipoact->type + 1, // + 1, because Blender starts to count at zero, + // Ketsji at 1, because zero is reserved for "NoDef" + ipo_as_force, + ipo_add, + local); baseact = tmpbaseact; break; } @@ -293,14 +297,14 @@ void BL_ConvertActuators(const char* maggiename, /* visifac, fac and axis are not copied from the struct... */ /* that's some internal state... */ - KX_CameraActuator *tmpcamact - = new KX_CameraActuator(gameobj, - tmpgob, - camact->height, - camact->min, - camact->max, - camact->axis, - camact->damping); + KX_CameraActuator *tmpcamact = new KX_CameraActuator( + gameobj, + tmpgob, + camact->height, + camact->min, + camact->max, + camact->axis, + camact->damping); baseact = tmpcamact; } break; @@ -333,14 +337,13 @@ void BL_ConvertActuators(const char* maggiename, ? (char*) msgAct->body : ""); - KX_NetworkMessageActuator *tmpmsgact = - new KX_NetworkMessageActuator( - gameobj, // actuator controlling object - scene->GetNetworkScene(), // needed for replication - toPropName, - subject, - bodyType, - body); + KX_NetworkMessageActuator *tmpmsgact = new KX_NetworkMessageActuator( + gameobj, // actuator controlling object + scene->GetNetworkScene(), // needed for replication + toPropName, + subject, + bodyType, + body); baseact = tmpmsgact; break; } @@ -355,7 +358,7 @@ void BL_ConvertActuators(const char* maggiename, KX_SoundActuator::KX_SOUNDACT_TYPE soundActuatorType = KX_SoundActuator::KX_SOUNDACT_NODEF; - switch(soundact->type) { + switch (soundact->type) { case ACT_SND_PLAY_STOP_SOUND: soundActuatorType = KX_SoundActuator::KX_SOUNDACT_PLAYSTOP; break; @@ -457,11 +460,11 @@ void BL_ConvertActuators(const char* maggiename, destinationObj = converter->FindGameObject(propact->ob); SCA_PropertyActuator* tmppropact = new SCA_PropertyActuator( - gameobj, - destinationObj, - propact->name, - propact->value, - propact->type+1); // + 1 because Ketsji Logic starts + gameobj, + destinationObj, + propact->name, + propact->value, + propact->type + 1); // + 1 because Ketsji Logic starts // with 0 for KX_ACT_PROP_NODEF baseact = tmppropact; break; @@ -491,18 +494,16 @@ void BL_ConvertActuators(const char* maggiename, } } - KX_SCA_AddObjectActuator* tmpaddact = - new KX_SCA_AddObjectActuator( - gameobj, - originalval, - editobact->time, - scene, - editobact->linVelocity, - (editobact->localflag & ACT_EDOB_LOCAL_LINV)!=0, - editobact->angVelocity, - (editobact->localflag & ACT_EDOB_LOCAL_ANGV)!=0 - ); - + KX_SCA_AddObjectActuator* tmpaddact = new KX_SCA_AddObjectActuator( + gameobj, + originalval, + editobact->time, + scene, + editobact->linVelocity, + (editobact->localflag & ACT_EDOB_LOCAL_LINV) != 0, + editobact->angVelocity, + (editobact->localflag & ACT_EDOB_LOCAL_ANGV) != 0); + //editobact->ob to gameobj baseact = tmpaddact; } @@ -519,23 +520,20 @@ void BL_ConvertActuators(const char* maggiename, RAS_MeshObject *tmpmesh = NULL; if (editobact->me) tmpmesh = BL_ConvertMesh( - editobact->me, - blenderobject, - scene, - converter - ); + editobact->me, + blenderobject, + scene, + converter + ); - KX_SCA_ReplaceMeshActuator* tmpreplaceact - = new KX_SCA_ReplaceMeshActuator( - gameobj, - tmpmesh, - scene, - (editobact->flag & ACT_EDOB_REPLACE_MESH_NOGFX)==0, - (editobact->flag & ACT_EDOB_REPLACE_MESH_PHYS)!=0 - - ); - - baseact = tmpreplaceact; + KX_SCA_ReplaceMeshActuator* tmpreplaceact = new KX_SCA_ReplaceMeshActuator( + gameobj, + tmpmesh, + scene, + (editobact->flag & ACT_EDOB_REPLACE_MESH_NOGFX) == 0, + (editobact->flag & ACT_EDOB_REPLACE_MESH_PHYS) != 0); + + baseact = tmpreplaceact; } break; case ACT_EDOB_TRACK_TO: @@ -544,25 +542,23 @@ void BL_ConvertActuators(const char* maggiename, if (editobact->ob) originalval = converter->FindGameObject(editobact->ob); - KX_TrackToActuator* tmptrackact - = new KX_TrackToActuator(gameobj, - originalval, - editobact->time, - editobact->flag, - blenderobject->trackflag, - blenderobject->upflag - ); - baseact = tmptrackact; + KX_TrackToActuator* tmptrackact = new KX_TrackToActuator( + gameobj, + originalval, + editobact->time, + editobact->flag, + blenderobject->trackflag, + blenderobject->upflag); + baseact = tmptrackact; break; } case ACT_EDOB_DYNAMICS: { - KX_SCA_DynamicActuator* tmpdynact - = new KX_SCA_DynamicActuator(gameobj, - editobact->dyn_operation, - editobact->mass - ); - baseact = tmpdynact; + KX_SCA_DynamicActuator* tmpdynact = new KX_SCA_DynamicActuator( + gameobj, + editobact->dyn_operation, + editobact->mass); + baseact = tmpdynact; } } break; @@ -694,17 +690,17 @@ void BL_ConvertActuators(const char* maggiename, ; /* error */ } } - KX_ConstraintActuator *tmpconact - = new KX_ConstraintActuator(gameobj, - conact->damp, - conact->rotdamp, - min, - max, - conact->maxrot, - locrot, - conact->time, - conact->flag, - prop); + KX_ConstraintActuator *tmpconact = new KX_ConstraintActuator( + gameobj, + conact->damp, + conact->rotdamp, + min, + max, + conact->maxrot, + locrot, + conact->time, + conact->flag, + prop); baseact = tmpconact; break; } @@ -777,13 +773,14 @@ void BL_ConvertActuators(const char* maggiename, default: ; /* flag error */ } - tmpsceneact = new KX_SceneActuator(gameobj, - mode, - scene, - ketsjiEngine, - nextSceneName, - cam); - baseact = tmpsceneact; + tmpsceneact = new KX_SceneActuator( + gameobj, + mode, + scene, + ketsjiEngine, + nextSceneName, + cam); + baseact = tmpsceneact; break; } case ACT_GAME: @@ -832,13 +829,14 @@ void BL_ConvertActuators(const char* maggiename, default: ; /* flag error */ } - tmpgameact = new KX_GameActuator(gameobj, - mode, - filename, - loadinganimationname, - scene, - ketsjiEngine); - baseact = tmpgameact; + tmpgameact = new KX_GameActuator( + gameobj, + mode, + filename, + loadinganimationname, + scene, + ketsjiEngine); + baseact = tmpgameact; break; } @@ -903,14 +901,15 @@ void BL_ConvertActuators(const char* maggiename, modeArg = SCA_RandomActuator::KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL; break; default: - ; /* error */ + ; /* error */ } - tmprandomact = new SCA_RandomActuator(gameobj, - seedArg, - modeArg, - paraArg1, - paraArg2, - randAct->propname); + tmprandomact = new SCA_RandomActuator( + gameobj, + seedArg, + modeArg, + paraArg1, + paraArg2, + randAct->propname); baseact = tmprandomact; } break; @@ -947,8 +946,7 @@ void BL_ConvertActuators(const char* maggiename, SCA_2DFilterActuator *tmp = NULL; RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode; - switch(_2dfilter->type) - { + switch (_2dfilter->type) { case ACT_2DFILTER_MOTIONBLUR: filtermode = RAS_2DFilterManager::RAS_2DFILTER_MOTIONBLUR; break; @@ -999,8 +997,9 @@ void BL_ConvertActuators(const char* maggiename, break; } - tmp = new SCA_2DFilterActuator(gameobj, filtermode, _2dfilter->flag, - _2dfilter->float_arg,_2dfilter->int_arg,ketsjiEngine->GetRasterizer(),scene); + tmp = new SCA_2DFilterActuator(gameobj, filtermode, _2dfilter->flag, + _2dfilter->float_arg, _2dfilter->int_arg, + ketsjiEngine->GetRasterizer(), scene); if (_2dfilter->text) { @@ -1026,8 +1025,7 @@ void BL_ConvertActuators(const char* maggiename, bool ghost = true; KX_GameObject *tmpgob = NULL; - switch(parAct->type) - { + switch (parAct->type) { case ACT_PARENT_SET: mode = KX_ParentActuator::KX_PARENT_SET; tmpgob = converter->FindGameObject(parAct->ob); @@ -1055,7 +1053,15 @@ void BL_ConvertActuators(const char* maggiename, bArmatureActuator* armAct = (bArmatureActuator*) bact->data; KX_GameObject *tmpgob = converter->FindGameObject(armAct->target); KX_GameObject *subgob = converter->FindGameObject(armAct->subtarget); - BL_ArmatureActuator* tmparmact = new BL_ArmatureActuator(gameobj, armAct->type, armAct->posechannel, armAct->constraint, tmpgob, subgob, armAct->weight, armAct->influence); + BL_ArmatureActuator* tmparmact = new BL_ArmatureActuator( + gameobj, + armAct->type, + armAct->posechannel, + armAct->constraint, + tmpgob, + subgob, + armAct->weight, + armAct->influence); baseact = tmparmact; break; } @@ -1073,8 +1079,7 @@ void BL_ConvertActuators(const char* maggiename, KX_GameObject *targetob = converter->FindGameObject(stAct->target); int mode = KX_SteeringActuator::KX_STEERING_NODEF; - switch(stAct->type) - { + switch (stAct->type) { case ACT_STEERING_SEEK: mode = KX_SteeringActuator::KX_STEERING_SEEK; break; diff --git a/source/gameengine/Converter/KX_ConvertActuators.h b/source/gameengine/Converter/KX_ConvertActuators.h index b7c890458cc..385d274bf89 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.h +++ b/source/gameengine/Converter/KX_ConvertActuators.h @@ -33,16 +33,14 @@ #define __KX_CONVERTACTUATORS_H__ void BL_ConvertActuators(const char* maggiename, - struct Object* blenderobject, - class KX_GameObject* gameobj, - class SCA_LogicManager* logicmgr, - class KX_Scene* scene, - class KX_KetsjiEngine* ketsjiEngine, - int activeLayerBitInfo, - bool isInActiveLayer, - class RAS_IRenderTools* rendertools, - class KX_BlenderSceneConverter* converter); - - -#endif //__KX_CONVERTACTUATORS_H__ + struct Object* blenderobject, + class KX_GameObject* gameobj, + class SCA_LogicManager* logicmgr, + class KX_Scene* scene, + class KX_KetsjiEngine* ketsjiEngine, + int activeLayerBitInfo, + bool isInActiveLayer, + class RAS_IRenderTools* rendertools, + class KX_BlenderSceneConverter* converter); +#endif /* __KX_CONVERTACTUATORS_H__ */ diff --git a/source/gameengine/Converter/KX_ConvertControllers.cpp b/source/gameengine/Converter/KX_ConvertControllers.cpp index 81778928c2e..769abd01ce0 100644 --- a/source/gameengine/Converter/KX_ConvertControllers.cpp +++ b/source/gameengine/Converter/KX_ConvertControllers.cpp @@ -69,7 +69,7 @@ static void LinkControllerToActuators( SCA_IController *game_controller, - bController* bcontr, + bController* bcontr, SCA_LogicManager* logicmgr, KX_BlenderSceneConverter* converter ) { @@ -110,8 +110,7 @@ void BL_ConvertControllers( while (bcontr) { SCA_IController* gamecontroller = NULL; - switch(bcontr->type) - { + switch (bcontr->type) { case CONT_LOGIC_AND: { gamecontroller = new SCA_ANDController(gameobj); diff --git a/source/gameengine/Converter/KX_ConvertControllers.h b/source/gameengine/Converter/KX_ConvertControllers.h index d1d52f866ec..817a49e1b2f 100644 --- a/source/gameengine/Converter/KX_ConvertControllers.h +++ b/source/gameengine/Converter/KX_ConvertControllers.h @@ -43,6 +43,4 @@ void BL_ConvertControllers( class KX_BlenderSceneConverter* converter ); - -#endif //__KX_CONVERTCONTROLLERS_H__ - +#endif /* __KX_CONVERTCONTROLLERS_H__ */ diff --git a/source/gameengine/Converter/KX_ConvertProperties.cpp b/source/gameengine/Converter/KX_ConvertProperties.cpp index faa7780bac0..7222c673322 100644 --- a/source/gameengine/Converter/KX_ConvertProperties.cpp +++ b/source/gameengine/Converter/KX_ConvertProperties.cpp @@ -67,15 +67,14 @@ void BL_ConvertProperties(Object* object,KX_GameObject* gameobj,SCA_TimeEventMan { bProperty* prop = (bProperty*)object->prop.first; - CValue* propval; + CValue* propval; bool show_debug_info; - while(prop) - { - + + while (prop) { propval = NULL; show_debug_info = bool (prop->flag & PROP_DEBUG); - switch(prop->type) { + switch (prop->type) { case GPROP_BOOL: { propval = new CBoolValue((bool)(prop->data != 0)); @@ -177,14 +176,14 @@ void BL_ConvertTextProperty(Object* object, KX_FontObject* fontobj,SCA_TimeEvent { CValue* tprop = fontobj->GetProperty("Text"); if (!tprop) return; - bProperty* prop = get_ob_property(object, "Text"); + bProperty* prop = BKE_bproperty_object_get(object, "Text"); if (!prop) return; Curve *curve = static_cast(object->data); STR_String str = curve->str; CValue* propval = NULL; - switch(prop->type) { + switch (prop->type) { case GPROP_BOOL: { int value = atoi(str); diff --git a/source/gameengine/Converter/KX_ConvertProperties.h b/source/gameengine/Converter/KX_ConvertProperties.h index 345af3bfa74..8f96cc21af6 100644 --- a/source/gameengine/Converter/KX_ConvertProperties.h +++ b/source/gameengine/Converter/KX_ConvertProperties.h @@ -38,5 +38,4 @@ void BL_ConvertProperties(struct Object* object, class SCA_IScene* scene, bool isInActiveLayer); -#endif //__KX_CONVERTPROPERTIES_H__ - +#endif /* __KX_CONVERTPROPERTIES_H__ */ diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index 9f155a6ebc3..538f9e2c833 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -33,17 +33,17 @@ #include -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable : 4786) -#endif //WIN32 +#ifdef _MSC_VER +# pragma warning (disable:4786) +#endif #include "wm_event_types.h" #include "KX_BlenderSceneConverter.h" #include "KX_ConvertSensors.h" /* This little block needed for linking to Blender... */ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#include "BLI_winstuff.h" +#ifdef _MSC_VER +# include "BLI_winstuff.h" #endif #include "DNA_object_types.h" @@ -118,8 +118,8 @@ void BL_ConvertSensors(struct Object* blenderobject, } gameobj->ReserveSensor(count); sens = (bSensor*)blenderobject->sensors.first; - while(sens) - { + + while (sens) { SCA_ISensor* gamesensor=NULL; /* All sensors have a pulse toggle, frequency, and invert field. */ /* These are extracted here, and set when the sensor is added to the */ @@ -183,7 +183,7 @@ void BL_ConvertSensors(struct Object* blenderobject, if (gameobj->GetPhysicsController()) - { + { gamesensor = new KX_TouchSensor(eventmgr, gameobj, bFindMaterial, @@ -209,7 +209,7 @@ void BL_ConvertSensors(struct Object* blenderobject, } bool bFindMaterial = true; if (gameobj->GetPhysicsController()) - { + { gamesensor = new KX_TouchSensor(eventmgr, gameobj, bFindMaterial, @@ -224,7 +224,7 @@ void BL_ConvertSensors(struct Object* blenderobject, KX_NetworkEventManager* eventmgr = (KX_NetworkEventManager*) logicmgr->FindEventManager(SCA_EventManager::NETWORK_EVENTMGR); if (eventmgr) { - bMessageSensor* msgSens = (bMessageSensor*) sens->data; + bMessageSensor* msgSens = (bMessageSensor*) sens->data; /* Get our NetworkScene */ NG_NetworkScene *NetworkScene = kxscene->GetNetworkScene(); @@ -247,7 +247,7 @@ void BL_ConvertSensors(struct Object* blenderobject, SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); if (eventmgr) { - STR_String nearpropertyname; + STR_String nearpropertyname; bNearSensor* blendernearsensor = (bNearSensor*)sens->data; if (blendernearsensor->name) { @@ -311,7 +311,7 @@ void BL_ConvertSensors(struct Object* blenderobject, } case SENS_MOUSE: { - int keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_NODEF; + int keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_NODEF; int trackfocus = 0; bMouseSensor *bmouse = (bMouseSensor *)sens->data; @@ -398,7 +398,7 @@ void BL_ConvertSensors(struct Object* blenderobject, /* Better do an explicit conversion here! (was implicit */ /* before...) */ - switch(blenderpropsensor->type) { + switch (blenderpropsensor->type) { case SENS_PROP_EQUAL: propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EQUAL; break; @@ -573,8 +573,7 @@ void BL_ConvertSensors(struct Object* blenderobject, int hatf =0; int prec =0; - switch(bjoy->type) - { + switch (bjoy->type) { case SENS_JOY_AXIS: axis = bjoy->axis; axisf = bjoy->axisf; @@ -633,13 +632,13 @@ void BL_ConvertSensors(struct Object* blenderobject, uniqueval->Release(); /* Conversion succeeded, so we can set the generic props here. */ - gamesensor->SetPulseMode(pos_pulsemode, - neg_pulsemode, - frequency); + gamesensor->SetPulseMode(pos_pulsemode, + neg_pulsemode, + frequency); gamesensor->SetInvert(invert); gamesensor->SetLevel(level); gamesensor->SetTap(tap); - gamesensor->SetName(sens->name); + gamesensor->SetName(sens->name); gameobj->AddSensor(gamesensor); diff --git a/source/gameengine/Converter/KX_ConvertSensors.h b/source/gameengine/Converter/KX_ConvertSensors.h index 0694815c77e..56248721a37 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.h +++ b/source/gameengine/Converter/KX_ConvertSensors.h @@ -42,5 +42,4 @@ void BL_ConvertSensors(struct Object* blenderobject, class RAS_ICanvas* canvas, class KX_BlenderSceneConverter* converter); -#endif //__KX_CONVERTSENSORS_H__ - +#endif /* __KX_CONVERTSENSORS_H__ */ diff --git a/source/gameengine/Converter/KX_IpoConvert.cpp b/source/gameengine/Converter/KX_IpoConvert.cpp index 309959b4324..a81d52f6698 100644 --- a/source/gameengine/Converter/KX_IpoConvert.cpp +++ b/source/gameengine/Converter/KX_IpoConvert.cpp @@ -29,10 +29,9 @@ * \ingroup bgeconv */ - -#if defined(WIN32) && !defined(FREE_WINDOWS) -// don't show stl-warnings -#pragma warning (disable:4786) +#ifdef _MSC_VER + /* don't show stl-warnings */ +# pragma warning (disable:4786) #endif #include "BKE_material.h" /* give_current_material */ @@ -76,12 +75,12 @@ static BL_InterpolatorList *GetAdtList(struct bAction *for_act, KX_BlenderSceneC { BL_InterpolatorList *adtList= converter->FindInterpolatorList(for_act); - if (!adtList) { + if (!adtList) { adtList = new BL_InterpolatorList(for_act); converter->RegisterInterpolatorList(adtList, for_act); } - return adtList; + return adtList; } SG_Controller *BL_CreateIPO(struct bAction *action, KX_GameObject* gameobj, KX_BlenderSceneConverter *converter) @@ -97,7 +96,7 @@ SG_Controller *BL_CreateIPO(struct bAction *action, KX_GameObject* gameobj, KX_B const char *rotmode, *drotmode; - switch(blenderobject->rotmode) { + switch (blenderobject->rotmode) { case ROT_MODE_AXISANGLE: rotmode = "rotation_axis_angle"; drotmode = "delta_rotation_axis_angle"; @@ -441,7 +440,7 @@ static void ConvertMaterialIpos( } interpolator= new KX_ScalarInterpolator(&ipocontr->m_ref, sinterp); ipocontr->AddInterpolator(interpolator); - } + } if ((sinterp = adtList->GetScalarInterpolator("emit", 0))) { if (!ipocontr) { @@ -452,7 +451,7 @@ static void ConvertMaterialIpos( interpolator= new KX_ScalarInterpolator(&ipocontr->m_emit, sinterp); ipocontr->AddInterpolator(interpolator); } - } + } } void BL_ConvertMaterialIpos( diff --git a/source/gameengine/Converter/KX_IpoConvert.h b/source/gameengine/Converter/KX_IpoConvert.h index 7bb2df978f6..861a2ba66f2 100644 --- a/source/gameengine/Converter/KX_IpoConvert.h +++ b/source/gameengine/Converter/KX_IpoConvert.h @@ -66,5 +66,4 @@ void BL_ConvertMaterialIpos(struct Object* blenderobject, class KX_BlenderSceneConverter *converter); -#endif //__KX_IPOCONVERT_H__ - +#endif /* __KX_IPOCONVERT_H__ */ diff --git a/source/gameengine/Converter/KX_SoftBodyDeformer.cpp b/source/gameengine/Converter/KX_SoftBodyDeformer.cpp index e3c12c2b966..72d0c8733f2 100644 --- a/source/gameengine/Converter/KX_SoftBodyDeformer.cpp +++ b/source/gameengine/Converter/KX_SoftBodyDeformer.cpp @@ -30,8 +30,8 @@ */ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable : 4786) +#ifdef _MSC_VER +# pragma warning (disable:4786) #endif //WIN32 #include "MT_assert.h" diff --git a/source/gameengine/Converter/KX_SoftBodyDeformer.h b/source/gameengine/Converter/KX_SoftBodyDeformer.h index d692d45eb18..d7bc088e1c0 100644 --- a/source/gameengine/Converter/KX_SoftBodyDeformer.h +++ b/source/gameengine/Converter/KX_SoftBodyDeformer.h @@ -32,9 +32,9 @@ #ifndef __KX_SOFTBODYDEFORMER_H__ #define __KX_SOFTBODYDEFORMER_H__ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning -#endif //WIN32 +#ifdef _MSC_VER +# pragma warning (disable:4786) /* get rid of stupid stl-visual compiler debug warning */ +#endif #include "RAS_Deformer.h" #include "BL_DeformableGameObject.h" diff --git a/source/gameengine/Expressions/BoolValue.cpp b/source/gameengine/Expressions/BoolValue.cpp index 40997a25be1..ee913877c96 100644 --- a/source/gameengine/Expressions/BoolValue.cpp +++ b/source/gameengine/Expressions/BoolValue.cpp @@ -104,39 +104,37 @@ this object { CValue *ret; - switch(dtype) - { - case VALUE_EMPTY_TYPE: - case VALUE_BOOL_TYPE: + switch (dtype) { + case VALUE_EMPTY_TYPE: + case VALUE_BOOL_TYPE: { - switch(op) - { - case VALUE_AND_OPERATOR: + switch (op) { + case VALUE_AND_OPERATOR: { ret = new CBoolValue (((CBoolValue *) val)->GetBool() && m_bool); break; } - case VALUE_OR_OPERATOR: + case VALUE_OR_OPERATOR: { ret = new CBoolValue (((CBoolValue *) val)->GetBool() || m_bool); break; } - case VALUE_EQL_OPERATOR: + case VALUE_EQL_OPERATOR: { ret = new CBoolValue (((CBoolValue *) val)->GetBool() == m_bool); break; } - case VALUE_NEQ_OPERATOR: + case VALUE_NEQ_OPERATOR: { ret = new CBoolValue (((CBoolValue *) val)->GetBool() != m_bool); break; } - case VALUE_NOT_OPERATOR: + case VALUE_NOT_OPERATOR: { return new CBoolValue (!m_bool); break; } - default: + default: { ret = new CErrorValue(val->GetText() + op2str(op) + "[operator not allowed on booleans]"); @@ -145,16 +143,15 @@ this object } break; } - case VALUE_STRING_TYPE: + case VALUE_STRING_TYPE: { - switch(op) - { - case VALUE_ADD_OPERATOR: + switch (op) { + case VALUE_ADD_OPERATOR: { ret = new CStringValue(val->GetText() + GetText(),""); break; } - default: + default: { ret = new CErrorValue(val->GetText() + op2str(op) + "[Only + allowed on boolean and string]"); break; @@ -162,8 +159,8 @@ this object } break; } - default: - ret = new CErrorValue("[type mismatch]" + op2str(op) + GetText()); + default: + ret = new CErrorValue("[type mismatch]" + op2str(op) + GetText()); } return ret; @@ -205,7 +202,7 @@ CValue* CBoolValue::GetReplica() } #ifdef WITH_PYTHON -PyObject* CBoolValue::ConvertValueToPython() +PyObject *CBoolValue::ConvertValueToPython() { return PyBool_FromLong(m_bool != 0); } diff --git a/source/gameengine/Expressions/BoolValue.h b/source/gameengine/Expressions/BoolValue.h index 09e931ea661..b88c839a58e 100644 --- a/source/gameengine/Expressions/BoolValue.h +++ b/source/gameengine/Expressions/BoolValue.h @@ -29,7 +29,7 @@ class CBoolValue : public CPropValue { - //PLUGIN_DECLARE_SERIAL(CBoolValue,CValue) + //PLUGIN_DECLARE_SERIAL(CBoolValue,CValue) public: static const STR_String sTrueString; @@ -61,5 +61,4 @@ private: #endif }; -#endif // !defined __BOOLVALUE_H__ - +#endif /* __BOOLVALUE_H__ */ diff --git a/source/gameengine/Expressions/ConstExpr.h b/source/gameengine/Expressions/ConstExpr.h index 86d411cef26..768f2bbd10e 100644 --- a/source/gameengine/Expressions/ConstExpr.h +++ b/source/gameengine/Expressions/ConstExpr.h @@ -51,5 +51,4 @@ private: #endif }; -#endif // !defined(AFX_CONSTEXPR_H__061ECFC3_BE87_11D1_A51C_00A02472FC58__INCLUDED_) - +#endif /* __CONSTEXPR_H__ */ diff --git a/source/gameengine/Expressions/EXP_C-Api.cpp b/source/gameengine/Expressions/EXP_C-Api.cpp index 763d115a840..2822fd8f6de 100644 --- a/source/gameengine/Expressions/EXP_C-Api.cpp +++ b/source/gameengine/Expressions/EXP_C-Api.cpp @@ -102,8 +102,8 @@ int EXP_IsValid(EXP_ValueHandle inval) /* assign property 'propval' to 'destinationval' */ void EXP_SetProperty(EXP_ValueHandle destinationval, - const char* propname, - EXP_ValueHandle propval) + const char *propname, + EXP_ValueHandle propval) { ((CValue*) destinationval)->SetProperty(propname,(CValue*)propval); } diff --git a/source/gameengine/Expressions/EXP_C-Api.h b/source/gameengine/Expressions/EXP_C-Api.h index 6be1e57481c..d73b0a209d4 100644 --- a/source/gameengine/Expressions/EXP_C-Api.h +++ b/source/gameengine/Expressions/EXP_C-Api.h @@ -53,7 +53,7 @@ extern void EXP_ReleaseValue(EXP_ValueHandle); extern int EXP_IsValid(EXP_ValueHandle); /* assign property 'propval' to 'destinationval' */ -extern void EXP_SetProperty(EXP_ValueHandle propval,EXP_ValueHandle destinationval); +extern void EXP_SetProperty(EXP_ValueHandle destinationval, const char *propname, EXP_ValueHandle propval); /* returns NULL if property doesn't exist */ extern EXP_ValueHandle EXP_GetProperty(EXP_ValueHandle inval,const char* propname); @@ -64,5 +64,4 @@ const char* EXP_GetText(EXP_ValueHandle); } #endif -#endif //__EXP_C_API_H__ - +#endif /* __EXP_C_API_H__ */ diff --git a/source/gameengine/Expressions/EmptyValue.h b/source/gameengine/Expressions/EmptyValue.h index 54920359f3f..8eccb97e0f5 100644 --- a/source/gameengine/Expressions/EmptyValue.h +++ b/source/gameengine/Expressions/EmptyValue.h @@ -45,5 +45,4 @@ public: #endif }; -#endif // !defined __EMPTYVALUE_H__ - +#endif /* __EMPTYVALUE_H__ */ diff --git a/source/gameengine/Expressions/ErrorValue.h b/source/gameengine/Expressions/ErrorValue.h index 12bc7c7ffcb..0095528254e 100644 --- a/source/gameengine/Expressions/ErrorValue.h +++ b/source/gameengine/Expressions/ErrorValue.h @@ -43,5 +43,4 @@ private: #endif }; -#endif // !defined __ERRORVALUE_H__ - +#endif /* __ERRORVALUE_H__ */ diff --git a/source/gameengine/Expressions/Expression.h b/source/gameengine/Expressions/Expression.h index 5f5db505331..d1b7eda43f0 100644 --- a/source/gameengine/Expressions/Expression.h +++ b/source/gameengine/Expressions/Expression.h @@ -146,5 +146,4 @@ protected: #endif }; -#endif // !defined __EXPRESSION_H__ - +#endif /* __EXPRESSION_H__ */ diff --git a/source/gameengine/Expressions/FloatValue.cpp b/source/gameengine/Expressions/FloatValue.cpp index 403338573e2..b7d7f528155 100644 --- a/source/gameengine/Expressions/FloatValue.cpp +++ b/source/gameengine/Expressions/FloatValue.cpp @@ -120,138 +120,134 @@ ret: a new object containing the result of applying operator op to val and { CValue *ret; - switch(dtype) - { - case VALUE_INT_TYPE: + switch (dtype) { + case VALUE_INT_TYPE: { - switch (op) - { - case VALUE_MOD_OPERATOR: - ret = new CFloatValue(fmod(((CIntValue *) val)->GetInt(), m_float)); - break; - case VALUE_ADD_OPERATOR: - ret = new CFloatValue(((CIntValue *) val)->GetInt() + m_float); - break; - case VALUE_SUB_OPERATOR: - ret = new CFloatValue(((CIntValue *) val)->GetInt() - m_float); - break; - case VALUE_MUL_OPERATOR: - ret = new CFloatValue(((CIntValue *) val)->GetInt() * m_float); - break; - case VALUE_DIV_OPERATOR: - if (m_float == 0) - ret = new CErrorValue("Division by zero"); - else - ret = new CFloatValue (((CIntValue *) val)->GetInt() / m_float); - break; - case VALUE_EQL_OPERATOR: - ret = new CBoolValue(((CIntValue *) val)->GetInt() == m_float); - break; - case VALUE_NEQ_OPERATOR: - ret = new CBoolValue(((CIntValue *) val)->GetInt() != m_float); - break; - case VALUE_GRE_OPERATOR: - ret = new CBoolValue(((CIntValue *) val)->GetInt() > m_float); - break; - case VALUE_LES_OPERATOR: - ret = new CBoolValue(((CIntValue *) val)->GetInt() < m_float); - break; - case VALUE_GEQ_OPERATOR: - ret = new CBoolValue(((CIntValue *) val)->GetInt() >= m_float); - break; - case VALUE_LEQ_OPERATOR: - ret = new CBoolValue(((CIntValue *) val)->GetInt() <= m_float); - break; - default: - ret = new CErrorValue("illegal operator. please send a bug report."); - break; + switch (op) { + case VALUE_MOD_OPERATOR: + ret = new CFloatValue(fmod(((CIntValue *) val)->GetInt(), m_float)); + break; + case VALUE_ADD_OPERATOR: + ret = new CFloatValue(((CIntValue *) val)->GetInt() + m_float); + break; + case VALUE_SUB_OPERATOR: + ret = new CFloatValue(((CIntValue *) val)->GetInt() - m_float); + break; + case VALUE_MUL_OPERATOR: + ret = new CFloatValue(((CIntValue *) val)->GetInt() * m_float); + break; + case VALUE_DIV_OPERATOR: + if (m_float == 0) + ret = new CErrorValue("Division by zero"); + else + ret = new CFloatValue (((CIntValue *) val)->GetInt() / m_float); + break; + case VALUE_EQL_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() == m_float); + break; + case VALUE_NEQ_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() != m_float); + break; + case VALUE_GRE_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() > m_float); + break; + case VALUE_LES_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() < m_float); + break; + case VALUE_GEQ_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() >= m_float); + break; + case VALUE_LEQ_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() <= m_float); + break; + default: + ret = new CErrorValue("illegal operator. please send a bug report."); + break; } break; } - case VALUE_EMPTY_TYPE: - case VALUE_FLOAT_TYPE: + case VALUE_EMPTY_TYPE: + case VALUE_FLOAT_TYPE: { - switch (op) - { - case VALUE_MOD_OPERATOR: - ret = new CFloatValue(fmod(((CFloatValue *) val)->GetFloat(), m_float)); - break; - case VALUE_ADD_OPERATOR: - ret = new CFloatValue(((CFloatValue *) val)->GetFloat() + m_float); - break; - case VALUE_SUB_OPERATOR: - ret = new CFloatValue(((CFloatValue *) val)->GetFloat() - m_float); - break; - case VALUE_MUL_OPERATOR: - ret = new CFloatValue(((CFloatValue *) val)->GetFloat() * m_float); - break; - case VALUE_DIV_OPERATOR: - if (m_float == 0) - ret = new CErrorValue("Division by zero"); - else - ret = new CFloatValue (((CFloatValue *) val)->GetFloat() / m_float); - break; - case VALUE_EQL_OPERATOR: - ret = new CBoolValue(((CFloatValue *) val)->GetFloat() == m_float); - break; - case VALUE_NEQ_OPERATOR: - ret = new CBoolValue(((CFloatValue *) val)->GetFloat() != m_float); - break; - case VALUE_GRE_OPERATOR: - ret = new CBoolValue(((CFloatValue *) val)->GetFloat() > m_float); - break; - case VALUE_LES_OPERATOR: - ret = new CBoolValue(((CFloatValue *) val)->GetFloat() < m_float); - break; - case VALUE_GEQ_OPERATOR: - ret = new CBoolValue(((CFloatValue *) val)->GetFloat() >= m_float); - break; - case VALUE_LEQ_OPERATOR: - ret = new CBoolValue(((CFloatValue *) val)->GetFloat() <= m_float); - break; - case VALUE_NEG_OPERATOR: - ret = new CFloatValue (-m_float); - break; - case VALUE_POS_OPERATOR: - ret = new CFloatValue (m_float); - break; - - default: - ret = new CErrorValue("illegal operator. please send a bug report."); - break; + switch (op) { + case VALUE_MOD_OPERATOR: + ret = new CFloatValue(fmod(((CFloatValue *) val)->GetFloat(), m_float)); + break; + case VALUE_ADD_OPERATOR: + ret = new CFloatValue(((CFloatValue *) val)->GetFloat() + m_float); + break; + case VALUE_SUB_OPERATOR: + ret = new CFloatValue(((CFloatValue *) val)->GetFloat() - m_float); + break; + case VALUE_MUL_OPERATOR: + ret = new CFloatValue(((CFloatValue *) val)->GetFloat() * m_float); + break; + case VALUE_DIV_OPERATOR: + if (m_float == 0) + ret = new CErrorValue("Division by zero"); + else + ret = new CFloatValue (((CFloatValue *) val)->GetFloat() / m_float); + break; + case VALUE_EQL_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() == m_float); + break; + case VALUE_NEQ_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() != m_float); + break; + case VALUE_GRE_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() > m_float); + break; + case VALUE_LES_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() < m_float); + break; + case VALUE_GEQ_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() >= m_float); + break; + case VALUE_LEQ_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() <= m_float); + break; + case VALUE_NEG_OPERATOR: + ret = new CFloatValue (-m_float); + break; + case VALUE_POS_OPERATOR: + ret = new CFloatValue (m_float); + break; + + default: + ret = new CErrorValue("illegal operator. please send a bug report."); + break; } break; } - case VALUE_STRING_TYPE: + case VALUE_STRING_TYPE: { - switch(op) - { - case VALUE_ADD_OPERATOR: - ret = new CStringValue(val->GetText() + GetText(),""); - break; - case VALUE_EQL_OPERATOR: - case VALUE_NEQ_OPERATOR: - case VALUE_GRE_OPERATOR: - case VALUE_LES_OPERATOR: - case VALUE_GEQ_OPERATOR: - case VALUE_LEQ_OPERATOR: - ret = new CErrorValue("[Cannot compare string with float]" + op2str(op) + GetText()); - break; - default: - ret = new CErrorValue("[operator not allowed on strings]" + op2str(op) + GetText()); - break; + switch (op) { + case VALUE_ADD_OPERATOR: + ret = new CStringValue(val->GetText() + GetText(),""); + break; + case VALUE_EQL_OPERATOR: + case VALUE_NEQ_OPERATOR: + case VALUE_GRE_OPERATOR: + case VALUE_LES_OPERATOR: + case VALUE_GEQ_OPERATOR: + case VALUE_LEQ_OPERATOR: + ret = new CErrorValue("[Cannot compare string with float]" + op2str(op) + GetText()); + break; + default: + ret = new CErrorValue("[operator not allowed on strings]" + op2str(op) + GetText()); + break; } break; } - case VALUE_BOOL_TYPE: - ret = new CErrorValue("[operator not valid on boolean and float]" + op2str(op) + GetText()); - break; - case VALUE_ERROR_TYPE: - ret = new CErrorValue(val->GetText() + op2str(op) + GetText()); - break; - default: - ret = new CErrorValue("illegal type. contact your dealer (if any)"); - break; + case VALUE_BOOL_TYPE: + ret = new CErrorValue("[operator not valid on boolean and float]" + op2str(op) + GetText()); + break; + case VALUE_ERROR_TYPE: + ret = new CErrorValue(val->GetText() + op2str(op) + GetText()); + break; + default: + ret = new CErrorValue("illegal type. contact your dealer (if any)"); + break; } return ret; } @@ -314,7 +310,7 @@ CValue* CFloatValue::GetReplica() #ifdef WITH_PYTHON -PyObject* CFloatValue::ConvertValueToPython() +PyObject *CFloatValue::ConvertValueToPython() { return PyFloat_FromDouble(m_float); } diff --git a/source/gameengine/Expressions/FloatValue.h b/source/gameengine/Expressions/FloatValue.h index 59311e5d373..bc6a2d052d4 100644 --- a/source/gameengine/Expressions/FloatValue.h +++ b/source/gameengine/Expressions/FloatValue.h @@ -54,5 +54,4 @@ protected: #endif }; -#endif // !defined __FLOATVALUE_H__ - +#endif /* __FLOATVALUE_H__ */ diff --git a/source/gameengine/Expressions/IdentifierExpr.h b/source/gameengine/Expressions/IdentifierExpr.h index 58e75c4b02e..26eb3691378 100644 --- a/source/gameengine/Expressions/IdentifierExpr.h +++ b/source/gameengine/Expressions/IdentifierExpr.h @@ -56,5 +56,4 @@ public: #endif }; -#endif //__IDENTIFIEREXPR_H__ - +#endif /* __IDENTIFIEREXPR_H__ */ diff --git a/source/gameengine/Expressions/IfExpr.h b/source/gameengine/Expressions/IfExpr.h index f8ed81168d0..80e35471d82 100644 --- a/source/gameengine/Expressions/IfExpr.h +++ b/source/gameengine/Expressions/IfExpr.h @@ -16,12 +16,8 @@ * \ingroup expressions */ -#if !defined(AFX_IFEXPR_H__1F691841_C5C7_11D1_A863_0000B4542BD8__INCLUDED_) -#define AFX_IFEXPR_H__1F691841_C5C7_11D1_A863_0000B4542BD8__INCLUDED_ - -#if defined(_MSC_VER) && _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 +#ifndef __IFEXPR_H__ +#define __IFEXPR_H__ #include "Expression.h" @@ -55,5 +51,4 @@ public: #endif }; -#endif // !defined(AFX_IFEXPR_H__1F691841_C5C7_11D1_A863_0000B4542BD8__INCLUDED_) - +#endif /* __IFEXPR_H__ */ diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/InputParser.cpp index 58837235d30..0a5af4a18ea 100644 --- a/source/gameengine/Expressions/InputParser.cpp +++ b/source/gameengine/Expressions/InputParser.cpp @@ -187,11 +187,10 @@ void CParser::NextSym() // sets the global variable cellcoord to the kind of operator errmsg = NULL; - while(ch == ' ' || ch == 0x9) + while (ch == ' ' || ch == 0x9) NextCh(); - switch(ch) - { + switch (ch) { case '(': sym = lbracksym; NextCh(); break; @@ -359,7 +358,7 @@ STR_String CParser::Symbol2Str(int s) { // returns a string representation of of symbol s, // for use in Term when generating an error - switch(s) { + switch (s) { case errorsym: return "error"; case lbracksym: return "("; case rbracksym: return ")"; @@ -394,7 +393,7 @@ int CParser::Priority(int optorkind) { // returns the priority of an operator // higher number means higher priority - switch(optorkind) { + switch (optorkind) { case OPor: return 1; case OPand: return 2; case OPgreater: @@ -426,102 +425,103 @@ CExpression *CParser::Ex(int i) opkind2 = opkind; NextSym(); e2 = Ex(i + 1); - switch(opkind2) { - case OPmodulus: e1 = new COperator2Expr(VALUE_MOD_OPERATOR,e1, e2); break; - case OPplus: e1 = new COperator2Expr(VALUE_ADD_OPERATOR,e1, e2); break; - case OPminus: e1 = new COperator2Expr(VALUE_SUB_OPERATOR,e1, e2); break; - case OPtimes: e1 = new COperator2Expr(VALUE_MUL_OPERATOR,e1, e2); break; - case OPdivide: e1 = new COperator2Expr(VALUE_DIV_OPERATOR,e1, e2); break; - case OPand: e1 = new COperator2Expr(VALUE_AND_OPERATOR,e1, e2); break; - case OPor: e1 = new COperator2Expr(VALUE_OR_OPERATOR,e1, e2); break; - case OPequal: e1 = new COperator2Expr(VALUE_EQL_OPERATOR,e1, e2); break; - case OPunequal: e1 = new COperator2Expr(VALUE_NEQ_OPERATOR,e1, e2); break; - case OPgreater: e1 = new COperator2Expr(VALUE_GRE_OPERATOR,e1, e2); break; - case OPless: e1 = new COperator2Expr(VALUE_LES_OPERATOR,e1, e2); break; - case OPgreaterequal: e1 = new COperator2Expr(VALUE_GEQ_OPERATOR,e1, e2); break; - case OPlessequal: e1 = new COperator2Expr(VALUE_LEQ_OPERATOR,e1, e2); break; - default: MT_assert(false); break; // should not happen + switch (opkind2) { + case OPmodulus: e1 = new COperator2Expr(VALUE_MOD_OPERATOR,e1, e2); break; + case OPplus: e1 = new COperator2Expr(VALUE_ADD_OPERATOR,e1, e2); break; + case OPminus: e1 = new COperator2Expr(VALUE_SUB_OPERATOR,e1, e2); break; + case OPtimes: e1 = new COperator2Expr(VALUE_MUL_OPERATOR,e1, e2); break; + case OPdivide: e1 = new COperator2Expr(VALUE_DIV_OPERATOR,e1, e2); break; + case OPand: e1 = new COperator2Expr(VALUE_AND_OPERATOR,e1, e2); break; + case OPor: e1 = new COperator2Expr(VALUE_OR_OPERATOR,e1, e2); break; + case OPequal: e1 = new COperator2Expr(VALUE_EQL_OPERATOR,e1, e2); break; + case OPunequal: e1 = new COperator2Expr(VALUE_NEQ_OPERATOR,e1, e2); break; + case OPgreater: e1 = new COperator2Expr(VALUE_GRE_OPERATOR,e1, e2); break; + case OPless: e1 = new COperator2Expr(VALUE_LES_OPERATOR,e1, e2); break; + case OPgreaterequal: e1 = new COperator2Expr(VALUE_GEQ_OPERATOR,e1, e2); break; + case OPlessequal: e1 = new COperator2Expr(VALUE_LEQ_OPERATOR,e1, e2); break; + default: MT_assert(false); break; // should not happen } } } else if (i == NUM_PRIORITY) { - if ((sym == opsym) - && ( (opkind == OPminus) || (opkind == OPnot) || (opkind == OPplus) ) - ) + if ((sym == opsym) + && ( (opkind == OPminus) || (opkind == OPnot) || (opkind == OPplus) ) + ) { NextSym(); - switch(opkind) { - /* +1 is also a valid number! */ - case OPplus: e1 = new COperator1Expr(VALUE_POS_OPERATOR, Ex(NUM_PRIORITY)); break; - case OPminus: e1 = new COperator1Expr(VALUE_NEG_OPERATOR, Ex(NUM_PRIORITY)); break; - case OPnot: e1 = new COperator1Expr(VALUE_NOT_OPERATOR, Ex(NUM_PRIORITY)); break; - default: { - // should not happen - e1 = Error("operator +, - or ! expected"); - } + switch (opkind) { + /* +1 is also a valid number! */ + case OPplus: e1 = new COperator1Expr(VALUE_POS_OPERATOR, Ex(NUM_PRIORITY)); break; + case OPminus: e1 = new COperator1Expr(VALUE_NEG_OPERATOR, Ex(NUM_PRIORITY)); break; + case OPnot: e1 = new COperator1Expr(VALUE_NOT_OPERATOR, Ex(NUM_PRIORITY)); break; + default: + { + // should not happen + e1 = Error("operator +, - or ! expected"); + } } } else { - switch(sym) { - case constsym: { - switch(constkind) { - case booltype: - e1 = new CConstExpr(new CBoolValue(boolvalue)); - break; - case inttype: - { - cInt temp; - temp = strtoll(const_as_string, NULL, 10); /* atoi is for int only */ - e1 = new CConstExpr(new CIntValue(temp)); - break; + switch (sym) { + case constsym: { + switch (constkind) { + case booltype: + e1 = new CConstExpr(new CBoolValue(boolvalue)); + break; + case inttype: + { + cInt temp; + temp = strtoll(const_as_string, NULL, 10); /* atoi is for int only */ + e1 = new CConstExpr(new CIntValue(temp)); + break; + } + case floattype: + { + double temp; + temp = atof(const_as_string); + e1 = new CConstExpr(new CFloatValue(temp)); + break; + } + case stringtype: + e1 = new CConstExpr(new CStringValue(const_as_string,"")); + break; + default : + MT_assert(false); + break; } - case floattype: - { - double temp; - temp = atof(const_as_string); - e1 = new CConstExpr(new CFloatValue(temp)); - break; - } - case stringtype: - e1 = new CConstExpr(new CStringValue(const_as_string,"")); - break; - default : - MT_assert(false); - break; - } - NextSym(); - break; - } - case lbracksym: - NextSym(); - e1 = Ex(1); - Term(rbracksym); - break; - case ifsym: - { - CExpression *e3; - NextSym(); - Term(lbracksym); - e1 = Ex(1); - Term(commasym); - e2 = Ex(1); - if (sym == commasym) { NextSym(); - e3 = Ex(1); - } else { - e3 = new CConstExpr(new CEmptyValue()); + break; } - Term(rbracksym); - e1 = new CIfExpr(e1, e2, e3); - break; - } - case idsym: + case lbracksym: + NextSym(); + e1 = Ex(1); + Term(rbracksym); + break; + case ifsym: + { + CExpression *e3; + NextSym(); + Term(lbracksym); + e1 = Ex(1); + Term(commasym); + e2 = Ex(1); + if (sym == commasym) { + NextSym(); + e3 = Ex(1); + } else { + e3 = new CConstExpr(new CEmptyValue()); + } + Term(rbracksym); + e1 = new CIfExpr(e1, e2, e3); + break; + } + case idsym: { e1 = new CIdentifierExpr(const_as_string,m_identifierContext); NextSym(); break; } - case errorsym: + case errorsym: { MT_assert(!e1); STR_String errtext="[no info]"; @@ -530,7 +530,7 @@ CExpression *CParser::Ex(int i) CValue* errmsgval = errmsg->Calculate(); errtext=errmsgval->GetText(); errmsgval->Release(); - + //e1 = Error(errmsg->Calculate()->GetText());//new CConstExpr(errmsg->Calculate()); if ( !(errmsg->Release()) ) @@ -543,13 +543,13 @@ CExpression *CParser::Ex(int i) } e1 = Error(errtext); - break; + break; } - default: - NextSym(); - //return Error("Expression expected"); - MT_assert(!e1); - e1 = Error("Expression expected"); + default: + NextSym(); + //return Error("Expression expected"); + MT_assert(!e1); + e1 = Error("Expression expected"); } } } @@ -573,7 +573,7 @@ CExpression* CParser::ProcessText text = intext; - chcount = 0; + chcount = 0; if (text.Length() == 0) { return NULL; } diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/IntValue.cpp index 2d427440620..cb6bc556bab 100644 --- a/source/gameengine/Expressions/IntValue.cpp +++ b/source/gameengine/Expressions/IntValue.cpp @@ -108,165 +108,160 @@ object and val } } - - -CValue* CIntValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) /* -pre: the type of val is dtype -ret: a new object containing the result of applying operator op to val and -this object -*/ + * pre: the type of val is dtype + * ret: a new object containing the result of applying operator op to val and + * this object + */ +CValue* CIntValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) { CValue *ret; - switch(dtype) { - case VALUE_EMPTY_TYPE: - case VALUE_INT_TYPE: + switch (dtype) { + case VALUE_EMPTY_TYPE: + case VALUE_INT_TYPE: { switch (op) { - case VALUE_MOD_OPERATOR: - ret = new CIntValue (((CIntValue *) val)->GetInt() % m_int); - break; - case VALUE_ADD_OPERATOR: - ret = new CIntValue (((CIntValue *) val)->GetInt() + m_int); - break; - case VALUE_SUB_OPERATOR: - ret = new CIntValue (((CIntValue *) val)->GetInt() - m_int); - break; - case VALUE_MUL_OPERATOR: - ret = new CIntValue (((CIntValue *) val)->GetInt() * m_int); - break; - case VALUE_DIV_OPERATOR: - if (m_int == 0) - { - if (val->GetNumber() == 0) - { - ret = new CErrorValue("Not a Number"); - } else - { - ret = new CErrorValue("Division by zero"); + case VALUE_MOD_OPERATOR: + ret = new CIntValue (((CIntValue *) val)->GetInt() % m_int); + break; + case VALUE_ADD_OPERATOR: + ret = new CIntValue (((CIntValue *) val)->GetInt() + m_int); + break; + case VALUE_SUB_OPERATOR: + ret = new CIntValue (((CIntValue *) val)->GetInt() - m_int); + break; + case VALUE_MUL_OPERATOR: + ret = new CIntValue (((CIntValue *) val)->GetInt() * m_int); + break; + case VALUE_DIV_OPERATOR: + if (m_int == 0) { + if (val->GetNumber() == 0) { + ret = new CErrorValue("Not a Number"); + } + else { + ret = new CErrorValue("Division by zero"); + } } - } - else - ret = new CIntValue (((CIntValue *) val)->GetInt() / m_int); - break; - case VALUE_EQL_OPERATOR: - ret = new CBoolValue(((CIntValue *) val)->GetInt() == m_int); - break; - case VALUE_NEQ_OPERATOR: - ret = new CBoolValue(((CIntValue *) val)->GetInt() != m_int); - break; - case VALUE_GRE_OPERATOR: - ret = new CBoolValue(((CIntValue *) val)->GetInt() > m_int); - break; - case VALUE_LES_OPERATOR: - ret = new CBoolValue(((CIntValue *) val)->GetInt() < m_int); - break; - case VALUE_GEQ_OPERATOR: - ret = new CBoolValue(((CIntValue *) val)->GetInt() >= m_int); - break; - case VALUE_LEQ_OPERATOR: - ret = new CBoolValue(((CIntValue *) val)->GetInt() <= m_int); - break; - case VALUE_NEG_OPERATOR: - ret = new CIntValue (-m_int); - break; - case VALUE_POS_OPERATOR: - ret = new CIntValue (m_int); - break; - default: - ret = new CErrorValue("illegal operator. please send a bug report."); - break; + else + ret = new CIntValue (((CIntValue *) val)->GetInt() / m_int); + break; + case VALUE_EQL_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() == m_int); + break; + case VALUE_NEQ_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() != m_int); + break; + case VALUE_GRE_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() > m_int); + break; + case VALUE_LES_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() < m_int); + break; + case VALUE_GEQ_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() >= m_int); + break; + case VALUE_LEQ_OPERATOR: + ret = new CBoolValue(((CIntValue *) val)->GetInt() <= m_int); + break; + case VALUE_NEG_OPERATOR: + ret = new CIntValue (-m_int); + break; + case VALUE_POS_OPERATOR: + ret = new CIntValue (m_int); + break; + default: + ret = new CErrorValue("illegal operator. please send a bug report."); + break; } break; } - case VALUE_FLOAT_TYPE: + case VALUE_FLOAT_TYPE: { switch (op) { - case VALUE_MOD_OPERATOR: - ret = new CFloatValue(fmod(((CFloatValue *) val)->GetFloat(), m_int)); - break; - case VALUE_ADD_OPERATOR: - ret = new CFloatValue (((CFloatValue *) val)->GetFloat() + m_int); - break; - case VALUE_SUB_OPERATOR: - ret = new CFloatValue (((CFloatValue *) val)->GetFloat() - m_int); - break; - case VALUE_MUL_OPERATOR: - ret = new CFloatValue (((CFloatValue *) val)->GetFloat() * m_int); - break; - case VALUE_DIV_OPERATOR: - if (m_int == 0) - ret = new CErrorValue("Division by zero"); - else - ret = new CFloatValue (((CFloatValue *) val)->GetFloat() / m_int); - break; - case VALUE_EQL_OPERATOR: - ret = new CBoolValue(((CFloatValue *) val)->GetFloat() == m_int); - break; - case VALUE_NEQ_OPERATOR: - ret = new CBoolValue(((CFloatValue *) val)->GetFloat() != m_int); - break; - case VALUE_GRE_OPERATOR: - ret = new CBoolValue(((CFloatValue *) val)->GetFloat() > m_int); - break; - case VALUE_LES_OPERATOR: - ret = new CBoolValue(((CFloatValue *) val)->GetFloat() < m_int); - break; - case VALUE_GEQ_OPERATOR: - ret = new CBoolValue(((CFloatValue *) val)->GetFloat() >= m_int); - break; - case VALUE_LEQ_OPERATOR: - ret = new CBoolValue(((CFloatValue *) val)->GetFloat() <= m_int); - break; - default: - ret = new CErrorValue("illegal operator. please send a bug report."); - break; + case VALUE_MOD_OPERATOR: + ret = new CFloatValue(fmod(((CFloatValue *) val)->GetFloat(), m_int)); + break; + case VALUE_ADD_OPERATOR: + ret = new CFloatValue (((CFloatValue *) val)->GetFloat() + m_int); + break; + case VALUE_SUB_OPERATOR: + ret = new CFloatValue (((CFloatValue *) val)->GetFloat() - m_int); + break; + case VALUE_MUL_OPERATOR: + ret = new CFloatValue (((CFloatValue *) val)->GetFloat() * m_int); + break; + case VALUE_DIV_OPERATOR: + if (m_int == 0) + ret = new CErrorValue("Division by zero"); + else + ret = new CFloatValue (((CFloatValue *) val)->GetFloat() / m_int); + break; + case VALUE_EQL_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() == m_int); + break; + case VALUE_NEQ_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() != m_int); + break; + case VALUE_GRE_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() > m_int); + break; + case VALUE_LES_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() < m_int); + break; + case VALUE_GEQ_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() >= m_int); + break; + case VALUE_LEQ_OPERATOR: + ret = new CBoolValue(((CFloatValue *) val)->GetFloat() <= m_int); + break; + default: + ret = new CErrorValue("illegal operator. please send a bug report."); + break; } break; } - case VALUE_STRING_TYPE: + case VALUE_STRING_TYPE: { - switch(op) { - case VALUE_ADD_OPERATOR: - ret = new CStringValue(val->GetText() + GetText(),""); - break; - case VALUE_EQL_OPERATOR: - case VALUE_NEQ_OPERATOR: - case VALUE_GRE_OPERATOR: - case VALUE_LES_OPERATOR: - case VALUE_GEQ_OPERATOR: - case VALUE_LEQ_OPERATOR: - ret = new CErrorValue("[Cannot compare string with integer]" + op2str(op) + GetText()); - break; - default: - ret = new CErrorValue("[operator not allowed on strings]" + op2str(op) + GetText()); - break; + switch (op) { + case VALUE_ADD_OPERATOR: + ret = new CStringValue(val->GetText() + GetText(),""); + break; + case VALUE_EQL_OPERATOR: + case VALUE_NEQ_OPERATOR: + case VALUE_GRE_OPERATOR: + case VALUE_LES_OPERATOR: + case VALUE_GEQ_OPERATOR: + case VALUE_LEQ_OPERATOR: + ret = new CErrorValue("[Cannot compare string with integer]" + op2str(op) + GetText()); + break; + default: + ret = new CErrorValue("[operator not allowed on strings]" + op2str(op) + GetText()); + break; } break; } - case VALUE_BOOL_TYPE: - ret = new CErrorValue("[operator not valid on boolean and integer]" + op2str(op) + GetText()); - break; - /* + case VALUE_BOOL_TYPE: + ret = new CErrorValue("[operator not valid on boolean and integer]" + op2str(op) + GetText()); + break; +#if 0 case VALUE_EMPTY_TYPE: { - switch(op) { - - case VALUE_ADD_OPERATOR: - ret = new CIntValue (m_int); - break; - case VALUE_SUB_OPERATOR: - ret = new CIntValue (-m_int); - break; - default: - { - ret = new CErrorValue(op2str(op) + GetText()); - } - } - break; - } - */ + switch (op) { + case VALUE_ADD_OPERATOR: + ret = new CIntValue (m_int); + break; + case VALUE_SUB_OPERATOR: + ret = new CIntValue (-m_int); + break; + default: + { + ret = new CErrorValue(op2str(op) + GetText()); + } + } + break; + } +#endif case VALUE_ERROR_TYPE: ret = new CErrorValue(val->GetText() + op2str(op) + GetText()); break; @@ -326,7 +321,7 @@ void CIntValue::SetValue(CValue* newval) #ifdef WITH_PYTHON -PyObject* CIntValue::ConvertValueToPython() +PyObject *CIntValue::ConvertValueToPython() { if ((m_int > INT_MIN) && (m_int < INT_MAX)) return PyLong_FromSsize_t(m_int); diff --git a/source/gameengine/Expressions/IntValue.h b/source/gameengine/Expressions/IntValue.h index e728467cc4e..8411b09693c 100644 --- a/source/gameengine/Expressions/IntValue.h +++ b/source/gameengine/Expressions/IntValue.h @@ -69,5 +69,4 @@ private: #endif }; -#endif // !defined __INTVALUE_H__ - +#endif /* __INTVALUE_H__ */ diff --git a/source/gameengine/Expressions/KX_HashedPtr.h b/source/gameengine/Expressions/KX_HashedPtr.h index ffc6ff647d5..d822af38c44 100644 --- a/source/gameengine/Expressions/KX_HashedPtr.h +++ b/source/gameengine/Expressions/KX_HashedPtr.h @@ -50,7 +50,7 @@ public: inline friend bool operator ==( const CHashedPtr & rhs,const CHashedPtr & lhs) { return rhs.m_valptr == lhs.m_valptr; - } + } #ifdef WITH_CXX_GUARDEDALLOC @@ -58,5 +58,4 @@ public: #endif }; -#endif //__KX_HASHEDPTR_H__ - +#endif /* __KX_HASHEDPTR_H__ */ diff --git a/source/gameengine/Expressions/KX_Python.h b/source/gameengine/Expressions/KX_Python.h index 4a7ce4d3fb7..62dd9a13dd4 100644 --- a/source/gameengine/Expressions/KX_Python.h +++ b/source/gameengine/Expressions/KX_Python.h @@ -79,5 +79,4 @@ #undef toupper #endif -#endif // __KX_PYTHON_H__ - +#endif /* __KX_PYTHON_H__ */ diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp index f43625a7821..8cff5a01c0e 100644 --- a/source/gameengine/Expressions/ListValue.cpp +++ b/source/gameengine/Expressions/ListValue.cpp @@ -278,7 +278,7 @@ bool CListValue::IsModified() /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ -Py_ssize_t listvalue_bufferlen(PyObject* self) +static Py_ssize_t listvalue_bufferlen(PyObject *self) { CListValue *list= static_cast(BGE_PROXY_REF(self)); if (list==NULL) @@ -287,7 +287,7 @@ Py_ssize_t listvalue_bufferlen(PyObject* self) return (Py_ssize_t)list->GetCount(); } -PyObject* listvalue_buffer_item(PyObject* self, Py_ssize_t index) +static PyObject *listvalue_buffer_item(PyObject *self, Py_ssize_t index) { CListValue *list= static_cast(BGE_PROXY_REF(self)); CValue *cval; @@ -309,14 +309,44 @@ PyObject* listvalue_buffer_item(PyObject* self, Py_ssize_t index) cval= list->GetValue(index); - PyObject* pyobj = cval->ConvertValueToPython(); + PyObject *pyobj = cval->ConvertValueToPython(); if (pyobj) return pyobj; else return cval->GetProxy(); } -PyObject* listvalue_mapping_subscript(PyObject* self, PyObject* pyindex) + +/* just slice it into a python list... */ +static PyObject *listvalue_buffer_slice(CListValue *list, Py_ssize_t start, Py_ssize_t stop) +{ + PyObject *newlist; + Py_ssize_t i, j; + + /* caller needs to validate negative index */ +#if 0 + Py_ssize_t len = list->GetCount(); + + if (start > len) start = len; + if (stop > len) stop = len; +#endif + + newlist = PyList_New(stop - start); + if (!newlist) + return NULL; + + for (i = start, j = 0; i < stop; i++, j++) { + PyObject *pyobj = list->GetValue(i)->ConvertValueToPython(); + if (!pyobj) { + pyobj = list->GetValue(i)->GetProxy(); + } + PyList_SET_ITEM(newlist, j, pyobj); + } + return newlist; +} + + +static PyObject *listvalue_mapping_subscript(PyObject *self, PyObject *key) { CListValue *list= static_cast(BGE_PROXY_REF(self)); if (list==NULL) { @@ -324,67 +354,45 @@ PyObject* listvalue_mapping_subscript(PyObject* self, PyObject* pyindex) return NULL; } - if (PyUnicode_Check(pyindex)) - { - CValue *item = ((CListValue*) list)->FindValue(_PyUnicode_AsString(pyindex)); + if (PyUnicode_Check(key)) { + CValue *item = ((CListValue*) list)->FindValue(_PyUnicode_AsString(key)); if (item) { - PyObject* pyobj = item->ConvertValueToPython(); + PyObject *pyobj = item->ConvertValueToPython(); if (pyobj) return pyobj; else return item->GetProxy(); } } - else if (PyLong_Check(pyindex)) - { - int index = PyLong_AsSsize_t(pyindex); + else if (PyIndex_Check(key)) { + int index = PyLong_AsSsize_t(key); return listvalue_buffer_item(self, index); /* wont add a ref */ } + else if (PySlice_Check(key)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx(key, list->GetCount(), &start, &stop, &step, &slicelength) < 0) + return NULL; + + if (slicelength <= 0) { + return PyList_New(0); + } + else if (step == 1) { + return listvalue_buffer_slice(list, start, stop); + } + else { + PyErr_SetString(PyExc_TypeError, "CList[slice]: slice steps not supported"); + return NULL; + } + } PyErr_Format(PyExc_KeyError, - "CList[key]: '%R' key not in list", pyindex); + "CList[key]: '%R' key not in list", key); return NULL; } - -/* just slice it into a python list... */ -PyObject* listvalue_buffer_slice(PyObject* self,Py_ssize_t ilow, Py_ssize_t ihigh) -{ - CListValue *list= static_cast(BGE_PROXY_REF(self)); - if (list==NULL) { - PyErr_SetString(PyExc_SystemError, "val = CList[i:j], "BGE_PROXY_ERROR_MSG); - return NULL; - } - - int i, j; - PyObject *newlist; - - if (ilow < 0) ilow = 0; - - int n = ((CListValue*) list)->GetCount(); - - if (ihigh >= n) - ihigh = n; - if (ihigh < ilow) - ihigh = ilow; - - newlist = PyList_New(ihigh - ilow); - if (!newlist) - return NULL; - - for (i = ilow, j = 0; i < ihigh; i++, j++) - { - PyObject* pyobj = list->GetValue(i)->ConvertValueToPython(); - if (!pyobj) - pyobj = list->GetValue(i)->GetProxy(); - PyList_SET_ITEM(newlist, i, pyobj); - } - return newlist; -} - - /* clist + list, return a list that python owns */ -static PyObject *listvalue_buffer_concat(PyObject * self, PyObject * other) +static PyObject *listvalue_buffer_concat(PyObject *self, PyObject *other) { CListValue *listval= static_cast(BGE_PROXY_REF(self)); Py_ssize_t i, numitems, numitems_orig; @@ -460,9 +468,9 @@ static PyObject *listvalue_buffer_concat(PyObject * self, PyObject * other) static int listvalue_buffer_contains(PyObject *self_v, PyObject *value) { - CListValue *self= static_cast(BGE_PROXY_REF(self_v)); + CListValue *self = static_cast(BGE_PROXY_REF(self_v)); - if (self==NULL) { + if (self == NULL) { PyErr_SetString(PyExc_SystemError, "val in CList, "BGE_PROXY_ERROR_MSG); return -1; } @@ -560,7 +568,7 @@ PyAttributeDef CListValue::Attributes[] = { { NULL } //Sentinel }; -PyObject* CListValue::Pyappend(PyObject* value) +PyObject *CListValue::Pyappend(PyObject *value) { CValue* objval = ConvertPythonToValue(value, "CList.append(i): CValueList, "); @@ -577,15 +585,15 @@ PyObject* CListValue::Pyappend(PyObject* value) Py_RETURN_NONE; } -PyObject* CListValue::Pyreverse() +PyObject *CListValue::Pyreverse() { std::reverse(m_pValueArray.begin(),m_pValueArray.end()); Py_RETURN_NONE; } -PyObject* CListValue::Pyindex(PyObject *value) +PyObject *CListValue::Pyindex(PyObject *value) { - PyObject* result = NULL; + PyObject *result = NULL; CValue* checkobj = ConvertPythonToValue(value, "val = cList[i]: CValueList, "); if (checkobj==NULL) @@ -612,7 +620,7 @@ PyObject* CListValue::Pyindex(PyObject *value) -PyObject* CListValue::Pycount(PyObject* value) +PyObject *CListValue::Pycount(PyObject *value) { int numfound = 0; @@ -638,17 +646,17 @@ PyObject* CListValue::Pycount(PyObject* value) } /* Matches python dict.get(key, [default]) */ -PyObject* CListValue::Pyget(PyObject *args) +PyObject *CListValue::Pyget(PyObject *args) { char *key; - PyObject* def = Py_None; + PyObject *def = Py_None; if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) return NULL; CValue *item = FindValue((const char *)key); if (item) { - PyObject* pyobj = item->ConvertValueToPython(); + PyObject *pyobj = item->ConvertValueToPython(); if (pyobj) return pyobj; else @@ -659,7 +667,7 @@ PyObject* CListValue::Pyget(PyObject *args) } -PyObject* CListValue::Pyfrom_id(PyObject* value) +PyObject *CListValue::Pyfrom_id(PyObject *value) { uintptr_t id= (uintptr_t)PyLong_AsVoidPtr(value); diff --git a/source/gameengine/Expressions/ListValue.h b/source/gameengine/Expressions/ListValue.h index 4d104a4bd3a..5240c54ae4e 100644 --- a/source/gameengine/Expressions/ListValue.h +++ b/source/gameengine/Expressions/ListValue.h @@ -64,7 +64,7 @@ public: bool CheckEqual(CValue* first,CValue* second); #ifdef WITH_PYTHON - virtual PyObject* py_repr(void) { + virtual PyObject *py_repr(void) { PyObject *py_proxy= this->GetProxy(); PyObject *py_list= PySequence_List(py_proxy); PyObject *py_string= PyObject_Repr(py_list); @@ -87,5 +87,5 @@ private: bool m_bReleaseContents; }; -#endif // !defined __LISTVALUE_H__ +#endif /* __LISTVALUE_H__ */ diff --git a/source/gameengine/Expressions/Operator1Expr.h b/source/gameengine/Expressions/Operator1Expr.h index 13a1b16500a..3dd76f773f2 100644 --- a/source/gameengine/Expressions/Operator1Expr.h +++ b/source/gameengine/Expressions/Operator1Expr.h @@ -16,8 +16,8 @@ * \ingroup expressions */ -#if !defined(AFX_OPERATOR1EXPR_H__A1653901_BF41_11D1_A51C_00A02472FC58__INCLUDED_) -#define AFX_OPERATOR1EXPR_H__A1653901_BF41_11D1_A51C_00A02472FC58__INCLUDED_ +#ifndef __OPERATOR1EXPR_H__ +#define __OPERATOR1EXPR_H__ #include "Expression.h" @@ -56,5 +56,4 @@ private: #endif }; -#endif // !defined(AFX_OPERATOR1EXPR_H__A1653901_BF41_11D1_A51C_00A02472FC58__INCLUDED_) - +#endif /* __OPERATOR1EXPR_H__ */ diff --git a/source/gameengine/Expressions/Operator2Expr.cpp b/source/gameengine/Expressions/Operator2Expr.cpp index 2224b0ff5e8..d0240b5ec75 100644 --- a/source/gameengine/Expressions/Operator2Expr.cpp +++ b/source/gameengine/Expressions/Operator2Expr.cpp @@ -102,7 +102,7 @@ and m_rhs m_cached_calculate = ffleft->Calc(m_op,ffright); - //if (m_cached_calculate) + //if (m_cached_calculate) // m_cached_calculate->Action(CValue::SETOWNEREXPR,&CVoidValue(this,false,CValue::STACKVALUE)); ffleft->Release(); @@ -163,7 +163,7 @@ bool COperator2Expr::IsInside(float x, float y, float z,bool bBorderInclude) } } - return inside; + return inside; } @@ -241,7 +241,7 @@ CExpression* COperator2Expr::CheckLink(std::vector& brokenlink if (m_rhs) return Release(m_rhs->AddRef()); -/ +/ */ return Release(); diff --git a/source/gameengine/Expressions/Operator2Expr.h b/source/gameengine/Expressions/Operator2Expr.h index 23272930131..8c30b7cd634 100644 --- a/source/gameengine/Expressions/Operator2Expr.h +++ b/source/gameengine/Expressions/Operator2Expr.h @@ -62,5 +62,5 @@ private: #endif }; -#endif // !defined __OPERATOR2EXPR_H__ +#endif /* __OPERATOR2EXPR_H__ */ diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index a35cb4f9f69..bb1d0a31c1f 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -145,7 +145,7 @@ PyObject *PyObjectPlus::py_base_repr(PyObject *self) // This should be the ent } -PyObject * PyObjectPlus::py_base_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +PyObject *PyObjectPlus::py_base_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyTypeObject *base_type; PyObjectPlus_Proxy *base = NULL; @@ -170,7 +170,7 @@ PyObject * PyObjectPlus::py_base_new(PyTypeObject *type, PyObject *args, PyObjec * * */ base_type= Py_TYPE(base); - while(base_type && !BGE_PROXY_CHECK_TYPE(base_type)) + while (base_type && !BGE_PROXY_CHECK_TYPE(base_type)) base_type= base_type->tp_base; if (base_type==NULL || !BGE_PROXY_CHECK_TYPE(base_type)) { @@ -270,7 +270,7 @@ PyAttributeDef PyObjectPlus::Attributes[] = { -PyObject* PyObjectPlus::pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *PyObjectPlus::pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { return PyBool_FromLong(self_v ? 0:1); } @@ -303,7 +303,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * ptr += attrdef->m_offset; if (attrdef->m_length > 1) { - PyObject* resultlist = PyList_New(attrdef->m_length); + PyObject *resultlist = PyList_New(attrdef->m_length); for (unsigned int i=0; im_length; i++) { switch (attrdef->m_type) { @@ -420,7 +420,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * #ifdef USE_MATHUTILS return Vector_CreatePyObject(val, attrdef->m_imax, Py_NEW, NULL); #else - PyObject* resultlist = PyList_New(attrdef->m_imax); + PyObject *resultlist = PyList_New(attrdef->m_imax); for (unsigned int i=0; im_imax; i++) { PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble(val[i])); @@ -437,10 +437,10 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * #ifdef USE_MATHUTILS return Matrix_CreatePyObject(val, attrdef->m_imin, attrdef->m_imax, Py_WRAP, NULL); #else - PyObject* collist = PyList_New(attrdef->m_imin); + PyObject *collist = PyList_New(attrdef->m_imin); for (unsigned int i=0; im_imin; i++) { - PyObject* col = PyList_New(attrdef->m_imax); + PyObject *col = PyList_New(attrdef->m_imax); for (unsigned int j=0; jm_imax; j++) { PyList_SET_ITEM(col,j,PyFloat_FromDouble(val[j])); @@ -460,7 +460,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * val->getValue(fval); return Vector_CreatePyObject(fval, 3, Py_NEW, NULL); #else - PyObject* resultlist = PyList_New(3); + PyObject *resultlist = PyList_New(3); for (unsigned int i=0; i<3; i++) { PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble((*val)[i])); @@ -1100,7 +1100,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt } if (undoBuffer) free(undoBuffer); - return 0; + return 0; } @@ -1139,7 +1139,7 @@ PyObject *PyObjectPlus::NewProxyPlus_Ext(PyObjectPlus *self, PyTypeObject *tp, v if (!self) { // in case of proxy without reference to game object - PyObject* proxy = reinterpret_castPyObject_NEW( PyObjectPlus_Proxy, tp); + PyObject *proxy = reinterpret_castPyObject_NEW( PyObjectPlus_Proxy, tp); BGE_PROXY_PYREF(proxy) = false; BGE_PROXY_PYOWNS(proxy) = py_owns; BGE_PROXY_REF(proxy) = NULL; @@ -1198,8 +1198,7 @@ void PyObjectPlus::ClearDeprecationWarning() WarnLink *wlink_next; WarnLink *wlink = GetDeprecationWarningLinkFirst(); - while(wlink) - { + while (wlink) { wlink->warn_done= false; /* no need to NULL the link, its cleared before adding to the list next time round */ wlink_next= reinterpret_cast(wlink->link); wlink->link= NULL; diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index f74ed7db8f7..83b7c8c8771 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -190,9 +190,9 @@ public: \ * macro is one that also requires a documentation string */ #define KX_PYMETHOD(class_name, method_name) \ - PyObject* Py##method_name(PyObject* args, PyObject* kwds); \ - static PyObject* \ - sPy##method_name(PyObject* self, PyObject* args, PyObject* kwds) { \ + PyObject *Py##method_name(PyObject *args, PyObject *kwds); \ + static PyObject * \ + sPy##method_name(PyObject *self, PyObject *args, PyObject *kwds) { \ if(BGE_PROXY_REF(self)==NULL) { \ PyErr_SetString(PyExc_RuntimeError, \ #class_name "." #method_name "() - " \ @@ -203,9 +203,9 @@ public: \ } \ #define KX_PYMETHOD_VARARGS(class_name, method_name) \ - PyObject* Py##method_name(PyObject* args); \ + PyObject *Py##method_name(PyObject *args); \ static PyObject* \ - sPy##method_name(PyObject* self, PyObject* args) { \ + sPy##method_name(PyObject *self, PyObject *args) { \ if(BGE_PROXY_REF(self)==NULL) { \ PyErr_SetString(PyExc_RuntimeError, \ #class_name "." #method_name "() - " \ @@ -215,9 +215,9 @@ public: \ } \ #define KX_PYMETHOD_NOARGS(class_name, method_name) \ - PyObject* Py##method_name(); \ + PyObject *Py##method_name(); \ static PyObject* \ - sPy##method_name(PyObject* self) { \ + sPy##method_name(PyObject *self) { \ if(BGE_PROXY_REF(self)==NULL) { \ PyErr_SetString(PyExc_RuntimeError, \ #class_name "." #method_name "() - " \ @@ -227,9 +227,9 @@ public: \ } \ #define KX_PYMETHOD_O(class_name, method_name) \ - PyObject* Py##method_name(PyObject* value); \ + PyObject *Py##method_name(PyObject *value); \ static PyObject* \ - sPy##method_name(PyObject* self, PyObject* value) { \ + sPy##method_name(PyObject *self, PyObject *value) { \ if(BGE_PROXY_REF(self)==NULL) { \ PyErr_SetString(PyExc_RuntimeError, \ #class_name "." #method_name "(value) - " \ @@ -239,9 +239,9 @@ public: \ } \ #define KX_PYMETHOD_DOC(class_name, method_name) \ - PyObject* Py##method_name(PyObject* args, PyObject* kwds); \ + PyObject *Py##method_name(PyObject *args, PyObject *kwds); \ static PyObject* \ - sPy##method_name(PyObject* self, PyObject* args, PyObject* kwds) { \ + sPy##method_name(PyObject *self, PyObject *args, PyObject *kwds) { \ if(BGE_PROXY_REF(self)==NULL) { \ PyErr_SetString(PyExc_RuntimeError, \ #class_name "." #method_name "(...) - " \ @@ -252,9 +252,9 @@ public: \ static const char method_name##_doc[]; \ #define KX_PYMETHOD_DOC_VARARGS(class_name, method_name) \ - PyObject* Py##method_name(PyObject* args); \ + PyObject *Py##method_name(PyObject *args); \ static PyObject* \ - sPy##method_name(PyObject* self, PyObject* args) { \ + sPy##method_name(PyObject *self, PyObject *args) { \ if(BGE_PROXY_REF(self)==NULL) { \ PyErr_SetString(PyExc_RuntimeError, \ #class_name "." #method_name "(...) - " \ @@ -266,9 +266,9 @@ public: \ static const char method_name##_doc[]; \ #define KX_PYMETHOD_DOC_O(class_name, method_name) \ - PyObject* Py##method_name(PyObject* value); \ - static PyObject* \ - sPy##method_name(PyObject* self, PyObject* value) { \ + PyObject *Py##method_name(PyObject *value); \ + static PyObject * \ + sPy##method_name(PyObject *self, PyObject *value) { \ if(BGE_PROXY_REF(self)==NULL) { \ PyErr_SetString(PyExc_RuntimeError, \ #class_name "." #method_name "(value) - " \ @@ -280,9 +280,9 @@ public: \ static const char method_name##_doc[]; \ #define KX_PYMETHOD_DOC_NOARGS(class_name, method_name) \ - PyObject* Py##method_name(); \ - static PyObject* \ - sPy##method_name(PyObject* self) { \ + PyObject *Py##method_name(); \ + static PyObject * \ + sPy##method_name(PyObject *self) { \ if(BGE_PROXY_REF(self)==NULL) { \ PyErr_SetString(PyExc_RuntimeError, \ #class_name "." #method_name "() - " \ @@ -315,19 +315,19 @@ public: \ */ #define KX_PYMETHODDEF_DOC(class_name, method_name, doc_string) \ const char class_name::method_name##_doc[] = doc_string; \ -PyObject* class_name::Py##method_name(PyObject* args, PyObject* kwds) +PyObject *class_name::Py##method_name(PyObject *args, PyObject *kwds) #define KX_PYMETHODDEF_DOC_VARARGS(class_name, method_name, doc_string) \ const char class_name::method_name##_doc[] = doc_string; \ -PyObject* class_name::Py##method_name(PyObject* args) +PyObject *class_name::Py##method_name(PyObject *args) #define KX_PYMETHODDEF_DOC_O(class_name, method_name, doc_string) \ const char class_name::method_name##_doc[] = doc_string; \ -PyObject* class_name::Py##method_name(PyObject* value) +PyObject *class_name::Py##method_name(PyObject *value) #define KX_PYMETHODDEF_DOC_NOARGS(class_name, method_name, doc_string) \ const char class_name::method_name##_doc[] = doc_string; \ -PyObject* class_name::Py##method_name() +PyObject *class_name::Py##method_name() /** * Attribute management @@ -354,7 +354,7 @@ enum KX_PYATTRIBUTE_ACCESS { struct KX_PYATTRIBUTE_DEF; typedef int (*KX_PYATTRIBUTE_CHECK_FUNCTION)(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); typedef int (*KX_PYATTRIBUTE_SET_FUNCTION)(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); -typedef PyObject* (*KX_PYATTRIBUTE_GET_FUNCTION)(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); +typedef PyObject *(*KX_PYATTRIBUTE_GET_FUNCTION)(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); typedef struct KX_PYATTRIBUTE_DEF { const char *m_name; // name of the python attribute @@ -548,7 +548,7 @@ public: \ #define Py_HeaderPtr \ public: \ -#endif // WITH_CXX_GUARDEDALLOC +#endif /* WITH_CXX_GUARDEDALLOC */ #endif @@ -633,4 +633,4 @@ public: PyObject *PyUnicode_From_STR_String(const STR_String& str); #endif -#endif // __PYOBJECTPLUS_H__ +#endif /* __PYOBJECTPLUS_H__ */ diff --git a/source/gameengine/Expressions/StringValue.cpp b/source/gameengine/Expressions/StringValue.cpp index 2e29a39222b..166125bc906 100644 --- a/source/gameengine/Expressions/StringValue.cpp +++ b/source/gameengine/Expressions/StringValue.cpp @@ -77,33 +77,34 @@ CValue* CStringValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue ret = new CErrorValue(val->GetText() + op2str(op) + GetText()); else ret = new CStringValue(val->GetText() + GetText(),""); - } else { - + } + else { if (dtype == VALUE_STRING_TYPE || dtype == VALUE_EMPTY_TYPE) { - switch(op) { - case VALUE_EQL_OPERATOR: - ret = new CBoolValue(val->GetText() == GetText()); - break; - case VALUE_NEQ_OPERATOR: - ret = new CBoolValue(val->GetText() != GetText()); - break; - case VALUE_GRE_OPERATOR: - ret = new CBoolValue(val->GetText() > GetText()); - break; - case VALUE_LES_OPERATOR: - ret = new CBoolValue(val->GetText() < GetText()); - break; - case VALUE_GEQ_OPERATOR: - ret = new CBoolValue(val->GetText() >= GetText()); - break; - case VALUE_LEQ_OPERATOR: - ret = new CBoolValue(val->GetText() <= GetText()); - break; - default: - ret = new CErrorValue(val->GetText() + op2str(op) + "[operator not allowed on strings]"); - break; + switch (op) { + case VALUE_EQL_OPERATOR: + ret = new CBoolValue(val->GetText() == GetText()); + break; + case VALUE_NEQ_OPERATOR: + ret = new CBoolValue(val->GetText() != GetText()); + break; + case VALUE_GRE_OPERATOR: + ret = new CBoolValue(val->GetText() > GetText()); + break; + case VALUE_LES_OPERATOR: + ret = new CBoolValue(val->GetText() < GetText()); + break; + case VALUE_GEQ_OPERATOR: + ret = new CBoolValue(val->GetText() >= GetText()); + break; + case VALUE_LEQ_OPERATOR: + ret = new CBoolValue(val->GetText() <= GetText()); + break; + default: + ret = new CErrorValue(val->GetText() + op2str(op) + "[operator not allowed on strings]"); + break; } - } else { + } + else { ret = new CErrorValue(val->GetText() + op2str(op) + "[operator not allowed on strings]"); } } diff --git a/source/gameengine/Expressions/StringValue.h b/source/gameengine/Expressions/StringValue.h index e37b4638a1e..22d433455ec 100644 --- a/source/gameengine/Expressions/StringValue.h +++ b/source/gameengine/Expressions/StringValue.h @@ -25,7 +25,7 @@ class CStringValue : public CPropValue { - //PLUGIN_DECLARE_SERIAL(CStringValue,CValue) + //PLUGIN_DECLARE_SERIAL(CStringValue,CValue) public: /// Construction / destruction CStringValue(); @@ -45,7 +45,7 @@ public: virtual PyObject* ConvertValueToPython() { return PyUnicode_From_STR_String(m_strString); } -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ private: // data member @@ -57,5 +57,4 @@ private: #endif }; -#endif - +#endif /* __STRINGVALUE_H__ */ diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index 6507cc32cf1..bcfb7e92d71 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -340,7 +340,7 @@ vector CValue::GetPropertyNames() // Clear all properties // void CValue::ClearProperties() -{ +{ // Check if we have any properties if (m_pNamedPropertyArray == NULL) return; @@ -530,13 +530,13 @@ PyAttributeDef CValue::Attributes[] = { { NULL } //Sentinel }; -PyObject * CValue::pyattr_get_name(void * self_v, const KX_PYATTRIBUTE_DEF * attrdef) +PyObject *CValue::pyattr_get_name(void * self_v, const KX_PYATTRIBUTE_DEF *attrdef) { CValue * self = static_cast (self_v); return PyUnicode_From_STR_String(self->GetName()); } -CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix) +CValue* CValue::ConvertPythonToValue(PyObject *pyobj, const char *error_prefix) { CValue* vallie = NULL; @@ -551,7 +551,7 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix) Py_ssize_t numitems = PyList_GET_SIZE(pyobj); for (i=0;iGetNumber() == 10121969); + assertd(newval->GetNumber() == 10121969); } diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h index e3b52e80ba6..c4af3255f4a 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/Value.h @@ -16,13 +16,13 @@ * \ingroup expressions */ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable:4786) -#endif //WIN32 - #ifndef __VALUE_H__ #define __VALUE_H__ +#ifdef _MSC_VER +# pragma warning (disable:4786) +#endif + #include // array functionality for the propertylist #include "STR_String.h" // STR_String class @@ -53,14 +53,6 @@ using namespace std; #define assertd(exp) ((void)NULL) #endif - -#ifndef USE_PRAGMA_ONCE -#ifdef WIN32 - #pragma once - -#endif //WIN32 -#endif - enum VALUE_OPERATOR { VALUE_MOD_OPERATOR, // % @@ -218,22 +210,22 @@ public: CValue(); #ifdef WITH_PYTHON - //static PyObject* PyMake(PyObject*,PyObject*); + //static PyObject *PyMake(PyObject *, PyObject *); virtual PyObject *py_repr(void) { return PyUnicode_From_STR_String(GetText()); } - virtual PyObject* ConvertValueToPython() { + virtual PyObject *ConvertValueToPython() { return NULL; } - virtual CValue* ConvertPythonToValue(PyObject* pyobj, const char *error_prefix); + virtual CValue *ConvertPythonToValue(PyObject *pyobj, const char *error_prefix); - static PyObject * pyattr_get_name(void * self, const KX_PYATTRIBUTE_DEF * attrdef); + static PyObject *pyattr_get_name(void * self, const KX_PYATTRIBUTE_DEF * attrdef); - virtual PyObject* ConvertKeysToPython( void ); -#endif // WITH_PYTHON + virtual PyObject *ConvertKeysToPython( void ); +#endif /* WITH_PYTHON */ @@ -250,13 +242,13 @@ public: }; /// Reference Counting - int GetRefCount() + int GetRefCount() { return m_refcount; } // Add a reference to this value - CValue* AddRef() + CValue *AddRef() { // Increase global reference count, used to see at the end of the program // if all CValue-derived classes have been dereferenced to 0 @@ -269,7 +261,7 @@ public: } // Release a reference to this value (when reference count reaches 0, the value is removed from the heap) - int Release() + int Release() { // Decrease global reference count, used to see at the end of the program // if all CValue-derived classes have been dereferenced to 0 @@ -354,16 +346,16 @@ public: virtual void SetCustomFlag2(bool bCustomFlag) { m_ValFlags.CustomFlag2 = bCustomFlag;} virtual bool IsCustomFlag2() { return m_ValFlags.CustomFlag2;} -protected: +protected: virtual void DisableRefCount(); // Disable reference counting for this value - //virtual void AddDataToReplica(CValue* replica); + //virtual void AddDataToReplica(CValue* replica); virtual ~CValue(); private: - // Member variables + // Member variables std::map* m_pNamedPropertyArray; // Properties for user/game etc ValueFlags m_ValFlags; // Frequently used flags in a bitfield (low memoryusage) - int m_refcount; // Reference Counter - static double m_sZeroVec[3]; + int m_refcount; // Reference Counter + static double m_sZeroVec[3]; }; @@ -439,5 +431,4 @@ protected: #endif }; -#endif // !defined _VALUEBASECLASS_H - +#endif /* __VALUE_H__ */ diff --git a/source/gameengine/Expressions/VectorValue.cpp b/source/gameengine/Expressions/VectorValue.cpp index 65f5d7d3d22..612de658ce9 100644 --- a/source/gameengine/Expressions/VectorValue.cpp +++ b/source/gameengine/Expressions/VectorValue.cpp @@ -15,8 +15,8 @@ * */ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable:4786) +#ifdef _MSC_VER +# pragma warning (disable:4786) #endif #include "Value.h" @@ -96,61 +96,60 @@ CValue* CVectorValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue { CValue *ret = NULL; - switch(op) - { - case VALUE_ADD_OPERATOR: + switch (op) { + case VALUE_ADD_OPERATOR: { switch (dtype) { - case VALUE_EMPTY_TYPE: - case VALUE_VECTOR_TYPE: + case VALUE_EMPTY_TYPE: + case VALUE_VECTOR_TYPE: { ret = new CVectorValue( - val->GetVector3()[KX_X] + GetVector3()[KX_X], - val->GetVector3()[KX_Y] + GetVector3()[KX_Y], - val->GetVector3()[KX_Z] + GetVector3()[KX_Z], - CValue::HEAPVALUE); + val->GetVector3()[KX_X] + GetVector3()[KX_X], + val->GetVector3()[KX_Y] + GetVector3()[KX_Y], + val->GetVector3()[KX_Z] + GetVector3()[KX_Z], + CValue::HEAPVALUE); ret->SetName(GetName()); break; } - - default: - ret = new CErrorValue(val->GetText() + op2str(op) + GetText()); + + default: + ret = new CErrorValue(val->GetText() + op2str(op) + GetText()); } break; } - case VALUE_MUL_OPERATOR: + case VALUE_MUL_OPERATOR: { switch (dtype) { - case VALUE_EMPTY_TYPE: - case VALUE_VECTOR_TYPE: + case VALUE_EMPTY_TYPE: + case VALUE_VECTOR_TYPE: { //MT_Vector3 supports 'scaling' by another vector, instead of using general transform, Gino? //ret = new CVectorValue(val->GetVector3().Scaled(GetVector3()),GetName()); break; } - case VALUE_FLOAT_TYPE: + case VALUE_FLOAT_TYPE: { ret = new CVectorValue( - val->GetVector3()[KX_X] * GetVector3()[KX_X], - val->GetVector3()[KX_Y] * GetVector3()[KX_Y], - val->GetVector3()[KX_Z] * GetVector3()[KX_Z], - CValue::HEAPVALUE); + val->GetVector3()[KX_X] * GetVector3()[KX_X], + val->GetVector3()[KX_Y] * GetVector3()[KX_Y], + val->GetVector3()[KX_Z] * GetVector3()[KX_Z], + CValue::HEAPVALUE); ret->SetName(GetName()); break; } - - default: - ret = new CErrorValue(val->GetText() + op2str(op) + GetText()); + + default: + ret = new CErrorValue(val->GetText() + op2str(op) + GetText()); } break; } - - default: - ret = new CErrorValue(val->GetText() + op2str(op) + GetText()); + + default: + ret = new CErrorValue(val->GetText() + op2str(op) + GetText()); } diff --git a/source/gameengine/Expressions/VectorValue.h b/source/gameengine/Expressions/VectorValue.h index b7afa61d4dd..9b9f9612810 100644 --- a/source/gameengine/Expressions/VectorValue.h +++ b/source/gameengine/Expressions/VectorValue.h @@ -90,5 +90,4 @@ protected: #endif }; -#endif // !defined __VECTORVALUE_H__ - +#endif /* __VECTORVALUE_H__ */ diff --git a/source/gameengine/Expressions/VoidValue.h b/source/gameengine/Expressions/VoidValue.h index a1a82f8aa65..e97278b3142 100644 --- a/source/gameengine/Expressions/VoidValue.h +++ b/source/gameengine/Expressions/VoidValue.h @@ -78,4 +78,3 @@ public: }; #endif /* __VOIDVALUE_H__ */ - diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp index 48fa3257d20..8b343be8226 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp +++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp @@ -51,11 +51,11 @@ SCA_Joystick::SCA_Joystick(short int index) m_istrig_button(0), m_istrig_hat(0) { - for (int i=0; iDestroyJoystickDevice(); delete m_instance[i]; } - m_instance[i]= NULL; + m_instance[i] = NULL; } - // The video subsystem is required for joystick input to work. However, - // when GHOST is running under SDL, video is freed elsewhere. - // Do this once only. + /* The video subsystem is required for joystick input to work. However, + * when GHOST is running under SDL, video is freed elsewhere. + * Do this once only. */ # ifdef WITH_GHOST_SDL SDL_QuitSubSystem(SDL_INIT_JOYSTICK); # else @@ -241,10 +241,10 @@ bool SCA_Joystick::CreateJoystickDevice(void) #else /* WITH_SDL */ if (m_isinit == false) { if (m_joyindex>=m_joynum) { - // don't print a message, because this is done anyway + /* don't print a message, because this is done anyway */ //ECHO("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)"); - // Need this so python args can return empty lists + /* Need this so python args can return empty lists */ m_axismax = m_buttonmax = m_hatmax = 0; return false; } @@ -256,17 +256,17 @@ bool SCA_Joystick::CreateJoystickDevice(void) ECHO("Joystick " << m_joyindex << " initialized"); /* must run after being initialized */ - m_axismax = SDL_JoystickNumAxes(m_private->m_joystick); - m_buttonmax = SDL_JoystickNumButtons(m_private->m_joystick); - m_hatmax = SDL_JoystickNumHats(m_private->m_joystick); + m_axismax = SDL_JoystickNumAxes(m_private->m_joystick); + m_buttonmax = SDL_JoystickNumButtons(m_private->m_joystick); + m_hatmax = SDL_JoystickNumHats(m_private->m_joystick); + + if (m_axismax > JOYAXIS_MAX) m_axismax = JOYAXIS_MAX; /* very unlikely */ + else if (m_axismax < 0) m_axismax = 0; - if (m_axismax > JOYAXIS_MAX) m_axismax= JOYAXIS_MAX; /* very unlikely */ - else if (m_axismax < 0) m_axismax = 0; + if (m_hatmax > JOYHAT_MAX) m_hatmax = JOYHAT_MAX; /* very unlikely */ + else if (m_hatmax < 0) m_hatmax = 0; - if (m_hatmax > JOYHAT_MAX) m_hatmax= JOYHAT_MAX; /* very unlikely */ - else if (m_hatmax<0) m_hatmax= 0; - - if (m_buttonmax<0) m_buttonmax= 0; + if (m_buttonmax < 0) m_buttonmax = 0; } return true; @@ -307,16 +307,16 @@ int SCA_Joystick::pGetAxis(int axisnum, int udlr) int SCA_Joystick::pAxisTest(int axisnum) { #ifdef WITH_SDL - short i1= m_axis_array[(axisnum*2)]; - short i2= m_axis_array[(axisnum*2)+1]; + short i1 = m_axis_array[(axisnum * 2)]; + short i2 = m_axis_array[(axisnum * 2) + 1]; - /* long winded way to do - * return maxf(absf(i1), absf(i2)) - * avoid abs from math.h */ + /* long winded way to do: + * return max_ff(absf(i1), absf(i2)) + * ...avoid abs from math.h */ if (i1 < 0) i1 = -i1; if (i2 < 0) i2 = -i2; if (i1 jaxis.axis >= JOYAXIS_MAX) return; - m_axis_array[sdl_event->jaxis.axis]= sdl_event->jaxis.value; + m_axis_array[sdl_event->jaxis.axis] = sdl_event->jaxis.value; m_istrig_axis = 1; } @@ -53,7 +53,7 @@ void SCA_Joystick::OnHatMotion(SDL_Event* sdl_event) if (sdl_event->jhat.hat >= JOYHAT_MAX) return; - m_hat_array[sdl_event->jhat.hat]= sdl_event->jhat.value; + m_hat_array[sdl_event->jhat.hat] = sdl_event->jhat.value; m_istrig_hat = 1; } @@ -89,8 +89,7 @@ void SCA_Joystick::HandleEvents(void) SCA_Joystick::m_instance[i]->OnNothing(&sdl_event); } - while(SDL_PollEvent(&sdl_event)) - { + while (SDL_PollEvent(&sdl_event)) { /* Note! m_instance[sdl_event.jaxis.which] * will segfault if over JOYINDEX_MAX, not too nice but what are the chances? */ @@ -100,28 +99,27 @@ void SCA_Joystick::HandleEvents(void) /* Note!, if you manage to press and release a button within 1 logic tick * it wont work as it should */ - switch(sdl_event.type) - { - case SDL_JOYAXISMOTION: - SCA_Joystick::m_instance[sdl_event.jaxis.which]->OnAxisMotion(&sdl_event); - break; - case SDL_JOYHATMOTION: - SCA_Joystick::m_instance[sdl_event.jhat.which]->OnHatMotion(&sdl_event); - break; - case SDL_JOYBUTTONUP: - SCA_Joystick::m_instance[sdl_event.jbutton.which]->OnButtonUp(&sdl_event); - break; - case SDL_JOYBUTTONDOWN: - SCA_Joystick::m_instance[sdl_event.jbutton.which]->OnButtonDown(&sdl_event); - break; + switch (sdl_event.type) { + case SDL_JOYAXISMOTION: + SCA_Joystick::m_instance[sdl_event.jaxis.which]->OnAxisMotion(&sdl_event); + break; + case SDL_JOYHATMOTION: + SCA_Joystick::m_instance[sdl_event.jhat.which]->OnHatMotion(&sdl_event); + break; + case SDL_JOYBUTTONUP: + SCA_Joystick::m_instance[sdl_event.jbutton.which]->OnButtonUp(&sdl_event); + break; + case SDL_JOYBUTTONDOWN: + SCA_Joystick::m_instance[sdl_event.jbutton.which]->OnButtonDown(&sdl_event); + break; #if 0 /* Not used yet */ - case SDL_JOYBALLMOTION: - SCA_Joystick::m_instance[sdl_event.jball.which]->OnBallMotion(&sdl_event); - break; + case SDL_JOYBALLMOTION: + SCA_Joystick::m_instance[sdl_event.jball.which]->OnBallMotion(&sdl_event); + break; #endif - default: - printf("SCA_Joystick::HandleEvents, Unknown SDL event, this should not happen\n"); - break; + default: + printf("SCA_Joystick::HandleEvents, Unknown SDL event, this should not happen\n"); + break; } } } diff --git a/source/gameengine/GameLogic/SCA_ANDController.h b/source/gameengine/GameLogic/SCA_ANDController.h index ccc3f9be3af..ff152d6d2fb 100644 --- a/source/gameengine/GameLogic/SCA_ANDController.h +++ b/source/gameengine/GameLogic/SCA_ANDController.h @@ -48,5 +48,4 @@ public: virtual void Trigger(SCA_LogicManager* logicmgr); }; -#endif //__SCA_ANDCONTROLLER_H__ - +#endif /* __SCA_ANDCONTROLLER_H__ */ diff --git a/source/gameengine/GameLogic/SCA_ActuatorEventManager.h b/source/gameengine/GameLogic/SCA_ActuatorEventManager.h index dee9ea4e8ba..997be1145db 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorEventManager.h +++ b/source/gameengine/GameLogic/SCA_ActuatorEventManager.h @@ -53,5 +53,4 @@ public: #endif }; -#endif //__SCA_ACTUATOREVENTMANAGER_H__ - +#endif /* __SCA_ACTUATOREVENTMANAGER_H__ */ diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.h b/source/gameengine/GameLogic/SCA_ActuatorSensor.h index 894dc2162cf..6005bd3ac6c 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.h +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.h @@ -64,7 +64,7 @@ public: static int CheckActuator(void *self, const PyAttributeDef*); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; -#endif +#endif /* __SCA_ACTUATORSENSOR_H__ */ diff --git a/source/gameengine/GameLogic/SCA_AlwaysEventManager.h b/source/gameengine/GameLogic/SCA_AlwaysEventManager.h index cf4063fba1f..47293c75726 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysEventManager.h +++ b/source/gameengine/GameLogic/SCA_AlwaysEventManager.h @@ -47,5 +47,4 @@ public: #endif }; -#endif //__SCA_ALWAYSEVENTMANAGER_H__ - +#endif /* __SCA_ALWAYSEVENTMANAGER_H__ */ diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp index 6b697f4f15b..1a6a82a33eb 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp +++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp @@ -32,11 +32,10 @@ * \ingroup gamelogic */ - -#if defined(WIN32) && !defined(FREE_WINDOWS) -// This warning tells us about truncation of __long__ stl-generated names. -// It can occasionally cause DevStudio to have internal compiler warnings. -#pragma warning( disable : 4786 ) +#ifdef _MSC_VER + /* This warning tells us about truncation of __long__ stl-generated names. + * It can occasionally cause DevStudio to have internal compiler warnings. */ +# pragma warning( disable:4786 ) #endif #include "SCA_AlwaysSensor.h" diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.h b/source/gameengine/GameLogic/SCA_AlwaysSensor.h index d0963fd0ea1..e0ab4279b1c 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysSensor.h +++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.h @@ -50,5 +50,4 @@ public: virtual void Init(); }; -#endif //__SCA_ALWAYSSENSOR_H__ - +#endif /* __SCA_ALWAYSSENSOR_H__ */ diff --git a/source/gameengine/GameLogic/SCA_BasicEventManager.h b/source/gameengine/GameLogic/SCA_BasicEventManager.h index 24206e46a61..a015233454b 100644 --- a/source/gameengine/GameLogic/SCA_BasicEventManager.h +++ b/source/gameengine/GameLogic/SCA_BasicEventManager.h @@ -54,5 +54,4 @@ public: #endif }; -#endif //__SCA_BASICEVENTMANAGER_H__ - +#endif /* __SCA_BASICEVENTMANAGER_H__ */ diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.cpp b/source/gameengine/GameLogic/SCA_DelaySensor.cpp index f2bcd67e652..af751cffc2e 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.cpp +++ b/source/gameengine/GameLogic/SCA_DelaySensor.cpp @@ -32,11 +32,10 @@ * \ingroup gamelogic */ - -#if defined(WIN32) && !defined(FREE_WINDOWS) -// This warning tells us about truncation of __long__ stl-generated names. -// It can occasionally cause DevStudio to have internal compiler warnings. -#pragma warning( disable : 4786 ) +#ifdef _MSC_VER + /* This warning tells us about truncation of __long__ stl-generated names. + * It can occasionally cause DevStudio to have internal compiler warnings. */ +# pragma warning( disable:4786 ) #endif #include diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.h b/source/gameengine/GameLogic/SCA_DelaySensor.h index 2c408921f27..b516cd8360e 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.h +++ b/source/gameengine/GameLogic/SCA_DelaySensor.h @@ -65,5 +65,4 @@ public: }; -#endif //__KX_ALWAYSSENSOR - +#endif /* __SCA_DELAYSENSOR_H__ */ diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.h b/source/gameengine/GameLogic/SCA_ExpressionController.h index 06edc83ab96..c16944ccde1 100644 --- a/source/gameengine/GameLogic/SCA_ExpressionController.h +++ b/source/gameengine/GameLogic/SCA_ExpressionController.h @@ -63,5 +63,4 @@ public: #endif }; -#endif //__SCA_EXPRESSIONCONTROLLER_H__ - +#endif /* __SCA_EXPRESSIONCONTROLLER_H__ */ diff --git a/source/gameengine/GameLogic/SCA_IActuator.h b/source/gameengine/GameLogic/SCA_IActuator.h index 801483bb882..090df1e75e2 100644 --- a/source/gameengine/GameLogic/SCA_IActuator.h +++ b/source/gameengine/GameLogic/SCA_IActuator.h @@ -164,5 +164,4 @@ public: #endif }; -#endif //__SCA_IACTUATOR_H__ - +#endif /* __SCA_IACTUATOR_H__ */ diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp index 3fda542410a..57f7dd64287 100644 --- a/source/gameengine/GameLogic/SCA_IController.cpp +++ b/source/gameengine/GameLogic/SCA_IController.cpp @@ -238,19 +238,19 @@ PyAttributeDef SCA_IController::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_IController::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_IController::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_IController* self= static_cast(self_v); + SCA_IController* self = static_cast(self_v); return PyLong_FromSsize_t(self->m_statemask); } -PyObject* SCA_IController::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_IController::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - return KX_PythonSeq_CreatePyObject((static_cast(self_v))->m_proxy, KX_PYGENSEQ_CONT_TYPE_SENSORS); + return KX_PythonSeq_CreatePyObject((static_cast(self_v))->m_proxy, KX_PYGENSEQ_CONT_TYPE_SENSORS); } -PyObject* SCA_IController::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_IController::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - return KX_PythonSeq_CreatePyObject((static_cast(self_v))->m_proxy, KX_PYGENSEQ_CONT_TYPE_ACTUATORS); + return KX_PythonSeq_CreatePyObject((static_cast(self_v))->m_proxy, KX_PYGENSEQ_CONT_TYPE_ACTUATORS); } #endif // WITH_PYTHON diff --git a/source/gameengine/GameLogic/SCA_IController.h b/source/gameengine/GameLogic/SCA_IController.h index 656c4299dff..1bc6b60bf1e 100644 --- a/source/gameengine/GameLogic/SCA_IController.h +++ b/source/gameengine/GameLogic/SCA_IController.h @@ -106,8 +106,7 @@ public: static PyObject* pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; -#endif - +#endif /* __SCA_ICONTROLLER_H__ */ diff --git a/source/gameengine/GameLogic/SCA_IInputDevice.cpp b/source/gameengine/GameLogic/SCA_IInputDevice.cpp index 16626b05526..f4fce034c87 100644 --- a/source/gameengine/GameLogic/SCA_IInputDevice.cpp +++ b/source/gameengine/GameLogic/SCA_IInputDevice.cpp @@ -45,7 +45,7 @@ SCA_IInputDevice::SCA_IInputDevice() SCA_IInputDevice::~SCA_IInputDevice() { -} +} void SCA_IInputDevice::HookEscape() { @@ -134,6 +134,6 @@ void SCA_IInputDevice::NextFrame() break; default: ; /* error */ - } + } } } diff --git a/source/gameengine/GameLogic/SCA_IInputDevice.h b/source/gameengine/GameLogic/SCA_IInputDevice.h index 0382a2efd21..1a403f40955 100644 --- a/source/gameengine/GameLogic/SCA_IInputDevice.h +++ b/source/gameengine/GameLogic/SCA_IInputDevice.h @@ -69,7 +69,7 @@ class SCA_IInputDevice public: SCA_IInputDevice(); - virtual ~SCA_IInputDevice(); + virtual ~SCA_IInputDevice(); enum KX_EnumInputs { @@ -120,17 +120,17 @@ public: KX_RETKEY = 13, KX_SPACEKEY = 32, KX_PADASTERKEY = 42, - KX_COMMAKEY = 44, - KX_MINUSKEY = 45, + KX_COMMAKEY = 44, + KX_MINUSKEY = 45, KX_PERIODKEY = 46, KX_ZEROKEY = 48, KX_ONEKEY, // =49 - KX_TWOKEY, + KX_TWOKEY, KX_THREEKEY, - KX_FOURKEY, - KX_FIVEKEY, - KX_SIXKEY, + KX_FOURKEY, + KX_FIVEKEY, + KX_SIXKEY, KX_SEVENKEY, KX_EIGHTKEY, KX_NINEKEY, // = 57 @@ -167,17 +167,17 @@ public: KX_CAPSLOCKKEY, // 123 KX_LEFTCTRLKEY, // 124 - KX_LEFTALTKEY, - KX_RIGHTALTKEY, - KX_RIGHTCTRLKEY, - KX_RIGHTSHIFTKEY, + KX_LEFTALTKEY, + KX_RIGHTALTKEY, + KX_RIGHTCTRLKEY, + KX_RIGHTSHIFTKEY, KX_LEFTSHIFTKEY,// 129 KX_ESCKEY, // 130 KX_TABKEY, //131 - KX_LINEFEEDKEY, // 132 + KX_LINEFEEDKEY, // 132 KX_BACKSPACEKEY, KX_DELKEY, KX_SEMICOLONKEY, // 135 @@ -188,13 +188,13 @@ public: KX_SLASHKEY, //138 KX_BACKSLASHKEY, - KX_EQUALKEY, - KX_LEFTBRACKETKEY, + KX_EQUALKEY, + KX_LEFTBRACKETKEY, KX_RIGHTBRACKETKEY, // 142 KX_LEFTARROWKEY, // 145 KX_DOWNARROWKEY, - KX_RIGHTARROWKEY, + KX_RIGHTARROWKEY, KX_UPARROWKEY, // 148 KX_PAD2 , @@ -320,5 +320,5 @@ public: #endif }; -#endif //__SCA_IINPUTDEVICE_H__ +#endif /* __SCA_IINPUTDEVICE_H__ */ diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index 018a939f68d..ab0e6c5edcb 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -231,9 +231,9 @@ int SCA_ILogicBrick::CheckProperty(void *self, const PyAttributeDef *attrdef) } /*Attribute functions */ -PyObject* SCA_ILogicBrick::pyattr_get_owner(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_ILogicBrick::pyattr_get_owner(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_ILogicBrick* self= static_cast(self_v); + SCA_ILogicBrick* self = static_cast(self_v); CValue* parent = self->GetParent(); if (parent) @@ -254,9 +254,9 @@ bool SCA_ILogicBrick::PyArgToBool(int boolArg) } } -PyObject* SCA_ILogicBrick::BoolToPyArg(bool boolarg) +PyObject *SCA_ILogicBrick::BoolToPyArg(bool boolarg) { - return PyLong_FromSsize_t(boolarg? KX_TRUE: KX_FALSE); + return PyLong_FromSsize_t(boolarg? KX_TRUE: KX_FALSE); } #endif // WITH_PYTHON diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h index b505353c7cd..dc0aa4ce331 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.h +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h @@ -157,11 +157,10 @@ protected: bool PyArgToBool(int boolArg); /** Convert a a c++ value to KX_TRUE, KX_FALSE in Python. */ - PyObject* BoolToPyArg(bool); + PyObject *BoolToPyArg(bool); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; -#endif - +#endif /* __SCA_ILOGICBRICK_H__ */ diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp index b90952b2092..ab9e2781001 100644 --- a/source/gameengine/GameLogic/SCA_IObject.cpp +++ b/source/gameengine/GameLogic/SCA_IObject.cpp @@ -224,7 +224,7 @@ SCA_IController* SCA_IObject::FindController(const STR_String& controllername) { foundcontroller = (*itc); break; - } + } } return foundcontroller; } diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h index 0e657794195..0189af00322 100644 --- a/source/gameengine/GameLogic/SCA_IObject.h +++ b/source/gameengine/GameLogic/SCA_IObject.h @@ -43,7 +43,7 @@ class SCA_IController; class SCA_IActuator; #ifdef WITH_PYTHON -template T PyVecTo(PyObject*); +template T PyVecTo(PyObject *); #endif typedef std::vector SCA_SensorList; @@ -213,7 +213,7 @@ public: */ unsigned int GetState(void) { return m_state; } -// const class MT_Point3& ConvertPythonPylist(PyObject* pylist); +// const class MT_Point3& ConvertPythonPylist(PyObject *pylist); virtual int GetGameObjectType() {return -1;} @@ -225,5 +225,4 @@ public: }; -#endif //__SCA_IOBJECT_H__ - +#endif /* __SCA_IOBJECT_H__ */ diff --git a/source/gameengine/GameLogic/SCA_IScene.h b/source/gameengine/GameLogic/SCA_IScene.h index a399e313082..997266976ad 100644 --- a/source/gameengine/GameLogic/SCA_IScene.h +++ b/source/gameengine/GameLogic/SCA_IScene.h @@ -78,5 +78,4 @@ public: #endif }; -#endif //__SCA_ISCENE_H__ - +#endif /* __SCA_ISCENE_H__ */ diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index 76b9a8df00f..bfb78abef04 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -248,7 +248,7 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr) if (result) { // the sensor triggered this frame if (m_state || !m_tap) { - ActivateControllers(logicmgr); + ActivateControllers(logicmgr); // reset these counters so that pulse are synchronized with transition m_pos_ticks = 0; m_neg_ticks = 0; @@ -380,24 +380,24 @@ PyAttributeDef SCA_ISensor::Attributes[] = { }; -PyObject* SCA_ISensor::pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_ISensor::pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_ISensor* self= static_cast(self_v); + SCA_ISensor* self = static_cast(self_v); int retval = 0; if (SCA_PythonController::m_sCurrentController) retval = SCA_PythonController::m_sCurrentController->IsTriggered(self); return PyLong_FromSsize_t(retval); } -PyObject* SCA_ISensor::pyattr_get_positive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_ISensor::pyattr_get_positive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_ISensor* self= static_cast(self_v); + SCA_ISensor* self = static_cast(self_v); return PyLong_FromSsize_t(self->GetState()); } -PyObject* SCA_ISensor::pyattr_get_status(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_ISensor::pyattr_get_status(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_ISensor* self= static_cast(self_v); + SCA_ISensor* self = static_cast(self_v); int status = 0; if (self->GetState()) { @@ -417,21 +417,21 @@ PyObject* SCA_ISensor::pyattr_get_status(void *self_v, const KX_PYATTRIBUTE_DEF return PyLong_FromSsize_t(status); } -PyObject* SCA_ISensor::pyattr_get_posTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_ISensor::pyattr_get_posTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_ISensor* self= static_cast(self_v); + SCA_ISensor* self = static_cast(self_v); return PyLong_FromLong(self->GetPosTicks()); } -PyObject* SCA_ISensor::pyattr_get_negTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_ISensor::pyattr_get_negTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_ISensor* self= static_cast(self_v); + SCA_ISensor* self = static_cast(self_v); return PyLong_FromLong(self->GetNegTicks()); } int SCA_ISensor::pyattr_check_level(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_ISensor* self= static_cast(self_v); + SCA_ISensor* self = static_cast(self_v); if (self->m_level) self->m_tap = false; return 0; @@ -439,7 +439,7 @@ int SCA_ISensor::pyattr_check_level(void *self_v, const KX_PYATTRIBUTE_DEF *attr int SCA_ISensor::pyattr_check_tap(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_ISensor* self= static_cast(self_v); + SCA_ISensor* self = static_cast(self_v); if (self->m_tap) self->m_level = false; return 0; diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index 3bb29f3f0a2..091aa675741 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -212,8 +212,7 @@ public: KX_SENSOR_JUST_DEACTIVATED }; -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; -#endif //__SCA_ISENSOR_H__ - +#endif /* __SCA_ISENSOR_H__ */ diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index 2c6beb79fd3..0c4dcae16f7 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -60,7 +60,7 @@ SCA_JoystickSensor::SCA_JoystickSensor(class SCA_JoystickManager* eventmgr, m_joymode(joymode), m_joyindex(joyindex), m_bAllEvents(allevents) -{ +{ /* std::cout << " axis " << m_axis << std::endl; std::cout << " axis flag " << m_axisf << std::endl; @@ -113,21 +113,21 @@ bool SCA_JoystickSensor::Evaluate() return false; m_reset = false; - switch(m_joymode) - { - case KX_JOYSENSORMODE_AXIS: + + switch (m_joymode) { + case KX_JOYSENSORMODE_AXIS: { - /* what is what! - m_axisf == JOYAXIS_RIGHT, JOYAXIS_UP, JOYAXIS_DOWN, JOYAXIS_LEFT - m_axisf == 1 == up - m_axisf == 2 == left - m_axisf == 3 == down - - numberof== m_axis (1-4), range is half of JOYAXIS_MAX since - it assumes the axis joysticks are axis parirs (0,1), (2,3), etc - also note that this starts at 1 where functions its used - with expect a zero index. - */ + /* what is what! + * m_axisf == JOYAXIS_RIGHT, JOYAXIS_UP, JOYAXIS_DOWN, JOYAXIS_LEFT + * m_axisf == 1 == up + * m_axisf == 2 == left + * m_axisf == 3 == down + * + * numberof== m_axis (1-4), range is half of JOYAXIS_MAX since + * it assumes the axis joysticks are axis parirs (0,1), (2,3), etc + * also note that this starts at 1 where functions its used + * with expect a zero index. + */ if (!js->IsTrigAxis() && !reset) /* No events from SDL? - don't bother */ return false; @@ -159,7 +159,7 @@ bool SCA_JoystickSensor::Evaluate() } break; } - case KX_JOYSENSORMODE_AXIS_SINGLE: + case KX_JOYSENSORMODE_AXIS_SINGLE: { /* Like KX_JOYSENSORMODE_AXIS but don't pair up axis */ if (!js->IsTrigAxis() && !reset) /* No events from SDL? - don't bother */ @@ -179,12 +179,12 @@ bool SCA_JoystickSensor::Evaluate() } break; } - - case KX_JOYSENSORMODE_BUTTON: + + case KX_JOYSENSORMODE_BUTTON: { - /* what is what! - m_button = the actual button in question - */ + /* what is what! + * m_button = the actual button in question + */ if (!js->IsTrigButton() && !reset) /* No events from SDL? - don't bother */ return false; @@ -200,12 +200,12 @@ bool SCA_JoystickSensor::Evaluate() } break; } - case KX_JOYSENSORMODE_HAT: + case KX_JOYSENSORMODE_HAT: { - /* what is what! - numberof = m_hat -- max 4 - direction= m_hatf -- max 12 - */ + /* what is what! + * numberof = m_hat -- max 4 + * direction= m_hatf -- max 12 + */ if (!js->IsTrigHat() && !reset) /* No events from SDL? - don't bother */ return false; @@ -222,18 +222,19 @@ bool SCA_JoystickSensor::Evaluate() } break; } - /* test for ball anyone ?*/ - default: - printf("Error invalid switch statement\n"); - break; + /* test for ball anyone ?*/ + default: + printf("Error invalid switch statement\n"); + break; } - /* if not all events are enabled, only send a positive pulse when + /* if not all events are enabled, only send a positive pulse when * the button state changes */ if (!m_bAllEvents) { if (m_istrig_prev == m_istrig) { result = false; - } else { + } + else { m_istrig_prev = m_istrig; } } @@ -308,7 +309,7 @@ PyAttributeDef SCA_JoystickSensor::Attributes[] = { const char SCA_JoystickSensor::GetButtonActiveList_doc[] = "getButtonActiveList\n" "\tReturns a list containing the indices of the button currently pressed.\n"; -PyObject* SCA_JoystickSensor::PyGetButtonActiveList( ) +PyObject *SCA_JoystickSensor::PyGetButtonActiveList( ) { SCA_Joystick *joy = ((SCA_JoystickManager *)m_eventmgr)->GetJoystickDevice(m_joyindex); PyObject *ls = PyList_New(0); @@ -331,7 +332,7 @@ PyObject* SCA_JoystickSensor::PyGetButtonActiveList( ) const char SCA_JoystickSensor::GetButtonStatus_doc[] = "getButtonStatus(buttonIndex)\n" "\tReturns a bool of the current pressed state of the specified button.\n"; -PyObject* SCA_JoystickSensor::PyGetButtonStatus( PyObject* args ) +PyObject *SCA_JoystickSensor::PyGetButtonStatus( PyObject *args ) { SCA_Joystick *joy = ((SCA_JoystickManager *)m_eventmgr)->GetJoystickDevice(m_joyindex); int index; @@ -345,24 +346,24 @@ PyObject* SCA_JoystickSensor::PyGetButtonStatus( PyObject* args ) return PyBool_FromLong(0); } -PyObject* SCA_JoystickSensor::pyattr_get_axis_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_JoystickSensor::pyattr_get_axis_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_JoystickSensor* self= static_cast(self_v); + SCA_JoystickSensor* self = static_cast(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); int axis_index= joy->GetNumberOfAxes(); PyObject *list= PyList_New(axis_index); - while(axis_index--) { + while (axis_index--) { PyList_SET_ITEM(list, axis_index, PyLong_FromSsize_t(joy->GetAxisPosition(axis_index))); } return list; } -PyObject* SCA_JoystickSensor::pyattr_get_axis_single(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_JoystickSensor::pyattr_get_axis_single(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_JoystickSensor* self= static_cast(self_v); + SCA_JoystickSensor* self = static_cast(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); if (self->m_joymode != KX_JOYSENSORMODE_AXIS_SINGLE) { @@ -373,53 +374,53 @@ PyObject* SCA_JoystickSensor::pyattr_get_axis_single(void *self_v, const KX_PYAT return PyLong_FromSsize_t(joy->GetAxisPosition(self->m_axis-1)); } -PyObject* SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_JoystickSensor* self= static_cast(self_v); + SCA_JoystickSensor* self = static_cast(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); int hat_index= joy->GetNumberOfHats(); PyObject *list= PyList_New(hat_index); - while(hat_index--) { + while (hat_index--) { PyList_SET_ITEM(list, hat_index, PyLong_FromSsize_t(joy->GetHat(hat_index))); } return list; } -PyObject* SCA_JoystickSensor::pyattr_get_hat_single(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_JoystickSensor::pyattr_get_hat_single(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_JoystickSensor* self= static_cast(self_v); + SCA_JoystickSensor* self = static_cast(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); return PyLong_FromSsize_t(joy->GetHat(self->m_hat-1)); } -PyObject* SCA_JoystickSensor::pyattr_get_num_axis(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_JoystickSensor::pyattr_get_num_axis(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_JoystickSensor* self= static_cast(self_v); + SCA_JoystickSensor* self = static_cast(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); return PyLong_FromSsize_t( joy ? joy->GetNumberOfAxes() : 0 ); } -PyObject* SCA_JoystickSensor::pyattr_get_num_buttons(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_JoystickSensor::pyattr_get_num_buttons(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_JoystickSensor* self= static_cast(self_v); + SCA_JoystickSensor* self = static_cast(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); return PyLong_FromSsize_t( joy ? joy->GetNumberOfButtons() : 0 ); } -PyObject* SCA_JoystickSensor::pyattr_get_num_hats(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_JoystickSensor::pyattr_get_num_hats(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_JoystickSensor* self= static_cast(self_v); + SCA_JoystickSensor* self = static_cast(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); return PyLong_FromSsize_t( joy ? joy->GetNumberOfHats() : 0 ); } -PyObject* SCA_JoystickSensor::pyattr_get_connected(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_JoystickSensor::pyattr_get_connected(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_JoystickSensor* self= static_cast(self_v); + SCA_JoystickSensor* self = static_cast(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); return PyBool_FromLong( joy ? joy->Connected() : 0 ); } diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.h b/source/gameengine/GameLogic/SCA_JoystickSensor.h index 5dc35faf244..6c6dc019a5e 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.h +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.h @@ -30,11 +30,11 @@ */ -#ifndef __JOYSENSOR_H_ -#define __JOYSENSOR_H +#ifndef __JOYSENSOR_H__ +#define __JOYSENSOR_H__ #include "SCA_ISensor.h" -#include "./Joystick/SCA_JoystickDefines.h" +#include "Joystick/SCA_JoystickDefines.h" class SCA_JoystickSensor :public SCA_ISensor { @@ -161,8 +161,8 @@ public: return 0; } -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; -#endif +#endif /* __JOYSENSOR_H__ */ diff --git a/source/gameengine/GameLogic/SCA_KeyboardManager.h b/source/gameengine/GameLogic/SCA_KeyboardManager.h index 2d9ad45833f..cd1cbf4adee 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardManager.h +++ b/source/gameengine/GameLogic/SCA_KeyboardManager.h @@ -54,7 +54,7 @@ public: bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode); - virtual void NextFrame(); + virtual void NextFrame(); SCA_IInputDevice* GetInputDevice(); @@ -63,5 +63,4 @@ public: #endif }; -#endif //__SCA_KEYBOARDMANAGER_H__ - +#endif /* __SCA_KEYBOARDMANAGER_H__ */ diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index 5208252ceae..b3346270b61 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -225,37 +225,37 @@ bool SCA_KeyboardSensor::Evaluate() */ if (m_qual > 0) { const SCA_InputEvent & qualevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) m_qual); - switch(qualevent.m_status) { - case SCA_InputEvent::KX_NO_INPUTSTATUS: - qual = false; - break; - case SCA_InputEvent::KX_JUSTRELEASED: - qual_change = true; - qual = false; - break; - case SCA_InputEvent::KX_JUSTACTIVATED: - qual_change = true; - case SCA_InputEvent::KX_ACTIVE: - /* do nothing */ - break; + switch (qualevent.m_status) { + case SCA_InputEvent::KX_NO_INPUTSTATUS: + qual = false; + break; + case SCA_InputEvent::KX_JUSTRELEASED: + qual_change = true; + qual = false; + break; + case SCA_InputEvent::KX_JUSTACTIVATED: + qual_change = true; + case SCA_InputEvent::KX_ACTIVE: + /* do nothing */ + break; } } if (m_qual2 > 0 && qual==true) { const SCA_InputEvent & qualevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) m_qual2); /* copy of above */ - switch(qualevent.m_status) { - case SCA_InputEvent::KX_NO_INPUTSTATUS: - qual = false; - break; - case SCA_InputEvent::KX_JUSTRELEASED: - qual_change = true; - qual = false; - break; - case SCA_InputEvent::KX_JUSTACTIVATED: - qual_change = true; - case SCA_InputEvent::KX_ACTIVE: - /* do nothing */ - break; + switch (qualevent.m_status) { + case SCA_InputEvent::KX_NO_INPUTSTATUS: + qual = false; + break; + case SCA_InputEvent::KX_JUSTRELEASED: + qual_change = true; + qual = false; + break; + case SCA_InputEvent::KX_JUSTACTIVATED: + qual_change = true; + case SCA_InputEvent::KX_ACTIVE: + /* do nothing */ + break; } } /* done reading qualifiers */ @@ -351,12 +351,12 @@ void SCA_KeyboardSensor::AddToTargetProp(int keyIndex) CStringValue * newstringprop = new CStringValue(newprop, m_targetprop); GetParent()->SetProperty(m_targetprop, newstringprop); newstringprop->Release(); - } + } } else { /* append */ char pchar = ToCharacter(keyIndex, IsShifted()); STR_String newprop = tprop->GetText() + pchar; - CStringValue * newstringprop = new CStringValue(newprop, m_targetprop); + CStringValue * newstringprop = new CStringValue(newprop, m_targetprop); GetParent()->SetProperty(m_targetprop, newstringprop); newstringprop->Release(); } @@ -365,7 +365,7 @@ void SCA_KeyboardSensor::AddToTargetProp(int keyIndex) /* Make a new property. Deletes can be ignored. */ char pchar = ToCharacter(keyIndex, IsShifted()); STR_String newprop = pchar; - CStringValue * newstringprop = new CStringValue(newprop, m_targetprop); + CStringValue * newstringprop = new CStringValue(newprop, m_targetprop); GetParent()->SetProperty(m_targetprop, newstringprop); newstringprop->Release(); } @@ -376,7 +376,7 @@ void SCA_KeyboardSensor::AddToTargetProp(int keyIndex) /** * Tests whether shift is pressed - */ + */ bool SCA_KeyboardSensor::IsShifted(void) { SCA_IInputDevice* inputdev = ((SCA_KeyboardManager *)m_eventmgr)->GetInputDevice(); @@ -391,9 +391,10 @@ bool SCA_KeyboardSensor::IsShifted(void) == SCA_InputEvent::KX_JUSTACTIVATED) ) { return true; - } else { + } + else { return false; - } + } } void SCA_KeyboardSensor::LogKeystrokes(void) @@ -494,25 +495,25 @@ PyAttributeDef SCA_KeyboardSensor::Attributes[] = { }; -PyObject* SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_KeyboardSensor* self= static_cast(self_v); + SCA_KeyboardSensor* self = static_cast(self_v); SCA_IInputDevice* inputdev = ((SCA_KeyboardManager *)self->m_eventmgr)->GetInputDevice(); - PyObject* resultlist = PyList_New(0); + PyObject *resultlist = PyList_New(0); for (int i=SCA_IInputDevice::KX_BEGINKEY ; i<= SCA_IInputDevice::KX_ENDKEY;i++) { const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) i); if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) { - PyObject* keypair = PyList_New(2); + PyObject *keypair = PyList_New(2); PyList_SET_ITEM(keypair,0,PyLong_FromSsize_t(i)); PyList_SET_ITEM(keypair,1,PyLong_FromSsize_t(inevent.m_status)); PyList_Append(resultlist,keypair); } - } + } return resultlist; } @@ -655,7 +656,7 @@ bool IsPrintable(int keyIndex) /** * Tests whether this is a delete key. - */ + */ bool IsDelete(int keyIndex) { if ( (keyIndex == SCA_IInputDevice::KX_DELKEY) diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.h b/source/gameengine/GameLogic/SCA_KeyboardSensor.h index c059aba305b..c6610d0284e 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.h +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.h @@ -134,11 +134,8 @@ bool IsPrintable(int keyIndex); /** * Tests whether this is a delete key. - */ + */ bool IsDelete(int keyIndex); -#endif //__SCA_KEYBOARDSENSOR_H__ - - - +#endif /* __SCA_KEYBOARDSENSOR_H__ */ diff --git a/source/gameengine/GameLogic/SCA_LogicManager.h b/source/gameengine/GameLogic/SCA_LogicManager.h index 817f3a1c22a..690930196b3 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.h +++ b/source/gameengine/GameLogic/SCA_LogicManager.h @@ -31,8 +31,8 @@ #ifndef __SCA_LOGICMANAGER_H__ #define __SCA_LOGICMANAGER_H__ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable:4786) +#ifdef _MSC_VER +# pragma warning (disable:4786) #endif #include @@ -151,5 +151,4 @@ public: #endif }; -#endif //__SCA_LOGICMANAGER_H__ - +#endif /* __SCA_LOGICMANAGER_H__ */ diff --git a/source/gameengine/GameLogic/SCA_MouseManager.cpp b/source/gameengine/GameLogic/SCA_MouseManager.cpp index a067b9c4d5b..6d05b862c2d 100644 --- a/source/gameengine/GameLogic/SCA_MouseManager.cpp +++ b/source/gameengine/GameLogic/SCA_MouseManager.cpp @@ -34,10 +34,10 @@ */ -#if defined(WIN32) && !defined(FREE_WINDOWS) -// This warning tells us about truncation of __long__ stl-generated names. -// It can occasionally cause DevStudio to have internal compiler warnings. -#pragma warning( disable : 4786 ) +#ifdef _MSC_VER + /* This warning tells us about truncation of __long__ stl-generated names. + * It can occasionally cause DevStudio to have internal compiler warnings. */ +# pragma warning( disable:4786 ) #endif #include "BoolValue.h" diff --git a/source/gameengine/GameLogic/SCA_MouseManager.h b/source/gameengine/GameLogic/SCA_MouseManager.h index 60edb2816cb..a57e52070a7 100644 --- a/source/gameengine/GameLogic/SCA_MouseManager.h +++ b/source/gameengine/GameLogic/SCA_MouseManager.h @@ -63,7 +63,7 @@ public: * mouse related events. Can also flag mouse movement. */ bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode); - virtual void NextFrame(); + virtual void NextFrame(); SCA_IInputDevice* GetInputDevice(); @@ -72,5 +72,4 @@ public: #endif }; -#endif //__SCA_MOUSEMANAGER_H__ - +#endif /* __SCA_MOUSEMANAGER_H__ */ diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index f4ee54c56a6..51e0bc6550b 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -156,7 +156,7 @@ bool SCA_MouseSensor::Evaluate() case KX_MOUSESENSORMODE_WHEELDOWN: { const SCA_InputEvent& mevent = mousedev->GetEventValue(m_hotkey); - switch (mevent.m_status) { + switch (mevent.m_status) { case SCA_InputEvent::KX_JUSTACTIVATED: m_val = 1; result = true; @@ -189,15 +189,15 @@ bool SCA_MouseSensor::Evaluate() const SCA_InputEvent& eventY = mousedev->GetEventValue(SCA_IInputDevice::KX_MOUSEY); if (eventX.m_status == SCA_InputEvent::KX_JUSTACTIVATED || - eventY.m_status == SCA_InputEvent::KX_JUSTACTIVATED || - eventX.m_status == SCA_InputEvent::KX_ACTIVE || - eventY.m_status == SCA_InputEvent::KX_ACTIVE) + eventY.m_status == SCA_InputEvent::KX_JUSTACTIVATED || + eventX.m_status == SCA_InputEvent::KX_ACTIVE || + eventY.m_status == SCA_InputEvent::KX_ACTIVE) { m_val = 1; result = true; } else if (eventX.m_status == SCA_InputEvent::KX_JUSTRELEASED || - eventY.m_status == SCA_InputEvent::KX_JUSTRELEASED ) + eventY.m_status == SCA_InputEvent::KX_JUSTRELEASED ) { m_val = 0; result = true; diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.h b/source/gameengine/GameLogic/SCA_MouseSensor.h index d4eff371d4a..8d05a548681 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.h +++ b/source/gameengine/GameLogic/SCA_MouseSensor.h @@ -117,5 +117,4 @@ class SCA_MouseSensor : public SCA_ISensor #endif }; -#endif //__SCA_MOUSESENSOR_H__ - +#endif /* __SCA_MOUSESENSOR_H__ */ diff --git a/source/gameengine/GameLogic/SCA_NANDController.h b/source/gameengine/GameLogic/SCA_NANDController.h index 040df7f0ade..a3f02908dd2 100644 --- a/source/gameengine/GameLogic/SCA_NANDController.h +++ b/source/gameengine/GameLogic/SCA_NANDController.h @@ -49,5 +49,4 @@ public: /* --------------------------------------------------------------------- */ }; -#endif //__SCA_NANDCONTROLLER_H__ - +#endif /* __SCA_NANDCONTROLLER_H__ */ diff --git a/source/gameengine/GameLogic/SCA_NORController.h b/source/gameengine/GameLogic/SCA_NORController.h index 1630f8055ec..ec8159de8d1 100644 --- a/source/gameengine/GameLogic/SCA_NORController.h +++ b/source/gameengine/GameLogic/SCA_NORController.h @@ -45,5 +45,4 @@ public: virtual void Trigger(SCA_LogicManager* logicmgr); }; -#endif //__SCA_NORCONTROLLER_H__ - +#endif /* __SCA_NORCONTROLLER_H__ */ diff --git a/source/gameengine/GameLogic/SCA_ORController.h b/source/gameengine/GameLogic/SCA_ORController.h index 9a4e4c7398d..9499c893c72 100644 --- a/source/gameengine/GameLogic/SCA_ORController.h +++ b/source/gameengine/GameLogic/SCA_ORController.h @@ -46,5 +46,4 @@ public: virtual void Trigger(SCA_LogicManager* logicmgr); }; -#endif //__SCA_ORCONTROLLER_H__ - +#endif /* __SCA_ORCONTROLLER_H__ */ diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp index 31f988fe4b9..0eab6187d07 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp @@ -173,7 +173,7 @@ isValid( SCA_PropertyActuator::KX_ACT_PROP_MODE mode ) { - bool res = false; + bool res = false; res = ((mode > KX_ACT_PROP_NODEF) && (mode < KX_ACT_PROP_MAX)); return res; } diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.h b/source/gameengine/GameLogic/SCA_PropertyActuator.h index e465098131e..83a6d05df1b 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.h +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.h @@ -86,5 +86,4 @@ public: }; -#endif //__KX_PROPERTYACTUATOR_DOC - +#endif /* __KX_PROPERTYACTUATOR_DOC */ diff --git a/source/gameengine/GameLogic/SCA_PropertyEventManager.h b/source/gameengine/GameLogic/SCA_PropertyEventManager.h index 7a4ec750484..554fe686df2 100644 --- a/source/gameengine/GameLogic/SCA_PropertyEventManager.h +++ b/source/gameengine/GameLogic/SCA_PropertyEventManager.h @@ -52,5 +52,4 @@ public: #endif }; -#endif //__SCA_PROPERTYEVENTMANAGER_H__ - +#endif /* __SCA_PROPERTYEVENTMANAGER_H__ */ diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index ab7f57a5454..ece9d7b6c8f 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -179,7 +179,7 @@ int SCA_PythonController::IsTriggered(class SCA_ISensor* sensor) #ifdef WITH_PYTHON /* warning, self is not the SCA_PythonController, its a PyObjectPlus_Proxy */ -PyObject* SCA_PythonController::sPyGetCurrentController(PyObject *self) +PyObject *SCA_PythonController::sPyGetCurrentController(PyObject *self) { if (m_sCurrentController==NULL) { @@ -271,7 +271,7 @@ void SCA_PythonController::ErrorPrint(const char *error_msg) } bool SCA_PythonController::Compile() -{ +{ //printf("py script modified '%s'\n", m_scriptName.Ptr()); m_bModified= false; @@ -374,66 +374,65 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) m_sCurrentLogicManager = logicmgr; PyObject *excdict= NULL; - PyObject* resultobj= NULL; + PyObject *resultobj= NULL; - switch(m_mode) { - case SCA_PYEXEC_SCRIPT: - { - if (m_bModified) - if (Compile()==false) // sets m_bModified to false + switch (m_mode) { + case SCA_PYEXEC_SCRIPT: + { + if (m_bModified) + if (Compile()==false) // sets m_bModified to false + return; + if (!m_bytecode) return; - if (!m_bytecode) - return; - - /* - * This part here with excdict is a temporary patch - * to avoid python/gameengine crashes when python - * inadvertently holds references to game objects - * in global variables. - * - * The idea is always make a fresh dictionary, and - * destroy it right after it is used to make sure - * python won't hold any gameobject references. - * - * Note that the PyDict_Clear _is_ necessary before - * the Py_DECREF() because it is possible for the - * variables inside the dictionary to hold references - * to the dictionary (ie. generate a cycle), so we - * break it by hand, then DECREF (which in this case - * should always ensure excdict is cleared). - */ - excdict= PyDict_Copy(m_pythondictionary); + /* + * This part here with excdict is a temporary patch + * to avoid python/gameengine crashes when python + * inadvertently holds references to game objects + * in global variables. + * + * The idea is always make a fresh dictionary, and + * destroy it right after it is used to make sure + * python won't hold any gameobject references. + * + * Note that the PyDict_Clear _is_ necessary before + * the Py_DECREF() because it is possible for the + * variables inside the dictionary to hold references + * to the dictionary (ie. generate a cycle), so we + * break it by hand, then DECREF (which in this case + * should always ensure excdict is cleared). + */ - resultobj = PyEval_EvalCode((PyObject *)m_bytecode, excdict, excdict); + excdict= PyDict_Copy(m_pythondictionary); - /* PyRun_SimpleString(m_scriptText.Ptr()); */ - break; - } - case SCA_PYEXEC_MODULE: - { - if (m_bModified || m_debug) - if (Import()==false) // sets m_bModified to false - return; - if (!m_function) - return; - - PyObject *args= NULL; - - if (m_function_argc==1) { - args = PyTuple_New(1); - PyTuple_SET_ITEM(args, 0, GetProxy()); + resultobj = PyEval_EvalCode((PyObject *)m_bytecode, excdict, excdict); + + /* PyRun_SimpleString(m_scriptText.Ptr()); */ + break; } - - resultobj = PyObject_CallObject(m_function, args); - Py_XDECREF(args); - break; - } - + case SCA_PYEXEC_MODULE: + { + if (m_bModified || m_debug) + if (Import()==false) // sets m_bModified to false + return; + if (!m_function) + return; + + PyObject *args= NULL; + + if (m_function_argc==1) { + args = PyTuple_New(1); + PyTuple_SET_ITEM(args, 0, GetProxy()); + } + + resultobj = PyObject_CallObject(m_function, args); + Py_XDECREF(args); + break; + } + } /* end switch */ - - - + + /* Free the return value and print the error */ if (resultobj) Py_DECREF(resultobj); @@ -447,13 +446,13 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) // This doesn't appear to be needed anymore //PyDict_Clear(excdict); Py_DECREF(excdict); - } + } m_triggeredSensors.clear(); m_sCurrentController = NULL; } -PyObject* SCA_PythonController::PyActivate(PyObject *value) +PyObject *SCA_PythonController::PyActivate(PyObject *value) { if (m_sCurrentController != this) { PyErr_SetString(PyExc_SystemError, "Cannot add an actuator from a non-active controller"); @@ -468,7 +467,7 @@ PyObject* SCA_PythonController::PyActivate(PyObject *value) Py_RETURN_NONE; } -PyObject* SCA_PythonController::PyDeActivate(PyObject *value) +PyObject *SCA_PythonController::PyDeActivate(PyObject *value) { if (m_sCurrentController != this) { PyErr_SetString(PyExc_SystemError, "Cannot add an actuator from a non-active controller"); @@ -483,12 +482,12 @@ PyObject* SCA_PythonController::PyDeActivate(PyObject *value) Py_RETURN_NONE; } -PyObject* SCA_PythonController::pyattr_get_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_PythonController::pyattr_get_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - //SCA_PythonController* self= static_cast(static_cast(static_cast(static_cast(static_cast(self_v))))); + //SCA_PythonController* self = static_cast(static_cast(static_cast(static_cast(static_cast(self_v))))); // static_cast(dynamic_cast(obj)) - static_cast(obj) - SCA_PythonController* self= static_cast(self_v); + SCA_PythonController* self = static_cast(self_v); return PyUnicode_From_STR_String(self->m_scriptText); } @@ -496,7 +495,7 @@ PyObject* SCA_PythonController::pyattr_get_script(void *self_v, const KX_PYATTRI int SCA_PythonController::pyattr_set_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - SCA_PythonController* self= static_cast(self_v); + SCA_PythonController* self = static_cast(self_v); const char *scriptArg = _PyUnicode_AsString(value); diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h index ccdb82aa722..f1f10d22711 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.h +++ b/source/gameengine/GameLogic/SCA_PythonController.h @@ -74,7 +74,7 @@ class SCA_PythonController : public SCA_IController //for debugging //virtual CValue* AddRef(); - //virtual int Release(); // Release a reference to this value (when reference count reaches 0, the value is removed from the heap) + //virtual int Release(); // Release a reference to this value (when reference count reaches 0, the value is removed from the heap) SCA_PythonController(SCA_IObject* gameobj, int mode); virtual ~SCA_PythonController(); @@ -96,11 +96,11 @@ class SCA_PythonController : public SCA_IController void ErrorPrint(const char *error_msg); #ifdef WITH_PYTHON - static const char* sPyGetCurrentController__doc__; - static PyObject* sPyGetCurrentController(PyObject* self); - static const char* sPyAddActiveActuator__doc__; - static PyObject* sPyAddActiveActuator(PyObject* self, - PyObject* args); + static const char *sPyGetCurrentController__doc__; + static PyObject *sPyGetCurrentController(PyObject *self); + static const char *sPyAddActiveActuator__doc__; + static PyObject *sPyAddActiveActuator(PyObject *self, + PyObject *args); static SCA_IActuator* LinkedActuatorFromPy(PyObject *value); @@ -115,5 +115,4 @@ class SCA_PythonController : public SCA_IController #endif }; -#endif //__SCA_PYTHONCONTROLLER_H__ - +#endif /* __SCA_PYTHONCONTROLLER_H__ */ diff --git a/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp b/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp index f83b23f510c..42cda9433b8 100644 --- a/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp +++ b/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp @@ -58,13 +58,13 @@ SCA_PythonKeyboard::~SCA_PythonKeyboard() /* ------------------------------------------------------------------------- */ /* clipboard */ -static PyObject* gPyGetClipboard(PyObject* args, PyObject* kwds) +static PyObject *gPyGetClipboard(PyObject *args, PyObject *kwds) { char *buf = (char *)GHOST_getClipboard(0); return PyUnicode_FromString(buf?buf:""); } -static PyObject* gPySetClipboard(PyObject* args, PyObject* value) +static PyObject *gPySetClipboard(PyObject *args, PyObject *value) { char* buf; if (!PyArg_ParseTuple(value,"s:setClipboard",&buf)) @@ -109,7 +109,7 @@ PyAttributeDef SCA_PythonKeyboard::Attributes[] = { { NULL } //Sentinel }; -PyObject* SCA_PythonKeyboard::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_PythonKeyboard::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_PythonKeyboard* self = static_cast(self_v); @@ -123,7 +123,7 @@ PyObject* SCA_PythonKeyboard::pyattr_get_events(void *self_v, const KX_PYATTRIBU return self->m_event_dict; } -PyObject* SCA_PythonKeyboard::pyattr_get_active_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_PythonKeyboard::pyattr_get_active_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_PythonKeyboard* self = static_cast(self_v); diff --git a/source/gameengine/GameLogic/SCA_PythonKeyboard.h b/source/gameengine/GameLogic/SCA_PythonKeyboard.h index df5e46f8c28..53068f38e6a 100644 --- a/source/gameengine/GameLogic/SCA_PythonKeyboard.h +++ b/source/gameengine/GameLogic/SCA_PythonKeyboard.h @@ -35,7 +35,7 @@ class SCA_PythonKeyboard : public PyObjectPlus private: class SCA_IInputDevice *m_keyboard; #ifdef WITH_PYTHON - PyObject* m_event_dict; + PyObject *m_event_dict; #endif public: SCA_PythonKeyboard(class SCA_IInputDevice* keyboard); @@ -47,5 +47,4 @@ public: #endif }; -#endif //__SCA_PYTHONKEYBOARD_H__ - +#endif /* __SCA_PYTHONKEYBOARD_H__ */ diff --git a/source/gameengine/GameLogic/SCA_PythonMouse.cpp b/source/gameengine/GameLogic/SCA_PythonMouse.cpp index cdbeaba2235..0806bda072b 100644 --- a/source/gameengine/GameLogic/SCA_PythonMouse.cpp +++ b/source/gameengine/GameLogic/SCA_PythonMouse.cpp @@ -90,9 +90,9 @@ PyAttributeDef SCA_PythonMouse::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("position", SCA_PythonMouse, pyattr_get_position, pyattr_set_position), KX_PYATTRIBUTE_RW_FUNCTION("visible", SCA_PythonMouse, pyattr_get_visible, pyattr_set_visible), { NULL } //Sentinel -}; +}; -PyObject* SCA_PythonMouse::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_PythonMouse::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_PythonMouse* self = static_cast(self_v); @@ -106,7 +106,7 @@ PyObject* SCA_PythonMouse::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_ return self->m_event_dict; } -PyObject* SCA_PythonMouse::pyattr_get_active_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_PythonMouse::pyattr_get_active_events(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_PythonMouse* self = static_cast(self_v); @@ -123,7 +123,7 @@ PyObject* SCA_PythonMouse::pyattr_get_active_events(void *self_v, const KX_PYATT return self->m_event_dict; } -PyObject* SCA_PythonMouse::pyattr_get_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_PythonMouse::pyattr_get_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_PythonMouse* self = static_cast(self_v); const SCA_InputEvent & xevent = self->m_mouse->GetEventValue(SCA_IInputDevice::KX_MOUSEX); @@ -134,7 +134,7 @@ PyObject* SCA_PythonMouse::pyattr_get_position(void *self_v, const KX_PYATTRIBUT x_coord = self->m_canvas->GetMouseNormalizedX(xevent.m_eventval); y_coord = self->m_canvas->GetMouseNormalizedY(yevent.m_eventval); - PyObject* ret = PyTuple_New(2); + PyObject *ret = PyTuple_New(2); PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(x_coord)); PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(y_coord)); @@ -158,7 +158,7 @@ int SCA_PythonMouse::pyattr_set_position(void *self_v, const KX_PYATTRIBUTE_DEF return PY_SET_ATTR_SUCCESS; } -PyObject* SCA_PythonMouse::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_PythonMouse::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_PythonMouse* self = static_cast(self_v); diff --git a/source/gameengine/GameLogic/SCA_PythonMouse.h b/source/gameengine/GameLogic/SCA_PythonMouse.h index 1313d55005f..bc6e65f07a8 100644 --- a/source/gameengine/GameLogic/SCA_PythonMouse.h +++ b/source/gameengine/GameLogic/SCA_PythonMouse.h @@ -36,7 +36,7 @@ private: class SCA_IInputDevice *m_mouse; class RAS_ICanvas *m_canvas; #ifdef WITH_PYTHON - PyObject* m_event_dict; + PyObject *m_event_dict; #endif public: SCA_PythonMouse(class SCA_IInputDevice* mouse, class RAS_ICanvas* canvas); @@ -47,14 +47,13 @@ public: #ifdef WITH_PYTHON KX_PYMETHOD_DOC(SCA_PythonMouse, show); - static PyObject* pyattr_get_events(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_active_events(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_position(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static int pyattr_set_position(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value); - static PyObject* pyattr_get_visible(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static int pyattr_set_visible(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value); + static PyObject *pyattr_get_events(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_active_events(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_position(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_position(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_visible(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_visible(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); #endif }; -#endif //__SCA_PYTHONMOUSE_H__ - +#endif /* __SCA_PYTHONMOUSE_H__ */ diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp index c727eebd015..2d51a45fe55 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp @@ -48,13 +48,13 @@ /* ------------------------------------------------------------------------- */ SCA_RandomActuator::SCA_RandomActuator(SCA_IObject *gameobj, - long seed, - SCA_RandomActuator::KX_RANDOMACT_MODE mode, - float para1, - float para2, - const STR_String &propName) - : SCA_IActuator(gameobj, KX_ACT_RANDOM), - m_propname(propName), + long seed, + SCA_RandomActuator::KX_RANDOMACT_MODE mode, + float para1, + float para2, + const STR_String &propName) + : SCA_IActuator(gameobj, KX_ACT_RANDOM), + m_propname(propName), m_parameter1(para1), m_parameter2(para2), m_distribution(mode) @@ -161,7 +161,7 @@ bool SCA_RandomActuator::Update() while (b >= a) { b = b * m_base->DrawFloat(); res++; - }; + }; tmpval = new CIntValue(res); } break; @@ -196,33 +196,30 @@ bool SCA_RandomActuator::Update() */ tmpval = new CFloatValue(m_parameter1); - } else { - /* - - 070301 - nzc - Now, with seed != 0, we will most assuredly get some - sensible values. The termination condition states two - things: - 1. s >= 0 is not allowed: to prevent the distro from - getting a bias towards high values. This is a small - correction, really, and might also be left out. - 2. s == 0 is not allowed: to prevent a division by zero - when renormalising the drawn value to the desired - distribution shape. As a side effect, the distro will - never yield the exact mean. - I am not sure whether this is consistent, since the error - cause by #2 is of the same magnitude as the one - prevented by #1. The error introduced into the SD will be - improved, though. By how much? Hard to say... If you like - the maths, feel free to analyse. Be aware that this is - one of the really old standard algorithms. I think the - original came in Fortran, was translated to Pascal, and - then someone came up with the C code. My guess it that - this will be quite sufficient here. - + } + else { + /* 070301 - nzc + * Now, with seed != 0, we will most assuredly get some + * sensible values. The termination condition states two + * things: + * 1. s >= 0 is not allowed: to prevent the distro from + * getting a bias towards high values. This is a small + * correction, really, and might also be left out. + * 2. s == 0 is not allowed: to prevent a division by zero + * when renormalising the drawn value to the desired + * distribution shape. As a side effect, the distro will + * never yield the exact mean. + * I am not sure whether this is consistent, since the error + * cause by #2 is of the same magnitude as the one + * prevented by #1. The error introduced into the SD will be + * improved, though. By how much? Hard to say... If you like + * the maths, feel free to analyse. Be aware that this is + * one of the really old standard algorithms. I think the + * original came in Fortran, was translated to Pascal, and + * then someone came up with the C code. My guess it that + * this will be quite sufficient here. */ - do - { + do { x = 2.0 * m_base->DrawFloat() - 1.0; y = 2.0 * m_base->DrawFloat() - 1.0; s = x*x + y*y; @@ -361,9 +358,9 @@ PyAttributeDef SCA_RandomActuator::Attributes[] = { KX_PYATTRIBUTE_STRING_RW_CHECK("propName",0,MAX_PROP_NAME,false,SCA_RandomActuator,m_propname,CheckProperty), KX_PYATTRIBUTE_RW_FUNCTION("seed",SCA_RandomActuator,pyattr_get_seed,pyattr_set_seed), { NULL } //Sentinel -}; +}; -PyObject* SCA_RandomActuator::pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_RandomActuator::pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { SCA_RandomActuator* act = static_cast(self); return PyLong_FromSsize_t(act->m_base->GetSeed()); @@ -420,7 +417,7 @@ KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setBoolBernouilli, } m_distribution = KX_RANDOMACT_BOOL_BERNOUILLI; - m_parameter1 = paraArg; + m_parameter1 = paraArg; enforceConstraints(); Py_RETURN_NONE; } @@ -473,7 +470,7 @@ KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setIntPoisson, } m_distribution = KX_RANDOMACT_INT_POISSON; - m_parameter1 = paraArg; + m_parameter1 = paraArg; enforceConstraints(); Py_RETURN_NONE; } @@ -489,7 +486,7 @@ KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setFloatConst, } m_distribution = KX_RANDOMACT_FLOAT_CONST; - m_parameter1 = paraArg; + m_parameter1 = paraArg; enforceConstraints(); Py_RETURN_NONE; } @@ -544,7 +541,7 @@ KX_PYMETHODDEF_DOC_VARARGS(SCA_RandomActuator, setFloatNegativeExponential, } m_distribution = KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL; - m_parameter1 = paraArg; + m_parameter1 = paraArg; enforceConstraints(); Py_RETURN_NONE; } diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.h b/source/gameengine/GameLogic/SCA_RandomActuator.h index 522663651e0..32b29fc4f43 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.h +++ b/source/gameengine/GameLogic/SCA_RandomActuator.h @@ -67,10 +67,10 @@ class SCA_RandomActuator : public SCA_IActuator KX_RANDOMACT_NODEF, KX_RANDOMACT_BOOL_CONST, KX_RANDOMACT_BOOL_UNIFORM, - KX_RANDOMACT_BOOL_BERNOUILLI, + KX_RANDOMACT_BOOL_BERNOUILLI, KX_RANDOMACT_INT_CONST, KX_RANDOMACT_INT_UNIFORM, - KX_RANDOMACT_INT_POISSON, + KX_RANDOMACT_INT_POISSON, KX_RANDOMACT_FLOAT_CONST, KX_RANDOMACT_FLOAT_UNIFORM, KX_RANDOMACT_FLOAT_NORMAL, @@ -98,7 +98,7 @@ class SCA_RandomActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - static PyObject* pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); KX_PYMETHOD_DOC_VARARGS(SCA_RandomActuator, setBoolConst); @@ -112,7 +112,7 @@ class SCA_RandomActuator : public SCA_IActuator KX_PYMETHOD_DOC_VARARGS(SCA_RandomActuator, setFloatNormal); KX_PYMETHOD_DOC_VARARGS(SCA_RandomActuator, setFloatNegativeExponential); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; /* end of class KX_EditObjectActuator : public SCA_PropertyActuator */ diff --git a/source/gameengine/GameLogic/SCA_RandomEventManager.h b/source/gameengine/GameLogic/SCA_RandomEventManager.h index b46899b1355..2d83c5fcdca 100644 --- a/source/gameengine/GameLogic/SCA_RandomEventManager.h +++ b/source/gameengine/GameLogic/SCA_RandomEventManager.h @@ -51,5 +51,4 @@ public: #endif }; -#endif //__SCA_RANDOMEVENTMANAGER_H__ - +#endif /* __SCA_RANDOMEVENTMANAGER_H__ */ diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp index 3b37507dcf3..7199ee6cf22 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp +++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp @@ -165,15 +165,15 @@ PyAttributeDef SCA_RandomSensor::Attributes[] = { {NULL} //Sentinel }; -PyObject* SCA_RandomSensor::pyattr_get_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *SCA_RandomSensor::pyattr_get_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - SCA_RandomSensor* self= static_cast(self_v); + SCA_RandomSensor* self = static_cast(self_v); return PyLong_FromSsize_t(self->m_basegenerator->GetSeed()); } int SCA_RandomSensor::pyattr_set_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - SCA_RandomSensor* self= static_cast(self_v); + SCA_RandomSensor* self = static_cast(self_v); if (!PyLong_Check(value)) { PyErr_SetString(PyExc_TypeError, "sensor.seed = int: Random Sensor, expected an integer"); return PY_SET_ATTR_FAIL; diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.h b/source/gameengine/GameLogic/SCA_RandomSensor.h index 008445ef878..628562b77e6 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.h +++ b/source/gameengine/GameLogic/SCA_RandomSensor.h @@ -68,5 +68,4 @@ public: #endif }; -#endif //__SCA_RANDOMSENSOR_H__ - +#endif /* __SCA_RANDOMSENSOR_H__ */ diff --git a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp index e28f00abba2..5aa6fdc8625 100644 --- a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp @@ -29,11 +29,10 @@ * \ingroup gamelogic */ - -#if defined(WIN32) && !defined(FREE_WINDOWS) -// This warning tells us about truncation of __long__ stl-generated names. -// It can occasionally cause DevStudio to have internal compiler warnings. -#pragma warning( disable : 4786 ) +#ifdef _MSC_VER + /* This warning tells us about truncation of __long__ stl-generated names. + * It can occasionally cause DevStudio to have internal compiler warnings. */ +# pragma warning(disable:4786) #endif #include "SCA_TimeEventManager.h" @@ -54,7 +53,7 @@ SCA_TimeEventManager::~SCA_TimeEventManager() !(it == m_timevalues.end()); ++it) { (*it)->Release(); - } + } } diff --git a/source/gameengine/GameLogic/SCA_TimeEventManager.h b/source/gameengine/GameLogic/SCA_TimeEventManager.h index 092cf016370..4c929dca23c 100644 --- a/source/gameengine/GameLogic/SCA_TimeEventManager.h +++ b/source/gameengine/GameLogic/SCA_TimeEventManager.h @@ -59,5 +59,4 @@ public: #endif }; -#endif //__SCA_TIMEEVENTMANAGER_H__ - +#endif /* __SCA_TIMEEVENTMANAGER_H__ */ diff --git a/source/gameengine/GameLogic/SCA_XNORController.h b/source/gameengine/GameLogic/SCA_XNORController.h index 5ef4dc67cf2..c257b71273e 100644 --- a/source/gameengine/GameLogic/SCA_XNORController.h +++ b/source/gameengine/GameLogic/SCA_XNORController.h @@ -50,5 +50,4 @@ public: }; -#endif //__SCA_XNORCONTROLLER_H__ - +#endif /* __SCA_XNORCONTROLLER_H__ */ diff --git a/source/gameengine/GameLogic/SCA_XORController.h b/source/gameengine/GameLogic/SCA_XORController.h index 56cd2440863..c64a3380ede 100644 --- a/source/gameengine/GameLogic/SCA_XORController.h +++ b/source/gameengine/GameLogic/SCA_XORController.h @@ -45,5 +45,4 @@ public: virtual void Trigger(SCA_LogicManager* logicmgr); }; -#endif //__SCA_XORCONTROLLER_H__ - +#endif /* __SCA_XORCONTROLLER_H__ */ diff --git a/source/gameengine/GamePlayer/CMakeLists.txt b/source/gameengine/GamePlayer/CMakeLists.txt index cdf3f826ea9..e1a26668d11 100644 --- a/source/gameengine/GamePlayer/CMakeLists.txt +++ b/source/gameengine/GamePlayer/CMakeLists.txt @@ -26,6 +26,6 @@ add_subdirectory(common) add_subdirectory(ghost) -if(WITH_WEBPLUGIN) +if(WITH_WEBPLUGIN) add_subdirectory(xembed) endif() diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.cpp b/source/gameengine/GamePlayer/common/GPC_Canvas.cpp index f4224b9e255..b5c1c29238a 100644 --- a/source/gameengine/GamePlayer/common/GPC_Canvas.cpp +++ b/source/gameengine/GamePlayer/common/GPC_Canvas.cpp @@ -57,6 +57,8 @@ GPC_Canvas::GPC_Canvas( m_displayarea.m_y1 = 0; m_displayarea.m_x2 = width; m_displayarea.m_y2 = height; + + glGetIntegerv(GL_VIEWPORT, (GLint*)m_viewport); } @@ -99,7 +101,7 @@ void GPC_Canvas::Resize(int width, int height) void GPC_Canvas::EndFrame() { if (m_bannersEnabled) - DrawAllBanners(); + DrawAllBanners(); } @@ -121,11 +123,31 @@ void GPC_Canvas::SetViewPort(int x1, int y1, int x2, int y2) * whole canvas/rendertools mess. */ glEnable(GL_SCISSOR_TEST); + + m_viewport[0] = x1; + m_viewport[1] = y1; + m_viewport[2] = x2-x1 + 1; + m_viewport[3] = y2-y1 + 1; glViewport(x1,y1,x2-x1 + 1,y2-y1 + 1); glScissor(x1,y1,x2-x1 + 1,y2-y1 + 1); }; +const int *GPC_Canvas::GetViewPort() +{ +#ifdef DEBUG + // If we're in a debug build, we might as well make sure our values don't differ + // from what the gpu thinks we have. This could lead to nasty, hard to find bugs. + int viewport[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + assert(viewport[0] == m_viewport[0]); + assert(viewport[1] == m_viewport[1]); + assert(viewport[2] == m_viewport[2]); + assert(viewport[3] == m_viewport[3]); +#endif + + return m_viewport; +} void GPC_Canvas::ClearBuffer( int type diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.h b/source/gameengine/GamePlayer/common/GPC_Canvas.h index 25a50fbcac3..ec5375c0e13 100644 --- a/source/gameengine/GamePlayer/common/GPC_Canvas.h +++ b/source/gameengine/GamePlayer/common/GPC_Canvas.h @@ -38,7 +38,7 @@ #ifdef WIN32 #pragma warning (disable:4786) // suppress stl-MSVC debug info warning #include -#endif // WIN32 +#endif /* WIN32 */ #include "GL/glew.h" @@ -90,6 +90,8 @@ protected: * relative to the context */ RAS_Rect m_displayarea; + int m_viewport[4]; + /** Storage for the banners to display. */ TBannerMap m_banners; /** State of banner display. */ @@ -153,6 +155,7 @@ public: ); void SetViewPort(int x1, int y1, int x2, int y2); + const int *GetViewPort(); void ClearColor(float r, float g, float b, float a); @@ -163,7 +166,7 @@ public: void SetMouseState(RAS_MouseState mousestate) { - // not yet + // not yet } void SetMousePosition(int x, int y) @@ -250,7 +253,7 @@ protected: int oldWriteMask; }; - void + void PushRenderState( CanvasRenderState & render_state ); @@ -270,5 +273,4 @@ protected: static TBannerId s_bannerId; }; -#endif // __GPC_CANVAS_H__ - +#endif /* __GPC_CANVAS_H__ */ diff --git a/source/gameengine/GamePlayer/common/GPC_Engine.h b/source/gameengine/GamePlayer/common/GPC_Engine.h index 60f0d2af199..6247bd630bb 100644 --- a/source/gameengine/GamePlayer/common/GPC_Engine.h +++ b/source/gameengine/GamePlayer/common/GPC_Engine.h @@ -121,5 +121,4 @@ private: }; -#endif // __GPC_ENGINE_H__ - +#endif /* __GPC_ENGINE_H__ */ diff --git a/source/gameengine/GamePlayer/common/GPC_KeyboardDevice.h b/source/gameengine/GamePlayer/common/GPC_KeyboardDevice.h index 63e051dd1d4..c082bc1b82f 100644 --- a/source/gameengine/GamePlayer/common/GPC_KeyboardDevice.h +++ b/source/gameengine/GamePlayer/common/GPC_KeyboardDevice.h @@ -33,8 +33,8 @@ #define __GPC_KEYBOARDDEVICE_H__ #ifdef WIN32 -#pragma warning (disable : 4786) -#endif // WIN32 +#pragma warning (disable:4786) +#endif /* WIN32 */ #include "SCA_IInputDevice.h" @@ -87,5 +87,4 @@ public: virtual void HookEscape(); }; -#endif // _GPC_KEYBOARDDEVICE_H - +#endif /* __GPC_KEYBOARDDEVICE_H__ */ diff --git a/source/gameengine/GamePlayer/common/GPC_MouseDevice.cpp b/source/gameengine/GamePlayer/common/GPC_MouseDevice.cpp index a38bba7788b..e38a9e3d6cb 100644 --- a/source/gameengine/GamePlayer/common/GPC_MouseDevice.cpp +++ b/source/gameengine/GamePlayer/common/GPC_MouseDevice.cpp @@ -67,7 +67,8 @@ void GPC_MouseDevice::NextFrame() for (int mouseevent= KX_BEGINMOUSE; mouseevent< KX_ENDMOUSEBUTTONS; mouseevent++) { SCA_InputEvent& oldevent = m_eventStatusTables[previousTable][mouseevent]; if (oldevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED || - oldevent.m_status == SCA_InputEvent::KX_ACTIVE) { + oldevent.m_status == SCA_InputEvent::KX_ACTIVE) + { m_eventStatusTables[m_currentTable][mouseevent] = oldevent; m_eventStatusTables[m_currentTable][mouseevent].m_status = SCA_InputEvent::KX_ACTIVE; } @@ -76,7 +77,8 @@ void GPC_MouseDevice::NextFrame() SCA_InputEvent& oldevent = m_eventStatusTables[previousTable][mousemove]; m_eventStatusTables[m_currentTable][mousemove] = oldevent; if (oldevent.m_status == SCA_InputEvent::KX_JUSTACTIVATED || - oldevent.m_status == SCA_InputEvent::KX_ACTIVE) { + oldevent.m_status == SCA_InputEvent::KX_ACTIVE) + { m_eventStatusTables[m_currentTable][mousemove].m_status = SCA_InputEvent::KX_JUSTRELEASED; } else { diff --git a/source/gameengine/GamePlayer/common/GPC_MouseDevice.h b/source/gameengine/GamePlayer/common/GPC_MouseDevice.h index 2db1b1ec34c..b092fbd21dd 100644 --- a/source/gameengine/GamePlayer/common/GPC_MouseDevice.h +++ b/source/gameengine/GamePlayer/common/GPC_MouseDevice.h @@ -33,8 +33,8 @@ #define __GPC_MOUSEDEVICE_H__ #ifdef WIN32 -#pragma warning (disable : 4786) -#endif // WIN32 +#pragma warning (disable:4786) +#endif /* WIN32 */ #include "SCA_IInputDevice.h" @@ -102,5 +102,4 @@ protected: virtual bool ConvertEvent(KX_EnumInputs kxevent, int eventval); }; -#endif // __GPC_MOUSEDEVICE_H__ - +#endif /* __GPC_MOUSEDEVICE_H__ */ diff --git a/source/gameengine/GamePlayer/common/GPC_RawImage.cpp b/source/gameengine/GamePlayer/common/GPC_RawImage.cpp index 9f129c1cdfb..c0d66541800 100644 --- a/source/gameengine/GamePlayer/common/GPC_RawImage.cpp +++ b/source/gameengine/GamePlayer/common/GPC_RawImage.cpp @@ -89,7 +89,7 @@ bool GPC_RawImage::Load( // Put original in upper left corner // Add vertical offset - dst += offsetY * dstBytesWidth; + dst += offsetY * dstBytesWidth; // Add horizontal offset dst += offsetX * 4; for (int row = 0; row < numRows; row++) diff --git a/source/gameengine/GamePlayer/common/GPC_RawImage.h b/source/gameengine/GamePlayer/common/GPC_RawImage.h index 4d3f45597f8..afff59484b9 100644 --- a/source/gameengine/GamePlayer/common/GPC_RawImage.h +++ b/source/gameengine/GamePlayer/common/GPC_RawImage.h @@ -117,5 +117,4 @@ protected: int m_height; }; -#endif // __GPC_RAWIMAGE_H__ - +#endif /* __GPC_RAWIMAGE_H__ */ diff --git a/source/gameengine/GamePlayer/common/GPC_RawLoadDotBlendArray.cpp b/source/gameengine/GamePlayer/common/GPC_RawLoadDotBlendArray.cpp index adf0bcd8e57..c4022d69153 100644 --- a/source/gameengine/GamePlayer/common/GPC_RawLoadDotBlendArray.cpp +++ b/source/gameengine/GamePlayer/common/GPC_RawLoadDotBlendArray.cpp @@ -38,7 +38,8 @@ void GetRawLoadingAnimation(unsigned char **data, int *dataSize) { // create an array that will automatically be deleted when) // we're outta this scope - static unsigned char load_blend[]= { 66, 76, 69, 78, 68, 70, + static unsigned char load_blend[] = { + 66, 76, 69, 78, 68, 70, 73, 10, 0, 2, 21, 0, 0, 2, 22, 0, 0, 0, 0, 0, 0, 2, 30, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 25, 242, 2, 0, 2, 29, 253, 0, 0, 0, 4, 160, 249, 227, diff --git a/source/gameengine/GamePlayer/common/GPC_RawLoadDotBlendArray.h b/source/gameengine/GamePlayer/common/GPC_RawLoadDotBlendArray.h index 6f15276ab83..d5c1b210454 100644 --- a/source/gameengine/GamePlayer/common/GPC_RawLoadDotBlendArray.h +++ b/source/gameengine/GamePlayer/common/GPC_RawLoadDotBlendArray.h @@ -34,5 +34,4 @@ void GetRawLoadingAnimation(unsigned char **data, int *dataSize); -#endif // __GPC_RAWLOADDOTBLENDARRAY_H__ - +#endif /* __GPC_RAWLOADDOTBLENDARRAY_H__ */ diff --git a/source/gameengine/GamePlayer/common/GPC_RawLogoArrays.cpp b/source/gameengine/GamePlayer/common/GPC_RawLogoArrays.cpp index 2471b528eac..2f58e9a692f 100644 --- a/source/gameengine/GamePlayer/common/GPC_RawLogoArrays.cpp +++ b/source/gameengine/GamePlayer/common/GPC_RawLogoArrays.cpp @@ -38,7 +38,8 @@ void GetRawBlenderLogo(unsigned char **data, int *width, int *height) { // create an array that will automatically be deleted when) // we're outta this scope - static unsigned char logo_blender_raw[]= { 0, 0, 0, 0, 0, + static unsigned char logo_blender_raw[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1041,7 +1042,8 @@ void GetRawBlender3DLogo(unsigned char **data, int *width, int *height) { // create an array that will automatically be deleted when) // we're outta this scope - static unsigned char logo_blender3d_raw[]= {255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, + static unsigned char logo_blender3d_raw[] = { + 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, diff --git a/source/gameengine/GamePlayer/common/GPC_RawLogoArrays.h b/source/gameengine/GamePlayer/common/GPC_RawLogoArrays.h index ade00020353..bb5c5e220a3 100644 --- a/source/gameengine/GamePlayer/common/GPC_RawLogoArrays.h +++ b/source/gameengine/GamePlayer/common/GPC_RawLogoArrays.h @@ -38,5 +38,4 @@ void GetRawBlender3DLogo(unsigned char **data, int *width, int *height); void GetRawNaNLogo(unsigned char **data, int *width, int *height); #endif -#endif // __GPC_RAWLOGOARRAYS_H__ - +#endif /* __GPC_RAWLOGOARRAYS_H__ */ diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp index 749e7748e19..dfc866526eb 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp @@ -173,11 +173,11 @@ bool GPC_RenderTools::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, vo left = (dir.cross(resultnormal)).safe_normalized(); // for the up vector, we take the 'resultnormal' returned by the physics - double maat[16]={ - left[0], left[1], left[2], 0, - dir[0], dir[1], dir[2], 0, - resultnormal[0],resultnormal[1],resultnormal[2], 0, - 0, 0, 0, 1}; + double maat[16] = {left[0], left[1], left[2], 0, + dir[0], dir[1], dir[2], 0, + resultnormal[0], resultnormal[1], resultnormal[2], 0, + 0, 0, 0, 1}; + glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]); //glMultMatrixd(oglmatrix); glMultMatrixd(maat); @@ -236,16 +236,16 @@ void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,in left *= size[0]; dir *= size[1]; up *= size[2]; - double maat[16]={ - left[0], left[1],left[2], 0, - dir[0], dir[1],dir[2],0, - up[0],up[1],up[2],0, - 0,0,0,1}; - glTranslated(objpos[0],objpos[1],objpos[2]); - glMultMatrixd(maat); - - } else - { + + double maat[16] = {left[0], left[1], left[2], 0, + dir[0], dir[1], dir[2], 0, + up[0], up[1], up[2], 0, + 0, 0, 0, 1}; + + glTranslated(objpos[0],objpos[1],objpos[2]); + glMultMatrixd(maat); + } + else { if (objectdrawmode & RAS_IPolyMaterial::SHADOW) { // shadow must be cast to the ground, physics system needed here! @@ -359,7 +359,8 @@ void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, glGetIntegerv(GL_LIGHTING, (GLint*)&light); glDisable(GL_LIGHTING); - + glDisable(GL_DEPTH_TEST); + // Set up viewing settings glMatrixMode(GL_PROJECTION); glPushMatrix(); @@ -442,7 +443,7 @@ void GPC_RenderTools::PopMatrix() int GPC_RenderTools::applyLights(int objectlayer, const MT_Transform& viewmat) { - // taken from blender source, incompatibility between Blender Object / GameObject + // taken from blender source, incompatibility between Blender Object / GameObject KX_Scene* kxscene = (KX_Scene*)m_auxilaryClientInfo; float glviewmat[16]; unsigned int count; diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.h b/source/gameengine/GamePlayer/common/GPC_RenderTools.h index 166a931beab..1030c09548a 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.h +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.h @@ -36,7 +36,7 @@ // don't show stl-warnings #pragma warning (disable:4786) #include -#endif // WIN32 +#endif /* WIN32 */ #include "RAS_IRenderTools.h" @@ -106,7 +106,4 @@ public: virtual void SetClientObject(RAS_IRasterizer *rasty, void* obj); }; -#endif // __GPC_RENDERTOOLS_H__ - - - +#endif /* __GPC_RENDERTOOLS_H__ */ diff --git a/source/gameengine/GamePlayer/common/GPC_System.h b/source/gameengine/GamePlayer/common/GPC_System.h index 03bb7743637..4169064179e 100644 --- a/source/gameengine/GamePlayer/common/GPC_System.h +++ b/source/gameengine/GamePlayer/common/GPC_System.h @@ -59,5 +59,4 @@ public: // NG_NetworkDeviceInterface* m_ndi; }; -#endif // __GPC_SYSTEM_H__ - +#endif /* __GPC_SYSTEM_H__ */ diff --git a/source/gameengine/GamePlayer/common/bmfont.cpp b/source/gameengine/GamePlayer/common/bmfont.cpp index 4c1c6ae5604..fe6f2187138 100644 --- a/source/gameengine/GamePlayer/common/bmfont.cpp +++ b/source/gameengine/GamePlayer/common/bmfont.cpp @@ -104,13 +104,13 @@ void readBitmapFontVersion0(ImBuf * ibuf, unsigned char * rect, int step) ysize = (bytes + (ibuf->x - 1)) / ibuf->x; if (ysize < ibuf->y) { - // we're first going to copy all data into a liniar buffer. + // we're first going to copy all data into a linear buffer. // step can be 4 or 1 bytes, and the data is not sequential because // the bitmap was flipped vertically. buffer = (unsigned char*)MEM_mallocN(bytes, "readBitmapFontVersion0:buffer"); - index = 0; + index = 0; for (i = 0; i < bytes; i++) { buffer[i] = rect[index]; index += step; diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index 21de7011eda..40b52c3212a 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -479,7 +479,7 @@ bool GPG_Application::processEvent(GHOST_IEvent* event) // // first check if we want to exit // m_exitRequested = m_ketsjiengine->GetExitCode(); - // + // // // kick the engine // bool renderFrame = m_ketsjiengine->NextFrame(); // if (renderFrame) @@ -546,7 +546,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) return false; // SYS_WriteCommandLineInt(syshandle, "fixedtime", 0); - // SYS_WriteCommandLineInt(syshandle, "vertexarrays",1); + // SYS_WriteCommandLineInt(syshandle, "vertexarrays",1); GameData *gm= &m_startScene->gm; bool properties = (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0); bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0); @@ -576,7 +576,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) m_canvas->Init(); if (gm->flag & GAME_SHOW_MOUSE) - m_canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL); + m_canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL); m_rendertools = new GPC_RenderTools(); if (!m_rendertools) @@ -681,7 +681,7 @@ bool GPG_Application::startEngine(void) // Temporary hack to disable banner display for NaN approved content. /* - m_canvas->SetBannerDisplayEnabled(true); + m_canvas->SetBannerDisplayEnabled(true); Camera* cam; cam = (Camera*)scene->camera->data; if (cam) { @@ -730,7 +730,7 @@ bool GPG_Application::startEngine(void) // Set the GameLogic.globalDict from marshal'd data, so we can // load new blend files and keep data in GameLogic.globalDict loadGamePythonConfig(m_pyGlobalDictString, m_pyGlobalDictString_Length); -#endif +#endif m_sceneconverter->ConvertScene( startscene, m_rendertools, diff --git a/source/gameengine/GamePlayer/ghost/GPG_Canvas.h b/source/gameengine/GamePlayer/ghost/GPG_Canvas.h index d931f605a64..440fd2bba27 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Canvas.h +++ b/source/gameengine/GamePlayer/ghost/GPG_Canvas.h @@ -33,8 +33,8 @@ #define __GPG_CANVAS_H__ #ifdef WIN32 -#pragma warning (disable : 4786) -#endif // WIN32 +#pragma warning (disable:4786) +#endif /* WIN32 */ #include "GPC_Canvas.h" @@ -66,5 +66,4 @@ public: void EndDraw() {}; }; -#endif // __GPG_CANVAS_H__ - +#endif /* __GPG_CANVAS_H__ */ diff --git a/source/gameengine/GamePlayer/ghost/GPG_KeyboardDevice.cpp b/source/gameengine/GamePlayer/ghost/GPG_KeyboardDevice.cpp index b31803b761e..e8d3441e4ce 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_KeyboardDevice.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_KeyboardDevice.cpp @@ -72,7 +72,7 @@ GPG_KeyboardDevice::GPG_KeyboardDevice(void) m_reverseKeyTranslateTable[GHOST_kKey7 ] = KX_SEVENKEY ; m_reverseKeyTranslateTable[GHOST_kKey8 ] = KX_EIGHTKEY ; m_reverseKeyTranslateTable[GHOST_kKey9 ] = KX_NINEKEY ; - + // Middle keyboard area keys m_reverseKeyTranslateTable[GHOST_kKeyPause ] = KX_PAUSEKEY ; m_reverseKeyTranslateTable[GHOST_kKeyInsert ] = KX_INSERTKEY ; @@ -81,7 +81,7 @@ GPG_KeyboardDevice::GPG_KeyboardDevice(void) m_reverseKeyTranslateTable[GHOST_kKeyEnd ] = KX_ENDKEY ; m_reverseKeyTranslateTable[GHOST_kKeyUpPage ] = KX_PAGEUPKEY ; m_reverseKeyTranslateTable[GHOST_kKeyDownPage ] = KX_PAGEDOWNKEY ; - + // Arrow keys m_reverseKeyTranslateTable[GHOST_kKeyUpArrow ] = KX_UPARROWKEY ; m_reverseKeyTranslateTable[GHOST_kKeyDownArrow ] = KX_DOWNARROWKEY ; @@ -108,19 +108,19 @@ GPG_KeyboardDevice::GPG_KeyboardDevice(void) m_reverseKeyTranslateTable[GHOST_kKeyF17 ] = KX_F17KEY ; m_reverseKeyTranslateTable[GHOST_kKeyF18 ] = KX_F18KEY ; m_reverseKeyTranslateTable[GHOST_kKeyF19 ] = KX_F19KEY ; - + // Numpad keys - m_reverseKeyTranslateTable[GHOST_kKeyNumpad0 ] = KX_PAD0 ; - m_reverseKeyTranslateTable[GHOST_kKeyNumpad1 ] = KX_PAD1 ; - m_reverseKeyTranslateTable[GHOST_kKeyNumpad2 ] = KX_PAD2 ; - m_reverseKeyTranslateTable[GHOST_kKeyNumpad3 ] = KX_PAD3 ; - m_reverseKeyTranslateTable[GHOST_kKeyNumpad4 ] = KX_PAD4 ; - m_reverseKeyTranslateTable[GHOST_kKeyNumpad5 ] = KX_PAD5 ; - m_reverseKeyTranslateTable[GHOST_kKeyNumpad6 ] = KX_PAD6 ; - m_reverseKeyTranslateTable[GHOST_kKeyNumpad7 ] = KX_PAD7 ; - m_reverseKeyTranslateTable[GHOST_kKeyNumpad8 ] = KX_PAD8 ; - m_reverseKeyTranslateTable[GHOST_kKeyNumpad9 ] = KX_PAD9 ; + m_reverseKeyTranslateTable[GHOST_kKeyNumpad0 ] = KX_PAD0 ; + m_reverseKeyTranslateTable[GHOST_kKeyNumpad1 ] = KX_PAD1 ; + m_reverseKeyTranslateTable[GHOST_kKeyNumpad2 ] = KX_PAD2 ; + m_reverseKeyTranslateTable[GHOST_kKeyNumpad3 ] = KX_PAD3 ; + m_reverseKeyTranslateTable[GHOST_kKeyNumpad4 ] = KX_PAD4 ; + m_reverseKeyTranslateTable[GHOST_kKeyNumpad5 ] = KX_PAD5 ; + m_reverseKeyTranslateTable[GHOST_kKeyNumpad6 ] = KX_PAD6 ; + m_reverseKeyTranslateTable[GHOST_kKeyNumpad7 ] = KX_PAD7 ; + m_reverseKeyTranslateTable[GHOST_kKeyNumpad8 ] = KX_PAD8 ; + m_reverseKeyTranslateTable[GHOST_kKeyNumpad9 ] = KX_PAD9 ; m_reverseKeyTranslateTable[GHOST_kKeyNumpadAsterisk ] = KX_PADASTERKEY ; m_reverseKeyTranslateTable[GHOST_kKeyNumpadPlus ] = KX_PADPLUSKEY ; m_reverseKeyTranslateTable[GHOST_kKeyNumpadPeriod ] = KX_PADPERIOD ; @@ -133,7 +133,7 @@ GPG_KeyboardDevice::GPG_KeyboardDevice(void) m_reverseKeyTranslateTable[GHOST_kKeyEsc ] = KX_ESCKEY ; m_reverseKeyTranslateTable[GHOST_kKeyTab ] = KX_TABKEY ; m_reverseKeyTranslateTable[GHOST_kKeySpace ] = KX_SPACEKEY ; - m_reverseKeyTranslateTable[GHOST_kKeyEnter ] = KX_RETKEY ; + m_reverseKeyTranslateTable[GHOST_kKeyEnter ] = KX_RETKEY ; m_reverseKeyTranslateTable[GHOST_kKeyBackSpace ] = KX_BACKSPACEKEY ; m_reverseKeyTranslateTable[GHOST_kKeySemicolon ] = KX_SEMICOLONKEY ; m_reverseKeyTranslateTable[GHOST_kKeyPeriod ] = KX_PERIODKEY ; @@ -141,19 +141,19 @@ GPG_KeyboardDevice::GPG_KeyboardDevice(void) m_reverseKeyTranslateTable[GHOST_kKeyQuote ] = KX_QUOTEKEY ; m_reverseKeyTranslateTable[GHOST_kKeyAccentGrave ] = KX_ACCENTGRAVEKEY ; m_reverseKeyTranslateTable[GHOST_kKeyMinus ] = KX_MINUSKEY ; - m_reverseKeyTranslateTable[GHOST_kKeySlash ] = KX_SLASHKEY ; + m_reverseKeyTranslateTable[GHOST_kKeySlash ] = KX_SLASHKEY ; m_reverseKeyTranslateTable[GHOST_kKeyBackslash ] = KX_BACKSLASHKEY ; m_reverseKeyTranslateTable[GHOST_kKeyEqual ] = KX_EQUALKEY ; - m_reverseKeyTranslateTable[GHOST_kKeyLeftBracket ] = KX_LEFTBRACKETKEY ; - m_reverseKeyTranslateTable[GHOST_kKeyRightBracket ] = KX_RIGHTBRACKETKEY ; + m_reverseKeyTranslateTable[GHOST_kKeyLeftBracket ] = KX_LEFTBRACKETKEY ; + m_reverseKeyTranslateTable[GHOST_kKeyRightBracket ] = KX_RIGHTBRACKETKEY ; // Modifier keys. - m_reverseKeyTranslateTable[GHOST_kKeyLeftControl ] = KX_LEFTCTRLKEY ; - m_reverseKeyTranslateTable[GHOST_kKeyRightControl ] = KX_RIGHTCTRLKEY ; + m_reverseKeyTranslateTable[GHOST_kKeyLeftControl ] = KX_LEFTCTRLKEY ; + m_reverseKeyTranslateTable[GHOST_kKeyRightControl ] = KX_RIGHTCTRLKEY ; m_reverseKeyTranslateTable[GHOST_kKeyLeftAlt ] = KX_LEFTALTKEY ; m_reverseKeyTranslateTable[GHOST_kKeyRightAlt ] = KX_RIGHTALTKEY ; m_reverseKeyTranslateTable[GHOST_kKeyLeftShift ] = KX_LEFTSHIFTKEY ; - m_reverseKeyTranslateTable[GHOST_kKeyRightShift ] = KX_RIGHTSHIFTKEY ; + m_reverseKeyTranslateTable[GHOST_kKeyRightShift ] = KX_RIGHTSHIFTKEY ; } diff --git a/source/gameengine/GamePlayer/ghost/GPG_KeyboardDevice.h b/source/gameengine/GamePlayer/ghost/GPG_KeyboardDevice.h index 8d72a621b6a..ff8d56db40a 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_KeyboardDevice.h +++ b/source/gameengine/GamePlayer/ghost/GPG_KeyboardDevice.h @@ -34,8 +34,8 @@ #define __GPG_KEYBOARDDEVICE_H__ #ifdef WIN32 -#pragma warning (disable : 4786) -#endif // WIN32 +#pragma warning (disable:4786) +#endif /* WIN32 */ #include "GHOST_Types.h" #include "GPC_KeyboardDevice.h" @@ -53,5 +53,4 @@ public: virtual ~GPG_KeyboardDevice(void); }; -#endif //__GPG_KEYBOARDDEVICE_H__ - +#endif /* __GPG_KEYBOARDDEVICE_H__ */ diff --git a/source/gameengine/GamePlayer/ghost/GPG_System.h b/source/gameengine/GamePlayer/ghost/GPG_System.h index 796ad0c2b8c..d68fc812dd3 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_System.h +++ b/source/gameengine/GamePlayer/ghost/GPG_System.h @@ -35,7 +35,7 @@ #ifdef WIN32 #pragma warning (disable:4786) // suppress stl-MSVC debug info warning -#endif // WIN32 +#endif /* WIN32 */ #include "GPC_System.h" @@ -51,5 +51,4 @@ public: virtual double GetTimeInSeconds(); }; -#endif // __GPG_SYSTEM_H__ - +#endif /* __GPG_SYSTEM_H__ */ diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index d8b07fd50d9..725c23c60e3 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -57,10 +57,10 @@ extern "C" { #endif // __cplusplus #include "MEM_guardedalloc.h" -#include "BKE_blender.h" -#include "BKE_global.h" -#include "BKE_icons.h" -#include "BKE_node.h" +#include "BKE_blender.h" +#include "BKE_global.h" +#include "BKE_icons.h" +#include "BKE_node.h" #include "BKE_report.h" #include "BKE_library.h" #include "BLI_threads.h" @@ -119,11 +119,11 @@ static void mem_error_cb(const char *errorStr) #ifdef WIN32 typedef enum { - SCREEN_SAVER_MODE_NONE = 0, - SCREEN_SAVER_MODE_PREVIEW, - SCREEN_SAVER_MODE_SAVER, - SCREEN_SAVER_MODE_CONFIGURATION, - SCREEN_SAVER_MODE_PASSWORD, + SCREEN_SAVER_MODE_NONE = 0, + SCREEN_SAVER_MODE_PREVIEW, + SCREEN_SAVER_MODE_SAVER, + SCREEN_SAVER_MODE_CONFIGURATION, + SCREEN_SAVER_MODE_PASSWORD, } ScreenSaverMode; static ScreenSaverMode scr_saver_mode = SCREEN_SAVER_MODE_NONE; @@ -223,7 +223,7 @@ void usage(const char* program, bool isBlenderPlayer) printf(" --Optional parameters--\n"); printf(" angle = field of view in degrees\n"); printf(" tilt = tilt angle in degrees\n"); - printf(" warpdata = a file to use for warping the image (absolute path)\n"); + printf(" warpdata = a file to use for warping the image (absolute path)\n"); printf(" mode: fisheye (Fisheye)\n"); printf(" truncatedfront (Front-Truncated)\n"); printf(" truncatedrear (Rear-Truncated)\n"); @@ -1016,12 +1016,12 @@ int main(int argc, char** argv) gpg_nextframestate.app = &app; gpg_nextframestate.gs = &gs; pynextframestate.state = &gpg_nextframestate; - pynextframestate.func = &GPG_PyNextFrame; + pynextframestate.func = &GPG_PyNextFrame; printf("Yielding control to Python script '%s'...\n", python_main); PyRun_SimpleString(python_code); printf("Exit Python script '%s'\n", python_main); -#endif // WITH_PYTHON +#endif // WITH_PYTHON MEM_freeN(python_code); } else { @@ -1064,6 +1064,7 @@ int main(int argc, char** argv) #ifdef WITH_INTERNATIONAL BLF_free_unifont(); + BLF_lang_free(); #endif IMB_exit(); diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp index a21c3965be9..5b7a2313f43 100644 --- a/source/gameengine/Ketsji/BL_Action.cpp +++ b/source/gameengine/Ketsji/BL_Action.cpp @@ -352,29 +352,27 @@ void BL_Action::Update(float curtime) } // Handle wrap around - if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe)) - { - switch(m_playmode) - { - case ACT_MODE_PLAY: - // Clamp - m_localtime = m_endframe; - m_done = true; - break; - case ACT_MODE_LOOP: - // Put the time back to the beginning - m_localtime = m_startframe; - m_starttime = curtime; - break; - case ACT_MODE_PING_PONG: - // Swap the start and end frames - float temp = m_startframe; - m_startframe = m_endframe; - m_endframe = temp; + if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe)) { + switch (m_playmode) { + case ACT_MODE_PLAY: + // Clamp + m_localtime = m_endframe; + m_done = true; + break; + case ACT_MODE_LOOP: + // Put the time back to the beginning + m_localtime = m_startframe; + m_starttime = curtime; + break; + case ACT_MODE_PING_PONG: + // Swap the start and end frames + float temp = m_startframe; + m_startframe = m_endframe; + m_endframe = temp; - m_starttime = curtime; + m_starttime = curtime; - break; + break; } } diff --git a/source/gameengine/Ketsji/BL_Action.h b/source/gameengine/Ketsji/BL_Action.h index ab2adf7fe34..370bbf51d72 100644 --- a/source/gameengine/Ketsji/BL_Action.h +++ b/source/gameengine/Ketsji/BL_Action.h @@ -136,5 +136,4 @@ public: #endif }; -#endif //BL_ACTION - +#endif /* BL_ACTION */ diff --git a/source/gameengine/Ketsji/BL_ActionManager.h b/source/gameengine/Ketsji/BL_ActionManager.h index dbdaa6652ad..600e7b6621e 100644 --- a/source/gameengine/Ketsji/BL_ActionManager.h +++ b/source/gameengine/Ketsji/BL_ActionManager.h @@ -98,5 +98,4 @@ public: #endif }; -#endif //BL_ACTIONMANAGER - +#endif /* BL_ACTIONMANAGER */ diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index 122d692b599..23bfd7a111b 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -6,6 +6,8 @@ #include "DNA_material_types.h" #include "DNA_scene_types.h" +#include "BLI_utildefines.h" + #include "BKE_global.h" #include "BKE_main.h" #include "BKE_DerivedMesh.h" @@ -143,9 +145,9 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) viewinv.getValue((float*)viewinvmat); if (ms.m_bObjectColor) - ms.m_RGBAcolor.getValue((float*)obcol); + ms.m_RGBAcolor.getValue((float *)obcol); else - obcol[0]= obcol[1]= obcol[2]= obcol[3]= 1.0f; + 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); diff --git a/source/gameengine/Ketsji/BL_BlenderShader.h b/source/gameengine/Ketsji/BL_BlenderShader.h index f23dbfdf3a5..626c65baadd 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.h +++ b/source/gameengine/Ketsji/BL_BlenderShader.h @@ -101,4 +101,4 @@ public: #endif }; -#endif//__BL_BLENDERSHADER_H__ +#endif /* __BL_BLENDERSHADER_H__ */ diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index c0fca88c426..fb8e7beb157 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -52,51 +52,70 @@ void BL_Uniform::Apply(class BL_Shader *shader) #ifdef SORT_UNIFORMS MT_assert(mType > UNI_NONE && mType < UNI_MAX && mData); - if (!mDirty) + if (!mDirty) return; - switch(mType) - { - case UNI_FLOAT: { + switch (mType) { + case UNI_FLOAT: + { float *f = (float*)mData; glUniform1fARB(mLoc,(GLfloat)*f); - }break; - case UNI_INT: { + break; + } + case UNI_INT: + { int *f = (int*)mData; glUniform1iARB(mLoc, (GLint)*f); - }break; - case UNI_FLOAT2: { + break; + } + case UNI_FLOAT2: + { float *f = (float*)mData; glUniform2fvARB(mLoc,1, (GLfloat*)f); - }break; - case UNI_FLOAT3: { + break; + } + case UNI_FLOAT3: + { float *f = (float*)mData; glUniform3fvARB(mLoc,1,(GLfloat*)f); - }break; - case UNI_FLOAT4: { + break; + } + case UNI_FLOAT4: + { float *f = (float*)mData; glUniform4fvARB(mLoc,1,(GLfloat*)f); - }break; - case UNI_INT2: { + break; + } + case UNI_INT2: + { int *f = (int*)mData; glUniform2ivARB(mLoc,1,(GLint*)f); - }break; - case UNI_INT3: { + break; + } + case UNI_INT3: + { int *f = (int*)mData; glUniform3ivARB(mLoc,1,(GLint*)f); - }break; - case UNI_INT4: { + break; + } + case UNI_INT4: + { int *f = (int*)mData; glUniform4ivARB(mLoc,1,(GLint*)f); - }break; - case UNI_MAT4: { + break; + } + case UNI_MAT4: + { float *f = (float*)mData; glUniformMatrix4fvARB(mLoc, 1, mTranspose?GL_TRUE:GL_FALSE,(GLfloat*)f); - }break; - case UNI_MAT3: { + break; + } + case UNI_MAT3: + { float *f = (float*)mData; glUniformMatrix3fvARB(mLoc, 1, mTranspose?GL_TRUE:GL_FALSE,(GLfloat*)f); - }break; + break; + } } mDirty = false; #endif @@ -157,7 +176,7 @@ BL_Shader::~BL_Shader() void BL_Shader::ClearUniforms() { BL_UniformVec::iterator it = mUniforms.begin(); - while(it != mUniforms.end()) { + while (it != mUniforms.end()) { delete (*it); it++; } @@ -165,7 +184,7 @@ void BL_Shader::ClearUniforms() BL_UniformVecDef::iterator itp = mPreDef.begin(); - while(itp != mPreDef.end()) { + while (itp != mPreDef.end()) { delete (*itp); itp++; } @@ -178,7 +197,7 @@ BL_Uniform *BL_Shader::FindUniform(const int location) { #ifdef SORT_UNIFORMS BL_UniformVec::iterator it = mUniforms.begin(); - while(it != mUniforms.end()) { + while (it != mUniforms.end()) { if ((*it)->GetLocation() == location) return (*it); it++; @@ -431,7 +450,7 @@ void BL_Shader::SetProg(bool enable) glUseProgramObjectARB(mShader); } else { - glUseProgramObjectARB(0); + glUseProgramObjectARB(0); } } } @@ -613,7 +632,7 @@ void BL_Shader::SetUniform(int uniform, const MT_Tuple3& vec) GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects ) - { + { float value[3]; vec.getValue(value); glUniform3fvARB(uniform, 1, value); @@ -931,7 +950,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" ) { #ifdef SORT_UNIFORMS SetUniformfv(loc, BL_Uniform::UNI_FLOAT, &value, sizeof(float)); -#else +#else SetUniform( loc, (float)value ); #endif } @@ -947,7 +966,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f, "setUniform2f(name, fx, fy)") Py_RETURN_NONE; } const char *uniform=""; - float array[2]={ 0,0 }; + float array[2] = {0, 0}; if (PyArg_ParseTuple(args, "sff:setUniform2f", &uniform, &array[0],&array[1] )) { int loc = GetUniformLocation(uniform); @@ -971,7 +990,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ") Py_RETURN_NONE; } const char *uniform=""; - float array[3]={0,0,0}; + float array[3] = {0, 0, 0}; if (PyArg_ParseTuple(args, "sfff:setUniform3f", &uniform, &array[0],&array[1],&array[2])) { int loc = GetUniformLocation(uniform); @@ -996,7 +1015,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) " Py_RETURN_NONE; } const char *uniform=""; - float array[4]={0,0,0,0}; + float array[4] = {0, 0, 0, 0}; if (PyArg_ParseTuple(args, "sffff:setUniform4f", &uniform, &array[0],&array[1],&array[2], &array[3])) { int loc = GetUniformLocation(uniform); @@ -1044,7 +1063,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i, "setUniform2i(name, ix, iy)") Py_RETURN_NONE; } const char *uniform=""; - int array[2]={ 0,0 }; + int array[2] = {0, 0}; if (PyArg_ParseTuple(args, "sii:setUniform2i", &uniform, &array[0],&array[1] )) { int loc = GetUniformLocation(uniform); @@ -1069,7 +1088,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ") } const char *uniform=""; - int array[3]={0,0,0}; + int array[3] = {0, 0, 0}; if (PyArg_ParseTuple(args, "siii:setUniform3i", &uniform, &array[0],&array[1],&array[2])) { int loc = GetUniformLocation(uniform); @@ -1092,7 +1111,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) " Py_RETURN_NONE; } const char *uniform=""; - int array[4]={0,0,0, 0}; + int array[4] = {0, 0, 0, 0}; if (PyArg_ParseTuple(args, "siiii:setUniform4i", &uniform, &array[0],&array[1],&array[2], &array[3] )) { int loc = GetUniformLocation(uniform); @@ -1134,7 +1153,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv, "setUniformfv( float (list2 or list Py_DECREF(item); } - switch(list_size) + switch (list_size) { case 2: { @@ -1142,7 +1161,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv, "setUniformfv( float (list2 or list #ifdef SORT_UNIFORMS SetUniformfv(loc, BL_Uniform::UNI_FLOAT2, array2, sizeof(float)*2); #else - SetUniform(loc, array2, 2); + SetUniform(loc, array2, 2); #endif Py_RETURN_NONE; } break; @@ -1152,7 +1171,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv, "setUniformfv( float (list2 or list #ifdef SORT_UNIFORMS SetUniformfv(loc, BL_Uniform::UNI_FLOAT3, array3, sizeof(float)*3); #else - SetUniform(loc, array3, 3); + SetUniform(loc, array3, 3); #endif Py_RETURN_NONE; }break; @@ -1162,7 +1181,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv, "setUniformfv( float (list2 or list #ifdef SORT_UNIFORMS SetUniformfv(loc, BL_Uniform::UNI_FLOAT4, array4, sizeof(float)*4); #else - SetUniform(loc, array4, 4); + SetUniform(loc, array4, 4); #endif Py_RETURN_NONE; }break; @@ -1218,7 +1237,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( uniform_name, (list2 /* Sanity checks done! */ - switch(list_size) + switch (list_size) { case 2: { @@ -1226,7 +1245,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( uniform_name, (list2 #ifdef SORT_UNIFORMS SetUniformiv(loc, BL_Uniform::UNI_INT2, array2, sizeof(int)*2); #else - SetUniform(loc, array2, 2); + SetUniform(loc, array2, 2); #endif Py_RETURN_NONE; } break; @@ -1237,7 +1256,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( uniform_name, (list2 SetUniformiv(loc, BL_Uniform::UNI_INT3, array3, sizeof(int)*3); #else - SetUniform(loc, array3, 3); + SetUniform(loc, array3, 3); #endif Py_RETURN_NONE; }break; @@ -1248,7 +1267,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( uniform_name, (list2 SetUniformiv(loc, BL_Uniform::UNI_INT4, array4, sizeof(int)*4); #else - SetUniform(loc, array4, 4); + SetUniform(loc, array4, 4); #endif Py_RETURN_NONE; }break; @@ -1394,15 +1413,14 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformDef, "setUniformDef(name, enum)" ) { bool defined = false; BL_UniformVecDef::iterator it = mPreDef.begin(); - while(it != mPreDef.end()) { + while (it != mPreDef.end()) { if ((*it)->mLoc == loc) { defined = true; break; } it++; } - if (defined) - { + if (defined) { Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/BL_Shader.h b/source/gameengine/Ketsji/BL_Shader.h index 2bb094f12ee..82476873b85 100644 --- a/source/gameengine/Ketsji/BL_Shader.h +++ b/source/gameengine/Ketsji/BL_Shader.h @@ -222,7 +222,7 @@ public: // Python interface #ifdef WITH_PYTHON - virtual PyObject* py_repr(void) { return PyUnicode_FromFormat("BL_Shader\n\tvertex shader:%s\n\n\tfragment shader%s\n\n", vertProg, fragProg); } + virtual PyObject *py_repr(void) { return PyUnicode_FromFormat("BL_Shader\n\tvertex shader:%s\n\n\tfragment shader%s\n\n", vertProg, fragProg); } // ----------------------------------- KX_PYMETHOD_DOC(BL_Shader, setSource); @@ -252,4 +252,4 @@ public: #endif }; -#endif//__BL_SHADER_H__ +#endif /* __BL_SHADER_H__ */ diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp index b8cc4ebeff9..26523df8db3 100644 --- a/source/gameengine/Ketsji/BL_Texture.cpp +++ b/source/gameengine/Ketsji/BL_Texture.cpp @@ -47,7 +47,7 @@ static int power_of_2_min_i(int num) { while (!is_power_of_2_i(num)) num= num&(num-1); - return num; + return num; } // Place holder for a full texture manager @@ -427,7 +427,7 @@ void BL_Texture::DisableAllTextures() glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); - glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glDisable(GL_TEXTURE_GEN_R); @@ -447,14 +447,14 @@ void BL_Texture::ActivateTexture() if (mType == GL_TEXTURE_CUBE_MAP_ARB && GLEW_ARB_texture_cube_map) { - glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, mTexture ); + glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, mTexture ); glEnable(GL_TEXTURE_CUBE_MAP_ARB); } else { if (GLEW_ARB_texture_cube_map ) glDisable(GL_TEXTURE_CUBE_MAP_ARB); - glBindTexture( GL_TEXTURE_2D, mTexture ); + glBindTexture( GL_TEXTURE_2D, mTexture ); glEnable(GL_TEXTURE_2D); } } @@ -562,7 +562,7 @@ void BL_Texture::setTexEnv(BL_Material *mat, bool modulate) using_alpha = true; } - switch( mat->blend_mode[mUnit] ) { + switch (mat->blend_mode[mUnit]) { case BLEND_MIX: { // ------------------------------ @@ -659,7 +659,7 @@ void my_envmap_split_ima(EnvMap *env, ImBuf *ibuf) { int dx, part; - my_free_envmapdata(env); + my_free_envmapdata(env); dx= ibuf->y; dx/= 2; @@ -670,7 +670,7 @@ void my_envmap_split_ima(EnvMap *env, ImBuf *ibuf) } else { for (part=0; part<6; part++) { - env->cube[part]= IMB_allocImBuf(dx, dx, 24, IB_rect); + env->cube[part] = IMB_allocImBuf(dx, dx, 24, IB_rect); } IMB_rectcpy(env->cube[0], ibuf, 0, 0, 0, 0, dx, dx); @@ -698,7 +698,7 @@ void my_free_envmapdata(EnvMap *env) ImBuf *ibuf= env->cube[part]; if (ibuf) { IMB_freeImBuf(ibuf); - env->cube[part]= NULL; + env->cube[part] = NULL; } } env->ok= 0; diff --git a/source/gameengine/Ketsji/BL_Texture.h b/source/gameengine/Ketsji/BL_Texture.h index a6bd354d260..cd18ef93822 100644 --- a/source/gameengine/Ketsji/BL_Texture.h +++ b/source/gameengine/Ketsji/BL_Texture.h @@ -79,4 +79,4 @@ public: #endif }; -#endif//__BL_TEXTURE_H__ +#endif /* __BL_TEXTURE_H__ */ diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt index 269311b7e00..4778a6ef9b9 100644 --- a/source/gameengine/Ketsji/CMakeLists.txt +++ b/source/gameengine/Ketsji/CMakeLists.txt @@ -74,6 +74,7 @@ set(SRC KX_Camera.cpp KX_CameraActuator.cpp KX_CameraIpoSGController.cpp + KX_CharacterWrapper.cpp KX_ConstraintActuator.cpp KX_ConstraintWrapper.cpp KX_ConvertPhysicsObjects.cpp @@ -149,6 +150,7 @@ set(SRC KX_Camera.h KX_CameraActuator.h KX_CameraIpoSGController.h + KX_CharacterWrapper.h KX_ClientObjectInfo.h KX_ConstraintActuator.h KX_ConstraintWrapper.h @@ -248,9 +250,11 @@ endif() if(WITH_BULLET) list(APPEND INC - ../../../extern/bullet2/src ../Physics/Bullet ) + list(APPEND INC + ../../../extern/bullet2/src + ) add_definitions(-DUSE_BULLET) endif() diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.h index 3202785ee81..9a13b6d53e2 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.h @@ -52,5 +52,4 @@ public: return m_ndi; } }; -#endif //__KX_NETWORKEVENTMANAGER_H__ - +#endif /* __KX_NETWORKEVENTMANAGER_H__ */ diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h index 980e1cda6dc..325a7be9bd7 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h @@ -69,5 +69,4 @@ public: }; -#endif //__KX_NETWORKMESSAGEACTUATOR_H__ - +#endif /* __KX_NETWORKMESSAGEACTUATOR_H__ */ diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp index a69f02baa57..6260596159d 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp @@ -38,7 +38,7 @@ #include "NG_NetworkMessage.h" #include "NG_NetworkScene.h" #include "NG_NetworkObject.h" -#include "SCA_IObject.h" +#include "SCA_IObject.h" #include "InputParser.h" #include "ListValue.h" #include "StringValue.h" @@ -201,7 +201,7 @@ PyAttributeDef KX_NetworkMessageSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_NetworkMessageSensor::pyattr_get_bodies(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_NetworkMessageSensor::pyattr_get_bodies(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_NetworkMessageSensor *self = static_cast(self_v); if (self->m_BodyList) { @@ -211,7 +211,7 @@ PyObject* KX_NetworkMessageSensor::pyattr_get_bodies(void *self_v, const KX_PYAT } } -PyObject* KX_NetworkMessageSensor::pyattr_get_subjects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_NetworkMessageSensor::pyattr_get_subjects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_NetworkMessageSensor *self = static_cast(self_v); if (self->m_SubjectList) { diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h index 66f723d072c..a1f0692b7b3 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h @@ -80,12 +80,11 @@ public: /* ------------------------------------------------------------- */ /* attributes */ - static PyObject* pyattr_get_bodies(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_bodies(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_subjects(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; -#endif //__KX_NETWORKMESSAGESENSOR_H__ - +#endif /* __KX_NETWORKMESSAGESENSOR_H__ */ diff --git a/source/gameengine/Ketsji/KX_ArmatureSensor.cpp b/source/gameengine/Ketsji/KX_ArmatureSensor.cpp index f72d9c1dee6..523f3ceeaea 100644 --- a/source/gameengine/Ketsji/KX_ArmatureSensor.cpp +++ b/source/gameengine/Ketsji/KX_ArmatureSensor.cpp @@ -86,7 +86,7 @@ void KX_ArmatureSensor::FindConstraint() /* this constraint is not valid, can't use it */ break; m_constraint = pcon; - break; + break; } } break; @@ -193,13 +193,13 @@ PyAttributeDef KX_ArmatureSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_ArmatureSensor::pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_ArmatureSensor::pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_ArmatureSensor* sensor = static_cast(self); if (sensor->m_gameobj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) { BL_ArmatureObject* armobj = (BL_ArmatureObject*)sensor->m_gameobj; BL_ArmatureConstraint* constraint = armobj->GetConstraint(sensor->m_posechannel, sensor->m_constraintname); - if (constraint) + if (constraint) return constraint->GetProxy(); } Py_RETURN_NONE; diff --git a/source/gameengine/Ketsji/KX_ArmatureSensor.h b/source/gameengine/Ketsji/KX_ArmatureSensor.h index 9c3faa355a6..b3ea905d198 100644 --- a/source/gameengine/Ketsji/KX_ArmatureSensor.h +++ b/source/gameengine/Ketsji/KX_ArmatureSensor.h @@ -72,9 +72,9 @@ public: /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - static PyObject* pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_constraint(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ private: struct bConstraint* m_constraint; diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index b602ba447ad..2154beeb205 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -165,11 +165,11 @@ void KX_BlenderMaterial::InitTextures() continue; } if (!mTextures[i].InitCubeMap(i, mMaterial->cubemap[i] ) ) - spit("unable to initialize image("<matname<< ", image will not be available"); - } - // If we're using glsl materials, the textures are handled by bf_gpu, so don't load them twice! - // However, if we're using a custom shader, then we still need to load the textures ourselves. + spit("unable to initialize image("<matname<< ", image will not be available"); + } + /* If we're using glsl materials, the textures are handled by bf_gpu, so don't load them twice! + * However, if we're using a custom shader, then we still need to load the textures ourselves. */ else if (!mMaterial->glslmat || mShader) { if ( mMaterial->img[i] ) { if ( ! mTextures[i].InitFromImage(i, mMaterial->img[i], (mMaterial->flag[i] &MIPMAP)!=0 )) @@ -412,7 +412,7 @@ KX_BlenderMaterial::ActivatShaders( if ((mMaterial->ras_mode &WIRE) || (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) - { + { if (mMaterial->ras_mode &WIRE) rasty->SetCullFace(false); rasty->SetLines(true); @@ -457,7 +457,7 @@ KX_BlenderMaterial::ActivateBlenderShaders( if ((mMaterial->ras_mode &WIRE) || (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) - { + { if (mMaterial->ras_mode &WIRE) rasty->SetCullFace(false); rasty->SetLines(true); @@ -506,7 +506,7 @@ KX_BlenderMaterial::ActivateMat( if ((mMaterial->ras_mode &WIRE) || (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) - { + { if (mMaterial->ras_mode &WIRE) rasty->SetCullFace(false); rasty->SetLines(true); @@ -614,7 +614,7 @@ void KX_BlenderMaterial::ActivatGLMaterials( RAS_IRasterizer* rasty )const mMaterial->matcolor[2]*mMaterial->ref+mMaterial->emit, 1.0f); - rasty->SetEmissive( + rasty->SetEmissive( mMaterial->matcolor[0]*mMaterial->emit, mMaterial->matcolor[1]*mMaterial->emit, mMaterial->matcolor[2]*mMaterial->emit, @@ -726,7 +726,7 @@ void KX_BlenderMaterial::setObjectMatrixData(int i, RAS_IRasterizer *ras) GLenum plane = GL_EYE_PLANE; // figure plane gen - float proj[4]= {0.f,0.f,0.f,0.f}; + float proj[4] = {0.f,0.f,0.f,0.f}; GetProjPlane(mMaterial, i, 0, proj); glTexGenfv(GL_S, plane, proj); @@ -835,29 +835,29 @@ PyTypeObject KX_BlenderMaterial::Type = { py_base_new }; -PyObject* KX_BlenderMaterial::pyattr_get_shader(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_BlenderMaterial::pyattr_get_shader(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_BlenderMaterial* self= static_cast(self_v); + KX_BlenderMaterial* self = static_cast(self_v); return self->PygetShader(NULL, NULL); } -PyObject* KX_BlenderMaterial::pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_BlenderMaterial::pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_BlenderMaterial* self= static_cast(self_v); + KX_BlenderMaterial* self = static_cast(self_v); return PyLong_FromSsize_t(self->GetMaterialIndex()); } -PyObject* KX_BlenderMaterial::pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_BlenderMaterial::pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_BlenderMaterial* self= static_cast(self_v); + KX_BlenderMaterial* self = static_cast(self_v); unsigned int* bfunc = self->getBlendFunc(); return Py_BuildValue("(ll)", (long int)bfunc[0], (long int)bfunc[1]); } int KX_BlenderMaterial::pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_BlenderMaterial* self= static_cast(self_v); - PyObject* obj = self->PysetBlending(value, NULL); + KX_BlenderMaterial* self = static_cast(self_v); + PyObject *obj = self->PysetBlending(value, NULL); if (obj) { Py_DECREF(obj); diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index 8fc86ef9cf2..1653669ebcc 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -106,11 +106,11 @@ public: #ifdef WITH_PYTHON // -------------------------------- - virtual PyObject* py_repr(void) { return PyUnicode_From_STR_String(mMaterial->matname); } + virtual PyObject *py_repr(void) { return PyUnicode_From_STR_String(mMaterial->matname); } - static PyObject* pyattr_get_shader(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_shader(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); KX_PYMETHOD_DOC(KX_BlenderMaterial, getShader); @@ -119,7 +119,7 @@ public: KX_PYMETHOD_DOC(KX_BlenderMaterial, setTexture); KX_PYMETHOD_DOC(KX_BlenderMaterial, setBlending); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ // -------------------------------- // pre calculate to avoid pops/lag at startup diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp index b974886f60a..20c41b95dd3 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp @@ -269,7 +269,7 @@ void KX_BulletPhysicsController::AddCompoundChild(KX_IPhysicsController* chil rootScale[2] = 1.0/rootScale[2]; // relative scale = child_scale/parent_scale btVector3 relativeScale = childShape->getLocalScaling()*rootScale; - btMatrix3x3 rootRotInverse = rootTrans.getBasis().transpose(); + btMatrix3x3 rootRotInverse = rootTrans.getBasis().transpose(); // relative pos = parent_rot^-1 * ((parent_pos-child_pos)/parent_scale) btVector3 relativePos = rootRotInverse*((childTrans.getOrigin()-rootTrans.getOrigin())*rootScale); // relative rot = parent_rot^-1 * child_rot diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.h b/source/gameengine/Ketsji/KX_BulletPhysicsController.h index 71e806686ca..4813b39a34e 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.h +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.h @@ -96,5 +96,4 @@ public: #endif }; -#endif //__KX_BULLETPHYSICSCONTROLLER_H__ - +#endif /* __KX_BULLETPHYSICSCONTROLLER_H__ */ diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index ac17adaf052..39b0a24865e 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -38,19 +38,19 @@ #include "KX_Python.h" #include "KX_PyMath.h" KX_Camera::KX_Camera(void* sgReplicationInfo, - SG_Callbacks callbacks, - const RAS_CameraData& camdata, - bool frustum_culling, - bool delete_node) - : - KX_GameObject(sgReplicationInfo,callbacks), - m_camdata(camdata), - m_dirty(true), - m_normalized(false), - m_frustum_culling(frustum_culling), - m_set_projection_matrix(false), - m_set_frustum_center(false), - m_delete_node(delete_node) + SG_Callbacks callbacks, + const RAS_CameraData& camdata, + bool frustum_culling, + bool delete_node) + : + KX_GameObject(sgReplicationInfo,callbacks), + m_camdata(camdata), + m_dirty(true), + m_normalized(false), + m_frustum_culling(frustum_culling), + m_set_projection_matrix(false), + m_set_frustum_center(false), + m_delete_node(delete_node) { // setting a name would be nice... m_name = "cam"; @@ -67,7 +67,7 @@ KX_Camera::~KX_Camera() delete m_pSGNode; m_pSGNode = NULL; } -} +} CValue* KX_Camera::GetReplica() @@ -119,7 +119,7 @@ const MT_Point3 KX_Camera::GetCameraLocation() const //MT_Transform trans; //trans.setBasis(NodeGetWorldOrientation()); - return NodeGetWorldPosition(); + return NodeGetWorldPosition(); } @@ -712,15 +712,15 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, setOnTop, Py_RETURN_NONE; } -PyObject* KX_Camera::pyattr_get_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Camera::pyattr_get_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_Camera* self= static_cast(self_v); + KX_Camera* self = static_cast(self_v); return PyBool_FromLong(self->m_camdata.m_perspective); } int KX_Camera::pyattr_set_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_Camera* self= static_cast(self_v); + KX_Camera* self = static_cast(self_v); int param = PyObject_IsTrue( value ); if (param == -1) { PyErr_SetString(PyExc_AttributeError, "camera.perspective = bool: KX_Camera, expected True/False or 0/1"); @@ -732,15 +732,15 @@ int KX_Camera::pyattr_set_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *at return PY_SET_ATTR_SUCCESS; } -PyObject* KX_Camera::pyattr_get_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Camera::pyattr_get_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_Camera* self= static_cast(self_v); + KX_Camera* self = static_cast(self_v); return PyFloat_FromDouble(self->m_camdata.m_lens); } int KX_Camera::pyattr_set_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_Camera* self= static_cast(self_v); + KX_Camera* self = static_cast(self_v); float param = PyFloat_AsDouble(value); if (param == -1) { PyErr_SetString(PyExc_AttributeError, "camera.lens = float: KX_Camera, expected a float greater then zero"); @@ -752,15 +752,15 @@ int KX_Camera::pyattr_set_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, return PY_SET_ATTR_SUCCESS; } -PyObject* KX_Camera::pyattr_get_ortho_scale(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Camera::pyattr_get_ortho_scale(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_Camera* self= static_cast(self_v); + KX_Camera* self = static_cast(self_v); return PyFloat_FromDouble(self->m_camdata.m_scale); } int KX_Camera::pyattr_set_ortho_scale(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_Camera* self= static_cast(self_v); + KX_Camera* self = static_cast(self_v); float param = PyFloat_AsDouble(value); if (param == -1) { PyErr_SetString(PyExc_AttributeError, "camera.ortho_scale = float: KX_Camera, expected a float greater then zero"); @@ -772,15 +772,15 @@ int KX_Camera::pyattr_set_ortho_scale(void *self_v, const KX_PYATTRIBUTE_DEF *at return PY_SET_ATTR_SUCCESS; } -PyObject* KX_Camera::pyattr_get_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Camera::pyattr_get_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_Camera* self= static_cast(self_v); + KX_Camera* self = static_cast(self_v); return PyFloat_FromDouble(self->m_camdata.m_clipstart); } int KX_Camera::pyattr_set_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_Camera* self= static_cast(self_v); + KX_Camera* self = static_cast(self_v); float param = PyFloat_AsDouble(value); if (param == -1) { PyErr_SetString(PyExc_AttributeError, "camera.near = float: KX_Camera, expected a float greater then zero"); @@ -792,15 +792,15 @@ int KX_Camera::pyattr_set_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, return PY_SET_ATTR_SUCCESS; } -PyObject* KX_Camera::pyattr_get_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Camera::pyattr_get_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_Camera* self= static_cast(self_v); + KX_Camera* self = static_cast(self_v); return PyFloat_FromDouble(self->m_camdata.m_clipend); } int KX_Camera::pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_Camera* self= static_cast(self_v); + KX_Camera* self = static_cast(self_v); float param = PyFloat_AsDouble(value); if (param == -1) { PyErr_SetString(PyExc_AttributeError, "camera.far = float: KX_Camera, expected a float greater then zero"); @@ -813,15 +813,15 @@ int KX_Camera::pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, P } -PyObject* KX_Camera::pyattr_get_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Camera::pyattr_get_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_Camera* self= static_cast(self_v); + KX_Camera* self = static_cast(self_v); return PyBool_FromLong(self->GetViewport()); } int KX_Camera::pyattr_set_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_Camera* self= static_cast(self_v); + KX_Camera* self = static_cast(self_v); int param = PyObject_IsTrue( value ); if (param == -1) { PyErr_SetString(PyExc_AttributeError, "camera.useViewport = bool: KX_Camera, expected True or False"); @@ -832,15 +832,15 @@ int KX_Camera::pyattr_set_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *a } -PyObject* KX_Camera::pyattr_get_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Camera::pyattr_get_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_Camera* self= static_cast(self_v); + KX_Camera* self = static_cast(self_v); return PyObjectFrom(self->GetProjectionMatrix()); } int KX_Camera::pyattr_set_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_Camera* self= static_cast(self_v); + KX_Camera* self = static_cast(self_v); MT_Matrix4x4 mat; if (!PyMatTo(value, mat)) return PY_SET_ATTR_FAIL; @@ -849,34 +849,34 @@ int KX_Camera::pyattr_set_projection_matrix(void *self_v, const KX_PYATTRIBUTE_D return PY_SET_ATTR_SUCCESS; } -PyObject* KX_Camera::pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Camera::pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_Camera* self= static_cast(self_v); + KX_Camera* self = static_cast(self_v); return PyObjectFrom(self->GetModelviewMatrix()); } -PyObject* KX_Camera::pyattr_get_camera_to_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Camera::pyattr_get_camera_to_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_Camera* self= static_cast(self_v); + KX_Camera* self = static_cast(self_v); return PyObjectFrom(self->GetCameraToWorld()); } -PyObject* KX_Camera::pyattr_get_world_to_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Camera::pyattr_get_world_to_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_Camera* self= static_cast(self_v); + KX_Camera* self = static_cast(self_v); return PyObjectFrom(self->GetWorldToCamera()); } -PyObject* KX_Camera::pyattr_get_INSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Camera::pyattr_get_INSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { return PyLong_FromSsize_t(INSIDE); } -PyObject* KX_Camera::pyattr_get_OUTSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Camera::pyattr_get_OUTSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { return PyLong_FromSsize_t(OUTSIDE); } -PyObject* KX_Camera::pyattr_get_INTERSECT(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Camera::pyattr_get_INTERSECT(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { return PyLong_FromSsize_t(INTERSECT); } -bool ConvertPythonToCamera(PyObject * value, KX_Camera **object, bool py_none_ok, const char *error_prefix) +bool ConvertPythonToCamera(PyObject *value, KX_Camera **object, bool py_none_ok, const char *error_prefix) { if (value==NULL) { PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix); @@ -956,7 +956,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, getScreenPosition, } } - GLint viewport[4]; + const GLint *viewport; GLdouble win[3]; GLdouble modelmatrix[16]; GLdouble projmatrix[16]; @@ -967,7 +967,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, getScreenPosition, m_modelmatrix.getValue(modelmatrix); m_projmatrix.getValue(projmatrix); - glGetIntegerv(GL_VIEWPORT, viewport); + viewport = KX_GetActiveEngine()->GetCanvas()->GetViewPort(); gluProject(vect[0], vect[1], vect[2], modelmatrix, projmatrix, viewport, &win[0], &win[1], &win[2]); @@ -976,7 +976,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, getScreenPosition, vect[1] = 1.0 - vect[1]; //to follow Blender window coordinate system (Top-Down) - PyObject* ret = PyTuple_New(2); + PyObject *ret = PyTuple_New(2); if (ret) { PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(vect[0])); PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(vect[1])); @@ -999,7 +999,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenVect, MT_Vector3 vect; MT_Point3 campos, screenpos; - GLint viewport[4]; + const GLint *viewport; GLdouble win[3]; GLdouble modelmatrix[16]; GLdouble projmatrix[16]; @@ -1010,7 +1010,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenVect, m_modelmatrix.getValue(modelmatrix); m_projmatrix.getValue(projmatrix); - glGetIntegerv(GL_VIEWPORT, viewport); + viewport = KX_GetActiveEngine()->GetCanvas()->GetViewPort(); vect[0] = x * viewport[2]; vect[1] = y * viewport[3]; @@ -1040,7 +1040,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenRay, if (!PyArg_ParseTuple(args,"ddd|s:getScreenRay",&x,&y,&dist,&propName)) return NULL; - PyObject* argValue = PyTuple_New(2); + PyObject *argValue = PyTuple_New(2); PyTuple_SET_ITEM(argValue, 0, PyFloat_FromDouble(x)); PyTuple_SET_ITEM(argValue, 1, PyFloat_FromDouble(y)); @@ -1065,7 +1065,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenRay, if (propName) PyTuple_SET_ITEM(argValue, 2, PyUnicode_FromString(propName)); - PyObject* ret= this->PyrayCastTo(argValue,NULL); + PyObject *ret= this->PyrayCastTo(argValue,NULL); Py_DECREF(argValue); return ret; } diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h index 7481b2eb7f0..f615fefc223 100644 --- a/source/gameengine/Ketsji/KX_Camera.h +++ b/source/gameengine/Ketsji/KX_Camera.h @@ -45,7 +45,7 @@ #ifdef WITH_PYTHON /* utility conversion function */ -bool ConvertPythonToCamera(PyObject * value, KX_Camera **object, bool py_none_ok, const char *error_prefix); +bool ConvertPythonToCamera(PyObject *value, KX_Camera **object, bool py_none_ok, const char *error_prefix); #endif class KX_Camera : public KX_GameObject @@ -120,7 +120,7 @@ protected: /** * whether the camera should delete the node itself (only for shadow camera) */ - bool m_delete_node; + bool m_delete_node; /** * Extracts the camera clip frames from the projection and world-to-camera matrices. @@ -156,7 +156,7 @@ public: * instance allocated on the heap. Ownership of the new * object belongs with the caller. */ - virtual CValue* + virtual CValue* GetReplica( ); virtual void ProcessReplica(); @@ -286,8 +286,8 @@ public: KX_PYMETHOD_DOC_NOARGS(KX_Camera, getCameraToWorld); KX_PYMETHOD_DOC_NOARGS(KX_Camera, getWorldToCamera); - KX_PYMETHOD_DOC_VARARGS(KX_Camera, setViewport); - KX_PYMETHOD_DOC_NOARGS(KX_Camera, setOnTop); + KX_PYMETHOD_DOC_VARARGS(KX_Camera, setViewport); + KX_PYMETHOD_DOC_NOARGS(KX_Camera, setOnTop); KX_PYMETHOD_DOC_O(KX_Camera, getScreenPosition); KX_PYMETHOD_DOC_VARARGS(KX_Camera, getScreenVect); @@ -321,5 +321,4 @@ public: #endif }; -#endif //__KX_CAMERA_H__ - +#endif /* __KX_CAMERA_H__ */ diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index 4c63afa7f3e..a37b1b0c396 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -143,9 +143,9 @@ static void Kx_VecUpMat3(float vec[3], float mat[][3], short axis) } if (axis==3) { cox= 0; coy= 1; coz= 2; /* Y op -Z tr */ - vec[0]= -vec[0]; - vec[1]= -vec[1]; - vec[2]= -vec[2]; + vec[0] = -vec[0]; + vec[1] = -vec[1]; + vec[2] = -vec[2]; } if (axis==4) { cox= 1; coy= 0; coz= 2; /* */ @@ -154,9 +154,9 @@ static void Kx_VecUpMat3(float vec[3], float mat[][3], short axis) cox= 2; coy= 1; coz= 0; /* Y up X tr */ } - mat[coz][0]= vec[0]; - mat[coz][1]= vec[1]; - mat[coz][2]= vec[2]; + mat[coz][0] = vec[0]; + mat[coz][1] = vec[1]; + mat[coz][2] = vec[2]; if (normalize_v3((float *)mat[coz]) == 0.f) { /* this is a very abnormal situation: the camera has reach the object center exactly * We will choose a completely arbitrary direction */ @@ -281,13 +281,13 @@ bool KX_CameraActuator::Update(double curtime, bool frame) assert(0); break; } - + inp = fp1[0]*fp2[0] + fp1[1]*fp2[1] + fp1[2]*fp2[2]; fac = (-1.0f + inp) * m_damping; - from[0]+= fac*fp1[0]; - from[1]+= fac*fp1[1]; - from[2]+= fac*fp1[2]; + from[0] += fac * fp1[0]; + from[1] += fac * fp1[1]; + from[2] += fac * fp1[2]; /* alleen alstie ervoor ligt: cross testen en loodrechte bijtellen */ if (inp < 0.0f) { @@ -303,9 +303,9 @@ bool KX_CameraActuator::Update(double curtime, bool frame) /* CONSTRAINT 5: minimum / maximum afstand */ - rc[0]= (lookat[0]-from[0]); - rc[1]= (lookat[1]-from[1]); - rc[2]= (lookat[2]-from[2]); + rc[0] = (lookat[0]-from[0]); + rc[1] = (lookat[1]-from[1]); + rc[2] = (lookat[2]-from[2]); distsq = rc[0]*rc[0] + rc[1]*rc[1] + rc[2]*rc[2]; if (distsq > maxdistsq) { @@ -325,9 +325,9 @@ bool KX_CameraActuator::Update(double curtime, bool frame) /* CONSTRAINT 7: track to schaduw */ - rc[0]= (lookat[0]-from[0]); - rc[1]= (lookat[1]-from[1]); - rc[2]= (lookat[2]-from[2]); + rc[0] = (lookat[0]-from[0]); + rc[1] = (lookat[1]-from[1]); + rc[2] = (lookat[2]-from[2]); Kx_VecUpMat3(rc, mat, 3); /* y up Track -z */ @@ -337,9 +337,9 @@ bool KX_CameraActuator::Update(double curtime, bool frame) obj->NodeSetLocalPosition(from); - actormat[0][0]= mat[0][0]; actormat[0][1]= mat[1][0]; actormat[0][2]= mat[2][0]; - actormat[1][0]= mat[0][1]; actormat[1][1]= mat[1][1]; actormat[1][2]= mat[2][1]; - actormat[2][0]= mat[0][2]; actormat[2][1]= mat[1][2]; actormat[2][2]= mat[2][2]; + actormat[0][0] = mat[0][0]; actormat[0][1] = mat[1][0]; actormat[0][2] = mat[2][0]; + actormat[1][0] = mat[0][1]; actormat[1][1] = mat[1][1]; actormat[1][2] = mat[2][1]; + actormat[2][0] = mat[0][2]; actormat[2][1] = mat[1][2]; actormat[2][2] = mat[2][2]; obj->NodeSetLocalOrientation(actormat); return true; @@ -394,9 +394,9 @@ PyAttributeDef KX_CameraActuator::Attributes[] = { {NULL} }; -PyObject* KX_CameraActuator::pyattr_get_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_CameraActuator::pyattr_get_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_CameraActuator* self= static_cast(self_v); + KX_CameraActuator* self = static_cast(self_v); if (self->m_ob==NULL) Py_RETURN_NONE; else @@ -405,14 +405,14 @@ PyObject* KX_CameraActuator::pyattr_get_object(void *self_v, const KX_PYATTRIBUT int KX_CameraActuator::pyattr_set_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_CameraActuator* self= static_cast(self_v); + KX_CameraActuator* self = static_cast(self_v); KX_GameObject *gameobj; if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_CameraActuator")) return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error if (self->m_ob) - self->m_ob->UnregisterActuator(self); + self->m_ob->UnregisterActuator(self); if ((self->m_ob = (SCA_IObject*)gameobj)) self->m_ob->RegisterActuator(self); diff --git a/source/gameengine/Ketsji/KX_CameraActuator.h b/source/gameengine/Ketsji/KX_CameraActuator.h index c67174d2830..fb0a7d88dd9 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.h +++ b/source/gameengine/Ketsji/KX_CameraActuator.h @@ -131,9 +131,8 @@ private : static PyObject* pyattr_get_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; -#endif //__KX_CAMERAACTUATOR_H__ - +#endif /* __KX_CAMERAACTUATOR_H__ */ diff --git a/source/gameengine/Ketsji/KX_CameraIpoSGController.h b/source/gameengine/Ketsji/KX_CameraIpoSGController.h index 06058760332..1f6f211622c 100644 --- a/source/gameengine/Ketsji/KX_CameraIpoSGController.h +++ b/source/gameengine/Ketsji/KX_CameraIpoSGController.h @@ -77,13 +77,13 @@ public: m_ipotime = time; m_modified = true; } - void SetModifyLens(bool modify) { + void SetModifyLens(bool modify) { m_modify_lens = modify; } - void SetModifyClipEnd(bool modify) { + void SetModifyClipEnd(bool modify) { m_modify_clipend = modify; } - void SetModifyClipStart(bool modify) { + void SetModifyClipStart(bool modify) { m_modify_clipstart = modify; } void AddInterpolator(KX_IInterpolator* interp); @@ -94,5 +94,4 @@ public: #endif }; -#endif // __KX_CAMERAIPOSGCONTROLLER_H__ - +#endif /* __KX_CAMERAIPOSGCONTROLLER_H__ */ diff --git a/source/gameengine/Ketsji/KX_CharacterWrapper.cpp b/source/gameengine/Ketsji/KX_CharacterWrapper.cpp new file mode 100644 index 00000000000..ce208f3a75f --- /dev/null +++ b/source/gameengine/Ketsji/KX_CharacterWrapper.cpp @@ -0,0 +1,94 @@ +/** \file gameengine/Ketsji/KX_CharacterWrapper.cpp + * \ingroup ketsji + */ + + +#include "KX_CharacterWrapper.h" +#include "PHY_ICharacter.h" + +KX_CharacterWrapper::KX_CharacterWrapper(PHY_ICharacter* character) : + PyObjectPlus(), + m_character(character) +{ +} + +KX_CharacterWrapper::~KX_CharacterWrapper() +{ + if (m_character) + delete m_character; // We're responsible for the character object! +} + +#ifdef WITH_PYTHON + +PyTypeObject KX_CharacterWrapper::Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "KX_CharacterWrapper", + sizeof(PyObjectPlus_Proxy), + 0, + py_base_dealloc, + 0, + 0, + 0, + 0, + py_base_repr, + 0,0,0,0,0,0,0,0,0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new +}; + +PyAttributeDef KX_CharacterWrapper::Attributes[] = { + KX_PYATTRIBUTE_RO_FUNCTION("onGround", KX_CharacterWrapper, pyattr_get_onground), + KX_PYATTRIBUTE_RW_FUNCTION("gravity", KX_CharacterWrapper, pyattr_get_gravity, pyattr_set_gravity), + { NULL } //Sentinel +}; + +PyObject *KX_CharacterWrapper::pyattr_get_onground(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_CharacterWrapper* self = static_cast(self_v); + + return PyBool_FromLong(self->m_character->OnGround()); +} + +PyObject *KX_CharacterWrapper::pyattr_get_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_CharacterWrapper* self = static_cast(self_v); + + return PyFloat_FromDouble(self->m_character->GetGravity()); +} + +int KX_CharacterWrapper::pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_CharacterWrapper* self = static_cast(self_v); + double param = PyFloat_AsDouble(value); + + if (param == -1) + { + PyErr_SetString(PyExc_ValueError, "KX_CharacterWrapper.gravity: expected a float"); + return PY_SET_ATTR_FAIL; + } + + self->m_character->SetGravity((float)param); + return PY_SET_ATTR_SUCCESS; +} + +PyMethodDef KX_CharacterWrapper::Methods[] = { + KX_PYMETHODTABLE_NOARGS(KX_CharacterWrapper, jump), + {NULL,NULL} //Sentinel +}; + +KX_PYMETHODDEF_DOC_NOARGS(KX_CharacterWrapper, jump, + "jump()\n" + "makes the character jump.\n") +{ + m_character->Jump(); + + Py_RETURN_NONE; +} + +#endif // WITH_PYTHON diff --git a/source/gameengine/Ketsji/KX_CharacterWrapper.h b/source/gameengine/Ketsji/KX_CharacterWrapper.h new file mode 100644 index 00000000000..cc99aba99f6 --- /dev/null +++ b/source/gameengine/Ketsji/KX_CharacterWrapper.h @@ -0,0 +1,35 @@ + +/** \file KX_CharacterWrapper.h + * \ingroup ketsji + */ + +#ifndef __KX_CHARACTERWRAPPER_H__ +#define __KX_CHARACTERWRAPPER_H__ + +#include "Value.h" +#include "PHY_DynamicTypes.h" +class PHY_ICharacter; + + +///Python interface to character physics +class KX_CharacterWrapper : public PyObjectPlus +{ + Py_Header + +public: + KX_CharacterWrapper(PHY_ICharacter* character); + virtual ~KX_CharacterWrapper(); +#ifdef WITH_PYTHON + KX_PYMETHOD_DOC_NOARGS(KX_CharacterWrapper, jump); + + static PyObject* pyattr_get_onground(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + + static PyObject* pyattr_get_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); +#endif // WITH_PYTHON + +private: + PHY_ICharacter* m_character; +}; + +#endif //__KX_CHARACTERWRAPPER_H__ diff --git a/source/gameengine/Ketsji/KX_ClientObjectInfo.h b/source/gameengine/Ketsji/KX_ClientObjectInfo.h index 6fd1271160a..e947eb4be6d 100644 --- a/source/gameengine/Ketsji/KX_ClientObjectInfo.h +++ b/source/gameengine/Ketsji/KX_ClientObjectInfo.h @@ -84,5 +84,4 @@ public: #endif }; -#endif //__KX_CLIENTOBJECTINFO_H__ - +#endif /* __KX_CLIENTOBJECTINFO_H__ */ diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp index 322d6e60071..3caa4d35565 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp @@ -166,7 +166,7 @@ bool KX_ConstraintActuator::NeedRayCast(KX_ClientObjectInfo* client) bool KX_ConstraintActuator::Update(double curtime, bool frame) { - bool result = false; + bool result = false; bool bNegativeEvent = IsNegativeEvent(); RemoveAllEvents(); @@ -462,7 +462,7 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) // we expect a hit object if (!m_hitObject) result = false; - if (result) + if (result) { MT_Vector3 newnormal = callback.m_hitNormal; // compute new position & orientation @@ -619,7 +619,7 @@ int KX_ConstraintActuator::pyattr_check_direction(void *self, const struct KX_PY return 1; } act->m_refDirVector = dir/len; - return 0; + return 0; } #endif diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h index f491aedba74..edb2e5e0180 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.h +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h @@ -43,7 +43,7 @@ class KX_GameObject; class KX_ConstraintActuator : public SCA_IActuator { Py_Header -protected: +protected: // Damp time (int), int m_posDampTime; int m_rotDampTime; @@ -145,5 +145,4 @@ protected: }; -#endif //__KX_CONSTRAINTACTUATOR_H__ - +#endif /* __KX_CONSTRAINTACTUATOR_H__ */ diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp index df6b08974dd..662db974ee8 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp @@ -50,13 +50,13 @@ KX_ConstraintWrapper::~KX_ConstraintWrapper() #ifdef WITH_PYTHON -PyObject* KX_ConstraintWrapper::PyGetConstraintId() +PyObject *KX_ConstraintWrapper::PyGetConstraintId() { return PyLong_FromSsize_t(m_constraintId); } -PyObject* KX_ConstraintWrapper::PyGetParam(PyObject* args, PyObject* kwds) +PyObject *KX_ConstraintWrapper::PyGetParam(PyObject *args, PyObject *kwds) { int dof; float value; @@ -69,7 +69,7 @@ PyObject* KX_ConstraintWrapper::PyGetParam(PyObject* args, PyObject* kwds) } -PyObject* KX_ConstraintWrapper::PySetParam(PyObject* args, PyObject* kwds) +PyObject *KX_ConstraintWrapper::PySetParam(PyObject *args, PyObject *kwds) { int dof; float minLimit,maxLimit; @@ -117,9 +117,9 @@ PyAttributeDef KX_ConstraintWrapper::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_ConstraintWrapper::pyattr_get_constraintId(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_ConstraintWrapper::pyattr_get_constraintId(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_ConstraintWrapper* self= static_cast(self_v); + KX_ConstraintWrapper* self = static_cast(self_v); return self->PyGetConstraintId(); } diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.h b/source/gameengine/Ketsji/KX_ConstraintWrapper.h index a92ae83e7f0..eafc45b5a70 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.h +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.h @@ -48,7 +48,7 @@ public: KX_PYMETHOD(KX_ConstraintWrapper,SetParam); KX_PYMETHOD(KX_ConstraintWrapper,GetParam); - static PyObject* pyattr_get_constraintId(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_constraintId(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); #endif private: @@ -57,5 +57,4 @@ private: PHY_IPhysicsEnvironment* m_physenv; }; -#endif //__KX_CONSTRAINTWRAPPER_H__ - +#endif /* __KX_CONSTRAINTWRAPPER_H__ */ diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h index 0f1ce403881..e71037d08a0 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h @@ -159,4 +159,4 @@ void KX_ClearBulletSharedShapes(); bool KX_ReInstanceBulletShapeFromMesh(KX_GameObject *gameobj, KX_GameObject *from_gameobj, RAS_MeshObject* from_meshobj); #endif -#endif //__KX_CONVERTPHYSICSOBJECT_H__ +#endif /* __KX_CONVERTPHYSICSOBJECT_H__ */ diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index f1038c04499..ff3c46cb8ab 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -29,8 +29,8 @@ * \ingroup ketsji */ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable : 4786) +#ifdef _MSC_VER +# pragma warning (disable:4786) #endif #include "MT_assert.h" @@ -54,6 +54,7 @@ #include "KX_MotionState.h" // bridge between motionstate and scenegraph node extern "C"{ + #include "BLI_utildefines.h" #include "BKE_DerivedMesh.h" } @@ -282,7 +283,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, relativeRot.getValue(rot); shapeInfo->m_childTrans.getBasis().setFromOpenGLSubMatrix(rot); - parentShapeInfo->AddShape(shapeInfo); + parentShapeInfo->AddShape(shapeInfo); compoundShape->addChildShape(shapeInfo->m_childTrans,bm); //do some recalc? //recalc inertia for rigidbody @@ -439,7 +440,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, { env->addCcdPhysicsController( physicscontroller); } - physicscontroller->setNewClientInfo(gameobj->getClientInfo()); + physicscontroller->setNewClientInfo(gameobj->getClientInfo()); { btRigidBody* rbody = physicscontroller->GetRigidBody(); diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp index 44c9cb1dab8..fca407f6398 100644 --- a/source/gameengine/Ketsji/KX_Dome.cpp +++ b/source/gameengine/Ketsji/KX_Dome.cpp @@ -90,12 +90,11 @@ KX_Dome::KX_Dome ( } //setting the viewport size - GLuint viewport[4]={0}; - glGetIntegerv(GL_VIEWPORT,(GLint *)viewport); + const int *viewport = m_canvas->GetViewPort(); SetViewPort(viewport); - switch(m_mode) { + switch (m_mode) { case DOME_FISHEYE: if (m_angle <= 180) { cubetop.resize(1); @@ -178,7 +177,7 @@ KX_Dome::~KX_Dome (void) glDeleteLists(dlistId, (GLsizei) m_numimages); } -void KX_Dome::SetViewPort(GLuint viewport[4]) +void KX_Dome::SetViewPort(const int viewport[4]) { if (canvaswidth != m_viewport.GetWidth() || canvasheight != m_viewport.GetHeight()) { @@ -592,7 +591,7 @@ void KX_Dome::CreateMeshDome180(void) cubebottom[0].u[2] = 0.0; cubebottom[0].v[2] = 0.0; - nfacesbottom = 1; + nfacesbottom = 1; /* Left face - two triangles */ @@ -682,12 +681,12 @@ void KX_Dome::CreateMeshDome180(void) cubetop.resize(4*nfacestop); SplitFace(cubetop,&nfacestop); cubebottom.resize(4*nfacesbottom); - SplitFace(cubebottom,&nfacesbottom); + SplitFace(cubebottom,&nfacesbottom); cubeleft.resize(4*nfacesleft); SplitFace(cubeleft,&nfacesleft); cuberight.resize(4*nfacesright); SplitFace(cuberight,&nfacesright); - } + } // Turn into a hemisphere for (j=0;j<3;j++) { @@ -763,13 +762,13 @@ void KX_Dome::CreateMeshDome250(void) cubefront[0].verts[1][0] = 1.0; cubefront[0].verts[1][1] = 1.0; - cubefront[0].verts[1][2] = 1.0; + cubefront[0].verts[1][2] = 1.0; cubefront[0].u[1] = uv_ratio; cubefront[0].v[1] = uv_ratio; cubefront[0].verts[2][0] =-1.0; cubefront[0].verts[2][1] = 1.0; - cubefront[0].verts[2][2] = 1.0; + cubefront[0].verts[2][2] = 1.0; cubefront[0].u[2] = 0.0; cubefront[0].v[2] = uv_ratio; @@ -782,13 +781,13 @@ void KX_Dome::CreateMeshDome250(void) cubefront[1].verts[1][0] =-1.0; cubefront[1].verts[1][1] = 1.0; - cubefront[1].verts[1][2] =-1.0; + cubefront[1].verts[1][2] =-1.0; cubefront[1].u[1] = 0.0; cubefront[1].v[1] = 0.0; cubefront[1].verts[2][0] = 1.0; cubefront[1].verts[2][1] = 1.0; - cubefront[1].verts[2][2] =-1.0; + cubefront[1].verts[2][2] =-1.0; cubefront[1].u[2] = uv_ratio; cubefront[1].v[2] = 0.0; @@ -803,13 +802,13 @@ void KX_Dome::CreateMeshDome250(void) cubeleft[0].verts[1][0] =-1.0; cubeleft[0].verts[1][1] =-verts_height; - cubeleft[0].verts[1][2] = 1.0; + cubeleft[0].verts[1][2] = 1.0; cubeleft[0].u[1] = uv_base; cubeleft[0].v[1] = uv_ratio; cubeleft[0].verts[2][0] =-1.0; cubeleft[0].verts[2][1] =-verts_height; - cubeleft[0].verts[2][2] =-1.0; + cubeleft[0].verts[2][2] =-1.0; cubeleft[0].u[2] = uv_base; cubeleft[0].v[2] = 0.0; @@ -822,13 +821,13 @@ void KX_Dome::CreateMeshDome250(void) cubeleft[1].verts[1][0] =-1.0; cubeleft[1].verts[1][1] = 1.0; - cubeleft[1].verts[1][2] =-1.0; + cubeleft[1].verts[1][2] =-1.0; cubeleft[1].u[1] = uv_ratio; cubeleft[1].v[1] = 0.0; cubeleft[1].verts[2][0] =-1.0; cubeleft[1].verts[2][1] = 1.0; - cubeleft[1].verts[2][2] = 1.0; + cubeleft[1].verts[2][2] = 1.0; cubeleft[1].u[2] = uv_ratio; cubeleft[1].v[2] = uv_ratio; @@ -843,13 +842,13 @@ void KX_Dome::CreateMeshDome250(void) cuberight[0].verts[1][0] = 1.0; cuberight[0].verts[1][1] =-verts_height; - cuberight[0].verts[1][2] =-1.0; + cuberight[0].verts[1][2] =-1.0; cuberight[0].u[1] = uv_height; cuberight[0].v[1] = 0.0; cuberight[0].verts[2][0] = 1.0; cuberight[0].verts[2][1] =-verts_height; - cuberight[0].verts[2][2] = 1.0; + cuberight[0].verts[2][2] = 1.0; cuberight[0].u[2] = uv_height; cuberight[0].v[2] = uv_ratio; @@ -862,13 +861,13 @@ void KX_Dome::CreateMeshDome250(void) cuberight[1].verts[1][0] = 1.0; cuberight[1].verts[1][1] = 1.0; - cuberight[1].verts[1][2] = 1.0; + cuberight[1].verts[1][2] = 1.0; cuberight[1].u[1] = 0.0; cuberight[1].v[1] = uv_ratio; cuberight[1].verts[2][0] = 1.0; cuberight[1].verts[2][1] = 1.0; - cuberight[1].verts[2][2] =-1.0; + cuberight[1].verts[2][2] =-1.0; cuberight[1].u[2] = 0.0; cuberight[1].v[2] = 0.0; @@ -883,13 +882,13 @@ void KX_Dome::CreateMeshDome250(void) cubetop[0].verts[1][0] = 1.0; cubetop[0].verts[1][1] =-verts_height; - cubetop[0].verts[1][2] = 1.0; + cubetop[0].verts[1][2] = 1.0; cubetop[0].u[1] = uv_ratio; cubetop[0].v[1] = uv_height; cubetop[0].verts[2][0] =-1.0; cubetop[0].verts[2][1] =-verts_height; - cubetop[0].verts[2][2] = 1.0; + cubetop[0].verts[2][2] = 1.0; cubetop[0].u[2] = 0.0; cubetop[0].v[2] = uv_height; @@ -902,13 +901,13 @@ void KX_Dome::CreateMeshDome250(void) cubetop[1].verts[1][0] =-1.0; cubetop[1].verts[1][1] = 1.0; - cubetop[1].verts[1][2] = 1.0; + cubetop[1].verts[1][2] = 1.0; cubetop[1].u[1] = 0.0; cubetop[1].v[1] = 0.0; cubetop[1].verts[2][0] = 1.0; cubetop[1].verts[2][1] = 1.0; - cubetop[1].verts[2][2] = 1.0; + cubetop[1].verts[2][2] = 1.0; cubetop[1].u[2] = uv_ratio; cubetop[1].v[2] = 0.0; @@ -923,13 +922,13 @@ void KX_Dome::CreateMeshDome250(void) cubebottom[0].verts[1][0] = 1.0; cubebottom[0].verts[1][1] = 1.0; - cubebottom[0].verts[1][2] =-1.0; + cubebottom[0].verts[1][2] =-1.0; cubebottom[0].u[1] = uv_ratio; cubebottom[0].v[1] = uv_ratio; cubebottom[0].verts[2][0] =-1.0; cubebottom[0].verts[2][1] = 1.0; - cubebottom[0].verts[2][2] =-1.0; + cubebottom[0].verts[2][2] =-1.0; cubebottom[0].u[2] = 0.0; cubebottom[0].v[2] = uv_ratio; @@ -942,13 +941,13 @@ void KX_Dome::CreateMeshDome250(void) cubebottom[1].verts[1][0] =-1.0; cubebottom[1].verts[1][1] =-verts_height; - cubebottom[1].verts[1][2] =-1.0; + cubebottom[1].verts[1][2] =-1.0; cubebottom[1].u[1] = 0.0; cubebottom[1].v[1] = uv_base; cubebottom[1].verts[2][0] = 1.0; cubebottom[1].verts[2][1] =-verts_height; - cubebottom[1].verts[2][2] =-1.0; + cubebottom[1].verts[2][2] =-1.0; cubebottom[1].u[2] = uv_ratio; cubebottom[1].v[2] = uv_base; @@ -963,7 +962,7 @@ void KX_Dome::CreateMeshDome250(void) cubetop.resize(4*nfacestop); SplitFace(cubetop,&nfacestop); cubebottom.resize(4*nfacesbottom); - SplitFace(cubebottom,&nfacesbottom); + SplitFace(cubebottom,&nfacesbottom); cubeleft.resize(4*nfacesleft); SplitFace(cubeleft,&nfacesleft); cuberight.resize(4*nfacesright); @@ -986,13 +985,13 @@ void KX_Dome::CreateMeshDome250(void) //flatten onto xz plane for (i=0;i& face, int *nfaces) face[n2+2].u[2] = (face[i].u[2] + face[i].u[0]) /2; face[n2+2].v[0] = (face[i].v[0] + face[i].v[1]) /2; face[n2+2].v[1] = (face[i].v[1] + face[i].v[2]) /2; - face[n2+2].v[2] = (face[i].v[2] + face[i].v[0]) /2; + face[n2+2].v[2] = (face[i].v[2] + face[i].v[0]) /2; //face[i].verts[0] = face[i].verts[0]; face[i].verts[1] = (face[i].verts[0] + face[i].verts[1]) /2; @@ -1427,7 +1426,7 @@ void KX_Dome::SplitFace(vector & face, int *nfaces) face[i].u[2] = (face[i].u[0] + face[i].u[2]) /2; //face[i].v[0] = face[i].v[0]; face[i].v[1] = (face[i].v[0] + face[i].v[1]) /2; - face[i].v[2] = (face[i].v[0] + face[i].v[2]) /2; + face[i].v[2] = (face[i].v[0] + face[i].v[2]) /2; n2 += 3; // number of faces } @@ -1621,7 +1620,7 @@ void KX_Dome::Draw(void) glScissor(0,0,warp.imagesize, warp.imagesize); } - switch(m_mode) { + switch (m_mode) { case DOME_FISHEYE: DrawDomeFisheye(); break; @@ -1858,7 +1857,7 @@ void KX_Dome::DrawDomeFisheye(void) glBindTexture(GL_TEXTURE_2D, domefacesId[0]); GLDrawTriangles(cubetop, nfacestop); - // bottom triangle + // bottom triangle glBindTexture(GL_TEXTURE_2D, domefacesId[1]); GLDrawTriangles(cubebottom, nfacesbottom); diff --git a/source/gameengine/Ketsji/KX_Dome.h b/source/gameengine/Ketsji/KX_Dome.h index 24177af5d60..17eec3a5fcb 100644 --- a/source/gameengine/Ketsji/KX_Dome.h +++ b/source/gameengine/Ketsji/KX_Dome.h @@ -119,7 +119,7 @@ public: void RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i); void BindImages(int i); - void SetViewPort(GLuint viewport[4]); + void SetViewPort(const int viewport[4]); void CalculateFrustum(KX_Camera* cam); void RotateCamera(KX_Camera* cam, int i); diff --git a/source/gameengine/Ketsji/KX_EmptyObject.h b/source/gameengine/Ketsji/KX_EmptyObject.h index b99f44c38c5..63a0782a544 100644 --- a/source/gameengine/Ketsji/KX_EmptyObject.h +++ b/source/gameengine/Ketsji/KX_EmptyObject.h @@ -47,5 +47,4 @@ public: #endif }; -#endif //__KX_EMPTYOBJECT_H__ - +#endif /* __KX_EMPTYOBJECT_H__ */ diff --git a/source/gameengine/Ketsji/KX_FontObject.cpp b/source/gameengine/Ketsji/KX_FontObject.cpp index 931eac7a974..138124f9b1a 100644 --- a/source/gameengine/Ketsji/KX_FontObject.cpp +++ b/source/gameengine/Ketsji/KX_FontObject.cpp @@ -52,7 +52,7 @@ extern "C" { /* proptotype */ int GetFontId(VFont *font); -std::vector split_string(STR_String str) +static std::vector split_string(STR_String str) { std::vector text = std::vector(); @@ -73,10 +73,10 @@ std::vector split_string(STR_String str) return text; } -KX_FontObject::KX_FontObject( void* sgReplicationInfo, - SG_Callbacks callbacks, - RAS_IRenderTools* rendertools, - Object *ob): +KX_FontObject::KX_FontObject(void* sgReplicationInfo, + SG_Callbacks callbacks, + RAS_IRenderTools* rendertools, + Object *ob): KX_GameObject(sgReplicationInfo, callbacks), m_object(ob), m_dpi(72), @@ -252,9 +252,9 @@ PyAttributeDef KX_FontObject::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_FontObject::pyattr_get_text(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_FontObject::pyattr_get_text(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_FontObject* self= static_cast(self_v); + KX_FontObject* self = static_cast(self_v); STR_String str = STR_String(); for (int i=0; im_text.size(); ++i) { @@ -267,7 +267,7 @@ PyObject* KX_FontObject::pyattr_get_text(void *self_v, const KX_PYATTRIBUTE_DEF int KX_FontObject::pyattr_set_text(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_FontObject* self= static_cast(self_v); + KX_FontObject* self = static_cast(self_v); if (!PyUnicode_Check(value)) return PY_SET_ATTR_FAIL; char* chars = _PyUnicode_AsString(value); diff --git a/source/gameengine/Ketsji/KX_FontObject.h b/source/gameengine/Ketsji/KX_FontObject.h index ae8b4166238..ac22de6fb6f 100644 --- a/source/gameengine/Ketsji/KX_FontObject.h +++ b/source/gameengine/Ketsji/KX_FontObject.h @@ -76,4 +76,4 @@ protected: }; -#endif //__KX_FONTOBJECT_H__ +#endif /* __KX_FONTOBJECT_H__ */ diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 3818cef7d6e..a669f4346ea 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -30,6 +30,11 @@ * \ingroup ketsji */ +#ifdef _MSC_VER + /* This warning tells us about truncation of __long__ stl-generated names. + * It can occasionally cause DevStudio to have internal compiler warnings. */ +# pragma warning( disable:4786 ) +#endif #if defined(_WIN64) && !defined(FREE_WINDOWS64) typedef unsigned __int64 uint_ptr; @@ -37,13 +42,6 @@ typedef unsigned __int64 uint_ptr; typedef unsigned long uint_ptr; #endif -#if defined(WIN32) && !defined(FREE_WINDOWS) -// This warning tells us about truncation of __long__ stl-generated names. -// It can occasionally cause DevStudio to have internal compiler warnings. -#pragma warning( disable : 4786 ) -#endif - - #define KX_INERTIA_INFINITE 10000 #include "RAS_IPolygonMaterial.h" #include "KX_BlenderMaterial.h" @@ -109,6 +107,8 @@ KX_GameObject::KX_GameObject( m_xray(false), m_pHitObject(NULL), m_pObstacleSimulation(NULL), + m_pInstanceObjects(NULL), + m_pDupliGroupObject(NULL), m_actionManager(NULL), m_isDeformable(false) #ifdef WITH_PYTHON @@ -168,6 +168,16 @@ KX_GameObject::~KX_GameObject() KX_GetActiveScene()->RemoveAnimatedObject(this); delete m_actionManager; } + + if (m_pDupliGroupObject) + { + m_pDupliGroupObject->Release(); + } + + if (m_pInstanceObjects) + { + m_pInstanceObjects->Release(); + } #ifdef WITH_PYTHON if (m_attr_dict) { PyDict_Clear(m_attr_dict); /* in case of circular refs or other weird cases */ @@ -218,17 +228,57 @@ STR_String& KX_GameObject::GetName() } - +/* Set the name of the value */ void KX_GameObject::SetName(const char *name) { m_name = name; -}; // Set the name of the value +} KX_IPhysicsController* KX_GameObject::GetPhysicsController() { return m_pPhysicsController1; } +KX_GameObject* KX_GameObject::GetDupliGroupObject() +{ + return m_pDupliGroupObject; +} + +CListValue* KX_GameObject::GetInstanceObjects() +{ + return m_pInstanceObjects; +} + +void KX_GameObject::AddInstanceObjects(KX_GameObject* obj) +{ + if (!m_pInstanceObjects) + m_pInstanceObjects = new CListValue(); + + obj->AddRef(); + m_pInstanceObjects->Add(obj); +} + +void KX_GameObject::RemoveInstanceObject(KX_GameObject* obj) +{ + assert(m_pInstanceObjects); + m_pInstanceObjects->RemoveValue(obj); + obj->Release(); +} + +void KX_GameObject::RemoveDupliGroupObject() +{ + if (m_pDupliGroupObject) { + m_pDupliGroupObject->Release(); + m_pDupliGroupObject = NULL; + } +} + +void KX_GameObject::SetDupliGroupObject(KX_GameObject* obj) +{ + obj->AddRef(); + m_pDupliGroupObject = obj; +} + KX_GameObject* KX_GameObject::GetParent() { KX_GameObject* result = NULL; @@ -362,7 +412,7 @@ BL_ActionManager* KX_GameObject::GetActionManager() { // We only want to create an action manager if we need it if (!m_actionManager) - { + { KX_GetActiveScene()->AddAnimatedObject(this); m_actionManager = new BL_ActionManager(this); } @@ -481,6 +531,19 @@ void KX_GameObject::ActivateGraphicController(bool recurse) } } +void KX_GameObject::SetUserCollisionGroup(short group) +{ + m_userCollisionGroup = group; +} +void KX_GameObject::SetUserCollisionMask(short mask) +{ + m_userCollisionMask = mask; +} + +bool KX_GameObject::CheckCollision(KX_GameObject* other) +{ + return this->m_userCollisionGroup & other->m_userCollisionMask; +} CValue* KX_GameObject::GetReplica() { @@ -690,7 +753,7 @@ void KX_GameObject::SynchronizeTransformFunc(SG_IObject* node, void* gameobj, vo void KX_GameObject::SetDebugColor(unsigned int bgra) { for (size_t i=0;iDebugColor(bgra); + m_meshes[i]->DebugColor(bgra); } @@ -701,8 +764,8 @@ void KX_GameObject::ResetDebugColor() } void KX_GameObject::InitIPO(bool ipo_as_force, - bool ipo_add, - bool ipo_local) + bool ipo_add, + bool ipo_local) { SGControllerList::iterator it = GetSGNode()->GetSGControllerList().begin(); @@ -939,7 +1002,7 @@ void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac) vect /= len; orimat = GetSGNode()->GetWorldOrientation(); switch (axis) - { + { case 0: //x axis ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]); //pivot axis if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) //is the vector parallel to the pivot? @@ -1041,7 +1104,7 @@ MT_Vector3 KX_GameObject::GetLinearVelocity(bool local) return locvel; } } - return velocity; + return velocity; } MT_Vector3 KX_GameObject::GetAngularVelocity(bool local) @@ -1060,7 +1123,7 @@ MT_Vector3 KX_GameObject::GetAngularVelocity(bool local) return locvel; } } - return velocity; + return velocity; } MT_Vector3 KX_GameObject::GetVelocity(const MT_Point3& point) @@ -1377,8 +1440,8 @@ static unsigned char mathutils_kxgameob_vector_cb_index= -1; /* index for our ca static int mathutils_kxgameob_generic_check(BaseMathObject *bmo) { - KX_GameObject* self= static_castBGE_PROXY_REF(bmo->cb_user); - if (self==NULL) + KX_GameObject* self = static_castBGE_PROXY_REF(bmo->cb_user); + if (self == NULL) return -1; return 0; @@ -1386,13 +1449,13 @@ static int mathutils_kxgameob_generic_check(BaseMathObject *bmo) static int mathutils_kxgameob_vector_get(BaseMathObject *bmo, int subtype) { - KX_GameObject* self= static_castBGE_PROXY_REF(bmo->cb_user); - if (self==NULL) + KX_GameObject* self = static_castBGE_PROXY_REF(bmo->cb_user); + if (self == NULL) return -1; #define PHYS_ERR(attr) PyErr_SetString(PyExc_AttributeError, "KX_GameObject." attr ", is missing a physics controller") - switch(subtype) { + switch (subtype) { case MATHUTILS_VEC_CB_POS_LOCAL: self->NodeGetLocalPosition().getValue(bmo->data); break; @@ -1438,11 +1501,11 @@ static int mathutils_kxgameob_vector_get(BaseMathObject *bmo, int subtype) static int mathutils_kxgameob_vector_set(BaseMathObject *bmo, int subtype) { - KX_GameObject* self= static_castBGE_PROXY_REF(bmo->cb_user); - if (self==NULL) + KX_GameObject* self = static_castBGE_PROXY_REF(bmo->cb_user); + if (self == NULL) return -1; - switch(subtype) { + switch (subtype) { case MATHUTILS_VEC_CB_POS_LOCAL: self->NodeSetLocalPosition(MT_Point3(bmo->data)); self->NodeUpdateGS(0.f); @@ -1497,7 +1560,7 @@ static int mathutils_kxgameob_vector_set_index(BaseMathObject *bmo, int subtype, if (mathutils_kxgameob_vector_get(bmo, subtype) == -1) return -1; - bmo->data[index]= f; + bmo->data[index] = f; return mathutils_kxgameob_vector_set(bmo, subtype); } @@ -1517,11 +1580,11 @@ static unsigned char mathutils_kxgameob_matrix_cb_index= -1; /* index for our ca static int mathutils_kxgameob_matrix_get(BaseMathObject *bmo, int subtype) { - KX_GameObject* self= static_castBGE_PROXY_REF(bmo->cb_user); - if (self==NULL) + KX_GameObject* self = static_castBGE_PROXY_REF(bmo->cb_user); + if (self == NULL) return -1; - switch(subtype) { + switch (subtype) { case MATHUTILS_MAT_CB_ORI_LOCAL: self->NodeGetLocalOrientation().getValue3x3(bmo->data); break; @@ -1536,12 +1599,12 @@ static int mathutils_kxgameob_matrix_get(BaseMathObject *bmo, int subtype) static int mathutils_kxgameob_matrix_set(BaseMathObject *bmo, int subtype) { - KX_GameObject* self= static_castBGE_PROXY_REF(bmo->cb_user); - if (self==NULL) + KX_GameObject* self = static_castBGE_PROXY_REF(bmo->cb_user); + if (self == NULL) return -1; MT_Matrix3x3 mat3x3; - switch(subtype) { + switch (subtype) { case MATHUTILS_MAT_CB_ORI_LOCAL: mat3x3.setValue3x3(bmo->data); self->NodeSetLocalOrientation(mat3x3); @@ -1629,6 +1692,9 @@ PyMethodDef KX_GameObject::Methods[] = { PyAttributeDef KX_GameObject::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("name", KX_GameObject, pyattr_get_name), KX_PYATTRIBUTE_RO_FUNCTION("parent", KX_GameObject, pyattr_get_parent), + KX_PYATTRIBUTE_RO_FUNCTION("group_children", KX_GameObject, pyattr_get_group_children), + KX_PYATTRIBUTE_RO_FUNCTION("group_parent", KX_GameObject, pyattr_get_group_parent), + KX_PYATTRIBUTE_RO_FUNCTION("scene", KX_GameObject, pyattr_get_scene), KX_PYATTRIBUTE_RO_FUNCTION("life", KX_GameObject, pyattr_get_life), KX_PYATTRIBUTE_RW_FUNCTION("mass", KX_GameObject, pyattr_get_mass, pyattr_set_mass), KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin", KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min), @@ -1668,7 +1734,7 @@ PyAttributeDef KX_GameObject::Attributes[] = { {NULL} //Sentinel }; -PyObject* KX_GameObject::PyReplaceMesh(PyObject* args) +PyObject *KX_GameObject::PyReplaceMesh(PyObject *args) { KX_Scene *scene = KX_GetActiveScene(); @@ -1686,7 +1752,7 @@ PyObject* KX_GameObject::PyReplaceMesh(PyObject* args) Py_RETURN_NONE; } -PyObject* KX_GameObject::PyEndObject() +PyObject *KX_GameObject::PyEndObject() { SG_Node* node = this->GetSGNode(); KX_Scene* scene = static_cast(node->GetSGClientInfo()); @@ -1697,7 +1763,7 @@ PyObject* KX_GameObject::PyEndObject() } -PyObject* KX_GameObject::PyReinstancePhysicsMesh(PyObject* args) +PyObject *KX_GameObject::PyReinstancePhysicsMesh(PyObject *args) { KX_GameObject *gameobj= NULL; RAS_MeshObject *mesh= NULL; @@ -1721,19 +1787,19 @@ PyObject* KX_GameObject::PyReinstancePhysicsMesh(PyObject* args) static PyObject *Map_GetItem(PyObject *self_v, PyObject *item) { - KX_GameObject* self= static_castBGE_PROXY_REF(self_v); + KX_GameObject* self = static_castBGE_PROXY_REF(self_v); const char *attr_str= _PyUnicode_AsString(item); CValue* resultattr; - PyObject* pyconvert; + PyObject *pyconvert; - if (self==NULL) { + if (self == NULL) { PyErr_SetString(PyExc_SystemError, "val = gameOb[key]: KX_GameObject, "BGE_PROXY_ERROR_MSG); return NULL; } /* first see if the attributes a string and try get the cvalue attribute */ if (attr_str && (resultattr=self->GetProperty(attr_str))) { - pyconvert = resultattr->ConvertValueToPython(); + pyconvert = resultattr->ConvertValueToPython(); return pyconvert ? pyconvert:resultattr->GetProxy(); } /* no CValue attribute, try get the python only m_attr_dict attribute */ @@ -1755,12 +1821,12 @@ static PyObject *Map_GetItem(PyObject *self_v, PyObject *item) static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) { - KX_GameObject* self= static_castBGE_PROXY_REF(self_v); + KX_GameObject* self = static_castBGE_PROXY_REF(self_v); const char *attr_str= _PyUnicode_AsString(key); if (attr_str==NULL) PyErr_Clear(); - if (self==NULL) { + if (self == NULL) { PyErr_SetString(PyExc_SystemError, "gameOb[key] = value: KX_GameObject, "BGE_PROXY_ERROR_MSG); return -1; } @@ -1843,9 +1909,9 @@ static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) static int Seq_Contains(PyObject *self_v, PyObject *value) { - KX_GameObject* self= static_castBGE_PROXY_REF(self_v); + KX_GameObject* self = static_castBGE_PROXY_REF(self_v); - if (self==NULL) { + if (self == NULL) { PyErr_SetString(PyExc_SystemError, "val in gameOb: KX_GameObject, "BGE_PROXY_ERROR_MSG); return -1; } @@ -1907,15 +1973,15 @@ PyTypeObject KX_GameObject::Type = { py_base_new }; -PyObject* KX_GameObject::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); return PyUnicode_From_STR_String(self->GetName()); } -PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); KX_GameObject* parent = self->GetParent(); if (parent) { parent->Release(); /* self->GetParent() AddRef's */ @@ -1924,9 +1990,40 @@ PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DE Py_RETURN_NONE; } -PyObject* KX_GameObject::pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_group_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); + CListValue* instances = self->GetInstanceObjects(); + if (instances) { + return instances->GetProxy(); + } + Py_RETURN_NONE; +} + +PyObject* KX_GameObject::pyattr_get_scene(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject *self = static_cast(self_v); + SG_Node *node = self->GetSGNode(); + KX_Scene *scene = static_cast(node->GetSGClientInfo()); + if (scene) { + return scene->GetProxy(); + } + Py_RETURN_NONE; +} + +PyObject *KX_GameObject::pyattr_get_group_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self = static_cast(self_v); + KX_GameObject* pivot = self->GetDupliGroupObject(); + if (pivot) { + return pivot->GetProxy(); + } + Py_RETURN_NONE; +} + +PyObject *KX_GameObject::pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self = static_cast(self_v); CValue *life = self->GetProperty("::timebomb"); if (life) @@ -1937,16 +2034,16 @@ PyObject* KX_GameObject::pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF Py_RETURN_NONE; } -PyObject* KX_GameObject::pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); KX_IPhysicsController *spc = self->GetPhysicsController(); return PyFloat_FromDouble(spc ? spc->GetMass() : 0.0); } int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); KX_IPhysicsController *spc = self->GetPhysicsController(); MT_Scalar val = PyFloat_AsDouble(value); if (val < 0.0) { /* also accounts for non float */ @@ -1960,16 +2057,16 @@ int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrd return PY_SET_ATTR_SUCCESS; } -PyObject* KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); KX_IPhysicsController *spc = self->GetPhysicsController(); return PyFloat_FromDouble(spc ? spc->GetLinVelocityMin() : 0.0f); } int KX_GameObject::pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); KX_IPhysicsController *spc = self->GetPhysicsController(); MT_Scalar val = PyFloat_AsDouble(value); if (val < 0.0) { /* also accounts for non float */ @@ -1983,16 +2080,16 @@ int KX_GameObject::pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF return PY_SET_ATTR_SUCCESS; } -PyObject* KX_GameObject::pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); KX_IPhysicsController *spc = self->GetPhysicsController(); return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f); } int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); KX_IPhysicsController *spc = self->GetPhysicsController(); MT_Scalar val = PyFloat_AsDouble(value); if (val < 0.0) { /* also accounts for non float */ @@ -2007,15 +2104,15 @@ int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF } -PyObject* KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); return PyBool_FromLong(self->GetVisible()); } int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); int param = PyObject_IsTrue( value ); if (param == -1) { PyErr_SetString(PyExc_AttributeError, "gameOb.visible = bool: KX_GameObject, expected True or False"); @@ -2027,19 +2124,19 @@ int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *at return PY_SET_ATTR_SUCCESS; } -PyObject* KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL); #else - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); return PyObjectFrom(self->NodeGetWorldPosition()); #endif } int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); MT_Point3 pos; if (!PyVecTo(value, pos)) return PY_SET_ATTR_FAIL; @@ -2049,19 +2146,19 @@ int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_D return PY_SET_ATTR_SUCCESS; } -PyObject* KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { -#ifdef USE_MATHUTILS +#ifdef USE_MATHUTILS return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL); -#else - KX_GameObject* self= static_cast(self_v); +#else + KX_GameObject* self = static_cast(self_v); return PyObjectFrom(self->NodeGetLocalPosition()); #endif } int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); MT_Point3 pos; if (!PyVecTo(value, pos)) return PY_SET_ATTR_FAIL; @@ -2071,31 +2168,31 @@ int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_D return PY_SET_ATTR_SUCCESS; } -PyObject* KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL); #else - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); if (self->GetPhysicsController()) return PyObjectFrom(self->GetPhysicsController()->GetLocalInertia()); return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f); #endif } -PyObject* KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS return Matrix_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL); #else - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); return PyObjectFrom(self->NodeGetWorldOrientation()); #endif } int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); /* if value is not a sequence PyOrientationTo makes an error */ MT_Matrix3x3 rot; @@ -2108,19 +2205,19 @@ int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUT return PY_SET_ATTR_SUCCESS; } -PyObject* KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS return Matrix_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL); #else - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); return PyObjectFrom(self->NodeGetLocalOrientation()); #endif } int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); /* if value is not a sequence PyOrientationTo makes an error */ MT_Matrix3x3 rot; @@ -2132,19 +2229,19 @@ int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUT return PY_SET_ATTR_SUCCESS; } -PyObject* KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL); #else - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); return PyObjectFrom(self->NodeGetWorldScaling()); #endif } int KX_GameObject::pyattr_set_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); MT_Vector3 scale; if (!PyVecTo(value, scale)) return PY_SET_ATTR_FAIL; @@ -2154,19 +2251,19 @@ int KX_GameObject::pyattr_set_worldScaling(void *self_v, const KX_PYATTRIBUTE_DE return PY_SET_ATTR_SUCCESS; } -PyObject* KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL); #else - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); return PyObjectFrom(self->NodeGetLocalScaling()); #endif } int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); MT_Vector3 scale; if (!PyVecTo(value, scale)) return PY_SET_ATTR_FAIL; @@ -2176,7 +2273,7 @@ int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DE return PY_SET_ATTR_SUCCESS; } -PyObject* KX_GameObject::pyattr_get_localTransform(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_localTransform(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self = static_cast(self_v); @@ -2222,7 +2319,7 @@ int KX_GameObject::pyattr_set_localTransform(void *self_v, const KX_PYATTRIBUTE_ return PY_SET_ATTR_SUCCESS; } -PyObject* KX_GameObject::pyattr_get_worldTransform(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_worldTransform(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self = static_cast(self_v); @@ -2256,19 +2353,19 @@ int KX_GameObject::pyattr_set_worldTransform(void *self_v, const KX_PYATTRIBUTE_ return PY_SET_ATTR_SUCCESS; } -PyObject* KX_GameObject::pyattr_get_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_GLOBAL); #else - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); return PyObjectFrom(GetLinearVelocity(false)); #endif } int KX_GameObject::pyattr_set_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); MT_Vector3 velocity; if (!PyVecTo(value, velocity)) return PY_SET_ATTR_FAIL; @@ -2278,19 +2375,19 @@ int KX_GameObject::pyattr_set_worldLinearVelocity(void *self_v, const KX_PYATTRI return PY_SET_ATTR_SUCCESS; } -PyObject* KX_GameObject::pyattr_get_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_LOCAL); #else - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); return PyObjectFrom(GetLinearVelocity(true)); #endif } int KX_GameObject::pyattr_set_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); MT_Vector3 velocity; if (!PyVecTo(value, velocity)) return PY_SET_ATTR_FAIL; @@ -2300,19 +2397,19 @@ int KX_GameObject::pyattr_set_localLinearVelocity(void *self_v, const KX_PYATTRI return PY_SET_ATTR_SUCCESS; } -PyObject* KX_GameObject::pyattr_get_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_GLOBAL); #else - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); return PyObjectFrom(GetAngularVelocity(false)); #endif } int KX_GameObject::pyattr_set_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); MT_Vector3 velocity; if (!PyVecTo(value, velocity)) return PY_SET_ATTR_FAIL; @@ -2322,19 +2419,19 @@ int KX_GameObject::pyattr_set_worldAngularVelocity(void *self_v, const KX_PYATTR return PY_SET_ATTR_SUCCESS; } -PyObject* KX_GameObject::pyattr_get_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_LOCAL); #else - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); return PyObjectFrom(GetAngularVelocity(true)); #endif } int KX_GameObject::pyattr_set_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); MT_Vector3 velocity; if (!PyVecTo(value, velocity)) return PY_SET_ATTR_FAIL; @@ -2345,9 +2442,9 @@ int KX_GameObject::pyattr_set_localAngularVelocity(void *self_v, const KX_PYATTR } -PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); SG_Node* sg_parent; if (self->GetSGNode() && (sg_parent = self->GetSGNode()->GetSGParent()) != NULL && sg_parent->IsSlowParent()) { return PyFloat_FromDouble(static_cast(sg_parent->GetParentRelation())->GetTimeOffset()); @@ -2358,7 +2455,7 @@ PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUT int KX_GameObject::pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); if (self->GetSGNode()) { MT_Scalar val = PyFloat_AsDouble(value); SG_Node *sg_parent= self->GetSGNode()->GetSGParent(); @@ -2372,9 +2469,9 @@ int KX_GameObject::pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF return PY_SET_ATTR_SUCCESS; } -PyObject* KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); int state = 0; state |= self->GetState(); return PyLong_FromSsize_t(state); @@ -2382,7 +2479,7 @@ PyObject* KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); int state_i = PyLong_AsSsize_t(value); unsigned int state = 0; @@ -2400,9 +2497,9 @@ int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attr return PY_SET_ATTR_SUCCESS; } -PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); PyObject *meshes= PyList_New(self->m_meshes.size()); int i; @@ -2415,19 +2512,19 @@ PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DE return meshes; } -PyObject* KX_GameObject::pyattr_get_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 4, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_OBJECT_COLOR); #else - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); return PyObjectFrom(self->GetObjectColor()); #endif } int KX_GameObject::pyattr_set_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); MT_Vector4 obcolor; if (!PyVecTo(value, obcolor)) return PY_SET_ATTR_FAIL; @@ -2437,37 +2534,37 @@ int KX_GameObject::pyattr_set_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *at } /* These are experimental! */ -PyObject* KX_GameObject::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { return KX_PythonSeq_CreatePyObject((static_cast(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_SENSORS); } -PyObject* KX_GameObject::pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { return KX_PythonSeq_CreatePyObject((static_cast(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_CONTROLLERS); } -PyObject* KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { return KX_PythonSeq_CreatePyObject((static_cast(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_ACTUATORS); } /* End experimental */ -PyObject* KX_GameObject::pyattr_get_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); return self->GetChildren()->NewProxy(true); } -PyObject* KX_GameObject::pyattr_get_children_recursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_children_recursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); return self->GetChildrenRecursive()->NewProxy(true); } -PyObject* KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_GameObject* self= static_cast(self_v); + KX_GameObject* self = static_cast(self_v); if (self->m_attr_dict==NULL) self->m_attr_dict= PyDict_New(); @@ -2476,10 +2573,10 @@ PyObject* KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_ return self->m_attr_dict; } -PyObject* KX_GameObject::PyApplyForce(PyObject* args) +PyObject *KX_GameObject::PyApplyForce(PyObject *args) { int local = 0; - PyObject* pyvect; + PyObject *pyvect; if (PyArg_ParseTuple(args, "O|i:applyForce", &pyvect, &local)) { MT_Vector3 force; @@ -2491,10 +2588,10 @@ PyObject* KX_GameObject::PyApplyForce(PyObject* args) return NULL; } -PyObject* KX_GameObject::PyApplyTorque(PyObject* args) +PyObject *KX_GameObject::PyApplyTorque(PyObject *args) { int local = 0; - PyObject* pyvect; + PyObject *pyvect; if (PyArg_ParseTuple(args, "O|i:applyTorque", &pyvect, &local)) { MT_Vector3 torque; @@ -2506,10 +2603,10 @@ PyObject* KX_GameObject::PyApplyTorque(PyObject* args) return NULL; } -PyObject* KX_GameObject::PyApplyRotation(PyObject* args) +PyObject *KX_GameObject::PyApplyRotation(PyObject *args) { int local = 0; - PyObject* pyvect; + PyObject *pyvect; if (PyArg_ParseTuple(args, "O|i:applyRotation", &pyvect, &local)) { MT_Vector3 rotation; @@ -2521,10 +2618,10 @@ PyObject* KX_GameObject::PyApplyRotation(PyObject* args) return NULL; } -PyObject* KX_GameObject::PyApplyMovement(PyObject* args) +PyObject *KX_GameObject::PyApplyMovement(PyObject *args) { int local = 0; - PyObject* pyvect; + PyObject *pyvect; if (PyArg_ParseTuple(args, "O|i:applyMovement", &pyvect, &local)) { MT_Vector3 movement; @@ -2536,7 +2633,7 @@ PyObject* KX_GameObject::PyApplyMovement(PyObject* args) return NULL; } -PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* args) +PyObject *KX_GameObject::PyGetLinearVelocity(PyObject *args) { // only can get the velocity if we have a physics object connected to us... int local = 0; @@ -2550,10 +2647,10 @@ PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* args) } } -PyObject* KX_GameObject::PySetLinearVelocity(PyObject* args) +PyObject *KX_GameObject::PySetLinearVelocity(PyObject *args) { int local = 0; - PyObject* pyvect; + PyObject *pyvect; if (PyArg_ParseTuple(args,"O|i:setLinearVelocity",&pyvect,&local)) { MT_Vector3 velocity; @@ -2565,7 +2662,7 @@ PyObject* KX_GameObject::PySetLinearVelocity(PyObject* args) return NULL; } -PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* args) +PyObject *KX_GameObject::PyGetAngularVelocity(PyObject *args) { // only can get the velocity if we have a physics object connected to us... int local = 0; @@ -2579,10 +2676,10 @@ PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* args) } } -PyObject* KX_GameObject::PySetAngularVelocity(PyObject* args) +PyObject *KX_GameObject::PySetAngularVelocity(PyObject *args) { int local = 0; - PyObject* pyvect; + PyObject *pyvect; if (PyArg_ParseTuple(args,"O|i:setAngularVelocity",&pyvect,&local)) { MT_Vector3 velocity; @@ -2594,7 +2691,7 @@ PyObject* KX_GameObject::PySetAngularVelocity(PyObject* args) return NULL; } -PyObject* KX_GameObject::PySetVisible(PyObject* args) +PyObject *KX_GameObject::PySetVisible(PyObject *args) { int visible, recursive = 0; if (!PyArg_ParseTuple(args,"i|i:setVisible",&visible, &recursive)) @@ -2606,7 +2703,7 @@ PyObject* KX_GameObject::PySetVisible(PyObject* args) } -PyObject* KX_GameObject::PySetOcclusion(PyObject* args) +PyObject *KX_GameObject::PySetOcclusion(PyObject *args) { int occlusion, recursive = 0; if (!PyArg_ParseTuple(args,"i|i:setOcclusion",&occlusion, &recursive)) @@ -2616,11 +2713,11 @@ PyObject* KX_GameObject::PySetOcclusion(PyObject* args) Py_RETURN_NONE; } -PyObject* KX_GameObject::PyGetVelocity(PyObject* args) +PyObject *KX_GameObject::PyGetVelocity(PyObject *args) { // only can get the velocity if we have a physics object connected to us... MT_Point3 point(0.0,0.0,0.0); - PyObject* pypos = NULL; + PyObject *pypos = NULL; if (!PyArg_ParseTuple(args, "|O:getVelocity", &pypos) || (pypos && !PyVecTo(pypos, point))) return NULL; @@ -2634,7 +2731,7 @@ PyObject* KX_GameObject::PyGetVelocity(PyObject* args) } } -PyObject* KX_GameObject::PyGetReactionForce() +PyObject *KX_GameObject::PyGetReactionForce() { // only can get the velocity if we have a physics object connected to us... @@ -2651,7 +2748,7 @@ PyObject* KX_GameObject::PyGetReactionForce() -PyObject* KX_GameObject::PyEnableRigidBody() +PyObject *KX_GameObject::PyEnableRigidBody() { if (GetPhysicsController()) GetPhysicsController()->setRigidBody(true); @@ -2661,7 +2758,7 @@ PyObject* KX_GameObject::PyEnableRigidBody() -PyObject* KX_GameObject::PyDisableRigidBody() +PyObject *KX_GameObject::PyDisableRigidBody() { if (GetPhysicsController()) GetPhysicsController()->setRigidBody(false); @@ -2670,10 +2767,10 @@ PyObject* KX_GameObject::PyDisableRigidBody() } -PyObject* KX_GameObject::PySetParent(PyObject* args) +PyObject *KX_GameObject::PySetParent(PyObject *args) { KX_Scene *scene = KX_GetActiveScene(); - PyObject* pyobj; + PyObject *pyobj; KX_GameObject *obj; int addToCompound=1, ghost=1; @@ -2687,7 +2784,7 @@ PyObject* KX_GameObject::PySetParent(PyObject* args) Py_RETURN_NONE; } -PyObject* KX_GameObject::PyRemoveParent() +PyObject *KX_GameObject::PyRemoveParent() { KX_Scene *scene = KX_GetActiveScene(); @@ -2696,7 +2793,7 @@ PyObject* KX_GameObject::PyRemoveParent() } -PyObject* KX_GameObject::PySetCollisionMargin(PyObject* value) +PyObject *KX_GameObject::PySetCollisionMargin(PyObject *value) { float collisionMargin = PyFloat_AsDouble(value); @@ -2716,10 +2813,10 @@ PyObject* KX_GameObject::PySetCollisionMargin(PyObject* value) -PyObject* KX_GameObject::PyApplyImpulse(PyObject* args) +PyObject *KX_GameObject::PyApplyImpulse(PyObject *args) { - PyObject* pyattach; - PyObject* pyimpulse; + PyObject *pyattach; + PyObject *pyimpulse; if (!m_pPhysicsController1) { PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller"); @@ -2743,7 +2840,7 @@ PyObject* KX_GameObject::PyApplyImpulse(PyObject* args) -PyObject* KX_GameObject::PySuspendDynamics() +PyObject *KX_GameObject::PySuspendDynamics() { SuspendDynamics(); Py_RETURN_NONE; @@ -2751,16 +2848,16 @@ PyObject* KX_GameObject::PySuspendDynamics() -PyObject* KX_GameObject::PyRestoreDynamics() +PyObject *KX_GameObject::PyRestoreDynamics() { RestoreDynamics(); Py_RETURN_NONE; } -PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* args) +PyObject *KX_GameObject::PyAlignAxisToVect(PyObject *args) { - PyObject* pyvect; + PyObject *pyvect; int axis = 2; //z axis is the default float fac = 1.0f; @@ -2780,7 +2877,7 @@ PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* args) return NULL; } -PyObject* KX_GameObject::PyGetAxisVect(PyObject* value) +PyObject *KX_GameObject::PyGetAxisVect(PyObject *value) { MT_Vector3 vect; if (PyVecTo(value, vect)) @@ -2791,7 +2888,7 @@ PyObject* KX_GameObject::PyGetAxisVect(PyObject* value) } -PyObject* KX_GameObject::PyGetPhysicsId() +PyObject *KX_GameObject::PyGetPhysicsId() { KX_IPhysicsController* ctrl = GetPhysicsController(); uint_ptr physid=0; @@ -2802,7 +2899,7 @@ PyObject* KX_GameObject::PyGetPhysicsId() return PyLong_FromSsize_t((long)physid); } -PyObject* KX_GameObject::PyGetPropertyNames() +PyObject *KX_GameObject::PyGetPropertyNames() { PyObject *list= ConvertKeysToPython(); @@ -2932,7 +3029,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, " other = 3-tuple or object reference") { MT_Point3 toPoint; - PyObject* pyarg; + PyObject *pyarg; float dist = 0.0f; char *propName = NULL; @@ -3050,8 +3147,8 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, { MT_Point3 toPoint; MT_Point3 fromPoint; - PyObject* pyto; - PyObject* pyfrom = NULL; + PyObject *pyto; + PyObject *pyfrom = NULL; float dist = 0.0f; char *propName = NULL; KX_GameObject *other; @@ -3125,7 +3222,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, if (m_pHitObject) { - PyObject* returnValue = (poly==2) ? PyTuple_New(5) : (poly) ? PyTuple_New(4) : PyTuple_New(3); + PyObject *returnValue = (poly == 2) ? PyTuple_New(5) : (poly) ? PyTuple_New(4) : PyTuple_New(3); if (returnValue) { // unlikely this would ever fail, if it does python sets an error PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->GetProxy()); PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(callback.m_hitPoint)); @@ -3301,11 +3398,11 @@ KX_PYMETHODDEF_DOC(KX_GameObject, isPlayingAction, /* Matches python dict.get(key, [default]) */ -PyObject* KX_GameObject::Pyget(PyObject *args) +PyObject *KX_GameObject::Pyget(PyObject *args) { PyObject *key; - PyObject* def = Py_None; - PyObject* ret; + PyObject *def = Py_None; + PyObject *ret; if (!PyArg_ParseTuple(args, "O|O:get", &key, &def)) return NULL; @@ -3331,7 +3428,7 @@ PyObject* KX_GameObject::Pyget(PyObject *args) return def; } -bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix) +bool ConvertPythonToGameObject(PyObject *value, KX_GameObject **object, bool py_none_ok, const char *error_prefix) { if (value==NULL) { PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix); diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 2b0d13ff2f7..d5ae13eb702 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -33,9 +33,9 @@ #ifndef __KX_GAMEOBJECT_H__ #define __KX_GAMEOBJECT_H__ -#if defined(WIN32) && !defined(FREE_WINDOWS) -// get rid of this stupid "warning 'this' used in initialiser list", generated by VC when including Solid/Sumo -#pragma warning (disable : 4355) +#ifdef _MSC_VER + /* get rid of this stupid "warning 'this' used in initialiser list", generated by VC when including Solid/Sumo */ +# pragma warning (disable:4355) #endif #include @@ -68,7 +68,7 @@ struct bAction; #ifdef WITH_PYTHON /* utility conversion function */ -bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix); +bool ConvertPythonToGameObject(PyObject *value, KX_GameObject **object, bool py_none_ok, const char *error_prefix); #endif #ifdef USE_MATHUTILS @@ -98,6 +98,10 @@ protected: bool m_bIsNegativeScaling; MT_Vector4 m_objectColor; + // Bit fields for user control over physics collisions + short m_userCollisionGroup; + short m_userCollisionMask; + // visible = user setting // culled = while rendering, depending on camera bool m_bVisible; @@ -116,9 +120,11 @@ protected: KX_ObstacleSimulation* m_pObstacleSimulation; + CListValue* m_pInstanceObjects; + KX_GameObject* m_pDupliGroupObject; // The action manager is used to play/stop/update actions - BL_ActionManager* m_actionManager; + BL_ActionManager* m_actionManager; BL_ActionManager* GetActionManager(); @@ -159,7 +165,7 @@ public: * side effect of storing the result internally. The * memory for the matrix remains the property of this class. */ - double* + double * GetOpenGLMatrix( ); @@ -170,7 +176,7 @@ public: * memory for the returned matrix. */ - MT_CmMatrix4x4* + MT_CmMatrix4x4 * GetOpenGLMatrixPtr( ) { return &m_OpenGL_4x4Matrix; @@ -193,20 +199,47 @@ public: * object. It is the responsibility of the caller to decrement * the reference count when you have finished with it. */ - KX_GameObject* + KX_GameObject* GetParent( ); /** * Sets the parent of this object to a game object - */ + */ void SetParent(KX_Scene *scene, KX_GameObject *obj, bool addToCompound=true, bool ghost=true); /** * Removes the parent of this object to a game object - */ + */ void RemoveParent(KX_Scene *scene); + /********************************* + * group reference API + *********************************/ + + KX_GameObject* + GetDupliGroupObject( + ); + + CListValue* + GetInstanceObjects( + ); + + void + SetDupliGroupObject(KX_GameObject* + ); + + void + AddInstanceObjects(KX_GameObject* + ); + + void + RemoveDupliGroupObject( + ); + + void + RemoveInstanceObject(KX_GameObject* + ); /********************************* * Animation API *********************************/ @@ -292,7 +325,7 @@ public: /** * Inherited from CValue -- does nothing! */ - CValue* + CValue* Calc( VALUE_OPERATOR op, CValue *val @@ -301,7 +334,7 @@ public: /** * Inherited from CValue -- does nothing! */ - CValue* + CValue* CalcFinal( VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, @@ -312,7 +345,7 @@ public: * Inherited from CValue -- does nothing! */ const - STR_String & + STR_String & GetText( ); @@ -331,14 +364,14 @@ public: /** * Inherited from CValue -- returns the name of this object. */ - STR_String& + STR_String& GetName( ); /** * Inherited from CValue -- set the name of this object. */ - void + void SetName( const char *name ); @@ -348,7 +381,7 @@ public: * instance allocated on the heap. Ownership of the new * object belongs with the caller. */ - virtual CValue* + virtual CValue* GetReplica( ); @@ -356,7 +389,7 @@ public: * Inherited from CValue -- Makes sure any internal * data owned by this class is deep copied. Called internally */ - virtual void + virtual void ProcessReplica(); /** @@ -379,7 +412,7 @@ public: /** * Return the mass of the object */ - MT_Scalar + MT_Scalar GetMass(); /** @@ -410,7 +443,7 @@ public: * Quick'n'dirty obcolor ipo stuff */ - void + void SetObjectColor( const MT_Vector4& rgbavec ); @@ -465,6 +498,13 @@ public: */ void ActivateGraphicController(bool recurse); + void SetUserCollisionGroup(short filter); + void SetUserCollisionMask(short mask); + /** + * Extra broadphase check for user controllable collisions + */ + bool CheckCollision(KX_GameObject *other); + /** * \section Coordinate system manipulation functions */ @@ -482,7 +522,7 @@ public: // adapt local position so that world position is set to desired position void NodeSetWorldPosition(const MT_Point3& trans); - void + void NodeUpdateGS( double time ); @@ -504,7 +544,7 @@ public: return m_pSGNode; } - const SG_Node* GetSGNode( ) const + const SG_Node* GetSGNode( ) const { return m_pSGNode; } @@ -581,48 +621,48 @@ public: * place. */ - void + void ApplyForce( const MT_Vector3& force, bool local ); - void + void ApplyTorque( const MT_Vector3& torque, bool local ); - void + void ApplyRotation( const MT_Vector3& drot, bool local ); - void + void ApplyMovement( const MT_Vector3& dloc, bool local ); - void + void addLinearVelocity( const MT_Vector3& lin_vel, bool local ); - void + void setLinearVelocity( const MT_Vector3& lin_vel, bool local ); - void + void setAngularVelocity( const MT_Vector3& ang_vel, bool local ); - /** + /** * Update the physics object transform based upon the current SG_Node * position. */ @@ -642,7 +682,7 @@ public: /** * Function to set IPO option at start of IPO */ - void + void InitIPO( bool ipo_as_force, bool ipo_add, @@ -652,7 +692,7 @@ public: /** * Odd function to update an ipo. ??? */ - void + void UpdateIPO( float curframetime, bool recurse @@ -676,20 +716,20 @@ public: * \section Mesh accessor functions. */ - /** + /** * Update buckets to indicate that there is a new * user of this object's meshes. */ - void + void AddMeshUser( ); - /** + /** * Update buckets with data about the mesh after * creating or duplicating the object, changing * visibility, object color, .. . */ - void + void UpdateBuckets( bool recursive ); @@ -699,7 +739,7 @@ public: * and remove from the bucketing system. * Don't think this actually deletes any of the meshes. */ - void + void RemoveMeshes( ); @@ -709,7 +749,7 @@ public: * Make sure you call RemoveMeshes() before deleting the * mesh though, */ - void + void AddMesh( RAS_MeshObject* mesh ) { @@ -719,7 +759,7 @@ public: /** * Pick out a mesh associated with the integer 'num'. */ - RAS_MeshObject* + RAS_MeshObject* GetMesh( int num ) const { @@ -730,17 +770,17 @@ public: * Return the number of meshes currently associated with this * game object. */ - int + int GetMeshCount( ) const { return m_meshes.size(); } - /** + /** * Set the debug color of the meshes associated with this * class. Does this still work? */ - void + void SetDebugColor( unsigned int bgra ); @@ -748,7 +788,7 @@ public: /** * Reset the debug color of meshes associated with this class. */ - void + void ResetDebugColor( ); @@ -855,7 +895,7 @@ public: m_bSuspendDynamics = true; } - void RestoreDynamics(void) { + void RestoreDynamics(void) { if (!m_bSuspendDynamics) { return; @@ -887,7 +927,7 @@ public: /** * \section Python interface functions. */ - virtual PyObject* py_repr(void) + virtual PyObject *py_repr(void) { return PyUnicode_From_STR_String(GetName()); } @@ -949,6 +989,10 @@ public: static PyObject* pyattr_get_name(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_group_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_group_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_scene(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); @@ -983,7 +1027,7 @@ public: static PyObject* pyattr_get_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static int pyattr_set_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static int pyattr_set_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); @@ -1008,5 +1052,4 @@ public: -#endif //__KX_GAMEOBJECT_H__ - +#endif /* __KX_GAMEOBJECT_H__ */ diff --git a/source/gameengine/Ketsji/KX_IInterpolator.h b/source/gameengine/Ketsji/KX_IInterpolator.h index 6ca44e1f6e5..6c0bf2d85cc 100644 --- a/source/gameengine/Ketsji/KX_IInterpolator.h +++ b/source/gameengine/Ketsji/KX_IInterpolator.h @@ -38,7 +38,7 @@ #include "MEM_guardedalloc.h" #endif -class KX_IInterpolator { +class KX_IInterpolator { public: virtual ~KX_IInterpolator() {} diff --git a/source/gameengine/Ketsji/KX_IPOTransform.h b/source/gameengine/Ketsji/KX_IPOTransform.h index 43019f3e54a..a68292bf9df 100644 --- a/source/gameengine/Ketsji/KX_IPOTransform.h +++ b/source/gameengine/Ketsji/KX_IPOTransform.h @@ -48,8 +48,8 @@ public: MT_Transform GetTransform() const { return MT_Transform(m_position + m_deltaPosition, - MT_Matrix3x3(m_eulerAngles + m_deltaEulerAngles, - m_scaling + m_deltaScaling)); + MT_Matrix3x3(m_eulerAngles + m_deltaEulerAngles, + m_scaling + m_deltaScaling)); } MT_Point3& GetPosition() { return m_position; } diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.cpp b/source/gameengine/Ketsji/KX_IPO_SGController.cpp index 950e3c88a9e..c5e11195547 100644 --- a/source/gameengine/Ketsji/KX_IPO_SGController.cpp +++ b/source/gameengine/Ketsji/KX_IPO_SGController.cpp @@ -37,10 +37,10 @@ typedef unsigned __int64 uint_ptr; typedef unsigned long uint_ptr; #endif -#if defined(WIN32) && !defined(FREE_WINDOWS) -// This warning tells us about truncation of __long__ stl-generated names. -// It can occasionally cause DevStudio to have internal compiler warnings. -#pragma warning( disable : 4786 ) +#ifdef _MSC_VER + /* This warning tells us about truncation of __long__ stl-generated names. + * It can occasionally cause DevStudio to have internal compiler warnings. */ +# pragma warning(disable:4786) #endif #include "KX_IPO_SGController.h" @@ -52,7 +52,7 @@ typedef unsigned long uint_ptr; // All objects should start on frame 1! Will we ever need an object to // start on another frame, the 1.0 should change. -KX_IpoSGController::KX_IpoSGController() +KX_IpoSGController::KX_IpoSGController() : m_ipo_as_force(false), m_ipo_add(false), m_ipo_local(false), diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.h b/source/gameengine/Ketsji/KX_IPO_SGController.h index 266b89ff969..cecfa9804db 100644 --- a/source/gameengine/Ketsji/KX_IPO_SGController.h +++ b/source/gameengine/Ketsji/KX_IPO_SGController.h @@ -126,6 +126,4 @@ public: #endif }; -#endif //__KX_IPO_SGCONTROLLER_H__ - - +#endif /* __KX_IPO_SGCONTROLLER_H__ */ diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.h b/source/gameengine/Ketsji/KX_IPhysicsController.h index dd34549c1fb..280b1816a1e 100644 --- a/source/gameengine/Ketsji/KX_IPhysicsController.h +++ b/source/gameengine/Ketsji/KX_IPhysicsController.h @@ -145,5 +145,4 @@ public: #endif }; -#endif //__KX_IPHYSICSCONTROLLER_H__ - +#endif /* __KX_IPHYSICSCONTROLLER_H__ */ diff --git a/source/gameengine/Ketsji/KX_IScalarInterpolator.h b/source/gameengine/Ketsji/KX_IScalarInterpolator.h index 2b5aefccfe7..1e822c49c6d 100644 --- a/source/gameengine/Ketsji/KX_IScalarInterpolator.h +++ b/source/gameengine/Ketsji/KX_IScalarInterpolator.h @@ -36,7 +36,7 @@ #include "MEM_guardedalloc.h" #endif -class KX_IScalarInterpolator { +class KX_IScalarInterpolator { public: virtual ~KX_IScalarInterpolator() {} diff --git a/source/gameengine/Ketsji/KX_ISceneConverter.h b/source/gameengine/Ketsji/KX_ISceneConverter.h index 919ae1d6de5..18fb336dbe0 100644 --- a/source/gameengine/Ketsji/KX_ISceneConverter.h +++ b/source/gameengine/Ketsji/KX_ISceneConverter.h @@ -93,5 +93,4 @@ public: #endif }; -#endif //__KX_ISCENECONVERTER_H__ - +#endif /* __KX_ISCENECONVERTER_H__ */ diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp index 5599f3e31c6..1597d7f8809 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.cpp +++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp @@ -182,7 +182,7 @@ bool KX_IpoActuator::Update(double curtime, bool frame) m_bIpoPlaying = true; bIpoStart = true; } - } + } switch ((IpoActType)m_type) { @@ -254,7 +254,7 @@ bool KX_IpoActuator::Update(double curtime, bool frame) result = false; if (bIpoStart) - ((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local); + ((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local); ((KX_GameObject*)GetParent())->UpdateIPO(m_localtime,m_recurse); break; } @@ -309,7 +309,7 @@ bool KX_IpoActuator::Update(double curtime, bool frame) bIpoStart = true; } else - { + { /* Perform clamping */ m_localtime=m_endframe; result = false; @@ -453,15 +453,15 @@ PyAttributeDef KX_IpoActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_IpoActuator::pyattr_get_frame_start(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_IpoActuator::pyattr_get_frame_start(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_IpoActuator* self= static_cast(self_v); + KX_IpoActuator* self = static_cast(self_v); return PyFloat_FromDouble(self->m_startframe); } int KX_IpoActuator::pyattr_set_frame_start(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_IpoActuator* self= static_cast(self_v); + KX_IpoActuator* self = static_cast(self_v); float param = PyFloat_AsDouble(value); if (PyErr_Occurred()) { @@ -474,15 +474,15 @@ int KX_IpoActuator::pyattr_set_frame_start(void *self_v, const KX_PYATTRIBUTE_DE return PY_SET_ATTR_SUCCESS; } -PyObject* KX_IpoActuator::pyattr_get_frame_end(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_IpoActuator::pyattr_get_frame_end(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_IpoActuator* self= static_cast(self_v); + KX_IpoActuator* self = static_cast(self_v); return PyFloat_FromDouble(self->m_endframe); } int KX_IpoActuator::pyattr_set_frame_end(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_IpoActuator* self= static_cast(self_v); + KX_IpoActuator* self = static_cast(self_v); float param = PyFloat_AsDouble(value); if (PyErr_Occurred()) { diff --git a/source/gameengine/Ketsji/KX_IpoActuator.h b/source/gameengine/Ketsji/KX_IpoActuator.h index 58cdfc28742..1c2f4e49b72 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.h +++ b/source/gameengine/Ketsji/KX_IpoActuator.h @@ -150,5 +150,4 @@ public: }; -#endif //__KX_IPOACTUATOR_H__ - +#endif /* __KX_IPOACTUATOR_H__ */ diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index a560b606f5b..0ab7b9ec9e5 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -30,10 +30,9 @@ * \ingroup ketsji */ - -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable : 4786) -#endif //WIN32 +#ifdef _MSC_VER +# pragma warning (disable:4786) +#endif #include #include @@ -46,7 +45,6 @@ #include "BoolValue.h" #include "FloatValue.h" -#define KX_NUM_ITERATIONS 4 #include "RAS_BucketManager.h" #include "RAS_Rect.h" #include "RAS_IRasterizer.h" @@ -253,7 +251,7 @@ void KX_KetsjiEngine::SetRasterizer(RAS_IRasterizer* rasterizer) * At the moment the bge.logic module is imported into 'pythondictionary' after this function is called. * if this function ever changes to assign a copy, make sure the game logic module is imported into this dictionary before hand. */ -void KX_KetsjiEngine::SetPyNamespace(PyObject* pythondictionary) +void KX_KetsjiEngine::SetPyNamespace(PyObject *pythondictionary) { MT_assert(pythondictionary); m_pythondictionary = pythondictionary; @@ -275,8 +273,7 @@ void KX_KetsjiEngine::InitDome(short res, short mode, short angle, float resbuf, void KX_KetsjiEngine::RenderDome() { - GLuint viewport[4]={0}; - glGetIntegerv(GL_VIEWPORT,(GLint *)viewport); + const GLint *viewport = m_canvas->GetViewPort(); m_dome->SetViewPort(viewport); @@ -337,8 +334,7 @@ void KX_KetsjiEngine::RenderDome() // Draw the scene once for each camera with an enabled viewport list::iterator it = cameras->begin(); - while(it != cameras->end()) - { + while (it != cameras->end()) { if ((*it)->GetViewport()) { if (scene->IsClearingZBuffer()) @@ -361,7 +357,7 @@ void KX_KetsjiEngine::RenderDome() // no FlushDebugLines } m_dome->BindImages(i); - } + } m_canvas->EndFrame();//XXX do we really need that? @@ -391,7 +387,7 @@ void KX_KetsjiEngine::RenderDome() // Draw Callback for the last scene #ifdef WITH_PYTHON scene->RunDrawingCallbacks(scene->GetPostDrawCB()); -#endif +#endif EndFrame(); } @@ -477,7 +473,7 @@ void KX_KetsjiEngine::ClearFrame() SetBackGround(firstscene->GetWorldInfo()); m_canvas->SetViewPort(clearvp.GetLeft(), clearvp.GetBottom(), - clearvp.GetRight(), clearvp.GetTop()); + clearvp.GetRight(), clearvp.GetTop()); m_rasterizer->ClearColorBuffer(); } } @@ -498,7 +494,7 @@ bool KX_KetsjiEngine::BeginFrame() } return false; -} +} void KX_KetsjiEngine::EndFrame() @@ -641,7 +637,7 @@ else scene->GetPhysicsEnvironment()->endFrame(); // Update scenegraph after physics step. This maps physics calculations - // into node positions. + // into node positions. //m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); //SG_SetActiveStage(SG_STAGE_PHYSICS1_UPDATE); //scene->UpdateParents(m_frameTime); @@ -692,7 +688,7 @@ else if (m_animation_record) - { + { m_sceneconverter->WritePhysicsObjectToAnimationIpo(++m_currentFrame); } @@ -725,7 +721,7 @@ else bool bUseAsyncLogicBricks= false;//true; if (bUseAsyncLogicBricks) - { + { // Logic update sub frame: this will let some logic bricks run at the // full frame rate. for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit) @@ -756,7 +752,7 @@ else m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); scene->GetPhysicsEnvironment()->proceedDeltaTime(m_clockTime,timestep,timestep); // Update scenegraph after physics step. This maps physics calculations - // into node positions. + // into node positions. m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_PHYSICS2); scene->UpdateParents(m_clockTime); @@ -892,8 +888,7 @@ void KX_KetsjiEngine::Render() // Draw the scene once for each camera with an enabled viewport list::iterator it = cameras->begin(); - while(it != cameras->end()) - { + while (it != cameras->end()) { if ((*it)->GetViewport()) { if (scene->IsClearingZBuffer()) @@ -938,12 +933,11 @@ void KX_KetsjiEngine::Render() //RenderFrame(scene); RenderFrame(scene, cam); - list* cameras = scene->GetCameras(); + list* cameras = scene->GetCameras(); // Draw the scene once for each camera with an enabled viewport list::iterator it = cameras->begin(); - while(it != cameras->end()) - { + while (it != cameras->end()) { if ((*it)->GetViewport()) { if (scene->IsClearingZBuffer()) @@ -1013,7 +1007,7 @@ void KX_KetsjiEngine::SetBackGround(KX_WorldInfo* wi) if (wi->hasWorld()) { if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED) - { + { m_rasterizer->SetBackColor( wi->getBackColorRed(), wi->getBackColorGreen(), @@ -1038,7 +1032,7 @@ void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi) ); if (m_drawingmode >= RAS_IRasterizer::KX_SOLID) - { + { if (wi->hasMist()) { m_rasterizer->SetFog( @@ -1203,11 +1197,11 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) GetSceneViewport(scene, cam, area, viewport); // store the computed viewport in the scene - scene->SetSceneViewport(viewport); + scene->SetSceneViewport(viewport); // set the viewport for this frame and scene m_canvas->SetViewPort(viewport.GetLeft(), viewport.GetBottom(), - viewport.GetRight(), viewport.GetTop()); + viewport.GetRight(), viewport.GetTop()); // see KX_BlenderMaterial::Activate //m_rasterizer->SetAmbient(); @@ -1330,8 +1324,7 @@ void KX_KetsjiEngine::RenderFonts(KX_Scene* scene) list* fonts = scene->GetFonts(); list::iterator it = fonts->begin(); - while(it != fonts->end()) - { + while (it != fonts->end()) { (*it)->DrawText(); ++it; } @@ -1348,7 +1341,7 @@ void KX_KetsjiEngine::PostRenderScene(KX_Scene* scene) m_rasterizer->FlushDebugShapes(); scene->Render2DFilters(m_canvas); #ifdef WITH_PYTHON - scene->RunDrawingCallbacks(scene->GetPostDrawCB()); + scene->RunDrawingCallbacks(scene->GetPostDrawCB()); #endif } @@ -1368,10 +1361,10 @@ void KX_KetsjiEngine::StopEngine() { KX_Scene* scene = *sceneit; m_sceneconverter->RemoveScene(scene); - } + } m_scenes.clear(); - // cleanup all the stuff + // cleanup all the stuff m_rasterizer->Exit(); } } @@ -1443,8 +1436,17 @@ void KX_KetsjiEngine::PostProcessScene(KX_Scene* scene) void KX_KetsjiEngine::RenderDebugProperties() { STR_String debugtxt; - int xcoord = 10; // mmmm, these constants were taken from blender source - int ycoord = 14; // to 'mimic' behavior + int title_xmargin = -7; + int title_y_top_margin = 4; + int title_y_bottom_margin = 2; + + int const_xindent = 4; + int const_ysize = 14; + + int xcoord = 12; // mmmm, these constants were taken from blender source + int ycoord = 17; // to 'mimic' behavior + + int profile_indent = 64; float tottime = m_logger->GetAverage(); if (tottime < 1e-6f) { @@ -1455,43 +1457,88 @@ void KX_KetsjiEngine::RenderDebugProperties() RAS_Rect viewport; m_canvas->SetViewPort(0, 0, int(m_canvas->GetWidth()), int(m_canvas->GetHeight())); - /* Framerate display */ - if (m_show_framerate) { - debugtxt.Format("swap : %.3f (%.3f frames per second)", tottime, 1.0/tottime); - m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, + if (m_show_framerate || m_show_profile) { + /* Title for profiling("Profile") */ + debugtxt.Format("Profile"); + m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, debugtxt.Ptr(), - xcoord, - ycoord, - m_canvas->GetWidth() /* RdV, TODO ?? */, + xcoord + const_xindent + title_xmargin, // Adds the constant x indent (0 for now) to the title x margin + ycoord, + m_canvas->GetWidth() /* RdV, TODO ?? */, m_canvas->GetHeight() /* RdV, TODO ?? */); - ycoord += 14; + + // Increase the indent by default increase + ycoord += const_ysize; + // Add the title indent afterwards + ycoord += title_y_bottom_margin; } - /* Profile and framerate display */ + /* Framerate display */ + if (m_show_framerate) { + debugtxt.Format("Frametime :"); + m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, + debugtxt.Ptr(), + xcoord + const_xindent, + ycoord, + m_canvas->GetWidth() /* RdV, TODO ?? */, + m_canvas->GetHeight() /* RdV, TODO ?? */); + + debugtxt.Format("%5.1fms (%5.1f fps)", tottime * 1000.f, 1.0/tottime); + m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, + debugtxt.Ptr(), + xcoord + const_xindent + profile_indent, + ycoord, + m_canvas->GetWidth() /* RdV, TODO ?? */, + m_canvas->GetHeight() /* RdV, TODO ?? */); + // Increase the indent by default increase + ycoord += const_ysize; + } + + /* Profile display */ if (m_show_profile) - { + { for (int j = tc_first; j < tc_numCategories; j++) { debugtxt.Format(m_profileLabels[j]); m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, debugtxt.Ptr(), - xcoord,ycoord, + xcoord + const_xindent, + ycoord, m_canvas->GetWidth(), m_canvas->GetHeight()); + double time = m_logger->GetAverage((KX_TimeCategory)j); - debugtxt.Format("%.3fms (%2.2f %%)", time*1000.f, time/tottime * 100.f); + + debugtxt.Format("%5.2fms (%2d%%)", time*1000.f, (int)(time/tottime * 100.f)); m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, debugtxt.Ptr(), - xcoord + 60, ycoord, + xcoord + const_xindent + profile_indent, ycoord, m_canvas->GetWidth(), m_canvas->GetHeight()); - ycoord += 14; + ycoord += const_ysize; } } + // Add the ymargin for titles below the other section of debug info + ycoord += title_y_top_margin; /* Property display*/ if (m_show_debug_properties && m_propertiesPresent) { + + /* Title for debugging("Debug properties") */ + debugtxt.Format("Debug Properties"); + m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, + debugtxt.Ptr(), + xcoord + const_xindent + title_xmargin, // Adds the constant x indent (0 for now) to the title x margin + ycoord, + m_canvas->GetWidth() /* RdV, TODO ?? */, + m_canvas->GetHeight() /* RdV, TODO ?? */); + + // Increase the indent by default increase + ycoord += const_ysize; + // Add the title indent afterwards + ycoord += title_y_bottom_margin; + KX_SceneList::iterator sceneit; for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++) { @@ -1526,11 +1573,11 @@ void KX_KetsjiEngine::RenderDebugProperties() } m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, debugtxt.Ptr(), - xcoord, + xcoord + const_xindent, ycoord, m_canvas->GetWidth(), m_canvas->GetHeight()); - ycoord += 14; + ycoord += const_ysize; } else { @@ -1538,14 +1585,14 @@ void KX_KetsjiEngine::RenderDebugProperties() if (propval) { STR_String text = propval->GetText(); - debugtxt = objname + "." + propname + " = " + text; + debugtxt = objname + ": '" + propname + "' = " + text; m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, debugtxt.Ptr(), - xcoord, + xcoord + const_xindent, ycoord, m_canvas->GetWidth(), m_canvas->GetHeight()); - ycoord += 14; + ycoord += const_ysize; } } } @@ -1556,7 +1603,7 @@ void KX_KetsjiEngine::RenderDebugProperties() KX_SceneList* KX_KetsjiEngine::CurrentScenes() { - return &m_scenes; + return &m_scenes; } @@ -1572,7 +1619,7 @@ KX_Scene* KX_KetsjiEngine::FindScene(const STR_String& scenename) sceneit++; } - return ((sceneit == m_scenes.end()) ? NULL : *sceneit); + return ((sceneit == m_scenes.end()) ? NULL : *sceneit); } @@ -1635,7 +1682,7 @@ void KX_KetsjiEngine::RemoveScheduledScenes() m_scenes.erase(sceneit); break; } - } + } } m_removingScenes.clear(); } @@ -1737,7 +1784,7 @@ void KX_KetsjiEngine::ReplaceScheduledScenes() } } m_replace_scenes.clear(); - } + } } @@ -1910,7 +1957,7 @@ void KX_KetsjiEngine::SceneListsChanged(void) while ((sceneit != m_scenes.end()) && (!m_propertiesPresent)) { KX_Scene* scene = *sceneit; - vector& debugproplist = scene->GetDebugProperties(); + vector& debugproplist = scene->GetDebugProperties(); m_propertiesPresent = !debugproplist.empty(); sceneit++; } diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index b3bef016b0f..972594bd90f 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -98,7 +98,7 @@ private: /* The current list of scenes. */ KX_SceneList m_scenes; /* State variable recording the presence of object debug info in the current scene list. */ - bool m_propertiesPresent; + bool m_propertiesPresent; bool m_bInitialized; int m_activecam; @@ -136,7 +136,7 @@ private: int m_drawingmode; float m_cameraZoom; - bool m_overrideCam; + bool m_overrideCam; STR_String m_overrideSceneName; bool m_overrideCamUseOrtho; @@ -220,7 +220,7 @@ public: void SetRenderTools(RAS_IRenderTools* rendertools); void SetRasterizer(RAS_IRasterizer* rasterizer); #ifdef WITH_PYTHON - void SetPyNamespace(PyObject* pythondictionary); + void SetPyNamespace(PyObject *pythondictionary); PyObject* GetPyNamespace() { return m_pythondictionary; } #endif void SetSceneConverter(KX_ISceneConverter* sceneconverter); @@ -415,7 +415,7 @@ public: KX_Scene* CreateScene(const STR_String& scenename); KX_Scene* CreateScene(Scene *scene); - GlobalSettings* GetGlobalSettings(void); + GlobalSettings* GetGlobalSettings(void); void SetGlobalSettings(GlobalSettings* gs); protected: @@ -447,6 +447,4 @@ protected: #endif }; -#endif //__KX_KETSJIENGINE_H__ - - +#endif /* __KX_KETSJIENGINE_H__ */ diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index f5aa1bb3c75..a4e90cb1e83 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -29,8 +29,8 @@ * \ingroup ketsji */ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable : 4786) +#ifdef _MSC_VER +# pragma warning (disable:4786) #endif #include @@ -50,9 +50,9 @@ #include "GPU_material.h" KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks, - class RAS_IRenderTools* rendertools, - const RAS_LightObject& lightobj, - bool glsl) + class RAS_IRenderTools* rendertools, + const RAS_LightObject& lightobj, + bool glsl) : KX_GameObject(sgReplicationInfo,callbacks), m_rendertools(rendertools) { @@ -126,14 +126,14 @@ bool KX_LightObject::ApplyLight(KX_Scene *kxscene, int oblayer, int slot) vec[0] = worldmatrix(0,2); vec[1] = worldmatrix(1,2); vec[2] = worldmatrix(2,2); - //vec[0]= base->object->obmat[2][0]; - //vec[1]= base->object->obmat[2][1]; - //vec[2]= base->object->obmat[2][2]; - vec[3]= 0.0; + //vec[0] = base->object->obmat[2][0]; + //vec[1] = base->object->obmat[2][1]; + //vec[2] = base->object->obmat[2][2]; + vec[3] = 0.0; glLightfv((GLenum)(GL_LIGHT0+slot), GL_POSITION, vec); } else { - //vec[3]= 1.0; + //vec[3] = 1.0; glLightfv((GLenum)(GL_LIGHT0+slot), GL_POSITION, vec); glLightf((GLenum)(GL_LIGHT0+slot), GL_CONSTANT_ATTENUATION, 1.0); glLightf((GLenum)(GL_LIGHT0+slot), GL_LINEAR_ATTENUATION, m_lightobj.m_att1/m_lightobj.m_distance); @@ -145,9 +145,9 @@ bool KX_LightObject::ApplyLight(KX_Scene *kxscene, int oblayer, int slot) vec[0] = -worldmatrix(0,2); vec[1] = -worldmatrix(1,2); vec[2] = -worldmatrix(2,2); - //vec[0]= -base->object->obmat[2][0]; - //vec[1]= -base->object->obmat[2][1]; - //vec[2]= -base->object->obmat[2][2]; + //vec[0] = -base->object->obmat[2][0]; + //vec[1] = -base->object->obmat[2][1]; + //vec[2] = -base->object->obmat[2][2]; glLightfv((GLenum)(GL_LIGHT0+slot), GL_SPOT_DIRECTION, vec); glLightf((GLenum)(GL_LIGHT0+slot), GL_SPOT_CUTOFF, m_lightobj.m_spotsize / 2.0f); glLightf((GLenum)(GL_LIGHT0+slot), GL_SPOT_EXPONENT, 128.0f * m_lightobj.m_spotblend); @@ -161,10 +161,10 @@ bool KX_LightObject::ApplyLight(KX_Scene *kxscene, int oblayer, int slot) vec[0] = vec[1] = vec[2] = vec[3] = 0.0; } else { - vec[0]= m_lightobj.m_energy*m_lightobj.m_red; - vec[1]= m_lightobj.m_energy*m_lightobj.m_green; - vec[2]= m_lightobj.m_energy*m_lightobj.m_blue; - vec[3]= 1.0; + vec[0] = m_lightobj.m_energy*m_lightobj.m_red; + vec[1] = m_lightobj.m_energy*m_lightobj.m_green; + vec[2] = m_lightobj.m_energy*m_lightobj.m_blue; + vec[3] = 1.0; } glLightfv((GLenum)(GL_LIGHT0+slot), GL_DIFFUSE, vec); @@ -173,10 +173,10 @@ bool KX_LightObject::ApplyLight(KX_Scene *kxscene, int oblayer, int slot) vec[0] = vec[1] = vec[2] = vec[3] = 0.0; } else if (m_lightobj.m_nodiffuse) { - vec[0]= m_lightobj.m_energy*m_lightobj.m_red; - vec[1]= m_lightobj.m_energy*m_lightobj.m_green; - vec[2]= m_lightobj.m_energy*m_lightobj.m_blue; - vec[3]= 1.0; + vec[0] = m_lightobj.m_energy*m_lightobj.m_red; + vec[1] = m_lightobj.m_energy*m_lightobj.m_green; + vec[2] = m_lightobj.m_energy*m_lightobj.m_blue; + vec[3] = 1.0; } glLightfv((GLenum)(GL_LIGHT0+slot), GL_SPECULAR, vec); @@ -344,7 +344,7 @@ PyAttributeDef KX_LightObject::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_LightObject::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_LightObject::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_LightObject* self = static_cast(self_v); return Py_BuildValue("[fff]", self->m_lightobj.m_red, self->m_lightobj.m_green, self->m_lightobj.m_blue); @@ -365,9 +365,9 @@ int KX_LightObject::pyattr_set_color(void *self_v, const KX_PYATTRIBUTE_DEF *att return PY_SET_ATTR_FAIL; } -PyObject* KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - PyObject* retvalue; + PyObject *retvalue; const char* type = attrdef->m_name; @@ -387,13 +387,13 @@ PyObject* KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUT return retvalue; } -PyObject* KX_LightObject::pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_LightObject::pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_LightObject* self = static_cast(self_v); return PyLong_FromSsize_t(self->m_lightobj.m_type); } -int KX_LightObject::pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value) +int KX_LightObject::pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_LightObject* self = static_cast(self_v); int val = PyLong_AsSsize_t(value); @@ -402,7 +402,7 @@ int KX_LightObject::pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attr return PY_SET_ATTR_FAIL; } - switch(val) { + switch (val) { case 0: self->m_lightobj.m_type = self->m_lightobj.LIGHT_SPOT; break; diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index 9fe13f471ba..52f076c772a 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -76,12 +76,11 @@ public: #ifdef WITH_PYTHON /* attributes */ static PyObject* pyattr_get_color(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static int pyattr_set_color(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value); + static int pyattr_set_color(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_typeconst(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static int pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value); + static int pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); #endif }; -#endif //__KX_LIGHT_H__ - +#endif /* __KX_LIGHT_H__ */ diff --git a/source/gameengine/Ketsji/KX_LightIpoSGController.h b/source/gameengine/Ketsji/KX_LightIpoSGController.h index 3a3a9677b04..c82fe7bcad5 100644 --- a/source/gameengine/Ketsji/KX_LightIpoSGController.h +++ b/source/gameengine/Ketsji/KX_LightIpoSGController.h @@ -74,15 +74,15 @@ public: m_modified = true; } - void SetModifyEnergy(bool modify) { + void SetModifyEnergy(bool modify) { m_modify_energy = modify; } - void SetModifyColor(bool modify) { + void SetModifyColor(bool modify) { m_modify_color = modify; } - void SetModifyDist(bool modify) { + void SetModifyDist(bool modify) { m_modify_dist = modify; } @@ -102,5 +102,4 @@ public: #endif }; -#endif // __KX_LIGHTIPOSGCONTROLLER_H__ - +#endif /* __KX_LIGHTIPOSGCONTROLLER_H__ */ diff --git a/source/gameengine/Ketsji/KX_MaterialIpoController.h b/source/gameengine/Ketsji/KX_MaterialIpoController.h index ee5546641c2..a7e9c2cc1c5 100644 --- a/source/gameengine/Ketsji/KX_MaterialIpoController.h +++ b/source/gameengine/Ketsji/KX_MaterialIpoController.h @@ -62,7 +62,4 @@ public: #endif }; - - - -#endif//__KX_MATERIALIPOCONTROLLER_H__ +#endif /* __KX_MATERIALIPOCONTROLLER_H__ */ diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index f1a9a93c2db..87c366046ad 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -105,7 +105,7 @@ KX_MeshProxy::~KX_MeshProxy() // stuff for cvalue related things CValue* KX_MeshProxy::Calc(VALUE_OPERATOR op, CValue *val) { return NULL;} -CValue* KX_MeshProxy::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) { return NULL;} +CValue* KX_MeshProxy::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) { return NULL;} const STR_String & KX_MeshProxy::GetText() {return m_meshobj->GetName();}; double KX_MeshProxy::GetNumber() { return -1;} @@ -116,7 +116,7 @@ CValue* KX_MeshProxy::GetReplica() { return NULL;} // stuff for python integration -PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* args, PyObject* kwds) +PyObject *KX_MeshProxy::PyGetMaterialName(PyObject *args, PyObject *kwds) { int matid= 1; STR_String matname; @@ -134,7 +134,7 @@ PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* args, PyObject* kwds) } -PyObject* KX_MeshProxy::PyGetTextureName(PyObject* args, PyObject* kwds) +PyObject *KX_MeshProxy::PyGetTextureName(PyObject *args, PyObject *kwds) { int matid= 1; STR_String matname; @@ -151,7 +151,7 @@ PyObject* KX_MeshProxy::PyGetTextureName(PyObject* args, PyObject* kwds) } -PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* args, PyObject* kwds) +PyObject *KX_MeshProxy::PyGetVertexArrayLength(PyObject *args, PyObject *kwds) { int matid= 0; int length = 0; @@ -174,7 +174,7 @@ PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* args, PyObject* kwds) } -PyObject* KX_MeshProxy::PyGetVertex(PyObject* args, PyObject* kwds) +PyObject *KX_MeshProxy::PyGetVertex(PyObject *args, PyObject *kwds) { int vertexindex; int matindex; @@ -192,10 +192,10 @@ PyObject* KX_MeshProxy::PyGetVertex(PyObject* args, PyObject* kwds) return (new KX_VertexProxy(this, vertex))->NewProxy(true); } -PyObject* KX_MeshProxy::PyGetPolygon(PyObject* args, PyObject* kwds) +PyObject *KX_MeshProxy::PyGetPolygon(PyObject *args, PyObject *kwds) { int polyindex= 1; - PyObject* polyob = NULL; + PyObject *polyob = NULL; if (!PyArg_ParseTuple(args,"i:getPolygon",&polyindex)) return NULL; @@ -218,9 +218,9 @@ PyObject* KX_MeshProxy::PyGetPolygon(PyObject* args, PyObject* kwds) return polyob; } -PyObject* KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_MeshProxy* self= static_cast(self_v); + KX_MeshProxy* self = static_cast(self_v); int tot= self->m_meshobj->NumMaterials(); int i; @@ -233,17 +233,17 @@ PyObject* KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_ for (i=0; im_bucket->GetPolyMaterial(); - /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */ + /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject *)? - Campbell */ if (polymat->GetFlag() & RAS_BLENDERMAT) { KX_BlenderMaterial *mat = static_cast(polymat); PyList_SET_ITEM(materials, i, mat->GetProxy()); } - else { + else { KX_PolygonMaterial *mat = static_cast(polymat); PyList_SET_ITEM(materials, i, mat->GetProxy()); } - } + } return materials; } @@ -260,7 +260,7 @@ PyObject * KX_MeshProxy::pyattr_get_numPolygons(void * selfv, const KX_PYATTRIBU } /* a close copy of ConvertPythonToGameObject but for meshes */ -bool ConvertPythonToMesh(PyObject * value, RAS_MeshObject **object, bool py_none_ok, const char *error_prefix) +bool ConvertPythonToMesh(PyObject *value, RAS_MeshObject **object, bool py_none_ok, const char *error_prefix) { if (value==NULL) { PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix); @@ -297,7 +297,7 @@ bool ConvertPythonToMesh(PyObject * value, RAS_MeshObject **object, bool py_none if (kx_mesh==NULL) { PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix); return false; - } + } *object = kx_mesh->GetMesh(); return true; diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h index 58b5c87e494..98e73aa626f 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.h +++ b/source/gameengine/Ketsji/KX_MeshProxy.h @@ -37,7 +37,7 @@ #include "SCA_IObject.h" /* utility conversion function */ -bool ConvertPythonToMesh(PyObject * value, class RAS_MeshObject **object, bool py_none_ok, const char *error_prefix); +bool ConvertPythonToMesh(PyObject *value, class RAS_MeshObject **object, bool py_none_ok, const char *error_prefix); class KX_MeshProxy : public CValue { @@ -73,11 +73,10 @@ public: KX_PYMETHOD(KX_MeshProxy,GetPolygon); static PyObject* pyattr_get_materials(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject * pyattr_get_numMaterials(void * self, const KX_PYATTRIBUTE_DEF * attrdef); - static PyObject * pyattr_get_numPolygons(void * self, const KX_PYATTRIBUTE_DEF * attrdef); + static PyObject *pyattr_get_numMaterials(void * self, const KX_PYATTRIBUTE_DEF * attrdef); + static PyObject *pyattr_get_numPolygons(void * self, const KX_PYATTRIBUTE_DEF * attrdef); }; -#endif // WITH_PYTHON - -#endif //__KX_MESHPROXY_H__ +#endif /* WITH_PYTHON */ +#endif /* __KX_MESHPROXY_H__ */ diff --git a/source/gameengine/Ketsji/KX_MotionState.h b/source/gameengine/Ketsji/KX_MotionState.h index 3bead93cbda..116e62f408f 100644 --- a/source/gameengine/Ketsji/KX_MotionState.h +++ b/source/gameengine/Ketsji/KX_MotionState.h @@ -62,5 +62,4 @@ public: #endif }; -#endif //__KX_MOTIONSTATE_H__ - +#endif /* __KX_MOTIONSTATE_H__ */ diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index bfee124d443..9368bc6458f 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -30,11 +30,10 @@ * \ingroup ketsji */ - -#if defined(WIN32) && !defined(FREE_WINDOWS) -// This warning tells us about truncation of __long__ stl-generated names. -// It can occasionally cause DevStudio to have internal compiler warnings. -#pragma warning( disable : 4786 ) +#ifdef _MSC_VER + /* This warning tells us about truncation of __long__ stl-generated names. + * It can occasionally cause DevStudio to have internal compiler warnings. */ +# pragma warning(disable:4786) #endif #include "MT_Point3.h" @@ -60,14 +59,14 @@ /* ------------------------------------------------------------------------- */ KX_MouseFocusSensor::KX_MouseFocusSensor(SCA_MouseManager* eventmgr, - int startx, - int starty, - short int mousemode, - int focusmode, - bool bTouchPulse, - KX_Scene* kxscene, - KX_KetsjiEngine *kxengine, - SCA_IObject* gameobj) + int startx, + int starty, + short int mousemode, + int focusmode, + bool bTouchPulse, + KX_Scene* kxscene, + KX_KetsjiEngine *kxengine, + SCA_IObject* gameobj) : SCA_MouseSensor(eventmgr, startx, starty, mousemode, gameobj), m_focusmode(focusmode), m_bTouchPulse(bTouchPulse), @@ -142,7 +141,7 @@ bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo* client_info, KX_RayCast* r KX_GameObject* hitKXObj = client_info->m_gameobject; /* Is this me? In the ray test, there are a lot of extra checks - * for aliasing artefacts from self-hits. That doesn't happen + * for aliasing artifacts from self-hits. That doesn't happen * here, so a simple test suffices. Or does the camera also get * self-hits? (No, and the raysensor shouldn't do it either, since * self-hits are excluded by setting the correct ignore-object.) @@ -239,7 +238,7 @@ bool KX_MouseFocusSensor::ParentObjectHasFocusCamera(KX_Camera *cam) /* build the from and to point in normalized device coordinates * Normalized device coordinates are [-1,1] in x, y, z - * + * * The actual z coordinates used don't have to be exact just infront and * behind of the near and far clip planes. */ @@ -309,8 +308,7 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus() list* cameras = m_kxscene->GetCameras(); list::iterator it = cameras->begin(); - while(it != cameras->end()) - { + while (it != cameras->end()) { if (((*it) != cam) && (*it)->GetViewport()) if (ParentObjectHasFocusCamera(*it)) return true; @@ -392,30 +390,30 @@ PyAttributeDef KX_MouseFocusSensor::Attributes[] = { }; /* Attributes */ -PyObject* KX_MouseFocusSensor::pyattr_get_ray_source(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_MouseFocusSensor::pyattr_get_ray_source(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_MouseFocusSensor* self= static_cast(self_v); + KX_MouseFocusSensor* self = static_cast(self_v); return PyObjectFrom(self->RaySource()); } -PyObject* KX_MouseFocusSensor::pyattr_get_ray_target(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_MouseFocusSensor::pyattr_get_ray_target(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_MouseFocusSensor* self= static_cast(self_v); + KX_MouseFocusSensor* self = static_cast(self_v); return PyObjectFrom(self->RayTarget()); } -PyObject* KX_MouseFocusSensor::pyattr_get_ray_direction(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_MouseFocusSensor::pyattr_get_ray_direction(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_MouseFocusSensor* self= static_cast(self_v); + KX_MouseFocusSensor* self = static_cast(self_v); MT_Vector3 dir = self->RayTarget() - self->RaySource(); if (MT_fuzzyZero(dir)) dir.setValue(0,0,0); else dir.normalize(); return PyObjectFrom(dir); } -PyObject* KX_MouseFocusSensor::pyattr_get_hit_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_MouseFocusSensor::pyattr_get_hit_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_MouseFocusSensor* self= static_cast(self_v); + KX_MouseFocusSensor* self = static_cast(self_v); if (self->m_hitObject) return self->m_hitObject->GetProxy(); @@ -423,21 +421,21 @@ PyObject* KX_MouseFocusSensor::pyattr_get_hit_object(void *self_v, const KX_PYAT Py_RETURN_NONE; } -PyObject* KX_MouseFocusSensor::pyattr_get_hit_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_MouseFocusSensor::pyattr_get_hit_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_MouseFocusSensor* self= static_cast(self_v); + KX_MouseFocusSensor* self = static_cast(self_v); return PyObjectFrom(self->HitPosition()); } -PyObject* KX_MouseFocusSensor::pyattr_get_hit_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_MouseFocusSensor::pyattr_get_hit_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_MouseFocusSensor* self= static_cast(self_v); + KX_MouseFocusSensor* self = static_cast(self_v); return PyObjectFrom(self->HitNormal()); } -PyObject* KX_MouseFocusSensor::pyattr_get_hit_uv(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_MouseFocusSensor::pyattr_get_hit_uv(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_MouseFocusSensor* self= static_cast(self_v); + KX_MouseFocusSensor* self = static_cast(self_v); return PyObjectFrom(self->HitUV()); } diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h index db9e3697492..1f7809831e7 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h @@ -111,7 +111,7 @@ class KX_MouseFocusSensor : public SCA_MouseSensor static PyObject* pyattr_get_hit_normal(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_hit_uv(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ /* --------------------------------------------------------------------- */ SCA_IObject* m_hitObject; @@ -151,27 +151,27 @@ class KX_MouseFocusSensor : public SCA_MouseSensor /** * (in game world coordinates) the place where the object was hit. */ - MT_Point3 m_hitPosition; + MT_Point3 m_hitPosition; /** * (in game world coordinates) the position to which to shoot the ray. */ - MT_Point3 m_prevTargetPoint; + MT_Point3 m_prevTargetPoint; /** * (in game world coordinates) the position from which to shoot the ray. */ - MT_Point3 m_prevSourcePoint; - + MT_Point3 m_prevSourcePoint; + /** * (in game world coordinates) the face normal of the vertex where * the object was hit. */ - MT_Vector3 m_hitNormal; + MT_Vector3 m_hitNormal; /** * UV texture coordinate of the hit point if any, (0,0) otherwise */ - MT_Vector2 m_hitUV; + MT_Vector2 m_hitUV; /** * The KX scene that holds the camera. The camera position @@ -183,5 +183,4 @@ class KX_MouseFocusSensor : public SCA_MouseSensor KX_KetsjiEngine* m_kxengine; }; -#endif //__KX_MOUSESENSOR - +#endif /* __KX_MOUSESENSOR */ diff --git a/source/gameengine/Ketsji/KX_NavMeshObject.cpp b/source/gameengine/Ketsji/KX_NavMeshObject.cpp index 35058e5fe5d..33656e9fd52 100644 --- a/source/gameengine/Ketsji/KX_NavMeshObject.cpp +++ b/source/gameengine/Ketsji/KX_NavMeshObject.cpp @@ -210,7 +210,7 @@ bool KX_NavMeshObject::BuildVertIndArrays(float *&vertices, int& nverts, { //detailed mesh vertex memcpy(dvertices+3*(newIdx-nverts), allVerts+3*vi, 3*sizeof(float)); - } + } } } @@ -245,11 +245,11 @@ bool KX_NavMeshObject::BuildVertIndArrays(float *&vertices, int& nverts, { memset(vert, 0, 3*sizeof(float)); //vertex isn't in any poly, set dummy zero coordinates } - vert+=3; + vert+=3; } //create tris - polys = (unsigned short*)MEM_callocN(sizeof(unsigned short)*3*2*npolys, "BuildVertIndArrays polys"); + polys = (unsigned short *)MEM_callocN(sizeof(unsigned short)*3*2*npolys, "BuildVertIndArrays polys"); memset(polys, 0xff, sizeof(unsigned short)*3*2*npolys); unsigned short *poly = polys; RAS_Polygon* raspoly; @@ -258,10 +258,10 @@ bool KX_NavMeshObject::BuildVertIndArrays(float *&vertices, int& nverts, raspoly = meshobj->GetPolygon(p); for (int v=0; vVertexCount()-2; v++) { - poly[0]= raspoly->GetVertex(0)->getOrigIndex(); + poly[0] = raspoly->GetVertex(0)->getOrigIndex(); for (size_t i=1; i<3; i++) { - poly[i]= raspoly->GetVertex(v+i)->getOrigIndex(); + poly[i] = raspoly->GetVertex(v+i)->getOrigIndex(); } poly += 6; } @@ -294,7 +294,7 @@ bool KX_NavMeshObject::BuildNavMesh() float *vertices = NULL, *dvertices = NULL; unsigned short *polys = NULL, *dtris = NULL, *dmeshes = NULL; - int nverts = 0, npolys = 0, ndvertsuniq = 0, ndtris = 0; + int nverts = 0, npolys = 0, ndvertsuniq = 0, ndtris = 0; int vertsPerPoly = 0; if (!BuildVertIndArrays(vertices, nverts, polys, npolys, dmeshes, dvertices, ndvertsuniq, dtris, ndtris, vertsPerPoly ) @@ -446,11 +446,11 @@ bool KX_NavMeshObject::BuildNavMesh() dtl.nverts = dmeshes[i*4+1]; dtl.tbase = dmeshes[i*4+2]; dtl.ntris = dmeshes[i*4+3]; - } + } } m_navMesh = new dtStatNavMesh; - m_navMesh->init(data, dataSize, true); + m_navMesh->init(data, dataSize, true); delete [] vertices; @@ -487,7 +487,7 @@ void KX_NavMeshObject::DrawNavMesh(NavMeshRenderMode renderMode) const dtStatPoly* poly = m_navMesh->getPoly(pi); for (int i = 0, j = (int)poly->nv-1; i < (int)poly->nv; j = i++) - { + { if (poly->n[j] && renderMode==RM_WALLS) continue; const float* vif = m_navMesh->getVertex(poly->v[i]); @@ -564,7 +564,7 @@ int KX_NavMeshObject::FindPath(const MT_Point3& from, const MT_Point3& to, float if (!m_navMesh) return 0; MT_Point3 localfrom = TransformToLocalCoords(from); - MT_Point3 localto = TransformToLocalCoords(to); + MT_Point3 localto = TransformToLocalCoords(to); float spos[3], epos[3]; localfrom.getValue(spos); flipAxes(spos); localto.getValue(epos); flipAxes(epos); @@ -598,7 +598,7 @@ float KX_NavMeshObject::Raycast(const MT_Point3& from, const MT_Point3& to) if (!m_navMesh) return 0.f; MT_Point3 localfrom = TransformToLocalCoords(from); - MT_Point3 localto = TransformToLocalCoords(to); + MT_Point3 localto = TransformToLocalCoords(to); float spos[3], epos[3]; localfrom.getValue(spos); flipAxes(spos); localto.getValue(epos); flipAxes(epos); diff --git a/source/gameengine/Ketsji/KX_NavMeshObject.h b/source/gameengine/Ketsji/KX_NavMeshObject.h index db35a011c16..1599361b334 100644 --- a/source/gameengine/Ketsji/KX_NavMeshObject.h +++ b/source/gameengine/Ketsji/KX_NavMeshObject.h @@ -74,8 +74,7 @@ public: KX_PYMETHOD_DOC(KX_NavMeshObject, raycast); KX_PYMETHOD_DOC(KX_NavMeshObject, draw); KX_PYMETHOD_DOC_NOARGS(KX_NavMeshObject, rebuild); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; -#endif //__KX_NAVMESHOBJECT_H__ - +#endif /* __KX_NAVMESHOBJECT_H__ */ diff --git a/source/gameengine/Ketsji/KX_NearSensor.h b/source/gameengine/Ketsji/KX_NearSensor.h index 82f523283ed..ef6e15f602f 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.h +++ b/source/gameengine/Ketsji/KX_NearSensor.h @@ -100,9 +100,8 @@ public: return 0; } -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; -#endif //__KX_NEARSENSOR_H__ - +#endif /* __KX_NEARSENSOR_H__ */ diff --git a/source/gameengine/Ketsji/KX_ObColorIpoSGController.h b/source/gameengine/Ketsji/KX_ObColorIpoSGController.h index 9a9b3dac098..a7b0b2c4ffc 100644 --- a/source/gameengine/Ketsji/KX_ObColorIpoSGController.h +++ b/source/gameengine/Ketsji/KX_ObColorIpoSGController.h @@ -77,5 +77,4 @@ public: #endif }; -#endif // __KX_OBCOLORIPOSGCONTROLLER_H__ - +#endif /* __KX_OBCOLORIPOSGCONTROLLER_H__ */ diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index a3f098c3b1f..2999550fb8f 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -114,7 +114,14 @@ bool KX_ObjectActuator::Update() (m_bitLocalFlag.AngularVelocity) != 0 ); m_active_combined_velocity = false; - } + } + + // Explicitly stop the movement if we're using a character (apply movement is a little different for characters) + if (parent->GetPhysicsController()->IsCharacter()) { + MT_Vector3 vec(0.0, 0.0, 0.0); + parent->ApplyMovement(vec, true); + } + m_linear_damping_active = false; m_angular_damping_active = false; m_error_accumulator.setValue(0.0,0.0,0.0); @@ -389,8 +396,8 @@ static unsigned char mathutils_kxobactu_vector_cb_index = -1; /* index for our c static int mathutils_obactu_generic_check(BaseMathObject *bmo) { - KX_ObjectActuator* self= static_castBGE_PROXY_REF(bmo->cb_user); - if (self==NULL) + KX_ObjectActuator* self = static_castBGE_PROXY_REF(bmo->cb_user); + if (self == NULL) return -1; return 0; @@ -398,11 +405,11 @@ static int mathutils_obactu_generic_check(BaseMathObject *bmo) static int mathutils_obactu_vector_get(BaseMathObject *bmo, int subtype) { - KX_ObjectActuator* self= static_castBGE_PROXY_REF(bmo->cb_user); - if (self==NULL) + KX_ObjectActuator* self = static_castBGE_PROXY_REF(bmo->cb_user); + if (self == NULL) return -1; - switch(subtype) { + switch (subtype) { case MATHUTILS_VEC_CB_LINV: self->m_linear_velocity.getValue(bmo->data); break; @@ -416,11 +423,11 @@ static int mathutils_obactu_vector_get(BaseMathObject *bmo, int subtype) static int mathutils_obactu_vector_set(BaseMathObject *bmo, int subtype) { - KX_ObjectActuator* self= static_castBGE_PROXY_REF(bmo->cb_user); - if (self==NULL) + KX_ObjectActuator* self = static_castBGE_PROXY_REF(bmo->cb_user); + if (self == NULL) return -1; - switch(subtype) { + switch (subtype) { case MATHUTILS_VEC_CB_LINV: self->m_linear_velocity.setValue(bmo->data); break; @@ -442,13 +449,13 @@ static int mathutils_obactu_vector_get_index(BaseMathObject *bmo, int subtype, i static int mathutils_obactu_vector_set_index(BaseMathObject *bmo, int subtype, int index) { - float f= bmo->data[index]; + float f = bmo->data[index]; /* lazy, avoid repeteing the case statement */ if (mathutils_obactu_vector_get(bmo, subtype) == -1) return -1; - bmo->data[index]= f; + bmo->data[index] = f; return mathutils_obactu_vector_set(bmo, subtype); } @@ -460,14 +467,14 @@ Mathutils_Callback mathutils_obactu_vector_cb = { mathutils_obactu_vector_set_index }; -PyObject* KX_ObjectActuator::pyattr_get_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_ObjectActuator::pyattr_get_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV); } int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_ObjectActuator* self= static_cast(self_v); + KX_ObjectActuator* self = static_cast(self_v); if (!PyVecTo(value, self->m_linear_velocity)) return PY_SET_ATTR_FAIL; @@ -476,14 +483,14 @@ int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *a return PY_SET_ATTR_SUCCESS; } -PyObject* KX_ObjectActuator::pyattr_get_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_ObjectActuator::pyattr_get_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV); } int KX_ObjectActuator::pyattr_set_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_ObjectActuator* self= static_cast(self_v); + KX_ObjectActuator* self = static_cast(self_v); if (!PyVecTo(value, self->m_angular_velocity)) return PY_SET_ATTR_FAIL; @@ -501,7 +508,7 @@ void KX_ObjectActuator_Mathutils_Callback_Init(void) #endif // USE_MATHUTILS -PyObject* KX_ObjectActuator::pyattr_get_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_ObjectActuator::pyattr_get_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_ObjectActuator* self = reinterpret_cast(self_v); PyObject *retVal = PyList_New(3); @@ -517,7 +524,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitX(void *self_v, const KX_PYATTRIBUTE { KX_ObjectActuator* self = reinterpret_cast(self_v); - PyObject* seq = PySequence_Fast(value, ""); + PyObject *seq = PySequence_Fast(value, ""); if (seq && PySequence_Fast_GET_SIZE(seq) == 3) { self->m_drot[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)); @@ -537,7 +544,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitX(void *self_v, const KX_PYATTRIBUTE return PY_SET_ATTR_FAIL; } -PyObject* KX_ObjectActuator::pyattr_get_forceLimitY(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_ObjectActuator::pyattr_get_forceLimitY(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_ObjectActuator* self = reinterpret_cast(self_v); PyObject *retVal = PyList_New(3); @@ -553,7 +560,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitY(void *self_v, const KX_PYATTRIBUTE { KX_ObjectActuator* self = reinterpret_cast(self_v); - PyObject* seq = PySequence_Fast(value, ""); + PyObject *seq = PySequence_Fast(value, ""); if (seq && PySequence_Fast_GET_SIZE(seq) == 3) { self->m_drot[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)); @@ -573,7 +580,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitY(void *self_v, const KX_PYATTRIBUTE return PY_SET_ATTR_FAIL; } -PyObject* KX_ObjectActuator::pyattr_get_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_ObjectActuator::pyattr_get_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_ObjectActuator* self = reinterpret_cast(self_v); PyObject *retVal = PyList_New(3); @@ -589,7 +596,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitZ(void *self_v, const KX_PYATTRIBUTE { KX_ObjectActuator* self = reinterpret_cast(self_v); - PyObject* seq = PySequence_Fast(value, ""); + PyObject *seq = PySequence_Fast(value, ""); if (seq && PySequence_Fast_GET_SIZE(seq) == 3) { self->m_drot[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)); @@ -609,7 +616,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitZ(void *self_v, const KX_PYATTRIBUTE return PY_SET_ATTR_FAIL; } -PyObject* KX_ObjectActuator::pyattr_get_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_ObjectActuator::pyattr_get_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_ObjectActuator* actuator = static_cast(self); if (!actuator->m_reference) @@ -632,7 +639,7 @@ int KX_ObjectActuator::pyattr_set_reference(void *self, const struct KX_PYATTRIB if (refOb==NULL) { actuator->m_reference= NULL; } - else { + else { actuator->m_reference = refOb; actuator->m_reference->RegisterActuator(actuator); } diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h index 397234488b7..b0efee550af 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.h +++ b/source/gameengine/Ketsji/KX_ObjectActuator.h @@ -218,9 +218,8 @@ public: return 0; } -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; -#endif //__KX_OBJECTACTUATOR_H__ - +#endif /* __KX_OBJECTACTUATOR_H__ */ diff --git a/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp b/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp index a942f87856c..99d9fc7f9ee 100644 --- a/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp +++ b/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp @@ -257,7 +257,7 @@ void KX_ObstacleSimulation::AddObstacleForObj(KX_GameObject* gameobj) } void KX_ObstacleSimulation::AddObstaclesForNavMesh(KX_NavMeshObject* navmeshobj) -{ +{ dtStatNavMesh* navmesh = navmeshobj->GetNavMesh(); if (navmesh) { @@ -267,7 +267,7 @@ void KX_ObstacleSimulation::AddObstaclesForNavMesh(KX_NavMeshObject* navmeshobj) const dtStatPoly* poly = navmesh->getPoly(pi); for (int i = 0, j = (int)poly->nv-1; i < (int)poly->nv; j = i++) - { + { if (poly->n[j]) continue; const float* vj = navmesh->getVertex(poly->v[j]); const float* vi = navmesh->getVertex(poly->v[i]); @@ -364,9 +364,9 @@ void KX_ObstacleSimulation::DrawObstacles() else if (m_obstacles[i]->m_shape==KX_OBSTACLE_CIRCLE) { KX_RasterizerDrawDebugCircle(m_obstacles[i]->m_pos, m_obstacles[i]->m_rad, bluecolor, - normal, SECTORS_NUM); + normal, SECTORS_NUM); } - } + } } static MT_Point3 nearestPointToObstacle(MT_Point3& pos ,KX_Obstacle* obstacle) @@ -424,7 +424,7 @@ KX_ObstacleSimulationTOI::KX_ObstacleSimulationTOI(MT_Scalar levelHeight, bool e void KX_ObstacleSimulationTOI::AdjustObstacleVelocity(KX_Obstacle* activeObst, KX_NavMeshObject* activeNavMeshObj, - MT_Vector3& velocity, MT_Scalar maxDeltaSpeed, MT_Scalar maxDeltaAngle) + MT_Vector3& velocity, MT_Scalar maxDeltaSpeed, MT_Scalar maxDeltaAngle) { int nobs = m_obstacles.size(); int obstidx = std::find(m_obstacles.begin(), m_obstacles.end(), activeObst) - m_obstacles.begin(); @@ -446,7 +446,7 @@ void KX_ObstacleSimulationTOI::AdjustObstacleVelocity(KX_Obstacle* activeObst, K vadd(vel, activeObst->vel, dv); velocity.x() = vel[0]; - velocity.y() = vel[1]; + velocity.y() = vel[1]; } ///////////*********TOI_rays**********///////////////// @@ -642,7 +642,7 @@ static void processSamples(KX_Obstacle* activeObst, KX_NavMeshObject* activeNavM for (int n = 0; n < nspos; ++n) { float vcand[2]; - vcpy(vcand, &spos[n*2]); + vcpy(vcand, &spos[n*2]); // Find min time of impact and exit amongst all obstacles. float tmin = maxToi; diff --git a/source/gameengine/Ketsji/KX_ObstacleSimulation.h b/source/gameengine/Ketsji/KX_ObstacleSimulation.h index 5b359fc031e..50589b5bc69 100644 --- a/source/gameengine/Ketsji/KX_ObstacleSimulation.h +++ b/source/gameengine/Ketsji/KX_ObstacleSimulation.h @@ -34,13 +34,13 @@ class KX_GameObject; class KX_NavMeshObject; enum KX_OBSTACLE_TYPE -{ +{ KX_OBSTACLE_OBJ, KX_OBSTACLE_NAV_MESH, }; enum KX_OBSTACLE_SHAPE -{ +{ KX_OBSTACLE_CIRCLE, KX_OBSTACLE_SEGMENT, }; @@ -86,9 +86,9 @@ public: void DestroyObstacleForObj(KX_GameObject* gameobj); void AddObstaclesForNavMesh(KX_NavMeshObject* navmesh); KX_Obstacle* GetObstacle(KX_GameObject* gameobj); - void UpdateObstacles(); + void UpdateObstacles(); virtual void AdjustObstacleVelocity(KX_Obstacle* activeObst, KX_NavMeshObject* activeNavMeshObj, - MT_Vector3& velocity, MT_Scalar maxDeltaSpeed,MT_Scalar maxDeltaAngle); + MT_Vector3& velocity, MT_Scalar maxDeltaSpeed,MT_Scalar maxDeltaAngle); }; class KX_ObstacleSimulationTOI: public KX_ObstacleSimulation diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index 5058af18d15..6926fdb1d4c 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -172,10 +172,10 @@ PyAttributeDef KX_ParentActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_ParentActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_ParentActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_ParentActuator* actuator = static_cast(self); - if (!actuator->m_ob) + if (!actuator->m_ob) Py_RETURN_NONE; else return actuator->m_ob->GetProxy(); @@ -190,7 +190,7 @@ int KX_ParentActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error if (actuator->m_ob != NULL) - actuator->m_ob->UnregisterActuator(actuator); + actuator->m_ob->UnregisterActuator(actuator); actuator->m_ob = (SCA_IObject*) gameobj; diff --git a/source/gameengine/Ketsji/KX_ParentActuator.h b/source/gameengine/Ketsji/KX_ParentActuator.h index 6191b889da3..40baac6b2b2 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.h +++ b/source/gameengine/Ketsji/KX_ParentActuator.h @@ -81,12 +81,11 @@ public: /* --------------------------------------------------------------------- */ /* These are used to get and set m_ob */ - static PyObject* pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; /* end of class KX_ParentActuator : public SCA_PropertyActuator */ -#endif - +#endif /* __KX_PARENTACTUATOR_H__ */ diff --git a/source/gameengine/Ketsji/KX_PhysicsEngineEnums.h b/source/gameengine/Ketsji/KX_PhysicsEngineEnums.h index 5cebedf8c30..ca99c2e7526 100644 --- a/source/gameengine/Ketsji/KX_PhysicsEngineEnums.h +++ b/source/gameengine/Ketsji/KX_PhysicsEngineEnums.h @@ -39,5 +39,4 @@ enum e_PhysicsEngine UseBullet = 5, }; -#endif //__KX_PHYSICSENGINEENUMS_H__ - +#endif /* __KX_PHYSICSENGINEENUMS_H__ */ diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp index 225a1628b3b..f18c35c0c78 100644 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp +++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp @@ -51,7 +51,7 @@ KX_PhysicsObjectWrapper::~KX_PhysicsObjectWrapper() #ifdef WITH_PYTHON -PyObject* KX_PhysicsObjectWrapper::PySetPosition(PyObject* args) +PyObject *KX_PhysicsObjectWrapper::PySetPosition(PyObject *args) { float x,y,z; if (PyArg_ParseTuple(args,"fff:setPosition",&x,&y,&z)) @@ -65,7 +65,7 @@ PyObject* KX_PhysicsObjectWrapper::PySetPosition(PyObject* args) } -PyObject* KX_PhysicsObjectWrapper::PySetLinearVelocity(PyObject* args) +PyObject *KX_PhysicsObjectWrapper::PySetLinearVelocity(PyObject *args) { float x,y,z; int local; @@ -79,7 +79,7 @@ PyObject* KX_PhysicsObjectWrapper::PySetLinearVelocity(PyObject* args) Py_RETURN_NONE; } -PyObject* KX_PhysicsObjectWrapper::PySetAngularVelocity(PyObject* args) +PyObject *KX_PhysicsObjectWrapper::PySetAngularVelocity(PyObject *args) { float x,y,z; int local; @@ -93,7 +93,7 @@ PyObject* KX_PhysicsObjectWrapper::PySetAngularVelocity(PyObject* args) Py_RETURN_NONE; } -PyObject* KX_PhysicsObjectWrapper::PySetActive(PyObject* args) +PyObject* KX_PhysicsObjectWrapper::PySetActive(PyObject *args) { int active; if (PyArg_ParseTuple(args,"i:setActive",&active)) diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h index a074ff9a3bd..171416c5e8f 100644 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h +++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h @@ -49,12 +49,11 @@ public: KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetAngularVelocity); KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetActive); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ private: class PHY_IPhysicsController* m_ctrl; PHY_IPhysicsEnvironment* m_physenv; }; -#endif //__KX_PHYSICSOBJECTWRAPPER_H__ - +#endif /* __KX_PHYSICSOBJECTWRAPPER_H__ */ diff --git a/source/gameengine/Ketsji/KX_PhysicsPropertiesobsolete.h b/source/gameengine/Ketsji/KX_PhysicsPropertiesobsolete.h index 86ba2500763..ee685edb9c1 100644 --- a/source/gameengine/Ketsji/KX_PhysicsPropertiesobsolete.h +++ b/source/gameengine/Ketsji/KX_PhysicsPropertiesobsolete.h @@ -58,5 +58,4 @@ struct KX_MaterialProps { bool m_fh_normal; // Should the object slide off slopes? }; -#endif //__KX_PHYSICSPROPERTIESOBSOLETE_H__ - +#endif /* __KX_PHYSICSPROPERTIESOBSOLETE_H__ */ diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp index 85c88337d60..465e91ffb32 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.cpp +++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp @@ -102,7 +102,7 @@ KX_PolyProxy::~KX_PolyProxy() // stuff for cvalue related things CValue* KX_PolyProxy::Calc(VALUE_OPERATOR, CValue *) { return NULL;} -CValue* KX_PolyProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;} +CValue* KX_PolyProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;} STR_String sPolyName="polygone"; const STR_String & KX_PolyProxy::GetText() {return sPolyName;}; double KX_PolyProxy::GetNumber() { return -1;} @@ -112,54 +112,54 @@ CValue* KX_PolyProxy::GetReplica() { return NULL;} // stuff for python integration -PyObject* KX_PolyProxy::pyattr_get_material_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_PolyProxy::pyattr_get_material_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_PolyProxy* self= static_cast(self_v); + KX_PolyProxy* self = static_cast(self_v); return self->PygetMaterialName(); } -PyObject* KX_PolyProxy::pyattr_get_texture_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_PolyProxy::pyattr_get_texture_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_PolyProxy* self= static_cast(self_v); + KX_PolyProxy* self = static_cast(self_v); return self->PygetTextureName(); } -PyObject* KX_PolyProxy::pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_PolyProxy::pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_PolyProxy* self= static_cast(self_v); + KX_PolyProxy* self = static_cast(self_v); return self->PygetMaterial(); } -PyObject* KX_PolyProxy::pyattr_get_material_id(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_PolyProxy::pyattr_get_material_id(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_PolyProxy* self= static_cast(self_v); + KX_PolyProxy* self = static_cast(self_v); return self->PygetMaterialIndex(); } -PyObject* KX_PolyProxy::pyattr_get_v1(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_PolyProxy::pyattr_get_v1(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_PolyProxy* self= static_cast(self_v); + KX_PolyProxy* self = static_cast(self_v); return PyLong_FromSsize_t(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 0)); } -PyObject* KX_PolyProxy::pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_PolyProxy::pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_PolyProxy* self= static_cast(self_v); + KX_PolyProxy* self = static_cast(self_v); return PyLong_FromSsize_t(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 1)); } -PyObject* KX_PolyProxy::pyattr_get_v3(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_PolyProxy::pyattr_get_v3(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_PolyProxy* self= static_cast(self_v); + KX_PolyProxy* self = static_cast(self_v); return PyLong_FromSsize_t(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 2)); } -PyObject* KX_PolyProxy::pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_PolyProxy::pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_PolyProxy* self= static_cast(self_v); + KX_PolyProxy* self = static_cast(self_v); if (3 < self->m_polygon->VertexCount()) { @@ -168,15 +168,15 @@ PyObject* KX_PolyProxy::pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *at return PyLong_FromSsize_t(0); } -PyObject* KX_PolyProxy::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_PolyProxy::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_PolyProxy* self= static_cast(self_v); + KX_PolyProxy* self = static_cast(self_v); return self->PyisVisible(); } -PyObject* KX_PolyProxy::pyattr_get_collide(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_PolyProxy::pyattr_get_collide(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_PolyProxy* self= static_cast(self_v); + KX_PolyProxy* self = static_cast(self_v); return self->PyisCollider(); } diff --git a/source/gameengine/Ketsji/KX_PolyProxy.h b/source/gameengine/Ketsji/KX_PolyProxy.h index 83c3bff0ee2..f02aa90998e 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.h +++ b/source/gameengine/Ketsji/KX_PolyProxy.h @@ -57,16 +57,16 @@ public: // stuff for python integration - static PyObject* pyattr_get_material_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_texture_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_material_id(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_v1(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_v3(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_collide(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_material_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_texture_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_material_id(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_v1(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_v3(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_collide(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterialIndex) KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getNumVertex) @@ -80,7 +80,6 @@ public: }; -#endif // WITH_PYTHON - -#endif //__KX_POLYPROXY +#endif /* WITH_PYTHON */ +#endif /* __KX_POLYPROXY */ diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index 2e39190f4f9..36c94dc997b 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -143,7 +143,7 @@ bool KX_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingI { PyObject *pyRasty = PyCapsule_New((void*)rasty, KX_POLYGONMATERIAL_CAPSULE_ID, NULL); /* new reference */ PyObject *pyCachingInfo = PyCapsule_New((void*) &cachingInfo, KX_POLYGONMATERIAL_CAPSULE_ID, NULL); /* new reference */ - PyObject *ret = PyObject_CallMethod(m_pymaterial, (char *)"activate", (char *)"(NNO)", pyRasty, pyCachingInfo, (PyObject*) this->m_proxy); + PyObject *ret = PyObject_CallMethod(m_pymaterial, (char *)"activate", (char *)"(NNO)", pyRasty, pyCachingInfo, (PyObject *) this->m_proxy); if (ret) { bool value = PyLong_AsSsize_t(ret); @@ -252,7 +252,7 @@ PyAttributeDef KX_PolygonMaterial::Attributes[] = { KX_PYATTRIBUTE_INT_RW("tile", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tile), KX_PYATTRIBUTE_INT_RW("tilexrep", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tilexrep), KX_PYATTRIBUTE_INT_RW("tileyrep", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tileyrep), - KX_PYATTRIBUTE_INT_RW("drawingmode", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_drawingmode), + KX_PYATTRIBUTE_INT_RW("drawingmode", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_drawingmode), //KX_PYATTRIBUTE_INT_RW("lightlayer", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_lightlayer), KX_PYATTRIBUTE_BOOL_RW("transparent", KX_PolygonMaterial, m_alpha), @@ -262,7 +262,7 @@ PyAttributeDef KX_PolygonMaterial::Attributes[] = { KX_PYATTRIBUTE_FLOAT_RW("specularity", 0.0f, 1000.0f, KX_PolygonMaterial, m_specularity), KX_PYATTRIBUTE_RW_FUNCTION("diffuse", KX_PolygonMaterial, pyattr_get_diffuse, pyattr_set_diffuse), - KX_PYATTRIBUTE_RW_FUNCTION("specular",KX_PolygonMaterial, pyattr_get_specular, pyattr_set_specular), + KX_PYATTRIBUTE_RW_FUNCTION("specular",KX_PolygonMaterial, pyattr_get_specular, pyattr_set_specular), KX_PYATTRIBUTE_RO_FUNCTION("tface", KX_PolygonMaterial, pyattr_get_tface), /* How the heck is this even useful??? - Campbell */ KX_PYATTRIBUTE_RO_FUNCTION("gl_texture", KX_PolygonMaterial, pyattr_get_gl_texture), /* could be called 'bindcode' */ @@ -355,28 +355,28 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, activate, "activate(rasty, cachingInfo)") return NULL; } -PyObject* KX_PolygonMaterial::pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_PolygonMaterial::pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_PolygonMaterial* self= static_cast(self_v); + KX_PolygonMaterial* self = static_cast(self_v); return PyUnicode_From_STR_String(self->m_texturename); } -PyObject* KX_PolygonMaterial::pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_PolygonMaterial::pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_PolygonMaterial* self= static_cast(self_v); + KX_PolygonMaterial* self = static_cast(self_v); return PyUnicode_From_STR_String(self->m_materialname); } /* this does not seem useful */ -PyObject* KX_PolygonMaterial::pyattr_get_tface(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_PolygonMaterial::pyattr_get_tface(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_PolygonMaterial* self= static_cast(self_v); + KX_PolygonMaterial* self = static_cast(self_v); return PyCapsule_New(&self->m_tface, KX_POLYGONMATERIAL_CAPSULE_ID, NULL); } -PyObject* KX_PolygonMaterial::pyattr_get_gl_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_PolygonMaterial::pyattr_get_gl_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_PolygonMaterial* self= static_cast(self_v); + KX_PolygonMaterial* self = static_cast(self_v); int bindcode= 0; if (self->m_tface.tpage) bindcode= self->m_tface.tpage->bindcode; @@ -385,15 +385,15 @@ PyObject* KX_PolygonMaterial::pyattr_get_gl_texture(void *self_v, const KX_PYATT } -PyObject* KX_PolygonMaterial::pyattr_get_diffuse(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_PolygonMaterial::pyattr_get_diffuse(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_PolygonMaterial* self= static_cast(self_v); + KX_PolygonMaterial* self = static_cast(self_v); return PyObjectFrom(self->m_diffuse); } int KX_PolygonMaterial::pyattr_set_diffuse(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_PolygonMaterial* self= static_cast(self_v); + KX_PolygonMaterial* self = static_cast(self_v); MT_Vector3 vec; if (!PyVecTo(value, vec)) @@ -403,15 +403,15 @@ int KX_PolygonMaterial::pyattr_set_diffuse(void *self_v, const KX_PYATTRIBUTE_DE return PY_SET_ATTR_SUCCESS; } -PyObject* KX_PolygonMaterial::pyattr_get_specular(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_PolygonMaterial::pyattr_get_specular(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_PolygonMaterial* self= static_cast(self_v); + KX_PolygonMaterial* self = static_cast(self_v); return PyObjectFrom(self->m_specular); } int KX_PolygonMaterial::pyattr_set_specular(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_PolygonMaterial* self= static_cast(self_v); + KX_PolygonMaterial* self = static_cast(self_v); MT_Vector3 vec; if (!PyVecTo(value, vec)) diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index f7ad3973212..89bfb4ff9fb 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -137,7 +137,7 @@ public: KX_PYMETHOD_DOC(KX_PolygonMaterial, setCustomMaterial); KX_PYMETHOD_DOC(KX_PolygonMaterial, loadProgram); - virtual PyObject* py_repr(void) { return PyUnicode_FromString(m_material ? ((ID *)m_material)->name+2 : ""); } + virtual PyObject *py_repr(void) { return PyUnicode_FromString(m_material ? ((ID *)m_material)->name+2 : ""); } static PyObject* pyattr_get_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_material(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); @@ -145,13 +145,12 @@ public: static PyObject* pyattr_get_tface(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_gl_texture(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_diffuse(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_diffuse(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_diffuse(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); - static PyObject* pyattr_get_specular(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_specular(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_specular(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); #endif }; -#endif // __KX_POLYGONMATERIAL_H__ - +#endif /* __KX_POLYGONMATERIAL_H__ */ diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index 556d451cf66..4475ac8ec96 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -33,12 +33,15 @@ #include "PHY_IPhysicsEnvironment.h" #include "KX_ConstraintWrapper.h" #include "KX_VehicleWrapper.h" +#include "KX_CharacterWrapper.h" #include "KX_PhysicsObjectWrapper.h" #include "PHY_IPhysicsController.h" #include "PHY_IVehicle.h" #include "PHY_DynamicTypes.h" #include "MT_Matrix3x3.h" +#include "KX_GameObject.h" // ConvertPythonToGameObject() + #include "PyObjectPlus.h" #ifdef USE_BULLET @@ -81,6 +84,7 @@ static char gPySetSolverType__doc__[] = "setSolverType(int solverType) Very expe static char gPyCreateConstraint__doc__[] = "createConstraint(ob1,ob2,float restLength,float restitution,float damping)"; static char gPyGetVehicleConstraint__doc__[] = "getVehicleConstraint(int constraintId)"; +static char gPyGetCharacter__doc__[] = "getCharacter(KX_GameObject obj)"; static char gPyRemoveConstraint__doc__[] = "removeConstraint(int constraintId)"; static char gPyGetAppliedImpulse__doc__[] = "getAppliedImpulse(int constraintId)"; @@ -89,9 +93,9 @@ static char gPyGetAppliedImpulse__doc__[] = "getAppliedImpulse(int constraintId) -static PyObject* gPySetGravity(PyObject* self, - PyObject* args, - PyObject* kwds) +static PyObject *gPySetGravity(PyObject *self, + PyObject *args, + PyObject *kwds) { float x,y,z; if (PyArg_ParseTuple(args,"fff",&x,&y,&z)) @@ -106,9 +110,9 @@ static PyObject* gPySetGravity(PyObject* self, Py_RETURN_NONE; } -static PyObject* gPySetDebugMode(PyObject* self, - PyObject* args, - PyObject* kwds) +static PyObject *gPySetDebugMode(PyObject *self, + PyObject *args, + PyObject *kwds) { int mode; if (PyArg_ParseTuple(args,"i",&mode)) @@ -129,9 +133,9 @@ static PyObject* gPySetDebugMode(PyObject* self, -static PyObject* gPySetNumTimeSubSteps(PyObject* self, - PyObject* args, - PyObject* kwds) +static PyObject *gPySetNumTimeSubSteps(PyObject *self, + PyObject *args, + PyObject *kwds) { int substep; if (PyArg_ParseTuple(args,"i",&substep)) @@ -148,9 +152,9 @@ static PyObject* gPySetNumTimeSubSteps(PyObject* self, } -static PyObject* gPySetNumIterations(PyObject* self, - PyObject* args, - PyObject* kwds) +static PyObject *gPySetNumIterations(PyObject *self, + PyObject *args, + PyObject *kwds) { int iter; if (PyArg_ParseTuple(args,"i",&iter)) @@ -167,9 +171,9 @@ static PyObject* gPySetNumIterations(PyObject* self, } -static PyObject* gPySetDeactivationTime(PyObject* self, - PyObject* args, - PyObject* kwds) +static PyObject *gPySetDeactivationTime(PyObject *self, + PyObject *args, + PyObject *kwds) { float deactive_time; if (PyArg_ParseTuple(args,"f",&deactive_time)) @@ -186,9 +190,9 @@ static PyObject* gPySetDeactivationTime(PyObject* self, } -static PyObject* gPySetDeactivationLinearTreshold(PyObject* self, - PyObject* args, - PyObject* kwds) +static PyObject *gPySetDeactivationLinearTreshold(PyObject *self, + PyObject *args, + PyObject *kwds) { float linearDeactivationTreshold; if (PyArg_ParseTuple(args,"f",&linearDeactivationTreshold)) @@ -205,9 +209,9 @@ static PyObject* gPySetDeactivationLinearTreshold(PyObject* self, } -static PyObject* gPySetDeactivationAngularTreshold(PyObject* self, - PyObject* args, - PyObject* kwds) +static PyObject *gPySetDeactivationAngularTreshold(PyObject *self, + PyObject *args, + PyObject *kwds) { float angularDeactivationTreshold; if (PyArg_ParseTuple(args,"f",&angularDeactivationTreshold)) @@ -223,9 +227,9 @@ static PyObject* gPySetDeactivationAngularTreshold(PyObject* self, Py_RETURN_NONE; } -static PyObject* gPySetContactBreakingTreshold(PyObject* self, - PyObject* args, - PyObject* kwds) +static PyObject *gPySetContactBreakingTreshold(PyObject *self, + PyObject *args, + PyObject *kwds) { float contactBreakingTreshold; if (PyArg_ParseTuple(args,"f",&contactBreakingTreshold)) @@ -242,9 +246,9 @@ static PyObject* gPySetContactBreakingTreshold(PyObject* self, } -static PyObject* gPySetCcdMode(PyObject* self, - PyObject* args, - PyObject* kwds) +static PyObject *gPySetCcdMode(PyObject *self, + PyObject *args, + PyObject *kwds) { float ccdMode; if (PyArg_ParseTuple(args,"f",&ccdMode)) @@ -260,9 +264,9 @@ static PyObject* gPySetCcdMode(PyObject* self, Py_RETURN_NONE; } -static PyObject* gPySetSorConstant(PyObject* self, - PyObject* args, - PyObject* kwds) +static PyObject *gPySetSorConstant(PyObject *self, + PyObject *args, + PyObject *kwds) { float sor; if (PyArg_ParseTuple(args,"f",&sor)) @@ -278,9 +282,9 @@ static PyObject* gPySetSorConstant(PyObject* self, Py_RETURN_NONE; } -static PyObject* gPySetSolverTau(PyObject* self, - PyObject* args, - PyObject* kwds) +static PyObject *gPySetSolverTau(PyObject *self, + PyObject *args, + PyObject *kwds) { float tau; if (PyArg_ParseTuple(args,"f",&tau)) @@ -297,9 +301,9 @@ static PyObject* gPySetSolverTau(PyObject* self, } -static PyObject* gPySetSolverDamping(PyObject* self, - PyObject* args, - PyObject* kwds) +static PyObject *gPySetSolverDamping(PyObject *self, + PyObject *args, + PyObject *kwds) { float damping; if (PyArg_ParseTuple(args,"f",&damping)) @@ -315,9 +319,9 @@ static PyObject* gPySetSolverDamping(PyObject* self, Py_RETURN_NONE; } -static PyObject* gPySetLinearAirDamping(PyObject* self, - PyObject* args, - PyObject* kwds) +static PyObject *gPySetLinearAirDamping(PyObject *self, + PyObject *args, + PyObject *kwds) { float damping; if (PyArg_ParseTuple(args,"f",&damping)) @@ -334,9 +338,9 @@ static PyObject* gPySetLinearAirDamping(PyObject* self, } -static PyObject* gPySetUseEpa(PyObject* self, - PyObject* args, - PyObject* kwds) +static PyObject *gPySetUseEpa(PyObject *self, + PyObject *args, + PyObject *kwds) { int epa; if (PyArg_ParseTuple(args,"i",&epa)) @@ -351,9 +355,9 @@ static PyObject* gPySetUseEpa(PyObject* self, } Py_RETURN_NONE; } -static PyObject* gPySetSolverType(PyObject* self, - PyObject* args, - PyObject* kwds) +static PyObject *gPySetSolverType(PyObject *self, + PyObject *args, + PyObject *kwds) { int solverType; if (PyArg_ParseTuple(args,"i",&solverType)) @@ -371,9 +375,9 @@ static PyObject* gPySetSolverType(PyObject* self, -static PyObject* gPyGetVehicleConstraint(PyObject* self, - PyObject* args, - PyObject* kwds) +static PyObject *gPyGetVehicleConstraint(PyObject *self, + PyObject *args, + PyObject *kwds) { #if defined(_WIN64) __int64 constraintid; @@ -402,10 +406,37 @@ static PyObject* gPyGetVehicleConstraint(PyObject* self, Py_RETURN_NONE; } +static PyObject* gPyGetCharacter(PyObject* self, + PyObject* args, + PyObject* kwds) +{ + PyObject* pyob; + KX_GameObject *ob; -static PyObject* gPyCreateConstraint(PyObject* self, - PyObject* args, - PyObject* kwds) + if (!PyArg_ParseTuple(args,"O", &pyob)) + return NULL; + + if (!ConvertPythonToGameObject(pyob, &ob, false, "bge.constraints.getCharacter(value)")) + return NULL; + + if (PHY_GetActiveEnvironment()) + { + + PHY_ICharacter* character= PHY_GetActiveEnvironment()->getCharacterController(ob); + if (character) + { + KX_CharacterWrapper* pyWrapper = new KX_CharacterWrapper(character); + return pyWrapper->NewProxy(true); + } + + } + + Py_RETURN_NONE; +} + +static PyObject *gPyCreateConstraint(PyObject *self, + PyObject *args, + PyObject *kwds) { /* FIXME - physicsid is a long being cast to a pointer, should at least use PyCapsule */ #if defined(_WIN64) @@ -435,7 +466,7 @@ static PyObject* gPyCreateConstraint(PyObject* self, #else success = PyArg_ParseTuple(args,"llifff",&physicsid,&physicsid2,&constrainttype, &pivotX,&pivotY,&pivotZ); -#endif +#endif } else if (len == 9) { @@ -521,9 +552,9 @@ static PyObject* gPyCreateConstraint(PyObject* self, -static PyObject* gPyGetAppliedImpulse(PyObject* self, - PyObject* args, - PyObject* kwds) +static PyObject *gPyGetAppliedImpulse(PyObject *self, + PyObject *args, + PyObject *kwds) { float appliedImpulse = 0.f; @@ -548,9 +579,9 @@ static PyObject* gPyGetAppliedImpulse(PyObject* self, } -static PyObject* gPyRemoveConstraint(PyObject* self, - PyObject* args, - PyObject* kwds) +static PyObject *gPyRemoveConstraint(PyObject *self, + PyObject *args, + PyObject *kwds) { #if defined(_WIN64) __int64 constraintid; @@ -572,7 +603,7 @@ static PyObject* gPyRemoveConstraint(PyObject* self, Py_RETURN_NONE; } -static PyObject* gPyExportBulletFile(PyObject*, PyObject* args) +static PyObject *gPyExportBulletFile(PyObject *, PyObject *args) { char* filename; if (!PyArg_ParseTuple(args,"s:exportBulletFile",&filename)) @@ -631,6 +662,9 @@ static struct PyMethodDef physicsconstraints_methods[] = { {"getVehicleConstraint",(PyCFunction) gPyGetVehicleConstraint, METH_VARARGS, (const char *)gPyGetVehicleConstraint__doc__}, + {"getCharacter",(PyCFunction) gPyGetCharacter, + METH_VARARGS, (const char *)gPyGetCharacter__doc__}, + {"removeConstraint",(PyCFunction) gPyRemoveConstraint, METH_VARARGS, (const char *)gPyRemoveConstraint__doc__}, {"getAppliedImpulse",(PyCFunction) gPyGetAppliedImpulse, @@ -655,13 +689,13 @@ static struct PyModuleDef PhysicsConstraints_module_def = { 0, /* m_free */ }; -PyObject* initPythonConstraintBinding() +PyObject *initPythonConstraintBinding() { - PyObject* ErrorObject; - PyObject* m; - PyObject* d; - PyObject* item; + PyObject *ErrorObject; + PyObject *m; + PyObject *d; + PyObject *item; /* Use existing module where possible * be careful not to init any runtime vars after this */ @@ -716,10 +750,11 @@ PyObject* initPythonConstraintBinding() return d; } - -void KX_RemovePythonConstraintBinding() +#if 0 +static void KX_RemovePythonConstraintBinding() { } +#endif void PHY_SetActiveEnvironment(class PHY_IPhysicsEnvironment* env) { diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.h b/source/gameengine/Ketsji/KX_PyConstraintBinding.h index 69a6e333cee..b4a520ce71b 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.h +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.h @@ -39,7 +39,6 @@ PyObject* initPythonConstraintBinding(); void PHY_SetActiveEnvironment(class PHY_IPhysicsEnvironment* env); PHY_IPhysicsEnvironment* PHY_GetActiveEnvironment(); -#endif // WITH_PYTHON - -#endif //__KX_PYCONSTRAINTBINDING_H__ +#endif /* WITH_PYTHON */ +#endif /* __KX_PYCONSTRAINTBINDING_H__ */ diff --git a/source/gameengine/Ketsji/KX_PyMath.cpp b/source/gameengine/Ketsji/KX_PyMath.cpp index f459b806d2f..804e8de2ad1 100644 --- a/source/gameengine/Ketsji/KX_PyMath.cpp +++ b/source/gameengine/Ketsji/KX_PyMath.cpp @@ -31,9 +31,9 @@ */ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable : 4786) -#endif //WIN32 +#ifdef _MSC_VER +# pragma warning (disable:4786) +#endif #ifdef WITH_PYTHON @@ -47,7 +47,7 @@ #include "KX_Python.h" #include "KX_PyMath.h" -bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &rot, const char *error_prefix) +bool PyOrientationTo(PyObject *pyval, MT_Matrix3x3 &rot, const char *error_prefix) { int size= PySequence_Size(pyval); @@ -80,22 +80,22 @@ bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &rot, const char *error_prefi return false; } -bool PyQuatTo(PyObject* pyval, MT_Quaternion &qrot) +bool PyQuatTo(PyObject *pyval, MT_Quaternion &qrot) { if (!PyVecTo(pyval, qrot)) return false; /* annoying!, Blender/Mathutils have the W axis first! */ - MT_Scalar w= qrot[0]; /* from python, this is actually the W */ - qrot[0]= qrot[1]; - qrot[1]= qrot[2]; - qrot[2]= qrot[3]; - qrot[3]= w; + MT_Scalar w = qrot[0]; /* from python, this is actually the W */ + qrot[0] = qrot[1]; + qrot[1] = qrot[2]; + qrot[2] = qrot[3]; + qrot[3] = w; return true; } -PyObject* PyObjectFrom(const MT_Matrix4x4 &mat) +PyObject *PyObjectFrom(const MT_Matrix4x4 &mat) { #ifdef USE_MATHUTILS float fmat[16]; @@ -119,7 +119,7 @@ PyObject* PyObjectFrom(const MT_Matrix4x4 &mat) #endif } -PyObject* PyObjectFrom(const MT_Matrix3x3 &mat) +PyObject *PyObjectFrom(const MT_Matrix3x3 &mat) { #ifdef USE_MATHUTILS float fmat[9]; @@ -143,7 +143,7 @@ PyObject* PyObjectFrom(const MT_Matrix3x3 &mat) } #ifdef USE_MATHUTILS -PyObject* PyObjectFrom(const MT_Quaternion &qrot) +PyObject *PyObjectFrom(const MT_Quaternion &qrot) { /* NOTE, were re-ordering here for Mathutils compat */ float fvec[4]; @@ -152,7 +152,7 @@ PyObject* PyObjectFrom(const MT_Quaternion &qrot) } #endif -PyObject* PyObjectFrom(const MT_Tuple4 &vec) +PyObject *PyObjectFrom(const MT_Tuple4 &vec) { #ifdef USE_MATHUTILS float fvec[4]; @@ -168,7 +168,7 @@ PyObject* PyObjectFrom(const MT_Tuple4 &vec) #endif } -PyObject* PyObjectFrom(const MT_Tuple3 &vec) +PyObject *PyObjectFrom(const MT_Tuple3 &vec) { #ifdef USE_MATHUTILS float fvec[3]; @@ -180,10 +180,10 @@ PyObject* PyObjectFrom(const MT_Tuple3 &vec) PyList_SET_ITEM(list, 1, PyFloat_FromDouble(vec[1])); PyList_SET_ITEM(list, 2, PyFloat_FromDouble(vec[2])); return list; -#endif +#endif } -PyObject* PyObjectFrom(const MT_Tuple2 &vec) +PyObject *PyObjectFrom(const MT_Tuple2 &vec) { #ifdef USE_MATHUTILS float fvec[2]; diff --git a/source/gameengine/Ketsji/KX_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h index aec871d7700..159506946e8 100644 --- a/source/gameengine/Ketsji/KX_PyMath.h +++ b/source/gameengine/Ketsji/KX_PyMath.h @@ -61,7 +61,7 @@ inline unsigned int Size(const MT_Tuple4&) { return 4; } * Converts the given python matrix (column-major) to an MT class (row-major). */ template -bool PyMatTo(PyObject* pymat, T& mat) +bool PyMatTo(PyObject *pymat, T& mat) { bool noerror = true; mat.setIdentity(); @@ -133,7 +133,7 @@ bool PyMatTo(PyObject* pymat, T& mat) * Converts a python sequence to a MT class. */ template -bool PyVecTo(PyObject* pyval, T& vec) +bool PyVecTo(PyObject *pyval, T& vec) { #ifdef USE_MATHUTILS /* no need for BaseMath_ReadCallback() here, reading the sequences will do this */ @@ -235,42 +235,42 @@ bool PyVecTo(PyObject* pyval, T& vec) } -bool PyQuatTo(PyObject* pyval, MT_Quaternion &qrot); +bool PyQuatTo(PyObject *pyval, MT_Quaternion &qrot); -bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &mat, const char *error_prefix); +bool PyOrientationTo(PyObject *pyval, MT_Matrix3x3 &mat, const char *error_prefix); /** * Converts an MT_Matrix4x4 to a python object. */ -PyObject* PyObjectFrom(const MT_Matrix4x4 &mat); +PyObject *PyObjectFrom(const MT_Matrix4x4 &mat); /** * Converts an MT_Matrix3x3 to a python object. */ -PyObject* PyObjectFrom(const MT_Matrix3x3 &mat); +PyObject *PyObjectFrom(const MT_Matrix3x3 &mat); /** * Converts an MT_Tuple2 to a python object. */ -PyObject* PyObjectFrom(const MT_Tuple2 &vec); +PyObject *PyObjectFrom(const MT_Tuple2 &vec); /** * Converts an MT_Tuple3 to a python object */ -PyObject* PyObjectFrom(const MT_Tuple3 &vec); +PyObject *PyObjectFrom(const MT_Tuple3 &vec); #ifdef USE_MATHUTILS /** * Converts an MT_Quaternion to a python object. */ -PyObject* PyObjectFrom(const MT_Quaternion &qrot); +PyObject *PyObjectFrom(const MT_Quaternion &qrot); #endif /** * Converts an MT_Tuple4 to a python object. */ -PyObject* PyObjectFrom(const MT_Tuple4 &pos); +PyObject *PyObjectFrom(const MT_Tuple4 &pos); #endif -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 7d29a20d1a2..7f6655861f1 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -30,54 +30,48 @@ * \ingroup ketsji */ - #include "GL/glew.h" -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable : 4786) -#endif //WIN32 +#ifdef _MSC_VER +# pragma warning (disable:4786) +#endif #ifdef WITH_PYTHON - -#ifdef _POSIX_C_SOURCE -#undef _POSIX_C_SOURCE -#endif - -#ifdef _XOPEN_SOURCE -#undef _XOPEN_SOURCE -#endif - -#if defined(__sun) || defined(sun) -#if defined(_XPG4) -#undef _XPG4 -#endif -#endif - -#include +# ifdef _POSIX_C_SOURCE +# undef _POSIX_C_SOURCE +# endif +# ifdef _XOPEN_SOURCE +# undef _XOPEN_SOURCE +# endif +# if defined(__sun) || defined(sun) +# if defined(_XPG4) +# undef _XPG4 +# endif +# endif +# include extern "C" { - #include "bpy_internal_import.h" /* from the blender python api, but we want to import text too! */ - #include "py_capi_utils.h" - #include "mathutils.h" // 'mathutils' module copied here so the blenderlayer can use. - #include "bgl.h" - #include "blf_py_api.h" + # include "bpy_internal_import.h" /* from the blender python api, but we want to import text too! */ + # include "py_capi_utils.h" + # include "mathutils.h" // 'mathutils' module copied here so the blenderlayer can use. + # include "bgl.h" + # include "blf_py_api.h" - #include "marshal.h" /* python header for loading/saving dicts */ + # include "marshal.h" /* python header for loading/saving dicts */ } - #include "AUD_PyInit.h" -#endif +#endif /* WITH_PYTHON */ #include "KX_PythonInit.h" // directory header for py function getBlendFileList #ifndef WIN32 - #include - #include +# include +# include #else - #include - #include "BLI_winstuff.h" +# include +# include "BLI_winstuff.h" #endif //python physics binding @@ -186,8 +180,8 @@ void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,cons gp_Rasterizer->DrawDebugLine(from,to,color); } -void KX_RasterizerDrawDebugCircle(const MT_Vector3& center, const MT_Scalar radius, const MT_Vector3& color, - const MT_Vector3& normal, int nsector) +void KX_RasterizerDrawDebugCircle(const MT_Vector3& center, const MT_Scalar radius, const MT_Vector3& color, + const MT_Vector3& normal, int nsector) { if (gp_Rasterizer) gp_Rasterizer->DrawDebugCircle(center, radius, color, normal, nsector); @@ -210,15 +204,15 @@ static PyObject *gp_OrigPythonSysModules= NULL; #include "SCA_PythonController.h" // List of methods defined in the module -static PyObject* ErrorObject; +static PyObject *ErrorObject; static const char *gPyGetRandomFloat_doc="getRandomFloat returns a random floating point value in the range [0..1]"; -static PyObject* gPyGetRandomFloat(PyObject*) +static PyObject *gPyGetRandomFloat(PyObject *) { return PyFloat_FromDouble(MT_random()); } -static PyObject* gPySetGravity(PyObject*, PyObject* value) +static PyObject *gPySetGravity(PyObject *, PyObject *value) { MT_Vector3 vec; if (!PyVecTo(value, vec)) @@ -240,7 +234,7 @@ file to make a full path name (doesn't change during the game, even if you load\ other .blend).\n\ The function also converts the directory separator to the local file system format."; -static PyObject* gPyExpandPath(PyObject*, PyObject* args) +static PyObject *gPyExpandPath(PyObject *, PyObject *args) { char expanded[FILE_MAX]; char* filename; @@ -257,7 +251,7 @@ static char gPyStartGame_doc[] = "startGame(blend)\n\ Loads the blend file"; -static PyObject* gPyStartGame(PyObject*, PyObject* args) +static PyObject *gPyStartGame(PyObject *, PyObject *args) { char* blendfile; @@ -274,7 +268,7 @@ static char gPyEndGame_doc[] = "endGame()\n\ Ends the current game"; -static PyObject* gPyEndGame(PyObject*) +static PyObject *gPyEndGame(PyObject *) { gp_KetsjiEngine->RequestExit(KX_EXIT_REQUEST_QUIT_GAME); @@ -287,7 +281,7 @@ static char gPyRestartGame_doc[] = "restartGame()\n\ Restarts the current game by reloading the .blend file"; -static PyObject* gPyRestartGame(PyObject*) +static PyObject *gPyRestartGame(PyObject *) { gp_KetsjiEngine->RequestExit(KX_EXIT_REQUEST_RESTART_GAME); gp_KetsjiEngine->SetNameNextGame(gp_GamePythonPath); @@ -299,7 +293,7 @@ static char gPySaveGlobalDict_doc[] = "saveGlobalDict()\n" "Saves bge.logic.globalDict to a file"; -static PyObject* gPySaveGlobalDict(PyObject*) +static PyObject *gPySaveGlobalDict(PyObject *) { char marshal_path[512]; char *marshal_buffer = NULL; @@ -336,7 +330,7 @@ static char gPyLoadGlobalDict_doc[] = "LoadGlobalDict()\n" "Loads bge.logic.globalDict from a file"; -static PyObject* gPyLoadGlobalDict(PyObject*) +static PyObject *gPyLoadGlobalDict(PyObject *) { char marshal_path[512]; char *marshal_buffer = NULL; @@ -381,7 +375,7 @@ body = Message body\ to = Name of object to send the message to\ from = Name of object to send the string from"; -static PyObject* gPySendMessage(PyObject*, PyObject* args) +static PyObject *gPySendMessage(PyObject *, PyObject *args) { char* subject; char* body = (char *)""; @@ -397,9 +391,9 @@ static PyObject* gPySendMessage(PyObject*, PyObject* args) } // this gets a pointer to an array filled with floats -static PyObject* gPyGetSpectrum(PyObject*) +static PyObject *gPyGetSpectrum(PyObject *) { - PyObject* resultlist = PyList_New(512); + PyObject *resultlist = PyList_New(512); for (int index = 0; index < 512; index++) { @@ -409,7 +403,7 @@ static PyObject* gPyGetSpectrum(PyObject*) return resultlist; } -static PyObject* gPySetLogicTicRate(PyObject*, PyObject* args) +static PyObject *gPySetLogicTicRate(PyObject *, PyObject *args) { float ticrate; if (!PyArg_ParseTuple(args, "f:setLogicTicRate", &ticrate)) @@ -419,12 +413,12 @@ static PyObject* gPySetLogicTicRate(PyObject*, PyObject* args) Py_RETURN_NONE; } -static PyObject* gPyGetLogicTicRate(PyObject*) +static PyObject *gPyGetLogicTicRate(PyObject *) { return PyFloat_FromDouble(KX_KetsjiEngine::GetTicRate()); } -static PyObject* gPySetExitKey(PyObject*, PyObject* args) +static PyObject *gPySetExitKey(PyObject *, PyObject *args) { short exitkey; if (!PyArg_ParseTuple(args, "h:setExitKey", &exitkey)) @@ -433,12 +427,12 @@ static PyObject* gPySetExitKey(PyObject*, PyObject* args) Py_RETURN_NONE; } -static PyObject* gPyGetExitKey(PyObject*) +static PyObject *gPyGetExitKey(PyObject *) { return PyLong_FromSsize_t(KX_KetsjiEngine::GetExitKey()); } -static PyObject* gPySetMaxLogicFrame(PyObject*, PyObject* args) +static PyObject *gPySetMaxLogicFrame(PyObject *, PyObject *args) { int frame; if (!PyArg_ParseTuple(args, "i:setMaxLogicFrame", &frame)) @@ -448,12 +442,12 @@ static PyObject* gPySetMaxLogicFrame(PyObject*, PyObject* args) Py_RETURN_NONE; } -static PyObject* gPyGetMaxLogicFrame(PyObject*) +static PyObject *gPyGetMaxLogicFrame(PyObject *) { return PyLong_FromSsize_t(KX_KetsjiEngine::GetMaxLogicFrame()); } -static PyObject* gPySetMaxPhysicsFrame(PyObject*, PyObject* args) +static PyObject *gPySetMaxPhysicsFrame(PyObject *, PyObject *args) { int frame; if (!PyArg_ParseTuple(args, "i:setMaxPhysicsFrame", &frame)) @@ -463,12 +457,12 @@ static PyObject* gPySetMaxPhysicsFrame(PyObject*, PyObject* args) Py_RETURN_NONE; } -static PyObject* gPyGetMaxPhysicsFrame(PyObject*) +static PyObject *gPyGetMaxPhysicsFrame(PyObject *) { return PyLong_FromSsize_t(KX_KetsjiEngine::GetMaxPhysicsFrame()); } -static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args) +static PyObject *gPySetPhysicsTicRate(PyObject *, PyObject *args) { float ticrate; if (!PyArg_ParseTuple(args, "f:setPhysicsTicRate", &ticrate)) @@ -478,7 +472,7 @@ static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args) Py_RETURN_NONE; } #if 0 // unused -static PyObject* gPySetPhysicsDebug(PyObject*, PyObject* args) +static PyObject *gPySetPhysicsDebug(PyObject *, PyObject *args) { int debugMode; if (!PyArg_ParseTuple(args, "i:setPhysicsDebug", &debugMode)) @@ -490,21 +484,21 @@ static PyObject* gPySetPhysicsDebug(PyObject*, PyObject* args) #endif -static PyObject* gPyGetPhysicsTicRate(PyObject*) +static PyObject *gPyGetPhysicsTicRate(PyObject *) { return PyFloat_FromDouble(PHY_GetActiveEnvironment()->getFixedTimeStep()); } -static PyObject* gPyGetAverageFrameRate(PyObject*) +static PyObject *gPyGetAverageFrameRate(PyObject *) { return PyFloat_FromDouble(KX_KetsjiEngine::GetAverageFrameRate()); } -static PyObject* gPyGetBlendFileList(PyObject*, PyObject* args) +static PyObject *gPyGetBlendFileList(PyObject *, PyObject *args) { char cpath[sizeof(gp_GamePythonPath)]; char *searchpath = NULL; - PyObject* list, *value; + PyObject *list, *value; DIR *dp; struct dirent *dirp; @@ -545,7 +539,7 @@ static char gPyAddScene_doc[] = adds a scene to the game engine\n\ name = Name of the scene\n\ overlay = Overlay or underlay"; -static PyObject* gPyAddScene(PyObject*, PyObject* args) +static PyObject *gPyAddScene(PyObject *, PyObject *args) { char* name; int overlay = 1; @@ -561,7 +555,7 @@ static PyObject* gPyAddScene(PyObject*, PyObject* args) static const char *gPyGetCurrentScene_doc = "getCurrentScene()\n" "Gets a reference to the current scene.\n"; -static PyObject* gPyGetCurrentScene(PyObject* self) +static PyObject *gPyGetCurrentScene(PyObject *self) { return gp_KetsjiScene->GetProxy(); } @@ -569,10 +563,10 @@ static PyObject* gPyGetCurrentScene(PyObject* self) static const char *gPyGetSceneList_doc = "getSceneList()\n" "Return a list of converted scenes.\n"; -static PyObject* gPyGetSceneList(PyObject* self) +static PyObject *gPyGetSceneList(PyObject *self) { KX_KetsjiEngine* m_engine = KX_GetActiveEngine(); - PyObject* list; + PyObject *list; KX_SceneList* scenes = m_engine->CurrentScenes(); int numScenes = scenes->size(); int i; @@ -665,7 +659,7 @@ static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *) Py_RETURN_NONE; } -static PyObject *gLibLoad(PyObject*, PyObject* args, PyObject* kwds) +static PyObject *gLibLoad(PyObject *, PyObject *args, PyObject *kwds) { KX_Scene *kx_scene= gp_KetsjiScene; char *path; @@ -721,7 +715,7 @@ static PyObject *gLibLoad(PyObject*, PyObject* args, PyObject* kwds) Py_RETURN_FALSE; } -static PyObject *gLibNew(PyObject*, PyObject* args) +static PyObject *gLibNew(PyObject *, PyObject *args) { KX_Scene *kx_scene= gp_KetsjiScene; char *path; @@ -779,7 +773,7 @@ static PyObject *gLibNew(PyObject*, PyObject* args) Py_RETURN_NONE; } -static PyObject *gLibFree(PyObject*, PyObject* args) +static PyObject *gLibFree(PyObject *, PyObject *args) { KX_Scene *kx_scene= gp_KetsjiScene; char *path; @@ -796,7 +790,7 @@ static PyObject *gLibFree(PyObject*, PyObject* args) } } -static PyObject *gLibList(PyObject*, PyObject* args) +static PyObject *gLibList(PyObject *, PyObject *args) { vector &dynMaggie = gp_KetsjiScene->GetSceneConverter()->GetMainDynamic(); int i= 0; @@ -866,14 +860,14 @@ static struct PyMethodDef game_methods[] = { {NULL, (PyCFunction) NULL, 0, NULL } }; -static PyObject* gPyGetWindowHeight(PyObject*, PyObject* args) +static PyObject *gPyGetWindowHeight(PyObject *, PyObject *args) { return PyLong_FromSsize_t((gp_Canvas ? gp_Canvas->GetHeight() : 0)); } -static PyObject* gPyGetWindowWidth(PyObject*, PyObject* args) +static PyObject *gPyGetWindowWidth(PyObject *, PyObject *args) { return PyLong_FromSsize_t((gp_Canvas ? gp_Canvas->GetWidth() : 0)); } @@ -883,7 +877,7 @@ static PyObject* gPyGetWindowWidth(PyObject*, PyObject* args) // temporarility visibility thing, will be moved to rasterizer/renderer later bool gUseVisibilityTemp = false; -static PyObject* gPyEnableVisibility(PyObject*, PyObject* args) +static PyObject *gPyEnableVisibility(PyObject *, PyObject *args) { int visible; if (!PyArg_ParseTuple(args,"i:enableVisibility",&visible)) @@ -895,7 +889,7 @@ static PyObject* gPyEnableVisibility(PyObject*, PyObject* args) -static PyObject* gPyShowMouse(PyObject*, PyObject* args) +static PyObject *gPyShowMouse(PyObject *, PyObject *args) { int visible; if (!PyArg_ParseTuple(args,"i:showMouse",&visible)) @@ -916,7 +910,7 @@ static PyObject* gPyShowMouse(PyObject*, PyObject* args) -static PyObject* gPySetMousePosition(PyObject*, PyObject* args) +static PyObject *gPySetMousePosition(PyObject *, PyObject *args) { int x,y; if (!PyArg_ParseTuple(args,"ii:setMousePosition",&x,&y)) @@ -928,7 +922,7 @@ static PyObject* gPySetMousePosition(PyObject*, PyObject* args) Py_RETURN_NONE; } -static PyObject* gPySetEyeSeparation(PyObject*, PyObject* args) +static PyObject *gPySetEyeSeparation(PyObject *, PyObject *args) { float sep; if (!PyArg_ParseTuple(args, "f:setEyeSeparation", &sep)) @@ -944,7 +938,7 @@ static PyObject* gPySetEyeSeparation(PyObject*, PyObject* args) Py_RETURN_NONE; } -static PyObject* gPyGetEyeSeparation(PyObject*) +static PyObject *gPyGetEyeSeparation(PyObject *) { if (!gp_Rasterizer) { PyErr_SetString(PyExc_RuntimeError, "Rasterizer.getEyeSeparation(), Rasterizer not available"); @@ -954,7 +948,7 @@ static PyObject* gPyGetEyeSeparation(PyObject*) return PyFloat_FromDouble(gp_Rasterizer->GetEyeSeparation()); } -static PyObject* gPySetFocalLength(PyObject*, PyObject* args) +static PyObject *gPySetFocalLength(PyObject *, PyObject *args) { float focus; if (!PyArg_ParseTuple(args, "f:setFocalLength", &focus)) @@ -970,7 +964,7 @@ static PyObject* gPySetFocalLength(PyObject*, PyObject* args) Py_RETURN_NONE; } -static PyObject* gPyGetFocalLength(PyObject*, PyObject*, PyObject*) +static PyObject *gPyGetFocalLength(PyObject *, PyObject *, PyObject *) { if (!gp_Rasterizer) { PyErr_SetString(PyExc_RuntimeError, "Rasterizer.getFocalLength(), Rasterizer not available"); @@ -982,7 +976,7 @@ static PyObject* gPyGetFocalLength(PyObject*, PyObject*, PyObject*) Py_RETURN_NONE; } -static PyObject* gPySetBackgroundColor(PyObject*, PyObject* value) +static PyObject *gPySetBackgroundColor(PyObject *, PyObject *value) { MT_Vector4 vec; @@ -1003,7 +997,7 @@ static PyObject* gPySetBackgroundColor(PyObject*, PyObject* value) -static PyObject* gPySetMistColor(PyObject*, PyObject* value) +static PyObject *gPySetMistColor(PyObject *, PyObject *value) { MT_Vector3 vec; @@ -1013,25 +1007,25 @@ static PyObject* gPySetMistColor(PyObject*, PyObject* value) if (!gp_Rasterizer) { PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistColor(color), Rasterizer not available"); return NULL; - } + } gp_Rasterizer->SetFogColor((float)vec[0], (float)vec[1], (float)vec[2]); Py_RETURN_NONE; } -static PyObject* gPyDisableMist(PyObject*) +static PyObject *gPyDisableMist(PyObject *) { if (!gp_Rasterizer) { PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistColor(color), Rasterizer not available"); return NULL; - } + } gp_Rasterizer->DisableFog(); Py_RETURN_NONE; } -static PyObject* gPySetMistStart(PyObject*, PyObject* args) +static PyObject *gPySetMistStart(PyObject *, PyObject *args) { float miststart; @@ -1050,7 +1044,7 @@ static PyObject* gPySetMistStart(PyObject*, PyObject* args) -static PyObject* gPySetMistEnd(PyObject*, PyObject* args) +static PyObject *gPySetMistEnd(PyObject *, PyObject *args) { float mistend; @@ -1068,7 +1062,7 @@ static PyObject* gPySetMistEnd(PyObject*, PyObject* args) } -static PyObject* gPySetAmbientColor(PyObject*, PyObject* value) +static PyObject *gPySetAmbientColor(PyObject *, PyObject *value) { MT_Vector3 vec; @@ -1078,7 +1072,7 @@ static PyObject* gPySetAmbientColor(PyObject*, PyObject* value) if (!gp_Rasterizer) { PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setAmbientColor(color), Rasterizer not available"); return NULL; - } + } gp_Rasterizer->SetAmbientColor((float)vec[0], (float)vec[1], (float)vec[2]); Py_RETURN_NONE; @@ -1087,7 +1081,7 @@ static PyObject* gPySetAmbientColor(PyObject*, PyObject* value) -static PyObject* gPyMakeScreenshot(PyObject*, PyObject* args) +static PyObject *gPyMakeScreenshot(PyObject *, PyObject *args) { char* filename; if (!PyArg_ParseTuple(args,"s:makeScreenshot",&filename)) @@ -1101,7 +1095,7 @@ static PyObject* gPyMakeScreenshot(PyObject*, PyObject* args) Py_RETURN_NONE; } -static PyObject* gPyEnableMotionBlur(PyObject*, PyObject* args) +static PyObject *gPyEnableMotionBlur(PyObject *, PyObject *args) { float motionblurvalue; if (!PyArg_ParseTuple(args,"f:enableMotionBlur",&motionblurvalue)) @@ -1117,7 +1111,7 @@ static PyObject* gPyEnableMotionBlur(PyObject*, PyObject* args) Py_RETURN_NONE; } -static PyObject* gPyDisableMotionBlur(PyObject*) +static PyObject *gPyDisableMotionBlur(PyObject *) { if (!gp_Rasterizer) { PyErr_SetString(PyExc_RuntimeError, "Rasterizer.disableMotionBlur(), Rasterizer not available"); @@ -1147,9 +1141,9 @@ static int getGLSLSettingFlag(const char *setting) return -1; } -static PyObject* gPySetGLSLMaterialSetting(PyObject*, - PyObject* args, - PyObject*) +static PyObject *gPySetGLSLMaterialSetting(PyObject *, + PyObject *args, + PyObject *) { GlobalSettings *gs= gp_KetsjiEngine->GetGlobalSettings(); char *setting; @@ -1190,9 +1184,9 @@ static PyObject* gPySetGLSLMaterialSetting(PyObject*, Py_RETURN_NONE; } -static PyObject* gPyGetGLSLMaterialSetting(PyObject*, - PyObject* args, - PyObject*) +static PyObject *gPyGetGLSLMaterialSetting(PyObject *, + PyObject *args, + PyObject *) { GlobalSettings *gs= gp_KetsjiEngine->GetGlobalSettings(); char *setting; @@ -1216,9 +1210,9 @@ static PyObject* gPyGetGLSLMaterialSetting(PyObject*, #define KX_BLENDER_MULTITEX_MATERIAL 1 #define KX_BLENDER_GLSL_MATERIAL 2 -static PyObject* gPySetMaterialType(PyObject*, - PyObject* args, - PyObject*) +static PyObject *gPySetMaterialType(PyObject *, + PyObject *args, + PyObject *) { GlobalSettings *gs= gp_KetsjiEngine->GetGlobalSettings(); int type; @@ -1240,7 +1234,7 @@ static PyObject* gPySetMaterialType(PyObject*, Py_RETURN_NONE; } -static PyObject* gPyGetMaterialType(PyObject*) +static PyObject *gPyGetMaterialType(PyObject *) { GlobalSettings *gs= gp_KetsjiEngine->GetGlobalSettings(); int flag; @@ -1255,7 +1249,7 @@ static PyObject* gPyGetMaterialType(PyObject*) return PyLong_FromSsize_t(flag); } -static PyObject* gPySetAnisotropicFiltering(PyObject*, PyObject* args) +static PyObject *gPySetAnisotropicFiltering(PyObject *, PyObject *args) { short level; @@ -1272,16 +1266,16 @@ static PyObject* gPySetAnisotropicFiltering(PyObject*, PyObject* args) Py_RETURN_NONE; } -static PyObject* gPyGetAnisotropicFiltering(PyObject*, PyObject* args) +static PyObject *gPyGetAnisotropicFiltering(PyObject *, PyObject *args) { return PyLong_FromLong(gp_Rasterizer->GetAnisotropicFiltering()); } -static PyObject* gPyDrawLine(PyObject*, PyObject* args) +static PyObject *gPyDrawLine(PyObject *, PyObject *args) { - PyObject* ob_from; - PyObject* ob_to; - PyObject* ob_color; + PyObject *ob_from; + PyObject *ob_to; + PyObject *ob_color; if (!gp_Rasterizer) { PyErr_SetString(PyExc_RuntimeError, "Rasterizer.drawLine(obFrom, obTo, color): Rasterizer not available"); @@ -1306,7 +1300,7 @@ static PyObject* gPyDrawLine(PyObject*, PyObject* args) Py_RETURN_NONE; } -static PyObject* gPySetWindowSize(PyObject*, PyObject* args) +static PyObject *gPySetWindowSize(PyObject *, PyObject *args) { int width, height; if (!PyArg_ParseTuple(args, "ii:resize", &width, &height)) @@ -1317,48 +1311,47 @@ static PyObject* gPySetWindowSize(PyObject*, PyObject* args) } static struct PyMethodDef rasterizer_methods[] = { - {"getWindowWidth",(PyCFunction) gPyGetWindowWidth, - METH_VARARGS, "getWindowWidth doc"}, - {"getWindowHeight",(PyCFunction) gPyGetWindowHeight, - METH_VARARGS, "getWindowHeight doc"}, - {"makeScreenshot",(PyCFunction)gPyMakeScreenshot, - METH_VARARGS, "make Screenshot doc"}, - {"enableVisibility",(PyCFunction) gPyEnableVisibility, - METH_VARARGS, "enableVisibility doc"}, + {"getWindowWidth",(PyCFunction) gPyGetWindowWidth, + METH_VARARGS, "getWindowWidth doc"}, + {"getWindowHeight",(PyCFunction) gPyGetWindowHeight, + METH_VARARGS, "getWindowHeight doc"}, + {"makeScreenshot",(PyCFunction)gPyMakeScreenshot, + METH_VARARGS, "make Screenshot doc"}, + {"enableVisibility",(PyCFunction) gPyEnableVisibility, + METH_VARARGS, "enableVisibility doc"}, {"showMouse",(PyCFunction) gPyShowMouse, - METH_VARARGS, "showMouse(bool visible)"}, - {"setMousePosition",(PyCFunction) gPySetMousePosition, - METH_VARARGS, "setMousePosition(int x,int y)"}, - {"setBackgroundColor",(PyCFunction)gPySetBackgroundColor,METH_O,"set Background Color (rgb)"}, + METH_VARARGS, "showMouse(bool visible)"}, + {"setMousePosition",(PyCFunction) gPySetMousePosition, + METH_VARARGS, "setMousePosition(int x,int y)"}, + {"setBackgroundColor",(PyCFunction)gPySetBackgroundColor,METH_O,"set Background Color (rgb)"}, {"setAmbientColor",(PyCFunction)gPySetAmbientColor,METH_O,"set Ambient Color (rgb)"}, - {"disableMist",(PyCFunction)gPyDisableMist,METH_NOARGS,"turn off mist"}, - {"setMistColor",(PyCFunction)gPySetMistColor,METH_O,"set Mist Color (rgb)"}, - {"setMistStart",(PyCFunction)gPySetMistStart,METH_VARARGS,"set Mist Start(rgb)"}, - {"setMistEnd",(PyCFunction)gPySetMistEnd,METH_VARARGS,"set Mist End(rgb)"}, - {"enableMotionBlur",(PyCFunction)gPyEnableMotionBlur,METH_VARARGS,"enable motion blur"}, - {"disableMotionBlur",(PyCFunction)gPyDisableMotionBlur,METH_NOARGS,"disable motion blur"}, + {"disableMist",(PyCFunction)gPyDisableMist,METH_NOARGS,"turn off mist"}, + {"setMistColor",(PyCFunction)gPySetMistColor,METH_O,"set Mist Color (rgb)"}, + {"setMistStart",(PyCFunction)gPySetMistStart,METH_VARARGS,"set Mist Start(rgb)"}, + {"setMistEnd",(PyCFunction)gPySetMistEnd,METH_VARARGS,"set Mist End(rgb)"}, + {"enableMotionBlur",(PyCFunction)gPyEnableMotionBlur,METH_VARARGS,"enable motion blur"}, + {"disableMotionBlur",(PyCFunction)gPyDisableMotionBlur,METH_NOARGS,"disable motion blur"}, - - {"setEyeSeparation", (PyCFunction) gPySetEyeSeparation, METH_VARARGS, "set the eye separation for stereo mode"}, - {"getEyeSeparation", (PyCFunction) gPyGetEyeSeparation, METH_NOARGS, "get the eye separation for stereo mode"}, - {"setFocalLength", (PyCFunction) gPySetFocalLength, METH_VARARGS, "set the focal length for stereo mode"}, - {"getFocalLength", (PyCFunction) gPyGetFocalLength, METH_VARARGS, "get the focal length for stereo mode"}, - {"setMaterialMode",(PyCFunction) gPySetMaterialType, - METH_VARARGS, "set the material mode to use for OpenGL rendering"}, - {"getMaterialMode",(PyCFunction) gPyGetMaterialType, - METH_NOARGS, "get the material mode being used for OpenGL rendering"}, - {"setGLSLMaterialSetting",(PyCFunction) gPySetGLSLMaterialSetting, - METH_VARARGS, "set the state of a GLSL material setting"}, - {"getGLSLMaterialSetting",(PyCFunction) gPyGetGLSLMaterialSetting, - METH_VARARGS, "get the state of a GLSL material setting"}, - {"setAnisotropicFiltering", (PyCFunction) gPySetAnisotropicFiltering, - METH_VARARGS, "set the anisotropic filtering level (must be one of 1, 2, 4, 8, 16)"}, - {"getAnisotropicFiltering", (PyCFunction) gPyGetAnisotropicFiltering, - METH_VARARGS, "get the anisotropic filtering level"}, - {"drawLine", (PyCFunction) gPyDrawLine, - METH_VARARGS, "draw a line on the screen"}, - {"setWindowSize", (PyCFunction) gPySetWindowSize, METH_VARARGS, ""}, - { NULL, (PyCFunction) NULL, 0, NULL } + {"setEyeSeparation", (PyCFunction) gPySetEyeSeparation, METH_VARARGS, "set the eye separation for stereo mode"}, + {"getEyeSeparation", (PyCFunction) gPyGetEyeSeparation, METH_NOARGS, "get the eye separation for stereo mode"}, + {"setFocalLength", (PyCFunction) gPySetFocalLength, METH_VARARGS, "set the focal length for stereo mode"}, + {"getFocalLength", (PyCFunction) gPyGetFocalLength, METH_VARARGS, "get the focal length for stereo mode"}, + {"setMaterialMode",(PyCFunction) gPySetMaterialType, + METH_VARARGS, "set the material mode to use for OpenGL rendering"}, + {"getMaterialMode",(PyCFunction) gPyGetMaterialType, + METH_NOARGS, "get the material mode being used for OpenGL rendering"}, + {"setGLSLMaterialSetting",(PyCFunction) gPySetGLSLMaterialSetting, + METH_VARARGS, "set the state of a GLSL material setting"}, + {"getGLSLMaterialSetting",(PyCFunction) gPyGetGLSLMaterialSetting, + METH_VARARGS, "get the state of a GLSL material setting"}, + {"setAnisotropicFiltering", (PyCFunction) gPySetAnisotropicFiltering, + METH_VARARGS, "set the anisotropic filtering level (must be one of 1, 2, 4, 8, 16)"}, + {"getAnisotropicFiltering", (PyCFunction) gPyGetAnisotropicFiltering, + METH_VARARGS, "get the anisotropic filtering level"}, + {"drawLine", (PyCFunction) gPyDrawLine, + METH_VARARGS, "draw a line on the screen"}, + {"setWindowSize", (PyCFunction) gPySetWindowSize, METH_VARARGS, ""}, + { NULL, (PyCFunction) NULL, 0, NULL } }; // Initialization function for the module (*must* be called initGameLogic) @@ -1383,11 +1376,11 @@ static struct PyModuleDef GameLogic_module_def = { 0, /* m_free */ }; -PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack to get gravity hook +PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack to get gravity hook { - PyObject* m; - PyObject* d; - PyObject* item; /* temp PyObject* storage */ + PyObject *m; + PyObject *d; + PyObject *item; /* temp PyObject *storage */ gp_KetsjiEngine = engine; gp_KetsjiScene = scene; @@ -1405,7 +1398,7 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack } else { PyErr_Clear(); - // Create the module and add the functions + // Create the module and add the functions m = PyModule_Create(&GameLogic_module_def); PyDict_SetItemString(PySys_GetObject("modules"), GameLogic_module_def.m_name, m); } @@ -1802,7 +1795,7 @@ static void initPySysObjects(Main *maggie) Library *lib= (Library *)maggie->library.first; - while(lib) { + while (lib) { /* lib->name wont work in some cases (on win32), * even when expanding with gp_GamePythonPath, using lib->filename is less trouble */ initPySysObjects__append(sys_path, lib->filepath); @@ -1832,7 +1825,7 @@ static void restorePySysObjects(void) PyDict_Clear(sys_mods); PyDict_Update(sys_mods, gp_OrigPythonSysModules); Py_DECREF(gp_OrigPythonSysModules); - gp_OrigPythonSysModules= NULL; + gp_OrigPythonSysModules= NULL; // fprintf(stderr, "\nRestore Path: %d ", PyList_GET_SIZE(sys_path)); @@ -1850,7 +1843,7 @@ void removeImportMain(struct Main *maggie) } // Copied from bpy_interface.c -static struct _inittab bge_internal_modules[]= { +static struct _inittab bge_internal_modules[] = { {(char *)"mathutils", PyInit_mathutils}, {(char *)"bgl", BPyInit_bgl}, {(char *)"blf", BPyInit_blf}, @@ -1862,7 +1855,7 @@ static struct _inittab bge_internal_modules[]= { * Python is not initialized. * see bpy_interface.c's BPY_python_start() which shares the same functionality in blender. */ -PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie, int argc, char** argv) +PyObject *initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie, int argc, char** argv) { /* Yet another gotcha in the py api * Cant run PySys_SetArgv more then once because this adds the @@ -1935,7 +1928,7 @@ PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur } void exitGamePlayerPythonScripting() -{ +{ /* Clean up the Python mouse and keyboard */ delete gp_PythonKeyboard; gp_PythonKeyboard = NULL; @@ -1956,7 +1949,7 @@ void exitGamePlayerPythonScripting() /** * Python is already initialized. */ -PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie) +PyObject *initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie) { #if 0 // XXX TODO Py3 STR_String pname = progname; @@ -1998,9 +1991,10 @@ void exitGamePythonScripting() /* similar to the above functions except it sets up the namespace * and other more general things */ -void setupGamePython(KX_KetsjiEngine* ketsjiengine, KX_Scene* startscene, Main *blenderdata, PyObject * pyGlobalDict, PyObject **gameLogic, PyObject **gameLogic_keys, int argc, char** argv) +void setupGamePython(KX_KetsjiEngine* ketsjiengine, KX_Scene *startscene, Main *blenderdata, + PyObject *pyGlobalDict, PyObject **gameLogic, PyObject **gameLogic_keys, int argc, char** argv) { - PyObject* dictionaryobject; + PyObject *dictionaryobject; if (argv) /* player only */ dictionaryobject= initGamePlayerPythonScripting("Ketsji", psl_Lowest, blenderdata, argc, argv); @@ -2053,15 +2047,15 @@ static struct PyModuleDef Rasterizer_module_def = { 0, /* m_free */ }; -PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas) +PyObject *initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas) { gp_Canvas = canvas; gp_Rasterizer = rasty; - PyObject* m; - PyObject* d; - PyObject* item; + PyObject *m; + PyObject *d; + PyObject *item; /* Use existing module where possible * be careful not to init any runtime vars after this */ @@ -2114,9 +2108,9 @@ static char gPyEventToString_doc[] = "EventToString(event) - Take a valid event from the GameKeys module or Keyboard Sensor and return a name" ; -static PyObject* gPyEventToString(PyObject*, PyObject* value) +static PyObject *gPyEventToString(PyObject *, PyObject *value) { - PyObject* mod, *dict, *key, *val, *ret = NULL; + PyObject *mod, *dict, *key, *val, *ret = NULL; Py_ssize_t pos = 0; mod = PyImport_ImportModule( "GameKeys" ); @@ -2144,7 +2138,7 @@ static char gPyEventToCharacter_doc[] = "EventToCharacter(event, is_shift) - Take a valid event from the GameKeys module or Keyboard Sensor and return a character" ; -static PyObject* gPyEventToCharacter(PyObject*, PyObject* args) +static PyObject *gPyEventToCharacter(PyObject *, PyObject *args) { int event, shift; if (!PyArg_ParseTuple(args,"ii:EventToCharacter", &event, &shift)) @@ -2179,11 +2173,11 @@ static struct PyModuleDef GameKeys_module_def = { 0, /* m_free */ }; -PyObject* initGameKeys() +PyObject *initGameKeys() { - PyObject* m; - PyObject* d; - PyObject* item; + PyObject *m; + PyObject *d; + PyObject *item; /* Use existing module where possible */ m = PyImport_ImportModule( "GameKeys" ); @@ -2231,24 +2225,24 @@ PyObject* initGameKeys() KX_MACRO_addTypesToDict(d, YKEY, SCA_IInputDevice::KX_YKEY); KX_MACRO_addTypesToDict(d, ZKEY, SCA_IInputDevice::KX_ZKEY); - KX_MACRO_addTypesToDict(d, ZEROKEY, SCA_IInputDevice::KX_ZEROKEY); - KX_MACRO_addTypesToDict(d, ONEKEY, SCA_IInputDevice::KX_ONEKEY); - KX_MACRO_addTypesToDict(d, TWOKEY, SCA_IInputDevice::KX_TWOKEY); + KX_MACRO_addTypesToDict(d, ZEROKEY, SCA_IInputDevice::KX_ZEROKEY); + KX_MACRO_addTypesToDict(d, ONEKEY, SCA_IInputDevice::KX_ONEKEY); + KX_MACRO_addTypesToDict(d, TWOKEY, SCA_IInputDevice::KX_TWOKEY); KX_MACRO_addTypesToDict(d, THREEKEY, SCA_IInputDevice::KX_THREEKEY); - KX_MACRO_addTypesToDict(d, FOURKEY, SCA_IInputDevice::KX_FOURKEY); - KX_MACRO_addTypesToDict(d, FIVEKEY, SCA_IInputDevice::KX_FIVEKEY); - KX_MACRO_addTypesToDict(d, SIXKEY, SCA_IInputDevice::KX_SIXKEY); + KX_MACRO_addTypesToDict(d, FOURKEY, SCA_IInputDevice::KX_FOURKEY); + KX_MACRO_addTypesToDict(d, FIVEKEY, SCA_IInputDevice::KX_FIVEKEY); + KX_MACRO_addTypesToDict(d, SIXKEY, SCA_IInputDevice::KX_SIXKEY); KX_MACRO_addTypesToDict(d, SEVENKEY, SCA_IInputDevice::KX_SEVENKEY); KX_MACRO_addTypesToDict(d, EIGHTKEY, SCA_IInputDevice::KX_EIGHTKEY); - KX_MACRO_addTypesToDict(d, NINEKEY, SCA_IInputDevice::KX_NINEKEY); + KX_MACRO_addTypesToDict(d, NINEKEY, SCA_IInputDevice::KX_NINEKEY); KX_MACRO_addTypesToDict(d, CAPSLOCKKEY, SCA_IInputDevice::KX_CAPSLOCKKEY); - KX_MACRO_addTypesToDict(d, LEFTCTRLKEY, SCA_IInputDevice::KX_LEFTCTRLKEY); - KX_MACRO_addTypesToDict(d, LEFTALTKEY, SCA_IInputDevice::KX_LEFTALTKEY); - KX_MACRO_addTypesToDict(d, RIGHTALTKEY, SCA_IInputDevice::KX_RIGHTALTKEY); - KX_MACRO_addTypesToDict(d, RIGHTCTRLKEY, SCA_IInputDevice::KX_RIGHTCTRLKEY); - KX_MACRO_addTypesToDict(d, RIGHTSHIFTKEY, SCA_IInputDevice::KX_RIGHTSHIFTKEY); + KX_MACRO_addTypesToDict(d, LEFTCTRLKEY, SCA_IInputDevice::KX_LEFTCTRLKEY); + KX_MACRO_addTypesToDict(d, LEFTALTKEY, SCA_IInputDevice::KX_LEFTALTKEY); + KX_MACRO_addTypesToDict(d, RIGHTALTKEY, SCA_IInputDevice::KX_RIGHTALTKEY); + KX_MACRO_addTypesToDict(d, RIGHTCTRLKEY, SCA_IInputDevice::KX_RIGHTCTRLKEY); + KX_MACRO_addTypesToDict(d, RIGHTSHIFTKEY, SCA_IInputDevice::KX_RIGHTSHIFTKEY); KX_MACRO_addTypesToDict(d, LEFTSHIFTKEY, SCA_IInputDevice::KX_LEFTSHIFTKEY); KX_MACRO_addTypesToDict(d, ESCKEY, SCA_IInputDevice::KX_ESCKEY); @@ -2256,25 +2250,25 @@ PyObject* initGameKeys() KX_MACRO_addTypesToDict(d, RETKEY, SCA_IInputDevice::KX_RETKEY); KX_MACRO_addTypesToDict(d, ENTERKEY, SCA_IInputDevice::KX_RETKEY); KX_MACRO_addTypesToDict(d, SPACEKEY, SCA_IInputDevice::KX_SPACEKEY); - KX_MACRO_addTypesToDict(d, LINEFEEDKEY, SCA_IInputDevice::KX_LINEFEEDKEY); + KX_MACRO_addTypesToDict(d, LINEFEEDKEY, SCA_IInputDevice::KX_LINEFEEDKEY); KX_MACRO_addTypesToDict(d, BACKSPACEKEY, SCA_IInputDevice::KX_BACKSPACEKEY); KX_MACRO_addTypesToDict(d, DELKEY, SCA_IInputDevice::KX_DELKEY); KX_MACRO_addTypesToDict(d, SEMICOLONKEY, SCA_IInputDevice::KX_SEMICOLONKEY); - KX_MACRO_addTypesToDict(d, PERIODKEY, SCA_IInputDevice::KX_PERIODKEY); - KX_MACRO_addTypesToDict(d, COMMAKEY, SCA_IInputDevice::KX_COMMAKEY); - KX_MACRO_addTypesToDict(d, QUOTEKEY, SCA_IInputDevice::KX_QUOTEKEY); - KX_MACRO_addTypesToDict(d, ACCENTGRAVEKEY, SCA_IInputDevice::KX_ACCENTGRAVEKEY); - KX_MACRO_addTypesToDict(d, MINUSKEY, SCA_IInputDevice::KX_MINUSKEY); - KX_MACRO_addTypesToDict(d, SLASHKEY, SCA_IInputDevice::KX_SLASHKEY); + KX_MACRO_addTypesToDict(d, PERIODKEY, SCA_IInputDevice::KX_PERIODKEY); + KX_MACRO_addTypesToDict(d, COMMAKEY, SCA_IInputDevice::KX_COMMAKEY); + KX_MACRO_addTypesToDict(d, QUOTEKEY, SCA_IInputDevice::KX_QUOTEKEY); + KX_MACRO_addTypesToDict(d, ACCENTGRAVEKEY, SCA_IInputDevice::KX_ACCENTGRAVEKEY); + KX_MACRO_addTypesToDict(d, MINUSKEY, SCA_IInputDevice::KX_MINUSKEY); + KX_MACRO_addTypesToDict(d, SLASHKEY, SCA_IInputDevice::KX_SLASHKEY); KX_MACRO_addTypesToDict(d, BACKSLASHKEY, SCA_IInputDevice::KX_BACKSLASHKEY); - KX_MACRO_addTypesToDict(d, EQUALKEY, SCA_IInputDevice::KX_EQUALKEY); - KX_MACRO_addTypesToDict(d, LEFTBRACKETKEY, SCA_IInputDevice::KX_LEFTBRACKETKEY); - KX_MACRO_addTypesToDict(d, RIGHTBRACKETKEY, SCA_IInputDevice::KX_RIGHTBRACKETKEY); + KX_MACRO_addTypesToDict(d, EQUALKEY, SCA_IInputDevice::KX_EQUALKEY); + KX_MACRO_addTypesToDict(d, LEFTBRACKETKEY, SCA_IInputDevice::KX_LEFTBRACKETKEY); + KX_MACRO_addTypesToDict(d, RIGHTBRACKETKEY, SCA_IInputDevice::KX_RIGHTBRACKETKEY); KX_MACRO_addTypesToDict(d, LEFTARROWKEY, SCA_IInputDevice::KX_LEFTARROWKEY); KX_MACRO_addTypesToDict(d, DOWNARROWKEY, SCA_IInputDevice::KX_DOWNARROWKEY); - KX_MACRO_addTypesToDict(d, RIGHTARROWKEY, SCA_IInputDevice::KX_RIGHTARROWKEY); - KX_MACRO_addTypesToDict(d, UPARROWKEY, SCA_IInputDevice::KX_UPARROWKEY); + KX_MACRO_addTypesToDict(d, RIGHTARROWKEY, SCA_IInputDevice::KX_RIGHTARROWKEY); + KX_MACRO_addTypesToDict(d, UPARROWKEY, SCA_IInputDevice::KX_UPARROWKEY); KX_MACRO_addTypesToDict(d, PAD2 , SCA_IInputDevice::KX_PAD2); KX_MACRO_addTypesToDict(d, PAD4 , SCA_IInputDevice::KX_PAD4); @@ -2347,14 +2341,14 @@ PyObject* initGameKeys() int saveGamePythonConfig( char **marshal_buffer) { int marshal_length = 0; - PyObject* gameLogic = PyImport_ImportModule("GameLogic"); + PyObject *gameLogic = PyImport_ImportModule("GameLogic"); if (gameLogic) { - PyObject* pyGlobalDict = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module + PyObject *pyGlobalDict = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module if (pyGlobalDict) { -#ifdef Py_MARSHAL_VERSION - PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict, 2); // Py_MARSHAL_VERSION == 2 as of Py2.5 +#ifdef Py_MARSHAL_VERSION + PyObject *pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict, 2); // Py_MARSHAL_VERSION == 2 as of Py2.5 #else - PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict ); + PyObject *pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict ); #endif if (pyGlobalDictMarshal) { // for testing only @@ -2384,12 +2378,12 @@ int loadGamePythonConfig(char *marshal_buffer, int marshal_length) { /* Restore the dict */ if (marshal_buffer) { - PyObject* gameLogic = PyImport_ImportModule("GameLogic"); + PyObject *gameLogic = PyImport_ImportModule("GameLogic"); if (gameLogic) { - PyObject* pyGlobalDict = PyMarshal_ReadObjectFromString(marshal_buffer, marshal_length); + PyObject *pyGlobalDict = PyMarshal_ReadObjectFromString(marshal_buffer, marshal_length); if (pyGlobalDict) { - PyObject* pyGlobalDict_orig = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module. + PyObject *pyGlobalDict_orig = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module. if (pyGlobalDict_orig) { PyDict_Clear(pyGlobalDict_orig); PyDict_Update(pyGlobalDict_orig, pyGlobalDict); @@ -2405,10 +2399,11 @@ int loadGamePythonConfig(char *marshal_buffer, int marshal_length) PyErr_Clear(); printf("Error could not marshall string\n"); } - } else { + } + else { PyErr_Clear(); printf("Error, bge.logic failed to import bge.logic.globalDict will be lost\n"); - } + } } return 0; } diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h index 1500dd97ae1..859c31adcd3 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.h +++ b/source/gameengine/Ketsji/KX_PythonInit.h @@ -52,7 +52,8 @@ void exitGamePlayerPythonScripting(); PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level, struct Main *maggie); void exitGamePythonScripting(); -void setupGamePython(KX_KetsjiEngine* ketsjiengine, KX_Scene* startscene, Main *blenderdata, PyObject *pyGlobalDict, PyObject **gameLogic, PyObject **gameLogic_keys, int argc, char** argv); +void setupGamePython(KX_KetsjiEngine *ketsjiengine, KX_Scene *startscene, Main *blenderdata, + PyObject *pyGlobalDict, PyObject **gameLogic, PyObject **gameLogic_keys, int argc, char** argv); void setGamePythonPath(const char *path); void resetGamePythonPath(); @@ -72,11 +73,12 @@ class KX_Scene* KX_GetActiveScene(); class KX_KetsjiEngine* KX_GetActiveEngine(); typedef int (*PyNextFrameFunc)(void *); + struct PyNextFrameState { - //state: can be either a GPG_NextFrameState or a BL_KetsjiNextFrameState - void *state; - //func: can be either GPG_PyNextFrame or BL_KetsjiPyNextFrame - PyNextFrameFunc func; + /** can be either a GPG_NextFrameState or a BL_KetsjiNextFrameState */ + void *state; + /** can be either GPG_PyNextFrame or BL_KetsjiPyNextFrame */ + PyNextFrameFunc func; }; extern struct PyNextFrameState pynextframestate; @@ -84,8 +86,7 @@ extern struct PyNextFrameState pynextframestate; void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color); void KX_RasterizerDrawDebugCircle(const MT_Vector3& center, const MT_Scalar radius, const MT_Vector3& color, - const MT_Vector3& normal, int nsector); + const MT_Vector3& normal, int nsector); -#endif //__KX_PYTHONINIT_H__ - +#endif /* __KX_PYTHONINIT_H__ */ diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp index 3033c534e84..805b9ce2fc2 100644 --- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp +++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp @@ -29,14 +29,10 @@ * \ingroup ketsji */ - - - -#ifndef _adr_py_init_types_h_ // only process once, -#define _adr_py_init_types_h_ // even if multiply included - #ifdef WITH_PYTHON +#include "KX_PythonInitTypes.h" + /* Only for Class::Parents */ #include "BL_BlenderShader.h" #include "BL_ShapeActionActuator.h" @@ -46,6 +42,7 @@ #include "BL_ArmatureChannel.h" #include "KX_BlenderMaterial.h" #include "KX_CameraActuator.h" +#include "KX_CharacterWrapper.h" #include "KX_ConstraintActuator.h" #include "KX_ConstraintWrapper.h" #include "KX_GameActuator.h" @@ -166,7 +163,7 @@ static void PyType_Ready_ADD(PyObject *dict, PyTypeObject *tp, PyAttributeDef *a void initPyTypes(void) { - + /* * initPyObjectPlusType(BL_ActionActuator::Parents); * ..... @@ -193,6 +190,7 @@ void initPyTypes(void) PyType_Ready_Attr(dict, KX_BlenderMaterial, init_getset); PyType_Ready_Attr(dict, KX_Camera, init_getset); PyType_Ready_Attr(dict, KX_CameraActuator, init_getset); + PyType_Ready_Attr(dict, KX_CharacterWrapper, init_getset); PyType_Ready_Attr(dict, KX_ConstraintActuator, init_getset); PyType_Ready_Attr(dict, KX_ConstraintWrapper, init_getset); PyType_Ready_Attr(dict, KX_GameActuator, init_getset); @@ -266,5 +264,3 @@ void initPyTypes(void) } #endif // WITH_PYTHON - -#endif diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.h b/source/gameengine/Ketsji/KX_PythonInitTypes.h index a06fe46a0ea..d8ee4f75fdd 100644 --- a/source/gameengine/Ketsji/KX_PythonInitTypes.h +++ b/source/gameengine/Ketsji/KX_PythonInitTypes.h @@ -29,11 +29,11 @@ * \ingroup ketsji */ -#ifndef _adr_py_init_types_h_ // only process once, -#define _adr_py_init_types_h_ // even if multiply included +#ifndef __KX_PYTHON_INIT_TYPES__ +#define __KX_PYTHON_INIT_TYPES__ #ifdef WITH_PYTHON void initPyTypes(void); #endif -#endif +#endif /* __KX_PYTHON_INIT_TYPES__ */ diff --git a/source/gameengine/Ketsji/KX_PythonMain.cpp b/source/gameengine/Ketsji/KX_PythonMain.cpp index d926dff0bf5..740bb102fd9 100644 --- a/source/gameengine/Ketsji/KX_PythonMain.cpp +++ b/source/gameengine/Ketsji/KX_PythonMain.cpp @@ -1,6 +1,4 @@ -/* - * $Id: KX_PythonMain.cpp 37750 2011-06-27 09:27:56Z sjoerd $ - * +/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -17,15 +15,11 @@ * 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. + * Contributor(s): Benoit Bolsee * * ***** END GPL LICENSE BLOCK ***** */ + /** \file gameengine/Ketsji/KX_PythonMain.cpp * \ingroup ketsji */ diff --git a/source/gameengine/Ketsji/KX_PythonMain.h b/source/gameengine/Ketsji/KX_PythonMain.h index 1460ea2ca96..e638fa9094e 100644 --- a/source/gameengine/Ketsji/KX_PythonMain.h +++ b/source/gameengine/Ketsji/KX_PythonMain.h @@ -1,6 +1,4 @@ -/* - * $Id: KX_PythonMain.h 37750 2011-06-27 09:27:56Z sjoerd $ - * +/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -31,11 +29,12 @@ * \ingroup ketsji */ -#ifndef __KX_PYTHON_MAIN -#define __KX_PYTHON_MAIN +#ifndef __KX_PYTHON_MAIN__ +#define __KX_PYTHON_MAIN__ #include "BKE_main.h" #include "DNA_scene_types.h" extern "C" char *KX_GetPythonMain(struct Scene* scene); extern "C" char *KX_GetPythonCode(struct Main *main, char *python_main); -#endif + +#endif /* __KX_PYTHON_MAIN__ */ diff --git a/source/gameengine/Ketsji/KX_PythonSeq.cpp b/source/gameengine/Ketsji/KX_PythonSeq.cpp index 6eadc0cbef3..6b4d88709e8 100644 --- a/source/gameengine/Ketsji/KX_PythonSeq.cpp +++ b/source/gameengine/Ketsji/KX_PythonSeq.cpp @@ -69,38 +69,38 @@ static void KX_PythonSeq_dealloc(KX_PythonSeq * self) PyObject_GC_Del(self); } -static Py_ssize_t KX_PythonSeq_len( PyObject * self ) +static Py_ssize_t KX_PythonSeq_len( PyObject *self ) { PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); - + if (self_plus==NULL) { PyErr_SetString(PyExc_SystemError, "len(seq): "BGE_PROXY_ERROR_MSG); return -1; } - switch(((KX_PythonSeq *)self)->type) { - case KX_PYGENSEQ_CONT_TYPE_SENSORS: - return ((SCA_IController *)self_plus)->GetLinkedSensors().size(); - case KX_PYGENSEQ_CONT_TYPE_ACTUATORS: - return ((SCA_IController *)self_plus)->GetLinkedActuators().size(); - case KX_PYGENSEQ_OB_TYPE_SENSORS: - return ((KX_GameObject *)self_plus)->GetSensors().size(); - case KX_PYGENSEQ_OB_TYPE_CONTROLLERS: - return ((KX_GameObject *)self_plus)->GetControllers().size(); - case KX_PYGENSEQ_OB_TYPE_ACTUATORS: - return ((KX_GameObject *)self_plus)->GetActuators().size(); - case KX_PYGENSEQ_OB_TYPE_CONSTRAINTS: - return ((BL_ArmatureObject *)self_plus)->GetConstraintNumber(); - case KX_PYGENSEQ_OB_TYPE_CHANNELS: - return ((BL_ArmatureObject *)self_plus)->GetChannelNumber(); - default: - /* Should never happen */ - PyErr_SetString(PyExc_SystemError, "invalid type, internal error"); - return -1; + switch (((KX_PythonSeq *)self)->type) { + case KX_PYGENSEQ_CONT_TYPE_SENSORS: + return ((SCA_IController *)self_plus)->GetLinkedSensors().size(); + case KX_PYGENSEQ_CONT_TYPE_ACTUATORS: + return ((SCA_IController *)self_plus)->GetLinkedActuators().size(); + case KX_PYGENSEQ_OB_TYPE_SENSORS: + return ((KX_GameObject *)self_plus)->GetSensors().size(); + case KX_PYGENSEQ_OB_TYPE_CONTROLLERS: + return ((KX_GameObject *)self_plus)->GetControllers().size(); + case KX_PYGENSEQ_OB_TYPE_ACTUATORS: + return ((KX_GameObject *)self_plus)->GetActuators().size(); + case KX_PYGENSEQ_OB_TYPE_CONSTRAINTS: + return ((BL_ArmatureObject *)self_plus)->GetConstraintNumber(); + case KX_PYGENSEQ_OB_TYPE_CHANNELS: + return ((BL_ArmatureObject *)self_plus)->GetChannelNumber(); + default: + /* Should never happen */ + PyErr_SetString(PyExc_SystemError, "invalid type, internal error"); + return -1; } } -static PyObject *KX_PythonSeq_getIndex(PyObject* self, int index) +static PyObject *KX_PythonSeq_getIndex(PyObject *self, int index) { PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); @@ -109,7 +109,7 @@ static PyObject *KX_PythonSeq_getIndex(PyObject* self, int index) return NULL; } - switch(((KX_PythonSeq *)self)->type) { + switch (((KX_PythonSeq *)self)->type) { case KX_PYGENSEQ_CONT_TYPE_SENSORS: { vector& linkedsensors = ((SCA_IController *)self_plus)->GetLinkedSensors(); @@ -193,7 +193,7 @@ static PyObjectPlus * KX_PythonSeq_subscript__internal(PyObject *self, const cha { PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); - switch(((KX_PythonSeq *)self)->type) { + switch (((KX_PythonSeq *)self)->type) { case KX_PYGENSEQ_CONT_TYPE_SENSORS: { vector& linkedsensors = ((SCA_IController *)self_plus)->GetLinkedSensors(); @@ -264,7 +264,7 @@ static PyObjectPlus * KX_PythonSeq_subscript__internal(PyObject *self, const cha } -static PyObject * KX_PythonSeq_subscript(PyObject * self, PyObject *key) +static PyObject * KX_PythonSeq_subscript(PyObject *self, PyObject *key) { PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); @@ -314,10 +314,10 @@ static int KX_PythonSeq_contains(PyObject *self, PyObject *key) } /* Matches python dict.get(key, [default]) */ -PyObject* KX_PythonSeq_get(PyObject * self, PyObject *args) +static PyObject *KX_PythonSeq_get(PyObject *self, PyObject *args) { char *key; - PyObject* def = Py_None; + PyObject *def = Py_None; PyObjectPlus* ret_plus; if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) @@ -396,7 +396,7 @@ static PyObject *KX_PythonSeq_nextIter(KX_PythonSeq *self) static int KX_PythonSeq_compare( KX_PythonSeq * a, KX_PythonSeq * b ) { - return ( a->type == b->type && a->base == b->base) ? 0 : -1; + return ( a->type == b->type && a->base == b->base) ? 0 : -1; } static PyObject *KX_PythonSeq_richcmp(PyObject *a, PyObject *b, int op) diff --git a/source/gameengine/Ketsji/KX_PythonSeq.h b/source/gameengine/Ketsji/KX_PythonSeq.h index 47a01737cdb..568d59119c0 100644 --- a/source/gameengine/Ketsji/KX_PythonSeq.h +++ b/source/gameengine/Ketsji/KX_PythonSeq.h @@ -30,8 +30,8 @@ * \brief Readonly sequence wrapper for lookups on logic bricks */ -#ifndef _adr_py_seq_h_ // only process once, -#define _adr_py_seq_h_ // even if multiply included +#ifndef __KX_PYTHONSEQ_H__ +#define __KX_PYTHONSEQ_H__ #ifdef WITH_PYTHON @@ -63,6 +63,6 @@ typedef struct { PyObject *KX_PythonSeq_CreatePyObject(PyObject *base, short type); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ -#endif // _adr_py_seq_h_ +#endif /* __KX_PYTHONSEQ_H__ */ diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp index 74009f51078..04d67fc73e1 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.cpp +++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp @@ -217,9 +217,9 @@ PyAttributeDef KX_RadarSensor::Attributes[] = { {NULL} //Sentinel }; -PyObject* KX_RadarSensor::pyattr_get_angle(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_RadarSensor::pyattr_get_angle(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_RadarSensor* self= static_cast(self_v); + KX_RadarSensor* self = static_cast(self_v); // The original angle from the gui was converted, so we recalculate the value here to maintain // consistency between Python and the gui diff --git a/source/gameengine/Ketsji/KX_RadarSensor.h b/source/gameengine/Ketsji/KX_RadarSensor.h index 2de58f8b3a0..6a2d50ffa3a 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.h +++ b/source/gameengine/Ketsji/KX_RadarSensor.h @@ -97,5 +97,4 @@ public: #endif }; -#endif //__KX_RADARSENSOR_H__ - +#endif /* __KX_RADARSENSOR_H__ */ diff --git a/source/gameengine/Ketsji/KX_RayCast.cpp b/source/gameengine/Ketsji/KX_RayCast.cpp index 459600f2e34..2a6b7d122b5 100644 --- a/source/gameengine/Ketsji/KX_RayCast.cpp +++ b/source/gameengine/Ketsji/KX_RayCast.cpp @@ -76,9 +76,9 @@ bool KX_RayCast::RayTest(PHY_IPhysicsEnvironment* physics_environment, const MT_ PHY_IPhysicsController* hit_controller; - while((hit_controller = physics_environment->rayTest(callback, - frompoint.x(),frompoint.y(),frompoint.z(), - topoint.x(),topoint.y(),topoint.z())) != NULL) + while ((hit_controller = physics_environment->rayTest(callback, + frompoint.x(),frompoint.y(),frompoint.z(), + topoint.x(),topoint.y(),topoint.z())) != NULL) { KX_ClientObjectInfo* info = static_cast(hit_controller->getNewClientInfo()); diff --git a/source/gameengine/Ketsji/KX_RayEventManager.h b/source/gameengine/Ketsji/KX_RayEventManager.h index f795495d1c9..07506b9e32b 100644 --- a/source/gameengine/Ketsji/KX_RayEventManager.h +++ b/source/gameengine/Ketsji/KX_RayEventManager.h @@ -50,5 +50,4 @@ public: #endif }; -#endif //__KX_RAYEVENTMANAGER_H__ - +#endif /* __KX_RAYEVENTMANAGER_H__ */ diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp index 58ca847b617..14786e8429e 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.cpp +++ b/source/gameengine/Ketsji/KX_RaySensor.cpp @@ -361,7 +361,7 @@ PyAttributeDef KX_RaySensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_RaySensor::pyattr_get_hitobject(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_RaySensor::pyattr_get_hitobject(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_RaySensor* self = static_cast(self_v); if (self->m_hitObject) diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h index f5d1c72d098..9d40fb55747 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.h +++ b/source/gameengine/Ketsji/KX_RaySensor.h @@ -94,11 +94,10 @@ public: #ifdef WITH_PYTHON /* Attributes */ - static PyObject* pyattr_get_hitobject(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_hitobject(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; -#endif //__KX_RAYSENSOR_H__ - +#endif /* __KX_RAYSENSOR_H__ */ diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index 841feda5237..d850168afdf 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -203,10 +203,10 @@ PyAttributeDef KX_SCA_AddObjectActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_SCA_AddObjectActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_SCA_AddObjectActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SCA_AddObjectActuator* actuator = static_cast(self); - if (!actuator->m_OriginalObject) + if (!actuator->m_OriginalObject) Py_RETURN_NONE; else return actuator->m_OriginalObject->GetProxy(); @@ -221,7 +221,7 @@ int KX_SCA_AddObjectActuator::pyattr_set_object(void *self, const struct KX_PYAT return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error if (actuator->m_OriginalObject != NULL) - actuator->m_OriginalObject->UnregisterActuator(actuator); + actuator->m_OriginalObject->UnregisterActuator(actuator); actuator->m_OriginalObject = (SCA_IObject*)gameobj; @@ -231,7 +231,7 @@ int KX_SCA_AddObjectActuator::pyattr_set_object(void *self, const struct KX_PYAT return PY_SET_ATTR_SUCCESS; } -PyObject* KX_SCA_AddObjectActuator::pyattr_get_objectLastCreated(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_SCA_AddObjectActuator::pyattr_get_objectLastCreated(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SCA_AddObjectActuator* actuator = static_cast(self); if (!actuator->m_lastCreatedObject) @@ -240,7 +240,7 @@ PyObject* KX_SCA_AddObjectActuator::pyattr_get_objectLastCreated(void *self, con return actuator->m_lastCreatedObject->GetProxy(); } -PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject() +PyObject *KX_SCA_AddObjectActuator::PyInstantAddObject() { InstantAddObject(); @@ -253,7 +253,7 @@ void KX_SCA_AddObjectActuator::InstantAddObject() { if (m_OriginalObject) { - // Add an identical object, with properties inherited from the original object + // Add an identical object, with properties inherited from the original object // Now it needs to be added to the current scene. SCA_IObject* replica = m_scene->AddReplicaObject(m_OriginalObject,GetParent(),m_timeProp ); KX_GameObject * game_obj = static_cast(replica); diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h index f49f2473036..976f3c58d68 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h @@ -50,7 +50,7 @@ class KX_SCA_AddObjectActuator : public SCA_IActuator /// Time field: lifetime of the new object int m_timeProp; - /// Original object reference (object to replicate) + /// Original object reference (object to replicate) SCA_IObject* m_OriginalObject; /// Object will be added to the following scene @@ -112,7 +112,7 @@ public: virtual bool Update(); - SCA_IObject* + SCA_IObject * GetLastCreatedObject( ) const; @@ -122,13 +122,12 @@ public: KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,InstantAddObject); - static PyObject* pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); - static PyObject* pyattr_get_objectLastCreated(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_objectLastCreated(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; /* end of class KX_SCA_AddObjectActuator : public KX_EditObjectActuator */ -#endif - +#endif /* __KX_SCA_ADDOBJECTACTUATOR_H__ */ diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp index f408b2cd7c9..5dc67a4cff3 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp @@ -119,14 +119,14 @@ bool KX_SCA_DynamicActuator::Update() switch (m_dyn_operation) { - case 0: - obj->RestoreDynamics(); + case 0: + obj->RestoreDynamics(); break; case 1: obj->SuspendDynamics(); break; case 2: - controller->setRigidBody(true); + controller->setRigidBody(true); break; case 3: controller->setRigidBody(false); diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp index ffe5556cfe6..b105256836b 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp @@ -87,7 +87,7 @@ PyAttributeDef KX_SCA_ReplaceMeshActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_SCA_ReplaceMeshActuator::pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_SCA_ReplaceMeshActuator::pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SCA_ReplaceMeshActuator* actuator = static_cast(self); if (!actuator->m_mesh) diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h index 6db16a0e1b6..4370b5d4a4f 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h @@ -84,14 +84,13 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator m_scene= val; }; - static PyObject* pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); KX_PYMETHOD_DOC(KX_SCA_ReplaceMeshActuator,instantReplaceMesh); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; -#endif - +#endif /* __KX_SCA_REPLACEMESHACTUATOR_H__ */ diff --git a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp index 13200696ffb..19b9d13087d 100644 --- a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp +++ b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp @@ -51,14 +51,14 @@ KX_BoneParentRelation:: New(Bone* bone ) { return new KX_BoneParentRelation(bone); -} +} bool KX_BoneParentRelation:: UpdateChildCoordinates( SG_Spatial * child, const SG_Spatial * parent, - bool& parentUpdated + bool& parentUpdated ) { MT_assert(child != NULL); @@ -71,7 +71,7 @@ UpdateChildCoordinates( // we don't know if the armature has been updated or not, assume yes parentUpdated = true; - // the childs world locations which we will update. + // the childs world locations which we will update. MT_Vector3 child_w_scale; MT_Point3 child_w_pos; diff --git a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h index 76fefdebe08..6f4fd482198 100644 --- a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h +++ b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.h @@ -57,7 +57,7 @@ public : static KX_BoneParentRelation * New(Bone* bone - ); + ); /** * Updates the childs world coordinates relative to the parent's diff --git a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp index 699b267496d..e80de76861e 100644 --- a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp +++ b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp @@ -45,14 +45,14 @@ KX_NormalParentRelation:: New( ) { return new KX_NormalParentRelation(); -} +} bool KX_NormalParentRelation:: UpdateChildCoordinates( SG_Spatial * child, const SG_Spatial * parent, - bool& parentUpdated + bool& parentUpdated ) { MT_assert(child != NULL); @@ -67,7 +67,7 @@ UpdateChildCoordinates( return true; //false; } else { - // the childs world locations which we will update. + // the childs world locations which we will update. const MT_Vector3 & p_world_scale = parent->GetWorldScaling(); const MT_Point3 & p_world_pos = parent->GetWorldPosition(); const MT_Matrix3x3 & p_world_rotation = parent->GetWorldOrientation(); @@ -121,7 +121,7 @@ KX_VertexParentRelation:: UpdateChildCoordinates( SG_Spatial * child, const SG_Spatial * parent, - bool& parentUpdated + bool& parentUpdated ) { MT_assert(child != NULL); @@ -176,7 +176,7 @@ New( MT_Scalar relaxation ) { return new KX_SlowParentRelation(relaxation); -} +} /** * Method inherited from KX_ParentRelation @@ -187,7 +187,7 @@ KX_SlowParentRelation:: UpdateChildCoordinates( SG_Spatial * child, const SG_Spatial * parent, - bool& parentUpdated + bool& parentUpdated ) { MT_assert(child != NULL); @@ -198,7 +198,7 @@ UpdateChildCoordinates( const MT_Point3 & child_pos = child->GetLocalPosition(); const MT_Matrix3x3 & child_rotation = child->GetLocalOrientation(); - // the childs world locations which we will update. + // the childs world locations which we will update. MT_Vector3 child_w_scale; MT_Point3 child_w_pos; @@ -230,7 +230,7 @@ UpdateChildCoordinates( child_w_scale = child->GetWorldScaling(); child_w_pos = child->GetWorldPosition(); - child_w_rotation = child->GetWorldOrientation(); + child_w_rotation = child->GetWorldOrientation(); // now 'interpolate' the normal coordinates with the last // world coordinates to get the new world coordinates. diff --git a/source/gameengine/Ketsji/KX_SG_NodeRelationships.h b/source/gameengine/Ketsji/KX_SG_NodeRelationships.h index b5ab5302910..5d777f5028f 100644 --- a/source/gameengine/Ketsji/KX_SG_NodeRelationships.h +++ b/source/gameengine/Ketsji/KX_SG_NodeRelationships.h @@ -57,7 +57,7 @@ public : static KX_NormalParentRelation * New( - ); + ); /** * Method inherited from KX_ParentRelation @@ -67,7 +67,7 @@ public : UpdateChildCoordinates( SG_Spatial * child, const SG_Spatial * parent, - bool& parentUpdated + bool& parentUpdated ); /** @@ -106,7 +106,7 @@ public : static KX_VertexParentRelation * New( - ); + ); /** * Method inherited from KX_ParentRelation @@ -116,7 +116,7 @@ public : UpdateChildCoordinates( SG_Spatial * child, const SG_Spatial * parent, - bool& parentUpdated + bool& parentUpdated ); /** @@ -162,7 +162,7 @@ public : KX_SlowParentRelation * New( MT_Scalar relaxation - ); + ); /** * Method inherited from KX_ParentRelation @@ -172,7 +172,7 @@ public : UpdateChildCoordinates( SG_Spatial * child, const SG_Spatial * parent, - bool& parentUpdated + bool& parentUpdated ); /** diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index c1afed82b02..96b4a21a36c 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -31,9 +31,9 @@ */ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable : 4786) -#endif //WIN32 +#ifdef _MSC_VER +# pragma warning (disable:4786) +#endif #include "KX_Scene.h" #include "KX_PythonInit.h" @@ -98,7 +98,7 @@ #include -void* KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene) +static void *KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene) { KX_GameObject* replica = ((KX_Scene*)scene)->AddNodeReplicaObject(node,(KX_GameObject*)gameobj); @@ -108,7 +108,7 @@ void* KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene) return (void*)replica; } -void* KX_SceneDestructionFunc(SG_IObject* node,void* gameobj,void* scene) +static void *KX_SceneDestructionFunc(SG_IObject* node,void* gameobj,void* scene) { ((KX_Scene*)scene)->RemoveNodeDestructObject(node,(KX_GameObject*)gameobj); @@ -368,7 +368,7 @@ void KX_Scene::SetFramingType(RAS_FrameSettings & frame_settings) const RAS_FrameSettings& KX_Scene::GetFramingType() const { return m_frame_settings; -}; +}; @@ -441,7 +441,7 @@ void KX_Scene::EnableZBufferClearing(bool isclearingZbuffer) void KX_Scene::RemoveNodeDestructObject(class SG_IObject* node,class CValue* gameobj) { - KX_GameObject* orgobj = (KX_GameObject*)gameobj; + KX_GameObject* orgobj = (KX_GameObject*)gameobj; if (NewRemoveObject(orgobj) != 0) { // object is not yet deleted because a reference is hanging somewhere. @@ -769,6 +769,13 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) // we can now add the graphic controller to the physic engine replica->ActivateGraphicController(true); + // set references for dupli-group + // groupobj holds a list of all objects, that belongs to this group + groupobj->AddInstanceObjects(replica); + + // every object gets the reference to its dupli-group object + replica->SetDupliGroupObject(groupobj); + // done with replica replica->Release(); } @@ -1017,6 +1024,20 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) m_timemgr->RemoveTimeProperty(propval); } } + + // if the object is the dupligroup proxy, you have to cleanup all m_pDupliGroupObject's in all + // instances refering to this group + if (newobj->GetInstanceObjects()) { + for (int i = 0; i < newobj->GetInstanceObjects()->GetCount(); i++) { + KX_GameObject* instance = (KX_GameObject*)newobj->GetInstanceObjects()->GetValue(i); + instance->RemoveDupliGroupObject(); + } + } + + // if this object was part of a group, make sure to remove it from that group's instance list + KX_GameObject* group = newobj->GetDupliGroupObject(); + if (group) + group->RemoveInstanceObject(newobj); newobj->RemoveMeshes(); ret = 1; @@ -1072,7 +1093,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj, bool use_gfx, bool u } if (use_gfx && mesh != NULL) - { + { gameobj->RemoveMeshes(); gameobj->AddMesh(mesh); @@ -1233,9 +1254,9 @@ KX_FontObject* KX_Scene::FindFont(KX_FontObject* font) { list::iterator it = m_fonts.begin(); - while ( (it != m_fonts.end()) - && ((*it) != font) ) { - ++it; + while ((it != m_fonts.end()) && ((*it) != font)) + { + ++it; } return ((it == m_fonts.end()) ? NULL : (*it)); @@ -1247,9 +1268,7 @@ KX_Camera* KX_Scene::FindCamera(KX_Camera* cam) { list::iterator it = m_cameras.begin(); - while ( (it != m_cameras.end()) - && ((*it) != cam) ) - { + while ((it != m_cameras.end()) && ((*it) != cam)) { it++; } @@ -1261,9 +1280,7 @@ KX_Camera* KX_Scene::FindCamera(STR_String& name) { list::iterator it = m_cameras.begin(); - while ( (it != m_cameras.end()) - && ((*it)->GetName() != name) ) - { + while ((it != m_cameras.end()) && ((*it)->GetName() != name)) { it++; } @@ -1278,7 +1295,7 @@ void KX_Scene::AddCamera(KX_Camera* cam) KX_Camera* KX_Scene::GetActiveCamera() -{ +{ // NULL if not defined return m_active_camera; } @@ -1481,7 +1498,15 @@ void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int planes[4].setValue(cplanes[2].getValue()); // top planes[5].setValue(cplanes[3].getValue()); // bottom CullingInfo info(layer); - dbvt_culling = m_physicsEnvironment->cullingTest(PhysicsCullingCallback,&info,planes,5,m_dbvt_occlusion_res); + + double mvmat[16] = {0}; + cam->GetModelviewMatrix().getValue(mvmat); + double pmat[16] = {0}; + cam->GetProjectionMatrix().getValue(pmat); + + dbvt_culling = m_physicsEnvironment->cullingTest(PhysicsCullingCallback,&info,planes,5,m_dbvt_occlusion_res, + KX_GetActiveEngine()->GetCanvas()->GetViewPort(), + mvmat, pmat); } if (!dbvt_culling) { // the physics engine couldn't help us, do it the hard way @@ -1610,8 +1635,8 @@ RAS_MaterialBucket* KX_Scene::FindBucket(class RAS_IPolyMaterial* polymat, bool void KX_Scene::RenderBuckets(const MT_Transform & cameratransform, - class RAS_IRasterizer* rasty, - class RAS_IRenderTools* rendertools) + class RAS_IRasterizer* rasty, + class RAS_IRenderTools* rendertools) { m_bucketmanager->Renderbuckets(cameratransform,rasty,rendertools); KX_BlenderMaterial::EndFrame(); @@ -1634,16 +1659,17 @@ void KX_Scene::UpdateObjectActivity(void) * Manhattan distance. */ MT_Point3 obpos = ob->NodeGetWorldPosition(); - if ( (fabs(camloc[0] - obpos[0]) > m_activity_box_radius) - || (fabs(camloc[1] - obpos[1]) > m_activity_box_radius) - || (fabs(camloc[2] - obpos[2]) > m_activity_box_radius) ) - { + if ((fabs(camloc[0] - obpos[0]) > m_activity_box_radius) || + (fabs(camloc[1] - obpos[1]) > m_activity_box_radius) || + (fabs(camloc[2] - obpos[2]) > m_activity_box_radius) ) + { ob->Suspend(); - } else { + } + else { ob->Resume(); } } - } + } } } @@ -1944,15 +1970,15 @@ void KX_Scene::Render2DFilters(RAS_ICanvas* canvas) #ifdef WITH_PYTHON -void KX_Scene::RunDrawingCallbacks(PyObject* cb_list) +void KX_Scene::RunDrawingCallbacks(PyObject *cb_list) { Py_ssize_t len; if (cb_list && (len=PyList_GET_SIZE(cb_list))) { - PyObject* args= PyTuple_New(0); // save python creating each call - PyObject* func; - PyObject* ret; + PyObject *args = PyTuple_New(0); // save python creating each call + PyObject *func; + PyObject *ret; // Iterate the list and run the callbacks for (Py_ssize_t pos=0; pos < len; pos++) @@ -2017,11 +2043,11 @@ PyMethodDef KX_Scene::Methods[] = { }; static PyObject *Map_GetItem(PyObject *self_v, PyObject *item) { - KX_Scene* self= static_castBGE_PROXY_REF(self_v); + KX_Scene* self = static_castBGE_PROXY_REF(self_v); const char *attr_str= _PyUnicode_AsString(item); - PyObject* pyconvert; + PyObject *pyconvert; - if (self==NULL) { + if (self == NULL) { PyErr_SetString(PyExc_SystemError, "val = scene[key]: KX_Scene, "BGE_PROXY_ERROR_MSG); return NULL; } @@ -2043,12 +2069,12 @@ static PyObject *Map_GetItem(PyObject *self_v, PyObject *item) static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) { - KX_Scene* self= static_castBGE_PROXY_REF(self_v); + KX_Scene* self = static_castBGE_PROXY_REF(self_v); const char *attr_str= _PyUnicode_AsString(key); if (attr_str==NULL) PyErr_Clear(); - if (self==NULL) { + if (self == NULL) { PyErr_SetString(PyExc_SystemError, "scene[key] = value: KX_Scene, "BGE_PROXY_ERROR_MSG); return -1; } @@ -2090,9 +2116,9 @@ static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) static int Seq_Contains(PyObject *self_v, PyObject *value) { - KX_Scene* self= static_castBGE_PROXY_REF(self_v); + KX_Scene* self = static_castBGE_PROXY_REF(self_v); - if (self==NULL) { + if (self == NULL) { PyErr_SetString(PyExc_SystemError, "val in scene: KX_Scene, "BGE_PROXY_ERROR_MSG); return -1; } @@ -2104,56 +2130,56 @@ static int Seq_Contains(PyObject *self_v, PyObject *value) } PyMappingMethods KX_Scene::Mapping = { - (lenfunc)NULL , /*inquiry mp_length */ - (binaryfunc)Map_GetItem, /*binaryfunc mp_subscript */ - (objobjargproc)Map_SetItem, /*objobjargproc mp_ass_subscript */ + (lenfunc)NULL, /* inquiry mp_length */ + (binaryfunc)Map_GetItem, /* binaryfunc mp_subscript */ + (objobjargproc)Map_SetItem, /* objobjargproc mp_ass_subscript */ }; PySequenceMethods KX_Scene::Sequence = { - NULL, /* Cant set the len otherwise it can evaluate as false */ - NULL, /* sq_concat */ - NULL, /* sq_repeat */ - NULL, /* sq_item */ - NULL, /* sq_slice */ - NULL, /* sq_ass_item */ - NULL, /* sq_ass_slice */ - (objobjproc)Seq_Contains, /* sq_contains */ - (binaryfunc) NULL, /* sq_inplace_concat */ - (ssizeargfunc) NULL, /* sq_inplace_repeat */ + NULL, /* Cant set the len otherwise it can evaluate as false */ + NULL, /* sq_concat */ + NULL, /* sq_repeat */ + NULL, /* sq_item */ + NULL, /* sq_slice */ + NULL, /* sq_ass_item */ + NULL, /* sq_ass_slice */ + (objobjproc)Seq_Contains, /* sq_contains */ + (binaryfunc) NULL, /* sq_inplace_concat */ + (ssizeargfunc) NULL, /* sq_inplace_repeat */ }; -PyObject* KX_Scene::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Scene::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_Scene* self= static_cast(self_v); + KX_Scene* self = static_cast(self_v); return PyUnicode_From_STR_String(self->GetName()); } -PyObject* KX_Scene::pyattr_get_objects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Scene::pyattr_get_objects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_Scene* self= static_cast(self_v); + KX_Scene* self = static_cast(self_v); return self->GetObjectList()->GetProxy(); } -PyObject* KX_Scene::pyattr_get_objects_inactive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Scene::pyattr_get_objects_inactive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_Scene* self= static_cast(self_v); + KX_Scene* self = static_cast(self_v); return self->GetInactiveList()->GetProxy(); } -PyObject* KX_Scene::pyattr_get_lights(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Scene::pyattr_get_lights(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_Scene* self= static_cast(self_v); + KX_Scene* self = static_cast(self_v); return self->GetLightList()->GetProxy(); } -PyObject* KX_Scene::pyattr_get_cameras(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Scene::pyattr_get_cameras(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { /* With refcounts in this case... * the new CListValue is owned by python, so its possible python holds onto it longer then the BGE * however this is the same with "scene.objects + []", when you make a copy by adding lists. */ - KX_Scene* self= static_cast(self_v); + KX_Scene* self = static_cast(self_v); CListValue* clist = new CListValue(); /* return self->GetCameras()->GetProxy(); */ @@ -2167,9 +2193,9 @@ PyObject* KX_Scene::pyattr_get_cameras(void *self_v, const KX_PYATTRIBUTE_DEF *a return clist->NewProxy(true); } -PyObject* KX_Scene::pyattr_get_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Scene::pyattr_get_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_Scene* self= static_cast(self_v); + KX_Scene* self = static_cast(self_v); KX_Camera* cam= self->GetActiveCamera(); if (cam) return self->GetActiveCamera()->GetProxy(); @@ -2180,7 +2206,7 @@ PyObject* KX_Scene::pyattr_get_active_camera(void *self_v, const KX_PYATTRIBUTE_ int KX_Scene::pyattr_set_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_Scene* self= static_cast(self_v); + KX_Scene* self = static_cast(self_v); KX_Camera *camOb; if (!ConvertPythonToCamera(value, &camOb, false, "scene.active_camera = value: KX_Scene")) @@ -2190,7 +2216,7 @@ int KX_Scene::pyattr_set_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *a return PY_SET_ATTR_SUCCESS; } -PyObject* KX_Scene::pyattr_get_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Scene::pyattr_get_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_Scene* self = static_cast(self_v); @@ -2200,7 +2226,7 @@ PyObject* KX_Scene::pyattr_get_drawing_callback_pre(void *self_v, const KX_PYATT return self->m_draw_call_pre; } -PyObject* KX_Scene::pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_Scene::pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_Scene* self = static_cast(self_v); @@ -2354,8 +2380,8 @@ KX_PYMETHODDEF_DOC(KX_Scene, drawObstacleSimulation, KX_PYMETHODDEF_DOC(KX_Scene, get, "") { PyObject *key; - PyObject* def = Py_None; - PyObject* ret; + PyObject *def = Py_None; + PyObject *ret; if (!PyArg_ParseTuple(args, "O|O:get", &key, &def)) return NULL; diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index f8480753395..c2e468e6da6 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -237,7 +237,7 @@ protected: /** * The execution priority of replicated object actuators? - */ + */ int m_ueberExecutionPriority; /** @@ -295,7 +295,7 @@ protected: KX_ObstacleSimulation* m_obstacleSimulation; -public: +public: KX_Scene(class SCA_IInputDevice* keyboarddevice, class SCA_IInputDevice* mousedevice, class NG_NetworkDeviceInterface* ndi, @@ -303,7 +303,7 @@ public: struct Scene* scene, class RAS_ICanvas* canvas); - virtual + virtual ~KX_Scene(); RAS_BucketManager* GetBucketManager(); @@ -349,11 +349,11 @@ public: void LogicUpdateFrame(double curtime, bool frame); void UpdateAnimations(double curtime); - void + void LogicEndFrame( ); - CListValue* + CListValue* GetTempObjectList( ); @@ -361,23 +361,23 @@ public: GetObjectList( ); - CListValue* + CListValue* GetInactiveList( ); - CListValue* + CListValue* GetRootParentList( ); - CListValue* + CListValue* GetLightList( ); - SCA_LogicManager* + SCA_LogicManager * GetLogicManager( ); - SCA_TimeEventManager* + SCA_TimeEventManager * GetTimeEventManager( ); @@ -426,7 +426,7 @@ public: ); /** Find the currently active camera. */ - KX_Camera* + KX_Camera* GetActiveCamera( ); @@ -435,7 +435,7 @@ public: * camera is not present in the camera list, it will be added */ - void + void SetActiveCamera( class KX_Camera* ); @@ -453,7 +453,7 @@ public: * Activates new desired canvas width set at design time. * \param width The new desired width. */ - void + void SetCanvasDesignWidth( unsigned int width ); @@ -461,7 +461,7 @@ public: * Activates new desired canvas height set at design time. * \param width The new desired height. */ - void + void SetCanvasDesignHeight( unsigned int height ); @@ -469,7 +469,7 @@ public: * Returns the current desired canvas width set at design time. * \return The desired width. */ - unsigned int + unsigned int GetCanvasDesignWidth( void ) const; @@ -478,7 +478,7 @@ public: * Returns the current desired canvas height set at design time. * \return The desired height. */ - unsigned int + unsigned int GetCanvasDesignHeight( void ) const; @@ -617,7 +617,7 @@ public: static PyObject* pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_drawing_callback_post(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); - virtual PyObject* py_repr(void) { return PyUnicode_From_STR_String(GetName()); } + virtual PyObject *py_repr(void) { return PyUnicode_From_STR_String(GetName()); } /* getitem/setitem */ static PyMappingMethods Mapping; @@ -626,10 +626,10 @@ public: /** * Run the registered python drawing functions. */ - void RunDrawingCallbacks(PyObject* cb_list); + void RunDrawingCallbacks(PyObject *cb_list); - PyObject* GetPreDrawCB() { return m_draw_call_pre; } - PyObject* GetPostDrawCB() { return m_draw_call_post; } + PyObject *GetPreDrawCB() { return m_draw_call_pre; } + PyObject *GetPostDrawCB() { return m_draw_call_post; } #endif /** @@ -665,5 +665,4 @@ public: typedef std::vector KX_SceneList; -#endif //__KX_SCENE_H__ - +#endif /* __KX_SCENE_H__ */ diff --git a/source/gameengine/Ketsji/KX_SceneActuator.cpp b/source/gameengine/Ketsji/KX_SceneActuator.cpp index 781c1fdab87..83b57dee7c1 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.cpp +++ b/source/gameengine/Ketsji/KX_SceneActuator.cpp @@ -256,7 +256,7 @@ PyAttributeDef KX_SceneActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_SceneActuator::pyattr_get_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_SceneActuator::pyattr_get_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SceneActuator* actuator = static_cast(self); if (!actuator->m_camera) @@ -279,7 +279,7 @@ int KX_SceneActuator::pyattr_set_camera(void *self, const struct KX_PYATTRIBUTE_ if (camOb==NULL) { actuator->m_camera= NULL; } - else { + else { actuator->m_camera = camOb; actuator->m_camera->RegisterActuator(actuator); } diff --git a/source/gameengine/Ketsji/KX_SceneActuator.h b/source/gameengine/Ketsji/KX_SceneActuator.h index 8e157544e2e..389e9208ef3 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.h +++ b/source/gameengine/Ketsji/KX_SceneActuator.h @@ -99,12 +99,11 @@ class KX_SceneActuator : public SCA_IActuator /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - static PyObject* pyattr_get_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; /* end of class KXSceneActuator */ #endif - diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index db91cea9074..f76f94aa81d 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -325,15 +325,14 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, startSound, "startSound()\n" "\tStarts the sound.\n") { - switch(m_handle.isNull() ? AUD_STATUS_INVALID : m_handle->getStatus()) - { - case AUD_STATUS_PLAYING: - break; - case AUD_STATUS_PAUSED: - m_handle->resume(); - break; - default: - play(); + switch (m_handle.isNull() ? AUD_STATUS_INVALID : m_handle->getStatus()) { + case AUD_STATUS_PLAYING: + break; + case AUD_STATUS_PAUSED: + m_handle->resume(); + break; + default: + play(); } Py_RETURN_NONE; } @@ -358,7 +357,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, stopSound, } /* Atribute setting and getting -------------------------------------------- */ -PyObject* KX_SoundActuator::pyattr_get_3d_property(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_SoundActuator::pyattr_get_3d_property(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SoundActuator * actuator = static_cast (self); const char* prop = attrdef->m_name; @@ -392,11 +391,11 @@ PyObject* KX_SoundActuator::pyattr_get_3d_property(void *self, const struct KX_P Py_RETURN_NONE; } - PyObject* result = PyFloat_FromDouble(result_value); + PyObject *result = PyFloat_FromDouble(result_value); return result; } -PyObject* KX_SoundActuator::pyattr_get_audposition(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_SoundActuator::pyattr_get_audposition(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SoundActuator * actuator = static_cast (self); float position = 0.0; @@ -404,32 +403,32 @@ PyObject* KX_SoundActuator::pyattr_get_audposition(void *self, const struct KX_P if (!actuator->m_handle.isNull()) position = actuator->m_handle->getPosition(); - PyObject* result = PyFloat_FromDouble(position); + PyObject *result = PyFloat_FromDouble(position); return result; } -PyObject* KX_SoundActuator::pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_SoundActuator::pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SoundActuator * actuator = static_cast (self); float gain = actuator->m_volume; - PyObject* result = PyFloat_FromDouble(gain); + PyObject *result = PyFloat_FromDouble(gain); return result; } -PyObject* KX_SoundActuator::pyattr_get_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_SoundActuator::pyattr_get_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SoundActuator * actuator = static_cast (self); float pitch = actuator->m_pitch; - PyObject* result = PyFloat_FromDouble(pitch); + PyObject *result = PyFloat_FromDouble(pitch); return result; } -PyObject* KX_SoundActuator::pyattr_get_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_SoundActuator::pyattr_get_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SoundActuator * actuator = static_cast (self); if (!actuator->m_sound.isNull()) @@ -542,7 +541,7 @@ int KX_SoundActuator::pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_D int KX_SoundActuator::pyattr_set_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - PyObject* sound = NULL; + PyObject *sound = NULL; KX_SoundActuator * actuator = static_cast (self); if (!PyArg_Parse(value, "O", &sound)) return PY_SET_ATTR_FAIL; diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h index dbdb17d0da5..1ce44e942e8 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.h +++ b/source/gameengine/Ketsji/KX_SoundActuator.h @@ -115,16 +115,15 @@ public: static int pyattr_set_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_set_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); - static PyObject* pyattr_get_3d_property(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_audposition(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_3d_property(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_audposition(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; -#endif //__KX_SOUNDACTUATOR_H__ - +#endif /* __KX_SOUNDACTUATOR_H__ */ diff --git a/source/gameengine/Ketsji/KX_SteeringActuator.cpp b/source/gameengine/Ketsji/KX_SteeringActuator.cpp index 16b9285386a..2fa72c04a20 100644 --- a/source/gameengine/Ketsji/KX_SteeringActuator.cpp +++ b/source/gameengine/Ketsji/KX_SteeringActuator.cpp @@ -253,7 +253,7 @@ bool KX_SteeringActuator::Update(double curtime, bool frame) static const MT_Vector3 PATH_COLOR(1,0,0); m_navmesh->DrawPath(m_path, m_pathLen, PATH_COLOR); } - } + } } break; @@ -285,7 +285,7 @@ bool KX_SteeringActuator::Update(double curtime, bool frame) //temporary solution: set 2D steering velocity directly to obj //correct way is to apply physical force MT_Vector3 curvel = obj->GetLinearVelocity(); - newvel.z() = curvel.z(); + newvel.z() = curvel.z(); obj->setLinearVelocity(newvel, false); } else @@ -356,8 +356,8 @@ static bool getNavmeshNormal(dtStatNavMesh* navmesh, const MT_Vector3& pos, MT_V { static const float polyPickExt[3] = {2, 4, 2}; float spos[3]; - pos.getValue(spos); - flipAxes(spos); + pos.getValue(spos); + flipAxes(spos); dtStatPolyRef sPolyRef = navmesh->findNearestPoly(spos, polyPickExt); if (sPolyRef == 0) return false; @@ -382,7 +382,7 @@ static bool getNavmeshNormal(dtStatNavMesh* navmesh, const MT_Vector3& pos, MT_V { distMin = dist; idxMin = i; - } + } } if (idxMin>=0) @@ -416,7 +416,7 @@ void KX_SteeringActuator::HandleActorFace(MT_Vector3& velocity) KX_GameObject* curobj = (KX_GameObject*) GetParent(); MT_Vector3 dir = m_facingMode==0 ? curobj->NodeGetLocalOrientation().getColumn(1) : velocity; if (dir.fuzzyZero()) - return; + return; dir.normalize(); MT_Vector3 up(0,0,1); MT_Vector3 left; @@ -431,7 +431,7 @@ void KX_SteeringActuator::HandleActorFace(MT_Vector3& velocity) { left = (dir.cross(up)).safe_normalized(); - dir = (-left.cross(normal)).safe_normalized(); + dir = (-left.cross(normal)).safe_normalized(); up = normal; } } @@ -495,7 +495,7 @@ void KX_SteeringActuator::HandleActorFace(MT_Vector3& velocity) MT_Point3 localpos; localpos = curobj->GetSGNode()->GetLocalPosition(); MT_Matrix3x3 parentmatinv; - parentmatinv = parentObject->NodeGetWorldOrientation ().inverse (); + parentmatinv = parentObject->NodeGetWorldOrientation ().inverse (); mat = parentmatinv * mat; mat = m_parentlocalmat * mat; curobj->NodeSetLocalOrientation(mat); @@ -551,16 +551,16 @@ PyAttributeDef KX_SteeringActuator::Attributes[] = { KX_PYATTRIBUTE_FLOAT_RW("turnspeed", 0.0f, 720.0f, KX_SteeringActuator, m_turnspeed), KX_PYATTRIBUTE_BOOL_RW("selfterminated", KX_SteeringActuator, m_isSelfTerminated), KX_PYATTRIBUTE_BOOL_RW("enableVisualization", KX_SteeringActuator, m_enableVisualization), - KX_PYATTRIBUTE_RO_FUNCTION("steeringVec", KX_SteeringActuator, pyattr_get_steeringVec), + KX_PYATTRIBUTE_RO_FUNCTION("steeringVec", KX_SteeringActuator, pyattr_get_steeringVec), KX_PYATTRIBUTE_SHORT_RW("facingMode", 0, 6, true, KX_SteeringActuator, m_facingMode), KX_PYATTRIBUTE_INT_RW("pathUpdatePeriod", -1, 100000, true, KX_SteeringActuator, m_pathUpdatePeriod), { NULL } //Sentinel }; -PyObject* KX_SteeringActuator::pyattr_get_target(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_SteeringActuator::pyattr_get_target(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SteeringActuator* actuator = static_cast(self); - if (!actuator->m_target) + if (!actuator->m_target) Py_RETURN_NONE; else return actuator->m_target->GetProxy(); @@ -575,7 +575,7 @@ int KX_SteeringActuator::pyattr_set_target(void *self, const struct KX_PYATTRIBU return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error if (actuator->m_target != NULL) - actuator->m_target->UnregisterActuator(actuator); + actuator->m_target->UnregisterActuator(actuator); actuator->m_target = (KX_GameObject*) gameobj; @@ -585,10 +585,10 @@ int KX_SteeringActuator::pyattr_set_target(void *self, const struct KX_PYATTRIBU return PY_SET_ATTR_SUCCESS; } -PyObject* KX_SteeringActuator::pyattr_get_navmesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_SteeringActuator::pyattr_get_navmesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SteeringActuator* actuator = static_cast(self); - if (!actuator->m_navmesh) + if (!actuator->m_navmesh) Py_RETURN_NONE; else return actuator->m_navmesh->GetProxy(); @@ -609,7 +609,7 @@ int KX_SteeringActuator::pyattr_set_navmesh(void *self, const struct KX_PYATTRIB } if (actuator->m_navmesh != NULL) - actuator->m_navmesh->UnregisterActuator(actuator); + actuator->m_navmesh->UnregisterActuator(actuator); actuator->m_navmesh = static_cast(gameobj); @@ -619,7 +619,7 @@ int KX_SteeringActuator::pyattr_set_navmesh(void *self, const struct KX_PYATTRIB return PY_SET_ATTR_SUCCESS; } -PyObject* KX_SteeringActuator::pyattr_get_steeringVec(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_SteeringActuator::pyattr_get_steeringVec(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SteeringActuator* actuator = static_cast(self); const MT_Vector3& steeringVec = actuator->GetSteeringVec(); diff --git a/source/gameengine/Ketsji/KX_SteeringActuator.h b/source/gameengine/Ketsji/KX_SteeringActuator.h index c22a636cd95..1e8ac9a54f0 100644 --- a/source/gameengine/Ketsji/KX_SteeringActuator.h +++ b/source/gameengine/Ketsji/KX_SteeringActuator.h @@ -82,7 +82,7 @@ public: KX_GameObject *navmesh, float distance, float velocity, - float acceleration, + float acceleration, float turnspeed, bool isSelfTerminated, int pathUpdatePeriod, @@ -107,16 +107,15 @@ public: /* --------------------------------------------------------------------- */ /* These are used to get and set m_target */ - static PyObject* pyattr_get_target(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); - static int pyattr_set_target(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); - static PyObject* pyattr_get_navmesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); - static int pyattr_set_navmesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); - static PyObject* pyattr_get_steeringVec(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_target(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_target(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_navmesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_navmesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_steeringVec(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; /* end of class KX_SteeringActuator : public SCA_PropertyActuator */ -#endif - +#endif /* __KX_STEERINGACTUATOR_H__ */ diff --git a/source/gameengine/Ketsji/KX_TimeCategoryLogger.h b/source/gameengine/Ketsji/KX_TimeCategoryLogger.h index ea780739695..e097454fca7 100644 --- a/source/gameengine/Ketsji/KX_TimeCategoryLogger.h +++ b/source/gameengine/Ketsji/KX_TimeCategoryLogger.h @@ -32,8 +32,8 @@ #ifndef __KX_TIMECATEGORYLOGGER_H__ #define __KX_TIMECATEGORYLOGGER_H__ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable:4786) // suppress stl-MSVC debug info warning +#ifdef _MSC_VER +# pragma warning (disable:4786) /* suppress stl-MSVC debug info warning */ #endif #include @@ -133,5 +133,4 @@ protected: #endif }; -#endif // __KX_TIMECATEGORYLOGGER_H__ - +#endif /* __KX_TIMECATEGORYLOGGER_H__ */ diff --git a/source/gameengine/Ketsji/KX_TimeLogger.h b/source/gameengine/Ketsji/KX_TimeLogger.h index 83c934ea81b..59d7bdc84e3 100644 --- a/source/gameengine/Ketsji/KX_TimeLogger.h +++ b/source/gameengine/Ketsji/KX_TimeLogger.h @@ -32,14 +32,14 @@ #ifndef __KX_TIMELOGGER_H__ #define __KX_TIMELOGGER_H__ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable:4786) // suppress stl-MSVC debug info warning +#ifdef _MSC_VER +# pragma warning (disable:4786) /* suppress stl-MSVC debug info warning */ #endif #include #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif /** @@ -111,5 +111,4 @@ protected: #endif }; -#endif // __KX_TIMELOGGER_H__ - +#endif /* __KX_TIMELOGGER_H__ */ diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.h b/source/gameengine/Ketsji/KX_TouchEventManager.h index d9a0164fd05..63e9d15959e 100644 --- a/source/gameengine/Ketsji/KX_TouchEventManager.h +++ b/source/gameengine/Ketsji/KX_TouchEventManager.h @@ -85,5 +85,4 @@ public: #endif }; -#endif //__KX_TOUCHEVENTMANAGER_H__ - +#endif /* __KX_TOUCHEVENTMANAGER_H__ */ diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index d7bcf1306a1..36e0bf692f1 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -331,9 +331,9 @@ PyAttributeDef KX_TouchSensor::Attributes[] = { /* Python API */ -PyObject* KX_TouchSensor::pyattr_get_object_hit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_TouchSensor::pyattr_get_object_hit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_TouchSensor* self= static_cast(self_v); + KX_TouchSensor* self = static_cast(self_v); if (self->m_hitObject) return self->m_hitObject->GetProxy(); @@ -341,9 +341,9 @@ PyObject* KX_TouchSensor::pyattr_get_object_hit(void *self_v, const KX_PYATTRIBU Py_RETURN_NONE; } -PyObject* KX_TouchSensor::pyattr_get_object_hit_list(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_TouchSensor::pyattr_get_object_hit_list(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_TouchSensor* self= static_cast(self_v); + KX_TouchSensor* self = static_cast(self_v); return self->m_colliders->GetProxy(); } diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h index d739144d70d..6bd606db8eb 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.h +++ b/source/gameengine/Ketsji/KX_TouchSensor.h @@ -56,7 +56,7 @@ protected: /** * The sensor should only look for objects with this property. */ - STR_String m_touchedpropname; + STR_String m_touchedpropname; bool m_bFindMaterial; bool m_bTouchPulse; /* changes in the colliding objects trigger pulses */ @@ -134,5 +134,4 @@ public: }; -#endif //__KX_TOUCHSENSOR_H__ - +#endif /* __KX_TOUCHSENSOR_H__ */ diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index 99732130f83..1597948bafe 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -90,7 +90,7 @@ KX_TrackToActuator::KX_TrackToActuator(SCA_IObject *gameobj, /* old function from Blender */ -MT_Matrix3x3 EulToMat3(float *eul) +static MT_Matrix3x3 EulToMat3(float eul[3]) { MT_Matrix3x3 mat; float ci, cj, ch, si, sj, sh, cc, cs, sc, ss; @@ -122,7 +122,7 @@ MT_Matrix3x3 EulToMat3(float *eul) /* old function from Blender */ -void Mat3ToEulOld(MT_Matrix3x3 mat, float eul[3]) +static void Mat3ToEulOld(MT_Matrix3x3 mat, float eul[3]) { const float cy = sqrtf(mat[0][0] * mat[0][0] + mat[0][1] * mat[0][1]); @@ -141,7 +141,7 @@ void Mat3ToEulOld(MT_Matrix3x3 mat, float eul[3]) /* old function from Blender */ -void compatible_eulFast(float *eul, float *oldrot) +static void compatible_eulFast(float *eul, float *oldrot) { float dx, dy, dz; @@ -164,9 +164,9 @@ void compatible_eulFast(float *eul, float *oldrot) -MT_Matrix3x3 matrix3x3_interpol(MT_Matrix3x3 oldmat, MT_Matrix3x3 mat, int m_time) +static MT_Matrix3x3 matrix3x3_interpol(MT_Matrix3x3 oldmat, MT_Matrix3x3 mat, int m_time) { - float eul[3], oldeul[3]; + float eul[3], oldeul[3]; Mat3ToEulOld(oldmat, oldeul); Mat3ToEulOld(mat, eul); @@ -238,7 +238,7 @@ void KX_TrackToActuator::Relink(CTR_Map *obj_map) bool KX_TrackToActuator::Update(double curtime, bool frame) { - bool result = false; + bool result = false; bool bNegativeEvent = IsNegativeEvent(); RemoveAllEvents(); @@ -395,7 +395,7 @@ bool KX_TrackToActuator::Update(double curtime, bool frame) localpos = curobj->GetSGNode()->GetLocalPosition(); // Get the inverse of the parent matrix MT_Matrix3x3 parentmatinv; - parentmatinv = m_parentobj->NodeGetWorldOrientation ().inverse (); + parentmatinv = m_parentobj->NodeGetWorldOrientation ().inverse (); // transform the local coordinate system into the parents system mat = parentmatinv * mat; // append the initial parent local rotation matrix @@ -458,10 +458,10 @@ PyAttributeDef KX_TrackToActuator::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_TrackToActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_TrackToActuator::pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_TrackToActuator* actuator = static_cast(self); - if (!actuator->m_object) + if (!actuator->m_object) Py_RETURN_NONE; else return actuator->m_object->GetProxy(); @@ -476,7 +476,7 @@ int KX_TrackToActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUT return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error if (actuator->m_object != NULL) - actuator->m_object->UnregisterActuator(actuator); + actuator->m_object->UnregisterActuator(actuator); actuator->m_object = (SCA_IObject*) gameobj; diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.h b/source/gameengine/Ketsji/KX_TrackToActuator.h index fb2ced2a415..f5f5c4c2836 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.h +++ b/source/gameengine/Ketsji/KX_TrackToActuator.h @@ -74,12 +74,11 @@ class KX_TrackToActuator : public SCA_IActuator /* Python part */ /* These are used to get and set m_ob */ - static PyObject* pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); - static int pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ }; /* end of class KX_TrackToActuator : public KX_EditObjectActuator */ -#endif - +#endif /* __KX_TRACKTOACTUATOR_H__ */ diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index 1c03df80dc1..b5d6f11a2d5 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -34,11 +34,11 @@ KX_VehicleWrapper::~KX_VehicleWrapper() #ifdef WITH_PYTHON -PyObject* KX_VehicleWrapper::PyAddWheel(PyObject* args) +PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args) { - PyObject* pylistPos,*pylistDir,*pylistAxleDir; - PyObject* wheelGameObject; + PyObject *pylistPos,*pylistDir,*pylistAxleDir; + PyObject *wheelGameObject; float suspensionRestLength,wheelRadius; int hasSteering; @@ -83,7 +83,7 @@ PyObject* KX_VehicleWrapper::PyAddWheel(PyObject* args) -PyObject* KX_VehicleWrapper::PyGetWheelPosition(PyObject* args) +PyObject *KX_VehicleWrapper::PyGetWheelPosition(PyObject *args) { int wheelIndex; @@ -98,7 +98,7 @@ PyObject* KX_VehicleWrapper::PyGetWheelPosition(PyObject* args) return NULL; } -PyObject* KX_VehicleWrapper::PyGetWheelRotation(PyObject* args) +PyObject *KX_VehicleWrapper::PyGetWheelRotation(PyObject *args) { int wheelIndex; if (PyArg_ParseTuple(args,"i:getWheelRotation",&wheelIndex)) @@ -108,7 +108,7 @@ PyObject* KX_VehicleWrapper::PyGetWheelRotation(PyObject* args) return NULL; } -PyObject* KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject* args) +PyObject *KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject *args) { int wheelIndex; if (PyArg_ParseTuple(args,"i:getWheelOrientationQuaternion",&wheelIndex)) @@ -124,20 +124,20 @@ PyObject* KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject* args) } -PyObject* KX_VehicleWrapper::PyGetNumWheels(PyObject* args) +PyObject *KX_VehicleWrapper::PyGetNumWheels(PyObject *args) { return PyLong_FromSsize_t(m_vehicle->GetNumWheels()); } -PyObject* KX_VehicleWrapper::PyGetConstraintId(PyObject* args) +PyObject *KX_VehicleWrapper::PyGetConstraintId(PyObject *args) { return PyLong_FromSsize_t(m_vehicle->GetUserConstraintId()); } -PyObject* KX_VehicleWrapper::PyApplyEngineForce(PyObject* args) +PyObject *KX_VehicleWrapper::PyApplyEngineForce(PyObject *args) { float force; int wheelIndex; @@ -153,7 +153,7 @@ PyObject* KX_VehicleWrapper::PyApplyEngineForce(PyObject* args) Py_RETURN_NONE; } -PyObject* KX_VehicleWrapper::PySetTyreFriction(PyObject* args) +PyObject *KX_VehicleWrapper::PySetTyreFriction(PyObject *args) { float wheelFriction; int wheelIndex; @@ -168,7 +168,7 @@ PyObject* KX_VehicleWrapper::PySetTyreFriction(PyObject* args) Py_RETURN_NONE; } -PyObject* KX_VehicleWrapper::PySetSuspensionStiffness(PyObject* args) +PyObject *KX_VehicleWrapper::PySetSuspensionStiffness(PyObject *args) { float suspensionStiffness; int wheelIndex; @@ -183,7 +183,7 @@ PyObject* KX_VehicleWrapper::PySetSuspensionStiffness(PyObject* args) Py_RETURN_NONE; } -PyObject* KX_VehicleWrapper::PySetSuspensionDamping(PyObject* args) +PyObject *KX_VehicleWrapper::PySetSuspensionDamping(PyObject *args) { float suspensionDamping; int wheelIndex; @@ -197,7 +197,7 @@ PyObject* KX_VehicleWrapper::PySetSuspensionDamping(PyObject* args) Py_RETURN_NONE; } -PyObject* KX_VehicleWrapper::PySetSuspensionCompression(PyObject* args) +PyObject *KX_VehicleWrapper::PySetSuspensionCompression(PyObject *args) { float suspensionCompression; int wheelIndex; @@ -211,7 +211,7 @@ PyObject* KX_VehicleWrapper::PySetSuspensionCompression(PyObject* args) Py_RETURN_NONE; } -PyObject* KX_VehicleWrapper::PySetRollInfluence(PyObject* args) +PyObject *KX_VehicleWrapper::PySetRollInfluence(PyObject *args) { float rollInfluence; int wheelIndex; @@ -227,7 +227,7 @@ PyObject* KX_VehicleWrapper::PySetRollInfluence(PyObject* args) } -PyObject* KX_VehicleWrapper::PyApplyBraking(PyObject* args) +PyObject *KX_VehicleWrapper::PyApplyBraking(PyObject *args) { float braking; int wheelIndex; @@ -245,7 +245,7 @@ PyObject* KX_VehicleWrapper::PyApplyBraking(PyObject* args) -PyObject* KX_VehicleWrapper::PySetSteeringValue(PyObject* args) +PyObject *KX_VehicleWrapper::PySetSteeringValue(PyObject *args) { float steeringValue; int wheelIndex; @@ -261,7 +261,7 @@ PyObject* KX_VehicleWrapper::PySetSteeringValue(PyObject* args) } -PyObject* KX_VehicleWrapper::PyGetConstraintType(PyObject* args) +PyObject *KX_VehicleWrapper::PyGetConstraintType(PyObject *args) { return PyLong_FromSsize_t(m_vehicle->GetUserConstraintType()); } diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.h b/source/gameengine/Ketsji/KX_VehicleWrapper.h index 3684019277c..ccd666e84f3 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.h +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.h @@ -52,11 +52,11 @@ public: KX_PYMETHOD_VARARGS(KX_VehicleWrapper,SetSuspensionCompression); KX_PYMETHOD_VARARGS(KX_VehicleWrapper,SetRollInfluence); -#endif // WITH_PYTHON +#endif /* WITH_PYTHON */ private: PHY_IVehicle* m_vehicle; PHY_IPhysicsEnvironment* m_physenv; }; -#endif //__KX_VEHICLEWRAPPER_H__ +#endif /* __KX_VEHICLEWRAPPER_H__ */ diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index d489c015273..dabb79b357d 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -101,102 +101,102 @@ PyAttributeDef KX_VertexProxy::Attributes[] = { { NULL } //Sentinel }; -PyObject* KX_VertexProxy::pyattr_get_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_VertexProxy::pyattr_get_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); return PyFloat_FromDouble(self->m_vertex->getXYZ()[0]); } -PyObject* KX_VertexProxy::pyattr_get_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_VertexProxy::pyattr_get_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); return PyFloat_FromDouble(self->m_vertex->getXYZ()[1]); } -PyObject* KX_VertexProxy::pyattr_get_z(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_VertexProxy::pyattr_get_z(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); return PyFloat_FromDouble(self->m_vertex->getXYZ()[2]); } -PyObject* KX_VertexProxy::pyattr_get_r(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_VertexProxy::pyattr_get_r(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); return PyFloat_FromDouble(self->m_vertex->getRGBA()[0]/255.0); } -PyObject* KX_VertexProxy::pyattr_get_g(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_VertexProxy::pyattr_get_g(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); return PyFloat_FromDouble(self->m_vertex->getRGBA()[1]/255.0); } -PyObject* KX_VertexProxy::pyattr_get_b(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_VertexProxy::pyattr_get_b(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); return PyFloat_FromDouble(self->m_vertex->getRGBA()[2]/255.0); } -PyObject* KX_VertexProxy::pyattr_get_a(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_VertexProxy::pyattr_get_a(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); return PyFloat_FromDouble(self->m_vertex->getRGBA()[3]/255.0); } -PyObject* KX_VertexProxy::pyattr_get_u(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_VertexProxy::pyattr_get_u(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); return PyFloat_FromDouble(self->m_vertex->getUV1()[0]); } -PyObject* KX_VertexProxy::pyattr_get_v(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_VertexProxy::pyattr_get_v(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); return PyFloat_FromDouble(self->m_vertex->getUV1()[1]); } -PyObject* KX_VertexProxy::pyattr_get_u2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_VertexProxy::pyattr_get_u2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); return PyFloat_FromDouble(self->m_vertex->getUV2()[0]); } -PyObject* KX_VertexProxy::pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_VertexProxy::pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); return PyFloat_FromDouble(self->m_vertex->getUV2()[1]); } -PyObject* KX_VertexProxy::pyattr_get_XYZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_VertexProxy::pyattr_get_XYZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); return PyObjectFrom(MT_Vector3(self->m_vertex->getXYZ())); } -PyObject* KX_VertexProxy::pyattr_get_UV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_VertexProxy::pyattr_get_UV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); return PyObjectFrom(MT_Point2(self->m_vertex->getUV1())); } -PyObject* KX_VertexProxy::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_VertexProxy::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); const unsigned char *colp = self->m_vertex->getRGBA(); MT_Vector4 color(colp[0], colp[1], colp[2], colp[3]); color /= 255.0; return PyObjectFrom(color); } -PyObject* KX_VertexProxy::pyattr_get_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_VertexProxy::pyattr_get_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); return PyObjectFrom(MT_Vector3(self->m_vertex->getNormal())); } int KX_VertexProxy::pyattr_set_x(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); @@ -211,7 +211,7 @@ int KX_VertexProxy::pyattr_set_x(void *self_v, const struct KX_PYATTRIBUTE_DEF * int KX_VertexProxy::pyattr_set_y(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); @@ -226,7 +226,7 @@ int KX_VertexProxy::pyattr_set_y(void *self_v, const struct KX_PYATTRIBUTE_DEF * int KX_VertexProxy::pyattr_set_z(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); @@ -241,7 +241,7 @@ int KX_VertexProxy::pyattr_set_z(void *self_v, const struct KX_PYATTRIBUTE_DEF * int KX_VertexProxy::pyattr_set_u(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); @@ -256,7 +256,7 @@ int KX_VertexProxy::pyattr_set_u(void *self_v, const struct KX_PYATTRIBUTE_DEF * int KX_VertexProxy::pyattr_set_v(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); @@ -271,7 +271,7 @@ int KX_VertexProxy::pyattr_set_v(void *self_v, const struct KX_PYATTRIBUTE_DEF * int KX_VertexProxy::pyattr_set_u2(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); @@ -286,7 +286,7 @@ int KX_VertexProxy::pyattr_set_u2(void *self_v, const struct KX_PYATTRIBUTE_DEF int KX_VertexProxy::pyattr_set_v2(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); @@ -301,7 +301,7 @@ int KX_VertexProxy::pyattr_set_v2(void *self_v, const struct KX_PYATTRIBUTE_DEF int KX_VertexProxy::pyattr_set_r(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); @@ -318,7 +318,7 @@ int KX_VertexProxy::pyattr_set_r(void *self_v, const struct KX_PYATTRIBUTE_DEF * int KX_VertexProxy::pyattr_set_g(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); @@ -335,7 +335,7 @@ int KX_VertexProxy::pyattr_set_g(void *self_v, const struct KX_PYATTRIBUTE_DEF * int KX_VertexProxy::pyattr_set_b(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); @@ -352,7 +352,7 @@ int KX_VertexProxy::pyattr_set_b(void *self_v, const struct KX_PYATTRIBUTE_DEF * int KX_VertexProxy::pyattr_set_a(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); if (PyFloat_Check(value)) { float val = PyFloat_AsDouble(value); @@ -369,7 +369,7 @@ int KX_VertexProxy::pyattr_set_a(void *self_v, const struct KX_PYATTRIBUTE_DEF * int KX_VertexProxy::pyattr_set_XYZ(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); if (PySequence_Check(value)) { MT_Point3 vec; @@ -385,7 +385,7 @@ int KX_VertexProxy::pyattr_set_XYZ(void *self_v, const struct KX_PYATTRIBUTE_DEF int KX_VertexProxy::pyattr_set_UV(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); if (PySequence_Check(value)) { MT_Point2 vec; @@ -401,7 +401,7 @@ int KX_VertexProxy::pyattr_set_UV(void *self_v, const struct KX_PYATTRIBUTE_DEF int KX_VertexProxy::pyattr_set_color(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); if (PySequence_Check(value)) { MT_Vector4 vec; @@ -417,7 +417,7 @@ int KX_VertexProxy::pyattr_set_color(void *self_v, const struct KX_PYATTRIBUTE_D int KX_VertexProxy::pyattr_set_normal(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_VertexProxy* self= static_cast(self_v); + KX_VertexProxy* self = static_cast(self_v); if (PySequence_Check(value)) { MT_Vector3 vec; @@ -459,12 +459,12 @@ CValue* KX_VertexProxy::GetReplica() { return NULL;} // stuff for python integration -PyObject* KX_VertexProxy::PyGetXYZ() +PyObject *KX_VertexProxy::PyGetXYZ() { return PyObjectFrom(MT_Point3(m_vertex->getXYZ())); } -PyObject* KX_VertexProxy::PySetXYZ(PyObject* value) +PyObject *KX_VertexProxy::PySetXYZ(PyObject *value) { MT_Point3 vec; if (!PyVecTo(value, vec)) @@ -475,12 +475,12 @@ PyObject* KX_VertexProxy::PySetXYZ(PyObject* value) Py_RETURN_NONE; } -PyObject* KX_VertexProxy::PyGetNormal() +PyObject *KX_VertexProxy::PyGetNormal() { return PyObjectFrom(MT_Vector3(m_vertex->getNormal())); } -PyObject* KX_VertexProxy::PySetNormal(PyObject* value) +PyObject *KX_VertexProxy::PySetNormal(PyObject *value) { MT_Vector3 vec; if (!PyVecTo(value, vec)) @@ -492,13 +492,13 @@ PyObject* KX_VertexProxy::PySetNormal(PyObject* value) } -PyObject* KX_VertexProxy::PyGetRGBA() +PyObject *KX_VertexProxy::PyGetRGBA() { int *rgba = (int *) m_vertex->getRGBA(); return PyLong_FromSsize_t(*rgba); } -PyObject* KX_VertexProxy::PySetRGBA(PyObject* value) +PyObject *KX_VertexProxy::PySetRGBA(PyObject *value) { if (PyLong_Check(value)) { int rgba = PyLong_AsSsize_t(value); @@ -521,12 +521,12 @@ PyObject* KX_VertexProxy::PySetRGBA(PyObject* value) } -PyObject* KX_VertexProxy::PyGetUV() +PyObject *KX_VertexProxy::PyGetUV() { return PyObjectFrom(MT_Vector2(m_vertex->getUV1())); } -PyObject* KX_VertexProxy::PySetUV(PyObject* value) +PyObject *KX_VertexProxy::PySetUV(PyObject *value) { MT_Point2 vec; if (!PyVecTo(value, vec)) @@ -537,17 +537,17 @@ PyObject* KX_VertexProxy::PySetUV(PyObject* value) Py_RETURN_NONE; } -PyObject* KX_VertexProxy::PyGetUV2() +PyObject *KX_VertexProxy::PyGetUV2() { return PyObjectFrom(MT_Vector2(m_vertex->getUV2())); } -PyObject* KX_VertexProxy::PySetUV2(PyObject* args) +PyObject *KX_VertexProxy::PySetUV2(PyObject *args) { MT_Point2 vec; unsigned int unit= RAS_TexVert::SECOND_UV; - PyObject* list= NULL; + PyObject *list = NULL; if (!PyArg_ParseTuple(args, "O|i:setUV2", &list, &unit)) return NULL; diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h index 3084e5fac93..6e193d35b4c 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.h +++ b/source/gameengine/Ketsji/KX_VertexProxy.h @@ -59,21 +59,21 @@ public: // stuff for python integration - static PyObject* pyattr_get_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_z(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_r(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_g(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_b(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_a(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_u(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_v(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_u2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_XYZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_UV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_z(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_r(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_g(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_b(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_a(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_u(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_v(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_u2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_XYZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_UV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_normal(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_x(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_set_y(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_set_z(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); @@ -105,7 +105,6 @@ public: }; -#endif // WITH_PYTHON - -#endif //__KX_VERTEXPROXY_H__ +#endif /* WITH_PYTHON */ +#endif /* __KX_VERTEXPROXY_H__ */ diff --git a/source/gameengine/Ketsji/KX_WorldInfo.h b/source/gameengine/Ketsji/KX_WorldInfo.h index 5b35ca2ec54..a64ca5c191e 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.h +++ b/source/gameengine/Ketsji/KX_WorldInfo.h @@ -74,5 +74,4 @@ public: #endif }; -#endif //__KX_WORLDINFO_H__ - +#endif /* __KX_WORLDINFO_H__ */ diff --git a/source/gameengine/Ketsji/KX_WorldIpoController.h b/source/gameengine/Ketsji/KX_WorldIpoController.h index 409b1fec321..63983b3129b 100644 --- a/source/gameengine/Ketsji/KX_WorldIpoController.h +++ b/source/gameengine/Ketsji/KX_WorldIpoController.h @@ -72,15 +72,15 @@ public: m_modified = true; } - void SetModifyMistStart(bool modify) { + void SetModifyMistStart(bool modify) { m_modify_mist_start = modify; } - void SetModifyMistColor(bool modify) { + void SetModifyMistColor(bool modify) { m_modify_mist_color = modify; } - void SetModifyMistDist(bool modify) { + void SetModifyMistDist(bool modify) { m_modify_mist_dist = modify; } @@ -100,5 +100,4 @@ public: #endif }; -#endif // __KX_WORLDIPOCONTROLLER_H__ - +#endif /* __KX_WORLDIPOCONTROLLER_H__ */ diff --git a/source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.h b/source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.h index 92ba6100359..7581486c80a 100644 --- a/source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.h +++ b/source/gameengine/Network/LoopBackNetwork/NG_LoopBackNetworkDeviceInterface.h @@ -36,7 +36,7 @@ #include "NG_NetworkDeviceInterface.h" class NG_LoopBackNetworkDeviceInterface : public NG_NetworkDeviceInterface -{ +{ std::deque m_messages[2]; int m_currentQueue; @@ -60,5 +60,4 @@ public: virtual std::vector RetrieveNetworkMessages(); }; -#endif //__NG_LOOPBACKNETWORKDEVICEINTERFACE_H__ - +#endif /* __NG_LOOPBACKNETWORKDEVICEINTERFACE_H__ */ diff --git a/source/gameengine/Network/NG_NetworkDeviceInterface.h b/source/gameengine/Network/NG_NetworkDeviceInterface.h index 8f903cc64fa..48edbdfc7fe 100644 --- a/source/gameengine/Network/NG_NetworkDeviceInterface.h +++ b/source/gameengine/Network/NG_NetworkDeviceInterface.h @@ -79,5 +79,4 @@ public: #endif }; -#endif //__NG_NETWORKDEVICEINTERFACE_H__ - +#endif /* __NG_NETWORKDEVICEINTERFACE_H__ */ diff --git a/source/gameengine/Network/NG_NetworkMessage.h b/source/gameengine/Network/NG_NetworkMessage.h index 25e7fd97596..5185849f8d7 100644 --- a/source/gameengine/Network/NG_NetworkMessage.h +++ b/source/gameengine/Network/NG_NetworkMessage.h @@ -135,5 +135,4 @@ public: #endif }; -#endif //__NG_NETWORKMESSAGE_H__ - +#endif /* __NG_NETWORKMESSAGE_H__ */ diff --git a/source/gameengine/Network/NG_NetworkObject.h b/source/gameengine/Network/NG_NetworkObject.h index b9858cd8d43..54459cad55d 100644 --- a/source/gameengine/Network/NG_NetworkObject.h +++ b/source/gameengine/Network/NG_NetworkObject.h @@ -52,5 +52,4 @@ public: #endif }; -#endif //__NG_NETWORKOBJECT_H__ - +#endif /* __NG_NETWORKOBJECT_H__ */ diff --git a/source/gameengine/Network/NG_NetworkScene.h b/source/gameengine/Network/NG_NetworkScene.h index 41ac8ead5e4..10dad210128 100644 --- a/source/gameengine/Network/NG_NetworkScene.h +++ b/source/gameengine/Network/NG_NetworkScene.h @@ -51,7 +51,7 @@ class NG_NetworkDeviceInterface; class NG_NetworkScene { - class NG_NetworkDeviceInterface *m_networkdevice; + class NG_NetworkDeviceInterface *m_networkdevice; CTR_Map m_networkObjects; // CTR_Maps used as a 'Bloom' filter @@ -107,7 +107,7 @@ protected: * Releases messages for the given message map. * \param map Message map with messages. */ - void ClearMessageMap(TMessageMap& map); + void ClearMessageMap(TMessageMap& map); #ifdef WITH_CXX_GUARDEDALLOC @@ -115,5 +115,4 @@ protected: #endif }; -#endif //__NG_NETWORKSCENE_H__ - +#endif /* __NG_NETWORKSCENE_H__ */ diff --git a/source/gameengine/Physics/Bullet/CMakeLists.txt b/source/gameengine/Physics/Bullet/CMakeLists.txt index cdae3cc5526..43b1bfe7468 100644 --- a/source/gameengine/Physics/Bullet/CMakeLists.txt +++ b/source/gameengine/Physics/Bullet/CMakeLists.txt @@ -37,7 +37,6 @@ set(INC ../../../blender/blenkernel ../../../blender/blenlib ../../../blender/makesdna - ../../../../extern/bullet2/src ../../../../intern/container ../../../../intern/guardedalloc ../../../../intern/moto/include @@ -45,6 +44,7 @@ set(INC ) set(INC_SYS + ../../../../extern/bullet2/src ${GLEW_INCLUDE_PATH} ${PYTHON_INCLUDE_DIRS} ) diff --git a/source/gameengine/Physics/Bullet/CcdGraphicController.h b/source/gameengine/Physics/Bullet/CcdGraphicController.h index 60ff475832b..72eb699ce5b 100644 --- a/source/gameengine/Physics/Bullet/CcdGraphicController.h +++ b/source/gameengine/Physics/Bullet/CcdGraphicController.h @@ -33,7 +33,7 @@ class CcdPhysicsEnvironment; class btCollisionObject; ///CcdGraphicController is a graphic object that supports view frustrum culling and occlusion -class CcdGraphicController : public PHY_IGraphicController +class CcdGraphicController : public PHY_IGraphicController { public: CcdGraphicController(CcdPhysicsEnvironment* phyEnv, PHY_IMotionState* motionState); @@ -87,4 +87,4 @@ private: #endif }; -#endif //BULLET2_PHYSICSCONTROLLER_H +#endif /* BULLET2_PHYSICSCONTROLLER_H */ diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index ed2b9cfcb0b..8d587cf39f6 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -46,9 +46,11 @@ subject to the following restrictions: #include "DNA_meshdata_types.h" extern "C"{ -#include "BKE_cdderivedmesh.h" + #include "BLI_utildefines.h" + #include "BKE_cdderivedmesh.h" } + class BP_Proxy; ///todo: fill all the empty CcdPhysicsController methods, hook them up to the btRigidBody class @@ -215,8 +217,7 @@ bool CcdPhysicsController::CreateSoftbody() btSoftBody* psb = 0; btSoftBodyWorldInfo& worldInfo = m_cci.m_physicsEnv->getDynamicsWorld()->getWorldInfo(); - if (m_cci.m_collisionShape->getShapeType() == CONVEX_HULL_SHAPE_PROXYTYPE) - { + if (m_cci.m_collisionShape->getShapeType() == CONVEX_HULL_SHAPE_PROXYTYPE) { btConvexHullShape* convexHull = (btConvexHullShape* )m_cci.m_collisionShape; { int nvertices = convexHull->getNumPoints(); @@ -224,26 +225,25 @@ bool CcdPhysicsController::CreateSoftbody() HullDesc hdsc(QF_TRIANGLES,nvertices,vertices); HullResult hres; - HullLibrary hlib;/*??*/ + HullLibrary hlib; /*??*/ hdsc.mMaxVertices=nvertices; hlib.CreateConvexHull(hdsc,hres); - psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices, - &hres.m_OutputVertices[0],0); - for (int i=0;i<(int)hres.mNumFaces;++i) - { - const int idx[]={ hres.m_Indices[i*3+0], - hres.m_Indices[i*3+1], - hres.m_Indices[i*3+2]}; - if (idx[0]appendLink( idx[0],idx[1]); - if (idx[1]appendLink( idx[1],idx[2]); - if (idx[2]appendLink( idx[2],idx[0]); - psb->appendFace(idx[0],idx[1],idx[2]); + psb = new btSoftBody(&worldInfo, (int)hres.mNumOutputVertices, + &hres.m_OutputVertices[0], 0); + for (int i = 0; i < (int)hres.mNumFaces; ++i) { + const unsigned int idx[3] = {hres.m_Indices[i * 3 + 0], + hres.m_Indices[i * 3 + 1], + hres.m_Indices[i * 3 + 2]}; + if (idx[0] < idx[1]) psb->appendLink(idx[0], idx[1]); + if (idx[1] < idx[2]) psb->appendLink(idx[1], idx[2]); + if (idx[2] < idx[0]) psb->appendLink(idx[2], idx[0]); + psb->appendFace(idx[0], idx[1], idx[2]); } hlib.ReleaseResult(hres); } - } else - { + } + else { int numtris = 0; if (m_cci.m_collisionShape->getShapeType() ==SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE) { @@ -787,7 +787,7 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta if (oldbody->getActivationState() == DISABLE_DEACTIVATION) body->setActivationState(DISABLE_DEACTIVATION); } - } + } // sensor object are added when needed if (!m_cci.m_bSensor) m_cci.m_physicsEnv->addCcdPhysicsController(this); @@ -806,7 +806,7 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta m_sumoObj = new SM_Object( orgsumoobject->getShapeHandle(), - orgsumoobject->getMaterialProps(), + orgsumoobject->getMaterialProps(), orgsumoobject->getShapeProps(), dynaparent); @@ -895,18 +895,22 @@ void CcdPhysicsController::RelativeTranslate(float dlocX,float dlocY,float dloc return; } - // btRigidBody* body = GetRigidBody(); // not used anymore - btVector3 dloc(dlocX,dlocY,dlocZ); btTransform xform = m_object->getWorldTransform(); if (local) - { dloc = xform.getBasis()*dloc; - } - xform.setOrigin(xform.getOrigin() + dloc); - SetCenterOfMassTransform(xform); + if (m_characterController) + { + m_characterController->setWalkDirection(dloc/GetPhysicsEnvironment()->getNumTimeSubSteps()); + } + else + { + + xform.setOrigin(xform.getOrigin() + dloc); + SetCenterOfMassTransform(xform); + } } } @@ -1142,7 +1146,7 @@ void CcdPhysicsController::ApplyForce(float forceX,float forceY,float forceZ,bo btTransform xform = m_object->getWorldTransform(); if (local) - { + { force = xform.getBasis()*force; } btRigidBody* body = GetRigidBody(); @@ -1498,9 +1502,15 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, MFace *mface = dm->getTessFaceArray(dm); numpolys = dm->getNumTessFaces(dm); numverts = dm->getNumVerts(dm); - int* index = (int*)dm->getTessFaceDataArray(dm, CD_ORIGINDEX); MTFace *tface = (MTFace *)dm->getTessFaceDataArray(dm, CD_MTFACE); + /* double lookup */ + const int *index_mf_to_mpoly = (const int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); + if ((index_mf_to_mpoly && index_mp_to_orig) == false) { + index_mf_to_mpoly = index_mp_to_orig = NULL; + } + m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH; /* Convert blender geometry into bullet mesh, need these vars for mapping */ @@ -1513,15 +1523,16 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, for (int p2=0; p2GetPolygon((index)? index[p2]: p2); + const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2; + RAS_Polygon* poly = meshobj->GetPolygon(origi); // only add polygons that have the collision flag set if (poly->IsCollider()) { - if (vert_tag_array[mf->v1]==false) {vert_tag_array[mf->v1]= true;tot_bt_verts++;} - if (vert_tag_array[mf->v2]==false) {vert_tag_array[mf->v2]= true;tot_bt_verts++;} - if (vert_tag_array[mf->v3]==false) {vert_tag_array[mf->v3]= true;tot_bt_verts++;} - if (mf->v4 && vert_tag_array[mf->v4]==false) {vert_tag_array[mf->v4]= true;tot_bt_verts++;} + if (vert_tag_array[mf->v1] == false) {vert_tag_array[mf->v1] = true; tot_bt_verts++;} + if (vert_tag_array[mf->v2] == false) {vert_tag_array[mf->v2] = true; tot_bt_verts++;} + if (vert_tag_array[mf->v3] == false) {vert_tag_array[mf->v3] = true; tot_bt_verts++;} + if (mf->v4 && vert_tag_array[mf->v4] == false) {vert_tag_array[mf->v4] = true; tot_bt_verts++;} } } @@ -1532,7 +1543,8 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, for (int p2=0; p2GetPolygon((index)? index[p2]: p2); + const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2; + RAS_Polygon* poly= meshobj->GetPolygon(origi); // only add polygons that have the collisionflag set if (poly->IsCollider()) @@ -1540,7 +1552,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, if (vert_tag_array[mf->v1]==true) { const float* vtx = mvert[mf->v1].co; - vert_tag_array[mf->v1]= false; + vert_tag_array[mf->v1] = false; *bt++ = vtx[0]; *bt++ = vtx[1]; *bt++ = vtx[2]; @@ -1548,7 +1560,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, if (vert_tag_array[mf->v2]==true) { const float* vtx = mvert[mf->v2].co; - vert_tag_array[mf->v2]= false; + vert_tag_array[mf->v2] = false; *bt++ = vtx[0]; *bt++ = vtx[1]; *bt++ = vtx[2]; @@ -1556,7 +1568,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, if (vert_tag_array[mf->v3]==true) { const float* vtx = mvert[mf->v3].co; - vert_tag_array[mf->v3]= false; + vert_tag_array[mf->v3] = false; *bt++ = vtx[0]; *bt++ = vtx[1]; *bt++ = vtx[2]; @@ -1564,7 +1576,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, if (mf->v4 && vert_tag_array[mf->v4]==true) { const float* vtx = mvert[mf->v4].co; - vert_tag_array[mf->v4]= false; + vert_tag_array[mf->v4] = false; *bt++ = vtx[0]; *bt++ = vtx[1]; *bt++ = vtx[2]; @@ -1580,19 +1592,20 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, for (int p2=0; p2GetPolygon((index)? index[p2]: p2); + const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2; + RAS_Polygon* poly= meshobj->GetPolygon(origi); // only add polygons that have the collision flag set if (poly->IsCollider()) { if (vert_tag_array[mf->v1]==false) - {vert_tag_array[mf->v1]= true;vert_remap_array[mf->v1]= tot_bt_verts;tot_bt_verts++;} + {vert_tag_array[mf->v1] = true;vert_remap_array[mf->v1] = tot_bt_verts;tot_bt_verts++;} if (vert_tag_array[mf->v2]==false) - {vert_tag_array[mf->v2]= true;vert_remap_array[mf->v2]= tot_bt_verts;tot_bt_verts++;} + {vert_tag_array[mf->v2] = true;vert_remap_array[mf->v2] = tot_bt_verts;tot_bt_verts++;} if (vert_tag_array[mf->v3]==false) - {vert_tag_array[mf->v3]= true;vert_remap_array[mf->v3]= tot_bt_verts;tot_bt_verts++;} + {vert_tag_array[mf->v3] = true;vert_remap_array[mf->v3] = tot_bt_verts;tot_bt_verts++;} if (mf->v4 && vert_tag_array[mf->v4]==false) - {vert_tag_array[mf->v4]= true;vert_remap_array[mf->v4]= tot_bt_verts;tot_bt_verts++;} + {vert_tag_array[mf->v4] = true;vert_remap_array[mf->v4] = tot_bt_verts;tot_bt_verts++;} tot_bt_tris += (mf->v4 ? 2:1); /* a quad or a tri */ } } @@ -1617,7 +1630,8 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, { MFace* mf = &mface[p2]; MTFace* tf = (tface) ? &tface[p2] : NULL; - RAS_Polygon* poly= meshobj->GetPolygon((index)? index[p2]: p2); + const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2; + RAS_Polygon* poly= meshobj->GetPolygon(origi); // only add polygons that have the collisionflag set if (poly->IsCollider()) @@ -1627,9 +1641,9 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, MVert *v3= &mvert[mf->v3]; // the face indices - tri_pt[0]= vert_remap_array[mf->v1]; - tri_pt[1]= vert_remap_array[mf->v2]; - tri_pt[2]= vert_remap_array[mf->v3]; + tri_pt[0] = vert_remap_array[mf->v1]; + tri_pt[1] = vert_remap_array[mf->v2]; + tri_pt[2] = vert_remap_array[mf->v3]; tri_pt= tri_pt+3; if (tf) { @@ -1643,25 +1657,25 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, } // m_polygonIndexArray - *poly_index_pt= (index)? index[p2]: p2; + *poly_index_pt = origi; poly_index_pt++; // the vertex location if (vert_tag_array[mf->v1]==true) { /* *** v1 *** */ - vert_tag_array[mf->v1]= false; + vert_tag_array[mf->v1] = false; *bt++ = v1->co[0]; *bt++ = v1->co[1]; *bt++ = v1->co[2]; } if (vert_tag_array[mf->v2]==true) { /* *** v2 *** */ - vert_tag_array[mf->v2]= false; + vert_tag_array[mf->v2] = false; *bt++ = v2->co[0]; *bt++ = v2->co[1]; *bt++ = v2->co[2]; } if (vert_tag_array[mf->v3]==true) { /* *** v3 *** */ - vert_tag_array[mf->v3]= false; - *bt++ = v3->co[0]; + vert_tag_array[mf->v3] = false; + *bt++ = v3->co[0]; *bt++ = v3->co[1]; *bt++ = v3->co[2]; } @@ -1670,9 +1684,9 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, { MVert *v4= &mvert[mf->v4]; - tri_pt[0]= vert_remap_array[mf->v1]; - tri_pt[1]= vert_remap_array[mf->v3]; - tri_pt[2]= vert_remap_array[mf->v4]; + tri_pt[0] = vert_remap_array[mf->v1]; + tri_pt[1] = vert_remap_array[mf->v3]; + tri_pt[2] = vert_remap_array[mf->v4]; tri_pt= tri_pt+3; if (tf) { @@ -1686,14 +1700,14 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, } // m_polygonIndexArray - *poly_index_pt= (index)? index[p2]: p2; + *poly_index_pt = origi; poly_index_pt++; // the vertex location - if (vert_tag_array[mf->v4]==true) { /* *** v4 *** */ - vert_tag_array[mf->v4]= false; + if (vert_tag_array[mf->v4] == true) { /* *** v4 *** */ + vert_tag_array[mf->v4] = false; *bt++ = v4->co[0]; - *bt++ = v4->co[1]; + *bt++ = v4->co[1]; *bt++ = v4->co[2]; } } @@ -1798,7 +1812,13 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA MFace *mface = dm->getTessFaceArray(dm); numpolys = dm->getNumTessFaces(dm); numverts = dm->getNumVerts(dm); - int* index = (int*)dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + + /* double lookup */ + const int *index_mf_to_mpoly = (const int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); + if ((index_mf_to_mpoly && index_mp_to_orig) == false) { + index_mf_to_mpoly = index_mp_to_orig = NULL; + } MFace *mf; MVert *mv; @@ -1830,8 +1850,8 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA if (vert_tag_array[v_orig]==false) { - vert_tag_array[v_orig]= true; - vert_remap_array[v_orig]= tot_bt_verts; + vert_tag_array[v_orig] = true; + vert_remap_array[v_orig] = tot_bt_verts; tot_bt_verts++; } } @@ -1854,7 +1874,7 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA { if (tf->mode & TF_DYNAMIC) { - int origi = (index)? index[i]: i; + int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i; if (mf->v4) { fv_pt= quad_verts; @@ -1878,7 +1898,7 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA *bt++ = mv->co[1]; *bt++ = mv->co[2]; - vert_tag_array[v_orig]= false; + vert_tag_array[v_orig] = false; } *tri_pt++ = vert_remap_array[v_orig]; uv_pt->uv[0] = tf->uv[*fv_pt][0]; @@ -1913,7 +1933,7 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA } for (mf= mface, i=0; i < numpolys; mf++, i++) { - int origi = (index)? index[i]: i; + int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i; if (mf->v4) { fv_pt= quad_verts; @@ -1939,7 +1959,7 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA /* transverts are only used for deformed RAS_Meshes, the RAS_TexVert data * is too hard to get at, see below for details */ - float (*transverts)[3]= NULL; + float (*transverts)[3] = NULL; int transverts_tot= 0; /* with deformed meshes - should always be greater then the max orginal index, or we get crashes */ if (deformer) { @@ -1969,8 +1989,8 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA v_orig= poly->GetVertex(i)->getOrigIndex(); if (vert_tag_array[v_orig]==false) { - vert_tag_array[v_orig]= true; - vert_remap_array[v_orig]= tot_bt_verts; + vert_tag_array[v_orig] = true; + vert_remap_array[v_orig] = tot_bt_verts; tot_bt_verts++; } } @@ -2023,14 +2043,14 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA *bt++ = xyz[2]; } - vert_tag_array[v_orig]= false; + vert_tag_array[v_orig] = false; } *tri_pt++ = vert_remap_array[v_orig]; } } - m_polygonIndexArray[p]= p; /* dumb counting */ + m_polygonIndexArray[p] = p; /* dumb counting */ } } @@ -2089,7 +2109,7 @@ bool CcdShapeConstructionInfo::SetProxy(CcdShapeConstructionInfo* shapeInfo) btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin, bool useGimpact, bool useBvh) { btCollisionShape* collisionShape = 0; - btCompoundShape* compoundShape = 0; + btCompoundShape* compoundShape = 0; if (m_shapeType == PHY_SHAPE_PROXY && m_shapeProxy != NULL) return m_shapeProxy->CreateBulletShape(margin, useGimpact, useBvh); @@ -2138,7 +2158,7 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin, b // One possible optimization is to use directly the btBvhTriangleMeshShape when the scale is 1,1,1 // and btScaledBvhTriangleMeshShape otherwise. if (useGimpact) - { + { btTriangleIndexVertexArray* indexVertexArrays = new btTriangleIndexVertexArray( m_polygonIndexArray.size(), &m_triFaceArray[0], diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 94dc796df23..6df5c85f5c0 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -171,7 +171,7 @@ public: btVector3 m_halfExtend; btTransform m_childTrans; btVector3 m_childScale; - void* m_userData; + void* m_userData; btAlignedObjectArray m_vertexArray; // Contains both vertex array for polytope shape and // triangle array for concave mesh shape. Each vertex is 3 consecutive values // In this case a triangle is made of 3 consecutive points @@ -397,7 +397,7 @@ class btCollisionObject; class btSoftBody; ///CcdPhysicsController is a physics object that supports continuous collision detection and time of impact based physics resolution. -class CcdPhysicsController : public PHY_IPhysicsController +class CcdPhysicsController : public PHY_IPhysicsController { protected: btCollisionObject* m_object; @@ -665,4 +665,4 @@ class DefaultMotionState : public PHY_IMotionState }; -#endif //__CCDPHYSICSCONTROLLER_H__ +#endif /* __CCDPHYSICSCONTROLLER_H__ */ diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 5d28bf47401..486411d7e35 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -37,6 +37,7 @@ subject to the following restrictions: #include "PHY_IMotionState.h" +#include "PHY_ICharacter.h" #include "KX_GameObject.h" #include "RAS_MeshObject.h" #include "RAS_Polygon.h" @@ -57,7 +58,6 @@ btRaycastVehicle::btVehicleTuning gTuning; #include "LinearMath/btAabbUtil2.h" #include "MT_Matrix4x4.h" #include "MT_Vector3.h" -#include "GL/glew.h" #ifdef WIN32 void DrawRasterizerLine(const float* from,const float* to,int color); @@ -267,6 +267,36 @@ public: }; #endif //NEW_BULLET_VEHICLE_SUPPORT +class CharacterWrapper : public PHY_ICharacter +{ +private: + btKinematicCharacterController* m_controller; + +public: + CharacterWrapper(btKinematicCharacterController* cont) + : m_controller(cont) + {} + + virtual void Jump() + { + m_controller->jump(); + } + + virtual bool OnGround() + { + return m_controller->onGround(); + } + + virtual float GetGravity() + { + return m_controller->getGravity(); + } + virtual void SetGravity(float gravity) + { + m_controller->setGravity(gravity); + } +}; + class CcdOverlapFilterCallBack : public btOverlapFilterCallback { private: @@ -303,13 +333,13 @@ static void DrawAabb(btIDebugDraw* debugDrawer,const btVector3& from,const btVec { for (j=0;j<3;j++) { - pa = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1], + pa = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1], edgecoord[2]*halfExtents[2]); pa+=center; int othercoord = j%3; edgecoord[othercoord]*=-1.f; - pb = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1], + pb = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1], edgecoord[2]*halfExtents[2]); pb+=center; @@ -484,9 +514,8 @@ void CcdPhysicsEnvironment::updateCcdPhysicsController(CcdPhysicsController* ctr body->getCollisionShape()->calculateLocalInertia(newMass, inertia); body->setMassProps(newMass, inertia); m_dynamicsWorld->addRigidBody(body, newCollisionGroup, newCollisionMask); - } - else - { + } + else { m_dynamicsWorld->addCollisionObject(obj, newCollisionGroup, newCollisionMask); } } @@ -605,7 +634,7 @@ bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep,float float subStep = timeStep / float(m_numTimeSubSteps); i = m_dynamicsWorld->stepSimulation(interval,25,subStep);//perform always a full simulation step -//uncomment next line to see where Bullet spend its time (printf in console) +//uncomment next line to see where Bullet spend its time (printf in console) //CProfileManager::dumpAll(); processFhSprings(curTime,i*subStep); @@ -1080,11 +1109,11 @@ static bool GetHitTriangle(btCollisionShape* shape, CcdShapeConstructionInfo* sh const btVector3& meshScaling = shape->getLocalScaling(); for (int j=2;j>=0;j--) { - int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + int graphicsindex = (indicestype == PHY_SHORT) ? ((unsigned short *)gfxbase)[j] : gfxbase[j]; btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); - triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); + triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); } meshInterface->unLockReadOnlyVertexBase(0); return true; @@ -1248,7 +1277,7 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac result.m_hitNormal[1] = rayCallback.m_hitNormalWorld.getY(); result.m_hitNormal[2] = rayCallback.m_hitNormalWorld.getZ(); filterCallback.reportHit(&result); - } + } return result.m_controller; @@ -1310,22 +1339,19 @@ struct OcclusionBuffer m[14] = btScalar(m1[ 2]*m2[12]+m1[ 6]*m2[13]+m1[10]*m2[14]+m1[14]*m2[15]); m[15] = btScalar(m1[ 3]*m2[12]+m1[ 7]*m2[13]+m1[11]*m2[14]+m1[15]*m2[15]); } - void setup(int size) + void setup(int size, const int *view, double modelview[16], double projection[16]) { m_initialized=false; m_occlusion=false; // compute the size of the buffer - GLint v[4]; - GLdouble m[16],p[16]; int maxsize; double ratio; - glGetIntegerv(GL_VIEWPORT,v); - maxsize = (v[2] > v[3]) ? v[2] : v[3]; + maxsize = (view[2] > view[3]) ? view[2] : view[3]; assert(maxsize > 0); ratio = 1.0/(2*maxsize); // ensure even number - m_sizes[0] = 2*((int)(size*v[2]*ratio+0.5)); - m_sizes[1] = 2*((int)(size*v[3]*ratio+0.5)); + m_sizes[0] = 2*((int)(size*view[2]*ratio+0.5)); + m_sizes[1] = 2*((int)(size*view[3]*ratio+0.5)); m_scales[0]=btScalar(m_sizes[0]/2); m_scales[1]=btScalar(m_sizes[1]/2); m_offsets[0]=m_scales[0]+0.5f; @@ -1333,10 +1359,8 @@ struct OcclusionBuffer // prepare matrix // at this time of the rendering, the modelview matrix is the // world to camera transformation and the projection matrix is - // camera to clip transformation. combine both so that - glGetDoublev(GL_MODELVIEW_MATRIX,m); - glGetDoublev(GL_PROJECTION_MATRIX,p); - CMmat4mul(m_wtc,p,m); + // camera to clip transformation. combine both so that + CMmat4mul(m_wtc, projection, modelview); } void initialize() { @@ -1391,7 +1415,7 @@ struct OcclusionBuffer static bool project(btVector4* p,int n) { for (int i=0;i y[1]) { ytmp=y[1];y[1]=y[0];y[0]=ytmp;ztmp=z[1];z[1]=z[0];z[0]=ztmp; } if (y[0] > y[2]) { ytmp=y[2];y[2]=y[0];y[0]=ytmp;ztmp=z[2];z[2]=z[0];z[0]=ztmp; } if (y[1] > y[2]) { ytmp=y[2];y[2]=y[1];y[1]=ytmp;ztmp=z[2];z[2]=z[1];z[1]=ztmp; } - int dy[]={ y[0]-y[1], - y[1]-y[2], - y[2]-y[0]}; + int dy[] = {y[0] - y[1], + y[1] - y[2], + y[2] - y[0]}; btScalar dzy[3]; - dzy[0] = (dy[0]) ? (z[0]-z[1])/dy[0] : btScalar(0.f); - dzy[1] = (dy[1]) ? (z[1]-z[2])/dy[1] : btScalar(0.f); - dzy[2] = (dy[2]) ? (z[2]-z[0])/dy[2] : btScalar(0.f); - btScalar v[3] = { dzy[0]*(miy-y[0])+z[0], - dzy[1]*(miy-y[1])+z[1], - dzy[2]*(miy-y[2])+z[2] }; + dzy[0] = (dy[0]) ? (z[0] - z[1]) / dy[0] : btScalar(0.f); + dzy[1] = (dy[1]) ? (z[1] - z[2]) / dy[1] : btScalar(0.f); + dzy[2] = (dy[2]) ? (z[2] - z[0]) / dy[2] : btScalar(0.f); + btScalar v[3] = {dzy[0] * (miy - y[0]) + z[0], + dzy[1] * (miy - y[1]) + z[1], + dzy[2] * (miy - y[2]) + z[2]}; dy[0] = y[1]-y[0]; dy[1] = y[0]-y[1]; dy[2] = y[2]-y[0]; @@ -1573,16 +1597,16 @@ struct OcclusionBuffer if (x[0] > x[1]) { xtmp=x[1];x[1]=x[0];x[0]=xtmp;ztmp=z[1];z[1]=z[0];z[0]=ztmp; } if (x[0] > x[2]) { xtmp=x[2];x[2]=x[0];x[0]=xtmp;ztmp=z[2];z[2]=z[0];z[0]=ztmp; } if (x[1] > x[2]) { xtmp=x[2];x[2]=x[1];x[1]=xtmp;ztmp=z[2];z[2]=z[1];z[1]=ztmp; } - int dx[]={ x[0]-x[1], - x[1]-x[2], - x[2]-x[0]}; + int dx[] = {x[0] - x[1], + x[1] - x[2], + x[2] - x[0]}; btScalar dzx[3]; dzx[0] = (dx[0]) ? (z[0]-z[1])/dx[0] : btScalar(0.f); dzx[1] = (dx[1]) ? (z[1]-z[2])/dx[1] : btScalar(0.f); dzx[2] = (dx[2]) ? (z[2]-z[0])/dx[2] : btScalar(0.f); - btScalar v[3] = { dzx[0]*(mix-x[0])+z[0], - dzx[1]*(mix-x[1])+z[1], - dzx[2]*(mix-x[2])+z[2] }; + btScalar v[3] = {dzx[0] * (mix - x[0]) + z[0], + dzx[1] * (mix - x[1]) + z[1], + dzx[2] * (mix - x[2]) + z[2]}; dx[0] = x[1]-x[0]; dx[1] = x[0]-x[1]; dx[2] = x[2]-x[0]; @@ -1599,24 +1623,24 @@ struct OcclusionBuffer v[0] += dzx[0]; v[1] += dzx[1]; v[2] += dzx[2]; dx[0]--; dx[1]++, dx[2]--; } - } else - { + } + else { // general case - const int dx[]={ y[0]-y[1], - y[1]-y[2], - y[2]-y[0]}; - const int dy[]={ x[1]-x[0]-dx[0]*width, - x[2]-x[1]-dx[1]*width, - x[0]-x[2]-dx[2]*width}; - const int a=x[2]*y[0]+x[0]*y[1]-x[2]*y[1]-x[0]*y[2]+x[1]*y[2]-x[1]*y[0]; - const btScalar ia=1/(btScalar)a; - const btScalar dzx=ia*(y[2]*(z[1]-z[0])+y[1]*(z[0]-z[2])+y[0]*(z[2]-z[1])); - const btScalar dzy=ia*(x[2]*(z[0]-z[1])+x[0]*(z[1]-z[2])+x[1]*(z[2]-z[0]))-(dzx*width); - int c[]={ miy*x[1]+mix*y[0]-x[1]*y[0]-mix*y[1]+x[0]*y[1]-miy*x[0], - miy*x[2]+mix*y[1]-x[2]*y[1]-mix*y[2]+x[1]*y[2]-miy*x[1], - miy*x[0]+mix*y[2]-x[0]*y[2]-mix*y[0]+x[2]*y[0]-miy*x[2]}; - btScalar v=ia*((z[2]*c[0])+(z[0]*c[1])+(z[1]*c[2])); - btScalar* scan=&m_buffer[miy*m_sizes[0]]; + const int dx[] = {y[0] - y[1], + y[1] - y[2], + y[2] - y[0]}; + const int dy[] = {x[1] - x[0] - dx[0] * width, + x[2] - x[1] - dx[1] * width, + x[0] - x[2] - dx[2] * width}; + const int a = x[2] * y[0] + x[0] * y[1] - x[2] * y[1] - x[0] * y[2] + x[1] * y[2] - x[1] * y[0]; + const btScalar ia = 1 / (btScalar)a; + const btScalar dzx = ia*(y[2]*(z[1]-z[0])+y[1]*(z[0]-z[2])+y[0]*(z[2]-z[1])); + const btScalar dzy = ia*(x[2]*(z[0]-z[1])+x[0]*(z[1]-z[2])+x[1]*(z[2]-z[0]))-(dzx*width); + int c[] = {miy*x[1]+mix*y[0]-x[1]*y[0]-mix*y[1]+x[0]*y[1]-miy*x[0], + miy*x[2]+mix*y[1]-x[2]*y[1]-mix*y[2]+x[1]*y[2]-miy*x[1], + miy*x[0]+mix*y[2]-x[0]*y[2]-mix*y[0]+x[2]*y[0]-miy*x[2]}; + btScalar v = ia*((z[2]*c[0])+(z[0]*c[1])+(z[1]*c[2])); + btScalar *scan = &m_buffer[miy*m_sizes[0]]; for (int iy=miy;iy(p,1.f,0.f)) return(true); } @@ -1744,7 +1768,7 @@ struct DbvtCullingCallback : btDbvt::ICollide Process(node); } void Process(const btDbvtNode* leaf) - { + { btBroadphaseProxy* proxy=(btBroadphaseProxy*)leaf->data; // the client object is a graphic controller CcdGraphicController* ctrl = static_cast(proxy->m_clientObject); @@ -1796,7 +1820,7 @@ struct DbvtCullingCallback : btDbvt::ICollide }; static OcclusionBuffer gOcb; -bool CcdPhysicsEnvironment::cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4 *planes, int nplanes, int occlusionRes) +bool CcdPhysicsEnvironment::cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4 *planes, int nplanes, int occlusionRes, const int *viewport, double modelview[16], double projection[16]) { if (!m_cullingTree) return false; @@ -1813,15 +1837,15 @@ bool CcdPhysicsEnvironment::cullingTest(PHY_CullingCallback callback, void* user // if occlusionRes != 0 => occlusion culling if (occlusionRes) { - gOcb.setup(occlusionRes); + gOcb.setup(occlusionRes, viewport, modelview, projection); dispatcher.m_ocb = &gOcb; // occlusion culling, the direction of the view is taken from the first plan which MUST be the near plane btDbvt::collideOCL(m_cullingTree->m_sets[1].m_root,planes_n,planes_o,planes_n[0],nplanes,dispatcher); - btDbvt::collideOCL(m_cullingTree->m_sets[0].m_root,planes_n,planes_o,planes_n[0],nplanes,dispatcher); + btDbvt::collideOCL(m_cullingTree->m_sets[0].m_root,planes_n,planes_o,planes_n[0],nplanes,dispatcher); } else { btDbvt::collideKDOP(m_cullingTree->m_sets[1].m_root,planes_n,planes_o,nplanes,dispatcher); - btDbvt::collideKDOP(m_cullingTree->m_sets[0].m_root,planes_n,planes_o,nplanes,dispatcher); + btDbvt::collideKDOP(m_cullingTree->m_sets[0].m_root,planes_n,planes_o,nplanes,dispatcher); } return true; } @@ -1973,8 +1997,8 @@ void CcdPhysicsEnvironment::setConstraintParam(int constraintId,int param,float btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint; int transMotorIndex = param-6; btTranslationalLimitMotor* transMotor = genCons->getTranslationalLimitMotor(); - transMotor->m_targetVelocity[transMotorIndex]= value0; - transMotor->m_maxMotorForce[transMotorIndex]=value1; + transMotor->m_targetVelocity[transMotorIndex] = value0; + transMotor->m_maxMotorForce[transMotorIndex] = value1; transMotor->m_enableMotor[transMotorIndex] = (value1>0.f); break; } @@ -2215,10 +2239,29 @@ bool CcdOverlapFilterCallBack::needBroadphaseCollision(btBroadphaseProxy* proxy0 { btCollisionObject *colObj0, *colObj1; CcdPhysicsController *sensorCtrl, *objCtrl; + + KX_GameObject *kxObj0 = KX_GameObject::GetClientObject( + (KX_ClientObjectInfo*) + ((CcdPhysicsController*) + (((btCollisionObject*)proxy0->m_clientObject)->getUserPointer())) + ->getNewClientInfo()); + KX_GameObject *kxObj1 = KX_GameObject::GetClientObject( + (KX_ClientObjectInfo*) + ((CcdPhysicsController*) + (((btCollisionObject*)proxy1->m_clientObject)->getUserPointer())) + ->getNewClientInfo()); + + // First check the filters. Note that this is called during scene + // conversion, so we can't assume the KX_GameObject instances exist. This + // may make some objects erroneously collide on the first frame, but the + // alternative is to have them erroneously miss. bool collides; - // first check the filters collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); + if (kxObj0 && kxObj1) { + collides = collides && kxObj0->CheckCollision(kxObj1); + collides = collides && kxObj1->CheckCollision(kxObj0); + } if (!collides) return false; @@ -2273,6 +2316,15 @@ PHY_IVehicle* CcdPhysicsEnvironment::getVehicleConstraint(int constraintId) #endif //NEW_BULLET_VEHICLE_SUPPORT +PHY_ICharacter* CcdPhysicsEnvironment::getCharacterController(KX_GameObject *ob) +{ + CcdPhysicsController* controller = (CcdPhysicsController*)ob->GetPhysicsController()->GetUserData(); + if (controller->GetCharacterController()) + return new CharacterWrapper(controller->GetCharacterController()); + + return NULL; +} + int currentController = 0; int numController = 0; diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index c499a1ef75c..18ce0550498 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -115,6 +115,11 @@ protected: virtual void setLinearAirDamping(float damping); virtual void setUseEpa(bool epa); + int getNumTimeSubSteps() + { + return m_numTimeSubSteps; + } + virtual void beginFrame(); virtual void endFrame() {} /// Perform an integration step of duration 'timeStep'. @@ -178,12 +183,14 @@ protected: { return 0; } -#endif //NEW_BULLET_VEHICLE_SUPPORT +#endif /* NEW_BULLET_VEHICLE_SUPPORT */ + // Character physics wrapper + virtual PHY_ICharacter* getCharacterController(class KX_GameObject* ob); btTypedConstraint* getConstraintById(int constraintId); virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ); - virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes, int occlusionRes); + virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes, int occlusionRes, const int *viewport, double modelview[16], double projection[16]); //Methods for gamelogic collision/physics callbacks @@ -292,4 +299,4 @@ protected: #endif }; -#endif //__CCDPHYSICSENVIRONMENT_H__ +#endif /* __CCDPHYSICSENVIRONMENT_H__ */ diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h index 9c109168b18..233c4412d9e 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h @@ -68,12 +68,18 @@ public: //complex constraint for vehicles virtual PHY_IVehicle* getVehicleConstraint(int constraintId) + { + return 0; + } + + // Character physics wrapper + virtual PHY_ICharacter* getCharacterController(class KX_GameObject* ob) { return 0; } virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ); - virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes, int occlusionRes) { return false; } + virtual bool cullingTest(PHY_CullingCallback callback, void* userData, PHY__Vector4* planes, int nplanes, int occlusionRes, const int *viewport, double modelview[16], double projection[16]) { return false; } //gamelogic callbacks @@ -102,5 +108,4 @@ public: #endif }; -#endif //__DUMMYPHYSICSENVIRONMENT_H__ - +#endif /* __DUMMYPHYSICSENVIRONMENT_H__ */ diff --git a/source/gameengine/Physics/common/CMakeLists.txt b/source/gameengine/Physics/common/CMakeLists.txt index ceb7a8ba548..400e475f8a2 100644 --- a/source/gameengine/Physics/common/CMakeLists.txt +++ b/source/gameengine/Physics/common/CMakeLists.txt @@ -41,6 +41,7 @@ set(SRC PHY_IVehicle.cpp PHY_DynamicTypes.h + PHY_ICharacter.h PHY_IController.h PHY_IGraphicController.h PHY_IMotionState.h diff --git a/source/gameengine/Physics/common/PHY_DynamicTypes.h b/source/gameengine/Physics/common/PHY_DynamicTypes.h index 69bbc7745e0..0fe2533cf93 100644 --- a/source/gameengine/Physics/common/PHY_DynamicTypes.h +++ b/source/gameengine/Physics/common/PHY_DynamicTypes.h @@ -32,11 +32,11 @@ struct PHY__Vector2 operator const float* () const { return &m_vec[0]; - } + } operator float* () { return &m_vec[0]; - } + } }; struct PHY__Vector3 @@ -46,11 +46,11 @@ struct PHY__Vector3 operator const float* () const { return &m_vec[0]; - } + } operator float* () { return &m_vec[0]; - } + } }; struct PHY__Vector4 @@ -75,11 +75,11 @@ struct PHY__Vector4 operator const float* () const { return &m_vec[0]; - } + } operator float* () { return &m_vec[0]; - } + } }; //typedef float PHY__Vector3[4]; @@ -151,4 +151,4 @@ typedef enum PHY_ShapeType { typedef float PHY_Vector3[3]; -#endif //__PHY_DYNAMICTYPES_H__ +#endif /* __PHY_DYNAMICTYPES_H__ */ diff --git a/source/gameengine/Physics/common/PHY_ICharacter.h b/source/gameengine/Physics/common/PHY_ICharacter.h new file mode 100644 index 00000000000..e2fc5e45125 --- /dev/null +++ b/source/gameengine/Physics/common/PHY_ICharacter.h @@ -0,0 +1,30 @@ + +/** \file PHY_ICharacter.h + * \ingroup phys + */ + +#ifndef __PHY_ICHARACTER_H__ +#define __PHY_ICHARACTER_H__ + +//PHY_ICharacter provides a generic interface for "character" controllers + +#ifdef WITH_CXX_GUARDEDALLOC +#include "MEM_guardedalloc.h" +#endif + +class PHY_ICharacter +{ +public: + + virtual void Jump()= 0; + virtual bool OnGround()= 0; + + virtual float GetGravity()= 0; + virtual void SetGravity(float gravity)= 0; + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("GE:PHY_ICharacter") +#endif +}; + +#endif //__PHY_ICHARACTER_H__ diff --git a/source/gameengine/Physics/common/PHY_IController.h b/source/gameengine/Physics/common/PHY_IController.h index 239ac3366e1..003c4edf598 100644 --- a/source/gameengine/Physics/common/PHY_IController.h +++ b/source/gameengine/Physics/common/PHY_IController.h @@ -45,7 +45,7 @@ class PHY_IPhysicsEnvironment; controlled by the physics engine. This includes the physics objects and the graphics object for view frustrum and occlusion culling. */ -class PHY_IController +class PHY_IController { public: virtual ~PHY_IController(); @@ -60,5 +60,4 @@ class PHY_IController #endif }; -#endif //__PHY_ICONTROLLER_H__ - +#endif /* __PHY_ICONTROLLER_H__ */ diff --git a/source/gameengine/Physics/common/PHY_IGraphicController.h b/source/gameengine/Physics/common/PHY_IGraphicController.h index af337188818..cb13eda4f18 100644 --- a/source/gameengine/Physics/common/PHY_IGraphicController.h +++ b/source/gameengine/Physics/common/PHY_IGraphicController.h @@ -58,5 +58,4 @@ class PHY_IGraphicController : public PHY_IController #endif }; -#endif //__PHY_IGRAPHICCONTROLLER_H__ - +#endif /* __PHY_IGRAPHICCONTROLLER_H__ */ diff --git a/source/gameengine/Physics/common/PHY_IMotionState.h b/source/gameengine/Physics/common/PHY_IMotionState.h index 2eb2a9f39cf..ccf7cf74724 100644 --- a/source/gameengine/Physics/common/PHY_IMotionState.h +++ b/source/gameengine/Physics/common/PHY_IMotionState.h @@ -43,7 +43,7 @@ class PHY_IMotionState { - public: + public: virtual ~PHY_IMotionState(); virtual void getWorldPosition(float& posX,float& posY,float& posZ)=0; @@ -65,5 +65,4 @@ class PHY_IMotionState #endif }; -#endif //__PHY_IMOTIONSTATE_H__ - +#endif /* __PHY_IMOTIONSTATE_H__ */ diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h index 7eea2a183a1..bc7671abe80 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsController.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h @@ -108,5 +108,4 @@ class PHY_IPhysicsController : public PHY_IController #endif }; -#endif //__PHY_IPHYSICSCONTROLLER_H__ - +#endif /* __PHY_IPHYSICSCONTROLLER_H__ */ diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h index 30d63e6695d..077d225903c 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h @@ -40,6 +40,7 @@ #endif class PHY_IVehicle; +class PHY_ICharacter; class RAS_MeshObject; class PHY_IPhysicsController; @@ -48,7 +49,7 @@ class PHY_IPhysicsController; */ struct PHY_RayCastResult { - PHY_IPhysicsController* m_controller; + PHY_IPhysicsController* m_controller; PHY__Vector3 m_hitPoint; PHY__Vector3 m_hitNormal; const RAS_MeshObject* m_meshObject; // !=NULL for mesh object (only for Bullet controllers) @@ -156,12 +157,15 @@ class PHY_IPhysicsEnvironment //complex constraint for vehicles virtual PHY_IVehicle* getVehicleConstraint(int constraintId) =0; + // Character physics wrapper + virtual PHY_ICharacter* getCharacterController(class KX_GameObject* ob) =0; + virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ)=0; //culling based on physical broad phase // the plane number must be set as follow: near, far, left, right, top, botton // the near plane must be the first one and must always be present, it is used to get the direction of the view - virtual bool cullingTest(PHY_CullingCallback callback, void *userData, PHY__Vector4* planeNormals, int planeNumber, int occlusionRes) = 0; + virtual bool cullingTest(PHY_CullingCallback callback, void *userData, PHY__Vector4* planeNormals, int planeNumber, int occlusionRes, const int *viewport, double modelview[16], double projection[16]) = 0; //Methods for gamelogic collision/physics callbacks //todo: @@ -185,5 +189,4 @@ class PHY_IPhysicsEnvironment #endif }; -#endif //__PHY_IPHYSICSENVIRONMENT_H__ - +#endif /* __PHY_IPHYSICSENVIRONMENT_H__ */ diff --git a/source/gameengine/Physics/common/PHY_IVehicle.h b/source/gameengine/Physics/common/PHY_IVehicle.h index 731e22d9f0f..ecf7a87c40f 100644 --- a/source/gameengine/Physics/common/PHY_IVehicle.h +++ b/source/gameengine/Physics/common/PHY_IVehicle.h @@ -66,4 +66,4 @@ public: #endif }; -#endif //__PHY_IVEHICLE_H__ +#endif /* __PHY_IVEHICLE_H__ */ diff --git a/source/gameengine/Physics/common/PHY_Pro.h b/source/gameengine/Physics/common/PHY_Pro.h index b930177d3a8..7c5d9c9638e 100644 --- a/source/gameengine/Physics/common/PHY_Pro.h +++ b/source/gameengine/Physics/common/PHY_Pro.h @@ -62,5 +62,4 @@ struct PHY_MaterialProps { bool m_fh_normal; // Should the object slide off slopes? }; -#endif //__PHY_PRO_H__ - +#endif /* __PHY_PRO_H__ */ diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp index 06251cd2282..cf869e71945 100644 --- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp +++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp @@ -110,7 +110,7 @@ void RAS_2DFilterManager::PrintShaderErrors(unsigned int shader, const char *tas unsigned int RAS_2DFilterManager::CreateShaderProgram(const char* shadersource) { - GLuint program = 0; + GLuint program = 0; GLuint fShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER); GLint success; @@ -153,8 +153,7 @@ unsigned int RAS_2DFilterManager::CreateShaderProgram(const char* shadersource) unsigned int RAS_2DFilterManager::CreateShaderProgram(int filtermode) { - switch(filtermode) - { + switch (filtermode) { case RAS_2DFILTER_BLUR: return CreateShaderProgram(BlurFragmentShader); case RAS_2DFILTER_SHARPEN: @@ -398,8 +397,7 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas) if (num_filters <= 0) return; - GLuint viewport[4]={0}; - glGetIntegerv(GL_VIEWPORT,(GLint *)viewport); + const GLint *viewport = canvas->GetViewPort(); RAS_Rect rect = canvas->GetWindowArea(); int rect_width = rect.GetWidth()+1, rect_height = rect.GetHeight()+1; @@ -469,7 +467,7 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas) glEnable(GL_DEPTH_TEST); glViewport(viewport[0],viewport[1],viewport[2],viewport[3]); - EndShaderProgram(); + EndShaderProgram(); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp index 90587bb9739..f24e3397801 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp +++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp @@ -29,13 +29,11 @@ * \ingroup bgerast */ - -#if defined(WIN32) && !defined(FREE_WINDOWS) -// don't show these anoying STL warnings -#pragma warning (disable:4786) +#ifdef _MSC_VER + /* don't show these anoying STL warnings */ +# pragma warning (disable:4786) #endif -#include "CTR_Map.h" #include "RAS_MaterialBucket.h" #include "STR_HashedString.h" #include "RAS_MeshObject.h" @@ -130,7 +128,7 @@ void RAS_BucketManager::OrderBuckets(const MT_Transform& cameratrans, BucketList RAS_MaterialBucket* bucket = *bit; RAS_MeshSlot* ms; // remove the mesh slot form the list, it culls them automatically for next frame - while((ms = bucket->GetNextActiveMeshSlot())) { + while ((ms = bucket->GetNextActiveMeshSlot())) { slots[i++].set(ms, bucket, pnorm); } } @@ -157,7 +155,7 @@ void RAS_BucketManager::RenderAlphaBuckets( for (sit=slots.begin(); sit!=slots.end(); ++sit) { rendertools->SetClientObject(rasty, sit->m_ms->m_clientObj); - while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools)) + while (sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools)) sit->m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(sit->m_ms)); // make this mesh slot culled automatically for next frame @@ -180,8 +178,7 @@ void RAS_BucketManager::RenderSolidBuckets( RAS_MaterialBucket* bucket = *bit; RAS_MeshSlot* ms; // remove the mesh slot form the list, it culls them automatically for next frame - while((ms = bucket->GetNextActiveMeshSlot())) - { + while ((ms = bucket->GetNextActiveMeshSlot())) { rendertools->SetClientObject(rasty, ms->m_clientObj); while (bucket->ActivateMaterial(cameratrans, rasty, rendertools)) bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *ms); @@ -220,7 +217,7 @@ void RAS_BucketManager::RenderSolidBuckets( for (sit=slots.begin(); sit!=slots.end(); ++sit) { rendertools->SetClientObject(rasty, sit->m_ms->m_clientObj); - while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools)) + while (sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools)) sit->m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(sit->m_ms)); } #endif @@ -232,8 +229,8 @@ void RAS_BucketManager::Renderbuckets( /* beginning each frame, clear (texture/material) caching information */ rasty->ClearCachingInfo(); - RenderSolidBuckets(cameratrans, rasty, rendertools); - RenderAlphaBuckets(cameratrans, rasty, rendertools); + RenderSolidBuckets(cameratrans, rasty, rendertools); + RenderAlphaBuckets(cameratrans, rasty, rendertools); rendertools->SetClientObject(rasty, NULL); } diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.h b/source/gameengine/Rasterizer/RAS_BucketManager.h index 2650bc9f722..78125a7bbb3 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.h +++ b/source/gameengine/Rasterizer/RAS_BucketManager.h @@ -34,7 +34,6 @@ #include "MT_Transform.h" #include "RAS_MaterialBucket.h" -#include "CTR_Map.h" #include @@ -90,5 +89,4 @@ private: #endif }; -#endif //__RAS_BUCKETMANAGER_H__ - +#endif /* __RAS_BUCKETMANAGER_H__ */ diff --git a/source/gameengine/Rasterizer/RAS_CameraData.h b/source/gameengine/Rasterizer/RAS_CameraData.h index 4a70df6e505..7a6bb541a1a 100644 --- a/source/gameengine/Rasterizer/RAS_CameraData.h +++ b/source/gameengine/Rasterizer/RAS_CameraData.h @@ -71,5 +71,4 @@ struct RAS_CameraData } }; -#endif //__RAS_CAMERADATA_H__ - +#endif /* __RAS_CAMERADATA_H__ */ diff --git a/source/gameengine/Rasterizer/RAS_Deformer.h b/source/gameengine/Rasterizer/RAS_Deformer.h index 51c4da3c49d..058f2304f3d 100644 --- a/source/gameengine/Rasterizer/RAS_Deformer.h +++ b/source/gameengine/Rasterizer/RAS_Deformer.h @@ -32,9 +32,9 @@ #ifndef __RAS_DEFORMER_H__ #define __RAS_DEFORMER_H__ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning -#endif //WIN32 +#ifdef _MSC_VER +# pragma warning (disable:4786) /* get rid of stupid stl-visual compiler debug warning */ +#endif #include #include "CTR_Map.h" @@ -91,7 +91,7 @@ public: protected: class RAS_MeshObject *m_pMesh; - bool m_bDynamic; + bool m_bDynamic; #ifdef WITH_CXX_GUARDEDALLOC diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.cpp b/source/gameengine/Rasterizer/RAS_FramingManager.cpp index 1cd110f8cc6..53d9b64ab0e 100644 --- a/source/gameengine/Rasterizer/RAS_FramingManager.cpp +++ b/source/gameengine/Rasterizer/RAS_FramingManager.cpp @@ -43,7 +43,7 @@ ComputeDefaultFrustum( const short sensor_fit, const float design_aspect_ratio, RAS_FrameFrustum & frustum -) { +) { float halfSize; float sizeX; float sizeY; @@ -202,7 +202,7 @@ ComputeViewport( { ComputeBestFitViewRect( availableViewport, - design_aspect_ratio, + design_aspect_ratio, viewport ); @@ -260,7 +260,7 @@ ComputeFrustum( RAS_Rect vt; ComputeBestFitViewRect( availableViewport, - design_aspect_ratio, + design_aspect_ratio, vt ); @@ -277,13 +277,13 @@ ComputeFrustum( frustum.y2 *= y_scale; break; - } + } case RAS_FrameSettings::e_frame_scale : case RAS_FrameSettings::e_frame_bars: default : break; } -} +} void RAS_FramingManager:: @@ -330,7 +330,7 @@ RAS_FramingManager:: RAS_Rect vt; ComputeBestFitViewRect( availableViewport, - design_aspect_ratio, + design_aspect_ratio, vt ); @@ -347,7 +347,7 @@ RAS_FramingManager:: frustum.y2 *= y_scale; break; - } + } case RAS_FrameSettings::e_frame_scale : case RAS_FrameSettings::e_frame_bars: default : diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.h b/source/gameengine/Rasterizer/RAS_FramingManager.h index dd640bc6839..122f0ca46ec 100644 --- a/source/gameengine/Rasterizer/RAS_FramingManager.h +++ b/source/gameengine/Rasterizer/RAS_FramingManager.h @@ -109,7 +109,7 @@ public : */ const - RAS_FrameType & + RAS_FrameType & FrameType( ) const { return m_frame_type; @@ -143,13 +143,13 @@ public : unsigned int DesignAspectWidth( ) const { - return m_design_aspect_width; + return m_design_aspect_width; }; unsigned int DesignAspectHeight( ) const { - return m_design_aspect_height; + return m_design_aspect_height; }; private : @@ -262,7 +262,7 @@ public : const short sensor_fit, const float design_aspect_ratio, RAS_FrameFrustum & frustum - ); + ); static void diff --git a/source/gameengine/Rasterizer/RAS_ICanvas.h b/source/gameengine/Rasterizer/RAS_ICanvas.h index 713a06845ac..53195d79768 100644 --- a/source/gameengine/Rasterizer/RAS_ICanvas.h +++ b/source/gameengine/Rasterizer/RAS_ICanvas.h @@ -180,6 +180,13 @@ public: int x2, int y2 ) = 0; + /** + * Get the visible viewport + */ + virtual + const int* + GetViewPort() = 0; + virtual void SetMouseState( @@ -224,5 +231,4 @@ protected: #endif }; -#endif //__RAS_ICANVAS_H__ - +#endif /* __RAS_ICANVAS_H__ */ diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp index 4af1753c2da..ddadd97b567 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp @@ -254,12 +254,18 @@ bool RAS_IPolyMaterial::UsesLighting(RAS_IRasterizer *rasty) const { bool dolights = false; - if (m_flag & RAS_BLENDERMAT) - dolights = (m_flag &RAS_MULTILIGHT)!=0; - else if (rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID); - else if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW); - else + if (m_flag & RAS_BLENDERMAT) { + dolights = (m_flag & RAS_MULTILIGHT) != 0; + } + else if (rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID) { + /* pass */ + } + else if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW) { + /* pass */ + } + else { dolights = m_light; + } return dolights; } diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h index 169bc6e4ee6..9fffc8bebc9 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h @@ -202,5 +202,4 @@ inline bool operator < ( const RAS_IPolyMaterial & lhs, const RAS_IPolyMaterial return lhs.Less(rhs); } -#endif //__RAS_IPOLYGONMATERIAL_H__ - +#endif /* __RAS_IPOLYGONMATERIAL_H__ */ diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index 7749c4af9d6..e6948025999 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -32,8 +32,8 @@ #ifndef __RAS_IRASTERIZER_H__ #define __RAS_IRASTERIZER_H__ -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable:4786) +#ifdef _MSC_VER +# pragma warning (disable:4786) #endif #include "STR_HashedString.h" @@ -301,7 +301,7 @@ public: virtual int GetDrawingMode()=0; /** * Sets face culling - */ + */ virtual void SetCullFace(bool enable)=0; /** * Sets wireframe mode. @@ -423,6 +423,4 @@ public: #endif }; -#endif //__RAS_IRASTERIZER_H__ - - +#endif /* __RAS_IRASTERIZER_H__ */ diff --git a/source/gameengine/Rasterizer/RAS_IRenderTools.h b/source/gameengine/Rasterizer/RAS_IRenderTools.h index c02bc5e7a44..bccda634222 100644 --- a/source/gameengine/Rasterizer/RAS_IRenderTools.h +++ b/source/gameengine/Rasterizer/RAS_IRenderTools.h @@ -72,18 +72,18 @@ public: { }; - virtual + virtual ~RAS_IRenderTools( ) {}; virtual - void + void BeginFrame( RAS_IRasterizer* rasty )=0; virtual - void + void EndFrame( RAS_IRasterizer* rasty )=0; @@ -94,7 +94,7 @@ public: // so must be renamed to 'applyTransform' or something virtual - void + void applyTransform( class RAS_IRasterizer* rasty, double* oglmatrix, @@ -112,7 +112,7 @@ public: * \param aspect A scaling factor to compensate for the size. */ virtual - void + void RenderText3D(int fontid, const char* text, int size, @@ -133,7 +133,7 @@ public: * \param height Height of the canvas to draw to. */ virtual - void + void RenderText2D( RAS_TEXT_RENDER_MODE mode, const char* text, @@ -145,7 +145,7 @@ public: // 3d text, mapped on polygon virtual - void + void RenderText( int mode, RAS_IPolyMaterial* polymat, @@ -156,8 +156,8 @@ public: int glattrib )=0; - virtual - void + virtual + void ProcessLighting( RAS_IRasterizer *rasty, bool uselights, @@ -165,35 +165,35 @@ public: )=0; virtual - void + void SetClientObject( RAS_IRasterizer* rasty, void* obj ); - void + void SetAuxilaryClientInfo( void* inf ); virtual - void + void PushMatrix( )=0; virtual - void + void PopMatrix( )=0; virtual - void + void AddLight( struct RAS_LightObject* lightobject ); virtual - void + void RemoveLight( struct RAS_LightObject* lightobject ); @@ -208,7 +208,4 @@ public: #endif }; -#endif //__RAS_IRENDERTOOLS_H__ - - - +#endif /* __RAS_IRENDERTOOLS_H__ */ diff --git a/source/gameengine/Rasterizer/RAS_LightObject.h b/source/gameengine/Rasterizer/RAS_LightObject.h index ddf360683cd..79818def5f0 100644 --- a/source/gameengine/Rasterizer/RAS_LightObject.h +++ b/source/gameengine/Rasterizer/RAS_LightObject.h @@ -64,5 +64,4 @@ struct RAS_LightObject bool m_nospecular; }; -#endif //__RAS_LIGHTOBJECT_H__ - +#endif /* __RAS_LIGHTOBJECT_H__ */ diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index a18adfd8986..9fb47117f1d 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -32,8 +32,8 @@ #include "RAS_MaterialBucket.h" -#if defined(WIN32) && !defined(FREE_WINDOWS) -#pragma warning (disable:4786) +#ifdef _MSC_VER +# pragma warning (disable:4786) #endif #ifdef WIN32 @@ -73,7 +73,7 @@ RAS_MeshSlot::~RAS_MeshSlot() #ifdef USE_SPLIT Split(true); - while(m_joinedSlots.size()) + while (m_joinedSlots.size()) m_joinedSlots.front()->Split(true); #endif @@ -147,7 +147,7 @@ void RAS_MeshSlot::begin(RAS_MeshSlot::iterator& it) int startvertex, endvertex; int startindex, endindex; - it.array = (m_displayArrays.size() > 0)? m_displayArrays[m_startarray]: NULL; + it.array = m_displayArrays.empty() ? NULL : m_displayArrays[m_startarray]; if (it.array == NULL || it.array->m_index.size() == 0 || it.array->m_vertex.size() == 0) { it.array = NULL; @@ -368,7 +368,7 @@ bool RAS_MeshSlot::Join(RAS_MeshSlot *target, MT_Scalar distance) size_t i; // verify if we can join - if (m_joinSlot || m_joinedSlots.size() || target->m_joinSlot) + if (m_joinSlot || (m_joinedSlots.empty() == false) || target->m_joinSlot) return false; if (!Equals(target)) @@ -393,7 +393,7 @@ bool RAS_MeshSlot::Join(RAS_MeshSlot *target, MT_Scalar distance) target->m_joinedSlots.push_back(this); MT_Matrix4x4 ntransform = m_joinInvTransform.transposed(); - ntransform[0][3]= ntransform[1][3]= ntransform[2][3]= 0.0f; + ntransform[0][3] = ntransform[1][3] = ntransform[2][3] = 0.0f; for (begin(mit); !end(mit); next(mit)) for (i=mit.startvertex; im_displayArrays.size()) { + if (target->m_displayArrays.empty() == false) { target->m_endvertex = target->m_displayArrays.back()->m_vertex.size(); target->m_endindex = target->m_displayArrays.back()->m_index.size(); } @@ -471,7 +471,7 @@ bool RAS_MeshSlot::Split(bool force) } MT_Matrix4x4 ntransform = m_joinInvTransform.inverse().transposed(); - ntransform[0][3]= ntransform[1][3]= ntransform[2][3]= 0.0f; + ntransform[0][3] = ntransform[1][3] = ntransform[2][3] = 0.0f; for (begin(mit); !end(mit); next(mit)) for (i=mit.startvertex; iIsAlpha()); } bool RAS_MaterialBucket::IsZSort() const -{ +{ return (m_material->IsZSort()); } diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h index 295f2510313..16ecffb9a32 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h @@ -254,4 +254,4 @@ private: #endif }; -#endif //__RAS_MATERIAL_BUCKET +#endif /* __RAS_MATERIAL_BUCKET */ diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index 25afefbcc5a..2ccb9453b3d 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -173,7 +173,7 @@ const STR_String& RAS_MeshObject::GetMaterialName(unsigned int matid) RAS_MeshMaterial* RAS_MeshObject::GetMeshMaterial(unsigned int matid) { - if (m_materials.size() > 0 && (matid < m_materials.size())) + if ((m_materials.empty() == false) && (matid < m_materials.size())) { list::iterator it = m_materials.begin(); while (matid--) ++it; @@ -584,7 +584,7 @@ void RAS_MeshObject::CheckWeightCache(Object* obj) if (!m_mesh->key) return; - for (kbindex=0, kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next, kbindex++) + for (kbindex = 0, kb = (KeyBlock *)m_mesh->key->block.first; kb; kb = kb->next, kbindex++) { // first check the cases where the weight must be cleared if (kb->vgroup[0] == 0 || @@ -608,7 +608,7 @@ void RAS_MeshObject::CheckWeightCache(Object* obj) weights= (float*)MEM_mallocN(totvert*sizeof(float), "weights"); for (i=0; i < totvert; i++, dv++) { - weights[i]= defvert_find_weight(dv, defindex); + weights[i] = defvert_find_weight(dv, defindex); } kb->weights = weights; diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h index eb8655c8b1f..281eae8734a 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.h +++ b/source/gameengine/Rasterizer/RAS_MeshObject.h @@ -32,9 +32,9 @@ #ifndef __RAS_MESHOBJECT_H__ #define __RAS_MESHOBJECT_H__ -#if defined(WIN32) && !defined(FREE_WINDOWS) -// disable the STL warnings ("debug information length > 255") -#pragma warning (disable:4786) +#ifdef _MSC_VER + /* disable the STL warnings ("debug information length > 255") */ +# pragma warning (disable:4786) #endif #include @@ -177,5 +177,4 @@ public: #endif }; -#endif //__RAS_MESHOBJECT_H__ - +#endif /* __RAS_MESHOBJECT_H__ */ diff --git a/source/gameengine/Rasterizer/RAS_ObjectColor.h b/source/gameengine/Rasterizer/RAS_ObjectColor.h index f8fbe69e97b..77feffccffc 100644 --- a/source/gameengine/Rasterizer/RAS_ObjectColor.h +++ b/source/gameengine/Rasterizer/RAS_ObjectColor.h @@ -38,5 +38,4 @@ struct RAS_ObjectColor { float m_blue; }; -#endif //__RAS_OBJECTCOLOR_H__ - +#endif /* __RAS_OBJECTCOLOR_H__ */ diff --git a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Erosion2DFilter.h b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Erosion2DFilter.h index 6319be6ce4a..eaefd5c13fa 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Erosion2DFilter.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLFilters/RAS_Erosion2DFilter.h @@ -32,7 +32,7 @@ #ifndef __RAS_EROSION2DFILTER_H__ #define __RAS_EROSION2DFILTER_H__ -const char * ErosionFragmentShader=STRINGIFY( +const char * ErosionFragmentShader = STRINGIFY( uniform sampler2D bgl_RenderedTexture; uniform vec2 bgl_TextureCoordinateOffset[9]; diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp index 1f411a09586..d74aa134779 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp @@ -124,7 +124,7 @@ void RAS_ListRasterizer::RemoveListSlot(RAS_ListSlot* list) { if (list->m_flag & LIST_DERIVEDMESH) { RAS_DerivedMeshLists::iterator it = mDerivedMeshLists.begin(); - while(it != mDerivedMeshLists.end()) { + while (it != mDerivedMeshLists.end()) { RAS_ListSlots *slots = it->second; if (slots->size() > list->m_matnr && slots->at(list->m_matnr) == list) { (*slots)[list->m_matnr] = NULL; @@ -145,7 +145,7 @@ void RAS_ListRasterizer::RemoveListSlot(RAS_ListSlot* list) } } else { RAS_ArrayLists::iterator it = mArrayLists.begin(); - while(it != mArrayLists.end()) { + while (it != mArrayLists.end()) { if (it->second == list) { mArrayLists.erase(it); break; diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index b769fc4b703..22a700c7d2b 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -52,7 +52,10 @@ #include "DNA_material_types.h" #include "DNA_scene_types.h" -#include "BKE_DerivedMesh.h" +extern "C"{ + #include "BLI_utildefines.h" + #include "BKE_DerivedMesh.h" +} #ifndef M_PI #define M_PI 3.14159265358979323846 @@ -239,10 +242,10 @@ void RAS_OpenGLRasterizer::DisplayFog() glFogf(GL_FOG_DENSITY, 0.1f); glFogf(GL_FOG_START, m_fogstart); glFogf(GL_FOG_END, m_fogstart + m_fogdist); - params[0]= m_fogr; - params[1]= m_fogg; - params[2]= m_fogb; - params[3]= 0.0; + params[0] = m_fogr; + params[1] = m_fogg; + params[2] = m_fogb; + params[3] = 0.0; glFogfv(GL_FOG_COLOR, params); glEnable(GL_FOG); } @@ -359,7 +362,7 @@ void RAS_OpenGLRasterizer::ClearCachingInfo(void) void RAS_OpenGLRasterizer::FlushDebugShapes() { - if (!m_debugShapes.size()) + if (m_debugShapes.empty()) return; // DrawDebugLines @@ -438,7 +441,7 @@ void RAS_OpenGLRasterizer::EndFrame() glDisable(GL_MULTISAMPLE_ARB); m_2DCanvas->EndFrame(); -} +} void RAS_OpenGLRasterizer::SetRenderArea() { @@ -447,8 +450,7 @@ void RAS_OpenGLRasterizer::SetRenderArea() switch (m_stereomode) { case RAS_STEREO_ABOVEBELOW: - switch(m_curreye) - { + switch (m_curreye) { case RAS_STEREO_LEFTEYE: // upper half of window area.SetLeft(0); @@ -716,53 +718,53 @@ void RAS_OpenGLRasterizer::TexCoord(const RAS_TexVert &tv) glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2()); continue; } - switch(m_texco[unit]) { - case RAS_TEXCO_ORCO: - case RAS_TEXCO_GLOB: - glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getXYZ()); - break; - case RAS_TEXCO_UV1: - glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV1()); - break; - case RAS_TEXCO_NORM: - glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getNormal()); - break; - case RAS_TEXTANGENT: - glMultiTexCoord4fvARB(GL_TEXTURE0_ARB+unit, tv.getTangent()); - break; - case RAS_TEXCO_UV2: - glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2()); - break; - default: - break; + switch (m_texco[unit]) { + case RAS_TEXCO_ORCO: + case RAS_TEXCO_GLOB: + glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getXYZ()); + break; + case RAS_TEXCO_UV1: + glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV1()); + break; + case RAS_TEXCO_NORM: + glMultiTexCoord3fvARB(GL_TEXTURE0_ARB+unit, tv.getNormal()); + break; + case RAS_TEXTANGENT: + glMultiTexCoord4fvARB(GL_TEXTURE0_ARB+unit, tv.getTangent()); + break; + case RAS_TEXCO_UV2: + glMultiTexCoord2fvARB(GL_TEXTURE0_ARB+unit, tv.getUV2()); + break; + default: + break; } } } if (GLEW_ARB_vertex_program) { for (unit=0; unitgetUV2()); continue; } - switch(m_texco[unit]) - { + switch (m_texco[unit]) { case RAS_TEXCO_ORCO: case RAS_TEXCO_GLOB: glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getXYZ()); @@ -274,7 +273,7 @@ void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv) if (GLEW_ARB_vertex_program) { for (unit=0; unitgetXYZ()); @@ -330,8 +329,7 @@ void RAS_VAOpenGLRasterizer::EnableTextures(bool enable) for (unit=0; unit // the Py object is actually a proxy - return (PyObj*)BGE_PROXY_REF(obj); + return (PyObj *)BGE_PROXY_REF(obj); } /// parse arguments to get object - PyObj * parseArg (PyObject * args) + PyObj *parseArg(PyObject *args) { // parse arguments - PyObject * obj; - if (PyArg_ParseTuple(args, "O", &obj)) + PyObject *obj; + if (PyArg_ParseTuple(args, "O", &obj)) { // if successfully parsed, return pointer to object return checkType(obj); + } // otherwise return NULL return NULL; } @@ -74,7 +75,7 @@ protected: /// name of Python type const char * m_name; /// pointer to Python type - PyTypeObject * m_objType; + PyTypeObject *m_objType; }; diff --git a/source/gameengine/VideoTexture/FilterBase.cpp b/source/gameengine/VideoTexture/FilterBase.cpp index 90ea8436ffe..6ec5e237ac2 100644 --- a/source/gameengine/VideoTexture/FilterBase.cpp +++ b/source/gameengine/VideoTexture/FilterBase.cpp @@ -90,10 +90,10 @@ PyTypeList pyFilterTypes; // object allocation -PyObject * Filter_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds) +PyObject *Filter_allocNew (PyTypeObject *type, PyObject *args, PyObject *kwds) { // allocate object - PyFilter * self = reinterpret_cast(type->tp_alloc(type, 0)); + PyFilter *self = reinterpret_cast(type->tp_alloc(type, 0)); // initialize object structure self->m_filter = NULL; // return allocated object @@ -101,7 +101,7 @@ PyObject * Filter_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwd } // object deallocation -void Filter_dealloc (PyFilter * self) +void Filter_dealloc (PyFilter *self) { // release object attributes if (self->m_filter != NULL) @@ -114,7 +114,7 @@ void Filter_dealloc (PyFilter * self) // get previous pixel filter object -PyObject * Filter_getPrevious (PyFilter * self, void * closure) +PyObject *Filter_getPrevious (PyFilter *self, void *closure) { // if filter object is available if (self->m_filter != NULL) @@ -135,7 +135,7 @@ PyObject * Filter_getPrevious (PyFilter * self, void * closure) // set previous pixel filter object -int Filter_setPrevious (PyFilter * self, PyObject * value, void * closure) +int Filter_setPrevious (PyFilter *self, PyObject *value, void *closure) { // if filter object is available if (self->m_filter != NULL) diff --git a/source/gameengine/VideoTexture/FilterBase.h b/source/gameengine/VideoTexture/FilterBase.h index 63561c25ffa..98bc495375a 100644 --- a/source/gameengine/VideoTexture/FilterBase.h +++ b/source/gameengine/VideoTexture/FilterBase.h @@ -95,6 +95,10 @@ protected: virtual unsigned int filter (unsigned int * src, short x, short y, short * size, unsigned int pixSize, unsigned int val = 0) { return val; } + /// filter pixel, source float buffer + virtual unsigned int filter (float * src, short x, short y, + short * size, unsigned int pixSize, unsigned int val = 0) + { return val; } /// get source pixel size virtual unsigned int getPixelSize (void) { return 1; } @@ -118,9 +122,9 @@ extern PyTypeList pyFilterTypes; // functions for python interface // object initialization -template static int Filter_init (PyObject * pySelf, PyObject * args, PyObject * kwds) +template static int Filter_init (PyObject *pySelf, PyObject *args, PyObject *kwds) { - PyFilter * self = reinterpret_cast(pySelf); + PyFilter *self = reinterpret_cast(pySelf); // create filter object if (self->m_filter != NULL) delete self->m_filter; self->m_filter = new T(); @@ -129,14 +133,14 @@ template static int Filter_init (PyObject * pySelf, PyObject * args, P } // object allocation -PyObject * Filter_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds); +PyObject *Filter_allocNew(PyTypeObject *type, PyObject *args, PyObject *kwds); // object deallocation -void Filter_dealloc (PyFilter * self); +void Filter_dealloc(PyFilter *self); // get previous pixel filter object -PyObject * Filter_getPrevious (PyFilter * self, void * closure); +PyObject *Filter_getPrevious(PyFilter *self, void *closure); // set previous pixel filter object -int Filter_setPrevious (PyFilter * self, PyObject * value, void * closure); +int Filter_setPrevious(PyFilter *self, PyObject *value, void *closure); #endif diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.cpp b/source/gameengine/VideoTexture/FilterBlueScreen.cpp index 02a6a8f0344..8559e8f87f4 100644 --- a/source/gameengine/VideoTexture/FilterBlueScreen.cpp +++ b/source/gameengine/VideoTexture/FilterBlueScreen.cpp @@ -66,21 +66,21 @@ void FilterBlueScreen::setLimits (unsigned short minLimit, unsigned short maxLim // cast Filter pointer to FilterBlueScreen -inline FilterBlueScreen * getFilter (PyFilter * self) +inline FilterBlueScreen * getFilter (PyFilter *self) { return static_cast(self->m_filter); } // python methods and get/sets // get color -static PyObject * getColor (PyFilter * self, void * closure) +static PyObject *getColor (PyFilter *self, void *closure) { return Py_BuildValue("[BBB]", getFilter(self)->getColor()[0], getFilter(self)->getColor()[1], getFilter(self)->getColor()[2]); } // set color -static int setColor (PyFilter * self, PyObject * value, void * closure) +static int setColor (PyFilter *self, PyObject *value, void *closure) { // check validity of parameter if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 3 @@ -100,14 +100,14 @@ static int setColor (PyFilter * self, PyObject * value, void * closure) } // get limits -static PyObject * getLimits (PyFilter * self, void * closure) +static PyObject *getLimits (PyFilter *self, void *closure) { return Py_BuildValue("[II]", getFilter(self)->getLimits()[0], getFilter(self)->getLimits()[1]); } // set limit -static int setLimits (PyFilter * self, PyObject * value, void * closure) +static int setLimits (PyFilter *self, PyObject *value, void *closure) { // check validity of parameter if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 2 diff --git a/source/gameengine/VideoTexture/FilterColor.cpp b/source/gameengine/VideoTexture/FilterColor.cpp index ed75b4f8da8..35a6414f383 100644 --- a/source/gameengine/VideoTexture/FilterColor.cpp +++ b/source/gameengine/VideoTexture/FilterColor.cpp @@ -108,14 +108,14 @@ void FilterColor::setMatrix (ColorMatrix & mat) // cast Filter pointer to FilterColor -inline FilterColor * getFilterColor (PyFilter * self) +inline FilterColor * getFilterColor (PyFilter *self) { return static_cast(self->m_filter); } // python methods and get/sets // get color matrix -static PyObject * getMatrix (PyFilter * self, void * closure) +static PyObject *getMatrix (PyFilter *self, void *closure) { ColorMatrix & mat = getFilterColor(self)->getMatrix(); return Py_BuildValue("((hhhhh)(hhhhh)(hhhhh)(hhhhh))", @@ -126,7 +126,7 @@ static PyObject * getMatrix (PyFilter * self, void * closure) } // set color matrix -static int setMatrix (PyFilter * self, PyObject * value, void * closure) +static int setMatrix (PyFilter *self, PyObject *value, void *closure) { // matrix to store items ColorMatrix mat; @@ -243,14 +243,14 @@ void FilterLevel::setLevels (ColorLevel & lev) // cast Filter pointer to FilterLevel -inline FilterLevel * getFilterLevel (PyFilter * self) +inline FilterLevel * getFilterLevel (PyFilter *self) { return static_cast(self->m_filter); } // python methods and get/sets // get color levels -static PyObject * getLevels (PyFilter * self, void * closure) +static PyObject *getLevels (PyFilter *self, void *closure) { ColorLevel & lev = getFilterLevel(self)->getLevels(); return Py_BuildValue("((HH)(HH)(HH)(HH))", @@ -259,7 +259,7 @@ static PyObject * getLevels (PyFilter * self, void * closure) } // set color levels -static int setLevels (PyFilter * self, PyObject * value, void * closure) +static int setLevels (PyFilter *self, PyObject *value, void *closure) { // matrix to store items ColorLevel lev; diff --git a/source/gameengine/VideoTexture/FilterNormal.cpp b/source/gameengine/VideoTexture/FilterNormal.cpp index dda1a493291..03c500a7e14 100644 --- a/source/gameengine/VideoTexture/FilterNormal.cpp +++ b/source/gameengine/VideoTexture/FilterNormal.cpp @@ -59,20 +59,20 @@ void FilterNormal::setDepth (float depth) // cast Filter pointer to FilterNormal -inline FilterNormal * getFilter (PyFilter * self) +inline FilterNormal * getFilter (PyFilter *self) { return static_cast(self->m_filter); } // python methods and get/sets // get index of color used to calculate normal -static PyObject * getColor (PyFilter * self, void * closure) +static PyObject *getColor (PyFilter *self, void *closure) { return Py_BuildValue("H", getFilter(self)->getColor()); } // set index of color used to calculate normal -static int setColor (PyFilter * self, PyObject * value, void * closure) +static int setColor (PyFilter *self, PyObject *value, void *closure) { // check validity of parameter if (value == NULL || !PyLong_Check(value)) @@ -88,13 +88,13 @@ static int setColor (PyFilter * self, PyObject * value, void * closure) // get depth -static PyObject * getDepth (PyFilter * self, void * closure) +static PyObject *getDepth (PyFilter *self, void *closure) { return Py_BuildValue("f", getFilter(self)->getDepth()); } // set depth -static int setDepth (PyFilter * self, PyObject * value, void * closure) +static int setDepth (PyFilter *self, PyObject *value, void *closure) { // check validity of parameter if (value) diff --git a/source/gameengine/VideoTexture/FilterSource.h b/source/gameengine/VideoTexture/FilterSource.h index a4900e8c148..cb9e22a133d 100644 --- a/source/gameengine/VideoTexture/FilterSource.h +++ b/source/gameengine/VideoTexture/FilterSource.h @@ -31,7 +31,6 @@ http://www.gnu.org/copyleft/lesser.txt. #include "FilterBase.h" - /// class for RGB24 conversion class FilterRGB24 : public FilterBase { @@ -97,6 +96,65 @@ protected: { VT_RGBA(val,src[2],src[1],src[0],0xFF); return val; } }; +/// class for Z_buffer conversion +class FilterZZZA : public FilterBase +{ +public: + /// constructor + FilterZZZA (void) {} + /// destructor + virtual ~FilterZZZA (void) {} + + /// get source pixel size + virtual unsigned int getPixelSize (void) { return 1; } + +protected: + /// filter pixel, source float buffer + virtual unsigned int filter (float * src, short x, short y, + short * size, unsigned int pixSize, unsigned int val) + { + // calculate gray value + // convert float to unsigned char + unsigned int depth = int(src[0] * 255); + // return depth scale value + VT_R(val) = depth; + VT_G(val) = depth; + VT_B(val) = depth; + VT_A(val) = 0xFF; + + return val; + } +}; + + +/// class for Z_buffer conversion +class FilterDEPTH : public FilterBase +{ +public: + /// constructor + FilterDEPTH (void) {} + /// destructor + virtual ~FilterDEPTH (void) {} + + /// get source pixel size + virtual unsigned int getPixelSize (void) { return 1; } + +protected: + /// filter pixel, source float buffer + virtual unsigned int filter (float * src, short x, short y, + short * size, unsigned int pixSize, unsigned int val) + { + /* Copy the float value straight away + * The user can retrieve the original float value by using + * 'F' mode in BGL buffer */ + memcpy(&val, src, sizeof (unsigned int)); + return val; + } +}; + + + + /// class for YV12 conversion class FilterYV12 : public FilterBase { diff --git a/source/gameengine/VideoTexture/ImageBase.cpp b/source/gameengine/VideoTexture/ImageBase.cpp index 54c1939ce6b..de54d8e8940 100644 --- a/source/gameengine/VideoTexture/ImageBase.cpp +++ b/source/gameengine/VideoTexture/ImageBase.cpp @@ -49,6 +49,8 @@ extern "C" { // constructor ImageBase::ImageBase (bool staticSrc) : m_image(NULL), m_imgSize(0), m_avail(false), m_scale(false), m_scaleChange(false), m_flip(false), +m_zbuff(false), +m_depth(false), m_staticSources(staticSrc), m_pyfilter(NULL) { m_size[0] = m_size[1] = 0; @@ -128,7 +130,7 @@ PyImage * ImageBase::getSource (const char * id) // set source object -bool ImageBase::setSource (const char * id, PyImage * source) +bool ImageBase::setSource (const char * id, PyImage *source) { // find source ImageSourceList::iterator src = findSource(id); @@ -315,7 +317,7 @@ bool ImageSource::is (const char * id) // set source object -void ImageSource::setSource (PyImage * source) +void ImageSource::setSource (PyImage *source) { // reference new source if (source != NULL) Py_INCREF(source); @@ -358,10 +360,10 @@ PyTypeList pyImageTypes; // functions for python interface // object allocation -PyObject * Image_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds) +PyObject *Image_allocNew (PyTypeObject *type, PyObject *args, PyObject *kwds) { // allocate object - PyImage * self = reinterpret_cast(type->tp_alloc(type, 0)); + PyImage *self = reinterpret_cast(type->tp_alloc(type, 0)); // initialize object structure self->m_image = NULL; // return allocated object @@ -369,7 +371,7 @@ PyObject * Image_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds } // object deallocation -void Image_dealloc (PyImage * self) +void Image_dealloc (PyImage *self) { // release object attributes if (self->m_image != NULL) @@ -388,7 +390,7 @@ void Image_dealloc (PyImage * self) } // get image data -PyObject * Image_getImage (PyImage * self, char * mode) +PyObject *Image_getImage (PyImage *self, char * mode) { try { @@ -402,6 +404,18 @@ PyObject * Image_getImage (PyImage * self, char * mode) { buffer = BGL_MakeBuffer( GL_BYTE, 1, &dimensions, image); } + else if (!strcasecmp(mode, "F")) + { + // this mode returns the image as an array of float. + // This makes sense ONLY for the depth buffer: + // source = VideoTexture.ImageViewport() + // source.depth = True + // depth = VideoTexture.imageToArray(source, 'F') + + // adapt dimension from byte to float + dimensions /= sizeof(float); + buffer = BGL_MakeBuffer( GL_FLOAT, 1, &dimensions, image); + } else { int i, c, ncolor, pixels; @@ -463,7 +477,7 @@ PyObject * Image_getImage (PyImage * self, char * mode) } } } - return (PyObject*)buffer; + return (PyObject *)buffer; } } catch (Exception & exp) @@ -475,28 +489,28 @@ PyObject * Image_getImage (PyImage * self, char * mode) } // get image size -PyObject * Image_getSize (PyImage * self, void * closure) +PyObject *Image_getSize (PyImage *self, void *closure) { return Py_BuildValue("(hh)", self->m_image->getSize()[0], self->m_image->getSize()[1]); } // refresh image -PyObject * Image_refresh (PyImage * self) +PyObject *Image_refresh (PyImage *self) { self->m_image->refresh(); Py_RETURN_NONE; } // get scale -PyObject * Image_getScale (PyImage * self, void * closure) +PyObject *Image_getScale (PyImage *self, void *closure) { if (self->m_image != NULL && self->m_image->getScale()) Py_RETURN_TRUE; else Py_RETURN_FALSE; } // set scale -int Image_setScale (PyImage * self, PyObject * value, void * closure) +int Image_setScale (PyImage *self, PyObject *value, void *closure) { // check parameter, report failure if (value == NULL || !PyBool_Check(value)) @@ -511,14 +525,14 @@ int Image_setScale (PyImage * self, PyObject * value, void * closure) } // get flip -PyObject * Image_getFlip (PyImage * self, void * closure) +PyObject *Image_getFlip (PyImage *self, void *closure) { if (self->m_image != NULL && self->m_image->getFlip()) Py_RETURN_TRUE; else Py_RETURN_FALSE; } // set flip -int Image_setFlip (PyImage * self, PyObject * value, void * closure) +int Image_setFlip (PyImage *self, PyObject *value, void *closure) { // check parameter, report failure if (value == NULL || !PyBool_Check(value)) @@ -532,9 +546,55 @@ int Image_setFlip (PyImage * self, PyObject * value, void * closure) return 0; } +// get zbuff +PyObject * Image_getZbuff (PyImage * self, void * closure) +{ + if (self->m_image != NULL && self->m_image->getZbuff()) Py_RETURN_TRUE; + else Py_RETURN_FALSE; +} + +// set zbuff +int Image_setZbuff (PyImage * self, PyObject * value, void * closure) +{ + // check parameter, report failure + if (value == NULL || !PyBool_Check(value)) + { + PyErr_SetString(PyExc_TypeError, "The value must be a bool"); + return -1; + } + // set scale + if (self->m_image != NULL) self->m_image->setZbuff(value == Py_True); + // success + return 0; +} + +// get depth +PyObject * Image_getDepth (PyImage * self, void * closure) +{ + if (self->m_image != NULL && self->m_image->getDepth()) Py_RETURN_TRUE; + else Py_RETURN_FALSE; +} + +// set depth +int Image_setDepth (PyImage * self, PyObject * value, void * closure) +{ + // check parameter, report failure + if (value == NULL || !PyBool_Check(value)) + { + PyErr_SetString(PyExc_TypeError, "The value must be a bool"); + return -1; + } + // set scale + if (self->m_image != NULL) self->m_image->setDepth(value == Py_True); + // success + return 0; +} + + + // get filter source object -PyObject * Image_getSource (PyImage * self, PyObject * args) +PyObject *Image_getSource (PyImage *self, PyObject *args) { // get arguments char * id; @@ -543,7 +603,7 @@ PyObject * Image_getSource (PyImage * self, PyObject * args) if (self->m_image != NULL) { // get source object - PyObject * src = reinterpret_cast(self->m_image->getSource(id)); + PyObject *src = reinterpret_cast(self->m_image->getSource(id)); // if source is available if (src != NULL) { @@ -558,11 +618,11 @@ PyObject * Image_getSource (PyImage * self, PyObject * args) // set filter source object -PyObject * Image_setSource (PyImage * self, PyObject * args) +PyObject *Image_setSource (PyImage *self, PyObject *args) { // get arguments char * id; - PyObject * obj; + PyObject *obj; if (!PyArg_ParseTuple(args, "sO:setSource", &id, &obj)) return NULL; if (self->m_image != NULL) @@ -593,7 +653,7 @@ PyObject * Image_setSource (PyImage * self, PyObject * args) // get pixel filter object -PyObject * Image_getFilter (PyImage * self, void * closure) +PyObject *Image_getFilter (PyImage *self, void *closure) { // if image object is available if (self->m_image != NULL) @@ -614,7 +674,7 @@ PyObject * Image_getFilter (PyImage * self, void * closure) // set pixel filter object -int Image_setFilter (PyImage * self, PyObject * value, void * closure) +int Image_setFilter (PyImage *self, PyObject *value, void *closure) { // if image object is available if (self->m_image != NULL) @@ -632,7 +692,7 @@ int Image_setFilter (PyImage * self, PyObject * value, void * closure) // return success return 0; } -PyObject * Image_valid(PyImage * self, void * closure) +PyObject *Image_valid(PyImage *self, void *closure) { if (self->m_image->isImageAvailable()) { @@ -644,7 +704,7 @@ PyObject * Image_valid(PyImage * self, void * closure) } } -int Image_getbuffer(PyImage *self, Py_buffer *view, int flags) +static int Image_getbuffer(PyImage *self, Py_buffer *view, int flags) { unsigned int * image; int ret; @@ -674,7 +734,7 @@ int Image_getbuffer(PyImage *self, Py_buffer *view, int flags) self->m_image->m_exports++; return 0; } - ret = PyBuffer_FillInfo(view, (PyObject*)self, image, self->m_image->getBuffSize(), 0, flags); + ret = PyBuffer_FillInfo(view, (PyObject *)self, image, self->m_image->getBuffSize(), 0, flags); if (ret >= 0) self->m_image->m_exports++; return ret; @@ -684,14 +744,14 @@ error: // The bug is fixed in Python SVN 77916, as soon as the python revision used by Blender is // updated, you can simply return -1 and set the error static char* buf = (char *)""; - ret = PyBuffer_FillInfo(view, (PyObject*)self, buf, 0, 0, flags); + ret = PyBuffer_FillInfo(view, (PyObject *)self, buf, 0, 0, flags); if (ret >= 0) self->m_image->m_exports++; return ret; } -void Image_releaseBuffer(PyImage *self, Py_buffer *buffer) +static void Image_releaseBuffer(PyImage *self, Py_buffer *buffer) { self->m_image->m_exports--; } diff --git a/source/gameengine/VideoTexture/ImageBase.h b/source/gameengine/VideoTexture/ImageBase.h index 6c38b107a4d..a9f25f61406 100644 --- a/source/gameengine/VideoTexture/ImageBase.h +++ b/source/gameengine/VideoTexture/ImageBase.h @@ -78,11 +78,19 @@ public: bool getFlip (void) { return m_flip; } /// set vertical flip void setFlip (bool flip) { m_flip = flip; } + /// get Z buffer + bool getZbuff (void) { return m_zbuff; } + /// set Z buffer + void setZbuff (bool zbuff) { m_zbuff = zbuff; } + /// get depth + bool getDepth (void) { return m_depth; } + /// set depth + void setDepth (bool depth) { m_depth = depth; } /// get source object PyImage * getSource (const char * id); /// set source object, return true, if source was set - bool setSource (const char * id, PyImage * source); + bool setSource (const char * id, PyImage *source); /// get pixel filter PyFilter * getFilter (void) { return m_pyfilter; } @@ -111,6 +119,10 @@ protected: bool m_scaleChange; /// flip image vertically bool m_flip; + /// use the Z buffer as a texture + bool m_zbuff; + /// extract the Z buffer with unisgned int precision + bool m_depth; /// source image list ImageSourceList m_sources; @@ -276,7 +288,7 @@ public: /// get source object PyImage * getSource (void) { return m_source; } /// set source object - void setSource (PyImage * source); + void setSource (PyImage *source); /// get image from source unsigned int * getImage (double ts=-1.0); @@ -312,9 +324,9 @@ extern PyTypeList pyImageTypes; // functions for python interface // object initialization -template static int Image_init (PyObject * pySelf, PyObject * args, PyObject * kwds) +template static int Image_init (PyObject *pySelf, PyObject *args, PyObject *kwds) { - PyImage * self = reinterpret_cast(pySelf); + PyImage *self = reinterpret_cast(pySelf); // create source object if (self->m_image != NULL) delete self->m_image; self->m_image = new T(); @@ -323,37 +335,45 @@ template static int Image_init (PyObject * pySelf, PyObject * args, Py } // object allocation -PyObject * Image_allocNew (PyTypeObject * type, PyObject * args, PyObject * kwds); +PyObject *Image_allocNew (PyTypeObject *type, PyObject *args, PyObject *kwds); // object deallocation -void Image_dealloc (PyImage * self); +void Image_dealloc (PyImage *self); // get image data -PyObject * Image_getImage (PyImage * self, char * mode); +PyObject *Image_getImage (PyImage *self, char * mode); // get image size -PyObject * Image_getSize (PyImage * self, void * closure); +PyObject *Image_getSize (PyImage *self, void *closure); // refresh image - invalidate current content -PyObject * Image_refresh (PyImage * self); +PyObject *Image_refresh (PyImage *self); // get scale -PyObject * Image_getScale (PyImage * self, void * closure); +PyObject *Image_getScale (PyImage *self, void *closure); // set scale -int Image_setScale (PyImage * self, PyObject * value, void * closure); +int Image_setScale (PyImage *self, PyObject *value, void *closure); // get flip -PyObject * Image_getFlip (PyImage * self, void * closure); +PyObject *Image_getFlip (PyImage *self, void *closure); // set flip -int Image_setFlip (PyImage * self, PyObject * value, void * closure); +int Image_setFlip (PyImage *self, PyObject *value, void *closure); // get filter source object -PyObject * Image_getSource (PyImage * self, PyObject * args); +PyObject *Image_getSource (PyImage *self, PyObject *args); // set filter source object -PyObject * Image_setSource (PyImage * self, PyObject * args); - +PyObject *Image_setSource (PyImage *self, PyObject *args); +// get Z buffer +PyObject * Image_getZbuff (PyImage * self, void * closure); +// set Z buffer +int Image_setZbuff (PyImage * self, PyObject * value, void * closure); +// get depth +PyObject * Image_getDepth (PyImage * self, void * closure); +// set depth +int Image_setDepth (PyImage * self, PyObject * value, void * closure); + // get pixel filter object -PyObject * Image_getFilter (PyImage * self, void * closure); +PyObject *Image_getFilter (PyImage *self, void *closure); // set pixel filter object -int Image_setFilter (PyImage * self, PyObject * value, void * closure); +int Image_setFilter (PyImage *self, PyObject *value, void *closure); // check if a buffer can be extracted -PyObject * Image_valid(PyImage * self, void * closure); +PyObject *Image_valid(PyImage *self, void *closure); // for buffer access to PyImage objects extern PyBufferProcs imageBufferProcs; diff --git a/source/gameengine/VideoTexture/ImageBuff.cpp b/source/gameengine/VideoTexture/ImageBuff.cpp index 17513d20a39..eec0bccbe56 100644 --- a/source/gameengine/VideoTexture/ImageBuff.cpp +++ b/source/gameengine/VideoTexture/ImageBuff.cpp @@ -47,7 +47,7 @@ FilterRGB24 defFilter; // forward declaration; extern PyTypeObject ImageBuffType; -static int ImageBuff_init (PyObject * pySelf, PyObject * args, PyObject * kwds) +static int ImageBuff_init (PyObject *pySelf, PyObject *args, PyObject *kwds) { short width = -1; short height = -1; @@ -55,7 +55,7 @@ static int ImageBuff_init (PyObject * pySelf, PyObject * args, PyObject * kwds) PyObject *py_scale = Py_False; ImageBuff *image; - PyImage * self = reinterpret_cast(pySelf); + PyImage *self = reinterpret_cast(pySelf); // create source object if (self->m_image != NULL) delete self->m_image; @@ -190,7 +190,7 @@ void ImageBuff::plot (ImageBuff* img, short x, short y, short mode) // cast Image pointer to ImageBuff -inline ImageBuff * getImageBuff (PyImage * self) +inline ImageBuff * getImageBuff (PyImage *self) { return static_cast(self->m_image); } @@ -245,7 +245,7 @@ static bool testBGLBuffer(Buffer* buffer, int width, int height, unsigned int pi // load image -static PyObject * load (PyImage * self, PyObject * args) +static PyObject *load(PyImage *self, PyObject *args) { // parameters: string image buffer, its size, width, height Py_buffer buffer; @@ -306,10 +306,10 @@ static PyObject * load (PyImage * self, PyObject * args) } if (PyErr_Occurred()) return NULL; - Py_RETURN_NONE; + Py_RETURN_NONE; } -static PyObject * plot (PyImage * self, PyObject * args) +static PyObject *plot (PyImage *self, PyObject *args) { PyImage * other; Buffer* bglBuffer; @@ -332,7 +332,7 @@ static PyObject * plot (PyImage * self, PyObject * args) PyBuffer_Release(&buffer); if (PyErr_Occurred()) return NULL; - Py_RETURN_NONE; + Py_RETURN_NONE; } PyErr_Clear(); // try the other format @@ -354,7 +354,7 @@ static PyObject * plot (PyImage * self, PyObject * args) } if (PyErr_Occurred()) return NULL; - Py_RETURN_NONE; + Py_RETURN_NONE; } // methods structure diff --git a/source/gameengine/VideoTexture/ImageMix.cpp b/source/gameengine/VideoTexture/ImageMix.cpp index cd8c6683a7f..f09454a517b 100644 --- a/source/gameengine/VideoTexture/ImageMix.cpp +++ b/source/gameengine/VideoTexture/ImageMix.cpp @@ -101,14 +101,14 @@ void ImageMix::calcImage (unsigned int texId, double ts) // cast Image pointer to ImageMix -inline ImageMix * getImageMix (PyImage * self) +inline ImageMix * getImageMix (PyImage *self) { return static_cast(self->m_image); } // python methods // get source weight -PyObject * getWeight (PyImage * self, PyObject * args) +static PyObject *getWeight (PyImage *self, PyObject *args) { // weight short weight = 0; @@ -125,7 +125,7 @@ PyObject * getWeight (PyImage * self, PyObject * args) // set source weight -PyObject * setWeight (PyImage * self, PyObject * args) +static PyObject *setWeight (PyImage *self, PyObject *args) { // get arguments char * id; diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index c8763671dd1..85857165403 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -277,7 +277,7 @@ void ImageRender::Render() // cast Image pointer to ImageRender -inline ImageRender * getImageRender (PyImage * self) +inline ImageRender * getImageRender (PyImage *self) { return static_cast(self->m_image); } @@ -290,10 +290,10 @@ BlendType cameraType ("KX_Camera"); // object initialization -static int ImageRender_init (PyObject * pySelf, PyObject * args, PyObject * kwds) +static int ImageRender_init (PyObject *pySelf, PyObject *args, PyObject *kwds) { // parameters - scene object - PyObject * scene; + PyObject *scene; // camera object PyObject * camera; // parameter keywords @@ -317,7 +317,7 @@ static int ImageRender_init (PyObject * pySelf, PyObject * args, PyObject * kwds if (cameraPtr == NULL) THRWEXCP(CameraInvalid, S_OK); // get pointer to image structure - PyImage * self = reinterpret_cast(pySelf); + PyImage *self = reinterpret_cast(pySelf); // create source object if (self->m_image != NULL) delete self->m_image; self->m_image = new ImageRender(scenePtr, cameraPtr); @@ -333,7 +333,7 @@ static int ImageRender_init (PyObject * pySelf, PyObject * args, PyObject * kwds // get background color -PyObject * getBackground (PyImage * self, void * closure) +static PyObject *getBackground (PyImage *self, void *closure) { return Py_BuildValue("[BBBB]", getImageRender(self)->getBackground(0), @@ -343,7 +343,7 @@ PyObject * getBackground (PyImage * self, void * closure) } // set color -static int setBackground (PyImage * self, PyObject * value, void * closure) +static int setBackground (PyImage *self, PyObject *value, void *closure) { // check validity of parameter if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 4 @@ -385,6 +385,8 @@ static PyGetSetDef imageRenderGetSets[] = {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL}, {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbor)", NULL}, {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL}, + {(char*)"zbuff", (getter)Image_getZbuff, (setter)Image_setZbuff, (char*)"use depth buffer as texture", NULL}, + {(char*)"depth", (getter)Image_getDepth, (setter)Image_setDepth, (char*)"get depth information from z-buffer using unsigned int precision", NULL}, {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL}, {NULL} }; @@ -434,14 +436,14 @@ PyTypeObject ImageRenderType = }; // object initialization -static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds) +static int ImageMirror_init (PyObject *pySelf, PyObject *args, PyObject *kwds) { // parameters - scene object - PyObject * scene; + PyObject *scene; // reference object for mirror - PyObject * observer; + PyObject *observer; // object holding the mirror - PyObject * mirror; + PyObject *mirror; // material of the mirror short materialID = 0; // parameter keywords @@ -490,7 +492,7 @@ static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds THRWEXCP(MaterialNotAvail, S_OK); // get pointer to image structure - PyImage * self = reinterpret_cast(pySelf); + PyImage *self = reinterpret_cast(pySelf); // create source object if (self->m_image != NULL) @@ -510,13 +512,13 @@ static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds } // get background color -PyObject * getClip (PyImage * self, void * closure) +static PyObject *getClip (PyImage *self, void *closure) { return PyFloat_FromDouble(getImageRender(self)->getClip()); } // set clip -static int setClip (PyImage * self, PyObject * value, void * closure) +static int setClip (PyImage *self, PyObject *value, void *closure) { // check validity of parameter double clip; @@ -547,6 +549,8 @@ static PyGetSetDef imageMirrorGetSets[] = {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL}, {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbor)", NULL}, {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL}, + {(char*)"zbuff", (getter)Image_getZbuff, (setter)Image_setZbuff, (char*)"use depth buffer as texture", NULL}, + {(char*)"depth", (getter)Image_getDepth, (setter)Image_setDepth, (char*)"get depth information from z-buffer using unsigned int precision", NULL}, {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL}, {NULL} }; diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp index a780fdcc38c..af44e394fce 100644 --- a/source/gameengine/VideoTexture/ImageViewport.cpp +++ b/source/gameengine/VideoTexture/ImageViewport.cpp @@ -50,6 +50,8 @@ ImageViewport::ImageViewport (void) : m_alpha(false), m_texInit(false) //glGetIntegerv(GL_VIEWPORT, m_viewport); // create buffer for viewport image + // Warning: this buffer is also used to get the depth buffer as an array of + // float (1 float = 4 bytes per pixel) m_viewportImage = new BYTE [4 * getViewportSize()[0] * getViewportSize()[1]]; // set attributes setWhole(false); @@ -57,7 +59,9 @@ ImageViewport::ImageViewport (void) : m_alpha(false), m_texInit(false) // destructor ImageViewport::~ImageViewport (void) -{ delete [] m_viewportImage; } +{ + delete [] m_viewportImage; +} // use whole viewport to capture image @@ -123,15 +127,14 @@ void ImageViewport::calcImage (unsigned int texId, double ts) // reset image init(m_capSize[0], m_capSize[1]); // if texture wasn't initialized - if (!m_texInit) - { + if (!m_texInit) { // initialize it loadTexture(texId, m_image, m_size); m_texInit = true; } // if texture can be directly created if (texId != 0 && m_pyfilter == NULL && m_capSize[0] == calcSize(m_capSize[0]) - && m_capSize[1] == calcSize(m_capSize[1]) && !m_flip) + && m_capSize[1] == calcSize(m_capSize[1]) && !m_flip && !m_zbuff && !m_depth) { // just copy current viewport to texture glBindTexture(GL_TEXTURE_2D, texId); @@ -140,24 +143,47 @@ void ImageViewport::calcImage (unsigned int texId, double ts) m_avail = false; } // otherwise copy viewport to buffer, if image is not available - else if (!m_avail) - { - // get frame buffer data - if (m_alpha) - { - glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], GL_RGBA, - GL_UNSIGNED_BYTE, m_viewportImage); + else if (!m_avail) { + if (m_zbuff) { + // Use read pixels with the depth buffer + // *** misusing m_viewportImage here, but since it has the correct size + // (4 bytes per pixel = size of float) and we just need it to apply + // the filter, it's ok + glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], + GL_DEPTH_COMPONENT, GL_FLOAT, m_viewportImage); // filter loaded data - FilterRGBA32 filt; - filterImage(filt, m_viewportImage, m_capSize); + FilterZZZA filt; + filterImage(filt, (float *)m_viewportImage, m_capSize); } - else - { - glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], GL_RGB, - GL_UNSIGNED_BYTE, m_viewportImage); - // filter loaded data - FilterRGB24 filt; - filterImage(filt, m_viewportImage, m_capSize); + else { + + if (m_depth) { + // Use read pixels with the depth buffer + // See warning above about m_viewportImage. + glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], + GL_DEPTH_COMPONENT, GL_FLOAT, m_viewportImage); + // filter loaded data + FilterDEPTH filt; + filterImage(filt, (float *)m_viewportImage, m_capSize); + } + else { + + // get frame buffer data + if (m_alpha) { + glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], GL_RGBA, + GL_UNSIGNED_BYTE, m_viewportImage); + // filter loaded data + FilterRGBA32 filt; + filterImage(filt, m_viewportImage, m_capSize); + } + else { + glReadPixels(m_upLeft[0], m_upLeft[1], (GLsizei)m_capSize[0], (GLsizei)m_capSize[1], GL_RGB, + GL_UNSIGNED_BYTE, m_viewportImage); + // filter loaded data + FilterRGB24 filt; + filterImage(filt, m_viewportImage, m_capSize); + } + } } } } @@ -165,7 +191,7 @@ void ImageViewport::calcImage (unsigned int texId, double ts) // cast Image pointer to ImageViewport -inline ImageViewport * getImageViewport (PyImage * self) +inline ImageViewport * getImageViewport (PyImage *self) { return static_cast(self->m_image); } @@ -173,14 +199,14 @@ inline ImageViewport * getImageViewport (PyImage * self) // get whole -PyObject * ImageViewport_getWhole (PyImage * self, void * closure) +PyObject *ImageViewport_getWhole (PyImage *self, void *closure) { if (self->m_image != NULL && getImageViewport(self)->getWhole()) Py_RETURN_TRUE; else Py_RETURN_FALSE; } // set whole -int ImageViewport_setWhole (PyImage * self, PyObject * value, void * closure) +int ImageViewport_setWhole (PyImage *self, PyObject *value, void *closure) { // check parameter, report failure if (value == NULL || !PyBool_Check(value)) @@ -203,14 +229,14 @@ int ImageViewport_setWhole (PyImage * self, PyObject * value, void * closure) } // get alpha -PyObject * ImageViewport_getAlpha (PyImage * self, void * closure) +PyObject *ImageViewport_getAlpha (PyImage *self, void *closure) { if (self->m_image != NULL && getImageViewport(self)->getAlpha()) Py_RETURN_TRUE; else Py_RETURN_FALSE; } // set whole -int ImageViewport_setAlpha (PyImage * self, PyObject * value, void * closure) +int ImageViewport_setAlpha (PyImage *self, PyObject *value, void *closure) { // check parameter, report failure if (value == NULL || !PyBool_Check(value)) @@ -226,14 +252,14 @@ int ImageViewport_setAlpha (PyImage * self, PyObject * value, void * closure) // get position -static PyObject * ImageViewport_getPosition (PyImage * self, void * closure) +static PyObject *ImageViewport_getPosition (PyImage *self, void *closure) { return Py_BuildValue("(ii)", getImageViewport(self)->getPosition()[0], getImageViewport(self)->getPosition()[1]); } // set position -static int ImageViewport_setPosition (PyImage * self, PyObject * value, void * closure) +static int ImageViewport_setPosition (PyImage *self, PyObject *value, void *closure) { // check validity of parameter if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 2 @@ -254,14 +280,14 @@ static int ImageViewport_setPosition (PyImage * self, PyObject * value, void * c } // get capture size -PyObject * ImageViewport_getCaptureSize (PyImage * self, void * closure) +PyObject *ImageViewport_getCaptureSize (PyImage *self, void *closure) { return Py_BuildValue("(ii)", getImageViewport(self)->getCaptureSize()[0], getImageViewport(self)->getCaptureSize()[1]); } // set capture size -int ImageViewport_setCaptureSize (PyImage * self, PyObject * value, void * closure) +int ImageViewport_setCaptureSize (PyImage *self, PyObject *value, void *closure) { // check validity of parameter if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 2 @@ -310,6 +336,8 @@ static PyGetSetDef imageViewportGetSets[] = {(char*)"size", (getter)Image_getSize, NULL, (char*)"image size", NULL}, {(char*)"scale", (getter)Image_getScale, (setter)Image_setScale, (char*)"fast scale of image (near neighbor)", NULL}, {(char*)"flip", (getter)Image_getFlip, (setter)Image_setFlip, (char*)"flip image vertically", NULL}, + {(char*)"zbuff", (getter)Image_getZbuff, (setter)Image_setZbuff, (char*)"use depth buffer as texture", NULL}, + {(char*)"depth", (getter)Image_getDepth, (setter)Image_setDepth, (char*)"get depth information from z-buffer as array of float", NULL}, {(char*)"filter", (getter)Image_getFilter, (setter)Image_setFilter, (char*)"pixel filter", NULL}, {NULL} }; diff --git a/source/gameengine/VideoTexture/ImageViewport.h b/source/gameengine/VideoTexture/ImageViewport.h index ccc58a41605..198655c6ebf 100644 --- a/source/gameengine/VideoTexture/ImageViewport.h +++ b/source/gameengine/VideoTexture/ImageViewport.h @@ -91,12 +91,12 @@ protected: GLint * getViewportSize (void) { return m_viewport + 2; } }; -PyObject * ImageViewport_getCaptureSize (PyImage * self, void * closure); -int ImageViewport_setCaptureSize (PyImage * self, PyObject * value, void * closure); -PyObject * ImageViewport_getWhole (PyImage * self, void * closure); -int ImageViewport_setWhole (PyImage * self, PyObject * value, void * closure); -PyObject * ImageViewport_getAlpha (PyImage * self, void * closure); -int ImageViewport_setAlpha (PyImage * self, PyObject * value, void * closure); +PyObject *ImageViewport_getCaptureSize (PyImage *self, void *closure); +int ImageViewport_setCaptureSize (PyImage *self, PyObject *value, void *closure); +PyObject *ImageViewport_getWhole (PyImage *self, void *closure); +int ImageViewport_setWhole (PyImage *self, PyObject *value, void *closure); +PyObject *ImageViewport_getAlpha (PyImage *self, void *closure); +int ImageViewport_setAlpha (PyImage *self, PyObject *value, void *closure); #endif diff --git a/source/gameengine/VideoTexture/PyTypeList.cpp b/source/gameengine/VideoTexture/PyTypeList.cpp index ed53e8bd1f1..9fe98544961 100644 --- a/source/gameengine/VideoTexture/PyTypeList.cpp +++ b/source/gameengine/VideoTexture/PyTypeList.cpp @@ -41,7 +41,7 @@ PyTypeList::~PyTypeList() } /// check, if type is in list -bool PyTypeList::in (PyTypeObject * type) +bool PyTypeList::in (PyTypeObject *type) { // if list exists if (m_list.get() != NULL) @@ -54,7 +54,7 @@ bool PyTypeList::in (PyTypeObject * type) } /// add type to list -void PyTypeList::add (PyTypeObject * type, const char * name) +void PyTypeList::add (PyTypeObject *type, const char * name) { // if list doesn't exist, create it if (m_list.get() == NULL) @@ -78,7 +78,7 @@ bool PyTypeList::ready (void) } /// register types to module -void PyTypeList::reg (PyObject * module) +void PyTypeList::reg(PyObject *module) { // if list exists if (m_list.get() != NULL) @@ -88,6 +88,6 @@ void PyTypeList::reg (PyObject * module) // increase ref count Py_INCREF((*it)->getType()); // add type to module - PyModule_AddObject(module, (char*)(*it)->getName(), (PyObject*)(*it)->getType()); + PyModule_AddObject(module, (char*)(*it)->getName(), (PyObject *)(*it)->getType()); } } diff --git a/source/gameengine/VideoTexture/PyTypeList.h b/source/gameengine/VideoTexture/PyTypeList.h index aa1df0ce54b..4872b3c3d5c 100644 --- a/source/gameengine/VideoTexture/PyTypeList.h +++ b/source/gameengine/VideoTexture/PyTypeList.h @@ -49,16 +49,16 @@ public: ~PyTypeList(); /// check, if type is in list - bool in (PyTypeObject * type); + bool in (PyTypeObject *type); /// add type to list - void add (PyTypeObject * type, const char * name); + void add (PyTypeObject *type, const char * name); /// prepare types bool ready (void); /// register types to module - void reg (PyObject * module); + void reg(PyObject *module); protected: /// pointer to list of types @@ -71,21 +71,21 @@ class PyTypeListItem { public: /// constructor adds type into list - PyTypeListItem (PyTypeObject * type, const char * name) + PyTypeListItem (PyTypeObject *type, const char * name) : m_type(type), m_name(name) { } /// does type match - PyTypeObject * getType (void) { return m_type; } + PyTypeObject *getType (void) { return m_type; } /// get name of type const char * getName (void) { return m_name; } protected: /// pointer to type object - PyTypeObject * m_type; + PyTypeObject *m_type; /// name of type - const char * m_name; + const char *m_name; }; diff --git a/source/gameengine/VideoTexture/Texture.cpp b/source/gameengine/VideoTexture/Texture.cpp index a21300018eb..f58d17f949c 100644 --- a/source/gameengine/VideoTexture/Texture.cpp +++ b/source/gameengine/VideoTexture/Texture.cpp @@ -108,7 +108,7 @@ RAS_IPolyMaterial * getMaterial (PyObject *obj, short matID) } // get pointer to a lamp -KX_LightObject * getLamp(PyObject *obj) +static KX_LightObject *getLamp(PyObject *obj) { // if object is available if (obj == NULL) return NULL; @@ -119,7 +119,7 @@ KX_LightObject * getLamp(PyObject *obj) // get material ID -short getMaterialID(PyObject * obj, const char *name) +short getMaterialID(PyObject *obj, const char *name) { // search for material for (short matID = 0;; ++matID) @@ -147,7 +147,7 @@ short getMaterialID(PyObject * obj, const char *name) // Texture object allocation -PyObject * Texture_new (PyTypeObject *type, PyObject *args, PyObject *kwds) +static PyObject *Texture_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { // allocate object Texture * self = reinterpret_cast(type->tp_alloc(type, 0)); @@ -167,22 +167,22 @@ PyObject * Texture_new (PyTypeObject *type, PyObject *args, PyObject *kwds) // forward declaration -PyObject * Texture_close(Texture * self); -int Texture_setSource (Texture * self, PyObject * value, void * closure); +PyObject *Texture_close(Texture * self); +int Texture_setSource (Texture * self, PyObject *value, void *closure); // Texture object deallocation -void Texture_dealloc (Texture * self) +static void Texture_dealloc(Texture *self) { // release renderer Py_XDECREF(self->m_source); // close texture - PyObject* ret = Texture_close(self); + PyObject *ret = Texture_close(self); Py_DECREF(ret); // release scaled image buffer delete [] self->m_scaledImg; // release object - Py_TYPE((PyObject *)self)->tp_free((PyObject*)self); + Py_TYPE((PyObject *)self)->tp_free((PyObject *)self); } @@ -190,10 +190,10 @@ ExceptionID MaterialNotAvail; ExpDesc MaterialNotAvailDesc (MaterialNotAvail, "Texture material is not available"); // Texture object initialization -int Texture_init (Texture *self, PyObject *args, PyObject *kwds) +static int Texture_init(Texture *self, PyObject *args, PyObject *kwds) { // parameters - game object with video texture - PyObject * obj = NULL; + PyObject *obj = NULL; // material ID short matID = 0; // texture ID @@ -275,7 +275,7 @@ int Texture_init (Texture *self, PyObject *args, PyObject *kwds) // close added texture -PyObject * Texture_close(Texture * self) +PyObject *Texture_close(Texture * self) { // restore texture if (self->m_orgSaved) @@ -298,10 +298,10 @@ PyObject * Texture_close(Texture * self) // refresh texture -PyObject * Texture_refresh (Texture * self, PyObject * args) +static PyObject *Texture_refresh(Texture *self, PyObject *args) { // get parameter - refresh source - PyObject * param; + PyObject *param; double ts = -1.0; if (!PyArg_ParseTuple(args, "O|d:refresh", ¶m, &ts) || !PyBool_Check(param)) @@ -390,14 +390,14 @@ PyObject * Texture_refresh (Texture * self, PyObject * args) } // get OpenGL Bind Id -PyObject * Texture_getBindId (Texture * self, void * closure) +static PyObject *Texture_getBindId(Texture *self, void *closure) { unsigned int id = self->m_actTex; return Py_BuildValue("h", id); } // get mipmap value -PyObject * Texture_getMipmap (Texture * self, void * closure) +static PyObject *Texture_getMipmap(Texture *self, void *closure) { // return true if flag is set, otherwise false if (self->m_mipmap) Py_RETURN_TRUE; @@ -405,7 +405,7 @@ PyObject * Texture_getMipmap (Texture * self, void * closure) } // set mipmap value -int Texture_setMipmap (Texture * self, PyObject * value, void * closure) +static int Texture_setMipmap(Texture *self, PyObject *value, void *closure) { // check parameter, report failure if (value == NULL || !PyBool_Check(value)) @@ -421,7 +421,7 @@ int Texture_setMipmap (Texture * self, PyObject * value, void * closure) // get source object -PyObject * Texture_getSource (Texture * self, PyObject * value, void * closure) +static PyObject *Texture_getSource(Texture *self, PyObject *value, void *closure) { // if source exists if (self->m_source != NULL) @@ -435,7 +435,7 @@ PyObject * Texture_getSource (Texture * self, PyObject * value, void * closure) // set source object -int Texture_setSource (Texture * self, PyObject * value, void * closure) +int Texture_setSource (Texture * self, PyObject *value, void *closure) { // check new value if (value == NULL || !pyImageTypes.in(Py_TYPE(value))) diff --git a/source/gameengine/VideoTexture/Texture.h b/source/gameengine/VideoTexture/Texture.h index ad5b7b9fb44..cc265725b29 100644 --- a/source/gameengine/VideoTexture/Texture.h +++ b/source/gameengine/VideoTexture/Texture.h @@ -78,14 +78,14 @@ struct Texture extern PyTypeObject TextureType; // load texture -void loadTexture (unsigned int texId, unsigned int * texture, short * size, - bool mipmap = false); +void loadTexture(unsigned int texId, unsigned int *texture, short *size, + bool mipmap = false); // get material -RAS_IPolyMaterial * getMaterial (PyObject *obj, short matID); +RAS_IPolyMaterial *getMaterial(PyObject *obj, short matID); // get material ID -short getMaterialID (PyObject * obj, const char *name); +short getMaterialID(PyObject *obj, const char *name); // Exceptions extern ExceptionID MaterialNotAvail; diff --git a/source/gameengine/VideoTexture/VideoBase.cpp b/source/gameengine/VideoTexture/VideoBase.cpp index 6662df8d7d1..1eb2e830d37 100644 --- a/source/gameengine/VideoTexture/VideoBase.cpp +++ b/source/gameengine/VideoTexture/VideoBase.cpp @@ -116,24 +116,24 @@ void Video_open (VideoBase * self, char * file, short captureID) // play video -PyObject * Video_play (PyImage * self) +PyObject *Video_play(PyImage *self) { if (getVideo(self)->play()) Py_RETURN_TRUE; else Py_RETURN_FALSE; } // pause video -PyObject * Video_pause (PyImage * self) +PyObject *Video_pause(PyImage *self) { if (getVideo(self)->pause()) Py_RETURN_TRUE; else Py_RETURN_FALSE; } -PyObject * Video_stop (PyImage * self) +PyObject *Video_stop(PyImage *self) { if (getVideo(self)->stop()) Py_RETURN_TRUE; else Py_RETURN_FALSE; } // get status -PyObject * Video_getStatus (PyImage * self, void * closure) +PyObject *Video_getStatus(PyImage *self, void *closure) { return Py_BuildValue("h", getVideo(self)->getStatus()); } // refresh video -PyObject * Video_refresh (PyImage * self) +PyObject *Video_refresh(PyImage *self) { getVideo(self)->refresh(); return Video_getStatus(self, NULL); @@ -141,19 +141,20 @@ PyObject * Video_refresh (PyImage * self) // get range -PyObject * Video_getRange (PyImage * self, void * closure) +PyObject *Video_getRange(PyImage *self, void *closure) { return Py_BuildValue("[ff]", getVideo(self)->getRange()[0], getVideo(self)->getRange()[1]); } // set range -int Video_setRange (PyImage * self, PyObject * value, void * closure) +int Video_setRange(PyImage *self, PyObject *value, void *closure) { // check validity of parameter - if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 2 - || !PyFloat_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyFloat_Check(PySequence_Fast_GET_ITEM(value, 1))) + if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 2 || + /* XXX - this is incorrect if the sequence is not a list/tuple! */ + !PyFloat_Check(PySequence_Fast_GET_ITEM(value, 0)) || + !PyFloat_Check(PySequence_Fast_GET_ITEM(value, 1))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 float"); return -1; @@ -166,11 +167,11 @@ int Video_setRange (PyImage * self, PyObject * value, void * closure) } // get repeat -PyObject * Video_getRepeat (PyImage * self, void * closure) +PyObject *Video_getRepeat (PyImage *self, void *closure) { return Py_BuildValue("h", getVideo(self)->getRepeat()); } // set repeat -int Video_setRepeat (PyImage * self, PyObject * value, void * closure) +int Video_setRepeat(PyImage *self, PyObject *value, void *closure) { // check validity of parameter if (value == NULL || !PyLong_Check(value)) @@ -185,11 +186,11 @@ int Video_setRepeat (PyImage * self, PyObject * value, void * closure) } // get frame rate -PyObject * Video_getFrameRate (PyImage * self, void * closure) +PyObject *Video_getFrameRate (PyImage *self, void *closure) { return Py_BuildValue("f", double(getVideo(self)->getFrameRate())); } // set frame rate -int Video_setFrameRate (PyImage * self, PyObject * value, void * closure) +int Video_setFrameRate(PyImage *self, PyObject *value, void *closure) { // check validity of parameter if (value == NULL || !PyFloat_Check(value)) diff --git a/source/gameengine/VideoTexture/VideoBase.h b/source/gameengine/VideoTexture/VideoBase.h index e221d876358..4cf913d755d 100644 --- a/source/gameengine/VideoTexture/VideoBase.h +++ b/source/gameengine/VideoTexture/VideoBase.h @@ -164,14 +164,14 @@ protected: // cast Image pointer to Video -inline VideoBase * getVideo (PyImage * self) +inline VideoBase *getVideo(PyImage *self) { return static_cast(self->m_image); } extern ExceptionID SourceVideoCreation; // object initialization -template void Video_init (PyImage * self) +template void Video_init(PyImage *self) { // create source video object if (self->m_image != NULL) delete self->m_image; @@ -182,18 +182,18 @@ template void Video_init (PyImage * self) // video functions -void Video_open (VideoBase * self, char * file, short captureID); -PyObject * Video_play (PyImage * self); -PyObject * Video_pause (PyImage * self); -PyObject * Video_stop (PyImage * self); -PyObject * Video_refresh (PyImage * self); -PyObject * Video_getStatus (PyImage * self, void * closure); -PyObject * Video_getRange (PyImage * self, void * closure); -int Video_setRange (PyImage * self, PyObject * value, void * closure); -PyObject * Video_getRepeat (PyImage * self, void * closure); -int Video_setRepeat (PyImage * self, PyObject * value, void * closure); -PyObject * Video_getFrameRate (PyImage * self, void * closure); -int Video_setFrameRate (PyImage * self, PyObject * value, void * closure); +void Video_open(VideoBase * self, char * file, short captureID); +PyObject *Video_play(PyImage *self); +PyObject *Video_pause(PyImage *self); +PyObject *Video_stop(PyImage *self); +PyObject *Video_refresh(PyImage *self); +PyObject *Video_getStatus(PyImage *self, void *closure); +PyObject *Video_getRange(PyImage *self, void *closure); +int Video_setRange(PyImage *self, PyObject *value, void *closure); +PyObject *Video_getRepeat(PyImage *self, void *closure); +int Video_setRepeat(PyImage *self, PyObject *value, void *closure); +PyObject *Video_getFrameRate(PyImage *self, void *closure); +int Video_setFrameRate(PyImage *self, PyObject *value, void *closure); #endif diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp index 1ba944aa955..3f42d5c4fed 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp +++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp @@ -485,13 +485,13 @@ void VideoFFmpeg::stopCache() av_free(frame->frame); delete frame; } - while((packet = (CachePacket *)m_packetCacheBase.first) != NULL) + while ((packet = (CachePacket *)m_packetCacheBase.first) != NULL) { BLI_remlink(&m_packetCacheBase, packet); av_free_packet(&packet->packet); delete packet; } - while((packet = (CachePacket *)m_packetCacheFree.first) != NULL) + while ((packet = (CachePacket *)m_packetCacheFree.first) != NULL) { BLI_remlink(&m_packetCacheFree, packet); delete packet; @@ -524,7 +524,7 @@ void VideoFFmpeg::openFile (char * filename) if (m_codecCtx->gop_size) m_preseek = (m_codecCtx->gop_size < 25) ? m_codecCtx->gop_size+1 : 25; - else if (m_codecCtx->has_b_frames) + else if (m_codecCtx->has_b_frames) m_preseek = 25; // should determine gopsize else m_preseek = 0; @@ -921,7 +921,7 @@ AVFrame *VideoFFmpeg::grabFrame(long position) && m_preseek && position - (m_curPosition + 1) < m_preseek) { - while(av_read_frame(m_formatCtx, &packet)>=0) + while (av_read_frame(m_formatCtx, &packet)>=0) { if (packet.stream_index == m_videoStream) { @@ -996,7 +996,7 @@ AVFrame *VideoFFmpeg::grabFrame(long position) // find the correct frame, in case of streaming and no cache, it means just // return the next frame. This is not quite correct, may need more work - while(av_read_frame(m_formatCtx, &packet)>=0) + while (av_read_frame(m_formatCtx, &packet) >= 0) { if (packet.stream_index == m_videoStream) { @@ -1076,14 +1076,14 @@ AVFrame *VideoFFmpeg::grabFrame(long position) // cast Image pointer to VideoFFmpeg -inline VideoFFmpeg * getVideoFFmpeg (PyImage * self) +inline VideoFFmpeg * getVideoFFmpeg (PyImage *self) { return static_cast(self->m_image); } // object initialization -static int VideoFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds) +static int VideoFFmpeg_init (PyObject *pySelf, PyObject *args, PyObject *kwds) { - PyImage * self = reinterpret_cast(pySelf); + PyImage *self = reinterpret_cast(pySelf); // parameters - video source // file name or format type for capture (only for Linux: video4linux or dv1394) char * file = NULL; @@ -1123,13 +1123,13 @@ static int VideoFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds return 0; } -PyObject * VideoFFmpeg_getPreseek (PyImage *self, void * closure) +static PyObject *VideoFFmpeg_getPreseek(PyImage *self, void *closure) { return Py_BuildValue("h", getFFmpeg(self)->getPreseek()); } // set range -int VideoFFmpeg_setPreseek (PyImage * self, PyObject * value, void * closure) +static int VideoFFmpeg_setPreseek(PyImage *self, PyObject *value, void *closure) { // check validity of parameter if (value == NULL || !PyLong_Check(value)) @@ -1144,7 +1144,7 @@ int VideoFFmpeg_setPreseek (PyImage * self, PyObject * value, void * closure) } // get deinterlace -PyObject * VideoFFmpeg_getDeinterlace (PyImage * self, void * closure) +static PyObject *VideoFFmpeg_getDeinterlace(PyImage *self, void *closure) { if (getFFmpeg(self)->getDeinterlace()) Py_RETURN_TRUE; @@ -1153,7 +1153,7 @@ PyObject * VideoFFmpeg_getDeinterlace (PyImage * self, void * closure) } // set flip -int VideoFFmpeg_setDeinterlace (PyImage * self, PyObject * value, void * closure) +static int VideoFFmpeg_setDeinterlace(PyImage *self, PyObject *value, void *closure) { // check parameter, report failure if (value == NULL || !PyBool_Check(value)) @@ -1239,9 +1239,9 @@ PyTypeObject VideoFFmpegType = }; // object initialization -static int ImageFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds) +static int ImageFFmpeg_init (PyObject *pySelf, PyObject *args, PyObject *kwds) { - PyImage * self = reinterpret_cast(pySelf); + PyImage *self = reinterpret_cast(pySelf); // parameters - video source // file name or format type for capture (only for Linux: video4linux or dv1394) char * file = NULL; @@ -1269,7 +1269,7 @@ static int ImageFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds return 0; } -PyObject * Image_reload (PyImage * self, PyObject *args) +static PyObject *Image_reload(PyImage *self, PyObject *args) { char * newname = NULL; if (!PyArg_ParseTuple(args, "|s:reload", &newname)) diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.h b/source/gameengine/VideoTexture/VideoFFmpeg.h index e63032e0c66..d5b575851ee 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.h +++ b/source/gameengine/VideoTexture/VideoFFmpeg.h @@ -204,11 +204,11 @@ private: static void *cacheThread(void *); }; -inline VideoFFmpeg * getFFmpeg (PyImage * self) +inline VideoFFmpeg *getFFmpeg(PyImage *self) { return static_cast(self->m_image); } -#endif //WITH_FFMPEG +#endif /* WITH_FFMPEG */ -#endif +#endif /* __VIDEOFFMPEG_H__ */ diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp index 627da57baac..dd9d83c043f 100644 --- a/source/gameengine/VideoTexture/blendVideoTex.cpp +++ b/source/gameengine/VideoTexture/blendVideoTex.cpp @@ -26,6 +26,8 @@ http://www.gnu.org/copyleft/lesser.txt. #include "PyObjectPlus.h" +#include "KX_PythonInit.h" + #include #include @@ -46,10 +48,10 @@ http://www.gnu.org/copyleft/lesser.txt. // get material id -static PyObject * getMaterialID (PyObject *self, PyObject *args) +static PyObject *getMaterialID (PyObject *self, PyObject *args) { // parameters - game object with video texture - PyObject * obj = NULL; + PyObject *obj = NULL; // material name char * matName; @@ -70,13 +72,13 @@ static PyObject * getMaterialID (PyObject *self, PyObject *args) // get last error description -static PyObject * getLastError (PyObject *self, PyObject *args) +static PyObject *getLastError (PyObject *self, PyObject *args) { return PyUnicode_FromString(Exception::m_lastError.c_str()); } // set log file -static PyObject * setLogFile (PyObject *self, PyObject *args) +static PyObject *setLogFile (PyObject *self, PyObject *args) { // get parameters if (!PyArg_ParseTuple(args, "s:setLogFile", &Exception::m_logFile)) @@ -87,10 +89,10 @@ static PyObject * setLogFile (PyObject *self, PyObject *args) // image to numpy array -static PyObject * imageToArray (PyObject * self, PyObject *args) +static PyObject *imageToArray(PyObject *self, PyObject *args) { // parameter is Image object - PyObject * pyImg; + PyObject *pyImg; char *mode = NULL; if (!PyArg_ParseTuple(args, "O|s:imageToArray", &pyImg, &mode) || !pyImageTypes.in(Py_TYPE(pyImg))) { @@ -168,9 +170,9 @@ static struct PyModuleDef VideoTexture_module_def = { 0, /* m_free */ }; -PyObject* initVideoTexture(void) +PyObject *initVideoTexture(void) { - PyObject * m; + PyObject *m; // initialize GL extensions //bgl::InitExtensions(0); @@ -208,7 +210,7 @@ PyObject* initVideoTexture(void) pyFilterTypes.reg(m); Py_INCREF(&TextureType); - PyModule_AddObject(m, (char*)"Texture", (PyObject*)&TextureType); + PyModule_AddObject(m, (char*)"Texture", (PyObject *)&TextureType); PyModule_AddIntConstant(m, (char*)"SOURCE_ERROR", SourceError); PyModule_AddIntConstant(m, (char*)"SOURCE_EMPTY", SourceEmpty); PyModule_AddIntConstant(m, (char*)"SOURCE_READY", SourceReady); diff --git a/source/tests/CMakeLists.txt b/source/tests/CMakeLists.txt index 2bad58699a8..dd84882bea3 100644 --- a/source/tests/CMakeLists.txt +++ b/source/tests/CMakeLists.txt @@ -27,11 +27,11 @@ set(TEST_SRC_DIR ${CMAKE_SOURCE_DIR}/../lib/tests) set(TEST_OUT_DIR ${CMAKE_BINARY_DIR}/tests) # ugh, any better way to do this on testing only? -execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${TEST_OUT_DIR}) +execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${TEST_OUT_DIR}) -#~ if(NOT IS_DIRECTORY ${TEST_SRC_DIR}) -#~ message(FATAL_ERROR "CMake test directory not found!") -#~ endif() +#~ if(NOT IS_DIRECTORY ${TEST_SRC_DIR}) +#~ message(FATAL_ERROR "CMake test directory not found!") +#~ endif() # all calls to blender use this if(APPLE) diff --git a/source/tests/batch_import.py b/source/tests/batch_import.py index 5c228c014ca..177ab8ea0b0 100644 --- a/source/tests/batch_import.py +++ b/source/tests/batch_import.py @@ -63,12 +63,12 @@ def clear_scene(): def batch_import(operator="", - path="", - save_path="", - match="", - start=0, - end=sys.maxsize, - ): + path="", + save_path="", + match="", + start=0, + end=sys.maxsize, + ): import addon_utils _reset_all = addon_utils.reset_all # XXX, hack diff --git a/source/tests/bl_load_addons.py b/source/tests/bl_load_addons.py index 21a0101d684..5d9ac750362 100644 --- a/source/tests/bl_load_addons.py +++ b/source/tests/bl_load_addons.py @@ -36,7 +36,7 @@ def reload_addons(do_reload=True, do_reverse=True): for mod_name in list(addons.keys()): addon_utils.disable(mod_name) - assert(bool(addons) == False) + assert(bool(addons) is False) # Run twice each time. for i in (0, 1): diff --git a/source/tests/bl_load_py_modules.py b/source/tests/bl_load_py_modules.py index 619cad67cb8..b634b4c4385 100644 --- a/source/tests/bl_load_py_modules.py +++ b/source/tests/bl_load_py_modules.py @@ -49,7 +49,7 @@ def load_addons(): for mod_name in list(addons.keys()): addon_utils.disable(mod_name) - assert(bool(addons) == False) + assert(bool(addons) is False) for mod in modules: mod_name = mod.__name__ diff --git a/source/tests/bl_mesh_modifiers.py b/source/tests/bl_mesh_modifiers.py index 390679800f6..92fae25df16 100644 --- a/source/tests/bl_mesh_modifiers.py +++ b/source/tests/bl_mesh_modifiers.py @@ -846,7 +846,7 @@ if __name__ == "__main__": @persistent def load_handler(dummy): print("Load Handler:", bpy.data.filepath) - if load_handler.first == False: + if load_handler.first is False: bpy.app.handlers.scene_update_post.remove(load_handler) try: main() diff --git a/source/tests/bl_rna_wiki_reference.py b/source/tests/bl_rna_wiki_reference.py index 2018c4327a3..cfe7f22f7dd 100644 --- a/source/tests/bl_rna_wiki_reference.py +++ b/source/tests/bl_rna_wiki_reference.py @@ -21,38 +21,71 @@ # Use for validating our wiki interlinking. # ./blender.bin --background -noaudio --python source/tests/bl_rna_wiki_reference.py # -# 1) test_lookup_coverage() -- ensure that we have lookups for _every_ RNA path -# 2) test_urls() -- ensure all the URL's are correct -# 3) test_language_coverage() -- ensure language lookup table is complete +# 1) test_data() -- ensure the data we have is correct format +# 2) test_lookup_coverage() -- ensure that we have lookups for _every_ RNA path +# 3) test_urls() -- ensure all the URL's are correct +# 4) test_language_coverage() -- ensure language lookup table is complete # import bpy + +def test_data(): + import rna_wiki_reference + + assert(isinstance(rna_wiki_reference.url_manual_mapping, tuple)) + for i, value in enumerate(rna_wiki_reference.url_manual_mapping): + try: + assert(len(value) == 2) + assert(isinstance(value[0], str)) + assert(isinstance(value[1], str)) + except: + print("Expected a tuple of 2 strings, instead item %d is a %s: %r" % (i, type(value), value)) + import traceback + traceback.print_exc() + raise + + # a stripped down version of api_dump() in rna_info_dump.py - - def test_lookup_coverage(): def rna_ids(): - import rna_info struct = rna_info.BuildRNAInfo()[0] for struct_id, v in sorted(struct.items()): props = [(prop.identifier, prop) for prop in v.properties] + struct_path = "bpy.types.%s" % struct_id[1] for prop_id, prop in props: - yield "bpy.types.%s.%s" % (struct_id[1], prop_id) + yield (struct_path, "%s.%s" % (struct_path, prop_id)) for submod_id in dir(bpy.ops): + op_path = "bpy.ops.%s" % submod_id for op_id in dir(getattr(bpy.ops, submod_id)): - yield "bpy.ops.%s.%s" % (submod_id, op_id) + yield (op_path, "%s.%s" % (op_path, op_id)) # check coverage from bl_operators import wm - for rna_id in rna_ids(): + set_group_all = set() + set_group_doc = set() + + for rna_group, rna_id in rna_ids(): url = wm.WM_OT_doc_view_manual._lookup_rna_url(rna_id, verbose=False) print(rna_id, "->", url) + set_group_all.add(rna_group) + if url is not None: + set_group_doc.add(rna_group) + + # finally report undocumented groups + print("") + print("---------------------") + print("Undocumented Sections") + + for rna_group in sorted(set_group_all): + if rna_group not in set_group_doc: + print("%s.*" % rna_group) + def test_urls(): pass # TODO @@ -63,6 +96,7 @@ def test_language_coverage(): def main(): + test_data() test_lookup_coverage() test_language_coverage() diff --git a/source/tests/bl_run_operators.py b/source/tests/bl_run_operators.py index 53cc37bc02b..f792b83a8cd 100644 --- a/source/tests/bl_run_operators.py +++ b/source/tests/bl_run_operators.py @@ -44,7 +44,7 @@ op_blacklist = ( "help.operator_cheat_sheet", "wm.keyconfig_test", # just annoying - but harmless "wm.memory_statistics", # another annoying one - # "mesh.vertex_color_remove", #crashes! fixme + "console.*", # just annoying - but harmless ) @@ -61,7 +61,7 @@ def filter_op_list(operators): operators[:] = [op for op in operators if is_op_ok(op[0])] -def run_ops(operators, setup_func=None): +def run_ops(operators, setup_func=None, reset=True): print("\ncontext:", setup_func.__name__) # first invoke for op_id, op in operators: @@ -70,7 +70,8 @@ def run_ops(operators, setup_func=None): sys.stdout.flush() # in case of crash # disable will get blender in a bad state and crash easy! - bpy.ops.wm.read_factory_settings() + if reset: + bpy.ops.wm.read_factory_settings() setup_func() @@ -82,6 +83,12 @@ def run_ops(operators, setup_func=None): #traceback.print_exc() pass + if not operators: + # run test + if reset: + bpy.ops.wm.read_factory_settings() + setup_func() + # contexts def ctx_clear_scene(): # copied from batch_import.py @@ -99,7 +106,23 @@ def ctx_clear_scene(): # copied from batch_import.py def ctx_editmode_mesh(): bpy.ops.object.mode_set(mode='EDIT') + + +def ctx_editmode_mesh_extra(): bpy.ops.object.vertex_group_add() + bpy.ops.object.shape_key_add(from_mix=False) + bpy.ops.object.shape_key_add(from_mix=True) + bpy.ops.mesh.uv_texture_add() + bpy.ops.mesh.vertex_color_add() + bpy.ops.object.material_slot_add() + # editmode last! + bpy.ops.object.mode_set(mode='EDIT') + + +def ctx_editmode_mesh_empty(): + bpy.ops.object.mode_set(mode='EDIT') + bpy.ops.mesh.select_all(action='SELECT') + bpy.ops.mesh.delete() def ctx_editmode_curves(): @@ -107,6 +130,12 @@ def ctx_editmode_curves(): bpy.ops.object.mode_set(mode='EDIT') +def ctx_editmode_curves_empty(): + bpy.ops.curve.primitive_nurbs_circle_add() + bpy.ops.object.mode_set(mode='EDIT') + bpy.ops.curve.delete(type='ALL') + + def ctx_editmode_surface(): bpy.ops.surface.primitive_nurbs_surface_torus_add() bpy.ops.object.mode_set(mode='EDIT') @@ -127,6 +156,13 @@ def ctx_editmode_armature(): bpy.ops.object.mode_set(mode='EDIT') +def ctx_editmode_armature_empty(): + bpy.ops.object.armature_add() + bpy.ops.object.mode_set(mode='EDIT') + bpy.ops.armature.select_all(action='SELECT') + bpy.ops.armature.delete() + + def ctx_editmode_lattice(): bpy.ops.object.add(type='LATTICE') bpy.ops.object.mode_set(mode='EDIT') @@ -137,10 +173,28 @@ def ctx_object_empty(): bpy.ops.object.add(type='EMPTY') -def ctx_weightpaint(): +def ctx_object_pose(): + bpy.ops.object.armature_add() + bpy.ops.object.mode_set(mode='POSE') + bpy.ops.pose.select_all(action='SELECT') + + +def ctx_object_paint_weight(): bpy.ops.object.mode_set(mode='WEIGHT_PAINT') +def ctx_object_paint_vertex(): + bpy.ops.object.mode_set(mode='VERTEX_PAINT') + + +def ctx_object_paint_sculpt(): + bpy.ops.object.mode_set(mode='SCULPT') + + +def ctx_object_paint_texture(): + bpy.ops.object.mode_set(mode='TEXTURE_PAINT') + + def bpy_check_type_duplicates(): # non essential sanity check bl_types = dir(bpy.types) @@ -179,20 +233,38 @@ def main(): #import random #random.shuffle(operators) - # Run the operator tests in different contexts - run_ops(operators, setup_func=lambda: None) - run_ops(operators, setup_func=ctx_editmode_surface) - run_ops(operators, setup_func=ctx_object_empty) - run_ops(operators, setup_func=ctx_editmode_armature) - run_ops(operators, setup_func=ctx_editmode_mesh) - run_ops(operators, setup_func=ctx_clear_scene) - run_ops(operators, setup_func=ctx_editmode_curves) - run_ops(operators, setup_func=ctx_editmode_mball) - run_ops(operators, setup_func=ctx_editmode_text) - run_ops(operators, setup_func=ctx_weightpaint) - run_ops(operators, setup_func=ctx_editmode_lattice) + # 2 passes, first just run setup_func to make sure they are ok + for operators_test in ((), operators): + # Run the operator tests in different contexts + run_ops(operators_test, setup_func=lambda: None) + run_ops(operators_test, setup_func=ctx_clear_scene) + # object modes + run_ops(operators_test, setup_func=ctx_object_empty) + run_ops(operators_test, setup_func=ctx_object_pose) + run_ops(operators_test, setup_func=ctx_object_paint_weight) + run_ops(operators_test, setup_func=ctx_object_paint_vertex) + run_ops(operators_test, setup_func=ctx_object_paint_sculpt) + run_ops(operators_test, setup_func=ctx_object_paint_texture) + # mesh + run_ops(operators_test, setup_func=ctx_editmode_mesh) + run_ops(operators_test, setup_func=ctx_editmode_mesh_extra) + run_ops(operators_test, setup_func=ctx_editmode_mesh_empty) + # armature + run_ops(operators_test, setup_func=ctx_editmode_armature) + run_ops(operators_test, setup_func=ctx_editmode_armature_empty) + # curves + run_ops(operators_test, setup_func=ctx_editmode_curves) + run_ops(operators_test, setup_func=ctx_editmode_curves_empty) + run_ops(operators_test, setup_func=ctx_editmode_surface) + # other + run_ops(operators_test, setup_func=ctx_editmode_mball) + run_ops(operators_test, setup_func=ctx_editmode_text) + run_ops(operators_test, setup_func=ctx_editmode_lattice) - print("finished") + if not operators_test: + print("All setup functions run fine!") + + print("Finished %r" % __file__) if __name__ == "__main__": main() diff --git a/source/tests/bl_test.py b/source/tests/bl_test.py index cfe91356444..0cb322a21b1 100644 --- a/source/tests/bl_test.py +++ b/source/tests/bl_test.py @@ -145,7 +145,7 @@ def main(): if write_blend is not None: print(" Writing Blend: %s" % write_blend) - bpy.ops.wm.save_mainfile(filepath=write_blend, check_existing=False) + bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=write_blend) print(" Result: '%s'" % str(result)) if not result: diff --git a/source/tests/rna_array.py b/source/tests/rna_array.py index 06b4735cc0d..a2241dff108 100644 --- a/source/tests/rna_array.py +++ b/source/tests/rna_array.py @@ -98,14 +98,14 @@ class TestArray(unittest.TestCase): for arr, rand_func in zip((test.farr, test.iarr, test.barr), (rand_float, rand_int, rand_bool)): for i in range(len(arr)): val= rand_func() - arr[i]= val + arr[i] = val self.assertEqual(arr[i], val) # float prop should accept also int for i in range(len(test.farr)): val= rand_int() - test.farr[i]= val + test.farr[i] = val self.assertEqual(test.farr[i], float(val)) # @@ -115,7 +115,7 @@ class TestArray(unittest.TestCase): arr[4] = 1.0 def assign_bad_type(arr): - arr[1]= "123" + arr[1] = "123" for arr in [test.farr, test.iarr, test.barr]: self.assertRaises(IndexError, assign_bad_index, arr) @@ -183,7 +183,7 @@ class TestMArray(unittest.TestCase): rval= make_random_2d_array((4, 5), func) for i in range(3): - getattr(test, arr)[i]= rval + getattr(test, arr)[i] = rval self.assertEqual(prop_to_list(getattr(test, arr)[i]), rval) # arr[i][j] = x @@ -194,13 +194,13 @@ class TestMArray(unittest.TestCase): for i in range(3): for j in range(4): - arr[i][j]= rval + arr[i][j] = rval self.assertEqual(prop_to_list(arr[i][j]), rval) def test_assign_item_fail(self): def assign_wrong_size(arr, i, rval): - getattr(test, arr)[i]= rval + getattr(test, arr)[i] = rval # assign wrong size at level 2 for arr, func in zip(("fmarr", "imarr", "bmarr"), (rand_float, rand_int, rand_bool)): From 53e952d3f904fc4bbba69fbf1bd9c5e65fbbcb92 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 5 Nov 2012 19:44:33 +0000 Subject: [PATCH 155/160] This files apparently were't marked for delete/add properly --- intern/opencolorio/fallback_impl.cc | 382 ++++++++++++++++++ intern/opencolorio/ocio_capi.cc | 284 ++++++++++++++ intern/opencolorio/ocio_capi.cpp | 525 ------------------------- intern/opencolorio/ocio_capi_stub.cpp | 380 ------------------ intern/opencolorio/ocio_impl.cc | 544 ++++++++++++++++++++++++++ intern/opencolorio/ocio_impl.h | 240 ++++++++++++ 6 files changed, 1450 insertions(+), 905 deletions(-) create mode 100644 intern/opencolorio/fallback_impl.cc create mode 100644 intern/opencolorio/ocio_capi.cc delete mode 100644 intern/opencolorio/ocio_capi.cpp delete mode 100644 intern/opencolorio/ocio_capi_stub.cpp create mode 100644 intern/opencolorio/ocio_impl.cc create mode 100644 intern/opencolorio/ocio_impl.h diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc new file mode 100644 index 00000000000..44c02d1442b --- /dev/null +++ b/intern/opencolorio/fallback_impl.cc @@ -0,0 +1,382 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Brecht van Lommel + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include + +#include "MEM_guardedalloc.h" +#include "BLI_math_color.h" + +#include "ocio_impl.h" + +#define CONFIG_DEFAULT ((OCIO_ConstConfigRcPtr*)1) + +#define PROCESSOR_LINEAR_TO_SRGB ((OCIO_ConstProcessorRcPtr*)1) +#define PROCESSOR_SRGB_TO_LINEAR ((OCIO_ConstProcessorRcPtr*)2) +#define PROCESSOR_UNKNOWN ((OCIO_ConstProcessorRcPtr*)3) + +#define COLORSPACE_LINEAR ((OCIO_ConstColorSpaceRcPtr*)1) +#define COLORSPACE_SRGB ((OCIO_ConstColorSpaceRcPtr*)2) + +typedef struct OCIO_PackedImageDescription { + float *data; + long width; + long height; + long numChannels; + long chanStrideBytes; + long xStrideBytes; + long yStrideBytes; +} OCIO_PackedImageDescription; + +OCIO_ConstConfigRcPtr *FallbackImpl::getCurrentConfig(void) +{ + return CONFIG_DEFAULT; +} + +void FallbackImpl::setCurrentConfig(const OCIO_ConstConfigRcPtr *) +{ +} + +OCIO_ConstConfigRcPtr *FallbackImpl::configCreateFromEnv(void) +{ + return CONFIG_DEFAULT; +} + +OCIO_ConstConfigRcPtr *FallbackImpl::configCreateFromFile(const char *) +{ + return CONFIG_DEFAULT; +} + +void FallbackImpl::configRelease(OCIO_ConstConfigRcPtr *) +{ +} + +int FallbackImpl::configGetNumColorSpaces(OCIO_ConstConfigRcPtr *) +{ + return 2; +} + +const char *FallbackImpl::configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr *, int index) +{ + if (index == 0) + return "Linear"; + else if (index == 1) + return "sRGB"; + + return NULL; +} + +OCIO_ConstColorSpaceRcPtr *FallbackImpl::configGetColorSpace(OCIO_ConstConfigRcPtr *, const char *name) +{ + if (strcmp(name, "scene_linear") == 0) + return COLORSPACE_LINEAR; + else if (strcmp(name, "color_picking") == 0) + return COLORSPACE_SRGB; + else if (strcmp(name, "texture_paint") == 0) + return COLORSPACE_LINEAR; + else if (strcmp(name, "default_byte") == 0) + return COLORSPACE_SRGB; + else if (strcmp(name, "default_float") == 0) + return COLORSPACE_LINEAR; + else if (strcmp(name, "default_sequencer") == 0) + return COLORSPACE_SRGB; + else if (strcmp(name, "Linear") == 0) + return COLORSPACE_LINEAR; + else if (strcmp(name, "sRGB") == 0) + return COLORSPACE_SRGB; + + return NULL; +} + +int FallbackImpl::configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, const char *name) +{ + OCIO_ConstColorSpaceRcPtr *cs = configGetColorSpace(config, name); + + if (cs == COLORSPACE_LINEAR) + return 0; + else if (cs == COLORSPACE_SRGB) + return 1; + + return -1; +} + +const char *FallbackImpl::configGetDefaultDisplay(OCIO_ConstConfigRcPtr *) +{ + return "sRGB"; +} + +int FallbackImpl::configGetNumDisplays(OCIO_ConstConfigRcPtr* config) +{ + return 1; +} + +const char *FallbackImpl::configGetDisplay(OCIO_ConstConfigRcPtr *, int index) +{ + if (index == 0) + return "sRGB"; + + return NULL; +} + +const char *FallbackImpl::configGetDefaultView(OCIO_ConstConfigRcPtr *, const char *) +{ + return "Default"; +} + +int FallbackImpl::configGetNumViews(OCIO_ConstConfigRcPtr *, const char *) +{ + return 1; +} + +const char *FallbackImpl::configGetView(OCIO_ConstConfigRcPtr *, const char *, int index) +{ + if (index == 0) + return "Default"; + + return NULL; +} + +const char *FallbackImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *, const char *, const char *) +{ + return "sRGB"; +} + +int FallbackImpl::colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs) +{ + return 1; +} + +int FallbackImpl::colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs) +{ + return 0; +} + +void FallbackImpl::colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs) +{ +} + +OCIO_ConstProcessorRcPtr *FallbackImpl::configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, const char *srcName, const char *dstName) +{ + OCIO_ConstColorSpaceRcPtr *cs_src = configGetColorSpace(config, srcName); + OCIO_ConstColorSpaceRcPtr *cs_dst = configGetColorSpace(config, dstName); + + if (cs_src == COLORSPACE_LINEAR && cs_dst == COLORSPACE_SRGB) + return PROCESSOR_LINEAR_TO_SRGB; + else if (cs_src == COLORSPACE_SRGB && cs_dst == COLORSPACE_LINEAR) + return PROCESSOR_SRGB_TO_LINEAR; + + return 0; +} + +OCIO_ConstProcessorRcPtr *FallbackImpl::configGetProcessor(OCIO_ConstConfigRcPtr *, OCIO_ConstTransformRcPtr *tfm) +{ + return (OCIO_ConstProcessorRcPtr*)tfm; +} + +void FallbackImpl::processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img) +{ + /* OCIO_TODO stride not respected, channels must be 3 or 4 */ + OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription*)img; + int channels = desc->numChannels; + float *pixels = desc->data; + int width = desc->width; + int height = desc->height; + int x, y; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + float *pixel = pixels + channels * (y * width + x); + + if (channels == 4) + processorApplyRGBA(processor, pixel); + else if (channels == 3) + processorApplyRGB(processor, pixel); + } + } +} + +void FallbackImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img) +{ + /* OCIO_TODO stride not respected, channels must be 3 or 4 */ + OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription*)img; + int channels = desc->numChannels; + float *pixels = desc->data; + int width = desc->width; + int height = desc->height; + int x, y; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + float *pixel = pixels + channels * (y * width + x); + + if (channels == 4) + processorApplyRGBA_predivide(processor, pixel); + else if (channels == 3) + processorApplyRGB(processor, pixel); + } + } +} + +void FallbackImpl::processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel) +{ + if (processor == PROCESSOR_LINEAR_TO_SRGB) + linearrgb_to_srgb_v3_v3(pixel, pixel); + else if (processor == PROCESSOR_SRGB_TO_LINEAR) + srgb_to_linearrgb_v3_v3(pixel, pixel); +} + +void FallbackImpl::processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel) +{ + if (processor == PROCESSOR_LINEAR_TO_SRGB) + linearrgb_to_srgb_v4(pixel, pixel); + else if (processor == PROCESSOR_SRGB_TO_LINEAR) + srgb_to_linearrgb_v4(pixel, pixel); +} + +void FallbackImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel) +{ + if (pixel[3] == 1.0f || pixel[3] == 0.0f) { + processorApplyRGBA(processor, pixel); + } + else { + float alpha, inv_alpha; + + alpha = pixel[3]; + inv_alpha = 1.0f / alpha; + + pixel[0] *= inv_alpha; + pixel[1] *= inv_alpha; + pixel[2] *= inv_alpha; + + processorApplyRGBA(processor, pixel); + + pixel[0] *= alpha; + pixel[1] *= alpha; + pixel[2] *= alpha; + } +} + +void FallbackImpl::processorRelease(OCIO_ConstProcessorRcPtr *) +{ +} + +const char *FallbackImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs) +{ + if (cs == COLORSPACE_LINEAR) + return "Linear"; + else if (cs == COLORSPACE_SRGB) + return "sRGB"; + + return NULL; +} + +const char *FallbackImpl::colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *) +{ + return ""; +} + +const char *FallbackImpl::colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *) +{ + return ""; +} + +OCIO_DisplayTransformRcPtr *FallbackImpl::createDisplayTransform(void) +{ + return (OCIO_DisplayTransformRcPtr*)PROCESSOR_LINEAR_TO_SRGB; +} + +void FallbackImpl::displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *, const char *) +{ +} + +void FallbackImpl::displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *, const char *) +{ +} + +void FallbackImpl::displayTransformSetView(OCIO_DisplayTransformRcPtr *, const char *) +{ +} + +void FallbackImpl::displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *, OCIO_ConstTransformRcPtr *) +{ +} + +void FallbackImpl::displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *, OCIO_ConstTransformRcPtr *) +{ +} + +void FallbackImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr *) +{ +} + +OCIO_PackedImageDesc *FallbackImpl::createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels, + long chanStrideBytes, long xStrideBytes, long yStrideBytes) +{ + OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription*)MEM_callocN(sizeof(OCIO_PackedImageDescription), "OCIO_PackedImageDescription"); + + desc->data = data; + desc->width = width; + desc->height = height; + desc->numChannels = numChannels; + desc->chanStrideBytes = chanStrideBytes; + desc->xStrideBytes = xStrideBytes; + desc->yStrideBytes = yStrideBytes; + + return (OCIO_PackedImageDesc*)desc; +} + +void FallbackImpl::OCIO_PackedImageDescRelease(OCIO_PackedImageDesc* id) +{ + MEM_freeN(id); +} + +OCIO_ExponentTransformRcPtr *FallbackImpl::createExponentTransform(void) +{ + return (OCIO_ExponentTransformRcPtr*)PROCESSOR_UNKNOWN; +} + +void FallbackImpl::exponentTransformSetValue(OCIO_ExponentTransformRcPtr *, const float *) +{ +} + +void FallbackImpl::exponentTransformRelease(OCIO_ExponentTransformRcPtr *) +{ +} + +OCIO_MatrixTransformRcPtr *FallbackImpl::createMatrixTransform(void) +{ + return (OCIO_MatrixTransformRcPtr*)PROCESSOR_UNKNOWN; +} + +void FallbackImpl::matrixTransformSetValue(OCIO_MatrixTransformRcPtr *, const float *, const float *) +{ +} + +void FallbackImpl::matrixTransformRelease(OCIO_MatrixTransformRcPtr *) +{ +} + +void FallbackImpl::matrixTransformScale(float * , float * , const float *) +{ +} diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc new file mode 100644 index 00000000000..18fa4b7cb1b --- /dev/null +++ b/intern/opencolorio/ocio_capi.cc @@ -0,0 +1,284 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "MEM_guardedalloc.h" + +#include "ocio_impl.h" + +static IOCIOImpl *impl = NULL; + +void OCIO_init(void) +{ +#ifdef WITH_OCIO + impl = new OCIOImpl(); +#else + impl = new FallbackImpl(); +#endif +} + +void OCIO_exit(void) +{ + delete impl; + impl = NULL; +} + +OCIO_ConstConfigRcPtr *OCIO_getCurrentConfig(void) +{ + return impl->getCurrentConfig(); +} + +OCIO_ConstConfigRcPtr *OCIO_configCreateFallback(void) +{ + delete impl; + impl = new FallbackImpl(); + + return impl->getCurrentConfig(); +} + +void OCIO_setCurrentConfig(const OCIO_ConstConfigRcPtr *config) +{ + impl->setCurrentConfig(config); +} + +OCIO_ConstConfigRcPtr *OCIO_configCreateFromEnv(void) +{ + return impl->configCreateFromEnv(); +} + +OCIO_ConstConfigRcPtr *OCIO_configCreateFromFile(const char *filename) +{ + return impl->configCreateFromFile(filename); +} + +void OCIO_configRelease(OCIO_ConstConfigRcPtr *config) +{ + impl->configRelease(config); +} + +int OCIO_configGetNumColorSpaces(OCIO_ConstConfigRcPtr *config) +{ + return impl->configGetNumColorSpaces(config); +} + +const char *OCIO_configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr *config, int index) +{ + return impl->configGetColorSpaceNameByIndex(config, index); +} + +OCIO_ConstColorSpaceRcPtr *OCIO_configGetColorSpace(OCIO_ConstConfigRcPtr *config, const char *name) +{ + return impl->configGetColorSpace(config, name); +} + +int OCIO_configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, const char *name) +{ + return impl->configGetIndexForColorSpace(config, name); +} + +const char *OCIO_configGetDefaultDisplay(OCIO_ConstConfigRcPtr *config) +{ + return impl->configGetDefaultDisplay(config); +} + +int OCIO_configGetNumDisplays(OCIO_ConstConfigRcPtr* config) +{ + return impl->configGetNumDisplays(config); +} + +const char *OCIO_configGetDisplay(OCIO_ConstConfigRcPtr *config, int index) +{ + return impl->configGetDisplay(config, index); +} + +const char *OCIO_configGetDefaultView(OCIO_ConstConfigRcPtr *config, const char *display) +{ + return impl->configGetDefaultView(config, display); +} + +int OCIO_configGetNumViews(OCIO_ConstConfigRcPtr *config, const char *display) +{ + return impl->configGetNumViews(config, display); +} + +const char *OCIO_configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index) +{ + return impl->configGetView(config, display, index); +} + +const char *OCIO_configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view) +{ + return impl->configGetDisplayColorSpaceName(config, display, view); +} + +int OCIO_colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs) +{ + return impl->colorSpaceIsInvertible(cs); +} + +int OCIO_colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs) +{ + return impl->colorSpaceIsData(cs); +} + +void OCIO_colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs) +{ + impl->colorSpaceRelease(cs); +} + +OCIO_ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, const char *srcName, const char *dstName) +{ + return impl->configGetProcessorWithNames(config, srcName, dstName); +} + +OCIO_ConstProcessorRcPtr *OCIO_configGetProcessor(OCIO_ConstConfigRcPtr *config, OCIO_ConstTransformRcPtr *transform) +{ + return impl->configGetProcessor(config, transform); +} + +void OCIO_processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img) +{ + impl->processorApply(processor, img); +} + +void OCIO_processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img) +{ + impl->processorApply_predivide(processor, img); +} + +void OCIO_processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel) +{ + impl->processorApplyRGB(processor, pixel); +} + +void OCIO_processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel) +{ + impl->processorApplyRGBA(processor, pixel); +} + +void OCIO_processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel) +{ + impl->processorApplyRGBA_predivide(processor, pixel); +} + +void OCIO_processorRelease(OCIO_ConstProcessorRcPtr *p) +{ + impl->processorRelease(p); +} + +const char *OCIO_colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs) +{ + return impl->colorSpaceGetName(cs); +} + +const char *OCIO_colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs) +{ + return impl->colorSpaceGetDescription(cs); +} + +const char *OCIO_colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs) +{ + return impl->colorSpaceGetFamily(cs); +} + +OCIO_DisplayTransformRcPtr *OCIO_createDisplayTransform(void) +{ + return impl->createDisplayTransform(); +} + +void OCIO_displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name) +{ + impl->displayTransformSetInputColorSpaceName(dt, name); +} + +void OCIO_displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name) +{ + impl->displayTransformSetDisplay(dt, name); +} + +void OCIO_displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name) +{ + impl->displayTransformSetView(dt, name); +} + +void OCIO_displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *t) +{ + impl->displayTransformSetDisplayCC(dt, t); +} + +void OCIO_displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *t) +{ + impl->displayTransformSetLinearCC(dt, t); +} + +void OCIO_displayTransformRelease(OCIO_DisplayTransformRcPtr *dt) +{ + impl->displayTransformRelease(dt); +} + +OCIO_PackedImageDesc *OCIO_createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels, + long chanStrideBytes, long xStrideBytes, long yStrideBytes) +{ + return impl->createOCIO_PackedImageDesc(data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes); +} + +void OCIO_OCIO_PackedImageDescRelease(OCIO_PackedImageDesc* id) +{ + impl->OCIO_PackedImageDescRelease(id); +} + +OCIO_ExponentTransformRcPtr *OCIO_createExponentTransform(void) +{ + return impl->createExponentTransform(); +} + +void OCIO_exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent) +{ + impl->exponentTransformSetValue(et, exponent); +} + +void OCIO_exponentTransformRelease(OCIO_ExponentTransformRcPtr *et) +{ + impl->exponentTransformRelease(et); +} + +OCIO_MatrixTransformRcPtr *OCIO_createMatrixTransform(void) +{ + return impl->createMatrixTransform(); +} + +void OCIO_matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt, const float *m44, const float *offset4) +{ + impl->matrixTransformSetValue(mt, m44, offset4); +} + +void OCIO_matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt) +{ + impl->matrixTransformRelease(mt); +} + +void OCIO_matrixTransformScale(float * m44, float * offset4, const float *scale4f) +{ + impl->matrixTransformScale(m44, offset4, scale4f); +} diff --git a/intern/opencolorio/ocio_capi.cpp b/intern/opencolorio/ocio_capi.cpp deleted file mode 100644 index ec8012cc30f..00000000000 --- a/intern/opencolorio/ocio_capi.cpp +++ /dev/null @@ -1,525 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2012 Blender Foundation. - * All rights reserved. - * - * Contributor(s): Xavier Thomas - * Lukas Toene, - * Sergey Sharybin - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include -#include - -#include - -#include "MEM_guardedalloc.h" - -#define OCIO_CAPI_IMPLEMENTATION -#include "ocio_capi.h" - -#ifdef NDEBUG -# define OCIO_abort() -#else -# include -# define OCIO_abort() abort() -#endif - -#if defined(_MSC_VER) -# define __func__ __FUNCTION__ -#endif - -#define MEM_NEW(type) new(MEM_mallocN(sizeof(type), __func__)) type() -#define MEM_DELETE(what, type) { what->~type(); MEM_freeN(what); } (void)0 - -static void OCIO_reportError(const char *err) -{ - std::cerr << "OpenColorIO Error: " << err << std::endl; - - OCIO_abort(); -} - -static void OCIO_reportException(Exception &exception) -{ - OCIO_reportError(exception.what()); -} - -ConstConfigRcPtr *OCIO_getCurrentConfig(void) -{ - ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr); - - try { - *config = GetCurrentConfig(); - - if(*config) - return config; - } - catch (Exception &exception) { - OCIO_reportException(exception); - } - - return NULL; -} - -void OCIO_setCurrentConfig(const ConstConfigRcPtr *config) -{ - try { - SetCurrentConfig(*config); - } - catch (Exception &exception) { - OCIO_reportException(exception); - } -} - -ConstConfigRcPtr *OCIO_configCreateFromEnv(void) -{ - ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr); - - try { - *config = Config::CreateFromEnv(); - - if (*config) - return config; - } - catch (Exception &exception) { - OCIO_reportException(exception); - } - - return NULL; -} - - -ConstConfigRcPtr *OCIO_configCreateFromFile(const char *filename) -{ - ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr); - - try { - *config = Config::CreateFromFile(filename); - - if (*config) - return config; - } - catch (Exception &exception) { - OCIO_reportException(exception); - } - - return NULL; -} - -void OCIO_configRelease(ConstConfigRcPtr *config) -{ - MEM_DELETE(config, ConstConfigRcPtr); -} - -int OCIO_configGetNumColorSpaces(ConstConfigRcPtr *config) -{ - try { - return (*config)->getNumColorSpaces(); - } - catch (Exception &exception) { - OCIO_reportException(exception); - } - - return 0; -} - -const char *OCIO_configGetColorSpaceNameByIndex(ConstConfigRcPtr *config, int index) -{ - try { - return (*config)->getColorSpaceNameByIndex(index); - } - catch (Exception &exception) { - OCIO_reportException(exception); - } - - return NULL; -} - -ConstColorSpaceRcPtr *OCIO_configGetColorSpace(ConstConfigRcPtr *config, const char *name) -{ - ConstColorSpaceRcPtr *cs = MEM_NEW(ConstColorSpaceRcPtr); - - try { - *cs = (*config)->getColorSpace(name); - - if (*cs) - return cs; - } - catch (Exception &exception) { - OCIO_reportException(exception); - MEM_DELETE(cs, ConstColorSpaceRcPtr); - } - - return NULL; -} - -int OCIO_configGetIndexForColorSpace(ConstConfigRcPtr *config, const char *name) -{ - try { - return (*config)->getIndexForColorSpace(name); - } - catch (Exception &exception) { - OCIO_reportException(exception); - } - - return -1; -} - -const char *OCIO_configGetDefaultDisplay(ConstConfigRcPtr *config) -{ - try { - return (*config)->getDefaultDisplay(); - } - catch (Exception &exception) { - OCIO_reportException(exception); - } - - return NULL; -} - -int OCIO_configGetNumDisplays(ConstConfigRcPtr* config) -{ - try { - return (*config)->getNumDisplays(); - } - catch (Exception &exception) { - OCIO_reportException(exception); - } - - return 0; -} - -const char *OCIO_configGetDisplay(ConstConfigRcPtr *config, int index) -{ - try { - return (*config)->getDisplay(index); - } - catch (Exception &exception) { - OCIO_reportException(exception); - } - - return NULL; -} - -const char *OCIO_configGetDefaultView(ConstConfigRcPtr *config, const char *display) -{ - try { - return (*config)->getDefaultView(display); - } - catch (Exception &exception) { - OCIO_reportException(exception); - } - - return NULL; -} - -int OCIO_configGetNumViews(ConstConfigRcPtr *config, const char *display) -{ - try { - return (*config)->getNumViews(display); - } - catch (Exception &exception) { - OCIO_reportException(exception); - } - - return 0; -} - -const char *OCIO_configGetView(ConstConfigRcPtr *config, const char *display, int index) -{ - try { - return (*config)->getView(display, index); - } - catch (Exception &exception) { - OCIO_reportException(exception); - } - - return NULL; -} - -const char *OCIO_configGetDisplayColorSpaceName(ConstConfigRcPtr *config, const char *display, const char *view) -{ - try { - return (*config)->getDisplayColorSpaceName(display, view); - } - catch (Exception &exception) { - OCIO_reportException(exception); - } - - return NULL; -} - -int OCIO_colorSpaceIsInvertible(ConstColorSpaceRcPtr *cs) -{ - const char *family = (*cs)->getFamily(); - - if (!strcmp(family, "rrt") || !strcmp(family, "display")) { - /* assume display and rrt transformations are not invertible - * in fact some of them could be, but it doesn't make much sense to allow use them as invertible - */ - return false; - } - - if ((*cs)->isData()) { - /* data color spaces don't have transformation at all */ - return true; - } - - if ((*cs)->getTransform(COLORSPACE_DIR_TO_REFERENCE)) { - /* if there's defined transform to reference space, color space could be converted to scene linear */ - return true; - } - - return true; -} - -void OCIO_colorSpaceRelease(ConstColorSpaceRcPtr *cs) -{ - MEM_DELETE(cs, ConstColorSpaceRcPtr); -} - -ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(ConstConfigRcPtr *config, const char *srcName, const char *dstName) -{ - ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr); - - try { - *p = (*config)->getProcessor(srcName, dstName); - - if (*p) - return p; - } - catch (Exception &exception) { - OCIO_reportException(exception); - } - - return 0; -} - -ConstProcessorRcPtr *OCIO_configGetProcessor(ConstConfigRcPtr *config, ConstTransformRcPtr *transform) -{ - ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr); - - try { - *p = (*config)->getProcessor(*transform); - - if (*p) - return p; - } - catch (Exception &exception) { - OCIO_reportException(exception); - } - - return NULL; -} - -void OCIO_processorApply(ConstProcessorRcPtr *processor, PackedImageDesc *img) -{ - try { - (*processor)->apply(*img); - } - catch (Exception &exception) { - OCIO_reportException(exception); - } -} - -void OCIO_processorApply_predivide(ConstProcessorRcPtr *processor, PackedImageDesc *img) -{ - try { - int channels = img->getNumChannels(); - - if (channels == 4) { - float *pixels = img->getData(); - - int width = img->getWidth(); - int height = img->getHeight(); - - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - float *pixel = pixels + 4 * (y * width + x); - - OCIO_processorApplyRGBA_predivide(processor, pixel); - } - } - } - else { - (*processor)->apply(*img); - } - } - catch (Exception &exception) { - OCIO_reportException(exception); - } -} - -void OCIO_processorApplyRGB(ConstProcessorRcPtr *processor, float *pixel) -{ - (*processor)->applyRGB(pixel); -} - -void OCIO_processorApplyRGBA(ConstProcessorRcPtr *processor, float *pixel) -{ - (*processor)->applyRGBA(pixel); -} - -void OCIO_processorApplyRGBA_predivide(ConstProcessorRcPtr *processor, float *pixel) -{ - if (pixel[3] == 1.0f || pixel[3] == 0.0f) { - (*processor)->applyRGBA(pixel); - } - else { - float alpha, inv_alpha; - - alpha = pixel[3]; - inv_alpha = 1.0f / alpha; - - pixel[0] *= inv_alpha; - pixel[1] *= inv_alpha; - pixel[2] *= inv_alpha; - - (*processor)->applyRGBA(pixel); - - pixel[0] *= alpha; - pixel[1] *= alpha; - pixel[2] *= alpha; - } -} - -void OCIO_processorRelease(ConstProcessorRcPtr *p) -{ - p->~ConstProcessorRcPtr(); - MEM_freeN(p); -} - -const char *OCIO_colorSpaceGetName(ConstColorSpaceRcPtr *cs) -{ - return (*cs)->getName(); -} - -const char *OCIO_colorSpaceGetDescription(ConstColorSpaceRcPtr *cs) -{ - return (*cs)->getDescription(); -} - -const char *OCIO_colorSpaceGetFamily(ConstColorSpaceRcPtr *cs) -{ - return (*cs)->getFamily(); -} - -DisplayTransformRcPtr *OCIO_createDisplayTransform(void) -{ - DisplayTransformRcPtr *dt = MEM_NEW(DisplayTransformRcPtr); - - *dt = DisplayTransform::Create(); - - return dt; -} - -void OCIO_displayTransformSetInputColorSpaceName(DisplayTransformRcPtr *dt, const char *name) -{ - (*dt)->setInputColorSpaceName(name); -} - -void OCIO_displayTransformSetDisplay(DisplayTransformRcPtr *dt, const char *name) -{ - (*dt)->setDisplay(name); -} - -void OCIO_displayTransformSetView(DisplayTransformRcPtr *dt, const char *name) -{ - (*dt)->setView(name); -} - -void OCIO_displayTransformSetDisplayCC(DisplayTransformRcPtr *dt, ConstTransformRcPtr *t) -{ - (*dt)->setDisplayCC(*t); -} - -void OCIO_displayTransformSetLinearCC(DisplayTransformRcPtr *dt, ConstTransformRcPtr *t) -{ - (*dt)->setLinearCC(*t); -} - -void OCIO_displayTransformRelease(DisplayTransformRcPtr *dt) -{ - MEM_DELETE(dt, DisplayTransformRcPtr); -} - -PackedImageDesc *OCIO_createPackedImageDesc(float *data, long width, long height, long numChannels, - long chanStrideBytes, long xStrideBytes, long yStrideBytes) -{ - try { - void *mem = MEM_mallocN(sizeof(PackedImageDesc), __func__); - PackedImageDesc *id = new(mem) PackedImageDesc(data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes); - - return id; - } - catch (Exception &exception) { - OCIO_reportException(exception); - } - - return NULL; -} - -void OCIO_packedImageDescRelease(PackedImageDesc* id) -{ - MEM_DELETE(id, PackedImageDesc); -} - -ExponentTransformRcPtr *OCIO_createExponentTransform(void) -{ - ExponentTransformRcPtr *et = MEM_NEW(ExponentTransformRcPtr); - - *et = ExponentTransform::Create(); - - return et; -} - -void OCIO_exponentTransformSetValue(ExponentTransformRcPtr *et, const float *exponent) -{ - (*et)->setValue(exponent); -} - -void OCIO_exponentTransformRelease(ExponentTransformRcPtr *et) -{ - MEM_DELETE(et, ExponentTransformRcPtr); -} - -MatrixTransformRcPtr *OCIO_createMatrixTransform(void) -{ - MatrixTransformRcPtr *mt = MEM_NEW(MatrixTransformRcPtr); - - *mt = MatrixTransform::Create(); - - return mt; -} - -void OCIO_matrixTransformSetValue(MatrixTransformRcPtr *mt, const float *m44, const float *offset4) -{ - (*mt)->setValue(m44, offset4); -} - -void OCIO_matrixTransformRelease(MatrixTransformRcPtr *mt) -{ - MEM_DELETE(mt, MatrixTransformRcPtr); -} - -void OCIO_matrixTransformScale(float * m44, float * offset4, const float *scale4f) -{ - MatrixTransform::Scale(m44, offset4, scale4f); -} diff --git a/intern/opencolorio/ocio_capi_stub.cpp b/intern/opencolorio/ocio_capi_stub.cpp deleted file mode 100644 index a601cd3be91..00000000000 --- a/intern/opencolorio/ocio_capi_stub.cpp +++ /dev/null @@ -1,380 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2012 Blender Foundation. - * All rights reserved. - * - * Contributor(s): Brecht van Lommel - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include - -#include "MEM_guardedalloc.h" -#include "BLI_math_color.h" - -namespace OCIO_NAMESPACE {}; - -#include "ocio_capi.h" - -#define CONFIG_DEFAULT ((ConstConfigRcPtr*)1) - -#define PROCESSOR_LINEAR_TO_SRGB ((ConstProcessorRcPtr*)1) -#define PROCESSOR_SRGB_TO_LINEAR ((ConstProcessorRcPtr*)2) -#define PROCESSOR_UNKNOWN ((ConstProcessorRcPtr*)3) - -#define COLORSPACE_LINEAR ((ConstColorSpaceRcPtr*)1) -#define COLORSPACE_SRGB ((ConstColorSpaceRcPtr*)2) - -typedef struct PackedImageDescription { - float *data; - long width; - long height; - long numChannels; - long chanStrideBytes; - long xStrideBytes; - long yStrideBytes; -} PackedImageDescription; - -ConstConfigRcPtr *OCIO_getCurrentConfig(void) -{ - return CONFIG_DEFAULT; -} - -void OCIO_setCurrentConfig(const ConstConfigRcPtr *) -{ -} - -ConstConfigRcPtr *OCIO_configCreateFromEnv(void) -{ - return CONFIG_DEFAULT; -} - -ConstConfigRcPtr *OCIO_configCreateFromFile(const char *) -{ - return CONFIG_DEFAULT; -} - -void OCIO_configRelease(ConstConfigRcPtr *) -{ -} - -int OCIO_configGetNumColorSpaces(ConstConfigRcPtr *) -{ - return 2; -} - -const char *OCIO_configGetColorSpaceNameByIndex(ConstConfigRcPtr *, int index) -{ - if (index == 0) - return "Linear"; - else if (index == 1) - return "sRGB"; - - return NULL; -} - -ConstColorSpaceRcPtr *OCIO_configGetColorSpace(ConstConfigRcPtr *, const char *name) -{ - if (strcmp(name, "scene_linear") == 0) - return COLORSPACE_LINEAR; - else if (strcmp(name, "color_picking") == 0) - return COLORSPACE_SRGB; - else if (strcmp(name, "texture_paint") == 0) - return COLORSPACE_LINEAR; - else if (strcmp(name, "default_byte") == 0) - return COLORSPACE_SRGB; - else if (strcmp(name, "default_float") == 0) - return COLORSPACE_LINEAR; - else if (strcmp(name, "default_sequencer") == 0) - return COLORSPACE_SRGB; - else if (strcmp(name, "Linear") == 0) - return COLORSPACE_LINEAR; - else if (strcmp(name, "sRGB") == 0) - return COLORSPACE_SRGB; - - return NULL; -} - -int OCIO_configGetIndexForColorSpace(ConstConfigRcPtr *config, const char *name) -{ - ConstColorSpaceRcPtr *cs = OCIO_configGetColorSpace(config, name); - - if (cs == COLORSPACE_LINEAR) - return 0; - else if (cs == COLORSPACE_SRGB) - return 1; - - return -1; -} - -const char *OCIO_configGetDefaultDisplay(ConstConfigRcPtr *) -{ - return "sRGB"; -} - -int OCIO_configGetNumDisplays(ConstConfigRcPtr* config) -{ - return 1; -} - -const char *OCIO_configGetDisplay(ConstConfigRcPtr *, int index) -{ - if (index == 0) - return "sRGB"; - - return NULL; -} - -const char *OCIO_configGetDefaultView(ConstConfigRcPtr *, const char *) -{ - return "Default"; -} - -int OCIO_configGetNumViews(ConstConfigRcPtr *, const char *) -{ - return 1; -} - -const char *OCIO_configGetView(ConstConfigRcPtr *, const char *, int index) -{ - if (index == 0) - return "Default"; - - return NULL; -} - -const char *OCIO_configGetDisplayColorSpaceName(ConstConfigRcPtr *, const char *, const char *) -{ - return "sRGB"; -} - -int OCIO_colorSpaceIsInvertible(ConstColorSpaceRcPtr *cs) -{ - return 1; -} - -void OCIO_colorSpaceRelease(ConstColorSpaceRcPtr *cs) -{ -} - -ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(ConstConfigRcPtr *config, const char *srcName, const char *dstName) -{ - ConstColorSpaceRcPtr *cs_src = OCIO_configGetColorSpace(config, srcName); - ConstColorSpaceRcPtr *cs_dst = OCIO_configGetColorSpace(config, dstName); - - if (cs_src == COLORSPACE_LINEAR && cs_dst == COLORSPACE_SRGB) - return PROCESSOR_LINEAR_TO_SRGB; - else if (cs_src == COLORSPACE_SRGB && cs_dst == COLORSPACE_LINEAR) - return PROCESSOR_SRGB_TO_LINEAR; - - return 0; -} - -ConstProcessorRcPtr *OCIO_configGetProcessor(ConstConfigRcPtr *, ConstTransformRcPtr *tfm) -{ - return (ConstProcessorRcPtr*)tfm; -} - -void OCIO_processorApply(ConstProcessorRcPtr *processor, PackedImageDesc *img) -{ - /* OCIO_TODO stride not respected, channels must be 3 or 4 */ - PackedImageDescription *desc = (PackedImageDescription*)img; - int channels = desc->numChannels; - float *pixels = desc->data; - int width = desc->width; - int height = desc->height; - int x, y; - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - float *pixel = pixels + channels * (y * width + x); - - if (channels == 4) - OCIO_processorApplyRGBA(processor, pixel); - else if (channels == 3) - OCIO_processorApplyRGB(processor, pixel); - } - } -} - -void OCIO_processorApply_predivide(ConstProcessorRcPtr *processor, PackedImageDesc *img) -{ - /* OCIO_TODO stride not respected, channels must be 3 or 4 */ - PackedImageDescription *desc = (PackedImageDescription*)img; - int channels = desc->numChannels; - float *pixels = desc->data; - int width = desc->width; - int height = desc->height; - int x, y; - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - float *pixel = pixels + channels * (y * width + x); - - if (channels == 4) - OCIO_processorApplyRGBA_predivide(processor, pixel); - else if (channels == 3) - OCIO_processorApplyRGB(processor, pixel); - } - } -} - -void OCIO_processorApplyRGB(ConstProcessorRcPtr *processor, float *pixel) -{ - if (processor == PROCESSOR_LINEAR_TO_SRGB) - linearrgb_to_srgb_v3_v3(pixel, pixel); - else if (processor == PROCESSOR_SRGB_TO_LINEAR) - srgb_to_linearrgb_v3_v3(pixel, pixel); -} - -void OCIO_processorApplyRGBA(ConstProcessorRcPtr *processor, float *pixel) -{ - if (processor == PROCESSOR_LINEAR_TO_SRGB) - linearrgb_to_srgb_v4(pixel, pixel); - else if (processor == PROCESSOR_SRGB_TO_LINEAR) - srgb_to_linearrgb_v4(pixel, pixel); -} - -void OCIO_processorApplyRGBA_predivide(ConstProcessorRcPtr *processor, float *pixel) -{ - if (pixel[3] == 1.0f || pixel[3] == 0.0f) { - OCIO_processorApplyRGBA(processor, pixel); - } - else { - float alpha, inv_alpha; - - alpha = pixel[3]; - inv_alpha = 1.0f / alpha; - - pixel[0] *= inv_alpha; - pixel[1] *= inv_alpha; - pixel[2] *= inv_alpha; - - OCIO_processorApplyRGBA(processor, pixel); - - pixel[0] *= alpha; - pixel[1] *= alpha; - pixel[2] *= alpha; - } -} - -void OCIO_processorRelease(ConstProcessorRcPtr *) -{ -} - -const char *OCIO_colorSpaceGetName(ConstColorSpaceRcPtr *cs) -{ - if (cs == COLORSPACE_LINEAR) - return "Linear"; - else if (cs == COLORSPACE_SRGB) - return "sRGB"; - - return NULL; -} - -const char *OCIO_colorSpaceGetDescription(ConstColorSpaceRcPtr *) -{ - return ""; -} - -const char *OCIO_colorSpaceGetFamily(ConstColorSpaceRcPtr *) -{ - return ""; -} - -DisplayTransformRcPtr *OCIO_createDisplayTransform(void) -{ - return (DisplayTransformRcPtr*)PROCESSOR_LINEAR_TO_SRGB; -} - -void OCIO_displayTransformSetInputColorSpaceName(DisplayTransformRcPtr *, const char *) -{ -} - -void OCIO_displayTransformSetDisplay(DisplayTransformRcPtr *, const char *) -{ -} - -void OCIO_displayTransformSetView(DisplayTransformRcPtr *, const char *) -{ -} - -void OCIO_displayTransformSetDisplayCC(DisplayTransformRcPtr *, ConstTransformRcPtr *) -{ -} - -void OCIO_displayTransformSetLinearCC(DisplayTransformRcPtr *, ConstTransformRcPtr *) -{ -} - -void OCIO_displayTransformRelease(DisplayTransformRcPtr *) -{ -} - -PackedImageDesc *OCIO_createPackedImageDesc(float *data, long width, long height, long numChannels, - long chanStrideBytes, long xStrideBytes, long yStrideBytes) -{ - PackedImageDescription *desc = (PackedImageDescription*)MEM_callocN(sizeof(PackedImageDescription), "PackedImageDescription"); - - desc->data = data; - desc->width = width; - desc->height = height; - desc->numChannels = numChannels; - desc->chanStrideBytes = chanStrideBytes; - desc->xStrideBytes = xStrideBytes; - desc->yStrideBytes = yStrideBytes; - - return (PackedImageDesc*)desc; -} - -void OCIO_packedImageDescRelease(PackedImageDesc* id) -{ - MEM_freeN(id); -} - -ExponentTransformRcPtr *OCIO_createExponentTransform(void) -{ - return (ExponentTransformRcPtr*)PROCESSOR_UNKNOWN; -} - -void OCIO_exponentTransformSetValue(ExponentTransformRcPtr *, const float *) -{ -} - -void OCIO_exponentTransformRelease(ExponentTransformRcPtr *) -{ -} - -MatrixTransformRcPtr *OCIO_createMatrixTransform(void) -{ - return (MatrixTransformRcPtr*)PROCESSOR_UNKNOWN; -} - -void OCIO_matrixTransformSetValue(MatrixTransformRcPtr *, const float *, const float *) -{ -} - -void OCIO_matrixTransformRelease(MatrixTransformRcPtr *) -{ -} - -void OCIO_matrixTransformScale(float * , float * , const float *) -{ -} - diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc new file mode 100644 index 00000000000..49fc44d1e12 --- /dev/null +++ b/intern/opencolorio/ocio_impl.cc @@ -0,0 +1,544 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Xavier Thomas + * Lukas Toene, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include + +#include + +using namespace OCIO_NAMESPACE; + +#include "MEM_guardedalloc.h" + +#include "ocio_impl.h" + +#if !defined(WITH_ASSERT_ABORT) +# define OCIO_abort() +#else +# include +# define OCIO_abort() abort() +#endif + +#if defined(_MSC_VER) +# define __func__ __FUNCTION__ +#endif + +#define MEM_NEW(type) new(MEM_mallocN(sizeof(type), __func__)) type() +#define MEM_DELETE(what, type) if(what) { (what)->~type(); MEM_freeN(what); } (void)0 + +static void OCIO_reportError(const char *err) +{ + std::cerr << "OpenColorIO Error: " << err << std::endl; + + OCIO_abort(); +} + +static void OCIO_reportException(Exception &exception) +{ + OCIO_reportError(exception.what()); +} + +OCIO_ConstConfigRcPtr *OCIOImpl::getCurrentConfig(void) +{ + ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr); + + try { + *config = GetCurrentConfig(); + + if (*config) + return (OCIO_ConstConfigRcPtr *) config; + } + catch (Exception &exception) { + OCIO_reportException(exception); + } + + MEM_DELETE(config, ConstConfigRcPtr); + + return NULL; +} + +void OCIOImpl::setCurrentConfig(const OCIO_ConstConfigRcPtr *config) +{ + try { + SetCurrentConfig(*(ConstConfigRcPtr *) config); + } + catch (Exception &exception) { + OCIO_reportException(exception); + } +} + +OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromEnv(void) +{ + ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr); + + try { + *config = Config::CreateFromEnv(); + + if (*config) + return (OCIO_ConstConfigRcPtr *) config; + } + catch (Exception &exception) { + OCIO_reportException(exception); + } + + MEM_DELETE(config, ConstConfigRcPtr); + + return NULL; +} + + +OCIO_ConstConfigRcPtr *OCIOImpl::configCreateFromFile(const char *filename) +{ + ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr); + + try { + *config = Config::CreateFromFile(filename); + + if (*config) + return (OCIO_ConstConfigRcPtr *) config; + } + catch (Exception &exception) { + OCIO_reportException(exception); + } + + MEM_DELETE(config, ConstConfigRcPtr); + + return NULL; +} + +void OCIOImpl::configRelease(OCIO_ConstConfigRcPtr *config) +{ + MEM_DELETE((ConstConfigRcPtr *) config, ConstConfigRcPtr); +} + +int OCIOImpl::configGetNumColorSpaces(OCIO_ConstConfigRcPtr *config) +{ + try { + return (*(ConstConfigRcPtr *) config)->getNumColorSpaces(); + } + catch (Exception &exception) { + OCIO_reportException(exception); + } + + return 0; +} + +const char *OCIOImpl::configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr *config, int index) +{ + try { + return (*(ConstConfigRcPtr *) config)->getColorSpaceNameByIndex(index); + } + catch (Exception &exception) { + OCIO_reportException(exception); + } + + return NULL; +} + +OCIO_ConstColorSpaceRcPtr *OCIOImpl::configGetColorSpace(OCIO_ConstConfigRcPtr *config, const char *name) +{ + ConstColorSpaceRcPtr *cs = MEM_NEW(ConstColorSpaceRcPtr); + + try { + *cs = (*(ConstConfigRcPtr *) config)->getColorSpace(name); + + if (*cs) + return (OCIO_ConstColorSpaceRcPtr *) cs; + } + catch (Exception &exception) { + OCIO_reportException(exception); + } + + MEM_DELETE(cs, ConstColorSpaceRcPtr); + + return NULL; +} + +int OCIOImpl::configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, const char *name) +{ + try { + return (*(ConstConfigRcPtr *) config)->getIndexForColorSpace(name); + } + catch (Exception &exception) { + OCIO_reportException(exception); + } + + return -1; +} + +const char *OCIOImpl::configGetDefaultDisplay(OCIO_ConstConfigRcPtr *config) +{ + try { + return (*(ConstConfigRcPtr *) config)->getDefaultDisplay(); + } + catch (Exception &exception) { + OCIO_reportException(exception); + } + + return NULL; +} + +int OCIOImpl::configGetNumDisplays(OCIO_ConstConfigRcPtr* config) +{ + try { + return (*(ConstConfigRcPtr *) config)->getNumDisplays(); + } + catch (Exception &exception) { + OCIO_reportException(exception); + } + + return 0; +} + +const char *OCIOImpl::configGetDisplay(OCIO_ConstConfigRcPtr *config, int index) +{ + try { + return (*(ConstConfigRcPtr *) config)->getDisplay(index); + } + catch (Exception &exception) { + OCIO_reportException(exception); + } + + return NULL; +} + +const char *OCIOImpl::configGetDefaultView(OCIO_ConstConfigRcPtr *config, const char *display) +{ + try { + return (*(ConstConfigRcPtr *) config)->getDefaultView(display); + } + catch (Exception &exception) { + OCIO_reportException(exception); + } + + return NULL; +} + +int OCIOImpl::configGetNumViews(OCIO_ConstConfigRcPtr *config, const char *display) +{ + try { + return (*(ConstConfigRcPtr *) config)->getNumViews(display); + } + catch (Exception &exception) { + OCIO_reportException(exception); + } + + return 0; +} + +const char *OCIOImpl::configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index) +{ + try { + return (*(ConstConfigRcPtr *) config)->getView(display, index); + } + catch (Exception &exception) { + OCIO_reportException(exception); + } + + return NULL; +} + +const char *OCIOImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view) +{ + try { + return (*(ConstConfigRcPtr *) config)->getDisplayColorSpaceName(display, view); + } + catch (Exception &exception) { + OCIO_reportException(exception); + } + + return NULL; +} + +int OCIOImpl::colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs_) +{ + ConstColorSpaceRcPtr *cs = (ConstColorSpaceRcPtr *) cs_; + const char *family = (*cs)->getFamily(); + + if (!strcmp(family, "rrt") || !strcmp(family, "display")) { + /* assume display and rrt transformations are not invertible + * in fact some of them could be, but it doesn't make much sense to allow use them as invertible + */ + return false; + } + + if ((*cs)->isData()) { + /* data color spaces don't have transformation at all */ + return true; + } + + if ((*cs)->getTransform(COLORSPACE_DIR_TO_REFERENCE)) { + /* if there's defined transform to reference space, color space could be converted to scene linear */ + return true; + } + + return true; +} + +int OCIOImpl::colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs) +{ + return (*(ConstColorSpaceRcPtr *) cs)->isData(); +} + +void OCIOImpl::colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs) +{ + MEM_DELETE((ConstColorSpaceRcPtr *) cs, ConstColorSpaceRcPtr); +} + +OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, const char *srcName, const char *dstName) +{ + ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr); + + try { + *p = (*(ConstConfigRcPtr *) config)->getProcessor(srcName, dstName); + + if (*p) + return (OCIO_ConstProcessorRcPtr *) p; + } + catch (Exception &exception) { + OCIO_reportException(exception); + } + + MEM_DELETE(p, ConstProcessorRcPtr); + + return 0; +} + +OCIO_ConstProcessorRcPtr *OCIOImpl::configGetProcessor(OCIO_ConstConfigRcPtr *config, OCIO_ConstTransformRcPtr *transform) +{ + ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr); + + try { + *p = (*(ConstConfigRcPtr *) config)->getProcessor(*(ConstTransformRcPtr *) transform); + + if (*p) + return (OCIO_ConstProcessorRcPtr *) p; + } + catch (Exception &exception) { + OCIO_reportException(exception); + } + + MEM_DELETE(p, ConstProcessorRcPtr); + + return NULL; +} + +void OCIOImpl::processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img) +{ + try { + (*(ConstProcessorRcPtr *) processor)->apply(*(PackedImageDesc *) img); + } + catch (Exception &exception) { + OCIO_reportException(exception); + } +} + +void OCIOImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img_) +{ + try { + PackedImageDesc *img = (PackedImageDesc *) img_; + int channels = img->getNumChannels(); + + if (channels == 4) { + float *pixels = img->getData(); + + int width = img->getWidth(); + int height = img->getHeight(); + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + float *pixel = pixels + 4 * (y * width + x); + + processorApplyRGBA_predivide(processor, pixel); + } + } + } + else { + (*(ConstProcessorRcPtr *) processor)->apply(*img); + } + } + catch (Exception &exception) { + OCIO_reportException(exception); + } +} + +void OCIOImpl::processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel) +{ + (*(ConstProcessorRcPtr *) processor)->applyRGB(pixel); +} + +void OCIOImpl::processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel) +{ + (*(ConstProcessorRcPtr *) processor)->applyRGBA(pixel); +} + +void OCIOImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel) +{ + if (pixel[3] == 1.0f || pixel[3] == 0.0f) { + (*(ConstProcessorRcPtr *) processor)->applyRGBA(pixel); + } + else { + float alpha, inv_alpha; + + alpha = pixel[3]; + inv_alpha = 1.0f / alpha; + + pixel[0] *= inv_alpha; + pixel[1] *= inv_alpha; + pixel[2] *= inv_alpha; + + (*(ConstProcessorRcPtr *) processor)->applyRGBA(pixel); + + pixel[0] *= alpha; + pixel[1] *= alpha; + pixel[2] *= alpha; + } +} + +void OCIOImpl::processorRelease(OCIO_ConstProcessorRcPtr *p) +{ + p->~OCIO_ConstProcessorRcPtr(); + MEM_freeN(p); +} + +const char *OCIOImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs) +{ + return (*(ConstColorSpaceRcPtr *) cs)->getName(); +} + +const char *OCIOImpl::colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs) +{ + return (*(ConstColorSpaceRcPtr *) cs)->getDescription(); +} + +const char *OCIOImpl::colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs) +{ + return (*(ConstColorSpaceRcPtr *)cs)->getFamily(); +} + +OCIO_DisplayTransformRcPtr *OCIOImpl::createDisplayTransform(void) +{ + DisplayTransformRcPtr *dt = MEM_NEW(DisplayTransformRcPtr); + + *dt = DisplayTransform::Create(); + + return (OCIO_DisplayTransformRcPtr *) dt; +} + +void OCIOImpl::displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name) +{ + (*(DisplayTransformRcPtr *) dt)->setInputColorSpaceName(name); +} + +void OCIOImpl::displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name) +{ + (*(DisplayTransformRcPtr *) dt)->setDisplay(name); +} + +void OCIOImpl::displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name) +{ + (*(DisplayTransformRcPtr *) dt)->setView(name); +} + +void OCIOImpl::displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *t) +{ + (*(DisplayTransformRcPtr *) dt)->setDisplayCC(* (ConstTransformRcPtr *) t); +} + +void OCIOImpl::displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *t) +{ + (*(DisplayTransformRcPtr *) dt)->setLinearCC(*(ConstTransformRcPtr *) t); +} + +void OCIOImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr *dt) +{ + MEM_DELETE((DisplayTransformRcPtr *) dt, DisplayTransformRcPtr); +} + +OCIO_PackedImageDesc *OCIOImpl::createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels, + long chanStrideBytes, long xStrideBytes, long yStrideBytes) +{ + try { + void *mem = MEM_mallocN(sizeof(PackedImageDesc), __func__); + PackedImageDesc *id = new(mem) PackedImageDesc(data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes); + + return (OCIO_PackedImageDesc *) id; + } + catch (Exception &exception) { + OCIO_reportException(exception); + } + + return NULL; +} + +void OCIOImpl::OCIO_PackedImageDescRelease(OCIO_PackedImageDesc* id) +{ + MEM_DELETE((PackedImageDesc *) id, PackedImageDesc); +} + +OCIO_ExponentTransformRcPtr *OCIOImpl::createExponentTransform(void) +{ + ExponentTransformRcPtr *et = MEM_NEW(ExponentTransformRcPtr); + + *et = ExponentTransform::Create(); + + return (OCIO_ExponentTransformRcPtr *) et; +} + +void OCIOImpl::exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent) +{ + (*(ExponentTransformRcPtr *) et)->setValue(exponent); +} + +void OCIOImpl::exponentTransformRelease(OCIO_ExponentTransformRcPtr *et) +{ + MEM_DELETE((ExponentTransformRcPtr *) et, ExponentTransformRcPtr); +} + +OCIO_MatrixTransformRcPtr *OCIOImpl::createMatrixTransform(void) +{ + MatrixTransformRcPtr *mt = MEM_NEW(MatrixTransformRcPtr); + + *mt = MatrixTransform::Create(); + + return (OCIO_MatrixTransformRcPtr *) mt; +} + +void OCIOImpl::matrixTransformSetValue(OCIO_MatrixTransformRcPtr *mt, const float *m44, const float *offset4) +{ + (*(MatrixTransformRcPtr *) mt)->setValue(m44, offset4); +} + +void OCIOImpl::matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt) +{ + MEM_DELETE((MatrixTransformRcPtr *) mt, MatrixTransformRcPtr); +} + +void OCIOImpl::matrixTransformScale(float * m44, float * offset4, const float *scale4f) +{ + MatrixTransform::Scale(m44, offset4, scale4f); +} diff --git a/intern/opencolorio/ocio_impl.h b/intern/opencolorio/ocio_impl.h new file mode 100644 index 00000000000..64cf5ec3322 --- /dev/null +++ b/intern/opencolorio/ocio_impl.h @@ -0,0 +1,240 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __OCIO_IMPL_H__ +#define __OCIO_IMPL_H__ + +#include "ocio_capi.h" + +class IOCIOImpl { +public: + virtual ~IOCIOImpl() {}; + + virtual OCIO_ConstConfigRcPtr *getCurrentConfig(void) = 0; + virtual void setCurrentConfig(const OCIO_ConstConfigRcPtr *config) = 0; + + virtual OCIO_ConstConfigRcPtr *configCreateFromEnv(void) = 0; + virtual OCIO_ConstConfigRcPtr *configCreateFromFile(const char* filename) = 0; + + virtual void configRelease(OCIO_ConstConfigRcPtr *config) = 0; + + virtual int configGetNumColorSpaces(OCIO_ConstConfigRcPtr *config) = 0; + virtual const char *configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr *config, int index) = 0; + virtual OCIO_ConstColorSpaceRcPtr *configGetColorSpace(OCIO_ConstConfigRcPtr *config, const char *name) = 0; + virtual int configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, const char *name) = 0; + + virtual int colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs) = 0; + virtual int colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs) = 0; + + virtual void colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs) = 0; + + virtual const char *configGetDefaultDisplay(OCIO_ConstConfigRcPtr *config) = 0; + virtual int configGetNumDisplays(OCIO_ConstConfigRcPtr *config) = 0; + virtual const char *configGetDisplay(OCIO_ConstConfigRcPtr *config, int index) = 0; + virtual const char *configGetDefaultView(OCIO_ConstConfigRcPtr *config, const char *display) = 0; + virtual int configGetNumViews(OCIO_ConstConfigRcPtr *config, const char *display) = 0; + virtual const char *configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index) = 0; + virtual const char *configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view) = 0; + + virtual OCIO_ConstProcessorRcPtr *configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, const char *srcName, const char *dstName) = 0; + virtual OCIO_ConstProcessorRcPtr *configGetProcessor(OCIO_ConstConfigRcPtr *config, OCIO_ConstTransformRcPtr *transform) = 0; + + virtual void processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img) = 0; + virtual void processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img) = 0; + virtual void processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel) = 0; + virtual void processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel) = 0; + virtual void processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel) = 0; + + virtual void processorRelease(OCIO_ConstProcessorRcPtr *p) = 0; + + virtual const char *colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs) = 0; + virtual const char *colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs) = 0; + virtual const char *colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs) = 0; + + virtual OCIO_DisplayTransformRcPtr *createDisplayTransform(void) = 0; + virtual void displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name) = 0; + virtual void displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name) = 0; + virtual void displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name) = 0; + virtual void displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et) = 0; + virtual void displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et) = 0; + virtual void displayTransformRelease(OCIO_DisplayTransformRcPtr *dt) = 0; + + virtual OCIO_PackedImageDesc *createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels, + long chanStrideBytes, long xStrideBytes, long yStrideBytes) = 0; + + virtual void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p) = 0; + + virtual OCIO_ExponentTransformRcPtr *createExponentTransform(void) = 0; + virtual void exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent) = 0; + virtual void exponentTransformRelease(OCIO_ExponentTransformRcPtr *et) = 0; + + virtual OCIO_MatrixTransformRcPtr *createMatrixTransform(void) = 0; + virtual void matrixTransformSetValue(OCIO_MatrixTransformRcPtr *et, const float *m44, const float *offset4) = 0; + virtual void matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt) = 0; + + virtual void matrixTransformScale(float * m44, float * offset4, const float * scale4) = 0; +}; + +class FallbackImpl : public IOCIOImpl { +public: + FallbackImpl() {}; + + OCIO_ConstConfigRcPtr *getCurrentConfig(void); + void setCurrentConfig(const OCIO_ConstConfigRcPtr *config); + + OCIO_ConstConfigRcPtr *configCreateFromEnv(void); + OCIO_ConstConfigRcPtr *configCreateFromFile(const char* filename); + + void configRelease(OCIO_ConstConfigRcPtr *config); + + int configGetNumColorSpaces(OCIO_ConstConfigRcPtr *config); + const char *configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr *config, int index); + OCIO_ConstColorSpaceRcPtr *configGetColorSpace(OCIO_ConstConfigRcPtr *config, const char *name); + int configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, const char *name); + + int colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs); + int colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs); + + void colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs); + + const char *configGetDefaultDisplay(OCIO_ConstConfigRcPtr *config); + int configGetNumDisplays(OCIO_ConstConfigRcPtr *config); + const char *configGetDisplay(OCIO_ConstConfigRcPtr *config, int index); + const char *configGetDefaultView(OCIO_ConstConfigRcPtr *config, const char *display); + int configGetNumViews(OCIO_ConstConfigRcPtr *config, const char *display); + const char *configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index); + const char *configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view); + + OCIO_ConstProcessorRcPtr *configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, const char *srcName, const char *dstName); + OCIO_ConstProcessorRcPtr *configGetProcessor(OCIO_ConstConfigRcPtr *config, OCIO_ConstTransformRcPtr *transform); + + void processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img); + void processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img); + void processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel); + void processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel); + void processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel); + + void processorRelease(OCIO_ConstProcessorRcPtr *p); + + const char *colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs); + const char *colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs); + const char *colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs); + + OCIO_DisplayTransformRcPtr *createDisplayTransform(void); + void displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name); + void displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name); + void displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name); + void displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et); + void displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et); + void displayTransformRelease(OCIO_DisplayTransformRcPtr *dt); + + OCIO_PackedImageDesc *createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels, + long chanStrideBytes, long xStrideBytes, long yStrideBytes); + + void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p); + + OCIO_ExponentTransformRcPtr *createExponentTransform(void); + void exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent); + void exponentTransformRelease(OCIO_ExponentTransformRcPtr *et); + + OCIO_MatrixTransformRcPtr *createMatrixTransform(void); + void matrixTransformSetValue(OCIO_MatrixTransformRcPtr *et, const float *m44, const float *offset4); + void matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt); + + void matrixTransformScale(float * m44, float * offset4, const float * scale4); +}; + +#ifdef WITH_OCIO +class OCIOImpl : public IOCIOImpl { +public: + OCIOImpl() {}; + + OCIO_ConstConfigRcPtr *getCurrentConfig(void); + void setCurrentConfig(const OCIO_ConstConfigRcPtr *config); + + OCIO_ConstConfigRcPtr *configCreateFromEnv(void); + OCIO_ConstConfigRcPtr *configCreateFromFile(const char* filename); + + void configRelease(OCIO_ConstConfigRcPtr *config); + + int configGetNumColorSpaces(OCIO_ConstConfigRcPtr *config); + const char *configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr *config, int index); + OCIO_ConstColorSpaceRcPtr *configGetColorSpace(OCIO_ConstConfigRcPtr *config, const char *name); + int configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, const char *name); + + int colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs); + int colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs); + + void colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs); + + const char *configGetDefaultDisplay(OCIO_ConstConfigRcPtr *config); + int configGetNumDisplays(OCIO_ConstConfigRcPtr *config); + const char *configGetDisplay(OCIO_ConstConfigRcPtr *config, int index); + const char *configGetDefaultView(OCIO_ConstConfigRcPtr *config, const char *display); + int configGetNumViews(OCIO_ConstConfigRcPtr *config, const char *display); + const char *configGetView(OCIO_ConstConfigRcPtr *config, const char *display, int index); + const char *configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr *config, const char *display, const char *view); + + OCIO_ConstProcessorRcPtr *configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, const char *srcName, const char *dstName); + OCIO_ConstProcessorRcPtr *configGetProcessor(OCIO_ConstConfigRcPtr *config, OCIO_ConstTransformRcPtr *transform); + + void processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img); + void processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img); + void processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel); + void processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel); + void processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel); + + void processorRelease(OCIO_ConstProcessorRcPtr *p); + + const char *colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs); + const char *colorSpaceGetDescription(OCIO_ConstColorSpaceRcPtr *cs); + const char *colorSpaceGetFamily(OCIO_ConstColorSpaceRcPtr *cs); + + OCIO_DisplayTransformRcPtr *createDisplayTransform(void); + void displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr *dt, const char *name); + void displayTransformSetDisplay(OCIO_DisplayTransformRcPtr *dt, const char *name); + void displayTransformSetView(OCIO_DisplayTransformRcPtr *dt, const char *name); + void displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et); + void displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr *dt, OCIO_ConstTransformRcPtr *et); + void displayTransformRelease(OCIO_DisplayTransformRcPtr *dt); + + OCIO_PackedImageDesc *createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels, + long chanStrideBytes, long xStrideBytes, long yStrideBytes); + + void OCIO_PackedImageDescRelease(OCIO_PackedImageDesc *p); + + OCIO_ExponentTransformRcPtr *createExponentTransform(void); + void exponentTransformSetValue(OCIO_ExponentTransformRcPtr *et, const float *exponent); + void exponentTransformRelease(OCIO_ExponentTransformRcPtr *et); + + OCIO_MatrixTransformRcPtr *createMatrixTransform(void); + void matrixTransformSetValue(OCIO_MatrixTransformRcPtr *et, const float *m44, const float *offset4); + void matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt); + + void matrixTransformScale(float * m44, float * offset4, const float * scale4); +}; +#endif + +#endif /* OCIO_IMPL_H */ From 712af7f097858a2fa28b73816b40de11f7beb48d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 5 Nov 2012 19:49:30 +0000 Subject: [PATCH 156/160] Synchronize changes with trunk --- intern/opencolorio/CMakeLists.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/intern/opencolorio/CMakeLists.txt b/intern/opencolorio/CMakeLists.txt index aeb10669d57..c281a6e7bbb 100644 --- a/intern/opencolorio/CMakeLists.txt +++ b/intern/opencolorio/CMakeLists.txt @@ -23,23 +23,23 @@ # # ***** END GPL LICENSE BLOCK ***** - set(INC - . +set(INC + . ../guardedalloc ../../source/blender/blenlib ) set(INC_SYS - ) +) - set(SRC +set(SRC ocio_capi.cc fallback_impl.cc - ocio_capi.h + ocio_capi.h ocio_impl.h - ) +) if(WITH_OPENCOLORIO) add_definitions( @@ -52,12 +52,12 @@ if(WITH_OPENCOLORIO) list(APPEND SRC ocio_impl.cc -) + ) if(WIN32 AND NOT MINGW) list(APPEND INC_SYS ${BOOST_INCLUDE_DIR} -) + ) endif() endif() From da24aa8d109a08b40b5547aacf3586026de78af2 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 5 Nov 2012 19:57:59 +0000 Subject: [PATCH 157/160] Merging r51897 through r51922 from trunk into soc-2011-tomato --- .../build_environment/prepare_release_env.sh | 2 +- .../config/user-config-glibc27-i686.py | 4 +- .../config/user-config-glibc27-x86_64.py | 4 +- .../user-config-player-glibc211-i686.py | 8 + .../user-config-player-glibc211-x86_64.py | 8 + .../config/user-config-player-glibc27-i686.py | 11 +- .../user-config-player-glibc27-x86_64.py | 11 +- .../cmake/Modules/FindPythonLibsUnix.cmake | 2 +- .../scons/config/Modules/FindPython.py | 2 +- extern/carve/lib/intersect_face_division.cpp | 3 +- intern/audaspace/CMakeLists.txt | 6 +- .../audaspace/FX/AUD_AccumulatorFactory.cpp | 8 +- intern/audaspace/FX/AUD_AccumulatorFactory.h | 4 +- .../audaspace/FX/AUD_BaseIIRFilterReader.cpp | 2 +- intern/audaspace/FX/AUD_BaseIIRFilterReader.h | 2 +- .../audaspace/FX/AUD_ButterworthFactory.cpp | 2 +- intern/audaspace/FX/AUD_ButterworthFactory.h | 2 +- .../FX/AUD_CallbackIIRFilterReader.cpp | 2 +- .../FX/AUD_CallbackIIRFilterReader.h | 2 +- intern/audaspace/FX/AUD_DelayFactory.cpp | 6 +- intern/audaspace/FX/AUD_DelayFactory.h | 4 +- intern/audaspace/FX/AUD_DelayReader.cpp | 2 +- intern/audaspace/FX/AUD_DelayReader.h | 2 +- intern/audaspace/FX/AUD_DoubleFactory.cpp | 10 +- intern/audaspace/FX/AUD_DoubleFactory.h | 8 +- intern/audaspace/FX/AUD_DoubleReader.cpp | 4 +- intern/audaspace/FX/AUD_DoubleReader.h | 9 +- .../FX/AUD_DynamicIIRFilterFactory.cpp | 8 +- .../FX/AUD_DynamicIIRFilterFactory.h | 18 +- .../FX/AUD_DynamicIIRFilterReader.cpp | 8 +- .../audaspace/FX/AUD_DynamicIIRFilterReader.h | 8 +- intern/audaspace/FX/AUD_EffectFactory.cpp | 4 +- intern/audaspace/FX/AUD_EffectFactory.h | 8 +- intern/audaspace/FX/AUD_EffectReader.cpp | 2 +- intern/audaspace/FX/AUD_EffectReader.h | 7 +- intern/audaspace/FX/AUD_EnvelopeFactory.cpp | 10 +- intern/audaspace/FX/AUD_EnvelopeFactory.h | 4 +- intern/audaspace/FX/AUD_FaderFactory.cpp | 6 +- intern/audaspace/FX/AUD_FaderFactory.h | 4 +- intern/audaspace/FX/AUD_FaderReader.cpp | 2 +- intern/audaspace/FX/AUD_FaderReader.h | 2 +- intern/audaspace/FX/AUD_HighpassFactory.cpp | 2 +- intern/audaspace/FX/AUD_HighpassFactory.h | 2 +- .../AUD_IDynamicIIRFilterCalculator.h} | 44 +-- intern/audaspace/FX/AUD_IIRFilterFactory.cpp | 6 +- intern/audaspace/FX/AUD_IIRFilterFactory.h | 5 +- intern/audaspace/FX/AUD_IIRFilterReader.cpp | 2 +- intern/audaspace/FX/AUD_IIRFilterReader.h | 2 +- intern/audaspace/FX/AUD_LimiterFactory.cpp | 6 +- intern/audaspace/FX/AUD_LimiterFactory.h | 4 +- intern/audaspace/FX/AUD_LimiterReader.cpp | 2 +- intern/audaspace/FX/AUD_LimiterReader.h | 2 +- intern/audaspace/FX/AUD_LoopFactory.cpp | 6 +- intern/audaspace/FX/AUD_LoopFactory.h | 4 +- intern/audaspace/FX/AUD_LoopReader.cpp | 2 +- intern/audaspace/FX/AUD_LoopReader.h | 2 +- intern/audaspace/FX/AUD_LowpassFactory.cpp | 2 +- intern/audaspace/FX/AUD_LowpassFactory.h | 2 +- intern/audaspace/FX/AUD_PingPongFactory.cpp | 10 +- intern/audaspace/FX/AUD_PingPongFactory.h | 4 +- intern/audaspace/FX/AUD_PitchFactory.cpp | 6 +- intern/audaspace/FX/AUD_PitchFactory.h | 4 +- intern/audaspace/FX/AUD_PitchReader.cpp | 2 +- intern/audaspace/FX/AUD_PitchReader.h | 2 +- intern/audaspace/FX/AUD_RectifyFactory.cpp | 6 +- intern/audaspace/FX/AUD_RectifyFactory.h | 4 +- intern/audaspace/FX/AUD_ReverseFactory.cpp | 6 +- intern/audaspace/FX/AUD_ReverseFactory.h | 4 +- intern/audaspace/FX/AUD_ReverseReader.cpp | 2 +- intern/audaspace/FX/AUD_ReverseReader.h | 2 +- intern/audaspace/FX/AUD_SquareFactory.cpp | 8 +- intern/audaspace/FX/AUD_SquareFactory.h | 4 +- intern/audaspace/FX/AUD_SumFactory.cpp | 6 +- intern/audaspace/FX/AUD_SumFactory.h | 4 +- intern/audaspace/FX/AUD_SuperposeFactory.cpp | 10 +- intern/audaspace/FX/AUD_SuperposeFactory.h | 8 +- intern/audaspace/FX/AUD_SuperposeReader.cpp | 2 +- intern/audaspace/FX/AUD_SuperposeReader.h | 9 +- intern/audaspace/FX/AUD_VolumeFactory.cpp | 6 +- intern/audaspace/FX/AUD_VolumeFactory.h | 4 +- intern/audaspace/OpenAL/AUD_OpenALDevice.cpp | 63 ++-- intern/audaspace/OpenAL/AUD_OpenALDevice.h | 14 +- intern/audaspace/Python/AUD_PyAPI.cpp | 170 +++++------ intern/audaspace/SConscript | 2 +- intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp | 8 +- intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h | 6 +- intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp | 2 +- intern/audaspace/ffmpeg/AUD_FFMPEGReader.h | 6 +- intern/audaspace/intern/AUD_BufferReader.cpp | 2 +- intern/audaspace/intern/AUD_BufferReader.h | 7 +- intern/audaspace/intern/AUD_C-API.cpp | 140 ++++----- intern/audaspace/intern/AUD_C-API.h | 4 +- .../intern/AUD_ChannelMapperFactory.cpp | 8 +- .../intern/AUD_ChannelMapperFactory.h | 4 +- .../intern/AUD_ChannelMapperReader.cpp | 2 +- .../intern/AUD_ChannelMapperReader.h | 2 +- .../audaspace/intern/AUD_ConverterFactory.cpp | 8 +- .../audaspace/intern/AUD_ConverterFactory.h | 4 +- .../audaspace/intern/AUD_ConverterReader.cpp | 2 +- intern/audaspace/intern/AUD_ConverterReader.h | 2 +- intern/audaspace/intern/AUD_FileFactory.cpp | 14 +- intern/audaspace/intern/AUD_FileFactory.h | 6 +- intern/audaspace/intern/AUD_FileWriter.cpp | 10 +- intern/audaspace/intern/AUD_FileWriter.h | 9 +- intern/audaspace/intern/AUD_IDevice.h | 7 +- intern/audaspace/intern/AUD_IFactory.h | 5 +- .../intern/AUD_JOSResampleFactory.cpp | 6 +- .../audaspace/intern/AUD_JOSResampleFactory.h | 4 +- .../intern/AUD_JOSResampleReader.cpp | 2 +- .../audaspace/intern/AUD_JOSResampleReader.h | 2 +- .../intern/AUD_LinearResampleFactory.cpp | 6 +- .../intern/AUD_LinearResampleFactory.h | 4 +- .../intern/AUD_LinearResampleReader.cpp | 2 +- .../intern/AUD_LinearResampleReader.h | 2 +- intern/audaspace/intern/AUD_Mixer.h | 3 +- intern/audaspace/intern/AUD_MixerFactory.cpp | 6 +- intern/audaspace/intern/AUD_MixerFactory.h | 8 +- intern/audaspace/intern/AUD_NULLDevice.cpp | 8 +- intern/audaspace/intern/AUD_NULLDevice.h | 4 +- intern/audaspace/intern/AUD_Reference.h | 275 ------------------ .../audaspace/intern/AUD_ResampleReader.cpp | 2 +- intern/audaspace/intern/AUD_ResampleReader.h | 2 +- intern/audaspace/intern/AUD_Sequencer.cpp | 176 +++++++++++ intern/audaspace/intern/AUD_Sequencer.h | 206 +++++++++++++ .../audaspace/intern/AUD_SequencerEntry.cpp | 4 +- intern/audaspace/intern/AUD_SequencerEntry.h | 8 +- .../audaspace/intern/AUD_SequencerFactory.cpp | 109 ++----- .../audaspace/intern/AUD_SequencerFactory.h | 59 +--- .../audaspace/intern/AUD_SequencerHandle.cpp | 20 +- intern/audaspace/intern/AUD_SequencerHandle.h | 10 +- .../audaspace/intern/AUD_SequencerReader.cpp | 66 ++--- intern/audaspace/intern/AUD_SequencerReader.h | 14 +- .../audaspace/intern/AUD_SilenceFactory.cpp | 4 +- intern/audaspace/intern/AUD_SilenceFactory.h | 2 +- intern/audaspace/intern/AUD_SinusFactory.cpp | 4 +- intern/audaspace/intern/AUD_SinusFactory.h | 2 +- .../audaspace/intern/AUD_SoftwareDevice.cpp | 83 ++++-- intern/audaspace/intern/AUD_SoftwareDevice.h | 22 +- .../intern/AUD_StreamBufferFactory.cpp | 8 +- .../intern/AUD_StreamBufferFactory.h | 9 +- .../audaspace/sndfile/AUD_SndFileFactory.cpp | 8 +- intern/audaspace/sndfile/AUD_SndFileFactory.h | 6 +- .../audaspace/sndfile/AUD_SndFileReader.cpp | 2 +- intern/audaspace/sndfile/AUD_SndFileReader.h | 6 +- intern/bsp/intern/BOP_CarveInterface.cpp | 5 - intern/cycles/blender/addon/enums.py | 4 +- intern/cycles/render/tile.cpp | 2 +- .../scripts/startup/bl_ui/space_sequencer.py | 4 + release/scripts/startup/bl_ui/space_view3d.py | 1 + source/blender/blenkernel/BKE_sequencer.h | 1 + source/blender/blenkernel/intern/sequencer.c | 38 ++- source/blender/blenkernel/intern/text.c | 28 +- .../blender/bmesh/intern/bmesh_operator_api.h | 2 + source/blender/bmesh/intern/bmesh_operators.c | 14 + .../bmesh/operators/bmo_removedoubles.c | 57 ++-- .../editors/space_sequencer/sequencer_add.c | 4 +- source/blender/imbuf/intern/thumbs.c | 2 +- source/blender/makesdna/DNA_sequence_types.h | 3 + source/blender/makesrna/intern/rna_color.c | 33 +++ .../blender/makesrna/intern/rna_sequencer.c | 12 + .../makesrna/intern/rna_sequencer_api.c | 2 + .../composite/nodes/node_composite_math.c | 3 +- .../nodes/shader/nodes/node_shader_math.c | 19 +- .../nodes/shader/nodes/node_shader_script.c | 13 +- source/blender/python/generic/bgl.c | 4 +- source/blender/python/generic/idprop_py_api.c | 4 +- source/blender/python/intern/bpy.c | 5 +- source/blender/python/intern/bpy_rna.c | 4 +- source/blender/python/intern/bpy_util.h | 14 +- .../python/mathutils/mathutils_Color.c | 4 +- .../python/mathutils/mathutils_Euler.c | 4 +- .../python/mathutils/mathutils_Matrix.c | 6 +- .../python/mathutils/mathutils_Quaternion.c | 4 +- .../python/mathutils/mathutils_Vector.c | 4 +- .../bad_level_call_stubs/stubs.c | 1 + .../gameengine/BlenderRoutines/CMakeLists.txt | 1 + source/gameengine/BlenderRoutines/SConscript | 1 + source/gameengine/Converter/CMakeLists.txt | 2 +- .../Converter/KX_ConvertActuators.cpp | 8 +- source/gameengine/Converter/SConscript | 1 + source/gameengine/Ketsji/CMakeLists.txt | 1 + .../gameengine/Ketsji/KX_ObjectActuator.cpp | 2 +- source/gameengine/Ketsji/KX_SoundActuator.cpp | 72 ++--- source/gameengine/Ketsji/KX_SoundActuator.h | 8 +- source/gameengine/Ketsji/SConscript | 1 + 185 files changed, 1349 insertions(+), 1149 deletions(-) rename intern/audaspace/{intern/AUD_ReferenceHandler.cpp => FX/AUD_IDynamicIIRFilterCalculator.h} (54%) delete mode 100644 intern/audaspace/intern/AUD_Reference.h create mode 100644 intern/audaspace/intern/AUD_Sequencer.cpp create mode 100644 intern/audaspace/intern/AUD_Sequencer.h diff --git a/build_files/build_environment/prepare_release_env.sh b/build_files/build_environment/prepare_release_env.sh index 0bad1501540..b16ce784be9 100755 --- a/build_files/build_environment/prepare_release_env.sh +++ b/build_files/build_environment/prepare_release_env.sh @@ -715,7 +715,7 @@ EOF # NOTE: this sounds strange, but make sure /dev/shm/ is writable by your user, # otherwise syncronization primitives wouldn't be included into python -if [[ "`stat -c '%a' /dev/shm/`" != "777" ]]; then +if [[ "\`stat -c '%a' /dev/shm/\`" != "777" ]]; then echo "Error checking syncronization primitives" exit 1 fi diff --git a/build_files/buildbot/config/user-config-glibc27-i686.py b/build_files/buildbot/config/user-config-glibc27-i686.py index 04b83253678..c1e72662f89 100644 --- a/build_files/buildbot/config/user-config-glibc27-i686.py +++ b/build_files/buildbot/config/user-config-glibc27-i686.py @@ -3,8 +3,8 @@ BF_INSTALLDIR = '../blender-install/linux-glibc27-i686' BF_NUMJOBS = 2 # Python configuration -BF_PYTHON_VERSION = '3.2' -BF_PYTHON_ABI_FLAGS = 'mu' +BF_PYTHON_VERSION = '3.3' +BF_PYTHON_ABI_FLAGS = 'm' BF_PYTHON = '/opt/python3' WITH_BF_STATICPYTHON = True diff --git a/build_files/buildbot/config/user-config-glibc27-x86_64.py b/build_files/buildbot/config/user-config-glibc27-x86_64.py index 070e62b2f20..4380b404ac3 100644 --- a/build_files/buildbot/config/user-config-glibc27-x86_64.py +++ b/build_files/buildbot/config/user-config-glibc27-x86_64.py @@ -3,8 +3,8 @@ BF_INSTALLDIR = '../blender-install/linux-glibc27-x86_64' BF_NUMJOBS = 2 # Python configuration -BF_PYTHON_VERSION = '3.2' -BF_PYTHON_ABI_FLAGS = 'mu' +BF_PYTHON_VERSION = '3.3' +BF_PYTHON_ABI_FLAGS = 'm' BF_PYTHON = '/opt/python3' WITH_BF_STATICPYTHON = True diff --git a/build_files/buildbot/config/user-config-player-glibc211-i686.py b/build_files/buildbot/config/user-config-player-glibc211-i686.py index 3ac061d934f..1b387445390 100644 --- a/build_files/buildbot/config/user-config-player-glibc211-i686.py +++ b/build_files/buildbot/config/user-config-player-glibc211-i686.py @@ -93,6 +93,14 @@ BF_OCIO_INC = '${BF_OCIO}/include' BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a' BF_OCIO_LIBPATH = '${BF_OCIO}/lib' +WITH_BF_BOOST = True +WITH_BF_STATICBOOST = True +BF_BOOST = '/opt/lib/boost' +BF_BOOST_INC = '${BF_BOOST}/include' +BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \ + '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' +BF_BOOST_LIBPATH = '${BF_BOOST}/lib' + # JACK WITH_BF_JACK = True WITH_BF_STATICJACK = True diff --git a/build_files/buildbot/config/user-config-player-glibc211-x86_64.py b/build_files/buildbot/config/user-config-player-glibc211-x86_64.py index 08d277edb7b..83540150c33 100644 --- a/build_files/buildbot/config/user-config-player-glibc211-x86_64.py +++ b/build_files/buildbot/config/user-config-player-glibc211-x86_64.py @@ -93,6 +93,14 @@ BF_OCIO_INC = '${BF_OCIO}/include' BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a' BF_OCIO_LIBPATH = '${BF_OCIO}/lib' +WITH_BF_BOOST = True +WITH_BF_STATICBOOST = True +BF_BOOST = '/opt/lib/boost' +BF_BOOST_INC = '${BF_BOOST}/include' +BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \ + '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' +BF_BOOST_LIBPATH = '${BF_BOOST}/lib' + # JACK WITH_BF_JACK = True WITH_BF_STATICJACK = True diff --git a/build_files/buildbot/config/user-config-player-glibc27-i686.py b/build_files/buildbot/config/user-config-player-glibc27-i686.py index e23fc70262f..e200e0fccf4 100644 --- a/build_files/buildbot/config/user-config-player-glibc27-i686.py +++ b/build_files/buildbot/config/user-config-player-glibc27-i686.py @@ -3,8 +3,8 @@ BF_INSTALLDIR = '../blender-install/linux-glibc27-i686' BF_NUMJOBS = 2 # Python configuration -BF_PYTHON_VERSION = '3.2' -BF_PYTHON_ABI_FLAGS = 'mu' +BF_PYTHON_VERSION = '3.3' +BF_PYTHON_ABI_FLAGS = 'm' BF_PYTHON = '/opt/python3' WITH_BF_STATICPYTHON = True @@ -90,6 +90,13 @@ BF_OCIO_INC = '${BF_OCIO}/include' BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a' BF_OCIO_LIBPATH = '${BF_OCIO}/lib' +WITH_BF_BOOST = True +WITH_BF_STATICBOOST = True +BF_BOOST = '/opt/boost' +BF_BOOST_INC = '${BF_BOOST}/include' +BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' +BF_BOOST_LIBPATH = '${BF_BOOST}/lib' + # JACK WITH_BF_JACK = True diff --git a/build_files/buildbot/config/user-config-player-glibc27-x86_64.py b/build_files/buildbot/config/user-config-player-glibc27-x86_64.py index 3c09603473e..2ee177960cd 100644 --- a/build_files/buildbot/config/user-config-player-glibc27-x86_64.py +++ b/build_files/buildbot/config/user-config-player-glibc27-x86_64.py @@ -3,8 +3,8 @@ BF_INSTALLDIR = '../blender-install/linux-glibc27-x86_64' BF_NUMJOBS = 2 # Python configuration -BF_PYTHON_VERSION = '3.2' -BF_PYTHON_ABI_FLAGS = 'mu' +BF_PYTHON_VERSION = '3.3' +BF_PYTHON_ABI_FLAGS = 'm' BF_PYTHON = '/opt/python3' WITH_BF_STATICPYTHON = True @@ -90,6 +90,13 @@ BF_OCIO_INC = '${BF_OCIO}/include' BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a' BF_OCIO_LIBPATH = '${BF_OCIO}/lib' +WITH_BF_BOOST = True +WITH_BF_STATICBOOST = True +BF_BOOST = '/opt/boost' +BF_BOOST_INC = '${BF_BOOST}/include' +BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' +BF_BOOST_LIBPATH = '${BF_BOOST}/lib' + # JACK WITH_BF_JACK = True diff --git a/build_files/cmake/Modules/FindPythonLibsUnix.cmake b/build_files/cmake/Modules/FindPythonLibsUnix.cmake index 448e587e224..34394864861 100644 --- a/build_files/cmake/Modules/FindPythonLibsUnix.cmake +++ b/build_files/cmake/Modules/FindPythonLibsUnix.cmake @@ -34,7 +34,7 @@ IF(NOT PYTHON_ROOT_DIR AND NOT $ENV{PYTHON_ROOT_DIR} STREQUAL "") SET(PYTHON_ROOT_DIR $ENV{PYTHON_ROOT_DIR}) ENDIF() -SET(PYTHON_VERSION 3.2 CACHE STRING "Python Version (major and minor only)") +SET(PYTHON_VERSION 3.3 CACHE STRING "Python Version (major and minor only)") MARK_AS_ADVANCED(PYTHON_VERSION) diff --git a/build_files/scons/config/Modules/FindPython.py b/build_files/scons/config/Modules/FindPython.py index 969d9db92a4..c93a10351d5 100644 --- a/build_files/scons/config/Modules/FindPython.py +++ b/build_files/scons/config/Modules/FindPython.py @@ -5,7 +5,7 @@ def FindPython(): python = "/usr" abi_flags = "m" # Most common for linux distros - version = "3.2" + version = "3.3" # Determine ABI flags used on this system include = os.path.join(python, "include") diff --git a/extern/carve/lib/intersect_face_division.cpp b/extern/carve/lib/intersect_face_division.cpp index 08550c021ad..c74b52dd557 100644 --- a/extern/carve/lib/intersect_face_division.cpp +++ b/extern/carve/lib/intersect_face_division.cpp @@ -1106,7 +1106,8 @@ namespace { } // copy up to the end of the path. - std::copy(base_loop.begin() + pos, base_loop.begin() + e1_1, std::back_inserter(out)); + if (pos < e1_1) + std::copy(base_loop.begin() + pos, base_loop.begin() + e1_1, std::back_inserter(out)); CARVE_ASSERT(base_loop[e1_1] == p1.back()); std::copy(p1.rbegin(), p1.rend() - 1, std::back_inserter(out)); diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt index 1671194653a..1617e520ac7 100644 --- a/intern/audaspace/CMakeLists.txt +++ b/intern/audaspace/CMakeLists.txt @@ -28,6 +28,7 @@ set(INC set(INC_SYS ${PTHREADS_INCLUDE_DIRS} + ${BOOST_INCLUDE_DIR} ) set(SRC @@ -115,11 +116,11 @@ set(SRC intern/AUD_PyInit.h intern/AUD_ReadDevice.cpp intern/AUD_ReadDevice.h - intern/AUD_Reference.h - intern/AUD_ReferenceHandler.cpp intern/AUD_ResampleFactory.h intern/AUD_ResampleReader.cpp intern/AUD_ResampleReader.h + intern/AUD_Sequencer.cpp + intern/AUD_Sequencer.h intern/AUD_SequencerEntry.cpp intern/AUD_SequencerEntry.h intern/AUD_SequencerFactory.cpp @@ -150,6 +151,7 @@ set(SRC FX/AUD_DelayReader.h FX/AUD_DoubleFactory.h FX/AUD_DoubleReader.h + FX/AUD_IDynamicIIRFilterCalculator.h FX/AUD_DynamicIIRFilterFactory.h FX/AUD_DynamicIIRFilterReader.h FX/AUD_EffectFactory.h diff --git a/intern/audaspace/FX/AUD_AccumulatorFactory.cpp b/intern/audaspace/FX/AUD_AccumulatorFactory.cpp index 1862b9ab79d..00d3a9f2395 100644 --- a/intern/audaspace/FX/AUD_AccumulatorFactory.cpp +++ b/intern/audaspace/FX/AUD_AccumulatorFactory.cpp @@ -50,15 +50,15 @@ sample_t AUD_AccumulatorFactory::accumulatorFilter(AUD_CallbackIIRFilterReader* return out; } -AUD_AccumulatorFactory::AUD_AccumulatorFactory(AUD_Reference factory, +AUD_AccumulatorFactory::AUD_AccumulatorFactory(boost::shared_ptr factory, bool additive) : AUD_EffectFactory(factory), m_additive(additive) { } -AUD_Reference AUD_AccumulatorFactory::createReader() +boost::shared_ptr AUD_AccumulatorFactory::createReader() { - return new AUD_CallbackIIRFilterReader(getReader(), 2, 2, - m_additive ? accumulatorFilterAdditive : accumulatorFilter); + return boost::shared_ptr(new AUD_CallbackIIRFilterReader(getReader(), 2, 2, + m_additive ? accumulatorFilterAdditive : accumulatorFilter)); } diff --git a/intern/audaspace/FX/AUD_AccumulatorFactory.h b/intern/audaspace/FX/AUD_AccumulatorFactory.h index ac73c5aa6ae..9087218a5f9 100644 --- a/intern/audaspace/FX/AUD_AccumulatorFactory.h +++ b/intern/audaspace/FX/AUD_AccumulatorFactory.h @@ -58,9 +58,9 @@ public: * \param factory The input factory. * \param additive Whether the accumulator is additive. */ - AUD_AccumulatorFactory(AUD_Reference factory, bool additive = false); + AUD_AccumulatorFactory(boost::shared_ptr factory, bool additive = false); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); static sample_t accumulatorFilterAdditive(AUD_CallbackIIRFilterReader* reader, void* useless); static sample_t accumulatorFilter(AUD_CallbackIIRFilterReader* reader, void* useless); diff --git a/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp b/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp index fa9e8746b2b..eadfc525f96 100644 --- a/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp +++ b/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp @@ -33,7 +33,7 @@ #define CC m_specs.channels + m_channel -AUD_BaseIIRFilterReader::AUD_BaseIIRFilterReader(AUD_Reference reader, int in, +AUD_BaseIIRFilterReader::AUD_BaseIIRFilterReader(boost::shared_ptr reader, int in, int out) : AUD_EffectReader(reader), m_specs(reader->getSpecs()), diff --git a/intern/audaspace/FX/AUD_BaseIIRFilterReader.h b/intern/audaspace/FX/AUD_BaseIIRFilterReader.h index 43970c96a42..fe0a8efce64 100644 --- a/intern/audaspace/FX/AUD_BaseIIRFilterReader.h +++ b/intern/audaspace/FX/AUD_BaseIIRFilterReader.h @@ -90,7 +90,7 @@ protected: * \param in The count of past input samples needed. * \param out The count of past output samples needed. */ - AUD_BaseIIRFilterReader(AUD_Reference reader, int in, int out); + AUD_BaseIIRFilterReader(boost::shared_ptr reader, int in, int out); void setLengths(int in, int out); diff --git a/intern/audaspace/FX/AUD_ButterworthFactory.cpp b/intern/audaspace/FX/AUD_ButterworthFactory.cpp index af1a5af97df..97d85c8122f 100644 --- a/intern/audaspace/FX/AUD_ButterworthFactory.cpp +++ b/intern/audaspace/FX/AUD_ButterworthFactory.cpp @@ -39,7 +39,7 @@ #define BWPB41 0.76536686473 #define BWPB42 1.84775906502 -AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_Reference factory, +AUD_ButterworthFactory::AUD_ButterworthFactory(boost::shared_ptr factory, float frequency) : AUD_DynamicIIRFilterFactory(factory), m_frequency(frequency) diff --git a/intern/audaspace/FX/AUD_ButterworthFactory.h b/intern/audaspace/FX/AUD_ButterworthFactory.h index dc8b4d92775..e796f76aa29 100644 --- a/intern/audaspace/FX/AUD_ButterworthFactory.h +++ b/intern/audaspace/FX/AUD_ButterworthFactory.h @@ -53,7 +53,7 @@ public: * \param factory The input factory. * \param frequency The cutoff frequency. */ - AUD_ButterworthFactory(AUD_Reference factory, float frequency); + AUD_ButterworthFactory(boost::shared_ptr factory, float frequency); virtual void recalculateCoefficients(AUD_SampleRate rate, std::vector& b, diff --git a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp index 1a5c99adfb9..b5157d47666 100644 --- a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp +++ b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp @@ -29,7 +29,7 @@ #include "AUD_CallbackIIRFilterReader.h" -AUD_CallbackIIRFilterReader::AUD_CallbackIIRFilterReader(AUD_Reference reader, +AUD_CallbackIIRFilterReader::AUD_CallbackIIRFilterReader(boost::shared_ptr reader, int in, int out, doFilterIIR doFilter, endFilterIIR endFilter, diff --git a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h index 7ced73844c9..d9df65f03eb 100644 --- a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h +++ b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h @@ -74,7 +74,7 @@ public: * \param endFilter The finishing callback. * \param data Data pointer for the callbacks. */ - AUD_CallbackIIRFilterReader(AUD_Reference reader, int in, int out, + AUD_CallbackIIRFilterReader(boost::shared_ptr reader, int in, int out, doFilterIIR doFilter, endFilterIIR endFilter = 0, void* data = 0); diff --git a/intern/audaspace/FX/AUD_DelayFactory.cpp b/intern/audaspace/FX/AUD_DelayFactory.cpp index a4606597933..3e5a7cfd2f8 100644 --- a/intern/audaspace/FX/AUD_DelayFactory.cpp +++ b/intern/audaspace/FX/AUD_DelayFactory.cpp @@ -31,7 +31,7 @@ #include "AUD_DelayReader.h" #include "AUD_Space.h" -AUD_DelayFactory::AUD_DelayFactory(AUD_Reference factory, float delay) : +AUD_DelayFactory::AUD_DelayFactory(boost::shared_ptr factory, float delay) : AUD_EffectFactory(factory), m_delay(delay) { @@ -42,7 +42,7 @@ float AUD_DelayFactory::getDelay() const return m_delay; } -AUD_Reference AUD_DelayFactory::createReader() +boost::shared_ptr AUD_DelayFactory::createReader() { - return new AUD_DelayReader(getReader(), m_delay); + return boost::shared_ptr(new AUD_DelayReader(getReader(), m_delay)); } diff --git a/intern/audaspace/FX/AUD_DelayFactory.h b/intern/audaspace/FX/AUD_DelayFactory.h index 26855a05d70..8cfb2be9ac8 100644 --- a/intern/audaspace/FX/AUD_DelayFactory.h +++ b/intern/audaspace/FX/AUD_DelayFactory.h @@ -53,14 +53,14 @@ public: * \param factory The input factory. * \param delay The desired delay in seconds. */ - AUD_DelayFactory(AUD_Reference factory, float delay = 0); + AUD_DelayFactory(boost::shared_ptr factory, float delay = 0); /** * Returns the delay in seconds. */ float getDelay() const; - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_DELAYFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_DelayReader.cpp b/intern/audaspace/FX/AUD_DelayReader.cpp index 0e9833cd07f..050508f28da 100644 --- a/intern/audaspace/FX/AUD_DelayReader.cpp +++ b/intern/audaspace/FX/AUD_DelayReader.cpp @@ -31,7 +31,7 @@ #include -AUD_DelayReader::AUD_DelayReader(AUD_Reference reader, float delay) : +AUD_DelayReader::AUD_DelayReader(boost::shared_ptr reader, float delay) : AUD_EffectReader(reader), m_delay(int((AUD_SampleRate)delay * reader->getSpecs().rate)), m_remdelay(int((AUD_SampleRate)delay * reader->getSpecs().rate)) diff --git a/intern/audaspace/FX/AUD_DelayReader.h b/intern/audaspace/FX/AUD_DelayReader.h index 9d9b6619470..d4388e3befc 100644 --- a/intern/audaspace/FX/AUD_DelayReader.h +++ b/intern/audaspace/FX/AUD_DelayReader.h @@ -59,7 +59,7 @@ public: * \param reader The reader to read from. * \param delay The delay in seconds. */ - AUD_DelayReader(AUD_Reference reader, float delay); + AUD_DelayReader(boost::shared_ptr reader, float delay); virtual void seek(int position); virtual int getLength() const; diff --git a/intern/audaspace/FX/AUD_DoubleFactory.cpp b/intern/audaspace/FX/AUD_DoubleFactory.cpp index ab0111f8955..21bcbc2f649 100644 --- a/intern/audaspace/FX/AUD_DoubleFactory.cpp +++ b/intern/audaspace/FX/AUD_DoubleFactory.cpp @@ -30,15 +30,15 @@ #include "AUD_DoubleFactory.h" #include "AUD_DoubleReader.h" -AUD_DoubleFactory::AUD_DoubleFactory(AUD_Reference factory1, AUD_Reference factory2) : +AUD_DoubleFactory::AUD_DoubleFactory(boost::shared_ptr factory1, boost::shared_ptr factory2) : m_factory1(factory1), m_factory2(factory2) { } -AUD_Reference AUD_DoubleFactory::createReader() +boost::shared_ptr AUD_DoubleFactory::createReader() { - AUD_Reference reader1 = m_factory1->createReader(); - AUD_Reference reader2 = m_factory2->createReader(); + boost::shared_ptr reader1 = m_factory1->createReader(); + boost::shared_ptr reader2 = m_factory2->createReader(); - return new AUD_DoubleReader(reader1, reader2); + return boost::shared_ptr(new AUD_DoubleReader(reader1, reader2)); } diff --git a/intern/audaspace/FX/AUD_DoubleFactory.h b/intern/audaspace/FX/AUD_DoubleFactory.h index e4d8fbfde8f..4a02cc7bcdb 100644 --- a/intern/audaspace/FX/AUD_DoubleFactory.h +++ b/intern/audaspace/FX/AUD_DoubleFactory.h @@ -41,12 +41,12 @@ private: /** * First played factory. */ - AUD_Reference m_factory1; + boost::shared_ptr m_factory1; /** * Second played factory. */ - AUD_Reference m_factory2; + boost::shared_ptr m_factory2; // hide copy constructor and operator= AUD_DoubleFactory(const AUD_DoubleFactory&); @@ -58,9 +58,9 @@ public: * \param factory1 The first input factory. * \param factory2 The second input factory. */ - AUD_DoubleFactory(AUD_Reference factory1, AUD_Reference factory2); + AUD_DoubleFactory(boost::shared_ptr factory1, boost::shared_ptr factory2); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_DOUBLEFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_DoubleReader.cpp b/intern/audaspace/FX/AUD_DoubleReader.cpp index 2b28bc7d679..ee18914e93f 100644 --- a/intern/audaspace/FX/AUD_DoubleReader.cpp +++ b/intern/audaspace/FX/AUD_DoubleReader.cpp @@ -31,8 +31,8 @@ #include -AUD_DoubleReader::AUD_DoubleReader(AUD_Reference reader1, - AUD_Reference reader2) : +AUD_DoubleReader::AUD_DoubleReader(boost::shared_ptr reader1, + boost::shared_ptr reader2) : m_reader1(reader1), m_reader2(reader2), m_finished1(false) { AUD_Specs s1, s2; diff --git a/intern/audaspace/FX/AUD_DoubleReader.h b/intern/audaspace/FX/AUD_DoubleReader.h index 1489f4eb184..5d2f65f1a90 100644 --- a/intern/audaspace/FX/AUD_DoubleReader.h +++ b/intern/audaspace/FX/AUD_DoubleReader.h @@ -32,7 +32,8 @@ #include "AUD_IReader.h" #include "AUD_Buffer.h" -#include "AUD_Reference.h" + +#include /** * This reader plays two readers sequently. @@ -43,12 +44,12 @@ private: /** * The first reader. */ - AUD_Reference m_reader1; + boost::shared_ptr m_reader1; /** * The second reader. */ - AUD_Reference m_reader2; + boost::shared_ptr m_reader2; /** * Whether we've reached the end of the first reader. @@ -65,7 +66,7 @@ public: * \param reader1 The first reader to read from. * \param reader2 The second reader to read from. */ - AUD_DoubleReader(AUD_Reference reader1, AUD_Reference reader2); + AUD_DoubleReader(boost::shared_ptr reader1, boost::shared_ptr reader2); /** * Destroys the reader. diff --git a/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp b/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp index 3d6beb6c554..e8ea4323b2e 100644 --- a/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp +++ b/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp @@ -29,12 +29,14 @@ #include "AUD_DynamicIIRFilterFactory.h" #include "AUD_DynamicIIRFilterReader.h" -AUD_DynamicIIRFilterFactory::AUD_DynamicIIRFilterFactory(AUD_Reference factory) : + +AUD_DynamicIIRFilterFactory::AUD_DynamicIIRFilterFactory(boost::shared_ptr factory) : AUD_EffectFactory(factory) { } -AUD_Reference AUD_DynamicIIRFilterFactory::createReader() +boost::shared_ptr AUD_DynamicIIRFilterFactory::createReader() { - return new AUD_DynamicIIRFilterReader(getReader(), this); + return boost::shared_ptr(new AUD_DynamicIIRFilterReader(getReader(), m_calculator)); } + diff --git a/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h b/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h index 5b297db2d56..f36a37f44b4 100644 --- a/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h +++ b/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h @@ -30,6 +30,7 @@ #define __AUD_DYNAMICIIRFILTERFACTORY_H__ #include "AUD_EffectFactory.h" +#include "AUD_IDynamicIIRFilterCalculator.h" #include /** @@ -40,24 +41,17 @@ */ class AUD_DynamicIIRFilterFactory : public AUD_EffectFactory { +protected: + boost::shared_ptr m_calculator; + public: /** * Creates a new Dynmic IIR filter factory. * \param factory The input factory. */ - AUD_DynamicIIRFilterFactory(AUD_Reference factory); + AUD_DynamicIIRFilterFactory(boost::shared_ptr factory); - virtual AUD_Reference createReader(); - - /** - * Recalculates the filter coefficients. - * \param rate The sample rate of the audio data. - * \param[out] b The input filter coefficients. - * \param[out] a The output filter coefficients. - */ - virtual void recalculateCoefficients(AUD_SampleRate rate, - std::vector& b, - std::vector& a)=0; + virtual boost::shared_ptr createReader(); }; #endif // __AUD_DYNAMICIIRFILTERFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp b/intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp index 24332ebfc1a..52aaf2311c0 100644 --- a/intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp +++ b/intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp @@ -28,10 +28,10 @@ #include "AUD_DynamicIIRFilterReader.h" -AUD_DynamicIIRFilterReader::AUD_DynamicIIRFilterReader(AUD_Reference reader, - AUD_Reference factory) : +AUD_DynamicIIRFilterReader::AUD_DynamicIIRFilterReader(boost::shared_ptr reader, + boost::shared_ptr calculator) : AUD_IIRFilterReader(reader, std::vector(), std::vector()), - m_factory(factory) + m_calculator(calculator) { sampleRateChanged(reader->getSpecs().rate); } @@ -39,6 +39,6 @@ AUD_DynamicIIRFilterReader::AUD_DynamicIIRFilterReader(AUD_Reference a, b; - m_factory->recalculateCoefficients(rate, b, a); + m_calculator->recalculateCoefficients(rate, b, a); setCoefficients(b, a); } diff --git a/intern/audaspace/FX/AUD_DynamicIIRFilterReader.h b/intern/audaspace/FX/AUD_DynamicIIRFilterReader.h index 8a53c15b18f..0b68578bc53 100644 --- a/intern/audaspace/FX/AUD_DynamicIIRFilterReader.h +++ b/intern/audaspace/FX/AUD_DynamicIIRFilterReader.h @@ -30,7 +30,7 @@ #define __AUD_DYNAMICIIRFILTERREADER_H__ #include "AUD_IIRFilterReader.h" -#include "AUD_DynamicIIRFilterFactory.h" +#include "AUD_IDynamicIIRFilterCalculator.h" /** * This class is for dynamic infinite impulse response filters with simple @@ -42,11 +42,11 @@ private: /** * The factory for dynamically recalculating filter coefficients. */ - AUD_Reference m_factory; + boost::shared_ptr m_calculator; public: - AUD_DynamicIIRFilterReader(AUD_Reference reader, - AUD_Reference factory); + AUD_DynamicIIRFilterReader(boost::shared_ptr reader, + boost::shared_ptr calculator); virtual void sampleRateChanged(AUD_SampleRate rate); }; diff --git a/intern/audaspace/FX/AUD_EffectFactory.cpp b/intern/audaspace/FX/AUD_EffectFactory.cpp index d35f8affec8..6018ed561ca 100644 --- a/intern/audaspace/FX/AUD_EffectFactory.cpp +++ b/intern/audaspace/FX/AUD_EffectFactory.cpp @@ -30,7 +30,7 @@ #include "AUD_EffectFactory.h" #include "AUD_IReader.h" -AUD_EffectFactory::AUD_EffectFactory(AUD_Reference factory) +AUD_EffectFactory::AUD_EffectFactory(boost::shared_ptr factory) { m_factory = factory; } @@ -39,7 +39,7 @@ AUD_EffectFactory::~AUD_EffectFactory() { } -AUD_Reference AUD_EffectFactory::getFactory() const +boost::shared_ptr AUD_EffectFactory::getFactory() const { return m_factory; } diff --git a/intern/audaspace/FX/AUD_EffectFactory.h b/intern/audaspace/FX/AUD_EffectFactory.h index c8d26a1daa7..d09872638be 100644 --- a/intern/audaspace/FX/AUD_EffectFactory.h +++ b/intern/audaspace/FX/AUD_EffectFactory.h @@ -47,7 +47,7 @@ protected: /** * If there is no reader it is created out of this factory. */ - AUD_Reference m_factory; + boost::shared_ptr m_factory; /** * Returns the reader created out of the factory. @@ -55,7 +55,7 @@ protected: * classes. * \return The reader created out of the factory. */ - inline AUD_Reference getReader() const + inline boost::shared_ptr getReader() const { return m_factory->createReader(); } @@ -65,7 +65,7 @@ public: * Creates a new factory. * \param factory The input factory. */ - AUD_EffectFactory(AUD_Reference factory); + AUD_EffectFactory(boost::shared_ptr factory); /** * Destroys the factory. @@ -76,7 +76,7 @@ public: * Returns the saved factory. * \return The factory or NULL if there has no factory been saved. */ - AUD_Reference getFactory() const; + boost::shared_ptr getFactory() const; }; #endif //__AUD_EFFECTFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_EffectReader.cpp b/intern/audaspace/FX/AUD_EffectReader.cpp index 6c08549e744..b3e80bef03b 100644 --- a/intern/audaspace/FX/AUD_EffectReader.cpp +++ b/intern/audaspace/FX/AUD_EffectReader.cpp @@ -29,7 +29,7 @@ #include "AUD_EffectReader.h" -AUD_EffectReader::AUD_EffectReader(AUD_Reference reader) +AUD_EffectReader::AUD_EffectReader(boost::shared_ptr reader) { m_reader = reader; } diff --git a/intern/audaspace/FX/AUD_EffectReader.h b/intern/audaspace/FX/AUD_EffectReader.h index b089ec9a318..2745c12afaf 100644 --- a/intern/audaspace/FX/AUD_EffectReader.h +++ b/intern/audaspace/FX/AUD_EffectReader.h @@ -31,7 +31,8 @@ #define __AUD_EFFECTREADER_H__ #include "AUD_IReader.h" -#include "AUD_Reference.h" + +#include /** * This reader is a base class for all effect readers that take one other reader @@ -48,14 +49,14 @@ protected: /** * The reader to read from. */ - AUD_Reference m_reader; + boost::shared_ptr m_reader; public: /** * Creates a new effect reader. * \param reader The reader to read from. */ - AUD_EffectReader(AUD_Reference reader); + AUD_EffectReader(boost::shared_ptr reader); /** * Destroys the reader. diff --git a/intern/audaspace/FX/AUD_EnvelopeFactory.cpp b/intern/audaspace/FX/AUD_EnvelopeFactory.cpp index c7176662659..1e5737557c1 100644 --- a/intern/audaspace/FX/AUD_EnvelopeFactory.cpp +++ b/intern/audaspace/FX/AUD_EnvelopeFactory.cpp @@ -54,7 +54,7 @@ void AUD_EnvelopeFactory::endEnvelopeFilter(EnvelopeParameters* param) delete param; } -AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_Reference factory, float attack, +AUD_EnvelopeFactory::AUD_EnvelopeFactory(boost::shared_ptr factory, float attack, float release, float threshold, float arthreshold) : AUD_EffectFactory(factory), @@ -65,9 +65,9 @@ AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_Reference factory, fl { } -AUD_Reference AUD_EnvelopeFactory::createReader() +boost::shared_ptr AUD_EnvelopeFactory::createReader() { - AUD_Reference reader = getReader(); + boost::shared_ptr reader = getReader(); EnvelopeParameters* param = new EnvelopeParameters(); param->arthreshold = m_arthreshold; @@ -75,8 +75,8 @@ AUD_Reference AUD_EnvelopeFactory::createReader() param->release = pow(m_arthreshold, 1.0f/(static_cast(reader->getSpecs().rate) * m_release)); param->threshold = m_threshold; - return new AUD_CallbackIIRFilterReader(reader, 1, 2, + return boost::shared_ptr(new AUD_CallbackIIRFilterReader(reader, 1, 2, (doFilterIIR) envelopeFilter, (endFilterIIR) endEnvelopeFilter, - param); + param)); } diff --git a/intern/audaspace/FX/AUD_EnvelopeFactory.h b/intern/audaspace/FX/AUD_EnvelopeFactory.h index c8f3dc37cd2..656212c8cac 100644 --- a/intern/audaspace/FX/AUD_EnvelopeFactory.h +++ b/intern/audaspace/FX/AUD_EnvelopeFactory.h @@ -73,10 +73,10 @@ public: * \param threshold The threshold value. * \param arthreshold The attack/release threshold value. */ - AUD_EnvelopeFactory(AUD_Reference factory, float attack, float release, + AUD_EnvelopeFactory(boost::shared_ptr factory, float attack, float release, float threshold, float arthreshold); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); static sample_t envelopeFilter(AUD_CallbackIIRFilterReader* reader, EnvelopeParameters* param); static void endEnvelopeFilter(EnvelopeParameters* param); diff --git a/intern/audaspace/FX/AUD_FaderFactory.cpp b/intern/audaspace/FX/AUD_FaderFactory.cpp index ec119ef9388..b34d2134385 100644 --- a/intern/audaspace/FX/AUD_FaderFactory.cpp +++ b/intern/audaspace/FX/AUD_FaderFactory.cpp @@ -30,7 +30,7 @@ #include "AUD_FaderFactory.h" #include "AUD_FaderReader.h" -AUD_FaderFactory::AUD_FaderFactory(AUD_Reference factory, AUD_FadeType type, +AUD_FaderFactory::AUD_FaderFactory(boost::shared_ptr factory, AUD_FadeType type, float start, float length) : AUD_EffectFactory(factory), m_type(type), @@ -54,7 +54,7 @@ float AUD_FaderFactory::getLength() const return m_length; } -AUD_Reference AUD_FaderFactory::createReader() +boost::shared_ptr AUD_FaderFactory::createReader() { - return new AUD_FaderReader(getReader(), m_type, m_start, m_length); + return boost::shared_ptr(new AUD_FaderReader(getReader(), m_type, m_start, m_length)); } diff --git a/intern/audaspace/FX/AUD_FaderFactory.h b/intern/audaspace/FX/AUD_FaderFactory.h index 82eaf2fae9f..f9ad88a751d 100644 --- a/intern/audaspace/FX/AUD_FaderFactory.h +++ b/intern/audaspace/FX/AUD_FaderFactory.h @@ -67,7 +67,7 @@ public: * \param start The time where fading should start in seconds. * \param length How long fading should last in seconds. */ - AUD_FaderFactory(AUD_Reference factory, + AUD_FaderFactory(boost::shared_ptr factory, AUD_FadeType type = AUD_FADE_IN, float start = 0.0f, float length = 1.0f); @@ -86,7 +86,7 @@ public: */ float getLength() const; - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_FADERFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_FaderReader.cpp b/intern/audaspace/FX/AUD_FaderReader.cpp index 4ece91ca899..e09072054cb 100644 --- a/intern/audaspace/FX/AUD_FaderReader.cpp +++ b/intern/audaspace/FX/AUD_FaderReader.cpp @@ -31,7 +31,7 @@ #include -AUD_FaderReader::AUD_FaderReader(AUD_Reference reader, AUD_FadeType type, +AUD_FaderReader::AUD_FaderReader(boost::shared_ptr reader, AUD_FadeType type, float start,float length) : AUD_EffectReader(reader), m_type(type), diff --git a/intern/audaspace/FX/AUD_FaderReader.h b/intern/audaspace/FX/AUD_FaderReader.h index 788e8539228..a49960b30fb 100644 --- a/intern/audaspace/FX/AUD_FaderReader.h +++ b/intern/audaspace/FX/AUD_FaderReader.h @@ -67,7 +67,7 @@ public: * \param start The time where fading should start in seconds. * \param length How long fading should last in seconds. */ - AUD_FaderReader(AUD_Reference reader, AUD_FadeType type, + AUD_FaderReader(boost::shared_ptr reader, AUD_FadeType type, float start,float length); virtual void read(int& length, bool& eos, sample_t* buffer); diff --git a/intern/audaspace/FX/AUD_HighpassFactory.cpp b/intern/audaspace/FX/AUD_HighpassFactory.cpp index b56be8942ff..ba5297d21ed 100644 --- a/intern/audaspace/FX/AUD_HighpassFactory.cpp +++ b/intern/audaspace/FX/AUD_HighpassFactory.cpp @@ -36,7 +36,7 @@ #define M_PI 3.14159265358979323846 #endif -AUD_HighpassFactory::AUD_HighpassFactory(AUD_Reference factory, float frequency, +AUD_HighpassFactory::AUD_HighpassFactory(boost::shared_ptr factory, float frequency, float Q) : AUD_DynamicIIRFilterFactory(factory), m_frequency(frequency), diff --git a/intern/audaspace/FX/AUD_HighpassFactory.h b/intern/audaspace/FX/AUD_HighpassFactory.h index 66aa8091234..ed7e9db44a4 100644 --- a/intern/audaspace/FX/AUD_HighpassFactory.h +++ b/intern/audaspace/FX/AUD_HighpassFactory.h @@ -59,7 +59,7 @@ public: * \param frequency The cutoff frequency. * \param Q The Q factor. */ - AUD_HighpassFactory(AUD_Reference factory, float frequency, float Q = 1.0f); + AUD_HighpassFactory(boost::shared_ptr factory, float frequency, float Q = 1.0f); virtual void recalculateCoefficients(AUD_SampleRate rate, std::vector &b, std::vector &a); }; diff --git a/intern/audaspace/intern/AUD_ReferenceHandler.cpp b/intern/audaspace/FX/AUD_IDynamicIIRFilterCalculator.h similarity index 54% rename from intern/audaspace/intern/AUD_ReferenceHandler.cpp rename to intern/audaspace/FX/AUD_IDynamicIIRFilterCalculator.h index 6aa4f87ea96..77d83360255 100644 --- a/intern/audaspace/intern/AUD_ReferenceHandler.cpp +++ b/intern/audaspace/FX/AUD_IDynamicIIRFilterCalculator.h @@ -22,31 +22,31 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file audaspace/intern/AUD_ReferenceHandler.cpp - * \ingroup audaspaceintern +/** \file audaspace/FX/AUD_IDynamicIIRFilterCalculator.h + * \ingroup audfx */ -#include "AUD_Reference.h" +#ifndef AUD_IDYNAMICIIRFILTERCALCULATOR_H +#define AUD_IDYNAMICIIRFILTERCALCULATOR_H -std::map AUD_ReferenceHandler::m_references; -pthread_mutex_t AUD_ReferenceHandler::m_mutex; -bool AUD_ReferenceHandler::m_mutex_initialised = false; +#include -pthread_mutex_t *AUD_ReferenceHandler::getMutex() +/** + * This interface calculates dynamic filter coefficients which depend on the + * sampling rate for AUD_DynamicIIRFilterReaders. + */ +class AUD_IDynamicIIRFilterCalculator { - if(!m_mutex_initialised) - { - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - - pthread_mutex_init(&m_mutex, &attr); - - pthread_mutexattr_destroy(&attr); - - m_mutex_initialised = true; - } - - return &m_mutex; -} +public: + /** + * Recalculates the filter coefficients. + * \param rate The sample rate of the audio data. + * \param[out] b The input filter coefficients. + * \param[out] a The output filter coefficients. + */ + virtual void recalculateCoefficients(AUD_SampleRate rate, + std::vector& b, + std::vector& a)=0; +}; +#endif // AUD_IDYNAMICIIRFILTERCALCULATOR_H diff --git a/intern/audaspace/FX/AUD_IIRFilterFactory.cpp b/intern/audaspace/FX/AUD_IIRFilterFactory.cpp index 807b0ef4899..c4f94a2dc27 100644 --- a/intern/audaspace/FX/AUD_IIRFilterFactory.cpp +++ b/intern/audaspace/FX/AUD_IIRFilterFactory.cpp @@ -30,14 +30,14 @@ #include "AUD_IIRFilterFactory.h" #include "AUD_IIRFilterReader.h" -AUD_IIRFilterFactory::AUD_IIRFilterFactory(AUD_Reference factory, +AUD_IIRFilterFactory::AUD_IIRFilterFactory(boost::shared_ptr factory, std::vector b, std::vector a) : AUD_EffectFactory(factory), m_a(a), m_b(b) { } -AUD_Reference AUD_IIRFilterFactory::createReader() +boost::shared_ptr AUD_IIRFilterFactory::createReader() { - return new AUD_IIRFilterReader(getReader(), m_b, m_a); + return boost::shared_ptr(new AUD_IIRFilterReader(getReader(), m_b, m_a)); } diff --git a/intern/audaspace/FX/AUD_IIRFilterFactory.h b/intern/audaspace/FX/AUD_IIRFilterFactory.h index 43256a166aa..0b55c120384 100644 --- a/intern/audaspace/FX/AUD_IIRFilterFactory.h +++ b/intern/audaspace/FX/AUD_IIRFilterFactory.h @@ -31,6 +31,7 @@ #define __AUD_IIRFILTERFACTORY_H__ #include "AUD_EffectFactory.h" +#include "AUD_IDynamicIIRFilterCalculator.h" #include @@ -61,10 +62,10 @@ public: * \param b The input filter coefficients. * \param a The output filter coefficients. */ - AUD_IIRFilterFactory(AUD_Reference factory, std::vector b, + AUD_IIRFilterFactory(boost::shared_ptr factory, std::vector b, std::vector a); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_IIRFILTERFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_IIRFilterReader.cpp b/intern/audaspace/FX/AUD_IIRFilterReader.cpp index 8f78c110d1f..6716e6b9ddc 100644 --- a/intern/audaspace/FX/AUD_IIRFilterReader.cpp +++ b/intern/audaspace/FX/AUD_IIRFilterReader.cpp @@ -29,7 +29,7 @@ #include "AUD_IIRFilterReader.h" -AUD_IIRFilterReader::AUD_IIRFilterReader(AUD_Reference reader, +AUD_IIRFilterReader::AUD_IIRFilterReader(boost::shared_ptr reader, const std::vector& b, const std::vector& a) : AUD_BaseIIRFilterReader(reader, b.size(), a.size()), m_a(a), m_b(b) diff --git a/intern/audaspace/FX/AUD_IIRFilterReader.h b/intern/audaspace/FX/AUD_IIRFilterReader.h index d9be52f2919..d663805b50f 100644 --- a/intern/audaspace/FX/AUD_IIRFilterReader.h +++ b/intern/audaspace/FX/AUD_IIRFilterReader.h @@ -61,7 +61,7 @@ public: * \param b The input filter coefficients. * \param a The output filter coefficients. */ - AUD_IIRFilterReader(AUD_Reference reader, const std::vector& b, + AUD_IIRFilterReader(boost::shared_ptr reader, const std::vector& b, const std::vector& a); virtual sample_t filter(); diff --git a/intern/audaspace/FX/AUD_LimiterFactory.cpp b/intern/audaspace/FX/AUD_LimiterFactory.cpp index e58657d8d70..679ed3a6b8b 100644 --- a/intern/audaspace/FX/AUD_LimiterFactory.cpp +++ b/intern/audaspace/FX/AUD_LimiterFactory.cpp @@ -31,7 +31,7 @@ #include "AUD_LimiterReader.h" #include "AUD_Space.h" -AUD_LimiterFactory::AUD_LimiterFactory(AUD_Reference factory, +AUD_LimiterFactory::AUD_LimiterFactory(boost::shared_ptr factory, float start, float end) : AUD_EffectFactory(factory), m_start(start), @@ -49,7 +49,7 @@ float AUD_LimiterFactory::getEnd() const return m_end; } -AUD_Reference AUD_LimiterFactory::createReader() +boost::shared_ptr AUD_LimiterFactory::createReader() { - return new AUD_LimiterReader(getReader(), m_start, m_end); + return boost::shared_ptr(new AUD_LimiterReader(getReader(), m_start, m_end)); } diff --git a/intern/audaspace/FX/AUD_LimiterFactory.h b/intern/audaspace/FX/AUD_LimiterFactory.h index ddc8183ce7a..0376952b4bd 100644 --- a/intern/audaspace/FX/AUD_LimiterFactory.h +++ b/intern/audaspace/FX/AUD_LimiterFactory.h @@ -60,7 +60,7 @@ public: * \param end The desired end time, a negative value signals that it should * play to the end. */ - AUD_LimiterFactory(AUD_Reference factory, + AUD_LimiterFactory(boost::shared_ptr factory, float start = 0, float end = -1); /** @@ -73,7 +73,7 @@ public: */ float getEnd() const; - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_LIMITERFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_LimiterReader.cpp b/intern/audaspace/FX/AUD_LimiterReader.cpp index 0abf496c7f9..9c1d4443b06 100644 --- a/intern/audaspace/FX/AUD_LimiterReader.cpp +++ b/intern/audaspace/FX/AUD_LimiterReader.cpp @@ -30,7 +30,7 @@ #include "AUD_LimiterReader.h" #include "AUD_Buffer.h" -AUD_LimiterReader::AUD_LimiterReader(AUD_Reference reader, +AUD_LimiterReader::AUD_LimiterReader(boost::shared_ptr reader, float start, float end) : AUD_EffectReader(reader), m_start(start), diff --git a/intern/audaspace/FX/AUD_LimiterReader.h b/intern/audaspace/FX/AUD_LimiterReader.h index 34c4ea7c20e..607eb9e5bec 100644 --- a/intern/audaspace/FX/AUD_LimiterReader.h +++ b/intern/audaspace/FX/AUD_LimiterReader.h @@ -60,7 +60,7 @@ public: * \param end The desired end time (sample exklusive), a negative value * signals that it should play to the end. */ - AUD_LimiterReader(AUD_Reference reader, float start = 0, float end = -1); + AUD_LimiterReader(boost::shared_ptr reader, float start = 0, float end = -1); virtual void seek(int position); virtual int getLength() const; diff --git a/intern/audaspace/FX/AUD_LoopFactory.cpp b/intern/audaspace/FX/AUD_LoopFactory.cpp index 32c9e6bad7f..a9e83e349a0 100644 --- a/intern/audaspace/FX/AUD_LoopFactory.cpp +++ b/intern/audaspace/FX/AUD_LoopFactory.cpp @@ -30,7 +30,7 @@ #include "AUD_LoopFactory.h" #include "AUD_LoopReader.h" -AUD_LoopFactory::AUD_LoopFactory(AUD_Reference factory, int loop) : +AUD_LoopFactory::AUD_LoopFactory(boost::shared_ptr factory, int loop) : AUD_EffectFactory(factory), m_loop(loop) { @@ -41,7 +41,7 @@ int AUD_LoopFactory::getLoop() const return m_loop; } -AUD_Reference AUD_LoopFactory::createReader() +boost::shared_ptr AUD_LoopFactory::createReader() { - return new AUD_LoopReader(getReader(), m_loop); + return boost::shared_ptr(new AUD_LoopReader(getReader(), m_loop)); } diff --git a/intern/audaspace/FX/AUD_LoopFactory.h b/intern/audaspace/FX/AUD_LoopFactory.h index 754b780bd99..570536bee9a 100644 --- a/intern/audaspace/FX/AUD_LoopFactory.h +++ b/intern/audaspace/FX/AUD_LoopFactory.h @@ -55,14 +55,14 @@ public: * \param loop The desired loop count, negative values result in endless * looping. */ - AUD_LoopFactory(AUD_Reference factory, int loop = -1); + AUD_LoopFactory(boost::shared_ptr factory, int loop = -1); /** * Returns the loop count. */ int getLoop() const; - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_LOOPFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_LoopReader.cpp b/intern/audaspace/FX/AUD_LoopReader.cpp index 863f66f9f46..6fbcaa5af37 100644 --- a/intern/audaspace/FX/AUD_LoopReader.cpp +++ b/intern/audaspace/FX/AUD_LoopReader.cpp @@ -32,7 +32,7 @@ #include -AUD_LoopReader::AUD_LoopReader(AUD_Reference reader, int loop) : +AUD_LoopReader::AUD_LoopReader(boost::shared_ptr reader, int loop) : AUD_EffectReader(reader), m_count(loop), m_left(loop) { } diff --git a/intern/audaspace/FX/AUD_LoopReader.h b/intern/audaspace/FX/AUD_LoopReader.h index fd2dd71d78f..12b8078b12d 100644 --- a/intern/audaspace/FX/AUD_LoopReader.h +++ b/intern/audaspace/FX/AUD_LoopReader.h @@ -61,7 +61,7 @@ public: * \param loop The desired loop count, negative values result in endless * looping. */ - AUD_LoopReader(AUD_Reference reader, int loop); + AUD_LoopReader(boost::shared_ptr reader, int loop); virtual void seek(int position); virtual int getLength() const; diff --git a/intern/audaspace/FX/AUD_LowpassFactory.cpp b/intern/audaspace/FX/AUD_LowpassFactory.cpp index 14dbc951c7f..e2faa241ac9 100644 --- a/intern/audaspace/FX/AUD_LowpassFactory.cpp +++ b/intern/audaspace/FX/AUD_LowpassFactory.cpp @@ -36,7 +36,7 @@ #define M_PI 3.14159265358979323846 #endif -AUD_LowpassFactory::AUD_LowpassFactory(AUD_Reference factory, float frequency, +AUD_LowpassFactory::AUD_LowpassFactory(boost::shared_ptr factory, float frequency, float Q) : AUD_DynamicIIRFilterFactory(factory), m_frequency(frequency), diff --git a/intern/audaspace/FX/AUD_LowpassFactory.h b/intern/audaspace/FX/AUD_LowpassFactory.h index 7e98720a2db..fdbc6e5d91d 100644 --- a/intern/audaspace/FX/AUD_LowpassFactory.h +++ b/intern/audaspace/FX/AUD_LowpassFactory.h @@ -59,7 +59,7 @@ public: * \param frequency The cutoff frequency. * \param Q The Q factor. */ - AUD_LowpassFactory(AUD_Reference factory, float frequency, float Q = 1.0f); + AUD_LowpassFactory(boost::shared_ptr factory, float frequency, float Q = 1.0f); virtual void recalculateCoefficients(AUD_SampleRate rate, std::vector &b, std::vector &a); }; diff --git a/intern/audaspace/FX/AUD_PingPongFactory.cpp b/intern/audaspace/FX/AUD_PingPongFactory.cpp index 3d5011cf47b..84e4b29415e 100644 --- a/intern/audaspace/FX/AUD_PingPongFactory.cpp +++ b/intern/audaspace/FX/AUD_PingPongFactory.cpp @@ -31,16 +31,16 @@ #include "AUD_DoubleReader.h" #include "AUD_ReverseFactory.h" -AUD_PingPongFactory::AUD_PingPongFactory(AUD_Reference factory) : +AUD_PingPongFactory::AUD_PingPongFactory(boost::shared_ptr factory) : AUD_EffectFactory(factory) { } -AUD_Reference AUD_PingPongFactory::createReader() +boost::shared_ptr AUD_PingPongFactory::createReader() { - AUD_Reference reader = getReader(); + boost::shared_ptr reader = getReader(); AUD_ReverseFactory factory(m_factory); - AUD_Reference reader2 = factory.createReader(); + boost::shared_ptr reader2 = factory.createReader(); - return new AUD_DoubleReader(reader, reader2); + return boost::shared_ptr(new AUD_DoubleReader(reader, reader2)); } diff --git a/intern/audaspace/FX/AUD_PingPongFactory.h b/intern/audaspace/FX/AUD_PingPongFactory.h index f25624a7c5e..e8ee5c9e389 100644 --- a/intern/audaspace/FX/AUD_PingPongFactory.h +++ b/intern/audaspace/FX/AUD_PingPongFactory.h @@ -48,9 +48,9 @@ public: * Creates a new ping pong factory. * \param factory The input factory. */ - AUD_PingPongFactory(AUD_Reference factory); + AUD_PingPongFactory(boost::shared_ptr factory); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_PINGPONGFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_PitchFactory.cpp b/intern/audaspace/FX/AUD_PitchFactory.cpp index c6e9ae0b457..9dc27a58162 100644 --- a/intern/audaspace/FX/AUD_PitchFactory.cpp +++ b/intern/audaspace/FX/AUD_PitchFactory.cpp @@ -31,13 +31,13 @@ #include "AUD_PitchReader.h" #include "AUD_Space.h" -AUD_PitchFactory::AUD_PitchFactory(AUD_Reference factory, float pitch) : +AUD_PitchFactory::AUD_PitchFactory(boost::shared_ptr factory, float pitch) : AUD_EffectFactory(factory), m_pitch(pitch) { } -AUD_Reference AUD_PitchFactory::createReader() +boost::shared_ptr AUD_PitchFactory::createReader() { - return new AUD_PitchReader(getReader(), m_pitch); + return boost::shared_ptr(new AUD_PitchReader(getReader(), m_pitch)); } diff --git a/intern/audaspace/FX/AUD_PitchFactory.h b/intern/audaspace/FX/AUD_PitchFactory.h index 5ad37ad1a6c..159388b28dd 100644 --- a/intern/audaspace/FX/AUD_PitchFactory.h +++ b/intern/audaspace/FX/AUD_PitchFactory.h @@ -53,9 +53,9 @@ public: * \param factory The input factory. * \param pitch The desired pitch. */ - AUD_PitchFactory(AUD_Reference factory, float pitch); + AUD_PitchFactory(boost::shared_ptr factory, float pitch); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_PITCHFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_PitchReader.cpp b/intern/audaspace/FX/AUD_PitchReader.cpp index 0d1ff012e73..218af4fc090 100644 --- a/intern/audaspace/FX/AUD_PitchReader.cpp +++ b/intern/audaspace/FX/AUD_PitchReader.cpp @@ -29,7 +29,7 @@ #include "AUD_PitchReader.h" -AUD_PitchReader::AUD_PitchReader(AUD_Reference reader, float pitch) : +AUD_PitchReader::AUD_PitchReader(boost::shared_ptr reader, float pitch) : AUD_EffectReader(reader), m_pitch(pitch) { } diff --git a/intern/audaspace/FX/AUD_PitchReader.h b/intern/audaspace/FX/AUD_PitchReader.h index 3185bfdf30b..d22e589b05d 100644 --- a/intern/audaspace/FX/AUD_PitchReader.h +++ b/intern/audaspace/FX/AUD_PitchReader.h @@ -53,7 +53,7 @@ public: * \param reader The reader to read from. * \param pitch The pitch value. */ - AUD_PitchReader(AUD_Reference reader, float pitch); + AUD_PitchReader(boost::shared_ptr reader, float pitch); virtual AUD_Specs getSpecs() const; diff --git a/intern/audaspace/FX/AUD_RectifyFactory.cpp b/intern/audaspace/FX/AUD_RectifyFactory.cpp index ad01f404698..26bb5615dad 100644 --- a/intern/audaspace/FX/AUD_RectifyFactory.cpp +++ b/intern/audaspace/FX/AUD_RectifyFactory.cpp @@ -37,12 +37,12 @@ sample_t AUD_RectifyFactory::rectifyFilter(AUD_CallbackIIRFilterReader* reader, return fabs(reader->x(0)); } -AUD_RectifyFactory::AUD_RectifyFactory(AUD_Reference factory) : +AUD_RectifyFactory::AUD_RectifyFactory(boost::shared_ptr factory) : AUD_EffectFactory(factory) { } -AUD_Reference AUD_RectifyFactory::createReader() +boost::shared_ptr AUD_RectifyFactory::createReader() { - return new AUD_CallbackIIRFilterReader(getReader(), 1, 1, rectifyFilter); + return boost::shared_ptr(new AUD_CallbackIIRFilterReader(getReader(), 1, 1, rectifyFilter)); } diff --git a/intern/audaspace/FX/AUD_RectifyFactory.h b/intern/audaspace/FX/AUD_RectifyFactory.h index 5ad41d424d9..eb595e43e4f 100644 --- a/intern/audaspace/FX/AUD_RectifyFactory.h +++ b/intern/audaspace/FX/AUD_RectifyFactory.h @@ -48,9 +48,9 @@ public: * Creates a new rectify factory. * \param factory The input factory. */ - AUD_RectifyFactory(AUD_Reference factory); + AUD_RectifyFactory(boost::shared_ptr factory); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); static sample_t rectifyFilter(AUD_CallbackIIRFilterReader* reader, void* useless); }; diff --git a/intern/audaspace/FX/AUD_ReverseFactory.cpp b/intern/audaspace/FX/AUD_ReverseFactory.cpp index 063cbc88180..afb4ad2bec9 100644 --- a/intern/audaspace/FX/AUD_ReverseFactory.cpp +++ b/intern/audaspace/FX/AUD_ReverseFactory.cpp @@ -31,12 +31,12 @@ #include "AUD_ReverseReader.h" #include "AUD_Space.h" -AUD_ReverseFactory::AUD_ReverseFactory(AUD_Reference factory) : +AUD_ReverseFactory::AUD_ReverseFactory(boost::shared_ptr factory) : AUD_EffectFactory(factory) { } -AUD_Reference AUD_ReverseFactory::createReader() +boost::shared_ptr AUD_ReverseFactory::createReader() { - return new AUD_ReverseReader(getReader()); + return boost::shared_ptr(new AUD_ReverseReader(getReader())); } diff --git a/intern/audaspace/FX/AUD_ReverseFactory.h b/intern/audaspace/FX/AUD_ReverseFactory.h index e2d75dc560a..5b0c9e3c29a 100644 --- a/intern/audaspace/FX/AUD_ReverseFactory.h +++ b/intern/audaspace/FX/AUD_ReverseFactory.h @@ -48,9 +48,9 @@ public: * Creates a new reverse factory. * \param factory The input factory. */ - AUD_ReverseFactory(AUD_Reference factory); + AUD_ReverseFactory(boost::shared_ptr factory); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_REVERSEFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_ReverseReader.cpp b/intern/audaspace/FX/AUD_ReverseReader.cpp index 6b454c66d25..c0a5962a299 100644 --- a/intern/audaspace/FX/AUD_ReverseReader.cpp +++ b/intern/audaspace/FX/AUD_ReverseReader.cpp @@ -34,7 +34,7 @@ static const char* props_error = "AUD_ReverseReader: The reader has to be " "seekable and a finite length."; -AUD_ReverseReader::AUD_ReverseReader(AUD_Reference reader) : +AUD_ReverseReader::AUD_ReverseReader(boost::shared_ptr reader) : AUD_EffectReader(reader), m_length(reader->getLength()), m_position(0) diff --git a/intern/audaspace/FX/AUD_ReverseReader.h b/intern/audaspace/FX/AUD_ReverseReader.h index d1e5179b8ec..219047915bd 100644 --- a/intern/audaspace/FX/AUD_ReverseReader.h +++ b/intern/audaspace/FX/AUD_ReverseReader.h @@ -61,7 +61,7 @@ public: * \exception AUD_Exception Thrown if the reader specified has an * undeterminable/infinite length or is not seekable. */ - AUD_ReverseReader(AUD_Reference reader); + AUD_ReverseReader(boost::shared_ptr reader); virtual void seek(int position); virtual int getLength() const; diff --git a/intern/audaspace/FX/AUD_SquareFactory.cpp b/intern/audaspace/FX/AUD_SquareFactory.cpp index 7aabdb775f6..4b4dccb6e6b 100644 --- a/intern/audaspace/FX/AUD_SquareFactory.cpp +++ b/intern/audaspace/FX/AUD_SquareFactory.cpp @@ -46,7 +46,7 @@ void AUD_SquareFactory::endSquareFilter(float* threshold) delete threshold; } -AUD_SquareFactory::AUD_SquareFactory(AUD_Reference factory, float threshold) : +AUD_SquareFactory::AUD_SquareFactory(boost::shared_ptr factory, float threshold) : AUD_EffectFactory(factory), m_threshold(threshold) { @@ -57,10 +57,10 @@ float AUD_SquareFactory::getThreshold() const return m_threshold; } -AUD_Reference AUD_SquareFactory::createReader() +boost::shared_ptr AUD_SquareFactory::createReader() { - return new AUD_CallbackIIRFilterReader(getReader(), 1, 1, + return boost::shared_ptr(new AUD_CallbackIIRFilterReader(getReader(), 1, 1, (doFilterIIR) squareFilter, (endFilterIIR) endSquareFilter, - new float(m_threshold)); + new float(m_threshold))); } diff --git a/intern/audaspace/FX/AUD_SquareFactory.h b/intern/audaspace/FX/AUD_SquareFactory.h index 9c0dea25d2b..27e62b6f4cc 100644 --- a/intern/audaspace/FX/AUD_SquareFactory.h +++ b/intern/audaspace/FX/AUD_SquareFactory.h @@ -54,14 +54,14 @@ public: * \param factory The input factory. * \param threshold The threshold. */ - AUD_SquareFactory(AUD_Reference factory, float threshold = 0.0f); + AUD_SquareFactory(boost::shared_ptr factory, float threshold = 0.0f); /** * Returns the threshold. */ float getThreshold() const; - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); static sample_t squareFilter(AUD_CallbackIIRFilterReader* reader, float* threshold); static void endSquareFilter(float* threshold); diff --git a/intern/audaspace/FX/AUD_SumFactory.cpp b/intern/audaspace/FX/AUD_SumFactory.cpp index b58c44b0171..7f82233a0b7 100644 --- a/intern/audaspace/FX/AUD_SumFactory.cpp +++ b/intern/audaspace/FX/AUD_SumFactory.cpp @@ -30,16 +30,16 @@ #include "AUD_SumFactory.h" #include "AUD_IIRFilterReader.h" -AUD_SumFactory::AUD_SumFactory(AUD_Reference factory) : +AUD_SumFactory::AUD_SumFactory(boost::shared_ptr factory) : AUD_EffectFactory(factory) { } -AUD_Reference AUD_SumFactory::createReader() +boost::shared_ptr AUD_SumFactory::createReader() { std::vector a, b; a.push_back(1); a.push_back(-1); b.push_back(1); - return new AUD_IIRFilterReader(getReader(), b, a); + return boost::shared_ptr(new AUD_IIRFilterReader(getReader(), b, a)); } diff --git a/intern/audaspace/FX/AUD_SumFactory.h b/intern/audaspace/FX/AUD_SumFactory.h index ec17faf3fb2..a916f3509cb 100644 --- a/intern/audaspace/FX/AUD_SumFactory.h +++ b/intern/audaspace/FX/AUD_SumFactory.h @@ -47,9 +47,9 @@ public: * Creates a new sum factory. * \param factory The input factory. */ - AUD_SumFactory(AUD_Reference factory); + AUD_SumFactory(boost::shared_ptr factory); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_SUMFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_SuperposeFactory.cpp b/intern/audaspace/FX/AUD_SuperposeFactory.cpp index 30c57198c73..3efad37a5b3 100644 --- a/intern/audaspace/FX/AUD_SuperposeFactory.cpp +++ b/intern/audaspace/FX/AUD_SuperposeFactory.cpp @@ -30,15 +30,15 @@ #include "AUD_SuperposeFactory.h" #include "AUD_SuperposeReader.h" -AUD_SuperposeFactory::AUD_SuperposeFactory(AUD_Reference factory1, AUD_Reference factory2) : +AUD_SuperposeFactory::AUD_SuperposeFactory(boost::shared_ptr factory1, boost::shared_ptr factory2) : m_factory1(factory1), m_factory2(factory2) { } -AUD_Reference AUD_SuperposeFactory::createReader() +boost::shared_ptr AUD_SuperposeFactory::createReader() { - AUD_Reference reader1 = m_factory1->createReader(); - AUD_Reference reader2 = m_factory2->createReader(); + boost::shared_ptr reader1 = m_factory1->createReader(); + boost::shared_ptr reader2 = m_factory2->createReader(); - return new AUD_SuperposeReader(reader1, reader2); + return boost::shared_ptr(new AUD_SuperposeReader(reader1, reader2)); } diff --git a/intern/audaspace/FX/AUD_SuperposeFactory.h b/intern/audaspace/FX/AUD_SuperposeFactory.h index 2da8e34496d..caa0dfb752f 100644 --- a/intern/audaspace/FX/AUD_SuperposeFactory.h +++ b/intern/audaspace/FX/AUD_SuperposeFactory.h @@ -43,12 +43,12 @@ private: /** * First played factory. */ - AUD_Reference m_factory1; + boost::shared_ptr m_factory1; /** * Second played factory. */ - AUD_Reference m_factory2; + boost::shared_ptr m_factory2; // hide copy constructor and operator= AUD_SuperposeFactory(const AUD_SuperposeFactory&); @@ -60,9 +60,9 @@ public: * \param factory1 The first input factory. * \param factory2 The second input factory. */ - AUD_SuperposeFactory(AUD_Reference factory1, AUD_Reference factory2); + AUD_SuperposeFactory(boost::shared_ptr factory1, boost::shared_ptr factory2); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_SUPERPOSEFACTORY_H__ diff --git a/intern/audaspace/FX/AUD_SuperposeReader.cpp b/intern/audaspace/FX/AUD_SuperposeReader.cpp index 535d3590a8f..294a48b3e7a 100644 --- a/intern/audaspace/FX/AUD_SuperposeReader.cpp +++ b/intern/audaspace/FX/AUD_SuperposeReader.cpp @@ -34,7 +34,7 @@ static const char* specs_error = "AUD_SuperposeReader: Both readers have to " "have the same specs."; -AUD_SuperposeReader::AUD_SuperposeReader(AUD_Reference reader1, AUD_Reference reader2) : +AUD_SuperposeReader::AUD_SuperposeReader(boost::shared_ptr reader1, boost::shared_ptr reader2) : m_reader1(reader1), m_reader2(reader2) { } diff --git a/intern/audaspace/FX/AUD_SuperposeReader.h b/intern/audaspace/FX/AUD_SuperposeReader.h index d0fde13a267..a04ab90fe43 100644 --- a/intern/audaspace/FX/AUD_SuperposeReader.h +++ b/intern/audaspace/FX/AUD_SuperposeReader.h @@ -32,7 +32,8 @@ #include "AUD_IReader.h" #include "AUD_Buffer.h" -#include "AUD_Reference.h" + +#include /** * This reader plays two readers with the same specs in parallel. @@ -43,12 +44,12 @@ private: /** * The first reader. */ - AUD_Reference m_reader1; + boost::shared_ptr m_reader1; /** * The second reader. */ - AUD_Reference m_reader2; + boost::shared_ptr m_reader2; /** * Buffer used for mixing. @@ -66,7 +67,7 @@ public: * \param reader2 The second reader to read from. * \exception AUD_Exception Thrown if the specs from the readers differ. */ - AUD_SuperposeReader(AUD_Reference reader1, AUD_Reference reader2); + AUD_SuperposeReader(boost::shared_ptr reader1, boost::shared_ptr reader2); /** * Destroys the reader. diff --git a/intern/audaspace/FX/AUD_VolumeFactory.cpp b/intern/audaspace/FX/AUD_VolumeFactory.cpp index f5e635eec2d..4f0e1e425e6 100644 --- a/intern/audaspace/FX/AUD_VolumeFactory.cpp +++ b/intern/audaspace/FX/AUD_VolumeFactory.cpp @@ -30,7 +30,7 @@ #include "AUD_VolumeFactory.h" #include "AUD_IIRFilterReader.h" -AUD_VolumeFactory::AUD_VolumeFactory(AUD_Reference factory, float volume) : +AUD_VolumeFactory::AUD_VolumeFactory(boost::shared_ptr factory, float volume) : AUD_EffectFactory(factory), m_volume(volume) { @@ -41,10 +41,10 @@ float AUD_VolumeFactory::getVolume() const return m_volume; } -AUD_Reference AUD_VolumeFactory::createReader() +boost::shared_ptr AUD_VolumeFactory::createReader() { std::vector a, b; a.push_back(1); b.push_back(m_volume); - return new AUD_IIRFilterReader(getReader(), b, a); + return boost::shared_ptr(new AUD_IIRFilterReader(getReader(), b, a)); } diff --git a/intern/audaspace/FX/AUD_VolumeFactory.h b/intern/audaspace/FX/AUD_VolumeFactory.h index b12838373b3..6fe779ffb88 100644 --- a/intern/audaspace/FX/AUD_VolumeFactory.h +++ b/intern/audaspace/FX/AUD_VolumeFactory.h @@ -55,7 +55,7 @@ public: * \param factory The input factory. * \param volume The desired volume. */ - AUD_VolumeFactory(AUD_Reference factory, float volume); + AUD_VolumeFactory(boost::shared_ptr factory, float volume); /** * Returns the volume. @@ -63,7 +63,7 @@ public: */ float getVolume() const; - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_VOLUMEFACTORY_H__ diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp index a114d8b8a87..371e0007bd3 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp @@ -67,7 +67,7 @@ static const char* queue_error = "AUD_OpenALDevice: Buffer couldn't be " static const char* bufferdata_error = "AUD_OpenALDevice: Buffer couldn't be " "filled with data."; -AUD_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, AUD_Reference reader, bool keep) : +AUD_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, boost::shared_ptr reader, bool keep) : m_isBuffered(false), m_reader(reader), m_keep(keep), m_format(format), m_current(0), m_eos(false), m_loopcount(0), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING), m_device(device) @@ -130,14 +130,22 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::pause() if(m_status == AUD_STATUS_PLAYING) { - m_device->m_playingSounds.remove(this); - m_device->m_pausedSounds.push_back(this); + for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++) + { + if(it->get() == this) + { + boost::shared_ptr This = *it; - alSourcePause(m_source); + m_device->m_playingSounds.erase(it); + m_device->m_pausedSounds.push_back(This); - m_status = AUD_STATUS_PAUSED; + alSourcePause(m_source); - return true; + m_status = AUD_STATUS_PAUSED; + + return true; + } + } } } @@ -152,12 +160,21 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::resume() if(m_status == AUD_STATUS_PAUSED) { - m_device->m_pausedSounds.remove(this); - m_device->m_playingSounds.push_back(this); + for(AUD_HandleIterator it = m_device->m_pausedSounds.begin(); it != m_device->m_pausedSounds.end(); it++) + { + if(it->get() == this) + { + boost::shared_ptr This = *it; - m_device->start(); - m_status = AUD_STATUS_PLAYING; - return true; + m_device->m_pausedSounds.erase(it); + m_device->m_playingSounds.push_back(This); + + m_device->start(); + m_status = AUD_STATUS_PLAYING; + + return true; + } + } } } @@ -184,7 +201,7 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::stop() { if(it->get() == this) { - AUD_Reference This = *it; + boost::shared_ptr This = *it; m_device->m_playingSounds.erase(it); @@ -838,15 +855,15 @@ void AUD_OpenALDevice::start(bool join) void AUD_OpenALDevice::updateStreams() { - AUD_Reference sound; + boost::shared_ptr sound; int length; ALint info; AUD_DeviceSpecs specs = m_specs; ALCenum cerr; - std::list > stopSounds; - std::list > pauseSounds; + std::list > stopSounds; + std::list > pauseSounds; AUD_HandleIterator it; while(1) @@ -1204,32 +1221,32 @@ bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs) return valid; } -AUD_Reference AUD_OpenALDevice::play(AUD_Reference reader, bool keep) +boost::shared_ptr AUD_OpenALDevice::play(boost::shared_ptr reader, bool keep) { AUD_Specs specs = reader->getSpecs(); // check format if(specs.channels == AUD_CHANNELS_INVALID) - return AUD_Reference(); + return boost::shared_ptr(); if(m_specs.format != AUD_FORMAT_FLOAT32) - reader = new AUD_ConverterReader(reader, m_specs); + reader = boost::shared_ptr(new AUD_ConverterReader(reader, m_specs)); ALenum format; if(!getFormat(format, specs)) - return AUD_Reference(); + return boost::shared_ptr(); AUD_MutexLock lock(*this); alcSuspendContext(m_context); - AUD_Reference sound; + boost::shared_ptr sound; try { // create the handle - sound = new AUD_OpenALDevice::AUD_OpenALHandle(this, format, reader, keep); + sound = boost::shared_ptr(new AUD_OpenALDevice::AUD_OpenALHandle(this, format, reader, keep)); } catch(AUD_Exception&) { @@ -1244,10 +1261,10 @@ AUD_Reference AUD_OpenALDevice::play(AUD_Reference rea start(); - return AUD_Reference(sound); + return boost::shared_ptr(sound); } -AUD_Reference AUD_OpenALDevice::play(AUD_Reference factory, bool keep) +boost::shared_ptr AUD_OpenALDevice::play(boost::shared_ptr factory, bool keep) { /* AUD_XXX disabled AUD_OpenALHandle* sound = NULL; diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.h b/intern/audaspace/OpenAL/AUD_OpenALDevice.h index 0a409b42462..d2a4be227ba 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.h +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.h @@ -58,7 +58,7 @@ private: bool m_isBuffered; /// The reader source. - AUD_Reference m_reader; + boost::shared_ptr m_reader; /// Whether to keep the source if end of it is reached. bool m_keep; @@ -105,7 +105,7 @@ private: * \param reader The reader this handle plays. * \param keep Whether to keep the handle alive when the reader ends. */ - AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, AUD_Reference reader, bool keep); + AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, boost::shared_ptr reader, bool keep); virtual ~AUD_OpenALHandle() {} virtual bool pause(); @@ -150,7 +150,7 @@ private: virtual bool setConeVolumeOuter(float volume); }; - typedef std::list >::iterator AUD_HandleIterator; + typedef std::list >::iterator AUD_HandleIterator; /** * The OpenAL device handle. @@ -175,12 +175,12 @@ private: /** * The list of sounds that are currently playing. */ - std::list > m_playingSounds; + std::list > m_playingSounds; /** * The list of sounds that are currently paused. */ - std::list > m_pausedSounds; + std::list > m_pausedSounds; /** * The list of buffered factories. @@ -255,8 +255,8 @@ public: virtual ~AUD_OpenALDevice(); virtual AUD_DeviceSpecs getSpecs() const; - virtual AUD_Reference play(AUD_Reference reader, bool keep = false); - virtual AUD_Reference play(AUD_Reference factory, bool keep = false); + virtual boost::shared_ptr play(boost::shared_ptr reader, bool keep = false); + virtual boost::shared_ptr play(boost::shared_ptr factory, bool keep = false); virtual void stopAll(); virtual void lock(); virtual void unlock(); diff --git a/intern/audaspace/Python/AUD_PyAPI.cpp b/intern/audaspace/Python/AUD_PyAPI.cpp index dd58e5a7398..9beba2eb0a0 100644 --- a/intern/audaspace/Python/AUD_PyAPI.cpp +++ b/intern/audaspace/Python/AUD_PyAPI.cpp @@ -90,7 +90,7 @@ static void Factory_dealloc(Factory* self) { if(self->factory) - delete reinterpret_cast*>(self->factory); + delete reinterpret_cast*>(self->factory); Py_XDECREF(self->child_list); Py_TYPE(self)->tp_free((PyObject *)self); } @@ -114,7 +114,7 @@ Factory_new(PyTypeObject *type, PyObject *args, PyObject *kwds) try { - self->factory = new AUD_Reference(new AUD_FileFactory(filename)); + self->factory = new boost::shared_ptr(new AUD_FileFactory(filename)); } catch(AUD_Exception& e) { @@ -154,7 +154,7 @@ Factory_sine(PyTypeObject* type, PyObject *args) { try { - self->factory = new AUD_Reference(new AUD_SinusFactory(frequency, (AUD_SampleRate)rate)); + self->factory = new boost::shared_ptr(new AUD_SinusFactory(frequency, (AUD_SampleRate)rate)); } catch(AUD_Exception& e) { @@ -193,7 +193,7 @@ Factory_file(PyTypeObject* type, PyObject *args) { try { - self->factory = new AUD_Reference(new AUD_FileFactory(filename)); + self->factory = new boost::shared_ptr(new AUD_FileFactory(filename)); } catch(AUD_Exception& e) { @@ -236,7 +236,7 @@ Factory_lowpass(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference(new AUD_LowpassFactory(*reinterpret_cast*>(self->factory), frequency, Q)); + parent->factory = new boost::shared_ptr(new AUD_LowpassFactory(*reinterpret_cast*>(self->factory), frequency, Q)); } catch(AUD_Exception& e) { @@ -277,7 +277,7 @@ Factory_delay(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference(new AUD_DelayFactory(*reinterpret_cast*>(self->factory), delay)); + parent->factory = new boost::shared_ptr(new AUD_DelayFactory(*reinterpret_cast*>(self->factory), delay)); } catch(AUD_Exception& e) { @@ -321,7 +321,7 @@ Factory_join(Factory* self, PyObject *object) try { - parent->factory = new AUD_Reference(new AUD_DoubleFactory(*reinterpret_cast*>(self->factory), *reinterpret_cast*>(child->factory))); + parent->factory = new boost::shared_ptr(new AUD_DoubleFactory(*reinterpret_cast*>(self->factory), *reinterpret_cast*>(child->factory))); } catch(AUD_Exception& e) { @@ -364,7 +364,7 @@ Factory_highpass(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference(new AUD_HighpassFactory(*reinterpret_cast*>(self->factory), frequency, Q)); + parent->factory = new boost::shared_ptr(new AUD_HighpassFactory(*reinterpret_cast*>(self->factory), frequency, Q)); } catch(AUD_Exception& e) { @@ -405,7 +405,7 @@ Factory_limit(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference(new AUD_LimiterFactory(*reinterpret_cast*>(self->factory), start, end)); + parent->factory = new boost::shared_ptr(new AUD_LimiterFactory(*reinterpret_cast*>(self->factory), start, end)); } catch(AUD_Exception& e) { @@ -449,7 +449,7 @@ Factory_pitch(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference(new AUD_PitchFactory(*reinterpret_cast*>(self->factory), factor)); + parent->factory = new boost::shared_ptr(new AUD_PitchFactory(*reinterpret_cast*>(self->factory), factor)); } catch(AUD_Exception& e) { @@ -491,7 +491,7 @@ Factory_volume(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference(new AUD_VolumeFactory(*reinterpret_cast*>(self->factory), volume)); + parent->factory = new boost::shared_ptr(new AUD_VolumeFactory(*reinterpret_cast*>(self->factory), volume)); } catch(AUD_Exception& e) { @@ -534,7 +534,7 @@ Factory_fadein(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference(new AUD_FaderFactory(*reinterpret_cast*>(self->factory), AUD_FADE_IN, start, length)); + parent->factory = new boost::shared_ptr(new AUD_FaderFactory(*reinterpret_cast*>(self->factory), AUD_FADE_IN, start, length)); } catch(AUD_Exception& e) { @@ -578,7 +578,7 @@ Factory_fadeout(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference(new AUD_FaderFactory(*reinterpret_cast*>(self->factory), AUD_FADE_OUT, start, length)); + parent->factory = new boost::shared_ptr(new AUD_FaderFactory(*reinterpret_cast*>(self->factory), AUD_FADE_OUT, start, length)); } catch(AUD_Exception& e) { @@ -620,7 +620,7 @@ Factory_loop(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference(new AUD_LoopFactory(*reinterpret_cast*>(self->factory), loop)); + parent->factory = new boost::shared_ptr(new AUD_LoopFactory(*reinterpret_cast*>(self->factory), loop)); } catch(AUD_Exception& e) { @@ -663,7 +663,7 @@ Factory_mix(Factory* self, PyObject *object) try { - parent->factory = new AUD_Reference(new AUD_SuperposeFactory(*reinterpret_cast*>(self->factory), *reinterpret_cast*>(child->factory))); + parent->factory = new boost::shared_ptr(new AUD_SuperposeFactory(*reinterpret_cast*>(self->factory), *reinterpret_cast*>(child->factory))); } catch(AUD_Exception& e) { @@ -696,7 +696,7 @@ Factory_pingpong(Factory* self) try { - parent->factory = new AUD_Reference(new AUD_PingPongFactory(*reinterpret_cast*>(self->factory))); + parent->factory = new boost::shared_ptr(new AUD_PingPongFactory(*reinterpret_cast*>(self->factory))); } catch(AUD_Exception& e) { @@ -735,7 +735,7 @@ Factory_reverse(Factory* self) try { - parent->factory = new AUD_Reference(new AUD_ReverseFactory(*reinterpret_cast*>(self->factory))); + parent->factory = new boost::shared_ptr(new AUD_ReverseFactory(*reinterpret_cast*>(self->factory))); } catch(AUD_Exception& e) { @@ -770,7 +770,7 @@ Factory_buffer(Factory* self) { try { - parent->factory = new AUD_Reference(new AUD_StreamBufferFactory(*reinterpret_cast*>(self->factory))); + parent->factory = new boost::shared_ptr(new AUD_StreamBufferFactory(*reinterpret_cast*>(self->factory))); } catch(AUD_Exception& e) { @@ -812,7 +812,7 @@ Factory_square(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference(new AUD_SquareFactory(*reinterpret_cast*>(self->factory), threshold)); + parent->factory = new boost::shared_ptr(new AUD_SquareFactory(*reinterpret_cast*>(self->factory), threshold)); } catch(AUD_Exception& e) { @@ -915,7 +915,7 @@ Factory_filter(Factory* self, PyObject *args) try { - parent->factory = new AUD_Reference(new AUD_IIRFilterFactory(*reinterpret_cast*>(self->factory), b, a)); + parent->factory = new boost::shared_ptr(new AUD_IIRFilterFactory(*reinterpret_cast*>(self->factory), b, a)); } catch(AUD_Exception& e) { @@ -1039,7 +1039,7 @@ static void Handle_dealloc(Handle* self) { if(self->handle) - delete reinterpret_cast*>(self->handle); + delete reinterpret_cast*>(self->handle); Py_TYPE(self)->tp_free((PyObject *)self); } @@ -1054,7 +1054,7 @@ Handle_pause(Handle *self) { try { - return PyBool_FromLong((long)(*reinterpret_cast*>(self->handle))->pause()); + return PyBool_FromLong((long)(*reinterpret_cast*>(self->handle))->pause()); } catch(AUD_Exception& e) { @@ -1074,7 +1074,7 @@ Handle_resume(Handle *self) { try { - return PyBool_FromLong((long)(*reinterpret_cast*>(self->handle))->resume()); + return PyBool_FromLong((long)(*reinterpret_cast*>(self->handle))->resume()); } catch(AUD_Exception& e) { @@ -1095,7 +1095,7 @@ Handle_stop(Handle *self) { try { - return PyBool_FromLong((long)(*reinterpret_cast*>(self->handle))->stop()); + return PyBool_FromLong((long)(*reinterpret_cast*>(self->handle))->stop()); } catch(AUD_Exception& e) { @@ -1125,7 +1125,7 @@ Handle_get_position(Handle *self, void* nothing) { try { - return Py_BuildValue("f", (*reinterpret_cast*>(self->handle))->getPosition()); + return Py_BuildValue("f", (*reinterpret_cast*>(self->handle))->getPosition()); } catch(AUD_Exception& e) { @@ -1144,7 +1144,7 @@ Handle_set_position(Handle *self, PyObject *args, void* nothing) try { - if((*reinterpret_cast*>(self->handle))->seek(position)) + if((*reinterpret_cast*>(self->handle))->seek(position)) return 0; PyErr_SetString(AUDError, "Couldn't seek the sound!"); } @@ -1170,7 +1170,7 @@ Handle_get_keep(Handle *self, void* nothing) { try { - return PyBool_FromLong((long)(*reinterpret_cast*>(self->handle))->getKeep()); + return PyBool_FromLong((long)(*reinterpret_cast*>(self->handle))->getKeep()); } catch(AUD_Exception& e) { @@ -1192,7 +1192,7 @@ Handle_set_keep(Handle *self, PyObject *args, void* nothing) try { - if((*reinterpret_cast*>(self->handle))->setKeep(keep)) + if((*reinterpret_cast*>(self->handle))->setKeep(keep)) return 0; PyErr_SetString(AUDError, "Couldn't set keep of the sound!"); } @@ -1212,7 +1212,7 @@ Handle_get_status(Handle *self, void* nothing) { try { - return PyBool_FromLong((long)(*reinterpret_cast*>(self->handle))->getStatus()); + return PyBool_FromLong((long)(*reinterpret_cast*>(self->handle))->getStatus()); } catch(AUD_Exception& e) { @@ -1229,7 +1229,7 @@ Handle_get_volume(Handle *self, void* nothing) { try { - return Py_BuildValue("f", (*reinterpret_cast*>(self->handle))->getVolume()); + return Py_BuildValue("f", (*reinterpret_cast*>(self->handle))->getVolume()); } catch(AUD_Exception& e) { @@ -1248,7 +1248,7 @@ Handle_set_volume(Handle *self, PyObject *args, void* nothing) try { - if((*reinterpret_cast*>(self->handle))->setVolume(volume)) + if((*reinterpret_cast*>(self->handle))->setVolume(volume)) return 0; PyErr_SetString(AUDError, "Couldn't set the sound volume!"); } @@ -1268,7 +1268,7 @@ Handle_get_pitch(Handle *self, void* nothing) { try { - return Py_BuildValue("f", (*reinterpret_cast*>(self->handle))->getPitch()); + return Py_BuildValue("f", (*reinterpret_cast*>(self->handle))->getPitch()); } catch(AUD_Exception& e) { @@ -1287,7 +1287,7 @@ Handle_set_pitch(Handle *self, PyObject *args, void* nothing) try { - if((*reinterpret_cast*>(self->handle))->setPitch(pitch)) + if((*reinterpret_cast*>(self->handle))->setPitch(pitch)) return 0; PyErr_SetString(AUDError, "Couldn't set the sound pitch!"); } @@ -1307,7 +1307,7 @@ Handle_get_loop_count(Handle *self, void* nothing) { try { - return Py_BuildValue("i", (*reinterpret_cast*>(self->handle))->getLoopCount()); + return Py_BuildValue("i", (*reinterpret_cast*>(self->handle))->getLoopCount()); } catch(AUD_Exception& e) { @@ -1326,7 +1326,7 @@ Handle_set_loop_count(Handle *self, PyObject *args, void* nothing) try { - if((*reinterpret_cast*>(self->handle))->setLoopCount(loops)) + if((*reinterpret_cast*>(self->handle))->setLoopCount(loops)) return 0; PyErr_SetString(AUDError, "Couldn't set the loop count!"); } @@ -1346,7 +1346,7 @@ Handle_get_location(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { AUD_Vector3 v = handle->getSourceLocation(); @@ -1375,7 +1375,7 @@ Handle_set_location(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { AUD_Vector3 location(x, y, z); @@ -1402,7 +1402,7 @@ Handle_get_velocity(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { AUD_Vector3 v = handle->getSourceVelocity(); @@ -1431,7 +1431,7 @@ Handle_set_velocity(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { AUD_Vector3 velocity(x, y, z); @@ -1458,7 +1458,7 @@ Handle_get_orientation(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { AUD_Quaternion o = handle->getSourceOrientation(); @@ -1487,7 +1487,7 @@ Handle_set_orientation(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { AUD_Quaternion orientation(w, x, y, z); @@ -1514,7 +1514,7 @@ Handle_get_relative(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { return PyBool_FromLong((long)handle->isRelative()); @@ -1545,7 +1545,7 @@ Handle_set_relative(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { if(handle->setRelative(relative)) @@ -1572,7 +1572,7 @@ Handle_get_volume_minimum(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getVolumeMinimum()); @@ -1600,7 +1600,7 @@ Handle_set_volume_minimum(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { if(handle->setVolumeMinimum(volume)) @@ -1627,7 +1627,7 @@ Handle_get_volume_maximum(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getVolumeMaximum()); @@ -1655,7 +1655,7 @@ Handle_set_volume_maximum(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { if(handle->setVolumeMaximum(volume)) @@ -1683,7 +1683,7 @@ Handle_get_distance_reference(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getDistanceReference()); @@ -1711,7 +1711,7 @@ Handle_set_distance_reference(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { if(handle->setDistanceReference(distance)) @@ -1739,7 +1739,7 @@ Handle_get_distance_maximum(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getDistanceMaximum()); @@ -1767,7 +1767,7 @@ Handle_set_distance_maximum(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { if(handle->setDistanceMaximum(distance)) @@ -1795,7 +1795,7 @@ Handle_get_attenuation(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getAttenuation()); @@ -1823,7 +1823,7 @@ Handle_set_attenuation(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { if(handle->setAttenuation(factor)) @@ -1856,7 +1856,7 @@ Handle_get_cone_angle_inner(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getConeAngleInner()); @@ -1884,7 +1884,7 @@ Handle_set_cone_angle_inner(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { if(handle->setConeAngleInner(angle)) @@ -1911,7 +1911,7 @@ Handle_get_cone_angle_outer(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getConeAngleOuter()); @@ -1939,7 +1939,7 @@ Handle_set_cone_angle_outer(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { if(handle->setConeAngleOuter(angle)) @@ -1966,7 +1966,7 @@ Handle_get_cone_volume_outer(Handle *self, void* nothing) { try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { return Py_BuildValue("f", handle->getConeVolumeOuter()); @@ -1994,7 +1994,7 @@ Handle_set_cone_volume_outer(Handle *self, PyObject *args, void* nothing) try { - AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); + AUD_I3DHandle* handle = dynamic_cast(reinterpret_cast*>(self->handle)->get()); if(handle) { if(handle->setConeVolumeOuter(volume)) @@ -2104,7 +2104,7 @@ static void Device_dealloc(Device* self) { if(self->device) - delete reinterpret_cast*>(self->device); + delete reinterpret_cast*>(self->device); Py_TYPE(self)->tp_free((PyObject *)self); } @@ -2147,21 +2147,21 @@ Device_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { case AUD_DEVICE_NULL: (void)specs; /* quiet warning when others disabled */ - self->device = new AUD_Reference(new AUD_NULLDevice()); + self->device = new boost::shared_ptr(new AUD_NULLDevice()); break; case AUD_DEVICE_OPENAL: #ifdef WITH_OPENAL - self->device = new AUD_Reference(new AUD_OpenALDevice(specs, buffersize)); + self->device = new boost::shared_ptr(new AUD_OpenALDevice(specs, buffersize)); #endif break; case AUD_DEVICE_SDL: #ifdef WITH_SDL - self->device = new AUD_Reference(new AUD_SDLDevice(specs, buffersize)); + self->device = new boost::shared_ptr(new AUD_SDLDevice(specs, buffersize)); #endif break; case AUD_DEVICE_JACK: #ifdef WITH_JACK - self->device = new AUD_Reference(new AUD_JackDevice(name, specs, buffersize)); + self->device = new boost::shared_ptr(new AUD_JackDevice(name, specs, buffersize)); #endif break; case AUD_DEVICE_READ: @@ -2236,7 +2236,7 @@ Device_play(Device *self, PyObject *args, PyObject *kwds) { try { - handle->handle = new AUD_Reference((*reinterpret_cast*>(self->device))->play(*reinterpret_cast*>(sound->factory), keep)); + handle->handle = new boost::shared_ptr((*reinterpret_cast*>(self->device))->play(*reinterpret_cast*>(sound->factory), keep)); } catch(AUD_Exception& e) { @@ -2258,7 +2258,7 @@ Device_stopAll(Device *self) { try { - (*reinterpret_cast*>(self->device))->stopAll(); + (*reinterpret_cast*>(self->device))->stopAll(); Py_RETURN_NONE; } catch(AUD_Exception& e) @@ -2284,7 +2284,7 @@ Device_lock(Device *self) { try { - (*reinterpret_cast*>(self->device))->lock(); + (*reinterpret_cast*>(self->device))->lock(); Py_RETURN_NONE; } catch(AUD_Exception& e) @@ -2304,7 +2304,7 @@ Device_unlock(Device *self) { try { - (*reinterpret_cast*>(self->device))->unlock(); + (*reinterpret_cast*>(self->device))->unlock(); Py_RETURN_NONE; } catch(AUD_Exception& e) @@ -2338,7 +2338,7 @@ Device_get_rate(Device *self, void* nothing) { try { - AUD_DeviceSpecs specs = (*reinterpret_cast*>(self->device))->getSpecs(); + AUD_DeviceSpecs specs = (*reinterpret_cast*>(self->device))->getSpecs(); return Py_BuildValue("d", specs.rate); } catch(AUD_Exception& e) @@ -2356,7 +2356,7 @@ Device_get_format(Device *self, void* nothing) { try { - AUD_DeviceSpecs specs = (*reinterpret_cast*>(self->device))->getSpecs(); + AUD_DeviceSpecs specs = (*reinterpret_cast*>(self->device))->getSpecs(); return Py_BuildValue("i", specs.format); } catch(AUD_Exception& e) @@ -2374,7 +2374,7 @@ Device_get_channels(Device *self, void* nothing) { try { - AUD_DeviceSpecs specs = (*reinterpret_cast*>(self->device))->getSpecs(); + AUD_DeviceSpecs specs = (*reinterpret_cast*>(self->device))->getSpecs(); return Py_BuildValue("i", specs.channels); } catch(AUD_Exception& e) @@ -2392,7 +2392,7 @@ Device_get_volume(Device *self, void* nothing) { try { - return Py_BuildValue("f", (*reinterpret_cast*>(self->device))->getVolume()); + return Py_BuildValue("f", (*reinterpret_cast*>(self->device))->getVolume()); } catch(AUD_Exception& e) { @@ -2411,7 +2411,7 @@ Device_set_volume(Device *self, PyObject *args, void* nothing) try { - (*reinterpret_cast*>(self->device))->setVolume(volume); + (*reinterpret_cast*>(self->device))->setVolume(volume); return 0; } catch(AUD_Exception& e) @@ -2429,7 +2429,7 @@ Device_get_listener_location(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); if(device) { AUD_Vector3 v = device->getListenerLocation(); @@ -2458,7 +2458,7 @@ Device_set_listener_location(Device *self, PyObject *args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); if(device) { AUD_Vector3 location(x, y, z); @@ -2484,7 +2484,7 @@ Device_get_listener_velocity(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); if(device) { AUD_Vector3 v = device->getListenerVelocity(); @@ -2513,7 +2513,7 @@ Device_set_listener_velocity(Device *self, PyObject *args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); if(device) { AUD_Vector3 velocity(x, y, z); @@ -2539,7 +2539,7 @@ Device_get_listener_orientation(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); if(device) { AUD_Quaternion o = device->getListenerOrientation(); @@ -2568,7 +2568,7 @@ Device_set_listener_orientation(Device *self, PyObject *args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); if(device) { AUD_Quaternion orientation(w, x, y, z); @@ -2595,7 +2595,7 @@ Device_get_speed_of_sound(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); if(device) { return Py_BuildValue("f", device->getSpeedOfSound()); @@ -2623,7 +2623,7 @@ Device_set_speed_of_sound(Device *self, PyObject *args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); if(device) { device->setSpeedOfSound(speed); @@ -2651,7 +2651,7 @@ Device_get_doppler_factor(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); if(device) { return Py_BuildValue("f", device->getDopplerFactor()); @@ -2679,7 +2679,7 @@ Device_set_doppler_factor(Device *self, PyObject *args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); if(device) { device->setDopplerFactor(factor); @@ -2705,7 +2705,7 @@ Device_get_distance_model(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); if(device) { return Py_BuildValue("i", int(device->getDistanceModel())); @@ -2733,7 +2733,7 @@ Device_set_distance_model(Device *self, PyObject *args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); + AUD_I3DDevice* device = dynamic_cast(reinterpret_cast*>(self->device)->get()); if(device) { device->setDistanceModel(AUD_DistanceModel(model)); diff --git a/intern/audaspace/SConscript b/intern/audaspace/SConscript index 50c81db46dd..e2b6efacc96 100644 --- a/intern/audaspace/SConscript +++ b/intern/audaspace/SConscript @@ -3,7 +3,7 @@ Import ('env') sources = env.Glob('intern/*.cpp') + env.Glob('FX/*.cpp') -incs = '. intern FX ' + env['BF_PTHREADS_INC'] +incs = '. intern FX ' + env['BF_PTHREADS_INC'] + ' ' + env['BF_BOOST_INC'] defs = [] if env['WITH_BF_FFMPEG']: diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp index c4c384f054c..403c367fccc 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp @@ -46,10 +46,10 @@ AUD_FFMPEGFactory::AUD_FFMPEGFactory(const data_t* buffer, int size) : memcpy(m_buffer->getBuffer(), buffer, size); } -AUD_Reference AUD_FFMPEGFactory::createReader() +boost::shared_ptr AUD_FFMPEGFactory::createReader() { - if(m_buffer.isNull()) - return new AUD_FFMPEGReader(m_filename); + if(m_buffer.get()) + return boost::shared_ptr(new AUD_FFMPEGReader(m_buffer)); else - return new AUD_FFMPEGReader(m_buffer); + return boost::shared_ptr(new AUD_FFMPEGReader(m_filename)); } diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h index 349f55dd7db..23d0f07ed0b 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h @@ -31,10 +31,10 @@ #define __AUD_FFMPEGFACTORY_H__ #include "AUD_IFactory.h" -#include "AUD_Reference.h" #include "AUD_Buffer.h" #include +#include /** * This factory reads a sound file via ffmpeg. @@ -52,7 +52,7 @@ private: /** * The buffer to read from. */ - AUD_Reference m_buffer; + boost::shared_ptr m_buffer; // hide copy constructor and operator= AUD_FFMPEGFactory(const AUD_FFMPEGFactory&); @@ -72,7 +72,7 @@ public: */ AUD_FFMPEGFactory(const data_t* buffer, int size); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_FFMPEGFACTORY_H__ diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp index 28a14a9cfc7..0a3d0f8e85a 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp @@ -197,7 +197,7 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(std::string filename) : static const char* streamopen_error = "AUD_FFMPEGReader: Stream couldn't be " "opened."; -AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference buffer) : +AUD_FFMPEGReader::AUD_FFMPEGReader(boost::shared_ptr buffer) : m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1), m_membuffer(buffer), m_membufferpos(0) diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h index 2b354b0b2a1..d5d9fb300ff 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h @@ -32,10 +32,10 @@ #include "AUD_ConverterFunctions.h" #include "AUD_IReader.h" -#include "AUD_Reference.h" #include "AUD_Buffer.h" #include +#include struct AVCodecContext; extern "C" { @@ -99,7 +99,7 @@ private: /** * The memory file to read from. */ - AUD_Reference m_membuffer; + boost::shared_ptr m_membuffer; /** * The buffer to read with. @@ -143,7 +143,7 @@ public: * \exception AUD_Exception Thrown if the buffer specified cannot be read * with ffmpeg. */ - AUD_FFMPEGReader(AUD_Reference buffer); + AUD_FFMPEGReader(boost::shared_ptr buffer); /** * Destroys the reader and closes the file. diff --git a/intern/audaspace/intern/AUD_BufferReader.cpp b/intern/audaspace/intern/AUD_BufferReader.cpp index dbff70095ad..b9d819ff774 100644 --- a/intern/audaspace/intern/AUD_BufferReader.cpp +++ b/intern/audaspace/intern/AUD_BufferReader.cpp @@ -33,7 +33,7 @@ #include -AUD_BufferReader::AUD_BufferReader(AUD_Reference buffer, +AUD_BufferReader::AUD_BufferReader(boost::shared_ptr buffer, AUD_Specs specs) : m_position(0), m_buffer(buffer), m_specs(specs) { diff --git a/intern/audaspace/intern/AUD_BufferReader.h b/intern/audaspace/intern/AUD_BufferReader.h index 0e8c5de9a9d..d0c90ce7e61 100644 --- a/intern/audaspace/intern/AUD_BufferReader.h +++ b/intern/audaspace/intern/AUD_BufferReader.h @@ -31,9 +31,10 @@ #define __AUD_BUFFERREADER_H__ #include "AUD_IReader.h" -#include "AUD_Reference.h" class AUD_Buffer; +#include + /** * This class represents a simple reader from a buffer that exists in memory. * \warning Notice that the buffer used for creating the reader must exist as @@ -50,7 +51,7 @@ private: /** * The buffer that is read. */ - AUD_Reference m_buffer; + boost::shared_ptr m_buffer; /** * The specification of the sample data in the buffer. @@ -67,7 +68,7 @@ public: * \param buffer The buffer to read from. * \param specs The specification of the sample data in the buffer. */ - AUD_BufferReader(AUD_Reference buffer, AUD_Specs specs); + AUD_BufferReader(boost::shared_ptr buffer, AUD_Specs specs); virtual bool isSeekable() const; virtual void seek(int position); diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp index a1da90b073e..3150c1af011 100644 --- a/intern/audaspace/intern/AUD_C-API.cpp +++ b/intern/audaspace/intern/AUD_C-API.cpp @@ -91,10 +91,10 @@ extern "C" { #include -typedef AUD_Reference AUD_Sound; -typedef AUD_Reference AUD_Device; -typedef AUD_Reference AUD_Handle; -typedef AUD_Reference AUD_SEntry; +typedef boost::shared_ptr AUD_Sound; +typedef boost::shared_ptr AUD_Device; +typedef boost::shared_ptr AUD_Handle; +typedef boost::shared_ptr AUD_SEntry; #define AUD_CAPI_IMPLEMENTATION #include "AUD_C-API.h" @@ -103,7 +103,7 @@ typedef AUD_Reference AUD_SEntry; # define NULL (void *)0 #endif -static AUD_Reference AUD_device; +static boost::shared_ptr AUD_device; static AUD_I3DDevice *AUD_3ddevice; void AUD_initOnce() @@ -115,25 +115,25 @@ void AUD_initOnce() int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) { - AUD_Reference dev; + boost::shared_ptr dev; - if (!AUD_device.isNull()) { + if (AUD_device.get()) { AUD_exit(); } try { switch(device) { case AUD_NULL_DEVICE: - dev = new AUD_NULLDevice(); + dev = boost::shared_ptr(new AUD_NULLDevice()); break; #ifdef WITH_SDL case AUD_SDL_DEVICE: - dev = new AUD_SDLDevice(specs, buffersize); + dev = boost::shared_ptr(new AUD_SDLDevice(specs, buffersize)); break; #endif #ifdef WITH_OPENAL case AUD_OPENAL_DEVICE: - dev = new AUD_OpenALDevice(specs, buffersize); + dev = boost::shared_ptr(new AUD_OpenALDevice(specs, buffersize)); break; #endif #ifdef WITH_JACK @@ -147,7 +147,7 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) else { #endif - dev = new AUD_JackDevice("Blender", specs, buffersize); + dev = boost::shared_ptr(new AUD_JackDevice("Blender", specs, buffersize)); break; #ifdef __APPLE__ } @@ -170,17 +170,17 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) void AUD_exit() { - AUD_device = AUD_Reference(); + AUD_device = boost::shared_ptr(); AUD_3ddevice = NULL; } #ifdef WITH_PYTHON static PyObject *AUD_getCDevice(PyObject *self) { - if (!AUD_device.isNull()) { + if (AUD_device.get()) { Device *device = (Device *)Device_empty(); if (device != NULL) { - device->device = new AUD_Reference(AUD_device); + device->device = new boost::shared_ptr(AUD_device); return (PyObject *)device; } } @@ -206,12 +206,12 @@ static PyObject *AUD_getSoundFromPointer(PyObject *self, PyObject *args) if (PyArg_Parse(args, "l:_sound_from_pointer", &lptr)) { if (lptr) { - AUD_Reference* factory = (AUD_Reference*) sound_get_factory((void *) lptr); + boost::shared_ptr* factory = (boost::shared_ptr*) sound_get_factory((void *) lptr); if (factory) { Factory *obj = (Factory *)Factory_empty(); if (obj) { - obj->factory = new AUD_Reference(*factory); + obj->factory = new boost::shared_ptr(*factory); return (PyObject *) obj; } } @@ -246,7 +246,7 @@ void *AUD_getPythonFactory(AUD_Sound *sound) if (sound) { Factory *obj = (Factory *) Factory_empty(); if (obj) { - obj->factory = new AUD_Reference(*sound); + obj->factory = new boost::shared_ptr(*sound); return (PyObject *) obj; } } @@ -261,7 +261,7 @@ AUD_Sound *AUD_getPythonSound(void *sound) if (!factory) return NULL; - return new AUD_Reference(*reinterpret_cast*>(factory->factory)); + return new boost::shared_ptr(*reinterpret_cast*>(factory->factory)); } #endif @@ -286,9 +286,9 @@ AUD_SoundInfo AUD_getInfo(AUD_Sound *sound) info.length = 0.0f; try { - AUD_Reference reader = (*sound)->createReader(); + boost::shared_ptr reader = (*sound)->createReader(); - if (!reader.isNull()) { + if (reader.get()) { info.specs = reader->getSpecs(); info.length = reader->getLength() / (float) info.specs.rate; } @@ -432,7 +432,7 @@ AUD_Handle *AUD_play(AUD_Sound *sound, int keep) assert(sound); try { AUD_Handle handle = AUD_device->play(*sound, keep); - if (!handle.isNull()) { + if (handle.get()) { return new AUD_Handle(handle); } } @@ -552,9 +552,9 @@ int AUD_setDistanceModel(AUD_DistanceModel model) int AUD_setSourceLocation(AUD_Handle *handle, const float location[3]) { assert(handle); - AUD_Reference h(*handle); + boost::shared_ptr h = boost::dynamic_pointer_cast(*handle); - if (!h.isNull()) { + if (h.get()) { AUD_Vector3 v(location[0], location[1], location[2]); return h->setSourceLocation(v); } @@ -565,9 +565,9 @@ int AUD_setSourceLocation(AUD_Handle *handle, const float location[3]) int AUD_setSourceVelocity(AUD_Handle *handle, const float velocity[3]) { assert(handle); - AUD_Reference h(*handle); + boost::shared_ptr h = boost::dynamic_pointer_cast(*handle); - if (!h.isNull()) { + if (h.get()) { AUD_Vector3 v(velocity[0], velocity[1], velocity[2]); return h->setSourceVelocity(v); } @@ -578,9 +578,9 @@ int AUD_setSourceVelocity(AUD_Handle *handle, const float velocity[3]) int AUD_setSourceOrientation(AUD_Handle *handle, const float orientation[4]) { assert(handle); - AUD_Reference h(*handle); + boost::shared_ptr h = boost::dynamic_pointer_cast(*handle); - if (!h.isNull()) { + if (h.get()) { AUD_Quaternion q(orientation[3], orientation[0], orientation[1], orientation[2]); return h->setSourceOrientation(q); } @@ -591,9 +591,9 @@ int AUD_setSourceOrientation(AUD_Handle *handle, const float orientation[4]) int AUD_setRelative(AUD_Handle *handle, int relative) { assert(handle); - AUD_Reference h(*handle); + boost::shared_ptr h = boost::dynamic_pointer_cast(*handle); - if (!h.isNull()) { + if (h.get()) { return h->setRelative(relative); } @@ -603,9 +603,9 @@ int AUD_setRelative(AUD_Handle *handle, int relative) int AUD_setVolumeMaximum(AUD_Handle *handle, float volume) { assert(handle); - AUD_Reference h(*handle); + boost::shared_ptr h = boost::dynamic_pointer_cast(*handle); - if (!h.isNull()) { + if (h.get()) { return h->setVolumeMaximum(volume); } @@ -615,9 +615,9 @@ int AUD_setVolumeMaximum(AUD_Handle *handle, float volume) int AUD_setVolumeMinimum(AUD_Handle *handle, float volume) { assert(handle); - AUD_Reference h(*handle); + boost::shared_ptr h = boost::dynamic_pointer_cast(*handle); - if (!h.isNull()) { + if (h.get()) { return h->setVolumeMinimum(volume); } @@ -627,9 +627,9 @@ int AUD_setVolumeMinimum(AUD_Handle *handle, float volume) int AUD_setDistanceMaximum(AUD_Handle *handle, float distance) { assert(handle); - AUD_Reference h(*handle); + boost::shared_ptr h = boost::dynamic_pointer_cast(*handle); - if (!h.isNull()) { + if (h.get()) { return h->setDistanceMaximum(distance); } @@ -639,9 +639,9 @@ int AUD_setDistanceMaximum(AUD_Handle *handle, float distance) int AUD_setDistanceReference(AUD_Handle *handle, float distance) { assert(handle); - AUD_Reference h(*handle); + boost::shared_ptr h = boost::dynamic_pointer_cast(*handle); - if (!h.isNull()) { + if (h.get()) { return h->setDistanceReference(distance); } @@ -651,9 +651,9 @@ int AUD_setDistanceReference(AUD_Handle *handle, float distance) int AUD_setAttenuation(AUD_Handle *handle, float factor) { assert(handle); - AUD_Reference h(*handle); + boost::shared_ptr h = boost::dynamic_pointer_cast(*handle); - if (!h.isNull()) { + if (h.get()) { return h->setAttenuation(factor); } @@ -663,9 +663,9 @@ int AUD_setAttenuation(AUD_Handle *handle, float factor) int AUD_setConeAngleOuter(AUD_Handle *handle, float angle) { assert(handle); - AUD_Reference h(*handle); + boost::shared_ptr h = boost::dynamic_pointer_cast(*handle); - if (!h.isNull()) { + if (h.get()) { return h->setConeAngleOuter(angle); } @@ -675,9 +675,9 @@ int AUD_setConeAngleOuter(AUD_Handle *handle, float angle) int AUD_setConeAngleInner(AUD_Handle *handle, float angle) { assert(handle); - AUD_Reference h(*handle); + boost::shared_ptr h = boost::dynamic_pointer_cast(*handle); - if (!h.isNull()) { + if (h.get()) { return h->setConeAngleInner(angle); } @@ -687,9 +687,9 @@ int AUD_setConeAngleInner(AUD_Handle *handle, float angle) int AUD_setConeVolumeOuter(AUD_Handle *handle, float volume) { assert(handle); - AUD_Reference h(*handle); + boost::shared_ptr h = boost::dynamic_pointer_cast(*handle); - if (!h.isNull()) { + if (h.get()) { return h->setConeVolumeOuter(volume); } @@ -734,7 +734,7 @@ AUD_Handle *AUD_playDevice(AUD_Device *device, AUD_Sound *sound, float seek) try { AUD_Handle handle = (*device)->play(*sound); - if (!handle.isNull()) { + if (handle.get()) { handle->seek(seek); return new AUD_Handle(handle); } @@ -793,38 +793,38 @@ float *AUD_readSoundBuffer(const char *filename, float low, float high, AUD_DeviceSpecs specs; specs.channels = AUD_CHANNELS_MONO; specs.rate = (AUD_SampleRate)samplerate; - AUD_Reference sound; + boost::shared_ptr sound; - AUD_Reference file = new AUD_FileFactory(filename); + boost::shared_ptr file = boost::shared_ptr(new AUD_FileFactory(filename)); int position = 0; try { - AUD_Reference reader = file->createReader(); + boost::shared_ptr reader = file->createReader(); AUD_SampleRate rate = reader->getSpecs().rate; - sound = new AUD_ChannelMapperFactory(file, specs); + sound = boost::shared_ptr(new AUD_ChannelMapperFactory(file, specs)); if (high < rate) - sound = new AUD_LowpassFactory(sound, high); + sound = boost::shared_ptr(new AUD_LowpassFactory(sound, high)); if (low > 0) - sound = new AUD_HighpassFactory(sound, low); + sound = boost::shared_ptr(new AUD_HighpassFactory(sound, low)); - sound = new AUD_EnvelopeFactory(sound, attack, release, threshold, 0.1f); - sound = new AUD_LinearResampleFactory(sound, specs); + sound = boost::shared_ptr(new AUD_EnvelopeFactory(sound, attack, release, threshold, 0.1f)); + sound = boost::shared_ptr(new AUD_LinearResampleFactory(sound, specs)); if (square) - sound = new AUD_SquareFactory(sound, sthreshold); + sound = boost::shared_ptr(new AUD_SquareFactory(sound, sthreshold)); if (accumulate) - sound = new AUD_AccumulatorFactory(sound, additive); + sound = boost::shared_ptr(new AUD_AccumulatorFactory(sound, additive)); else if (additive) - sound = new AUD_SumFactory(sound); + sound = boost::shared_ptr(new AUD_SumFactory(sound)); reader = sound->createReader(); - if (reader.isNull()) + if (!reader.get()) return NULL; int len; @@ -856,14 +856,14 @@ static void pauseSound(AUD_Handle *handle) AUD_Handle *AUD_pauseAfter(AUD_Handle *handle, float seconds) { - AUD_Reference silence = new AUD_SilenceFactory; - AUD_Reference limiter = new AUD_LimiterFactory(silence, 0, seconds); + boost::shared_ptr silence = boost::shared_ptr(new AUD_SilenceFactory); + boost::shared_ptr limiter = boost::shared_ptr(new AUD_LimiterFactory(silence, 0, seconds)); AUD_MutexLock lock(*AUD_device); try { AUD_Handle handle2 = AUD_device->play(limiter); - if (!handle2.isNull()) { + if (handle2.get()) { handle2->setStopCallback((stopCallback)pauseSound, handle); return new AUD_Handle(handle2); } @@ -881,7 +881,7 @@ AUD_Sound *AUD_createSequencer(float fps, int muted) AUD_Specs specs; specs.channels = AUD_CHANNELS_STEREO; specs.rate = AUD_RATE_44100; - AUD_Sound *sequencer = new AUD_Sound(AUD_Reference(new AUD_SequencerFactory(specs, fps, muted))); + AUD_Sound *sequencer = new AUD_Sound(boost::shared_ptr(new AUD_SequencerFactory(specs, fps, muted))); return sequencer; } @@ -1070,7 +1070,7 @@ int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_pe specs.channels = AUD_CHANNELS_MONO; specs.format = AUD_FORMAT_INVALID; - AUD_Reference reader = AUD_ChannelMapperFactory(*sound, specs).createReader(); + boost::shared_ptr reader = AUD_ChannelMapperFactory(*sound, specs).createReader(); specs.specs = reader->getSpecs(); int len; @@ -1124,7 +1124,7 @@ int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_pe AUD_Sound *AUD_copy(AUD_Sound *sound) { - return new AUD_Reference(*sound); + return new boost::shared_ptr(*sound); } void AUD_freeHandle(AUD_Handle *handle) @@ -1176,9 +1176,9 @@ const char *AUD_mixdown(AUD_Sound *sound, unsigned int start, unsigned int lengt AUD_SequencerFactory *f = dynamic_cast(sound->get()); f->setSpecs(specs.specs); - AUD_Reference reader = f->createQualityReader(); + boost::shared_ptr reader = f->createQualityReader(); reader->seek(start); - AUD_Reference writer = AUD_FileWriter::createWriter(filename, specs, format, codec, bitrate); + boost::shared_ptr writer = AUD_FileWriter::createWriter(filename, specs, format, codec, bitrate); AUD_FileWriter::writeReader(reader, writer, length, buffersize); return NULL; @@ -1196,7 +1196,7 @@ const char *AUD_mixdown_per_channel(AUD_Sound *sound, unsigned int start, unsign f->setSpecs(specs.specs); - std::vector > writers; + std::vector > writers; int channels = specs.channels; specs.channels = AUD_CHANNELS_MONO; @@ -1220,7 +1220,7 @@ const char *AUD_mixdown_per_channel(AUD_Sound *sound, unsigned int start, unsign writers.push_back(AUD_FileWriter::createWriter(stream.str(), specs, format, codec, bitrate)); } - AUD_Reference reader = f->createQualityReader(); + boost::shared_ptr reader = f->createQualityReader(); reader->seek(start); AUD_FileWriter::writeReader(reader, writers, length, buffersize); @@ -1242,7 +1242,7 @@ AUD_Device *AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound *sequencer, f dynamic_cast(sequencer->get())->setSpecs(specs.specs); AUD_Handle handle = device->play(*sequencer); - if (!handle.isNull()) { + if (handle.get()) { handle->seek(start); } @@ -1254,7 +1254,7 @@ AUD_Device *AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound *sequencer, f } } -AUD_Reference AUD_getDevice() +boost::shared_ptr AUD_getDevice() { return AUD_device; } diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h index 75e3456de9a..9c6611fe04a 100644 --- a/intern/audaspace/intern/AUD_C-API.h +++ b/intern/audaspace/intern/AUD_C-API.h @@ -755,7 +755,7 @@ extern AUD_Sound *AUD_getPythonSound(void *sound); #ifdef __cplusplus } -#include "AUD_Reference.h" +#include class AUD_IDevice; class AUD_I3DDevice; @@ -763,7 +763,7 @@ class AUD_I3DDevice; * Returns the current playback device. * \return The playback device. */ -AUD_Reference AUD_getDevice(); +boost::shared_ptr AUD_getDevice(); /** * Returns the current playback 3D device. diff --git a/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp b/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp index 7743ccf46da..f4ba5d05ff0 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp +++ b/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp @@ -32,14 +32,14 @@ #include -AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_Reference factory, +AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(boost::shared_ptr factory, AUD_DeviceSpecs specs) : AUD_MixerFactory(factory, specs) { } -AUD_Reference AUD_ChannelMapperFactory::createReader() +boost::shared_ptr AUD_ChannelMapperFactory::createReader() { - AUD_Reference reader = getReader(); - return new AUD_ChannelMapperReader(reader, m_specs.channels); + boost::shared_ptr reader = getReader(); + return boost::shared_ptr(new AUD_ChannelMapperReader(reader, m_specs.channels)); } diff --git a/intern/audaspace/intern/AUD_ChannelMapperFactory.h b/intern/audaspace/intern/AUD_ChannelMapperFactory.h index b60a32d5510..611b5041c39 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperFactory.h +++ b/intern/audaspace/intern/AUD_ChannelMapperFactory.h @@ -49,9 +49,9 @@ public: * \param factory The input factory. * \param specs The target specifications. */ - AUD_ChannelMapperFactory(AUD_Reference factory, AUD_DeviceSpecs specs); + AUD_ChannelMapperFactory(boost::shared_ptr factory, AUD_DeviceSpecs specs); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_CHANNELMAPPERFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp index 7a179c6f94a..8b983d5c43d 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp +++ b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp @@ -38,7 +38,7 @@ #include "AUD_ChannelMapperReader.h" -AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_Reference reader, +AUD_ChannelMapperReader::AUD_ChannelMapperReader(boost::shared_ptr reader, AUD_Channels channels) : AUD_EffectReader(reader), m_target_channels(channels), m_source_channels(AUD_CHANNELS_INVALID), m_mapping(0), m_map_size(0), m_mono_angle(0) diff --git a/intern/audaspace/intern/AUD_ChannelMapperReader.h b/intern/audaspace/intern/AUD_ChannelMapperReader.h index 32adb058115..b122b070d29 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperReader.h +++ b/intern/audaspace/intern/AUD_ChannelMapperReader.h @@ -110,7 +110,7 @@ public: * \param reader The reader to map. * \param mapping The mapping specification as two dimensional float array. */ - AUD_ChannelMapperReader(AUD_Reference reader, AUD_Channels channels); + AUD_ChannelMapperReader(boost::shared_ptr reader, AUD_Channels channels); /** * Destroys the reader. diff --git a/intern/audaspace/intern/AUD_ConverterFactory.cpp b/intern/audaspace/intern/AUD_ConverterFactory.cpp index b61f9bc194c..7cbf64f1697 100644 --- a/intern/audaspace/intern/AUD_ConverterFactory.cpp +++ b/intern/audaspace/intern/AUD_ConverterFactory.cpp @@ -30,18 +30,18 @@ #include "AUD_ConverterFactory.h" #include "AUD_ConverterReader.h" -AUD_ConverterFactory::AUD_ConverterFactory(AUD_Reference factory, +AUD_ConverterFactory::AUD_ConverterFactory(boost::shared_ptr factory, AUD_DeviceSpecs specs) : AUD_MixerFactory(factory, specs) { } -AUD_Reference AUD_ConverterFactory::createReader() +boost::shared_ptr AUD_ConverterFactory::createReader() { - AUD_Reference reader = getReader(); + boost::shared_ptr reader = getReader(); if(m_specs.format != AUD_FORMAT_FLOAT32) - reader = new AUD_ConverterReader(reader, m_specs); + reader = boost::shared_ptr(new AUD_ConverterReader(reader, m_specs)); return reader; } diff --git a/intern/audaspace/intern/AUD_ConverterFactory.h b/intern/audaspace/intern/AUD_ConverterFactory.h index 3211b607517..2c9c82d235b 100644 --- a/intern/audaspace/intern/AUD_ConverterFactory.h +++ b/intern/audaspace/intern/AUD_ConverterFactory.h @@ -49,9 +49,9 @@ public: * \param factory The input factory. * \param specs The target specifications. */ - AUD_ConverterFactory(AUD_Reference factory, AUD_DeviceSpecs specs); + AUD_ConverterFactory(boost::shared_ptr factory, AUD_DeviceSpecs specs); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_CONVERTERFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_ConverterReader.cpp b/intern/audaspace/intern/AUD_ConverterReader.cpp index 63178f316b2..a90a54670e8 100644 --- a/intern/audaspace/intern/AUD_ConverterReader.cpp +++ b/intern/audaspace/intern/AUD_ConverterReader.cpp @@ -29,7 +29,7 @@ #include "AUD_ConverterReader.h" -AUD_ConverterReader::AUD_ConverterReader(AUD_Reference reader, +AUD_ConverterReader::AUD_ConverterReader(boost::shared_ptr reader, AUD_DeviceSpecs specs) : AUD_EffectReader(reader), m_format(specs.format) diff --git a/intern/audaspace/intern/AUD_ConverterReader.h b/intern/audaspace/intern/AUD_ConverterReader.h index 2dedbd89180..987b7c70279 100644 --- a/intern/audaspace/intern/AUD_ConverterReader.h +++ b/intern/audaspace/intern/AUD_ConverterReader.h @@ -65,7 +65,7 @@ public: * \param reader The reader to convert. * \param specs The target specification. */ - AUD_ConverterReader(AUD_Reference reader, AUD_DeviceSpecs specs); + AUD_ConverterReader(boost::shared_ptr reader, AUD_DeviceSpecs specs); virtual void read(int& length, bool& eos, sample_t* buffer); }; diff --git a/intern/audaspace/intern/AUD_FileFactory.cpp b/intern/audaspace/intern/AUD_FileFactory.cpp index a27acff19cf..f9353db6677 100644 --- a/intern/audaspace/intern/AUD_FileFactory.cpp +++ b/intern/audaspace/intern/AUD_FileFactory.cpp @@ -56,15 +56,15 @@ AUD_FileFactory::AUD_FileFactory(const data_t* buffer, int size) : static const char* read_error = "AUD_FileFactory: File couldn't be read."; -AUD_Reference AUD_FileFactory::createReader() +boost::shared_ptr AUD_FileFactory::createReader() { #ifdef WITH_SNDFILE try { - if(m_buffer.isNull()) - return new AUD_SndFileReader(m_filename); + if(m_buffer.get()) + return boost::shared_ptr(new AUD_SndFileReader(m_buffer)); else - return new AUD_SndFileReader(m_buffer); + return boost::shared_ptr(new AUD_SndFileReader(m_filename)); } catch(AUD_Exception&) {} #endif @@ -72,10 +72,10 @@ AUD_Reference AUD_FileFactory::createReader() #ifdef WITH_FFMPEG try { - if(m_buffer.isNull()) - return new AUD_FFMPEGReader(m_filename); + if(m_buffer.get()) + return boost::shared_ptr(new AUD_FFMPEGReader(m_buffer)); else - return new AUD_FFMPEGReader(m_buffer); + return boost::shared_ptr(new AUD_FFMPEGReader(m_filename)); } catch(AUD_Exception&) {} #endif diff --git a/intern/audaspace/intern/AUD_FileFactory.h b/intern/audaspace/intern/AUD_FileFactory.h index 4ea4a9392e9..35c8db731b4 100644 --- a/intern/audaspace/intern/AUD_FileFactory.h +++ b/intern/audaspace/intern/AUD_FileFactory.h @@ -31,10 +31,10 @@ #define __AUD_FILEFACTORY_H__ #include "AUD_IFactory.h" -#include "AUD_Reference.h" #include "AUD_Buffer.h" #include +#include /** * This factory tries to read a sound file via all available file readers. @@ -50,7 +50,7 @@ private: /** * The buffer to read from. */ - AUD_Reference m_buffer; + boost::shared_ptr m_buffer; // hide copy constructor and operator= AUD_FileFactory(const AUD_FileFactory&); @@ -70,7 +70,7 @@ public: */ AUD_FileFactory(const data_t* buffer, int size); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_FILEFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_FileWriter.cpp b/intern/audaspace/intern/AUD_FileWriter.cpp index f74021acad1..e3072fa82e0 100644 --- a/intern/audaspace/intern/AUD_FileWriter.cpp +++ b/intern/audaspace/intern/AUD_FileWriter.cpp @@ -43,13 +43,13 @@ static const char* write_error = "AUD_FileWriter: File couldn't be written."; -AUD_Reference AUD_FileWriter::createWriter(std::string filename,AUD_DeviceSpecs specs, +boost::shared_ptr AUD_FileWriter::createWriter(std::string filename,AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate) { #ifdef WITH_SNDFILE try { - return new AUD_SndFileWriter(filename, specs, format, codec, bitrate); + return boost::shared_ptr(new AUD_SndFileWriter(filename, specs, format, codec, bitrate)); } catch(AUD_Exception&) {} #endif @@ -57,7 +57,7 @@ AUD_Reference AUD_FileWriter::createWriter(std::string filename,AUD #ifdef WITH_FFMPEG try { - return new AUD_FFMPEGWriter(filename, specs, format, codec, bitrate); + return boost::shared_ptr(new AUD_FFMPEGWriter(filename, specs, format, codec, bitrate)); } catch(AUD_Exception&) {} #endif @@ -65,7 +65,7 @@ AUD_Reference AUD_FileWriter::createWriter(std::string filename,AUD AUD_THROW(AUD_ERROR_SPECS, write_error); } -void AUD_FileWriter::writeReader(AUD_Reference reader, AUD_Reference writer, unsigned int length, unsigned int buffersize) +void AUD_FileWriter::writeReader(boost::shared_ptr reader, boost::shared_ptr writer, unsigned int length, unsigned int buffersize) { AUD_Buffer buffer(buffersize * AUD_SAMPLE_SIZE(writer->getSpecs())); sample_t* buf = buffer.getBuffer(); @@ -94,7 +94,7 @@ void AUD_FileWriter::writeReader(AUD_Reference reader, AUD_Referenc } } -void AUD_FileWriter::writeReader(AUD_Reference reader, std::vector >& writers, unsigned int length, unsigned int buffersize) +void AUD_FileWriter::writeReader(boost::shared_ptr reader, std::vector >& writers, unsigned int length, unsigned int buffersize) { AUD_Buffer buffer(buffersize * AUD_SAMPLE_SIZE(reader->getSpecs())); AUD_Buffer buffer2(buffersize * sizeof(sample_t)); diff --git a/intern/audaspace/intern/AUD_FileWriter.h b/intern/audaspace/intern/AUD_FileWriter.h index 385aba5ef45..da52c7e0fb2 100644 --- a/intern/audaspace/intern/AUD_FileWriter.h +++ b/intern/audaspace/intern/AUD_FileWriter.h @@ -32,8 +32,7 @@ #include #include - -#include "AUD_Reference.h" +#include #include "AUD_IWriter.h" #include "AUD_IReader.h" @@ -59,7 +58,7 @@ public: * \param bitrate The bitrate for encoding. * \return The writer to write data to. */ - static AUD_Reference createWriter(std::string filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate); + static boost::shared_ptr createWriter(std::string filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate); /** * Writes a reader to a writer. @@ -68,7 +67,7 @@ public: * \param length How many samples should be transfered. * \param buffersize How many samples should be transfered at once. */ - static void writeReader(AUD_Reference reader, AUD_Reference writer, unsigned int length, unsigned int buffersize); + static void writeReader(boost::shared_ptr reader, boost::shared_ptr writer, unsigned int length, unsigned int buffersize); /** * Writes a reader to several writers. @@ -77,7 +76,7 @@ public: * \param length How many samples should be transfered. * \param buffersize How many samples should be transfered at once. */ - static void writeReader(AUD_Reference reader, std::vector >& writers, unsigned int length, unsigned int buffersize); + static void writeReader(boost::shared_ptr reader, std::vector >& writers, unsigned int length, unsigned int buffersize); }; #endif //__AUD_FILEWRITER_H__ diff --git a/intern/audaspace/intern/AUD_IDevice.h b/intern/audaspace/intern/AUD_IDevice.h index f4d6635e79a..a7f9a985ce4 100644 --- a/intern/audaspace/intern/AUD_IDevice.h +++ b/intern/audaspace/intern/AUD_IDevice.h @@ -31,12 +31,13 @@ #define __AUD_IDEVICE_H__ #include "AUD_Space.h" -#include "AUD_Reference.h" #include "AUD_IFactory.h" #include "AUD_IReader.h" #include "AUD_IHandle.h" #include "AUD_ILockable.h" +#include + /** * This class represents an output device for sound sources. * Output devices may be several backends such as plattform independand like @@ -68,7 +69,7 @@ public: * \exception AUD_Exception Thrown if there's an unexpected (from the * device side) error during creation of the reader. */ - virtual AUD_Reference play(AUD_Reference reader, bool keep = false)=0; + virtual boost::shared_ptr play(boost::shared_ptr reader, bool keep = false)=0; /** * Plays a sound source. @@ -80,7 +81,7 @@ public: * \exception AUD_Exception Thrown if there's an unexpected (from the * device side) error during creation of the reader. */ - virtual AUD_Reference play(AUD_Reference factory, bool keep = false)=0; + virtual boost::shared_ptr play(boost::shared_ptr factory, bool keep = false)=0; /** * Stops all playing sounds. diff --git a/intern/audaspace/intern/AUD_IFactory.h b/intern/audaspace/intern/AUD_IFactory.h index 95b4643072e..75103963c68 100644 --- a/intern/audaspace/intern/AUD_IFactory.h +++ b/intern/audaspace/intern/AUD_IFactory.h @@ -31,9 +31,10 @@ #define __AUD_IFACTORY_H__ #include "AUD_Space.h" -#include "AUD_Reference.h" #include "AUD_IReader.h" +#include + /** * This class represents a type of sound source and saves the necessary values * for it. It is able to create a reader that is actually usable for playback @@ -54,7 +55,7 @@ public: * \exception AUD_Exception An exception may be thrown if there has been * a more unexpected error during reader creation. */ - virtual AUD_Reference createReader()=0; + virtual boost::shared_ptr createReader()=0; }; #endif //__AUD_IFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_JOSResampleFactory.cpp b/intern/audaspace/intern/AUD_JOSResampleFactory.cpp index 21aae6b0547..188960f986f 100644 --- a/intern/audaspace/intern/AUD_JOSResampleFactory.cpp +++ b/intern/audaspace/intern/AUD_JOSResampleFactory.cpp @@ -30,13 +30,13 @@ #include "AUD_JOSResampleFactory.h" #include "AUD_JOSResampleReader.h" -AUD_JOSResampleFactory::AUD_JOSResampleFactory(AUD_Reference factory, +AUD_JOSResampleFactory::AUD_JOSResampleFactory(boost::shared_ptr factory, AUD_DeviceSpecs specs) : AUD_MixerFactory(factory, specs) { } -AUD_Reference AUD_JOSResampleFactory::createReader() +boost::shared_ptr AUD_JOSResampleFactory::createReader() { - return new AUD_JOSResampleReader(getReader(), m_specs.specs); + return boost::shared_ptr(new AUD_JOSResampleReader(getReader(), m_specs.specs)); } diff --git a/intern/audaspace/intern/AUD_JOSResampleFactory.h b/intern/audaspace/intern/AUD_JOSResampleFactory.h index 6d18150d852..b6c2961c88a 100644 --- a/intern/audaspace/intern/AUD_JOSResampleFactory.h +++ b/intern/audaspace/intern/AUD_JOSResampleFactory.h @@ -48,9 +48,9 @@ public: * \param factory The input factory. * \param specs The target specifications. */ - AUD_JOSResampleFactory(AUD_Reference factory, AUD_DeviceSpecs specs); + AUD_JOSResampleFactory(boost::shared_ptr factory, AUD_DeviceSpecs specs); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_JOSRESAMPLEFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_JOSResampleReader.cpp b/intern/audaspace/intern/AUD_JOSResampleReader.cpp index 0f7a038c88e..62fab48272b 100644 --- a/intern/audaspace/intern/AUD_JOSResampleReader.cpp +++ b/intern/audaspace/intern/AUD_JOSResampleReader.cpp @@ -68,7 +68,7 @@ static inline int lrint(double d) #define fp_rest(x) (x & ((1 << SHIFT_BITS) - 1)) #define fp_rest_to_double(x) fp_to_double(fp_rest(x)) -AUD_JOSResampleReader::AUD_JOSResampleReader(AUD_Reference reader, AUD_Specs specs) : +AUD_JOSResampleReader::AUD_JOSResampleReader(boost::shared_ptr reader, AUD_Specs specs) : AUD_ResampleReader(reader, specs.rate), m_channels(AUD_CHANNELS_INVALID), m_n(0), diff --git a/intern/audaspace/intern/AUD_JOSResampleReader.h b/intern/audaspace/intern/AUD_JOSResampleReader.h index 94524c1db3e..fb68e4dc9f5 100644 --- a/intern/audaspace/intern/AUD_JOSResampleReader.h +++ b/intern/audaspace/intern/AUD_JOSResampleReader.h @@ -123,7 +123,7 @@ public: * \param reader The reader to mix. * \param specs The target specification. */ - AUD_JOSResampleReader(AUD_Reference reader, AUD_Specs specs); + AUD_JOSResampleReader(boost::shared_ptr reader, AUD_Specs specs); virtual void seek(int position); virtual int getLength() const; diff --git a/intern/audaspace/intern/AUD_LinearResampleFactory.cpp b/intern/audaspace/intern/AUD_LinearResampleFactory.cpp index 7f602599b7a..cd573f1047c 100644 --- a/intern/audaspace/intern/AUD_LinearResampleFactory.cpp +++ b/intern/audaspace/intern/AUD_LinearResampleFactory.cpp @@ -30,13 +30,13 @@ #include "AUD_LinearResampleFactory.h" #include "AUD_LinearResampleReader.h" -AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_Reference factory, +AUD_LinearResampleFactory::AUD_LinearResampleFactory(boost::shared_ptr factory, AUD_DeviceSpecs specs) : AUD_MixerFactory(factory, specs) { } -AUD_Reference AUD_LinearResampleFactory::createReader() +boost::shared_ptr AUD_LinearResampleFactory::createReader() { - return new AUD_LinearResampleReader(getReader(), m_specs.specs); + return boost::shared_ptr(new AUD_LinearResampleReader(getReader(), m_specs.specs)); } diff --git a/intern/audaspace/intern/AUD_LinearResampleFactory.h b/intern/audaspace/intern/AUD_LinearResampleFactory.h index 7d9efa01d2d..ceb29ef2edd 100644 --- a/intern/audaspace/intern/AUD_LinearResampleFactory.h +++ b/intern/audaspace/intern/AUD_LinearResampleFactory.h @@ -48,9 +48,9 @@ public: * \param factory The input factory. * \param specs The target specifications. */ - AUD_LinearResampleFactory(AUD_Reference factory, AUD_DeviceSpecs specs); + AUD_LinearResampleFactory(boost::shared_ptr factory, AUD_DeviceSpecs specs); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_LINEARRESAMPLEFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_LinearResampleReader.cpp b/intern/audaspace/intern/AUD_LinearResampleReader.cpp index aff62d7c3aa..6aa0faed863 100644 --- a/intern/audaspace/intern/AUD_LinearResampleReader.cpp +++ b/intern/audaspace/intern/AUD_LinearResampleReader.cpp @@ -34,7 +34,7 @@ #define CC m_channels + channel -AUD_LinearResampleReader::AUD_LinearResampleReader(AUD_Reference reader, +AUD_LinearResampleReader::AUD_LinearResampleReader(boost::shared_ptr reader, AUD_Specs specs) : AUD_ResampleReader(reader, specs.rate), m_channels(reader->getSpecs().channels), diff --git a/intern/audaspace/intern/AUD_LinearResampleReader.h b/intern/audaspace/intern/AUD_LinearResampleReader.h index 4f6d422f772..9beea251c07 100644 --- a/intern/audaspace/intern/AUD_LinearResampleReader.h +++ b/intern/audaspace/intern/AUD_LinearResampleReader.h @@ -74,7 +74,7 @@ public: * \param reader The reader to mix. * \param specs The target specification. */ - AUD_LinearResampleReader(AUD_Reference reader, AUD_Specs specs); + AUD_LinearResampleReader(boost::shared_ptr reader, AUD_Specs specs); virtual void seek(int position); virtual int getLength() const; diff --git a/intern/audaspace/intern/AUD_Mixer.h b/intern/audaspace/intern/AUD_Mixer.h index 0de9b7fc7dc..3dd03b0a3fe 100644 --- a/intern/audaspace/intern/AUD_Mixer.h +++ b/intern/audaspace/intern/AUD_Mixer.h @@ -32,9 +32,10 @@ #include "AUD_ConverterFunctions.h" #include "AUD_Buffer.h" -#include "AUD_Reference.h" class AUD_IReader; +#include + /** * This abstract class is able to mix audiosignals with same channel count * and sample rate and convert it to a specific output format. diff --git a/intern/audaspace/intern/AUD_MixerFactory.cpp b/intern/audaspace/intern/AUD_MixerFactory.cpp index 95a7291d3eb..f3f00ea2cb6 100644 --- a/intern/audaspace/intern/AUD_MixerFactory.cpp +++ b/intern/audaspace/intern/AUD_MixerFactory.cpp @@ -30,12 +30,12 @@ #include "AUD_MixerFactory.h" #include "AUD_IReader.h" -AUD_Reference AUD_MixerFactory::getReader() const +boost::shared_ptr AUD_MixerFactory::getReader() const { return m_factory->createReader(); } -AUD_MixerFactory::AUD_MixerFactory(AUD_Reference factory, +AUD_MixerFactory::AUD_MixerFactory(boost::shared_ptr factory, AUD_DeviceSpecs specs) : m_specs(specs), m_factory(factory) { @@ -46,7 +46,7 @@ AUD_DeviceSpecs AUD_MixerFactory::getSpecs() const return m_specs; } -AUD_Reference AUD_MixerFactory::getFactory() const +boost::shared_ptr AUD_MixerFactory::getFactory() const { return m_factory; } diff --git a/intern/audaspace/intern/AUD_MixerFactory.h b/intern/audaspace/intern/AUD_MixerFactory.h index d65eb8ef6ae..1d2b6a4cc91 100644 --- a/intern/audaspace/intern/AUD_MixerFactory.h +++ b/intern/audaspace/intern/AUD_MixerFactory.h @@ -46,7 +46,7 @@ protected: /** * If there is no reader it is created out of this factory. */ - AUD_Reference m_factory; + boost::shared_ptr m_factory; /** * Returns the reader created out of the factory. @@ -54,7 +54,7 @@ protected: * classes. * \return The reader to mix. */ - AUD_Reference getReader() const; + boost::shared_ptr getReader() const; public: /** @@ -62,7 +62,7 @@ public: * \param factory The factory to create the readers to mix out of. * \param specs The target specification. */ - AUD_MixerFactory(AUD_Reference factory, AUD_DeviceSpecs specs); + AUD_MixerFactory(boost::shared_ptr factory, AUD_DeviceSpecs specs); /** * Returns the target specification for resampling. @@ -73,7 +73,7 @@ public: * Returns the saved factory. * \return The factory. */ - AUD_Reference getFactory() const; + boost::shared_ptr getFactory() const; }; #endif //__AUD_MIXERFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_NULLDevice.cpp b/intern/audaspace/intern/AUD_NULLDevice.cpp index f390971c686..98a0d324c61 100644 --- a/intern/audaspace/intern/AUD_NULLDevice.cpp +++ b/intern/audaspace/intern/AUD_NULLDevice.cpp @@ -127,14 +127,14 @@ AUD_DeviceSpecs AUD_NULLDevice::getSpecs() const return specs; } -AUD_Reference AUD_NULLDevice::play(AUD_Reference reader, bool keep) +boost::shared_ptr AUD_NULLDevice::play(boost::shared_ptr reader, bool keep) { - return new AUD_NULLHandle(); + return boost::shared_ptr(new AUD_NULLHandle()); } -AUD_Reference AUD_NULLDevice::play(AUD_Reference factory, bool keep) +boost::shared_ptr AUD_NULLDevice::play(boost::shared_ptr factory, bool keep) { - return new AUD_NULLHandle(); + return boost::shared_ptr(new AUD_NULLHandle()); } void AUD_NULLDevice::stopAll() diff --git a/intern/audaspace/intern/AUD_NULLDevice.h b/intern/audaspace/intern/AUD_NULLDevice.h index ee97b151ebe..ae1435bbeea 100644 --- a/intern/audaspace/intern/AUD_NULLDevice.h +++ b/intern/audaspace/intern/AUD_NULLDevice.h @@ -72,8 +72,8 @@ public: virtual ~AUD_NULLDevice(); virtual AUD_DeviceSpecs getSpecs() const; - virtual AUD_Reference play(AUD_Reference reader, bool keep = false); - virtual AUD_Reference play(AUD_Reference factory, bool keep = false); + virtual boost::shared_ptr play(boost::shared_ptr reader, bool keep = false); + virtual boost::shared_ptr play(boost::shared_ptr factory, bool keep = false); virtual void stopAll(); virtual void lock(); virtual void unlock(); diff --git a/intern/audaspace/intern/AUD_Reference.h b/intern/audaspace/intern/AUD_Reference.h deleted file mode 100644 index 5a1aa947148..00000000000 --- a/intern/audaspace/intern/AUD_Reference.h +++ /dev/null @@ -1,275 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * Copyright 2009-2011 Jörg Hermann Müller - * - * This file is part of AudaSpace. - * - * Audaspace 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. - * - * AudaSpace 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 Audaspace; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file audaspace/intern/AUD_Reference.h - * \ingroup audaspaceintern - */ - -#ifndef __AUD_REFERENCE_H__ -#define __AUD_REFERENCE_H__ - -#include -#include -#include - -// #define MEM_DEBUG - -#ifdef MEM_DEBUG -#include -#include -#endif - -/** - * This class handles the reference counting. - */ -class AUD_ReferenceHandler -{ -private: - /** - * Saves the reference counts. - */ - static std::map m_references; - static pthread_mutex_t m_mutex; - static bool m_mutex_initialised; - -public: - - static pthread_mutex_t* getMutex(); - - /** - * Reference increment. - * \param reference The reference. - */ - static inline void incref(void* reference) - { - if(!reference) - return; - - std::map::iterator result = m_references.find(reference); - if(result != m_references.end()) - { - m_references[reference]++; - } - else - { - m_references[reference] = 1; - } - } - - /** - * Reference decrement. - * \param reference The reference. - * \return Whether the reference has to be deleted. - */ - static inline bool decref(void* reference) - { - if(!reference) - return false; - - if(!--m_references[reference]) - { - m_references.erase(reference); - return true; - } - return false; - } -}; - -template -/** - * This class provides reference counting functionality. - */ -class AUD_Reference -{ -private: - /// The reference. - T* m_reference; - void* m_original; -public: - /** - * Creates a new reference counter. - * \param reference The reference. - */ - template - AUD_Reference(U* reference) - { - pthread_mutex_lock(AUD_ReferenceHandler::getMutex()); - m_original = reference; - m_reference = dynamic_cast(reference); - AUD_ReferenceHandler::incref(m_original); -#ifdef MEM_DEBUG - if(m_reference != NULL) - std::cerr << "+" << typeid(*m_reference).name() << std::endl; -#endif - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); - } - - AUD_Reference() - { - m_original = NULL; - m_reference = NULL; - } - - /** - * Copies an AUD_Reference object. - * \param ref The AUD_Reference object to copy. - */ - AUD_Reference(const AUD_Reference& ref) - { - pthread_mutex_lock(AUD_ReferenceHandler::getMutex()); - m_original = ref.m_original; - m_reference = ref.m_reference; - AUD_ReferenceHandler::incref(m_original); -#ifdef MEM_DEBUG - if(m_reference != NULL) - std::cerr << "+" << typeid(*m_reference).name() << std::endl; -#endif - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); - } - - template - explicit AUD_Reference(const AUD_Reference& ref) - { - pthread_mutex_lock(AUD_ReferenceHandler::getMutex()); - m_original = ref.get(); - m_reference = dynamic_cast(ref.get()); - AUD_ReferenceHandler::incref(m_original); -#ifdef MEM_DEBUG - if(m_reference != NULL) - std::cerr << "+" << typeid(*m_reference).name() << std::endl; -#endif - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); - } - - /** - * Destroys a AUD_Reference object, if there's no furthere reference on the - * reference, it is destroyed as well. - */ - ~AUD_Reference() - { - pthread_mutex_lock(AUD_ReferenceHandler::getMutex()); -#ifdef MEM_DEBUG - if(m_reference != NULL) - std::cerr << "-" << typeid(*m_reference).name() << std::endl; -#endif - if(AUD_ReferenceHandler::decref(m_original)) - { - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); - delete m_reference; - } - else - { - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); - } - } - - /** - * Assigns an AUD_Reference to this object. - * \param ref The AUD_Reference object to assign. - */ - AUD_Reference& operator=(const AUD_Reference& ref) - { - if(&ref == this) - return *this; - - pthread_mutex_lock(AUD_ReferenceHandler::getMutex()); - -#ifdef MEM_DEBUG - if(m_reference != NULL) - std::cerr << "-" << typeid(*m_reference).name() << std::endl; -#endif - if(AUD_ReferenceHandler::decref(m_original)) - { - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); - delete m_reference; - pthread_mutex_lock(AUD_ReferenceHandler::getMutex()); - } - - m_original = ref.m_original; - m_reference = ref.m_reference; - AUD_ReferenceHandler::incref(m_original); -#ifdef MEM_DEBUG - if(m_reference != NULL) - std::cerr << "+" << typeid(*m_reference).name() << std::endl; -#endif - - pthread_mutex_unlock(AUD_ReferenceHandler::getMutex()); - - return *this; - } - - /** - * Returns whether the reference is NULL. - */ - inline bool isNull() const - { - return m_reference == NULL; - } - - /** - * Returns the reference. - */ - inline T* get() const - { - return m_reference; - } - - /** - * Returns the original pointer. - */ - inline void* getOriginal() const - { - return m_original; - } - - /** - * Returns the reference. - */ - inline T& operator*() const - { - return *m_reference; - } - - /** - * Returns the reference. - */ - inline T* operator->() const - { - return m_reference; - } -}; - -template -inline bool operator==(const AUD_Reference& a, const AUD_Reference& b) -{ - return a.getOriginal() == b.getOriginal(); -} - -template -inline bool operator!=(const AUD_Reference& a, const AUD_Reference& b) -{ - return a.getOriginal() != b.getOriginal(); -} - -#endif // __AUD_REFERENCE_H__ diff --git a/intern/audaspace/intern/AUD_ResampleReader.cpp b/intern/audaspace/intern/AUD_ResampleReader.cpp index 514d790be09..4b247ffd862 100644 --- a/intern/audaspace/intern/AUD_ResampleReader.cpp +++ b/intern/audaspace/intern/AUD_ResampleReader.cpp @@ -29,7 +29,7 @@ #include "AUD_ResampleReader.h" -AUD_ResampleReader::AUD_ResampleReader(AUD_Reference reader, AUD_SampleRate rate) : +AUD_ResampleReader::AUD_ResampleReader(boost::shared_ptr reader, AUD_SampleRate rate) : AUD_EffectReader(reader), m_rate(rate) { } diff --git a/intern/audaspace/intern/AUD_ResampleReader.h b/intern/audaspace/intern/AUD_ResampleReader.h index c423326489d..7e21989bfa8 100644 --- a/intern/audaspace/intern/AUD_ResampleReader.h +++ b/intern/audaspace/intern/AUD_ResampleReader.h @@ -47,7 +47,7 @@ protected: * \param reader The reader to mix. * \param rate The target sampling rate. */ - AUD_ResampleReader(AUD_Reference reader, AUD_SampleRate rate); + AUD_ResampleReader(boost::shared_ptr reader, AUD_SampleRate rate); public: /** diff --git a/intern/audaspace/intern/AUD_Sequencer.cpp b/intern/audaspace/intern/AUD_Sequencer.cpp new file mode 100644 index 00000000000..58e8f682714 --- /dev/null +++ b/intern/audaspace/intern/AUD_Sequencer.cpp @@ -0,0 +1,176 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * Copyright 2009-2011 Jörg Hermann Müller + * + * This file is part of AudaSpace. + * + * Audaspace 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. + * + * AudaSpace 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 Audaspace; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file audaspace/intern/AUD_Sequencer.cpp + * \ingroup audaspaceintern + */ + + +#include "AUD_Sequencer.h" +#include "AUD_SequencerReader.h" +#include "AUD_3DMath.h" +#include "AUD_MutexLock.h" + +AUD_Sequencer::AUD_Sequencer(AUD_Specs specs, float fps, bool muted) : + m_specs(specs), + m_status(0), + m_entry_status(0), + m_id(0), + m_muted(muted), + m_fps(fps), + m_speed_of_sound(434), + m_doppler_factor(1), + m_distance_model(AUD_DISTANCE_MODEL_INVERSE_CLAMPED), + m_location(3), + m_orientation(4) +{ + AUD_Quaternion q; + m_orientation.write(q.get()); + float f = 1; + m_volume.write(&f); + + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + + pthread_mutex_init(&m_mutex, &attr); + + pthread_mutexattr_destroy(&attr); +} + +AUD_Sequencer::~AUD_Sequencer() +{ + pthread_mutex_destroy(&m_mutex); +} + +void AUD_Sequencer::lock() +{ + pthread_mutex_lock(&m_mutex); +} + +void AUD_Sequencer::unlock() +{ + pthread_mutex_unlock(&m_mutex); +} + +void AUD_Sequencer::setSpecs(AUD_Specs specs) +{ + AUD_MutexLock lock(*this); + + m_specs = specs; + m_status++; +} + +void AUD_Sequencer::setFPS(float fps) +{ + AUD_MutexLock lock(*this); + + m_fps = fps; +} + +void AUD_Sequencer::mute(bool muted) +{ + AUD_MutexLock lock(*this); + + m_muted = muted; +} + +bool AUD_Sequencer::getMute() const +{ + return m_muted; +} + +float AUD_Sequencer::getSpeedOfSound() const +{ + return m_speed_of_sound; +} + +void AUD_Sequencer::setSpeedOfSound(float speed) +{ + AUD_MutexLock lock(*this); + + m_speed_of_sound = speed; + m_status++; +} + +float AUD_Sequencer::getDopplerFactor() const +{ + return m_doppler_factor; +} + +void AUD_Sequencer::setDopplerFactor(float factor) +{ + AUD_MutexLock lock(*this); + + m_doppler_factor = factor; + m_status++; +} + +AUD_DistanceModel AUD_Sequencer::getDistanceModel() const +{ + return m_distance_model; +} + +void AUD_Sequencer::setDistanceModel(AUD_DistanceModel model) +{ + AUD_MutexLock lock(*this); + + m_distance_model = model; + m_status++; +} + +AUD_AnimateableProperty* AUD_Sequencer::getAnimProperty(AUD_AnimateablePropertyType type) +{ + switch(type) + { + case AUD_AP_VOLUME: + return &m_volume; + case AUD_AP_LOCATION: + return &m_location; + case AUD_AP_ORIENTATION: + return &m_orientation; + default: + return NULL; + } +} + +boost::shared_ptr AUD_Sequencer::add(boost::shared_ptr sound, float begin, float end, float skip) +{ + AUD_MutexLock lock(*this); + + boost::shared_ptr entry = boost::shared_ptr(new AUD_SequencerEntry(sound, begin, end, skip, m_id++)); + + m_entries.push_front(entry); + m_entry_status++; + + return entry; +} + +void AUD_Sequencer::remove(boost::shared_ptr entry) +{ + AUD_MutexLock lock(*this); + + m_entries.remove(entry); + m_entry_status++; +} diff --git a/intern/audaspace/intern/AUD_Sequencer.h b/intern/audaspace/intern/AUD_Sequencer.h new file mode 100644 index 00000000000..9fdf537ff97 --- /dev/null +++ b/intern/audaspace/intern/AUD_Sequencer.h @@ -0,0 +1,206 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * Copyright 2009-2011 Jörg Hermann Müller + * + * This file is part of AudaSpace. + * + * Audaspace 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. + * + * AudaSpace 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 Audaspace; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file audaspace/intern/AUD_Sequencer.h + * \ingroup audaspaceintern + */ + + +#ifndef __AUD_SEQUENCER_H__ +#define __AUD_SEQUENCER_H__ + +#include "AUD_AnimateableProperty.h" +#include "AUD_IFactory.h" +#include "AUD_ILockable.h" + +#include +#include + +class AUD_SequencerEntry; + +/** + * This class represents sequenced entries to play a sound scene. + */ +class AUD_Sequencer : public AUD_ILockable +{ + friend class AUD_SequencerReader; +private: + /// The target specification. + AUD_Specs m_specs; + + /// The status of the sequence. Changes every time a non-animated parameter changes. + int m_status; + + /// The entry status. Changes every time an entry is removed or added. + int m_entry_status; + + /// The next unused ID for the entries. + int m_id; + + /// The sequenced entries. + std::list > m_entries; + + /// Whether the whole scene is muted. + bool m_muted; + + /// The FPS of the scene. + float m_fps; + + /// Speed of Sound. + float m_speed_of_sound; + + /// Doppler factor. + float m_doppler_factor; + + /// Distance model. + AUD_DistanceModel m_distance_model; + + /// The animated volume. + AUD_AnimateableProperty m_volume; + + /// The animated listener location. + AUD_AnimateableProperty m_location; + + /// The animated listener orientation. + AUD_AnimateableProperty m_orientation; + + /// The mutex for locking. + pthread_mutex_t m_mutex; + + // hide copy constructor and operator= + AUD_Sequencer(const AUD_Sequencer&); + AUD_Sequencer& operator=(const AUD_Sequencer&); + +public: + /** + * Creates a new sound scene. + * \param specs The output audio data specification. + * \param fps The FPS of the scene. + * \param muted Whether the whole scene is muted. + */ + AUD_Sequencer(AUD_Specs specs, float fps, bool muted); + ~AUD_Sequencer(); + + /** + * Locks the sequence. + */ + virtual void lock(); + + /** + * Unlocks the previously locked sequence. + */ + virtual void unlock(); + + /** + * Sets the audio output specification. + * \param specs The new specification. + */ + void setSpecs(AUD_Specs specs); + + /** + * Sets the scene's FPS. + * \param fps The new FPS. + */ + void setFPS(float fps); + + /** + * Sets the muting state of the scene. + * \param muted Whether the scene is muted. + */ + void mute(bool muted); + + /** + * Retrieves the muting state of the scene. + * \return Whether the scene is muted. + */ + bool getMute() const; + + /** + * Retrieves the speed of sound. + * This value is needed for doppler effect calculation. + * \return The speed of sound. + */ + float getSpeedOfSound() const; + + /** + * Sets the speed of sound. + * This value is needed for doppler effect calculation. + * \param speed The new speed of sound. + */ + void setSpeedOfSound(float speed); + + /** + * Retrieves the doppler factor. + * This value is a scaling factor for the velocity vectors of sources and + * listener which is used while calculating the doppler effect. + * \return The doppler factor. + */ + float getDopplerFactor() const; + + /** + * Sets the doppler factor. + * This value is a scaling factor for the velocity vectors of sources and + * listener which is used while calculating the doppler effect. + * \param factor The new doppler factor. + */ + void setDopplerFactor(float factor); + + /** + * Retrieves the distance model. + * \return The distance model. + */ + AUD_DistanceModel getDistanceModel() const; + + /** + * Sets the distance model. + * \param model distance model. + */ + void setDistanceModel(AUD_DistanceModel model); + + /** + * Retrieves one of the animated properties of the sequence. + * \param type Which animated property to retrieve. + * \return A pointer to the animated property, valid as long as the + * sequence is. + */ + AUD_AnimateableProperty* getAnimProperty(AUD_AnimateablePropertyType type); + + /** + * Adds a new entry to the scene. + * \param sound The sound this entry should play. + * \param begin The start time. + * \param end The end time or a negative value if determined by the sound. + * \param skip How much seconds should be skipped at the beginning. + * \return The entry added. + */ + boost::shared_ptr add(boost::shared_ptr sound, float begin, float end, float skip); + + /** + * Removes an entry from the scene. + * \param entry The entry to remove. + */ + void remove(boost::shared_ptr entry); +}; + +#endif //__AUD_SEQUENCER_H__ diff --git a/intern/audaspace/intern/AUD_SequencerEntry.cpp b/intern/audaspace/intern/AUD_SequencerEntry.cpp index 96fd15a0bf8..005557bbed1 100644 --- a/intern/audaspace/intern/AUD_SequencerEntry.cpp +++ b/intern/audaspace/intern/AUD_SequencerEntry.cpp @@ -34,7 +34,7 @@ #include #include -AUD_SequencerEntry::AUD_SequencerEntry(AUD_Reference sound, float begin, float end, float skip, int id) : +AUD_SequencerEntry::AUD_SequencerEntry(boost::shared_ptr sound, float begin, float end, float skip, int id) : m_status(0), m_pos_status(1), m_sound_status(0), @@ -86,7 +86,7 @@ void AUD_SequencerEntry::unlock() pthread_mutex_unlock(&m_mutex); } -void AUD_SequencerEntry::setSound(AUD_Reference sound) +void AUD_SequencerEntry::setSound(boost::shared_ptr sound) { AUD_MutexLock lock(*this); diff --git a/intern/audaspace/intern/AUD_SequencerEntry.h b/intern/audaspace/intern/AUD_SequencerEntry.h index 46efc52d66b..aa1edebfc2f 100644 --- a/intern/audaspace/intern/AUD_SequencerEntry.h +++ b/intern/audaspace/intern/AUD_SequencerEntry.h @@ -30,12 +30,12 @@ #ifndef __AUD_SEQUENCERENTRY_H__ #define __AUD_SEQUENCERENTRY_H__ -#include "AUD_Reference.h" #include "AUD_AnimateableProperty.h" #include "AUD_IFactory.h" #include "AUD_ILockable.h" #include +#include /** * This class represents a sequenced entry in a sequencer factory. @@ -57,7 +57,7 @@ private: int m_id; /// The sound this entry plays. - AUD_Reference m_sound; + boost::shared_ptr m_sound; /// The begin time. float m_begin; @@ -125,7 +125,7 @@ public: * \param skip How much seconds should be skipped at the beginning. * \param id The ID of the entry. */ - AUD_SequencerEntry(AUD_Reference sound, float begin, float end, float skip, int id); + AUD_SequencerEntry(boost::shared_ptr sound, float begin, float end, float skip, int id); virtual ~AUD_SequencerEntry(); /** @@ -142,7 +142,7 @@ public: * Sets the sound of the entry. * \param sound The new sound. */ - void setSound(AUD_Reference sound); + void setSound(boost::shared_ptr sound); /** * Moves the entry. diff --git a/intern/audaspace/intern/AUD_SequencerFactory.cpp b/intern/audaspace/intern/AUD_SequencerFactory.cpp index 2cc0a656cf1..f6076603c2b 100644 --- a/intern/audaspace/intern/AUD_SequencerFactory.cpp +++ b/intern/audaspace/intern/AUD_SequencerFactory.cpp @@ -32,39 +32,12 @@ #include "AUD_3DMath.h" #include "AUD_MutexLock.h" -AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, float fps, bool muted) : - m_specs(specs), - m_status(0), - m_entry_status(0), - m_id(0), - m_muted(muted), - m_fps(fps), - m_speed_of_sound(434), - m_doppler_factor(1), - m_distance_model(AUD_DISTANCE_MODEL_INVERSE_CLAMPED), - m_location(3), - m_orientation(4) +AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, float fps, bool muted) { - AUD_Quaternion q; - m_orientation.write(q.get()); - float f = 1; - m_volume.write(&f); - - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - - pthread_mutex_init(&m_mutex, &attr); - - pthread_mutexattr_destroy(&attr); + m_sequence = boost::shared_ptr(new AUD_Sequencer(specs, fps, muted)); } -AUD_SequencerFactory::~AUD_SequencerFactory() -{ - pthread_mutex_destroy(&m_mutex); -} - -void AUD_SequencerFactory::lock() +/*void AUD_SequencerFactory::lock() { pthread_mutex_lock(&m_mutex); } @@ -72,115 +45,79 @@ void AUD_SequencerFactory::lock() void AUD_SequencerFactory::unlock() { pthread_mutex_unlock(&m_mutex); -} +}*/ void AUD_SequencerFactory::setSpecs(AUD_Specs specs) { - AUD_MutexLock lock(*this); - - m_specs = specs; - m_status++; + m_sequence->setSpecs(specs); } void AUD_SequencerFactory::setFPS(float fps) { - AUD_MutexLock lock(*this); - - m_fps = fps; + m_sequence->setFPS(fps); } void AUD_SequencerFactory::mute(bool muted) { - AUD_MutexLock lock(*this); - - m_muted = muted; + m_sequence->mute(muted); } bool AUD_SequencerFactory::getMute() const { - return m_muted; + return m_sequence->getMute(); } float AUD_SequencerFactory::getSpeedOfSound() const { - return m_speed_of_sound; + return m_sequence->getSpeedOfSound(); } void AUD_SequencerFactory::setSpeedOfSound(float speed) { - AUD_MutexLock lock(*this); - - m_speed_of_sound = speed; - m_status++; + m_sequence->setSpeedOfSound(speed); } float AUD_SequencerFactory::getDopplerFactor() const { - return m_doppler_factor; + return m_sequence->getDopplerFactor(); } void AUD_SequencerFactory::setDopplerFactor(float factor) { - AUD_MutexLock lock(*this); - - m_doppler_factor = factor; - m_status++; + m_sequence->setDopplerFactor(factor); } AUD_DistanceModel AUD_SequencerFactory::getDistanceModel() const { - return m_distance_model; + return m_sequence->getDistanceModel(); } void AUD_SequencerFactory::setDistanceModel(AUD_DistanceModel model) { - AUD_MutexLock lock(*this); - - m_distance_model = model; - m_status++; + m_sequence->setDistanceModel(model); } AUD_AnimateableProperty* AUD_SequencerFactory::getAnimProperty(AUD_AnimateablePropertyType type) { - switch(type) - { - case AUD_AP_VOLUME: - return &m_volume; - case AUD_AP_LOCATION: - return &m_location; - case AUD_AP_ORIENTATION: - return &m_orientation; - default: - return NULL; - } + return m_sequence->getAnimProperty(type); } -AUD_Reference AUD_SequencerFactory::add(AUD_Reference sound, float begin, float end, float skip) +boost::shared_ptr AUD_SequencerFactory::add(boost::shared_ptr sound, float begin, float end, float skip) { - AUD_MutexLock lock(*this); - - AUD_Reference entry = new AUD_SequencerEntry(sound, begin, end, skip, m_id++); - - m_entries.push_front(entry); - m_entry_status++; - - return entry; + return m_sequence->add(sound, begin, end, skip); } -void AUD_SequencerFactory::remove(AUD_Reference entry) +void AUD_SequencerFactory::remove(boost::shared_ptr entry) { - AUD_MutexLock lock(*this); - - m_entries.remove(entry); - m_entry_status++; + m_sequence->remove(entry); } -AUD_Reference AUD_SequencerFactory::createQualityReader() +boost::shared_ptr AUD_SequencerFactory::createQualityReader() { - return new AUD_SequencerReader(this, true); + return boost::shared_ptr(new AUD_SequencerReader(m_sequence, true)); } -AUD_Reference AUD_SequencerFactory::createReader() +boost::shared_ptr AUD_SequencerFactory::createReader() { - return new AUD_SequencerReader(this); + return boost::shared_ptr(new AUD_SequencerReader(m_sequence)); } diff --git a/intern/audaspace/intern/AUD_SequencerFactory.h b/intern/audaspace/intern/AUD_SequencerFactory.h index 38cbc2d1867..3ef847d4b34 100644 --- a/intern/audaspace/intern/AUD_SequencerFactory.h +++ b/intern/audaspace/intern/AUD_SequencerFactory.h @@ -32,7 +32,8 @@ #include "AUD_IFactory.h" #include "AUD_AnimateableProperty.h" -#include "AUD_ILockable.h" +//#include "AUD_ILockable.h" +#include "AUD_Sequencer.h" #include #include @@ -42,51 +43,12 @@ class AUD_SequencerEntry; /** * This factory represents sequenced entries to play a sound scene. */ -class AUD_SequencerFactory : public AUD_IFactory, public AUD_ILockable +class AUD_SequencerFactory : public AUD_IFactory//, public AUD_ILockable { friend class AUD_SequencerReader; private: - /// The target specification. - AUD_Specs m_specs; - - /// The status of the factory. Changes every time a non-animated parameter changes. - int m_status; - - /// The entry status. Changes every time an entry is removed or added. - int m_entry_status; - - /// The next unused ID for the entries. - int m_id; - - /// The sequenced entries. - std::list > m_entries; - - /// Whether the whole scene is muted. - bool m_muted; - - /// The FPS of the scene. - float m_fps; - - /// Speed of Sound. - float m_speed_of_sound; - - /// Doppler factor. - float m_doppler_factor; - - /// Distance model. - AUD_DistanceModel m_distance_model; - - /// The animated volume. - AUD_AnimateableProperty m_volume; - - /// The animated listener location. - AUD_AnimateableProperty m_location; - - /// The animated listener orientation. - AUD_AnimateableProperty m_orientation; - - /// The mutex for locking. - pthread_mutex_t m_mutex; + /// The sequence. + boost::shared_ptr m_sequence; // hide copy constructor and operator= AUD_SequencerFactory(const AUD_SequencerFactory&); @@ -100,8 +62,8 @@ public: * \param muted Whether the whole scene is muted. */ AUD_SequencerFactory(AUD_Specs specs, float fps, bool muted); - ~AUD_SequencerFactory(); +#if 0 /** * Locks the factory. */ @@ -111,6 +73,7 @@ public: * Unlocks the previously locked factory. */ virtual void unlock(); +#endif /** * Sets the audio output specification. @@ -194,21 +157,21 @@ public: * \param skip How much seconds should be skipped at the beginning. * \return The entry added. */ - AUD_Reference add(AUD_Reference sound, float begin, float end, float skip); + boost::shared_ptr add(boost::shared_ptr sound, float begin, float end, float skip); /** * Removes an entry from the scene. * \param entry The entry to remove. */ - void remove(AUD_Reference entry); + void remove(boost::shared_ptr entry); /** * Creates a new reader with high quality resampling. * \return The new reader. */ - AUD_Reference createQualityReader(); + boost::shared_ptr createQualityReader(); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_SEQUENCERFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_SequencerHandle.cpp b/intern/audaspace/intern/AUD_SequencerHandle.cpp index 38d2ed38a7e..c9473cf274e 100644 --- a/intern/audaspace/intern/AUD_SequencerHandle.cpp +++ b/intern/audaspace/intern/AUD_SequencerHandle.cpp @@ -31,17 +31,17 @@ #include "AUD_ReadDevice.h" #include "AUD_MutexLock.h" -AUD_SequencerHandle::AUD_SequencerHandle(AUD_Reference entry, AUD_ReadDevice& device) : +AUD_SequencerHandle::AUD_SequencerHandle(boost::shared_ptr entry, AUD_ReadDevice& device) : m_entry(entry), m_status(0), m_pos_status(0), m_sound_status(0), m_device(device) { - if(!entry->m_sound.isNull()) + if(entry->m_sound.get()) { m_handle = device.play(entry->m_sound, true); - m_3dhandle = AUD_Reference(m_handle); + m_3dhandle = boost::dynamic_pointer_cast(m_handle); } } @@ -50,7 +50,7 @@ AUD_SequencerHandle::~AUD_SequencerHandle() stop(); } -int AUD_SequencerHandle::compare(AUD_Reference entry) const +int AUD_SequencerHandle::compare(boost::shared_ptr entry) const { if(m_entry->getID() < entry->getID()) return -1; @@ -61,13 +61,13 @@ int AUD_SequencerHandle::compare(AUD_Reference entry) const void AUD_SequencerHandle::stop() { - if(!m_handle.isNull()) + if(m_handle.get()) m_handle->stop(); } void AUD_SequencerHandle::update(float position, float frame, float fps) { - if(!m_handle.isNull()) + if(m_handle.get()) { AUD_MutexLock lock(*m_entry); if(position >= m_entry->m_end && m_entry->m_end >= 0) @@ -77,13 +77,13 @@ void AUD_SequencerHandle::update(float position, float frame, float fps) if(m_sound_status != m_entry->m_sound_status) { - if(!m_handle.isNull()) + if(m_handle.get()) m_handle->stop(); - if(!m_entry->m_sound.isNull()) + if(m_entry->m_sound.get()) { m_handle = m_device.play(m_entry->m_sound, true); - m_3dhandle = AUD_Reference(m_handle); + m_3dhandle = boost::dynamic_pointer_cast(m_handle); } m_sound_status = m_entry->m_sound_status; @@ -140,7 +140,7 @@ void AUD_SequencerHandle::update(float position, float frame, float fps) void AUD_SequencerHandle::seek(float position) { - if(!m_handle.isNull()) + if(m_handle.get()) { AUD_MutexLock lock(*m_entry); if(position >= m_entry->m_end && m_entry->m_end >= 0) diff --git a/intern/audaspace/intern/AUD_SequencerHandle.h b/intern/audaspace/intern/AUD_SequencerHandle.h index 72d3240a103..881bbdd43dc 100644 --- a/intern/audaspace/intern/AUD_SequencerHandle.h +++ b/intern/audaspace/intern/AUD_SequencerHandle.h @@ -43,13 +43,13 @@ class AUD_SequencerHandle { private: /// The entry this handle belongs to. - AUD_Reference m_entry; + boost::shared_ptr m_entry; /// The handle in the read device. - AUD_Reference m_handle; + boost::shared_ptr m_handle; /// The 3D handle in the read device. - AUD_Reference m_3dhandle; + boost::shared_ptr m_3dhandle; /// The last read status from the entry. int m_status; @@ -69,7 +69,7 @@ public: * \param entry The entry this handle plays. * \param device The read device to play on. */ - AUD_SequencerHandle(AUD_Reference entry, AUD_ReadDevice& device); + AUD_SequencerHandle(boost::shared_ptr entry, AUD_ReadDevice& device); /** * Destroys the handle. @@ -81,7 +81,7 @@ public: * \param entry The entry to compare to. * \return Whether the entries ID is smaller, equal or bigger. */ - int compare(AUD_Reference entry) const; + int compare(boost::shared_ptr entry) const; /** * Stops playing back the handle. diff --git a/intern/audaspace/intern/AUD_SequencerReader.cpp b/intern/audaspace/intern/AUD_SequencerReader.cpp index 39a4d29e6e4..d5e14590df5 100644 --- a/intern/audaspace/intern/AUD_SequencerReader.cpp +++ b/intern/audaspace/intern/AUD_SequencerReader.cpp @@ -30,11 +30,11 @@ #include "AUD_SequencerReader.h" #include "AUD_MutexLock.h" -typedef std::list >::iterator AUD_HandleIterator; -typedef std::list >::iterator AUD_EntryIterator; +typedef std::list >::iterator AUD_HandleIterator; +typedef std::list >::iterator AUD_EntryIterator; -AUD_SequencerReader::AUD_SequencerReader(AUD_Reference factory, bool quality) : - m_position(0), m_device(factory->m_specs), m_factory(factory), m_status(0), m_entry_status(0) +AUD_SequencerReader::AUD_SequencerReader(boost::shared_ptr sequence, bool quality) : + m_position(0), m_device(sequence->m_specs), m_sequence(sequence), m_status(0), m_entry_status(0) { m_device.setQuality(quality); } @@ -57,7 +57,7 @@ void AUD_SequencerReader::seek(int position) for(AUD_HandleIterator it = m_handles.begin(); it != m_handles.end(); it++) { - (*it)->seek(position / m_factory->m_specs.rate); + (*it)->seek(position / m_sequence->m_specs.rate); } } @@ -73,37 +73,37 @@ int AUD_SequencerReader::getPosition() const AUD_Specs AUD_SequencerReader::getSpecs() const { - return m_factory->m_specs; + return m_sequence->m_specs; } void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer) { - AUD_MutexLock lock(*m_factory); + AUD_MutexLock lock(*m_sequence); - if(m_factory->m_status != m_status) + if(m_sequence->m_status != m_status) { - m_device.changeSpecs(m_factory->m_specs); - m_device.setSpeedOfSound(m_factory->m_speed_of_sound); - m_device.setDistanceModel(m_factory->m_distance_model); - m_device.setDopplerFactor(m_factory->m_doppler_factor); + m_device.changeSpecs(m_sequence->m_specs); + m_device.setSpeedOfSound(m_sequence->m_speed_of_sound); + m_device.setDistanceModel(m_sequence->m_distance_model); + m_device.setDopplerFactor(m_sequence->m_doppler_factor); - m_status = m_factory->m_status; + m_status = m_sequence->m_status; } - if(m_factory->m_entry_status != m_entry_status) + if(m_sequence->m_entry_status != m_entry_status) { - std::list > handles; + std::list > handles; AUD_HandleIterator hit = m_handles.begin(); - AUD_EntryIterator eit = m_factory->m_entries.begin(); + AUD_EntryIterator eit = m_sequence->m_entries.begin(); int result; - AUD_Reference handle; + boost::shared_ptr handle; - while(hit != m_handles.end() && eit != m_factory->m_entries.end()) + while(hit != m_handles.end() && eit != m_sequence->m_entries.end()) { handle = *hit; - AUD_Reference entry = *eit; + boost::shared_ptr entry = *eit; result = handle->compare(entry); @@ -111,7 +111,7 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer) { try { - handle = new AUD_SequencerHandle(entry, m_device); + handle = boost::shared_ptr(new AUD_SequencerHandle(entry, m_device)); handles.push_front(handle); } catch(AUD_Exception&) @@ -138,11 +138,11 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer) hit++; } - while(eit != m_factory->m_entries.end()) + while(eit != m_sequence->m_entries.end()) { try { - handle = new AUD_SequencerHandle(*eit, m_device); + handle = boost::shared_ptr(new AUD_SequencerHandle(*eit, m_device)); handles.push_front(handle); } catch(AUD_Exception&) @@ -153,10 +153,10 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer) m_handles = handles; - m_entry_status = m_factory->m_entry_status; + m_entry_status = m_sequence->m_entry_status; } - AUD_Specs specs = m_factory->m_specs; + AUD_Specs specs = m_sequence->m_specs; int pos = 0; float time = float(m_position) / float(specs.rate); float volume, frame; @@ -167,30 +167,30 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer) while(pos < length) { - frame = time * m_factory->m_fps; + frame = time * m_sequence->m_fps; cfra = int(floor(frame)); - len = int(ceil((cfra + 1) / m_factory->m_fps * specs.rate)) - m_position; + len = int(ceil((cfra + 1) / m_sequence->m_fps * specs.rate)) - m_position; len = AUD_MIN(length - pos, len); len = AUD_MAX(len, 1); for(AUD_HandleIterator it = m_handles.begin(); it != m_handles.end(); it++) { - (*it)->update(time, frame, m_factory->m_fps); + (*it)->update(time, frame, m_sequence->m_fps); } - m_factory->m_volume.read(frame, &volume); - if(m_factory->m_muted) + m_sequence->m_volume.read(frame, &volume); + if(m_sequence->m_muted) volume = 0.0f; m_device.setVolume(volume); - m_factory->m_orientation.read(frame, q.get()); + m_sequence->m_orientation.read(frame, q.get()); m_device.setListenerOrientation(q); - m_factory->m_location.read(frame, v.get()); + m_sequence->m_location.read(frame, v.get()); m_device.setListenerLocation(v); - m_factory->m_location.read(frame + 1, v2.get()); + m_sequence->m_location.read(frame + 1, v2.get()); v2 -= v; - m_device.setListenerVelocity(v2 * m_factory->m_fps); + m_device.setListenerVelocity(v2 * m_sequence->m_fps); m_device.read(reinterpret_cast(buffer + specs.channels * pos), len); diff --git a/intern/audaspace/intern/AUD_SequencerReader.h b/intern/audaspace/intern/AUD_SequencerReader.h index b3c3a3ea7a6..6b3dbc9313e 100644 --- a/intern/audaspace/intern/AUD_SequencerReader.h +++ b/intern/audaspace/intern/AUD_SequencerReader.h @@ -32,7 +32,7 @@ #include "AUD_IReader.h" #include "AUD_ReadDevice.h" -#include "AUD_SequencerFactory.h" +#include "AUD_Sequencer.h" #include "AUD_SequencerHandle.h" /** @@ -52,22 +52,22 @@ private: AUD_ReadDevice m_device; /** - * Saves the SequencerFactory the reader belongs to. + * Saves the sequence the reader belongs to. */ - AUD_Reference m_factory; + boost::shared_ptr m_sequence; /** * The list of playback handles for the entries. */ - std::list > m_handles; + std::list > m_handles; /** - * Last status read from the factory. + * Last status read from the sequence. */ int m_status; /** - * Last entry status read from the factory. + * Last entry status read from the sequence. */ int m_entry_status; @@ -81,7 +81,7 @@ public: * \param reader The reader to mix. * \param specs The target specification. */ - AUD_SequencerReader(AUD_Reference factory, bool quality = false); + AUD_SequencerReader(boost::shared_ptr sequence, bool quality = false); /** * Destroys the reader. diff --git a/intern/audaspace/intern/AUD_SilenceFactory.cpp b/intern/audaspace/intern/AUD_SilenceFactory.cpp index 0ba553f1c02..85034b316ca 100644 --- a/intern/audaspace/intern/AUD_SilenceFactory.cpp +++ b/intern/audaspace/intern/AUD_SilenceFactory.cpp @@ -35,7 +35,7 @@ AUD_SilenceFactory::AUD_SilenceFactory() { } -AUD_Reference AUD_SilenceFactory::createReader() +boost::shared_ptr AUD_SilenceFactory::createReader() { - return new AUD_SilenceReader(); + return boost::shared_ptr(new AUD_SilenceReader()); } diff --git a/intern/audaspace/intern/AUD_SilenceFactory.h b/intern/audaspace/intern/AUD_SilenceFactory.h index 3bc7fc067ed..de62a2f94fc 100644 --- a/intern/audaspace/intern/AUD_SilenceFactory.h +++ b/intern/audaspace/intern/AUD_SilenceFactory.h @@ -48,7 +48,7 @@ public: */ AUD_SilenceFactory(); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_SILENCEFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_SinusFactory.cpp b/intern/audaspace/intern/AUD_SinusFactory.cpp index 3ef6a11de5b..2b9742cc90c 100644 --- a/intern/audaspace/intern/AUD_SinusFactory.cpp +++ b/intern/audaspace/intern/AUD_SinusFactory.cpp @@ -42,7 +42,7 @@ float AUD_SinusFactory::getFrequency() const return m_frequency; } -AUD_Reference AUD_SinusFactory::createReader() +boost::shared_ptr AUD_SinusFactory::createReader() { - return new AUD_SinusReader(m_frequency, m_sampleRate); + return boost::shared_ptr(new AUD_SinusReader(m_frequency, m_sampleRate)); } diff --git a/intern/audaspace/intern/AUD_SinusFactory.h b/intern/audaspace/intern/AUD_SinusFactory.h index d83323c6635..d1909dedb66 100644 --- a/intern/audaspace/intern/AUD_SinusFactory.h +++ b/intern/audaspace/intern/AUD_SinusFactory.h @@ -66,7 +66,7 @@ public: */ float getFrequency() const; - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_SINUSFACTORY_H__ diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp index 1fbd0ad82d2..a7e5b25664b 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp +++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp @@ -57,7 +57,7 @@ typedef enum /********************** AUD_SoftwareHandle Handle Code ************************/ /******************************************************************************/ -AUD_SoftwareDevice::AUD_SoftwareHandle::AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference reader, AUD_Reference pitch, AUD_Reference resampler, AUD_Reference mapper, bool keep) : +AUD_SoftwareDevice::AUD_SoftwareHandle::AUD_SoftwareHandle(AUD_SoftwareDevice* device, boost::shared_ptr reader, boost::shared_ptr pitch, boost::shared_ptr resampler, boost::shared_ptr mapper, bool keep) : m_reader(reader), m_pitch(pitch), m_resampler(resampler), m_mapper(mapper), m_keep(keep), m_user_pitch(1.0f), m_user_volume(1.0f), m_user_pan(0.0f), m_volume(1.0f), m_loopcount(0), m_relative(true), m_volume_max(1.0f), m_volume_min(0), m_distance_max(std::numeric_limits::max()), m_distance_reference(1.0f), m_attenuation(1.0f), m_cone_angle_outer(M_PI), m_cone_angle_inner(M_PI), m_cone_volume_outer(0), @@ -231,14 +231,23 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::pause() if(m_status == AUD_STATUS_PLAYING) { - m_device->m_playingSounds.remove(this); - m_device->m_pausedSounds.push_back(this); + for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++) + { + if(it->get() == this) + { + boost::shared_ptr This = *it; - if(m_device->m_playingSounds.empty()) - m_device->playing(m_device->m_playback = false); - m_status = AUD_STATUS_PAUSED; + m_device->m_playingSounds.erase(it); + m_device->m_pausedSounds.push_back(This); - return true; + if(m_device->m_playingSounds.empty()) + m_device->playing(m_device->m_playback = false); + + m_status = AUD_STATUS_PAUSED; + + return true; + } + } } } @@ -253,13 +262,23 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::resume() if(m_status == AUD_STATUS_PAUSED) { - m_device->m_pausedSounds.remove(this); - m_device->m_playingSounds.push_back(this); + for(AUD_HandleIterator it = m_device->m_pausedSounds.begin(); it != m_device->m_pausedSounds.end(); it++) + { + if(it->get() == this) + { + boost::shared_ptr This = *it; - if(!m_device->m_playback) - m_device->playing(m_device->m_playback = true); - m_status = AUD_STATUS_PLAYING; - return true; + m_device->m_pausedSounds.erase(it); + + m_device->m_playingSounds.push_back(This); + + if(!m_device->m_playback) + m_device->playing(m_device->m_playback = true); + m_status = AUD_STATUS_PLAYING; + + return true; + } + } } } @@ -283,7 +302,7 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::stop() { if(it->get() == this) { - AUD_Reference This = *it; + boost::shared_ptr This = *it; m_device->m_playingSounds.erase(it); @@ -670,7 +689,7 @@ void AUD_SoftwareDevice::create() { m_playback = false; m_volume = 1.0f; - m_mixer = new AUD_Mixer(m_specs); + m_mixer = boost::shared_ptr(new AUD_Mixer(m_specs)); m_speed_of_sound = 343.0f; m_doppler_factor = 1.0f; m_distance_model = AUD_DISTANCE_MODEL_INVERSE_CLAMPED; @@ -707,12 +726,12 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length) AUD_MutexLock lock(*this); { - AUD_Reference sound; + boost::shared_ptr sound; int len; int pos; bool eos; - std::list > stopSounds; - std::list > pauseSounds; + std::list > stopSounds; + std::list > pauseSounds; sample_t* buf = m_buffer.getBuffer(); m_mixer->clear(length); @@ -817,32 +836,32 @@ AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() const return m_specs; } -AUD_Reference AUD_SoftwareDevice::play(AUD_Reference reader, bool keep) +boost::shared_ptr AUD_SoftwareDevice::play(boost::shared_ptr reader, bool keep) { // prepare the reader // pitch - AUD_Reference pitch = new AUD_PitchReader(reader, 1); - reader = AUD_Reference(pitch); + boost::shared_ptr pitch = boost::shared_ptr(new AUD_PitchReader(reader, 1)); + reader = boost::shared_ptr(pitch); - AUD_Reference resampler; + boost::shared_ptr resampler; // resample if(m_quality) - resampler = new AUD_JOSResampleReader(reader, m_specs.specs); + resampler = boost::shared_ptr(new AUD_JOSResampleReader(reader, m_specs.specs)); else - resampler = new AUD_LinearResampleReader(reader, m_specs.specs); - reader = AUD_Reference(resampler); + resampler = boost::shared_ptr(new AUD_LinearResampleReader(reader, m_specs.specs)); + reader = boost::shared_ptr(resampler); // rechannel - AUD_Reference mapper = new AUD_ChannelMapperReader(reader, m_specs.channels); - reader = AUD_Reference(mapper); + boost::shared_ptr mapper = boost::shared_ptr(new AUD_ChannelMapperReader(reader, m_specs.channels)); + reader = boost::shared_ptr(mapper); - if(reader.isNull()) - return AUD_Reference(); + if(!reader.get()) + return boost::shared_ptr(); // play sound - AUD_Reference sound = new AUD_SoftwareDevice::AUD_SoftwareHandle(this, reader, pitch, resampler, mapper, keep); + boost::shared_ptr sound = boost::shared_ptr(new AUD_SoftwareDevice::AUD_SoftwareHandle(this, reader, pitch, resampler, mapper, keep)); AUD_MutexLock lock(*this); @@ -851,10 +870,10 @@ AUD_Reference AUD_SoftwareDevice::play(AUD_Reference r if(!m_playback) playing(m_playback = true); - return AUD_Reference(sound); + return boost::shared_ptr(sound); } -AUD_Reference AUD_SoftwareDevice::play(AUD_Reference factory, bool keep) +boost::shared_ptr AUD_SoftwareDevice::play(boost::shared_ptr factory, bool keep) { return play(factory->createReader(), keep); } diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.h b/intern/audaspace/intern/AUD_SoftwareDevice.h index c429508b622..8675a5ce2b8 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.h +++ b/intern/audaspace/intern/AUD_SoftwareDevice.h @@ -59,16 +59,16 @@ protected: { public: /// The reader source. - AUD_Reference m_reader; + boost::shared_ptr m_reader; /// The pitch reader in between. - AUD_Reference m_pitch; + boost::shared_ptr m_pitch; /// The resample reader in between. - AUD_Reference m_resampler; + boost::shared_ptr m_resampler; /// The channel mapper reader in between. - AUD_Reference m_mapper; + boost::shared_ptr m_mapper; /// Whether to keep the source if end of it is reached. bool m_keep; @@ -150,7 +150,7 @@ protected: * \param mapper The channel mapping reader. * \param keep Whether to keep the handle when the sound ends. */ - AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference reader, AUD_Reference pitch, AUD_Reference resampler, AUD_Reference mapper, bool keep); + AUD_SoftwareHandle(AUD_SoftwareDevice* device, boost::shared_ptr reader, boost::shared_ptr pitch, boost::shared_ptr resampler, boost::shared_ptr mapper, bool keep); /** * Updates the handle's playback parameters. @@ -206,7 +206,7 @@ protected: virtual bool setConeVolumeOuter(float volume); }; - typedef std::list >::iterator AUD_HandleIterator; + typedef std::list >::iterator AUD_HandleIterator; /** * The specification of the device. @@ -216,7 +216,7 @@ protected: /** * The mixer. */ - AUD_Reference m_mixer; + boost::shared_ptr m_mixer; /** * Whether to do high or low quality resampling. @@ -261,12 +261,12 @@ private: /** * The list of sounds that are currently playing. */ - std::list > m_playingSounds; + std::list > m_playingSounds; /** * The list of sounds that are currently paused. */ - std::list > m_pausedSounds; + std::list > m_pausedSounds; /** * Whether there is currently playback. @@ -320,8 +320,8 @@ public: void setQuality(bool quality); virtual AUD_DeviceSpecs getSpecs() const; - virtual AUD_Reference play(AUD_Reference reader, bool keep = false); - virtual AUD_Reference play(AUD_Reference factory, bool keep = false); + virtual boost::shared_ptr play(boost::shared_ptr reader, bool keep = false); + virtual boost::shared_ptr play(boost::shared_ptr factory, bool keep = false); virtual void stopAll(); virtual void lock(); virtual void unlock(); diff --git a/intern/audaspace/intern/AUD_StreamBufferFactory.cpp b/intern/audaspace/intern/AUD_StreamBufferFactory.cpp index 1c8d2a99351..daa714aeec3 100644 --- a/intern/audaspace/intern/AUD_StreamBufferFactory.cpp +++ b/intern/audaspace/intern/AUD_StreamBufferFactory.cpp @@ -33,10 +33,10 @@ #include -AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_Reference factory) : +AUD_StreamBufferFactory::AUD_StreamBufferFactory(boost::shared_ptr factory) : m_buffer(new AUD_Buffer()) { - AUD_Reference reader = factory->createReader(); + boost::shared_ptr reader = factory->createReader(); m_specs = reader->getSpecs(); @@ -70,7 +70,7 @@ AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_Reference fac m_buffer->resize(index * sample_size, true); } -AUD_Reference AUD_StreamBufferFactory::createReader() +boost::shared_ptr AUD_StreamBufferFactory::createReader() { - return new AUD_BufferReader(m_buffer, m_specs); + return boost::shared_ptr(new AUD_BufferReader(m_buffer, m_specs)); } diff --git a/intern/audaspace/intern/AUD_StreamBufferFactory.h b/intern/audaspace/intern/AUD_StreamBufferFactory.h index 99795d95d33..1bcd73d59b6 100644 --- a/intern/audaspace/intern/AUD_StreamBufferFactory.h +++ b/intern/audaspace/intern/AUD_StreamBufferFactory.h @@ -31,9 +31,10 @@ #define __AUD_STREAMBUFFERFACTORY_H__ #include "AUD_IFactory.h" -#include "AUD_Reference.h" #include "AUD_Buffer.h" +#include + /** * This factory creates a buffer out of a reader. This way normally streamed * sound sources can be loaded into memory for buffered playback. @@ -44,7 +45,7 @@ private: /** * The buffer that holds the audio data. */ - AUD_Reference m_buffer; + boost::shared_ptr m_buffer; /** * The specification of the samples. @@ -62,9 +63,9 @@ public: * \param factory The factory that creates the reader for buffering. * \exception AUD_Exception Thrown if the reader cannot be created. */ - AUD_StreamBufferFactory(AUD_Reference factory); + AUD_StreamBufferFactory(boost::shared_ptr factory); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_STREAMBUFFERFACTORY_H__ diff --git a/intern/audaspace/sndfile/AUD_SndFileFactory.cpp b/intern/audaspace/sndfile/AUD_SndFileFactory.cpp index 1fc77fbde66..106b2937a06 100644 --- a/intern/audaspace/sndfile/AUD_SndFileFactory.cpp +++ b/intern/audaspace/sndfile/AUD_SndFileFactory.cpp @@ -43,10 +43,10 @@ AUD_SndFileFactory::AUD_SndFileFactory(const data_t* buffer, int size) : memcpy(m_buffer->getBuffer(), buffer, size); } -AUD_Reference AUD_SndFileFactory::createReader() +boost::shared_ptr AUD_SndFileFactory::createReader() { - if(m_buffer.isNull()) - return new AUD_SndFileReader(m_filename); + if(m_buffer.get()) + return boost::shared_ptr(new AUD_SndFileReader(m_buffer)); else - return new AUD_SndFileReader(m_buffer); + return boost::shared_ptr(new AUD_SndFileReader(m_filename)); } diff --git a/intern/audaspace/sndfile/AUD_SndFileFactory.h b/intern/audaspace/sndfile/AUD_SndFileFactory.h index 7039c7a2615..bc96325d6eb 100644 --- a/intern/audaspace/sndfile/AUD_SndFileFactory.h +++ b/intern/audaspace/sndfile/AUD_SndFileFactory.h @@ -31,10 +31,10 @@ #define __AUD_SNDFILEFACTORY_H__ #include "AUD_IFactory.h" -#include "AUD_Reference.h" #include "AUD_Buffer.h" #include +#include /** * This factory reads a sound file via libsndfile. @@ -50,7 +50,7 @@ private: /** * The buffer to read from. */ - AUD_Reference m_buffer; + boost::shared_ptr m_buffer; // hide copy constructor and operator= AUD_SndFileFactory(const AUD_SndFileFactory&); @@ -70,7 +70,7 @@ public: */ AUD_SndFileFactory(const data_t* buffer, int size); - virtual AUD_Reference createReader(); + virtual boost::shared_ptr createReader(); }; #endif //__AUD_SNDFILEFACTORY_H__ diff --git a/intern/audaspace/sndfile/AUD_SndFileReader.cpp b/intern/audaspace/sndfile/AUD_SndFileReader.cpp index 8dbb43cb17e..aaee814f56b 100644 --- a/intern/audaspace/sndfile/AUD_SndFileReader.cpp +++ b/intern/audaspace/sndfile/AUD_SndFileReader.cpp @@ -100,7 +100,7 @@ AUD_SndFileReader::AUD_SndFileReader(std::string filename) : m_seekable = sfinfo.seekable; } -AUD_SndFileReader::AUD_SndFileReader(AUD_Reference buffer) : +AUD_SndFileReader::AUD_SndFileReader(boost::shared_ptr buffer) : m_position(0), m_membuffer(buffer), m_memoffset(0) diff --git a/intern/audaspace/sndfile/AUD_SndFileReader.h b/intern/audaspace/sndfile/AUD_SndFileReader.h index 81d8b45120c..5cac5051ee2 100644 --- a/intern/audaspace/sndfile/AUD_SndFileReader.h +++ b/intern/audaspace/sndfile/AUD_SndFileReader.h @@ -31,11 +31,11 @@ #define __AUD_SNDFILEREADER_H__ #include "AUD_IReader.h" -#include "AUD_Reference.h" #include "AUD_Buffer.h" #include #include +#include typedef sf_count_t (*sf_read_f)(SNDFILE *sndfile, void *ptr, sf_count_t frames); @@ -78,7 +78,7 @@ private: /** * The pointer to the memory file. */ - AUD_Reference m_membuffer; + boost::shared_ptr m_membuffer; /** * The current reading pointer of the memory file. @@ -110,7 +110,7 @@ public: * \exception AUD_Exception Thrown if the buffer specified cannot be read * with libsndfile. */ - AUD_SndFileReader(AUD_Reference buffer); + AUD_SndFileReader(boost::shared_ptr buffer); /** * Destroys the reader and closes the file. diff --git a/intern/bsp/intern/BOP_CarveInterface.cpp b/intern/bsp/intern/BOP_CarveInterface.cpp index 49c999a1dd4..f7da76e5794 100644 --- a/intern/bsp/intern/BOP_CarveInterface.cpp +++ b/intern/bsp/intern/BOP_CarveInterface.cpp @@ -559,8 +559,6 @@ static bool Carve_checkDegeneratedFace(std::map::vertex_t*, uint> *ve if (v1 == v2 || v2 == v3 || v1 == v3) return true; - - return triangleArea(face->edge->prev->vert->v, face->edge->vert->v, face->edge->next->vert->v) < DBL_EPSILON; } else if (face->n_edges == 4) { uint v1, v2, v3, v4; @@ -572,9 +570,6 @@ static bool Carve_checkDegeneratedFace(std::map::vertex_t*, uint> *ve if (v1 == v2 || v1 == v3 || v1 == v4 || v2 == v3 || v2 == v4 || v3 == v4) return true; - - return triangleArea(face->edge->vert->v, face->edge->next->vert->v, face->edge->next->next->vert->v) + - triangleArea(face->edge->prev->vert->v, face->edge->vert->v, face->edge->next->next->vert->v) < DBL_EPSILON; } return false; diff --git a/intern/cycles/blender/addon/enums.py b/intern/cycles/blender/addon/enums.py index e63e1e84245..dd7a555c2a8 100644 --- a/intern/cycles/blender/addon/enums.py +++ b/intern/cycles/blender/addon/enums.py @@ -57,7 +57,7 @@ aperture_types = ( panorama_types = ( ('EQUIRECTANGULAR', "Equirectangular", "Render the scene with a spherical camera, also known as Lat Long panorama"), - ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ideal for fulldomes, ignore the sensor dimensions"), - ('FISHEYE_EQUISOLID', "Fisheye Equisolid", "Similar to most fisheye modern lens, take sensor dimensions into consideration"), + ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ignore the sensor dimensions"), + ('FISHEYE_EQUISOLID', "Fisheye Equisolid", "Similar to most fisheye modern lens, take sensor dimensions into consideration. For fulldomes use it with a square sensor ratio", ) diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index 74585dd5058..bbcdb47260e 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -135,7 +135,7 @@ void TileManager::gen_tiles_sliced() int x = tile_x * tile_size.x; int y = tile_y * tile_size.y; int w = (tile_x == tile_w-1)? image_w - x: tile_size.x; - int h = (tile_y == tile_h-1)? device_h - y: tile_size.x; + int h = (tile_y == tile_h-1)? device_h - y: tile_size.y; state.tiles.push_back(Tile(tile_index, x, y + device_y, w, h, device)); } diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 14fbc7c34be..cba45d4c2b7 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -601,6 +601,8 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel): split.label(text="File:") split.prop(elem, "filename", text="") # strip.elements[0] could be a fallback + layout.prop(strip.colorspace_settings, "name") + layout.operator("sequencer.change_path") elif seq_type == 'MOVIE': @@ -608,6 +610,8 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel): split.label(text="Path:") split.prop(strip, "filepath", text="") + layout.prop(strip.colorspace_settings, "name") + layout.prop(strip, "mpeg_preseek") layout.prop(strip, "stream_index") diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 6361a0dfc27..21a80df9ead 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -356,6 +356,7 @@ class VIEW3D_MT_view(Menu): layout.operator("view3d.clip_border", text="Clipping Border...") layout.operator("view3d.zoom_border", text="Zoom Border...") + layout.operator("view3d.render_border", text="Render Border...") layout.separator() diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 1667c119790..ba611817c8f 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -356,6 +356,7 @@ typedef struct SeqLoadInfo { typedef struct Sequence *(*SeqLoadFunc)(struct bContext *, ListBase *, struct SeqLoadInfo *); struct Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine); +void BKE_sequence_init_colorspace(struct Sequence *seq); struct Sequence *BKE_sequencer_add_image_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); struct Sequence *BKE_sequencer_add_sound_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 80ea00fc703..af0cab98fe0 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -676,8 +676,8 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, int lock_range) if (seq->anim) IMB_free_anim(seq->anim); - /* OCIO_TODO: support configurable input space for strips */ - seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), seq->streamindex, NULL); + seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), + seq->streamindex, seq->strip->colorspace_settings.name); if (!seq->anim) { return; @@ -1174,8 +1174,8 @@ static void seq_open_anim_file(Sequence *seq) seq->strip->dir, seq->strip->stripdata->name); BLI_path_abs(name, G.main->name); - /* OCIO_TODO: support configurable input space for strips */ - seq->anim = openanim(name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), seq->streamindex, NULL); + seq->anim = openanim(name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), + seq->streamindex, seq->strip->colorspace_settings.name); if (seq->anim == NULL) { return; @@ -1301,7 +1301,6 @@ static ImBuf *seq_proxy_fetch(SeqRenderData context, Sequence *seq, int cfra) } if (BLI_exists(name)) { - /* OCIO_TODO: support configurable spaces for strips */ ImBuf *ibuf = IMB_loadiffname(name, IB_rect, NULL); if (ibuf) @@ -1346,7 +1345,6 @@ static void seq_proxy_build_frame(SeqRenderData context, Sequence *seq, int cfra BLI_make_existing_file(name); - /* OCIO_TODO: support per-strip color space settings */ ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat); if (ok == 0) { perror(name); @@ -2529,8 +2527,7 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo BLI_path_abs(name, G.main->name); } - /* OCIO_TODO: support configurable space for image strips */ - if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect, NULL))) { + if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect, seq->strip->colorspace_settings.name))) { /* we don't need both (speed reasons)! */ if (ibuf->rect_float && ibuf->rect) imb_freerectImBuf(ibuf); @@ -3940,6 +3937,25 @@ Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine) return seq; } +void BKE_sequence_init_colorspace(Sequence *seq) +{ + if (seq->strip && seq->strip->stripdata) { + char name[FILE_MAX]; + ImBuf *ibuf; + + BLI_join_dirfile(name, sizeof(name), seq->strip->dir, seq->strip->stripdata->name); + BLI_path_abs(name, G.main->name); + + /* initialize input color space */ + if (seq->type == SEQ_TYPE_IMAGE) { + ibuf = IMB_loadiffname(name, IB_rect, seq->strip->colorspace_settings.name); + + if (ibuf) + IMB_freeImBuf(ibuf); + } + } +} + /* NOTE: this function doesn't fill in image names */ Sequence *BKE_sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load) { @@ -4046,14 +4062,14 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad Sequence *seq; /* generic strip vars */ Strip *strip; StripElem *se; + char colorspace[64] = "\0"; /* MAX_COLORSPACE_NAME */ struct anim *an; BLI_strncpy(path, seq_load->path, sizeof(path)); BLI_path_abs(path, G.main->name); - /* OCIO_TODO: support configurable input space for strips */ - an = openanim(path, IB_rect, 0, NULL); + an = openanim(path, IB_rect, 0, colorspace); if (an == NULL) return NULL; @@ -4072,6 +4088,8 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad seq->len = IMB_anim_get_duration(an, IMB_TC_RECORD_RUN); strip->us = 1; + BLI_strncpy(seq->strip->colorspace_settings.name, colorspace, sizeof(seq->strip->colorspace_settings.name)); + /* we only need 1 element for MOVIE strips */ strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem"); diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index b3497b9932f..d230cf8f1fe 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -2862,7 +2862,7 @@ int txt_replace_char(Text *text, unsigned int add) void txt_indent(Text *text) { - int len, num; + int len, num, curc_old; char *tmp; const char *add = "\t"; @@ -2885,6 +2885,8 @@ void txt_indent(Text *text) indentlen = spaceslen; } + curc_old = text->curc; + num = 0; while (TRUE) { tmp = MEM_mallocN(text->curl->len + indentlen + 1, "textline_string"); @@ -2905,7 +2907,7 @@ void txt_indent(Text *text) txt_clean_text(text); if (text->curl == text->sell) { - text->selc = text->sell->len; + text->selc += indentlen; break; } else { @@ -2913,7 +2915,9 @@ void txt_indent(Text *text) num++; } } - text->curc = 0; + if (!curc_old) text->curc = 0; + else text->curc = curc_old + indentlen; + while (num > 0) { text->curl = text->curl->prev; num--; @@ -2928,7 +2932,8 @@ void txt_unindent(Text *text) { int num = 0; const char *remove = "\t"; - int indent = 1; + int indentlen = 1; + int unindented_first = FALSE; /* hardcoded: TXT_TABSIZE = 4 spaces: */ int spaceslen = TXT_TABSIZE; @@ -2940,25 +2945,26 @@ void txt_unindent(Text *text) /* insert spaces rather than tabs */ if (text->flags & TXT_TABSTOSPACES) { remove = tab_to_spaces; - indent = spaceslen; + indentlen = spaceslen; } while (TRUE) { int i = 0; - if (BLI_strncasecmp(text->curl->line, remove, indent) == 0) { + if (BLI_strncasecmp(text->curl->line, remove, indentlen) == 0) { + if (num == 0) unindented_first = TRUE; while (i < text->curl->len) { - text->curl->line[i] = text->curl->line[i + indent]; + text->curl->line[i] = text->curl->line[i + indentlen]; i++; } - text->curl->len -= indent; + text->curl->len -= indentlen; } txt_make_dirty(text); txt_clean_text(text); if (text->curl == text->sell) { - text->selc = text->sell->len; + if (i > 0) text->selc = MAX2(text->selc - indentlen, 0); break; } else { @@ -2967,7 +2973,9 @@ void txt_unindent(Text *text) } } - text->curc = 0; + + if (unindented_first) text->curc = MAX2(text->curc - indentlen, 0); + while (num > 0) { text->curl = text->curl->prev; num--; diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index a2f4cdc8c6a..671cfbbc55e 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -285,6 +285,8 @@ void BMO_slot_int_set(BMOperator *op, const char *slot_name, const int i); int BMO_slot_int_get(BMOperator *op, const char *slot_name); void BMO_slot_bool_set(BMOperator *op, const char *slot_name, const int i); int BMO_slot_bool_get(BMOperator *op, const char *slot_name); +void *BMO_slot_as_arrayN(BMOperator *op, const char *slot_name, int *len); + /* don't pass in arrays that are supposed to map to elements this way. * diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 2413f3a7be0..4cc946a3a40 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -429,6 +429,20 @@ int BMO_slot_bool_get(BMOperator *op, const char *slot_name) return slot->data.i; } +/* if you want a copy of the elem buffer */ +void *BMO_slot_as_arrayN(BMOperator *op, const char *slot_name, int *len) +{ + BMOpSlot *slot = BMO_slot_get(op, slot_name); + void *ret; + + /* could add support for mapping type */ + BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + + ret = MEM_mallocN(sizeof(void *) * slot->len, __func__); + memcpy(ret, slot->data.buf, sizeof(void *) * slot->len); + *len = slot->len; + return ret; +} void *BMO_slot_ptr_get(BMOperator *op, const char *slot_name) { diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index cd792f911a9..ea6cd747037 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -488,72 +488,71 @@ void bmo_collapse_uvs_exec(BMesh *bm, BMOperator *op) static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, BMOperator *optarget, const char *targetmapname) { - BMOIter oiter; - BMVert *v, *v2; - BMVert **verts = NULL; - BLI_array_declare(verts); - float dist, dist3; - int i, j, len, keepvert = 0; + BMVert **verts; + int verts_len; - dist = BMO_slot_float_get(op, "dist"); - dist3 = dist * 3.0f; + int i, j, keepvert = 0; - i = 0; - BMO_ITER (v, &oiter, bm, op, "verts", BM_VERT) { - BLI_array_grow_one(verts); - verts[i++] = v; - } + const float dist = BMO_slot_float_get(op, "dist"); + const float dist3 = dist * 3.0f; /* Test whether keep_verts arg exists and is non-empty */ if (BMO_slot_exists(op, "keep_verts")) { + BMOIter oiter; keepvert = BMO_iter_new(&oiter, bm, op, "keep_verts", BM_VERT) != NULL; } + /* get the verts as an array we can sort */ + verts = BMO_slot_as_arrayN(op, "verts", &verts_len); + /* sort by vertex coordinates added together */ - qsort(verts, BLI_array_count(verts), sizeof(void *), vergaverco); + qsort(verts, verts_len, sizeof(BMVert *), vergaverco); /* Flag keep_verts */ if (keepvert) { BMO_slot_buffer_flag_enable(bm, op, "keep_verts", BM_VERT, VERT_KEEP); } - len = BLI_array_count(verts); - for (i = 0; i < len; i++) { - v = verts[i]; - if (BMO_elem_flag_test(bm, v, VERT_DOUBLE)) { + for (i = 0; i < verts_len; i++) { + BMVert *v_check = verts[i]; + + if (BMO_elem_flag_test(bm, v_check, VERT_DOUBLE)) { continue; } - for (j = i + 1; j < len; j++) { - v2 = verts[j]; + for (j = i + 1; j < verts_len; j++) { + BMVert *v_other = verts[j]; /* Compare sort values of the verts using 3x tolerance (allowing for the tolerance * on each of the three axes). This avoids the more expensive length comparison * for most vertex pairs. */ - if ((v2->co[0] + v2->co[1] + v2->co[2]) - (v->co[0] + v->co[1] + v->co[2]) > dist3) + if ((v_other->co[0] + v_other->co[1] + v_other->co[2]) - + (v_check->co[0] + v_check->co[1] + v_check->co[2]) > dist3) + { break; + } if (keepvert) { - if (BMO_elem_flag_test(bm, v2, VERT_KEEP) == BMO_elem_flag_test(bm, v, VERT_KEEP)) + if (BMO_elem_flag_test(bm, v_other, VERT_KEEP) == BMO_elem_flag_test(bm, v_check, VERT_KEEP)) continue; } - if (compare_len_v3v3(v->co, v2->co, dist)) { + if (compare_len_v3v3(v_check->co, v_other->co, dist)) { /* If one vert is marked as keep, make sure it will be the target */ - if (BMO_elem_flag_test(bm, v2, VERT_KEEP)) { - SWAP(BMVert *, v, v2); + if (BMO_elem_flag_test(bm, v_other, VERT_KEEP)) { + SWAP(BMVert *, v_check, v_other); } - BMO_elem_flag_enable(bm, v2, VERT_DOUBLE); - BMO_elem_flag_enable(bm, v, VERT_TARGET); + BMO_elem_flag_enable(bm, v_other, VERT_DOUBLE); + BMO_elem_flag_enable(bm, v_check, VERT_TARGET); - BMO_slot_map_ptr_insert(bm, optarget, targetmapname, v2, v); + BMO_slot_map_ptr_insert(bm, optarget, targetmapname, v_other, v_check); } } } - BLI_array_free(verts); + MEM_freeN(verts); } void bmo_remove_doubles_exec(BMesh *bm, BMOperator *op) diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index fd46f69da83..8155f9d645e 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -719,7 +719,9 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) seq->endstill = seq_load.end_frame - seq_load.start_frame; } } - + + BKE_sequence_init_colorspace(seq); + BKE_sequence_calc_disp(scene, seq); BKE_sequencer_sort(scene); diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index a3ce332b609..94bb85b49ea 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -436,7 +436,7 @@ ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source) struct stat st; ImBuf *img = NULL; - if (stat(path, &st)) { + if (BLI_stat(path, &st)) { return NULL; } if (!uri_from_filename(path, uri)) { diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 4d259fad246..f106c8f918a 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -100,6 +100,9 @@ typedef struct Strip { StripCrop *crop; StripTransform *transform; StripColorBalance *color_balance DNA_DEPRECATED; + + /* color management */ + ColorManagedColorspaceSettings colorspace_settings; } Strip; /** diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index c93d2ef15cf..f534864e65a 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -45,6 +45,7 @@ #include "DNA_material_types.h" #include "DNA_movieclip_types.h" #include "DNA_node_types.h" +#include "DNA_sequence_types.h" #include "MEM_guardedalloc.h" @@ -53,6 +54,7 @@ #include "BKE_image.h" #include "BKE_movieclip.h" #include "BKE_node.h" +#include "BKE_sequencer.h" #include "BKE_texture.h" #include "ED_node.h" @@ -504,6 +506,37 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *UNUSED(bmain) WM_main_add_notifier(NC_MOVIECLIP | ND_DISPLAY, &clip->id); WM_main_add_notifier(NC_MOVIECLIP | NA_EDITED, &clip->id); } + else if (GS(id->name) == ID_SCE) { + Scene *scene = (Scene *) id; + + if (scene->ed) { + ColorManagedColorspaceSettings *colorspace_settings = (ColorManagedColorspaceSettings *) ptr->data; + Sequence *seq; + int seq_found = FALSE; + + if (&scene->sequencer_colorspace_settings != colorspace_settings) { + SEQ_BEGIN(scene->ed, seq); + { + if (seq->strip && &seq->strip->colorspace_settings == colorspace_settings) { + seq_found = TRUE; + break; + } + } + SEQ_END; + } + + if (seq_found) { + BKE_sequence_invalidate_cache(scene, seq); + BKE_sequencer_preprocessed_cache_cleanup_sequence(seq); + } + else { + BKE_sequencer_cache_cleanup(); + BKE_sequencer_preprocessed_cache_cleanup(); + } + + WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); + } + } } static void rna_ColorManagement_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 054d0cc82c6..c2fa64698e4 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -1688,6 +1688,16 @@ static void rna_def_effect_inputs(StructRNA *srna, int count) #endif } +static void rna_def_color_management(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "colorspace_settings", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "strip->colorspace_settings"); + RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings"); + RNA_def_property_ui_text(prop, "Color Space Settings", "Input color space settings"); +} + static void rna_def_image(BlenderRNA *brna) { StructRNA *srna; @@ -1714,6 +1724,7 @@ static void rna_def_image(BlenderRNA *brna) rna_def_filter_video(srna); rna_def_proxy(srna); rna_def_input(srna); + rna_def_color_management(srna); } static void rna_def_meta(BlenderRNA *brna) @@ -1799,6 +1810,7 @@ static void rna_def_movie(BlenderRNA *brna) rna_def_filter_video(srna); rna_def_proxy(srna); rna_def_input(srna); + rna_def_color_management(srna); } static void rna_def_movieclip(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index 8ddb9d0a7e7..7602ec99c2b 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -89,6 +89,8 @@ static Sequence *alloc_generic_sequence(Editing *ed, const char *name, int start if (file) { strip->stripdata = se = MEM_callocN(sizeof(StripElem), "stripelem"); BLI_split_dirfile(file, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name)); + + BKE_sequence_init_colorspace(seq); } else { strip->stripdata = NULL; diff --git a/source/blender/nodes/composite/nodes/node_composite_math.c b/source/blender/nodes/composite/nodes/node_composite_math.c index c99e12a95b9..bbd44c58314 100644 --- a/source/blender/nodes/composite/nodes/node_composite_math.c +++ b/source/blender/nodes/composite/nodes/node_composite_math.c @@ -103,7 +103,8 @@ static void do_math(bNode *node, float *out, float *in, float *in2) out[0] = pow(in[0], in2[0]); } else { - float y_mod_1 = fmod(in2[0], 1); + float y_mod_1 = ABS(fmod(in2[0], 1)); + /* if input value is not nearly an integer, fall back to zero, nicer than straight rounding */ if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) { out[0] = powf(in[0], floorf(in2[0] + 0.5f)); diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c index a70134b2325..9dc900e6bd4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_math.c +++ b/source/blender/nodes/shader/nodes/node_shader_math.c @@ -137,11 +137,22 @@ bNodeStack **out) break; case 10: /* Power */ { - /* Don't want any imaginary numbers... */ - if ( in[0]->vec[0] >= 0 ) + /* Only raise negative numbers by full integers */ + if ( in[0]->vec[0] >= 0 ) { out[0]->vec[0] = pow(in[0]->vec[0], in[1]->vec[0]); - else - out[0]->vec[0] = 0.0; + } + else { + float y_mod_1 = ABS(fmod(in[1]->vec[0], 1)); + + /* if input value is not nearly an integer, fall back to zero, nicer than straight rounding */ + if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) { + out[0]->vec[0] = powf(in[0]->vec[0], floorf(in[1]->vec[0] + 0.5f)); + } + else { + out[0]->vec[0] = 0.0f; + } + } + } break; case 11: /* Logarithm */ diff --git a/source/blender/nodes/shader/nodes/node_shader_script.c b/source/blender/nodes/shader/nodes/node_shader_script.c index 52d39363de6..d4c2d188ffa 100644 --- a/source/blender/nodes/shader/nodes/node_shader_script.c +++ b/source/blender/nodes/shader/nodes/node_shader_script.c @@ -46,16 +46,17 @@ static void node_free_script(bNode *node) NodeShaderScript *nss = node->storage; if (nss) { - if (nss->bytecode) + if (nss->bytecode) { MEM_freeN(nss->bytecode); + } + + if (nss->prop) { + IDP_FreeProperty(nss->prop); + MEM_freeN(nss->prop); + } MEM_freeN(nss); } - - if (nss->prop) { - IDP_FreeProperty(nss->prop); - MEM_freeN(nss->prop); - } } static void node_copy_script(bNode *orig_node, bNode *new_node) diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c index 45b767c6eda..a10bfef2a8d 100644 --- a/source/blender/python/generic/bgl.c +++ b/source/blender/python/generic/bgl.c @@ -520,7 +520,7 @@ static PyObject *Buffer_subscript(Buffer *self, PyObject *item) else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((void *)item, self->dimensions[0], &start, &stop, &step, &slicelength) < 0) + if (PySlice_GetIndicesEx(item, self->dimensions[0], &start, &stop, &step, &slicelength) < 0) return NULL; if (slicelength <= 0) { @@ -556,7 +556,7 @@ static int Buffer_ass_subscript(Buffer *self, PyObject *item, PyObject *value) else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((void *)item, self->dimensions[0], &start, &stop, &step, &slicelength) < 0) + if (PySlice_GetIndicesEx(item, self->dimensions[0], &start, &stop, &step, &slicelength) < 0) return -1; if (step == 1) diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index d2890bc046e..529b2e708ad 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -1187,7 +1187,7 @@ static PyObject *BPy_IDArray_subscript(BPy_IDArray *self, PyObject *item) else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((void *)item, self->prop->len, &start, &stop, &step, &slicelength) < 0) + if (PySlice_GetIndicesEx(item, self->prop->len, &start, &stop, &step, &slicelength) < 0) return NULL; if (slicelength <= 0) { @@ -1222,7 +1222,7 @@ static int BPy_IDArray_ass_subscript(BPy_IDArray *self, PyObject *item, PyObject else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((void *)item, self->prop->len, &start, &stop, &step, &slicelength) < 0) + if (PySlice_GetIndicesEx(item, self->prop->len, &start, &stop, &step, &slicelength) < 0) return -1; if (step == 1) diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index ad900343704..3ed662f41d7 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -32,6 +32,9 @@ #include +#include "RNA_types.h" +#include "RNA_access.h" + #include "bpy.h" #include "bpy_util.h" #include "bpy_rna.h" @@ -49,8 +52,6 @@ #include "BKE_global.h" /* XXX, G.main only */ #include "BKE_blender.h" -#include "RNA_access.h" - #include "MEM_guardedalloc.h" /* external util modules */ diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 68b6baadd71..eaaced416fe 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -2612,7 +2612,7 @@ static PyObject *pyrna_prop_array_subscript(BPy_PropertyArrayRNA *self, PyObject int len = pyrna_prop_array_length(self); Py_ssize_t start, stop, slicelength; - if (PySlice_GetIndicesEx((void *)key, len, &start, &stop, &step, &slicelength) < 0) + if (PySlice_GetIndicesEx(key, len, &start, &stop, &step, &slicelength) < 0) return NULL; if (slicelength <= 0) { @@ -2780,7 +2780,7 @@ static int pyrna_prop_array_ass_subscript(BPy_PropertyArrayRNA *self, PyObject * int len = RNA_property_array_length(&self->ptr, self->prop); Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((void *)key, len, &start, &stop, &step, &slicelength) < 0) { + if (PySlice_GetIndicesEx(key, len, &start, &stop, &step, &slicelength) < 0) { ret = -1; } else if (slicelength <= 0) { diff --git a/source/blender/python/intern/bpy_util.h b/source/blender/python/intern/bpy_util.h index 63660b06813..6aa50cf88de 100644 --- a/source/blender/python/intern/bpy_util.h +++ b/source/blender/python/intern/bpy_util.h @@ -24,15 +24,20 @@ * \ingroup pythonintern */ - #ifndef __BPY_UTIL_H__ #define __BPY_UTIL_H__ #if PY_VERSION_HEX < 0x03020000 -#error "Python 3.2 or greater is required, you'll need to update your python." +# error "Python 3.2 or greater is required, you'll need to update your python." #endif -#include "RNA_types.h" /* for EnumPropertyItem only */ +#if PY_VERSION_HEX < 0x03030000 +# ifdef _MSC_VER +# pragma message("Python 3.2 will be deprecated soon, upgrade to Python 3.3.") +# else +# warning "Python 3.2 will be deprecated soon, upgrade to Python 3.3." +# endif +#endif struct EnumPropertyItem; struct ReportList; @@ -51,4 +56,5 @@ void BPy_SetContext(struct bContext *C); extern void bpy_context_set(struct bContext *C, PyGILState_STATE *gilstate); extern void bpy_context_clear(struct bContext *C, PyGILState_STATE *gilstate); -#endif + +#endif /* __BPY_UTIL_H__ */ diff --git a/source/blender/python/mathutils/mathutils_Color.c b/source/blender/python/mathutils/mathutils_Color.c index 747a23a719d..f16b488f9d0 100644 --- a/source/blender/python/mathutils/mathutils_Color.c +++ b/source/blender/python/mathutils/mathutils_Color.c @@ -306,7 +306,7 @@ static PyObject *Color_subscript(ColorObject *self, PyObject *item) else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((void *)item, COLOR_SIZE, &start, &stop, &step, &slicelength) < 0) + if (PySlice_GetIndicesEx(item, COLOR_SIZE, &start, &stop, &step, &slicelength) < 0) return NULL; if (slicelength <= 0) { @@ -342,7 +342,7 @@ static int Color_ass_subscript(ColorObject *self, PyObject *item, PyObject *valu else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((void *)item, COLOR_SIZE, &start, &stop, &step, &slicelength) < 0) + if (PySlice_GetIndicesEx(item, COLOR_SIZE, &start, &stop, &step, &slicelength) < 0) return -1; if (step == 1) diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c index 3592e1084fb..829d3ee27e1 100644 --- a/source/blender/python/mathutils/mathutils_Euler.c +++ b/source/blender/python/mathutils/mathutils_Euler.c @@ -497,7 +497,7 @@ static PyObject *Euler_subscript(EulerObject *self, PyObject *item) else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((void *)item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0) + if (PySlice_GetIndicesEx(item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0) return NULL; if (slicelength <= 0) { @@ -534,7 +534,7 @@ static int Euler_ass_subscript(EulerObject *self, PyObject *item, PyObject *valu else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((void *)item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0) + if (PySlice_GetIndicesEx(item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0) return -1; if (step == 1) diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index b9f0ce9ad96..64112024dd1 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -2087,7 +2087,7 @@ static PyObject *Matrix_subscript(MatrixObject *self, PyObject *item) else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((void *)item, self->num_row, &start, &stop, &step, &slicelength) < 0) + if (PySlice_GetIndicesEx(item, self->num_row, &start, &stop, &step, &slicelength) < 0) return NULL; if (slicelength <= 0) { @@ -2123,7 +2123,7 @@ static int Matrix_ass_subscript(MatrixObject *self, PyObject *item, PyObject *va else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((void *)item, self->num_row, &start, &stop, &step, &slicelength) < 0) + if (PySlice_GetIndicesEx(item, self->num_row, &start, &stop, &step, &slicelength) < 0) return -1; if (step == 1) @@ -2626,7 +2626,7 @@ static PyObject *MatrixAccess_subscript(MatrixAccessObject *self, PyObject *item else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((void *)item, MatrixAccess_len(self), &start, &stop, &step, &slicelength) < 0) + if (PySlice_GetIndicesEx(item, MatrixAccess_len(self), &start, &stop, &step, &slicelength) < 0) return NULL; if (slicelength <= 0) { diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index b9aba995973..cda39932610 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -670,7 +670,7 @@ static PyObject *Quaternion_subscript(QuaternionObject *self, PyObject *item) else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((void *)item, QUAT_SIZE, &start, &stop, &step, &slicelength) < 0) + if (PySlice_GetIndicesEx(item, QUAT_SIZE, &start, &stop, &step, &slicelength) < 0) return NULL; if (slicelength <= 0) { @@ -707,7 +707,7 @@ static int Quaternion_ass_subscript(QuaternionObject *self, PyObject *item, PyOb else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((void *)item, QUAT_SIZE, &start, &stop, &step, &slicelength) < 0) + if (PySlice_GetIndicesEx(item, QUAT_SIZE, &start, &stop, &step, &slicelength) < 0) return -1; if (step == 1) diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index 06d7f3fec51..19be2b6a62e 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -1976,7 +1976,7 @@ static PyObject *Vector_subscript(VectorObject *self, PyObject *item) else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((void *)item, self->size, &start, &stop, &step, &slicelength) < 0) + if (PySlice_GetIndicesEx(item, self->size, &start, &stop, &step, &slicelength) < 0) return NULL; if (slicelength <= 0) { @@ -2012,7 +2012,7 @@ static int Vector_ass_subscript(VectorObject *self, PyObject *item, PyObject *va else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; - if (PySlice_GetIndicesEx((void *)item, self->size, &start, &stop, &step, &slicelength) < 0) + if (PySlice_GetIndicesEx(item, self->size, &start, &stop, &step, &slicelength) < 0) return -1; if (step == 1) diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 238f3468a41..5550cc69f89 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -460,6 +460,7 @@ void RE_engine_report(struct RenderEngine *engine, int type, const char *msg) {} ListBase R_engines = {NULL, NULL}; void RE_engine_free(struct RenderEngine *engine) {} struct RenderEngineType *RE_engines_find(const char *idname) { return NULL; } +void RE_engine_update_memory_stats(struct RenderEngine *engine, float mem_used, float mem_peak) {}; /* python */ struct wmOperatorType *WM_operatortype_find(const char *idname, int quiet) {return (struct wmOperatorType *) NULL;} diff --git a/source/gameengine/BlenderRoutines/CMakeLists.txt b/source/gameengine/BlenderRoutines/CMakeLists.txt index a053e069153..9a47d223f76 100644 --- a/source/gameengine/BlenderRoutines/CMakeLists.txt +++ b/source/gameengine/BlenderRoutines/CMakeLists.txt @@ -33,6 +33,7 @@ set(INC_SYS ../../../extern/bullet2/src ${PTHREADS_INCLUDE_DIRS} ${GLEW_INCLUDE_PATH} + ${BOOST_INCLUDE_DIR} ) set(SRC diff --git a/source/gameengine/BlenderRoutines/SConscript b/source/gameengine/BlenderRoutines/SConscript index 998396aba7c..04dbe27337f 100644 --- a/source/gameengine/BlenderRoutines/SConscript +++ b/source/gameengine/BlenderRoutines/SConscript @@ -34,6 +34,7 @@ if env['WITH_BF_CXX_GUARDEDALLOC']: incs += ' ' + env['BF_BULLET_INC'] incs += ' ' + env['BF_OPENGL_INC'] +incs += ' ' + env['BF_BOOST_INC'] if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): incs += ' ' + env['BF_PTHREADS_INC'] diff --git a/source/gameengine/Converter/CMakeLists.txt b/source/gameengine/Converter/CMakeLists.txt index 7b801fd4ffb..e9dd97f3821 100644 --- a/source/gameengine/Converter/CMakeLists.txt +++ b/source/gameengine/Converter/CMakeLists.txt @@ -59,7 +59,7 @@ set(INC_SYS ../../../extern/recastnavigation/Detour/Include ../../../extern/Eigen3 ${PTHREADS_INCLUDE_DIRS} - + ${BOOST_INCLUDE_DIR} ) set(SRC diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 24d321730eb..06399642edd 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -387,7 +387,7 @@ void BL_ConvertActuators(const char* maggiename, { bSound* sound = soundact->sound; bool is3d = soundact->flag & ACT_SND_3D_SOUND ? true : false; - AUD_Reference snd_sound; + boost::shared_ptr snd_sound; KX_3DSoundSettings settings; settings.cone_inner_angle = soundact->sound3D.cone_inner_angle; settings.cone_outer_angle = soundact->sound3D.cone_outer_angle; @@ -406,21 +406,21 @@ void BL_ConvertActuators(const char* maggiename, } else { - snd_sound = *reinterpret_cast*>(sound->playback_handle); + snd_sound = *reinterpret_cast*>(sound->playback_handle); // if sound shall be 3D but isn't mono, we have to make it mono! if (is3d) { try { - AUD_Reference reader = snd_sound->createReader(); + boost::shared_ptr reader = snd_sound->createReader(); if (reader->getSpecs().channels != AUD_CHANNELS_MONO) { AUD_DeviceSpecs specs; specs.channels = AUD_CHANNELS_MONO; specs.rate = AUD_RATE_INVALID; specs.format = AUD_FORMAT_INVALID; - snd_sound = new AUD_ChannelMapperFactory(snd_sound, specs); + snd_sound = boost::shared_ptr(new AUD_ChannelMapperFactory(snd_sound, specs)); } } catch(AUD_Exception&) diff --git a/source/gameengine/Converter/SConscript b/source/gameengine/Converter/SConscript index e95ae5448fb..bfd44dc90fc 100644 --- a/source/gameengine/Converter/SConscript +++ b/source/gameengine/Converter/SConscript @@ -24,6 +24,7 @@ incs += ' #extern/recastnavigation/Detour/Include' incs += ' #extern/Eigen3' incs += ' ' + env['BF_BULLET_INC'] +incs += ' ' + env['BF_BOOST_INC'] if env['BF_DEBUG']: if env['OURPLATFORM'] in ('win32-mingw', 'win32-vc', 'win64-vc', 'win64-mingw'): diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt index 4778a6ef9b9..2eada3e5071 100644 --- a/source/gameengine/Ketsji/CMakeLists.txt +++ b/source/gameengine/Ketsji/CMakeLists.txt @@ -57,6 +57,7 @@ set(INC set(INC_SYS ${PTHREADS_INCLUDE_DIRS} ${GLEW_INCLUDE_PATH} + ${BOOST_INCLUDE_DIR} ../../../extern/recastnavigation/Recast/Include ../../../extern/recastnavigation/Detour/Include ) diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index 2999550fb8f..e5f7ea22b36 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -117,7 +117,7 @@ bool KX_ObjectActuator::Update() } // Explicitly stop the movement if we're using a character (apply movement is a little different for characters) - if (parent->GetPhysicsController()->IsCharacter()) { + if (parent->GetPhysicsController() && parent->GetPhysicsController()->IsCharacter()) { MT_Vector3 vec(0.0, 0.0, 0.0); parent->ApplyMovement(vec, true); } diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index f76f94aa81d..2a4f2b3e7d9 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -53,7 +53,7 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj, - AUD_Reference sound, + boost::shared_ptr sound, float volume, float pitch, bool is3d, @@ -74,20 +74,20 @@ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj, KX_SoundActuator::~KX_SoundActuator() { - if (!m_handle.isNull()) + if (m_handle.get()) m_handle->stop(); } void KX_SoundActuator::play() { - if (!m_handle.isNull()) + if (m_handle.get()) m_handle->stop(); - if (m_sound.isNull()) + if (!m_sound.get()) return; // this is the sound that will be played and not deleted afterwards - AUD_Reference sound = m_sound; + boost::shared_ptr sound = m_sound; bool loop = false; @@ -95,7 +95,7 @@ void KX_SoundActuator::play() { case KX_SOUNDACT_LOOPBIDIRECTIONAL: case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP: - sound = new AUD_PingPongFactory(sound); + sound = boost::shared_ptr(new AUD_PingPongFactory(sound)); // fall through case KX_SOUNDACT_LOOPEND: case KX_SOUNDACT_LOOPSTOP: @@ -117,9 +117,9 @@ void KX_SoundActuator::play() return; } - AUD_Reference handle3d = AUD_Reference(m_handle); + boost::shared_ptr handle3d = boost::dynamic_pointer_cast(m_handle); - if (m_is3d && !handle3d.isNull()) + if (m_is3d && handle3d.get()) { handle3d->setRelative(true); handle3d->setVolumeMaximum(m_3d.max_gain); @@ -149,7 +149,7 @@ CValue* KX_SoundActuator::GetReplica() void KX_SoundActuator::ProcessReplica() { SCA_IActuator::ProcessReplica(); - m_handle = AUD_Reference(); + m_handle = boost::shared_ptr(); } bool KX_SoundActuator::Update(double curtime, bool frame) @@ -164,11 +164,11 @@ bool KX_SoundActuator::Update(double curtime, bool frame) RemoveAllEvents(); - if (m_sound.isNull()) + if (!m_sound.get()) return false; // actual audio device playing state - bool isplaying = m_handle.isNull() ? false : (m_handle->getStatus() == AUD_STATUS_PLAYING); + bool isplaying = m_handle.get() ? (m_handle->getStatus() == AUD_STATUS_PLAYING) : false; if (bNegativeEvent) { @@ -182,9 +182,9 @@ bool KX_SoundActuator::Update(double curtime, bool frame) case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP: { // stop immediately - if (!m_handle.isNull()) + if (m_handle.get()) m_handle->stop(); - m_handle = AUD_Reference(); + m_handle = boost::shared_ptr(); break; } case KX_SOUNDACT_PLAYEND: @@ -196,7 +196,7 @@ bool KX_SoundActuator::Update(double curtime, bool frame) case KX_SOUNDACT_LOOPBIDIRECTIONAL: { // stop the looping so that the sound stops when it finished - if (!m_handle.isNull()) + if (m_handle.get()) m_handle->setLoopCount(0); break; } @@ -223,13 +223,13 @@ bool KX_SoundActuator::Update(double curtime, bool frame) play(); } // verify that the sound is still playing - isplaying = m_handle.isNull() ? false : (m_handle->getStatus() == AUD_STATUS_PLAYING); + isplaying = m_handle.get() ? (m_handle->getStatus() == AUD_STATUS_PLAYING) : false; if (isplaying) { - AUD_Reference handle3d = AUD_Reference(m_handle); + boost::shared_ptr handle3d = boost::dynamic_pointer_cast(m_handle); - if (m_is3d && !handle3d.isNull()) + if (m_is3d && handle3d.get()) { KX_Camera* cam = KX_GetActiveScene()->GetActiveCamera(); if (cam) @@ -325,7 +325,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, startSound, "startSound()\n" "\tStarts the sound.\n") { - switch (m_handle.isNull() ? AUD_STATUS_INVALID : m_handle->getStatus()) { + switch (m_handle.get() ? m_handle->getStatus() : AUD_STATUS_INVALID) { case AUD_STATUS_PLAYING: break; case AUD_STATUS_PAUSED: @@ -341,7 +341,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, pauseSound, "pauseSound()\n" "\tPauses the sound.\n") { - if (!m_handle.isNull()) + if (m_handle.get()) m_handle->pause(); Py_RETURN_NONE; } @@ -350,9 +350,9 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, stopSound, "stopSound()\n" "\tStops the sound.\n") { - if (!m_handle.isNull()) + if (m_handle.get()) m_handle->stop(); - m_handle = AUD_Reference(); + m_handle = boost::shared_ptr(); Py_RETURN_NONE; } @@ -400,7 +400,7 @@ PyObject *KX_SoundActuator::pyattr_get_audposition(void *self, const struct KX_P KX_SoundActuator * actuator = static_cast (self); float position = 0.0; - if (!actuator->m_handle.isNull()) + if (actuator->m_handle.get()) position = actuator->m_handle->getPosition(); PyObject *result = PyFloat_FromDouble(position); @@ -431,7 +431,7 @@ PyObject *KX_SoundActuator::pyattr_get_pitch(void *self, const struct KX_PYATTRI PyObject *KX_SoundActuator::pyattr_get_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SoundActuator * actuator = static_cast (self); - if (!actuator->m_sound.isNull()) + if (actuator->m_sound.get()) return (PyObject *)AUD_getPythonFactory(&actuator->m_sound); else Py_RETURN_NONE; @@ -446,49 +446,49 @@ int KX_SoundActuator::pyattr_set_3d_property(void *self, const struct KX_PYATTRI if (!PyArg_Parse(value, "f", &prop_value)) return PY_SET_ATTR_FAIL; - AUD_Reference handle3d = AUD_Reference(actuator->m_handle); + boost::shared_ptr handle3d = boost::dynamic_pointer_cast(actuator->m_handle); // if sound is working and 3D, set the new setting if (!actuator->m_is3d) return PY_SET_ATTR_FAIL; if (!strcmp(prop, "volume_maximum")) { actuator->m_3d.max_gain = prop_value; - if (!handle3d.isNull()) + if (handle3d.get()) handle3d->setVolumeMaximum(prop_value); } else if (!strcmp(prop, "volume_minimum")) { actuator->m_3d.min_gain = prop_value; - if (!handle3d.isNull()) + if (handle3d.get()) handle3d->setVolumeMinimum(prop_value); } else if (!strcmp(prop, "distance_reference")) { actuator->m_3d.reference_distance = prop_value; - if (!handle3d.isNull()) + if (handle3d.get()) handle3d->setDistanceReference(prop_value); } else if (!strcmp(prop, "distance_maximum")) { actuator->m_3d.max_distance = prop_value; - if (!handle3d.isNull()) + if (handle3d.get()) handle3d->setDistanceMaximum(prop_value); } else if (!strcmp(prop, "attenuation")) { actuator->m_3d.rolloff_factor = prop_value; - if (!handle3d.isNull()) + if (handle3d.get()) handle3d->setAttenuation(prop_value); } else if (!!strcmp(prop, "cone_angle_inner")) { actuator->m_3d.cone_inner_angle = prop_value; - if (!handle3d.isNull()) + if (handle3d.get()) handle3d->setConeAngleInner(prop_value); } else if (!strcmp(prop, "cone_angle_outer")) { actuator->m_3d.cone_outer_angle = prop_value; - if (!handle3d.isNull()) + if (handle3d.get()) handle3d->setConeAngleOuter(prop_value); } else if (!strcmp(prop, "cone_volume_outer")) { actuator->m_3d.cone_outer_gain = prop_value; - if (!handle3d.isNull()) + if (handle3d.get()) handle3d->setConeVolumeOuter(prop_value); } else { @@ -506,7 +506,7 @@ int KX_SoundActuator::pyattr_set_audposition(void *self, const struct KX_PYATTRI if (!PyArg_Parse(value, "f", &position)) return PY_SET_ATTR_FAIL; - if (!actuator->m_handle.isNull()) + if (actuator->m_handle.get()) actuator->m_handle->seek(position); return PY_SET_ATTR_SUCCESS; } @@ -519,7 +519,7 @@ int KX_SoundActuator::pyattr_set_gain(void *self, const struct KX_PYATTRIBUTE_DE return PY_SET_ATTR_FAIL; actuator->m_volume = gain; - if (!actuator->m_handle.isNull()) + if (actuator->m_handle.get()) actuator->m_handle->setVolume(gain); return PY_SET_ATTR_SUCCESS; @@ -533,7 +533,7 @@ int KX_SoundActuator::pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_D return PY_SET_ATTR_FAIL; actuator->m_pitch = pitch; - if (!actuator->m_handle.isNull()) + if (actuator->m_handle.get()) actuator->m_handle->setPitch(pitch); return PY_SET_ATTR_SUCCESS; @@ -546,7 +546,7 @@ int KX_SoundActuator::pyattr_set_sound(void *self, const struct KX_PYATTRIBUTE_D if (!PyArg_Parse(value, "O", &sound)) return PY_SET_ATTR_FAIL; - AUD_Reference* snd = reinterpret_cast*>(AUD_getPythonSound((void *)sound)); + boost::shared_ptr* snd = reinterpret_cast*>(AUD_getPythonSound((void *)sound)); if (snd) { actuator->m_sound = *snd; diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h index 1ce44e942e8..68eff56797b 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.h +++ b/source/gameengine/Ketsji/KX_SoundActuator.h @@ -36,9 +36,9 @@ #ifdef WITH_AUDASPACE # include "AUD_C-API.h" -# include "AUD_Reference.h" # include "AUD_IFactory.h" # include "AUD_IHandle.h" +# include #endif #include "BKE_sound.h" @@ -58,12 +58,12 @@ class KX_SoundActuator : public SCA_IActuator { Py_Header bool m_isplaying; - AUD_Reference m_sound; + boost::shared_ptr m_sound; float m_volume; float m_pitch; bool m_is3d; KX_3DSoundSettings m_3d; - AUD_Reference m_handle; + boost::shared_ptr m_handle; void play(); @@ -84,7 +84,7 @@ public: KX_SOUNDACT_TYPE m_type; KX_SoundActuator(SCA_IObject* gameobj, - AUD_Reference sound, + boost::shared_ptr sound, float volume, float pitch, bool is3d, diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript index 5fdf250006f..88689a5a736 100644 --- a/source/gameengine/Ketsji/SConscript +++ b/source/gameengine/Ketsji/SConscript @@ -24,6 +24,7 @@ incs += ' #extern/recastnavigation/Recast/Include #extern/recastnavigation/Detou incs += ' ' + env['BF_BULLET_INC'] incs += ' ' + env['BF_OPENGL_INC'] +incs += ' ' + env['BF_BOOST_INC'] if env['WITH_BF_SDL']: incs += ' ' + env['BF_SDL_INC'] From b1afaa8312cf2dcb601f0e91cef66efd62f0682a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 10 Dec 2012 15:18:00 +0000 Subject: [PATCH 158/160] Merging r51923 through r52851 from trunk into soc-2011-tomato --- CMakeLists.txt | 435 ++-- GNUmakefile | 49 +- SConstruct | 66 +- build_files/build_environment/install_deps.sh | 1875 +++++++++++++++++ .../build_environment/prepare_release_env.sh | 76 +- .../config/user-config-glibc211-i686.py | 27 +- .../config/user-config-glibc211-x86_64.py | 24 +- .../config/user-config-glibc27-i686.py | 26 +- .../config/user-config-glibc27-x86_64.py | 23 +- .../user-config-player-glibc211-i686.py | 5 +- .../user-config-player-glibc211-x86_64.py | 5 +- .../config/user-config-player-glibc27-i686.py | 4 +- .../user-config-player-glibc27-x86_64.py | 4 +- build_files/buildbot/master.cfg | 14 +- build_files/buildbot/slave_rsync.py | 45 + build_files/cmake/Modules/FindIcuLinux.cmake | 146 ++ .../cmake/Modules/FindOpenColorIO.cmake | 1 + .../cmake/Modules/FindOpenImageIO.cmake | 1 + .../cmake/Modules/FindPythonLibsUnix.cmake | 65 +- build_files/cmake/cmake_consistency_check.py | 6 +- build_files/cmake/cmake_netbeans_project.py | 2 +- build_files/cmake/cmake_qtcreator_project.py | 2 +- .../cmake/cmake_static_check_clang_array.py | 13 +- .../cmake/cmake_static_check_cppcheck.py | 18 +- .../cmake/cmake_static_check_smatch.py | 13 +- .../cmake/cmake_static_check_sparse.py | 14 +- .../cmake/cmake_static_check_splint.py | 14 +- .../cmake/example_scripts/make_quicky.py | 2 +- build_files/cmake/macros.cmake | 21 +- build_files/cmake/project_info.py | 2 +- build_files/scons/config/darwin-config.py | 46 +- build_files/scons/config/freebsd7-config.py | 7 +- build_files/scons/config/freebsd8-config.py | 7 +- build_files/scons/config/freebsd9-config.py | 7 +- build_files/scons/config/linux-config.py | 24 +- build_files/scons/config/linuxcross-config.py | 7 +- .../scons/config/win32-mingw-config.py | 22 +- build_files/scons/config/win32-vc-config.py | 35 +- .../scons/config/win64-mingw-config.py | 16 +- build_files/scons/config/win64-vc-config.py | 37 +- build_files/scons/tools/Blender.py | 61 +- build_files/scons/tools/btools.py | 52 +- .../BlendFileDnaExporter_25.py | 2 +- doc/blender_file_format/BlendFileReader.py | 2 +- doc/manpage/blender.1 | 14 +- doc/python_api/examples/bmesh.ops.1.py | 108 + doc/python_api/rst/bge.logic.rst | 550 +++-- doc/python_api/rst/bge.types.rst | 638 +++--- doc/python_api/rst/bgl.rst | 253 ++- doc/python_api/rst/gpu.rst | 8 +- doc/python_api/rst/include__bmesh.rst | 8 +- doc/python_api/rst/info_api_reference.rst | 305 +++ doc/python_api/rst/info_gotcha.rst | 76 +- doc/python_api/rst/info_overview.rst | 2 + doc/python_api/rst/info_quickstart.rst | 2 + doc/python_api/rst/info_tips_and_tricks.rst | 14 +- doc/python_api/rst/info_tutorial_addon.rst | 645 ++++++ doc/python_api/rst_from_bmesh_opdefines.py | 380 ++++ doc/python_api/sphinx_doc_gen.py | 33 +- extern/CMakeLists.txt | 7 +- extern/SConscript | 3 + extern/glew/src/glew.c | 4 +- extern/libmv/CMakeLists.txt | 3 + extern/libmv/libmv-capi.cpp | 7 +- extern/libmv/libmv/simple_pipeline/resect.cc | 2 +- extern/xdnd/xdnd.c | 2 +- intern/CMakeLists.txt | 4 + intern/SConscript | 3 + intern/audaspace/intern/AUD_FileWriter.h | 8 +- .../intern/AUD_LinearResampleReader.cpp | 2 +- intern/bsp/intern/BOP_CarveInterface.cpp | 4 +- intern/container/CTR_HashedPtr.h | 6 +- intern/cycles/CMakeLists.txt | 16 +- intern/cycles/SConscript | 15 +- intern/cycles/app/CMakeLists.txt | 4 - intern/cycles/app/cycles_test.cpp | 2 +- intern/cycles/blender/CCL_api.h | 6 +- intern/cycles/blender/addon/__init__.py | 6 +- intern/cycles/blender/addon/engine.py | 7 + intern/cycles/blender/addon/enums.py | 6 +- intern/cycles/blender/addon/osl.py | 7 +- intern/cycles/blender/addon/ui.py | 8 +- intern/cycles/blender/blender_camera.cpp | 237 ++- intern/cycles/blender/blender_mesh.cpp | 106 +- intern/cycles/blender/blender_object.cpp | 105 +- intern/cycles/blender/blender_particles.cpp | 206 +- intern/cycles/blender/blender_python.cpp | 52 +- intern/cycles/blender/blender_session.cpp | 59 +- intern/cycles/blender/blender_session.h | 2 + intern/cycles/blender/blender_shader.cpp | 93 +- intern/cycles/blender/blender_sync.cpp | 31 +- intern/cycles/blender/blender_sync.h | 21 +- intern/cycles/blender/blender_util.h | 58 +- intern/cycles/cmake/external_libs.cmake | 27 - intern/cycles/device/device.cpp | 17 +- intern/cycles/device/device.h | 2 +- intern/cycles/device/device_cpu.cpp | 55 +- intern/cycles/device/device_cuda.cpp | 15 +- intern/cycles/device/device_intern.h | 2 +- intern/cycles/device/device_task.cpp | 2 +- intern/cycles/kernel/CMakeLists.txt | 1 + intern/cycles/kernel/SConscript | 5 +- .../cycles/kernel/closure/bsdf_phong_ramp.h | 140 ++ intern/cycles/kernel/closure/bsdf_ward.h | 10 +- intern/cycles/kernel/kernel.cpp | 32 - intern/cycles/kernel/kernel_accumulate.h | 4 - intern/cycles/kernel/kernel_attribute.h | 22 +- intern/cycles/kernel/kernel_camera.h | 21 +- intern/cycles/kernel/kernel_globals.h | 18 +- intern/cycles/kernel/kernel_light.h | 7 +- intern/cycles/kernel/kernel_object.h | 28 +- intern/cycles/kernel/kernel_passes.h | 4 +- intern/cycles/kernel/kernel_path.h | 46 +- intern/cycles/kernel/kernel_projection.h | 2 +- intern/cycles/kernel/kernel_shader.h | 74 +- intern/cycles/kernel/kernel_triangle.h | 3 - intern/cycles/kernel/kernel_types.h | 30 +- intern/cycles/kernel/osl/CMakeLists.txt | 1 + intern/cycles/kernel/osl/SConscript | 27 + intern/cycles/kernel/osl/background.cpp | 27 + intern/cycles/kernel/osl/bsdf_phong_ramp.cpp | 115 + intern/cycles/kernel/osl/osl_closures.cpp | 8 +- intern/cycles/kernel/osl/osl_closures.h | 42 +- intern/cycles/kernel/osl/osl_globals.h | 28 +- intern/cycles/kernel/osl/osl_services.cpp | 464 +++- intern/cycles/kernel/osl/osl_services.h | 69 +- intern/cycles/kernel/osl/osl_shader.cpp | 147 +- intern/cycles/kernel/osl/osl_shader.h | 21 +- intern/cycles/kernel/shaders/CMakeLists.txt | 14 +- intern/cycles/kernel/shaders/SConscript | 42 + .../kernel/shaders/node_ambient_occlusion.osl | 28 + .../kernel/shaders/node_brick_texture.osl | 9 +- .../cycles/kernel/shaders/node_brightness.osl | 29 +- .../kernel/shaders/node_checker_texture.osl | 9 +- .../shaders/node_convert_from_color.osl | 3 +- .../shaders/node_convert_from_float.osl | 1 + .../kernel/shaders/node_convert_from_int.osl | 1 + .../shaders/node_convert_from_normal.osl | 1 + .../shaders/node_convert_from_point.osl | 1 + .../shaders/node_convert_from_string.osl | 31 + .../shaders/node_convert_from_vector.osl | 1 + .../shaders/node_environment_texture.osl | 40 +- .../cycles/kernel/shaders/node_geometry.osl | 26 +- .../kernel/shaders/node_gradient_texture.osl | 9 +- intern/cycles/kernel/shaders/node_hsv.osl | 3 +- .../kernel/shaders/node_image_texture.osl | 33 +- .../kernel/shaders/node_light_falloff.osl | 6 +- .../kernel/shaders/node_magic_texture.osl | 9 +- intern/cycles/kernel/shaders/node_mapping.osl | 10 +- intern/cycles/kernel/shaders/node_mix.osl | 2 +- .../kernel/shaders/node_musgrave_texture.osl | 9 +- .../kernel/shaders/node_noise_texture.osl | 9 +- .../cycles/kernel/shaders/node_normal_map.osl | 52 + .../kernel/shaders/node_refraction_bsdf.osl | 39 + .../cycles/kernel/shaders/node_rgb_ramp.osl | 3 + .../kernel/shaders/node_sky_texture.osl | 15 +- intern/cycles/kernel/shaders/node_tangent.osl | 50 + .../shaders/node_texture_coordinate.osl | 4 +- .../kernel/shaders/node_voronoi_texture.osl | 9 +- .../cycles/kernel/shaders/node_ward_bsdf.osl | 12 +- .../kernel/shaders/node_wave_texture.osl | 9 +- intern/cycles/kernel/shaders/stdosl.h | 2 + intern/cycles/kernel/svm/svm.h | 13 + intern/cycles/kernel/svm/svm_brick.h | 21 +- intern/cycles/kernel/svm/svm_bsdf.h | 21 +- intern/cycles/kernel/svm/svm_closure.h | 303 ++- intern/cycles/kernel/svm/svm_geometry.h | 23 +- intern/cycles/kernel/svm/svm_hsv.h | 2 +- intern/cycles/kernel/svm/svm_math.h | 17 +- intern/cycles/kernel/svm/svm_ramp.h | 3 +- intern/cycles/kernel/svm/svm_tex_coord.h | 112 +- intern/cycles/kernel/svm/svm_texture.h | 43 +- intern/cycles/kernel/svm/svm_types.h | 31 +- intern/cycles/kernel/svm/svm_voronoi.h | 9 +- intern/cycles/render/attribute.cpp | 4 +- intern/cycles/render/camera.cpp | 57 +- intern/cycles/render/camera.h | 13 +- intern/cycles/render/graph.cpp | 105 +- intern/cycles/render/graph.h | 22 +- intern/cycles/render/image.cpp | 24 +- intern/cycles/render/image.h | 7 +- intern/cycles/render/light.cpp | 8 + intern/cycles/render/mesh.cpp | 4 +- intern/cycles/render/nodes.cpp | 395 +++- intern/cycles/render/nodes.h | 50 +- intern/cycles/render/object.cpp | 35 +- intern/cycles/render/object.h | 4 +- intern/cycles/render/osl.cpp | 22 +- intern/cycles/render/osl.h | 5 +- intern/cycles/render/particles.cpp | 3 +- intern/cycles/render/scene.cpp | 95 +- intern/cycles/render/scene.h | 10 +- intern/cycles/render/session.cpp | 29 +- intern/cycles/render/session.h | 1 + intern/cycles/render/shader.cpp | 4 +- intern/cycles/render/shader.h | 4 +- intern/cycles/render/svm.cpp | 77 +- intern/cycles/render/svm.h | 7 +- intern/cycles/util/CMakeLists.txt | 3 +- intern/cycles/util/util_attribute.cpp | 4 +- intern/cycles/util/util_boundbox.h | 81 + intern/cycles/util/util_opencl.cpp | 4 + intern/cycles/util/util_progress.h | 15 + intern/cycles/util/util_stats.h | 11 +- intern/cycles/util/util_task.cpp | 10 +- intern/cycles/util/util_task.h | 5 +- intern/cycles/util/util_thread.h | 38 - intern/cycles/util/util_transform.cpp | 25 +- intern/cycles/util/util_transform.h | 71 +- intern/cycles/util/util_types.h | 5 +- intern/elbeem/intern/ntl_geometryobject.cpp | 2 +- intern/elbeem/intern/ntl_world.cpp | 11 +- intern/elbeem/intern/ntl_world.h | 3 + intern/ghost/CMakeLists.txt | 1 - intern/ghost/GHOST_C-api.h | 14 +- intern/ghost/intern/GHOST_NDOFManagerX11.cpp | 4 +- intern/ghost/intern/GHOST_SystemCocoa.h | 3 - intern/ghost/intern/GHOST_SystemCocoa.mm | 41 +- intern/ghost/intern/GHOST_SystemSDL.cpp | 2 +- intern/ghost/intern/GHOST_SystemX11.cpp | 2 +- intern/ghost/intern/GHOST_WindowCocoa.mm | 19 +- intern/ghost/intern/GHOST_WindowSDL.cpp | 28 +- intern/ghost/intern/GHOST_WindowWin32.cpp | 2 +- intern/ghost/intern/GHOST_WindowX11.cpp | 4 + intern/guardedalloc/cpp/mallocn.cpp | 3 + intern/guardedalloc/intern/mallocn.c | 2 +- intern/iksolver/intern/IK_QJacobianSolver.cpp | 2 +- intern/itasc/CMakeLists.txt | 2 +- intern/itasc/kdl/chain.hpp | 9 +- intern/itasc/kdl/tree.hpp | 19 +- intern/locale/CMakeLists.txt | 47 + intern/locale/SConscript | 14 + intern/locale/boost_locale_wrapper.cpp | 114 + intern/locale/boost_locale_wrapper.h | 49 + intern/memutil/MEM_CacheLimiter.h | 6 +- intern/memutil/MEM_SmartPtr.h | 2 +- intern/opencolorio/ocio_impl.cc | 5 +- intern/opennl/CMakeLists.txt | 6 +- intern/smoke/intern/FFT_NOISE.h | 2 + intern/smoke/intern/WTURBULENCE.cpp | 20 +- intern/utfconv/utfconv.h | 20 +- .../darwin/blender.app/Contents/Info.plist | 0 .../darwin/blender.app/Contents/MacOS/blender | 0 .../darwin/blender.app/Contents/PkgInfo | 0 .../Contents/Resources/blender file icon.icns | Bin .../Contents/Resources/blender icon.icns | Bin .../blenderplayer.app/Contents/Info.plist | 0 .../Contents/MacOS/blenderplayer | 0 .../darwin/blenderplayer.app/Contents/PkgInfo | 0 .../Contents/Resources/blender file icon.icns | Bin .../Resources/blender player icon.icns | Bin .../Contents/Info.plist | 0 .../Contents/MacOS/applet | Bin .../Contents/PkgInfo | 0 .../Contents/Resources/Scripts/main.scpt | Bin .../Contents/Resources/applet.icns | Bin .../Contents/Resources/applet.rsrc | Bin .../Resources/description.rtfd/TXT.rtf | 0 release/datafiles/blender_icons.png | Bin 228428 -> 189744 bytes release/datafiles/prvicons.png | Bin 14130 -> 13948 bytes release/datafiles/splash.png | Bin 212426 -> 330539 bytes release/datafiles/startup.blend | Bin 408072 -> 415348 bytes release/scripts/modules/addon_utils.py | 2 +- .../scripts/modules/bl_i18n_utils/settings.py | 88 +- .../bl_i18n_utils/spell_check_utils.py | 6 + .../bl_i18n_utils/update_languages_menu.py | 20 +- .../modules/bl_i18n_utils/update_pot.py | 77 +- .../modules/bl_i18n_utils/update_trunk.py | 2 +- release/scripts/modules/bpy/ops.py | 4 +- release/scripts/modules/bpy/utils.py | 2 +- .../scripts/modules/bpy_extras/mesh_utils.py | 18 +- release/scripts/modules/bpy_types.py | 2 +- release/scripts/modules/rna_xml.py | 2 +- .../presets/interface_theme/back_to_black.xml | 1565 +++++++------- .../presets/interface_theme/blender_24x.xml | 1589 +++++++------- .../presets/interface_theme/elsyiun.xml | 1579 +++++++------- .../presets/interface_theme/hexagon.xml | 1587 +++++++------- .../interface_theme/ubuntu_ambiance.xml | 1583 +++++++------- release/scripts/presets/keyconfig/maya.py | 2 +- release/scripts/startup/bl_operators/image.py | 2 +- .../scripts/startup/bl_operators/object.py | 49 +- .../scripts/startup/bl_operators/presets.py | 6 + .../bl_operators/screen_play_rendered_anim.py | 8 +- .../bl_operators/uvcalc_follow_active.py | 279 +-- .../startup/bl_operators/uvcalc_lightmap.py | 2 +- .../bl_operators/uvcalc_smart_project.py | 12 +- release/scripts/startup/bl_operators/wm.py | 13 +- .../startup/bl_ui/properties_data_armature.py | 2 +- .../startup/bl_ui/properties_data_bone.py | 1 - .../startup/bl_ui/properties_data_camera.py | 8 +- .../startup/bl_ui/properties_data_curve.py | 7 +- .../startup/bl_ui/properties_data_modifier.py | 7 +- .../bl_ui/properties_object_constraint.py | 28 +- .../startup/bl_ui/properties_particle.py | 2 +- .../scripts/startup/bl_ui/space_console.py | 2 +- .../scripts/startup/bl_ui/space_dopesheet.py | 6 +- release/scripts/startup/bl_ui/space_graph.py | 6 +- release/scripts/startup/bl_ui/space_image.py | 7 +- release/scripts/startup/bl_ui/space_info.py | 4 +- .../scripts/startup/bl_ui/space_sequencer.py | 8 +- release/scripts/startup/bl_ui/space_text.py | 15 - .../scripts/startup/bl_ui/space_userpref.py | 28 +- release/scripts/startup/bl_ui/space_view3d.py | 27 +- .../startup/bl_ui/space_view3d_toolbar.py | 6 +- release/scripts/templates/bmesh_simple.py | 1 + .../templates/bmesh_simple_editmode.py | 23 + release/scripts/templates/script_stub.py | 5 +- release/text/readme.html | 10 +- source/blender/avi/intern/avi.c | 14 +- source/blender/avi/intern/avi_rgb.c | 2 +- source/blender/blenfont/BLF_translation.h | 75 +- source/blender/blenfont/CMakeLists.txt | 4 +- source/blender/blenfont/SConscript | 3 +- source/blender/blenfont/intern/blf.c | 1 - source/blender/blenfont/intern/blf_lang.c | 254 +-- .../blender/blenfont/intern/blf_translation.c | 86 +- source/blender/blenkernel/BKE_DerivedMesh.h | 8 +- source/blender/blenkernel/BKE_blender.h | 8 +- source/blender/blenkernel/BKE_global.h | 3 + source/blender/blenkernel/BKE_icons.h | 4 +- source/blender/blenkernel/BKE_image.h | 10 +- source/blender/blenkernel/BKE_lamp.h | 3 + source/blender/blenkernel/BKE_mesh.h | 4 +- source/blender/blenkernel/BKE_modifier.h | 4 +- source/blender/blenkernel/BKE_multires.h | 2 +- source/blender/blenkernel/BKE_node.h | 12 +- source/blender/blenkernel/BKE_sequencer.h | 2 +- source/blender/blenkernel/BKE_text.h | 34 +- source/blender/blenkernel/BKE_utildefines.h | 6 +- source/blender/blenkernel/CMakeLists.txt | 14 +- source/blender/blenkernel/SConscript | 4 +- .../blender/blenkernel/intern/DerivedMesh.c | 157 +- source/blender/blenkernel/intern/action.c | 4 +- source/blender/blenkernel/intern/anim.c | 123 +- source/blender/blenkernel/intern/anim_sys.c | 17 +- source/blender/blenkernel/intern/armature.c | 9 +- source/blender/blenkernel/intern/blender.c | 10 +- source/blender/blenkernel/intern/bmfont.c | 13 +- source/blender/blenkernel/intern/brush.c | 2 - source/blender/blenkernel/intern/camera.c | 1 + .../blender/blenkernel/intern/cdderivedmesh.c | 104 +- source/blender/blenkernel/intern/collision.c | 10 +- source/blender/blenkernel/intern/colortools.c | 39 +- source/blender/blenkernel/intern/constraint.c | 8 +- source/blender/blenkernel/intern/context.c | 10 + source/blender/blenkernel/intern/curve.c | 16 +- source/blender/blenkernel/intern/customdata.c | 4 +- source/blender/blenkernel/intern/depsgraph.c | 72 +- source/blender/blenkernel/intern/displist.c | 111 +- .../blender/blenkernel/intern/dynamicpaint.c | 10 +- .../blenkernel/intern/editderivedmesh.c | 2 +- source/blender/blenkernel/intern/idcode.c | 65 +- source/blender/blenkernel/intern/image.c | 299 +-- source/blender/blenkernel/intern/lamp.c | 40 +- source/blender/blenkernel/intern/library.c | 5 +- source/blender/blenkernel/intern/mask.c | 12 +- .../blender/blenkernel/intern/mask_evaluate.c | 8 +- .../blenkernel/intern/mask_rasterize.c | 2 +- source/blender/blenkernel/intern/mesh.c | 6 +- source/blender/blenkernel/intern/modifier.c | 4 +- .../blenkernel/intern/modifiers_bmesh.c | 6 +- source/blender/blenkernel/intern/movieclip.c | 11 +- source/blender/blenkernel/intern/multires.c | 2 +- source/blender/blenkernel/intern/node.c | 32 +- source/blender/blenkernel/intern/object.c | 20 +- source/blender/blenkernel/intern/ocean.c | 20 +- source/blender/blenkernel/intern/particle.c | 32 +- .../blenkernel/intern/particle_system.c | 25 +- source/blender/blenkernel/intern/pointcache.c | 9 +- source/blender/blenkernel/intern/scene.c | 33 +- source/blender/blenkernel/intern/seqeffects.c | 3 + .../blender/blenkernel/intern/seqmodifier.c | 12 +- source/blender/blenkernel/intern/sequencer.c | 44 +- source/blender/blenkernel/intern/shrinkwrap.c | 49 +- source/blender/blenkernel/intern/smoke.c | 33 +- source/blender/blenkernel/intern/sound.c | 20 +- .../blender/blenkernel/intern/subsurf_ccg.c | 3 +- .../blender/blenkernel/intern/suggestions.c | 10 +- source/blender/blenkernel/intern/text.c | 1036 +++------ source/blender/blenkernel/intern/tracking.c | 36 +- .../blender/blenkernel/intern/writeffmpeg.c | 41 +- source/blender/blenlib/BLI_array.h | 27 +- source/blender/blenlib/BLI_bpath.h | 5 + source/blender/blenlib/BLI_endian_switch.h | 3 +- .../blenlib/BLI_endian_switch_inline.h | 34 +- source/blender/blenlib/BLI_ghash.h | 2 +- source/blender/blenlib/BLI_math.h | 1 + source/blender/blenlib/BLI_math_base.h | 4 +- source/blender/blenlib/BLI_math_color.h | 2 +- source/blender/blenlib/BLI_math_geom.h | 6 +- source/blender/blenlib/BLI_math_inline.h | 5 +- source/blender/blenlib/BLI_math_interp.h | 44 + source/blender/blenlib/BLI_math_matrix.h | 21 +- source/blender/blenlib/BLI_math_vector.h | 3 +- source/blender/blenlib/BLI_pbvh.h | 3 +- source/blender/blenlib/BLI_quadric.h | 2 +- source/blender/blenlib/BLI_rect.h | 14 +- source/blender/blenlib/BLI_scanfill.h | 13 +- source/blender/blenlib/BLI_string_utf8.h | 1 + source/blender/blenlib/BLI_threads.h | 17 + source/blender/blenlib/BLI_utildefines.h | 19 +- source/blender/blenlib/CMakeLists.txt | 8 + source/blender/blenlib/PIL_time.h | 13 +- source/blender/blenlib/intern/BLI_ghash.c | 2 +- source/blender/blenlib/intern/BLI_kdopbvh.c | 4 +- source/blender/blenlib/intern/bpath.c | 197 +- .../blender/blenlib/intern/math_base_inline.c | 24 +- .../blenlib/intern/math_color_inline.c | 6 +- source/blender/blenlib/intern/math_geom.c | 34 + .../blender/blenlib/intern/math_geom_inline.c | 5 +- source/blender/blenlib/intern/math_interp.c | 351 +++ source/blender/blenlib/intern/math_matrix.c | 62 +- source/blender/blenlib/intern/math_rotation.c | 2 +- source/blender/blenlib/intern/math_vector.c | 27 + .../blenlib/intern/math_vector_inline.c | 5 +- source/blender/blenlib/intern/noise.c | 60 +- source/blender/blenlib/intern/pbvh.c | 13 +- source/blender/blenlib/intern/quadric.c | 9 +- source/blender/blenlib/intern/scanfill.c | 147 +- source/blender/blenlib/intern/smallhash.c | 18 +- source/blender/blenlib/intern/string.c | 22 +- .../blenlib/intern/string_cursor_utf8.c | 36 +- source/blender/blenlib/intern/string_utf8.c | 71 +- source/blender/blenlib/intern/threads.c | 36 + source/blender/blenlib/intern/voronoi.c | 6 +- source/blender/blenloader/intern/readfile.c | 150 +- .../blenloader/intern/versioning_250.c | 2 +- source/blender/blenloader/intern/writefile.c | 24 +- source/blender/bmesh/CMakeLists.txt | 10 +- source/blender/bmesh/bmesh.h | 4 +- source/blender/bmesh/bmesh_class.h | 44 +- source/blender/bmesh/intern/bmesh_construct.c | 46 +- source/blender/bmesh/intern/bmesh_construct.h | 4 +- source/blender/bmesh/intern/bmesh_core.c | 175 +- source/blender/bmesh/intern/bmesh_core.h | 15 +- source/blender/bmesh/intern/bmesh_interp.c | 20 +- source/blender/bmesh/intern/bmesh_iterators.c | 10 +- source/blender/bmesh/intern/bmesh_iterators.h | 7 +- source/blender/bmesh/intern/bmesh_mesh.c | 55 +- source/blender/bmesh/intern/bmesh_mesh.h | 12 +- source/blender/bmesh/intern/bmesh_mesh_conv.c | 31 +- source/blender/bmesh/intern/bmesh_mods.c | 9 +- source/blender/bmesh/intern/bmesh_opdefines.c | 1311 ++++++++---- .../blender/bmesh/intern/bmesh_operator_api.h | 243 ++- .../bmesh/intern/bmesh_operator_api_inline.h | 107 +- source/blender/bmesh/intern/bmesh_operators.c | 627 ++++-- source/blender/bmesh/intern/bmesh_operators.h | 20 +- .../bmesh/intern/bmesh_operators_private.h | 2 +- source/blender/bmesh/intern/bmesh_polygon.c | 9 +- source/blender/bmesh/intern/bmesh_private.h | 20 +- source/blender/bmesh/intern/bmesh_queries.c | 158 +- source/blender/bmesh/intern/bmesh_queries.h | 19 +- source/blender/bmesh/operators/bmo_bevel.c | 881 +------- source/blender/bmesh/operators/bmo_connect.c | 21 +- source/blender/bmesh/operators/bmo_create.c | 118 +- source/blender/bmesh/operators/bmo_dissolve.c | 30 +- source/blender/bmesh/operators/bmo_dupe.c | 166 +- .../blender/bmesh/operators/bmo_edgesplit.c | 20 +- source/blender/bmesh/operators/bmo_extrude.c | 78 +- source/blender/bmesh/operators/bmo_hull.c | 88 +- source/blender/bmesh/operators/bmo_inset.c | 61 +- .../bmesh/operators/bmo_join_triangles.c | 12 +- .../blender/bmesh/operators/bmo_mesh_conv.c | 14 +- source/blender/bmesh/operators/bmo_mirror.c | 29 +- .../blender/bmesh/operators/bmo_primitive.c | 155 +- .../bmesh/operators/bmo_removedoubles.c | 105 +- source/blender/bmesh/operators/bmo_similar.c | 30 +- source/blender/bmesh/operators/bmo_slide.c | 23 +- .../bmesh/operators/bmo_smooth_laplacian.c | 45 +- .../blender/bmesh/operators/bmo_subdivide.c | 85 +- .../blender/bmesh/operators/bmo_subdivide.h | 2 + .../blender/bmesh/operators/bmo_symmetrize.c | 55 +- .../blender/bmesh/operators/bmo_triangulate.c | 29 +- .../blender/bmesh/operators/bmo_unsubdivide.c | 6 +- source/blender/bmesh/operators/bmo_utils.c | 123 +- .../blender/bmesh/operators/bmo_wireframe.c | 95 +- source/blender/bmesh/tools/BME_bevel.c | 17 +- source/blender/bmesh/tools/bmesh_bevel.c | 1835 ++++++++++++++++ source/blender/bmesh/tools/bmesh_bevel.h | 32 + .../bmesh/{intern => tools}/bmesh_decimate.h | 5 +- .../bmesh_decimate_collapse.c | 139 +- .../bmesh_decimate_dissolve.c | 9 +- .../bmesh_decimate_unsubdivide.c | 8 +- source/blender/collada/AnimationImporter.cpp | 2 +- source/blender/collada/DocumentImporter.cpp | 4 +- source/blender/collada/DocumentImporter.h | 4 +- source/blender/collada/ImageExporter.cpp | 4 +- source/blender/collada/MaterialExporter.cpp | 2 +- source/blender/collada/MeshImporter.cpp | 2 +- source/blender/collada/TransformReader.cpp | 2 +- source/blender/collada/collada_utils.cpp | 4 +- source/blender/compositor/CMakeLists.txt | 4 + .../compositor/intern/COM_Converter.cpp | 4 + .../compositor/intern/COM_ExecutionGroup.cpp | 3 +- .../compositor/intern/COM_ExecutionGroup.h | 6 +- .../compositor/intern/COM_ExecutionSystem.cpp | 5 + source/blender/compositor/intern/COM_Node.cpp | 20 +- source/blender/compositor/intern/COM_Node.h | 4 + .../compositor/intern/COM_NodeOperation.h | 6 +- .../compositor/intern/COM_WorkPackage.h | 2 +- .../blender/compositor/nodes/COM_BlurNode.cpp | 48 +- .../compositor/nodes/COM_ImageNode.cpp | 14 +- .../compositor/nodes/COM_MapRangeNode.cpp | 54 + .../compositor/nodes/COM_MapRangeNode.h | 38 + .../blender/compositor/nodes/COM_MuteNode.cpp | 4 + .../compositor/nodes/COM_NormalNode.cpp | 11 +- .../compositor/nodes/COM_OutputFileNode.cpp | 6 + .../compositor/nodes/COM_ScaleNode.cpp | 22 +- .../compositor/nodes/COM_Stabilize2dNode.cpp | 2 + .../operations/COM_CropOperation.cpp | 6 + .../COM_FastGaussianBlurOperation.cpp | 5 +- .../operations/COM_GammaCorrectOperation.cpp | 28 +- .../operations/COM_ImageOperation.cpp | 6 +- .../operations/COM_KeyingScreenOperation.cpp | 33 +- .../operations/COM_MapRangeOperation.cpp | 96 + .../operations/COM_MapRangeOperation.h | 71 + .../COM_MovieDistortionOperation.cpp | 17 +- .../operations/COM_MovieDistortionOperation.h | 1 - .../operations/COM_NormalizeOperation.cpp | 6 + .../operations/COM_PixelateOperation.h | 2 +- .../operations/COM_RenderLayersBaseProg.cpp | 55 +- .../operations/COM_RenderLayersBaseProg.h | 1 + .../operations/COM_ScaleOperation.cpp | 51 +- .../operations/COM_ScaleOperation.h | 18 +- .../operations/COM_TrackPositionOperation.cpp | 2 +- .../operations/COM_ViewerBaseOperation.cpp | 12 +- .../editors/animation/anim_channels_edit.c | 20 +- source/blender/editors/animation/anim_draw.c | 2 +- .../blender/editors/animation/anim_filter.c | 20 +- .../blender/editors/animation/anim_markers.c | 64 +- source/blender/editors/animation/keyingsets.c | 20 +- .../blender/editors/armature/editarmature.c | 6 +- .../editors/armature/editarmature_sketch.c | 18 +- source/blender/editors/curve/editcurve.c | 36 +- source/blender/editors/curve/editfont.c | 7 + .../editors/gpencil/editaction_gpencil.c | 21 +- source/blender/editors/gpencil/gpencil_edit.c | 1109 +++++++++- .../blender/editors/gpencil/gpencil_paint.c | 289 ++- source/blender/editors/include/ED_gpencil.h | 4 +- source/blender/editors/include/ED_image.h | 2 +- source/blender/editors/include/ED_mask.h | 3 +- source/blender/editors/include/ED_mesh.h | 5 + source/blender/editors/include/ED_view3d.h | 14 +- source/blender/editors/include/UI_icons.h | 12 +- source/blender/editors/include/UI_interface.h | 8 +- source/blender/editors/include/UI_resources.h | 6 +- source/blender/editors/interface/interface.c | 47 +- .../editors/interface/interface_draw.c | 18 +- .../editors/interface/interface_handlers.c | 66 +- .../editors/interface/interface_intern.h | 22 +- .../editors/interface/interface_layout.c | 33 +- .../blender/editors/interface/interface_ops.c | 5 +- .../editors/interface/interface_regions.c | 153 +- .../editors/interface/interface_templates.c | 429 ++-- .../editors/interface/interface_widgets.c | 18 +- source/blender/editors/interface/resources.c | 43 +- source/blender/editors/mask/mask_editaction.c | 75 +- source/blender/editors/mesh/editmesh_add.c | 66 +- source/blender/editors/mesh/editmesh_bvh.c | 6 +- source/blender/editors/mesh/editmesh_knife.c | 103 +- .../blender/editors/mesh/editmesh_loopcut.c | 64 +- source/blender/editors/mesh/editmesh_rip.c | 4 +- source/blender/editors/mesh/editmesh_select.c | 732 +++++-- source/blender/editors/mesh/editmesh_slide.c | 18 +- source/blender/editors/mesh/editmesh_tools.c | 349 ++- source/blender/editors/mesh/editmesh_utils.c | 17 +- source/blender/editors/mesh/mesh_intern.h | 4 +- source/blender/editors/mesh/mesh_navmesh.c | 4 +- source/blender/editors/mesh/mesh_ops.c | 13 +- source/blender/editors/object/object_add.c | 10 +- source/blender/editors/object/object_bake.c | 76 +- source/blender/editors/object/object_edit.c | 7 +- .../blender/editors/object/object_modifier.c | 11 +- .../blender/editors/object/object_relations.c | 6 +- .../blender/editors/object/object_shapekey.c | 8 +- source/blender/editors/object/object_vgroup.c | 45 +- .../blender/editors/physics/particle_edit.c | 13 +- .../blender/editors/physics/physics_fluid.c | 11 +- .../blender/editors/render/render_internal.c | 19 +- source/blender/editors/render/render_opengl.c | 47 +- .../blender/editors/render/render_preview.c | 44 +- .../blender/editors/render/render_shading.c | 4 +- source/blender/editors/render/render_update.c | 66 +- source/blender/editors/screen/screen_ops.c | 14 +- source/blender/editors/screen/screendump.c | 60 +- .../editors/sculpt_paint/paint_image.c | 290 ++- .../editors/sculpt_paint/paint_stroke.c | 2 +- .../editors/sculpt_paint/paint_utils.c | 4 +- .../editors/sculpt_paint/paint_vertex.c | 8 +- source/blender/editors/sculpt_paint/sculpt.c | 10 +- .../editors/space_action/action_edit.c | 36 +- .../editors/space_buttons/buttons_context.c | 23 +- .../editors/space_buttons/buttons_texture.c | 2 +- .../editors/space_buttons/space_buttons.c | 2 + source/blender/editors/space_clip/clip_draw.c | 15 +- .../blender/editors/space_clip/clip_editor.c | 2 +- source/blender/editors/space_clip/clip_ops.c | 2 +- .../blender/editors/space_clip/clip_utils.c | 22 +- .../blender/editors/space_clip/space_clip.c | 11 +- .../blender/editors/space_clip/tracking_ops.c | 23 +- .../editors/space_console/console_draw.c | 3 +- .../editors/space_console/console_ops.c | 22 +- .../editors/space_console/space_console.c | 9 +- source/blender/editors/space_file/filelist.c | 1 + source/blender/editors/space_file/filesel.c | 2 + .../editors/space_graph/graph_buttons.c | 12 +- .../blender/editors/space_graph/graph_edit.c | 12 +- .../blender/editors/space_graph/graph_ops.c | 12 +- .../blender/editors/space_graph/space_graph.c | 6 +- .../editors/space_image/image_buttons.c | 5 +- .../blender/editors/space_image/image_draw.c | 11 +- .../blender/editors/space_image/image_edit.c | 16 +- .../blender/editors/space_image/image_ops.c | 170 +- .../blender/editors/space_image/space_image.c | 2 +- source/blender/editors/space_info/info_ops.c | 8 +- .../blender/editors/space_info/space_info.c | 8 +- source/blender/editors/space_node/drawnode.c | 182 +- source/blender/editors/space_node/node_add.c | 3 + source/blender/editors/space_node/node_draw.c | 2 +- source/blender/editors/space_node/node_edit.c | 35 +- .../blender/editors/space_node/node_group.c | 9 +- source/blender/editors/space_node/node_view.c | 29 +- .../blender/editors/space_node/space_node.c | 2 + .../editors/space_outliner/outliner_draw.c | 6 +- .../editors/space_outliner/outliner_edit.c | 7 +- .../editors/space_outliner/outliner_select.c | 2 +- .../editors/space_outliner/outliner_tree.c | 2 +- .../editors/space_outliner/space_outliner.c | 9 +- .../editors/space_sequencer/SConscript | 2 +- .../editors/space_sequencer/sequencer_draw.c | 20 +- .../editors/space_sequencer/sequencer_edit.c | 18 +- .../blender/editors/space_text/space_text.c | 5 - source/blender/editors/space_text/text_draw.c | 207 +- .../blender/editors/space_text/text_intern.h | 9 +- source/blender/editors/space_text/text_ops.c | 319 +-- .../blender/editors/space_text/text_python.c | 174 -- .../blender/editors/space_view3d/drawmesh.c | 9 +- .../blender/editors/space_view3d/drawobject.c | 72 +- .../editors/space_view3d/space_view3d.c | 18 +- .../editors/space_view3d/view3d_draw.c | 156 +- .../editors/space_view3d/view3d_edit.c | 75 +- .../blender/editors/space_view3d/view3d_fly.c | 2 - .../editors/space_view3d/view3d_header.c | 54 +- .../editors/space_view3d/view3d_iterators.c | 2 +- .../blender/editors/space_view3d/view3d_ops.c | 4 +- .../editors/space_view3d/view3d_project.c | 50 +- .../editors/space_view3d/view3d_select.c | 18 +- .../editors/space_view3d/view3d_toolbar.c | 2 +- .../editors/space_view3d/view3d_view.c | 59 +- .../blender/editors/transform/CMakeLists.txt | 1 + source/blender/editors/transform/SConscript | 2 +- source/blender/editors/transform/transform.c | 95 +- source/blender/editors/transform/transform.h | 1 + .../editors/transform/transform_constraints.c | 2 +- .../editors/transform/transform_conversions.c | 27 +- .../editors/transform/transform_manipulator.c | 10 +- .../editors/transform/transform_snap.c | 8 +- source/blender/editors/util/numinput.c | 3 + .../blender/editors/uvedit/uvedit_buttons.c | 7 +- source/blender/editors/uvedit/uvedit_ops.c | 272 ++- .../editors/uvedit/uvedit_parametrizer.c | 8 +- .../editors/uvedit/uvedit_smart_stitch.c | 30 +- .../editors/uvedit/uvedit_unwrap_ops.c | 8 +- source/blender/gpu/GPU_material.h | 1 - source/blender/gpu/SConscript | 1 - source/blender/gpu/intern/gpu_codegen.c | 9 - source/blender/gpu/intern/gpu_draw.c | 18 +- source/blender/gpu/intern/gpu_extensions.c | 12 + source/blender/gpu/intern/gpu_material.c | 24 +- .../gpu/shaders/gpu_shader_material.glsl | 30 +- .../gpu/shaders/gpu_shader_vertex.glsl | 8 + source/blender/ikplugin/intern/ikplugin_api.c | 6 +- .../blender/ikplugin/intern/iksolver_plugin.c | 3 +- .../blender/ikplugin/intern/itasc_plugin.cpp | 2 +- source/blender/imbuf/intern/anim_movie.c | 8 + .../blender/imbuf/intern/cineon/cineon_dpx.c | 16 +- .../blender/imbuf/intern/cineon/cineonlib.c | 2 +- source/blender/imbuf/intern/cineon/dpxlib.c | 2 +- source/blender/imbuf/intern/colormanagement.c | 15 +- source/blender/imbuf/intern/dds/BlockDXT.h | 40 +- source/blender/imbuf/intern/dds/FlipDXT.cpp | 6 +- source/blender/imbuf/intern/dds/SConscript | 9 +- source/blender/imbuf/intern/dds/Stream.h | 2 +- source/blender/imbuf/intern/divers.c | 18 +- source/blender/imbuf/intern/imageprocess.c | 197 +- source/blender/imbuf/intern/indexer.c | 11 +- source/blender/imbuf/intern/jp2.c | 6 +- source/blender/imbuf/intern/jpeg.c | 39 +- .../imbuf/intern/openexr/openexr_api.cpp | 20 +- .../imbuf/intern/openexr/openexr_multi.h | 8 +- .../imbuf/intern/openexr/openexr_stub.cpp | 34 +- source/blender/imbuf/intern/radiance_hdr.c | 1 - source/blender/imbuf/intern/readimage.c | 2 +- source/blender/imbuf/intern/rectop.c | 2 +- source/blender/imbuf/intern/scaling.c | 22 +- source/blender/imbuf/intern/util.c | 21 +- source/blender/makesdna/DNA_action_types.h | 2 +- source/blender/makesdna/DNA_curve_types.h | 5 +- source/blender/makesdna/DNA_gpencil_types.h | 5 +- source/blender/makesdna/DNA_modifier_types.h | 20 +- source/blender/makesdna/DNA_node_types.h | 36 +- source/blender/makesdna/DNA_object_types.h | 17 +- source/blender/makesdna/DNA_scene_types.h | 62 +- source/blender/makesdna/DNA_text_types.h | 11 - source/blender/makesdna/DNA_tracking_types.h | 4 +- source/blender/makesdna/DNA_userdef_types.h | 20 +- source/blender/makesdna/intern/makesdna.c | 2 +- source/blender/makesrna/RNA_access.h | 8 +- source/blender/makesrna/intern/makesrna.c | 98 +- source/blender/makesrna/intern/rna_access.c | 177 +- source/blender/makesrna/intern/rna_action.c | 9 +- source/blender/makesrna/intern/rna_actuator.c | 4 +- .../blender/makesrna/intern/rna_animation.c | 51 +- source/blender/makesrna/intern/rna_boid.c | 8 +- source/blender/makesrna/intern/rna_brush.c | 4 +- source/blender/makesrna/intern/rna_color.c | 4 + .../blender/makesrna/intern/rna_constraint.c | 2 +- source/blender/makesrna/intern/rna_curve.c | 11 +- source/blender/makesrna/intern/rna_image.c | 27 +- .../blender/makesrna/intern/rna_image_api.c | 19 +- source/blender/makesrna/intern/rna_lamp.c | 2 +- source/blender/makesrna/intern/rna_mask.c | 3 +- source/blender/makesrna/intern/rna_material.c | 4 +- source/blender/makesrna/intern/rna_mesh.c | 5 +- source/blender/makesrna/intern/rna_modifier.c | 33 +- source/blender/makesrna/intern/rna_nodetree.c | 140 +- .../makesrna/intern/rna_nodetree_types.h | 7 +- source/blender/makesrna/intern/rna_object.c | 61 +- .../makesrna/intern/rna_object_force.c | 6 +- source/blender/makesrna/intern/rna_particle.c | 6 +- source/blender/makesrna/intern/rna_pose.c | 21 +- source/blender/makesrna/intern/rna_scene.c | 39 +- .../blender/makesrna/intern/rna_scene_api.c | 16 +- .../blender/makesrna/intern/rna_sequencer.c | 4 +- source/blender/makesrna/intern/rna_space.c | 11 +- source/blender/makesrna/intern/rna_speaker.c | 4 +- source/blender/makesrna/intern/rna_text.c | 48 - source/blender/makesrna/intern/rna_texture.c | 40 +- source/blender/makesrna/intern/rna_tracking.c | 29 +- source/blender/makesrna/intern/rna_ui_api.c | 2 +- source/blender/makesrna/intern/rna_userdef.c | 43 +- source/blender/makesrna/intern/rna_wm.c | 6 +- source/blender/makesrna/intern/rna_wm_api.c | 4 +- .../makesrna/rna_cleanup/rna_cleaner.py | 2 +- .../makesrna/rna_cleanup/rna_cleaner_merge.py | 2 +- source/blender/modifiers/CMakeLists.txt | 1 + source/blender/modifiers/MOD_modifiertypes.h | 1 + .../blender/modifiers/intern/MOD_armature.c | 2 +- source/blender/modifiers/intern/MOD_array.c | 75 +- source/blender/modifiers/intern/MOD_bevel.c | 44 +- .../blender/modifiers/intern/MOD_decimate.c | 7 +- .../blender/modifiers/intern/MOD_edgesplit.c | 5 +- source/blender/modifiers/intern/MOD_explode.c | 3 +- .../modifiers/intern/MOD_fluidsim_util.c | 6 +- .../modifiers/intern/MOD_laplaciansmooth.c | 6 +- source/blender/modifiers/intern/MOD_skin.c | 71 +- .../blender/modifiers/intern/MOD_solidify.c | 11 +- .../modifiers/intern/MOD_triangulate.c | 144 ++ source/blender/modifiers/intern/MOD_util.c | 1 + source/blender/nodes/CMakeLists.txt | 38 +- source/blender/nodes/NOD_composite.h | 3 +- source/blender/nodes/NOD_shader.h | 6 +- source/blender/nodes/NOD_socket.h | 1 + source/blender/nodes/NOD_texture.h | 2 - .../nodes/composite/node_composite_tree.c | 99 +- .../composite/nodes/node_composite_blur.c | 4 +- .../nodes/node_composite_colorSpill.c | 7 +- .../nodes/node_composite_colorbalance.c | 16 +- .../composite/nodes/node_composite_image.c | 22 +- .../nodes/node_composite_keyingscreen.c | 27 +- .../composite/nodes/node_composite_mapRange.c | 58 + .../composite/nodes/node_composite_math.c | 2 +- .../composite/nodes/node_composite_normal.c | 2 +- .../nodes/node_composite_outputFile.c | 2 +- .../nodes/node_composite_splitViewer.c | 4 +- .../composite/nodes/node_composite_viewer.c | 4 +- source/blender/nodes/intern/node_socket.c | 91 +- .../nodes/node_shader_ambient_occlusion.c | 63 + .../nodes/node_shader_bsdf_refraction.c | 68 + .../nodes/shader/nodes/node_shader_bump.c | 2 +- .../nodes/shader/nodes/node_shader_material.c | 10 +- .../nodes/shader/nodes/node_shader_math.c | 23 +- .../nodes/shader/nodes/node_shader_normal.c | 4 +- .../shader/nodes/node_shader_normal_map.c | 70 + .../nodes/shader/nodes/node_shader_script.c | 2 +- .../nodes/shader/nodes/node_shader_tangent.c | 60 + .../nodes/node_shader_tex_environment.c | 3 +- .../shader/nodes/node_shader_tex_image.c | 3 +- .../nodes/shader/nodes/node_shader_texture.c | 3 +- .../nodes/shader/nodes/node_shader_vectMath.c | 21 +- .../nodes/texture/nodes/node_texture_image.c | 4 +- source/blender/python/bmesh/CMakeLists.txt | 2 + source/blender/python/bmesh/bmesh_py_api.c | 57 +- source/blender/python/bmesh/bmesh_py_ops.c | 291 +-- .../blender/python/bmesh/bmesh_py_ops_call.c | 783 +++++++ .../blender/python/bmesh/bmesh_py_ops_call.h | 41 + source/blender/python/bmesh/bmesh_py_types.c | 231 +- source/blender/python/bmesh/bmesh_py_types.h | 20 +- .../python/bmesh/bmesh_py_types_customdata.c | 16 +- .../python/bmesh/bmesh_py_types_meshdata.c | 4 +- .../python/bmesh/bmesh_py_types_select.c | 14 +- source/blender/python/bmesh/bmesh_py_utils.c | 10 +- source/blender/python/generic/bgl.c | 22 +- .../python/generic/bpy_internal_import.c | 31 +- source/blender/python/generic/idprop_py_api.c | 8 +- source/blender/python/generic/py_capi_utils.c | 8 +- source/blender/python/intern/bpy_app.c | 4 +- source/blender/python/intern/bpy_interface.c | 19 +- .../blender/python/intern/bpy_intern_string.c | 6 + .../blender/python/intern/bpy_intern_string.h | 2 + source/blender/python/intern/bpy_rna.c | 36 +- source/blender/python/intern/bpy_rna_array.c | 6 +- source/blender/python/intern/bpy_traceback.c | 64 +- source/blender/python/intern/bpy_util.h | 10 +- source/blender/python/mathutils/mathutils.c | 9 +- source/blender/python/mathutils/mathutils.h | 5 +- .../python/mathutils/mathutils_Color.c | 11 +- .../python/mathutils/mathutils_Euler.c | 11 +- .../python/mathutils/mathutils_Matrix.c | 11 +- .../python/mathutils/mathutils_Quaternion.c | 11 +- .../python/mathutils/mathutils_Vector.c | 14 +- .../python/mathutils/mathutils_geometry.c | 6 +- source/blender/quicktime/quicktime_export.h | 4 +- .../blender/render/extern/include/RE_engine.h | 1 + .../render/extern/include/RE_pipeline.h | 2 + .../render/intern/include/initrender.h | 5 +- .../render/intern/include/render_types.h | 4 + .../intern/raytrace/rayobject_internal.h | 2 +- .../intern/raytrace/rayobject_octree.cpp | 2 +- .../intern/raytrace/rayobject_rtbuild.cpp | 2 +- .../render/intern/source/convertblender.c | 16 +- source/blender/render/intern/source/envmap.c | 3 +- .../render/intern/source/external_engine.c | 38 +- .../render/intern/source/imagetexture.c | 81 +- .../blender/render/intern/source/initrender.c | 24 +- .../blender/render/intern/source/pipeline.c | 32 +- .../render/intern/source/render_texture.c | 30 +- .../blender/render/intern/source/rendercore.c | 28 +- .../render/intern/source/renderdatabase.c | 34 +- source/blender/render/intern/source/shadbuf.c | 2 +- .../render/intern/source/shadeoutput.c | 4 +- source/blender/render/intern/source/sunsky.c | 4 +- .../blender/render/intern/source/voxeldata.c | 13 +- source/blender/render/intern/source/zbuf.c | 4 +- source/blender/windowmanager/WM_api.h | 13 +- source/blender/windowmanager/WM_types.h | 2 + source/blender/windowmanager/intern/wm_draw.c | 15 +- .../windowmanager/intern/wm_event_system.c | 234 +- .../blender/windowmanager/intern/wm_files.c | 4 +- .../blender/windowmanager/intern/wm_gesture.c | 2 +- source/blender/windowmanager/intern/wm_jobs.c | 47 +- .../blender/windowmanager/intern/wm_keymap.c | 9 +- .../windowmanager/intern/wm_operators.c | 211 +- .../windowmanager/intern/wm_playanim.c | 250 ++- .../blender/windowmanager/intern/wm_window.c | 14 +- source/blender/windowmanager/wm_event_types.h | 6 +- source/blenderplayer/CMakeLists.txt | 6 +- .../bad_level_call_stubs/stubs.c | 4 +- source/creator/CMakeLists.txt | 50 +- source/creator/blender.map | 16 + source/creator/creator.c | 5 +- source/creator/osx_locals.map | 3 + .../BlenderRoutines/KX_BlenderGL.cpp | 22 +- .../KX_BlenderKeyboardDevice.cpp | 2 +- .../BlenderRoutines/KX_BlenderMouseDevice.cpp | 2 +- .../Converter/BL_ArmatureChannel.cpp | 2 +- .../Converter/BL_ArmatureConstraint.cpp | 2 +- .../Converter/BL_ArmatureObject.cpp | 1 - .../Converter/BL_BlenderDataConversion.cpp | 268 ++- .../Converter/KX_BlenderSceneConverter.cpp | 11 +- source/gameengine/Converter/SConscript | 2 +- source/gameengine/Expressions/IntValue.cpp | 7 +- source/gameengine/Expressions/ListValue.cpp | 10 +- .../gameengine/Expressions/PyObjectPlus.cpp | 44 +- source/gameengine/Expressions/PyObjectPlus.h | 2 +- .../gameengine/GameLogic/SCA_IController.cpp | 2 +- .../gameengine/GameLogic/SCA_ILogicBrick.cpp | 4 +- source/gameengine/GameLogic/SCA_ISensor.cpp | 8 +- .../GameLogic/SCA_JoystickSensor.cpp | 16 +- .../GameLogic/SCA_KeyboardSensor.cpp | 15 +- .../gameengine/GameLogic/SCA_MouseSensor.cpp | 11 +- .../GameLogic/SCA_PropertySensor.cpp | 24 +- .../GameLogic/SCA_PythonController.cpp | 10 +- .../GameLogic/SCA_PythonController.h | 2 +- .../GameLogic/SCA_PythonKeyboard.cpp | 4 +- .../gameengine/GameLogic/SCA_PythonMouse.cpp | 4 +- .../GameLogic/SCA_RandomActuator.cpp | 20 +- .../gameengine/GameLogic/SCA_RandomSensor.cpp | 4 +- .../gameengine/GamePlayer/common/SConscript | 1 - .../gameengine/GamePlayer/common/bmfont.cpp | 3 - .../GamePlayer/ghost/GPG_Application.cpp | 2 +- .../gameengine/GamePlayer/ghost/GPG_ghost.cpp | 11 +- source/gameengine/GamePlayer/ghost/SConscript | 1 - source/gameengine/Ketsji/BL_Material.cpp | 55 +- source/gameengine/Ketsji/BL_Material.h | 15 +- source/gameengine/Ketsji/BL_Shader.cpp | 60 +- source/gameengine/Ketsji/BL_Shader.h | 6 +- source/gameengine/Ketsji/BL_Texture.cpp | 20 +- source/gameengine/Ketsji/CMakeLists.txt | 2 - .../gameengine/Ketsji/KX_BlenderMaterial.cpp | 11 +- source/gameengine/Ketsji/KX_BlenderMaterial.h | 2 + source/gameengine/Ketsji/KX_Camera.cpp | 12 +- .../gameengine/Ketsji/KX_CameraActuator.cpp | 4 +- .../gameengine/Ketsji/KX_CharacterWrapper.h | 2 +- .../Ketsji/KX_ConstraintWrapper.cpp | 2 +- source/gameengine/Ketsji/KX_Dome.cpp | 30 +- source/gameengine/Ketsji/KX_Dome.h | 46 +- source/gameengine/Ketsji/KX_GameObject.cpp | 15 +- source/gameengine/Ketsji/KX_GameObject.h | 4 +- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 30 +- source/gameengine/Ketsji/KX_Light.cpp | 10 +- source/gameengine/Ketsji/KX_MeshProxy.cpp | 176 +- source/gameengine/Ketsji/KX_MeshProxy.h | 4 +- .../gameengine/Ketsji/KX_ObjectActuator.cpp | 6 +- .../Ketsji/KX_ObstacleSimulation.cpp | 8 +- .../Ketsji/KX_PhysicsObjectWrapper.cpp | 145 -- .../Ketsji/KX_PhysicsObjectWrapper.h | 59 - source/gameengine/Ketsji/KX_PolyProxy.cpp | 22 +- .../gameengine/Ketsji/KX_PolygonMaterial.cpp | 8 +- source/gameengine/Ketsji/KX_PolygonMaterial.h | 2 +- .../Ketsji/KX_PyConstraintBinding.cpp | 5 +- source/gameengine/Ketsji/KX_PythonInit.cpp | 21 +- .../gameengine/Ketsji/KX_PythonInitTypes.cpp | 6 +- source/gameengine/Ketsji/KX_PythonSeq.cpp | 6 +- .../Ketsji/KX_SCA_AddObjectActuator.cpp | 4 +- .../Ketsji/KX_SCA_EndObjectActuator.cpp | 2 +- source/gameengine/Ketsji/KX_Scene.cpp | 33 +- source/gameengine/Ketsji/KX_Scene.h | 3 + .../gameengine/Ketsji/KX_VehicleWrapper.cpp | 6 +- source/gameengine/Ketsji/KX_VertexProxy.cpp | 41 +- source/gameengine/Ketsji/KX_VertexProxy.h | 4 +- .../Network/NG_NetworkDeviceInterface.h | 4 +- .../Physics/Bullet/CcdPhysicsController.cpp | 8 +- .../Physics/Dummy/DummyPhysicsEnvironment.cpp | 5 +- .../Physics/Dummy/DummyPhysicsEnvironment.h | 1 + .../Physics/common/PHY_IPhysicsEnvironment.h | 1 + source/gameengine/Rasterizer/RAS_ICanvas.h | 2 +- .../Rasterizer/RAS_MaterialBucket.h | 2 + .../RAS_OpenGLRasterizer/SConscript | 2 +- source/gameengine/Rasterizer/RAS_TexVert.cpp | 32 +- source/gameengine/Rasterizer/RAS_TexVert.h | 8 +- source/gameengine/SceneGraph/SG_IObject.h | 10 +- source/gameengine/VideoTexture/BlendType.h | 46 +- source/gameengine/VideoTexture/Common.h | 46 +- source/gameengine/VideoTexture/Exception.cpp | 44 +- source/gameengine/VideoTexture/Exception.h | 47 +- source/gameengine/VideoTexture/FilterBase.cpp | 44 +- source/gameengine/VideoTexture/FilterBase.h | 46 +- .../VideoTexture/FilterBlueScreen.cpp | 90 +- .../VideoTexture/FilterBlueScreen.h | 46 +- .../gameengine/VideoTexture/FilterColor.cpp | 48 +- source/gameengine/VideoTexture/FilterColor.h | 46 +- .../gameengine/VideoTexture/FilterNormal.cpp | 46 +- source/gameengine/VideoTexture/FilterNormal.h | 46 +- .../gameengine/VideoTexture/FilterSource.cpp | 44 +- source/gameengine/VideoTexture/FilterSource.h | 46 +- source/gameengine/VideoTexture/ImageBase.cpp | 44 +- source/gameengine/VideoTexture/ImageBase.h | 46 +- source/gameengine/VideoTexture/ImageBuff.cpp | 44 +- source/gameengine/VideoTexture/ImageBuff.h | 46 +- source/gameengine/VideoTexture/ImageMix.cpp | 44 +- source/gameengine/VideoTexture/ImageMix.h | 46 +- .../gameengine/VideoTexture/ImageRender.cpp | 55 +- source/gameengine/VideoTexture/ImageRender.h | 46 +- .../gameengine/VideoTexture/ImageViewport.cpp | 90 +- .../gameengine/VideoTexture/ImageViewport.h | 50 +- source/gameengine/VideoTexture/PyTypeList.cpp | 44 +- source/gameengine/VideoTexture/PyTypeList.h | 46 +- source/gameengine/VideoTexture/Texture.cpp | 44 +- source/gameengine/VideoTexture/Texture.h | 46 +- source/gameengine/VideoTexture/VideoBase.cpp | 46 +- source/gameengine/VideoTexture/VideoBase.h | 46 +- .../gameengine/VideoTexture/VideoFFmpeg.cpp | 46 +- source/gameengine/VideoTexture/VideoFFmpeg.h | 46 +- .../gameengine/VideoTexture/blendVideoTex.cpp | 44 +- source/tests/bl_rst_completeness.py | 159 ++ source/tests/bl_run_operators.py | 5 +- source/tests/rst_to_doctree_mini.py | 91 + 978 files changed, 32475 insertions(+), 17107 deletions(-) create mode 100755 build_files/build_environment/install_deps.sh create mode 100644 build_files/buildbot/slave_rsync.py create mode 100644 build_files/cmake/Modules/FindIcuLinux.cmake create mode 100644 doc/python_api/examples/bmesh.ops.1.py create mode 100644 doc/python_api/rst/info_api_reference.rst create mode 100644 doc/python_api/rst/info_tutorial_addon.rst create mode 100644 doc/python_api/rst_from_bmesh_opdefines.py create mode 100644 intern/cycles/kernel/closure/bsdf_phong_ramp.h create mode 100644 intern/cycles/kernel/osl/SConscript create mode 100644 intern/cycles/kernel/osl/bsdf_phong_ramp.cpp create mode 100644 intern/cycles/kernel/shaders/SConscript create mode 100644 intern/cycles/kernel/shaders/node_ambient_occlusion.osl create mode 100644 intern/cycles/kernel/shaders/node_convert_from_string.osl create mode 100644 intern/cycles/kernel/shaders/node_normal_map.osl create mode 100644 intern/cycles/kernel/shaders/node_refraction_bsdf.osl create mode 100644 intern/cycles/kernel/shaders/node_tangent.osl create mode 100644 intern/locale/CMakeLists.txt create mode 100644 intern/locale/SConscript create mode 100644 intern/locale/boost_locale_wrapper.cpp create mode 100644 intern/locale/boost_locale_wrapper.h rename {source => release}/darwin/blender.app/Contents/Info.plist (100%) rename {source => release}/darwin/blender.app/Contents/MacOS/blender (100%) rename {source => release}/darwin/blender.app/Contents/PkgInfo (100%) rename {source => release}/darwin/blender.app/Contents/Resources/blender file icon.icns (100%) rename {source => release}/darwin/blender.app/Contents/Resources/blender icon.icns (100%) rename {source => release}/darwin/blenderplayer.app/Contents/Info.plist (100%) rename {source => release}/darwin/blenderplayer.app/Contents/MacOS/blenderplayer (100%) rename {source => release}/darwin/blenderplayer.app/Contents/PkgInfo (100%) rename {source => release}/darwin/blenderplayer.app/Contents/Resources/blender file icon.icns (100%) rename {source => release}/darwin/blenderplayer.app/Contents/Resources/blender player icon.icns (100%) rename {source => release}/darwin/set_simulation_threads.app/Contents/Info.plist (100%) rename {source => release}/darwin/set_simulation_threads.app/Contents/MacOS/applet (100%) rename {source => release}/darwin/set_simulation_threads.app/Contents/PkgInfo (100%) rename {source => release}/darwin/set_simulation_threads.app/Contents/Resources/Scripts/main.scpt (100%) rename {source => release}/darwin/set_simulation_threads.app/Contents/Resources/applet.icns (100%) rename {source => release}/darwin/set_simulation_threads.app/Contents/Resources/applet.rsrc (100%) rename {source => release}/darwin/set_simulation_threads.app/Contents/Resources/description.rtfd/TXT.rtf (100%) create mode 100644 release/scripts/templates/bmesh_simple_editmode.py create mode 100644 source/blender/blenlib/BLI_math_interp.h create mode 100644 source/blender/blenlib/intern/math_interp.c create mode 100644 source/blender/bmesh/tools/bmesh_bevel.c create mode 100644 source/blender/bmesh/tools/bmesh_bevel.h rename source/blender/bmesh/{intern => tools}/bmesh_decimate.h (86%) rename source/blender/bmesh/{intern => tools}/bmesh_decimate_collapse.c (85%) rename source/blender/bmesh/{intern => tools}/bmesh_decimate_dissolve.c (97%) rename source/blender/bmesh/{intern => tools}/bmesh_decimate_unsubdivide.c (97%) create mode 100644 source/blender/compositor/nodes/COM_MapRangeNode.cpp create mode 100644 source/blender/compositor/nodes/COM_MapRangeNode.h create mode 100644 source/blender/compositor/operations/COM_MapRangeOperation.cpp create mode 100644 source/blender/compositor/operations/COM_MapRangeOperation.h create mode 100644 source/blender/modifiers/intern/MOD_triangulate.c create mode 100644 source/blender/nodes/composite/nodes/node_composite_mapRange.c create mode 100644 source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c create mode 100644 source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c create mode 100644 source/blender/nodes/shader/nodes/node_shader_normal_map.c create mode 100644 source/blender/nodes/shader/nodes/node_shader_tangent.c create mode 100644 source/blender/python/bmesh/bmesh_py_ops_call.c create mode 100644 source/blender/python/bmesh/bmesh_py_ops_call.h create mode 100644 source/creator/blender.map create mode 100644 source/creator/osx_locals.map delete mode 100644 source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp delete mode 100644 source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h create mode 100644 source/tests/bl_rst_completeness.py create mode 100644 source/tests/rst_to_doctree_mini.py diff --git a/CMakeLists.txt b/CMakeLists.txt index b53c6f6b71f..3e1c8fec02a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -127,7 +127,7 @@ option(WITH_PYTHON_MODULE "Enable building as a python module which runs without option(WITH_BUILDINFO "Include extra build details (only disable for development & faster builds)" ON) option(WITH_IK_ITASC "Enable ITASC IK solver (only disable for development & for incompatible C++ compilers)" ON) option(WITH_IK_SOLVER "Enable Legacy IK solver (only disable for development)" ON) -option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke and audio effects)" OFF) +option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke and audio effects)" ON) option(WITH_BULLET "Enable Bullet (Physics Engine)" ON) option(WITH_GAMEENGINE "Enable Game Engine" ON) option(WITH_PLAYER "Build Player" OFF) @@ -190,8 +190,8 @@ option(WITH_MOD_FLUID "Enable Elbeem Modifier (Fluid Simulation)" ON) option(WITH_MOD_SMOKE "Enable Smoke Modifier (Smoke Simulation)" ON) option(WITH_MOD_BOOLEAN "Enable Boolean Modifier" ON) option(WITH_MOD_REMESH "Enable Remesh Modifier" ON) -option(WITH_MOD_CLOTH_ELTOPO "Enable Experimental cloth solver" OFF) -mark_as_advanced(WITH_MOD_CLOTH_ELTOPO) +# option(WITH_MOD_CLOTH_ELTOPO "Enable Experimental cloth solver" OFF) # this is now only available in a branch +# mark_as_advanced(WITH_MOD_CLOTH_ELTOPO) option(WITH_MOD_OCEANSIM "Enable Ocean Modifier" OFF) # Image format support @@ -234,17 +234,13 @@ option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" option(WITH_RAYOPTIMIZATION "Enable use of SIMD (SSE) optimizations for the raytracer" ON) if(UNIX AND NOT APPLE) option(WITH_INSTALL_PORTABLE "Install redistributeable runtime, otherwise install into CMAKE_INSTALL_PREFIX" ON) + option(WITH_STATIC_LIBS "Try to link with static libraries, as much as possible, to make blender more portable across distributions" OFF) endif() option(WITH_PYTHON_INSTALL "Copy system python into the blender install folder" ON) option(WITH_PYTHON_INSTALL_NUMPY "Copy system numpy into the blender install folder" ON) set(PYTHON_NUMPY_PATH "" CACHE PATH "Python to python site-packages or dist-packages containing 'numpy' module") mark_as_advanced(PYTHON_NUMPY_PATH) -if(MINGW) - option(WITH_MINGW64 "Use the 64-bit version of MinGW" OFF) - mark_as_advanced(WITH_MINGW64) -endif() - # Cycles option(WITH_CYCLES "Enable cycles Render Engine" ON) option(WITH_CYCLES_TEST "Build cycles test application" OFF) @@ -270,6 +266,9 @@ mark_as_advanced(WITH_ASSERT_ABORT) if(APPLE) + cmake_minimum_required(VERSION 2.8.8) + cmake_policy(VERSION 2.8.8) + if(NOT CMAKE_OSX_ARCHITECTURES) set(CMAKE_OSX_ARCHITECTURES x86_64 CACHE STRING "Choose the architecture you want to build Blender for: i386, x86_64 or ppc" @@ -289,18 +288,14 @@ if(APPLE) set(OSX_SYSTEM unsupported) endif() message(STATUS "Detected system-version: " ${OSX_SYSTEM}) - - if(NOT CMAKE_OSX_DEPLOYMENT_TARGET) - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.5" CACHE STRING "" FORCE) # 10.5 is our minimum target, if you have higher sdk, weak linking happens - endif() if(${CMAKE_GENERATOR} MATCHES "Xcode") - ##### workaround for actual official cmake incompatibility with xcode 4.3 ##### + ##### cmake incompatibility with xcode 4.3 and higher ##### if(${XCODE_VERSION} MATCHES '') # cmake fails due looking for xcode in the wrong path, thus will be empty var - message("Official cmake does not yet support Xcode 4.3, get a patched version here: http://www.jensverwiebe.de/Blender/CMake%202.8-7patched.zip") + message(FATAL_ERROR "Xcode 4.3 and higher must be used with cmake 2.8-8 or higher") endif() - ### end workaround for actual official cmake incompatibility with xcode 4.3 ### + ### end cmake incompatibility with xcode 4.3 and higher ### if(${XCODE_VERSION} VERSION_EQUAL 4 OR ${XCODE_VERSION} VERSION_GREATER 4 AND ${XCODE_VERSION} VERSION_LESS 4.3) # Xcode 4 defaults to the Apple LLVM Compiler. @@ -315,7 +310,28 @@ if(APPLE) endif() message(STATUS "Detected Xcode-version: " ${XCODE_VERSION}) + + if(${XCODE_VERSION} VERSION_LESS 4.3) + set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk CACHE PATH "" FORCE) # use guaranteed existing sdk + else() + # note: i don't use xcode-select path on purpose, cause also /Applications/Xcode.app would be allowed + # absolute pathes are more foolproof here ! + set(OSX_SYSROOT_PREFIX /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform) + set(OSX_DEVELOPER_PREFIX /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk) # use guaranteed existing sdk + set(CMAKE_OSX_SYSROOT ${OSX_SYSROOT_PREFIX}/${OSX_DEVELOPER_PREFIX} CACHE PATH "" FORCE) + endif() + if(NOT CMAKE_OSX_DEPLOYMENT_TARGET) + set(CMAKE_OSX_DEPLOYMENT_TARGET "10.5" CACHE STRING "" FORCE) # 10.5 is our min. target, if you use higher sdk, weak linking happens + endif() + + if(NOT ${CMAKE_GENERATOR} MATCHES "Xcode") + # force CMAKE_OSX_DEPLOYMENT_TARGET for makefiles, will not work else ( cmake bug ? ) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") + add_definitions ("-DMACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}") + endif() + option(WITH_COCOA "Use Cocoa framework instead of deprecated Carbon" ON) option(USE_QTKIT "Use QtKit instead of Carbon quicktime (needed for having partial quicktime for 64bit)" OFF) option(WITH_LIBS10.5 "Use 10.5 libs (needed for 64bit builds)" OFF) @@ -336,12 +352,20 @@ if(NOT WITH_GAMEENGINE AND WITH_PLAYER) message(FATAL_ERROR "WITH_PLAYER requires WITH_GAMEENGINE") endif() -if(NOT WITH_AUDASPACE AND (WITH_OPENAL OR WITH_SDL OR WITH_JACK OR WITH_GAMEENGINE)) - message(FATAL_ERROR "WITH_OPENAL/WITH_SDL/WITH_JACK/WITH_CODEC_FFMPEG/WITH_GAMEENGINE require WITH_AUDASPACE") +if(NOT WITH_AUDASPACE) + if(WITH_OPENAL) + message(FATAL_ERROR "WITH_OPENAL requires WITH_AUDASPACE") + endif() + if(WITH_JACK) + message(FATAL_ERROR "WITH_JACK requires WITH_AUDASPACE") + endif() + if(WITH_GAMEENGINE) + message(FATAL_ERROR "WITH_GAMEENGINE requires WITH_AUDASPACE") + endif() endif() if(NOT WITH_SDL AND WITH_GHOST_SDL) - message(FATAL_ERROR "WITH_GHOST_SDL requires WITH_SDL to be ON") + message(FATAL_ERROR "WITH_GHOST_SDL requires WITH_SDL") endif() if(WITH_IMAGE_REDCODE AND ((NOT WITH_IMAGE_OPENJPEG) OR (NOT WITH_CODEC_FFMPEG))) @@ -358,10 +382,6 @@ if(WITH_PYTHON_MODULE AND WITH_PYTHON_INSTALL) endif() -if(NOT WITH_FFTW3 AND WITH_MOD_OCEANSIM) - message(FATAL_ERROR "WITH_MOD_OCEANSIM requires WITH_FFTW3 to be ON") -endif() - # may as well build python module without a UI if(WITH_PYTHON_MODULE) set(WITH_HEADLESS ON) @@ -372,8 +392,8 @@ if(WITH_CYCLES) set(WITH_OPENIMAGEIO ON) endif() -# auto enable boost for cycles and booleans -if(WITH_CYCLES OR WITH_MOD_BOOLEAN) +# auto enable boost for cycles, booleans, audaspace or i18n +if(WITH_CYCLES OR WITH_MOD_BOOLEAN OR WITH_AUDASPACE OR WITH_INTERNATIONAL) set(WITH_BOOST ON) endif() @@ -461,14 +481,14 @@ set(PLATFORM_LINKFLAGS_DEBUG "") # For alternate Python locations the commandline can be used to override detected/default cache settings, e.g: # On Unix: # cmake ../blender \ -# -D PYTHON_VERSION=3.2 \ -# -D PYTHON_INCLUDE_DIR=/opt/py32/include/python3.2d \ -# -D PYTHON_LIBRARY=/opt/py32/lib/libpython3.2d.so +# -D PYTHON_VERSION=3.3 \ +# -D PYTHON_INCLUDE_DIR=/opt/py33/include/python3.3d \ +# -D PYTHON_LIBRARY=/opt/py33/lib/libpython3.3d.so # # On Macs: # cmake ../blender \ -# -D PYTHON_INCLUDE_DIR=/System/Library/Frameworks/Python.framework/Versions/3.2/include/python3.2 \ -# -D PYTHON_LIBPATH=/System/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/config \ +# -D PYTHON_INCLUDE_DIR=/System/Library/Frameworks/Python.framework/Versions/3.3/include/python3.3 \ +# -D PYTHON_LIBPATH=/System/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/config \ # -G Xcode # # When changing any of this remember to update the notes in doc/build_systems/cmake.txt @@ -477,50 +497,52 @@ set(PLATFORM_LINKFLAGS_DEBUG "") #Platform specifics if(UNIX AND NOT APPLE) - - # set lib directory if it exists - if(CMAKE_SYSTEM_NAME MATCHES "Linux") - if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") - set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/linux64) - else() - set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/linux) + macro(find_package_wrapper) + STRING(TOUPPER ${ARGV0} _NAME_UPPER) + if(${WITH_STATIC_LIBS}) + set(_cmake_find_library_suffixes_back ${CMAKE_FIND_LIBRARY_SUFFIXES}) + set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) endif() - - if(NOT EXISTS ${LIBDIR}) - unset(LIBDIR) + find_package(${ARGV}) + if(${WITH_STATIC_LIBS}) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${_cmake_find_library_suffixes_back}) + unset(_cmake_find_library_suffixes_back) endif() - endif() + endmacro() - find_package(JPEG REQUIRED) - find_package(PNG REQUIRED) - find_package(ZLIB REQUIRED) - find_package(Freetype REQUIRED) + find_package_wrapper(JPEG REQUIRED) + find_package_wrapper(PNG REQUIRED) + find_package_wrapper(ZLIB REQUIRED) + find_package_wrapper(Freetype REQUIRED) if(WITH_PYTHON) - # No way to set py32. remove for now. + # No way to set py33. remove for now. # find_package(PythonLibs) # Use our own instead, since wothout py is such a rare case, # require this package + # XXX Linking errors with debian static python :/ +# find_package_wrapper(PythonLibsUnix REQUIRED) find_package(PythonLibsUnix REQUIRED) endif() - if(WITH_IMAGE_OPENEXR) - find_package(OpenEXR) # our own module + find_package_wrapper(OpenEXR) # our own module if(NOT OPENEXR_FOUND) set(WITH_IMAGE_OPENEXR OFF) endif() endif() if(WITH_IMAGE_OPENJPEG) - find_package(OpenJPEG) + find_package_wrapper(OpenJPEG) if(NOT OPENJPEG_FOUND) set(WITH_IMAGE_OPENJPEG OFF) endif() endif() if(WITH_IMAGE_TIFF) + # XXX Linking errors with debian static tiff :/ +# find_package_wrapper(TIFF) find_package(TIFF) if(NOT TIFF_FOUND) set(WITH_IMAGE_TIFF OFF) @@ -529,14 +551,14 @@ if(UNIX AND NOT APPLE) # Audio IO if(WITH_OPENAL) - find_package(OpenAL) + find_package_wrapper(OpenAL) if(NOT OPENAL_FOUND) set(WITH_OPENAL OFF) endif() endif() if(WITH_SDL) - find_package(SDL) + find_package_wrapper(SDL) mark_as_advanced( SDLMAIN_LIBRARY SDL_INCLUDE_DIR @@ -550,7 +572,7 @@ if(UNIX AND NOT APPLE) endif() if(WITH_JACK) - find_package(Jack) + find_package_wrapper(Jack) if(NOT JACK_FOUND) set(WITH_JACK OFF) endif() @@ -558,22 +580,15 @@ if(UNIX AND NOT APPLE) # Codecs if(WITH_CODEC_SNDFILE) - find_package(SndFile) + find_package_wrapper(SndFile) if(NOT SNDFILE_FOUND) set(WITH_CODEC_SNDFILE OFF) endif() endif() if(WITH_CODEC_FFMPEG) - # use lib dir if available and nothing else specified - if(LIBDIR AND NOT FFMPEG) - set(FFMPEG ${LIBDIR}/ffmpeg CACHE PATH "FFMPEG Directory") - # XXX, some distros might need 'theoraenc theoradec' too - set(FFMPEG_LIBRARIES avformat avcodec avutil avdevice swscale dirac_encoder mp3lame ogg orc-0.4 schroedinger-1.0 theora vorbis vorbisenc vpx x264 xvidcore faad asound CACHE STRING "FFMPEG Libraries") - else() - set(FFMPEG /usr CACHE PATH "FFMPEG Directory") - set(FFMPEG_LIBRARIES avformat avcodec avutil avdevice swscale CACHE STRING "FFMPEG Libraries") - endif() + set(FFMPEG /usr CACHE PATH "FFMPEG Directory") + set(FFMPEG_LIBRARIES avformat avcodec avutil avdevice swscale CACHE STRING "FFMPEG Libraries") mark_as_advanced(FFMPEG) @@ -589,54 +604,32 @@ if(UNIX AND NOT APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__STDC_CONSTANT_MACROS") endif() - if(WITH_INTERNATIONAL) - find_library(INTL_LIBRARY - NAMES intl - PATHS - /sw/lib - ) - - find_library(ICONV_LIBRARY - NAMES iconv - PATHS - /sw/lib - ) - mark_as_advanced( - ICONV_LIBRARY - INTL_LIBRARY - ) - - if(INTL_LIBRARY AND ICONV_LIBRARY) - set(GETTEXT_LIBRARIES ${INTL_LIBRARY} ${ICONV_LIBRARY}) - endif() - endif() - if(WITH_FFTW3) - find_package(Fftw3) + find_package_wrapper(Fftw3) if(NOT FFTW3_FOUND) set(WITH_FFTW3 OFF) endif() endif() if(WITH_OPENCOLLADA) - find_package(OpenCOLLADA) + find_package_wrapper(OpenCOLLADA) if(OPENCOLLADA_FOUND) - find_package(XML2) - find_package(PCRE) + find_package_wrapper(XML2) + find_package_wrapper(PCRE) else() set(WITH_OPENCOLLADA OFF) endif() endif() if(WITH_MEM_JEMALLOC) - find_package(JeMalloc) + find_package_wrapper(JeMalloc) if(NOT JEMALLOC_FOUND) set(WITH_MEM_JEMALLOC OFF) endif() endif() if (WITH_INPUT_NDOF) - find_package(Spacenav) + find_package_wrapper(Spacenav) if(NOT SPACENAV_FOUND) set(WITH_INPUT_NDOF OFF) endif() @@ -651,14 +644,23 @@ if(UNIX AND NOT APPLE) if(WITH_BOOST) # uses in build instructions to override include and library variables if(NOT BOOST_CUSTOM) - # use lib dir if available and nothing else specified - if(LIBDIR AND NOT BOOST_ROOT) - set(BOOST_ROOT ${LIBDIR}/boost) + # XXX No more lib dir, is this multithread stuff still needed? + if(${WITH_STATIC_LIBS}) + set(Boost_USE_STATIC_LIBS ON) + endif() + if(NOT BOOST_ROOT) set(Boost_USE_MULTITHREADED OFF) else() set(Boost_USE_MULTITHREADED ON) endif() - find_package(Boost 1.34 COMPONENTS filesystem regex system thread) + set(__boost_packages filesystem regex system thread date_time) + if (WITH_INTERNATIONAL) + list(APPEND __boost_packages locale) + endif() + find_package(Boost 1.34 COMPONENTS ${__boost_packages}) + if(Boost_USE_STATIC_LIBS AND Boost_USE_ICU) + find_package(IcuLinux) + endif() mark_as_advanced(Boost_DIR) # why doesnt boost do this? endif() @@ -669,12 +671,7 @@ if(UNIX AND NOT APPLE) endif() if(WITH_OPENIMAGEIO) - # use lib dir if available and nothing else specified - if(LIBDIR AND NOT OPENIMAGEIO_ROOT_DIR) - set(OPENIMAGEIO_ROOT_DIR ${LIBDIR}/oiio) - endif() - - find_package(OpenImageIO) + find_package_wrapper(OpenImageIO) set(OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO_LIBRARIES} ${PNG_LIBRARIES} ${JPEG_LIBRARIES} ${ZLIB_LIBRARIES} ${BOOST_LIBRARIES}) set(OPENIMAGEIO_LIBPATH) # TODO, remove and reference the absolute path everywhere @@ -694,12 +691,7 @@ if(UNIX AND NOT APPLE) endif() if(WITH_OPENCOLORIO) - # use lib dir if available and nothing else specified - if(LIBDIR AND NOT OPENCOLORIO_ROOT_DIR) - set(OPENCOLORIO_ROOT_DIR ${LIBDIR}/ocio) - endif() - - find_package(OpenColorIO) + find_package_wrapper(OpenColorIO) set(OPENCOLORIO_LIBRARIES ${OPENCOLORIO_LIBRARIES}) set(OPENCOLORIO_LIBPATH) # TODO, remove and reference the absolute path everywhere @@ -711,14 +703,23 @@ if(UNIX AND NOT APPLE) endif() endif() + # XXX Maybe most of this section should go into an llvm module? if(WITH_LLVM) - set(LLVM_DIRECTORY ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation") - set(LLVM_VERSION "3.0" CACHE STRING "Version of LLVM to use") + # Set llvm version if not specified + if(NOT LLVM_VERSION) + set(LLVM_VERSION "3.0") + endif() set(LLVM_STATIC YES) if(LLVM_DIRECTORY) - set(LLVM_CONFIG "${LLVM_DIRECTORY}/bin/llvm-config") + FIND_PROGRAM(LLVM_CONFIG llvm-config-${LLVM_VERSION} HINTS ${LLVM_DIRECTORY}/bin NO_CMAKE_PATH) + if(NOT LLVM_CONFIG) + FIND_PROGRAM(LLVM_CONFIG llvm-config HINTS ${LLVM_DIRECTORY}/bin NO_CMAKE_PATH) + endif() else() - set(LLVM_CONFIG llvm-config) + FIND_PROGRAM(LLVM_CONFIG llvm-config-${LLVM_VERSION}) + if(NOT LLVM_CONFIG) + FIND_PROGRAM(LLVM_CONFIG llvm-config) + endif() endif() execute_process(COMMAND ${LLVM_CONFIG} --version OUTPUT_VARIABLE LLVM_VERSION @@ -730,11 +731,13 @@ if(UNIX AND NOT APPLE) OUTPUT_VARIABLE LLVM_LIB_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) find_library(LLVM_LIBRARY - NAMES libLLVMAnalysis.a # first of a whole bunch of libs to get + NAMES LLVMAnalysis # first of a whole bunch of libs to get PATHS ${LLVM_LIB_DIR}) message(STATUS "LLVM version = ${LLVM_VERSION}") message(STATUS "LLVM dir = ${LLVM_DIRECTORY}") message(STATUS "LLVM lib dir = ${LLVM_LIB_DIR}") + set(LLVM_VERSION ${LLVM_VERSION} CACHE STRING "Version of LLVM to use") + set(LLVM_DIRECTORY ${LLVM_DIRECTORY} CACHE PATH "Path to the LLVM installation") if(LLVM_LIBRARY AND LLVM_DIRECTORY AND LLVM_LIB_DIR) if(LLVM_STATIC) @@ -746,10 +749,12 @@ if(UNIX AND NOT APPLE) OUTPUT_STRIP_TRAILING_WHITESPACE) string(REPLACE " " ";" LLVM_LIBRARY ${LLVM_LIBRARY}) endif() - message(STATUS "LLVM library = ${LLVM_LIBRARY}") else() message(FATAL_ERROR "LLVM not found.") endif() + + # Fix for conflict with Mesa llvmpipe + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -Wl,--version-script=${CMAKE_SOURCE_DIR}/source/creator/blender.map") endif() if(WITH_CYCLES_OSL) @@ -812,7 +817,7 @@ if(UNIX AND NOT APPLE) endif() endif() - set(PLATFORM_LINKFLAGS "-pthread") + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -pthread") # lfs on glibc, all compilers should use add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE) @@ -857,10 +862,18 @@ elseif(WIN32) if(CMAKE_COMPILER_IS_GNUCC) set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw32) - + INCLUDE (CheckCSourceCompiles) # Setup 64bit and 64bit windows systems + CHECK_C_SOURCE_COMPILES(" + #ifndef __MINGW64__ + #error + #endif + main(){} + " + WITH_MINGW64) + if(WITH_MINGW64) - message("Set 64 bit compiler for MinGW.") + message("Compiling for 64 bit with MinGW-w64.") set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw64) endif() else() @@ -875,13 +888,6 @@ elseif(WIN32) add_definitions(-DWIN32) - if(WITH_INTERNATIONAL) - set(ICONV ${LIBDIR}/iconv) - set(ICONV_INCLUDE_DIRS ${ICONV}/include) - set(ICONV_LIBRARIES iconv) - set(ICONV_LIBPATH ${ICONV}/lib) - endif() - set(JPEG "${LIBDIR}/jpeg") set(JPEG_INCLUDE_DIR "${JPEG}/include") set(JPEG_LIBPATH ${JPEG}/lib) # not cmake defined @@ -923,28 +929,22 @@ elseif(WIN32) if(WITH_CYCLES_OSL) set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation") - message(STATUS "CYCLES_OSL = ${CYCLES_OSL}") - find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib) - # WARNING! depends on correct order of OSL libs linking list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} ${OSL_LIB_EXEC} ${OSL_LIB_QUERY}) find_path(OSL_INCLUDES OSL/oslclosure.h PATHS ${CYCLES_OSL}/include) find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin) if(OSL_INCLUDES AND OSL_LIBRARIES AND OSL_COMPILER) set(OSL_FOUND TRUE) - message(STATUS "OSL includes = ${OSL_INCLUDES}") - message(STATUS "OSL library = ${OSL_LIBRARIES}") - message(STATUS "OSL compiler = ${OSL_COMPILER}") else() message(STATUS "OSL not found") endif() endif() if(MSVC) - set(PLATFORM_LINKLIBS ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 advapi32 shfolder shell32 ole32 oleaut32 uuid) + set(PLATFORM_LINKLIBS ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 advapi32 shfolder shell32 ole32 oleaut32 uuid psapi) add_definitions(/D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /D_CONSOLE /D_LIB) @@ -974,13 +974,6 @@ elseif(WIN32) set(CXX_WARNINGS "${_WARNINGS}") unset(_WARNINGS) - if(WITH_INTERNATIONAL) - set(GETTEXT ${LIBDIR}/gettext) - set(GETTEXT_INCLUDE_DIRS ${GETTEXT}/include) - set(GETTEXT_LIBPATH ${GETTEXT}/lib) - set(GETTEXT_LIBRARIES gnu_gettext) - endif() - if(WITH_MOD_CLOTH_ELTOPO) set(LAPACK ${LIBDIR}/lapack) # set(LAPACK_INCLUDE_DIR ${LAPACK}/include) @@ -1072,6 +1065,7 @@ elseif(WIN32) if(WITH_IMAGE_OPENEXR) set_lib_path(OPENEXR "openexr") set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include) + set(OPENEXR_INCLUDE_DIRS ${OPENEXR}/include/OpenEXR) set(OPENEXR_LIBPATH ${OPENEXR}/lib) set(OPENEXR_LIBRARIES ${OPENEXR_LIBPATH}/Iex.lib @@ -1080,12 +1074,6 @@ elseif(WIN32) ${OPENEXR_LIBPATH}/Imath.lib ${OPENEXR_LIBPATH}/IlmThread.lib ) - set(OPENEXR_INCLUDE_DIRS - ${OPENEXR_INCLUDE_DIR} - ${OPENEXR_INCLUDE_DIR}/IlmImf - ${OPENEXR_INCLUDE_DIR}/Iex - ${OPENEXR_INCLUDE_DIR}/Imath - ) endif() if(WITH_IMAGE_TIFF) @@ -1103,9 +1091,17 @@ elseif(WIN32) if(WITH_PYTHON) # normally cached but not since we include them with blender - set(PYTHON_VERSION 3.2) # CACHE STRING) + if(MSVC10) + set(PYTHON_VERSION 3.2) # CACHE STRING) + else() + set(PYTHON_VERSION 3.3) # CACHE STRING) + endif() + set_lib_path(PYTHON "python") - set(PYTHON_LIBRARY ${PYTHON}/lib/python32.lib) #CACHE FILEPATH + STRING(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) + set(PYTHON_LIBRARY ${PYTHON}/lib/python${_PYTHON_VERSION_NO_DOTS}.lib) #CACHE FILEPATH + unset(_PYTHON_VERSION_NO_DOTS) + #Shared includes for both vc2008 and vc2010 set(PYTHON_INCLUDE_DIR ${LIBDIR}/python/include/python${PYTHON_VERSION}) @@ -1133,17 +1129,28 @@ elseif(WIN32) debug libboost_date_time-${BOOST_DEBUG_POSTFIX} debug libboost_filesystem-${BOOST_DEBUG_POSTFIX} debug libboost_regex-${BOOST_DEBUG_POSTFIX} debug libboost_system-${BOOST_DEBUG_POSTFIX} debug libboost_thread-${BOOST_DEBUG_POSTFIX}) + if(WITH_INTERNATIONAL) + set(BOOST_LIBRARIES ${BOOST_LIBRARIES} + optimized libboost_locale-${BOOST_POSTFIX} + debug libboost_locale-${BOOST_DEBUG_POSTFIX}) + endif(WITH_INTERNATIONAL) set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB") endif() if(WITH_OPENIMAGEIO) set(OPENIMAGEIO ${LIBDIR}/openimageio) set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include) - set(OPENIMAGEIO_LIBRARIES OpenImageIO) + set(OPENIMAGEIO_LIBRARIES optimized OpenImageIO debug OpenImageIO_d) set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib) - set(OPENIMAGEIO_DEFINITIONS) + set(OPENIMAGEIO_DEFINITIONS "-DUSE_TBB=0") endif() + if(WITH_LLVM) + set(LLVM_DIRECTORY ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation") + file(GLOB LLVM_LIBRARY ${LLVM_DIRECTORY}/lib/*.lib) + set(LLVM_STATIC YES) + endif() + if(WITH_OPENCOLORIO) set(OPENCOLORIO ${LIBDIR}/opencolorio) set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include) @@ -1152,6 +1159,7 @@ elseif(WIN32) set(OPENCOLORIO_DEFINITIONS) endif() + set(PLATFORM_LINKFLAGS "/SUBSYSTEM:CONSOLE /STACK:2097152 /INCREMENTAL:NO /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:msvcmrt.lib /NODEFAULTLIB:msvcurt.lib /NODEFAULTLIB:msvcrtd.lib") # MSVC only, Mingw doesnt need @@ -1186,16 +1194,8 @@ elseif(WIN32) add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE) - add_definitions(-DFREE_WINDOWS) - if(WITH_INTERNATIONAL) - set(GETTEXT ${LIBDIR}/gettext) - set(GETTEXT_INCLUDE_DIRS ${GETTEXT}/include) - set(GETTEXT_LIBPATH ${GETTEXT}/lib) - set(GETTEXT_LIBRARIES intl) - endif() - set(PNG "${LIBDIR}/png") set(PNG_INCLUDE_DIR "${PNG}/include") set(PNG_LIBPATH ${PNG}/lib) # not cmake defined @@ -1215,7 +1215,7 @@ elseif(WIN32) #comes with own pthread library if(NOT WITH_MINGW64) set(PTHREADS ${LIBDIR}/pthreads) - set(PTHREADS_INCLUDE_DIRS ${PTHREADS}/include) + #set(PTHREADS_INCLUDE_DIRS ${PTHREADS}/include) set(PTHREADS_LIBPATH ${PTHREADS}/lib) set(PTHREADS_LIBRARIES pthreadGC2) endif() @@ -1263,6 +1263,7 @@ elseif(WIN32) if(WITH_IMAGE_OPENEXR) set(OPENEXR ${LIBDIR}/openexr) + set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include) set(OPENEXR_INCLUDE_DIRS ${OPENEXR}/include/OpenEXR) set(OPENEXR_LIBRARIES Half IlmImf Imath IlmThread Iex) set(OPENEXR_LIBPATH ${OPENEXR}/lib) @@ -1287,9 +1288,9 @@ elseif(WIN32) if(WITH_PYTHON) # normally cached but not since we include them with blender - set(PYTHON_VERSION 3.2) # CACHE STRING) + set(PYTHON_VERSION 3.3) # CACHE STRING) set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}") # CACHE PATH) - set(PYTHON_LIBRARY "${LIBDIR}/python/lib/python32mw.lib") # CACHE FILEPATH) + set(PYTHON_LIBRARY "${LIBDIR}/python/lib/python33mw.lib") # CACHE FILEPATH) # uncached vars set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}") @@ -1313,6 +1314,11 @@ elseif(WIN32) debug boost_date_time-${BOOST_DEBUG_POSTFIX} boost_filesystem-${BOOST_DEBUG_POSTFIX} boost_regex-${BOOST_DEBUG_POSTFIX} boost_system-${BOOST_DEBUG_POSTFIX} boost_thread-${BOOST_DEBUG_POSTFIX}) + if(WITH_INTERNATIONAL) + set(BOOST_LIBRARIES ${BOOST_LIBRARIES} + optimized boost_locale-${BOOST_POSTFIX} + debug boost_locale-${BOOST_DEBUG_POSTFIX}) + endif() set(BOOST_LIBPATH ${BOOST}/lib) set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB -DBOOST_THREAD_USE_LIB ") endif() @@ -1325,6 +1331,34 @@ elseif(WIN32) set(OPENIMAGEIO_DEFINITIONS) endif() + if(WITH_LLVM) + set(LLVM_DIRECTORY ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation") + set(LLVM_LIB_DIR ${LLVM_DIRECTORY}/lib) + #Explicitly set llvm lib order. + #---- WARNING ON GCC ORDER OF LIBS IS IMPORTANT, DO NOT CHANGE! --------- + set(LLVM_LIBRARY LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMAnalysis LLVMArchive + LLVMAsmParser LLVMAsmPrinter + LLVMBitReader LLVMBitWriter + LLVMDebugInfo LLVMExecutionEngine + LLVMInstCombine LLVMInstrumentation + LLVMInterpreter LLVMJIT + LLVMLinker LLVMMC + LLVMMCDisassembler LLVMMCJIT + LLVMMCParser LLVMObject + LLVMRuntimeDyld + LLVMSupport + LLVMTableGen LLVMTarget + LLVMTransformUtils LLVMVectorize + LLVMX86AsmParser LLVMX86AsmPrinter + LLVMX86CodeGen LLVMX86Desc + 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") + set(LLVM_STATIC YES) + endif() + if(WITH_OPENCOLORIO) set(OPENCOLORIO ${LIBDIR}/opencolorio) set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include) @@ -1347,16 +1381,6 @@ elseif(APPLE) set(WITH_LIBS10.5 ON CACHE BOOL "Use 10.5 libs" FORCE) # valid also for 10.6/10.7 endif() - if(${XCODE_VERSION} VERSION_LESS 4.3) - set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk CACHE PATH "" FORCE) # use guaranteed existing sdk - else() - # note: i don't use xcode-select path on purpose, cause also /Applications/Xcode.app would be allowed - # absolute pathes are more foolproof here ! - set(OSX_SYSROOT_PREFIX /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform) - set(OSX_DEVELOPER_PREFIX /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk) # use guaranteed existing sdk - set(CMAKE_OSX_SYSROOT ${OSX_SYSROOT_PREFIX}/${OSX_DEVELOPER_PREFIX} CACHE PATH "" FORCE) - endif() - if(WITH_LIBS10.5) set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin-9.x.universal) else() @@ -1379,10 +1403,13 @@ elseif(APPLE) endif() if(WITH_JACK) - set(JACK /usr) - set(JACK_INCLUDE_DIRS ${JACK}/include/jack) - set(JACK_LIBRARIES jack) - set(JACK_LIBPATH ${JACK}/lib) + find_library(JACK_FRAMEWORK + NAMES jackmp + ) + set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers) + if(NOT JACK_FRAMEWORK) + set(WITH_JACK OFF) + endif() endif() if(WITH_CODEC_SNDFILE) @@ -1394,13 +1421,13 @@ elseif(APPLE) if(WITH_PYTHON) if(NOT WITH_PYTHON_MODULE) - # we use precompiled libraries for py 3.2 and up by default + # we use precompiled libraries for py 3.3 and up by default # normally cached but not since we include them with blender - set(PYTHON_VERSION 3.2) - set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}") + set(PYTHON_VERSION 3.3) + set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}m") # set(PYTHON_BINARY "${LIBDIR}/python/bin/python${PYTHON_VERSION}") # not used yet - set(PYTHON_LIBRARY python${PYTHON_VERSION}) + set(PYTHON_LIBRARY python${PYTHON_VERSION}m) set(PYTHON_LIBPATH "${LIBDIR}/python/lib/python${PYTHON_VERSION}") # set(PYTHON_LINKFLAGS "-u _PyMac_Error") # won't build with this enabled else() @@ -1420,13 +1447,6 @@ elseif(APPLE) set(PYTHON_LIBRARIES "${PYTHON_LIBRARY}") endif() - if(WITH_INTERNATIONAL) - set(GETTEXT ${LIBDIR}/gettext) - set(GETTEXT_INCLUDE_DIRS "${GETTEXT}/include") - set(GETTEXT_LIBRARIES intl iconv) - set(GETTEXT_LIBPATH ${GETTEXT}/lib) - endif() - if(WITH_FFTW3) set(FFTW3 ${LIBDIR}/fftw3) set(FFTW3_INCLUDE_DIRS ${FFTW3}/include) @@ -1493,10 +1513,10 @@ elseif(APPLE) if(WITH_INPUT_NDOF) # This thread it *should* work and check the framework - campbell # http://www.cmake.org/pipermail/cmake/2005-December/007740.html - find_library(3D_CONNEXION_CLIENT_LIBRARY + find_library(3DCONNEXION_CLIENT_FRAMEWORK NAMES 3DconnexionClient ) - if(NOT 3D_CONNEXION_CLIENT_LIBRARY) + if(NOT 3DCONNEXION_CLIENT_FRAMEWORK) set(WITH_INPUT_NDOF OFF) endif() @@ -1505,6 +1525,10 @@ elseif(APPLE) endif() endif() + if(WITH_JACK) + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -weak_framework jackmp") + endif() + else() set(PLATFORM_CFLAGS "-pipe -funsigned-char") set(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Carbon -framework AGL -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime") @@ -1567,7 +1591,11 @@ elseif(APPLE) if(WITH_BOOST) set(BOOST ${LIBDIR}/boost) set(BOOST_INCLUDE_DIR ${BOOST}/include) - set(BOOST_LIBRARIES boost_date_time-mt boost_filesystem-mt boost_regex-mt boost_system-mt boost_thread-mt) + set(BOOST_LIBRARIES boost_date_time-mt boost_filesystem-mt boost_regex-mt boost_system-mt boost_thread-mt boost_wave-mt) + if (WITH_INTERNATIONAL) + list(APPEND BOOST_LIBRARIES boost_locale-mt) + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -liconv") # boost_locale needs it ! + endif() set(BOOST_LIBPATH ${BOOST}/lib) set(BOOST_DEFINITIONS) endif() @@ -1592,7 +1620,7 @@ elseif(APPLE) set(LLVM_DIRECTORY ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation") set(LLVM_VERSION "3.1" CACHE STRING "Version of LLVM to use") set(LLVM_STATIC YES) - if(LLVM_DIRECTORY) + if(EXISTS "${LLVM_DIRECTORY}/bin/llvm-config") set(LLVM_CONFIG "${LLVM_DIRECTORY}/bin/llvm-config") else() set(LLVM_CONFIG llvm-config) @@ -1607,11 +1635,8 @@ elseif(APPLE) OUTPUT_VARIABLE LLVM_LIB_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) find_library(LLVM_LIBRARY - NAMES libLLVMAnalysis.a # first of a whole bunch of libs to get + NAMES LLVMAnalysis # first of a whole bunch of libs to get PATHS ${LLVM_LIB_DIR}) - message(STATUS "LLVM version = ${LLVM_VERSION}") - message(STATUS "LLVM dir = ${LLVM_DIRECTORY}") - message(STATUS "LLVM lib dir = ${LLVM_LIB_DIR}") if(LLVM_LIBRARY AND LLVM_DIRECTORY AND LLVM_LIB_DIR) if(LLVM_STATIC) @@ -1623,7 +1648,6 @@ elseif(APPLE) OUTPUT_STRIP_TRAILING_WHITESPACE) string(REPLACE " " ";" LLVM_LIBRARY ${LLVM_LIBRARY}) endif() - message(STATUS "LLVM library = ${LLVM_LIBRARY}") else() message(FATAL_ERROR "LLVM not found.") endif() @@ -1632,8 +1656,6 @@ elseif(APPLE) if(WITH_CYCLES_OSL) set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation") - message(STATUS "CYCLES_OSL = ${CYCLES_OSL}") - find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib) @@ -1644,9 +1666,6 @@ elseif(APPLE) if(OSL_INCLUDES AND OSL_LIBRARIES AND OSL_COMPILER) set(OSL_FOUND TRUE) - message(STATUS "OSL includes = ${OSL_INCLUDES}") - message(STATUS "OSL library = ${OSL_LIBRARIES}") - message(STATUS "OSL compiler = ${OSL_COMPILER}") else() message(STATUS "OSL not found") endif() @@ -1678,6 +1697,10 @@ if(APPLE OR WIN32) endif() endif() +if(NOT WITH_FFTW3 AND WITH_MOD_OCEANSIM) + message(FATAL_ERROR "WITH_MOD_OCEANSIM requires WITH_FFTW3 to be ON") +endif() + if(WITH_CYCLES) if(NOT WITH_OPENIMAGEIO) message(FATAL_ERROR "Cycles reqires WITH_OPENIMAGEIO, the library may not have been found. Configure OIIO or disable WITH_CYCLES") @@ -1693,6 +1716,11 @@ if(WITH_CYCLES) endif() endif() +if(WITH_INTERNATIONAL) + if(NOT WITH_BOOST) + message(FATAL_ERROR "Internationalization reqires WITH_BOOST, the library may not have been found. Configure BOOST or disable WITH_INTERNATIONAL") + endif() +endif() # See TEST_SSE_SUPPORT() for how this is defined. @@ -1842,7 +1870,7 @@ if(CMAKE_COMPILER_IS_GNUCC) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero) # gcc 4.2 gives annoying warnings on every file with this - if ("${CMAKE_C_COMPILER_VERSION}" VERSION_GREATER "4.2") + if (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.3") ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNINITIALIZED -Wuninitialized) endif() @@ -1862,7 +1890,7 @@ if(CMAKE_COMPILER_IS_GNUCC) ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero) # gcc 4.2 gives annoying warnings on every file with this - if ("${CMAKE_C_COMPILER_VERSION}" VERSION_GREATER "4.2") + if (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.3") ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNINITIALIZED -Wuninitialized) endif() @@ -1935,12 +1963,13 @@ if(WITH_PYTHON) if(WITH_PYTHON_INSTALL AND WITH_PYTHON_INSTALL_NUMPY) # set but invalid - if(NOT ${PYTHON_NUMPY_PATH} STREQUAL "") - if(NOT EXISTS "${PYTHON_NUMPY_PATH}/numpy") - message(WARNING "PYTHON_NUMPY_PATH is invalid, numpy not found in '${PYTHON_NUMPY_PATH}' " - "WITH_PYTHON_INSTALL_NUMPY option will be ignored when installing python") - set(WITH_PYTHON_INSTALL_NUMPY OFF) - endif() + # -- disabled until we make numpy bundled with blender - campbell + if((NOT ${PYTHON_NUMPY_PATH} STREQUAL "") AND (NOT ${PYTHON_NUMPY_PATH} MATCHES NOTFOUND)) +# if(NOT EXISTS "${PYTHON_NUMPY_PATH}/numpy") +# message(WARNING "PYTHON_NUMPY_PATH is invalid, numpy not found in '${PYTHON_NUMPY_PATH}' " +# "WITH_PYTHON_INSTALL_NUMPY option will be ignored when installing python") +# set(WITH_PYTHON_INSTALL_NUMPY OFF) +# endif() # not set, so initialize else() string(REPLACE "." ";" _PY_VER_SPLIT "${PYTHON_VERSION}") diff --git a/GNUmakefile b/GNUmakefile index f8207787cbe..c1b67c86ed2 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -173,14 +173,15 @@ help: @echo " * test_style_osl_qtc - checks OpenShadingLanguage conforms with blenders style guide: http://wiki.blender.org/index.php/Dev:Doc/CodeStyle" @echo "" @echo "Static Source Code Checking (not associated with building blender)" - @echo " * check_cppcheck - run blender source through cppcheck (C & C++)" - @echo " * check_clang_array - run blender source through clang array checking script (C & C++)" - @echo " * check_splint - run blenders source through splint (C only)" - @echo " * check_sparse - run blenders source through sparse (C only)" - @echo " * check_smatch - run blenders source through smatch (C only)" - @echo " * check_spelling_c - check for spelling errors (OSL only)" - @echo " * check_spelling_osl - check for spelling errors (C/C++ only)" - @echo " * check_spelling_py - check for spelling errors (Python only)" + @echo " * check_cppcheck - run blender source through cppcheck (C & C++)" + @echo " * check_clang_array - run blender source through clang array checking script (C & C++)" + @echo " * check_splint - run blenders source through splint (C only)" + @echo " * check_sparse - run blenders source through sparse (C only)" + @echo " * check_smatch - run blenders source through smatch (C only)" + @echo " * check_spelling_c - check for spelling errors (OSL only)" + @echo " * check_spelling_c_qtc - same as check_spelling_c but outputs QtCreator tasks format" + @echo " * check_spelling_osl - check for spelling errors (C/C++ only)" + @echo " * check_spelling_py - check for spelling errors (Python only)" @echo "" @echo "Utilities (not associated with building blender)" @echo " * tbz - create a compressed svn export 'blender_archive.tar.bz2'" @@ -240,13 +241,13 @@ test_style_c_qtc: test_style_osl: # run our own checks on C/C++ style - PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/check_style_c.py $(BLENDER_DIR)/intern/cycles/kernel/osl + PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/check_style_c.py $(BLENDER_DIR)/intern/cycles/kernel/shaders test_style_osl_qtc: # run our own checks on C/C++ style USE_QTC_TASK=1 \ - PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/check_style_c.py $(BLENDER_DIR)/intern/cycles/kernel/osl > \ + PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/check_style_c.py $(BLENDER_DIR)/intern/cycles/kernel/shaders > \ test_style.tasks @echo "written: test_style.tasks" @@ -270,32 +271,44 @@ project_eclipse: check_cppcheck: $(CMAKE_CONFIG) - cd $(BUILD_DIR) ; python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_cppcheck.py + cd $(BUILD_DIR) ; \ + python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_cppcheck.py check_clang_array: $(CMAKE_CONFIG) - cd $(BUILD_DIR) ; python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_clang_array.py + cd $(BUILD_DIR) ; \ + python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_clang_array.py check_splint: $(CMAKE_CONFIG) - cd $(BUILD_DIR) ; python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_splint.py + cd $(BUILD_DIR) ; \ + python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_splint.py check_sparse: $(CMAKE_CONFIG) - cd $(BUILD_DIR) ; python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_sparse.py + cd $(BUILD_DIR) ; \ + python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_sparse.py check_smatch: $(CMAKE_CONFIG) - cd $(BUILD_DIR) ; python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_smatch.py + cd $(BUILD_DIR) ; \ + python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_smatch.py check_spelling_py: - cd $(BUILD_DIR) ; PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/release/scripts + cd $(BUILD_DIR) ; \ + PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/release/scripts check_spelling_c: - cd $(BUILD_DIR) ; PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/source + cd $(BUILD_DIR) ; \ + PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/source + +check_spelling_c_qtc: + cd $(BUILD_DIR) ; USE_QTC_TASK=1 \ + PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/source > \ + $(BLENDER_DIR)/check_spelling_c.tasks check_spelling_osl: - cd $(BUILD_DIR) ; PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/intern/cycles/kernel/osl + cd $(BUILD_DIR) ; PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/intern/cycles/kernel/shaders # ----------------------------------------------------------------------------- # Utilities diff --git a/SConstruct b/SConstruct index 064ae0bc0b5..c2bae0459ca 100644 --- a/SConstruct +++ b/SConstruct @@ -306,6 +306,15 @@ if env['OURPLATFORM']=='darwin': else: env.Append(LINKFLAGS=['-Xlinker','-weak_framework','-Xlinker','Jackmp']) + if env['WITH_BF_CYCLES_OSL'] == 1: + OSX_OSL_LIBPATH = Dir(env.subst(env['BF_OSL_LIBPATH'])).abspath + # we need 2 variants of passing the oslexec with the force_load option, string and list type atm + env.Append(LINKFLAGS=['-L'+OSX_OSL_LIBPATH,'-loslcomp','-force_load '+ OSX_OSL_LIBPATH +'/liboslexec.a','-loslquery']) + env.Append(BF_PROGRAM_LINKFLAGS=['-Xlinker','-force_load','-Xlinker',OSX_OSL_LIBPATH +'/liboslexec.a']) + + # Trying to get rid of eventually clashes, we export some explicite as local symbols + env.Append(LINKFLAGS=['-Xlinker','-unexported_symbols_list','-Xlinker','./source/creator/osx_locals.map']) + if env['WITH_BF_OPENMP'] == 1: if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): env['CCFLAGS'].append('/openmp') @@ -422,16 +431,22 @@ if not quickie and do_clean: # with _any_ library but since we used a fixed python version this tends to # be most problematic. if env['WITH_BF_PYTHON']: - py_h = os.path.join(Dir(env.subst('${BF_PYTHON_INC}')).abspath, "Python.h") + found_python_h = found_pyconfig_h = False + for bf_python_inc in env.subst('${BF_PYTHON_INC}').split(): + py_h = os.path.join(Dir(bf_python_inc).abspath, "Python.h") + if os.path.exists(py_h): + found_python_h = True + py_h = os.path.join(Dir(bf_python_inc).abspath, "pyconfig.h") + if os.path.exists(py_h): + found_pyconfig_h = True - if not os.path.exists(py_h): - print("\nMissing: \"" + env.subst('${BF_PYTHON_INC}') + os.sep + "Python.h\",\n" + if not (found_python_h and found_pyconfig_h): + print("\nMissing: Python.h and/or pyconfig.h in\"" + env.subst('${BF_PYTHON_INC}') + "\",\n" " Set 'BF_PYTHON_INC' to point " - "to a valid python include path.\n Containing " - "Python.h for python version \"" + env.subst('${BF_PYTHON_VERSION}') + "\"") + "to valid python include path(s).\n Containing " + "Python.h and pyconfig.h for python version \"" + env.subst('${BF_PYTHON_VERSION}') + "\"") Exit() - del py_h if not os.path.isdir ( B.root_build_dir): @@ -571,11 +586,11 @@ B.init_lib_dict() Export('env') -BuildDir(B.root_build_dir+'/source', 'source', duplicate=0) +VariantDir(B.root_build_dir+'/source', 'source', duplicate=0) SConscript(B.root_build_dir+'/source/SConscript') -BuildDir(B.root_build_dir+'/intern', 'intern', duplicate=0) +VariantDir(B.root_build_dir+'/intern', 'intern', duplicate=0) SConscript(B.root_build_dir+'/intern/SConscript') -BuildDir(B.root_build_dir+'/extern', 'extern', duplicate=0) +VariantDir(B.root_build_dir+'/extern', 'extern', duplicate=0) SConscript(B.root_build_dir+'/extern/SConscript') # now that we have read all SConscripts, we know what @@ -685,6 +700,8 @@ if env['OURPLATFORM']!='darwin': source.remove('kernel.cpp') source.remove('CMakeLists.txt') source.remove('svm') + source.remove('closure') + source.remove('shaders') source.remove('osl') source=['intern/cycles/kernel/'+s for s in source] source.append('intern/cycles/util/util_color.h') @@ -700,6 +717,14 @@ if env['OURPLATFORM']!='darwin': if '__pycache__' in source: source.remove('__pycache__') source=['intern/cycles/kernel/svm/'+s for s in source] scriptinstall.append(env.Install(dir=dir,source=source)) + # closure + dir=os.path.join(env['BF_INSTALLDIR'], VERSION, 'scripts', 'addons','cycles', 'kernel', 'closure') + source=os.listdir('intern/cycles/kernel/closure') + if '.svn' in source: source.remove('.svn') + if '_svn' in source: source.remove('_svn') + if '__pycache__' in source: source.remove('__pycache__') + source=['intern/cycles/kernel/closure/'+s for s in source] + scriptinstall.append(env.Install(dir=dir,source=source)) # licenses dir=os.path.join(env['BF_INSTALLDIR'], VERSION, 'scripts', 'addons','cycles', 'license') @@ -719,6 +744,22 @@ if env['OURPLATFORM']!='darwin': cubin_file = os.path.join(kernel_build_dir, "kernel_%s.cubin" % arch) scriptinstall.append(env.Install(dir=dir,source=cubin_file)) + # osl shaders + if env['WITH_BF_CYCLES_OSL']: + dir=os.path.join(env['BF_INSTALLDIR'], VERSION, 'scripts', 'addons','cycles', 'shader') + + osl_source_dir = Dir('./intern/cycles/kernel/shaders').srcnode().path + oso_build_dir = os.path.join(B.root_build_dir, 'intern/cycles/kernel/shaders') + + headers='node_color.h node_fresnel.h node_texture.h oslutil.h stdosl.h'.split() + source=['intern/cycles/kernel/shaders/'+s for s in headers] + scriptinstall.append(env.Install(dir=dir,source=source)) + + for f in os.listdir(osl_source_dir): + if f.endswith('.osl'): + oso_file = os.path.join(oso_build_dir, f.replace('.osl', '.oso')) + scriptinstall.append(env.Install(dir=dir,source=oso_file)) + if env['WITH_BF_OCIO']: colormanagement = os.path.join('release', 'datafiles', 'colormanagement') @@ -819,10 +860,6 @@ else: if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'): dllsources = [] - if not env['OURPLATFORM'] in ('win32-mingw', 'linuxcross'): - # For MinGW and linuxcross static linking will be used - dllsources += ['${LCGDIR}/gettext/lib/gnu_gettext.dll'] - dllsources += ['${BF_ZLIB_LIBPATH}/zlib.dll'] # Used when linking to libtiff was dynamic # keep it here until compilation on all platform would be ok @@ -868,9 +905,6 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'): dllsources.append('${LCGDIR}/thumbhandler/lib/BlendThumb.dll') dllsources.append('${LCGDIR}/thumbhandler/lib/BlendThumb64.dll') - if env['WITH_BF_OIIO'] and env['OURPLATFORM'] != 'win32-mingw': - dllsources.append('${LCGDIR}/openimageio/bin/OpenImageIO.dll') - if env['WITH_BF_OCIO']: if not env['OURPLATFORM'] in ('win32-mingw', 'linuxcross'): dllsources.append('${LCGDIR}/opencolorio/bin/OpenColorIO.dll') diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh new file mode 100755 index 00000000000..072e999d827 --- /dev/null +++ b/build_files/build_environment/install_deps.sh @@ -0,0 +1,1875 @@ +#!/bin/bash + +# Parse command line! +ARGS=$( \ +getopt \ +-o s:i:t:h \ +--long source:,install:,threads:,help,with-all,with-osl,all-static,force-all,force-python,\ +force-boost,force-ocio,force-oiio,force-llvm,force-osl,force-ffmpeg,\ +skip-python,skip-boost,skip-ocio,skip-oiio,skip-llvm,skip-osl,skip-ffmpeg \ +-- "$@" \ +) + +DISTRO="" +SRC="$HOME/src/blender-deps" +INST="/opt/lib" +CWD=$PWD + +# Do not install some optional, potentially conflicting libs by default... +WITH_ALL=false + +# Do not yet enable osl, use --with-osl (or --with-all) option to try it. +WITH_OSL=false + +# Try to link everything statically. Use this to produce portable versions of blender. +ALL_STATIC=false + +THREADS=`cat /proc/cpuinfo | grep cores | uniq | sed -e "s/.*: *\(.*\)/\\1/"` +if [ -z "$THREADS" ]; then + THREADS=1 +fi + +COMMON_INFO="\"Source code of dependencies needed to be compiled will be downloaded and extracted into '\$SRC'. +Built libs of dependencies needed to be compiled will be installed into '\$INST'. +Please edit \\\$SRC and/or \\\$INST variables at the beginning of this script, +or use --source/--install options, if you want to use other paths! + +Number of threads for building: \$THREADS (automatically detected, use --threads= to override it). +Full install: \$WITH_ALL (use --with-all option to enable it). +Building OSL: \$WITH_OSL (use --with-osl option to enable it). +All static linking: \$ALL_STATIC (use --all-static option to enable it). + +Use --help to show all available options!\"" + +ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS: + -h, --help + Show this message and exit. + + -s , --source= + Use a specific path where to store downloaded libraries sources (defaults to '\$SRC'). + + -i , --install= + Use a specific path where to install built libraries (defaults to '\$INST'). + + -t n, --threads=n + Use a specific number of threads when building the libraries (auto-detected as '\$THREADS'). + + --with-all + By default, a number of optional and not-so-often needed libraries are not installed. + This option will try to install them, at the cost of potential conflicts (depending on + how your package system is set…). + Note this option also implies all other (more specific) --with-foo options below. + + --with-osl + Try to install or build the OpenShadingLanguage libraries (and their dependencies). + Still experimental! + + --all-static + Build libraries as statically as possible, to create static builds of Blender. + + --force-all + Force the rebuild of all built libraries. + + --force-python + Force the rebuild of Python. + + --force-boost + Force the rebuild of Boost. + + --force-ocio + Force the rebuild of OpenColorIO. + + --force-oiio + Force the rebuild of OpenImageIO. + + --force-llvm + Force the rebuild of LLVM. + + --force-osl + Force the rebuild of OpenShadingLanguage. + + --force-ffmpeg + Force the rebuild of FFMpeg. + + Note about the --force-foo options: + * They obviously only have an effect if those libraries are built by this script + (i.e. if there is no available and satisfactory package)! + * If the “force-rebuilt” library is a dependency of others, it will force the rebuild + of those libraries too (e.g. --force-boost will also rebuild oiio and osl...). + * Do not forget --with-osl if you built it and still want it! + + --skip-python + Unconditionally skip Python installation/building. + + --skip-boost + Unconditionally skip Boost installation/building. + + --skip-ocio + Unconditionally skip OpenColorIO installation/building. + + --skip-oiio + Unconditionally skip OpenImageIO installation/building. + + --skip-llvm + Unconditionally skip LLVM installation/building. + + --skip-osl + Unconditionally skip OpenShadingLanguage installation/building. + + --skip-ffmpeg + Unconditionally skip FFMpeg installation/building.\"" + +PYTHON_VERSION="3.3.0" +PYTHON_VERSION_MIN="3.3" +PYTHON_SOURCE="http://python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSION.tar.bz2" +PYTHON_FORCE_REBUILD=false +PYTHON_SKIP=false + +BOOST_VERSION="1.51.0" +_boost_version_nodots=`echo "$BOOST_VERSION" | sed -r 's/\./_/g'` +BOOST_SOURCE="http://sourceforge.net/projects/boost/files/boost/$BOOST_VERSION/boost_$_boost_version_nodots.tar.bz2/download" +BOOST_VERSION_MIN="1.49" +BOOST_FORCE_REBUILD=false +BOOST_SKIP=false + +OCIO_VERSION="1.0.7" +OCIO_SOURCE="https://github.com/imageworks/OpenColorIO/tarball/v$OCIO_VERSION" +OCIO_VERSION_MIN="1.0" +OCIO_FORCE_REBUILD=false +OCIO_SKIP=false + +OIIO_VERSION="1.1.1" +OIIO_SOURCE="https://github.com/OpenImageIO/oiio/tarball/Release-$OIIO_VERSION" +OIIO_VERSION_MIN="1.1" +OIIO_FORCE_REBUILD=false +OIIO_SKIP=false + +LLVM_VERSION="3.1" +LLVM_VERSION_MIN="3.0" +LLVM_VERSION_FOUND="" +LLVM_SOURCE="http://llvm.org/releases/$LLVM_VERSION/llvm-$LLVM_VERSION.src.tar.gz" +LLVM_CLANG_SOURCE="http://llvm.org/releases/$LLVM_VERSION/clang-$LLVM_VERSION.src.tar.gz" +LLVM_FORCE_REBUILD=false +LLVM_SKIP=false + +# OSL needs to be compiled for now! +OSL_VERSION="1.2.0" +OSL_SOURCE="https://github.com/mont29/OpenShadingLanguage/archive/blender-fixes.tar.gz" +OSL_FORCE_REBUILD=false +OSL_SKIP=false + +FFMPEG_VERSION="1.0" +FFMPEG_SOURCE="http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" +FFMPEG_VERSION_MIN="0.7.6" +FFMPEG_FORCE_REBUILD=false +FFMPEG_SKIP=false +_ffmpeg_list_sep=";" + +# FFMPEG optional libs. +VORBIS_USE=false +VORBIS_DEV="" +SCHRO_USE=false +SCRHO_DEV="" +THEORA_USE=false +THEORA_DEV="" +XVID_USE=false +XVID_DEV="" +X264_USE=false +X264_DEV="" +X264_VERSION_MIN=0.118 +VPX_USE=false +VPX_VERSION_MIN=0.9.7 +VPX_DEV="" +MP3LAME_USE=false +MP3LAME_DEV="" +OPENJPEG_USE=false +OPENJPEG_DEV="" + +# Switch to english language, else some things (like check_package_DEB()) won't work! +LANG_BACK=$LANG +LANG="" +export LANG + + +_echo() { + if [ "X$1" = "X-n" ]; then + shift; printf "%s" "$@" + else + printf "%s\n" "$@" + fi +} + +ERROR() { + _echo "$@" +} + +INFO() { + _echo "$@" +} + +# Finish parsing the commandline args. +eval set -- "$ARGS" +while true; do + case $1 in + -s|--source) + SRC="$2"; shift; shift; continue + ;; + -i|--install) + INST="$2"; shift; shift; continue + ;; + -t|--threads) + THREADS="$2"; shift; shift; continue + ;; + -h|--help) + INFO "" + INFO "USAGE:" + INFO "" + INFO "`eval _echo "$COMMON_INFO"`" + INFO "" + INFO "`eval _echo "$ARGUMENTS_INFO"`" + INFO "" + exit 0 + ;; + --with-all) + WITH_ALL=true; shift; continue + ;; + --with-osl) + WITH_OSL=true; shift; continue + ;; + --all-static) + ALL_STATIC=true; shift; continue + ;; + --force-all) + PYTHON_FORCE_REBUILD=true + BOOST_FORCE_REBUILD=true + OCIO_FORCE_REBUILD=true + OIIO_FORCE_REBUILD=true + LLVM_FORCE_REBUILD=true + OSL_FORCE_REBUILD=true + FFMPEG_FORCE_REBUILD=true + shift; continue + ;; + --force-python) + PYTHON_FORCE_REBUILD=true; shift; continue + ;; + --force-boost) + BOOST_FORCE_REBUILD=true; shift; continue + ;; + --force-ocio) + OCIO_FORCE_REBUILD=true; shift; continue + ;; + --force-oiio) + OIIO_FORCE_REBUILD=true; shift; continue + ;; + --force-llvm) + LLVM_FORCE_REBUILD=true; shift; continue + ;; + --force-osl) + OSL_FORCE_REBUILD=true; shift; continue + ;; + --force-ffmpeg) + FFMPEG_FORCE_REBUILD=true; shift; continue + ;; + --skip-python) + PYTHON_SKIP=true; shift; continue + ;; + --skip-boost) + BOOST_SKIP=true; shift; continue + ;; + --skip-ocio) + OCIO_SKIP=true; shift; continue + ;; + --skip-oiio) + OIIO_SKIP=true; shift; continue + ;; + --skip-llvm) + LLVM_SKIP=true; shift; continue + ;; + --skip-osl) + OSL_SKIP=true; shift; continue + ;; + --skip-ffmpeg) + FFMPEG_SKIP=true; shift; continue + ;; + --) + # no more arguments to parse + break + ;; + *) + INFO "" + INFO "Wrong parameter! Usage:" + INFO "" + INFO "`eval _echo "$COMMON_INFO"`" + INFO "" + exit 1 + ;; + esac +done + +if $WITH_ALL; then + WITH_OSL=true +fi + +# Return 0 if $1 = $2 (i.e. 1.01.0 = 1.1, but 1.1.1 != 1.1), else 1. +# $1 and $2 should be version numbers made of numbers only. +version_eq() { + backIFS=$IFS + IFS='.' + + # Split both version numbers into their numeric elements. + arr1=( $1 ) + arr2=( $2 ) + + ret=1 + + count1=${#arr1[@]} + count2=${#arr2[@]} + if [ $count2 -ge $count1 ]; then + _t=$count1 + count1=$count2 + count2=$_t + arr1=( $2 ) + arr2=( $1 ) + fi + + ret=0 + for (( i=0; $i < $count2; i++ )) + do + if [ $(( 10#${arr1[$i]} )) -ne $(( 10#${arr2[$i]} )) ]; then + ret=1 + break + fi + done + + for (( i=$count2; $i < $count1; i++ )) + do + if [ $(( 10#${arr1[$i]} )) -ne 0 ]; then + ret=1 + break + fi + done + + IFS=$backIFS + return $ret +} + +# Return 0 if $1 >= $2, else 1. +# $1 and $2 should be version numbers made of numbers only. +version_ge() { + version_eq $1 $2 + if [ $? -eq 1 -a $(_echo "$1" "$2" | sort --version-sort | head --lines=1) = "$1" ]; then + return 1 + else + return 0 + fi +} + +# Return 0 if $1 is into $2 (e.g. 3.3.2 is into 3.3, but not 3.3.0 or 3.3.5), else 1. +# $1 and $2 should be version numbers made of numbers only. +# $1 should be at least as long as $2! +version_match() { + backIFS=$IFS + IFS='.' + + # Split both version numbers into their numeric elements. + arr1=( $1 ) + arr2=( $2 ) + + ret=1 + + count1=${#arr1[@]} + count2=${#arr2[@]} + if [ $count1 -ge $count2 ]; then + ret=0 + for (( i=0; $i < $count2; i++ )) + do + if [ $(( 10#${arr1[$i]} )) -ne $(( 10#${arr2[$i]} )) ]; then + ret=1 + break + fi + done + fi + + IFS=$backIFS + return $ret +} + +detect_distro() { + if [ -f /etc/debian_version ]; then + DISTRO="DEB" + elif [ -f /etc/redhat-release ]; then + DISTRO="RPM" + elif [ -f /etc/SuSE-release ]; then + DISTRO="SUSE" + fi +} + +prepare_opt() { + INFO "Ensuring $INST exists and is writable by us" + if [ ! -d $INST ]; then + sudo mkdir -p $INST + fi + + if [ ! -w $INST ]; then + sudo chown $USER $INST + sudo chmod 775 $INST + fi +} + +# Check whether the current package needs to be recompiled, based on a dummy file containing a magic number in its name... +magic_compile_check() { + if [ -f $INST/.$1-magiccheck-$2 ]; then + return 0 + else + return 1 + fi +} + +magic_compile_set() { + rm -f $INST/.$1-magiccheck-* + touch $INST/.$1-magiccheck-$2 +} + +compile_Python() { + # To be changed each time we make edits that would modify the compiled result! + py_magic=0 + + _src=$SRC/Python-$PYTHON_VERSION + _inst=$INST/python-$PYTHON_VERSION + + # Clean install if needed! + magic_compile_check python-$PYTHON_VERSION $py_magic + if [ $? -eq 1 -o $PYTHON_FORCE_REBUILD == true ]; then + rm -rf $_inst + fi + + if [ ! -d $_inst ]; then + INFO "Building Python-$PYTHON_VERSION" + + prepare_opt + + if [ ! -d $_src ]; then + mkdir -p $SRC + wget -c $PYTHON_SOURCE -O $_src.tar.bz2 + + INFO "Unpacking Python-$PYTHON_VERSION" + tar -C $SRC -xf $_src.tar.bz2 + fi + + cd $_src + + ./configure --prefix=$_inst --enable-ipv6 \ + --enable-loadable-sqlite-extensions --with-dbmliborder=bdb \ + --with-computed-gotos --with-pymalloc + + make -j$THREADS && make install + make clean + + if [ -d $_inst ]; then + rm -f $INST/python-3.3 + ln -s python-$PYTHON_VERSION $INST/python-3.3 + else + ERROR "Python--$PYTHON_VERSION failed to compile, exiting" + exit 1 + fi + + magic_compile_set python-$PYTHON_VERSION $py_magic + + cd $CWD + INFO "Done compiling Python-$PYTHON_VERSION!" + else + INFO "Own Python-$PYTHON_VERSION is up to date, nothing to do!" + INFO "If you want to force rebuild of this lib, use the --force-python option." + fi +} + +compile_Boost() { + # To be changed each time we make edits that would modify the compiled result! + boost_magic=7 + + _src=$SRC/boost-$BOOST_VERSION + _inst=$INST/boost-$BOOST_VERSION + + # Clean install if needed! + magic_compile_check boost-$BOOST_VERSION $boost_magic + if [ $? -eq 1 -o $BOOST_FORCE_REBUILD == true ]; then + rm -rf $_inst + fi + + if [ ! -d $_inst ]; then + INFO "Building Boost-$BOOST_VERSION" + + prepare_opt + + if [ ! -d $_src ]; then + INFO "Downloading Boost-$BOOST_VERSION" + mkdir -p $SRC + wget -c $BOOST_SOURCE -O $_src.tar.bz2 + tar -C $SRC --transform "s,(.*/?)boost_1_[^/]+(.*),\1boost-$BOOST_VERSION\2,x" -xf $_src.tar.bz2 + fi + + cd $_src + if [ ! -f $_src/b2 ]; then + ./bootstrap.sh + fi + ./b2 -j$THREADS -a --with-system --with-filesystem --with-thread --with-regex --with-locale --with-date_time \ + --prefix=$_inst --disable-icu boost.locale.icu=off install + ./b2 --clean + + if [ -d $_inst ]; then + rm -f $INST/boost + ln -s boost-$BOOST_VERSION $INST/boost + else + ERROR "Boost-$BOOST_VERSION failed to compile, exiting" + exit 1 + fi + + magic_compile_set boost-$BOOST_VERSION $boost_magic + + # Rebuild dependecies as well! + OIIO_FORCE_REBUILD=true + OSL_FORCE_REBUILD=true + + cd $CWD + INFO "Done compiling Boost-$BOOST_VERSION!" + else + INFO "Own Boost-$BOOST_VERSION is up to date, nothing to do!" + INFO "If you want to force rebuild of this lib, use the --force-boost option." + fi +} + +compile_OCIO() { + # To be changed each time we make edits that would modify the compiled result! + ocio_magic=1 + + _src=$SRC/OpenColorIO-$OCIO_VERSION + _inst=$INST/ocio-$OCIO_VERSION + + # Clean install if needed! + magic_compile_check ocio-$OCIO_VERSION $ocio_magic + if [ $? -eq 1 -o $OCIO_FORCE_REBUILD == true ]; then + rm -rf $_inst + fi + + if [ ! -d $_inst ]; then + INFO "Building OpenColorIO-$OCIO_VERSION" + + prepare_opt + + if [ ! -d $_src ]; then + INFO "Downloading OpenColorIO-$OCIO_VERSION" + mkdir -p $SRC + wget -c $OCIO_SOURCE -O $_src.tar.gz + + INFO "Unpacking OpenColorIO-$OCIO_VERSION" + tar -C $SRC --transform "s,(.*/?)imageworks-OpenColorIO[^/]*(.*),\1OpenColorIO-$OCIO_VERSION\2,x" \ + -xf $_src.tar.gz + fi + + cd $_src + # Always refresh the whole build! + if [ -d build ]; then + rm -rf build + fi + mkdir build + cd build + + if file /bin/cp | grep -q '32-bit'; then + cflags="-fPIC -m32 -march=i686" + else + cflags="-fPIC" + fi + + cmake -D CMAKE_BUILD_TYPE=Release \ + -D CMAKE_PREFIX_PATH=$_inst \ + -D CMAKE_INSTALL_PREFIX=$_inst \ + -D CMAKE_CXX_FLAGS="$cflags" \ + -D CMAKE_EXE_LINKER_FLAGS="-lgcc_s -lgcc" \ + -D OCIO_BUILD_APPS=OFF \ + -D OCIO_BUILD_PYGLUE=OFF \ + .. + + make -j$THREADS && make install + + # Force linking against static libs + rm -f $_inst/lib/*.so* + + # Additional depencencies + cp ext/dist/lib/libtinyxml.a $_inst/lib + cp ext/dist/lib/libyaml-cpp.a $_inst/lib + + make clean + + if [ -d $_inst ]; then + rm -f $INST/ocio + ln -s ocio-$OCIO_VERSION $INST/ocio + else + ERROR "OpenColorIO-$OCIO_VERSION failed to compile, exiting" + exit 1 + fi + + magic_compile_set ocio-$OCIO_VERSION $ocio_magic + + cd $CWD + INFO "Done compiling OpenColorIO-$OCIO_VERSION!" + else + INFO "Own OpenColorIO-$OCIO_VERSION is up to date, nothing to do!" + INFO "If you want to force rebuild of this lib, use the --force-ocio option." + fi +} + +compile_OIIO() { + # To be changed each time we make edits that would modify the compiled result! + oiio_magic=6 + + _src=$SRC/OpenImageIO-$OIIO_VERSION + _inst=$INST/oiio-$OIIO_VERSION + + # Clean install if needed! + magic_compile_check oiio-$OIIO_VERSION $oiio_magic + if [ $? -eq 1 -o $OIIO_FORCE_REBUILD == true ]; then + rm -rf $_inst + fi + + if [ ! -d $_inst ]; then + INFO "Building OpenImageIO-$OIIO_VERSION" + + prepare_opt + + if [ ! -d $_src ]; then + mkdir -p $SRC + wget -c $OIIO_SOURCE -O "$_src.tar.gz" + + INFO "Unpacking OpenImageIO-$OIIO_VERSION" + tar -C $SRC --transform "s,(.*/?)OpenImageIO-oiio[^/]*(.*),\1OpenImageIO-$OIIO_VERSION\2,x" \ + -xf $_src.tar.gz + + cd $_src + + # XXX Ugly patching hack! + cat << EOF | patch -p1 +diff --git a/src/libutil/SHA1.cpp b/src/libutil/SHA1.cpp +index b9e6c8b..c761185 100644 +--- a/src/libutil/SHA1.cpp ++++ b/src/libutil/SHA1.cpp +@@ -8,9 +8,9 @@ + + // If compiling with MFC, you might want to add #include "StdAfx.h" + ++#include "SHA1.h" + #include "hash.h" + #include "dassert.h" +-#include "SHA1.h" + + #ifdef SHA1_UTILITY_FUNCTIONS + #define SHA1_MAX_FILE_BUFFER 8000 +EOF + + cd $CWD + + fi + + cd $_src + # Always refresh the whole build! + if [ -d build ]; then + rm -rf build + fi + mkdir build + cd build + + cmake_d="-D CMAKE_BUILD_TYPE=Release" + cmake_d="$cmake_d -D CMAKE_PREFIX_PATH=$_inst" + cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst" + cmake_d="$cmake_d -D BUILDSTATIC=ON" + + # linking statically could give issues on Debian/Ubuntu (and probably other distros + # which doesn't like static linking) when linking shared oiio library due to missing + # text symbols (static libs should be compiled with -fPIC) + # cmake_d="$cmake_d -D LINKSTATIC=ON" + + if [ -d $INST/boost ]; then + cmake_d="$cmake_d -D BOOST_ROOT=$INST/boost -D Boost_NO_SYSTEM_PATHS=ON" + if $ALL_STATIC; then + cmake_d="$cmake_d -D Boost_USE_STATIC_LIBS=ON" + fi + fi + + # Looks like we do not need ocio in oiio for now... +# if [ -d $INST/ocio ]; then +# cmake_d="$cmake_d -D OCIO_PATH=$INST/ocio" +# fi + + if file /bin/cp | grep -q '32-bit'; then + cflags="-fPIC -m32 -march=i686" + else + cflags="-fPIC" + fi + + cmake $cmake_d -D CMAKE_CXX_FLAGS="$cflags" -D CMAKE_EXE_LINKER_FLAGS="-lgcc_s -lgcc" ../src + + make -j$THREADS && make install + make clean + + if [ -d $_inst ]; then + rm -f $INST/oiio + ln -s oiio-$OIIO_VERSION $INST/oiio + else + ERROR "OpenImageIO-$OIIO_VERSION failed to compile, exiting" + exit 1 + fi + + magic_compile_set oiio-$OIIO_VERSION $oiio_magic + + # Rebuild dependecies as well! + OSL_FORCE_REBUILD=true + + cd $CWD + INFO "Done compiling OpenImageIO-$OIIO_VERSION!" + else + INFO "Own OpenImageIO-$OIIO_VERSION is up to date, nothing to do!" + INFO "If you want to force rebuild of this lib, use the --force-oiio option." + fi +} + +compile_LLVM() { + # To be changed each time we make edits that would modify the compiled result! + llvm_magic=1 + + _src=$SRC/LLVM-$LLVM_VERSION + _inst=$INST/llvm-$LLVM_VERSION + _src_clang=$SRC/CLANG-$LLVM_VERSION + + # Clean install if needed! + magic_compile_check llvm-$LLVM_VERSION $llvm_magic + if [ $? -eq 1 -o $LLVM_FORCE_REBUILD == true ]; then + rm -rf $_inst + rm -rf $_inst_clang + fi + + if [ ! -d $_inst ]; then + INFO "Building LLVM-$LLVM_VERSION (CLANG included!)" + + prepare_opt + + if [ ! -d $_src -o true ]; then + mkdir -p $SRC + wget -c $LLVM_SOURCE -O "$_src.tar.gz" + wget -c $LLVM_CLANG_SOURCE -O "$_src_clang.tar.gz" + + INFO "Unpacking LLVM-$LLVM_VERSION" + tar -C $SRC --transform "s,([^/]*/?)llvm-[^/]*(.*),\1LLVM-$LLVM_VERSION\2,x" \ + -xf $_src.tar.gz + INFO "Unpacking CLANG-$LLVM_VERSION to $_src/tools/clang" + tar -C $_src/tools \ + --transform "s,([^/]*/?)clang-[^/]*(.*),\1clang\2,x" \ + -xf $_src_clang.tar.gz + + cd $_src + + # XXX Ugly patching hack! + cat << EOF | patch -p1 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -13,7 +13,7 @@ + set(LLVM_VERSION_MAJOR 3) + set(LLVM_VERSION_MINOR 1) + +-set(PACKAGE_VERSION "\${LLVM_VERSION_MAJOR}.\${LLVM_VERSION_MINOR}svn") ++set(PACKAGE_VERSION "\${LLVM_VERSION_MAJOR}.\${LLVM_VERSION_MINOR}") + + set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +EOF + + cd $CWD + + fi + + cd $_src + + # Always refresh the whole build! + if [ -d build ]; then + rm -rf build + fi + mkdir build + cd build + + cmake_d="-D CMAKE_BUILD_TYPE=Release" + cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst" + cmake_d="$cmake_d -D LLVM_ENABLE_FFI=ON" + + if [ -d $_FFI_INCLUDE_DIR ]; then + cmake_d="$cmake_d -D FFI_INCLUDE_DIR=$_FFI_INCLUDE_DIR" + fi + + cmake $cmake_d .. + + make -j$THREADS && make install + make clean + + if [ -d $_inst ]; then + rm -f $INST/llvm + ln -s llvm-$LLVM_VERSION $INST/llvm + else + ERROR "LLVM-$LLVM_VERSION failed to compile, exiting" + exit 1 + fi + + magic_compile_set llvm-$LLVM_VERSION $llvm_magic + + # Rebuild dependecies as well! + OSL_FORCE_REBUILD=true + + cd $CWD + INFO "Done compiling LLVM-$LLVM_VERSION (CLANG included)!" + else + INFO "Own LLVM-$LLVM_VERSION (CLANG included) is up to date, nothing to do!" + INFO "If you want to force rebuild of this lib, use the --force-llvm option." + fi +} + +compile_OSL() { + # To be changed each time we make edits that would modify the compiled result! + osl_magic=7 + + _src=$SRC/OpenShadingLanguage-$OSL_VERSION + _inst=$INST/osl-$OSL_VERSION + + # Clean install if needed! + magic_compile_check osl-$OSL_VERSION $osl_magic + if [ $? -eq 1 -o $OSL_FORCE_REBUILD == true ]; then + rm -rf $_inst + fi + + if [ ! -d $_inst ]; then + INFO "Building OpenShadingLanguage-$OSL_VERSION" + + prepare_opt + + if [ ! -d $_src ]; then + mkdir -p $SRC + + # XXX Using git on my own repo for now, looks like archives are not updated immediately... :/ +# wget -c $OSL_SOURCE -O "$_src.tar.gz" + +# INFO "Unpacking OpenShadingLanguage-$OSL_VERSION" +# tar -C $SRC --transform "s,(.*/?)OpenShadingLanguage-[^/]*(.*),\1OpenShadingLanguage-$OSL_VERSION\2,x" \ +# -xf $_src.tar.gz + git clone https://github.com/mont29/OpenShadingLanguage.git $_src + cd $_src + git checkout blender-fixes + cd $CWD + fi + + cd $_src + # XXX For now, always update from latest repo... + git pull origin + + # Always refresh the whole build! + if [ -d build ]; then + rm -rf build + fi + mkdir build + cd build + + cmake_d="-D CMAKE_BUILD_TYPE=Release" + cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst" + cmake_d="$cmake_d -D BUILDSTATIC=ON" + cmake_d="$cmake_d -D BUILD_TESTING=OFF" + + if [ -d $INST/boost ]; then + cmake_d="$cmake_d -D BOOST_ROOT=$INST/boost -D Boost_NO_SYSTEM_PATHS=ON" + if $ALL_STATIC; then + cmake_d="$cmake_d -D Boost_USE_STATIC_LIBS=ON" + fi + fi + + if [ -d $INST/oiio ]; then + cmake_d="$cmake_d -D OPENIMAGEIOHOME=$INST/oiio" + fi + + if [ ! -z $LLVM_VERSION_FOUND ]; then + cmake_d="$cmake_d -D LLVM_VERSION=$LLVM_VERSION_FOUND" + if [ -d $INST/llvm ]; then + cmake_d="$cmake_d -D LLVM_DIRECTORY=$INST/llvm" + cmake_d="$cmake_d -D LLVM_STATIC=ON" + fi + fi + + cmake $cmake_d ../src + + make -j$THREADS && make install + make clean + + if [ -d $_inst ]; then + rm -f $INST/osl + ln -s osl-$OSL_VERSION $INST/osl + else + ERROR "OpenShadingLanguage-$OSL_VERSION failed to compile, exiting" + exit 1 + fi + + magic_compile_set osl-$OSL_VERSION $osl_magic + + cd $CWD + INFO "Done compiling OpenShadingLanguage-$OSL_VERSION!" + else + INFO "Own OpenShadingLanguage-$OSL_VERSION is up to date, nothing to do!" + INFO "If you want to force rebuild of this lib, use the --force-osl option." + fi +} + +compile_FFmpeg() { + # To be changed each time we make edits that would modify the compiled result! + ffmpeg_magic=3 + + _src=$SRC/ffmpeg-$FFMPEG_VERSION + _inst=$INST/ffmpeg-$FFMPEG_VERSION + + # Clean install if needed! + magic_compile_check ffmpeg-$FFMPEG_VERSION $ffmpeg_magic + if [ $? -eq 1 -o $FFMPEG_FORCE_REBUILD == true ]; then + rm -rf $_inst + fi + + if [ ! -d $_inst ]; then + INFO "Building ffmpeg-$FFMPEG_VERSION" + + prepare_opt + + if [ ! -d $_src ]; then + INFO "Downloading ffmpeg-$FFMPEG_VERSION" + mkdir -p $SRC + wget -c $FFMPEG_SOURCE -O "$_src.tar.bz2" + + INFO "Unpacking ffmpeg-$FFMPEG_VERSION" + tar -C $SRC -xf $_src.tar.bz2 + fi + + cd $_src + + extra="" + + if $VORBIS_USE; then + extra="$extra --enable-libvorbis" + fi + + if $THEORA_USE; then + extra="$extra --enable-libtheora" + fi + + # XXX At least under Debian, static schro gives problem at blender linking time... :/ + if $SCHRO_USE && ! $ALL_STATIC; then + extra="$extra --enable-libschroedinger" + fi + + if $XVID_USE; then + extra="$extra --enable-libxvid" + fi + + if $X264_USE; then + extra="$extra --enable-libx264" + fi + + if $VPX_USE; then + extra="$extra --enable-libvpx" + fi + + if $MP3LAME_USE; then + extra="$extra --enable-libmp3lame" + fi + + if $OPENJPEG_USE; then + extra="$extra --enable-libopenjpeg" + fi + + ./configure --cc="gcc -Wl,--as-needed" \ + --extra-ldflags="-pthread -static-libgcc" \ + --prefix=$_inst --enable-static \ + --disable-ffplay --disable-ffserver --disable-doc \ + --enable-gray \ + --enable-avfilter --disable-vdpau \ + --disable-bzlib --disable-libgsm --disable-libspeex \ + --enable-pthreads --enable-zlib --enable-stripping --enable-runtime-cpudetect \ + --disable-vaapi --disable-libfaac --disable-nonfree --enable-gpl \ + --disable-postproc --disable-x11grab --disable-librtmp --disable-libopencore-amrnb \ + --disable-libopencore-amrwb --disable-libdc1394 --disable-version3 --disable-outdev=sdl \ + --disable-outdev=alsa --disable-indev=sdl --disable-indev=alsa --disable-indev=jack \ + --disable-indev=lavfi $extra + + make -j$THREADS && make install + make clean + + if [ -d $_inst ]; then + rm -f $INST/ffmpeg + ln -s ffmpeg-$FFMPEG_VERSION $INST/ffmpeg + else + ERROR "FFmpeg-$FFMPEG_VERSION failed to compile, exiting" + exit 1 + fi + + magic_compile_set ffmpeg-$FFMPEG_VERSION $ffmpeg_magic + + cd $CWD + INFO "Done compiling ffmpeg-$FFMPEG_VERSION!" + else + INFO "Own ffmpeg-$FFMPEG_VERSION is up to date, nothing to do!" + INFO "If you want to force rebuild of this lib, use the --force-ffmpeg option." + fi +} + +get_package_version_DEB() { + dpkg-query -W -f '${Version}' $1 | sed -r 's/.*:\s*([0-9]+:)(([0-9]+\.?)+).*/\2/' +} + +check_package_DEB() { + r=`apt-cache policy $1 | grep -c 'Candidate:'` + + if [ $r -ge 1 ]; then + return 0 + else + return 1 + fi +} + +check_package_version_match_DEB() { + v=`apt-cache policy $1 | grep 'Candidate:' | sed -r 's/.*:\s*([0-9]+:)(([0-9]+\.?)+).*/\2/'` + + if [ -z "$v" ]; then + return 1 + fi + + version_match $v $2 + return $? +} + +check_package_version_ge_DEB() { + v=`apt-cache policy $1 | grep 'Candidate:' | sed -r 's/.*:\s*([0-9]+:)?(([0-9]+\.?)+).*/\2/'` + + if [ -z "$v" ]; then + return 1 + fi + + version_ge $v $2 + return $? +} + +install_packages_DEB() { + sudo apt-get install -y $@ + if [ $? -ge 1 ]; then + ERROR "apt-get failed to install requested packages, exiting." + exit 1 + fi +} + +install_DEB() { + INFO "" + INFO "Installing dependencies for DEB-based distribution" + INFO "" + INFO "`eval _echo "$COMMON_INFO"`" + INFO "" + + if [ ! -z "`cat /etc/debian_version | grep ^6`" ]; then + if [ -z "`cat /etc/apt/sources.list | grep backports.debian.org`" ]; then + INFO "Looks like you're using Debian Squeeze which does have broken CMake" + INFO "It is highly recommended to install cmake from backports, otherwise" + INFO "compilation of some libraries could fail" + INFO "" + INFO "You could install newer CMake from debian-backports repository" + INFO "Add this this line to your /etc/apt/sources.lixt:" + INFO "" + INFO "deb http://backports.debian.org/debian-backports squeeze-backports main" + INFO "" + INFO "and then run:" + INFO "" + INFO "sudo apt-get update && sudo apt-get install cmake=2.8.7-4~bpo60+1 sudo apt-get install cmake=2.8.7-4~bpo60+1" + INFO "" + INFO "(you could also add this reporisotry using GUI like synaptic)" + INFO "" + INFO "Hit Enter to continue running the script, or hit Ctrl-C to abort the script" + + read + INFO "" + fi + fi + + sudo apt-get update +# XXX Why in hell? Let's let this stuff to the user's responsability!!! +# sudo apt-get -y upgrade + + # These libs should always be available in debian/ubuntu official repository... + OPENJPEG_DEV="libopenjpeg-dev" + SCHRO_DEV="libschroedinger-dev" + VORBIS_DEV="libvorbis-dev" + THEORA_DEV="libtheora-dev" + + _packages="gawk cmake scons build-essential libjpeg-dev libpng-dev libtiff-dev \ + libfreetype6-dev libx11-dev libxi-dev wget libsqlite3-dev libbz2-dev \ + libncurses5-dev libssl-dev liblzma-dev libreadline-dev $OPENJPEG_DEV \ + libopenexr-dev libopenal-dev libglew-dev yasm $THEORA_DEV \ + $VORBIS_DEV libsdl1.2-dev libfftw3-dev python-dev patch bzip2" + OPENJPEG_USE=true + VORBIS_USE=true + THEORA_USE=true + + if $WITH_ALL; then + _packages="$_packages $SCHRO_DEV libjack0 libjack-dev" + SCHRO_USE=true + fi + + INFO "" + install_packages_DEB $_packages + + INFO "" + X264_DEV="libx264-dev" + check_package_version_ge_DEB $X264_DEV $X264_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_DEB $X264_DEV + X264_USE=true + fi + + if $WITH_ALL; then + INFO "" + # Grmpf, debian is libxvidcore-dev and ubuntu libxvidcore4-dev! + XVID_DEV="libxvidcore-dev" + check_package_DEB $XVID_DEV + if [ $? -eq 0 ]; then + install_packages_DEB $XVID_DEV + XVID_USE=true + else + XVID_DEV="libxvidcore4-dev" + check_package_DEB $XVID_DEV + if [ $? -eq 0 ]; then + install_packages_DEB $XVID_DEV + XVID_USE=true + fi + fi + + INFO "" + MP3LAME_DEV="libmp3lame-dev" + check_package_DEB $MP3LAME_DEV + if [ $? -eq 0 ]; then + install_packages_DEB $MP3LAME_DEV + MP3LAME_USE=true + fi + + INFO "" + VPX_DEV="libvpx-dev" + check_package_version_ge_DEB $VPX_DEV $VPX_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_DEB $VPX_DEV + VPX_USE=true + fi + + INFO "" + check_package_DEB libspnav-dev + if [ $? -eq 0 ]; then + install_packages_DEB libspnav-dev + fi + fi + + INFO "" + if $PYTHON_SKIP; then + INFO "WARNING! Skipping Python installation, as requested..." + else + check_package_DEB python3.3-dev + if [ $? -eq 0 ]; then + install_packages_DEB python3.3-dev + else + compile_Python + fi + fi + + INFO "" + if $BOOST_SKIP; then + INFO "WARNING! Skipping Boost installation, as requested..." + else + check_package_version_ge_DEB libboost-dev $BOOST_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_DEB libboost-dev + + boost_version=$(echo `get_package_version_DEB libboost-dev` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/') + + check_package_DEB libboost-locale$boost_version-dev + if [ $? -eq 0 ]; then + install_packages_DEB libboost-locale$boost_version-dev libboost-filesystem$boost_version-dev \ + libboost-regex$boost_version-dev libboost-system$boost_version-dev \ + libboost-thread$boost_version-dev + else + compile_Boost + fi + else + compile_Boost + fi + fi + + INFO "" + if $OCIO_SKIP; then + INFO "WARNING! Skipping OpenColorIO installation, as requested..." + else + check_package_version_ge_DEB libopencolorio-dev $OCIO_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_DEB libopencolorio-dev + else + compile_OCIO + fi + fi + + INFO "" + if $OIIO_SKIP; then + INFO "WARNING! Skipping OpenImageIO installation, as requested..." + else + check_package_version_ge_DEB libopenimageio-dev $OIIO_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_DEB libopenimageio-dev + else + compile_OIIO + fi + fi + + if $WITH_OSL; then + have_llvm=false + + if $LLVM_SKIP; then + INFO "WARNING! Skipping LLVM installation, as requested (this also implies skipping OSL!)..." + else + INFO "" + check_package_DEB llvm-$LLVM_VERSION-dev + if [ $? -eq 0 ]; then + install_packages_DEB llvm-$LLVM_VERSION-dev + have_llvm=true + LLVM_VERSION_FOUND=$LLVM_VERSION + else + check_package_DEB llvm-$LLVM_VERSION_MIN-dev + if [ $? -eq 0 ]; then + install_packages_DEB llvm-$LLVM_VERSION_MIN-dev + have_llvm=true + LLVM_VERSION_FOUND=$LLVM_VERSION_MIN + else + install_packages_DEB libffi-dev + INFO "" + compile_LLVM + have_llvm=true + LLVM_VERSION_FOUND=$LLVM_VERSION + fi + fi + fi + + if $OSL_SKIP; then + INFO "" + INFO "WARNING! Skipping OpenShadingLanguage installation, as requested..." + else + if $have_llvm; then + INFO "" + install_packages_DEB clang flex bison libtbb-dev git + # No package currently! + INFO "" + compile_OSL + fi + fi + fi + + + INFO "" + if $FFMPEG_SKIP; then + INFO "WARNING! Skipping FFMpeg installation, as requested..." + else +# XXX Debian features libav packages as ffmpeg, those are not really compatible with blender code currently :/ +# So for now, always build our own ffmpeg. +# check_package_DEB ffmpeg +# if [ $? -eq 0 ]; then +# install_packages_DEB ffmpeg +# ffmpeg_version=`get_package_version_DEB ffmpeg` +# INFO "ffmpeg version: $ffmpeg_version" +# if [ ! -z "$ffmpeg_version" ]; then +# if dpkg --compare-versions $ffmpeg_version gt 0.7.2; then +# install_packages_DEB libavfilter-dev libavcodec-dev libavdevice-dev libavformat-dev libavutil-dev libswscale-dev +# else +# compile_FFmpeg +# fi +# fi +# fi + compile_FFmpeg + fi +} + +get_package_version_RPM() { + yum info $1 | grep Version | tail -n 1 | sed -r 's/.*:\s+(([0-9]+\.?)+).*/\1/' +} + +check_package_RPM() { + r=`yum info $1 | grep -c 'Summary'` + + if [ $r -ge 1 ]; then + return 0 + else + return 1 + fi +} + +check_package_version_match_RPM() { + v=`get_package_version_RPM $1` + + if [ -z "$v" ]; then + return 1 + fi + + version_match $v $2 + return $? +} + +check_package_version_ge_RPM() { + v=`get_package_version_RPM $1` + + if [ -z "$v" ]; then + return 1 + fi + + version_ge $v $2 + return $? +} + +install_packages_RPM() { + sudo yum install -y $@ + if [ $? -ge 1 ]; then + ERROR "yum failed to install requested packages, exiting." + exit 1 + fi +} + +install_RPM() { + INFO "" + INFO "Installing dependencies for RPM-based distribution" + INFO "" + INFO "`eval _echo "$COMMON_INFO"`" + INFO "" + + sudo yum -y update + + # These libs should always be available in debian/ubuntu official repository... + OPENJPEG_DEV="openjpeg-devel" + SCHRO_DEV="schroedinger-devel" + VORBIS_DEV="libvorbis-devel" + THEORA_DEV="libtheora-devel" + + _packages="gawk gcc gcc-c++ cmake scons libpng-devel libtiff-devel freetype-devel \ + libX11-devel libXi-devel wget libsqlite3x-devel ncurses-devel \ + readline-devel $OPENJPEG_DEV openexr-devel openal-soft-devel \ + glew-devel yasm $THEORA_DEV $VORBIS_DEV SDL-devel fftw-devel \ + lame-libs libjpeg-devel patch python-devel" + OPENJPEG_USE=true + VORBIS_USE=true + THEORA_USE=true + + if $WITH_ALL; then + _packages="$_packages $SCHRO_DEV jack-audio-connection-kit-devel libspnav-devel" + SCHRO_USE=true + fi + + INFO "" + install_packages_RPM $_packages + + INFO "" + X264_DEV="x264-devel" + check_package_version_ge_RPM $X264_DEV $X264_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_RPM $X264_DEV + X264_USE=true + fi + + if $WITH_ALL; then + INFO "" + XVID_DEV="xvidcore-devel" + check_package_RPM $XVID_DEV + if [ $? -eq 0 ]; then + install_packages_RPM $XVID_DEV + XVID_USE=true + fi + + INFO "" + VPX_DEV="libvpx-devel" + check_package_version_ge_RPM $VPX_DEV $VPX_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_RPM $VPX_DEV + VPX_USE=true + fi + + INFO "" + MP3LAME_DEV="lame-devel" + check_package_RPM $MP3LAME_DEV + if [ $? -eq 0 ]; then + install_packages_RPM $MP3LAME_DEV + MP3LAME_USE=true + fi + fi + + INFO "" + if $PYTHON_SKIP; then + INFO "WARNING! Skipping Python installation, as requested..." + else + check_package_version_match_RPM python3-devel $PYTHON_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_RPM python3-devel + else + compile_Python + fi + fi + + INFO "" + if $BOOST_SKIP; then + INFO "WARNING! Skipping Boost installation, as requested..." + else + check_package_version_ge_RPM boost-devel $BOOST_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_RPM boost-devel + else + compile_Boost + fi + fi + + INFO "" + if $OCIO_SKIP; then + INFO "WARNING! Skipping OpenColorIO installation, as requested..." + else + check_package_version_ge_RPM OpenColorIO-devel $OCIO_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_RPM OpenColorIO-devel + else + compile_OCIO + fi + fi + + INFO "" + if $OIIO_SKIP; then + INFO "WARNING! Skipping OpenImageIO installation, as requested..." + else + check_package_version_ge_RPM OpenImageIO-devel $OIIO_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_RPM OpenImageIO-devel + else + compile_OIIO + fi + fi + + if $WITH_OSL; then + have_llvm=false + + INFO "" + if $LLVM_SKIP; then + INFO "WARNING! Skipping LLVM installation, as requested (this also implies skipping OSL!)..." + else + check_package_RPM llvm-$LLVM_VERSION-devel + if [ $? -eq 0 ]; then + install_packages_RPM llvm-$LLVM_VERSION-devel + have_llvm=true + LLVM_VERSION_FOUND=$LLVM_VERSION + else +# check_package_RPM llvm-$LLVM_VERSION_MIN-devel +# if [ $? -eq 0 ]; then +# install_packages_RPM llvm-$LLVM_VERSION_MIN-devel +# have_llvm=true +# LLVM_VERSION_FOUND=$LLVM_VERSION_MIN +# else +# check_package_version_ge_RPM llvm-devel $LLVM_VERSION_MIN +# if [ $? -eq 0 ]; then +# install_packages_RPM llvm-devel +# have_llvm=true +# LLVM_VERSION_FOUND=`get_package_version_RPM llvm-devel` +# fi +# fi + install_packages_RPM libffi-devel + # XXX Stupid fedora puts ffi header into a darn stupid dir! + _FFI_INCLUDE_DIR=`rpm -ql libffi-devel | grep -e ".*/ffi.h" | sed -r 's/(.*)\/ffi.h/\1/'` + INFO "" + compile_LLVM + have_llvm=true + LLVM_VERSION_FOUND=$LLVM_VERSION + fi + fi + + if $OSL_SKIP; then + INFO "" + INFO "WARNING! Skipping OpenShadingLanguage installation, as requested..." + else + if $have_llvm; then + INFO "" + install_packages_RPM flex bison clang tbb-devel git + # No package currently! + INFO "" + compile_OSL + fi + fi + fi + + INFO "" + if $FFMPEG_SKIP; then + INFO "WARNING! Skipping FFMpeg installation, as requested..." + else + # Always for now, not sure which packages should be installed + compile_FFmpeg + fi +} + +get_package_version_SUSE() { + zypper info $1 | grep Version | tail -n 1 | sed -r 's/.*:\s+(([0-9]+\.?)+).*/\1/' +} + +check_package_SUSE() { + r=`zypper info $1 | grep -c 'Summary'` + + if [ $r -ge 1 ]; then + return 0 + else + return 1 + fi +} + +check_package_version_match_SUSE() { + v=`get_package_version_SUSE $1` + + if [ -z "$v" ]; then + return 1 + fi + + version_match $v $2 + return $? +} + +check_package_version_ge_SUSE() { + v=`get_package_version_SUSE $1` + + if [ -z "$v" ]; then + return 1 + fi + + version_ge $v $2 + return $? +} + +install_packages_SUSE() { + sudo zypper --non-interactive install --auto-agree-with-licenses $@ + if [ $? -ge 1 ]; then + ERROR "zypper failed to install requested packages, exiting." + exit 1 + fi +} + + +install_SUSE() { + INFO "" + INFO "Installing dependencies for SuSE-based distribution" + INFO "" + INFO "`eval _echo "$COMMON_INFO"`" + INFO "" + + sudo zypper --non-interactive update --auto-agree-with-licenses + + # These libs should always be available in debian/ubuntu official repository... + OPENJPEG_DEV="openjpeg-devel" + SCHRO_DEV="schroedinger-devel" + VORBIS_DEV="libvorbis-devel" + THEORA_DEV="libtheora-devel" + + _packages="gawk gcc gcc-c++ cmake scons libpng12-devel libtiff-devel freetype-devel \ + libX11-devel libXi-devel wget sqlite3-devel ncurses-devel \ + readline-devel $OPENJPEG_DEV libopenexr-devel openal-soft-devel \ + glew-devel yasm $THEORA_DEV $VORBIS_DEV libSDL-devel fftw3-devel \ + libjpeg62-devel patch python-devel" + OPENJPEG_USE=true + VORBIS_USE=true + THEORA_USE=true + + if $WITH_ALL; then + _packages="$_packages $SCHRO_DEV libjack-devel libspnav-devel" + SCHRO_USE=true + fi + + INFO "" + install_packages_SUSE $_packages + + OPENJPEG_USE=true + SCHRO_USE=true + VORBIS_USE=true + THEORA_USE=true + + INFO "" + X264_DEV="x264-devel" + check_package_version_ge_SUSE $X264_DEV $X264_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_SUSE $X264_DEV + X264_USE=true + fi + + if $WITH_ALL; then + INFO "" + XVID_DEV="xvidcore-devel" + check_package_SUSE $XVID_DEV + if [ $? -eq 0 ]; then + install_packages_SUSE $XVID_DEV + XVID_USE=true + fi + + INFO "" + VPX_DEV="libvpx-devel" + check_package_version_ge_SUSE $VPX_DEV $VPX_VERSION_MIN + if [ $? -eq 0 ]; then + install_packages_SUSE $VPX_DEV + VPX_USE=true + fi + + INFO "" + # No mp3 in suse, it seems. + MP3LAME_DEV="lame-devel" + check_package_SUSE $MP3LAME_DEV + if [ $? -eq 0 ]; then + install_packages_SUSE $MP3LAME_DEV + MP3LAME_USE=true + fi + fi + + INFO "" + if $PYTHON_SKIP; then + INFO "WARNING! Skipping Python installation, as requested..." + else + check_package_version_match_SUSE python3-devel 3.3. + if [ $? -eq 0 ]; then + install_packages_SUSE python3-devel + else + compile_Python + fi + fi + + INFO "" + if $BOOST_SKIP; then + INFO "WARNING! Skipping Boost installation, as requested..." + else + # No boost_locale currently available, so let's build own boost. + compile_Boost + fi + + INFO "" + if $OCIO_SKIP; then + INFO "WARNING! Skipping OpenColorIO installation, as requested..." + else + # No ocio currently available, so let's build own boost. + compile_OCIO + fi + + INFO "" + if $OIIO_SKIP; then + INFO "WARNING! Skipping OpenImageIO installation, as requested..." + else + # No oiio currently available, so let's build own boost. + compile_OIIO + fi + + if $WITH_OSL; then + have_llvm=false + + INFO "" + if $LLVM_SKIP; then + INFO "WARNING! Skipping LLVM installation, as requested (this also implies skipping OSL!)..." + else + # Suse llvm package *_$SUCKS$_* (tm) !!! +# check_package_version_ge_SUSE llvm-devel $LLVM_VERSION_MIN +# if [ $? -eq 0 ]; then +# install_packages_SUSE llvm-devel +# have_llvm=true +# LLVM_VERSION_FOUND=`get_package_version_SUSE llvm-devel` +# fi + + install_packages_SUSE libffi47-devel + INFO "" + compile_LLVM + have_llvm=true + LLVM_VERSION_FOUND=$LLVM_VERSION + fi + + if $OSL_SKIP; then + INFO "" + INFO "WARNING! Skipping OpenShaderLanguage installation, as requested..." + else + if $have_llvm; then + INFO "" + # XXX No tbb lib! + install_packages_SUSE flex bison git + # No package currently! + INFO "" + compile_OSL + fi + fi + fi + + INFO "" + if $FFMPEG_SKIP; then + INFO "WARNING! Skipping FFMpeg installation, as requested..." + else + # No ffmpeg currently available, so let's build own boost. + compile_FFmpeg + fi +} + +print_info_ffmpeglink_DEB() { + if $ALL_STATIC; then + dpkg -L $_packages | grep -e ".*\/lib[^\/]\+\.a" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", $0); nlines++ }' + else + dpkg -L $_packages | grep -e ".*\/lib[^\/]\+\.so" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", "g", $0)); nlines++ }' + fi +} + +print_info_ffmpeglink_RPM() { + if $ALL_STATIC; then + rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.a" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", $0); nlines++ }' + else + rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.so" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", "g", $0)); nlines++ }' + fi +} + +print_info_ffmpeglink_SUSE() { + if $ALL_STATIC; then + rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.a" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", $0); nlines++ }' + else + rpm -ql $_packages | grep -e ".*\/lib[^\/]\+\.so" | gawk '{ printf(nlines ? "'"$_ffmpeg_list_sep"'%s" : "%s", gensub(/.*lib([^\/]+)\.so/, "\\1", "g", $0)); nlines++ }' + fi +} + +print_info_ffmpeglink() { + # This func must only print a ';'-separated list of libs... + if [ -z "$DISTRO" ]; then + ERROR "Failed to detect distribution type" + exit 1 + fi + + # Create list of packages from which to get libs names... + _packages="" + + if $THEORA_USE; then + _packages="$_packages $THEORA_DEV" + fi + + if $VORBIS_USE; then + _packages="$_packages $VORBIS_DEV" + fi + + if $XVID_USE; then + _packages="$_packages $XVID_DEV" + fi + + if $VPX_USE; then + _packages="$_packages $VPX_DEV" + fi + + if $MP3LAME_USE; then + _packages="$_packages $MP3LAME_DEV" + fi + + if $X264_USE; then + _packages="$_packages $X264_DEV" + fi + + if $OPENJPEG_USE; then + _packages="$_packages $OPENJPEG_DEV" + fi + + # XXX At least under Debian, static schro gives problem at blender linking time... :/ + if $SCHRO_USE && ! $ALL_STATIC; then + _packages="$_packages $SCHRO_DEV" + fi + + if [ "$DISTRO" = "DEB" ]; then + print_info_ffmpeglink_DEB + elif [ "$DISTRO" = "RPM" ]; then + print_info_ffmpeglink_RPM + elif [ "$DISTRO" = "SUSE" ]; then + print_info_ffmpeglink_SUSE + # XXX TODO! + else INFO "" + fi +} + +print_info() { + INFO "" + INFO "If you're using CMake add this to your configuration flags:" + + if $ALL_STATIC; then + INFO " -D WITH_STATIC_LIBS=ON" + fi + + if [ -d $INST/boost ]; then + INFO " -D BOOST_ROOT=$INST/boost" + INFO " -D Boost_NO_SYSTEM_PATHS=ON" + elif $ALL_STATIC; then + INFO " -D Boost_USE_ICU=ON" + fi + + if [ -d $INST/osl -a $WITH_OSL == true ]; then + INFO " -D CYCLES_OSL=$INST/osl" + INFO " -D WITH_CYCLES_OSL=ON" + INFO " -D LLVM_VERSION=$LLVM_VERSION_FOUND" + if [ -d $INST/llvm ]; then + INFO " -D LLVM_DIRECTORY=$INST/llvm" + INFO " -D LLVM_STATIC=ON" + fi + fi + + if [ -d $INST/ffmpeg ]; then + INFO " -D WITH_CODEC_FFMPEG=ON" + INFO " -D FFMPEG=$INST/ffmpeg" + INFO " -D FFMPEG_LIBRARIES='avformat;avcodec;avutil;avdevice;swscale;rt;`print_info_ffmpeglink`'" + fi + + INFO "" + INFO "If you're using SCons add this to your user-config:" + + if [ -d $INST/python-3.3 ]; then + INFO "BF_PYTHON = '$INST/python-3.3'" + INFO "BF_PYTHON_ABI_FLAGS = 'm'" + fi + + if [ -d $INST/ocio ]; then + INFO "BF_OCIO = '$INST/ocio'" + fi + + if [ -d $INST/oiio ]; then + INFO "BF_OIIO = '$INST/oiio'" + fi + + if [ -d $INST/boost ]; then + INFO "BF_BOOST = '$INST/boost'" + fi + + if [ -d $INST/ffmpeg ]; then + INFO "BF_FFMPEG = '$INST/ffmpeg'" + _ffmpeg_list_sep=" " + INFO "BF_FFMPEG_LIB = 'avformat avcodec swscale avutil avdevice `print_info_ffmpeglink`'" + fi + + INFO "" + INFO "" + INFO "WARNING: If this script had to build boost into $INST, and you are dynamically linking " + INFO " blender against it, you will have to run those commands as root user:" + INFO "" + INFO " echo \"$INST/boost/lib\" > /etc/ld.so.conf.d/boost.conf" + INFO " ldconfig" + INFO "" +} + +# Detect distributive type used on this machine +detect_distro + +if [ -z "$DISTRO" ]; then + ERROR "Failed to detect distribution type" + exit 1 +elif [ "$DISTRO" = "DEB" ]; then + install_DEB +elif [ "$DISTRO" = "RPM" ]; then + install_RPM +elif [ "$DISTRO" = "SUSE" ]; then + install_SUSE +fi + +print_info + +# Switch back to user language. +LANG=LANG_BACK +export LANG diff --git a/build_files/build_environment/prepare_release_env.sh b/build_files/build_environment/prepare_release_env.sh index b16ce784be9..9889feadcd2 100755 --- a/build_files/build_environment/prepare_release_env.sh +++ b/build_files/build_environment/prepare_release_env.sh @@ -88,6 +88,9 @@ OIIO_V="1.0.9" OCIO_V="1.0.7" MESA_V="8.0.5" +OPENSSL_V="0.9.8o" +OPENSSL_FV="0.9.8o-4squeeze13" + CUDA_V="4.2.9" CUDA_DISTR="ubuntu10.04" CUDA_32="cudatoolkit_${CUDA_V}_linux_32_${CUDA_DISTR}.run" @@ -611,6 +614,15 @@ INSTALL_SOURCES() { -P "$SOURCES_PATH/backport/gcc-4.7" fi + if [ ! -d "$SOURCES_PATH/backport/openssl" ]; then + INFO "Downloading openssl" + mkdir -p "$SOURCES_PATH/backport/openssl" + wget -c $DEBIAN_MIRROR/pool/main/o/openssl/openssl_$OPENSSL_FV.debian.tar.gz \ + $DEBIAN_MIRROR/pool/main/o/openssl/openssl_$OPENSSL_FV.dsc \ + $DEBIAN_MIRROR/pool/main/o/openssl/openssl_$OPENSSL_V.orig.tar.gz \ + -P "$SOURCES_PATH/backport/openssl" + fi + # JeMalloc J="$SOURCES_PATH/packages/jemalloc-$JEMALLOC_V" if [ ! -d "$J" ]; then @@ -731,7 +743,6 @@ EOF chmod +x "$P/0config.sh" fi - # OpenImageIO O="$SOURCES_PATH/packages/OpenImageIO-$OIIO_V" if [ ! -d "$O" ]; then @@ -1075,6 +1086,64 @@ DO_BACKPORT() { INFO "Cleaning gcc-4.7" $RUN sh -c "cd '$G' && fakeroot debian/rules clean" fi + + # Backport OpenSSL + if [ ! -f $CHROOT_PATH/usr/lib/libssl_pic.a ]; then + INFO "Backporting OpenSSL" + O="$P/openssl/openssl-$OPENSSL_V" + + pkg="libssl-dev_0.9.8o-4squeeze13_amd64.deb libssl0.9.8_0.9.8o-4squeeze13_amd64.deb openssl_0.9.8o-4squeeze13_amd64.deb" + + if [ ! -d "$CHROOT_PATH/$O" ]; then + INFO "Unpacking OpenSSL" + $RUN dpkg-source -x "$P/openssl/openssl_$OPENSSL_FV.dsc" "$O" + fi + + if [ "$CHROOT_ARCH" = "i386" ]; then + pkg=`echo "$pkg" | sed -r 's/amd64/i386/g'` + fi + + ok=true + for x in `echo "$pkg"`; do + if [ ! -f "$CHROOT_PATH/$P/openssl/$x" ]; then + ok=false + break; + fi + done + + if ! $ok; then + INFO "Compiling OpenSSL" + sed -ie 's/#\s*mv debian\/tmp\/usr\/lib\/libcrypto.a debian\/tmp\/usr\/lib\/libcrypto_pic.a/ mv debian\/tmp\/usr\/lib\/libcrypto.a debian\/tmp\/usr\/lib\/libcrypto_pic.a/' "$CHROOT_PATH/$O/debian/rules" + sed -ie 's/#\s*mv debian\/tmp\/usr\/lib\/libssl.a debian\/tmp\/usr\/lib\/libssl_pic.a/ mv debian\/tmp\/usr\/lib\/libssl.a debian\/tmp\/usr\/lib\/libssl_pic.a/' "$CHROOT_PATH/$O/debian/rules" + cat << EOF > $CHROOT_PATH/$O/debian/libssl-dev.files +usr/lib/libssl.so +usr/lib/libcrypto.so +usr/lib/libssl.a +usr/lib/libcrypto.a +usr/lib/libssl_pic.a +usr/lib/libcrypto_pic.a +usr/lib/pkgconfig +usr/include +usr/share/man/man3 +EOF + $RUN sh -c "cd '$O' && dpkg-buildpackage -rfakeroot -j$THREADS" + fi + + inst="" + for x in `echo "$pkg"`; do + inst="$inst $P/openssl/$x" + done + + INFO "Installing OpenSSL" + $RUN dpkg -i $inst + + echo "openssl hold" | $RUN dpkg --set-selections + echo "libssl-dev hold" | $RUN dpkg --set-selections + echo "libssl0.9.8 hold" | $RUN dpkg --set-selections + + INFO "Cleaning OpenSSL" + $RUN sh -c "cd '$O' && fakeroot debian/rules clean" + fi } DO_COMPILE() { @@ -1161,6 +1230,8 @@ _sha256 sha256module.c _sha512 sha512module.c EOF + sed -ie "s/libraries = \['ssl', 'crypto'\]/libraries = ['ssl_pic', 'crypto_pic', 'z']/" "$P/Python-$PYTHON_V/setup.py" + $RUN sh -c "cd '$P/Python-$PYTHON_V' && ./0config.sh && make clean && make -j$THREADS && make install && make clean" rm -f "$L/python-$PYTHIN_V_SHORT" @@ -1356,6 +1427,7 @@ EOF fi INFO "Installing packages from repository" + $RUN apt-get install -y mc gcc g++ cmake python dpkg-dev build-essential autoconf bison \ flex gettext texinfo dejagnu quilt file lsb-release zlib1g-dev fakeroot debhelper \ g++-multilib libtool autoconf2.64 automake gawk lzma patchutils gperf sharutils \ @@ -1366,7 +1438,7 @@ EOF libsqlite3-dev liblzma-dev libncurses5-dev xutils-dev libxext-dev python-libxml2 \ libglu1-mesa-dev libfftw3-dev libfreetype6-dev libsdl1.2-dev libopenal-dev libjack-dev \ libxi-dev portaudio19-dev po4a subversion scons libpcre3-dev libexpat1-dev sudo \ - expect + expect bc if [ $CHROOT_ARCH = "amd64" ]; then $RUN apt-get install -y libc6-dev-i386 lib32gcc1 diff --git a/build_files/buildbot/config/user-config-glibc211-i686.py b/build_files/buildbot/config/user-config-glibc211-i686.py index 23ab87a6ba3..e665657d91e 100644 --- a/build_files/buildbot/config/user-config-glibc211-i686.py +++ b/build_files/buildbot/config/user-config-glibc211-i686.py @@ -110,8 +110,7 @@ BF_JACK_LIB_STATIC = '${BF_ZLIB}/lib/libjack.a' # Cycles WITH_BF_CYCLES = True WITH_BF_CYCLES_CUDA_BINARIES = True -#BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30'] -BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30'] +BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30'] WITH_BF_OIIO = True WITH_BF_STATICOIIO = True @@ -120,6 +119,24 @@ BF_OIIO_INC = '${BF_OIIO}/include' BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_JPEG}/lib/libjpeg.a' BF_OIIO_LIBPATH = '${BF_OIIO}/lib' +WITH_BF_CYCLES_OSL = True +WITH_BF_STATICOSL = False +BF_OSL = '/opt/lib/osl' +BF_OSL_INC = '${BF_OSL}/include' +# note oslexec would passed via program linkflags, which is needed to +# make llvm happy with osl_allocate_closure_component +BF_OSL_LIB = 'oslcomp oslexec oslquery' +BF_OSL_LIBPATH = '${BF_OSL}/lib' +BF_OSL_COMPILER = '${BF_OSL}/bin/oslc' + +WITH_BF_LLVM = True +WITH_BF_STATICLLVM = False +BF_LLVM = '/opt/lib/llvm-3.1' +BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \ + 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \ + 'LLVMTarget LLVMMC LLVMCore LLVMSupport' +BF_LLVM_LIBPATH = '${BF_LLVM}/lib' + # Color management WITH_BF_OCIO = True WITH_BF_STATICOCIO = True @@ -133,7 +150,8 @@ WITH_BF_STATICBOOST = True BF_BOOST = '/opt/lib/boost' BF_BOOST_INC = '${BF_BOOST}/include' BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \ - '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' + '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a \ + ${BF_BOOST_LIBPATH}/libboost_thread.a' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' # Ocean Simulation @@ -141,5 +159,6 @@ WITH_BF_OCEANSIM = True # Compilation and optimization BF_DEBUG = False -REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++ +REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++ PLATFORM_LINKFLAGS = ['-lrt'] +BF_PROGRAM_LINKFLAGS = ['-Wl,--whole-archive', '-loslexec', '-Wl,--no-whole-archive', '-Wl,--version-script=source/creator/blender.map'] diff --git a/build_files/buildbot/config/user-config-glibc211-x86_64.py b/build_files/buildbot/config/user-config-glibc211-x86_64.py index 84899cc3848..420d9ed4db9 100644 --- a/build_files/buildbot/config/user-config-glibc211-x86_64.py +++ b/build_files/buildbot/config/user-config-glibc211-x86_64.py @@ -119,6 +119,24 @@ BF_OIIO_INC = '${BF_OIIO}/include' BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_JPEG}/lib/libjpeg.a' BF_OIIO_LIBPATH = '${BF_OIIO}/lib' +WITH_BF_CYCLES_OSL = True +WITH_BF_STATICOSL = False +BF_OSL = '/opt/lib/osl' +BF_OSL_INC = '${BF_OSL}/include' +# note oslexec would passed via program linkflags, which is needed to +# make llvm happy with osl_allocate_closure_component +BF_OSL_LIB = 'oslcomp oslexec oslquery' +BF_OSL_LIBPATH = '${BF_OSL}/lib' +BF_OSL_COMPILER = '${BF_OSL}/bin/oslc' + +WITH_BF_LLVM = True +WITH_BF_STATICLLVM = False +BF_LLVM = '/opt/lib/llvm-3.1' +BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \ + 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \ + 'LLVMTarget LLVMMC LLVMCore LLVMSupport' +BF_LLVM_LIBPATH = '${BF_LLVM}/lib' + # Color management WITH_BF_OCIO = True WITH_BF_STATICOCIO = True @@ -132,7 +150,8 @@ WITH_BF_STATICBOOST = True BF_BOOST = '/opt/lib/boost' BF_BOOST_INC = '${BF_BOOST}/include' BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \ - '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' + '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a \ + ${BF_BOOST_LIBPATH}/libboost_thread.a' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' # Ocean Simulation @@ -140,5 +159,6 @@ WITH_BF_OCEANSIM = True # Compilation and optimization BF_DEBUG = False -REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++ +REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++ PLATFORM_LINKFLAGS = ['-lrt'] +BF_PROGRAM_LINKFLAGS = ['-Wl,--whole-archive', '-loslexec', '-Wl,--no-whole-archive', '-Wl,--version-script=source/creator/blender.map'] diff --git a/build_files/buildbot/config/user-config-glibc27-i686.py b/build_files/buildbot/config/user-config-glibc27-i686.py index c1e72662f89..b36196fd835 100644 --- a/build_files/buildbot/config/user-config-glibc27-i686.py +++ b/build_files/buildbot/config/user-config-glibc27-i686.py @@ -97,8 +97,7 @@ WITH_BF_JACK = True # Cycles WITH_BF_CYCLES = True WITH_BF_CYCLES_CUDA_BINARIES = True -#BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30'] -BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30'] +BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30'] WITH_BF_OIIO = True WITH_BF_STATICOIIO = True @@ -107,6 +106,24 @@ BF_OIIO_INC = '${BF_OIIO}/include' BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a' BF_OIIO_LIBPATH = '${BF_OIIO}/lib' +WITH_BF_CYCLES_OSL = True +WITH_BF_STATICOSL = False +BF_OSL = '/opt/osl' +BF_OSL_INC = '${BF_OSL}/include' +# note oslexec would passed via program linkflags, which is needed to +# make llvm happy with osl_allocate_closure_component +BF_OSL_LIB = 'oslcomp oslexec oslquery' +BF_OSL_LIBPATH = '${BF_OSL}/lib' +BF_OSL_COMPILER = '${BF_OSL}/bin/oslc' + +WITH_BF_LLVM = True +WITH_BF_STATICLLVM = False +BF_LLVM = '/opt/llvm-3.1' +BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \ + 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \ + 'LLVMTarget LLVMMC LLVMCore LLVMSupport' +BF_LLVM_LIBPATH = '${BF_LLVM}/lib' + # Color management WITH_BF_OCIO = True WITH_BF_STATICOCIO = True @@ -119,7 +136,7 @@ WITH_BF_BOOST = True WITH_BF_STATICBOOST = True BF_BOOST = '/opt/boost' BF_BOOST_INC = '${BF_BOOST}/include' -BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' +BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' # Ocean Simulation @@ -127,5 +144,6 @@ WITH_BF_OCEANSIM = True # Compilation and optimization BF_DEBUG = False -REL_CCFLAGS = ['-O2'] # C & C++ +REL_CCFLAGS = ['-DNDEBUG', '-DNDEBUG', '-O2'] # C & C++ PLATFORM_LINKFLAGS = ['-L/home/sources/staticlibs/lib32'] +BF_PROGRAM_LINKFLAGS = ['-Wl,--whole-archive', '-loslexec', '-Wl,--no-whole-archive', '-Wl,--version-script=source/creator/blender.map'] diff --git a/build_files/buildbot/config/user-config-glibc27-x86_64.py b/build_files/buildbot/config/user-config-glibc27-x86_64.py index 4380b404ac3..7359e155586 100644 --- a/build_files/buildbot/config/user-config-glibc27-x86_64.py +++ b/build_files/buildbot/config/user-config-glibc27-x86_64.py @@ -106,6 +106,24 @@ BF_OIIO_INC = '${BF_OIIO}/include' BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a' BF_OIIO_LIBPATH = '${BF_OIIO}/lib' +WITH_BF_CYCLES_OSL = True +WITH_BF_STATICOSL = False +BF_OSL = '/opt/osl' +BF_OSL_INC = '${BF_OSL}/include' +# note oslexec would passed via program linkflags, which is needed to +# make llvm happy with osl_allocate_closure_component +BF_OSL_LIB = 'oslcomp oslexec oslquery' +BF_OSL_LIBPATH = '${BF_OSL}/lib' +BF_OSL_COMPILER = '${BF_OSL}/bin/oslc' + +WITH_BF_LLVM = True +WITH_BF_STATICLLVM = False +BF_LLVM = '/opt/llvm-3.1' +BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \ + 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \ + 'LLVMTarget LLVMMC LLVMCore LLVMSupport' +BF_LLVM_LIBPATH = '${BF_LLVM}/lib' + # Color management WITH_BF_OCIO = True WITH_BF_STATICOCIO = True @@ -118,7 +136,7 @@ WITH_BF_BOOST = True WITH_BF_STATICBOOST = True BF_BOOST = '/opt/boost' BF_BOOST_INC = '${BF_BOOST}/include' -BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' +BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' # Ocean Simulation @@ -126,5 +144,6 @@ WITH_BF_OCEANSIM = True # Compilation and optimization BF_DEBUG = False -REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++ +REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++ PLATFORM_LINKFLAGS = ['-L/home/sources/staticlibs/lib64'] +BF_PROGRAM_LINKFLAGS = ['-Wl,--whole-archive', '-loslexec', '-Wl,--no-whole-archive', '-Wl,--version-script=source/creator/blender.map'] diff --git a/build_files/buildbot/config/user-config-player-glibc211-i686.py b/build_files/buildbot/config/user-config-player-glibc211-i686.py index 1b387445390..96f201235c4 100644 --- a/build_files/buildbot/config/user-config-player-glibc211-i686.py +++ b/build_files/buildbot/config/user-config-player-glibc211-i686.py @@ -98,7 +98,8 @@ WITH_BF_STATICBOOST = True BF_BOOST = '/opt/lib/boost' BF_BOOST_INC = '${BF_BOOST}/include' BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \ - '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' + '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a \ + ${BF_BOOST_LIBPATH}/libboost_thread.a' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' # JACK @@ -116,5 +117,5 @@ WITH_BF_OCEANSIM = True # Compilation and optimization BF_DEBUG = False -REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++ +REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++ PLATFORM_LINKFLAGS = ['-lrt'] diff --git a/build_files/buildbot/config/user-config-player-glibc211-x86_64.py b/build_files/buildbot/config/user-config-player-glibc211-x86_64.py index 83540150c33..75979d0bcfe 100644 --- a/build_files/buildbot/config/user-config-player-glibc211-x86_64.py +++ b/build_files/buildbot/config/user-config-player-glibc211-x86_64.py @@ -98,7 +98,8 @@ WITH_BF_STATICBOOST = True BF_BOOST = '/opt/lib/boost' BF_BOOST_INC = '${BF_BOOST}/include' BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \ - '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' + '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a \ + ${BF_BOOST_LIBPATH}/libboost_thread.a' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' # JACK @@ -116,5 +117,5 @@ WITH_BF_OCEANSIM = True # Compilation and optimization BF_DEBUG = False -REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++ +REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++ PLATFORM_LINKFLAGS = ['-lrt'] diff --git a/build_files/buildbot/config/user-config-player-glibc27-i686.py b/build_files/buildbot/config/user-config-player-glibc27-i686.py index e200e0fccf4..82b105c4527 100644 --- a/build_files/buildbot/config/user-config-player-glibc27-i686.py +++ b/build_files/buildbot/config/user-config-player-glibc27-i686.py @@ -94,7 +94,7 @@ WITH_BF_BOOST = True WITH_BF_STATICBOOST = True BF_BOOST = '/opt/boost' BF_BOOST_INC = '${BF_BOOST}/include' -BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' +BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' # JACK @@ -110,5 +110,5 @@ WITH_BF_OCEANSIM = True # Compilation and optimization BF_DEBUG = False -REL_CCFLAGS = ['-O2'] # C & C++ +REL_CCFLAGS = ['-DNDEBUG', '-O2'] # C & C++ PLATFORM_LINKFLAGS = ['-L/home/sources/staticlibs/lib32'] diff --git a/build_files/buildbot/config/user-config-player-glibc27-x86_64.py b/build_files/buildbot/config/user-config-player-glibc27-x86_64.py index 2ee177960cd..1e6aa4af802 100644 --- a/build_files/buildbot/config/user-config-player-glibc27-x86_64.py +++ b/build_files/buildbot/config/user-config-player-glibc27-x86_64.py @@ -94,7 +94,7 @@ WITH_BF_BOOST = True WITH_BF_STATICBOOST = True BF_BOOST = '/opt/boost' BF_BOOST_INC = '${BF_BOOST}/include' -BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' +BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_locale.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' # JACK @@ -110,5 +110,5 @@ WITH_BF_OCEANSIM = True # Compilation and optimization BF_DEBUG = False -REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++ +REL_CCFLAGS = ['-DNDEBUG', '-O2', '-msse', '-msse2'] # C & C++ PLATFORM_LINKFLAGS = ['-L/home/sources/staticlibs/lib64'] diff --git a/build_files/buildbot/master.cfg b/build_files/buildbot/master.cfg index e9deade6e99..90f0c805f58 100644 --- a/build_files/buildbot/master.cfg +++ b/build_files/buildbot/master.cfg @@ -77,17 +77,18 @@ def svn_step(branch=''): def lib_svn_step(dir): return SVN(name='lib svn', baseURL='https://svn.blender.org/svnroot/bf-blender/%%BRANCH%%/lib/' + dir, mode='update', defaultBranch='trunk', workdir='lib/' + dir) -def rsync_step(file_from, file_to): - return ShellCommand(name='rsync', command=['rsync', '-v', '-P', file_from, 'brecht@builder.blender.org:/data/buildbot-master/' + file_to], haltOnFailure=True, description=['rsync']) +def rsync_step(id, branch, rsync_script): + return ShellCommand(name='rsync', command=['python', rsync_script, id, branch], description='uploading', descriptionDone='uploaded', workdir='install') # generic builder def generic_builder(id, libdir='', branch='', rsync=False): - filename = 'buildbot_upload_' + id + '.zip' + filename = 'uploaded/buildbot_upload_' + id + '.zip' compile_script = '../blender/build_files/buildbot/slave_compile.py' test_script = '../blender/build_files/buildbot/slave_test.py' pack_script = '../blender/build_files/buildbot/slave_pack.py' + rsync_script = '../blender/build_files/buildbot/slave_rsync.py' unpack_script = 'master_unpack.py' f = BuildFactory() @@ -95,11 +96,11 @@ def generic_builder(id, libdir='', branch='', rsync=False): if libdir != '': f.addStep(lib_svn_step(libdir)) - f.addStep(Compile(command=['python', compile_script, id])) + f.addStep(Compile(command=['python', compile_script, id], timeout=3600)) f.addStep(Test(command=['python', test_script, id])) f.addStep(ShellCommand(name='package', command=['python', pack_script, id, branch], description='packaging', descriptionDone='packaged')) if rsync: - f.addStep(rsync_step('../install/buildbot_upload.zip', filename)) + f.addStep(rsync_step(id, branch, rsync_script)) elif id.find('cmake') != -1: f.addStep(FileUpload(name='upload', slavesrc='buildbot_upload.zip', masterdest=filename, maxsize=100 * 1024 * 1024)) else: @@ -109,7 +110,8 @@ def generic_builder(id, libdir='', branch='', rsync=False): # builders -add_builder(c, 'mac_x86_64_scons', '', generic_builder) +add_builder(c, 'mac_x86_64_10_6_scons', 'darwin-9.x.universal', generic_builder, '', True) +add_builder(c, 'mac_x86_64_10_5_scons', '', generic_builder, '', True) #add_builder(c, 'salad_mac_x86_64_scons', 'darwin-9.x.universal', generic_builder, 'soc-2011-salad') add_builder(c, 'mac_i386_scons', 'darwin-9.x.universal', generic_builder) add_builder(c, 'mac_ppc_scons', 'darwin-9.x.universal', generic_builder) diff --git a/build_files/buildbot/slave_rsync.py b/build_files/buildbot/slave_rsync.py new file mode 100644 index 00000000000..aea1b65e333 --- /dev/null +++ b/build_files/buildbot/slave_rsync.py @@ -0,0 +1,45 @@ +# ##### 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. +# +# ##### END GPL LICENSE BLOCK ##### + +# + +# Runs on buildbot slave, rsync zip directly to buildbot server rather +# than using upload which is much slower + +import os +import sys + +# get builder name +if len(sys.argv) < 2: + sys.stderr.write("Not enough arguments, expecting builder name\n") + sys.exit(1) + +builder = sys.argv[1] + +# rsync, this assumes ssh keys are setup so no password is needed +local_zip = "buildbot_upload.zip" +remote_folder = "builder.blender.org:/data/buildbot-master/uploaded/" +remote_zip = remote_folder + "buildbot_upload_" + builder + ".zip" +command = "rsync -avz %s %s" % (local_zip, remote_zip) + +print(command) + +ret = os.system(command) +sys.exit(ret) + + diff --git a/build_files/cmake/Modules/FindIcuLinux.cmake b/build_files/cmake/Modules/FindIcuLinux.cmake new file mode 100644 index 00000000000..e0e5873a4eb --- /dev/null +++ b/build_files/cmake/Modules/FindIcuLinux.cmake @@ -0,0 +1,146 @@ +# - Find static icu libraries +# Find the native static icu libraries (needed for static boost_locale :/ ). +# This module defines +# ICU_LIBRARIES, libraries to link against to use icu. +# ICU_ROOT_DIR, The base directory to search for icu. +# This can also be an environment variable. +# ICU_FOUND, If false, do not try to use icu. +# +# also defined, but not for general use are +# ICU_LIBRARY_xxx, where to find the icu libraries. + +#============================================================================= +# Copyright 2012 Blender Foundation. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= + +# If ICU_ROOT_DIR was defined in the environment, use it. +IF(NOT ICU_ROOT_DIR AND NOT $ENV{ICU_ROOT_DIR} STREQUAL "") + SET(ICU_ROOT_DIR $ENV{ICU_ROOT_DIR}) +ENDIF() + +if(Boost_USE_STATIC_LIBS) + set(_icu_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + set(CMAKE_FIND_LIBRARY_SUFFIXES .a) +endif() + +SET(_icu_SEARCH_DIRS + ${ICU_ROOT_DIR} + /usr/local + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave +) + +# We don't need includes, only libs to link against... +#FIND_PATH(ICU_INCLUDE_DIR +# NAMES +# utf.h +# HINTS +# ${_icu_SEARCH_DIRS} +# PATH_SUFFIXES +# include/unicode +#) + +FIND_LIBRARY(ICU_LIBRARY_DATA + NAMES + icudata + HINTS + ${_icu_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + +FIND_LIBRARY(ICU_LIBRARY_I18N + NAMES + icui18n + HINTS + ${_icu_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + +FIND_LIBRARY(ICU_LIBRARY_IO + NAMES + icuio + HINTS + ${_icu_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + +FIND_LIBRARY(ICU_LIBRARY_LE + NAMES + icule + HINTS + ${_icu_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + +FIND_LIBRARY(ICU_LIBRARY_LX + NAMES + iculx + HINTS + ${_icu_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + +FIND_LIBRARY(ICU_LIBRARY_TU + NAMES + icutu + HINTS + ${_icu_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + +FIND_LIBRARY(ICU_LIBRARY_UC + NAMES + icuuc + HINTS + ${_icu_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + +# Restore the original find library ordering +if(Boost_USE_STATIC_LIBS) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${_icu_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) +endif() + +# handle the QUIETLY and REQUIRED arguments and set ICU_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Icu DEFAULT_MSG + ICU_LIBRARY_DATA + ICU_LIBRARY_I18N + ICU_LIBRARY_IO + ICU_LIBRARY_LE + ICU_LIBRARY_LX + ICU_LIBRARY_TU + ICU_LIBRARY_UC +) + +IF(ICU_FOUND) + SET(ICU_LIBRARIES ${ICU_LIBRARY_DATA} ${ICU_LIBRARY_I18N} ${ICU_LIBRARY_IO} ${ICU_LIBRARY_LE} ${ICU_LIBRARY_LX} ${ICU_LIBRARY_TU} ${ICU_LIBRARY_UC}) + SET(ICU_INCLUDE_DIRS ${ICU_INCLUDE_DIR}) +ENDIF(ICU_FOUND) + +MARK_AS_ADVANCED( + ICU_INCLUDE_DIR + ICU_LIBRARY_DATA + ICU_LIBRARY_I18N + ICU_LIBRARY_IO + ICU_LIBRARY_LE + ICU_LIBRARY_LX + ICU_LIBRARY_TU + ICU_LIBRARY_UC +) diff --git a/build_files/cmake/Modules/FindOpenColorIO.cmake b/build_files/cmake/Modules/FindOpenColorIO.cmake index 79bc0127674..e152f0f81d9 100644 --- a/build_files/cmake/Modules/FindOpenColorIO.cmake +++ b/build_files/cmake/Modules/FindOpenColorIO.cmake @@ -39,6 +39,7 @@ SET(_opencolorio_SEARCH_DIRS /sw # Fink /opt/local # DarwinPorts /opt/csw # Blastwave + /opt/lib/ocio ) FIND_PATH(OPENCOLORIO_INCLUDE_DIR diff --git a/build_files/cmake/Modules/FindOpenImageIO.cmake b/build_files/cmake/Modules/FindOpenImageIO.cmake index 7512b93e09e..9b8c8b075b1 100644 --- a/build_files/cmake/Modules/FindOpenImageIO.cmake +++ b/build_files/cmake/Modules/FindOpenImageIO.cmake @@ -33,6 +33,7 @@ SET(_openimageio_SEARCH_DIRS /sw # Fink /opt/local # DarwinPorts /opt/csw # Blastwave + /opt/lib/oiio ) FIND_PATH(OPENIMAGEIO_INCLUDE_DIR diff --git a/build_files/cmake/Modules/FindPythonLibsUnix.cmake b/build_files/cmake/Modules/FindPythonLibsUnix.cmake index 34394864861..1dffd54fed1 100644 --- a/build_files/cmake/Modules/FindPythonLibsUnix.cmake +++ b/build_files/cmake/Modules/FindPythonLibsUnix.cmake @@ -9,6 +9,7 @@ # This module defines # PYTHON_VERSION # PYTHON_INCLUDE_DIRS +# PYTHON_INCLUDE_CONFIG_DIRS # PYTHON_LIBRARIES # PYTHON_LIBPATH, Used for installation # PYTHON_LINKFLAGS @@ -46,17 +47,25 @@ MARK_AS_ADVANCED(PYTHON_LINKFLAGS) # if the user passes these defines as args, we dont want to overwrite SET(_IS_INC_DEF OFF) +SET(_IS_INC_CONF_DEF OFF) SET(_IS_LIB_DEF OFF) +SET(_IS_LIB_PATH_DEF OFF) IF(DEFINED PYTHON_INCLUDE_DIR) SET(_IS_INC_DEF ON) ENDIF() +IF(DEFINED PYTHON_INCLUDE_CONFIG_DIR) + SET(_IS_INC_CONF_DEF ON) +ENDIF() IF(DEFINED PYTHON_LIBRARY) SET(_IS_LIB_DEF ON) ENDIF() +IF(DEFINED PYTHON_LIBPATH) + SET(_IS_LIB_PATH_DEF ON) +ENDIF() # only search for the dirs if we havn't already -IF((NOT _IS_INC_DEF) OR (NOT _IS_LIB_DEF)) +IF((NOT _IS_INC_DEF) OR (NOT _IS_INC_CONF_DEF) OR (NOT _IS_LIB_DEF) OR (NOT _IS_LIB_PATH_DEF)) SET(_python_ABI_FLAGS "m;mu;u; " # release @@ -69,6 +78,7 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_LIB_DEF)) ${PYTHON_ROOT_DIR} "$ENV{HOME}/py${_PYTHON_VERSION_NO_DOTS}" "/opt/py${_PYTHON_VERSION_NO_DOTS}" + "/opt/lib/python-${PYTHON_VERSION}" ) FOREACH(_CURRENT_ABI_FLAGS ${_python_ABI_FLAGS}) @@ -85,9 +95,27 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_LIB_DEF)) ${_python_SEARCH_DIRS} PATH_SUFFIXES include/python${PYTHON_VERSION}${_CURRENT_ABI_FLAGS} + include/${CMAKE_LIBRARY_ARCHITECTURE}/python${PYTHON_VERSION}${_CURRENT_ABI_FLAGS} ) ENDIF() + IF(NOT DEFINED PYTHON_INCLUDE_CONFIG_DIR) + FIND_PATH(PYTHON_INCLUDE_CONFIG_DIR + NAMES + pyconfig.h + HINTS + ${_python_SEARCH_DIRS} + PATH_SUFFIXES + include/python${PYTHON_VERSION}${_CURRENT_ABI_FLAGS} + include/${CMAKE_LIBRARY_ARCHITECTURE}/python${PYTHON_VERSION}${_CURRENT_ABI_FLAGS} + ) + IF((NOT PYTHON_INCLUDE_CONFIG_DIR) AND PYTHON_INCLUDE_DIR) + # Fallback... + UNSET(PYTHON_INCLUDE_CONFIG_DIR CACHE) + SET(PYTHON_INCLUDE_CONFIG_DIR ${PYTHON_INCLUDE_DIR} CACHE PATH "") + ENDIF() + ENDIF() + IF(NOT DEFINED PYTHON_LIBRARY) FIND_LIBRARY(PYTHON_LIBRARY NAMES @@ -99,16 +127,38 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_LIB_DEF)) ) ENDIF() - IF(PYTHON_LIBRARY AND PYTHON_INCLUDE_DIR) + IF(NOT DEFINED PYTHON_LIBPATH) + FIND_PATH(PYTHON_LIBPATH + NAMES + "python${PYTHON_VERSION}/abc.py" # This is a bit hackish! :/ + HINTS + ${_python_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + IF((NOT PYTHON_LIBPATH) AND PYTHON_LIBRARY) + # Fallback... + UNSET(PYTHON_LIBPATH CACHE) + GET_FILENAME_COMPONENT(PYTHON_LIBPATH ${PYTHON_LIBRARY} PATH) + ENDIF() + ENDIF() + + IF(PYTHON_LIBRARY AND PYTHON_LIBPATH AND PYTHON_INCLUDE_DIR AND PYTHON_INCLUDE_CONFIG_DIR) break() ELSE() # ensure we dont find values from 2 different ABI versions IF(NOT _IS_INC_DEF) UNSET(PYTHON_INCLUDE_DIR CACHE) ENDIF() + IF(NOT _IS_INC_CONF_DEF) + UNSET(PYTHON_INCLUDE_CONFIG_DIR CACHE) + ENDIF() IF(NOT _IS_LIB_DEF) UNSET(PYTHON_LIBRARY CACHE) ENDIF() + IF(NOT _IS_LIB_PATH_DEF) + UNSET(PYTHON_LIBPATH CACHE) + ENDIF() ENDIF() ENDFOREACH() @@ -120,22 +170,24 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_LIB_DEF)) ENDIF() UNSET(_IS_INC_DEF) +UNSET(_IS_INC_CONF_DEF) UNSET(_IS_LIB_DEF) +UNSET(_IS_LIB_PATH_DEF) # handle the QUIETLY and REQUIRED arguments and SET PYTHONLIBSUNIX_FOUND to TRUE IF # all listed variables are TRUE INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(PythonLibsUnix DEFAULT_MSG - PYTHON_LIBRARY PYTHON_INCLUDE_DIR) - + PYTHON_LIBRARY PYTHON_LIBPATH PYTHON_INCLUDE_DIR PYTHON_INCLUDE_CONFIG_DIR) IF(PYTHONLIBSUNIX_FOUND) # Assign cache items - SET(PYTHON_INCLUDE_DIRS ${PYTHON_INCLUDE_DIR}) + SET(PYTHON_INCLUDE_DIRS ${PYTHON_INCLUDE_DIR} ${PYTHON_INCLUDE_CONFIG_DIR}) SET(PYTHON_LIBRARIES ${PYTHON_LIBRARY}) # we need this for installation - GET_FILENAME_COMPONENT(PYTHON_LIBPATH ${PYTHON_LIBRARY} PATH) + # XXX No more valid with debian-like py3.3 packages... +# GET_FILENAME_COMPONENT(PYTHON_LIBPATH ${PYTHON_LIBRARY} PATH) # not used # SET(PYTHON_BINARY ${PYTHON_EXECUTABLE} CACHE STRING "") @@ -143,5 +195,6 @@ ENDIF() MARK_AS_ADVANCED( PYTHON_INCLUDE_DIR + PYTHON_INCLUDE_CONFIG_DIR PYTHON_LIBRARY ) diff --git a/build_files/cmake/cmake_consistency_check.py b/build_files/cmake/cmake_consistency_check.py index 072bbb12fb3..b13b0ddb424 100755 --- a/build_files/cmake/cmake_consistency_check.py +++ b/build_files/cmake/cmake_consistency_check.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # @@ -222,8 +222,8 @@ def cmake_get_src(f): ''' # reset - sources_h[:] = [] - sources_c[:] = [] + del sources_h[:] + del sources_c[:] filen.close() diff --git a/build_files/cmake/cmake_netbeans_project.py b/build_files/cmake/cmake_netbeans_project.py index 8f3835c3401..2f36cad4d24 100755 --- a/build_files/cmake/cmake_netbeans_project.py +++ b/build_files/cmake/cmake_netbeans_project.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # diff --git a/build_files/cmake/cmake_qtcreator_project.py b/build_files/cmake/cmake_qtcreator_project.py index 83ea761e2d1..86201da23de 100755 --- a/build_files/cmake/cmake_qtcreator_project.py +++ b/build_files/cmake/cmake_qtcreator_project.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # diff --git a/build_files/cmake/cmake_static_check_clang_array.py b/build_files/cmake/cmake_static_check_clang_array.py index 941407170ff..7f45cc6aadc 100644 --- a/build_files/cmake/cmake_static_check_clang_array.py +++ b/build_files/cmake/cmake_static_check_clang_array.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # @@ -27,6 +27,8 @@ import subprocess import sys import os +USE_QUIET = (os.environ.get("QUIET", None) is not None) + CHECKER_IGNORE_PREFIX = [ "extern", "intern/moto", @@ -59,11 +61,12 @@ def main(): process_functions = [] def my_process(i, c, cmd): - percent = 100.0 * (i / (len(check_commands) - 1)) - percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" + if not USE_QUIET: + percent = 100.0 * (i / (len(check_commands) - 1)) + percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" - sys.stdout.flush() - sys.stdout.write("%s " % percent_str) + sys.stdout.flush() + sys.stdout.write("%s " % percent_str) return subprocess.Popen(cmd) diff --git a/build_files/cmake/cmake_static_check_cppcheck.py b/build_files/cmake/cmake_static_check_cppcheck.py index c458e8ede11..d79145f8586 100644 --- a/build_files/cmake/cmake_static_check_cppcheck.py +++ b/build_files/cmake/cmake_static_check_cppcheck.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # @@ -27,6 +27,8 @@ import subprocess import sys import os +USE_QUIET = (os.environ.get("QUIET", None) is not None) + CHECKER_IGNORE_PREFIX = [ "extern", "intern/moto", @@ -44,6 +46,9 @@ CHECKER_ARGS = [ # "--enable=all", # if you want sixty hundred pedantic suggestions ] +if USE_QUIET: + CHECKER_ARGS.append("--quiet") + def main(): source_info = project_source_info.build_info(ignore_prefix_list=CHECKER_IGNORE_PREFIX) @@ -62,11 +67,12 @@ def main(): process_functions = [] def my_process(i, c, cmd): - percent = 100.0 * (i / (len(check_commands) - 1)) - percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" + if not USE_QUIET: + percent = 100.0 * (i / (len(check_commands) - 1)) + percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" - sys.stdout.flush() - sys.stdout.write("%s " % percent_str) + sys.stdout.flush() + sys.stdout.write("%s " % percent_str) return subprocess.Popen(cmd) @@ -75,6 +81,8 @@ def main(): project_source_info.queue_processes(process_functions) + print("Finished!") + if __name__ == "__main__": main() diff --git a/build_files/cmake/cmake_static_check_smatch.py b/build_files/cmake/cmake_static_check_smatch.py index 5681d2ae5ed..7535f1cc55a 100644 --- a/build_files/cmake/cmake_static_check_smatch.py +++ b/build_files/cmake/cmake_static_check_smatch.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # @@ -37,7 +37,9 @@ CHECKER_ARGS = [ import project_source_info import subprocess import sys +import os +USE_QUIET = (os.environ.get("QUIET", None) is not None) def main(): source_info = project_source_info.build_info(use_cxx=False, ignore_prefix_list=CHECKER_IGNORE_PREFIX) @@ -55,11 +57,12 @@ def main(): check_commands.append((c, cmd)) def my_process(i, c, cmd): - percent = 100.0 * (i / (len(check_commands) - 1)) - percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" + if not USE_QUIET: + percent = 100.0 * (i / (len(check_commands) - 1)) + percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" - sys.stdout.flush() - sys.stdout.write("%s %s\n" % (percent_str, c)) + sys.stdout.flush() + sys.stdout.write("%s %s\n" % (percent_str, c)) return subprocess.Popen(cmd) diff --git a/build_files/cmake/cmake_static_check_sparse.py b/build_files/cmake/cmake_static_check_sparse.py index 4f4eb838dd5..06bef1a1327 100644 --- a/build_files/cmake/cmake_static_check_sparse.py +++ b/build_files/cmake/cmake_static_check_sparse.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # @@ -35,6 +35,9 @@ CHECKER_ARGS = [ import project_source_info import subprocess import sys +import os + +USE_QUIET = (os.environ.get("QUIET", None) is not None) def main(): @@ -53,11 +56,12 @@ def main(): check_commands.append((c, cmd)) def my_process(i, c, cmd): - percent = 100.0 * (i / (len(check_commands) - 1)) - percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" + if not USE_QUIET: + percent = 100.0 * (i / (len(check_commands) - 1)) + percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" - sys.stdout.flush() - sys.stdout.write("%s %s\n" % (percent_str, c)) + sys.stdout.flush() + sys.stdout.write("%s %s\n" % (percent_str, c)) return subprocess.Popen(cmd) diff --git a/build_files/cmake/cmake_static_check_splint.py b/build_files/cmake/cmake_static_check_splint.py index 7be28c01af8..5b1207543f5 100644 --- a/build_files/cmake/cmake_static_check_splint.py +++ b/build_files/cmake/cmake_static_check_splint.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # @@ -68,6 +68,9 @@ CHECKER_ARGS = [ import project_source_info import subprocess import sys +import os + +USE_QUIET = (os.environ.get("QUIET", None) is not None) def main(): @@ -85,11 +88,12 @@ def main(): check_commands.append((c, cmd)) def my_process(i, c, cmd): - percent = 100.0 * (i / (len(check_commands) - 1)) - percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" + if not USE_QUIET: + percent = 100.0 * (i / (len(check_commands) - 1)) + percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" - sys.stdout.write("%s %s\n" % (percent_str, c)) - sys.stdout.flush() + sys.stdout.write("%s %s\n" % (percent_str, c)) + sys.stdout.flush() return subprocess.Popen(cmd) diff --git a/build_files/cmake/example_scripts/make_quicky.py b/build_files/cmake/example_scripts/make_quicky.py index 9b853fc01d4..76d4df32f86 100755 --- a/build_files/cmake/example_scripts/make_quicky.py +++ b/build_files/cmake/example_scripts/make_quicky.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ##### BEGIN GPL LICENSE BLOCK ##### # diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 3c321cc60be..efa258aa9dc 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -196,10 +196,6 @@ macro(SETUP_LIBDIRS) if(WITH_PYTHON) # AND NOT WITH_PYTHON_MODULE # WIN32 needs link_directories(${PYTHON_LIBPATH}) endif() - if(WITH_INTERNATIONAL) - link_directories(${ICONV_LIBPATH}) - link_directories(${GETTEXT_LIBPATH}) - endif() if(WITH_SDL) link_directories(${SDL_LIBPATH}) endif() @@ -287,14 +283,6 @@ macro(setup_liblinks target_link_libraries(${target} ${GLEW_LIBRARY}) endif() - if(WITH_INTERNATIONAL) - target_link_libraries(${target} ${GETTEXT_LIBRARIES}) - - if(WIN32 AND NOT UNIX) - target_link_libraries(${target} ${ICONV_LIBRARIES}) - endif() - endif() - if(WITH_OPENAL) target_link_libraries(${target} ${OPENAL_LIBRARY}) endif() @@ -324,6 +312,9 @@ macro(setup_liblinks endif() if(WITH_BOOST) target_link_libraries(${target} ${BOOST_LIBRARIES}) + if(Boost_USE_STATIC_LIBS AND Boost_USE_ICU) + target_link_libraries(${target} ${ICU_LIBRARIES}) + endif() endif() target_link_libraries(${target} ${JPEG_LIBRARIES}) if(WITH_IMAGE_OPENEXR) @@ -712,7 +703,11 @@ macro(delayed_install destination) foreach(f ${files}) - set_property(GLOBAL APPEND PROPERTY DELAYED_INSTALL_FILES ${base}/${f}) + if(IS_ABSOLUTE ${f}) + set_property(GLOBAL APPEND PROPERTY DELAYED_INSTALL_FILES ${f}) + else() + set_property(GLOBAL APPEND PROPERTY DELAYED_INSTALL_FILES ${base}/${f}) + endif() set_property(GLOBAL APPEND PROPERTY DELAYED_INSTALL_DESTINATIONS ${destination}) endforeach() endmacro() diff --git a/build_files/cmake/project_info.py b/build_files/cmake/project_info.py index b154d578144..34f378a58dd 100755 --- a/build_files/cmake/project_info.py +++ b/build_files/cmake/project_info.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # diff --git a/build_files/scons/config/darwin-config.py b/build_files/scons/config/darwin-config.py index afab4131de8..252a1b1b37e 100644 --- a/build_files/scons/config/darwin-config.py +++ b/build_files/scons/config/darwin-config.py @@ -118,16 +118,16 @@ BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib' BF_FFMPEG_LIB = 'avcodec avdevice avformat avutil mp3lame swscale x264 xvidcore theora theoradec theoraenc vorbis vorbisenc vorbisfile ogg bz2' #bz2 is a standard osx dynlib -BF_PYTHON_VERSION = '3.2' +BF_PYTHON_VERSION = '3.3' WITH_OSX_STATICPYTHON = True if WITH_OSX_STATICPYTHON: - # python 3.2 uses precompiled libraries in bf svn /lib by default + # python 3.3 uses precompiled libraries in bf svn /lib by default BF_PYTHON = LIBDIR + '/python' - BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' + BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}m' # BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' - BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' + BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}m' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/python${BF_PYTHON_VERSION}' # BF_PYTHON_LINKFLAGS = ['-u', '_PyMac_Error', '-framework', 'System'] else: @@ -223,11 +223,6 @@ BF_ZLIB_LIB = 'z' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = LIBDIR + '/gettext' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'intl' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True @@ -281,23 +276,42 @@ BF_PCRE_LIBPATH = '${BF_PCRE}/lib' # Cycles WITH_BF_CYCLES = True +#OSL + +WITH_BF_CYCLES_OSL = True +BF_OSL = LIBDIR + '/osl' +BF_OSL_INC = '${BF_OSL}/include' +# note oslexec would passed via program linkflags, which is needed to +# make llvm happy with osl_allocate_closure_component +#BF_OSL_LIB = 'oslcomp oslquery' +BF_OSL_LIBPATH = '${BF_OSL}/lib' +BF_OSL_COMPILER = '${BF_OSL}/bin/oslc' + +WITH_BF_LLVM = True +BF_LLVM = LIBDIR + '/llvm' +BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \ + 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \ + 'LLVMTarget LLVMMC LLVMCore LLVMSupport' +BF_LLVM_LIBPATH = '${BF_LLVM}/lib' + WITH_BF_OIIO = True BF_OIIO = LIBDIR + '/openimageio' -BF_OIIO_INC = BF_OIIO + '/include' +BF_OIIO_INC = '${BF_OIIO}/include' BF_OIIO_LIB = 'OpenImageIO' -BF_OIIO_LIBPATH = BF_OIIO + '/lib' +BF_OIIO_LIBPATH = '${BF_OIIO}/lib' WITH_BF_OCIO = True BF_OCIO = LIBDIR + '/opencolorio' -BF_OCIO_INC = BF_OCIO + '/include' +BF_OCIO_INC = '${BF_OCIO}/include' BF_OCIO_LIB = 'OpenColorIO tinyxml yaml-cpp' -BF_OCIO_LIBPATH = BF_OCIO + '/lib' +BF_OCIO_LIBPATH = '${BF_OCIO}/lib' WITH_BF_BOOST = True BF_BOOST = LIBDIR + '/boost' -BF_BOOST_INC = BF_BOOST + '/include' -BF_BOOST_LIB = 'boost_date_time-mt boost_filesystem-mt boost_regex-mt boost_system-mt boost_thread-mt' -BF_BOOST_LIBPATH = BF_BOOST + '/lib' +BF_BOOST_INC = '${BF_BOOST}/include' +BF_BOOST_LIB = 'boost_date_time-mt boost_filesystem-mt boost_regex-mt boost_system-mt boost_thread-mt boost_wave-mt' +BF_BOOST_LIB_INTERNATIONAL = 'boost_locale-mt' +BF_BOOST_LIBPATH = '${BF_BOOST}/lib' WITH_BF_CYCLES_CUDA_BINARIES = False BF_CYCLES_CUDA_NVCC = '/usr/local/cuda/bin/nvcc' diff --git a/build_files/scons/config/freebsd7-config.py b/build_files/scons/config/freebsd7-config.py index 412b08d895b..02c9093567a 100644 --- a/build_files/scons/config/freebsd7-config.py +++ b/build_files/scons/config/freebsd7-config.py @@ -7,7 +7,7 @@ LIBDIR = "${LCGDIR}" BF_PYTHON_ABI_FLAGS = '' BF_PYTHON = '/usr/local' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' -BF_PYTHON_VERSION = '3.2' +BF_PYTHON_VERSION = '3.3' WITH_BF_STATICPYTHON = False BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}${BF_PYTHON_ABI_FLAGS}' BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' @@ -77,11 +77,6 @@ BF_ZLIB_LIB = 'z' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = '/usr/local' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'gettextlib' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = False WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True diff --git a/build_files/scons/config/freebsd8-config.py b/build_files/scons/config/freebsd8-config.py index ece86f799c3..5d3308c50d4 100644 --- a/build_files/scons/config/freebsd8-config.py +++ b/build_files/scons/config/freebsd8-config.py @@ -7,7 +7,7 @@ LIBDIR = "${LCGDIR}" BF_PYTHON_ABI_FLAGS = '' BF_PYTHON = '/usr/local' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' -BF_PYTHON_VERSION = '3.2' +BF_PYTHON_VERSION = '3.3' WITH_BF_STATICPYTHON = False BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}${BF_PYTHON_ABI_FLAGS}' BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' @@ -77,11 +77,6 @@ BF_ZLIB_LIB = 'z' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = '/usr/local' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'gettextlib' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = False WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True diff --git a/build_files/scons/config/freebsd9-config.py b/build_files/scons/config/freebsd9-config.py index a31c6da90f0..98c2c8fa500 100644 --- a/build_files/scons/config/freebsd9-config.py +++ b/build_files/scons/config/freebsd9-config.py @@ -7,7 +7,7 @@ LIBDIR = "${LCGDIR}" BF_PYTHON_ABI_FLAGS = '' BF_PYTHON = '/usr/local' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' -BF_PYTHON_VERSION = '3.2' +BF_PYTHON_VERSION = '3.3' WITH_BF_STATICPYTHON = False BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}${BF_PYTHON_ABI_FLAGS}' BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' @@ -77,11 +77,6 @@ BF_ZLIB_LIB = 'z' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = '/usr/local' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'gettextlib' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = False WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True diff --git a/build_files/scons/config/linux-config.py b/build_files/scons/config/linux-config.py index 45f6602e4dd..038a9bc421d 100644 --- a/build_files/scons/config/linux-config.py +++ b/build_files/scons/config/linux-config.py @@ -89,13 +89,6 @@ BF_ZLIB_LIB = 'z' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = '/usr' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'gettextlib' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' -#WITH_BF_GETTEXT_STATIC = True -#BF_GETTEXT_LIB_STATIC = '${BF_GETTEXT}/lib/libgettextlib.a' - WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True @@ -211,9 +204,9 @@ BF_OIIO = LIBDIR + '/oiio' if not os.path.exists(LCGDIR + '/oiio'): WITH_BF_OIIO = False BF_OIIO = '/usr' -BF_OIIO_INC = BF_OIIO + '/include' +BF_OIIO_INC = '${BF_OIIO}/include' BF_OIIO_LIB = 'OpenImageIO' -BF_OIIO_LIBPATH = BF_OIIO + '/lib' +BF_OIIO_LIBPATH = '${BF_OIIO}/lib' WITH_BF_OCIO = True WITH_BF_STATICOCIO = False @@ -221,9 +214,9 @@ BF_OCIO = LIBDIR + '/ocio' if not os.path.exists(LCGDIR + '/ocio'): WITH_BF_OCIO = False BF_OCIO = '/usr' -BF_OCIO_INC = BF_OCIO + '/include' +BF_OCIO_INC = '${BF_OCIO}/include' BF_OCIO_LIB = 'OpenColorIO yaml-cpp tinyxml' -BF_OCIO_LIBPATH = BF_OCIO + '/lib' +BF_OCIO_LIBPATH = '${BF_OCIO}/lib' WITH_BF_BOOST = True WITH_BF_STATICBOOST = False @@ -231,9 +224,10 @@ BF_BOOST = LIBDIR + '/boost' if not os.path.exists(LCGDIR + '/boost'): WITH_BF_BOOST = False BF_BOOST = '/usr' -BF_BOOST_INC = BF_BOOST + '/include' +BF_BOOST_INC = '${BF_BOOST}/include' BF_BOOST_LIB = 'boost_date_time boost_filesystem boost_regex boost_system boost_thread' -BF_BOOST_LIBPATH = BF_BOOST + '/lib' +BF_BOOST_LIB_INTERNATIONAL = 'boost_locale' +BF_BOOST_LIBPATH = '${BF_BOOST}/lib' WITH_BF_CYCLES = WITH_BF_OIIO and WITH_BF_BOOST @@ -304,3 +298,7 @@ BF_INSTALLDIR='../install/linux' #Link against pthread PLATFORM_LINKFLAGS = ['-pthread'] +#Fix for LLVM conflict with Mesa llvmpipe +if WITH_BF_LLVM: + PLATFORM_LINKFLAGS += ['-Wl,--version-script=source/creator/blender.map'] + diff --git a/build_files/scons/config/linuxcross-config.py b/build_files/scons/config/linuxcross-config.py index 6866241793b..54faf59b2a4 100644 --- a/build_files/scons/config/linuxcross-config.py +++ b/build_files/scons/config/linuxcross-config.py @@ -2,7 +2,7 @@ LCGDIR = '#../lib/windows' LIBDIR = '${LCGDIR}' BF_PYTHON = LIBDIR + '/python' -BF_PYTHON_VERSION = '3.2' +BF_PYTHON_VERSION = '3.3' BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = 'python' BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION[0]}${BF_PYTHON_VERSION[2]}mw' @@ -83,11 +83,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = LIBDIR + '/gcc/gettext' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'intl' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = False WITH_BF_OCEANSIM = True diff --git a/build_files/scons/config/win32-mingw-config.py b/build_files/scons/config/win32-mingw-config.py index 0a72d87bb2a..391421609d2 100644 --- a/build_files/scons/config/win32-mingw-config.py +++ b/build_files/scons/config/win32-mingw-config.py @@ -2,12 +2,12 @@ LCGDIR = '#../lib/mingw32' LIBDIR = "${LCGDIR}" BF_PYTHON = LIBDIR + '/python' -BF_PYTHON_VERSION = '3.2' +BF_PYTHON_VERSION = '3.3' WITH_BF_STATICPYTHON = False BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = 'python' BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION[0]}${BF_PYTHON_VERSION[2]}mw' -BF_PYTHON_DLL = 'python32' +BF_PYTHON_DLL = 'python33' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' BF_PYTHON_LIB_STATIC = '${BF_PYTHON}/lib/libpython${BF_PYTHON_VERSION[0]}${BF_PYTHON_VERSION[2]}.a' @@ -83,11 +83,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = LIBDIR + '/gettext' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'intl' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_OPENJPEG = True BF_OPENJPEG = '#extern/libopenjpeg' BF_OPENJPEG_LIB = '' @@ -155,21 +150,22 @@ WITH_BF_CYCLES = True WITH_BF_OIIO = True BF_OIIO = LIBDIR + '/openimageio' -BF_OIIO_INC = BF_OIIO + '/include' +BF_OIIO_INC = '${BF_OIIO}/include' BF_OIIO_LIB = 'OpenImageIO' -BF_OIIO_LIBPATH = BF_OIIO + '/lib' +BF_OIIO_LIBPATH = '${BF_OIIO}/lib' WITH_BF_OCIO = True BF_OCIO = LIBDIR + '/opencolorio' -BF_OCIO_INC = BF_OCIO + '/include' +BF_OCIO_INC = '${BF_OCIO}/include' BF_OCIO_LIB = 'OpenColorIO' -BF_OCIO_LIBPATH = BF_OCIO + '/lib' +BF_OCIO_LIBPATH = '${BF_OCIO}/lib' WITH_BF_BOOST = True BF_BOOST = LIBDIR + '/boost' -BF_BOOST_INC = BF_BOOST + '/include' +BF_BOOST_INC = '${BF_BOOST}/include' BF_BOOST_LIB = 'boost_date_time-mgw46-mt-s-1_49 boost_filesystem-mgw46-mt-s-1_49 boost_regex-mgw46-mt-s-1_49 boost_system-mgw46-mt-s-1_49 boost_thread-mgw46-mt-s-1_49' -BF_BOOST_LIBPATH = BF_BOOST + '/lib' +BF_BOOST_LIB_INTERNATIONAL = 'boost_locale-mgw46-mt-s-1_49' +BF_BOOST_LIBPATH = '${BF_BOOST}/lib' #Ray trace optimization WITH_BF_RAYOPTIMIZATION = True diff --git a/build_files/scons/config/win32-vc-config.py b/build_files/scons/config/win32-vc-config.py index b77ff8e70e0..21488e75f7e 100644 --- a/build_files/scons/config/win32-vc-config.py +++ b/build_files/scons/config/win32-vc-config.py @@ -9,10 +9,10 @@ BF_FFMPEG_LIB = 'avformat-53.lib avcodec-53.lib avdevice-53.lib avutil-51.lib sw BF_FFMPEG_DLL = '${BF_FFMPEG_LIBPATH}/avformat-53.dll ${BF_FFMPEG_LIBPATH}/avcodec-53.dll ${BF_FFMPEG_LIBPATH}/avdevice-53.dll ${BF_FFMPEG_LIBPATH}/avutil-51.dll ${BF_FFMPEG_LIBPATH}/swscale-2.dll' BF_PYTHON = LIBDIR + '/python' -BF_PYTHON_VERSION = '3.2' +BF_PYTHON_VERSION = '3.3' BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = 'python' -BF_PYTHON_LIB = 'python32' +BF_PYTHON_LIB = 'python33' BF_PYTHON_DLL = '${BF_PYTHON_LIB}' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' @@ -54,7 +54,7 @@ BF_PTHREADS_LIBPATH = '${BF_PTHREADS}/lib' WITH_BF_OPENEXR = True WITH_BF_STATICOPENEXR = False BF_OPENEXR = LIBDIR + '/openexr' -BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/IlmImf ${BF_OPENEXR}/include/Iex ${BF_OPENEXR}/include/Imath ' +BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR ' BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread ' BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib' BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a' @@ -87,11 +87,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = LIBDIR + '/gettext' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'gnu_gettext' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True @@ -155,22 +150,40 @@ WITH_BF_OPENMP = True #Cycles WITH_BF_CYCLES = True +WITH_BF_CYCLES_OSL = True +WITH_BF_STATICOSL = True +BF_OSL = '${LIBDIR}/osl' +BF_OSL_INC = '${BF_OSL}/include' +BF_OSL_LIBPATH = '${BF_OSL}/lib' +BF_OSL_LIB_STATIC = '${BF_OSL_LIBPATH}/oslcomp.lib ${BF_OSL_LIBPATH}/oslexec.lib ${BF_OSL_LIBPATH}/oslquery.lib ' +BF_OSL_COMPILER = '${BF_OSL}/bin/oslc' + +WITH_BF_LLVM = True +BF_LLVM = LIBDIR + '/llvm' +BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \ + 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \ + 'LLVMTarget LLVMMC LLVMCore LLVMSupport' +BF_LLVM_LIBPATH = '${BF_LLVM}/lib' + WITH_BF_OIIO = True BF_OIIO = '${LIBDIR}/openimageio' BF_OIIO_INC = '${BF_OIIO}/include' -BF_OIIO_LIB = 'OpenImageIO' BF_OIIO_LIBPATH = '${BF_OIIO}/lib' +BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/OpenImageIO.lib' +WITH_BF_STATICOIIO = True WITH_BF_OCIO = True BF_OCIO = '${LIBDIR}/opencolorio' BF_OCIO_INC = '${BF_OCIO}/include' -BF_OCIO_LIB = 'OpenColorIO' BF_OCIO_LIBPATH = '${BF_OCIO}/lib' +BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/OpenColorIO.lib' +WITH_BF_STATICOCIO = True WITH_BF_BOOST = True BF_BOOST = '${LIBDIR}/boost' BF_BOOST_INC = '${BF_BOOST}/include' BF_BOOST_LIB = 'libboost_date_time-vc90-mt-s-1_49 libboost_filesystem-vc90-mt-s-1_49 libboost_regex-vc90-mt-s-1_49 libboost_system-vc90-mt-s-1_49 libboost_thread-vc90-mt-s-1_49' +BF_BOOST_LIB_INTERNATIONAL = 'libboost_locale-vc90-mt-s-1_49' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' #CUDA @@ -208,7 +221,7 @@ C_WARN = [] CC_WARN = [] CXX_WARN = [] -LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid'] +LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid', 'psapi'] PLATFORM_LINKFLAGS = ['/SUBSYSTEM:CONSOLE','/MACHINE:IX86','/STACK:2097152','/INCREMENTAL:NO', '/LARGEADDRESSAWARE', '/NODEFAULTLIB:msvcrt.lib', '/NODEFAULTLIB:msvcmrt.lib', '/NODEFAULTLIB:msvcurt.lib', '/NODEFAULTLIB:msvcrtd.lib'] diff --git a/build_files/scons/config/win64-mingw-config.py b/build_files/scons/config/win64-mingw-config.py index 838822bbbcb..d00e7a3ffa7 100644 --- a/build_files/scons/config/win64-mingw-config.py +++ b/build_files/scons/config/win64-mingw-config.py @@ -2,12 +2,12 @@ LCGDIR = '#../lib/mingw64' LIBDIR = "${LCGDIR}" BF_PYTHON = LIBDIR + '/python' -BF_PYTHON_VERSION = '3.2' +BF_PYTHON_VERSION = '3.3' WITH_BF_STATICPYTHON = False BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = 'python' BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION[0]}${BF_PYTHON_VERSION[2]}mw' -BF_PYTHON_DLL = 'python32' +BF_PYTHON_DLL = 'python33' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' WITH_BF_OPENAL = True @@ -80,11 +80,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = LIBDIR + '/gettext' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'intl' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_OPENJPEG = True BF_OPENJPEG = '#extern/libopenjpeg' BF_OPENJPEG_LIB = '' @@ -118,7 +113,7 @@ BF_FREETYPE_LIBPATH = '${BF_FREETYPE}/lib' WITH_BF_QUICKTIME = False -WITH_BF_ICONV = True +WITH_BF_ICONV = False BF_ICONV = LIBDIR + "/iconv" BF_ICONV_INC = '${BF_ICONV}/include' BF_ICONV_LIB = 'iconv' @@ -167,9 +162,10 @@ BF_OCIO_LIBPATH = '${BF_OCIO}/lib' WITH_BF_BOOST = True BF_BOOST = LIBDIR + '/boost' -BF_BOOST_INC = BF_BOOST + '/include' +BF_BOOST_INC = '${BF_BOOST}/include' BF_BOOST_LIB = 'boost_date_time-mgw47-mt-s-1_49 boost_date_time-mgw47-mt-sd-1_49 boost_filesystem-mgw47-mt-s-1_49 boost_filesystem-mgw47-mt-sd-1_49 boost_regex-mgw47-mt-s-1_49 boost_regex-mgw47-mt-sd-1_49 boost_system-mgw47-mt-s-1_49 boost_system-mgw47-mt-sd-1_49 boost_thread-mgw47-mt-s-1_49 boost_thread-mgw47-mt-sd-1_49' -BF_BOOST_LIBPATH = BF_BOOST + '/lib' +BF_BOOST_LIB_INTERNATIONAL = ' boost_locale-mgw47-mt-s-1_49 boost_locale-mgw47-mt-sd-1_49' +BF_BOOST_LIBPATH = '${BF_BOOST}/lib' #Ray trace optimization WITH_BF_RAYOPTIMIZATION = True diff --git a/build_files/scons/config/win64-vc-config.py b/build_files/scons/config/win64-vc-config.py index 4b719469c39..c0ea7972aeb 100644 --- a/build_files/scons/config/win64-vc-config.py +++ b/build_files/scons/config/win64-vc-config.py @@ -9,10 +9,10 @@ BF_FFMPEG_LIB = 'avformat-53.lib avcodec-53.lib avdevice-53.lib avutil-51.lib sw BF_FFMPEG_DLL = '${BF_FFMPEG_LIBPATH}/avformat-53.dll ${BF_FFMPEG_LIBPATH}/avcodec-53.dll ${BF_FFMPEG_LIBPATH}/avdevice-53.dll ${BF_FFMPEG_LIBPATH}/avutil-51.dll ${BF_FFMPEG_LIBPATH}/swscale-2.dll' BF_PYTHON = LIBDIR + '/python' -BF_PYTHON_VERSION = '3.2' +BF_PYTHON_VERSION = '3.3' BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = 'python' -BF_PYTHON_LIB = 'python32' +BF_PYTHON_LIB = 'python33' BF_PYTHON_DLL = '${BF_PYTHON_LIB}' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' @@ -50,7 +50,7 @@ BF_PTHREADS_LIBPATH = '${BF_PTHREADS}/lib' WITH_BF_OPENEXR = True WITH_BF_STATICOPENEXR = False BF_OPENEXR = LIBDIR + '/openexr' -BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/IlmImf ${BF_OPENEXR}/include/Iex ${BF_OPENEXR}/include/Imath ' +BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR ' BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread ' BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib' BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a' @@ -83,11 +83,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = LIBDIR + '/gettext' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'gnu_gettext' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True @@ -151,24 +146,40 @@ WITH_BF_OPENMP = True #Cycles WITH_BF_CYCLES = True +WITH_BF_CYCLES_OSL = True +WITH_BF_STATICOSL = True +BF_OSL = '${LIBDIR}/osl' +BF_OSL_INC = '${BF_OSL}/include' +BF_OSL_LIBPATH = '${BF_OSL}/lib' +BF_OSL_LIB_STATIC = '${BF_OSL_LIBPATH}/oslcomp.lib ${BF_OSL_LIBPATH}/oslexec.lib ${BF_OSL_LIBPATH}/oslquery.lib ' +BF_OSL_COMPILER = '${BF_OSL}/bin/oslc' + +WITH_BF_LLVM = True +BF_LLVM = LIBDIR + '/llvm' +BF_LLVM_LIB = 'LLVMBitReader LLVMJIT LLVMipo LLVMVectorize LLVMBitWriter LLVMX86CodeGen LLVMX86Desc LLVMX86Info LLVMX86AsmPrinter ' + \ + 'LLVMX86Utils LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMExecutionEngine ' + \ + 'LLVMTarget LLVMMC LLVMCore LLVMSupport' +BF_LLVM_LIBPATH = '${BF_LLVM}/lib' + WITH_BF_OIIO = True BF_OIIO = '${LIBDIR}/openimageio' BF_OIIO_INC = '${BF_OIIO}/include' -BF_OIIO_LIB = 'OpenImageIO' -BF_OIIO_LIBPATH = '${BF_OIIO}/lib' BF_OIIO_LIBPATH = '${BF_OIIO}/lib' +BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/OpenImageIO.lib' +WITH_BF_STATICOIIO = True WITH_BF_OCIO = True BF_OCIO = '${LIBDIR}/opencolorio' BF_OCIO_INC = '${BF_OCIO}/include' -BF_OCIO_LIB = 'OpenColorIO' -BF_OCIO_LIBPATH = '${BF_OCIO}/lib' BF_OCIO_LIBPATH = '${BF_OCIO}/lib' +BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/OpenColorIO.lib' +WITH_BF_STATICOCIO = True WITH_BF_BOOST = True BF_BOOST = '${LIBDIR}/boost' BF_BOOST_INC = '${BF_BOOST}/include' BF_BOOST_LIB = 'libboost_date_time-vc90-mt-s-1_49 libboost_filesystem-vc90-mt-s-1_49 libboost_regex-vc90-mt-s-1_49 libboost_system-vc90-mt-s-1_49 libboost_thread-vc90-mt-s-1_49' +BF_BOOST_LIB_INTERNATIONAL = ' libboost_locale-vc90-mt-s-1_49' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' #CUDA @@ -207,7 +218,7 @@ C_WARN = [] CC_WARN = [] CXX_WARN = [] -LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid'] +LLIBS = ['ws2_32', 'vfw32', 'winmm', 'kernel32', 'user32', 'gdi32', 'comdlg32', 'advapi32', 'shfolder', 'shell32', 'ole32', 'oleaut32', 'uuid', 'psapi'] PLATFORM_LINKFLAGS = ['/SUBSYSTEM:CONSOLE','/MACHINE:X64','/STACK:2097152','/OPT:NOREF','/INCREMENTAL:NO', '/NODEFAULTLIB:msvcrt.lib', '/NODEFAULTLIB:msvcmrt.lib', '/NODEFAULTLIB:msvcurt.lib', '/NODEFAULTLIB:msvcrtd.lib'] diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py index eb646f27d53..94a9f1d9c24 100644 --- a/build_files/scons/tools/Blender.py +++ b/build_files/scons/tools/Blender.py @@ -166,16 +166,15 @@ def setup_staticlibs(lenv): libincs += Split(lenv['BF_FFTW3_LIBPATH']) if lenv['WITH_BF_STATICFFTW3']: statlibs += Split(lenv['BF_FFTW3_LIB_STATIC']) + ''' if lenv['WITH_BF_ELTOPO']: libincs += Split(lenv['BF_LAPACK_LIBPATH']) if lenv['WITH_BF_STATICLAPACK']: - statlibs += Split(lenv['BF_LAPACK_LIB_STATIC']) + statlibs += Split(lenv['BF_LAPACK_LIB_STATIC']) + ''' if lenv['WITH_BF_FFMPEG'] and lenv['WITH_BF_STATICFFMPEG']: statlibs += Split(lenv['BF_FFMPEG_LIB_STATIC']) if lenv['WITH_BF_INTERNATIONAL']: - libincs += Split(lenv['BF_GETTEXT_LIBPATH']) - if lenv['WITH_BF_GETTEXT_STATIC']: - statlibs += Split(lenv['BF_GETTEXT_LIB_STATIC']) if lenv['WITH_BF_FREETYPE_STATIC']: statlibs += Split(lenv['BF_FREETYPE_LIB_STATIC']) if lenv['WITH_BF_OPENAL']: @@ -225,6 +224,16 @@ def setup_staticlibs(lenv): if lenv['WITH_BF_STATICBOOST']: statlibs += Split(lenv['BF_BOOST_LIB_STATIC']) + if lenv['WITH_BF_CYCLES_OSL']: + libincs += Split(lenv['BF_OSL_LIBPATH']) + if lenv['WITH_BF_STATICOSL']: + statlibs += Split(lenv['BF_OSL_LIB_STATIC']) + + if lenv['WITH_BF_LLVM']: + libincs += Split(lenv['BF_LLVM_LIBPATH']) + if lenv['WITH_BF_STATICLLVM']: + statlibs += Split(lenv['BF_LLVM_LIB_STATIC']) + # setting this last so any overriding of manually libs could be handled if lenv['OURPLATFORM'] not in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross', 'win64-mingw'): libincs.append('/usr/lib') @@ -252,8 +261,6 @@ def setup_syslibs(lenv): syslibs.append(lenv['BF_PYTHON_LIB']+'_d') else: syslibs.append(lenv['BF_PYTHON_LIB']) - if lenv['WITH_BF_INTERNATIONAL'] and not lenv['WITH_BF_GETTEXT_STATIC']: - syslibs += Split(lenv['BF_GETTEXT_LIB']) if lenv['WITH_BF_OPENAL']: if not lenv['WITH_BF_STATICOPENAL']: syslibs += Split(lenv['BF_OPENAL_LIB']) @@ -288,8 +295,10 @@ def setup_syslibs(lenv): syslibs += Split(lenv['BF_SNDFILE_LIB']) if lenv['WITH_BF_FFTW3'] and not lenv['WITH_BF_STATICFFTW3']: syslibs += Split(lenv['BF_FFTW3_LIB']) + ''' if lenv['WITH_BF_ELTOPO']: syslibs += Split(lenv['BF_LAPACK_LIB']) + ''' if lenv['WITH_BF_SDL']: syslibs += Split(lenv['BF_SDL_LIB']) if not lenv['WITH_BF_STATICOPENGL']: @@ -315,6 +324,15 @@ def setup_syslibs(lenv): if lenv['WITH_BF_BOOST'] and not lenv['WITH_BF_STATICBOOST']: syslibs += Split(lenv['BF_BOOST_LIB']) + + if lenv['WITH_BF_INTERNATIONAL']: + syslibs += Split(lenv['BF_BOOST_LIB_INTERNATIONAL']) + + if lenv['WITH_BF_CYCLES_OSL'] and not lenv['WITH_BF_STATICOSL']: + syslibs += Split(lenv['BF_OSL_LIB']) + + if lenv['WITH_BF_LLVM'] and not lenv['WITH_BF_STATICLLVM']: + syslibs += Split(lenv['BF_LLVM_LIB']) if not lenv['WITH_BF_STATICJPEG']: syslibs += Split(lenv['BF_JPEG_LIB']) @@ -582,8 +600,8 @@ def AppIt(target=None, source=None, env=None): bldroot = env.Dir('.').abspath binary = env['BINARYKIND'] - sourcedir = bldroot + '/source/darwin/%s.app'%binary - sourceinfo = bldroot + "/source/darwin/%s.app/Contents/Info.plist"%binary + sourcedir = bldroot + '/release/darwin/%s.app' % binary + sourceinfo = bldroot + "/release/darwin/%s.app/Contents/Info.plist"%binary targetinfo = installdir +'/' + "%s.app/Contents/Info.plist"%binary cmd = installdir + '/' +'%s.app'%binary @@ -633,11 +651,19 @@ def AppIt(target=None, source=None, env=None): commands.getoutput(cmd) cmd = 'cp -R %s/kernel/*.h %s/kernel/*.cl %s/kernel/*.cu %s/kernel/' % (croot, croot, croot, cinstalldir) commands.getoutput(cmd) - cmd = 'cp -R %s/kernel/svm %s/util/util_color.h %s/util/util_math.h %s/util/util_transform.h %s/util/util_types.h %s/kernel/' % (croot, croot, croot, croot, croot, cinstalldir) + cmd = 'cp -R %s/kernel/svm %s/kernel/closure %s/util/util_color.h %s/util/util_math.h %s/util/util_transform.h %s/util/util_types.h %s/kernel/' % (croot, croot, croot, croot, croot, croot, cinstalldir) commands.getoutput(cmd) cmd = 'cp -R %s/../intern/cycles/kernel/*.cubin %s/lib/' % (builddir, cinstalldir) commands.getoutput(cmd) + if env['WITH_BF_CYCLES_OSL']: + cmd = 'mkdir %s/shader' % (cinstalldir) + commands.getoutput(cmd) + cmd = 'cp -R %s/kernel/shaders/*.h %s/shader' % (croot, cinstalldir) + commands.getoutput(cmd) + cmd = 'cp -R %s/../intern/cycles/kernel/shaders/*.oso %s/shader' % (builddir, cinstalldir) + commands.getoutput(cmd) + if env['WITH_OSX_STATICPYTHON']: cmd = 'mkdir %s/%s.app/Contents/MacOS/%s/python/'%(installdir,binary, VERSION) commands.getoutput(cmd) @@ -664,7 +690,7 @@ def AppIt(target=None, source=None, env=None): commands.getoutput(cmd) cmd = 'rm -rf %s/set_simulation_threads.app'%(installdir) # first clear omp_num_threads applescript commands.getoutput(cmd) - cmd = 'cp -R %s/source/darwin/set_simulation_threads.app %s/'%(bldroot, installdir) # copy the omp_num_threads applescript + cmd = 'cp -R %s/release/darwin/set_simulation_threads.app %s/'%(bldroot, installdir) # copy the omp_num_threads applescript commands.getoutput(cmd) # extract copy system python, be sure to update other build systems @@ -792,6 +818,20 @@ class BlenderEnvironment(SConsEnvironment): def BlenderLib(self=None, libname=None, sources=None, includes=[], defines=[], libtype='common', priority = 100, compileflags=None, cc_compileflags=None, cxx_compileflags=None, cc_compilerchange=None, cxx_compilerchange=None): global vcp + + # sanity check + # run once in a while to check we dont have duplicates + if 0: + for name, dirs in (("source", sources), ("include", includes)): + files_clean = [os.path.normpath(f) for f in dirs] + files_clean_set = set(files_clean) + if len(files_clean) != len(files_clean_set): + for f in sorted(files_clean_set): + if f != '.' and files_clean.count(f) > 1: + raise Exception("Found duplicate %s %r" % (name, f)) + del name, dirs, files_clean, files_clean_set, f + # end sanity check + if not self or not libname or not sources: print bc.FAIL+'Cannot continue. Missing argument for BuildBlenderLib '+libname+bc.ENDC self.Exit() @@ -871,6 +911,7 @@ class BlenderEnvironment(SConsEnvironment): print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC lenv = self.Clone() lenv.Append(LINKFLAGS = lenv['PLATFORM_LINKFLAGS']) + lenv.Append(LINKFLAGS = lenv['BF_PROGRAM_LINKFLAGS']) if lenv['OURPLATFORM'] in ('win32-mingw', 'win64-mingw', 'linuxcross', 'cygwin', 'linux'): lenv.Replace(LINK = '$CXX') if lenv['OURPLATFORM'] in ('win32-vc', 'cygwin', 'win64-vc'): diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py index 19652bb7851..19f4ac9a1de 100644 --- a/build_files/scons/tools/btools.py +++ b/build_files/scons/tools/btools.py @@ -116,11 +116,11 @@ def validate_arguments(args, bc): 'WITH_BF_TIFF', 'BF_TIFF', 'BF_TIFF_INC', 'BF_TIFF_LIB', 'BF_TIFF_LIBPATH', 'WITH_BF_STATICTIFF', 'BF_TIFF_LIB_STATIC', 'WITH_BF_ZLIB', 'BF_ZLIB', 'BF_ZLIB_INC', 'BF_ZLIB_LIB', 'BF_ZLIB_LIBPATH', 'WITH_BF_STATICZLIB', 'BF_ZLIB_LIB_STATIC', 'WITH_BF_INTERNATIONAL', - 'BF_GETTEXT', 'BF_GETTEXT_INC', 'BF_GETTEXT_LIB', 'WITH_BF_GETTEXT_STATIC', 'BF_GETTEXT_LIB_STATIC', 'BF_GETTEXT_LIBPATH', 'WITH_BF_ICONV', 'BF_ICONV', 'BF_ICONV_INC', 'BF_ICONV_LIB', 'BF_ICONV_LIBPATH', 'WITH_BF_GAMEENGINE', 'WITH_BF_BULLET', 'BF_BULLET', 'BF_BULLET_INC', 'BF_BULLET_LIB', - 'WITH_BF_ELTOPO', 'BF_LAPACK', 'BF_LAPACK_LIB', 'BF_LAPACK_LIBPATH', 'BF_LAPACK_LIB_STATIC', + # 'WITH_BF_ELTOPO', # now only available in a branch + 'BF_LAPACK', 'BF_LAPACK_LIB', 'BF_LAPACK_LIBPATH', 'BF_LAPACK_LIB_STATIC', 'BF_WINTAB', 'BF_WINTAB_INC', 'BF_FREETYPE', 'BF_FREETYPE_INC', 'BF_FREETYPE_LIB', 'BF_FREETYPE_LIBPATH', 'BF_FREETYPE_LIB_STATIC', 'WITH_BF_FREETYPE_STATIC', 'WITH_BF_QUICKTIME', 'BF_QUICKTIME', 'BF_QUICKTIME_INC', 'BF_QUICKTIME_LIB', 'BF_QUICKTIME_LIBPATH', @@ -164,8 +164,10 @@ def validate_arguments(args, bc): 'WITH_BF_CYCLES', 'WITH_BF_CYCLES_CUDA_BINARIES', 'BF_CYCLES_CUDA_NVCC', 'BF_CYCLES_CUDA_NVCC', 'WITH_BF_CYCLES_CUDA_THREADED_COMPILE', 'WITH_BF_OIIO', 'WITH_BF_STATICOIIO', 'BF_OIIO', 'BF_OIIO_INC', 'BF_OIIO_LIB', 'BF_OIIO_LIB_STATIC', 'BF_OIIO_LIBPATH', 'WITH_BF_OCIO', 'WITH_BF_STATICOCIO', 'BF_OCIO', 'BF_OCIO_INC', 'BF_OCIO_LIB', 'BF_OCIO_LIB_STATIC', 'BF_OCIO_LIBPATH', - 'WITH_BF_BOOST', 'WITH_BF_STATICBOOST', 'BF_BOOST', 'BF_BOOST_INC', 'BF_BOOST_LIB', 'BF_BOOST_LIB_STATIC', 'BF_BOOST_LIBPATH', - 'WITH_BF_LIBMV' + 'WITH_BF_BOOST', 'WITH_BF_STATICBOOST', 'BF_BOOST', 'BF_BOOST_INC', 'BF_BOOST_LIB', 'BF_BOOST_LIB_INTERNATIONAL', 'BF_BOOST_LIB_STATIC', 'BF_BOOST_LIBPATH', + 'WITH_BF_LIBMV', + 'WITH_BF_CYCLES_OSL', 'WITH_BF_STATICOSL', 'BF_OSL', 'BF_OSL_INC', 'BF_OSL_LIB', 'BF_OSL_LIBPATH', 'BF_OSL_LIB_STATIC', 'BF_OSL_COMPILER', + 'WITH_BF_LLVM', 'WITH_BF_STATICLLVM', 'BF_LLVM', 'BF_LLVM_LIB', 'BF_LLVM_LIBPATH', 'BF_LLVM_LIB_STATIC', 'BF_PROGRAM_LINKFLAGS' ] # Have options here that scons expects to be lists @@ -179,7 +181,7 @@ def validate_arguments(args, bc): 'BF_DEBUG_CFLAGS', 'BF_DEBUG_CCFLAGS', 'BF_DEBUG_CXXFLAGS', 'C_WARN', 'CC_WARN', 'CXX_WARN', 'LLIBS', 'PLATFORM_LINKFLAGS','MACOSX_ARCHITECTURE', 'MACOSX_SDK_CHECK', 'XCODE_CUR_VER', - 'BF_CYCLES_CUDA_BINARIES_ARCH', + 'BF_CYCLES_CUDA_BINARIES_ARCH', 'BF_PROGRAM_LINKFLAGS', 'MACOSX_DEPLOYMENT_TARGET' ] @@ -381,15 +383,8 @@ def read_opts(env, cfg, args): ('BF_ZLIB_LIBPATH', 'ZLib library path', ''), ('BF_ZLIB_LIB_STATIC', 'ZLib static library', ''), - (BoolVariable('WITH_BF_INTERNATIONAL', 'Use Gettext if true', True)), + (BoolVariable('WITH_BF_INTERNATIONAL', 'Use Boost::locale if true', True)), - ('BF_GETTEXT', 'gettext base path', ''), - ('BF_GETTEXT_INC', 'gettext include path', ''), - ('BF_GETTEXT_LIB', 'gettext library', ''), - (BoolVariable('WITH_BF_GETTEXT_STATIC', 'Use static gettext library if true', False)), - ('BF_GETTEXT_LIB_STATIC', 'static gettext library', ''), - ('BF_GETTEXT_LIBPATH', 'gettext library path', ''), - (BoolVariable('WITH_BF_ICONV', 'Use iconv if true', True)), ('BF_ICONV', 'iconv base path', ''), ('BF_ICONV_INC', 'iconv include path', ''), @@ -399,8 +394,7 @@ def read_opts(env, cfg, args): (BoolVariable('WITH_BF_GAMEENGINE', 'Build with gameengine' , False)), (BoolVariable('WITH_BF_BULLET', 'Use Bullet if true', True)), - - (BoolVariable('WITH_BF_ELTOPO', 'Use Eltopo collision library if true', False)), + # (BoolVariable('WITH_BF_ELTOPO', 'Use Eltopo collision library if true', False)), # this is now only available in a branch ('BF_LAPACK', 'LAPACK base path', ''), ('BF_LAPACK_LIB', 'LAPACK library', ''), ('BF_LAPACK_LIB_STATIC', 'LAPACK library', ''), @@ -508,8 +502,9 @@ def read_opts(env, cfg, args): ('LLIBS', 'Platform libs', []), ('PLATFORM_LINKFLAGS', 'Platform linkflags', []), ('MACOSX_ARCHITECTURE', 'python_arch.zip select', ''), - ('MACOSX_SDK_CHECK', 'detect available OSX sdk`s', ''), - ('XCODE_CUR_VER', 'detect XCode version', ''), + ('MACOSX_SDK_CHECK', 'Detect available OS X SDK`s', ''), + ('XCODE_CUR_VER', 'Detect XCode version', ''), + ('MACOSX_DEPLOYMENT_TARGET', 'Detect OS X target version', ''), (BoolVariable('BF_PROFILE', 'Add profiling information if true', False)), ('BF_PROFILE_CFLAGS', 'C only profiling flags', []), @@ -598,11 +593,30 @@ def read_opts(env, cfg, args): ('BF_BOOST', 'Boost root path', ''), ('BF_BOOST_INC', 'Boost include path', ''), ('BF_BOOST_LIB', 'Boost library', ''), + ('BF_BOOST_LIB_INTERNATIONAL', 'Boost library', ''), ('BF_BOOST_LIBPATH', 'Boost library path', ''), ('BF_BOOST_LIB_STATIC', 'Boost static library', ''), (BoolVariable('WITH_GHOST_XDND', 'Build with drag-n-drop support on Linux platforms using XDND protocol', True)), - (BoolVariable('WITH_BF_COMPOSITOR_LEGACY', 'Enable the legacy compositor', False)) + (BoolVariable('WITH_BF_COMPOSITOR_LEGACY', 'Enable the legacy compositor', False)), + + (BoolVariable('WITH_BF_CYCLES_OSL', 'Build with OSL sypport in Cycles', False)), + (BoolVariable('WITH_BF_STATICOSL', 'Staticly link to OSL', False)), + ('BF_OSL', 'OSL root path', ''), + ('BF_OSL_INC', 'OSL include path', ''), + ('BF_OSL_LIB', 'OSL library', ''), + ('BF_OSL_LIBPATH', 'OSL library path', ''), + ('BF_OSL_LIB_STATIC', 'OSL static library', ''), + ('BF_OSL_COMPILER', 'OSL compiler', ''), + + (BoolVariable('WITH_BF_LLVM', 'Build with LLVM sypport (required for OSL)', False)), + (BoolVariable('WITH_BF_STATICLLVM', 'Staticly link to LLVM', False)), + ('BF_LLVM', 'LLVM root path', ''), + ('BF_LLVM_LIB', 'LLVM library', ''), + ('BF_LLVM_LIBPATH', 'LLVM library path', ''), + ('BF_LLVM_LIB_STATIC', 'LLVM static library', ''), + + ('BF_PROGRAM_LINKFLAGS', 'Link flags applied only to final binaries (blender and blenderplayer, not makesrna/makesdna)', '') ) # end of opts.AddOptions() return localopts @@ -673,7 +687,7 @@ def buildslave(target=None, source=None, env=None): elif bitness == '32bit': platform = 'linux-' + glibc + '-i686' if platform == 'darwin': - platform = 'OSX-' + env['MACOSX_ARCHITECTURE'] + platform = 'OSX-' + env['MACOSX_DEPLOYMENT_TARGET'] + '-' + env['MACOSX_ARCHITECTURE'] branch = env['BUILDBOT_BRANCH'] diff --git a/doc/blender_file_format/BlendFileDnaExporter_25.py b/doc/blender_file_format/BlendFileDnaExporter_25.py index b7b89c89268..837b67c6eed 100755 --- a/doc/blender_file_format/BlendFileDnaExporter_25.py +++ b/doc/blender_file_format/BlendFileDnaExporter_25.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # diff --git a/doc/blender_file_format/BlendFileReader.py b/doc/blender_file_format/BlendFileReader.py index b7091ad8ff5..a4d2f494c5b 100644 --- a/doc/blender_file_format/BlendFileReader.py +++ b/doc/blender_file_format/BlendFileReader.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 # ***** BEGIN GPL LICENSE BLOCK ***** # diff --git a/doc/manpage/blender.1 b/doc/manpage/blender.1 index e7164fcb96b..2addb60c5f7 100644 --- a/doc/manpage/blender.1 +++ b/doc/manpage/blender.1 @@ -1,4 +1,4 @@ -.TH "BLENDER" "1" "October 04, 2012" "Blender Blender 2\&.64 (sub 0)" +.TH "BLENDER" "1" "December 04, 2012" "Blender Blender 2\&.65" .SH NAME blender \- a 3D modelling and rendering package @@ -15,7 +15,7 @@ Use Blender to create TV commercials, to make technical visualizations, business http://www.blender.org .SH OPTIONS -Blender 2.64 (sub 0) +Blender 2.65 Usage: blender [args ...] [file] [args ...] .br .SS "Render Options:" @@ -145,6 +145,10 @@ Playback , only operates this way when not running in background. .br \-j Set frame step to .br + \-s Play from +.br + \-e Play until +.br .IP @@ -344,6 +348,12 @@ Enable debug messages for python Enable debug messages for the event system .br +.TP +.B \-\-debug\-handlers +.br +Enable debug messages for event handling +.br + .TP .B \-\-debug\-wm .br diff --git a/doc/python_api/examples/bmesh.ops.1.py b/doc/python_api/examples/bmesh.ops.1.py new file mode 100644 index 00000000000..abce087ceb3 --- /dev/null +++ b/doc/python_api/examples/bmesh.ops.1.py @@ -0,0 +1,108 @@ +# This script uses bmesh operators to make 2 links of a chain. + +import bpy +import bmesh +import math +import mathutils + +# Make a new BMesh +bm = bmesh.new() + +# Add a circle XXX, should return all geometry created, not just verts. +bmesh.ops.create_circle( + bm, + cap_ends=False, + diameter=0.2, + segments=8) + + +# Spin and deal with geometry on side 'a' +edges_start_a = bm.edges[:] +geom_start_a = bm.verts[:] + edges_start_a +ret = bmesh.ops.spin( + bm, + geom=geom_start_a, + angle=math.radians(180.0), + steps=8, + axis=(1.0, 0.0, 0.0), + cent=(0.0, 1.0, 0.0)) +edges_end_a = [ele for ele in ret["geom_last"] + if isinstance(ele, bmesh.types.BMEdge)] +del ret + + +# Extrude and create geometry on side 'b' +ret = bmesh.ops.extrude_edge_only( + bm, + edges=edges_start_a) +geom_extrude_mid = ret["geom"] +del ret + + +# Collect the edges to spin XXX, 'extrude_edge_only' could return this. +verts_extrude_b = [ele for ele in geom_extrude_mid + if isinstance(ele, bmesh.types.BMVert)] +edges_extrude_b = [ele for ele in geom_extrude_mid + if isinstance(ele, bmesh.types.BMEdge) and ele.is_boundary] +bmesh.ops.translate( + bm, + verts=verts_extrude_b, + vec=(0.0, 0.0, 1.0)) + + +# Create the circle on side 'b' +ret = bmesh.ops.spin( + bm, + geom=verts_extrude_b + edges_extrude_b, + angle=-math.radians(180.0), + steps=8, + axis=(1.0, 0.0, 0.0), + cent=(0.0, 1.0, 1.0)) +edges_end_b = [ele for ele in ret["geom_last"] + if isinstance(ele, bmesh.types.BMEdge)] +del ret + + +# Bridge the resulting edge loops of both spins 'a & b' +bmesh.ops.bridge_loops( + bm, + edges=edges_end_a + edges_end_b) + + +# Now we have made a links of the chain, make a copy and rotate it +# (so this looks something like a chain) + +ret = bmesh.ops.duplicate( + bm, + geom=bm.verts[:] + bm.edges[:] + bm.faces[:]) +geom_dupe = ret["geom"] +verts_dupe = [ele for ele in geom_dupe if isinstance(ele, bmesh.types.BMVert)] +del ret + +# position the new link +bmesh.ops.translate( + bm, + verts=verts_dupe, + vec=(0.0, 0.0, 2.0)) +bmesh.ops.rotate( + bm, + verts=verts_dupe, + cent=(0.0, 1.0, 0.0), + matrix=mathutils.Matrix.Rotation(math.radians(90.0), 3, 'Z')) + +# Done with creating the mesh, simply link it into the scene so we can see it + +# Finish up, write the bmesh into a new mesh +me = bpy.data.meshes.new("Mesh") +bm.to_mesh(me) +bm.free() + + +# Add the mesh to the scene +scene = bpy.context.scene +obj = bpy.data.objects.new("Object", me) +scene.objects.link(obj) + +# Select and make active +scene.objects.active = obj +obj.select = True diff --git a/doc/python_api/rst/bge.logic.rst b/doc/python_api/rst/bge.logic.rst index 260a86f7c59..7d20aa31a36 100644 --- a/doc/python_api/rst/bge.logic.rst +++ b/doc/python_api/rst/bge.logic.rst @@ -254,13 +254,6 @@ General functions :rtype: list [float], len(getSpectrum()) == 512 -.. function:: stopDSP() - - Stops the sound driver using DSP effects. - - Only the fmod sound driver supports this. - DSP can be computationally expensive. - .. function:: getMaxLogicFrame() Gets the maximum number of logic frames per render frame. @@ -331,6 +324,24 @@ General functions .. warning: Not implimented yet +.. function:: getExitKey() + + Gets the key used to exit the game engine + + :return: The key (defaults to :mod:`bge.events.ESCKEY`) + :rtype: int + +.. function:: setExitKey(key) + + Sets the key used to exit the game engine + + :arg key: A key constant from :mod:`bge.events` + :type key: int + +.. function:: NextFrame() + + Render next frame (if Python has control) + ***************** Utility functions ***************** @@ -373,6 +384,10 @@ Utility functions .. function:: PrintGLInfo() Prints GL Extension Info into the console + +.. function:: PrintMemInfo() + + Prints engine statistics into the console ********* Constants @@ -401,6 +416,45 @@ Sensor Status .. data:: KX_SENSOR_ACTIVE .. data:: KX_SENSOR_JUST_DEACTIVATED +--------------- +Armature Sensor +--------------- + +.. _armaturesensor-type: + +See :class:`bge.types.KX_ArmatureSensor.type` + +.. data:: KX_ARMSENSOR_STATE_CHANGED + + Detect that the constraint is changing state (active/inactive) + + :value: 0 + +.. data:: KX_ARMSENSOR_LIN_ERROR_BELOW + + Detect that the constraint linear error is above a threshold + + :value: 1 + +.. data:: KX_ARMSENSOR_LIN_ERROR_ABOVE + + Detect that the constraint linear error is below a threshold + + :value: 2 + +.. data:: KX_ARMSENSOR_ROT_ERROR_BELOW + + Detect that the constraint rotation error is above a threshold + + :value: 3 + +.. data:: KX_ARMSENSOR_ROT_ERROR_ABOVE + + Detect that the constraint rotation error is below a threshold + + :value: 4 + + .. _logic-property-sensor: --------------- @@ -483,6 +537,52 @@ See :class:`bge.types.BL_ActionActuator` .. data:: KX_ACTIONACT_LOOPEND .. data:: KX_ACTIONACT_PROPERTY +----------------- +Armature Actuator +----------------- + + .. _armatureactuator-constants-type: + +See :class:`bge.types.BL_ArmatureActuator.type` + +.. data:: KX_ACT_ARMATURE_RUN + + Just make sure the armature will be updated on the next graphic frame. + This is the only persistent mode of the actuator: + it executes automatically once per frame until stopped by a controller + + :value: 0 + +.. data:: KX_ACT_ARMATURE_ENABLE + + Enable the constraint. + + :value: 1 + +.. data:: KX_ACT_ARMATURE_DISABLE + + Disable the constraint (runtime constraint values are not updated). + + :value: 2 + +.. data:: KX_ACT_ARMATURE_SETTARGET + + Change target and subtarget of constraint. + + :value: 3 + +.. data:: KX_ACT_ARMATURE_SETWEIGHT + + Change weight of constraint (IK only). + + :value: 4 + +.. data:: KX_ACT_ARMATURE_SETINFLUENCE + + Change influence of constraint. + + :value: 5 + ------------------- Constraint Actuator ------------------- @@ -493,31 +593,31 @@ See :class:`bge.types.KX_ConstraintActuator.option` * Applicable to Distance constraint: - .. data:: KX_ACT_CONSTRAINT_NORMAL +.. data:: KX_CONSTRAINTACT_NORMAL Activate alignment to surface - .. data:: KX_ACT_CONSTRAINT_DISTANCE +.. data:: KX_CONSTRAINTACT_DISTANCE Activate distance control - .. data:: KX_ACT_CONSTRAINT_LOCAL +.. data:: KX_CONSTRAINTACT_LOCAL Direction of the ray is along the local axis * Applicable to Force field constraint: - .. data:: KX_ACT_CONSTRAINT_DOROTFH +.. data:: KX_CONSTRAINTACT_DOROTFH Force field act on rotation as well * Applicable to both: - .. data:: KX_ACT_CONSTRAINT_MATERIAL +.. data:: KX_CONSTRAINTACT_MATERIAL Detect material rather than property - .. data:: KX_ACT_CONSTRAINT_PERMANENT +.. data:: KX_CONSTRAINTACT_PERMANENT No deactivation if ray does not hit target @@ -585,27 +685,27 @@ See :class:`bge.types.KX_ConstraintActuator.limit` Set orientation of Z axis -.. data:: KX_ACT_CONSTRAINT_FHNX +.. data:: KX_CONSTRAINTACT_FHNX Set force field along negative X axis -.. data:: KX_ACT_CONSTRAINT_FHNY +.. data:: KX_CONSTRAINTACT_FHNY Set force field along negative Y axis -.. data:: KX_ACT_CONSTRAINT_FHNZ +.. data:: KX_CONSTRAINTACT_FHNZ Set force field along negative Z axis -.. data:: KX_ACT_CONSTRAINT_FHPX +.. data:: KX_CONSTRAINTACT_FHPX Set force field along positive X axis -.. data:: KX_ACT_CONSTRAINT_FHPY +.. data:: KX_CONSTRAINTACT_FHPY Set force field along positive Y axis -.. data:: KX_ACT_CONSTRAINT_FHPZ +.. data:: KX_CONSTRAINTACT_FHPZ Set force field along positive Z axis @@ -708,102 +808,32 @@ See :class:`bge.types.KX_SoundActuator` .. data:: KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP :value: 6 - + +----------------- +Steering Actuator +----------------- + +.. _logic-steering-actuator: + +See :class:`bge.types.KX_SteeringActuator.behavior` + +.. data:: KX_STEERING_SEEK + + :value: 1 + +.. data:: KX_STEERING_FLEE + + :value: 2 + +.. data:: KX_STEERING_PATHFOLLOWING + + :value: 3 + ======= Various ======= -.. _input-status: - ------------- -Input Status ------------- - -See :class:`bge.types.SCA_PythonKeyboard`, :class:`bge.types.SCA_PythonMouse`, :class:`bge.types.SCA_MouseSensor`, :class:`bge.types.SCA_KeyboardSensor` - -.. data:: KX_INPUT_NONE -.. data:: KX_INPUT_JUST_ACTIVATED -.. data:: KX_INPUT_ACTIVE -.. data:: KX_INPUT_JUST_RELEASED - -------------- -Mouse Buttons -------------- - -See :class:`bge.types.SCA_MouseSensor` - -.. data:: KX_MOUSE_BUT_LEFT -.. data:: KX_MOUSE_BUT_MIDDLE -.. data:: KX_MOUSE_BUT_RIGHT - ------- -States ------- - -See :class:`bge.types.KX_StateActuator` - -.. data:: KX_STATE1 -.. data:: KX_STATE2 -.. data:: KX_STATE3 -.. data:: KX_STATE4 -.. data:: KX_STATE5 -.. data:: KX_STATE6 -.. data:: KX_STATE7 -.. data:: KX_STATE8 -.. data:: KX_STATE9 -.. data:: KX_STATE10 -.. data:: KX_STATE11 -.. data:: KX_STATE12 -.. data:: KX_STATE13 -.. data:: KX_STATE14 -.. data:: KX_STATE15 -.. data:: KX_STATE16 -.. data:: KX_STATE17 -.. data:: KX_STATE18 -.. data:: KX_STATE19 -.. data:: KX_STATE20 -.. data:: KX_STATE21 -.. data:: KX_STATE22 -.. data:: KX_STATE23 -.. data:: KX_STATE24 -.. data:: KX_STATE25 -.. data:: KX_STATE26 -.. data:: KX_STATE27 -.. data:: KX_STATE28 -.. data:: KX_STATE29 -.. data:: KX_STATE30 - -.. _state-actuator-operation: - -See :class:`bge.types.KX_StateActuator.operation` - -.. data:: KX_STATE_OP_CLR - - Substract bits to state mask - - :value: 0 - -.. data:: KX_STATE_OP_CPY - - Copy state mask - - :value: 1 - -.. data:: KX_STATE_OP_NEG - - Invert bits to state mask - - :value: 2 - -.. data:: KX_STATE_OP_SET - - Add bits to state mask - - :value: 3 - -.. _Two-D-FilterActuator-mode: - --------- 2D Filter --------- @@ -877,6 +907,227 @@ See :class:`bge.types.KX_StateActuator.operation` .. data:: RAS_2DFILTER_SOBEL :value: 7 + +---------------- +Armature Channel +---------------- +.. _armaturechannel-constants-rotation-mode: + +See :class:`bge.types.BL_ArmatureChannel.rotation_mode` + +.. note: + euler mode are named as in Blender UI but the actual axis order is reversed + +.. data:: ROT_MODE_QUAT + + Use quaternion in rotation attribute to update bone rotation. + + :value: 0 + +.. data:: ROT_MODE_XYZ + + Use euler_rotation and apply angles on bone's Z, Y, X axis successively. + + :value: 1 + +.. data:: ROT_MODE_XZY + + Use euler_rotation and apply angles on bone's Y, Z, X axis successively. + + :value: 2 + +.. data:: ROT_MODE_YXZ + + Use euler_rotation and apply angles on bone's Z, X, Y axis successively. + + :value: 3 + +.. data:: ROT_MODE_YZX + + Use euler_rotation and apply angles on bone's X, Z, Y axis successively. + + :value: 4 + +.. data:: ROT_MODE_ZXY + + Use euler_rotation and apply angles on bone's Y, X, Z axis successively. + + :value: 5 + +.. data:: ROT_MODE_ZYX + + Use euler_rotation and apply angles on bone's X, Y, Z axis successively. + + :value: 6 + + +------------------- +Armature Constraint +------------------- +.. _armatureconstraint-constants-type: + +See :class:`bge.types.BL_ArmatureConstraint.type` + +.. data:: CONSTRAINT_TYPE_TRACKTO +.. data:: CONSTRAINT_TYPE_KINEMATIC +.. data:: CONSTRAINT_TYPE_ROTLIKE +.. data:: CONSTRAINT_TYPE_LOCLIKE +.. data:: CONSTRAINT_TYPE_MINMAX +.. data:: CONSTRAINT_TYPE_SIZELIKE +.. data:: CONSTRAINT_TYPE_LOCKTRACK +.. data:: CONSTRAINT_TYPE_STRETCHTO +.. data:: CONSTRAINT_TYPE_CLAMPTO +.. data:: CONSTRAINT_TYPE_TRANSFORM +.. data:: CONSTRAINT_TYPE_DISTLIMIT + +.. _armatureconstraint-constants-ik-type: + +See :class:`bge.types.BL_ArmatureConstraint.ik_type` + +.. data:: CONSTRAINT_IK_COPYPOSE + + constraint is trying to match the position and eventually the rotation of the target. + + :value: 0 + +.. data:: CONSTRAINT_IK_DISTANCE + + Constraint is maintaining a certain distance to target subject to ik_mode + + :value: 1 + +.. _armatureconstraint-constants-ik-flag: + +See :class:`bge.types.BL_ArmatureConstraint.ik_flag` + +.. data:: CONSTRAINT_IK_FLAG_TIP + + Set when the constraint operates on the head of the bone and not the tail + + :value: 1 + +.. data:: CONSTRAINT_IK_FLAG_ROT + + Set when the constraint tries to match the orientation of the target + + :value: 2 + +.. data:: CONSTRAINT_IK_FLAG_STRETCH + + Set when the armature is allowed to stretch (only the bones with stretch factor > 0.0) + + :value: 16 + +.. data:: CONSTRAINT_IK_FLAG_POS + + Set when the constraint tries to match the position of the target. + + :value: 32 + +.. _armatureconstraint-constants-ik-mode: + +See :class:`bge.types.BL_ArmatureConstraint.ik_mode` + +.. data:: CONSTRAINT_IK_MODE_INSIDE + + The constraint tries to keep the bone within ik_dist of target + + :value: 0 + +.. data:: CONSTRAINT_IK_MODE_OUTSIDE + + The constraint tries to keep the bone outside ik_dist of the target + + :value: 1 + +.. data:: CONSTRAINT_IK_MODE_ONSURFACE + + The constraint tries to keep the bone exactly at ik_dist of the target. + + :value: 2 + +.. _input-status: + +---------------- +Blender Material +---------------- + +.. data:: BL_DST_ALPHA +.. data:: BL_DST_COLOR +.. data:: BL_ONE +.. data:: BL_ONE_MINUS_DST_ALPHA +.. data:: BL_ONE_MINUS_DST_COLOR +.. data:: BL_ONE_MINUS_SRC_ALPHA +.. data:: BL_ONE_MINUS_SRC_COLOR +.. data:: BL_SRC_ALPHA +.. data:: BL_SRC_ALPHA_SATURATE +.. data:: BL_SRC_COLOR +.. data:: BL_ZERO + +------------ +Input Status +------------ + +See :class:`bge.types.SCA_PythonKeyboard`, :class:`bge.types.SCA_PythonMouse`, :class:`bge.types.SCA_MouseSensor`, :class:`bge.types.SCA_KeyboardSensor` + +.. data:: KX_INPUT_NONE +.. data:: KX_INPUT_JUST_ACTIVATED +.. data:: KX_INPUT_ACTIVE +.. data:: KX_INPUT_JUST_RELEASED + +------------- +KX_GameObject +------------- +.. _gameobject-playaction-mode: + +See :class:`bge.types.KX_GameObject.playAction` + +.. data:: KX_ACTION_MODE_PLAY + + Play the action once. + + :value: 0 + +.. data:: KX_ACTION_MODE_LOOP + + Loop the action (repeat it). + + :value: 1 + +.. data:: KX_ACTION_MODE_PING_PONG + + Play the action one direct then back the other way when it has completed. + + :value: 2 + + +------------- +Mouse Buttons +------------- + +See :class:`bge.types.SCA_MouseSensor` + +.. data:: KX_MOUSE_BUT_LEFT +.. data:: KX_MOUSE_BUT_MIDDLE +.. data:: KX_MOUSE_BUT_RIGHT + +-------------------------- +Navigation Mesh Draw Modes +-------------------------- + +.. _navmesh-draw-mode: + +.. data:: RM_WALLS + + Draw only the walls. + +.. data:: RM_POLYS + + Draw only polygons. + +.. data:: RM_TRIS + + Draw triangle mesh. ------ Shader @@ -904,18 +1155,69 @@ Shader .. data:: SHD_TANGENT ----------------- -Blender Material ----------------- +------ +States +------ -.. data:: BL_DST_ALPHA -.. data:: BL_DST_COLOR -.. data:: BL_ONE -.. data:: BL_ONE_MINUS_DST_ALPHA -.. data:: BL_ONE_MINUS_DST_COLOR -.. data:: BL_ONE_MINUS_SRC_ALPHA -.. data:: BL_ONE_MINUS_SRC_COLOR -.. data:: BL_SRC_ALPHA -.. data:: BL_SRC_ALPHA_SATURATE -.. data:: BL_SRC_COLOR -.. data:: BL_ZERO +See :class:`bge.types.KX_StateActuator` + +.. data:: KX_STATE1 +.. data:: KX_STATE2 +.. data:: KX_STATE3 +.. data:: KX_STATE4 +.. data:: KX_STATE5 +.. data:: KX_STATE6 +.. data:: KX_STATE7 +.. data:: KX_STATE8 +.. data:: KX_STATE9 +.. data:: KX_STATE10 +.. data:: KX_STATE11 +.. data:: KX_STATE12 +.. data:: KX_STATE13 +.. data:: KX_STATE14 +.. data:: KX_STATE15 +.. data:: KX_STATE16 +.. data:: KX_STATE17 +.. data:: KX_STATE18 +.. data:: KX_STATE19 +.. data:: KX_STATE20 +.. data:: KX_STATE21 +.. data:: KX_STATE22 +.. data:: KX_STATE23 +.. data:: KX_STATE24 +.. data:: KX_STATE25 +.. data:: KX_STATE26 +.. data:: KX_STATE27 +.. data:: KX_STATE28 +.. data:: KX_STATE29 +.. data:: KX_STATE30 + +.. _state-actuator-operation: + +See :class:`bge.types.KX_StateActuator.operation` + +.. data:: KX_STATE_OP_CLR + + Substract bits to state mask + + :value: 0 + +.. data:: KX_STATE_OP_CPY + + Copy state mask + + :value: 1 + +.. data:: KX_STATE_OP_NEG + + Invert bits to state mask + + :value: 2 + +.. data:: KX_STATE_OP_SET + + Add bits to state mask + + :value: 3 + +.. _Two-D-FilterActuator-mode: diff --git a/doc/python_api/rst/bge.types.rst b/doc/python_api/rst/bge.types.rst index fdaeb61173f..8cf9ccb794c 100644 --- a/doc/python_api/rst/bge.types.rst +++ b/doc/python_api/rst/bge.types.rst @@ -205,6 +205,18 @@ Types :type: boolean + .. attribute:: pos_ticks + + The number of ticks since the last positive pulse (read-only). + + :type: int + + .. attribute:: neg_ticks + + The number of ticks since the last negative pulse (read-only). + + :type: int + .. attribute:: status The status of the sensor (read-only): can be one of :ref:`these constants`. @@ -621,6 +633,71 @@ Types :type: string + +.. class:: KX_SteeringActuator(SCA_IActuator) + + Steering Actuator for navigation. + + .. attribute:: behavior + + The steering behavior to use. + + :type: one of :ref:`these constants ` + + .. attribute:: velocity + + Velocity magnitude + + :type: float + + .. attribute:: acceleration + + Max acceleration + + :type: float + + .. attribute:: turnspeed + + Max turn speed + + :type: float + + .. attribute:: distance + + Relax distance + + :type: float + + .. attribute:: target + + Target object + + :type: :class:`KX_GameObject` + + .. attribute:: navmesh + + Navigation mesh + + :type: :class:`KX_GameObject` + + .. attribute:: selfterminated + + Terminate when target is reached + + :type: boolean + + .. attribute:: enableVisualization + + Enable debug visualization + + :type: boolean + + .. attribute:: pathUpdatePeriod + + Path update period + + :type: int + .. class:: CListValue(CPropValue) This is a list like object used in the game engine internally that behaves similar to a python list in most ways. @@ -682,10 +759,32 @@ Types The id is derived from a memory location and will be different each time the game engine starts. + .. warning:: + + The id can't be stored as an integer in game object properties, as those only have a limited range that the id may not be contained in. Instead an id can be stored as a string game property and converted back to an integer for use in from_id lookups. + .. class:: KX_BlenderMaterial(PyObjectPlus) KX_BlenderMaterial + .. attribute:: shader + + The materials shader. + + :type: :class:`BL_Shader` + + .. attribute:: blending + + Ints used for pixel blending, (src, dst), matching the setBlending method. + + :type: (integer, integer) + + .. attribute:: material_index + + The material's index. + + :type: integer + .. method:: getShader() Returns the material's shader. @@ -743,7 +842,13 @@ Types strength of of the camera following movement. :type: float - + + .. attribute:: axis + + The camera axis (0, 1, 2) for positive ``XYZ``, (3, 4, 5) for negative ``XYZ``. + + :type: int + .. attribute:: min minimum distance to the target object maintained by the actuator. @@ -762,12 +867,6 @@ Types :type: float - .. attribute:: useXY - - axis this actuator is tracking, True=X, False=Y. - - :type: boolean - .. attribute:: object the object this actuator tracks. @@ -988,14 +1087,14 @@ Types The object's parent object. (read-only). :type: :class:`KX_GameObject` or None - - .. attribute:: group_children + + .. attribute:: groupMembers Returns the list of group members if the object is a group object, otherwise None is returned. :type: :class:`CListValue` of :class:`KX_GameObject` or None - .. attribute:: group_parent + .. attribute:: groupObject Returns the group object that the object belongs to or None if the object is not part of a group. @@ -1100,30 +1199,30 @@ Types The object's world space transform matrix. 4x4 Matrix. :type: :class:`mathutils.Matrix` - + .. attribute:: localLinearVelocity - The object's local linear velocity. [x, y, z] - - :type: :class:`mathutils.Vector` - + The object's local linear velocity. [x, y, z] + + :type: :class:`mathutils.Vector` + .. attribute:: worldLinearVelocity The object's world linear velocity. [x, y, z] - - :type: :class:`mathutils.Vector` - + + :type: :class:`mathutils.Vector` + .. attribute:: localAngularVelocity The object's local angular velocity. [x, y, z] - - :type: :class:`mathutils.Vector` - + + :type: :class:`mathutils.Vector` + .. attribute:: worldAngularVelocity The object's world angular velocity. [x, y, z] - - :type: :class:`mathutils.Vector` + + :type: :class:`mathutils.Vector` .. attribute:: timeOffset @@ -1211,6 +1310,13 @@ Types :type: :class:`CListValue` of :class:`KX_GameObject`'s + .. attribute:: life + + The number of seconds until the object ends, assumes 50fps. + (when added with an add object actuator), (read-only). + + :type: float + .. method:: endObject() Delete this object, can be used in place of the EndObject Actuator. @@ -1653,7 +1759,7 @@ Types :arg blendin: the amount of blending between this animation and the previous one on this layer :type blendin: float :arg play_mode: the play mode - :type play_mode: KX_ACTION_MODE_PLAY, KX_ACTION_MODE_LOOP, or KX_ACTION_MODE_PING_PONG + :type play_mode: one of :ref:`these constants ` :arg layer_weight: how much of the previous layer to use for blending (0 = add) :type layer_weight: float :arg ipo_flags: flags for the old IPO behaviors (force, etc) @@ -1810,10 +1916,6 @@ Types :type: list [r, g, b] - .. attribute:: colour - - Synonym for color. - .. attribute:: lin_attenuation The linear component of this light's attenuation. (SPOT and NORMAL lights only). @@ -1898,11 +2000,6 @@ Types :type: integer - .. method:: getNumMaterials() - - :return: number of materials associated with this object - :rtype: integer - .. method:: getMaterialName(matid) Gets the name of the specified material. @@ -1943,11 +2040,6 @@ Types :return: a vertex object. :rtype: :class:`KX_VertexProxy` - .. method:: getNumPolygons() - - :return: The number of polygon in the mesh. - :rtype: integer - .. method:: getPolygon(index) Gets the specified polygon from the mesh. @@ -1957,6 +2049,28 @@ Types :return: a polygon object. :rtype: :class:`PolyProxy` + .. method:: transform(matid, matrix) + + Transforms the vertices of a mesh. + + :arg matid: material index, -1 transforms all. + :type matid: integer + :arg matrix: transformation matrix. + :type matrix: 4x4 matrix [[float]] + + .. method:: transformUV(matid, matrix, uv_index=-1, uv_index_from=-1) + + Transforms the vertices UV's of a mesh. + + :arg matid: material index, -1 transforms all. + :type matid: integer + :arg matrix: transformation matrix. + :type matrix: 4x4 matrix [[float]] + :arg uv_index: optional uv index, -1 for all, otherwise 0 or 1. + :type uv_index: integer + :arg uv_index_from: optional uv index to copy from, -1 to transform the current uv. + :type uv_index_from: integer + .. class:: SCA_MouseSensor(SCA_ISensor) Mouse Sensor logic brick. @@ -2156,6 +2270,52 @@ Types :type: list of strings + +.. class:: KX_FontObject(KX_GameObject) + + TODO. + + +.. class:: KX_NavMeshObject(KX_GameObject) + + Python interface for using and controlling navigation meshes. + + .. method:: findPath(start, goal) + + Finds the path from start to goal points. + + :arg start: the start point + :arg start: 3D Vector + :arg goal: the goal point + :arg start: 3D Vector + :return: a path as a list of points + :rtype: list of points + + .. method:: raycast(start, goal) + + Raycast from start to goal points. + + :arg start: the start point + :arg start: 3D Vector + :arg goal: the goal point + :arg start: 3D Vector + :return: the hit factor + :rtype: float + + .. method:: draw(mode) + + Draws a debug mesh for the navigation mesh. + + :arg mode: the drawing mode (one of :ref:`these constants `) + :arg mode: integer + :return: None + + .. method:: rebuild() + + Rebuild the navigation mesh. + + :return: None + .. class:: KX_ObjectActuator(SCA_IActuator) The object actuator ("Motion Actuator") applies force, torque, displacement, angular displacement, @@ -2309,49 +2469,6 @@ Types :type: boolean -.. class:: KX_PhysicsObjectWrapper(PyObjectPlus) - - KX_PhysicsObjectWrapper - - .. method:: setActive(active) - - Set the object to be active. - - :arg active: set to True to be active - :type active: boolean - - .. method:: setAngularVelocity(x, y, z, local) - - Set the angular velocity of the object. - - :arg x: angular velocity for the x-axis - :type x: float - - :arg y: angular velocity for the y-axis - :type y: float - - :arg z: angular velocity for the z-axis - :type z: float - - :arg local: set to True for local axis - :type local: boolean - - .. method:: setLinearVelocity(x, y, z, local) - - Set the linear velocity of the object. - - :arg x: linear velocity for the x-axis - :type x: float - - :arg y: linear velocity for the y-axis - :type y: float - - :arg z: linear velocity for the z-axis - :type z: float - - :arg local: set to True for local axis - :type local: boolean - .. class:: KX_PolyProxy(SCA_IObject) A polygon holds the index of the vertex forming the poylgon. @@ -2360,7 +2477,7 @@ Types The polygon attributes are read-only, you need to retrieve the vertex proxy if you want to change the vertex settings. - .. attribute:: matname + .. attribute:: material_name The name of polygon material, empty if no material. @@ -2372,13 +2489,13 @@ Types :type: :class:`KX_PolygonMaterial` or :class:`KX_BlenderMaterial` - .. attribute:: texture + .. attribute:: texture_name The texture name of the polygon. :type: string - .. attribute:: matid + .. attribute:: material_id The material index of the polygon, use this to retrieve vertex proxy from mesh proxy. @@ -2609,18 +2726,6 @@ Types :type: boolean - .. attribute:: lightlayer - - Light layers this material affects. - - :type: bitfield. - - .. attribute:: triangle - - Mesh data with this material is triangles. It's probably not safe to change this. - - :type: boolean - .. attribute:: diffuse The diffuse color of the material. black = [0.0, 0.0, 0.0] white = [1.0, 1.0, 1.0]. @@ -2886,8 +2991,8 @@ Types .. method:: instantAddObject() adds the object without needing to calling SCA_PythonController.activate() - - .. note:: Use objectLastCreated to get the newly created object. + + .. note:: Use objectLastCreated to get the newly created object. .. class:: KX_SCA_DynamicActuator(SCA_IActuator) @@ -3113,6 +3218,12 @@ Types :type: list + .. attribute:: gravity + + The scene gravity using the world x, y and z axis. + + :type: list [fx, fy, fz] + .. method:: addObject(object, other, time=0) Adds an object to the scene like the Add Object Actuator would. @@ -3154,6 +3265,10 @@ Types Return the value matching key, or the default value if its not found. :return: The key value or a default. + .. method:: drawObstacleSimulation() + + Draw debug visualization of obstacle simulation. + .. class:: KX_SceneActuator(SCA_IActuator) Scene Actuator logic brick. @@ -3200,13 +3315,7 @@ Types Sound Actuator. - The :data:`startSound`, :data:`pauseSound` and :data:`stopSound` do not requirethe actuator to be activated - they act instantly provided that the actuator has been activated once at least. - - .. attribute:: fileName - - The filename of the sound this actuator plays. - - :type: string + The :data:`startSound`, :data:`pauseSound` and :data:`stopSound` do not require the actuator to be activated - they act instantly provided that the actuator has been activated once at least. .. attribute:: volume @@ -3214,48 +3323,102 @@ Types :type: float + .. attribute:: time + + The current position in the audio stream (in seconds). + + :type: float + .. attribute:: pitch The pitch of the sound. :type: float - .. attribute:: rollOffFactor - - The roll off factor. Rolloff defines the rate of attenuation as the sound gets further away. - - :type: float - - .. attribute:: looping - - The loop mode of the actuator. - - :type: integer - - .. attribute:: position - - The position of the sound as a list: [x, y, z]. - - :type: float array - - .. attribute:: velocity - - The velocity of the emitter as a list: [x, y, z]. The relative velocity to the observer determines the pitch. List of 3 floats: [x, y, z]. - - :type: float array - - .. attribute:: orientation - - The orientation of the sound. When setting the orientation you can also use quaternion [float, float, float, float] or euler angles [float, float, float]. - - :type: 3x3 matrix [[float]] - .. attribute:: mode The operation mode of the actuator. Can be one of :ref:`these constants` :type: integer + .. attribute:: sound + + The sound the actuator should play. + + :type: Audaspace factory + + .. attribute:: is3D + + Whether or not the actuator should be using 3D sound. (read-only) + + :type: boolean + + .. attribute:: volume_maximum + + The maximum gain of the sound, no matter how near it is. + + :type: float + + .. attribute:: volume_minimum + + The minimum gain of the sound, no matter how far it is away. + + :type: float + + .. attribute:: distance_reference + + The distance where the sound has a gain of 1.0. + + :type: float + + .. attribute:: distance_maximum + + The maximum distance at which you can hear the sound. + + :type: float + + .. attribute:: attenuation + + The influence factor on volume depending on distance. + + :type: float + + .. attribute:: cone_angle_inner + + The angle of the inner cone. + + :type: float + + .. attribute:: cone_angle_outer + + The angle of the outer cone. + + :type: float + + .. attribute:: cone_volume_outer + + The gain outside the outer cone (the gain in the outer cone will be interpolated between this value and the normal gain in the inner cone). + + :type: float + + .. method:: startSound() + + Starts the sound. + + :return: None + + .. method:: pauseSound() + + Pauses the sound. + + :return: None + + .. method:: stopSound() + + Stops the sound. + + :return: None + .. class:: KX_StateActuator(SCA_IActuator) State actuator changes the state mask of parent object. @@ -3472,7 +3635,7 @@ Types Whether or not the character is on the ground. (read-only) - :type: boolean + :type: boolean .. attribute:: gravity @@ -3518,10 +3681,6 @@ Types Black = [0.0, 0.0, 0.0, 1.0], White = [1.0, 1.0, 1.0, 1.0] - .. attribute:: colour - - Synonym for color. - .. attribute:: x The x coordinate of the vertex. @@ -4242,24 +4401,6 @@ Types :type: integer - .. method:: setSeed(seed) - - Sets the seed of the random number generator. - - If the seed is 0, the generator will produce the same value on every call. - - :type seed: integer - - .. method:: getSeed() - - :return: The initial seed of the generator. Equal seeds produce equal random series. - :rtype: integer - - .. method:: getLastDraw() - - :return: The last random number generated. - :rtype: integer - .. class:: SCA_XNORController(SCA_IController) An XNOR controller activates when all linked sensors are the same (activated or inative). @@ -4327,7 +4468,7 @@ Types .. attribute:: projection_matrix This camera's 4x4 projection matrix. - + .. note:: This is the identity matrix prior to rendering the first frame (any Python done on frame 1). @@ -4580,48 +4721,6 @@ Types Armature Actuators change constraint condition on armatures. - .. _armatureactuator-constants-type: - - Constants related to :data:`~bge.types.BL_ArmatureActuator.type` - - .. data:: KX_ACT_ARMATURE_RUN - - Just make sure the armature will be updated on the next graphic frame. - This is the only persistent mode of the actuator: - it executes automatically once per frame until stopped by a controller - - :value: 0 - - .. data:: KX_ACT_ARMATURE_ENABLE - - Enable the constraint. - - :value: 1 - - .. data:: KX_ACT_ARMATURE_DISABLE - - Disable the constraint (runtime constraint values are not updated). - - :value: 2 - - .. data:: KX_ACT_ARMATURE_SETTARGET - - Change target and subtarget of constraint. - - :value: 3 - - .. data:: KX_ACT_ARMATURE_SETWEIGHT - - Change weight of constraint (IK only). - - :value: 4 - - .. data:: KX_ACT_ARMATURE_SETINFLUENCE - - Change influence of constraint. - - :value: 5 - .. attribute:: type The type of action that the actuator executes when it is active. @@ -4676,40 +4775,6 @@ Types Armature sensor detect conditions on armatures. - .. _armaturesensor-type: - - Constants related to :data:`type` - - .. data:: KX_ARMSENSOR_STATE_CHANGED - - Detect that the constraint is changing state (active/inactive) - - :value: 0 - - .. data:: KX_ARMSENSOR_LIN_ERROR_BELOW - - Detect that the constraint linear error is above a threshold - - :value: 1 - - .. data:: KX_ARMSENSOR_LIN_ERROR_ABOVE - - Detect that the constraint linear error is below a threshold - - :value: 2 - - .. data:: KX_ARMSENSOR_ROT_ERROR_BELOW - - Detect that the constraint rotation error is above a threshold - - :value: 3 - - .. data:: KX_ARMSENSOR_ROT_ERROR_ABOVE - - Detect that the constraint rotation error is below a threshold - - :value: 4 - .. attribute:: type The type of measurement that the sensor make when it is active. @@ -4744,87 +4809,6 @@ Types Not all armature constraints are supported in the GE. - .. _armatureconstraint-constants-type: - - Constants related to :data:`type` - - .. data:: CONSTRAINT_TYPE_TRACKTO - .. data:: CONSTRAINT_TYPE_KINEMATIC - .. data:: CONSTRAINT_TYPE_ROTLIKE - .. data:: CONSTRAINT_TYPE_LOCLIKE - .. data:: CONSTRAINT_TYPE_MINMAX - .. data:: CONSTRAINT_TYPE_SIZELIKE - .. data:: CONSTRAINT_TYPE_LOCKTRACK - .. data:: CONSTRAINT_TYPE_STRETCHTO - .. data:: CONSTRAINT_TYPE_CLAMPTO - .. data:: CONSTRAINT_TYPE_TRANSFORM - .. data:: CONSTRAINT_TYPE_DISTLIMIT - - .. _armatureconstraint-constants-ik-type: - - Constants related to :data:`ik_type` - - .. data:: CONSTRAINT_IK_COPYPOSE - - constraint is trying to match the position and eventually the rotation of the target. - - :value: 0 - - .. data:: CONSTRAINT_IK_DISTANCE - - Constraint is maintaining a certain distance to target subject to ik_mode - - :value: 1 - - .. _armatureconstraint-constants-ik-flag: - - Constants related to :data:`ik_flag` - - .. data:: CONSTRAINT_IK_FLAG_TIP - - Set when the constraint operates on the head of the bone and not the tail - - :value: 1 - - .. data:: CONSTRAINT_IK_FLAG_ROT - - Set when the constraint tries to match the orientation of the target - - :value: 2 - - .. data:: CONSTRAINT_IK_FLAG_STRETCH - - Set when the armature is allowed to stretch (only the bones with stretch factor > 0.0) - - :value: 16 - - .. data:: CONSTRAINT_IK_FLAG_POS - - Set when the constraint tries to match the position of the target. - - :value: 32 - - .. _armatureconstraint-constants-ik-mode: - - Constants related to :data:`ik_mode` - - .. data:: CONSTRAINT_IK_MODE_INSIDE - - The constraint tries to keep the bone within ik_dist of target - - :value: 0 - - .. data:: CONSTRAINT_IK_MODE_OUTSIDE - - The constraint tries to keep the bone outside ik_dist of the target - - :value: 1 - - .. data:: CONSTRAINT_IK_MODE_ONSURFACE - - The constraint tries to keep the bone exactly at ik_dist of the target. - - :value: 2 .. attribute:: type @@ -4943,16 +4927,6 @@ Types Proxy to armature pose channel. Allows to read and set armature pose. The attributes are identical to RNA attributes, but mostly in read-only mode. - See :data:`rotation_mode` - - .. data:: PCHAN_ROT_QUAT - .. data:: PCHAN_ROT_XYZ - .. data:: PCHAN_ROT_XZY - .. data:: PCHAN_ROT_YXZ - .. data:: PCHAN_ROT_YZX - .. data:: PCHAN_ROT_ZXY - .. data:: PCHAN_ROT_ZYX - .. attribute:: name channel name (=bone name), read-only. @@ -5086,17 +5060,7 @@ Types Method of updating the bone rotation, read-write. - :type: integer - - Use the following constants (euler mode are named as in Blender UI but the actual axis order is reversed). - - * PCHAN_ROT_QUAT(0) : use quaternioin in rotation attribute to update bone rotation - * PCHAN_ROT_XYZ(1) : use euler_rotation and apply angles on bone's Z, Y, X axis successively - * PCHAN_ROT_XZY(2) : use euler_rotation and apply angles on bone's Y, Z, X axis successively - * PCHAN_ROT_YXZ(3) : use euler_rotation and apply angles on bone's Z, X, Y axis successively - * PCHAN_ROT_YZX(4) : use euler_rotation and apply angles on bone's X, Z, Y axis successively - * PCHAN_ROT_ZXY(5) : use euler_rotation and apply angles on bone's Y, X, Z axis successively - * PCHAN_ROT_ZYX(6) : use euler_rotation and apply angles on bone's X, Y, Z axis successively + :type: integer (one of :ref:`these constants `) .. attribute:: channel_matrix diff --git a/doc/python_api/rst/bgl.rst b/doc/python_api/rst/bgl.rst index 9f7817c6fa2..fc4524b1213 100644 --- a/doc/python_api/rst/bgl.rst +++ b/doc/python_api/rst/bgl.rst @@ -689,7 +689,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources. Return the specified pixel map - .. seealso:: `OpenGL Docs `_ + .. seealso:: `OpenGL Docs `_ :type map: Enumerated constant :arg map: Specifies the name of the pixel map to return. @@ -701,7 +701,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources. Return the polygon stipple pattern - .. seealso:: `OpenGL Docs `_ + .. seealso:: `OpenGL Docs `_ :type mask: :class:`bgl.Buffer` object I{type GL_BYTE} :arg mask: Returns the stipple pattern. The initial value is all 1's. @@ -824,13 +824,25 @@ OpenGL}" and the online NeHe tutorials are two of the best resources. Set the current color index - .. seealso:: `OpenGL Docs `_ + .. seealso:: `OpenGL Docs `_ :type c: :class:`bgl.Buffer` object. Depends on function prototype. :arg c: Specifies a pointer to a one element array that contains the new value for the current color index. +.. function:: glIndexMask(mask): + + Control the writing of individual bits in the color index buffers + + .. seealso:: `OpenGL Docs `_ + + :type mask: int + :arg mask: Specifies a bit mask to enable and disable the writing of individual bits + in the color index buffers. + Initially, the mask is all 1's. + + .. function:: glInitNames(): Initialize the name stack @@ -1510,7 +1522,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources. :arg mode: Specifies a symbolic value representing a shading technique. -.. function:: glStencilFuc(func, ref, mask): +.. function:: glStencilFunc(func, ref, mask): Set function and reference value for stencil testing @@ -1835,7 +1847,238 @@ OpenGL}" and the online NeHe tutorials are two of the best resources. :arg objx, objy, objz: Return the computed object coordinates. -class Buffer: +.. function:: glUseProgram(program): + + Installs a program object as part of current rendering state + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies the handle of the program object whose executables are to be used as part of current rendering state. + + +.. function:: glValidateProgram(program): + + Validates a program object + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies the handle of the program object to be validated. + + +.. function:: glLinkProgram(program): + + Links a program object. + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies the handle of the program object to be linked. + + +.. function:: glActiveTexture(texture): + + Select active texture unit. + + .. seealso:: `OpenGL Docs `_ + + :type texture: int + :arg texture: Constant in ``GL_TEXTURE0`` 0 - 8 + + +.. function:: glAttachShader(program, shader): + + Attaches a shader object to a program object. + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies the program object to which a shader object will be attached. + :type shader: int + :arg shader: Specifies the shader object that is to be attached. + + +.. function:: glCompileShader(shader): + + Compiles a shader object. + + .. seealso:: `OpenGL Docs `_ + + :type shader: int + :arg shader: Specifies the shader object to be compiled. + + +.. function:: glCreateProgram(): + + Creates a program object + + .. seealso:: `OpenGL Docs `_ + + :rtype: int + :return: The new program or zero if an error occurs. + + +.. function:: glCreateShader(shaderType): + + Creates a shader object. + + .. seealso:: `OpenGL Docs `_ + + :type shaderType: Specifies the type of shader to be created. + Must be one of ``GL_VERTEX_SHADER``, + ``GL_TESS_CONTROL_SHADER``, + ``GL_TESS_EVALUATION_SHADER``, + ``GL_GEOMETRY_SHADER``, + or ``GL_FRAGMENT_SHADER``. + :arg shaderType: + :rtype: int + :return: 0 if an error occurs. + + +.. function:: glDeleteProgram(program): + + Deletes a program object. + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies the program object to be deleted. + + +.. function:: glDeleteShader(shader): + + Deletes a shader object. + + .. seealso:: `OpenGL Docs `_ + + :type shader: int + :arg shader: Specifies the shader object to be deleted. + + +.. function:: glDetachShader(program, shader): + + Detaches a shader object from a program object to which it is attached. + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies the program object from which to detach the shader object. + :type shader: int + :arg shader: pecifies the program object from which to detach the shader object. + + +.. function:: glGetAttachedShaders(program, maxCount, count, shaders): + + Returns the handles of the shader objects attached to a program object. + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies the program object to be queried. + :type maxCount: int + :arg maxCount: Specifies the size of the array for storing the returned object names. + :type count: :class:`bgl.Buffer` int buffer. + :arg count: Returns the number of names actually returned in objects. + :type shaders: :class:`bgl.Buffer` int buffer. + :arg shaders: Specifies an array that is used to return the names of attached shader objects. + + +.. function:: glGetProgramInfoLog(program, maxLength, length, infoLog): + + Returns the information log for a program object. + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies the program object whose information log is to be queried. + :type maxLength: int + :arg maxLength: Specifies the size of the character buffer for storing the returned information log. + :type length: :class:`bgl.Buffer` int buffer. + :arg length: Returns the length of the string returned in **infoLog** (excluding the null terminator). + :type infoLog: :class:`bgl.Buffer` char buffer. + :arg infoLog: Specifies an array of characters that is used to return the information log. + + +.. function:: glGetShaderInfoLog(program, maxLength, length, infoLog): + + Returns the information log for a shader object. + + .. seealso:: `OpenGL Docs `_ + + :type shader: int + :arg shader: Specifies the shader object whose information log is to be queried. + :type maxLength: int + :arg maxLength: Specifies the size of the character buffer for storing the returned information log. + :type length: :class:`bgl.Buffer` int buffer. + :arg length: Returns the length of the string returned in **infoLog** (excluding the null terminator). + :type infoLog: :class:`bgl.Buffer` char buffer. + :arg infoLog: Specifies an array of characters that is used to return the information log. + + +.. function:: glGetProgramiv(program, pname, params): + + Returns a parameter from a program object. + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies the program object to be queried. + :type pname: int + :arg pname: Specifies the object parameter. + :type params: :class:`bgl.Buffer` int buffer. + :arg params: Returns the requested object parameter. + + +.. function:: glIsShader(shader): + + Determines if a name corresponds to a shader object. + + .. seealso:: `OpenGL Docs `_ + + :type shader: int + :arg shader: Specifies a potential shader object. + + +.. function:: glIsProgram(program): + + Determines if a name corresponds to a program object + + .. seealso:: `OpenGL Docs `_ + + :type program: int + :arg program: Specifies a potential program object. + + +.. function:: glGetShaderSource(shader, bufSize, length, source): + + Returns the source code string from a shader object + + .. seealso:: `OpenGL Docs `_ + + :type shader: int + :arg shader: Specifies the shader object to be queried. + :type bufSize: int + :arg bufSize: Specifies the size of the character buffer for storing the returned source code string. + :type length: :class:`bgl.Buffer` int buffer. + :arg length: Returns the length of the string returned in source (excluding the null terminator). + :type source: :class:`bgl.Buffer` char. + :arg source: Specifies an array of characters that is used to return the source code string. + + +.. function:: glShaderSource(shader, shader_string): + + Replaces the source code in a shader object. + + .. seealso:: `OpenGL Docs `_ + + :type shader: int + :arg shader: Specifies the handle of the shader object whose source code is to be replaced. + :type shader_string: string + :arg shader_string: The shader string. + + +.. class:: Buffer The Buffer object is simply a block of memory that is delineated and initialized by the user. Many OpenGL functions return data to a C-style pointer, however, because this diff --git a/doc/python_api/rst/gpu.rst b/doc/python_api/rst/gpu.rst index 68dc30b6143..a225829b3e8 100644 --- a/doc/python_api/rst/gpu.rst +++ b/doc/python_api/rst/gpu.rst @@ -262,10 +262,16 @@ The calculation of some of the uniforms is based on matrices available in the sc .. data:: GPU_DYNAMIC_SAMPLER_2DSHADOW + The uniform is an float representing the bumpmap scaling. + + :value: 14 + +.. data:: GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE + The uniform is an integer representing a shadow buffer corresponding to a lamp casting shadow. - :value: 14 + :value: 15 GLSL attribute type diff --git a/doc/python_api/rst/include__bmesh.rst b/doc/python_api/rst/include__bmesh.rst index a55bf71b60f..ef4a1c272b4 100644 --- a/doc/python_api/rst/include__bmesh.rst +++ b/doc/python_api/rst/include__bmesh.rst @@ -4,6 +4,13 @@ ./blender.bin -b -noaudio -P doc/python_api/sphinx_doc_gen.py -- --partial bmesh* ; cd doc/python_api ; sphinx-build sphinx-in sphinx-out ; cd ../../ +Submodules: + +* :mod:`bmesh.ops` +* :mod:`bmesh.types` +* :mod:`bmesh.utils` + + Intro ----- @@ -35,7 +42,6 @@ For an overview of BMesh data types and how they reference each other see: TODO items are... * add access to BMesh **walkers** - * add api for calling BMesh operators (unrelated to bpy.ops) * add custom-data manipulation functions add/remove/rename. Example Script diff --git a/doc/python_api/rst/info_api_reference.rst b/doc/python_api/rst/info_api_reference.rst new file mode 100644 index 00000000000..ddee46dce11 --- /dev/null +++ b/doc/python_api/rst/info_api_reference.rst @@ -0,0 +1,305 @@ + +******************* +Reference API Usage +******************* + +Blender has many interlinking data types which have an auto-generated reference api which often has the information +you need to write a script, but can be difficult to use. + +This document is designed to help you understand how to use the reference api. + + +Reference API Scope +=================== + +The reference API covers :mod:`bpy.types`, which stores types accessed via :mod:`bpy.context` - *The user context* +or :mod:`bpy.data` - *Blend file data*. + +Other modules such as :mod:`bge`, :mod:`bmesh` and :mod:`aud` are not using Blenders data API +so this document doesn't apply to those modules. + + +Data Access +=========== + +The most common case for using the reference API is to find out how to access data in the blend file. + +Before going any further its best to be aware of ID Data-Blocks in Blender since you will often find properties +relative to them. + + +ID Data +------- + +ID Data-Blocks are used in Blender as top-level data containers. + +From the user interface this isn't so obvious, but when developing you need to know about ID Data-Blocks. + +ID data types include Scene, Group, Object, Mesh, Screen, World, Armature, Image and Texture. +for a full list see the sub-classes of :class:`bpy.types.ID` + +Here are some characteristics ID Data-Blocks share. + +- ID's are blend file data, so loading a new blend file reloads an entire new set of Data-Blocks. +- ID's can be accessed in Python from ``bpy.data.*`` +- Each data-block has a unique ``.name`` attribute, displayed in the interface. +- Animation data is stored in ID's ``.animation_data``. +- ID's are the only data types that can be linked between blend files. +- ID's can be added/copied and removed via Python. +- ID's have their own garbage-collection system which frees unused ID's when saving. +- When a data-block has a reference to some external data, this is typically an ID Data-Block. + + +Simple Data Access +------------------ + +Lets start with a simple case, say you wan't a python script to adjust the objects location. + +Start by finding this setting in the interface ``Properties Window -> Object -> Transform -> Location`` + +From the button you can right click and select **Online Python Reference**, this will link you to: +:class:`bpy.types.Object.location` + +Being an API reference, this link often gives little more information then the tool-tip, though some of the pages +include examples (normally at the top of the page). + +At this point you may say *Now what?* - you know that you have to use ``.location`` and that its an array of 3 floats +but you're still left wondering how to access this in a script. + +So the next step is to find out where to access objects, go down to the bottom of the page to the **References** +section, for objects there are many references, but one of the most common places to access objects is via the context. + +It's easy to be overwhelmed at this point since there ``Object`` get referenced in so many places - modifiers, +functions, textures and constraints. + +But if you want to access any data the user has selected +you typically only need to check the :mod:`bpy.context` references. + +Even then, in this case there are quite a few though if you read over these - most are mode specific. +If you happen to be writing a tool that only runs in weight paint mode, then using ``weight_paint_object`` +would be appropriate. +However to access an item the user last selected, look for the ``active`` members, +Having access to a single active member the user selects is a convention in Blender: eg. ``active_bone``, +``active_pose_bone``, ``active_node`` ... and in this case we can use - ``active_object``. + + +So now we have enough information to find the location of the active object. + +.. code-block:: python + + bpy.context.active_object.location + +You can type this into the python console to see the result. + +The other common place to access objects in the reference is :class:`bpy.types.BlendData.objects`. + +.. note:: + + This is **not** listed as :mod:`bpy.data.objects`, + this is because :mod:`bpy.data` is an instance of the :class:`bpy.types.BlendData` class, + so the documentation points there. + + +With :mod:`bpy.data.objects`, this is a collection of objects so you need to access one of its members. + +.. code-block:: python + + bpy.data.objects["Cube"].location + + +Nested Properties +----------------- + +The previous example is quite straightforward because ``location`` is a property of ``Object`` which can be accessed +from the context directly. + +Here are some more complex examples: + +.. code-block:: python + + # access a render layers samples + bpy.context.scene.render.layers["RenderLayer"].samples + + # access to the current weight paint brush size + bpy.context.tool_settings.weight_paint.brush.size + + # check if the window is fullscreen + bpy.context.window.screen.show_fullscreen + + +As you can see there are times when you want to access data which is nested +in a way that causes you to go through a few indirections. + +The properties are arranged to match how data is stored internally (in blenders C code) which is often logical but +not always quite what you would expect from using Blender. + +So this takes some time to learn, it helps you understand how data fits together in Blender which is important +to know when writing scripts. + + +When starting out scripting you will often run into the problem where you're not sure how to access the data you want. + +There are a few ways to do this. + +- Use the Python console's auto-complete to inspect properties. *This can be hit-and-miss but has the advantage + that you can easily see the values of properties and assign them to interactively see the results.* + +- Copy the Data-Path from the user interface. *Explained further in :ref:`Copy Data Path `* + +- Using the documentation to follow references. *Explained further in :ref:`Indirect Data Access `* + + +.. _info_data_path_copy + +Copy Data Path +-------------- + +Blender can compute the Python string to a property which is shown in the tool-tip, on the line below ``Python: ...``, +This saves having to use the API reference to click back up the references to find where data is accessed from. + +There is a user-interface feature to copy the data-path which gives the path from an :class:`bpy.types.ID` data-block, +to its property. + +To see how this works we'll get the path to the Subdivision-Surface modifiers subdivision setting. + +Start with the default scene and select the **Modifiers** tab, then add a **Subdivision-Surface** modifier to the cube. + +Now hover your mouse over the button labeled **View**, The tool-tip includes :class:`bpy.types.SubsurfModifier.levels` +but we want the path from the object to this property. + +Note that the text copied won't include the ``bpy.data.collection["name"].`` component since its assumed that +you won't be doing collection look-ups on every access and typically you'll want to use the context rather +then access each :class:`bpy.types.ID` instance by name. + + +Type in the ID path into a Python console :mod:`bpy.context.active_object`. Include the trailing dot and don't hit "enter", yet. + +Now right-click on the button and select **Copy Data Path**, then paste the result into the console. + +So now you should have the answer: + +.. code-block:: python + + bpy.context.active_object.modifiers["Subsurf"].levels + +Hit "enter" and you'll get the current value of 1. Now try changing the value to 2: + +.. code-block:: python + + bpy.context.active_object.modifiers["Subsurf"].levels = 2 + +You can see the value update in the Subdivision-Surface modifier's UI as well as the cube. + + +.. _info_data_path_indirect + +Indirect Data Access +-------------------- + +For this example we'll go over something more involved, showing the steps to access the active sculpt brushes texture. + +Lets say we want to access the texture of a brush via Python, to adjust its ``contrast`` for example. + +- Start in the default scene and enable 'Sculpt' mode from the 3D-View header. + +- From the toolbar expand the **Texture** panel and add a new texture. + + *Notice the texture button its self doesn't have very useful links (you can check the tool-tips).* + +- The contrast setting isn't exposed in the sculpt toolbar, so view the texture in the properties panel... + + - In the properties button select the Texture context. + + - Select the Brush icon to show the brush texture. + + - Expand the **Colors** panel to locate the **Contrast** button. + +- Right click on the contrast button and select **Online Python Reference** This takes you to ``bpy.types.Texture.contrast`` + +- Now we can see that ``contrast`` is a property of texture, so next we'll check on how to access the texture from the brush. + +- Check on the **References** at the bottom of the page, sometimes there are many references, and it may take + some guess work to find the right one, but in this case its obviously ``Brush.texture``. + + *Now we know that the texture can be accessed from* ``bpy.data.brushes["BrushName"].texture`` + *but normally you won't want to access the brush by name, so we'll see now to access the active brush instead.* + +- So the next step is to check on where brushes are accessed from via the **References**. + In this case there is simply ``bpy.context.brush`` which is all we need. + + +Now you can use the Python console to form the nested properties needed to access brush textures contrast, +logically we now know. + +*Context -> Brush -> Texture -> Contrast* + +Since the attribute for each is given along the way we can compose the data path in the python console: + +.. code-block:: python + + bpy.context.brush.texture.contrast + + +There can be multiple ways to access the same data, which you choose often depends on the task. + +An alternate path to access the same setting is... + +.. code-block:: python + + bpy.context.sculpt.brush.texture.contrast + +Or access the brush directly... + +.. code-block:: python + + bpy.data.brushes["BrushName"].texture.contrast + + +If you are writing a user tool normally you want to use the :mod:`bpy.context` since the user normally expects +the tool to operate on what they have selected. + +For automation you are more likely to use :mod:`bpy.data` since you want to be able to access specific data and manipulate +it, no matter what the user currently has the view set at. + + +Operators +========= + +Most key-strokes and buttons in Blender call an operator which is also exposed to python via :mod:`bpy.ops`, + +To see the Python equivalent hover your mouse over the button and see the tool-tip, +eg ``Python: bpy.ops.render.render()``, +If there is no tool-tip or the ``Python:`` line is missing then this button is not using an operator and +can't be accessed from Python. + + +If you want to use this in a script you can press :kbd:`Control-C` while your mouse is over the button to copy it to the +clipboard. + +You can also right click on the button and view the **Online Python Reference**, this mainly shows arguments and +their defaults however operators written in Python show their file and line number which may be useful if you +are interested to check on the source code. + +.. note:: + + Not all operators can be called usefully from Python, for more on this see :ref:`using operators `. + + +Info View +--------- + +Blender records operators you run and displays them in the **Info** space. +This is located above the file-menu which can be dragged down to display its contents. + +Select the **Script** screen that comes default with Blender to see its output. +You can perform some actions and see them show up - delete a vertex for example. + +Each entry can be selected (Right-Mouse-Button), then copied :kbd:`Control-C`, usually to paste in the text editor or python console. + +.. note:: + + Not all operators get registered for display, + zooming the view for example isn't so useful to repeat so its excluded from the output. + + To display *every* operator that runs see :ref:`Show All Operators ` + diff --git a/doc/python_api/rst/info_gotcha.rst b/doc/python_api/rst/info_gotcha.rst index 1d561216b52..34145c2ac49 100644 --- a/doc/python_api/rst/info_gotcha.rst +++ b/doc/python_api/rst/info_gotcha.rst @@ -5,6 +5,8 @@ Gotchas This document attempts to help you work with the Blender API in areas that can be troublesome and avoid practices that are known to give instability. +.. _using_operators: + Using Operators =============== @@ -118,18 +120,19 @@ If you insist - yes its possible, but scripts that use this hack wont be conside bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1) -I can't edit the mesh in edit-mode! -=================================== +Modes and Mesh Access +===================== -Blender's EditMesh is an internal data structure (not saved and not exposed to python), this gives the main annoyance that you need to exit edit-mode to edit the mesh from python. +When working with mesh data you may run into the problem where a script fails to run as expected in edit-mode. This is caused by edit-mode having its own data which is only written back to the mesh when exiting edit-mode. -The reason we have not made much attempt to fix this yet is because we -will likely move to BMesh mesh API eventually, so any work on the API now will be wasted effort. +A common example is that exporters may access a mesh through ``obj.data`` (a :class:`bpy.types.Mesh`) but the user is in edit-mode, where the mesh data is available but out of sync with the edit mesh. -With the BMesh API we may expose mesh data to python so we can -write useful tools in python which are also fast to execute while in edit-mode. +In this situation you can... -For the time being this limitation just has to be worked around but we're aware its frustrating needs to be addressed. +* Exit edit-mode before running the tool. +* Explicitly update the mesh by calling :class:`bmesh.types.BMesh.to_mesh`. +* Modify the script to support working on the edit-mode data directly, see: :mod:`bmesh.from_edit_mesh`. +* Report the context as incorrect and only allow the script to run outside edit-mode. .. _info_gotcha_mesh_faces: @@ -311,7 +314,7 @@ Naming Limitations A common mistake is to assume newly created data is given the requested name. -This can cause bugs when you add some data (normally imported) and then reference it later by name. +This can cause bugs when you add some data (normally imported) then reference it later by name. .. code-block:: python @@ -493,7 +496,7 @@ Heres an example of threading supported by Blender: t.join() -This an example of a timer which runs many times a second and moves the default cube continuously while Blender runs (Unsupported). +This an example of a timer which runs many times a second and moves the default cube continuously while Blender runs **(Unsupported)**. .. code-block:: python @@ -516,7 +519,7 @@ So far, no work has gone into making Blender's python integration thread safe, s .. note:: - Pythons threads only allow co-currency and won't speed up your scripts on multi-processor systems, the ``subprocess`` and ``multiprocess`` modules can be used with blender and make use of multiple CPU's too. + Pythons threads only allow co-currency and won't speed up your scripts on multi-processor systems, the ``subprocess`` and ``multiprocess`` modules can be used with Blender and make use of multiple CPU's too. Help! My script crashes Blender @@ -536,11 +539,18 @@ Here are some general hints to avoid running into these problems. * Crashes may not happen every time, they may happen more on some configurations/operating-systems. +.. note:: + + To find the line of your script that crashes you can use the ``faulthandler`` module. + See `faulthandler docs `_. + + While the crash may be in Blenders C/C++ code, this can help a lot to track down the area of the script that causes the crash. + Undo/Redo --------- -Undo invalidates all :class:`bpy.types.ID` instances (Object, Scene, Mesh etc). +Undo invalidates all :class:`bpy.types.ID` instances (Object, Scene, Mesh, Lamp... etc). This example shows how you can tell undo changes the memory locations. @@ -557,6 +567,21 @@ This example shows how you can tell undo changes the memory locations. As suggested above, simply not holding references to data when Blender is used interactively by the user is the only way to ensure the script doesn't become unstable. +Undo & Library Data +^^^^^^^^^^^^^^^^^^^ + +One of the advantages with Blenders library linking system that undo can skip checking changes in library data since it is assumed to be static. + +Tools in Blender are not allowed to modify library data. + +Python however does not enforce this restriction. + +This can be useful in some cases, using a script to adjust material values for example. +But its also possible to use a script to make library data point to newly created local data, which is not supported since a call to undo will remove the local data but leave the library referencing it and likely crash. + +So it's best to consider modifying library data an advanced usage of the API and only to use it when you know what you're doing. + + Edit Mode / Memory Access ------------------------- @@ -616,15 +641,36 @@ Removing Data **Any** data that you remove shouldn't be modified or accessed afterwards, this includes f-curves, drivers, render layers, timeline markers, modifiers, constraints along with objects, scenes, groups, bones.. etc. -This is a problem in the API at the moment that we should eventually solve. +The ``remove()`` api calls will invalidate the data they free to prevent common mistakes. + +The following example shows how this precortion works. + +.. code-block:: python + + mesh = bpy.data.meshes.new(name="MyMesh") + # normally the script would use the mesh here... + bpy.data.meshes.remove(mesh) + print(mesh.name) # <- give an exception rather then crashing: + + # ReferenceError: StructRNA of type Mesh has been removed + + +But take care because this is limited to scripts accessing the variable which is removed, the next example will still crash. + +.. code-block:: python + + mesh = bpy.data.meshes.new(name="MyMesh") + vertices = mesh.vertices + bpy.data.meshes.remove(mesh) + print(vertices) # <- this may crash sys.exit ======== -Some python modules will call sys.exit() themselves when an error occurs, while not common behavior this is something to watch out for because it may seem as if blender is crashing since sys.exit() will quit blender immediately. +Some python modules will call ``sys.exit()`` themselves when an error occurs, while not common behavior this is something to watch out for because it may seem as if blender is crashing since ``sys.exit()`` will quit blender immediately. For example, the ``optparse`` module will print an error and exit if the arguments are invalid. -An ugly way of troubleshooting this is to set ``sys.exit = None`` and see what line of python code is quitting, you could of course replace ``sys.exit``/ with your own function but manipulating python in this way is bad practice. +An ugly way of troubleshooting this is to set ``sys.exit = None`` and see what line of python code is quitting, you could of course replace ``sys.exit`` with your own function but manipulating python in this way is bad practice. diff --git a/doc/python_api/rst/info_overview.rst b/doc/python_api/rst/info_overview.rst index 818eb692be9..b2d524b74af 100644 --- a/doc/python_api/rst/info_overview.rst +++ b/doc/python_api/rst/info_overview.rst @@ -1,3 +1,5 @@ +.. _info_overview: + ******************* Python API Overview ******************* diff --git a/doc/python_api/rst/info_quickstart.rst b/doc/python_api/rst/info_quickstart.rst index 62ad4e9c4d8..e1264ae9d52 100644 --- a/doc/python_api/rst/info_quickstart.rst +++ b/doc/python_api/rst/info_quickstart.rst @@ -1,3 +1,5 @@ +.. _info_quickstart: + *********************** Quickstart Introduction *********************** diff --git a/doc/python_api/rst/info_tips_and_tricks.rst b/doc/python_api/rst/info_tips_and_tricks.rst index 521031f5e61..75e8ef61f6f 100644 --- a/doc/python_api/rst/info_tips_and_tricks.rst +++ b/doc/python_api/rst/info_tips_and_tricks.rst @@ -44,15 +44,17 @@ if this can't be generated, only the property name is copied. .. note:: - This uses the same method for creating the animation path used by :class:`FCurve.data_path` and :class:`DriverTarget.data_path` drivers. + This uses the same method for creating the animation path used by :class:`bpy.types.FCurve.data_path` and :class:`bpy.types.DriverTarget.data_path` drivers. +.. _info_show_all_operators + Show All Operators ================== While blender logs operators in the Info space, this only reports operators with the ``REGISTER`` option enabeld so as not to flood the Info view with calls to ``bpy.ops.view3d.smoothview`` and ``bpy.ops.view3d.zoom``. -However, for testing it can be useful to see **every** operator called in a terminal, do this by enabling the debug option either by passing the ``--debug`` argument when starting blender or by setting :mod:`bpy.app.debug` to True while blender is running. +However, for testing it can be useful to see **every** operator called in a terminal, do this by enabling the debug option either by passing the ``--debug-wm`` argument when starting blender or by setting :mod:`bpy.app.debug_wm` to True while blender is running. Use an External Editor @@ -218,6 +220,14 @@ The next example is an equivalent single line version of the script above which ``code.interact`` can be added at any line in the script and will pause the script an launch an interactive interpreter in the terminal, when you're done you can quit the interpreter and the script will continue execution. +If you have **IPython** installed you can use their ``embed()`` function which will implicitly use the current namespace, this has autocomplete and some useful features that the standard python eval-loop doesn't have. + +.. code-block:: python + + import IPython + IPython.embed() + + Admittedly this highlights the lack of any python debugging support built into blender, but its still handy to know. .. note:: diff --git a/doc/python_api/rst/info_tutorial_addon.rst b/doc/python_api/rst/info_tutorial_addon.rst new file mode 100644 index 00000000000..2a101041227 --- /dev/null +++ b/doc/python_api/rst/info_tutorial_addon.rst @@ -0,0 +1,645 @@ + +Addon Tutorial +############## + +************ +Introduction +************ + + +Intended Audience +================= + +This tutorial is designed to help technical artists or developers learn to extend Blender. +An understanding of the basics of Python is expected for those working through this tutorial. + + +Prerequisites +------------- + +Before going through the tutorial you should... + +* Familiarity with the basics of working in Blender. + +* Know how to run a script in Blender's text editor (as documented in the quick-start) + +* Have an understanding of Python primitive types (int, boolean, string, list, tuple, dictionary, and set). + +* Be familiar with the concept of Python modules. + +* Basic understanding of classes (object orientation) in Python. + + +Suggested reading before starting this tutorial. + +* `Dive Into Python `_ sections (1, 2, 3, 4, and 7). +* :ref:`Blender API Quickstart ` + to help become familiar with Blender/Python basics. + + +To best troubleshoot any error message Python prints while writing scripts you run blender with from a terminal, +see :ref:`Use The Terminal `. + +Documentation Links +=================== + +While going through the tutorial you may want to look into our reference documentation. + +* :ref:`Blender API Overview `. - + *This document is rather detailed but helpful if you want to know more on a topic.* + +* :mod:`bpy.context` api reference. - + *Handy to have a list of available items your script may operate on.* + +* :class:`bpy.types.Operator`. - + *The following addons define operators, these docs give details and more examples of operators.* + + +****** +Addons +****** + + +What is an Addon? +================= + +An addon is simply a Python module with some additional requirements so Blender can display it in a list with useful +information. + +To give an example, here is the simplest possible addon. + + +.. code-block:: python + + bl_info = {"name": "My Test Addon", "category": "Object"} + def register(): + print("Hello World") + def unregister(): + print("Goodbye World") + + +* ``bl_info`` is a dictionary containing addon meta-data such as the title, version and author to be displayed in the + user preferences addon list. +* ``register`` is a function which only runs when enabling the addon, this means the module can be loaded without + activating the addon. +* ``unregister`` is a function to unload anything setup by ``register``, this is called when the addon is disabled. + + + +Notice this addon does not do anything related to Blender, (the :mod:`bpy` module is not imported for example). + +This is a contrived example of an addon that serves to illustrate the point +that the base requirements of an addon are simple. + +An addon will typically register operators, panels, menu items etc, but its worth noting that _any_ script can do this, +when executed from the text editor or even the interactive console - there is nothing inherently different about an +addon that allows it to integrate with Blender, such functionality is just provided by the :mod:`bpy` module for any +script to access. + +So an addon is just a way to encapsulate a Python module in a way a user can easily utilize. + +.. note:: + + Running this script within the text editor won't print anything, + to see the output it must be installed through the user preferences. + Messages will be printed when enabling and disabling. + + +Your First Addon +================ + +The simplest possible addon above was useful as an example but not much else. +This next addon is simple but shows how to integrate a script into Blender using an ``Operator`` +which is the typical way to define a tool accessed from menus, buttons and keyboard shortcuts. + +For the first example we'll make a script that simply moves all objects in a scene. + + +Write The Script +---------------- + +Add the following script to the text editor in Blender. + +.. code-block:: python + + import bpy + + scene = bpy.context.scene + for obj in scene.objects: + obj.location.x += 1.0 + + +.. image:: run_script.png + :width: 924px + :align: center + :height: 574px + :alt: Run Script button + +Click the Run Script button, all objects in the active scene are moved by 1.0 Blender unit. +Next we'll make this script into an addon. + + +Write the Addon (Simple) +------------------------ + +This addon takes the body of the script above, and adds them to an operator's ``execute()`` function. + + +.. code-block:: python + + bl_info = { + "name": "Move X Axis", + "category": "Object", + } + + import bpy + + + class ObjectMoveX(bpy.types.Operator): + """My Object Moving Script""" # blender will use this as a tooltip for menu items and buttons. + bl_idname = "object.move_x" # unique identifier for buttons and menu items to reference. + bl_label = "Move X by One" # display name in the interface. + bl_options = {'REGISTER', 'UNDO'} # enable undo for the operator. + + def execute(self, context): # execute() is called by blender when running the operator. + + # The original script + scene = context.scene + for obj in scene.objects: + obj.location.x += 1.0 + + return {'FINISHED'} # this lets blender know the operator finished successfully. + + def register(): + bpy.utils.register_class(ObjectMoveX) + + + def unregister(): + bpy.utils.unregister_class(ObjectMoveX) + + + # This allows you to run the script directly from blenders text editor + # to test the addon without having to install it. + if __name__ == "__main__": + register() + + +.. note:: ``bl_info`` is split across multiple lines, this is just a style convention used to more easily add items. + +.. note:: Rather than using ``bpy.context.scene``, we use the ``context.scene`` argument passed to ``execute()``. + In most cases these will be the same however in some cases operators will be passed a custom context + so script authors should prefer the ``context`` argument passed to operators. + + +To test the script you can copy and paste this into Blender text editor and run it, this will execute the script +directly and call register immediately. + +However running the script wont move any objects, for this you need to execute the newly registered operator. + +.. image:: spacebar.png + :width: 924px + :align: center + :height: 574px + :alt: Spacebar + +Do this by pressing ``SpaceBar`` to bring up the operator search dialog and type in "Move X by One" (the ``bl_label``), +then press ``Enter``. + + + +The objects should move as before. + +*Keep this addon open in Blender for the next step - Installing.* + +Install The Addon +----------------- + +Once you have your addon within in Blender's text editor, you will want to be able to install it so it can be enabled in +the user preferences to load on startup. + +Even though the addon above is a test, lets go through the steps anyway so you know how to do it for later. + +To install the Blender text as an addon you will first have to save it to disk, take care to obey the naming +restrictions that apply to Python modules and end with a ``.py`` extension. + +Once the file is on disk, you can install it as you would for an addon downloaded online. + +Open the user **File -> User Preferences**, Select the **Addon** section, press **Install Addon...** and select the file. + +Now the addon will be listed and you can enable it by pressing the check-box, if you want it to be enabled on restart, +press **Save as Default**. + +.. note:: + + The destination of the addon depends on your Blender configuration. + When installing an addon the source and destination path are printed in the console. + You can also find addon path locations by running this in the Python console. + + .. code-block:: python + + import addon_utils + print(addon_utils.paths()) + + More is written on this topic here: + `Directory Layout `_ + + +Your Second Addon +================= + +For our second addon, we will focus on object instancing - this is - to make linked copies of an object in a +similar way to what you may have seen with the array modifier. + + +Write The Script +---------------- + +As before, first we will start with a script, develop it, then convert into an addon. + +.. code-block:: python + + import bpy + from bpy import context + + # Get the current scene + scene = context.scene + + # Get the 3D cursor + cursor = scene.cursor_location + + # Get the active object (assume we have one) + obj = scene.objects.active + + # Now make a copy of the object + obj_new = obj.copy() + + # The object won't automatically get into a new scene + scene.objects.link(obj_new) + + # Now we can place the object + obj_new.location = cursor + + +Now try copy this script into Blender and run it on the default cube. +Make sure you click to move the 3D cursor before running as the duplicate will appear at the cursor's location. + + +... go off and test ... + + +After running, notice that when you go into edit-mode to change the cube - all of the copies change, +in Blender this is known as *Linked-Duplicates*. + + +Next, we're going to do this in a loop, to make an array of objects between the active object and the cursor. + + +.. code-block:: python + + import bpy + from bpy import context + + scene = context.scene + cursor = scene.cursor_location + obj = scene.objects.active + + # Use a fixed value for now, eventually make this user adjustable + total = 10 + + # Add 'total' objects into the scene + for i in range(total): + obj_new = obj.copy() + scene.objects.link(obj_new) + + # Now place the object in between the cursor + # and the active object based on 'i' + factor = i / total + obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor)) + + +Try run this script with with the active object and the cursor spaced apart to see the result. + +With this script you'll notice we're doing some math with the object location and cursor, this works because both are +3D :class:`mathutils.Vector` instances, a convenient class provided by the :mod:`mathutils` module and +allows vectors to be multiplied by numbers and matrices. + +If you are interested in this area, read into :class:`mathutils.Vector` - there are many handy utility functions +such as getting the angle between vectors, cross product, dot products +as well as more advanced functions in :mod:`mathutils.geometry` such as bezier spline interpolation and +ray-triangle intersection. + +For now we'll focus on making this script an addon, but its good to know that this 3D math module is available and +can help you with more advanced functionality later on. + + +Write the Addon +--------------- + +The first step is to convert the script as-is into an addon. + + +.. code-block:: python + + bl_info = { + "name": "Cursor Array", + "category": "Object", + } + + import bpy + + + class ObjectCursorArray(bpy.types.Operator): + """Object Cursor Array""" + bl_idname = "object.cursor_array" + bl_label = "Cursor Array" + bl_options = {'REGISTER', 'UNDO'} + + def execute(self, context): + scene = context.scene + cursor = scene.cursor_location + obj = scene.objects.active + + total = 10 + + for i in range(total): + obj_new = obj.copy() + scene.objects.link(obj_new) + + factor = i / total + obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor)) + + return {'FINISHED'} + + def register(): + bpy.utils.register_class(ObjectCursorArray) + + + def unregister(): + bpy.utils.unregister_class(ObjectCursorArray) + + + if __name__ == "__main__": + register() + + +Everything here has been covered in the previous steps, you may want to try run the addon still +and consider what could be done to make it more useful. + + +... go off and test ... + + +The two of the most obvious missing things are - having the total fixed at 10, and having to access the operator from +space-bar is not very convenient. + +Both these additions are explained next, with the final script afterwards. + + +Operator Property +^^^^^^^^^^^^^^^^^ + +There are a variety of property types that are used for tool settings, common property types include: +int, float, vector, color, boolean and string. + +These properties are handled differently to typical Python class attributes +because Blender needs to be display them in the interface, +store their settings in key-maps and keep settings for re-use. + +While this is handled in a fairly Pythonic way, be mindful that you are in fact defining tool settings that +are loaded into Blender and accessed by other parts of Blender, outside of Python. + + +To get rid of the literal 10 for `total`, we'll us an operator property. +Operator properties are defined via bpy.props module, this is added to the class body. + +.. code-block:: python + + # moved assignment from execute() to the body of the class... + total = bpy.props.IntProperty(name="Steps", default=2, min=1, max=100) + + # and this is accessed on the class + # instance within the execute() function as... + self.total + + +These properties from :mod:`bpy.props` are handled specially by Blender when the class is registered +so they display as buttons in the user interface. +There are many arguments you can pass to properties to set limits, change the default and display a tooltip. + +.. seealso:: :mod:`bpy.props.IntProperty` + +This document doesn't go into details about using other property types, +however the link above includes examples of more advanced property usage. + + +Menu Item +^^^^^^^^^ + +Addons can add to the user interface of existing panels, headers and menus defined in Python. + +For this example we'll add to an existing menu. + +.. image:: menu_id.png + :width: 334px + :align: center + :height: 128px + :alt: Menu Identifier + +To find the identifier of a menu you can hover your mouse over the menu item and the identifier is displayed. + +The method used for adding a menu item is to append a draw function into an existing class. + + +.. code-block:: python + + def menu_func(self, context): + self.layout.operator(ObjectCursorArray.bl_idname) + + def register(): + bpy.types.VIEW3D_MT_object.append(menu_func) + + +For docs on extending menus see: :doc:`bpy.types.Menu`. + + +Keymap +^^^^^^ + +In Blender addons have their own key-maps so as not to interfere with Blenders built in key-maps. + +In the example below, a new object-mode :class:`bpy.types.KeyMap` is added, +then a :class:`bpy.types.KeyMapItem` is added to the key-map which references our newly added operator, +using :kbd:`Ctrl-Shift-Space` as the key shortcut to activate it. + + +.. code-block:: python + + # store keymaps here to access after registration + addon_keymaps = [] + + def register(): + + # handle the keymap + wm = bpy.context.window_manager + km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY') + + kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True) + kmi.properties.total = 4 + + addon_keymaps.append(km) + + + def unregister(): + + # handle the keymap + wm = bpy.context.window_manager + for km in addon_keymaps: + wm.keyconfigs.addon.keymaps.remove(km) + # clear the list + addon_keymaps.clear() + + +Notice how the key-map item can have a different ``total`` setting then the default set by the operator, +this allows you to have multiple keys accessing the same operator with different settings. + + +.. note:: + + While :kbd:`Ctrl-Shift-Space` isn't a default Blender key shortcut, its hard to make sure addons won't + overwrite each others keymaps, At least take care when assigning keys that they don't + conflict with important functionality within Blender. + +For API documentation on the functions listed above, see: +:class:`bpy.types.KeyMaps.new`, +:class:`bpy.types.KeyMap`, +:class:`bpy.types.KeyMapItems.new`, +:class:`bpy.types.KeyMapItem`. + + +Bringing it all together +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: python + + bl_info = { + "name": "Cursor Array", + "category": "Object", + } + + import bpy + + + class ObjectCursorArray(bpy.types.Operator): + """Object Cursor Array""" + bl_idname = "object.cursor_array" + bl_label = "Cursor Array" + bl_options = {'REGISTER', 'UNDO'} + + total = bpy.props.IntProperty(name="Steps", default=2, min=1, max=100) + + def execute(self, context): + scene = context.scene + cursor = scene.cursor_location + obj = scene.objects.active + + for i in range(self.total): + obj_new = obj.copy() + scene.objects.link(obj_new) + + factor = i / self.total + obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor)) + + return {'FINISHED'} + + + def menu_func(self, context): + self.layout.operator(ObjectCursorArray.bl_idname) + + # store keymaps here to access after registration + addon_keymaps = [] + + + def register(): + bpy.utils.register_class(ObjectCursorArray) + bpy.types.VIEW3D_MT_object.append(menu_func) + + # handle the keymap + wm = bpy.context.window_manager + km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY') + kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True) + kmi.properties.total = 4 + addon_keymaps.append(km) + + def unregister(): + bpy.utils.unregister_class(ObjectCursorArray) + bpy.types.VIEW3D_MT_object.remove(menu_func) + + # handle the keymap + wm = bpy.context.window_manager + for km in addon_keymaps: + wm.keyconfigs.addon.keymaps.remove(km) + # clear the list + del addon_keymaps[:] + + + if __name__ == "__main__": + register() + +.. image:: in_menu.png + :width: 591px + :align: center + :height: 649px + :alt: In the menu + +Run the script (or save it and add it through the Preferences like before) and it will appear in the menu. + +.. image:: op_prop.png + :width: 669px + :align: center + :height: 644px + :alt: Operator Property + +After selecting it from the menu, you can choose how many instance of the cube you want created. + + +.. note:: + + Directly executing the script multiple times will add the menu each time too. + While not useful behavior, theres nothing to worry about since addons won't register them selves multiple + times when enabled through the user preferences. + + +Conclusions +=========== + +Addons can encapsulate certain functionality neatly for writing tools to improve your work-flow or for writing utilities +for others to use. + +While there are limits to what Python can do within Blender, there is certainly a lot that can be achieved without +having to dive into Blender's C/C++ code. + +The example given in the tutorial is limited, but shows the Blender API used for common tasks that you can expand on +to write your own tools. + + +Further Reading +--------------- + +Blender comes commented templates which are accessible from the text editor header, if you have specific areas +you want to see example code for, this is a good place to start. + + +Here are some sites you might like to check on after completing this tutorial. + +* :ref:`Blender/Python API Overview ` - + *For more background details on Blender/Python integration.* + +* `How to Think Like a Computer Scientist `_ - + *Great info for those who are still learning Python.* + +* `Blender Development (Wiki) `_ - + *Blender Development, general information and helpful links.* + +* `Blender Artists (Coding Section) `_ - + *forum where people ask Python development questions* + diff --git a/doc/python_api/rst_from_bmesh_opdefines.py b/doc/python_api/rst_from_bmesh_opdefines.py new file mode 100644 index 00000000000..c1b6643389d --- /dev/null +++ b/doc/python_api/rst_from_bmesh_opdefines.py @@ -0,0 +1,380 @@ +# ##### 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. +# +# ##### END GPL LICENSE BLOCK ##### + +# + +# This is a quite stupid script which extracts bmesh api docs from +# 'bmesh_opdefines.c' in order to avoid having to add a lot of introspection +# data access into the api. +# +# The script is stupid becase it makes assumptions about formatting... +# that each arg has its own line, that comments above or directly after will be __doc__ etc... +# +# We may want to replace this script with something else one day but for now its good enough. +# if it needs large updates it may be better to rewrite using a real parser or +# add introspection into bmesh.ops. +# - campbell + +import os + +CURRENT_DIR = os.path.abspath(os.path.dirname(__file__)) +SOURCE_DIR = os.path.normpath(os.path.abspath(os.path.normpath(os.path.join(CURRENT_DIR, "..", "..")))) +FILE_OP_DEFINES_C = os.path.join(SOURCE_DIR, "source", "blender", "bmesh", "intern", "bmesh_opdefines.c") +OUT_RST = os.path.join(CURRENT_DIR, "rst", "bmesh.ops.rst") + +HEADER = r""" +BMesh Operators (bmesh.ops) +=========================== + +.. module:: bmesh.ops + +This module gives access to low level bmesh operations. + +Most operators take input and return output, they can be chained together +to perform useful operations. + +.. note:: + + This API us new in 2.65 and not yet well tested. + + +Operator Example +++++++++++++++++ +This script shows how operators can be used to model a link of a chain. + +.. literalinclude:: ../examples/bmesh.ops.1.py +""" + + +def main(): + fsrc = open(FILE_OP_DEFINES_C, 'r', encoding="utf-8") + + blocks = [] + + is_block = False + is_comment = False # /* global comments only */ + + comment_ctx = None + block_ctx = None + + for l in fsrc: + l = l[:-1] + # weak but ok + if ("BMOpDefine" in l and l.split()[1] == "BMOpDefine") and not "bmo_opdefines[]" in l: + is_block = True + block_ctx = [] + blocks.append((comment_ctx, block_ctx)) + elif l.strip().startswith("/*"): + is_comment = True + comment_ctx = [] + + if is_block: + if l.strip().startswith("//"): + pass + else: + # remove c++ comment if we have one + cpp_comment = l.find("//") + if cpp_comment != -1: + l = l[:cpp_comment] + + block_ctx.append(l) + + if l.strip() == "};": + is_block = False + comment_ctx = None + + if is_comment: + c_comment_start = l.find("/*") + if c_comment_start != -1: + l = l[c_comment_start + 2:] + + c_comment_end = l.find("*/") + if c_comment_end != -1: + l = l[:c_comment_end] + + is_comment = False + comment_ctx.append(l) + + fsrc.close() + del fsrc + + + # namespace hack + vars = ( + "BMO_OP_SLOT_ELEMENT_BUF", + "BMO_OP_SLOT_BOOL", + "BMO_OP_SLOT_FLT", + "BMO_OP_SLOT_INT", + "BMO_OP_SLOT_MAT", + "BMO_OP_SLOT_VEC", + "BMO_OP_SLOT_PTR", + "BMO_OP_SLOT_MAPPING", + + "BMO_OP_SLOT_SUBTYPE_MAP_ELEM", + "BMO_OP_SLOT_SUBTYPE_MAP_BOOL", + "BMO_OP_SLOT_SUBTYPE_MAP_INT", + "BMO_OP_SLOT_SUBTYPE_MAP_FLT", + "BMO_OP_SLOT_SUBTYPE_MAP_EMPTY", + "BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL", + + "BMO_OP_SLOT_SUBTYPE_PTR_SCENE", + "BMO_OP_SLOT_SUBTYPE_PTR_OBJECT", + "BMO_OP_SLOT_SUBTYPE_PTR_MESH", + "BMO_OP_SLOT_SUBTYPE_PTR_BMESH", + + "BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE", + + "BM_VERT", + "BM_EDGE", + "BM_FACE", + + "BMO_OP_FLAG_UNTAN_MULTIRES", + ) + vars_dict = {} + for i, v in enumerate(vars): + vars_dict[v] = (1 << i) + globals().update(vars_dict) + # reverse lookup + vars_dict_reverse = {v: k for k, v in vars_dict.items()} + # end namespace hack + + blocks_py = [] + for comment, b in blocks: + # magic, translate into python + b[0] = b[0].replace("static BMOpDefine ", "") + + for i, l in enumerate(b): + l = l.strip() + l = l.replace("{", "(") + l = l.replace("}", ")") + + if l.startswith("/*"): + l = l.replace("/*", "'''own <") + else: + l = l.replace("/*", "'''inline <") + l = l.replace("*/", ">''',") + + # exec func. eg: bmo_rotate_edges_exec, + if l.startswith("bmo_") and l.endswith("_exec,"): + l = "None," + b[i] = l + + #for l in b: + # print(l) + + text = "\n".join(b) + global_namespace = { + "__file__": "generated", + "__name__": "__main__", + } + + global_namespace.update(vars_dict) + + text_a, text_b = text.split("=", 1) + text = "result = " + text_b + exec(compile(text, "generated", 'exec'), global_namespace) + # print(global_namespace["result"]) + blocks_py.append((comment, global_namespace["result"])) + + + # --------------------- + # Now convert into rst. + fout = open(OUT_RST, 'w', encoding="utf-8") + fw = fout.write + fw(HEADER) + for comment, b in blocks_py: + args_in = None + args_out = None + for member in b[1:]: + if type(member) == tuple: + if args_in is None: + args_in = member + elif args_out is None: + args_out = member + break + + args_in_index = [] + args_out_index = [] + + if args_in is not None: + args_in_index[:] = [i for (i, a) in enumerate(args_in) if type(a) == tuple] + if args_out is not None: + args_out_index[:] = [i for (i, a) in enumerate(args_out) if type(a) == tuple] + + fw(".. function:: %s(bm, %s)\n\n" % (b[0], ", ".join([args_in[i][0] for i in args_in_index]))) + + # -- wash the comment + comment_washed = [] + for i, l in enumerate(comment): + assert((l.strip() == "") or + (l in {"/*", " *"}) or + (l.startswith(("/* ", " * ")))) + + l = l[3:] + if i == 0 and not l.strip(): + continue + if l.strip(): + l = " " + l + comment_washed.append(l) + + fw("\n".join(comment_washed)) + fw("\n") + # -- done + + + # get the args + def get_args_wash(args, args_index, is_ret): + args_wash = [] + for i in args_index: + arg = args[i] + if len(arg) == 3: + name, tp, tp_sub = arg + elif len(arg) == 2: + name, tp = arg + tp_sub = None + else: + print(arg) + assert(0) + + tp_str = "" + + comment_prev = "" + comment_next = "" + if i != 0: + comment_prev = args[i + 1] + if type(comment_prev) == str and comment_prev.startswith("our <"): + comment_prev = comment_next[5:-1] # strip inline <...> + else: + comment_prev = "" + + if i + 1 < len(args): + comment_next = args[i + 1] + if type(comment_next) == str and comment_next.startswith("inline <"): + comment_next = comment_next[8:-1] # strip inline <...> + else: + comment_next = "" + + comment = "" + if comment_prev: + comment += comment_prev.strip() + if comment_next: + comment += ("\n" if comment_prev else "") + comment_next.strip() + + if tp == BMO_OP_SLOT_FLT: + tp_str = "float" + elif tp == BMO_OP_SLOT_INT: + tp_str = "int" + elif tp == BMO_OP_SLOT_BOOL: + tp_str = "bool" + elif tp == BMO_OP_SLOT_MAT: + tp_str = ":class:`mathutils.Matrix`" + elif tp == BMO_OP_SLOT_VEC: + tp_str = ":class:`mathutils.Vector`" + if not is_ret: + tp_str += " or any sequence of 3 floats" + elif tp == BMO_OP_SLOT_PTR: + tp_str = "dict" + assert(tp_sub is not None) + if tp_sub == BMO_OP_SLOT_SUBTYPE_PTR_BMESH: + tp_str = ":class:`bmesh.types.BMesh`" + elif tp_sub == BMO_OP_SLOT_SUBTYPE_PTR_SCENE: + tp_str = ":class:`bpy.types.Scene`" + elif tp_sub == BMO_OP_SLOT_SUBTYPE_PTR_OBJECT: + tp_str = ":class:`bpy.types.Object`" + elif tp_sub == BMO_OP_SLOT_SUBTYPE_PTR_MESH: + tp_str = ":class:`bpy.types.Mesh`" + else: + print("Cant find", vars_dict_reverse[tp_sub]) + assert(0) + + elif tp == BMO_OP_SLOT_ELEMENT_BUF: + assert(tp_sub is not None) + + ls = [] + if tp_sub & BM_VERT: ls.append(":class:`bmesh.types.BMVert`") + if tp_sub & BM_EDGE: ls.append(":class:`bmesh.types.BMEdge`") + if tp_sub & BM_FACE: ls.append(":class:`bmesh.types.BMFace`") + assert(ls) # must be at least one + + if tp_sub & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE: + tp_str = "/".join(ls) + else: + tp_str = ("list of (%s)" % ", ".join(ls)) + + del ls + elif tp == BMO_OP_SLOT_MAPPING: + if tp_sub & BMO_OP_SLOT_SUBTYPE_MAP_EMPTY: + tp_str = "set of vert/edge/face type" + else: + tp_str = "dict mapping vert/edge/face types to " + if tp_sub == BMO_OP_SLOT_SUBTYPE_MAP_BOOL: + tp_str += "bool" + elif tp_sub == BMO_OP_SLOT_SUBTYPE_MAP_INT: + tp_str += "int" + elif tp_sub == BMO_OP_SLOT_SUBTYPE_MAP_FLT: + tp_str += "float" + elif tp_sub == BMO_OP_SLOT_SUBTYPE_MAP_ELEM: + tp_str += ":class:`bmesh.types.BMVert`/:class:`bmesh.types.BMEdge`/:class:`bmesh.types.BMFace`" + elif tp_sub == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL: + tp_str += "unknown internal data, not compatible with python" + else: + print("Cant find", vars_dict_reverse[tp_sub]) + assert(0) + else: + print("Cant find", vars_dict_reverse[tp]) + assert(0) + + args_wash.append((name, tp_str, comment)) + return args_wash + # end get_args_wash + + # all ops get this arg + fw(" :arg bm: The bmesh to operate on.\n") + fw(" :type bm: :class:`bmesh.types.BMesh`\n") + + args_in_wash = get_args_wash(args_in, args_in_index, False) + args_out_wash = get_args_wash(args_out, args_out_index, True) + + for (name, tp, comment) in args_in_wash: + if comment == "": + comment = "Undocumented." + + fw(" :arg %s: %s\n" % (name, comment)) + fw(" :type %s: %s\n" % (name, tp)) + + if args_out_wash: + fw(" :return:\n\n") + + for (name, tp, comment) in args_out_wash: + assert(name.endswith(".out")) + name = name[:-4] + fw(" - ``%s``: %s\n\n" % (name, comment)) + fw(" **type** %s\n" % tp) + + fw("\n") + fw(" :rtype: dict with string keys\n") + + fw("\n\n") + + fout.close() + del fout + print(OUT_RST) + + +if __name__ == "__main__": + main() diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 6f7d4f3582a..441a6c04efe 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -35,7 +35,7 @@ API dump in RST files ./blender.bin --background --python doc/python_api/sphinx_doc_gen.py -- --output ../python_api For quick builds: - ./blender.bin --background --python doc/python_api/sphinx_doc_gen.py -- --partial + ./blender.bin --background --python doc/python_api/sphinx_doc_gen.py -- --partial bmesh.* Sphinx: HTML generation @@ -245,6 +245,7 @@ else: "bgl", "blf", "bmesh", + "bmesh.ops", "bmesh.types", "bmesh.utils", "bpy.app", @@ -297,7 +298,7 @@ try: __import__("aud") except ImportError: BPY_LOGGER.debug("Warning: Built without 'aud' module, docs incomplete...") - EXCLUDE_MODULES = EXCLUDE_MODULES + ("aud", ) + EXCLUDE_MODULES = list(EXCLUDE_MODULES) + ["aud"] # examples EXAMPLES_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "examples")) @@ -315,6 +316,8 @@ RST_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "rst")) INFO_DOCS = ( ("info_quickstart.rst", "Blender/Python Quickstart: new to blender/scripting and want to get your feet wet?"), ("info_overview.rst", "Blender/Python API Overview: a more complete explanation of python integration"), + ("info_tutorial_addon.rst", "Blender/Python Addon Tutorial: a step by step guide on how to write an addon from scratch"), + ("info_api_reference.rst", "Blender/Python API Reference Usage: examples of how to use the API reference docs"), ("info_best_practice.rst", "Best Practice: Conventions to follow for writing good scripts"), ("info_tips_and_tricks.rst", "Tips and Tricks: Hints to help you while writing scripts for blender"), ("info_gotcha.rst", "Gotcha's: some of the problems you may come up against when writing scripts"), @@ -1251,7 +1254,7 @@ def pyrna2sphinx(basepath): bases = list(reversed(struct.get_bases())) # props - lines[:] = [] + del lines[:] if _BPY_STRUCT_FAKE: descr_items = [(key, descr) for key, descr in sorted(bpy.types.Struct.__bases__[0].__dict__.items()) if not key.startswith("__")] @@ -1282,7 +1285,7 @@ def pyrna2sphinx(basepath): fw("\n") # funcs - lines[:] = [] + del lines[:] if _BPY_STRUCT_FAKE: for key, descr in descr_items: @@ -1305,7 +1308,7 @@ def pyrna2sphinx(basepath): fw(line) fw("\n") - lines[:] = [] + del lines[:] if struct.references: # use this otherwise it gets in the index for a normal heading. @@ -1472,6 +1475,11 @@ def write_sphinx_conf_py(basepath): file.close() +def execfile(filepath): + global_namespace = {"__file__": filepath, "__name__": "__main__"} + exec(compile(open(filepath).read(), filepath, 'exec'), global_namespace) + + def write_rst_contents(basepath): ''' Write the rst file of the main page, needed for sphinx (index.html) @@ -1532,14 +1540,18 @@ def write_rst_contents(basepath): "mathutils", "mathutils.geometry", "mathutils.noise", # misc "bgl", "blf", "gpu", "aud", "bpy_extras", - # bmesh - "bmesh", "bmesh.types", "bmesh.utils", + # bmesh, submodules are in own page + "bmesh", ) for mod in standalone_modules: if mod not in EXCLUDE_MODULES: fw(" %s\n\n" % mod) + # special case, this 'bmesh.ops.rst' is extracted from C source + if "bmesh.ops" not in EXCLUDE_MODULES: + execfile(os.path.join(SCRIPT_DIR, "rst_from_bmesh_opdefines.py")) + # game engine if "bge" not in EXCLUDE_MODULES: fw(title_string("Game Engine Modules", "=", double=True)) @@ -1701,6 +1713,8 @@ def copy_handwritten_rsts(basepath): "bgl", # "Blender OpenGl wrapper" "gpu", # "GPU Shader Module" + "bmesh.ops", # generated by rst_from_bmesh_opdefines.py + # includes... "include__bmesh", ] @@ -1712,6 +1726,11 @@ def copy_handwritten_rsts(basepath): # changelog shutil.copy2(os.path.join(RST_DIR, "change_log.rst"), basepath) + # copy images, could be smarter but just glob for now. + for f in os.listdir(RST_DIR): + if f.endswith(".png"): + shutil.copy2(os.path.join(RST_DIR, f), basepath) + def rna2sphinx(basepath): diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt index 151df493062..2640c528c94 100644 --- a/extern/CMakeLists.txt +++ b/extern/CMakeLists.txt @@ -32,9 +32,10 @@ if(WITH_BULLET) add_subdirectory(bullet2) endif() -if(WITH_MOD_CLOTH_ELTOPO) - add_subdirectory(eltopo) -endif() +# now only available in a branch +#if(WITH_MOD_CLOTH_ELTOPO) +# add_subdirectory(eltopo) +#endif() if(WITH_BINRELOC) add_subdirectory(binreloc) diff --git a/extern/SConscript b/extern/SConscript index ce366deb38a..71998ee072c 100644 --- a/extern/SConscript +++ b/extern/SConscript @@ -8,8 +8,11 @@ SConscript(['colamd/SConscript']) if env['WITH_BF_GAMEENGINE']: SConscript(['recastnavigation/SConscript']) +# now only available in a branch +''' if env['WITH_BF_ELTOPO']: SConscript(['eltopo/SConscript']) +''' if env['WITH_BF_BULLET']: SConscript(['bullet2/src/SConscript']) diff --git a/extern/glew/src/glew.c b/extern/glew/src/glew.c index 5d886ce7807..833d3999268 100644 --- a/extern/glew/src/glew.c +++ b/extern/glew/src/glew.c @@ -93,7 +93,7 @@ void* dlGetProcAddress (const GLubyte* name) #include #include -#ifdef MAC_OS_X_VERSION_10_3 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3 #include @@ -142,7 +142,7 @@ void* NSGLGetProcAddress (const GLubyte *name) return NULL; #endif } -#endif /* MAC_OS_X_VERSION_10_3 */ +#endif /* MAC_OS_X_VERSION_MIN_REQUIRED */ #endif /* __APPLE__ */ /* diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt index 38be34add75..ebc5953d956 100644 --- a/extern/libmv/CMakeLists.txt +++ b/extern/libmv/CMakeLists.txt @@ -102,6 +102,8 @@ set(SRC libmv/multiview/conditioning.h libmv/multiview/euclidean_resection.h libmv/multiview/fundamental.h + libmv/multiview/homography.h + libmv/multiview/homography_parameterization.h libmv/multiview/nviewtriangulation.h libmv/multiview/projection.h libmv/multiview/resection.h @@ -131,6 +133,7 @@ set(SRC libmv/tracking/pyramid_region_tracker.h libmv/tracking/region_tracker.h libmv/tracking/retrack_region_tracker.h + libmv/tracking/track_region.h libmv/tracking/trklt_region_tracker.h third_party/fast/fast.h diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index a15927f881d..8e483abd386 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -192,7 +192,7 @@ static void imageToFloatBuf(const libmv::FloatImage *image, int channels, float } #if defined(DUMP_FAILURE) || defined (DUMP_ALWAYS) -void savePNGImage(png_bytep *row_pointers, int width, int height, int depth, int color_type, char *file_name) +static void savePNGImage(png_bytep *row_pointers, int width, int height, int depth, int color_type, char *file_name) { png_infop info_ptr; png_structp png_ptr; @@ -437,6 +437,9 @@ int libmv_trackRegion(const struct libmv_trackRegionOptions *options, #endif saveImage("old_patch", old_patch, x1[4], y1[4]); saveImage("new_patch", new_patch, x2[4], y2[4]); + + if (options->image1_mask) + saveImage("mask", image1_mask, x2[4], y2[4]); } #endif @@ -897,7 +900,7 @@ void libmv_CameraIntrinsicsUpdate(struct libmv_CameraIntrinsics *libmvIntrinsics intrinsics->SetFocalLength(focal_length, focal_length); if (intrinsics->principal_point_x() != principal_x || intrinsics->principal_point_y() != principal_y) - intrinsics->SetFocalLength(focal_length, focal_length); + intrinsics->SetPrincipalPoint(principal_x, principal_y); if (intrinsics->k1() != k1 || intrinsics->k2() != k2 || intrinsics->k3() != k3) intrinsics->SetRadialDistortion(k1, k2, k3); diff --git a/extern/libmv/libmv/simple_pipeline/resect.cc b/extern/libmv/libmv/simple_pipeline/resect.cc index 4c9ca6d8677..3929271e66f 100644 --- a/extern/libmv/libmv/simple_pipeline/resect.cc +++ b/extern/libmv/libmv/simple_pipeline/resect.cc @@ -57,7 +57,7 @@ struct EuclideanResectCostFunction { EuclideanResectCostFunction(const vector &markers, const EuclideanReconstruction &reconstruction, - const Mat3 initial_R) + const Mat3 &initial_R) : markers(markers), reconstruction(reconstruction), initial_R(initial_R) {} diff --git a/extern/xdnd/xdnd.c b/extern/xdnd/xdnd.c index 9bdee89c1ce..50d1fec4969 100644 --- a/extern/xdnd/xdnd.c +++ b/extern/xdnd/xdnd.c @@ -347,7 +347,7 @@ void xdnd_set_dnd_aware (DndClass * dnd, Window window, Atom * typelist) &nchildren_return); if (children_return) XFree (children_return); - if (r) + if (r && parent != root_return) xdnd_set_dnd_aware (dnd, parent, typelist); } diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt index cb2fc239859..be797c45ba1 100644 --- a/intern/CMakeLists.txt +++ b/intern/CMakeLists.txt @@ -65,6 +65,10 @@ if(WITH_CYCLES) add_subdirectory(cycles) endif() +if(WITH_INTERNATIONAL) + add_subdirectory(locale) +endif() + # only windows needs utf16 converter if(WIN32) add_subdirectory(utfconv) diff --git a/intern/SConscript b/intern/SConscript index 59e412333b0..5360ce4ea88 100644 --- a/intern/SConscript +++ b/intern/SConscript @@ -30,6 +30,9 @@ if env['WITH_BF_CYCLES']: if env['WITH_BF_BOOLEAN']: SConscript(['bsp/SConscript']) +if env['WITH_BF_INTERNATIONAL']: + SConscript(['locale/SConscript']) + if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-mingw', 'linuxcross', 'win64-vc'): SConscript(['utfconv/SConscript']) diff --git a/intern/audaspace/intern/AUD_FileWriter.h b/intern/audaspace/intern/AUD_FileWriter.h index da52c7e0fb2..3291c1ad03a 100644 --- a/intern/audaspace/intern/AUD_FileWriter.h +++ b/intern/audaspace/intern/AUD_FileWriter.h @@ -64,8 +64,8 @@ public: * Writes a reader to a writer. * \param reader The reader to read from. * \param writer The writer to write to. - * \param length How many samples should be transfered. - * \param buffersize How many samples should be transfered at once. + * \param length How many samples should be transferred. + * \param buffersize How many samples should be transferred at once. */ static void writeReader(boost::shared_ptr reader, boost::shared_ptr writer, unsigned int length, unsigned int buffersize); @@ -73,8 +73,8 @@ public: * Writes a reader to several writers. * \param reader The reader to read from. * \param writers The writers to write to. - * \param length How many samples should be transfered. - * \param buffersize How many samples should be transfered at once. + * \param length How many samples should be transferred. + * \param buffersize How many samples should be transferred at once. */ static void writeReader(boost::shared_ptr reader, std::vector >& writers, unsigned int length, unsigned int buffersize); }; diff --git a/intern/audaspace/intern/AUD_LinearResampleReader.cpp b/intern/audaspace/intern/AUD_LinearResampleReader.cpp index 6aa0faed863..b342b8f31fb 100644 --- a/intern/audaspace/intern/AUD_LinearResampleReader.cpp +++ b/intern/audaspace/intern/AUD_LinearResampleReader.cpp @@ -81,7 +81,7 @@ void AUD_LinearResampleReader::read(int& length, bool& eos, sample_t* buffer) int samplesize = AUD_SAMPLE_SIZE(specs); int size = length; float factor = m_rate / m_reader->getSpecs().rate; - float spos; + float spos = 0.0f; sample_t low, high; eos = false; diff --git a/intern/bsp/intern/BOP_CarveInterface.cpp b/intern/bsp/intern/BOP_CarveInterface.cpp index f7da76e5794..bb3a783548c 100644 --- a/intern/bsp/intern/BOP_CarveInterface.cpp +++ b/intern/bsp/intern/BOP_CarveInterface.cpp @@ -205,7 +205,7 @@ static void Carve_getIntersectedOperandMeshes(std::vector::mesh_t*> & std::vector::mesh_t*>::iterator it = meshes.begin(); std::vector< RTreeNode<3, Face<3> *> *> meshRTree; - while(it != meshes.end()) { + while (it != meshes.end()) { MeshSet<3>::mesh_t *mesh = *it; bool isAdded = false; @@ -279,7 +279,7 @@ static MeshSet<3> *Carve_unionIntersectingMeshes(MeshSet<3> *poly, return poly; } - while(orig_meshes.size()) { + while (orig_meshes.size()) { MeshSet<3> *right = Carve_getIntersectedOperand(orig_meshes, otherAABB); if (!right) { diff --git a/intern/container/CTR_HashedPtr.h b/intern/container/CTR_HashedPtr.h index b7ac460f270..ee832eee153 100644 --- a/intern/container/CTR_HashedPtr.h +++ b/intern/container/CTR_HashedPtr.h @@ -46,13 +46,13 @@ class CTR_HashedPtr void *m_valptr; public: CTR_HashedPtr(void *val) : m_valptr(val) { - }; + } unsigned int hash() const { return CTR_Hash(m_valptr); - }; + } inline friend bool operator ==(const CTR_HashedPtr & rhs, const CTR_HashedPtr & lhs) { return rhs.m_valptr == lhs.m_valptr; - }; + } void *getValue() const { return m_valptr; } diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 7562ee0a0a5..12829f15aed 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -21,8 +21,11 @@ elseif(CMAKE_COMPILER_IS_GNUCC) endif() # for OSL -set(RTTI_DISABLE_FLAGS "-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID") -# set(RTTI_DISABLE_FLAGS "/GR- -DBOOST_NO_RTTI -DBOOST_NO_TYPEID") +if(WIN32 AND MSVC) + set(RTTI_DISABLE_FLAGS "/GR- -DBOOST_NO_RTTI -DBOOST_NO_TYPEID") +elseif(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang")) + set(RTTI_DISABLE_FLAGS "-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID") +endif() # Definitions and Includes @@ -44,10 +47,6 @@ if(WITH_CYCLES_OSL) include_directories(${OSL_INCLUDES}) endif() -if(WITH_CYCLES_PARTIO) - add_definitions(-DWITH_PARTIO) -endif() - if(WITH_CYCLES_CUDA_BINARIES) add_definitions(-DWITH_CUDA_BINARIES) endif() @@ -69,7 +68,10 @@ if(WITH_CYCLES_BLENDER) add_subdirectory(blender) endif() -add_subdirectory(app) +if(WITH_CYCLES_TEST) + add_subdirectory(app) +endif() + add_subdirectory(bvh) add_subdirectory(device) add_subdirectory(doc) diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript index c0e0353d37d..a0e2650ddc6 100644 --- a/intern/cycles/SConscript +++ b/intern/cycles/SConscript @@ -23,6 +23,10 @@ defs.append('WITH_OPENCL') defs.append('WITH_MULTI') defs.append('WITH_CUDA') +if env['WITH_BF_CYCLES_OSL']: + defs.append('WITH_OSL') + incs.append(cycles['BF_OSL_INC']) + if env['WITH_BF_CYCLES_CUDA_BINARIES']: defs.append('WITH_CUDA_BINARIES') @@ -32,7 +36,8 @@ incs.extend('#source/blender/blenloader ../../source/blender/makesrna/intern'.sp incs.extend('#extern/glew/include #intern/mikktspace'.split()) incs.append(cycles['BF_OIIO_INC']) incs.append(cycles['BF_BOOST_INC']) -incs.append(cycles['BF_PYTHON_INC']) +incs.append(cycles['BF_OPENEXR_INC'].split()) +incs.extend(cycles['BF_PYTHON_INC'].split()) if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): cxxflags.append('-D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc'.split()) @@ -44,7 +49,7 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', ' # optimized kernel if env['WITH_BF_RAYOPTIMIZATION']: - optim_cxxflags = [] + optim_cxxflags = Split(env['CXXFLAGS']) if env['OURPLATFORM'] == 'win32-vc': optim_cxxflags.append('/arch:SSE2 -D_CRT_SECURE_NO_WARNINGS /fp:fast /EHsc'.split()) @@ -62,6 +67,12 @@ if env['WITH_BF_RAYOPTIMIZATION']: cycles.BlenderLib('bf_intern_cycles', sources, incs, defs, libtype=['intern'], priority=[0], cxx_compileflags=cxxflags) +if env['WITH_BF_CYCLES_OSL']: + oso_files = SConscript(['kernel/shaders/SConscript']) + cycles.Depends("kernel/osl/osl_shader.o", oso_files) + + SConscript(['kernel/osl/SConscript']) + # cuda kernel binaries if env['WITH_BF_CYCLES_CUDA_BINARIES']: kernel_binaries = SConscript(['kernel/SConscript']) diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt index 83b3f731ffe..3fb8aaf934f 100644 --- a/intern/cycles/app/CMakeLists.txt +++ b/intern/cycles/app/CMakeLists.txt @@ -35,10 +35,6 @@ if(WITH_CYCLES_OSL) list(APPEND LIBRARIES cycles_kernel_osl ${OSL_LIBRARIES}) endif() -if(WITH_CYCLES_PARTIO) - list(APPEND LIBRARIES ${PARTIO_LIBRARIES}) -endif() - include_directories(${INC}) include_directories(SYSTEM ${INC_SYS}) diff --git a/intern/cycles/app/cycles_test.cpp b/intern/cycles/app/cycles_test.cpp index e921cc46fe4..625e8cc1706 100644 --- a/intern/cycles/app/cycles_test.cpp +++ b/intern/cycles/app/cycles_test.cpp @@ -326,7 +326,7 @@ using namespace ccl; int main(int argc, const char **argv) { - path_init("../build/bin/2.59/scripts/addons/cycles/"); + path_init(); options_parse(argc, argv); diff --git a/intern/cycles/blender/CCL_api.h b/intern/cycles/blender/CCL_api.h index 469d63d1530..b8a30b71717 100644 --- a/intern/cycles/blender/CCL_api.h +++ b/intern/cycles/blender/CCL_api.h @@ -23,12 +23,12 @@ extern "C" { #endif -/* returns a list of devices for selection, array is name NULL pointer +/* returns a list of devices for selection, array is empty identifier * terminated and must not be freed */ typedef struct CCLDeviceInfo { - const char *identifier; - const char *name; + char identifier[128]; + char name[512]; int value; } CCLDeviceInfo; diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index 16697c08b2b..0fad2ac5618 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -48,7 +48,11 @@ class CyclesRender(bpy.types.RenderEngine): # final render def update(self, data, scene): - engine.create(self, data, scene) + if not self.session: + engine.create(self, data, scene) + else: + engine.reset(self, data, scene) + engine.update(self, data, scene) def render(self, scene): diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index e4f80cb4d5d..ca5cbee9325 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -61,6 +61,13 @@ def render(engine): _cycles.render(engine.session) +def reset(engine, data, scene): + import _cycles + data = data.as_pointer() + scene = scene.as_pointer() + _cycles.reset(engine.session, data, scene) + + def update(engine, data, scene): import _cycles _cycles.sync(engine.session) diff --git a/intern/cycles/blender/addon/enums.py b/intern/cycles/blender/addon/enums.py index dd7a555c2a8..82b48973ca1 100644 --- a/intern/cycles/blender/addon/enums.py +++ b/intern/cycles/blender/addon/enums.py @@ -57,7 +57,7 @@ aperture_types = ( panorama_types = ( ('EQUIRECTANGULAR', "Equirectangular", "Render the scene with a spherical camera, also known as Lat Long panorama"), - ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ignore the sensor dimensions"), - ('FISHEYE_EQUISOLID', "Fisheye Equisolid", "Similar to most fisheye modern lens, take sensor dimensions into consideration. For fulldomes use it with a square sensor ratio", + ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ideal for fulldomes, ignore the sensor dimensions"), + ('FISHEYE_EQUISOLID', "Fisheye Equisolid", + "Similar to most fisheye modern lens, takes sensor dimensions into consideration"), ) - diff --git a/intern/cycles/blender/addon/osl.py b/intern/cycles/blender/addon/osl.py index aac1e2422b9..79ce3df20c3 100644 --- a/intern/cycles/blender/addon/osl.py +++ b/intern/cycles/blender/addon/osl.py @@ -79,12 +79,13 @@ def update_script_node(node, report): if script.is_in_memory or script.is_dirty or script.is_modified or not os.path.exists(osl_path): # write text datablock contents to temporary file - osl_file = tempfile.NamedTemporaryFile(mode='w', suffix=".osl", delete=True) + osl_file = tempfile.NamedTemporaryFile(mode='w', suffix=".osl", delete=False) osl_file.write(script.as_string()) - osl_file.flush() + osl_file.close() + ok, oso_path = osl_compile(osl_file.name, report) oso_file_remove = False - osl_file.close() + os.remove(osl_file.name) else: # compile text datablock from disk directly ok, oso_path = osl_compile(osl_path, report) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 9cc58e65bef..ba931469e8a 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -216,6 +216,10 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel): sub.label(text="Viewport:") sub.prop(cscene, "preview_start_resolution") + sub = col.column(align=True) + sub.label(text="Final Render:") + sub.prop(rd, "use_persistent_data", text="Persistent Images") + class CyclesRender_PT_layers(CyclesButtonsPanel, Panel): bl_label = "Layers" @@ -953,7 +957,7 @@ def draw_device(self, context): elif device_type == 'OPENCL' and cscene.feature_set == 'EXPERIMENTAL': layout.prop(cscene, "device") - if engine.with_osl() and (cscene.device == 'CPU' or device_type == 'None'): + if engine.with_osl() and (cscene.device == 'CPU' or device_type == 'NONE'): layout.prop(cscene, "shading_system") @@ -1022,6 +1026,8 @@ def get_panels(): bpy.types.TEXTURE_PT_voxeldata, bpy.types.TEXTURE_PT_pointdensity, bpy.types.TEXTURE_PT_pointdensity_turbulence, + bpy.types.TEXTURE_PT_mapping, + bpy.types.TEXTURE_PT_influence, bpy.types.PARTICLE_PT_context_particles, bpy.types.PARTICLE_PT_emission, bpy.types.PARTICLE_PT_hair_dynamics, diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index af16e210301..0cbd2a0291f 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -56,15 +56,16 @@ struct BlenderCamera { float sensor_width; float sensor_height; - float border_left; - float border_right; - float border_bottom; - float border_top; + int full_width; + int full_height; + + BoundBox2D border; + BoundBox2D pano_viewplane; Transform matrix; }; -static void blender_camera_init(BlenderCamera *bcam) +static void blender_camera_init(BlenderCamera *bcam, BL::Scene b_scene) { memset(bcam, 0, sizeof(BlenderCamera)); @@ -75,8 +76,16 @@ static void blender_camera_init(BlenderCamera *bcam) bcam->sensor_height = 18.0f; bcam->sensor_fit = BlenderCamera::AUTO; bcam->shuttertime = 1.0f; - bcam->border_right = 1.0f; - bcam->border_top = 1.0f; + bcam->border.right = 1.0f; + bcam->border.top = 1.0f; + bcam->pano_viewplane.right = 1.0f; + bcam->pano_viewplane.top = 1.0f; + + /* render resolution */ + BL::RenderSettings r = b_scene.render(); + + bcam->full_width = (int)(r.resolution_x()*r.resolution_percentage()/100); + bcam->full_height = (int)(r.resolution_y()*r.resolution_percentage()/100); } static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera) @@ -199,7 +208,7 @@ static Transform blender_camera_matrix(const Transform& tfm, CameraType type) } static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height, - float *left, float *right, float *bottom, float *top, float *aspectratio, float *sensor_size) + BoundBox2D *viewplane, float *aspectratio, float *sensor_size) { /* dimensions */ float xratio = width*bcam->pixelaspect.x; @@ -207,10 +216,9 @@ static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height, /* compute x/y aspect and ratio */ float xaspect, yaspect; - - /* sensor fitting */ bool horizontal_fit; + /* sensor fitting */ if(bcam->sensor_fit == BlenderCamera::AUTO) { horizontal_fit = (xratio > yratio); *sensor_size = bcam->sensor_width; @@ -244,32 +252,26 @@ static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height, if(bcam->type == CAMERA_PANORAMA) { /* set viewplane */ - *left = 0.0f; - *right = 1.0f; - *bottom = 0.0f; - *top = 1.0f; + *viewplane = bcam->pano_viewplane; } else { /* set viewplane */ - *left = -xaspect; - *right = xaspect; - *bottom = -yaspect; - *top = yaspect; + viewplane->left = -xaspect; + viewplane->right = xaspect; + viewplane->bottom = -yaspect; + viewplane->top = yaspect; /* zoom for 3d camera view */ - *left *= bcam->zoom; - *right *= bcam->zoom; - *bottom *= bcam->zoom; - *top *= bcam->zoom; + *viewplane = (*viewplane) * bcam->zoom; /* modify viewplane with camera shift and 3d camera view offset */ float dx = 2.0f*(*aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f); float dy = 2.0f*(*aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f); - *left += dx; - *right += dx; - *bottom += dy; - *top += dy; + viewplane->left += dx; + viewplane->right += dx; + viewplane->bottom += dy; + viewplane->top += dy; } } @@ -281,11 +283,37 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int /* viewplane */ blender_camera_viewplane(bcam, width, height, - &cam->left, &cam->right, &cam->bottom, &cam->top, &aspectratio, &sensor_size); + &cam->viewplane, &aspectratio, &sensor_size); - /* sensor */ - cam->sensorwidth = bcam->sensor_width; - cam->sensorheight = bcam->sensor_height; + /* panorama sensor */ + if (bcam->type == CAMERA_PANORAMA && bcam->panorama_type == PANORAMA_FISHEYE_EQUISOLID) { + float fit_xratio = bcam->full_width*bcam->pixelaspect.x; + float fit_yratio = bcam->full_height*bcam->pixelaspect.y; + bool horizontal_fit; + float sensor_size; + + if(bcam->sensor_fit == BlenderCamera::AUTO) { + horizontal_fit = (fit_xratio > fit_yratio); + sensor_size = bcam->sensor_width; + } + else if(bcam->sensor_fit == BlenderCamera::HORIZONTAL) { + horizontal_fit = true; + sensor_size = bcam->sensor_width; + } + else { /* vertical */ + horizontal_fit = false; + sensor_size = bcam->sensor_height; + } + + if(horizontal_fit) { + cam->sensorwidth = sensor_size; + cam->sensorheight = sensor_size * fit_yratio / fit_xratio; + } + else { + cam->sensorwidth = sensor_size * fit_xratio / fit_yratio; + cam->sensorheight = sensor_size; + } + } /* clipping distances */ cam->nearclip = bcam->nearclip; @@ -314,10 +342,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int cam->shuttertime = bcam->shuttertime; /* border */ - cam->border_left = bcam->border_left; - cam->border_right = bcam->border_right; - cam->border_bottom = bcam->border_bottom; - cam->border_top = bcam->border_top; + cam->border = bcam->border; /* set update flag */ if(cam->modified(prevcam)) @@ -329,7 +354,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int void BlenderSync::sync_camera(BL::Object b_override, int width, int height) { BlenderCamera bcam; - blender_camera_init(&bcam); + blender_camera_init(&bcam, b_scene); /* pixel aspect */ BL::RenderSettings r = b_scene.render(); @@ -340,10 +365,10 @@ void BlenderSync::sync_camera(BL::Object b_override, int width, int height) /* border */ if(r.use_border()) { - bcam.border_left = r.border_min_x(); - bcam.border_right = r.border_max_x(); - bcam.border_bottom = r.border_min_y(); - bcam.border_top = r.border_max_y(); + bcam.border.left = r.border_min_x(); + bcam.border.right = r.border_max_x(); + bcam.border.bottom = r.border_min_y(); + bcam.border.top = r.border_max_y(); } /* camera object */ @@ -381,6 +406,9 @@ void BlenderSync::sync_camera_motion(BL::Object b_ob, int motion) /* Sync 3D View Camera */ +static void blender_camera_view_subset(BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d, + BL::RegionView3D b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box); + static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height, bool skip_panorama = false) { /* 3d view parameters */ @@ -396,14 +424,25 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL: if(b_ob) { blender_camera_from_object(bcam, b_ob, skip_panorama); - /* magic zoom formula */ - bcam->zoom = (float)b_rv3d.view_camera_zoom(); - bcam->zoom = (1.41421f + bcam->zoom/50.0f); - bcam->zoom *= bcam->zoom; - bcam->zoom = 2.0f/bcam->zoom; + if(!skip_panorama && bcam->type == CAMERA_PANORAMA) { + /* in panorama camera view, we map viewplane to camera border */ + BoundBox2D view_box, cam_box; - /* offset */ - bcam->offset = get_float2(b_rv3d.view_camera_offset()); + blender_camera_view_subset(b_scene, b_ob, b_v3d, b_rv3d, width, height, + &view_box, &cam_box); + + bcam->pano_viewplane = view_box.make_relative_to(cam_box); + } + else { + /* magic zoom formula */ + bcam->zoom = (float)b_rv3d.view_camera_zoom(); + bcam->zoom = (1.41421f + bcam->zoom/50.0f); + bcam->zoom *= bcam->zoom; + bcam->zoom = 2.0f/bcam->zoom; + + /* offset */ + bcam->offset = get_float2(b_rv3d.view_camera_offset()); + } } } else if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_ORTHO) { @@ -427,6 +466,34 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL: bcam->matrix = transform_inverse(get_transform(b_rv3d.view_matrix())); } +static void blender_camera_view_subset(BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d, + BL::RegionView3D b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box) +{ +// BL::RenderSettings r = b_scene.render(); /* UNUSED */ + BoundBox2D cam, view; + float view_aspect, cam_aspect, sensor_size; + + /* get viewport viewplane */ + BlenderCamera view_bcam; + blender_camera_init(&view_bcam, b_scene); + blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height, true); + + blender_camera_viewplane(&view_bcam, width, height, + &view, &view_aspect, &sensor_size); + + /* get camera viewplane */ + BlenderCamera cam_bcam; + blender_camera_init(&cam_bcam, b_scene); + blender_camera_from_object(&cam_bcam, b_ob, true); + + blender_camera_viewplane(&cam_bcam, cam_bcam.full_width, cam_bcam.full_height, + &cam, &cam_aspect, &sensor_size); + + /* return */ + *view_box = view * (1.0f/view_aspect); + *cam_box = cam * (1.0f/cam_aspect); +} + static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height) { @@ -442,10 +509,10 @@ static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::Sp * assume viewport has got correctly clamped border already */ if(b_v3d.use_render_border()) { - bcam->border_left = b_v3d.render_border_min_x(); - bcam->border_right = b_v3d.render_border_max_x(); - bcam->border_bottom = b_v3d.render_border_min_y(); - bcam->border_top = b_v3d.render_border_max_y(); + bcam->border.left = b_v3d.render_border_min_x(); + bcam->border.right = b_v3d.render_border_max_x(); + bcam->border.bottom = b_v3d.render_border_min_y(); + bcam->border.top = b_v3d.render_border_max_y(); return; } @@ -458,66 +525,26 @@ static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::Sp if(!b_ob) return; - bcam->border_left = r.border_min_x(); - bcam->border_right = r.border_max_x(); - bcam->border_bottom = r.border_min_y(); - bcam->border_top = r.border_max_y(); + bcam->border.left = r.border_min_x(); + bcam->border.right = r.border_max_x(); + bcam->border.bottom = r.border_min_y(); + bcam->border.top = r.border_max_y(); - float cam_left, cam_right, cam_bottom, cam_top; - float view_left, view_right, view_bottom, view_top; - float view_aspect, cam_aspect, sensor_size; + /* determine camera viewport subset */ + BoundBox2D view_box, cam_box; - /* get viewport viewplane */ - BlenderCamera view_bcam; - blender_camera_init(&view_bcam); - blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height, true); - - blender_camera_viewplane(&view_bcam, width, height, - &view_left, &view_right, &view_bottom, &view_top, &view_aspect, &sensor_size); - - view_left /= view_aspect; - view_right /= view_aspect; - view_bottom /= view_aspect; - view_top /= view_aspect; - - /* get camera viewplane */ - BlenderCamera cam_bcam; - blender_camera_init(&cam_bcam); - blender_camera_from_object(&cam_bcam, b_ob, true); - - width = (int)(r.resolution_x()*r.resolution_percentage()/100); - height = (int)(r.resolution_y()*r.resolution_percentage()/100); - - blender_camera_viewplane(&cam_bcam, width, height, - &cam_left, &cam_right, &cam_bottom, &cam_top, &cam_aspect, &sensor_size); - - cam_left /= cam_aspect; - cam_right /= cam_aspect; - cam_bottom /= cam_aspect; - cam_top /= cam_aspect; + blender_camera_view_subset(b_scene, b_ob, b_v3d, b_rv3d, width, height, + &view_box, &cam_box); /* determine viewport subset matching camera border */ - float tmp_left = ((cam_left - view_left) / (view_right - view_left)); - float tmp_right = ((cam_right - view_left) / (view_right - view_left)); - float tmp_bottom = ((cam_bottom - view_bottom) / (view_top - view_bottom)); - float tmp_top = ((cam_top - view_bottom) / (view_top - view_bottom)); - - bcam->border_left = tmp_left + bcam->border_left*(tmp_right - tmp_left); - bcam->border_right = tmp_left + bcam->border_right*(tmp_right - tmp_left); - bcam->border_bottom = tmp_bottom + bcam->border_bottom*(tmp_top - tmp_bottom); - bcam->border_top = tmp_bottom + bcam->border_top*(tmp_top - tmp_bottom); - - /* clamp */ - bcam->border_left = clamp(bcam->border_left, 0.0f, 1.0f); - bcam->border_right = clamp(bcam->border_right, 0.0f, 1.0f); - bcam->border_bottom = clamp(bcam->border_bottom, 0.0f, 1.0f); - bcam->border_top = clamp(bcam->border_top, 0.0f, 1.0f); + cam_box = cam_box.make_relative_to(view_box); + bcam->border = cam_box.subset(bcam->border).clamp(); } void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height) { BlenderCamera bcam; - blender_camera_init(&bcam); + blender_camera_init(&bcam, b_scene); blender_camera_from_view(&bcam, b_scene, b_v3d, b_rv3d, width, height); blender_camera_border(&bcam, b_scene, b_v3d, b_rv3d, width, height); @@ -539,10 +566,10 @@ BufferParams BlenderSync::get_buffer_params(BL::Scene b_scene, BL::SpaceView3D b if(use_border) { /* border render */ - params.full_x = cam->border_left*width; - params.full_y = cam->border_bottom*height; - params.width = (int)(cam->border_right*width) - params.full_x; - params.height = (int)(cam->border_top*height) - params.full_y; + params.full_x = cam->border.left*width; + params.full_y = cam->border.bottom*height; + params.width = (int)(cam->border.right*width) - params.full_x; + params.height = (int)(cam->border.top*height) - params.full_y; /* survive in case border goes out of view or becomes too small */ params.width = max(params.width, 1); diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 0e13479a761..c9748756d43 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -116,7 +116,7 @@ static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const floa userdata->tangent[face*4 + vert] = make_float4(T[0], T[1], T[2], sign); } -static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_layer, Mesh *mesh, vector& nverts) +static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_layer, Mesh *mesh, vector& nverts, bool need_sign, bool active_render) { /* setup userdata */ MikkUserData userdata(b_mesh, b_layer, nverts.size()); @@ -140,22 +140,57 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_la /* compute tangents */ genTangSpaceDefault(&context); - /* create attribute */ - /* todo: create float4 attribute for sign */ - Attribute *attr = mesh->attributes.add(ATTR_STD_TANGENT, ustring("tangent")); + /* create tangent attributes */ + Attribute *attr; + ustring name = ustring((string(b_layer.name().c_str()) + ".tangent").c_str()); + + if(active_render) + attr = mesh->attributes.add(ATTR_STD_UV_TANGENT, name); + else + attr = mesh->attributes.add(name, TypeDesc::TypeVector, Attribute::CORNER); + float3 *tangent = attr->data_float3(); - for (int i = 0; i < nverts.size(); i++) { + /* create bitangent sign attribute */ + float *tangent_sign = NULL; + + if(need_sign) { + Attribute *attr_sign; + ustring name_sign = ustring((string(b_layer.name().c_str()) + ".tangent_sign").c_str()); + + if(active_render) + attr_sign = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign); + else + attr_sign = mesh->attributes.add(name_sign, TypeDesc::TypeFloat, Attribute::CORNER); + + tangent_sign = attr_sign->data_float(); + } + + for(int i = 0; i < nverts.size(); i++) { tangent[0] = float4_to_float3(userdata.tangent[i*4 + 0]); tangent[1] = float4_to_float3(userdata.tangent[i*4 + 1]); tangent[2] = float4_to_float3(userdata.tangent[i*4 + 2]); tangent += 3; + if(tangent_sign) { + tangent_sign[0] = userdata.tangent[i*4 + 0].w; + tangent_sign[1] = userdata.tangent[i*4 + 1].w; + tangent_sign[2] = userdata.tangent[i*4 + 2].w; + tangent_sign += 3; + } + if(nverts[i] == 4) { tangent[0] = float4_to_float3(userdata.tangent[i*4 + 0]); tangent[1] = float4_to_float3(userdata.tangent[i*4 + 2]); tangent[2] = float4_to_float3(userdata.tangent[i*4 + 3]); tangent += 3; + + if(tangent_sign) { + tangent_sign[0] = userdata.tangent[i*4 + 0].w; + tangent_sign[1] = userdata.tangent[i*4 + 2].w; + tangent_sign[2] = userdata.tangent[i*4 + 3].w; + tangent_sign += 3; + } } } } @@ -233,48 +268,49 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< BL::Mesh::tessface_uv_textures_iterator l; for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) { - AttributeStandard std = (l->active_render())? ATTR_STD_UV: ATTR_STD_NONE; + bool active_render = l->active_render(); + AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE; ustring name = ustring(l->name().c_str()); - if(!(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std))) - continue; + /* UV map */ + if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) { + Attribute *attr; - Attribute *attr; + if(active_render) + attr = mesh->attributes.add(std, name); + else + attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER); - if(l->active_render()) - attr = mesh->attributes.add(std, name); - else - attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER); + BL::MeshTextureFaceLayer::data_iterator t; + float3 *fdata = attr->data_float3(); + size_t i = 0; - BL::MeshTextureFaceLayer::data_iterator t; - float3 *fdata = attr->data_float3(); - size_t i = 0; - - for(l->data.begin(t); t != l->data.end(); ++t, ++i) { - fdata[0] = get_float3(t->uv1()); - fdata[1] = get_float3(t->uv2()); - fdata[2] = get_float3(t->uv3()); - fdata += 3; - - if(nverts[i] == 4) { + for(l->data.begin(t); t != l->data.end(); ++t, ++i) { fdata[0] = get_float3(t->uv1()); - fdata[1] = get_float3(t->uv3()); - fdata[2] = get_float3(t->uv4()); + fdata[1] = get_float3(t->uv2()); + fdata[2] = get_float3(t->uv3()); fdata += 3; + + if(nverts[i] == 4) { + fdata[0] = get_float3(t->uv1()); + fdata[1] = get_float3(t->uv3()); + fdata[2] = get_float3(t->uv4()); + fdata += 3; + } } } - } - } - /* create texcoord-based tangent attributes */ - if(mesh->need_attribute(scene, ATTR_STD_TANGENT)) { - BL::Mesh::tessface_uv_textures_iterator l; + /* UV tangent */ + std = (active_render)? ATTR_STD_UV_TANGENT: ATTR_STD_NONE; + name = ustring((string(l->name().c_str()) + ".tangent").c_str()); - for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) { - if(!l->active_render()) - continue; + if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) { + std = (active_render)? ATTR_STD_UV_TANGENT_SIGN: ATTR_STD_NONE; + name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str()); + bool need_sign = (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)); - mikk_compute_tangents(b_mesh, *l, mesh, nverts); + mikk_compute_tangents(b_mesh, *l, mesh, nverts, need_sign, active_render); + } } } diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 1b920249733..38f27bcf2af 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -86,11 +86,11 @@ static uint object_ray_visibility(BL::Object b_ob) /* Light */ -void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm) +void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm) { /* test if we need to sync */ Light *light; - ObjectKey key(b_parent, b_index, b_ob); + ObjectKey key(b_parent, persistent_id, b_ob); if(!light_map.sync(&light, b_ob, b_parent, key)) return; @@ -196,23 +196,24 @@ void BlenderSync::sync_background_light() /* Object */ -void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject b_dupli_ob, Transform& tfm, uint layer_flag, int motion, int particle_id) +Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob, Transform& tfm, uint layer_flag, int motion) { BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent); /* light is handled separately */ if(object_is_light(b_ob)) { if(!motion) - sync_light(b_parent, b_index, b_ob, tfm); - return; + sync_light(b_parent, persistent_id, b_ob, tfm); + + return NULL; } /* only interested in object that we can create meshes from */ if(!object_is_mesh(b_ob)) - return; + return NULL; /* key to lookup object */ - ObjectKey key(b_parent, b_index, b_ob); + ObjectKey key(b_parent, persistent_id, b_ob); Object *object; /* motion vector case */ @@ -234,7 +235,7 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject sync_mesh_motion(b_ob, object->mesh, motion); } - return; + return object; } /* test if we need to sync */ @@ -248,13 +249,15 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject /* mesh sync */ object->mesh = sync_mesh(b_ob, object_updated); + /* sspecial case not tracked by object update flags */ if(use_holdout != object->use_holdout) { object->use_holdout = use_holdout; scene->object_manager->tag_update(scene); + object_updated = true; } - /* object sync */ - /* transform comparison should not be needed, but duplis don't work perfect + /* object sync + * transform comparison should not be needed, but duplis don't work perfect * in the depsgraph and may not signal changes, so this is a workaround */ if(object_updated || (object->mesh && object->mesh->need_update) || tfm != object->tfm) { object->name = b_ob.name().c_str(); @@ -264,7 +267,15 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject object->motion.post = tfm; object->use_motion = false; - object->random_id = hash_int_2d(hash_string(object->name.c_str()), b_index); + /* random number */ + object->random_id = hash_string(object->name.c_str()); + + if(persistent_id) { + for(int i = 0; i < OBJECT_PERSISTENT_ID_SIZE; i++) + object->random_id = hash_int_2d(object->random_id, persistent_id[i]); + } + else + object->random_id = hash_int_2d(object->random_id, 0); /* visibility flags for both parent */ object->visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL; @@ -273,6 +284,10 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject object->random_id ^= hash_int(hash_string(b_parent.name().c_str())); } + /* make holdout objects on excluded layer invisible for non-camera rays */ + if(use_holdout && (layer_flag & render_layer.exclude_layer)) + object->visibility &= ~(PATH_RAY_ALL - PATH_RAY_CAMERA); + /* camera flag is not actually used, instead is tested * against render layer flags */ if(object->visibility & PATH_RAY_CAMERA) { @@ -289,10 +304,17 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject object->dupli_uv = make_float2(0.0f, 0.0f); } - object->particle_id = particle_id; - object->tag_update(scene); } + + return object; +} + +static bool object_dupli_hide_original(BL::Object::dupli_type_enum dupli_type) +{ + return (dupli_type == BL::Object::dupli_type_VERTS || + dupli_type == BL::Object::dupli_type_FACES || + dupli_type == BL::Object::dupli_type_FRAMES); } /* Object Loop */ @@ -314,7 +336,9 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) /* object loop */ BL::Scene::objects_iterator b_ob; BL::Scene b_sce = b_scene; - int particle_offset = 1; /* first particle is dummy for regular, non-instanced objects */ + + /* global particle index counter */ + int particle_id = 1; bool cancel = false; @@ -327,16 +351,14 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) if(!hide) { progress.set_sync_status("Synchronizing object", (*b_ob).name()); - int num_particles = object_count_particles(*b_ob); - if(b_ob->is_duplicator()) { - hide = true; /* duplicators hidden by default */ + /* duplicators hidden by default */ + hide = true; /* dupli objects */ b_ob->dupli_list_create(b_scene, 2); BL::Object::dupli_list_iterator b_dup; - int b_index = 0; for(b_ob->dupli_list.begin(b_dup); b_dup != b_ob->dupli_list.end(); ++b_dup) { Transform tfm = get_transform(b_dup->matrix()); @@ -345,7 +367,9 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) bool emitter_hide = false; if(b_dup_ob.is_duplicator()) { - emitter_hide = true; /* duplicators hidden by default */ + /* duplicators hidden by default, except dupliframes which duplicate self */ + if(b_dup_ob.dupli_type() != BL::Object::dupli_type_FRAMES) + emitter_hide = true; /* check if we should render or hide particle emitter */ BL::Object::particle_systems_iterator b_psys; @@ -354,33 +378,54 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) emitter_hide = false; } + /* hide original object for duplis */ + BL::Object parent = b_dup_ob.parent(); + if(parent && object_dupli_hide_original(parent.dupli_type())) + if(b_dup->type() == BL::DupliObject::type_GROUP) + dup_hide = true; + if(!(b_dup->hide() || dup_hide || emitter_hide)) { - sync_object(*b_ob, b_index, *b_dup, tfm, ob_layer, motion, b_dup->particle_index() + particle_offset); + /* the persistent_id allows us to match dupli objects + * between frames and updates */ + BL::Array persistent_id = b_dup->persistent_id(); + + /* sync object and mesh or light data */ + Object *object = sync_object(*b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion); + + /* sync possible particle data, note particle_id + * starts counting at 1, first is dummy particle */ + if(!motion && object && sync_dupli_particle(*b_ob, *b_dup, object)) { + if(particle_id != object->particle_id) { + object->particle_id = particle_id; + scene->object_manager->tag_update(scene); + } + + particle_id++; + } + } - - ++b_index; } b_ob->dupli_list_clear(); } - /* sync particles and check if we should render or hide particle emitter */ + /* check if we should render or hide particle emitter */ BL::Object::particle_systems_iterator b_psys; - for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) { - if(!motion) - sync_particles(*b_ob, *b_psys); + for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) if(b_psys->settings().use_render_emitter()) hide = false; - } + + /* hide original object for duplis */ + BL::Object parent = b_ob->parent(); + if(parent && object_dupli_hide_original(parent.dupli_type())) + hide = true; if(!hide) { /* object itself */ Transform tfm = get_transform(b_ob->matrix_world()); - sync_object(*b_ob, 0, PointerRNA_NULL, tfm, ob_layer, motion, 0); + sync_object(*b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion); } - - particle_offset += num_particles; } cancel = progress.get_cancel(); diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp index c4c6d2f79a3..769cd9f532d 100644 --- a/intern/cycles/blender/blender_particles.cpp +++ b/intern/cycles/blender/blender_particles.cpp @@ -17,6 +17,7 @@ */ #include "mesh.h" +#include "object.h" #include "particles.h" #include "blender_sync.h" @@ -28,170 +29,57 @@ CCL_NAMESPACE_BEGIN /* Utilities */ - -/* Particles Sync */ - -bool BlenderSync::psys_need_update(BL::ParticleSystem b_psys) +bool BlenderSync::sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Object *object) { - /* Particle data is only needed for - * a) Billboard render mode if object's own material uses particle info - * b) object/group render mode if any dupli object's material uses particle info - * - * Note: Meshes have to be synced at this point! - */ - bool need_update = false; - - switch (b_psys.settings().render_type()) { - /* XXX not implemented yet! - * billboards/strands would become part of the mesh data (?), - * so the mesh attributes would store whether particle info is required. - */ - #if 0 - case BL::ParticleSettings::render_type_BILLBOARD: - case BL::ParticleSettings::render_type_PATH: { /* for strand rendering */ - BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob.data(); - Mesh *mesh = mesh_map.find(key); - if(mesh) { - need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update; - } - break; - } - #endif - - case BL::ParticleSettings::render_type_OBJECT: { - BL::Object b_dupli_ob = b_psys.settings().dupli_object(); - if(b_dupli_ob) { - BL::ID key = (BKE_object_is_modified(b_dupli_ob))? b_dupli_ob: b_dupli_ob.data(); - Mesh *mesh = mesh_map.find(key); - if(mesh) { - need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update; - } - } - break; - } - - case BL::ParticleSettings::render_type_GROUP: { - BL::Group b_dupli_group = b_psys.settings().dupli_group(); - if(b_dupli_group) { - BL::Group::objects_iterator b_gob; - for (b_dupli_group.objects.begin(b_gob); b_gob != b_dupli_group.objects.end(); ++b_gob) { - BL::ID key = (BKE_object_is_modified(*b_gob))? *b_gob: b_gob->data(); - Mesh *mesh = mesh_map.find(key); - if(mesh) { - need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update; - } - } - } - break; - } - - default: - /* avoid compiler warning */ - break; + /* test if this dupli was generated from a particle sytem */ + BL::ParticleSystem b_psys = b_dup.particle_system(); + if(!b_psys) + return false; + + /* test if we need particle data */ + if(!object->mesh->need_attribute(scene, ATTR_STD_PARTICLE)) + return false; + + /* don't handle child particles yet */ + BL::Array persistent_id = b_dup.persistent_id(); + + if(persistent_id[0] >= b_psys.particles.length()) + return false; + + /* find particle system */ + ParticleSystemKey key(b_ob, persistent_id); + ParticleSystem *psys; + + bool first_use = !particle_system_map.is_used(key); + bool need_update = particle_system_map.sync(&psys, b_ob, b_dup.object(), key); + + /* no update needed? */ + if(!need_update && !object->mesh->need_update && !scene->object_manager->need_update) + return true; + + /* first time used in this sync loop? clear and tag update */ + if(first_use) { + psys->particles.clear(); + psys->tag_update(scene); } - - return need_update; -} -static bool use_particle_system(BL::ParticleSystem b_psys) -{ - /* only use duplicator particles? disabled particle info for - * halo and billboard to reduce particle count. - * Probably not necessary since particles don't contain a huge amount - * of data compared to other textures. - */ - #if 0 - int render_type = b_psys->settings().render_type(); - return (render_type == BL::ParticleSettings::render_type_OBJECT - || render_type == BL::ParticleSettings::render_type_GROUP); - #endif + /* add particle */ + BL::Particle b_pa = b_psys.particles[persistent_id[0]]; + Particle pa; + pa.index = persistent_id[0]; + pa.age = b_scene.frame_current() - b_pa.birth_time(); + pa.lifetime = b_pa.lifetime(); + pa.location = get_float3(b_pa.location()); + pa.rotation = get_float4(b_pa.rotation()); + pa.size = b_pa.size(); + pa.velocity = get_float3(b_pa.velocity()); + pa.angular_velocity = get_float3(b_pa.angular_velocity()); + + psys->particles.push_back(pa); + + /* return that this object has particle data */ return true; } -static bool use_particle(BL::Particle b_pa, bool preview, bool show_unborn, bool use_dead) -{ - return b_pa.is_exist() && (!preview || b_pa.is_visible()) && - (b_pa.alive_state() != BL::Particle::alive_state_UNBORN || show_unborn) && - (b_pa.alive_state() != BL::Particle::alive_state_DEAD || use_dead); -} - -static int psys_count_particles(BL::ParticleSystem b_psys, bool preview) -{ - BL::ParticleSystem::particles_iterator b_pa; - bool show_unborn = b_psys.settings().show_unborn(); - bool use_dead = b_psys.settings().use_dead(); - int num = 0; - - for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) - if(use_particle(*b_pa, preview, show_unborn, use_dead)) - ++num; - - return num; -} - -int BlenderSync::object_count_particles(BL::Object b_ob) -{ - BL::Object::particle_systems_iterator b_psys; - int num = 0; - - for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) - if(use_particle_system(*b_psys)) - num += psys_count_particles(*b_psys, preview); - - return num; -} - -void BlenderSync::sync_particles(BL::Object b_ob, BL::ParticleSystem b_psys) -{ - /* depending on settings the psys may not even be rendered */ - if(!use_particle_system(b_psys)) - return; - - /* key to lookup particle system */ - ParticleSystemKey key(b_ob, b_psys); - ParticleSystem *psys; - - /* test if we need to sync */ - bool object_updated = false; - - if(particle_system_map.sync(&psys, b_ob, b_ob, key)) - object_updated = true; - - bool need_update = psys_need_update(b_psys); - - if(object_updated || need_update) { - bool show_unborn = b_psys.settings().show_unborn(); - bool use_dead = b_psys.settings().use_dead(); - - int num = psys_count_particles(b_psys, preview); - psys->particles.clear(); - psys->particles.reserve(num); - - BL::ParticleSystem::particles_iterator b_pa; - int index = 0; - - for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) { - if(use_particle(*b_pa, preview, show_unborn, use_dead)) { - Particle pa; - - pa.index = index; - pa.age = b_scene.frame_current() - b_pa->birth_time(); - pa.lifetime = b_pa->lifetime(); - pa.location = get_float3(b_pa->location()); - pa.rotation = get_float4(b_pa->rotation()); - pa.size = b_pa->size(); - pa.velocity = get_float3(b_pa->velocity()); - pa.angular_velocity = get_float3(b_pa->angular_velocity()); - - psys->particles.push_back(pa); - } - - ++index; - } - - psys->tag_update(scene); - } -} - CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index c047805c6ae..d164920ceff 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -146,6 +146,32 @@ static PyObject *draw_func(PyObject *self, PyObject *args) Py_RETURN_NONE; } +static PyObject *reset_func(PyObject *self, PyObject *args) +{ + PyObject *pysession, *pydata, *pyscene; + + if(!PyArg_ParseTuple(args, "OOO", &pysession, &pydata, &pyscene)) + return NULL; + + BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession); + + PointerRNA dataptr; + RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pydata), &dataptr); + BL::BlendData b_data(dataptr); + + PointerRNA sceneptr; + RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyscene), &sceneptr); + BL::Scene b_scene(sceneptr); + + Py_BEGIN_ALLOW_THREADS + + session->reset_session(b_data, b_scene); + + Py_END_ALLOW_THREADS + + Py_RETURN_NONE; +} + static PyObject *sync_func(PyObject *self, PyObject *value) { Py_BEGIN_ALLOW_THREADS @@ -217,6 +243,7 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args) float default_float4[4] = {0.0f, 0.0f, 0.0f, 1.0f}; float default_float = 0.0f; int default_int = 0; + std::string default_string = ""; if(param->isclosure) { socket_type = BL::NodeSocket::type_SHADER; @@ -252,6 +279,13 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args) if(param->validdefault) default_float = param->fdefault[0]; } + else if(param->type.basetype == TypeDesc::STRING) { + socket_type = BL::NodeSocket::type_STRING; + if(param->validdefault) + default_string = param->sdefault[0]; + } + else + continue; } else continue; @@ -286,6 +320,10 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args) BL::NodeSocketVectorNone b_vector_sock(b_sock.ptr); b_vector_sock.default_value(default_float4); } + else if(socket_type == BL::NodeSocket::type_STRING) { + BL::NodeSocketStringNone b_string_sock(b_sock.ptr); + b_string_sock.default_value(default_string); + } } used_sockets.insert(b_sock.ptr.data); @@ -342,6 +380,7 @@ static PyMethodDef methods[] = { {"render", render_func, METH_O, ""}, {"draw", draw_func, METH_VARARGS, ""}, {"sync", sync_func, METH_O, ""}, + {"reset", reset_func, METH_VARARGS, ""}, #ifdef WITH_OSL {"osl_update_node", osl_update_node_func, METH_VARARGS, ""}, {"osl_compile", osl_compile_func, METH_VARARGS, ""}, @@ -379,14 +418,23 @@ static CCLDeviceInfo *compute_device_list(DeviceType type) if(info.type == type || (info.type == DEVICE_MULTI && info.multi_devices[0].type == type)) { - CCLDeviceInfo cinfo = {info.id.c_str(), info.description.c_str(), i++}; + CCLDeviceInfo cinfo; + + strncpy(cinfo.identifier, info.id.c_str(), sizeof(cinfo.identifier)); + cinfo.identifier[info.id.length()] = '\0'; + + strncpy(cinfo.name, info.description.c_str(), sizeof(cinfo.name)); + cinfo.name[info.description.length()] = '\0'; + + cinfo.value = i++; + device_list.push_back(cinfo); } } /* null terminate */ if(!device_list.empty()) { - CCLDeviceInfo cinfo = {NULL, NULL, 0}; + CCLDeviceInfo cinfo = {"", "", 0}; device_list.push_back(cinfo); } } diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 01bd5f013e3..b8ed942f5b6 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -109,9 +109,53 @@ void BlenderSession::create_session() session->reset(buffer_params, session_params.samples); } +void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_) +{ + b_data = b_data_; + b_scene = b_scene_; + + SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background); + SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); + + width = b_engine.resolution_x(); + height = b_engine.resolution_y(); + + if(scene->params.modified(scene_params) || + session->params.modified(session_params)) + { + /* if scene or session parameters changed, it's easier to simply re-create + * them rather than trying to distinguish which settings need to be updated + */ + + delete session; + + create_session(); + + return; + } + + session->progress.reset(); + scene->reset(); + + /* peak memory usage should show current render peak, not peak for all renders + * made by this render session + */ + session->stats.mem_peak = session->stats.mem_used; + + /* sync object should be re-created */ + sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress); + sync->sync_data(b_v3d, b_engine.camera_override()); + sync->sync_camera(b_engine.camera_override(), width, height); + + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, PointerRNA_NULL, PointerRNA_NULL, scene->camera, width, height); + session->reset(buffer_params, session_params.samples); +} + void BlenderSession::free_session() { - delete sync; + if(sync) + delete sync; + delete session; } @@ -304,6 +348,15 @@ void BlenderSession::render() /* clear callback */ session->write_render_tile_cb = NULL; session->update_render_tile_cb = NULL; + + /* free all memory used (host and device), so we wouldn't leave render + * engine with extra memory allocated + */ + + session->device_free(); + + delete sync; + sync = NULL; } void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile, bool do_update_only) @@ -465,8 +518,8 @@ void BlenderSession::get_progress(float& progress, double& total_time) sample = session->progress.get_sample(); samples_per_tile = session->params.samples; - if(samples_per_tile) - progress = ((float)sample/(float)(tile_total * samples_per_tile)); + if(samples_per_tile && tile_total) + progress = ((float)sample / (float)(tile_total * samples_per_tile)); else progress = 0.0; } diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index d52e0103bbf..7f3973ae873 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -46,6 +46,8 @@ public: void create_session(); void free_session(); + void reset_session(BL::BlendData b_data, BL::Scene b_scene); + /* offline render */ void render(); diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 9e3380c6f8e..c9380d8d58b 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -90,6 +90,8 @@ static ShaderSocketType convert_socket_type(BL::NodeSocket::type_enum b_type) return SHADER_SOCKET_COLOR; case BL::NodeSocket::type_SHADER: return SHADER_SOCKET_CLOSURE; + case BL::NodeSocket::type_STRING: + return SHADER_SOCKET_STRING; case BL::NodeSocket::type_BOOLEAN: case BL::NodeSocket::type_MESH: @@ -98,7 +100,7 @@ static ShaderSocketType convert_socket_type(BL::NodeSocket::type_enum b_type) } } -static void set_default_value(ShaderInput *input, BL::NodeSocket sock) +static void set_default_value(ShaderInput *input, BL::NodeSocket sock, BL::BlendData b_data, BL::ID b_id) { /* copy values for non linked inputs */ switch(input->type) { @@ -124,6 +126,11 @@ static void set_default_value(ShaderInput *input, BL::NodeSocket sock) input->set(get_float3(vec_sock.default_value())); break; } + case SHADER_SOCKET_STRING: { + BL::NodeSocketStringNone string_sock(sock); + input->set((ustring)blender_absolute_path(b_data, b_id, string_sock.default_value())); + break; + } case SHADER_SOCKET_CLOSURE: break; } @@ -173,6 +180,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen case BL::ShaderNode::type_OUTPUT: break; case BL::ShaderNode::type_SQUEEZE: break; case BL::ShaderNode::type_TEXTURE: break; + case BL::ShaderNode::type_FRAME: break; /* handled outside this function */ case BL::ShaderNode::type_GROUP: break; /* existing blender nodes */ @@ -366,6 +374,23 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen node = glass; break; } + case BL::ShaderNode::type_BSDF_REFRACTION: { + BL::ShaderNodeBsdfRefraction b_refraction_node(b_node); + RefractionBsdfNode *refraction = new RefractionBsdfNode(); + switch(b_refraction_node.distribution()) { + case BL::ShaderNodeBsdfRefraction::distribution_SHARP: + refraction->distribution = ustring("Sharp"); + break; + case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN: + refraction->distribution = ustring("Beckmann"); + break; + case BL::ShaderNodeBsdfRefraction::distribution_GGX: + refraction->distribution = ustring("GGX"); + break; + } + node = refraction; + break; + } case BL::ShaderNode::type_BSDF_TRANSLUCENT: { node = new TranslucentBsdfNode(); break; @@ -382,6 +407,10 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen node = new EmissionNode(); break; } + case BL::ShaderNode::type_AMBIENT_OCCLUSION: { + node = new AmbientOcclusionNode(); + break; + } case BL::ShaderNode::type_VOLUME_ISOTROPIC: { node = new IsotropicVolumeNode(); break; @@ -416,7 +445,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen } case BL::ShaderNode::type_SCRIPT: { #ifdef WITH_OSL - if(scene->params.shadingsystem != SceneParams::OSL) + if(!scene->shader_manager->use_osl()) break; /* create script node */ @@ -435,7 +464,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen for (b_script_node.inputs.begin(b_input); b_input != b_script_node.inputs.end(); ++b_input) { script_node->input_names.push_back(ustring(b_input->name())); ShaderInput *input = script_node->add_input(script_node->input_names.back().c_str(), convert_socket_type(b_input->type())); - set_default_value(input, *b_input); + set_default_value(input, *b_input, b_data, b_ntree); } BL::Node::outputs_iterator b_output; @@ -471,8 +500,10 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen BL::Image b_image(b_image_node.image()); ImageTextureNode *image = new ImageTextureNode(); /* todo: handle generated/builtin images */ - if(b_image && b_image.source() != BL::Image::source_MOVIE) + if(b_image && b_image.source() != BL::Image::source_MOVIE) { image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current()); + image->animated = b_image_node.image_user().use_auto_refresh(); + } image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()]; image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()]; image->projection_blend = b_image_node.projection_blend(); @@ -484,8 +515,10 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen BL::ShaderNodeTexEnvironment b_env_node(b_node); BL::Image b_image(b_env_node.image()); EnvironmentTextureNode *env = new EnvironmentTextureNode(); - if(b_image && b_image.source() != BL::Image::source_MOVIE) + if(b_image && b_image.source() != BL::Image::source_MOVIE) { env->filename = image_user_file_path(b_env_node.image_user(), b_image, b_scene.frame_current()); + env->animated = b_env_node.image_user().use_auto_refresh(); + } env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()]; env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()]; get_tex_mapping(&env->tex_mapping, b_env_node.texture_mapping()); @@ -573,6 +606,23 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen node = sky; break; } + case BL::ShaderNode::type_NORMAL_MAP: { + BL::ShaderNodeNormalMap b_normal_map_node(b_node); + NormalMapNode *nmap = new NormalMapNode(); + nmap->space = NormalMapNode::space_enum[(int)b_normal_map_node.space()]; + nmap->attribute = b_normal_map_node.uv_map(); + node = nmap; + break; + } + case BL::ShaderNode::type_TANGENT: { + BL::ShaderNodeTangent b_tangent_node(b_node); + TangentNode *tangent = new TangentNode(); + tangent->direction_type = TangentNode::direction_type_enum[(int)b_tangent_node.direction_type()]; + tangent->axis = TangentNode::axis_enum[(int)b_tangent_node.axis()]; + tangent->attribute = b_tangent_node.uv_map(); + node = tangent; + break; + } } if(node && node != graph->output()) @@ -687,7 +737,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha group_sockmap[b_input->group_socket().ptr.data] = SocketPair(proxy, proxy->outputs[0]->name); /* default input values of the group node */ - set_default_value(proxy->inputs[0], *b_input); + set_default_value(proxy->inputs[0], *b_input, b_data, b_group_ntree); } for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { @@ -701,7 +751,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha group_sockmap[b_output->group_socket().ptr.data] = SocketPair(proxy, proxy->inputs[0]->name); /* default input values of internal, unlinked group outputs */ - set_default_value(proxy->inputs[0], b_output->group_socket()); + set_default_value(proxy->inputs[0], b_output->group_socket(), b_data, b_group_ntree); } add_nodes(scene, b_data, b_scene, graph, b_group_ntree, group_sockmap); @@ -721,7 +771,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha assert(input); /* copy values for non linked inputs */ - set_default_value(input, *b_input); + set_default_value(input, *b_input, b_data, b_ntree); } } } @@ -775,7 +825,7 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha /* Sync Materials */ -void BlenderSync::sync_materials() +void BlenderSync::sync_materials(bool update_all) { shader_map.set_default(scene->shaders[scene->default_surface]); @@ -786,7 +836,7 @@ void BlenderSync::sync_materials() Shader *shader; /* test if we need to sync */ - if(shader_map.sync(&shader, *b_mat)) { + if(shader_map.sync(&shader, *b_mat) || update_all) { ShaderGraph *graph = new ShaderGraph(); shader->name = b_mat->name().c_str(); @@ -822,14 +872,14 @@ void BlenderSync::sync_materials() /* Sync World */ -void BlenderSync::sync_world() +void BlenderSync::sync_world(bool update_all) { Background *background = scene->background; Background prevbackground = *background; BL::World b_world = b_scene.world(); - if(world_recalc || b_world.ptr.data != world_map) { + if(world_recalc || update_all || b_world.ptr.data != world_map) { Shader *shader = scene->shaders[scene->default_background]; ShaderGraph *graph = new ShaderGraph(); @@ -876,7 +926,7 @@ void BlenderSync::sync_world() /* Sync Lamps */ -void BlenderSync::sync_lamps() +void BlenderSync::sync_lamps(bool update_all) { shader_map.set_default(scene->shaders[scene->default_light]); @@ -887,7 +937,7 @@ void BlenderSync::sync_lamps() Shader *shader; /* test if we need to sync */ - if(shader_map.sync(&shader, *b_lamp)) { + if(shader_map.sync(&shader, *b_lamp) || update_all) { ShaderGraph *graph = new ShaderGraph(); /* create nodes */ @@ -926,11 +976,20 @@ void BlenderSync::sync_lamps() void BlenderSync::sync_shaders() { + /* for auto refresh images */ + bool auto_refresh_update = false; + + if(preview) { + ImageManager *image_manager = scene->image_manager; + int frame = b_scene.frame_current(); + auto_refresh_update = image_manager->set_animation_frame_update(frame); + } + shader_map.pre_sync(); - sync_world(); - sync_lamps(); - sync_materials(); + sync_world(auto_refresh_update); + sync_lamps(auto_refresh_update); + sync_materials(auto_refresh_update); /* false = don't delete unused shaders, not supported */ shader_map.post_sync(false); diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index c63f72c68c6..d0e8b508df6 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -179,12 +179,14 @@ void BlenderSync::sync_integrator() integrator->sample_clamp = get_float(cscene, "sample_clamp"); #ifdef __CAMERA_MOTION__ - if(integrator->motion_blur != r.use_motion_blur()) { - scene->object_manager->tag_update(scene); - scene->camera->tag_update(); - } + if(!preview) { + if(integrator->motion_blur != r.use_motion_blur()) { + scene->object_manager->tag_update(scene); + scene->camera->tag_update(); + } - integrator->motion_blur = (!preview && r.use_motion_blur()); + integrator->motion_blur = r.use_motion_blur(); + } #endif integrator->diffuse_samples = get_int(cscene, "diffuse_samples"); @@ -241,6 +243,7 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer) render_layer.use_localview = (b_v3d.local_view() ? true : false); render_layer.scene_layer = get_layer(b_v3d.layers(), b_v3d.layers_local_view(), render_layer.use_localview); render_layer.layer = render_layer.scene_layer; + render_layer.exclude_layer = 0; render_layer.holdout_layer = 0; render_layer.material_override = PointerRNA_NULL; render_layer.use_background = true; @@ -258,10 +261,16 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer) for(r.layers.begin(b_rlay); b_rlay != r.layers.end(); ++b_rlay) { if((!layer && first_layer) || (layer && b_rlay->name() == layer)) { render_layer.name = b_rlay->name(); - render_layer.scene_layer = get_layer(b_scene.layers()) & ~get_layer(b_rlay->layers_exclude()); - render_layer.layer = get_layer(b_rlay->layers()); + render_layer.holdout_layer = get_layer(b_rlay->layers_zmask()); + render_layer.exclude_layer = get_layer(b_rlay->layers_exclude()); + + render_layer.scene_layer = get_layer(b_scene.layers()) & ~render_layer.exclude_layer; + render_layer.scene_layer |= render_layer.exclude_layer & render_layer.holdout_layer; + + render_layer.layer = get_layer(b_rlay->layers()); render_layer.layer |= render_layer.holdout_layer; + render_layer.material_override = b_rlay->material_override(); render_layer.use_background = b_rlay->use_sky(); render_layer.use_viewport_visibility = false; @@ -277,6 +286,7 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer) SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background) { + BL::RenderSettings r = b_scene.render(); SceneParams params; PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); int shadingsystem = RNA_enum_get(&cscene, "shading_system"); @@ -294,6 +304,8 @@ SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background) params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits"); params.use_bvh_cache = (background)? RNA_boolean_get(&cscene, "use_cache"): false; + params.persistent_images = (background)? r.use_persistent_data(): false; + return params; } @@ -379,7 +391,10 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use params.start_resolution = get_int(cscene, "preview_start_resolution"); /* other parameters */ - params.threads = b_scene.render().threads(); + if(b_scene.render().threads_mode() == BL::RenderSettings::threads_mode_FIXED) + params.threads = b_scene.render().threads(); + else + params.threads = 0; params.cancel_timeout = get_float(cscene, "debug_cancel_timeout"); params.reset_timeout = get_float(cscene, "debug_reset_timeout"); diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 36cd5e684a7..d3d21fbdf72 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -42,6 +42,7 @@ class Film; class Light; class Mesh; class Object; +class ParticleSystem; class Scene; class Shader; class ShaderGraph; @@ -67,33 +68,33 @@ public: private: /* sync */ - void sync_lamps(); - void sync_materials(); + void sync_lamps(bool update_all); + void sync_materials(bool update_all); void sync_objects(BL::SpaceView3D b_v3d, int motion = 0); void sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override); void sync_film(); void sync_integrator(); void sync_view(); - void sync_world(); + void sync_world(bool update_all); void sync_render_layers(BL::SpaceView3D b_v3d, const char *layer); void sync_shaders(); void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree); Mesh *sync_mesh(BL::Object b_ob, bool object_updated); - void sync_object(BL::Object b_parent, int b_index, BL::DupliObject b_dupli_object, Transform& tfm, uint layer_flag, int motion, int particle_id); - void sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm); + Object *sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_object, Transform& tfm, uint layer_flag, int motion); + void sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm); void sync_background_light(); void sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion); void sync_camera_motion(BL::Object b_ob, int motion); - void sync_particles(BL::Object b_ob, BL::ParticleSystem b_psys); + + /* particles */ + bool sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Object *object); /* util */ void find_shader(BL::ID id, vector& used_shaders, int default_shader); bool BKE_object_is_modified(BL::Object b_ob); bool object_is_mesh(BL::Object b_ob); bool object_is_light(BL::Object b_ob); - bool psys_need_update(BL::ParticleSystem b_psys); - int object_count_particles(BL::Object b_ob); /* variables */ BL::RenderEngine b_engine; @@ -115,7 +116,8 @@ private: struct RenderLayerInfo { RenderLayerInfo() - : scene_layer(0), layer(0), holdout_layer(0), + : scene_layer(0), layer(0), + holdout_layer(0), exclude_layer(0), material_override(PointerRNA_NULL), use_background(true), use_viewport_visibility(false), @@ -126,6 +128,7 @@ private: uint scene_layer; uint layer; uint holdout_layer; + uint exclude_layer; BL::Material material_override; bool use_background; bool use_viewport_visibility; diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index df1e99882b8..0a9f2dd06aa 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -284,6 +284,12 @@ public: return recalc; } + bool is_used(const K& key) + { + T *data = find(key); + return (data) ? used_set.find(data) != used_set.end() : false; + } + void used(T *data) { /* tag data as still in use */ @@ -343,27 +349,63 @@ protected: /* Object Key */ +enum { OBJECT_PERSISTENT_ID_SIZE = 8 }; + struct ObjectKey { void *parent; - int index; + int id[OBJECT_PERSISTENT_ID_SIZE]; void *ob; - ObjectKey(void *parent_, int index_, void *ob_) - : parent(parent_), index(index_), ob(ob_) {} + ObjectKey(void *parent_, int id_[OBJECT_PERSISTENT_ID_SIZE], void *ob_) + : parent(parent_), ob(ob_) + { + if(id_) + memcpy(id, id_, sizeof(id)); + else + memset(id, 0, sizeof(id)); + } bool operator<(const ObjectKey& k) const - { return (parent < k.parent || (parent == k.parent && (index < k.index || (index == k.index && ob < k.ob)))); } + { + if(ob < k.ob) { + return true; + } + else if(ob == k.ob) { + if(parent < k.parent) + return true; + else if(parent == k.parent) + return memcmp(id, k.id, sizeof(id)) < 0; + } + + return false; + } }; +/* Particle System Key */ + struct ParticleSystemKey { void *ob; - void *psys; + int id[OBJECT_PERSISTENT_ID_SIZE]; - ParticleSystemKey(void *ob_, void *psys_) - : ob(ob_), psys(psys_) {} + ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE]) + : ob(ob_) + { + if(id_) + memcpy(id, id_, sizeof(id)); + else + memset(id, 0, sizeof(id)); + } bool operator<(const ParticleSystemKey& k) const - { return (ob < k.ob && psys < k.psys); } + { + /* first id is particle index, we don't compare that */ + if(ob < k.ob) + return true; + else if(ob == k.ob) + return memcmp(id+1, k.id+1, sizeof(int)*(OBJECT_PERSISTENT_ID_SIZE-1)) < 0; + + return false; + } }; CCL_NAMESPACE_END diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake index 332d3d74715..790049898ff 100644 --- a/intern/cycles/cmake/external_libs.cmake +++ b/intern/cycles/cmake/external_libs.cmake @@ -17,33 +17,6 @@ else() set(CYCLES_GLEW_LIBRARY extern_glew) endif() -########################################################################### -# Partio - -if(WITH_CYCLES_PARTIO) - - set(CYCLES_PARTIO "" CACHE PATH "Path to Partio installation") - - message(STATUS "CYCLES_PARTIO = ${CYCLES_PARTIO}") - - find_library(PARTIO_LIBRARIES NAMES partio PATHS ${CYCLES_PARTIO}/lib) - find_path(PARTIO_INCLUDES Partio.h ${CYCLES_PARTIO}/include) - - find_package(ZLIB) - - if(PARTIO_INCLUDES AND PARTIO_LIBRARIES AND ZLIB_LIBRARIES) - list(APPEND PARTIO_LIBRARIES ${ZLIB_LIBRARIES}) - set(PARTIO_FOUND TRUE) - message(STATUS "PARTIO includes = ${PARTIO_INCLUDES}") - message(STATUS "PARTIO library = ${PARTIO_LIBRARIES}") - else() - message(STATUS "PARTIO not found") - endif() - - include_directories(${PARTIO_INCLUDES}) - -endif() - ########################################################################### # CUDA diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index 550da2982a3..1248b42b738 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -78,13 +78,13 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int w glDisable(GL_BLEND); } -Device *Device::create(DeviceInfo& info, Stats &stats, bool background, int threads) +Device *Device::create(DeviceInfo& info, Stats &stats, bool background) { Device *device; switch(info.type) { case DEVICE_CPU: - device = device_cpu_create(info, stats, threads); + device = device_cpu_create(info, stats); break; #ifdef WITH_CUDA case DEVICE_CUDA: @@ -189,18 +189,6 @@ vector& Device::available_devices() { static vector devices; static bool devices_init = false; - static double device_update_time = 0.0; - - /* only update device list if we're not actively rendering already, things - * could go very wrong if a device suddenly becomes (un)available. also do - * it only every 5 seconds. it not super cpu intensive but don't want to do - * it on every redraw. */ - if(devices_init) { - if(!TaskScheduler::active() && (time_dt() > device_update_time + 5.0)) { - devices.clear(); - devices_init = false; - } - } if(!devices_init) { #ifdef WITH_CUDA @@ -224,7 +212,6 @@ vector& Device::available_devices() #endif devices_init = true; - device_update_time = time_dt(); } return devices; diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index 95da0a89833..9840687b76a 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -134,7 +134,7 @@ public: virtual int device_number(Device *sub_device) { return 0; } /* static */ - static Device *create(DeviceInfo& info, Stats &stats, bool background = true, int threads = 0); + static Device *create(DeviceInfo& info, Stats &stats, bool background = true); static DeviceType type_from_string(const char *name); static string string_from_type(DeviceType type); diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 519c458ffdf..a1d7706a34e 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -23,9 +23,12 @@ #include "device_intern.h" #include "kernel.h" +#include "kernel_compat_cpu.h" #include "kernel_types.h" +#include "kernel_globals.h" #include "osl_shader.h" +#include "osl_globals.h" #include "buffers.h" @@ -43,11 +46,16 @@ class CPUDevice : public Device { public: TaskPool task_pool; - KernelGlobals *kg; + KernelGlobals kernel_globals; +#ifdef WITH_OSL + OSLGlobals osl_globals; +#endif - CPUDevice(Stats &stats, int threads_num) : Device(stats) + CPUDevice(Stats &stats) : Device(stats) { - kg = kernel_globals_create(); +#ifdef WITH_OSL + kernel_globals.osl = &osl_globals; +#endif /* do now to avoid thread issues */ system_cpu_support_optimized(); @@ -56,7 +64,6 @@ public: ~CPUDevice() { task_pool.stop(); - kernel_globals_free(kg); } bool support_advanced_shading() @@ -95,12 +102,12 @@ public: void const_copy_to(const char *name, void *host, size_t size) { - kernel_const_copy(kg, name, host, size); + kernel_const_copy(&kernel_globals, name, host, size); } void tex_alloc(const char *name, device_memory& mem, bool interpolation, bool periodic) { - kernel_tex_copy(kg, name, mem.data_pointer, mem.data_width, mem.data_height); + kernel_tex_copy(&kernel_globals, name, mem.data_pointer, mem.data_width, mem.data_height); mem.device_pointer = mem.data_pointer; stats.mem_alloc(mem.memory_size()); @@ -116,7 +123,7 @@ public: void *osl_memory() { #ifdef WITH_OSL - return kernel_osl_memory(kg); + return &osl_globals; #else return NULL; #endif @@ -148,9 +155,10 @@ public: return; } + KernelGlobals kg = kernel_globals; + #ifdef WITH_OSL - if(kernel_osl_use(kg)) - OSLShader::thread_init(kg); + OSLShader::thread_init(&kg, &kernel_globals, &osl_globals); #endif RenderTile tile; @@ -171,7 +179,7 @@ public: for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) { - kernel_cpu_optimized_path_trace(kg, render_buffer, rng_state, + kernel_cpu_optimized_path_trace(&kg, render_buffer, rng_state, sample, x, y, tile.offset, tile.stride); } } @@ -192,7 +200,7 @@ public: for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) { - kernel_cpu_path_trace(kg, render_buffer, rng_state, + kernel_cpu_path_trace(&kg, render_buffer, rng_state, sample, x, y, tile.offset, tile.stride); } } @@ -212,8 +220,7 @@ public: } #ifdef WITH_OSL - if(kernel_osl_use(kg)) - OSLShader::thread_free(kg); + OSLShader::thread_free(&kg); #endif } @@ -223,7 +230,7 @@ public: if(system_cpu_support_optimized()) { for(int y = task.y; y < task.y + task.h; y++) for(int x = task.x; x < task.x + task.w; x++) - kernel_cpu_optimized_tonemap(kg, (uchar4*)task.rgba, (float*)task.buffer, + kernel_cpu_optimized_tonemap(&kernel_globals, (uchar4*)task.rgba, (float*)task.buffer, task.sample, task.resolution, x, y, task.offset, task.stride); } else @@ -231,22 +238,23 @@ public: { for(int y = task.y; y < task.y + task.h; y++) for(int x = task.x; x < task.x + task.w; x++) - kernel_cpu_tonemap(kg, (uchar4*)task.rgba, (float*)task.buffer, + kernel_cpu_tonemap(&kernel_globals, (uchar4*)task.rgba, (float*)task.buffer, task.sample, task.resolution, x, y, task.offset, task.stride); } } void thread_shader(DeviceTask& task) { + KernelGlobals kg = kernel_globals; + #ifdef WITH_OSL - if(kernel_osl_use(kg)) - OSLShader::thread_init(kg); + OSLShader::thread_init(&kg, &kernel_globals, &osl_globals); #endif #ifdef WITH_OPTIMIZED_KERNEL if(system_cpu_support_optimized()) { for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) { - kernel_cpu_optimized_shader(kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x); + kernel_cpu_optimized_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x); if(task_pool.cancelled()) break; @@ -256,7 +264,7 @@ public: #endif { for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) { - kernel_cpu_shader(kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x); + kernel_cpu_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x); if(task_pool.cancelled()) break; @@ -264,8 +272,7 @@ public: } #ifdef WITH_OSL - if(kernel_osl_use(kg)) - OSLShader::thread_free(kg); + OSLShader::thread_free(&kg); #endif } @@ -274,7 +281,7 @@ public: /* split task into smaller ones, more than number of threads for uneven * workloads where some parts of the image render slower than others */ list tasks; - task.split(tasks, TaskScheduler::num_threads()+1); + task.split(tasks, TaskScheduler::num_threads()); foreach(DeviceTask& task, tasks) task_pool.push(new CPUDeviceTask(this, task)); @@ -291,9 +298,9 @@ public: } }; -Device *device_cpu_create(DeviceInfo& info, Stats &stats, int threads) +Device *device_cpu_create(DeviceInfo& info, Stats &stats) { - return new CPUDevice(stats, threads); + return new CPUDevice(stats); } void device_cpu_info(vector& devices) diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index d797c0f09ca..14f8cfa8767 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -60,7 +60,7 @@ public: return (CUdeviceptr)mem; } - const char *cuda_error_string(CUresult result) + static const char *cuda_error_string(CUresult result) { switch(result) { case CUDA_SUCCESS: return "No errors"; @@ -915,12 +915,21 @@ Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background) void device_cuda_info(vector& devices) { + CUresult result; int count = 0; - if(cuInit(0) != CUDA_SUCCESS) + result = cuInit(0); + if(result != CUDA_SUCCESS) { + if(result != CUDA_ERROR_NO_DEVICE) + fprintf(stderr, "CUDA cuInit: %s\n", CUDADevice::cuda_error_string(result)); return; - if(cuDeviceGetCount(&count) != CUDA_SUCCESS) + } + + result = cuDeviceGetCount(&count); + if(result != CUDA_SUCCESS) { + fprintf(stderr, "CUDA cuDeviceGetCount: %s\n", CUDADevice::cuda_error_string(result)); return; + } vector display_devices; diff --git a/intern/cycles/device/device_intern.h b/intern/cycles/device/device_intern.h index 02fbac6860e..b49ebba3e8b 100644 --- a/intern/cycles/device/device_intern.h +++ b/intern/cycles/device/device_intern.h @@ -23,7 +23,7 @@ CCL_NAMESPACE_BEGIN class Device; -Device *device_cpu_create(DeviceInfo& info, Stats &stats, int threads); +Device *device_cpu_create(DeviceInfo& info, Stats &stats); Device *device_opencl_create(DeviceInfo& info, Stats &stats, bool background); Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background); Device *device_network_create(DeviceInfo& info, Stats &stats, const char *address); diff --git a/intern/cycles/device/device_task.cpp b/intern/cycles/device/device_task.cpp index c85e182d629..b3f02deaf6f 100644 --- a/intern/cycles/device/device_task.cpp +++ b/intern/cycles/device/device_task.cpp @@ -101,7 +101,7 @@ void DeviceTask::update_progress(RenderTile &rtile) if(update_tile_sample) { double current_time = time_dt(); - if (current_time - last_update_time >= 1.0f) { + if (current_time - last_update_time >= 1.0) { update_tile_sample(rtile); last_update_time = current_time; diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 82b0605ab6b..5a570328948 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -51,6 +51,7 @@ set(SRC_CLOSURE_HEADERS closure/bsdf_diffuse.h closure/bsdf_microfacet.h closure/bsdf_oren_nayar.h + closure/bsdf_phong_ramp.h closure/bsdf_reflection.h closure/bsdf_refraction.h closure/bsdf_transparent.h diff --git a/intern/cycles/kernel/SConscript b/intern/cycles/kernel/SConscript index 14890164a42..730f758194e 100644 --- a/intern/cycles/kernel/SConscript +++ b/intern/cycles/kernel/SConscript @@ -32,16 +32,17 @@ if env['WITH_BF_CYCLES_CUDA_BINARIES']: kernel_file = os.path.join(source_dir, "kernel.cu") util_dir = os.path.join(source_dir, "../util") svm_dir = os.path.join(source_dir, "../svm") + closure_dir = os.path.join(source_dir, "../closure") # nvcc flags nvcc_flags = "-m%s" % (bits) nvcc_flags += " --cubin --ptxas-options=\"-v\" --maxrregcount=24" nvcc_flags += " --opencc-options -OPT:Olimit=0" nvcc_flags += " -DCCL_NAMESPACE_BEGIN= -DCCL_NAMESPACE_END= -DNVCC" - nvcc_flags += " -I \"%s\" -I \"%s\"" % (util_dir, svm_dir) + nvcc_flags += " -I \"%s\" -I \"%s\" -I \"%s\"" % (util_dir, svm_dir, closure_dir) # dependencies - dependencies = ['kernel.cu'] + kernel.Glob('*.h') + kernel.Glob('../util/*.h') + kernel.Glob('svm/*.h') + dependencies = ['kernel.cu'] + kernel.Glob('*.h') + kernel.Glob('../util/*.h') + kernel.Glob('svm/*.h') + kernel.Glob('closure/*.h') last_cubin_file = None # add command for each cuda architecture diff --git a/intern/cycles/kernel/closure/bsdf_phong_ramp.h b/intern/cycles/kernel/closure/bsdf_phong_ramp.h new file mode 100644 index 00000000000..575a798aed4 --- /dev/null +++ b/intern/cycles/kernel/closure/bsdf_phong_ramp.h @@ -0,0 +1,140 @@ +/* + * Adapted from Open Shading Language with this license: + * + * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. + * All Rights Reserved. + * + * Modifications Copyright 2012, 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 __BSDF_PHONG_RAMP_H__ +#define __BSDF_PHONG_RAMP_H__ + +CCL_NAMESPACE_BEGIN + +__device float3 bsdf_phong_ramp_get_color(const ShaderClosure *sc, const float3 colors[8], float pos) +{ + int MAXCOLORS = 8; + + float npos = pos * (float)(MAXCOLORS - 1); + int ipos = (int)npos; + if (ipos >= (MAXCOLORS - 1)) + return colors[MAXCOLORS - 1]; + float offset = npos - (float)ipos; + return colors[ipos] * (1.0f - offset) + colors[ipos+1] * offset; +} + +__device int bsdf_phong_ramp_setup(ShaderClosure *sc) +{ + sc->type = CLOSURE_BSDF_PHONG_RAMP_ID; + return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_GLOSSY; +} + +__device void bsdf_phong_ramp_blur(ShaderClosure *sc, float roughness) +{ +} + +__device float3 bsdf_phong_ramp_eval_reflect(const ShaderClosure *sc, const float3 colors[8], const float3 I, const float3 omega_in, float *pdf) +{ + float m_exponent = sc->data0; + float cosNI = dot(sc->N, omega_in); + float cosNO = dot(sc->N, I); + + if (cosNI > 0 && cosNO > 0) { + // reflect the view vector + float3 R = (2 * cosNO) * sc->N - I; + float cosRI = dot(R, omega_in); + if (cosRI > 0) { + float cosp = powf(cosRI, m_exponent); + float common = 0.5f * (float) M_1_PI_F * cosp; + float out = cosNI * (m_exponent + 2) * common; + *pdf = (m_exponent + 1) * common; + return bsdf_phong_ramp_get_color(sc, colors, cosp) * out; + } + } + + return make_float3(0.0f, 0.0f, 0.0f); +} + +__device float3 bsdf_phong_ramp_eval_transmit(const ShaderClosure *sc, const float3 colors[8], const float3 I, const float3 omega_in, float *pdf) +{ + return make_float3(0.0f, 0.0f, 0.0f); +} + +__device int bsdf_phong_ramp_sample(const ShaderClosure *sc, const float3 colors[8], float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +{ + float cosNO = dot(sc->N, I); + float m_exponent = sc->data0; + + if (cosNO > 0) { + // reflect the view vector + float3 R = (2 * cosNO) * sc->N - I; + +#ifdef __RAY_DIFFERENTIALS__ + *domega_in_dx = (2 * dot(sc->N, dIdx)) * sc->N - dIdx; + *domega_in_dy = (2 * dot(sc->N, dIdy)) * sc->N - dIdy; +#endif + + float3 T, B; + make_orthonormals (R, &T, &B); + float phi = 2 * M_PI_F * randu; + float cosTheta = powf(randv, 1 / (m_exponent + 1)); + float sinTheta2 = 1 - cosTheta * cosTheta; + float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; + *omega_in = (cosf(phi) * sinTheta) * T + + (sinf(phi) * sinTheta) * B + + ( cosTheta) * R; + if (dot(Ng, *omega_in) > 0.0f) + { + // common terms for pdf and eval + float cosNI = dot(sc->N, *omega_in); + // make sure the direction we chose is still in the right hemisphere + if (cosNI > 0) + { + float cosp = powf(cosTheta, m_exponent); + float common = 0.5f * M_1_PI_F * cosp; + *pdf = (m_exponent + 1) * common; + float out = cosNI * (m_exponent + 2) * common; + *eval = bsdf_phong_ramp_get_color(sc, colors, cosp) * out; + +#ifdef __RAY_DIFFERENTIALS__ + // Since there is some blur to this reflection, make the + // derivatives a bit bigger. In theory this varies with the + // exponent but the exact relationship is complex and + // requires more ops than are practical. + *domega_in_dx *= 10; + *domega_in_dy *= 10; +#endif + } + } + } + return LABEL_REFLECT|LABEL_GLOSSY; +} + + +CCL_NAMESPACE_END + +#endif /* __BSDF_PHONG_RAMP_H__ */ diff --git a/intern/cycles/kernel/closure/bsdf_ward.h b/intern/cycles/kernel/closure/bsdf_ward.h index 9c81548a2c3..dbddcf20dba 100644 --- a/intern/cycles/kernel/closure/bsdf_ward.h +++ b/intern/cycles/kernel/closure/bsdf_ward.h @@ -68,7 +68,10 @@ __device float3 bsdf_ward_eval_reflect(const ShaderClosure *sc, const float3 I, float cosNO = dot(N, I); float cosNI = dot(N, omega_in); - if(cosNI > 0 && cosNO > 0) { + if(cosNI > 0.0f && cosNO > 0.0f) { + cosNO = max(cosNO, 1e-4f); + cosNI = max(cosNI, 1e-4f); + // get half vector and get x,y basis on the surface for anisotropy float3 H = normalize(omega_in + I); // normalize needed for pdf float3 X, Y; @@ -103,7 +106,7 @@ __device int bsdf_ward_sample(const ShaderClosure *sc, float3 Ng, float3 I, floa float3 T = sc->T; float cosNO = dot(N, I); - if(cosNO > 0) { + if(cosNO > 0.0f) { // get x,y basis on the surface for anisotropy float3 X, Y; make_orthonormals_tangent(N, T, &X, &Y); @@ -165,6 +168,9 @@ __device int bsdf_ward_sample(const ShaderClosure *sc, float3 Ng, float3 I, floa if(dot(Ng, *omega_in) > 0) { float cosNI = dot(N, *omega_in); if(cosNI > 0) { + cosNO = max(cosNO, 1e-4f); + cosNI = max(cosNI, 1e-4f); + // eq. 9 float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn); float denom = 4 * M_PI_F * m_ax * m_ay * oh * dotn * dotn * dotn; diff --git a/intern/cycles/kernel/kernel.cpp b/intern/cycles/kernel/kernel.cpp index 62d79bdd946..d760e63a290 100644 --- a/intern/cycles/kernel/kernel.cpp +++ b/intern/cycles/kernel/kernel.cpp @@ -29,38 +29,6 @@ CCL_NAMESPACE_BEGIN -/* Globals */ - -KernelGlobals *kernel_globals_create() -{ - KernelGlobals *kg = new KernelGlobals(); -#ifdef WITH_OSL - kg->osl.use = false; -#endif - return kg; -} - -void kernel_globals_free(KernelGlobals *kg) -{ - delete kg; -} - -/* OSL */ - -#ifdef WITH_OSL - -void *kernel_osl_memory(KernelGlobals *kg) -{ - return (void*)&kg->osl; -} - -bool kernel_osl_use(KernelGlobals *kg) -{ - return kg->osl.use; -} - -#endif - /* Memory Copy */ void kernel_const_copy(KernelGlobals *kg, const char *name, void *host, size_t size) diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index 2f2314c9a8b..d99beb8905a 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -301,10 +301,6 @@ __device_inline float3 path_radiance_sum(KernelGlobals *kg, PathRadiance *L) __device_inline void path_radiance_clamp(PathRadiance *L, float3 *L_sum, float clamp) { - #ifdef __OSL__ - using std::isfinite; - #endif - float sum = fabsf((*L_sum).x) + fabsf((*L_sum).y) + fabsf((*L_sum).z); if(!isfinite(sum)) { diff --git a/intern/cycles/kernel/kernel_attribute.h b/intern/cycles/kernel/kernel_attribute.h index 2774f5e924b..b7ad731c883 100644 --- a/intern/cycles/kernel/kernel_attribute.h +++ b/intern/cycles/kernel/kernel_attribute.h @@ -19,13 +19,6 @@ #ifndef __KERNEL_ATTRIBUTE_CL__ #define __KERNEL_ATTRIBUTE_CL__ -#include "util_types.h" - -#ifdef __OSL__ -#include -#include "util_attribute.h" -#endif - CCL_NAMESPACE_BEGIN /* note: declared in kernel.h, have to add it here because kernel.h is not available */ @@ -33,20 +26,9 @@ bool kernel_osl_use(KernelGlobals *kg); __device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id) { - #ifdef __OSL__ - if (kernel_osl_use(kg)) { - /* for OSL, a hash map is used to lookup the attribute by name. */ - OSLGlobals::AttributeMap &attr_map = kg->osl.attribute_map[sd->object]; - ustring stdname(std::string("std::") + std::string(attribute_standard_name((AttributeStandard)id))); - OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname); - if (it != attr_map.end()) { - const OSLGlobals::Attribute &osl_attr = it->second; - /* return result */ - return (osl_attr.elem == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : osl_attr.offset; - } - else - return (int)ATTR_STD_NOT_FOUND; + if (kg->osl) { + return OSLShader::find_attribute(kg, sd, id); } else #endif diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index 1b2fe8c56ee..97d37a8b3f4 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -65,7 +65,7 @@ __device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float #ifdef __CAMERA_MOTION__ if(kernel_data.cam.have_motion) - transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time); + transform_motion_interpolate(&cameratoworld, (const DecompMotionTransform*)&kernel_data.cam.motion, ray->time); #endif ray->P = transform_point(&cameratoworld, ray->P); @@ -108,7 +108,7 @@ __device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, floa #ifdef __CAMERA_MOTION__ if(kernel_data.cam.have_motion) - transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time); + transform_motion_interpolate(&cameratoworld, (const DecompMotionTransform*)&kernel_data.cam.motion, ray->time); #endif ray->P = transform_point(&cameratoworld, ray->P); @@ -182,7 +182,7 @@ __device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float ra #ifdef __CAMERA_MOTION__ if(kernel_data.cam.have_motion) - transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time); + transform_motion_interpolate(&cameratoworld, (const DecompMotionTransform*)&kernel_data.cam.motion, ray->time); #endif ray->P = transform_point(&cameratoworld, ray->P); @@ -229,5 +229,20 @@ __device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, flo camera_sample_panorama(kg, raster_x, raster_y, lens_u, lens_v, ray); } +/* Utilities */ + +__device_inline float camera_distance(KernelGlobals *kg, float3 P) +{ + Transform cameratoworld = kernel_data.cam.cameratoworld; + float3 camP = make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w); + + if(kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) { + float3 camD = make_float3(cameratoworld.x.z, cameratoworld.y.z, cameratoworld.z.z); + return fabsf(dot((P - camP), camD)); + } + else + return len(P - camP); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_globals.h b/intern/cycles/kernel/kernel_globals.h index 1e56c11ab90..529b7b8768f 100644 --- a/intern/cycles/kernel/kernel_globals.h +++ b/intern/cycles/kernel/kernel_globals.h @@ -18,14 +18,6 @@ /* Constant Globals */ -#ifdef __KERNEL_CPU__ - -#ifdef __OSL__ -#include "osl_globals.h" -#endif - -#endif - CCL_NAMESPACE_BEGIN /* On the CPU, we pass along the struct KernelGlobals to nearly everywhere in @@ -35,6 +27,12 @@ CCL_NAMESPACE_BEGIN #ifdef __KERNEL_CPU__ +#ifdef __OSL__ +struct OSLGlobals; +struct OSLThreadData; +struct OSLShadingSystem; +#endif + #define MAX_BYTE_IMAGES 512 #define MAX_FLOAT_IMAGES 5 @@ -51,7 +49,9 @@ typedef struct KernelGlobals { #ifdef __OSL__ /* On the CPU, we also have the OSL globals here. Most data structures are shared * with SVM, the difference is in the shaders and object/mesh attributes. */ - OSLGlobals osl; + OSLGlobals *osl; + OSLShadingSystem *osl_ss; + OSLThreadData *osl_tdata; #endif } KernelGlobals; diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 2791b3abbb6..97ae2d3db87 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -350,10 +350,9 @@ __device int light_distribution_sample(KernelGlobals *kg, float randt) } } - first = max(0, first-1); - kernel_assert(first >= 0 && first < kernel_data.integrator.num_distribution); - - return first; + /* clamping should not be needed but float rounding errors seem to + * make this fail on rare occasions */ + return clamp(first-1, 0, kernel_data.integrator.num_distribution-1); } /* Generic Light */ diff --git a/intern/cycles/kernel/kernel_object.h b/intern/cycles/kernel/kernel_object.h index 112bfbb86b5..2b38544e527 100644 --- a/intern/cycles/kernel/kernel_object.h +++ b/intern/cycles/kernel/kernel_object.h @@ -23,9 +23,8 @@ enum ObjectTransform { OBJECT_INVERSE_TRANSFORM = 3, OBJECT_PROPERTIES = 6, OBJECT_TRANSFORM_MOTION_PRE = 8, - OBJECT_TRANSFORM_MOTION_MID = 12, - OBJECT_TRANSFORM_MOTION_POST = 16, - OBJECT_DUPLI = 20 + OBJECT_TRANSFORM_MOTION_POST = 12, + OBJECT_DUPLI = 16 }; __device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, enum ObjectTransform type) @@ -44,24 +43,19 @@ __device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, #ifdef __OBJECT_MOTION__ __device_inline Transform object_fetch_transform_motion(KernelGlobals *kg, int object, float time) { - MotionTransform motion; + DecompMotionTransform motion; int offset = object*OBJECT_SIZE + (int)OBJECT_TRANSFORM_MOTION_PRE; - motion.pre.x = kernel_tex_fetch(__objects, offset + 0); - motion.pre.y = kernel_tex_fetch(__objects, offset + 1); - motion.pre.z = kernel_tex_fetch(__objects, offset + 2); - motion.pre.w = kernel_tex_fetch(__objects, offset + 3); + motion.mid.x = kernel_tex_fetch(__objects, offset + 0); + motion.mid.y = kernel_tex_fetch(__objects, offset + 1); + motion.mid.z = kernel_tex_fetch(__objects, offset + 2); + motion.mid.w = kernel_tex_fetch(__objects, offset + 3); - motion.mid.x = kernel_tex_fetch(__objects, offset + 4); - motion.mid.y = kernel_tex_fetch(__objects, offset + 5); - motion.mid.z = kernel_tex_fetch(__objects, offset + 6); - motion.mid.w = kernel_tex_fetch(__objects, offset + 7); - - motion.post.x = kernel_tex_fetch(__objects, offset + 8); - motion.post.y = kernel_tex_fetch(__objects, offset + 9); - motion.post.z = kernel_tex_fetch(__objects, offset + 10); - motion.post.w = kernel_tex_fetch(__objects, offset + 11); + motion.pre_x = kernel_tex_fetch(__objects, offset + 4); + motion.pre_y = kernel_tex_fetch(__objects, offset + 5); + motion.post_x = kernel_tex_fetch(__objects, offset + 6); + motion.post_y = kernel_tex_fetch(__objects, offset + 7); Transform tfm; transform_motion_interpolate(&tfm, &motion, time); diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index 42733d691e0..7f8b611ba14 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -52,9 +52,7 @@ __device_inline void kernel_write_data_passes(KernelGlobals *kg, __global float if(!(path_flag & PATH_RAY_TRANSPARENT)) { if(sample == 0) { if(flag & PASS_DEPTH) { - Transform tfm = kernel_data.cam.worldtocamera; - float depth = len(transform_point(&tfm, sd->P)); - + float depth = camera_distance(kg, sd->P); kernel_write_pass_float(buffer + kernel_data.film.pass_depth, sample, depth); } if(flag & PASS_OBJECT_ID) { diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 817f254a5e5..3588b09c790 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -16,10 +16,16 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#ifdef __OSL__ +#include "osl_shader.h" +#endif + #include "kernel_differential.h" #include "kernel_montecarlo.h" #include "kernel_projection.h" #include "kernel_object.h" +#include "kernel_attribute.h" +#include "kernel_projection.h" #include "kernel_triangle.h" #ifdef __QBVH__ #include "kernel_qbvh.h" @@ -326,15 +332,18 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, #ifdef __AO__ /* ambient occlusion */ - if(kernel_data.integrator.use_ambient_occlusion) { + if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) { /* todo: solve correlation */ float bsdf_u = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_U); float bsdf_v = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_V); + float ao_factor = kernel_data.background.ao_factor; + float3 ao_N; + float3 ao_bsdf = shader_bsdf_ao(kg, &sd, ao_factor, &ao_N); float3 ao_D; float ao_pdf; - sample_cos_hemisphere(sd.N, bsdf_u, bsdf_v, &ao_D, &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; @@ -347,10 +356,8 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, light_ray.time = sd.time; #endif - if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) { - float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*kernel_data.background.ao_factor; + if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) path_radiance_accum_ao(&L, throughput, ao_bsdf, ao_shadow, state.bounce); - } } } #endif @@ -423,7 +430,12 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, /* setup ray */ ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng); ray.D = bsdf_omega_in; - ray.t = FLT_MAX; + + if(state.bounce == 0) + ray.t -= sd.ray_length; /* clipping works through transparent */ + else + ray.t = FLT_MAX; + #ifdef __RAY_DIFFERENTIALS__ ray.dP = sd.dP; ray.dD = bsdf_domega_in; @@ -503,15 +515,18 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray #ifdef __AO__ /* ambient occlusion */ - if(kernel_data.integrator.use_ambient_occlusion) { + if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) { /* todo: solve correlation */ float bsdf_u = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_U); float bsdf_v = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_V); + float ao_factor = kernel_data.background.ao_factor; + float3 ao_N; + float3 ao_bsdf = shader_bsdf_ao(kg, &sd, ao_factor, &ao_N); float3 ao_D; float ao_pdf; - sample_cos_hemisphere(sd.N, bsdf_u, bsdf_v, &ao_D, &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; @@ -524,10 +539,8 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray light_ray.time = sd.time; #endif - if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) { - float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*kernel_data.background.ao_factor; + if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) path_radiance_accum_ao(L, throughput, ao_bsdf, ao_shadow, state.bounce); - } } } #endif @@ -706,10 +719,12 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam #ifdef __AO__ /* ambient occlusion */ - if(kernel_data.integrator.use_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 */ @@ -719,7 +734,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam float3 ao_D; float ao_pdf; - sample_cos_hemisphere(sd.N, bsdf_u, bsdf_v, &ao_D, &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; @@ -732,10 +747,8 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam light_ray.time = sd.time; #endif - if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) { - float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*ao_factor; + if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) path_radiance_accum_ao(&L, throughput*num_samples_inv, ao_bsdf, ao_shadow, state.bounce); - } } } } @@ -885,6 +898,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam path_state_next(kg, &state, LABEL_TRANSPARENT); ray.P = ray_offset(sd.P, -sd.Ng); + ray.t -= sd.ray_length; /* clipping works through transparent */ } float3 L_sum = path_radiance_sum(kg, &L); diff --git a/intern/cycles/kernel/kernel_projection.h b/intern/cycles/kernel/kernel_projection.h index 64747bcb42e..6516b9e4d82 100644 --- a/intern/cycles/kernel/kernel_projection.h +++ b/intern/cycles/kernel/kernel_projection.h @@ -98,7 +98,7 @@ __device float3 fisheye_to_direction(float u, float v, float fov) return make_float3(0.0f, 0.0f, 0.0f); float phi = acosf((r != 0.0f)? u/r: 0.0f); - float theta = asinf(r) * (fov / M_PI_F); + float theta = r * fov * 0.5f; if(v < 0.0f) phi = -phi; diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 86886a6a231..98a7ec59d7b 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -26,10 +26,6 @@ * */ -#ifdef __OSL__ -#include "osl_shader.h" -#endif - #include "closure/bsdf.h" #include "closure/emissive.h" #include "closure/volume.h" @@ -61,7 +57,7 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray) { #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) OSLShader::init(kg, sd); #endif @@ -147,7 +143,7 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, int shader, int object, int prim, float u, float v, float t, float time) { #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) OSLShader::init(kg, sd); #endif @@ -278,7 +274,7 @@ __device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd, __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData *sd, const Ray *ray) { #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) OSLShader::init(kg, sd); #endif @@ -387,7 +383,7 @@ __device void shader_bsdf_eval(KernelGlobals *kg, const ShaderData *sd, bsdf_eval_init(eval, NBUILTIN_CLOSURES, make_float3(0.0f, 0.0f, 0.0f), kernel_data.film.use_light_pass); #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) return _shader_bsdf_multi_eval_osl(sd, omega_in, pdf, -1, eval, 0.0f, 0.0f); else #endif @@ -444,7 +440,7 @@ __device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd, *pdf = 0.0f; #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) label = OSLShader::bsdf_sample(sd, sc, randu, randv, eval, *omega_in, *domega_in, *pdf); else #endif @@ -456,7 +452,7 @@ __device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd, if(sd->num_closure > 1) { float sweight = sc->sample_weight; #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) _shader_bsdf_multi_eval_osl(sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight); else #endif @@ -483,7 +479,7 @@ __device int shader_bsdf_sample_closure(KernelGlobals *kg, const ShaderData *sd, *pdf = 0.0f; #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) label = OSLShader::bsdf_sample(sd, sc, randu, randv, eval, *omega_in, *domega_in, *pdf); else #endif @@ -503,7 +499,7 @@ __device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughnes if(CLOSURE_IS_BSDF(sc->type)) { #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) OSLShader::bsdf_blur(sc, roughness); else #endif @@ -599,6 +595,44 @@ __device float3 shader_bsdf_transmission(KernelGlobals *kg, ShaderData *sd) #endif } +__device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_factor, float3 *N) +{ +#ifdef __MULTI_CLOSURE__ + float3 eval = make_float3(0.0f, 0.0f, 0.0f); + + *N = make_float3(0.0f, 0.0f, 0.0f); + + for(int i = 0; i< sd->num_closure; i++) { + ShaderClosure *sc = &sd->closure[i]; + + if(CLOSURE_IS_BSDF_DIFFUSE(sc->type)) { + eval += sc->weight*ao_factor; + *N += sc->N*average(sc->weight); + } + if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type)) { + eval += sc->weight; + *N += sd->N*average(sc->weight); + } + } + + if(is_zero(*N)) + *N = sd->N; + else + *N = normalize(*N); + + return eval; +#else + *N = sd->N; + + if(CLOSURE_IS_BSDF_DIFFUSE(sd->closure.type)) + return sd->closure.weight*ao_factor; + else if(CLOSURE_IS_AMBIENT_OCCLUSION(sd->closure.type)) + return sd->closure.weight; + else + return make_float3(0.0f, 0.0f, 0.0f); +#endif +} + /* Emission */ __device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd) @@ -612,7 +646,7 @@ __device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd) if(CLOSURE_IS_EMISSION(sc->type)) { #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) eval += OSLShader::emissive_eval(sd, sc)*sc->weight; else #endif @@ -656,7 +690,7 @@ __device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag) { #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) OSLShader::eval_surface(kg, sd, randb, path_flag); else #endif @@ -664,7 +698,7 @@ __device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, #ifdef __SVM__ svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, randb, path_flag); #else - bsdf_diffuse_setup(sd, &sd->closure); + bsdf_diffuse_setup(&sd->closure); sd->closure.weight = make_float3(0.8f, 0.8f, 0.8f); #endif } @@ -675,7 +709,7 @@ __device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, __device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag) { #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) return OSLShader::eval_background(kg, sd, path_flag); else #endif @@ -721,7 +755,7 @@ __device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd, if(CLOSURE_IS_VOLUME(sc->type)) { #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) eval += OSLShader::volume_eval_phase(sc, omega_in, omega_out); else #endif @@ -742,7 +776,7 @@ __device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd, { #ifdef __SVM__ #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) OSLShader::eval_volume(kg, sd, randb, path_flag); else #endif @@ -757,7 +791,7 @@ __device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd) /* this will modify sd->P */ #ifdef __SVM__ #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) OSLShader::eval_displacement(kg, sd); else #endif @@ -813,7 +847,7 @@ __device void shader_merge_closures(KernelGlobals *kg, ShaderData *sd) __device void shader_release(KernelGlobals *kg, ShaderData *sd) { #ifdef __OSL__ - if (kernel_osl_use(kg)) + if (kg->osl) OSLShader::release(kg, sd); #endif } diff --git a/intern/cycles/kernel/kernel_triangle.h b/intern/cycles/kernel/kernel_triangle.h index e39ae1d4fbc..0db447289c8 100644 --- a/intern/cycles/kernel/kernel_triangle.h +++ b/intern/cycles/kernel/kernel_triangle.h @@ -16,9 +16,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "kernel_attribute.h" -#include "kernel_projection.h" - CCL_NAMESPACE_BEGIN /* Point on triangle for Moller-Trumbore triangles */ diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 98d998351a7..e3a766e56b1 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -29,7 +29,7 @@ CCL_NAMESPACE_BEGIN /* constants */ -#define OBJECT_SIZE 22 +#define OBJECT_SIZE 18 #define LIGHT_SIZE 4 #define FILTER_TABLE_SIZE 256 #define RAMP_TABLE_SIZE 256 @@ -102,6 +102,7 @@ CCL_NAMESPACE_BEGIN #define __IMAGE_TEXTURES__ #define __EXTRA_NODES__ #define __HOLDOUT__ +#define __NORMAL_MAP__ #endif #ifdef __KERNEL_ADV_SHADING__ @@ -111,13 +112,10 @@ CCL_NAMESPACE_BEGIN #define __BACKGROUND_MIS__ #define __AO__ #define __CAMERA_MOTION__ - -#ifndef __KERNEL_CUDA__ +#define __ANISOTROPIC__ #define __OBJECT_MOTION__ #endif -#endif - //#define __SOBOL_FULL_SCREEN__ /* Shader Evaluation */ @@ -368,15 +366,17 @@ typedef struct ShaderClosure { float sample_weight; #endif -#ifdef __OSL__ - void *prim; -#endif float data0; float data1; float3 N; +#ifdef __ANISOTROPIC__ float3 T; +#endif +#ifdef __OSL__ + void *prim; +#endif } ShaderClosure; /* Shader Data @@ -393,16 +393,18 @@ enum ShaderDataFlag { 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? */ /* shader flags */ - SD_SAMPLE_AS_LIGHT = 128, /* direct light sample */ - SD_HAS_SURFACE_TRANSPARENT = 256, /* has surface transparency */ - SD_HAS_VOLUME = 512, /* has volume shader */ - SD_HOMOGENEOUS_VOLUME = 1024, /* has homogeneous volume */ + 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 */ /* object flags */ - SD_HOLDOUT_MASK = 2048, /* holdout for camera rays */ - SD_OBJECT_MOTION = 4096 /* has object motion blur */ + SD_HOLDOUT_MASK = 4096, /* holdout for camera rays */ + SD_OBJECT_MOTION = 8192, /* has object motion blur */ + SD_TRANSFORM_APPLIED = 16384 /* vertices have transform applied */ }; typedef struct ShaderData { diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt index 8938b16a48f..1b1bb558bc9 100644 --- a/intern/cycles/kernel/osl/CMakeLists.txt +++ b/intern/cycles/kernel/osl/CMakeLists.txt @@ -14,6 +14,7 @@ set(INC_SYS set(SRC background.cpp + bsdf_phong_ramp.cpp emissive.cpp osl_closures.cpp osl_services.cpp diff --git a/intern/cycles/kernel/osl/SConscript b/intern/cycles/kernel/osl/SConscript new file mode 100644 index 00000000000..d4b42d2becb --- /dev/null +++ b/intern/cycles/kernel/osl/SConscript @@ -0,0 +1,27 @@ +#!/usr/bin/python + +Import('env') + +defs = [] +incs = [] +cxxflags = Split(env['CXXFLAGS']) + +sources = env.Glob('*.cpp') + +incs.extend('. .. ../svm ../../render ../../util ../../device'.split()) +incs.append(env['BF_OIIO_INC']) +incs.append(env['BF_BOOST_INC']) +incs.append(env['BF_OSL_INC']) +incs.append(env['BF_OPENEXR_INC'].split()) + +defs.append('CCL_NAMESPACE_BEGIN=namespace ccl {') +defs.append('CCL_NAMESPACE_END=}') +defs.append('WITH_OSL') + +if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): + cxxflags.append('-DBOOST_NO_RTTI -DBOOST_NO_TYPEID'.split()) + incs.append(env['BF_PTHREADS_INC']) +else: + cxxflags.append('-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID'.split()) + +env.BlenderLib ('cycles_kernel_osl', sources, incs, defs, libtype=['intern'], priority=[10], cxx_compileflags=cxxflags) diff --git a/intern/cycles/kernel/osl/background.cpp b/intern/cycles/kernel/osl/background.cpp index b6e9473b7bf..eed4446cddc 100644 --- a/intern/cycles/kernel/osl/background.cpp +++ b/intern/cycles/kernel/osl/background.cpp @@ -73,6 +73,22 @@ public: void print_on(std::ostream &out) const { out << name() << " ()"; } }; +/// ambient occlusion closure +/// +/// We only have a ambient occlusion closure for the shaders +/// to return a color in ambient occlusion shaders. No methods, +/// only the weight is taking into account +/// +class AmbientOcclusionClosure : public ClosurePrimitive { +public: + AmbientOcclusionClosure () : ClosurePrimitive((ClosurePrimitive::Category)AmbientOcclusion) {} + + void setup() {}; + size_t memsize() const { return sizeof(*this); } + const char *name() const { return "ambient_occlusion"; } + void print_on(std::ostream &out) const { out << name() << " ()"; } +}; + ClosureParam *closure_background_params() { static ClosureParam params[] = { @@ -94,5 +110,16 @@ ClosureParam *closure_holdout_params() CLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure) +ClosureParam *closure_ambient_occlusion_params() +{ + static ClosureParam params[] = { + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(AmbientOcclusionClosure) + }; + return params; +} + +CLOSURE_PREPARE(closure_ambient_occlusion_prepare, AmbientOcclusionClosure) + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp new file mode 100644 index 00000000000..fb144be7e50 --- /dev/null +++ b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp @@ -0,0 +1,115 @@ +/* + * 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 + +#include + +#include "osl_closures.h" + +#include "kernel_types.h" +#include "closure/bsdf_phong_ramp.h" + +CCL_NAMESPACE_BEGIN + +using namespace OSL; + +class PhongRampClosure : public CBSDFClosure { +public: + PhongRampClosure() : CBSDFClosure(LABEL_GLOSSY) {} + Color3 colors[8]; + float3 fcolors[8]; + + size_t memsize() const { return sizeof(*this); } + const char *name() const { return "phong_ramp"; } + + void setup() + { + sc.N = TO_FLOAT3(N); + m_shaderdata_flag = bsdf_phong_ramp_setup(&sc); + + for(int i = 0; i < 8; i++) + fcolors[i] = TO_FLOAT3(colors[i]); + } + + bool mergeable(const ClosurePrimitive *other) const + { + return false; + } + + void blur(float roughness) + { + bsdf_phong_ramp_blur(&sc, roughness); + } + + void print_on(std::ostream &out) const + { + out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))"; + } + + float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const + { + return bsdf_phong_ramp_eval_reflect(&sc, fcolors, omega_out, omega_in, &pdf); + } + + float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const + { + return bsdf_phong_ramp_eval_transmit(&sc, fcolors, omega_out, omega_in, &pdf); + } + + int sample(const float3 &Ng, + const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy, + float randu, float randv, + float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy, + float &pdf, float3 &eval) const + { + return bsdf_phong_ramp_sample(&sc, fcolors, Ng, omega_out, domega_out_dx, domega_out_dy, + randu, randv, &eval, &omega_in, &domega_in_dx, &domega_in_dy, &pdf); + } +}; + +ClosureParam *closure_bsdf_phong_ramp_params() +{ + static ClosureParam params[] = { + CLOSURE_VECTOR_PARAM(PhongRampClosure, N), + CLOSURE_FLOAT_PARAM(PhongRampClosure, sc.data0), + CLOSURE_COLOR_ARRAY_PARAM(PhongRampClosure, colors, 8), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(PhongRampClosure) + }; + return params; +} + +CLOSURE_PREPARE(closure_bsdf_phong_ramp_prepare, PhongRampClosure) + +CCL_NAMESPACE_END + diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index 73e96643df7..f95859d237d 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -48,6 +48,7 @@ #include "closure/bsdf_diffuse.h" #include "closure/bsdf_microfacet.h" #include "closure/bsdf_oren_nayar.h" +#include "closure/bsdf_phong_ramp.h" #include "closure/bsdf_reflection.h" #include "closure/bsdf_refraction.h" #include "closure/bsdf_transparent.h" @@ -152,8 +153,9 @@ static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, O ss->register_closure(name, id, params, prepare, generic_closure_setup, generic_closure_compare); } -void OSLShader::register_closures(OSL::ShadingSystem *ss) +void OSLShader::register_closures(OSLShadingSystem *ss_) { + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)ss_; int id = 0; register_closure(ss, "diffuse", id++, @@ -190,6 +192,10 @@ void OSLShader::register_closures(OSL::ShadingSystem *ss) closure_background_params(), closure_background_prepare); register_closure(ss, "holdout", id++, closure_holdout_params(), closure_holdout_prepare); + register_closure(ss, "ambient_occlusion", id++, + closure_ambient_occlusion_params(), closure_ambient_occlusion_prepare); + register_closure(ss, "phong_ramp", id++, + closure_bsdf_phong_ramp_params(), closure_bsdf_phong_ramp_prepare); } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h index 574cb685db5..2d91b37be7e 100644 --- a/intern/cycles/kernel/osl/osl_closures.h +++ b/intern/cycles/kernel/osl/osl_closures.h @@ -46,10 +46,18 @@ CCL_NAMESPACE_BEGIN OSL::ClosureParam *closure_emission_params(); OSL::ClosureParam *closure_background_params(); OSL::ClosureParam *closure_holdout_params(); +OSL::ClosureParam *closure_ambient_occlusion_params(); +OSL::ClosureParam *closure_bsdf_phong_ramp_params(); void closure_emission_prepare(OSL::RendererServices *, int id, void *data); void closure_background_prepare(OSL::RendererServices *, int id, void *data); void closure_holdout_prepare(OSL::RendererServices *, int id, void *data); +void closure_ambient_occlusion_prepare(OSL::RendererServices *, int id, void *data); +void closure_bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data); + +enum { + AmbientOcclusion = 100 +}; #define CLOSURE_PREPARE(name, classname) \ void name(RendererServices *, int id, void *data) \ @@ -58,6 +66,8 @@ void name(RendererServices *, int id, void *data) \ new (data) classname(); \ } +#define CLOSURE_PREPARE_STATIC(name, classname) static CLOSURE_PREPARE(name, classname) + #define TO_VEC3(v) (*(OSL::Vec3 *)&(v)) #define TO_COLOR3(v) (*(OSL::Color3 *)&(v)) #define TO_FLOAT3(v) make_float3(v[0], v[1], v[2]) @@ -69,26 +79,26 @@ public: ShaderClosure sc; OSL::Vec3 N, T; - CBSDFClosure(int scattering) : OSL::ClosurePrimitive(BSDF), - m_scattering_label(scattering), m_shaderdata_flag(0) { } - ~CBSDFClosure() { } + CBSDFClosure(int scattering) : OSL::ClosurePrimitive(BSDF), + m_scattering_label(scattering), m_shaderdata_flag(0) { } + ~CBSDFClosure() { } - int scattering() const { return m_scattering_label; } - int shaderdata_flag() const { return m_shaderdata_flag; } + int scattering() const { return m_scattering_label; } + int shaderdata_flag() const { return m_shaderdata_flag; } ClosureType shaderclosure_type() const { return sc.type; } - virtual void blur(float roughness) = 0; - virtual float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0; - virtual float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0; + virtual void blur(float roughness) = 0; + virtual float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0; + virtual float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0; - virtual int sample(const float3 &Ng, - const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy, - float randu, float randv, - float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy, - float &pdf, float3 &eval) const = 0; + virtual int sample(const float3 &Ng, + const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy, + float randu, float randv, + float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy, + float &pdf, float3 &eval) const = 0; protected: - int m_scattering_label; + int m_scattering_label; int m_shaderdata_flag; }; @@ -143,7 +153,7 @@ public: \ } \ }; \ \ -ClosureParam *bsdf_##lower##_params() \ +static ClosureParam *bsdf_##lower##_params() \ { \ static ClosureParam params[] = { @@ -156,7 +166,7 @@ ClosureParam *bsdf_##lower##_params() \ return params; \ } \ \ -CLOSURE_PREPARE(bsdf_##lower##_prepare, Upper##Closure) +CLOSURE_PREPARE_STATIC(bsdf_##lower##_prepare, Upper##Closure) CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h index 8cbbfc8dbb1..1a2a210de88 100644 --- a/intern/cycles/kernel/osl/osl_globals.h +++ b/intern/cycles/kernel/osl/osl_globals.h @@ -22,22 +22,35 @@ #ifdef WITH_OSL #include +#include #include "util_map.h" #include "util_param.h" #include "util_thread.h" #include "util_vector.h" +#ifndef WIN32 +using std::isfinite; +#endif + CCL_NAMESPACE_BEGIN class OSLRenderServices; struct OSLGlobals { - /* use */ + OSLGlobals() + { + ss = NULL; + ts = NULL; + services = NULL; + use = false; + } + bool use; /* shading system */ OSL::ShadingSystem *ss; + OSL::TextureSystem *ts; OSLRenderServices *services; /* shader states */ @@ -59,14 +72,13 @@ struct OSLGlobals { vector attribute_map; ObjectNameMap object_name_map; + vector object_names; +}; - /* thread key for thread specific data lookup */ - struct ThreadData { - OSL::ShaderGlobals globals; - OSL::PerThreadInfo *thread_info; - }; - - static tls_ptr(ThreadData, thread_data); +/* thread key for thread specific data lookup */ +struct OSLThreadData { + OSL::ShaderGlobals globals; + OSL::PerThreadInfo *thread_info; }; CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index ac26fc1c18d..b584a54b1b7 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -22,6 +22,8 @@ #include "object.h" #include "scene.h" +#include "osl_closures.h" +#include "osl_globals.h" #include "osl_services.h" #include "osl_shader.h" @@ -30,8 +32,16 @@ #include "kernel_compat_cpu.h" #include "kernel_globals.h" +#include "kernel_montecarlo.h" +#include "kernel_projection.h" +#include "kernel_differential.h" #include "kernel_object.h" +#include "kernel_bvh.h" +#include "kernel_attribute.h" +#include "kernel_projection.h" #include "kernel_triangle.h" +#include "kernel_accumulate.h" +#include "kernel_shader.h" CCL_NAMESPACE_BEGIN @@ -46,6 +56,34 @@ ustring OSLRenderServices::u_camera("camera"); ustring OSLRenderServices::u_screen("screen"); ustring OSLRenderServices::u_raster("raster"); ustring OSLRenderServices::u_ndc("NDC"); +ustring OSLRenderServices::u_object_location("object:location"); +ustring OSLRenderServices::u_object_index("object:index"); +ustring OSLRenderServices::u_geom_dupli_generated("geom:dupli_generated"); +ustring OSLRenderServices::u_geom_dupli_uv("geom:dupli_uv"); +ustring OSLRenderServices::u_material_index("material:index"); +ustring OSLRenderServices::u_object_random("object:random"); +ustring OSLRenderServices::u_particle_index("particle:index"); +ustring OSLRenderServices::u_particle_age("particle:age"); +ustring OSLRenderServices::u_particle_lifetime("particle:lifetime"); +ustring OSLRenderServices::u_particle_location("particle:location"); +ustring OSLRenderServices::u_particle_rotation("particle:rotation"); +ustring OSLRenderServices::u_particle_size("particle:size"); +ustring OSLRenderServices::u_particle_velocity("particle:velocity"); +ustring OSLRenderServices::u_particle_angular_velocity("particle:angular_velocity"); +ustring OSLRenderServices::u_geom_numpolyvertices("geom:numpolyvertices"); +ustring OSLRenderServices::u_geom_trianglevertices("geom:trianglevertices"); +ustring OSLRenderServices::u_geom_polyvertices("geom:polyvertices"); +ustring OSLRenderServices::u_geom_name("geom:name"); +ustring OSLRenderServices::u_path_ray_length("path:ray_length"); +ustring OSLRenderServices::u_trace("trace"); +ustring OSLRenderServices::u_hit("hit"); +ustring OSLRenderServices::u_hitdist("hitdist"); +ustring OSLRenderServices::u_N("N"); +ustring OSLRenderServices::u_Ng("Ng"); +ustring OSLRenderServices::u_P("P"); +ustring OSLRenderServices::u_I("I"); +ustring OSLRenderServices::u_u("u"); +ustring OSLRenderServices::u_v("v"); ustring OSLRenderServices::u_empty; OSLRenderServices::OSLRenderServices() @@ -73,7 +111,12 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr if (object != ~0) { #ifdef __OBJECT_MOTION__ - Transform tfm = object_fetch_transform_motion_test(kg, object, time, NULL); + Transform tfm; + + if(time == sd->time) + tfm = sd->ob_tfm; + else + tfm = object_fetch_transform_motion_test(kg, object, time, NULL); #else Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); #endif @@ -99,7 +142,11 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::Transform if (object != ~0) { #ifdef __OBJECT_MOTION__ Transform itfm; - object_fetch_transform_motion_test(kg, object, time, &itfm); + + if(time == sd->time) + itfm = sd->ob_itfm; + else + object_fetch_transform_motion_test(kg, object, time, &itfm); #else Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); #endif @@ -282,7 +329,7 @@ bool OSLRenderServices::get_array_attribute(void *renderstate, bool derivatives, return false; } -static void set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, void *val) +static bool set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, void *val) { if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) @@ -302,8 +349,10 @@ static void set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, v fval[7] = f[2].y; fval[8] = f[2].z; } + + return true; } - else { + else if(type == TypeDesc::TypeFloat) { float *fval = (float *)val; fval[0] = average(f[0]); @@ -311,10 +360,25 @@ static void set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, v fval[1] = average(f[1]); fval[2] = average(f[2]); } + + return true; } + + return false; } -static void set_attribute_float(float f[3], TypeDesc type, bool derivatives, void *val) +static bool set_attribute_float3(float3 f, TypeDesc type, bool derivatives, void *val) +{ + float3 fv[3]; + + fv[0] = f; + fv[1] = make_float3(0.0f, 0.0f, 0.0f); + fv[2] = make_float3(0.0f, 0.0f, 0.0f); + + return set_attribute_float3(fv, type, derivatives, val); +} + +static bool set_attribute_float(float f[3], TypeDesc type, bool derivatives, void *val) { if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) @@ -333,8 +397,10 @@ static void set_attribute_float(float f[3], TypeDesc type, bool derivatives, voi fval[7] = f[2]; fval[8] = f[2]; } + + return true; } - else { + else if(type == TypeDesc::TypeFloat) { float *fval = (float *)val; fval[0] = f[0]; @@ -342,7 +408,22 @@ static void set_attribute_float(float f[3], TypeDesc type, bool derivatives, voi fval[1] = f[1]; fval[2] = f[2]; } + + return true; } + + return false; +} + +static bool set_attribute_float(float f, TypeDesc type, bool derivatives, void *val) +{ + float fv[3]; + + fv[0] = f; + fv[1] = 0.0f; + fv[2] = 0.0f; + + return set_attribute_float(fv, type, derivatives, val); } static bool set_attribute_int(int i, TypeDesc type, bool derivatives, void *val) @@ -362,6 +443,23 @@ static bool set_attribute_int(int i, TypeDesc type, bool derivatives, void *val) return false; } +static bool set_attribute_string(ustring str, TypeDesc type, bool derivatives, void *val) +{ + if(type.basetype == TypeDesc::INT && type.aggregate == TypeDesc::SCALAR && type.arraylen == 0) { + ustring *sval = (ustring *)val; + sval[0] = str; + + if (derivatives) { + sval[1] = OSLRenderServices::u_empty; + sval[2] = OSLRenderServices::u_empty; + } + + return true; + } + + return false; +} + static bool set_attribute_float3_3(float3 P[3], TypeDesc type, bool derivatives, void *val) { if(type.vecsemantics == TypeDesc::POINT && type.arraylen >= 3) { @@ -394,20 +492,18 @@ static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OS const TypeDesc& type, bool derivatives, void *val) { if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector || - attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) + attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) { float3 fval[3]; fval[0] = triangle_attribute_float3(kg, sd, attr.elem, attr.offset, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); - set_attribute_float3(fval, type, derivatives, val); - return true; + return set_attribute_float3(fval, type, derivatives, val); } else if (attr.type == TypeDesc::TypeFloat) { float fval[3]; fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); - set_attribute_float(fval, type, derivatives, val); - return true; + return set_attribute_float(fval, type, derivatives, val); } else { return false; @@ -423,147 +519,110 @@ static void get_object_attribute(const OSLGlobals::Attribute& attr, bool derivat memset((char *)val + datasize, 0, datasize * 2); } -static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, - TypeDesc type, bool derivatives, void *val) +bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, + TypeDesc type, bool derivatives, void *val) { - /* todo: turn this into hash table + callback once */ + /* todo: turn this into hash table? */ /* Object Attributes */ - if (name == "object:location") { - float3 fval[3]; - fval[0] = object_location(kg, sd); - fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float3(fval, type, derivatives, val); - return true; + if (name == u_object_location) { + float3 f = object_location(kg, sd); + return set_attribute_float3(f, type, derivatives, val); } - else if (name == "object:index") { - float fval[3]; - fval[0] = object_pass_id(kg, sd->object); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + else if (name == u_object_index) { + float f = object_pass_id(kg, sd->object); + return set_attribute_float(f, type, derivatives, val); } - else if (name == "geom:dupli_generated") { - float3 fval[3]; - fval[0] = object_dupli_generated(kg, sd->object); - fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float3(fval, type, derivatives, val); - return true; + else if (name == u_geom_dupli_generated) { + float3 f = object_dupli_generated(kg, sd->object); + return set_attribute_float3(f, type, derivatives, val); } - else if (name == "geom:dupli_uv") { - float3 fval[3]; - fval[0] = object_dupli_uv(kg, sd->object); - fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float3(fval, type, derivatives, val); - return true; + else if (name == u_geom_dupli_uv) { + float3 f = object_dupli_uv(kg, sd->object); + return set_attribute_float3(f, type, derivatives, val); } - else if (name == "material:index") { - float fval[3]; - fval[0] = shader_pass_id(kg, sd); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + else if (name == u_material_index) { + float f = shader_pass_id(kg, sd); + return set_attribute_float(f, type, derivatives, val); } - else if (name == "object:random") { - float fval[3]; - fval[0] = object_random_number(kg, sd->object); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + else if (name == u_object_random) { + float f = object_random_number(kg, sd->object); + return set_attribute_float(f, type, derivatives, val); } /* Particle Attributes */ - else if (name == "particle:index") { - float fval[3]; + else if (name == u_particle_index) { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_index(kg, particle_id); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + float f = particle_index(kg, particle_id); + return set_attribute_float(f, type, derivatives, val); } - else if (name == "particle:age") { - float fval[3]; + else if (name == u_particle_age) { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_age(kg, particle_id); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + float f = particle_age(kg, particle_id); + return set_attribute_float(f, type, derivatives, val); } - else if (name == "particle:lifetime") { - float fval[3]; + else if (name == u_particle_lifetime) { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_lifetime(kg, particle_id); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + float f= particle_lifetime(kg, particle_id); + return set_attribute_float(f, type, derivatives, val); } - else if (name == "particle:location") { - float3 fval[3]; + else if (name == u_particle_location) { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_location(kg, particle_id); - fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float3(fval, type, derivatives, val); - return true; + float3 f = particle_location(kg, particle_id); + return set_attribute_float3(f, type, derivatives, val); } #if 0 /* unsupported */ - else if (name == "particle:rotation") { - float4 fval[3]; + else if (name == u_particle_rotation) { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_rotation(kg, particle_id); - fval[1] = fval[2] = make_float4(0.0, 0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float4(fval, type, derivatives, val); - return true; + float4 f = particle_rotation(kg, particle_id); + return set_attribute_float4(f, type, derivatives, val); } #endif - else if (name == "particle:size") { - float fval[3]; + else if (name == u_particle_size) { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_size(kg, particle_id); - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + float f = particle_size(kg, particle_id); + return set_attribute_float(f, type, derivatives, val); } - else if (name == "particle:velocity") { - float3 fval[3]; + else if (name == u_particle_velocity) { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_velocity(kg, particle_id); - fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float3(fval, type, derivatives, val); - return true; + float3 f = particle_velocity(kg, particle_id); + return set_attribute_float3(f, type, derivatives, val); } - else if (name == "particle:angular_velocity") { - float3 fval[3]; + else if (name == u_particle_angular_velocity) { uint particle_id = object_particle_id(kg, sd->object); - fval[0] = particle_angular_velocity(kg, particle_id); - fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ - set_attribute_float3(fval, type, derivatives, val); - return true; + float3 f = particle_angular_velocity(kg, particle_id); + return set_attribute_float3(f, type, derivatives, val); } - else if (name == "geom:numpolyvertices") { + else if (name == u_geom_numpolyvertices) { return set_attribute_int(3, type, derivatives, val); } - else if (name == "geom:trianglevertices" || name == "geom:polyvertices") { + else if (name == u_geom_trianglevertices || name == u_geom_polyvertices) { float3 P[3]; triangle_vertices(kg, sd->prim, P); - object_position_transform(kg, sd, &P[0]); - object_position_transform(kg, sd, &P[1]); - object_position_transform(kg, sd, &P[2]); + + if(!(sd->flag & SD_TRANSFORM_APPLIED)) { + object_position_transform(kg, sd, &P[0]); + object_position_transform(kg, sd, &P[1]); + object_position_transform(kg, sd, &P[2]); + } + return set_attribute_float3_3(P, type, derivatives, val); } + else if(name == u_geom_name) { + ustring object_name = kg->osl->object_names[sd->object]; + return set_attribute_string(object_name, type, derivatives, val); + } else return false; } -static bool get_background_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, - TypeDesc type, bool derivatives, void *val) +bool OSLRenderServices::get_background_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, + TypeDesc type, bool derivatives, void *val) { /* Ray Length */ - if (name == "path:ray_length") { - float fval[3]; - fval[0] = sd->ray_length; - fval[1] = fval[2] = 0.0; /* derivates set to 0 */ - set_attribute_float(fval, type, derivatives, val); - return true; + if (name == u_path_ray_length) { + float f = sd->ray_length; + return set_attribute_float(f, type, derivatives, val); } else @@ -580,9 +639,9 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri /* lookup of attribute on another object */ if (object_name != u_empty) { - OSLGlobals::ObjectNameMap::iterator it = kg->osl.object_name_map.find(object_name); + OSLGlobals::ObjectNameMap::iterator it = kg->osl->object_name_map.find(object_name); - if (it == kg->osl.object_name_map.end()) + if (it == kg->osl->object_name_map.end()) return false; object = it->second; @@ -593,7 +652,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri } /* find attribute on object */ - OSLGlobals::AttributeMap& attribute_map = kg->osl.attribute_map[object]; + OSLGlobals::AttributeMap& attribute_map = kg->osl->attribute_map[object]; OSLGlobals::AttributeMap::iterator it = attribute_map.find(name); if (it != attribute_map.end()) { @@ -634,6 +693,80 @@ bool OSLRenderServices::has_userdata(ustring name, TypeDesc type, void *renderst return false; /* never called by OSL */ } +bool OSLRenderServices::texture(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, + float s, float t, float dsdx, float dtdx, + float dsdy, float dtdy, float *result) +{ + OSL::TextureSystem *ts = kernel_globals->osl->ts; + bool status = ts->texture(filename, options, s, t, dsdx, dtdx, dsdy, dtdy, result); + + if(!status) { + if(options.nchannels == 3 || options.nchannels == 4) { + result[0] = 1.0f; + result[1] = 0.0f; + result[2] = 1.0f; + + if(options.nchannels == 4) + result[3] = 1.0f; + } + } + + return status; +} + +bool OSLRenderServices::texture3d(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, const OSL::Vec3 &P, + const OSL::Vec3 &dPdx, const OSL::Vec3 &dPdy, + const OSL::Vec3 &dPdz, float *result) +{ + OSL::TextureSystem *ts = kernel_globals->osl->ts; + bool status = ts->texture3d(filename, options, P, dPdx, dPdy, dPdz, result); + + if(!status) { + if(options.nchannels == 3 || options.nchannels == 4) { + result[0] = 1.0f; + result[1] = 0.0f; + result[2] = 1.0f; + + if(options.nchannels == 4) + result[3] = 1.0f; + } + + } + + return status; +} + +bool OSLRenderServices::environment(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, const OSL::Vec3 &R, + const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy, float *result) +{ + OSL::TextureSystem *ts = kernel_globals->osl->ts; + bool status = ts->environment(filename, options, R, dRdx, dRdy, result); + + if(!status) { + if(options.nchannels == 3 || options.nchannels == 4) { + result[0] = 1.0f; + result[1] = 0.0f; + result[2] = 1.0f; + + if(options.nchannels == 4) + result[3] = 1.0f; + } + } + + return status; +} + +bool OSLRenderServices::get_texture_info(ustring filename, int subimage, + ustring dataname, + TypeDesc datatype, void *data) +{ + OSL::TextureSystem *ts = kernel_globals->osl->ts; + return ts->get_texture_info(filename, subimage, dataname, datatype, data); +} + int OSLRenderServices::pointcloud_search(OSL::ShaderGlobals *sg, ustring filename, const OSL::Vec3 ¢er, float radius, int max_points, bool sort, size_t *out_indices, float *out_distances, int derivs_offset) @@ -647,4 +780,107 @@ int OSLRenderServices::pointcloud_get(ustring filename, size_t *indices, int cou return 0; } +bool OSLRenderServices::trace(TraceOpt &options, OSL::ShaderGlobals *sg, + const OSL::Vec3 &P, const OSL::Vec3 &dPdx, + const OSL::Vec3 &dPdy, const OSL::Vec3 &R, + const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy) +{ + /* todo: options.shader support, maybe options.traceset */ + ShaderData *sd = (ShaderData *)(sg->renderstate); + + /* setup ray */ + Ray ray; + + ray.P = TO_FLOAT3(P); + ray.D = TO_FLOAT3(R); + ray.t = (options.maxdist == 1.0e30)? FLT_MAX: options.maxdist - options.mindist; + ray.time = sd->time; + + if(options.mindist == 0.0f) { + /* avoid self-intersections */ + if(ray.P == sd->P) { + bool transmit = (dot(sd->Ng, ray.D) < 0.0f); + ray.P = ray_offset(sd->P, (transmit)? -sd->Ng: sd->Ng); + } + } + else { + /* offset for minimum distance */ + ray.P += options.mindist*ray.D; + } + + /* ray differentials */ + ray.dP.dx = TO_FLOAT3(dPdx); + ray.dP.dy = TO_FLOAT3(dPdy); + ray.dD.dx = TO_FLOAT3(dRdx); + ray.dD.dy = TO_FLOAT3(dRdy); + + /* allocate trace data */ + TraceData *tracedata = new TraceData(); + tracedata->ray = ray; + tracedata->setup = false; + + if(sg->tracedata) + delete (TraceData*)sg->tracedata; + sg->tracedata = tracedata; + + /* raytrace */ + return scene_intersect(kernel_globals, &ray, ~0, &tracedata->isect); +} + + +bool OSLRenderServices::getmessage(OSL::ShaderGlobals *sg, ustring source, ustring name, + TypeDesc type, void *val, bool derivatives) +{ + TraceData *tracedata = (TraceData*)sg->tracedata; + + if(source == u_trace && tracedata) { + if(name == u_hit) { + return set_attribute_int((tracedata->isect.prim != ~0), type, derivatives, val); + } + else if(tracedata->isect.prim != ~0) { + if(name == u_hitdist) { + float f[3] = {tracedata->isect.t, 0.0f, 0.0f}; + return set_attribute_float(f, type, derivatives, val); + } + else { + KernelGlobals *kg = kernel_globals; + ShaderData *sd = &tracedata->sd; + + if(!tracedata->setup) { + /* lazy shader data setup */ + shader_setup_from_ray(kg, sd, &tracedata->isect, &tracedata->ray); + tracedata->setup = true; + } + + if(name == u_N) { + return set_attribute_float3(sd->N, type, derivatives, val); + } + else if(name == u_Ng) { + return set_attribute_float3(sd->Ng, type, derivatives, val); + } + else if(name == u_P) { + float3 f[3] = {sd->P, sd->dP.dx, sd->dP.dy}; + return set_attribute_float3(f, type, derivatives, val); + } + else if(name == u_I) { + float3 f[3] = {sd->I, sd->dI.dx, sd->dI.dy}; + return set_attribute_float3(f, type, derivatives, val); + } + else if(name == u_u) { + float f[3] = {sd->u, sd->du.dx, sd->du.dy}; + return set_attribute_float(f, type, derivatives, val); + } + else if(name == u_v) { + float f[3] = {sd->v, sd->dv.dx, sd->dv.dy}; + return set_attribute_float(f, type, derivatives, val); + } + + return get_attribute(sd, derivatives, u_empty, type, name, val); + } + } + } + + return false; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h index fa32d47a89f..e687700b383 100644 --- a/intern/cycles/kernel/osl/osl_services.h +++ b/intern/cycles/kernel/osl/osl_services.h @@ -76,8 +76,42 @@ public: int pointcloud_get(ustring filename, size_t *indices, int count, ustring attr_name, TypeDesc attr_type, void *out_data); -private: - KernelGlobals *kernel_globals; + bool trace(TraceOpt &options, OSL::ShaderGlobals *sg, + const OSL::Vec3 &P, const OSL::Vec3 &dPdx, + const OSL::Vec3 &dPdy, const OSL::Vec3 &R, + const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy); + + bool getmessage(OSL::ShaderGlobals *sg, ustring source, ustring name, + TypeDesc type, void *val, bool derivatives); + + bool texture(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, + float s, float t, float dsdx, float dtdx, + float dsdy, float dtdy, float *result); + + bool texture3d(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, const OSL::Vec3 &P, + const OSL::Vec3 &dPdx, const OSL::Vec3 &dPdy, + const OSL::Vec3 &dPdz, float *result); + + bool environment(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, const OSL::Vec3 &R, + const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy, float *result); + + bool get_texture_info(ustring filename, int subimage, + ustring dataname, TypeDesc datatype, void *data); + + static bool get_background_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, + TypeDesc type, bool derivatives, void *val); + static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, + TypeDesc type, bool derivatives, void *val); + + struct TraceData { + Ray ray; + Intersection isect; + ShaderData sd; + bool setup; + }; static ustring u_distance; static ustring u_index; @@ -85,7 +119,38 @@ private: static ustring u_screen; static ustring u_raster; static ustring u_ndc; + static ustring u_object_location; + static ustring u_object_index; + static ustring u_geom_dupli_generated; + static ustring u_geom_dupli_uv; + static ustring u_material_index; + static ustring u_object_random; + static ustring u_particle_index; + static ustring u_particle_age; + static ustring u_particle_lifetime; + static ustring u_particle_location; + static ustring u_particle_rotation; + static ustring u_particle_size; + static ustring u_particle_velocity; + static ustring u_particle_angular_velocity; + static ustring u_geom_numpolyvertices; + static ustring u_geom_trianglevertices; + static ustring u_geom_polyvertices; + static ustring u_geom_name; + static ustring u_path_ray_length; + static ustring u_trace; + static ustring u_hit; + static ustring u_hitdist; + static ustring u_N; + static ustring u_Ng; + static ustring u_P; + static ustring u_I; + static ustring u_u; + static ustring u_v; static ustring u_empty; + +private: + KernelGlobals *kernel_globals; }; CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index 8b71ac30ab6..32712b25e92 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -22,42 +22,56 @@ #include "kernel_object.h" #include "osl_closures.h" +#include "osl_globals.h" #include "osl_services.h" #include "osl_shader.h" +#include "util_attribute.h" #include "util_foreach.h" #include CCL_NAMESPACE_BEGIN -tls_ptr(OSLGlobals::ThreadData, OSLGlobals::thread_data); - /* Threads */ -void OSLShader::thread_init(KernelGlobals *kg) +void OSLShader::thread_init(KernelGlobals *kg, KernelGlobals *kernel_globals, OSLGlobals *osl_globals) { - OSL::ShadingSystem *ss = kg->osl.ss; + /* no osl used? */ + if(!osl_globals->use) { + kg->osl = NULL; + return; + } - OSLGlobals::ThreadData *tdata = new OSLGlobals::ThreadData(); + /* per thread kernel data init*/ + kg->osl = osl_globals; + kg->osl->services->thread_init(kernel_globals); + + OSL::ShadingSystem *ss = kg->osl->ss; + OSLThreadData *tdata = new OSLThreadData(); memset(&tdata->globals, 0, sizeof(OSL::ShaderGlobals)); tdata->thread_info = ss->create_thread_info(); - tls_set(kg->osl.thread_data, tdata); - - kg->osl.services->thread_init(kg); + kg->osl_ss = (OSLShadingSystem*)ss; + kg->osl_tdata = tdata; } void OSLShader::thread_free(KernelGlobals *kg) { - OSL::ShadingSystem *ss = kg->osl.ss; + if(!kg->osl) + return; - OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; + OSLThreadData *tdata = kg->osl_tdata; ss->destroy_thread_info(tdata->thread_info); delete tdata; + + kg->osl = NULL; + kg->osl_ss = NULL; + kg->osl_tdata = NULL; } /* Globals */ @@ -83,6 +97,7 @@ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, globals->dPdu = TO_VEC3(sd->dPdu); globals->dPdv = TO_VEC3(sd->dPdv); globals->surfacearea = (sd->object == ~0) ? 1.0f : object_surface_area(kg, sd->object); + globals->time = sd->time; /* booleans */ globals->raytype = path_flag; /* todo: add our own ray types */ @@ -93,6 +108,7 @@ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, /* shader data to be used in services callbacks */ globals->renderstate = sd; + globals->tracedata = NULL; /* hacky, we leave it to services to fetch actual object matrix */ globals->shader2common = sd; @@ -134,13 +150,15 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, /* sample weight */ float sample_weight = fabsf(average(weight)); - sd->flag |= bsdf->shaderdata_flag(); - sc.sample_weight = sample_weight; sc.type = bsdf->shaderclosure_type(); + sc.N = bsdf->sc.N; /* needed for AO */ /* add */ - sd->closure[sd->num_closure++] = sc; + if(sc.sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE) { + sd->closure[sd->num_closure++] = sc; + sd->flag |= bsdf->shaderdata_flag(); + } break; } case OSL::ClosurePrimitive::Emissive: { @@ -154,9 +172,26 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, sc.type = CLOSURE_EMISSION_ID; /* flag */ - sd->flag |= SD_EMISSION; + if(sd->num_closure < MAX_CLOSURE) { + sd->closure[sd->num_closure++] = sc; + sd->flag |= SD_EMISSION; + } + break; + } + case AmbientOcclusion: { + if (sd->num_closure == MAX_CLOSURE) + return; - sd->closure[sd->num_closure++] = sc; + /* sample weight */ + float sample_weight = fabsf(average(weight)); + + sc.sample_weight = sample_weight; + sc.type = CLOSURE_AMBIENT_OCCLUSION_ID; + + if(sd->num_closure < MAX_CLOSURE) { + sd->closure[sd->num_closure++] = sc; + sd->flag |= SD_AO; + } break; } case OSL::ClosurePrimitive::Holdout: @@ -165,8 +200,11 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, sc.sample_weight = 0.0f; sc.type = CLOSURE_HOLDOUT_ID; - sd->flag |= SD_HOLDOUT; - sd->closure[sd->num_closure++] = sc; + + if(sd->num_closure < MAX_CLOSURE) { + sd->closure[sd->num_closure++] = sc; + sd->flag |= SD_HOLDOUT; + } break; case OSL::ClosurePrimitive::BSSRDF: case OSL::ClosurePrimitive::Debug: @@ -191,8 +229,8 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag) { /* gather pointers */ - OSL::ShadingSystem *ss = kg->osl.ss; - OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; + OSLThreadData *tdata = kg->osl_tdata; OSL::ShaderGlobals *globals = &tdata->globals; OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; @@ -202,8 +240,12 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int /* execute shader for this point */ int shader = sd->shader & SHADER_MASK; - if (kg->osl.surface_state[shader]) - ss->execute(*ctx, *(kg->osl.surface_state[shader]), *globals); + if (kg->osl->surface_state[shader]) + ss->execute(*ctx, *(kg->osl->surface_state[shader]), *globals); + + /* free trace data */ + if(globals->tracedata) + delete (OSLRenderServices::TraceData*)globals->tracedata; /* flatten closure tree */ sd->num_closure = 0; @@ -248,8 +290,8 @@ static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure) float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag) { /* gather pointers */ - OSL::ShadingSystem *ss = kg->osl.ss; - OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; + OSLThreadData *tdata = kg->osl_tdata; OSL::ShaderGlobals *globals = &tdata->globals; OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; @@ -257,8 +299,12 @@ float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_fl shaderdata_to_shaderglobals(kg, sd, path_flag, globals); /* execute shader for this point */ - if (kg->osl.background_state) - ss->execute(*ctx, *(kg->osl.background_state), *globals); + if (kg->osl->background_state) + ss->execute(*ctx, *(kg->osl->background_state), *globals); + + /* free trace data */ + if(globals->tracedata) + delete (OSLRenderServices::TraceData*)globals->tracedata; /* return background color immediately */ if (globals->Ci) @@ -296,7 +342,8 @@ static void flatten_volume_closure_tree(ShaderData *sd, sc.type = CLOSURE_VOLUME_ID; /* add */ - sd->closure[sd->num_closure++] = sc; + if(sc.sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE) + sd->closure[sd->num_closure++] = sc; break; } case OSL::ClosurePrimitive::Holdout: @@ -324,8 +371,8 @@ static void flatten_volume_closure_tree(ShaderData *sd, void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag) { /* gather pointers */ - OSL::ShadingSystem *ss = kg->osl.ss; - OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; + OSLThreadData *tdata = kg->osl_tdata; OSL::ShaderGlobals *globals = &tdata->globals; OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; @@ -335,8 +382,12 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int /* execute shader */ int shader = sd->shader & SHADER_MASK; - if (kg->osl.volume_state[shader]) - ss->execute(*ctx, *(kg->osl.volume_state[shader]), *globals); + if (kg->osl->volume_state[shader]) + ss->execute(*ctx, *(kg->osl->volume_state[shader]), *globals); + + /* free trace data */ + if(globals->tracedata) + delete (OSLRenderServices::TraceData*)globals->tracedata; if (globals->Ci) flatten_volume_closure_tree(sd, globals->Ci); @@ -347,8 +398,8 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) { /* gather pointers */ - OSL::ShadingSystem *ss = kg->osl.ss; - OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; + OSLThreadData *tdata = kg->osl_tdata; OSL::ShaderGlobals *globals = &tdata->globals; OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; @@ -358,8 +409,12 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) /* execute shader */ int shader = sd->shader & SHADER_MASK; - if (kg->osl.displacement_state[shader]) - ss->execute(*ctx, *(kg->osl.displacement_state[shader]), *globals); + if (kg->osl->displacement_state[shader]) + ss->execute(*ctx, *(kg->osl->displacement_state[shader]), *globals); + + /* free trace data */ + if(globals->tracedata) + delete (OSLRenderServices::TraceData*)globals->tracedata; /* get back position */ sd->P = TO_FLOAT3(globals->P); @@ -367,15 +422,15 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) void OSLShader::init(KernelGlobals *kg, ShaderData *sd) { - OSL::ShadingSystem *ss = kg->osl.ss; - OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; + OSLThreadData *tdata = kg->osl_tdata; sd->osl_ctx = ss->get_context(tdata->thread_info); } void OSLShader::release(KernelGlobals *kg, ShaderData *sd) { - OSL::ShadingSystem *ss = kg->osl.ss; + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; ss->release_context((OSL::ShadingContext *)sd->osl_ctx); } @@ -433,5 +488,23 @@ float3 OSLShader::volume_eval_phase(const ShaderClosure *sc, const float3 omega_ return TO_FLOAT3(volume_eval) * sc->weight; } +/* Attributes */ + +int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id) +{ + /* for OSL, a hash map is used to lookup the attribute by name. */ + OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[sd->object]; + ustring stdname(std::string("std::") + std::string(attribute_standard_name((AttributeStandard)id))); + OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname); + + if (it != attr_map.end()) { + const OSLGlobals::Attribute &osl_attr = it->second; + /* return result */ + return (osl_attr.elem == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : osl_attr.offset; + } + else + return (int)ATTR_STD_NOT_FOUND; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h index 9ff31e9160b..e614f240dc1 100644 --- a/intern/cycles/kernel/osl/osl_shader.h +++ b/intern/cycles/kernel/osl/osl_shader.h @@ -31,33 +31,27 @@ * This means no thread state must be passed along in the kernel itself. */ -#include -#include - #include "kernel_types.h" -#include "util_map.h" -#include "util_param.h" -#include "util_vector.h" - CCL_NAMESPACE_BEGIN -namespace OSL = ::OSL; - -class OSLRenderServices; class Scene; + struct ShaderClosure; struct ShaderData; struct differential3; struct KernelGlobals; +struct OSLGlobals; +struct OSLShadingSystem; + class OSLShader { public: /* init */ - static void register_closures(OSL::ShadingSystem *ss); + static void register_closures(OSLShadingSystem *ss); /* per thread data */ - static void thread_init(KernelGlobals *kg); + static void thread_init(KernelGlobals *kg, KernelGlobals *kernel_globals, OSLGlobals *osl_globals); static void thread_free(KernelGlobals *kg); /* eval */ @@ -82,6 +76,9 @@ public: /* release */ static void init(KernelGlobals *kg, ShaderData *sd); static void release(KernelGlobals *kg, ShaderData *sd); + + /* attributes */ + static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id); }; CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt index 00ab52a1d13..f7fec62fd6d 100644 --- a/intern/cycles/kernel/shaders/CMakeLists.txt +++ b/intern/cycles/kernel/shaders/CMakeLists.txt @@ -3,9 +3,11 @@ set(SRC_OSL node_add_closure.osl + node_ambient_occlusion.osl node_attribute.osl node_background.osl node_brick_texture.osl + node_brightness.osl node_bump.osl node_camera.osl node_checker_texture.osl @@ -21,35 +23,37 @@ set(SRC_OSL node_environment_texture.osl node_fresnel.osl node_gamma.osl - node_gradient_texture.osl - node_brightness.osl node_geometry.osl node_glass_bsdf.osl node_glossy_bsdf.osl + node_gradient_texture.osl node_holdout.osl node_hsv.osl node_image_texture.osl node_invert.osl node_layer_weight.osl - node_light_path.osl node_light_falloff.osl + node_light_path.osl node_magic_texture.osl node_mapping.osl node_math.osl node_mix.osl node_mix_closure.osl node_musgrave_texture.osl - node_normal.osl node_noise_texture.osl + node_normal.osl + node_normal_map.osl node_object_info.osl node_output_displacement.osl node_output_surface.osl node_output_volume.osl node_particle_info.osl + node_refraction_bsdf.osl node_rgb_ramp.osl node_separate_rgb.osl node_set_normal.osl node_sky_texture.osl + node_tangent.osl node_texture_coordinate.osl node_translucent_bsdf.osl node_transparent_bsdf.osl @@ -85,7 +89,7 @@ foreach(_file ${SRC_OSL}) list(APPEND SRC_OSO ${_OSO_FILE} ) - + unset(_OSL_FILE) unset(_OSO_FILE) endforeach() diff --git a/intern/cycles/kernel/shaders/SConscript b/intern/cycles/kernel/shaders/SConscript new file mode 100644 index 00000000000..36b86d7b4f6 --- /dev/null +++ b/intern/cycles/kernel/shaders/SConscript @@ -0,0 +1,42 @@ +#!/usr/bin/python +import sys +import os +import Blender as B + +def normpath(path): + return os.path.abspath(os.path.normpath(path)) + +Import ('env') + +oso_files = [] + +if env['WITH_BF_CYCLES_OSL']: + shaders = env.Clone() + + # osl compiler + osl_compiler = File(env.subst(env['BF_OSL_COMPILER'])).abspath + + # build directory + root_build_dir = normpath(env['BF_BUILDDIR']) + build_dir = os.path.join(root_build_dir, 'intern/cycles/kernel/shaders') + + # source directories and files + source_dir = Dir('.').srcnode().path + + # dependencies + dependencies = shaders.Glob('*.h') + + for f in os.listdir(source_dir): + if f.endswith('.osl'): + osl_file = os.path.join(source_dir, f) + oso_file = os.path.join(build_dir, f.replace('.osl', '.oso')) + + command = "%s -O2 -I%s -o %s %s" % (osl_compiler, source_dir, oso_file, osl_file) + + shaders.Command(oso_file, f, command) + shaders.Depends(oso_file, [f] + dependencies) + + oso_files.append(oso_file) + + +Return('oso_files') diff --git a/intern/cycles/kernel/shaders/node_ambient_occlusion.osl b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl new file mode 100644 index 00000000000..b9423344e73 --- /dev/null +++ b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl @@ -0,0 +1,28 @@ +/* + * 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_ambient_occlusion( + normal NormalIn = N, + color Color = color(0.8, 0.8, 0.8), + output closure color AO = ambient_occlusion()) +{ + AO = Color * ambient_occlusion(); +} + diff --git a/intern/cycles/kernel/shaders/node_brick_texture.osl b/intern/cycles/kernel/shaders/node_brick_texture.osl index 478d9457001..b1f2a35789f 100644 --- a/intern/cycles/kernel/shaders/node_brick_texture.osl +++ b/intern/cycles/kernel/shaders/node_brick_texture.osl @@ -58,6 +58,8 @@ float brick(point p, float mortar_size, float bias, } shader node_brick_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), float Offset = 0.5, int OffsetFrequency = 2, float Squash = 1.0, @@ -74,10 +76,15 @@ shader node_brick_texture( output float Fac = 0.0, output color Color = color(0.2, 0.2, 0.2)) { + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + float tint = 0.0; color Col = Color1; - Fac = brick(Vector * Scale, MortarSize, Bias, BrickWidth, RowHeight, + Fac = brick(p * Scale, MortarSize, Bias, BrickWidth, RowHeight, Offset, OffsetFrequency, Squash, SquashFrequency, tint); if (Fac != 1.0) { diff --git a/intern/cycles/kernel/shaders/node_brightness.osl b/intern/cycles/kernel/shaders/node_brightness.osl index 8e9f5c9c796..b263d815566 100644 --- a/intern/cycles/kernel/shaders/node_brightness.osl +++ b/intern/cycles/kernel/shaders/node_brightness.osl @@ -20,32 +20,15 @@ shader node_brightness( color ColorIn = color(0.8, 0.8, 0.8), - float Brightness = 0.0, + float Bright = 0.0, float Contrast = 0.0, output color ColorOut = color(0.8, 0.8, 0.8)) { - float delta = Contrast * (1.0 / 200.0); - float a = 1.0 - delta * 2.0; - float b; + float a = 1.0 + Contrast; + float b = Bright - Contrast*0.5; - /* input value is a percentage */ - float bright_factor = Brightness / 100.0; - - /* - * The algorithm is by Werner D. Streidt - * (http://visca.com/ffactory/archives/5-99/msg00021.html) - * Extracted of OpenCV demhist.c - */ - - if (Contrast > 0.0) { - a = (a < 0.0 ? 1.0 / a : 0.0); - b = a * (bright_factor - delta); - } - else { - delta *= -1.0; - b = a * (bright_factor + delta); - } - - ColorOut = a * ColorIn + b; + ColorOut[0] = max(a*ColorIn[0] + b, 0.0); + ColorOut[1] = max(a*ColorIn[1] + b, 0.0); + ColorOut[2] = max(a*ColorIn[2] + b, 0.0); } diff --git a/intern/cycles/kernel/shaders/node_checker_texture.osl b/intern/cycles/kernel/shaders/node_checker_texture.osl index 577caf308ff..eed56f4453a 100644 --- a/intern/cycles/kernel/shaders/node_checker_texture.osl +++ b/intern/cycles/kernel/shaders/node_checker_texture.osl @@ -40,6 +40,8 @@ float checker(point p) } shader node_checker_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), float Scale = 5.0, point Vector = P, color Color1 = color(0.8, 0.8, 0.8), @@ -47,7 +49,12 @@ shader node_checker_texture( output float Fac = 0.0, output color Color = color(0.0, 0.0, 0.0)) { - Fac = checker(Vector * Scale); + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + + Fac = checker(p * Scale); if (Fac == 1.0) { Color = Color1; } diff --git a/intern/cycles/kernel/shaders/node_convert_from_color.osl b/intern/cycles/kernel/shaders/node_convert_from_color.osl index 2884c772414..ea488c9ce4c 100644 --- a/intern/cycles/kernel/shaders/node_convert_from_color.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_color.osl @@ -20,6 +20,7 @@ shader node_convert_from_color( color Color = color(0.0, 0.0, 0.0), + output string String = "", output float Val = 0.0, output int ValInt = 0, output vector Vector = vector(0.0, 0.0, 0.0), @@ -27,7 +28,7 @@ shader node_convert_from_color( output normal Normal = normal(0.0, 0.0, 0.0)) { Val = Color[0] * 0.2126 + Color[1] * 0.7152 + Color[2] * 0.0722; - ValInt = (int)(Color[0]*0.2126 + Color[1]*0.7152 + Color[2]*0.0722); + ValInt = (int)(Color[0] * 0.2126 + Color[1] * 0.7152 + Color[2] * 0.0722); Vector = vector(Color[0], Color[1], Color[2]); Point = point(Color[0], Color[1], Color[2]); Normal = normal(Color[0], Color[1], Color[2]); diff --git a/intern/cycles/kernel/shaders/node_convert_from_float.osl b/intern/cycles/kernel/shaders/node_convert_from_float.osl index 4466fbae3a6..a20b491c91d 100644 --- a/intern/cycles/kernel/shaders/node_convert_from_float.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_float.osl @@ -20,6 +20,7 @@ shader node_convert_from_float( float Val = 0.0, + output string String = "", output int ValInt = 0, output color Color = color(0.0, 0.0, 0.0), output vector Vector = vector(0.0, 0.0, 0.0), diff --git a/intern/cycles/kernel/shaders/node_convert_from_int.osl b/intern/cycles/kernel/shaders/node_convert_from_int.osl index 060d4184fa6..911b4928db8 100644 --- a/intern/cycles/kernel/shaders/node_convert_from_int.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_int.osl @@ -20,6 +20,7 @@ shader node_convert_from_int( int ValInt = 0, + output string String = "", output float Val = 0.0, output color Color = color(0.0, 0.0, 0.0), output vector Vector = vector(0.0, 0.0, 0.0), diff --git a/intern/cycles/kernel/shaders/node_convert_from_normal.osl b/intern/cycles/kernel/shaders/node_convert_from_normal.osl index 32ef430d93b..1add7400a22 100644 --- a/intern/cycles/kernel/shaders/node_convert_from_normal.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_normal.osl @@ -20,6 +20,7 @@ shader node_convert_from_normal( normal Normal = normal(0.0, 0.0, 0.0), + output string String = "", output float Val = 0.0, output int ValInt = 0, output vector Vector = vector(0.0, 0.0, 0.0), diff --git a/intern/cycles/kernel/shaders/node_convert_from_point.osl b/intern/cycles/kernel/shaders/node_convert_from_point.osl index a9435c8abf4..8a315828c55 100644 --- a/intern/cycles/kernel/shaders/node_convert_from_point.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_point.osl @@ -20,6 +20,7 @@ shader node_convert_from_point( point Point = point(0.0, 0.0, 0.0), + output string String = "", output float Val = 0.0, output int ValInt = 0, output vector Vector = vector(0.0, 0.0, 0.0), diff --git a/intern/cycles/kernel/shaders/node_convert_from_string.osl b/intern/cycles/kernel/shaders/node_convert_from_string.osl new file mode 100644 index 00000000000..f40535ac7a3 --- /dev/null +++ b/intern/cycles/kernel/shaders/node_convert_from_string.osl @@ -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. + */ + +#include "stdosl.h" + +shader node_convert_from_string( + string String = "", + output color Color = color(0.0, 0.0, 0.0), + output float Val = 0.0, + output int ValInt = 0, + output vector Vector = vector(0.0, 0.0, 0.0), + output point Point = point(0.0, 0.0, 0.0), + output normal Normal = normal(0.0, 0.0, 0.0)) +{ +} + diff --git a/intern/cycles/kernel/shaders/node_convert_from_vector.osl b/intern/cycles/kernel/shaders/node_convert_from_vector.osl index 4516f92c753..ae9f97414d5 100644 --- a/intern/cycles/kernel/shaders/node_convert_from_vector.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_vector.osl @@ -20,6 +20,7 @@ shader node_convert_from_vector( vector Vector = vector(0.0, 0.0, 0.0), + output string String = "", output float Val = 0.0, output int ValInt = 0, output color Color = color(0.0, 0.0, 0.0), diff --git a/intern/cycles/kernel/shaders/node_environment_texture.osl b/intern/cycles/kernel/shaders/node_environment_texture.osl index bad62e56ab4..7da336a53f0 100644 --- a/intern/cycles/kernel/shaders/node_environment_texture.osl +++ b/intern/cycles/kernel/shaders/node_environment_texture.osl @@ -19,14 +19,52 @@ #include "stdosl.h" #include "node_color.h" +vector environment_texture_direction_to_equirectangular(vector dir) +{ + float u = -atan2(dir[1], dir[0]) / (2.0 * M_PI) + 0.5; + float v = atan2(dir[2], hypot(dir[0], dir[1])) / M_PI + 0.5; + + return vector(u, v, 0.0); +} + +vector environment_texture_direction_to_mirrorball(vector dir) +{ + dir[1] -= 1.0; + + float div = 2.0 * sqrt(max(-0.5 * dir[1], 0.0)); + if (div > 0.0) + dir /= div; + + float u = 0.5 * (dir[0] + 1.0); + float v = 0.5 * (dir[2] + 1.0); + + return vector(u, v, 0.0); +} + shader node_environment_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), vector Vector = P, string filename = "", + string projection = "Equirectangular", string color_space = "sRGB", output color Color = color(0.0, 0.0, 0.0), output float Alpha = 1.0) { - Color = (color)environment(filename, Vector, "alpha", Alpha); + vector p = Vector; + + if (use_mapping) + p = transform(mapping, p); + + p = normalize(p); + + if (projection == "Equirectangular") + p = environment_texture_direction_to_equirectangular(p); + else + p = environment_texture_direction_to_mirrorball(p); + + /* todo: use environment for better texture filtering of equirectangular */ + Color = (color)texture(filename, p[0], 1.0 - p[1], "wrap", "periodic", "alpha", Alpha); if (color_space == "sRGB") Color = color_srgb_to_scene_linear(Color); diff --git a/intern/cycles/kernel/shaders/node_geometry.osl b/intern/cycles/kernel/shaders/node_geometry.osl index 953c5d1fa2b..d1c11b70081 100644 --- a/intern/cycles/kernel/shaders/node_geometry.osl +++ b/intern/cycles/kernel/shaders/node_geometry.osl @@ -47,26 +47,22 @@ shader node_geometry( } /* first try to get tangent attribute */ - vector T; + point generated; - if (getattribute("geom:tangent", T)) { - /* ensure orthogonal and normalized (interpolation breaks it) */ + /* try to create spherical tangent from generated coordinates */ + if (getattribute("geom:generated", generated)) { + matrix project = matrix(0.0, 1.0, 0.0, 0.0, + -1.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.5, -0.5, 0.0, 1.0); + + vector T = transform(project, generated); T = transform("object", "world", T); Tangent = cross(Normal, normalize(cross(T, Normal))); } else { - point generated; - - /* try to create spherical tangent from generated coordinates */ - if (getattribute("geom:generated", generated)) { - T = vector(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0); - T = transform("object", "world", T); - Tangent = cross(Normal, normalize(cross(T, Normal))); - } - else { - /* otherwise use surface derivatives */ - Tangent = normalize(dPdu); - } + /* otherwise use surface derivatives */ + Tangent = normalize(dPdu); } } diff --git a/intern/cycles/kernel/shaders/node_gradient_texture.osl b/intern/cycles/kernel/shaders/node_gradient_texture.osl index ae7cfa51f59..8d862dbad67 100644 --- a/intern/cycles/kernel/shaders/node_gradient_texture.osl +++ b/intern/cycles/kernel/shaders/node_gradient_texture.osl @@ -63,12 +63,19 @@ float gradient(point p, string type) } shader node_gradient_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), string Type = "Linear", point Vector = P, output float Fac = 0.0, output color Color = color(0.0, 0.0, 0.0)) { - Fac = gradient(Vector, Type); + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + + Fac = gradient(p, Type); Color = color(Fac, Fac, Fac); } diff --git a/intern/cycles/kernel/shaders/node_hsv.osl b/intern/cycles/kernel/shaders/node_hsv.osl index 8fd7a1612e8..0f4bedfb0f8 100644 --- a/intern/cycles/kernel/shaders/node_hsv.osl +++ b/intern/cycles/kernel/shaders/node_hsv.osl @@ -27,7 +27,6 @@ shader node_hsv( color ColorIn = color(0.0, 0.0, 0.0), output color ColorOut = color(0.0, 0.0, 0.0)) { - float t = clamp(Fac, 0.0, 1.0); color Color = rgb_to_hsv(ColorIn); // remember: fmod doesn't work for negative numbers @@ -38,6 +37,6 @@ shader node_hsv( Color = hsv_to_rgb(Color); - ColorOut = mix(Color, ColorIn, t); + ColorOut = mix(ColorIn, Color, Fac); } diff --git a/intern/cycles/kernel/shaders/node_image_texture.osl b/intern/cycles/kernel/shaders/node_image_texture.osl index 6393605e6b5..99074672a6a 100644 --- a/intern/cycles/kernel/shaders/node_image_texture.osl +++ b/intern/cycles/kernel/shaders/node_image_texture.osl @@ -30,6 +30,8 @@ color image_texture_lookup(string filename, string color_space, float u, float v } shader node_image_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), point Vector = P, string filename = "", string color_space = "sRGB", @@ -38,8 +40,13 @@ shader node_image_texture( output color Color = color(0.0, 0.0, 0.0), output float Alpha = 1.0) { + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + if (projection == "Flat") { - Color = image_texture_lookup(filename, color_space, Vector[0], Vector[1], Alpha); + Color = image_texture_lookup(filename, color_space, p[0], p[1], Alpha); } else if (projection == "Box") { /* object space normal */ @@ -61,26 +68,26 @@ shader node_image_texture( vector weight = vector(0.0, 0.0, 0.0); float blend = projection_blend; - float limit = 0.5*(1.0 + blend); + float limit = 0.5 * (1.0 + blend); /* first test for corners with single texture */ - if (Nob[0] > limit*(Nob[0] + Nob[1]) && Nob[0] > limit*(Nob[0] + Nob[2])) { + if (Nob[0] > limit * (Nob[0] + Nob[1]) && Nob[0] > limit * (Nob[0] + Nob[2])) { weight[0] = 1.0; } - else if (Nob[1] > limit*(Nob[0] + Nob[1]) && Nob[1] > limit*(Nob[1] + Nob[2])) { + else if (Nob[1] > limit * (Nob[0] + Nob[1]) && Nob[1] > limit * (Nob[1] + Nob[2])) { weight[1] = 1.0; } - else if (Nob[2] > limit*(Nob[0] + Nob[2]) && Nob[2] > limit*(Nob[1] + Nob[2])) { + else if (Nob[2] > limit * (Nob[0] + Nob[2]) && Nob[2] > limit * (Nob[1] + Nob[2])) { weight[2] = 1.0; } else if (blend > 0.0) { /* in case of blending, test for mixes between two textures */ - if (Nob[2] < (1.0 - limit)*(Nob[1] + Nob[0])) { + if (Nob[2] < (1.0 - limit) * (Nob[1] + Nob[0])) { weight[0] = Nob[0] / (Nob[0] + Nob[1]); weight[0] = clamp((weight[0] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); weight[1] = 1.0 - weight[0]; } - else if (Nob[0] < (1.0 - limit)*(Nob[1] + Nob[2])) { + else if (Nob[0] < (1.0 - limit) * (Nob[1] + Nob[2])) { weight[1] = Nob[1] / (Nob[1] + Nob[2]); weight[1] = clamp((weight[1] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); weight[2] = 1.0 - weight[1]; @@ -104,16 +111,16 @@ shader node_image_texture( float tmp_alpha; if (weight[0] > 0.0) { - Color += weight[0]*image_texture_lookup(filename, color_space, Vector[1], Vector[2], tmp_alpha); - Alpha += weight[0]*tmp_alpha; + Color += weight[0] * image_texture_lookup(filename, color_space, p[1], p[2], tmp_alpha); + Alpha += weight[0] * tmp_alpha; } if (weight[1] > 0.0) { - Color += weight[1]*image_texture_lookup(filename, color_space, Vector[0], Vector[2], tmp_alpha); - Alpha += weight[1]*tmp_alpha; + Color += weight[1] * image_texture_lookup(filename, color_space, p[0], p[2], tmp_alpha); + Alpha += weight[1] * tmp_alpha; } if (weight[2] > 0.0) { - Color += weight[2]*image_texture_lookup(filename, color_space, Vector[1], Vector[0], tmp_alpha); - Alpha += weight[2]*tmp_alpha; + Color += weight[2] * image_texture_lookup(filename, color_space, p[1], p[0], tmp_alpha); + Alpha += weight[2] * tmp_alpha; } } } diff --git a/intern/cycles/kernel/shaders/node_light_falloff.osl b/intern/cycles/kernel/shaders/node_light_falloff.osl index 7ffa6fe0ffb..a9d41604361 100644 --- a/intern/cycles/kernel/shaders/node_light_falloff.osl +++ b/intern/cycles/kernel/shaders/node_light_falloff.osl @@ -30,7 +30,7 @@ shader node_light_falloff( getattribute("path:ray_length", ray_length); if (Smooth > 0.0) { - float squared = ray_length*ray_length; + float squared = ray_length * ray_length; strength *= squared / (Smooth + squared); } @@ -38,9 +38,9 @@ shader node_light_falloff( Quadratic = strength; /* Linear */ - Linear = (strength*ray_length); + Linear = (strength * ray_length); /* Constant */ - Constant = (strength*ray_length*ray_length); + Constant = (strength * ray_length * ray_length); } diff --git a/intern/cycles/kernel/shaders/node_magic_texture.osl b/intern/cycles/kernel/shaders/node_magic_texture.osl index e464b83bc9e..b81a30499b2 100644 --- a/intern/cycles/kernel/shaders/node_magic_texture.osl +++ b/intern/cycles/kernel/shaders/node_magic_texture.osl @@ -93,12 +93,19 @@ color magic(point p, int n, float distortion) } shader node_magic_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), int Depth = 2, float Distortion = 5.0, float Scale = 5.0, point Vector = P, output color Color = color(0.0, 0.0, 0.0)) { - Color = magic(Vector * Scale, Depth, Distortion); + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + + Color = magic(p * Scale, Depth, Distortion); } diff --git a/intern/cycles/kernel/shaders/node_mapping.osl b/intern/cycles/kernel/shaders/node_mapping.osl index 2e720edfc7e..92df043b39d 100644 --- a/intern/cycles/kernel/shaders/node_mapping.osl +++ b/intern/cycles/kernel/shaders/node_mapping.osl @@ -20,9 +20,17 @@ shader node_mapping( matrix Matrix = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + point mapping_min = point(0.0, 0.0, 0.0), + point mapping_max = point(0.0, 0.0, 0.0), + int use_minmax = 0, point VectorIn = point(0.0, 0.0, 0.0), output point VectorOut = point(0.0, 0.0, 0.0)) { - VectorOut = transform(Matrix, VectorIn); + point p = transform(Matrix, VectorIn); + + if(use_minmax) + p = min(max(mapping_min, p), mapping_max); + + VectorOut = p; } diff --git a/intern/cycles/kernel/shaders/node_mix.osl b/intern/cycles/kernel/shaders/node_mix.osl index 69e68e5ed15..b2af36230f8 100644 --- a/intern/cycles/kernel/shaders/node_mix.osl +++ b/intern/cycles/kernel/shaders/node_mix.osl @@ -272,7 +272,7 @@ color node_mix_clamp(color col) color outcol = col; outcol[0] = clamp(col[0], 0.0, 1.0); - outcol[1] = clamp(col[2], 0.0, 1.0); + outcol[1] = clamp(col[1], 0.0, 1.0); outcol[2] = clamp(col[2], 0.0, 1.0); return outcol; diff --git a/intern/cycles/kernel/shaders/node_musgrave_texture.osl b/intern/cycles/kernel/shaders/node_musgrave_texture.osl index 71461b8fd79..afdbca27a3f 100644 --- a/intern/cycles/kernel/shaders/node_musgrave_texture.osl +++ b/intern/cycles/kernel/shaders/node_musgrave_texture.osl @@ -187,6 +187,8 @@ float noise_musgrave_ridged_multi_fractal(point p, string basis, float H, /* Shader */ shader node_musgrave_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), string Type = "fBM", float Dimension = 2.0, float Lacunarity = 1.0, @@ -204,7 +206,12 @@ shader node_musgrave_texture( string Basis = "Perlin"; float intensity = 1.0; - point p = Vector * Scale; + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + + p = p * Scale; if (Type == "Multifractal") Fac = intensity * noise_musgrave_multi_fractal(p, Basis, dimension, lacunarity, octaves); diff --git a/intern/cycles/kernel/shaders/node_noise_texture.osl b/intern/cycles/kernel/shaders/node_noise_texture.osl index 227b2bf8cea..0a379491781 100644 --- a/intern/cycles/kernel/shaders/node_noise_texture.osl +++ b/intern/cycles/kernel/shaders/node_noise_texture.osl @@ -43,6 +43,8 @@ float noise(point p, string basis, float distortion, float detail, float fac, co } shader node_noise_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), float Distortion = 0.0, float Scale = 5.0, float Detail = 2.0, @@ -50,7 +52,12 @@ shader node_noise_texture( output float Fac = 0.0, output color Color = color(0.2, 0.2, 0.2)) { + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + string Basis = "Perlin"; - Fac = noise(Vector * Scale, Basis, Distortion, Detail, Fac, Color); + Fac = noise(p * Scale, Basis, Distortion, Detail, Fac, Color); } diff --git a/intern/cycles/kernel/shaders/node_normal_map.osl b/intern/cycles/kernel/shaders/node_normal_map.osl new file mode 100644 index 00000000000..dc25eb8539f --- /dev/null +++ b/intern/cycles/kernel/shaders/node_normal_map.osl @@ -0,0 +1,52 @@ +/* + * 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_normal_map( + normal NormalIn = N, + float Strength = 1.0, + color Color = color(0.5, 0.5, 1.0), + string space = "Tangent", + string attr_name = "geom:tangent", + string attr_sign_name = "geom:tangent_sign", + output normal Normal = NormalIn) +{ + color mcolor = 2.0 * color(Color[0] - 0.5, Color[1] - 0.5, Color[2] - 0.5); + + if (space == "Tangent") { + vector tangent; + float tangent_sign; + + getattribute(attr_name, tangent); + getattribute(attr_sign_name, tangent_sign); + + tangent = transform("object", "world", tangent); + + vector B = tangent_sign * cross(NormalIn, tangent); + Normal = normalize(mcolor[0] * tangent + mcolor[1] * B + mcolor[2] * NormalIn); + } + else if (space == "Object") + Normal = normalize(transform("object", "world", vector(mcolor))); + else if (space == "World") + Normal = normalize(vector(mcolor)); + + if (Strength != 1.0) + Normal = normalize(NormalIn + (Normal - NormalIn) * max(Strength, 0.0)); +} + diff --git a/intern/cycles/kernel/shaders/node_refraction_bsdf.osl b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl new file mode 100644 index 00000000000..0cf9d460c6e --- /dev/null +++ b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl @@ -0,0 +1,39 @@ +/* + * 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_refraction_bsdf( + color Color = color(0.8, 0.8, 0.8), + string distribution = "Sharp", + float Roughness = 0.2, + float IOR = 1.45, + normal Normal = N, + output closure color BSDF = diffuse(Normal)) +{ + float f = max(IOR, 1.0 + 1e-5); + float eta = backfacing() ? 1.0 / f: f; + + if (distribution == "Sharp") + BSDF = Color * refraction(Normal, eta); + else if (distribution == "Beckmann") + BSDF = Color * microfacet_beckmann_refraction(Normal, Roughness, eta); + else if (distribution == "GGX") + BSDF = Color * microfacet_ggx_refraction(Normal, Roughness, eta); +} + diff --git a/intern/cycles/kernel/shaders/node_rgb_ramp.osl b/intern/cycles/kernel/shaders/node_rgb_ramp.osl index a128ebbd1cf..0df11bb38de 100644 --- a/intern/cycles/kernel/shaders/node_rgb_ramp.osl +++ b/intern/cycles/kernel/shaders/node_rgb_ramp.osl @@ -29,7 +29,10 @@ shader node_rgb_ramp( { float f = clamp(Fac, 0.0, 1.0) * (RAMP_TABLE_SIZE - 1); + /* clamp int as well in case of NaN */ int i = (int)f; + if (i < 0) i = 0; + if (i >= RAMP_TABLE_SIZE) i = RAMP_TABLE_SIZE - 1; float t = f - (float)i; Color = ramp_color[i]; diff --git a/intern/cycles/kernel/shaders/node_sky_texture.osl b/intern/cycles/kernel/shaders/node_sky_texture.osl index 932fb1e2f17..24a63c78458 100644 --- a/intern/cycles/kernel/shaders/node_sky_texture.osl +++ b/intern/cycles/kernel/shaders/node_sky_texture.osl @@ -43,9 +43,9 @@ color xyY_to_xyz(float x, float y, float Y) color xyz_to_rgb(float x, float y, float z) { - return color(3.240479 * x + -1.537150 * y + -0.498535 * z, - -0.969256 * x + 1.875991 * y + 0.041556 * z, - 0.055648 * x + -0.204043 * y + 1.057311 * z); + return color( 3.240479 * x + -1.537150 * y + -0.498535 * z, + -0.969256 * x + 1.875991 * y + 0.041556 * z, + 0.055648 * x + -0.204043 * y + 1.057311 * z); } float sky_angle_between(float thetav, float phiv, float theta, float phi) @@ -149,14 +149,21 @@ void precompute_sunsky(vector dir, float turbidity, output KernelSunSky sunsky) } shader node_sky_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), vector Vector = P, vector sun_direction = vector(0, 0, 1), float turbidity = 2.2, output color Color = color(0.0, 0.0, 0.0)) { + vector p = Vector; + + if (use_mapping) + p = transform(mapping, p); + KernelSunSky sunsky; precompute_sunsky(sun_direction, turbidity, sunsky); - Color = sky_xyz_radiance(sunsky, Vector); + Color = sky_xyz_radiance(sunsky, p); } diff --git a/intern/cycles/kernel/shaders/node_tangent.osl b/intern/cycles/kernel/shaders/node_tangent.osl new file mode 100644 index 00000000000..731af89231a --- /dev/null +++ b/intern/cycles/kernel/shaders/node_tangent.osl @@ -0,0 +1,50 @@ +/* + * 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_tangent( + normal NormalIn = N, + string attr_name = "geom:tangent", + string direction_type = "Radial", + string axis = "Z", + output normal Tangent = normalize(dPdu)) +{ + vector T; + + if (direction_type == "UV Map") { + getattribute(attr_name, T); + } + else if (direction_type == "Radial") { + point generated; + + if (!getattribute("geom:generated", generated)) + generated = P; + + if (axis == "X") + T = vector(0.0, -(generated[2] - 0.5), (generated[1] - 0.5)); + else if (axis == "Y") + T = vector(-(generated[2] - 0.5), 0.0, (generated[0] - 0.5)); + else + T = vector(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0); + } + + T = transform("object", "world", T); + Tangent = cross(NormalIn, normalize(cross(T, NormalIn))); +} + diff --git a/intern/cycles/kernel/shaders/node_texture_coordinate.osl b/intern/cycles/kernel/shaders/node_texture_coordinate.osl index 791838dfffe..37460bcfc98 100644 --- a/intern/cycles/kernel/shaders/node_texture_coordinate.osl +++ b/intern/cycles/kernel/shaders/node_texture_coordinate.osl @@ -56,7 +56,7 @@ shader node_texture_coordinate( Camera = transform("camera", P); Window = transform("NDC", P); Normal = transform("world", "object", NormalIn); - Reflection = reflect(I, NormalIn); + Reflection = -reflect(I, NormalIn); } if (bump_offset == "dx") { @@ -77,5 +77,7 @@ shader node_texture_coordinate( Camera += Dy(Camera); Window += Dy(Window); } + + Window[2] = 0.0; } diff --git a/intern/cycles/kernel/shaders/node_voronoi_texture.osl b/intern/cycles/kernel/shaders/node_voronoi_texture.osl index a44df00a267..43f8ecc666a 100644 --- a/intern/cycles/kernel/shaders/node_voronoi_texture.osl +++ b/intern/cycles/kernel/shaders/node_voronoi_texture.osl @@ -22,17 +22,24 @@ /* Voronoi */ shader node_voronoi_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), string Coloring = "Intensity", float Scale = 5.0, point Vector = P, output float Fac = 0.0, output color Color = color(0.0, 0.0, 0.0)) { + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + /* compute distance and point coordinate of 4 nearest neighbours */ float da[4]; point pa[4]; - voronoi(Vector * Scale, "Distance Squared", 1.0, da, pa); + voronoi(p * Scale, "Distance Squared", 1.0, da, pa); /* Colored output */ if (Coloring == "Intensity") { diff --git a/intern/cycles/kernel/shaders/node_ward_bsdf.osl b/intern/cycles/kernel/shaders/node_ward_bsdf.osl index 03a0477038e..82ce15ab9b6 100644 --- a/intern/cycles/kernel/shaders/node_ward_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_ward_bsdf.osl @@ -30,20 +30,20 @@ shader node_ward_bsdf( /* rotate tangent around normal */ vector T = Tangent; - if(Rotation != 0.0) + if (Rotation != 0.0) T = rotate(T, Rotation*2.0*M_PI, point(0.0, 0.0, 0.0), Normal); /* compute roughness */ float RoughnessU, RoughnessV; float aniso = clamp(Anisotropy, -0.99, 0.99); - if(aniso < 0.0) { - RoughnessU = Roughness*(1.0 + aniso); - RoughnessV = Roughness/(1.0 + aniso); + if (aniso < 0.0) { + RoughnessU = Roughness / (1.0 + aniso); + RoughnessV = Roughness * (1.0 + aniso); } else { - RoughnessU = Roughness/(1.0 - aniso); - RoughnessV = Roughness*(1.0 - aniso); + RoughnessU = Roughness * (1.0 - aniso); + RoughnessV = Roughness / (1.0 - aniso); } BSDF = Color * ward(Normal, T, RoughnessU, RoughnessV); diff --git a/intern/cycles/kernel/shaders/node_wave_texture.osl b/intern/cycles/kernel/shaders/node_wave_texture.osl index 79b8a8885d1..6648cd06278 100644 --- a/intern/cycles/kernel/shaders/node_wave_texture.osl +++ b/intern/cycles/kernel/shaders/node_wave_texture.osl @@ -46,6 +46,8 @@ float wave(point p, float scale, string type, float detail, float distortion, fl } shader node_wave_texture( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), string Type = "Bands", float Scale = 5.0, float Distortion = 0.0, @@ -55,7 +57,12 @@ shader node_wave_texture( output float Fac = 0.0, output color Color = color (0.0, 0.0, 0.0)) { - Fac = wave(Vector, Scale, Type, Detail, Distortion, DetailScale); + point p = Vector; + + if (use_mapping) + p = transform(mapping, p); + + Fac = wave(p, Scale, Type, Detail, Distortion, DetailScale); Color = color(Fac, Fac, Fac); } diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h index 4237291c7a4..24c3a50e6f6 100644 --- a/intern/cycles/kernel/shaders/stdosl.h +++ b/intern/cycles/kernel/shaders/stdosl.h @@ -433,6 +433,7 @@ string concat (string a, string b, string c, string d, string e, string f) { closure color diffuse(normal N) BUILTIN; closure color oren_nayar(normal N, float sigma) BUILTIN; +closure color phong_ramp(normal N, float exponent, color colors[8]) BUILTIN; closure color translucent(normal N) BUILTIN; closure color reflection(normal N) BUILTIN; closure color refraction(normal N, float eta) BUILTIN; @@ -446,6 +447,7 @@ closure color ashikhmin_velvet(normal N, float sigma) BUILTIN; closure color emission() BUILTIN; closure color background() BUILTIN; closure color holdout() BUILTIN; +closure color ambient_occlusion() BUILTIN; // Renderer state int raytype (string typename) BUILTIN; diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 698ef5016f0..9c79886fdca 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -215,6 +215,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT case NODE_CLOSURE_HOLDOUT: svm_node_closure_holdout(sd, stack, node); break; + case NODE_CLOSURE_AMBIENT_OCCLUSION: + svm_node_closure_ambient_occlusion(sd, stack, node); + break; case NODE_CLOSURE_VOLUME: svm_node_closure_volume(kg, sd, stack, node, path_flag); break; @@ -398,6 +401,16 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT case NODE_LIGHT_FALLOFF: svm_node_light_falloff(sd, stack, node); break; +#endif +#ifdef __ANISOTROPIC__ + case NODE_TANGENT: + svm_node_tangent(kg, sd, stack, node); + break; +#endif +#ifdef __NORMAL_MAP__ + case NODE_NORMAL_MAP: + svm_node_normal_map(kg, sd, stack, node); + break; #endif case NODE_END: default: diff --git a/intern/cycles/kernel/svm/svm_brick.h b/intern/cycles/kernel/svm/svm_brick.h index 7e38ac84bf1..49466c07a97 100644 --- a/intern/cycles/kernel/svm/svm_brick.h +++ b/intern/cycles/kernel/svm/svm_brick.h @@ -28,9 +28,9 @@ __device_noinline float brick_noise(int n) /* fast integer noise */ return 0.5f * ((float)nn / 1073741824.0f); } -__device_noinline float svm_brick(float3 p, float scale, float mortar_size, float bias, +__device_noinline float2 svm_brick(float3 p, float scale, float mortar_size, float bias, float brick_width, float row_height, float offset_amount, int offset_frequency, - float squash_amount, int squash_frequency, float *tint) + float squash_amount, int squash_frequency) { p *= scale; @@ -50,11 +50,12 @@ __device_noinline float svm_brick(float3 p, float scale, float mortar_size, floa x = (p.x+offset) - brick_width*bricknum; y = p.y - row_height*rownum; - *tint = clamp((brick_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0f, 1.0f); + return make_float2( + clamp((brick_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0f, 1.0f), - return (x < mortar_size || y < mortar_size || + (x < mortar_size || y < mortar_size || x > (brick_width - mortar_size) || - y > (row_height - mortar_size)) ? 1.0f : 0.0f; + y > (row_height - mortar_size)) ? 1.0f : 0.0f); } __device void svm_node_tex_brick(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset) @@ -70,8 +71,6 @@ __device void svm_node_tex_brick(KernelGlobals *kg, ShaderData *sd, float *stack /* RNA properties */ uint offset_frequency, squash_frequency; - float tint = 0.0f; - decode_node_uchar4(node.y, &co_offset, &color1_offset, &color2_offset, &mortar_offset); decode_node_uchar4(node.z, &scale_offset, &mortar_size_offset, &bias_offset, &brick_width_offset); decode_node_uchar4(node.w, &row_height_offset, &color_offset, &fac_offset, NULL); @@ -92,9 +91,11 @@ __device void svm_node_tex_brick(KernelGlobals *kg, ShaderData *sd, float *stack float offset_amount = __int_as_float(node3.z); float squash_amount = __int_as_float(node3.w); - float f = svm_brick(co, scale, mortar_size, bias, brick_width, row_height, - offset_amount, offset_frequency, squash_amount, squash_frequency, - &tint); + float2 f2 = svm_brick(co, scale, mortar_size, bias, brick_width, row_height, + offset_amount, offset_frequency, squash_amount, squash_frequency); + + float tint = f2.x; + float f = f2.y; if(f != 1.0f) { float facm = 1.0f - tint; diff --git a/intern/cycles/kernel/svm/svm_bsdf.h b/intern/cycles/kernel/svm/svm_bsdf.h index 07c20231d54..07927fe5691 100644 --- a/intern/cycles/kernel/svm/svm_bsdf.h +++ b/intern/cycles/kernel/svm/svm_bsdf.h @@ -19,11 +19,12 @@ #include "../closure/bsdf_ashikhmin_velvet.h" #include "../closure/bsdf_diffuse.h" #include "../closure/bsdf_oren_nayar.h" +#include "../closure/bsdf_phong_ramp.h" #include "../closure/bsdf_microfacet.h" #include "../closure/bsdf_reflection.h" #include "../closure/bsdf_refraction.h" #include "../closure/bsdf_transparent.h" -#ifdef __DPDU__ +#ifdef __ANISOTROPIC__ #include "../closure/bsdf_ward.h" #endif #include "../closure/bsdf_westin.h" @@ -44,6 +45,10 @@ __device int svm_bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, floa label = bsdf_oren_nayar_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; + /*case CLOSURE_BSDF_PHONG_RAMP_ID: + label = bsdf_phong_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break;*/ case CLOSURE_BSDF_TRANSLUCENT_ID: label = bsdf_translucent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); @@ -70,7 +75,7 @@ __device int svm_bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, floa label = bsdf_microfacet_beckmann_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; -#ifdef __DPDU__ +#ifdef __ANISOTROPIC__ case CLOSURE_BSDF_WARD_ID: label = bsdf_ward_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); @@ -110,6 +115,9 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con case CLOSURE_BSDF_OREN_NAYAR_ID: eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf); break; + /*case CLOSURE_BSDF_PHONG_RAMP_ID: + eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf); + break;*/ case CLOSURE_BSDF_TRANSLUCENT_ID: eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf); break; @@ -130,7 +138,7 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf); break; -#ifdef __DPDU__ +#ifdef __ANISOTROPIC__ case CLOSURE_BSDF_WARD_ID: eval = bsdf_ward_eval_reflect(sc, sd->I, omega_in, pdf); break; @@ -179,7 +187,7 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf); break; -#ifdef __DPDU__ +#ifdef __ANISOTROPIC__ case CLOSURE_BSDF_WARD_ID: eval = bsdf_ward_eval_transmit(sc, sd->I, omega_in, pdf); break; @@ -213,6 +221,9 @@ __device void svm_bsdf_blur(ShaderClosure *sc, float roughness) case CLOSURE_BSDF_OREN_NAYAR_ID: bsdf_oren_nayar_blur(sc, roughness); break; + /*case CLOSURE_BSDF_PHONG_RAMP_ID: + bsdf_phong_ramp_blur(sc, roughness); + break;*/ case CLOSURE_BSDF_TRANSLUCENT_ID: bsdf_translucent_blur(sc, roughness); break; @@ -233,7 +244,7 @@ __device void svm_bsdf_blur(ShaderClosure *sc, float roughness) case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: bsdf_microfacet_beckmann_blur(sc, roughness); break; -#ifdef __DPDU__ +#ifdef __ANISOTROPIC__ case CLOSURE_BSDF_WARD_ID: bsdf_ward_blur(sc, roughness); break; diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index 11ce3b7c5d1..b5bd2b42cb4 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -20,9 +20,9 @@ CCL_NAMESPACE_BEGIN /* Closure Nodes */ -__device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract) +__device void svm_node_glass_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract) { - if(type == CLOSURE_BSDF_REFRACTION_ID) { + if(type == CLOSURE_BSDF_SHARP_GLASS_ID) { if(refract) { sc->data0 = eta; sd->flag |= bsdf_refraction_setup(sc); @@ -30,7 +30,7 @@ __device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type, else sd->flag |= bsdf_reflection_setup(sc); } - else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) { + else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID) { sc->data0 = roughness; sc->data1 = eta; @@ -50,25 +50,41 @@ __device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type, } } -__device_inline ShaderClosure *svm_node_closure_get(ShaderData *sd) +__device_inline ShaderClosure *svm_node_closure_get_non_bsdf(ShaderData *sd, ClosureType type, float mix_weight) { #ifdef __MULTI_CLOSURE__ ShaderClosure *sc = &sd->closure[sd->num_closure]; - if(sd->num_closure < MAX_CLOSURE) + if(sd->num_closure < MAX_CLOSURE) { + sc->weight *= mix_weight; + sc->type = type; sd->num_closure++; + return sc; + } - return sc; + return NULL; #else return &sd->closure; #endif } -__device_inline void svm_node_closure_set_mix_weight(ShaderClosure *sc, float mix_weight) +__device_inline ShaderClosure *svm_node_closure_get_bsdf(ShaderData *sd, float mix_weight) { #ifdef __MULTI_CLOSURE__ - sc->weight *= mix_weight; - sc->sample_weight = fabsf(average(sc->weight)); + 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 < MAX_CLOSURE) { + sc->weight = weight; + sc->sample_weight = sample_weight; + sd->num_closure++; + return sc; + } + + return NULL; +#else + return &sd->closure; #endif } @@ -101,33 +117,39 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st switch(type) { case CLOSURE_BSDF_DIFFUSE_ID: { - ShaderClosure *sc = svm_node_closure_get(sd); - sc->N = N; - svm_node_closure_set_mix_weight(sc, mix_weight); + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); - float roughness = param1; + if(sc) { + sc->N = N; - if(roughness == 0.0f) { - sd->flag |= bsdf_diffuse_setup(sc); - } - else { - sc->data0 = roughness; - sd->flag |= bsdf_oren_nayar_setup(sc); + float roughness = param1; + + if(roughness == 0.0f) { + sd->flag |= bsdf_diffuse_setup(sc); + } + else { + sc->data0 = roughness; + sd->flag |= bsdf_oren_nayar_setup(sc); + } } break; } case CLOSURE_BSDF_TRANSLUCENT_ID: { - ShaderClosure *sc = svm_node_closure_get(sd); - sc->N = N; - svm_node_closure_set_mix_weight(sc, mix_weight); - sd->flag |= bsdf_translucent_setup(sc); + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); + + if(sc) { + sc->N = N; + sd->flag |= bsdf_translucent_setup(sc); + } break; } case CLOSURE_BSDF_TRANSPARENT_ID: { - ShaderClosure *sc = svm_node_closure_get(sd); - sc->N = N; - svm_node_closure_set_mix_weight(sc, mix_weight); - sd->flag |= bsdf_transparent_setup(sc); + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); + + if(sc) { + sc->N = N; + sd->flag |= bsdf_transparent_setup(sc); + } break; } case CLOSURE_BSDF_REFLECTION_ID: @@ -137,18 +159,20 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) break; #endif - ShaderClosure *sc = svm_node_closure_get(sd); - sc->N = N; - sc->data0 = param1; - svm_node_closure_set_mix_weight(sc, mix_weight); + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); - /* setup bsdf */ - if(type == CLOSURE_BSDF_REFLECTION_ID) - sd->flag |= bsdf_reflection_setup(sc); - else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID) - sd->flag |= bsdf_microfacet_beckmann_setup(sc); - else - sd->flag |= bsdf_microfacet_ggx_setup(sc); + if(sc) { + sc->N = N; + sc->data0 = param1; + + /* setup bsdf */ + if(type == CLOSURE_BSDF_REFLECTION_ID) + sd->flag |= bsdf_reflection_setup(sc); + else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID) + sd->flag |= bsdf_microfacet_beckmann_setup(sc); + else + sd->flag |= bsdf_microfacet_ggx_setup(sc); + } break; } @@ -158,6 +182,33 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st #ifdef __CAUSTICS_TRICKS__ if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) break; +#endif + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); + + if(sc) { + sc->N = N; + sc->data0 = param1; + + float eta = fmaxf(param2, 1.0f + 1e-5f); + sc->data1 = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta; + + /* setup bsdf */ + if(type == CLOSURE_BSDF_REFRACTION_ID) + sd->flag |= bsdf_refraction_setup(sc); + else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) + sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc); + else + sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc); + } + + break; + } + case CLOSURE_BSDF_SHARP_GLASS_ID: + case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID: + case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: { +#ifdef __CAUSTICS_TRICKS__ + if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) + break; #endif /* index of refraction */ float eta = fmaxf(param2, 1.0f + 1e-5f); @@ -170,78 +221,89 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st #ifdef __MULTI_CLOSURE__ /* reflection */ - ShaderClosure *sc = svm_node_closure_get(sd); - sc->N = N; - + ShaderClosure *sc = &sd->closure[sd->num_closure]; float3 weight = sc->weight; float sample_weight = sc->sample_weight; - svm_node_closure_set_mix_weight(sc, mix_weight*fresnel); - svm_node_glossy_setup(sd, sc, type, eta, roughness, false); + sc = svm_node_closure_get_bsdf(sd, mix_weight*fresnel); + + if(sc) { + sc->N = N; + svm_node_glass_setup(sd, sc, type, eta, roughness, false); + } /* refraction */ - sc = svm_node_closure_get(sd); - sc->N = N; - + sc = &sd->closure[sd->num_closure]; sc->weight = weight; sc->sample_weight = sample_weight; - svm_node_closure_set_mix_weight(sc, mix_weight*(1.0f - fresnel)); - svm_node_glossy_setup(sd, sc, type, eta, roughness, true); + sc = svm_node_closure_get_bsdf(sd, mix_weight*(1.0f - fresnel)); + + if(sc) { + sc->N = N; + svm_node_glass_setup(sd, sc, type, eta, roughness, true); + } #else - ShaderClosure *sc = svm_node_closure_get(sd); - sc->N = N; + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); - bool refract = (randb > fresnel); - - svm_node_closure_set_mix_weight(sc, mix_weight); - svm_node_glossy_setup(sd, sc, type, eta, roughness, refract); + if(sc) { + sc->N = N; + bool refract = (randb > fresnel); + svm_node_glass_setup(sd, sc, type, eta, roughness, refract); + } #endif break; } -#ifdef __DPDU__ case CLOSURE_BSDF_WARD_ID: { #ifdef __CAUSTICS_TRICKS__ if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) break; #endif - ShaderClosure *sc = svm_node_closure_get(sd); - sc->N = N; - sc->T = stack_load_float3(stack, data_node.z); - svm_node_closure_set_mix_weight(sc, mix_weight); + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); - /* rotate tangent */ - float rotation = stack_load_float(stack, data_node.w); + if(sc) { + sc->N = N; - if(rotation != 0.0f) - sc->T = rotate_around_axis(sc->T, sc->N, rotation * 2.0f * M_PI_F); +#ifdef __ANISOTROPIC__ + sc->T = stack_load_float3(stack, data_node.z); - /* compute roughness */ - float roughness = param1; - float anisotropy = clamp(param2, -0.99f, 0.99f); + /* rotate tangent */ + float rotation = stack_load_float(stack, data_node.w); - if(anisotropy < 0.0f) { - sc->data0 = roughness*(1.0f + anisotropy); - sc->data1 = roughness/(1.0f + anisotropy); + if(rotation != 0.0f) + sc->T = rotate_around_axis(sc->T, sc->N, rotation * 2.0f * M_PI_F); + + /* compute roughness */ + float roughness = param1; + float anisotropy = clamp(param2, -0.99f, 0.99f); + + if(anisotropy < 0.0f) { + sc->data0 = roughness/(1.0f + anisotropy); + sc->data1 = roughness*(1.0f + anisotropy); + } + else { + sc->data0 = roughness*(1.0f - anisotropy); + sc->data1 = roughness/(1.0f - anisotropy); + } + + sd->flag |= bsdf_ward_setup(sc); +#else + sd->flag |= bsdf_diffuse_setup(sc); +#endif } - else { - sc->data0 = roughness/(1.0f - anisotropy); - sc->data1 = roughness*(1.0f - anisotropy); - } - - sd->flag |= bsdf_ward_setup(sc); break; } -#endif case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: { - ShaderClosure *sc = svm_node_closure_get(sd); - sc->N = N; - svm_node_closure_set_mix_weight(sc, mix_weight); + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); - /* sigma */ - sc->data0 = clamp(param1, 0.0f, 1.0f); - sd->flag |= bsdf_ashikhmin_velvet_setup(sc); + if(sc) { + sc->N = N; + + /* sigma */ + sc->data0 = clamp(param1, 0.0f, 1.0f); + sd->flag |= bsdf_ashikhmin_velvet_setup(sc); + } break; } default: @@ -270,19 +332,21 @@ __device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float * switch(type) { case CLOSURE_VOLUME_TRANSPARENT_ID: { - ShaderClosure *sc = svm_node_closure_get(sd); - svm_node_closure_set_mix_weight(sc, mix_weight); + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); - float density = param1; - sd->flag |= volume_transparent_setup(sc, density); + if(sc) { + float density = param1; + sd->flag |= volume_transparent_setup(sc, density); + } break; } case CLOSURE_VOLUME_ISOTROPIC_ID: { - ShaderClosure *sc = svm_node_closure_get(sd); - svm_node_closure_set_mix_weight(sc, mix_weight); + ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); - float density = param1; - sd->flag |= volume_isotropic_setup(sc, density); + if(sc) { + float density = param1; + sd->flag |= volume_isotropic_setup(sc, density); + } break; } default: @@ -301,15 +365,10 @@ __device void svm_node_closure_emission(ShaderData *sd, float *stack, uint4 node if(mix_weight == 0.0f) return; - ShaderClosure *sc = svm_node_closure_get(sd); - sc->weight *= mix_weight; - sc->type = CLOSURE_EMISSION_ID; + svm_node_closure_get_non_bsdf(sd, CLOSURE_EMISSION_ID, mix_weight); } - else { - ShaderClosure *sc = svm_node_closure_get(sd); - sc->type = CLOSURE_EMISSION_ID; - } - + else + svm_node_closure_get_non_bsdf(sd, CLOSURE_EMISSION_ID, 1.0f); #else ShaderClosure *sc = &sd->closure; sc->type = CLOSURE_EMISSION_ID; @@ -329,15 +388,10 @@ __device void svm_node_closure_background(ShaderData *sd, float *stack, uint4 no if(mix_weight == 0.0f) return; - ShaderClosure *sc = svm_node_closure_get(sd); - sc->weight *= mix_weight; - sc->type = CLOSURE_BACKGROUND_ID; + svm_node_closure_get_non_bsdf(sd, CLOSURE_BACKGROUND_ID, mix_weight); } - else { - ShaderClosure *sc = svm_node_closure_get(sd); - sc->type = CLOSURE_BACKGROUND_ID; - } - + else + svm_node_closure_get_non_bsdf(sd, CLOSURE_BACKGROUND_ID, 1.0f); #else ShaderClosure *sc = &sd->closure; sc->type = CLOSURE_BACKGROUND_ID; @@ -355,15 +409,10 @@ __device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node) if(mix_weight == 0.0f) return; - ShaderClosure *sc = svm_node_closure_get(sd); - sc->weight = make_float3(mix_weight, mix_weight, mix_weight); - sc->type = CLOSURE_HOLDOUT_ID; - } - else { - ShaderClosure *sc = svm_node_closure_get(sd); - sc->weight = make_float3(1.0f, 1.0f, 1.0f); - sc->type = CLOSURE_HOLDOUT_ID; + svm_node_closure_get_non_bsdf(sd, CLOSURE_HOLDOUT_ID, mix_weight); } + else + svm_node_closure_get_non_bsdf(sd, CLOSURE_HOLDOUT_ID, 1.0f); #else ShaderClosure *sc = &sd->closure; sc->type = CLOSURE_HOLDOUT_ID; @@ -372,12 +421,36 @@ __device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node) sd->flag |= SD_HOLDOUT; } +__device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack, uint4 node) +{ +#ifdef __MULTI_CLOSURE__ + uint mix_weight_offset = node.y; + + if(stack_valid(mix_weight_offset)) { + float mix_weight = stack_load_float(stack, mix_weight_offset); + + if(mix_weight == 0.0f) + return; + + svm_node_closure_get_non_bsdf(sd, CLOSURE_AMBIENT_OCCLUSION_ID, mix_weight); + } + else + svm_node_closure_get_non_bsdf(sd, CLOSURE_AMBIENT_OCCLUSION_ID, 1.0f); +#else + ShaderClosure *sc = &sd->closure; + sc->type = CLOSURE_AMBIENT_OCCLUSION_ID; +#endif + + sd->flag |= SD_AO; +} + /* Closure Nodes */ __device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight) { #ifdef __MULTI_CLOSURE__ - sd->closure[sd->num_closure].weight = weight; + if(sd->num_closure < MAX_CLOSURE) + sd->closure[sd->num_closure].weight = weight; #else sd->closure.weight = weight; #endif diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h index 8e772f849c7..c4d03c1f948 100644 --- a/intern/cycles/kernel/svm/svm_geometry.h +++ b/intern/cycles/kernel/svm/svm_geometry.h @@ -29,29 +29,18 @@ __device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack, case NODE_GEOM_N: data = sd->N; break; #ifdef __DPDU__ case NODE_GEOM_T: { - /* first try to get tangent attribute */ - int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_TANGENT): ATTR_STD_NOT_FOUND; + /* try to create spherical tangent from generated coordinates */ + int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_GENERATED): ATTR_STD_NOT_FOUND; if(attr_offset != ATTR_STD_NOT_FOUND) { - /* ensure orthogonal and normalized (interpolation breaks it) */ - data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL); + data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL); + data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f); object_normal_transform(kg, sd, &data); data = cross(sd->N, normalize(cross(data, sd->N)));; } else { - /* try to create spherical tangent from generated coordinates */ - int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_GENERATED): ATTR_STD_NOT_FOUND; - - if(attr_offset != ATTR_STD_NOT_FOUND) { - data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL); - data = make_float3(-(data.y - 0.5), (data.x - 0.5), 0.0f); - object_normal_transform(kg, sd, &data); - data = cross(sd->N, normalize(cross(data, sd->N)));; - } - else { - /* otherwise use surface derivatives */ - data = normalize(sd->dPdu); - } + /* otherwise use surface derivatives */ + data = normalize(sd->dPdu); } break; diff --git a/intern/cycles/kernel/svm/svm_hsv.h b/intern/cycles/kernel/svm/svm_hsv.h index bce11d62923..26b6141ee3f 100644 --- a/intern/cycles/kernel/svm/svm_hsv.h +++ b/intern/cycles/kernel/svm/svm_hsv.h @@ -110,7 +110,7 @@ __device void svm_node_hsv(KernelGlobals *kg, ShaderData *sd, float *stack, uint color = rgb_to_hsv(color); - // remember: fmod doesn't work for negative numbers + /* remember: fmod doesn't work for negative numbers here */ color.x += hue + 0.5f; color.x = fmod(color.x, 1.0f); color.y *= sat; diff --git a/intern/cycles/kernel/svm/svm_math.h b/intern/cycles/kernel/svm/svm_math.h index e39c7a4ba6c..db3b8d3f763 100644 --- a/intern/cycles/kernel/svm/svm_math.h +++ b/intern/cycles/kernel/svm/svm_math.h @@ -38,6 +38,21 @@ __device float safe_acosf(float a) return acosf(a); } +__device float compatible_powf(float x, float y) +{ + /* GPU pow doesn't accept negative x, do manual checks here */ + if(x < 0.0f) { + if(fmod(-y, 2.0f) == 0.0f) + return powf(-x, y); + else + return -powf(-x, y); + } + else if(x == 0.0f) + return 0.0f; + + return powf(x, y); +} + __device float safe_powf(float a, float b) { if(b == 0.0f) @@ -47,7 +62,7 @@ __device float safe_powf(float a, float b) if(a < 0.0f && b != (int)b) return 0.0f; - return powf(a, b); + return compatible_powf(a, b); } __device float safe_logf(float a, float b) diff --git a/intern/cycles/kernel/svm/svm_ramp.h b/intern/cycles/kernel/svm/svm_ramp.h index 55c2b3f6af4..c64413cbe84 100644 --- a/intern/cycles/kernel/svm/svm_ramp.h +++ b/intern/cycles/kernel/svm/svm_ramp.h @@ -25,7 +25,8 @@ __device float4 rgb_ramp_lookup(KernelGlobals *kg, int offset, float f) { f = clamp(f, 0.0f, 1.0f)*(RAMP_TABLE_SIZE-1); - int i = (int)f; + /* clamp int as well in case of NaN */ + int i = clamp((int)f, 0, RAMP_TABLE_SIZE-1); float t = f - (float)i; float4 a = fetch_node_float(kg, offset+i); diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index 6bd8f2ac69c..9f2d3367420 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -20,17 +20,19 @@ CCL_NAMESPACE_BEGIN /* Texture Coordinate Node */ -__device_inline float3 svm_background_offset(KernelGlobals *kg) +__device_inline float3 svm_background_position(KernelGlobals *kg, float3 P) { Transform cameratoworld = kernel_data.cam.cameratoworld; - return make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w); + float3 camP = make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w); + + return camP + P; } __device_inline float3 svm_world_to_ndc(KernelGlobals *kg, ShaderData *sd, float3 P) { if(kernel_data.cam.type != CAMERA_PANORAMA) { if(sd->object == ~0) - P += svm_background_offset(kg); + P = svm_background_position(kg, P); Transform tfm = kernel_data.cam.worldtondc; return transform_perspective(&tfm, P); @@ -78,11 +80,12 @@ __device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, float *stack if(sd->object != ~0) data = transform_point(&tfm, sd->P); else - data = transform_point(&tfm, sd->P + svm_background_offset(kg)); + data = transform_point(&tfm, svm_background_position(kg, sd->P)); break; } case NODE_TEXCO_WINDOW: { data = svm_world_to_ndc(kg, sd, sd->P); + data.z = 0.0f; break; } case NODE_TEXCO_REFLECTION: { @@ -135,11 +138,12 @@ __device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, floa if(sd->object != ~0) data = transform_point(&tfm, sd->P + sd->dP.dx); else - data = transform_point(&tfm, sd->P + sd->dP.dx + svm_background_offset(kg)); + data = transform_point(&tfm, svm_background_position(kg, sd->P + sd->dP.dx)); break; } case NODE_TEXCO_WINDOW: { data = svm_world_to_ndc(kg, sd, sd->P + sd->dP.dx); + data.z = 0.0f; break; } case NODE_TEXCO_REFLECTION: { @@ -195,11 +199,12 @@ __device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, floa if(sd->object != ~0) data = transform_point(&tfm, sd->P + sd->dP.dy); else - data = transform_point(&tfm, sd->P + sd->dP.dy + svm_background_offset(kg)); + data = transform_point(&tfm, svm_background_position(kg, sd->P + sd->dP.dy)); break; } case NODE_TEXCO_WINDOW: { data = svm_world_to_ndc(kg, sd, sd->P + sd->dP.dy); + data.z = 0.0f; break; } case NODE_TEXCO_REFLECTION: { @@ -225,5 +230,100 @@ __device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, floa #endif } +__device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) +{ + uint color_offset, strength_offset, normal_offset, space; + decode_node_uchar4(node.y, &color_offset, &strength_offset, &normal_offset, &space); + + float3 color = stack_load_float3(stack, color_offset); + color = 2.0f*make_float3(color.x - 0.5f, color.y - 0.5f, color.z - 0.5f); + + float3 N; + + if(space == NODE_NORMAL_MAP_TANGENT) { + /* tangent space */ + if(sd->object == ~0) { + stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f)); + return; + } + + /* first try to get tangent attribute */ + int attr_offset = find_attribute(kg, sd, node.z); + int attr_sign_offset = find_attribute(kg, sd, node.w); + + if(attr_offset == ATTR_STD_NOT_FOUND || attr_sign_offset == ATTR_STD_NOT_FOUND) { + stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f)); + return; + } + + /* ensure orthogonal and normalized (interpolation breaks it) */ + float3 tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL); + float sign = triangle_attribute_float(kg, sd, ATTR_ELEMENT_CORNER, attr_sign_offset, NULL, NULL); + + object_normal_transform(kg, sd, &tangent); + tangent = cross(sd->N, normalize(cross(tangent, sd->N)));; + + float3 B = sign * cross(sd->N, tangent); + N = normalize(color.x * tangent + color.y * B + color.z * sd->N); + } + else { + /* object, world space */ + N = color; + + if(space == NODE_NORMAL_MAP_OBJECT) + object_normal_transform(kg, sd, &N); + + N = normalize(N); + } + + float strength = stack_load_float(stack, strength_offset); + + if(strength != 1.0f) { + strength = max(strength, 0.0f); + N = normalize(sd->N + (N - sd->N)*strength); + } + + stack_store_float3(stack, normal_offset, N); +} + +__device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) +{ + uint tangent_offset, direction_type, axis; + decode_node_uchar4(node.y, &tangent_offset, &direction_type, &axis, NULL); + + float3 tangent; + + if(direction_type == NODE_TANGENT_UVMAP) { + /* UV map */ + int attr_offset = find_attribute(kg, sd, node.z); + + if(attr_offset == ATTR_STD_NOT_FOUND) + tangent = make_float3(0.0f, 0.0f, 0.0f); + else + tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL); + } + else { + /* radial */ + int attr_offset = find_attribute(kg, sd, node.z); + float3 generated; + + if(attr_offset == ATTR_STD_NOT_FOUND) + generated = sd->P; + else + generated = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL); + + if(axis == NODE_TANGENT_AXIS_X) + tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f)); + else if(axis == NODE_TANGENT_AXIS_Y) + tangent = make_float3(-(generated.z - 0.5f), 0.0f, (generated.x - 0.5f)); + else + tangent = make_float3(-(generated.y - 0.5f), (generated.x - 0.5f), 0.0f); + } + + object_normal_transform(kg, sd, &tangent); + tangent = cross(sd->N, normalize(cross(tangent, sd->N))); + stack_store_float3(stack, tangent_offset, tangent); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_texture.h b/intern/cycles/kernel/svm/svm_texture.h index 6c22d98e0df..a4f6691435c 100644 --- a/intern/cycles/kernel/svm/svm_texture.h +++ b/intern/cycles/kernel/svm/svm_texture.h @@ -42,8 +42,12 @@ __device float voronoi_distance(NodeDistanceMetric distance_metric, float3 d, fl /* Voronoi / Worley like */ -__device_noinline void voronoi(float3 p, NodeDistanceMetric distance_metric, float e, float da[4], float3 pa[4]) +__device_noinline float4 voronoi_Fn(float3 p, float e, int n1, int n2) { + float da[4]; + float3 pa[4]; + NodeDistanceMetric distance_metric = NODE_VORONOI_DISTANCE_SQUARED; + /* returns distances in da and point coords in pa */ int xx, yy, zz, xi, yi, zi; @@ -105,33 +109,20 @@ __device_noinline void voronoi(float3 p, NodeDistanceMetric distance_metric, flo } } } + + float4 result = make_float4(pa[n1].x, pa[n1].y, pa[n1].z, da[n1]); + + if(n2 != -1) + result = make_float4(pa[n2].x, pa[n2].y, pa[n2].z, da[n2]) - result; + + return result; } -__device float voronoi_Fn(float3 p, int n) -{ - float da[4]; - float3 pa[4]; - - voronoi(p, NODE_VORONOI_DISTANCE_SQUARED, 0, da, pa); - - return da[n]; -} - -__device float voronoi_FnFn(float3 p, int n1, int n2) -{ - float da[4]; - float3 pa[4]; - - voronoi(p, NODE_VORONOI_DISTANCE_SQUARED, 0, da, pa); - - return da[n2] - da[n1]; -} - -__device float voronoi_F1(float3 p) { return voronoi_Fn(p, 0); } -__device float voronoi_F2(float3 p) { return voronoi_Fn(p, 1); } -__device float voronoi_F3(float3 p) { return voronoi_Fn(p, 2); } -__device float voronoi_F4(float3 p) { return voronoi_Fn(p, 3); } -__device float voronoi_F1F2(float3 p) { return voronoi_FnFn(p, 0, 1); } +__device float voronoi_F1(float3 p) { return voronoi_Fn(p, 0.0f, 0, -1).w; } +__device float voronoi_F2(float3 p) { return voronoi_Fn(p, 0.0f, 1, -1).w; } +__device float voronoi_F3(float3 p) { return voronoi_Fn(p, 0.0f, 2, -1).w; } +__device float voronoi_F4(float3 p) { return voronoi_Fn(p, 0.0f, 3, -1).w; } +__device float voronoi_F1F2(float3 p) { return voronoi_Fn(p, 0.0f, 0, 1).w; } __device float voronoi_Cr(float3 p) { diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 77df373a159..b41e34ab407 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -94,6 +94,9 @@ typedef enum NodeType { NODE_PARTICLE_INFO, NODE_TEX_BRICK, NODE_CLOSURE_SET_NORMAL, + NODE_CLOSURE_AMBIENT_OCCLUSION, + NODE_TANGENT, + NODE_NORMAL_MAP } NodeType; typedef enum NodeAttributeType { @@ -279,6 +282,23 @@ typedef enum NodeBlendWeightType { NODE_LAYER_WEIGHT_FACING } NodeBlendWeightType; +typedef enum NodeTangentDirectionType { + NODE_TANGENT_RADIAL, + NODE_TANGENT_UVMAP +} NodeTangentDirectionType; + +typedef enum NodeTangentAxis { + NODE_TANGENT_AXIS_X, + NODE_TANGENT_AXIS_Y, + NODE_TANGENT_AXIS_Z +} NodeTangentAxis; + +typedef enum NodeNormalMapSpace { + NODE_NORMAL_MAP_TANGENT, + NODE_NORMAL_MAP_OBJECT, + NODE_NORMAL_MAP_WORLD +} NodeNormalMapSpace; + typedef enum ShaderType { SHADER_TYPE_SURFACE, SHADER_TYPE_VOLUME, @@ -300,6 +320,7 @@ typedef enum ClosureType { CLOSURE_BSDF_WARD_ID, CLOSURE_BSDF_ASHIKHMIN_VELVET_ID, CLOSURE_BSDF_WESTIN_SHEEN_ID, + CLOSURE_BSDF_PHONG_RAMP_ID, CLOSURE_BSDF_TRANSMISSION_ID, CLOSURE_BSDF_TRANSLUCENT_ID, @@ -307,7 +328,9 @@ typedef enum ClosureType { CLOSURE_BSDF_WESTIN_BACKSCATTER_ID, CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID, CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID, - CLOSURE_BSDF_GLASS_ID, + CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID, + CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID, + CLOSURE_BSDF_SHARP_GLASS_ID, CLOSURE_BSDF_TRANSPARENT_ID, @@ -317,6 +340,7 @@ typedef enum ClosureType { CLOSURE_BACKGROUND_ID, CLOSURE_HOLDOUT_ID, CLOSURE_SUBSURFACE_ID, + CLOSURE_AMBIENT_OCCLUSION_ID, CLOSURE_VOLUME_ID, CLOSURE_VOLUME_TRANSPARENT_ID, @@ -328,12 +352,13 @@ typedef enum ClosureType { /* watch this, being lazy with memory usage */ #define CLOSURE_IS_BSDF(type) (type <= CLOSURE_BSDF_TRANSPARENT_ID) #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_WESTIN_SHEEN_ID) -#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_GLASS_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_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) #define CLOSURE_IS_BACKGROUND(type) (type == CLOSURE_BACKGROUND_ID) +#define CLOSURE_IS_AMBIENT_OCCLUSION(type) (type == CLOSURE_AMBIENT_OCCLUSION_ID) CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_voronoi.h b/intern/cycles/kernel/svm/svm_voronoi.h index 7e7bd970320..55110d06f22 100644 --- a/intern/cycles/kernel/svm/svm_voronoi.h +++ b/intern/cycles/kernel/svm/svm_voronoi.h @@ -23,21 +23,18 @@ CCL_NAMESPACE_BEGIN __device_noinline float4 svm_voronoi(NodeVoronoiColoring coloring, float scale, float3 p) { /* compute distance and point coordinate of 4 nearest neighbours */ - float da[4]; - float3 pa[4]; - - voronoi(p*scale, NODE_VORONOI_DISTANCE_SQUARED, 1.0f, da, pa); + float4 dpa0 = voronoi_Fn(p*scale, 1.0f, 0, -1); /* output */ float fac; float3 color; if(coloring == NODE_VORONOI_INTENSITY) { - fac = fabsf(da[0]); + fac = fabsf(dpa0.w); color = make_float3(fac, fac, fac); } else { - color = cellnoise_color(pa[0]); + color = cellnoise_color(float4_to_float3(dpa0)); fac = average(color); } diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index c7a9ab3e51a..95941c14b6c 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -162,8 +162,10 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) attr = add(name, TypeDesc::TypeNormal, Attribute::FACE); else if(std == ATTR_STD_UV) attr = add(name, TypeDesc::TypePoint, Attribute::CORNER); - else if(std == ATTR_STD_TANGENT) + else if(std == ATTR_STD_UV_TANGENT) attr = add(name, TypeDesc::TypeVector, Attribute::CORNER); + else if(std == ATTR_STD_UV_TANGENT_SIGN) + attr = add(name, TypeDesc::TypeFloat, Attribute::CORNER); else if(std == ATTR_STD_GENERATED) attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX); else if(std == ATTR_STD_POSITION_UNDEFORMED) diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 649936bec04..a78ede979b2 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -55,15 +55,10 @@ Camera::Camera() width = 1024; height = 512; - left = -((float)width/(float)height); - right = (float)width/(float)height; - bottom = -1.0f; - top = 1.0f; - - border_left = 0.0f; - border_right = 1.0f; - border_bottom = 0.0f; - border_top = 1.0f; + viewplane.left = -((float)width/(float)height); + viewplane.right = (float)width/(float)height; + viewplane.bottom = -1.0f; + viewplane.top = 1.0f; screentoworld = transform_identity(); rastertoworld = transform_identity(); @@ -94,12 +89,12 @@ void Camera::update() Transform ndctoraster = transform_scale(width, height, 1.0f); /* raster to screen */ - Transform screentoraster = ndctoraster; - - screentoraster = ndctoraster * - transform_scale(1.0f/(right - left), 1.0f/(top - bottom), 1.0f) * - transform_translate(-left, -bottom, 0.0f); + Transform screentondc = + transform_scale(1.0f/(viewplane.right - viewplane.left), + 1.0f/(viewplane.top - viewplane.bottom), 1.0f) * + transform_translate(-viewplane.left, -viewplane.bottom, 0.0f); + Transform screentoraster = ndctoraster * screentondc; Transform rastertoscreen = transform_inverse(screentoraster); /* screen to camera */ @@ -109,14 +104,24 @@ void Camera::update() screentocamera = transform_inverse(transform_orthographic(nearclip, farclip)); else screentocamera = transform_identity(); + + Transform cameratoscreen = transform_inverse(screentocamera); rastertocamera = screentocamera * rastertoscreen; + cameratoraster = screentoraster * cameratoscreen; cameratoworld = matrix; screentoworld = cameratoworld * screentocamera; rastertoworld = cameratoworld * rastertocamera; ndctoworld = rastertoworld * ndctoraster; - worldtoraster = transform_inverse(rastertoworld); + + /* note we recompose matrices instead of taking inverses of the above, this + * is needed to avoid inverting near degenerate matrices that happen due to + * precision issues with large scenes */ + worldtocamera = transform_inverse(matrix); + worldtoscreen = cameratoscreen * worldtocamera; + worldtondc = screentondc * worldtoscreen; + worldtoraster = ndctoraster * worldtondc; /* differentials */ if(type == CAMERA_ORTHOGRAPHIC) { @@ -164,10 +169,10 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) kcam->rastertoworld = rastertoworld; kcam->rastertocamera = rastertocamera; kcam->cameratoworld = cameratoworld; - kcam->worldtoscreen = transform_inverse(screentoworld); + kcam->worldtocamera = worldtocamera; + kcam->worldtoscreen = worldtoscreen; kcam->worldtoraster = worldtoraster; - kcam->worldtondc = transform_inverse(ndctoworld); - kcam->worldtocamera = transform_inverse(cameratoworld); + kcam->worldtondc = worldtondc; /* camera motion */ kcam->have_motion = 0; @@ -185,8 +190,8 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) } else { if(use_motion) { - kcam->motion.pre = transform_inverse(motion.pre * rastertocamera); - kcam->motion.post = transform_inverse(motion.post * rastertocamera); + kcam->motion.pre = cameratoraster * transform_inverse(motion.pre); + kcam->motion.post = cameratoraster * transform_inverse(motion.post); } else { kcam->motion.pre = worldtoraster; @@ -197,7 +202,7 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) #ifdef __CAMERA_MOTION__ else if(need_motion == Scene::MOTION_BLUR) { if(use_motion) { - transform_motion_decompose(&kcam->motion, &motion, &matrix); + transform_motion_decompose((DecompMotionTransform*)&kcam->motion, &motion, &matrix); kcam->have_motion = 1; } } @@ -265,14 +270,8 @@ bool Camera::modified(const Camera& cam) // modified for progressive render // (width == cam.width) && // (height == cam.height) && - (left == cam.left) && - (right == cam.right) && - (bottom == cam.bottom) && - (top == cam.top) && - (border_left == cam.border_left) && - (border_right == cam.border_right) && - (border_bottom == cam.border_bottom) && - (border_top == cam.border_top) && + (viewplane == cam.viewplane) && + (border == cam.border) && (matrix == cam.matrix) && (panorama_type == cam.panorama_type) && (fisheye_fov == cam.fisheye_fov) && diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 1407c86e7c2..9696161180d 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -21,6 +21,7 @@ #include "kernel_types.h" +#include "util_boundbox.h" #include "util_transform.h" #include "util_types.h" @@ -65,10 +66,10 @@ public: /* screen */ int width, height; - float left, right, bottom, top; + BoundBox2D viewplane; /* border */ - float border_left, border_right, border_bottom, border_top; + BoundBox2D border; /* transformation */ Transform matrix; @@ -81,9 +82,15 @@ public: Transform screentoworld; Transform rastertoworld; Transform ndctoworld; - Transform rastertocamera; Transform cameratoworld; + Transform worldtoraster; + Transform worldtoscreen; + Transform worldtondc; + Transform worldtocamera; + + Transform rastertocamera; + Transform cameratoraster;; float3 dx; float3 dy; diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index c1c976dc193..14b219383d0 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -37,7 +37,7 @@ ShaderInput::ShaderInput(ShaderNode *parent_, const char *name_, ShaderSocketTyp value = make_float3(0, 0, 0); stack_offset = SVM_STACK_INVALID; default_value = NONE; - osl_only = false; + usage = USE_ALL; } ShaderOutput::ShaderOutput(ShaderNode *parent_, const char *name_, ShaderSocketType type_) @@ -85,27 +85,29 @@ ShaderOutput *ShaderNode::output(const char *name) return NULL; } -ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float value) +ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float value, int usage) { ShaderInput *input = new ShaderInput(this, name, type); input->value.x = value; + input->usage = usage; inputs.push_back(input); return input; } -ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float3 value) +ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float3 value, int usage) { ShaderInput *input = new ShaderInput(this, name, type); input->value = value; + input->usage = usage; inputs.push_back(input); return input; } -ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, bool osl_only) +ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, int usage) { ShaderInput *input = add_input(name, type); input->default_value = value; - input->osl_only = osl_only; + input->usage = usage; return input; } @@ -219,7 +221,7 @@ void ShaderGraph::disconnect(ShaderInput *to) from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end()); } -void ShaderGraph::finalize(bool do_bump, bool do_osl) +void ShaderGraph::finalize(bool do_bump, bool do_osl, bool do_multi_transform) { /* before compiling, the shader graph may undergo a number of modifications. * currently we set default geometry shader inputs, and create automatic bump @@ -234,6 +236,18 @@ void ShaderGraph::finalize(bool do_bump, bool do_osl) if(do_bump) bump_from_displacement(); + if(do_multi_transform) { + ShaderInput *surface_in = output()->input("Surface"); + ShaderInput *volume_in = output()->input("Volume"); + + /* todo: make this work when surface and volume closures are tangled up */ + + if(surface_in->link) + transform_multi_closure(surface_in->link->parent, NULL, false); + if(volume_in->link) + transform_multi_closure(volume_in->link->parent, NULL, true); + } + finalized = true; } } @@ -326,6 +340,7 @@ void ShaderGraph::remove_proxy_nodes(vector& removed) /* transfer the default input value to the target socket */ to->set(input->value); + to->set(input->value_string); } } @@ -439,7 +454,7 @@ void ShaderGraph::default_inputs(bool do_osl) foreach(ShaderNode *node, nodes) { foreach(ShaderInput *input, node->inputs) { - if(!input->link && !(input->osl_only && !do_osl)) { + if(!input->link && ((input->usage & ShaderInput::USE_SVM) || do_osl)) { if(input->default_value == ShaderInput::TEXTURE_GENERATED) { if(!texco) texco = new TextureCoordinateNode(); @@ -628,5 +643,81 @@ void ShaderGraph::bump_from_displacement() add(pair.second); } +void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume) +{ + /* for SVM in multi closure mode, this transforms the shader mix/add part of + * the graph into nodes that feed weights into closure nodes. this is too + * avoid building a closure tree and then flattening it, and instead write it + * directly to an array */ + + if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) { + ShaderInput *fin = node->input("Fac"); + ShaderInput *cl1in = node->input("Closure1"); + ShaderInput *cl2in = node->input("Closure2"); + ShaderOutput *weight1_out, *weight2_out; + + if(fin) { + /* mix closure: add node to mix closure weights */ + ShaderNode *mix_node = add(new MixClosureWeightNode()); + ShaderInput *fac_in = mix_node->input("Fac"); + ShaderInput *weight_in = mix_node->input("Weight"); + + if(fin->link) + connect(fin->link, fac_in); + else + fac_in->value = fin->value; + + if(weight_out) + connect(weight_out, weight_in); + + weight1_out = mix_node->output("Weight1"); + weight2_out = mix_node->output("Weight2"); + } + else { + /* add closure: just pass on any weights */ + weight1_out = weight_out; + weight2_out = weight_out; + } + + if(cl1in->link) + transform_multi_closure(cl1in->link->parent, weight1_out, volume); + if(cl2in->link) + transform_multi_closure(cl2in->link->parent, weight2_out, volume); + } + else { + ShaderInput *weight_in = node->input((volume)? "VolumeMixWeight": "SurfaceMixWeight"); + + /* not a closure node? */ + if(!weight_in) + return; + + /* already has a weight connected to it? add weights */ + if(weight_in->link || weight_in->value.x != 0.0f) { + ShaderNode *math_node = add(new MathNode()); + ShaderInput *value1_in = math_node->input("Value1"); + ShaderInput *value2_in = math_node->input("Value2"); + + if(weight_in->link) + connect(weight_in->link, value1_in); + else + value1_in->value = weight_in->value; + + if(weight_out) + connect(weight_out, value2_in); + else + value2_in->value.x = 1.0f; + + weight_out = math_node->output("Value"); + disconnect(weight_in); + } + + /* connected to closure mix weight */ + if(weight_out) + connect(weight_out, weight_in); + else + weight_in->value.x += 1.0f; + } +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index b339c3c3847..b79167839ab 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -49,7 +49,8 @@ enum ShaderSocketType { SHADER_SOCKET_VECTOR, SHADER_SOCKET_POINT, SHADER_SOCKET_NORMAL, - SHADER_SOCKET_CLOSURE + SHADER_SOCKET_CLOSURE, + SHADER_SOCKET_STRING }; /* Bump @@ -117,9 +118,16 @@ public: NONE }; + enum Usage { + USE_SVM = 1, + USE_OSL = 2, + USE_ALL = USE_SVM|USE_OSL + }; + ShaderInput(ShaderNode *parent, const char *name, ShaderSocketType type); void set(const float3& v) { value = v; } void set(float f) { value = make_float3(f, 0, 0); } + void set(const ustring v) { value_string = v; } const char *name; ShaderSocketType type; @@ -129,9 +137,10 @@ public: DefaultValue default_value; float3 value; + ustring value_string; int stack_offset; /* for SVM compiler */ - bool osl_only; + int usage; }; /* Output @@ -164,9 +173,9 @@ public: ShaderInput *input(const char *name); ShaderOutput *output(const char *name); - ShaderInput *add_input(const char *name, ShaderSocketType type, float value=0.0f); - ShaderInput *add_input(const char *name, ShaderSocketType type, float3 value); - ShaderInput *add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, bool osl_only=false); + ShaderInput *add_input(const char *name, ShaderSocketType type, float value=0.0f, int usage=ShaderInput::USE_ALL); + ShaderInput *add_input(const char *name, ShaderSocketType type, float3 value, int usage=ShaderInput::USE_ALL); + ShaderInput *add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, int usage=ShaderInput::USE_ALL); ShaderOutput *add_output(const char *name, ShaderSocketType type); virtual ShaderNode *clone() const = 0; @@ -224,7 +233,7 @@ public: void connect(ShaderOutput *from, ShaderInput *to); void disconnect(ShaderInput *to); - void finalize(bool do_bump = false, bool do_osl = false); + void finalize(bool do_bump = false, bool do_osl = false, bool do_multi_closure = false); protected: typedef pair NodePair; @@ -238,6 +247,7 @@ protected: void bump_from_displacement(); void refine_bump_nodes(); void default_inputs(bool do_osl); + void transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume); }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index f136f08dc2c..230a12f9ff2 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -36,6 +36,7 @@ ImageManager::ImageManager() need_update = true; pack_images = false; osl_texture_system = NULL; + animation_frame = 0; tex_num_images = TEX_NUM_IMAGES; tex_num_float_images = TEX_NUM_FLOAT_IMAGES; @@ -67,7 +68,24 @@ void ImageManager::set_extended_image_limits(void) tex_image_byte_start = TEX_EXTENDED_IMAGE_BYTE_START; } -static bool is_float_image(const string& filename) +bool ImageManager::set_animation_frame_update(int frame) +{ + if(frame != animation_frame) { + animation_frame = frame; + + for(size_t slot = 0; slot < images.size(); slot++) + if(images[slot] && images[slot]->animated) + return true; + + for(size_t slot = 0; slot < float_images.size(); slot++) + if(float_images[slot] && float_images[slot]->animated) + return true; + } + + return false; +} + +bool ImageManager::is_float_image(const string& filename) { ImageInput *in = ImageInput::create(filename); bool is_float = false; @@ -95,7 +113,7 @@ static bool is_float_image(const string& filename) return is_float; } -int ImageManager::add_image(const string& filename, bool& is_float) +int ImageManager::add_image(const string& filename, bool animated, bool& is_float) { Image *img; size_t slot; @@ -133,6 +151,7 @@ int ImageManager::add_image(const string& filename, bool& is_float) img = new Image(); img->filename = filename; img->need_load = true; + img->animated = animated; img->users = 1; float_images[slot] = img; @@ -166,6 +185,7 @@ int ImageManager::add_image(const string& filename, bool& is_float) img = new Image(); img->filename = filename; img->need_load = true; + img->animated = animated; img->users = 1; images[slot] = img; diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 485bfc5cbf5..4d177174971 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -51,16 +51,17 @@ public: ImageManager(); ~ImageManager(); - int add_image(const string& filename, bool& is_float); + int add_image(const string& filename, bool animated, bool& is_float); void remove_image(const string& filename); + bool is_float_image(const string& filename); void device_update(Device *device, DeviceScene *dscene, Progress& progress); void device_free(Device *device, DeviceScene *dscene); void set_osl_texture_system(void *texture_system); void set_pack_images(bool pack_images_); - void set_extended_image_limits(void); + bool set_animation_frame_update(int frame); bool need_update; @@ -69,11 +70,13 @@ private: int tex_num_float_images; int tex_image_byte_start; thread_mutex device_mutex; + int animation_frame; struct Image { string filename; bool need_load; + bool animated; int users; }; diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index d77516a1b18..4173da453fd 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -147,6 +147,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen Mesh *mesh = object->mesh; bool have_emission = false; + /* skip if we are not visible for BSDFs */ + if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) + continue; + /* skip if we have no emission shaders */ foreach(uint sindex, mesh->used_shaders) { Shader *shader = scene->shaders[sindex]; @@ -183,6 +187,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen Mesh *mesh = object->mesh; bool have_emission = false; + /* skip if we are not visible for BSDFs */ + if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) + continue; + /* skip if we have no emission shaders */ foreach(uint sindex, mesh->used_shaders) { Shader *shader = scene->shaders[sindex]; diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 14f23992664..bc782a78c60 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -325,6 +325,7 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vectorobject_name_map.clear(); og->attribute_map.clear(); + og->object_names.clear(); og->attribute_map.resize(scene->objects.size()); @@ -332,6 +333,7 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vectorobjects[i]; og->object_name_map[object->name] = i; + og->object_names.push_back(object->name); /* set object attributes */ foreach(ParamValue& attr, object->attributes) { @@ -545,7 +547,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, } /* create attribute lookup maps */ - if(scene->params.shadingsystem == SceneParams::OSL) + if(scene->shader_manager->use_osl()) update_osl_attributes(device, scene, mesh_attributes); else update_svm_attributes(device, dscene, scene, mesh_attributes); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index d7bf71337f6..3f8055b3540 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -100,6 +100,16 @@ void TextureMapping::compile(SVMCompiler& compiler, int offset_in, int offset_ou } } +void TextureMapping::compile(OSLCompiler &compiler) +{ + if(!skip()) { + Transform tfm = transform_transpose(compute_transform()); + + compiler.parameter("mapping", tfm); + compiler.parameter("use_mapping", 1); + } +} + /* Image Texture */ static ShaderEnum color_space_init() @@ -130,11 +140,12 @@ ImageTextureNode::ImageTextureNode() { image_manager = NULL; slot = -1; - is_float = false; + is_float = -1; filename = ""; color_space = ustring("Color"); projection = ustring("Flat");; projection_blend = 0.0f; + animated = false; add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_UV); add_output("Color", SHADER_SOCKET_COLOR); @@ -152,7 +163,7 @@ ShaderNode *ImageTextureNode::clone() const ImageTextureNode *node = new ImageTextureNode(*this); node->image_manager = NULL; node->slot = -1; - node->is_float = false; + node->is_float = -1; return node; } @@ -163,8 +174,11 @@ void ImageTextureNode::compile(SVMCompiler& compiler) ShaderOutput *alpha_out = output("Alpha"); image_manager = compiler.image_manager; - if(slot == -1) - slot = image_manager->add_image(filename, is_float); + if(is_float == -1) { + bool is_float_bool; + slot = image_manager->add_image(filename, animated, is_float_bool); + is_float = (int)is_float_bool; + } if(!color_out->links.empty()) compiler.stack_assign(color_out); @@ -220,6 +234,11 @@ void ImageTextureNode::compile(SVMCompiler& compiler) void ImageTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + + if(is_float == -1) + is_float = (int)image_manager->is_float_image(filename); + compiler.parameter("filename", filename.c_str()); if(is_float || color_space != "Color") compiler.parameter("color_space", "Linear"); @@ -250,10 +269,11 @@ EnvironmentTextureNode::EnvironmentTextureNode() { image_manager = NULL; slot = -1; - is_float = false; + is_float = -1; filename = ""; color_space = ustring("Color"); projection = ustring("Equirectangular"); + animated = false; add_input("Vector", SHADER_SOCKET_VECTOR, ShaderInput::POSITION); add_output("Color", SHADER_SOCKET_COLOR); @@ -271,7 +291,7 @@ ShaderNode *EnvironmentTextureNode::clone() const EnvironmentTextureNode *node = new EnvironmentTextureNode(*this); node->image_manager = NULL; node->slot = -1; - node->is_float = false; + node->is_float = -1; return node; } @@ -282,8 +302,11 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler) ShaderOutput *alpha_out = output("Alpha"); image_manager = compiler.image_manager; - if(slot == -1) - slot = image_manager->add_image(filename, is_float); + if(slot == -1) { + bool is_float_bool; + slot = image_manager->add_image(filename, animated, is_float_bool); + is_float = (int)is_float_bool; + } if(!color_out->links.empty()) compiler.stack_assign(color_out); @@ -328,7 +351,13 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler) void EnvironmentTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + + if(is_float == -1) + is_float = (int)image_manager->is_float_image(filename); + compiler.parameter("filename", filename.c_str()); + compiler.parameter("projection", projection); if(is_float || color_space != "Color") compiler.parameter("color_space", "Linear"); else @@ -438,6 +467,8 @@ void SkyTextureNode::compile(SVMCompiler& compiler) void SkyTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter_vector("sun_direction", sun_direction); compiler.parameter("turbidity", turbidity); compiler.add(this, "node_sky_texture"); @@ -501,6 +532,8 @@ void GradientTextureNode::compile(SVMCompiler& compiler) void GradientTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter("Type", type); compiler.add(this, "node_gradient_texture"); } @@ -559,6 +592,8 @@ void NoiseTextureNode::compile(SVMCompiler& compiler) void NoiseTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.add(this, "node_noise_texture"); } @@ -619,6 +654,8 @@ void VoronoiTextureNode::compile(SVMCompiler& compiler) void VoronoiTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter("Coloring", coloring); compiler.add(this, "node_voronoi_texture"); } @@ -706,6 +743,8 @@ void MusgraveTextureNode::compile(SVMCompiler& compiler) void MusgraveTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter("Type", type); compiler.add(this, "node_musgrave_texture"); @@ -784,6 +823,8 @@ void WaveTextureNode::compile(SVMCompiler& compiler) void WaveTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter("Type", type); compiler.add(this, "node_wave_texture"); @@ -841,6 +882,8 @@ void MagicTextureNode::compile(SVMCompiler& compiler) void MagicTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter("Depth", depth); compiler.add(this, "node_magic_texture"); } @@ -897,6 +940,8 @@ void CheckerTextureNode::compile(SVMCompiler& compiler) void CheckerTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.add(this, "node_checker_texture"); } @@ -985,6 +1030,8 @@ void BrickTextureNode::compile(SVMCompiler& compiler) void BrickTextureNode::compile(OSLCompiler& compiler) { + tex_mapping.compile(compiler); + compiler.parameter("Offset", offset); compiler.parameter("OffsetFrequency", offset_frequency); compiler.parameter("Squash", squash); @@ -1051,6 +1098,9 @@ void MappingNode::compile(OSLCompiler& compiler) { Transform tfm = transform_transpose(tex_mapping.compute_transform()); compiler.parameter("Matrix", tfm); + compiler.parameter_point("mapping_min", tex_mapping.min); + compiler.parameter_point("mapping_max", tex_mapping.max); + compiler.parameter("use_minmax", tex_mapping.use_minmax); compiler.add(this, "node_mapping"); } @@ -1077,6 +1127,8 @@ ConvertNode::ConvertNode(ShaderSocketType from_, ShaderSocketType to_) add_input("Point", SHADER_SOCKET_POINT); else if(from == SHADER_SOCKET_NORMAL) add_input("Normal", SHADER_SOCKET_NORMAL); + else if(from == SHADER_SOCKET_STRING) + add_input("String", SHADER_SOCKET_STRING); else assert(0); @@ -1092,6 +1144,8 @@ ConvertNode::ConvertNode(ShaderSocketType from_, ShaderSocketType to_) add_output("Point", SHADER_SOCKET_POINT); else if(to == SHADER_SOCKET_NORMAL) add_output("Normal", SHADER_SOCKET_NORMAL); + else if(to == SHADER_SOCKET_STRING) + add_output("String", SHADER_SOCKET_STRING); else assert(0); } @@ -1210,6 +1264,7 @@ BsdfNode::BsdfNode() 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); } @@ -1284,10 +1339,8 @@ void WardBsdfNode::attributes(AttributeRequestSet *attributes) { ShaderInput *tangent_in = input("Tangent"); - if(!tangent_in->link) { - attributes->add(ATTR_STD_TANGENT); + if(!tangent_in->link) attributes->add(ATTR_STD_GENERATED); - } ShaderNode::attributes(attributes); } @@ -1346,9 +1399,9 @@ static ShaderEnum glass_distribution_init() { ShaderEnum enm; - enm.insert("Sharp", CLOSURE_BSDF_REFRACTION_ID); - enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID); - enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID); + enm.insert("Sharp", CLOSURE_BSDF_SHARP_GLASS_ID); + enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID); + enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID); return enm; } @@ -1367,7 +1420,7 @@ void GlassBsdfNode::compile(SVMCompiler& compiler) { closure = (ClosureType)distribution_enum[distribution]; - if(closure == CLOSURE_BSDF_REFRACTION_ID) + if(closure == CLOSURE_BSDF_SHARP_GLASS_ID) BsdfNode::compile(compiler, NULL, input("IOR")); else BsdfNode::compile(compiler, input("Roughness"), input("IOR")); @@ -1379,6 +1432,45 @@ void GlassBsdfNode::compile(OSLCompiler& compiler) compiler.add(this, "node_glass_bsdf"); } +/* Refraction BSDF Closure */ + +static ShaderEnum refraction_distribution_init() +{ + ShaderEnum enm; + + enm.insert("Sharp", CLOSURE_BSDF_REFRACTION_ID); + enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID); + enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID); + + return enm; +} + +ShaderEnum RefractionBsdfNode::distribution_enum = refraction_distribution_init(); + +RefractionBsdfNode::RefractionBsdfNode() +{ + distribution = ustring("Sharp"); + + add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f); + add_input("IOR", SHADER_SOCKET_FLOAT, 0.3f); +} + +void RefractionBsdfNode::compile(SVMCompiler& compiler) +{ + closure = (ClosureType)distribution_enum[distribution]; + + if(closure == CLOSURE_BSDF_REFRACTION_ID) + BsdfNode::compile(compiler, NULL, input("IOR")); + else + BsdfNode::compile(compiler, input("Roughness"), input("IOR")); +} + +void RefractionBsdfNode::compile(OSLCompiler& compiler) +{ + compiler.parameter("distribution", distribution); + compiler.add(this, "node_refraction_bsdf"); +} + /* Velvet BSDF Closure */ VelvetBsdfNode::VelvetBsdfNode() @@ -1460,6 +1552,8 @@ EmissionNode::EmissionNode() add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); add_input("Strength", SHADER_SOCKET_FLOAT, 10.0f); + add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); + add_output("Emission", SHADER_SOCKET_CLOSURE); } @@ -1494,6 +1588,8 @@ BackgroundNode::BackgroundNode() { add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f); + add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); + add_output("Background", SHADER_SOCKET_CLOSURE); } @@ -1523,11 +1619,17 @@ void BackgroundNode::compile(OSLCompiler& compiler) HoldoutNode::HoldoutNode() : ShaderNode("holdout") { + add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); + add_input("VolumeMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); + add_output("Holdout", SHADER_SOCKET_CLOSURE); } void HoldoutNode::compile(SVMCompiler& compiler) { + float3 value = make_float3(1.0f, 1.0f, 1.0f); + + compiler.add_node(NODE_CLOSURE_SET_WEIGHT, value); compiler.add_node(NODE_CLOSURE_HOLDOUT, compiler.closure_mix_weight_offset()); } @@ -1536,6 +1638,37 @@ void HoldoutNode::compile(OSLCompiler& compiler) compiler.add(this, "node_holdout"); } +/* Ambient Occlusion */ + +AmbientOcclusionNode::AmbientOcclusionNode() +: ShaderNode("ambient_occlusion") +{ + add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL); + add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); + add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); + + add_output("AO", SHADER_SOCKET_CLOSURE); +} + +void AmbientOcclusionNode::compile(SVMCompiler& compiler) +{ + ShaderInput *color_in = input("Color"); + + if(color_in->link) { + compiler.stack_assign(color_in); + compiler.add_node(NODE_CLOSURE_WEIGHT, color_in->stack_offset); + } + else + compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value); + + compiler.add_node(NODE_CLOSURE_AMBIENT_OCCLUSION, compiler.closure_mix_weight_offset()); +} + +void AmbientOcclusionNode::compile(OSLCompiler& compiler) +{ + compiler.add(this, "node_ambient_occlusion"); +} + /* Volume Closure */ VolumeNode::VolumeNode() @@ -1545,6 +1678,7 @@ VolumeNode::VolumeNode() add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); add_input("Density", SHADER_SOCKET_FLOAT, 1.0f); + add_input("VolumeMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); add_output("Volume", SHADER_SOCKET_CLOSURE); } @@ -1623,7 +1757,7 @@ void IsotropicVolumeNode::compile(OSLCompiler& compiler) GeometryNode::GeometryNode() : ShaderNode("geometry") { - add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL); add_output("Position", SHADER_SOCKET_POINT); add_output("Normal", SHADER_SOCKET_NORMAL); add_output("Tangent", SHADER_SOCKET_NORMAL); @@ -1635,10 +1769,8 @@ GeometryNode::GeometryNode() void GeometryNode::attributes(AttributeRequestSet *attributes) { - if(!output("Tangent")->links.empty()) { - attributes->add(ATTR_STD_TANGENT); + if(!output("Tangent")->links.empty()) attributes->add(ATTR_STD_GENERATED); - } ShaderNode::attributes(attributes); } @@ -1713,7 +1845,7 @@ void GeometryNode::compile(OSLCompiler& compiler) TextureCoordinateNode::TextureCoordinateNode() : ShaderNode("texture_coordinate") { - add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL); add_output("Generated", SHADER_SOCKET_POINT); add_output("Normal", SHADER_SOCKET_NORMAL); add_output("UV", SHADER_SOCKET_POINT); @@ -2075,13 +2207,14 @@ void ParticleInfoNode::compile(SVMCompiler& compiler) compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LOCATION, out->stack_offset); } - #if 0 /* XXX Quaternion data is not yet supported by Cycles */ + /* quaternion data is not yet supported by Cycles */ +#if 0 out = output("Rotation"); if(!out->links.empty()) { compiler.stack_assign(out); compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_ROTATION, out->stack_offset); } - #endif +#endif out = output("Size"); if(!out->links.empty()) { @@ -2202,6 +2335,39 @@ void MixClosureNode::compile(OSLCompiler& compiler) compiler.add(this, "node_mix_closure"); } +/* Mix Closure */ + +MixClosureWeightNode::MixClosureWeightNode() +: ShaderNode("mix_closure_weight") +{ + add_input("Weight", SHADER_SOCKET_FLOAT, 1.0f); + add_input("Fac", SHADER_SOCKET_FLOAT, 1.0f); + add_output("Weight1", SHADER_SOCKET_FLOAT); + add_output("Weight2", SHADER_SOCKET_FLOAT); +} + +void MixClosureWeightNode::compile(SVMCompiler& compiler) +{ + ShaderInput *weight_in = input("Weight"); + ShaderInput *fac_in = input("Fac"); + ShaderOutput *weight1_out = output("Weight1"); + ShaderOutput *weight2_out = output("Weight2"); + + compiler.stack_assign(weight_in); + compiler.stack_assign(fac_in); + compiler.stack_assign(weight1_out); + compiler.stack_assign(weight2_out); + + compiler.add_node(NODE_MIX_CLOSURE, + compiler.encode_uchar4(fac_in->stack_offset, weight_in->stack_offset, + weight1_out->stack_offset, weight2_out->stack_offset)); +} + +void MixClosureWeightNode::compile(OSLCompiler& compiler) +{ + assert(0); +} + /* Invert */ InvertNode::InvertNode() @@ -2567,7 +2733,7 @@ void CameraNode::compile(OSLCompiler& compiler) FresnelNode::FresnelNode() : ShaderNode("Fresnel") { - add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL); add_input("IOR", SHADER_SOCKET_FLOAT, 1.45f); add_output("Fac", SHADER_SOCKET_FLOAT); } @@ -2592,7 +2758,7 @@ void FresnelNode::compile(OSLCompiler& compiler) LayerWeightNode::LayerWeightNode() : ShaderNode("LayerWeight") { - add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL); add_input("Blend", SHADER_SOCKET_FLOAT, 0.5f); add_output("Fresnel", SHADER_SOCKET_FLOAT); @@ -2946,5 +3112,186 @@ void OSLScriptNode::compile(OSLCompiler& compiler) compiler.add(this, bytecode_hash.c_str(), false); } +/* Normal Map */ + +static ShaderEnum normal_map_space_init() +{ + ShaderEnum enm; + + enm.insert("Tangent", NODE_NORMAL_MAP_TANGENT); + enm.insert("Object", NODE_NORMAL_MAP_OBJECT); + enm.insert("World", NODE_NORMAL_MAP_WORLD); + + return enm; +} + +ShaderEnum NormalMapNode::space_enum = normal_map_space_init(); + +NormalMapNode::NormalMapNode() +: ShaderNode("normal_map") +{ + space = ustring("Tangent"); + attribute = ustring(""); + + add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL); + add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f); + add_input("Color", SHADER_SOCKET_COLOR); + + add_output("Normal", SHADER_SOCKET_NORMAL); +} + +void NormalMapNode::attributes(AttributeRequestSet *attributes) +{ + if(space == ustring("Tangent")) { + if(attribute == ustring("")) { + attributes->add(ATTR_STD_UV_TANGENT); + attributes->add(ATTR_STD_UV_TANGENT_SIGN); + } + else { + attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str())); + attributes->add(ustring((string(attribute.c_str()) + ".tangent_sign").c_str())); + } + } + + ShaderNode::attributes(attributes); +} + +void NormalMapNode::compile(SVMCompiler& compiler) +{ + ShaderInput *color_in = input("Color"); + ShaderInput *strength_in = input("Strength"); + ShaderOutput *normal_out = output("Normal"); + int attr = 0, attr_sign = 0; + + if(space == ustring("Tangent")) { + if(attribute == ustring("")) { + attr = compiler.attribute(ATTR_STD_UV_TANGENT); + attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN); + } + else { + attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str())); + attr_sign = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent_sign").c_str())); + } + } + + compiler.stack_assign(color_in); + compiler.stack_assign(strength_in); + compiler.stack_assign(normal_out); + + compiler.add_node(NODE_NORMAL_MAP, + compiler.encode_uchar4( + color_in->stack_offset, + strength_in->stack_offset, + normal_out->stack_offset, + space_enum[space]), + attr, attr_sign); +} + +void NormalMapNode::compile(OSLCompiler& compiler) +{ + if(space == ustring("Tangent")) { + if(attribute == ustring("")) { + compiler.parameter("attr_name", ustring("geom:tangent")); + compiler.parameter("attr_sign_name", ustring("geom:tangent_sign")); + } + else { + compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str())); + compiler.parameter("attr_sign_name", ustring((string(attribute.c_str()) + ".tangent_sign").c_str())); + } + } + + compiler.parameter("space", space); + + compiler.add(this, "node_normal_map"); +} + +/* Tangent */ + +static ShaderEnum tangent_direction_type_init() +{ + ShaderEnum enm; + + enm.insert("Radial", NODE_TANGENT_RADIAL); + enm.insert("UV Map", NODE_TANGENT_UVMAP); + + return enm; +} + +static ShaderEnum tangent_axis_init() +{ + ShaderEnum enm; + + enm.insert("X", NODE_TANGENT_AXIS_X); + enm.insert("Y", NODE_TANGENT_AXIS_Y); + enm.insert("Z", NODE_TANGENT_AXIS_Z); + + return enm; +} + +ShaderEnum TangentNode::direction_type_enum = tangent_direction_type_init(); +ShaderEnum TangentNode::axis_enum = tangent_axis_init(); + +TangentNode::TangentNode() +: ShaderNode("normal_map") +{ + direction_type = ustring("Radial"); + axis = ustring("X"); + attribute = ustring(""); + + add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL); + add_output("Tangent", SHADER_SOCKET_NORMAL); +} + +void TangentNode::attributes(AttributeRequestSet *attributes) +{ + if(direction_type == ustring("UV Map")) { + if(attribute == ustring("")) + attributes->add(ATTR_STD_UV_TANGENT); + else + attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str())); + } + else + attributes->add(ATTR_STD_GENERATED); + + ShaderNode::attributes(attributes); +} + +void TangentNode::compile(SVMCompiler& compiler) +{ + ShaderOutput *tangent_out = output("Tangent"); + int attr; + + if(direction_type == ustring("UV Map")) { + if(attribute == ustring("")) + attr = compiler.attribute(ATTR_STD_UV_TANGENT); + else + attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str())); + } + else + attr = compiler.attribute(ATTR_STD_GENERATED); + + compiler.stack_assign(tangent_out); + + compiler.add_node(NODE_TANGENT, + compiler.encode_uchar4( + tangent_out->stack_offset, + direction_type_enum[direction_type], + axis_enum[axis]), attr); +} + +void TangentNode::compile(OSLCompiler& compiler) +{ + if(direction_type == ustring("UV Map")) { + if(attribute == ustring("")) + compiler.parameter("attr_name", ustring("geom:tangent")); + else + compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str())); + } + + compiler.parameter("direction_type", direction_type); + compiler.parameter("axis", axis); + compiler.add(this, "node_tangent"); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index d90cae5f668..67733142dd1 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -36,6 +36,7 @@ public: Transform compute_transform(); bool skip(); void compile(SVMCompiler& compiler, int offset_in, int offset_out); + void compile(OSLCompiler &compiler); float3 translation; float3 rotation; @@ -67,11 +68,12 @@ public: ImageManager *image_manager; int slot; - bool is_float; + int is_float; string filename; ustring color_space; ustring projection; float projection_blend; + bool animated; static ShaderEnum color_space_enum; static ShaderEnum projection_enum; @@ -85,10 +87,11 @@ public: ImageManager *image_manager; int slot; - bool is_float; + int is_float; string filename; ustring color_space; ustring projection; + bool animated; static ShaderEnum color_space_enum; static ShaderEnum projection_enum; @@ -240,6 +243,14 @@ public: static ShaderEnum distribution_enum; }; +class RefractionBsdfNode : public BsdfNode { +public: + SHADER_NODE_CLASS(RefractionBsdfNode) + + ustring distribution; + static ShaderEnum distribution_enum; +}; + class EmissionNode : public ShaderNode { public: SHADER_NODE_CLASS(EmissionNode) @@ -257,6 +268,11 @@ public: SHADER_NODE_CLASS(HoldoutNode) }; +class AmbientOcclusionNode : public ShaderNode { +public: + SHADER_NODE_CLASS(AmbientOcclusionNode) +}; + class VolumeNode : public ShaderNode { public: SHADER_NODE_CLASS(VolumeNode) @@ -335,6 +351,11 @@ public: SHADER_NODE_CLASS(MixClosureNode) }; +class MixClosureWeightNode : public ShaderNode { +public: + SHADER_NODE_CLASS(MixClosureWeightNode); +}; + class InvertNode : public ShaderNode { public: SHADER_NODE_CLASS(InvertNode) @@ -457,6 +478,31 @@ public: vector output_names; }; +class NormalMapNode : public ShaderNode { +public: + SHADER_NODE_CLASS(NormalMapNode) + void attributes(AttributeRequestSet *attributes); + + ustring space; + static ShaderEnum space_enum; + + ustring attribute; +}; + +class TangentNode : public ShaderNode { +public: + SHADER_NODE_CLASS(TangentNode) + void attributes(AttributeRequestSet *attributes); + + ustring direction_type; + static ShaderEnum direction_type_enum; + + ustring axis; + static ShaderEnum axis_enum; + + ustring attribute; +}; + CCL_NAMESPACE_END #endif /* __NODES_H__ */ diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 25b4d1f08cc..bd9f16d64ef 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -56,7 +56,7 @@ void Object::compute_bounds(bool motion_blur, float shuttertime) BoundBox mbounds = mesh->bounds; if(motion_blur && use_motion) { - MotionTransform decomp; + DecompMotionTransform decomp; transform_motion_decompose(&decomp, &motion, &tfm); bounds = BoundBox::empty; @@ -148,10 +148,9 @@ ObjectManager::~ObjectManager() { } -void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) +void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, uint *object_flag, Progress& progress) { float4 *objects = dscene->objects.resize(OBJECT_SIZE*scene->objects.size()); - uint *object_flag = dscene->object_flag.resize(scene->objects.size()); int i = 0; map surface_area_map; Scene::MotionType need_motion = scene->need_motion(device->info.advanced_shading); @@ -222,29 +221,29 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene mtfm_post = mtfm_post * itfm; memcpy(&objects[offset+8], &mtfm_pre, sizeof(float4)*4); - memcpy(&objects[offset+16], &mtfm_post, sizeof(float4)*4); + memcpy(&objects[offset+12], &mtfm_post, sizeof(float4)*4); } #ifdef __OBJECT_MOTION__ else if(need_motion == Scene::MOTION_BLUR) { if(ob->use_motion) { /* decompose transformations for interpolation */ - MotionTransform decomp; + DecompMotionTransform decomp; transform_motion_decompose(&decomp, &ob->motion, &ob->tfm); - memcpy(&objects[offset+8], &decomp, sizeof(float4)*12); + memcpy(&objects[offset+8], &decomp, sizeof(float4)*8); flag |= SD_OBJECT_MOTION; have_motion = true; } else { float4 no_motion = make_float4(FLT_MAX); - memcpy(&objects[offset+8], &no_motion, sizeof(float4)*12); + memcpy(&objects[offset+8], &no_motion, sizeof(float4)*8); } } #endif /* dupli object coords */ - objects[offset+20] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f); - objects[offset+21] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f); + objects[offset+16] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f); + objects[offset+17] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f); /* object flag */ if(ob->use_holdout) @@ -257,7 +256,6 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene } device->tex_alloc("__objects", dscene->objects); - device->tex_alloc("__object_flag", dscene->object_flag); dscene->data.bvh.have_motion = have_motion; } @@ -272,9 +270,12 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc if(scene->objects.size() == 0) return; + /* object info flag */ + uint *object_flag = dscene->object_flag.resize(scene->objects.size()); + /* set object transform matrices, before applying static transforms */ progress.set_status("Updating Objects", "Copying Transformations to device"); - device_update_transforms(device, dscene, scene, progress); + device_update_transforms(device, dscene, scene, object_flag, progress); if(progress.get_cancel()) return; @@ -282,10 +283,11 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc /* todo: do before to support getting object level coords? */ if(scene->params.bvh_type == SceneParams::BVH_STATIC) { progress.set_status("Updating Objects", "Applying Static Transformations"); - apply_static_transforms(scene, progress); + apply_static_transforms(scene, object_flag, progress); } - if(progress.get_cancel()) return; + /* allocate object flag */ + device->tex_alloc("__object_flag", dscene->object_flag); need_update = false; } @@ -299,7 +301,7 @@ void ObjectManager::device_free(Device *device, DeviceScene *dscene) dscene->object_flag.clear(); } -void ObjectManager::apply_static_transforms(Scene *scene, Progress& progress) +void ObjectManager::apply_static_transforms(Scene *scene, uint *object_flag, Progress& progress) { /* todo: normals and displacement should be done before applying transform! */ /* todo: create objects/meshes in right order! */ @@ -312,6 +314,7 @@ void ObjectManager::apply_static_transforms(Scene *scene, Progress& progress) #else bool motion_blur = false; #endif + int i = 0; foreach(Object *object, scene->objects) { map::iterator it = mesh_users.find(object->mesh); @@ -334,8 +337,12 @@ void ObjectManager::apply_static_transforms(Scene *scene, Progress& progress) if(progress.get_cancel()) return; } + + object_flag[i] |= SD_TRANSFORM_APPLIED; } } + + i++; } } diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index 922c886d961..9c9b11bc29c 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -73,12 +73,12 @@ public: ~ObjectManager(); void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); - void device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); + void device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, uint *object_flag, Progress& progress); void device_free(Device *device, DeviceScene *dscene); void tag_update(Scene *scene); - void apply_static_transforms(Scene *scene, Progress& progress); + void apply_static_transforms(Scene *scene, uint *object_flag, Progress& progress); }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index a8a40a4e596..e4ee40d881e 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -79,20 +79,19 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene if(shader->sample_as_light && shader->has_surface_emission) scene->light_manager->need_update = true; - OSLCompiler compiler((void*)this, (void*)ss); + OSLCompiler compiler((void*)this, (void*)ss, scene->image_manager); compiler.background = (shader == scene->shaders[scene->default_background]); compiler.compile(og, shader); } /* setup shader engine */ og->ss = ss; + og->ts = ts; og->services = services; int background_id = scene->shader_manager->get_shader_id(scene->default_background); og->background_state = og->surface_state[background_id & SHADER_MASK]; og->use = true; - tls_create(OSLGlobals::ThreadData, og->thread_data); - foreach(Shader *shader, scene->shaders) shader->need_update = false; @@ -113,8 +112,7 @@ void OSLShaderManager::device_free(Device *device, DeviceScene *dscene) /* clear shader engine */ og->use = false; og->ss = NULL; - - tls_delete(OSLGlobals::ThreadData, og->thread_data); + og->ts = NULL; og->surface_state.clear(); og->volume_state.clear(); @@ -128,6 +126,7 @@ void OSLShaderManager::texture_system_init() ts = TextureSystem::create(true); ts->attribute("automip", 1); ts->attribute("autotile", 64); + ts->attribute("gray_to_rgb", 1); /* effectively unlimited for now, until we support proper mipmap lookups */ ts->attribute("max_memory_MB", 16384); @@ -159,7 +158,7 @@ void OSLShaderManager::shading_system_init() const int nraytypes = sizeof(raytypes)/sizeof(raytypes[0]); ss->attribute("raytypes", TypeDesc(TypeDesc::STRING, nraytypes), raytypes); - OSLShader::register_closures(ss); + OSLShader::register_closures((OSLShadingSystem*)ss); loaded_shaders.clear(); } @@ -278,10 +277,11 @@ const char *OSLShaderManager::shader_load_bytecode(const string& hash, const str /* Graph Compiler */ -OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_) +OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_, ImageManager *image_manager_) { manager = manager_; shadingsys = shadingsys_; + image_manager = image_manager_; current_type = SHADER_TYPE_SURFACE; current_shader = NULL; background = false; @@ -325,7 +325,7 @@ string OSLCompiler::compatible_name(ShaderNode *node, ShaderOutput *output) while((i = sname.find(" ")) != string::npos) sname.replace(i, 1, ""); - /* if output exists with the same name, add "In" suffix */ + /* if input exists with the same name, add "Out" suffix */ foreach(ShaderInput *input, node->inputs) { if (strcmp(input->name, output->name)==0) { sname += "Out"; @@ -340,6 +340,9 @@ bool OSLCompiler::node_skip_input(ShaderNode *node, ShaderInput *input) { /* exception for output node, only one input is actually used * depending on the current shader type */ + + if(!(input->usage & ShaderInput::USE_OSL)) + return true; if(node->name == ustring("output")) { if(strcmp(input->name, "Surface") == 0 && current_type != SHADER_TYPE_SURFACE) @@ -403,6 +406,9 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath) case SHADER_SOCKET_INT: parameter(param_name.c_str(), (int)input->value.x); break; + case SHADER_SOCKET_STRING: + parameter(param_name.c_str(), input->value_string); + break; case SHADER_SOCKET_CLOSURE: break; } diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h index cee37c58d74..9b58745bd46 100644 --- a/intern/cycles/render/osl.h +++ b/intern/cycles/render/osl.h @@ -52,6 +52,8 @@ public: OSLShaderManager(); ~OSLShaderManager(); + bool use_osl() { return true; } + void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_free(Device *device, DeviceScene *dscene); @@ -81,7 +83,7 @@ protected: class OSLCompiler { public: - OSLCompiler(void *manager, void *shadingsys); + OSLCompiler(void *manager, void *shadingsys, ImageManager *image_manager); void compile(OSLGlobals *og, Shader *shader); void add(ShaderNode *node, const char *name, bool isfilepath = false); @@ -108,6 +110,7 @@ public: ShaderType output_type() { return current_type; } bool background; + ImageManager *image_manager; private: string id(ShaderNode *node); diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp index 9f951d9673f..2a1570f7a0d 100644 --- a/intern/cycles/render/particles.cpp +++ b/intern/cycles/render/particles.cpp @@ -57,8 +57,7 @@ void ParticleSystemManager::device_update_particles(Device *device, DeviceScene { /* count particles. * adds one dummy particle at the beginning to avoid invalid lookups, - * in case a shader uses particle info without actual particle data. - */ + * in case a shader uses particle info without actual particle data. */ int num_particles = 1; foreach(ParticleSystem *psys, scene->particle_systems) num_particles += psys->particles.size(); diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 15031b9500c..8085cfdd3e6 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -53,42 +53,25 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_) object_manager = new ObjectManager(); integrator = new Integrator(); image_manager = new ImageManager(); - shader_manager = ShaderManager::create(this); particle_system_manager = new ParticleSystemManager(); + /* OSL only works on the CPU */ + if(device_info_.type == DEVICE_CPU) + shader_manager = ShaderManager::create(this, params.shadingsystem); + else + shader_manager = ShaderManager::create(this, SceneParams::SVM); + if (device_info_.type == DEVICE_CPU) image_manager->set_extended_image_limits(); } Scene::~Scene() { - if(device) camera->device_free(device, &dscene); - delete camera; - - if(device) filter->device_free(device, &dscene); - delete filter; - - if(device) film->device_free(device, &dscene); - delete film; - - if(device) background->device_free(device, &dscene); - delete background; - - if(device) mesh_manager->device_free(device, &dscene); - delete mesh_manager; - - if(device) object_manager->device_free(device, &dscene); - delete object_manager; - - if(device) integrator->device_free(device, &dscene); - delete integrator; - - if(device) shader_manager->device_free(device, &dscene); - delete shader_manager; - - if(device) light_manager->device_free(device, &dscene); - delete light_manager; + free_memory(true); +} +void Scene::free_memory(bool final) +{ foreach(Shader *s, shaders) delete s; foreach(Mesh *m, meshes) @@ -100,11 +83,44 @@ Scene::~Scene() foreach(ParticleSystem *p, particle_systems) delete p; - if(device) image_manager->device_free(device, &dscene); - delete image_manager; + if(device) { + camera->device_free(device, &dscene); + filter->device_free(device, &dscene); + film->device_free(device, &dscene); + background->device_free(device, &dscene); + integrator->device_free(device, &dscene); - if(device) particle_system_manager->device_free(device, &dscene); - delete particle_system_manager; + object_manager->device_free(device, &dscene); + mesh_manager->device_free(device, &dscene); + shader_manager->device_free(device, &dscene); + light_manager->device_free(device, &dscene); + + particle_system_manager->device_free(device, &dscene); + + if(!params.persistent_images || final) + image_manager->device_free(device, &dscene); + } + + if(final) { + delete filter; + delete camera; + delete film; + delete background; + delete integrator; + delete object_manager; + delete mesh_manager; + delete shader_manager; + delete light_manager; + delete particle_system_manager; + delete image_manager; + } + else { + shaders.clear(); + meshes.clear(); + objects.clear(); + lights.clear(); + particle_systems.clear(); + } } void Scene::device_update(Device *device_, Progress& progress) @@ -229,5 +245,22 @@ bool Scene::need_reset() || particle_system_manager->need_update); } +void Scene::reset() +{ + shader_manager->add_default(this); + + /* ensure all objects are updated */ + camera->tag_update(); + filter->tag_update(this); + film->tag_update(this); + background->tag_update(this); + integrator->tag_update(this); +} + +void Scene::device_free() +{ + free_memory(false); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index bd45c1c04e6..92ef692b4b9 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -120,6 +120,7 @@ public: bool use_bvh_cache; bool use_bvh_spatial_split; bool use_qbvh; + bool persistent_images; SceneParams() { @@ -139,7 +140,8 @@ public: && bvh_type == params.bvh_type && use_bvh_cache == params.use_bvh_cache && use_bvh_spatial_split == params.use_bvh_spatial_split - && use_qbvh == params.use_qbvh); } + && use_qbvh == params.use_qbvh + && persistent_images == params.persistent_images); } }; /* Scene */ @@ -198,6 +200,12 @@ public: bool need_update(); bool need_reset(); + + void reset(); + void device_free(); + +protected: + void free_memory(bool final); }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 7303cb52ad8..1d1a3d54893 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -49,7 +49,7 @@ Session::Session(const SessionParams& params_) TaskScheduler::init(params.threads); - device = Device::create(params.device, stats, params.background, params.threads); + device = Device::create(params.device, stats, params.background); if(params.background) { buffers = NULL; @@ -637,6 +637,15 @@ void Session::reset(BufferParams& buffer_params, int samples) reset_gpu(buffer_params, samples); else reset_cpu(buffer_params, samples); + + if(params.progressive_refine) { + thread_scoped_lock buffers_lock(buffers_mutex); + + foreach(RenderBuffers *buffers, tile_buffers) + delete buffers; + + tile_buffers.clear(); + } } void Session::set_samples(int samples) @@ -757,7 +766,7 @@ void Session::update_status_time(bool show_pause, bool show_done) if(preview_time == 0.0 && resolution == 1) preview_time = time_dt(); - double tile_time = (tile == 0)? 0.0: (time_dt() - preview_time - paused_time)/(sample); + double tile_time = (tile == 0 || sample == 0)? 0.0: (time_dt() - preview_time - paused_time) / sample; /* negative can happen when we pause a bit before rendering, can discard that */ if(preview_time < 0.0) preview_time = 0.0; @@ -818,7 +827,7 @@ bool Session::update_progressive_refine(bool cancel) double current_time = time_dt(); - if (current_time - last_update_time < 1.0f) { + if (current_time - last_update_time < 1.0) { /* if last sample was processed, we need to write buffers anyway */ if (!write) return false; @@ -842,4 +851,18 @@ bool Session::update_progressive_refine(bool cancel) return write; } +void Session::device_free() +{ + scene->device_free(); + + foreach(RenderBuffers *buffers, tile_buffers) + delete buffers; + + tile_buffers.clear(); + + /* used from background render only, so no need to + * re-create render/display buffers here + */ +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 7bb0cd1ae01..cfc1502287d 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -130,6 +130,7 @@ public: void set_samples(int samples); void set_pause(bool pause); + void device_free(); protected: struct DelayedReset { thread_mutex mutex; diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 17f7fbd43d6..b9b49bf2989 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -121,12 +121,12 @@ ShaderManager::~ShaderManager() { } -ShaderManager *ShaderManager::create(Scene *scene) +ShaderManager *ShaderManager::create(Scene *scene, int shadingsystem) { ShaderManager *manager; #ifdef WITH_OSL - if(scene->params.shadingsystem == SceneParams::OSL) + if(shadingsystem == SceneParams::OSL) manager = new OSLShaderManager(); else #endif diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index 373b3356f51..d4421002ceb 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -107,9 +107,11 @@ class ShaderManager { public: bool need_update; - static ShaderManager *create(Scene *scene); + static ShaderManager *create(Scene *scene, int shadingsystem); virtual ~ShaderManager(); + virtual bool use_osl() { return false; } + /* device update */ virtual void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) = 0; virtual void device_free(Device *device, DeviceScene *dscene) = 0; diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index dc249984499..4acd174e60f 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -487,56 +487,28 @@ void SVMCompiler::generate_closure(ShaderNode *node, set& done) } } -void SVMCompiler::generate_multi_closure(ShaderNode *node, set& done, uint in_offset) +void SVMCompiler::generate_multi_closure(ShaderNode *node, set& done, set& closure_done) { /* todo: the weaks point here is that unlike the single closure sampling * we will evaluate all nodes even if they are used as input for closures * that are unused. it's not clear what would be the best way to skip such * nodes at runtime, especially if they are tangled up */ + + /* only generate once */ + if(closure_done.find(node) != closure_done.end()) + return; + + closure_done.insert(node); if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) { - ShaderInput *fin = node->input("Fac"); + /* weighting is already taken care of in ShaderGraph::transform_multi_closure */ ShaderInput *cl1in = node->input("Closure1"); ShaderInput *cl2in = node->input("Closure2"); - uint out1_offset = SVM_STACK_INVALID; - uint out2_offset = SVM_STACK_INVALID; - - if(fin) { - /* mix closure */ - set dependencies; - find_dependencies(dependencies, done, fin); - generate_svm_nodes(dependencies, done); - - stack_assign(fin); - - if(cl1in->link) - out1_offset = stack_find_offset(SHADER_SOCKET_FLOAT); - if(cl2in->link) - out2_offset = stack_find_offset(SHADER_SOCKET_FLOAT); - - add_node(NODE_MIX_CLOSURE, - encode_uchar4(fin->stack_offset, in_offset, out1_offset, out2_offset)); - } - else { - /* add closure */ - out1_offset = in_offset; - out2_offset = in_offset; - } - - if(cl1in->link) { - generate_multi_closure(cl1in->link->parent, done, out1_offset); - - if(fin) - stack_clear_offset(SHADER_SOCKET_FLOAT, out1_offset); - } - - if(cl2in->link) { - generate_multi_closure(cl2in->link->parent, done, out2_offset); - - if(fin) - stack_clear_offset(SHADER_SOCKET_FLOAT, out2_offset); - } + if(cl1in->link) + generate_multi_closure(cl1in->link->parent, done, closure_done); + if(cl2in->link) + generate_multi_closure(cl2in->link->parent, done, closure_done); } else { /* execute dependencies for closure */ @@ -548,7 +520,16 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set& don } } - mix_weight_offset = in_offset; + /* closure mix weight */ + const char *weight_name = (current_type == SHADER_TYPE_VOLUME)? "VolumeMixWeight": "SurfaceMixWeight"; + ShaderInput *weight_in = node->input(weight_name); + + if(weight_in && (weight_in->link || weight_in->value.x != 1.0f)) { + stack_assign(weight_in); + mix_weight_offset = weight_in->stack_offset; + } + else + mix_weight_offset = SVM_STACK_INVALID; /* compile closure itself */ node->compile(*this); @@ -561,9 +542,9 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set& don current_shader->has_surface_emission = true; if(node->name == ustring("transparent")) current_shader->has_surface_transparent = true; - - /* end node is added outside of this */ } + + done.insert(node); } @@ -634,8 +615,10 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty if(generate) { set done; - if(use_multi_closure) - generate_multi_closure(clin->link->parent, done, SVM_STACK_INVALID); + if(use_multi_closure) { + set closure_done; + generate_multi_closure(clin->link->parent, done, closure_done); + } else generate_closure(clin->link->parent, done); } @@ -658,9 +641,9 @@ void SVMCompiler::compile(Shader *shader, vector& global_svm_nodes, int in shader->graph_bump = shader->graph->copy(); /* finalize */ - shader->graph->finalize(false, false); + shader->graph->finalize(false, false, use_multi_closure); if(shader->graph_bump) - shader->graph_bump->finalize(true, false); + shader->graph_bump->finalize(true, false, use_multi_closure); current_shader = shader; diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h index 0db68f400fc..0b15c5aaa1e 100644 --- a/intern/cycles/render/svm.h +++ b/intern/cycles/render/svm.h @@ -81,6 +81,7 @@ public: bool background; protected: + /* stack */ struct Stack { Stack() { memset(users, 0, sizeof(users)); } Stack(const Stack& other) { memcpy(users, other.users, sizeof(users)); } @@ -123,11 +124,15 @@ protected: bool node_skip_input(ShaderNode *node, ShaderInput *input); + /* single closure */ void find_dependencies(set& dependencies, const set& done, ShaderInput *input); void generate_svm_nodes(const set& nodes, set& done); void generate_closure(ShaderNode *node, set& done); - void generate_multi_closure(ShaderNode *node, set& done, uint in_offset); + /* multi closure */ + void generate_multi_closure(ShaderNode *node, set& done, set& closure_done); + + /* compile */ void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type); vector svm_nodes; diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt index bf5f791a245..dce417704cc 100644 --- a/intern/cycles/util/CMakeLists.txt +++ b/intern/cycles/util/CMakeLists.txt @@ -54,6 +54,7 @@ set(SRC_HEADERS util_path.h util_progress.h util_set.h + util_stats.h util_string.h util_system.h util_task.h @@ -61,8 +62,8 @@ set(SRC_HEADERS util_time.h util_transform.h util_types.h - util_view.h util_vector.h + util_view.h util_xml.h ) diff --git a/intern/cycles/util/util_attribute.cpp b/intern/cycles/util/util_attribute.cpp index 163a92902f3..057fb6213e9 100644 --- a/intern/cycles/util/util_attribute.cpp +++ b/intern/cycles/util/util_attribute.cpp @@ -30,8 +30,10 @@ const char *attribute_standard_name(AttributeStandard std) return "uv"; else if(std == ATTR_STD_GENERATED) return "generated"; - else if(std == ATTR_STD_TANGENT) + else if(std == ATTR_STD_UV_TANGENT) return "tangent"; + else if(std == ATTR_STD_UV_TANGENT_SIGN) + return "tangent_sign"; else if(std == ATTR_STD_POSITION_UNDEFORMED) return "undeformed"; else if(std == ATTR_STD_POSITION_UNDISPLACED) diff --git a/intern/cycles/util/util_boundbox.h b/intern/cycles/util/util_boundbox.h index b35c4c12bb8..6dd1c6c71e8 100644 --- a/intern/cycles/util/util_boundbox.h +++ b/intern/cycles/util/util_boundbox.h @@ -31,6 +31,8 @@ using namespace std; CCL_NAMESPACE_BEGIN +/* 3D BoundBox */ + class BoundBox { public: @@ -160,6 +162,85 @@ __forceinline BoundBox intersect(const BoundBox& a, const BoundBox& b, const Bou return intersect(a, intersect(b, c)); } +/* 2D BoundBox */ + +class BoundBox2D { +public: + float left; + float right; + float bottom; + float top; + + BoundBox2D() + : left(0.0f), right(1.0f), bottom(0.0f), top(1.0f) + { + } + + bool operator==(const BoundBox2D& other) const + { + return (left == other.left && right == other.right && + bottom == other.bottom && top == other.top); + } + + float width() + { + return right - left; + } + + float height() + { + return top - bottom; + } + + BoundBox2D operator*(float f) const + { + BoundBox2D result; + + result.left = left*f; + result.right = right*f; + result.bottom = bottom*f; + result.top = top*f; + + return result; + } + + BoundBox2D subset(const BoundBox2D& other) const + { + BoundBox2D subset; + + subset.left = left + other.left*(right - left); + subset.right = left + other.right*(right - left); + subset.bottom = bottom + other.bottom*(top - bottom); + subset.top = bottom + other.top*(top - bottom); + + return subset; + } + + BoundBox2D make_relative_to(const BoundBox2D& other) const + { + BoundBox2D result; + + result.left = ((left - other.left) / (other.right - other.left)); + result.right = ((right - other.left) / (other.right - other.left)); + result.bottom = ((bottom - other.bottom) / (other.top - other.bottom)); + result.top = ((top - other.bottom) / (other.top - other.bottom)); + + return result; + } + + BoundBox2D clamp(float mn = 0.0f, float mx = 1.0f) + { + BoundBox2D result; + + result.left = ccl::clamp(left, mn, mx); + result.right = ccl::clamp(right, mn, mx); + result.bottom = ccl::clamp(bottom, mn, mx); + result.top = ccl::clamp(top, mn, mx); + + return result; + } +}; + CCL_NAMESPACE_END #endif /* __UTIL_BOUNDBOX_H__ */ diff --git a/intern/cycles/util/util_opencl.cpp b/intern/cycles/util/util_opencl.cpp index 40b637f5cb7..c146c14b10c 100644 --- a/intern/cycles/util/util_opencl.cpp +++ b/intern/cycles/util/util_opencl.cpp @@ -140,6 +140,10 @@ int clLibraryInit() #endif int error = 0; + // OpenCL disabled for now, only works with this environment variable set + if(!getenv("CYCLES_OPENCL_TEST")) + return 0; + // Check if already initialized if (module != NULL) { diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h index c97379d8776..03e25d4d132 100644 --- a/intern/cycles/util/util_progress.h +++ b/intern/cycles/util/util_progress.h @@ -68,6 +68,21 @@ public: return *this; } + void reset() + { + tile = 0; + sample = 0; + start_time = time_dt(); + total_time = 0.0f; + tile_time = 0.0f; + status = "Initializing"; + substatus = ""; + sync_status = ""; + sync_substatus = ""; + cancel = false; + cancel_message = ""; + } + /* cancel */ void set_cancel(const string& cancel_message_) { diff --git a/intern/cycles/util/util_stats.h b/intern/cycles/util/util_stats.h index 405c81a1e1f..27638015f40 100644 --- a/intern/cycles/util/util_stats.h +++ b/intern/cycles/util/util_stats.h @@ -19,31 +19,22 @@ #ifndef __UTIL_STATS_H__ #define __UTIL_STATS_H__ -#include "util_thread.h" - CCL_NAMESPACE_BEGIN class Stats { public: - Stats() : lock(), mem_used(0), mem_peak(0) {} + Stats() : mem_used(0), mem_peak(0) {} void mem_alloc(size_t size) { - lock.lock(); - mem_used += size; if(mem_used > mem_peak) mem_peak = mem_used; - - lock.unlock(); } void mem_free(size_t size) { - lock.lock(); mem_used -= size; - lock.unlock(); } - spin_lock lock; size_t mem_used; size_t mem_peak; }; diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp index ea0abd6f54f..8c4ec312256 100644 --- a/intern/cycles/util/util_task.cpp +++ b/intern/cycles/util/util_task.cpp @@ -168,10 +168,16 @@ void TaskScheduler::init(int num_threads) if(users == 0) { do_exit = false; - /* launch threads that will be waiting for work */ - if(num_threads == 0) + if(num_threads == 0) { + /* automatic number of threads will be main thread + num cores */ num_threads = system_cpu_thread_count(); + } + else { + /* main thread will also work, for fixed threads we count it too */ + num_threads -= 1; + } + /* launch threads that will be waiting for work */ threads.resize(num_threads); thread_level.resize(num_threads); diff --git a/intern/cycles/util/util_task.h b/intern/cycles/util/util_task.h index a2f284479c7..b795ca7524b 100644 --- a/intern/cycles/util/util_task.h +++ b/intern/cycles/util/util_task.h @@ -94,7 +94,10 @@ public: static void init(int num_threads = 0); static void exit(); - static int num_threads() { return threads.size(); } + /* number of threads that can work on tasks, main thread counts too */ + static int num_threads() { return threads.size() + 1; } + + /* test if any session is using the scheduler */ static bool active() { return users != 0; } protected: diff --git a/intern/cycles/util/util_thread.h b/intern/cycles/util/util_thread.h index 6d1bd0023a7..d7e9ec03df3 100644 --- a/intern/cycles/util/util_thread.h +++ b/intern/cycles/util/util_thread.h @@ -33,9 +33,6 @@ typedef boost::mutex thread_mutex; typedef boost::mutex::scoped_lock thread_scoped_lock; typedef boost::condition_variable thread_condition_variable; -/* use boost for spinlocks as well */ -typedef boost::detail::spinlock spin_lock; - /* own pthread based implementation, to avoid boost version conflicts with * dynamically loaded blender plugins */ @@ -73,41 +70,6 @@ protected: bool joined; }; -/* Thread Local Storage - * - * Boost implementation is a bit slow, and Mac OS X __thread is not supported - * but the pthreads implementation is optimized, so we use these macros. */ - -#ifdef __APPLE__ - -#define tls_ptr(type, name) \ - pthread_key_t name -#define tls_set(name, value) \ - pthread_setspecific(name, value) -#define tls_get(type, name) \ - ((type*)pthread_getspecific(name)) -#define tls_create(type, name) \ - pthread_key_create(&name, NULL) -#define tls_delete(type, name) \ - pthread_key_delete(name); - -#else - -#ifdef __WIN32 -#define __thread __declspec(thread) -#endif - -#define tls_ptr(type, name) \ - __thread type *name -#define tls_set(name, value) \ - name = value -#define tls_get(type, name) \ - name -#define tls_create(type, name) -#define tls_delete(type, name) - -#endif - CCL_NAMESPACE_END #endif /* __UTIL_THREAD_H__ */ diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp index 70ee13d96d7..ca19146e125 100644 --- a/intern/cycles/util/util_transform.cpp +++ b/intern/cycles/util/util_transform.cpp @@ -246,11 +246,30 @@ static void transform_decompose(Transform *decomp, const Transform *tfm) decomp->w = make_float4(scale.y.z, scale.z.x, scale.z.y, scale.z.z); } -void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid) +void transform_motion_decompose(DecompMotionTransform *decomp, const MotionTransform *motion, const Transform *mid) { - transform_decompose(&decomp->pre, &motion->pre); + Transform pre, post; + + transform_decompose(&pre, &motion->pre); transform_decompose(&decomp->mid, mid); - transform_decompose(&decomp->post, &motion->post); + transform_decompose(&post, &motion->post); + + /* ensure rotation around shortest angle, negated quaternions are the same + * but this means we don't have to do the check in quat_interpolate */ + if(dot(decomp->mid.x, post.x) < 0.0f) + decomp->mid.x = -decomp->mid.x; + if(dot(pre.x, decomp->mid.x) < 0.0f) + pre.x = -pre.x; + + /* drop scale of pre/post */ + pre.y.w = decomp->mid.y.w; + post.y.w = decomp->mid.y.w; + + /* store translation/rotation part of pre/post */ + decomp->pre_x = pre.x; + decomp->pre_y = pre.y; + decomp->post_x = post.x; + decomp->post_y = post.y; } CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h index df525542207..a1c12ddf0e1 100644 --- a/intern/cycles/util/util_transform.h +++ b/intern/cycles/util/util_transform.h @@ -39,15 +39,23 @@ typedef struct Transform { #endif } Transform; +/* transform decomposed in rotation/translation/scale. we use the same data + * structure as Transform, and tightly pack decomposition into it. first the + * rotation (4), then translation (3), then 3x3 scale matrix (9). + * + * For the DecompMotionTransform we drop scale from pre/post. */ + typedef struct MotionTransform { Transform pre; Transform mid; Transform post; } MotionTransform; -/* transform decomposed in rotation/translation/scale. we use the same data - * structure as Transform, and tightly pack decomposition into it. first the - * rotation (4), then translation (3), then 3x3 scale matrix (9) */ +typedef struct DecompMotionTransform { + Transform mid; + float4 pre_x, pre_y; + float4 post_x, post_y; +} DecompMotionTransform; /* Functions */ @@ -303,13 +311,15 @@ __device_inline Transform transform_clear_scale(const Transform& tfm) __device_inline float4 quat_interpolate(float4 q1, float4 q2, float t) { + /* use simpe nlerp instead of slerp. it's faster and almost the same */ + return normalize((1.0f - t)*q1 + t*q2); + +#if 0 + /* note: this does not ensure rotation around shortest angle, q1 and q2 + * are assumed to be matched already in transform_motion_decompose */ float costheta = dot(q1, q2); - /* rotate around shortest angle */ - if(costheta < 0.0f) { - costheta = -costheta; - q1 = -q1; - } + /* possible optimization: it might be possible to precompute theta/qperp */ if(costheta > 0.9995f) { /* linear interpolation in degenerate case */ @@ -318,14 +328,18 @@ __device_inline float4 quat_interpolate(float4 q1, float4 q2, float t) else { /* slerp */ float theta = acosf(clamp(costheta, -1.0f, 1.0f)); - float thetap = theta * t; float4 qperp = normalize(q2 - q1 * costheta); + float thetap = theta * t; return q1 * cosf(thetap) + qperp * sinf(thetap); } +#endif } __device_inline Transform transform_quick_inverse(Transform M) { + /* possible optimization: can we avoid doing this altogether and construct + * the inverse matrix directly from negated translation, transposed rotation, + * scale can be inverted but what about shearing? */ Transform R; float det = M.x.x*(M.z.z*M.y.y - M.z.y*M.y.z) - M.y.x*(M.z.z*M.x.y - M.z.y*M.x.z) + M.z.x*(M.y.z*M.x.y - M.y.y*M.x.z); @@ -380,14 +394,21 @@ __device_inline void transform_compose(Transform *tfm, const Transform *decomp) tfm->w = make_float4(0.0f, 0.0f, 0.0f, 1.0f); } -__device void transform_motion_interpolate(Transform *tfm, const MotionTransform *motion, float t) +/* Disabled for now, need arc-length parametrization for constant speed motion. + * #define CURVED_MOTION_INTERPOLATE */ + +__device void transform_motion_interpolate(Transform *tfm, const DecompMotionTransform *motion, float t) { + /* possible optimization: is it worth it adding a check to skip scaling? + * it's probably quite uncommon to have scaling objects. or can we skip + * just shearing perhaps? */ Transform decomp; +#ifdef CURVED_MOTION_INTERPOLATE /* 3 point bezier curve interpolation for position */ - float3 Ppre = float4_to_float3(motion->pre.y); + float3 Ppre = float4_to_float3(motion->pre_y); float3 Pmid = float4_to_float3(motion->mid.y); - float3 Ppost = float4_to_float3(motion->post.y); + float3 Ppost = float4_to_float3(motion->post_y); float3 Pcontrol = 2.0f*Pmid - 0.5f*(Ppre + Ppost); float3 P = Ppre*t*t + Pcontrol*2.0f*t*(1.0f - t) + Ppost*(1.0f - t)*(1.0f - t); @@ -395,25 +416,33 @@ __device void transform_motion_interpolate(Transform *tfm, const MotionTransform decomp.y.x = P.x; decomp.y.y = P.y; decomp.y.z = P.z; +#endif /* linear interpolation for rotation and scale */ if(t < 0.5f) { t *= 2.0f; - decomp.x = quat_interpolate(motion->pre.x, motion->mid.x, t); - decomp.y.w = (1.0f - t)*motion->pre.y.w + t*motion->mid.y.w; - decomp.z = (1.0f - t)*motion->pre.z + t*motion->mid.z; - decomp.w = (1.0f - t)*motion->pre.w + t*motion->mid.w; + decomp.x = quat_interpolate(motion->pre_x, motion->mid.x, t); +#ifdef CURVED_MOTION_INTERPOLATE + decomp.y.w = (1.0f - t)*motion->pre_y.w + t*motion->mid.y.w; +#else + decomp.y = (1.0f - t)*motion->pre_y + t*motion->mid.y; +#endif } else { t = (t - 0.5f)*2.0f; - decomp.x = quat_interpolate(motion->mid.x, motion->post.x, t); - decomp.y.w = (1.0f - t)*motion->mid.y.w + t*motion->post.y.w; - decomp.z = (1.0f - t)*motion->mid.z + t*motion->post.z; - decomp.w = (1.0f - t)*motion->mid.w + t*motion->post.w; + decomp.x = quat_interpolate(motion->mid.x, motion->post_x, t); +#ifdef CURVED_MOTION_INTERPOLATE + decomp.y.w = (1.0f - t)*motion->mid.y.w + t*motion->post_y.w; +#else + decomp.y = (1.0f - t)*motion->mid.y + t*motion->post_y; +#endif } + decomp.z = motion->mid.z; + decomp.w = motion->mid.w; + /* compose rotation, translation, scale into matrix */ transform_compose(tfm, &decomp); } @@ -425,7 +454,7 @@ __device_inline bool operator==(const MotionTransform& A, const MotionTransform& return (A.pre == B.pre && A.post == B.post); } -void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid); +void transform_motion_decompose(DecompMotionTransform *decomp, const MotionTransform *motion, const Transform *mid); #endif diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h index f2c02cadcbf..3d246104ddc 100644 --- a/intern/cycles/util/util_types.h +++ b/intern/cycles/util/util_types.h @@ -41,7 +41,9 @@ #define __align(...) __declspec(align(__VA_ARGS__)) #else #define __device_inline static inline __attribute__((always_inline)) +#ifndef FREE_WINDOWS64 #define __forceinline inline __attribute__((always_inline)) +#endif #define __align(...) __attribute__((aligned(__VA_ARGS__))) #endif @@ -449,7 +451,8 @@ typedef enum AttributeStandard { ATTR_STD_VERTEX_NORMAL, ATTR_STD_FACE_NORMAL, ATTR_STD_UV, - ATTR_STD_TANGENT, + ATTR_STD_UV_TANGENT, + ATTR_STD_UV_TANGENT_SIGN, ATTR_STD_GENERATED, ATTR_STD_POSITION_UNDEFORMED, ATTR_STD_POSITION_UNDISPLACED, diff --git a/intern/elbeem/intern/ntl_geometryobject.cpp b/intern/elbeem/intern/ntl_geometryobject.cpp index 4f640253f0f..1e08cb96a95 100644 --- a/intern/elbeem/intern/ntl_geometryobject.cpp +++ b/intern/elbeem/intern/ntl_geometryobject.cpp @@ -787,7 +787,7 @@ ntlVec3Gfx ntlGeometryObject::getTranslation(double t) { } /*! get active flag time t*/ float ntlGeometryObject::getGeoActive(double t) { - float act = mcGeoActive.get(t); // if <= 0.0 -> off + float act = (mcGeoActive.get(t) >= 1.) ? 1.0 : 0.0; return act; } diff --git a/intern/elbeem/intern/ntl_world.cpp b/intern/elbeem/intern/ntl_world.cpp index 0b36f724985..dcc81dbe5cb 100644 --- a/intern/elbeem/intern/ntl_world.cpp +++ b/intern/elbeem/intern/ntl_world.cpp @@ -143,6 +143,7 @@ void ntlWorld::initDefaults() mFirstSim = 1; mSingleStepDebug = false; mFrameCnt = 0; + mSimFrameCnt = 0; mpOpenGLRenderer = NULL; /* create scene storage */ @@ -406,7 +407,6 @@ int ntlWorld::advanceSims(int framenum) } for(size_t i=0;isize();i++) { (*mpSims)[i]->setFrameNum(framenum); } - double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getFrameTime(framenum); // time stopped? nothing else to do... if( (*mpSims)[mFirstSim]->getFrameTime(framenum) <= 0.0 ){ @@ -416,6 +416,13 @@ int ntlWorld::advanceSims(int framenum) (*mpSims)[mFirstSim]->checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0); } + // Prevent bug [#29186] Object contribute to fluid sim animation start earlier than keyframe + // Was: double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getFrameTime(framenum); - DG + double totalTime = 0.0, targetTime = 0.0; + for(size_t i = 0; i < mSimFrameCnt; i++) + totalTime += (*mpSims)[mFirstSim]->getFrameTime(framenum); + targetTime = totalTime + (*mpSims)[mFirstSim]->getFrameTime(framenum); + int gstate = 0; myTime_t advsstart = getTime(); @@ -461,6 +468,8 @@ int ntlWorld::advanceSims(int framenum) sim->prepareVisualization(); } + mSimFrameCnt++; + return 0; } diff --git a/intern/elbeem/intern/ntl_world.h b/intern/elbeem/intern/ntl_world.h index 3c5958477d4..c207904cf75 100644 --- a/intern/elbeem/intern/ntl_world.h +++ b/intern/elbeem/intern/ntl_world.h @@ -115,6 +115,9 @@ class ntlWorld /*! count no. of frame for viz render */ int mFrameCnt; + + /*! count no. of frame for correct sim time */ + int mSimFrameCnt; }; diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index e52ac0af2ed..ea09987c564 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -189,7 +189,6 @@ elseif(APPLE) if(WITH_INPUT_NDOF) list(APPEND SRC intern/GHOST_NDOFManagerCocoa.mm - intern/GHOST_NDOFManagerCocoa.h ) endif() diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 87ab3c013c6..f886dfd9d7d 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -120,7 +120,7 @@ extern GHOST_TimerTaskHandle GHOST_InstallTimer(GHOST_SystemHandle systemhandle, /** * Removes a timer. * \param systemhandle The handle to the system - * \param timerTask Timer task to be removed. + * \param timertaskhandle Timer task to be removed. * \return Indication of success. */ extern GHOST_TSuccess GHOST_RemoveTimer(GHOST_SystemHandle systemhandle, @@ -185,7 +185,7 @@ extern GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandl /** * Changes the window user data. * \param windowhandle The handle to the window - * \param data The window user data. + * \param userdata The window user data. */ extern void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr userdata); @@ -212,6 +212,7 @@ extern int GHOST_ValidWindow(GHOST_SystemHandle systemhandle, * Begins full screen mode. * \param systemhandle The handle to the system * \param setting The new setting of the display. + * \param stereoVisual Option for stereo display. * \return A handle to the window displayed in full screen. * This window is invalid after full screen has been ended. */ @@ -302,7 +303,7 @@ extern GHOST_TStandardCursor GHOST_GetCursorShape(GHOST_WindowHandle windowhandl /** * Set the shape of the cursor. * \param windowhandle The handle to the window - * \param cursor The new cursor shape type id. + * \param cursorshape The new cursor shape type id. * \return Indication of success. */ extern GHOST_TSuccess GHOST_SetCursorShape(GHOST_WindowHandle windowhandle, @@ -484,10 +485,10 @@ extern GHOST_TUserDataPtr GHOST_GetTimerTaskUserData(GHOST_TimerTaskHandle timer /** * Changes the time user data. * \param timertaskhandle The handle to the timertask - * \param data The timer user data. + * \param userdata The timer user data. */ extern void GHOST_SetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle, - GHOST_TUserDataPtr userData); + GHOST_TUserDataPtr userdata); /** * Returns indication as to whether the window is valid. @@ -825,7 +826,8 @@ extern GHOST_TUns8 *GHOST_getClipboard(int selection); /** * Put data to the Clipboard - * \param set the selection instead, X11 only feature + * \param buffer the string buffer to set. + * \param selection Set the selection instead, X11 only feature. */ extern void GHOST_putClipboard(GHOST_TInt8 *buffer, int selection); diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp index 49e7def8730..468a37de633 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp @@ -90,8 +90,8 @@ bool GHOST_NDOFManagerX11::processEvents() case SPNAV_EVENT_MOTION: { /* convert to blender view coords */ - short t[3] = {e.motion.x, e.motion.y, -e.motion.z}; - short r[3] = {-e.motion.rx, -e.motion.ry, e.motion.rz}; + short t[3] = {(short)e.motion.x, (short)e.motion.y, (short)-e.motion.z}; + short r[3] = {(short)-e.motion.rx, (short)-e.motion.ry, (short)e.motion.rz}; updateTranslation(t, now); updateRotation(r, now); diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index 08f982ffd3f..9162b7ce4e0 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -282,9 +282,6 @@ protected: /** Raised window is not yet known by the window manager, so delay application become active event handling */ bool m_needDelayedApplicationBecomeActiveEventProcessing; - /** Mouse buttons state */ - GHOST_TUns32 m_pressedMouseButtons; - /** State of the modifiers. */ GHOST_TUns32 m_modifierMask; diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 27720a01a3f..16edb4af575 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -423,7 +423,7 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) #pragma mark defines for 10.6 api not documented in 10.5 -#ifndef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 enum { /* The following event types are available on some hardware on 10.5.2 and later */ NSEventTypeGesture = 29, @@ -435,12 +435,10 @@ enum { }; @interface NSEvent(GestureEvents) -/* This message is valid for events of type NSEventTypeMagnify, on 10.5.2 or later */ -#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 - (float)magnification; // change in magnification. #else -- (CGFloat)magnification; // change in magnification. -#endif +@interface NSEvent(GestureEvents) +- (CGFloat)magnification; // change in magnification on 10.5.2 or later. @end #endif @@ -553,7 +551,6 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() char *rstring = NULL; m_modifierMask =0; - m_pressedMouseButtons =0; m_isGestureInProgress = false; m_cursorDelta_x=0; m_cursorDelta_y=0; @@ -579,8 +576,10 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() sysctl( mib, 2, rstring, &len, NULL, 0 ); //Hack on MacBook revision, as multitouch avail. function missing + //MacbookAir or MacBook version >= 5 (retina is MacBookPro10,1) if (strstr(rstring,"MacBookAir") || - (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9'))) + (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9')) || + (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-4]>='1') && (rstring[strlen(rstring)-4]<='9'))) m_hasMultiTouchTrackpad = true; else m_hasMultiTouchTrackpad = false; @@ -850,12 +849,14 @@ GHOST_TSuccess GHOST_SystemCocoa::getModifierKeys(GHOST_ModifierKeys& keys) cons GHOST_TSuccess GHOST_SystemCocoa::getButtons(GHOST_Buttons& buttons) const { + UInt32 button_state = GetCurrentEventButtonState(); + buttons.clear(); - buttons.set(GHOST_kButtonMaskLeft, m_pressedMouseButtons & GHOST_kButtonMaskLeft); - buttons.set(GHOST_kButtonMaskRight, m_pressedMouseButtons & GHOST_kButtonMaskRight); - buttons.set(GHOST_kButtonMaskMiddle, m_pressedMouseButtons & GHOST_kButtonMaskMiddle); - buttons.set(GHOST_kButtonMaskButton4, m_pressedMouseButtons & GHOST_kButtonMaskButton4); - buttons.set(GHOST_kButtonMaskButton5, m_pressedMouseButtons & GHOST_kButtonMaskButton5); + buttons.set(GHOST_kButtonMaskLeft, button_state & (1 << 0)); + buttons.set(GHOST_kButtonMaskRight, button_state & (1 << 1)); + buttons.set(GHOST_kButtonMaskMiddle, button_state & (1 << 2)); + buttons.set(GHOST_kButtonMaskButton4, button_state & (1 << 3)); + buttons.set(GHOST_kButtonMaskButton5, button_state & (1 << 4)); return GHOST_kSuccess; } @@ -1593,13 +1594,17 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) if ((dx == 0) && (dy == 0)) break; /* Quadratic acceleration */ - dx = dx*(fabs(dx)+0.5); - if (dx<0.0) dx-=0.5; else dx+=0.5; - if (dx< -deltaMax) dx= -deltaMax; else if (dx>deltaMax) dx=deltaMax; + dx = dx*(fabs(dx) + 0.5); + if (dx < 0.0) dx -= 0.5; + else dx += 0.5; + if (dx < -deltaMax) dx = -deltaMax; + else if (dx > deltaMax) dx = deltaMax; - dy = dy*(fabs(dy)+0.5); - if (dy<0.0) dy-=0.5; else dy+=0.5; - if (dy< -deltaMax) dy= -deltaMax; else if (dy>deltaMax) dy=deltaMax; + dy = dy*(fabs(dy) + 0.5); + if (dy < 0.0) dy -= 0.5; + else dy += 0.5; + if (dy < -deltaMax) dy= -deltaMax; + else if (dy > deltaMax) dy= deltaMax; window->clientToScreenIntern(mousePos.x, mousePos.y, x, y); dy = -dy; diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp index 237d4c0f787..fdc4f33b784 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.cpp +++ b/intern/ghost/intern/GHOST_SystemSDL.cpp @@ -73,7 +73,7 @@ GHOST_SystemSDL::createWindow(const STR_String& title, { GHOST_WindowSDL *window = NULL; - window = new GHOST_WindowSDL(this, title, left, top, width, height, state, parentWindow, type, stereoVisual, 1); + window = new GHOST_WindowSDL(this, title, left, top, width, height, state, parentWindow, type, stereoVisual, numOfAASamples); if (window) { if (GHOST_kWindowStateFullScreen == state) { diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index c9953c80a52..2d3cc4f88dc 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -256,7 +256,7 @@ createWindow( window = new GHOST_WindowX11(this, m_display, title, left, top, width, height, - state, parentWindow, type, stereoVisual); + state, parentWindow, type, stereoVisual, numOfAASamples); if (window) { /* Both are now handle in GHOST_WindowX11.cpp diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 23eefe17959..7a5bb8ab604 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -28,7 +28,7 @@ #include -#ifndef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5 //Use of the SetSystemUIMode function (64bit compatible) #include #endif @@ -58,7 +58,7 @@ extern "C" { extern void wm_draw_update(bContext *C); };*/ @interface CocoaWindowDelegate : NSObject -#ifdef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 #endif { @@ -115,12 +115,12 @@ extern "C" { - (void)windowDidResize:(NSNotification *)notification { -#ifdef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 //if (![[notification object] inLiveResize]) { //Send event only once, at end of resize operation (when user has released mouse button) #endif systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, associatedWindow); -#ifdef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 //} #endif /* Live resize ugly patch. Needed because live resize runs in a modal loop, not letting main loop run @@ -609,9 +609,12 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa() [m_openGLView release]; if (m_window) { + // previously we called [m_window release], but on 10.8 this does not + // remove the window from [NSApp orderedWindows] and perhaps other + // places, leading to crashes. so instead we set setReleasedWhenClosed + // back to YES right before closing + [m_window setReleasedWhenClosed:YES]; [m_window close]; - [[m_window delegate] release]; - [m_window release]; m_window = nil; } @@ -913,7 +916,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) * doesn't know view/window difference. */ m_fullScreen = true; -#ifdef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 //10.6 provides Cocoa functions to autoshow menu bar, and to change a window style //Hide menu & dock if needed if ([[m_window screen] isEqual:[[NSScreen screens] objectAtIndex:0]]) { @@ -972,7 +975,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) m_fullScreen = false; //Exit fullscreen -#ifdef MAC_OS_X_VERSION_10_6 +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 //Show again menu & dock if needed if ([[m_window screen] isEqual:[NSScreen mainScreen]]) { [NSApp setPresentationOptions:NSApplicationPresentationDefault]; diff --git a/intern/ghost/intern/GHOST_WindowSDL.cpp b/intern/ghost/intern/GHOST_WindowSDL.cpp index 369fc4ace14..6641b28a20e 100644 --- a/intern/ghost/intern/GHOST_WindowSDL.cpp +++ b/intern/ghost/intern/GHOST_WindowSDL.cpp @@ -26,6 +26,7 @@ #include "GHOST_WindowSDL.h" #include "SDL_mouse.h" +#include #include static SDL_GLContext s_firstContext = NULL; @@ -48,6 +49,20 @@ GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system, m_invalid_window(false), m_sdl_custom_cursor(NULL) { + SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + + if (numOfAASamples) { + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, numOfAASamples); + } + + /* creating the window _must_ come after setting attributes */ m_sdl_win = SDL_CreateWindow(title, left, top, @@ -55,14 +70,7 @@ GHOST_WindowSDL::GHOST_WindowSDL(GHOST_SystemSDL *system, height, SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); - //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); - //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + m_sdl_glcontext = SDL_GL_CreateContext(m_sdl_win); @@ -164,6 +172,10 @@ GHOST_WindowSDL::activateDrawingContext() if (m_sdl_glcontext != NULL) { int status = SDL_GL_MakeCurrent(m_sdl_win, m_sdl_glcontext); (void)status; + /* Disable AA by default */ + if (m_numOfAASamples > 0) { + glDisable(GL_MULTISAMPLE_ARB); + } return GHOST_kSuccess; } return GHOST_kFailure; diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index dded7dc256d..fead1884f8a 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -868,7 +868,7 @@ GHOST_TSuccess GHOST_WindowWin32::installDrawingContext(GHOST_TDrawingContextTyp } // Attempt to enable multisample - if (m_multisample && WGL_ARB_multisample && !m_multisampleEnabled) + if (m_multisample && WGL_ARB_multisample && !m_multisampleEnabled && !is_crappy_intel_card()) { success = initMultisample(preferredFormat); diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index dd1930a241b..156bc86869a 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -1265,6 +1265,10 @@ activateDrawingContext() { if (m_context != NULL) { glXMakeCurrent(m_display, m_window, m_context); + /* Disable AA by default */ + if (m_numOfAASamples > 0) { + glDisable(GL_MULTISAMPLE_ARB); + } return GHOST_kSuccess; } return GHOST_kFailure; diff --git a/intern/guardedalloc/cpp/mallocn.cpp b/intern/guardedalloc/cpp/mallocn.cpp index da77f0e1c83..8b05d25018f 100644 --- a/intern/guardedalloc/cpp/mallocn.cpp +++ b/intern/guardedalloc/cpp/mallocn.cpp @@ -28,6 +28,9 @@ #include #include "../MEM_guardedalloc.h" +void *operator new(size_t size, const char *str) throw(std::bad_alloc); +void *operator new[](size_t size, const char *str) throw(std::bad_alloc); + /* not default but can be used when needing to set a string */ void *operator new(size_t size, const char *str) throw(std::bad_alloc) { diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c index a65871f4410..4a79f5d0de1 100644 --- a/intern/guardedalloc/intern/mallocn.c +++ b/intern/guardedalloc/intern/mallocn.c @@ -58,7 +58,7 @@ * store original buffer's name when doing MEM_dupallocN * helpful to profile issues with non-freed "dup_alloc" buffers, * but this introduces some overhead to memory header and makes - * things slower a bit, so betterto keep disabled by default + * things slower a bit, so better to keep disabled by default */ //#define DEBUG_MEMDUPLINAME diff --git a/intern/iksolver/intern/IK_QJacobianSolver.cpp b/intern/iksolver/intern/IK_QJacobianSolver.cpp index 43d177d0651..75f51f566c9 100644 --- a/intern/iksolver/intern/IK_QJacobianSolver.cpp +++ b/intern/iksolver/intern/IK_QJacobianSolver.cpp @@ -377,7 +377,7 @@ bool IK_QJacobianSolver::Solve( norm = maxnorm; // check for convergence - if (norm < 1e-3) { + if (norm < 1e-3 && iterations > 10) { solved = true; break; } diff --git a/intern/itasc/CMakeLists.txt b/intern/itasc/CMakeLists.txt index 99c64d956cb..bc3ea0cf24c 100644 --- a/intern/itasc/CMakeLists.txt +++ b/intern/itasc/CMakeLists.txt @@ -22,7 +22,7 @@ # Contributor(s): Jacques Beaurain. # # ***** END GPL LICENSE BLOCK ***** - +remove_strict_flags() set(INC ) diff --git a/intern/itasc/kdl/chain.hpp b/intern/itasc/kdl/chain.hpp index 773f472cc5c..fde9d4ed23e 100644 --- a/intern/itasc/kdl/chain.hpp +++ b/intern/itasc/kdl/chain.hpp @@ -35,11 +35,16 @@ namespace KDL { */ class Chain { private: -#if !defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_5) +#if defined(__APPLE__) +# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5 + std::vector segments; +# else // Eigen allocator is needed for alignment of Eigen data types std::vector > segments; +# endif /* MAC_OS_X_VERSION_MIN_REQUIRED */ #else - std::vector segments; + // Eigen allocator is needed for alignment of Eigen data types + std::vector > segments; #endif unsigned int nrOfJoints; unsigned int nrOfSegments; diff --git a/intern/itasc/kdl/tree.hpp b/intern/itasc/kdl/tree.hpp index 08c1aadc6de..a020c6cf2cf 100644 --- a/intern/itasc/kdl/tree.hpp +++ b/intern/itasc/kdl/tree.hpp @@ -27,19 +27,30 @@ #include #include -#if !defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_5) -#include +#if defined(__APPLE__) +# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5 + //no include +# else +# include +# endif /* MAC_OS_X_VERSION_MIN_REQUIRED */ +#else +# include #endif namespace KDL { //Forward declaration class TreeElement; -#if !defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_5) +#if defined(__APPLE__) +# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5 + typedef std::map SegmentMap; +# else // Eigen allocator is needed for alignment of Eigen data types typedef std::map, Eigen::aligned_allocator > > SegmentMap; +# endif /* MAC_OS_X_VERSION_MIN_REQUIRED */ #else - typedef std::map SegmentMap; + // Eigen allocator is needed for alignment of Eigen data types + typedef std::map, Eigen::aligned_allocator > > SegmentMap; #endif class TreeElement { diff --git a/intern/locale/CMakeLists.txt b/intern/locale/CMakeLists.txt new file mode 100644 index 00000000000..1f14a0e7a6a --- /dev/null +++ b/intern/locale/CMakeLists.txt @@ -0,0 +1,47 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2012, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Bastien Montagne. +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + . +) + +set(INC_SYS +) + +set(SRC + boost_locale_wrapper.cpp + + boost_locale_wrapper.h +) + +if(WITH_INTERNATIONAL) + list(APPEND INC_SYS + ${BOOST_INCLUDE_DIR} + ) + add_definitions(-DWITH_INTERNATIONAL) + add_definitions(${BOOST_DEFINITIONS}) +endif() + +blender_add_lib(bf_intern_locale "${SRC}" "${INC}" "${INC_SYS}") diff --git a/intern/locale/SConscript b/intern/locale/SConscript new file mode 100644 index 00000000000..df745f093ea --- /dev/null +++ b/intern/locale/SConscript @@ -0,0 +1,14 @@ +#!/usr/bin/python + +Import('env') + +sources = env.Glob('*.cpp') + +incs = '.' +defs = [] + +if env['WITH_BF_INTERNATIONAL']: + defs.append('WITH_INTERNATIONAL') + incs += ' ' + env['BF_BOOST_INC'] + +env.BlenderLib( 'bf_intern_locale', sources, Split(incs), defs, libtype=['intern','player'], priority=[10, 185]) diff --git a/intern/locale/boost_locale_wrapper.cpp b/intern/locale/boost_locale_wrapper.cpp new file mode 100644 index 00000000000..939c66bad13 --- /dev/null +++ b/intern/locale/boost_locale_wrapper.cpp @@ -0,0 +1,114 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012, Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Bastien Montagne. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#include +#include + +#include "boost_locale_wrapper.h" + +static std::string messages_path; +static std::string default_domain; + +void bl_locale_init(const char *_messages_path, const char *_default_domain) +{ + // Avoid using ICU backend, we do not need its power and it's rather heavy! + boost::locale::localization_backend_manager lman = boost::locale::localization_backend_manager::global(); +#if defined (_WIN32) + lman.select("winapi"); +#else + lman.select("posix"); +#endif + boost::locale::localization_backend_manager::global(lman); + + messages_path = _messages_path; + default_domain = _default_domain; +} + +void bl_locale_set(const char *locale) +{ + boost::locale::generator gen; + // Specify location of dictionaries. + gen.add_messages_path(messages_path); + gen.add_messages_domain(default_domain); + //gen.set_default_messages_domain(default_domain); + + if (locale && locale[0]) { + std::locale::global(gen(locale)); + } + else { +#if defined (__APPLE__) + // workaround to get osx system locale from user defaults + FILE* fp; + std::string locale_osx = ""; + char result[16]; + int result_len = 0; + + fp = popen("defaults read .GlobalPreferences AppleLocale", "r"); + + if(fp) { + result_len = fread(result, 1, sizeof(result) - 1, fp); + + if(result_len > 0) { + result[result_len-1] = '\0'; // \0 terminate and remove \n + locale_osx = std::string(result) + std::string(".UTF-8"); + } + + pclose(fp); + } + + if(locale_osx == "") + fprintf(stderr, "Locale set: failed to read AppleLocale read from defaults\n"); + + std::locale::global(gen(locale_osx.c_str())); +#else + std::locale::global(gen("")); +#endif + } + // Note: boost always uses "C" LC_NUMERIC by default! +} + +const char* bl_locale_pgettext(const char *msgctxt, const char *msgid) +{ + // Note: We cannot use short stuff like boost::locale::gettext, because those return + // std::basic_string objects, which c_ptr()-returned char* is no more valid + // once deleted (which happens as soons they are out of scope of this func). + typedef boost::locale::message_format char_message_facet; + try { + std::locale l; + char_message_facet const &facet = std::use_facet(l); + char const *r = facet.get(0, msgctxt, msgid); + if(r) + return r; + return msgid; + } + catch(std::exception const &e) { +// std::cout << "boost_locale_pgettext: " << e.what() << " \n"; + return msgid; + } +} + diff --git a/intern/locale/boost_locale_wrapper.h b/intern/locale/boost_locale_wrapper.h new file mode 100644 index 00000000000..e7956d216f1 --- /dev/null +++ b/intern/locale/boost_locale_wrapper.h @@ -0,0 +1,49 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012, Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Bastien Montagne. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +/** \file locale/boost_locale_wrapper.h + * \ingroup locale + * A thin C wrapper around boost::locale... + */ + +#ifndef __BOOST_LOCALE_WRAPPER_H__ +#define __BOOST_LOCALE_WRAPPER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void bl_locale_init(const char *messages_path, const char *default_domain); +void bl_locale_set(const char *locale); +const char* bl_locale_pgettext(const char *msgctxt, const char *msgid); + +#ifdef __cplusplus +} +#endif + +#endif /* __BOOST_LOCALE_WRAPPER_H__ */ diff --git a/intern/memutil/MEM_CacheLimiter.h b/intern/memutil/MEM_CacheLimiter.h index cfff5d10e4f..daf66dc05b1 100644 --- a/intern/memutil/MEM_CacheLimiter.h +++ b/intern/memutil/MEM_CacheLimiter.h @@ -247,8 +247,10 @@ private: if (!elem->can_destroy()) continue; - /* by default 0 means higherst priority element */ - int priority = -(queue.size() - i - 1); + /* by default 0 means highest priority element */ + /* casting a size type to int is questionable, + but unlikely to cause problems */ + int priority = -((int)(queue.size()) - i - 1); priority = getItemPriority(elem->get()->get_data(), priority); if (priority < best_match_priority || best_match_elem == NULL) { diff --git a/intern/memutil/MEM_SmartPtr.h b/intern/memutil/MEM_SmartPtr.h index 09cf5c95854..dd19aae9db9 100644 --- a/intern/memutil/MEM_SmartPtr.h +++ b/intern/memutil/MEM_SmartPtr.h @@ -170,7 +170,7 @@ public : } /** - * Assignment operator - ownership is transfered from rhs to lhs. + * Assignment operator - ownership is transferred from rhs to lhs. * There is an intenional side-effect of function of transferring * ownership from the const parameter rhs. This is to insure * the 1-1 relationship. diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc index 49fc44d1e12..2d73d2ff56b 100644 --- a/intern/opencolorio/ocio_impl.cc +++ b/intern/opencolorio/ocio_impl.cc @@ -48,7 +48,7 @@ using namespace OCIO_NAMESPACE; #endif #define MEM_NEW(type) new(MEM_mallocN(sizeof(type), __func__)) type() -#define MEM_DELETE(what, type) if(what) { (what)->~type(); MEM_freeN(what); } (void)0 +#define MEM_DELETE(what, type) if(what) { ((type*)(what))->~type(); MEM_freeN(what); } (void)0 static void OCIO_reportError(const char *err) { @@ -421,8 +421,7 @@ void OCIOImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, void OCIOImpl::processorRelease(OCIO_ConstProcessorRcPtr *p) { - p->~OCIO_ConstProcessorRcPtr(); - MEM_freeN(p); + MEM_DELETE(p, ConstProcessorRcPtr); } const char *OCIOImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs) diff --git a/intern/opennl/CMakeLists.txt b/intern/opennl/CMakeLists.txt index b7a24839e38..754036de101 100644 --- a/intern/opennl/CMakeLists.txt +++ b/intern/opennl/CMakeLists.txt @@ -28,7 +28,11 @@ remove_strict_flags() # remove debug flag here since this is not a blender maintained library # and debug gives a lot of prints on UV unwrapping. developers can enable if they need to. -add_definitions(-UDEBUG) +if(MSVC) + remove_definitions(-DDEBUG) +else() + add_definitions(-UDEBUG) +endif() # quiet compiler warnings about undefined defines diff --git a/intern/smoke/intern/FFT_NOISE.h b/intern/smoke/intern/FFT_NOISE.h index a087b4e1391..8b7e4f2728b 100644 --- a/intern/smoke/intern/FFT_NOISE.h +++ b/intern/smoke/intern/FFT_NOISE.h @@ -167,6 +167,8 @@ static void generatTile_FFT(float* const noiseTileData, std::string filename) for (int x = 0; x < xRes; x++, index++) noise[index] -= forward[index][0] / totalCells; + // fill noiseTileData + memcpy(noiseTileData, noise, sizeof(float) * totalCells); // save out the noise tile saveTile(noise, filename); diff --git a/intern/smoke/intern/WTURBULENCE.cpp b/intern/smoke/intern/WTURBULENCE.cpp index 1c89f5d681b..5b6509afead 100644 --- a/intern/smoke/intern/WTURBULENCE.cpp +++ b/intern/smoke/intern/WTURBULENCE.cpp @@ -220,21 +220,25 @@ void WTURBULENCE::setNoise(int type) { if(type == (1<<1)) // FFT { +#ifdef WITH_FFTW3 // needs fft - #ifdef WITH_FFTW3 std::string noiseTileFilename = std::string("noise.fft"); generatTile_FFT(_noiseTile, noiseTileFilename); - #endif + return; +#else + fprintf(stderr, "FFTW not enabled, falling back to wavelet noise.\n"); +#endif } - else if(type == (1<<2)) // curl +#if 0 + if(type == (1<<2)) // curl { // TODO: not supported yet + return; } - else // standard - wavelet - { - std::string noiseTileFilename = std::string("noise.wavelets"); - generateTile_WAVELET(_noiseTile, noiseTileFilename); - } +#endif + + std::string noiseTileFilename = std::string("noise.wavelets"); + generateTile_WAVELET(_noiseTile, noiseTileFilename); } // init direct access functions from blender diff --git a/intern/utfconv/utfconv.h b/intern/utfconv/utfconv.h index cf0e69170a2..ada85e274e3 100644 --- a/intern/utfconv/utfconv.h +++ b/intern/utfconv/utfconv.h @@ -57,18 +57,18 @@ size_t count_utf_16_from_8(const char *string8); /** * Converts utf-16 string to allocated utf-8 string - * @params in16 utf-16 string to convert - * @params out8 utf-8 string to string the conversion - * @params size8 the allocated size in bytes of out8 + * @param in16 utf-16 string to convert + * @param out8 utf-8 string to string the conversion + * @param size8 the allocated size in bytes of out8 * @return Returns any errors occured during conversion. See the block above, */ int conv_utf_16_to_8(const wchar_t *in16, char *out8, size_t size8); /** * Converts utf-8 string to allocated utf-16 string - * @params in8 utf-8 string to convert - * @params out16 utf-16 string to string the conversion - * @params size16 the allocated size in wchar_t (two byte) of out16 + * @param in8 utf-8 string to convert + * @param out16 utf-16 string to string the conversion + * @param size16 the allocated size in wchar_t (two byte) of out16 * @return Returns any errors occured during conversion. See the block above, */ int conv_utf_8_to_16(const char *in8, wchar_t *out16, size_t size16); @@ -76,16 +76,16 @@ int conv_utf_8_to_16(const char *in8, wchar_t *out16, size_t size16); /** * Allocates and converts the utf-8 string from utf-16 - * @params in16 utf-16 string to convert - * @params add any additional size which will be allocated for new utf-8 string in bytes + * @param in16 utf-16 string to convert + * @param add any additional size which will be allocated for new utf-8 string in bytes * @return New allocated and converted utf-8 string or NULL if in16 is 0. */ char *alloc_utf_8_from_16(const wchar_t *in16, size_t add); /** * Allocates and converts the utf-16 string from utf-8 - * @params in8 utf-8 string to convert - * @params add any additional size which will be allocated for new utf-16 string in wchar_t (two bytes) + * @param in8 utf-8 string to convert + * @param add any additional size which will be allocated for new utf-16 string in wchar_t (two bytes) * @return New allocated and converted utf-16 string or NULL if in8 is 0. */ wchar_t *alloc_utf16_from_8(const char *in8, size_t add); diff --git a/source/darwin/blender.app/Contents/Info.plist b/release/darwin/blender.app/Contents/Info.plist similarity index 100% rename from source/darwin/blender.app/Contents/Info.plist rename to release/darwin/blender.app/Contents/Info.plist diff --git a/source/darwin/blender.app/Contents/MacOS/blender b/release/darwin/blender.app/Contents/MacOS/blender similarity index 100% rename from source/darwin/blender.app/Contents/MacOS/blender rename to release/darwin/blender.app/Contents/MacOS/blender diff --git a/source/darwin/blender.app/Contents/PkgInfo b/release/darwin/blender.app/Contents/PkgInfo similarity index 100% rename from source/darwin/blender.app/Contents/PkgInfo rename to release/darwin/blender.app/Contents/PkgInfo diff --git a/source/darwin/blender.app/Contents/Resources/blender file icon.icns b/release/darwin/blender.app/Contents/Resources/blender file icon.icns similarity index 100% rename from source/darwin/blender.app/Contents/Resources/blender file icon.icns rename to release/darwin/blender.app/Contents/Resources/blender file icon.icns diff --git a/source/darwin/blender.app/Contents/Resources/blender icon.icns b/release/darwin/blender.app/Contents/Resources/blender icon.icns similarity index 100% rename from source/darwin/blender.app/Contents/Resources/blender icon.icns rename to release/darwin/blender.app/Contents/Resources/blender icon.icns diff --git a/source/darwin/blenderplayer.app/Contents/Info.plist b/release/darwin/blenderplayer.app/Contents/Info.plist similarity index 100% rename from source/darwin/blenderplayer.app/Contents/Info.plist rename to release/darwin/blenderplayer.app/Contents/Info.plist diff --git a/source/darwin/blenderplayer.app/Contents/MacOS/blenderplayer b/release/darwin/blenderplayer.app/Contents/MacOS/blenderplayer similarity index 100% rename from source/darwin/blenderplayer.app/Contents/MacOS/blenderplayer rename to release/darwin/blenderplayer.app/Contents/MacOS/blenderplayer diff --git a/source/darwin/blenderplayer.app/Contents/PkgInfo b/release/darwin/blenderplayer.app/Contents/PkgInfo similarity index 100% rename from source/darwin/blenderplayer.app/Contents/PkgInfo rename to release/darwin/blenderplayer.app/Contents/PkgInfo diff --git a/source/darwin/blenderplayer.app/Contents/Resources/blender file icon.icns b/release/darwin/blenderplayer.app/Contents/Resources/blender file icon.icns similarity index 100% rename from source/darwin/blenderplayer.app/Contents/Resources/blender file icon.icns rename to release/darwin/blenderplayer.app/Contents/Resources/blender file icon.icns diff --git a/source/darwin/blenderplayer.app/Contents/Resources/blender player icon.icns b/release/darwin/blenderplayer.app/Contents/Resources/blender player icon.icns similarity index 100% rename from source/darwin/blenderplayer.app/Contents/Resources/blender player icon.icns rename to release/darwin/blenderplayer.app/Contents/Resources/blender player icon.icns diff --git a/source/darwin/set_simulation_threads.app/Contents/Info.plist b/release/darwin/set_simulation_threads.app/Contents/Info.plist similarity index 100% rename from source/darwin/set_simulation_threads.app/Contents/Info.plist rename to release/darwin/set_simulation_threads.app/Contents/Info.plist diff --git a/source/darwin/set_simulation_threads.app/Contents/MacOS/applet b/release/darwin/set_simulation_threads.app/Contents/MacOS/applet similarity index 100% rename from source/darwin/set_simulation_threads.app/Contents/MacOS/applet rename to release/darwin/set_simulation_threads.app/Contents/MacOS/applet diff --git a/source/darwin/set_simulation_threads.app/Contents/PkgInfo b/release/darwin/set_simulation_threads.app/Contents/PkgInfo similarity index 100% rename from source/darwin/set_simulation_threads.app/Contents/PkgInfo rename to release/darwin/set_simulation_threads.app/Contents/PkgInfo diff --git a/source/darwin/set_simulation_threads.app/Contents/Resources/Scripts/main.scpt b/release/darwin/set_simulation_threads.app/Contents/Resources/Scripts/main.scpt similarity index 100% rename from source/darwin/set_simulation_threads.app/Contents/Resources/Scripts/main.scpt rename to release/darwin/set_simulation_threads.app/Contents/Resources/Scripts/main.scpt diff --git a/source/darwin/set_simulation_threads.app/Contents/Resources/applet.icns b/release/darwin/set_simulation_threads.app/Contents/Resources/applet.icns similarity index 100% rename from source/darwin/set_simulation_threads.app/Contents/Resources/applet.icns rename to release/darwin/set_simulation_threads.app/Contents/Resources/applet.icns diff --git a/source/darwin/set_simulation_threads.app/Contents/Resources/applet.rsrc b/release/darwin/set_simulation_threads.app/Contents/Resources/applet.rsrc similarity index 100% rename from source/darwin/set_simulation_threads.app/Contents/Resources/applet.rsrc rename to release/darwin/set_simulation_threads.app/Contents/Resources/applet.rsrc diff --git a/source/darwin/set_simulation_threads.app/Contents/Resources/description.rtfd/TXT.rtf b/release/darwin/set_simulation_threads.app/Contents/Resources/description.rtfd/TXT.rtf similarity index 100% rename from source/darwin/set_simulation_threads.app/Contents/Resources/description.rtfd/TXT.rtf rename to release/darwin/set_simulation_threads.app/Contents/Resources/description.rtfd/TXT.rtf diff --git a/release/datafiles/blender_icons.png b/release/datafiles/blender_icons.png index 55a83964a8be84cb7435e49cc6bbcc7ff9907f8b..b0d5e825738ce6548801ada3b73cba2fd1144313 100644 GIT binary patch literal 189744 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

      YCv|O=v)*eeo^T8j?D%$zcGC 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ϋ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 literal 228428 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%0D0lWZq;=j+>T}Egeb#;zwf+l( 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�g8aa5btFTqSt8% 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%0AZf2u>QUsm8+u|AB0#`=#6_uPFq`*Kv!n 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 z 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 PVjwjoZN++d%kcjKK2fC^ literal 14130 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

      H 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 E3y102M*si- diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png index 7f40ead3911a72ea22362d50239e169107df00ce..41284eff9c19c1920f9c68a24ebca19662df0cb3 100644 GIT binary patch literal 330539 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­x`um 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 JrM7DP|`t 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 XbVYj|aU92G00000NkvXXu0mjfiNf_) literal 212426 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 Q5!oJy&(wBA* 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

        ;7HG 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 JPDHLkV1nlEe8B(! diff --git a/release/datafiles/startup.blend b/release/datafiles/startup.blend index 5056246e7439390550e6274262563d01421b1e4d..cdd43c74f3bbf39983861609586efa14db42012b 100644 GIT binary patch literal 415348 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%0AnNRwtV}FaEZX{McwX=*E8J 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 literal 408072 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 z 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 diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py index 7e604c5de4c..6bf81d73f8b 100644 --- a/release/scripts/modules/addon_utils.py +++ b/release/scripts/modules/addon_utils.py @@ -232,7 +232,6 @@ def enable(module_name, default_set=True, persistent=False): import os import sys - import imp def handle_error(): import traceback @@ -246,6 +245,7 @@ def enable(module_name, default_set=True, persistent=False): mtime_orig = getattr(mod, "__time__", 0) mtime_new = os.path.getmtime(mod.__file__) if mtime_orig != mtime_new: + import imp print("module changed on disk:", mod.__file__, "reloading...") try: diff --git a/release/scripts/modules/bl_i18n_utils/settings.py b/release/scripts/modules/bl_i18n_utils/settings.py index 0db3f85f1ff..c7414e84046 100644 --- a/release/scripts/modules/bl_i18n_utils/settings.py +++ b/release/scripts/modules/bl_i18n_utils/settings.py @@ -40,46 +40,46 @@ LANGUAGES_CATEGORIES = ( ) LANGUAGES = ( # ID, UI english label, ISO code. - ( 0, "Default (Default)", "DEFAULT", ""), - ( 1, "English (English)", "en_US", "english"), - ( 2, "Japanese (日本語)", "ja_JP", "japanese"), - ( 3, "Dutch (Nederlandse taal)", "nl_NL", "dutch"), - ( 4, "Italian (Italiano)", "it_IT", "italian"), - ( 5, "German (Deutsch)", "de_DE", "german"), - ( 6, "Finnish (Suomi)", "fi_FI", "finnish"), - ( 7, "Swedish (Svenska)", "sv_SE", "swedish"), - ( 8, "French (Français)", "fr_FR", "french"), - ( 9, "Spanish (Español)", "es", "spanish"), - (10, "Catalan (Català)", "ca_AD", "catalan"), - (11, "Czech (Český)", "cs_CZ", "czech"), - (12, "Portuguese (Português)", "pt_PT", "portuguese_portugal"), - (13, "Simplified Chinese (简体中文)", "zh_CN", "Chinese (Simplified)_China.1252"), - (14, "Traditional Chinese (繁體中文)", "zh_TW", "Chinese (Traditional)_China.1252"), - (15, "Russian (Русский)", "ru_RU", "russian"), - (16, "Croatian (Hrvatski)", "hr_HR", "croatian"), - (17, "Serbian (Српски)", "sr_RS", "serbian"), - (18, "Ukrainian (Український)", "uk_UA", "ukrainian"), - (19, "Polish (Polski)", "pl_PL", "polish"), - (20, "Romanian (Român)", "ro_RO", "romanian"), + ( 0, "Default (Default)", "DEFAULT"), + ( 1, "English (English)", "en_US"), + ( 2, "Japanese (日本語)", "ja_JP"), + ( 3, "Dutch (Nederlandse taal)", "nl_NL"), + ( 4, "Italian (Italiano)", "it_IT"), + ( 5, "German (Deutsch)", "de_DE"), + ( 6, "Finnish (Suomi)", "fi_FI"), + ( 7, "Swedish (Svenska)", "sv_SE"), + ( 8, "French (Français)", "fr_FR"), + ( 9, "Spanish (Español)", "es"), + (10, "Catalan (Català)", "ca_AD"), + (11, "Czech (Český)", "cs_CZ"), + (12, "Portuguese (Português)", "pt_PT"), + (13, "Simplified Chinese (简体中文)", "zh_CN"), + (14, "Traditional Chinese (繁體中文)", "zh_TW"), + (15, "Russian (Русский)", "ru_RU"), + (16, "Croatian (Hrvatski)", "hr_HR"), + (17, "Serbian (Српски)", "sr_RS"), + (18, "Ukrainian (Український)", "uk_UA"), + (19, "Polish (Polski)", "pl_PL"), + (20, "Romanian (Român)", "ro_RO"), # Using the utf8 flipped form of Arabic (العربية). - (21, "Arabic (ﺔﻴﺑﺮﻌﻟﺍ)", "ar_EG", "arabic"), - (22, "Bulgarian (Български)", "bg_BG", "bulgarian"), - (23, "Greek (Ελληνικά)", "el_GR", "greek"), - (24, "Korean (한국 언어)", "ko_KR", "korean"), - (25, "Nepali (नेपाली)", "ne_NP", "nepali"), + (21, "Arabic (ﺔﻴﺑﺮﻌﻟﺍ)", "ar_EG"), + (22, "Bulgarian (Български)", "bg_BG"), + (23, "Greek (Ελληνικά)", "el_GR"), + (24, "Korean (한국 언어)", "ko_KR"), + (25, "Nepali (नेपाली)", "ne_NP"), # Using the utf8 flipped form of Persian (فارسی). - (26, "Persian (ﯽﺳﺭﺎﻓ)", "fa_IR", "farsi"), - (27, "Indonesian (Bahasa indonesia)", "id_ID", "indonesian"), - (28, "Serbian Latin (Srpski latinica)", "sr_RS@latin", "serbian (latin)"), - (29, "Kyrgyz (Кыргыз тили)", "ky_KG", "kyrgyz"), - (30, "Turkish (Türkçe)", "tr_TR", "turkish"), - (31, "Hungarian (Magyar)", "hu_HU", "hungarian"), - (32, "Brazilian Portuguese (Português do Brasil)", "pt_BR", "protuguese_brazil"), + (26, "Persian (ﯽﺳﺭﺎﻓ)", "fa_IR"), + (27, "Indonesian (Bahasa indonesia)", "id_ID"), + (28, "Serbian Latin (Srpski latinica)", "sr_RS@latin"), + (29, "Kyrgyz (Кыргыз тили)", "ky_KG"), + (30, "Turkish (Türkçe)", "tr_TR"), + (31, "Hungarian (Magyar)", "hu_HU"), + (32, "Brazilian Portuguese (Português do Brasil)", "pt_BR"), # Using the utf8 flipped form of Hebrew (עִבְרִית)). - (33, "Hebrew (תירִבְעִ)", "he_IL", "hebrew"), - (34, "Estonian (Eestlane)", "et_EE", "estonian"), - (35, "Esperanto (Esperanto)", "eo", "esperanto"), - (36, "Spanish from Spain (Español de España)", "es_ES", "spanish_spain"), + (33, "Hebrew (תירִבְעִ)", "he_IL"), + (34, "Estonian (Eestlane)", "et_EE"), + (35, "Esperanto (Esperanto)", "eo"), + (36, "Spanish from Spain (Español de España)", "es_ES"), ) # Name of language file used by Blender to generate translations' menu. @@ -114,6 +114,9 @@ DOMAIN = "blender" # File type (ext) to parse. PYGETTEXT_ALLOWED_EXTS = {".c", ".cpp", ".cxx", ".hpp", ".hxx", ".h"} +# Max number of contexts into a BLF_I18N_MSGID_MULTI_CTXT macro... +PYGETTEXT_MAX_MULTI_CTXT = 16 + # Where to search contexts definitions, relative to SOURCE_DIR (defined below). PYGETTEXT_CONTEXTS_DEFSRC = os.path.join("source", "blender", "blenfont", "BLF_translation.h") @@ -149,7 +152,10 @@ _str_whole_re = ( # End of loop. "))*" ) -_ctxt_re = r"(?P(?:" + _str_whole_re.format(_="_ctxt") + r")|(?:[A-Z_0-9]+))" +_ctxt_re_gen = lambda uid : r"(?P(?:".format(uid=uid) + \ + _str_whole_re.format(_="_ctxt{uid}".format(uid=uid)) + \ + r")|(?:[A-Z_0-9]+))" +_ctxt_re = _ctxt_re_gen("") _msg_re = r"(?P" + _str_whole_re.format(_="_msg") + r")" PYGETTEXT_KEYWORDS = (() + tuple((r"{}\(\s*" + _msg_re + r"\s*\)").format(it) @@ -165,7 +171,11 @@ PYGETTEXT_KEYWORDS = (() + for it in ("BMO_error_raise",)) + tuple(("{}\\((?:[^\"',]+,)\\s*" + _msg_re + r"\s*(?:\)|,)").format(it) - for it in ("modifier_setError",)) + for it in ("modifier_setError",)) + + + tuple((r"{}\(\s*" + _msg_re + r"\s*,\s*(?:" + \ + r"\s*,\s*)?(?:".join(_ctxt_re_gen(i) for i in range(PYGETTEXT_MAX_MULTI_CTXT)) + r")?\s*\)").format(it) + for it in ("BLF_I18N_MSGID_MULTI_CTXT",)) ) ESCAPE_RE = ( diff --git a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py b/release/scripts/modules/bl_i18n_utils/spell_check_utils.py index 60a943d2bd4..fbe405a61c6 100644 --- a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py +++ b/release/scripts/modules/bl_i18n_utils/spell_check_utils.py @@ -77,6 +77,7 @@ dict_uimsgs = { "boxpack", "buffersize", "builtin", "builtins", + "bytecode", "chunksize", "de", "defocus", @@ -425,12 +426,14 @@ dict_uimsgs = { "fh", "fov", "fft", + "futura", "gfx", "gl", "glsl", "gpl", "gpu", "gpus", "hc", + "hdc", "hdr", "hh", "mm", "ss", "ff", # hh:mm:ss:ff timecode "hsv", "hsva", @@ -441,6 +444,7 @@ dict_uimsgs = { "mux", "ndof", "ppc", + "precisa", "px", "qmc", "rgb", "rgba", @@ -502,6 +506,8 @@ dict_uimsgs = { "mtl", "ogg", "openjpeg", + "osl", + "oso", "piz", "png", "po", diff --git a/release/scripts/modules/bl_i18n_utils/update_languages_menu.py b/release/scripts/modules/bl_i18n_utils/update_languages_menu.py index d45a5543220..9b4cb20fadf 100755 --- a/release/scripts/modules/bl_i18n_utils/update_languages_menu.py +++ b/release/scripts/modules/bl_i18n_utils/update_languages_menu.py @@ -53,7 +53,7 @@ FLAG_MESSAGES = { def find_matching_po(languages, stats, forbidden): """Match languages defined in LANGUAGES setting to relevant po, if possible!""" ret = [] - for uid, label, org_key, long_loc in languages: + for uid, label, org_key, in languages: key = org_key if key not in stats: # Try to simplify the key (eg from es_ES to es). @@ -64,11 +64,11 @@ def find_matching_po(languages, stats, forbidden): key = key + org_key[org_key.index('@'):] if key in stats: if key in forbidden: - ret.append((stats[key], uid, label, org_key, long_loc, FORBIDDEN)) + ret.append((stats[key], uid, label, org_key, FORBIDDEN)) else: - ret.append((stats[key], uid, label, org_key, long_loc, OK)) + ret.append((stats[key], uid, label, org_key, OK)) else: - ret.append((0.0, uid, label, org_key, long_loc, MISSING)) + ret.append((0.0, uid, label, org_key, MISSING)) return ret def main(): @@ -103,14 +103,14 @@ def main(): stats = sorted(stats, key=lambda it: it[0], reverse=True) langs_cats = [[] for i in range(len(limits))] highest_uid = 0 - for prop, uid, label, key, long_loc, flag in stats: + for prop, uid, label, key, flag in stats: if prop < limits[idx][0]: # Sub-sort languages by iso-codes. langs_cats[idx].sort(key=lambda it: it[2]) idx += 1 if prop < min_trans and flag == OK: flag = TOOLOW - langs_cats[idx].append((uid, label, key, long_loc, flag)) + langs_cats[idx].append((uid, label, key, flag)) if abs(uid) > highest_uid: highest_uid = abs(uid) # Sub-sort last group of languages by iso-codes! @@ -120,7 +120,7 @@ def main(): f.write("# and to generate translation menu.\n") f.write("#\n") f.write("# File format:\n") - f.write("# ID:MENULABEL:ISOCODE:WINCODE\n") + f.write("# ID:MENULABEL:ISOCODE\n") f.write("# ID must be unique, except for 0 value (marks categories for menu).\n") f.write("# Line starting with a # are comments!\n") f.write("#\n") @@ -135,12 +135,12 @@ def main(): # Do not write the category if it has no language! f.write("# Void category! #0:{}:\n".format(cat[1])) # ...and all matching language entries! - for uid, label, key, long_loc, flag in langs_cat: + for uid, label, key, flag in langs_cat: if flag == OK: - f.write("{}:{}:{}:{}\n".format(uid, label, key, long_loc)) + f.write("{}:{}:{}\n".format(uid, label, key)) else: # Non-existing, commented entry! - f.write("# {} #{}:{}:{}:{}\n".format(FLAG_MESSAGES[flag], uid, label, key, long_loc)) + f.write("# {} #{}:{}:{}\n".format(FLAG_MESSAGES[flag], uid, label, key)) if __name__ == "__main__": diff --git a/release/scripts/modules/bl_i18n_utils/update_pot.py b/release/scripts/modules/bl_i18n_utils/update_pot.py index 51197b86678..ecb5d837a09 100755 --- a/release/scripts/modules/bl_i18n_utils/update_pot.py +++ b/release/scripts/modules/bl_i18n_utils/update_pot.py @@ -52,6 +52,7 @@ SRC_POTFILES = settings.FILE_NAME_SRC_POTFILES CONTEXT_DEFAULT = settings.CONTEXT_DEFAULT PYGETTEXT_ALLOWED_EXTS = settings.PYGETTEXT_ALLOWED_EXTS +PYGETTEXT_MAX_MULTI_CTXT = settings.PYGETTEXT_MAX_MULTI_CTXT SVN_EXECUTABLE = settings.SVN_EXECUTABLE @@ -79,6 +80,31 @@ clean_str = lambda s: "".join(m.group("clean") for m in _clean_str(s)) def check_file(path, rel_path, messages): + def process_entry(ctxt, msg): + # Context. + if ctxt: + if ctxt in CONTEXTS: + ctxt = CONTEXTS[ctxt] + elif '"' in ctxt or "'" in ctxt: + ctxt = clean_str(ctxt) + else: + print("WARNING: raw context “{}” couldn’t be resolved!" + "".format(ctxt)) + ctxt = CONTEXT_DEFAULT + else: + ctxt = CONTEXT_DEFAULT + # Message. + if msg: + if '"' in msg or "'" in msg: + msg = clean_str(msg) + else: + print("WARNING: raw message “{}” couldn’t be resolved!" + "".format(msg)) + msg = "" + else: + msg = "" + return (ctxt, msg) + with open(path, encoding="utf-8") as f: f = f.read() for srch in pygettexts: @@ -86,34 +112,23 @@ def check_file(path, rel_path, messages): line = pos = 0 while m: d = m.groupdict() - # Context. - ctxt = d.get("ctxt_raw") - if ctxt: - if ctxt in CONTEXTS: - ctxt = CONTEXTS[ctxt] - elif '"' in ctxt or "'" in ctxt: - ctxt = clean_str(ctxt) - else: - print("WARNING: raw context “{}” couldn’t be resolved!" - "".format(ctxt)) - ctxt = CONTEXT_DEFAULT - else: - ctxt = CONTEXT_DEFAULT - # Message. - msg = d.get("msg_raw") - if msg: - if '"' in msg or "'" in msg: - msg = clean_str(msg) - else: - print("WARNING: raw message “{}” couldn’t be resolved!" - "".format(msg)) - msg = "" - else: - msg = "" # Line. line += f[pos:m.start()].count('\n') - # And we are done for this item! - messages.setdefault((ctxt, msg), []).append(":".join((rel_path, str(line)))) + msg = d.get("msg_raw") + # First, try the "multi-contexts" stuff! + ctxts = tuple(d.get("ctxt_raw{}".format(i)) for i in range(PYGETTEXT_MAX_MULTI_CTXT)) + if ctxts[0]: + for ctxt in ctxts: + if not ctxt: + break + ctxt, _msg = process_entry(ctxt, msg) + # And we are done for this item! + messages.setdefault((ctxt, _msg), []).append(":".join((rel_path, str(line)))) + else: + ctxt = d.get("ctxt_raw") + ctxt, msg = process_entry(ctxt, msg) + # And we are done for this item! + messages.setdefault((ctxt, msg), []).append(":".join((rel_path, str(line)))) pos = m.end() line += f[m.start():pos].count('\n') m = srch(f, pos) @@ -138,12 +153,12 @@ def py_xgettext(messages): rel_path = os.path.relpath(path, SOURCE_DIR) if rel_path in forbidden: continue - elif rel_path in forced: - forced.remove(rel_path) - check_file(path, rel_path, messages) - for path in forced: + elif rel_path not in forced: + forced.add(rel_path) + for rel_path in sorted(forced): + path = os.path.join(SOURCE_DIR, rel_path) if os.path.exists(path): - check_file(os.path.join(SOURCE_DIR, path), path, messages) + check_file(path, rel_path, messages) # Spell checking! diff --git a/release/scripts/modules/bl_i18n_utils/update_trunk.py b/release/scripts/modules/bl_i18n_utils/update_trunk.py index 9b904ec861a..b84a227ae0a 100755 --- a/release/scripts/modules/bl_i18n_utils/update_trunk.py +++ b/release/scripts/modules/bl_i18n_utils/update_trunk.py @@ -115,7 +115,7 @@ def main(): if not os.path.exists(os.path.join(TRUNK_PO_DIR, ".".join((lang, "po")))): failed.add(lang) - # Check and compile each po separatly, to keep track of those failing. + # Check and compile each po separately, to keep track of those failing. # XXX There should not be any failing at this stage, import step is # supposed to have already filtered them out! for po in os.listdir(TRUNK_PO_DIR): diff --git a/release/scripts/modules/bpy/ops.py b/release/scripts/modules/bpy/ops.py index 34beb6035ae..52bf1c04e65 100644 --- a/release/scripts/modules/bpy/ops.py +++ b/release/scripts/modules/bpy/ops.py @@ -74,7 +74,7 @@ class BPyOpsSubMod(object): eg. bpy.ops.object """ - __keys__ = ("module",) + __slots__ = ("module",) def __init__(self, module): self.module = module @@ -111,7 +111,7 @@ class BPyOpsSubModOp(object): eg. bpy.ops.object.somefunc """ - __keys__ = ("module", "func") + __slots__ = ("module", "func") def _get_doc(self): return op_as_string(self.idname()) diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py index 573694ff08e..4ad00eb267e 100644 --- a/release/scripts/modules/bpy/utils.py +++ b/release/scripts/modules/bpy/utils.py @@ -216,7 +216,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False): for mod in _global_loaded_modules: test_reload(mod) - _global_loaded_modules[:] = [] + del _global_loaded_modules[:] for base_path in script_paths(): for path_subdir in _script_module_dirs: diff --git a/release/scripts/modules/bpy_extras/mesh_utils.py b/release/scripts/modules/bpy_extras/mesh_utils.py index ad3cf8c08ec..0166f954dc9 100644 --- a/release/scripts/modules/bpy_extras/mesh_utils.py +++ b/release/scripts/modules/bpy_extras/mesh_utils.py @@ -223,7 +223,7 @@ def edge_loops_from_tessfaces(mesh, tessfaces=None, seams=()): else: other_dir = None - ed_adj[:] = [] + del ed_adj[:] flipped = False @@ -235,22 +235,22 @@ def edge_loops_from_tessfaces(mesh, tessfaces=None, seams=()): if other_dir and flipped is False: flipped = True # only flip the list once context_loop.reverse() - ed_adj[:] = [] + del ed_adj[:] context_loop.append(other_dir) # save 1 look-up ed_adj = edges[context_loop[-1]] if len(ed_adj) != 2: - ed_adj[:] = [] + del ed_adj[:] break else: - ed_adj[:] = [] + del ed_adj[:] break i = ed_adj.index(context_loop[-2]) context_loop.append(ed_adj[not i]) # Dont look at this again - ed_adj[:] = [] + del ed_adj[:] return edge_loops @@ -325,10 +325,12 @@ def ngon_tessellate(from_data, indices, fix_loops=True): fgon to create from existing verts. from_data: either a mesh, or a list/tuple of vectors. - indices: a list of indices to use this list is the ordered closed polyline + :arg indices: a list of indices to use this list is the ordered closed polyline to fill, and can be a subset of the data given. - fix_loops: If this is enabled polylines that use loops to make multiple + :type indices: list + :arg fix_loops: If this is enabled polylines that use loops to make multiple polylines are delt with correctly. + :type fix_loops: bool """ from mathutils.geometry import tessellate_polygon @@ -436,7 +438,7 @@ def ngon_tessellate(from_data, indices, fix_loops=True): if s1[0][1] == s1[-1][1]: # remove endpoints double s1.pop() - s2[:] = [] # Empty this segment s2 so we don't use it again. + del s2[:] # Empty this segment s2 so we don't use it again. return True joining_segments = True diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index 4cd823d9184..e42ae43aed6 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -394,7 +394,7 @@ class Mesh(bpy_types.ID): p.vertices = f loop_index += loop_len - # if no edges - calculae them + # if no edges - calculate them if faces and (not edges): self.update(calc_edges=True) diff --git a/release/scripts/modules/rna_xml.py b/release/scripts/modules/rna_xml.py index fc8e3125228..e21ccd08a35 100644 --- a/release/scripts/modules/rna_xml.py +++ b/release/scripts/modules/rna_xml.py @@ -178,7 +178,7 @@ def rna2xml(fw=print_ln, fw("%s\n" % (ident, value_type_name)) # ------------------------------------------------------------------------- - # needs re-workign to be generic + # needs re-working to be generic if root_node: fw("%s<%s>\n" % (root_ident, root_node)) diff --git a/release/scripts/presets/interface_theme/back_to_black.xml b/release/scripts/presets/interface_theme/back_to_black.xml index 805aa9bd184..0a77aa132a8 100644 --- a/release/scripts/presets/interface_theme/back_to_black.xml +++ b/release/scripts/presets/interface_theme/back_to_black.xml @@ -1,849 +1,852 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + text_sel="#ffffff" + show_shaded="TRUE" + shadetop="-100" + shadedown="0"> - - - + + + text_sel="#ffffff" + show_shaded="TRUE" + shadetop="-100" + shadedown="0"> - - - + + + text_sel="#ffffff" + show_shaded="TRUE" + shadetop="-100" + shadedown="0"> - - - + + - - - - + shadedown="0"> - - - - - + - + text_sel="#ffffff" + show_shaded="TRUE" + shadetop="-100" + shadedown="0"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text="#ffffff" + text_hi="#ffffff" + header="#000000" + header_text="#979797" + header_text_hi="#ffffff" + button="#000000" + button_title="#c5c5c5" + button_text="#c3c3c3" + button_text_hi="#ffffff"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/release/scripts/presets/interface_theme/blender_24x.xml b/release/scripts/presets/interface_theme/blender_24x.xml index 232276e300e..18ae3072208 100644 --- a/release/scripts/presets/interface_theme/blender_24x.xml +++ b/release/scripts/presets/interface_theme/blender_24x.xml @@ -1,849 +1,852 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + shadetop="10" + shadedown="-10"> - - - + + - - - - - - - - + shadetop="10" + shadedown="-10"> - - - - - - - - - - - + + + text_sel="#ffffff" + show_shaded="TRUE" + shadetop="10" + shadedown="-10"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + text="#000000" + text_hi="#0f0f0f" + header="#b4b4b4" + header_text="#000000" + header_text_hi="#ffffff" + button="#b4b4b4" + button_title="#000000" + button_text="#000000" + button_text_hi="#ffffff"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/release/scripts/presets/interface_theme/elsyiun.xml b/release/scripts/presets/interface_theme/elsyiun.xml index 581f5ce82d6..c10eb108000 100644 --- a/release/scripts/presets/interface_theme/elsyiun.xml +++ b/release/scripts/presets/interface_theme/elsyiun.xml @@ -1,849 +1,852 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - + text_sel="#ffffff" + show_shaded="FALSE" + shadetop="0" + shadedown="0"> - - - + + + + + + - - - - + shadedown="0"> - - - + + + shadetop="5" + shadedown="0"> - + - + text_sel="#ffffff" + show_shaded="TRUE" + shadetop="5" + shadedown="0"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text="#000000" + text_hi="#ffffff" + header="#3b3b3b" + header_text="#000000" + header_text_hi="#ffffff" + button="#3b3b3b" + button_title="#8b8b8b" + button_text="#8b8b8b" + button_text_hi="#ffffff"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/release/scripts/presets/interface_theme/hexagon.xml b/release/scripts/presets/interface_theme/hexagon.xml index 61730583396..ad514bbbafa 100644 --- a/release/scripts/presets/interface_theme/hexagon.xml +++ b/release/scripts/presets/interface_theme/hexagon.xml @@ -1,849 +1,852 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + shadetop="10" + shadedown="0"> - - - - - - - - - - - + + - - - - - - - - + text_sel="#000000" + show_shaded="TRUE" + shadetop="10" + shadedown="0"> - + + + + + - + text_sel="#000000" + show_shaded="TRUE" + shadetop="10" + shadedown="0"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + text="#000000" + text_hi="#0f0f0f" + header="#5c606c" + header_text="#dddddd" + header_text_hi="#ffffff" + button="#6c717f" + button_title="#d7d7d7" + button_text="#d7d7d7" + button_text_hi="#ffffff"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/release/scripts/presets/interface_theme/ubuntu_ambiance.xml b/release/scripts/presets/interface_theme/ubuntu_ambiance.xml index 05075f06239..8f4a42b6ab7 100644 --- a/release/scripts/presets/interface_theme/ubuntu_ambiance.xml +++ b/release/scripts/presets/interface_theme/ubuntu_ambiance.xml @@ -1,849 +1,852 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + text="#dfdfdf" + text_sel="#dfdfdf" + show_shaded="TRUE" + shadetop="21" + shadedown="-21"> - - - + + + - - - + + - - - - + text_sel="#dfdbcf" + show_shaded="TRUE" + shadetop="5" + shadedown="-5"> - - - + + + text_sel="#ffffff" + show_shaded="TRUE" + shadetop="-10" + shadedown="0"> - + - + text_sel="#dfdbcf" + show_shaded="TRUE" + shadetop="15" + shadedown="-5"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + button_text="#000000" + button_text_hi="#ffffff"> + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py index b5df519cf59..ec8efc8d371 100644 --- a/release/scripts/presets/keyconfig/maya.py +++ b/release/scripts/presets/keyconfig/maya.py @@ -366,7 +366,7 @@ kmi = km.keymap_items.new('mesh.split', 'Y', 'PRESS') kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'CLICK', ctrl=True) kmi = km.keymap_items.new('mesh.delete', 'X', 'PRESS') kmi = km.keymap_items.new('mesh.delete', 'DEL', 'PRESS') -kmi = km.keymap_items.new('mesh.knifetool', 'LEFTMOUSE', 'PRESS', key_modifier='K') +kmi = km.keymap_items.new('mesh.knife_tool', 'LEFTMOUSE', 'PRESS', key_modifier='K') # BMESH_TODO: midpoints for knife were moved to modal keymap #kmi = km.keymap_items.new('mesh.knifetool', 'LEFTMOUSE', 'PRESS', shift=True, key_modifier='K') #kmi.properties.type = 'MIDPOINTS' diff --git a/release/scripts/startup/bl_operators/image.py b/release/scripts/startup/bl_operators/image.py index 074069255bc..ce328b86eac 100644 --- a/release/scripts/startup/bl_operators/image.py +++ b/release/scripts/startup/bl_operators/image.py @@ -224,7 +224,7 @@ class ProjectApply(Operator): image_name = ProjectEdit._proj_hack[0] # TODO, deal with this nicer try: - image = bpy.data.images[image_name] + image = bpy.data.images[image_name, None] except KeyError: import traceback traceback.print_exc() diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py index 4e90f2e8585..9e449f325d6 100644 --- a/release/scripts/startup/bl_operators/object.py +++ b/release/scripts/startup/bl_operators/object.py @@ -665,15 +665,60 @@ class TransformsToDeltasAnim(Operator): return (obs is not None) def execute(self, context): + # map from standard transform paths to "new" transform paths + STANDARD_TO_DELTA_PATHS = { + "location" : "delta_location", + "rotation_euler" : "delta_rotation_euler", + "rotation_quaternion" : "delta_rotation_quaternion", + #"rotation_axis_angle" : "delta_rotation_axis_angle", + "scale" : "delta_scale" + } + DELTA_PATHS = STANDARD_TO_DELTA_PATHS.values() + + # try to apply on each selected object + success = False for obj in context.selected_editable_objects: - # get animation data adt = obj.animation_data if (adt is None) or (adt.action is None): self.report({'WARNING'}, "No animation data to convert on object: %r" % obj.name) continue - + + # first pass over F-Curves: ensure that we don't have conflicting + # transforms already (e.g. if this was applied already) [#29110] + existingFCurves = {} + for fcu in adt.action.fcurves: + # get "delta" path - i.e. the final paths which may clash + path = fcu.data_path + if path in STANDARD_TO_DELTA_PATHS: + # to be converted - conflicts may exist... + dpath = STANDARD_TO_DELTA_PATHS[path] + elif path in DELTA_PATHS: + # already delta - check for conflicts... + dpath = path + else: + # non-transform - ignore + continue + + # a delta path like this for the same index shouldn't + # exist already, otherwise we've got a conflict + if dpath in existingFCurves: + # ensure that this index hasn't occurred before + if fcu.array_index in existingFCurves[dpath]: + # conflict + self.report({'ERROR'}, + "Object '%r' already has '%r' F-Curve(s). Remove these before trying again" % + (obj.name, dpath)) + return {'CANCELLED'} + else: + # no conflict here + existingFCurves[dpath] += [fcu.array_index] + else: + # no conflict yet + existingFCurves[dpath] = [fcu.array_index] + + # if F-Curve uses standard transform path # just append "delta_" to this path for fcu in adt.action.fcurves: diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py index b7adf53dbf1..ee9769d8b43 100644 --- a/release/scripts/startup/bl_operators/presets.py +++ b/release/scripts/startup/bl_operators/presets.py @@ -554,6 +554,12 @@ class WM_MT_operator_presets(Menu): def draw(self, context): self.operator = context.active_operator.bl_idname + + # dummy 'default' menu item + layout = self.layout + layout.operator("wm.operator_defaults") + layout.separator() + Menu.draw_preset(self, context) @property diff --git a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py index 694412e51d7..6d1f35fe937 100644 --- a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py +++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py @@ -116,8 +116,12 @@ class PlayRenderedAnim(Operator): cmd = [player_path] # extra options, fps controls etc. if preset in {'BLENDER24', 'INTERNAL'}: - opts = ["-a", "-f", str(rd.fps), str(rd.fps_base), - "-j", str(scene.frame_step), file] + opts = ["-a", + "-f", str(rd.fps), str(rd.fps_base), + "-s", str(scene.frame_start), + "-e", str(scene.frame_end), + "-j", str(scene.frame_step), + file] cmd.extend(opts) elif preset == 'DJV': opts = [file, "-playback_speed", "%d" % int(rd.fps / rd.fps_base)] diff --git a/release/scripts/startup/bl_operators/uvcalc_follow_active.py b/release/scripts/startup/bl_operators/uvcalc_follow_active.py index b60b5257984..727c4ad739f 100644 --- a/release/scripts/startup/bl_operators/uvcalc_follow_active.py +++ b/release/scripts/startup/bl_operators/uvcalc_follow_active.py @@ -26,195 +26,124 @@ from bpy.types import Operator def extend(obj, operator, EXTEND_MODE): - from bpy_extras import mesh_utils - + import bmesh me = obj.data - me_verts = me.vertices - # script will fail without UVs if not me.uv_textures: me.uv_textures.new() - - # Toggle Edit mode - is_editmode = (obj.mode == 'EDIT') - if is_editmode: - bpy.ops.object.mode_set(mode='OBJECT') - - #t = sys.time() - edge_average_lengths = {} - - OTHER_INDEX = 2, 3, 0, 1 - - def extend_uvs(face_source, face_target, edge_key): - """ - Takes 2 faces, - Projects its extends its UV coords onto the face next to it. - Both faces must share an edge - """ - - def face_edge_vs(vi): - vlen = len(vi) - return [(vi[i], vi[(i + 1) % vlen]) for i in range(vlen)] - - vidx_source = face_source.vertices - vidx_target = face_target.vertices - - uv_layer = me.uv_layers.active.data - uvs_source = [uv_layer[i].uv for i in face_source.loop_indices] - uvs_target = [uv_layer[i].uv for i in face_target.loop_indices] - - # vertex index is the key, uv is the value - - uvs_vhash_source = {vindex: uvs_source[i] for i, vindex in enumerate(vidx_source)} - - uvs_vhash_target = {vindex: uvs_target[i] for i, vindex in enumerate(vidx_target)} - - edge_idxs_source = face_edge_vs(vidx_source) - edge_idxs_target = face_edge_vs(vidx_target) - - source_matching_edge = -1 - target_matching_edge = -1 - - edge_key_swap = edge_key[1], edge_key[0] - - try: - source_matching_edge = edge_idxs_source.index(edge_key) - except: - source_matching_edge = edge_idxs_source.index(edge_key_swap) - try: - target_matching_edge = edge_idxs_target.index(edge_key) - except: - target_matching_edge = edge_idxs_target.index(edge_key_swap) - - edgepair_inner_source = edge_idxs_source[source_matching_edge] - edgepair_inner_target = edge_idxs_target[target_matching_edge] - edgepair_outer_source = edge_idxs_source[OTHER_INDEX[source_matching_edge]] - edgepair_outer_target = edge_idxs_target[OTHER_INDEX[target_matching_edge]] - - if edge_idxs_source[source_matching_edge] == edge_idxs_target[target_matching_edge]: - iA = 0 # Flipped, most common - iB = 1 - else: # The normals of these faces must be different - iA = 1 - iB = 0 - - # Set the target UV's touching source face, no tricky calculations needed, - uvs_vhash_target[edgepair_inner_target[0]][:] = uvs_vhash_source[edgepair_inner_source[iA]] - uvs_vhash_target[edgepair_inner_target[1]][:] = uvs_vhash_source[edgepair_inner_source[iB]] - - # Set the 2 UV's on the target face that are not touching - # for this we need to do basic expanding on the source faces UV's - if EXTEND_MODE == 'LENGTH': - - try: # divide by zero is possible - ''' - measure the length of each face from the middle of each edge to the opposite - along the axis we are copying, use this - ''' - i1a = edgepair_outer_target[iB] - i2a = edgepair_inner_target[iA] - if i1a > i2a: - i1a, i2a = i2a, i1a - - i1b = edgepair_outer_source[iB] - i2b = edgepair_inner_source[iA] - if i1b > i2b: - i1b, i2b = i2b, i1b - # print edge_average_lengths - factor = edge_average_lengths[i1a, i2a][0] / edge_average_lengths[i1b, i2b][0] - except: - # Div By Zero? - factor = 1.0 - - uvs_vhash_target[edgepair_outer_target[iB]][:] = uvs_vhash_source[edgepair_inner_source[0]] + factor * (uvs_vhash_source[edgepair_inner_source[0]] - uvs_vhash_source[edgepair_outer_source[1]]) - uvs_vhash_target[edgepair_outer_target[iA]][:] = uvs_vhash_source[edgepair_inner_source[1]] + factor * (uvs_vhash_source[edgepair_inner_source[1]] - uvs_vhash_source[edgepair_outer_source[0]]) - - else: - # same as above but with no factors - uvs_vhash_target[edgepair_outer_target[iB]][:] = uvs_vhash_source[edgepair_inner_source[0]] + (uvs_vhash_source[edgepair_inner_source[0]] - uvs_vhash_source[edgepair_outer_source[1]]) - uvs_vhash_target[edgepair_outer_target[iA]][:] = uvs_vhash_source[edgepair_inner_source[1]] + (uvs_vhash_source[edgepair_inner_source[1]] - uvs_vhash_source[edgepair_outer_source[0]]) - - face_act = me.polygons.active - if face_act == -1: + + bm = bmesh.from_edit_mesh(me) + + f_act = bm.faces.active + uv_act = bm.loops.layers.uv.active + + if f_act is None: operator.report({'ERROR'}, "No active face") return - - face_sel = [f for f in me.polygons if len(f.vertices) == 4 and f.select] - - face_act_local_index = -1 - for i, f in enumerate(face_sel): - if f.index == face_act: - face_act_local_index = i - break - - if face_act_local_index == -1: - operator.report({'ERROR'}, "Active face not selected") + elif len(f_act.verts) != 4: + operator.report({'ERROR'}, "Active face must be a quad") return - # Modes - # 0 not yet searched for. - # 1:mapped, use search from this face - removed! - # 2:all siblings have been searched. don't search again. - face_modes = [0] * len(face_sel) - face_modes[face_act_local_index] = 1 # extend UV's from this face. + faces = [f for f in bm.faces if f.select and len(f.verts) == 4] - # Edge connectivity - edge_faces = {} - for i, f in enumerate(face_sel): - for edkey in f.edge_keys: + for f in faces: + f.tag = False + f_act.tag = True + + + # our own local walker + def walk_face(f): + # all faces in this list must be tagged + f.tag = True + faces_a = [f] + faces_b = [] + + while faces_a: + for f in faces_a: + for l in f.loops: + l_edge = l.edge + if (l_edge.is_manifold is True) and (l_edge.seam is False): + l_other = l.link_loop_radial_next + f_other = l_other.face + if not f_other.tag: + yield (f, l, f_other) + f_other.tag = True + faces_b.append(f_other) + # swap + faces_a, faces_b = faces_b, faces_a + faces_b.clear() + + def extrapolate_uv(fac, + l_a_outer, l_a_inner, + l_b_outer, l_b_inner): + l_b_inner[:] = l_a_inner + l_b_outer[:] = l_a_inner + ((l_a_inner - l_a_outer) * fac) + + def apply_uv(f_prev, l_prev, f_next): + l_a = [None, None, None, None] + l_b = [None, None, None, None] + + l_a[0] = l_prev + l_a[1] = l_a[0].link_loop_next + l_a[2] = l_a[1].link_loop_next + l_a[3] = l_a[2].link_loop_next + + # l_b + # +-----------+ + # |(3) |(2) + # | | + # |l_next(0) |(1) + # +-----------+ + # ^ + # l_a | + # +-----------+ + # |l_prev(0) |(1) + # | (f) | + # |(3) |(2) + # +-----------+ + # copy from this face to the one above. + + # get the other loops + l_next = l_prev.link_loop_radial_next + if l_next.vert != l_prev.vert: + l_b[1] = l_next + l_b[0] = l_b[1].link_loop_next + l_b[3] = l_b[0].link_loop_next + l_b[2] = l_b[3].link_loop_next + else: + l_b[0] = l_next + l_b[1] = l_b[0].link_loop_next + l_b[2] = l_b[1].link_loop_next + l_b[3] = l_b[2].link_loop_next + + l_a_uv = [l[uv_act].uv for l in l_a] + l_b_uv = [l[uv_act].uv for l in l_b] + + if EXTEND_MODE == 'LENGTH': + a0, b0, c0 = l_a[3].vert.co, l_a[0].vert.co, l_b[3].vert.co + a1, b1, c1 = l_a[2].vert.co, l_a[1].vert.co, l_b[2].vert.co + + d1 = (a0 - b0).length + (a1 - b1).length + d2 = (b0 - c0).length + (b1 - c1).length try: - edge_faces[edkey].append(i) - except: - edge_faces[edkey] = [i] + fac = d2 / d1 + except ZeroDivisionError: + fac = 1.0 + else: + fac = 1.0 - if EXTEND_MODE == 'LENGTH': - edge_loops = mesh_utils.edge_loops_from_tessfaces(me, face_sel, [ed.key for ed in me.edges if ed.use_seam]) - me_verts = me.vertices - for loop in edge_loops: - looplen = [0.0] - for ed in loop: - edge_average_lengths[ed] = looplen - looplen[0] += (me_verts[ed[0]].co - me_verts[ed[1]].co).length - looplen[0] = looplen[0] / len(loop) + extrapolate_uv(fac, + l_a_uv[3], l_a_uv[0], + l_b_uv[3], l_b_uv[0]) - # remove seams, so we don't map across seams. - for ed in me.edges: - if ed.use_seam: - # remove the edge pair if we can - try: - del edge_faces[ed.key] - except: - pass - # Done finding seams + extrapolate_uv(fac, + l_a_uv[2], l_a_uv[1], + l_b_uv[2], l_b_uv[1]) - # face connectivity - faces around each face - # only store a list of indices for each face. - face_faces = [[] for i in range(len(face_sel))] + for f_triple in walk_face(f_act): + apply_uv(*f_triple) - for edge_key, faces in edge_faces.items(): - if len(faces) == 2: # Only do edges with 2 face users for now - face_faces[faces[0]].append((faces[1], edge_key)) - face_faces[faces[1]].append((faces[0], edge_key)) - - # Now we know what face is connected to what other face, map them by connectivity - ok = True - while ok: - ok = False - for i in range(len(face_sel)): - if face_modes[i] == 1: # searchable - for f_sibling, edge_key in face_faces[i]: - if face_modes[f_sibling] == 0: - face_modes[f_sibling] = 1 # mapped and search from. - extend_uvs(face_sel[i], face_sel[f_sibling], edge_key) - face_modes[i] = 1 # we can map from this one now. - ok = True # keep searching - - face_modes[i] = 2 # don't search again - - if is_editmode: - bpy.ops.object.mode_set(mode='EDIT') - else: - me.update_tag() + bmesh.update_edit_mesh(me, False) def main(context, operator): diff --git a/release/scripts/startup/bl_operators/uvcalc_lightmap.py b/release/scripts/startup/bl_operators/uvcalc_lightmap.py index 526d78c4c11..198b3660ff8 100644 --- a/release/scripts/startup/bl_operators/uvcalc_lightmap.py +++ b/release/scripts/startup/bl_operators/uvcalc_lightmap.py @@ -552,7 +552,7 @@ class LightMapPack(Operator): # Disable REGISTER flag for now because this operator might create new # images. This leads to non-proper operator redo because current undo # stack is local for edit mode and can not remove images created by this - # oprtator. + # operator. # Proper solution would be to make undo stack aware of such things, # but for now just disable redo. Keep undo here so unwanted changes to uv # coords might be undone. diff --git a/release/scripts/startup/bl_operators/uvcalc_smart_project.py b/release/scripts/startup/bl_operators/uvcalc_smart_project.py index 9fa44cac812..160ca5c6977 100644 --- a/release/scripts/startup/bl_operators/uvcalc_smart_project.py +++ b/release/scripts/startup/bl_operators/uvcalc_smart_project.py @@ -23,7 +23,7 @@ import bpy from bpy.types import Operator DEG_TO_RAD = 0.017453292519943295 # pi/180.0 -SMALL_NUM = 0.000000001 +SMALL_NUM = 0.0000001 # see bug [#31598] why we dont have smaller values BIG_NUM = 1e15 global USER_FILL_HOLES @@ -517,7 +517,7 @@ def mergeUvIslands(islandList): for uv in f.uv: uv+= offset - sourceIsland[0][:] = [] # Empty + del sourceIsland[0][:] # Empty # Move edge loop into new and offset. @@ -527,7 +527,7 @@ def mergeUvIslands(islandList): (e[0]+offset, e[1]+offset, e[2])\ ) for e in sourceIsland[6] ] ) - sourceIsland[6][:] = [] # Empty + del sourceIsland[6][:] # Empty # Sort by edge length, reverse so biggest are first. @@ -540,7 +540,7 @@ def mergeUvIslands(islandList): for p in sourceIsland[7]: p+= offset - sourceIsland[7][:] = [] + del sourceIsland[7][:] # Decrement the efficiency @@ -759,7 +759,7 @@ class thickface(object): self.v = [mesh_verts[i] for i in face.vertices] self.uv = [uv_layer[i].uv for i in face.loop_indices] - self.no = face.normal + self.no = face.normal.copy() self.area = face.area self.edge_keys = face.edge_keys @@ -993,7 +993,7 @@ def main(context, if mostUniqueAngle < USER_PROJECTION_LIMIT_CONVERTED: #print 'adding', mostUniqueAngle, USER_PROJECTION_LIMIT, len(newProjectMeshFaces) # Now weight the vector to all its faces, will give a more direct projection - # if the face its self was not representive of the normal from surrounding faces. + # if the face its self was not representative of the normal from surrounding faces. newProjectVec = tempMeshFaces[mostUniqueIndex].no newProjectMeshFaces = [tempMeshFaces.pop(mostUniqueIndex)] diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index 2bff11a686d..105b532ac38 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -41,12 +41,17 @@ class MESH_OT_delete_edgeloop(Operator): return bpy.ops.transform.edge_slide.poll() def execute(self, context): + mesh = context.object.data + use_mirror_x = mesh.use_mirror_x + mesh.use_mirror_x = False if 'FINISHED' in bpy.ops.transform.edge_slide(value=1.0): bpy.ops.mesh.select_more() bpy.ops.mesh.remove_doubles() - return {'FINISHED'} - - return {'CANCELLED'} + ret = {'FINISHED'} + else: + ret = {'CANCELLED'} + mesh.use_mirror_x = use_mirror_x + return ret rna_path_prop = StringProperty( name="Context Attributes", @@ -1044,6 +1049,8 @@ class WM_OT_properties_edit(Operator): try: value_eval = eval(value) + # assert else None -> None, not "None", see [#33431] + assert(type(value_eval) in {str, float, int, bool, tuple, list}) except: value_eval = value diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py index 50c34be1414..845beb0f862 100644 --- a/release/scripts/startup/bl_ui/properties_data_armature.py +++ b/release/scripts/startup/bl_ui/properties_data_armature.py @@ -239,7 +239,7 @@ class DATA_PT_ghost(ArmatureButtonsPanel, Panel): class DATA_PT_iksolver_itasc(ArmatureButtonsPanel, Panel): - bl_label = "iTaSC parameters" + bl_label = "Inverse Kinematics" bl_options = {'DEFAULT_CLOSED'} @classmethod diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py index 1441c642d51..fdaee6b7cde 100644 --- a/release/scripts/startup/bl_ui/properties_data_bone.py +++ b/release/scripts/startup/bl_ui/properties_data_bone.py @@ -244,7 +244,6 @@ class BONE_PT_inverse_kinematics(BoneButtonsPanel, Panel): pchan = ob.pose.bones[bone.name] row = layout.row() - row.prop(ob.pose, "ik_solver") active = pchan.is_in_ik_chain diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py index 5f6036c8945..25cecc90c70 100644 --- a/release/scripts/startup/bl_ui/properties_data_camera.py +++ b/release/scripts/startup/bl_ui/properties_data_camera.py @@ -142,8 +142,12 @@ class DATA_PT_camera(CameraButtonsPanel, Panel): if cam.sensor_fit == 'AUTO': col.prop(cam, "sensor_width", text="Size") else: - col.prop(cam, "sensor_width", text="Width") - col.prop(cam, "sensor_height", text="Height") + sub = col.column() + sub.active = cam.sensor_fit == 'HORIZONTAL' + sub.prop(cam, "sensor_width", text="Width") + sub = col.column() + sub.active = cam.sensor_fit == 'VERTICAL' + sub.prop(cam, "sensor_height", text="Height") col = split.column(align=True) col.prop(cam, "sensor_fit", text="") diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py index a8f4aa30e95..7747ef45c4d 100644 --- a/release/scripts/startup/bl_ui/properties_data_curve.py +++ b/release/scripts/startup/bl_ui/properties_data_curve.py @@ -174,11 +174,14 @@ class DATA_PT_geometry_curve(CurveButtonsPanel, Panel): col.prop(curve, "bevel_object", text="") col = layout.column(align=True) - col.active = (curve.bevel_object is not None) - col.prop(curve, "use_fill_caps") col.prop(curve, "bevel_factor_start") col.prop(curve, "bevel_factor_end") + row = col.row() + row.active = (curve.bevel_object is not None) + row.prop(curve, "use_fill_caps") + row.prop(curve, "use_map_taper") + class DATA_PT_pathanim(CurveButtonsPanelCurve, Panel): bl_label = "Path Animation" diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index 902358813df..62461d800f6 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -625,6 +625,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col.prop(md, "wrap_method", text="") if md.wrap_method == 'PROJECT': + col.prop(md, "project_limit", text="Limit") split = layout.split(percentage=0.25) col = split.column() @@ -642,8 +643,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col.label(text="Cull Faces:") col.prop(md, "cull_face", expand=True) - layout.label(text="Auxiliary Target:") - layout.prop(md, "auxiliary_target", text="") + layout.prop(md, "auxiliary_target") elif md.wrap_method == 'NEAREST_SURFACEPOINT': layout.prop(md, "use_keep_above_surface") @@ -1029,5 +1029,8 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col.prop(md, "use_y_symmetry") col.prop(md, "use_z_symmetry") + def TRIANGULATE(self, layout, ob, md): + layout.prop(md, "use_beauty") + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/release/scripts/startup/bl_ui/properties_object_constraint.py b/release/scripts/startup/bl_ui/properties_object_constraint.py index 3fa63bac13c..eb0929895f8 100644 --- a/release/scripts/startup/bl_ui/properties_object_constraint.py +++ b/release/scripts/startup/bl_ui/properties_object_constraint.py @@ -134,7 +134,7 @@ class ConstraintButtonsPanel(): layout.prop(con, "ik_type") getattr(self, 'IK_' + con.ik_type)(context, layout, con) else: - # Legacy IK constraint + # Standard IK constraint self.target_template(layout, con) layout.prop(con, "pole_target") @@ -151,17 +151,27 @@ class ConstraintButtonsPanel(): col.prop(con, "iterations") col.prop(con, "chain_count") - col.label(text="Weight:") - col.prop(con, "weight", text="Position", slider=True) - sub = col.column() - sub.active = con.use_rotation - sub.prop(con, "orient_weight", text="Rotation", slider=True) - col = split.column() col.prop(con, "use_tail") col.prop(con, "use_stretch") - col.separator() - col.prop(con, "use_rotation") + + layout.label(text="Weight:") + + split = layout.split() + col = split.column() + row = col.row(align=True) + row.prop(con, "use_location", text="") + sub = row.row() + sub.active = con.use_location + sub.prop(con, "weight", text="Position", slider=True) + + col = split.column() + row = col.row(align=True) + row.prop(con, "use_rotation", text="") + sub = row.row() + sub.active = con.use_rotation + sub.prop(con, "orient_weight", text="Rotation", slider=True) + def IK_COPY_POSE(self, context, layout, con): self.target_template(layout, con) diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py index 6fcd56fb99e..3f672d2a977 100644 --- a/release/scripts/startup/bl_ui/properties_particle.py +++ b/release/scripts/startup/bl_ui/properties_particle.py @@ -148,7 +148,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel): #row.label(text="Render") if part.is_fluid: - layout.label(text="{} fluid particles for this frame".format(str(part.count))) + layout.label(text="%d fluid particles for this frame" % part.count) return row = col.row() diff --git a/release/scripts/startup/bl_ui/space_console.py b/release/scripts/startup/bl_ui/space_console.py index 5ff179902a3..23d16c14f2d 100644 --- a/release/scripts/startup/bl_ui/space_console.py +++ b/release/scripts/startup/bl_ui/space_console.py @@ -25,7 +25,7 @@ class CONSOLE_HT_header(Header): bl_space_type = 'CONSOLE' def draw(self, context): - layout = self.layout.row(align=True) + layout = self.layout.row() layout.template_header() diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index a81553a8257..5535070c1c4 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -241,9 +241,9 @@ class DOPESHEET_MT_channel(Menu): layout.operator("anim.channels_delete") layout.separator() - layout.operator("anim.channels_setting_toggle") - layout.operator("anim.channels_setting_enable") - layout.operator("anim.channels_setting_disable") + layout.operator_menu_enum("anim.channels_setting_toggle", "type") + layout.operator_menu_enum("anim.channels_setting_enable", "type") + layout.operator_menu_enum("anim.channels_setting_disable", "type") layout.separator() layout.operator("anim.channels_editable_toggle") diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index e89bd78a84f..4cb6538458f 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -161,9 +161,9 @@ class GRAPH_MT_channel(Menu): layout.operator("anim.channels_delete") layout.separator() - layout.operator("anim.channels_setting_toggle") - layout.operator("anim.channels_setting_enable") - layout.operator("anim.channels_setting_disable") + layout.operator_menu_enum("anim.channels_setting_toggle", "type") + layout.operator_menu_enum("anim.channels_setting_enable", "type") + layout.operator_menu_enum("anim.channels_setting_disable", "type") layout.separator() layout.operator("anim.channels_editable_toggle") diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 5302ad9b471..1ea20d96386 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -249,6 +249,7 @@ class IMAGE_MT_uvs_weldalign(Menu): layout = self.layout layout.operator("uv.weld") # W, 1 + layout.operator("uv.remove_doubles") layout.operator_enum("uv.align", "axis") # W, 2/3/4 @@ -413,7 +414,9 @@ class IMAGE_HT_header(Header): row = layout.row(align=True) row.prop(toolsettings, "use_snap", text="") - row.prop(toolsettings, "snap_target", text="") + row.prop(toolsettings, "snap_uv_element", text="", icon_only=True) + if toolsettings.snap_uv_element != 'INCREMENT': + row.prop(toolsettings, "snap_target", text="") mesh = context.edit_object.data layout.prop_search(mesh.uv_textures, "active", mesh, "uv_textures", text="") @@ -684,7 +687,7 @@ class IMAGE_PT_paint(Panel, ImagePaintPanel): if brush: col = layout.column() - col.template_color_wheel(brush, "color", value_slider=True) + col.template_color_picker(brush, "color", value_slider=True) col.prop(brush, "color", text="") row = col.row(align=True) diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py index c0f2d3c361b..8df117e27a0 100644 --- a/release/scripts/startup/bl_ui/space_info.py +++ b/release/scripts/startup/bl_ui/space_info.py @@ -193,7 +193,7 @@ class INFO_MT_mesh_add(Menu): def draw(self, context): layout = self.layout - layout.operator_context = 'EXEC_REGION_WIN' + layout.operator_context = 'INVOKE_REGION_WIN' layout.operator("mesh.primitive_plane_add", icon='MESH_PLANE', text="Plane") layout.operator("mesh.primitive_cube_add", icon='MESH_CUBE', text="Cube") layout.operator("mesh.primitive_circle_add", icon='MESH_CIRCLE', text="Circle") @@ -373,7 +373,7 @@ class INFO_MT_help(Menu): layout = self.layout layout.operator("wm.url_open", text="Manual", icon='HELP').url = "http://wiki.blender.org/index.php/Doc:2.6/Manual" - layout.operator("wm.url_open", text="Release Log", icon='URL').url = "http://www.blender.org/development/release-logs/blender-264" + layout.operator("wm.url_open", text="Release Log", icon='URL').url = "http://www.blender.org/development/release-logs/blender-265" layout.separator() layout.operator("wm.url_open", text="Blender Website", icon='URL').url = "http://www.blender.org" diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index cba45d4c2b7..fdfd43157c7 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -31,21 +31,21 @@ def act_strip(context): def draw_color_balance(layout, color_balance): col = layout.column() col.label(text="Lift:") - col.template_color_wheel(color_balance, "lift", value_slider=True, cubic=True) + col.template_color_picker(color_balance, "lift", value_slider=True, cubic=True) row = col.row() row.prop(color_balance, "lift", text="") row.prop(color_balance, "invert_lift", text="Inverse") col = layout.column() col.label(text="Gamma:") - col.template_color_wheel(color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True) + col.template_color_picker(color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True) row = col.row() row.prop(color_balance, "gamma", text="") row.prop(color_balance, "invert_gamma", text="Inverse") col = layout.column() col.label(text="Gain:") - col.template_color_wheel(color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True) + col.template_color_picker(color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True) row = col.row() row.prop(color_balance, "gain", text="") row.prop(color_balance, "invert_gain", text="Inverse") @@ -707,8 +707,6 @@ class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel): layout.template_ID(strip, "scene") scene = strip.scene - if scene: - layout.prop(scene.render, "use_sequencer") layout.label(text="Camera Override") layout.template_ID(strip, "scene_camera") diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py index a64f8aa4aed..fa8752c21be 100644 --- a/release/scripts/startup/bl_ui/space_text.py +++ b/release/scripts/startup/bl_ui/space_text.py @@ -137,9 +137,6 @@ class TEXT_PT_find(Panel): row.operator("text.replace_set_selected", text="", icon='TEXT') col.operator("text.replace") - # mark - layout.operator("text.mark_all") - # settings layout.prop(st, "use_match_case") row = layout.row() @@ -216,17 +213,6 @@ class TEXT_MT_edit_select(Menu): layout.operator("text.select_line") -class TEXT_MT_edit_markers(Menu): - bl_label = "Markers" - - def draw(self, context): - layout = self.layout - - layout.operator("text.markers_clear") - layout.operator("text.next_marker") - layout.operator("text.previous_marker") - - class TEXT_MT_format(Menu): bl_label = "Format" @@ -290,7 +276,6 @@ class TEXT_MT_edit(Menu): layout.separator() layout.menu("TEXT_MT_edit_select") - layout.menu("TEXT_MT_edit_markers") layout.separator() diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 455bf210ac2..0bb25e98456 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -422,7 +422,7 @@ class USERPREF_PT_system(Panel): col.separator() col.separator() - if hasattr(system, "compute_device"): + if hasattr(system, "compute_device_type"): col.label(text="Compute Device:") col.row().prop(system, "compute_device_type", expand=True) sub = col.row() @@ -442,10 +442,9 @@ class USERPREF_PT_system(Panel): col.label(text="Anisotropic Filtering") col.prop(system, "anisotropic_filter", text="") col.prop(system, "use_vertex_buffer_objects") - # Anti-aliasing is disabled as it breaks border/lasso select - #~ col.prop(system, "use_antialiasing") col.label(text="Window Draw Method:") col.prop(system, "window_draw_method", text="") + col.prop(system, "multi_sample", text="") col.label(text="Text Draw Options:") col.prop(system, "use_text_antialiasing") col.label(text="Textures:") @@ -728,6 +727,29 @@ class USERPREF_PT_theme(Panel): colsub = padding.column() colsub.row().prop(ui, "header") + col.separator() + col.separator() + + ui = theme.user_interface + col.label("Axis Colors:") + + row = col.row() + + subsplit = row.split(percentage=0.95) + + padding = subsplit.split(percentage=0.15) + colsub = padding.column() + colsub = padding.column() + colsub.row().prop(ui, "axis_x") + colsub.row().prop(ui, "axis_y") + colsub.row().prop(ui, "axis_z") + + subsplit = row.split(percentage=0.85) + + padding = subsplit.split(percentage=0.15) + colsub = padding.column() + colsub = padding.column() + layout.separator() layout.separator() elif theme.theme_area == 'BONE_COLOR_SETS': diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 21a80df9ead..b1dfc397ce0 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -168,6 +168,8 @@ class VIEW3D_MT_transform(VIEW3D_MT_transform_base): # generic... layout = self.layout + layout.operator("transform.shrink_fatten", text="Shrink Fatten") + layout.separator() layout.operator("transform.translate", text="Move Texture Space").texture_space = True @@ -1734,18 +1736,9 @@ class VIEW3D_MT_edit_mesh_select_mode(Menu): layout = self.layout layout.operator_context = 'INVOKE_REGION_WIN' - - props = layout.operator("wm.context_set_value", text="Vertex", icon='VERTEXSEL') - props.value = "(True, False, False)" - props.data_path = "tool_settings.mesh_select_mode" - - props = layout.operator("wm.context_set_value", text="Edge", icon='EDGESEL') - props.value = "(False, True, False)" - props.data_path = "tool_settings.mesh_select_mode" - - props = layout.operator("wm.context_set_value", text="Face", icon='FACESEL') - props.value = "(False, False, True)" - props.data_path = "tool_settings.mesh_select_mode" + layout.operator("mesh.select_mode", text="Vertex", icon='VERTEXSEL').type = 'VERT' + layout.operator("mesh.select_mode", text="Edge", icon='EDGESEL').type = 'EDGE' + layout.operator("mesh.select_mode", text="Face", icon='FACESEL').type = 'FACE' class VIEW3D_MT_edit_mesh_extrude(Menu): @@ -1845,8 +1838,8 @@ class VIEW3D_MT_edit_mesh_edges(Menu): layout.separator() - layout.operator("mesh.edge_rotate", text="Rotate Edge CW").direction = 'CW' - layout.operator("mesh.edge_rotate", text="Rotate Edge CCW").direction = 'CCW' + layout.operator("mesh.edge_rotate", text="Rotate Edge CW").use_ccw = False + layout.operator("mesh.edge_rotate", text="Rotate Edge CCW").use_ccw = True layout.separator() @@ -1895,13 +1888,13 @@ class VIEW3D_MT_edit_mesh_faces(Menu): layout.separator() - layout.operator("mesh.edge_rotate", text="Rotate Edge CW").direction = 'CW' + layout.operator("mesh.edge_rotate", text="Rotate Edge CW").use_ccw = False layout.separator() - layout.operator_menu_enum("mesh.uvs_rotate", "direction") + layout.operator("mesh.uvs_rotate") layout.operator("mesh.uvs_reverse") - layout.operator_menu_enum("mesh.colors_rotate", "direction") + layout.operator("mesh.colors_rotate") layout.operator("mesh.colors_reverse") diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 49355de4006..91132a72b07 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -633,7 +633,7 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel): elif context.image_paint_object and brush: col = layout.column() - col.template_color_wheel(brush, "color", value_slider=True) + col.template_color_picker(brush, "color", value_slider=True) col.prop(brush, "color", text="") row = col.row(align=True) @@ -681,7 +681,7 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel): # Vertex Paint Mode # elif context.vertex_paint_object and brush: col = layout.column() - col.template_color_wheel(brush, "color", value_slider=True) + col.template_color_picker(brush, "color", value_slider=True) col.prop(brush, "color", text="") row = col.row(align=True) @@ -1048,7 +1048,7 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel, Panel): @classmethod def poll(cls, context): brush = context.tool_settings.image_paint.brush - return (brush and brush.image_tool != 'SOFTEN') + return (brush is not None) def draw_header(self, context): ipaint = context.tool_settings.image_paint diff --git a/release/scripts/templates/bmesh_simple.py b/release/scripts/templates/bmesh_simple.py index 656febf4918..45e6b52d578 100644 --- a/release/scripts/templates/bmesh_simple.py +++ b/release/scripts/templates/bmesh_simple.py @@ -19,3 +19,4 @@ for v in bm.verts: # Finish up, write the bmesh back to the mesh bm.to_mesh(me) +bm.free() # free and prevent further access diff --git a/release/scripts/templates/bmesh_simple_editmode.py b/release/scripts/templates/bmesh_simple_editmode.py new file mode 100644 index 00000000000..d79ba02c2cb --- /dev/null +++ b/release/scripts/templates/bmesh_simple_editmode.py @@ -0,0 +1,23 @@ +# This example assumes we have a mesh object in edit-mode + +import bpy +import bmesh + +# Get the active mesh +obj = bpy.context.edit_object +me = obj.data + + +# Get a BMesh representation +bm = bmesh.from_edit_mesh(me) + +bm.faces.active = None + +# Modify the BMesh, can do anything here... +for v in bm.verts: + v.co.x += 1.0 + + +# Show the updates in the viewport +# and recalculate n-gon tessellation. +bmesh.update_edit_mesh(me, True) diff --git a/release/scripts/templates/script_stub.py b/release/scripts/templates/script_stub.py index 3b3212892d5..44c7b802e2c 100644 --- a/release/scripts/templates/script_stub.py +++ b/release/scripts/templates/script_stub.py @@ -8,4 +8,7 @@ import os filename = "my_script.py" filepath = os.path.join(os.path.dirname(bpy.data.filepath), filename) -exec(compile(open(filepath).read(), filepath, 'exec')) +global_namespace = {"__file__": filepath, "__name__": "__main__"} +file = open(filepath, 'rb') +exec(compile(file.read(), filepath, 'exec'), global_namespace) +file.close() diff --git a/release/text/readme.html b/release/text/readme.html index 40ea9035835..414a7d8e744 100644 --- a/release/text/readme.html +++ b/release/text/readme.html @@ -12,18 +12,18 @@ -

        Blender 2.64

        +

        Blender 2.65


        About

        Welcome to Blender, the free, open source 3D application for modeling, animation, rendering, compositing, video editing and game creation. Blender is available for Linux, Mac OS X, Windows and FreeBSD and has a large world-wide community.

        Blender can be used freely for any purpose, including commercial use and distribution. It's free and open-source software, released under the GNU GPL licence. The entire source code is available on our website.


        -

        2.64

        -

        The Blender Foundation and online developer community is proud to present Blender 2.64. This release is the fifth official stable release of the Blender 2.6 series, in which we will refine the 2.5 series and add exciting new features. More information about this release.

        +

        2.65

        +

        The Blender Foundation and online developer community is proud to present Blender 2.65. This release is the sixth official stable release of the Blender 2.6 series, in which we will refine the 2.5 series and add exciting new features. More information about this release.


        Bugs

        -

        Although Blender 2.64 is considered a stable release, you may encounter a bug. If you do, please help us by posting it in the bug tracker or using Help → Report a Bug from inside Blender. If it wasn’t reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.

        +

        Although Blender 2.65 is considered a stable release, you may encounter a bug. If you do, please help us by posting it in the bug tracker or using Help → Report a Bug from inside Blender. If it wasn’t reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.


        Package Contents

        The downloaded Blender package includes:

        @@ -47,7 +47,7 @@

        Links

        Users:

        General information www.blender.org
        - Full release log www.blender.org/development/release-logs/blender-264/
        + Full release log www.blender.org/development/release-logs/blender-265/
        Tutorials www.blender.org/education-help/
        Manual wiki.blender.org/index.php/Doc:2.6/Manual
        User Forum www.blenderartists.org
        diff --git a/source/blender/avi/intern/avi.c b/source/blender/avi/intern/avi.c index e1732b0caae..d6301b723a7 100644 --- a/source/blender/avi/intern/avi.c +++ b/source/blender/avi/intern/avi.c @@ -665,13 +665,13 @@ AviError AVI_open_movie(const char *name, AviMovie *movie) } } -/* Some AVI's have offset entries in absolute coordinates - * instead of an offset from the movie beginning... this is... - * wacky, but we need to handle it. The wacky offset always - * starts at movi_offset it seems... so we'll check that. - * Note the the offset needs an extra 4 bytes for some - * undetermined reason */ - + /* Some AVI's have offset entries in absolute coordinates + * instead of an offset from the movie beginning... this is... + * wacky, but we need to handle it. The wacky offset always + * starts at movi_offset it seems... so we'll check that. + * Note the the offset needs an extra 4 bytes for some + * undetermined reason */ + if (movie->entries[0].Offset == movie->movi_offset) movie->read_offset = 4; } diff --git a/source/blender/avi/intern/avi_rgb.c b/source/blender/avi/intern/avi_rgb.c index 11d9bdf8612..c6a78eccce2 100644 --- a/source/blender/avi/intern/avi_rgb.c +++ b/source/blender/avi/intern/avi_rgb.c @@ -98,7 +98,7 @@ void *avi_converter_from_avi_rgb(AviMovie *movie, int stream, unsigned char *buf buf = MEM_mallocN(movie->header->Height * movie->header->Width * 3, "fromavirgbbuf"); rowstride = movie->header->Width * 3; - if (bits != 16) if (movie->header->Width % 2) rowstride++; + if ((bits != 16) && (movie->header->Width % 2)) rowstride++; for (y = 0; y < movie->header->Height; y++) { memcpy(&buf[y * movie->header->Width * 3], &buffer[((movie->header->Height - 1) - y) * rowstride], movie->header->Width * 3); diff --git a/source/blender/blenfont/BLF_translation.h b/source/blender/blenfont/BLF_translation.h index b01ce93cb65..159d4b067b6 100644 --- a/source/blender/blenfont/BLF_translation.h +++ b/source/blender/blenfont/BLF_translation.h @@ -35,16 +35,6 @@ #define TEXT_DOMAIN_NAME "blender" -/* blf_translation.c */ - -#ifdef WITH_INTERNATIONAL -unsigned char *BLF_get_unifont(int *unifont_size); -void BLF_free_unifont(void); -#endif - -const char *BLF_gettext(const char *msgid); -const char *BLF_pgettext(const char *context, const char *message); - /* blf_lang.c */ /* Search the path directory to the locale files, this try all @@ -61,22 +51,29 @@ void BLF_lang_set(const char *); /* Get the current locale (short code, e.g. es_ES). */ const char *BLF_lang_get(void); -/* Set the current encoding name. */ -void BLF_lang_encoding(const char *str); - /* Get EnumPropertyItem's for translations menu. */ struct EnumPropertyItem *BLF_RNA_lang_enum_properties(void); +/* blf_translation.c */ + +#ifdef WITH_INTERNATIONAL +unsigned char *BLF_get_unifont(int *unifont_size); +void BLF_free_unifont(void); +#endif + +const char *BLF_pgettext(const char *msgctxt, const char *msgid); + /* translation */ int BLF_translate_iface(void); int BLF_translate_tooltips(void); -const char *BLF_translate_do_iface(const char *contex, const char *msgid); -const char *BLF_translate_do_tooltip(const char *contex, const char *msgid); +const char *BLF_translate_do_iface(const char *msgctxt, const char *msgid); +const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid); /* The "translation-marker" macro. */ #define N_(msgid) msgid #define CTX_N_(context, msgid) msgid + /* Those macros should be used everywhere in UI code. */ #ifdef WITH_INTERNATIONAL /* #define _(msgid) BLF_gettext(msgid) */ @@ -88,10 +85,17 @@ const char *BLF_translate_do_tooltip(const char *contex, const char *msgid); /* #define _(msgid) msgid */ #define IFACE_(msgid) msgid #define TIP_(msgid) msgid - #define CTX_IFACE_(context, msgid) msgid - #define CTX_TIP_(context, msgid) msgid + #define CTX_IFACE_(context, msgid) ((void)context, msgid) + #define CTX_TIP_(context, msgid) ((void)context, msgid) #endif +/* Helper macro, when we want to define a same msgid for multiple msgctxt... + * Does nothing in C, but is "parsed" by our i18n py tools. + * XXX Currently limited to at most 16 contexts at most + * (but you can call it several times with the same msgid, should you need more contexts!). + */ +#define BLF_I18N_MSGID_MULTI_CTXT(msgid, ...) + /****************************************************************************** * All i18n contexts must be defined here. * This is a nice way to be sure not to use a context twice for different @@ -104,8 +108,39 @@ const char *BLF_translate_do_tooltip(const char *contex, const char *msgid); /* Default context for operator names/labels. */ #define BLF_I18NCONTEXT_OPERATOR_DEFAULT "Operator" -/* Audio disambiguation context. */ -#define BLF_I18NCONTEXT_AUDIO "Audio" - +/* ID-types contexts. */ +/* WARNING! Keep it in sync with idtypes in blenkernel/intern/idcode.c */ +#define BLF_I18NCONTEXT_ID_ACTION "Action" +#define BLF_I18NCONTEXT_ID_ARMATURE "Armature" +#define BLF_I18NCONTEXT_ID_BRUSH "Brush" +#define BLF_I18NCONTEXT_ID_CAMERA "Camera" +#define BLF_I18NCONTEXT_ID_CURVE "Curve" +#define BLF_I18NCONTEXT_ID_GPENCIL "GPencil" +#define BLF_I18NCONTEXT_ID_GROUP "Group" +#define BLF_I18NCONTEXT_ID_ID "ID" +#define BLF_I18NCONTEXT_ID_IMAGE "Image" +/*#define BLF_I18NCONTEXT_ID_IPO "Ipo"*/ /* Deprecated */ +#define BLF_I18NCONTEXT_ID_SHAPEKEY "Key" +#define BLF_I18NCONTEXT_ID_LAMP "Lamp" +#define BLF_I18NCONTEXT_ID_LIBRARY "Library" +#define BLF_I18NCONTEXT_ID_LATTICE "Lattice" +#define BLF_I18NCONTEXT_ID_MATERIAL "Material" +#define BLF_I18NCONTEXT_ID_METABALL "Metaball" +#define BLF_I18NCONTEXT_ID_MESH "Mesh" +#define BLF_I18NCONTEXT_ID_NODETREE "NodeTree" +#define BLF_I18NCONTEXT_ID_OBJECT "Object" +#define BLF_I18NCONTEXT_ID_PARTICLESETTINGS "ParticleSettings" +#define BLF_I18NCONTEXT_ID_SCENE "Scene" +#define BLF_I18NCONTEXT_ID_SCREEN "Screen" +#define BLF_I18NCONTEXT_ID_SEQUENCE "Sequence" +#define BLF_I18NCONTEXT_ID_SPEAKER "Speaker" +#define BLF_I18NCONTEXT_ID_SOUND "Sound" +#define BLF_I18NCONTEXT_ID_TEXTURE "Texture" +#define BLF_I18NCONTEXT_ID_TEXT "Text" +#define BLF_I18NCONTEXT_ID_VFONT "VFont" +#define BLF_I18NCONTEXT_ID_WORLD "World" +#define BLF_I18NCONTEXT_ID_WINDOWMANAGER "WindowManager" +#define BLF_I18NCONTEXT_ID_MOVIECLIP "MovieClip" +#define BLF_I18NCONTEXT_ID_MASK "Mask" #endif /* __BLF_TRANSLATION_H__ */ diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt index 022dfd282b0..90baef14a74 100644 --- a/source/blender/blenfont/CMakeLists.txt +++ b/source/blender/blenfont/CMakeLists.txt @@ -31,6 +31,7 @@ set(INC ../makesrna ../imbuf ../../../intern/guardedalloc + ../../../intern/locale ) set(INC_SYS @@ -54,9 +55,6 @@ set(SRC ) if(WITH_INTERNATIONAL) - list(APPEND INC_SYS - ${GETTEXT_INCLUDE_DIRS} - ) add_definitions(-DWITH_INTERNATIONAL) endif() diff --git a/source/blender/blenfont/SConscript b/source/blender/blenfont/SConscript index 075da58b116..c0591c877ef 100644 --- a/source/blender/blenfont/SConscript +++ b/source/blender/blenfont/SConscript @@ -4,11 +4,10 @@ Import ('env') sources = env.Glob('intern/*.c') -incs = '. intern #/intern/guardedalloc ../blenkernel ../blenlib ../blenloader' +incs = '. intern #/intern/guardedalloc #/intern/locale ../blenkernel ../blenlib ../blenloader' incs += ' ../makesdna ../makesrna ../imbuf ../editors/include' incs += ' #/extern/glew/include' incs += ' ' + env['BF_FREETYPE_INC'] -incs += ' ' + env['BF_GETTEXT_INC'] defs = ['GLEW_STATIC'] diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index f3cc92e7a27..778b6c11e5a 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -28,7 +28,6 @@ * \ingroup blf */ - #include #include #include diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c index 501f8cd2958..0ed48623dd5 100644 --- a/source/blender/blenfont/intern/blf_lang.c +++ b/source/blender/blenfont/intern/blf_lang.c @@ -28,20 +28,17 @@ */ -#include -#include -#include - -#include "BKE_global.h" - -#include "BLF_api.h" #include "BLF_translation.h" /* own include */ #ifdef WITH_INTERNATIONAL -#include +#include +#include +#include -#include "libintl.h" +#include "boost_locale_wrapper.h" + +#include "BKE_global.h" #include "DNA_userdef_types.h" @@ -49,52 +46,33 @@ #include "MEM_guardedalloc.h" -#include "BLI_string.h" -#include "BLI_utildefines.h" -#include "BLI_path_util.h" #include "BLI_fileops.h" #include "BLI_linklist.h" +#include "BLI_path_util.h" #include "BLI_string.h" - -#define SYSTEM_ENCODING_DEFAULT "UTF-8" -#define FONT_SIZE_DEFAULT 12 +#include "BLI_utildefines.h" /* Locale options. */ -static char global_messagepath[1024]; -static char global_language[32]; -static char global_encoding_name[32]; - static const char **locales = NULL; -static char **long_locales = NULL; /* XXX Temp fix until we get a final solution with modern intl lib under windows! */ static int num_locales = 0; static EnumPropertyItem *locales_menu = NULL; static int num_locales_menu = 0; #define ULANGUAGE ((U.language >= 0 && U.language < num_locales) ? U.language : 0) #define LOCALE(_id) (locales ? locales[_id] : "") -#define LONG_LOCALE(_id) (long_locales ? long_locales[_id] : "") static void free_locales(void) { if (locales) { int idx = num_locales_menu - 1; /* Last item does not need to be freed! */ while (idx--) { - MEM_freeN((void*)locales_menu[idx].identifier); - MEM_freeN((void*)locales_menu[idx].name); - MEM_freeN((void*)locales_menu[idx].description); /* Also frees locales's relevant value! */ - } - - idx = num_locales; - while (idx--) { - if (long_locales[idx]) { - MEM_freeN(long_locales[idx]); - } + MEM_freeN((void *)locales_menu[idx].identifier); + MEM_freeN((void *)locales_menu[idx].name); + MEM_freeN((void *)locales_menu[idx].description); /* Also frees locales's relevant value! */ } MEM_freeN(locales); locales = NULL; - MEM_freeN(long_locales); - long_locales = NULL; } if (locales_menu) { MEM_freeN(locales_menu); @@ -140,7 +118,6 @@ static void fill_locales(void) /* Do not allocate locales with zero-sized mem, as LOCALE macro uses NULL locales as invalid marker! */ if (num_locales > 0) { locales = MEM_callocN(num_locales * sizeof(char*), __func__); - long_locales = MEM_callocN(num_locales * sizeof(char*), __func__); while (line) { int id; char *loc, *sep1, *sep2, *sep3; @@ -163,26 +140,28 @@ static void fill_locales(void) sep2++; sep3 = strchr(sep2, ':'); + if (sep3) { locales_menu[idx].identifier = loc = BLI_strdupn(sep2, sep3 - sep2); - - if (id == 0) { - /* The DEFAULT item... */ - if (BLI_strnlen(loc, 2)) { - locales[id] = locales_menu[idx].description = BLI_strdup(""); - long_locales[id] = BLI_strdup(""); - } - /* Menu "label", not to be stored in locales! */ - else { - locales_menu[idx].description = BLI_strdup(""); - } - } - else { - locales[id] = locales_menu[idx].description = BLI_strdup(loc); - long_locales[id] = BLI_strdup(sep3 + 1); - } - idx++; } + else { + locales_menu[idx].identifier = loc = BLI_strdup(sep2); + } + + if (id == 0) { + /* The DEFAULT item... */ + if (BLI_strnlen(loc, 2)) { + locales[id] = locales_menu[idx].description = BLI_strdup(""); + } + /* Menu "label", not to be stored in locales! */ + else { + locales_menu[idx].description = BLI_strdup(""); + } + } + else { + locales[id] = locales_menu[idx].description = BLI_strdup(loc); + } + idx++; } } @@ -207,15 +186,12 @@ void BLF_lang_init(void) { char *messagepath = BLI_get_folder(BLENDER_DATAFILES, "locale"); - BLI_strncpy(global_encoding_name, SYSTEM_ENCODING_DEFAULT, sizeof(global_encoding_name)); - if (messagepath) { - BLI_strncpy(global_messagepath, messagepath, sizeof(global_messagepath)); + bl_locale_init(messagepath, TEXT_DOMAIN_NAME); fill_locales(); } else { printf("%s: 'locale' data path for translations not found, continuing\n", __func__); - global_messagepath[0] = '\0'; } } @@ -224,159 +200,37 @@ void BLF_lang_free(void) free_locales(); } -/* Get LANG/LANGUAGE environment variable. */ -static void get_language_variable(const char *varname, char *var, const size_t maxlen) -{ - char *env = getenv(varname); - - if (env) { - char *s; - - /* Store defaul locale. */ - BLI_strncpy(var, env, maxlen); - - /* Use first language as default. */ - s = strchr(var, ':'); - if (s) - s[0] = 0; - } -} - -/* Get language to be used based on locale (which might be empty when using default language) and - * LANG environment variable. - */ -static void get_language(const char *locale, const char *lang, char *language, const size_t maxlen) -{ - if (locale[0]) { - BLI_strncpy(language, locale, maxlen); - } - else { - char *s; - - BLI_strncpy(language, lang, maxlen); - - s = strchr(language, '.'); - if (s) - s[0] = 0; - } -} - -/* XXX WARNING!!! In osx somehow the previous function call jumps in this one??? (ton, ppc) */ void BLF_lang_set(const char *str) { - char *locreturn; - int ok = TRUE; int ulang = ULANGUAGE; + const char *short_locale = str ? str : LOCALE(ulang); + const char *short_locale_utf8 = NULL; if ((U.transopts & USER_DOTRANSLATE) == 0) return; -#if defined(_WIN32) && !defined(FREE_WINDOWS) - { - const char *long_locale = str ? str : LONG_LOCALE(ulang); - if (long_locale) { - char *envStr; - - if (ulang) - envStr = BLI_sprintfN("LANG=%s", long_locale); - else /* Use system setting. */ - envStr = BLI_sprintfN("LANG=%s", getenv("LANG")); - - gettext_putenv(envStr); - MEM_freeN(envStr); - } - - locreturn = setlocale(LC_ALL, long_locale); - - if (locreturn == NULL) { - if (G.debug & G_DEBUG) - printf("Could not change locale to %s\n", long_locale); - - ok = FALSE; - } - } -#else - { - const char *short_locale = str ? str : LOCALE(ulang); - static char default_lang[64] = "\0"; - static char default_language[64] = "\0"; - - if (default_lang[0] == 0) - get_language_variable("LANG", default_lang, sizeof(default_lang)); - - if (default_language[0] == 0) - get_language_variable("LANGUAGE", default_language, sizeof(default_language)); - - if (short_locale[0]) { - char *short_locale_utf8 = BLI_sprintfN("%s.UTF-8", short_locale); - - if (G.debug & G_DEBUG) - printf("Setting LANG and LANGUAGE to %s\n", short_locale_utf8); - - locreturn = setlocale(LC_ALL, short_locale_utf8); - - if (locreturn != NULL) { - BLI_setenv("LANG", short_locale_utf8); - BLI_setenv("LANGUAGE", short_locale_utf8); - } - else { - if (G.debug & G_DEBUG) - printf("Setting LANG and LANGUAGE to %s\n", short_locale); - - locreturn = setlocale(LC_ALL, short_locale); - - if (locreturn != NULL) { - BLI_setenv("LANG", short_locale); - BLI_setenv("LANGUAGE", short_locale); - } - } - - if (G.debug & G_DEBUG && locreturn == NULL) - printf("Could not change locale to %s nor %s\n", short_locale, short_locale_utf8); - - MEM_freeN(short_locale_utf8); + /* We want to avoid locales like '.UTF-8'! */ + if (short_locale[0]) { + /* Hurrey! encoding needs to be placed *before* variant! */ + char *variant = strchr(short_locale, '@'); + if (variant) { + char *locale = BLI_strdupn(short_locale, variant - short_locale); + short_locale_utf8 = BLI_sprintfN("%s.UTF-8%s", locale, variant); + MEM_freeN(locale); } else { - if (G.debug & G_DEBUG) - printf("Setting LANG=%s and LANGUAGE=%s\n", default_lang, default_language); - - BLI_setenv("LANG", default_lang); - BLI_setenv("LANGUAGE", default_language); - locreturn = setlocale(LC_ALL, ""); - - if (G.debug & G_DEBUG && locreturn == NULL) - printf("Could not reset locale\n"); - } - - if (locreturn == NULL) { - char language[65]; - - get_language(short_locale, default_lang, language, sizeof(language)); - - if (G.debug & G_DEBUG) - printf("Fallback to LANG=%s and LANGUAGE=%s\n", default_lang, language); - - /* Fallback to default settings. */ - BLI_setenv("LANG", default_lang); - BLI_setenv("LANGUAGE", language); - - locreturn = setlocale(LC_ALL, ""); - - ok = FALSE; + short_locale_utf8 = BLI_sprintfN("%s.UTF-8", short_locale); } } -#endif - - if (ok) { - /*printf("Change locale to %s\n", locreturn ); */ - BLI_strncpy(global_language, locreturn, sizeof(global_language)); + else { + short_locale_utf8 = short_locale; } - setlocale(LC_NUMERIC, "C"); + bl_locale_set(short_locale_utf8); - textdomain(TEXT_DOMAIN_NAME); - bindtextdomain(TEXT_DOMAIN_NAME, global_messagepath); - bind_textdomain_codeset(TEXT_DOMAIN_NAME, global_encoding_name); + if (short_locale[0]) { + MEM_freeN((void*)short_locale_utf8); + } } const char *BLF_lang_get(void) @@ -385,12 +239,6 @@ const char *BLF_lang_get(void) return LOCALE(uilang); } -void BLF_lang_encoding(const char *str) -{ - BLI_strncpy(global_encoding_name, str, sizeof(global_encoding_name)); - /* bind_textdomain_codeset(TEXT_DOMAIN_NAME, encoding_name); */ -} - #undef LOCALE #undef ULANGUAGE @@ -406,12 +254,6 @@ void BLF_lang_free(void) return; } -void BLF_lang_encoding(const char *str) -{ - (void)str; - return; -} - void BLF_lang_set(const char *str) { (void)str; diff --git a/source/blender/blenfont/intern/blf_translation.c b/source/blender/blenfont/intern/blf_translation.c index 9c863da9eba..5d4b631688a 100644 --- a/source/blender/blenfont/intern/blf_translation.c +++ b/source/blender/blenfont/intern/blf_translation.c @@ -31,18 +31,11 @@ #include #include +#include "BLF_translation.h" + #ifdef WITH_INTERNATIONAL -#include -#include -#define GETTEXT_CONTEXT_GLUE "\004" - -/* needed for windows version of gettext */ -#ifndef LC_MESSAGES -# define LC_MESSAGES 1729 -#endif - -#endif +#include "boost_locale_wrapper.h" #include "MEM_guardedalloc.h" @@ -52,11 +45,8 @@ #include "BLI_path_util.h" #include "BLI_fileops.h" -#include "BLF_translation.h" - #include "DNA_userdef_types.h" /* For user settings. */ -#ifdef WITH_INTERNATIONAL static const char unifont_filename[] = "droidsans.ttf.gz"; static unsigned char *unifont_ttf = NULL; static int unifont_size = 0; @@ -90,55 +80,19 @@ void BLF_free_unifont(void) #endif -const char *BLF_gettext(const char *msgid) +const char *BLF_pgettext(const char *msgctxt, const char *msgid) { #ifdef WITH_INTERNATIONAL - if (msgid && msgid[0]) - return gettext(msgid); + if (msgid && msgid[0]) { + return bl_locale_pgettext(msgctxt, msgid); + } return ""; #else + (void)msgctxt; return msgid; #endif } -const char *BLF_pgettext(const char *context, const char *message) -{ -#ifdef WITH_INTERNATIONAL - char static_msg_ctxt_id[1024]; - char *dynamic_msg_ctxt_id = NULL; - char *msg_ctxt_id; - const char *translation; - - size_t overall_length = strlen(context) + strlen(message) + sizeof(GETTEXT_CONTEXT_GLUE) + 1; - - if (!message || !context || !message[0]) - return ""; - - if (overall_length > sizeof(static_msg_ctxt_id)) { - dynamic_msg_ctxt_id = malloc(overall_length); - msg_ctxt_id = dynamic_msg_ctxt_id; - } - else { - msg_ctxt_id = static_msg_ctxt_id; - } - - sprintf(msg_ctxt_id, "%s%s%s", context, GETTEXT_CONTEXT_GLUE, message); - - translation = (char *)dcgettext(TEXT_DOMAIN_NAME, msg_ctxt_id, LC_MESSAGES); - - if (dynamic_msg_ctxt_id) - free(dynamic_msg_ctxt_id); - - if (translation == msg_ctxt_id) - translation = message; - - return translation; -#else - (void)context; - return message; -#endif -} - int BLF_translate_iface(void) { #ifdef WITH_INTERNATIONAL @@ -157,36 +111,32 @@ int BLF_translate_tooltips(void) #endif } -const char *BLF_translate_do_iface(const char *context, const char *msgid) +const char *BLF_translate_do_iface(const char *msgctxt, const char *msgid) { #ifdef WITH_INTERNATIONAL if (BLF_translate_iface()) { - if (context) - return BLF_pgettext(context, msgid); - else - return BLF_gettext(msgid); + return BLF_pgettext(msgctxt, msgid); } - else + else { return msgid; + } #else - (void)context; + (void)msgctxt; return msgid; #endif } -const char *BLF_translate_do_tooltip(const char *context, const char *msgid) +const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid) { #ifdef WITH_INTERNATIONAL if (BLF_translate_tooltips()) { - if (context) - return BLF_pgettext(context, msgid); - else - return BLF_gettext(msgid); + return BLF_pgettext(msgctxt, msgid); } - else + else { return msgid; + } #else - (void)context; + (void)msgctxt; return msgid; #endif } diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index c6c54cc6e8a..617c4cd2bc8 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -709,10 +709,16 @@ void DM_debug_print(DerivedMesh *dm); void DM_debug_print_cdlayers(CustomData *cdata); #endif +#ifdef __GNUC__ +BLI_INLINE int DM_origindex_mface_mpoly(const int *index_mf_to_mpoly, const int *index_mp_to_orig, const int i) + __attribute__((nonnull(1))) +; +#endif + BLI_INLINE int DM_origindex_mface_mpoly(const int *index_mf_to_mpoly, const int *index_mp_to_orig, const int i) { const int j = index_mf_to_mpoly[i]; - return (j != ORIGINDEX_NONE) ? index_mp_to_orig[j] : ORIGINDEX_NONE; + return (j != ORIGINDEX_NONE) ? (index_mp_to_orig ? index_mp_to_orig[j] : j) : ORIGINDEX_NONE; } #endif diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 87e87904fe7..b624d0f9c3a 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -41,8 +41,8 @@ extern "C" { /* these lines are grep'd, watch out for our not-so-awesome regex * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ -#define BLENDER_VERSION 264 -#define BLENDER_SUBVERSION 7 +#define BLENDER_VERSION 265 +#define BLENDER_SUBVERSION 0 /* 262 was the last editmesh release but it has compatibility code for bmesh data */ #define BLENDER_MINVERSION 262 @@ -50,9 +50,9 @@ extern "C" { /* used by packaging tools */ /* can be left blank, otherwise a,b,c... etc with no quotes */ -#define BLENDER_VERSION_CHAR a +#define BLENDER_VERSION_CHAR /* alpha/beta/rc/release, docs use this */ -#define BLENDER_VERSION_CYCLE alpha +#define BLENDER_VERSION_CYCLE release extern char versionstr[]; /* from blender.c */ diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index f7af534c2c2..f6276a69d57 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -167,6 +167,9 @@ enum { #define G_FILE_RELATIVE_REMAP (1 << 24) #define G_FILE_HISTORY (1 << 25) #define G_FILE_MESH_COMPAT (1 << 26) /* BMesh option to save as older mesh format */ +#define G_FILE_SAVE_COPY (1 << 27) /* restore paths after editing them */ + +#define G_FILE_FLAGS_RUNTIME (G_FILE_NO_UI | G_FILE_RELATIVE_REMAP | G_FILE_MESH_COMPAT | G_FILE_SAVE_COPY) /* G.windowstate */ #define G_WINDOWSTATE_USERDEF 0 diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index ebfbe94802a..9af0d96884a 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -30,9 +30,7 @@ /** \file BKE_icons.h * \ingroup bke - */ - -/* + * * Resizable Icons for Blender */ diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 1875fd66628..1f9630d9fce 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -48,6 +48,9 @@ struct Main; #define IMA_MAX_SPACE 64 +void BKE_images_init(void); +void BKE_images_exit(void); + /* call from library */ void BKE_image_free(struct Image *me); @@ -133,14 +136,13 @@ enum { #define IMA_CHAN_FLAG_RGB 2 #define IMA_CHAN_FLAG_ALPHA 4 -/* depending Image type, and (optional) ImageUser setting it returns ibuf */ -/* always call to make signals work */ -struct ImBuf *BKE_image_get_ibuf(struct Image *ima, struct ImageUser *iuser); +/* checks whether there's an image buffer for given image and user */ +int BKE_image_has_ibuf(struct Image *ima, struct ImageUser *iuser); /* same as above, but can be used to retrieve images being rendered in * a thread safe way, always call both acquire and release */ struct ImBuf *BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **lock_r); -void BKE_image_release_ibuf(struct Image *ima, void *lock); +void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock); /* returns a new image or NULL if it can't load */ struct Image *BKE_image_load(const char *filepath); diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h index 3acd4d1986e..244decf9d52 100644 --- a/source/blender/blenkernel/BKE_lamp.h +++ b/source/blender/blenkernel/BKE_lamp.h @@ -37,6 +37,7 @@ extern "C" { #endif struct Lamp; +struct Scene; struct Lamp *BKE_lamp_add(const char *name) WARN_UNUSED; struct Lamp *BKE_lamp_copy(struct Lamp *la) WARN_UNUSED; @@ -44,6 +45,8 @@ struct Lamp *localize_lamp(struct Lamp *la) WARN_UNUSED; void BKE_lamp_make_local(struct Lamp *la); void BKE_lamp_free(struct Lamp *la); +void lamp_drivers_update(struct Scene *scene, struct Lamp *la, float ctime); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 2f889084d0e..e53d0efffbd 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -283,9 +283,9 @@ typedef struct IndexNode { void create_vert_poly_map(MeshElemMap **map, int **mem, const struct MPoly *mface, const struct MLoop *mloop, int totvert, int totface, int totloop); - + void create_vert_edge_map(MeshElemMap **map, int **mem, - const struct MEdge *medge, int totvert, int totedge); + const struct MEdge *medge, int totvert, int totedge); /* vertex level transformations & checks (no derived mesh) */ diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 7ee1c85d0de..2fa78b30835 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -319,8 +319,8 @@ int modifier_dependsOnTime(struct ModifierData *md); int modifier_supportsMapping(struct ModifierData *md); int modifier_couldBeCage(struct Scene *scene, struct ModifierData *md); int modifier_isCorrectableDeformed(struct ModifierData *md); -int modifier_sameTopology(ModifierData *md); -int modifier_nonGeometrical(ModifierData *md); +int modifier_isSameTopology(ModifierData *md); +int modifier_isNonGeometrical(ModifierData *md); int modifier_isEnabled(struct Scene *scene, struct ModifierData *md, int required_mode); void modifier_setError(struct ModifierData *md, const char *format, ...) #ifdef __GNUC__ diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 8fa20eb2cc2..bee2c374f27 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -48,7 +48,7 @@ struct Scene; void multires_customdata_delete(struct Mesh *me); void multires_set_tot_level(struct Object *ob, - struct MultiresModifierData *mmd, int lvl); + struct MultiresModifierData *mmd, int lvl); void multires_mark_as_modified(struct Object *ob, enum MultiresModifiedFlags flags); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 29e03f66bcc..b8f168cbdea 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -34,8 +34,6 @@ #include "DNA_listBase.h" -#include "RNA_types.h" - /* not very important, but the stack solver likes to know a maximum */ #define MAX_SOCKET 64 @@ -82,7 +80,7 @@ typedef struct bNodeSocketTemplate { char name[64]; /* MAX_NAME */ float val1, val2, val3, val4; /* default alloc value for inputs */ float min, max; - PropertySubType subtype; + int subtype; /* would use PropertySubType but this is a bad level include to use RNA */ int flag; /* after this line is used internal only */ @@ -316,6 +314,8 @@ void ntreeUserIncrefID(struct bNodeTree *ntree); void ntreeUserDecrefID(struct bNodeTree *ntree); +struct bNodeTree *ntreeFromID(struct ID *id); + void ntreeMakeLocal(struct bNodeTree *ntree); int ntreeHasType(struct bNodeTree *ntree, int type); void ntreeUpdateTree(struct bNodeTree *ntree); @@ -553,6 +553,10 @@ struct ShadeResult; #define SH_NODE_TEX_BRICK 169 #define SH_NODE_BUMP 170 #define SH_NODE_SCRIPT 171 +#define SH_NODE_AMBIENT_OCCLUSION 172 +#define SH_NODE_BSDF_REFRACTION 173 +#define SH_NODE_TANGENT 174 +#define SH_NODE_NORMAL_MAP 175 /* custom defines options for Material node */ #define SH_NODE_MAT_DIFF 1 @@ -702,6 +706,8 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria #define CMP_NODE_SWITCH 317 #define CMP_NODE_PIXELATE 318 +#define CMP_NODE_MAP_RANGE 319 + /* channel toggles */ #define CMP_CHAN_RGB 1 #define CMP_CHAN_A 2 diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index ba611817c8f..88294cb30b6 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -248,7 +248,7 @@ void BKE_sequencer_cache_cleanup(void); struct ImBuf *BKE_sequencer_cache_get(SeqRenderData context, struct Sequence *seq, float cfra, seq_stripelem_ibuf_t type); /* passed ImBuf is properly refed, so ownership is *not* - * transfered to the cache. + * transferred to the cache. * you can pass the same ImBuf multiple times to the cache without problems. */ diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index 875903f2e20..accac8694a9 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -83,7 +83,7 @@ void txt_sel_line (struct Text *text); char* txt_sel_to_buf (struct Text *text); void txt_insert_buf (struct Text *text, const char *in_buffer); void txt_print_undo (struct Text *text); -void txt_undo_add_toop (struct Text *text, int op, unsigned int froml, unsigned short fromc, unsigned int tol, unsigned short toc); +void txt_undo_add_op (struct Text *text, int op); void txt_do_undo (struct Text *text); void txt_do_redo (struct Text *text); void txt_split_curline (struct Text *text); @@ -100,14 +100,6 @@ void txt_move_lines (struct Text *text, const int direction); void txt_duplicate_line (struct Text *text); int setcurr_tab_spaces (struct Text *text, int space); -void txt_add_marker (struct Text *text, struct TextLine *line, int start, int end, const unsigned char color[4], int group, int flags); -short txt_clear_marker_region (struct Text *text, struct TextLine *line, int start, int end, int group, int flags); -short txt_clear_markers (struct Text *text, int group, int flags); -struct TextMarker *txt_find_marker (struct Text *text, struct TextLine *line, int curs, int group, int flags); -struct TextMarker *txt_find_marker_region (struct Text *text, struct TextLine *line, int start, int end, int group, int flags); -struct TextMarker *txt_prev_marker (struct Text *text, struct TextMarker *marker); -struct TextMarker *txt_next_marker (struct Text *text, struct TextMarker *marker); - /* utility functions, could be moved somewhere more generic but are python/text related */ int text_check_bracket(const char ch); int text_check_delim(const char ch); @@ -123,24 +115,6 @@ enum { /* Undo opcodes */ -/* Simple main cursor movement */ -#define UNDO_CLEFT 001 -#define UNDO_CRIGHT 002 -#define UNDO_CUP 003 -#define UNDO_CDOWN 004 - -/* Simple selection cursor movement */ -#define UNDO_SLEFT 005 -#define UNDO_SRIGHT 006 -#define UNDO_SUP 007 -#define UNDO_SDOWN 010 - -/* Complex movement (opcode is followed - * by 4 character line ID + a 2 character - * position ID and opcode (repeat)) */ -#define UNDO_CTO 011 -#define UNDO_STO 012 - /* Complex editing */ /* 1 - opcode is followed by 1 byte for ascii character and opcode (repeat)) */ /* 2 - opcode is followed by 2 bytes for utf-8 character and opcode (repeat)) */ @@ -169,8 +143,6 @@ enum { #define UNDO_IBLOCK 030 /* Insert block */ /* Misc */ -#define UNDO_SWAP 031 /* Swap cursors */ - #define UNDO_INDENT 032 #define UNDO_UNINDENT 033 #define UNDO_COMMENT 034 @@ -181,10 +153,6 @@ enum { #define UNDO_DUPLICATE 040 -/* Marker flags */ -#define TMARK_TEMP 0x01 /* Remove on non-editing events, don't save */ -#define TMARK_EDITALL 0x02 /* Edit all markers of the same group as one */ - #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index 06f8b89ec05..7c1e0e97565 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -32,7 +32,11 @@ extern "C" { #endif -/* currently unused but we may want to add macros here for BKE later */ +#define BKE_BIT_TEST_SET(value, test, flag) \ +{ \ + if (test) (value) |= flag; \ + else (value) &= ~flag; \ +} (void)0 #ifdef __cplusplus } diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index c5dc7da8edf..2da9b402d59 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -255,13 +255,13 @@ if(WITH_BULLET) add_definitions(-DUSE_BULLET) endif() -if(WITH_MOD_CLOTH_ELTOPO) - list(APPEND INC - ../../../extern/eltopo - ../../../extern/eltopo/eltopo3d - ) - add_definitions(-DWITH_ELTOPO) -endif() +#if(WITH_MOD_CLOTH_ELTOPO) +# list(APPEND INC +# ../../../extern/eltopo +# ../../../extern/eltopo/eltopo3d +# ) +# add_definitions(-DWITH_ELTOPO) +#endif() if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index f7b8f59fa57..22be2f78ea7 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -4,6 +4,7 @@ import os sources = env.Glob('intern/*.c') sources.remove('intern' + os.sep + 'mask_rasterize.c') +sources.remove('intern' + os.sep + 'mask_evaluate.c') sources.remove('intern' + os.sep + 'mask.c') sources_mask = env.Glob('intern/mask*.c') @@ -40,11 +41,12 @@ if env['WITH_BF_PYTHON']: if env['BF_DEBUG']: defs.append('DEBUG') +''' if env['WITH_BF_ELTOPO']: incs += ' #/extern/eltopo' incs += ' #/extern/eltopo/eltopo3d' defs.append('WITH_ELTOPO') - +''' if env['WITH_BF_QUICKTIME']: incs += ' ../quicktime' diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index fd92b7b5d69..d09bea0f662 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -392,7 +392,7 @@ void DM_ensure_tessface(DerivedMesh *dm) } else if (dm->dirty & DM_DIRTY_TESS_CDLAYERS) { - BLI_assert(CustomData_has_layer(&dm->faceData, CD_ORIGINDEX)); + BLI_assert(CustomData_has_layer(&dm->faceData, CD_ORIGINDEX) || numTessFaces == 0); DM_update_tessface_data(dm); } @@ -1159,120 +1159,65 @@ void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag, ColorBand *coba = stored_cb; /* warning, not a local var */ unsigned char *wtcol_v; -#if 0 /* See coment below. */ - unsigned char *wtcol_f = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL); -#endif unsigned char(*wtcol_l)[4] = CustomData_get_layer(dm->getLoopDataLayout(dm), CD_PREVIEW_MLOOPCOL); -#if 0 /* See coment below. */ - MFace *mf = dm->getTessFaceArray(dm); -#endif MLoop *mloop = dm->getLoopArray(dm), *ml; MPoly *mp = dm->getPolyArray(dm); -#if 0 - int numFaces = dm->getNumTessFaces(dm); -#endif int numVerts = dm->getNumVerts(dm); int totloop; int i, j; -#if 0 /* See comment below */ - /* If no CD_PREVIEW_MCOL existed yet, add a new one! */ - if (!wtcol_f) - wtcol_f = CustomData_add_layer(&dm->faceData, CD_PREVIEW_MCOL, CD_CALLOC, NULL, numFaces); - - if (wtcol_f) { - unsigned char *wtcol_f_step = wtcol_f; -# else -#if 0 - /* XXX We have to create a CD_PREVIEW_MCOL, else it might sigsev (after a SubSurf mod, eg)... */ - if (!dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL)) - CustomData_add_layer(&dm->faceData, CD_PREVIEW_MCOL, CD_CALLOC, NULL, numFaces); -#endif - - { -#endif - - /* Weights are given by caller. */ - if (weights) { - float *w = weights; - /* If indices is not NULL, it means we do not have weights for all vertices, - * so we must create them (and set them to zero)... */ - if (indices) { - w = MEM_callocN(sizeof(float) * numVerts, "Temp weight array DM_update_weight_mcol"); - i = num; - while (i--) - w[indices[i]] = weights[i]; - } - - /* Convert float weights to colors. */ - wtcol_v = calc_colors_from_weights_array(numVerts, w); - - if (indices) - MEM_freeN(w); + /* Weights are given by caller. */ + if (weights) { + float *w = weights; + /* If indices is not NULL, it means we do not have weights for all vertices, + * so we must create them (and set them to zero)... */ + if (indices) { + w = MEM_callocN(sizeof(float) * numVerts, "Temp weight array DM_update_weight_mcol"); + i = num; + while (i--) + w[indices[i]] = weights[i]; } - /* No weights given, take them from active vgroup(s). */ - else - wtcol_v = calc_weightpaint_vert_array(ob, dm, draw_flag, coba); + /* Convert float weights to colors. */ + wtcol_v = calc_colors_from_weights_array(numVerts, w); - /* Now copy colors in all face verts. */ - /* first add colors to the tessellation faces */ - /* XXX Why update that layer? We have to update WEIGHT_MLOOPCOL anyway, - * and tessellation recreates mface layers from mloop/mpoly ones, so no - * need to fill WEIGHT_MCOL here. */ -#if 0 - for (i = 0; i < numFaces; i++, mf++, wtcol_f_step += (4 * 4)) { - /*origindex being NULL means we're operating on original mesh data*/ -#if 0 - unsigned int fidx = mf->v4 ? 3 : 2; - -#else /* better zero out triangles 4th component. else valgrind complains when the buffer's copied */ - unsigned int fidx; - if (mf->v4) { - fidx = 3; - } - else { - fidx = 2; - *(int *)(&wtcol_f_step[3 * 4]) = 0; - } -#endif - - do { - copy_v4_v4_char((char *)&wtcol_f_step[fidx * 4], - (char *)&wtcol_v[4 * (*(&mf->v1 + fidx))]); - } while (fidx--); - } -#endif - /*now add to loops, so the data can be passed through the modifier stack*/ - /* If no CD_PREVIEW_MLOOPCOL existed yet, we have to add a new one! */ - if (!wtcol_l) { - BLI_array_declare(wtcol_l); - totloop = 0; - for (i = 0; i < dm->numPolyData; i++, mp++) { - ml = mloop + mp->loopstart; - - BLI_array_grow_items(wtcol_l, mp->totloop); - for (j = 0; j < mp->totloop; j++, ml++, totloop++) { - copy_v4_v4_char((char *)&wtcol_l[totloop], - (char *)&wtcol_v[4 * ml->v]); - } - } - CustomData_add_layer(&dm->loopData, CD_PREVIEW_MLOOPCOL, CD_ASSIGN, wtcol_l, totloop); - } - else { - totloop = 0; - for (i = 0; i < dm->numPolyData; i++, mp++) { - ml = mloop + mp->loopstart; - - for (j = 0; j < mp->totloop; j++, ml++, totloop++) { - copy_v4_v4_char((char *)&wtcol_l[totloop], - (char *)&wtcol_v[4 * ml->v]); - } - } - } - MEM_freeN(wtcol_v); + if (indices) + MEM_freeN(w); } + /* No weights given, take them from active vgroup(s). */ + else + wtcol_v = calc_weightpaint_vert_array(ob, dm, draw_flag, coba); + + /* now add to loops, so the data can be passed through the modifier stack */ + /* If no CD_PREVIEW_MLOOPCOL existed yet, we have to add a new one! */ + if (!wtcol_l) { + BLI_array_declare(wtcol_l); + totloop = 0; + for (i = 0; i < dm->numPolyData; i++, mp++) { + ml = mloop + mp->loopstart; + + BLI_array_grow_items(wtcol_l, mp->totloop); + for (j = 0; j < mp->totloop; j++, ml++, totloop++) { + copy_v4_v4_char((char *)&wtcol_l[totloop], + (char *)&wtcol_v[4 * ml->v]); + } + } + CustomData_add_layer(&dm->loopData, CD_PREVIEW_MLOOPCOL, CD_ASSIGN, wtcol_l, totloop); + } + else { + totloop = 0; + for (i = 0; i < dm->numPolyData; i++, mp++) { + ml = mloop + mp->loopstart; + + for (j = 0; j < mp->totloop; j++, ml++, totloop++) { + copy_v4_v4_char((char *)&wtcol_l[totloop], + (char *)&wtcol_v[4 * ml->v]); + } + } + } + MEM_freeN(wtcol_v); + dm->dirty |= DM_DIRTY_TESS_CDLAYERS; } @@ -1680,8 +1625,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos nextmask &= ~CD_MASK_ORCO; DM_set_only_copy(orcodm, nextmask | CD_MASK_ORIGINDEX | - (mti->requiredDataMask ? - mti->requiredDataMask(ob, md) : 0)); + (mti->requiredDataMask ? + mti->requiredDataMask(ob, md) : 0)); ndm = mti->applyModifier(md, ob, orcodm, app_flags & ~MOD_APPLY_USECACHE); if (ndm) { @@ -2167,6 +2112,8 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask, /* weight paint and face select need original indices because of selection buffer drawing */ int needMapping = (ob == obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT))); + BLI_assert(ob->type == OB_MESH); + clear_mesh_caches(ob); mesh_calc_modifiers(scene, ob, NULL, &ob->derivedDeform, diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index e95451252d0..dd27cc70ba3 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -512,7 +512,7 @@ const char *BKE_pose_ikparam_get_name(bPose *pose) { if (pose) { switch (pose->iksolver) { - case IKSOLVER_LEGACY: + case IKSOLVER_STANDARD: return NULL; case IKSOLVER_ITASC: return "bItasc"; @@ -587,7 +587,7 @@ void BKE_pose_ikparam_init(bPose *pose) BKE_pose_itasc_init(itasc); pose->ikparam = itasc; break; - case IKSOLVER_LEGACY: + case IKSOLVER_STANDARD: default: pose->ikparam = NULL; break; diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index dffe26bd782..9a2462e9724 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -76,8 +76,8 @@ /* --------------------- */ /* forward declarations */ -static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, - int level, short flag); +static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], + int persistent_id[MAX_DUPLI_RECUR], int level, int index, short flag); /* ******************************************************************** */ /* Animation Visualization */ @@ -706,31 +706,45 @@ int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float qua #define DUPLILIST_FOR_RENDER 2 #define DUPLILIST_ANIMATED 4 -static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index, int par_index, int type, short flag) +static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, + int persistent_id[MAX_DUPLI_RECUR], int level, int index, int type, short flag) { DupliObject *dob = MEM_callocN(sizeof(DupliObject), "dupliobject"); - + int i; + BLI_addtail(lb, dob); dob->ob = ob; copy_m4_m4(dob->mat, mat); copy_m4_m4(dob->omat, ob->obmat); dob->origlay = ob->lay; - dob->index = index; - dob->particle_index = par_index; dob->type = type; dob->animated = (type == OB_DUPLIGROUP) && (flag & DUPLILIST_ANIMATED); ob->lay = lay; + + /* set persistent id, which is an array with a persistent index for each level + * (particle number, vertex number, ..). by comparing this we can find the same + * dupli object between frames, which is needed for motion blur. last level + * goes first in the array. */ + dob->persistent_id[0] = index; + for (i = 1; i < level; i++) + dob->persistent_id[i] = persistent_id[level - 1 - i]; + + /* metaballs never draw in duplis, they are instead merged into one by the basis + * mball outside of the group. this does mean that if that mball is not in the + * scene, they will not show up at all, limitation that should be solved once. */ + if (ob->type == OB_MBALL) + dob->no_draw = TRUE; return dob; } -static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, +static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int persistent_id[MAX_DUPLI_RECUR], int level, short flag) { DupliObject *dob; Group *group; GroupObject *go; - float mat[4][4], tmat[4][4]; + float mat[4][4], tmat[4][4], id; if (ob->dup_group == NULL) return; group = ob->dup_group; @@ -750,7 +764,7 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde if (group_is_animated(ob, group)) flag |= DUPLILIST_ANIMATED; - for (go = group->gobject.first; go; go = go->next) { + for (go = group->gobject.first, id = 0; go; go = go->next, id++) { /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */ if (go->ob != ob) { @@ -764,7 +778,7 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde mult_m4_m4m4(mat, ob->obmat, go->ob->obmat); } - dob = new_dupli_object(lb, go->ob, mat, ob->lay, 0, par_index, OB_DUPLIGROUP, flag); + dob = new_dupli_object(lb, go->ob, mat, ob->lay, persistent_id, level, id, OB_DUPLIGROUP, flag); /* check the group instance and object layers match, also that the object visible flags are ok. */ if ((dob->origlay & group->layer) == 0 || @@ -773,20 +787,17 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde { dob->no_draw = TRUE; } - else { - dob->no_draw = FALSE; - } if (go->ob->transflag & OB_DUPLI) { copy_m4_m4(dob->ob->obmat, dob->mat); - object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, par_index, level + 1, flag); + object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, persistent_id, level + 1, id, flag); copy_m4_m4(dob->ob->obmat, dob->omat); } } } } -static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, short flag) +static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int persistent_id[MAX_DUPLI_RECUR], int level, short flag) { extern int enable_cu_speed; /* object.c */ Object copyob; @@ -834,7 +845,7 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_ind BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */ BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra); - dob = new_dupli_object(lb, ob, ob->obmat, ob->lay, scene->r.cfra, par_index, OB_DUPLIFRAMES, flag); + dob = new_dupli_object(lb, ob, ob->obmat, ob->lay, persistent_id, level, scene->r.cfra, OB_DUPLIFRAMES, flag); copy_m4_m4(dob->omat, copyob.obmat); } } @@ -865,7 +876,7 @@ typedef struct VertexDupliData { Scene *scene; Object *ob, *par; float (*orco)[3]; - int par_index; + int *persistent_id; } VertexDupliData; /* ------------- */ @@ -902,7 +913,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], origlay = vdd->ob->lay; - dob = new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, vdd->par_index, OB_DUPLIVERTS, vdd->flag); + dob = new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, vdd->persistent_id, vdd->level, index, OB_DUPLIVERTS, vdd->flag); /* restore the original layer so that each dupli will have proper dob->origlay */ vdd->ob->lay = origlay; @@ -914,12 +925,12 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], float tmpmat[4][4]; copy_m4_m4(tmpmat, vdd->ob->obmat); copy_m4_m4(vdd->ob->obmat, obmat); /* pretend we are really this mat */ - object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->par_index, vdd->level + 1, vdd->flag); + object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->persistent_id, vdd->level + 1, index, vdd->flag); copy_m4_m4(vdd->ob->obmat, tmpmat); } } -static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, +static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int persistent_id[MAX_DUPLI_RECUR], int level, short flag) { Object *ob, *ob_iter; @@ -1004,7 +1015,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl vdd.scene = scene; vdd.par = par; copy_m4_m4(vdd.pmat, pmat); - vdd.par_index = par_index; + vdd.persistent_id = persistent_id; /* mballs have a different dupli handling */ if (ob->type != OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ @@ -1043,7 +1054,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl dm->release(dm); } -static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, +static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int persistent_id[MAX_DUPLI_RECUR], int level, short flag) { Object *ob, *ob_iter; @@ -1186,7 +1197,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa copy_m4_m4(tmat, obmat); mul_m4_m4m3(obmat, tmat, mat); - dob = new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIFACES, (flag & DUPLILIST_ANIMATED)); + dob = new_dupli_object(lb, ob, obmat, par->lay, persistent_id, level, a, OB_DUPLIFACES, (flag & DUPLILIST_ANIMATED)); if (flag & DUPLILIST_FOR_RENDER) { w = 1.0f / (float)mp->totloop; @@ -1209,7 +1220,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa float tmpmat[4][4]; copy_m4_m4(tmpmat, ob->obmat); copy_m4_m4(ob->obmat, obmat); /* pretend we are really this mat */ - object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, par_index, level + 1, flag); + object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, persistent_id, level + 1, a, flag); copy_m4_m4(ob->obmat, tmpmat); } } @@ -1229,7 +1240,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa dm->release(dm); } -static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int UNUSED(par_index), ParticleSystem *psys, +static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int persistent_id[MAX_DUPLI_RECUR], ParticleSystem *psys, int level, short flag) { GroupObject *go; @@ -1244,8 +1255,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p float ctime, pa_time, scale = 1.0f; float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size = 0.0; float (*obmat)[4], (*oldobmat)[4]; - int a, b, counter, index, hair = 0; + int a, b, hair = 0; int totpart, totchild, totgroup = 0 /*, pa_num */; + int dupli_type_hack = !BKE_scene_use_new_shading_nodes(scene); int no_draw_flag = PARS_UNEXIST; @@ -1360,8 +1372,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p else a = totpart; - index = 0; - for (pa = psys->particles, counter = 0; a < totpart + totchild; a++, pa++, counter++) { + for (pa = psys->particles; a < totpart + totchild; a++, pa++) { if (a < totpart) { /* handle parent particle */ if (pa->flag & no_draw_flag) @@ -1456,13 +1467,21 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p else copy_m4_m4(mat, tmat); - dob = new_dupli_object(lb, go->ob, mat, par->lay, counter, index, OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED)); + dob = new_dupli_object(lb, go->ob, mat, par->lay, persistent_id, level, a, OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED)); + dob->particle_system = psys; copy_m4_m4(dob->omat, obcopylist[b].obmat); if (flag & DUPLILIST_FOR_RENDER) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } else { + int dupli_type = OB_DUPLIPARTS; + + /* blender internal needs this to be set to dupligroup to render + * groups correctly, but we don't want this hack for cycles */ + if(dupli_type_hack && GS(id->name) == ID_GR) + dupli_type = OB_DUPLIGROUP; + /* to give ipos in object correct offset */ BKE_object_where_is_calc_time(scene, ob, ctime - pa_time); @@ -1516,14 +1535,12 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p if (part->draw & PART_DRAW_GLOBAL_OB) add_v3_v3v3(mat[3], mat[3], vec); - dob = new_dupli_object(lb, ob, mat, ob->lay, counter, index, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED)); + dob = new_dupli_object(lb, ob, mat, ob->lay, persistent_id, level, a, dupli_type, (flag & DUPLILIST_ANIMATED)); + dob->particle_system = psys; copy_m4_m4(dob->omat, oldobmat); if (flag & DUPLILIST_FOR_RENDER) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } - - /* only counts visible particles */ - index++; } /* restore objects since they were changed in BKE_object_where_is_calc_time */ @@ -1570,7 +1587,7 @@ static Object *find_family_object(Object **obar, char *family, char ch) } -static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_index, int level, short flag) +static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int persistent_id[MAX_DUPLI_RECUR], int level, short flag) { Object *ob, *obar[256] = {NULL}; Curve *cu; @@ -1609,7 +1626,7 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_inde copy_m4_m4(obmat, par->obmat); copy_v3_v3(obmat[3], vec); - new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIVERTS, flag); + new_dupli_object(lb, ob, obmat, par->lay, persistent_id, level, a, OB_DUPLIVERTS, flag); } } @@ -1618,8 +1635,8 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_inde /* ------------- */ -static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, - int level, short flag) +static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], + int persistent_id[MAX_DUPLI_RECUR], int level, int index, short flag) { if ((ob->transflag & OB_DUPLI) == 0) return; @@ -1636,34 +1653,45 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas } } + /* keep track of persistent id */ + if (level > 0) + persistent_id[level - 1] = index; + if (ob->transflag & OB_DUPLIPARTS) { ParticleSystem *psys = ob->particlesystem.first; - for (; psys; psys = psys->next) - new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, psys, level + 1, flag); + int psysid = 0; + + /* particle system take up one level in id, the particles another */ + for (; psys; psys = psys->next, psysid++) { + persistent_id[level] = psysid; + new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, persistent_id, psys, level + 2, flag); + } + + persistent_id[level] = 0; } else if (ob->transflag & OB_DUPLIVERTS) { if (ob->type == OB_MESH) { - vertex_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, flag); + vertex_duplilist(duplilist, id, scene, ob, par_space_mat, persistent_id, level + 1, flag); } else if (ob->type == OB_FONT) { if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */ - font_duplilist(duplilist, scene, ob, par_index, level + 1, flag); + font_duplilist(duplilist, scene, ob, persistent_id, level + 1, flag); } } } else if (ob->transflag & OB_DUPLIFACES) { if (ob->type == OB_MESH) - face_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, flag); + face_duplilist(duplilist, id, scene, ob, par_space_mat, persistent_id, level + 1, flag); } else if (ob->transflag & OB_DUPLIFRAMES) { if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */ - frames_duplilist(duplilist, scene, ob, par_index, level + 1, flag); + frames_duplilist(duplilist, scene, ob, persistent_id, level + 1, flag); } } else if (ob->transflag & OB_DUPLIGROUP) { DupliObject *dob; - group_duplilist(duplilist, scene, ob, par_index, level + 1, flag); /* now recursive */ + group_duplilist(duplilist, scene, ob, persistent_id, level + 1, flag); /* now recursive */ if (level == 0) { for (dob = duplilist->first; dob; dob = dob->next) @@ -1671,6 +1699,10 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas copy_m4_m4(dob->ob->obmat, dob->mat); } } + + /* clear persistent id */ + if (level > 0) + persistent_id[level - 1] = 0; } /* Returns a list of DupliObject @@ -1678,13 +1710,14 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas ListBase *object_duplilist_ex(Scene *sce, Object *ob, int update, int for_render) { ListBase *duplilist = MEM_mallocN(sizeof(ListBase), "duplilist"); + int persistent_id[MAX_DUPLI_RECUR] = {0}; int flag = 0; if (update) flag |= DUPLILIST_DO_UPDATE; if (for_render) flag |= DUPLILIST_FOR_RENDER; duplilist->first = duplilist->last = NULL; - object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0, flag); + object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, persistent_id, 0, 0, flag); return duplilist; } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 66ed31c5b72..40b883e3f4e 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -781,7 +781,7 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u ANIMDATA_NODETREE_IDS_CB(mainptr->tex.first, Tex); /* lamps */ - ANIMDATA_IDS_CB(mainptr->lamp.first); + ANIMDATA_NODETREE_IDS_CB(mainptr->lamp.first, Lamp); /* materials */ ANIMDATA_NODETREE_IDS_CB(mainptr->mat.first, Material); @@ -823,7 +823,7 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u ANIMDATA_IDS_CB(mainptr->mask.first); /* worlds */ - ANIMDATA_IDS_CB(mainptr->world.first); + ANIMDATA_NODETREE_IDS_CB(mainptr->world.first, World); /* scenes */ ANIMDATA_NODETREE_IDS_CB(mainptr->scene.first, Scene); @@ -868,7 +868,7 @@ void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const cha RENAMEFIX_ANIM_NODETREE_IDS(mainptr->tex.first, Tex); /* lamps */ - RENAMEFIX_ANIM_IDS(mainptr->lamp.first); + RENAMEFIX_ANIM_NODETREE_IDS(mainptr->lamp.first, Lamp); /* materials */ RENAMEFIX_ANIM_NODETREE_IDS(mainptr->mat.first, Material); @@ -910,7 +910,7 @@ void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const cha RENAMEFIX_ANIM_IDS(mainptr->mask.first); /* worlds */ - RENAMEFIX_ANIM_IDS(mainptr->world.first); + RENAMEFIX_ANIM_NODETREE_IDS(mainptr->world.first, World); /* scenes */ RENAMEFIX_ANIM_NODETREE_IDS(mainptr->scene.first, Scene); @@ -973,9 +973,8 @@ KeyingSet *BKE_keyingset_add(ListBase *list, const char idname[], const char nam /* allocate new KeyingSet */ ks = MEM_callocN(sizeof(KeyingSet), "KeyingSet"); - BLI_strncpy(ks->idname, idname ? idname : name ? name : "KeyingSet", sizeof(ks->idname)); - - BLI_strncpy(ks->name, name ? name : idname ? idname : "Keying Set", sizeof(ks->name)); + BLI_strncpy(ks->idname, (idname) ? idname : (name) ? name : "KeyingSet", sizeof(ks->idname)); + BLI_strncpy(ks->name, (name) ? name : (idname) ? idname : "Keying Set", sizeof(ks->name)); ks->flag = flag; ks->keyingflag = keyingflag; @@ -983,10 +982,10 @@ KeyingSet *BKE_keyingset_add(ListBase *list, const char idname[], const char nam /* add KeyingSet to list */ BLI_addtail(list, ks); - /* Make sure KeyingSet has a unique idname. */ + /* Make sure KeyingSet has a unique idname */ BLI_uniquename(list, ks, "KeyingSet", '.', offsetof(KeyingSet, idname), sizeof(ks->idname)); - /* Make sure KeyingSet has a unique label (this helps with identification). */ + /* Make sure KeyingSet has a unique label (this helps with identification) */ BLI_uniquename(list, ks, "Keying Set", '.', offsetof(KeyingSet, name), sizeof(ks->name)); /* return new KeyingSet for further editing */ diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index b3cbc1f2b16..1970df54339 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1822,8 +1822,15 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos */ /* only happens on reload file, but violates depsgraph still... fix! */ - if ((cu->path == NULL) || (cu->path->data == NULL)) + if (ELEM(NULL, cu->path, cu->path->data)) { BKE_displist_make_curveTypes(scene, ikData->tar, 0); + + /* path building may fail in EditMode after removing verts [#33268]*/ + if (ELEM(NULL, cu->path, cu->path->data)) { + /* BLI_assert(cu->path != NULL); */ + return; + } + } } /* find the root bone and the chain of bones from the root to the tip diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index e1e868b234e..f0d201ea3f7 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -70,6 +70,7 @@ #include "BKE_displist.h" #include "BKE_global.h" #include "BKE_idprop.h" +#include "BKE_image.h" #include "BKE_ipo.h" #include "BKE_library.h" #include "BKE_main.h" @@ -113,6 +114,7 @@ void free_blender(void) BKE_spacetypes_free(); /* after free main, it uses space callbacks */ IMB_exit(); + BKE_images_exit(); BLI_callback_global_finalize(); @@ -266,7 +268,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath G.winpos = bfd->winpos; G.displaymode = bfd->displaymode; G.fileflags = bfd->fileflags; - CTX_wm_manager_set(C, bfd->main->wm.first); + CTX_wm_manager_set(C, G.main->wm.first); CTX_wm_screen_set(C, bfd->curscreen); CTX_data_scene_set(C, bfd->curscreen->scene); CTX_wm_area_set(C, NULL); @@ -276,7 +278,11 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath /* this can happen when active scene was lib-linked, and doesn't exist anymore */ if (CTX_data_scene(C) == NULL) { - CTX_data_scene_set(C, bfd->main->scene.first); + /* in case we don't even have a local scene, add one */ + if (!G.main->scene.first) + BKE_scene_add("Scene"); + + CTX_data_scene_set(C, G.main->scene.first); CTX_wm_screen(C)->scene = CTX_data_scene(C); curscene = CTX_data_scene(C); } diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c index df7fb2c1807..0495e729937 100644 --- a/source/blender/blenkernel/intern/bmfont.c +++ b/source/blender/blenkernel/intern/bmfont.c @@ -247,12 +247,13 @@ int locateGlyph(bmFont *bmfont, unsigned short unicode) return(current); } -void matrixGlyph(ImBuf * ibuf, unsigned short unicode, - float *centerx, float *centery, - float *sizex, float *sizey, - float *transx, float *transy, - float *movex, float *movey, - float *advance) +void matrixGlyph( + ImBuf * ibuf, unsigned short unicode, + float *centerx, float *centery, + float *sizex, float *sizey, + float *transx, float *transy, + float *movex, float *movey, + float *advance) { int index; bmFont *bmfont; diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 98b206712d6..f310895f590 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -1287,8 +1287,6 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side) texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache"); - BKE_image_get_ibuf(mtex->tex->ima, NULL); - /*do normalized cannonical view coords for texture*/ for (y = -1.0, iy = 0; iy < side; iy++, y += step) { for (x = -1.0, ix = 0; ix < side; ix++, x += step) { diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 9118baeae6f..57c88919021 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -267,6 +267,7 @@ void BKE_camera_params_from_view3d(CameraParams *params, View3D *v3d, RegionView params->clipsta = -params->clipend; params->is_ortho = TRUE; + /* make sure any changes to this match ED_view3d_radius_to_ortho_dist() */ params->ortho_scale = rv3d->dist * sensor_size / v3d->lens; params->zoom = 2.0f; } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 2e0b3a3c64a..54bbe4bf495 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -623,8 +623,8 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, /* double lookup */ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } colType = CD_TEXTURE_MCOL; @@ -653,12 +653,29 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, else { if (index_mf_to_mpoly) { orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i); - if (orig == ORIGINDEX_NONE) { if (nors) nors += 3; continue; } - if (drawParamsMapped) { draw_option = drawParamsMapped(userData, orig); } - else { if (nors) nors += 3; continue; } + if (orig == ORIGINDEX_NONE) { + /* XXX, this is not really correct + * it will draw the previous faces context for this one when we don't know its settings. + * but better then skipping it altogether. - campbell */ + draw_option = DM_DRAW_OPTION_NORMAL; + } + else if (drawParamsMapped) { + draw_option = drawParamsMapped(userData, orig); + } + else { + if (nors) { + nors += 3; continue; + } + } + } + else if (drawParamsMapped) { + draw_option = drawParamsMapped(userData, i); + } + else { + if (nors) { + nors += 3; continue; + } } - else if (drawParamsMapped) { draw_option = drawParamsMapped(userData, i); } - else { if (nors) nors += 3; continue; } } if (draw_option != DM_DRAW_OPTION_SKIP) { @@ -742,9 +759,12 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, if (index_mf_to_mpoly) { orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace); if (orig == ORIGINDEX_NONE) { - continue; + /* XXX, this is not really correct + * it will draw the previous faces context for this one when we don't know its settings. + * but better then skipping it altogether. - campbell */ + draw_option = DM_DRAW_OPTION_NORMAL; } - if (drawParamsMapped) { + else if (drawParamsMapped) { draw_option = drawParamsMapped(userData, orig); } } @@ -812,8 +832,8 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, /* double lookup */ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } @@ -828,8 +848,6 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, mcol = DM_get_tessface_data_layer(dm, colType); } - printf("%s: %p(%d/%d)\n", __func__, mcol, CD_ID_MCOL, colType); - cdDM_update_normals_from_pbvh(dm); /* back-buffer always uses legacy since VBO's would need the @@ -1050,8 +1068,8 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, /* double lookup */ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } cdDM_update_normals_from_pbvh(dm); @@ -1351,8 +1369,8 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm, /* double lookup */ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } cdDM_update_normals_from_pbvh(dm); @@ -1956,12 +1974,11 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, int use_mdisps, /* avoid this where possiblem, takes extra memory */ if (use_tessface) { - int *polyindex; BM_mesh_elem_index_ensure(bm, BM_FACE); index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); - for (i = 0; i < dm->numTessFaceData; i++, index++, polyindex++) { + for (i = 0; i < dm->numTessFaceData; i++, index++) { MFace *mf = &mface[i]; const BMLoop **l = em_looptris[i]; efa = l[0]->f; @@ -2257,6 +2274,11 @@ void CDDM_calc_normals_tessface(DerivedMesh *dm) * this is a really horribly written function. ger. - joeedh * * note, CDDM_recalc_tessellation has to run on the returned DM if you want to access tessfaces. + * + * Note: This function is currently only used by the Mirror modifier, so it + * skips any faces that have all vertices merged (to avoid creating pairs + * of faces sharing the same set of vertices). If used elsewhere, it may + * be necessary to make this functionality optional. */ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) { @@ -2300,14 +2322,11 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) newv[i] = newv[vtargetmap[i]]; } } - - /* find-replace merged vertices with target vertices */ - ml = cddm->mloop; - for (i = 0; i < totloop; i++, ml++) { - if (vtargetmap[ml->v] != -1) { - ml->v = vtargetmap[ml->v]; - } - } + + /* Don't remap vertices in cddm->mloop, because we need to know the original + * indices in order to skip faces with all vertices merged. + * The "update loop indices..." section further down remaps vertices in mloop. + */ /* now go through and fix edges and faces */ med = cddm->medge; @@ -2341,6 +2360,24 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) ml = cddm->mloop + mp->loopstart; + /* skip faces with all vertices merged */ + { + int all_vertices_merged = TRUE; + + for (j = 0; j < mp->totloop; j++, ml++) { + if (vtargetmap[ml->v] == -1) { + all_vertices_merged = FALSE; + break; + } + } + + if (UNLIKELY(all_vertices_merged)) { + continue; + } + } + + ml = cddm->mloop + mp->loopstart; + c = 0; for (j = 0; j < mp->totloop; j++, ml++) { med = cddm->medge + ml->e; @@ -2499,7 +2536,7 @@ void CDDM_calc_edges(DerivedMesh *dm) EdgeHashIterator *ehi; MPoly *mp = cddm->mpoly; MLoop *ml; - MEdge *med; + MEdge *med, *origmed; EdgeHash *eh = BLI_edgehash_new(); int v1, v2; int *eindex; @@ -2532,6 +2569,7 @@ void CDDM_calc_edges(DerivedMesh *dm) CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); + origmed = cddm->medge; med = CustomData_get_layer(&edgeData, CD_MEDGE); index = CustomData_get_layer(&edgeData, CD_ORIGINDEX); @@ -2542,8 +2580,14 @@ void CDDM_calc_edges(DerivedMesh *dm) BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2); j = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); - med->flag = ME_EDGEDRAW | ME_EDGERENDER; - *index = j == 0 ? ORIGINDEX_NONE : eindex[j - 1]; + if (j == 0) { + med->flag = ME_EDGEDRAW | ME_EDGERENDER; + *index = ORIGINDEX_NONE; + } + else { + med->flag = ME_EDGEDRAW | ME_EDGERENDER | origmed[j - 1].flag; + *index = eindex[j - 1]; + } BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i)); } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index b488e683947..4641a02265a 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -198,8 +198,10 @@ static void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3 w3[0] = 1.0f - w1[0] - w2[0]; } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdouble-promotion" +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif DO_INLINE void collision_interpolateOnTriangle ( float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3 ) { @@ -371,7 +373,9 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM return result; } -#pragma GCC diagnostic pop +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif //Determines collisions on overlap, collisions are written to collpair[i] and collision+number_collision_found is returned static CollPair* cloth_collision(ModifierData *md1, ModifierData *md2, diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 75276adf518..529fe07cab3 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -1008,8 +1008,8 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings * const ColorManagedDisplaySettings *display_settings) { int x, y, c; - unsigned int n, nl; - double div, divl; + unsigned int nl, na, nr, ng, nb; + double divl, diva, divr, divg, divb; float *rf = NULL; unsigned char *rc = NULL; unsigned int *bin_lum, *bin_r, *bin_g, *bin_b, *bin_a; @@ -1149,24 +1149,37 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings * savedlines += 1; } + /* test for nicer distribution even - non standard, leave it out for a while */ +#if 0 + for (x = 0; x < 256; x++) { + bin_lum[x] = sqrt (bin_lum[x]); + bin_r[x] = sqrt(bin_r[x]); + bin_g[x] = sqrt(bin_g[x]); + bin_b[x] = sqrt(bin_b[x]); + bin_a[x] = sqrt(bin_a[x]); + } +#endif + /* convert hist data to float (proportional to max count) */ - n = 0; - nl = 0; + nl = na = nr = nb = ng = 0; for (x = 0; x < 256; x++) { if (bin_lum[x] > nl) nl = bin_lum[x]; - if (bin_r[x] > n) n = bin_r[x]; - if (bin_g[x] > n) n = bin_g[x]; - if (bin_b[x] > n) n = bin_b[x]; - if (bin_a[x] > n) n = bin_a[x]; + if (bin_r[x] > nr) nr = bin_r[x]; + if (bin_g[x] > ng) ng = bin_g[x]; + if (bin_b[x] > nb) nb = bin_b[x]; + if (bin_a[x] > na) na = bin_a[x]; } - div = 1.0 / (double)n; 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; for (x = 0; x < 256; x++) { scopes->hist.data_luma[x] = bin_lum[x] * divl; - scopes->hist.data_r[x] = bin_r[x] * div; - scopes->hist.data_g[x] = bin_g[x] * div; - scopes->hist.data_b[x] = bin_b[x] * div; - scopes->hist.data_a[x] = bin_a[x] * div; + scopes->hist.data_r[x] = bin_r[x] * divr; + scopes->hist.data_g[x] = bin_g[x] * divg; + scopes->hist.data_b[x] = bin_b[x] * divb; + scopes->hist.data_a[x] = bin_a[x] * diva; } MEM_freeN(bin_lum); MEM_freeN(bin_r); diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index e300b5e0f19..97d750854f4 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -84,15 +84,9 @@ #include "BKE_movieclip.h" #ifdef WITH_PYTHON -#include "BPY_extern.h" +# include "BPY_extern.h" #endif -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - - - /* ************************ Constraints - General Utilities *************************** */ /* These functions here don't act on any specific constraints, and are therefore should/will * not require any of the special function-pointers afforded by the relevant constraint diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 719ae7357b4..ffb93139358 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -44,6 +44,7 @@ #include "BLI_listbase.h" #include "BLI_string.h" +#include "BLI_threads.h" #include "BLI_utildefines.h" #include "BKE_context.h" @@ -245,6 +246,10 @@ static void *ctx_wm_python_context_get(const bContext *C, const char *member, vo (void)C, (void)member; #endif + /* don't allow UI context access from non-main threads */ + if (!BLI_thread_is_main()) + return NULL; + return fall_through; } @@ -264,6 +269,11 @@ static int ctx_data_get(bContext *C, const char *member, bContextDataResult *res // return 1; } #endif + + /* don't allow UI context access from non-main threads */ + if (!BLI_thread_is_main()) + return done; + /* we check recursion to ensure that we do not get infinite * loops requesting data from ourselfs in a context callback */ diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 67aaaceaa38..754a4fbc0c8 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1116,13 +1116,13 @@ void BKE_nurb_makeCurve(Nurb *nu, float *coord_array, float *tilt_array, float * *fp = basisu[i] * bp->vec[3]; sumdiv += *fp; } - if (sumdiv != 0.0f) if (sumdiv < 0.999f || sumdiv > 1.001f) { - /* is normalizing needed? */ - fp = sum; - for (i = istart; i <= iend; i++, fp++) { - *fp /= sumdiv; - } + if ((sumdiv != 0.0f) && (sumdiv < 0.999f || sumdiv > 1.001f)) { + /* is normalizing needed? */ + fp = sum; + for (i = istart; i <= iend; i++, fp++) { + *fp /= sumdiv; } + } /* one! (1.0) real point */ fp = sum; @@ -2481,8 +2481,8 @@ void BKE_curve_bevelList_make(Object *ob) else bevp2 = bevp1 + 1; - inp = (bevp1->vec[0] - bevp0->vec[0]) * (bevp0->vec[1] - bevp2->vec[1]) + - (bevp0->vec[1] - bevp1->vec[1]) * (bevp0->vec[0] - bevp2->vec[0]); + inp = ((bevp1->vec[0] - bevp0->vec[0]) * (bevp0->vec[1] - bevp2->vec[1]) + + (bevp0->vec[1] - bevp1->vec[1]) * (bevp0->vec[0] - bevp2->vec[0])); if (inp > 0.0f) sd->dir = 1; diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 93c776ae30e..b2f8db0dcce 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -761,7 +761,7 @@ static void layerDoMinMax_mloopuv(void *data, void *vmin, void *vmax) { MLoopUV *min = vmin, *max = vmax, *luv = data; - DO_MINMAX2(luv->uv, min->uv, max->uv); + minmax_v2v2_v2(min->uv, max->uv, luv->uv); } static void layerAdd_mloopuv(void *data1, void *data2) @@ -833,7 +833,7 @@ static void layerDoMinMax_mloop_origspace(void *data, void *vmin, void *vmax) { OrigSpaceLoop *min = vmin, *max = vmax, *luv = data; - DO_MINMAX2(luv->uv, min->uv, max->uv); + minmax_v2v2_v2(min->uv, max->uv, luv->uv); } static void layerAdd_mloop_origspace(void *data1, void *data2) diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 950a0ca3d60..3ed759392b6 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -45,6 +45,7 @@ #include "DNA_anim_types.h" #include "DNA_camera_types.h" #include "DNA_group_types.h" +#include "DNA_lamp_types.h" #include "DNA_lattice_types.h" #include "DNA_key_types.h" #include "DNA_material_types.h" @@ -350,8 +351,8 @@ static void dag_add_driver_relation(AnimData *adt, DagForest *dag, DagNode *node /* XXX: forward def for material driver handling... */ static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Material *ma); -/* recursive handling for material nodetree drivers */ -static void dag_add_material_nodetree_driver_relations(DagForest *dag, DagNode *node, bNodeTree *ntree) +/* recursive handling for shader nodetree drivers */ +static void dag_add_shader_nodetree_driver_relations(DagForest *dag, DagNode *node, bNodeTree *ntree) { bNode *n; @@ -367,7 +368,7 @@ static void dag_add_material_nodetree_driver_relations(DagForest *dag, DagNode * dag_add_material_driver_relations(dag, node, (Material *)n->id); } else if (n->type == NODE_GROUP) { - dag_add_material_nodetree_driver_relations(dag, node, (bNodeTree *)n->id); + dag_add_shader_nodetree_driver_relations(dag, node, (bNodeTree *)n->id); } } } @@ -386,21 +387,45 @@ static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Mat ma->id.flag |= LIB_DOIT; /* material itself */ - if (ma->adt) { + if (ma->adt) dag_add_driver_relation(ma->adt, dag, node, 1); - } /* textures */ // TODO... //dag_add_texture_driver_relations(DagForest *dag, DagNode *node, ID *id); /* material's nodetree */ - if (ma->nodetree) { - dag_add_material_nodetree_driver_relations(dag, node, ma->nodetree); - } + if (ma->nodetree) + dag_add_shader_nodetree_driver_relations(dag, node, ma->nodetree); } -static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node, int skip_forcefield){ +/* recursive handling for lamp drivers */ +static void dag_add_lamp_driver_relations(DagForest *dag, DagNode *node, Lamp *la) +{ + /* Prevent infinite recursion by checking (and tagging the lamp) as having been visited + * already (see build_dag()). This assumes la->id.flag & LIB_DOIT isn't set by anything else + * in the meantime... [#32017] + */ + if (la->id.flag & LIB_DOIT) + return; + else + la->id.flag |= LIB_DOIT; + + /* lamp itself */ + if (la->adt) + dag_add_driver_relation(la->adt, dag, node, 1); + + /* textures */ + // TODO... + //dag_add_texture_driver_relations(DagForest *dag, DagNode *node, ID *id); + + /* lamp's nodetree */ + if (la->nodetree) + dag_add_shader_nodetree_driver_relations(dag, node, la->nodetree); +} + +static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node, int skip_forcefield) +{ Base *base; DagNode *node2; @@ -646,6 +671,9 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O } } } + else if (ob->type == OB_LAMP) { + dag_add_lamp_driver_relations(dag, node, ob->data); + } /* particles */ psys = ob->particlesystem.first; @@ -816,6 +844,7 @@ DagForest *build_dag(Main *bmain, Scene *sce, short mask) /* clear "LIB_DOIT" flag from all materials, to prevent infinite recursion problems later [#32017] */ tag_main_idcode(bmain, ID_MA, FALSE); + tag_main_idcode(bmain, ID_LA, FALSE); /* add base node for scene. scene is always the first node in DAG */ scenenode = dag_add_node(dag, sce); @@ -1911,13 +1940,13 @@ void DAG_scene_sort(Main *bmain, Scene *sce) static void lib_id_recalc_tag(Main *bmain, ID *id) { id->flag |= LIB_ID_RECALC; - bmain->id_tag_update[id->name[0]] = 1; + DAG_id_type_tag(bmain, GS(id->name)); } static void lib_id_recalc_data_tag(Main *bmain, ID *id) { id->flag |= LIB_ID_RECALC_DATA; - bmain->id_tag_update[id->name[0]] = 1; + DAG_id_type_tag(bmain, GS(id->name)); } /* node was checked to have lasttime != curtime and is if type ID_OB */ @@ -2789,6 +2818,7 @@ void DAG_ids_check_recalc(Main *bmain, Scene *scene, int time) void DAG_ids_clear_recalc(Main *bmain) { ListBase *lbarray[MAX_LIBARRAY]; + bNodeTree *ntree; int a; /* loop over all ID types */ @@ -2801,9 +2831,15 @@ void DAG_ids_clear_recalc(Main *bmain) /* we tag based on first ID type character to avoid * looping over all ID's in case there are no tags */ if (id && bmain->id_tag_update[id->name[0]]) { - for (; id; id = id->next) + for (; id; id = id->next) { if (id->flag & (LIB_ID_RECALC | LIB_ID_RECALC_DATA)) id->flag &= ~(LIB_ID_RECALC | LIB_ID_RECALC_DATA); + + /* some ID's contain semi-datablock nodetree */ + ntree = ntreeFromID(id); + if (ntree && (ntree->id.flag & (LIB_ID_RECALC | LIB_ID_RECALC_DATA))) + ntree->id.flag &= ~(LIB_ID_RECALC | LIB_ID_RECALC_DATA); + } } } @@ -2870,8 +2906,18 @@ void DAG_id_tag_update(ID *id, short flag) } } -void DAG_id_type_tag(struct Main *bmain, short idtype) +void DAG_id_type_tag(Main *bmain, short idtype) { + if (idtype == ID_NT) { + /* stupid workaround so parent datablocks of nested nodetree get looped + * over when we loop over tagged datablock types */ + DAG_id_type_tag(bmain, ID_MA); + DAG_id_type_tag(bmain, ID_TE); + DAG_id_type_tag(bmain, ID_LA); + DAG_id_type_tag(bmain, ID_WO); + DAG_id_type_tag(bmain, ID_SCE); + } + bmain->id_tag_update[((char *)&idtype)[0]] = 1; } diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index e13d05d0a2f..083cb02fd3d 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -487,7 +487,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, int flipnormal) } /* XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) { */ - if (totvert && (tot = BLI_scanfill_calc(&sf_ctx, FALSE))) { + if (totvert && (tot = BLI_scanfill_calc(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES))) { if (tot) { dlnew = MEM_callocN(sizeof(DispList), "filldisplist"); dlnew->type = DL_INDEX3; @@ -630,7 +630,7 @@ static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dis * - first point left, last point right * - based on subdivided points in original curve, not on points in taper curve (still) */ -float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot) +static float displist_calc_taper(Scene *scene, Object *taperobj, float fac) { DispList *dl; @@ -643,7 +643,6 @@ float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot) dl = taperobj->disp.first; } if (dl) { - float fac = ((float)cur) / (float)(tot - 1); float minx, dx, *fp; int a; @@ -671,6 +670,13 @@ float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot) return 1.0; } +float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot) +{ + float fac = ((float)cur) / (float)(tot - 1); + + return displist_calc_taper(scene, taperobj, fac); +} + void BKE_displist_make_mball(Scene *scene, Object *ob) { if (!ob || ob->type != OB_MBALL) @@ -1240,7 +1246,7 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase, } } -static void rotateBevelPiece(Curve *cu, BevPoint *bevp, DispList *dlb, float widfac, float fac, float **data_r) +static void rotateBevelPiece(Curve *cu, BevPoint *bevp, BevPoint *nbevp, DispList *dlb, float bev_blend, float widfac, float fac, float **data_r) { float *fp, *data = *data_r; int b; @@ -1248,22 +1254,48 @@ static void rotateBevelPiece(Curve *cu, BevPoint *bevp, DispList *dlb, float wid fp = dlb->verts; for (b = 0; b < dlb->nr; b++, fp += 3, data += 3) { if (cu->flag & CU_3D) { - float vec[3]; + float vec[3], quat[4]; vec[0] = fp[1] + widfac; vec[1] = fp[2]; vec[2] = 0.0; - mul_qt_v3(bevp->quat, vec); + if (nbevp == NULL) { + copy_v3_v3(data, bevp->vec); + copy_qt_qt(quat, bevp->quat); + } + else { + interp_v3_v3v3(data, bevp->vec, nbevp->vec, bev_blend); + interp_qt_qtqt(quat, bevp->quat, nbevp->quat, bev_blend); + } - data[0] = bevp->vec[0] + fac * vec[0]; - data[1] = bevp->vec[1] + fac * vec[1]; - data[2] = bevp->vec[2] + fac * vec[2]; + mul_qt_v3(quat, vec); + + data[0] += fac * vec[0]; + data[1] += fac * vec[1]; + data[2] += fac * vec[2]; } else { - data[0] = bevp->vec[0] + fac * (widfac + fp[1]) * bevp->sina; - data[1] = bevp->vec[1] + fac * (widfac + fp[1]) * bevp->cosa; - data[2] = bevp->vec[2] + fac * fp[2]; + float sina, cosa; + + if (nbevp == NULL) { + copy_v3_v3(data, bevp->vec); + sina = bevp->sina; + cosa = bevp->cosa; + } + else { + interp_v3_v3v3(data, bevp->vec, nbevp->vec, bev_blend); + + /* perhaps we need to interpolate angles instead. but the thing is + * cosa and sina are not actually sine and cosine + */ + sina = nbevp->sina * bev_blend + bevp->sina * (1.0f - bev_blend); + cosa = nbevp->cosa * bev_blend + bevp->cosa * (1.0f - bev_blend); + } + + data[0] += fac * (widfac + fp[1]) * sina; + data[1] += fac * (widfac + fp[1]) * cosa; + data[2] += fac * fp[2]; } } @@ -1399,8 +1431,8 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba firstblend = 1.0f - (bevfac1 * (bl->nr - 1) - (int)(bevfac1 * (bl->nr - 1))); lastblend = bevfac2 * (bl->nr - 1) - (int)(bevfac2 * (bl->nr - 1)); - if (steps > bl->nr) { - steps = bl->nr; + if (start + steps > bl->nr) { + steps = bl->nr - start; lastblend = 1.0f; } @@ -1438,7 +1470,29 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba fac = bevp->radius; } else { - fac = BKE_displist_calc_taper(scene, cu->taperobj, i, bl->nr); + float len, taper_fac; + + if (cu->flag & CU_MAP_TAPER) { + len = (steps - 3) + firstblend + lastblend; + + if (a == 0) + taper_fac = 0.0f; + else if (a == steps - 1) + taper_fac = 1.0f; + else + taper_fac = ((float) a - (1.0f - firstblend)) / len; + } + else { + len = bl->nr - 1; + taper_fac = (float) i / len; + + if (a == 0) + taper_fac += (1.0f - firstblend) / len; + else if (a == steps - 1) + taper_fac -= (1.0f - lastblend) / len; + } + + fac = displist_calc_taper(scene, cu->taperobj, taper_fac); } if (bevp->split_tag) { @@ -1446,27 +1500,12 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba } /* rotate bevel piece and write in data */ - rotateBevelPiece(cu, bevp, dlb, widfac, fac, &data); - - if (a == 1 || a == steps - 1) { - float *cur_fp = cur_data, *prev_fp = cur_data - 3 * dlb->nr; - int b; - - for (b = 0; b < dlb->nr; b++, prev_fp += 3, cur_fp += 3) { - float cur[3], prev[3]; - - copy_v3_v3(cur, cur_fp); - copy_v3_v3(prev, prev_fp); - - if (a == 1) - interp_v3_v3v3(prev, cur_fp, prev_fp, firstblend); - if (a == steps - 1) - interp_v3_v3v3(cur, prev_fp, cur_fp, lastblend); - - copy_v3_v3(cur_fp, cur); - copy_v3_v3(prev_fp, prev); - } - } + if (a == 0) + rotateBevelPiece(cu, bevp, bevp + 1, dlb, 1.0f - firstblend, widfac, fac, &data); + else if (a == steps - 1) + rotateBevelPiece(cu, bevp, bevp - 1, dlb, 1.0f - lastblend, widfac, fac, &data); + else + rotateBevelPiece(cu, bevp, NULL, dlb, 0.0f, widfac, fac, &data); if (cu->bevobj && (cu->flag & CU_FILL_CAPS)) { if (a == 1) diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 89d728c0419..ed85e5b627b 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -86,11 +86,13 @@ #include "RE_shader_ext.h" #ifdef _OPENMP -#include +# include #endif /* could enable at some point but for now there are far too many conversions */ -#pragma GCC diagnostic ignored "-Wdouble-promotion" +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif /* precalculated gaussian factors for 5x super sampling */ static float gaussianFactors[5] = {0.996849f, @@ -3364,7 +3366,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, (!hit_found || (brush->flags & MOD_DPAINT_INVERSE_PROX))) { float proxDist = -1.0f; - float hitCo[3]; + float hitCo[3] = {0.0f, 0.0f, 0.0f}; short hQuad; int face; @@ -3721,6 +3723,8 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, float smooth_range = smooth * (1.0f - strength), dist; /* calculate max range that can have particles with higher influence than the nearest one */ float max_range = smooth - strength * smooth + solidradius; + /* Make gcc happy! */ + dist = max_range; particles = BLI_kdtree_range_search(tree, max_range, bData->realCoord[bData->s_pos[index]].v, NULL, &nearest); diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 8d430eb58b5..321a61ce238 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -215,7 +215,7 @@ static void BMEdit_RecalcTessellation_intern(BMEditMesh *tm) /* complete the loop */ BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert); - totfilltri = BLI_scanfill_calc_ex(&sf_ctx, FALSE, efa->no); + totfilltri = BLI_scanfill_calc_ex(&sf_ctx, 0, efa->no); BLI_array_grow_items(looptris, totfilltri); for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c index 30427a81c4b..c3008d17bd1 100644 --- a/source/blender/blenkernel/intern/idcode.c +++ b/source/blender/blenkernel/intern/idcode.c @@ -47,39 +47,40 @@ typedef struct { } IDType; /* plural need to match rna_main.c's MainCollectionDef */ +/* WARNING! Keep it in sync with i18n contexts in BLF_translation.h */ static IDType idtypes[] = { - { ID_AC, "Action", "actions", IDTYPE_FLAGS_ISLINKABLE}, - { ID_AR, "Armature", "armatures", IDTYPE_FLAGS_ISLINKABLE}, - { ID_BR, "Brush", "brushes", IDTYPE_FLAGS_ISLINKABLE}, - { ID_CA, "Camera", "cameras", IDTYPE_FLAGS_ISLINKABLE}, - { ID_CU, "Curve", "curves", IDTYPE_FLAGS_ISLINKABLE}, - { ID_GD, "GPencil", "grease_pencil", IDTYPE_FLAGS_ISLINKABLE}, /* rename gpencil */ - { ID_GR, "Group", "groups", IDTYPE_FLAGS_ISLINKABLE}, - { ID_ID, "ID", "ids", 0}, /* plural is fake */ - { ID_IM, "Image", "images", IDTYPE_FLAGS_ISLINKABLE}, - { ID_IP, "Ipo", "ipos", IDTYPE_FLAGS_ISLINKABLE}, /* deprecated */ - { ID_KE, "Key", "shape_keys", 0}, - { ID_LA, "Lamp", "lamps", IDTYPE_FLAGS_ISLINKABLE}, - { ID_LI, "Library", "libraries", 0}, - { ID_LT, "Lattice", "lattices", IDTYPE_FLAGS_ISLINKABLE}, - { ID_MA, "Material", "materials", IDTYPE_FLAGS_ISLINKABLE}, - { ID_MB, "Metaball", "metaballs", IDTYPE_FLAGS_ISLINKABLE}, - { ID_ME, "Mesh", "meshes", IDTYPE_FLAGS_ISLINKABLE}, - { ID_NT, "NodeTree", "node_groups", IDTYPE_FLAGS_ISLINKABLE}, - { ID_OB, "Object", "objects", IDTYPE_FLAGS_ISLINKABLE}, - { ID_PA, "ParticleSettings", "particles", 0}, - { ID_SCE, "Scene", "scenes", IDTYPE_FLAGS_ISLINKABLE}, - { ID_SCR, "Screen", "screens", 0}, - { ID_SEQ, "Sequence", "sequences", 0}, /* not actually ID data */ - { ID_SPK, "Speaker", "speakers", IDTYPE_FLAGS_ISLINKABLE}, - { ID_SO, "Sound", "sounds", IDTYPE_FLAGS_ISLINKABLE}, - { ID_TE, "Texture", "textures", IDTYPE_FLAGS_ISLINKABLE}, - { ID_TXT, "Text", "texts", IDTYPE_FLAGS_ISLINKABLE}, - { ID_VF, "VFont", "fonts", IDTYPE_FLAGS_ISLINKABLE}, - { ID_WO, "World", "worlds", IDTYPE_FLAGS_ISLINKABLE}, - { ID_WM, "WindowManager", "window_managers", 0}, - { ID_MC, "MovieClip", "movieclips", IDTYPE_FLAGS_ISLINKABLE}, - { ID_MSK, "Mask", "masks", IDTYPE_FLAGS_ISLINKABLE}, + { ID_AC, "Action", "actions", IDTYPE_FLAGS_ISLINKABLE }, + { ID_AR, "Armature", "armatures", IDTYPE_FLAGS_ISLINKABLE }, + { ID_BR, "Brush", "brushes", IDTYPE_FLAGS_ISLINKABLE }, + { ID_CA, "Camera", "cameras", IDTYPE_FLAGS_ISLINKABLE }, + { ID_CU, "Curve", "curves", IDTYPE_FLAGS_ISLINKABLE }, + { ID_GD, "GPencil", "grease_pencil", IDTYPE_FLAGS_ISLINKABLE }, /* rename gpencil */ + { ID_GR, "Group", "groups", IDTYPE_FLAGS_ISLINKABLE }, + { ID_ID, "ID", "ids", 0 }, /* plural is fake */ + { ID_IM, "Image", "images", IDTYPE_FLAGS_ISLINKABLE }, + { ID_IP, "Ipo", "ipos", IDTYPE_FLAGS_ISLINKABLE }, /* deprecated */ + { ID_KE, "Key", "shape_keys", 0 }, + { ID_LA, "Lamp", "lamps", IDTYPE_FLAGS_ISLINKABLE }, + { ID_LI, "Library", "libraries", 0 }, + { ID_LT, "Lattice", "lattices", IDTYPE_FLAGS_ISLINKABLE }, + { ID_MA, "Material", "materials", IDTYPE_FLAGS_ISLINKABLE }, + { ID_MB, "Metaball", "metaballs", IDTYPE_FLAGS_ISLINKABLE }, + { ID_MC, "MovieClip", "movieclips", IDTYPE_FLAGS_ISLINKABLE }, + { ID_ME, "Mesh", "meshes", IDTYPE_FLAGS_ISLINKABLE }, + { ID_MSK, "Mask", "masks", IDTYPE_FLAGS_ISLINKABLE }, + { ID_NT, "NodeTree", "node_groups", IDTYPE_FLAGS_ISLINKABLE }, + { ID_OB, "Object", "objects", IDTYPE_FLAGS_ISLINKABLE }, + { ID_PA, "ParticleSettings", "particles", 0 }, + { ID_SCE, "Scene", "scenes", IDTYPE_FLAGS_ISLINKABLE }, + { ID_SCR, "Screen", "screens", 0 }, + { ID_SEQ, "Sequence", "sequences", 0 }, /* not actually ID data */ + { ID_SPK, "Speaker", "speakers", IDTYPE_FLAGS_ISLINKABLE }, + { ID_SO, "Sound", "sounds", IDTYPE_FLAGS_ISLINKABLE }, + { ID_TE, "Texture", "textures", IDTYPE_FLAGS_ISLINKABLE }, + { ID_TXT, "Text", "texts", IDTYPE_FLAGS_ISLINKABLE }, + { ID_VF, "VFont", "fonts", IDTYPE_FLAGS_ISLINKABLE }, + { ID_WO, "World", "worlds", IDTYPE_FLAGS_ISLINKABLE }, + { ID_WM, "WindowManager", "window_managers", 0 }, }; static int nidtypes = sizeof(idtypes) / sizeof(idtypes[0]); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index ef751ce3493..f09f128e874 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -100,6 +100,8 @@ #include "WM_api.h" +static SpinLock image_spin; + /* max int, to indicate we don't store sequences in ibuf */ #define IMA_NO_INDEX 0x7FEFEFEF @@ -108,6 +110,16 @@ #define IMA_INDEX_FRAME(index) (index >> 10) #define IMA_INDEX_PASS(index) (index & ~1023) +void BKE_images_init(void) +{ + BLI_spin_init(&image_spin); +} + +void BKE_images_exit(void) +{ + BLI_spin_end(&image_spin); +} + /* ******** IMAGE PROCESSING ************* */ static void de_interlace_ng(struct ImBuf *ibuf) /* neogeo fields */ @@ -168,13 +180,14 @@ static void de_interlace_st(struct ImBuf *ibuf) /* standard fields */ void BKE_image_de_interlace(Image *ima, int odd) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ibuf) { if (odd) de_interlace_st(ibuf); else de_interlace_ng(ibuf); } + BKE_image_release_ibuf(ima, ibuf, NULL); } /* ***************** ALLOC & FREE, DATA MANAGING *************** */ @@ -260,8 +273,9 @@ static ImBuf *image_get_ibuf(Image *ima, int index, int frame) /* this function is intended to be thread safe. with IMA_NO_INDEX this * should be OK, but when iterating over the list this is more tricky * */ - if (index == IMA_NO_INDEX) + if (index == IMA_NO_INDEX) { return ima->ibufs.first; + } else { ImBuf *ibuf; @@ -269,9 +283,9 @@ static ImBuf *image_get_ibuf(Image *ima, int index, int frame) for (ibuf = ima->ibufs.first; ibuf; ibuf = ibuf->next) if (ibuf->index == index) return ibuf; - - return NULL; } + + return NULL; } /* no ima->ibuf anymore, but listbase */ @@ -534,7 +548,7 @@ int BKE_image_scale(Image *image, int width, int height) ibuf->userflags |= IB_BITMAPDIRTY; } - BKE_image_release_ibuf(image, lock); + BKE_image_release_ibuf(image, ibuf, lock); return (ibuf != NULL); } @@ -649,6 +663,13 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char BKE_image_buf_fill_color(rect, rect_float, width, height, color); } + if (rect_float) { + /* both byte and float buffers are filling in sRGB space, need to linearize float buffer after BKE_image_buf_fill* functions */ + + IMB_buffer_float_from_float(rect_float, rect_float, ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, + ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x); + } + return ibuf; } @@ -1561,7 +1582,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* also a little of space to the background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and draw the text. */ BLF_position(mono, x, y + y_ofs, 0.0); @@ -1578,7 +1599,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* and space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.note); @@ -1594,7 +1615,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* and space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.date); @@ -1610,7 +1631,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* and space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.rendertime); @@ -1625,7 +1646,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ BLF_position(mono, x, y + y_ofs, 0.0); @@ -1641,7 +1662,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ BLF_position(mono, x, y + y_ofs, 0.0); @@ -1656,7 +1677,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ BLF_position(mono, x, y + y_ofs, 0.0); @@ -1671,7 +1692,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.camera); @@ -1684,7 +1705,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.cameralens); } @@ -1697,7 +1718,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ BLF_position(mono, x, y + y_ofs, 0.0); @@ -1713,7 +1734,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.strip); @@ -2081,6 +2102,8 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) if (ima == NULL) return; + BLI_spin_lock(&image_spin); + switch (signal) { case IMA_SIGNAL_FREE: image_free_buffers(ima); @@ -2157,6 +2180,8 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) break; } + BLI_spin_unlock(&image_spin); + /* don't use notifiers because they are not 100% sure to succeeded * this also makes sure all scenes are accounted for. */ { @@ -2320,7 +2345,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) if (ibuf) { #ifdef WITH_OPENEXR - /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_get_ibuf */ + /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */ if (ibuf->ftype == OPENEXR && ibuf->userdata) { image_create_multilayer(ima, ibuf, frame); ima->type = IMA_TYPE_MULTILAYER; @@ -2482,7 +2507,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) } if (ibuf) { - /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_get_ibuf */ + /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */ if (ibuf->ftype == OPENEXR && ibuf->userdata) { image_create_multilayer(ima, ibuf, cfra); ima->type = IMA_TYPE_MULTILAYER; @@ -2751,38 +2776,32 @@ static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame * a big bottleneck */ } - *frame_r = frame; - *index_r = index; + if (frame_r) + *frame_r = frame; + + if (index_r) + *index_r = index; return ibuf; } -/* Checks optional ImageUser and verifies/creates ImBuf. */ -/* use this one if you want to get a render result in progress, - * if not, use BKE_image_get_ibuf which doesn't require a release */ -ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) +/* Checks optional ImageUser and verifies/creates ImBuf. + * + * not thread-safe, so callee should worry about thread locks + */ +static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) { ImBuf *ibuf = NULL; float color[] = {0, 0, 0, 1}; int frame = 0, index = 0; - /* This function is intended to be thread-safe. It postpones the mutex lock - * until it needs to load the image, if the image is already there it - * should just get the pointer and return. The reason is that a lot of mutex - * locks appears to be very slow on certain multicore macs, causing a render - * with image textures to actually slow down as more threads are used. - * - * Note that all the image loading functions should also make sure they do - * things in a threadsafe way for image_get_ibuf_threadsafe to work correct. - * That means, the last two steps must be, 1) add the ibuf to the list and - * 2) set ima/iuser->ok to 0 to IMA_OK_LOADED */ - if (lock_r) *lock_r = NULL; /* quick reject tests */ if (ima == NULL) return NULL; + if (iuser) { if (iuser->ok == 0) return NULL; @@ -2790,95 +2809,71 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) else if (ima->ok == 0) return NULL; - /* try to get the ibuf without locking */ ibuf = image_get_ibuf_threadsafe(ima, iuser, &frame, &index); if (ibuf == NULL) { - /* couldn't get ibuf and image is not ok, so let's lock and try to - * load the image */ - BLI_lock_thread(LOCK_IMAGE); - - /* need to check ok flag and loading ibuf again, because the situation - * might have changed in the meantime */ - if (iuser) { - if (iuser->ok == 0) { - BLI_unlock_thread(LOCK_IMAGE); - return NULL; + /* we are sure we have to load the ibuf, using source and type */ + if (ima->source == IMA_SRC_MOVIE) { + /* source is from single file, use flipbook to store ibuf */ + ibuf = image_load_movie_file(ima, iuser, frame); + } + else if (ima->source == IMA_SRC_SEQUENCE) { + if (ima->type == IMA_TYPE_IMAGE) { + /* regular files, ibufs in flipbook, allows saving */ + ibuf = image_load_sequence_file(ima, iuser, frame); + } + /* no else; on load the ima type can change */ + if (ima->type == IMA_TYPE_MULTILAYER) { + /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */ + ibuf = image_load_sequence_multilayer(ima, iuser, frame); } } - else if (ima->ok == 0) { - BLI_unlock_thread(LOCK_IMAGE); - return NULL; + else if (ima->source == IMA_SRC_FILE) { + + if (ima->type == IMA_TYPE_IMAGE) + ibuf = image_load_image_file(ima, iuser, frame); /* cfra only for '#', this global is OK */ + /* no else; on load the ima type can change */ + if (ima->type == IMA_TYPE_MULTILAYER) + /* keeps render result, stores ibufs in listbase, allows saving */ + ibuf = image_get_ibuf_multilayer(ima, iuser); + } - - ibuf = image_get_ibuf_threadsafe(ima, iuser, &frame, &index); - - if (ibuf == NULL) { - /* we are sure we have to load the ibuf, using source and type */ - if (ima->source == IMA_SRC_MOVIE) { - /* source is from single file, use flipbook to store ibuf */ - ibuf = image_load_movie_file(ima, iuser, frame); + else if (ima->source == IMA_SRC_GENERATED) { + /* generated is: ibuf is allocated dynamically */ + /* UV testgrid or black or solid etc */ + if (ima->gen_x == 0) ima->gen_x = 1024; + if (ima->gen_y == 0) ima->gen_y = 1024; + ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 24, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type, + color, &ima->colorspace_settings); + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + ima->ok = IMA_OK_LOADED; + } + else if (ima->source == IMA_SRC_VIEWER) { + if (ima->type == IMA_TYPE_R_RESULT) { + /* always verify entirely, and potentially + * returns pointer to release later */ + ibuf = image_get_render_result(ima, iuser, lock_r); } - else if (ima->source == IMA_SRC_SEQUENCE) { - if (ima->type == IMA_TYPE_IMAGE) { - /* regular files, ibufs in flipbook, allows saving */ - ibuf = image_load_sequence_file(ima, iuser, frame); - } - /* no else; on load the ima type can change */ - if (ima->type == IMA_TYPE_MULTILAYER) { - /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */ - ibuf = image_load_sequence_multilayer(ima, iuser, frame); - } - } - else if (ima->source == IMA_SRC_FILE) { + else if (ima->type == IMA_TYPE_COMPOSITE) { + /* requires lock/unlock, otherwise don't return image */ + if (lock_r) { + /* unlock in BKE_image_release_ibuf */ + BLI_lock_thread(LOCK_VIEWER); + *lock_r = ima; - if (ima->type == IMA_TYPE_IMAGE) - ibuf = image_load_image_file(ima, iuser, frame); /* cfra only for '#', this global is OK */ - /* no else; on load the ima type can change */ - if (ima->type == IMA_TYPE_MULTILAYER) - /* keeps render result, stores ibufs in listbase, allows saving */ - ibuf = image_get_ibuf_multilayer(ima, iuser); + /* XXX anim play for viewer nodes not yet supported */ + frame = 0; // XXX iuser?iuser->framenr:0; + ibuf = image_get_ibuf(ima, 0, frame); - } - else if (ima->source == IMA_SRC_GENERATED) { - /* generated is: ibuf is allocated dynamically */ - /* UV testgrid or black or solid etc */ - if (ima->gen_x == 0) ima->gen_x = 1024; - if (ima->gen_y == 0) ima->gen_y = 1024; - ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 24, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type, - color, &ima->colorspace_settings); - image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); - ima->ok = IMA_OK_LOADED; - } - else if (ima->source == IMA_SRC_VIEWER) { - if (ima->type == IMA_TYPE_R_RESULT) { - /* always verify entirely, and potentially - * returns pointer to release later */ - ibuf = image_get_render_result(ima, iuser, lock_r); - } - else if (ima->type == IMA_TYPE_COMPOSITE) { - /* requires lock/unlock, otherwise don't return image */ - if (lock_r) { - /* unlock in BKE_image_release_ibuf */ - BLI_lock_thread(LOCK_VIEWER); - *lock_r = ima; - - /* XXX anim play for viewer nodes not yet supported */ - frame = 0; // XXX iuser?iuser->framenr:0; - ibuf = image_get_ibuf(ima, 0, frame); - - if (!ibuf) { - /* Composite Viewer, all handled in compositor */ - /* fake ibuf, will be filled in compositor */ - ibuf = IMB_allocImBuf(256, 256, 32, IB_rect); - image_assign_ibuf(ima, ibuf, 0, frame); - } + if (!ibuf) { + /* Composite Viewer, all handled in compositor */ + /* fake ibuf, will be filled in compositor */ + ibuf = IMB_allocImBuf(256, 256, 32, IB_rect); + image_assign_ibuf(ima, ibuf, 0, frame); } } } } - - BLI_unlock_thread(LOCK_IMAGE); } BKE_image_tag_time(ima); @@ -2886,23 +2881,79 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) return ibuf; } -void BKE_image_release_ibuf(Image *ima, void *lock) +/* return image buffer for given image and user + * + * - will lock render result if image type is render result and lock is not NULL + * - will return NULL if image type if render or composite result and lock is NULL + * + * references the result, BKE_image_release_ibuf should be used to de-reference + */ +ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) { - /* for getting image during threaded render / compositing, need to release */ - if (lock == ima) { - BLI_unlock_thread(LOCK_VIEWER); /* viewer image */ + ImBuf *ibuf; + + BLI_spin_lock(&image_spin); + + ibuf = image_acquire_ibuf(ima, iuser, lock_r); + + if (ibuf) + IMB_refImBuf(ibuf); + + BLI_spin_unlock(&image_spin); + + return ibuf; +} + +void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock) +{ + if (lock) { + /* for getting image during threaded render / compositing, need to release */ + if (lock == ima) { + BLI_unlock_thread(LOCK_VIEWER); /* viewer image */ + } + else if (lock) { + RE_ReleaseResultImage(lock); /* render result */ + BLI_unlock_thread(LOCK_VIEWER); /* view image imbuf */ + } } - else if (lock) { - RE_ReleaseResultImage(lock); /* render result */ - BLI_unlock_thread(LOCK_VIEWER); /* view image imbuf */ + + if (ibuf) { + BLI_spin_lock(&image_spin); + IMB_freeImBuf(ibuf); + BLI_spin_unlock(&image_spin); } } -/* warning, this can allocate generated images */ -ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) +/* checks whether there's an image buffer for given image and user */ +int BKE_image_has_ibuf(Image *ima, ImageUser *iuser) { - /* here (+fie_ima/2-1) makes sure that division happens correctly */ - return BKE_image_acquire_ibuf(ima, iuser, NULL); + ImBuf *ibuf; + + /* quick reject tests */ + if (ima == NULL) + return FALSE; + + if (iuser) { + if (iuser->ok == 0) + return FALSE; + } + else if (ima->ok == 0) + return FALSE; + + ibuf = image_get_ibuf_threadsafe(ima, iuser, NULL, NULL); + + if (!ibuf) { + BLI_spin_lock(&image_spin); + + ibuf = image_get_ibuf_threadsafe(ima, iuser, NULL, NULL); + + if (!ibuf) + ibuf = image_acquire_ibuf(ima, iuser, NULL); + + BLI_spin_unlock(&image_spin); + } + + return ibuf != NULL; } int BKE_image_user_frame_get(const ImageUser *iuser, int cfra, int fieldnr, short *r_is_in_range) @@ -3020,7 +3071,7 @@ int BKE_image_has_alpha(struct Image *image) ibuf = BKE_image_acquire_ibuf(image, NULL, &lock); planes = (ibuf ? ibuf->planes : 0); - BKE_image_release_ibuf(image, lock); + BKE_image_release_ibuf(image, ibuf, lock); if (planes == 32) return 1; @@ -3044,7 +3095,7 @@ void BKE_image_get_size(Image *image, ImageUser *iuser, int *width, int *height) *height = IMG_SIZE_FALLBACK; } - BKE_image_release_ibuf(image, lock); + BKE_image_release_ibuf(image, ibuf, lock); } void BKE_image_get_size_fl(Image *image, ImageUser *iuser, float size[2]) diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index 4782d09a7c8..2f37db846f3 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -33,9 +33,12 @@ #include "MEM_guardedalloc.h" +#include "DNA_anim_types.h" #include "DNA_lamp_types.h" #include "DNA_material_types.h" +#include "DNA_node_types.h" #include "DNA_object_types.h" +#include "DNA_scene_types.h" #include "DNA_texture_types.h" #include "BLI_listbase.h" @@ -73,7 +76,7 @@ Lamp *BKE_lamp_add(const char *name) la->soft = 3.0f; la->compressthresh = 0.05f; la->ray_samp = la->ray_sampy = la->ray_sampz = 1; - la->area_size = la->area_sizey = la->area_sizez = 1.0f; + la->area_size = la->area_sizey = la->area_sizez = 0.1f; la->buffers = 1; la->buftype = LA_SHADBUF_HALFWAY; la->ray_samp_method = LA_SAMP_HALTON; @@ -232,3 +235,38 @@ void BKE_lamp_free(Lamp *la) la->id.icon_id = 0; } +/* Calculate all drivers for lamps, see material_drivers_update for why this is a bad hack */ + +static void lamp_node_drivers_update(Scene *scene, bNodeTree *ntree, float ctime) +{ + bNode *node; + + /* nodetree itself */ + if (ntree->adt && ntree->adt->drivers.first) + BKE_animsys_evaluate_animdata(scene, &ntree->id, ntree->adt, ctime, ADT_RECALC_DRIVERS); + + /* nodes */ + for (node = ntree->nodes.first; node; node = node->next) + if (node->id && node->type == NODE_GROUP) + lamp_node_drivers_update(scene, (bNodeTree *)node->id, ctime); +} + +void lamp_drivers_update(Scene *scene, Lamp *la, float ctime) +{ + /* Prevent infinite recursion by checking (and tagging the lamp) as having been visited already + * (see BKE_scene_update_tagged()). This assumes la->id.flag & LIB_DOIT isn't set by anything else + * in the meantime... [#32017] */ + if (la->id.flag & LIB_DOIT) + return; + else + la->id.flag |= LIB_DOIT; + + /* lamp itself */ + if (la->adt && la->adt->drivers.first) + BKE_animsys_evaluate_animdata(scene, &la->id, la->adt, ctime, ADT_RECALC_DRIVERS); + + /* nodes */ + if (la->nodetree) + lamp_node_drivers_update(scene, la->nodetree, ctime); +} + diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 942e71b5052..eb0612a75bd 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -998,7 +998,6 @@ void free_main(Main *mainvar) #endif } } - a = set_listbasepointers(mainvar, lbarray); MEM_freeN(mainvar); } @@ -1521,7 +1520,9 @@ void test_idbutton(char *name) /* search for id */ idtest = BLI_findstring(lb, name, offsetof(ID, name) + 2); - if (idtest) if (new_id(lb, idtest, name) == 0) id_sort_by_name(lb, idtest); + if (idtest && (new_id(lb, idtest, name) == 0)) { + id_sort_by_name(lb, idtest); + } } void text_idbutton(struct ID *id, char *text) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index b7f4c4bd61e..bda924060d5 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1416,7 +1416,7 @@ void BKE_mask_layer_evaluate(MaskLayer *masklay, const float ctime, const int do for (spline = masklay->splines.first; spline; spline = spline->next) { int i; - int has_auto = FALSE; + int need_handle_recalc = FALSE; BKE_mask_spline_ensure_deform(spline); @@ -1436,16 +1436,16 @@ void BKE_mask_layer_evaluate(MaskLayer *masklay, const float ctime, const int do add_v2_v2(point_deform->bezt.vec[2], delta); } - if (point->bezt.h1 == HD_AUTO) { - has_auto = TRUE; + if (ELEM(point->bezt.h1, HD_AUTO, HD_VECT)) { + need_handle_recalc = TRUE; } } - /* if the spline has auto handles, these need to be recalculated after deformation */ - if (has_auto) { + /* if the spline has auto or vector handles, these need to be recalculated after deformation */ + if (need_handle_recalc) { for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point_deform = &spline->points_deform[i]; - if (point_deform->bezt.h1 == HD_AUTO) { + if (ELEM(point_deform->bezt.h1, HD_AUTO, HD_VECT)) { BKE_mask_calc_handle_point(spline, point_deform); } } diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c index e67df9c6419..a2f6b3c1929 100644 --- a/source/blender/blenkernel/intern/mask_evaluate.c +++ b/source/blender/blenkernel/intern/mask_evaluate.c @@ -245,7 +245,7 @@ static void feather_bucket_add_edge(FeatherEdgesBucket *bucket, int start, int e } else { bucket->segments = MEM_reallocN(bucket->segments, - (alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments)); + (alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments)); } bucket->alloc_segment += alloc_delta; @@ -289,10 +289,10 @@ static void feather_bucket_check_intersect(float (*feather_points)[2], int tot_f /* collapse loop with smaller AABB */ for (k = 0; k < tot_feather_point; k++) { if (k >= check_b && k <= cur_a) { - DO_MINMAX2(feather_points[k], min_a, max_a); + minmax_v2v2_v2(min_a, max_a, feather_points[k]); } else { - DO_MINMAX2(feather_points[k], min_b, max_b); + minmax_v2v2_v2(min_b, max_b, feather_points[k]); } } @@ -379,7 +379,7 @@ void BKE_mask_spline_feather_collapse_inner_loops(MaskSpline *spline, float (*fe int next = i + 1; float delta; - DO_MINMAX2(feather_points[i], min, max); + minmax_v2v2_v2(min, max, feather_points[i]); if (next == tot_feather_point) { if (spline->flag & MASK_SPLINE_CYCLIC) diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 88393fab79c..2fa928e7c07 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -933,7 +933,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas } /* main scan-fill */ - sf_tri_tot = BLI_scanfill_calc_ex(&sf_ctx, FALSE, zvec); + sf_tri_tot = BLI_scanfill_calc_ex(&sf_ctx, 0, zvec); face_array = MEM_mallocN(sizeof(*face_array) * (sf_tri_tot + tot_feather_quads), "maskrast_face_index"); face_index = 0; diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 6d44473583f..036f8f5e673 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -2388,7 +2388,7 @@ void create_vert_poly_map(MeshElemMap **map, int **mem, * of edges that use that vertex as an endpoint. The lists are allocated * from one memory pool. */ void create_vert_edge_map(MeshElemMap **map, int **mem, - const MEdge *medge, int totvert, int totedge) + const MEdge *medge, int totvert, int totedge) { int i, *indices; @@ -2607,7 +2607,7 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, } BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert_first); - totfilltri = BLI_scanfill_calc(&sf_ctx, FALSE); + totfilltri = BLI_scanfill_calc(&sf_ctx, 0); if (totfilltri) { BLI_array_grow_items(mface_to_poly_map, totfilltri); BLI_array_grow_items(mface, totfilltri); @@ -3011,7 +3011,7 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart, MLoop *l_iter = loopstart; float area, polynorm_local[3], (*vertexcos)[3]; const float *no = polynormal ? polynormal : polynorm_local; - BLI_array_fixedstack_declare(vertexcos, BM_NGON_STACK_SIZE, mpoly->totloop, __func__); + BLI_array_fixedstack_declare(vertexcos, BM_DEFAULT_NGON_STACK_SIZE, mpoly->totloop, __func__); /* pack vertex cos into an array for area_poly_v3 */ for (i = 0; i < mpoly->totloop; i++, l_iter++) { diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 9c7cbc42bdd..25b70ce1793 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -249,13 +249,13 @@ int modifier_couldBeCage(struct Scene *scene, ModifierData *md) modifier_supportsMapping(md)); } -int modifier_sameTopology(ModifierData *md) +int modifier_isSameTopology(ModifierData *md) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); return ELEM(mti->type, eModifierTypeType_OnlyDeform, eModifierTypeType_NonGeometrical); } -int modifier_nonGeometrical(ModifierData *md) +int modifier_isNonGeometrical(ModifierData *md) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); return (mti->type == eModifierTypeType_NonGeometrical); diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c index 98eac9b95af..381e4350391 100644 --- a/source/blender/blenkernel/intern/modifiers_bmesh.c +++ b/source/blender/blenkernel/intern/modifiers_bmesh.c @@ -79,7 +79,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) /*do verts*/ mv = mvert = dm->dupVertArray(dm); for (i = 0; i < totvert; i++, mv++) { - v = BM_vert_create(bm, mv->co, NULL); + v = BM_vert_create(bm, mv->co, NULL, BM_CREATE_SKIP_CD); normal_short_to_float_v3(v->no, mv->no); v->head.hflag = BM_vert_flag_from_mflag(mv->flag); BM_elem_index_set(v, i); /* set_inline */ @@ -97,7 +97,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) me = medge = dm->dupEdgeArray(dm); for (i = 0; i < totedge; i++, me++) { //BLI_assert(BM_edge_exists(vtable[me->v1], vtable[me->v2]) == NULL); - e = BM_edge_create(bm, vtable[me->v1], vtable[me->v2], NULL, FALSE); + e = BM_edge_create(bm, vtable[me->v1], vtable[me->v2], NULL, BM_CREATE_SKIP_CD); e->head.hflag = BM_edge_flag_from_mflag(me->flag); BM_elem_index_set(e, i); /* set_inline */ @@ -134,7 +134,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm) edges[j] = etable[ml->e]; } - f = BM_face_create_ngon(bm, verts[0], verts[1], edges, mp->totloop, FALSE); + f = BM_face_create_ngon(bm, verts[0], verts[1], edges, mp->totloop, BM_CREATE_SKIP_CD); if (UNLIKELY(f == NULL)) { continue; diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 6e8f2697ee1..4156b5b4367 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1176,13 +1176,16 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, &undist_marker, TRUE, TRUE); - if (!search_ibuf->rect_float) { - /* sampling happens in float buffer */ - IMB_float_from_rect(search_ibuf); + if (search_ibuf) { + if (!search_ibuf->rect_float) { + /* sampling happens in float buffer */ + IMB_float_from_rect(search_ibuf); + } + + scopes->track_search = search_ibuf; } scopes->undist_marker = undist_marker; - scopes->track_search = search_ibuf; scopes->frame_width = ibuf->x; scopes->frame_height = ibuf->y; diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 66f2ff12258..c737dccc5d2 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -984,7 +984,7 @@ static void grid_tangent(const CCGKey *key, int x, int y, int axis, CCGElem *gri /* Construct 3x3 tangent-space matrix in 'mat' */ static void grid_tangent_matrix(float mat[3][3], const CCGKey *key, - int x, int y, CCGElem *grid) + int x, int y, CCGElem *grid) { grid_tangent(key, x, y, 0, grid, mat[0]); normalize_v3(mat[0]); diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 153eb5271c5..17dcf34b71f 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -38,9 +38,13 @@ #include "DNA_action_types.h" #include "DNA_anim_types.h" +#include "DNA_lamp_types.h" +#include "DNA_material_types.h" #include "DNA_node_types.h" #include "DNA_node_types.h" #include "DNA_scene_types.h" +#include "DNA_texture_types.h" +#include "DNA_world_types.h" #include "BLI_string.h" #include "BLI_math.h" @@ -406,13 +410,14 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node) /* only shader nodes get pleasant preview updating this way, compo uses own system */ if (node->preview) { - if (ntree->type == NTREE_SHADER) { + if (ntree && (ntree->type == NTREE_SHADER)) { nnode->preview = MEM_dupallocN(node->preview); if (node->preview->rect) nnode->preview->rect = MEM_dupallocN(node->preview->rect); } - else + else { nnode->preview = NULL; + } } if (ntree) @@ -1153,6 +1158,18 @@ void ntreeSetOutput(bNodeTree *ntree) * might be different for editor or for "real" use... */ } +bNodeTree *ntreeFromID(ID *id) +{ + switch (GS(id->name)) { + case ID_MA: return ((Material*)id)->nodetree; + case ID_LA: return ((Lamp*)id)->nodetree; + case ID_WO: return ((World*)id)->nodetree; + case ID_TE: return ((Tex*)id)->nodetree; + case ID_SCE: return ((Scene*)id)->nodetree; + default: return NULL; + } +} + typedef struct MakeLocalCallData { ID *group_id; ID *new_id; @@ -2153,8 +2170,6 @@ static void registerCompositNodes(bNodeTreeType *ttype) register_node_type_reroute(ttype); register_node_type_cmp_group(ttype); -// register_node_type_cmp_forloop(ttype); -// register_node_type_cmp_whileloop(ttype); register_node_type_cmp_rlayers(ttype); register_node_type_cmp_image(ttype); @@ -2184,6 +2199,7 @@ static void registerCompositNodes(bNodeTreeType *ttype) register_node_type_cmp_normal(ttype); register_node_type_cmp_curve_vec(ttype); register_node_type_cmp_map_value(ttype); + register_node_type_cmp_map_range(ttype); register_node_type_cmp_normalize(ttype); register_node_type_cmp_filter(ttype); @@ -2254,8 +2270,6 @@ static void registerShaderNodes(bNodeTreeType *ttype) register_node_type_reroute(ttype); register_node_type_sh_group(ttype); - //register_node_type_sh_forloop(ttype); - //register_node_type_sh_whileloop(ttype); register_node_type_sh_output(ttype); register_node_type_sh_material(ttype); @@ -2293,17 +2307,21 @@ static void registerShaderNodes(bNodeTreeType *ttype) register_node_type_sh_particle_info(ttype); register_node_type_sh_bump(ttype); register_node_type_sh_script(ttype); + register_node_type_sh_tangent(ttype); + register_node_type_sh_normal_map(ttype); register_node_type_sh_background(ttype); register_node_type_sh_bsdf_anisotropic(ttype); register_node_type_sh_bsdf_diffuse(ttype); register_node_type_sh_bsdf_glossy(ttype); register_node_type_sh_bsdf_glass(ttype); + register_node_type_sh_bsdf_refraction(ttype); register_node_type_sh_bsdf_translucent(ttype); register_node_type_sh_bsdf_transparent(ttype); register_node_type_sh_bsdf_velvet(ttype); register_node_type_sh_emission(ttype); register_node_type_sh_holdout(ttype); + register_node_type_sh_ambient_occlusion(ttype); //register_node_type_sh_volume_transparent(ttype); //register_node_type_sh_volume_isotropic(ttype); register_node_type_sh_mix_shader(ttype); @@ -2332,8 +2350,6 @@ static void registerTextureNodes(bNodeTreeType *ttype) register_node_type_reroute(ttype); register_node_type_tex_group(ttype); -// register_node_type_tex_forloop(ttype); -// register_node_type_tex_whileloop(ttype); register_node_type_tex_math(ttype); register_node_type_tex_mix_rgb(ttype); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 0611e84bdf3..47ca502d247 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -196,18 +196,18 @@ int BKE_object_support_modifier_type_check(Object *ob, int modifier_type) return TRUE; } -void BKE_object_link_modifiers(struct Object *ob, struct Object *from) +void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src) { ModifierData *md; - BKE_object_free_modifiers(ob); + BKE_object_free_modifiers(ob_dst); - if (!ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { + if (!ELEM5(ob_dst->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { /* only objects listed above can have modifiers and linking them to objects * which doesn't have modifiers stack is quite silly */ return; } - for (md = from->modifiers.first; md; md = md->next) { + for (md = ob_src->modifiers.first; md; md = md->next) { ModifierData *nmd = NULL; if (ELEM4(md->type, @@ -219,16 +219,18 @@ void BKE_object_link_modifiers(struct Object *ob, struct Object *from) continue; } - if (!BKE_object_support_modifier_type_check(ob, md->type)) + if (!BKE_object_support_modifier_type_check(ob_dst, md->type)) continue; nmd = modifier_new(md->type); + BLI_strncpy(nmd->name, md->name, sizeof(nmd->name)); modifier_copyData(md, nmd); - BLI_addtail(&ob->modifiers, nmd); + BLI_addtail(&ob_dst->modifiers, nmd); + modifier_unique_name(&ob_dst->modifiers, nmd); } - BKE_object_copy_particlesystems(ob, from); - BKE_object_copy_softbody(ob, from); + BKE_object_copy_particlesystems(ob_dst, ob_src); + BKE_object_copy_softbody(ob_dst, ob_src); /* TODO: smoke?, cloth? */ } @@ -2654,6 +2656,8 @@ void BKE_object_handle_update(Scene *scene, Object *ob) } } } + else if (ob->type == OB_LAMP) + lamp_drivers_update(scene, ob->data, ctime); /* particles */ if (ob->particlesystem.first) { diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 7bc736d394e..e694a7e7eb3 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -183,7 +183,7 @@ MINLINE float catrom(float p0, float p1, float p2, float p3, float f) MINLINE float omega(float k, float depth) { - return sqrt(GRAVITY * k * tanh(k * depth)); + return sqrtf(GRAVITY * k * tanhf(k * depth)); } // modified Phillips spectrum @@ -256,8 +256,8 @@ static void add_comlex_c(fftw_complex res, fftw_complex cmpl1, fftw_complex cmpl static void mul_complex_f(fftw_complex res, fftw_complex cmpl, float f) { - res[0] = cmpl[0] * f; - res[1] = cmpl[1] * f; + res[0] = cmpl[0] * (double)f; + res[1] = cmpl[1] * (double)f; } static void mul_complex_c(fftw_complex res, fftw_complex cmpl1, fftw_complex cmpl2) @@ -289,8 +289,8 @@ static void exp_complex(fftw_complex res, fftw_complex cmpl) { float r = expf(cmpl[0]); - res[0] = cos(cmpl[1]) * r; - res[1] = sin(cmpl[1]) * r; + res[0] = cosf(cmpl[1]) * r; + res[1] = sinf(cmpl[1]) * r; } float BKE_ocean_jminus_to_foam(float jminus, float coverage) @@ -462,7 +462,7 @@ void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j) i = abs(i) % oc->_M; j = abs(j) % oc->_N; - ocr->disp[1] = oc->_do_disp_y ? oc->_disp_y[i * oc->_N + j] : 0.0f; + ocr->disp[1] = oc->_do_disp_y ? (float)oc->_disp_y[i * oc->_N + j] : 0.0f; if (oc->_do_chop) { ocr->disp[0] = oc->_disp_x[i * oc->_N + j]; @@ -546,7 +546,7 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, minus_i); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); - mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0 ? 0.0 : o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j])); + mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_x[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } @@ -568,7 +568,7 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, minus_i); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); - mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0 ? 0.0 : o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); + mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_z[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } @@ -589,7 +589,7 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); - mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0 ? 0.0 : o->_kx[i] * o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j])); + mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kx[i] * o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_jxx[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } @@ -616,7 +616,7 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); - mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0 ? 0.0 : o->_kz[j] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); + mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kz[j] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_jzz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index d645204d29c..5f5a713064d 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -822,8 +822,8 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } facearea = MEM_callocN(sizeof(float) * totorigface, "SimplifyFaceArea"); @@ -1645,8 +1645,8 @@ int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, const f /* double lookup */ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } mpoly = dm->getPolyArray(dm); @@ -3786,14 +3786,22 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, co return 1; } -#define SET_PARTICLE_TEXTURE(type, pvalue, texfac) \ - if ((event & mtex->mapto) & type) { pvalue = texture_value_blend(def, pvalue, value, texfac, blend); } (void)0 +#define SET_PARTICLE_TEXTURE(type, pvalue, texfac) \ + if ((event & mtex->mapto) & type) { \ + pvalue = texture_value_blend(def, pvalue, value, texfac, blend); \ + } (void)0 -#define CLAMP_PARTICLE_TEXTURE_POS(type, pvalue) \ - if (event & type) { if (pvalue < 0.0f) pvalue = 1.0f + pvalue; CLAMP(pvalue, 0.0f, 1.0f); } (void)0 +#define CLAMP_PARTICLE_TEXTURE_POS(type, pvalue) \ + if (event & type) { \ + if (pvalue < 0.0f) \ + pvalue = 1.0f + pvalue; \ + CLAMP(pvalue, 0.0f, 1.0f); \ + } (void)0 -#define CLAMP_PARTICLE_TEXTURE_POSNEG(type, pvalue) \ - if (event & type) { CLAMP(pvalue, -1.0f, 1.0f); } (void)0 +#define CLAMP_PARTICLE_TEXTURE_POSNEG(type, pvalue) \ + if (event & type) { \ + CLAMP(pvalue, -1.0f, 1.0f); \ + } (void)0 static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSettings *part, ParticleData *par, int child_index, int face_index, const float fw[4], float *orco, ParticleTexture *ptex, int event, float cfra) { @@ -3802,8 +3810,8 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti float value, rgba[4], texvec[3]; ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp = - ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink = - ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.f; + ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink = + ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.0f; ptex->length = 1.0f - part->randlength * PSYS_FRAND(child_index + 26); ptex->length *= part->clength_thres < PSYS_FRAND(child_index + 27) ? part->clength : 1.0f; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 2b95946f571..90889d7c09e 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -367,11 +367,12 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys) nodedmelem= MEM_callocN(sizeof(LinkNode)*totdmelem, "psys node elems"); nodearray= MEM_callocN(sizeof(LinkNode *)*totelem, "psys node array"); - for (i=0, node=nodedmelem; ilink = SET_INT_IN_POINTER(i); - origindex_final = *origindex; + /* may be vertex or face origindex */ + origindex_final = origindex ? origindex[i] : ORIGINDEX_NONE; /* if we have a poly source, do an index lookup */ if (origindex_poly && origindex_final != ORIGINDEX_NONE) { @@ -466,13 +467,7 @@ static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys) mv++; for (i=1; ico[0]); - min[1]=MIN2(min[1],mv->co[1]); - min[2]=MIN2(min[2],mv->co[2]); - - max[0]=MAX2(max[0],mv->co[0]); - max[1]=MAX2(max[1],mv->co[1]); - max[2]=MAX2(max[2],mv->co[2]); + minmax_v3v3_v3(min, max, mv->co); } sub_v3_v3v3(delta, max, min); @@ -2145,16 +2140,22 @@ static void psys_update_effectors(ParticleSimulationData *sim) precalc_guides(sim, sim->psys->effectors); } -static void integrate_particle(ParticleSettings *part, ParticleData *pa, float dtime, float *external_acceleration, void (*force_func)(void *forcedata, ParticleKey *state, float *force, float *impulse), void *forcedata) +static void integrate_particle(ParticleSettings *part, ParticleData *pa, float dtime, float *external_acceleration, + void (*force_func)(void *forcedata, ParticleKey *state, float *force, float *impulse), + void *forcedata) { +#define ZERO_F43 {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}} + ParticleKey states[5]; - float force[3],acceleration[3],impulse[3],dx[4][3],dv[4][3],oldpos[3]; + float force[3], acceleration[3], impulse[3], dx[4][3] = ZERO_F43, dv[4][3] = ZERO_F43, oldpos[3]; float pa_mass= (part->flag & PART_SIZEMASS ? part->mass * pa->size : part->mass); int i, steps=1; int integrator = part->integrator; +#undef ZERO_F43 + copy_v3_v3(oldpos, pa->state.co); - + /* Verlet integration behaves strangely with moving emitters, so do first step with euler. */ if (pa->prev_state.time < 0.f && integrator == PART_INT_VERLET) integrator = PART_INT_EULER; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index f195b3d71b0..965a1e2b4a6 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -686,7 +686,7 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v) /* reallocate fluid if needed*/ if (reallocate) { - sds->active_fields = active_fields; + sds->active_fields = active_fields | cache_fields; smoke_reallocate_fluid(sds, ch_dx, ch_res, 1); sds->dx = ch_dx; VECCOPY(sds->res, ch_res); @@ -755,6 +755,7 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v) if (cache_fields & SM_ACTIVE_FIRE) { ptcache_file_compressed_read(pf, (unsigned char *)flame, out_len_big); ptcache_file_compressed_read(pf, (unsigned char *)fuel, out_len_big); + ptcache_file_compressed_read(pf, (unsigned char *)react, out_len_big); } if (cache_fields & SM_ACTIVE_COLORS) { ptcache_file_compressed_read(pf, (unsigned char *)r, out_len_big); @@ -2568,10 +2569,12 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) sbFreeSimulation(pid->calldata); else if (pid->type == PTCACHE_TYPE_PARTICLES) psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH); - /*else if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) +#if 0 + else if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) smokeModifier_reset(pid->calldata); else if (pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) - smokeModifier_reset_turbulence(pid->calldata);*/ + smokeModifier_reset_turbulence(pid->calldata); +#endif else if (pid->type == PTCACHE_TYPE_DYNAMICPAINT) dynamicPaint_clearSurface((DynamicPaintSurface*)pid->calldata); } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index a1918b77a1e..9bb2fb2de52 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -58,8 +58,10 @@ #include "BKE_anim.h" #include "BKE_animsys.h" +#include "BKE_action.h" #include "BKE_colortools.h" #include "BKE_depsgraph.h" +#include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_group.h" #include "BKE_idprop.h" @@ -115,6 +117,24 @@ void free_qtcodecdata(QuicktimeCodecData *qcd) } } +static void remove_sequencer_fcurves(Scene *sce) +{ + AnimData *adt = BKE_animdata_from_id(&sce->id); + + if (adt && adt->action) { + FCurve *fcu, *nextfcu; + + for (fcu = adt->action->curves.first; fcu; fcu = nextfcu) { + nextfcu = fcu->next; + + if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) { + action_groups_remove_channel(adt->action, fcu); + free_fcurve(fcu); + } + } + } +} + Scene *BKE_scene_copy(Scene *sce, int type) { Scene *scen; @@ -179,6 +199,10 @@ Scene *BKE_scene_copy(Scene *sce, int type) BLI_strncpy(scen->sequencer_colorspace_settings.name, sce->sequencer_colorspace_settings.name, sizeof(scen->sequencer_colorspace_settings.name)); + + /* remove animation used by sequencer */ + if (type != SCE_COPY_FULL) + remove_sequencer_fcurves(scen); } /* tool settings */ @@ -377,6 +401,7 @@ Scene *BKE_scene_add(const char *name) sce->r.im_format.planes = R_IMF_PLANES_RGB; sce->r.im_format.imtype = R_IMF_IMTYPE_PNG; sce->r.im_format.quality = 90; + sce->r.im_format.compress = 90; sce->r.displaymode = R_OUTPUT_AREA; sce->r.framapto = 100; @@ -1019,8 +1044,10 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP)) group_handle_recalc_and_update(scene_parent, ob, ob->dup_group); - /* always update layer, so that animating layers works */ - base->lay = ob->lay; + /* always update layer, so that animating layers works (joshua july 2010) */ + /* XXX commented out, this has depsgraph issues anyway - and this breaks setting scenes + * (on scene-set, the base-lay is copied to ob-lay (ton nov 2012) */ + // base->lay = ob->lay; } /* scene drivers... */ @@ -1048,6 +1075,7 @@ void BKE_scene_update_tagged(Main *bmain, Scene *scene) * when trying to find materials with drivers that need evaluating [#32017] */ tag_main_idcode(bmain, ID_MA, FALSE); + tag_main_idcode(bmain, ID_LA, FALSE); /* update all objects: drivers, matrices, displists, etc. flags set * by depgraph or manual, no layer check here, gets correct flushed @@ -1117,6 +1145,7 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay) * when trying to find materials with drivers that need evaluating [#32017] */ tag_main_idcode(bmain, ID_MA, FALSE); + tag_main_idcode(bmain, ID_LA, FALSE); /* BKE_object_handle_update() on all objects, groups and sets */ scene_update_tagged_recursive(bmain, sce, sce); diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 469881020c1..0b7fdaa7c1d 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -139,6 +139,9 @@ static ImBuf *prepare_effect_imbufs(SeqRenderData context, ImBuf *ibuf1, ImBuf * IMB_rect_from_float(ibuf3); } + if (out->rect_float) + IMB_colormanagement_assign_float_colorspace(out, context.scene->sequencer_colorspace_settings.name); + return out; } diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c index b0dcad64722..5b2e9f2bf23 100644 --- a/source/blender/blenkernel/intern/seqmodifier.c +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -349,9 +349,9 @@ static void hue_correct_apply_threaded(int width, int height, unsigned char *rec hsv_to_rgb(hsv[0], hsv[1], hsv[2], result, result + 1, result + 2); if (mask_rect_float) - copy_v3_v3(mask, mask_rect_float + pixel_index); + copy_v3_v3(mask, mask_rect_float + pixel_index); else if (mask_rect) - rgb_uchar_to_float(mask, mask_rect + pixel_index); + rgb_uchar_to_float(mask, mask_rect + pixel_index); result[0] = pixel[0] * (1.0f - mask[0]) + result[0] * mask[0]; result[1] = pixel[1] * (1.0f - mask[1]) + result[1] * mask[1]; @@ -427,17 +427,17 @@ static void brightcontrast_apply_threaded(int width, int height, unsigned char * unsigned char *pixel = rect + pixel_index; for (c = 0; c < 3; c++) { - i = pixel[c]; + i = (float) pixel[c] / 255.0f; v = a * i + b; if (mask_rect) { unsigned char *m = mask_rect + pixel_index; float t = (float) m[c] / 255.0f; - pixel[c] = pixel[c] * (1.0f - t) + v * t; + v = (float) pixel[c] * (1.0f - t) + v * t; } - else - pixel[c] = v; + + pixel[c] = FTOCHAR(v); } } else if (rect_float) { diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index af0cab98fe0..acce3740c98 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1835,6 +1835,8 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, StripCrop c = {0}; StripTransform t = {0}; int sx, sy, dx, dy; + double xscale = 1.0; + double yscale = 1.0; if (is_proxy_image) { double f = seq_rendersize_to_scale_factor(context.preview_render_size); @@ -1851,6 +1853,17 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, t = *seq->strip->transform; } + xscale = context.scene->r.xsch ? ((double)context.rectx / (double)context.scene->r.xsch) : 1.0; + yscale = context.scene->r.ysch ? ((double)context.recty / (double)context.scene->r.ysch) : 1.0; + + xscale /= (double)context.rectx / (double)ibuf->x; + yscale /= (double)context.recty / (double)ibuf->y; + + c.left *= xscale; c.right *= xscale; + c.top *= yscale; c.bottom *= yscale; + + t.xofs *= xscale; t.yofs *= yscale; + sx = ibuf->x - c.left - c.right; sy = ibuf->y - c.top - c.bottom; dx = sx; @@ -2338,12 +2351,15 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float */ const short is_rendering = G.is_rendering; + const short is_background = G.background; const int do_seq_gl = G.is_rendering ? 0 /* (context.scene->r.seq_flag & R_SEQ_GL_REND) */ : (context.scene->r.seq_flag & R_SEQ_GL_PREV); int do_seq; - int have_seq = FALSE; + // int have_seq = FALSE; /* UNUSED */ + int have_comp = FALSE; Scene *scene; + int is_thread_main = BLI_thread_is_main(); /* don't refer to seq->scene above this point!, it can be NULL */ if (seq->scene == NULL) { @@ -2353,7 +2369,8 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float scene = seq->scene; frame = scene->r.sfra + nr + seq->anim_startofs; - have_seq = (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first; + // have_seq = (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first; /* UNUSED */ + have_comp = (scene->r.scemode & R_DOCOMP) && scene->use_nodes && scene->nodetree; oldcfra = scene->r.cfra; scene->r.cfra = frame; @@ -2366,14 +2383,14 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float camera = scene->camera; } - if (have_seq == FALSE && camera == NULL) { + if (have_comp == FALSE && camera == NULL) { scene->r.cfra = oldcfra; return NULL; } /* prevent eternal loop */ do_seq = context.scene->r.scemode & R_DOSEQ; - context.scene->r.scemode &= ~R_DOSEQ; + scene->r.scemode &= ~R_DOSEQ; #ifdef DURIAN_CAMERA_SWITCH /* stooping to new low's in hackyness :( */ @@ -2383,10 +2400,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float (void)oldmarkers; #endif - if ((sequencer_view3d_cb && do_seq_gl && camera) && - (BLI_thread_is_main() == TRUE) && - ((have_seq == FALSE) || (scene == context.scene))) - { + if ((sequencer_view3d_cb && do_seq_gl && camera) && is_thread_main) { char err_out[256] = "unknown"; /* for old scened this can be uninitialized, * should probably be added to do_versions at some point if the functionality stays */ @@ -2405,11 +2419,19 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float Render *re = RE_GetRender(scene->id.name); RenderResult rres; - /* XXX: this if can be removed when sequence preview rendering uses the job system */ - if (is_rendering || context.scene != scene) { + /* XXX: this if can be removed when sequence preview rendering uses the job system + * + * disable rendered preview for sequencer while rendering -- it's very much possible + * that preview render will went into conflict with final render + * + * When rendering from command line renderer is called from main thread, in this + * case it's always safe to render scene here + */ + if (!is_thread_main || is_rendering == FALSE || is_background) { if (re == NULL) re = RE_NewRender(scene->id.name); + BKE_scene_update_for_newframe(context.bmain, scene, scene->lay); RE_BlenderFrame(re, context.bmain, scene, NULL, camera, scene->lay, frame, FALSE); /* restore previous state after it was toggled on & off by RE_BlenderFrame */ @@ -2440,7 +2462,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float } /* restore */ - context.scene->r.scemode |= do_seq; + scene->r.scemode |= do_seq; scene->r.cfra = oldcfra; diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 96faec389df..72db34d339c 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -56,33 +56,16 @@ #include "BKE_mesh.h" #include "BKE_tessmesh.h" +/* for timing... */ +#if 0 +# include "PIL_time.h" +#else +# define TIMEIT_BENCH(expr, id) (expr) +#endif + /* Util macros */ #define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n")) -/* Benchmark macros */ -#if !defined(_WIN32) && 0 - -#include - -#define BENCH(a) \ - do { \ - double _t1, _t2; \ - struct timeval _tstart, _tend; \ - clock_t _clock_init = clock(); \ - gettimeofday ( &_tstart, NULL); \ - (a); \ - gettimeofday ( &_tend, NULL); \ - _t1 = ( double ) _tstart.tv_sec + ( double ) _tstart.tv_usec/ ( 1000*1000 ); \ - _t2 = ( double ) _tend.tv_sec + ( double ) _tend.tv_usec/ ( 1000*1000 ); \ - printf("%s: %fs (real) %fs (cpu)\n", #a, _t2-_t1, (float)(clock()-_clock_init)/CLOCKS_PER_SEC);\ - } while (0) - -#else - -#define BENCH(a) (a) - -#endif - /* get derived mesh */ /* TODO is anyfunction that does this? returning the derivedFinal without we caring if its in edit mode or not? */ DerivedMesh *object_get_derived_final(Object *ob) @@ -143,7 +126,7 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) BVHTreeNearest nearest = NULL_BVHTreeNearest; - BENCH(bvhtree_from_mesh_verts(&treeData, calc->target, 0.0, 2, 6)); + TIMEIT_BENCH(bvhtree_from_mesh_verts(&treeData, calc->target, 0.0, 2, 6), bvhtree_verts); if (treeData.tree == NULL) { OUT_OF_MEMORY(); return; @@ -294,6 +277,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) /* Options about projection direction */ const char use_normal = calc->smd->shrinkOpts; + const float proj_limit_squared = calc->smd->projLimit * calc->smd->projLimit; float proj_axis[3] = {0.0f, 0.0f, 0.0f}; /* Raycast and tree stuff */ @@ -410,6 +394,13 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) treeData.raycast_callback, &treeData); } + /* don't set the initial dist (which is more efficient), + * because its calculated in the targets space, we want the dist in our own space */ + if (proj_limit_squared != 0.0f) { + if (len_squared_v3v3(hit.co, co) > proj_limit_squared) { + hit.index = -1; + } + } if (hit.index != -1) { madd_v3_v3v3fl(hit.co, hit.co, tmp_no, calc->keepDist); @@ -437,7 +428,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) BVHTreeNearest nearest = NULL_BVHTreeNearest; /* Create a bvh-tree of the given target */ - BENCH(bvhtree_from_mesh_faces(&treeData, calc->target, 0.0, 2, 6)); + TIMEIT_BENCH(bvhtree_from_mesh_faces(&treeData, calc->target, 0.0, 2, 6), bvhtree_faces); if (treeData.tree == NULL) { OUT_OF_MEMORY(); return; @@ -584,15 +575,15 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM if (calc.target) { switch (smd->shrinkType) { case MOD_SHRINKWRAP_NEAREST_SURFACE: - BENCH(shrinkwrap_calc_nearest_surface_point(&calc)); + TIMEIT_BENCH(shrinkwrap_calc_nearest_surface_point(&calc), deform_surface); break; case MOD_SHRINKWRAP_PROJECT: - BENCH(shrinkwrap_calc_normal_projection(&calc)); + TIMEIT_BENCH(shrinkwrap_calc_normal_projection(&calc), deform_project); break; case MOD_SHRINKWRAP_NEAREST_VERTEX: - BENCH(shrinkwrap_calc_nearest_vertex(&calc)); + TIMEIT_BENCH(shrinkwrap_calc_nearest_vertex(&calc), deform_vertex); break; } } diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 443aed1fc41..53dfbdcfb85 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -165,7 +165,7 @@ void flame_get_spectrum(unsigned char *UNUSED(spec), int UNUSED(width), float UN void smoke_reallocate_fluid(SmokeDomainSettings *sds, float dx, int res[3], int free_old) { int use_heat = (sds->active_fields & SM_ACTIVE_HEAT); - int use_fire = (sds->active_fields & (SM_ACTIVE_HEAT | SM_ACTIVE_FIRE)); + int use_fire = (sds->active_fields & SM_ACTIVE_FIRE); int use_colors = (sds->active_fields & SM_ACTIVE_COLORS); if (free_old && sds->fluid) @@ -262,21 +262,21 @@ static void smoke_set_domain_from_derivedmesh(SmokeDomainSettings *sds, Object * scale = res / size[0]; sds->scale = size[0] / ob->size[0]; sds->base_res[0] = res; - sds->base_res[1] = (int)(size[1] * scale + 0.5); - sds->base_res[2] = (int)(size[2] * scale + 0.5); + sds->base_res[1] = (int)(size[1] * scale + 0.5f); + sds->base_res[2] = (int)(size[2] * scale + 0.5f); } else if (size[1] > MAX2(size[0], size[2])) { scale = res / size[1]; sds->scale = size[1] / ob->size[1]; - sds->base_res[0] = (int)(size[0] * scale + 0.5); + sds->base_res[0] = (int)(size[0] * scale + 0.5f); sds->base_res[1] = res; - sds->base_res[2] = (int)(size[2] * scale + 0.5); + sds->base_res[2] = (int)(size[2] * scale + 0.5f); } else { scale = res / size[2]; sds->scale = size[2] / ob->size[2]; - sds->base_res[0] = (int)(size[0] * scale + 0.5); - sds->base_res[1] = (int)(size[1] * scale + 0.5); + sds->base_res[0] = (int)(size[0] * scale + 0.5f); + sds->base_res[1] = (int)(size[1] * scale + 0.5f); sds->base_res[2] = res; } @@ -1581,7 +1581,7 @@ BLI_INLINE void apply_inflow_fields(SmokeFlowSettings *sfs, float emission_value if (fuel && fuel[index]) { /* instead of using 1.0 for all new fuel add slight falloff * to reduce flow blockiness */ - float value = 1.0f - pow(1.0f - emission_value, 2.0f); + float value = 1.0f - powf(1.0f - emission_value, 2.0f); if (value > react[index]) { float f = fuel_flow / fuel[index]; @@ -1944,9 +1944,9 @@ static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds, mul_v3_fl(retvel, mag); // TODO dg - do in force! - force_x[index] = MIN2(MAX2(-1.0, retvel[0] * 0.2), 1.0); - force_y[index] = MIN2(MAX2(-1.0, retvel[1] * 0.2), 1.0); - force_z[index] = MIN2(MAX2(-1.0, retvel[2] * 0.2), 1.0); + force_x[index] = min_ff(max_ff(-1.0f, retvel[0] * 0.2f), 1.0f); + force_y[index] = min_ff(max_ff(-1.0f, retvel[1] * 0.2f), 1.0f); + force_z[index] = min_ff(max_ff(-1.0f, retvel[2] * 0.2f), 1.0f); } } } @@ -1999,7 +1999,7 @@ static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh * /* adapt timestep for different framerates, dt = 0.1 is at 25fps */ dt = DT_DEFAULT * (25.0f / fps); // maximum timestep/"CFL" constraint: dt < 5.0 *dx / maxVel - maxVel = (sds->dx * 5.0); + maxVel = (sds->dx * 5.0f); #if 0 for (i = 0; i < size; i++) { @@ -2009,7 +2009,7 @@ static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh * } #endif - maxVelMag = sqrt(maxVelMag) * dt * sds->time_scale; + maxVelMag = sqrtf(maxVelMag) * dt * sds->time_scale; totalSubsteps = (int)((maxVelMag / maxVel) + 1.0f); /* always round up */ totalSubsteps = (totalSubsteps < 1) ? 1 : totalSubsteps; totalSubsteps = (totalSubsteps > maxSubSteps) ? maxSubSteps : totalSubsteps; @@ -2267,7 +2267,8 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object * } } -struct DerivedMesh *smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm){ +struct DerivedMesh *smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm) +{ smokeModifier_process(smd, scene, ob, dm); /* return generated geometry for adaptive domain */ @@ -2285,7 +2286,7 @@ static float calc_voxel_transp(float *result, float *input, int res[3], int *pix const size_t index = smoke_get_index(pixel[0], res[0], pixel[1], res[1], pixel[2]); // T_ray *= T_vox - *tRay *= exp(input[index] * correct); + *tRay *= expf(input[index] * correct); if (result[index] < 0.0f) { @@ -2385,7 +2386,7 @@ static void smoke_calc_transparency(SmokeDomainSettings *sds, Scene *scene) float light[3]; int a, z, slabsize = sds->res[0] * sds->res[1], size = sds->res[0] * sds->res[1] * sds->res[2]; float *density = smoke_get_density(sds->fluid); - float correct = -7.0 * sds->dx; + float correct = -7.0f * sds->dx; if (!get_lamp(scene, light)) return; diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index aad205bb5bf..af9d21d8cbc 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -353,17 +353,17 @@ void sound_load(struct Main *bmain, bSound *sound) } // XXX unused currently #if 0 - break; + break; + } + case SOUND_TYPE_BUFFER: + if (sound->child_sound && sound->child_sound->handle) + sound->handle = AUD_bufferSound(sound->child_sound->handle); + break; + case SOUND_TYPE_LIMITER: + if (sound->child_sound && sound->child_sound->handle) + sound->handle = AUD_limitSound(sound->child_sound, sound->start, sound->end); + break; } - case SOUND_TYPE_BUFFER: - if (sound->child_sound && sound->child_sound->handle) - sound->handle = AUD_bufferSound(sound->child_sound->handle); - break; - case SOUND_TYPE_LIMITER: - if (sound->child_sound && sound->child_sound->handle) - sound->handle = AUD_limitSound(sound->child_sound, sound->start, sound->end); - break; -} #endif if (sound->flags & SOUND_FLAGS_MONO) { void *handle = AUD_monoSound(sound->handle); diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 8a669b89907..be8b572417e 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -3025,7 +3025,8 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) * when the ccgdm gets remade, the assumption is that the topology * does not change. */ ccgdm_create_grids(dm); - BLI_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void **)ccgdm->gridFaces); + BLI_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void **)ccgdm->gridFaces, + ccgdm->gridFlagMats, ccgdm->gridHidden); } ccgdm->pbvh = ob->sculpt->pbvh; diff --git a/source/blender/blenkernel/intern/suggestions.c b/source/blender/blenkernel/intern/suggestions.c index 99e33594a3e..ff9774f85af 100644 --- a/source/blender/blenkernel/intern/suggestions.c +++ b/source/blender/blenkernel/intern/suggestions.c @@ -47,6 +47,7 @@ static SuggList suggestions = {NULL, NULL, NULL, NULL, NULL}; static char *documentation = NULL; //static int doc_lines = 0; +/* TODO, replace with BLI_strncasecmp() */ static int txttl_cmp(const char *first, const char *second, int len) { int cmp, i; @@ -113,19 +114,18 @@ short texttool_text_is_active(Text *text) void texttool_suggest_add(const char *name, char type) { + const int len = strlen(name); + int cmp; SuggItem *newitem, *item; - int len, cmp; - newitem = MEM_mallocN(sizeof(SuggItem) + strlen(name) + 1, "SuggestionItem"); + newitem = MEM_mallocN(sizeof(SuggItem) + len + 1, "SuggItem"); if (!newitem) { printf("Failed to allocate memory for suggestion.\n"); return; } newitem->name = (char *) (newitem + 1); - len = strlen(name); - strncpy(newitem->name, name, len); - newitem->name[len] = '\0'; + memcpy(newitem->name, name, len + 1); newitem->type = type; newitem->prev = newitem->next = NULL; diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index d230cf8f1fe..322b77e0462 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -96,17 +96,6 @@ * If the user moves the cursor the st containing that cursor should * be popped ... other st's retain their own top location. * - * Markers - * -- - * The mrk->flags define the behavior and relationships between markers. The - * upper two bytes are used to hold a group ID, the lower two are normal flags. If - * TMARK_EDITALL is set the group ID defines which other markers should be edited. - * - * The mrk->clr field is used to visually group markers where the flags may not - * match. A template system, for example, may allow editing of repeating tokens - * (in one group) but include other marked positions (in another group) all in the - * same template with the same color. - * * Undo * -- * Undo/Redo works by storing @@ -136,8 +125,7 @@ static void txt_pop_first(Text *text); static void txt_pop_last(Text *text); -static void txt_undo_add_op(Text *text, int op); -static void txt_undo_add_block(Text *text, int op, const char *buf); +static void txt_undo_add_blockop(Text *text, int op, const char *buf); static void txt_delete_line(Text *text, TextLine *line); static void txt_delete_sel(Text *text); static void txt_make_dirty(Text *text); @@ -175,7 +163,6 @@ void BKE_text_free(Text *text) } BLI_freelistN(&text->lines); - BLI_freelistN(&text->markers); if (text->name) MEM_freeN(text->name); MEM_freeN(text->undo_buf); @@ -203,7 +190,6 @@ Text *BKE_text_add(const char *name) ta->flags |= TXT_TABSTOSPACES; ta->lines.first = ta->lines.last = NULL; - ta->markers.first = ta->markers.last = NULL; tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line = (char *) MEM_mallocN(1, "textline_string"); @@ -399,7 +385,6 @@ Text *BKE_text_load(const char *file, const char *relpath) ta->id.us = 1; ta->lines.first = ta->lines.last = NULL; - ta->markers.first = ta->markers.last = NULL; ta->curl = ta->sell = NULL; if ((U.flag & USER_TXT_TABSTOSPACES_DISABLE) == 0) @@ -496,7 +481,6 @@ Text *BKE_text_copy(Text *ta) tan->flags = ta->flags | TXT_ISDIRTY; tan->lines.first = tan->lines.last = NULL; - tan->markers.first = tan->markers.last = NULL; tan->curl = tan->sell = NULL; tan->nlines = ta->nlines; @@ -785,23 +769,6 @@ static void txt_curs_sel(Text *text, TextLine ***linep, int **charp) *linep = &text->sell; *charp = &text->selc; } -static void txt_curs_first(Text *text, TextLine **linep, int *charp) -{ - if (text->curl == text->sell) { - *linep = text->curl; - if (text->curc < text->selc) *charp = text->curc; - else *charp = text->selc; - } - else if (txt_get_span(text->lines.first, text->curl) < txt_get_span(text->lines.first, text->sell)) { - *linep = text->curl; - *charp = text->curc; - } - else { - *linep = text->sell; - *charp = text->selc; - } -} - /*****************************/ /* Cursor movement functions */ /*****************************/ @@ -843,13 +810,11 @@ void txt_move_up(Text *text, short sel) { TextLine **linep; int *charp; - /* int old; */ /* UNUSED */ if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - /* old = *charp; */ /* UNUSED */ if ((*linep)->prev) { int index = txt_utf8_offset_to_index((*linep)->line, *charp); @@ -857,8 +822,6 @@ void txt_move_up(Text *text, short sel) if (index > txt_utf8_len((*linep)->line)) *charp = (*linep)->len; else *charp = txt_utf8_index_to_offset((*linep)->line, index); - if (!undoing) - txt_undo_add_op(text, sel ? UNDO_SUP : UNDO_CUP); } else { txt_move_bol(text, sel); @@ -871,22 +834,17 @@ void txt_move_down(Text *text, short sel) { TextLine **linep; int *charp; - /* int old; */ /* UNUSED */ if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - /* old = *charp; */ /* UNUSED */ if ((*linep)->next) { int index = txt_utf8_offset_to_index((*linep)->line, *charp); *linep = (*linep)->next; if (index > txt_utf8_len((*linep)->line)) *charp = (*linep)->len; else *charp = txt_utf8_index_to_offset((*linep)->line, index); - - if (!undoing) - txt_undo_add_op(text, sel ? UNDO_SDOWN : UNDO_CDOWN); } else { txt_move_eol(text, sel); @@ -898,7 +856,7 @@ void txt_move_down(Text *text, short sel) void txt_move_left(Text *text, short sel) { TextLine **linep; - int *charp, oundoing = undoing; + int *charp; int tabsize = 0, i = 0; if (!text) return; @@ -906,8 +864,6 @@ void txt_move_left(Text *text, short sel) else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - undoing = 1; - if (*charp == 0) { if ((*linep)->prev) { txt_move_up(text, sel); @@ -939,24 +895,19 @@ void txt_move_left(Text *text, short sel) } } - undoing = oundoing; - if (!undoing) txt_undo_add_op(text, sel ? UNDO_SLEFT : UNDO_CLEFT); - if (!sel) txt_pop_sel(text); } void txt_move_right(Text *text, short sel) { TextLine **linep; - int *charp, oundoing = undoing, do_tab = FALSE, i; + int *charp, do_tab = FALSE, i; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - undoing = 1; - if (*charp == (*linep)->len) { if ((*linep)->next) { txt_move_down(text, sel); @@ -984,124 +935,103 @@ void txt_move_right(Text *text, short sel) else (*charp) += BLI_str_utf8_size((*linep)->line + *charp); } - undoing = oundoing; - if (!undoing) txt_undo_add_op(text, sel ? UNDO_SRIGHT : UNDO_CRIGHT); - if (!sel) txt_pop_sel(text); } void txt_jump_left(Text *text, short sel) { TextLine **linep; - int *charp, oldc; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - oldc = *charp; BLI_str_cursor_step_utf8((*linep)->line, (*linep)->len, charp, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM); if (!sel) txt_pop_sel(text); - if (!undoing) { - int span = txt_get_span(text->lines.first, *linep); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, span, oldc, span, (unsigned short)*charp); - } } void txt_jump_right(Text *text, short sel) { TextLine **linep; - int *charp, oldc; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - oldc = *charp; BLI_str_cursor_step_utf8((*linep)->line, (*linep)->len, charp, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM); if (!sel) txt_pop_sel(text); - if (!undoing) { - int span = txt_get_span(text->lines.first, *linep); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, span, oldc, span, (unsigned short)*charp); - } } void txt_move_bol(Text *text, short sel) { TextLine **linep; - int *charp, old; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - old = *charp; *charp = 0; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } void txt_move_eol(Text *text, short sel) { TextLine **linep; - int *charp, old; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - old = *charp; - + *charp = (*linep)->len; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } void txt_move_bof(Text *text, short sel) { TextLine **linep; - int *charp, old; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - old = *charp; *linep = text->lines.first; *charp = 0; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } void txt_move_eof(Text *text, short sel) { TextLine **linep; - int *charp, old; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - old = *charp; *linep = text->lines.last; *charp = (*linep)->len; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } void txt_move_toline(Text *text, unsigned int line, short sel) @@ -1112,16 +1042,14 @@ void txt_move_toline(Text *text, unsigned int line, short sel) /* Moves to a certain byte in a line, not a certain utf8-character! */ void txt_move_to(Text *text, unsigned int line, unsigned int ch, short sel) { - TextLine **linep, *oldl; - int *charp, oldc; + TextLine **linep; + int *charp; unsigned int i; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - oldc = *charp; - oldl = *linep; *linep = text->lines.first; for (i = 0; i < line; i++) { @@ -1133,7 +1061,6 @@ void txt_move_to(Text *text, unsigned int line, unsigned int ch, short sel) *charp = ch; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } /****************************/ @@ -1152,8 +1079,6 @@ static void txt_curs_swap(Text *text) tmpc = text->curc; text->curc = text->selc; text->selc = tmpc; - - if (!undoing) txt_undo_add_op(text, UNDO_SWAP); } static void txt_pop_first(Text *text) @@ -1164,12 +1089,6 @@ static void txt_pop_first(Text *text) { txt_curs_swap(text); } - - if (!undoing) txt_undo_add_toop(text, UNDO_STO, - txt_get_span(text->lines.first, text->sell), - text->selc, - txt_get_span(text->lines.first, text->curl), - text->curc); txt_pop_sel(text); } @@ -1181,12 +1100,6 @@ static void txt_pop_last(Text *text) { txt_curs_swap(text); } - - if (!undoing) txt_undo_add_toop(text, UNDO_STO, - txt_get_span(text->lines.first, text->sell), - text->selc, - txt_get_span(text->lines.first, text->curl), - text->curc); txt_pop_sel(text); } @@ -1222,9 +1135,7 @@ int txt_has_sel(Text *text) static void txt_delete_sel(Text *text) { TextLine *tmpl; - TextMarker *mrk; char *buf; - int move, lineno; if (!text) return; if (!text->curl) return; @@ -1236,33 +1147,11 @@ static void txt_delete_sel(Text *text) if (!undoing) { buf = txt_sel_to_buf(text); - txt_undo_add_block(text, UNDO_DBLOCK, buf); + txt_undo_add_blockop(text, UNDO_DBLOCK, buf); MEM_freeN(buf); } buf = MEM_mallocN(text->curc + (text->sell->len - text->selc) + 1, "textline_string"); - - if (text->curl != text->sell) { - txt_clear_marker_region(text, text->curl, text->curc, text->curl->len, 0, 0); - move = txt_get_span(text->curl, text->sell); - } - else { - mrk = txt_find_marker_region(text, text->curl, text->curc, text->selc, 0, 0); - if (mrk && (mrk->start > text->curc || mrk->end < text->selc)) - txt_clear_marker_region(text, text->curl, text->curc, text->selc, 0, 0); - move = 0; - } - - mrk = txt_find_marker_region(text, text->sell, text->selc - 1, text->sell->len, 0, 0); - if (mrk) { - lineno = mrk->lineno; - do { - mrk->lineno -= move; - if (mrk->start > text->curc) mrk->start -= text->selc - text->curc; - mrk->end -= text->selc - text->curc; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } strncpy(buf, text->curl->line, text->curc); strcpy(buf + text->curc, text->sell->line + text->selc); @@ -1491,19 +1380,9 @@ char *txt_sel_to_buf(Text *text) return buf; } -static void txt_shift_markers(Text *text, int lineno, int count) -{ - TextMarker *marker; - - for (marker = text->markers.first; marker; marker = marker->next) - if (marker->lineno >= lineno) { - marker->lineno += count; - } -} - void txt_insert_buf(Text *text, const char *in_buffer) { - int l = 0, u, len, lineno = -1, count = 0; + int l = 0, u, len; size_t i = 0, j; TextLine *add; char *buffer; @@ -1517,7 +1396,7 @@ void txt_insert_buf(Text *text, const char *in_buffer) buffer = BLI_strdupn(in_buffer, len); len += txt_extended_ascii_as_utf8(&buffer); - if (!undoing) txt_undo_add_block(text, UNDO_IBLOCK, buffer); + if (!undoing) txt_undo_add_blockop(text, UNDO_IBLOCK, buffer); u = undoing; undoing = 1; @@ -1530,9 +1409,6 @@ void txt_insert_buf(Text *text, const char *in_buffer) else { undoing = u; MEM_freeN(buffer); return; } i++; - /* Read as many full lines as we can */ - lineno = txt_get_span(text->lines.first, text->curl); - while (i < len) { l = 0; @@ -1544,14 +1420,8 @@ void txt_insert_buf(Text *text, const char *in_buffer) add = txt_new_linen(buffer + (i - l), l); BLI_insertlinkbefore(&text->lines, text->curl, add); i++; - count++; } else { - if (count) { - txt_shift_markers(text, lineno, count); - count = 0; - } - for (j = i - l; j < i && j < len; ) txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &j)); break; @@ -1560,10 +1430,6 @@ void txt_insert_buf(Text *text, const char *in_buffer) MEM_freeN(buffer); - if (count) { - txt_shift_markers(text, lineno, count); - } - undoing = u; } @@ -1599,6 +1465,7 @@ static void dump_buffer(Text *text) while (i++ < text->undo_pos) printf("%d: %d %c\n", i, text->undo_buf[i], text->undo_buf[i]); } +/* Note: this function is outdated and must be updated if needed for future use */ void txt_print_undo(Text *text) { int i = 0; @@ -1615,37 +1482,7 @@ void txt_print_undo(Text *text) while (i <= text->undo_pos) { op = text->undo_buf[i]; - if (op == UNDO_CLEFT) { - ops = "Cursor left"; - } - else if (op == UNDO_CRIGHT) { - ops = "Cursor right"; - } - else if (op == UNDO_CUP) { - ops = "Cursor up"; - } - else if (op == UNDO_CDOWN) { - ops = "Cursor down"; - } - else if (op == UNDO_SLEFT) { - ops = "Selection left"; - } - else if (op == UNDO_SRIGHT) { - ops = "Selection right"; - } - else if (op == UNDO_SUP) { - ops = "Selection up"; - } - else if (op == UNDO_SDOWN) { - ops = "Selection down"; - } - else if (op == UNDO_STO) { - ops = "Selection "; - } - else if (op == UNDO_CTO) { - ops = "Cursor "; - } - else if (op == UNDO_INSERT_1) { + if (op == UNDO_INSERT_1) { ops = "Insert ascii "; } else if (op == UNDO_INSERT_2) { @@ -1681,9 +1518,6 @@ void txt_print_undo(Text *text) else if (op == UNDO_DEL_4) { ops = "Delete unicode "; } - else if (op == UNDO_SWAP) { - ops = "Cursor swap"; - } else if (op == UNDO_DBLOCK) { ops = "Delete text block"; } @@ -1738,29 +1572,6 @@ void txt_print_undo(Text *text) } } } - else if (op == UNDO_STO || op == UNDO_CTO) { - i++; - - charp = text->undo_buf[i]; i++; - charp = charp + (text->undo_buf[i] << 8); i++; - - linep = text->undo_buf[i]; i++; - linep = linep + (text->undo_buf[i] << 8); i++; - linep = linep + (text->undo_buf[i] << 16); i++; - linep = linep + (text->undo_buf[i] << 24); i++; - - printf("to <%d, %d> ", linep, charp); - - charp = text->undo_buf[i]; i++; - charp = charp + (text->undo_buf[i] << 8); i++; - - linep = text->undo_buf[i]; i++; - linep = linep + (text->undo_buf[i] << 8); i++; - linep = linep + (text->undo_buf[i] << 16); i++; - linep = linep + (text->undo_buf[i] << 24); i++; - - printf("from <%d, %d>", linep, charp); - } else if (op == UNDO_DBLOCK || op == UNDO_IBLOCK) { i++; @@ -1811,16 +1622,6 @@ void txt_print_undo(Text *text) } } -static void txt_undo_add_op(Text *text, int op) -{ - if (!max_undo_test(text, 2)) - return; - - text->undo_pos++; - text->undo_buf[text->undo_pos] = op; - text->undo_buf[text->undo_pos + 1] = 0; -} - static void txt_undo_store_uint16(char *undo_buf, int *undo_pos, unsigned short value) { undo_buf[*undo_pos] = (value) & 0xff; @@ -1841,17 +1642,41 @@ static void txt_undo_store_uint32(char *undo_buf, int *undo_pos, unsigned int va (*undo_pos)++; } -static void txt_undo_add_block(Text *text, int op, const char *buf) +/* store the cur cursor to the undo buffer */ +static void txt_undo_store_cur(Text *text) +{ + txt_undo_store_uint16(text->undo_buf, &text->undo_pos, text->curc); + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, txt_get_span(text->lines.first, text->curl)); +} + +/* store the sel cursor to the undo buffer */ +static void txt_undo_store_sel(Text *text) +{ + txt_undo_store_uint16(text->undo_buf, &text->undo_pos, text->selc); + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, txt_get_span(text->lines.first, text->sell)); +} + +/* store both cursors to the undo buffer */ +static void txt_undo_store_cursors(Text *text) +{ + txt_undo_store_cur(text); + txt_undo_store_sel(text); +} + +/* store an operator along with a block of data */ +static void txt_undo_add_blockop(Text *text, int op, const char *buf) { unsigned int length = strlen(buf); - if (!max_undo_test(text, length + 11)) + if (!max_undo_test(text, length + 11 + 12)) return; text->undo_pos++; text->undo_buf[text->undo_pos] = op; text->undo_pos++; + txt_undo_store_cursors(text); + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, length); strncpy(text->undo_buf + text->undo_pos, buf, length); @@ -1863,34 +1688,30 @@ static void txt_undo_add_block(Text *text, int op, const char *buf) text->undo_buf[text->undo_pos + 1] = 0; } -void txt_undo_add_toop(Text *text, int op, unsigned int froml, unsigned short fromc, unsigned int tol, unsigned short toc) +/* store a regular operator */ +void txt_undo_add_op(Text *text, int op) { if (!max_undo_test(text, 15)) return; - if (froml == tol && fromc == toc) return; - text->undo_pos++; text->undo_buf[text->undo_pos] = op; text->undo_pos++; - txt_undo_store_uint16(text->undo_buf, &text->undo_pos, fromc); - txt_undo_store_uint32(text->undo_buf, &text->undo_pos, froml); - txt_undo_store_uint16(text->undo_buf, &text->undo_pos, toc); - txt_undo_store_uint32(text->undo_buf, &text->undo_pos, tol); + txt_undo_store_cursors(text); text->undo_buf[text->undo_pos] = op; - text->undo_buf[text->undo_pos + 1] = 0; } +/* store an operator for a single character */ static void txt_undo_add_charop(Text *text, int op_start, unsigned int c) { char utf8[BLI_UTF8_MAX]; size_t i, utf8_size = BLI_str_utf8_from_unicode(c, utf8); - if (!max_undo_test(text, 3 + utf8_size)) + if (!max_undo_test(text, 3 + utf8_size + 12)) return; text->undo_pos++; @@ -1899,6 +1720,8 @@ static void txt_undo_add_charop(Text *text, int op_start, unsigned int c) text->undo_buf[text->undo_pos] = op_start + utf8_size - 1; text->undo_pos++; + txt_undo_store_cur(text); + for (i = 0; i < utf8_size; i++) { text->undo_buf[text->undo_pos] = utf8[i]; text->undo_pos++; @@ -1909,6 +1732,9 @@ static void txt_undo_add_charop(Text *text, int op_start, unsigned int c) else { text->undo_buf[text->undo_pos] = op_start + 3; text->undo_pos++; + + txt_undo_store_cursors(text); + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, c); text->undo_buf[text->undo_pos] = op_start + 3; } @@ -1934,6 +1760,29 @@ static unsigned int txt_undo_read_uint32(const char *undo_buf, int *undo_pos) return val; } +/* read the cur cursor from the undo buffer */ +static void txt_undo_read_cur(const char *undo_buf, int *undo_pos, unsigned int *curln, unsigned short *curc) +{ + *curln = txt_undo_read_uint32(undo_buf, undo_pos); + *curc = txt_undo_read_uint16(undo_buf, undo_pos); +} + +/* read the sel cursor from the undo buffer */ +static void txt_undo_read_sel(const char *undo_buf, int *undo_pos, unsigned int *selln, unsigned short *selc) +{ + *selln = txt_undo_read_uint32(undo_buf, undo_pos); + *selc = txt_undo_read_uint16(undo_buf, undo_pos); +} + +/* read both cursors from the undo buffer */ +static void txt_undo_read_cursors(const char *undo_buf, int *undo_pos, + unsigned int *curln, unsigned short *curc, + unsigned int *selln, unsigned short *selc) +{ + txt_undo_read_sel(undo_buf, undo_pos, selln, selc); + txt_undo_read_cur(undo_buf, undo_pos, curln, curc); +} + static unsigned int txt_undo_read_unicode(const char *undo_buf, int *undo_pos, short bytes) { unsigned int unicode; @@ -1986,6 +1835,29 @@ static unsigned int txt_redo_read_uint32(const char *undo_buf, int *undo_pos) return val; } +/* redo read cur cursor from the undo buffer */ +static void txt_redo_read_cur(const char *undo_buf, int *undo_pos, unsigned int *curln, unsigned short *curc) +{ + *curc = txt_redo_read_uint16(undo_buf, undo_pos); + *curln = txt_redo_read_uint32(undo_buf, undo_pos); +} + +/* redo read sel cursor from the undo buffer */ +static void txt_redo_read_sel(const char *undo_buf, int *undo_pos, unsigned int *selln, unsigned short *selc) +{ + *selc = txt_redo_read_uint16(undo_buf, undo_pos); + *selln = txt_redo_read_uint32(undo_buf, undo_pos); +} + +/* redo read both cursors from the undo buffer */ +static void txt_redo_read_cursors(const char *undo_buf, int *undo_pos, + unsigned int *curln, unsigned short *curc, + unsigned int *selln, unsigned short *selc) +{ + txt_redo_read_cur(undo_buf, undo_pos, curln, curc); + txt_redo_read_sel(undo_buf, undo_pos, selln, selc); +} + static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, short bytes) { unsigned int unicode; @@ -2024,9 +1896,10 @@ void txt_do_undo(Text *text) { int op = text->undo_buf[text->undo_pos]; unsigned int linep, i; + unsigned int uchar; + unsigned int curln, selln; + unsigned short curc, selc; unsigned short charp; - TextLine *holdl; - int holdc, holdln; char *buf; if (text->undo_pos < 0) { @@ -2038,88 +1911,60 @@ void txt_do_undo(Text *text) undoing = 1; switch (op) { - case UNDO_CLEFT: - txt_move_right(text, 0); - break; - - case UNDO_CRIGHT: - txt_move_left(text, 0); - break; - - case UNDO_CUP: - txt_move_down(text, 0); - break; - - case UNDO_CDOWN: - txt_move_up(text, 0); - break; - - case UNDO_SLEFT: - txt_move_right(text, 1); - break; - - case UNDO_SRIGHT: - txt_move_left(text, 1); - break; - - case UNDO_SUP: - txt_move_down(text, 1); - break; - - case UNDO_SDOWN: - txt_move_up(text, 1); - break; - - case UNDO_CTO: - case UNDO_STO: - text->undo_pos--; - text->undo_pos--; - text->undo_pos--; - text->undo_pos--; - - text->undo_pos--; - text->undo_pos--; - - linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); - charp = txt_undo_read_uint16(text->undo_buf, &text->undo_pos); - - if (op == UNDO_CTO) { - txt_move_toline(text, linep, 0); - text->curc = charp; - txt_pop_sel(text); - } - else { - txt_move_toline(text, linep, 1); - text->selc = charp; - } - - text->undo_pos--; - break; - - case UNDO_INSERT_1: case UNDO_INSERT_2: case UNDO_INSERT_3: case UNDO_INSERT_4: - txt_backspace_char(text); + case UNDO_INSERT_1: + case UNDO_INSERT_2: + case UNDO_INSERT_3: + case UNDO_INSERT_4: text->undo_pos -= op - UNDO_INSERT_1 + 1; - text->undo_pos--; - break; - - case UNDO_BS_1: case UNDO_BS_2: case UNDO_BS_3: case UNDO_BS_4: - charp = op - UNDO_BS_1 + 1; - txt_add_char(text, txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp)); - text->undo_pos--; - break; - case UNDO_DEL_1: case UNDO_DEL_2: case UNDO_DEL_3: case UNDO_DEL_4: - charp = op - UNDO_DEL_1 + 1; - txt_add_char(text, txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp)); - txt_move_left(text, 0); + /* get and restore the cursors */ + txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + + txt_delete_char(text); + text->undo_pos--; break; - case UNDO_SWAP: - txt_curs_swap(text); + case UNDO_BS_1: + case UNDO_BS_2: + case UNDO_BS_3: + case UNDO_BS_4: + charp = op - UNDO_BS_1 + 1; + uchar = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp); + + /* get and restore the cursors */ + txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + + txt_add_char(text, uchar); + + text->undo_pos--; + break; + + case UNDO_DEL_1: + case UNDO_DEL_2: + case UNDO_DEL_3: + case UNDO_DEL_4: + charp = op - UNDO_DEL_1 + 1; + uchar = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp); + + /* get and restore the cursors */ + txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + + txt_add_char(text, uchar); + + txt_move_left(text, 0); + + text->undo_pos--; break; case UNDO_DBLOCK: + /* length of the string in the buffer */ linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); buf = MEM_mallocN(linep + 1, "dblock buffer"); @@ -2128,34 +1973,33 @@ void txt_do_undo(Text *text) text->undo_pos--; } buf[i] = 0; - - txt_curs_first(text, &holdl, &holdc); - holdln = txt_get_span(text->lines.first, holdl); - - txt_insert_buf(text, buf); - MEM_freeN(buf); - - text->curl = text->lines.first; - while (holdln > 0) { - if (text->curl->next) - text->curl = text->curl->next; - - holdln--; - } - text->curc = holdc; + /* skip over the length that was stored again */ text->undo_pos--; text->undo_pos--; text->undo_pos--; text->undo_pos--; + /* Get the cursor positions */ + txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + + /* move cur to location that needs buff inserted */ + txt_move_to(text, curln, curc, 0); + + txt_insert_buf(text, buf); + MEM_freeN(buf); + + /* restore the cursors */ + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + text->undo_pos--; break; case UNDO_IBLOCK: + /* length of the string in the buffer */ linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); - txt_delete_sel(text); /* txt_backspace_char removes utf8-characters, not bytes */ buf = MEM_mallocN(linep + 1, "iblock buffer"); @@ -2167,47 +2011,38 @@ void txt_do_undo(Text *text) linep = txt_utf8_len(buf); MEM_freeN(buf); - while (linep > 0) { - txt_backspace_char(text); - linep--; + /* skip over the length that was stored again */ + text->undo_pos--; + text->undo_pos--; + text->undo_pos--; + text->undo_pos--; + + /* get and restore the cursors */ + txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + + if ((curln == selln) && (curc == selc)) { + for (i = 0; i < linep; i++) + txt_move_right(text, 1); } - text->undo_pos--; - text->undo_pos--; - text->undo_pos--; - text->undo_pos--; + txt_delete_selected(text); text->undo_pos--; - break; case UNDO_INDENT: case UNDO_UNINDENT: case UNDO_COMMENT: case UNDO_UNCOMMENT: - linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); - //linep is now the end line of the selection - - charp = txt_undo_read_uint16(text->undo_buf, &text->undo_pos); - //charp is the last char selected or text->line->len - - //set the selection for this now - text->selc = charp; - text->sell = text->lines.first; - for (i = 0; i < linep; i++) { - text->sell = text->sell->next; - } - - linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); - //first line to be selected - - charp = txt_undo_read_uint16(text->undo_buf, &text->undo_pos); - //first postion to be selected - text->curc = charp; - text->curl = text->lines.first; - for (i = 0; i < linep; i++) { - text->curl = text->curl->next; - } - + case UNDO_DUPLICATE: + case UNDO_MOVE_LINES_UP: + case UNDO_MOVE_LINES_DOWN: + /* get and restore the cursors */ + txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); if (op == UNDO_INDENT) { txt_unindent(text); @@ -2221,37 +2056,24 @@ void txt_do_undo(Text *text) else if (op == UNDO_UNCOMMENT) { txt_comment(text); } + else if (op == UNDO_DUPLICATE) { + txt_delete_line(text, text->curl->next); + } + else if (op == UNDO_MOVE_LINES_UP) { + txt_move_lines(text, TXT_MOVE_LINE_DOWN); + } + else if (op == UNDO_MOVE_LINES_DOWN) { + txt_move_lines(text, TXT_MOVE_LINE_UP); + } text->undo_pos--; break; - case UNDO_DUPLICATE: - txt_delete_line(text, text->curl->next); - break; - case UNDO_MOVE_LINES_UP: - txt_move_lines(text, TXT_MOVE_LINE_DOWN); - break; - case UNDO_MOVE_LINES_DOWN: - txt_move_lines(text, TXT_MOVE_LINE_UP); - break; default: //XXX error("Undo buffer error - resetting"); text->undo_pos = -1; break; } - - /* next undo step may need evaluating */ - if (text->undo_pos >= 0) { - switch (text->undo_buf[text->undo_pos]) { - case UNDO_STO: - txt_do_undo(text); - txt_do_redo(text); /* selections need restoring */ - break; - case UNDO_SWAP: - txt_do_undo(text); /* swaps should appear transparent */ - break; - } - } undoing = 0; } @@ -2259,9 +2081,12 @@ void txt_do_undo(Text *text) void txt_do_redo(Text *text) { char op; - unsigned int linep, i; - unsigned short charp; char *buf; + unsigned int linep; + unsigned short charp; + unsigned int uchar; + unsigned int curln, selln; + unsigned short curc, selc; text->undo_pos++; op = text->undo_buf[text->undo_pos]; @@ -2274,104 +2099,91 @@ void txt_do_redo(Text *text) undoing = 1; switch (op) { - case UNDO_CLEFT: - txt_move_left(text, 0); - break; - - case UNDO_CRIGHT: - txt_move_right(text, 0); - break; - - case UNDO_CUP: - txt_move_up(text, 0); - break; - - case UNDO_CDOWN: - txt_move_down(text, 0); - break; - - case UNDO_SLEFT: - txt_move_left(text, 1); - break; - - case UNDO_SRIGHT: - txt_move_right(text, 1); - break; - - case UNDO_SUP: - txt_move_up(text, 1); - break; - - case UNDO_SDOWN: - txt_move_down(text, 1); - break; - - case UNDO_INSERT_1: case UNDO_INSERT_2: case UNDO_INSERT_3: case UNDO_INSERT_4: + case UNDO_INSERT_1: + case UNDO_INSERT_2: + case UNDO_INSERT_3: + case UNDO_INSERT_4: text->undo_pos++; + + /* get and restore the cursors */ + txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + charp = op - UNDO_INSERT_1 + 1; - txt_add_char(text, txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp)); + uchar = txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp); + + txt_add_char(text, uchar); break; - case UNDO_BS_1: case UNDO_BS_2: case UNDO_BS_3: case UNDO_BS_4: + case UNDO_BS_1: + case UNDO_BS_2: + case UNDO_BS_3: + case UNDO_BS_4: text->undo_pos++; - txt_backspace_char(text); + + /* get and restore the cursors */ + txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + text->undo_pos += op - UNDO_BS_1 + 1; + + /* move right so we backspace the correct char */ + txt_move_right(text, 0); + txt_backspace_char(text); + break; - case UNDO_DEL_1: case UNDO_DEL_2: case UNDO_DEL_3: case UNDO_DEL_4: + case UNDO_DEL_1: + case UNDO_DEL_2: + case UNDO_DEL_3: + case UNDO_DEL_4: text->undo_pos++; - txt_delete_char(text); + + /* get and restore the cursors */ + txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + text->undo_pos += op - UNDO_DEL_1 + 1; - break; - case UNDO_SWAP: - txt_curs_swap(text); - txt_do_redo(text); /* swaps should appear transparent a*/ - break; - - case UNDO_CTO: - case UNDO_STO: - text->undo_pos++; - text->undo_pos++; - - text->undo_pos++; - text->undo_pos++; - text->undo_pos++; - text->undo_pos++; - - text->undo_pos++; - - charp = txt_redo_read_uint16(text->undo_buf, &text->undo_pos); - linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); - - if (op == UNDO_CTO) { - txt_move_toline(text, linep, 0); - text->curc = charp; - txt_pop_sel(text); - } - else { - txt_move_toline(text, linep, 1); - text->selc = charp; - } + txt_delete_char(text); break; case UNDO_DBLOCK: text->undo_pos++; + + /* get and restore the cursors */ + txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + + /* length of the block */ linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); - txt_delete_sel(text); text->undo_pos += linep; + /* skip over the length that was stored again */ text->undo_pos++; text->undo_pos++; text->undo_pos++; text->undo_pos++; + txt_delete_sel(text); + break; case UNDO_IBLOCK: text->undo_pos++; + + /* get and restore the cursors */ + txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + + /* length of the block */ linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); buf = MEM_mallocN(linep + 1, "iblock buffer"); @@ -2382,40 +2194,27 @@ void txt_do_redo(Text *text) txt_insert_buf(text, buf); MEM_freeN(buf); + /* skip over the length that was stored again */ text->undo_pos++; text->undo_pos++; text->undo_pos++; text->undo_pos++; + break; case UNDO_INDENT: case UNDO_UNINDENT: case UNDO_COMMENT: case UNDO_UNCOMMENT: + case UNDO_DUPLICATE: + case UNDO_MOVE_LINES_UP: + case UNDO_MOVE_LINES_DOWN: text->undo_pos++; - charp = txt_redo_read_uint16(text->undo_buf, &text->undo_pos); - //charp is the first char selected or 0 - - linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); - //linep is now the first line of the selection - //set the selcetion for this now - text->curc = charp; - text->curl = text->lines.first; - for (i = 0; i < linep; i++) { - text->curl = text->curl->next; - } - - charp = txt_redo_read_uint16(text->undo_buf, &text->undo_pos); - //last postion to be selected - - linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); - //Last line to be selected - - text->selc = charp; - text->sell = text->lines.first; - for (i = 0; i < linep; i++) { - text->sell = text->sell->next; - } + + /* get and restore the cursors */ + txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); if (op == UNDO_INDENT) { txt_indent(text); @@ -2429,15 +2228,28 @@ void txt_do_redo(Text *text) else if (op == UNDO_UNCOMMENT) { txt_uncomment(text); } - break; - case UNDO_DUPLICATE: - txt_duplicate_line(text); - break; - case UNDO_MOVE_LINES_UP: - txt_move_lines(text, TXT_MOVE_LINE_UP); - break; - case UNDO_MOVE_LINES_DOWN: - txt_move_lines(text, TXT_MOVE_LINE_DOWN); + else if (op == UNDO_DUPLICATE) { + txt_duplicate_line(text); + } + else if (op == UNDO_MOVE_LINES_UP) { + /* offset the cursor by + 1 */ + txt_move_to(text, curln + 1, curc, 0); + txt_move_to(text, selln + 1, selc, 1); + + txt_move_lines(text, TXT_MOVE_LINE_UP); + } + else if (op == UNDO_MOVE_LINES_DOWN) { + /* offset the cursor by - 1 */ + txt_move_to(text, curln - 1, curc, 0); + txt_move_to(text, selln - 1, selc, 1); + + txt_move_lines(text, TXT_MOVE_LINE_DOWN); + } + + /* re-restore the cursors since they got moved when redoing */ + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + break; default: //XXX error("Undo buffer error - resetting"); @@ -2456,31 +2268,15 @@ void txt_do_redo(Text *text) void txt_split_curline(Text *text) { TextLine *ins; - TextMarker *mrk; char *left, *right; - int lineno = -1; if (!text) return; if (!text->curl) return; txt_delete_sel(text); - /* Move markers */ - - lineno = txt_get_span(text->lines.first, text->curl); - mrk = text->markers.first; - while (mrk) { - if (mrk->lineno == lineno && mrk->start > text->curc) { - mrk->lineno++; - mrk->start -= text->curc; - mrk->end -= text->curc; - } - else if (mrk->lineno > lineno) { - mrk->lineno++; - } - mrk = mrk->next; - } - + if (!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, '\n'); + /* Make the two half strings */ left = MEM_mallocN(text->curc + 1, "textline_string"); @@ -2512,28 +2308,13 @@ void txt_split_curline(Text *text) txt_clean_text(text); txt_pop_sel(text); - if (!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, '\n'); } static void txt_delete_line(Text *text, TextLine *line) { - TextMarker *mrk = NULL, *nxt; - int lineno = -1; - if (!text) return; if (!text->curl) return; - lineno = txt_get_span(text->lines.first, line); - mrk = text->markers.first; - while (mrk) { - nxt = mrk->next; - if (mrk->lineno == lineno) - BLI_freelinkN(&text->markers, mrk); - else if (mrk->lineno > lineno) - mrk->lineno--; - mrk = nxt; - } - BLI_remlink(&text->lines, line); if (line->line) MEM_freeN(line->line); @@ -2548,25 +2329,12 @@ static void txt_delete_line(Text *text, TextLine *line) static void txt_combine_lines(Text *text, TextLine *linea, TextLine *lineb) { char *tmp; - TextMarker *mrk = NULL; - int lineno = -1; - + if (!text) return; if (!linea || !lineb) return; - mrk = txt_find_marker_region(text, lineb, 0, lineb->len, 0, 0); - if (mrk) { - lineno = mrk->lineno; - do { - mrk->lineno--; - mrk->start += linea->len; - mrk->end += linea->len; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } - if (lineno == -1) lineno = txt_get_span(text->lines.first, lineb); - + tmp = MEM_mallocN(linea->len + lineb->len + 1, "textline_string"); strcpy(tmp, linea->line); @@ -2619,27 +2387,7 @@ void txt_delete_char(Text *text) } else { /* Just deleting a char */ size_t c_len = 0; - TextMarker *mrk; c = BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &c_len); - - mrk = txt_find_marker_region(text, text->curl, text->curc - c_len, text->curl->len, 0, 0); - if (mrk) { - int lineno = mrk->lineno; - if (mrk->end == text->curc) { - if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) { - txt_clear_markers(text, mrk->group, TMARK_TEMP); - } - else { - BLI_freelinkN(&text->markers, mrk); - } - return; - } - do { - if (mrk->start > text->curc) mrk->start -= c_len; - mrk->end -= c_len; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } memmove(text->curl->line + text->curc, text->curl->line + text->curc + c_len, text->curl->len - text->curc - c_len + 1); @@ -2683,28 +2431,8 @@ void txt_backspace_char(Text *text) } else { /* Just backspacing a char */ size_t c_len = 0; - TextMarker *mrk; char *prev = BLI_str_prev_char_utf8(text->curl->line + text->curc); c = BLI_str_utf8_as_unicode_and_size(prev, &c_len); - - mrk = txt_find_marker_region(text, text->curl, text->curc - c_len, text->curl->len, 0, 0); - if (mrk) { - int lineno = mrk->lineno; - if (mrk->start == text->curc) { - if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) { - txt_clear_markers(text, mrk->group, TMARK_TEMP); - } - else { - BLI_freelinkN(&text->markers, mrk); - } - return; - } - do { - if (mrk->start > text->curc - c_len) mrk->start -= c_len; - mrk->end -= c_len; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } /* source and destination overlap, don't use memcpy() */ memmove(text->curl->line + text->curc - c_len, @@ -2746,9 +2474,7 @@ static void txt_convert_tab_to_spaces(Text *text) static int txt_add_char_intern(Text *text, unsigned int add, int replace_tabs) { - int lineno; char *tmp, ch[BLI_UTF8_MAX]; - TextMarker *mrk; size_t add_len; if (!text) return 0; @@ -2767,16 +2493,9 @@ static int txt_add_char_intern(Text *text, unsigned int add, int replace_tabs) txt_delete_sel(text); + if (!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, add); + add_len = BLI_str_utf8_from_unicode(add, ch); - mrk = txt_find_marker_region(text, text->curl, text->curc - 1, text->curl->len, 0, 0); - if (mrk) { - lineno = mrk->lineno; - do { - if (mrk->start > text->curc) mrk->start += add_len; - mrk->end += add_len; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } tmp = MEM_mallocN(text->curl->len + add_len + 1, "textline_string"); @@ -2793,7 +2512,6 @@ static int txt_add_char_intern(Text *text, unsigned int add, int replace_tabs) txt_make_dirty(text); txt_clean_text(text); - if (!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, add); return 1; } @@ -2824,10 +2542,7 @@ int txt_replace_char(Text *text, unsigned int add) /* If text is selected or we're at the end of the line just use txt_add_char */ if (text->curc == text->curl->len || txt_has_sel(text) || add == '\n') { - int i = txt_add_char(text, add); - TextMarker *mrk = txt_find_marker(text, text->curl, text->curc, 0, 0); - if (mrk) BLI_freelinkN(&text->markers, mrk); - return i; + return txt_add_char(text, add); } del = BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &del_size); @@ -2854,8 +2569,8 @@ int txt_replace_char(Text *text, unsigned int add) /* Should probably create a new op for this */ if (!undoing) { - txt_undo_add_charop(text, UNDO_DEL_1, del); txt_undo_add_charop(text, UNDO_INSERT_1, add); + txt_undo_add_charop(text, UNDO_DEL_1, del); } return 1; } @@ -2924,7 +2639,7 @@ void txt_indent(Text *text) } if (!undoing) { - txt_undo_add_toop(text, UNDO_INDENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc); + txt_undo_add_op(text, UNDO_INDENT); } } @@ -2982,7 +2697,7 @@ void txt_unindent(Text *text) } if (!undoing) { - txt_undo_add_toop(text, UNDO_UNINDENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc); + txt_undo_add_op(text, UNDO_UNINDENT); } } @@ -3031,7 +2746,7 @@ void txt_comment(Text *text) } if (!undoing) { - txt_undo_add_toop(text, UNDO_COMMENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc); + txt_undo_add_op(text, UNDO_COMMENT); } } @@ -3076,7 +2791,7 @@ void txt_uncomment(Text *text) } if (!undoing) { - txt_undo_add_toop(text, UNDO_UNCOMMENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc); + txt_undo_add_op(text, UNDO_UNCOMMENT); } } @@ -3165,157 +2880,6 @@ int setcurr_tab_spaces(Text *text, int space) return i; } -/*********************************/ -/* Text marker utility functions */ -/*********************************/ - -/* Creates and adds a marker to the list maintaining sorted order */ -void txt_add_marker(Text *text, TextLine *line, int start, int end, const unsigned char color[4], int group, int flags) -{ - TextMarker *tmp, *marker; - - marker = MEM_mallocN(sizeof(TextMarker), "text_marker"); - - marker->lineno = txt_get_span(text->lines.first, line); - marker->start = MIN2(start, end); - marker->end = MAX2(start, end); - marker->group = group; - marker->flags = flags; - - marker->color[0] = color[0]; - marker->color[1] = color[1]; - marker->color[2] = color[2]; - marker->color[3] = color[3]; - - for (tmp = text->markers.last; tmp; tmp = tmp->prev) - if (tmp->lineno < marker->lineno || (tmp->lineno == marker->lineno && tmp->start < marker->start)) - break; - - if (tmp) BLI_insertlinkafter(&text->markers, tmp, marker); - else BLI_addhead(&text->markers, marker); -} - -/* Returns the first matching marker on the specified line between two points. - * If the group or flags fields are non-zero the returned flag must be in the - * specified group and have at least the specified flags set. */ -TextMarker *txt_find_marker_region(Text *text, TextLine *line, int start, int end, int group, int flags) -{ - TextMarker *marker, *next; - int lineno = txt_get_span(text->lines.first, line); - - for (marker = text->markers.first; marker; marker = next) { - next = marker->next; - - if (group && marker->group != group) continue; - else if ((marker->flags & flags) != flags) continue; - else if (marker->lineno < lineno) continue; - else if (marker->lineno > lineno) break; - - if ((marker->start == marker->end && start <= marker->start && marker->start <= end) || - (marker->start < end && marker->end > start)) - { - return marker; - } - } - return NULL; -} - -/* Clears all markers on the specified line between two points. If the group or - * flags fields are non-zero the returned flag must be in the specified group - * and have at least the specified flags set. */ -short txt_clear_marker_region(Text *text, TextLine *line, int start, int end, int group, int flags) -{ - TextMarker *marker, *next; - int lineno = txt_get_span(text->lines.first, line); - short cleared = 0; - - for (marker = text->markers.first; marker; marker = next) { - next = marker->next; - - if (group && marker->group != group) continue; - else if ((marker->flags & flags) != flags) continue; - else if (marker->lineno < lineno) continue; - else if (marker->lineno > lineno) break; - - if ((marker->start == marker->end && start <= marker->start && marker->start <= end) || - (marker->start < end && marker->end > start)) - { - BLI_freelinkN(&text->markers, marker); - cleared = 1; - } - } - return cleared; -} - -/* Clears all markers in the specified group (if given) with at least the - * specified flags set. Useful for clearing temporary markers (group = 0, - * flags = TMARK_TEMP) */ -short txt_clear_markers(Text *text, int group, int flags) -{ - TextMarker *marker, *next; - short cleared = 0; - - for (marker = text->markers.first; marker; marker = next) { - next = marker->next; - - if ((!group || marker->group == group) && - (marker->flags & flags) == flags) - { - BLI_freelinkN(&text->markers, marker); - cleared = 1; - } - } - return cleared; -} - -/* Finds the marker at the specified line and cursor position with at least the - * specified flags set in the given group (if non-zero). */ -TextMarker *txt_find_marker(Text *text, TextLine *line, int curs, int group, int flags) -{ - TextMarker *marker; - int lineno = txt_get_span(text->lines.first, line); - - for (marker = text->markers.first; marker; marker = marker->next) { - if (group && marker->group != group) continue; - else if ((marker->flags & flags) != flags) continue; - else if (marker->lineno < lineno) continue; - else if (marker->lineno > lineno) break; - - if (marker->start <= curs && curs <= marker->end) - return marker; - } - return NULL; -} - -/* Finds the previous marker in the same group. If no other is found, the same - * marker will be returned */ -TextMarker *txt_prev_marker(Text *text, TextMarker *marker) -{ - TextMarker *tmp = marker; - while (tmp) { - if (tmp->prev) tmp = tmp->prev; - else tmp = text->markers.last; - if (tmp->group == marker->group) - return tmp; - } - return NULL; /* Only if (marker == NULL) */ -} - -/* Finds the next marker in the same group. If no other is found, the same - * marker will be returned */ -TextMarker *txt_next_marker(Text *text, TextMarker *marker) -{ - TextMarker *tmp = marker; - while (tmp) { - if (tmp->next) tmp = tmp->next; - else tmp = text->markers.first; - if (tmp->group == marker->group) - return tmp; - } - return NULL; /* Only if (marker == NULL) */ -} - - /*******************************/ /* Character utility functions */ /*******************************/ diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 89446a1856f..30b48401046 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1124,10 +1124,10 @@ void BKE_tracking_marker_pattern_minmax(const MovieTrackingMarker *marker, float { INIT_MINMAX2(min, max); - DO_MINMAX2(marker->pattern_corners[0], min, max); - DO_MINMAX2(marker->pattern_corners[1], min, max); - DO_MINMAX2(marker->pattern_corners[2], min, max); - DO_MINMAX2(marker->pattern_corners[3], min, max); + minmax_v2v2_v2(min, max, marker->pattern_corners[0]); + minmax_v2v2_v2(min, max, marker->pattern_corners[1]); + minmax_v2v2_v2(min, max, marker->pattern_corners[2]); + minmax_v2v2_v2(min, max, marker->pattern_corners[3]); } void BKE_tracking_marker_get_subframe_position(MovieTrackingTrack *track, float framenr, float pos[2]) @@ -1624,6 +1624,9 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *sea double warped_position_x, warped_position_y; float *mask = NULL; + if (num_samples_x <= 0 || num_samples_y <= 0) + return NULL; + pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat); if (!search_ibuf->rect_float) { @@ -1690,10 +1693,15 @@ ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mo search_ibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, anchored, disable_channels); - pattern_ibuf = BKE_tracking_sample_pattern(ibuf->x, ibuf->y, search_ibuf, track, marker, - FALSE, num_samples_x, num_samples_y, NULL); + if (search_ibuf) { + pattern_ibuf = BKE_tracking_sample_pattern(ibuf->x, ibuf->y, search_ibuf, track, marker, + FALSE, num_samples_x, num_samples_y, NULL); - IMB_freeImBuf(search_ibuf); + IMB_freeImBuf(search_ibuf); + } + else { + pattern_ibuf = NULL; + } return pattern_ibuf; } @@ -1718,6 +1726,9 @@ ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mov w = (marker->search_max[0] - marker->search_min[0]) * ibuf->x; h = (marker->search_max[1] - marker->search_min[1]) * ibuf->y; + if (w <= 0 || h <= 0) + return NULL; + searchibuf = IMB_allocImBuf(w, h, 32, ibuf->rect_float ? IB_rectfloat : IB_rect); IMB_rectcpy(searchibuf, ibuf, 0, 0, x, y, w, h); @@ -2187,6 +2198,12 @@ static float *track_get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, FALSE, TRUE); + if (!searchibuf) { + *width_r = 0; + *height_r = 0; + return NULL; + } + width = searchibuf->x; height = searchibuf->y; @@ -2506,6 +2523,9 @@ int BKE_tracking_context_step(MovieTrackingContext *context) get_marker_coords_for_tracking(frame_width, frame_height, &track_context->marker, src_pixel_x, src_pixel_y); get_marker_coords_for_tracking(frame_width, frame_height, marker, dst_pixel_x, dst_pixel_y); + if (!patch_new || !track_context->search_area) + continue; + /* run the tracker! */ tracked = libmv_trackRegion(&options, track_context->search_area, @@ -3141,7 +3161,7 @@ static int stabilization_median_point_get(MovieTracking *tracking, int framenr, if (track->flag & TRACK_USE_2D_STAB) { MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); - DO_MINMAX2(marker->pos, min, max); + minmax_v2v2_v2(min, max, marker->pos); ok = TRUE; } diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 3a8a14290dc..0f861a7ed37 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -111,6 +111,11 @@ static void delete_picture(AVFrame *f) } } +static int use_float_audio_buffer(int codec_id) +{ + return codec_id == CODEC_ID_AAC || codec_id == CODEC_ID_AC3 || codec_id == CODEC_ID_VORBIS; +} + #ifdef WITH_AUDASPACE static int write_audio_frame(void) { @@ -478,9 +483,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex c->time_base.den = 2997; c->time_base.num = 100; } - else if ((double) ((int) rd->frs_sec_base) == - rd->frs_sec_base) - { + else if ((float) ((int) rd->frs_sec_base) == rd->frs_sec_base) { c->time_base.den = rd->frs_sec; c->time_base.num = (int) rd->frs_sec_base; } @@ -601,12 +604,14 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex /* Prepare an audio stream for the output file */ -static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext *of) +static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext *of, char *error, int error_size) { AVStream *st; AVCodecContext *c; AVCodec *codec; + error[0] = '\0'; + st = av_new_stream(of, 1); if (!st) return NULL; @@ -618,6 +623,10 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex c->bit_rate = ffmpeg_audio_bitrate * 1000; c->sample_fmt = AV_SAMPLE_FMT_S16; c->channels = rd->ffcodecdata.audio_channels; + if (use_float_audio_buffer(codec_id)) { + c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; + c->sample_fmt = AV_SAMPLE_FMT_FLT; + } codec = avcodec_find_encoder(c->codec_id); if (!codec) { //XXX error("Couldn't find a valid audio codec"); @@ -628,6 +637,7 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex if (avcodec_open(c, codec) < 0) { //XXX error("Couldn't initialize audio codec"); + BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size); return NULL; } @@ -648,7 +658,12 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex audio_output_buffer = (uint8_t *) av_malloc(audio_outbuf_size); - audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(int16_t)); + if (use_float_audio_buffer(codec_id)) { + 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_time = 0.0f; @@ -803,9 +818,12 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report } if (ffmpeg_audio_codec != CODEC_ID_NONE) { - audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of); + audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of, error, sizeof(error)); if (!audio_stream) { - BKE_report(reports, RPT_ERROR, "Error initializing audio stream"); + if (error[0]) + BKE_report(reports, RPT_ERROR, error); + else + BKE_report(reports, RPT_ERROR, "Error initializing audio stream"); av_dict_free(&opts); return 0; } @@ -945,7 +963,12 @@ 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; - specs.format = AUD_FORMAT_S16; + if (use_float_audio_buffer(c->codec_id)) { + specs.format = AUD_FORMAT_FLOAT32; + } + else { + specs.format = AUD_FORMAT_S16; + } specs.rate = rd->ffcodecdata.audio_mixrate; audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->ffcodecdata.audio_volume); #ifdef FFMPEG_CODEC_TIME_BASE @@ -999,7 +1022,7 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i } #ifdef WITH_AUDASPACE - write_audio_frames((frame - rd->sfra) / (((double)rd->frs_sec) / rd->frs_sec_base)); + write_audio_frames((frame - rd->sfra) / (((double)rd->frs_sec) / (double)rd->frs_sec_base)); #endif return success; } diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h index 84cfe89f1b8..a21778307c1 100644 --- a/source/blender/blenlib/BLI_array.h +++ b/source/blender/blenlib/BLI_array.h @@ -77,11 +77,13 @@ MEM_allocN_len(arr) / sizeof(*arr) \ ) +#define _bli_array_totalsize_static(arr) \ + (sizeof(_##arr##_static) / sizeof(*arr)) #define BLI_array_totalsize(arr) ( \ (size_t) \ (((void *)(arr) == (void *)_##arr##_static && (void *)(arr) != NULL) ? \ - (sizeof(_##arr##_static) / sizeof(*arr)) : \ + _bli_array_totalsize_static(arr) : \ BLI_array_totalsize_dyn(arr)) \ ) @@ -93,8 +95,18 @@ * * Allow for a large 'num' value when the new size is more then double * to allocate the exact sized array. */ -#define _bli_array_grow_items(arr, num) ( \ - (BLI_array_totalsize(arr) >= _##arr##_count + num) ? \ + +/* grow an array by a specified number of items */ +#define BLI_array_grow_items(arr, num) ( \ + (((void *)(arr) == NULL) && \ + ((void *)(_##arr##_static) != NULL) && \ + /* dont add _##arr##_count below because it must be zero */ \ + (_bli_array_totalsize_static(arr) >= _##arr##_count + num)) ? \ + /* we have an empty array and a static var big enough */ \ + ((arr = (void *)_##arr##_static), (_##arr##_count += (num))) \ + : \ + /* use existing static array or allocate */ \ + ((BLI_array_totalsize(arr) >= _##arr##_count + num) ? \ (_##arr##_count += num) : \ ( \ (void) (_##arr##_tmp = MEM_callocN( \ @@ -115,14 +127,7 @@ (void) (arr = _##arr##_tmp \ ), \ (_##arr##_count += num) \ - ) \ -) - -/* grow an array by a specified number of items */ -#define BLI_array_grow_items(arr, num) ( \ - ((void *)(arr) == NULL && (void *)(_##arr##_static) != NULL) ? \ - ((arr = (void *)_##arr##_static), (_##arr##_count += num)) : \ - _bli_array_grow_items(arr, num) \ + )) \ ) /* returns length of array */ diff --git a/source/blender/blenlib/BLI_bpath.h b/source/blender/blenlib/BLI_bpath.h index a86b362c271..438bffb2fc5 100644 --- a/source/blender/blenlib/BLI_bpath.h +++ b/source/blender/blenlib/BLI_bpath.h @@ -48,6 +48,11 @@ void BLI_bpath_traverse_id_list(struct Main *bmain, struct ListBase *lb, BPathVi void BLI_bpath_traverse_main(struct Main *bmain, BPathVisitor visit_cb, const int flag, void *userdata); int BLI_bpath_relocate_visitor(void *oldbasepath, char *path_dst, const char *path_src); +/* Functions for temp backup/restore of paths, path count must NOT change */ +void *BLI_bpath_list_backup(struct Main *bmain, const int flag); +void BLI_bpath_list_restore(struct Main *bmain, const int flag, void *ls_handle); +void BLI_bpath_list_free(void *ls_handle); + #define BLI_BPATH_TRAVERSE_ABS (1 << 0) /* convert paths to absolute */ #define BLI_BPATH_TRAVERSE_SKIP_LIBRARY (1 << 2) /* skip library paths */ #define BLI_BPATH_TRAVERSE_SKIP_PACKED (1 << 3) /* skip packed data */ diff --git a/source/blender/blenlib/BLI_endian_switch.h b/source/blender/blenlib/BLI_endian_switch.h index 7cb2790525d..f48b1b072c3 100644 --- a/source/blender/blenlib/BLI_endian_switch.h +++ b/source/blender/blenlib/BLI_endian_switch.h @@ -29,8 +29,7 @@ #ifdef __GNUC__ # define ATTR_ENDIAN_SWITCH \ - __attribute__((nonnull(1))) \ - __attribute__((pure)) + __attribute__((nonnull(1))) #else # define ATTR_ENDIAN_SWITCH #endif diff --git a/source/blender/blenlib/BLI_endian_switch_inline.h b/source/blender/blenlib/BLI_endian_switch_inline.h index 4bc6d3828b9..358206f1177 100644 --- a/source/blender/blenlib/BLI_endian_switch_inline.h +++ b/source/blender/blenlib/BLI_endian_switch_inline.h @@ -38,41 +38,43 @@ /* *** 16 *** */ BLI_INLINE void BLI_endian_switch_int16(short *val) { - short tval = *val; - *val = (tval >> 8) | - (tval << 8); - + BLI_endian_switch_uint16((unsigned short *)val); } BLI_INLINE void BLI_endian_switch_uint16(unsigned short *val) { - BLI_endian_switch_int16((short *)val); + unsigned short tval = *val; + *val = (tval >> 8) | + (tval << 8); } /* *** 32 *** */ BLI_INLINE void BLI_endian_switch_int32(int *val) { - int tval = *val; + BLI_endian_switch_uint32((unsigned int *)val); +} +BLI_INLINE void BLI_endian_switch_uint32(unsigned int *val) +{ + unsigned int tval = *val; *val = ((tval >> 24)) | ((tval << 8) & 0x00ff0000) | ((tval >> 8) & 0x0000ff00) | ((tval << 24)); - -} -BLI_INLINE void BLI_endian_switch_uint32(unsigned int *val) -{ - BLI_endian_switch_int32((int *)val); } BLI_INLINE void BLI_endian_switch_float(float *val) { - BLI_endian_switch_int32((int *)val); + BLI_endian_switch_uint32((unsigned int *)val); } /* *** 64 *** */ BLI_INLINE void BLI_endian_switch_int64(int64_t *val) { - int64_t tval = *val; + BLI_endian_switch_uint64((uint64_t *)val); +} +BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val) +{ + uint64_t tval = *val; *val = ((tval >> 56)) | ((tval << 40) & 0x00ff000000000000ll) | ((tval << 24) & 0x0000ff0000000000ll) | @@ -82,13 +84,9 @@ BLI_INLINE void BLI_endian_switch_int64(int64_t *val) ((tval >> 40) & 0x000000000000ff00ll) | ((tval << 56)); } -BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val) -{ - BLI_endian_switch_int64((int64_t *)val); -} BLI_INLINE void BLI_endian_switch_double(double *val) { - BLI_endian_switch_int64((int64_t *)val); + BLI_endian_switch_uint64((uint64_t *)val); } #endif /* __BLI_ENDIAN_SWITCH_INLINE_H__ */ diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index c26e6cd15b3..7eac1425a5c 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -71,7 +71,7 @@ void BLI_ghash_insert(GHash *gh, void *key, void *val); void *BLI_ghash_lookup(GHash *gh, const void *key); int BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp); -int BLI_ghash_haskey(GHash *gh, void *key); +int BLI_ghash_haskey(GHash *gh, const void *key); int BLI_ghash_size(GHash *gh); /* *** */ diff --git a/source/blender/blenlib/BLI_math.h b/source/blender/blenlib/BLI_math.h index 89c37daae84..db2fed433da 100644 --- a/source/blender/blenlib/BLI_math.h +++ b/source/blender/blenlib/BLI_math.h @@ -58,6 +58,7 @@ #include "BLI_math_rotation.h" #include "BLI_math_vector.h" #include "BLI_math_geom.h" +#include "BLI_math_interp.h" #endif /* __BLI_MATH_H__ */ diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index 2b513cbec41..69d6478e0e2 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -170,7 +170,7 @@ } (void)0 #endif -#ifdef __BLI_MATH_INLINE_H__ +#if BLI_MATH_DO_INLINE #include "intern/math_base_inline.c" #endif @@ -203,7 +203,7 @@ MINLINE int is_power_of_2_i(int n); MINLINE int power_of_2_max_i(int n); MINLINE int power_of_2_min_i(int n); -MINLINE float shell_angle_to_dist(float angle); +MINLINE float shell_angle_to_dist(const float angle); #if (defined(WIN32) || defined(WIN64)) && !defined(FREE_WINDOWS) extern double copysign(double x, double y); diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 7c8bf88943d..c71463da61d 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -121,7 +121,7 @@ MINLINE int compare_rgb_uchar(const unsigned char a[3], const unsigned char b[3] void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *offset, float *slope, float *power); -#ifdef __BLI_MATH_INLINE_H__ +#if BLI_MATH_DO_INLINE #include "intern/math_color_inline.c" #endif diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 80169e952bf..cfd163d4e57 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -36,7 +36,7 @@ extern "C" { #include "BLI_math_inline.h" -#ifdef __BLI_MATH_INLINE_H__ +#if BLI_MATH_DO_INLINE #include "intern/math_geom_inline.c" #endif @@ -187,6 +187,10 @@ int barycentric_inside_triangle_v2(const float w[3]); void resolve_tri_uv(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2]); void resolve_quad_uv(float uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2]); +/* use to find the point of a UV on a face */ +void interp_bilinear_quad_v3(float data[4][3], float u, float v, float res[3]); +void interp_barycentric_tri_v3(float data[3][3], float u, float v, float res[3]); + /***************************** View & Projection *****************************/ void lookat_m4(float mat[4][4], float vx, float vy, diff --git a/source/blender/blenlib/BLI_math_inline.h b/source/blender/blenlib/BLI_math_inline.h index ce43d5fb941..6dad44644f2 100644 --- a/source/blender/blenlib/BLI_math_inline.h +++ b/source/blender/blenlib/BLI_math_inline.h @@ -35,9 +35,10 @@ extern "C" { #endif /* add platform/compiler checks here if it is not supported */ -#define __BLI_MATH_INLINE_H__ +/* all platforms support forcing inline so this is always enabled */ +#define BLI_MATH_DO_INLINE 1 -#ifdef __BLI_MATH_INLINE_H__ +#if BLI_MATH_DO_INLINE # ifdef _MSC_VER # define MINLINE static __forceinline # define MALWAYS_INLINE MINLINE diff --git a/source/blender/blenlib/BLI_math_interp.h b/source/blender/blenlib/BLI_math_interp.h new file mode 100644 index 00000000000..21975763779 --- /dev/null +++ b/source/blender/blenlib/BLI_math_interp.h @@ -0,0 +1,44 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 by Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#ifndef BLI_MATH_INTERP +#define BLI_MATH_INTERP + +void BLI_bicubic_interpolation_fl(const float *buffer, float *output, int width, int height, + int components, float u, float v); + +void BLI_bicubic_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, + int components, float u, float v); + +void BLI_bilinear_interpolation_fl(const float *buffer, float *output, int width, int height, + int components, float u, float v); + +void BLI_bilinear_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, + int components, float u, float v); + +#endif diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index 9e34631d460..f51bd1cf840 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -36,14 +36,18 @@ extern "C" { /********************************* Init **************************************/ -#define MAT4_UNITY {{ 1.0, 0.0, 0.0, 0.0}, \ - { 0.0, 1.0, 0.0, 0.0}, \ - { 0.0, 0.0, 1.0, 0.0}, \ - { 0.0, 0.0, 0.0, 1.0}} +#define MAT4_UNITY { \ + { 1.0, 0.0, 0.0, 0.0}, \ + { 0.0, 1.0, 0.0, 0.0}, \ + { 0.0, 0.0, 1.0, 0.0}, \ + { 0.0, 0.0, 0.0, 1.0} \ +} -#define MAT3_UNITY {{ 1.0, 0.0, 0.0}, \ - { 0.0, 1.0, 0.0}, \ - { 0.0, 0.0, 1.0}} +#define MAT3_UNITY { \ + { 1.0, 0.0, 0.0}, \ + { 0.0, 1.0, 0.0}, \ + { 0.0, 0.0, 1.0} \ +} void zero_m3(float R[3][3]); void zero_m4(float R[4][4]); @@ -98,6 +102,9 @@ void mul_m3_fl(float R[3][3], float f); void mul_m4_fl(float R[4][4], float f); void mul_mat3_m4_fl(float R[4][4], float f); +int invert_m3_ex(float m[3][3], const float epsilon); +int invert_m3_m3_ex(float m1[3][3], float m2[3][3], const float epsilon); + int invert_m3(float R[3][3]); int invert_m3_m3(float R[3][3], float A[3][3]); int invert_m4(float R[4][4]); diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 77c0ec0a88f..f4572afec84 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -36,7 +36,7 @@ extern "C" { #include "BLI_math_inline.h" -#ifdef __BLI_MATH_INLINE_H__ +#if BLI_MATH_DO_INLINE #include "intern/math_vector_inline.c" #endif @@ -169,6 +169,7 @@ void interp_v4_v4v4v4v4(float p[4], const float v1[4], const float v2[4], const void mid_v3_v3v3(float r[3], const float a[3], const float b[3]); void mid_v2_v2v2(float r[2], const float a[2], const float b[2]); +void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3]); /********************************* Comparison ********************************/ diff --git a/source/blender/blenlib/BLI_pbvh.h b/source/blender/blenlib/BLI_pbvh.h index 9483d068bb9..59ecdb359c9 100644 --- a/source/blender/blenlib/BLI_pbvh.h +++ b/source/blender/blenlib/BLI_pbvh.h @@ -153,7 +153,8 @@ void BLI_pbvh_update(PBVH *bvh, int flags, float (*face_nors)[3]); void BLI_pbvh_redraw_BB(PBVH * bvh, float bb_min[3], float bb_max[3]); void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface); void BLI_pbvh_grids_update(PBVH *bvh, struct CCGElem **grid_elems, - struct DMGridAdjacency *gridadj, void **gridfaces); + struct DMGridAdjacency *gridadj, void **gridfaces, + struct DMFlagMat *flagmats, unsigned int **grid_hidden); /* vertex deformer */ float (*BLI_pbvh_get_vertCos(struct PBVH *pbvh))[3]; diff --git a/source/blender/blenlib/BLI_quadric.h b/source/blender/blenlib/BLI_quadric.h index aec11ec2b44..e71a6473852 100644 --- a/source/blender/blenlib/BLI_quadric.h +++ b/source/blender/blenlib/BLI_quadric.h @@ -51,6 +51,6 @@ void BLI_quadric_mul(Quadric *a, const float scalar); /* solve */ float BLI_quadric_evaluate(const Quadric *q, const float v[3]); -int BLI_quadric_optimize(const Quadric *q, float v[3]); +int BLI_quadric_optimize(const Quadric *q, float v[3], const float epsilon); #endif /* __BLI_QUADRIC_H__ */ diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h index f84820e94f3..f2e26093711 100644 --- a/source/blender/blenlib/BLI_rect.h +++ b/source/blender/blenlib/BLI_rect.h @@ -33,6 +33,9 @@ * \ingroup bli */ +#include "DNA_vec_types.h" +#include "BLI_utildefines.h" + struct rctf; struct rcti; @@ -75,17 +78,6 @@ void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src); void print_rctf(const char *str, const struct rctf *rect); void print_rcti(const char *str, const struct rcti *rect); -/* hrmf, we need to work out this inline stuff */ -#if defined(_MSC_VER) -# define BLI_INLINE static __forceinline -#elif defined(__GNUC__) -# define BLI_INLINE static inline __attribute((always_inline)) -#else -/* #warning "MSC/GNUC defines not found, inline non-functional" */ -# define BLI_INLINE static -#endif - -#include "DNA_vec_types.h" BLI_INLINE float BLI_rcti_cent_x_fl(const struct rcti *rct) { return (float)(rct->xmin + rct->xmax) / 2.0f; } BLI_INLINE float BLI_rcti_cent_y_fl(const struct rcti *rct) { return (float)(rct->ymin + rct->ymax) / 2.0f; } BLI_INLINE int BLI_rcti_cent_x(const struct rcti *rct) { return (rct->xmin + rct->xmax) / 2; } diff --git a/source/blender/blenlib/BLI_scanfill.h b/source/blender/blenlib/BLI_scanfill.h index 892afdd0b27..c8fd72bbbd2 100644 --- a/source/blender/blenlib/BLI_scanfill.h +++ b/source/blender/blenlib/BLI_scanfill.h @@ -94,9 +94,18 @@ typedef struct ScanFillFace { struct ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3]); struct ScanFillEdge *BLI_scanfill_edge_add(ScanFillContext *sf_ctx, struct ScanFillVert *v1, struct ScanFillVert *v2); +enum { + BLI_SCANFILL_CALC_QUADTRI_FASTPATH = (1 << 0), + + /* note: using BLI_SCANFILL_CALC_REMOVE_DOUBLES + * Assumes ordered edges, otherwise we risk an eternal loop + * removing double verts. - campbell */ + BLI_SCANFILL_CALC_REMOVE_DOUBLES = (1 << 1), +}; + int BLI_scanfill_begin(ScanFillContext *sf_ctx); -int BLI_scanfill_calc(ScanFillContext *sf_ctx, const short do_quad_tri_speedup); -int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedup, +int BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag); +int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float nor_proj[3]); void BLI_scanfill_end(ScanFillContext *sf_ctx); diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h index 73f138a750d..ecbc4cb1cd4 100644 --- a/source/blender/blenlib/BLI_string_utf8.h +++ b/source/blender/blenlib/BLI_string_utf8.h @@ -37,6 +37,7 @@ int BLI_utf8_invalid_byte(const char *str, int length); int BLI_utf8_invalid_strip(char *str, int length); int BLI_str_utf8_size(const char *p); /* warning, can return -1 on bad chars */ +int BLI_str_utf8_size_safe(const char *p); /* copied from glib */ unsigned int BLI_str_utf8_as_unicode(const char *p); unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index); diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index 9cd801f819d..ec8e567c0ef 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -37,6 +37,10 @@ extern "C" { #include +#ifdef __APPLE__ +#include +#endif + /* for tables, button in UI, etc */ #define BLENDER_MAX_THREADS 64 @@ -92,6 +96,19 @@ void BLI_mutex_lock(ThreadMutex *mutex); void BLI_mutex_unlock(ThreadMutex *mutex); void BLI_mutex_end(ThreadMutex *mutex); +/* Spin Lock */ + +#ifdef __APPLE__ +typedef OSSpinLock SpinLock; +#else +typedef pthread_spinlock_t SpinLock; +#endif + +void BLI_spin_init(SpinLock *spin); +void BLI_spin_lock(SpinLock *spin); +void BLI_spin_unlock(SpinLock *spin); +void BLI_spin_end(SpinLock *spin); + /* Read/Write Mutex Lock */ #define THREAD_LOCK_READ 1 diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index 056fa916da1..7c3b70545d6 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -257,6 +257,15 @@ #define IN_RANGE(a, b, c) ((b < c) ? ((b < a && a < c) ? 1 : 0) : ((c < a && a < b) ? 1 : 0)) #define IN_RANGE_INCL(a, b, c) ((b < c) ? ((b <= a && a <= c) ? 1 : 0) : ((c <= a && a <= b) ? 1 : 0)) +/* unpack vector for args */ +#define UNPACK2(a) ((a)[0]), ((a)[1]) +#define UNPACK3(a) ((a)[0]), ((a)[1]), ((a)[2]) +#define UNPACK4(a) ((a)[0]), ((a)[1]), ((a)[2]), ((a)[3]) +/* op may be '&' or '*' */ +#define UNPACK2OP(a, op) op((a)[0]), op((a)[1]) +#define UNPACK3OP(a, op) op((a)[0]), op((a)[1]), op((a)[2]) +#define UNPACK4OP(a, op) op((a)[0]), op((a)[1]), op((a)[2]), op((a)[3]) + /* array helpers */ #define ARRAY_LAST_ITEM(arr_start, arr_dtype, elem_size, tot) \ (arr_dtype *)((char *)arr_start + (elem_size * (tot - 1))) @@ -315,11 +324,13 @@ /*little macro so inline keyword works*/ #if defined(_MSC_VER) # define BLI_INLINE static __forceinline -#elif defined(__GNUC__) -# define BLI_INLINE static inline __attribute((always_inline)) #else -/* #warning "MSC/GNUC defines not found, inline non-functional" */ -# define BLI_INLINE static +# if (defined(__APPLE__) && defined(__ppc__)) +/* static inline __attribute__ here breaks osx ppc gcc42 build */ +# define BLI_INLINE static __attribute__((always_inline)) +# else +# define BLI_INLINE static inline __attribute__((always_inline)) +# endif #endif diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 6839f05bfbc..8a3b1c9675b 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -70,6 +70,7 @@ set(SRC intern/math_color_inline.c intern/math_geom.c intern/math_geom_inline.c + intern/math_interp.c intern/math_matrix.c intern/math_rotation.c intern/math_vector.c @@ -127,6 +128,7 @@ set(SRC BLI_math_color.h BLI_math_geom.h BLI_math_inline.h + BLI_math_interp.h BLI_math_matrix.h BLI_math_rotation.h BLI_math_vector.h @@ -173,3 +175,9 @@ if(WIN32) endif() blender_add_lib(bf_blenlib "${SRC}" "${INC}" "${INC_SYS}") + +if(MSVC) + # Quiet warning about inline math library files that do not export symbols. + # (normally you'd exclude from project, but we still want to see the files in MSVC) + set_target_properties(bf_blenlib PROPERTIES STATIC_LIBRARY_FLAGS /ignore:4221) +endif() diff --git a/source/blender/blenlib/PIL_time.h b/source/blender/blenlib/PIL_time.h index b8f895c5c82..c3e7e8486d9 100644 --- a/source/blender/blenlib/PIL_time.h +++ b/source/blender/blenlib/PIL_time.h @@ -20,7 +20,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Campbell Barton * * ***** END GPL LICENSE BLOCK ***** */ @@ -76,6 +76,17 @@ void PIL_sleep_ms(int ms); fflush(stdout); \ } (void)0 +/** + * Given some function/expression: + * TIMEIT_BENCH(some_function(), some_unique_description); + */ +#define TIMEIT_BENCH(expr, id) \ + { \ + TIMEIT_START(id); \ + (expr); \ + TIMEIT_END(id); \ + } (void)0 + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 0cae9bab531..c4094920c2a 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -178,7 +178,7 @@ void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp) return NULL; } -int BLI_ghash_haskey(GHash *gh, void *key) +int BLI_ghash_haskey(GHash *gh, const void *key) { unsigned int hash = gh->hashfp(key) % gh->nbuckets; Entry *e; diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 70617453eff..6cf167b8823 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -1117,7 +1117,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int data[j]->overlap = (BVHTreeOverlap *)malloc(sizeof(BVHTreeOverlap) * max_ii(tree1->totleaf, tree2->totleaf)); data[j]->tree1 = tree1; data[j]->tree2 = tree2; - data[j]->max_overlap = MAX2(tree1->totleaf, tree2->totleaf); + data[j]->max_overlap = max_ii(tree1->totleaf, tree2->totleaf); data[j]->i = 0; data[j]->start_axis = min_axis(tree1->start_axis, tree2->start_axis); data[j]->stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis); @@ -1410,7 +1410,7 @@ static float ray_nearest_hit(BVHRayCastData *data, const float bv[6]) * Based on Tactical Optimization of Ray/Box Intersection, by Graham Fyffe * [http://tog.acm.org/resources/RTNews/html/rtnv21n1.html#art9] * - * TODO this doens't has data->ray.radius in consideration */ + * TODO this doesn't take data->ray.radius into consideration */ static float fast_ray_nearest_hit(const BVHRayCastData *data, const BVHNode *node) { const float *bv = node->bv; diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c index 8ae2b941fa8..c650438a31e 100644 --- a/source/blender/blenlib/intern/bpath.c +++ b/source/blender/blenlib/intern/bpath.c @@ -64,6 +64,8 @@ #include "DNA_sequence_types.h" #include "DNA_sound_types.h" #include "DNA_text_types.h" +#include "DNA_material_types.h" +#include "DNA_node_types.h" #include "DNA_texture_types.h" #include "DNA_vfont_types.h" #include "DNA_scene_types.h" @@ -76,6 +78,7 @@ #include "BKE_font.h" #include "BKE_library.h" #include "BKE_main.h" +#include "BKE_node.h" #include "BKE_report.h" #include "BKE_sequencer.h" #include "BKE_image.h" /* so we can check the image's type */ @@ -382,7 +385,6 @@ static int rewrite_path_alloc(char **path, BPathVisitor visit_cb, const char *ab /* Run visitor function 'visit' on all paths contained in 'id'. */ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int flag, void *bpath_user_data) { - Image *ima; const char *absbase = (flag & BLI_BPATH_TRAVERSE_ABS) ? ID_BLEND_PATH(bmain, id) : NULL; if ((flag & BLI_BPATH_TRAVERSE_SKIP_LIBRARY) && id->lib) { @@ -391,6 +393,8 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int switch (GS(id->name)) { case ID_IM: + { + Image *ima; ima = (Image *)id; if (ima->packedfile == NULL || (flag & BLI_BPATH_TRAVERSE_SKIP_PACKED) == 0) { if (ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { @@ -398,15 +402,20 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int } } break; + } case ID_BR: { Brush *brush = (Brush *)id; if (brush->icon_filepath[0]) { rewrite_path_fixed(brush->icon_filepath, visit_cb, absbase, bpath_user_data); } + break; } - break; case ID_OB: + { + Object *ob = (Object *)id; + ModifierData *md; + ParticleSystem *psys; #define BPATH_TRAVERSE_POINTCACHE(ptcaches) \ { \ @@ -421,62 +430,56 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int } \ } (void)0 - - { - Object *ob = (Object *)id; - ModifierData *md; - ParticleSystem *psys; - - /* do via modifiers instead */ + /* do via modifiers instead */ #if 0 - if (ob->fluidsimSettings) { - rewrite_path_fixed(ob->fluidsimSettings->surfdataPath, visit_cb, absbase, bpath_user_data); - } + if (ob->fluidsimSettings) { + rewrite_path_fixed(ob->fluidsimSettings->surfdataPath, visit_cb, absbase, bpath_user_data); + } #endif - for (md = ob->modifiers.first; md; md = md->next) { - if (md->type == eModifierType_Fluidsim) { - FluidsimModifierData *fluidmd = (FluidsimModifierData *)md; - if (fluidmd->fss) { - rewrite_path_fixed(fluidmd->fss->surfdataPath, visit_cb, absbase, bpath_user_data); - } - } - else if (md->type == eModifierType_Smoke) { - SmokeModifierData *smd = (SmokeModifierData *)md; - if (smd->type & MOD_SMOKE_TYPE_DOMAIN) { - BPATH_TRAVERSE_POINTCACHE(smd->domain->ptcaches[0]); - } - } - else if (md->type == eModifierType_Cloth) { - ClothModifierData *clmd = (ClothModifierData *) md; - BPATH_TRAVERSE_POINTCACHE(clmd->ptcaches); - } - else if (md->type == eModifierType_Ocean) { - OceanModifierData *omd = (OceanModifierData *) md; - rewrite_path_fixed(omd->cachepath, visit_cb, absbase, bpath_user_data); + for (md = ob->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_Fluidsim) { + FluidsimModifierData *fluidmd = (FluidsimModifierData *)md; + if (fluidmd->fss) { + rewrite_path_fixed(fluidmd->fss->surfdataPath, visit_cb, absbase, bpath_user_data); } } + else if (md->type == eModifierType_Smoke) { + SmokeModifierData *smd = (SmokeModifierData *)md; + if (smd->type & MOD_SMOKE_TYPE_DOMAIN) { + BPATH_TRAVERSE_POINTCACHE(smd->domain->ptcaches[0]); + } + } + else if (md->type == eModifierType_Cloth) { + ClothModifierData *clmd = (ClothModifierData *) md; + BPATH_TRAVERSE_POINTCACHE(clmd->ptcaches); + } + else if (md->type == eModifierType_Ocean) { + OceanModifierData *omd = (OceanModifierData *) md; + rewrite_path_fixed(omd->cachepath, visit_cb, absbase, bpath_user_data); + } + } - if (ob->soft) { - BPATH_TRAVERSE_POINTCACHE(ob->soft->ptcaches); - } + if (ob->soft) { + BPATH_TRAVERSE_POINTCACHE(ob->soft->ptcaches); + } - for (psys = ob->particlesystem.first; psys; psys = psys->next) { - BPATH_TRAVERSE_POINTCACHE(psys->ptcaches); - } + for (psys = ob->particlesystem.first; psys; psys = psys->next) { + BPATH_TRAVERSE_POINTCACHE(psys->ptcaches); } #undef BPATH_TRAVERSE_POINTCACHE break; + } case ID_SO: { bSound *sound = (bSound *)id; if (sound->packedfile == NULL || (flag & BLI_BPATH_TRAVERSE_SKIP_PACKED) == 0) { rewrite_path_fixed(sound->name, visit_cb, absbase, bpath_user_data); } + break; } - break; case ID_TXT: if (((Text *)id)->name) { rewrite_path_alloc(&((Text *)id)->name, visit_cb, absbase, bpath_user_data); @@ -490,17 +493,49 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int rewrite_path_fixed(((VFont *)id)->name, visit_cb, absbase, bpath_user_data); } } + break; + } + case ID_MA: + { + Material *ma = (Material *)id; + bNodeTree *ntree = ma->nodetree; + + if (ntree) { + bNode *node; + + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_SCRIPT) { + NodeShaderScript *nss = (NodeShaderScript *)node->storage; + rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data); + } + } + } + break; + } + case ID_NT: + { + bNodeTree *ntree = (bNodeTree *)id; + bNode *node; + + if (ntree->type == NTREE_SHADER) { + /* same as lines above */ + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_SCRIPT) { + NodeShaderScript *nss = (NodeShaderScript *)node->storage; + rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data); + } + } + } + break; } - break; case ID_TE: { Tex *tex = (Tex *)id; if (tex->type == TEX_VOXELDATA && TEX_VD_IS_SOURCE_PATH(tex->vd->file_format)) { rewrite_path_fixed(tex->vd->source_path, visit_cb, absbase, bpath_user_data); } + break; } - break; - case ID_SCE: { Scene *scene = (Scene *)id; @@ -539,30 +574,30 @@ void BLI_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int } SEQ_END } + break; } - break; case ID_ME: { Mesh *me = (Mesh *)id; if (me->ldata.external) { rewrite_path_fixed(me->ldata.external->filename, visit_cb, absbase, bpath_user_data); } + break; } - break; case ID_LI: { Library *lib = (Library *)id; if (rewrite_path_fixed(lib->name, visit_cb, absbase, bpath_user_data)) { BKE_library_filepath_set(lib, lib->name); } + break; } - break; case ID_MC: { MovieClip *clip = (MovieClip *)id; rewrite_path_fixed(clip->name, visit_cb, absbase, bpath_user_data); + break; } - break; default: /* Nothing to do for other IDs that don't contain file paths. */ break; @@ -618,3 +653,73 @@ int BLI_bpath_relocate_visitor(void *pathbase_v, char *path_dst, const char *pat return FALSE; } } + + +/* -------------------------------------------------------------------- */ +/** + * Backup/Restore/Free functions, + * \note These functions assume the data won't chane order. + */ + +struct PathStore { + struct PathStore *next, *prev; +} PathStore; + +static int bpath_list_append(void *userdata, char *UNUSED(path_dst), const char *path_src) +{ + /* store the path and string in a single alloc */ + ListBase *ls = userdata; + size_t path_size = strlen(path_src) + 1; + struct PathStore *path_store = MEM_mallocN(sizeof(PathStore) + path_size, __func__); + char *filepath = (char *)(path_store + 1); + + memcpy(filepath, path_src, path_size); + BLI_addtail(ls, path_store); + return FALSE; +} + +static int bpath_list_restore(void *userdata, char *path_dst, const char *path_src) +{ + /* assume ls->first wont be NULL because the number of paths can't change! + * (if they do caller is wrong) */ + ListBase *ls = userdata; + struct PathStore *path_store = ls->first; + const char *filepath = (char *)(path_store + 1); + int ret; + + if (strcmp(path_src, filepath) == 0) { + ret = FALSE; + } + else { + BLI_strncpy(path_dst, filepath, FILE_MAX); + ret = TRUE; + } + + BLI_freelinkN(ls, path_store); + return ret; +} + +/* return ls_handle */ +void *BLI_bpath_list_backup(Main *bmain, const int flag) +{ + ListBase *ls = MEM_callocN(sizeof(ListBase), __func__); + + BLI_bpath_traverse_main(bmain, bpath_list_append, flag, ls); + + return ls; +} + +void BLI_bpath_list_restore(Main *bmain, const int flag, void *ls_handle) +{ + ListBase *ls = ls_handle; + + BLI_bpath_traverse_main(bmain, bpath_list_restore, flag, ls); +} + +void BLI_bpath_list_free(void *ls_handle) +{ + ListBase *ls = ls_handle; + BLI_assert(ls->first == NULL); /* assumes we were used */ + BLI_freelistN(ls); + MEM_freeN(ls); +} diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index f27da759482..b9866f9c6e6 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -27,6 +27,8 @@ * \ingroup bli */ +#ifndef __MATH_BASE_INLINE_C__ +#define __MATH_BASE_INLINE_C__ #include #include @@ -35,9 +37,6 @@ #include "BLI_math.h" -#ifndef __MATH_BASE_INLINE_C__ -#define __MATH_BASE_INLINE_C__ - /* A few small defines. Keep'em local! */ #define SMALL_NUMBER 1.e-8f @@ -139,6 +138,25 @@ MINLINE int power_of_2_min_i(int n) return n; } +MINLINE unsigned int highest_order_bit_i(unsigned int n) +{ + n |= (n >> 1); + n |= (n >> 2); + n |= (n >> 4); + n |= (n >> 8); + n |= (n >> 16); + return n - (n >> 1); +} + +MINLINE unsigned short highest_order_bit_s(unsigned short n) +{ + n |= (n >> 1); + n |= (n >> 2); + n |= (n >> 4); + n |= (n >> 8); + return n - (n >> 1); +} + MINLINE float min_ff(float a, float b) { return (a < b) ? a : b; diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c index f520b2318e5..4c8bd43ef73 100644 --- a/source/blender/blenlib/intern/math_color_inline.c +++ b/source/blender/blenlib/intern/math_color_inline.c @@ -164,7 +164,11 @@ MINLINE void linearrgb_to_srgb_ushort4_predivide(unsigned short srgb[4], const f for (i = 0; i < 3; ++i) { t = linear[i] * inv_alpha; - srgb[i] = (t < 1.0f) ? (unsigned short) (to_srgb_table_lookup(t) * alpha) : FTOUSHORT(linearrgb_to_srgb(t) * alpha); + srgb[i] = (t <= 1.0f) ? + /* warning - converts: float -> short -> float -> short */ + (unsigned short) (to_srgb_table_lookup(t) * alpha) : + /* if FTOUSHORT was an inline function this could be done less confusingly */ + ((t = linearrgb_to_srgb(t) * alpha), FTOUSHORT(t)); } srgb[3] = FTOUSHORT(linear[3]); diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index e10229f11da..74abd7e8c7e 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -1453,9 +1453,16 @@ float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3 float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2]) { float h[2], u[2]; + float dot; sub_v2_v2v2(u, l2, l1); sub_v2_v2v2(h, p, l1); +#if 0 return (dot_v2v2(u, h) / dot_v2v2(u, u)); +#else + /* better check for zero */ + dot = dot_v2v2(u, u); + return (dot != 0.0f) ? (dot_v2v2(u, h) / dot) : 0.0f; +#endif } /* ensure the distance between these points is no greater then 'dist' @@ -2399,6 +2406,33 @@ void resolve_quad_uv(float r_uv[2], const float st[2], const float st0[2], const #undef IS_ZERO +/* reverse of the functions above */ +void interp_bilinear_quad_v3(float data[4][3], float u, float v, float res[3]) +{ + float vec[3]; + + copy_v3_v3(res, data[0]); + mul_v3_fl(res, (1 - u) * (1 - v)); + copy_v3_v3(vec, data[1]); + mul_v3_fl(vec, u * (1 - v)); add_v3_v3(res, vec); + copy_v3_v3(vec, data[2]); + mul_v3_fl(vec, u * v); add_v3_v3(res, vec); + copy_v3_v3(vec, data[3]); + mul_v3_fl(vec, (1 - u) * v); add_v3_v3(res, vec); +} + +void interp_barycentric_tri_v3(float data[3][3], float u, float v, float res[3]) +{ + float vec[3]; + + copy_v3_v3(res, data[0]); + mul_v3_fl(res, u); + copy_v3_v3(vec, data[1]); + mul_v3_fl(vec, v); add_v3_v3(res, vec); + copy_v3_v3(vec, data[2]); + mul_v3_fl(vec, 1.0f - u - v); add_v3_v3(res, vec); +} + /***************************** View & Projection *****************************/ void orthographic_m4(float matrix[][4], const float left, const float right, const float bottom, const float top, diff --git a/source/blender/blenlib/intern/math_geom_inline.c b/source/blender/blenlib/intern/math_geom_inline.c index 01585c93bc8..ba9770e1bd1 100644 --- a/source/blender/blenlib/intern/math_geom_inline.c +++ b/source/blender/blenlib/intern/math_geom_inline.c @@ -27,11 +27,12 @@ * \ingroup bli */ +#ifndef __MATH_GEOM_INLINE_C__ +#define __MATH_GEOM_INLINE_C__ #include "BLI_math.h" -#ifndef __MATH_GEOM_INLINE_C__ -#define __MATH_GEOM_INLINE_C__ +#include /****************************** Spherical Harmonics **************************/ diff --git a/source/blender/blenlib/intern/math_interp.c b/source/blender/blenlib/intern/math_interp.c new file mode 100644 index 00000000000..5a9e8244a46 --- /dev/null +++ b/source/blender/blenlib/intern/math_interp.c @@ -0,0 +1,351 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 by Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#include + +#include "BLI_math.h" + +/************************************************************************** + * INTERPOLATIONS + * + * Reference and docs: + * http://wiki.blender.org/index.php/User:Damiles#Interpolations_Algorithms + ***************************************************************************/ + +/* BICUBIC Interpolation functions + * More info: http://wiki.blender.org/index.php/User:Damiles#Bicubic_pixel_interpolation + * function assumes out to be zero'ed, only does RGBA */ + +static float P(float k) +{ + float p1, p2, p3, p4; + p1 = MAX2(k + 2.0f, 0); + p2 = MAX2(k + 1.0f, 0); + p3 = MAX2(k, 0); + p4 = MAX2(k - 1.0f, 0); + return (float)(1.0f / 6.0f) * (p1 * p1 * p1 - 4.0f * p2 * p2 * p2 + 6.0f * p3 * p3 * p3 - 4.0f * p4 * p4 * p4); +} + + +#if 0 +/* older, slower function, works the same as above */ +static float P(float k) +{ + return (float)(1.0f / 6.0f) * (pow(MAX2(k + 2.0f, 0), 3.0f) - 4.0f * pow(MAX2(k + 1.0f, 0), 3.0f) + 6.0f * pow(MAX2(k, 0), 3.0f) - 4.0f * pow(MAX2(k - 1.0f, 0), 3.0f)); +} +#endif + +static void vector_from_float(const float *data, float vector[4], int components) +{ + if (components == 1) { + vector[0] = data[0]; + } + else if (components == 3) { + copy_v3_v3(vector, data); + } + else { + copy_v4_v4(vector, data); + } +} + +static void vector_from_byte(const unsigned char *data, float vector[4], int components) +{ + if (components == 1) { + vector[0] = data[0]; + } + else if (components == 3) { + vector[0] = data[0]; + vector[1] = data[1]; + vector[2] = data[2]; + } + else { + vector[0] = data[0]; + vector[1] = data[1]; + vector[2] = data[2]; + vector[3] = data[3]; + } +} + +/* BICUBIC INTERPOLATION */ +BLI_INLINE void bicubic_interpolation(const unsigned char *byte_buffer, const float *float_buffer, + unsigned char *byte_output, float *float_output, int width, int height, + int components, float u, float v) +{ + int i, j, n, m, x1, y1; + float a, b, w, wx, wy[4], out[4]; + + /* sample area entirely outside image? */ + if (ceil(u) < 0 || floor(u) > width - 1 || ceil(v) < 0 || floor(v) > height - 1) { + return; + } + + i = (int)floor(u); + j = (int)floor(v); + a = u - i; + b = v - j; + + zero_v4(out); + +/* Optimized and not so easy to read */ + + /* avoid calling multiple times */ + wy[0] = P(b - (-1)); + wy[1] = P(b - 0); + wy[2] = P(b - 1); + wy[3] = P(b - 2); + + for (n = -1; n <= 2; n++) { + x1 = i + n; + CLAMP(x1, 0, width - 1); + wx = P(n - a); + for (m = -1; m <= 2; m++) { + float data[4]; + + y1 = j + m; + CLAMP(y1, 0, height - 1); + /* normally we could do this */ + /* w = P(n-a) * P(b-m); */ + /* except that would call P() 16 times per pixel therefor pow() 64 times, better precalc these */ + w = wx * wy[m + 1]; + + if (float_output) { + const float *float_data = float_buffer + width * y1 * components + components * x1; + + vector_from_float(float_data, data, components); + } + else { + const unsigned char *byte_data = byte_buffer + width * y1 * components + components * x1; + + vector_from_byte(byte_data, data, components); + } + + if (components == 1) { + out[0] += data[0] * w; + } + else if (components == 3) { + out[0] += data[0] * w; + out[1] += data[1] * w; + out[2] += data[2] * w; + } + else { + out[0] += data[0] * w; + out[1] += data[1] * w; + out[2] += data[2] * w; + out[3] += data[3] * w; + } + } + } + +/* Done with optimized part */ + +#if 0 + /* older, slower function, works the same as above */ + for (n = -1; n <= 2; n++) { + for (m = -1; m <= 2; m++) { + x1 = i + n; + y1 = j + m; + if (x1 > 0 && x1 < width && y1 > 0 && y1 < height) { + float data[4]; + + if (float_output) { + const float *float_data = float_buffer + width * y1 * components + components * x1; + + vector_from_float(float_data, data, components); + } + else { + const unsigned char *byte_data = byte_buffer + width * y1 * components + components * x1; + + vector_from_byte(byte_data, data, components); + } + + if (components == 1) { + out[0] += data[0] * P(n - a) * P(b - m); + } + else if (components == 3) { + out[0] += data[0] * P(n - a) * P(b - m); + out[1] += data[1] * P(n - a) * P(b - m); + out[2] += data[2] * P(n - a) * P(b - m); + } + else { + out[0] += data[0] * P(n - a) * P(b - m); + out[1] += data[1] * P(n - a) * P(b - m); + out[2] += data[2] * P(n - a) * P(b - m); + out[3] += data[3] * P(n - a) * P(b - m); + } + } + } + } +#endif + + if (float_output) { + if (components == 1) { + float_output[0] = out[0]; + } + else if (components == 3) { + copy_v3_v3(float_output, out); + } + else { + copy_v4_v4(float_output, out); + } + } + else { + if (components == 1) { + byte_output[0] = out[0]; + } + else if (components == 3) { + byte_output[0] = out[0]; + byte_output[1] = out[1]; + byte_output[2] = out[2]; + } + else { + byte_output[0] = out[0]; + byte_output[1] = out[1]; + byte_output[2] = out[2]; + byte_output[3] = out[3]; + } + } +} + +void BLI_bicubic_interpolation_fl(const float *buffer, float *output, int width, int height, + int components, float u, float v) +{ + bicubic_interpolation(NULL, buffer, NULL, output, width, height, components, u, v); +} + +void BLI_bicubic_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, + int components, float u, float v) +{ + bicubic_interpolation(buffer, NULL, output, NULL, width, height, components, u, v); +} + +/* BILINEAR INTERPOLATION */ +BLI_INLINE void bilinear_interpolation(const unsigned char *byte_buffer, const float *float_buffer, + unsigned char *byte_output, float *float_output, int width, int height, + int components, float u, float v) +{ + float a, b; + float a_b, ma_b, a_mb, ma_mb; + int y1, y2, x1, x2; + + /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ + + x1 = (int)floor(u); + x2 = (int)ceil(u); + y1 = (int)floor(v); + y2 = (int)ceil(v); + + /* sample area entirely outside image? */ + if (x2 < 0 || x1 > width - 1 || y2 < 0 || y1 > height - 1) { + return; + } + + if (float_output) { + const float *row1, *row2, *row3, *row4; + float empty[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + /* sample including outside of edges of image */ + if (x1 < 0 || y1 < 0) row1 = empty; + else row1 = float_buffer + width * y1 * components + components * x1; + + if (x1 < 0 || y2 > height - 1) row2 = empty; + else row2 = float_buffer + width * y2 * components + components * x1; + + if (x2 > width - 1 || y1 < 0) row3 = empty; + else row3 = float_buffer + width * y1 * components + components * x2; + + if (x2 > width - 1 || y2 > height - 1) row4 = empty; + else row4 = float_buffer + width * y2 * components + components * x2; + + a = u - floorf(u); + b = v - floorf(v); + a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); + + if (components == 1) { + float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + } + else if (components == 3) { + float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + float_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + float_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + } + else { + float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + float_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + float_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + float_output[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; + } + } + else { + const unsigned char *row1, *row2, *row3, *row4; + unsigned char empty[4] = {0, 0, 0, 0}; + + /* sample including outside of edges of image */ + if (x1 < 0 || y1 < 0) row1 = empty; + else row1 = byte_buffer + width * y1 * components + components * x1; + + if (x1 < 0 || y2 > height - 1) row2 = empty; + else row2 = byte_buffer + width * y2 * components + components * x1; + + if (x2 > width - 1 || y1 < 0) row3 = empty; + else row3 = byte_buffer + width * y1 * components + components * x2; + + if (x2 > width - 1 || y2 > height - 1) row4 = empty; + else row4 = byte_buffer + width * y2 * components + components * x2; + + a = u - floorf(u); + b = v - floorf(v); + a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); + + if (components == 1) { + byte_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + } + else if (components == 3) { + byte_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + byte_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + byte_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + } + else { + byte_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + byte_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + byte_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + byte_output[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; + } + } +} + +void BLI_bilinear_interpolation_fl(const float *buffer, float *output, int width, int height, + int components, float u, float v) +{ + bilinear_interpolation(NULL, buffer, NULL, output, width, height, components, u, v); +} + +void BLI_bilinear_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, + int components, float u, float v) +{ + bilinear_interpolation(buffer, NULL, output, NULL, width, height, components, u, v); +} diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index f622a5ace35..38214f9c6b0 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -504,6 +504,51 @@ void sub_m4_m4m4(float m1[][4], float m2[][4], float m3[][4]) m1[i][j] = m2[i][j] - m3[i][j]; } +/* why not make this a standard part of the API? */ +static float determinant_m3_local(float m[3][3]) +{ + return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) - + m[1][0] * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) + + m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1])); +} + +int invert_m3_ex(float m[3][3], const float epsilon) +{ + float tmp[3][3]; + int success; + + success = invert_m3_m3_ex(tmp, m, epsilon); + copy_m3_m3(m, tmp); + + return success; +} + +int invert_m3_m3_ex(float m1[3][3], float m2[3][3], const float epsilon) +{ + float det; + int a, b, success; + + BLI_assert(epsilon >= 0.0f); + + /* calc adjoint */ + adjoint_m3_m3(m1, m2); + + /* then determinant old matrix! */ + det = determinant_m3_local(m2); + + success = (fabsf(det) > epsilon); + + if (LIKELY(det != 0.0f)) { + det = 1.0f / det; + for (a = 0; a < 3; a++) { + for (b = 0; b < 3; b++) { + m1[a][b] *= det; + } + } + } + return success; +} + int invert_m3(float m[3][3]) { float tmp[3][3]; @@ -524,17 +569,16 @@ int invert_m3_m3(float m1[3][3], float m2[3][3]) adjoint_m3_m3(m1, m2); /* then determinant old matrix! */ - det = (m2[0][0] * (m2[1][1] * m2[2][2] - m2[1][2] * m2[2][1]) - - m2[1][0] * (m2[0][1] * m2[2][2] - m2[0][2] * m2[2][1]) + - m2[2][0] * (m2[0][1] * m2[1][2] - m2[0][2] * m2[1][1])); + det = determinant_m3_local(m2); - success = (det != 0); + success = (det != 0.0f); - if (det == 0) det = 1; - det = 1 / det; - for (a = 0; a < 3; a++) { - for (b = 0; b < 3; b++) { - m1[a][b] *= det; + if (LIKELY(det != 0.0f)) { + det = 1.0f / det; + for (a = 0; a < 3; a++) { + for (b = 0; b < 3; b++) { + m1[a][b] *= det; + } } } diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index b0c4724e1ec..3069542107e 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -84,7 +84,7 @@ void mul_qt_qtqt(float q[4], const float q1[4], const float q2[4]) * \note: * Assumes a unit quaternion? * - * in fact not, but you may wan't to use a unit quat, read on... + * in fact not, but you may want to use a unit quat, read on... * * Shortcut for 'q v q*' when \a v is actually a quaternion. * This removes the need for converting a vector to a quaternion, diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 976895fe6fc..812e2b3e63d 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -115,6 +115,13 @@ void mid_v2_v2v2(float v[2], const float v1[2], const float v2[2]) v[1] = 0.5f * (v1[1] + v2[1]); } +void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3]) +{ + v[0] = (v1[0] + v2[0] + v3[0]) / 3.0f; + v[1] = (v1[1] + v2[1] + v3[1]) / 3.0f; + v[2] = (v1[2] + v2[2] + v3[2]) / 3.0f; +} + /********************************** Angles ***********************************/ /* Return the angle in radians between vecs 1-2 and 2-3 in radians @@ -201,6 +208,13 @@ float angle_signed_v2v2(const float v1[2], const float v2[2]) float angle_normalized_v3v3(const float v1[3], const float v2[3]) { + /* double check they are normalized */ +#ifdef DEBUG + float test; + BLI_assert(fabsf((test = len_squared_v3(v1)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); + BLI_assert(fabsf((test = len_squared_v3(v2)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); +#endif + /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */ if (dot_v3v3(v1, v2) < 0.0f) { float vec[3]; @@ -217,6 +231,13 @@ float angle_normalized_v3v3(const float v1[3], const float v2[3]) float angle_normalized_v2v2(const float v1[2], const float v2[2]) { + /* double check they are normalized */ +#ifdef DEBUG + float test; + BLI_assert(fabsf((test = len_squared_v2(v1)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); + BLI_assert(fabsf((test = len_squared_v2(v2)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); +#endif + /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */ if (dot_v2v2(v1, v2) < 0.0f) { float vec[2]; @@ -401,6 +422,12 @@ void rotate_normalized_v3_v3v3fl(float r[3], const float p[3], const float axis[ const float costheta = cos(angle); const float sintheta = sin(angle); + /* double check they are normalized */ +#ifdef DEBUG + float test; + BLI_assert(fabsf((test = len_squared_v3(axis)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); +#endif + r[0] = ((costheta + (1 - costheta) * axis[0] * axis[0]) * p[0]) + (((1 - costheta) * axis[0] * axis[1] - axis[2] * sintheta) * p[1]) + (((1 - costheta) * axis[0] * axis[2] + axis[1] * sintheta) * p[2]); diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index 191b0e16025..3ede8636aa5 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -27,12 +27,11 @@ * \ingroup bli */ - -#include "BLI_math.h" - #ifndef __MATH_VECTOR_INLINE_C__ #define __MATH_VECTOR_INLINE_C__ +#include "BLI_math.h" + /********************************** Init *************************************/ MINLINE void zero_v2(float r[2]) diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c index fb33d7ce127..f37e1e03f39 100644 --- a/source/blender/blenlib/intern/noise.c +++ b/source/blender/blenlib/intern/noise.c @@ -398,7 +398,8 @@ static float orgBlenderNoise(float x, float y, float z) h = hashvectf + 3 * hash[b21 + b11]; n += i * (h[0] * jx + h[1] * jy + h[2] * jz); - if (n < 0.0f) n = 0.0f; else if (n > 1.0f) n = 1.0f; + if (n < 0.0f) n = 0.0f; + else if (n > 1.0f) n = 1.0f; return n; } @@ -456,16 +457,50 @@ float BLI_turbulence1(float noisesize, float x, float y, float z, int nr) /* ********************* FROM PERLIN HIMSELF: ******************** */ -static char p[512 + 2] = { - 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC, 0x3F, 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, 0x80, 0xB5, 0x40, 0x13, 0xB2, 0x22, 0x7E, 0x57, - 0xBC, 0x7F, 0x6B, 0x9D, 0x86, 0x4C, 0xC8, 0xDB, 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, 0xCD, 0xB3, 0x7A, 0xBB, 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, 0xB, 0x96, 0xD3, 0x9E, 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, 0x24, 0x72, 0x49, 0x8C, 0x90, 0x4B, 0x84, 0x34, 0x38, 0xAB, 0x78, 0xCA, 0x1F, 0x1, 0xD7, 0x93, 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, - 0xBF, 0x33, 0x9C, 0x5F, 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, 0x7B, 0x46, 0x15, 0x30, 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, 0x62, 0xAC, 0x4F, 0xC2, 0xC0, 0xE, 0xB1, 0x23, 0xA7, 0xDF, 0x47, 0xB0, 0x77, 0x69, 0x5, 0xE9, 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, 0x56, 0xEF, 0x12, 0xA5, 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, 0xB9, 0xCE, 0xC9, 0x8D, - 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, 0xA, 0xCC, 0xD2, 0xE8, 0x43, 0x3D, 0x70, 0xB7, 0x2, 0x7D, 0x99, 0xD8, 0xD, 0x60, 0x8A, 0x4, 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, 0x29, 0xA6, 0xC5, 0xE3, 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, 0x52, 0x2D, 0x21, 0xAD, 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, 0x45, 0x39, 0xCF, 0x75, 0xA4, 0x88, 0xFB, 0x5D, - 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC, 0x3F, 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, 0x80, 0xB5, 0x40, 0x13, 0xB2, 0x22, 0x7E, 0x57, - 0xBC, 0x7F, 0x6B, 0x9D, 0x86, 0x4C, 0xC8, 0xDB, 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, 0xCD, 0xB3, 0x7A, 0xBB, 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, 0xB, 0x96, 0xD3, 0x9E, 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, 0x24, 0x72, 0x49, 0x8C, 0x90, 0x4B, 0x84, 0x34, 0x38, 0xAB, 0x78, 0xCA, 0x1F, 0x1, 0xD7, 0x93, 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, - 0xBF, 0x33, 0x9C, 0x5F, 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, 0x7B, 0x46, 0x15, 0x30, 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, 0x62, 0xAC, 0x4F, 0xC2, 0xC0, 0xE, 0xB1, 0x23, 0xA7, 0xDF, 0x47, 0xB0, 0x77, 0x69, 0x5, 0xE9, 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, 0x56, 0xEF, 0x12, 0xA5, 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, 0xB9, 0xCE, 0xC9, 0x8D, - 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, 0xA, 0xCC, 0xD2, 0xE8, 0x43, 0x3D, 0x70, 0xB7, 0x2, 0x7D, 0x99, 0xD8, 0xD, 0x60, 0x8A, 0x4, 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, 0x29, 0xA6, 0xC5, 0xE3, 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, 0x52, 0x2D, 0x21, 0xAD, 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, 0x45, 0x39, 0xCF, 0x75, 0xA4, 0x88, 0xFB, 0x5D, - 0xA2, 0xA0 +static const char p[512 + 2] = { + 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, 0x67, 0x28, + 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC, 0x3F, 0x3A, 0x82, 0x35, 0x4D, + 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, 0xD1, 0x59, 0xF4, 0x8, + 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, + 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, 0x80, 0xB5, 0x40, 0x13, + 0xB2, 0x22, 0x7E, 0x57, 0xBC, 0x7F, 0x6B, 0x9D, 0x86, 0x4C, 0xC8, 0xDB, + 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, 0xCD, 0xB3, 0x7A, 0xBB, + 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, 0xB, 0x96, 0xD3, 0x9E, + 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, 0x24, 0x72, 0x49, 0x8C, + 0x90, 0x4B, 0x84, 0x34, 0x38, 0xAB, 0x78, 0xCA, 0x1F, 0x1, 0xD7, 0x93, + 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, 0xBF, 0x33, 0x9C, 0x5F, + 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, 0x7B, 0x46, 0x15, 0x30, + 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, 0x62, 0xAC, 0x4F, 0xC2, + 0xC0, 0xE, 0xB1, 0x23, 0xA7, 0xDF, 0x47, 0xB0, 0x77, 0x69, 0x5, 0xE9, + 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, 0x56, 0xEF, 0x12, 0xA5, + 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, 0xB9, 0xCE, 0xC9, 0x8D, + 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, 0xA, 0xCC, 0xD2, 0xE8, + 0x43, 0x3D, 0x70, 0xB7, 0x2, 0x7D, 0x99, 0xD8, 0xD, 0x60, 0x8A, 0x4, + 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, 0x29, 0xA6, 0xC5, 0xE3, + 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, 0x52, 0x2D, 0x21, 0xAD, + 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, 0x45, 0x39, 0xCF, 0x75, + 0xA4, 0x88, 0xFB, 0x5D, 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, + 0xF3, 0x1C, 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC, 0x3F, + 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, + 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, + 0xF2, 0x8F, 0x18, 0xC7, 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, + 0x80, 0xB5, 0x40, 0x13, 0xB2, 0x22, 0x7E, 0x57, 0xBC, 0x7F, 0x6B, 0x9D, + 0x86, 0x4C, 0xC8, 0xDB, 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, + 0xCD, 0xB3, 0x7A, 0xBB, 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, + 0xB, 0x96, 0xD3, 0x9E, 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, + 0x24, 0x72, 0x49, 0x8C, 0x90, 0x4B, 0x84, 0x34, 0x38, 0xAB, 0x78, 0xCA, + 0x1F, 0x1, 0xD7, 0x93, 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, + 0xBF, 0x33, 0x9C, 0x5F, 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, + 0x7B, 0x46, 0x15, 0x30, 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, + 0x62, 0xAC, 0x4F, 0xC2, 0xC0, 0xE, 0xB1, 0x23, 0xA7, 0xDF, 0x47, 0xB0, + 0x77, 0x69, 0x5, 0xE9, 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, + 0x56, 0xEF, 0x12, 0xA5, 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, + 0xB9, 0xCE, 0xC9, 0x8D, 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, + 0xA, 0xCC, 0xD2, 0xE8, 0x43, 0x3D, 0x70, 0xB7, 0x2, 0x7D, 0x99, 0xD8, + 0xD, 0x60, 0x8A, 0x4, 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, + 0x29, 0xA6, 0xC5, 0xE3, 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, + 0x52, 0x2D, 0x21, 0xAD, 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, + 0x45, 0x39, 0xCF, 0x75, 0xA4, 0x88, 0xFB, 0x5D, 0xA2, 0xA0 }; @@ -1856,7 +1891,8 @@ float mg_RidgedMultiFractal(float x, float y, float z, float H, float lacunarity y *= lacunarity; z *= lacunarity; weight = signal * gain; - if (weight > 1.0f) weight = 1.0f; else if (weight < 0.0f) weight = 0.0f; + if (weight > 1.0f) weight = 1.0f; + else if (weight < 0.0f) weight = 0.0f; signal = offset - fabsf(noisefunc(x, y, z)); signal *= signal; signal *= weight; diff --git a/source/blender/blenlib/intern/pbvh.c b/source/blender/blenlib/intern/pbvh.c index 7637c60ec16..6fa6d86589f 100644 --- a/source/blender/blenlib/intern/pbvh.c +++ b/source/blender/blenlib/intern/pbvh.c @@ -1707,11 +1707,22 @@ void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3], } } -void BLI_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, void **gridfaces) +void BLI_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, void **gridfaces, + DMFlagMat *flagmats, BLI_bitmap *grid_hidden) { + int a; + bvh->grids = grids; bvh->gridadj = gridadj; bvh->gridfaces = gridfaces; + + if (flagmats != bvh->grid_flag_mats || bvh->grid_hidden != grid_hidden) { + bvh->grid_flag_mats = flagmats; + bvh->grid_hidden = grid_hidden; + + for (a = 0; a < bvh->totnode; ++a) + BLI_pbvh_node_mark_rebuild_draw(&bvh->nodes[a]); + } } float (*BLI_pbvh_get_vertCos(PBVH * pbvh))[3] diff --git a/source/blender/blenlib/intern/quadric.c b/source/blender/blenlib/intern/quadric.c index bb39cb61e78..b06534d282a 100644 --- a/source/blender/blenlib/intern/quadric.c +++ b/source/blender/blenlib/intern/quadric.c @@ -107,18 +107,13 @@ float BLI_quadric_evaluate(const Quadric *q, const float v[3]) q->d2); } -int BLI_quadric_optimize(const Quadric *q, float v[3]) +int BLI_quadric_optimize(const Quadric *q, float v[3], const float epsilon) { float m[3][3]; - float det; BLI_quadric_to_tensor_m3(q, m); - det = determinant_m3(m[0][0], m[0][1], m[0][2], - m[1][0], m[1][1], m[1][2], - m[2][0], m[2][1], m[2][2]); - if (fabsf(det) > FLT_EPSILON) { - invert_m3(m); + if (invert_m3_ex(m, epsilon)) { BLI_quadric_to_vector_v3(q, v); mul_m3_v3(m, v); negate_v3(v); diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index 362a87782c6..defe500cb21 100644 --- a/source/blender/blenlib/intern/scanfill.c +++ b/source/blender/blenlib/intern/scanfill.c @@ -503,8 +503,7 @@ static void splitlist(ScanFillContext *sf_ctx, ListBase *tempve, ListBase *tempe } } - -static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf) +static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag) { ScanFillVertLink *sc = NULL, *sc1; ScanFillVert *eve, *v1, *v2, *v3; @@ -530,26 +529,28 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf) #endif /* STEP 0: remove zero sized edges */ - eed = sf_ctx->filledgebase.first; - while (eed) { - if (equals_v2v2(eed->v1->xy, eed->v2->xy)) { - if (eed->v1->f == SF_VERT_ZERO_LEN && eed->v2->f != SF_VERT_ZERO_LEN) { - eed->v2->f = SF_VERT_ZERO_LEN; - eed->v2->tmp.v = eed->v1->tmp.v; - } - else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f != SF_VERT_ZERO_LEN) { - eed->v1->f = SF_VERT_ZERO_LEN; - eed->v1->tmp.v = eed->v2->tmp.v; - } - else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f == SF_VERT_ZERO_LEN) { - eed->v1->tmp.v = eed->v2->tmp.v; - } - else { - eed->v2->f = SF_VERT_ZERO_LEN; - eed->v2->tmp.v = eed->v1; + if (flag & BLI_SCANFILL_CALC_REMOVE_DOUBLES) { + eed = sf_ctx->filledgebase.first; + while (eed) { + if (equals_v2v2(eed->v1->xy, eed->v2->xy)) { + if (eed->v1->f == SF_VERT_ZERO_LEN && eed->v2->f != SF_VERT_ZERO_LEN) { + eed->v2->f = SF_VERT_ZERO_LEN; + eed->v2->tmp.v = eed->v1->tmp.v; + } + else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f != SF_VERT_ZERO_LEN) { + eed->v1->f = SF_VERT_ZERO_LEN; + eed->v1->tmp.v = eed->v2->tmp.v; + } + else if (eed->v2->f == SF_VERT_ZERO_LEN && eed->v1->f == SF_VERT_ZERO_LEN) { + eed->v1->tmp.v = eed->v2->tmp.v; + } + else { + eed->v2->f = SF_VERT_ZERO_LEN; + eed->v2->tmp.v = eed->v1; + } } + eed = eed->next; } - eed = eed->next; } /* STEP 1: make using FillVert and FillEdge lists a sorted @@ -572,28 +573,42 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf) qsort(sf_ctx->_scdata, verts, sizeof(ScanFillVertLink), vergscdata); - eed = sf_ctx->filledgebase.first; - while (eed) { - nexted = eed->next; - BLI_remlink(&sf_ctx->filledgebase, eed); - /* This code is for handling zero-length edges that get - * collapsed in step 0. It was removed for some time to - * fix trunk bug #4544, so if that comes back, this code - * may need some work, or there will have to be a better - * fix to #4544. */ - if (eed->v1->f == SF_VERT_ZERO_LEN) { - v1 = eed->v1; - while ((eed->v1->f == SF_VERT_ZERO_LEN) && (eed->v1->tmp.v != v1) && (eed->v1 != eed->v1->tmp.v)) - eed->v1 = eed->v1->tmp.v; + if (flag & BLI_SCANFILL_CALC_REMOVE_DOUBLES) { + for (eed = sf_ctx->filledgebase.first; eed; eed = nexted) { + nexted = eed->next; + BLI_remlink(&sf_ctx->filledgebase, eed); + /* This code is for handling zero-length edges that get + * collapsed in step 0. It was removed for some time to + * fix trunk bug #4544, so if that comes back, this code + * may need some work, or there will have to be a better + * fix to #4544. + * + * warning, this can hang on un-ordered edges, see: [#33281] + * for now disable 'BLI_SCANFILL_CALC_REMOVE_DOUBLES' for ngons. + */ + if (eed->v1->f == SF_VERT_ZERO_LEN) { + v1 = eed->v1; + while ((eed->v1->f == SF_VERT_ZERO_LEN) && (eed->v1->tmp.v != v1) && (eed->v1 != eed->v1->tmp.v)) + eed->v1 = eed->v1->tmp.v; + } + if (eed->v2->f == SF_VERT_ZERO_LEN) { + v2 = eed->v2; + while ((eed->v2->f == SF_VERT_ZERO_LEN) && (eed->v2->tmp.v != v2) && (eed->v2 != eed->v2->tmp.v)) + eed->v2 = eed->v2->tmp.v; + } + if (eed->v1 != eed->v2) { + addedgetoscanlist(sf_ctx, eed, verts); + } } - if (eed->v2->f == SF_VERT_ZERO_LEN) { - v2 = eed->v2; - while ((eed->v2->f == SF_VERT_ZERO_LEN) && (eed->v2->tmp.v != v2) && (eed->v2 != eed->v2->tmp.v)) - eed->v2 = eed->v2->tmp.v; + } + else { + for (eed = sf_ctx->filledgebase.first; eed; eed = nexted) { + nexted = eed->next; + BLI_remlink(&sf_ctx->filledgebase, eed); + if (eed->v1 != eed->v2) { + addedgetoscanlist(sf_ctx, eed, verts); + } } - if (eed->v1 != eed->v2) addedgetoscanlist(sf_ctx, eed, verts); - - eed = nexted; } #if 0 sc = scdata; @@ -775,12 +790,12 @@ int BLI_scanfill_begin(ScanFillContext *sf_ctx) return 1; } -int BLI_scanfill_calc(ScanFillContext *sf_ctx, const short do_quad_tri_speedup) +int BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag) { - return BLI_scanfill_calc_ex(sf_ctx, do_quad_tri_speedup, NULL); + return BLI_scanfill_calc_ex(sf_ctx, flag, NULL); } -int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedup, const float nor_proj[3]) +int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float nor_proj[3]) { /* * - fill works with its own lists, so create that first (no faces!) @@ -810,30 +825,32 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedu a += 1; } - if (do_quad_tri_speedup && (a == 3)) { - eve = sf_ctx->fillvertbase.first; + if (flag & BLI_SCANFILL_CALC_QUADTRI_FASTPATH) { + if (a == 3) { + eve = sf_ctx->fillvertbase.first; - addfillface(sf_ctx, eve, eve->next, eve->next->next); - return 1; - } - else if (do_quad_tri_speedup && (a == 4)) { - float vec1[3], vec2[3]; - - eve = sf_ctx->fillvertbase.first; - /* no need to check 'eve->next->next->next' is valid, already counted */ - /* use shortest diagonal for quad */ - sub_v3_v3v3(vec1, eve->co, eve->next->next->co); - sub_v3_v3v3(vec2, eve->next->co, eve->next->next->next->co); - - if (dot_v3v3(vec1, vec1) < dot_v3v3(vec2, vec2)) { addfillface(sf_ctx, eve, eve->next, eve->next->next); - addfillface(sf_ctx, eve->next->next, eve->next->next->next, eve); + return 1; } - else { - addfillface(sf_ctx, eve->next, eve->next->next, eve->next->next->next); - addfillface(sf_ctx, eve->next->next->next, eve, eve->next); + else if (a == 4) { + float vec1[3], vec2[3]; + + eve = sf_ctx->fillvertbase.first; + /* no need to check 'eve->next->next->next' is valid, already counted */ + /* use shortest diagonal for quad */ + sub_v3_v3v3(vec1, eve->co, eve->next->next->co); + sub_v3_v3v3(vec2, eve->next->co, eve->next->next->next->co); + + if (dot_v3v3(vec1, vec1) < dot_v3v3(vec2, vec2)) { + addfillface(sf_ctx, eve, eve->next, eve->next->next); + addfillface(sf_ctx, eve->next->next, eve->next->next->next, eve); + } + else { + addfillface(sf_ctx, eve->next, eve->next->next, eve->next->next->next); + addfillface(sf_ctx, eve->next->next->next, eve, eve->next); + } + return 2; } - return 2; } /* first test vertices if they are in edges */ @@ -985,7 +1002,7 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedu /* CURRENT STATUS: - * - eve->f :1 = availalble in edges + * - eve->f :1 = available in edges * - eve->xs :polynumber * - eve->h :amount of edges connected to vertex * - eve->tmp.v :store! original vertex number @@ -1091,7 +1108,7 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedu for (a = 0; a < poly; a++) { if (pf->edges > 1) { splitlist(sf_ctx, &tempve, &temped, pf->nr); - totfaces += scanfill(sf_ctx, pf); + totfaces += scanfill(sf_ctx, pf, flag); } pf++; } diff --git a/source/blender/blenlib/intern/smallhash.c b/source/blender/blenlib/intern/smallhash.c index 92125c6e988..64bb503fa3c 100644 --- a/source/blender/blenlib/intern/smallhash.c +++ b/source/blender/blenlib/intern/smallhash.c @@ -43,8 +43,22 @@ #define SMHASH_CELL_UNUSED ((void *)0x7FFFFFFF) #define SMHASH_CELL_FREE ((void *)0x7FFFFFFD) -#define SMHASH_NONZERO(n) ((n) + !(n)) -#define SMHASH_NEXT(h, hoff) ABS(((h) + ((hoff = SMHASH_NONZERO(hoff * 2) + 1), hoff))) +BLI_INLINE int smhash_nonzero(const int n) +{ + return n + !n; +} + +BLI_INLINE int smhash_abs_i(const int n) +{ + return (n > 0) ? n : -n; +} + +/* typically this re-assigns 'h' */ +#define SMHASH_NEXT(h, hoff) ( \ + CHECK_TYPE_INLINE(&(h), int), \ + CHECK_TYPE_INLINE(&(hoff), int), \ + smhash_abs_i((h) + (((hoff) = smhash_nonzero((hoff) * 2) + 1), (hoff))) \ + ) extern unsigned int hashsizes[]; diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index ff589764287..f23f75f69d9 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -56,7 +56,7 @@ char *BLI_strdup(const char *str) return BLI_strdupn(str, strlen(str)); } -char *BLI_strdupcat(const char *str1, const char *str2) +char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2) { size_t len; char *n; @@ -69,7 +69,7 @@ char *BLI_strdupcat(const char *str1, const char *str2) return n; } -char *BLI_strncpy(char *dst, const char *src, const size_t maxncpy) +char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) { size_t srclen = strlen(src); size_t cpylen = (srclen > (maxncpy - 1)) ? (maxncpy - 1) : srclen; @@ -81,10 +81,14 @@ char *BLI_strncpy(char *dst, const char *src, const size_t maxncpy) return dst; } -size_t BLI_vsnprintf(char *buffer, size_t count, const char *format, va_list arg) +size_t BLI_vsnprintf(char *__restrict buffer, size_t count, const char *__restrict format, va_list arg) { size_t n; + BLI_assert(buffer != NULL); + BLI_assert(count > 0); + BLI_assert(format != NULL); + n = vsnprintf(buffer, count, format, arg); if (n != -1 && n < count) { @@ -97,7 +101,7 @@ size_t BLI_vsnprintf(char *buffer, size_t count, const char *format, va_list arg return n; } -size_t BLI_snprintf(char *buffer, size_t count, const char *format, ...) +size_t BLI_snprintf(char *__restrict buffer, size_t count, const char *__restrict format, ...) { size_t n; va_list arg; @@ -109,12 +113,14 @@ size_t BLI_snprintf(char *buffer, size_t count, const char *format, ...) return n; } -char *BLI_sprintfN(const char *format, ...) +char *BLI_sprintfN(const char *__restrict format, ...) { DynStr *ds; va_list arg; char *n; + BLI_assert(format != NULL); + va_start(arg, format); ds = BLI_dynstr_new(); @@ -133,7 +139,7 @@ char *BLI_sprintfN(const char *format, ...) * TODO: support more fancy string escaping. current code is primitive * this basically is an ascii version of PyUnicode_EncodeUnicodeEscape() * which is a useful reference. */ -size_t BLI_strescape(char *dst, const char *src, const size_t maxncpy) +size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) { size_t len = 0; @@ -186,7 +192,7 @@ escape_finish: * * TODO, return the offset and a length so as to avoid doing an allocation. */ -char *BLI_str_quoted_substrN(const char *str, const char *prefix) +char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix) { size_t prefixLen = strlen(prefix); char *startMatch, *endMatch; @@ -207,7 +213,7 @@ char *BLI_str_quoted_substrN(const char *str, const char *prefix) /* A rather wasteful string-replacement utility, though this shall do for now... * Feel free to replace this with an even safe + nicer alternative */ -char *BLI_replacestr(char *str, const char *oldText, const char *newText) +char *BLI_replacestr(char *__restrict str, const char *__restrict oldText, const char *__restrict newText) { DynStr *ds = NULL; size_t lenOld = strlen(oldText); diff --git a/source/blender/blenlib/intern/string_cursor_utf8.c b/source/blender/blenlib/intern/string_cursor_utf8.c index bab144266a4..65763f21b0f 100644 --- a/source/blender/blenlib/intern/string_cursor_utf8.c +++ b/source/blender/blenlib/intern/string_cursor_utf8.c @@ -38,7 +38,7 @@ typedef enum strCursorDelimType { STRCUR_DELIM_NONE, - STRCUR_DELIM_ALPHA, + STRCUR_DELIM_ALPHANUMERIC, STRCUR_DELIM_PUNCT, STRCUR_DELIM_BRACE, STRCUR_DELIM_OPERATOR, @@ -47,21 +47,12 @@ typedef enum strCursorDelimType { STRCUR_DELIM_OTHER } strCursorDelimType; -/* return 1 if char ch is special character, otherwise return 0 */ -static strCursorDelimType test_special_char(const char *ch_utf8) +static strCursorDelimType cursor_delim_type(const char *ch_utf8) { /* for full unicode support we really need to have large lookup tables to figure * out whats what in every possible char set - and python, glib both have these. */ unsigned int uch = BLI_str_utf8_as_unicode(ch_utf8); - if ((uch >= 'a' && uch <= 'z') || - (uch >= 'A' && uch <= 'Z') || - (uch == '_') /* not quite correct but allow for python, could become configurable */ - ) - { - return STRCUR_DELIM_ALPHA; - } - switch (uch) { case ',': case '.': @@ -86,10 +77,11 @@ static strCursorDelimType test_special_char(const char *ch_utf8) case '^': case '*': case '&': + case '|': return STRCUR_DELIM_OPERATOR; case '\'': - case '\"': // " - an extra closing one for Aligorith's text editor + case '\"': return STRCUR_DELIM_QUOTE; case ' ': @@ -97,20 +89,22 @@ static strCursorDelimType test_special_char(const char *ch_utf8) return STRCUR_DELIM_WHITESPACE; case '\\': - case '!': case '@': case '#': case '$': case ':': case ';': case '?': + case '!': + case 0xA3: /* pound */ + case 0x80: /* euro */ /* case '_': *//* special case, for python */ return STRCUR_DELIM_OTHER; default: break; } - return STRCUR_DELIM_NONE; + return STRCUR_DELIM_ALPHANUMERIC; /* Not quite true, but ok for now */ } int BLI_str_cursor_step_next_utf8(const char *str, size_t maxlen, int *pos) @@ -153,14 +147,14 @@ void BLI_str_cursor_step_utf8(const char *str, size_t maxlen, BLI_str_cursor_step_next_utf8(str, maxlen, pos); if (jump != STRCUR_JUMP_NONE) { - const strCursorDelimType is_special = (*pos) < maxlen ? test_special_char(&str[*pos]) : STRCUR_DELIM_NONE; + const strCursorDelimType delim_type = (*pos) < maxlen ? cursor_delim_type(&str[*pos]) : STRCUR_DELIM_NONE; /* jump between special characters (/,\,_,-, etc.), - * look at function test_special_char() for complete + * look at function cursor_delim_type() for complete * list of special character, ctr -> */ while ((*pos) < maxlen) { if (BLI_str_cursor_step_next_utf8(str, maxlen, pos)) { - if ((jump != STRCUR_JUMP_ALL) && (is_special != test_special_char(&str[*pos]))) - break; + if ((jump != STRCUR_JUMP_ALL) && (delim_type != cursor_delim_type(&str[*pos]))) + break; } else { break; /* unlikely but just in case */ @@ -172,13 +166,13 @@ void BLI_str_cursor_step_utf8(const char *str, size_t maxlen, BLI_str_cursor_step_prev_utf8(str, maxlen, pos); if (jump != STRCUR_JUMP_NONE) { - const strCursorDelimType is_special = (*pos) > 1 ? test_special_char(&str[(*pos) - 1]) : STRCUR_DELIM_NONE; + const strCursorDelimType delim_type = (*pos) > 1 ? cursor_delim_type(&str[(*pos) - 1]) : STRCUR_DELIM_NONE; /* jump between special characters (/,\,_,-, etc.), - * look at function test_special_char() for complete + * look at function cursor_delim_type() for complete * list of special character, ctr -> */ while ((*pos) > 0) { if (BLI_str_cursor_step_prev_utf8(str, maxlen, pos)) { - if ((jump != STRCUR_JUMP_ALL) && (is_special != test_special_char(&str[*pos]))) + if ((jump != STRCUR_JUMP_ALL) && (delim_type != cursor_delim_type(&str[*pos]))) break; } else { diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index 0b737e0eff5..bf98f2ae77c 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -184,7 +184,7 @@ static const size_t utf8_skip_data[256] = { *dst = '\0'; \ } (void)0 -char *BLI_strncpy_utf8(char *dst, const char *src, size_t maxncpy) +char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) { char *dst_r = dst; @@ -196,7 +196,7 @@ char *BLI_strncpy_utf8(char *dst, const char *src, size_t maxncpy) return dst_r; } -char *BLI_strncat_utf8(char *dst, const char *src, size_t maxncpy) +char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) { while (*dst && maxncpy > 0) { dst++; @@ -213,7 +213,7 @@ char *BLI_strncat_utf8(char *dst, const char *src, size_t maxncpy) /* --------------------------------------------------------------------------*/ /* wchar_t / utf8 functions */ -size_t BLI_strncpy_wchar_as_utf8(char *dst, const wchar_t *src, const size_t maxncpy) +size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, const size_t maxncpy) { size_t len = 0; @@ -289,7 +289,7 @@ size_t BLI_strnlen_utf8(const char *start, const size_t maxlen) return len; } -size_t BLI_strncpy_wchar_from_utf8(wchar_t *dst_w, const char *src_c, const size_t maxncpy) +size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w, const char *__restrict src_c, const size_t maxncpy) { int len = 0; @@ -317,12 +317,12 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *dst_w, const char *src_c, const size /* end wchar_t / utf8 functions */ /* --------------------------------------------------------------------------*/ -/* copied from glib's gutf8.c */ +/* copied from glib's gutf8.c, added 'Err' arg */ /* note, glib uses unsigned int for unicode, best we do the same, * though we don't typedef it - campbell */ -#define UTF8_COMPUTE(Char, Mask, Len) \ +#define UTF8_COMPUTE(Char, Mask, Len, Err) \ if (Char < 128) { \ Len = 1; \ Mask = 0x7f; \ @@ -348,7 +348,7 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *dst_w, const char *src_c, const size Mask = 0x01; \ } \ else { \ - Len = -1; \ + Len = Err; /* -1 is the typical error value or 1 to skip */ \ } (void)0 /* same as glib define but added an 'Err' arg */ @@ -371,7 +371,20 @@ int BLI_str_utf8_size(const char *p) int mask = 0, len; unsigned char c = (unsigned char) *p; - UTF8_COMPUTE (c, mask, len); + UTF8_COMPUTE (c, mask, len, -1); + + (void)mask; /* quiet warning */ + + return len; +} + +/* use when we want to skip errors */ +int BLI_str_utf8_size_safe(const char *p) +{ + int mask = 0, len; + unsigned char c = (unsigned char) *p; + + UTF8_COMPUTE (c, mask, len, 1); (void)mask; /* quiet warning */ @@ -381,10 +394,10 @@ int BLI_str_utf8_size(const char *p) /* was g_utf8_get_char */ /** * BLI_str_utf8_as_unicode: - * @p a pointer to Unicode character encoded as UTF-8 + * \param p a pointer to Unicode character encoded as UTF-8 * * Converts a sequence of bytes encoded as UTF-8 to a Unicode character. - * If @p does not point to a valid UTF-8 encoded character, results are + * If \a p does not point to a valid UTF-8 encoded character, results are * undefined. If you are not sure that the bytes are complete * valid Unicode characters, you should use g_utf8_get_char_validated() * instead. @@ -397,7 +410,7 @@ unsigned int BLI_str_utf8_as_unicode(const char *p) unsigned int result; unsigned char c = (unsigned char) *p; - UTF8_COMPUTE (c, mask, len); + UTF8_COMPUTE (c, mask, len, -1); if (len == -1) return BLI_UTF8_ERR; UTF8_GET (result, p, i, mask, len, BLI_UTF8_ERR); @@ -406,13 +419,13 @@ unsigned int BLI_str_utf8_as_unicode(const char *p) } /* variant that increments the length */ -unsigned int BLI_str_utf8_as_unicode_and_size(const char *p, size_t *index) +unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index) { int i, mask = 0, len; unsigned int result; unsigned char c = (unsigned char) *p; - UTF8_COMPUTE (c, mask, len); + UTF8_COMPUTE (c, mask, len, -1); if (len == -1) return BLI_UTF8_ERR; UTF8_GET (result, p, i, mask, len, BLI_UTF8_ERR); @@ -422,7 +435,7 @@ unsigned int BLI_str_utf8_as_unicode_and_size(const char *p, size_t *index) /* another variant that steps over the index, * note, currently this also falls back to latin1 for text drawing. */ -unsigned int BLI_str_utf8_as_unicode_step(const char *p, size_t *index) +unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index) { int i, mask = 0, len; unsigned int result; @@ -431,7 +444,7 @@ unsigned int BLI_str_utf8_as_unicode_step(const char *p, size_t *index) p += *index; c = (unsigned char) *p; - UTF8_COMPUTE (c, mask, len); + UTF8_COMPUTE (c, mask, len, -1); if (len == -1) { /* when called with NULL end, result will never be NULL, * checks for a NULL character */ @@ -523,14 +536,14 @@ size_t BLI_str_utf8_from_unicode(unsigned int c, char *outbuf) /* was g_utf8_find_prev_char */ /** * BLI_str_find_prev_char_utf8: - * @str: pointer to the beginning of a UTF-8 encoded string - * @p pointer to some position within @str + * \param str pointer to the beginning of a UTF-8 encoded string + * \param p pointer to some position within \a str * - * Given a position @p with a UTF-8 encoded string @str, find the start - * of the previous UTF-8 character starting before. @p Returns %NULL if no - * UTF-8 characters are present in @str before @p + * Given a position \a p with a UTF-8 encoded string \a str, find the start + * of the previous UTF-8 character starting before. \a p Returns %NULL if no + * UTF-8 characters are present in \a str before \a p * - * @p does not have to be at the beginning of a UTF-8 character. No check + * \a p does not have to be at the beginning of a UTF-8 character. No check * is made to see if the character found is actually valid other than * it starts with an appropriate byte. * @@ -549,13 +562,13 @@ char * BLI_str_find_prev_char_utf8(const char *str, const char *p) /* was g_utf8_find_next_char */ /** * BLI_str_find_next_char_utf8: - * @p a pointer to a position within a UTF-8 encoded string - * @end a pointer to the byte following the end of the string, + * \param p a pointer to a position within a UTF-8 encoded string + * \param end a pointer to the byte following the end of the string, * or %NULL to indicate that the string is nul-terminated. * - * Finds the start of the next UTF-8 character in the string after @p + * Finds the start of the next UTF-8 character in the string after \a p * - * @p does not have to be at the beginning of a UTF-8 character. No check + * \a p does not have to be at the beginning of a UTF-8 character. No check * is made to see if the character found is actually valid other than * it starts with an appropriate byte. * @@ -581,13 +594,13 @@ char *BLI_str_find_next_char_utf8(const char *p, const char *end) /* was g_utf8_prev_char */ /** * BLI_str_prev_char_utf8: - * @p a pointer to a position within a UTF-8 encoded string + * \param p a pointer to a position within a UTF-8 encoded string * - * Finds the previous UTF-8 character in the string before @p + * Finds the previous UTF-8 character in the string before \a p * - * @p does not have to be at the beginning of a UTF-8 character. No check + * \a p does not have to be at the beginning of a UTF-8 character. No check * is made to see if the character found is actually valid other than - * it starts with an appropriate byte. If @p might be the first + * it starts with an appropriate byte. If \a p might be the first * character of the string, you must use g_utf8_find_prev_char() instead. * * Return value: a pointer to the found character. diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index 66527b9b92a..146e1d531f1 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -400,6 +400,42 @@ void BLI_mutex_end(ThreadMutex *mutex) pthread_mutex_destroy(mutex); } +/* Spin Locks */ + +void BLI_spin_init(SpinLock *spin) +{ +#ifdef __APPLE__ + *spin = OS_SPINLOCK_INIT; +#else + pthread_spin_init(spin, 0); +#endif +} + +void BLI_spin_lock(SpinLock *spin) +{ +#ifdef __APPLE__ + OSSpinLockLock(spin); +#else + pthread_spin_lock(spin); +#endif +} + +void BLI_spin_unlock(SpinLock *spin) +{ +#ifdef __APPLE__ + OSSpinLockUnlock(spin); +#else + pthread_spin_unlock(spin); +#endif +} + +void BLI_spin_end(SpinLock *spin) +{ +#ifndef __APPLE__ + pthread_spin_destroy(spin); +#endif +} + /* Read/Write Mutex Lock */ void BLI_rw_mutex_init(ThreadRWMutex *mutex) diff --git a/source/blender/blenlib/intern/voronoi.c b/source/blender/blenlib/intern/voronoi.c index 0d411038b3e..601b07c9a5d 100644 --- a/source/blender/blenlib/intern/voronoi.c +++ b/source/blender/blenlib/intern/voronoi.c @@ -609,9 +609,9 @@ static int voronoi_getNextSideCoord(ListBase *edges, float coord[2], int dim, in static void voronoi_createBoundaryEdges(ListBase *edges, int width, int height) { const float corners[4][2] = {{width - 1, 0.0f}, - {width - 1, height - 1}, - {0.0f, height - 1}, - {0.0f, 0.0f}}; + {width - 1, height - 1}, + {0.0f, height - 1}, + {0.0f, 0.0f}}; int i, dim = 0, dir = 1; float coord[2] = {0.0f, 0.0f}; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 2ea3fb75709..203af1d8316 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -360,36 +360,39 @@ static void *oldnewmap_lookup_and_inc(OldNewMap *onm, void *addr) } /* for libdata, nr has ID code, no increment */ -static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib) +static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib) { - int i; - - if (addr == NULL) return NULL; - + if (addr == NULL) { + return NULL; + } + /* lasthit works fine for non-libdata, linking there is done in same sequence as writing */ if (onm->sorted) { OldNew entry_s, *entry; - + entry_s.old = addr; - + entry = bsearch(&entry_s, onm->entries, onm->nentries, sizeof(OldNew), verg_oldnewmap); if (entry) { ID *id = entry->newp; - + if (id && (!lib || id->lib)) { - return entry->newp; + return id; } } } - - for (i = 0; i < onm->nentries; i++) { - OldNew *entry = &onm->entries[i]; - - if (entry->old == addr) { - ID *id = entry->newp; - - if (id && (!lib || id->lib)) { - return entry->newp; + else { + /* note, this can be a bottle neck when loading some files */ + unsigned int nentries = (unsigned int)onm->nentries; + unsigned int i; + OldNew *entry; + + for (i = 0, entry = onm->entries; i < nentries; i++, entry++) { + if (entry->old == addr) { + ID *id = id = entry->newp; + if (id && (!lib || id->lib)) { + return id; + } } } } @@ -2406,6 +2409,8 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree) ntree->adt = newdataadr(fd, ntree->adt); direct_link_animdata(fd, ntree->adt); + ntree->id.flag &= ~(LIB_ID_RECALC|LIB_ID_RECALC_DATA); + link_list(fd, &ntree->nodes); for (node = ntree->nodes.first; node; node = node->next) { node->typeinfo = NULL; @@ -2980,7 +2985,6 @@ static void direct_link_text(FileData *fd, Text *text) #endif link_list(fd, &text->lines); - link_list(fd, &text->markers); text->curl = newdataadr(fd, text->curl); text->sell = newdataadr(fd, text->sell); @@ -3040,7 +3044,7 @@ static void direct_link_image(FileData *fd, Image *ima) link_ibuf_list(fd, &ima->ibufs); else ima->ibufs.first = ima->ibufs.last = NULL; - + /* if not restored, we keep the binded opengl index */ if (ima->ibufs.first == NULL) { ima->bindcode = 0; @@ -7168,7 +7172,36 @@ static void do_version_logic_264(ListBase *regionbase) } - + +static void do_versions_affine_tracker_track(MovieTrackingTrack *track) +{ + int i; + + for (i = 0; i < track->markersnr; i++) { + MovieTrackingMarker *marker = &track->markers[i]; + + if (is_zero_v2(marker->pattern_corners[0]) && is_zero_v2(marker->pattern_corners[1]) && + is_zero_v2(marker->pattern_corners[2]) && is_zero_v2(marker->pattern_corners[3])) + { + marker->pattern_corners[0][0] = track->pat_min[0]; + marker->pattern_corners[0][1] = track->pat_min[1]; + + marker->pattern_corners[1][0] = track->pat_max[0]; + marker->pattern_corners[1][1] = track->pat_min[1]; + + marker->pattern_corners[2][0] = track->pat_max[0]; + marker->pattern_corners[2][1] = track->pat_max[1]; + + marker->pattern_corners[3][0] = track->pat_min[0]; + marker->pattern_corners[3][1] = track->pat_max[1]; + } + + if (is_zero_v2(marker->search_min) && is_zero_v2(marker->search_max)) { + copy_v2_v2(marker->search_min, track->search_min); + copy_v2_v2(marker->search_max, track->search_max); + } + } +} static void do_versions(FileData *fd, Library *lib, Main *main) @@ -7939,32 +7972,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) track = clip->tracking.tracks.first; while (track) { - int i; - - for (i = 0; i < track->markersnr; i++) { - MovieTrackingMarker *marker = &track->markers[i]; - - if (is_zero_v2(marker->pattern_corners[0]) && is_zero_v2(marker->pattern_corners[1]) && - is_zero_v2(marker->pattern_corners[2]) && is_zero_v2(marker->pattern_corners[3])) - { - marker->pattern_corners[0][0] = track->pat_min[0]; - marker->pattern_corners[0][1] = track->pat_min[1]; - - marker->pattern_corners[1][0] = track->pat_max[0]; - marker->pattern_corners[1][1] = track->pat_min[1]; - - marker->pattern_corners[2][0] = track->pat_max[0]; - marker->pattern_corners[2][1] = track->pat_max[1]; - - marker->pattern_corners[3][0] = track->pat_min[0]; - marker->pattern_corners[3][1] = track->pat_max[1]; - } - - if (is_zero_v2(marker->search_min) && is_zero_v2(marker->search_max)) { - copy_v2_v2(marker->search_min, track->search_min); - copy_v2_v2(marker->search_max, track->search_max); - } - } + do_versions_affine_tracker_track(track); track = track->next; } @@ -8306,11 +8314,17 @@ static void do_versions(FileData *fd, Library *lib, Main *main) for (scene = main->scene.first; scene; scene = scene->id.next) { if (scene->r.tilex == 0 || scene->r.tiley == 1) { - /* scene could be set for panoramic rendering, so clamp with the - * lowest possible tile size value - */ - scene->r.tilex = max_ii(scene->r.xsch * scene->r.size / scene->r.xparts / 100, 8); - scene->r.tiley = max_ii(scene->r.ysch * scene->r.size / scene->r.yparts / 100, 8); + if (scene->r.xparts && scene->r.yparts) { + /* scene could be set for panoramic rendering, so clamp with the + * lowest possible tile size value + */ + scene->r.tilex = max_ii(scene->r.xsch * scene->r.size / scene->r.xparts / 100, 8); + scene->r.tiley = max_ii(scene->r.ysch * scene->r.size / scene->r.yparts / 100, 8); + } + else { + /* happens when mixing using current trunk and previous release */ + scene->r.tilex = scene->r.tiley = 64; + } } } } @@ -8332,12 +8346,42 @@ static void do_versions(FileData *fd, Library *lib, Main *main) for (clip = main->movieclip.first; clip; clip = clip->id.next) { if (clip->tracking.settings.reconstruction_success_threshold == 0.0f) { - clip->tracking.settings.reconstruction_success_threshold = 1e-3; + clip->tracking.settings.reconstruction_success_threshold = 1e-3f; } } } } + if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 7)) { + MovieClip *clip; + + for (clip = main->movieclip.first; clip; clip = clip->id.next) { + MovieTrackingTrack *track; + MovieTrackingObject *object; + + for (track = clip->tracking.tracks.first; track; track = track->next) { + do_versions_affine_tracker_track(track); + } + + for (object = clip->tracking.objects.first; object; object = object->next) { + for (track = object->tracks.first; track; track = track->next) { + do_versions_affine_tracker_track(track); + } + } + } + } + + if (main->versionfile < 265) { + Object *ob; + for (ob = main->object.first; ob; ob = ob->id.next) { + if (ob->step_height == 0.0f) { + ob->step_height = 0.15f; + ob->jump_speed = 10.0f; + ob->fall_speed = 55.0f; + } + } + } + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */ diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index d75339252d9..1521739258e 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -901,7 +901,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main) ob->matbits = MEM_callocN(sizeof(char)*ob->totcol, "ob->matbits"); for (a = 0; a < ob->totcol; a++) - ob->matbits[a] = ob->colbits & (1<matbits[a] = (ob->colbits & (1<first; while (text) { @@ -2631,13 +2630,6 @@ static void write_texts(WriteData *wd, ListBase *idbase) writedata(wd, DATA, tmp->len+1, tmp->line); tmp= tmp->next; } - - /* write markers */ - mrk= text->markers.first; - while (mrk) { - writestruct(wd, DATA, "TextMarker", 1, mrk); - mrk= mrk->next; - } } @@ -2890,7 +2882,7 @@ static void write_global(WriteData *wd, int fileflags, Main *mainvar) fg.winpos= G.winpos; /* prevent to save this, is not good convention, and feature with concerns... */ - fg.fileflags= (fileflags & ~(G_FILE_NO_UI|G_FILE_RELATIVE_REMAP|G_FILE_MESH_COMPAT)); + fg.fileflags= (fileflags & ~G_FILE_FLAGS_RUNTIME); fg.globalf= G.f; BLI_strncpy(fg.filename, mainvar->name, sizeof(fg.filename)); @@ -3039,6 +3031,10 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL char tempname[FILE_MAX+1]; int file, err, write_user_block; + /* path backup/restore */ + void *path_list_backup = NULL; + const int path_list_flag = (BLI_BPATH_TRAVERSE_SKIP_LIBRARY | BLI_BPATH_TRAVERSE_SKIP_MULTIFILE); + /* open temporary file, so we preserve the original in case we crash */ BLI_snprintf(tempname, sizeof(tempname), "%s@", filepath); @@ -3048,6 +3044,11 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL return 0; } + /* check if we need to backup and restore paths */ + if (UNLIKELY((write_flags & G_FILE_RELATIVE_REMAP) && (G_FILE_SAVE_COPY & write_flags))) { + path_list_backup = BLI_bpath_list_backup(mainvar, path_list_flag); + } + /* remapping of relative paths to new file location */ if (write_flags & G_FILE_RELATIVE_REMAP) { char dir1[FILE_MAX]; @@ -3083,6 +3084,11 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL err= write_file_handle(mainvar, file, NULL, NULL, write_user_block, write_flags, thumb); close(file); + if (UNLIKELY(path_list_backup)) { + BLI_bpath_list_restore(mainvar, path_list_flag, path_list_backup); + BLI_bpath_list_free(path_list_backup); + } + if (err) { BKE_report(reports, RPT_ERROR, strerror(errno)); remove(tempname); diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt index d7858ebbc0d..2a23658f5d0 100644 --- a/source/blender/bmesh/CMakeLists.txt +++ b/source/blender/bmesh/CMakeLists.txt @@ -68,10 +68,6 @@ set(SRC intern/bmesh_construct.h intern/bmesh_core.c intern/bmesh_core.h - intern/bmesh_decimate_collapse.c - intern/bmesh_decimate_dissolve.c - intern/bmesh_decimate_unsubdivide.c - intern/bmesh_decimate.h intern/bmesh_inline.h intern/bmesh_interp.c intern/bmesh_interp.h @@ -109,6 +105,12 @@ set(SRC intern/bmesh_error.h tools/BME_bevel.c + tools/bmesh_bevel.c + tools/bmesh_bevel.h + tools/bmesh_decimate_collapse.c + tools/bmesh_decimate_dissolve.c + tools/bmesh_decimate_unsubdivide.c + tools/bmesh_decimate.h bmesh.h bmesh_class.h diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h index a672ec0b6a7..6257aa4bf3e 100644 --- a/source/blender/bmesh/bmesh.h +++ b/source/blender/bmesh/bmesh.h @@ -252,7 +252,6 @@ extern "C" { #include "intern/bmesh_construct.h" #include "intern/bmesh_core.h" -#include "intern/bmesh_decimate.h" #include "intern/bmesh_interp.h" #include "intern/bmesh_iterators.h" #include "intern/bmesh_marking.h" @@ -267,6 +266,9 @@ extern "C" { #include "intern/bmesh_inline.h" +#include "tools/bmesh_decimate.h" +#include "tools/bmesh_bevel.h" + #ifdef __cplusplus } #endif diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index cff7da78ef2..9d797c1e602 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -48,6 +48,8 @@ struct Object; * hrm. it doesn't but stull works ok, remove the comment above? - campbell. */ +// #pragma GCC diagnostic error "-Wpadded" + /** * BMHeader * @@ -69,10 +71,19 @@ typedef struct BMHeader { * this is abused by various tools which set it dirty. * - For loops this is used for sorting during tessellation. */ - char htype; /* element geometric type (verts/edges/loops/faces) */ - char hflag; /* this would be a CD layer, see below */ + char htype; /* element geometric type (verts/edges/loops/faces) */ + char hflag; /* this would be a CD layer, see below */ + + /* internal use only! + * note,.we are very picky about not bloating this struct + * but in this case its padded up to 16 bytes anyway, + * so adding a flag here gives no increase in size */ + char api_flag; +// char _pad; } BMHeader; +BLI_STATIC_ASSERT((sizeof(BMHeader) <= 16), "BMHeader size has grown!"); + /* note: need some way to specify custom locations for custom data layers. so we can * make them point directly into structs. and some way to make it only happen to the * active layer, and properly update when switching active layers.*/ @@ -122,7 +133,10 @@ typedef struct BMLoop { /* can cast BMFace/BMEdge/BMVert, but NOT BMLoop, since these don't have a flag layer */ typedef struct BMElemF { BMHeader head; - struct BMFlagLayer *oflags; /* keep after header, an array of flags, mostly used by the operator stack */ + + /* keep directly after header, + * optional array of flags, only used by the operator stack */ + struct BMFlagLayer *oflags; } BMElemF; /* can cast anything to this, including BMLoop */ @@ -142,21 +156,24 @@ typedef struct BMFace { BMHeader head; struct BMFlagLayer *oflags; /* an array of flags, mostly used by the operator stack */ - int len; /*includes all boundary loops*/ #ifdef USE_BMESH_HOLES int totbounds; /*total boundaries, is one plus the number of holes in the face*/ ListBase loops; #else BMLoop *l_first; #endif - float no[3]; /*yes, we do store this here*/ + int len; /* includes all boundary loops */ + float no[3]; /* yes, we do store this here */ short mat_nr; +// short _pad[3]; } BMFace; typedef struct BMFlagLayer { - short f, pflag; /* flags */ + short f; /* flags */ } BMFlagLayer; +// #pragma GCC diagnostic ignored "-Wpadded" + typedef struct BMesh { int totvert, totedge, totloop, totface; int totvertsel, totedgesel, totfacesel; @@ -166,7 +183,7 @@ typedef struct BMesh { * valid flags are - BM_VERT | BM_EDGE | BM_FACE. * BM_LOOP isn't handled so far. */ char elem_index_dirty; - + /*element pools*/ struct BLI_mempool *vpool, *epool, *lpool, *fpool; @@ -192,7 +209,7 @@ typedef struct BMesh { int walkers, totflags; ListBase selected, error_stack; - + BMFace *act_face; ListBase errorstack; @@ -209,6 +226,7 @@ enum { }; #define BM_ALL (BM_VERT | BM_EDGE | BM_LOOP | BM_FACE) +#define BM_ALL_NOLOOP (BM_VERT | BM_EDGE | BM_FACE) /* BMHeader->hflag (char) */ enum { @@ -243,10 +261,16 @@ enum { # define BM_FACE_FIRST_LOOP(p) ((p)->l_first) #endif -/* size to use for static arrays when dealing with NGons, +/** + * size to use for stack arrays when dealing with NGons, * alloc after this limit is reached. * this value is rather arbitrary */ -#define BM_NGON_STACK_SIZE 32 +#define BM_DEFAULT_NGON_STACK_SIZE 32 +/** + * size to use for stack arrays dealing with connected mesh data + * verts of faces, edges of vert - etc. + * often used with #BM_iter_as_arrayN() */ +#define BM_DEFAULT_ITER_STACK_SIZE 16 /* avoid inf loop, this value is arbitrary * but should not error on valid cases */ diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index d86a26e19ac..8b7fac1eacd 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -99,23 +99,23 @@ BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFa if (nodouble) { /* check if face exists or overlaps */ - is_overlap = BM_face_exists(bm, verts, len, &f); + is_overlap = BM_face_exists(verts, len, &f); } /* make new face */ if ((f == NULL) && (!is_overlap)) { BMEdge *edar[4] = {NULL}; - edar[0] = BM_edge_create(bm, verts[0], verts[1], NULL, TRUE); - edar[1] = BM_edge_create(bm, verts[1], verts[2], NULL, TRUE); + edar[0] = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE); + edar[1] = BM_edge_create(bm, verts[1], verts[2], NULL, BM_CREATE_NO_DOUBLE); if (len == 4) { - edar[2] = BM_edge_create(bm, verts[2], verts[3], NULL, TRUE); - edar[3] = BM_edge_create(bm, verts[3], verts[0], NULL, TRUE); + edar[2] = BM_edge_create(bm, verts[2], verts[3], NULL, BM_CREATE_NO_DOUBLE); + edar[3] = BM_edge_create(bm, verts[3], verts[0], NULL, BM_CREATE_NO_DOUBLE); } else { - edar[2] = BM_edge_create(bm, verts[2], verts[0], NULL, TRUE); + edar[2] = BM_edge_create(bm, verts[2], verts[0], NULL, BM_CREATE_NO_DOUBLE); } - f = BM_face_create(bm, verts, edar, len, FALSE); + f = BM_face_create(bm, verts, edar, len, 0); if (example && f) { BM_elem_attrs_copy(bm, bm, example, f); @@ -171,12 +171,12 @@ void BM_face_copy_shared(BMesh *bm, BMFace *f) * #BM_face_create should be considered over this function as it * avoids some unnecessary work. */ -BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, int nodouble) +BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, const int create_flag) { BMEdge **edges2 = NULL; - BLI_array_staticdeclare(edges2, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(edges2, BM_DEFAULT_NGON_STACK_SIZE); BMVert **verts = NULL; - BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); BMFace *f = NULL; BMEdge *e; BMVert *v, *ev1, *ev2; @@ -187,8 +187,10 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, i * _and_ the old bmesh_mf functions, so its kindof smashed together * - joeedh */ - if (!len || !v1 || !v2 || !edges || !bm) + if (!len || !v1 || !v2 || !edges || !bm) { + BLI_assert(0); return NULL; + } /* put edges in correct order */ for (i = 0; i < len; i++) { @@ -280,7 +282,7 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, i BM_ELEM_API_FLAG_DISABLE(verts[i], _FLAG_MV); } - f = BM_face_create(bm, verts, edges2, len, nodouble); + f = BM_face_create(bm, verts, edges2, len, create_flag); /* clean up flags */ for (i = 0; i < len; i++) { @@ -336,7 +338,7 @@ static int angle_index_pair_cmp(const void *e1, const void *e2) * * \note Since this is a vcloud there is no direction. */ -BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, int nodouble) +BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, const int create_flag) { BMFace *f; @@ -397,11 +399,11 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, int n /* more of a weight then a distance */ far_cross_dist = (/* first we want to have a value close to zero mapped to 1 */ - 1.0f - fabsf(dot_v3v3(far_vec, far_cross_vec)) * + 1.0f - fabsf(dot_v3v3(far_vec, far_cross_vec)) * - /* second we multiply by the distance - * so points close to the center are not preferred */ - far_cross_dist); + /* second we multiply by the distance + * so points close to the center are not preferred */ + far_cross_dist); if (far_cross_dist > far_cross_best || far_cross == NULL) { far_cross = vert_arr[i]->co; @@ -462,7 +464,7 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, int n i_prev = totv - 1; for (i = 0; i < totv; i++) { - edge_arr[i] = BM_edge_create(bm, vert_arr_map[i_prev], vert_arr_map[i], NULL, TRUE); + edge_arr[i] = BM_edge_create(bm, vert_arr_map[i_prev], vert_arr_map[i], NULL, BM_CREATE_NO_DOUBLE); /* the edge may exist already and be attached to a face * in this case we can find the best winding to use for the new face */ @@ -491,7 +493,7 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, int n /* --- */ /* create the face */ - f = BM_face_create_ngon(bm, vert_arr_map[winding[0]], vert_arr_map[winding[1]], edge_arr, totv, nodouble); + f = BM_face_create_ngon(bm, vert_arr_map[winding[0]], vert_arr_map[winding[1]], edge_arr, totv, create_flag); MEM_freeN(edge_arr); MEM_freeN(vert_arr_map); @@ -854,7 +856,7 @@ BMesh *BM_mesh_copy(BMesh *bm_old) v = BM_iter_new(&iter, bm_old, BM_VERTS_OF_MESH, NULL); for (i = 0; v; v = BM_iter_step(&iter), i++) { - v2 = BM_vert_create(bm_new, v->co, NULL); /* copy between meshes so cant use 'example' argument */ + v2 = BM_vert_create(bm_new, v->co, NULL, BM_CREATE_SKIP_CD); /* copy between meshes so cant use 'example' argument */ BM_elem_attrs_copy(bm_old, bm_new, v, v2); vtable[i] = v2; BM_elem_index_set(v, i); /* set_inline */ @@ -871,7 +873,7 @@ BMesh *BM_mesh_copy(BMesh *bm_old) e2 = BM_edge_create(bm_new, vtable[BM_elem_index_get(e->v1)], vtable[BM_elem_index_get(e->v2)], - e, FALSE); + e, BM_CREATE_SKIP_CD); BM_elem_attrs_copy(bm_old, bm_new, e, e2); etable[i] = e2; @@ -907,7 +909,7 @@ BMesh *BM_mesh_copy(BMesh *bm_old) v2 = vtable[BM_elem_index_get(loops[0]->v)]; } - f2 = BM_face_create_ngon(bm_new, v, v2, edges, f->len, FALSE); + f2 = BM_face_create_ngon(bm_new, v, v2, edges, f->len, BM_CREATE_SKIP_CD); if (UNLIKELY(f2 == NULL)) { continue; } diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h index 29b84046884..60c465e5f5a 100644 --- a/source/blender/bmesh/intern/bmesh_construct.h +++ b/source/blender/bmesh/intern/bmesh_construct.h @@ -36,9 +36,9 @@ BMFace *BM_face_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, B void BM_face_copy_shared(BMesh *bm, BMFace *f); -BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, int nodouble); +BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, const int create_flag); -BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, int nodouble); +BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const int create_flag); void BMO_remove_tagged_faces(BMesh *bm, const short oflag); void BMO_remove_tagged_edges(BMesh *bm, const short oflag); diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 0910dd82701..14fab7abdc9 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -54,7 +54,7 @@ /** * \brief Main function for creating a new vertex. */ -BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example) +BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, const eBMCreateFlag create_flag) { BMVert *v = BLI_mempool_calloc(bm->vpool); @@ -64,6 +64,9 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example) BM_elem_index_set(v, -1); /* set_ok_invalid */ #endif + /* disallow this flag for verts - its meaningless */ + BLI_assert((create_flag & BM_CREATE_NO_DOUBLE) == 0); + bm->elem_index_dirty |= BM_VERT; /* may add to middle of the pool */ bm->totvert++; @@ -76,19 +79,24 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example) } /* allocate flag */ - v->oflags = BLI_mempool_calloc(bm->toolflagpool); + if (bm->toolflagpool) { + v->oflags = BLI_mempool_calloc(bm->toolflagpool); + } - CustomData_bmesh_set_default(&bm->vdata, &v->head.data); - - if (example) { - int *keyi; + if (!(create_flag & BM_CREATE_SKIP_CD)) { + if (example) { + int *keyi; - BM_elem_attrs_copy(bm, bm, example, v); + BM_elem_attrs_copy(bm, bm, example, v); - /* exception: don't copy the original shapekey index */ - keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX); - if (keyi) { - *keyi = ORIGINDEX_NONE; + /* exception: don't copy the original shapekey index */ + keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX); + if (keyi) { + *keyi = ORIGINDEX_NONE; + } + } + else { + CustomData_bmesh_set_default(&bm->vdata, &v->head.data); } } @@ -103,11 +111,11 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example) * \note Duplicate edges are supported by the API however users should _never_ see them. * so unless you need a unique edge or know the edge won't exist, you should call with \a nodouble = TRUE */ -BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, int nodouble) +BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, const eBMCreateFlag create_flag) { BMEdge *e; - if (nodouble && (e = BM_edge_exists(v1, v2))) + if ((create_flag & BM_CREATE_NO_DOUBLE) && (e = BM_edge_exists(v1, v2))) return e; e = BLI_mempool_calloc(bm->epool); @@ -125,27 +133,35 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, e->head.htype = BM_EDGE; /* allocate flag */ - e->oflags = BLI_mempool_calloc(bm->toolflagpool); + if (bm->toolflagpool) { + e->oflags = BLI_mempool_calloc(bm->toolflagpool); + } e->v1 = v1; e->v2 = v2; - BM_elem_flag_enable(e, BM_ELEM_SMOOTH); - - CustomData_bmesh_set_default(&bm->edata, &e->head.data); + BM_elem_flag_enable(e, BM_ELEM_SMOOTH | BM_ELEM_DRAW); bmesh_disk_edge_append(e, e->v1); bmesh_disk_edge_append(e, e->v2); - if (example) - BM_elem_attrs_copy(bm, bm, example, e); + if (!(create_flag & BM_CREATE_SKIP_CD)) { + if (example) { + BM_elem_attrs_copy(bm, bm, example, e); + } + else { + CustomData_bmesh_set_default(&bm->edata, &e->head.data); + } + } + BM_CHECK_ELEMENT(e); return e; } -static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, const BMLoop *example) +static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, + const BMLoop *example, const eBMCreateFlag create_flag) { BMLoop *l = NULL; @@ -160,22 +176,24 @@ static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, const bm->totloop++; - if (example) { - CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, example->head.data, &l->head.data); - } - else { - CustomData_bmesh_set_default(&bm->ldata, &l->head.data); + if (!(create_flag & BM_CREATE_SKIP_CD)) { + if (example) { + CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, example->head.data, &l->head.data); + } + else { + CustomData_bmesh_set_default(&bm->ldata, &l->head.data); + } } return l; } -static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte) +static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte, const int create_flag) { #ifdef USE_BMESH_HOLES BMLoopList *lst = BLI_mempool_calloc(bm->looplistpool); #endif - BMLoop *l = bm_loop_create(bm, startv, starte, f, NULL); + BMLoop *l = bm_loop_create(bm, startv, starte, f, starte->l, create_flag); bmesh_radial_append(starte, l); @@ -195,8 +213,8 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co { BMVert **verts = NULL; BMEdge **edges = NULL; - BLI_array_fixedstack_declare(verts, BM_NGON_STACK_SIZE, f->len, __func__); - BLI_array_fixedstack_declare(edges, BM_NGON_STACK_SIZE, f->len, __func__); + BLI_array_fixedstack_declare(verts, BM_DEFAULT_NGON_STACK_SIZE, f->len, __func__); + BLI_array_fixedstack_declare(edges, BM_DEFAULT_NGON_STACK_SIZE, f->len, __func__); BMLoop *l_iter; BMLoop *l_first; BMLoop *l_copy; @@ -207,7 +225,7 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co i = 0; do { if (copyverts) { - verts[i] = BM_vert_create(bm, l_iter->v->co, l_iter->v); + verts[i] = BM_vert_create(bm, l_iter->v->co, l_iter->v, 0); } else { verts[i] = l_iter->v; @@ -230,7 +248,7 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co v1 = verts[(i + 1) % f->len]; } - edges[i] = BM_edge_create(bm, v1, v2, l_iter->e, FALSE); + edges[i] = BM_edge_create(bm, v1, v2, l_iter->e, 0); } else { edges[i] = l_iter->e; @@ -238,7 +256,7 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co i++; } while ((l_iter = l_iter->next) != l_first); - f_copy = BM_face_create(bm, verts, edges, f->len, FALSE); + f_copy = BM_face_create(bm, verts, edges, f->len, BM_CREATE_SKIP_CD); BM_elem_attrs_copy(bm, bm, f, f_copy); @@ -259,7 +277,7 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co * only create the face, since this calloc's the length is initialized to 0, * leave adding loops to the caller. */ -BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm) +BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm, const eBMCreateFlag create_flag) { BMFace *f; @@ -278,9 +296,13 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm) f->head.htype = BM_FACE; /* allocate flag */ - f->oflags = BLI_mempool_calloc(bm->toolflagpool); + if (bm->toolflagpool) { + f->oflags = BLI_mempool_calloc(bm->toolflagpool); + } - CustomData_bmesh_set_default(&bm->pdata, &f->head.data); + if (!(create_flag & BM_CREATE_SKIP_CD)) { + CustomData_bmesh_set_default(&bm->pdata, &f->head.data); + } #ifdef USE_BMESH_HOLES f->totbounds = 0; @@ -292,7 +314,7 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm) /** * \brief Main face creation function */ -BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, int nodouble) +BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, const eBMCreateFlag create_flag) { BMFace *f = NULL; BMLoop *l, *startl, *lastl; @@ -303,9 +325,9 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, return NULL; } - if (nodouble) { + if (create_flag & BM_CREATE_NO_DOUBLE) { /* Check if face already exists */ - overlap = BM_face_exists(bm, verts, len, &f); + overlap = BM_face_exists(verts, len, &f); if (overlap) { return f; } @@ -314,14 +336,14 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, } } - f = bm_face_create__internal(bm); + f = bm_face_create__internal(bm, create_flag); - startl = lastl = bm_face_boundary_add(bm, f, verts[0], edges[0]); + startl = lastl = bm_face_boundary_add(bm, f, verts[0], edges[0], create_flag); startl->v = verts[0]; startl->e = edges[0]; for (i = 1; i < len; i++) { - l = bm_loop_create(bm, verts[i], edges[i], f, edges[i]->l); + l = bm_loop_create(bm, verts[i], edges[i], f, edges[i]->l, create_flag); l->f = f; bmesh_radial_append(edges[i], l); @@ -495,7 +517,9 @@ static void bm_kill_only_vert(BMesh *bm, BMVert *v) if (v->head.data) CustomData_bmesh_free_block(&bm->vdata, &v->head.data); - BLI_mempool_free(bm->toolflagpool, v->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, v->oflags); + } BLI_mempool_free(bm->vpool, v); } @@ -513,7 +537,9 @@ static void bm_kill_only_edge(BMesh *bm, BMEdge *e) if (e->head.data) CustomData_bmesh_free_block(&bm->edata, &e->head.data); - BLI_mempool_free(bm->toolflagpool, e->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, e->oflags); + } BLI_mempool_free(bm->epool, e); } @@ -534,7 +560,9 @@ static void bm_kill_only_face(BMesh *bm, BMFace *f) if (f->head.data) CustomData_bmesh_free_block(&bm->pdata, &f->head.data); - BLI_mempool_free(bm->toolflagpool, f->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, f->oflags); + } BLI_mempool_free(bm->fpool, f); } @@ -558,7 +586,7 @@ static void bm_kill_only_loop(BMesh *bm, BMLoop *l) void BM_face_edges_kill(BMesh *bm, BMFace *f) { BMEdge **edges = NULL; - BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE); BMLoop *l_iter; BMLoop *l_first; int i; @@ -582,7 +610,7 @@ void BM_face_edges_kill(BMesh *bm, BMFace *f) void BM_face_verts_kill(BMesh *bm, BMFace *f) { BMVert **verts = NULL; - BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); BMLoop *l_iter; BMLoop *l_first; int i; @@ -734,7 +762,7 @@ static int bm_loop_reverse_loop(BMesh *bm, BMFace *f const int do_disps = CustomData_has_layer(&bm->ldata, CD_MDISPS); BMLoop *l_iter, *oldprev, *oldnext; BMEdge **edar = NULL; - BLI_array_fixedstack_declare(edar, BM_NGON_STACK_SIZE, len, __func__); + BLI_array_fixedstack_declare(edar, BM_DEFAULT_NGON_STACK_SIZE, len, __func__); int i, j, edok; for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next) { @@ -937,9 +965,9 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del BMEdge **edges = NULL; BMEdge **deledges = NULL; BMVert **delverts = NULL; - BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE); - BLI_array_staticdeclare(deledges, BM_NGON_STACK_SIZE); - BLI_array_staticdeclare(delverts, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE); + BLI_array_staticdeclare(deledges, BM_DEFAULT_NGON_STACK_SIZE); + BLI_array_staticdeclare(delverts, BM_DEFAULT_NGON_STACK_SIZE); BMVert *v1 = NULL, *v2 = NULL; const char *err = NULL; int i, tote = 0; @@ -1021,7 +1049,7 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del } /* create region face */ - newf = BM_face_create_ngon(bm, v1, v2, edges, tote, FALSE); + newf = tote ? BM_face_create_ngon(bm, v1, v2, edges, tote, 0) : NULL; if (UNLIKELY(!newf || BMO_error_occurred(bm))) { if (!BMO_error_occurred(bm)) err = N_("Invalid boundary region to join faces"); @@ -1127,7 +1155,7 @@ static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *UNUSED(example)) BMLoopList *lst; #endif - f = bm_face_create__internal(bm); + f = bm_face_create__internal(bm, 0); #ifdef USE_BMESH_HOLES lst = BLI_mempool_calloc(bm->looplistpool); @@ -1211,11 +1239,11 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, } /* allocate new edge between v1 and v2 */ - e = BM_edge_create(bm, v1, v2, example, nodouble); + e = BM_edge_create(bm, v1, v2, example, nodouble ? BM_CREATE_NO_DOUBLE : 0); f2 = bm_face_create__sfme(bm, f); - f1loop = bm_loop_create(bm, v2, e, f, v2loop); - f2loop = bm_loop_create(bm, v1, e, f2, v1loop); + f1loop = bm_loop_create(bm, v2, e, f, v2loop, 0); + f2loop = bm_loop_create(bm, v1, e, f2, v1loop, 0); f1loop->prev = v2loop->prev; f2loop->prev = v1loop->prev; @@ -1322,10 +1350,10 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, * will be attached to that end and is returned in \a r_e. * * \par Examples: + * *

          *                     E
          *     Before: OV-------------TV
        - *
          *                 E       RE
          *     After:  OV------NV-----TV
          * 
        @@ -1347,8 +1375,8 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) valence2 = bmesh_disk_count(tv); - nv = BM_vert_create(bm, tv->co, tv); - ne = BM_edge_create(bm, nv, tv, e, FALSE); + nv = BM_vert_create(bm, tv->co, tv, 0); + ne = BM_edge_create(bm, nv, tv, e, 0); bmesh_disk_edge_remove(ne, tv); bmesh_disk_edge_remove(ne, nv); @@ -1391,7 +1419,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) nextl = nextl != nextl->radial_next ? nextl->radial_next : NULL; bmesh_radial_loop_remove(l, NULL); - nl = bm_loop_create(bm, NULL, NULL, l->f, l); + nl = bm_loop_create(bm, NULL, NULL, l->f, l, 0); nl->prev = l; nl->next = (l->next); nl->prev->next = nl; @@ -1587,7 +1615,7 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_dou if (LIKELY(radlen)) { BMLoop **loops = NULL; - BLI_array_fixedstack_declare(loops, BM_NGON_STACK_SIZE, radlen, __func__); + BLI_array_fixedstack_declare(loops, BM_DEFAULT_NGON_STACK_SIZE, radlen, __func__); killoop = ke->l; @@ -1773,14 +1801,18 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) bmesh_disk_edge_remove(f1loop->e, f1loop->e->v2); /* deallocate edge and its two loops as well as f2 */ - BLI_mempool_free(bm->toolflagpool, f1loop->e->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, f1loop->e->oflags); + } BLI_mempool_free(bm->epool, f1loop->e); bm->totedge--; BLI_mempool_free(bm->lpool, f1loop); bm->totloop--; BLI_mempool_free(bm->lpool, f2loop); bm->totloop--; - BLI_mempool_free(bm->toolflagpool, f2->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, f2->oflags); + } BLI_mempool_free(bm->fpool, f2); bm->totface--; /* account for both above */ @@ -1808,23 +1840,28 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) */ int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target) { - BMEdge *e; - + void *loops_stack[BM_DEFAULT_ITER_STACK_SIZE]; BMLoop **loops; int i, loops_tot; + BMEdge *e; + /* verts already spliced */ if (v == v_target) { return FALSE; } /* we can't modify the vert while iterating so first allocate an array of loops */ - loops = BM_iter_as_arrayN(bm, BM_LOOPS_OF_VERT, v, &loops_tot); - if (loops) { + loops = BM_iter_as_arrayN(bm, BM_LOOPS_OF_VERT, v, &loops_tot, + loops_stack, BM_DEFAULT_ITER_STACK_SIZE); + + if (LIKELY(loops != NULL)) { for (i = 0; i < loops_tot; i++) { loops[i]->v = v_target; } - MEM_freeN(loops); + if (loops != (BMLoop **)loops_stack) { + MEM_freeN(loops); + } } /* move all the edges from v's disk to vtarget's disk */ @@ -1898,7 +1935,7 @@ int bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len) verts = MEM_callocN(sizeof(BMVert *) * maxindex, __func__); verts[0] = v; for (i = 1; i < maxindex; i++) { - verts[i] = BM_vert_create(bm, v->co, v); + verts[i] = BM_vert_create(bm, v->co, v, 0); } /* Replace v with the new verts in each group */ @@ -2064,7 +2101,7 @@ int bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep) e->l = l_sep->radial_next; } - ne = BM_edge_create(bm, e->v1, e->v2, e, FALSE); + ne = BM_edge_create(bm, e->v1, e->v2, e, 0); bmesh_radial_loop_remove(l_sep, e); bmesh_radial_append(ne, l_sep); l_sep->e = ne; diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index 0667ed9ea1c..5fd4a6ec7df 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -29,9 +29,18 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short copyedges); -BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example); -BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, int nodouble); -BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, int nodouble); +typedef enum eBMCreateFlag { + /* faces and edges only */ + BM_CREATE_NO_DOUBLE = (1 << 1), + /* Skip CustomData - for all element types data, + * use if we immediately write customdata into the element so this skips copying from 'example' + * args or setting defaults, speeds up conversion when data is converted all at once. */ + BM_CREATE_SKIP_CD = (1 << 2), +} eBMCreateFlag; + +BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, const eBMCreateFlag create_flag); +BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, const eBMCreateFlag create_flag); +BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, const eBMCreateFlag create_flag); void BM_face_edges_kill(BMesh *bm, BMFace *f); void BM_face_verts_kill(BMesh *bm, BMFace *f); diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index 508b3b8fcdf..caf9f3c70d5 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -174,9 +174,9 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source) void **blocks = NULL; float (*cos)[3] = NULL, *w = NULL; - BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(w, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(blocks, BM_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(cos, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(w, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(blocks, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); int i; BM_elem_attrs_copy(bm, bm, source, target); @@ -613,10 +613,10 @@ void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source, void **vblocks = NULL; float (*cos)[3] = NULL, co[3], *w = NULL; float cent[3] = {0.0f, 0.0f, 0.0f}; - BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(w, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(blocks, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(vblocks, BM_NGON_STACK_SIZE, do_vertex ? source->len : 0, __func__); + BLI_array_fixedstack_declare(cos, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(w, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(blocks, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(vblocks, BM_DEFAULT_NGON_STACK_SIZE, do_vertex ? source->len : 0, __func__); int i, ax, ay; BM_elem_attrs_copy(bm, bm, source, target->f); @@ -689,9 +689,9 @@ void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source) void **blocks = NULL; float (*cos)[3] = NULL, *w = NULL; float cent[3] = {0.0f, 0.0f, 0.0f}; - BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(w, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(blocks, BM_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(cos, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(w, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(blocks, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); int i; i = 0; diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c index 1cb95d94e9b..c3f33eb95e1 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.c +++ b/source/blender/bmesh/intern/bmesh_iterators.c @@ -116,10 +116,14 @@ int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, cons * * Caller needs to free the array. */ -void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len) +void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len, + /* optional args to avoid an alloc (normally stack array) */ + void **stack_array, int stack_array_size) { BMIter iter; + BLI_assert(stack_array_size == 0 || (stack_array_size && stack_array)); + /* we can't rely on coun't being set */ switch (itype) { case BM_VERTS_OF_MESH: @@ -137,7 +141,9 @@ void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len) if (BM_iter_init(&iter, bm, itype, data) && iter.count > 0) { BMElem *ele; - BMElem **array = MEM_mallocN(sizeof(ele) * iter.count, __func__); + BMElem **array = iter.count > stack_array_size ? + MEM_mallocN(sizeof(ele) * iter.count, __func__) : + stack_array; int i = 0; *r_len = iter.count; /* set before iterating */ diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h index 3c42b3d610c..7291bca6356 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.h +++ b/source/blender/bmesh/intern/bmesh_iterators.h @@ -107,14 +107,14 @@ typedef struct BMIter { BMesh *bm; void (*begin)(struct BMIter *iter); void *(*step)(struct BMIter *iter); - /* +#if 0 union { void *p; int i; long l; float f; } filter; - */ +#endif int count; /* note, only some iterators set this, don't rely on it */ char itype; } BMIter; @@ -125,7 +125,8 @@ __attribute__((warn_unused_result)) #endif ; int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len); -void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len) +void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len, + void **stack_array, int stack_array_size) #ifdef __GNUC__ __attribute__((warn_unused_result)) #endif diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index d3e3bcd3556..590edc45d07 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -42,8 +42,8 @@ #include "intern/bmesh_private.h" /* used as an extern, defined in bmesh.h */ -BMAllocTemplate bm_mesh_allocsize_default = {512, 1024, 2048, 512}; -BMAllocTemplate bm_mesh_chunksize_default = {512, 1024, 2048, 512}; +const BMAllocTemplate bm_mesh_allocsize_default = {512, 1024, 2048, 512}; +const BMAllocTemplate bm_mesh_chunksize_default = {512, 1024, 2048, 512}; static void bm_mempool_init(BMesh *bm, const BMAllocTemplate *allocsize) { @@ -59,9 +59,45 @@ static void bm_mempool_init(BMesh *bm, const BMAllocTemplate *allocsize) #ifdef USE_BMESH_HOLES bm->looplistpool = BLI_mempool_create(sizeof(BMLoopList), 512, 512, 0); #endif +} - /* allocate one flag pool that we don't get rid of. */ - bm->toolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), 512, 512, 0); +void BM_mesh_elem_toolflags_ensure(BMesh *bm) +{ + if (bm->toolflagpool == NULL) { + const int totflagpool_size = max_ii(512, bm->totvert + bm->totedge + bm->totface); + BLI_mempool *toolflagpool; + + BMIter iter; + BMElemF *ele; + const char iter_types[3] = {BM_VERTS_OF_MESH, + BM_EDGES_OF_MESH, + BM_FACES_OF_MESH}; + + int i; + + BLI_assert(bm->totflags == 0); + + /* allocate one flag pool that we don't get rid of. */ + toolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), totflagpool_size, 512, 0); + + + for (i = 0; i < 3; i++) { + BM_ITER_MESH (ele, &iter, bm, iter_types[i]) { + ele->oflags = BLI_mempool_calloc(toolflagpool); + } + } + + bm->toolflagpool = toolflagpool; + bm->totflags = 1; + } +} + +void BM_mesh_elem_toolflags_clear(BMesh *bm) +{ + if (bm->toolflagpool) { + BLI_mempool_destroy(bm->toolflagpool); + bm->toolflagpool = NULL; + } } /** @@ -73,7 +109,7 @@ static void bm_mempool_init(BMesh *bm, const BMAllocTemplate *allocsize) * * \note ob is needed by multires */ -BMesh *BM_mesh_create(BMAllocTemplate *allocsize) +BMesh *BM_mesh_create(const BMAllocTemplate *allocsize) { /* allocate the structure */ BMesh *bm = MEM_callocN(sizeof(BMesh), __func__); @@ -83,7 +119,7 @@ BMesh *BM_mesh_create(BMAllocTemplate *allocsize) /* allocate one flag pool that we don't get rid of. */ bm->stackdepth = 1; - bm->totflags = 1; + bm->totflags = 0; CustomData_reset(&bm->vdata); CustomData_reset(&bm->edata); @@ -143,7 +179,7 @@ void BM_mesh_data_free(BMesh *bm) BLI_mempool_destroy(bm->fpool); /* destroy flag pool */ - BLI_mempool_destroy(bm->toolflagpool); + BM_mesh_elem_toolflags_clear(bm); #ifdef USE_BMESH_HOLES BLI_mempool_destroy(bm->looplistpool); @@ -170,6 +206,11 @@ void BM_mesh_clear(BMesh *bm) bm->stackdepth = 1; bm->totflags = 1; + + CustomData_reset(&bm->vdata); + CustomData_reset(&bm->edata); + CustomData_reset(&bm->ldata); + CustomData_reset(&bm->pdata); } /** diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h index 8b6ef9aa3e0..8baba568fb8 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.h +++ b/source/blender/bmesh/intern/bmesh_mesh.h @@ -29,7 +29,9 @@ struct BMAllocTemplate; -BMesh *BM_mesh_create(struct BMAllocTemplate *allocsize); +void BM_mesh_elem_toolflags_ensure(BMesh *bm); +void BM_mesh_elem_toolflags_clear(BMesh *bm); +BMesh *BM_mesh_create(const struct BMAllocTemplate *allocsize); void BM_mesh_free(BMesh *bm); void BM_mesh_data_free(BMesh *bm); @@ -55,7 +57,11 @@ typedef struct BMAllocTemplate { int totvert, totedge, totloop, totface; } BMAllocTemplate; -extern BMAllocTemplate bm_mesh_allocsize_default; -extern BMAllocTemplate bm_mesh_chunksize_default; +extern const BMAllocTemplate bm_mesh_allocsize_default; +extern const BMAllocTemplate bm_mesh_chunksize_default; + +enum { + BM_MESH_CREATE_USE_TOOLFLAGS = (1 << 0) +}; #endif /* __BMESH_MESH_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 62abf43829b..388d148377a 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -206,7 +206,7 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE); for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) { - v = BM_vert_create(bm, keyco && set_key ? keyco[i] : mvert->co, NULL); + v = BM_vert_create(bm, keyco && set_key ? keyco[i] : mvert->co, NULL, BM_CREATE_SKIP_CD); BM_elem_index_set(v, i); /* set_ok */ vt[i] = v; @@ -220,11 +220,11 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) normal_short_to_float_v3(v->no, mvert->no); - BM_elem_float_data_set(&bm->vdata, v, CD_BWEIGHT, (float)mvert->bweight / 255.0f); - - /* Copy Custom Dat */ + /* Copy Custom Data */ CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data); + BM_elem_float_data_set(&bm->vdata, v, CD_BWEIGHT, (float)mvert->bweight / 255.0f); + /* set shapekey data */ if (me->key) { /* set shape key original index */ @@ -254,7 +254,7 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) medge = me->medge; for (i = 0; i < me->totedge; i++, medge++) { - e = BM_edge_create(bm, vt[medge->v1], vt[medge->v2], NULL, FALSE); + e = BM_edge_create(bm, vt[medge->v1], vt[medge->v2], NULL, BM_CREATE_SKIP_CD); BM_elem_index_set(e, i); /* set_ok */ et[i] = e; @@ -312,7 +312,7 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) } #endif - f = BM_face_create(bm, verts, fedges, mpoly->totloop, FALSE); + f = BM_face_create(bm, verts, fedges, mpoly->totloop, BM_CREATE_SKIP_CD); if (UNLIKELY(f == NULL)) { printf("%s: Warning! Bad face in mesh" @@ -338,7 +338,7 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) j = 0; BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, j) { /* Save index of correspsonding MLoop */ - BM_elem_index_set(l, mpoly->loopstart + j); /* set_loop */ + CustomData_to_bmesh_block(&me->ldata, &bm->ldata, mpoly->loopstart + j, &l->head.data); } /* Copy Custom Data */ @@ -347,23 +347,6 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) bm->elem_index_dirty &= ~BM_FACE; /* added in order, clear dirty flag */ - { - BMIter fiter; - BMIter liter; - - /* Copy over loop CustomData. Doing this in a separate loop isn't necessary - * but is an optimization, to avoid copying a bunch of interpolated customdata - * for each BMLoop (from previous BMLoops using the same edge), always followed - * by freeing the interpolated data and overwriting it with data from the Mesh. */ - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - int li = BM_elem_index_get(l); - CustomData_to_bmesh_block(&me->ldata, &bm->ldata, li, &l->head.data); - BM_elem_index_set(l, 0); /* set_loop */ - } - } - } - if (me->mselect && me->totselect != 0) { BMVert **vert_array = MEM_callocN(sizeof(BMVert *) * bm->totvert, diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 62374d8b7bb..89516061f91 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -118,7 +118,7 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v) e = v->e; do { e = bmesh_disk_edge_next(e, v); - if (!(BM_edge_share_face_count(e, v->e))) { + if (!(BM_edge_share_face_check(e, v->e))) { keepedge = e; baseedge = v->e; break; @@ -142,9 +142,10 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v) return FALSE; } #else - BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, TRUE); - - if (!BM_vert_collapse_faces(bm, v->e, v, 1.0, FALSE, TRUE)) { + if (UNLIKELY(!BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, TRUE))) { + return FALSE; + } + else if (UNLIKELY(!BM_vert_collapse_faces(bm, v->e, v, 1.0, FALSE, TRUE))) { return FALSE; } #endif diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 31698f0abc1..58c6e051e48 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -47,9 +47,9 @@ * "in" (e.g. edgefacein). for three-type slots, use geom. * * for output slots, for single-type geometry slots, use the type name plus "out", - * (e.g. vertout), for double-type slots, use the two type names plus "out", - * (e.g. vertfaceout), for three-type slots, use geom. note that you can also - * use more esohteric names (e.g. skirtout) so long as the comment next to the + * (e.g. verts.out), for double-type slots, use the two type names plus "out", + * (e.g. vertfaces.out), for three-type slots, use geom. note that you can also + * use more esohteric names (e.g. geom_skirt.out) so long as the comment next to the * slot definition tells you what types of elements are in it. * */ @@ -59,8 +59,10 @@ #include "bmesh.h" #include "intern/bmesh_private.h" -/* ok, I'm going to write a little docgen script. so all - * bmop comments must conform to the following template/rules: +/* The formatting of these bmesh operators is parsed by + * 'doc/python_api/rst_from_bmesh_opdefines.py' + * for use in python docs, so reStructuredText may be used + * rather then doxygen syntax. * * template (py quotes used because nested comments don't work * on all C compilers): @@ -79,250 +81,291 @@ * so the first line is the "title" of the bmop. * subsequent line blocks separated by blank lines * are paragraphs. individual descriptions of slots - * would be extracted from comments - * next to them, e.g. + * are extracted from comments next to them. * - * {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, //output slot, boundary region + * eg: + * {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, """ output slot, boundary region """ * - * the doc generator would automatically detect the presence of "output slot" - * and flag the slot as an output. the same happens for "input slot". also - * note that "edges", "faces", "verts", "loops", and "geometry" are valid - * substitutions for "slot". + * ... or: * - * note that slots default to being input slots. + * """ output slot, boundary region """ + * {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, + * + * Both are acceptable. + * note that '//' comments are ignored. */ /* - * Vertex Smooth + * Vertex Smooth. * * Smooths vertices by using a basic vertex averaging scheme. */ static BMOpDefine bmo_smooth_vert_def = { "smooth_vert", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_BOOL, "mirror_clip_x"}, /* set vertices close to the x axis before the operation to 0 */ - {BMO_OP_SLOT_BOOL, "mirror_clip_y"}, /* set vertices close to the y axis before the operation to 0 */ - {BMO_OP_SLOT_BOOL, "mirror_clip_z"}, /* set vertices close to the z axis before the operation to 0 */ - {BMO_OP_SLOT_FLT, "clipdist"}, /* clipping threshod for the above three slots */ - {BMO_OP_SLOT_BOOL, "use_axis_x"}, /* smooth vertices along X axis */ - {BMO_OP_SLOT_BOOL, "use_axis_y"}, /* smooth vertices along Y axis */ - {BMO_OP_SLOT_BOOL, "use_axis_z"}, /* smooth vertices along Z axis */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"mirror_clip_x", BMO_OP_SLOT_BOOL}, /* set vertices close to the x axis before the operation to 0 */ + {"mirror_clip_y", BMO_OP_SLOT_BOOL}, /* set vertices close to the y axis before the operation to 0 */ + {"mirror_clip_z", BMO_OP_SLOT_BOOL}, /* set vertices close to the z axis before the operation to 0 */ + {"clip_dist", BMO_OP_SLOT_FLT}, /* clipping threshold for the above three slots */ + {"use_axis_x", BMO_OP_SLOT_BOOL}, /* smooth vertices along X axis */ + {"use_axis_y", BMO_OP_SLOT_BOOL}, /* smooth vertices along Y axis */ + {"use_axis_z", BMO_OP_SLOT_BOOL}, /* smooth vertices along Z axis */ + {{'\0'}}, }, + {{{'\0'}}}, /* no output */ bmo_smooth_vert_exec, 0 }; /* - * Vertext Smooth Laplacian + * Vertext Smooth Laplacian. + * * Smooths vertices by using Laplacian smoothing propose by. - * Desbrun, et al. Implicit Fairing of Irregular Meshes using Diffusion and Curvature Flow -*/ + * Desbrun, et al. Implicit Fairing of Irregular Meshes using Diffusion and Curvature Flow. + */ static BMOpDefine bmo_smooth_laplacian_vert_def = { "smooth_laplacian_vert", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, //input vertices - {BMO_OP_SLOT_FLT, "lambda"}, //lambda param - {BMO_OP_SLOT_FLT, "lambda_border"}, //lambda param in border - {BMO_OP_SLOT_BOOL, "use_x"}, //Smooth object along X axis - {BMO_OP_SLOT_BOOL, "use_y"}, //Smooth object along Y axis - {BMO_OP_SLOT_BOOL, "use_z"}, //Smooth object along Z axis - {BMO_OP_SLOT_BOOL, "volume_preservation"}, //Apply volume preservation after smooth - {0} /* null-terminating sentinel */, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"lambda", BMO_OP_SLOT_FLT}, /* lambda param */ + {"lambda_border", BMO_OP_SLOT_FLT}, /* lambda param in border */ + {"use_x", BMO_OP_SLOT_BOOL}, /* Smooth object along X axis */ + {"use_y", BMO_OP_SLOT_BOOL}, /* Smooth object along Y axis */ + {"use_z", BMO_OP_SLOT_BOOL}, /* Smooth object along Z axis */ + {"preserve_volume", BMO_OP_SLOT_BOOL}, /* Apply volume preservation after smooth */ + {{'\0'}}, }, + {{{'\0'}}}, /* no output */ bmo_smooth_laplacian_vert_exec, 0 }; /* - * Right-Hand Faces + * Right-Hand Faces. * * Computes an "outside" normal for the specified input faces. */ - static BMOpDefine bmo_recalc_face_normals_def = { "recalc_face_normals", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, - {BMO_OP_SLOT_BOOL, "do_flip"}, /* internal flag, used by bmesh_rationalize_normals */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"use_flip", BMO_OP_SLOT_BOOL}, /* Reverse the result */ + {{'\0'}}, }, + {{{'\0'}}}, /* no output */ bmo_recalc_face_normals_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Region Extend + * Region Extend. * * used to implement the select more/less tools. * this puts some geometry surrounding regions of - * geometry in geom into geomout. + * geometry in geom into geom.out. * - * if usefaces is 0 then geomout spits out verts and edges, + * if use_faces is 0 then geom.out spits out verts and edges, * otherwise it spits out faces. */ static BMOpDefine bmo_region_extend_def = { "region_extend", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* output slot, computed boundary geometry. */ - {BMO_OP_SLOT_BOOL, "constrict"}, /* find boundary inside the regions, not outside. */ - {BMO_OP_SLOT_BOOL, "use_faces"}, /* extend from faces instead of edges */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */ + {"use_constrict", BMO_OP_SLOT_BOOL}, /* find boundary inside the regions, not outside. */ + {"use_faces", BMO_OP_SLOT_BOOL}, /* extend from faces instead of edges */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output slot, computed boundary geometry. */ + {{'\0'}}, }, bmo_region_extend_exec, 0 }; /* - * Edge Rotate + * Edge Rotate. * * Rotates edges topologically. Also known as "spin edge" to some people. - * Simple example: [/] becomes [|] then [\]. + * Simple example: ``[/] becomes [|] then [\]``. */ static BMOpDefine bmo_rotate_edges_def = { "rotate_edges", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* newly spun edges */ - {BMO_OP_SLOT_BOOL, "ccw"}, /* rotate edge counter-clockwise if true, othewise clockwise */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate edge counter-clockwise if true, otherwise clockwise */ + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* newly spun edges */ + {{'\0'}}, }, bmo_rotate_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; /* - * Reverse Faces + * Reverse Faces. * - * Reverses the winding (vertex order) of faces. This has the effect of - * flipping the normal. + * Reverses the winding (vertex order) of faces. + * This has the effect of flipping the normal. */ static BMOpDefine bmo_reverse_faces_def = { "reverse_faces", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {{'\0'}}, }, + {{{'\0'}}}, /* no output */ bmo_reverse_faces_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Edge Bisect + * Edge Bisect. * * Splits input edges (but doesn't do anything else). * This creates a 2-valence vert. */ static BMOpDefine bmo_bisect_edges_def = { "bisect_edges", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_INT, "numcuts"}, /* number of cuts */ - {BMO_OP_SLOT_ELEMENT_BUF, "outsplit"}, /* newly created vertices and edges */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"cuts", BMO_OP_SLOT_INT}, /* number of cuts */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom_split.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* newly created vertices and edges */ + {{'\0'}}, }, bmo_bisect_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; /* - * Mirror + * Mirror. * * Mirrors geometry along an axis. The resulting geometry is welded on using - * mergedist. Pairs of original/mirrored vertices are welded using the mergedist + * merge_dist. Pairs of original/mirrored vertices are welded using the merge_dist * parameter (which defines the minimum distance for welding to happen). */ - static BMOpDefine bmo_mirror_def = { "mirror", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix defining the mirror transformation */ - {BMO_OP_SLOT_FLT, "mergedist"}, /* maximum distance for merging. does no merging if 0. */ - {BMO_OP_SLOT_ELEMENT_BUF, "newout"}, /* output geometry, mirrored */ - {BMO_OP_SLOT_INT, "axis"}, /* the axis to use, 0, 1, or 2 for x, y, z */ - {BMO_OP_SLOT_BOOL, "mirror_u"}, /* mirror UVs across the u axis */ - {BMO_OP_SLOT_BOOL, "mirror_v"}, /* mirror UVs across the v axis */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix defining the mirror transformation */ + {"merge_dist", BMO_OP_SLOT_FLT}, /* maximum distance for merging. does no merging if 0. */ + {"axis", BMO_OP_SLOT_INT}, /* the axis to use, 0, 1, or 2 for x, y, z */ + {"mirror_u", BMO_OP_SLOT_BOOL}, /* mirror UVs across the u axis */ + {"mirror_v", BMO_OP_SLOT_BOOL}, /* mirror UVs across the v axis */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output geometry, mirrored */ + {{'\0'}}, + }, bmo_mirror_exec, 0, }; /* - * Find Doubles + * Find Doubles. * - * Takes input verts and find vertices they should weld to. Outputs a - * mapping slot suitable for use with the weld verts bmop. + * Takes input verts and find vertices they should weld to. + * Outputs a mapping slot suitable for use with the weld verts bmop. * * If keep_verts is used, vertices outside that set can only be merged * with vertices in that set. */ static BMOpDefine bmo_find_doubles_def = { "find_doubles", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "keep_verts"}, /* list of verts to keep */ - {BMO_OP_SLOT_FLT, "dist"}, /* minimum distance */ - {BMO_OP_SLOT_MAPPING, "targetmapout"}, - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"keep_verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* list of verts to keep */ + {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ + {{'\0'}}, + }, + /* slots_out */ + {{"targetmap.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, + }, bmo_find_doubles_exec, 0, }; /* - * Remove Doubles + * Remove Doubles. * * Finds groups of vertices closer then dist and merges them together, * using the weld verts bmop. */ static BMOpDefine bmo_remove_doubles_def = { "remove_doubles", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input verts */ - {BMO_OP_SLOT_FLT, "dist"}, /* minimum distance */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */ + {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_remove_doubles_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Auto Merge + * Auto Merge. * - * Finds groups of vertices closer then dist and merges them together, + * Finds groups of vertices closer then **dist** and merges them together, * using the weld verts bmop. The merges must go from a vert not in - * verts to one in verts. + * **verts** to one in **verts**. */ static BMOpDefine bmo_automerge_def = { "automerge", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input verts */ - {BMO_OP_SLOT_FLT, "dist"}, /* minimum distance */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */ + {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_automerge_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Collapse Connected + * Collapse Connected. * * Collapses connected vertices */ static BMOpDefine bmo_collapse_def = { "collapse", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edge */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_collapse_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; - /* - * Facedata point Merge + * Face-Data Point Merge. * * Merge uv/vcols at a specific vertex. */ static BMOpDefine bmo_pointmerge_facedata_def = { "pointmerge_facedata", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */ - {BMO_OP_SLOT_ELEMENT_BUF, "snapv"}, /* snap verte */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"vert_snap", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, /* snap vertex */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_pointmerge_facedata_exec, 0, }; /* - * Average Vertices Facevert Data + * Average Vertices Facevert Data. * * Merge uv/vcols associated with the input vertices at * the bounding box center. (I know, it's not averaging but @@ -330,145 +373,189 @@ static BMOpDefine bmo_pointmerge_facedata_def = { */ static BMOpDefine bmo_average_vert_facedata_def = { "average_vert_facedata", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertice */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_average_vert_facedata_exec, 0, }; /* - * Point Merge + * Point Merge. * * Merge verts together at a point. */ static BMOpDefine bmo_pointmerge_def = { "pointmerge", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */ - {BMO_OP_SLOT_VEC, "merge_co"}, - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertice */ + {"merge_co", BMO_OP_SLOT_VEC}, + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_pointmerge_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Collapse Connected UVs + * Collapse Connected UV's. * * Collapses connected UV vertices. */ static BMOpDefine bmo_collapse_uvs_def = { "collapse_uvs", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edge */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_collapse_uvs_exec, 0, }; /* - * Weld Verts + * Weld Verts. * - * Welds verts together (kindof like remove doubles, merge, etc, all of which + * Welds verts together (kind-of like remove doubles, merge, etc, all of which * use or will use this bmop). You pass in mappings from vertices to the vertices * they weld with. */ static BMOpDefine bmo_weld_verts_def = { "weld_verts", - {{BMO_OP_SLOT_MAPPING, "targetmap"}, /* maps welded vertices to verts they should weld to */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + /* maps welded vertices to verts they should weld to */ + {{"targetmap", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_weld_verts_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Make Vertex + * Make Vertex. * * Creates a single vertex; this bmop was necessary * for click-create-vertex. */ static BMOpDefine bmo_create_vert_def = { "create_vert", - {{BMO_OP_SLOT_VEC, "co"}, /* the coordinate of the new vert */ - {BMO_OP_SLOT_ELEMENT_BUF, "newvertout"}, /* the new vert */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"co", BMO_OP_SLOT_VEC}, /* the coordinate of the new vert */ + {{'\0'}}, + }, + /* slots_out */ + {{"vert.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* the new vert */ + {{'\0'}}, + }, bmo_create_vert_exec, 0, }; /* - * Join Triangles + * Join Triangles. * * Tries to intelligently join triangles according * to various settings and stuff. */ static BMOpDefine bmo_join_triangles_def = { "join_triangles", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input geometry. */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* joined faces */ - {BMO_OP_SLOT_BOOL, "cmp_sharp"}, - {BMO_OP_SLOT_BOOL, "cmp_uvs"}, - {BMO_OP_SLOT_BOOL, "cmp_vcols"}, - {BMO_OP_SLOT_BOOL, "cmp_materials"}, - {BMO_OP_SLOT_FLT, "limit"}, - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input geometry. */ + {"cmp_sharp", BMO_OP_SLOT_BOOL}, + {"cmp_uvs", BMO_OP_SLOT_BOOL}, + {"cmp_vcols", BMO_OP_SLOT_BOOL}, + {"cmp_materials", BMO_OP_SLOT_BOOL}, + {"limit", BMO_OP_SLOT_FLT}, + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* joined faces */ + {{'\0'}}, + }, bmo_join_triangles_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Contextual Create + * Contextual Create. * - * This is basically fkey, it creates + * This is basically F-key, it creates * new faces from vertices, makes stuff from edge nets, - * makes wire edges, etc. It also dissolves - * faces. + * makes wire edges, etc. It also dissolves faces. * * Three verts become a triangle, four become a quad. Two * become a wire edge. */ static BMOpDefine bmo_contextual_create_def = { "contextual_create", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry. */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* newly-made face(s) */ + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry. */ + {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */ + {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth to use */ + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* newly-made face(s) */ /* note, this is for stand-alone edges only, not edges which are apart of newly created faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* newly-made edge(s) */ - {BMO_OP_SLOT_INT, "mat_nr"}, /* material to use */ - {BMO_OP_SLOT_BOOL, "use_smooth"}, /* material to use */ - {0, /* null-terminating sentinel */}}, + {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* newly-made edge(s) */ + {{'\0'}}, + }, bmo_contextual_create_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; /* - * Bridge edge loops with faces + * Bridge edge loops with faces. */ static BMOpDefine bmo_bridge_loops_def = { "bridge_loops", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* new face */ - {BMO_OP_SLOT_BOOL, "use_merge"}, - {BMO_OP_SLOT_FLT, "merge_factor"}, - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edge */ + {"use_merge", BMO_OP_SLOT_BOOL}, + {"merge_factor", BMO_OP_SLOT_FLT}, + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */ + {{'\0'}}, + }, bmo_bridge_loops_exec, 0, }; +/* + * Edge Net Fill. + * + * Create faces defined by enclosed edges. + */ static BMOpDefine bmo_edgenet_fill_def = { "edgenet_fill", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {BMO_OP_SLOT_MAPPING, "restrict"}, /* restricts edges to groups. maps edges to integer */ - {BMO_OP_SLOT_BOOL, "use_restrict"}, - {BMO_OP_SLOT_BOOL, "use_fill_check"}, - {BMO_OP_SLOT_ELEMENT_BUF, "excludefaces"}, /* list of faces to ignore for manifold check */ - {BMO_OP_SLOT_MAPPING, "faceout_groupmap"}, /* maps new faces to the group numbers they came fro */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* new face */ - {BMO_OP_SLOT_INT, "mat_nr"}, /* material to use */ - {BMO_OP_SLOT_BOOL, "use_smooth"}, /* material to use */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edge */ + /* restricts edges to groups. maps edges to integer */ + {"restrict", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_BOOL}}, + {"use_restrict", BMO_OP_SLOT_BOOL}, + {"use_fill_check", BMO_OP_SLOT_BOOL}, + {"exclude_faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* list of faces to ignore for manifold check */ + {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */ + {"use_smooth", BMO_OP_SLOT_BOOL}, /* material to use */ + {{'\0'}}, + }, + /* slots_out */ + /* maps new faces to the group numbers they came from */ + {{"face_groupmap.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new face */ + {{'\0'}}, + }, bmo_edgenet_fill_exec, 0, }; /* - * Edgenet Prepare + * Edgenet Prepare. * * Identifies several useful edge loop cases and modifies them so * they'll become a face when edgenet_fill is called. The cases covered are: @@ -479,708 +566,992 @@ static BMOpDefine bmo_edgenet_fill_def = { */ static BMOpDefine bmo_edgenet_prepare_def = { "edgenet_prepare", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* new edges */ - {0, /* null-terminating sentinel */}}, - bmo_edgenet_prepare, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* new edges */ + {{'\0'}}, + }, + bmo_edgenet_prepare_exec, 0, }; /* - * Rotate + * Rotate. * - * Rotate vertices around a center, using a 3x3 rotation - * matrix. Equivalent of the old rotateflag function. + * Rotate vertices around a center, using a 3x3 rotation matrix. */ static BMOpDefine bmo_rotate_def = { "rotate", - {{BMO_OP_SLOT_VEC, "cent"}, /* center of rotation */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix defining rotation */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"cent", BMO_OP_SLOT_VEC}, /* center of rotation */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix defining rotation */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_rotate_exec, 0, }; /* - * Translate + * Translate. * - * Translate vertices by an offset. Equivalent of the - * old translateflag function. + * Translate vertices by an offset. */ static BMOpDefine bmo_translate_def = { "translate", - {{BMO_OP_SLOT_VEC, "vec"}, /* translation offset */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"vec", BMO_OP_SLOT_VEC}, /* translation offset */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_translate_exec, 0, }; /* - * Scale + * Scale. * * Scales vertices by an offset. */ static BMOpDefine bmo_scale_def = { "scale", - {{BMO_OP_SLOT_VEC, "vec"}, /* scale factor */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"vec", BMO_OP_SLOT_VEC}, /* scale factor */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_scale_exec, 0, }; /* - * Transform + * Transform. * * Transforms a set of vertices by a matrix. Multiplies * the vertex coordinates with the matrix. */ static BMOpDefine bmo_transform_def = { "transform", - {{BMO_OP_SLOT_MAT, "mat"}, /* transform matrix */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"matrix", BMO_OP_SLOT_MAT}, /* transform matrix */ + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_transform_exec, 0, }; /* - * Object Load BMesh + * Object Load BMesh. * * Loads a bmesh into an object/mesh. This is a "private" * bmop. */ static BMOpDefine bmo_object_load_bmesh_def = { "object_load_bmesh", - {{BMO_OP_SLOT_PTR, "scene"}, - {BMO_OP_SLOT_PTR, "object"}, - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"scene", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_SCENE}}, + {"object", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_object_load_bmesh_exec, 0, }; /* - * BMesh to Mesh + * BMesh to Mesh. * * Converts a bmesh to a Mesh. This is reserved for exiting editmode. */ static BMOpDefine bmo_bmesh_to_mesh_def = { "bmesh_to_mesh", - {{BMO_OP_SLOT_PTR, "mesh"}, /* pointer to a mesh structure to fill in */ - {BMO_OP_SLOT_PTR, "object"}, /* pointer to an object structure */ - {BMO_OP_SLOT_BOOL, "notessellation"}, /* don't calculate mfaces */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + { + /* pointer to a mesh structure to fill in */ + {"mesh", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_MESH}}, + /* pointer to an object structure */ + {"object", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, + {"skip_tessface", BMO_OP_SLOT_BOOL}, /* don't calculate mfaces */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_bmesh_to_mesh_exec, 0, }; /* - * Mesh to BMesh + * Mesh to BMesh. * * Load the contents of a mesh into the bmesh. this bmop is private, it's * reserved exclusively for entering editmode. */ static BMOpDefine bmo_mesh_to_bmesh_def = { "mesh_to_bmesh", - {{BMO_OP_SLOT_PTR, "mesh"}, /* pointer to a Mesh structure */ - {BMO_OP_SLOT_PTR, "object"}, /* pointer to an Object structure */ - {BMO_OP_SLOT_BOOL, "set_shapekey"}, /* load active shapekey coordinates into verts */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + { + /* pointer to a Mesh structure */ + {"mesh", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_MESH}}, + /* pointer to an Object structure */ + {"object", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}}, + {"use_shapekey", BMO_OP_SLOT_BOOL}, /* load active shapekey coordinates into verts */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_mesh_to_bmesh_exec, 0 }; /* - * Individual Face Extrude + * Individual Face Extrude. * * Extrudes faces individually. */ static BMOpDefine bmo_extrude_discrete_faces_def = { "extrude_discrete_faces", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "skirtout"}, /* output skirt geometry, faces and edges */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, + }, bmo_extrude_discrete_faces_exec, 0 }; /* - * Extrude Only Edges + * Extrude Only Edges. * * Extrudes Edges into faces, note that this is very simple, there's no fancy * winged extrusion. */ static BMOpDefine bmo_extrude_edge_only_def = { "extrude_edge_only", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* output geometry */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output geometry */ + {{'\0'}}, + }, bmo_extrude_edge_only_exec, 0 }; /* - * Individual Vertex Extrude + * Individual Vertex Extrude. * * Extrudes wire edges from vertices. */ static BMOpDefine bmo_extrude_vert_indiv_def = { "extrude_vert_indiv", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* output wire edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output wire edges */ + {"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output vertices */ + {{'\0'}}, + }, bmo_extrude_vert_indiv_exec, 0 }; +/* + * Connect Verts. + * + * Split faces by adding edges that connect **verts**. + */ static BMOpDefine bmo_connect_verts_def = { "connect_verts", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {{'\0'}}, + }, bmo_connect_verts_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Extrude Faces. + * + * Extrude operator (does not transform) + */ static BMOpDefine bmo_extrude_face_region_def = { "extrude_face_region", - {{BMO_OP_SLOT_ELEMENT_BUF, "edgefacein"}, - {BMO_OP_SLOT_MAPPING, "exclude"}, - {BMO_OP_SLOT_BOOL, "alwayskeeporig"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* edges and faces */ + {"edges_exclude", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_EMPTY}}, + {"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{'\0'}}, + }, bmo_extrude_face_region_exec, 0 }; +/* + * Dissolve Verts. + */ static BMOpDefine bmo_dissolve_verts_def = { "dissolve_verts", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_dissolve_verts_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Dissolve Edges. + */ static BMOpDefine bmo_dissolve_edges_def = { "dissolve_edges", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {BMO_OP_SLOT_ELEMENT_BUF, "regionout"}, - {BMO_OP_SLOT_BOOL, "use_verts"}, /* dissolve verts left between only 2 edges. */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"use_verts", BMO_OP_SLOT_BOOL}, /* dissolve verts left between only 2 edges. */ + {{'\0'}}, + }, + /* slots_out */ + {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{'\0'}}, + }, bmo_dissolve_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Dissolve Edge Loop. + */ static BMOpDefine bmo_dissolve_edge_loop_def = { "dissolve_edge_loop", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {BMO_OP_SLOT_ELEMENT_BUF, "regionout"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {{'\0'}}, + }, + /* slots_out */ + {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{'\0'}}, + }, bmo_dissolve_edgeloop_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Dissolve Faces. + */ static BMOpDefine bmo_dissolve_faces_def = { "dissolve_faces", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, - {BMO_OP_SLOT_ELEMENT_BUF, "regionout"}, - {BMO_OP_SLOT_BOOL, "use_verts"}, /* dissolve verts left between only 2 edges. */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"use_verts", BMO_OP_SLOT_BOOL}, /* dissolve verts left between only 2 edges. */ + {{'\0'}}, + }, + /* slots_out */ + {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {{'\0'}}, + }, bmo_dissolve_faces_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Limited Dissolve. + * + * Dissolve planar faces and co-linear edges. + */ static BMOpDefine bmo_dissolve_limit_def = { "dissolve_limit", - {{BMO_OP_SLOT_FLT, "angle_limit"}, /* total rotation angle (degrees) */ - {BMO_OP_SLOT_BOOL, "use_dissolve_boundaries"}, - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, - {BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"angle_limit", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */ + {"use_dissolve_boundaries", BMO_OP_SLOT_BOOL}, + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_dissolve_limit_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Triangulate. + */ static BMOpDefine bmo_triangulate_def = { "triangulate", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, - {BMO_OP_SLOT_MAPPING, "facemap"}, - {BMO_OP_SLOT_BOOL, "use_beauty"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"use_beauty", BMO_OP_SLOT_BOOL}, + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, + {"face_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, + }, bmo_triangulate_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Un-Subdivide. + * + * Reduce detail in geometry containing grids. + */ static BMOpDefine bmo_unsubdivide_def = { "unsubdivide", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_INT, "iterations"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"iterations", BMO_OP_SLOT_INT}, + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_unsubdivide_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Subdivide Edges. + * + * Advanced operator for subdividing edges + * with options for face patterns, smoothing and randomization. + */ static BMOpDefine bmo_subdivide_edges_def = { "subdivide_edges", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {BMO_OP_SLOT_FLT, "smooth"}, - {BMO_OP_SLOT_FLT, "fractal"}, - {BMO_OP_SLOT_FLT, "along_normal"}, - {BMO_OP_SLOT_INT, "numcuts"}, - {BMO_OP_SLOT_INT, "seed"}, - {BMO_OP_SLOT_MAPPING, "custompatterns"}, - {BMO_OP_SLOT_MAPPING, "edgepercents"}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"smooth", BMO_OP_SLOT_FLT}, + {"fractal", BMO_OP_SLOT_FLT}, + {"along_normal", BMO_OP_SLOT_FLT}, + {"cuts", BMO_OP_SLOT_INT}, + {"seed", BMO_OP_SLOT_INT}, + {"custom_patterns", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL}}, /* uses custom pointers */ + {"edge_percents", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_FLT}}, - /* these next three can have multiple types of elements in them */ - {BMO_OP_SLOT_ELEMENT_BUF, "outinner"}, - {BMO_OP_SLOT_ELEMENT_BUF, "outsplit"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* contains all output geometr */ - - {BMO_OP_SLOT_INT, "quadcornertype"}, /* quad corner type, see bmesh_operators.h */ - {BMO_OP_SLOT_BOOL, "use_gridfill"}, /* fill in fully-selected faces with a grid */ - {BMO_OP_SLOT_BOOL, "use_singleedge"}, /* tessellate the case of one edge selected in a quad or triangle */ - {BMO_OP_SLOT_BOOL, "use_sphere"}, /* for making new primitives only */ - - {0} /* null-terminating sentinel */, + {"quad_corner_type", BMO_OP_SLOT_INT}, /* quad corner type, see bmesh_operators.h */ + {"use_grid_fill", BMO_OP_SLOT_BOOL}, /* fill in fully-selected faces with a grid */ + {"use_single_edge", BMO_OP_SLOT_BOOL}, /* tessellate the case of one edge selected in a quad or triangle */ + {"use_only_quads", BMO_OP_SLOT_BOOL}, /* only subdivide quads (for loopcut) */ + {"use_sphere", BMO_OP_SLOT_BOOL}, /* for making new primitives only */ + {{'\0'}}, + }, + /* slots_out */ + {/* these next three can have multiple types of elements in them */ + {"geom_inner.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom_split.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* contains all output geometr */ + {{'\0'}}, }, bmo_subdivide_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; +/* + * Delete Geometry. + * + * Utility operator to delete geometry. + */ static BMOpDefine bmo_delete_def = { "delete", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_INT, "context"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"context", BMO_OP_SLOT_INT}, /* enum DEL_VERTS ... */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_delete_exec, 0 }; +/* + * Duplicate Geometry. + * + * Utility operator to duplicate geometry, + * optionally into a destination mesh. + */ static BMOpDefine bmo_duplicate_def = { "duplicate", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "origout"}, - {BMO_OP_SLOT_ELEMENT_BUF, "newout"}, + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + /* destination bmesh, if NULL will use current on */ + {"dest", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, + {{'\0'}}, + }, + /* slots_out */ + {{"geom_orig.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* facemap maps from source faces to dupe * faces, and from dupe faces to source faces */ - {BMO_OP_SLOT_MAPPING, "facemap"}, - {BMO_OP_SLOT_MAPPING, "boundarymap"}, - {BMO_OP_SLOT_MAPPING, "isovertmap"}, - {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current on */ - {0} /* null-terminating sentinel */}, + {"face_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"boundary_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"isovert_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, + }, bmo_duplicate_exec, 0 }; +/* + * Split Off Geometry. + * + * Disconnect geometry from adjacent edges and faces, + * optionally into a destination mesh. + */ static BMOpDefine bmo_split_def = { "split", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - {BMO_OP_SLOT_MAPPING, "boundarymap"}, - {BMO_OP_SLOT_MAPPING, "isovertmap"}, - {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current on */ - {BMO_OP_SLOT_BOOL, "use_only_faces"}, /* when enabled. don't duplicate loose verts/edges */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + /* destination bmesh, if NULL will use current one */ + {"dest", BMO_OP_SLOT_PTR, {BMO_OP_SLOT_SUBTYPE_PTR_BMESH}}, + {"use_only_faces", BMO_OP_SLOT_BOOL}, /* when enabled. don't duplicate loose verts/edges */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"boundary_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"isovert_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {{'\0'}}, + }, bmo_split_exec, 0 }; /* - * Spin + * Spin. * * Extrude or duplicate geometry a number of times, * rotating and possibly translating after each step */ static BMOpDefine bmo_spin_def = { "spin", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "lastout"}, /* result of last step */ - {BMO_OP_SLOT_VEC, "cent"}, /* rotation center */ - {BMO_OP_SLOT_VEC, "axis"}, /* rotation axis */ - {BMO_OP_SLOT_VEC, "dvec"}, /* translation delta per step */ - {BMO_OP_SLOT_FLT, "ang"}, /* total rotation angle (degrees) */ - {BMO_OP_SLOT_INT, "steps"}, /* number of steps */ - {BMO_OP_SLOT_BOOL, "do_dupli"}, /* duplicate or extrude? */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"cent", BMO_OP_SLOT_VEC}, /* rotation center */ + {"axis", BMO_OP_SLOT_VEC}, /* rotation axis */ + {"dvec", BMO_OP_SLOT_VEC}, /* translation delta per step */ + {"angle", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */ + {"steps", BMO_OP_SLOT_INT}, /* number of steps */ + {"use_duplicate", BMO_OP_SLOT_BOOL}, /* duplicate or extrude? */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom_last.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* result of last step */ + {{'\0'}}, + }, bmo_spin_exec, 0 }; /* - * Similar faces search + * Similar Faces Search. * * Find similar faces (area/material/perimeter, ...). */ static BMOpDefine bmo_similar_faces_def = { "similar_faces", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ - {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"type", BMO_OP_SLOT_INT}, /* type of selection */ + {"thresh", BMO_OP_SLOT_FLT}, /* threshold of selection */ + {"compare", BMO_OP_SLOT_INT}, /* comparison method */ + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, + }, bmo_similar_faces_exec, 0 }; /* - * Similar edges search + * Similar Edges Search. * * Find similar edges (length, direction, edge, seam, ...). */ static BMOpDefine bmo_similar_edges_def = { "similar_edges", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* output edges */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ - {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"type", BMO_OP_SLOT_INT}, /* type of selection */ + {"thresh", BMO_OP_SLOT_FLT}, /* threshold of selection */ + {"compare", BMO_OP_SLOT_INT}, /* comparison method */ + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output edges */ + {{'\0'}}, + }, bmo_similar_edges_exec, 0 }; /* - * Similar vertices search + * Similar Verts Search. * * Find similar vertices (normal, face, vertex group, ...). */ static BMOpDefine bmo_similar_verts_def = { "similar_verts", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ - {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ + {"type", BMO_OP_SLOT_INT}, /* type of selection */ + {"thresh", BMO_OP_SLOT_FLT}, /* threshold of selection */ + {"compare", BMO_OP_SLOT_INT}, /* comparison method */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output vertices */ + {{'\0'}}, + }, bmo_similar_verts_exec, 0 }; /* - * uv rotation - * cycle the uvs + * UV Rotation. + * + * Cycle the loop UV's */ static BMOpDefine bmo_rotate_uvs_def = { "rotate_uvs", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_INT, "dir"}, /* direction */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate counter-clockwise if true, otherwise clockwise */ + {{'\0'}}, + }, + /* slots_out */ + {{{'\0'}}}, /* no output */ bmo_rotate_uvs_exec, 0 }; /* - * uv reverse - * reverse the uvs + * UV Reverse. + * + * Reverse the UV's */ static BMOpDefine bmo_reverse_uvs_def = { "reverse_uvs", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_reverse_uvs_exec, 0 }; /* - * color rotation - * cycle the colors + * Color Rotation. + * + * Cycle the loop colors */ static BMOpDefine bmo_rotate_colors_def = { "rotate_colors", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_INT, "dir"}, /* direction */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate counter-clockwise if true, otherwise clockwise */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_rotate_colors_exec, 0 }; /* - * color reverse - * reverse the colors + * Color Reverse + * + * Reverse the loop colors. */ static BMOpDefine bmo_reverse_colors_def = { "reverse_colors", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {{'\0'}}, + }, + {{{'\0'}}}, /* no output */ bmo_reverse_colors_exec, 0 }; /* - * Similar vertices search + * Shortest Path. * - * Find similar vertices (normal, face, vertex group, ...). + * Select the shortest path between 2 verts. */ static BMOpDefine bmo_shortest_path_def = { "shortest_path", - {{BMO_OP_SLOT_ELEMENT_BUF, "startv"}, /* start vertex */ - {BMO_OP_SLOT_ELEMENT_BUF, "endv"}, /* end vertex */ - {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"vert_start", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, /* start vertex */ + {"vert_end", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, /* end vertex */ + {"type", BMO_OP_SLOT_INT}, /* type of selection */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output vertices */ + {{'\0'}}, + }, bmo_shortest_path_exec, 0 }; /* - * Edge Split + * Edge Split. * * Disconnects faces along input edges. */ static BMOpDefine bmo_split_edges_def = { "split_edges", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* old output disconnected edges */ + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ /* needed for vertex rip so we can rip only half an edge at a boundary wich would otherwise split off */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* optional tag verts, use to have greater control of splits */ - {BMO_OP_SLOT_BOOL, "use_verts"}, /* use 'verts' for splitting, else just find verts to split from edges */ - {0} /* null-terminating sentinel */}, + {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* optional tag verts, use to have greater control of splits */ + {"use_verts", BMO_OP_SLOT_BOOL}, /* use 'verts' for splitting, else just find verts to split from edges */ + {{'\0'}}, + }, + /* slots_out */ + {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* old output disconnected edges */ + {{'\0'}}, + }, bmo_split_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; /* - * Create Grid + * Create Grid. * * Creates a grid with a variable number of subdivisions */ static BMOpDefine bmo_create_grid_def = { "create_grid", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_INT, "xsegments"}, /* number of x segments */ - {BMO_OP_SLOT_INT, "ysegments"}, /* number of y segments */ - {BMO_OP_SLOT_FLT, "size"}, /* size of the grid */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"x_segments", BMO_OP_SLOT_INT}, /* number of x segments */ + {"y_segments", BMO_OP_SLOT_INT}, /* number of y segments */ + {"size", BMO_OP_SLOT_FLT}, /* size of the grid */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, bmo_create_grid_exec, 0, }; /* - * Create UV Sphere + * Create UV Sphere. * * Creates a grid with a variable number of subdivisions */ static BMOpDefine bmo_create_uvsphere_def = { "create_uvsphere", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_INT, "segments"}, /* number of u segments */ - {BMO_OP_SLOT_INT, "revolutions"}, /* number of v segment */ - {BMO_OP_SLOT_FLT, "diameter"}, /* diameter */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"u_segments", BMO_OP_SLOT_INT}, /* number of u segments */ + {"v_segments", BMO_OP_SLOT_INT}, /* number of v segment */ + {"diameter", BMO_OP_SLOT_FLT}, /* diameter */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, bmo_create_uvsphere_exec, 0, }; /* - * Create Ico Sphere + * Create Ico-Sphere. * * Creates a grid with a variable number of subdivisions */ static BMOpDefine bmo_create_icosphere_def = { "create_icosphere", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_INT, "subdivisions"}, /* how many times to recursively subdivide the sphere */ - {BMO_OP_SLOT_FLT, "diameter"}, /* diameter */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"subdivisions", BMO_OP_SLOT_INT}, /* how many times to recursively subdivide the sphere */ + {"diameter", BMO_OP_SLOT_FLT}, /* diameter */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, bmo_create_icosphere_exec, 0, }; /* - * Create Suzanne + * Create Suzanne. * - * Creates a monkey. Be wary. + * Creates a monkey (standard blender primitive). */ static BMOpDefine bmo_create_monkey_def = { "create_monkey", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, bmo_create_monkey_exec, 0, }; /* - * Create Cone + * Create Cone. * * Creates a cone with variable depth at both ends */ static BMOpDefine bmo_create_cone_def = { "create_cone", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_BOOL, "cap_ends"}, /* wheter or not to fill in the ends with faces */ - {BMO_OP_SLOT_BOOL, "cap_tris"}, /* fill ends with triangles instead of ngons */ - {BMO_OP_SLOT_INT, "segments"}, - {BMO_OP_SLOT_FLT, "diameter1"}, /* diameter of one end */ - {BMO_OP_SLOT_FLT, "diameter2"}, /* diameter of the opposite */ - {BMO_OP_SLOT_FLT, "depth"}, /* distance between ends */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"cap_ends", BMO_OP_SLOT_BOOL}, /* whether or not to fill in the ends with faces */ + {"cap_tris", BMO_OP_SLOT_BOOL}, /* fill ends with triangles instead of ngons */ + {"segments", BMO_OP_SLOT_INT}, + {"diameter1", BMO_OP_SLOT_FLT}, /* diameter of one end */ + {"diameter2", BMO_OP_SLOT_FLT}, /* diameter of the opposite */ + {"depth", BMO_OP_SLOT_FLT}, /* distance between ends */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, bmo_create_cone_exec, 0, }; /* - * Creates a circle + * Creates a Circle. */ static BMOpDefine bmo_create_circle_def = { "create_circle", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_BOOL, "cap_ends"}, /* wheter or not to fill in the ends with faces */ - {BMO_OP_SLOT_BOOL, "cap_tris"}, /* fill ends with triangles instead of ngons */ - {BMO_OP_SLOT_INT, "segments"}, - {BMO_OP_SLOT_FLT, "diameter"}, /* diameter of one end */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"cap_ends", BMO_OP_SLOT_BOOL}, /* whether or not to fill in the ends with faces */ + {"cap_tris", BMO_OP_SLOT_BOOL}, /* fill ends with triangles instead of ngons */ + {"segments", BMO_OP_SLOT_INT}, + {"diameter", BMO_OP_SLOT_FLT}, /* diameter of one end */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, bmo_create_circle_exec, 0, }; /* - * Create Cone + * Create Cube * - * Creates a cone with variable depth at both ends + * Creates a cube. */ static BMOpDefine bmo_create_cube_def = { "create_cube", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_FLT, "size"}, /* size of the cube */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{"size", BMO_OP_SLOT_FLT}, /* size of the cube */ + {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */ + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ + {{'\0'}}, + }, bmo_create_cube_exec, 0, }; /* - * Bevel + * Bevel. * * Bevels edges and vertices */ static BMOpDefine bmo_bevel_def = { "bevel", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "face_spans"}, /* new geometry */ - {BMO_OP_SLOT_ELEMENT_BUF, "face_holes"}, /* new geometry */ - {BMO_OP_SLOT_BOOL, "use_lengths"}, /* grab edge lengths from a PROP_FLT customdata layer */ - {BMO_OP_SLOT_BOOL, "use_even"}, /* corner vert placement: use shell/angle calculations */ - {BMO_OP_SLOT_BOOL, "use_dist"}, /* corner vert placement: evaluate percent as a distance, - * modifier uses this. We could do this as another float setting */ - {BMO_OP_SLOT_INT, "lengthlayer"}, /* which PROP_FLT layer to us */ - {BMO_OP_SLOT_FLT, "percent"}, /* percentage to expand beveled edge */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input edges and vertices */ + {"offset", BMO_OP_SLOT_FLT}, /* amount to offset beveled edge */ + {"segments", BMO_OP_SLOT_INT}, /* number of segments in bevel */ + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, + }, +/* old bevel*/ +// {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input edges and vertices */ +// {"face_spans", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new geometry */ +// {"face_holes", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new geometry */ +// {"use_lengths", BMO_OP_SLOT_BOOL}, /* grab edge lengths from a PROP_FLT customdata layer */ +// {"use_even", BMO_OP_SLOT_BOOL}, /* corner vert placement: use shell/angle calculations */ +// {"use_dist", BMO_OP_SLOT_BOOL}, /* corner vert placement: evaluate percent as a distance, +// * modifier uses this. We could do this as another float setting */ +// {"lengthlayer", BMO_OP_SLOT_INT}, /* which PROP_FLT layer to us */ +// {"percent", BMO_OP_SLOT_FLT}, /* percentage to expand beveled edge */ +// {{'\0'}}, +// }, + bmo_bevel_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; /* - * Beautify Fill + * Beautify Fill. * - * Makes triangle a bit nicer + * Rotate edges to create more evenly spaced triangles. */ static BMOpDefine bmo_beautify_fill_def = { "beautify_fill", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "constrain_edges"}, /* edges that can't be flipped */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* new flipped faces and edges */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"constrain_edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* edges that can't be flipped */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* new flipped faces and edges */ + {{'\0'}}, + }, bmo_beautify_fill_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; /* - * Triangle Fill + * Triangle Fill. * * Fill edges with triangles */ static BMOpDefine bmo_triangle_fill_def = { "triangle_fill", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* new faces and edges */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* new faces and edges */ + {{'\0'}}, + }, bmo_triangle_fill_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; /* - * Solidify + * Solidify. * * Turns a mesh into a shell with thickness */ static BMOpDefine bmo_solidify_def = { "solidify", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_FLT, "thickness"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - {0}}, + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"thickness", BMO_OP_SLOT_FLT}, + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{'\0'}}, + }, bmo_solidify_face_region_exec, 0 }; /* - * Face Inset + * Face Inset. * - * Extrudes faces individually. + * Inset or outset faces. */ static BMOpDefine bmo_inset_def = { "inset", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ - {BMO_OP_SLOT_BOOL, "use_boundary"}, - {BMO_OP_SLOT_BOOL, "use_even_offset"}, - {BMO_OP_SLOT_BOOL, "use_relative_offset"}, - {BMO_OP_SLOT_FLT, "thickness"}, - {BMO_OP_SLOT_FLT, "depth"}, - {BMO_OP_SLOT_BOOL, "use_outset"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"use_boundary", BMO_OP_SLOT_BOOL}, + {"use_even_offset", BMO_OP_SLOT_BOOL}, + {"use_relative_offset", BMO_OP_SLOT_BOOL}, + {"thickness", BMO_OP_SLOT_FLT}, + {"depth", BMO_OP_SLOT_FLT}, + {"use_outset", BMO_OP_SLOT_BOOL}, + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, + }, bmo_inset_exec, 0 }; /* - * Wire Frame + * Wire Frame. * - * Makes a wire copy of faces. + * Makes a wire-frame copy of faces. */ static BMOpDefine bmo_wireframe_def = { "wireframe", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ - {BMO_OP_SLOT_BOOL, "use_boundary"}, - {BMO_OP_SLOT_BOOL, "use_even_offset"}, - {BMO_OP_SLOT_BOOL, "use_crease"}, - {BMO_OP_SLOT_FLT, "thickness"}, - {BMO_OP_SLOT_BOOL, "use_relative_offset"}, - {BMO_OP_SLOT_FLT, "depth"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"use_boundary", BMO_OP_SLOT_BOOL}, + {"use_even_offset", BMO_OP_SLOT_BOOL}, + {"use_crease", BMO_OP_SLOT_BOOL}, + {"thickness", BMO_OP_SLOT_FLT}, + {"use_relative_offset", BMO_OP_SLOT_BOOL}, + {"depth", BMO_OP_SLOT_FLT}, + {{'\0'}}, + }, + /* slots_out */ + {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {{'\0'}}, + }, bmo_wireframe_exec, 0 }; /* - * Vertex Slide + * Vertex Slide. * - * Translates vertes along an edge + * Translates verts along an edge */ static BMOpDefine bmo_slide_vert_def = { "slide_vert", - {{BMO_OP_SLOT_ELEMENT_BUF, "vert"}, - {BMO_OP_SLOT_ELEMENT_BUF, "edge"}, - {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, - {BMO_OP_SLOT_FLT, "distance_t"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"vert", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, + {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"factor", BMO_OP_SLOT_FLT}, + {{'\0'}}, + }, + /* slots_out */ + {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, + {{'\0'}}, + }, bmo_slide_vert_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; @@ -1194,7 +1565,7 @@ static BMOpDefine bmo_slide_vert_def = { * If 'use_existing_faces' is true, the hull will not output triangles * that are covered by a pre-existing face. * - * All hull vertices, faces, and edges are added to 'geomout'. Any + * All hull vertices, faces, and edges are added to 'geom.out'. Any * input elements that end up inside the hull (i.e. are not used by an * output face) are added to the 'interior_geom' slot. The * 'unused_geom' slot will contain all interior geometry that is @@ -1203,44 +1574,49 @@ static BMOpDefine bmo_slide_vert_def = { */ static BMOpDefine bmo_convex_hull_def = { "convex_hull", - {{BMO_OP_SLOT_ELEMENT_BUF, "input"}, - {BMO_OP_SLOT_BOOL, "use_existing_faces"}, - - /* Outputs */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - {BMO_OP_SLOT_ELEMENT_BUF, "interior_geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "unused_geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "holes_geom"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"use_existing_faces", BMO_OP_SLOT_BOOL}, + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom_interior.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom_unused.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"geom_holes.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{'\0'}}, + }, bmo_convex_hull_exec, 0 }; #endif /* - * Symmetrize + * Symmetrize. * - * Mekes the mesh elements in the "input" slot symmetrical. Unlike + * Makes the mesh elements in the "input" slot symmetrical. Unlike * normal mirroring, it only copies in one direction, as specified by * the "direction" slot. The edges and faces that cross the plane of * symmetry are split as needed to enforce symmetry. * - * All new vertices, edges, and faces are added to the "geomout" slot. + * All new vertices, edges, and faces are added to the "geom.out" slot. */ static BMOpDefine bmo_symmetrize_def = { "symmetrize", - {{BMO_OP_SLOT_ELEMENT_BUF, "input"}, - {BMO_OP_SLOT_INT, "direction"}, - - /* Outputs */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"direction", BMO_OP_SLOT_INT}, + {{'\0'}}, + }, + /* slots_out */ + {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {{'\0'}}, + }, bmo_symmetrize_exec, 0 }; -BMOpDefine *opdefines[] = { +const BMOpDefine *bmo_opdefines[] = { &bmo_automerge_def, &bmo_average_vert_facedata_def, &bmo_beautify_fill_def, @@ -1315,7 +1691,6 @@ BMOpDefine *opdefines[] = { &bmo_unsubdivide_def, &bmo_weld_verts_def, &bmo_wireframe_def, - }; -int bmesh_total_ops = (sizeof(opdefines) / sizeof(void *)); +const int bmo_opdefines_total = (sizeof(bmo_opdefines) / sizeof(void *)); diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index 671cfbbc55e..7df9c94a2f1 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -91,15 +91,15 @@ BLI_INLINE void _bmo_elem_flag_toggle( BMesh *bm, BMFlagLayer *oflags, const /* slot type arrays are terminated by the last member * having a slot type of 0 */ -enum { - BMO_OP_SLOT_SENTINEL = 0, +typedef enum eBMOpSlotType { + /* BMO_OP_SLOT_SENTINEL = 0, */ BMO_OP_SLOT_BOOL = 1, BMO_OP_SLOT_INT = 2, BMO_OP_SLOT_FLT = 3, /* normally store pointers to object, scene, * _never_ store arrays corresponding to mesh elements with this */ - BMO_OP_SLOT_PTR = 4, + BMO_OP_SLOT_PTR = 4, /* requres subtype BMO_OP_SLOT_SUBTYPE_PTR_xxx */ BMO_OP_SLOT_MAT = 5, BMO_OP_SLOT_VEC = 8, @@ -108,38 +108,84 @@ enum { * * it's very important this remain a power of two */ BMO_OP_SLOT_ELEMENT_BUF = 9, /* list of verts/edges/faces */ - BMO_OP_SLOT_MAPPING = 10 /* simple hash map */ -}; + BMO_OP_SLOT_MAPPING = 10 /* simple hash map, requres subtype BMO_OP_SLOT_SUBTYPE_MAP_xxx */ +} eBMOpSlotType; #define BMO_OP_SLOT_TOTAL_TYPES 11 +/* don't overlap values to avoid confusion */ +typedef enum eBMOpSlotSubType_Elem { + /* use as flags */ + BMO_OP_SLOT_SUBTYPE_ELEM_VERT = BM_VERT, + BMO_OP_SLOT_SUBTYPE_ELEM_EDGE = BM_EDGE, + BMO_OP_SLOT_SUBTYPE_ELEM_FACE = BM_FACE, + BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE = (BM_FACE << 1), +} eBMOpSlotSubType_Elem; +typedef enum eBMOpSlotSubType_Map { + BMO_OP_SLOT_SUBTYPE_MAP_EMPTY = 64, /* use as a set(), unused value */ + BMO_OP_SLOT_SUBTYPE_MAP_ELEM = 65, + BMO_OP_SLOT_SUBTYPE_MAP_FLT = 66, + BMO_OP_SLOT_SUBTYPE_MAP_INT = 67, + BMO_OP_SLOT_SUBTYPE_MAP_BOOL = 68, + BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL = 69, /* python can't convert these */ +} eBMOpSlotSubType_Map; +typedef enum eBMOpSlotSubType_Ptr { + BMO_OP_SLOT_SUBTYPE_PTR_BMESH = 100, + BMO_OP_SLOT_SUBTYPE_PTR_SCENE = 101, + BMO_OP_SLOT_SUBTYPE_PTR_OBJECT = 102, + BMO_OP_SLOT_SUBTYPE_PTR_MESH = 103, +} eBMOpSlotSubType_Ptr; + +typedef union eBMOpSlotSubType_Union { + eBMOpSlotSubType_Elem elem; + eBMOpSlotSubType_Ptr ptr; + eBMOpSlotSubType_Map map; +} eBMOpSlotSubType_Union; + /* please ignore all these structures, don't touch them in tool code, except * for when your defining an operator with BMOpDefine.*/ typedef struct BMOpSlot { - int slot_type; + const char *slot_name; /* pointer to BMOpDefine.slot_args */ + eBMOpSlotType slot_type; + eBMOpSlotSubType_Union slot_subtype; + int len; - int flag; - int index; /* index within slot array */ +// int flag; /* UNUSED */ +// int index; /* index within slot array */ /* UNUSED */ union { int i; float f; void *p; float vec[3]; - void *buf; + void **buf; GHash *ghash; } data; } BMOpSlot; -#define BMO_OP_MAX_SLOTS 16 /* way more than probably needed */ +/* mainly for use outside bmesh internal code */ +#define BMO_SLOT_AS_BOOL(slot) ((slot)->data.i) +#define BMO_SLOT_AS_INT(slot) ((slot)->data.i) +#define BMO_SLOT_AS_FLOAT(slot) ((slot)->data.f) +#define BMO_SLOT_AS_VECTOR(slot) ((slot)->data.vec) +#define BMO_SLOT_AS_MATRIX(slot ) ((float (*)[4])((slot)->data.p)) +#define BMO_SLOT_AS_BUFFER(slot ) ((slot)->data.buf) +#define BMO_SLOT_AS_GHASH(slot ) ((slot)->data.ghash) + +#define BMO_ASSERT_SLOT_IN_OP(slot, op) \ + BLI_assert(((slot >= (op)->slots_in) && (slot < &(op)->slots_in[BMO_OP_MAX_SLOTS])) || \ + ((slot >= (op)->slots_out) && (slot < &(op)->slots_out[BMO_OP_MAX_SLOTS]))) + +/* way more than probably needed, compiler complains if limit hit */ +#define BMO_OP_MAX_SLOTS 16 typedef struct BMOperator { - int type; - int slot_type; - int type_flag; - int flag; /* runtime options */ - struct BMOpSlot slot_args[BMO_OP_MAX_SLOTS]; + struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]; + struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]; void (*exec)(BMesh *bm, struct BMOperator *op); struct MemArena *arena; + int type; + int type_flag; + int flag; /* runtime options */ } BMOperator; enum { @@ -151,13 +197,15 @@ enum { #define MAX_SLOTNAME 32 typedef struct BMOSlotType { - int type; char name[MAX_SLOTNAME]; + eBMOpSlotType type; + eBMOpSlotSubType_Union subtype; } BMOSlotType; typedef struct BMOpDefine { - const char *name; - BMOSlotType slot_types[BMO_OP_MAX_SLOTS]; + const char *opname; + BMOSlotType slot_types_in[BMO_OP_MAX_SLOTS]; + BMOSlotType slot_types_out[BMO_OP_MAX_SLOTS]; void (*exec)(BMesh *bm, BMOperator *op); int type_flag; } BMOpDefine; @@ -192,43 +240,6 @@ int BMO_mesh_enabled_flag_count(BMesh *bm, const char htype, const short oflag); int BMO_mesh_disabled_flag_count(BMesh *bm, const char htype, const short oflag); /*---------formatted operator initialization/execution-----------*/ -/* - * this system is used to execute or initialize an operator, - * using a formatted-string system. - * - * for example, BMO_op_callf(bm, BMO_FLAG_DEFAULTS, "delete geom=%hf context=%i", BM_ELEM_SELECT, DEL_FACES); - * . . .will execute the delete operator, feeding in selected faces, deleting them. - * - * the basic format for the format string is: - * [operatorname] [slot_name]=%[code] [slot_name]=%[code] - * - * as in printf, you pass in one additional argument to the function - * for every code. - * - * the formatting codes are: - * %d - put int in slot - * %f - put float in slot - * %p - put pointer in slot - * %h[f/e/v] - put elements with a header flag in slot. - * the letters after %h define which element types to use, - * so e.g. %hf will do faces, %hfe will do faces and edges, - * %hv will do verts, etc. must pass in at least one - * element type letter. - * %H[f/e/v] - same as %h, but tests if the flag is disabled - * %f[f/e/v] - same as %h, except it deals with tool flags instead of - * header flags. - * %F[f/e/v] - same as %f, but tests if the flag is disabled - * %a[f/e/v] - pass all elements (of types specified by f/e/v) to the - * slot. - * %e - pass in a single element. - * %v - pointer to a float vector of length 3. - * %m[3/4] - matrix, 3/4 refers to the matrix size, 3 or 4. the - * corresponding argument must be a pointer to - * a float matrix. - * %s - copy a slot from another op, instead of mapping to one - * argument, it maps to two, a pointer to an operator and - * a slot name. - */ void BMO_push(BMesh *bm, BMOperator *op); void BMO_pop(BMesh *bm); @@ -245,15 +256,22 @@ int BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ... int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, va_list vlist); /* test whether a named slot exists */ -int BMO_slot_exists(BMOperator *op, const char *slot_name); +int BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); /* get a pointer to a slot. this may be removed layer on from the public API. */ -BMOpSlot *BMO_slot_get(BMOperator *op, const char *slot_name); +BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); /* copies the data of a slot from one operator to another. src and dst are the * source/destination slot codes, respectively. */ -void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op, - const char *src, const char *dst); +#define BMO_slot_copy(op_src, slots_src, slot_name_src, \ + op_dst, slots_dst, slot_name_dst) \ + _bmo_slot_copy((op_src)->slots_src, slot_name_src, \ + (op_dst)->slots_dst, slot_name_dst, \ + (op_dst)->arena) + +void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + struct MemArena *arena_dst); /* del "context" slot values, used for operator too */ enum { @@ -279,13 +297,13 @@ typedef enum { void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag); void BMO_op_flag_disable(BMesh *bm, BMOperator *op, const int op_flag); -void BMO_slot_float_set(BMOperator *op, const char *slot_name, const float f); -float BMO_slot_float_get(BMOperator *op, const char *slot_name); -void BMO_slot_int_set(BMOperator *op, const char *slot_name, const int i); -int BMO_slot_int_get(BMOperator *op, const char *slot_name); -void BMO_slot_bool_set(BMOperator *op, const char *slot_name, const int i); -int BMO_slot_bool_get(BMOperator *op, const char *slot_name); -void *BMO_slot_as_arrayN(BMOperator *op, const char *slot_name, int *len); +void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float f); +float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i); +int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i); +int BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len); /* don't pass in arrays that are supposed to map to elements this way. @@ -293,69 +311,85 @@ void *BMO_slot_as_arrayN(BMOperator *op, const char *slot_name, int *len); * so, e.g. passing in list of floats per element in another slot is bad. * passing in, e.g. pointer to an editmesh for the conversion operator is fine * though. */ -void BMO_slot_ptr_set(BMOperator *op, const char *slot_name, void *p); -void *BMO_slot_ptr_get(BMOperator *op, const char *slot_name); -void BMO_slot_vec_set(BMOperator *op, const char *slot_name, const float vec[3]); -void BMO_slot_vec_get(BMOperator *op, const char *slot_name, float r_vec[3]); +void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p); +void *BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float vec[3]); +void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3]); /* only supports square mats */ /* size must be 3 or 4; this api is meant only for transformation matrices. * note that internally the matrix is stored in 4x4 form, and it's safe to * call whichever BMO_Get_MatXXX function you want. */ -void BMO_slot_mat_set(BMOperator *op, const char *slot_name, const float *mat, int size); -void BMO_slot_mat4_get(BMOperator *op, const char *slot_name, float r_mat[4][4]); -void BMO_slot_mat3_set(BMOperator *op, const char *slot_name, float r_mat[3][3]); +void BMO_slot_mat_set(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float *mat, int size); +void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[4][4]); +void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[3][3]); void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, const short oflag); /* copies the values from another slot to the end of the output slot */ -void BMO_slot_buffer_append(BMOperator *output_op, const char *output_op_slot, - BMOperator *other_op, const char *other_op_slot); +#define BMO_slot_buffer_append(op_src, slots_src, slot_name_src, \ + op_dst, slots_dst, slot_name_dst) \ + _bmo_slot_buffer_append((op_src)->slots_src, slot_name_src, \ + (op_dst)->slots_dst, slot_name_dst, \ + (op_dst)->arena) +void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + struct MemArena *arena_dst); /* puts every element of type 'type' (which is a bitmask) with tool * flag 'flag', into a slot. */ -void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag); /* puts every element of type 'type' (which is a bitmask) without tool * flag 'flag', into a slot. */ -void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag); /* tool-flags all elements inside an element slot array with flag flag. */ -void BMO_slot_buffer_flag_enable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_flag_enable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag); /* clears tool-flag flag from all elements inside a slot array. */ -void BMO_slot_buffer_flag_disable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_flag_disable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag); /* tool-flags all elements inside an element slot array with flag flag. */ -void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_hflag_enable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, const char do_flush); /* clears tool-flag flag from all elements inside a slot array. */ -void BMO_slot_buffer_hflag_disable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_hflag_disable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, const char do_flush); /* puts every element of type 'type' (which is a bitmask) with header * flag 'flag', into a slot. note: ignores hidden elements * (e.g. elements with header flag BM_ELEM_HIDDEN set).*/ void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, - const char *slot_name, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag); /* puts every element of type 'type' (which is a bitmask) without * header flag 'flag', into a slot. note: ignores hidden elements * (e.g. elements with header flag BM_ELEM_HIDDEN set).*/ void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, - const char *slot_name, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag); -/* counts number of elements inside a slot array. */ -int BMO_slot_buffer_count(BMesh *bm, BMOperator *op, const char *slot_name); -int BMO_slot_map_count(BMesh *bm, BMOperator *op, const char *slot_name); +void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele); +void *BMO_slot_buffer_get_single(BMOpSlot *slot); -void BMO_slot_map_insert(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name, - void *element, void *data, int len); + +/* counts number of elements inside a slot array. */ +int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); + +void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, + const void *element, const void *data, const int len); /* Counts the number of edges with tool flag toolflag around */ @@ -363,23 +397,27 @@ int BMO_vert_edge_flags_count(BMesh *bm, BMVert *v, const short oflag); /* flags all elements in a mapping. note that the mapping must only have * bmesh elements in it.*/ -void BMO_slot_map_to_flag(BMesh *bm, BMOperator *op, const char *slot_name, - const char hflag, const short oflag); +void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const char hflag, const short oflag); -void *BMO_slot_buffer_alloc(BMOperator *op, const char *slot_name, const int len); +void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const int len); -void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, - const char htype); +void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const char htype); -/* this part of the API is used to iterate over element buffer or +/** + * This part of the API is used to iterate over element buffer or * mapping slots. * * for example, iterating over the faces in a slot is: * + * \code{.c} + * * BMOIter oiter; * BMFace *f; * - * f = BMO_iter_new(&oiter, bm, some_operator, "slot_name", BM_FACE); + * f = BMO_iter_new(&oiter, some_operator, "slot_name", BM_FACE); * for (; f; f = BMO_iter_step(&oiter)) { * /do something with the face * } @@ -400,6 +438,7 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, * // *((void**)BMO_iter_map_value(&oiter)); * //or something like that. * } + * \endcode */ /* contents of this structure are private, @@ -412,10 +451,11 @@ typedef struct BMOIter { char restrictmask; /* bitwise '&' with BMHeader.htype */ } BMOIter; -void *BMO_slot_buffer_elem_first(BMOperator *op, const char *slot_name); +void *BMO_slot_buffer_elem_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); -void *BMO_iter_new(BMOIter *iter, BMesh *bm, BMOperator *op, - const char *slot_name, const char restrictmask); +void *BMO_iter_new(BMOIter *iter, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char restrictmask); void *BMO_iter_step(BMOIter *iter); /* returns a pointer to the key value when iterating over mappings. @@ -428,8 +468,8 @@ void *BMO_iter_map_value_p(BMOIter *iter); /* use this for float mappings */ float BMO_iter_map_value_f(BMOIter *iter); -#define BMO_ITER(ele, iter, bm, op, slot_name, restrict) \ - for (ele = BMO_iter_new(iter, bm, op, slot_name, restrict); ele; ele = BMO_iter_step(iter)) +#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag) \ + for (ele = BMO_iter_new(iter, slot_args, slot_name, restrict_flag); ele; ele = BMO_iter_step(iter)) /******************* Inlined Functions********************/ typedef void (*opexec)(BMesh *bm, BMOperator *op); @@ -441,6 +481,9 @@ typedef struct BMOElemMapping { int len; } BMOElemMapping; +/* pointer after BMOElemMapping */ +#define BMO_OP_SLOT_MAPPING_DATA(var) (void *)(((BMOElemMapping *)var) + 1) + extern const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES]; #ifdef __cplusplus diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h index 16c2b8b0505..ad116011421 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h +++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h @@ -69,16 +69,26 @@ BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const shor oflags[bm->stackdepth - 1].f ^= oflag; } -BLI_INLINE void BMO_slot_map_int_insert(BMesh *bm, BMOperator *op, const char *slot_name, - void *element, int val) +BLI_INLINE void BMO_slot_map_int_insert(BMOperator *op, BMOpSlot *slot, + void *element, const int val) { - BMO_slot_map_insert(bm, op, slot_name, element, &val, sizeof(int)); + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT); + BMO_slot_map_insert(op, slot, element, &val, sizeof(int)); } -BLI_INLINE void BMO_slot_map_float_insert(BMesh *bm, BMOperator *op, const char *slot_name, - void *element, float val) +BLI_INLINE void BMO_slot_map_bool_insert(BMOperator *op, BMOpSlot *slot, + void *element, const int val) { - BMO_slot_map_insert(bm, op, slot_name, element, &val, sizeof(float)); + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); + BLI_assert(val == FALSE || val == TRUE); + BMO_slot_map_insert(op, slot, element, &val, sizeof(int)); +} + +BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot, + void *element, const float val) +{ + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT); + BMO_slot_map_insert(op, slot, element, &val, sizeof(float)); } @@ -87,62 +97,107 @@ BLI_INLINE void BMO_slot_map_float_insert(BMesh *bm, BMOperator *op, const char * do NOT use these for non-operator-api-allocated memory! instead * use BMO_slot_map_data_get and BMO_slot_map_insert, which copies the data. */ -BLI_INLINE void BMO_slot_map_ptr_insert(BMesh *bm, BMOperator *op, const char *slot_name, - void *element, void *val) +BLI_INLINE void BMO_slot_map_ptr_insert(BMOperator *op, BMOpSlot *slot, + const void *element, void *val) { - BMO_slot_map_insert(bm, op, slot_name, element, &val, sizeof(void *)); + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL); + BMO_slot_map_insert(op, slot, element, &val, sizeof(void *)); } -BLI_INLINE int BMO_slot_map_contains(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name, void *element) +BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, BMOpSlot *slot, + const void *element, void *val) +{ + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM); + BMO_slot_map_insert(op, slot, element, &val, sizeof(void *)); +} + + +/* no values */ +BLI_INLINE void BMO_slot_map_empty_insert(BMOperator *op, BMOpSlot *slot, + const void *element) +{ + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_EMPTY); + BMO_slot_map_insert(op, slot, element, NULL, 0); +} + +BLI_INLINE int BMO_slot_map_contains(BMOpSlot *slot, const void *element) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); /* sanity check */ - if (!slot->data.ghash) return 0; + if (UNLIKELY(slot->data.ghash == NULL)) { + return 0; + } return BLI_ghash_haskey(slot->data.ghash, element); } -BLI_INLINE void *BMO_slot_map_data_get(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name, - void *element) +BLI_INLINE void *BMO_slot_map_data_get(BMOpSlot *slot, const void *element) { BMOElemMapping *mapping; - BMOpSlot *slot = BMO_slot_get(op, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); /* sanity check */ - if (!slot->data.ghash) return NULL; + if (UNLIKELY(slot->data.ghash == NULL)) { + return NULL; + } mapping = (BMOElemMapping *)BLI_ghash_lookup(slot->data.ghash, element); - if (!mapping) return NULL; + if (!mapping) { + return NULL; + } return mapping + 1; } -BLI_INLINE float BMO_slot_map_float_get(BMesh *bm, BMOperator *op, const char *slot_name, - void *element) +BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element) { - float *val = (float *) BMO_slot_map_data_get(bm, op, slot_name, element); + float *val; + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT); + + val = (float *) BMO_slot_map_data_get(slot, element); if (val) return *val; return 0.0f; } -BLI_INLINE int BMO_slot_map_int_get(BMesh *bm, BMOperator *op, const char *slot_name, - void *element) +BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element) { - int *val = (int *) BMO_slot_map_data_get(bm, op, slot_name, element); + int *val; + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT); + + val = (int *) BMO_slot_map_data_get(slot, element); if (val) return *val; return 0; } -BLI_INLINE void *BMO_slot_map_ptr_get(BMesh *bm, BMOperator *op, const char *slot_name, - void *element) +BLI_INLINE int BMO_slot_map_bool_get(BMOpSlot *slot, const void *element) { - void **val = (void **) BMO_slot_map_data_get(bm, op, slot_name, element); + int *val; + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); + + val = (int *) BMO_slot_map_data_get(slot, element); + BLI_assert(val == NULL || *val == FALSE || *val == TRUE); + if (val) return *val; + + return 0; +} + +BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element) +{ + void **val = (void **) BMO_slot_map_data_get(slot, element); + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL); + if (val) return *val; + + return NULL; +} + +BLI_INLINE void *BMO_slot_map_elem_get(BMOpSlot *slot, const void *element) +{ + void **val = (void **) BMO_slot_map_data_get(slot, element); + BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM); if (val) return *val; return NULL; diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 4cc946a3a40..5e51f5a5ada 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -45,8 +45,8 @@ static void bmo_flag_layer_alloc(BMesh *bm); static void bmo_flag_layer_free(BMesh *bm); static void bmo_flag_layer_clear(BMesh *bm); -static int bmo_name_to_slotcode(BMOpDefine *def, const char *name); -static int bmo_name_to_slotcode_check(BMOpDefine *def, const char *name); +static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); +static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); static int bmo_opname_to_opcode(const char *opname); static const char *bmo_error_messages[] = { @@ -80,7 +80,7 @@ const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES] = { }; /* Dummy slot so there is something to return when slot name lookup fails */ -static BMOpSlot BMOpEmptySlot = {0}; +// static BMOpSlot BMOpEmptySlot = {0}; void BMO_op_flag_enable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag) { @@ -101,6 +101,8 @@ void BMO_push(BMesh *bm, BMOperator *UNUSED(op)) { bm->stackdepth++; + BLI_assert(bm->totflags > 0); + /* add flag layer, if appropriate */ if (bm->stackdepth > 1) bmo_flag_layer_alloc(bm); @@ -123,6 +125,19 @@ void BMO_pop(BMesh *bm) bm->stackdepth--; } + +/* use for both slot_types_in and slot_types_out */ +static void bmo_op_slots_init(const BMOSlotType *slot_types, BMOpSlot *slot_args) +{ + unsigned int i; + for (i = 0; slot_types[i].type; i++) { + slot_args[i].slot_name = slot_types[i].name; + slot_args[i].slot_type = slot_types[i].type; + slot_args[i].slot_subtype = slot_types[i].subtype; + // slot_args[i].index = i; // UNUSED + } +} + /** * \brief BMESH OPSTACK INIT OP * @@ -130,7 +145,7 @@ void BMO_pop(BMesh *bm) */ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname) { - int i, opcode = bmo_opname_to_opcode(opname); + int opcode = bmo_opname_to_opcode(opname); #ifdef DEBUG BM_ELEM_INDEX_VALIDATE(bm, "pre bmo", opname); @@ -144,17 +159,15 @@ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname) memset(op, 0, sizeof(BMOperator)); op->type = opcode; - op->type_flag = opdefines[opcode]->type_flag; + op->type_flag = bmo_opdefines[opcode]->type_flag; op->flag = flag; /* initialize the operator slot types */ - for (i = 0; opdefines[opcode]->slot_types[i].type; i++) { - op->slot_args[i].slot_type = opdefines[opcode]->slot_types[i].type; - op->slot_args[i].index = i; - } + bmo_op_slots_init(bmo_opdefines[opcode]->slot_types_in, op->slots_in); + bmo_op_slots_init(bmo_opdefines[opcode]->slot_types_out, op->slots_out); /* callback */ - op->exec = opdefines[opcode]->exec; + op->exec = bmo_opdefines[opcode]->exec; /* memarena, used for operator's slot buffers */ op->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); @@ -172,7 +185,9 @@ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname) */ void BMO_op_exec(BMesh *bm, BMOperator *op) { - + /* allocate tool flags on demand */ + BM_mesh_elem_toolflags_ensure(bm); + BMO_push(bm, op); if (bm->stackdepth == 2) @@ -185,6 +200,20 @@ void BMO_op_exec(BMesh *bm, BMOperator *op) BMO_pop(bm); } +static void bmo_op_slots_free(const BMOSlotType *slot_types, BMOpSlot *slot_args) +{ + BMOpSlot *slot; + unsigned int i; + for (i = 0; slot_types[i].type; i++) { + slot = &slot_args[i]; + if (slot->slot_type == BMO_OP_SLOT_MAPPING) { + if (slot->data.ghash) { + BLI_ghash_free(slot->data.ghash, NULL, NULL); + } + } + } +} + /** * \brief BMESH OPSTACK FINISH OP * @@ -192,21 +221,13 @@ void BMO_op_exec(BMesh *bm, BMOperator *op) */ void BMO_op_finish(BMesh *bm, BMOperator *op) { - BMOpSlot *slot; - int i; - - for (i = 0; opdefines[op->type]->slot_types[i].type; i++) { - slot = &op->slot_args[i]; - if (slot->slot_type == BMO_OP_SLOT_MAPPING) { - if (slot->data.ghash) - BLI_ghash_free(slot->data.ghash, NULL, NULL); - } - } + bmo_op_slots_free(bmo_opdefines[op->type]->slot_types_in, op->slots_in); + bmo_op_slots_free(bmo_opdefines[op->type]->slot_types_out, op->slots_out); BLI_memarena_free(op->arena); #ifdef DEBUG - BM_ELEM_INDEX_VALIDATE(bm, "post bmo", opdefines[op->type]->name); + BM_ELEM_INDEX_VALIDATE(bm, "post bmo", bmo_opdefines[op->type]->opname); #else (void)bm; #endif @@ -217,9 +238,9 @@ void BMO_op_finish(BMesh *bm, BMOperator *op) * * \return Success if the slot if found. */ -int BMO_slot_exists(BMOperator *op, const char *slot_name) +int BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int slot_code = bmo_name_to_slotcode(opdefines[op->type], slot_name); + int slot_code = bmo_name_to_slotcode(slot_args, identifier); return (slot_code >= 0); } @@ -228,73 +249,118 @@ int BMO_slot_exists(BMOperator *op, const char *slot_name) * * Returns a pointer to the slot of type 'slot_code' */ -BMOpSlot *BMO_slot_get(BMOperator *op, const char *slot_name) +BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int slot_code = bmo_name_to_slotcode_check(opdefines[op->type], slot_name); + int slot_code = bmo_name_to_slotcode_check(slot_args, identifier); - if (slot_code < 0) { - return &BMOpEmptySlot; + if (UNLIKELY(slot_code < 0)) { + //return &BMOpEmptySlot; + BLI_assert(0); + return NULL; /* better crash */ } - return &(op->slot_args[slot_code]); + return &slot_args[slot_code]; } /** * \brief BMESH OPSTACK COPY SLOT * + * define used. * Copies data from one slot to another. */ -void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op, const char *src, const char *dst) +void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + struct MemArena *arena_dst) { - BMOpSlot *source_slot = BMO_slot_get(source_op, src); - BMOpSlot *dest_slot = BMO_slot_get(dest_op, dst); + BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src); + BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst); - if (source_slot == dest_slot) + if (slot_src == slot_dst) return; - if (source_slot->slot_type != dest_slot->slot_type) { - /* possibly assert here? */ + BLI_assert(slot_src->slot_type == slot_dst->slot_type); + if (slot_src->slot_type != slot_dst->slot_type) { return; } - if (dest_slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { + if (slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { /* do buffer copy */ - dest_slot->data.buf = NULL; - dest_slot->len = source_slot->len; - if (dest_slot->len) { - const int slot_alloc_size = BMO_OPSLOT_TYPEINFO[dest_slot->slot_type] * dest_slot->len; - dest_slot->data.buf = BLI_memarena_alloc(dest_op->arena, slot_alloc_size); - memcpy(dest_slot->data.buf, source_slot->data.buf, slot_alloc_size); + slot_dst->data.buf = NULL; + slot_dst->len = slot_src->len; + if (slot_dst->len) { + /* check dest has all flags enabled that the source has */ + const eBMOpSlotSubType_Elem src_elem_flag = (slot_src->slot_subtype.elem & BM_ALL_NOLOOP); + const eBMOpSlotSubType_Elem dst_elem_flag = (slot_dst->slot_subtype.elem & BM_ALL_NOLOOP); + + if ((src_elem_flag | dst_elem_flag) == dst_elem_flag) { + /* pass */ + } + else { + /* check types */ + const unsigned int tot = slot_src->len; + unsigned int i; + unsigned int out = 0; + BMElem **ele_src = (BMElem **)slot_src->data.buf; + for (i = 0; i < tot; i++, ele_src++) { + if ((*ele_src)->head.htype & dst_elem_flag) { + out++; + } + } + if (out != tot) { + slot_dst->len = out; + } + } + + if (slot_dst->len) { + const int slot_alloc_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type] * slot_dst->len; + slot_dst->data.buf = BLI_memarena_alloc(arena_dst, slot_alloc_size); + if (slot_src->len == slot_dst->len) { + memcpy(slot_dst->data.buf, slot_src->data.buf, slot_alloc_size); + } + else { + /* only copy compatible elements */ + const unsigned int tot = slot_src->len; + unsigned int i; + BMElem **ele_src = (BMElem **)slot_src->data.buf; + BMElem **ele_dst = (BMElem **)slot_dst->data.buf; + for (i = 0; i < tot; i++, ele_src++) { + if ((*ele_src)->head.htype & dst_elem_flag) { + *ele_dst = *ele_src; + ele_dst++; + } + } + } + } } } - else if (dest_slot->slot_type == BMO_OP_SLOT_MAPPING) { + else if (slot_dst->slot_type == BMO_OP_SLOT_MAPPING) { GHashIterator it; BMOElemMapping *srcmap, *dstmap; /* sanity check */ - if (!source_slot->data.ghash) { + if (!slot_src->data.ghash) { return; } - if (!dest_slot->data.ghash) { - dest_slot->data.ghash = BLI_ghash_ptr_new("bmesh operator 2"); + if (!slot_dst->data.ghash) { + slot_dst->data.ghash = BLI_ghash_ptr_new("bmesh operator 2"); } - BLI_ghashIterator_init(&it, source_slot->data.ghash); - for ( ; (srcmap = BLI_ghashIterator_getValue(&it)); - BLI_ghashIterator_step(&it)) + for (BLI_ghashIterator_init(&it, slot_src->data.ghash); + (srcmap = BLI_ghashIterator_getValue(&it)); + BLI_ghashIterator_step(&it)) { - dstmap = BLI_memarena_alloc(dest_op->arena, sizeof(*dstmap) + srcmap->len); + dstmap = BLI_memarena_alloc(arena_dst, sizeof(*dstmap) + srcmap->len); dstmap->element = srcmap->element; dstmap->len = srcmap->len; - memcpy(dstmap + 1, srcmap + 1, srcmap->len); + memcpy(BMO_OP_SLOT_MAPPING_DATA(dstmap), BMO_OP_SLOT_MAPPING_DATA(srcmap), srcmap->len); - BLI_ghash_insert(dest_slot->data.ghash, dstmap->element, dstmap); + BLI_ghash_insert(slot_dst->data.ghash, dstmap->element, dstmap); } } else { - dest_slot->data = source_slot->data; + slot_dst->data = slot_src->data; } } @@ -304,9 +370,9 @@ void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op, const char *src, * Sets the value of a slot depending on it's type */ -void BMO_slot_float_set(BMOperator *op, const char *slot_name, const float f) +void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float f) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT); if (!(slot->slot_type == BMO_OP_SLOT_FLT)) return; @@ -314,9 +380,9 @@ void BMO_slot_float_set(BMOperator *op, const char *slot_name, const float f) slot->data.f = f; } -void BMO_slot_int_set(BMOperator *op, const char *slot_name, const int i) +void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_INT); if (!(slot->slot_type == BMO_OP_SLOT_INT)) return; @@ -324,9 +390,9 @@ void BMO_slot_int_set(BMOperator *op, const char *slot_name, const int i) slot->data.i = i; } -void BMO_slot_bool_set(BMOperator *op, const char *slot_name, const int i) +void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL); if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) return; @@ -335,9 +401,9 @@ void BMO_slot_bool_set(BMOperator *op, const char *slot_name, const int i) } /* only supports square mats */ -void BMO_slot_mat_set(BMOperator *op, const char *slot_name, const float *mat, int size) +void BMO_slot_mat_set(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float *mat, int size) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT); if (!(slot->slot_type == BMO_OP_SLOT_MAT)) return; @@ -354,33 +420,43 @@ void BMO_slot_mat_set(BMOperator *op, const char *slot_name, const float *mat, i else { fprintf(stderr, "%s: invalid size argument %d (bmesh internal error)\n", __func__, size); - memset(slot->data.p, 0, sizeof(float) * 4 * 4); + zero_m4(slot->data.p); } } -void BMO_slot_mat4_get(BMOperator *op, const char *slot_name, float r_mat[4][4]) +void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[4][4]) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT); if (!(slot->slot_type == BMO_OP_SLOT_MAT)) return; - copy_m4_m4(r_mat, (float (*)[4])slot->data.p); + if (slot->data.p) { + copy_m4_m4(r_mat, BMO_SLOT_AS_MATRIX(slot)); + } + else { + unit_m4(r_mat); + } } -void BMO_slot_mat3_set(BMOperator *op, const char *slot_name, float r_mat[3][3]) +void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[3][3]) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT); if (!(slot->slot_type == BMO_OP_SLOT_MAT)) return; - copy_m3_m4(r_mat, slot->data.p); + if (slot->data.p) { + copy_m3_m4(r_mat, BMO_SLOT_AS_MATRIX(slot)); + } + else { + unit_m3(r_mat); + } } -void BMO_slot_ptr_set(BMOperator *op, const char *slot_name, void *p) +void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_PTR); if (!(slot->slot_type == BMO_OP_SLOT_PTR)) return; @@ -388,9 +464,9 @@ void BMO_slot_ptr_set(BMOperator *op, const char *slot_name, void *p) slot->data.p = p; } -void BMO_slot_vec_set(BMOperator *op, const char *slot_name, const float vec[3]) +void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float vec[3]) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_VEC); if (!(slot->slot_type == BMO_OP_SLOT_VEC)) return; @@ -399,9 +475,9 @@ void BMO_slot_vec_set(BMOperator *op, const char *slot_name, const float vec[3]) } -float BMO_slot_float_get(BMOperator *op, const char *slot_name) +float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT); if (!(slot->slot_type == BMO_OP_SLOT_FLT)) return 0.0f; @@ -409,9 +485,9 @@ float BMO_slot_float_get(BMOperator *op, const char *slot_name) return slot->data.f; } -int BMO_slot_int_get(BMOperator *op, const char *slot_name) +int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_INT); if (!(slot->slot_type == BMO_OP_SLOT_INT)) return 0; @@ -419,9 +495,9 @@ int BMO_slot_int_get(BMOperator *op, const char *slot_name) return slot->data.i; } -int BMO_slot_bool_get(BMOperator *op, const char *slot_name) +int BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL); if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) return 0; @@ -430,23 +506,23 @@ int BMO_slot_bool_get(BMOperator *op, const char *slot_name) } /* if you want a copy of the elem buffer */ -void *BMO_slot_as_arrayN(BMOperator *op, const char *slot_name, int *len) +void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); void *ret; /* could add support for mapping type */ BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - ret = MEM_mallocN(sizeof(void *) * slot->len, __func__); - memcpy(ret, slot->data.buf, sizeof(void *) * slot->len); + ret = MEM_mallocN(sizeof(void **) * slot->len, __func__); + memcpy(ret, slot->data.buf, sizeof(void **) * slot->len); *len = slot->len; return ret; } -void *BMO_slot_ptr_get(BMOperator *op, const char *slot_name) +void *BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_PTR); if (!(slot->slot_type == BMO_OP_SLOT_PTR)) return NULL; @@ -454,9 +530,9 @@ void *BMO_slot_ptr_get(BMOperator *op, const char *slot_name) return slot->data.p; } -void BMO_slot_vec_get(BMOperator *op, const char *slot_name, float r_vec[3]) +void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3]) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_VEC); if (!(slot->slot_type == BMO_OP_SLOT_VEC)) return; @@ -532,9 +608,9 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char hty } } -int BMO_slot_buffer_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name) +int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); /* check if its actually a buffer */ @@ -544,9 +620,9 @@ int BMO_slot_buffer_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_na return slot->len; } -int BMO_slot_map_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name) +int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); /* check if its actually a buffer */ @@ -559,24 +635,27 @@ int BMO_slot_map_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name) /* inserts a key/value mapping into a mapping slot. note that it copies the * value, it doesn't store a reference to it. */ -void BMO_slot_map_insert(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name, - void *element, void *data, int len) +void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, + const void *element, const void *data, const int len) { BMOElemMapping *mapping; - BMOpSlot *slot = BMO_slot_get(op, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); + BMO_ASSERT_SLOT_IN_OP(slot, op); mapping = (BMOElemMapping *) BLI_memarena_alloc(op->arena, sizeof(*mapping) + len); mapping->element = (BMHeader *) element; mapping->len = len; - memcpy(mapping + 1, data, len); + memcpy(BMO_OP_SLOT_MAPPING_DATA(mapping), data, len); if (!slot->data.ghash) { slot->data.ghash = BLI_ghash_ptr_new("bmesh slot map hash"); } + else { + BLI_assert(slot->data.ghash); + } - BLI_ghash_insert(slot->data.ghash, element, mapping); + BLI_ghash_insert(slot->data.ghash, (void *)element, mapping); } #if 0 @@ -596,7 +675,7 @@ void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd) if (slot->len >= slot->size) { slot->size = (slot->size + 1 + totadd) * 2; - allocsize = BMO_OPSLOT_TYPEINFO[opdefines[op->type]->slot_types[slot_code].type] * slot->size; + allocsize = BMO_OPSLOT_TYPEINFO[bmo_opdefines[op->type]->slot_types[slot_code].type] * slot->size; tmp = slot->data.buf; slot->data.buf = MEM_callocN(allocsize, "opslot dynamic array"); @@ -611,7 +690,7 @@ void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd) slot->len += totadd; slot->size = slot->len + 2; - allocsize = BMO_OPSLOT_TYPEINFO[opdefines[op->type]->slot_types[slot_code].type] * slot->len; + allocsize = BMO_OPSLOT_TYPEINFO[bmo_opdefines[op->type]->slot_types[slot_code].type] * slot->len; tmp = slot->data.buf; slot->data.buf = MEM_callocN(allocsize, "opslot dynamic array"); @@ -622,11 +701,11 @@ void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd) } #endif -void BMO_slot_map_to_flag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { GHashIterator it; - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BMElemF *ele_f; BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); @@ -642,18 +721,22 @@ void BMO_slot_map_to_flag(BMesh *bm, BMOperator *op, const char *slot_name, } } -void *BMO_slot_buffer_alloc(BMOperator *op, const char *slot_name, const int len) +void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int len) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); /* check if its actually a buffer */ if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) return NULL; slot->len = len; - if (len) + if (len) { slot->data.buf = BLI_memarena_alloc(op->arena, BMO_OPSLOT_TYPEINFO[slot->slot_type] * len); + } + else { + slot->data.buf = NULL; + } + return slot->data.buf; } @@ -662,9 +745,10 @@ void *BMO_slot_buffer_alloc(BMOperator *op, const char *slot_name, const int len * * Copies all elements of a certain type into an operator slot. */ -void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, const char htype) +void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const char htype) { - BMOpSlot *output = BMO_slot_get(op, slot_name); + BMOpSlot *output = BMO_slot_get(slot_args, slot_name); int totelement = 0, i = 0; if (htype & BM_VERT) totelement += bm->totvert; @@ -675,27 +759,27 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, BMIter iter; BMHeader *ele; - BMO_slot_buffer_alloc(op, slot_name, totelement); + BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); /* TODO - collapse these loops into one */ if (htype & BM_VERT) { BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { - ((BMHeader **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } if (htype & BM_EDGE) { BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - ((BMHeader **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } if (htype & BM_FACE) { BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - ((BMHeader **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } @@ -708,11 +792,11 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, * Copies elements of a certain type, which have a certain header flag * enabled/disabled into a slot for an operator. */ -static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *slot_name, +static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, const short test_for_enabled) { - BMOpSlot *output = BMO_slot_get(op, slot_name); + BMOpSlot *output = BMO_slot_get(slot_args, slot_name); int totelement = 0, i = 0; const int respecthide = (op->flag & BMO_FLAG_RESPECT_HIDE) != 0; @@ -727,7 +811,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl BMIter iter; BMElem *ele; - BMO_slot_buffer_alloc(op, slot_name, totelement); + BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); /* TODO - collapse these loops into one */ @@ -736,7 +820,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) && BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { - ((BMElem **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } @@ -747,7 +831,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) && BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { - ((BMElem **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } @@ -758,7 +842,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) && BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { - ((BMElem **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } @@ -769,46 +853,74 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl } } -void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag) { - bmo_slot_buffer_from_hflag(bm, op, slot_name, htype, hflag, TRUE); + bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, TRUE); } -void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag) { - bmo_slot_buffer_from_hflag(bm, op, slot_name, htype, hflag, FALSE); + bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, FALSE); +} + +void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele) +{ + BMO_ASSERT_SLOT_IN_OP(slot, op); + BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE); + BLI_assert(slot->len == 0 || slot->len == 1); + + BLI_assert(slot->slot_subtype.elem & ele->htype); + + slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4); /* XXX, why 'x4' ? */ + slot->len = 1; + *slot->data.buf = ele; +} + +void *BMO_slot_buffer_get_single(BMOpSlot *slot) +{ + BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE); + BLI_assert(slot->len == 0 || slot->len == 1); + + return slot->len ? (BMHeader *)slot->data.buf[0] : NULL; } /** * Copies the values from another slot to the end of the output slot. */ -void BMO_slot_buffer_append(BMOperator *output_op, const char *output_slot_name, - BMOperator *other_op, const char *other_slot_name) +void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + struct MemArena *arena_dst) { - BMOpSlot *output_slot = BMO_slot_get(output_op, output_slot_name); - BMOpSlot *other_slot = BMO_slot_get(other_op, other_slot_name); + BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst); + BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src); - BLI_assert(output_slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF && - other_slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF && + slot_src->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - if (output_slot->len == 0) { + if (slot_dst->len == 0) { /* output slot is empty, copy rather than append */ - BMO_slot_copy(other_op, output_op, other_slot_name, output_slot_name); + _bmo_slot_copy(slot_args_src, slot_name_src, + slot_args_dst, slot_name_dst, + arena_dst); } - else if (other_slot->len != 0) { - int elem_size = BMO_OPSLOT_TYPEINFO[output_slot->slot_type]; - int alloc_size = elem_size * (output_slot->len + other_slot->len); + else if (slot_src->len != 0) { + int elem_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type]; + int alloc_size = elem_size * (slot_dst->len + slot_src->len); /* allocate new buffer */ - void *buf = BLI_memarena_alloc(output_op->arena, alloc_size); + void *buf = BLI_memarena_alloc(arena_dst, alloc_size); /* copy slot data */ - memcpy(buf, output_slot->data.buf, elem_size * output_slot->len); - memcpy(((char *)buf) + elem_size * output_slot->len, other_slot->data.buf, elem_size * other_slot->len); + memcpy(buf, slot_dst->data.buf, elem_size * slot_dst->len); + memcpy(((char *)buf) + elem_size * slot_dst->len, slot_src->data.buf, elem_size * slot_src->len); - output_slot->data.buf = buf; - output_slot->len += other_slot->len; + slot_dst->data.buf = buf; + slot_dst->len += slot_src->len; } } @@ -818,13 +930,15 @@ void BMO_slot_buffer_append(BMOperator *output_op, const char *output_slot_name, * Copies elements of a certain type, which have a certain flag set * into an output slot for an operator. */ -static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, const char *slot_name, +static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag, const short test_for_enabled) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); int totelement, i = 0; + BLI_assert(op->slots_in == slot_args || op->slots_out == slot_args); BLI_assert(ELEM(TRUE, FALSE, test_for_enabled)); if (test_for_enabled) @@ -833,15 +947,16 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, const char *slo totelement = BMO_mesh_disabled_flag_count(bm, htype, oflag); BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); if (totelement) { BMIter iter; BMHeader *ele; BMHeader **ele_array; - BMO_slot_buffer_alloc(op, slot_name, totelement); + BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); - ele_array = (BMHeader **)slot->data.p; + ele_array = (BMHeader **)slot->data.buf; /* TODO - collapse these loops into one */ @@ -877,16 +992,18 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, const char *slo } } -void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { - bmo_slot_buffer_from_flag(bm, op, slot_name, htype, oflag, TRUE); + bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, TRUE); } -void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { - bmo_slot_buffer_from_flag(bm, op, slot_name, htype, oflag, FALSE); + bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, FALSE); } /** @@ -895,16 +1012,18 @@ void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, const char *s * Header Flags elements in a slots buffer, automatically * using the selection API where appropriate. */ -void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_hflag_enable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, const char do_flush) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); - BMElem **data = slot->data.p; + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BMElem **data = (BMElem **)slot->data.buf; int i; const char do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT)); const char do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN)); BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); for (i = 0; i < slot->len; i++, data++) { if (!(htype & (*data)->head.htype)) @@ -928,16 +1047,18 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOperator *op, const char *slot_na * Removes flags from elements in a slots buffer, automatically * using the selection API where appropriate. */ -void BMO_slot_buffer_hflag_disable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_hflag_disable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, const char do_flush) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); - BMElem **data = slot->data.p; + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BMElem **data = (BMElem **)slot->data.buf; int i; const char do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT)); const char do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN)); BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); for (i = 0; i < slot->len; i++, data++) { if (!(htype & (*data)->head.htype)) @@ -979,14 +1100,16 @@ int BMO_vert_edge_flags_count(BMesh *bm, BMVert *v, const short oflag) * * Flags elements in a slots buffer */ -void BMO_slot_buffer_flag_enable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_flag_enable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BMHeader **data = slot->data.p; int i; BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); for (i = 0; i < slot->len; i++) { if (!(htype & data[i]->htype)) @@ -1001,14 +1124,16 @@ void BMO_slot_buffer_flag_enable(BMesh *bm, BMOperator *op, const char *slot_nam * * Removes flags from elements in a slots buffer */ -void BMO_slot_buffer_flag_disable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_flag_disable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); - BMHeader **data = slot->data.p; + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BMHeader **data = (BMHeader **)slot->data.buf; int i; BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); for (i = 0; i < slot->len; i++) { if (!(htype & data[i]->htype)) @@ -1046,7 +1171,9 @@ static void bmo_flag_layer_alloc(BMesh *bm) /* store memcpy size for reuse */ const size_t old_totflags_size = (bm->totflags * sizeof(BMFlagLayer)); - + + BLI_assert(oldpool != NULL); + bm->totflags++; /* allocate new flag poo */ @@ -1058,18 +1185,21 @@ static void bmo_flag_layer_alloc(BMesh *bm) ele->oflags = BLI_mempool_calloc(newpool); memcpy(ele->oflags, oldflags, old_totflags_size); BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); } BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { oldflags = ele->oflags; ele->oflags = BLI_mempool_calloc(newpool); memcpy(ele->oflags, oldflags, old_totflags_size); BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); } BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { oldflags = ele->oflags; ele->oflags = BLI_mempool_calloc(newpool); memcpy(ele->oflags, oldflags, old_totflags_size); BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); } bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); @@ -1095,7 +1225,7 @@ static void bmo_flag_layer_free(BMesh *bm) /* de-increment the totflags first.. */ bm->totflags--; /* allocate new flag poo */ - bm->toolflagpool = newpool = BLI_mempool_create(new_totflags_size, 512, 512, BLI_MEMPOOL_SYSMALLOC); + bm->toolflagpool = newpool = BLI_mempool_create(new_totflags_size, 512, 512, 0); /* now go through and memcpy all the flag */ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) { @@ -1103,18 +1233,21 @@ static void bmo_flag_layer_free(BMesh *bm) ele->oflags = BLI_mempool_calloc(newpool); memcpy(ele->oflags, oldflags, new_totflags_size); BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); } BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { oldflags = ele->oflags; ele->oflags = BLI_mempool_calloc(newpool); memcpy(ele->oflags, oldflags, new_totflags_size); BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); } BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { oldflags = ele->oflags; ele->oflags = BLI_mempool_calloc(newpool); memcpy(ele->oflags, oldflags, new_totflags_size); BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); } bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); @@ -1149,14 +1282,14 @@ static void bmo_flag_layer_clear(BMesh *bm) bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); } -void *BMO_slot_buffer_elem_first(BMOperator *op, const char *slot_name) +void *BMO_slot_buffer_elem_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) return NULL; - return slot->data.buf ? *(void **)slot->data.buf : NULL; + return slot->data.buf ? *slot->data.buf : NULL; } /** @@ -1165,10 +1298,11 @@ void *BMO_slot_buffer_elem_first(BMOperator *op, const char *slot_name) * \param restrictmask restricts the iteration to certain element types * (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating * over an element buffer (not a mapping). */ -void *BMO_iter_new(BMOIter *iter, BMesh *UNUSED(bm), BMOperator *op, - const char *slot_name, const char restrictmask) +void *BMO_iter_new(BMOIter *iter, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char restrictmask) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); memset(iter, 0, sizeof(BMOIter)); @@ -1190,35 +1324,42 @@ void *BMO_iter_new(BMOIter *iter, BMesh *UNUSED(bm), BMOperator *op, void *BMO_iter_step(BMOIter *iter) { - if (iter->slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { - BMHeader *h; + BMOpSlot *slot = iter->slot; + if (slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { + BMHeader *ele; - if (iter->cur >= iter->slot->len) { + if (iter->cur >= slot->len) { return NULL; } - h = ((void **)iter->slot->data.buf)[iter->cur++]; - while (!(iter->restrictmask & h->htype)) { - if (iter->cur >= iter->slot->len) { + ele = slot->data.buf[iter->cur++]; + while (!(iter->restrictmask & ele->htype)) { + if (iter->cur >= slot->len) { return NULL; } - h = ((void **)iter->slot->data.buf)[iter->cur++]; + ele = slot->data.buf[iter->cur++]; + BLI_assert((ele == NULL) || (slot->slot_subtype.elem & ele->htype)); } - return h; + BLI_assert((ele == NULL) || (slot->slot_subtype.elem & ele->htype)); + + return ele; } - else if (iter->slot->slot_type == BMO_OP_SLOT_MAPPING) { + else if (slot->slot_type == BMO_OP_SLOT_MAPPING) { BMOElemMapping *map; void *ret = BLI_ghashIterator_getKey(&iter->giter); map = BLI_ghashIterator_getValue(&iter->giter); - iter->val = map + 1; + iter->val = BMO_OP_SLOT_MAPPING_DATA(map); BLI_ghashIterator_step(&iter->giter); return ret; } + else { + BLI_assert(0); + } return NULL; } @@ -1302,24 +1443,26 @@ int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op) #define NEXT_CHAR(fmt) ((fmt)[0] != 0 ? (fmt)[1] : 0) -static int bmo_name_to_slotcode(BMOpDefine *def, const char *name) +static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int i; + int i = 0; - for (i = 0; def->slot_types[i].type; i++) { - if (!strncmp(name, def->slot_types[i].name, MAX_SLOTNAME)) { + while (slot_args->slot_name) { + if (strncmp(identifier, slot_args->slot_name, MAX_SLOTNAME) == 0) { return i; } + slot_args++; + i++; } return -1; } -static int bmo_name_to_slotcode_check(BMOpDefine *def, const char *name) +static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int i = bmo_name_to_slotcode(def, name); + int i = bmo_name_to_slotcode(slot_args, identifier); if (i < 0) { - fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, name); + fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, identifier); } return i; @@ -1329,36 +1472,78 @@ static int bmo_opname_to_opcode(const char *opname) { int i; - for (i = 0; i < bmesh_total_ops; i++) { - if (!strcmp(opname, opdefines[i]->name)) { + for (i = 0; i < bmo_opdefines_total; i++) { + if (!strcmp(opname, bmo_opdefines[i]->opname)) { return i; } } - fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, opname); + fprintf(stderr, "%s: could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, opname); return -1; } -/* Example: - * BMO_op_callf(bm, BMO_FLAG_DEFAULTS, "delete %i %hv", DEL_ONLYFACES, BM_ELEM_SELECT); +/** + * \brief Format Strings for #BMOperator Initialization. * - * i - int - * b - boolean (same as int but 1/0 only) - * f - float - * hv - header flagged verts (hflag) - * he - header flagged edges (hflag) - * hf - header flagged faces (hflag) - * fv - flagged verts (oflag) - * fe - flagged edges (oflag) - * ff - flagged faces (oflag) + * This system is used to execute or initialize an operator, + * using a formatted-string system. * - * capitals - H, F to use the flag flipped (when the flag is off) - * Hv, He, Hf, Fv, Fe, Ff, + * The basic format for the format string is: + * `[operatorname] [slot_name]=%[code] [slot_name]=%[code]` + * + * Example: + * + * \code{.c} + * BMO_op_callf(bm, BMO_FLAG_DEFAULTS, + * "delete context=%i geom=%hv", + * DEL_ONLYFACES, BM_ELEM_SELECT); + * \endcode + * + * + * **Primitive Types** + * - `b` - boolean (same as int but 1/0 only). #BMO_OP_SLOT_BOOL + * - `i` - int. #BMO_OP_SLOT_INT + * - `f` - float. #BMO_OP_SLOT_FLT + * - `p` - pointer (normally to a Scene/Mesh/Object/BMesh). #BMO_OP_SLOT_PTR + * - `m3` - 3x3 matrix of floats. #BMO_OP_SLOT_MAT + * - `m4` - 4x4 matrix of floats. #BMO_OP_SLOT_MAT + * - `v` - 3D vector of floats. #BMO_OP_SLOT_VEC + * + * + * **Utility** + * + * Pass an existing slot which is copied to either an input or output slot. + * Taking the operator and slot-name pair of args. + * - `s` - slot_in (lower case) + * - `S` - slot_out (upper case) + * + * + * **Element Buffer** (#BMO_OP_SLOT_ELEMENT_BUF) + * - `e` - single element vert/edge/face (use with #BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE). + * - `av` - all verts + * - `ae` - all edges + * - `af` - all faces + * - `hv` - header flagged verts (hflag) + * - `he` - header flagged edges (hflag) + * - `hf` - header flagged faces (hflag) + * - `Hv` - header flagged verts (hflag off) + * - `He` - header flagged edges (hflag off) + * - `Hf` - header flagged faces (hflag off) + * - `fv` - flagged verts (oflag) + * - `fe` - flagged edges (oflag) + * - `ff` - flagged faces (oflag) + * - `Fv` - flagged verts (oflag off) + * - `Fe` - flagged edges (oflag off) + * - `Ff` - flagged faces (oflag off) + * + * \note The common v/e/f suffix can be mixed, + * so `avef` is can be used for all verts, edges and faces. + * Order is not important so `Hfev` is also valid (all unflagged verts, edges and faces). */ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, va_list vlist) { - BMOpDefine *def; +// BMOpDefine *def; char *opname, *ofmt, *fmt; char slot_name[64] = {0}; int i /*, n = strlen(fmt) */, stop /*, slot_code = -1 */, type, state; @@ -1397,7 +1582,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v } BMO_op_init(bm, op, flag, opname); - def = opdefines[i]; +// def = bmo_opdefines[i]; i = 0; state = 1; /* 0: not inside slot_code name, 1: inside slot_code name */ @@ -1420,7 +1605,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v fmt[i] = 0; - if (bmo_name_to_slotcode_check(def, fmt) < 0) { + if (bmo_name_to_slotcode_check(op->slots_in, fmt) < 0) { GOTO_ERROR("name to slot code check failed"); } @@ -1446,47 +1631,55 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v else if (c == '4') size = 4; else GOTO_ERROR("matrix size was not 3 or 4"); - BMO_slot_mat_set(op, slot_name, va_arg(vlist, void *), size); + BMO_slot_mat_set(op, op->slots_in, slot_name, va_arg(vlist, void *), size); state = 1; break; } case 'v': { - BMO_slot_vec_set(op, slot_name, va_arg(vlist, float *)); + BMO_slot_vec_set(op->slots_in, slot_name, va_arg(vlist, float *)); state = 1; break; } - case 'e': + case 'e': /* single vert/edge/face */ { BMHeader *ele = va_arg(vlist, void *); - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(op->slots_in, slot_name); - slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4); - slot->len = 1; - *((void **)slot->data.buf) = ele; + BMO_slot_buffer_from_single(op, slot, ele); state = 1; break; } case 's': + case 'S': { - BMOperator *op2 = va_arg(vlist, void *); - const char *slot_name2 = va_arg(vlist, char *); + BMOperator *op_other = va_arg(vlist, void *); + const char *slot_name_other = va_arg(vlist, char *); - BMO_slot_copy(op2, op, slot_name2, slot_name); + if (*fmt == 's') { + BLI_assert(bmo_name_to_slotcode_check(op_other->slots_in, slot_name_other) != -1); + BMO_slot_copy(op_other, slots_in, slot_name_other, + op, slots_in, slot_name); + } + else { + BLI_assert(bmo_name_to_slotcode_check(op_other->slots_out, slot_name_other) != -1); + BMO_slot_copy(op_other, slots_out, slot_name_other, + op, slots_in, slot_name); + } state = 1; break; } case 'i': - BMO_slot_int_set(op, slot_name, va_arg(vlist, int)); + BMO_slot_int_set(op->slots_in, slot_name, va_arg(vlist, int)); state = 1; break; case 'b': - BMO_slot_bool_set(op, slot_name, va_arg(vlist, int)); + BMO_slot_bool_set(op->slots_in, slot_name, va_arg(vlist, int)); state = 1; break; case 'p': - BMO_slot_ptr_set(op, slot_name, va_arg(vlist, void *)); + BMO_slot_ptr_set(op->slots_in, slot_name, va_arg(vlist, void *)); state = 1; break; case 'f': @@ -1497,7 +1690,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v type = *fmt; if (NEXT_CHAR(fmt) == ' ' || NEXT_CHAR(fmt) == '\0') { - BMO_slot_float_set(op, slot_name, va_arg(vlist, double)); + BMO_slot_float_set(op->slots_in, slot_name, va_arg(vlist, double)); } else { htype = 0; @@ -1519,19 +1712,19 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v } if (type == 'h') { - BMO_slot_buffer_from_enabled_hflag(bm, op, slot_name, htype, va_arg(vlist, int)); + BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); } else if (type == 'H') { - BMO_slot_buffer_from_disabled_hflag(bm, op, slot_name, htype, va_arg(vlist, int)); + BMO_slot_buffer_from_disabled_hflag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); } else if (type == 'a') { - BMO_slot_buffer_from_all(bm, op, slot_name, htype); + BMO_slot_buffer_from_all(bm, op, op->slots_in, slot_name, htype); } else if (type == 'f') { - BMO_slot_buffer_from_enabled_flag(bm, op, slot_name, htype, va_arg(vlist, int)); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); } else if (type == 'F') { - BMO_slot_buffer_from_disabled_flag(bm, op, slot_name, htype, va_arg(vlist, int)); + BMO_slot_buffer_from_disabled_flag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); } } diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h index 14da93302b9..d02b0dce728 100644 --- a/source/blender/bmesh/intern/bmesh_operators.h +++ b/source/blender/bmesh/intern/bmesh_operators.h @@ -83,34 +83,22 @@ enum { SIMVERT_EDGE }; -enum { - OPUVC_AXIS_X = 1, - OPUVC_AXIS_Y -}; - -enum { - DIRECTION_CW = 1, - DIRECTION_CCW -}; - /* vertex path selection values */ enum { VPATH_SELECT_EDGE_LENGTH = 0, VPATH_SELECT_TOPOLOGICAL }; -extern BMOpDefine *opdefines[]; -extern int bmesh_total_ops; +extern const BMOpDefine *bmo_opdefines[]; +extern const int bmo_opdefines_total; /*------specific operator helper functions-------*/ - -struct Object; - void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, float smooth, float fractal, float along_normal, int numcuts, int seltype, int cornertype, - const short use_singleedge, const short use_gridfill, + const short use_single_edge, const short use_grid_fill, + const short use_only_quads, int seed); #include "intern/bmesh_operator_api_inline.h" diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h index 65c9cf0c421..9175af1c822 100644 --- a/source/blender/bmesh/intern/bmesh_operators_private.h +++ b/source/blender/bmesh/intern/bmesh_operators_private.h @@ -61,7 +61,7 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op); void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op); void bmo_duplicate_exec(BMesh *bm, BMOperator *op); void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op); -void bmo_edgenet_prepare(BMesh *bm, BMOperator *op); +void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op); void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op); void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op); void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op); diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 98edceb30a2..2e0471863d4 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -162,7 +162,7 @@ float BM_face_calc_area(BMFace *f) float area; int i; - BLI_array_fixedstack_declare(verts, BM_NGON_STACK_SIZE, f->len, __func__); + BLI_array_fixedstack_declare(verts, BM_DEFAULT_NGON_STACK_SIZE, f->len, __func__); BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, i) { copy_v3_v3(verts[i], l->v->co); @@ -677,6 +677,7 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa BMLoop *l_first; const float cos_threshold = 0.9f; + const float bias = 1.0f + 1e-6f; if (f->len == 4) { BMLoop *larr[4]; @@ -691,7 +692,7 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa /* pick 0/1 based on best lenth */ /* XXX Can't only rely on such test, also must check we do not get (too much) degenerated triangles!!! */ i = (((len_squared_v3v3(larr[0]->v->co, larr[2]->v->co) > - len_squared_v3v3(larr[1]->v->co, larr[3]->v->co))) != use_beauty); + len_squared_v3v3(larr[1]->v->co, larr[3]->v->co) * bias)) != use_beauty); i4 = (i + 3) % 4; /* Check produced tris aren’t too flat/narrow... * Probably not the best test, but is quite efficient and should at least avoid null-area faces! */ @@ -965,8 +966,8 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) float fac1 = 1.0000001f, fac2 = 0.9f; //9999f; //0.999f; int i, j, a = 0, clen; - BLI_array_fixedstack_declare(projverts, BM_NGON_STACK_SIZE, f->len, "projvertsb"); - BLI_array_fixedstack_declare(edgeverts, BM_NGON_STACK_SIZE * 2, len * 2, "edgevertsb"); + BLI_array_fixedstack_declare(projverts, BM_DEFAULT_NGON_STACK_SIZE, f->len, "projvertsb"); + BLI_array_fixedstack_declare(edgeverts, BM_DEFAULT_NGON_STACK_SIZE * 2, len * 2, "edgevertsb"); i = 0; l = BM_iter_new(&iter, bm, BM_LOOPS_OF_FACE, f); diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h index b3fe3676ab8..850e81ba3ac 100644 --- a/source/blender/bmesh/intern/bmesh_private.h +++ b/source/blender/bmesh/intern/bmesh_private.h @@ -56,15 +56,21 @@ int bmesh_elem_check(void *element, const char htype); int bmesh_radial_length(BMLoop *l); int bmesh_disk_count(BMVert *v); -/* NOTE: ensure different parts of the API do not conflict +/** + * Internal BMHeader.api_flag + * \note Ensure different parts of the API do not conflict * on using these internal flags!*/ -#define _FLAG_JF 1 /* join faces */ -#define _FLAG_MF 2 /* make face */ -#define _FLAG_MV 2 /* make face, vertex */ +enum { + _FLAG_JF = (1 << 0), /* join faces */ + _FLAG_MF = (1 << 1), /* make face */ + _FLAG_MV = (1 << 1), /* make face, vertex */ + _FLAG_OVERLAP = (1 << 2) /* general overlap flag */ +}; -#define BM_ELEM_API_FLAG_ENABLE(element, f) ((element)->oflags[0].pflag |= (f)) -#define BM_ELEM_API_FLAG_DISABLE(element, f) ((element)->oflags[0].pflag &= ~(f)) -#define BM_ELEM_API_FLAG_TEST(element, f) ((element)->oflags[0].pflag & (f)) +#define BM_ELEM_API_FLAG_ENABLE(element, f) ((element)->head.api_flag |= (f)) +#define BM_ELEM_API_FLAG_DISABLE(element, f) ((element)->head.api_flag &= ~(f)) +#define BM_ELEM_API_FLAG_TEST(element, f) ((element)->head.api_flag & (f)) +#define BM_ELEM_API_FLAG_CLEAR(element) ((element)->head.api_flag = 0) void calc_poly_plane(float (*verts)[3], const int nverts); void poly_rotate_plane(const float normal[3], float (*verts)[3], const int nverts); diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 4b07dd74eef..195c60c5a9c 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -39,8 +39,6 @@ #include "bmesh.h" #include "intern/bmesh_private.h" -#define BM_OVERLAP (1 << 13) - /** * Returns whether or not a given vertex is * is part of a given edge. @@ -240,7 +238,7 @@ int BM_vert_in_face(BMFace *f, BMVert *v) * Compares the number of vertices in an array * that appear in a given face */ -int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len) +int BM_verts_in_face(BMFace *f, BMVert **varr, int len) { BMLoop *l_iter, *l_first; @@ -251,7 +249,7 @@ int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len) int i, count = 0; for (i = 0; i < len; i++) { - BMO_elem_flag_enable(bm, varr[i], BM_OVERLAP); + BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP); } #ifdef USE_BMESH_HOLES @@ -266,14 +264,16 @@ int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len) #endif do { - if (BMO_elem_flag_test(bm, l_iter->v, BM_OVERLAP)) { + if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) { count++; } } while ((l_iter = l_iter->next) != l_first); } - for (i = 0; i < len; i++) BMO_elem_flag_disable(bm, varr[i], BM_OVERLAP); + for (i = 0; i < len; i++) { + BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP); + } return count; } @@ -401,6 +401,7 @@ BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step) } else { BLI_assert(0); + return NULL; } if (BM_edge_is_manifold(e_next)) { @@ -723,6 +724,47 @@ int BM_edge_is_boundary(BMEdge *e) } #endif +/** + * Returns the number of faces that are adjacent to both f1 and f2, + * \note Could be sped up a bit by not using iterators and by tagging + * faces on either side, then count the tags rather then searching. + */ +int BM_face_share_face_count(BMFace *f1, BMFace *f2) +{ + BMIter iter1, iter2; + BMEdge *e; + BMFace *f; + int count = 0; + + BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) { + BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) { + if (f != f1 && f != f2 && BM_face_share_edge_check(f, f2)) + count++; + } + } + + return count; +} + +/** + * same as #BM_face_share_face_count but returns a bool + */ +int BM_face_share_face_check(BMFace *f1, BMFace *f2) +{ + BMIter iter1, iter2; + BMEdge *e; + BMFace *f; + + BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) { + BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) { + if (f != f1 && f != f2 && BM_face_share_edge_check(f, f2)) + return TRUE; + } + } + + return FALSE; +} + /** * Counts the number of edges two faces share (if any) */ @@ -742,10 +784,28 @@ int BM_face_share_edge_count(BMFace *f1, BMFace *f2) return count; } +/** + * Returns TRUE if the faces share an edge + */ +int BM_face_share_edge_check(BMFace *f1, BMFace *f2) +{ + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f1); + do { + if (bmesh_radial_face_find(l_iter->e, f2)) { + return TRUE; + } + } while ((l_iter = l_iter->next) != l_first); + + return FALSE; +} + /** * Test if e1 shares any faces with e2 */ -int BM_edge_share_face_count(BMEdge *e1, BMEdge *e2) +int BM_edge_share_face_check(BMEdge *e1, BMEdge *e2) { BMLoop *l; BMFace *f; @@ -763,10 +823,33 @@ int BM_edge_share_face_count(BMEdge *e1, BMEdge *e2) return FALSE; } +/** + * Test if e1 shares any quad faces with e2 + */ +int BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2) +{ + BMLoop *l; + BMFace *f; + + if (e1->l && e2->l) { + l = e1->l; + do { + f = l->f; + if (f->len == 4) { + if (bmesh_radial_face_find(e2, f)) { + return TRUE; + } + } + l = l->radial_next; + } while (l != e1->l); + } + return FALSE; +} + /** * Tests to see if e1 shares a vertex with e2 */ -int BM_edge_share_vert_count(BMEdge *e1, BMEdge *e2) +int BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2) { return (e1->v1 == e2->v1 || e1->v1 == e2->v2 || @@ -1023,7 +1106,12 @@ float BM_vert_calc_shell_factor(BMVert *v) accum_angle += face_angle; } - return accum_shell / accum_angle; + if (accum_angle != 0.0f) { + return accum_shell / accum_angle; + } + else { + return 1.0f; + } } /** @@ -1044,7 +1132,12 @@ float BM_vert_calc_mean_tagged_edge_length(BMVert *v) } } - return length / (float)tot; + if (tot) { + return length / (float)tot; + } + else { + return 0.0f; + } } @@ -1147,7 +1240,7 @@ BMEdge *BM_edge_find_double(BMEdge *e) * \returns TRUE for overlap * */ -int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_overlapface) +int BM_face_exists_overlap(BMVert **varr, int len, BMFace **r_overlapface) { BMIter viter; BMFace *f; @@ -1155,7 +1248,7 @@ int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_overlap for (i = 0; i < len; i++) { BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { - amount = BM_verts_in_face(bm, f, varr, len); + amount = BM_verts_in_face(f, varr, len); if (amount >= len) { if (r_overlapface) { *r_overlapface = f; @@ -1177,7 +1270,7 @@ int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_overlap * there is a face with exactly those vertices * (and only those vertices). */ -int BM_face_exists(BMesh *bm, BMVert **varr, int len, BMFace **r_existface) +int BM_face_exists(BMVert **varr, int len, BMFace **r_existface) { BMIter viter; BMFace *f; @@ -1185,7 +1278,7 @@ int BM_face_exists(BMesh *bm, BMVert **varr, int len, BMFace **r_existface) for (i = 0; i < len; i++) { BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { - amount = BM_verts_in_face(bm, f, varr, len); + amount = BM_verts_in_face(f, varr, len); if (amount == len && amount == f->len) { if (r_existface) { *r_existface = f; @@ -1323,7 +1416,7 @@ int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) int BM_face_exists_multi_edge(BMEdge **earr, int len) { BMVert **varr; - BLI_array_fixedstack_declare(varr, BM_NGON_STACK_SIZE, len, __func__); + BLI_array_fixedstack_declare(varr, BM_DEFAULT_NGON_STACK_SIZE, len, __func__); int ok; int i, i_next; @@ -1349,3 +1442,38 @@ int BM_face_exists_multi_edge(BMEdge **earr, int len) return ok; } + +/* convenience functions for checking flags */ +int BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag) +{ + return (BM_elem_flag_test(e->v1, hflag) || + BM_elem_flag_test(e->v2, hflag)); +} + +int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag) +{ + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (BM_elem_flag_test(l_iter->v, hflag)) { + return TRUE; + } + } while ((l_iter = l_iter->next) != l_first); + return FALSE; +} + +int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag) +{ + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (BM_elem_flag_test(l_iter->e, hflag)) { + return TRUE; + } + } while ((l_iter = l_iter->next) != l_first); + return FALSE; +} diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 34d0747676c..7a18f69371e 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -28,7 +28,7 @@ */ int BM_vert_in_face(BMFace *f, BMVert *v); -int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len); +int BM_verts_in_face(BMFace *f, BMVert **varr, int len); int BM_edge_in_face(BMFace *f, BMEdge *e); int BM_edge_in_loop(BMEdge *e, BMLoop *l); @@ -77,16 +77,21 @@ BMLoop *BM_face_find_longest_loop(BMFace *f); BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2); BMEdge *BM_edge_find_double(BMEdge *e); -int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_existface); +int BM_face_exists_overlap(BMVert **varr, int len, BMFace **r_existface); -int BM_face_exists(BMesh *bm, BMVert **varr, int len, BMFace **r_existface); +int BM_face_exists(BMVert **varr, int len, BMFace **r_existface); int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len); int BM_face_exists_multi_edge(BMEdge **earr, int len); +int BM_face_share_face_count(BMFace *f1, BMFace *f2); int BM_face_share_edge_count(BMFace *f1, BMFace *f2); -int BM_edge_share_face_count(BMEdge *e1, BMEdge *e2); -int BM_edge_share_vert_count(BMEdge *e1, BMEdge *e2); + +int BM_face_share_face_check(BMFace *f1, BMFace *f2); +int BM_face_share_edge_check(BMFace *f1, BMFace *f2); +int BM_edge_share_face_check(BMEdge *e1, BMEdge *e2); +int BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2); +int BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2); BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2); BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v); @@ -96,4 +101,8 @@ void BM_edge_ordered_verts(BMEdge *edge, BMVert **r_v1, BMVert **r_v2); void BM_edge_ordered_verts_ex(BMEdge *edge, BMVert **r_v1, BMVert **r_v2, BMLoop *edge_loop); +int BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag); +int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag); +int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag); + #endif /* __BMESH_QUERIES_H__ */ diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index c5120571755..126d0f46119 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -15,7 +15,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Contributor(s): Joseph Eagar. + * Contributor(s): * * ***** END GPL LICENSE BLOCK ***** */ @@ -24,865 +24,38 @@ * \ingroup bmesh */ -#include "MEM_guardedalloc.h" - -#include "BLI_array.h" -#include "BLI_math.h" -#include "BLI_smallhash.h" - -#include "BKE_customdata.h" +#include "BLI_utildefines.h" #include "bmesh.h" #include "intern/bmesh_operators_private.h" /* own include */ -#define BEVEL_FLAG 1 -#define BEVEL_DEL 2 -#define FACE_NEW 4 -#define EDGE_OLD 8 -#define FACE_OLD 16 -#define VERT_OLD 32 -#define FACE_SPAN 64 -#define FACE_HOLE 128 - -typedef struct LoopTag { - BMVert *newv; -} LoopTag; - -typedef struct EdgeTag { - BMVert *newv1, *newv2; -} EdgeTag; - -static void calc_corner_co(BMLoop *l, const float fac, float r_co[3], - const short do_dist, const short do_even) -{ - float no[3], l_vec_prev[3], l_vec_next[3], l_co_prev[3], l_co[3], l_co_next[3], co_ofs[3]; - int is_concave; - - /* first get the prev/next verts */ - if (l->f->len > 2) { - copy_v3_v3(l_co_prev, l->prev->v->co); - copy_v3_v3(l_co, l->v->co); - copy_v3_v3(l_co_next, l->next->v->co); - - /* calculate normal */ - sub_v3_v3v3(l_vec_prev, l_co_prev, l_co); - sub_v3_v3v3(l_vec_next, l_co_next, l_co); - - cross_v3_v3v3(no, l_vec_prev, l_vec_next); - is_concave = dot_v3v3(no, l->f->no) > 0.0f; - } - else { - BMIter iter; - BMLoop *l2; - float up[3] = {0.0f, 0.0f, 1.0f}; - - copy_v3_v3(l_co_prev, l->prev->v->co); - copy_v3_v3(l_co, l->v->co); - - BM_ITER_ELEM (l2, &iter, l->v, BM_LOOPS_OF_VERT) { - if (l2->f != l->f) { - copy_v3_v3(l_co_next, BM_edge_other_vert(l2->e, l2->next->v)->co); - break; - } - } - - sub_v3_v3v3(l_vec_prev, l_co_prev, l_co); - sub_v3_v3v3(l_vec_next, l_co_next, l_co); - - cross_v3_v3v3(no, l_vec_prev, l_vec_next); - if (dot_v3v3(no, no) == 0.0f) { - no[0] = no[1] = 0.0f; no[2] = -1.0f; - } - - is_concave = dot_v3v3(no, up) < 0.0f; - } - - - /* now calculate the new location */ - if (do_dist) { /* treat 'fac' as distance */ - - normalize_v3(l_vec_prev); - normalize_v3(l_vec_next); - - add_v3_v3v3(co_ofs, l_vec_prev, l_vec_next); - if (UNLIKELY(normalize_v3(co_ofs) == 0.0f)) { /* edges form a straight line */ - cross_v3_v3v3(co_ofs, l_vec_prev, l->f->no); - } - - if (do_even) { - negate_v3(l_vec_next); - mul_v3_fl(co_ofs, fac * shell_angle_to_dist(0.5f * angle_normalized_v3v3(l_vec_prev, l_vec_next))); - /* negate_v3(l_vec_next); */ /* no need unless we use again */ - } - else { - mul_v3_fl(co_ofs, fac); - } - } - else { /* treat as 'fac' as a factor (0 - 1) */ - - /* not strictly necessary, balance vectors - * so the longer edge doesn't skew the result, - * gives nicer, move even output. - * - * Use the minimum rather then the middle value so skinny faces don't flip along the short axis */ - float min_fac = min_ff(normalize_v3(l_vec_prev), normalize_v3(l_vec_next)); - float angle; - - if (do_even) { - negate_v3(l_vec_next); - angle = angle_normalized_v3v3(l_vec_prev, l_vec_next); - negate_v3(l_vec_next); /* no need unless we use again */ - } - else { - angle = 0.0f; - } - - mul_v3_fl(l_vec_prev, min_fac); - mul_v3_fl(l_vec_next, min_fac); - - add_v3_v3v3(co_ofs, l_vec_prev, l_vec_next); - - if (UNLIKELY(is_zero_v3(co_ofs))) { - cross_v3_v3v3(co_ofs, l_vec_prev, l->f->no); - normalize_v3(co_ofs); - mul_v3_fl(co_ofs, min_fac); - } - - /* done */ - if (do_even) { - mul_v3_fl(co_ofs, (fac * 0.5f) * shell_angle_to_dist(0.5f * angle)); - } - else { - mul_v3_fl(co_ofs, fac * 0.5f); - } - } - - /* apply delta vec */ - if (is_concave) - negate_v3(co_ofs); - - add_v3_v3v3(r_co, co_ofs, l->v->co); -} - - -#define ETAG_SET(e, v, nv) ( \ - (v) == (e)->v1 ? \ - (etags[BM_elem_index_get((e))].newv1 = (nv)) : \ - (etags[BM_elem_index_get((e))].newv2 = (nv)) \ - ) - -#define ETAG_GET(e, v) ( \ - (v) == (e)->v1 ? \ - (etags[BM_elem_index_get((e))].newv1) : \ - (etags[BM_elem_index_get((e))].newv2) \ - ) - void bmo_bevel_exec(BMesh *bm, BMOperator *op) { - BMOIter siter; - BMIter iter; - BMEdge *e; - BMVert *v; - BMFace **faces = NULL, *f; - LoopTag *tags = NULL, *tag; - EdgeTag *etags = NULL; - BMVert **verts = NULL; - BMEdge **edges = NULL; - BLI_array_declare(faces); - BLI_array_declare(tags); - BLI_array_declare(etags); - BLI_array_declare(verts); - BLI_array_declare(edges); - SmallHash hash; - float fac = BMO_slot_float_get(op, "percent"); - const short do_even = BMO_slot_bool_get(op, "use_even"); - const short do_dist = BMO_slot_bool_get(op, "use_dist"); - int i, li, has_elens, HasMDisps = CustomData_has_layer(&bm->ldata, CD_MDISPS); - - has_elens = CustomData_has_layer(&bm->edata, CD_PROP_FLT) && BMO_slot_bool_get(op, "use_lengths"); - if (has_elens) { - li = BMO_slot_int_get(op, "lengthlayer"); + const float offset = BMO_slot_float_get(op->slots_in, "offset"); + const int seg = BMO_slot_int_get(op->slots_in, "segments"); + + if (offset > 0) { + BMOIter siter; + BMEdge *e; + BMVert *v; + + /* first flush 'geom' into flags, this makes it possible to check connected data, + * BM_FACE is cleared so we can put newly created faces into a bmesh slot. */ + BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, FALSE); + + BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) { + BM_elem_flag_enable(v, BM_ELEM_TAG); + } + + BMO_ITER (e, &siter, op->slots_in, "geom", BM_EDGE) { + if (BM_edge_is_manifold(e)) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + } + } + + BM_mesh_bevel(bm, offset, seg); + + BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG); } - - BLI_smallhash_init(&hash); - - BMO_ITER (e, &siter, bm, op, "geom", BM_EDGE) { - BMO_elem_flag_enable(bm, e, BEVEL_FLAG | BEVEL_DEL); - BMO_elem_flag_enable(bm, e->v1, BEVEL_FLAG | BEVEL_DEL); - BMO_elem_flag_enable(bm, e->v2, BEVEL_FLAG | BEVEL_DEL); - - if (BM_edge_face_count(e) < 2) { - BMO_elem_flag_disable(bm, e, BEVEL_DEL); - BMO_elem_flag_disable(bm, e->v1, BEVEL_DEL); - BMO_elem_flag_disable(bm, e->v2, BEVEL_DEL); - } -#if 0 - if (BM_edge_face_count(e) == 0) { - BMVert *verts[2] = {e->v1, e->v2}; - BMEdge *edges[2] = {e, BM_edge_create(bm, e->v1, e->v2, e, 0)}; - - BMO_elem_flag_enable(bm, edges[1], BEVEL_FLAG); - BM_face_create(bm, verts, edges, 2, FALSE); - } -#endif - } - - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - BMO_elem_flag_enable(bm, v, VERT_OLD); - } - -#if 0 - /* a bit of cleaner code that, alas, doens't work. */ - /* build edge tag */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BMO_elem_flag_test(bm, e->v1, BEVEL_FLAG) || BMO_elem_flag_test(bm, e->v2, BEVEL_FLAG)) { - BMIter liter; - BMLoop *l; - - if (!BMO_elem_flag_test(bm, e, EDGE_OLD)) { - BM_elem_index_set(e, BLI_array_count(etags)); /* set_dirty! */ - BLI_array_grow_one(etags); - - BMO_elem_flag_enable(bm, e, EDGE_OLD); - } - - BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) { - BMLoop *l2; - BMIter liter2; - - if (BMO_elem_flag_test(bm, l->f, BEVEL_FLAG)) - continue; - - BM_ITER_ELEM (l2, &liter2, l->f, BM_LOOPS_OF_FACE) { - BM_elem_index_set(l2, BLI_array_count(tags)); /* set_loop */ - BLI_array_grow_one(tags); - - if (!BMO_elem_flag_test(bm, l2->e, EDGE_OLD)) { - BM_elem_index_set(l2->e, BLI_array_count(etags)); /* set_dirty! */ - BLI_array_grow_one(etags); - - BMO_elem_flag_enable(bm, l2->e, EDGE_OLD); - } - } - - BMO_elem_flag_enable(bm, l->f, BEVEL_FLAG); - BLI_array_append(faces, l->f); - } - } - else { - BM_elem_index_set(e, -1); /* set_dirty! */ - } - } -#endif - - /* create and assign looptag structure */ - BMO_ITER (e, &siter, bm, op, "geom", BM_EDGE) { - BMLoop *l; - BMIter liter; - - BMO_elem_flag_enable(bm, e->v1, BEVEL_FLAG | BEVEL_DEL); - BMO_elem_flag_enable(bm, e->v2, BEVEL_FLAG | BEVEL_DEL); - - if (BM_edge_face_count(e) < 2) { - BMO_elem_flag_disable(bm, e, BEVEL_DEL); - BMO_elem_flag_disable(bm, e->v1, BEVEL_DEL); - BMO_elem_flag_disable(bm, e->v2, BEVEL_DEL); - } - - if (!BLI_smallhash_haskey(&hash, (intptr_t)e)) { - BLI_array_grow_one(etags); - BM_elem_index_set(e, BLI_array_count(etags) - 1); /* set_dirty! */ - BLI_smallhash_insert(&hash, (intptr_t)e, NULL); - BMO_elem_flag_enable(bm, e, EDGE_OLD); - } - - /* find all faces surrounding e->v1 and, e->v2 */ - for (i = 0; i < 2; i++) { - BM_ITER_ELEM (l, &liter, i ? e->v2:e->v1, BM_LOOPS_OF_VERT) { - BMLoop *l2; - BMIter liter2; - - /* see if we've already processed this loop's fac */ - if (BLI_smallhash_haskey(&hash, (intptr_t)l->f)) - continue; - - /* create tags for all loops in l-> */ - BM_ITER_ELEM (l2, &liter2, l->f, BM_LOOPS_OF_FACE) { - BLI_array_grow_one(tags); - BM_elem_index_set(l2, BLI_array_count(tags) - 1); /* set_loop */ - - if (!BLI_smallhash_haskey(&hash, (intptr_t)l2->e)) { - BLI_array_grow_one(etags); - BM_elem_index_set(l2->e, BLI_array_count(etags) - 1); /* set_dirty! */ - BLI_smallhash_insert(&hash, (intptr_t)l2->e, NULL); - BMO_elem_flag_enable(bm, l2->e, EDGE_OLD); - } - } - - BLI_smallhash_insert(&hash, (intptr_t)l->f, NULL); - BMO_elem_flag_enable(bm, l->f, BEVEL_FLAG); - BLI_array_append(faces, l->f); - } - } - } - - bm->elem_index_dirty |= BM_EDGE; - - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - BMIter eiter; - - if (!BMO_elem_flag_test(bm, v, BEVEL_FLAG)) - continue; - - BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - if (!BMO_elem_flag_test(bm, e, BEVEL_FLAG) && !ETAG_GET(e, v)) { - BMVert *v2; - float co[3]; - - v2 = BM_edge_other_vert(e, v); - sub_v3_v3v3(co, v2->co, v->co); - if (has_elens) { - float elen = *(float *)CustomData_bmesh_get_n(&bm->edata, e->head.data, CD_PROP_FLT, li); - - normalize_v3(co); - mul_v3_fl(co, elen); - } - - mul_v3_fl(co, fac); - add_v3_v3(co, v->co); - - v2 = BM_vert_create(bm, co, v); - ETAG_SET(e, v, v2); - } - } - } - - for (i = 0; i < BLI_array_count(faces); i++) { - BMLoop *l; - BMIter liter; - - BMO_elem_flag_enable(bm, faces[i], FACE_OLD); - - BM_ITER_ELEM (l, &liter, faces[i], BM_LOOPS_OF_FACE) { - float co[3]; - - if (BMO_elem_flag_test(bm, l->e, BEVEL_FLAG)) { - if (BMO_elem_flag_test(bm, l->prev->e, BEVEL_FLAG)) { - tag = tags + BM_elem_index_get(l); - calc_corner_co(l, fac, co, do_dist, do_even); - tag->newv = BM_vert_create(bm, co, l->v); - } - else { - tag = tags + BM_elem_index_get(l); - tag->newv = ETAG_GET(l->prev->e, l->v); - - if (!tag->newv) { - sub_v3_v3v3(co, l->prev->v->co, l->v->co); - if (has_elens) { - float elen = *(float *)CustomData_bmesh_get_n(&bm->edata, l->prev->e->head.data, - CD_PROP_FLT, li); - - normalize_v3(co); - mul_v3_fl(co, elen); - } - - mul_v3_fl(co, fac); - add_v3_v3(co, l->v->co); - - tag->newv = BM_vert_create(bm, co, l->v); - - ETAG_SET(l->prev->e, l->v, tag->newv); - } - } - } - else if (BMO_elem_flag_test(bm, l->v, BEVEL_FLAG)) { - tag = tags + BM_elem_index_get(l); - tag->newv = ETAG_GET(l->e, l->v); - - if (!tag->newv) { - sub_v3_v3v3(co, l->next->v->co, l->v->co); - if (has_elens) { - float elen = *(float *)CustomData_bmesh_get_n(&bm->edata, l->e->head.data, CD_PROP_FLT, li); - - normalize_v3(co); - mul_v3_fl(co, elen); - } - - mul_v3_fl(co, fac); - add_v3_v3(co, l->v->co); - - tag = tags + BM_elem_index_get(l); - tag->newv = BM_vert_create(bm, co, l->v); - - ETAG_SET(l->e, l->v, tag->newv); - } - } - else { - tag = tags + BM_elem_index_get(l); - tag->newv = l->v; - BMO_elem_flag_disable(bm, l->v, BEVEL_DEL); - } - } - } - - /* create new faces inset from original face */ - for (i = 0; i < BLI_array_count(faces); i++) { - BMLoop *l; - BMIter liter; - BMFace *f; - BMVert *lastv = NULL, *firstv = NULL; - - BMO_elem_flag_enable(bm, faces[i], BEVEL_DEL); - - BLI_array_empty(verts); - BLI_array_empty(edges); - - BM_ITER_ELEM (l, &liter, faces[i], BM_LOOPS_OF_FACE) { - BMVert *v2; - - tag = tags + BM_elem_index_get(l); - BLI_array_append(verts, tag->newv); - - if (!firstv) - firstv = tag->newv; - - if (lastv) { - e = BM_edge_create(bm, lastv, tag->newv, l->e, TRUE); - BM_elem_attrs_copy(bm, bm, l->prev->e, e); - BLI_array_append(edges, e); - } - lastv = tag->newv; - - v2 = ETAG_GET(l->e, l->next->v); - - tag = &tags[BM_elem_index_get(l->next)]; - if (!BMO_elem_flag_test(bm, l->e, BEVEL_FLAG) && v2 && v2 != tag->newv) { - BLI_array_append(verts, v2); - - e = BM_edge_create(bm, lastv, v2, l->e, TRUE); - BM_elem_attrs_copy(bm, bm, l->e, e); - - BLI_array_append(edges, e); - lastv = v2; - } - } - - e = BM_edge_create(bm, firstv, lastv, BM_FACE_FIRST_LOOP(faces[i])->e, TRUE); - if (BM_FACE_FIRST_LOOP(faces[i])->prev->e != e) { - BM_elem_attrs_copy(bm, bm, BM_FACE_FIRST_LOOP(faces[i])->prev->e, e); - } - BLI_array_append(edges, e); - - f = BM_face_create_ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), FALSE); - if (UNLIKELY(f == NULL)) { - printf("%s: could not make face!\n", __func__); - continue; - } - - BMO_elem_flag_enable(bm, f, FACE_NEW); - } - - for (i = 0; i < BLI_array_count(faces); i++) { - BMLoop *l; - BMIter liter; - int j; - - /* create quad spans between split edge */ - BM_ITER_ELEM (l, &liter, faces[i], BM_LOOPS_OF_FACE) { - BMVert *v1 = NULL, *v2 = NULL, *v3 = NULL, *v4 = NULL; - - if (!BMO_elem_flag_test(bm, l->e, BEVEL_FLAG)) - continue; - - v1 = tags[BM_elem_index_get(l)].newv; - v2 = tags[BM_elem_index_get(l->next)].newv; - if (l->radial_next != l) { - v3 = tags[BM_elem_index_get(l->radial_next)].newv; - if (l->radial_next->next->v == l->next->v) { - v4 = v3; - v3 = tags[BM_elem_index_get(l->radial_next->next)].newv; - } - else { - v4 = tags[BM_elem_index_get(l->radial_next->next)].newv; - } - } - else { - /* the loop is on a boundar */ - v3 = l->next->v; - v4 = l->v; - - for (j = 0; j < 2; j++) { - BMIter eiter; - BMVert *v = j ? v4 : v3; - - BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - if (!BM_vert_in_edge(e, v3) || !BM_vert_in_edge(e, v4)) - continue; - - if (!BMO_elem_flag_test(bm, e, BEVEL_FLAG) && BMO_elem_flag_test(bm, e, EDGE_OLD)) { - BMVert *vv; - - vv = ETAG_GET(e, v); - if (!vv || BMO_elem_flag_test(bm, vv, BEVEL_FLAG)) - continue; - - if (j) { - v1 = vv; - } - else { - v2 = vv; - } - break; - } - } - } - - BMO_elem_flag_disable(bm, v3, BEVEL_DEL); - BMO_elem_flag_disable(bm, v4, BEVEL_DEL); - } - - if (v1 != v2 && v2 != v3 && v3 != v4) { - BMIter liter2; - BMLoop *l2, *l3; - BMEdge *e1, *e2; - float d1, d2, *d3; - - f = BM_face_create_quad_tri(bm, v4, v3, v2, v1, l->f, TRUE); - - e1 = BM_edge_exists(v4, v3); - e2 = BM_edge_exists(v2, v1); - BM_elem_attrs_copy(bm, bm, l->e, e1); - BM_elem_attrs_copy(bm, bm, l->e, e2); - - /* set edge lengths of cross edges as the average of the cross edges they're based o */ - if (has_elens) { - /* angle happens not to be used. why? - not sure it just isn't - campbell. - * leave this in in case we need to use it later */ -#if 0 - float ang; -#endif - e1 = BM_edge_exists(v1, v4); - e2 = BM_edge_exists(v2, v3); - - if (l->radial_next->v == l->v) { - l2 = l->radial_next->prev; - l3 = l->radial_next->next; - } - else { - l2 = l->radial_next->next; - l3 = l->radial_next->prev; - } - - d3 = CustomData_bmesh_get_n(&bm->edata, e1->head.data, CD_PROP_FLT, li); - d1 = *(float *)CustomData_bmesh_get_n(&bm->edata, l->prev->e->head.data, CD_PROP_FLT, li); - d2 = *(float *)CustomData_bmesh_get_n(&bm->edata, l2->e->head.data, CD_PROP_FLT, li); -#if 0 - ang = angle_v3v3v3(l->prev->v->co, l->v->co, BM_edge_other_vert(l2->e, l->v)->co); -#endif - *d3 = (d1 + d2) * 0.5f; - - d3 = CustomData_bmesh_get_n(&bm->edata, e2->head.data, CD_PROP_FLT, li); - d1 = *(float *)CustomData_bmesh_get_n(&bm->edata, l->next->e->head.data, CD_PROP_FLT, li); - d2 = *(float *)CustomData_bmesh_get_n(&bm->edata, l3->e->head.data, CD_PROP_FLT, li); -#if 0 - ang = angle_v3v3v3(BM_edge_other_vert(l->next->e, l->next->v)->co, l->next->v->co, - BM_edge_other_vert(l3->e, l->next->v)->co); -#endif - *d3 = (d1 + d2) * 0.5f; - } - - if (UNLIKELY(f == NULL)) { - fprintf(stderr, "%s: face index out of range! (bmesh internal error)\n", __func__); - continue; - } - - BMO_elem_flag_enable(bm, f, FACE_NEW | FACE_SPAN); - - /* un-tag edges in f for deletio */ - BM_ITER_ELEM (l2, &liter2, f, BM_LOOPS_OF_FACE) { - BMO_elem_flag_disable(bm, l2->e, BEVEL_DEL); - } - } - else { - f = NULL; - } - } - } - - /* fill in holes at vertices */ - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - BMIter eiter; - BMVert *vv, *vstart = NULL, *lastv = NULL; - SmallHash tmphash; - int rad, insorig = 0, err = 0; - - BLI_smallhash_init(&tmphash); - - if (!BMO_elem_flag_test(bm, v, BEVEL_FLAG)) - continue; - - BLI_array_empty(verts); - BLI_array_empty(edges); - - BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - BMIter liter; - BMVert *v1 = NULL, *v2 = NULL; - BMLoop *l; - - if (BM_edge_face_count(e) < 2) - insorig = 1; - - if (BM_elem_index_get(e) == -1) - continue; - - rad = 0; - BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) { - if (!BMO_elem_flag_test(bm, l->f, FACE_OLD)) - continue; - - rad++; - - tag = tags + BM_elem_index_get((l->v == v) ? l : l->next); - - if (!v1) - v1 = tag->newv; - else if (!v2) - v2 = tag->newv; - } - - if (rad < 2) - insorig = 1; - - if (!v1) - v1 = ETAG_GET(e, v); - if (!v2 || v1 == v2) - v2 = ETAG_GET(e, v); - - if (v1) { - if (!BLI_smallhash_haskey(&tmphash, (intptr_t)v1)) { - BLI_array_append(verts, v1); - BLI_smallhash_insert(&tmphash, (intptr_t)v1, NULL); - } - - if (v2 && v1 != v2 && !BLI_smallhash_haskey(&tmphash, (intptr_t)v2)) { - BLI_array_append(verts, v2); - BLI_smallhash_insert(&tmphash, (intptr_t)v2, NULL); - } - } - } - - if (!BLI_array_count(verts)) - continue; - - if (insorig) { - BLI_array_append(verts, v); - BLI_smallhash_insert(&tmphash, (intptr_t)v, NULL); - } - - /* find edges that exist between vertices in verts. this is basically - * a topological walk of the edges connecting them */ - vstart = vstart ? vstart : verts[0]; - vv = vstart; - do { - BM_ITER_ELEM (e, &eiter, vv, BM_EDGES_OF_VERT) { - BMVert *vv2 = BM_edge_other_vert(e, vv); - - if (vv2 != lastv && BLI_smallhash_haskey(&tmphash, (intptr_t)vv2)) { - /* if we've go over the same vert twice, break out of outer loop */ - if (BLI_smallhash_lookup(&tmphash, (intptr_t)vv2) != NULL) { - e = NULL; - err = 1; - break; - } - - /* use self pointer as ta */ - BLI_smallhash_remove(&tmphash, (intptr_t)vv2); - BLI_smallhash_insert(&tmphash, (intptr_t)vv2, vv2); - - lastv = vv; - BLI_array_append(edges, e); - vv = vv2; - break; - } - } - - if (e == NULL) { - break; - } - } while (vv != vstart); - - if (err) { - continue; - } - - /* there may not be a complete loop of edges, so start again and make - * final edge afterwards. in this case, the previous loop worked to - * find one of the two edges at the extremes. */ - if (vv != vstart) { - /* undo previous taggin */ - for (i = 0; i < BLI_array_count(verts); i++) { - BLI_smallhash_remove(&tmphash, (intptr_t)verts[i]); - BLI_smallhash_insert(&tmphash, (intptr_t)verts[i], NULL); - } - - vstart = vv; - lastv = NULL; - BLI_array_empty(edges); - do { - BM_ITER_ELEM (e, &eiter, vv, BM_EDGES_OF_VERT) { - BMVert *vv2 = BM_edge_other_vert(e, vv); - - if (vv2 != lastv && BLI_smallhash_haskey(&tmphash, (intptr_t)vv2)) { - /* if we've go over the same vert twice, break out of outer loo */ - if (BLI_smallhash_lookup(&tmphash, (intptr_t)vv2) != NULL) { - e = NULL; - err = 1; - break; - } - - /* use self pointer as ta */ - BLI_smallhash_remove(&tmphash, (intptr_t)vv2); - BLI_smallhash_insert(&tmphash, (intptr_t)vv2, vv2); - - lastv = vv; - BLI_array_append(edges, e); - vv = vv2; - break; - } - } - if (e == NULL) - break; - } while (vv != vstart); - - if (!err) { - e = BM_edge_create(bm, vv, vstart, NULL, TRUE); - BLI_array_append(edges, e); - } - } - - if (err) - continue; - - if (BLI_array_count(edges) >= 3) { - BMFace *f; - - if (BM_face_exists(bm, verts, BLI_array_count(verts), &f)) - continue; - - f = BM_face_create_ngon(bm, lastv, vstart, edges, BLI_array_count(edges), FALSE); - if (UNLIKELY(f == NULL)) { - fprintf(stderr, "%s: in bevel vert fill! (bmesh internal error)\n", __func__); - } - else { - BMO_elem_flag_enable(bm, f, FACE_NEW | FACE_HOLE); - } - } - BLI_smallhash_release(&tmphash); - } - - /* copy over customdat */ - for (i = 0; i < BLI_array_count(faces); i++) { - BMLoop *l; - BMIter liter; - BMFace *f = faces[i]; - - BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - BMLoop *l2; - BMIter liter2; - - tag = tags + BM_elem_index_get(l); - if (!tag->newv) - continue; - - BM_ITER_ELEM (l2, &liter2, tag->newv, BM_LOOPS_OF_VERT) { - if (!BMO_elem_flag_test(bm, l2->f, FACE_NEW) || (l2->v != tag->newv && l2->v != l->v)) - continue; - - if (tag->newv != l->v || HasMDisps) { - BM_elem_attrs_copy(bm, bm, l->f, l2->f); - BM_loop_interp_from_face(bm, l2, l->f, TRUE, TRUE); - } - else { - BM_elem_attrs_copy(bm, bm, l->f, l2->f); - BM_elem_attrs_copy(bm, bm, l, l2); - } - - if (HasMDisps) { - BMLoop *l3; - BMIter liter3; - - BM_ITER_ELEM (l3, &liter3, l2->f, BM_LOOPS_OF_FACE) { - BM_loop_interp_multires(bm, l3, l->f); - } - } - } - } - } - - /* handle vertices along boundary edge */ - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - if (BMO_elem_flag_test(bm, v, VERT_OLD) && - BMO_elem_flag_test(bm, v, BEVEL_FLAG) && - !BMO_elem_flag_test(bm, v, BEVEL_DEL)) - { - BMLoop *l; - BMLoop *lorig = NULL; - BMIter liter; - - BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - // BMIter liter2; - // BMLoop *l2 = l->v == v ? l : l->next, *l3; - - if (BMO_elem_flag_test(bm, l->f, FACE_OLD)) { - lorig = l; - break; - } - } - - if (!lorig) - continue; - - BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - BMLoop *l2 = l->v == v ? l : l->next; - - BM_elem_attrs_copy(bm, bm, lorig->f, l2->f); - BM_elem_attrs_copy(bm, bm, lorig, l2); - } - } - } -#if 0 - /* clean up any remaining 2-edged face */ - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (f->len == 2) { - BMFace *faces[2] = {f, BM_FACE_FIRST_LOOP(f)->radial_next->f}; - - if (faces[0] == faces[1]) - BM_face_kill(bm, f); - else - BM_faces_join(bm, faces, 2); - } - } -#endif - - BMO_op_callf(bm, op->flag, "delete geom=%fv context=%i", BEVEL_DEL, DEL_VERTS); - - /* clean up any edges that might not get properly delete */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BMO_elem_flag_test(bm, e, EDGE_OLD) && !e->l) - BMO_elem_flag_enable(bm, e, BEVEL_DEL); - } - - BMO_op_callf(bm, op->flag, "delete geom=%fe context=%i", BEVEL_DEL, DEL_EDGES); - BMO_op_callf(bm, op->flag, "delete geom=%ff context=%i", BEVEL_DEL, DEL_FACES); - - BLI_smallhash_release(&hash); - BLI_array_free(tags); - BLI_array_free(etags); - BLI_array_free(verts); - BLI_array_free(edges); - BLI_array_free(faces); - - BMO_slot_buffer_from_enabled_flag(bm, op, "face_spans", BM_FACE, FACE_SPAN); - BMO_slot_buffer_from_enabled_flag(bm, op, "face_holes", BM_FACE, FACE_HOLE); } diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c index ebd848ff8b2..c7cd1e742d8 100644 --- a/source/blender/bmesh/operators/bmo_connect.c +++ b/source/blender/bmesh/operators/bmo_connect.c @@ -52,8 +52,10 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op) BLI_array_declare(verts_pair); int i; - BMO_slot_buffer_flag_enable(bm, op, "verts", BM_VERT, VERT_INPUT); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_INPUT); + /* BMESH_TODO, loop over vert faces: + * faster then looping over all faces, then searching each for flagged verts*/ for (f = BM_iter_new(&iter, bm, BM_FACES_OF_MESH, NULL); f; f = BM_iter_step(&iter)) { BLI_array_empty(loops_split); BLI_array_empty(verts_pair); @@ -117,7 +119,7 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EDGE_OUT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT); BLI_array_free(loops_split); BLI_array_free(verts_pair); @@ -219,12 +221,12 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) int c = 0, cl1 = 0, cl2 = 0; /* merge-bridge support */ - const int use_merge = BMO_slot_bool_get(op, "use_merge"); - const float merge_factor = BMO_slot_float_get(op, "merge_factor"); + const int use_merge = BMO_slot_bool_get(op->slots_in, "use_merge"); + const float merge_factor = BMO_slot_float_get(op->slots_in, "merge_factor"); - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK); - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (!BMO_elem_flag_test(bm, e, EDGE_DONE)) { BMVert *v, *ov; /* BMEdge *e2, *e3, *oe = e; */ /* UNUSED */ @@ -380,18 +382,19 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) /* compute summed length between vertices in forward direction */ len = 0.0f; - for (j = 0; j < lenv2; j++) { + for (j = 0; (j < lenv2) && (len < min); j++) { len += len_v3v3(vv1[clamp_index(i + j, lenv1)]->co, vv2[j]->co); } if (len < min) { min = len; starti = i; + dir1 = 1; } /* compute summed length between vertices in backward direction */ len = 0.0f; - for (j = 0; j < lenv2; j++) { + for (j = 0; (j < lenv2) && (len < min); j++) { len += len_v3v3(vv1[clamp_index(i - j, lenv1)]->co, vv2[j]->co); } @@ -523,7 +526,7 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_OUT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT); cleanup: BLI_array_free(ee1); diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c index bd1c0f809bd..aa69806fb37 100644 --- a/source/blender/bmesh/operators/bmo_create.c +++ b/source/blender/bmesh/operators/bmo_create.c @@ -168,7 +168,7 @@ static void rotsys_reverse(BMEdge *UNUSED(e), BMVert *v, EdgeData *edata, VertDa BMEdge **edges = NULL; BMEdge *e_first; BMEdge *e; - BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE); int i, totedge; e = e_first = vdata[BM_elem_index_get(v)].e; @@ -274,7 +274,7 @@ static int UNUSED_FUNCTION(rotsys_fill_faces)(BMesh *bm, EdgeData *edata, VertDa if (!ok || BLI_array_count(edges) < 3) continue; - f = BM_face_create_ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), TRUE); + f = BM_face_create_ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), BM_CREATE_NO_DOUBLE); if (UNLIKELY(f == NULL)) { continue; } @@ -359,10 +359,10 @@ static void init_rotsys(BMesh *bm, EdgeData *edata, VertData *vdata) BMIter iter; BMEdge *e; BMEdge **edges = NULL; - BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE); BMVert *v; /* BMVert **verts = NULL; */ - /* BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE); */ /* UNUSE */ + /* BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); */ /* UNUSE */ int i; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { @@ -611,11 +611,11 @@ static void init_rotsys(BMesh *bm, EdgeData *edata, VertData *vdata) v2 = BM_vert_create(bm, co, NULL); BM_elem_index_set(v2, -1); /* set_dirty! */ - //BM_edge_create(bm, cv, v2, NULL, FALSE); + //BM_edge_create(bm, cv, v2, NULL, 0); BM_vert_select_set(bm, v2, TRUE); if (lastv) { - e2 = BM_edge_create(bm, lastv, v2, NULL, FALSE); + e2 = BM_edge_create(bm, lastv, v2, NULL, 0); BM_edge_select_set(bm, e2, TRUE); } @@ -741,7 +741,10 @@ static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, E BMVert *startv; BMVert *endv; EPathNode *node; - int i, use_restrict = BMO_slot_bool_get(op, "use_restrict"); + int i; + const int use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict"); + BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict"); + startv = edata[BM_elem_index_get(edge)].ftag ? edge->v2 : edge->v1; endv = edata[BM_elem_index_get(edge)].ftag ? edge->v1 : edge->v2; @@ -769,7 +772,7 @@ static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, E verts[i] = node->v; } - if (BM_face_exists(bm, verts, i, &f)) { + if (BM_face_exists(verts, i, &f)) { if (!BMO_elem_flag_test(bm, f, FACE_IGNORE)) { BLI_ghash_remove(gh, endv, NULL, NULL); continue; @@ -806,12 +809,13 @@ static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, E continue; } - if (use_restrict && BMO_slot_map_contains(bm, op, "restrict", e)) { - int group = BMO_slot_map_int_get(bm, op, "restrict", e); - - if (!(group & path->group)) { - v2 = NULL; - continue; + if (use_restrict) { + int *group = (int *)BMO_slot_map_data_get(slot_restrict, e); + if (group) { + if (!(*group & path->group)) { + v2 = NULL; + continue; + } } } @@ -895,12 +899,14 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) BMEdge **edges = NULL; PathBase *pathbase; BLI_array_declare(edges); - int use_restrict = BMO_slot_bool_get(op, "use_restrict"); - int use_fill_check = BMO_slot_bool_get(op, "use_fill_check"); - const short mat_nr = BMO_slot_int_get(op, "mat_nr"); - const short use_smooth = BMO_slot_bool_get(op, "use_smooth"); + int use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict"); + int use_fill_check = BMO_slot_bool_get(op->slots_in, "use_fill_check"); + const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr"); + const short use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth"); int i, j, group = 0; unsigned int winding[2]; /* accumulte winding directions for each edge which has a face */ + BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict"); + BMOpSlot *slot_face_groupmap_out = BMO_slot_get(op->slots_out, "face_groupmap.out"); if (!bm->totvert || !bm->totedge) return; @@ -910,8 +916,8 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) edata = MEM_callocN(sizeof(EdgeData) * bm->totedge, "EdgeData"); vdata = MEM_callocN(sizeof(VertData) * bm->totvert, "VertData"); - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK); - BMO_slot_buffer_flag_enable(bm, op, "excludefaces", BM_FACE, FACE_IGNORE); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "exclude_faces", BM_FACE, FACE_IGNORE); BM_mesh_elem_index_ensure(bm, BM_VERT); @@ -932,14 +938,14 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) bm->elem_index_dirty &= ~BM_EDGE; init_rotsys(bm, edata, vdata); - + while (1) { edge = NULL; group = 0; - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { /* if restrict is on, only start on faces in the restrict map */ - if (use_restrict && !BMO_slot_map_contains(bm, op, "restrict", e)) + if (use_restrict && !BMO_slot_map_contains(slot_restrict, e)) continue; if (edata[BM_elem_index_get(e)].tag < 2) { @@ -948,7 +954,7 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) if (use_restrict) { int i = 0, j = 0, gi = 0; - group = BMO_slot_map_int_get(bm, op, "restrict", e); + group = BMO_slot_map_int_get(slot_restrict, e); for (i = 0; i < 30; i++) { if (group & (1 << i)) { @@ -1045,7 +1051,7 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) /* fairly expensive check - see if there are already faces filling this area */ (BM_face_exists_multi_edge(edges, i) == FALSE)) { - f = BM_face_create_ngon(bm, v1, v2, edges, i, TRUE); + f = BM_face_create_ngon(bm, v1, v2, edges, i, BM_CREATE_NO_DOUBLE); if (f && !BMO_elem_flag_test(bm, f, ELE_ORIG)) { BMO_elem_flag_enable(bm, f, FACE_NEW); f->mat_nr = mat_nr; @@ -1055,7 +1061,7 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) } if (use_restrict) { - BMO_slot_map_int_insert(bm, op, "faceout_groupmap", f, path->group); + BMO_slot_map_int_insert(op, slot_face_groupmap_out, f, path->group); } } } @@ -1063,7 +1069,7 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) edge_free_path(pathbase, path); } - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_NEW); BLI_array_free(edges); BLI_array_free(verts); @@ -1092,7 +1098,7 @@ static BMEdge *edge_next(BMesh *bm, BMEdge *e) return NULL; } -void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) +void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op) { BMOIter siter; BMEdge *e; @@ -1103,11 +1109,11 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) int ok = 1; int i, count; - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK); /* validate that each edge has at most one other tagged edge in the * disk cycle around each of it's vertices */ - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { for (i = 0; i < 2; i++) { count = BMO_vert_edge_flags_count(bm, i ? e->v2 : e->v1, EDGE_MARK); if (count > 2) { @@ -1129,7 +1135,7 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) /* find connected loops within the input edge */ count = 0; while (1) { - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (!BMO_elem_flag_test(bm, e, EDGE_VIS)) { if (BMO_vert_edge_flags_count(bm, e->v1, EDGE_MARK) == 1 || BMO_vert_edge_flags_count(bm, e->v2, EDGE_MARK) == 1) @@ -1177,10 +1183,10 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) } if (edges1 && BLI_array_count(edges1) > 2 && - BM_edge_share_vert_count(edges1[0], edges1[BLI_array_count(edges1) - 1])) + BM_edge_share_vert_check(edges1[0], edges1[BLI_array_count(edges1) - 1])) { if (edges2 && BLI_array_count(edges2) > 2 && - BM_edge_share_vert_count(edges2[0], edges2[BLI_array_count(edges2) - 1])) + BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1])) { BLI_array_free(edges1); BLI_array_free(edges2); @@ -1193,7 +1199,7 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) } if (edges2 && BLI_array_count(edges2) > 2 && - BM_edge_share_vert_count(edges2[0], edges2[BLI_array_count(edges2) - 1])) + BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1])) { edges2 = NULL; } @@ -1243,9 +1249,9 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) SWAP(BMVert *, v3, v4); } - e = BM_edge_create(bm, v1, v3, NULL, TRUE); + e = BM_edge_create(bm, v1, v3, NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, e, ELE_NEW); - e = BM_edge_create(bm, v2, v4, NULL, TRUE); + e = BM_edge_create(bm, v2, v4, NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, e, ELE_NEW); } else if (edges1) { @@ -1255,12 +1261,12 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1; i = BLI_array_count(edges1) - 1; v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1; - e = BM_edge_create(bm, v1, v2, NULL, TRUE); + e = BM_edge_create(bm, v1, v2, NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, e, ELE_NEW); } } - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, ELE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_NEW); BLI_array_free(edges1); BLI_array_free(edges2); @@ -1280,11 +1286,11 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) BMEdge *e; BMFace *f; int totv = 0, tote = 0, totf = 0, amount; - const short mat_nr = BMO_slot_int_get(op, "mat_nr"); - const short use_smooth = BMO_slot_bool_get(op, "use_smooth"); + const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr"); + const short use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth"); /* count number of each element type we were passe */ - BMO_ITER (h, &oiter, bm, op, "geom", BM_VERT | BM_EDGE | BM_FACE) { + BMO_ITER (h, &oiter, op->slots_in, "geom", BM_VERT | BM_EDGE | BM_FACE) { switch (h->htype) { case BM_VERT: totv++; break; case BM_EDGE: tote++; break; @@ -1318,7 +1324,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) int ok = TRUE; - BMO_ITER (v, &oiter, bm, op, "geom", BM_VERT) { + BMO_ITER (v, &oiter, op->slots_in, "geom", BM_VERT) { /* count how many flagged edges this vertex uses */ int tot_edges = 0; BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { @@ -1353,10 +1359,10 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) } if (ok == TRUE && v_free && v_a && v_b) { - e = BM_edge_create(bm, v_free, v_a, NULL, TRUE); + e = BM_edge_create(bm, v_free, v_a, NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, e, ELE_NEW); - e = BM_edge_create(bm, v_free, v_b, NULL, TRUE); + e = BM_edge_create(bm, v_free, v_b, NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, e, ELE_NEW); } } @@ -1366,7 +1372,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) /* call edgenet prepare op so additional face creation cases wore */ BMO_op_initf(bm, &op2, op->flag, "edgenet_prepare edges=%fe", ELE_NEW); BMO_op_exec(bm, &op2); - BMO_slot_buffer_flag_enable(bm, &op2, "edgeout", BM_EDGE, ELE_NEW); + BMO_slot_buffer_flag_enable(bm, op2.slots_out, "edges.out", BM_EDGE, ELE_NEW); BMO_op_finish(bm, &op2); BMO_op_initf(bm, &op2, op->flag, @@ -1376,8 +1382,9 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) BMO_op_exec(bm, &op2); /* return if edge net create did something */ - if (BMO_slot_buffer_count(bm, &op2, "faceout")) { - BMO_slot_copy(&op2, op, "faceout", "faceout"); + if (BMO_slot_buffer_count(op2.slots_out, "faces.out")) { + BMO_slot_copy(&op2, slots_out, "faces.out", + op, slots_out, "faces.out"); BMO_op_finish(bm, &op2); return; } @@ -1389,8 +1396,9 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) BMO_op_exec(bm, &op2); /* if we dissolved anything, then return */ - if (BMO_slot_buffer_count(bm, &op2, "regionout")) { - BMO_slot_copy(&op2, op, "regionout", "faceout"); + if (BMO_slot_buffer_count(op2.slots_out, "region.out")) { + BMO_slot_copy(&op2, slots_out, "region.out", + op, slots_out, "faces.out"); BMO_op_finish(bm, &op2); return; } @@ -1412,9 +1420,9 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) if (amount == 2) { /* create edge */ - e = BM_edge_create(bm, verts[0], verts[1], NULL, TRUE); + e = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, e, ELE_OUT); - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, ELE_OUT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT); } else if (0) { /* nice feature but perhaps it should be a different tool? */ @@ -1453,14 +1461,14 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) if (ese->htype == BM_VERT) { v = (BMVert *)ese->ele; if (v_prev) { - e = BM_edge_create(bm, v, v_prev, NULL, TRUE); + e = BM_edge_create(bm, v, v_prev, NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, e, ELE_OUT); } v_prev = v; } } } - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, ELE_OUT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT); /* done creating edges */ } else if (amount > 2) { @@ -1470,12 +1478,12 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) BMVert **vert_arr = MEM_mallocN(sizeof(BMVert **) * totv, __func__); int i = 0; - BMO_ITER (v, &oiter, bm, op, "geom", BM_VERT) { + BMO_ITER (v, &oiter, op->slots_in, "geom", BM_VERT) { vert_arr[i] = v; i++; } - f = BM_face_create_ngon_vcloud(bm, vert_arr, totv, TRUE); + f = BM_face_create_ngon_vcloud(bm, vert_arr, totv, BM_CREATE_NO_DOUBLE); if (f) { BMO_elem_flag_enable(bm, f, ELE_OUT); diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index 9addb1b1657..7c3bcd60daa 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -85,7 +85,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) BMWalker regwalker; int i; - int use_verts = BMO_slot_bool_get(op, "use_verts"); + int use_verts = BMO_slot_bool_get(op->slots_in, "use_verts"); if (use_verts) { /* tag verts that start out with only 2 edges, @@ -98,10 +98,10 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_flag_enable(bm, op, "faces", BM_FACE, FACE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces", BM_FACE, FACE_MARK); /* collect region */ - BMO_ITER (f, &oiter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) { if (!BMO_elem_flag_test(bm, f, FACE_MARK)) { continue; @@ -184,7 +184,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) goto cleanup; } - BMO_slot_buffer_from_enabled_flag(bm, op, "regionout", BM_FACE, FACE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "region.out", BM_FACE, FACE_NEW); cleanup: /* free/cleanup */ @@ -208,7 +208,7 @@ void bmo_dissolve_edgeloop_exec(BMesh *bm, BMOperator *op) int i; - BMO_ITER (e, &oiter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &oiter, op->slots_in, "edges", BM_EDGE) { if (BM_edge_face_pair(e, &fa, &fb)) { BMO_elem_flag_enable(bm, e->v1, VERT_MARK); BMO_elem_flag_enable(bm, e->v2, VERT_MARK); @@ -237,7 +237,7 @@ void bmo_dissolve_edgeloop_exec(BMesh *bm, BMOperator *op) //BMO_op_initf(bm, &fop, "dissolve_faces faces=%ff", FACE_MARK); //BMO_op_exec(bm, &fop); - //BMO_slot_copy(op, &fop, "regionout", "regionout"); + //BMO_slot_copy(op, &fop, "region.out", "region.out"); //BMO_op_finish(bm, &fop); } @@ -254,7 +254,7 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) BMIter viter; BMVert *v; - int use_verts = BMO_slot_bool_get(op, "use_verts"); + int use_verts = BMO_slot_bool_get(op->slots_in, "use_verts"); if (use_verts) { BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { @@ -262,7 +262,7 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) } } - BMO_ITER (e, &eiter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &eiter, op->slots_in, "edges", BM_EDGE) { BMFace *fa, *fb; if (BM_edge_face_pair(e, &fa, &fb)) { @@ -338,7 +338,7 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op) BMFace *f; /* int i; */ - BMO_slot_buffer_flag_enable(bm, op, "verts", BM_VERT, VERT_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_MARK); for (v = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); v; v = BM_iter_step(&iter)) { if (BMO_elem_flag_test(bm, v, VERT_MARK)) { @@ -479,13 +479,13 @@ void dummy_exec(BMesh *bm, BMOperator *op) /* Limited Dissolve */ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op) { - BMOpSlot *einput = BMO_slot_get(op, "edges"); - BMOpSlot *vinput = BMO_slot_get(op, "verts"); + BMOpSlot *einput = BMO_slot_get(op->slots_in, "edges"); + BMOpSlot *vinput = BMO_slot_get(op->slots_in, "verts"); const float angle_max = (float)M_PI / 2.0f; - const float angle_limit = min_ff(angle_max, BMO_slot_float_get(op, "angle_limit")); - const int do_dissolve_boundaries = BMO_slot_bool_get(op, "use_dissolve_boundaries"); + const float angle_limit = min_ff(angle_max, BMO_slot_float_get(op->slots_in, "angle_limit")); + const int do_dissolve_boundaries = BMO_slot_bool_get(op->slots_in, "use_dissolve_boundaries"); BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries, - vinput->data.p, vinput->len, - einput->data.p, einput->len); + (BMVert **)BMO_SLOT_AS_BUFFER(vinput), vinput->len, + (BMEdge **)BMO_SLOT_AS_BUFFER(einput), einput->len); } diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c index 32270007a0b..9a58d7acfb9 100644 --- a/source/blender/bmesh/operators/bmo_dupe.c +++ b/source/blender/bmesh/operators/bmo_dupe.c @@ -49,7 +49,7 @@ static BMVert *copy_vertex(BMesh *source_mesh, BMVert *source_vertex, BMesh *tar BMVert *target_vertex = NULL; /* Create a new vertex */ - target_vertex = BM_vert_create(target_mesh, source_vertex->co, NULL); + target_vertex = BM_vert_create(target_mesh, source_vertex->co, NULL, BM_CREATE_SKIP_CD); /* Insert new vertex into the vert hash */ BLI_ghash_insert(vhash, source_vertex, target_vertex); @@ -68,7 +68,9 @@ static BMVert *copy_vertex(BMesh *source_mesh, BMVert *source_vertex, BMesh *tar * * Copy an existing edge from one bmesh to another. */ -static BMEdge *copy_edge(BMOperator *op, BMesh *source_mesh, +static BMEdge *copy_edge(BMOperator *op, + BMOpSlot *slot_boundarymap_out, + BMesh *source_mesh, BMEdge *source_edge, BMesh *target_mesh, GHash *vhash, GHash *ehash) { @@ -96,14 +98,13 @@ static BMEdge *copy_edge(BMOperator *op, BMesh *source_mesh, target_vert2 = BLI_ghash_lookup(vhash, source_edge->v2); /* Create a new edge */ - target_edge = BM_edge_create(target_mesh, target_vert1, target_vert2, NULL, FALSE); + target_edge = BM_edge_create(target_mesh, target_vert1, target_vert2, NULL, BM_CREATE_SKIP_CD); /* add to new/old edge map if necassary */ if (rlen < 2) { /* not sure what non-manifold cases of greater then three * radial should do. */ - BMO_slot_map_ptr_insert(source_mesh, op, "boundarymap", - source_edge, target_edge); + BMO_slot_map_elem_insert(op, slot_boundarymap_out, source_edge, target_edge); } /* Insert new edge into the edge hash */ @@ -124,7 +125,9 @@ static BMEdge *copy_edge(BMOperator *op, BMesh *source_mesh, * Copy an existing face from one bmesh to another. */ -static BMFace *copy_face(BMOperator *op, BMesh *source_mesh, +static BMFace *copy_face(BMOperator *op, + BMOpSlot *slot_facemap_out, + BMesh *source_mesh, BMFace *source_face, BMesh *target_mesh, BMVert **vtar, BMEdge **edar, GHash *vhash, GHash *ehash) { @@ -151,11 +154,11 @@ static BMFace *copy_face(BMOperator *op, BMesh *source_mesh, vtar[i] = BLI_ghash_lookup(vhash, source_loop->v); edar[i] = BLI_ghash_lookup(ehash, source_loop->e); } - + /* create new face */ - target_face = BM_face_create(target_mesh, vtar, edar, source_face->len, FALSE); - BMO_slot_map_ptr_insert(source_mesh, op, "facemap", source_face, target_face); - BMO_slot_map_ptr_insert(source_mesh, op, "facemap", target_face, source_face); + target_face = BM_face_create(target_mesh, vtar, edar, source_face->len, BM_CREATE_SKIP_CD); + BMO_slot_map_elem_insert(op, slot_facemap_out, source_face, target_face); + BMO_slot_map_elem_insert(op, slot_facemap_out, target_face, source_face); BM_elem_attrs_copy(source_mesh, target_mesh, source_face, target_face); @@ -181,7 +184,7 @@ static BMFace *copy_face(BMOperator *op, BMesh *source_mesh, * Internal Copy function. */ -static void BKE_mesh_copy(BMOperator *op, BMesh *source, BMesh *target) +static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst) { BMVert *v = NULL, *v2; @@ -196,22 +199,26 @@ static void BKE_mesh_copy(BMOperator *op, BMesh *source, BMesh *target) BMIter viter, eiter, fiter; GHash *vhash, *ehash; + BMOpSlot *slot_boundary_map_out = BMO_slot_get(op->slots_out, "boundary_map.out"); + BMOpSlot *slot_face_map_out = BMO_slot_get(op->slots_out, "face_map.out"); + BMOpSlot *slot_isovert_map_out = BMO_slot_get(op->slots_out, "isovert_map.out"); + /* initialize pointer hashes */ vhash = BLI_ghash_ptr_new("bmesh dupeops v"); ehash = BLI_ghash_ptr_new("bmesh dupeops e"); /* duplicate flagged vertices */ - BM_ITER_MESH (v, &viter, source, BM_VERTS_OF_MESH) { - if (BMO_elem_flag_test(source, v, DUPE_INPUT) && - !BMO_elem_flag_test(source, v, DUPE_DONE)) + BM_ITER_MESH (v, &viter, bm_src, BM_VERTS_OF_MESH) { + if (BMO_elem_flag_test(bm_src, v, DUPE_INPUT) && + !BMO_elem_flag_test(bm_src, v, DUPE_DONE)) { BMIter iter; int isolated = 1; - v2 = copy_vertex(source, v, target, vhash); + v2 = copy_vertex(bm_src, v, bm_dst, vhash); BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) { - if (BMO_elem_flag_test(source, f, DUPE_INPUT)) { + if (BMO_elem_flag_test(bm_src, f, DUPE_INPUT)) { isolated = 0; break; } @@ -219,7 +226,7 @@ static void BKE_mesh_copy(BMOperator *op, BMesh *source, BMesh *target) if (isolated) { BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { - if (BMO_elem_flag_test(source, e, DUPE_INPUT)) { + if (BMO_elem_flag_test(bm_src, e, DUPE_INPUT)) { isolated = 0; break; } @@ -227,49 +234,49 @@ static void BKE_mesh_copy(BMOperator *op, BMesh *source, BMesh *target) } if (isolated) { - BMO_slot_map_ptr_insert(source, op, "isovertmap", v, v2); + BMO_slot_map_elem_insert(op, slot_isovert_map_out, v, v2); } - BMO_elem_flag_enable(source, v, DUPE_DONE); + BMO_elem_flag_enable(bm_src, v, DUPE_DONE); } } /* now we dupe all the edges */ - BM_ITER_MESH (e, &eiter, source, BM_EDGES_OF_MESH) { - if (BMO_elem_flag_test(source, e, DUPE_INPUT) && - !BMO_elem_flag_test(source, e, DUPE_DONE)) + BM_ITER_MESH (e, &eiter, bm_src, BM_EDGES_OF_MESH) { + if (BMO_elem_flag_test(bm_src, e, DUPE_INPUT) && + !BMO_elem_flag_test(bm_src, e, DUPE_DONE)) { /* make sure that verts are copied */ - if (!BMO_elem_flag_test(source, e->v1, DUPE_DONE)) { - copy_vertex(source, e->v1, target, vhash); - BMO_elem_flag_enable(source, e->v1, DUPE_DONE); + if (!BMO_elem_flag_test(bm_src, e->v1, DUPE_DONE)) { + copy_vertex(bm_src, e->v1, bm_dst, vhash); + BMO_elem_flag_enable(bm_src, e->v1, DUPE_DONE); } - if (!BMO_elem_flag_test(source, e->v2, DUPE_DONE)) { - copy_vertex(source, e->v2, target, vhash); - BMO_elem_flag_enable(source, e->v2, DUPE_DONE); + if (!BMO_elem_flag_test(bm_src, e->v2, DUPE_DONE)) { + copy_vertex(bm_src, e->v2, bm_dst, vhash); + BMO_elem_flag_enable(bm_src, e->v2, DUPE_DONE); } /* now copy the actual edge */ - copy_edge(op, source, e, target, vhash, ehash); - BMO_elem_flag_enable(source, e, DUPE_DONE); + copy_edge(op, slot_boundary_map_out, bm_src, e, bm_dst, vhash, ehash); + BMO_elem_flag_enable(bm_src, e, DUPE_DONE); } } /* first we dupe all flagged faces and their elements from source */ - BM_ITER_MESH (f, &fiter, source, BM_FACES_OF_MESH) { - if (BMO_elem_flag_test(source, f, DUPE_INPUT)) { + BM_ITER_MESH (f, &fiter, bm_src, BM_FACES_OF_MESH) { + if (BMO_elem_flag_test(bm_src, f, DUPE_INPUT)) { /* vertex pass */ BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) { - if (!BMO_elem_flag_test(source, v, DUPE_DONE)) { - copy_vertex(source, v, target, vhash); - BMO_elem_flag_enable(source, v, DUPE_DONE); + if (!BMO_elem_flag_test(bm_src, v, DUPE_DONE)) { + copy_vertex(bm_src, v, bm_dst, vhash); + BMO_elem_flag_enable(bm_src, v, DUPE_DONE); } } /* edge pass */ BM_ITER_ELEM (e, &eiter, f, BM_EDGES_OF_FACE) { - if (!BMO_elem_flag_test(source, e, DUPE_DONE)) { - copy_edge(op, source, e, target, vhash, ehash); - BMO_elem_flag_enable(source, e, DUPE_DONE); + if (!BMO_elem_flag_test(bm_src, e, DUPE_DONE)) { + copy_edge(op, slot_boundary_map_out, bm_src, e, bm_dst, vhash, ehash); + BMO_elem_flag_enable(bm_src, e, DUPE_DONE); } } @@ -280,8 +287,8 @@ static void BKE_mesh_copy(BMOperator *op, BMesh *source, BMesh *target) BLI_array_grow_items(vtar, f->len); BLI_array_grow_items(edar, f->len); - copy_face(op, source, f, target, vtar, edar, vhash, ehash); - BMO_elem_flag_enable(source, f, DUPE_DONE); + copy_face(op, slot_face_map_out, bm_src, f, bm_dst, vtar, edar, vhash, ehash); + BMO_elem_flag_enable(bm_src, f, DUPE_DONE); } } @@ -317,23 +324,24 @@ static void BKE_mesh_copy(BMOperator *op, BMesh *source, BMesh *target) void bmo_duplicate_exec(BMesh *bm, BMOperator *op) { BMOperator *dupeop = op; - BMesh *bm2 = BMO_slot_ptr_get(op, "dest"); + BMesh *bm2 = BMO_slot_ptr_get(op->slots_in, "dest"); if (!bm2) bm2 = bm; /* flag input */ - BMO_slot_buffer_flag_enable(bm, dupeop, "geom", BM_ALL, DUPE_INPUT); + BMO_slot_buffer_flag_enable(bm, dupeop->slots_in, "geom", BM_ALL_NOLOOP, DUPE_INPUT); /* use the internal copy function */ - BKE_mesh_copy(dupeop, bm, bm2); + bmo_mesh_copy(dupeop, bm, bm2); /* Output */ /* First copy the input buffers to output buffers - original data */ - BMO_slot_copy(dupeop, dupeop, "geom", "origout"); + BMO_slot_copy(dupeop, slots_in, "geom", + dupeop, slots_out, "geom_orig.out"); /* Now alloc the new output buffers */ - BMO_slot_buffer_from_enabled_flag(bm, dupeop, "newout", BM_ALL, DUPE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, dupeop, dupeop->slots_out, "geom.out", BM_ALL_NOLOOP, DUPE_NEW); } #if 0 /* UNUSED */ @@ -378,16 +386,17 @@ void bmo_split_exec(BMesh *bm, BMOperator *op) BMOperator *splitop = op; BMOperator dupeop; BMOperator delop; - const short use_only_faces = BMO_slot_bool_get(op, "use_only_faces"); + const short use_only_faces = BMO_slot_bool_get(op->slots_in, "use_only_faces"); /* initialize our sub-operator */ BMO_op_init(bm, &dupeop, op->flag, "duplicate"); BMO_op_init(bm, &delop, op->flag, "delete"); - BMO_slot_copy(splitop, &dupeop, "geom", "geom"); + BMO_slot_copy(splitop, slots_in, "geom", + &dupeop, slots_in, "geom"); BMO_op_exec(bm, &dupeop); - BMO_slot_buffer_flag_enable(bm, splitop, "geom", BM_ALL, SPLIT_INPUT); + BMO_slot_buffer_flag_enable(bm, splitop->slots_in, "geom", BM_ALL_NOLOOP, SPLIT_INPUT); if (use_only_faces) { BMVert *v; @@ -427,16 +436,22 @@ void bmo_split_exec(BMesh *bm, BMOperator *op) } /* connect outputs of dupe to delete, exluding keep geometry */ - BMO_slot_int_set(&delop, "context", DEL_FACES); - BMO_slot_buffer_from_enabled_flag(bm, &delop, "geom", BM_ALL, SPLIT_INPUT); + BMO_slot_int_set(delop.slots_in, "context", DEL_FACES); + BMO_slot_buffer_from_enabled_flag(bm, &delop, delop.slots_in, "geom", BM_ALL_NOLOOP, SPLIT_INPUT); BMO_op_exec(bm, &delop); /* now we make our outputs by copying the dupe output */ - BMO_slot_copy(&dupeop, splitop, "newout", "geomout"); - BMO_slot_copy(&dupeop, splitop, "boundarymap", "boundarymap"); - BMO_slot_copy(&dupeop, splitop, "isovertmap", "isovertmap"); - + BMO_slot_copy(&dupeop, slots_out, "geom.out", + splitop, slots_out, "geom.out"); + + BMO_slot_copy(&dupeop, slots_out, "boundary_map.out", + splitop, slots_out, "boundary_map.out"); + + BMO_slot_copy(&dupeop, slots_out, "isovert_map.out", + splitop, slots_out, "isovert_map.out"); + + /* cleanup */ BMO_op_finish(bm, &delop); BMO_op_finish(bm, &dupeop); @@ -450,9 +465,9 @@ void bmo_delete_exec(BMesh *bm, BMOperator *op) BMOperator *delop = op; /* Mark Buffer */ - BMO_slot_buffer_flag_enable(bm, delop, "geom", BM_ALL, DEL_INPUT); + BMO_slot_buffer_flag_enable(bm, delop->slots_in, "geom", BM_ALL_NOLOOP, DEL_INPUT); - BMO_remove_tagged_context(bm, DEL_INPUT, BMO_slot_int_get(op, "context")); + BMO_remove_tagged_context(bm, DEL_INPUT, BMO_slot_int_get(op->slots_in, "context")); #undef DEL_INPUT } @@ -473,44 +488,47 @@ void bmo_spin_exec(BMesh *bm, BMOperator *op) float phi; int steps, do_dupli, a, usedvec; - BMO_slot_vec_get(op, "cent", cent); - BMO_slot_vec_get(op, "axis", axis); + BMO_slot_vec_get(op->slots_in, "cent", cent); + BMO_slot_vec_get(op->slots_in, "axis", axis); normalize_v3(axis); - BMO_slot_vec_get(op, "dvec", dvec); + BMO_slot_vec_get(op->slots_in, "dvec", dvec); usedvec = !is_zero_v3(dvec); - steps = BMO_slot_int_get(op, "steps"); - phi = BMO_slot_float_get(op, "ang") * DEG2RADF(1.0f) / steps; - do_dupli = BMO_slot_bool_get(op, "do_dupli"); + steps = BMO_slot_int_get(op->slots_in, "steps"); + phi = BMO_slot_float_get(op->slots_in, "angle") / steps; + do_dupli = BMO_slot_bool_get(op->slots_in, "use_duplicate"); axis_angle_to_mat3(rmat, axis, phi); - BMO_slot_copy(op, op, "geom", "lastout"); + BMO_slot_copy(op, slots_in, "geom", + op, slots_out, "geom_last.out"); for (a = 0; a < steps; a++) { if (do_dupli) { - BMO_op_initf(bm, &dupop, op->flag, "duplicate geom=%s", op, "lastout"); + BMO_op_initf(bm, &dupop, op->flag, "duplicate geom=%S", op, "geom_last.out"); BMO_op_exec(bm, &dupop); BMO_op_callf(bm, op->flag, - "rotate cent=%v mat=%m3 verts=%s", - cent, rmat, &dupop, "newout"); - BMO_slot_copy(&dupop, op, "newout", "lastout"); + "rotate cent=%v matrix=%m3 verts=%S", + cent, rmat, &dupop, "geom.out"); + BMO_slot_copy(&dupop, slots_out, "geom.out", + op, slots_out, "geom_last.out"); BMO_op_finish(bm, &dupop); } else { - BMO_op_initf(bm, &extop, op->flag, "extrude_face_region edgefacein=%s", - op, "lastout"); + BMO_op_initf(bm, &extop, op->flag, "extrude_face_region geom=%S", + op, "geom_last.out"); BMO_op_exec(bm, &extop); BMO_op_callf(bm, op->flag, - "rotate cent=%v mat=%m3 verts=%s", - cent, rmat, &extop, "geomout"); - BMO_slot_copy(&extop, op, "geomout", "lastout"); + "rotate cent=%v matrix=%m3 verts=%S", + cent, rmat, &extop, "geom.out"); + BMO_slot_copy(&extop, slots_out, "geom.out", + op, slots_out, "geom_last.out"); BMO_op_finish(bm, &extop); } if (usedvec) { mul_m3_v3(rmat, dvec); BMO_op_callf(bm, op->flag, - "translate vec=%v verts=%s", - dvec, op, "lastout"); + "translate vec=%v verts=%S", + dvec, op, "geom_last.out"); } } } diff --git a/source/blender/bmesh/operators/bmo_edgesplit.c b/source/blender/bmesh/operators/bmo_edgesplit.c index 1f6689ed06c..9e9e4b8c962 100644 --- a/source/blender/bmesh/operators/bmo_edgesplit.c +++ b/source/blender/bmesh/operators/bmo_edgesplit.c @@ -81,14 +81,14 @@ static void bm_edgesplit_validate_seams(BMesh *bm, BMOperator *op) /* single marked edges unconnected to any other marked edges * are illegal, go through and unmark them */ - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { /* lame, but we don't want the count to exceed 255, * so just count to 2, its all we need */ unsigned char *vt; vt = &vtouch[BM_elem_index_get(e->v1)]; if (*vt < 2) (*vt)++; vt = &vtouch[BM_elem_index_get(e->v2)]; if (*vt < 2) (*vt)++; } - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (vtouch[BM_elem_index_get(e->v1)] == 1 && vtouch[BM_elem_index_get(e->v2)] == 1) { @@ -104,13 +104,13 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) { BMOIter siter; BMEdge *e; - const int use_verts = BMO_slot_bool_get(op, "use_verts"); + const int use_verts = BMO_slot_bool_get(op->slots_in, "use_verts"); - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_SEAM); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_SEAM); if (use_verts) { /* this slows down the operation but its ok because the modifier doesn't use */ - BMO_slot_buffer_flag_enable(bm, op, "verts", BM_VERT, VERT_SEAM); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_SEAM); /* prevent one edge having both verts unflagged * we could alternately disable these edges, either way its a corner case. @@ -118,7 +118,7 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) * This is needed so we don't split off the edge but then none of its verts which * would leave a duplicate edge. */ - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (UNLIKELY((BMO_elem_flag_test(bm, e->v1, VERT_SEAM) == FALSE && (BMO_elem_flag_test(bm, e->v2, VERT_SEAM) == FALSE)))) { @@ -130,7 +130,7 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) bm_edgesplit_validate_seams(bm, op); - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (BMO_elem_flag_test(bm, e, EDGE_SEAM)) { /* this flag gets copied so we can be sure duplicate edges get it too (important) */ BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG); @@ -146,7 +146,7 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) } if (use_verts) { - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (BMO_elem_flag_test(bm, e->v1, VERT_SEAM) == FALSE) { BM_elem_flag_disable(e->v1, BM_ELEM_TAG); } @@ -156,7 +156,7 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) } } - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (BMO_elem_flag_test(bm, e, EDGE_SEAM)) { if (BM_elem_flag_test(e->v1, BM_ELEM_TAG)) { BM_elem_flag_disable(e->v1, BM_ELEM_TAG); @@ -169,5 +169,5 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_hflag(bm, op, "edgeout", BM_EDGE, BM_ELEM_INTERNAL_TAG); + BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_INTERNAL_TAG); } diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c index 627351ead11..065a1b57737 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -60,18 +60,18 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) BLI_array_declare(edges); int i; - BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { BLI_array_empty(edges); BLI_array_grow_items(edges, f->len); i = 0; firstv = lastv = NULL; BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - v = BM_vert_create(bm, l->v->co, l->v); + v = BM_vert_create(bm, l->v->co, l->v, 0); /* skip on the first iteration */ if (lastv) { - e = BM_edge_create(bm, lastv, v, l->e, FALSE); + e = BM_edge_create(bm, lastv, v, l->e, 0); edges[i++] = e; } @@ -81,12 +81,12 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) } /* this fits in the array because we skip one in the loop above */ - e = BM_edge_create(bm, v, firstv, laste, FALSE); + e = BM_edge_create(bm, v, firstv, laste, 0); edges[i++] = e; BMO_elem_flag_enable(bm, f, EXT_DEL); - f2 = BM_face_create_ngon(bm, firstv, BM_edge_other_vert(edges[0], firstv), edges, f->len, FALSE); + f2 = BM_face_create_ngon(bm, firstv, BM_edge_other_vert(edges[0], firstv), edges, f->len, 0); if (UNLIKELY(f2 == NULL)) { BMO_error_raise(bm, op, BMERR_MESH_ERROR, "Extrude failed: could not create face"); BLI_array_free(edges); @@ -122,7 +122,7 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) BMO_op_callf(bm, op->flag, "delete geom=%ff context=%i", EXT_DEL, DEL_ONLYFACES); - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, EXT_KEEP); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, EXT_KEEP); } /** @@ -181,7 +181,7 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op) BMFace *f; BMEdge *e, *e_new; - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { BMO_elem_flag_enable(bm, e, EXT_INPUT); BMO_elem_flag_enable(bm, e->v1, EXT_INPUT); BMO_elem_flag_enable(bm, e->v2, EXT_INPUT); @@ -193,12 +193,12 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op) /* disable root flag on all new skin nodes */ if (CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { BMVert *v; - BMO_ITER(v, &siter, bm, &dupeop, "newout", BM_VERT) { + BMO_ITER(v, &siter, dupeop.slots_out, "geom.out", BM_VERT) { bm_extrude_disable_skin_root(bm, v); } } - for (e = BMO_iter_new(&siter, bm, &dupeop, "boundarymap", 0); e; e = BMO_iter_step(&siter)) { + for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundary_map.out", 0); e; e = BMO_iter_step(&siter)) { BMVert *f_verts[4]; e_new = *(BMEdge **)BMO_iter_map_value(&siter); @@ -230,7 +230,7 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op) BMO_op_finish(bm, &dupeop); - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, EXT_KEEP); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, EXT_KEEP); } void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op) @@ -240,19 +240,19 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op) BMEdge *e; const int has_vskin = CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN); - for (v = BMO_iter_new(&siter, bm, op, "verts", BM_VERT); v; v = BMO_iter_step(&siter)) { - dupev = BM_vert_create(bm, v->co, v); + for (v = BMO_iter_new(&siter, op->slots_in, "verts", BM_VERT); v; v = BMO_iter_step(&siter)) { + dupev = BM_vert_create(bm, v->co, v, 0); if (has_vskin) bm_extrude_disable_skin_root(bm, v); - e = BM_edge_create(bm, v, dupev, NULL, FALSE); + e = BM_edge_create(bm, v, dupev, NULL, 0); BMO_elem_flag_enable(bm, e, EXT_KEEP); BMO_elem_flag_enable(bm, dupev, EXT_KEEP); } - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, EXT_KEEP); - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EXT_KEEP); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, EXT_KEEP); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EXT_KEEP); } void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) @@ -264,15 +264,17 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) BMVert *v, *v2; BMFace *f; int found, fwd, delorig = FALSE; + BMOpSlot *slot_facemap_out; + BMOpSlot *slot_edges_exclude; /* initialize our sub-operators */ BMO_op_init(bm, &dupeop, op->flag, "duplicate"); - BMO_slot_buffer_flag_enable(bm, op, "edgefacein", BM_EDGE | BM_FACE, EXT_INPUT); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_EDGE | BM_FACE, EXT_INPUT); /* if one flagged face is bordered by an un-flagged face, then we delete * original geometry unless caller explicitly asked to keep it. */ - if (!BMO_slot_bool_get(op, "alwayskeeporig")) { + if (!BMO_slot_bool_get(op->slots_in, "use_keep_orig")) { BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { int edge_face_tot; @@ -339,18 +341,21 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) EXT_DEL, DEL_ONLYTAGGED); } - BMO_slot_copy(op, &dupeop, "edgefacein", "geom"); + BMO_slot_copy(op, slots_in, "geom", + &dupeop, slots_in, "geom"); BMO_op_exec(bm, &dupeop); /* disable root flag on all new skin nodes */ if (CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { - BMO_ITER(v, &siter, bm, &dupeop, "newout", BM_VERT) { + BMO_ITER(v, &siter, dupeop.slots_out, "geom.out", BM_VERT) { bm_extrude_disable_skin_root(bm, v); } } - if (bm->act_face && BMO_elem_flag_test(bm, bm->act_face, EXT_INPUT)) - bm->act_face = BMO_slot_map_ptr_get(bm, &dupeop, "facemap", bm->act_face); + slot_facemap_out = BMO_slot_get(dupeop.slots_out, "face_map.out"); + if (bm->act_face && BMO_elem_flag_test(bm, bm->act_face, EXT_INPUT)) { + bm->act_face = BMO_slot_map_elem_get(slot_facemap_out, bm->act_face); + } if (delorig) { BMO_op_exec(bm, &delop); @@ -365,13 +370,15 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_copy(&dupeop, op, "newout", "geomout"); + BMO_slot_copy(&dupeop, slots_out, "geom.out", + op, slots_out, "geom.out"); - for (e = BMO_iter_new(&siter, bm, &dupeop, "boundarymap", 0); e; e = BMO_iter_step(&siter)) { + slot_edges_exclude = BMO_slot_get(op->slots_in, "edges_exclude"); + for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundary_map.out", 0); e; e = BMO_iter_step(&siter)) { BMVert *f_verts[4]; /* this should always be wire, so this is mainly a speedup to avoid map lookup */ - if (BM_edge_is_wire(e) && BMO_slot_map_contains(bm, op, "exclude", e)) { + if (BM_edge_is_wire(e) && BMO_slot_map_contains(slot_edges_exclude, e)) { BMVert *v1 = e->v1, *v2 = e->v2; /* The original edge was excluded, @@ -421,9 +428,9 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) } /* link isolated vert */ - for (v = BMO_iter_new(&siter, bm, &dupeop, "isovertmap", 0); v; v = BMO_iter_step(&siter)) { + for (v = BMO_iter_new(&siter, dupeop.slots_out, "isovert_map.out", 0); v; v = BMO_iter_step(&siter)) { v2 = *((void **)BMO_iter_map_value(&siter)); - BM_edge_create(bm, v, v2, v->e, TRUE); + BM_edge_create(bm, v, v2, v->e, BM_CREATE_NO_DOUBLE); } /* cleanup */ @@ -595,10 +602,10 @@ static void solidify_add_thickness(BMesh *bm, const float dist) /* array for passing verts to angle_poly_v3 */ float **verts = NULL; - BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); /* array for receiving angles from angle_poly_v3 */ float *face_angles = NULL; - BLI_array_staticdeclare(face_angles, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(face_angles, BM_DEFAULT_NGON_STACK_SIZE); BM_mesh_elem_index_ensure(bm, BM_VERT); @@ -647,25 +654,28 @@ void bmo_solidify_face_region_exec(BMesh *bm, BMOperator *op) BMOperator reverseop; float thickness; - thickness = BMO_slot_float_get(op, "thickness"); + thickness = BMO_slot_float_get(op->slots_in, "thickness"); /* Flip original faces (so the shell is extruded inward) */ BMO_op_init(bm, &reverseop, op->flag, "reverse_faces"); - BMO_slot_copy(op, &reverseop, "geom", "faces"); + BMO_slot_copy(op, slots_in, "geom", + &reverseop, slots_in, "faces"); BMO_op_exec(bm, &reverseop); BMO_op_finish(bm, &reverseop); /* Extrude the region */ - BMO_op_initf(bm, &extrudeop, op->flag, "extrude_face_region alwayskeeporig=%b", TRUE); - BMO_slot_copy(op, &extrudeop, "geom", "edgefacein"); + BMO_op_initf(bm, &extrudeop, op->flag, "extrude_face_region use_keep_orig=%b", TRUE); + BMO_slot_copy(op, slots_in, "geom", + &extrudeop, slots_in, "geom"); BMO_op_exec(bm, &extrudeop); /* Push the verts of the extruded faces inward to create thickness */ - BMO_slot_buffer_flag_enable(bm, &extrudeop, "geomout", BM_FACE, FACE_MARK); + BMO_slot_buffer_flag_enable(bm, extrudeop.slots_out, "geom.out", BM_FACE, FACE_MARK); calc_solidify_normals(bm); solidify_add_thickness(bm, thickness); - BMO_slot_copy(&extrudeop, op, "geomout", "geomout"); + BMO_slot_copy(&extrudeop, slots_out, "geom.out", + op, slots_out, "geom.out"); BMO_op_finish(bm, &extrudeop); } diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c index 013b6183f84..e2da4f4f89c 100644 --- a/source/blender/bmesh/operators/bmo_hull.c +++ b/source/blender/bmesh/operators/bmo_hull.c @@ -113,13 +113,13 @@ static void hull_output_triangles(BMesh *bm, GHash *hull_triangles) if (!t->skip) { BMEdge *edges[3] = { - BM_edge_create(bm, t->v[0], t->v[1], NULL, TRUE), - BM_edge_create(bm, t->v[1], t->v[2], NULL, TRUE), - BM_edge_create(bm, t->v[2], t->v[0], NULL, TRUE) + BM_edge_create(bm, t->v[0], t->v[1], NULL, BM_CREATE_NO_DOUBLE), + BM_edge_create(bm, t->v[1], t->v[2], NULL, BM_CREATE_NO_DOUBLE), + BM_edge_create(bm, t->v[2], t->v[0], NULL, BM_CREATE_NO_DOUBLE) }; BMFace *f, *example = NULL; - if (BM_face_exists(bm, t->v, 3, &f)) { + if (BM_face_exists(t->v, 3, &f)) { /* If the operator is run with "use_existing_faces" * disabled, but an output face in the hull is the * same as a face in the existing mesh, it should not @@ -139,17 +139,17 @@ static void hull_output_triangles(BMesh *bm, GHash *hull_triangles) f = BM_face_create_quad_tri_v(bm, t->v, 3, example, TRUE); BM_face_copy_shared(bm, f); } - /* Mark face for 'geomout' slot and select */ + /* Mark face for 'geom.out' slot and select */ BMO_elem_flag_enable(bm, f, HULL_FLAG_OUTPUT_GEOM); BM_face_select_set(bm, f, TRUE); - /* Mark edges for 'geomout' slot */ + /* Mark edges for 'geom.out' slot */ for (i = 0; i < 3; i++) { BMO_elem_flag_enable(bm, edges[i], HULL_FLAG_OUTPUT_GEOM); } } else { - /* Mark input edges for 'geomout' slot */ + /* Mark input edges for 'geom.out' slot */ for (i = 0; i < 3; i++) { const int next = (i == 2 ? 0 : i + 1); BMEdge *e = BM_edge_exists(t->v[i], t->v[next]); @@ -161,7 +161,7 @@ static void hull_output_triangles(BMesh *bm, GHash *hull_triangles) } } - /* Mark verts for 'geomout' slot */ + /* Mark verts for 'geom.out' slot */ for (i = 0; i < 3; i++) { BMO_elem_flag_enable(bm, t->v[i], HULL_FLAG_OUTPUT_GEOM); } @@ -304,14 +304,14 @@ static void hull_mark_interior_elements(BMesh *bm, BMOperator *op, BMOIter oiter; /* Check for interior edges too */ - BMO_ITER (e, &oiter, bm, op, "input", BM_EDGE) { + BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) { if (!hull_final_edges_lookup(final_edges, e->v1, e->v2)) BMO_elem_flag_enable(bm, e, HULL_FLAG_INTERIOR_ELE); } /* Mark all input faces as interior, some may be unmarked in * hull_remove_overlapping() */ - BMO_ITER (f, &oiter, bm, op, "input", BM_FACE) { + BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) { BMO_elem_flag_enable(bm, f, HULL_FLAG_INTERIOR_ELE); } } @@ -328,7 +328,7 @@ static void hull_tag_unused(BMesh *bm, BMOperator *op) * interior (i.e. were already part of the input, but not part of * the hull), but that aren't also used by elements outside the * input set */ - BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { + BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) { if (BMO_elem_flag_test(bm, v, HULL_FLAG_INTERIOR_ELE)) { int del = TRUE; @@ -351,7 +351,7 @@ static void hull_tag_unused(BMesh *bm, BMOperator *op) } } - BMO_ITER (e, &oiter, bm, op, "input", BM_EDGE) { + BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) { if (BMO_elem_flag_test(bm, e, HULL_FLAG_INTERIOR_ELE)) { int del = TRUE; @@ -367,7 +367,7 @@ static void hull_tag_unused(BMesh *bm, BMOperator *op) } } - BMO_ITER (f, &oiter, bm, op, "input", BM_FACE) { + BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) { if (BMO_elem_flag_test(bm, f, HULL_FLAG_INTERIOR_ELE)) BMO_elem_flag_enable(bm, f, HULL_FLAG_DEL); } @@ -382,10 +382,10 @@ static void hull_tag_holes(BMesh *bm, BMOperator *op) /* Unmark any hole faces if they are isolated or part of a * border */ - BMO_ITER (f, &oiter, bm, op, "input", BM_FACE) { + BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) { if (BMO_elem_flag_test(bm, f, HULL_FLAG_HOLE)) { BM_ITER_ELEM (e, &iter, f, BM_EDGES_OF_FACE) { - if (BM_edge_face_count(e) == 1) { + if (BM_edge_is_boundary(e)) { BMO_elem_flag_disable(bm, f, HULL_FLAG_HOLE); break; } @@ -395,7 +395,7 @@ static void hull_tag_holes(BMesh *bm, BMOperator *op) /* Mark edges too if all adjacent faces are holes and the edge is * not already isolated */ - BMO_ITER (e, &oiter, bm, op, "input", BM_EDGE) { + BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) { int hole = TRUE; int any_faces = FALSE; @@ -412,29 +412,29 @@ static void hull_tag_holes(BMesh *bm, BMOperator *op) } } -static int hull_input_vert_count(BMesh *bm, BMOperator *op) +static int hull_input_vert_count(BMOperator *op) { BMOIter oiter; BMVert *v; int count = 0; - BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { + BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) { count++; } return count; } -static BMVert **hull_input_verts_copy(BMesh *bm, BMOperator *op, - const int num_input_verts) +static BMVert **hull_input_verts_copy(BMOperator *op, + const int num_input_verts) { BMOIter oiter; BMVert *v; BMVert **input_verts = MEM_callocN(sizeof(*input_verts) * - num_input_verts, AT); + num_input_verts, AT); int i = 0; - BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { + BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) { input_verts[i++] = v; } @@ -442,7 +442,7 @@ static BMVert **hull_input_verts_copy(BMesh *bm, BMOperator *op, } static float (*hull_verts_for_bullet(BMVert **input_verts, - const int num_input_verts))[3] + const int num_input_verts))[3] { float (*coords)[3] = MEM_callocN(sizeof(*coords) * num_input_verts, AT); int i; @@ -455,12 +455,12 @@ static float (*hull_verts_for_bullet(BMVert **input_verts, } static BMVert **hull_verts_from_bullet(plConvexHull hull, - BMVert **input_verts, - const int num_input_verts) + BMVert **input_verts, + const int num_input_verts) { const int num_verts = plConvexHullNumVertices(hull); BMVert **hull_verts = MEM_mallocN(sizeof(*hull_verts) * - num_verts, AT); + num_verts, AT); int i; for (i = 0; i < num_verts; i++) { @@ -479,8 +479,8 @@ static BMVert **hull_verts_from_bullet(plConvexHull hull, } static void hull_from_bullet(BMesh *bm, BMOperator *op, - GHash *hull_triangles, - BLI_mempool *pool) + GHash *hull_triangles, + BLI_mempool *pool) { int *fvi = NULL; BLI_array_declare(fvi); @@ -492,9 +492,9 @@ static void hull_from_bullet(BMesh *bm, BMOperator *op, plConvexHull hull; int i, count = 0; - const int num_input_verts = hull_input_vert_count(bm, op); + const int num_input_verts = hull_input_vert_count(op); - input_verts = hull_input_verts_copy(bm, op, num_input_verts); + input_verts = hull_input_verts_copy(op, num_input_verts); coords = hull_verts_for_bullet(input_verts, num_input_verts); hull = plConvexHullCompute(coords, num_input_verts); @@ -523,7 +523,7 @@ static void hull_from_bullet(BMesh *bm, BMOperator *op, fv[2] = hull_verts[fvi[j]]; hull_add_triangle(bm, hull_triangles, pool, - fv[0], fv[1], fv[2]); + fv[0], fv[1], fv[2]); } } } @@ -535,13 +535,13 @@ static void hull_from_bullet(BMesh *bm, BMOperator *op, } /* Check that there are at least three vertices in the input */ -static int hull_num_input_verts_is_ok(BMesh *bm, BMOperator *op) +static int hull_num_input_verts_is_ok(BMOperator *op) { BMOIter oiter; BMVert *v; int partial_num_verts = 0; - BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { + BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) { partial_num_verts++; if (partial_num_verts >= 3) break; @@ -559,14 +559,14 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op) GHash *hull_triangles; /* Verify that at least three verts in the input */ - if (!hull_num_input_verts_is_ok(bm, op)) { + if (!hull_num_input_verts_is_ok(op)) { BMO_error_raise(bm, op, BMERR_CONVEX_HULL_FAILED, "Requires at least three vertices"); return; } /* Tag input elements */ - BMO_ITER (ele, &oiter, bm, op, "input", BM_ALL) { + BMO_ITER (ele, &oiter, op->slots_in, "input", BM_ALL) { BMO_elem_flag_enable(bm, ele, HULL_FLAG_INPUT); /* Mark all vertices as interior to begin with */ @@ -584,7 +584,7 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op) hull_mark_interior_elements(bm, op, final_edges); /* Remove hull triangles covered by an existing face */ - if (BMO_slot_bool_get(op, "use_existing_faces")) { + if (BMO_slot_bool_get(op->slots_in, "use_existing_faces")) { hull_remove_overlapping(bm, hull_triangles, final_edges); hull_tag_holes(bm, op); @@ -603,23 +603,23 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op) /* Output slot of input elements that ended up inside the hull * rather than part of it */ - BMO_slot_buffer_from_enabled_flag(bm, op, "interior_geom", BM_ALL, - HULL_FLAG_INTERIOR_ELE); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_interior.out", + BM_ALL_NOLOOP, HULL_FLAG_INTERIOR_ELE); /* Output slot of input elements that ended up inside the hull and * are are unused by other geometry. */ - BMO_slot_buffer_from_enabled_flag(bm, op, "unused_geom", BM_ALL, - HULL_FLAG_DEL); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_unused.out", + BM_ALL_NOLOOP, HULL_FLAG_DEL); /* Output slot of faces and edges that were in the input and on * the hull (useful for cases like bridging where you want to * delete some input geometry) */ - BMO_slot_buffer_from_enabled_flag(bm, op, "holes_geom", BM_ALL, - HULL_FLAG_HOLE); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_holes.out", + BM_ALL_NOLOOP, HULL_FLAG_HOLE); /* Output slot of all hull vertices, faces, and edges */ - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, - HULL_FLAG_OUTPUT_GEOM); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", + BM_ALL_NOLOOP, HULL_FLAG_OUTPUT_GEOM); } #endif /* WITH_BULLET */ diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c index 132d7050b31..cef1181f63b 100644 --- a/source/blender/bmesh/operators/bmo_inset.c +++ b/source/blender/bmesh/operators/bmo_inset.c @@ -92,13 +92,13 @@ static BMLoop *bm_edge_is_mixed_face_tag(BMLoop *l) void bmo_inset_exec(BMesh *bm, BMOperator *op) { - const int use_outset = BMO_slot_bool_get(op, "use_outset"); - const int use_boundary = BMO_slot_bool_get(op, "use_boundary") && (use_outset == FALSE); - const int use_even_offset = BMO_slot_bool_get(op, "use_even_offset"); + const int use_outset = BMO_slot_bool_get(op->slots_in, "use_outset"); + const int use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary") && (use_outset == FALSE); + const int use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset"); const int use_even_boundry = use_even_offset; /* could make own option */ - const int use_relative_offset = BMO_slot_bool_get(op, "use_relative_offset"); - const float thickness = BMO_slot_float_get(op, "thickness"); - const float depth = BMO_slot_float_get(op, "depth"); + const int use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset"); + const float thickness = BMO_slot_float_get(op->slots_in, "thickness"); + const float depth = BMO_slot_float_get(op->slots_in, "depth"); int edge_info_len = 0; @@ -113,11 +113,11 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) if (use_outset == FALSE) { BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, FALSE); - BMO_slot_buffer_hflag_enable(bm, op, "faces", BM_FACE, BM_ELEM_TAG, FALSE); + BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, FALSE); } else { BM_mesh_elem_hflag_enable_all(bm, BM_FACE, BM_ELEM_TAG, FALSE); - BMO_slot_buffer_hflag_disable(bm, op, "faces", BM_FACE, BM_ELEM_TAG, FALSE); + BMO_slot_buffer_hflag_disable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, FALSE); } /* first count all inset edges we will split */ @@ -181,7 +181,7 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) if (es->e_new == es->e_old) { /* happens on boundary edges */ /* take care here, we're creating this double edge which _must_ have its verts replaced later on */ - es->e_old = BM_edge_create(bm, es->e_new->v1, es->e_new->v2, es->e_new, FALSE); + es->e_old = BM_edge_create(bm, es->e_new->v1, es->e_new->v2, es->e_new, 0); } /* store index back to original in 'edge_info' */ @@ -205,7 +205,7 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) v1 = BM_vert_create(bm, tvec, NULL); v2 = BM_vert_create(bm, tvec, NULL); madd_v3_v3fl(v2->co, es->no, 0.1f); - BM_edge_create(bm, v1, v2, NULL, FALSE); + BM_edge_create(bm, v1, v2, NULL, 0); } #endif @@ -477,11 +477,48 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) /* copy for loop data, otherwise UV's and vcols are no good. * tiny speedup here we could be more clever and copy from known adjacent data * also - we could attempt to interpolate the loop data, this would be much slower but more useful too */ +#if 0 + /* don't use this because face boundaries have no adjacent loops and won't be filled in. + * instead copy from the opposite side with the code below */ BM_face_copy_shared(bm, f); +#else + { + /* 2 inner loops on the edge between the new face and the original */ + BMLoop *l_a; + BMLoop *l_b; + BMLoop *l_a_other; + BMLoop *l_b_other; + + l_a = BM_FACE_FIRST_LOOP(f); + l_b = l_a->next; + + /* we know this side has a radial_next because of the order of created verts in the quad */ + l_a_other = BM_edge_other_loop(l_a->e, l_a); + l_b_other = BM_edge_other_loop(l_a->e, l_b); + BM_elem_attrs_copy(bm, bm, l_a_other, l_a); + BM_elem_attrs_copy(bm, bm, l_b_other, l_b); + + /* step around to the opposite side of the quad - warning, this may have no other edges! */ + l_a = l_a->next->next; + l_b = l_a->next; + if (!BM_edge_is_boundary(l_a->e)) { + /* same as above */ + l_a_other = BM_edge_other_loop(l_a->e, l_a); + l_b_other = BM_edge_other_loop(l_a->e, l_b); + BM_elem_attrs_copy(bm, bm, l_a_other, l_a); + BM_elem_attrs_copy(bm, bm, l_b_other, l_b); + } + else { /* boundary edges have no useful data to copy from, use opposite side of face */ + /* swap a<->b intentionally */ + BM_elem_attrs_copy(bm, bm, l_a_other, l_b); + BM_elem_attrs_copy(bm, bm, l_b_other, l_a); + } + } +#endif } /* we could flag new edges/verts too, is it useful? */ - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, ELE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_NEW); /* cheap feature to add depth to the inset */ if (depth != 0.0f) { @@ -514,7 +551,7 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, FALSE); /* tag face verts */ - BMO_ITER (f, &oiter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) { BM_ITER_ELEM (v, &iter, f, BM_VERTS_OF_FACE) { BM_elem_flag_enable(v, BM_ELEM_TAG); } diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c index 3dbc0d0a5eb..1e18a83a0a0 100644 --- a/source/blender/bmesh/operators/bmo_join_triangles.c +++ b/source/blender/bmesh/operators/bmo_join_triangles.c @@ -204,16 +204,16 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) BMEdge *e; BLI_array_declare(jedges); JoinEdge *jedges = NULL; - int do_sharp = BMO_slot_bool_get(op, "cmp_sharp"); - int do_uv = BMO_slot_bool_get(op, "cmp_uvs"); + int do_sharp = BMO_slot_bool_get(op->slots_in, "cmp_sharp"); + int do_uv = BMO_slot_bool_get(op->slots_in, "cmp_uvs"); int do_tf = do_uv; /* texture face, make make its own option eventually */ - int do_vcol = BMO_slot_bool_get(op, "cmp_vcols"); - int do_mat = BMO_slot_bool_get(op, "cmp_materials"); - float limit = BMO_slot_float_get(op, "limit"); + int do_vcol = BMO_slot_bool_get(op->slots_in, "cmp_vcols"); + int do_mat = BMO_slot_bool_get(op->slots_in, "cmp_materials"); + float limit = BMO_slot_float_get(op->slots_in, "limit"); int i, totedge; /* flag all edges of all input face */ - BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { BMO_elem_flag_enable(bm, f, FACE_INPUT); BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { BMO_elem_flag_enable(bm, l->e, EDGE_MARK); diff --git a/source/blender/bmesh/operators/bmo_mesh_conv.c b/source/blender/bmesh/operators/bmo_mesh_conv.c index c4b988ae82d..4b897a24c8a 100644 --- a/source/blender/bmesh/operators/bmo_mesh_conv.c +++ b/source/blender/bmesh/operators/bmo_mesh_conv.c @@ -53,9 +53,9 @@ void bmo_mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) { - Object *ob = BMO_slot_ptr_get(op, "object"); - Mesh *me = BMO_slot_ptr_get(op, "mesh"); - int set_key = BMO_slot_bool_get(op, "set_shapekey"); + Object *ob = BMO_slot_ptr_get(op->slots_in, "object"); + Mesh *me = BMO_slot_ptr_get(op->slots_in, "mesh"); + int set_key = BMO_slot_bool_get(op->slots_in, "use_shapekey"); BM_mesh_bm_from_me(bm, me, set_key, ob->shapenr); @@ -66,20 +66,20 @@ void bmo_mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) void bmo_object_load_bmesh_exec(BMesh *bm, BMOperator *op) { - Object *ob = BMO_slot_ptr_get(op, "object"); + Object *ob = BMO_slot_ptr_get(op->slots_in, "object"); /* Scene *scene = BMO_slot_ptr_get(op, "scene"); */ Mesh *me = ob->data; BMO_op_callf(bm, op->flag, - "bmesh_to_mesh mesh=%p object=%p notessellation=%b", + "bmesh_to_mesh mesh=%p object=%p skip_tessface=%b", me, ob, TRUE); } void bmo_bmesh_to_mesh_exec(BMesh *bm, BMOperator *op) { - Mesh *me = BMO_slot_ptr_get(op, "mesh"); + Mesh *me = BMO_slot_ptr_get(op->slots_in, "mesh"); /* Object *ob = BMO_slot_ptr_get(op, "object"); */ - int dotess = !BMO_slot_bool_get(op, "notessellation"); + int dotess = !BMO_slot_bool_get(op->slots_in, "skip_tessface"); BM_mesh_bm_to_me(bm, me, dotess); } diff --git a/source/blender/bmesh/operators/bmo_mirror.c b/source/blender/bmesh/operators/bmo_mirror.c index c6b228b988e..61b061dd21f 100644 --- a/source/blender/bmesh/operators/bmo_mirror.c +++ b/source/blender/bmesh/operators/bmo_mirror.c @@ -50,27 +50,28 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) float mtx[4][4]; float imtx[4][4]; float scale[3] = {1.0f, 1.0f, 1.0f}; - float dist = BMO_slot_float_get(op, "mergedist"); + float dist = BMO_slot_float_get(op->slots_in, "merge_dist"); int i, ototvert /*, ototedge */; - int axis = BMO_slot_int_get(op, "axis"); - int mirroru = BMO_slot_bool_get(op, "mirror_u"); - int mirrorv = BMO_slot_bool_get(op, "mirror_v"); + int axis = BMO_slot_int_get(op->slots_in, "axis"); + int mirroru = BMO_slot_bool_get(op->slots_in, "mirror_u"); + int mirrorv = BMO_slot_bool_get(op->slots_in, "mirror_v"); + BMOpSlot *slot_targetmap; ototvert = bm->totvert; /* ototedge = bm->totedge; */ /* UNUSED */ - BMO_slot_mat4_get(op, "mat", mtx); + BMO_slot_mat4_get(op->slots_in, "matrix", mtx); invert_m4_m4(imtx, mtx); BMO_op_initf(bm, &dupeop, op->flag, "duplicate geom=%s", op, "geom"); BMO_op_exec(bm, &dupeop); - BMO_slot_buffer_flag_enable(bm, &dupeop, "newout", BM_ALL, ELE_NEW); + BMO_slot_buffer_flag_enable(bm, dupeop.slots_out, "geom.out", BM_ALL_NOLOOP, ELE_NEW); /* create old -> new mappin */ i = 0; /* v2 = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); */ /* UNUSED */ - BMO_ITER (v, &siter, bm, &dupeop, "newout", BM_VERT) { + BMO_ITER (v, &siter, dupeop.slots_out, "geom.out", BM_VERT) { BLI_array_grow_one(vmap); vmap[i] = v; /* v2 = BM_iter_step(&iter); */ /* UNUSED */ @@ -80,16 +81,18 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) /* feed old data to transform bmo */ scale[axis] = -1.0f; - BMO_op_callf(bm, op->flag, "transform verts=%fv mat=%m4", ELE_NEW, mtx); + BMO_op_callf(bm, op->flag, "transform verts=%fv matrix=%m4", ELE_NEW, mtx); BMO_op_callf(bm, op->flag, "scale verts=%fv vec=%v", ELE_NEW, scale); - BMO_op_callf(bm, op->flag, "transform verts=%fv mat=%m4", ELE_NEW, imtx); + BMO_op_callf(bm, op->flag, "transform verts=%fv matrix=%m4", ELE_NEW, imtx); BMO_op_init(bm, &weldop, op->flag, "weld_verts"); + slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap"); + v = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); for (i = 0; i < ototvert; i++) { - if (ABS(v->co[axis]) <= dist) { - BMO_slot_map_ptr_insert(bm, &weldop, "targetmap", vmap[i], v); + if (fabsf(v->co[axis]) <= dist) { + BMO_slot_map_elem_insert(&weldop, slot_targetmap, vmap[i], v); } v = BM_iter_step(&iter); } @@ -101,7 +104,7 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) int totlayer; BMIter liter; - BMO_ITER (f, &siter, bm, &dupeop, "newout", BM_FACE) { + BMO_ITER (f, &siter, dupeop.slots_out, "geom.out", BM_FACE) { BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { totlayer = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV); for (i = 0; i < totlayer; i++) { @@ -120,7 +123,7 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) BMO_op_finish(bm, &weldop); BMO_op_finish(bm, &dupeop); - BMO_slot_buffer_from_enabled_flag(bm, op, "newout", BM_ALL, ELE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_NEW); BLI_array_free(vmap); BLI_array_free(emap); diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c index d7b163cb760..c582f710f43 100644 --- a/source/blender/bmesh/operators/bmo_primitive.c +++ b/source/blender/bmesh/operators/bmo_primitive.c @@ -227,16 +227,17 @@ static signed char monkeyf[250][4] = { void bmo_create_grid_exec(BMesh *bm, BMOperator *op) { + const float dia = BMO_slot_float_get(op->slots_in, "size"); + const int tot = max_ii(2, BMO_slot_int_get(op->slots_in, "x_segments")); + const int seg = max_ii(2, BMO_slot_int_get(op->slots_in, "y_segments")); + BMOperator bmop, prevop; BMVert *eve, *preveve; BMEdge *e; - float vec[3], mat[4][4], phi, phid, dia = BMO_slot_float_get(op, "size"); - int a, tot = BMO_slot_int_get(op, "xsegments"), seg = BMO_slot_int_get(op, "ysegments"); + float vec[3], mat[4][4], phi, phid; + int a; - if (tot < 2) tot = 2; - if (seg < 2) seg = 2; - - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); /* one segment first: the X axis */ phi = 1.0f; @@ -247,11 +248,11 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op) vec[2] = 0.0f; mul_m4_v3(mat, vec); - eve = BM_vert_create(bm, vec, NULL); + eve = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, eve, VERT_MARK); if (a != 0) { - e = BM_edge_create(bm, preveve, eve, NULL, TRUE); + e = BM_edge_create(bm, preveve, eve, NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, e, EDGE_ORIG); } @@ -267,39 +268,43 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op) for (a = 0; a < seg - 1; a++) { if (a) { - BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%s", &prevop, "geomout"); + BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%S", &prevop, "geom.out"); BMO_op_exec(bm, &bmop); BMO_op_finish(bm, &prevop); - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_VERT, VERT_MARK); + BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK); } else { BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%fe", EDGE_ORIG); BMO_op_exec(bm, &bmop); - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_VERT, VERT_MARK); + BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK); } - BMO_op_callf(bm, op->flag, "translate vec=%v verts=%s", vec, &bmop, "geomout"); + BMO_op_callf(bm, op->flag, "translate vec=%v verts=%S", vec, &bmop, "geom.out"); prevop = bmop; } if (a) BMO_op_finish(bm, &bmop); - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) { + const float dia = BMO_slot_float_get(op->slots_in, "diameter"); + const int seg = BMO_slot_int_get(op->slots_in, "u_segments"); + const int tot = BMO_slot_int_get(op->slots_in, "v_segments"); + BMOperator bmop, prevop; BMVert *eve, *preveve; BMEdge *e; BMIter iter; float vec[3], mat[4][4], cmat[3][3], phi, q[4]; - float phid, dia = BMO_slot_float_get(op, "diameter"); - int a, seg = BMO_slot_int_get(op, "segments"), tot = BMO_slot_int_get(op, "revolutions"); + float phid; + int a; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); phid = 2.0f * (float)M_PI / tot; /* phi = 0.25f * (float)M_PI; */ /* UNUSED */ @@ -312,11 +317,11 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) vec[0] = -dia * sinf(phi); vec[1] = 0.0; vec[2] = dia * cosf(phi); - eve = BM_vert_create(bm, vec, NULL); + eve = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, eve, VERT_MARK); if (a != 0) { - e = BM_edge_create(bm, preveve, eve, NULL, FALSE); + e = BM_edge_create(bm, preveve, eve, NULL, 0); BMO_elem_flag_enable(bm, e, EDGE_ORIG); } @@ -333,7 +338,7 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) for (a = 0; a < seg; a++) { if (a) { - BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%s", &prevop, "geomout"); + BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%S", &prevop, "geom.out"); BMO_op_exec(bm, &bmop); BMO_op_finish(bm, &prevop); } @@ -342,8 +347,8 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) BMO_op_exec(bm, &bmop); } - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_VERT, VERT_MARK); - BMO_op_callf(bm, op->flag, "rotate cent=%v mat=%m3 verts=%s", vec, cmat, &bmop, "geomout"); + BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK); + BMO_op_callf(bm, op->flag, "rotate cent=%v matrix=%m3 verts=%S", vec, cmat, &bmop, "geom.out"); prevop = bmop; } @@ -375,31 +380,34 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) { + const float dia = BMO_slot_float_get(op->slots_in, "diameter"); + const float dia_div = dia / 200.0f; + const int subdiv = BMO_slot_int_get(op->slots_in, "subdivisions"); + BMVert *eva[12]; BMVert *v; BMIter liter; BMIter viter; BMLoop *l; float vec[3], mat[4][4] /* , phi, phid */; - float dia = BMO_slot_float_get(op, "diameter"); - int a, subdiv = BMO_slot_int_get(op, "subdivisions"); + int a; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); /* phid = 2.0f * (float)M_PI / subdiv; */ /* UNUSED */ /* phi = 0.25f * (float)M_PI; */ /* UNUSED */ - dia /= 200.0f; + for (a = 0; a < 12; a++) { - vec[0] = dia * icovert[a][0]; - vec[1] = dia * icovert[a][1]; - vec[2] = dia * icovert[a][2]; - eva[a] = BM_vert_create(bm, vec, NULL); + vec[0] = dia_div * icovert[a][0]; + vec[1] = dia_div * icovert[a][1]; + vec[2] = dia_div * icovert[a][2]; + eva[a] = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, eva[a], VERT_MARK); } @@ -421,22 +429,20 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) BMO_elem_flag_enable(bm, eftemp, FACE_MARK); } - dia *= 200.0f; - if (subdiv > 1) { BMOperator bmop; BMO_op_initf(bm, &bmop, op->flag, "subdivide_edges edges=%fe " "smooth=%f " - "numcuts=%i " - "use_gridfill=%b use_sphere=%b", + "cuts=%i " + "use_grid_fill=%b use_sphere=%b", EDGE_MARK, dia, (1 << (subdiv - 1)) - 1, TRUE, TRUE); BMO_op_exec(bm, &bmop); - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_VERT, VERT_MARK); - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK); + BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_EDGE, EDGE_MARK); BMO_op_finish(bm, &bmop); } @@ -447,7 +453,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) @@ -457,19 +463,19 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) float mat[4][4]; int i; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); for (i = 0; i < monkeynv; i++) { float v[3]; v[0] = (monkeyv[i][0] + 127) / 128.0, v[1] = monkeyv[i][1] / 128.0, v[2] = monkeyv[i][2] / 128.0; - tv[i] = BM_vert_create(bm, v, NULL); + tv[i] = BM_vert_create(bm, v, NULL, 0); BMO_elem_flag_enable(bm, tv[i], VERT_MARK); tv[monkeynv + i] = (fabsf(v[0] = -v[0]) < 0.001f) ? tv[i] : - (eve = BM_vert_create(bm, v, NULL), mul_m4_v3(mat, eve->co), eve); + (eve = BM_vert_create(bm, v, NULL, 0), mul_m4_v3(mat, eve->co), eve); BMO_elem_flag_enable(bm, tv[monkeynv + i], VERT_MARK); @@ -494,24 +500,25 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) MEM_freeN(tv); - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_circle_exec(BMesh *bm, BMOperator *op) { + const float dia = BMO_slot_float_get(op->slots_in, "diameter"); + const int segs = BMO_slot_int_get(op->slots_in, "segments"); + const int cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends"); + const int cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris"); + BMVert *v1, *lastv1 = NULL, *cent1, *firstv1 = NULL; float vec[3], mat[4][4], phi, phid; - float dia = BMO_slot_float_get(op, "diameter"); - int segs = BMO_slot_int_get(op, "segments"); - int cap_ends = BMO_slot_bool_get(op, "cap_ends"); - int cap_tris = BMO_slot_bool_get(op, "cap_tris"); int a; if (!segs) return; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); phid = 2.0f * (float)M_PI / segs; phi = 0; @@ -520,7 +527,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) zero_v3(vec); mul_m4_v3(mat, vec); - cent1 = BM_vert_create(bm, vec, NULL); + cent1 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, cent1, VERT_MARK); } @@ -530,12 +537,12 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) vec[1] = dia * cosf(phi); vec[2] = 0.0f; mul_m4_v3(mat, vec); - v1 = BM_vert_create(bm, vec, NULL); + v1 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v1, VERT_MARK); if (lastv1) - BM_edge_create(bm, v1, lastv1, NULL, FALSE); + BM_edge_create(bm, v1, lastv1, NULL, 0); if (a && cap_ends) { BMFace *f; @@ -553,7 +560,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) if (!a) return; - BM_edge_create(bm, lastv1, firstv1, NULL, FALSE); + BM_edge_create(bm, firstv1, lastv1, NULL, 0); if (cap_ends) { BMFace *f; @@ -566,25 +573,25 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_NEW); } - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_cone_exec(BMesh *bm, BMOperator *op) { BMVert *v1, *v2, *lastv1 = NULL, *lastv2 = NULL, *cent1, *cent2, *firstv1, *firstv2; float vec[3], mat[4][4], phi, phid; - float dia1 = BMO_slot_float_get(op, "diameter1"); - float dia2 = BMO_slot_float_get(op, "diameter2"); - float depth = BMO_slot_float_get(op, "depth"); - int segs = BMO_slot_int_get(op, "segments"); - int cap_ends = BMO_slot_bool_get(op, "cap_ends"); - int cap_tris = BMO_slot_bool_get(op, "cap_tris"); + float dia1 = BMO_slot_float_get(op->slots_in, "diameter1"); + float dia2 = BMO_slot_float_get(op->slots_in, "diameter2"); + float depth = BMO_slot_float_get(op->slots_in, "depth"); + int segs = BMO_slot_int_get(op->slots_in, "segments"); + int cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends"); + int cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris"); int a; if (!segs) return; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); phid = 2.0f * (float)M_PI / segs; phi = 0; @@ -595,13 +602,13 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) vec[2] = -depth; mul_m4_v3(mat, vec); - cent1 = BM_vert_create(bm, vec, NULL); + cent1 = BM_vert_create(bm, vec, NULL, 0); vec[0] = vec[1] = 0.0f; vec[2] = depth; mul_m4_v3(mat, vec); - cent2 = BM_vert_create(bm, vec, NULL); + cent2 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, cent1, VERT_MARK); BMO_elem_flag_enable(bm, cent2, VERT_MARK); @@ -612,13 +619,13 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) vec[1] = dia1 * cosf(phi); vec[2] = -depth; mul_m4_v3(mat, vec); - v1 = BM_vert_create(bm, vec, NULL); + v1 = BM_vert_create(bm, vec, NULL, 0); vec[0] = dia2 * sinf(phi); vec[1] = dia2 * cosf(phi); vec[2] = depth; mul_m4_v3(mat, vec); - v2 = BM_vert_create(bm, vec, NULL); + v2 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v1, VERT_MARK); BMO_elem_flag_enable(bm, v2, VERT_MARK); @@ -662,15 +669,15 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) BM_face_create_quad_tri(bm, v1, v2, firstv2, firstv1, NULL, FALSE); BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, 0.000001); - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_cube_exec(BMesh *bm, BMOperator *op) { BMVert *v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8; - float vec[3], mat[4][4], off = BMO_slot_float_get(op, "size") / 2.0f; + float vec[3], mat[4][4], off = BMO_slot_float_get(op->slots_in, "size") / 2.0f; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); if (!off) off = 0.5f; @@ -678,56 +685,56 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op) vec[1] = -off; vec[2] = -off; mul_m4_v3(mat, vec); - v1 = BM_vert_create(bm, vec, NULL); + v1 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v1, VERT_MARK); vec[0] = -off; vec[1] = off; vec[2] = -off; mul_m4_v3(mat, vec); - v2 = BM_vert_create(bm, vec, NULL); + v2 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v2, VERT_MARK); vec[0] = off; vec[1] = off; vec[2] = -off; mul_m4_v3(mat, vec); - v3 = BM_vert_create(bm, vec, NULL); + v3 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v3, VERT_MARK); vec[0] = off; vec[1] = -off; vec[2] = -off; mul_m4_v3(mat, vec); - v4 = BM_vert_create(bm, vec, NULL); + v4 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v4, VERT_MARK); vec[0] = -off; vec[1] = -off; vec[2] = off; mul_m4_v3(mat, vec); - v5 = BM_vert_create(bm, vec, NULL); + v5 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v5, VERT_MARK); vec[0] = -off; vec[1] = off; vec[2] = off; mul_m4_v3(mat, vec); - v6 = BM_vert_create(bm, vec, NULL); + v6 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v6, VERT_MARK); vec[0] = off; vec[1] = off; vec[2] = off; mul_m4_v3(mat, vec); - v7 = BM_vert_create(bm, vec, NULL); + v7 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v7, VERT_MARK); vec[0] = off; vec[1] = -off; vec[2] = off; mul_m4_v3(mat, vec); - v8 = BM_vert_create(bm, vec, NULL); + v8 = BM_vert_create(bm, vec, NULL, 0); BMO_elem_flag_enable(bm, v8, VERT_MARK); /* the four sides */ @@ -740,5 +747,5 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op) BM_face_create_quad_tri(bm, v1, v2, v3, v4, NULL, FALSE); BM_face_create_quad_tri(bm, v8, v7, v6, v5, NULL, FALSE); - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index ea6cd747037..87e26f11d4b 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -36,7 +36,7 @@ #include "intern/bmesh_operators_private.h" /* own include */ -static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op) +static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op, BMOpSlot *slot_targetmap) { BMIter liter; BMLoop *l; @@ -44,7 +44,7 @@ static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op) int split = FALSE; BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - v2 = BMO_slot_map_ptr_get(bm, op, "targetmap", l->v); + v2 = BMO_slot_map_elem_get(slot_targetmap, l->v); /* ok: if v2 is NULL (e.g. not in the map) then it's * a target vert, otherwise it's a double */ if ((v2 && BM_vert_in_face(f, v2)) && @@ -61,8 +61,8 @@ static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op) BMLoop *nl; BMFace *f2 = BM_face_split(bm, f, doub, v2, &nl, NULL, FALSE); - remdoubles_splitface(f, bm, op); - remdoubles_splitface(f2, bm, op); + remdoubles_splitface(f, bm, op, slot_targetmap); + remdoubles_splitface(f2, bm, op, slot_targetmap); } } @@ -106,10 +106,11 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) BLI_array_declare(loops); BMFace *f, *f2; int a, b; + BMOpSlot *slot_targetmap = BMO_slot_get(op->slots_in, "targetmap"); /* mark merge verts for deletion */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - if ((v2 = BMO_slot_map_ptr_get(bm, op, "targetmap", v))) { + if ((v2 = BMO_slot_map_elem_get(slot_targetmap, v))) { BMO_elem_flag_enable(bm, v, ELE_DEL); /* merge the vertex flags, else we get randomly selected/unselected verts */ @@ -120,13 +121,13 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) /* check if any faces are getting their own corners merged * together, split face if so */ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - remdoubles_splitface(f, bm, op); + remdoubles_splitface(f, bm, op, slot_targetmap); } BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BMO_elem_flag_test(bm, e->v1, ELE_DEL) || BMO_elem_flag_test(bm, e->v2, ELE_DEL)) { - v = BMO_slot_map_ptr_get(bm, op, "targetmap", e->v1); - v2 = BMO_slot_map_ptr_get(bm, op, "targetmap", e->v2); + v = BMO_slot_map_elem_get(slot_targetmap, e->v1); + v2 = BMO_slot_map_elem_get(slot_targetmap, e->v2); if (!v) v = e->v1; if (!v2) v2 = e->v2; @@ -135,7 +136,7 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) BMO_elem_flag_enable(bm, e, EDGE_COL); } else if (!BM_edge_exists(v, v2)) { - BM_edge_create(bm, v, v2, e, TRUE); + BM_edge_create(bm, v, v2, e, BM_CREATE_NO_DOUBLE); } BMO_elem_flag_enable(bm, e, ELE_DEL); @@ -174,10 +175,10 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) v = l->v; v2 = l->next->v; if (BMO_elem_flag_test(bm, v, ELE_DEL)) { - v = BMO_slot_map_ptr_get(bm, op, "targetmap", v); + v = BMO_slot_map_elem_get(slot_targetmap, v); } if (BMO_elem_flag_test(bm, v2, ELE_DEL)) { - v2 = BMO_slot_map_ptr_get(bm, op, "targetmap", v2); + v2 = BMO_slot_map_elem_get(slot_targetmap, v2); } e2 = v != v2 ? BM_edge_exists(v, v2) : NULL; @@ -207,13 +208,13 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) v2 = loops[1]->v; if (BMO_elem_flag_test(bm, v, ELE_DEL)) { - v = BMO_slot_map_ptr_get(bm, op, "targetmap", v); + v = BMO_slot_map_elem_get(slot_targetmap, v); } if (BMO_elem_flag_test(bm, v2, ELE_DEL)) { - v2 = BMO_slot_map_ptr_get(bm, op, "targetmap", v2); + v2 = BMO_slot_map_elem_get(slot_targetmap, v2); } - f2 = BM_face_create_ngon(bm, v, v2, edges, a, TRUE); + f2 = BM_face_create_ngon(bm, v, v2, edges, a, BM_CREATE_NO_DOUBLE); if (f2 && (f2 != f)) { BM_elem_attrs_copy(bm, bm, f, f2); @@ -257,19 +258,19 @@ void bmo_pointmerge_facedata_exec(BMesh *bm, BMOperator *op) { BMOIter siter; BMIter iter; - BMVert *v, *snapv; + BMVert *v, *vert_snap; BMLoop *l, *firstl = NULL; float fac; int i, tot; - snapv = BMO_iter_new(&siter, bm, op, "snapv", BM_VERT); - tot = BM_vert_face_count(snapv); + vert_snap = BMO_slot_buffer_get_single(BMO_slot_get(op->slots_in, "vert_snap")); + tot = BM_vert_face_count(vert_snap); if (!tot) return; fac = 1.0f / tot; - BM_ITER_ELEM (l, &iter, snapv, BM_LOOPS_OF_VERT) { + BM_ITER_ELEM (l, &iter, vert_snap, BM_LOOPS_OF_VERT) { if (!firstl) { firstl = l; } @@ -290,7 +291,7 @@ void bmo_pointmerge_facedata_exec(BMesh *bm, BMOperator *op) } } - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { if (l == firstl) { continue; @@ -318,7 +319,7 @@ void bmo_average_vert_facedata_exec(BMesh *bm, BMOperator *op) type = bm->ldata.layers[i].type; CustomData_data_initminmax(type, &min, &max); - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { block = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i); CustomData_data_dominmax(type, block, &min, &max); @@ -329,7 +330,7 @@ void bmo_average_vert_facedata_exec(BMesh *bm, BMOperator *op) CustomData_data_multiply(type, &max, 0.5f); CustomData_data_add(type, &min, &max); - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { block = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i); CustomData_data_copy_value(type, &min, block); @@ -342,21 +343,24 @@ void bmo_pointmerge_exec(BMesh *bm, BMOperator *op) { BMOperator weldop; BMOIter siter; - BMVert *v, *snapv = NULL; + BMVert *v, *vert_snap = NULL; float vec[3]; + BMOpSlot *slot_targetmap; - BMO_slot_vec_get(op, "merge_co", vec); + BMO_slot_vec_get(op->slots_in, "merge_co", vec); //BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges"); BMO_op_init(bm, &weldop, op->flag, "weld_verts"); - - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { - if (!snapv) { - snapv = v; - copy_v3_v3(snapv->co, vec); + + slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap"); + + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { + if (!vert_snap) { + vert_snap = v; + copy_v3_v3(vert_snap->co, vec); } else { - BMO_slot_map_ptr_insert(bm, &weldop, "targetmap", v, snapv); + BMO_slot_map_elem_insert(&weldop, slot_targetmap, v, vert_snap); } } @@ -373,11 +377,13 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) BLI_array_declare(edges); float min[3], max[3], center[3]; int i, tot; + BMOpSlot *slot_targetmap; BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges"); BMO_op_init(bm, &weldop, op->flag, "weld_verts"); + slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap"); - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK); BMW_init(&walker, bm, BMW_SHELL, BMW_MASK_NOP, EDGE_MARK, BMW_MASK_NOP, @@ -408,9 +414,9 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) copy_v3_v3(edges[i]->v2->co, center); if (edges[i]->v1 != edges[0]->v1) - BMO_slot_map_ptr_insert(bm, &weldop, "targetmap", edges[i]->v1, edges[0]->v1); + BMO_slot_map_elem_insert(&weldop, slot_targetmap, edges[i]->v1, edges[0]->v1); if (edges[i]->v2 != edges[0]->v1) - BMO_slot_map_ptr_insert(bm, &weldop, "targetmap", edges[i]->v2, edges[0]->v1); + BMO_slot_map_elem_insert(&weldop, slot_targetmap, edges[i]->v2, edges[0]->v1); } } @@ -436,7 +442,7 @@ static void bmo_collapsecon_do_layer(BMesh *bm, BMOperator *op, int layer) /* clear all short flags */ BMO_mesh_flag_disable_all(bm, op, BM_ALL, (1 << 16) - 1); - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK); BMW_init(&walker, bm, BMW_LOOPDATA_ISLAND, BMW_MASK_NOP, EDGE_MARK, BMW_MASK_NOP, @@ -486,31 +492,32 @@ void bmo_collapse_uvs_exec(BMesh *bm, BMOperator *op) } } -static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, BMOperator *optarget, const char *targetmapname) +static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, + BMOperator *optarget, BMOpSlot *optarget_slot) { BMVert **verts; int verts_len; int i, j, keepvert = 0; - const float dist = BMO_slot_float_get(op, "dist"); + const float dist = BMO_slot_float_get(op->slots_in, "dist"); const float dist3 = dist * 3.0f; /* Test whether keep_verts arg exists and is non-empty */ - if (BMO_slot_exists(op, "keep_verts")) { + if (BMO_slot_exists(op->slots_in, "keep_verts")) { BMOIter oiter; - keepvert = BMO_iter_new(&oiter, bm, op, "keep_verts", BM_VERT) != NULL; + keepvert = BMO_iter_new(&oiter, op->slots_in, "keep_verts", BM_VERT) != NULL; } /* get the verts as an array we can sort */ - verts = BMO_slot_as_arrayN(op, "verts", &verts_len); + verts = BMO_slot_as_arrayN(op->slots_in, "verts", &verts_len); /* sort by vertex coordinates added together */ qsort(verts, verts_len, sizeof(BMVert *), vergaverco); /* Flag keep_verts */ if (keepvert) { - BMO_slot_buffer_flag_enable(bm, op, "keep_verts", BM_VERT, VERT_KEEP); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "keep_verts", BM_VERT, VERT_KEEP); } for (i = 0; i < verts_len; i++) { @@ -547,7 +554,7 @@ static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, BMOperator *opt BMO_elem_flag_enable(bm, v_other, VERT_DOUBLE); BMO_elem_flag_enable(bm, v_check, VERT_TARGET); - BMO_slot_map_ptr_insert(bm, optarget, targetmapname, v_other, v_check); + BMO_slot_map_elem_insert(optarget, optarget_slot, v_other, v_check); } } } @@ -558,9 +565,12 @@ static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, BMOperator *opt void bmo_remove_doubles_exec(BMesh *bm, BMOperator *op) { BMOperator weldop; + BMOpSlot *slot_targetmap; BMO_op_init(bm, &weldop, op->flag, "weld_verts"); - bmesh_find_doubles_common(bm, op, &weldop, "targetmap"); + slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap"); + bmesh_find_doubles_common(bm, op, + &weldop, slot_targetmap); BMO_op_exec(bm, &weldop); BMO_op_finish(bm, &weldop); } @@ -568,7 +578,10 @@ void bmo_remove_doubles_exec(BMesh *bm, BMOperator *op) void bmo_find_doubles_exec(BMesh *bm, BMOperator *op) { - bmesh_find_doubles_common(bm, op, op, "targetmapout"); + BMOpSlot *slot_targetmap_out; + slot_targetmap_out = BMO_slot_get(op->slots_out, "targetmap.out"); + bmesh_find_doubles_common(bm, op, + op, slot_targetmap_out); } void bmo_automerge_exec(BMesh *bm, BMOperator *op) @@ -580,7 +593,7 @@ void bmo_automerge_exec(BMesh *bm, BMOperator *op) /* The "verts" input sent to this op is the set of verts that * can be merged away into any other verts. Mark all other verts * as VERT_KEEP. */ - BMO_slot_buffer_flag_enable(bm, op, "verts", BM_VERT, VERT_IN); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_IN); BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { if (!BMO_elem_flag_test(bm, v, VERT_IN)) { BMO_elem_flag_enable(bm, v, VERT_KEEP); @@ -590,12 +603,14 @@ void bmo_automerge_exec(BMesh *bm, BMOperator *op) /* Search for doubles among all vertices, but only merge non-VERT_KEEP * vertices into VERT_KEEP vertices. */ BMO_op_initf(bm, &findop, op->flag, "find_doubles verts=%av keep_verts=%fv", VERT_KEEP); - BMO_slot_copy(op, &findop, "dist", "dist"); + BMO_slot_copy(op, slots_in, "dist", + &findop, slots_in, "dist"); BMO_op_exec(bm, &findop); /* weld the vertices */ BMO_op_init(bm, &weldop, op->flag, "weld_verts"); - BMO_slot_copy(&findop, &weldop, "targetmapout", "targetmap"); + BMO_slot_copy(&findop, slots_out, "targetmap.out", + &weldop, slots_in, "targetmap"); BMO_op_exec(bm, &weldop); BMO_op_finish(bm, &findop); diff --git a/source/blender/bmesh/operators/bmo_similar.c b/source/blender/bmesh/operators/bmo_similar.c index df03e50d2c4..548e1adf17d 100644 --- a/source/blender/bmesh/operators/bmo_similar.c +++ b/source/blender/bmesh/operators/bmo_similar.c @@ -103,10 +103,10 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) SimSel_FaceExt *f_ext = NULL; int *indices = NULL; float t_no[3]; /* temporary normal */ - const int type = BMO_slot_int_get(op, "type"); - const float thresh = BMO_slot_float_get(op, "thresh"); + const int type = BMO_slot_int_get(op->slots_in, "type"); + const float thresh = BMO_slot_float_get(op->slots_in, "thresh"); const float thresh_radians = thresh * (float)M_PI; - const int compare = BMO_slot_int_get(op, "compare"); + const int compare = BMO_slot_int_get(op->slots_in, "compare"); /* initial_elem - other_elem */ float delta_fl; @@ -121,7 +121,7 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) * so the overall complexity will be less than $O(mn)$ where is the total number of selected faces, * and n is the total number of faces */ - BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { + BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) { if (!BMO_elem_flag_test(bm, fs, FACE_MARK)) { /* is this really needed ? */ BMO_elem_flag_enable(bm, fs, FACE_MARK); num_sels++; @@ -256,7 +256,7 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) MEM_freeN(indices); /* transfer all marked faces to the output slot */ - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_MARK); #undef FACE_MARK } @@ -299,9 +299,9 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) float angle; int num_sels = 0, num_total = 0; - const int type = BMO_slot_int_get(op, "type"); - const float thresh = BMO_slot_float_get(op, "thresh"); - const int compare = BMO_slot_int_get(op, "compare"); + const int type = BMO_slot_int_get(op->slots_in, "type"); + const float thresh = BMO_slot_float_get(op->slots_in, "thresh"); + const int compare = BMO_slot_int_get(op->slots_in, "compare"); /* initial_elem - other_elem */ float delta_fl; @@ -324,7 +324,7 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) num_total = BM_mesh_elem_count(bm, BM_EDGE); /* iterate through all selected edges and mark them */ - BMO_ITER (es, &es_iter, bm, op, "edges", BM_EDGE) { + BMO_ITER (es, &es_iter, op->slots_in, "edges", BM_EDGE) { BMO_elem_flag_enable(bm, es, EDGE_MARK); num_sels++; } @@ -474,7 +474,7 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) MEM_freeN(indices); /* transfer all marked edges to the output slot */ - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_MARK); #undef EDGE_MARK } @@ -507,10 +507,10 @@ void bmo_similar_verts_exec(BMesh *bm, BMOperator *op) SimSel_VertExt *v_ext = NULL; int *indices = NULL; int num_total = 0, num_sels = 0, i = 0, idx = 0; - const int type = BMO_slot_int_get(op, "type"); - const float thresh = BMO_slot_float_get(op, "thresh"); + const int type = BMO_slot_int_get(op->slots_in, "type"); + const float thresh = BMO_slot_float_get(op->slots_in, "thresh"); const float thresh_radians = thresh * (float)M_PI; - const int compare = BMO_slot_int_get(op, "compare"); + const int compare = BMO_slot_int_get(op->slots_in, "compare"); /* initial_elem - other_elem */ // float delta_fl; @@ -519,7 +519,7 @@ void bmo_similar_verts_exec(BMesh *bm, BMOperator *op) num_total = BM_mesh_elem_count(bm, BM_VERT); /* iterate through all selected edges and mark them */ - BMO_ITER (vs, &vs_iter, bm, op, "verts", BM_VERT) { + BMO_ITER (vs, &vs_iter, op->slots_in, "verts", BM_VERT) { BMO_elem_flag_enable(bm, vs, VERT_MARK); num_sels++; } @@ -608,7 +608,7 @@ void bmo_similar_verts_exec(BMesh *bm, BMOperator *op) MEM_freeN(indices); MEM_freeN(v_ext); - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); #undef VERT_MARK } diff --git a/source/blender/bmesh/operators/bmo_slide.c b/source/blender/bmesh/operators/bmo_slide.c index 6db76119205..ea9f9bf9eba 100644 --- a/source/blender/bmesh/operators/bmo_slide.c +++ b/source/blender/bmesh/operators/bmo_slide.c @@ -53,11 +53,10 @@ void bmo_slide_vert_exec(BMesh *bm, BMOperator *op) int selected_edges = 0; /* Get slide amount */ - const float distance_t = BMO_slot_float_get(op, "distance_t"); + const float factor = BMO_slot_float_get(op->slots_in, "factor"); /* Get start vertex */ - vertex = BMO_iter_new(&oiter, bm, op, "vert", BM_VERT); - + vertex = BMO_slot_buffer_get_single(BMO_slot_get(op->slots_in, "vert")); if (!vertex) { if (G.debug & G_DEBUG) { @@ -67,15 +66,13 @@ void bmo_slide_vert_exec(BMesh *bm, BMOperator *op) return; } + /* BMESH_TODO - this is odd, it only uses one edge, why take a list at all? */ /* Count selected edges */ - BMO_ITER (h, &oiter, bm, op, "edge", BM_VERT | BM_EDGE) { - switch (h->htype) { - case BM_EDGE: - selected_edges++; - /* Mark all selected edges (cast BMHeader->BMEdge) */ - BMO_elem_flag_enable(bm, (BMElemF *)h, EDGE_MARK); - break; - } + BMO_ITER (h, &oiter, op->slots_in, "edges", BM_EDGE) { + selected_edges++; + /* Mark all selected edges (cast BMHeader->BMEdge) */ + BMO_elem_flag_enable(bm, (BMElemF *)h, EDGE_MARK); + break; } /* Only allow sliding if an edge is selected */ @@ -104,11 +101,11 @@ void bmo_slide_vert_exec(BMesh *bm, BMOperator *op) BMO_elem_flag_enable(bm, vertex, VERT_MARK); /* Interpolate */ - interp_v3_v3v3(vertex->co, vertex->co, other->co, distance_t); + interp_v3_v3v3(vertex->co, vertex->co, other->co, factor); } /* Return the new edge. The same previously marked with VERT_MARK */ - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); return; } diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c index 51b9adb5de3..4a367a8fd6f 100644 --- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c +++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c @@ -43,8 +43,8 @@ #include "intern/bmesh_operators_private.h" /* own include */ -#define SMOOTH_LAPLACIAN_AREA_FACTOR 4.0f -#define SMOOTH_LAPLACIAN_EDGE_FACTOR 2.0f +// #define SMOOTH_LAPLACIAN_AREA_FACTOR 4.0f /* UNUSED */ +// #define SMOOTH_LAPLACIAN_EDGE_FACTOR 2.0f /* UNUSED */ #define SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE 1.8f #define SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE 0.15f @@ -78,8 +78,8 @@ static void delete_laplacian_system(LaplacianSystem *sys); static void delete_void_pointer(void *data); static void fill_laplacian_matrix(LaplacianSystem *sys); static void memset_laplacian_system(LaplacianSystem *sys, int val); -static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int volumepreservation); -static void volume_preservation(BMesh *bm, BMOperator *op, float vini, float vend, int usex, int usey, int usez); +static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int preserve_volume); +static void volume_preservation(BMOperator *op, float vini, float vend, int usex, int usey, int usez); static void delete_void_pointer(void *data) { @@ -455,7 +455,7 @@ static float compute_volume(BMesh *bm) return fabs(vol); } -static void volume_preservation(BMesh *bm, BMOperator *op, float vini, float vend, int usex, int usey, int usez) +static void volume_preservation(BMOperator *op, float vini, float vend, int usex, int usey, int usez) { float beta; BMOIter siter; @@ -463,9 +463,9 @@ static void volume_preservation(BMesh *bm, BMOperator *op, float vini, float ven if (vend != 0.0f) { beta = pow(vini / vend, 1.0f / 3.0f); - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { if (usex) { - v->co[0] *= beta; + v->co[0] *= beta; } if (usey) { v->co[1] *= beta; @@ -478,7 +478,7 @@ static void volume_preservation(BMesh *bm, BMOperator *op, float vini, float ven } } -static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int volumepreservation) +static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int preserve_volume) { int m_vertex_id; float leni, lene; @@ -509,10 +509,10 @@ static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez } } - if (volumepreservation) { + if (preserve_volume) { vini = compute_volume(sys->bm); } - BMO_ITER (v, &siter, sys->bm, sys->op, "verts", BM_VERT) { + BMO_ITER (v, &siter, sys->op->slots_in, "verts", BM_VERT) { m_vertex_id = BM_elem_index_get(v); if (sys->zerola[m_vertex_id] == 0) { if (usex) { @@ -526,9 +526,9 @@ static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez } } } - if (volumepreservation) { + if (preserve_volume) { vend = compute_volume(sys->bm); - volume_preservation(sys->bm, sys->op, vini, vend, usex, usey, usez); + volume_preservation(sys->op, vini, vend, usex, usey, usez); } } @@ -537,13 +537,14 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) { int i; int m_vertex_id; - int usex, usey, usez, volumepreservation; + int usex, usey, usez, preserve_volume; float lambda, lambda_border; float w; BMOIter siter; BMVert *v; LaplacianSystem *sys; + if (bm->totface == 0) return; sys = init_laplacian_system(bm->totedge, bm->totface, bm->totvert); if (!sys) return; sys->bm = bm; @@ -552,13 +553,13 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) memset_laplacian_system(sys, 0); BM_mesh_elem_index_ensure(bm, BM_VERT); - lambda = BMO_slot_float_get(op, "lambda"); - lambda_border = BMO_slot_float_get(op, "lambda_border"); + lambda = BMO_slot_float_get(op->slots_in, "lambda"); + lambda_border = BMO_slot_float_get(op->slots_in, "lambda_border"); sys->min_area = 0.00001f; - usex = BMO_slot_bool_get(op, "use_x"); - usey = BMO_slot_bool_get(op, "use_y"); - usez = BMO_slot_bool_get(op, "use_z"); - volumepreservation = BMO_slot_bool_get(op, "volume_preservation"); + usex = BMO_slot_bool_get(op->slots_in, "use_x"); + usey = BMO_slot_bool_get(op->slots_in, "use_y"); + usez = BMO_slot_bool_get(op->slots_in, "use_z"); + preserve_volume = BMO_slot_bool_get(op->slots_in, "preserve_volume"); nlNewContext(); @@ -573,7 +574,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) for (i = 0; i < bm->totvert; i++) { nlLockVariable(i); } - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { m_vertex_id = BM_elem_index_get(v); nlUnlockVariable(m_vertex_id); nlSetVariable(0, m_vertex_id, v->co[0]); @@ -583,7 +584,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) nlBegin(NL_MATRIX); init_laplacian_matrix(sys); - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { m_vertex_id = BM_elem_index_get(v); nlRightHandSideAdd(0, m_vertex_id, v->co[0]); nlRightHandSideAdd(1, m_vertex_id, v->co[1]); @@ -612,7 +613,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) nlEnd(NL_SYSTEM); if (nlSolveAdvanced(NULL, NL_TRUE) ) { - validate_solution(sys, usex, usey, usez, volumepreservation); + validate_solution(sys, usex, usey, usez, preserve_volume); } delete_laplacian_system(sys); diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index 346daf830d0..7407eb4423a 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -165,7 +165,7 @@ static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), const SubDPar } /* apply the new difference to the rest of the shape keys, - * note that this doent take rotations into account, we _could_ support + * note that this dosn't take rotations into account, we _could_ support * this by getting the normals and coords for each shape key and * re-calculate the smooth value for each but this is quite involved. * for now its ok to simply apply the difference IMHO - campbell */ @@ -225,8 +225,9 @@ static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge, BMVert *ev; float percent, percent2 = 0.0f; - if (BMO_elem_flag_test(bm, edge, EDGE_PERCENT) && totpoint == 1) - percent = BMO_slot_map_float_get(bm, params->op, "edgepercents", edge); + if (BMO_elem_flag_test(bm, edge, EDGE_PERCENT) && totpoint == 1) { + percent = BMO_slot_map_float_get(params->slot_edge_percents, edge); + } else { percent = 1.0f / (float)(totpoint + 1 - curpoint); percent2 = (float)(curpoint + 1) / (float)(totpoint + 1); @@ -714,21 +715,22 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BMFace *face; BLI_array_declare(verts); float smooth, fractal, along_normal; - int use_sphere, cornertype, use_singleedge, use_gridfill; + int use_sphere, cornertype, use_single_edge, use_grid_fill, use_only_quads; int skey, seed, i, j, matched, a, b, numcuts, totesel; - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, SUBD_SPLIT); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT); - numcuts = BMO_slot_int_get(op, "numcuts"); - seed = BMO_slot_int_get(op, "seed"); - smooth = BMO_slot_float_get(op, "smooth"); - fractal = BMO_slot_float_get(op, "fractal"); - along_normal = BMO_slot_float_get(op, "along_normal"); - cornertype = BMO_slot_int_get(op, "quadcornertype"); + numcuts = BMO_slot_int_get(op->slots_in, "cuts"); + seed = BMO_slot_int_get(op->slots_in, "seed"); + smooth = BMO_slot_float_get(op->slots_in, "smooth"); + fractal = BMO_slot_float_get(op->slots_in, "fractal"); + along_normal = BMO_slot_float_get(op->slots_in, "along_normal"); + cornertype = BMO_slot_int_get(op->slots_in, "quad_corner_type"); - use_singleedge = BMO_slot_bool_get(op, "use_singleedge"); - use_gridfill = BMO_slot_bool_get(op, "use_gridfill"); - use_sphere = BMO_slot_bool_get(op, "use_sphere"); + use_single_edge = BMO_slot_bool_get(op->slots_in, "use_single_edge"); + use_grid_fill = BMO_slot_bool_get(op->slots_in, "use_grid_fill"); + use_only_quads = BMO_slot_bool_get(op->slots_in, "use_only_quads"); + use_sphere = BMO_slot_bool_get(op->slots_in, "use_sphere"); BLI_srandom(seed); @@ -746,7 +748,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) break; } - if (use_singleedge) { + if (use_single_edge) { patterns[0] = &quad_1edge; patterns[2] = &tri_1edge; } @@ -755,7 +757,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) patterns[2] = NULL; } - if (use_gridfill) { + if (use_grid_fill) { patterns[3] = &quad_4edge; patterns[5] = &tri_3edge; } @@ -774,10 +776,12 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } /* first go through and tag edges */ - BMO_slot_buffer_from_enabled_flag(bm, op, "edges", BM_EDGE, SUBD_SPLIT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT); params.numcuts = numcuts; params.op = op; + params.slot_edge_percents = BMO_slot_get(op->slots_in, "edge_percents"); + params.slot_custom_patterns = BMO_slot_get(op->slots_in, "custom_patterns"); params.smooth = smooth; params.seed = seed; params.fractal = fractal; @@ -790,10 +794,10 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) params.off[1] = (float)BLI_drand() * 200.0f; params.off[2] = (float)BLI_drand() * 200.0f; - BMO_slot_map_to_flag(bm, op, "custompatterns", + BMO_slot_map_to_flag(bm, op->slots_in, "custom_patterns", BM_FACE, FACE_CUSTOMFILL); - BMO_slot_map_to_flag(bm, op, "edgepercents", + BMO_slot_map_to_flag(bm, op->slots_in, "edge_percents", BM_EDGE, EDGE_PERCENT); @@ -801,6 +805,10 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BMEdge *e1 = NULL, *e2 = NULL; float vec1[3], vec2[3]; + /* skip non-quads if requested */ + if (use_only_quads && face->len != 4) + continue; + /* figure out which pattern to use */ BLI_array_empty(edges); @@ -825,7 +833,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } /* make sure the two edges have a valid angle to each other */ - if (totesel == 2 && BM_edge_share_vert_count(e1, e2)) { + if (totesel == 2 && BM_edge_share_vert_check(e1, e2)) { sub_v3_v3v3(vec1, e1->v2->co, e1->v1->co); sub_v3_v3v3(vec2, e2->v2->co, e2->v1->co); normalize_v3(vec1); @@ -837,8 +845,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } if (BMO_elem_flag_test(bm, face, FACE_CUSTOMFILL)) { - pat = BMO_slot_map_data_get(bm, op, - "custompatterns", face); + pat = BMO_slot_map_data_get(params.slot_custom_patterns, face); for (i = 0; i < pat->len; i++) { matched = 1; for (j = 0; j < pat->len; j++) { @@ -910,11 +917,11 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } } - einput = BMO_slot_get(op, "edges"); + einput = BMO_slot_get(op->slots_in, "edges"); /* go through and split edges */ for (i = 0; i < einput->len; i++) { - edge = ((BMEdge **)einput->data.p)[i]; + edge = einput->data.buf[i]; bm_subdivide_multicut(bm, edge, ¶ms, edge->v1, edge->v2); } @@ -1075,10 +1082,10 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BLI_array_free(loops_split); BLI_array_free(loops); - BMO_slot_buffer_from_enabled_flag(bm, op, "outinner", BM_ALL, ELE_INNER); - BMO_slot_buffer_from_enabled_flag(bm, op, "outsplit", BM_ALL, ELE_SPLIT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_inner.out", BM_ALL_NOLOOP, ELE_INNER); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_split.out", BM_ALL_NOLOOP, ELE_SPLIT); - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, ELE_INNER | ELE_SPLIT | SUBD_SPLIT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_INNER | ELE_SPLIT | SUBD_SPLIT); } /* editmesh-emulating function */ @@ -1086,7 +1093,8 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, float smooth, float fractal, float along_normal, int numcuts, int seltype, int cornertype, - const short use_singleedge, const short use_gridfill, + const short use_single_edge, const short use_grid_fill, + const short use_only_quads, int seed) { BMOperator op; @@ -1095,15 +1103,17 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, BMO_op_initf(bm, &op, BMO_FLAG_DEFAULTS, "subdivide_edges edges=%he " "smooth=%f fractal=%f along_normal=%f " - "numcuts=%i " - "quadcornertype=%i " - "use_singleedge=%b use_gridfill=%b " + "cuts=%i " + "quad_corner_type=%i " + "use_single_edge=%b use_grid_fill=%b " + "use_only_quads=%b " "seed=%i", edge_hflag, smooth, fractal, along_normal, numcuts, cornertype, - use_singleedge, use_gridfill, + use_single_edge, use_grid_fill, + use_only_quads, seed); BMO_op_exec(bm, &op); @@ -1112,7 +1122,7 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, BMOIter iter; BMElem *ele; - for (ele = BMO_iter_new(&iter, bm, &op, "outinner", BM_EDGE | BM_VERT); ele; ele = BMO_iter_step(&iter)) { + for (ele = BMO_iter_new(&iter, op.slots_out, "geom_inner.out", BM_EDGE | BM_VERT); ele; ele = BMO_iter_step(&iter)) { BM_elem_select_set(bm, ele, TRUE); } } @@ -1123,7 +1133,7 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, /* deselect input */ BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE); - for (ele = BMO_iter_new(&iter, bm, &op, "outinner", BM_EDGE | BM_VERT); ele; ele = BMO_iter_step(&iter)) { + for (ele = BMO_iter_new(&iter, op.slots_out, "geom_inner.out", BM_EDGE | BM_VERT); ele; ele = BMO_iter_step(&iter)) { BM_elem_select_set(bm, ele, TRUE); if (ele->head.htype == BM_VERT) { @@ -1158,8 +1168,9 @@ void bmo_bisect_edges_exec(BMesh *bm, BMOperator *op) SubDParams params = {0}; int skey; - params.numcuts = BMO_slot_int_get(op, "numcuts"); + params.numcuts = BMO_slot_int_get(op->slots_in, "cuts"); params.op = op; + params.slot_edge_percents = BMO_slot_get(op->slots_in, "edge_percents"); BM_data_layer_add(bm, &bm->vdata, CD_SHAPEKEY); skey = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY) - 1; @@ -1167,11 +1178,11 @@ void bmo_bisect_edges_exec(BMesh *bm, BMOperator *op) params.origkey = skey; /* go through and split edges */ - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { bm_subdivide_multicut(bm, e, ¶ms, e->v1, e->v2); } - BMO_slot_buffer_from_enabled_flag(bm, op, "outsplit", BM_ALL, ELE_SPLIT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_split.out", BM_ALL_NOLOOP, ELE_SPLIT); BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, skey); } diff --git a/source/blender/bmesh/operators/bmo_subdivide.h b/source/blender/bmesh/operators/bmo_subdivide.h index d4b926b9275..529075aab02 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.h +++ b/source/blender/bmesh/operators/bmo_subdivide.h @@ -39,6 +39,8 @@ typedef struct SubDParams { int seed; int origkey; /* shapekey holding displaced vertex coordinates for current geometry */ BMOperator *op; + BMOpSlot *slot_edge_percents; /* BMO_slot_get(params->op->slots_in, "edge_percents"); */ + BMOpSlot *slot_custom_patterns; /* BMO_slot_get(params->op->slots_in, "custom_patterns"); */ float off[3]; } SubDParams; diff --git a/source/blender/bmesh/operators/bmo_symmetrize.c b/source/blender/bmesh/operators/bmo_symmetrize.c index a428405fb8b..248c7268ac6 100644 --- a/source/blender/bmesh/operators/bmo_symmetrize.c +++ b/source/blender/bmesh/operators/bmo_symmetrize.c @@ -96,7 +96,7 @@ static void symm_verts_mirror(Symm *symm) symm->vert_symm_map = BLI_ghash_ptr_new(AT); - BMO_ITER (src_v, &oiter, symm->bm, symm->op, "input", BM_VERT) { + BMO_ITER (src_v, &oiter, symm->op->slots_in, "input", BM_VERT) { SymmSide side = symm_co_side(symm, src_v->co); float co[3]; @@ -106,7 +106,7 @@ static void symm_verts_mirror(Symm *symm) copy_v3_v3(co, src_v->co); co[symm->axis] = -co[symm->axis]; - dst_v = BM_vert_create(symm->bm, co, src_v); + dst_v = BM_vert_create(symm->bm, co, src_v, 0); BMO_elem_flag_enable(symm->bm, dst_v, SYMM_OUTPUT_GEOM); BLI_ghash_insert(symm->vert_symm_map, src_v, dst_v); break; @@ -145,7 +145,7 @@ static void symm_split_asymmetric_edges(Symm *symm) symm->edge_split_map = BLI_ghash_ptr_new(AT); - BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) { + BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) { float flipped[3]; copy_v3_v3(flipped, e->v1->co); @@ -183,7 +183,7 @@ static void symm_split_asymmetric_edges(Symm *symm) co[symm->axis] = 0; /* Edge is asymmetric, split it with a new vertex */ - v = BM_vert_create(symm->bm, co, e->v1); + v = BM_vert_create(symm->bm, co, e->v1, 0); BMO_elem_flag_enable(symm->bm, v, SYMM_OUTPUT_GEOM); BLI_ghash_insert(symm->edge_split_map, e, v); } @@ -195,7 +195,7 @@ static void symm_mirror_edges(Symm *symm) BMOIter oiter; BMEdge *e; - BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) { + BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) { BMVert *v1 = NULL, *v2 = NULL; BMEdge *e_new; @@ -203,7 +203,7 @@ static void symm_mirror_edges(Symm *symm) v2 = BLI_ghash_lookup(symm->vert_symm_map, e->v2); if (v1 && v2) { - e_new = BM_edge_create(symm->bm, v1, v2, e, TRUE); + e_new = BM_edge_create(symm->bm, v1, v2, e, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM); } else if (v1 || v2) { @@ -212,18 +212,18 @@ static void symm_mirror_edges(Symm *symm) /* Output the keep side of the split edge */ if (!v1) { - e_new = BM_edge_create(symm->bm, v_split, e->v2, e, TRUE); + e_new = BM_edge_create(symm->bm, v_split, e->v2, e, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM); v1 = v_split; } else { - e_new = BM_edge_create(symm->bm, e->v1, v_split, e, TRUE); + e_new = BM_edge_create(symm->bm, e->v1, v_split, e, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM); v2 = v_split; } /* Output the kill side of the split edge */ - e_new = BM_edge_create(symm->bm, v1, v2, e, TRUE); + e_new = BM_edge_create(symm->bm, v1, v2, e, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM); } } @@ -245,6 +245,8 @@ typedef struct { /* True only if none of the polygon's edges were split */ int already_symmetric; + + BMFace *src_face; } SymmPoly; static void symm_poly_with_splits(const Symm *symm, @@ -255,6 +257,8 @@ static void symm_poly_with_splits(const Symm *symm, BMLoop *l; int i; + out->src_face = f; + /* Count vertices and check for edge splits */ out->len = f->len; out->already_symmetric = TRUE; @@ -351,7 +355,8 @@ static int symm_poly_next_crossing(const Symm *symm, return FALSE; } -static BMFace *symm_face_create_v(BMesh *bm, BMVert **fv, BMEdge **fe, int len) +static BMFace *symm_face_create_v(BMesh *bm, BMFace *example, + BMVert **fv, BMEdge **fe, int len) { BMFace *f_new; int i; @@ -360,11 +365,13 @@ static BMFace *symm_face_create_v(BMesh *bm, BMVert **fv, BMEdge **fe, int len) int j = (i + 1) % len; fe[i] = BM_edge_exists(fv[i], fv[j]); if (!fe[i]) { - fe[i] = BM_edge_create(bm, fv[i], fv[j], NULL, FALSE); + fe[i] = BM_edge_create(bm, fv[i], fv[j], NULL, 0); BMO_elem_flag_enable(bm, fe[i], SYMM_OUTPUT_GEOM); } } - f_new = BM_face_create(bm, fv, fe, len, TRUE); + f_new = BM_face_create(bm, fv, fe, len, BM_CREATE_NO_DOUBLE); + if (example) + BM_elem_attrs_copy(bm, bm, example, f_new); BM_face_select_set(bm, f_new, TRUE); BMO_elem_flag_enable(bm, f_new, SYMM_OUTPUT_GEOM); return f_new; @@ -399,7 +406,7 @@ static void symm_mesh_output_poly_zero_splits(Symm *symm, } } - symm_face_create_v(symm->bm, fv, fe, j); + symm_face_create_v(symm->bm, sp->src_face, fv, fe, j); } static void symm_mesh_output_poly_with_splits(Symm *symm, @@ -422,7 +429,7 @@ static void symm_mesh_output_poly_with_splits(Symm *symm, fv[i] = v; } - symm_face_create_v(symm->bm, fv, fe, segment_len); + symm_face_create_v(symm->bm, sp->src_face, fv, fe, segment_len); /* Output the kill side of the input polygon */ @@ -434,7 +441,7 @@ static void symm_mesh_output_poly_with_splits(Symm *symm, } - symm_face_create_v(symm->bm, fv, fe, segment_len); + symm_face_create_v(symm->bm, sp->src_face, fv, fe, segment_len); } static void symm_mirror_polygons(Symm *symm) @@ -448,7 +455,7 @@ static void symm_mirror_polygons(Symm *symm) BLI_array_declare(fv); BLI_array_declare(fe); - BMO_ITER (f, &oiter, symm->bm, symm->op, "input", BM_FACE) { + BMO_ITER (f, &oiter, symm->op->slots_in, "input", BM_FACE) { BMIter iter; BMLoop *l; int mirror_all = TRUE, ignore_all = TRUE; @@ -482,7 +489,7 @@ static void symm_mirror_polygons(Symm *symm) fv[i] = l->v; } - symm_face_create_v(symm->bm, fv, fe, f->len); + symm_face_create_v(symm->bm, f, fv, fe, f->len); } else if (ignore_all) { BM_face_kill(symm->bm, f); @@ -589,7 +596,7 @@ static void symm_mirror_polygons(Symm *symm) BLI_assert(fv[0] && fv[1] && fv[2]); - symm_face_create_v(symm->bm, fv, fe, 3); + symm_face_create_v(symm->bm, NULL, fv, fe, 3); } } } @@ -607,7 +614,7 @@ static void symm_kill_unused(Symm *symm) BMVert *v; /* Kill unused edges */ - BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) { + BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) { const int crosses = symm_edge_crosses_axis(symm, e); const int symmetric = (crosses && (!BLI_ghash_haskey(symm->edge_split_map, e))); @@ -617,13 +624,13 @@ static void symm_kill_unused(Symm *symm) !symmetric) { /* The edge might be used by a face outside the input set */ - if (BM_edge_face_count(e) == 0) + if (BM_edge_is_wire(e)) BM_edge_kill(symm->bm, e); } } /* Kill unused vertices */ - BMO_ITER (v, &oiter, symm->bm, symm->op, "input", BM_VERT) { + BMO_ITER (v, &oiter, symm->op->slots_in, "input", BM_VERT) { if (symm_co_side(symm, v->co) == SYMM_SIDE_KILL) { if (BM_vert_edge_count(v) == 0) BM_vert_kill(symm->bm, v); @@ -634,7 +641,7 @@ static void symm_kill_unused(Symm *symm) void bmo_symmetrize_exec(BMesh *bm, BMOperator *op) { Symm symm; - BMO_SymmDirection direction = BMO_slot_int_get(op, "direction"); + BMO_SymmDirection direction = BMO_slot_int_get(op->slots_in, "direction"); symm.bm = bm; symm.op = op; @@ -658,6 +665,6 @@ void bmo_symmetrize_exec(BMesh *bm, BMOperator *op) BLI_ghash_free(symm.vert_symm_map, NULL, NULL); BLI_ghash_free(symm.edge_split_map, NULL, NULL); - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, - SYMM_OUTPUT_GEOM); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", + BM_ALL_NOLOOP, SYMM_OUTPUT_GEOM); } diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c index de876477e5a..d20d01af114 100644 --- a/source/blender/bmesh/operators/bmo_triangulate.c +++ b/source/blender/bmesh/operators/bmo_triangulate.c @@ -52,9 +52,10 @@ void bmo_triangulate_exec(BMesh *bm, BMOperator *op) float (*projectverts)[3] = NULL; BLI_array_declare(projectverts); int i; - const int use_beauty = BMO_slot_bool_get(op, "use_beauty"); + const int use_beauty = BMO_slot_bool_get(op->slots_in, "use_beauty"); + BMOpSlot *slot_facemap_out = BMO_slot_get(op->slots_out, "face_map.out"); - for (face = BMO_iter_new(&siter, bm, op, "faces", BM_FACE); face; face = BMO_iter_step(&siter)) { + for (face = BMO_iter_new(&siter, op->slots_in, "faces", BM_FACE); face; face = BMO_iter_step(&siter)) { BLI_array_empty(projectverts); BLI_array_empty(newfaces); @@ -64,16 +65,14 @@ void bmo_triangulate_exec(BMesh *bm, BMOperator *op) BM_face_triangulate(bm, face, projectverts, EDGE_NEW, FACE_NEW, newfaces, use_beauty); - BMO_slot_map_ptr_insert(bm, op, "facemap", face, face); + BMO_slot_map_elem_insert(op, slot_facemap_out, face, face); for (i = 0; newfaces[i]; i++) { - BMO_slot_map_ptr_insert(bm, op, "facemap", - newfaces[i], face); - + BMO_slot_map_elem_insert(op, slot_facemap_out, newfaces[i], face); } } - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EDGE_NEW); - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_NEW); BLI_array_free(projectverts); BLI_array_free(newfaces); @@ -87,9 +86,9 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op) BMEdge *e; int stop = 0; - BMO_slot_buffer_flag_enable(bm, op, "constrain_edges", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "constrain_edges", BM_EDGE, EDGE_MARK); - BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { if (f->len == 3) { BMO_elem_flag_enable(bm, f, FACE_MARK); } @@ -152,7 +151,7 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_EDGE | BM_FACE, ELE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_EDGE | BM_FACE, ELE_NEW); } void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) @@ -170,7 +169,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) BLI_scanfill_begin(&sf_ctx); - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { BMO_elem_flag_enable(bm, e, EDGE_MARK); if (!BLI_smallhash_haskey(&hash, (uintptr_t)e->v1)) { @@ -191,7 +190,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) /* sf_edge->tmp.p = e; */ /* UNUSED */ } - BLI_scanfill_calc(&sf_ctx, FALSE); + BLI_scanfill_calc(&sf_ctx, 0); for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { BMFace *f = BM_face_create_quad_tri(bm, @@ -214,8 +213,8 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) /* clean up fill */ BMO_op_initf(bm, &bmop, op->flag, "beautify_fill faces=%ff constrain_edges=%fe", ELE_NEW, EDGE_MARK); BMO_op_exec(bm, &bmop); - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_FACE | BM_EDGE, ELE_NEW); + BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_FACE | BM_EDGE, ELE_NEW); BMO_op_finish(bm, &bmop); - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_EDGE | BM_FACE, ELE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_EDGE | BM_FACE, ELE_NEW); } diff --git a/source/blender/bmesh/operators/bmo_unsubdivide.c b/source/blender/bmesh/operators/bmo_unsubdivide.c index 3d44feac380..fae7db3d175 100644 --- a/source/blender/bmesh/operators/bmo_unsubdivide.c +++ b/source/blender/bmesh/operators/bmo_unsubdivide.c @@ -39,10 +39,10 @@ void bmo_unsubdivide_exec(BMesh *bm, BMOperator *op) BMVert *v; BMIter iter; - const int iterations = max_ii(1, BMO_slot_int_get(op, "iterations")); + const int iterations = max_ii(1, BMO_slot_int_get(op->slots_in, "iterations")); - BMOpSlot *vinput = BMO_slot_get(op, "verts"); - BMVert **vinput_arr = (BMVert **)vinput->data.p; + BMOpSlot *vinput = BMO_slot_get(op->slots_in, "verts"); + BMVert **vinput_arr = (BMVert **)vinput->data.buf; int v_index; /* tag verts */ diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c index e311b383b86..64dbf0cc0e7 100644 --- a/source/blender/bmesh/operators/bmo_utils.c +++ b/source/blender/bmesh/operators/bmo_utils.c @@ -45,21 +45,21 @@ void bmo_create_vert_exec(BMesh *bm, BMOperator *op) { float vec[3]; - BMO_slot_vec_get(op, "co", vec); + BMO_slot_vec_get(op->slots_in, "co", vec); - BMO_elem_flag_enable(bm, BM_vert_create(bm, vec, NULL), 1); - BMO_slot_buffer_from_enabled_flag(bm, op, "newvertout", BM_VERT, 1); + BMO_elem_flag_enable(bm, BM_vert_create(bm, vec, NULL, 0), 1); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "vert.out", BM_VERT, 1); } -void bmo_transform_exec(BMesh *bm, BMOperator *op) +void bmo_transform_exec(BMesh *UNUSED(bm), BMOperator *op) { BMOIter iter; BMVert *v; float mat[4][4]; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "matrix", mat); - BMO_ITER (v, &iter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &iter, op->slots_in, "verts", BM_VERT) { mul_m4_v3(mat, v->co); } } @@ -68,33 +68,33 @@ void bmo_translate_exec(BMesh *bm, BMOperator *op) { float mat[4][4], vec[3]; - BMO_slot_vec_get(op, "vec", vec); + BMO_slot_vec_get(op->slots_in, "vec", vec); unit_m4(mat); copy_v3_v3(mat[3], vec); - BMO_op_callf(bm, op->flag, "transform mat=%m4 verts=%s", mat, op, "verts"); + BMO_op_callf(bm, op->flag, "transform matrix=%m4 verts=%s", mat, op, "verts"); } void bmo_scale_exec(BMesh *bm, BMOperator *op) { float mat[3][3], vec[3]; - BMO_slot_vec_get(op, "vec", vec); + BMO_slot_vec_get(op->slots_in, "vec", vec); unit_m3(mat); mat[0][0] = vec[0]; mat[1][1] = vec[1]; mat[2][2] = vec[2]; - BMO_op_callf(bm, op->flag, "transform mat=%m3 verts=%s", mat, op, "verts"); + BMO_op_callf(bm, op->flag, "transform matrix=%m3 verts=%s", mat, op, "verts"); } void bmo_rotate_exec(BMesh *bm, BMOperator *op) { float vec[3]; - BMO_slot_vec_get(op, "cent", vec); + BMO_slot_vec_get(op->slots_in, "cent", vec); /* there has to be a proper matrix way to do this, but * this is how editmesh did it and I'm too tired to think @@ -102,7 +102,7 @@ void bmo_rotate_exec(BMesh *bm, BMOperator *op) mul_v3_fl(vec, -1.0f); BMO_op_callf(bm, op->flag, "translate verts=%s vec=%v", op, "verts", vec); - BMO_op_callf(bm, op->flag, "transform mat=%s verts=%s", op, "mat", op, "verts"); + BMO_op_callf(bm, op->flag, "transform matrix=%s verts=%s", op, "matrix", op, "verts"); mul_v3_fl(vec, -1.0f); BMO_op_callf(bm, op->flag, "translate verts=%s vec=%v", op, "verts", vec); @@ -113,7 +113,7 @@ void bmo_reverse_faces_exec(BMesh *bm, BMOperator *op) BMOIter siter; BMFace *f; - BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { BM_face_normal_flip(bm, f); } } @@ -122,8 +122,8 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op) { BMOIter siter; BMEdge *e, *e2; - int ccw = BMO_slot_bool_get(op, "ccw"); - int is_single = BMO_slot_buffer_count(bm, op, "edges") == 1; + const int use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw"); + const int is_single = BMO_slot_buffer_count(op->slots_in, "edges") == 1; short check_flag = is_single ? BM_EDGEROT_CHECK_EXISTS : BM_EDGEROT_CHECK_EXISTS | BM_EDGEROT_CHECK_DEGENERATE; @@ -131,7 +131,7 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op) #define EDGE_OUT 1 #define FACE_TAINT 1 - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { /** * this ends up being called twice, could add option to not to call check in * #BM_edge_rotate to get some extra speed */ @@ -144,7 +144,7 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op) BMO_elem_flag_test(bm, fb, FACE_TAINT) == FALSE) { - if (!(e2 = BM_edge_rotate(bm, e, ccw, check_flag))) { + if (!(e2 = BM_edge_rotate(bm, e, use_ccw, check_flag))) { #if 0 BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Could not rotate edge"); return; @@ -162,7 +162,7 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EDGE_OUT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT); #undef EDGE_OUT #undef FACE_TAINT @@ -180,7 +180,7 @@ static void bmo_region_extend_extend(BMesh *bm, BMOperator *op, int usefaces) BMOIter siter; if (!usefaces) { - BMO_ITER (v, &siter, bm, op, "geom", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) { BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) if (!BMO_elem_flag_test(bm, e, SEL_ORIG)) @@ -202,7 +202,7 @@ static void bmo_region_extend_extend(BMesh *bm, BMOperator *op, int usefaces) BMFace *f, *f2; BMLoop *l; - BMO_ITER (f, &siter, bm, op, "geom", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "geom", BM_FACE) { BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { BM_ITER_ELEM (f2, &fiter, l->e, BM_FACES_OF_EDGE) { if (!BM_elem_flag_test(f2, BM_ELEM_HIDDEN)) { @@ -224,7 +224,7 @@ static void bmo_region_extend_constrict(BMesh *bm, BMOperator *op, int usefaces) BMOIter siter; if (!usefaces) { - BMO_ITER (v, &siter, bm, op, "geom", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) { BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) if (!BMO_elem_flag_test(bm, e, SEL_ORIG)) @@ -248,7 +248,7 @@ static void bmo_region_extend_constrict(BMesh *bm, BMOperator *op, int usefaces) BMFace *f, *f2; BMLoop *l; - BMO_ITER (f, &siter, bm, op, "geom", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "geom", BM_FACE) { BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { BM_ITER_ELEM (f2, &fiter, l->e, BM_FACES_OF_EDGE) { if (!BM_elem_flag_test(f2, BM_ELEM_HIDDEN)) { @@ -265,24 +265,24 @@ static void bmo_region_extend_constrict(BMesh *bm, BMOperator *op, int usefaces) void bmo_region_extend_exec(BMesh *bm, BMOperator *op) { - int use_faces = BMO_slot_bool_get(op, "use_faces"); - int constrict = BMO_slot_bool_get(op, "constrict"); + int use_faces = BMO_slot_bool_get(op->slots_in, "use_faces"); + int constrict = BMO_slot_bool_get(op->slots_in, "use_constrict"); - BMO_slot_buffer_flag_enable(bm, op, "geom", BM_ALL, SEL_ORIG); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_ALL_NOLOOP, SEL_ORIG); if (constrict) bmo_region_extend_constrict(bm, op, use_faces); else bmo_region_extend_extend(bm, op, use_faces); - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, SEL_FLAG); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, SEL_FLAG); } /********* righthand faces implementation ****** */ #define FACE_VIS 1 #define FACE_FLAG 2 -#define FACE_MARK 4 +// #define FACE_MARK 4 /* UNUSED */ #define FACE_FLIP 8 /* NOTE: these are the original recalc_face_normals comment in editmesh_mods.c, @@ -314,15 +314,15 @@ void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op) BLI_array_declare(fstack); BMLoop *l, *l2; float maxx, maxx_test, cent[3]; - int i, i_max, flagflip = BMO_slot_bool_get(op, "do_flip"); + int i, i_max, flagflip = BMO_slot_bool_get(op->slots_in, "use_flip"); startf = NULL; maxx = -1.0e10; - BMO_slot_buffer_flag_enable(bm, op, "faces", BM_FACE, FACE_FLAG); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces", BM_FACE, FACE_FLAG); /* find a starting face */ - BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { /* clear dirty flag */ BM_elem_flag_disable(f, BM_ELEM_TAG); @@ -405,7 +405,7 @@ void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op) BLI_array_free(fstack); /* check if we have faces yet to do. if so, recurse */ - BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { if (!BMO_elem_flag_test(bm, f, FACE_VIS)) { bmo_recalc_face_normals_exec(bm, op); break; @@ -413,7 +413,7 @@ void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op) } } -void bmo_smooth_vert_exec(BMesh *bm, BMOperator *op) +void bmo_smooth_vert_exec(BMesh *UNUSED(bm), BMOperator *op) { BMOIter siter; BMIter iter; @@ -421,20 +421,20 @@ void bmo_smooth_vert_exec(BMesh *bm, BMOperator *op) BMEdge *e; BLI_array_declare(cos); float (*cos)[3] = NULL; - float *co, *co2, clipdist = BMO_slot_float_get(op, "clipdist"); + float *co, *co2, clip_dist = BMO_slot_float_get(op->slots_in, "clip_dist"); int i, j, clipx, clipy, clipz; int xaxis, yaxis, zaxis; - clipx = BMO_slot_bool_get(op, "mirror_clip_x"); - clipy = BMO_slot_bool_get(op, "mirror_clip_y"); - clipz = BMO_slot_bool_get(op, "mirror_clip_z"); + clipx = BMO_slot_bool_get(op->slots_in, "mirror_clip_x"); + clipy = BMO_slot_bool_get(op->slots_in, "mirror_clip_y"); + clipz = BMO_slot_bool_get(op->slots_in, "mirror_clip_z"); - xaxis = BMO_slot_bool_get(op, "use_axis_x"); - yaxis = BMO_slot_bool_get(op, "use_axis_y"); - zaxis = BMO_slot_bool_get(op, "use_axis_z"); + xaxis = BMO_slot_bool_get(op->slots_in, "use_axis_x"); + yaxis = BMO_slot_bool_get(op->slots_in, "use_axis_y"); + zaxis = BMO_slot_bool_get(op->slots_in, "use_axis_z"); i = 0; - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { BLI_array_grow_one(cos); co = cos[i]; @@ -454,18 +454,18 @@ void bmo_smooth_vert_exec(BMesh *bm, BMOperator *op) mul_v3_fl(co, 1.0f / (float)j); mid_v3_v3v3(co, co, v->co); - if (clipx && fabsf(v->co[0]) <= clipdist) + if (clipx && fabsf(v->co[0]) <= clip_dist) co[0] = 0.0f; - if (clipy && fabsf(v->co[1]) <= clipdist) + if (clipy && fabsf(v->co[1]) <= clip_dist) co[1] = 0.0f; - if (clipz && fabsf(v->co[2]) <= clipdist) + if (clipz && fabsf(v->co[2]) <= clip_dist) co[2] = 0.0f; i++; } i = 0; - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { if (xaxis) v->co[0] = cos[i][0]; if (yaxis) @@ -489,11 +489,11 @@ void bmo_rotate_uvs_exec(BMesh *bm, BMOperator *op) BMFace *fs; /* current face */ BMIter l_iter; /* iteration loop */ - int dir = BMO_slot_int_get(op, "dir"); + const int use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw"); - BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { + BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) { if (CustomData_has_layer(&(bm->ldata), CD_MLOOPUV)) { - if (dir == DIRECTION_CW) { /* same loops direction */ + if (use_ccw == FALSE) { /* same loops direction */ BMLoop *lf; /* current face loops */ MLoopUV *f_luv; /* first face loop uv */ float p_uv[2]; /* previous uvs */ @@ -517,7 +517,7 @@ void bmo_rotate_uvs_exec(BMesh *bm, BMOperator *op) copy_v2_v2(f_luv->uv, p_uv); } - else if (dir == DIRECTION_CCW) { /* counter loop direction */ + else { /* counter loop direction */ BMLoop *lf; /* current face loops */ MLoopUV *p_luv; /* previous loop uv */ MLoopUV *luv; @@ -556,7 +556,7 @@ void bmo_reverse_uvs_exec(BMesh *bm, BMOperator *op) BLI_array_declare(uvs); float (*uvs)[2] = NULL; - BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { + BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) { if (CustomData_has_layer(&(bm->ldata), CD_MLOOPUV)) { BMLoop *lf; /* current face loops */ int i; @@ -594,11 +594,11 @@ void bmo_rotate_colors_exec(BMesh *bm, BMOperator *op) BMFace *fs; /* current face */ BMIter l_iter; /* iteration loop */ - int dir = BMO_slot_int_get(op, "dir"); + const int use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw"); - BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { + BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) { if (CustomData_has_layer(&(bm->ldata), CD_MLOOPCOL)) { - if (dir == DIRECTION_CW) { /* same loops direction */ + if (use_ccw == FALSE) { /* same loops direction */ BMLoop *lf; /* current face loops */ MLoopCol *f_lcol; /* first face loop color */ MLoopCol p_col; /* previous color */ @@ -622,7 +622,7 @@ void bmo_rotate_colors_exec(BMesh *bm, BMOperator *op) *f_lcol = p_col; } - else if (dir == DIRECTION_CCW) { /* counter loop direction */ + else { /* counter loop direction */ BMLoop *lf; /* current face loops */ MLoopCol *p_lcol; /* previous loop color */ MLoopCol *lcol; @@ -661,7 +661,7 @@ void bmo_reverse_colors_exec(BMesh *bm, BMOperator *op) BLI_array_declare(cols); MLoopCol *cols = NULL; - BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { + BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) { if (CustomData_has_layer(&(bm->ldata), CD_MLOOPCOL)) { BMLoop *lf; /* current face loops */ int i; @@ -701,23 +701,18 @@ typedef struct ElemNode { void bmo_shortest_path_exec(BMesh *bm, BMOperator *op) { - BMOIter vs_iter /* , vs2_iter */; /* selected verts iterator */ BMIter v_iter; /* mesh verts iterator */ - BMVert *vs, *sv, *ev; /* starting vertex, ending vertex */ + BMVert *sv, *ev; /* starting vertex, ending vertex */ BMVert *v; /* mesh vertex */ Heap *h = NULL; ElemNode *vert_list = NULL; int num_total = 0 /*, num_sels = 0 */, i = 0; - const int type = BMO_slot_int_get(op, "type"); + const int type = BMO_slot_int_get(op->slots_in, "type"); - BMO_ITER (vs, &vs_iter, bm, op, "startv", BM_VERT) { - sv = vs; - } - BMO_ITER (vs, &vs_iter, bm, op, "endv", BM_VERT) { - ev = vs; - } + sv = BMO_slot_buffer_get_single(BMO_slot_get(op->slots_in, "vert_start")); + ev = BMO_slot_buffer_get_single(BMO_slot_get(op->slots_in, "vert_end")); num_total = BM_mesh_elem_count(bm, BM_VERT); @@ -795,5 +790,5 @@ void bmo_shortest_path_exec(BMesh *bm, BMOperator *op) BLI_heap_free(h, NULL); MEM_freeN(vert_list); - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } diff --git a/source/blender/bmesh/operators/bmo_wireframe.c b/source/blender/bmesh/operators/bmo_wireframe.c index d572a1c5863..7401704310f 100644 --- a/source/blender/bmesh/operators/bmo_wireframe.c +++ b/source/blender/bmesh/operators/bmo_wireframe.c @@ -77,39 +77,60 @@ static void bm_vert_boundary_tangent(BMVert *v, float r_no[3], float r_no_face[3 } } - l_a = bm_edge_tag_faceloop(e_a); - l_b = bm_edge_tag_faceloop(e_b); + if (e_a && e_b) { + l_a = bm_edge_tag_faceloop(e_a); + l_b = bm_edge_tag_faceloop(e_b); - /* average edge face normal */ - add_v3_v3v3(no_face, l_a->f->no, l_b->f->no); + /* average edge face normal */ + add_v3_v3v3(no_face, l_a->f->no, l_b->f->no); - /* average edge direction */ - v_a = BM_edge_other_vert(e_a, v); - v_b = BM_edge_other_vert(e_b, v); + /* average edge direction */ + v_a = BM_edge_other_vert(e_a, v); + v_b = BM_edge_other_vert(e_b, v); - sub_v3_v3v3(tvec_a, v->co, v_a->co); - sub_v3_v3v3(tvec_b, v_b->co, v->co); - normalize_v3(tvec_a); - normalize_v3(tvec_b); - add_v3_v3v3(no_edge, tvec_a, tvec_b); /* not unit length but this is ok */ + sub_v3_v3v3(tvec_a, v->co, v_a->co); + sub_v3_v3v3(tvec_b, v_b->co, v->co); + normalize_v3(tvec_a); + normalize_v3(tvec_b); + add_v3_v3v3(no_edge, tvec_a, tvec_b); /* not unit length but this is ok */ + /* check are we flipped the right way */ + BM_edge_calc_face_tangent(e_a, l_a, tvec_a); + BM_edge_calc_face_tangent(e_b, l_b, tvec_b); + add_v3_v3(tvec_a, tvec_b); + + *r_va_other = v_a; + *r_vb_other = v_b; + } + else { + /* degenerate case - vertex connects a boundary edged face to other faces, + * so we have only one boundary face - only use it for calculations */ + l_a = bm_edge_tag_faceloop(e_a); + + copy_v3_v3(no_face, l_a->f->no); + + /* edge direction */ + v_a = BM_edge_other_vert(e_a, v); + v_b = NULL; + + sub_v3_v3v3(no_edge, v->co, v_a->co); + + /* check are we flipped the right way */ + BM_edge_calc_face_tangent(e_a, l_a, tvec_a); + + *r_va_other = NULL; + *r_vb_other = NULL; + } /* find the normal */ cross_v3_v3v3(r_no, no_edge, no_face); normalize_v3(r_no); - /* check are we flipped the right way */ - BM_edge_calc_face_tangent(e_a, l_a, tvec_a); - BM_edge_calc_face_tangent(e_b, l_b, tvec_b); - add_v3_v3(tvec_a, tvec_b); - if (dot_v3v3(r_no, tvec_a) > 0.0f) { negate_v3(r_no); } copy_v3_v3(r_no_face, no_face); - *r_va_other = v_a; - *r_vb_other = v_b; } /* check if we are the only tagged loop-face around this edge */ @@ -134,12 +155,12 @@ extern float BM_vert_calc_mean_tagged_edge_length(BMVert *v); void bmo_wireframe_exec(BMesh *bm, BMOperator *op) { - const int use_boundary = BMO_slot_bool_get(op, "use_boundary"); - const int use_even_offset = BMO_slot_bool_get(op, "use_even_offset"); - const int use_relative_offset = BMO_slot_bool_get(op, "use_relative_offset"); - const int use_crease = (BMO_slot_bool_get(op, "use_crease") && + const int use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary"); + const int use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset"); + const int use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset"); + const int use_crease = (BMO_slot_bool_get(op->slots_in, "use_crease") && CustomData_has_layer(&bm->edata, CD_CREASE)); - const float depth = BMO_slot_float_get(op, "thickness"); + const float depth = BMO_slot_float_get(op->slots_in, "thickness"); const float inset = depth; const int totvert_orig = bm->totvert; @@ -184,7 +205,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) /* setup tags, all faces and verts will be tagged which will be duplicated */ BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, FALSE); - BMO_ITER (f_src, &oiter, bm, op, "faces", BM_FACE) { + BMO_ITER (f_src, &oiter, op->slots_in, "faces", BM_FACE) { verts_loop_tot += f_src->len; BM_elem_flag_enable(f_src, BM_ELEM_TAG); BM_ITER_ELEM (l, &itersub, f_src, BM_LOOPS_OF_FACE) { @@ -206,9 +227,9 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) } madd_v3_v3v3fl(tvec, v_src->co, v_src->no, -fac); - verts_neg[i] = BM_vert_create(bm, tvec, v_src); + verts_neg[i] = BM_vert_create(bm, tvec, v_src, 0); madd_v3_v3v3fl(tvec, v_src->co, v_src->no, fac); - verts_pos[i] = BM_vert_create(bm, tvec, v_src); + verts_pos[i] = BM_vert_create(bm, tvec, v_src, 0); } else { /* could skip this */ @@ -230,7 +251,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) verts_loop = MEM_mallocN(sizeof(BMVert **) * verts_loop_tot, __func__); verts_loop_tot = 0; /* count up again */ - BMO_ITER (f_src, &oiter, bm, op, "faces", BM_FACE) { + BMO_ITER (f_src, &oiter, op->slots_in, "faces", BM_FACE) { BM_ITER_ELEM (l, &itersub, f_src, BM_LOOPS_OF_FACE) { BM_elem_index_set(l, verts_loop_tot); /* set_loop */ @@ -246,7 +267,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) } madd_v3_v3v3fl(tvec, l->v->co, tvec, fac); - verts_loop[verts_loop_tot] = BM_vert_create(bm, tvec, l->v); + verts_loop[verts_loop_tot] = BM_vert_create(bm, tvec, l->v, 0); if (use_boundary) { @@ -269,16 +290,18 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) /* similar to code above but different angle calc */ fac = inset; if (use_even_offset) { - fac *= shell_angle_to_dist(((float)M_PI - angle_on_axis_v3v3v3_v3(va_other->co, - l_pair[i]->v->co, - vb_other->co, - no_face)) * 0.5f); + if (va_other) { /* for verts with only one boundary edge - this will be NULL */ + fac *= shell_angle_to_dist(((float)M_PI - angle_on_axis_v3v3v3_v3(va_other->co, + l_pair[i]->v->co, + vb_other->co, + no_face)) * 0.5f); + } } if (use_relative_offset) { fac *= verts_relfac[BM_elem_index_get(l_pair[i]->v)]; } madd_v3_v3v3fl(tvec, l_pair[i]->v->co, tvec, fac); - verts_boundary[BM_elem_index_get(l_pair[i]->v)] = BM_vert_create(bm, tvec, l_pair[i]->v); + verts_boundary[BM_elem_index_get(l_pair[i]->v)] = BM_vert_create(bm, tvec, l_pair[i]->v, 0); } } } @@ -288,7 +311,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) } } - BMO_ITER (f_src, &oiter, bm, op, "faces", BM_FACE) { + BMO_ITER (f_src, &oiter, op->slots_in, "faces", BM_FACE) { BM_elem_flag_disable(f_src, BM_ELEM_TAG); BM_ITER_ELEM (l, &itersub, f_src, BM_LOOPS_OF_FACE) { BMFace *f_new; @@ -400,5 +423,5 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) MEM_freeN(verts_pos); MEM_freeN(verts_loop); - BMO_slot_buffer_from_enabled_hflag(bm, op, "faceout", BM_FACE, BM_ELEM_TAG); + BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG); } diff --git a/source/blender/bmesh/tools/BME_bevel.c b/source/blender/bmesh/tools/BME_bevel.c index a632a4446ed..3f2ca21bcee 100644 --- a/source/blender/bmesh/tools/BME_bevel.c +++ b/source/blender/bmesh/tools/BME_bevel.c @@ -689,8 +689,16 @@ static BMFace *BME_bevel_poly(BMesh *bm, BMFace *f, float value, int options, BM BMO_elem_flag_test(bm, l->v, BME_BEVEL_ORIG) && !BMO_elem_flag_test(bm, l->prev->e, BME_BEVEL_BEVEL)) { - max = 1.0f; - l = BME_bevel_vert(bm, l, value, options, up_vec, td); + /* avoid making double vertices [#33438] */ + BME_TransData *vtd; + vtd = BME_get_transdata(td, l->v); + if (vtd->weight == 0.0f) { + BMO_elem_flag_disable(bm, l->v, BME_BEVEL_BEVEL); + } + else { + max = 1.0f; + l = BME_bevel_vert(bm, l, value, options, up_vec, td); + } } } @@ -1110,10 +1118,13 @@ BMesh *BME_bevel(BMesh *bm, float value, int res, int options, int defgrp_index, td = BME_init_transdata(BLI_MEMARENA_STD_BUFSIZE); /* recursion math courtesy of Martin Poirier (theeth) */ for (i = 0; i < res - 1; i++) { - if (i == 0) fac += 1.0 / 3.0; else fac += 1.0 / (3.0 * i * 2.0); + if (i == 0) fac += 1.0 / 3.0; + else fac += 1.0 / (3.0 * i * 2.0); } d = 1.0 / fac; + BM_mesh_elem_toolflags_ensure(bm); + for (i = 0; i < res || (res == 0 && i == 0); i++) { BMO_push(bm, NULL); BME_bevel_initialize(bm, options, defgrp_index, angle, td); diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c new file mode 100644 index 00000000000..9125800d3e8 --- /dev/null +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -0,0 +1,1835 @@ +/* + * ***** 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. + * + * Contributor(s): + * Joseph Eagar, + * Aleksandr Mokhov, + * Howard Trickey, + * Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/bmesh/tools/bmesh_bevel.c + * \ingroup bmesh + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_array.h" +#include "BLI_math.h" +#include "BLI_memarena.h" + +#include "BKE_customdata.h" + +#include "bmesh.h" + + + +/* experemental - Campbell */ +// #define USE_ALTERNATE_ADJ + +#define BEVEL_EPSILON 1e-6 + +/* for testing */ +// #pragma GCC diagnostic error "-Wpadded" + +/* Constructed vertex, sometimes later instantiated as BMVert */ +typedef struct NewVert { + BMVert *v; + float co[3]; +// int _pad; +} NewVert; + +struct BoundVert; + +/* Data for one end of an edge involved in a bevel */ +typedef struct EdgeHalf { + struct EdgeHalf *next, *prev; /* in CCW order */ + BMEdge *e; /* original mesh edge */ + BMFace *fprev; /* face between this edge and previous, if any */ + BMFace *fnext; /* face between this edge and next, if any */ + struct BoundVert *leftv; /* left boundary vert (looking along edge to end) */ + struct BoundVert *rightv; /* right boundary vert, if beveled */ + short is_bev; /* is this edge beveled? */ + short is_rev; /* is e->v2 the vertex at this end? */ + int seg; /* how many segments for the bevel */ + float offset; /* offset for this edge */ +// int _pad; +} EdgeHalf; + +/* An element in a cyclic boundary of a Vertex Mesh (VMesh) */ +typedef struct BoundVert { + struct BoundVert *next, *prev; /* in CCW order */ + NewVert nv; + EdgeHalf *efirst; /* first of edges attached here: in CCW order */ + EdgeHalf *elast; + EdgeHalf *ebev; /* beveled edge whose left side is attached here, if any */ + int index; /* used for vmesh indexing */ +// int _pad; +} BoundVert; + +/* Mesh structure replacing a vertex */ +typedef struct VMesh { + NewVert *mesh; /* allocated array - size and structure depends on kind */ + BoundVert *boundstart; /* start of boundary double-linked list */ + int count; /* number of vertices in the boundary */ + int seg; /* common # of segments for segmented edges */ + enum { + M_NONE, /* no polygon mesh needed */ + M_POLY, /* a simple polygon */ + M_ADJ, /* "adjacent edges" mesh pattern */ +// M_CROSS, /* "cross edges" mesh pattern */ + M_TRI_FAN, /* a simple polygon - fan filled */ + M_QUAD_STRIP, /* a simple polygon - cut into paralelle strips */ + } mesh_kind; +// int _pad; +} VMesh; + +/* Data for a vertex involved in a bevel */ +typedef struct BevVert { + BMVert *v; /* original mesh vertex */ + int edgecount; /* total number of edges around the vertex */ + int selcount; /* number of selected edges around the vertex */ + EdgeHalf *edges; /* array of size edgecount; CCW order from vertex normal side */ + VMesh *vmesh; /* mesh structure for replacing vertex */ +} BevVert; + +/* Bevel parameters and state */ +typedef struct BevelParams { + /* hash of BevVert for each vertex involved in bevel + * GHash: (key=(BMVert *), value=(BevVert *)) */ + GHash *vert_hash; + MemArena *mem_arena; /* use for all allocs while bevel runs, if we need to free we can switch to mempool */ + + float offset; /* blender units to offset each side of a beveled edge */ + int seg; /* number of segments in beveled edge profile */ +} BevelParams; + +// #pragma GCC diagnostic ignored "-Wpadded" + +//#include "bevdebug.c" + +/* Make a new BoundVert of the given kind, insert it at the end of the circular linked + * list with entry point bv->boundstart, and return it. */ +static BoundVert *add_new_bound_vert(MemArena *mem_arena, VMesh *vm, const float co[3]) +{ + BoundVert *ans = (BoundVert *)BLI_memarena_alloc(mem_arena, sizeof(BoundVert)); + + copy_v3_v3(ans->nv.co, co); + if (!vm->boundstart) { + ans->index = 0; + vm->boundstart = ans; + ans->next = ans->prev = ans; + } + else { + BoundVert *tail = vm->boundstart->prev; + ans->index = tail->index + 1; + ans->prev = tail; + ans->next = vm->boundstart; + tail->next = ans; + vm->boundstart->prev = ans; + } + vm->count++; + return ans; +} + +/* Mesh verts are indexed (i, j, k) where + * i = boundvert index (0 <= i < nv) + * j = ring index (0 <= j <= ns2) + * k = segment index (0 <= k <= ns) + * Not all of these are used, and some will share BMVerts */ +static NewVert *mesh_vert(VMesh *vm, int i, int j, int k) +{ + int nj = (vm->seg / 2) + 1; + int nk = vm->seg + 1; + + return &vm->mesh[i * nk * nj + j * nk + k]; +} + +static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert *eg) +{ + NewVert *nv = mesh_vert(vm, i, j, k); + nv->v = BM_vert_create(bm, nv->co, eg, 0); +} + +static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto, + int ifrom, int jfrom, int kfrom) +{ + NewVert *nvto, *nvfrom; + + nvto = mesh_vert(vm, ito, jto, kto); + nvfrom = mesh_vert(vm, ifrom, jfrom, kfrom); + nvto->v = nvfrom->v; + copy_v3_v3(nvto->co, nvfrom->co); +} + +/* find the EdgeHalf in bv's array that has edge bme */ +static EdgeHalf *find_edge_half(BevVert *bv, BMEdge *bme) +{ + int i; + + for (i = 0; i < bv->edgecount; i++) { + if (bv->edges[i].e == bme) + return &bv->edges[i]; + } + return NULL; +} + +/* Return the next EdgeHalf after from_e that is beveled. + * If from_e is NULL, find the first beveled edge. */ +static EdgeHalf *next_bev(BevVert *bv, EdgeHalf *from_e) +{ + EdgeHalf *e; + + if (from_e == NULL) + from_e = &bv->edges[bv->edgecount - 1]; + e = from_e; + do { + if (e->is_bev) { + return e; + } + } while ((e = e->next) != from_e); + return NULL; +} + +/* find the BevVert corresponding to BMVert bmv */ +static BevVert *find_bevvert(BevelParams *bp, BMVert *bmv) +{ + return BLI_ghash_lookup(bp->vert_hash, bmv); +} + +/* Return a good respresentative face (for materials, etc.) for faces + * created around/near BoundVert v */ +static BMFace *boundvert_rep_face(BoundVert *v) +{ + BMFace *fans = NULL; + BMFace *firstf = NULL; + BMEdge *e1, *e2; + BMFace *f1, *f2; + BMIter iter1, iter2; + + BLI_assert(v->efirst != NULL && v->elast != NULL); + e1 = v->efirst->e; + e2 = v->elast->e; + BM_ITER_ELEM (f1, &iter1, e1, BM_FACES_OF_EDGE) { + if (!firstf) + firstf = f1; + BM_ITER_ELEM (f2, &iter2, e2, BM_FACES_OF_EDGE) { + if (f1 == f2) { + fans = f1; + break; + } + } + } + if (!fans) + fans = firstf; + + return fans; +} + +/** + * Make ngon from verts alone. + * Make sure to properly copy face attributes and do custom data interpolation from + * example face, facerep. + * + * \note ALL face creation goes through this function, this is important to keep! + */ +static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv, BMFace *facerep) +{ + BMIter iter; + BMLoop *l; + BMFace *f; + + if (totv == 3) { + f = BM_face_create_quad_tri_v(bm, vert_arr, 3, facerep, FALSE); + } + else if (totv == 4) { + f = BM_face_create_quad_tri_v(bm, vert_arr, 4, facerep, FALSE); + } + else { + int i; + BMEdge **ee = NULL; + BLI_array_fixedstack_declare(ee, BM_DEFAULT_NGON_STACK_SIZE, totv, __func__); + + for (i = 0; i < totv; i++) { + ee[i] = BM_edge_create(bm, vert_arr[i], vert_arr[(i + 1) % totv], NULL, BM_CREATE_NO_DOUBLE); + } + f = BM_face_create_ngon(bm, vert_arr[0], vert_arr[1], ee, totv, 0); + BLI_array_fixedstack_free(ee); + } + if (facerep && f) { + int has_mdisps = CustomData_has_layer(&bm->ldata, CD_MDISPS); + BM_elem_attrs_copy(bm, bm, facerep, f); + BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { + BM_loop_interp_from_face(bm, l, facerep, TRUE, TRUE); + if (has_mdisps) + BM_loop_interp_multires(bm, l, facerep); + } + } + + /* not essential for bevels own internal logic, + * this is done so the operator can select newly created faces */ + if (f) { + BM_elem_flag_enable(f, BM_ELEM_TAG); + } + + return f; +} + +static BMFace *bev_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, + BMFace *facerep) +{ + BMVert *varr[4] = {v1, v2, v3, v4}; + return bev_create_ngon(bm, varr, v4 ? 4 : 3, facerep); +} + +/* + * Calculate the meeting point between the offset edges for e1 and e2, putting answer in meetco. + * e1 and e2 share vertex v and face f (may be NULL) and viewed from the normal side of + * the bevel vertex, e1 precedes e2 in CCW order. + * If on_right is true, offset edge is on right of both edges, where e1 enters v and + * e2 leave it. If on_right is false, then the offset edge is on the left. + * When offsets are equal, the new point is on the edge bisector, with length offset/sin(angle/2), + * but if the offsets are not equal (allowing for this, as bevel modifier has edge weights that may + * lead to different offsets) then meeting point can be found be intersecting offset lines. + */ +static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, + int on_right, float meetco[3]) +{ + float dir1[3], dir2[3], norm_v[3], norm_perp1[3], norm_perp2[3], + off1a[3], off1b[3], off2a[3], off2b[3], isect2[3]; + + /* get direction vectors for two offset lines */ + sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co); + sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co); + + if (angle_v3v3(dir1, dir2) < 100.0f * (float)BEVEL_EPSILON) { + /* special case: e1 and e2 are parallel; put offset point perp to both, from v. + * need to find a suitable plane. + * if offsets are different, we're out of luck: just use e1->offset */ + if (f) + copy_v3_v3(norm_v, f->no); + else + copy_v3_v3(norm_v, v->no); + cross_v3_v3v3(norm_perp1, dir1, norm_v); + normalize_v3(norm_perp1); + copy_v3_v3(off1a, v->co); + madd_v3_v3fl(off1a, norm_perp1, e1->offset); + copy_v3_v3(meetco, off1a); + } + else { + /* get normal to plane where meet point should be */ + cross_v3_v3v3(norm_v, dir2, dir1); + normalize_v3(norm_v); + if (!on_right) + negate_v3(norm_v); + + /* get vectors perp to each edge, perp to norm_v, and pointing into face */ + if (f) { + copy_v3_v3(norm_v, f->no); + } + cross_v3_v3v3(norm_perp1, dir1, norm_v); + cross_v3_v3v3(norm_perp2, dir2, norm_v); + normalize_v3(norm_perp1); + normalize_v3(norm_perp2); + + /* get points that are offset distances from each line, then another point on each line */ + copy_v3_v3(off1a, v->co); + madd_v3_v3fl(off1a, norm_perp1, e1->offset); + add_v3_v3v3(off1b, off1a, dir1); + copy_v3_v3(off2a, v->co); + madd_v3_v3fl(off2a, norm_perp2, e2->offset); + add_v3_v3v3(off2b, off2a, dir2); + + /* intersect the lines; by construction they should be on the same plane and not parallel */ + if (!isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2)) { + BLI_assert(!"offset_meet failure"); + copy_v3_v3(meetco, off1a); /* just to do something */ + } + } +} + +/* Like offset_meet, but here f1 and f2 must not be NULL and give the + * planes in which to run the offset lines. + * They may not meet exactly: the offsets for the edges may be different + * or both the planes and the lines may be angled so that they can't meet. + * In that case, pick a close point on emid, which should be the dividing + * edge between the two planes. + * TODO: should have a global 'offset consistency' prepass to adjust offset + * widths so that all edges have the same offset at both ends. */ +static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, + BMVert *v, BMFace *f1, BMFace *f2, float meetco[3]) +{ + float dir1[3], dir2[3], dirmid[3], norm_perp1[3], norm_perp2[3], + off1a[3], off1b[3], off2a[3], off2b[3], isect2[3], co[3], + f1no[3], f2no[3]; + int iret; + + BLI_assert(f1 != NULL && f2 != NULL); + + /* get direction vectors for two offset lines */ + sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co); + sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co); + sub_v3_v3v3(dirmid, BM_edge_other_vert(emid->e, v)->co, v->co); + + /* get directions into offset planes */ + /* calculate face normals at corner in case faces are nonplanar */ + cross_v3_v3v3(f1no, dirmid, dir1); + cross_v3_v3v3(f2no, dirmid, dir2); + cross_v3_v3v3(norm_perp1, dir1, f1no); + normalize_v3(norm_perp1); + cross_v3_v3v3(norm_perp2, dir2, f2no); + normalize_v3(norm_perp2); + + /* get points that are offset distances from each line, then another point on each line */ + copy_v3_v3(off1a, v->co); + madd_v3_v3fl(off1a, norm_perp1, e1->offset); + sub_v3_v3v3(off1b, off1a, dir1); + copy_v3_v3(off2a, v->co); + madd_v3_v3fl(off2a, norm_perp2, e2->offset); + add_v3_v3v3(off2b, off2a, dir2); + + if (angle_v3v3(dir1, dir2) < 100.0f * (float)BEVEL_EPSILON) { + /* lines are parallel; off1a is a good meet point */ + copy_v3_v3(meetco, off1a); + } + else { + iret = isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2); + if (iret == 0) { + /* lines colinear: another test says they are parallel. so shouldn't happen */ + copy_v3_v3(meetco, off1a); + } + else if (iret == 2) { + /* lines are not coplanar; meetco and isect2 are nearest to first and second lines */ + if (len_v3v3(meetco, isect2) > 100.0f * (float)BEVEL_EPSILON) { + /* offset lines don't meet: project average onto emid; this is not ideal (see TODO above) */ + mid_v3_v3v3(co, meetco, isect2); + closest_to_line_v3(meetco, co, v->co, BM_edge_other_vert(emid->e, v)->co); + } + } + /* else iret == 1 and the lines are coplanar so meetco has the intersection */ + } +} + +/* Offset by e->offset in plane with normal plane_no, on left if left==TRUE, + * else on right. If no is NULL, choose an arbitrary plane different + * from eh's direction. */ +static void offset_in_plane(EdgeHalf *e, const float plane_no[3], int left, float r[3]) +{ + float dir[3], no[3], fdir[3]; + BMVert *v; + + v = e->is_rev ? e->e->v2 : e->e->v1; + + sub_v3_v3v3(dir, BM_edge_other_vert(e->e, v)->co, v->co); + normalize_v3(dir); + if (plane_no) { + copy_v3_v3(no, plane_no); + } + else { + zero_v3(no); + if (fabs(dir[0]) < fabs(dir[1])) + no[0] = 1.0f; + else + no[1] = 1.0f; + } + if (left) + cross_v3_v3v3(fdir, dir, no); + else + cross_v3_v3v3(fdir, no, dir); + normalize_v3(fdir); + copy_v3_v3(r, v->co); + madd_v3_v3fl(r, fdir, e->offset); +} + +/* Calculate coordinates of a point a distance d from v on e->e and return it in slideco */ +static void slide_dist(EdgeHalf *e, BMVert *v, float d, float slideco[3]) +{ + float dir[3], len; + + sub_v3_v3v3(dir, v->co, BM_edge_other_vert(e->e, v)->co); + len = normalize_v3(dir); + if (d > len) + d = len - (float)(50.0 * BEVEL_EPSILON); + copy_v3_v3(slideco, v->co); + madd_v3_v3fl(slideco, dir, -d); +} + +/* Calculate the point on e where line (co_a, co_b) comes closest to and return it in projco */ +static void project_to_edge(BMEdge *e, const float co_a[3], const float co_b[3], float projco[3]) +{ + float otherco[3]; + + if (!isect_line_line_v3(e->v1->co, e->v2->co, co_a, co_b, projco, otherco)) { + BLI_assert(!"project meet failure"); + copy_v3_v3(projco, e->v1->co); + } +} + +/* return 1 if a and b are in CCW order on the normal side of f, + * and -1 if they are reversed, and 0 if there is no shared face f */ +static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f) +{ + BMLoop *la, *lb; + + if (!f) + return 0; + la = BM_face_edge_share_loop(f, a); + lb = BM_face_edge_share_loop(f, b); + if (!la || !lb) + return 0; + return lb->next == la ? 1 : -1; +} + +#ifdef USE_ALTERNATE_ADJ + +static void vmesh_cent(VMesh *vm, float r_cent[3]) +{ + BoundVert *v; + zero_v3(r_cent); + + v = vm->boundstart; + do { + add_v3_v3(r_cent, v->nv.co); + } while ((v = v->next) != vm->boundstart); + mul_v3_fl(r_cent, 1.0f / (float)vm->count); +} + +/** + * + * This example shows a tri fan of quads, + * but could be an NGon fan of quads too. + *
        + *      The whole triangle   X
        + *      represents the      / \
        + *      new bevel face.    /   \
        + *                        /     \
        + *       Split into      /       \
        + *       a quad fan.    /         \
        + *                     /           \
        + *                    /             \
        + *                   /               \
        + *          co_prev +-.             .-+
        + *                 /   `-._     _.-'   \
        + *                / co_cent`-+-'        \
        + *               /           |           \
        + * Quad of      /            |            \
        + * interest -- / ---> X      |             \
        + *            /              |              \
        + *           /               |               \
        + *          /         co_next|                \
        + * co_orig +-----------------+-----------------+
        + *
        + *         For each quad, calcualte UV's based on the following:
        + *           U = k    / (vm->seg * 2)
        + *           V = ring / (vm->seg * 2)
        + *           quad = (co_orig, co_prev, co_cent, co_next)
        + *           ... note that co_cent is the same for all quads in the fan.
        + * 
        + * + */ + +static void get_point_uv(float uv[2], + /* all these args are int's originally + * but pass as floats to the function */ + const float seg, const float ring, const float k) +{ + uv[0] = (ring / seg) * 2.0f; + uv[1] = (k / seg) * 2.0f; +} + +/* TODO: make this a lot smarter!, + * this is the main reason USE_ALTERNATE_ADJ isn't so good right now :S */ +static float get_point_uv_factor(const float uv[2]) +{ + return sinf(1.0f - max_ff(uv[0], uv[1]) / 2.0f); +} + +static void get_point_on_round_edge(const float uv[2], + float quad[4][3], + float r_co[3]) +{ + interp_bilinear_quad_v3(quad, uv[0], uv[1], r_co); +} + +#else /* USE_ALTERNATE_ADJ */ + +/* Fill matrix r_mat so that a point in the sheared parallelogram with corners + * va, vmid, vb (and the 4th that is implied by it being a parallelogram) + * is transformed to the unit square by multiplication with r_mat. + * If it can't be done because the parallelogram is degenerate, return FALSE + * else return TRUE. + * Method: + * Find vo, the origin of the parallelogram with other three points va, vmid, vb. + * Also find vd, which is in direction normal to parallelogram and 1 unit away + * from the origin. + * The quarter circle in first quadrant of unit square will be mapped to the + * quadrant of a sheared ellipse in the parallelgram, using a matrix. + * The matrix mat is calculated to map: + * (0,1,0) -> va + * (1,1,0) -> vmid + * (1,0,0) -> vb + * (0,1,1) -> vd + * We want M to make M*A=B where A has the left side above, as columns + * and B has the right side as columns - both extended into homogeneous coords. + * So M = B*(Ainverse). Doing Ainverse by hand gives the code below. +*/ +static int make_unit_square_map(const float va[3], const float vmid[3], const float vb[3], + float r_mat[4][4]) +{ + float vo[3], vd[3], vb_vmid[3], va_vmid[3], vddir[3]; + + sub_v3_v3v3(va_vmid, vmid, va); + sub_v3_v3v3(vb_vmid, vmid, vb); + if (fabsf(angle_v3v3(va_vmid, vb_vmid) - (float)M_PI) > 100.f *(float)BEVEL_EPSILON) { + sub_v3_v3v3(vo, va, vb_vmid); + cross_v3_v3v3(vddir, vb_vmid, va_vmid); + normalize_v3(vddir); + add_v3_v3v3(vd, vo, vddir); + + /* The cols of m are: {vmid - va, vmid - vb, vmid + vd - va -vb, va + vb - vmid; + * blender transform matrices are stored such that m[i][*] is ith column; + * the last elements of each col remain as they are in unity matrix */ + sub_v3_v3v3(&r_mat[0][0], vmid, va); + r_mat[0][3] = 0.0f; + sub_v3_v3v3(&r_mat[1][0], vmid, vb); + r_mat[1][3] = 0.0f; + add_v3_v3v3(&r_mat[2][0], vmid, vd); + sub_v3_v3(&r_mat[2][0], va); + sub_v3_v3(&r_mat[2][0], vb); + r_mat[2][3] = 0.0f; + add_v3_v3v3(&r_mat[3][0], va, vb); + sub_v3_v3(&r_mat[3][0], vmid); + r_mat[3][3] = 1.0f; + + return TRUE; + } + else + return FALSE; +} + +/* + * Find the point (/n) of the way around the round profile for e, + * where start point is va, midarc point is vmid, and end point is vb. + * Return the answer in profileco. + * If va -- vmid -- vb is approximately a straight line, just + * interpolate along the line. + */ +static void get_point_on_round_edge(EdgeHalf *e, int k, + const float va[3], const float vmid[3], const float vb[3], + float r_co[3]) +{ + float p[3], angle; + float m[4][4]; + int n = e->seg; + + if (make_unit_square_map(va, vmid, vb, m)) { + /* Find point k/(e->seg) along quarter circle from (0,1,0) to (1,0,0) */ + angle = (float)M_PI * (float)k / (2.0f * (float)n); /* angle from y axis */ + p[0] = sinf(angle); + p[1] = cosf(angle); + p[2] = 0.0f; + mul_v3_m4v3(r_co, m, p); + } + else { + /* degenerate case: profile is a line */ + interp_v3_v3v3(r_co, va, vb, (float)k / (float)n); + } +} + +/* Calculate a snapped point to the transformed profile of edge e, extended as + * in a cylinder-like surface in the direction of e. + * co is the point to snap and is modified in place. + * va and vb are the limits of the profile (with peak on e). */ +static void snap_to_edge_profile(EdgeHalf *e, const float va[3], const float vb[3], + float co[3]) +{ + float m[4][4], minv[4][4]; + float edir[3], va0[3], vb0[3], vmid0[3], p[3], snap[3]; + + sub_v3_v3v3(edir, e->e->v1->co, e->e->v2->co); + normalize_v3(edir); + + /* project va and vb onto plane P, with normal edir and containing co */ + closest_to_plane_v3(va0, co, edir, va); + closest_to_plane_v3(vb0, co, edir, vb); + project_to_edge(e->e, va0, vb0, vmid0); + if (make_unit_square_map(va0, vmid0, vb0, m)) { + /* Transform co and project it onto the unit circle. + * Projecting is in fact just normalizing the transformed co */ + if (!invert_m4_m4(minv, m)) { + /* shouldn't happen, by angle test and construction of vd */ + BLI_assert(!"failed inverse during profile snap"); + return; + } + mul_v3_m4v3(p, minv, co); + normalize_v3(p); + mul_v3_m4v3(snap, m, p); + copy_v3_v3(co, snap); + } + else { + /* planar case: just snap to line va--vb */ + closest_to_line_segment_v3(p, co, va, vb); + copy_v3_v3(co, p); + } +} + +#endif /* !USE_ALTERNATE_ADJ */ + +/* Make a circular list of BoundVerts for bv, each of which has the coordinates + * of a vertex on the the boundary of the beveled vertex bv->v. + * Also decide on the mesh pattern that will be used inside the boundary. + * Doesn't make the actual BMVerts */ +static void build_boundary(MemArena *mem_arena, BevVert *bv) +{ + EdgeHalf *efirst, *e; + BoundVert *v; + VMesh *vm; + float co[3]; + const float *no; + float lastd; + + e = efirst = next_bev(bv, NULL); + vm = bv->vmesh; + + BLI_assert(bv->edgecount >= 2); /* since bevel edges incident to 2 faces */ + + if (bv->edgecount == 2 && bv->selcount == 1) { + /* special case: beveled edge meets non-beveled one at valence 2 vert */ + no = e->fprev ? e->fprev->no : (e->fnext ? e->fnext->no : NULL); + offset_in_plane(e, no, TRUE, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = v->elast = v->ebev = e; + e->leftv = v; + no = e->fnext ? e->fnext->no : (e->fprev ? e->fprev->no : NULL); + offset_in_plane(e, no, FALSE, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = v->elast = e; + e->rightv = v; + /* make artifical extra point along unbeveled edge, and form triangle */ + slide_dist(e->next, bv->v, e->offset, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = v->elast = e->next; + e->next->leftv = e->next->rightv = v; + /* could use M_POLY too, but tri-fan looks nicer)*/ + vm->mesh_kind = M_TRI_FAN; + return; + } + + lastd = e->offset; + vm->boundstart = NULL; + do { + if (e->is_bev) { + /* handle only left side of beveled edge e here: next iteration should do right side */ + if (e->prev->is_bev) { + BLI_assert(e->prev != e); /* see: wire edge special case */ + offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = e->prev; + v->elast = v->ebev = e; + e->leftv = v; + e->prev->rightv = v; + } + else { + /* e->prev is not beveled */ + if (e->prev->prev->is_bev) { + BLI_assert(e->prev->prev != e); /* see: edgecount 2, selcount 1 case */ + /* find meet point between e->prev->prev and e and attach e->prev there */ + offset_in_two_planes(e->prev->prev, e, e->prev, bv->v, + e->prev->prev->fnext, e->fprev, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = e->prev->prev; + v->elast = v->ebev = e; + e->leftv = v; + e->prev->leftv = v; + e->prev->prev->rightv = v; + } + else { + /* neither e->prev nor e->prev->prev are beveled: make on-edge on e->prev */ + offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = e->prev; + v->elast = v->ebev = e; + e->leftv = v; + e->prev->leftv = v; + } + } + lastd = len_v3v3(bv->v->co, v->nv.co); + } + else { + /* e is not beveled */ + if (e->next->is_bev) { + /* next iteration will place e between beveled previous and next edges */ + /* do nothing... */ + } + else if (e->prev->is_bev) { + /* on-edge meet between e->prev and e */ + offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = e->prev; + v->elast = e; + e->leftv = v; + e->prev->rightv = v; + } + else { + /* None of e->prev, e, e->next are beveled. + * could either leave alone or add slide points to make + * one polygon around bv->v. For now, we choose latter. + * Could slide to make an even bevel plane but for now will + * just use last distance a meet point moved from bv->v. */ + slide_dist(e, bv->v, lastd, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = v->elast = e; + e->leftv = v; + } + } + } while ((e = e->next) != efirst); + + BLI_assert(vm->count >= 2); + if (vm->count == 2 && bv->edgecount == 3) { + vm->mesh_kind = M_NONE; + } + else if (bv->selcount == 2) { + vm->mesh_kind = M_QUAD_STRIP; + } + else if (efirst->seg == 1 || bv->selcount == 1) { + if (vm->count == 3 && bv->selcount == 1) { + vm->mesh_kind = M_TRI_FAN; + } + else { + vm->mesh_kind = M_POLY; + } + } + else { + vm->mesh_kind = M_ADJ; + } +} + +/* + * Given that the boundary is built and the boundary BMVerts have been made, + * calculate the positions of the interior mesh points for the M_ADJ pattern, + * then make the BMVerts and the new faces. */ +static void bevel_build_rings(BMesh *bm, BevVert *bv) +{ + int k, ring, i, n, ns, ns2, nn; + VMesh *vm = bv->vmesh; + BoundVert *v, *vprev, *vnext; + NewVert *nv, *nvprev, *nvnext; + EdgeHalf *e1, *e2, *epipe; + BMVert *bmv, *bmv1, *bmv2, *bmv3, *bmv4; + BMFace *f; + float co[3], coa[3], cob[3], midco[3]; + float va_pipe[3], vb_pipe[3]; + +#ifdef USE_ALTERNATE_ADJ + /* ordered as follows (orig, prev, center, next)*/ + float quad_plane[4][3]; + float quad_orig[4][3]; +#endif + + +#ifdef USE_ALTERNATE_ADJ + /* the rest are initialized inline, this remains the same for all */ + vmesh_cent(vm, quad_plane[2]); + copy_v3_v3(quad_orig[2], bv->v->co); +#endif + + n = vm->count; + ns = vm->seg; + ns2 = ns / 2; + BLI_assert(n > 2 && ns > 1); + + /* special case: two beveled edges are in line and share a face, making a "pipe" */ + epipe = NULL; + if (bv->selcount > 2) { + for (e1 = &bv->edges[0]; epipe == NULL && e1 != &bv->edges[bv->edgecount]; e1++) { + if (e1->is_bev) { + for (e2 = &bv->edges[0]; e2 != &bv->edges[bv->edgecount]; e2++) { + if (e1 != e2 && e2->is_bev) { + if ((e1->fnext == e2->fprev) || (e1->fprev == e2->fnext)) { + float dir1[3], dir2[3]; + sub_v3_v3v3(dir1, bv->v->co, BM_edge_other_vert(e1->e, bv->v)->co); + sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, bv->v)->co, bv->v->co); + if (angle_v3v3(dir1, dir2) < 100.0f * (float)BEVEL_EPSILON) { + epipe = e1; + break; + } + } + } + } + } + } + } + + /* Make initial rings, going between points on neighbors. + * After this loop, will have coords for all (i, r, k) where + * BoundVert for i has a bevel, 0 <= r <= ns2, 0 <= k <= ns */ + for (ring = 1; ring <= ns2; ring++) { + v = vm->boundstart; + + do { + i = v->index; + if (v->ebev) { + /* get points coords of points a and b, on outer rings + * of prev and next edges, k away from this edge */ + vprev = v->prev; + vnext = v->next; + + if (vprev->ebev) + nvprev = mesh_vert(vm, vprev->index, 0, ns - ring); + else + nvprev = mesh_vert(vm, vprev->index, 0, ns); + copy_v3_v3(coa, nvprev->co); + nv = mesh_vert(vm, i, ring, 0); + copy_v3_v3(nv->co, coa); + nv->v = nvprev->v; + + if (vnext->ebev) + nvnext = mesh_vert(vm, vnext->index, 0, ring); + else + nvnext = mesh_vert(vm, vnext->index, 0, 0); + copy_v3_v3(cob, nvnext->co); + nv = mesh_vert(vm, i, ring, ns); + copy_v3_v3(nv->co, cob); + nv->v = nvnext->v; + +#ifdef USE_ALTERNATE_ADJ + /* plane */ + copy_v3_v3(quad_plane[0], v->nv.co); + mid_v3_v3v3(quad_plane[1], v->nv.co, v->prev->nv.co); + /* quad[2] is set */ + mid_v3_v3v3(quad_plane[3], v->nv.co, v->next->nv.co); + + /* orig */ + copy_v3_v3(quad_orig[0], v->nv.co); /* only shared location between 2 quads */ + project_to_edge(v->ebev->prev->e, v->nv.co, v->prev->nv.co, quad_orig[1]); + project_to_edge(v->ebev->e, v->nv.co, v->next->nv.co, quad_orig[3]); + + //bl_debug_draw_quad_add(UNPACK4(quad_plane)); + //bl_debug_draw_quad_add(UNPACK4(quad_orig)); +#endif + +#ifdef USE_ALTERNATE_ADJ + for (k = 1; k < ns; k++) { + float uv[2]; + float fac; + float co_plane[3]; + float co_orig[3]; + + get_point_uv(uv, v->ebev->seg, ring, k); + get_point_on_round_edge(uv, quad_plane, co_plane); + get_point_on_round_edge(uv, quad_orig, co_orig); + fac = get_point_uv_factor(uv); + interp_v3_v3v3(co, co_plane, co_orig, fac); + copy_v3_v3(mesh_vert(vm, i, ring, k)->co, co); + } +#else + /* TODO: better calculation of new midarc point? */ + project_to_edge(v->ebev->e, coa, cob, midco); + + for (k = 1; k < ns; k++) { + get_point_on_round_edge(v->ebev, k, coa, midco, cob, co); + copy_v3_v3(mesh_vert(vm, i, ring, k)->co, co); + } + + if (v->ebev == epipe) { + /* save profile extremes for later snapping */ + copy_v3_v3(va_pipe, mesh_vert(vm, i, 0, 0)->co); + copy_v3_v3(vb_pipe, mesh_vert(vm, i, 0, ns)->co); + } +#endif + } + } while ((v = v->next) != vm->boundstart); + } + + /* Now make sure cross points of rings share coordinates and vertices. + * After this loop, will have BMVerts for all (i, r, k) where + * i is for a BoundVert that is beveled and has either a predecessor or + * successor BoundVert beveled too, and + * for odd ns: 0 <= r <= ns2, 0 <= k <= ns + * for even ns: 0 <= r < ns2, 0 <= k <= ns except k=ns2 */ + v = vm->boundstart; + do { + i = v->index; + if (v->ebev) { + vprev = v->prev; + vnext = v->next; + if (vprev->ebev) { + for (ring = 1; ring <= ns2; ring++) { + for (k = 1; k <= ns2; k++) { + if (ns % 2 == 0 && (k == ns2 || ring == ns2)) + continue; /* center line is special case: do after the rest are done */ + nv = mesh_vert(vm, i, ring, k); + nvprev = mesh_vert(vm, vprev->index, k, ns - ring); + mid_v3_v3v3(co, nv->co, nvprev->co); + if (epipe) + snap_to_edge_profile(epipe, va_pipe, vb_pipe, co); + +#ifndef USE_ALTERNATE_ADJ + copy_v3_v3(nv->co, co); +#endif + BLI_assert(nv->v == NULL && nvprev->v == NULL); + create_mesh_bmvert(bm, vm, i, ring, k, bv->v); + copy_mesh_vert(vm, vprev->index, k, ns - ring, i, ring, k); + } + } + if (!vprev->prev->ebev) { + for (ring = 1; ring <= ns2; ring++) { + for (k = 1; k <= ns2; k++) { + if (ns % 2 == 0 && (k == ns2 || ring == ns2)) + continue; + create_mesh_bmvert(bm, vm, vprev->index, ring, k, bv->v); + } + } + } + if (!vnext->ebev) { + for (ring = 1; ring <= ns2; ring++) { + for (k = ns - ns2; k < ns; k++) { + if (ns % 2 == 0 && (k == ns2 || ring == ns2)) + continue; + create_mesh_bmvert(bm, vm, i, ring, k, bv->v); + } + } + } + } + } + } while ((v = v->next) != vm->boundstart); + + if (ns % 2 == 0) { + /* Do special case center lines. + * This loop makes verts for (i, ns2, k) for 1 <= k <= ns-1, k!=ns2 + * and for (i, r, ns2) for 1 <= r <= ns2-1, + * whenever i is in a sequence of at least two beveled verts */ + v = vm->boundstart; + do { + i = v->index; + if (v->ebev) { + vprev = v->prev; + vnext = v->next; + for (k = 1; k < ns2; k++) { + nv = mesh_vert(vm, i, k, ns2); + if (vprev->ebev) + nvprev = mesh_vert(vm, vprev->index, ns2, ns - k); + if (vnext->ebev) + nvnext = mesh_vert(vm, vnext->index, ns2, k); + if (vprev->ebev && vnext->ebev) { + mid_v3_v3v3v3(co, nvprev->co, nv->co, nvnext->co); + if (epipe) + snap_to_edge_profile(epipe, va_pipe, vb_pipe, co); +#ifndef USE_ALTERNATE_ADJ + copy_v3_v3(nv->co, co); +#endif + create_mesh_bmvert(bm, vm, i, k, ns2, bv->v); + copy_mesh_vert(vm, vprev->index, ns2, ns - k, i, k, ns2); + copy_mesh_vert(vm, vnext->index, ns2, k, i, k, ns2); + + } + else if (vprev->ebev) { + mid_v3_v3v3(co, nvprev->co, nv->co); + if (epipe) + snap_to_edge_profile(epipe, va_pipe, vb_pipe, co); +#ifndef USE_ALTERNATE_ADJ + copy_v3_v3(nv->co, co); +#endif + create_mesh_bmvert(bm, vm, i, k, ns2, bv->v); + copy_mesh_vert(vm, vprev->index, ns2, ns - k, i, k, ns2); + + create_mesh_bmvert(bm, vm, i, ns2, ns - k, bv->v); + } + else if (vnext->ebev) { + mid_v3_v3v3(co, nv->co, nvnext->co); + if (epipe) + snap_to_edge_profile(epipe, va_pipe, vb_pipe, co); +#ifndef USE_ALTERNATE_ADJ + copy_v3_v3(nv->co, co); +#endif + create_mesh_bmvert(bm, vm, i, k, ns2, bv->v); + copy_mesh_vert(vm, vnext->index, ns2, k, i, k, ns2); + + create_mesh_bmvert(bm, vm, i, ns2, k, bv->v); + } + } + } + } while ((v = v->next) != vm->boundstart); + + /* center point need to be average of all centers of rings */ + /* TODO: this is wrong if not all verts have ebev: could have + * several disconnected sections of mesh. */ + zero_v3(midco); + nn = 0; + v = vm->boundstart; + do { + i = v->index; + if (v->ebev) { + nv = mesh_vert(vm, i, ns2, ns2); + add_v3_v3(midco, nv->co); + nn++; + } + } while ((v = v->next) != vm->boundstart); + mul_v3_fl(midco, 1.0f / nn); + if (epipe) + snap_to_edge_profile(epipe, va_pipe, vb_pipe, midco); + bmv = BM_vert_create(bm, midco, NULL, 0); + v = vm->boundstart; + do { + i = v->index; + if (v->ebev) { + nv = mesh_vert(vm, i, ns2, ns2); + copy_v3_v3(nv->co, midco); + nv->v = bmv; + } + } while ((v = v->next) != vm->boundstart); + } + + /* Make the ring quads */ + for (ring = 0; ring < ns2; ring++) { + v = vm->boundstart; + do { + i = v->index; + f = boundvert_rep_face(v); + if (v->ebev && (v->prev->ebev || v->next->ebev)) { + for (k = 0; k < ns2 + (ns % 2); k++) { + bmv1 = mesh_vert(vm, i, ring, k)->v; + bmv2 = mesh_vert(vm, i, ring, k + 1)->v; + bmv3 = mesh_vert(vm, i, ring + 1, k + 1)->v; + bmv4 = mesh_vert(vm, i, ring + 1, k)->v; + BLI_assert(bmv1 && bmv2 && bmv3 && bmv4); + if (bmv3 == bmv4 || bmv1 == bmv4) + bmv4 = NULL; + bev_create_quad_tri(bm, bmv1, bmv2, bmv3, bmv4, f); + } + } + else if (v->prev->ebev && v->prev->prev->ebev) { + /* finish off a sequence of beveled edges */ + i = v->prev->index; + f = boundvert_rep_face(v->prev); + for (k = ns2 + (ns % 2); k < ns; k++) { + bmv1 = mesh_vert(vm, i, ring, k)->v; + bmv2 = mesh_vert(vm, i, ring, k + 1)->v; + bmv3 = mesh_vert(vm, i, ring + 1, k + 1)->v; + bmv4 = mesh_vert(vm, i, ring + 1, k)->v; + BLI_assert(bmv1 && bmv2 && bmv3 && bmv4); + if (bmv2 == bmv3) { + bmv3 = bmv4; + bmv4 = NULL; + } + bev_create_quad_tri(bm, bmv1, bmv2, bmv3, bmv4, f); + } + } + } while ((v = v->next) != vm->boundstart); + } + + /* Make center ngon if odd number of segments and fully beveled */ + if (ns % 2 == 1 && vm->count == bv->selcount) { + BMVert **vv = NULL; + BLI_array_declare(vv); + + v = vm->boundstart; + do { + i = v->index; + BLI_assert(v->ebev); + BLI_array_append(vv, mesh_vert(vm, i, ns2, ns2)->v); + } while ((v = v->next) != vm->boundstart); + f = boundvert_rep_face(vm->boundstart); + bev_create_ngon(bm, vv, BLI_array_count(vv), f); + + BLI_array_free(vv); + } + + /* Make 'rest-of-vmesh' polygon if not fully beveled */ + if (vm->count > bv->selcount) { + int j; + BMVert **vv = NULL; + BLI_array_declare(vv); + + v = vm->boundstart; + f = boundvert_rep_face(v); + j = 0; + do { + i = v->index; + if (v->ebev) { + if (!v->prev->ebev) { + for (k = 0; k < ns2; k++) { + bmv1 = mesh_vert(vm, i, ns2, k)->v; + if (!bmv1) + bmv1 = mesh_vert(vm, i, 0, k)->v; + if (!(j > 0 && bmv1 == vv[j - 1])) { + BLI_assert(bmv1 != NULL); + BLI_array_append(vv, bmv1); + j++; + } + } + } + bmv1 = mesh_vert(vm, i, ns2, ns2)->v; + if (!bmv1) + bmv1 = mesh_vert(vm, i, 0, ns2)->v; + if (!(j > 0 && bmv1 == vv[j - 1])) { + BLI_assert(bmv1 != NULL); + BLI_array_append(vv, bmv1); + j++; + } + if (!v->next->ebev) { + for (k = ns - ns2; k < ns; k++) { + bmv1 = mesh_vert(vm, i, ns2, k)->v; + if (!bmv1) + bmv1 = mesh_vert(vm, i, 0, k)->v; + if (!(j > 0 && bmv1 == vv[j - 1])) { + BLI_assert(bmv1 != NULL); + BLI_array_append(vv, bmv1); + j++; + } + } + } + } + else { + BLI_assert(mesh_vert(vm, i, 0, 0)->v != NULL); + BLI_array_append(vv, mesh_vert(vm, i, 0, 0)->v); + j++; + } + } while ((v = v->next) != vm->boundstart); + if (vv[0] == vv[j - 1]) + j--; + bev_create_ngon(bm, vv, j, f); + + BLI_array_free(vv); + } +} + +static BMFace *bevel_build_poly_ex(BMesh *bm, BevVert *bv) +{ + BMFace *f; + int n, k; + VMesh *vm = bv->vmesh; + BoundVert *v; + BMVert **vv = NULL; + BLI_array_declare(vv); + + v = vm->boundstart; + n = 0; + do { + /* accumulate vertices for vertex ngon */ + BLI_array_append(vv, v->nv.v); + n++; + if (v->ebev && v->ebev->seg > 1) { + for (k = 1; k < v->ebev->seg; k++) { + BLI_array_append(vv, mesh_vert(vm, v->index, 0, k)->v); + n++; + } + } + } while ((v = v->next) != vm->boundstart); + if (n > 2) { + f = bev_create_ngon(bm, vv, n, boundvert_rep_face(v)); + } + else { + f = NULL; + } + BLI_array_free(vv); + return f; +} + +static void bevel_build_poly(BMesh *bm, BevVert *bv) +{ + bevel_build_poly_ex(bm, bv); +} + +static void bevel_build_trifan(BMesh *bm, BevVert *bv) +{ + BMFace *f; + BLI_assert(next_bev(bv, NULL)->seg == 1 || bv->selcount == 1); + + f = bevel_build_poly_ex(bm, bv); + + if (f) { + /* we have a polygon which we know starts at the previous vertex, make it into a fan */ + BMLoop *l_fan = BM_FACE_FIRST_LOOP(f)->prev; + BMVert *v_fan = l_fan->v; + + while (f->len > 3) { + BMLoop *l_new; + BMFace *f_new; + BLI_assert(v_fan == l_fan->v); + f_new = BM_face_split(bm, f, l_fan->v, l_fan->next->next->v, &l_new, NULL, FALSE); + + if (f_new->len > f->len) { + f = f_new; + if (l_new->v == v_fan) { l_fan = l_new; } + else if (l_new->next->v == v_fan) { l_fan = l_new->next; } + else if (l_new->prev->v == v_fan) { l_fan = l_new->prev; } + else { BLI_assert(0); } + } + else { + if (l_fan->v == v_fan) { l_fan = l_fan; } + else if (l_fan->next->v == v_fan) { l_fan = l_fan->next; } + else if (l_fan->prev->v == v_fan) { l_fan = l_fan->prev; } + else { BLI_assert(0); } + } + } + } +} + +static void bevel_build_quadstrip(BMesh *bm, BevVert *bv) +{ + BMFace *f; + BLI_assert(bv->selcount == 2); + + f = bevel_build_poly_ex(bm, bv); + + if (f) { + /* we have a polygon which we know starts at this vertex, make it into strips */ + EdgeHalf *eh_a = bv->vmesh->boundstart->elast; + EdgeHalf *eh_b = next_bev(bv, eh_a->next); /* since (selcount == 2) we know this is valid */ + BMLoop *l_a = BM_face_vert_share_loop(f, eh_a->rightv->nv.v); + BMLoop *l_b = BM_face_vert_share_loop(f, eh_b->leftv->nv.v); + int split_count = bv->vmesh->seg + 1; /* ensure we don't walk past the segments */ + + while (f->len > 4 && split_count > 0) { + BMLoop *l_new; + BLI_assert(l_a->f == f); + BLI_assert(l_b->f == f); + + if (l_a-> v == l_b->v || l_a->next == l_b) { + /* l_a->v and l_b->v can be the same or such that we'd make a 2-vertex poly */ + l_a = l_a->prev; + l_b = l_b->next; + } + else { + BM_face_split(bm, f, l_a->v, l_b->v, &l_new, NULL, FALSE); + f = l_new->f; + + /* walk around the new face to get the next verts to split */ + l_a = l_new->prev; + l_b = l_new->next->next; + } + split_count--; + } + } +} + +/* Given that the boundary is built, now make the actual BMVerts + * for the boundary and the interior of the vertex mesh. */ +static void build_vmesh(MemArena *mem_arena, BMesh *bm, BevVert *bv) +{ + VMesh *vm = bv->vmesh; + BoundVert *v, *weld1, *weld2; + int n, ns, ns2, i, k, weld; + float *va, *vb, co[3]; + +#ifdef USE_ALTERNATE_ADJ + /* ordered as follows (orig, prev, center, next)*/ + float quad_plane[4][3]; + float quad_orig_a[4][3]; + float quad_orig_b[4][3]; + const int is_odd = (vm->seg % 2); +#else + float midco[3]; +#endif + +#ifdef USE_ALTERNATE_ADJ + /* the rest are initialized inline, this remains the same for all */ + /* NOTE; in this usage we only interpolate on the 'V' so cent and next points are unused (2,3)*/ + vmesh_cent(vm, quad_plane[2]); + copy_v3_v3(quad_orig_a[2], bv->v->co); + copy_v3_v3(quad_orig_b[2], bv->v->co); +#endif + + n = vm->count; + ns = vm->seg; + ns2 = ns / 2; + + vm->mesh = (NewVert *)BLI_memarena_alloc(mem_arena, n * (ns2 + 1) * (ns + 1) * sizeof(NewVert)); + + /* special case: two beveled ends welded together */ + weld = (bv->selcount == 2) && (vm->count == 2); + weld1 = weld2 = NULL; /* will hold two BoundVerts involved in weld */ + + /* make (i, 0, 0) mesh verts for all i */ + v = vm->boundstart; + do { + i = v->index; + copy_v3_v3(mesh_vert(vm, i, 0, 0)->co, v->nv.co); + create_mesh_bmvert(bm, vm, i, 0, 0, bv->v); + v->nv.v = mesh_vert(vm, i, 0, 0)->v; + if (weld && v->ebev) { + if (!weld1) + weld1 = v; + else + weld2 = v; + } + } while ((v = v->next) != vm->boundstart); + + /* copy other ends to (i, 0, ns) for all i, and fill in profiles for beveled edges */ + v = vm->boundstart; + do { + i = v->index; + copy_mesh_vert(vm, i, 0, ns, v->next->index, 0, 0); + if (v->ebev) { + +#ifdef USE_ALTERNATE_ADJ + copy_v3_v3(quad_plane[0], v->nv.co); + mid_v3_v3v3(quad_plane[1], v->nv.co, v->prev->nv.co); + /* quad[2] is set */ + mid_v3_v3v3(quad_plane[3], v->nv.co, v->next->nv.co); + + /* orig 'A' */ + copy_v3_v3(quad_orig_a[0], v->nv.co); /* only shared location between 2 quads */ + project_to_edge(v->ebev->prev->e, v->nv.co, v->prev->nv.co, quad_orig_a[1]); + project_to_edge(v->ebev->e, v->nv.co, v->next->nv.co, quad_orig_a[3]); + + /* orig 'B' */ + copy_v3_v3(quad_orig_b[3], v->next->nv.co); /* only shared location between 2 quads */ + project_to_edge(v->ebev->prev->e, v->nv.co, v->prev->nv.co, quad_orig_b[1]); + project_to_edge(v->ebev->e, v->nv.co, v->next->nv.co, quad_orig_b[0]); + + //bl_debug_draw_quad_add(UNPACK4(quad_plane)); + //bl_debug_draw_quad_add(UNPACK4(quad_orig_a)); + //bl_debug_draw_quad_add(UNPACK4(quad_orig_b)); +#endif /* USE_ALTERNATE_ADJ */ + +#ifdef USE_ALTERNATE_ADJ + for (k = 1; k < ns; k++) { + float uv[2]; + float fac; + float co_plane[3]; + float co_orig[3]; + + /* quad_plane */ + get_point_uv(uv, v->ebev->seg, 0, k); + get_point_on_round_edge(uv, quad_plane, co_plane); + + /* quad_orig */ + /* each half has different UV's */ + if (k <= ns2) { + get_point_uv(uv, v->ebev->seg, 0, k); + get_point_on_round_edge(uv, quad_orig_a, co_orig); + } + else { + get_point_uv(uv, v->ebev->seg, 0, (k - ns2) - (is_odd ? 0.5f : 0.0f)); + get_point_on_round_edge(uv, quad_orig_b, co_orig); + uv[1] = 1.0f - uv[1]; /* so we can get the factor */ + } + fac = get_point_uv_factor(uv); + + /* done. interp */ + interp_v3_v3v3(co, co_plane, co_orig, fac); + copy_v3_v3(mesh_vert(vm, i, 0, k)->co, co); + if (!weld) + create_mesh_bmvert(bm, vm, i, 0, k, bv->v); + } +#else /* USE_ALTERNATE_ADJ */ + va = mesh_vert(vm, i, 0, 0)->co; + vb = mesh_vert(vm, i, 0, ns)->co; + project_to_edge(v->ebev->e, va, vb, midco); + for (k = 1; k < ns; k++) { + get_point_on_round_edge(v->ebev, k, va, midco, vb, co); + copy_v3_v3(mesh_vert(vm, i, 0, k)->co, co); + if (!weld) + create_mesh_bmvert(bm, vm, i, 0, k, bv->v); + } +#endif /* !USE_ALTERNATE_ADJ */ + } + } while ((v = v->next) != vm->boundstart); + + if (weld) { + vm->mesh_kind = M_NONE; + for (k = 1; k < ns; k++) { + va = mesh_vert(vm, weld1->index, 0, k)->co; + vb = mesh_vert(vm, weld2->index, 0, ns - k)->co; + mid_v3_v3v3(co, va, vb); + copy_v3_v3(mesh_vert(vm, weld1->index, 0, k)->co, co); + create_mesh_bmvert(bm, vm, weld1->index, 0, k, bv->v); + } + for (k = 1; k < ns; k++) + copy_mesh_vert(vm, weld2->index, 0, ns - k, weld1->index, 0, k); + } + + switch (vm->mesh_kind) { + case M_NONE: + /* do nothing */ + break; + case M_POLY: + bevel_build_poly(bm, bv); + break; + case M_ADJ: + bevel_build_rings(bm, bv); + break; + case M_TRI_FAN: + bevel_build_trifan(bm, bv); + break; + case M_QUAD_STRIP: + bevel_build_quadstrip(bm, bv); + break; + } +} + +/* take care, this flag isn't cleared before use, it just so happens that its not set */ +#define BM_BEVEL_EDGE_TAG_ENABLE(bme) BM_elem_flag_enable( (bme)->l, BM_ELEM_TAG) +#define BM_BEVEL_EDGE_TAG_DISABLE(bme) BM_elem_flag_disable( (bme)->l, BM_ELEM_TAG) +#define BM_BEVEL_EDGE_TAG_TEST(bme) BM_elem_flag_test( (bme)->l, BM_ELEM_TAG) + +/* + * Construction around the vertex + */ +static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v) +{ + BMEdge *bme; + BevVert *bv; + BMEdge *bme2, *unflagged_bme; + BMFace *f; + BMIter iter, iter2; + EdgeHalf *e; + int i, found_shared_face, ccw_test_sum; + int nsel = 0; + int ntot = 0; + + /* Gather input selected edges. + * Only bevel selected edges that have exactly two incident faces. + */ + + BM_ITER_ELEM (bme, &iter, v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(bme, BM_ELEM_TAG)) { + BLI_assert(BM_edge_is_manifold(bme)); + nsel++; + } + ntot++; + } + + if (nsel == 0) { + /* signal this vert isn't being beveled */ + BM_elem_flag_disable(v, BM_ELEM_TAG); + return; + } + + /* avoid calling BM_vert_edge_count since we loop over edges already */ + // ntot = BM_vert_edge_count(v); + // BLI_assert(ntot == BM_vert_edge_count(v)); + + bv = (BevVert *)BLI_memarena_alloc(bp->mem_arena, (sizeof(BevVert))); + bv->v = v; + bv->edgecount = ntot; + bv->selcount = nsel; + bv->edges = (EdgeHalf *)BLI_memarena_alloc(bp->mem_arena, ntot * sizeof(EdgeHalf)); + bv->vmesh = (VMesh *)BLI_memarena_alloc(bp->mem_arena, sizeof(VMesh)); + bv->vmesh->seg = bp->seg; + BLI_ghash_insert(bp->vert_hash, v, bv); + + /* add edges to bv->edges in order that keeps adjacent edges sharing + * a face, if possible */ + i = 0; + bme = v->e; + BM_BEVEL_EDGE_TAG_ENABLE(bme); + e = &bv->edges[0]; + e->e = bme; + for (i = 0; i < ntot; i++) { + if (i > 0) { + /* find an unflagged edge bme2 that shares a face f with previous bme */ + found_shared_face = 0; + unflagged_bme = NULL; + BM_ITER_ELEM (bme2, &iter, v, BM_EDGES_OF_VERT) { + if (BM_BEVEL_EDGE_TAG_TEST(bme2)) + continue; + if (!unflagged_bme) + unflagged_bme = bme2; + BM_ITER_ELEM (f, &iter2, bme2, BM_FACES_OF_EDGE) { + if (BM_face_edge_share_loop(f, bme)) { + found_shared_face = 1; + break; + } + } + if (found_shared_face) + break; + } + e = &bv->edges[i]; + if (found_shared_face) { + e->e = bme2; + e->fprev = f; + bv->edges[i - 1].fnext = f; + } + else { + e->e = unflagged_bme; + } + } + bme = e->e; + BM_BEVEL_EDGE_TAG_ENABLE(bme); + if (BM_elem_flag_test(bme, BM_ELEM_TAG)) { + e->is_bev = TRUE; + e->seg = bp->seg; + } + else { + e->is_bev = FALSE; + e->seg = 0; + } + e->is_rev = (bme->v2 == v); + e->offset = e->is_bev ? bp->offset : 0.0f; + } + /* find wrap-around shared face */ + BM_ITER_ELEM (f, &iter2, bme, BM_FACES_OF_EDGE) { + if (BM_face_edge_share_loop(f, bv->edges[0].e)) { + if (bv->edges[0].fnext == f) + continue; /* if two shared faces, want the other one now */ + bv->edges[ntot - 1].fnext = f; + bv->edges[0].fprev = f; + break; + } + } + + /* do later when we loop over edges */ +#if 0 + /* clear BEVEL_EDGE_TAG now that we are finished with it*/ + for (i = 0; i < ntot; i++) { + BM_BEVEL_EDGE_TAG_DISABLE(bv->edges[i].e); + } +#endif + + /* if edge array doesn't go CCW around vertex from average normal side, + * reverse the array, being careful to reverse face pointers too */ + if (ntot > 1) { + ccw_test_sum = 0; + for (i = 0; i < ntot; i++) + ccw_test_sum += bev_ccw_test(bv->edges[i].e, bv->edges[(i + 1) % ntot].e, + bv->edges[i].fnext); + if (ccw_test_sum < 0) { + for (i = 0; i <= (ntot / 2) - 1; i++) { + SWAP(EdgeHalf, bv->edges[i], bv->edges[ntot - i - 1]); + SWAP(BMFace *, bv->edges[i].fprev, bv->edges[i].fnext); + SWAP(BMFace *, bv->edges[ntot - i - 1].fprev, bv->edges[ntot - i - 1].fnext); + } + if (ntot % 2 == 1) { + i = ntot / 2; + SWAP(BMFace *, bv->edges[i].fprev, bv->edges[i].fnext); + } + } + } + + for (i = 0, e = bv->edges; i < ntot; i++, e++) { + e->next = &bv->edges[(i + 1) % ntot]; + e->prev = &bv->edges[(i + ntot - 1) % ntot]; + BM_BEVEL_EDGE_TAG_DISABLE(e->e); + } + + build_boundary(bp->mem_arena, bv); + build_vmesh(bp->mem_arena, bm, bv); +} + +/* Face f has at least one beveled vertex. Rebuild f */ +static int bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) +{ + BMIter liter; + BMLoop *l, *lprev; + BevVert *bv; + BoundVert *v, *vstart, *vend; + EdgeHalf *e, *eprev; + VMesh *vm; + int i, k; + int do_rebuild = FALSE; + BMVert *bmv; + BMVert **vv = NULL; + BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE); + + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { + if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { + lprev = l->prev; + bv = find_bevvert(bp, l->v); + e = find_edge_half(bv, l->e); + eprev = find_edge_half(bv, lprev->e); + BLI_assert(e != NULL && eprev != NULL); + vstart = eprev->leftv; + if (e->is_bev) + vend = e->rightv; + else + vend = e->leftv; + v = vstart; + vm = bv->vmesh; + BLI_array_append(vv, v->nv.v); + while (v != vend) { + if (vm->mesh_kind == M_NONE && v->ebev && v->ebev->seg > 1 && v->ebev != e && v->ebev != eprev) { + /* case of 3rd face opposite a beveled edge, with no vmesh */ + i = v->index; + e = v->ebev; + for (k = 1; k < e->seg; k++) { + bmv = mesh_vert(vm, i, 0, k)->v; + BLI_array_append(vv, bmv); + } + } + v = v->prev; + BLI_array_append(vv, v->nv.v); + } + + do_rebuild = TRUE; + } + else { + BLI_array_append(vv, l->v); + } + } + if (do_rebuild) { + BMFace *f_new = bev_create_ngon(bm, vv, BLI_array_count(vv), f); + + /* don't select newly created boundary faces... */ + if (f_new) { + BM_elem_flag_disable(f_new, BM_ELEM_TAG); + } + } + + BLI_array_free(vv); + return do_rebuild; +} + +/* All polygons touching v need rebuilding because beveling v has made new vertices */ +static void bevel_rebuild_existing_polygons(BMesh *bm, BevelParams *bp, BMVert *v) +{ + void *faces_stack[BM_DEFAULT_ITER_STACK_SIZE]; + int faces_len, f_index; + BMFace **faces = BM_iter_as_arrayN(bm, BM_FACES_OF_VERT, v, &faces_len, + faces_stack, BM_DEFAULT_ITER_STACK_SIZE); + + if (LIKELY(faces != NULL)) { + for (f_index = 0; f_index < faces_len; f_index++) { + BMFace *f = faces[f_index]; + if (bev_rebuild_polygon(bm, bp, f)) { + BM_face_kill(bm, f); + } + } + + if (faces != (BMFace **)faces_stack) { + MEM_freeN(faces); + } + } +} + + +/* + * Build the polygons along the selected Edge + */ +static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme) +{ + BevVert *bv1, *bv2; + BMVert *bmv1, *bmv2, *bmv3, *bmv4, *bmv1i, *bmv2i, *bmv3i, *bmv4i; + VMesh *vm1, *vm2; + EdgeHalf *e1, *e2; + BMFace *f1, *f2, *f; + int k, nseg, i1, i2; + + if (!BM_edge_is_manifold(bme)) + return; + + bv1 = find_bevvert(bp, bme->v1); + bv2 = find_bevvert(bp, bme->v2); + + BLI_assert(bv1 && bv2); + + e1 = find_edge_half(bv1, bme); + e2 = find_edge_half(bv2, bme); + + BLI_assert(e1 && e2); + + /* v4 v3 + * \ / + * e->v1 - e->v2 + * / \ + * v1 v2 + */ + nseg = e1->seg; + BLI_assert(nseg > 0 && nseg == e2->seg); + + bmv1 = e1->leftv->nv.v; + bmv4 = e1->rightv->nv.v; + bmv2 = e2->rightv->nv.v; + bmv3 = e2->leftv->nv.v; + + BLI_assert(bmv1 && bmv2 && bmv3 && bmv4); + + f1 = boundvert_rep_face(e1->leftv); + f2 = boundvert_rep_face(e1->rightv); + + if (nseg == 1) { + bev_create_quad_tri(bm, bmv1, bmv2, bmv3, bmv4, f1); + } + else { + i1 = e1->leftv->index; + i2 = e2->leftv->index; + vm1 = bv1->vmesh; + vm2 = bv2->vmesh; + bmv1i = bmv1; + bmv2i = bmv2; + for (k = 1; k <= nseg; k++) { + bmv4i = mesh_vert(vm1, i1, 0, k)->v; + bmv3i = mesh_vert(vm2, i2, 0, nseg - k)->v; + f = (k <= nseg / 2 + (nseg % 2)) ? f1 : f2; + bev_create_quad_tri(bm, bmv1i, bmv2i, bmv3i, bmv4i, f); + bmv1i = bmv4i; + bmv2i = bmv3i; + } + } +} + +/** + * - Currently only bevels BM_ELEM_TAG'd verts and edges. + * + * - Newly created faces are BM_ELEM_TAG'd too, + * the caller needs to ensure this is cleared before calling + * if its going to use this face tag. + * + * \warning all tagged edges _must_ be manifold. + */ +void BM_mesh_bevel(BMesh *bm, const float offset, const float segments) +{ + BMIter iter; + BMVert *v; + BMEdge *e; + BevelParams bp = {NULL}; + + bp.offset = offset; + bp.seg = segments; + + if (bp.offset > 0) { + /* primary alloc */ + bp.vert_hash = BLI_ghash_ptr_new(__func__); + bp.mem_arena = BLI_memarena_new((1 << 16), __func__); + BLI_memarena_use_calloc(bp.mem_arena); + + /* The analysis of the input vertices and execution additional constructions */ + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + bevel_vert_construct(bm, &bp, v); + } + } + + /* Build polygons for edges */ + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + bevel_build_edge_polygons(bm, &bp, e); + } + } + + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + bevel_rebuild_existing_polygons(bm, &bp, v); + } + } + + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + BLI_assert(find_bevvert(&bp, v) != NULL); + BM_vert_kill(bm, v); + } + } + + /* primary free */ + BLI_ghash_free(bp.vert_hash, NULL, NULL); + BLI_memarena_free(bp.mem_arena); + } +} diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h new file mode 100644 index 00000000000..a80e4f3a4a2 --- /dev/null +++ b/source/blender/bmesh/tools/bmesh_bevel.h @@ -0,0 +1,32 @@ +/* + * ***** 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. + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BMESH_BEVEL_H__ +#define __BMESH_BEVEL_H__ + +/** \file blender/bmesh/tools/bmesh_bevel.h + * \ingroup bmesh + */ + +void BM_mesh_bevel(BMesh *bm, const float offset, const float segments); + +#endif /* __BMESH_BEVEL_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_decimate.h b/source/blender/bmesh/tools/bmesh_decimate.h similarity index 86% rename from source/blender/bmesh/intern/bmesh_decimate.h rename to source/blender/bmesh/tools/bmesh_decimate.h index 04dc0cfd2ea..4a557c20ae3 100644 --- a/source/blender/bmesh/intern/bmesh_decimate.h +++ b/source/blender/bmesh/tools/bmesh_decimate.h @@ -23,7 +23,7 @@ #ifndef __BMESH_DECIMATE_H__ #define __BMESH_DECIMATE_H__ -/** \file blender/bmesh/intern/bmesh_decimate.h +/** \file blender/bmesh/tools/bmesh_decimate.h * \ingroup bmesh */ @@ -37,5 +37,8 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int BMEdge **einput_arr, const int einput_len); void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries); +/* these weights are accumulated so too high values may reach 'inf' too quickly */ +#define BM_MESH_DECIM_WEIGHT_MAX 100000.0f +#define BM_MESH_DECIM_WEIGHT_EPS (1.0f / BM_MESH_DECIM_WEIGHT_MAX) #endif /* __BMESH_DECIMATE_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c similarity index 85% rename from source/blender/bmesh/intern/bmesh_decimate_collapse.c rename to source/blender/bmesh/tools/bmesh_decimate_collapse.c index feeb2a926f3..7c054d84405 100644 --- a/source/blender/bmesh/intern/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -20,7 +20,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/bmesh/intern/bmesh_decimate_collapse.c +/** \file blender/bmesh/tools/bmesh_decimate_collapse.c * \ingroup bmesh * * BMesh decimator that uses an edge collapse method. @@ -39,17 +39,21 @@ #include "BKE_customdata.h" #include "bmesh.h" -#include "bmesh_structure.h" #include "bmesh_decimate.h" /* own include */ +#include "../intern/bmesh_structure.h" + /* defines for testing */ #define USE_CUSTOMDATA #define USE_TRIANGULATE +#define USE_VERT_NORMAL_INTERP /* has the advantage that flipped faces don't mess up vertex normals */ /* these checks are for rare cases that we can't avoid since they are valid meshes still */ #define USE_SAFETY_CHECKS #define BOUNDARY_PRESERVE_WEIGHT 100.0f +#define OPTIMIZE_EPS 0.01f /* FLT_EPSILON is too small, see [#33106] */ +#define COST_INVALID FLT_MAX typedef enum CD_UseFlag { CD_DO_VERT = (1 << 0), @@ -96,7 +100,7 @@ static void bm_decim_build_quadrics(BMesh *bm, Quadric *vquadrics) f = e->l->f; cross_v3_v3v3(edge_cross, edge_vector, f->no); - if (fabsf(normalize_v3(edge_cross)) > FLT_EPSILON) { + if (normalize_v3(edge_cross) > FLT_EPSILON) { Quadric q; BLI_quadric_from_v3_dist(&q, edge_cross, -dot_v3v3(edge_cross, e->v1->co)); BLI_quadric_mul(&q, BOUNDARY_PRESERVE_WEIGHT); @@ -122,7 +126,7 @@ static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3], &vquadrics[BM_elem_index_get(e->v2)]); - if (BLI_quadric_optimize(&q, optimize_co)) { + if (BLI_quadric_optimize(&q, optimize_co, OPTIMIZE_EPS)) { return; /* all is good */ } else { @@ -130,6 +134,56 @@ static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3], } } +static int bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_co[3]) +{ + BMIter liter; + BMLoop *l; + unsigned int i; + + for (i = 0; i < 2; i++) { + /* loop over both verts */ + BMVert *v = *((&e->v1) + i); + + BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { + if (l->e != e && l->prev->e != e) { + float *co_prev = l->prev->v->co; + float *co_next = l->next->v->co; + float cross_exist[3]; + float cross_optim[3]; + +#if 1 + float vec_other[3]; /* line between the two outer verts, re-use for both cross products */ + float vec_exist[3]; /* before collapse */ + float vec_optim[3]; /* after collapse */ + + sub_v3_v3v3(vec_other, co_prev, co_next); + sub_v3_v3v3(vec_exist, co_prev, v->co); + sub_v3_v3v3(vec_optim, co_prev, optimize_co); + + cross_v3_v3v3(cross_exist, vec_other, vec_exist); + cross_v3_v3v3(cross_optim, vec_other, vec_optim); + + /* normalize isn't really needed, but ensures the value at a unit we can compare against */ + normalize_v3(cross_exist); + normalize_v3(cross_optim); +#else + normal_tri_v3(cross_exist, v->co, co_prev, co_next); + normal_tri_v3(cross_optim, optimize_co, co_prev, co_next); +#endif + + /* use a small value rather then zero so we don't flip a face in multiple steps + * (first making it zero area, then flipping again)*/ + if (dot_v3v3(cross_exist, cross_optim) <= FLT_EPSILON) { + //printf("no flip\n"); + return TRUE; + } + } + } + } + + return FALSE; +} + static void bm_decim_build_edge_cost_single(BMEdge *e, const Quadric *vquadrics, const float *vweights, Heap *eheap, HeapNode **eheap_table) @@ -169,8 +223,8 @@ static void bm_decim_build_edge_cost_single(BMEdge *e, } if (vweights) { - if ((vweights[BM_elem_index_get(e->v1)] < FLT_EPSILON) && - (vweights[BM_elem_index_get(e->v2)] < FLT_EPSILON)) + if ((vweights[BM_elem_index_get(e->v1)] >= BM_MESH_DECIM_WEIGHT_MAX) && + (vweights[BM_elem_index_get(e->v2)] >= BM_MESH_DECIM_WEIGHT_MAX)) { /* skip collapsing this edge */ eheap_table[BM_elem_index_get(e)] = NULL; @@ -190,14 +244,25 @@ static void bm_decim_build_edge_cost_single(BMEdge *e, BLI_quadric_evaluate(q2, optimize_co)); } else { - cost = ((BLI_quadric_evaluate(q1, optimize_co) * vweights[BM_elem_index_get(e->v1)]) + - (BLI_quadric_evaluate(q2, optimize_co) * vweights[BM_elem_index_get(e->v2)])); + /* add 1.0 so planar edges are still weighted against */ + cost = (((BLI_quadric_evaluate(q1, optimize_co) + 1.0f) * vweights[BM_elem_index_get(e->v1)]) + + ((BLI_quadric_evaluate(q2, optimize_co) + 1.0f) * vweights[BM_elem_index_get(e->v2)])); } // print("COST %.12f\n"); eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, cost, e); } + +/* use this for degenerate cases - add back to the heap with an invalid cost, + * this way it may be calculated again if surrounding geometry changes */ +static void bm_decim_invalid_edge_cost_single(BMEdge *e, + Heap *eheap, HeapNode **eheap_table) +{ + BLI_assert(eheap_table[BM_elem_index_get(e)] == NULL); + eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, COST_INVALID, e); +} + static void bm_decim_build_edge_cost(BMesh *bm, const Quadric *vquadrics, const float *vweights, Heap *eheap, HeapNode **eheap_table) @@ -523,7 +588,7 @@ BLI_INLINE int bm_edge_is_manifold_or_boundary(BMLoop *l) #endif } -static int bm_edge_collapse_is_degenerate(BMEdge *e_first) +static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) { /* simply check that there is no overlap between faces and edges of each vert, * (excluding the 2 faces attached to 'e' and 'e' its self) */ @@ -627,11 +692,6 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e { BMVert *v_other; - /* disallow collapsing which results in degenerate cases */ - if (bm_edge_collapse_is_degenerate(e_clear)) { - return FALSE; - } - v_other = BM_edge_other_vert(e_clear, v_clear); BLI_assert(v_other != NULL); @@ -702,8 +762,11 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e BM_edge_kill(bm, e_clear); + v_other->head.hflag |= v_clear->head.hflag; BM_vert_splice(bm, v_clear, v_other); + e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag; + e_b_other[1]->head.hflag |= e_b_other[0]->head.hflag; BM_edge_splice(bm, e_a_other[0], e_a_other[1]); BM_edge_splice(bm, e_b_other[0], e_b_other[1]); @@ -748,8 +811,10 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e BM_edge_kill(bm, e_clear); + v_other->head.hflag |= v_clear->head.hflag; BM_vert_splice(bm, v_clear, v_other); + e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag; BM_edge_splice(bm, e_a_other[0], e_a_other[1]); // BM_mesh_validate(bm); @@ -774,12 +839,28 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, float optimize_co[3]; float customdata_fac; +#ifdef USE_VERT_NORMAL_INTERP + float v_clear_no[3]; + copy_v3_v3(v_clear_no, e->v2->no); +#endif + + /* disallow collapsing which results in degenerate cases */ + if (UNLIKELY(bm_edge_collapse_is_degenerate_topology(e))) { + bm_decim_invalid_edge_cost_single(e, eheap, eheap_table); /* add back with a high cost */ + return; + } + bm_decim_calc_target_co(e, optimize_co, vquadrics); + /* check if this would result in an overlapping face */ + if (UNLIKELY(bm_edge_collapse_is_degenerate_flip(e, optimize_co))) { + bm_decim_invalid_edge_cost_single(e, eheap, eheap_table); /* add back with a high cost */ + return; + } + /* use for customdata merging */ if (LIKELY(compare_v3v3(e->v1->co, e->v2->co, FLT_EPSILON) == FALSE)) { customdata_fac = line_point_factor_v3(optimize_co, e->v1->co, e->v2->co); - #if 0 /* simple test for stupid collapse */ if (customdata_fac < 0.0 - FLT_EPSILON || customdata_fac > 1.0f + FLT_EPSILON) { @@ -797,9 +878,7 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, int i; if (vweights) { - const int fac = CLAMPIS(customdata_fac, 0.0f, 1.0f); - vweights[BM_elem_index_get(v_other)] = (vweights[v_clear_index] * (1.0f - fac)) + - (vweights[BM_elem_index_get(v_other)] * fac); + vweights[BM_elem_index_get(v_other)] += vweights[v_clear_index]; } e = NULL; /* paranoid safety check */ @@ -822,7 +901,13 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, /* in fact face normals are not used for progressive updates, no need to update them */ // BM_vert_normal_update_all(v); +#ifdef USE_VERT_NORMAL_INTERP + interp_v3_v3v3(v_other->no, v_other->no, v_clear_no, customdata_fac); + normalize_v3(v_other->no); +#else BM_vert_normal_update(v_other); +#endif + /* update error costs and the eheap */ if (LIKELY(v_other->e)) { @@ -835,7 +920,10 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, } while ((e_iter = bmesh_disk_edge_next(e_iter, v_other)) != e_first); } -#if 0 + /* this block used to be disabled, + * but enable now since surrounding faces may have been + * set to COST_INVALID because of a face overlap that no longer occurs */ +#if 1 /* optional, update edges around the vertex face fan */ { BMIter liter; @@ -850,13 +938,17 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, BLI_assert(BM_vert_in_edge(e_outer, l->v) == FALSE); - bm_decim_build_edge_cost_single(e_outer, vquadrics, eheap, eheap_table); + bm_decim_build_edge_cost_single(e_outer, vquadrics, vweights, eheap, eheap_table); } } } /* end optional update */ #endif } + else { + /* add back with a high cost */ + bm_decim_invalid_edge_cost_single(e, eheap, eheap_table); + } } @@ -867,7 +959,7 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, * \brief BM_mesh_decimate * \param bm The mesh * \param factor face count multiplier [0 - 1] - * \param vertex_weights Optional array of vertex aligned weights [0 - 1], + * \param vweights Optional array of vertex aligned weights [0 - 1], * a vertex group is the usual source for this. */ void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const int do_triangulate) @@ -912,7 +1004,10 @@ void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, c #endif /* iterative edge collapse and maintain the eheap */ - while ((bm->totface > face_tot_target) && (BLI_heap_is_empty(eheap) == FALSE)) { + while ((bm->totface > face_tot_target) && + (BLI_heap_is_empty(eheap) == FALSE) && + (BLI_heap_node_value(BLI_heap_top(eheap)) != COST_INVALID)) + { // const float value = BLI_heap_node_value(BLI_heap_top(eheap)); BMEdge *e = BLI_heap_popmin(eheap); BLI_assert(BM_elem_index_get(e) < tot_edge_orig); /* handy to detect corruptions elsewhere */ diff --git a/source/blender/bmesh/intern/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c similarity index 97% rename from source/blender/bmesh/intern/bmesh_decimate_dissolve.c rename to source/blender/bmesh/tools/bmesh_decimate_dissolve.c index d1371a18160..f67f01e4585 100644 --- a/source/blender/bmesh/intern/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c @@ -20,7 +20,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/bmesh/intern/bmesh_decimate_dissolve.c +/** \file blender/bmesh/tools/bmesh_decimate_dissolve.c * \ingroup bmesh * * BMesh decimator that dissolves flat areas into polygons (ngons). @@ -69,9 +69,6 @@ static int dissolve_elem_cmp(const void *a1, const void *a2) return 0; } -/** - * \param do_all_verts Collapse all verts between 2 faces - don't check their edge angle. - */ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries, BMVert **vinput_arr, const int vinput_len, BMEdge **einput_arr, const int einput_len) @@ -231,8 +228,8 @@ void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const int do_ int vinput_len; int einput_len; - BMVert **vinput_arr = BM_iter_as_arrayN(bm, BM_VERTS_OF_MESH, NULL, &vinput_len); - BMEdge **einput_arr = BM_iter_as_arrayN(bm, BM_EDGES_OF_MESH, NULL, &einput_len); + BMVert **vinput_arr = BM_iter_as_arrayN(bm, BM_VERTS_OF_MESH, NULL, &vinput_len, NULL, 0); + BMEdge **einput_arr = BM_iter_as_arrayN(bm, BM_EDGES_OF_MESH, NULL, &einput_len, NULL, 0); BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries, vinput_arr, vinput_len, diff --git a/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c similarity index 97% rename from source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c rename to source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c index 68c0652d2c4..acdab2510a4 100644 --- a/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c +++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c @@ -20,7 +20,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/bmesh/intern/bmesh_decimate_unsubdivide.c +/** \file blender/bmesh/tools/bmesh_decimate_unsubdivide.c * \ingroup bmesh * * BMesh decimator that uses a grid un-subdivide method. @@ -247,9 +247,9 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int #ifdef USE_WALKER /* Walk over selected elements starting at active */ BMW_init(&walker, bm, BMW_CONNECTED_VERTEX, - ELE_VERT_TAG, BMW_MASK_NOP, BMW_MASK_NOP, - BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */ - BMW_NIL_LAY); + ELE_VERT_TAG, BMW_MASK_NOP, BMW_MASK_NOP, + BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */ + BMW_NIL_LAY); BLI_assert(walker.order == BMW_BREADTH_FIRST); for (v = BMW_begin(&walker, v_first); v != NULL; v = BMW_step(&walker)) { diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp index 374f6385ea7..44e74e320cc 100644 --- a/source/blender/collada/AnimationImporter.cpp +++ b/source/blender/collada/AnimationImporter.cpp @@ -844,7 +844,7 @@ void AnimationImporter::apply_matrix_curves(Object *ob, std::vector& a * This function returns the aspet ration from the Collada camera. * * Note:COLLADA allows to specify either XFov, or YFov alone. - * In tghat case the aspect ratio can be determined from + * In that case the aspect ratio can be determined from * the viewport aspect ratio (which is 1:1 ?) * XXX: check this: its probably wrong! * If both values are specified, then the aspect ration is simply xfov/yfov diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 1c4f0974c6d..084f71e0afc 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -552,8 +552,8 @@ bool DocumentImporter::writeVisualScene(const COLLADAFW::VisualScene *visualScen } /** When this method is called, the writer must handle all nodes contained in the -* library nodes. -* \return The writer should return true, if writing succeeded, false otherwise.*/ + * library nodes. + * \return The writer should return true, if writing succeeded, false otherwise.*/ bool DocumentImporter::writeLibraryNodes(const COLLADAFW::LibraryNodes *libraryNodes) { if (mImportStage != General) diff --git a/source/blender/collada/DocumentImporter.h b/source/blender/collada/DocumentImporter.h index e878a5a5b48..d54b8db9f00 100644 --- a/source/blender/collada/DocumentImporter.h +++ b/source/blender/collada/DocumentImporter.h @@ -81,8 +81,8 @@ public: /** * This method will be called if an error in the loading process occurred and the loader cannot * continue to load. The writer should undo all operations that have been performed. - \param errorMessage A message containing informations about the error that occurred. - */ + * \param errorMessage A message containing informations about the error that occurred. + */ void cancel(const COLLADAFW::String& errorMessage); /** This is the method called. The writer hast to prepare to receive data.*/ diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp index 2e0c0f1ea57..aba290f5ce4 100644 --- a/source/blender/collada/ImageExporter.cpp +++ b/source/blender/collada/ImageExporter.cpp @@ -61,7 +61,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) if (not_yet_exported) { - ImBuf *imbuf = BKE_image_get_ibuf(image, NULL); + ImBuf *imbuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (!imbuf) { fprintf(stderr, "Collada export: image does not exist:\n%s\n", image->name); return; @@ -147,6 +147,8 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) img.add(mSW); fprintf(stdout, "Collada export: Added image: %s\n", export_file); mImages.push_back(translated_name); + + BKE_image_release_ibuf(image, imbuf, NULL); } } diff --git a/source/blender/collada/MaterialExporter.cpp b/source/blender/collada/MaterialExporter.cpp index 5a1d8b7602a..4aece997f72 100644 --- a/source/blender/collada/MaterialExporter.cpp +++ b/source/blender/collada/MaterialExporter.cpp @@ -70,7 +70,7 @@ void MaterialsExporter::operator()(Material *ma, Object *ob) { std::string name(id_name(ma)); - openMaterial(get_material_id(ma), get_material_id(ma)); + openMaterial(get_material_id(ma), translate_id(name)); std::string efid = translate_id(name) + "-effect"; addInstanceEffect(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, efid)); diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp index 8337a977b3b..de8d1e85eb9 100644 --- a/source/blender/collada/MeshImporter.cpp +++ b/source/blender/collada/MeshImporter.cpp @@ -589,7 +589,7 @@ void MeshImporter::read_lines(COLLADAFW::Mesh *mesh, Mesh *me) for (int i = 0; i < edge_count; i++, med++) { med->bweight = 0; med->crease = 0; - med->flag = 0; + med->flag |= ME_LOOSEEDGE; med->v1 = indices[2 * i]; med->v2 = indices[2 * i + 1]; } diff --git a/source/blender/collada/TransformReader.cpp b/source/blender/collada/TransformReader.cpp index d10cd7378e9..61793589422 100644 --- a/source/blender/collada/TransformReader.cpp +++ b/source/blender/collada/TransformReader.cpp @@ -84,7 +84,7 @@ void TransformReader::dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[ COLLADAFW::Rotate *ro = (COLLADAFW::Rotate *)tm; COLLADABU::Math::Vector3& axis = ro->getRotationAxis(); const float angle = (float)DEG2RAD(ro->getRotationAngle()); - const float ax[] = {axis[0], axis[1], axis[2]}; + const float ax[] = {(float)axis[0], (float)axis[1], (float)axis[2]}; // float quat[4]; // axis_angle_to_quat(quat, axis, angle); // quat_to_mat4(m, quat); diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 35844b549de..7bdda387d5e 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -139,7 +139,7 @@ Mesh *bc_to_mesh_apply_modifiers(Scene *scene, Object *ob, BC_export_mesh_type e { Mesh *tmpmesh; CustomDataMask mask = CD_MASK_MESH; - DerivedMesh *dm; + DerivedMesh *dm = NULL; switch (export_mesh_type) { case BC_MESH_TYPE_VIEW: { dm = mesh_create_derived_view(scene, ob, mask); @@ -151,7 +151,7 @@ Mesh *bc_to_mesh_apply_modifiers(Scene *scene, Object *ob, BC_export_mesh_type e } } - tmpmesh = BKE_mesh_add("ColladaMesh"); // name is not important here + tmpmesh = BKE_mesh_add("ColladaMesh"); // name is not important here DM_to_mesh(dm, tmpmesh, ob); dm->release(dm); return tmpmesh; diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index b3e76a287ea..8259cb6f297 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -267,6 +267,8 @@ set(SRC nodes/COM_MathNode.h nodes/COM_MapValueNode.cpp nodes/COM_MapValueNode.h + nodes/COM_MapRangeNode.cpp + nodes/COM_MapRangeNode.h operations/COM_NormalizeOperation.cpp operations/COM_NormalizeOperation.h @@ -572,6 +574,8 @@ set(SRC operations/COM_SetAlphaOperation.h operations/COM_MapValueOperation.cpp operations/COM_MapValueOperation.h + operations/COM_MapRangeOperation.cpp + operations/COM_MapRangeOperation.h # Distort operation operations/COM_TranslateOperation.h diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index 2b09c9d5b8c..9c4a32f20c9 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -83,6 +83,7 @@ #include "COM_LuminanceMatteNode.h" #include "COM_MapUVNode.h" #include "COM_MapValueNode.h" +#include "COM_MapRangeNode.h" #include "COM_MaskNode.h" #include "COM_MathNode.h" #include "COM_MixNode.h" @@ -351,6 +352,9 @@ Node *Converter::convert(bNode *b_node, bool fast) case CMP_NODE_MAP_VALUE: node = new MapValueNode(b_node); break; + case CMP_NODE_MAP_RANGE: + node = new MapRangeNode(b_node); + break; case CMP_NODE_TRANSFORM: node = new TransformNode(b_node); break; diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp index 0553aebbba6..ffc36281874 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp +++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp @@ -352,7 +352,8 @@ void ExecutionGroup::execute(ExecutionSystem *graph) startEvaluated = true; numberEvaluated++; - WM_main_add_notifier(NC_WINDOW | ND_DRAW, NULL); + if (bTree->update_draw) + bTree->update_draw(bTree->udh); } else if (state == COM_ES_SCHEDULED) { finished = false; diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.h b/source/blender/compositor/intern/COM_ExecutionGroup.h index c7a7d06134e..00104c24194 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.h +++ b/source/blender/compositor/intern/COM_ExecutionGroup.h @@ -193,7 +193,7 @@ private: /** * @brief try to schedule a specific chunk. - * @note scheduling succeeds when all input requirements are met and the chunks hasen't been scheduled yet. + * @note scheduling succeeds when all input requirements are met and the chunks hasn't been scheduled yet. * @param graph * @param xChunk * @param yChunk @@ -245,7 +245,7 @@ public: /** * @brief add an operation to this ExecutionGroup - * @note this method will add input of the operations recursivly + * @note this method will add input of the operations recursively * @note this method can create multiple ExecutionGroup's * @param system * @param operation @@ -369,7 +369,7 @@ public: /** * @brief this method determines the MemoryProxy's where this execution group depends on. * @note After this method determineDependingAreaOfInterest can be called to determine - * @note the area of the MemoryProxy.creator thas has to be executed. + * @note the area of the MemoryProxy.creator that has to be executed. * @param memoryProxies result */ void determineDependingMemoryProxies(vector *memoryProxies); diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp index c6e0f6c2cfb..1ec4ac7699b 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp @@ -247,9 +247,14 @@ void ExecutionSystem::addReadWriteBufferOperations(NodeOperation *operation) */ static void debug_check_node_connections(Node *node) { + /* note: connected inputs are not checked here, + * it would break quite a lot and such inputs are ignored later anyway + */ +#if 0 for (int i = 0; i < node->getNumberOfInputSockets(); ++i) { BLI_assert(!node->getInputSocket(i)->isConnected()); } +#endif for (int i = 0; i < node->getNumberOfOutputSockets(); ++i) { BLI_assert(!node->getOutputSocket(i)->isConnected()); } diff --git a/source/blender/compositor/intern/COM_Node.cpp b/source/blender/compositor/intern/COM_Node.cpp index 300d7ef1952..d49bb5f96fb 100644 --- a/source/blender/compositor/intern/COM_Node.cpp +++ b/source/blender/compositor/intern/COM_Node.cpp @@ -137,18 +137,26 @@ void Node::addSetVectorOperation(ExecutionSystem *graph, InputSocket *inputsocke graph->addOperation(operation); } -/* when a node has no valid data (missing image or group pointer) */ +NodeOperation *Node::convertToOperations_invalid_index(ExecutionSystem *graph, int index) +{ + const float warning_color[4] = {1.0f, 0.0f, 1.0f, 1.0f}; + SetColorOperation *operation = new SetColorOperation(); + operation->setChannels(warning_color); + + /* link the operation */ + this->getOutputSocket(index)->relinkConnections(operation->getOutputSocket()); + graph->addOperation(operation); + return operation; +} + +/* when a node has no valid data (missing image / group pointer, or missing renderlayer from EXR) */ void Node::convertToOperations_invalid(ExecutionSystem *graph, CompositorContext *context) { /* this is a really bad situation - bring on the pink! - so artists know this is bad */ - const float warning_color[4] = {1.0f, 0.0f, 1.0f, 1.0f}; int index; vector &outputsockets = this->getOutputSockets(); for (index = 0; index < outputsockets.size(); index++) { - SetColorOperation *operation = new SetColorOperation(); - this->getOutputSocket(index)->relinkConnections(operation->getOutputSocket()); - operation->setChannels(warning_color); - graph->addOperation(operation); + convertToOperations_invalid_index(graph, index); } } diff --git a/source/blender/compositor/intern/COM_Node.h b/source/blender/compositor/intern/COM_Node.h index 468a95ed434..c098d6da32b 100644 --- a/source/blender/compositor/intern/COM_Node.h +++ b/source/blender/compositor/intern/COM_Node.h @@ -105,6 +105,10 @@ public: */ void addSetVectorOperation(ExecutionSystem *graph, InputSocket *inputsocket, int editorNodeInputSocketIndex); + /** + * Create dummy warning operation, use when we can't get the source data. + */ + NodeOperation *convertToOperations_invalid_index(ExecutionSystem *graph, int index); /** * when a node has no valid data (missing image or a group nodes ID pointer is NULL) * call this function from #convertToOperations, this way the node sockets are converted diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h index 42d90eca38f..f856d8e6a11 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.h +++ b/source/blender/compositor/intern/COM_NodeOperation.h @@ -77,7 +77,7 @@ private: ThreadMutex m_mutex; /** - * @brief reference to the editing bNodeTree only used for break callback + * @brief reference to the editing bNodeTree, used for break and update callback */ const bNodeTree *m_btree; @@ -247,6 +247,10 @@ public: return this->m_btree->test_break(this->m_btree->tbh); } + inline void updateDraw() { + if (this->m_btree->update_draw) + this->m_btree->update_draw(this->m_btree->udh); + } protected: NodeOperation(); diff --git a/source/blender/compositor/intern/COM_WorkPackage.h b/source/blender/compositor/intern/COM_WorkPackage.h index 953a164e95e..2bb124a1c84 100644 --- a/source/blender/compositor/intern/COM_WorkPackage.h +++ b/source/blender/compositor/intern/COM_WorkPackage.h @@ -44,7 +44,7 @@ private: unsigned int m_chunkNumber; public: /** - * @constructor + * constructor * @param group the ExecutionGroup * @param chunkNumber the number of the chunk */ diff --git a/source/blender/compositor/nodes/COM_BlurNode.cpp b/source/blender/compositor/nodes/COM_BlurNode.cpp index 4f120ea5a6e..6a4987c2075 100644 --- a/source/blender/compositor/nodes/COM_BlurNode.cpp +++ b/source/blender/compositor/nodes/COM_BlurNode.cpp @@ -31,6 +31,7 @@ #include "COM_FastGaussianBlurOperation.h" #include "COM_MathBaseOperation.h" #include "COM_SetValueOperation.h" +#include "COM_GammaCorrectOperation.h" BlurNode::BlurNode(bNode *editorNode) : Node(editorNode) { @@ -48,16 +49,17 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co const float size = ((const bNodeSocketValueFloat *)sock->default_value)->value; CompositorQuality quality = context->getQuality(); - + NodeOperation *input_operation = NULL, *output_operation = NULL; + if (data->filtertype == R_FILTER_FAST_GAUSS) { FastGaussianBlurOperation *operationfgb = new FastGaussianBlurOperation(); operationfgb->setData(data); operationfgb->setbNode(editorNode); - this->getInputSocket(0)->relinkConnections(operationfgb->getInputSocket(0), 0, graph); this->getInputSocket(1)->relinkConnections(operationfgb->getInputSocket(1), 1, graph); - this->getOutputSocket(0)->relinkConnections(operationfgb->getOutputSocket(0)); graph->addOperation(operationfgb); - addPreviewOperation(graph, context, operationfgb->getOutputSocket()); + + input_operation = operationfgb; + output_operation = operationfgb; } else if (editorNode->custom1 & CMP_NODEFLAG_BLUR_VARIABLE_SIZE) { MathAddOperation *clamp = new MathAddOperation(); @@ -93,48 +95,68 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co operation->setData(data); operation->setbNode(editorNode); operation->setQuality(quality); - this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); addLink(graph, operationy->getOutputSocket(), operation->getInputSocket(1)); graph->addOperation(operation); - this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); - addPreviewOperation(graph, context, operation->getOutputSocket()); + + output_operation = operation; + input_operation = operation; } else if (!data->bokeh) { GaussianXBlurOperation *operationx = new GaussianXBlurOperation(); operationx->setData(data); operationx->setbNode(editorNode); operationx->setQuality(quality); - this->getInputSocket(0)->relinkConnections(operationx->getInputSocket(0), 0, graph); this->getInputSocket(1)->relinkConnections(operationx->getInputSocket(1), 1, graph); graph->addOperation(operationx); GaussianYBlurOperation *operationy = new GaussianYBlurOperation(); operationy->setData(data); operationy->setbNode(editorNode); operationy->setQuality(quality); - this->getOutputSocket(0)->relinkConnections(operationy->getOutputSocket()); + graph->addOperation(operationy); addLink(graph, operationx->getOutputSocket(), operationy->getInputSocket(0)); addLink(graph, operationx->getInputSocket(1)->getConnection()->getFromSocket(), operationy->getInputSocket(1)); - addPreviewOperation(graph, context, operationy->getOutputSocket()); if (!connectedSizeSocket) { operationx->setSize(size); operationy->setSize(size); } + + input_operation = operationx; + output_operation = operationy; } else { GaussianBokehBlurOperation *operation = new GaussianBokehBlurOperation(); operation->setData(data); operation->setbNode(editorNode); - this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph); operation->setQuality(quality); graph->addOperation(operation); - this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); - addPreviewOperation(graph, context, operation->getOutputSocket()); if (!connectedSizeSocket) { operation->setSize(size); } + + input_operation = operation; + output_operation = operation; + } + + if (data->gamma) { + GammaCorrectOperation *correct = new GammaCorrectOperation(); + GammaUncorrectOperation *inverse = new GammaUncorrectOperation(); + + this->getInputSocket(0)->relinkConnections(correct->getInputSocket(0), 0, graph); + addLink(graph, correct->getOutputSocket(), input_operation->getInputSocket(0)); + addLink(graph, output_operation->getOutputSocket(), inverse->getInputSocket(0)); + this->getOutputSocket()->relinkConnections(inverse->getOutputSocket()); + graph->addOperation(correct); + graph->addOperation(inverse); + + addPreviewOperation(graph, context, inverse->getOutputSocket()); + } + else { + this->getInputSocket(0)->relinkConnections(input_operation->getInputSocket(0), 0, graph); + this->getOutputSocket()->relinkConnections(output_operation->getOutputSocket()); + addPreviewOperation(graph, context, output_operation->getOutputSocket()); } } diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp index 4ebd28d710a..4293e344c65 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.cpp +++ b/source/blender/compositor/nodes/COM_ImageNode.cpp @@ -73,7 +73,7 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c /* force a load, we assume iuser index will be set OK anyway */ if (image && image->type == IMA_TYPE_MULTILAYER) { bool is_multilayer_ok = false; - BKE_image_get_ibuf(image, imageuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, imageuser, NULL); if (image->rr) { RenderLayer *rl = (RenderLayer *)BLI_findlink(&image->rr->layers, imageuser->layer); if (rl) { @@ -83,6 +83,7 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c is_multilayer_ok = true; for (index = 0; index < numberOfOutputs; index++) { + NodeOperation *operation = NULL; socket = this->getOutputSocket(index); if (socket->isConnected() || index == 0) { bNodeSocket *bnodeSocket = socket->getbNodeSocket(); @@ -91,7 +92,6 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c RenderPass *rpass = (RenderPass *)BLI_findlink(&rl->passes, passindex); if (rpass) { - NodeOperation *operation = NULL; imageuser->pass = passindex; switch (rpass->channels) { case 1: @@ -105,19 +105,25 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c case 4: operation = doMultilayerCheck(graph, rl, image, imageuser, framenumber, index, passindex, COM_DT_COLOR); break; - default: - /* XXX add a dummy operation? */ + /* dummy operation is added below */ break; } + if (index == 0 && operation) { addPreviewOperation(graph, context, operation->getOutputSocket()); } } } + + /* incase we can't load the layer */ + if (operation == NULL) { + convertToOperations_invalid_index(graph, index); + } } } } + BKE_image_release_ibuf(image, ibuf, NULL); /* without this, multilayer that fail to load will crash blender [#32490] */ if (is_multilayer_ok == false) { diff --git a/source/blender/compositor/nodes/COM_MapRangeNode.cpp b/source/blender/compositor/nodes/COM_MapRangeNode.cpp new file mode 100644 index 00000000000..232be3d41b0 --- /dev/null +++ b/source/blender/compositor/nodes/COM_MapRangeNode.cpp @@ -0,0 +1,54 @@ +/* + * Copyright 2012, 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. + * + * Contributor: + * Dalai Felinto + * Daniel Salazar + */ + +#include "COM_MapRangeNode.h" + +#include "COM_MapRangeOperation.h" +#include "COM_ExecutionSystem.h" + +MapRangeNode::MapRangeNode(bNode *editorNode) : Node(editorNode) +{ + /* pass */ +} + +void MapRangeNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) +{ + InputSocket *valueSocket = this->getInputSocket(0); + InputSocket *sourceMinSocket = this->getInputSocket(1); + InputSocket *sourceMaxSocket = this->getInputSocket(2); + InputSocket *destMinSocket = this->getInputSocket(3); + InputSocket *destMaxSocket = this->getInputSocket(4); + OutputSocket *outputSocket = this->getOutputSocket(0); + + MapRangeOperation *operation = new MapRangeOperation(); + + valueSocket->relinkConnections(operation->getInputSocket(0), 0, graph); + sourceMinSocket->relinkConnections(operation->getInputSocket(1), 1, graph); + sourceMaxSocket->relinkConnections(operation->getInputSocket(2), 2, graph); + destMinSocket->relinkConnections(operation->getInputSocket(3), 3, graph); + destMaxSocket->relinkConnections(operation->getInputSocket(4), 4, graph); + outputSocket->relinkConnections(operation->getOutputSocket(0)); + + operation->setUseClamp(this->getbNode()->custom1); + + graph->addOperation(operation); +} diff --git a/source/blender/compositor/nodes/COM_MapRangeNode.h b/source/blender/compositor/nodes/COM_MapRangeNode.h new file mode 100644 index 00000000000..6667720be3d --- /dev/null +++ b/source/blender/compositor/nodes/COM_MapRangeNode.h @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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. + * + * Contributor: + * Dalai Felinto + * Daniel Salazar + */ + +#ifndef __COM_MAPRANGENODE_H__ +#define __COM_MAPRANGENODE_H__ + +#include "COM_Node.h" +#include "DNA_node_types.h" +/** + * @brief MapRangeNode + * @ingroup Node + */ +class MapRangeNode : public Node { +public: + MapRangeNode(bNode *editorNode); + void convertToOperations(ExecutionSystem *graph, CompositorContext *context); +}; + +#endif /* __COM_MAPRANGENODE_H__ */ diff --git a/source/blender/compositor/nodes/COM_MuteNode.cpp b/source/blender/compositor/nodes/COM_MuteNode.cpp index 4502dcf469c..de12fff3591 100644 --- a/source/blender/compositor/nodes/COM_MuteNode.cpp +++ b/source/blender/compositor/nodes/COM_MuteNode.cpp @@ -43,6 +43,10 @@ void MuteNode::reconnect(ExecutionSystem *graph, OutputSocket *output) if (input->getDataType() == output->getDataType()) { if (input->isConnected()) { output->relinkConnections(input->getConnection()->getFromSocket(), false); + /* output connections have been redirected, + * remove the input connection to completely unlink the node. + */ + input->unlinkConnections(graph); return; } } diff --git a/source/blender/compositor/nodes/COM_NormalNode.cpp b/source/blender/compositor/nodes/COM_NormalNode.cpp index e00e71e50e9..fbfff8386d0 100644 --- a/source/blender/compositor/nodes/COM_NormalNode.cpp +++ b/source/blender/compositor/nodes/COM_NormalNode.cpp @@ -41,9 +41,14 @@ void NormalNode::convertToOperations(ExecutionSystem *graph, CompositorContext * SetVectorOperation *operationSet = new SetVectorOperation(); bNodeSocket *insock = (bNodeSocket *)editorNode->outputs.first; bNodeSocketValueVector *dval = (bNodeSocketValueVector *)insock->default_value; - operationSet->setX(dval->value[0]); - operationSet->setY(dval->value[1]); - operationSet->setZ(dval->value[2]); + float normal[3]; + + /* animation can break normalization, this restores it */ + normalize_v3_v3(normal, dval->value); + + operationSet->setX(normal[0]); + operationSet->setY(normal[1]); + operationSet->setZ(normal[2]); operationSet->setW(0.0f); outputSocket->relinkConnections(operationSet->getOutputSocket(0)); diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.cpp b/source/blender/compositor/nodes/COM_OutputFileNode.cpp index 921b9e63a73..3b1871b307b 100644 --- a/source/blender/compositor/nodes/COM_OutputFileNode.cpp +++ b/source/blender/compositor/nodes/COM_OutputFileNode.cpp @@ -41,6 +41,12 @@ void OutputFileNode::convertToOperations(ExecutionSystem *graph, CompositorConte * otherwise, it overwrites the output files just * scrubbing through the timeline when the compositor updates. */ + + /* still, need to unlink input sockets to remove the node from the graph completely */ + int num_inputs = getNumberOfInputSockets(); + for (int i = 0; i < num_inputs; ++i) { + getInputSocket(i)->unlinkConnections(graph); + } return; } diff --git a/source/blender/compositor/nodes/COM_ScaleNode.cpp b/source/blender/compositor/nodes/COM_ScaleNode.cpp index c51782b77af..6f7bd33db6f 100644 --- a/source/blender/compositor/nodes/COM_ScaleNode.cpp +++ b/source/blender/compositor/nodes/COM_ScaleNode.cpp @@ -26,6 +26,7 @@ #include "COM_ExecutionSystem.h" #include "BKE_node.h" #include "COM_SetValueOperation.h" +#include "COM_SetSamplerOperation.h" ScaleNode::ScaleNode(bNode *editorNode) : Node(editorNode) { @@ -38,7 +39,9 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c InputSocket *inputXSocket = this->getInputSocket(1); InputSocket *inputYSocket = this->getInputSocket(2); OutputSocket *outputSocket = this->getOutputSocket(0); + BaseScaleOperation *scaleoperation = NULL; bNode *bnode = this->getbNode(); + switch (bnode->custom1) { case CMP_SCALE_RELATIVE: { ScaleOperation *operation = new ScaleOperation(); @@ -46,8 +49,8 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); inputXSocket->relinkConnections(operation->getInputSocket(1), 1, graph); inputYSocket->relinkConnections(operation->getInputSocket(2), 2, graph); - outputSocket->relinkConnections(operation->getOutputSocket(0)); - graph->addOperation(operation); + + scaleoperation = operation; } break; case CMP_SCALE_SCENEPERCENT: { @@ -57,9 +60,9 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); addLink(graph, scaleFactorOperation->getOutputSocket(), operation->getInputSocket(1)); addLink(graph, scaleFactorOperation->getOutputSocket(), operation->getInputSocket(2)); - outputSocket->relinkConnections(operation->getOutputSocket(0)); graph->addOperation(scaleFactorOperation); - graph->addOperation(operation); + + scaleoperation = operation; } break; @@ -75,9 +78,9 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c operation->setNewWidth(rd->xsch * rd->size / 100.0f); operation->setNewHeight(rd->ysch * rd->size / 100.0f); inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); - outputSocket->relinkConnections(operation->getOutputSocket(0)); operation->getInputSocket(0)->getConnection()->setIgnoreResizeCheck(true); - graph->addOperation(operation); + + scaleoperation = operation; } break; @@ -87,9 +90,12 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); inputXSocket->relinkConnections(operation->getInputSocket(1), 1, graph); inputYSocket->relinkConnections(operation->getInputSocket(2), 2, graph); - outputSocket->relinkConnections(operation->getOutputSocket(0)); - graph->addOperation(operation); + + scaleoperation = operation; } break; } + + outputSocket->relinkConnections(scaleoperation->getOutputSocket(0)); + graph->addOperation(scaleoperation); } diff --git a/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp b/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp index b28ee3eade1..a579503a829 100644 --- a/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp +++ b/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp @@ -72,6 +72,8 @@ void Stabilize2dNode::convertToOperations(ExecutionSystem *graph, CompositorCont addLink(graph, scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(1)); addLink(graph, scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(2)); + scaleOperation->setSampler((PixelSampler)this->getbNode()->custom1); + addLink(graph, scaleOperation->getOutputSocket(), rotateOperation->getInputSocket(0)); addLink(graph, angleAttribute->getOutputSocket(), rotateOperation->getInputSocket(1)); rotateOperation->setDoDegree2RadConversion(false); diff --git a/source/blender/compositor/operations/COM_CropOperation.cpp b/source/blender/compositor/operations/COM_CropOperation.cpp index 16c19f3ebaa..4f9cd771988 100644 --- a/source/blender/compositor/operations/COM_CropOperation.cpp +++ b/source/blender/compositor/operations/COM_CropOperation.cpp @@ -58,6 +58,12 @@ void CropBaseOperation::updateArea() this->m_ymax = max(this->m_settings->y1, this->m_settings->y2) + 1; this->m_ymin = min(this->m_settings->y1, this->m_settings->y2); } + else { + this->m_xmax = 0; + this->m_xmin = 0; + this->m_ymax = 0; + this->m_ymin = 0; + } } void CropBaseOperation::initExecution() diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp index 4bdb2591cb7..9231261986d 100644 --- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp @@ -230,6 +230,7 @@ FastGaussianBlurValueOperation::FastGaussianBlurValueOperation() : NodeOperation this->m_iirgaus = NULL; this->m_inputprogram = NULL; this->m_sigma = 1.0f; + this->m_overlay = 0; setComplex(true); } @@ -281,7 +282,7 @@ void *FastGaussianBlurValueOperation::initializeTileData(rcti *rect) if (this->m_overlay == FAST_GAUSS_OVERLAY_MIN) { float *src = newBuf->getBuffer(); float *dst = copy->getBuffer(); - for (int i = copy->getWidth() * copy->getHeight() * COM_NUMBER_OF_CHANNELS; i != 0; i--, src++, dst++) { + for (int i = copy->getWidth() * copy->getHeight(); i != 0; i--, src += COM_NUMBER_OF_CHANNELS, dst += COM_NUMBER_OF_CHANNELS) { if (*src < *dst) { *dst = *src; } @@ -290,7 +291,7 @@ void *FastGaussianBlurValueOperation::initializeTileData(rcti *rect) else if (this->m_overlay == FAST_GAUSS_OVERLAY_MAX) { float *src = newBuf->getBuffer(); float *dst = copy->getBuffer(); - for (int i = copy->getWidth() * copy->getHeight() * COM_NUMBER_OF_CHANNELS; i != 0; i--, src++, dst++) { + for (int i = copy->getWidth() * copy->getHeight(); i != 0; i--, src += COM_NUMBER_OF_CHANNELS, dst += COM_NUMBER_OF_CHANNELS) { if (*src > *dst) { *dst = *src; } diff --git a/source/blender/compositor/operations/COM_GammaCorrectOperation.cpp b/source/blender/compositor/operations/COM_GammaCorrectOperation.cpp index af990f4f3e0..8f92dc02a57 100644 --- a/source/blender/compositor/operations/COM_GammaCorrectOperation.cpp +++ b/source/blender/compositor/operations/COM_GammaCorrectOperation.cpp @@ -48,15 +48,13 @@ void GammaCorrectOperation::executePixel(float output[4], float x, float y, Pixe output[0] = inputColor[0] > 0.0f ? inputColor[0] * inputColor[0] : 0.0f; output[1] = inputColor[1] > 0.0f ? inputColor[1] * inputColor[1] : 0.0f; output[2] = inputColor[2] > 0.0f ? inputColor[2] * inputColor[2] : 0.0f; - - inputColor[0] *= inputColor[3]; - inputColor[1] *= inputColor[3]; - inputColor[2] *= inputColor[3]; - - output[0] = inputColor[0]; - output[1] = inputColor[1]; - output[2] = inputColor[2]; output[3] = inputColor[3]; + + if (inputColor[3] > 0.0f) { + output[0] *= inputColor[3]; + output[1] *= inputColor[3]; + output[2] *= inputColor[3]; + } } void GammaCorrectOperation::deinitExecution() @@ -89,15 +87,13 @@ void GammaUncorrectOperation::executePixel(float output[4], float x, float y, Pi output[0] = inputColor[0] > 0.0f ? sqrtf(inputColor[0]) : 0.0f; output[1] = inputColor[1] > 0.0f ? sqrtf(inputColor[1]) : 0.0f; output[2] = inputColor[2] > 0.0f ? sqrtf(inputColor[2]) : 0.0f; - - inputColor[0] *= inputColor[3]; - inputColor[1] *= inputColor[3]; - inputColor[2] *= inputColor[3]; - - output[0] = inputColor[0]; - output[1] = inputColor[1]; - output[2] = inputColor[2]; output[3] = inputColor[3]; + + if (inputColor[3] > 0.0f) { + output[0] *= inputColor[3]; + output[1] *= inputColor[3]; + output[2] *= inputColor[3]; + } } void GammaUncorrectOperation::deinitExecution() diff --git a/source/blender/compositor/operations/COM_ImageOperation.cpp b/source/blender/compositor/operations/COM_ImageOperation.cpp index fb3efbb67ed..84557118a1c 100644 --- a/source/blender/compositor/operations/COM_ImageOperation.cpp +++ b/source/blender/compositor/operations/COM_ImageOperation.cpp @@ -65,8 +65,9 @@ ImBuf *BaseImageOperation::getImBuf() { ImBuf *ibuf; - ibuf = BKE_image_get_ibuf(this->m_image, this->m_imageUser); + ibuf = BKE_image_acquire_ibuf(this->m_image, this->m_imageUser, NULL); if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) { + BKE_image_release_ibuf(this->m_image, ibuf, NULL); return NULL; } @@ -93,6 +94,7 @@ void BaseImageOperation::initExecution() void BaseImageOperation::deinitExecution() { this->m_imageBuffer = NULL; + BKE_image_release_ibuf(this->m_image, this->m_buffer, NULL); } void BaseImageOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) @@ -106,6 +108,8 @@ void BaseImageOperation::determineResolution(unsigned int resolution[2], unsigne resolution[0] = stackbuf->x; resolution[1] = stackbuf->y; } + + BKE_image_release_ibuf(this->m_image, stackbuf, NULL); } void ImageOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp index c9b129d8dcf..201dc99eb9e 100644 --- a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp @@ -151,22 +151,25 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, TRUE, FALSE); zero_v3(site->color); - for (j = 0; j < pattern_ibuf->x * pattern_ibuf->y; j++) { - if (pattern_ibuf->rect_float) { - add_v3_v3(site->color, &pattern_ibuf->rect_float[4 * j]); - } - else { - unsigned char *rrgb = (unsigned char *)pattern_ibuf->rect; - site->color[0] += srgb_to_linearrgb((float)rrgb[4 * j + 0] / 255.0f); - site->color[1] += srgb_to_linearrgb((float)rrgb[4 * j + 1] / 255.0f); - site->color[2] += srgb_to_linearrgb((float)rrgb[4 * j + 2] / 255.0f); + if (pattern_ibuf) { + for (j = 0; j < pattern_ibuf->x * pattern_ibuf->y; j++) { + if (pattern_ibuf->rect_float) { + add_v3_v3(site->color, &pattern_ibuf->rect_float[4 * j]); + } + else { + unsigned char *rrgb = (unsigned char *)pattern_ibuf->rect; + + site->color[0] += srgb_to_linearrgb((float)rrgb[4 * j + 0] / 255.0f); + site->color[1] += srgb_to_linearrgb((float)rrgb[4 * j + 1] / 255.0f); + site->color[2] += srgb_to_linearrgb((float)rrgb[4 * j + 2] / 255.0f); + } } + + mul_v3_fl(site->color, 1.0f / (pattern_ibuf->x * pattern_ibuf->y)); + IMB_freeImBuf(pattern_ibuf); } - mul_v3_fl(site->color, 1.0f / (pattern_ibuf->x * pattern_ibuf->y)); - IMB_freeImBuf(pattern_ibuf); - site->co[0] = pos[0] * width; site->co[1] = pos[1] * height; @@ -199,9 +202,9 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri INIT_MINMAX2(min, max); - DO_MINMAX2(a->co, min, max); - DO_MINMAX2(b->co, min, max); - DO_MINMAX2(c->co, min, max); + minmax_v2v2_v2(min, max, a->co); + minmax_v2v2_v2(min, max, b->co); + minmax_v2v2_v2(min, max, c->co); rect->xmin = min[0]; rect->ymin = min[1]; diff --git a/source/blender/compositor/operations/COM_MapRangeOperation.cpp b/source/blender/compositor/operations/COM_MapRangeOperation.cpp new file mode 100644 index 00000000000..1fe74ade0fc --- /dev/null +++ b/source/blender/compositor/operations/COM_MapRangeOperation.cpp @@ -0,0 +1,96 @@ +/* + * Copyright 2012, 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. + * + * Contributor: + * Dalai Felinto + * Daniel Salazar + */ + +#include "COM_MapRangeOperation.h" + +MapRangeOperation::MapRangeOperation() : NodeOperation() +{ + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); + this->m_inputOperation = NULL; + this->m_useClamp = FALSE; +} + +void MapRangeOperation::initExecution() +{ + this->m_inputOperation = this->getInputSocketReader(0); + this->m_sourceMinOperation = this->getInputSocketReader(1); + this->m_sourceMaxOperation = this->getInputSocketReader(2); + this->m_destMinOperation = this->getInputSocketReader(3); + this->m_destMaxOperation = this->getInputSocketReader(4); +} + +/* The code below assumes all data is inside range +- this, and that input buffer is single channel */ +#define BLENDER_ZMAX 10000.0f + +void MapRangeOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputs[8]; /* includes the 5 inputs + 3 pads */ + float value; + float source_min, source_max; + float dest_min, dest_max; + + this->m_inputOperation->read(inputs, x, y, sampler); + this->m_sourceMinOperation->read(inputs + 1, x, y, sampler); + this->m_sourceMaxOperation->read(inputs + 2, x, y, sampler); + this->m_destMinOperation->read(inputs + 3, x, y, sampler); + this->m_destMaxOperation->read(inputs + 4, x, y, sampler); + + value = inputs[0]; + source_min = inputs[1]; + source_max = inputs[2]; + dest_min = inputs[3]; + dest_max = inputs[4]; + + if (value >= -BLENDER_ZMAX && value <= BLENDER_ZMAX) { + value = (value - source_min) / (source_max - source_min); + value = dest_min + value * (dest_max - dest_min); + } + else if (value > BLENDER_ZMAX) + value = dest_max; + else + value = dest_min; + + if (this->m_useClamp) { + if (dest_max > dest_min) { + CLAMP(value, dest_min, dest_max); + } + else { + CLAMP(value, dest_max, dest_min); + } + } + + output[0] = value; +} + +void MapRangeOperation::deinitExecution() +{ + this->m_inputOperation = NULL; + this->m_sourceMinOperation = NULL; + this->m_sourceMaxOperation = NULL; + this->m_destMinOperation = NULL; + this->m_destMaxOperation = NULL; +} diff --git a/source/blender/compositor/operations/COM_MapRangeOperation.h b/source/blender/compositor/operations/COM_MapRangeOperation.h new file mode 100644 index 00000000000..00dfc68168c --- /dev/null +++ b/source/blender/compositor/operations/COM_MapRangeOperation.h @@ -0,0 +1,71 @@ +/* + * Copyright 2012, 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. + * + * Contributor: + * Dalai Felinto + * Daniel Salazar + */ + +#ifndef _COM_MapRangeOperation_h +#define _COM_MapRangeOperation_h +#include "COM_NodeOperation.h" +#include "DNA_texture_types.h" + +/** + * this program converts an input color to an output value. + * it assumes we are in sRGB color space. + */ +class MapRangeOperation : public NodeOperation { +private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputOperation; + SocketReader *m_sourceMinOperation; + SocketReader *m_sourceMaxOperation; + SocketReader *m_destMinOperation; + SocketReader *m_destMaxOperation; + + bool m_useClamp; +public: + /** + * Default constructor + */ + MapRangeOperation(); + + /** + * the inner loop of this program + */ + void executePixel(float output[4], float x, float y, PixelSampler sampler); + + /** + * Initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + /** + * Clamp the output + */ + void setUseClamp(bool value) { this->m_useClamp = value; } + +}; +#endif diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp index df48c7a6716..68a61dff801 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp @@ -50,6 +50,7 @@ MovieDistortionOperation::MovieDistortionOperation(bool distortion) : NodeOperat this->m_cache = NULL; this->m_distortion = distortion; } + void MovieDistortionOperation::initExecution() { this->m_inputOperation = this->getInputSocketReader(0); @@ -105,21 +106,9 @@ void MovieDistortionOperation::executePixel(float output[4], float x, float y, P if (this->m_cache != NULL) { float u, v; this->m_cache->getUV(&this->m_movieClip->tracking, x, y, &u, &v); - this->m_inputOperation->read(output, u, v, sampler); + this->m_inputOperation->read(output, u, v, COM_PS_BILINEAR); } else { - this->m_inputOperation->read(output, x, y, sampler); + this->m_inputOperation->read(output, x, y, COM_PS_BILINEAR); } } - -bool MovieDistortionOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) -{ - rcti newInput; - - newInput.xmax = input->xmax + 100; - newInput.xmin = input->xmin - 100; - newInput.ymax = input->ymax + 100; - newInput.ymin = input->ymin - 100; - - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); -} diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.h b/source/blender/compositor/operations/COM_MovieDistortionOperation.h index 93cc555fdbc..9f8aa065e3e 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.h +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.h @@ -155,7 +155,6 @@ protected: public: MovieDistortionOperation(bool distortion); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); void executePixel(float output[4], float x, float y, PixelSampler sampler); void initExecution(); diff --git a/source/blender/compositor/operations/COM_NormalizeOperation.cpp b/source/blender/compositor/operations/COM_NormalizeOperation.cpp index 5f7ac6bb9ca..f81b50e6836 100644 --- a/source/blender/compositor/operations/COM_NormalizeOperation.cpp +++ b/source/blender/compositor/operations/COM_NormalizeOperation.cpp @@ -43,6 +43,12 @@ void NormalizeOperation::executePixel(float output[4], int x, int y, void *data) this->m_imageReader->read(output, x, y, NULL); output[0] = (output[0] - minmult->x) * minmult->y; + + /* clamp infinities */ + if (output[0] > 1.0f) + output[0] = 1.0f; + else if (output[0] < 0.0f) + output[0] = 0.0f; } void NormalizeOperation::deinitExecution() diff --git a/source/blender/compositor/operations/COM_PixelateOperation.h b/source/blender/compositor/operations/COM_PixelateOperation.h index b16b21b2ec1..83603a59331 100644 --- a/source/blender/compositor/operations/COM_PixelateOperation.h +++ b/source/blender/compositor/operations/COM_PixelateOperation.h @@ -35,7 +35,7 @@ class PixelateOperation : public NodeOperation { private: /** - * @brief cached refeerence to the input operation + * @brief cached reference to the input operation */ SocketReader *m_inputOperation; public: diff --git a/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp b/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp index a4015c6283f..2ca499683d3 100644 --- a/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp +++ b/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp @@ -69,6 +69,46 @@ void RenderLayersBaseProg::initExecution() } } +void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler) +{ + unsigned int offset; + int ix, iy; + int width = this->getWidth(), height = this->getHeight(); + + switch (sampler) { + case COM_PS_NEAREST: + ix = x; + iy = y; + offset = (iy * width + ix) * this->m_elementsize; + + if (this->m_elementsize == 1) + output[0] = this->m_inputBuffer[offset]; + else if (this->m_elementsize == 3) + copy_v3_v3(output, &this->m_inputBuffer[offset]); + else + copy_v4_v4(output, &this->m_inputBuffer[offset]); + + break; + + case COM_PS_BILINEAR: + BLI_bilinear_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); + break; + + case COM_PS_BICUBIC: + BLI_bicubic_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); + break; + } + + if (this->m_elementsize == 1) { + output[1] = 0.0f; + output[2] = 0.0f; + output[3] = 0.0f; + } + else if (this->m_elementsize == 3) { + output[3] = 1.0f; + } +} + void RenderLayersBaseProg::executePixel(float output[4], float x, float y, PixelSampler sampler) { int ix = x; @@ -78,20 +118,7 @@ void RenderLayersBaseProg::executePixel(float output[4], float x, float y, Pixel zero_v4(output); } else { - unsigned int offset = (iy * this->getWidth() + ix) * this->m_elementsize; - if (this->m_elementsize == 1) { - output[0] = this->m_inputBuffer[offset]; - output[1] = 0.0f; - output[2] = 0.0f; - output[3] = 0.0f; - } - else if (this->m_elementsize == 3) { - copy_v3_v3(output, &this->m_inputBuffer[offset]); - output[3] = 1.0f; - } - else { - copy_v4_v4(output, &this->m_inputBuffer[offset]); - } + doInterpolation(output, x, y, sampler); } } diff --git a/source/blender/compositor/operations/COM_RenderLayersBaseProg.h b/source/blender/compositor/operations/COM_RenderLayersBaseProg.h index ea57d4bc421..3916862a0b3 100644 --- a/source/blender/compositor/operations/COM_RenderLayersBaseProg.h +++ b/source/blender/compositor/operations/COM_RenderLayersBaseProg.h @@ -80,6 +80,7 @@ protected: */ inline float *getInputBuffer() { return this->m_inputBuffer; } + void doInterpolation(float output[4], float x, float y, PixelSampler sampler); public: /** * setter for the scene field. Will be called from diff --git a/source/blender/compositor/operations/COM_ScaleOperation.cpp b/source/blender/compositor/operations/COM_ScaleOperation.cpp index 276b2f54b6e..9e8f5af0ef0 100644 --- a/source/blender/compositor/operations/COM_ScaleOperation.cpp +++ b/source/blender/compositor/operations/COM_ScaleOperation.cpp @@ -29,7 +29,16 @@ * note: use bilinear because bicubic makes fuzzy even when not scaling at all (1:1) */ -ScaleOperation::ScaleOperation() : NodeOperation() +BaseScaleOperation::BaseScaleOperation() +{ +#ifdef USE_FORCE_BILINEAR + m_sampler = (int) COM_PS_BILINEAR; +#else + m_sampler = -1; +#endif +} + +ScaleOperation::ScaleOperation() : BaseScaleOperation() { this->addInputSocket(COM_DT_COLOR); this->addInputSocket(COM_DT_VALUE); @@ -59,22 +68,20 @@ void ScaleOperation::deinitExecution() void ScaleOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) { -#ifdef USE_FORCE_BILINEAR - sampler = COM_PS_BILINEAR; -#endif + PixelSampler effective_sampler = getEffectiveSampler(sampler); float scaleX[4]; float scaleY[4]; - this->m_inputXOperation->read(scaleX, x, y, sampler); - this->m_inputYOperation->read(scaleY, x, y, sampler); + this->m_inputXOperation->read(scaleX, x, y, effective_sampler); + this->m_inputYOperation->read(scaleY, x, y, effective_sampler); const float scx = scaleX[0]; const float scy = scaleY[0]; float nx = this->m_centerX + (x - this->m_centerX) / scx; float ny = this->m_centerY + (y - this->m_centerY) / scy; - this->m_inputOperation->read(output, nx, ny, sampler); + this->m_inputOperation->read(output, nx, ny, effective_sampler); } bool ScaleOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) @@ -94,12 +101,12 @@ bool ScaleOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOpe newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / scy; newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / scy; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } // SCALE ABSOLUTE -ScaleAbsoluteOperation::ScaleAbsoluteOperation() : NodeOperation() +ScaleAbsoluteOperation::ScaleAbsoluteOperation() : BaseScaleOperation() { this->addInputSocket(COM_DT_COLOR); this->addInputSocket(COM_DT_VALUE); @@ -129,15 +136,13 @@ void ScaleAbsoluteOperation::deinitExecution() void ScaleAbsoluteOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) { -#ifdef USE_FORCE_BILINEAR - sampler = COM_PS_BILINEAR; -#endif + PixelSampler effective_sampler = getEffectiveSampler(sampler); float scaleX[4]; float scaleY[4]; - this->m_inputXOperation->read(scaleX, x, y, sampler); - this->m_inputYOperation->read(scaleY, x, y, sampler); + this->m_inputXOperation->read(scaleX, x, y, effective_sampler); + this->m_inputYOperation->read(scaleY, x, y, effective_sampler); const float scx = scaleX[0]; // target absolute scale const float scy = scaleY[0]; // target absolute scale @@ -151,7 +156,7 @@ void ScaleAbsoluteOperation::executePixel(float output[4], float x, float y, Pix float nx = this->m_centerX + (x - this->m_centerX) / relativeXScale; float ny = this->m_centerY + (y - this->m_centerY) / relativeYScale; - this->m_inputOperation->read(output, nx, ny, sampler); + this->m_inputOperation->read(output, nx, ny, effective_sampler); } bool ScaleAbsoluteOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) @@ -176,12 +181,12 @@ bool ScaleAbsoluteOperation::determineDependingAreaOfInterest(rcti *input, ReadB newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / relateveYScale; newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / relateveYScale; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } // Absolute fixed siez -ScaleFixedSizeOperation::ScaleFixedSizeOperation() : NodeOperation() +ScaleFixedSizeOperation::ScaleFixedSizeOperation() : BaseScaleOperation() { this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); this->addOutputSocket(COM_DT_COLOR); @@ -250,17 +255,15 @@ void ScaleFixedSizeOperation::deinitExecution() void ScaleFixedSizeOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) { -#ifdef USE_FORCE_BILINEAR - sampler = COM_PS_BILINEAR; -#endif + PixelSampler effective_sampler = getEffectiveSampler(sampler); if (this->m_is_offset) { float nx = ((x - this->m_offsetX) * this->m_relX); float ny = ((y - this->m_offsetY) * this->m_relY); - this->m_inputOperation->read(output, nx, ny, sampler); + this->m_inputOperation->read(output, nx, ny, effective_sampler); } else { - this->m_inputOperation->read(output, x * this->m_relX, y * this->m_relY, sampler); + this->m_inputOperation->read(output, x * this->m_relX, y * this->m_relY, effective_sampler); } } @@ -273,7 +276,7 @@ bool ScaleFixedSizeOperation::determineDependingAreaOfInterest(rcti *input, Read newInput.ymax = input->ymax * this->m_relY; newInput.ymin = input->ymin * this->m_relY; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } void ScaleFixedSizeOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) @@ -281,7 +284,7 @@ void ScaleFixedSizeOperation::determineResolution(unsigned int resolution[2], un unsigned int nr[2]; nr[0] = this->m_newWidth; nr[1] = this->m_newHeight; - NodeOperation::determineResolution(resolution, nr); + BaseScaleOperation::determineResolution(resolution, nr); resolution[0] = this->m_newWidth; resolution[1] = this->m_newHeight; } diff --git a/source/blender/compositor/operations/COM_ScaleOperation.h b/source/blender/compositor/operations/COM_ScaleOperation.h index 4239ff063fb..f42cdbd78ed 100644 --- a/source/blender/compositor/operations/COM_ScaleOperation.h +++ b/source/blender/compositor/operations/COM_ScaleOperation.h @@ -25,7 +25,19 @@ #include "COM_NodeOperation.h" -class ScaleOperation : public NodeOperation { +class BaseScaleOperation : public NodeOperation { +public: + void setSampler(PixelSampler sampler) { this->m_sampler = (int) sampler; } + +protected: + BaseScaleOperation(); + + PixelSampler getEffectiveSampler(PixelSampler sampler) { return (m_sampler == -1) ? sampler : (PixelSampler) m_sampler; } + + int m_sampler; +}; + +class ScaleOperation : public BaseScaleOperation { private: SocketReader *m_inputOperation; SocketReader *m_inputXOperation; @@ -41,7 +53,7 @@ public: void deinitExecution(); }; -class ScaleAbsoluteOperation : public NodeOperation { +class ScaleAbsoluteOperation : public BaseScaleOperation { SocketReader *m_inputOperation; SocketReader *m_inputXOperation; SocketReader *m_inputYOperation; @@ -57,7 +69,7 @@ public: void deinitExecution(); }; -class ScaleFixedSizeOperation : public NodeOperation { +class ScaleFixedSizeOperation : public BaseScaleOperation { SocketReader *m_inputOperation; int m_newWidth; int m_newHeight; diff --git a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp index d41d1c128da..8b5288321c1 100644 --- a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp +++ b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp @@ -92,7 +92,7 @@ void TrackPositionOperation::initExecution() } else if (this->m_position == POSITION_RELATIVE_FRAME) { int relative_clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, - this->m_relativeFrame); + this->m_relativeFrame); marker = BKE_tracking_marker_get(track, relative_clip_framenr); copy_v2_v2(this->m_relativePos, marker->pos); diff --git a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp index 4d4c1199f3e..d5f2c283c72 100644 --- a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp @@ -87,27 +87,23 @@ void ViewerBaseOperation::initImage() /* now we combine the input with ibuf */ this->m_outputBuffer = ibuf->rect_float; - /* needed for display buffer update - * - * no need to lock / reference the image buffer because it's seems - * to be the single place which changes buffers of viewer image - * which is this node - */ + /* needed for display buffer update */ this->m_ibuf = ibuf; if (m_doDepthBuffer) { this->m_depthBuffer = ibuf->zbuf_float; } - BKE_image_release_ibuf(this->m_image, this->m_lock); + BKE_image_release_ibuf(this->m_image, this->m_ibuf, this->m_lock); } + void ViewerBaseOperation:: updateImage(rcti *rect) { IMB_partial_display_buffer_update(this->m_ibuf, this->m_outputBuffer, NULL, getWidth(), 0, 0, this->m_viewSettings, this->m_displaySettings, rect->xmin, rect->ymin, rect->xmax, rect->ymax, FALSE); - WM_main_add_notifier(NC_WINDOW | ND_DRAW, NULL); + this->updateDraw(); } void ViewerBaseOperation::deinitExecution() diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index f19dbe740bc..fe836204c27 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -1560,6 +1560,8 @@ static int animchannels_setflag_exec(bContext *C, wmOperator *op) /* duplicate of 'ANIM_OT_channels_setting_toggle' for menu title only, weak! */ static void ANIM_OT_channels_setting_enable(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Enable Channel Setting"; ot->idname = "ANIM_OT_channels_setting_enable"; @@ -1575,13 +1577,16 @@ static void ANIM_OT_channels_setting_enable(wmOperatorType *ot) /* props */ /* flag-setting mode */ - RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_ADD, "Mode", ""); + prop = RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_ADD, "Mode", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); /* setting to set */ ot->prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", ""); } /* duplicate of 'ANIM_OT_channels_setting_toggle' for menu title only, weak! */ static void ANIM_OT_channels_setting_disable(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Disable Channel Setting"; ot->idname = "ANIM_OT_channels_setting_disable"; @@ -1597,13 +1602,16 @@ static void ANIM_OT_channels_setting_disable(wmOperatorType *ot) /* props */ /* flag-setting mode */ - RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_CLEAR, "Mode", ""); + prop = RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_CLEAR, "Mode", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); /* internal hack - don't expose */ /* setting to set */ ot->prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", ""); } static void ANIM_OT_channels_setting_toggle(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Toggle Channel Setting"; ot->idname = "ANIM_OT_channels_setting_toggle"; @@ -1619,13 +1627,16 @@ static void ANIM_OT_channels_setting_toggle(wmOperatorType *ot) /* props */ /* flag-setting mode */ - RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", ""); + prop = RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); /* internal hack - don't expose */ /* setting to set */ ot->prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", ""); } static void ANIM_OT_channels_editable_toggle(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Toggle Channel Editability"; ot->idname = "ANIM_OT_channels_editable_toggle"; @@ -1642,7 +1653,8 @@ static void ANIM_OT_channels_editable_toggle(wmOperatorType *ot) /* flag-setting mode */ RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", ""); /* setting to set */ - RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, ACHANNEL_SETTING_PROTECT, "Type", ""); + prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, ACHANNEL_SETTING_PROTECT, "Type", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); /* internal hack - don't expose */ } /* ********************** Expand Channels Operator *********************** */ diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 01c0a95e200..0f0584ad8fe 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -381,7 +381,7 @@ float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short rest return RAD2DEGF(1.0f); /* radians to degrees */ } } - + /* TODO: other rotation types here as necessary */ } } diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 721b3473792..5e215fbd6a2 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -175,7 +175,7 @@ static short actedit_get_context(bAnimContext *ac, SpaceAction *saction) return 1; case SACTCONT_MASK: /* Mask */ /* XXX review how this mode is handled... */ -{ + { /* TODO, other methods to get the mask */ // Sequence *seq = BKE_sequencer_active_get(ac->scene); //MovieClip *clip = ac->scene->clip; @@ -189,7 +189,7 @@ static short actedit_get_context(bAnimContext *ac, SpaceAction *saction) ac->mode = saction->mode; return 1; -} + } case SACTCONT_DOPESHEET: /* DopeSheet */ /* update scene-pointer (no need to check for pinning yet, as not implemented) */ saction->ads.source = (ID *)ac->scene; @@ -911,14 +911,16 @@ static short skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_i /* only consider if F-Curve involves sequence_editor.sequences */ if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) { Editing *ed = BKE_sequencer_editing_get(scene, FALSE); - Sequence *seq; + Sequence *seq = NULL; char *seq_name; - - /* get strip name, and check if this strip is selected */ - seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all["); - seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, FALSE); - if (seq_name) MEM_freeN(seq_name); - + + if (ed) { + /* get strip name, and check if this strip is selected */ + seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all["); + seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, FALSE); + if (seq_name) MEM_freeN(seq_name); + } + /* can only add this F-Curve if it is selected */ if (ads->filterflag & ADS_FILTER_ONLYSEL) { if ((seq == NULL) || (seq->flag & SELECT) == 0) diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 852f3fa5469..1b980790fdc 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -706,8 +706,13 @@ static int ed_marker_move_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *e } /* note, init has to be called succesfully */ -static void ed_marker_move_apply(wmOperator *op) +static void ed_marker_move_apply(bContext *C, wmOperator *op) { +#ifdef DURIAN_CAMERA_SWITCH + bScreen *sc = CTX_wm_screen(C); + Scene *scene = CTX_data_scene(C); + Object *camera = scene->camera; +#endif MarkerMove *mm = op->customdata; TimeMarker *marker; int a, offs; @@ -719,17 +724,27 @@ static void ed_marker_move_apply(wmOperator *op) a++; } } + + WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL); + WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL); + +#ifdef DURIAN_CAMERA_SWITCH + /* so we get view3d redraws */ + BKE_scene_camera_switch_update(scene); + + if (camera != scene->camera) { + BKE_screen_view3d_scene_sync(sc); + WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene); + } +#endif } /* only for modal */ static int ed_marker_move_cancel(bContext *C, wmOperator *op) { RNA_int_set(op->ptr, "frames", 0); - ed_marker_move_apply(op); + ed_marker_move_apply(C, op); ed_marker_move_exit(C, op); - - WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL); - WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL); return OPERATOR_CANCELLED; } @@ -789,7 +804,7 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) offs = (int)fac; RNA_int_set(op->ptr, "frames", offs); - ed_marker_move_apply(op); + ed_marker_move_apply(C, op); /* cruft below is for header print */ for (a = 0, marker = mm->markers->first; marker; marker = marker->next) { @@ -840,29 +855,29 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) } } - WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL); - WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL); ED_area_headerprint(CTX_wm_area(C), str); } } if (evt->val == KM_PRESS) { - float vec; - char str_tx[NUM_STR_REP_LEN]; - if (handleNumInput(&mm->num, evt)) { - applyNumInput(&mm->num, &vec); - outputNumInput(&mm->num, str_tx); - - RNA_int_set(op->ptr, "frames", vec); - ed_marker_move_apply(op); - // ed_marker_header_update(C, op, str, (int)vec[0]); + char str_tx[NUM_STR_REP_LEN]; + float value = RNA_int_get(op->ptr, "frames"); + applyNumInput(&mm->num, &value); + + if (hasNumInput(&mm->num)) { + outputNumInput(&mm->num, str_tx); + } + else { + BLI_snprintf(str_tx, sizeof(str_tx), "%d", (int)value); + } + + RNA_int_set(op->ptr, "frames", value); + ed_marker_move_apply(C, op); + // ed_marker_header_update(C, op, str, (int)value); // strcat(str, str_tx); BLI_snprintf(str, sizeof(str), "Marker offset %s", str_tx); ED_area_headerprint(CTX_wm_area(C), str); - - WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL); - WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL); } } @@ -872,7 +887,7 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) static int ed_marker_move_exec(bContext *C, wmOperator *op) { if (ed_marker_move_init(C, op)) { - ed_marker_move_apply(op); + ed_marker_move_apply(C, op); ed_marker_move_exit(C, op); return OPERATOR_FINISHED; } @@ -1394,6 +1409,11 @@ static int ed_marker_make_links_scene_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int ed_marker_make_links_scene_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt) +{ + return ed_markers_opwrap_invoke_custom(C, op, evt, WM_menu_invoke); +} + static void MARKER_OT_make_links_scene(wmOperatorType *ot) { PropertyRNA *prop; @@ -1405,7 +1425,7 @@ static void MARKER_OT_make_links_scene(wmOperatorType *ot) /* api callbacks */ ot->exec = ed_marker_make_links_scene_exec; - ot->invoke = ed_markers_opwrap_invoke; + ot->invoke = ed_marker_make_links_scene_invoke_wrapper; ot->poll = ed_markers_poll_selected_markers; /* flags */ diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index ae7abd82600..28db7bf572d 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -325,8 +325,9 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Cannot add property to built in keying set"); return OPERATOR_CANCELLED; } - else + else { ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1); + } /* try to add to keyingset using property retrieved from UI */ uiContextActiveProperty(C, &ptr, &prop, &index); @@ -360,9 +361,10 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op) if (success) { /* send updates */ DAG_ids_flush_update(bmain, 0); - - /* for now, only send ND_KEYS for KeyingSets */ WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL); + + /* show notification/report header, so that users notice that something changed */ + BKE_reportf(op->reports, RPT_INFO, "Property added to Keying Set: '%s'", ks->name); } return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; @@ -411,8 +413,9 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Cannot remove property from built in keying set"); return OPERATOR_CANCELLED; } - else + else { ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1); + } /* try to add to keyingset using property retrieved from UI */ uiContextActiveProperty(C, &ptr, &prop, &index); @@ -425,7 +428,7 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op) /* try to find a path matching this description */ ksp = BKE_keyingset_find_path(ks, ptr.id.data, ks->name, path, index, KSP_GROUP_KSNAME); - + if (ksp) { BKE_keyingset_free_path(ks, ksp); success = 1; @@ -440,9 +443,10 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op) if (success) { /* send updates */ DAG_ids_flush_update(bmain, 0); - - /* for now, only send ND_KEYS for KeyingSets */ WM_event_add_notifier(C, NC_SCENE | ND_KEYINGSET, NULL); + + /* show warning */ + BKE_report(op->reports, RPT_INFO, "Property removed from Keying Set"); } return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; @@ -891,11 +895,13 @@ short ANIM_validate_keyingset(bContext *C, ListBase *dsources, KeyingSet *ks) ksi->iter(ksi, C, ks); /* if we don't have any paths now, then this still qualifies as invalid context */ + // FIXME: we need some error conditions (to be retrieved from the iterator why this failed!) if (ks->paths.first == NULL) return MODIFYKEY_INVALID_CONTEXT; } else { /* poll callback tells us that KeyingSet is useless in current context */ + // FIXME: the poll callback needs to give us more info why return MODIFYKEY_INVALID_CONTEXT; } } diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 48da23d5e8d..e801d3689e5 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -3569,16 +3569,16 @@ static int armature_subdivide_exec(bContext *C, wmOperator *op) Object *obedit = CTX_data_edit_object(C); bArmature *arm = obedit->data; EditBone *newbone, *tbone; - int numcuts, i; + int cuts, i; /* there may not be a number_cuts property defined (for 'simple' subdivide) */ - numcuts = RNA_int_get(op->ptr, "number_cuts"); + cuts = RNA_int_get(op->ptr, "number_cuts"); /* loop over all editable bones */ // XXX the old code did this in reverse order though! CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) { - for (i = numcuts + 1; i > 1; i--) { + for (i = cuts + 1; i > 1; i--) { /* compute cut ratio first */ float cutratio = 1.0f / (float)i; float cutratioI = 1.0f - cutratio; diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c index da8fc328343..f9cf4a29269 100644 --- a/source/blender/editors/armature/editarmature_sketch.c +++ b/source/blender/editors/armature/editarmature_sketch.c @@ -2104,15 +2104,15 @@ static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch, if (sketch->depth_peels.first != NULL) { float colors[8][3] = { - {1, 0, 0}, - {0, 1, 0}, - {0, 0, 1}, - {1, 1, 0}, - {1, 0, 1}, - {0, 1, 1}, - {1, 1, 1}, - {0, 0, 0} - }; + {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}, + {1, 1, 0}, + {1, 0, 1}, + {0, 1, 1}, + {1, 1, 1}, + {0, 0, 0} + }; DepthPeel *p; GLUquadric *quad = gluNewQuadric(); gluQuadricNormals(quad, GLU_SMOOTH); diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 485d73974cd..23fed4ce8fc 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -1069,7 +1069,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) Nurb *nu = editnurb->nurbs.first; CVKeyIndex *keyIndex; char rna_path[64], orig_rna_path[64]; - AnimData *ad = BKE_animdata_from_id(&cu->id); + AnimData *adt = BKE_animdata_from_id(&cu->id); ListBase curves = {NULL, NULL}; FCurve *fcu, *next; @@ -1089,14 +1089,14 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) char handle_path[64], orig_handle_path[64]; BLI_snprintf(orig_handle_path, sizeof(orig_rna_path), "%s.handle_left", orig_rna_path); BLI_snprintf(handle_path, sizeof(rna_path), "%s.handle_right", rna_path); - fcurve_path_rename(ad, orig_handle_path, handle_path, orig_curves, &curves); + fcurve_path_rename(adt, orig_handle_path, handle_path, orig_curves, &curves); BLI_snprintf(orig_handle_path, sizeof(orig_rna_path), "%s.handle_right", orig_rna_path); BLI_snprintf(handle_path, sizeof(rna_path), "%s.handle_left", rna_path); - fcurve_path_rename(ad, orig_handle_path, handle_path, orig_curves, &curves); + fcurve_path_rename(adt, orig_handle_path, handle_path, orig_curves, &curves); } - fcurve_path_rename(ad, orig_rna_path, rna_path, orig_curves, &curves); + fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves); keyIndex->nu_index = nu_index; keyIndex->pt_index = pt_index; @@ -1116,7 +1116,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) if (keyIndex) { BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d].points[%d]", nu_index, pt_index); BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d].points[%d]", keyIndex->nu_index, keyIndex->pt_index); - fcurve_path_rename(ad, orig_rna_path, rna_path, orig_curves, &curves); + fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves); keyIndex->nu_index = nu_index; keyIndex->pt_index = pt_index; @@ -1140,7 +1140,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) char *ch = strchr(fcu->rna_path, '.'); if (ch && (!strncmp(ch, ".bezier_points", 14) || !strncmp(ch, ".points", 7))) - fcurve_remove(ad, orig_curves, fcu); + fcurve_remove(adt, orig_curves, fcu); } } @@ -1156,7 +1156,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) if (keyIndex) { BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d]", nu_index); BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d]", keyIndex->nu_index); - fcurve_path_rename(ad, orig_rna_path, rna_path, orig_curves, &curves); + fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves); } nu_index++; @@ -1168,7 +1168,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) for (fcu = orig_curves->first; fcu; fcu = next) { next = fcu->next; - if (!strncmp(fcu->rna_path, "splines", 7)) fcurve_remove(ad, orig_curves, fcu); + if (!strncmp(fcu->rna_path, "splines", 7)) fcurve_remove(adt, orig_curves, fcu); else BLI_addtail(&curves, fcu); } @@ -1178,14 +1178,14 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) /* return 0 if animation data wasn't changed, 1 otherwise */ int ED_curve_updateAnimPaths(Curve *cu) { - AnimData *ad = BKE_animdata_from_id(&cu->id); + AnimData *adt = BKE_animdata_from_id(&cu->id); if (!curve_is_animated(cu)) return 0; - if (ad->action) - curve_rename_fcurves(cu, &ad->action->curves); + if (adt->action) + curve_rename_fcurves(cu, &adt->action->curves); - curve_rename_fcurves(cu, &ad->drivers); + curve_rename_fcurves(cu, &adt->drivers); return 1; } @@ -3678,10 +3678,12 @@ static int is_u_selected(Nurb *nu, int u) /* what about resolu == 2? */ bp = &nu->bp[u]; for (v = 0; v < nu->pntsv - 1; v++, bp += nu->pntsu) { - if (v) if (bp->f1 & SELECT) return 1; + if ((v != 0) && (bp->f1 & SELECT)) { + return TRUE; + } } - return 0; + return FALSE; } typedef struct NurbSort { @@ -6464,9 +6466,9 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type bp->vec[0] += fac * grid; fac = (float)b - 1.5f; bp->vec[1] += fac * grid; - if (a == 1 || a == 2) if (b == 1 || b == 2) { - bp->vec[2] += grid; - } + if ((a == 1 || a == 2) && (b == 1 || b == 2)) { + bp->vec[2] += grid; + } mul_m4_v3(mat, bp->vec); bp->vec[3] = 1.0; bp++; diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index fd87e6752f2..257dfca051f 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -1289,6 +1289,13 @@ static int insert_text_invoke(bContext *C, wmOperator *op, wmEvent *evt) insert_into_textbuf(obedit, ascii); accentcode = 0; } + else if (ascii) { + insert_into_textbuf(obedit, ascii); + accentcode = 0; + } + else { + BLI_assert(0); + } kill_selection(obedit, 1); text_update_edited(C, scene, obedit, 1, FO_EDIT); diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c index a59a3f7a5ec..aee97f40c31 100644 --- a/source/blender/editors/gpencil/editaction_gpencil.c +++ b/source/blender/editors/gpencil/editaction_gpencil.c @@ -49,6 +49,7 @@ #include "ED_anim_api.h" #include "ED_gpencil.h" #include "ED_keyframes_edit.h" +#include "ED_markers.h" #include "gpencil_intern.h" @@ -460,11 +461,12 @@ void paste_gpdata(Scene *scene) /* undo and redraw stuff */ BIF_undo_push("Paste Grease Pencil Frames"); } +#endif /* XXX disabled until Grease Pencil code stabilises again... */ /* -------------------------------------- */ /* Snap Tools */ -static short snap_gpf_nearest(bGPDframe *gpf, Scene *scene) +static short snap_gpf_nearest(bGPDframe *gpf, Scene *UNUSED(scene)) { if (gpf->flag & GP_FRAME_SELECT) gpf->framenum = (int)(floor(gpf->framenum + 0.5)); @@ -475,7 +477,7 @@ static short snap_gpf_nearestsec(bGPDframe *gpf, Scene *scene) { float secf = (float)FPS; if (gpf->flag & GP_FRAME_SELECT) - gpf->framenum = (int)(floor(gpf->framenum / secf + 0.5f) * secf); + gpf->framenum = (int)(floorf(gpf->framenum / secf + 0.5f) * secf); return 0; } @@ -489,33 +491,32 @@ static short snap_gpf_cframe(bGPDframe *gpf, Scene *scene) static short snap_gpf_nearmarker(bGPDframe *gpf, Scene *scene) { if (gpf->flag & GP_FRAME_SELECT) - gpf->framenum = (int)find_nearest_marker_time(&scene->markers, (float)gpf->framenum); + gpf->framenum = (int)ED_markers_find_nearest_marker_time(&scene->markers, (float)gpf->framenum); return 0; } - /* snap selected frames to ... */ -void snap_gplayer_frames(bGPDlayer *gpl, Scene *scene, short mode) +void ED_gplayer_snap_frames(bGPDlayer *gpl, Scene *scene, short mode) { switch (mode) { - case 1: /* snap to nearest frame */ + case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */ ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearest); break; - case 2: /* snap to current frame */ + case SNAP_KEYS_CURFRAME: /* snap to current frame */ ED_gplayer_frames_looper(gpl, scene, snap_gpf_cframe); break; - case 3: /* snap to nearest marker */ + case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */ ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearmarker); break; - case 4: /* snap to nearest second */ + case SNAP_KEYS_NEARSEC: /* snap to nearest second */ ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearestsec); break; default: /* just in case */ - ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearest); break; } } +#if 0 /* XXX disabled until grease pencil code stabilises again */ /* -------------------------------------- */ /* Mirror Tools */ diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index ed8a1ea8280..e9ca7392752 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -40,8 +40,10 @@ #include "BLI_math.h" #include "BLI_blenlib.h" +#include "BLI_rand.h" #include "BLI_utildefines.h" +#include "DNA_anim_types.h" #include "DNA_curve_types.h" #include "DNA_object_types.h" #include "DNA_node_types.h" @@ -51,14 +53,19 @@ #include "DNA_view3d_types.h" #include "DNA_gpencil_types.h" +#include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_fcurve.h" +#include "BKE_global.h" #include "BKE_gpencil.h" #include "BKE_library.h" #include "BKE_object.h" #include "BKE_report.h" #include "BKE_tracking.h" +#include "UI_interface.h" #include "WM_api.h" #include "WM_types.h" @@ -71,6 +78,7 @@ #include "ED_gpencil.h" #include "ED_view3d.h" #include "ED_clip.h" +#include "ED_keyframing.h" #include "gpencil_intern.h" @@ -131,11 +139,11 @@ bGPdata **gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr) return &sseq->gpd; } break; - + case SPACE_IMAGE: /* Image/UV Editor */ { SpaceImage *sima = (SpaceImage *)CTX_wm_space_data(C); - + /* for now, Grease Pencil data is associated with the space... */ /* XXX our convention for everything else is to link to data though... */ if (ptr) RNA_pointer_create(screen_id, &RNA_SpaceImageEditor, sima, ptr); @@ -151,19 +159,19 @@ bGPdata **gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr) if (clip) { if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking); - + if (!track) return NULL; - + if (ptr) RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, ptr); - + return &track->gpd; } else { if (ptr) RNA_id_pointer_create(&clip->id, ptr); - + return &clip->gpd; } } @@ -387,6 +395,14 @@ enum { GP_STROKECONVERT_CURVE, }; +/* Defines for possible timing modes */ +enum { + GP_STROKECONVERT_TIMING_NONE = 1, + GP_STROKECONVERT_TIMING_LINEAR = 2, + GP_STROKECONVERT_TIMING_FULL = 3, + GP_STROKECONVERT_TIMING_CUSTOMGAP = 4, +}; + /* RNA enum define */ static EnumPropertyItem prop_gpencil_convertmodes[] = { {GP_STROKECONVERT_PATH, "PATH", 0, "Path", ""}, @@ -394,6 +410,31 @@ static EnumPropertyItem prop_gpencil_convertmodes[] = { {0, NULL, 0, NULL, NULL} }; +static EnumPropertyItem prop_gpencil_convert_timingmodes_restricted[] = { + {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"}, + {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"}, + {0, NULL, 0, NULL, NULL}, +}; + +static EnumPropertyItem prop_gpencil_convert_timingmodes[] = { + {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"}, + {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"}, + {GP_STROKECONVERT_TIMING_FULL, "FULL", 0, "Original", "Use the original timing, gaps included"}, + {GP_STROKECONVERT_TIMING_CUSTOMGAP, "CUSTOMGAP", 0, "Custom Gaps", + "Use the original timing, but with custom gap lengths (in frames)"}, + {0, NULL, 0, NULL, NULL}, +}; + +static EnumPropertyItem *rna_GPConvert_mode_items(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), + int *free) +{ + *free = FALSE; + if (RNA_boolean_get(ptr, "use_timing_data")) { + return prop_gpencil_convert_timingmodes; + } + return prop_gpencil_convert_timingmodes_restricted; +} + /* --- */ /* convert the coordinates from the given stroke point into 3d-coordinates @@ -430,7 +471,7 @@ static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoin mvalf[1] = (float)pt->y / 100.0f * ar->winy; } } - + /* convert screen coordinate to 3d coordinates * - method taken from editview.c - mouse_cursor() */ @@ -440,47 +481,510 @@ static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoin /* --- */ +/* temp struct for gp_stroke_path_animation() */ +typedef struct tGpTimingData { + /* Data set from operator settings */ + int mode; + int frame_range; /* Number of frames evaluated for path animation */ + int start_frame, end_frame; + int realtime; /* A bool, actually, will overwrite end_frame in case of Original or CustomGap timing... */ + float gap_duration, gap_randomness; /* To be used with CustomGap mode*/ + int seed; + + /* Data set from points, used to compute final timing FCurve */ + int num_points, cur_point; + + /* Distances */ + float *dists; + float tot_dist; + + /* Times */ + float *times; /* Note: Gap times will be negative! */ + float tot_time, gap_tot_time; + double inittime; +} tGpTimingData; + +/* init point buffers for timing data */ +static void _gp_timing_data_set_nbr(tGpTimingData *gtd, int nbr) +{ + float *tmp; + + BLI_assert(nbr > gtd->num_points); + + /* distances */ + tmp = gtd->dists; + gtd->dists = MEM_callocN(sizeof(float) * nbr, __func__); + if (tmp) { + memcpy(gtd->dists, tmp, sizeof(float) * gtd->num_points); + MEM_freeN(tmp); + } + + /* times */ + tmp = gtd->times; + gtd->times = MEM_callocN(sizeof(float) * nbr, __func__); + if (tmp) { + memcpy(gtd->times, tmp, sizeof(float) * gtd->num_points); + MEM_freeN(tmp); + } + + gtd->num_points = nbr; +} + +/* add stroke point to timing buffers */ +static void gp_timing_data_add_point(tGpTimingData *gtd, double stroke_inittime, float time, float delta_dist) +{ + if (time < 0.0f) { + /* This is a gap, negative value! */ + gtd->times[gtd->cur_point] = -(((float)(stroke_inittime - gtd->inittime)) + time); + gtd->tot_time = -gtd->times[gtd->cur_point]; + + gtd->gap_tot_time += gtd->times[gtd->cur_point] - gtd->times[gtd->cur_point - 1]; + } + else { + gtd->times[gtd->cur_point] = (((float)(stroke_inittime - gtd->inittime)) + time); + gtd->tot_time = (gtd->times[gtd->cur_point]); + } + + gtd->tot_dist += delta_dist; + gtd->dists[gtd->cur_point] = gtd->tot_dist; + + gtd->cur_point++; +} + +/* In frames! Binary search for FCurve keys have a threshold of 0.01, so we can't set + * arbitrarily close points - this is esp. important with NoGaps mode! + */ +#define MIN_TIME_DELTA 0.02f + +/* Loop over next points to find the end of the stroke, and compute */ +static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, int idx, int nbr_gaps, int *nbr_done_gaps, + float tot_gaps_time, float delta_time, float *next_delta_time) +{ + int j; + + for (j = idx + 1; j < gtd->num_points; j++) { + if (gtd->times[j] < 0) { + gtd->times[j] = -gtd->times[j]; + if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { + /* In this mode, gap time between this stroke and the next should be 0 currently... + * So we have to compute its final duration! + */ + if (gtd->gap_randomness > 0.0f) { + /* We want gaps that are in gtd->gap_duration +/- gtd->gap_randomness range, + * and which sum to exactly tot_gaps_time... + */ + int rem_gaps = nbr_gaps - (*nbr_done_gaps); + if (rem_gaps < 2) { + /* Last gap, just give remaining time! */ + *next_delta_time = tot_gaps_time; + } + else { + float delta, min, max; + + /* This code ensures that if the first gaps have been shorter than average gap_duration, + * next gaps will tend to be longer (i.e. try to recover the lateness), and vice-versa! + */ + delta = delta_time - (gtd->gap_duration * (*nbr_done_gaps)); + + /* Clamp min between [-gap_randomness, 0.0], with lower delta giving higher min */ + min = -gtd->gap_randomness - delta; + CLAMP(min, -gtd->gap_randomness, 0.0f); + + /* Clamp max between [0.0, gap_randomness], with lower delta giving higher max */ + max = gtd->gap_randomness - delta; + CLAMP(max, 0.0f, gtd->gap_randomness); + *next_delta_time += gtd->gap_duration + (BLI_frand() * (max - min)) + min; + } + } + else { + *next_delta_time += gtd->gap_duration; + } + } + (*nbr_done_gaps)++; + break; + } + } + + return j - 1; +} + +static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, int *nbr_gaps, float *tot_gaps_time) +{ + int i; + float delta_time = 0.0f; + + for (i = 0; i < gtd->num_points; i++) { + if (gtd->times[i] < 0 && i) { + (*nbr_gaps)++; + gtd->times[i] = -gtd->times[i] - delta_time; + delta_time += gtd->times[i] - gtd->times[i - 1]; + gtd->times[i] = -gtd->times[i - 1]; /* Temp marker, values *have* to be different! */ + } + else { + gtd->times[i] -= delta_time; + } + } + gtd->tot_time -= delta_time; + + *tot_gaps_time = (float)(*nbr_gaps) * gtd->gap_duration; + gtd->tot_time += *tot_gaps_time; + if (G.debug & G_DEBUG) { + printf("%f, %f, %f, %d\n", gtd->tot_time, delta_time, *tot_gaps_time, *nbr_gaps); + } + if (gtd->gap_randomness > 0.0f) { + BLI_srandom(gtd->seed); + } +} + +static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, + Curve *cu, tGpTimingData *gtd, float time_range, + int nbr_gaps, float tot_gaps_time) +{ + /* Use actual recorded timing! */ + float time_start = (float)gtd->start_frame; + + float last_valid_time = 0.0f; + int end_stroke_idx = -1, start_stroke_idx = 0; + float end_stroke_time = 0.0f; + + /* CustomGaps specific */ + float delta_time = 0.0f, next_delta_time = 0.0f; + int nbr_done_gaps = 0; + + int i; + float cfra; + + /* This is a bit tricky, as: + * - We can't add arbitrarily close points on FCurve (in time). + * - We *must* have all "caps" points of all strokes in FCurve, as much as possible! + */ + for (i = 0; i < gtd->num_points; i++) { + /* If new stroke... */ + if (i > end_stroke_idx) { + start_stroke_idx = i; + delta_time = next_delta_time; + /* find end of that new stroke */ + end_stroke_idx = gp_find_end_of_stroke_idx(gtd, i, nbr_gaps, &nbr_done_gaps, + tot_gaps_time, delta_time, &next_delta_time); + /* This one should *never* be negative! */ + end_stroke_time = time_start + ((gtd->times[end_stroke_idx] + delta_time) / gtd->tot_time * time_range); + } + + /* Simple proportional stuff... */ + cu->ctime = gtd->dists[i] / gtd->tot_dist * cu->pathlen; + cfra = time_start + ((gtd->times[i] + delta_time) / gtd->tot_time * time_range); + + /* And now, the checks about timing... */ + if (i == start_stroke_idx) { + /* If first point of a stroke, be sure it's enough ahead of last valid keyframe, and + * that the end point of the stroke is far enough! + * In case it is not, we keep the end point... + * Note that with CustomGaps mode, this is here we set the actual gap timing! + */ + if ((end_stroke_time - last_valid_time) > MIN_TIME_DELTA * 2) { + if ((cfra - last_valid_time) < MIN_TIME_DELTA) { + cfra = last_valid_time + MIN_TIME_DELTA; + } + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + last_valid_time = cfra; + } + else if (G.debug & G_DEBUG) { + printf("\t Skipping start point %d, too close from end point %d\n", i, end_stroke_idx); + } + } + else if (i == end_stroke_idx) { + /* Always try to insert end point of a curve (should be safe enough, anyway...) */ + if ((cfra - last_valid_time) < MIN_TIME_DELTA) { + cfra = last_valid_time + MIN_TIME_DELTA; + } + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + last_valid_time = cfra; + } + else { + /* Else ("middle" point), we only insert it if it's far enough from last keyframe, + * and also far enough from (not yet added!) end_stroke keyframe! + */ + if ((cfra - last_valid_time) > MIN_TIME_DELTA && (end_stroke_time - cfra) > MIN_TIME_DELTA) { + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + last_valid_time = cfra; + } + else if (G.debug & G_DEBUG) { + printf("\t Skipping \"middle\" point %d, too close from last added point or end point %d\n", + i, end_stroke_idx); + } + } + } +} + +static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu, tGpTimingData *gtd) +{ + Scene *scene = CTX_data_scene(C); + bAction *act; + FCurve *fcu; + PointerRNA ptr; + PropertyRNA *prop = NULL; + int nbr_gaps = 0, i; + + if (gtd->mode == GP_STROKECONVERT_TIMING_NONE) + return; + + /* gap_duration and gap_randomness are in frames, but we need seconds!!! */ + gtd->gap_duration = FRA2TIME(gtd->gap_duration); + gtd->gap_randomness = FRA2TIME(gtd->gap_randomness); + + /* Enable path! */ + cu->flag |= CU_PATH; + cu->pathlen = gtd->frame_range; + + /* Get RNA pointer to read/write path time values */ + RNA_id_pointer_create((ID *)cu, &ptr); + prop = RNA_struct_find_property(&ptr, "eval_time"); + + /* Ensure we have an F-Curve to add keyframes to */ + act = verify_adt_action((ID *)cu, TRUE); + fcu = verify_fcurve(act, NULL, &ptr, "eval_time", 0, TRUE); + + if (G.debug & G_DEBUG) { + printf("%s: tot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time); + for (i = 0; i < gtd->num_points; i++) { + printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]); + } + } + + if (gtd->mode == GP_STROKECONVERT_TIMING_LINEAR) { + float cfra; + + /* Linear extrapolation! */ + fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; + + cu->ctime = 0.0f; + cfra = (float)gtd->start_frame; + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + + cu->ctime = cu->pathlen; + if (gtd->realtime) { + cfra += (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */ + } + else { + cfra = (float)gtd->end_frame; + } + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + } + else { + /* Use actual recorded timing! */ + float time_range; + + /* CustomGaps specific */ + float tot_gaps_time = 0.0f; + + /* Pre-process gaps, in case we don't want to keep their original timing */ + if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { + gp_stroke_path_animation_preprocess_gaps(gtd, &nbr_gaps, &tot_gaps_time); + } + + if (gtd->realtime) { + time_range = (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */ + } + else { + time_range = (float)(gtd->end_frame - gtd->start_frame); + } + + if (G.debug & G_DEBUG) { + printf("GP Stroke Path Conversion: Starting keying!\n"); + } + + gp_stroke_path_animation_add_keyframes(reports, ptr, prop, fcu, cu, gtd, time_range, + nbr_gaps, tot_gaps_time); + } + + /* As we used INSERTKEY_FAST mode, we need to recompute all curve's handles now */ + calchandles_fcurve(fcu); + + if (G.debug & G_DEBUG) { + printf("%s: \ntot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time); + for (i = 0; i < gtd->num_points; i++) { + printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]); + } + printf("\n\n"); + } + + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + + /* send updates */ + DAG_id_tag_update(&cu->id, 0); +} + +#undef MIN_TIME_DELTA + +#define GAP_DFAC 0.05f +#define WIDTH_CORR_FAC 0.1f +#define BEZT_HANDLE_FAC 0.3f + /* convert stroke to 3d path */ -static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect) +static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu, + float minmax_weights[2], float rad_fac, int stitch, tGpTimingData *gtd) { bGPDspoint *pt; - Nurb *nu; - BPoint *bp; - int i; + Nurb *nu = (curnu) ? *curnu : NULL; + BPoint *bp, *prev_bp = NULL; + const int do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE); + int i, old_nbp = 0; - /* create new 'nurb' within the curve */ - nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)"); - - nu->pntsu = gps->totpoints; - nu->pntsv = 1; - nu->orderu = gps->totpoints; - nu->flagu = CU_NURB_ENDPOINT; - nu->resolu = 32; - - nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * gps->totpoints, "bpoints"); + /* create new 'nurb' or extend current one within the curve */ + if (nu) { + old_nbp = nu->pntsu; + + /* If stitch, the first point of this stroke is already present in current nu. + * Else, we have to add to additional points to make the zero-radius link between strokes. + */ + BKE_nurb_points_add(nu, gps->totpoints + (stitch ? -1 : 2)); + } + else { + nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)"); + + nu->pntsu = gps->totpoints; + nu->pntsv = 1; + nu->orderu = 2; /* point-to-point! */ + nu->type = CU_NURBS; + nu->flagu = CU_NURB_ENDPOINT; + nu->resolu = cu->resolu; + nu->resolv = cu->resolv; + nu->knotsu = NULL; + + nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * nu->pntsu, "bpoints"); + + stitch = FALSE; /* Security! */ + } + + if (do_gtd) { + _gp_timing_data_set_nbr(gtd, nu->pntsu); + } + + /* If needed, make the link between both strokes with two zero-radius additional points */ + /* About "zero-radius" point interpolations: + * - If we have at least two points in current curve (most common case), we linearly extrapolate + * the last segment to get the first point (p1) position and timing. + * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point + * with the first point of the current stroke. + * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated + * if it exists, else (if the stroke is a single point), linear interpolation with last curve point... + */ + if (curnu && !stitch && old_nbp) { + float p1[3], p2[3], p[3], next_p[3]; + float delta_time; + + prev_bp = NULL; + if ((old_nbp > 1) && gps->prev && (gps->prev->totpoints > 1)) { + /* Only use last curve segment if previous stroke was not a single-point one! */ + prev_bp = nu->bp + old_nbp - 2; + } + bp = nu->bp + old_nbp - 1; + + /* XXX We do this twice... Not sure it's worth to bother about this! */ + gp_strokepoint_convertcoords(C, gps, gps->points, p, subrect); + if (prev_bp) { + interp_v3_v3v3(p1, prev_bp->vec, bp->vec, 1.0f + GAP_DFAC); + } + else { + interp_v3_v3v3(p1, bp->vec, p, GAP_DFAC); + } + + if (gps->totpoints > 1) { + /* XXX We do this twice... Not sure it's worth to bother about this! */ + gp_strokepoint_convertcoords(C, gps, gps->points + 1, next_p, subrect); + interp_v3_v3v3(p2, p, next_p, -GAP_DFAC); + } + else { + interp_v3_v3v3(p2, p, bp->vec, GAP_DFAC); + } + + /* First point */ + bp++; + copy_v3_v3(bp->vec, p1); + bp->vec[3] = 1.0f; + bp->f1 = SELECT; + minmax_weights[0] = bp->radius = bp->weight = 0.0f; + if (do_gtd) { + if (prev_bp) { + delta_time = gtd->tot_time + (gtd->tot_time - gtd->times[gtd->cur_point - 1]) * GAP_DFAC; + } + else { + delta_time = gtd->tot_time + (((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC; + } + gp_timing_data_add_point(gtd, gtd->inittime, delta_time, len_v3v3((bp - 1)->vec, p1)); + } + + /* Second point */ + bp++; + copy_v3_v3(bp->vec, p2); + bp->vec[3] = 1.0f; + bp->f1 = SELECT; + minmax_weights[0] = bp->radius = bp->weight = 0.0f; + if (do_gtd) { + /* This negative delta_time marks the gap! */ + if (gps->totpoints > 1) { + delta_time = ((gps->points + 1)->time - gps->points->time) * -GAP_DFAC; + } + else { + delta_time = -(((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC; + } + gp_timing_data_add_point(gtd, gps->inittime, delta_time, len_v3v3(p1, p2)); + } + + old_nbp += 2; + } + if (old_nbp && do_gtd) { + prev_bp = nu->bp + old_nbp - 1; + } /* add points */ - for (i = 0, pt = gps->points, bp = nu->bp; i < gps->totpoints; i++, pt++, bp++) { + for (i = (stitch) ? 1 : 0, pt = gps->points + ((stitch) ? 1 : 0), bp = nu->bp + old_nbp; + i < gps->totpoints; + i++, pt++, bp++) + { float p3d[3]; + float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC; /* get coordinates to add at */ gp_strokepoint_convertcoords(C, gps, pt, p3d, subrect); copy_v3_v3(bp->vec, p3d); + bp->vec[3] = 1.0f; /* set settings */ bp->f1 = SELECT; - bp->radius = bp->weight = pt->pressure * gpl->thickness; + bp->radius = width * rad_fac; + bp->weight = width; + CLAMP(bp->weight, 0.0f, 1.0f); + if (bp->weight < minmax_weights[0]) { + minmax_weights[0] = bp->weight; + } + else if (bp->weight > minmax_weights[1]) { + minmax_weights[1] = bp->weight; + } + + /* Update timing data */ + if (do_gtd) { + gp_timing_data_add_point(gtd, gps->inittime, pt->time, (prev_bp) ? len_v3v3(prev_bp->vec, p3d) : 0.0f); + } + prev_bp = bp; } /* add nurb to curve */ - BLI_addtail(&cu->nurb, nu); + if (!curnu || !*curnu) { + BLI_addtail(&cu->nurb, nu); + } + if (curnu) { + *curnu = nu; + } + + BKE_nurb_knot_calc_u(nu); } static int gp_camera_view_subrect(bContext *C, rctf *subrect) { View3D *v3d = CTX_wm_view3d(C); ARegion *ar = CTX_wm_region(C); - + if (v3d) { RegionView3D *rv3d = ar->regiondata; @@ -491,48 +995,178 @@ static int gp_camera_view_subrect(bContext *C, rctf *subrect) return 1; } } - + return 0; } /* convert stroke to 3d bezier */ -static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect) +static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu, + float minmax_weights[2], float rad_fac, int stitch, tGpTimingData *gtd) { bGPDspoint *pt; - Nurb *nu; - BezTriple *bezt; - int i, tot; + Nurb *nu = (curnu) ? *curnu : NULL; + BezTriple *bezt, *prev_bezt = NULL; + int i, tot, old_nbezt = 0; float p3d_cur[3], p3d_prev[3], p3d_next[3]; + const int do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE); + + /* create new 'nurb' or extend current one within the curve */ + if (nu) { + old_nbezt = nu->pntsu; + /* If we do stitch, first point of current stroke is assumed the same as last point of previous stroke, + * so no need to add it. + * If no stitch, we want to add two additional points to make a "zero-radius" link between both strokes. + */ + BKE_nurb_bezierPoints_add(nu, gps->totpoints + ((stitch) ? -1 : 2)); + } + else { + nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)"); + + nu->pntsu = gps->totpoints; + nu->resolu = 12; + nu->resolv = 12; + nu->type = CU_BEZIER; + nu->bezt = (BezTriple *)MEM_callocN(gps->totpoints * sizeof(BezTriple), "bezts"); + + stitch = FALSE; /* Security! */ + } - /* create new 'nurb' within the curve */ - nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)"); - - nu->pntsu = gps->totpoints; - nu->resolu = 12; - nu->resolv = 12; - nu->type = CU_BEZIER; - nu->bezt = (BezTriple *)MEM_callocN(gps->totpoints * sizeof(BezTriple), "bezts"); + if (do_gtd) { + _gp_timing_data_set_nbr(gtd, nu->pntsu); + } tot = gps->totpoints; /* get initial coordinates */ pt = gps->points; if (tot) { - gp_strokepoint_convertcoords(C, gps, pt, p3d_cur, subrect); + gp_strokepoint_convertcoords(C, gps, pt, (stitch) ? p3d_prev : p3d_cur, subrect); if (tot > 1) { - gp_strokepoint_convertcoords(C, gps, pt + 1, p3d_next, subrect); + gp_strokepoint_convertcoords(C, gps, pt + 1, (stitch) ? p3d_cur : p3d_next, subrect); + } + if (stitch && tot > 2) { + gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect); } } + /* If needed, make the link between both strokes with two zero-radius additional points */ + if (curnu && old_nbezt) { + /* Update last point's second handle */ + if (stitch) { + float h2[3]; + bezt = nu->bezt + old_nbezt - 1; + interp_v3_v3v3(h2, bezt->vec[1], p3d_cur, BEZT_HANDLE_FAC); + copy_v3_v3(bezt->vec[2], h2); + pt++; + } + + /* Create "link points" */ + /* About "zero-radius" point interpolations: + * - If we have at least two points in current curve (most common case), we linearly extrapolate + * the last segment to get the first point (p1) position and timing. + * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point + * with the first point of the current stroke. + * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated + * if it exists, else (if the stroke is a single point), linear interpolation with last curve point... + */ + else { + float h1[3], h2[3], p1[3], p2[3]; + float delta_time; + + prev_bezt = NULL; + if (old_nbezt > 1 && gps->prev && gps->prev->totpoints > 1) { + /* Only use last curve segment if previous stroke was not a single-point one! */ + prev_bezt = nu->bezt + old_nbezt - 2; + } + bezt = nu->bezt + old_nbezt - 1; + if (prev_bezt) { + interp_v3_v3v3(p1, prev_bezt->vec[1], bezt->vec[1], 1.0f + GAP_DFAC); + } + else { + interp_v3_v3v3(p1, bezt->vec[1], p3d_cur, GAP_DFAC); + } + if (tot > 1) { + interp_v3_v3v3(p2, p3d_cur, p3d_next, -GAP_DFAC); + } + else { + interp_v3_v3v3(p2, p3d_cur, bezt->vec[1], GAP_DFAC); + } + + /* Second handle of last point */ + interp_v3_v3v3(h2, bezt->vec[1], p1, BEZT_HANDLE_FAC); + copy_v3_v3(bezt->vec[2], h2); + + /* First point */ + interp_v3_v3v3(h1, p1, bezt->vec[1], BEZT_HANDLE_FAC); + interp_v3_v3v3(h2, p1, p2, BEZT_HANDLE_FAC); + + bezt++; + copy_v3_v3(bezt->vec[0], h1); + copy_v3_v3(bezt->vec[1], p1); + copy_v3_v3(bezt->vec[2], h2); + bezt->h1 = bezt->h2 = HD_FREE; + bezt->f1 = bezt->f2 = bezt->f3 = SELECT; + minmax_weights[0] = bezt->radius = bezt->weight = 0.0f; + + if (do_gtd) { + if (prev_bezt) { + delta_time = gtd->tot_time + (gtd->tot_time - gtd->times[gtd->cur_point - 1]) * GAP_DFAC; + } + else { + delta_time = gtd->tot_time + (((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC; + } + gp_timing_data_add_point(gtd, gtd->inittime, delta_time, len_v3v3((bezt - 1)->vec[1], p1)); + } + + /* Second point */ + interp_v3_v3v3(h1, p2, p1, BEZT_HANDLE_FAC); + interp_v3_v3v3(h2, p2, p3d_cur, BEZT_HANDLE_FAC); + + bezt++; + copy_v3_v3(bezt->vec[0], h1); + copy_v3_v3(bezt->vec[1], p2); + copy_v3_v3(bezt->vec[2], h2); + bezt->h1 = bezt->h2 = HD_FREE; + bezt->f1 = bezt->f2 = bezt->f3 = SELECT; + minmax_weights[0] = bezt->radius = bezt->weight = 0.0f; + + if (do_gtd) { + /* This negative delta_time marks the gap! */ + if (tot > 1) { + delta_time = ((gps->points + 1)->time - gps->points->time) * -GAP_DFAC; + } + else { + delta_time = -(((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC; + } + gp_timing_data_add_point(gtd, gps->inittime, delta_time, len_v3v3(p1, p2)); + } + + old_nbezt += 2; + copy_v3_v3(p3d_prev, p2); + } + } + if (old_nbezt && do_gtd) { + prev_bezt = nu->bezt + old_nbezt - 1; + } + /* add points */ - for (i = 0, bezt = nu->bezt; i < tot; i++, pt++, bezt++) { + for (i = stitch ? 1 : 0, bezt = nu->bezt + old_nbezt; i < tot; i++, pt++, bezt++) { float h1[3], h2[3]; + float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC; - if (i) interp_v3_v3v3(h1, p3d_cur, p3d_prev, 0.3); - else interp_v3_v3v3(h1, p3d_cur, p3d_next, -0.3); + if (i || old_nbezt) { + interp_v3_v3v3(h1, p3d_cur, p3d_prev, BEZT_HANDLE_FAC); + } + else { + interp_v3_v3v3(h1, p3d_cur, p3d_next, -BEZT_HANDLE_FAC); + } - if (i < tot - 1) interp_v3_v3v3(h2, p3d_cur, p3d_next, 0.3); - else interp_v3_v3v3(h2, p3d_cur, p3d_prev, -0.3); + if (i < tot - 1) { + interp_v3_v3v3(h2, p3d_cur, p3d_next, BEZT_HANDLE_FAC); + } + else { + interp_v3_v3v3(h2, p3d_cur, p3d_prev, -BEZT_HANDLE_FAC); + } copy_v3_v3(bezt->vec[0], h1); copy_v3_v3(bezt->vec[1], p3d_cur); @@ -541,7 +1175,20 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu /* set settings */ bezt->h1 = bezt->h2 = HD_FREE; bezt->f1 = bezt->f2 = bezt->f3 = SELECT; - bezt->radius = bezt->weight = pt->pressure * gpl->thickness * 0.1f; + bezt->radius = width * rad_fac; + bezt->weight = width; + CLAMP(bezt->weight, 0.0f, 1.0f); + if (bezt->weight < minmax_weights[0]) { + minmax_weights[0] = bezt->weight; + } + else if (bezt->weight > minmax_weights[1]) { + minmax_weights[1] = bezt->weight; + } + + /* Update timing data */ + if (do_gtd) { + gp_timing_data_add_point(gtd, gps->inittime, pt->time, prev_bezt ? len_v3v3(prev_bezt->vec[1], p3d_cur) : 0.0f); + } /* shift coord vects */ copy_v3_v3(p3d_prev, p3d_cur); @@ -550,31 +1197,103 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu if (i + 2 < tot) { gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect); } + + prev_bezt = bezt; } - + /* must calculate handles or else we crash */ BKE_nurb_handles_calc(nu); - /* add nurb to curve */ - BLI_addtail(&cu->nurb, nu); + if (!curnu || !*curnu) { + BLI_addtail(&cu->nurb, nu); + } + if (curnu) { + *curnu = nu; + } +} + +#undef GAP_DFAC +#undef WIDTH_CORR_FAC +#undef BEZT_HANDLE_FAC + +static void gp_stroke_finalize_curve_endpoints(Curve *cu) +{ + /* start */ + Nurb *nu = cu->nurb.first; + int i = 0; + if (nu->bezt) { + BezTriple *bezt = nu->bezt; + if (bezt) { + bezt[i].weight = bezt[i].radius = 0.0f; + } + } + else if (nu->bp) { + BPoint *bp = nu->bp; + if (bp) { + bp[i].weight = bp[i].radius = 0.0f; + } + } + + /* end */ + nu = cu->nurb.last; + i = nu->pntsu - 1; + if (nu->bezt) { + BezTriple *bezt = nu->bezt; + if (bezt) { + bezt[i].weight = bezt[i].radius = 0.0f; + } + } + else if (nu->bp) { + BPoint *bp = nu->bp; + if (bp) { + bp[i].weight = bp[i].radius = 0.0f; + } + } +} + +static void gp_stroke_norm_curve_weights(Curve *cu, float minmax_weights[2]) +{ + Nurb *nu; + const float delta = minmax_weights[0]; + const float fac = 1.0f / (minmax_weights[1] - delta); + int i; + + for (nu = cu->nurb.first; nu; nu = nu->next) { + if (nu->bezt) { + BezTriple *bezt = nu->bezt; + for (i = 0; i < nu->pntsu; i++, bezt++) { + bezt->weight = (bezt->weight - delta) * fac; + } + } + else if (nu->bp) { + BPoint *bp = nu->bp; + for (i = 0; i < nu->pntsu; i++, bp++) { + bp->weight = (bp->weight - delta) * fac; + } + } + } } /* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */ -static void gp_layer_to_curve(bContext *C, bGPdata *gpd, bGPDlayer *gpl, short mode) +static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bGPDlayer *gpl, int mode, + int norm_weights, float rad_fac, int link_strokes, tGpTimingData *gtd) { Scene *scene = CTX_data_scene(C); bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0); - bGPDstroke *gps; + bGPDstroke *gps, *prev_gps = NULL; Object *ob; Curve *cu; + Nurb *nu = NULL; + Base *base = BASACT, *newbase = NULL; + float minmax_weights[2] = {1.0f, 0.0f}; /* camera framing */ rctf subrect, *subrect_ptr = NULL; - + /* error checking */ if (ELEM3(NULL, gpd, gpl, gpf)) return; - + /* only convert if there are any strokes on this layer's frame to convert */ if (gpf->strokes.first == NULL) return; @@ -583,7 +1302,7 @@ static void gp_layer_to_curve(bContext *C, bGPdata *gpd, bGPDlayer *gpl, short m if (gp_camera_view_subrect(C, &subrect)) { subrect_ptr = &subrect; } - + /* init the curve object (remove rotation and get curve data from it) * - must clear transforms set on object, as those skew our results */ @@ -597,24 +1316,125 @@ static void gp_layer_to_curve(bContext *C, bGPdata *gpd, bGPDlayer *gpl, short m rename_id((ID *)ob, gpl->info); rename_id((ID *)cu, gpl->info); + gtd->inittime = ((bGPDstroke *)gpf->strokes.first)->inittime; + /* add points to curve */ for (gps = gpf->strokes.first; gps; gps = gps->next) { + /* Detect new strokes created because of GP_STROKE_BUFFER_MAX reached, + * and stitch them to previous one. + */ + int stitch = FALSE; + + if (prev_gps) { + bGPDspoint *pt1 = prev_gps->points + prev_gps->totpoints - 1; + bGPDspoint *pt2 = gps->points; + + if ((pt1->x == pt2->x) && (pt1->y == pt2->y)) { + stitch = TRUE; + } + } + + /* Decide whether we connect this stroke to previous one */ + if (!(stitch || link_strokes)) { + nu = NULL; + } + switch (mode) { case GP_STROKECONVERT_PATH: - gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr); + gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, gtd); break; case GP_STROKECONVERT_CURVE: - gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr); + gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, gtd); break; default: BLI_assert(!"invalid mode"); break; } + prev_gps = gps; + } + + /* If link_strokes, be sure first and last points have a zero weight/size! */ + if (link_strokes) + gp_stroke_finalize_curve_endpoints(cu); + + /* Update curve's weights, if needed */ + if (norm_weights && ((minmax_weights[0] > 0.0f) || (minmax_weights[1] < 1.0f))) + gp_stroke_norm_curve_weights(cu, minmax_weights); + + /* Create the path animation, if needed */ + gp_stroke_path_animation(C, reports, cu, gtd); + + /* Reset original object as active, else we can't edit operator's settings!!! */ + /* set layers OK */ + newbase = BASACT; + if (base) { + newbase->lay = base->lay; + ob->lay = newbase->lay; + } + + /* restore, BKE_object_add sets active */ + BASACT = base; + if (base) { + base->flag |= SELECT; } } /* --- */ +/* Check a GP layer has valid timing data! Else, most timing options are hidden in the operator. + * op may be NULL. + */ +static int gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0); + bGPDstroke *gps = gpf->strokes.first; + bGPDspoint *pt; + double base_time, cur_time, prev_time = -1.0; + int i, valid = TRUE; + + do { + base_time = cur_time = gps->inittime; + if (cur_time <= prev_time) { + valid = FALSE; + break; + } + + prev_time = cur_time; + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + cur_time = base_time + (double)pt->time; + /* First point of a stroke should have the same time as stroke's inittime, + * so it's the only case where equality is allowed! + */ + if ((i && cur_time <= prev_time) || (cur_time < prev_time)) { + valid = FALSE; + break; + } + prev_time = cur_time; + } + + if (!valid) { + break; + } + } while ((gps = gps->next)); + + if (op) { + RNA_boolean_set(op->ptr, "use_timing_data", valid); + } + return valid; +} + +/* Check end_frame is always > start frame! */ +static void gp_convert_set_end_frame(struct Main *UNUSED(main), struct Scene *UNUSED(scene), struct PointerRNA *ptr) +{ + int start_frame = RNA_int_get(ptr, "start_frame"); + int end_frame = RNA_int_get(ptr, "end_frame"); + + if (end_frame <= start_frame) { + RNA_int_set(ptr, "end_frame", start_frame + 1); + } +} + static int gp_convert_poll(bContext *C) { bGPdata *gpd = gpencil_data_get_active(C); @@ -627,45 +1447,204 @@ static int gp_convert_poll(bContext *C) static int gp_convert_layer_exec(bContext *C, wmOperator *op) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_timing_data"); bGPdata *gpd = gpencil_data_get_active(C); bGPDlayer *gpl = gpencil_layer_getactive(gpd); Scene *scene = CTX_data_scene(C); int mode = RNA_enum_get(op->ptr, "type"); - + int norm_weights = RNA_boolean_get(op->ptr, "use_normalize_weights"); + float rad_fac = RNA_float_get(op->ptr, "radius_multiplier"); + int link_strokes = RNA_boolean_get(op->ptr, "use_link_strokes"); + int valid_timing; + tGpTimingData gtd; + /* check if there's data to work with */ if (gpd == NULL) { - BKE_report(op->reports, RPT_ERROR, "No grease pencil data to work on"); + BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data to work on"); return OPERATOR_CANCELLED; } - - gp_layer_to_curve(C, gpd, gpl, mode); - + + if (!RNA_property_is_set(op->ptr, prop) && !gp_convert_check_has_valid_timing(C, gpl, op)) { + BKE_report(op->reports, RPT_WARNING, + "Current Grease Pencil strokes have no valid timing data, most timing options will be hidden!"); + } + valid_timing = RNA_property_boolean_get(op->ptr, prop); + + gtd.mode = RNA_enum_get(op->ptr, "timing_mode"); + /* Check for illegal timing mode! */ + if (!valid_timing && !ELEM(gtd.mode, GP_STROKECONVERT_TIMING_NONE, GP_STROKECONVERT_TIMING_LINEAR)) { + gtd.mode = GP_STROKECONVERT_TIMING_LINEAR; + RNA_enum_set(op->ptr, "timing_mode", gtd.mode); + } + if (!link_strokes) { + gtd.mode = GP_STROKECONVERT_TIMING_NONE; + } + + /* grab all relevant settings */ + gtd.frame_range = RNA_int_get(op->ptr, "frame_range"); + gtd.start_frame = RNA_int_get(op->ptr, "start_frame"); + gtd.realtime = valid_timing ? RNA_boolean_get(op->ptr, "use_realtime") : FALSE; + gtd.end_frame = RNA_int_get(op->ptr, "end_frame"); + gtd.gap_duration = RNA_float_get(op->ptr, "gap_duration"); + gtd.gap_randomness = RNA_float_get(op->ptr, "gap_randomness"); + gtd.gap_randomness = min_ff(gtd.gap_randomness, gtd.gap_duration); + gtd.seed = RNA_int_get(op->ptr, "seed"); + gtd.num_points = gtd.cur_point = 0; + gtd.dists = gtd.times = NULL; + gtd.tot_dist = gtd.tot_time = gtd.gap_tot_time = 0.0f; + gtd.inittime = 0.0; + + /* perform conversion */ + gp_layer_to_curve(C, op->reports, gpd, gpl, mode, norm_weights, rad_fac, link_strokes, >d); + + /* free temp memory */ + if (gtd.dists) { + MEM_freeN(gtd.dists); + gtd.dists = NULL; + } + if (gtd.times) { + MEM_freeN(gtd.times); + gtd.times = NULL; + } + /* notifiers */ WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); - + /* done */ return OPERATOR_FINISHED; } +static int gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop) +{ + const char *prop_id = RNA_property_identifier(prop); + int link_strokes = RNA_boolean_get(ptr, "use_link_strokes"); + int timing_mode = RNA_enum_get(ptr, "timing_mode"); + int realtime = RNA_boolean_get(ptr, "use_realtime"); + float gap_duration = RNA_float_get(ptr, "gap_duration"); + float gap_randomness = RNA_float_get(ptr, "gap_randomness"); + int valid_timing = RNA_boolean_get(ptr, "use_timing_data"); + + /* Always show those props */ + if (strcmp(prop_id, "type") == 0 || + strcmp(prop_id, "use_normalize_weights") == 0 || + strcmp(prop_id, "radius_multiplier") == 0 || + strcmp(prop_id, "use_link_strokes") == 0) + { + return TRUE; + } + + /* Never show this prop */ + if (strcmp(prop_id, "use_timing_data") == 0) + return FALSE; + + if (link_strokes) { + /* Only show when link_stroke is TRUE */ + if (strcmp(prop_id, "timing_mode") == 0) + return TRUE; + + if (timing_mode != GP_STROKECONVERT_TIMING_NONE) { + /* Only show when link_stroke is TRUE and stroke timing is enabled */ + if (strcmp(prop_id, "frame_range") == 0 || + strcmp(prop_id, "start_frame") == 0) + { + return TRUE; + } + + /* Only show if we have valid timing data! */ + if (valid_timing && strcmp(prop_id, "use_realtime") == 0) + return TRUE; + + /* Only show if realtime or valid_timing is FALSE! */ + if ((!realtime || !valid_timing) && strcmp(prop_id, "end_frame") == 0) + return TRUE; + + if (valid_timing && timing_mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { + /* Only show for custom gaps! */ + if (strcmp(prop_id, "gap_duration") == 0) + return TRUE; + + /* Only show randomness for non-null custom gaps! */ + if (strcmp(prop_id, "gap_randomness") == 0 && (gap_duration > 0.0f)) + return TRUE; + + /* Only show seed for randomize action! */ + if (strcmp(prop_id, "seed") == 0 && (gap_duration > 0.0f) && (gap_randomness > 0.0f)) + return TRUE; + } + } + } + + /* Else, hidden! */ + return FALSE; +} + +static void gp_convert_ui(bContext *C, wmOperator *op) +{ + uiLayout *layout = op->layout; + wmWindowManager *wm = CTX_wm_manager(C); + PointerRNA ptr; + + RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); + + /* Main auto-draw call */ + uiDefAutoButsRNA(layout, &ptr, gp_convert_draw_check_prop, '\0'); +} + void GPENCIL_OT_convert(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Convert Grease Pencil"; ot->idname = "GPENCIL_OT_convert"; - ot->description = "Convert the active Grease Pencil layer to a new Object"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->description = "Convert the active Grease Pencil layer to a new Curve Object"; /* callbacks */ ot->invoke = WM_menu_invoke; ot->exec = gp_convert_layer_exec; ot->poll = gp_convert_poll; + ot->ui = gp_convert_ui; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", ""); + ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", "Which type of curve to convert to"); + + RNA_def_boolean(ot->srna, "use_normalize_weights", TRUE, "Normalize Weight", + "Normalize weight (set from stroke width)"); + RNA_def_float(ot->srna, "radius_multiplier", 1.0f, 0.0f, 1000.0f, "Radius Fac", + "Multiplier for the points' radii (set from stroke width)", 0.0f, 10.0f); + RNA_def_boolean(ot->srna, "use_link_strokes", TRUE, "Link Strokes", + "Whether to link strokes with zero-radius sections of curves"); + + prop = RNA_def_enum(ot->srna, "timing_mode", prop_gpencil_convert_timingmodes, GP_STROKECONVERT_TIMING_FULL, + "Timing Mode", "How to use timing data stored in strokes"); + RNA_def_enum_funcs(prop, rna_GPConvert_mode_items); + + RNA_def_int(ot->srna, "frame_range", 100, 1, 10000, "Frame Range", + "The duration of evaluation of the path control curve", 1, 1000); + RNA_def_int(ot->srna, "start_frame", 1, 1, 100000, "Start Frame", + "The start frame of the path control curve", 1, 100000); + RNA_def_boolean(ot->srna, "use_realtime", FALSE, "Realtime", + "Whether the path control curve reproduces the drawing in realtime, starting from Start Frame"); + prop = RNA_def_int(ot->srna, "end_frame", 250, 1, 100000, "End Frame", + "The end frame of the path control curve (if Realtime is not set)", 1, 100000); + RNA_def_property_update_runtime(prop, gp_convert_set_end_frame); + + RNA_def_float(ot->srna, "gap_duration", 0.0f, 0.0f, 10000.0f, "Gap Duration", + "Custom Gap mode: (Average) length of gaps, in frames " + "(Note: Realtime value, will be scaled if Realtime is not set)", 0.0f, 1000.0f); + RNA_def_float(ot->srna, "gap_randomness", 0.0f, 0.0f, 10000.0f, "Gap Randomness", + "Custom Gap mode: Number of frames that gap lengths can vary", 0.0f, 1000.0f); + RNA_def_int(ot->srna, "seed", 0, 0, 1000, "Random Seed", + "Custom Gap mode: Random generator seed", 0, 100); + + /* Note: Internal use, this one will always be hidden by UI code... */ + prop = RNA_def_boolean(ot->srna, "use_timing_data", FALSE, "Has Valid Timing", + "Whether the converted Grease Pencil layer has valid timing data (internal use)"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* ************************************************ */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 9bfd89075af..8fdca730674 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -39,6 +39,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "PIL_time.h" + #include "BKE_gpencil.h" #include "BKE_context.h" #include "BKE_global.h" @@ -98,6 +100,14 @@ typedef struct tGPsdata { short radius; /* radius of influence for eraser */ short flags; /* flags that can get set during runtime */ + + /* These need to be doubles, as (at least under unix) they are in seconds since epoch, + * float (and its 7 digits precision) is definitively not enough here! + * double, with its 15 digits precision, ensures us millisecond precision for a few centuries at least. + */ + double inittime; /* Used when converting to path */ + double curtime; /* Used when converting to path */ + double ocurtime; /* Used when converting to path */ float imat[4][4]; /* inverted transformation matrix applying when converting coords from screen-space * to region space */ @@ -201,7 +211,7 @@ static void gp_get_3d_reference(tGPsdata *p, float vec[3]) float *fp = give_cursor(p->scene, v3d); /* the reference point used depends on the owner... */ -#if 0 // XXX: disabled for now, since we can't draw relative to the owner yet +#if 0 /* XXX: disabled for now, since we can't draw relative to the owner yet */ if (p->ownerPtr.type == &RNA_Object) { Object *ob = (Object *)p->ownerPtr.data; @@ -249,7 +259,7 @@ static short gp_stroke_filtermval(tGPsdata *p, const int mval[2], int pmval[2]) } /* convert screen-coordinates to buffer-coordinates */ -// XXX this method needs a total overhaul! +/* XXX this method needs a total overhaul! */ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3], float *depth) { bGPdata *gpd = p->gpd; @@ -310,7 +320,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3] } /* add current stroke-point to buffer (returns whether point was successfully added) */ -static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) +static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, double curtime) { bGPdata *gpd = p->gpd; tGPspoint *pt; @@ -325,6 +335,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = pressure; + pt->time = (float)(curtime - p->inittime); /* increment buffer size */ gpd->sbuffer_size++; @@ -338,6 +349,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = pressure; + pt->time = (float)(curtime - p->inittime); /* if this is just the second point we've added, increment the buffer size * so that it will be drawn properly... @@ -361,6 +373,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = pressure; + pt->time = (float)(curtime - p->inittime); /* increment counters */ gpd->sbuffer_size++; @@ -378,10 +391,11 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = pressure; + pt->time = (float)(curtime - p->inittime); /* if there's stroke for this poly line session add (or replace last) point * to stroke. This allows to draw lines more interactively (see new segment - * during mouse slide, i.e.) + * during mouse slide, e.g.) */ if (gp_stroke_added_check(p)) { bGPDstroke *gps = p->gpf->strokes.last; @@ -410,8 +424,9 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &pt->x, &pts->x, NULL); - /* copy pressure */ + /* copy pressure and time */ pts->pressure = pt->pressure; + pts->time = pt->time; } /* increment counters */ @@ -425,18 +440,11 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) return GP_STROKEADD_INVALID; } - -/* temp struct for gp_stroke_smooth() */ -typedef struct tGpSmoothCo { - int x; - int y; -} tGpSmoothCo; - /* smooth a stroke (in buffer) before storing it */ static void gp_stroke_smooth(tGPsdata *p) { bGPdata *gpd = p->gpd; - tGpSmoothCo *smoothArray, *spc; + tGPspoint *spt, tmp_spt[3]; int i = 0, cmx = gpd->sbuffer_size; /* only smooth if smoothing is enabled, and we're not doing a straight line */ @@ -447,30 +455,28 @@ static void gp_stroke_smooth(tGPsdata *p) if ((cmx <= 2) || (gpd->sbuffer == NULL)) return; - /* create a temporary smoothing coordinates buffer, use to store calculated values to prevent sequential error */ - smoothArray = MEM_callocN(sizeof(tGpSmoothCo) * cmx, "gp_stroke_smooth smoothArray"); + /* Calculate smoothing coordinates using weighted-averages + * WARNING: we do NOT smooth first and last points (to avoid shrinkage) + */ + spt = (tGPspoint *)gpd->sbuffer; - /* first pass: calculate smoothing coordinates using weighted-averages */ - for (i = 0, spc = smoothArray; i < gpd->sbuffer_size; i++, spc++) { - const tGPspoint *pc = (((tGPspoint *)gpd->sbuffer) + i); - const tGPspoint *pb = (i - 1 > 0) ? (pc - 1) : (pc); - const tGPspoint *pa = (i - 2 > 0) ? (pc - 2) : (pb); - const tGPspoint *pd = (i + 1 < cmx) ? (pc + 1) : (pc); + /* This (tmp_spt) small array stores the last two points' original coordinates, + * as we don't want to use already averaged ones! It is used as a cyclic buffer... + */ + tmp_spt[0] = *spt; + for (i = 1, spt++; i < cmx - 1; i++, spt++) { + const tGPspoint *pc = spt; + const tGPspoint *pb = &tmp_spt[(i - 1) % 3]; + const tGPspoint *pa = (i - 1 > 0) ? (&tmp_spt[(i - 2) % 3]) : (pb); + const tGPspoint *pd = pc + 1; const tGPspoint *pe = (i + 2 < cmx) ? (pc + 2) : (pd); - spc->x = (int)(0.1 * pa->x + 0.2 * pb->x + 0.4 * pc->x + 0.2 * pd->x + 0.1 * pe->x); - spc->y = (int)(0.1 * pa->y + 0.2 * pb->y + 0.4 * pc->y + 0.2 * pd->y + 0.1 * pe->y); - } - - /* second pass: apply smoothed coordinates */ - for (i = 0, spc = smoothArray; i < gpd->sbuffer_size; i++, spc++) { - tGPspoint *pc = (((tGPspoint *)gpd->sbuffer) + i); + /* Store current point's original state for the two next points! */ + tmp_spt[i % 3] = *spt; - copy_v2_v2_int(&pc->x, &spc->x); + spt->x = (int)(0.1 * pa->x + 0.2 * pb->x + 0.4 * pc->x + 0.2 * pd->x + 0.1 * pe->x); + spt->y = (int)(0.1 * pa->y + 0.2 * pb->y + 0.4 * pc->y + 0.2 * pd->y + 0.1 * pe->y); } - - /* free temp array */ - MEM_freeN(smoothArray); } /* simplify a stroke (in buffer) before storing it @@ -492,7 +498,7 @@ static void gp_stroke_simplify(tGPsdata *p) /* don't simplify if less than 4 points in buffer */ if ((num_points <= 4) || (old_points == NULL)) return; - + /* clear buffer (but don't free mem yet) so that we can write to it * - firstly set sbuffer to NULL, so a new one is allocated * - secondly, reset flag after, as it gets cleared auto @@ -509,17 +515,21 @@ static void gp_stroke_simplify(tGPsdata *p) co[0] += (float)(old_points[offs].x * sfac); \ co[1] += (float)(old_points[offs].y * sfac); \ pressure += old_points[offs].pressure * sfac; \ + time += old_points[offs].time * sfac; \ } (void)0 + /* XXX Here too, do not lose start and end points! */ + gp_stroke_addpoint(p, &old_points->x, old_points->pressure, p->inittime + (double)old_points->time); for (i = 0, j = 0; i < num_points; i++) { if (i - j == 3) { - float co[2], pressure; + float co[2], pressure, time; int mco[2]; /* initialize values */ - co[0] = 0; - co[1] = 0; - pressure = 0; + co[0] = 0.0f; + co[1] = 0.0f; + pressure = 0.0f; + time = 0.0f; /* using macro, calculate new point */ GP_SIMPLIFY_AVPOINT(j, -0.25f); @@ -532,11 +542,13 @@ static void gp_stroke_simplify(tGPsdata *p) mco[1] = (int)co[1]; /* ignore return values on this... assume to be ok for now */ - gp_stroke_addpoint(p, mco, pressure); + gp_stroke_addpoint(p, mco, pressure, p->inittime + (double)time); j += 2; } } + gp_stroke_addpoint(p, &old_points[num_points - 1].x, old_points[num_points - 1].pressure, + p->inittime + (double)old_points[num_points - 1].time); /* free old buffer */ MEM_freeN(old_points); @@ -571,13 +583,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* special case for poly line -- for already added stroke during session * coordinates are getting added to stroke immediately to allow more - * interactive behavior */ + * interactive behavior + */ if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { if (gp_stroke_added_check(p)) { return; } } - + /* allocate memory for a new stroke */ gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke"); @@ -585,13 +598,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) gps->totpoints = totelem; gps->thickness = p->gpl->thickness; gps->flag = gpd->sbuffer_sflag; + gps->inittime = p->inittime; /* allocate enough memory for a continuous array for storage points */ gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); - + /* set pointer to first non-initialized point */ pt = gps->points + (gps->totpoints - totelem); - + /* copy points from the buffer to the stroke */ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) { /* straight lines only -> only endpoints */ @@ -602,8 +616,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); - /* copy pressure */ + /* copy pressure and time */ pt->pressure = ptc->pressure; + pt->time = ptc->time; pt++; } @@ -615,8 +630,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); - /* copy pressure */ + /* copy pressure and time */ pt->pressure = ptc->pressure; + pt->time = ptc->time; } } else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { @@ -626,8 +642,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); - /* copy pressure */ + /* copy pressure and time */ pt->pressure = ptc->pressure; + pt->time = ptc->time; } else { float *depth_arr = NULL; @@ -699,14 +716,15 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL); - /* copy pressure */ + /* copy pressure and time */ pt->pressure = ptc->pressure; + pt->time = ptc->time; } if (depth_arr) MEM_freeN(depth_arr); } - + /* add stroke to frame */ BLI_addtail(&p->gpf->strokes, gps); gp_stroke_added_enable(p); @@ -719,7 +737,7 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) { bGPDspoint *pt_tmp = gps->points; bGPDstroke *gsn = NULL; - + /* if stroke only had two points, get rid of stroke */ if (gps->totpoints == 2) { /* free stroke points, then stroke */ @@ -729,7 +747,7 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) /* nothing left in stroke, so stop */ return 1; } - + /* if last segment, just remove segment from the stroke */ else if (i == gps->totpoints - 2) { /* allocate new points array, and assign most of the old stroke there */ @@ -743,7 +761,7 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) /* nothing left in stroke, so stop */ return 1; } - + /* if first segment, just remove segment from the stroke */ else if (i == 0) { /* allocate new points array, and assign most of the old stroke there */ @@ -751,13 +769,32 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); memcpy(gps->points, pt_tmp + 1, sizeof(bGPDspoint) * gps->totpoints); + /* We must adjust timings! + * Each point's timing data is a delta from stroke's inittime, so as we erase the first + * point of the stroke, we have to offset this inittime and all remaining points' delta values. + * This way we get a new stroke with exactly the same timing as if user had started drawing from + * the second point... + */ + { + bGPDspoint *pts; + float delta = pt_tmp[1].time; + int j; + + gps->inittime += (double)delta; + + pts = gps->points; + for (j = 0; j < gps->totpoints; j++, pts++) { + pts->time -= delta; + } + } + /* free temp buffer */ MEM_freeN(pt_tmp); /* no break here, as there might still be stuff to remove in this stroke */ return 0; } - + /* segment occurs in 'middle' of stroke, so split */ else { /* duplicate stroke, and assign 'later' data to that stroke */ @@ -769,6 +806,25 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) gsn->points = MEM_callocN(sizeof(bGPDspoint) * gsn->totpoints, "gp_stroke_points"); memcpy(gsn->points, pt_tmp + i, sizeof(bGPDspoint) * gsn->totpoints); + /* We must adjust timings of this new stroke! + * Each point's timing data is a delta from stroke's inittime, so as we erase the first + * point of the stroke, we have to offset this inittime and all remaing points' delta values. + * This way we get a new stroke with exactly the same timing as if user had started drawing from + * the second point... + */ + { + bGPDspoint *pts; + float delta = pt_tmp[i].time; + int j; + + gsn->inittime += (double)delta; + + pts = gsn->points; + for (j = 0; j < gsn->totpoints; j++, pts++) { + pts->time -= delta; + } + } + /* adjust existing stroke */ gps->totpoints = i; gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); @@ -790,7 +846,7 @@ static short gp_stroke_eraser_strokeinside(const int mval[], const int UNUSED(mv const float mval_fl[2] = {mval[0], mval[1]}; const float screen_co_a[2] = {x0, y0}; const float screen_co_b[2] = {x1, y1}; - + if (edge_inside_circle(mval_fl, rad, screen_co_a, screen_co_b)) { return TRUE; } @@ -831,7 +887,7 @@ static void gp_point_to_xy(ARegion *ar, View2D *v2d, rctf *subrect, bGPDstroke * /* eraser tool - evaluation per stroke */ -// TODO: this could really do with some optimization (KD-Tree/BVH?) +/* TODO: this could really do with some optimization (KD-Tree/BVH?) */ static void gp_stroke_eraser_dostroke(tGPsdata *p, const int mval[], const int mvalo[], short rad, const rcti *rect, bGPDframe *gpf, bGPDstroke *gps) @@ -850,7 +906,6 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, gp_point_to_xy(p->ar, p->v2d, p->subrect, gps, gps->points, &x0, &y0); /* do boundbox check first */ - if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) { /* only check if point is inside */ if (((x0 - mval[0]) * (x0 - mval[0]) + (y0 - mval[1]) * (y0 - mval[1])) <= rad * rad) { @@ -868,10 +923,10 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, /* get points to work with */ pt1 = gps->points + i; pt2 = gps->points + i + 1; - + gp_point_to_xy(p->ar, p->v2d, p->subrect, gps, pt1, &x0, &y0); gp_point_to_xy(p->ar, p->v2d, p->subrect, gps, pt2, &x1, &y1); - + /* check that point segment of the boundbox of the eraser stroke */ if (((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) || ((!ELEM(V2D_IS_CLIPPED, x1, y1)) && BLI_rcti_isect_pt(rect, x1, y1))) { @@ -919,11 +974,11 @@ static void gp_session_validatebuffer(tGPsdata *p) /* clear memory of buffer (or allocate it if starting a new session) */ if (gpd->sbuffer) { - //printf("\t\tGP - reset sbuffer\n"); + /* printf("\t\tGP - reset sbuffer\n"); */ memset(gpd->sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX); } else { - //printf("\t\tGP - allocate sbuffer\n"); + /* printf("\t\tGP - allocate sbuffer\n"); */ gpd->sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer"); } @@ -932,6 +987,9 @@ static void gp_session_validatebuffer(tGPsdata *p) /* reset flags */ gpd->sbuffer_sflag = 0; + + /* reset inittime */ + p->inittime = 0.0; } /* (re)init new painting data */ @@ -959,8 +1017,8 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) /* supported views first */ case SPACE_VIEW3D: { - // View3D *v3d = curarea->spacedata.first; - // RegionView3D *rv3d = ar->regiondata; + /* View3D *v3d = curarea->spacedata.first; */ + /* RegionView3D *rv3d = ar->regiondata; */ /* set current area * - must verify that region data is 3D-view (and not something else) @@ -976,10 +1034,10 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) } } break; - + case SPACE_NODE: { - //SpaceNode *snode = curarea->spacedata.first; + /* SpaceNode *snode = curarea->spacedata.first; */ /* set current area */ p->sa = curarea; @@ -1007,7 +1065,7 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) break; case SPACE_IMAGE: { - //SpaceImage *sima = curarea->spacedata.first; + /* SpaceImage *sima = curarea->spacedata.first; */ /* set the current area */ p->sa = curarea; @@ -1072,7 +1130,8 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) if (ED_gpencil_session_active() == 0) { /* initialize undo stack, - * also, existing undo stack would make buffer drawn */ + * also, existing undo stack would make buffer drawn + */ gpencil_undo_init(p->gpd); } @@ -1107,7 +1166,7 @@ static void gp_session_cleanup(tGPsdata *p) /* free stroke buffer */ if (gpd->sbuffer) { - //printf("\t\tGP - free sbuffer\n"); + /* printf("\t\tGP - free sbuffer\n"); */ MEM_freeN(gpd->sbuffer); gpd->sbuffer = NULL; } @@ -1115,6 +1174,7 @@ static void gp_session_cleanup(tGPsdata *p) /* clear flags */ gpd->sbuffer_size = 0; gpd->sbuffer_sflag = 0; + p->inittime = 0.0; } /* init new stroke */ @@ -1259,7 +1319,8 @@ static void gp_paint_strokeend(tGPsdata *p) static void gp_paint_cleanup(tGPsdata *p) { /* p->gpd==NULL happens when stroke failed to initialize, - * for example. when GP is hidden in current space (sergey) */ + * for example when GP is hidden in current space (sergey) + */ if (p->gpd) { /* finish off a stroke */ gp_paint_strokeend(p); @@ -1307,7 +1368,7 @@ static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short en else if (enable) { /* enable cursor */ p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C), - NULL, // XXX + NULL, /* XXX */ gpencil_draw_eraser, p); } } @@ -1448,16 +1509,26 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p) /* only add current point to buffer if mouse moved (even though we got an event, it might be just noise) */ else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) { /* try to add point */ - short ok = gp_stroke_addpoint(p, p->mval, p->pressure); + short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime); /* handle errors while adding point */ if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) { /* finish off old stroke */ gp_paint_strokeend(p); + /* And start a new one!!! Else, projection errors! */ + gp_paint_initstroke(p, p->paintmode); /* start a new stroke, starting from previous point */ - gp_stroke_addpoint(p, p->mvalo, p->opressure); - gp_stroke_addpoint(p, p->mval, p->pressure); + /* XXX Must manually reset inittime... */ + /* XXX We only need to reuse previous point if overflow! */ + if (ok == GP_STROKEADD_OVERFLOW) { + p->inittime = p->ocurtime; + gp_stroke_addpoint(p, p->mvalo, p->opressure, p->ocurtime); + } + else { + p->inittime = p->curtime; + } + gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime); } else if (ok == GP_STROKEADD_INVALID) { /* the painting operation cannot continue... */ @@ -1473,6 +1544,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p) p->mvalo[0] = p->mval[0]; p->mvalo[1] = p->mval[1]; p->opressure = p->pressure; + p->ocurtime = p->curtime; } } @@ -1483,13 +1555,14 @@ static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event) PointerRNA itemptr; float mousef[2]; int tablet = 0; - + /* convert from window-space to area-space mouse coordinates - * NOTE: float to ints conversions, +1 factor is probably used to ensure a bit more accurate rounding... + * NOTE: float to ints conversions, +1 factor is probably used to ensure a bit more accurate rounding... */ p->mval[0] = event->mval[0] + 1; p->mval[1] = event->mval[1] + 1; - + p->curtime = PIL_check_seconds_timer(); + /* handle pressure sensitivity (which is supplied by tablets) */ if (event->custom == EVT_DATA_TABLET) { wmTabletData *wmtab = event->customdata; @@ -1497,8 +1570,8 @@ static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event) tablet = (wmtab->Active != EVT_TABLET_NONE); p->pressure = wmtab->Pressure; - //if (wmtab->Active == EVT_TABLET_ERASER) - // TODO... this should get caught by the keymaps which call drawing in the first place + /* if (wmtab->Active == EVT_TABLET_ERASER) */ + /* TODO... this should get caught by the keymaps which call drawing in the first place */ } else p->pressure = 1.0f; @@ -1519,14 +1592,17 @@ static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event) p->mvalo[0] = p->mval[0]; p->mvalo[1] = p->mval[1]; p->opressure = p->pressure; + p->inittime = p->ocurtime = p->curtime; /* special exception here for too high pressure values on first touch in - * windows for some tablets, then we just skip first touch .. + * windows for some tablets, then we just skip first touch... */ if (tablet && (p->pressure >= 0.99f)) return; } + RNA_float_set(&itemptr, "time", p->curtime - p->inittime); + /* apply the current latest drawing point */ gpencil_draw_apply(op, p); @@ -1541,18 +1617,18 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) { tGPsdata *p = NULL; - //printf("GPencil - Starting Re-Drawing\n"); + /* printf("GPencil - Starting Re-Drawing\n"); */ /* try to initialize context data needed while drawing */ if (!gpencil_draw_init(C, op)) { if (op->customdata) MEM_freeN(op->customdata); - //printf("\tGP - no valid data\n"); + /* printf("\tGP - no valid data\n"); */ return OPERATOR_CANCELLED; } else p = op->customdata; - //printf("\tGP - Start redrawing stroke\n"); + /* printf("\tGP - Start redrawing stroke\n"); */ /* loop over the stroke RNA elements recorded (i.e. progress of mouse movement), * setting the relevant values in context at each step, then applying @@ -1561,20 +1637,21 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) { float mousef[2]; - //printf("\t\tGP - stroke elem\n"); + /* printf("\t\tGP - stroke elem\n"); */ /* get relevant data for this point from stroke */ RNA_float_get_array(&itemptr, "mouse", mousef); p->mval[0] = (int)mousef[0]; p->mval[1] = (int)mousef[1]; p->pressure = RNA_float_get(&itemptr, "pressure"); + p->curtime = (double)RNA_float_get(&itemptr, "time") + p->inittime; if (RNA_boolean_get(&itemptr, "is_start")) { /* if first-run flag isn't set already (i.e. not true first stroke), * then we must terminate the previous one first before continuing */ if ((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) { - // TODO: both of these ops can set error-status, but we probably don't need to worry + /* TODO: both of these ops can set error-status, but we probably don't need to worry */ gp_paint_strokeend(p); gp_paint_initstroke(p, p->paintmode); } @@ -1587,6 +1664,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) p->mvalo[0] = p->mval[0]; p->mvalo[1] = p->mval[1]; p->opressure = p->pressure; + p->ocurtime = p->curtime; } /* apply this data as necessary now (as per usual) */ @@ -1594,7 +1672,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) } RNA_END; - //printf("\tGP - done\n"); + /* printf("\tGP - done\n"); */ /* cleanup */ gpencil_draw_exit(C, op); @@ -1640,7 +1718,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event) /* set cursor */ if (p->paintmode == GP_PAINTMODE_ERASER) - WM_cursor_modal(win, BC_CROSSCURSOR); // XXX need a better cursor + WM_cursor_modal(win, BC_CROSSCURSOR); /* XXX need a better cursor */ else WM_cursor_modal(win, BC_PAINTBRUSHCURSOR); @@ -1650,7 +1728,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event) */ if (event->val == KM_PRESS) { /* hotkey invoked - start drawing */ - //printf("\tGP - set first spot\n"); + /* printf("\tGP - set first spot\n"); */ p->status = GP_STATUS_PAINTING; /* handle the initial drawing - i.e. for just doing a simple dot */ @@ -1658,7 +1736,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event) } else { /* toolbar invoked - don't start drawing yet... */ - //printf("\tGP - hotkey invoked... waiting for click-drag\n"); + /* printf("\tGP - hotkey invoked... waiting for click-drag\n"); */ } WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); @@ -1677,7 +1755,7 @@ static int gpencil_area_exists(bContext *C, ScrArea *sa_test) static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) { tGPsdata *p = op->customdata; - + /* we must check that we're still within the area that we're set up to work from * otherwise we could crash (see bug #20586) */ @@ -1685,20 +1763,20 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) printf("\t\t\tGP - wrong area execution abort!\n"); p->status = GP_STATUS_ERROR; } - - //printf("\t\tGP - start stroke\n"); - + + /* printf("\t\tGP - start stroke\n"); */ + /* we may need to set up paint env again if we're resuming */ /* XXX: watch it with the paintmode! in future, * it'd be nice to allow changing paint-mode when in sketching-sessions */ /* XXX: with tablet events, we may event want to check for eraser here, for nicer tablet support */ - + if (gp_session_initdata(C, p)) gp_paint_initstroke(p, p->paintmode); - + if (p->status != GP_STATUS_ERROR) p->status = GP_STATUS_PAINTING; - + return op->customdata; } @@ -1723,7 +1801,7 @@ static void gpencil_stroke_end(wmOperator *op) static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) { tGPsdata *p = op->customdata; - int estate = OPERATOR_RUNNING_MODAL; /* default exit state - we don't pass on events, GP is used with key-modifiers */ + int estate = OPERATOR_PASS_THROUGH; /* default exit state - pass through to support MMB view nav, etc. */ /* if (event->type == NDOF_MOTION) * return OPERATOR_PASS_THROUGH; @@ -1735,8 +1813,19 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) * the stroke is converted to 3D only after * it is finished. This approach should work * better in tools that immediately apply - * in 3D space. */ + * in 3D space. + */ + /* we don't pass on key events, GP is used with key-modifiers - prevents Dkey to insert drivers */ + if (ISKEYBOARD(event->type)) { + if (ELEM4(event->type, LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY)) { + /* allow some keys - for frame changing: [#33412] */ + } + else { + estate = OPERATOR_RUNNING_MODAL; + } + } + //printf("\tGP - handle modal event...\n"); /* exit painting mode (and/or end current stroke) @@ -1744,7 +1833,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) */ if (ELEM4(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY)) { /* exit() ends the current stroke before cleaning up */ - //printf("\t\tGP - end of paint op + end of stroke\n"); + /* printf("\t\tGP - end of paint op + end of stroke\n"); */ p->status = GP_STATUS_DONE; estate = OPERATOR_FINISHED; } @@ -1768,7 +1857,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) if (sketch) { /* end stroke only, and then wait to resume painting soon */ - //printf("\t\tGP - end stroke only\n"); + /* printf("\t\tGP - end stroke only\n"); */ gpencil_stroke_end(op); /* we've just entered idling state, so this event was processed (but no others yet) */ @@ -1778,7 +1867,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); } else { - //printf("\t\tGP - end of stroke + op\n"); + /* printf("\t\tGP - end of stroke + op\n"); */ p->status = GP_STATUS_DONE; estate = OPERATOR_FINISHED; } @@ -1801,7 +1890,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) /* handle painting mouse-movements? */ if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) || (p->flags & GP_PAINTFLAG_FIRSTRUN)) { /* handle drawing event */ - //printf("\t\tGP - add point\n"); + /* printf("\t\tGP - add point\n"); */ gpencil_draw_apply_event(op, event); /* finish painting operation if anything went wrong just now */ @@ -1811,7 +1900,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) } else { /* event handled, so just tag as running modal */ - //printf("\t\t\t\tGP - add point handled!\n"); + /* printf("\t\t\t\tGP - add point handled!\n"); */ estate = OPERATOR_RUNNING_MODAL; } } @@ -1822,7 +1911,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) /* just resize the brush (local version) * TODO: fix the hardcoded size jumps (set to make a visible difference) and hardcoded keys */ - //printf("\t\tGP - resize eraser\n"); + /* printf("\t\tGP - resize eraser\n"); */ switch (event->type) { case WHEELUPMOUSE: /* larger */ case PADPLUSKEY: diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 1d461f797d6..5cc1ecade3e 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -56,6 +56,7 @@ struct wmKeyConfig; typedef struct tGPspoint { int x, y; /* x and y coordinates of cursor (in relative to area) */ float pressure; /* pressure of tablet at this point */ + float time; /* Time relative to stroke start (used when converting to path) */ } tGPspoint; @@ -96,12 +97,13 @@ void ED_gpencil_select_frame(struct bGPDlayer *gpl, int selx, short select_mode void ED_gplayer_frames_delete(struct bGPDlayer *gpl); void ED_gplayer_frames_duplicate(struct bGPDlayer *gpl); +void ED_gplayer_snap_frames(struct bGPDlayer *gpl, struct Scene *scene, short mode); + #if 0 void free_gpcopybuf(void); void copy_gpdata(void); void paste_gpdata(void); -void snap_gplayer_frames(struct bGPDlayer *gpl, short mode); void mirror_gplayer_frames(struct bGPDlayer *gpl, short mode); #endif diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index a50b33966c6..9b726cea56c 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -49,7 +49,7 @@ void ED_space_image_set_mask(struct bContext *C, struct SpaceImage *sim int ED_space_image_color_sample(struct SpaceImage *sima, struct ARegion *ar, int mval[2], float r_col[3]); struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **lock_r); -void ED_space_image_release_buffer(struct SpaceImage *sima, void *lock); +void ED_space_image_release_buffer(struct SpaceImage *sima, struct ImBuf *ibuf, void *lock); int ED_space_image_has_buffer(struct SpaceImage *sima); void ED_space_image_get_size(struct SpaceImage *sima, int *width, int *height); diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index 46ed9798d32..6644f59be94 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -83,12 +83,13 @@ void ED_mask_select_frame(struct MaskLayer *masklay, int selx, short select_mod void ED_masklayer_frames_delete(struct MaskLayer *masklay); void ED_masklayer_frames_duplicate(struct MaskLayer *masklay); +void ED_masklayer_snap_frames(struct MaskLayer *masklay, struct Scene *scene, short mode); + #if 0 void free_gpcopybuf(void); void copy_gpdata(void); void paste_gpdata(void); -void snap_masklayer_frames(struct MaskLayer *masklay, short mode); void mirror_masklayer_frames(struct MaskLayer *masklay, short mode); #endif diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 5ffcfbd94f0..865da8f0e6e 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -153,6 +153,11 @@ int EDBM_select_pick(struct bContext *C, const int mval[2], short extend, short void EDBM_selectmode_set(struct BMEditMesh *em); void EDBM_selectmode_convert(struct BMEditMesh *em, const short selectmode_old, const short selectmode_new); +/* user access this */ +int EDBM_selectmode_toggle(struct bContext *C, const short selectmode_new, + const int action, const int use_extend, const int use_expand); + + void EDBM_deselect_by_material(struct BMEditMesh *em, const short index, const short select); void EDBM_select_toggle_all(struct BMEditMesh *em); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index bd85e93f1af..f15f2418707 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -100,11 +100,6 @@ void ED_view3d_depth_tag_update(struct RegionView3D *rv3d); /* Projection */ #define IS_CLIPPED 12000 -/* TODO, these functions work quite differently, we should make them behave in a uniform way - * otherwise we can't be sure bugs are not added when we need to move from short->float types for eg - * - Campbell */ - - /* return values for ED_view3d_project_...() */ typedef enum { V3D_PROJ_RET_OK = 0, @@ -198,7 +193,8 @@ void ED_view3d_global_to_vector(struct RegionView3D *rv3d, const float coord[3], void ED_view3d_win_to_3d(struct ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]); void ED_view3d_win_to_delta(struct ARegion *ar, const float mval[2], float out[3]); void ED_view3d_win_to_vector(struct ARegion *ar, const float mval[2], float out[3]); -void ED_view3d_win_to_segment_clip(struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]); +void ED_view3d_win_to_segment(struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]); +int ED_view3d_win_to_segment_clip(struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]); void ED_view3d_ob_project_mat_get(struct RegionView3D *v3d, struct Object *ob, float pmat[4][4]); void ED_view3d_unproject(struct bglMats *mats, float out[3], const float x, const float y, const float z); @@ -220,6 +216,9 @@ void ED_view3d_clipping_disable(void); float ED_view3d_pixel_size(struct RegionView3D *rv3d, const float co[3]); +float ED_view3d_radius_to_persp_dist(const float angle, const float radius); +float ED_view3d_radius_to_ortho_dist(const float lens, const float radius); + void drawcircball(int mode, const float cent[3], float rad, float tmat[][4]); /* backbuffer select and draw support */ @@ -295,7 +294,10 @@ struct BGpic *ED_view3D_background_image_new(struct View3D *v3d); void ED_view3D_background_image_remove(struct View3D *v3d, struct BGpic *bgpic); void ED_view3D_background_image_clear(struct View3D *v3d); +#define VIEW3D_MARGIN 1.4f float ED_view3d_offset_distance(float mat[4][4], float ofs[3]); + +float ED_scene_grid_scale(struct Scene *scene, const char **grid_unit); float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit); /* view matrix properties utilities */ diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index e400e44e944..99f7f0856b3 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -97,7 +97,7 @@ DEF_ICON(PLUGIN) /* various ui */ DEF_ICON(HELP) DEF_ICON(GHOST_ENABLED) -DEF_ICON(COLOR) +DEF_ICON(COLOR) /* see COLOR_RED/GREEN/BLUE */ DEF_ICON(LINKED) DEF_ICON(UNLINKED) DEF_ICON(HAND) @@ -428,9 +428,11 @@ DEF_ICON(CURVE_PATH) DEF_ICON(BLANK646) DEF_ICON(BLANK647) DEF_ICON(BLANK648) - DEF_ICON(BLANK649) - DEF_ICON(BLANK650) - DEF_ICON(BLANK651) +#endif +DEF_ICON(COLOR_RED) +DEF_ICON(COLOR_GREEN) +DEF_ICON(COLOR_BLUE) +#ifndef DEF_ICON_BLANK_SKIP DEF_ICON(BLANK652) DEF_ICON(BLANK653) DEF_ICON(BLANK654) @@ -593,6 +595,7 @@ DEF_ICON(MOD_REMESH) DEF_ICON(MOD_OCEAN) DEF_ICON(MOD_WARP) DEF_ICON(MOD_SKIN) +DEF_ICON(MOD_TRIANGULATE) #ifndef DEF_ICON_BLANK_SKIP DEF_ICON(BLANK166) DEF_ICON(BLANK167) @@ -606,7 +609,6 @@ DEF_ICON(MOD_SKIN) DEF_ICON(BLANK175) DEF_ICON(BLANK176) DEF_ICON(BLANK177) - DEF_ICON(BLANK177b) #endif /* ANIMATION */ diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index ed4b4ae027f..2dc552d0fce 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -542,7 +542,7 @@ typedef struct uiStringInfo { /* Note: Expects pointers to uiStringInfo structs as parameters. * Will fill them with translated strings, when possible. * Strings in uiStringInfo must be MEM_freeN'ed by caller. */ -void uiButGetStrInfo(struct bContext *C, uiBut *but, int nbr, ...); +void uiButGetStrInfo(struct bContext *C, uiBut *but, ...); /* Edit i18n stuff. */ /* Name of the main py op from i18n addon. */ @@ -615,7 +615,8 @@ int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int /* 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 */ -int uiSearchBoxhHeight(void); +int uiSearchBoxHeight(void); +int uiSearchBoxWidth(void); void uiBlockSetHandleFunc(uiBlock *block, uiBlockHandleFunc func, void *arg); void uiBlockSetButmFunc(uiBlock *block, uiMenuHandleFunc func, void *arg); @@ -807,7 +808,7 @@ void uiTemplateHistogram(uiLayout *layout, struct PointerRNA *ptr, const char *p void uiTemplateWaveform(uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateVectorscope(uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int type, int levels, int brush); -void uiTemplateColorWheel(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic); +void uiTemplateColorPicker(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic); void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, const char *propname, PointerRNA *used_ptr, const char *used_propname, int active_layer); void uiTemplateGameStates(uiLayout *layout, struct PointerRNA *ptr, const char *propname, @@ -816,6 +817,7 @@ void uiTemplateImage(uiLayout *layout, struct bContext *C, struct PointerRNA *pt void uiTemplateImageSettings(uiLayout *layout, struct PointerRNA *imfptr, int color_management); void uiTemplateImageLayers(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser); void uiTemplateRunningJobs(uiLayout *layout, struct bContext *C); +void uiOperatorSearch_But(uiBut *but); void uiTemplateOperatorSearch(uiLayout *layout); void uiTemplateHeader3D(uiLayout *layout, struct bContext *C); void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C); diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index e879a01dbfb..f4e921e2fa4 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -215,7 +215,11 @@ enum { TH_NLA_META, TH_NLA_META_SEL, TH_NLA_SOUND, - TH_NLA_SOUND_SEL + TH_NLA_SOUND_SEL, + + TH_AXIS_X, /* X/Y/Z Axis */ + TH_AXIS_Y, + TH_AXIS_Z }; /* XXX WARNING: previous is saved in file, so do not change order! */ diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index b8e4fec1259..ce82e064531 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1677,7 +1677,7 @@ void ui_get_but_string(uiBut *but, char *str, size_t maxlen) { if (but->rnaprop && ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) { PropertyType type; - char *buf = NULL; + const char *buf = NULL; int buf_len; type = RNA_property_type(but->rnaprop); @@ -1686,11 +1686,22 @@ void ui_get_but_string(uiBut *but, char *str, size_t maxlen) /* RNA string */ buf = RNA_property_string_get_alloc(&but->rnapoin, but->rnaprop, str, maxlen, &buf_len); } + else if (type == PROP_ENUM) { + /* RNA enum */ + int value = RNA_property_enum_get(&but->rnapoin, but->rnaprop); + if (RNA_property_enum_name(but->block->evil_C, &but->rnapoin, but->rnaprop, value, &buf)) { + BLI_strncpy(str, buf, maxlen); + buf = str; + } + } else if (type == PROP_POINTER) { /* RNA pointer */ PointerRNA ptr = RNA_property_pointer_get(&but->rnapoin, but->rnaprop); buf = RNA_struct_name_get_alloc(&ptr, str, maxlen, &buf_len); } + else { + BLI_assert(0); + } if (!buf) { str[0] = '\0'; @@ -1698,7 +1709,7 @@ void ui_get_but_string(uiBut *but, char *str, size_t maxlen) else if (buf && buf != str) { /* string was too long, we have to truncate */ memcpy(str, buf, MIN2(maxlen, (size_t)buf_len + 1)); - MEM_freeN(buf); + MEM_freeN((void *)buf); } } else if (but->type == IDPOIN) { @@ -1841,6 +1852,17 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str) return 0; } + 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 0; + } + else { + BLI_assert(0); + } } } else if (but->type == IDPOIN) { @@ -1902,8 +1924,9 @@ void ui_set_but_default(bContext *C, short all) static double soft_range_round_up(double value, double max) { - /* round up to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, .. */ - double newmax = pow(10.0, ceil(log(value) / M_LN10)); + /* round up to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, .. + * checking for 0.0 prevents floating point exceptions */ + double newmax = (value != 0.0) ? pow(10.0, ceil(log(value) / M_LN10)) : 0.0; if (newmax * 0.2 >= max && newmax * 0.2 >= value) return newmax * 0.2; @@ -1915,8 +1938,9 @@ static double soft_range_round_up(double value, double max) static double soft_range_round_down(double value, double max) { - /* round down to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, .. */ - double newmax = pow(10.0, floor(log(value) / M_LN10)); + /* round down to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, .. + * checking for 0.0 prevents floating point exceptions */ + double newmax = (value != 0.0) ? pow(10.0, floor(log(value) / M_LN10)) : 0.0; if (newmax * 5.0 <= max && newmax * 5.0 <= value) return newmax * 5.0; @@ -2422,7 +2446,7 @@ void uiBlockEndAlign(uiBlock *block) int ui_but_can_align(uiBut *but) { - return !ELEM3(but->type, LABEL, OPTION, OPTIONN); + return !ELEM4(but->type, LABEL, OPTION, OPTIONN, SEPR); } static void ui_block_do_align_but(uiBut *first, short nr) @@ -2802,6 +2826,7 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s EnumPropertyItem *item; int i, totitem, free; + /* TODO, translate after getting the item, saves many lookups */ RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item, &totitem, &free); for (i = 0; i < totitem; i++) { if (item[i].identifier[0] && item[i].value == (int)max) { @@ -3772,16 +3797,16 @@ void uiButSetFocusOnEnter(wmWindow *win, uiBut *but) wm_event_add(win, &event); } -void uiButGetStrInfo(bContext *C, uiBut *but, int nbr, ...) +void uiButGetStrInfo(bContext *C, uiBut *but, ...) { va_list args; + uiStringInfo *si; EnumPropertyItem *items = NULL, *item = NULL; int totitems, free_items = FALSE; - va_start(args, nbr); - while (nbr--) { - uiStringInfo *si = (uiStringInfo *) va_arg(args, void *); + va_start(args, but); + while ((si = (uiStringInfo *) va_arg(args, void *))) { int type = si->type; char *tmp = NULL; diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 469bd11215e..4d96ad810d4 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -1597,17 +1597,15 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc &scopes->undist_marker, scopes->use_track_mask, width, height, scopes->track_pos); - if (tmpibuf->rect_float) - IMB_rect_from_float(tmpibuf); + if (tmpibuf) { + if (tmpibuf->rect_float) + IMB_rect_from_float(tmpibuf); - /* XXX: for debug only - * tmpibuf->ftype = PNG; - * IMB_saveiff(tmpibuf, "sample.png", IB_rect); */ - - if (tmpibuf->rect) - scopes->track_preview = tmpibuf; - else - IMB_freeImBuf(tmpibuf); + if (tmpibuf->rect) + scopes->track_preview = tmpibuf; + else + IMB_freeImBuf(tmpibuf); + } } if (!ok && scopes->track_preview) { diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 6d262daab12..b80025e0d77 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -279,12 +279,7 @@ static int ui_is_a_warp_but(uiBut *but) static float ui_mouse_scale_warp_factor(const short shift) { - if (U.uiflag & USER_CONTINUOUS_MOUSE) { - return shift ? 0.05f : 1.0f; - } - else { - return 1.0f; - } + return shift ? 0.05f : 1.0f; } static void ui_mouse_scale_warp(uiHandleButtonData *data, @@ -292,16 +287,11 @@ static void ui_mouse_scale_warp(uiHandleButtonData *data, float *r_mx, float *r_my, const short shift) { - if (U.uiflag & USER_CONTINUOUS_MOUSE) { - const float fac = ui_mouse_scale_warp_factor(shift); - /* slow down the mouse, this is fairly picky */ - *r_mx = (data->dragstartx * (1.0f - fac) + mx * fac); - *r_my = (data->dragstarty * (1.0f - fac) + my * fac); - } - else { - *r_mx = mx; - *r_my = my; - } + const float fac = ui_mouse_scale_warp_factor(shift); + + /* slow down the mouse, this is fairly picky */ + *r_mx = (data->dragstartx * (1.0f - fac) + mx * fac); + *r_my = (data->dragstarty * (1.0f - fac) + my * fac); } /* file selectors are exempt from utf-8 checks */ @@ -3306,7 +3296,7 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, ui_get_but_vectorf(but, rgb); - if (color_profile && (int)but->a1) + if (color_profile && (int)but->a1 != UI_GRAD_SV) ui_block_to_display_space_v3(but->block, rgb); rgb_to_hsv_compat_v(rgb, hsv); @@ -3352,7 +3342,7 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, hsv_to_rgb_v(hsv, rgb); - if (color_profile && (int)but->a1) + if (color_profile && ((int)but->a1 != UI_GRAD_SV)) ui_block_to_scene_linear_v3(but->block, rgb); copy_v3_v3(data->vec, rgb); @@ -3378,7 +3368,7 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, wmNDOF ui_get_but_vectorf(but, rgb); - if (color_profile && (int)but->a1) + if (color_profile && (int)but->a1 != UI_GRAD_SV) ui_block_to_display_space_v3(but->block, rgb); rgb_to_hsv_compat_v(rgb, hsv); @@ -3418,7 +3408,7 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, wmNDOF hsv_to_rgb_v(hsv, rgb); - if (color_profile && (int)but->a1) + if (color_profile && (int)but->a1 != UI_GRAD_SV) ui_block_to_scene_linear_v3(but->block, rgb); copy_v3_v3(data->vec, rgb); @@ -4643,7 +4633,7 @@ static int ui_but_menu(bContext *C, uiBut *but) uiPopupMenu *pup; uiLayout *layout; int length; - char *name; + const char *name; uiStringInfo label = {BUT_GET_LABEL, NULL}; /* if ((but->rnapoin.data && but->rnaprop) == 0 && but->optype == NULL)*/ @@ -4651,7 +4641,7 @@ static int ui_but_menu(bContext *C, uiBut *but) button_timers_tooltip_remove(C, but); - uiButGetStrInfo(C, but, 1, &label); + uiButGetStrInfo(C, but, &label, NULL); name = label.strinfo; pup = uiPupMenuBegin(C, name, ICON_NONE); @@ -6050,38 +6040,22 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) switch (event->type) { case MOUSEMOVE: { - /* if the mouse is over the button, do nothing */ - if (ui_mouse_inside_button(data->region, but, event->x, event->y)) { - break; - } + uiBut *bt; - /* if the mouse is over the menu, also do nothing */ if (data->menu && data->menu->region) { if (ui_mouse_inside_region(data->menu->region, event->x, event->y)) { break; } - else { - /* make a rectangle between the menu and the button that opened it, - * this avoids any space between them exiting the popup. see [#29072] - campbell */ - rctf rct_all = but->rect; - rctf rct_win; + } - ui_block_to_window_fl(ar, block, &rct_all.xmin, &rct_all.ymin); - ui_block_to_window_fl(ar, block, &rct_all.xmax, &rct_all.ymax); - - BLI_rctf_rcti_copy(&rct_win, &data->menu->region->winrct); - BLI_rctf_union(&rct_all, &rct_win); - - if (BLI_rctf_isect_pt(&rct_all, event->x, event->y)) { - break; - } + bt = ui_but_find_mouse_over(ar, event->x, event->y); + + if (bt && bt->active != data) { + if (but->type != COLOR) { /* exception */ + data->cancel = TRUE; } + button_activate_state(C, but, BUTTON_STATE_EXIT); } - - if (but->type != COLOR) { /* exception */ - data->cancel = TRUE; - } - button_activate_state(C, but, BUTTON_STATE_EXIT); break; } } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 16159e0f73a..23d3810e058 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -176,7 +176,25 @@ struct uiBut { char *poin; float hardmin, hardmax, softmin, softmax; - float a1, a2; + + /* both these values use depends on the button type + * (polymorphic struct or union would be nicer for this stuff) */ + + /* (type == COLOR), Use UI_GRAD_* values. + * (type == NUM), Use to store RNA 'step' value, for dragging and click-step. + * (type == LABEL), Use (a1 == 1.0f) to use a2 as a blending factor (wow, this is imaginative!). + * (type == SCROLL) Use as scroll size. + * (type == SEARCH_MENU) Use as number or rows. + */ + float a1; + + /* (type == HSVCIRCLE ), Use to store the luminosity. + * (type == NUM), Use to store RNA 'precision' value, for dragging and click-step. + * (type == LABEL), If (a1 == 1.0f) use a2 as a blending factor. + * (type == SEARCH_MENU) Use as number or columns. + */ + float a2; + float aspect; unsigned char col[4]; @@ -340,7 +358,7 @@ struct uiBlock { char color_profile; /* color profile for correcting linear colors for display */ - char *display_device; /* display devide name used to display this block, + char *display_device; /* display device name used to display this block, * used by color widgets to transform colors from/to scene linear */ }; diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 5170fc7d51b..9759c22f30e 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -68,6 +68,8 @@ #define EM_SEPR_X 6 #define EM_SEPR_Y 6 +// #define USE_OP_RESET_BUT // we may want to make this optional, disable for now. + #define UI_OPERATOR_ERROR_RET(_ot, _opname, return_statement) \ if (ot == NULL) { \ ui_item_disabled(layout, _opname); \ @@ -428,7 +430,7 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in but->type = NUMSLI; } } - else if (subtype == PROP_DIRECTION) { + else if (subtype == PROP_DIRECTION && !expand) { uiDefButR_prop(block, BUT_NORMAL, 0, name, x, y, UI_UNIT_X * 3, UI_UNIT_Y * 3, ptr, prop, 0, 0, 0, -1, -1, NULL); } else { @@ -1382,6 +1384,12 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN but->rnasearchprop = searchprop; but->flag |= UI_ICON_LEFT | UI_TEXT_LEFT; + if (RNA_property_type(prop) == PROP_ENUM) { + /* XXX, this will have a menu string, + * but in this case we just want the text */ + but->str[0] = 0; + } + uiButSetSearchFunc(but, rna_search_cb, but, NULL, NULL); } } @@ -1399,13 +1407,14 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna prop = RNA_struct_find_property(ptr, propname); if (!prop) { - RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); + RNA_warning("property not found: %s.%s", + RNA_struct_identifier(ptr->type), propname); return; } type = RNA_property_type(prop); - if (!ELEM(type, PROP_POINTER, PROP_STRING)) { - RNA_warning("Property %s must be a pointer or string", propname); + if (!ELEM3(type, PROP_POINTER, PROP_STRING, PROP_ENUM)) { + RNA_warning("Property %s must be a pointer, string or enum", propname); return; } @@ -1413,11 +1422,13 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna if (!searchprop) { - RNA_warning("search collection property not found: %s.%s", RNA_struct_identifier(ptr->type), searchpropname); + RNA_warning("search collection property not found: %s.%s", + RNA_struct_identifier(searchptr->type), searchpropname); return; } else if (RNA_property_type(searchprop) != PROP_COLLECTION) { - RNA_warning("search collection property is not a collection type: %s.%s", RNA_struct_identifier(ptr->type), searchpropname); + RNA_warning("search collection property is not a collection type: %s.%s", + RNA_struct_identifier(searchptr->type), searchpropname); return; } @@ -1780,7 +1791,7 @@ static void ui_litem_layout_row(uiLayout *litem) if (item->flag) { /* fixed minimum size items */ - itemw = ui_item_fit(minw, fixedx, fixedw, MIN2(w, fixedw), !item->next, litem->alignment, NULL); + itemw = ui_item_fit(minw, fixedx, fixedw, min_ii(w, fixedw), !item->next, litem->alignment, NULL); fixedx += itemw; } else { @@ -1959,9 +1970,9 @@ static void ui_litem_estimate_column_flow(uiLayout *litem) ui_item_size(item, &itemw, &itemh); y -= itemh + style->buttonspacey; - miny = MIN2(miny, y); + miny = min_ii(miny, y); emy -= itemh; - maxw = MAX2(itemw, maxw); + maxw = max_ii(itemw, maxw); /* decide to go to next one */ if (col < flow->totcol - 1 && emy <= -emh) { @@ -2840,10 +2851,12 @@ const char *uiLayoutIntrospect(uiLayout *layout) return str; } +#ifdef USE_OP_RESET_BUT static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), void *op_pt, void *UNUSED(arg_dummy2)) { WM_operator_properties_reset((wmOperator *)op_pt); } +#endif /* this function does not initialize the layout, functions can be called on the layout before and after */ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op, @@ -2911,6 +2924,7 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op, } } +#ifdef USE_OP_RESET_BUT /* its possible that reset can do nothing if all have PROP_SKIP_SAVE enabled * but this is not so important if this button is drawn in those cases * (which isn't all that likely anyway) - campbell */ @@ -2925,6 +2939,7 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Reset operator defaults")); uiButSetFunc(but, ui_layout_operator_buts__reset_cb, op, NULL); } +#endif /* set various special settings for buttons */ { diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index e7a5f993d32..e57e52d74b6 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -960,7 +960,6 @@ static int edittranslation_exec(bContext *C, wmOperator *op) const char *root = U.i18ndir; const char *uilng = BLF_lang_get(); - const int bufs_nbr = 10; uiStringInfo but_label = {BUT_GET_LABEL, NULL}; uiStringInfo rna_label = {BUT_GET_RNA_LABEL, NULL}; uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL}; @@ -990,8 +989,8 @@ static int edittranslation_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - uiButGetStrInfo(C, but, bufs_nbr, &but_label, &rna_label, &enum_label, &but_tip, &rna_tip, &enum_tip, - &rna_struct, &rna_prop, &rna_enum, &rna_ctxt); + uiButGetStrInfo(C, but, &but_label, &rna_label, &enum_label, &but_tip, &rna_tip, &enum_tip, + &rna_struct, &rna_prop, &rna_enum, &rna_ctxt, NULL); WM_operator_properties_create(&ptr, EDTSRC_I18N_OP_NAME); RNA_string_set(&ptr, "lang", uilng); diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 28e361ccf5a..c13aadee069 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -46,6 +46,7 @@ #include "BKE_context.h" #include "BKE_screen.h" +#include "BKE_idcode.h" #include "BKE_global.h" #include "WM_api.h" @@ -426,7 +427,6 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) rctf rect_fl; rcti rect_i; - const int nbr_info = 6; uiStringInfo but_tip = {BUT_GET_TIP, NULL}; uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL}; uiStringInfo enum_tip = {BUT_GET_RNAENUM_TIP, NULL}; @@ -440,50 +440,11 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) /* create tooltip data */ data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData"); - uiButGetStrInfo(C, but, nbr_info, &but_tip, &enum_label, &enum_tip, &op_keymap, &rna_struct, &rna_prop); + uiButGetStrInfo(C, but, &but_tip, &enum_label, &enum_tip, &op_keymap, &rna_struct, &rna_prop, NULL); /* special case, enum rna buttons only have enum item description, * use general enum description too before the specific one */ -#if 0 - if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) { - const char *descr = RNA_property_description(but->rnaprop); - if (descr && descr[0]) { - BLI_strncpy(data->lines[data->totline], descr, sizeof(data->lines[0])); - data->color_id[data->totline] = UI_TIP_LC_MAIN; - data->totline++; - } - if (ELEM(but->type, ROW, MENU)) { - EnumPropertyItem *item; - int totitem, free; - int value = (but->type == ROW) ? (int)but->hardmax : (int)ui_get_but_val(but); - - RNA_property_enum_items_gettexted(C, &but->rnapoin, but->rnaprop, &item, &totitem, &free); - - for (i = 0; i < totitem; i++) { - if (item[i].identifier[0] && item[i].value == value) { - if (item[i].description && item[i].description[0]) { - BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), "%s: %s", - item[i].name, item[i].description); - data->color_id[data->totline] = UI_TIP_LC_SUBMENU; - data->totline++; - } - break; - } - } - - if (free) { - MEM_freeN(item); - } - } - } - - if (but->tip && but->tip[0] != '\0') { - BLI_strncpy(data->lines[data->totline], but->tip, sizeof(data->lines[0])); - data->color_id[data->totline] = UI_TIP_LC_MAIN; - data->totline++; - } -#else /* Tip */ if (but_tip.strinfo) { BLI_strncpy(data->lines[data->totline], but_tip.strinfo, sizeof(data->lines[0])); @@ -497,29 +458,13 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) data->color_id[data->totline] = UI_TIP_LC_SUBMENU; data->totline++; } -#endif -#if 0 - if (but->optype && !(but->block->flag & UI_BLOCK_LOOP)) { - /* operator keymap (not menus, they already have it) */ - prop = (but->opptr) ? but->opptr->data : NULL; - - if (WM_key_event_operator_string(C, but->optype->idname, but->opcontext, prop, TRUE, - buf, sizeof(buf))) - { - BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Shortcut: %s"), buf); - data->color_id[data->totline] = UI_TIP_LC_NORMAL; - data->totline++; - } - } -#else /* Op shortcut */ if (op_keymap.strinfo) { BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Shortcut: %s"), op_keymap.strinfo); data->color_id[data->totline] = UI_TIP_LC_NORMAL; data->totline++; } -#endif if (ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) { /* full string */ @@ -553,15 +498,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) data->totline++; } } -#if 0 - /* rna info */ - if ((U.flag & USER_TOOLTIPS_PYTHON) == 0) { - BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Python: %s.%s"), - RNA_struct_identifier(but->rnapoin.type), RNA_property_identifier(but->rnaprop)); - data->color_id[data->totline] = UI_TIP_LC_PYTHON; - data->totline++; - } -#endif + if (but->rnapoin.id.data) { ID *id = but->rnapoin.id.data; if (id->lib && id->lib->name) { @@ -603,30 +540,55 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) } } } -#if 0 - else if (ELEM(but->type, MENU, PULLDOWN)) { - if ((U.flag & USER_TOOLTIPS_PYTHON) == 0) { - MenuType *mt = uiButGetMenuType(but); - if (mt) { - BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Python: %s"), mt->idname); - data->color_id[data->totline] = UI_TIP_LC_PYTHON; - data->totline++; - } - } - } -#else if ((U.flag & USER_TOOLTIPS_PYTHON) == 0 && !but->optype && rna_struct.strinfo) { - if (rna_prop.strinfo) + if (rna_prop.strinfo) { /* Struct and prop */ BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), - TIP_("Python: %s.%s"), rna_struct.strinfo, rna_prop.strinfo); - else + TIP_("Python: %s.%s"), + rna_struct.strinfo, rna_prop.strinfo); + } + else { /* Only struct (e.g. menus) */ - BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Python: %s"), rna_struct.strinfo); + BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), + TIP_("Python: %s"), rna_struct.strinfo); + } data->color_id[data->totline] = UI_TIP_LC_PYTHON; data->totline++; + + if (but->rnapoin.id.data) { + /* this could get its own 'BUT_GET_...' type */ + PointerRNA *ptr = &but->rnapoin; + PropertyRNA *prop = but->rnaprop; + ID *id = ptr->id.data; + + char *id_path; + char *data_path = NULL; + + /* never fails */ + id_path = RNA_path_from_ID_python(id); + + if (ptr->id.data && ptr->data && prop) { + data_path = RNA_path_from_ID_to_property(ptr, prop); + } + + if (data_path) { + BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), + "%s.%s", /* no need to translate */ + id_path, data_path); + MEM_freeN(data_path); + } + else if (prop) { + /* can't find the path. be explicit in our ignorance "..." */ + BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), + "%s ... %s", /* no need to translate */ + id_path, rna_prop.strinfo ? rna_prop.strinfo : RNA_property_identifier(prop)); + } + MEM_freeN(id_path); + + data->color_id[data->totline] = UI_TIP_LC_PYTHON; + data->totline++; + } } -#endif /* Free strinfo's... */ if (but_tip.strinfo) @@ -642,7 +604,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) if (rna_prop.strinfo) MEM_freeN(rna_prop.strinfo); - assert(data->totline < MAX_TOOLTIP_LINES); + BLI_assert(data->totline < MAX_TOOLTIP_LINES); if (data->totline == 0) { MEM_freeN(data); @@ -826,11 +788,17 @@ int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int icon return 1; } -int uiSearchBoxhHeight(void) +int uiSearchBoxHeight(void) { return SEARCH_ITEMS * UI_UNIT_Y + 2 * MENU_TOP; } +int uiSearchBoxWidth(void) +{ + /* was hardcoded at 150 */ + return 9 * UI_UNIT_X; +} + /* ar is the search box itself */ static void ui_searchbox_select(bContext *C, ARegion *ar, uiBut *but, int step) { @@ -1191,10 +1159,11 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but) } } else { + const int searchbox_width = uiSearchBoxWidth(); rect_fl.xmin = but->rect.xmin - 5; /* align text with button */ rect_fl.xmax = but->rect.xmax + 5; /* symmetrical */ rect_fl.ymax = but->rect.ymin; - rect_fl.ymin = rect_fl.ymax - uiSearchBoxhHeight(); + rect_fl.ymin = rect_fl.ymax - uiSearchBoxHeight(); ofsx = (but->block->panel) ? but->block->panel->ofsx : 0; ofsy = (but->block->panel) ? but->block->panel->ofsy : 0; @@ -1202,8 +1171,8 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but) BLI_rctf_translate(&rect_fl, ofsx, ofsy); /* minimal width */ - if (BLI_rctf_size_x(&rect_fl) < 150) { - rect_fl.xmax = rect_fl.xmin + 150; /* XXX arbitrary */ + if (BLI_rctf_size_x(&rect_fl) < searchbox_width) { + rect_fl.xmax = rect_fl.xmin + searchbox_width; } /* copy to int, gets projected if possible too */ @@ -1409,8 +1378,8 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, dir1 &= (UI_TOP | UI_DOWN); } - if (dir2 == 0) if (dir1 == UI_LEFT || dir1 == UI_RIGHT) dir2 = UI_DOWN; - if (dir2 == 0) if (dir1 == UI_TOP || dir1 == UI_DOWN) dir2 = UI_LEFT; + if ((dir2 == 0) && (dir1 == UI_LEFT || dir1 == UI_RIGHT)) dir2 = UI_DOWN; + if ((dir2 == 0) && (dir1 == UI_TOP || dir1 == UI_DOWN)) dir2 = UI_LEFT; /* no space at all? don't change */ if (left || right) { @@ -2254,13 +2223,11 @@ uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_ show_picker = (but->block->flag & UI_BLOCK_POPUP) == 0; } - uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT); - copy_v3_v3(handle->retvec, but->editvec); uiBlockPicker(block, handle->retvec, &but->rnapoin, but->rnaprop, show_picker); - block->flag = UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_KEEP_OPEN | UI_BLOCK_OUT_1; + block->flag = UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_KEEP_OPEN | UI_BLOCK_OUT_1 | UI_BLOCK_MOVEMOUSE_QUIT; uiBoundsBlock(block, 10); block->block_event_func = ui_picker_small_wheel_cb; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 24aca0c037d..f7a53c6bab2 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -185,15 +185,18 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem) /* fake button, it holds space for search items */ uiDefBut(block, LABEL, 0, "", 10, 15, w, h, NULL, 0, 0, 0, 0, NULL); - but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, 19, template.prv_rows, template.prv_cols, ""); + but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, 19, + template.prv_rows, template.prv_cols, ""); uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data); } /* list view */ else { + const int searchbox_width = uiSearchBoxWidth(); + const int searchbox_height = uiSearchBoxHeight(); /* fake button, it holds space for search items */ - uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); + uiDefBut(block, LABEL, 0, "", 10, 15, searchbox_width, searchbox_height, NULL, 0, 0, 0, 0, NULL); - but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, 150, 19, 0, 0, ""); + but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, searchbox_width, UI_UNIT_Y - 1, 0, 0, ""); uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data); } @@ -315,33 +318,68 @@ static const char *template_id_browse_tip(StructRNA *type) if (type) { switch (RNA_type_to_ID_code(type)) { case ID_SCE: return N_("Browse Scene to be linked"); - case ID_OB: return N_("Browse Object to be linked"); - case ID_ME: return N_("Browse Mesh Data to be linked"); - case ID_CU: return N_("Browse Curve Data to be linked"); - case ID_MB: return N_("Browse Metaball Data to be linked"); - case ID_MA: return N_("Browse Material to be linked"); - case ID_TE: return N_("Browse Texture to be linked"); - case ID_IM: return N_("Browse Image to be linked"); - case ID_LT: return N_("Browse Lattice Data to be linked"); - case ID_LA: return N_("Browse Lamp Data to be linked"); - case ID_CA: return N_("Browse Camera Data to be linked"); - case ID_WO: return N_("Browse World Settings to be linked"); + case ID_OB: return N_("Browse Object to be linked"); + case ID_ME: return N_("Browse Mesh Data to be linked"); + case ID_CU: return N_("Browse Curve Data to be linked"); + case ID_MB: return N_("Browse Metaball Data to be linked"); + case ID_MA: return N_("Browse Material to be linked"); + case ID_TE: return N_("Browse Texture to be linked"); + case ID_IM: return N_("Browse Image to be linked"); + case ID_LT: return N_("Browse Lattice Data to be linked"); + case ID_LA: return N_("Browse Lamp Data to be linked"); + case ID_CA: return N_("Browse Camera Data to be linked"); + case ID_WO: return N_("Browse World Settings to be linked"); case ID_SCR: return N_("Choose Screen lay-out"); case ID_TXT: return N_("Browse Text to be linked"); case ID_SPK: return N_("Browse Speaker Data to be linked"); - case ID_SO: return N_("Browse Sound to be linked"); - case ID_AR: return N_("Browse Armature data to be linked"); - case ID_AC: return N_("Browse Action to be linked"); - case ID_NT: return N_("Browse Node Tree to be linked"); - case ID_BR: return N_("Browse Brush to be linked"); - case ID_PA: return N_("Browse Particle System to be linked"); - case ID_GD: return N_("Browse Grease Pencil Data to be linked"); + case ID_SO: return N_("Browse Sound to be linked"); + case ID_AR: return N_("Browse Armature data to be linked"); + case ID_AC: return N_("Browse Action to be linked"); + case ID_NT: return N_("Browse Node Tree to be linked"); + case ID_BR: return N_("Browse Brush to be linked"); + case ID_PA: return N_("Browse Particle System to be linked"); + case ID_GD: return N_("Browse Grease Pencil Data to be linked"); } } return N_("Browse ID data to be linked"); } -static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, short idcode, int flag, const char *newop, const char *openop, const char *unlinkop) +/* Return a type-based i18n context, needed e.g. by "New" button. + * In most languages, this adjective takes different form based on gender of type name... + */ +static const char *template_id_context(StructRNA *type) +{ + if (type) { + switch (RNA_type_to_ID_code(type)) { + case ID_SCE: return BLF_I18NCONTEXT_ID_SCENE; + case ID_OB: return BLF_I18NCONTEXT_ID_OBJECT; + case ID_ME: return BLF_I18NCONTEXT_ID_MESH; + case ID_CU: return BLF_I18NCONTEXT_ID_CURVE; + case ID_MB: return BLF_I18NCONTEXT_ID_METABALL; + case ID_MA: return BLF_I18NCONTEXT_ID_MATERIAL; + case ID_TE: return BLF_I18NCONTEXT_ID_TEXTURE; + case ID_IM: return BLF_I18NCONTEXT_ID_IMAGE; + case ID_LT: return BLF_I18NCONTEXT_ID_LATTICE; + case ID_LA: return BLF_I18NCONTEXT_ID_LAMP; + case ID_CA: return BLF_I18NCONTEXT_ID_CAMERA; + case ID_WO: return BLF_I18NCONTEXT_ID_WORLD; + case ID_SCR: return BLF_I18NCONTEXT_ID_SCREEN; + case ID_TXT: return BLF_I18NCONTEXT_ID_TEXT; + case ID_SPK: return BLF_I18NCONTEXT_ID_SPEAKER; + case ID_SO: return BLF_I18NCONTEXT_ID_SOUND; + case ID_AR: return BLF_I18NCONTEXT_ID_ARMATURE; + case ID_AC: return BLF_I18NCONTEXT_ID_ACTION; + case ID_NT: return BLF_I18NCONTEXT_ID_NODETREE; + case ID_BR: return BLF_I18NCONTEXT_ID_BRUSH; + case ID_PA: return BLF_I18NCONTEXT_ID_PARTICLESETTINGS; + case ID_GD: return BLF_I18NCONTEXT_ID_GPENCIL; + } + } + return BLF_I18NCONTEXT_DEFAULT; +} + +static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, short idcode, int flag, + const char *newop, const char *openop, const char *unlinkop) { uiBut *but; uiBlock *block; @@ -349,6 +387,7 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str // ListBase *lb; // UNUSED ID *id, *idfrom; int editable = RNA_property_editable(&template->ptr, template->prop); + const char *i18n_ctxt = template_id_context(type); idptr = RNA_property_pointer_get(&template->ptr, template->prop); id = idptr.data; @@ -400,19 +439,20 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str //text_idbutton(id, name); name[0] = '\0'; - but = uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type)); + but = uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, + &idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type)); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME)); if (user_alert) uiButSetFlag(but, UI_BUT_REDALERT); if (id->lib) { if (id->flag & LIB_INDIRECT) { - but = uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, - TIP_("Indirect library datablock, cannot change")); + but = uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Indirect library datablock, cannot change")); uiButSetFlag(but, UI_BUT_DISABLED); } else { - but = uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, - TIP_("Direct linked library datablock, click to make local")); + but = uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Direct linked library datablock, click to make local")); if (!id_make_local(id, 1 /* test */) || (idfrom && idfrom->lib)) uiButSetFlag(but, UI_BUT_DISABLED); } @@ -425,7 +465,8 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str BLI_snprintf(numstr, sizeof(numstr), "%d", id->us); - but = uiDefBut(block, BUT, 0, numstr, 0, 0, UI_UNIT_X + ((id->us < 10) ? 0 : 10), UI_UNIT_Y, NULL, 0, 0, 0, 0, + but = uiDefBut(block, BUT, 0, numstr, 0, 0, UI_UNIT_X + ((id->us < 10) ? 0 : 10), UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Display number of users of this data (click to make a single-user copy)")); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE)); @@ -450,12 +491,39 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str if (flag & UI_ID_ADD_NEW) { int w = id ? UI_UNIT_X : (flag & UI_ID_OPEN) ? UI_UNIT_X * 3 : UI_UNIT_X * 6; + /* i18n markup, does nothing! */ + BLF_I18N_MSGID_MULTI_CTXT("New", BLF_I18NCONTEXT_DEFAULT, + BLF_I18NCONTEXT_ID_SCENE, + BLF_I18NCONTEXT_ID_OBJECT, + BLF_I18NCONTEXT_ID_MESH, + BLF_I18NCONTEXT_ID_CURVE, + BLF_I18NCONTEXT_ID_METABALL, + BLF_I18NCONTEXT_ID_MATERIAL, + BLF_I18NCONTEXT_ID_TEXTURE, + BLF_I18NCONTEXT_ID_IMAGE, + BLF_I18NCONTEXT_ID_LATTICE, + BLF_I18NCONTEXT_ID_LAMP, + BLF_I18NCONTEXT_ID_CAMERA, + BLF_I18NCONTEXT_ID_WORLD, + BLF_I18NCONTEXT_ID_SCREEN, + BLF_I18NCONTEXT_ID_TEXT); + BLF_I18N_MSGID_MULTI_CTXT("New", BLF_I18NCONTEXT_ID_SPEAKER, + BLF_I18NCONTEXT_ID_SOUND, + BLF_I18NCONTEXT_ID_ARMATURE, + BLF_I18NCONTEXT_ID_ACTION, + BLF_I18NCONTEXT_ID_NODETREE, + BLF_I18NCONTEXT_ID_BRUSH, + BLF_I18NCONTEXT_ID_PARTICLESETTINGS, + BLF_I18NCONTEXT_ID_GPENCIL); + if (newop) { - but = uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, (id) ? "" : IFACE_("New"), 0, 0, w, UI_UNIT_Y, NULL); + but = uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, + (id) ? "" : CTX_IFACE_(i18n_ctxt, "New"), 0, 0, w, UI_UNIT_Y, NULL); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW)); } else { - but = uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id) ? "" : IFACE_("New"), 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); + but = uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id) ? "" : CTX_IFACE_(i18n_ctxt, "New"), + 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW)); } @@ -467,11 +535,13 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str int w = id ? UI_UNIT_X : (flag & UI_ID_ADD_NEW) ? UI_UNIT_X * 3 : UI_UNIT_X * 6; if (openop) { - but = uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id) ? "" : IFACE_("Open"), 0, 0, w, UI_UNIT_Y, NULL); + but = uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id) ? "" : IFACE_("Open"), + 0, 0, w, UI_UNIT_Y, NULL); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN)); } else { - but = uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id) ? "" : IFACE_("Open"), 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); + but = uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id) ? "" : IFACE_("Open"), 0, 0, w, UI_UNIT_Y, + NULL, 0, 0, 0, 0, NULL); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN)); } @@ -488,7 +558,8 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str } else { but = uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, - TIP_("Unlink datablock. Shift + Click to set users to zero, data will then not be saved")); + TIP_("Unlink datablock " + "(Shift + Click to set users to zero, data will then not be saved)")); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE)); if (RNA_property_flag(template->prop) & PROP_NEVER_NULL) @@ -505,7 +576,8 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str uiBlockEndAlign(block); } -static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int flag, int prv_rows, int prv_cols) +static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop, int flag, int prv_rows, int prv_cols) { TemplateID *template; PropertyRNA *prop; @@ -545,19 +617,24 @@ static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const MEM_freeN(template); } -void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop) +void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop) { - ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE, 0, 0); + ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, + UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE, 0, 0); } -void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop) +void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop) { ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME, 0, 0); } -void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int rows, int cols) +void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop, int rows, int cols) { - ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS, rows, cols); + ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, + UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS, rows, cols); } /************************ ID Chooser Template ***************************/ @@ -567,7 +644,8 @@ void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const c * - propname: property identifier for property that ID-pointer gets stored to * - proptypename: property identifier for property used to determine the type of ID-pointer that can be used */ -void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, const char *text) +void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, + const char *text) { PropertyRNA *propID, *propType; uiLayout *row; @@ -614,7 +692,8 @@ void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, co * - propname: property identifier for property that path gets stored to * - root_ptr: struct that path gets built from */ -void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *UNUSED(root_ptr), const char *text) +void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *UNUSED(root_ptr), + const char *text) { PropertyRNA *propPath; uiLayout *row; @@ -707,7 +786,7 @@ static int modifier_can_delete(ModifierData *md) return 1; } -/* Check wheter Modifier is a simulation or not, this is used for switching to the physics/particles context tab */ +/* Check whether Modifier is a simulation or not, this is used for switching to the physics/particles context tab */ static int modifier_is_simulation(ModifierData *md) { /* Physic Tab */ @@ -779,7 +858,7 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, uiBlockBeginAlign(block); /* Softbody not allowed in this situation, enforce! */ if (((md->type != eModifierType_Softbody && md->type != eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) && - (md->type != eModifierType_Surface) ) + (md->type != eModifierType_Surface) ) { uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE); uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE); @@ -791,7 +870,8 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, if (ob->type == OB_MESH) { if (modifier_couldBeCage(scene, md) && (index <= lastCageIndex)) { /* -- convert to rna ? */ - but = uiDefIconButBitI(block, TOG, eModifierMode_OnCage, 0, ICON_MESH_DATA, 0, 0, UI_UNIT_X - 2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, + but = uiDefIconButBitI(block, TOG, eModifierMode_OnCage, 0, ICON_MESH_DATA, 0, 0, + UI_UNIT_X - 2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, TIP_("Apply modifier to editing cage during Edit mode")); if (index < cageIndex) uiButSetFlag(but, UI_BUT_DISABLED); @@ -802,7 +882,8 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, /* place holder button */ uiBlockSetEmboss(block, UI_EMBOSSN); - but = uiDefIconBut(block, BUT, 0, ICON_NONE, 0, 0, UI_UNIT_X - 2, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, NULL); + but = uiDefIconBut(block, BUT, 0, ICON_NONE, 0, 0, UI_UNIT_X - 2, UI_UNIT_Y, + NULL, 0.0, 0.0, 0.0, 0.0, NULL); uiButSetFlag(but, UI_BUT_DISABLED); uiBlockSetEmboss(block, UI_EMBOSS); } @@ -812,7 +893,8 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) { /* add disabled pre-tessellated button, so users could have * message for this modifiers */ - but = uiDefIconButBitI(block, TOG, eModifierMode_ApplyOnSpline, 0, ICON_SURFACE_DATA, 0, 0, UI_UNIT_X - 2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, + but = uiDefIconButBitI(block, TOG, eModifierMode_ApplyOnSpline, 0, ICON_SURFACE_DATA, 0, 0, + UI_UNIT_X - 2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, TIP_("This modifier could be applied on splines' points only")); uiButSetFlag(but, UI_BUT_DISABLED); } @@ -866,15 +948,20 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT); uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply"), 0, "apply_as", MODIFIER_APPLY_DATA); - if (modifier_sameTopology(md) && !modifier_nonGeometrical(md)) - uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply as Shape Key"), 0, "apply_as", MODIFIER_APPLY_SHAPE); + if (modifier_isSameTopology(md) && !modifier_isNonGeometrical(md)) { + uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply as Shape Key"), 0, + "apply_as", MODIFIER_APPLY_SHAPE); + } } uiBlockClearButLock(block); uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE); - if (!ELEM5(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem, eModifierType_Cloth, eModifierType_Smoke)) + if (!ELEM5(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem, + eModifierType_Cloth, eModifierType_Smoke)) + { uiItemO(row, IFACE_("Copy"), ICON_NONE, "OBJECT_OT_modifier_copy"); + } } /* result is the layout block inside the box, that we return so that modifier settings can be drawn */ @@ -1046,8 +1133,10 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) uiBlockSetEmboss(block, UI_EMBOSSN); /* draw a ghost icon (for proxy) and also a lock beside it, to show that constraint is "proxy locked" */ - uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_GHOST, xco + 244, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected")); - uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_LOCKED, xco + 262, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected")); + uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_GHOST, xco + 244, yco, 19, 19, + NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected")); + uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_LOCKED, xco + 262, yco, 19, 19, + NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected")); uiBlockSetEmboss(block, UI_EMBOSS); } @@ -1076,7 +1165,8 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) /* enabled */ uiBlockSetEmboss(block, UI_EMBOSSN); - uiItemR(row, &ptr, "mute", 0, "", (con->flag & CONSTRAINT_OFF) ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF); + uiItemR(row, &ptr, "mute", 0, "", + (con->flag & CONSTRAINT_OFF) ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF); uiBlockSetEmboss(block, UI_EMBOSS); uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT); @@ -1233,14 +1323,22 @@ void uiTemplatePreview(uiLayout *layout, ID *id, int show_buttons, ID *parent, M RNA_pointer_create(id, &RNA_Texture, tex, &texture_ptr); uiLayoutRow(layout, TRUE); - uiDefButS(block, ROW, B_MATPRV, IFACE_("Texture"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, pr_texture, 10, TEX_PR_TEXTURE, 0, 0, ""); - if (GS(parent->name) == ID_MA) - uiDefButS(block, ROW, B_MATPRV, IFACE_("Material"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); - else if (GS(parent->name) == ID_LA) - uiDefButS(block, ROW, B_MATPRV, IFACE_("Lamp"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); - else if (GS(parent->name) == ID_WO) - uiDefButS(block, ROW, B_MATPRV, IFACE_("World"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); - uiDefButS(block, ROW, B_MATPRV, IFACE_("Both"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, pr_texture, 10, TEX_PR_BOTH, 0, 0, ""); + uiDefButS(block, ROW, B_MATPRV, IFACE_("Texture"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, + pr_texture, 10, TEX_PR_TEXTURE, 0, 0, ""); + if (GS(parent->name) == ID_MA) { + uiDefButS(block, ROW, B_MATPRV, IFACE_("Material"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, + pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); + } + else if (GS(parent->name) == ID_LA) { + uiDefButS(block, ROW, B_MATPRV, IFACE_("Lamp"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, + pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); + } + else if (GS(parent->name) == ID_WO) { + uiDefButS(block, ROW, B_MATPRV, IFACE_("World"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, + pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); + } + uiDefButS(block, ROW, B_MATPRV, IFACE_("Both"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, + pr_texture, 10, TEX_PR_BOTH, 0, 0, ""); /* Alpha button for texture preview */ if (*pr_texture != TEX_PR_OTHER) { @@ -1330,7 +1428,8 @@ static void colorband_update_cb(bContext *UNUSED(C), void *bt_v, void *coba_v) } /* offset aligns from bottom, standard width 300, height 115 */ -static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand *coba, int xoffs, int yoffs, RNAUpdateCb *cb) +static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand *coba, + int xoffs, int yoffs, RNAUpdateCb *cb) { uiBut *bt; uiLayout *row; @@ -1349,13 +1448,16 @@ static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand /* XXX, todo for later - convert to operator - campbell */ - bt = uiDefBut(block, BUT, 0, "F", 95 + xoffs, line1_y, 20, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Flip colorband")); + bt = uiDefBut(block, BUT, 0, "F", 95 + xoffs, line1_y, 20, UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Flip colorband")); uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba); - uiDefButS(block, NUM, 0, "", 120 + xoffs, line1_y, 80, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot - 1)), 0, 0, TIP_("Choose active color stop")); + uiDefButS(block, NUM, 0, "", 120 + xoffs, line1_y, 80, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot - 1)), + 0, 0, TIP_("Choose active color stop")); - bt = uiDefButS(block, MENU, 0, IFACE_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"), - 210 + xoffs, line1_y, 90, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, TIP_("Set interpolation between color stops")); + bt = uiDefButS(block, MENU, 0, IFACE_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"), + 210 + xoffs, line1_y, 90, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, + TIP_("Set interpolation between color stops")); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); uiBlockEndAlign(block); @@ -1391,10 +1493,11 @@ static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand bt = uiDefBut(block, BUT, 0, IFACE_("Add"), xs, butr->ymin + UI_UNIT_Y, 2.0f * unit, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Add a new color stop to the colorband")); uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba); - bt = uiDefBut(block, BUT, 0, IFACE_("Delete"), xs + 2.0f * unit, butr->ymin + UI_UNIT_Y, 1.5f * unit, UI_UNIT_Y, NULL, 0, 0, 0, 0, - TIP_("Delete the active position")); + bt = uiDefBut(block, BUT, 0, IFACE_("Delete"), xs + 2.0f * unit, butr->ymin + UI_UNIT_Y, 1.5f * unit, UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Delete the active position")); uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba); - bt = uiDefBut(block, BUT, 0, "F", xs + 3.5f * unit, butr->ymin + UI_UNIT_Y, 0.5f * unit, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Flip the color ramp")); + bt = uiDefBut(block, BUT, 0, "F", xs + 3.5f * unit, butr->ymin + UI_UNIT_Y, 0.5f * unit, UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Flip the color ramp")); uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba); uiBlockEndAlign(block); @@ -1406,7 +1509,7 @@ static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand } bt = uiDefButS(block, MENU, 0, IFACE_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"), - xs + 10.0f * unit, butr->ymin + UI_UNIT_Y, unit * 4, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, + xs + 10.0f * unit, butr->ymin + UI_UNIT_Y, unit * 4, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, TIP_("Set interpolation between color stops")); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); @@ -1416,7 +1519,8 @@ static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand uiBlockEndAlign(block); } -static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, int small, RNAUpdateCb *cb) +static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, + int small, RNAUpdateCb *cb) { if (small) colorband_buttons_small(layout, block, coba, butr, cb); @@ -1485,7 +1589,8 @@ void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname hist->height = (hist->height <= UI_UNIT_Y) ? UI_UNIT_Y : hist->height; - bt = uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), hist->height, hist, 0, 0, 0, 0, ""); + bt = uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), hist->height, hist, + 0, 0, 0, 0, ""); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); MEM_freeN(cb); @@ -1522,7 +1627,8 @@ void uiTemplateWaveform(uiLayout *layout, PointerRNA *ptr, const char *propname) scopes->wavefrm_height = (scopes->wavefrm_height <= UI_UNIT_Y) ? UI_UNIT_Y : scopes->wavefrm_height; - bt = uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), scopes->wavefrm_height, scopes, 0, 0, 0, 0, ""); + bt = uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), scopes->wavefrm_height, scopes, + 0, 0, 0, 0, ""); (void)bt; /* UNUSED */ MEM_freeN(cb); @@ -1559,7 +1665,8 @@ void uiTemplateVectorscope(uiLayout *layout, PointerRNA *ptr, const char *propna scopes->vecscope_height = (scopes->vecscope_height <= UI_UNIT_Y) ? UI_UNIT_Y : scopes->vecscope_height; - bt = uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), scopes->vecscope_height, scopes, 0, 0, 0, 0, ""); + bt = uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), + scopes->vecscope_height, scopes, 0, 0, 0, 0, ""); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); MEM_freeN(cb); @@ -1658,10 +1765,14 @@ static uiBlock *curvemap_clipping_func(bContext *C, ARegion *ar, void *cumap_v) uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL); uiBlockBeginAlign(block); - uiDefButF(block, NUM, 0, IFACE_("Min X "), 0, 4 * UI_UNIT_Y, width, UI_UNIT_Y, &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, ""); - uiDefButF(block, NUM, 0, IFACE_("Min Y "), 0, 3 * UI_UNIT_Y, width, UI_UNIT_Y, &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, ""); - uiDefButF(block, NUM, 0, IFACE_("Max X "), 0, 2 * UI_UNIT_Y, width, UI_UNIT_Y, &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, ""); - uiDefButF(block, NUM, 0, IFACE_("Max Y "), 0, UI_UNIT_Y, width, UI_UNIT_Y, &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, ""); + uiDefButF(block, NUM, 0, IFACE_("Min X "), 0, 4 * UI_UNIT_Y, width, UI_UNIT_Y, + &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, ""); + uiDefButF(block, NUM, 0, IFACE_("Min Y "), 0, 3 * UI_UNIT_Y, width, UI_UNIT_Y, + &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, ""); + uiDefButF(block, NUM, 0, IFACE_("Max X "), 0, 2 * UI_UNIT_Y, width, UI_UNIT_Y, + &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, ""); + uiDefButF(block, NUM, 0, IFACE_("Max Y "), 0, UI_UNIT_Y, width, UI_UNIT_Y, + &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, ""); uiBlockSetDirection(block, UI_RIGHT); @@ -1710,12 +1821,18 @@ static uiBlock *curvemap_tools_func(bContext *C, ARegion *ar, void *cumap_v) block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Horizontal"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 4, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Extrapolated"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 5, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Horizontal"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 4, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Extrapolated"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 5, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); uiBlockSetDirection(block, UI_RIGHT); uiTextBoundsBlock(block, 50); @@ -1732,10 +1849,14 @@ static uiBlock *curvemap_brush_tools_func(bContext *C, ARegion *ar, void *cumap_ block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); uiBlockSetDirection(block, UI_RIGHT); uiTextBoundsBlock(block, 50); @@ -1775,7 +1896,8 @@ static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v) } /* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */ -static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, int brush, RNAUpdateCb *cb) +static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, + int brush, RNAUpdateCb *cb) { CurveMapping *cumap = ptr->data; CurveMap *cm = &cumap->cm[cumap->cur]; @@ -1899,10 +2021,16 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe } if (cmp) { + const float range_clamp[2] = {0.0f, 1.0f}; + const float range_unclamp[2] = {-1000.0f, 1000.0f}; /* arbitrary limits here */ + const float *range = (cumap->flag & CUMA_DO_CLIP) ? range_clamp : range_unclamp; + uiLayoutRow(layout, TRUE); uiBlockSetNFunc(block, curvemap_buttons_update, MEM_dupallocN(cb), cumap); - bt = uiDefButF(block, NUM, 0, "X", 0, 2 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, &cmp->x, 0.0f, 1.0f, 1, 5, ""); - bt = uiDefButF(block, NUM, 0, "Y", 0, 1 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, &cmp->y, 0.0f, 1.0f, 1, 5, ""); + bt = uiDefButF(block, NUM, 0, "X", 0, 2 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, + &cmp->x, range[0], range[1], 1, 5, ""); + bt = uiDefButF(block, NUM, 0, "Y", 0, 1 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, + &cmp->y, range[0], range[1], 1, 5, ""); } /* black/white levels */ @@ -1951,29 +2079,48 @@ void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propn MEM_freeN(cb); } -/********************* ColorWheel Template ************************/ +/********************* ColorPicker Template ************************/ #define WHEEL_SIZE 100 -void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic) +/* This template now follows User Preference for type - name is not correct anymore... */ +void uiTemplateColorPicker(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, + int lock, int lock_luminosity, int cubic) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); uiBlock *block = uiLayoutGetBlock(layout); uiLayout *col, *row; - uiBut *but; + uiBut *but = NULL; float softmin, softmax, step, precision; - + if (!prop) { RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); return; } RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision); - - col = uiLayoutColumn(layout, FALSE); + + col = uiLayoutColumn(layout, TRUE); row = uiLayoutRow(col, TRUE); - - but = uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, 0, 0, ""); + + switch (U.color_picker_type) { + case USER_CP_CIRCLE: + but = uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, + -1, 0.0, 0.0, 0, 0, ""); + break; + case USER_CP_SQUARE_SV: + but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, + -1, 0.0, 0.0, UI_GRAD_SV, 0, ""); + break; + case USER_CP_SQUARE_HS: + but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, + -1, 0.0, 0.0, UI_GRAD_HS, 0, ""); + break; + case USER_CP_SQUARE_HV: + but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, + -1, 0.0, 0.0, UI_GRAD_HV, 0, ""); + break; + } if (lock) { but->flag |= UI_BUT_COLOR_LOCK; @@ -1989,10 +2136,31 @@ void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propnam if (cubic) but->flag |= UI_BUT_COLOR_CUBIC; - uiItemS(row); - if (value_slider) - uiDefButR_prop(block, HSVCUBE, 0, "", WHEEL_SIZE + 6, 0, 14, WHEEL_SIZE, ptr, prop, -1, softmin, softmax, UI_GRAD_V_ALT, 0, ""); + if (value_slider) { + switch (U.color_picker_type) { + case USER_CP_CIRCLE: + uiItemS(row); + uiDefButR_prop(block, HSVCUBE, 0, "", WHEEL_SIZE + 6, 0, 14, WHEEL_SIZE, ptr, prop, + -1, softmin, softmax, UI_GRAD_V_ALT, 0, ""); + break; + case USER_CP_SQUARE_SV: + uiItemS(col); + uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop, + -1, softmin, softmax, UI_GRAD_SV + 3, 0, ""); + break; + case USER_CP_SQUARE_HS: + uiItemS(col); + uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop, + -1, softmin, softmax, UI_GRAD_HS + 3, 0, ""); + break; + case USER_CP_SQUARE_HV: + uiItemS(col); + uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop, + -1, softmin, softmax, UI_GRAD_HV + 3, 0, ""); + break; + } + } } /********************* Layer Buttons Template ************************/ @@ -2150,7 +2318,8 @@ void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propnam else if (used_prop && RNA_property_boolean_get_index(used_ptr, used_prop, state)) icon = ICON_LAYER_USED; - but = uiDefIconButR_prop(block, ICONTOG, 0, icon, 0, 0, UI_UNIT_X / 2, UI_UNIT_Y / 2, ptr, prop, state, 0, 0, -1, -1, sca_state_name_get(ob, state)); + but = uiDefIconButR_prop(block, ICONTOG, 0, icon, 0, 0, UI_UNIT_X / 2, UI_UNIT_Y / 2, ptr, prop, + state, 0, 0, -1, -1, sca_state_name_get(ob, state)); uiButSetFunc(but, handle_layer_buttons, but, SET_INT_IN_POINTER(state)); but->type = TOG; } @@ -2198,7 +2367,8 @@ static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon, int return rnaicon; } -static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i, int rnaicon, PointerRNA *activeptr, PropertyRNA *activeprop, const char *prop_list_id) +static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i, + int rnaicon, PointerRNA *activeptr, PropertyRNA *activeprop, const char *prop_list_id) { uiBlock *block = uiLayoutGetBlock(layout); uiBut *but; @@ -2212,7 +2382,8 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe /* list item behind label & other buttons */ sub = uiLayoutRow(overlap, FALSE); - but = uiDefButR_prop(block, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr, activeprop, 0, 0, i, 0, 0, ""); + but = uiDefButR_prop(block, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr, activeprop, + 0, 0, i, 0, 0, ""); uiButSetFlag(but, UI_BUT_NO_TOOLTIP); sub = uiLayoutRow(overlap, FALSE); @@ -2229,7 +2400,8 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe if (itemptr->type == &RNA_MeshTexturePolyLayer || itemptr->type == &RNA_MeshLoopColorLayer) { uiItemL(sub, name, icon); uiBlockSetEmboss(block, UI_EMBOSSN); - uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render", 0, 0, 0, 0, 0, NULL); + uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render", + 0, 0, 0, 0, 0, NULL); uiBlockSetEmboss(block, UI_EMBOSS); } else if (RNA_struct_is_a(itemptr->type, &RNA_MaterialTextureSlot)) { @@ -2322,7 +2494,8 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe uiItemL(sub, name_final, icon); if (dynamicPaint_surfaceHasColorPreview(surface)) { uiBlockSetEmboss(block, UI_EMBOSSN); - uiDefIconButR(block, OPTION, 0, (surface->flags & MOD_DPAINT_PREVIEW) ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON, + uiDefIconButR(block, OPTION, 0, + (surface->flags & MOD_DPAINT_PREVIEW) ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "show_preview", 0, 0, 0, 0, 0, NULL); uiBlockSetEmboss(block, UI_EMBOSS); } @@ -2411,7 +2584,8 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe } } -void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *activeptr, const char *activepropname, const char *prop_list, int rows, int maxrows, int listtype) +void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *activeptr, + const char *activepropname, const char *prop_list, int rows, int maxrows, int listtype) { PropertyRNA *prop = NULL, *activeprop; PropertyType type, activetype; @@ -2487,7 +2661,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char * row = uiLayoutRow(col, FALSE); icon = list_item_icon_get(C, &itemptr, rnaicon, 1); - but = uiDefIconButR_prop(block, LISTROW, 0, icon, 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr, activeprop, 0, 0, i, 0, 0, ""); + but = uiDefIconButR_prop(block, LISTROW, 0, icon, 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr, + activeprop, 0, 0, i, 0, 0, ""); uiButSetFlag(but, UI_BUT_NO_TOOLTIP); @@ -2529,7 +2704,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char * /* next/prev button */ BLI_snprintf(numstr, sizeof(numstr), "%d :", i); - but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, activeptr, activeprop, 0, 0, 0, 0, 0, ""); + but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, activeptr, + activeprop, 0, 0, 0, 0, 0, ""); if (i == 0) uiButSetFlag(but, UI_BUT_DISABLED); } @@ -2586,7 +2762,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char * /* add scrollbar */ if (len > items) { col = uiLayoutColumn(row, FALSE); - uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &pa->list_scroll, 0, len - items, items, 0, ""); + uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &pa->list_scroll, + 0, len - items, items, 0, ""); } } } @@ -2608,6 +2785,9 @@ static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) { wmOperatorType *ot = BLI_ghashIterator_getValue(iter); + if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0) + continue; + if (BLI_strcasestr(ot->name, str)) { if (WM_operator_poll((bContext *)C, ot)) { char name[256]; @@ -2633,6 +2813,11 @@ static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char BLI_ghashIterator_free(iter); } +void uiOperatorSearch_But(uiBut *but) +{ + uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL); +} + void uiTemplateOperatorSearch(uiLayout *layout) { uiBlock *block; @@ -2643,7 +2828,7 @@ void uiTemplateOperatorSearch(uiLayout *layout) uiBlockSetCurLayout(block, layout); but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, 0, ""); - uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL); + uiOperatorSearch_But(but); } /************************* Running Jobs Template **************************/ @@ -2733,19 +2918,19 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C) ui_abs = uiLayoutAbsolute(layout, FALSE); (void)ui_abs; /* UNUSED */ - uiDefIconBut(block, BUT, handle_event, ICON_PANEL_CLOSE, - 0, UI_UNIT_Y * 0.1, UI_UNIT_X * 0.8, UI_UNIT_Y * 0.8, NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop this job")); + uiDefIconBut(block, BUT, handle_event, ICON_PANEL_CLOSE, 0, UI_UNIT_Y * 0.1, UI_UNIT_X * 0.8, UI_UNIT_Y * 0.8, + NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop this job")); uiDefBut(block, PROGRESSBAR, 0, WM_jobs_name(wm, owner), UI_UNIT_X, 0, 100, UI_UNIT_Y, NULL, 0.0f, 0.0f, WM_jobs_progress(wm, owner), 0, TIP_("Progress")); uiLayoutRow(layout, FALSE); } if (WM_jobs_test(wm, screen, WM_JOB_TYPE_SCREENCAST)) - uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_CANCEL, IFACE_("Capture"), 0, 0, 85, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, - TIP_("Stop screencast")); + uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_CANCEL, IFACE_("Capture"), 0, 0, 85, UI_UNIT_Y, + NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop screencast")); if (screen->animtimer) - uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_CANCEL, IFACE_("Anim Player"), 0, 0, 100, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, - TIP_("Stop animation playback")); + uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_CANCEL, IFACE_("Anim Player"), 0, 0, 100, UI_UNIT_Y, + NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop animation playback")); } /************************* Reports for Last Operator Template **************************/ @@ -2784,7 +2969,8 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) rgb_float_to_uchar(but->col, rti->col); but->col[3] = 255; - but = uiDefBut(block, ROUNDBOX, 0, "", UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); + but = uiDefBut(block, ROUNDBOX, 0, "", UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y, + NULL, 0.0f, 0.0f, 0, 0, ""); but->col[0] = but->col[1] = but->col[2] = FTOCHAR(rti->grayscale); but->col[3] = 255; @@ -2805,14 +2991,15 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) uiBlockSetEmboss(block, UI_EMBOSSN); if (reports->list.first != reports->list.last) - uiDefIconButO(block, BUT, "UI_OT_reports_to_textblock", WM_OP_INVOKE_REGION_WIN, icon, 2, 0, - UI_UNIT_X, UI_UNIT_Y, TIP_("Click to see the remaining reports in text block: 'Recent Reports'")); + uiDefIconButO(block, BUT, "UI_OT_reports_to_textblock", WM_OP_INVOKE_REGION_WIN, icon, 2, 0, UI_UNIT_X, + UI_UNIT_Y, TIP_("Click to see the remaining reports in text block: 'Recent Reports'")); else uiDefIconBut(block, LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); uiBlockSetEmboss(block, UI_EMBOSS); - uiDefBut(block, LABEL, 0, report->message, UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); + uiDefBut(block, LABEL, 0, report->message, UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y, + NULL, 0.0f, 0.0f, 0, 0, ""); } /********************************* Keymap *************************************/ diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index f41abce947e..c4b80f0a42f 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -651,8 +651,8 @@ static void widget_verts_to_quad_strip_open(uiWidgetBase *wtb, const int totvert for (a = 0; a < totvert; a++) { quad_strip[a * 2][0] = wtb->outer_v[a][0]; quad_strip[a * 2][1] = wtb->outer_v[a][1]; - quad_strip[a * 2 + 1][0] = wtb->outer_v[a][0]; - quad_strip[a * 2 + 1][1] = wtb->outer_v[a][1] - 1.0f; + quad_strip[a * 2 + 1][0] = wtb->inner_v[a][0]; + quad_strip[a * 2 + 1][1] = wtb->inner_v[a][1]; } } @@ -1044,6 +1044,8 @@ static void ui_text_clip_cursor(uiFontStyle *fstyle, uiBut *but, rcti *rect) ui_text_clip_give_prev_off(but); len = strlen(but->drawstr); bytes = BLI_str_utf8_size(BLI_str_find_prev_char_utf8(but->drawstr, but->drawstr + len)); + if (bytes < 0) + bytes = 1; but->drawstr[len - bytes] = 0; } @@ -2057,7 +2059,7 @@ void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const floa /* old below */ - for (dx = 0.0f; dx < 1.0f; dx += color_step) { + for (dx = 0.0f; dx < 0.999f; dx += color_step) { /* 0.999 = prevent float inaccuracy for steps */ /* previous color */ copy_v3_v3(col0[0], col1[0]); copy_v3_v3(col0[1], col1[1]); @@ -2112,7 +2114,7 @@ void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const floa sx1 = rect->xmin + dx * BLI_rcti_size_x(rect); sx2 = rect->xmin + (dx + color_step) * BLI_rcti_size_x(rect); sy = rect->ymin; - dy = BLI_rcti_size_y(rect) / 3.0; + dy = (float)BLI_rcti_size_y(rect) / 3.0f; glBegin(GL_QUADS); for (a = 0; a < 3; a++, sy += dy) { @@ -2621,6 +2623,11 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat } +static void widget_normal(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign)) +{ + ui_draw_but_NORMAL(but, wcol, rect); +} + static void widget_icon_has_anim(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign)) { if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) { @@ -3028,6 +3035,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type) break; case UI_WTYPE_NORMAL: + wt.custom = widget_normal; break; case UI_WTYPE_SCROLL: @@ -3267,7 +3275,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct break; case BUT_NORMAL: - ui_draw_but_NORMAL(but, &tui->wcol_regular, rect); + wt = widget_type(UI_WTYPE_NORMAL); break; case BUT_IMAGE: diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index e03a2887866..fa5d5806bb8 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -236,7 +236,7 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo cp = ts->shade2; break; case TH_HILITE: cp = ts->hilite; break; - + case TH_GRID: cp = ts->grid; break; case TH_WIRE: @@ -510,6 +510,13 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo case TH_NLA_SOUND_SEL: cp = ts->nla_sound_sel; break; + + case TH_AXIS_X: + cp = btheme->tui.xaxis; break; + case TH_AXIS_Y: + cp = btheme->tui.yaxis; break; + case TH_AXIS_Z: + cp = btheme->tui.zaxis; break; } } } @@ -655,9 +662,14 @@ void ui_theme_init_default(void) /* UI buttons */ ui_widget_color_init(&btheme->tui); + btheme->tui.iconfile[0] = 0; btheme->tui.panel.show_header = FALSE; rgba_char_args_set(btheme->tui.panel.header, 0, 0, 0, 25); + + rgba_char_args_set(btheme->tui.xaxis, 220, 0, 0, 255); + rgba_char_args_set(btheme->tui.yaxis, 0, 220, 0, 255); + rgba_char_args_set(btheme->tui.zaxis, 0, 0, 220, 255); /* Bone Color Sets */ ui_theme_init_boneColorSets(btheme); @@ -1072,7 +1084,6 @@ float UI_GetThemeValuef(int colorid) cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); return ((float)cp[0]); - } /* get individual values, not scaled */ @@ -1082,7 +1093,6 @@ int UI_GetThemeValue(int colorid) cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); return ((int) cp[0]); - } @@ -1244,21 +1254,20 @@ void UI_ThemeClearColor(int colorid) void UI_make_axis_color(const unsigned char src_col[3], unsigned char dst_col[3], const char axis) { + unsigned char col[3]; + switch (axis) { case 'X': - dst_col[0] = src_col[0] > 219 ? 255 : src_col[0] + 36; - dst_col[1] = src_col[1] < 26 ? 0 : src_col[1] - 26; - dst_col[2] = src_col[2] < 26 ? 0 : src_col[2] - 26; + UI_GetThemeColor3ubv(TH_AXIS_X, col); + UI_GetColorPtrBlendShade3ubv(src_col, col, dst_col, 0.5f, -10); break; case 'Y': - dst_col[0] = src_col[0] < 46 ? 0 : src_col[0] - 36; - dst_col[1] = src_col[1] > 189 ? 255 : src_col[1] + 66; - dst_col[2] = src_col[2] < 46 ? 0 : src_col[2] - 36; + UI_GetThemeColor3ubv(TH_AXIS_Y, col); + UI_GetColorPtrBlendShade3ubv(src_col, col, dst_col, 0.5f, -10); break; case 'Z': - dst_col[0] = src_col[0] < 26 ? 0 : src_col[0] - 26; - dst_col[1] = src_col[1] < 26 ? 0 : src_col[1] - 26; - dst_col[2] = src_col[2] > 209 ? 255 : src_col[2] + 46; + UI_GetThemeColor3ubv(TH_AXIS_Z, col); + UI_GetColorPtrBlendShade3ubv(src_col, col, dst_col, 0.5f, -10); break; default: BLI_assert(!"invalid axis arg"); @@ -1946,6 +1955,16 @@ void init_userdef_do_versions(void) rgba_char_args_set(btheme->tv3d.skin_root, 180, 77, 77, 255); } } + + if (bmain->versionfile < 264 || (bmain->versionfile == 264 && bmain->subversionfile < 9)) { + bTheme *btheme; + + for (btheme = U.themes.first; btheme; btheme = btheme->next) { + rgba_char_args_set(btheme->tui.xaxis, 220, 0, 0, 255); + rgba_char_args_set(btheme->tui.yaxis, 0, 220, 0, 255); + rgba_char_args_set(btheme->tui.zaxis, 0, 0, 220, 255); + } + } /* GL Texture Garbage Collection (variable abused above!) */ if (U.textimeout == 0) { diff --git a/source/blender/editors/mask/mask_editaction.c b/source/blender/editors/mask/mask_editaction.c index 561ad004a1d..707622fa841 100644 --- a/source/blender/editors/mask/mask_editaction.c +++ b/source/blender/editors/mask/mask_editaction.c @@ -18,13 +18,13 @@ * The Original Code is Copyright (C) 2008, Blender Foundation * This is a new part of Blender * - * Contributor(s): Joshua Leung + * Contributor(s): Campbell Barton * * ***** END GPL LICENSE BLOCK ***** */ /** \file blender/editors/mask/mask_editaction.c - * \ingroup edgpencil + * \ingroup edmask */ #include @@ -49,17 +49,18 @@ #include "ED_anim_api.h" #include "ED_keyframes_edit.h" #include "ED_mask.h" /* own include */ +#include "ED_markers.h" /* ***************************************** */ /* NOTE ABOUT THIS FILE: - * This file contains code for editing Grease Pencil data in the Action Editor - * as a 'keyframes', so that a user can adjust the timing of Grease Pencil drawings. - * Therefore, this file mostly contains functions for selecting Grease-Pencil frames. + * This file contains code for editing Mask data in the Action Editor + * as a 'keyframes', so that a user can adjust the timing of Mask shapekeys. + * Therefore, this file mostly contains functions for selecting Mask frames (shapekeys). */ /* ***************************************** */ /* Generics - Loopers */ -/* Loops over the gp-frames for a gp-layer, and applies the given callback */ +/* Loops over the mask-frames for a mask-layer, and applies the given callback */ short ED_masklayer_frames_looper(MaskLayer *masklay, Scene *scene, short (*masklay_shape_cb)(MaskLayerShape *, Scene *)) { MaskLayerShape *masklay_shape; @@ -82,7 +83,7 @@ short ED_masklayer_frames_looper(MaskLayer *masklay, Scene *scene, short (*maskl /* ****************************************** */ /* Data Conversion Tools */ -/* make a listing all the gp-frames in a layer as cfraelems */ +/* make a listing all the mask-frames in a layer as cfraelems */ void ED_masklayer_make_cfra_list(MaskLayer *masklay, ListBase *elems, short onlysel) { MaskLayerShape *masklay_shape; @@ -92,7 +93,7 @@ void ED_masklayer_make_cfra_list(MaskLayer *masklay, ListBase *elems, short only if (ELEM(NULL, masklay, elems)) return; - /* loop through gp-frames, adding */ + /* loop through mask-frames, adding */ for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { if ((onlysel == 0) || (masklay_shape->flag & MASK_SHAPE_SELECT)) { ce = MEM_callocN(sizeof(CfraElem), "CfraElem"); @@ -127,7 +128,7 @@ short ED_masklayer_frame_select_check(MaskLayer *masklay) return 0; } -/* helper function - select gp-frame based on SELECT_* mode */ +/* helper function - select mask-frame based on SELECT_* mode */ static void masklayshape_select(MaskLayerShape *masklay_shape, short select_mode) { if (masklay_shape == NULL) @@ -223,7 +224,7 @@ void ED_masklayer_frames_delete(MaskLayer *masklay) } } -/* Duplicate selected frames from given gp-layer */ +/* Duplicate selected frames from given mask-layer */ void ED_masklayer_frames_duplicate(MaskLayer *masklay) { MaskLayerShape *masklay_shape, *gpfn; @@ -249,3 +250,57 @@ void ED_masklayer_frames_duplicate(MaskLayer *masklay) } } } + +/* -------------------------------------- */ +/* Snap Tools */ + +static short snap_masklayer_nearest(MaskLayerShape *masklay_shape, Scene *UNUSED(scene)) +{ + if (masklay_shape->flag & MASK_SHAPE_SELECT) + masklay_shape->frame = (int)(floor(masklay_shape->frame + 0.5)); + return 0; +} + +static short snap_masklayer_nearestsec(MaskLayerShape *masklay_shape, Scene *scene) +{ + float secf = (float)FPS; + if (masklay_shape->flag & MASK_SHAPE_SELECT) + masklay_shape->frame = (int)(floorf(masklay_shape->frame / secf + 0.5f) * secf); + return 0; +} + +static short snap_masklayer_cframe(MaskLayerShape *masklay_shape, Scene *scene) +{ + if (masklay_shape->flag & MASK_SHAPE_SELECT) + masklay_shape->frame = (int)CFRA; + return 0; +} + +static short snap_masklayer_nearmarker(MaskLayerShape *masklay_shape, Scene *scene) +{ + if (masklay_shape->flag & MASK_SHAPE_SELECT) + masklay_shape->frame = (int)ED_markers_find_nearest_marker_time(&scene->markers, (float)masklay_shape->frame); + return 0; +} + +/* snap selected frames to ... */ +void ED_masklayer_snap_frames(MaskLayer *masklay, Scene *scene, short mode) +{ + switch (mode) { + case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */ + ED_masklayer_frames_looper(masklay, scene, snap_masklayer_nearest); + break; + case SNAP_KEYS_CURFRAME: /* snap to current frame */ + ED_masklayer_frames_looper(masklay, scene, snap_masklayer_cframe); + break; + case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */ + ED_masklayer_frames_looper(masklay, scene, snap_masklayer_nearmarker); + break; + case SNAP_KEYS_NEARSEC: /* snap to nearest second */ + ED_masklayer_frames_looper(masklay, scene, snap_masklayer_nearestsec); + break; + default: /* just in case */ + break; + } +} + diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index 70b359d3e28..4a425c83d86 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -55,6 +55,8 @@ /* ********* add primitive operators ************* */ +/* BMESH_TODO: 'state' is not a good name, should be flipped and called 'was_editmode', + * or at least something more descriptive */ static Object *make_prim_init(bContext *C, const char *idname, float *dia, float mat[][4], int *state, const float loc[3], const float rot[3], const unsigned int layer) @@ -81,15 +83,17 @@ static Object *make_prim_init(bContext *C, const char *idname, static void make_prim_finish(bContext *C, Object *obedit, int *state, int enter_editmode) { BMEditMesh *em = BMEdit_FromObject(obedit); + const int exit_editmode = (*state && !enter_editmode); /* Primitive has all verts selected, use vert select flush * to push this up to edges & faces. */ EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX); - EDBM_update_generic(C, em, TRUE); + /* only recalc editmode tessface if we are staying in editmode */ + EDBM_update_generic(C, em, !exit_editmode); /* userdef */ - if (*state && !enter_editmode) { + if (exit_editmode) { ED_object_exit_editmode(C, EM_FREEDATA); /* adding EM_DO_UNDO messes up operator redo */ } WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); @@ -108,8 +112,8 @@ static int add_primitive_plane_exec(bContext *C, wmOperator *op) obedit = make_prim_init(C, "Plane", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "vertout", - "create_grid xsegments=%i ysegments=%i size=%f mat=%m4", 1, 1, dia, mat)) + if (!EDBM_op_call_and_selectf(em, op, "verts.out", + "create_grid x_segments=%i y_segments=%i size=%f matrix=%m4", 1, 1, dia, mat)) { return OPERATOR_CANCELLED; } @@ -149,7 +153,7 @@ static int add_primitive_cube_exec(bContext *C, wmOperator *op) obedit = make_prim_init(C, "Cube", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "vertout", "create_cube mat=%m4 size=%f", mat, dia * 2.0f)) { + if (!EDBM_op_call_and_selectf(em, op, "verts.out", "create_cube matrix=%m4 size=%f", mat, dia * 2.0f)) { return OPERATOR_CANCELLED; } @@ -198,9 +202,9 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op) obedit = make_prim_init(C, "Circle", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "vertout", - "create_circle segments=%i diameter=%f cap_ends=%b cap_tris=%b mat=%m4", - RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius") * dia, + if (!EDBM_op_call_and_selectf(em, op, "verts.out", + "create_circle segments=%i diameter=%f cap_ends=%b cap_tris=%b matrix=%m4", + RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius"), cap_end, cap_tri, mat)) { return OPERATOR_CANCELLED; @@ -221,6 +225,7 @@ void MESH_OT_primitive_circle_add(wmOperatorType *ot) ot->idname = "MESH_OT_primitive_circle_add"; /* api callbacks */ + ot->invoke = WM_operator_view3d_distance_invoke; ot->exec = add_primitive_circle_exec; ot->poll = ED_operator_scene_editable; @@ -253,13 +258,13 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op) em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf( - em, op, "vertout", - "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f mat=%m4", + em, op, "verts.out", + "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f matrix=%m4", RNA_int_get(op->ptr, "vertices"), - RNA_float_get(op->ptr, "radius") * dia, - RNA_float_get(op->ptr, "radius") * dia, + RNA_float_get(op->ptr, "radius"), + RNA_float_get(op->ptr, "radius"), cap_end, cap_tri, - RNA_float_get(op->ptr, "depth") * dia, mat)) + RNA_float_get(op->ptr, "depth"), mat)) { return OPERATOR_CANCELLED; } @@ -279,6 +284,7 @@ void MESH_OT_primitive_cylinder_add(wmOperatorType *ot) ot->idname = "MESH_OT_primitive_cylinder_add"; /* api callbacks */ + ot->invoke = WM_operator_view3d_distance_invoke; ot->exec = add_primitive_cylinder_exec; ot->poll = ED_operator_scene_editable; @@ -313,10 +319,10 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op) em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf( - em, op, "vertout", - "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f mat=%m4", - RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius1") * dia, - RNA_float_get(op->ptr, "radius2") * dia, cap_end, cap_tri, RNA_float_get(op->ptr, "depth") * dia, mat)) + em, op, "verts.out", + "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f matrix=%m4", + RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius1"), + RNA_float_get(op->ptr, "radius2"), cap_end, cap_tri, RNA_float_get(op->ptr, "depth"), mat)) { return OPERATOR_CANCELLED; } @@ -336,6 +342,7 @@ void MESH_OT_primitive_cone_add(wmOperatorType *ot) ot->idname = "MESH_OT_primitive_cone_add"; /* api callbacks */ + ot->invoke = WM_operator_view3d_distance_invoke; ot->exec = add_primitive_cone_exec; ot->poll = ED_operator_scene_editable; @@ -368,11 +375,11 @@ static int add_primitive_grid_exec(bContext *C, wmOperator *op) obedit = make_prim_init(C, "Grid", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "vertout", - "create_grid xsegments=%i ysegments=%i size=%f mat=%m4", + if (!EDBM_op_call_and_selectf(em, op, "verts.out", + "create_grid x_segments=%i y_segments=%i size=%f matrix=%m4", RNA_int_get(op->ptr, "x_subdivisions"), RNA_int_get(op->ptr, "y_subdivisions"), - RNA_float_get(op->ptr, "size") * dia, mat)) + RNA_float_get(op->ptr, "size"), mat)) { return OPERATOR_CANCELLED; } @@ -392,6 +399,7 @@ void MESH_OT_primitive_grid_add(wmOperatorType *ot) ot->idname = "MESH_OT_primitive_grid_add"; /* api callbacks */ + ot->invoke = WM_operator_view3d_distance_invoke; ot->exec = add_primitive_grid_exec; ot->poll = ED_operator_scene_editable; @@ -420,14 +428,14 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op) if (!view_aligned) rot[0] += (float)M_PI / 2.0f; - obedit = make_prim_init(C, "Monkey", &dia, mat, &state, loc, rot, layer); + obedit = make_prim_init(C, "Suzanne", &dia, mat, &state, loc, rot, layer); mat[0][0] *= dia; mat[1][1] *= dia; mat[2][2] *= dia; em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "vertout", "create_monkey mat=%m4", mat)) { + if (!EDBM_op_call_and_selectf(em, op, "verts.out", "create_monkey matrix=%m4", mat)) { return OPERATOR_CANCELLED; } @@ -466,10 +474,10 @@ static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op) obedit = make_prim_init(C, "Sphere", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "vertout", - "create_uvsphere segments=%i revolutions=%i diameter=%f mat=%m4", + if (!EDBM_op_call_and_selectf(em, op, "verts.out", + "create_uvsphere u_segments=%i v_segments=%i diameter=%f matrix=%m4", RNA_int_get(op->ptr, "segments"), RNA_int_get(op->ptr, "ring_count"), - RNA_float_get(op->ptr, "size") * dia, mat)) + RNA_float_get(op->ptr, "size"), mat)) { return OPERATOR_CANCELLED; } @@ -489,6 +497,7 @@ void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot) ot->idname = "MESH_OT_primitive_uv_sphere_add"; /* api callbacks */ + ot->invoke = WM_operator_view3d_distance_invoke; ot->exec = add_primitive_uvsphere_exec; ot->poll = ED_operator_scene_editable; @@ -518,10 +527,10 @@ static int add_primitive_icosphere_exec(bContext *C, wmOperator *op) em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf( - em, op, "vertout", - "create_icosphere subdivisions=%i diameter=%f mat=%m4", + em, op, "verts.out", + "create_icosphere subdivisions=%i diameter=%f matrix=%m4", RNA_int_get(op->ptr, "subdivisions"), - RNA_float_get(op->ptr, "size") * dia, mat)) + RNA_float_get(op->ptr, "size"), mat)) { return OPERATOR_CANCELLED; } @@ -541,6 +550,7 @@ void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot) ot->idname = "MESH_OT_primitive_ico_sphere_add"; /* api callbacks */ + ot->invoke = WM_operator_view3d_distance_invoke; ot->exec = add_primitive_icosphere_exec; ot->poll = ED_operator_scene_editable; diff --git a/source/blender/editors/mesh/editmesh_bvh.c b/source/blender/editors/mesh/editmesh_bvh.c index 468d0d8d8c6..8e397797dd9 100644 --- a/source/blender/editors/mesh/editmesh_bvh.c +++ b/source/blender/editors/mesh/editmesh_bvh.c @@ -157,13 +157,13 @@ BMBVHTree *BMBVH_NewBVH(BMEditMesh *em, int flag, Scene *scene, Object *obedit) if (flag & BMBVH_RESPECT_SELECT) { - /* note, the arrays wont allign now! take care */ + /* note, the arrays wont align now! take care */ if (!BM_elem_flag_test(em->looptris[i][0]->f, BM_ELEM_SELECT)) { continue; } } else if (flag & BMBVH_RESPECT_HIDDEN) { - /* note, the arrays wont allign now! take care */ + /* note, the arrays wont align now! take care */ if (BM_elem_flag_test(em->looptris[i][0]->f, BM_ELEM_HIDDEN)) { continue; } @@ -399,7 +399,7 @@ int BMBVH_EdgeVisible(BMBVHTree *tree, BMEdge *e, ARegion *ar, View3D *v3d, Obje const float mval_f[2] = {ar->winx / 2.0f, ar->winy / 2.0f}; - ED_view3d_win_to_segment_clip(ar, v3d, mval_f, origin, end); + ED_view3d_win_to_segment(ar, v3d, mval_f, origin, end); invert_m4_m4(invmat, obedit->obmat); mul_m4_v3(invmat, origin); diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 82447cc0168..a59c491fe13 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -207,8 +207,12 @@ typedef struct KnifeTool_OpData { static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd, BMFace *f); +#if 0 static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2], float r_origin[3], float r_ray[3]); +#endif +static void knife_input_ray_segment(KnifeTool_OpData *kcd, const int mval_i[2], const float ofs, + float r_origin[3], float r_dest[3]); static void knife_update_header(bContext *C, KnifeTool_OpData *kcd) { @@ -379,14 +383,13 @@ static void knife_start_cut(KnifeTool_OpData *kcd) if (kcd->prev.vert == NULL && kcd->prev.edge == NULL && is_zero_v3(kcd->prev.cage)) { /* Make prevcage a point on the view ray to mouse closest to a point on model: choose vertex 0 */ - float origin[3], ray[3], co[3]; + float origin[3], origin_ofs[3]; BMVert *v0; - knife_input_ray_cast(kcd, kcd->curr.mval, origin, ray); - add_v3_v3v3(co, origin, ray); + knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs); v0 = BM_vert_at_index(kcd->em->bm, 0); if (v0) { - closest_to_line_v3(kcd->prev.cage, v0->co, co, origin); + closest_to_line_v3(kcd->prev.cage, v0->co, origin_ofs, origin); copy_v3_v3(kcd->prev.co, kcd->prev.cage); /*TODO: do we need this? */ copy_v3_v3(kcd->curr.cage, kcd->prev.cage); copy_v3_v3(kcd->curr.co, kcd->prev.co); @@ -1178,7 +1181,6 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, result = results = BLI_bvhtree_overlap(tree, tree2, &tot); for (i = 0; i < tot; i++, result++) { - float p[3]; BMLoop *l1; BMFace *hitf; ListBase *lst; @@ -1197,7 +1199,7 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, } if (isect_line_tri_v3(kfe->v1->cageco, kfe->v2->cageco, v1, v2, v3, &lambda, NULL)) { - float no[3], view[3], sp[3]; + float p[3], no[3], view[3], sp[3]; interp_v3_v3v3(p, kfe->v1->cageco, kfe->v2->cageco, lambda); @@ -1212,6 +1214,11 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, { continue; } + if ((kcd->vc.rv3d->rflag & RV3D_CLIPPING) && + ED_view3d_clipping_test(kcd->vc.rv3d, p, TRUE)) + { + continue; + } knife_project_v3(kcd, p, sp); ED_view3d_unproject(mats, view, sp[0], sp[1], 0.0f); @@ -1403,6 +1410,8 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) BLI_smallhash_release(ehash); } +/* this works but gives numeric problems [#33400] */ +#if 0 static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2], float r_origin[3], float r_ray[3]) { @@ -1433,17 +1442,41 @@ static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2], mul_m4_v3(kcd->ob->imat, r_origin); mul_m3_v3(imat, r_ray); } +#endif + +static void knife_input_ray_segment(KnifeTool_OpData *kcd, const int mval_i[2], const float ofs, + float r_origin[3], float r_origin_ofs[3]) +{ + bglMats mats; + float mval[2]; + + knife_bgl_get_mats(kcd, &mats); + + mval[0] = (float)mval_i[0]; + mval[1] = (float)mval_i[1]; + + /* unproject to find view ray */ + ED_view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f); + ED_view3d_unproject(&mats, r_origin_ofs, mval[0], mval[1], ofs); + + /* transform into object space */ + invert_m4_m4(kcd->ob->imat, kcd->ob->obmat); + + mul_m4_v3(kcd->ob->imat, r_origin); + mul_m4_v3(kcd->ob->imat, r_origin_ofs); +} static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float cageco[3], int *is_space) { BMFace *f; float dist = KMAXDIST; float origin[3]; + float origin_ofs[3]; float ray[3]; /* unproject to find view ray */ - knife_input_ray_cast(kcd, kcd->vc.mval, origin, ray); - add_v3_v3v3(co, origin, ray); + knife_input_ray_segment(kcd, kcd->vc.mval, 1.0f, origin, origin_ofs); + sub_v3_v3v3(ray, origin_ofs, origin); f = BMBVH_RayCast(kcd->bmbvh, origin, ray, co, cageco); @@ -1494,12 +1527,7 @@ static int knife_sample_screen_density(KnifeTool_OpData *kcd, float radius) dis = len_v2v2(kfv->sco, sco); if (dis < radius) { if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) { - float vec[3]; - - copy_v3_v3(vec, kfv->cageco); - mul_m4_v3(kcd->vc.obedit->obmat, vec); - - if (ED_view3d_clipping_test(kcd->vc.rv3d, vec, TRUE) == 0) { + if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, TRUE) == 0) { c++; } } @@ -1566,13 +1594,10 @@ static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], flo dis = dist_to_line_segment_v2(sco, kfe->v1->sco, kfe->v2->sco); if (dis < curdis && dis < maxdist) { if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) { - float labda = labda_PdistVL2Dfl(sco, kfe->v1->sco, kfe->v2->sco); + float labda = line_point_factor_v2(sco, kfe->v1->sco, kfe->v2->sco); float vec[3]; - vec[0] = kfe->v1->cageco[0] + labda * (kfe->v2->cageco[0] - kfe->v1->cageco[0]); - vec[1] = kfe->v1->cageco[1] + labda * (kfe->v2->cageco[1] - kfe->v1->cageco[1]); - vec[2] = kfe->v1->cageco[2] + labda * (kfe->v2->cageco[2] - kfe->v1->cageco[2]); - mul_m4_v3(kcd->vc.obedit->obmat, vec); + interp_v3_v3v3(vec, kfe->v1->cageco, kfe->v2->cageco, labda); if (ED_view3d_clipping_test(kcd->vc.rv3d, vec, TRUE) == 0) { cure = kfe; @@ -1664,12 +1689,7 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo dis = len_v2v2(kfv->sco, sco); if (dis < curdis && dis < maxdist) { if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) { - float vec[3]; - - copy_v3_v3(vec, kfv->cageco); - mul_m4_v3(kcd->vc.obedit->obmat, vec); - - if (ED_view3d_clipping_test(kcd->vc.rv3d, vec, TRUE) == 0) { + if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, TRUE) == 0) { curv = kfv; curdis = dis; } @@ -1768,12 +1788,12 @@ static int knife_update_active(KnifeTool_OpData *kcd) * Note that drawing lines in `free-space` isn't properly supported * but theres no guarantee (0, 0, 0) has any geometry either - campbell */ if (kcd->curr.vert == NULL && kcd->curr.edge == NULL) { - float origin[3], ray[3], co[3]; + float origin[3]; + float origin_ofs[3]; - knife_input_ray_cast(kcd, kcd->vc.mval, origin, ray); - add_v3_v3v3(co, origin, ray); + knife_input_ray_segment(kcd, kcd->vc.mval, 1.0f, origin, origin_ofs); - closest_to_line_v3(kcd->curr.cage, kcd->prev.cage, co, origin); + closest_to_line_v3(kcd->curr.cage, kcd->prev.cage, origin_ofs, origin); } if (kcd->mode == MODE_DRAGGING) { @@ -1823,7 +1843,7 @@ static void remerge_faces(KnifeTool_OpData *kcd) BMO_op_initf(bm, &bmop, "beautify_fill faces=%ff constrain_edges=%fe", FACE_NEW, BOUNDARY); BMO_op_exec(bm, &bmop); - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_FACE, FACE_NEW); + BMO_slot_buffer_flag_enable(bm, &bmop, "geom.out", BM_FACE, FACE_NEW); BMO_op_finish(bm, &bmop); @@ -1965,7 +1985,7 @@ static void knifenet_fill_faces(KnifeTool_OpData *kcd) kfe->e = NULL; } - kfe->e = BM_edge_create(bm, kfe->v1->v, kfe->v2->v, NULL, TRUE); + kfe->e = BM_edge_create(bm, kfe->v1->v, kfe->v2->v, NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, kfe->e, BOUNDARY); for (ref = kfe->faces.first; ref; ref = ref->next) { @@ -2067,7 +2087,7 @@ static void knifenet_fill_faces(KnifeTool_OpData *kcd) } } - BLI_scanfill_calc(&sf_ctx, FALSE); + BLI_scanfill_calc(&sf_ctx, 0); for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { BMVert *v1 = sf_tri->v3->tmp.p, *v2 = sf_tri->v2->tmp.p, *v3 = sf_tri->v1->tmp.p; @@ -2573,8 +2593,8 @@ static void knife_make_chain_cut(KnifeTool_OpData *kcd, BMFace *f, ListBase *cha int nco = BLI_countlist(chain) - 1; float (*cos)[3] = NULL; KnifeVert **kverts; - BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, nco, __func__); - BLI_array_fixedstack_declare(kverts, BM_NGON_STACK_SIZE, nco, __func__); + BLI_array_fixedstack_declare(cos, BM_DEFAULT_NGON_STACK_SIZE, nco, __func__); + BLI_array_fixedstack_declare(kverts, BM_DEFAULT_NGON_STACK_SIZE, nco, __func__); kfe = ((Ref *)chain->first)->ref; v1 = kfe->v1->v ? kfe->v1->v : kfe->v2->v; @@ -3085,6 +3105,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) { Object *obedit = CTX_data_edit_object(C); KnifeTool_OpData *kcd = op->customdata; + int do_refresh = FALSE; if (!obedit || obedit->type != OB_MESH || BMEdit_FromObject(obedit) != kcd->em) { knifetool_exit(C, op); @@ -3093,6 +3114,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) } view3d_operator_needs_opengl(C); + ED_view3d_init_mats_rv3d(obedit, kcd->vc.rv3d); /* needed to initialize clipping */ if (kcd->mode == MODE_PANNING) kcd->mode = kcd->prevmode; @@ -3124,6 +3146,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) knife_update_active(kcd); knife_update_header(C, kcd); ED_region_tag_redraw(kcd->ar); + do_refresh = TRUE; break; case KNF_MODAL_MIDPOINT_OFF: kcd->snap_midpoints = 0; @@ -3132,25 +3155,29 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) knife_update_active(kcd); knife_update_header(C, kcd); ED_region_tag_redraw(kcd->ar); + do_refresh = TRUE; break; case KNF_MODEL_IGNORE_SNAP_ON: ED_region_tag_redraw(kcd->ar); kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = 1; knife_update_header(C, kcd); + do_refresh = TRUE; break; case KNF_MODEL_IGNORE_SNAP_OFF: ED_region_tag_redraw(kcd->ar); kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = 0; knife_update_header(C, kcd); + do_refresh = TRUE; break; case KNF_MODAL_ANGLE_SNAP_TOGGLE: kcd->angle_snapping = !kcd->angle_snapping; knife_update_header(C, kcd); + do_refresh = TRUE; break; case KNF_MODAL_CUT_THROUGH_TOGGLE: kcd->cut_through = !kcd->cut_through; - knifetool_update_mval(kcd, event->mval); /* refresh knife path */ knife_update_header(C, kcd); + do_refresh = TRUE; break; case KNF_MODAL_NEW_CUT: ED_region_tag_redraw(kcd->ar); @@ -3203,6 +3230,12 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) } } + if (do_refresh) { + /* we don't really need to update mval, + * but this happens to be the best way to refresh at the moment */ + knifetool_update_mval(kcd, event->mval); + } + /* keep going until the user confirms */ return OPERATOR_RUNNING_MODAL; } diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 8e5c89adfca..dec45b7f326 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -261,7 +261,11 @@ static void edgering_sel(RingSelOpData *lcd, int previewlines, int select) lasteed = eed; } - if (lasteed != startedge && BM_edge_share_face_count(lasteed, startedge)) { +#ifdef BMW_EDGERING_NGON + if (lasteed != startedge && BM_edge_share_face_check(lasteed, startedge)) { +#else + if (lasteed != startedge && BM_edge_share_quad_check(lasteed, startedge)) { +#endif v[1][0] = v[0][0]; v[1][1] = v[0][1]; @@ -307,7 +311,13 @@ static void ringsel_find_edge(RingSelOpData *lcd, int cuts) static void ringsel_finish(bContext *C, wmOperator *op) { RingSelOpData *lcd = op->customdata; - int cuts = RNA_int_get(op->ptr, "number_cuts"); + const int cuts = RNA_int_get(op->ptr, "number_cuts"); + const float smoothness = 0.292f * RNA_float_get(op->ptr, "smoothness"); +#ifdef BMW_EDGERING_NGON + const int use_only_quads = FALSE; +#else + const int use_only_quads = TRUE; +#endif if (lcd->eed) { BMEditMesh *em = lcd->em; @@ -319,9 +329,10 @@ static void ringsel_finish(bContext *C, wmOperator *op) * Note though that it will break edgeslide in this specific case. * See [#31939]. */ BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT, - 0.0f, 0.0f, 0.0f, + smoothness, 0.0f, 0.0f, cuts, - SUBDIV_SELECT_LOOPCUT, SUBD_PATH, 0, TRUE, 0); + SUBDIV_SELECT_LOOPCUT, SUBD_PATH, 0, TRUE, + use_only_quads, 0); /* force edge slide to edge select mode in in face select mode */ if (em->selectmode & SCE_SELECT_FACE) { @@ -413,6 +424,7 @@ static int ringcut_cancel(bContext *C, wmOperator *op) static int ringcut_invoke(bContext *C, wmOperator *op, wmEvent *evt) { + ScrArea *sa = CTX_wm_area(C); Object *obedit = CTX_data_edit_object(C); RingSelOpData *lcd; BMEdge *edge; @@ -438,13 +450,17 @@ static int ringcut_invoke(bContext *C, wmOperator *op, wmEvent *evt) lcd->eed = edge; ringsel_find_edge(lcd, 1); } - ED_area_headerprint(CTX_wm_area(C), "Select a ring to be cut, use mouse-wheel or page-up/down for number of cuts"); + ED_area_headerprint(sa, + "Select a ring to be cut, " + "use mouse-wheel or page-up/down for number of cuts, " + "Hold Alt for smooth"); return OPERATOR_RUNNING_MODAL; } static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) { + float smoothness = RNA_float_get(op->ptr, "smoothness"); int cuts = RNA_int_get(op->ptr, "number_cuts"); RingSelOpData *lcd = op->customdata; int show_cuts = 0; @@ -491,11 +507,17 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) case WHEELUPMOUSE: /* change number of cuts */ if (event->val == KM_RELEASE) break; - - cuts++; - RNA_int_set(op->ptr, "number_cuts", cuts); - ringsel_find_edge(lcd, cuts); - show_cuts = TRUE; + if (event->alt == 0) { + cuts++; + RNA_int_set(op->ptr, "number_cuts", cuts); + ringsel_find_edge(lcd, cuts); + show_cuts = TRUE; + } + else { + smoothness = min_ff(smoothness + 0.05f, 4.0f); + RNA_float_set(op->ptr, "smoothness", smoothness); + show_cuts = TRUE; + } ED_region_tag_redraw(lcd->ar); break; @@ -505,10 +527,17 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) if (event->val == KM_RELEASE) break; - cuts = max_ii(cuts - 1, 0); - RNA_int_set(op->ptr, "number_cuts", cuts); - ringsel_find_edge(lcd, cuts); - show_cuts = TRUE; + if (event->alt == 0) { + cuts = max_ii(cuts - 1, 0); + RNA_int_set(op->ptr, "number_cuts", cuts); + ringsel_find_edge(lcd, cuts); + show_cuts = TRUE; + } + else { + smoothness = max_ff(smoothness - 0.05f, 0.0f); + RNA_float_set(op->ptr, "smoothness", smoothness); + show_cuts = TRUE; + } ED_region_tag_redraw(lcd->ar); break; @@ -533,9 +562,9 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) /* using the keyboard to input the number of cuts */ if (event->val == KM_PRESS) { /* init as zero so backspace clears */ - float value = 0.0f; if (handleNumInput(&lcd->num, event)) { + float value = RNA_int_get(op->ptr, "number_cuts"); applyNumInput(&lcd->num, &value); /* allow zero so you can backspace and type in a value @@ -552,7 +581,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) if (show_cuts) { char buf[64]; - BLI_snprintf(buf, sizeof(buf), "Number of Cuts: %d", cuts); + BLI_snprintf(buf, sizeof(buf), "Number of Cuts: %d, Smooth: %.2f (Alt)", cuts, smoothness); ED_area_headerprint(CTX_wm_area(C), buf); } @@ -604,4 +633,7 @@ void MESH_OT_loopcut(wmOperatorType *ot) prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, INT_MAX, "Number of Cuts", "", 1, 10); /* avoid re-using last var because it can cause _very_ high poly meshes and annoy users (or worse crash) */ RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_float(ot->srna, "smoothness", 0.0f, 0.0f, FLT_MAX, "Smoothness", "Smoothness factor", 0.0f, 4.0f); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 6379bdbc0ca..2ecc20b2ddb 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -60,7 +60,7 @@ * * \param inset is used so we get some useful distance * when comparing multiple edges that meet at the same - * point and would result in teh same distance. + * point and would result in the same distance. */ #define INSET_DEFAULT 0.00001f static float edbm_rip_edgedist(ARegion *ar, float mat[][4], @@ -489,7 +489,7 @@ static void edbm_tagged_loop_pairs_do_fill_faces(BMesh *bm, UnorderedLoopPair *u } /* face should never exist */ - BLI_assert(BM_face_exists(bm, f_verts, f_verts[3] ? 4 : 3, &f) == FALSE); + BLI_assert(BM_face_exists(f_verts, f_verts[3] ? 4 : 3, &f) == FALSE); f = BM_face_create_quad_tri_v(bm, f_verts, f_verts[3] ? 4 : 3, f_example, FALSE); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 0379068afd9..3335f03ac17 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -56,6 +56,7 @@ #include "ED_mesh.h" #include "ED_screen.h" +#include "ED_util.h" #include "ED_uvedit.h" #include "ED_object.h" #include "ED_view3d.h" @@ -68,6 +69,7 @@ #include "mesh_intern.h" +#include "UI_resources.h" /* ****************************** MIRROR **************** */ @@ -448,20 +450,6 @@ BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist, const short sel, } } -/* returns labda for closest distance v1 to line-piece v2 - v3 */ -float labda_PdistVL2Dfl(const float v1[2], const float v2[2], const float v3[2]) -{ - float rc[2], len; - - rc[0] = v3[0] - v2[0]; - rc[1] = v3[1] - v2[1]; - len = rc[0] * rc[0] + rc[1] * rc[1]; - if (len == 0.0f) - return 0.0f; - - return (rc[0] * (v1[0] - v2[0]) + rc[1] * (v1[1] - v2[1])) / len; -} - /* note; uses v3d, so needs active 3d window */ static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index)) { @@ -476,7 +464,7 @@ static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float if (distance < data->dist) { if (data->vc.rv3d->rflag & RV3D_CLIPPING) { - float labda = labda_PdistVL2Dfl(data->mval_fl, screen_co_a, screen_co_b); + float labda = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b); float vec[3]; vec[0] = eed->v1->co[0] + labda * (eed->v2->co[0] - eed->v1->co[0]); @@ -730,7 +718,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op) EDBM_flag_disable_all(em, BM_ELEM_SELECT); /* select the output */ - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faceout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); /* finish the operator */ if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -771,7 +759,7 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op) EDBM_flag_disable_all(em, BM_ELEM_SELECT); /* select the output */ - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "edgeout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, TRUE); EDBM_selectmode_flush(em); /* finish the operator */ @@ -815,7 +803,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) EDBM_flag_disable_all(em, BM_ELEM_SELECT); /* select the output */ - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "vertout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, TRUE); /* finish the operator */ if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -915,6 +903,74 @@ void MESH_OT_select_similar(wmOperatorType *ot) RNA_def_float(ot->srna, "threshold", 0.0, 0.0, 1.0, "Threshold", "", 0.0, 1.0); } + +/* **************** Mode Select *************** */ + +static int edbm_select_mode_exec(bContext *C, wmOperator *op) +{ + const int type = RNA_enum_get(op->ptr, "type"); + const int action = RNA_enum_get(op->ptr, "action"); + const int use_extend = RNA_boolean_get(op->ptr, "use_extend"); + const int use_expand = RNA_boolean_get(op->ptr, "use_expand"); + + if (EDBM_selectmode_toggle(C, type, action, use_extend, use_expand)) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +static int edbm_select_mode_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + // RNA_enum_set(op->ptr, "type"); /* type must be set already */ + RNA_boolean_set(op->ptr, "use_extend", event->shift); + RNA_boolean_set(op->ptr, "use_expand", event->ctrl); + return edbm_select_mode_exec(C, op); +} + +void MESH_OT_select_mode(wmOperatorType *ot) +{ + PropertyRNA *prop; + + static EnumPropertyItem elem_items[] = { + {SCE_SELECT_VERTEX, "VERT", ICON_VERTEXSEL, "Vertices", ""}, + {SCE_SELECT_EDGE, "EDGE", ICON_EDGESEL, "Edges", ""}, + {SCE_SELECT_FACE, "FACE", ICON_FACESEL, "Faces", ""}, + {0, NULL, 0, NULL, NULL}, + }; + + static EnumPropertyItem actions_items[] = { + {0, "DISABLE", 0, "Disable", "Disable selected markers"}, + {1, "ENABLE", 0, "Enable", "Enable selected markers"}, + {2, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name = "Select Mode"; + ot->idname = "MESH_OT_select_mode"; + ot->description = "Change selection mode"; + + /* api callbacks */ + ot->invoke = edbm_select_mode_invoke; + ot->exec = edbm_select_mode_exec; + ot->poll = ED_operator_editmesh; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + prop = RNA_def_boolean(ot->srna, "use_extend", FALSE, "Extend", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "use_expand", FALSE, "Expand", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + ot->prop = prop = RNA_def_enum(ot->srna, "type", elem_items, 0, "Type", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + RNA_def_enum(ot->srna, "action", actions_items, 2, "Action", "Selection action to execute"); +} + /* ***************************************************** */ /* **************** LOOP SELECTS *************** */ @@ -1013,7 +1069,7 @@ void MESH_OT_loop_multi_select(wmOperatorType *ot) /* ***************** loop select (non modal) ************** */ -static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short ring) +static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short deselect, short toggle, short ring) { ViewContext vc; BMEditMesh *em; @@ -1032,14 +1088,20 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short ring) eed = EDBM_edge_find_nearest(&vc, &dist); if (eed) { - if (extend == 0) { + if (extend == 0 && deselect == 0 && toggle == 0) { EDBM_flag_disable_all(em, BM_ELEM_SELECT); } - if (BM_elem_flag_test(eed, BM_ELEM_SELECT) == 0) { + if (extend) { select = TRUE; } - else if (extend) { + else if (deselect) { + select = FALSE; + } + else if (BM_elem_flag_test(eed, BM_ELEM_SELECT) == 0) { + select = TRUE; + } + else if (toggle) { select = FALSE; } @@ -1132,6 +1194,8 @@ static int edbm_select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event) view3d_operator_needs_opengl(C); mouse_mesh_loop(C, event->mval, RNA_boolean_get(op->ptr, "extend"), + RNA_boolean_get(op->ptr, "deselect"), + RNA_boolean_get(op->ptr, "toggle"), RNA_boolean_get(op->ptr, "ring")); /* cannot do tweaks for as long this keymap is after transform map */ @@ -1154,6 +1218,8 @@ void MESH_OT_loop_select(wmOperatorType *ot) /* properties */ RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "Extend the selection"); + RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection"); + RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection"); RNA_def_boolean(ot->srna, "ring", 0, "Select Ring", "Select ring"); } @@ -1172,64 +1238,74 @@ void MESH_OT_edgering_select(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection"); + RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection"); + RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection"); RNA_def_boolean(ot->srna, "ring", 1, "Select Ring", "Select ring"); } -/* ******************* edgetag_shortest_path and helpers ****************** */ +/* ******************* generic tag_shortest_path and helpers ****************** */ -static float edgetag_cut_cost(BMEditMesh *UNUSED(em), BMEdge *e1, BMEdge *e2, BMVert *v) +static float step_cost_3_v3(const float v1[3], const float v2[3], const float v3[3]) { - BMVert *v1 = (e1->v1 == v) ? e1->v2 : e1->v1; - BMVert *v2 = (e2->v1 == v) ? e2->v2 : e2->v1; float cost, d1[3], d2[3]; + /* The cost is based on the simple sum of the length of the two edgees... */ - sub_v3_v3v3(d1, v->co, v1->co); - sub_v3_v3v3(d2, v2->co, v->co); - cost = len_v3(d1); - cost += len_v3(d2); + sub_v3_v3v3(d1, v2, v1); + sub_v3_v3v3(d2, v3, v2); + cost = normalize_v3(d1) + normalize_v3(d2); /* but is biased to give higher values to sharp turns, so that it will take * paths with fewer "turns" when selecting between equal-weighted paths between * the two edges */ - cost = cost + 0.5f * cost * (2.0f - sqrtf(fabsf(dot_v3v3(d1, d2)))); + cost = cost * (1.0f + 0.5f * (2.0f - sqrtf(fabsf(dot_v3v3(d1, d2))))); return cost; } -static void edgetag_add_adjacent(BMEditMesh *em, SmallHash *visithash, Heap *heap, int mednum, int vertnum, - int *nedges, int *edges, int *prevedge, float *cost) +/* ******************* edgetag_shortest_path and helpers ****************** */ + +static float edgetag_cut_cost(BMEdge *e1, BMEdge *e2, BMVert *v) { - BMEdge *e1 = EDBM_edge_at_index(em, mednum); - BMVert *v = EDBM_vert_at_index(em, vertnum); - int startadj, endadj = nedges[vertnum + 1]; + BMVert *v1 = BM_edge_other_vert(e1, v); + BMVert *v2 = BM_edge_other_vert(e2, v); + return step_cost_3_v3(v1->co, v->co, v2->co); +} - for (startadj = nedges[vertnum]; startadj < endadj; startadj++) { - int adjnum = edges[startadj]; - BMEdge *e2 = EDBM_edge_at_index(em, adjnum); - float newcost; - float cutcost; +static void edgetag_add_adjacent(Heap *heap, BMEdge *e1, BMEdge **edges_prev, float *cost) +{ + BMIter viter; + BMVert *v; - if (BLI_smallhash_haskey(visithash, (uintptr_t)e2)) - continue; + BMIter eiter; + BMEdge *e2; - cutcost = edgetag_cut_cost(em, e1, e2, v); - newcost = cost[mednum] + cutcost; + const int e1_index = BM_elem_index_get(e1); - if (cost[adjnum] > newcost) { - cost[adjnum] = newcost; - prevedge[adjnum] = mednum; - BLI_heap_insert(heap, newcost, SET_INT_IN_POINTER(adjnum)); + BM_ITER_ELEM (v, &viter, e1, BM_VERTS_OF_EDGE) { + BM_ITER_ELEM (e2, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e2, BM_ELEM_TAG)) { + /* we know 'e2' is not visited, check it out! */ + const int e2_index = BM_elem_index_get(e2); + const float cost_cut = edgetag_cut_cost(e1, e2, v); + const float cost_new = cost[e1_index] + cost_cut; + + if (cost[e2_index] > cost_new) { + cost[e2_index] = cost_new; + edges_prev[e2_index] = e1; + BLI_heap_insert(heap, cost_new, e2); + } + } } } } -static void edgetag_context_set(BMEditMesh *em, Scene *scene, BMEdge *e, int val) +static void edgetag_context_set(BMesh *bm, Scene *scene, BMEdge *e, int val) { switch (scene->toolsettings->edge_mode) { case EDGE_MODE_SELECT: - BM_edge_select_set(em->bm, e, val); + BM_edge_select_set(bm, e, val); break; case EDGE_MODE_TAG_SEAM: BM_elem_flag_set(e, BM_ELEM_SEAM, val); @@ -1238,98 +1314,66 @@ static void edgetag_context_set(BMEditMesh *em, Scene *scene, BMEdge *e, int val BM_elem_flag_set(e, BM_ELEM_SMOOTH, !val); break; case EDGE_MODE_TAG_CREASE: - { - float *crease = CustomData_bmesh_get(&em->bm->edata, e->head.data, CD_CREASE); - *crease = (val) ? 1.0f : 0.0f; + BM_elem_float_data_set(&bm->edata, e, CD_CREASE, (val) ? 1.0f : 0.0f); break; - } case EDGE_MODE_TAG_BEVEL: - { - float *bweight = CustomData_bmesh_get(&em->bm->edata, e->head.data, CD_BWEIGHT); - *bweight = (val) ? 1.0f : 0.0f; + BM_elem_float_data_set(&bm->edata, e, CD_BWEIGHT, (val) ? 1.0f : 0.0f); break; - } } } -static int edgetag_context_check(Scene *scene, BMEditMesh *em, BMEdge *e) +static int edgetag_context_check(Scene *scene, BMesh *bm, BMEdge *e) { switch (scene->toolsettings->edge_mode) { case EDGE_MODE_SELECT: - return BM_elem_flag_test(e, BM_ELEM_SELECT) ? 1 : 0; + return BM_elem_flag_test(e, BM_ELEM_SELECT) ? TRUE : FALSE; case EDGE_MODE_TAG_SEAM: return BM_elem_flag_test(e, BM_ELEM_SEAM); case EDGE_MODE_TAG_SHARP: return !BM_elem_flag_test(e, BM_ELEM_SMOOTH); case EDGE_MODE_TAG_CREASE: - return BM_elem_float_data_get(&em->bm->edata, e, CD_CREASE) ? 1 : 0; + return BM_elem_float_data_get(&bm->edata, e, CD_CREASE) ? TRUE : FALSE; case EDGE_MODE_TAG_BEVEL: - return BM_elem_float_data_get(&em->bm->edata, e, CD_BWEIGHT) ? 1 : 0; + return BM_elem_float_data_get(&bm->edata, e, CD_BWEIGHT) ? TRUE : FALSE; } return 0; } -static int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *source, BMEdge *target) +static int edgetag_shortest_path(Scene *scene, BMesh *bm, BMEdge *e_src, BMEdge *e_dst) { + /* BM_ELEM_TAG flag is used to store visited edges */ BMEdge *e; - BMIter iter; + BMIter eiter; Heap *heap; - SmallHash visithash; float *cost; - int i, totvert = 0, totedge = 0, *nedges, *edges, *prevedge, mednum = -1, nedgeswap = 0; - int targetnum; - - BLI_smallhash_init(&visithash); + BMEdge **edges_prev; + int i, totedge; /* note, would pass BM_EDGE except we are looping over all edges anyway */ - BM_mesh_elem_index_ensure(em->bm, BM_VERT /* | BM_EDGE */); + BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); - BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - BLI_smallhash_insert(&visithash, (uintptr_t)e, NULL); + BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) { + if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == FALSE) { + BM_elem_flag_disable(e, BM_ELEM_TAG); + } + else { + BM_elem_flag_enable(e, BM_ELEM_TAG); } - BM_elem_index_set(e, totedge); /* set_inline */ - totedge++; + BM_elem_index_set(e, i); /* set_inline */ } - em->bm->elem_index_dirty &= ~BM_EDGE; + bm->elem_index_dirty &= ~BM_EDGE; /* alloc */ - totvert = em->bm->totvert; - nedges = MEM_callocN(sizeof(*nedges) * totvert + 1, "SeamPathNEdges"); - edges = MEM_mallocN(sizeof(*edges) * totedge * 2, "SeamPathEdges"); - prevedge = MEM_mallocN(sizeof(*prevedge) * totedge, "SeamPathPrevious"); + totedge = bm->totedge; + edges_prev = MEM_callocN(sizeof(*edges_prev) * totedge, "SeamPathPrevious"); cost = MEM_mallocN(sizeof(*cost) * totedge, "SeamPathCost"); - /* count edges, compute adjacent edges offsets and fill adjacent */ - BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { - nedges[BM_elem_index_get(e->v1) + 1]++; - nedges[BM_elem_index_get(e->v2) + 1]++; - } - - for (i = 1; i < totvert; i++) { - int newswap = nedges[i + 1]; - nedges[i + 1] = nedgeswap + nedges[i]; - nedgeswap = newswap; - } - nedges[0] = nedges[1] = 0; - - i = 0; - BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { - edges[nedges[BM_elem_index_get(e->v1) + 1]++] = i; - edges[nedges[BM_elem_index_get(e->v2) + 1]++] = i; - - cost[i] = 1e20f; - prevedge[i] = -1; - i++; - } + fill_vn_fl(cost, totedge, 1e20f); /* * Arrays are now filled as follows: * - * nedges[n] = sum of the # of edges incident to all vertices numbered 0 through n - 1 - * edges[edges[n]..edges[n - 1]] = the indices of of the edges incident to vertex n - * * As the search continues, prevedge[n] will be the previous edge on the shortest * path found so far to edge n. The visitedhash will of course contain entries * for edges that have been visited, cost[n] will contain the length of the shortest @@ -1340,61 +1384,46 @@ static int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *source, B /* regular dijkstra shortest path, but over edges instead of vertices */ heap = BLI_heap_new(); - BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(BM_elem_index_get(source))); - cost[BM_elem_index_get(source)] = 0.0f; - EDBM_index_arrays_init(em, 1, 1, 0); - targetnum = BM_elem_index_get(target); + BLI_heap_insert(heap, 0.0f, e_src); + cost[BM_elem_index_get(e_src)] = 0.0f; + + e = NULL; while (!BLI_heap_is_empty(heap)) { - mednum = GET_INT_FROM_POINTER(BLI_heap_popmin(heap)); - e = EDBM_edge_at_index(em, mednum); + e = BLI_heap_popmin(heap); - if (mednum == targetnum) + if (e == e_dst) break; - if (BLI_smallhash_haskey(&visithash, (uintptr_t)e)) - continue; - - BLI_smallhash_insert(&visithash, (uintptr_t)e, NULL); - - edgetag_add_adjacent(em, &visithash, heap, mednum, BM_elem_index_get(e->v1), nedges, edges, prevedge, cost); - edgetag_add_adjacent(em, &visithash, heap, mednum, BM_elem_index_get(e->v2), nedges, edges, prevedge, cost); + if (!BM_elem_flag_test(e, BM_ELEM_TAG)) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + edgetag_add_adjacent(heap, e, edges_prev, cost); + } } - if (mednum == targetnum) { - short allseams = 1; + if (e == e_dst) { + short all_set = TRUE; /* Check whether the path is already completely tagged. * if it is, the tags will be cleared instead of set. */ - mednum = targetnum; + e = e_dst; do { - e = EDBM_edge_at_index(em, mednum); - if (!edgetag_context_check(scene, em, e)) { - allseams = 0; + if (!edgetag_context_check(scene, bm, e)) { + all_set = FALSE; break; } - mednum = prevedge[mednum]; - } while (mednum != BM_elem_index_get(source)); + } while ((e = edges_prev[BM_elem_index_get(e)])); /* Follow path back and source and add or remove tags */ - mednum = targetnum; + e = e_dst; do { - e = EDBM_edge_at_index(em, mednum); - if (allseams) - edgetag_context_set(em, scene, e, 0); - else - edgetag_context_set(em, scene, e, 1); - mednum = prevedge[mednum]; - } while (mednum != -1); + edgetag_context_set(bm, scene, e, !all_set); + } while ((e = edges_prev[BM_elem_index_get(e)])); } - EDBM_index_arrays_free(em); - MEM_freeN(nedges); - MEM_freeN(edges); - MEM_freeN(prevedge); + MEM_freeN(edges_prev); MEM_freeN(cost); BLI_heap_free(heap, NULL); - BLI_smallhash_release(&visithash); return 1; } @@ -1402,21 +1431,15 @@ static int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *source, B /* ******************* mesh shortest path select, uses prev-selected edge ****************** */ /* since you want to create paths with multiple selects, it doesn't have extend option */ -static int mouse_mesh_shortest_path(bContext *C, int mval[2]) +static int mouse_mesh_shortest_path_edge(bContext *C, ViewContext *vc) { - ViewContext vc; - BMEditMesh *em; - BMEdge *e; + BMEditMesh *em = vc->em; + BMEdge *e_dst; float dist = 75.0f; - em_setup_viewcontext(C, &vc); - vc.mval[0] = mval[0]; - vc.mval[1] = mval[1]; - em = vc.em; - - e = EDBM_edge_find_nearest(&vc, &dist); - if (e) { - Mesh *me = vc.obedit->data; + e_dst = EDBM_edge_find_nearest(vc, &dist); + if (e_dst) { + Mesh *me = vc->obedit->data; int path = 0; if (em->bm->selected.last) { @@ -1425,8 +1448,8 @@ static int mouse_mesh_shortest_path(bContext *C, int mval[2]) if (ese && ese->htype == BM_EDGE) { BMEdge *e_act; e_act = (BMEdge *)ese->ele; - if (e_act != e) { - if (edgetag_shortest_path(vc.scene, em, e_act, e)) { + if (e_act != e_dst) { + if (edgetag_shortest_path(vc->scene, em->bm, e_act, e_dst)) { BM_select_history_remove(em->bm, e_act); path = 1; } @@ -1434,24 +1457,24 @@ static int mouse_mesh_shortest_path(bContext *C, int mval[2]) } } if (path == 0) { - int act = (edgetag_context_check(vc.scene, em, e) == 0); - edgetag_context_set(em, vc.scene, e, act); /* switch the edge option */ + int act = (edgetag_context_check(vc->scene, em->bm, e_dst) == 0); + edgetag_context_set(em->bm, vc->scene, e_dst, act); /* switch the edge option */ } EDBM_selectmode_flush(em); /* even if this is selected it may not be in the selection list */ - if (edgetag_context_check(vc.scene, em, e) == 0) - BM_select_history_remove(em->bm, e); + if (edgetag_context_check(vc->scene, em->bm, e_dst) == 0) + BM_select_history_remove(em->bm, e_dst); else - BM_select_history_store(em->bm, e); + BM_select_history_store(em->bm, e_dst); /* force drawmode for mesh */ switch (CTX_data_tool_settings(C)->edge_mode) { case EDGE_MODE_TAG_SEAM: me->drawflag |= ME_DRAWSEAMS; - ED_uvedit_live_unwrap(vc.scene, vc.obedit); + ED_uvedit_live_unwrap(vc->scene, vc->obedit); break; case EDGE_MODE_TAG_SHARP: me->drawflag |= ME_DRAWSHARP; @@ -1474,25 +1497,237 @@ static int mouse_mesh_shortest_path(bContext *C, int mval[2]) } -static int edbm_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) -{ - - view3d_operator_needs_opengl(C); +/* ******************* facetag_shortest_path and helpers ****************** */ - if (mouse_mesh_shortest_path(C, event->mval)) { - return OPERATOR_FINISHED; + +static float facetag_cut_cost(BMFace *f1, BMFace *f2, BMEdge *e) +{ + float f1_cent[3]; + float f2_cent[3]; + float e_cent[3]; + + BM_face_calc_center_mean(f1, f1_cent); + BM_face_calc_center_mean(f2, f2_cent); + mid_v3_v3v3(e_cent, e->v1->co, e->v2->co); + + return step_cost_3_v3(f1_cent, e_cent, f2_cent); +} + +static void facetag_add_adjacent(Heap *heap, BMFace *f1, BMFace **faces_prev, float *cost) +{ + BMIter liter; + BMLoop *l2; + BMFace *f2; + + const int f1_index = BM_elem_index_get(f1); + + /* loop over faces of face, but do so by first looping over loops */ + BM_ITER_ELEM (l2, &liter, f1, BM_LOOPS_OF_FACE) { + BMLoop *l_first; + BMLoop *l_iter; + + l_iter = l_first = l2; + do { + f2 = l_iter->f; + if (!BM_elem_flag_test(f2, BM_ELEM_TAG)) { + /* we know 'f2' is not visited, check it out! */ + const int f2_index = BM_elem_index_get(f2); + const float cost_cut = facetag_cut_cost(f1, f2, l_iter->e); + const float cost_new = cost[f1_index] + cost_cut; + + if (cost[f2_index] > cost_new) { + cost[f2_index] = cost_new; + faces_prev[f2_index] = f1; + BLI_heap_insert(heap, cost_new, f2); + } + } + } while ((l_iter = l_iter->radial_next) != l_first); + } +} + +static void facetag_context_set(BMesh *bm, Scene *UNUSED(scene), BMFace *f, int val) +{ + BM_face_select_set(bm, f, val); +} + +static int facetag_context_check(Scene *UNUSED(scene), BMesh *UNUSED(bm), BMFace *f) +{ + return BM_elem_flag_test(f, BM_ELEM_SELECT) ? 1 : 0; +} + +static int facetag_shortest_path(Scene *scene, BMesh *bm, BMFace *f_src, BMFace *f_dst) +{ + /* BM_ELEM_TAG flag is used to store visited edges */ + BMFace *f; + BMIter fiter; + Heap *heap; + float *cost; + BMFace **faces_prev; + int i, totface; + + /* note, would pass BM_EDGE except we are looping over all faces anyway */ + // BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); // NOT NEEDED FOR FACETAG + + BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, i) { + if (BM_elem_flag_test(f, BM_ELEM_HIDDEN) == FALSE) { + BM_elem_flag_disable(f, BM_ELEM_TAG); + } + else { + BM_elem_flag_enable(f, BM_ELEM_TAG); + } + + BM_elem_index_set(f, i); /* set_inline */ + } + bm->elem_index_dirty &= ~BM_FACE; + + /* alloc */ + totface = bm->totface; + faces_prev = MEM_callocN(sizeof(*faces_prev) * totface, "SeamPathPrevious"); + cost = MEM_mallocN(sizeof(*cost) * totface, "SeamPathCost"); + + fill_vn_fl(cost, totface, 1e20f); + + /* + * Arrays are now filled as follows: + * + * As the search continues, faces_prev[n] will be the previous face on the shortest + * path found so far to face n. The visitedhash will of course contain entries + * for faces that have been visited, cost[n] will contain the length of the shortest + * path to face n found so far, Finally, heap is a priority heap which is built on the + * the same data as the cost array, but inverted: it is a worklist of faces prioritized + * by the shortest path found so far to the face. + */ + + /* regular dijkstra shortest path, but over faces instead of vertices */ + heap = BLI_heap_new(); + BLI_heap_insert(heap, 0.0f, f_src); + cost[BM_elem_index_get(f_src)] = 0.0f; + + f = NULL; + + while (!BLI_heap_is_empty(heap)) { + f = BLI_heap_popmin(heap); + + if (f == f_dst) + break; + + if (!BM_elem_flag_test(f, BM_ELEM_TAG)) { + BM_elem_flag_enable(f, BM_ELEM_TAG); + facetag_add_adjacent(heap, f, faces_prev, cost); + } + } + + if (f == f_dst) { + short all_set = TRUE; + + /* Check whether the path is already completely tagged. + * if it is, the tags will be cleared instead of set. */ + f = f_dst; + do { + if (!facetag_context_check(scene, bm, f)) { + all_set = FALSE; + break; + } + } while ((f = faces_prev[BM_elem_index_get(f)])); + + /* Follow path back and source and add or remove tags */ + f = f_dst; + do { + facetag_context_set(bm, scene, f, !all_set); + } while ((f = faces_prev[BM_elem_index_get(f)])); + } + + MEM_freeN(faces_prev); + MEM_freeN(cost); + BLI_heap_free(heap, NULL); + + return 1; +} + +static int mouse_mesh_shortest_path_face(bContext *C, ViewContext *vc) +{ + BMEditMesh *em = vc->em; + BMFace *f_dst; + float dist = 75.0f; + + f_dst = EDBM_face_find_nearest(vc, &dist); + if (f_dst) { + int path = 0; + BMFace *f_act = BM_active_face_get(em->bm, FALSE, TRUE); + + if (f_act) { + if (f_act != f_dst) { + if (facetag_shortest_path(vc->scene, em->bm, f_act, f_dst)) { + BM_select_history_remove(em->bm, f_act); + path = 1; + } + } + } + if (path == 0) { + int act = (facetag_context_check(vc->scene, em->bm, f_dst) == 0); + facetag_context_set(em->bm, vc->scene, f_dst, act); /* switch the face option */ + } + + EDBM_selectmode_flush(em); + + /* even if this is selected it may not be in the selection list */ + if (facetag_context_check(vc->scene, em->bm, f_dst) == 0) + BM_select_history_remove(em->bm, f_dst); + else + BM_select_history_store(em->bm, f_dst); + + BM_active_face_set(em->bm, f_dst); + + EDBM_update_generic(C, em, FALSE); + + return TRUE; } else { - return OPERATOR_PASS_THROUGH; + return FALSE; } } + +/* ******************* operator for edge and face tag ****************** */ + +static int edbm_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +{ + ViewContext vc; + BMEditMesh *em; + + view3d_operator_needs_opengl(C); + + em_setup_viewcontext(C, &vc); + vc.mval[0] = event->mval[0]; + vc.mval[1] = event->mval[1]; + em = vc.em; + + if (em->selectmode & SCE_SELECT_EDGE) { + if (mouse_mesh_shortest_path_edge(C, &vc)) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_PASS_THROUGH; + } + } + else if (em->selectmode & SCE_SELECT_FACE) { + if (mouse_mesh_shortest_path_face(C, &vc)) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_PASS_THROUGH; + } + } + + return OPERATOR_PASS_THROUGH; +} + static int edbm_shortest_path_select_poll(bContext *C) { if (ED_operator_editmesh_region_view3d(C)) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); - return (em->selectmode & SCE_SELECT_EDGE) != 0; + return (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_FACE)) != 0; } return 0; } @@ -1622,7 +1857,7 @@ int EDBM_select_pick(bContext *C, const int mval[2], short extend, short deselec vc.obedit->actcol = efa->mat_nr + 1; vc.em->mat_nr = efa->mat_nr; - WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING, NULL); + WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL); } @@ -1714,56 +1949,146 @@ void EDBM_selectmode_convert(BMEditMesh *em, const short selectmode_old, const s BMFace *efa; BMIter iter; + /* first tag-to-select, then select --- this avoids a feedback loop */ + /* have to find out what the selectionmode was previously */ if (selectmode_old == SCE_SELECT_VERTEX) { if (selectmode_new == SCE_SELECT_EDGE) { - /* select all edges associated with every selected vertex */ - eed = BM_iter_new(&iter, em->bm, BM_EDGES_OF_MESH, NULL); - for (; eed; eed = BM_iter_step(&iter)) { - if ((BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) || - BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))) - { + /* select all edges associated with every selected vert */ + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { + BM_elem_flag_set(eed, BM_ELEM_TAG, BM_edge_is_any_vert_flag_test(eed, BM_ELEM_SELECT)); + } + + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(eed, BM_ELEM_TAG)) { BM_edge_select_set(em->bm, eed, TRUE); } } } else if (selectmode_new == SCE_SELECT_FACE) { - BMIter liter; - BMLoop *l; + /* select all faces associated with every selected vert */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_vert_flag_test(efa, BM_ELEM_SELECT)); + } - /* select all faces associated with every selected vertex */ - efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL); - for (; efa; efa = BM_iter_step(&iter)) { - l = BM_iter_new(&liter, em->bm, BM_LOOPS_OF_FACE, efa); - for (; l; l = BM_iter_step(&liter)) { - if (BM_elem_flag_test(l->v, BM_ELEM_SELECT)) { - BM_face_select_set(em->bm, efa, TRUE); - break; - } + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { + BM_face_select_set(em->bm, efa, TRUE); } } } } else if (selectmode_old == SCE_SELECT_EDGE) { if (selectmode_new == SCE_SELECT_FACE) { - BMIter liter; - BMLoop *l; + /* select all faces associated with every selected edge */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_edge_flag_test(efa, BM_ELEM_SELECT)); + } - /* select all faces associated with every selected vertex */ - efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL); - for (; efa; efa = BM_iter_step(&iter)) { - l = BM_iter_new(&liter, em->bm, BM_LOOPS_OF_FACE, efa); - for (; l; l = BM_iter_step(&liter)) { - if (BM_elem_flag_test(l->v, BM_ELEM_SELECT)) { - BM_face_select_set(em->bm, efa, TRUE); - break; - } + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { + BM_face_select_set(em->bm, efa, TRUE); } } } } } +/* user facing function, does notification and undo push */ +int EDBM_selectmode_toggle(bContext *C, const short selectmode_new, + const int action, const int use_extend, const int use_expand) +{ + ToolSettings *ts = CTX_data_tool_settings(C); + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = NULL; + int ret = FALSE; + + if (obedit && obedit->type == OB_MESH) { + em = BMEdit_FromObject(obedit); + } + + if (em == NULL) { + return ret; + } + + switch (action) { + case -1: + /* already set */ + break; + case 0: /* disable */ + /* check we have something to do */ + if ((em->selectmode & selectmode_new) == 0) { + return FALSE; + } + em->selectmode &= ~selectmode_new; + break; + case 1: /* enable */ + /* check we have something to do */ + if ((em->selectmode & selectmode_new) != 0) { + return FALSE; + } + em->selectmode |= selectmode_new; + break; + case 2: /* toggle */ + /* can't disable this flag if its the only one set */ + if (em->selectmode == selectmode_new) { + return FALSE; + } + em->selectmode ^= selectmode_new; + break; + default: + BLI_assert(0); + } + + switch (selectmode_new) { + case SCE_SELECT_VERTEX: + if (use_extend == 0 || em->selectmode == 0) + em->selectmode = SCE_SELECT_VERTEX; + ts->selectmode = em->selectmode; + EDBM_selectmode_set(em); + ret = TRUE; + break; + case SCE_SELECT_EDGE: + if (use_extend == 0 || em->selectmode == 0) { + if (use_expand) { + const short selmode_max = highest_order_bit_s(ts->selectmode); + if (selmode_max == SCE_SELECT_VERTEX) { + EDBM_selectmode_convert(em, selmode_max, SCE_SELECT_EDGE); + } + } + em->selectmode = SCE_SELECT_EDGE; + } + ts->selectmode = em->selectmode; + EDBM_selectmode_set(em); + ret = TRUE; + break; + case SCE_SELECT_FACE: + if (use_extend == 0 || em->selectmode == 0) { + if (use_expand) { + const short selmode_max = highest_order_bit_s(ts->selectmode); + if (ELEM(selmode_max, SCE_SELECT_VERTEX, SCE_SELECT_EDGE)) { + EDBM_selectmode_convert(em, selmode_max, SCE_SELECT_FACE); + } + } + + em->selectmode = SCE_SELECT_FACE; + } + ts->selectmode = em->selectmode; + EDBM_selectmode_set(em); + ret = TRUE; + break; + default: + BLI_assert(0); + break; + } + + if (ret == TRUE) { + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL); + } + + return ret; +} void EDBM_deselect_by_material(BMEditMesh *em, const short index, const short select) { @@ -1911,6 +2236,8 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent * return OPERATOR_CANCELLED; if (limit) { + /* grr, shouldn't need to alloc BMO flags here */ + BM_mesh_elem_toolflags_ensure(bm); /* hflag no-seam --> bmo-tag */ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { /* BMESH_TODO, don't use 'BM_ELEM_SELECT' here, its a HFLAG only! */ @@ -2003,6 +2330,8 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) } if (limit) { + /* grr, shouldn't need to alloc BMO flags here */ + BM_mesh_elem_toolflags_ensure(bm); BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { /* BMESH_TODO, don't use 'BM_ELEM_SELECT' here, its a HFLAG only! */ BMO_elem_flag_set(bm, e, BM_ELEM_SELECT, !BM_elem_flag_test(e, BM_ELEM_SEAM)); @@ -2023,6 +2352,10 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) } } BMW_end(&walker); + + if (limit) { + BM_mesh_elem_toolflags_clear(bm); + } } else { BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { @@ -2168,6 +2501,9 @@ static void walker_deselect_nth(BMEditMesh *em, int nth, int offset, BMHeader *h break; } + /* grr, shouldn't need to alloc BMO flags here */ + BM_mesh_elem_toolflags_ensure(bm); + /* Walker restrictions uses BMO flags, not header flags, * so transfer BM_ELEM_SELECT from HFlags onto a BMO flag layer. */ BMO_push(bm, NULL); diff --git a/source/blender/editors/mesh/editmesh_slide.c b/source/blender/editors/mesh/editmesh_slide.c index d370b5a881e..4fbe9c2534f 100644 --- a/source/blender/editors/mesh/editmesh_slide.c +++ b/source/blender/editors/mesh/editmesh_slide.c @@ -695,7 +695,7 @@ static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_u BMOperator bmop; BMEditSelection *ese = (BMEditSelection *)em->bm->selected.last; - float distance_t = 0.0f; + float factor = 0.0f; /* Invoked modally? */ if (op->type->modal == edbm_vertex_slide_modal && op->customdata) { @@ -711,12 +711,12 @@ static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_u BM_select_history_store(em->bm, vso->start_vtx); ese = (BMEditSelection *)em->bm->selected.last; } - distance_t = vso->distance; - RNA_float_set(op->ptr, "distance_t", distance_t); + factor = vso->distance; + RNA_float_set(op->ptr, "factor", factor); } else { /* Get Properties */ - distance_t = RNA_float_get(op->ptr, "distance_t"); + factor = RNA_float_get(op->ptr, "factor"); } /* Is there a starting vertex ? */ @@ -729,8 +729,8 @@ static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_u /* Prepare operator */ if (!EDBM_op_init(em, &bmop, op, - "slide_vert vert=%e edge=%hev distance_t=%f", - start_vert, BM_ELEM_SELECT, distance_t)) + "slide_vert vert=%e edges=%he factor=%f", + start_vert, BM_ELEM_SELECT, factor)) { return OPERATOR_CANCELLED; } @@ -738,10 +738,10 @@ static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_u BMO_op_exec(bm, &bmop); /* Deselect the input edges */ - BMO_slot_buffer_hflag_disable(bm, &bmop, "edge", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_disable(bm, bmop.slots_in, "edges", BM_EDGE, BM_ELEM_SELECT, TRUE); /* Select the output vert */ - BMO_slot_buffer_hflag_enable(bm, &bmop, "vertout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, TRUE); /* Flush the select buffers */ EDBM_selectmode_flush(em); @@ -787,7 +787,7 @@ void MESH_OT_vert_slide(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* Properties for vertex slide */ - prop = RNA_def_float(ot->srna, "distance_t", 0.0f, -FLT_MAX, FLT_MAX, "Distance", "Distance", -5.0f, 5.0f); + prop = RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Distance", "Distance", -5.0f, 5.0f); RNA_def_property_ui_range(prop, -5.0f, 5.0f, 0.1, 4); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index f10faddc169..ad1077156ba 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -72,6 +72,7 @@ #include "RE_render_ext.h" #include "UI_interface.h" +#include "UI_resources.h" #include "mesh_intern.h" @@ -108,7 +109,7 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op) smooth, fractal, along_normal, cuts, SUBDIV_SELECT_ORIG, RNA_enum_get(op->ptr, "quadcorner"), - RNA_boolean_get(op->ptr, "quadtri"), TRUE, + RNA_boolean_get(op->ptr, "quadtri"), TRUE, FALSE, RNA_int_get(op->ptr, "seed")); EDBM_update_generic(C, em, TRUE); @@ -242,7 +243,7 @@ static short edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const c BMO_op_exec(em->bm, &bmop); - BMO_ITER (f, &siter, em->bm, &bmop, "faceout", BM_FACE) { + BMO_ITER (f, &siter, bmop.slots_out, "faces.out", BM_FACE) { BM_face_select_set(em->bm, f, TRUE); /* set face vertex normals to face normal */ @@ -269,7 +270,7 @@ static short edbm_extrude_edges_indiv(BMEditMesh *em, wmOperator *op, const char EDBM_flag_disable_all(em, BM_ELEM_SELECT); BMO_op_exec(em->bm, &bmop); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "geomout", BM_VERT | BM_EDGE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return 0; @@ -286,10 +287,10 @@ static short edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char EDBM_op_init(em, &bmop, op, "extrude_vert_indiv verts=%hv", hflag); /* deselect original verts */ - BMO_slot_buffer_hflag_disable(em->bm, &bmop, "verts", BM_VERT, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "verts", BM_VERT, BM_ELEM_SELECT, TRUE); BMO_op_exec(em->bm, &bmop); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "vertout", BM_VERT, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return 0; @@ -308,9 +309,12 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag, BMFace *f; ModifierData *md; BMElem *ele; + BMOpSlot *slot_edges_exclude; BMO_op_init(bm, &extop, BMO_FLAG_DEFAULTS, "extrude_face_region"); - BMO_slot_buffer_from_enabled_hflag(bm, &extop, "edgefacein", BM_VERT | BM_EDGE | BM_FACE, hflag); + BMO_slot_buffer_from_enabled_hflag(bm, &extop, extop.slots_in, "geom", BM_VERT | BM_EDGE | BM_FACE, hflag); + + slot_edges_exclude = BMO_slot_get(extop.slots_in, "edges_exclude"); /* If a mirror modifier with clipping is on, we need to adjust some * of the cases above to handle edges on the line of symmetry. @@ -350,21 +354,21 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag, if ((fabsf(co1[0]) < mmd->tolerance) && (fabsf(co2[0]) < mmd->tolerance)) { - BMO_slot_map_ptr_insert(bm, &extop, "exclude", edge, NULL); + BMO_slot_map_empty_insert(&extop, slot_edges_exclude, edge); } } if (mmd->flag & MOD_MIR_AXIS_Y) { if ((fabsf(co1[1]) < mmd->tolerance) && (fabsf(co2[1]) < mmd->tolerance)) { - BMO_slot_map_ptr_insert(bm, &extop, "exclude", edge, NULL); + BMO_slot_map_empty_insert(&extop, slot_edges_exclude, edge); } } if (mmd->flag & MOD_MIR_AXIS_Z) { if ((fabsf(co1[2]) < mmd->tolerance) && (fabsf(co2[2]) < mmd->tolerance)) { - BMO_slot_map_ptr_insert(bm, &extop, "exclude", edge, NULL); + BMO_slot_map_empty_insert(&extop, slot_edges_exclude, edge); } } } @@ -379,7 +383,7 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag, zero_v3(nor); - BMO_ITER (ele, &siter, bm, &extop, "geomout", BM_ALL) { + BMO_ITER (ele, &siter, extop.slots_out, "geom.out", BM_ALL) { BM_elem_select_set(bm, ele, TRUE); if (ele->head.htype == BM_FACE) { @@ -449,7 +453,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op) for (a = 0; a < steps; a++) { edbm_extrude_edge(obedit, em, BM_ELEM_SELECT, nor); - //BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "extrude_face_region edgefacein=%hef", BM_ELEM_SELECT); + //BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "extrude_face_region geom=%hef", BM_ELEM_SELECT); BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "translate vec=%v verts=%hv", (float *)dvec, BM_ELEM_SELECT); @@ -887,7 +891,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent } if (rot_src) { - EDBM_op_callf(vc.em, op, "rotate verts=%hv cent=%v mat=%m3", + EDBM_op_callf(vc.em, op, "rotate verts=%hv cent=%v matrix=%m3", BM_ELEM_SELECT, cent, mat); /* also project the source, for retopo workflow */ @@ -896,7 +900,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent } edbm_extrude_edge(vc.obedit, vc.em, BM_ELEM_SELECT, nor); - EDBM_op_callf(vc.em, op, "rotate verts=%hv cent=%v mat=%m3", + EDBM_op_callf(vc.em, op, "rotate verts=%hv cent=%v matrix=%m3", BM_ELEM_SELECT, cent, mat); EDBM_op_callf(vc.em, op, "translate verts=%hv vec=%v", BM_ELEM_SELECT, min); @@ -915,7 +919,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent EDBM_op_init(vc.em, &bmop, op, "create_vert co=%v", min); BMO_op_exec(vc.em->bm, &bmop); - BMO_ITER (v1, &oiter, vc.em->bm, &bmop, "newvertout", BM_VERT) { + BMO_ITER (v1, &oiter, bmop.slots_out, "vert.out", BM_VERT) { BM_vert_select_set(vc.em->bm, v1, TRUE); } @@ -1110,8 +1114,8 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op) } BMO_op_exec(em->bm, &bmop); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faceout", BM_FACE, BM_ELEM_SELECT, TRUE); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "edgeout", BM_EDGE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; @@ -1261,7 +1265,7 @@ static int edbm_vert_connect(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } BMO_op_exec(bm, &bmop); - len = BMO_slot_get(&bmop, "edgeout")->len; + len = BMO_slot_get(bmop.slots_out, "edges.out")->len; if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; } @@ -1301,7 +1305,7 @@ static int edbm_edge_split_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } BMO_op_exec(bm, &bmop); - len = BMO_slot_get(&bmop, "edgeout")->len; + len = BMO_slot_get(bmop.slots_out, "edges.out")->len; if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; } @@ -1339,7 +1343,7 @@ static int edbm_duplicate_exec(bContext *C, wmOperator *op) BMO_op_exec(em->bm, &bmop); EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "newout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; @@ -1405,8 +1409,8 @@ void MESH_OT_flip_normals(wmOperatorType *ot) } static const EnumPropertyItem direction_items[] = { - {DIRECTION_CW, "CW", 0, "Clockwise", ""}, - {DIRECTION_CCW, "CCW", 0, "Counter Clockwise", ""}, + {FALSE, "CW", 0, "Clockwise", ""}, + {TRUE, "CCW", 0, "Counter Clockwise", ""}, {0, NULL, 0, NULL, NULL} }; @@ -1418,7 +1422,7 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op) BMOperator bmop; BMEdge *eed; BMIter iter; - const int do_ccw = RNA_enum_get(op->ptr, "direction") == 1; + const int use_ccw = RNA_boolean_get(op->ptr, "use_ccw"); int tot = 0; if (em->bm->totedgesel == 0) { @@ -1448,17 +1452,17 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Could not find any selected edges that can be rotated"); return OPERATOR_CANCELLED; } - - EDBM_op_init(em, &bmop, op, "rotate_edges edges=%he ccw=%b", BM_ELEM_TAG, do_ccw); + + EDBM_op_init(em, &bmop, op, "rotate_edges edges=%he use_ccw=%b", BM_ELEM_TAG, use_ccw); /* avoids leaving old verts selected which can be a problem running multiple times, * since this means the edges become selected around the face which then attempt to rotate */ - BMO_slot_buffer_hflag_disable(em->bm, &bmop, "edges", BM_EDGE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "edges", BM_EDGE, BM_ELEM_SELECT, TRUE); BMO_op_exec(em->bm, &bmop); /* edges may rotate into hidden vertices, if this does _not_ run we get an ilogical state */ - BMO_slot_buffer_hflag_disable(em->bm, &bmop, "edgeout", BM_EDGE, BM_ELEM_HIDDEN, TRUE); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "edgeout", BM_EDGE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_HIDDEN, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, TRUE); EDBM_selectmode_flush(em); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -1485,7 +1489,7 @@ void MESH_OT_edge_rotate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* props */ - RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate edge around"); + RNA_def_boolean(ot->srna, "use_ccw", FALSE, "Counter Clockwise", ""); } @@ -1553,7 +1557,7 @@ static int edbm_normals_make_consistent_exec(bContext *C, wmOperator *op) /* doflip has to do with bmesh_rationalize_normals, it's an internal * thing */ - if (!EDBM_op_callf(em, op, "recalc_face_normals faces=%hf do_flip=%b", BM_ELEM_SELECT, TRUE)) + if (!EDBM_op_callf(em, op, "recalc_face_normals faces=%hf use_flip=%b", BM_ELEM_SELECT, TRUE)) return OPERATOR_CANCELLED; if (RNA_boolean_get(op->ptr, "inside")) @@ -1590,7 +1594,7 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) ModifierData *md; int mirrx = FALSE, mirry = FALSE, mirrz = FALSE; int i, repeat; - float clipdist = 0.0f; + float clip_dist = 0.0f; int xaxis = RNA_boolean_get(op->ptr, "xaxis"); int yaxis = RNA_boolean_get(op->ptr, "yaxis"); @@ -1616,7 +1620,7 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) if (mmd->flag & MOD_MIR_AXIS_Z) mirrz = TRUE; - clipdist = mmd->tolerance; + clip_dist = mmd->tolerance; } } } @@ -1627,9 +1631,9 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) for (i = 0; i < repeat; i++) { if (!EDBM_op_callf(em, op, - "smooth_vert verts=%hv mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b clipdist=%f " + "smooth_vert verts=%hv mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b clip_dist=%f " "use_axis_x=%b use_axis_y=%b use_axis_z=%b", - BM_ELEM_SELECT, mirrx, mirry, mirrz, clipdist, xaxis, yaxis, zaxis)) + BM_ELEM_SELECT, mirrx, mirry, mirrz, clip_dist, xaxis, yaxis, zaxis)) { return OPERATOR_CANCELLED; } @@ -1670,7 +1674,7 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); - int usex = TRUE, usey = TRUE, usez = TRUE, volume_preservation = TRUE; + int usex = TRUE, usey = TRUE, usez = TRUE, preserve_volume = TRUE; int i, repeat; float lambda; float lambda_border; @@ -1698,14 +1702,14 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) usex = RNA_boolean_get(op->ptr, "use_x"); usey = RNA_boolean_get(op->ptr, "use_y"); usez = RNA_boolean_get(op->ptr, "use_z"); - volume_preservation = RNA_boolean_get(op->ptr, "volume_preservation"); + preserve_volume = RNA_boolean_get(op->ptr, "preserve_volume"); if (!repeat) repeat = 1; for (i = 0; i < repeat; i++) { if (!EDBM_op_callf(em, op, - "smooth_laplacian_vert verts=%hv lambda=%f lambda_border=%f use_x=%b use_y=%b use_z=%b volume_preservation=%b", - BM_ELEM_SELECT, lambda, lambda_border, usex, usey, usez, volume_preservation)) + "smooth_laplacian_vert verts=%hv lambda=%f lambda_border=%f use_x=%b use_y=%b use_z=%b preserve_volume=%b", + BM_ELEM_SELECT, lambda, lambda_border, usex, usey, usez, preserve_volume)) { return OPERATOR_CANCELLED; } @@ -1736,16 +1740,16 @@ void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_int(ot->srna, "repeat", 1, 1, 200, - "Number of iterations to smooth the mesh", "", 1, 200); - RNA_def_float(ot->srna, "lambda", 0.00005f, 0.0000001f, 1000.0f, - "Lambda factor", "", 0.0000001f, 1000.0f); - RNA_def_float(ot->srna, "lambda_border", 0.00005f, 0.0000001f, 1000.0f, - "Lambda factor in border", "", 0.0000001f, 1000.0f); + RNA_def_int(ot->srna, "repeat", 1, 1, 200, + "Number of iterations to smooth the mesh", "", 1, 200); + RNA_def_float(ot->srna, "lambda", 0.00005f, 0.0000001f, 1000.0f, + "Lambda factor", "", 0.0000001f, 1000.0f); + RNA_def_float(ot->srna, "lambda_border", 0.00005f, 0.0000001f, 1000.0f, + "Lambda factor in border", "", 0.0000001f, 1000.0f); RNA_def_boolean(ot->srna, "use_x", 1, "Smooth X Axis", "Smooth object along X axis"); RNA_def_boolean(ot->srna, "use_y", 1, "Smooth Y Axis", "Smooth object along Y axis"); RNA_def_boolean(ot->srna, "use_z", 1, "Smooth Z Axis", "Smooth object along Z axis"); - RNA_def_boolean(ot->srna, "volume_preservation", 1, "Preserve Volume", "Apply volume preservation after smooth"); + RNA_def_boolean(ot->srna, "preserve_volume", 1, "Preserve Volume", "Apply volume preservation after smooth"); } /********************** Smooth/Solid Operators *************************/ @@ -1828,10 +1832,10 @@ static int edbm_rotate_uvs_exec(bContext *C, wmOperator *op) BMOperator bmop; /* get the direction from RNA */ - int dir = RNA_enum_get(op->ptr, "direction"); + const int use_ccw = RNA_boolean_get(op->ptr, "use_ccw"); /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ - EDBM_op_init(em, &bmop, op, "rotate_uvs faces=%hf dir=%i", BM_ELEM_SELECT, dir); + EDBM_op_init(em, &bmop, op, "rotate_uvs faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw); /* execute the operator */ BMO_op_exec(em->bm, &bmop); @@ -1877,10 +1881,10 @@ static int edbm_rotate_colors_exec(bContext *C, wmOperator *op) BMOperator bmop; /* get the direction from RNA */ - int dir = RNA_enum_get(op->ptr, "direction"); + const int use_ccw = RNA_boolean_get(op->ptr, "use_ccw"); /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ - EDBM_op_init(em, &bmop, op, "rotate_colors faces=%hf dir=%i", BM_ELEM_SELECT, dir); + EDBM_op_init(em, &bmop, op, "rotate_colors faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw); /* execute the operator */ BMO_op_exec(em->bm, &bmop); @@ -1936,7 +1940,7 @@ void MESH_OT_uvs_rotate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* props */ - RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate UVs around"); + RNA_def_boolean(ot->srna, "use_ccw", FALSE, "Counter Clockwise", ""); } //void MESH_OT_uvs_mirror(wmOperatorType *ot) @@ -1973,7 +1977,7 @@ void MESH_OT_colors_rotate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* props */ - RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CCW, "Direction", "Direction to rotate edge around"); + RNA_def_boolean(ot->srna, "use_ccw", FALSE, "Counter Clockwise", ""); } void MESH_OT_colors_reverse(wmOperatorType *ot) @@ -2014,7 +2018,7 @@ static int merge_firstlast(BMEditMesh *em, int first, int uvmerge, wmOperator *w return OPERATOR_CANCELLED; if (uvmerge) { - if (!EDBM_op_callf(em, wmop, "pointmerge_facedata verts=%hv snapv=%e", BM_ELEM_SELECT, mergevert)) + if (!EDBM_op_callf(em, wmop, "pointmerge_facedata verts=%hv vert_snap=%e", BM_ELEM_SELECT, mergevert)) return OPERATOR_CANCELLED; } @@ -2174,7 +2178,7 @@ void MESH_OT_merge(wmOperatorType *ot) /* properties */ ot->prop = RNA_def_enum(ot->srna, "type", merge_type_items, 3, "Type", "Merge method to use"); RNA_def_enum_funcs(ot->prop, merge_type_itemf); - RNA_def_boolean(ot->srna, "uvs", 1, "UVs", "Move UVs according to merge"); + RNA_def_boolean(ot->srna, "uvs", 0, "UVs", "Move UVs according to merge"); } @@ -2183,7 +2187,7 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op) Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); BMOperator bmop; - const float mergedist = RNA_float_get(op->ptr, "mergedist"); + const float threshold = RNA_float_get(op->ptr, "threshold"); int use_unselected = RNA_boolean_get(op->ptr, "use_unselected"); int totvert_orig = em->bm->totvert; int count; @@ -2191,7 +2195,7 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op) if (use_unselected) { EDBM_op_init(em, &bmop, op, "automerge verts=%hv dist=%f", - BM_ELEM_SELECT, mergedist); + BM_ELEM_SELECT, threshold); BMO_op_exec(em->bm, &bmop); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -2201,10 +2205,10 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op) else { EDBM_op_init(em, &bmop, op, "find_doubles verts=%hv dist=%f", - BM_ELEM_SELECT, mergedist); + BM_ELEM_SELECT, threshold); BMO_op_exec(em->bm, &bmop); - if (!EDBM_op_callf(em, op, "weld_verts targetmap=%s", &bmop, "targetmapout")) { + if (!EDBM_op_callf(em, op, "weld_verts targetmap=%S", &bmop, "targetmap.out")) { BMO_op_finish(em->bm, &bmop); return OPERATOR_CANCELLED; } @@ -2236,8 +2240,7 @@ void MESH_OT_remove_doubles(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_float(ot->srna, "mergedist", 0.0001f, 0.000001f, 50.0f, - "Merge Distance", + RNA_def_float(ot->srna, "threshold", 0.0001f, 0.000001f, 50.0f, "Merge Distance", "Minimum distance between elements to merge", 0.00001, 10.0); RNA_def_boolean(ot->srna, "use_unselected", 0, "Unselected", "Merge selected to other unselected vertices"); } @@ -2305,7 +2308,9 @@ static int edbm_select_vertex_path_exec(bContext *C, wmOperator *op) } /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ - EDBM_op_init(em, &bmop, op, "shortest_path startv=%e endv=%e type=%i", svert, evert, type); + EDBM_op_init(em, &bmop, op, + "shortest_path vert_start=%e vert_end=%e type=%i", + svert, evert, type); /* execute the operator */ BMO_op_exec(em->bm, &bmop); @@ -2314,7 +2319,7 @@ static int edbm_select_vertex_path_exec(bContext *C, wmOperator *op) /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */ /* select the output */ - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "vertout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, TRUE); /* finish the operator */ if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -2439,7 +2444,7 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op) totshape = CustomData_number_of_layers(&em->bm->vdata, CD_SHAPEKEY); if (totshape == 0 || shape < 0 || shape >= totshape) return OPERATOR_CANCELLED; - + /* get shape key - needed for finding reference shape (for add mode only) */ if (key) { kb = BLI_findlink(&key->block, shape); @@ -2506,6 +2511,22 @@ static EnumPropertyItem *shape_itemf(bContext *C, PointerRNA *UNUSED(ptr), Prop return item; } +static void edbm_blend_from_shape_ui(bContext *C, wmOperator *op) +{ + uiLayout *layout = op->layout; + PointerRNA ptr; + Object *obedit = CTX_data_edit_object(C); + Mesh *me = obedit->data; + PointerRNA ptr_key; + + RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); + RNA_id_pointer_create((ID *)me->key, &ptr_key); + + uiItemPointerR(layout, &ptr, "shape", &ptr_key, "key_blocks", "", ICON_SHAPEKEY_DATA); + uiItemR(layout, &ptr, "blend", 0, NULL, ICON_NONE); + uiItemR(layout, &ptr, "add", 0, NULL, ICON_NONE); +} + void MESH_OT_blend_from_shape(wmOperatorType *ot) { PropertyRNA *prop; @@ -2518,7 +2539,8 @@ void MESH_OT_blend_from_shape(wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_blend_from_shape_exec; - ot->invoke = WM_operator_props_popup; +// ot->invoke = WM_operator_props_popup_call; /* disable because search popup closes too easily */ + ot->ui = edbm_blend_from_shape_ui; ot->poll = ED_operator_editmesh; /* flags */ @@ -2631,13 +2653,13 @@ static int edbm_solidify_exec(bContext *C, wmOperator *op) /* deselect only the faces in the region to be solidified (leave wire * edges and loose verts selected, as there will be no corresponding * geometry selected below) */ - BMO_slot_buffer_hflag_disable(bm, &bmop, "geom", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_disable(bm, bmop.slots_in, "geom", BM_FACE, BM_ELEM_SELECT, TRUE); /* run the solidify operator */ BMO_op_exec(bm, &bmop); /* select the newly generated faces */ - BMO_slot_buffer_hflag_enable(bm, &bmop, "geomout", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; @@ -2869,6 +2891,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) float isect = 0.0f; int len = 0, isected, i; short numcuts = 1, mode = RNA_int_get(op->ptr, "type"); + BMOpSlot *slot_edge_percents; /* allocd vars */ float (*screen_vert_coords)[2], (*sco)[2], (*mouse_path)[2]; @@ -2923,6 +2946,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) } /* store percentage of edge cut for KNIFE_EXACT here.*/ + slot_edge_percents = BMO_slot_get(bmop.slots_in, "edge_percents"); for (be = BM_iter_new(&iter, bm, BM_EDGES_OF_MESH, NULL); be; be = BM_iter_step(&iter)) { int is_cut = FALSE; if (BM_elem_flag_test(be, BM_ELEM_SELECT)) { @@ -2935,9 +2959,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) if (isect != 0.0f) { if (mode != KNIFE_MULTICUT && mode != KNIFE_MIDPOINT) { - BMO_slot_map_float_insert(bm, &bmop, - "edgepercents", - be, isect); + BMO_slot_map_float_insert(&bmop, slot_edge_percents, be, isect); } } } @@ -2952,16 +2974,16 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) MEM_freeN(mouse_path); - BMO_slot_buffer_from_enabled_flag(bm, &bmop, "edges", BM_EDGE, ELE_EDGE_CUT); + BMO_slot_buffer_from_enabled_flag(bm, &bmop, bmop.slots_in, "edges", BM_EDGE, ELE_EDGE_CUT); if (mode == KNIFE_MIDPOINT) numcuts = 1; - BMO_slot_int_set(&bmop, "numcuts", numcuts); + BMO_slot_int_set(bmop.slots_in, "cuts", numcuts); - BMO_slot_int_set(&bmop, "quadcornertype", SUBD_STRAIGHT_CUT); - BMO_slot_bool_set(&bmop, "use_singleedge", FALSE); - BMO_slot_bool_set(&bmop, "use_gridfill", FALSE); + BMO_slot_int_set(bmop.slots_in, "quad_corner_type", SUBD_STRAIGHT_CUT); + BMO_slot_bool_set(bmop.slots_in, "use_single_edge", FALSE); + BMO_slot_bool_set(bmop.slots_in, "use_grid_fill", FALSE); - BMO_slot_float_set(&bmop, "radius", 0); + BMO_slot_float_set(bmop.slots_in, "radius", 0); BMO_op_exec(bm, &bmop); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -3007,6 +3029,8 @@ static int mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh BMesh *bm_new; bm_new = BM_mesh_create(&bm_mesh_allocsize_default); + BM_mesh_elem_toolflags_ensure(bm_new); /* needed for 'duplicate' bmo */ + CustomData_copy(&bm_old->vdata, &bm_new->vdata, CD_MASK_BMESH, CD_CALLOC, 0); CustomData_copy(&bm_old->edata, &bm_new->edata, CD_MASK_BMESH, CD_CALLOC, 0); CustomData_copy(&bm_old->ldata, &bm_new->ldata, CD_MASK_BMESH, CD_CALLOC, 0); @@ -3302,7 +3326,7 @@ static int edbm_fill_exec(bContext *C, wmOperator *op) BMO_op_exec(em->bm, &bmop); /* select new geometry */ - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "geomout", BM_FACE | BM_EDGE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_FACE | BM_EDGE, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; @@ -3574,7 +3598,7 @@ static int edbm_split_exec(bContext *C, wmOperator *op) EDBM_op_init(em, &bmop, op, "split geom=%hvef use_only_faces=%b", BM_ELEM_SELECT, FALSE); BMO_op_exec(em->bm, &bmop); BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "geomout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; } @@ -3612,14 +3636,14 @@ static int edbm_spin_exec(bContext *C, wmOperator *op) float cent[3], axis[3], imat[3][3]; float d[3] = {0.0f, 0.0f, 0.0f}; int steps, dupli; - float degr; + float angle; RNA_float_get_array(op->ptr, "center", cent); RNA_float_get_array(op->ptr, "axis", axis); steps = RNA_int_get(op->ptr, "steps"); - degr = RNA_float_get(op->ptr, "degrees"); + angle = RNA_float_get(op->ptr, "angle"); //if (ts->editbutflag & B_CLOCKWISE) - degr = -degr; + angle = -angle; dupli = RNA_boolean_get(op->ptr, "dupli"); /* undo object transformation */ @@ -3629,14 +3653,14 @@ static int edbm_spin_exec(bContext *C, wmOperator *op) mul_m3_v3(imat, axis); if (!EDBM_op_init(em, &spinop, op, - "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i ang=%f do_dupli=%b", - BM_ELEM_SELECT, cent, axis, d, steps, degr, dupli)) + "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i angle=%f use_duplicate=%b", + BM_ELEM_SELECT, cent, axis, d, steps, angle, dupli)) { return OPERATOR_CANCELLED; } BMO_op_exec(bm, &spinop); EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BMO_slot_buffer_hflag_enable(bm, &spinop, "lastout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(bm, spinop.slots_out, "geom_last.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &spinop, op, TRUE)) { return OPERATOR_CANCELLED; } @@ -3661,6 +3685,8 @@ static int edbm_spin_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) void MESH_OT_spin(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Spin"; ot->description = "Extrude selected vertices in a circle around the cursor in indicated viewport"; @@ -3677,7 +3703,8 @@ void MESH_OT_spin(wmOperatorType *ot) /* props */ RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, INT_MAX); RNA_def_boolean(ot->srna, "dupli", 0, "Dupli", "Make Duplicates"); - RNA_def_float(ot->srna, "degrees", 90.0f, -FLT_MAX, FLT_MAX, "Degrees", "Degrees", -360.0f, 360.0f); + prop = RNA_def_float(ot->srna, "angle", DEG2RADF(90.0f), -FLT_MAX, FLT_MAX, "Angle", "Angle", DEG2RADF(-360.0f), DEG2RADF(360.0f)); + RNA_def_property_subtype(prop, PROP_ANGLE); RNA_def_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX); RNA_def_float_vector(ot->srna, "axis", 3, NULL, -FLT_MAX, FLT_MAX, "Axis", "Axis in global view space", -1.0f, 1.0f); @@ -3715,15 +3742,11 @@ static int edbm_screw_exec(bContext *C, wmOperator *op) v1 = NULL; v2 = NULL; for (eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL); eve; eve = BM_iter_step(&iter)) { - valence = 0; - for (eed = BM_iter_new(&eiter, em->bm, BM_EDGES_OF_VERT, eve); eed; eed = BM_iter_step(&eiter)) { - if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { valence++; } - } if (valence == 1) { @@ -3753,14 +3776,14 @@ static int edbm_screw_exec(bContext *C, wmOperator *op) negate_v3(dvec); if (!EDBM_op_init(em, &spinop, op, - "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i ang=%f do_dupli=%b", + "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i angle=%f use_duplicate=%b", BM_ELEM_SELECT, cent, axis, dvec, turns * steps, 360.0f * turns, FALSE)) { return OPERATOR_CANCELLED; } BMO_op_exec(bm, &spinop); EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BMO_slot_buffer_hflag_enable(bm, &spinop, "lastout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(bm, spinop.slots_out, "geom_last.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &spinop, op, TRUE)) { return OPERATOR_CANCELLED; } @@ -4602,11 +4625,15 @@ void MESH_OT_noise(wmOperatorType *ot) RNA_def_float(ot->srna, "factor", 0.1f, -FLT_MAX, FLT_MAX, "Factor", "", 0.0f, 1.0f); } +#define NEW_BEVEL 1 + typedef struct { BMEditMesh *em; BMBackup mesh_backup; +#ifndef NEW_BEVEL float *weights; int li; +#endif int mcenter[2]; float initial_length; float pixel_size; /* use when mouse input is interpreted as spatial distance */ @@ -4619,13 +4646,25 @@ typedef struct { static void edbm_bevel_update_header(wmOperator *op, bContext *C) { +#ifdef NEW_BEVEL + static char str[] = "Confirm: Enter/LClick, Cancel: (Esc/RMB), offset: %s, segments: %d"; +#else static char str[] = "Confirm: Enter/LClick, Cancel: (Esc/RMB), factor: %s, Use Dist (D): %s: Use Even (E): %s"; + BevelData *opdata = op->customdata; +#endif char msg[HEADER_LENGTH]; ScrArea *sa = CTX_wm_area(C); - BevelData *opdata = op->customdata; if (sa) { +#ifdef NEW_BEVEL + char offset_str[NUM_STR_REP_LEN]; + BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "offset")); + BLI_snprintf(msg, HEADER_LENGTH, str, + offset_str, + RNA_int_get(op->ptr, "segments") + ); +#else char factor_str[NUM_STR_REP_LEN]; if (hasNumInput(&opdata->num_input)) outputNumInput(&opdata->num_input, factor_str); @@ -4636,11 +4675,13 @@ static void edbm_bevel_update_header(wmOperator *op, bContext *C) RNA_boolean_get(op->ptr, "use_dist") ? "On" : "Off", RNA_boolean_get(op->ptr, "use_even") ? "On" : "Off" ); +#endif ED_area_headerprint(sa, msg); } } +#ifndef NEW_BEVEL static void edbm_bevel_recalc_weights(wmOperator *op) { float df, s, ftot; @@ -4668,15 +4709,20 @@ static void edbm_bevel_recalc_weights(wmOperator *op) mul_vn_fl(opdata->weights, recursion, 1.0f / (float)ftot); } +#endif static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); +#ifdef NEW_BEVEL + BevelData *opdata; +#else BMIter iter; BMEdge *eed; BevelData *opdata; int li; +#endif if (em == NULL) { return 0; @@ -4684,6 +4730,7 @@ static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal) op->customdata = opdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator"); +#ifndef NEW_BEVEL BM_data_layer_add(em->bm, &em->bm->edata, CD_PROP_FLT); li = CustomData_number_of_layers(&em->bm->edata, CD_PROP_FLT) - 1; @@ -4693,10 +4740,12 @@ static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal) *dv = d; } - - opdata->em = em; + opdata->li = li; opdata->weights = NULL; +#endif + + opdata->em = em; opdata->is_modal = is_modal; opdata->shift_factor = -1.0f; @@ -4706,7 +4755,9 @@ static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal) /* avoid the cost of allocating a bm copy */ if (is_modal) opdata->mesh_backup = EDBM_redo_state_store(em); +#ifndef NEW_BEVEL edbm_bevel_recalc_weights(op); +#endif return 1; } @@ -4716,6 +4767,35 @@ static int edbm_bevel_calc(bContext *C, wmOperator *op) BevelData *opdata = op->customdata; BMEditMesh *em = opdata->em; BMOperator bmop; +#ifdef NEW_BEVEL + float offset = RNA_float_get(op->ptr, "offset"); + int segments = RNA_int_get(op->ptr, "segments"); + + /* revert to original mesh */ + if (opdata->is_modal) { + EDBM_redo_state_restore(opdata->mesh_backup, em, FALSE); + } + + if (!EDBM_op_init(em, &bmop, op, + "bevel geom=%hev offset=%f segments=%i", + BM_ELEM_SELECT, offset, segments)) + { + return 0; + } + + BMO_op_exec(em->bm, &bmop); + + if (offset != 0.0f) { + /* not essential, but we may have some loose geometry that + * won't get bevel'd and better not leave it selected */ + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); + } + + /* no need to de-select existing geometry */ + if (!EDBM_op_finish(em, &bmop, op, TRUE)) + return 0; +#else int i; float factor = RNA_float_get(op->ptr, "percent") /*, dfac */ /* UNUSED */; @@ -4743,6 +4823,7 @@ static int edbm_bevel_calc(bContext *C, wmOperator *op) if (!EDBM_op_finish(em, &bmop, op, TRUE)) return 0; } +#endif EDBM_mesh_normals_update(opdata->em); @@ -4760,10 +4841,12 @@ static void edbm_bevel_exit(bContext *C, wmOperator *op) if (sa) { ED_area_headerprint(sa, NULL); } +#ifndef NEW_BEVEL BM_data_layer_free_n(opdata->em->bm, &opdata->em->bm->edata, CD_PROP_FLT, opdata->li); if (opdata->weights) MEM_freeN(opdata->weights); +#endif if (opdata->is_modal) { EDBM_redo_state_free(&opdata->mesh_backup, NULL, FALSE); } @@ -4844,7 +4927,11 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event) static float edbm_bevel_mval_factor(wmOperator *op, wmEvent *event) { BevelData *opdata = op->customdata; +#ifdef NEW_BEVEL + int use_dist = TRUE; +#else int use_dist = RNA_boolean_get(op->ptr, "use_dist"); +#endif float mdiff[2]; float factor; @@ -4861,8 +4948,13 @@ static float edbm_bevel_mval_factor(wmOperator *op, wmEvent *event) /* Fake shift-transform... */ if (event->shift) { - if (opdata->shift_factor < 0.0f) + if (opdata->shift_factor < 0.0f) { +#ifdef NEW_BEVEL + opdata->shift_factor = RNA_float_get(op->ptr, "factor"); +#else opdata->shift_factor = RNA_float_get(op->ptr, "percent"); +#endif + } factor = (factor - opdata->shift_factor) * 0.1f + opdata->shift_factor; } else if (opdata->shift_factor >= 0.0f) @@ -4882,12 +4974,23 @@ static float edbm_bevel_mval_factor(wmOperator *op, wmEvent *event) static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) { BevelData *opdata = op->customdata; + int segments = RNA_int_get(op->ptr, "segments"); if (event->val == KM_PRESS) { /* Try to handle numeric inputs... */ - float factor; +#ifdef NEW_BEVEL if (handleNumInput(&opdata->num_input, event)) { + float value = RNA_float_get(op->ptr, "offset"); + applyNumInput(&opdata->num_input, &value); + RNA_float_set(op->ptr, "offset", value); + edbm_bevel_calc(C, op); + edbm_bevel_update_header(op, C); + return OPERATOR_RUNNING_MODAL; + } +#else + if (handleNumInput(&opdata->num_input, event)) { + float factor = RNA_float_get(op->ptr, "percent"); applyNumInput(&opdata->num_input, &factor); CLAMP(factor, 0.0f, 1.0f); RNA_float_set(op->ptr, "percent", factor); @@ -4896,6 +4999,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) edbm_bevel_update_header(op, C); return OPERATOR_RUNNING_MODAL; } +#endif } switch (event->type) { @@ -4907,7 +5011,11 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) case MOUSEMOVE: if (!hasNumInput(&opdata->num_input)) { const float factor = edbm_bevel_mval_factor(op, event); +#ifdef NEW_BEVEL + RNA_float_set(op->ptr, "offset", factor); +#else RNA_float_set(op->ptr, "percent", factor); +#endif edbm_bevel_calc(C, op); edbm_bevel_update_header(op, C); @@ -4921,6 +5029,30 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) edbm_bevel_exit(C, op); return OPERATOR_FINISHED; +#ifdef NEW_BEVEL + case WHEELUPMOUSE: /* change number of segments */ + case PAGEUPKEY: + if (event->val == KM_RELEASE) + break; + + segments++; + RNA_int_set(op->ptr, "segments", segments); + edbm_bevel_calc(C, op); + edbm_bevel_update_header(op, C); + break; + + case WHEELDOWNMOUSE: /* change number of segments */ + case PAGEDOWNKEY: + if (event->val == KM_RELEASE) + break; + + segments = max_ii(segments - 1, 1); + RNA_int_set(op->ptr, "segments", segments); + edbm_bevel_calc(C, op); + edbm_bevel_update_header(op, C); + break; + +#else case EKEY: if (event->val == KM_PRESS) { int use_even = RNA_boolean_get(op->ptr, "use_even"); @@ -4945,6 +5077,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) edbm_bevel_update_header(op, C); } break; +#endif } return OPERATOR_RUNNING_MODAL; @@ -4967,6 +5100,10 @@ void MESH_OT_bevel(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING; +#ifdef NEW_BEVEL + RNA_def_float(ot->srna, "offset", 0.0f, -FLT_MAX, FLT_MAX, "Offset", "", 0.0f, 1.0f); + RNA_def_int(ot->srna, "segments", 1, 1, 50, "Segments", "Segments for curved edge", 1, 8); +#else /* take note, used as a factor _and_ a distance depending on 'use_dist' */ RNA_def_float(ot->srna, "percent", 0.0f, -FLT_MAX, FLT_MAX, "Percentage", "", 0.0f, 1.0f); /* XXX, disabled for 2.63 release, needs to work much better without overlap before we can give to users. */ @@ -4974,6 +5111,7 @@ void MESH_OT_bevel(wmOperatorType *ot) RNA_def_boolean(ot->srna, "use_even", FALSE, "Even", "Calculate evenly spaced bevel"); RNA_def_boolean(ot->srna, "use_dist", FALSE, "Distance", "Interpret the percent in blender units"); +#endif } @@ -4994,7 +5132,7 @@ static int edbm_bridge_edge_loops_exec(bContext *C, wmOperator *op) /* when merge is used the edges are joined and remain selected */ if (use_merge == FALSE) { EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faceout", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); } if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -5167,11 +5305,11 @@ static int edbm_inset_calc(bContext *C, wmOperator *op) if (use_select_inset) { /* deselect original faces/verts */ EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faceout", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); } else { BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE, BM_ELEM_SELECT, FALSE); - BMO_slot_buffer_hflag_disable(em->bm, &bmop, "faceout", BM_FACE, BM_ELEM_SELECT, FALSE); + BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, FALSE); /* re-select faces so the verts and edges get selected too */ BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, TRUE, BM_ELEM_SELECT); } @@ -5234,9 +5372,10 @@ static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event) if (event->val == KM_PRESS) { /* Try to handle numeric inputs... */ - float amounts[2]; if (handleNumInput(&opdata->num_input, event)) { + float amounts[2] = {RNA_float_get(op->ptr, "thickness"), + RNA_float_get(op->ptr, "depth")}; applyNumInput(&opdata->num_input, amounts); amounts[0] = max_ff(amounts[0], 0.0f); RNA_float_set(op->ptr, "thickness", amounts[0]); @@ -5428,7 +5567,7 @@ static int edbm_wireframe_exec(bContext *C, wmOperator *op) if (use_replace) { BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, FALSE); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faces", BM_FACE, BM_ELEM_TAG, FALSE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_in, "faces", BM_FACE, BM_ELEM_TAG, FALSE); BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "delete geom=%hvef context=%i", @@ -5436,7 +5575,7 @@ static int edbm_wireframe_exec(bContext *C, wmOperator *op) } BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faceout", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; @@ -5499,8 +5638,8 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) /* Delete unused vertices, edges, and faces */ if (RNA_boolean_get(op->ptr, "delete_unused")) { - if (!EDBM_op_callf(em, op, "delete geom=%s context=%i", - &bmop, "unused_geom", DEL_ONLYTAGGED)) + if (!EDBM_op_callf(em, op, "delete geom=%S context=%i", + &bmop, "geom_unused.out", DEL_ONLYTAGGED)) { EDBM_op_finish(em, &bmop, op, TRUE); return OPERATOR_CANCELLED; @@ -5509,8 +5648,8 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) /* Delete hole edges/faces */ if (RNA_boolean_get(op->ptr, "make_holes")) { - if (!EDBM_op_callf(em, op, "delete geom=%s context=%i", - &bmop, "holes_geom", DEL_ONLYTAGGED)) + if (!EDBM_op_callf(em, op, "delete geom=%S context=%i", + &bmop, "geom_holes.out", DEL_ONLYTAGGED)) { EDBM_op_finish(em, &bmop, op, TRUE); return OPERATOR_CANCELLED; @@ -5519,8 +5658,8 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) /* Merge adjacent triangles */ if (RNA_boolean_get(op->ptr, "join_triangles")) { - if (!EDBM_op_callf(em, op, "join_triangles faces=%s limit=%f", - &bmop, "geomout", + if (!EDBM_op_callf(em, op, "join_triangles faces=%S limit=%f", + &bmop, "geom.out", RNA_float_get(op->ptr, "limit"))) { EDBM_op_finish(em, &bmop, op, TRUE); diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index ef3d8db4156..2cf63586142 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -263,11 +263,13 @@ int EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...) return EDBM_op_finish(em, &bmop, op, TRUE); } -int EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op, const char *selectslot, const char *fmt, ...) +int EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op, const char *select_slot_out, const char *fmt, ...) { + BMOpSlot *slot_select_out; BMesh *bm = em->bm; BMOperator bmop; va_list list; + char hflag; va_start(list, fmt); @@ -283,9 +285,12 @@ int EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op, const char *selects BMO_op_exec(bm, &bmop); + slot_select_out = BMO_slot_get(bmop.slots_out, select_slot_out); + hflag = slot_select_out->slot_subtype.elem & BM_ALL_NOLOOP; + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, selectslot, BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, select_slot_out, hflag, BM_ELEM_SELECT, TRUE); va_end(list); return EDBM_op_finish(em, &bmop, op, TRUE); @@ -494,11 +499,11 @@ void EDBM_select_more(BMEditMesh *em) int use_faces = em->selectmode == SCE_SELECT_FACE; BMO_op_initf(em->bm, &bmop, BMO_FLAG_DEFAULTS, - "region_extend geom=%hvef constrict=%b use_faces=%b", + "region_extend geom=%hvef use_constrict=%b use_faces=%b", BM_ELEM_SELECT, FALSE, use_faces); BMO_op_exec(em->bm, &bmop); /* don't flush selection in edge/vertex mode */ - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "geomout", BM_ALL, BM_ELEM_SELECT, use_faces ? TRUE : FALSE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? TRUE : FALSE); BMO_op_finish(em->bm, &bmop); EDBM_select_flush(em); @@ -510,11 +515,11 @@ void EDBM_select_less(BMEditMesh *em) int use_faces = em->selectmode == SCE_SELECT_FACE; BMO_op_initf(em->bm, &bmop, BMO_FLAG_DEFAULTS, - "region_extend geom=%hvef constrict=%b use_faces=%b", + "region_extend geom=%hvef use_constrict=%b use_faces=%b", BM_ELEM_SELECT, TRUE, use_faces); BMO_op_exec(em->bm, &bmop); /* don't flush selection in edge/vertex mode */ - BMO_slot_buffer_hflag_disable(em->bm, &bmop, "geomout", BM_ALL, BM_ELEM_SELECT, use_faces ? TRUE : FALSE); + BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? TRUE : FALSE); BMO_op_finish(em->bm, &bmop); EDBM_selectmode_flush(em); diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 82b785e5785..e335c909e8e 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -80,9 +80,6 @@ int EDBM_op_finish(struct BMEditMesh *em, struct BMOperator *bmop, void EDBM_flag_disable_all(struct BMEditMesh *em, const char hflag); void EDBM_stats_update(struct BMEditMesh *em); -/* TODO, move to math_geometry.c */ -float labda_PdistVL2Dfl(const float v1[3], const float v2[3], const float v3[3]); - /* ******************** editface.c */ void MESH_OT_separate(struct wmOperatorType *ot); @@ -129,6 +126,7 @@ void MESH_OT_faces_select_linked_flat(struct wmOperatorType *ot); void MESH_OT_edges_select_sharp(struct wmOperatorType *ot); void MESH_OT_select_shortest_path(struct wmOperatorType *ot); void MESH_OT_select_similar(struct wmOperatorType *ot); +void MESH_OT_select_mode(struct wmOperatorType *ot); void MESH_OT_select_random(struct wmOperatorType *ot); void MESH_OT_loop_multi_select(struct wmOperatorType *ot); void MESH_OT_mark_seam(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c index f6f8eee0a69..83a1261e981 100644 --- a/source/blender/editors/mesh/mesh_navmesh.c +++ b/source/blender/editors/mesh/mesh_navmesh.c @@ -341,7 +341,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, co[1] = bmin[1] + v[1] * ch; co[2] = bmin[2] + v[2] * cs; SWAP(float, co[1], co[2]); - BM_vert_create(em->bm, co, NULL); + BM_vert_create(em->bm, co, NULL, 0); } /* create custom data layer to save polygon idx */ @@ -372,7 +372,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, for (j = nv; j < ndv; j++) { copy_v3_v3(co, &dverts[3 * (vbase + j)]); SWAP(float, co[1], co[2]); - BM_vert_create(em->bm, co, NULL); + BM_vert_create(em->bm, co, NULL, 0); } EDBM_index_arrays_init(em, 1, 0, 0); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index d319fdcca26..a413a60412c 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -129,6 +129,7 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_edge_face_add); WM_operatortype_append(MESH_OT_select_shortest_path); WM_operatortype_append(MESH_OT_select_similar); + WM_operatortype_append(MESH_OT_select_mode); WM_operatortype_append(MESH_OT_loop_multi_select); WM_operatortype_append(MESH_OT_mark_seam); WM_operatortype_append(MESH_OT_mark_sharp); @@ -277,13 +278,21 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) /* standard mouse selection goes via space_view3d */ kmi = WM_keymap_add_item(keymap, "MESH_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", FALSE); kmi = WM_keymap_add_item(keymap, "MESH_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, 0); - RNA_boolean_set(kmi->ptr, "extend", TRUE); + RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", TRUE); kmi = WM_keymap_add_item(keymap, "MESH_OT_edgering_select", SELECTMOUSE, KM_PRESS, KM_ALT | KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", FALSE); kmi = WM_keymap_add_item(keymap, "MESH_OT_edgering_select", SELECTMOUSE, KM_PRESS, KM_SHIFT | KM_ALT | KM_CTRL, 0); - RNA_boolean_set(kmi->ptr, "extend", TRUE); + RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", TRUE); WM_keymap_add_item(keymap, "MESH_OT_select_shortest_path", SELECTMOUSE, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 9fc4e0a906d..7c4a547debc 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -210,8 +210,8 @@ float ED_object_new_primitive_matrix(bContext *C, Object *obedit, invert_m3_m3(imat, mat); mul_m3_v3(imat, primmat[3]); - if (v3d) { - float dia = ED_view3d_grid_scale(scene, v3d, NULL); + { + const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : ED_scene_grid_scale(scene, NULL); if (apply_diameter) { primmat[0][0] *= dia; @@ -271,7 +271,7 @@ int ED_object_add_generic_get_opts(bContext *C, wmOperator *op, float loc[3], fl if (RNA_struct_property_is_set(op->ptr, "enter_editmode") && enter_editmode) *enter_editmode = RNA_boolean_get(op->ptr, "enter_editmode"); else { - *enter_editmode = U.flag & USER_ADD_EDITMODE; + *enter_editmode = (U.flag & USER_ADD_EDITMODE) != 0; RNA_boolean_set(op->ptr, "enter_editmode", *enter_editmode); } } @@ -1136,7 +1136,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, if (dupli_gh) BLI_ghash_insert(dupli_gh, dob, ob); if (parent_gh) - BLI_ghash_insert(parent_gh, BLI_ghashutil_pairalloc(dob->ob, SET_INT_IN_POINTER(dob->index)), ob); + BLI_ghash_insert(parent_gh, BLI_ghashutil_pairalloc(dob->ob, SET_INT_IN_POINTER(dob->persistent_id[0])), ob); } if (use_hierarchy) { @@ -1150,7 +1150,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, /* find parent that was also made real */ if (ob_src_par) { - GHashPair *pair = BLI_ghashutil_pairalloc(ob_src_par, SET_INT_IN_POINTER(dob->index)); + GHashPair *pair = BLI_ghashutil_pairalloc(ob_src_par, SET_INT_IN_POINTER(dob->persistent_id[0])); ob_dst_par = BLI_ghash_lookup(parent_gh, pair); BLI_ghashutil_pairfree(pair); } diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index ee3c66b6eac..e144c38a350 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -114,7 +114,7 @@ typedef struct { } MultiresBakeRender; typedef void (*MPassKnownData)(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, - const int face_index, const int lvl, const float st[2], + ImBuf *ibuf, const int face_index, const int lvl, const float st[2], float tangmat[3][3], const int x, const int y); typedef void * (*MInitBakeData)(MultiresBakeRender *bkr, Image *ima); @@ -133,6 +133,7 @@ typedef struct { DerivedMesh *lores_dm, *hires_dm; int lvl; void *bake_data; + ImBuf *ibuf; MPassKnownData pass_data; } MResolvePixelData; @@ -257,7 +258,7 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y) /* sequence end */ data->pass_data(data->lores_dm, data->hires_dm, data->bake_data, - data->face_index, data->lvl, st, to_tang, x, y); + data->ibuf, data->face_index, data->lvl, st, to_tang, x, y); } static void set_rast_triangle(const MBakeRast *bake_rast, const int x, const int y) @@ -368,7 +369,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, MPassKnownData MInitBakeData initBakeData, MApplyBakeData applyBakeData, MFreeBakeData freeBakeData) { DerivedMesh *dm = bkr->lores_dm; - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); const int lvl = bkr->lvl; const int tot_face = dm->getNumTessFaces(dm); MVert *mvert = dm->getVertArray(dm); @@ -414,6 +415,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, MPassKnownData continue; data.face_index = f; + data.ibuf = ibuf; /* might support other forms of diagonal splits later on such as * split by shortest diagonal.*/ @@ -449,32 +451,8 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, MPassKnownData if (freeBakeData) freeBakeData(data.bake_data); } -} -static void interp_bilinear_quad_data(float data[4][3], float u, float v, float res[3]) -{ - float vec[3]; - - copy_v3_v3(res, data[0]); - mul_v3_fl(res, (1 - u) * (1 - v)); - copy_v3_v3(vec, data[1]); - mul_v3_fl(vec, u * (1 - v)); add_v3_v3(res, vec); - copy_v3_v3(vec, data[2]); - mul_v3_fl(vec, u * v); add_v3_v3(res, vec); - copy_v3_v3(vec, data[3]); - mul_v3_fl(vec, (1 - u) * v); add_v3_v3(res, vec); -} - -static void interp_barycentric_tri_data(float data[3][3], float u, float v, float res[3]) -{ - float vec[3]; - - copy_v3_v3(res, data[0]); - mul_v3_fl(res, u); - copy_v3_v3(vec, data[1]); - mul_v3_fl(vec, v); add_v3_v3(res, vec); - copy_v3_v3(vec, data[2]); - mul_v3_fl(vec, 1.0f - u - v); add_v3_v3(res, vec); + BKE_image_release_ibuf(ima, ibuf, NULL); } /* mode = 0: interpolate normals, @@ -507,7 +485,7 @@ static void interp_bilinear_grid(CCGKey *key, CCGElem *grid, float crn_x, float copy_v3_v3(data[3], CCG_grid_elem_co(key, grid, x0, y1)); } - interp_bilinear_quad_data(data, u, v, res); + interp_bilinear_quad_v3(data, u, v, res); } static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm, @@ -579,7 +557,7 @@ static void interp_bilinear_mface(DerivedMesh *dm, MFace *mface, const float u, dm->getVertCo(dm, mface->v4, data[3]); } - interp_bilinear_quad_data(data, u, v, res); + interp_bilinear_quad_v3(data, u, v, res); } /* mode = 0: interpolate normals, @@ -599,13 +577,13 @@ static void interp_barycentric_mface(DerivedMesh *dm, MFace *mface, const float dm->getVertCo(dm, mface->v3, data[2]); } - interp_barycentric_tri_data(data, u, v, res); + interp_barycentric_tri_v3(data, u, v, res); } static void *init_heights_data(MultiresBakeRender *bkr, Image *ima) { MHeightBakeData *height_data; - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); DerivedMesh *lodm = bkr->lores_dm; height_data = MEM_callocN(sizeof(MHeightBakeData), "MultiresBake heightData"); @@ -635,6 +613,8 @@ static void *init_heights_data(MultiresBakeRender *bkr, Image *ima) height_data->orig_index_mf_to_mpoly = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX); height_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX); + BKE_image_release_ibuf(ima, ibuf, NULL); + return (void *)height_data; } @@ -661,7 +641,7 @@ static void free_normal_data(void *bake_data) static void apply_heights_data(void *bake_data) { MHeightBakeData *height_data = (MHeightBakeData *)bake_data; - ImBuf *ibuf = BKE_image_get_ibuf(height_data->ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(height_data->ima, NULL, NULL); int x, y, i; float height, *heights = height_data->heights; float min = height_data->height_min, max = height_data->height_max; @@ -693,6 +673,8 @@ static void apply_heights_data(void *bake_data) } ibuf->userflags = IB_RECT_INVALID | IB_DISPLAY_BUFFER_INVALID; + + BKE_image_release_ibuf(height_data->ima, ibuf, NULL); } static void free_heights_data(void *bake_data) @@ -713,13 +695,11 @@ static void free_heights_data(void *bake_data) * mesh to make texture smoother) let's call this point p0 and n. * - height wound be dot(n, p1-p0) */ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, - const int face_index, const int lvl, const float st[2], + ImBuf *ibuf, const int face_index, const int lvl, const float st[2], float UNUSED(tangmat[3][3]), const int x, const int y) { MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE); MFace mface; - Image *ima = mtface[face_index].tpage; - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); MHeightBakeData *height_data = (MHeightBakeData *)bake_data; float uv[2], *st0, *st1, *st2, *st3; int pixel = ibuf->x * y + x; @@ -790,13 +770,11 @@ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, * - multiply it by tangmat * - vector in color space would be norm(vec) /2 + (0.5, 0.5, 0.5) */ static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, - const int face_index, const int lvl, const float st[2], + ImBuf *ibuf, const int face_index, const int lvl, const float st[2], float tangmat[3][3], const int x, const int y) { MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE); MFace mface; - Image *ima = mtface[face_index].tpage; - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); MNormalBakeData *normal_data = (MNormalBakeData *)bake_data; float uv[2], *st0, *st1, *st2, *st3; int pixel = ibuf->x * y + x; @@ -879,7 +857,7 @@ static void bake_images(MultiresBakeRender *bkr) for (link = bkr->image.first; link; link = link->next) { Image *ima = (Image *)link->data; - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ibuf->x > 0 && ibuf->y > 0) { ibuf->userdata = MEM_callocN(ibuf->y * ibuf->x, "MultiresBake imbuf mask"); @@ -895,6 +873,8 @@ static void bake_images(MultiresBakeRender *bkr) } } + BKE_image_release_ibuf(ima, ibuf, NULL); + ima->id.flag |= LIB_DOIT; } } @@ -905,7 +885,7 @@ static void finish_images(MultiresBakeRender *bkr) for (link = bkr->image.first; link; link = link->next) { Image *ima = (Image *)link->data; - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ibuf->x <= 0 || ibuf->y <= 0) continue; @@ -926,6 +906,8 @@ static void finish_images(MultiresBakeRender *bkr) MEM_freeN(ibuf->userdata); ibuf->userdata = NULL; } + + BKE_image_release_ibuf(ima, ibuf, NULL); } } @@ -1000,7 +982,7 @@ static int multiresbake_check(bContext *C, wmOperator *op) ok = 0; } else { - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (!ibuf) { BKE_report(op->reports, RPT_ERROR, "Baking should happen to image with image buffer"); @@ -1017,6 +999,8 @@ static int multiresbake_check(bContext *C, wmOperator *op) if (!ok) BKE_report(op->reports, RPT_ERROR, "Baking to unsupported image type"); } + + BKE_image_release_ibuf(ima, ibuf, NULL); } } } @@ -1087,10 +1071,12 @@ static void clear_images(MTFace *mtface, int totface) Image *ima = mtface[a].tpage; if ((ima->id.flag & LIB_DOIT) == 0) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid); ima->id.flag |= LIB_DOIT; + + BKE_image_release_ibuf(ima, ibuf, NULL); } } @@ -1384,7 +1370,7 @@ static void finish_bake_internal(BakeRender *bkr) /* force OpenGL reload and mipmap recalc */ for (ima = G.main->image.first; ima; ima = ima->id.next) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); /* some of the images could have been changed during bake, * so recreate mipmaps regardless bake result status @@ -1409,6 +1395,8 @@ static void finish_bake_internal(BakeRender *bkr) ibuf->userdata = NULL; } } + + BKE_image_release_ibuf(ima, ibuf, NULL); } } diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index c0c2195592b..d39e34824b9 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -550,7 +550,8 @@ static int editmode_toggle_poll(bContext *C) if (ELEM(NULL, ob, ob->data) || ((ID *)ob->data)->lib) return 0; - if (ob->restrictflag & OB_RESTRICT_VIEW) + /* if hidden but in edit mode, we still display */ + if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT)) return 0; return (ob->type == OB_MESH || ob->type == OB_ARMATURE || @@ -1380,7 +1381,7 @@ static void UNUSED_FUNCTION(image_aspect) (Scene * scene, View3D * v3d) if (ma->mtex[b] && ma->mtex[b]->tex) { tex = ma->mtex[b]->tex; if (tex->type == TEX_IMAGE && tex->ima) { - ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, NULL, NULL); /* texturespace */ space = 1.0; @@ -1402,6 +1403,8 @@ static void UNUSED_FUNCTION(image_aspect) (Scene * scene, View3D * v3d) done = TRUE; DAG_id_tag_update(&ob->id, OB_RECALC_OB); + + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } } if (done) break; diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 3d2c4f95624..7d3d6861418 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -555,7 +555,7 @@ static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, M Key *key = me->key; KeyBlock *kb; - if (!modifier_sameTopology(md) || mti->type == eModifierTypeType_NonGeometrical) { + if (!modifier_isSameTopology(md) || mti->type == eModifierTypeType_NonGeometrical) { BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to shapes"); return 0; } @@ -688,6 +688,13 @@ int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, Modi BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data"); return 0; } + else if ((ob->mode & OB_MODE_SCULPT) && + (find_multires_modifier_before(scene, md)) && + (modifier_isSameTopology(md) == FALSE)) + { + BKE_report(reports, RPT_ERROR, "Constructive modifier cannot be applied to multi-res data in sculpt mode"); + return 0; + } if (md != ob->modifiers.first) BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected"); @@ -1000,7 +1007,7 @@ static int modifier_apply_exec(bContext *C, wmOperator *op) Object *ob = ED_object_active_context(C); ModifierData *md = edit_modifier_property_get(op, ob, 0); int apply_as = RNA_enum_get(op->ptr, "apply_as"); - + if (!ob || !md || !ED_object_modifier_apply(op->reports, scene, ob, md, apply_as)) { return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 58c6959d6f0..0988a196fb1 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -643,8 +643,8 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object /* apply transformation of previous parenting */ if (keep_transform) { - /* was removed because of bug [#23577], - * but this can be handy in some cases too [#32616], so make optional */ + /* was removed because of bug [#23577], + * but this can be handy in some cases too [#32616], so make optional */ BKE_object_apply_mat4(ob, ob->obmat, FALSE, FALSE); } @@ -2148,7 +2148,7 @@ static int drop_named_material_invoke(bContext *C, wmOperator *op, wmEvent *even DAG_ids_flush_update(bmain, 0); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C)); - WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING, ma); + WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index 2b6d69ca694..6a511d4d924 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -137,9 +137,11 @@ static int ED_object_shape_key_remove(bContext *C, Object *ob) } if (key->totkey == 0) { - if (GS(key->from->name) == ID_ME) ((Mesh *)key->from)->key = NULL; - else if (GS(key->from->name) == ID_CU) ((Curve *)key->from)->key = NULL; - else if (GS(key->from->name) == ID_LT) ((Lattice *)key->from)->key = NULL; + switch (GS(key->from->name)) { + case ID_ME: ((Mesh *)key->from)->key = NULL; break; + case ID_CU: ((Curve *)key->from)->key = NULL; break; + case ID_LT: ((Lattice *)key->from)->key = NULL; break; + } BKE_libblock_free_us(&(bmain->key), key); } diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 05524af34f0..1b135c0686e 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -400,22 +400,22 @@ typedef enum WT_ReplaceMode { } WT_ReplaceMode; static EnumPropertyItem WT_vertex_group_mode_item[] = { - {WT_REPLACE_ACTIVE_VERTEX_GROUP, "WT_REPLACE_ACTIVE_VERTEX_GROUP", 1, "Active", "Transfer active vertex group from selected to active mesh"}, - {WT_REPLACE_ALL_VERTEX_GROUPS, "WT_REPLACE_ALL_VERTEX_GROUPS", 1, "All", "Transfer all vertex groups from selected to active mesh"}, + {WT_REPLACE_ACTIVE_VERTEX_GROUP, "WT_REPLACE_ACTIVE_VERTEX_GROUP", 0, "Active", "Transfer active vertex group from selected to active mesh"}, + {WT_REPLACE_ALL_VERTEX_GROUPS, "WT_REPLACE_ALL_VERTEX_GROUPS", 0, "All", "Transfer all vertex groups from selected to active mesh"}, {0, NULL, 0, NULL, NULL} }; static EnumPropertyItem WT_method_item[] = { - {WT_BY_INDEX, "WT_BY_INDEX", 1, "Vertex index", "Copy for identical meshes"}, - {WT_BY_NEAREST_VERTEX, "WT_BY_NEAREST_VERTEX", 1, "Nearest vertex", "Copy weight from closest vertex"}, - {WT_BY_NEAREST_FACE, "WT_BY_NEAREST_FACE", 1, "Nearest face", "Barycentric interpolation from nearest face"}, - {WT_BY_NEAREST_VERTEX_IN_FACE, "WT_BY_NEAREST_VERTEX_IN_FACE", 1, "Nearest vertex in face", "Copy weight from closest vertex in nearest face"}, + {WT_BY_INDEX, "WT_BY_INDEX", 0, "Vertex index", "Copy for identical meshes"}, + {WT_BY_NEAREST_VERTEX, "WT_BY_NEAREST_VERTEX", 0, "Nearest vertex", "Copy weight from closest vertex"}, + {WT_BY_NEAREST_FACE, "WT_BY_NEAREST_FACE", 0, "Nearest face", "Barycentric interpolation from nearest face"}, + {WT_BY_NEAREST_VERTEX_IN_FACE, "WT_BY_NEAREST_VERTEX_IN_FACE", 0, "Nearest vertex in face", "Copy weight from closest vertex in nearest face"}, {0, NULL, 0, NULL, NULL} }; static EnumPropertyItem WT_replace_mode_item[] = { - {WT_REPLACE_ALL_WEIGHTS, "WT_REPLACE_ALL_WEIGHTS", 1, "All", "Overwrite all weights"}, - {WT_REPLACE_EMPTY_WEIGHTS, "WT_REPLACE_EMPTY_WEIGHTS", 1, "Empty", "Add weights to vertices with no weight"}, + {WT_REPLACE_ALL_WEIGHTS, "WT_REPLACE_ALL_WEIGHTS", 0, "All", "Overwrite all weights"}, + {WT_REPLACE_EMPTY_WEIGHTS, "WT_REPLACE_EMPTY_WEIGHTS", 0, "Empty", "Add weights to vertices with no weight"}, {0, NULL, 0, NULL, NULL} }; @@ -845,25 +845,26 @@ void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum) static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum) { MDeformVert *dv = NULL; - BMVert *eve; - Mesh *me; /* get the deform vertices corresponding to the vertnum */ if (ob->type == OB_MESH) { - me = ob->data; + Mesh *me = ob->data; if (me->edit_btmesh) { - eve = BM_vert_at_index(me->edit_btmesh->bm, vertnum); + /* warning, this lookup is _not_ fast */ + BMVert *eve = BM_vert_at_index(me->edit_btmesh->bm, vertnum); if (!eve) { return 0.0f; } dv = CustomData_bmesh_get(&me->edit_btmesh->bm->vdata, eve->head.data, CD_MDEFORMVERT); } else { - if (vertnum >= me->totvert) { - return 0.0f; + if (me->dvert) { + if (vertnum >= me->totvert) { + return 0.0f; + } + dv = &me->dvert[vertnum]; } - dv = &me->dvert[vertnum]; } } else if (ob->type == OB_LATTICE) { @@ -2573,7 +2574,7 @@ static int vertex_group_add_exec(bContext *C, wmOperator *UNUSED(op)) ED_vgroup_add(ob); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return OPERATOR_FINISHED; @@ -2604,7 +2605,7 @@ static int vertex_group_remove_exec(bContext *C, wmOperator *op) vgroup_delete(ob); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return OPERATOR_FINISHED; @@ -2770,7 +2771,7 @@ static int vertex_group_copy_exec(bContext *C, wmOperator *UNUSED(op)) vgroup_duplicate(ob); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob->data); return OPERATOR_FINISHED; } @@ -3198,7 +3199,7 @@ static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op)) DAG_id_tag_update(&base->object->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, base->object); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, base->object->data); + WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, base->object->data); retval = OPERATOR_FINISHED; } @@ -3355,7 +3356,7 @@ static int set_active_group_exec(bContext *C, wmOperator *op) ob->actdef = nr + 1; DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob); + WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob); return OPERATOR_FINISHED; } @@ -3519,7 +3520,7 @@ static int vertex_group_sort_exec(bContext *C, wmOperator *op) if (ret != OPERATOR_CANCELLED) { DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob); + WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob); } if (name_array) MEM_freeN(name_array); @@ -3574,7 +3575,7 @@ static int vgroup_move_exec(bContext *C, wmOperator *op) if (ret != OPERATOR_CANCELLED) { DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob); + WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob); } return ret; diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index f8ec51c7a7c..f5754297e9f 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -401,6 +401,7 @@ static void PE_set_view3d_data(bContext *C, PEData *data) static int key_test_depth(PEData *data, const float co[3], const int screen_co[2]) { View3D *v3d= data->vc.v3d; + ViewDepths *vd = data->vc.rv3d->depths; double ux, uy, uz; float depth; @@ -428,12 +429,15 @@ static int key_test_depth(PEData *data, const float co[3], const int screen_co[2 /* view3d_validate_backbuf(&data->vc); */ glReadPixels(screen_co[0], screen_co[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth); #else /* faster to use depths, these are calculated in PE_set_view3d_data */ - { - ViewDepths *vd = data->vc.rv3d->depths; - assert(vd && vd->depths); + + /* check if screen_co is within bounds because brush_cut uses out of screen coords */ + if (screen_co[0] >= 0 && screen_co[0] < vd->w && screen_co[1] >= 0 && screen_co[1] < vd->h) { + BLI_assert(vd && vd->depths); /* we know its not clipped */ depth = vd->depths[screen_co[1] * vd->w + screen_co[0]]; } + else + return 0; #endif if ((float)uz - 0.00001f > depth) @@ -2437,7 +2441,8 @@ void PARTICLE_OT_remove_doubles(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; /* properties */ - RNA_def_float(ot->srna, "threshold", 0.0002f, 0.0f, FLT_MAX, "Threshold", "Threshold distance withing which particles are removed", 0.00001f, 0.1f); + RNA_def_float(ot->srna, "threshold", 0.0002f, 0.0f, FLT_MAX, + "Merge Distance", "Threshold distance withing which particles are removed", 0.00001f, 0.1f); } diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index 218af8f0f33..5304c64c2a9 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -446,7 +446,7 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid for (fobj=fobjects->first; fobj; fobj=fobj->next) { Object *ob = fobj->object; FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); - float active= (float)(fluidmd->fss->flag & OB_FLUIDSIM_ACTIVE); + float active= (float) ((fluidmd->fss->flag & OB_FLUIDSIM_ACTIVE) > 0 ? 1 : 0); float rot_d[3] = {0.f, 0.f, 0.f}, old_rot[3] = {0.f, 0.f, 0.f}; if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE)) @@ -467,6 +467,8 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid set_channel(fobj->Scale, timeAtFrame, ob->size, i, CHANNEL_VEC); set_channel(fobj->Active, timeAtFrame, &active, i, CHANNEL_FLOAT); set_channel(fobj->InitialVelocity, timeAtFrame, &fluidmd->fss->iniVelx, i, CHANNEL_VEC); + + // printf("Active: %f, Frame: %f\n", active, timeAtFrame); if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) { set_channel(fobj->AttractforceStrength, timeAtFrame, &fluidmd->fss->attractforceStrength, i, CHANNEL_FLOAT); @@ -574,7 +576,8 @@ static void export_fluid_objects(ListBase *fobjects, Scene *scene, int length) fsmesh.channelScale = NULL; /* Override user settings, only noslip is supported here! */ - fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP; + if (fsmesh.type != OB_FLUIDSIM_CONTROL) + fsmesh.obstacleType = FLUIDSIM_OBSTACLE_NOSLIP; } elbeemAddMesh(&fsmesh); @@ -961,8 +964,8 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor /* ******** prepare output file paths ******** */ outStringsChanged = fluid_init_filepaths(fsDomain, targetDir, targetFile, debugStrBuffer); - channels->length = scene->r.efra; - channels->aniFrameTime = (double)(domainSettings->animEnd - domainSettings->animStart) / (double)noFrames; + channels->length = scene->r.efra; // DG TODO: why using endframe and not "noFrames" here? .. because "noFrames" is buggy too? (not using sfra) + channels->aniFrameTime = (double)((double)domainSettings->animEnd - (double)domainSettings->animStart) / (double)noFrames; /* ******** initialize and allocate animation channels ******** */ fluid_init_all_channels(C, fsDomain, domainSettings, channels, fobjects); diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 4b177629f72..f8154f4abda 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -375,7 +375,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec /* make jobs timer to send notifier */ *(rj->do_update) = TRUE; } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); } static void render_startjob(void *rjv, short *stop, short *do_update, float *progress) @@ -553,13 +553,20 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event) rj->win = CTX_wm_window(C); rj->srl = srl; rj->camera_override = camera_override; - rj->lay = (v3d) ? v3d->lay : scene->lay; + rj->lay = scene->lay; rj->anim = is_animation; rj->write_still = is_write_still && !is_animation; rj->iuser.scene = scene; rj->iuser.ok = 1; rj->reports = op->reports; + if (v3d) { + rj->lay = v3d->lay; + + if (v3d->localvd) + rj->lay |= v3d->localvd->lay; + } + /* setup job */ if (RE_seq_render_active(scene, &scene->r)) name = "Sequence Render"; else name = "Render"; @@ -611,6 +618,8 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event) /* contextual render, using current scene, view3d? */ void RENDER_OT_render(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Render"; ot->description = "Render active scene"; @@ -625,7 +634,9 @@ void RENDER_OT_render(wmOperatorType *ot) RNA_def_boolean(ot->srna, "animation", 0, "Animation", "Render files from the animation range of this scene"); RNA_def_boolean(ot->srna, "write_still", 0, "Write Image", "Save rendered the image to the output path (used only when animation is disabled)"); - RNA_def_string(ot->srna, "layer", "", RE_MAXNAME, "Render Layer", "Single render layer to re-render (used only when animation is disabled)"); - RNA_def_string(ot->srna, "scene", "", MAX_ID_NAME - 2, "Scene", "Scene to render, current scene if not specified"); + prop = RNA_def_string(ot->srna, "layer", "", RE_MAXNAME, "Render Layer", "Single render layer to re-render (used only when animation is disabled)"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_string(ot->srna, "scene", "", MAX_ID_NAME - 2, "Scene", "Scene to render, current scene if not specified"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index e4592a4f77e..73f8abdf15f 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -288,7 +288,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) } } - BKE_image_release_ibuf(oglrender->ima, lock); + BKE_image_release_ibuf(oglrender->ima, ibuf, lock); } static int screen_opengl_render_init(bContext *C, wmOperator *op) @@ -481,7 +481,7 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); OGLRender *oglrender = op->customdata; Scene *scene = oglrender->scene; - ImBuf *ibuf; + ImBuf *ibuf, *ibuf_save = NULL; void *lock; char name[FILE_MAX]; int ok = 0; @@ -549,47 +549,46 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) if (ibuf) { int needs_free = FALSE; + ibuf_save = ibuf; + if (is_movie || !BKE_imtype_requires_linear_float(scene->r.im_format.imtype)) { - ImBuf *colormanage_ibuf; + ibuf_save = IMB_colormanagement_imbuf_for_write(ibuf, TRUE, TRUE, &scene->view_settings, + &scene->display_settings, &scene->r.im_format); - colormanage_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, TRUE, TRUE, &scene->view_settings, - &scene->display_settings, &scene->r.im_format); - - // IMB_freeImBuf(ibuf); /* owned by the image */ - ibuf = colormanage_ibuf; needs_free = TRUE; } /* color -> grayscale */ /* editing directly would alter the render view */ if (scene->r.im_format.planes == R_IMF_PLANES_BW) { - ImBuf *ibuf_bw = IMB_dupImBuf(ibuf); + ImBuf *ibuf_bw = IMB_dupImBuf(ibuf_save); IMB_color_to_bw(ibuf_bw); if (needs_free) - IMB_freeImBuf(ibuf); + IMB_freeImBuf(ibuf_save); - ibuf = ibuf_bw; + ibuf_save = ibuf_bw; } else { /* this is lightweight & doesnt re-alloc the buffers, only do this * to save the correct bit depth since the image is always RGBA */ - ImBuf *ibuf_cpy = IMB_allocImBuf(ibuf->x, ibuf->y, scene->r.im_format.planes, 0); - ibuf_cpy->rect = ibuf->rect; - ibuf_cpy->rect_float = ibuf->rect_float; - ibuf_cpy->zbuf_float = ibuf->zbuf_float; + ImBuf *ibuf_cpy = IMB_allocImBuf(ibuf_save->x, ibuf_save->y, scene->r.im_format.planes, 0); + + ibuf_cpy->rect = ibuf_save->rect; + ibuf_cpy->rect_float = ibuf_save->rect_float; + ibuf_cpy->zbuf_float = ibuf_save->zbuf_float; if (needs_free) { - ibuf_cpy->mall = ibuf->mall; - ibuf->mall = 0; - IMB_freeImBuf(ibuf); + ibuf_cpy->mall = ibuf_save->mall; + ibuf_save->mall = 0; + IMB_freeImBuf(ibuf_save); } - ibuf = ibuf_cpy; + ibuf_save = ibuf_cpy; } if (is_movie) { - ok = oglrender->mh->append_movie(&scene->r, SFRA, CFRA, (int *)ibuf->rect, + ok = oglrender->mh->append_movie(&scene->r, SFRA, CFRA, (int *)ibuf_save->rect, oglrender->sizex, oglrender->sizey, oglrender->reports); if (ok) { printf("Append frame %d", scene->r.cfra); @@ -597,7 +596,7 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) } } else { - ok = BKE_imbuf_write_stamp(scene, camera, ibuf, name, &scene->r.im_format); + ok = BKE_imbuf_write_stamp(scene, camera, ibuf_save, name, &scene->r.im_format); if (ok == 0) { printf("Write error: cannot save %s\n", name); @@ -609,11 +608,11 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) } } - /* imbuf knows which rects are not part of ibuf */ - IMB_freeImBuf(ibuf); + if (needs_free) + IMB_freeImBuf(ibuf_save); } - BKE_image_release_ibuf(oglrender->ima, lock); + BKE_image_release_ibuf(oglrender->ima, ibuf, lock); /* movie stats prints have no line break */ printf("\n"); diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 53cb5340940..a864fe306b3 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -237,6 +237,14 @@ static int preview_mat_has_sss(Material *mat, bNodeTree *ntree) return 0; } +static Scene *preview_get_scene(void) +{ + if (pr_main == NULL) return NULL; + + return pr_main->scene.first; +} + + /* call this with a pointer to initialize preview scene */ /* call this with NULL to restore assigned ID pointers in preview scene */ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPreview *sp) @@ -244,9 +252,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre Scene *sce; Base *base; - if (pr_main == NULL) return NULL; - - sce = pr_main->scene.first; + sce = preview_get_scene(); if (sce) { /* this flag tells render to not execute depsgraph or ipos etc */ @@ -665,8 +671,23 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs char name[32]; int sizex; + /* in case of split preview, use border render */ + if (split) { + if (first) sizex = sp->sizex / 2; + else sizex = sp->sizex - sp->sizex / 2; + } + else sizex = sp->sizex; + + /* we have to set preview variables first */ + sce = preview_get_scene(); + if (sce) { + sce->r.xsch = sizex; + sce->r.ysch = sp->sizey; + sce->r.size = 100; + } + /* get the stuff from the builtin preview dbase */ - sce = preview_prepare_scene(sp->scene, id, idtype, sp); // XXX sizex + sce = preview_prepare_scene(sp->scene, id, idtype, sp); if (sce == NULL) return; if (!split || first) sprintf(name, "Preview %p", sp->owner); @@ -694,17 +715,6 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs sce->r.mode |= R_OSA; } - /* in case of split preview, use border render */ - if (split) { - if (first) sizex = sp->sizex / 2; - else sizex = sp->sizex - sp->sizex / 2; - } - else sizex = sp->sizex; - - /* allocates or re-uses render result */ - sce->r.xsch = sizex; - sce->r.ysch = sp->sizey; - sce->r.size = 100; /* callbacs are cleared on GetRender() */ if (ELEM(sp->pr_method, PR_BUTS_RENDER, PR_NODE_RENDER)) { @@ -924,13 +934,15 @@ static void icon_preview_startjob(void *customdata, short *stop, short *do_updat /* elubie: this needs to be changed: here image is always loaded if not * already there. Very expensive for large images. Need to find a way to * only get existing ibuf */ - ibuf = BKE_image_get_ibuf(ima, &iuser); + ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); if (ibuf == NULL || ibuf->rect == NULL) return; icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect); *do_update = TRUE; + + BKE_image_release_ibuf(ima, ibuf, NULL); } else if (idtype == ID_BR) { Brush *br = (Brush *)id; diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 25a01d38dd5..eef5e705ce7 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -865,7 +865,7 @@ static int paste_material_exec(bContext *C, wmOperator *UNUSED(op)) paste_matcopybuf(ma); - WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_DRAW, ma); + WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma); return OPERATOR_FINISHED; } @@ -1027,7 +1027,7 @@ static int paste_mtex_exec(bContext *C, wmOperator *UNUSED(op)) paste_mtex_copybuf(id); - WM_event_add_notifier(C, NC_TEXTURE | ND_SHADING_DRAW, NULL); + WM_event_add_notifier(C, NC_TEXTURE | ND_SHADING_LINKS, NULL); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index c5320fde0ff..1ed1cbb2c6b 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -58,12 +58,15 @@ #include "GPU_material.h" #include "RE_engine.h" +#include "RE_pipeline.h" #include "ED_node.h" #include "ED_render.h" #include "render_intern.h" // own include +extern Material defmaterial; + /***************************** Render Engines ********************************/ void ED_render_scene_update(Main *bmain, Scene *scene, int updated) @@ -153,10 +156,16 @@ void ED_render_engine_changed(Main *bmain) /* on changing the render engine type, clear all running render engines */ bScreen *sc; ScrArea *sa; + Scene *scene; for (sc = bmain->screen.first; sc; sc = sc->id.next) for (sa = sc->areabase.first; sa; sa = sa->next) ED_render_engine_area_exit(sa); + + RE_FreePersistentData(); + + for (scene = bmain->scene.first; scene; scene = scene->id.next) + ED_render_id_flush_update(bmain, &scene->id); } /***************************** Updates *********************************** @@ -247,6 +256,27 @@ static void material_changed(Main *bmain, Material *ma) } } +static void lamp_changed(Main *bmain, Lamp *la) +{ + Object *ob; + Material *ma; + + /* icons */ + BKE_icon_changed(BKE_icon_getid(&la->id)); + + /* glsl */ + for (ob = bmain->object.first; ob; ob = ob->id.next) + if (ob->data == la && ob->gpulamp.first) + GPU_lamp_free(ob); + + for (ma = bmain->mat.first; ma; ma = ma->id.next) + if (ma->gpumaterial.first) + GPU_material_free(ma); + + if (defmaterial.gpumaterial.first) + GPU_material_free(&defmaterial); +} + static void texture_changed(Main *bmain, Tex *tex) { Material *ma; @@ -279,16 +309,14 @@ static void texture_changed(Main *bmain, Tex *tex) /* find lamps */ for (la = bmain->lamp.first; la; la = la->id.next) { if (mtex_use_tex(la->mtex, MAX_MTEX, tex)) { - /* pass */ + lamp_changed(bmain, la); } else if (la->nodetree && nodes_use_tex(la->nodetree, tex)) { - /* pass */ + lamp_changed(bmain, la); } else { continue; } - - BKE_icon_changed(BKE_icon_getid(&la->id)); } /* find worlds */ @@ -317,24 +345,6 @@ static void texture_changed(Main *bmain, Tex *tex) } } -static void lamp_changed(Main *bmain, Lamp *la) -{ - Object *ob; - Material *ma; - - /* icons */ - BKE_icon_changed(BKE_icon_getid(&la->id)); - - /* glsl */ - for (ob = bmain->object.first; ob; ob = ob->id.next) - if (ob->data == la && ob->gpulamp.first) - GPU_lamp_free(ob); - - for (ma = bmain->mat.first; ma; ma = ma->id.next) - if (ma->gpumaterial.first) - GPU_material_free(ma); -} - static void world_changed(Main *bmain, World *wo) { Material *ma; @@ -346,6 +356,9 @@ static void world_changed(Main *bmain, World *wo) for (ma = bmain->mat.first; ma; ma = ma->id.next) if (ma->gpumaterial.first) GPU_material_free(ma); + + if (defmaterial.gpumaterial.first) + GPU_material_free(&defmaterial); } static void image_changed(Main *bmain, Image *ima) @@ -374,10 +387,19 @@ static void scene_changed(Main *bmain, Scene *UNUSED(scene)) for (ma = bmain->mat.first; ma; ma = ma->id.next) if (ma->gpumaterial.first) GPU_material_free(ma); + + if (defmaterial.gpumaterial.first) + GPU_material_free(&defmaterial); } void ED_render_id_flush_update(Main *bmain, ID *id) { + /* this can be called from render or baking thread when a python script makes + * changes, in that case we don't want to do any editor updates, and making + * GPU changes is not possible because OpenGL only works in the main thread */ + if (!BLI_thread_is_main()) + return; + switch (GS(id->name)) { case ID_MA: material_changed(bmain, (Material *)id); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 6a9c24d2913..67d4af916aa 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -293,29 +293,35 @@ int ED_operator_console_active(bContext *C) return ed_spacetype_test(C, SPACE_CONSOLE); } +static int ed_object_hidden(Object *ob) +{ + /* if hidden but in edit mode, we still display, can happen with animation */ + return ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT)); +} + int ED_operator_object_active(bContext *C) { Object *ob = ED_object_active_context(C); - return ((ob != NULL) && !(ob->restrictflag & OB_RESTRICT_VIEW)); + return ((ob != NULL) && !ed_object_hidden(ob)); } int ED_operator_object_active_editable(bContext *C) { Object *ob = ED_object_active_context(C); - return ((ob != NULL) && !(ob->id.lib) && !(ob->restrictflag & OB_RESTRICT_VIEW)); + return ((ob != NULL) && !(ob->id.lib) && !ed_object_hidden(ob)); } int ED_operator_object_active_editable_mesh(bContext *C) { Object *ob = ED_object_active_context(C); - return ((ob != NULL) && !(ob->id.lib) && !(ob->restrictflag & OB_RESTRICT_VIEW) && + return ((ob != NULL) && !(ob->id.lib) && !ed_object_hidden(ob) && (ob->type == OB_MESH) && !(((ID *)ob->data)->lib)); } int ED_operator_object_active_editable_font(bContext *C) { Object *ob = ED_object_active_context(C); - return ((ob != NULL) && !(ob->id.lib) && !(ob->restrictflag & OB_RESTRICT_VIEW) && + return ((ob != NULL) && !(ob->id.lib) && !ed_object_hidden(ob) && (ob->type == OB_FONT)); } diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 0ecac5fc497..ca85daadf3b 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -35,6 +35,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_math.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -52,6 +53,7 @@ #include "BKE_writeavi.h" #include "BIF_gl.h" +#include "BIF_glutil.h" #include "RNA_access.h" #include "RNA_define.h" @@ -278,6 +280,7 @@ void SCREEN_OT_screenshot(wmOperatorType *ot) typedef struct ScreenshotJob { Main *bmain; Scene *scene; + wmWindowManager *wm; unsigned int *dumprect; int x, y, dumpsx, dumpsy; short *stop; @@ -395,6 +398,54 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float BKE_report(&sj->reports, RPT_INFO, "Screencast job stopped"); } +/* Helper callback for drawing the cursor itself */ +static void screencast_draw_cursor(bContext *UNUSED(C), int x, int y, void *UNUSED(p_ptr)) +{ + + glPushMatrix(); + + glTranslatef((float)x, (float)y, 0.0f); + + + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + + glColor4ub(0, 0, 0, 32); + glutil_draw_filled_arc(0.0, M_PI * 2.0, 20, 40); + + glColor4ub(255, 255, 255, 128); + glutil_draw_lined_arc(0.0, M_PI * 2.0, 20, 40); + + glDisable(GL_BLEND); + glDisable(GL_LINE_SMOOTH); + + glPopMatrix(); +} + +/* Turn brush cursor in 3D view on/off */ +static void screencast_cursor_toggle(wmWindowManager *wm, short enable) +{ + static void *cursor = NULL; + + if (cursor && !enable) { + /* clear cursor */ + WM_paint_cursor_end(wm, cursor); + cursor = NULL; + } + else if (enable) { + /* enable cursor */ + cursor = WM_paint_cursor_activate(wm, NULL, screencast_draw_cursor, NULL); + } +} + +static void screenshot_endjob(void *sjv) +{ + ScreenshotJob *sj = sjv; + + screencast_cursor_toggle(sj->wm, 0); +} + + static int screencast_exec(bContext *C, wmOperator *op) { bScreen *screen = CTX_wm_screen(C); @@ -418,15 +469,18 @@ static int screencast_exec(bContext *C, wmOperator *op) } sj->bmain = CTX_data_main(C); sj->scene = CTX_data_scene(C); - + sj->wm = CTX_wm_manager(C); + BKE_reports_init(&sj->reports, RPT_PRINT); /* setup job */ WM_jobs_customdata_set(wm_job, sj, screenshot_freejob); WM_jobs_timer(wm_job, 0.1, 0, NC_SCREEN | ND_SCREENCAST); - WM_jobs_callbacks(wm_job, screenshot_startjob, NULL, screenshot_updatejob, NULL); + WM_jobs_callbacks(wm_job, screenshot_startjob, NULL, screenshot_updatejob, screenshot_endjob); - WM_jobs_start(CTX_wm_manager(C), wm_job); + WM_jobs_start(sj->wm, wm_job); + + screencast_cursor_toggle(sj->wm, 1); WM_event_add_notifier(C, NC_SCREEN | ND_SCREENCAST, screen); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index e00a8776bea..b704414c321 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -109,19 +109,25 @@ #include "paint_intern.h" /* Defines and Structs */ +/* FTOCHAR as inline function */ +BLI_INLINE unsigned char f_to_char(const float val) +{ + return FTOCHAR(val); +} + #define IMAPAINT_CHAR_TO_FLOAT(c) ((c) / 255.0f) #define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { \ - (c)[0] = FTOCHAR((f)[0]); \ - (c)[1] = FTOCHAR((f)[1]); \ - (c)[2] = FTOCHAR((f)[2]); \ + (c)[0] = f_to_char((f)[0]); \ + (c)[1] = f_to_char((f)[1]); \ + (c)[2] = f_to_char((f)[2]); \ } (void)0 #define IMAPAINT_FLOAT_RGBA_TO_CHAR(c, f) { \ - (c)[0] = FTOCHAR((f)[0]); \ - (c)[1] = FTOCHAR((f)[1]); \ - (c)[2] = FTOCHAR((f)[2]); \ - (c)[3] = FTOCHAR((f)[3]); \ + (c)[0] = f_to_char((f)[0]); \ + (c)[1] = f_to_char((f)[1]); \ + (c)[2] = f_to_char((f)[2]); \ + (c)[3] = f_to_char((f)[3]); \ } (void)0 #define IMAPAINT_CHAR_RGB_TO_FLOAT(f, c) { \ (f)[0] = IMAPAINT_CHAR_TO_FLOAT((c)[0]); \ @@ -288,9 +294,11 @@ typedef struct ProjPaintState { char *vertFlags; /* store options per vert, now only store if the vert is pointing away from the view */ int buckets_x; /* The size of the bucket grid, the grid span's screenMin/screenMax so you can paint outsize the screen or with 2 brushes at once */ int buckets_y; - + ProjPaintImage *projImages; + int pixel_sizeof; /* result of project_paint_pixel_sizeof(), constant per stroke */ + int image_tot; /* size of projectImages array */ float (*screenCoords)[4]; /* verts projected into floating point screen space */ @@ -379,6 +387,18 @@ typedef struct ProjPixelClone { PixelStore clonepx; } ProjPixelClone; +/* blur, store surrounding colors */ +#define PROJ_PIXEL_SOFTEN_TOT 4 +/* blur picking offset (in screenspace) */ +#define PROJ_PIXEL_SOFTEN_OFS_PX 1.0f + +static const float proj_pixel_soften_v2[PROJ_PIXEL_SOFTEN_TOT][2] = { + {-PROJ_PIXEL_SOFTEN_OFS_PX, 0.0f}, + { 0.0f, -PROJ_PIXEL_SOFTEN_OFS_PX}, + { 0.0f, PROJ_PIXEL_SOFTEN_OFS_PX}, + { PROJ_PIXEL_SOFTEN_OFS_PX, 0.0f}, +}; + /* Finish projection painting structs */ typedef struct UndoImageTile { @@ -480,7 +500,7 @@ static void image_undo_restore(bContext *C, ListBase *lb) ima = BLI_findstring(&bmain->image, tile->idname, offsetof(ID, name)); } - ibuf = BKE_image_get_ibuf(ima, NULL); + ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ima && ibuf && strcmp(tile->ibufname, ibuf->name) != 0) { /* current ImBuf filename was changed, probably current frame @@ -488,19 +508,27 @@ static void image_undo_restore(bContext *C, ListBase *lb) * full image user (which isn't so obvious, btw) try to find ImBuf with * matched file name in list of already loaded images */ + BKE_image_release_ibuf(ima, ibuf, NULL); + ibuf = BLI_findstring(&ima->ibufs, tile->ibufname, offsetof(ImBuf, name)); } - if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) + if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) { + BKE_image_release_ibuf(ima, ibuf, NULL); continue; + } - if (ima->gen_type != tile->gen_type || ima->source != tile->source) + if (ima->gen_type != tile->gen_type || ima->source != tile->source) { + BKE_image_release_ibuf(ima, ibuf, NULL); continue; + } use_float = ibuf->rect_float ? 1 : 0; - if (use_float != tile->use_float) + if (use_float != tile->use_float) { + BKE_image_release_ibuf(ima, ibuf, NULL); continue; + } undo_copy_tile(tile, tmpibuf, ibuf, 1); @@ -510,6 +538,8 @@ static void image_undo_restore(bContext *C, ListBase *lb) if (ibuf->mipmap[0]) ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + + BKE_image_release_ibuf(ima, ibuf, NULL); } IMB_freeImBuf(tmpibuf); @@ -626,7 +656,7 @@ static float VecZDepthPersp(const float pt[2], * barycentric_weights_v2 would return, in this case its easiest just to * undo the 4th axis division and make it unit-sum * - * don't call barycentric_weights_v2() becaue our callers expect 'w' + * don't call barycentric_weights_v2() because our callers expect 'w' * to be weighted from the perspective */ w_tmp[0] = w[0] * v1[3]; w_tmp[1] = w[1] * v2[3]; @@ -1029,11 +1059,11 @@ static int pixel_bounds_uv( INIT_MINMAX2(min_uv, max_uv); - DO_MINMAX2(uv1, min_uv, max_uv); - DO_MINMAX2(uv2, min_uv, max_uv); - DO_MINMAX2(uv3, min_uv, max_uv); + minmax_v2v2_v2(min_uv, max_uv, uv1); + minmax_v2v2_v2(min_uv, max_uv, uv2); + minmax_v2v2_v2(min_uv, max_uv, uv3); if (is_quad) - DO_MINMAX2(uv4, min_uv, max_uv); + minmax_v2v2_v2(min_uv, max_uv, uv4); bounds_px->xmin = (int)(ibuf_x * min_uv[0]); bounds_px->ymin = (int)(ibuf_y * min_uv[1]); @@ -1059,7 +1089,7 @@ static int pixel_bounds_array(float (*uv)[2], rcti *bounds_px, const int ibuf_x, INIT_MINMAX2(min_uv, max_uv); while (tot--) { - DO_MINMAX2((*uv), min_uv, max_uv); + minmax_v2v2_v2(min_uv, max_uv, (*uv)); uv++; } @@ -1378,8 +1408,8 @@ static float project_paint_uvpixel_mask( Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_stencil, face_index); const MTFace *tf_other = ps->dm_mtface_stencil + face_index; - if (other_tpage && (ibuf_other = BKE_image_get_ibuf(other_tpage, NULL))) { - /* BKE_image_get_ibuf - TODO - this may be slow */ + if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) { + /* BKE_image_acquire_ibuf - TODO - this may be slow */ unsigned char rgba_ub[4]; float rgba_f[4]; @@ -1391,7 +1421,9 @@ static float project_paint_uvpixel_mask( else { /* from char to float */ mask = ((rgba_ub[0] + rgba_ub[1] + rgba_ub[2]) / (256 * 3.0f)) * (rgba_ub[3] / 256.0f); } - + + BKE_image_release_ibuf(other_tpage, ibuf_other, NULL); + if (!ps->do_layer_stencil_inv) /* matching the gimps layer mask black/white rules, white==full opacity */ mask = (1.0f - mask); @@ -1491,6 +1523,16 @@ static float project_paint_uvpixel_mask( return mask; } +static int project_paint_pixel_sizeof(const short tool) +{ + if ((tool == PAINT_TOOL_CLONE) || (tool == PAINT_TOOL_SMEAR)) { + return sizeof(ProjPixelClone); + } + else { + return sizeof(ProjPixel); + } +} + /* run this function when we know a bucket's, face's pixel can be initialized, * return the ProjPixel which is added to 'ps->bucketRect[bucket_index]' */ static ProjPixel *project_paint_uvpixel_init( @@ -1506,33 +1548,23 @@ static ProjPixel *project_paint_uvpixel_init( const float w[3]) { ProjPixel *projPixel; - short size; - + /* wrap pixel location */ x_px = x_px % ibuf->x; if (x_px < 0) x_px += ibuf->x; y_px = y_px % ibuf->y; if (y_px < 0) y_px += ibuf->y; - - if (ps->tool == PAINT_TOOL_CLONE) { - size = sizeof(ProjPixelClone); - } - else if (ps->tool == PAINT_TOOL_SMEAR) { - size = sizeof(ProjPixelClone); - } - else { - size = sizeof(ProjPixel); - } - - projPixel = (ProjPixel *)BLI_memarena_alloc(arena, size); + + BLI_assert(ps->pixel_sizeof == project_paint_pixel_sizeof(ps->tool)); + projPixel = (ProjPixel *)BLI_memarena_alloc(arena, ps->pixel_sizeof); //memset(projPixel, 0, size); if (ibuf->rect_float) { projPixel->pixel.f_pt = ibuf->rect_float + ((x_px + y_px * ibuf->x) * 4); - projPixel->origColor.f[0] = projPixel->newColor.f[0] = projPixel->pixel.f_pt[0]; - projPixel->origColor.f[1] = projPixel->newColor.f[1] = projPixel->pixel.f_pt[1]; - projPixel->origColor.f[2] = projPixel->newColor.f[2] = projPixel->pixel.f_pt[2]; - projPixel->origColor.f[3] = projPixel->newColor.f[3] = projPixel->pixel.f_pt[3]; + projPixel->origColor.f[0] = projPixel->newColor.f[0] = projPixel->pixel.f_pt[0]; + projPixel->origColor.f[1] = projPixel->newColor.f[1] = projPixel->pixel.f_pt[1]; + projPixel->origColor.f[2] = projPixel->newColor.f[2] = projPixel->pixel.f_pt[2]; + projPixel->origColor.f[3] = projPixel->newColor.f[3] = projPixel->pixel.f_pt[3]; } else { projPixel->pixel.ch_pt = ((unsigned char *)ibuf->rect + ((x_px + y_px * ibuf->x) * 4)); @@ -1559,8 +1591,8 @@ static ProjPixel *project_paint_uvpixel_init( Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_clone, face_index); const MTFace *tf_other = ps->dm_mtface_clone + face_index; - if (other_tpage && (ibuf_other = BKE_image_get_ibuf(other_tpage, NULL))) { - /* BKE_image_get_ibuf - TODO - this may be slow */ + if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) { + /* BKE_image_acquire_ibuf - TODO - this may be slow */ if (ibuf->rect_float) { if (ibuf_other->rect_float) { /* from float to float */ @@ -1582,6 +1614,8 @@ static ProjPixel *project_paint_uvpixel_init( project_face_pixel(tf_other, ibuf_other, w, side, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL); } } + + BKE_image_release_ibuf(other_tpage, ibuf_other, NULL); } else { if (ibuf->rect_float) { @@ -2906,7 +2940,7 @@ static void project_paint_delayed_face_init(ProjPaintState *ps, const MFace *mf, fidx = mf->v4 ? 3 : 2; do { vCoSS = ps->screenCoords[*(&mf->v1 + fidx)]; - DO_MINMAX2(vCoSS, min, max); + minmax_v2v2_v2(min, max, vCoSS); } while (fidx--); project_paint_bucket_bounds(ps, min, max, bucketMin, bucketMax); @@ -3171,7 +3205,7 @@ static void project_paint_begin(ProjPaintState *ps) /* screen space, not clamped */ projScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projScreenCo[0]; projScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projScreenCo[1]; - DO_MINMAX2(projScreenCo, ps->screenMin, ps->screenMax); + minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo); } } else { @@ -3186,7 +3220,7 @@ static void project_paint_begin(ProjPaintState *ps) projScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projScreenCo[0] / projScreenCo[3]; projScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projScreenCo[1] / projScreenCo[3]; projScreenCo[2] = projScreenCo[2] / projScreenCo[3]; /* Use the depth for bucket point occlusion */ - DO_MINMAX2(projScreenCo, ps->screenMin, ps->screenMax); + minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo); } else { /* TODO - deal with cases where 1 side of a face goes behind the view ? @@ -3388,7 +3422,7 @@ static void project_paint_begin(ProjPaintState *ps) image_index = BLI_linklist_index(image_LinkList, tpage); - if (image_index == -1 && BKE_image_get_ibuf(tpage, NULL)) { /* MemArena dosnt have an append func */ + if (image_index == -1 && BKE_image_has_ibuf(tpage, NULL)) { /* MemArena dosnt have an append func */ BLI_linklist_append(&image_LinkList, tpage); image_index = ps->image_tot; ps->image_tot++; @@ -3411,7 +3445,7 @@ static void project_paint_begin(ProjPaintState *ps) for (node = image_LinkList, i = 0; node; node = node->next, i++, projIma++) { projIma->ima = node->link; projIma->touch = 0; - projIma->ibuf = BKE_image_get_ibuf(projIma->ima, NULL); + projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL); projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); } @@ -3438,6 +3472,7 @@ static void project_paint_begin_clone(ProjPaintState *ps, int mouse[2]) static void project_paint_end(ProjPaintState *ps) { int a; + ProjPaintImage *projIma; /* build undo data from original pixel colors */ if (U.uiflag & USER_GLOBALUNDO) { @@ -3525,7 +3560,14 @@ static void project_paint_end(ProjPaintState *ps) if (tmpibuf_float) IMB_freeImBuf(tmpibuf_float); } /* done calculating undo data */ - + + /* dereference used image buffers */ + for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) { + BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL); + } + + BKE_image_release_ibuf(ps->reproject_image, ps->reproject_ibuf, NULL); + MEM_freeN(ps->screenCoords); MEM_freeN(ps->bucketRect); MEM_freeN(ps->bucketFaces); @@ -3814,15 +3856,97 @@ static void do_projectpaint_smear_f(ProjPaintState *ps, ProjPixel *projPixel, fl BLI_linklist_prepend_arena(smearPixels_f, (void *)projPixel, smearArena); } +/* do_projectpaint_soften for float & byte + */ +static float inv_pow2(float f) +{ + f = 1.0f - f; + f = f * f; + return 1.0f - f; +} + +static void do_projectpaint_soften_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, MemArena *softenArena, LinkNode **softenPixels) +{ + unsigned int accum_tot = 0; + unsigned int i; + + float *rgba = projPixel->newColor.f; + + /* sigh, alpha values tend to need to be a _lot_ stronger with blur */ + mask = inv_pow2(mask); + alpha = inv_pow2(alpha); + + /* rather then painting, accumulate surrounding colors */ + zero_v4(rgba); + + for (i = 0; i < PROJ_PIXEL_SOFTEN_TOT; i++) { + float co_ofs[2]; + float rgba_tmp[4]; + sub_v2_v2v2(co_ofs, projPixel->projCoSS, proj_pixel_soften_v2[i]); + if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, TRUE)) { + add_v4_v4(rgba, rgba_tmp); + accum_tot++; + } + } + + if (LIKELY(accum_tot != 0)) { + mul_v4_fl(rgba, 1.0f / (float)accum_tot); + blend_color_mix_float(rgba, projPixel->pixel.f_pt, rgba, alpha); + if (mask < 1.0f) blend_color_mix_float(rgba, projPixel->origColor.f, rgba, mask); + BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena); + } +} + +static void do_projectpaint_soften(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, MemArena *softenArena, LinkNode **softenPixels) +{ + unsigned int accum_tot = 0; + unsigned int i; + + float rgba[4]; /* convert to byte after */ + + /* sigh, alpha values tend to need to be a _lot_ stronger with blur */ + mask = inv_pow2(mask); + alpha = inv_pow2(alpha); + + /* rather then painting, accumulate surrounding colors */ + zero_v4(rgba); + + for (i = 0; i < PROJ_PIXEL_SOFTEN_TOT; i++) { + float co_ofs[2]; + float rgba_tmp[4]; + sub_v2_v2v2(co_ofs, projPixel->projCoSS, proj_pixel_soften_v2[i]); + if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, TRUE)) { + add_v4_v4(rgba, rgba_tmp); + accum_tot++; + } + } + + if (LIKELY(accum_tot != 0)) { + unsigned char *rgba_ub = projPixel->newColor.ch; + + mul_v4_fl(rgba, 1.0f / (float)accum_tot); + IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba_ub, rgba); + + blend_color_mix(rgba_ub, projPixel->pixel.ch_pt, rgba_ub, (int)(alpha * 255)); + if (mask != 1.0f) blend_color_mix(rgba_ub, projPixel->origColor.ch, rgba_ub, (int)(mask * 255)); + BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena); + } +} + +BLI_INLINE void rgba_float_to_uchar__mul_v3(unsigned char rgba_ub[4], const float rgba[4], const float rgb[3]) +{ + rgba_ub[0] = f_to_char(rgba[0] * rgb[0]); + rgba_ub[1] = f_to_char(rgba[1] * rgb[1]); + rgba_ub[2] = f_to_char(rgba[2] * rgb[2]); + rgba_ub[3] = f_to_char(rgba[3]); +} + static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, const float rgba[4], float alpha, float mask) { unsigned char rgba_ub[4]; if (ps->is_texbrush) { - rgba_ub[0] = FTOCHAR(rgba[0] * ps->brush->rgb[0]); - rgba_ub[1] = FTOCHAR(rgba[1] * ps->brush->rgb[1]); - rgba_ub[2] = FTOCHAR(rgba[2] * ps->brush->rgb[2]); - rgba_ub[3] = FTOCHAR(rgba[3]); + rgba_float_to_uchar__mul_v3(rgba_ub, rgba, ps->brush->rgb); } else { IMAPAINT_FLOAT_RGB_TO_CHAR(rgba_ub, ps->brush->rgb); @@ -3912,6 +4036,10 @@ static void *do_projectpaint_thread(void *ph_v) LinkNode *smearPixels = NULL; LinkNode *smearPixels_f = NULL; MemArena *smearArena = NULL; /* mem arena for this brush projection only */ + + LinkNode *softenPixels = NULL; + LinkNode *softenPixels_f = NULL; + MemArena *softenArena = NULL; /* mem arena for this brush projection only */ if (tool == PAINT_TOOL_SMEAR) { pos_ofs[0] = pos[0] - lastpos[0]; @@ -3919,6 +4047,9 @@ static void *do_projectpaint_thread(void *ph_v) smearArena = BLI_memarena_new(1 << 16, "paint smear arena"); } + else if (tool == PAINT_TOOL_SOFTEN) { + softenArena = BLI_memarena_new(1 << 16, "paint soften arena"); + } /* printf("brush bounds %d %d %d %d\n", bucketMin[0], bucketMin[1], bucketMax[0], bucketMax[1]); */ @@ -4058,6 +4189,10 @@ static void *do_projectpaint_thread(void *ph_v) if (is_floatbuf) do_projectpaint_smear_f(ps, projPixel, alpha, mask, smearArena, &smearPixels_f, co); else do_projectpaint_smear(ps, projPixel, alpha, mask, smearArena, &smearPixels, co); break; + case PAINT_TOOL_SOFTEN: + if (is_floatbuf) do_projectpaint_soften_f(ps, projPixel, alpha, mask, softenArena, &softenPixels_f); + else do_projectpaint_soften(ps, projPixel, alpha, mask, softenArena, &softenPixels); + break; default: if (is_floatbuf) do_projectpaint_draw_f(ps, projPixel, rgba, alpha, mask, use_color_correction); else do_projectpaint_draw(ps, projPixel, rgba, alpha, mask); @@ -4092,7 +4227,21 @@ static void *do_projectpaint_thread(void *ph_v) BLI_memarena_free(smearArena); } - + else if (tool == PAINT_TOOL_SOFTEN) { + + for (node = softenPixels; node; node = node->next) { /* this wont run for a float image */ + projPixel = node->link; + *projPixel->pixel.uint_pt = projPixel->newColor.uint; + } + + for (node = softenPixels_f; node; node = node->next) { + projPixel = node->link; + copy_v4_v4(projPixel->pixel.f_pt, projPixel->newColor.f); + } + + BLI_memarena_free(softenArena); + } + return NULL; } @@ -4545,7 +4694,7 @@ static int texpaint_break_stroke(float *prevuv, float *fwuv, float *bkuv, float static int imapaint_canvas_set(ImagePaintState *s, Image *ima) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, s->sima ? &s->sima->iuser : NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL); /* verify that we can paint and set canvas */ if (ima == NULL) { @@ -4568,10 +4717,12 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima) /* set clone canvas */ if (s->tool == PAINT_TOOL_CLONE) { ima = s->brush->clone.image; - ibuf = BKE_image_get_ibuf(ima, s->sima ? &s->sima->iuser : NULL); + ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL); - if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) + if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) { + BKE_image_release_ibuf(ima, ibuf, NULL); return 0; + } s->clonecanvas = ibuf; @@ -4586,13 +4737,15 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima) return 1; } -static void imapaint_canvas_free(ImagePaintState *UNUSED(s)) +static void imapaint_canvas_free(ImagePaintState *s) { + BKE_image_release_ibuf(s->image, s->canvas, NULL); + BKE_image_release_ibuf(s->brush->clone.image, s->clonecanvas, NULL); } static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, Image *image, short texpaint, float *uv, double time, int update, float pressure) { - ImBuf *ibuf = BKE_image_get_ibuf(image, s->sima ? &s->sima->iuser : NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, s->sima ? &s->sima->iuser : NULL, NULL); float pos[2]; int is_data; @@ -4612,9 +4765,13 @@ static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, is_data == FALSE)) { if (update) imapaint_image_update(s->scene, s->sima, image, ibuf, texpaint); + BKE_image_release_ibuf(image, ibuf, NULL); return 1; } - else return 0; + else { + BKE_image_release_ibuf(image, ibuf, NULL); + return 0; + } } static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPainter *painter, short texpaint, const int prevmval[2], const int mval[2], double time, float pressure) @@ -4632,7 +4789,7 @@ static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPaint ImBuf *ibuf; newimage = imapaint_face_image(s, newfaceindex); - ibuf = BKE_image_get_ibuf(newimage, s->sima ? &s->sima->iuser : NULL); + ibuf = BKE_image_acquire_ibuf(newimage, s->sima ? &s->sima->iuser : NULL, NULL); if (ibuf && ibuf->rect) imapaint_pick_uv(s->scene, s->ob, newfaceindex, mval, newuv); @@ -4640,6 +4797,8 @@ static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPaint newimage = NULL; newuv[0] = newuv[1] = 0.0f; } + + BKE_image_release_ibuf(newimage, ibuf, NULL); } else newuv[0] = newuv[1] = 0.0f; @@ -4842,6 +5001,10 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps) ps->tool = brush->imagepaint_tool; ps->blend = brush->blend; + /* sizeof ProjPixel, since we alloc this a _lot_ */ + ps->pixel_sizeof = project_paint_pixel_sizeof(ps->tool); + BLI_assert(ps->pixel_sizeof >= sizeof(ProjPixel)); + ps->is_airbrush = (brush->flag & BRUSH_AIRBRUSH) ? 1 : 0; ps->is_texbrush = (brush->mtex.tex) ? 1 : 0; @@ -4907,13 +5070,6 @@ static int texture_paint_init(bContext *C, wmOperator *op) pop->first = 1; op->customdata = pop; - - /* XXX: Soften tool does not support projection painting atm, so just disable - * projection for this brush */ - if (brush->imagepaint_tool == PAINT_TOOL_SOFTEN) { - settings->imapaint.flag |= IMAGEPAINT_PROJECT_DISABLE; - pop->restore_projection = 1; - } /* initialize from context */ if (CTX_wm_region_view3d(C)) { @@ -5766,7 +5922,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op) } ps.reproject_image = image; - ps.reproject_ibuf = BKE_image_get_ibuf(image, NULL); + ps.reproject_ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (ps.reproject_ibuf == NULL || ps.reproject_ibuf->rect == NULL) { BKE_report(op->reports, RPT_ERROR, "Image data could not be found"); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 6396a0c2cbc..9ebeb61a7bb 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -195,7 +195,7 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *ev /* Returns zero if no sculpt changes should be made, non-zero otherwise */ static int paint_smooth_stroke(PaintStroke *stroke, float output[2], - const PaintSample *sample) + const PaintSample *sample) { output[0] = sample->mouse[0]; output[1] = sample->mouse[1]; diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index c5eff1a1f0e..cb4b6346c2a 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -257,8 +257,8 @@ void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, const in /* double lookup */ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } minabsw = 1e10; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 56d46a22e10..94b00101dc2 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -125,9 +125,11 @@ static void update_tessface_data(Object *ob, Mesh *me) if (!me->mcol || !me->mface) { /* should always be true */ /* XXX Why this clearing? tessface_calc will reset it anyway! */ -/* if (me->mcol) {*/ -/* memset(me->mcol, 255, 4 * sizeof(MCol) * me->totface);*/ -/* }*/ +#if 0 + if (me->mcol) { + memset(me->mcol, 255, 4 * sizeof(MCol) * me->totface); + } +#endif /* create tessfaces because they will be used for drawing & fast updates */ BKE_mesh_tessface_calc(me); /* does own call to update pointers */ diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 38dbdcd8337..e2ed7776b7e 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -3356,7 +3356,10 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio sculpt_init_mirror_clipping(ob, ss); /* Initial mouse location */ - copy_v2_v2(ss->cache->initial_mouse, mouse); + if (mouse) + copy_v2_v2(ss->cache->initial_mouse, mouse); + else + zero_v2(ss->cache->initial_mouse); mode = RNA_enum_get(op->ptr, "mode"); cache->invert = mode == BRUSH_STROKE_INVERT; @@ -3761,6 +3764,7 @@ int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2]) mval[0] = mouse[0] - vc.ar->winrct.xmin; mval[1] = mouse[1] - vc.ar->winrct.ymin; + /* TODO: what if the segment is totally clipped? (return == 0) */ ED_view3d_win_to_segment_clip(vc.ar, vc.v3d, mval, ray_start, ray_end); invert_m4_m4(obimat, ob->obmat); @@ -3890,8 +3894,8 @@ static int sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const float mouse[2]) { /* Don't start the stroke until mouse goes over the mesh. - * note: event will only be null when re-executing the saved stroke. */ - if (over_mesh(C, op, mouse[0], mouse[1])) { + * note: mouse will only be null when re-executing the saved stroke. */ + if (!mouse || over_mesh(C, op, mouse[0], mouse[1])) { Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; Sculpt *sd = CTX_data_tool_settings(C)->sculpt; diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index ae78b71f2ad..a80d425b90a 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -52,6 +52,7 @@ #include "BKE_action.h" #include "BKE_fcurve.h" +#include "BKE_global.h" #include "BKE_nla.h" #include "BKE_context.h" #include "BKE_report.h" @@ -493,7 +494,7 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; /* copy keyframes */ - if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) { + if (ac.datatype == ANIMCONT_GPENCIL) { /* FIXME... */ BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for grease pencil mode"); return OPERATOR_CANCELLED; @@ -1308,6 +1309,15 @@ void ACTION_OT_keyframe_type(wmOperatorType *ot) /* ***************** Jump to Selected Frames Operator *********************** */ +static int actkeys_framejump_poll(bContext *C) +{ + /* prevent changes during render */ + if (G.is_rendering) + return 0; + + return ED_operator_action_active(C); +} + /* snap current-frame indicator to 'average time' of selected keyframe */ static int actkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1361,7 +1371,7 @@ void ACTION_OT_frame_jump(wmOperatorType *ot) /* api callbacks */ ot->exec = actkeys_framejump_exec; - ot->poll = ED_operator_action_active; + ot->poll = actkeys_framejump_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1412,15 +1422,20 @@ static void snap_action_keys(bAnimContext *ac, short mode) for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); - if (adt) { + if (ale->type == ANIMTYPE_GPLAYER) { + ED_gplayer_snap_frames(ale->data, ac->scene, mode); + } + else if (ale->type == ANIMTYPE_MASKLAYER) { + ED_masklayer_snap_frames(ale->data, ac->scene, mode); + } + else if (adt) { ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 1); ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve); ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } - //else if (ale->type == ACTTYPE_GPLAYER) - // snap_gplayer_frames(ale->data, mode); - else + else { ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, edit_cb, calchandles_fcurve); + } } BLI_freelistN(&anim_data); @@ -1436,11 +1451,7 @@ static int actkeys_snap_exec(bContext *C, wmOperator *op) /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; - - /* XXX... */ - if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) - return OPERATOR_PASS_THROUGH; - + /* get snapping mode */ mode = RNA_enum_get(op->ptr, "type"); @@ -1448,7 +1459,8 @@ static int actkeys_snap_exec(bContext *C, wmOperator *op) snap_action_keys(&ac, mode); /* validate keyframes after editing */ - ANIM_editkeyframes_refresh(&ac); + if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) + ANIM_editkeyframes_refresh(&ac); /* set notifier that keyframes have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 9c47c407bd9..2a5b64cd6ed 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -680,9 +680,9 @@ void buttons_context_compute(const bContext *C, SpaceButs *sbuts) /************************* Context Callback ************************/ const char *buttons_context_dir[] = { - "world", "object", "mesh", "armature", "lattice", "curve", + "texture_slot", "world", "object", "mesh", "armature", "lattice", "curve", "meta_ball", "lamp", "speaker", "camera", "material", "material_slot", - "texture", "texture_slot", "texture_user", "bone", "edit_bone", + "texture", "texture_user", "bone", "edit_bone", "pose_bone", "particle_system", "particle_system_editable", "particle_settings", "cloth", "soft_body", "fluid", "smoke", "collision", "brush", "dynamic_paint", NULL }; @@ -697,7 +697,12 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r /* here we handle context, getting data from precomputed path */ if (CTX_data_dir(member)) { - CTX_data_dir_set(result, buttons_context_dir); + /* in case of new shading system we skip texture_slot, complex python + * UI script logic depends on checking if this is available */ + if (sbuts->texuser) + CTX_data_dir_set(result, buttons_context_dir + 1); + else + CTX_data_dir_set(result, buttons_context_dir); return 1; } else if (CTX_data_equals(member, "world")) { @@ -817,12 +822,12 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r ButsContextTexture *ct = sbuts->texuser; PointerRNA *ptr; - if (ct) - return 0; /* new shading system */ - if ((ptr = get_pointer_type(path, &RNA_Material))) { Material *ma = ptr->data; + if (ct) + return 0; /* new shading system */ + /* if we have a node material, get slot from material in material node */ if (ma && ma->use_nodes && ma->nodetree) { /* if there's an active texture node in the node tree, @@ -843,12 +848,18 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r else if ((ptr = get_pointer_type(path, &RNA_Lamp))) { Lamp *la = ptr->data; + if (ct) + return 0; /* new shading system */ + if (la) CTX_data_pointer_set(result, &la->id, &RNA_LampTextureSlot, la->mtex[(int)la->texact]); } else if ((ptr = get_pointer_type(path, &RNA_World))) { World *wo = ptr->data; + if (ct) + return 0; /* new shading system */ + if (wo) CTX_data_pointer_set(result, &wo->id, &RNA_WorldTextureSlot, wo->mtex[(int)wo->texact]); } diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 0e82d8651f3..abfefba02b9 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -248,7 +248,7 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext * void buttons_texture_context_compute(const bContext *C, SpaceButs *sbuts) { - /* gatheravailable texture users in context. runs on every draw of + /* gather available texture users in context. runs on every draw of * properties editor, before the buttons are created. */ ButsContextTexture *ct = sbuts->texuser; Scene *scene = CTX_data_scene(C); diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 09ad7312123..c98d213e949 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -297,6 +297,7 @@ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn) buttons_area_redraw(sa, BCONTEXT_PHYSICS); case ND_SHADING: case ND_SHADING_DRAW: + case ND_SHADING_LINKS: /* currently works by redraws... if preview is set, it (re)starts job */ sbuts->preview = 1; break; @@ -319,6 +320,7 @@ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn) switch (wmn->data) { case ND_SHADING: case ND_SHADING_DRAW: + case ND_SHADING_LINKS: case ND_NODES: /* currently works by redraws... if preview is set, it (re)starts job */ sbuts->preview = 1; diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index a2e4da719e9..9cf389c4508 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -252,7 +252,6 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, int width, int height, float zoomx, float zoomy) { int x, y; - MovieClip *clip = ED_space_clip_get_clip(sc); /* find window pixel coordinates of origin */ UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y); @@ -306,6 +305,15 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, IMB_display_buffer_release(cache_handle); } +} + +static void draw_stabilization_border(SpaceClip *sc, ARegion *ar, int width, int height, float zoomx, float zoomy) +{ + int x, y; + MovieClip *clip = ED_space_clip_get_clip(sc); + + /* find window pixel coordinates of origin */ + UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y); /* draw boundary border for frame if stabilization is enabled */ if (sc->flag & SC_SHOW_STABLE && clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) { @@ -1276,7 +1284,7 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, BKE_tracking_undistort_v2(tracking, pos, tpos); - DO_MINMAX2(tpos, min, max); + minmax_v2v2_v2(min, max, tpos); } copy_v2_v2(pos, min); @@ -1469,6 +1477,7 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar) } if (width && height) { + draw_stabilization_border(sc, ar, width, height, zoomx, zoomy); draw_tracking_tracks(sc, ar, clip, width, height, zoomx, zoomy); draw_distortion(sc, ar, clip, width, height, zoomx, zoomy); } @@ -1488,7 +1497,7 @@ void clip_draw_grease_pencil(bContext *C, int onlyv2d) if (onlyv2d) { /* if manual calibration is used then grease pencil data is already - * drawed in draw_distortion */ + * drawn in draw_distortion */ if ((sc->flag & SC_MANUAL_CALIBRATION) == 0 || sc->mode != SC_MODE_DISTORTION) { glPushMatrix(); glMultMatrixf(sc->unistabmat); diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 71589517c83..1a62af39600 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -349,7 +349,7 @@ static int selected_boundbox(SpaceClip *sc, float min[2], float max[2]) mul_v3_m4v3(pos, sc->stabmat, pos); - DO_MINMAX2(pos, min, max); + minmax_v2v2_v2(min, max, pos); ok = TRUE; } diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 9ec2ad82bef..4e53f34359e 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -1065,7 +1065,7 @@ static int clip_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op)) if (clip->anim) { pj->index_context = IMB_anim_index_rebuild_context(clip->anim, clip->proxy.build_tc_flag, - clip->proxy.build_size_flag, clip->proxy.quality); + clip->proxy.build_size_flag, clip->proxy.quality); } WM_jobs_customdata_set(wm_job, pj, proxy_freejob); diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index ddc624b4cdf..d7a9b1c0cb6 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -63,11 +63,12 @@ #include "clip_intern.h" // own include -void clip_graph_tracking_values_iterate_track(SpaceClip *sc, MovieTrackingTrack *track, void *userdata, - void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord, - int scene_framenr, float val), - void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord), - void (*segment_end)(void *userdata)) +void clip_graph_tracking_values_iterate_track( + SpaceClip *sc, MovieTrackingTrack *track, void *userdata, + void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord, + int scene_framenr, float val), + void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord), + void (*segment_end)(void *userdata)) { MovieClip *clip = ED_space_clip_get_clip(sc); int width, height, coord; @@ -122,11 +123,12 @@ void clip_graph_tracking_values_iterate_track(SpaceClip *sc, MovieTrackingTrack } } -void clip_graph_tracking_values_iterate(SpaceClip *sc, int selected_only, int include_hidden, void *userdata, - void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int coord, int scene_framenr, float val), - void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord), - void (*segment_end)(void *userdata)) +void clip_graph_tracking_values_iterate( + SpaceClip *sc, int selected_only, int include_hidden, void *userdata, + void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, + int coord, int scene_framenr, float val), + void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord), + void (*segment_end)(void *userdata)) { MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index ffe4762ad15..77e2a1bb3d3 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -1028,17 +1028,14 @@ static void clip_refresh(const bContext *C, ScrArea *sa) static void movieclip_main_area_set_view2d(const bContext *C, ARegion *ar) { SpaceClip *sc = CTX_wm_space_clip(C); - MovieClip *clip = ED_space_clip_get_clip(sc); - float x1, y1, w, h; + float x1, y1, w, h, aspx, aspy; int width, height, winx, winy; ED_space_clip_get_size(sc, &width, &height); + ED_space_clip_get_aspect(sc, &aspx, &aspy); - w = width; - h = height; - - if (clip) - h *= clip->aspy / clip->aspx / clip->tracking.camera.pixel_aspect; + w = width * aspx; + h = height * aspy; winx = BLI_rcti_size_x(&ar->winrct) + 1; winy = BLI_rcti_size_y(&ar->winrct) + 1; diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index dd939d57cbe..a29524de36d 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1409,7 +1409,7 @@ static void solve_camera_freejob(void *scv) id_us_plus(&clip->id); /* set blender camera focal length so result would look fine there */ - if (scene->camera && GS(scene->camera->id.name) == ID_CA) { + if (scene->camera && scene->camera->data && GS(((ID *) scene->camera->data)->name) == ID_CA) { Camera *camera = (Camera *)scene->camera->data; int width, height; @@ -2944,6 +2944,19 @@ void CLIP_OT_track_copy_color(wmOperatorType *ot) /********************** add 2d stabilization tracks operator *********************/ +static int stabilize_2d_poll(bContext *C) +{ + if (ED_space_clip_tracking_poll(C)) { + SpaceClip *sc = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip_get_clip(sc); + MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(&clip->tracking); + + return tracking_object->flag & TRACKING_OBJECT_CAMERA; + } + + return FALSE; +} + static int stabilize_2d_add_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceClip *sc = CTX_wm_space_clip(C); @@ -2985,7 +2998,7 @@ void CLIP_OT_stabilize_2d_add(wmOperatorType *ot) /* api callbacks */ ot->exec = stabilize_2d_add_exec; - ot->poll = ED_space_clip_tracking_poll; + ot->poll = stabilize_2d_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3045,7 +3058,7 @@ void CLIP_OT_stabilize_2d_remove(wmOperatorType *ot) /* api callbacks */ ot->exec = stabilize_2d_remove_exec; - ot->poll = ED_space_clip_tracking_poll; + ot->poll = stabilize_2d_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3088,7 +3101,7 @@ void CLIP_OT_stabilize_2d_select(wmOperatorType *ot) /* api callbacks */ ot->exec = stabilize_2d_select_exec; - ot->poll = ED_space_clip_tracking_poll; + ot->poll = stabilize_2d_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3125,7 +3138,7 @@ void CLIP_OT_stabilize_2d_set_rotation(wmOperatorType *ot) /* api callbacks */ ot->exec = stabilize_2d_set_rotation_exec; - ot->poll = ED_space_clip_tracking_poll; + ot->poll = stabilize_2d_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c index f19835b7f85..a215b476094 100644 --- a/source/blender/editors/space_console/console_draw.c +++ b/source/blender/editors/space_console/console_draw.c @@ -146,7 +146,8 @@ static int console_textview_line_get(struct TextViewContext *tvc, const char **l ConsoleLine *cl = (ConsoleLine *)tvc->iter; *line = cl->line; *len = cl->len; - + // printf("'%s' %d\n", *line, cl->len); + BLI_assert(cl->line[cl->len] == '\0' && (cl->len == 0 || cl->line[cl->len - 1] != '\0')); return 1; } diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index d3ae5373a18..36716aeab95 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -157,10 +157,9 @@ static ConsoleLine *console_lb_add__internal(ListBase *lb, ConsoleLine *from) ConsoleLine *ci = MEM_callocN(sizeof(ConsoleLine), "ConsoleLine Add"); if (from) { - ci->line = BLI_strdup(from->line); - ci->len = strlen(ci->line); - ci->len_alloc = ci->len; - + BLI_assert(strlen(from->line) == from->len); + ci->line = BLI_strdupn(from->line, from->len); + ci->len = ci->len_alloc = from->len; ci->cursor = from->cursor; ci->type = from->type; } @@ -174,10 +173,8 @@ static ConsoleLine *console_lb_add__internal(ListBase *lb, ConsoleLine *from) return ci; } -static ConsoleLine *console_history_add(const bContext *C, ConsoleLine *from) +static ConsoleLine *console_history_add(SpaceConsole *sc, ConsoleLine *from) { - SpaceConsole *sc = CTX_wm_space_console(C); - return console_lb_add__internal(&sc->history, from); } @@ -217,7 +214,7 @@ ConsoleLine *console_history_verify(const bContext *C) SpaceConsole *sc = CTX_wm_space_console(C); ConsoleLine *ci = sc->history.last; if (ci == NULL) - ci = console_history_add(C, NULL); + ci = console_history_add(sc, NULL); return ci; } @@ -447,7 +444,7 @@ static int console_indent_exec(bContext *C, wmOperator *UNUSED(op)) console_line_verify_length(ci, ci->len + len); - memmove(ci->line + len, ci->line, ci->len); + memmove(ci->line + len, ci->line, ci->len + 1); memset(ci->line, ' ', len); ci->len += len; BLI_assert(ci->len >= 0); @@ -623,8 +620,9 @@ static int console_clear_line_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } - console_history_add(C, ci); - console_history_add(C, NULL); + console_history_add(sc, ci); + console_history_add(sc, NULL); + console_select_offset(sc, -ci->len); console_textview_update_rect(sc, ar); @@ -727,7 +725,7 @@ static int console_history_cycle_exec(bContext *C, wmOperator *op) while ((cl = console_history_find(sc, ci->line, ci))) console_history_free(sc, cl); - console_history_add(C, (ConsoleLine *)sc->history.last); + console_history_add(sc, (ConsoleLine *)sc->history.last); } ci = sc->history.last; diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index 75add570708..be8febdab23 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -170,16 +170,13 @@ static int id_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event static void id_drop_copy(wmDrag *drag, wmDropBox *drop) { - char text[64]; + char *text; ID *id = drag->poin; - char id_esc[(sizeof(id->name) - 2) * 2]; - - BLI_strescape(id_esc, id->name + 2, sizeof(id_esc)); - - BLI_snprintf(text, sizeof(text), "bpy.data.%s[\"%s\"]", BKE_idcode_to_name_plural(GS(id->name)), id_esc); /* copy drag path to properties */ + text = RNA_path_from_ID_python(id); RNA_string_set(drop->ptr, "text", text); + MEM_freeN(text); } static int path_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event)) diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 8f94086013c..a49b75477e4 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -744,6 +744,7 @@ void filelist_setfilter_types(struct FileList *filelist, const char *filter_glob BLI_strncpy(filelist->filter_glob, filter_glob, sizeof(filelist->filter_glob)); } +/* would recognize .blend as well */ static int file_is_blend_backup(const char *str) { short a, b; diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 49562958f82..778a3f4df3e 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -164,6 +164,8 @@ short ED_fileselect_set_params(SpaceFile *sfile) params->filter = 0; if (RNA_struct_find_property(op->ptr, "filter_blender")) params->filter |= RNA_boolean_get(op->ptr, "filter_blender") ? BLENDERFILE : 0; + if (RNA_struct_find_property(op->ptr, "filter_backup")) + params->filter |= RNA_boolean_get(op->ptr, "filter_backup") ? BLENDERFILE_BACKUP : 0; if (RNA_struct_find_property(op->ptr, "filter_image")) params->filter |= RNA_boolean_get(op->ptr, "filter_image") ? IMAGEFILE : 0; if (RNA_struct_find_property(op->ptr, "filter_movie")) diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 8bb57a32090..483348db18e 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -714,7 +714,17 @@ static void graph_panel_drivers(const bContext *C, Panel *pa) row = uiLayoutRow(box, TRUE); uiItemL(row, IFACE_("Value:"), ICON_NONE); - BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", dvar->curval); + if ((dvar->type == DVAR_TYPE_ROT_DIFF) || + (dvar->type == DVAR_TYPE_TRANSFORM_CHAN && + dvar->targets[0].transChan >= DTAR_TRANSCHAN_ROTX && + dvar->targets[0].transChan < DTAR_TRANSCHAN_SCALEX)) + { + BLI_snprintf(valBuf, sizeof(valBuf), "%.3f (%4.1f°)", dvar->curval, RAD2DEGF(dvar->curval)); + } + else { + BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", dvar->curval); + } + uiItemL(row, valBuf, ICON_NONE); } } diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 453549ebf79..21b0ed99f0b 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -56,6 +56,7 @@ #include "BLF_translation.h" #include "BKE_fcurve.h" +#include "BKE_global.h" #include "BKE_nla.h" #include "BKE_context.h" #include "BKE_report.h" @@ -1763,6 +1764,15 @@ void GRAPH_OT_euler_filter(wmOperatorType *ot) /* ***************** Jump to Selected Frames Operator *********************** */ +static int graphkeys_framejump_poll(bContext *C) +{ + /* prevent changes during render */ + if (G.is_rendering) + return 0; + + return graphop_visible_keyframes_poll(C); +} + /* snap current-frame indicator to 'average time' of selected keyframe */ static int graphkeys_framejump_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1829,7 +1839,7 @@ void GRAPH_OT_frame_jump(wmOperatorType *ot) /* api callbacks */ ot->exec = graphkeys_framejump_exec; - ot->poll = graphop_visible_keyframes_poll; + ot->poll = graphkeys_framejump_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 9b031c015a9..54b417e740a 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -39,6 +39,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_global.h" #include "BKE_main.h" #include "BKE_sound.h" @@ -66,6 +67,15 @@ * 2) Value Indicator (stored per Graph Editor instance) */ +static int graphview_cursor_poll(bContext *C) +{ + /* prevent changes during render */ + if (G.is_rendering) + return 0; + + return ED_operator_graphedit_active(C); +} + /* Set the new frame number */ static void graphview_cursor_apply(bContext *C, wmOperator *op) { @@ -172,7 +182,7 @@ static void GRAPH_OT_cursor_set(wmOperatorType *ot) ot->exec = graphview_cursor_exec; ot->invoke = graphview_cursor_invoke; ot->modal = graphview_cursor_modal; - ot->poll = ED_operator_graphedit_active; + ot->poll = graphview_cursor_poll; /* flags */ ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO; diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index f41169b6c39..fa7c6bd472a 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -563,13 +563,13 @@ static void graph_refresh(const bContext *C, ScrArea *sa) switch (fcu->array_index) { case 0: - col[0] = 1.0f; col[1] = 0.0f; col[2] = 0.0f; + UI_GetThemeColor3fv(TH_AXIS_X, col); break; case 1: - col[0] = 0.0f; col[1] = 1.0f; col[2] = 0.0f; + UI_GetThemeColor3fv(TH_AXIS_Y, col); break; case 2: - col[0] = 0.0f; col[1] = 0.0f; col[2] = 1.0f; + UI_GetThemeColor3fv(TH_AXIS_Z, col); break; default: /* 'unknown' color - bluish so as to not conflict with handles */ diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index ae7a718ab5b..0a3db59096a 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -593,7 +593,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char if (ima->source == IMA_SRC_VIEWER) { ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); image_info(scene, iuser, ima, ibuf, str); - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); uiItemL(layout, ima->id.name + 2, ICON_NONE); uiItemL(layout, str, ICON_NONE); @@ -663,7 +663,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char if (compact == 0) { ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); image_info(scene, iuser, ima, ibuf, str); - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); uiItemL(layout, str, ICON_NONE); } } @@ -722,7 +722,6 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char split = uiLayoutSplit(layout, 0.0f, FALSE); col = uiLayoutColumn(split, TRUE); - uiLayoutSetEnabled(col, 0); uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE); uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE); diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 9fc2b981547..d565e6f9e9a 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -652,7 +652,7 @@ static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int if (!brush || !brush->clone.image) return NULL; - ibuf = BKE_image_get_ibuf(brush->clone.image, NULL); + ibuf = BKE_image_acquire_ibuf(brush->clone.image, NULL, NULL); if (!ibuf) return NULL; @@ -660,6 +660,7 @@ static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); if (!display_buffer) { + BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); IMB_display_buffer_release(cache_handle); return NULL; @@ -669,8 +670,10 @@ static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int IMB_display_buffer_release(cache_handle); - if (!rect) + if (!rect) { + BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); return NULL; + } *width = ibuf->x; *height = ibuf->y; @@ -684,6 +687,8 @@ static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int cp += 4; } + BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); + return rect; } @@ -799,7 +804,7 @@ void draw_image_main(const bContext *C, ARegion *ar) } #endif - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); if (show_viewer) { BLI_unlock_thread(LOCK_DRAW_IMAGE); diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index 4ca2f8888f8..c4e2230e7a7 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -117,8 +117,12 @@ ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r) #endif ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, lock_r); - if (ibuf && (ibuf->rect || ibuf->rect_float)) - return ibuf; + if (ibuf) { + if (ibuf->rect || ibuf->rect_float) + return ibuf; + + BKE_image_release_ibuf(sima->image, ibuf, NULL); + } } else *lock_r = NULL; @@ -126,10 +130,10 @@ ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r) return NULL; } -void ED_space_image_release_buffer(SpaceImage *sima, void *lock) +void ED_space_image_release_buffer(SpaceImage *sima, ImBuf *ibuf, void *lock) { if (sima && sima->image) - BKE_image_release_ibuf(sima->image, lock); + BKE_image_release_ibuf(sima->image, ibuf, lock); } int ED_space_image_has_buffer(SpaceImage *sima) @@ -140,7 +144,7 @@ int ED_space_image_has_buffer(SpaceImage *sima) ibuf = ED_space_image_acquire_buffer(sima, &lock); has_buffer = (ibuf != NULL); - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return has_buffer; } @@ -175,7 +179,7 @@ void ED_space_image_get_size(SpaceImage *sima, int *width, int *height) *height = IMG_SIZE_FALLBACK; } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); } void ED_space_image_get_size_fl(SpaceImage *sima, float size[2]) diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index ce3c6e1fd26..0d0fdc6be1c 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -81,6 +81,8 @@ #include "WM_api.h" #include "WM_types.h" +#include "PIL_time.h" + #include "image_intern.h" /******************** view navigation utilities *********************/ @@ -167,7 +169,7 @@ static int space_image_file_exists_poll(bContext *C) ret = TRUE; } } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return ret; } @@ -367,10 +369,18 @@ void IMAGE_OT_view_pan(wmOperatorType *ot) /********************** view zoom operator *********************/ typedef struct ViewZoomData { - float x, y; + float origx, origy; float zoom; int event_type; float location[2]; + + /* needed for continuous zoom */ + wmTimer *timer; + double timer_lastdraw; + + /* */ + SpaceImage *sima; + ARegion *ar; } ViewZoomData; static void image_view_zoom_init(bContext *C, wmOperator *op, wmEvent *event) @@ -382,13 +392,22 @@ static void image_view_zoom_init(bContext *C, wmOperator *op, wmEvent *event) op->customdata = vpd = MEM_callocN(sizeof(ViewZoomData), "ImageViewZoomData"); WM_cursor_modal(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR); - vpd->x = event->x; - vpd->y = event->y; + vpd->origx = event->x; + vpd->origy = event->y; vpd->zoom = sima->zoom; vpd->event_type = event->type; UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &vpd->location[0], &vpd->location[1]); + if (U.viewzoom == USER_ZOOM_CONT) { + /* needs a timer to continue redrawing */ + vpd->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f); + vpd->timer_lastdraw = PIL_check_seconds_timer(); + } + + vpd->sima = sima; + vpd->ar = ar; + WM_event_add_modal_handler(C, op); } @@ -402,6 +421,9 @@ static void image_view_zoom_exit(bContext *C, wmOperator *op, int cancel) ED_region_tag_redraw(CTX_wm_region(C)); } + if (vpd->timer) + WM_event_remove_timer(CTX_wm_manager(C), vpd->timer->win, vpd->timer); + WM_cursor_restore(CTX_wm_window(C)); MEM_freeN(op->customdata); } @@ -427,6 +449,12 @@ static int image_view_zoom_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +enum { + VIEW_PASS = 0, + VIEW_APPLY, + VIEW_CONFIRM +}; + static int image_view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event) { if (event->type == MOUSEZOOM) { @@ -454,31 +482,72 @@ static int image_view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event) } } +static void image_zoom_apply(ViewZoomData *vpd, wmOperator *op, const int x, const int y, const short viewzoom, const short zoom_invert) +{ + float factor; + + if (viewzoom == USER_ZOOM_CONT) { + double time = PIL_check_seconds_timer(); + float time_step = (float)(time - vpd->timer_lastdraw); + float fac; + float zfac; + + if (U.uiflag & USER_ZOOM_HORIZ) { + fac = (float)(x - vpd->origx); + } + else { + fac = (float)(y - vpd->origy); + } + + if (zoom_invert) { + fac = -fac; + } + + /* oldstyle zoom */ + zfac = 1.0f + ((fac / 20.0f) * time_step); + vpd->timer_lastdraw = time; + /* this is the final zoom, but instead make it into a factor */ + //zoom = vpd->sima->zoom * zfac; + factor = (vpd->sima->zoom * zfac) / vpd->zoom; + } + else { + /* for now do the same things for scale and dolly */ + float delta = x - vpd->origx + y - vpd->origy; + + if (zoom_invert) + delta *= -1.0f; + + factor = 1.0f + delta / 300.0f; + } + + RNA_float_set(op->ptr, "factor", factor); + sima_zoom_set(vpd->sima, vpd->ar, vpd->zoom * factor, vpd->location); + ED_region_tag_redraw(vpd->ar); +} + static int image_view_zoom_modal(bContext *C, wmOperator *op, wmEvent *event) { - SpaceImage *sima = CTX_wm_space_image(C); - ARegion *ar = CTX_wm_region(C); ViewZoomData *vpd = op->customdata; - float delta, factor; + short event_code = VIEW_PASS; - switch (event->type) { - case MOUSEMOVE: - delta = event->x - vpd->x + event->y - vpd->y; + /* execute the events */ + if (event->type == TIMER && event->customdata == vpd->timer) { + /* continuous zoom */ + event_code = VIEW_APPLY; + } + else if (event->type == MOUSEMOVE) { + event_code = VIEW_APPLY; + } + else if (event->type == vpd->event_type && event->val == KM_RELEASE) { + event_code = VIEW_CONFIRM; + } - if (U.uiflag & USER_ZOOM_INVERT) - delta *= -1; - - factor = 1.0f + delta / 300.0f; - RNA_float_set(op->ptr, "factor", factor); - sima_zoom_set(sima, ar, vpd->zoom * factor, vpd->location); - ED_region_tag_redraw(CTX_wm_region(C)); - break; - default: - if (event->type == vpd->event_type && event->val == KM_RELEASE) { - image_view_zoom_exit(C, op, 0); - return OPERATOR_FINISHED; - } - break; + if (event_code == VIEW_APPLY) { + image_zoom_apply(vpd, op, event->x, event->y, U.viewzoom, (U.uiflag & USER_ZOOM_INVERT) != 0); + } + else if (event_code == VIEW_CONFIRM) { + image_view_zoom_exit(C, op, 0); + return OPERATOR_FINISHED; } return OPERATOR_RUNNING_MODAL; @@ -1188,7 +1257,7 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima, BKE_color_managed_view_settings_copy(&simopts->im_format.view_settings, &scene->view_settings); } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return (ibuf != NULL); } @@ -1328,7 +1397,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI IMB_freeImBuf(colormanaged_ibuf); } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); } static void image_save_as_free(wmOperator *op) @@ -1743,17 +1812,14 @@ void IMAGE_OT_new(wmOperatorType *ot) static int image_invert_poll(bContext *C) { Image *ima = CTX_data_edit_image(C); - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); - - if (ibuf != NULL) - return 1; - return 0; + + return BKE_image_has_ibuf(ima, NULL); } static int image_invert_exec(bContext *C, wmOperator *op) { Image *ima = CTX_data_edit_image(C); - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); /* flags indicate if this channel should be inverted */ const short r = RNA_boolean_get(op->ptr, "invert_r"); @@ -1792,6 +1858,7 @@ static int image_invert_exec(bContext *C, wmOperator *op) } } else { + BKE_image_release_ibuf(ima, ibuf, NULL); return OPERATOR_CANCELLED; } @@ -1800,6 +1867,9 @@ static int image_invert_exec(bContext *C, wmOperator *op) ibuf->userflags |= IB_MIPMAP_INVALID; WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); + + BKE_image_release_ibuf(ima, ibuf, NULL); + return OPERATOR_FINISHED; } @@ -1848,7 +1918,7 @@ static int image_pack_exec(bContext *C, wmOperator *op) { struct Main *bmain = CTX_data_main(C); Image *ima = CTX_data_edit_image(C); - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); int as_png = RNA_boolean_get(op->ptr, "as_png"); if (!image_pack_test(C, op)) @@ -1865,30 +1935,38 @@ static int image_pack_exec(bContext *C, wmOperator *op) ima->packedfile = newPackedFile(op->reports, ima->name, ID_BLEND_PATH(bmain, &ima->id)); WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); - + + BKE_image_release_ibuf(ima, ibuf, NULL); + return OPERATOR_FINISHED; } static int image_pack_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { Image *ima = CTX_data_edit_image(C); - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf; uiPopupMenu *pup; uiLayout *layout; int as_png = RNA_boolean_get(op->ptr, "as_png"); if (!image_pack_test(C, op)) return OPERATOR_CANCELLED; - + + ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); + if (!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) { pup = uiPupMenuBegin(C, "OK", ICON_QUESTION); layout = uiPupMenuLayout(pup); uiItemBooleanO(layout, "Can't pack edited image from disk. Pack as internal PNG?", ICON_NONE, op->idname, "as_png", 1); uiPupMenuEnd(C, pup); + BKE_image_release_ibuf(ima, ibuf, NULL); + return OPERATOR_CANCELLED; } + BKE_image_release_ibuf(ima, ibuf, NULL); + return image_pack_exec(C, op); } @@ -2032,7 +2110,7 @@ int ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], floa int ret = FALSE; if (ibuf == NULL) { - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return FALSE; } @@ -2058,7 +2136,7 @@ int ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], floa } } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return ret; } @@ -2074,7 +2152,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) CurveMapping *curve_mapping = scene->view_settings.curve_mapping; if (ibuf == NULL) { - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); info->draw = 0; return; } @@ -2175,7 +2253,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->draw = 0; } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); ED_area_tag_redraw(CTX_wm_area(C)); } @@ -2266,12 +2344,12 @@ static int image_sample_line_exec(bContext *C, wmOperator *op) float x1f, y1f, x2f, y2f; if (ibuf == NULL) { - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return OPERATOR_CANCELLED; } /* hmmmm */ if (ibuf->channels < 3) { - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return OPERATOR_CANCELLED; } @@ -2288,7 +2366,7 @@ static int image_sample_line_exec(bContext *C, wmOperator *op) /* reset y zoom */ hist->ymax = 1.0f; - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); ED_area_tag_redraw(CTX_wm_area(C)); @@ -2383,11 +2461,13 @@ static int image_record_composite_apply(bContext *C, wmOperator *op) ED_area_tag_redraw(CTX_wm_area(C)); - ibuf = BKE_image_get_ibuf(sima->image, &sima->iuser); + ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, NULL); /* save memory in flipbooks */ if (ibuf) imb_freerectfloatImBuf(ibuf); - + + BKE_image_release_ibuf(sima->image, ibuf, NULL); + scene->r.cfra++; return (scene->r.cfra <= rcd->efra); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 4131cbfdd0d..ea696772957 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -780,7 +780,7 @@ static void image_scope_area_draw(const bContext *C, ARegion *ar) } scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings); } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); ED_region_panels(C, ar, 1, NULL, -1); } diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c index 131908bc9db..48b5eaf7b44 100644 --- a/source/blender/editors/space_info/info_ops.c +++ b/source/blender/editors/space_info/info_ops.c @@ -87,10 +87,14 @@ static int pack_all_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) // first check for dirty images for (ima = bmain->image.first; ima; ima = ima->id.next) { if (ima->ibufs.first) { /* XXX FIX */ - ibuf = BKE_image_get_ibuf(ima, NULL); + ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); - if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) + if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) { + BKE_image_release_ibuf(ima, ibuf, NULL); break; + } + + BKE_image_release_ibuf(ima, ibuf, NULL); } } diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c index f108881091a..cba0a808d63 100644 --- a/source/blender/editors/space_info/space_info.c +++ b/source/blender/editors/space_info/space_info.c @@ -58,6 +58,7 @@ #include "UI_view2d.h" #include "info_intern.h" /* own include */ +#include "BLO_readfile.h" /* ******************** default callbacks for info space ***************** */ @@ -271,11 +272,16 @@ static void info_header_listener(ARegion *ar, wmNotifier *wmn) static void recent_files_menu_draw(const bContext *UNUSED(C), Menu *menu) { struct RecentFile *recent; + char file [FILE_MAX]; uiLayout *layout = menu->layout; uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN); if (G.recent_files.first) { for (recent = G.recent_files.first; (recent); recent = recent->next) { - uiItemStringO(layout, BLI_path_basename(recent->filepath), ICON_FILE_BLEND, "WM_OT_open_mainfile", "filepath", recent->filepath); + BLI_split_file_part(recent->filepath, file, sizeof(file)); + if (BLO_has_bfile_extension(file)) + uiItemStringO(layout, BLI_path_basename(recent->filepath), ICON_FILE_BLEND, "WM_OT_open_mainfile", "filepath", recent->filepath); + else + uiItemStringO(layout, BLI_path_basename(recent->filepath), ICON_FILE_BACKUP, "WM_OT_open_mainfile", "filepath", recent->filepath); } } else { diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 0938562857b..92edac356e6 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -108,6 +108,43 @@ static void node_socket_button_default(const bContext *C, uiBlock *block, } } +static void node_socket_button_string(const bContext *C, uiBlock *block, + bNodeTree *ntree, bNode *node, bNodeSocket *sock, + const char *name, int x, int y, int width) +{ + if (sock->link || (sock->flag & SOCK_HIDE_VALUE)) + node_socket_button_label(C, block, ntree, node, sock, name, x, y, width); + else { + PointerRNA ptr; + uiBut *bt; + + SpaceNode *snode = CTX_wm_space_node(C); + const char *ui_name = IFACE_(name); + float slen; + + UI_ThemeColor(TH_TEXT); + slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect_sqrt; + while (slen > (width * 0.5f) && *ui_name) { + ui_name = BLI_str_find_next_char_utf8(ui_name, NULL); + slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect_sqrt; + } + + RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr); + + if (name[0] == '\0') + slen = 0.0; + + bt = uiDefButR(block, TEX, B_NODE_EXEC, "", + x, y + 1, width - slen, NODE_DY - 2, + &ptr, "default_value", 0, 0, 0, -1, -1, ""); + if (node) + uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node); + + if (slen > 0.0f) + uiDefBut(block, LABEL, 0, IFACE_(name), x + (width - slen), y + 2, slen, NODE_DY - 2, NULL, 0, 0, 0, 0, ""); + } +} + typedef struct SocketComponentMenuArgs { PointerRNA ptr; int x, y, width; @@ -209,9 +246,9 @@ static void node_draw_output_default(const bContext *C, uiBlock *block, if (*ui_name) { uiDefBut(block, LABEL, 0, ui_name, - (int)(sock->locx - slen), (int)(sock->locy - 9.0f), - (short)slen, (short)NODE_DY, - NULL, 0, 0, 0, 0, ""); + (int)(sock->locx - slen), (int)(sock->locy - 9.0f), + (short)slen, (short)NODE_DY, + NULL, 0, 0, 0, 0, ""); } } @@ -282,7 +319,7 @@ static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr RNA_property_collection_lookup_int(ptr, prop, 0, &sockptr); col = uiLayoutColumn(layout, FALSE); - uiTemplateColorWheel(col, &sockptr, "default_value", 1, 0, 0, 0); + uiTemplateColorPicker(col, &sockptr, "default_value", 1, 0, 0, 0); uiItemR(col, &sockptr, "default_value", 0, "", ICON_NONE); } @@ -361,29 +398,15 @@ static void node_buts_curvecol(uiLayout *layout, bContext *UNUSED(C), PointerRNA uiTemplateCurveMapping(layout, ptr, "mapping", 'c', 0, 0); } -static void node_normal_cb(bContext *C, void *ntree_v, void *node_v) -{ - Main *bmain = CTX_data_main(C); - - ED_node_generic_update(bmain, ntree_v, node_v); - WM_event_add_notifier(C, NC_NODE | NA_EDITED, ntree_v); -} - static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiBlock *block = uiLayoutAbsoluteBlock(layout); - bNodeTree *ntree = ptr->id.data; - bNode *node = ptr->data; - rctf *butr = &node->butr; + bNodeTree *ntree = (bNodeTree*)ptr->id.data; + bNode *node = (bNode*)ptr->data; bNodeSocket *sock = node->outputs.first; /* first socket stores normal */ - float *nor = ((bNodeSocketValueVector *)sock->default_value)->value; - uiBut *bt; - - bt = uiDefButF(block, BUT_NORMAL, B_NODE_EXEC, "", - (int)butr->xmin, (int)butr->xmin, - (short)BLI_rctf_size_x(butr), (short)BLI_rctf_size_x(butr), - nor, 0.0f, 1.0f, 0, 0, ""); - uiButSetFunc(bt, node_normal_cb, ntree, node); + PointerRNA sockptr; + + RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &sockptr); + uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE); } #if 0 /* not used in 2.5x yet */ static void node_browse_tex_cb(bContext *C, void *ntree_v, void *node_v) @@ -486,8 +509,9 @@ static void node_update_group(const bContext *C, bNodeTree *ntree, bNode *gnode) bNodeSocket *sock, *gsock; float locx, locy; rctf *rect = &gnode->totr; - float node_group_frame = U.dpi * NODE_GROUP_FRAME / 72; - float group_header = 26 * U.dpi / 72; + const float dpi_fac = UI_DPI_ICON_FAC; + const float node_group_frame = NODE_GROUP_FRAME * dpi_fac; + const float group_header = 26 * dpi_fac; int counter; int dy; @@ -664,7 +688,7 @@ static void draw_group_socket_name(SpaceNode *snode, bNode *gnode, bNodeSocket * static void draw_group_socket(const bContext *C, SpaceNode *snode, bNodeTree *ntree, bNode *gnode, bNodeSocket *sock, bNodeSocket *gsock, int index, int in_out) { - const float dpi_fac = U.dpi / 72.0f; + const float dpi_fac = UI_DPI_ICON_FAC; bNodeTree *ngroup = (bNodeTree *)gnode->id; bNodeSocketType *stype = ntreeGetSocketType(gsock ? gsock->type : sock->type); uiBut *bt; @@ -776,9 +800,9 @@ static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bN uiLayout *layout; PointerRNA ptr; rctf rect = gnode->totr; - const float dpi_fac = U.dpi / 72.0f; - float node_group_frame = NODE_GROUP_FRAME * dpi_fac; - float group_header = 26 * dpi_fac; + const float dpi_fac = UI_DPI_ICON_FAC; + const float node_group_frame = NODE_GROUP_FRAME * dpi_fac; + const float group_header = 26 * dpi_fac; int index; @@ -1379,6 +1403,46 @@ static void node_shader_buts_tex_coord(uiLayout *layout, bContext *UNUSED(C), Po uiItemR(layout, ptr, "from_dupli", 0, NULL, 0); } +static void node_shader_buts_normal_map(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + uiItemR(layout, ptr, "space", 0, "", 0); + + if (RNA_enum_get(ptr, "space") == SHD_NORMAL_MAP_TANGENT) { + PointerRNA obptr = CTX_data_pointer_get(C, "active_object"); + + if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { + PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); + uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_textures", "", ICON_NONE); + } + else + uiItemR(layout, ptr, "uv_map", 0, "", 0); + } +} + +static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + uiLayout *split, *row; + + split = uiLayoutSplit(layout, 0.0f, FALSE); + + uiItemR(split, ptr, "direction_type", 0, "", 0); + + row = uiLayoutRow(split, FALSE); + + if (RNA_enum_get(ptr, "direction_type") == SHD_TANGENT_UVMAP) { + PointerRNA obptr = CTX_data_pointer_get(C, "active_object"); + + if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) { + PointerRNA dataptr = RNA_pointer_get(&obptr, "data"); + uiItemPointerR(row, ptr, "uv_map", &dataptr, "uv_textures", "", ICON_NONE); + } + else + uiItemR(row, ptr, "uv_map", 0, "", 0); + } + else + uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, 0); +} + static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE); @@ -1407,9 +1471,10 @@ static void node_shader_buts_script_details(uiLayout *layout, bContext *C, Point node_shader_buts_script(layout, C, ptr); - /* not implemented yet - if(RNA_enum_get(ptr, "mode") == NODE_SCRIPT_EXTERNAL) - uiItemR(layout, ptr, "use_auto_update", 0, NULL, ICON_NONE);*/ +#if 0 /* not implemented yet */ + if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_EXTERNAL) + uiItemR(layout, ptr, "use_auto_update", 0, NULL, ICON_NONE); +#endif } /* only once called */ @@ -1491,8 +1556,15 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_TEX_COORD: ntype->uifunc = node_shader_buts_tex_coord; break; + case SH_NODE_NORMAL_MAP: + ntype->uifunc = node_shader_buts_normal_map; + break; + case SH_NODE_TANGENT: + ntype->uifunc = node_shader_buts_tangent; + break; case SH_NODE_BSDF_GLOSSY: case SH_NODE_BSDF_GLASS: + case SH_NODE_BSDF_REFRACTION: ntype->uifunc = node_shader_buts_glossy; break; case SH_NODE_SCRIPT: @@ -1802,6 +1874,14 @@ static void node_composit_buts_double_edge_mask(uiLayout *layout, bContext *UNUS uiItemR(col, ptr, "edge_mode", 0, "", ICON_NONE); } +static void node_composit_buts_map_range(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiLayout *col; + + col = uiLayoutColumn(layout, TRUE); + uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE); +} + static void node_composit_buts_map_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *sub, *col; @@ -2173,17 +2253,17 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C split = uiLayoutSplit(layout, 0.0f, FALSE); col = uiLayoutColumn(split, FALSE); - uiTemplateColorWheel(col, ptr, "lift", 1, 1, 0, 1); + uiTemplateColorPicker(col, ptr, "lift", 1, 1, 0, 1); row = uiLayoutRow(col, FALSE); uiItemR(row, ptr, "lift", 0, NULL, ICON_NONE); col = uiLayoutColumn(split, FALSE); - uiTemplateColorWheel(col, ptr, "gamma", 1, 1, 1, 1); + uiTemplateColorPicker(col, ptr, "gamma", 1, 1, 1, 1); row = uiLayoutRow(col, FALSE); uiItemR(row, ptr, "gamma", 0, NULL, ICON_NONE); col = uiLayoutColumn(split, FALSE); - uiTemplateColorWheel(col, ptr, "gain", 1, 1, 1, 1); + uiTemplateColorPicker(col, ptr, "gain", 1, 1, 1, 1); row = uiLayoutRow(col, FALSE); uiItemR(row, ptr, "gain", 0, NULL, ICON_NONE); @@ -2192,17 +2272,17 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C split = uiLayoutSplit(layout, 0.0f, FALSE); col = uiLayoutColumn(split, FALSE); - uiTemplateColorWheel(col, ptr, "offset", 1, 1, 0, 1); + uiTemplateColorPicker(col, ptr, "offset", 1, 1, 0, 1); row = uiLayoutRow(col, FALSE); uiItemR(row, ptr, "offset", 0, NULL, ICON_NONE); col = uiLayoutColumn(split, FALSE); - uiTemplateColorWheel(col, ptr, "power", 1, 1, 0, 1); + uiTemplateColorPicker(col, ptr, "power", 1, 1, 0, 1); row = uiLayoutRow(col, FALSE); uiItemR(row, ptr, "power", 0, NULL, ICON_NONE); col = uiLayoutColumn(split, FALSE); - uiTemplateColorWheel(col, ptr, "slope", 1, 1, 0, 1); + uiTemplateColorPicker(col, ptr, "slope", 1, 1, 0, 1); row = uiLayoutRow(col, FALSE); uiItemR(row, ptr, "slope", 0, NULL, ICON_NONE); } @@ -2214,23 +2294,23 @@ static void node_composit_buts_colorbalance_but(uiLayout *layout, bContext *UNUS if (RNA_enum_get(ptr, "correction_method") == 0) { - uiTemplateColorWheel(layout, ptr, "lift", 1, 1, 0, 1); + uiTemplateColorPicker(layout, ptr, "lift", 1, 1, 0, 1); uiItemR(layout, ptr, "lift", 0, NULL, ICON_NONE); - uiTemplateColorWheel(layout, ptr, "gamma", 1, 1, 1, 1); + uiTemplateColorPicker(layout, ptr, "gamma", 1, 1, 1, 1); uiItemR(layout, ptr, "gamma", 0, NULL, ICON_NONE); - uiTemplateColorWheel(layout, ptr, "gain", 1, 1, 1, 1); + uiTemplateColorPicker(layout, ptr, "gain", 1, 1, 1, 1); uiItemR(layout, ptr, "gain", 0, NULL, ICON_NONE); } else { - uiTemplateColorWheel(layout, ptr, "offset", 1, 1, 0, 1); + uiTemplateColorPicker(layout, ptr, "offset", 1, 1, 0, 1); uiItemR(layout, ptr, "offset", 0, NULL, ICON_NONE); - uiTemplateColorWheel(layout, ptr, "power", 1, 1, 0, 1); + uiTemplateColorPicker(layout, ptr, "power", 1, 1, 0, 1); uiItemR(layout, ptr, "power", 0, NULL, ICON_NONE); - uiTemplateColorWheel(layout, ptr, "slope", 1, 1, 0, 1); + uiTemplateColorPicker(layout, ptr, "slope", 1, 1, 0, 1); uiItemR(layout, ptr, "slope", 0, NULL, ICON_NONE); } } @@ -2740,6 +2820,9 @@ static void node_composit_set_butfunc(bNodeType *ntype) case CMP_NODE_MAP_VALUE: ntype->uifunc = node_composit_buts_map_value; break; + case CMP_NODE_MAP_RANGE: + ntype->uifunc = node_composit_buts_map_range; + break; case CMP_NODE_TIME: ntype->uifunc = node_buts_time; break; @@ -3089,6 +3172,9 @@ void ED_node_init_butfuncs(void) case SOCK_BOOLEAN: stype->buttonfunc = node_socket_button_default; break; + case SOCK_STRING: + stype->buttonfunc = node_socket_button_string; + break; case SOCK_VECTOR: stype->buttonfunc = node_socket_button_components; break; @@ -3214,7 +3300,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode) glPopMatrix(); } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); } } @@ -3227,7 +3313,7 @@ static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode) if (snode->flag & SNODE_BACKDRAW) { Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ibuf) { int x, y; float zoom = 1.0; @@ -3263,6 +3349,8 @@ static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode) glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); + + BKE_image_release_ibuf(ima, ibuf, NULL); } } } diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c index 04d2947ce89..96ac716f383 100644 --- a/source/blender/editors/space_node/node_add.c +++ b/source/blender/editors/space_node/node_add.c @@ -386,6 +386,9 @@ static int node_add_file_exec(bContext *C, wmOperator *op) node->id = (ID *)ima; id_us_plus(node->id); + BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); + WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); + snode_notify(C, snode); snode_dag_update(C, snode); diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 1d3b21fe2d6..72461cfb2a8 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -843,7 +843,7 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b rctf *rct = &node->totr; float dx, centy = BLI_rctf_cent_y(rct); float hiddenrad = BLI_rctf_size_y(rct) / 2.0f; - float socket_size = NODE_SOCKSIZE * U.dpi / 72; + float socket_size = NODE_SOCKSIZE * UI_DPI_ICON_FAC; int color_id = node_get_colorid(node); char showname[128]; /* 128 is used below */ diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 6bf0e9f73e3..f757345bdcb 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -86,6 +86,7 @@ typedef struct CompoJob { short *stop; short *do_update; float *progress; + short need_sync; } CompoJob; /* called by compo, only to check job 'stop' value */ @@ -102,8 +103,17 @@ static int compo_breakjob(void *cjv) ); } +/* called by compo, wmJob sends notifier, old compositor system only */ +static void compo_statsdrawjob(void *cjv, char *UNUSED(str)) +{ + CompoJob *cj = cjv; + + *(cj->do_update) = TRUE; + cj->need_sync = TRUE; +} + /* called by compo, wmJob sends notifier */ -static void compo_redrawjob(void *cjv, char *UNUSED(str)) +static void compo_redrawjob(void *cjv) { CompoJob *cj = cjv; @@ -133,8 +143,15 @@ static void compo_initjob(void *cjv) static void compo_updatejob(void *cjv) { CompoJob *cj = cjv; - - ntreeLocalSync(cj->localtree, cj->ntree); + + if (cj->need_sync) { + /* was used by old compositor system only */ + ntreeLocalSync(cj->localtree, cj->ntree); + + cj->need_sync = FALSE; + } + + WM_main_add_notifier(NC_WINDOW | ND_DRAW, NULL); } static void compo_progressjob(void *cjv, float progress) @@ -161,11 +178,13 @@ static void compo_startjob(void *cjv, short *stop, short *do_update, float *prog ntree->test_break = compo_breakjob; ntree->tbh = cj; - ntree->stats_draw = compo_redrawjob; + ntree->stats_draw = compo_statsdrawjob; ntree->sdh = cj; ntree->progress = compo_progressjob; ntree->prh = cj; - + ntree->update_draw = compo_redrawjob; + ntree->udh = cj; + // XXX BIF_store_spare(); ntreeCompositExecTree(ntree, &cj->scene->r, 0, 1, &scene->view_settings, &scene->display_settings); /* 1 is do_previews */ @@ -177,7 +196,7 @@ static void compo_startjob(void *cjv, short *stop, short *do_update, float *prog } /** - * \param sa_owner is the owner of the job, + * \param scene_owner is the owner of the job, * we don't use it for anything else currently so could also be a void pointer, * but for now keep it an 'Scene' for consistency. * @@ -2226,13 +2245,13 @@ static int node_shader_script_update_exec(bContext *C, wmOperator *op) data.text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data; if (data.text) { - bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER); + bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER); if (ntreetype && ntreetype->foreach_nodetree) ntreetype->foreach_nodetree(bmain, &data, node_shader_script_update_text); if (!data.found) - BKE_report(op->reports, RPT_INFO, "Text not used by any node, no update done."); + BKE_report(op->reports, RPT_INFO, "Text not used by any node, no update done"); } } diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index 5f8b5db7766..4dd9c89375d 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -29,13 +29,18 @@ * \ingroup spnode */ +#include + #include "MEM_guardedalloc.h" #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_anim_types.h" -#include "BLI_blenlib.h" +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_rect.h" +#include "BLI_math.h" #include "BKE_action.h" #include "BKE_animsys.h" @@ -865,7 +870,7 @@ static void node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min, if (node == gnode) continue; if (node->flag & NODE_SELECT) { - DO_MINMAX2((&node->locx), min, max); + minmax_v2v2_v2(min, max, &node->locx); } } } diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index ccf5c4b540f..f386657c460 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -241,7 +241,7 @@ static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event) ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (ibuf == NULL) { - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); return OPERATOR_CANCELLED; } @@ -255,7 +255,7 @@ static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event) nvm->ymin = -(ar->winy / 2) - (ibuf->y * (0.5f * snode->zoom)) + pad; nvm->ymax = (ar->winy / 2) + (ibuf->y * (0.5f * snode->zoom)) - pad; - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); /* add modal handler */ WM_event_add_modal_handler(C, op); @@ -330,6 +330,12 @@ typedef struct ImageSampleInfo { unsigned char col[4]; float colf[4]; + + int z; + float zf; + + int *zp; + float *zfp; int draw; int color_manage; @@ -343,8 +349,7 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) if (info->draw) { ED_image_draw_info(scene, ar, info->color_manage, FALSE, info->channels, info->x, info->y, info->col, info->colf, - NULL, NULL /* zbuf - unused for nodes */ - ); + info->zp, info->zfp); } } @@ -398,7 +403,7 @@ int ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float } } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); return ret; } @@ -443,6 +448,9 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->draw = 1; info->channels = ibuf->channels; + info->zp = NULL; + info->zfp = NULL; + if (ibuf->rect) { cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x); @@ -468,6 +476,15 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->color_manage = TRUE; } + + if (ibuf->zbuf) { + info->z = ibuf->zbuf[y * ibuf->x + x]; + info->zp = &info->z; + } + if (ibuf->zbuf_float) { + info->zf = ibuf->zbuf_float[y * ibuf->x + x]; + info->zfp = &info->zf; + } ED_node_sample_set(info->colf); } @@ -476,7 +493,7 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) ED_node_sample_set(NULL); } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); ED_area_tag_redraw(CTX_wm_area(C)); } diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 4d2512cdc93..f7e0d51ea03 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -193,6 +193,8 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn) ED_area_tag_refresh(sa); else if (wmn->data == ND_SHADING_DRAW) ED_area_tag_refresh(sa); + else if (wmn->data == ND_SHADING_LINKS) + ED_area_tag_refresh(sa); else if (wmn->action == NA_ADDED && snode->edittree) nodeSetActiveID(snode->edittree, ID_MA, wmn->reference); diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index c4afe32e85f..d37cb4be8fa 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -631,7 +631,7 @@ static uiBlock *operator_search_menu(bContext *C, ARegion *ar, void *arg_kmi) uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_SEARCH_MENU); /* fake button, it holds space for search items */ - uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); + uiDefBut(block, LABEL, 0, "", 10, 15, uiSearchBoxWidth(), uiSearchBoxHeight(), NULL, 0, 0, 0, 0, NULL); but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, 150, UI_UNIT_Y, 0, 0, ""); uiButSetSearchFunc(but, operator_search_cb, arg_kmi, operator_call_cb, ot); @@ -1038,11 +1038,13 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto UI_icon_draw(x, y, ICON_MOD_WARP); break; case eModifierType_Skin: UI_icon_draw(x, y, ICON_MOD_SKIN); break; + case eModifierType_Triangulate: + UI_icon_draw(x, y, ICON_MOD_TRIANGULATE); break; /* Default */ case eModifierType_None: case eModifierType_ShapeKey: - case NUM_MODIFIER_TYPES: + case NUM_MODIFIER_TYPES: UI_icon_draw(x, y, ICON_DOT); break; } break; diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 23766d6a6fe..d11a8ed6369 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -836,6 +836,8 @@ static int outliner_one_level_exec(bContext *C, wmOperator *op) void OUTLINER_OT_show_one_level(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Show/Hide One Level"; ot->idname = "OUTLINER_OT_show_one_level"; @@ -848,7 +850,8 @@ void OUTLINER_OT_show_one_level(wmOperatorType *ot) /* no undo or registry, UI option */ /* properties */ - RNA_def_boolean(ot->srna, "open", 1, "Open", "Expand all entries one level deep"); + prop = RNA_def_boolean(ot->srna, "open", 1, "Open", "Expand all entries one level deep"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* Show Hierarchy ----------------------------------------------- */ @@ -1859,7 +1862,7 @@ static int material_drop_invoke(bContext *C, wmOperator *op, wmEvent *event) DAG_ids_flush_update(bmain, 0); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C)); - WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING, ma); + WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 4668dfa1386..0b585e1272b 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -222,7 +222,7 @@ static int tree_element_active_material(bContext *C, Scene *scene, SpaceOops *so } } if (set) { - WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING, NULL); + WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, NULL); } return 0; } diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index af890a81ad6..e6910280da4 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -133,7 +133,7 @@ static void outliner_storage_cleanup(SpaceOops *soops) } /* XXX - THIS FUNCTION IS INCREDIBLY SLOW - * ... it can bring blenders tools and viewport to a grinding halt becuase of searching + * ... it can bring blenders tools and viewport to a grinding halt because of searching * for duplicate items every times they are added. * * TODO (possible speedups) diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 6cfc3f97b31..ecc09a35670 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -326,19 +326,14 @@ static void outliner_main_area_listener(ARegion *ar, wmNotifier *wmn) break; case NC_MATERIAL: switch (wmn->data) { - case ND_SHADING: - case ND_SHADING_DRAW: + case ND_SHADING_LINKS: ED_region_tag_redraw(ar); break; } break; - case NC_TEXTURE: - ED_region_tag_redraw(ar); - break; case NC_GEOM: switch (wmn->data) { - case ND_DATA: - /* needed for vertex groups only, no special notifier atm so use NC_GEOM|ND_DATA */ + case ND_VERTEX_GROUP: ED_region_tag_redraw(ar); break; } diff --git a/source/blender/editors/space_sequencer/SConscript b/source/blender/editors/space_sequencer/SConscript index 0b429ae750b..bc72786fc5f 100644 --- a/source/blender/editors/space_sequencer/SConscript +++ b/source/blender/editors/space_sequencer/SConscript @@ -3,7 +3,7 @@ Import ('env') sources = env.Glob('*.c') -incs = '../include ../../blenlib ../../blenkernel ../../blenfont ../../makesdna ../../imbuf' +incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../makesrna ../../blenloader ../../blenfont' incs += ' #/intern/audaspace/intern' diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 29babd355ad..1a84efa0b50 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -285,8 +285,8 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, drawmeta_stipple(1); for (seq = seqm->seqbase.first; seq; seq = seq->next) { - chan_min = MIN2(chan_min, seq->machine); - chan_max = MAX2(chan_max, seq->machine); + chan_min = min_ii(chan_min, seq->machine); + chan_max = max_ii(chan_max, seq->machine); } chan_range = (chan_max - chan_min) + 1; @@ -822,6 +822,7 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int int rectx, recty; float render_size = 0.0; float proxy_size = 100.0; + short is_break = G.is_break; render_size = sseq->render_size; if (render_size == 0) { @@ -840,6 +841,11 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int context = BKE_sequencer_new_render_data(bmain, scene, rectx, recty, proxy_size); + /* sequencer could start rendering, in this case we need to be sure it wouldn't be canceled + * by Esc pressed somewhere in the past + */ + G.is_break = FALSE; + if (special_seq_update) ibuf = BKE_sequencer_give_ibuf_direct(context, cfra + frame_ofs, special_seq_update); else if (!U.prefetchframes) // XXX || (G.f & G_PLAYANIM) == 0) { @@ -847,6 +853,9 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int else ibuf = BKE_sequencer_give_ibuf_threaded(context, cfra + frame_ofs, sseq->chanshown); + /* restore state so real rendering would be canceled (if needed) */ + G.is_break = is_break; + return ibuf; } @@ -913,6 +922,13 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq unsigned char *display_buffer; void *cache_handle = NULL; + if (G.is_rendering == FALSE) { + /* stop all running jobs, except screen one. currently previews frustrate Render + * needed to make so sequencer's rendering doesn't conflict with compositor + */ + WM_jobs_kill_type(CTX_wm_manager(C), WM_JOB_TYPE_COMPOSITE); + } + render_size = sseq->render_size; if (render_size == 0) { render_size = scene->r.size; diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 7270516aa51..e7f77db3b9e 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -1686,7 +1686,7 @@ static int sequencer_delete_invoke(bContext *C, wmOperator *op, wmEvent *event) if (ar->regiontype == RGN_TYPE_WINDOW) { /* bounding box of 30 pixels is used for markers shortcuts, - * prevent conflict with markers shortcurts here + * prevent conflict with markers shortcuts here */ if (event->mval[1] <= 30) return OPERATOR_PASS_THROUGH; @@ -1850,6 +1850,7 @@ void SEQUENCER_OT_images_separate(wmOperatorType *ot) /* api callbacks */ ot->exec = sequencer_separate_images_exec; + ot->invoke = WM_operator_props_popup; ot->poll = sequencer_edit_poll; /* flags */ @@ -2404,6 +2405,15 @@ static int strip_jump_internal(Scene *scene, return change; } +static int sequencer_strip_jump_poll(bContext *C) +{ + /* prevent changes during render */ + if (G.is_rendering) + return 0; + + return sequencer_edit_poll(C); +} + /* jump frame to edit point operator */ static int sequencer_strip_jump_exec(bContext *C, wmOperator *op) { @@ -2430,7 +2440,7 @@ void SEQUENCER_OT_strip_jump(wmOperatorType *ot) /* api callbacks */ ot->exec = sequencer_strip_jump_exec; - ot->poll = sequencer_edit_poll; + ot->poll = sequencer_strip_jump_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -3075,8 +3085,12 @@ static int sequencer_change_path_invoke(bContext *C, wmOperator *op, wmEvent *UN { Scene *scene = CTX_data_scene(C); Sequence *seq = BKE_sequencer_active_get(scene); + char filepath[FILE_MAX]; + + BLI_join_dirfile(filepath, sizeof(filepath), seq->strip->dir, seq->strip->stripdata->name); RNA_string_set(op->ptr, "directory", seq->strip->dir); + RNA_string_set(op->ptr, "filepath", filepath); /* set default display depending on seq type */ if (seq->type == SEQ_TYPE_IMAGE) { diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index 3f70b2cb66e..d74e32620af 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -196,10 +196,6 @@ static void text_operatortypes(void) WM_operatortype_append(TEXT_OT_unindent); WM_operatortype_append(TEXT_OT_indent); - WM_operatortype_append(TEXT_OT_markers_clear); - WM_operatortype_append(TEXT_OT_next_marker); - WM_operatortype_append(TEXT_OT_previous_marker); - WM_operatortype_append(TEXT_OT_select_line); WM_operatortype_append(TEXT_OT_select_all); WM_operatortype_append(TEXT_OT_select_word); @@ -227,7 +223,6 @@ static void text_operatortypes(void) WM_operatortype_append(TEXT_OT_find_set_selected); WM_operatortype_append(TEXT_OT_replace); WM_operatortype_append(TEXT_OT_replace_set_selected); - WM_operatortype_append(TEXT_OT_mark_all); WM_operatortype_append(TEXT_OT_to_3d_object); diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index 94f64563fd8..46ab2d9e688 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -95,7 +95,7 @@ static int text_font_draw_character(SpaceText *st, int x, int y, char c) static int text_font_draw_character_utf8(SpaceText *st, int x, int y, const char *c) { char str[BLI_UTF8_MAX + 1]; - size_t len = BLI_str_utf8_size(c); + size_t len = BLI_str_utf8_size_safe(c); memcpy(str, c, len); str[len] = '\0'; @@ -158,7 +158,7 @@ int flatten_string(SpaceText *st, FlattenString *fs, const char *in) in++; } else { - size_t len = BLI_str_utf8_size(in); + size_t len = BLI_str_utf8_size_safe(in); flatten_string_append(fs, in, r, len); in += len; total++; @@ -342,7 +342,7 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next) if (*str == '\\') { *fmt = prev; fmt++; str++; if (*str == '\0') break; - *fmt = prev; fmt++; str += BLI_str_utf8_size(str); + *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str); continue; } /* Handle continuations */ @@ -363,14 +363,14 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next) } *fmt = 'l'; - str += BLI_str_utf8_size(str) - 1; + str += BLI_str_utf8_size_safe(str) - 1; } /* Not in a string... */ else { /* Deal with comments first */ if (prev == '#' || *str == '#') { *fmt = '#'; - str += BLI_str_utf8_size(str) - 1; + str += BLI_str_utf8_size_safe(str) - 1; } else if (*str == '"' || *str == '\'') { /* Strings */ @@ -399,7 +399,7 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next) *fmt = 'n'; } else { - str += BLI_str_utf8_size(str) - 1; + str += BLI_str_utf8_size_safe(str) - 1; *fmt = 'q'; } /* Punctuation */ @@ -407,7 +407,7 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next) *fmt = '!'; /* Identifiers and other text (no previous ws. or delims. so text continues) */ else if (prev == 'q') { - str += BLI_str_utf8_size(str) - 1; + str += BLI_str_utf8_size_safe(str) - 1; *fmt = 'q'; } /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */ @@ -427,7 +427,7 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next) *fmt = prev; } else { - str += BLI_str_utf8_size(str) - 1; + str += BLI_str_utf8_size_safe(str) - 1; *fmt = 'q'; } } @@ -575,7 +575,7 @@ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int * end = max; chop = 1; *offc = 0; - for (i = 0, j = 0; linep->line[j]; j += BLI_str_utf8_size(linep->line + j)) { + for (i = 0, j = 0; linep->line[j]; j += BLI_str_utf8_size_safe(linep->line + j)) { int chars; /* Mimic replacement of tabs */ @@ -640,7 +640,7 @@ void wrap_offset_in_line(SpaceText *st, ARegion *ar, TextLine *linein, int cursi *offc = 0; cursin = txt_utf8_offset_to_index(linein->line, cursin); - for (i = 0, j = 0; linein->line[j]; j += BLI_str_utf8_size(linein->line + j)) { + for (i = 0, j = 0; linein->line[j]; j += BLI_str_utf8_size_safe(linein->line + j)) { /* Mimic replacement of tabs */ ch = linein->line[j]; @@ -685,7 +685,7 @@ int text_get_char_pos(SpaceText *st, const char *line, int cur) { int a = 0, i; - for (i = 0; i < cur && line[i]; i += BLI_str_utf8_size(line + i)) { + for (i = 0; i < cur && line[i]; i += BLI_str_utf8_size_safe(line + i)) { if (line[i] == '\t') a += st->tabnumber - a % st->tabnumber; else @@ -698,7 +698,7 @@ static const char *txt_utf8_get_nth(const char *str, int n) { int pos = 0; while (str[pos] && n--) { - pos += BLI_str_utf8_size(str + pos); + pos += BLI_str_utf8_size_safe(str + pos); } return str + pos; } @@ -719,7 +719,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w start = 0; mstart = 0; end = max; mend = txt_utf8_get_nth(str, max) - str; - for (i = 0, mi = 0; str[mi]; i++, mi += BLI_str_utf8_size(str + mi)) { + for (i = 0, mi = 0; str[mi]; i++, mi += BLI_str_utf8_size_safe(str + mi)) { if (i - start >= max) { /* skip hidden part of line */ if (skip) { @@ -730,11 +730,11 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w } /* Draw the visible portion of text on the overshot line */ - for (a = start, ma = mstart; a < end; a++, ma += BLI_str_utf8_size(str + ma)) { + for (a = start, ma = mstart; a < end; a++, ma += BLI_str_utf8_size_safe(str + ma)) { if (st->showsyntax && format) format_draw_color(format[a]); x += text_font_draw_character_utf8(st, x, y, str + ma); } - y -= st->lheight; + y -= st->lheight + TXT_LINE_SPACING; x = basex; lines++; start = end; mstart = mend; @@ -748,7 +748,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w } /* Draw the remaining text */ - for (a = start, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size(str + ma)) { + for (a = start, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size_safe(str + ma)) { if (st->showsyntax && format) format_draw_color(format[a]); @@ -786,7 +786,7 @@ static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int dra for (a = 0; a < amount; a++) { format_draw_color(format[a]); x += text_font_draw_character_utf8(st, x, y, in + str_shift); - str_shift += BLI_str_utf8_size(in + str_shift); + str_shift += BLI_str_utf8_size_safe(in + str_shift); } } else text_font_draw(st, x, y, in); @@ -1016,7 +1016,7 @@ int text_get_visible_lines(SpaceText *st, ARegion *ar, const char *str) lines = 1; start = 0; end = max; - for (i = 0, j = 0; str[j]; j += BLI_str_utf8_size(str + j)) { + for (i = 0, j = 0; str[j]; j += BLI_str_utf8_size_safe(str + j)) { /* Mimic replacement of tabs */ ch = str[j]; if (ch == '\t') { @@ -1070,40 +1070,6 @@ int text_get_total_lines(SpaceText *st, ARegion *ar) return drawcache->total_lines; } -/* Move pointer to first visible line (top) */ -static TextLine *first_visible_line(SpaceText *st, ARegion *ar, int *wrap_top) -{ - Text *text = st->text; - TextLine *pline = text->lines.first; - int i = st->top, lineno = 0; - - text_update_drawcache(st, ar); - - if (wrap_top) *wrap_top = 0; - - if (st->wordwrap) { - while (i > 0 && pline) { - int lines = text_get_visible_lines_no(st, lineno); - - if (i - lines < 0) { - if (wrap_top) *wrap_top = i; - break; - } - else { - pline = pline->next; - i -= lines; - lineno++; - } - } - } - else { - for (i = st->top; pline->next && i > 0; i--) - pline = pline->next; - } - - return pline; -} - /************************ draw scrollbar *****************************/ static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll, rcti *back) @@ -1241,90 +1207,6 @@ static void draw_textscroll(SpaceText *st, rcti *scroll, rcti *back) glDisable(GL_BLEND); } -/************************** draw markers **************************/ - -static void draw_markers(SpaceText *st, ARegion *ar) -{ - Text *text = st->text; - TextMarker *marker, *next; - TextLine *top, *line; - int offl, offc, i, x1, x2, y1, y2, x, y; - int topi, topy; - - /* Move pointer to first visible line (top) */ - top = first_visible_line(st, ar, NULL); - topi = BLI_findindex(&text->lines, top); - - topy = txt_get_span(text->lines.first, top); - - for (marker = text->markers.first; marker; marker = next) { - next = marker->next; - - /* invisible line (before top) */ - if (marker->lineno < topi) continue; - - line = BLI_findlink(&text->lines, marker->lineno); - - /* Remove broken markers */ - if (marker->end > line->len || marker->start > marker->end) { - BLI_freelinkN(&text->markers, marker); - continue; - } - - wrap_offset(st, ar, line, marker->start, &offl, &offc); - y1 = txt_get_span(top, line) - st->top + offl + topy; - x1 = text_get_char_pos(st, line->line, marker->start) - st->left + offc; - - wrap_offset(st, ar, line, marker->end, &offl, &offc); - y2 = txt_get_span(top, line) - st->top + offl + topy; - x2 = text_get_char_pos(st, line->line, marker->end) - st->left + offc; - - /* invisible part of line (before top, after last visible line) */ - if (y2 < 0 || y1 > st->top + st->viewlines) continue; - - glColor3ubv(marker->color); - x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; - y = ar->winy - 3; - - if (y1 == y2) { - y -= y1 * st->lheight; - glBegin(GL_LINE_LOOP); - glVertex2i(x + x2 * st->cwidth + 1, y); - glVertex2i(x + x1 * st->cwidth - 2, y); - glVertex2i(x + x1 * st->cwidth - 2, y - st->lheight); - glVertex2i(x + x2 * st->cwidth + 1, y - st->lheight); - glEnd(); - } - else { - y -= y1 * st->lheight; - glBegin(GL_LINE_STRIP); - glVertex2i(ar->winx, y); - glVertex2i(x + x1 * st->cwidth - 2, y); - glVertex2i(x + x1 * st->cwidth - 2, y - st->lheight); - glVertex2i(ar->winx, y - st->lheight); - glEnd(); - y -= st->lheight; - - for (i = y1 + 1; i < y2; i++) { - glBegin(GL_LINES); - glVertex2i(x, y); - glVertex2i(ar->winx, y); - glVertex2i(x, y - st->lheight); - glVertex2i(ar->winx, y - st->lheight); - glEnd(); - y -= st->lheight; - } - - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x + x2 * st->cwidth + 1, y); - glVertex2i(x + x2 * st->cwidth + 1, y - st->lheight); - glVertex2i(x, y - st->lheight); - glEnd(); - } - } -} - /*********************** draw documentation *******************************/ static void draw_documentation(SpaceText *st, ARegion *ar) @@ -1494,6 +1376,7 @@ static void draw_cursor(SpaceText *st, ARegion *ar) Text *text = st->text; int vcurl, vcurc, vsell, vselc, hidden = 0; int x, y, w, i; + int lheight = st->lheight + TXT_LINE_SPACING; /* Draw the selection */ if (text->curl != text->sell || text->curc != text->selc) { @@ -1514,11 +1397,11 @@ static void draw_cursor(SpaceText *st, ARegion *ar) y = ar->winy - 2; if (vcurl == vsell) { - y -= vcurl * st->lheight; + y -= vcurl * lheight; if (vcurc < vselc) - glRecti(x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - st->lheight); + glRecti(x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - lheight + TXT_LINE_SPACING); else - glRecti(x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - st->lheight); + glRecti(x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - lheight + TXT_LINE_SPACING); } else { int froml, fromc, tol, toc; @@ -1532,12 +1415,12 @@ static void draw_cursor(SpaceText *st, ARegion *ar) fromc = vselc; toc = vcurc; } - y -= froml * st->lheight; - glRecti(x + fromc * st->cwidth - 1, y, ar->winx, y - st->lheight); y -= st->lheight; + y -= froml * lheight; + glRecti(x + fromc * st->cwidth - 1, y, ar->winx, y - lheight); y -= lheight; for (i = froml + 1; i < tol; i++) - glRecti(x - 4, y, ar->winx, y - st->lheight), y -= st->lheight; + glRecti(x - 4, y, ar->winx, y - lheight), y -= lheight; - glRecti(x - 4, y, x + toc * st->cwidth, y - st->lheight); y -= st->lheight; + glRecti(x - 4, y, x + toc * st->cwidth, y - lheight + TXT_LINE_SPACING); y -= lheight; } } else { @@ -1561,12 +1444,12 @@ static void draw_cursor(SpaceText *st, ARegion *ar) wrap_offset_in_line(st, ar, text->sell, text->selc, &offl, &offc); - y1 = ar->winy - 2 - (vsell - offl) * st->lheight; - y2 = y1 - st->lheight * visible_lines + 1; + y1 = ar->winy - 2 - (vsell - offl) * lheight; + y2 = y1 - lheight * visible_lines + 1; } else { - y1 = ar->winy - 2 - vsell * st->lheight; - y2 = y1 - st->lheight + 1; + y1 = ar->winy - 2 - vsell * lheight; + y2 = y1 - lheight + 1; } if (!(y1 < 0 || y2 > ar->winy)) { /* check we need to draw */ @@ -1577,7 +1460,7 @@ static void draw_cursor(SpaceText *st, ARegion *ar) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - glRecti(x1 - 4, y1, x2, y2); + glRecti(x1 - 4, y1, x2, y2 + TXT_LINE_SPACING); glDisable(GL_BLEND); } } @@ -1586,20 +1469,21 @@ static void draw_cursor(SpaceText *st, ARegion *ar) /* Draw the cursor itself (we draw the sel. cursor as this is the leading edge) */ x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; x += vselc * st->cwidth; - y = ar->winy - 2 - vsell * st->lheight; + y = ar->winy - 2 - vsell * lheight; if (st->overwrite) { char ch = text->sell->line[text->selc]; + y += TXT_LINE_SPACING; w = st->cwidth; if (ch == '\t') w *= st->tabnumber - (vselc + st->left) % st->tabnumber; UI_ThemeColor(TH_HILITE); - glRecti(x, y - st->lheight - 1, x + w, y - st->lheight + 1); + glRecti(x, y - lheight - 1, x + w, y - lheight + 1); } else { UI_ThemeColor(TH_HILITE); - glRecti(x - 1, y, x + 1, y - st->lheight); + glRecti(x - 1, y, x + 1, y - lheight + TXT_LINE_SPACING); } } } @@ -1639,7 +1523,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar) if (b > 0) { /* opening bracket, search forward for close */ fc++; - c += BLI_str_utf8_size(linep->line + c); + c += BLI_str_utf8_size_safe(linep->line + c); while (linep) { while (c < linep->len) { if (linep->format && linep->format[fc] != 'l' && linep->format[fc] != '#') { @@ -1657,7 +1541,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar) } } fc++; - c += BLI_str_utf8_size(linep->line + c); + c += BLI_str_utf8_size_safe(linep->line + c); } if (endl) break; linep = linep->next; @@ -1714,8 +1598,8 @@ static void draw_brackets(SpaceText *st, ARegion *ar) if (viewc >= 0) { viewl = txt_get_span(text->lines.first, startl) - st->top + offl; - text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * st->lheight, ch); - text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * st->lheight, ch); + text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * (st->lheight + TXT_LINE_SPACING), ch); + text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * (st->lheight + TXT_LINE_SPACING), ch); } /* draw closing bracket */ @@ -1726,8 +1610,8 @@ static void draw_brackets(SpaceText *st, ARegion *ar) if (viewc >= 0) { viewl = txt_get_span(text->lines.first, endl) - st->top + offl; - text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * st->lheight, ch); - text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * st->lheight, ch); + text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * (st->lheight + TXT_LINE_SPACING), ch); + text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * (st->lheight + TXT_LINE_SPACING), ch); } } @@ -1743,7 +1627,7 @@ void draw_text_main(SpaceText *st, ARegion *ar) int wraplinecount = 0, wrap_skip = 0; int margin_column_x; - if (st->lheight) st->viewlines = (int)ar->winy / st->lheight; + if (st->lheight) st->viewlines = (int)ar->winy / (st->lheight + TXT_LINE_SPACING); else st->viewlines = 0; /* if no text, nothing to do */ @@ -1832,14 +1716,14 @@ void draw_text_main(SpaceText *st, ARegion *ar) if (st->wordwrap) { /* draw word wrapped text */ int lines = text_draw_wrapped(st, tmp->line, x, y, winx - x, tmp->format, wrap_skip); - y -= lines * st->lheight; + y -= lines * (st->lheight + TXT_LINE_SPACING); } else { /* draw unwrapped text */ text_draw(st, tmp->line, st->left, ar->winx / st->cwidth, 1, x, y, tmp->format); - y -= st->lheight; + y -= st->lheight + TXT_LINE_SPACING; } - + wrap_skip = 0; } @@ -1858,7 +1742,6 @@ void draw_text_main(SpaceText *st, ARegion *ar) /* draw other stuff */ draw_brackets(st, ar); - draw_markers(st, ar); glTranslatef(GLA_PIXEL_OFS, GLA_PIXEL_OFS, 0.0f); /* XXX scroll requires exact pixel space */ draw_textscroll(st, &scroll, &back); draw_documentation(st, ar); diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h index 4f973e7076b..ea61644cee9 100644 --- a/source/blender/editors/space_text/text_intern.h +++ b/source/blender/editors/space_text/text_intern.h @@ -57,6 +57,7 @@ void text_update_cursor_moved(struct bContext *C); #define TXT_OFFSET 15 #define TXT_SCROLL_WIDTH 20 #define TXT_SCROLL_SPACE 2 +#define TXT_LINE_SPACING 4 /* space between lines */ #define TEXTXLOC (st->cwidth * st->linenrs_tot) @@ -68,9 +69,6 @@ void text_update_cursor_moved(struct bContext *C); #define TOOL_SUGG_LIST 0x01 #define TOOL_DOCUMENT 0x02 -#define TMARK_GRP_CUSTOM 0x00010000 /* Lower 2 bytes used for Python groups */ -#define TMARK_GRP_FINDALL 0x00020000 - typedef struct FlattenString { char fixedbuf[256]; int fixedaccum[256]; @@ -129,10 +127,6 @@ void TEXT_OT_indent(struct wmOperatorType *ot); void TEXT_OT_line_break(struct wmOperatorType *ot); void TEXT_OT_insert(struct wmOperatorType *ot); -void TEXT_OT_markers_clear(struct wmOperatorType *ot); -void TEXT_OT_next_marker(struct wmOperatorType *ot); -void TEXT_OT_previous_marker(struct wmOperatorType *ot); - void TEXT_OT_select_line(struct wmOperatorType *ot); void TEXT_OT_select_all(struct wmOperatorType *ot); void TEXT_OT_select_word(struct wmOperatorType *ot); @@ -157,7 +151,6 @@ void TEXT_OT_find(struct wmOperatorType *ot); void TEXT_OT_find_set_selected(struct wmOperatorType *ot); void TEXT_OT_replace(struct wmOperatorType *ot); void TEXT_OT_replace_set_selected(struct wmOperatorType *ot); -void TEXT_OT_mark_all(struct wmOperatorType *ot); void TEXT_OT_to_3d_object(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 2d902c4586a..5b7f92739ed 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -615,6 +615,8 @@ static int text_run_script(bContext *C, ReportList *reports) } BKE_report(reports, RPT_ERROR, "Python script fail, look in the console for now..."); + + return OPERATOR_FINISHED; } #else (void)C; @@ -1135,7 +1137,8 @@ static int text_convert_whitespace_exec(bContext *C, wmOperator *op) tmp = text->lines.first; - //first convert to all space, this make it a lot easier to convert to tabs because there is no mixtures of ' ' && '\t' + /* first convert to all space, this make it a lot easier to convert to tabs + * because there is no mixtures of ' ' && '\t' */ while (tmp) { text_check_line = tmp->line; number = flatten_string(st, &fs, text_check_line) + 1; @@ -1376,104 +1379,6 @@ void TEXT_OT_move_lines(wmOperatorType *ot) RNA_def_enum(ot->srna, "direction", direction_items, 1, "Direction", ""); } -/******************* previous marker operator *********************/ - -static int text_previous_marker_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Text *text = CTX_data_edit_text(C); - TextMarker *mrk; - int lineno; - - lineno = txt_get_span(text->lines.first, text->curl); - mrk = text->markers.last; - while (mrk && (mrk->lineno > lineno || (mrk->lineno == lineno && mrk->end > text->curc))) - mrk = mrk->prev; - if (!mrk) mrk = text->markers.last; - if (mrk) { - txt_move_to(text, mrk->lineno, mrk->start, 0); - txt_move_to(text, mrk->lineno, mrk->end, 1); - } - - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - - return OPERATOR_FINISHED; -} - -void TEXT_OT_previous_marker(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Previous Marker"; - ot->idname = "TEXT_OT_previous_marker"; - ot->description = "Move to previous marker"; - - /* api callbacks */ - ot->exec = text_previous_marker_exec; - ot->poll = text_edit_poll; -} - -/******************* next marker operator *********************/ - -static int text_next_marker_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Text *text = CTX_data_edit_text(C); - TextMarker *mrk; - int lineno; - - lineno = txt_get_span(text->lines.first, text->curl); - mrk = text->markers.first; - while (mrk && (mrk->lineno < lineno || (mrk->lineno == lineno && mrk->start <= text->curc))) - mrk = mrk->next; - if (!mrk) mrk = text->markers.first; - if (mrk) { - txt_move_to(text, mrk->lineno, mrk->start, 0); - txt_move_to(text, mrk->lineno, mrk->end, 1); - } - - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - - return OPERATOR_FINISHED; -} - -void TEXT_OT_next_marker(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Next Marker"; - ot->idname = "TEXT_OT_next_marker"; - ot->description = "Move to next marker"; - - /* api callbacks */ - ot->exec = text_next_marker_exec; - ot->poll = text_edit_poll; -} - -/******************* clear all markers operator *********************/ - -static int text_clear_all_markers_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Text *text = CTX_data_edit_text(C); - - txt_clear_markers(text, 0, 0); - - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - - return OPERATOR_FINISHED; -} - -void TEXT_OT_markers_clear(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Clear All Markers"; - ot->idname = "TEXT_OT_markers_clear"; - ot->description = "Clear all markers"; - - /* api callbacks */ - ot->exec = text_clear_all_markers_exec; - ot->poll = text_edit_poll; -} - /************************ move operator ************************/ static EnumPropertyItem move_type_items[] = { @@ -1503,7 +1408,7 @@ static int text_get_cursor_rel(SpaceText *st, ARegion *ar, TextLine *linein, int end = max; chop = loop = 1; - for (i = 0, j = 0; loop; j += BLI_str_utf8_size(linein->line + j)) { + for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe(linein->line + j)) { int chars; /* Mimic replacement of tabs */ ch = linein->line[j]; @@ -1664,16 +1569,15 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel) Text *text = st->text; TextLine **linep; int *charp; - int oldl, oldc, i, j, max, start, end, endj, chop, loop; + int oldc, i, j, max, start, end, endj, chop, loop; char ch; text_update_character_width(st); - if (sel) linep = &text->sell, charp = &text->selc; - else linep = &text->curl, charp = &text->curc; + if (sel) { linep = &text->sell; charp = &text->selc; } + else { linep = &text->curl; charp = &text->curc; } oldc = *charp; - oldl = txt_get_span(text->lines.first, *linep); max = wrap_width(st, ar); @@ -1682,7 +1586,7 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel) chop = loop = 1; *charp = 0; - for (i = 0, j = 0; loop; j += BLI_str_utf8_size((*linep)->line + j)) { + for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) { int chars; /* Mimic replacement of tabs */ ch = (*linep)->line[j]; @@ -1724,7 +1628,6 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel) } if (!sel) txt_pop_sel(text); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, oldl, *charp); } static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel) @@ -1732,16 +1635,15 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel) Text *text = st->text; TextLine **linep; int *charp; - int oldl, oldc, i, j, max, start, end, endj, chop, loop; + int oldc, i, j, max, start, end, endj, chop, loop; char ch; text_update_character_width(st); - if (sel) linep = &text->sell, charp = &text->selc; - else linep = &text->curl, charp = &text->curc; + if (sel) { linep = &text->sell; charp = &text->selc; } + else { linep = &text->curl; charp = &text->curc; } oldc = *charp; - oldl = txt_get_span(text->lines.first, *linep); max = wrap_width(st, ar); @@ -1750,7 +1652,7 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel) chop = loop = 1; *charp = 0; - for (i = 0, j = 0; loop; j += BLI_str_utf8_size((*linep)->line + j)) { + for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) { int chars; /* Mimic replacement of tabs */ ch = (*linep)->line[j]; @@ -1790,7 +1692,6 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel) } if (!sel) txt_pop_sel(text); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, oldl, *charp); } static void txt_wrap_move_up(SpaceText *st, ARegion *ar, short sel) @@ -1798,22 +1699,17 @@ static void txt_wrap_move_up(SpaceText *st, ARegion *ar, short sel) Text *text = st->text; TextLine **linep; int *charp; - int oldl, oldc, offl, offc, col, newl; + int offl, offc, col; text_update_character_width(st); - if (sel) linep = &text->sell, charp = &text->selc; - else linep = &text->curl, charp = &text->curc; - - /* store previous position */ - oldc = *charp; - newl = oldl = txt_get_span(text->lines.first, *linep); + if (sel) { linep = &text->sell; charp = &text->selc; } + else { linep = &text->curl; charp = &text->curc; } wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc); col = text_get_char_pos(st, (*linep)->line, *charp) + offc; if (offl) { *charp = text_get_cursor_rel(st, ar, *linep, offl - 1, col); - newl = BLI_findindex(&text->lines, linep); } else { if ((*linep)->prev) { @@ -1822,13 +1718,11 @@ static void txt_wrap_move_up(SpaceText *st, ARegion *ar, short sel) *linep = (*linep)->prev; visible_lines = text_get_visible_lines(st, ar, (*linep)->line); *charp = text_get_cursor_rel(st, ar, *linep, visible_lines - 1, col); - newl--; } else *charp = 0; } if (!sel) txt_pop_sel(text); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, newl, *charp); } static void txt_wrap_move_down(SpaceText *st, ARegion *ar, short sel) @@ -1836,35 +1730,28 @@ static void txt_wrap_move_down(SpaceText *st, ARegion *ar, short sel) Text *text = st->text; TextLine **linep; int *charp; - int oldl, oldc, offl, offc, col, newl, visible_lines; + int offl, offc, col, visible_lines; text_update_character_width(st); - if (sel) linep = &text->sell, charp = &text->selc; - else linep = &text->curl, charp = &text->curc; - - /* store previous position */ - oldc = *charp; - newl = oldl = txt_get_span(text->lines.first, *linep); + if (sel) { linep = &text->sell; charp = &text->selc; } + else { linep = &text->curl; charp = &text->curc; } wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc); col = text_get_char_pos(st, (*linep)->line, *charp) + offc; visible_lines = text_get_visible_lines(st, ar, (*linep)->line); if (offl < visible_lines - 1) { *charp = text_get_cursor_rel(st, ar, *linep, offl + 1, col); - newl = BLI_findindex(&text->lines, linep); } else { if ((*linep)->next) { *linep = (*linep)->next; *charp = text_get_cursor_rel(st, ar, *linep, 0, col); - newl++; } else *charp = (*linep)->len; } if (!sel) txt_pop_sel(text); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, newl, *charp); } /* Moves the cursor vertically by the specified number of lines. @@ -1876,12 +1763,10 @@ static void txt_wrap_move_down(SpaceText *st, ARegion *ar, short sel) static void cursor_skip(SpaceText *st, ARegion *ar, Text *text, int lines, int sel) { TextLine **linep; - int oldl, oldc, *charp; + int *charp; - if (sel) linep = &text->sell, charp = &text->selc; - else linep = &text->curl, charp = &text->curc; - oldl = txt_get_span(text->lines.first, *linep); - oldc = *charp; + if (sel) { linep = &text->sell; charp = &text->selc; } + else { linep = &text->curl; charp = &text->curc; } if (st && ar && st->wordwrap) { int rell, relc; @@ -1904,7 +1789,6 @@ static void cursor_skip(SpaceText *st, ARegion *ar, Text *text, int lines, int s if (*charp > (*linep)->len) *charp = (*linep)->len; if (!sel) txt_pop_sel(text); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, txt_get_span(text->lines.first, *linep), *charp); } static int text_move_cursor(bContext *C, int type, int select) @@ -2222,10 +2106,10 @@ static void text_scroll_apply(bContext *C, wmOperator *op, wmEvent *event) if (!tsc->scrollbar) { txtdelta[0] = -tsc->delta[0] / st->cwidth; - txtdelta[1] = tsc->delta[1] / st->lheight; + txtdelta[1] = tsc->delta[1] / (st->lheight + TXT_LINE_SPACING); tsc->delta[0] %= st->cwidth; - tsc->delta[1] %= st->lheight; + tsc->delta[1] %= (st->lheight + TXT_LINE_SPACING); } else { txtdelta[1] = -tsc->delta[1] * st->pix_per_line; @@ -2462,7 +2346,7 @@ static int flatten_len(SpaceText *st, const char *str) { int i, total = 0; - for (i = 0; str[i]; i += BLI_str_utf8_size(str + i)) { + for (i = 0; str[i]; i += BLI_str_utf8_size_safe(str + i)) { if (str[i] == '\t') { total += st->tabnumber - total % st->tabnumber; } @@ -2475,7 +2359,7 @@ static int flatten_len(SpaceText *st, const char *str) static int flatten_index_to_offset(SpaceText *st, const char *str, int index) { int i, j; - for (i = 0, j = 0; i < index; j += BLI_str_utf8_size(str + j)) + for (i = 0, j = 0; i < index; j += BLI_str_utf8_size_safe(str + j)) if (str[j] == '\t') i += st->tabnumber - i % st->tabnumber; else @@ -2519,7 +2403,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in int j = 0, curs = 0, endj = 0; /* mem */ int chop = 1; /* flags */ - for (; loop; j += BLI_str_utf8_size(linep->line + j)) { + for (; loop; j += BLI_str_utf8_size_safe(linep->line + j)) { int chars; /* Mimic replacement of tabs */ @@ -2611,7 +2495,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in if (linep && charp != -1) { if (sel) { text->sell = linep; text->selc = charp; } - else { text->curl = linep; text->curc = charp; } + else { text->curl = linep; text->curc = charp; } } } @@ -2619,7 +2503,7 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, int { Text *text = st->text; text_update_character_width(st); - y = (ar->winy - 2 - y) / st->lheight; + y = (ar->winy - 2 - y) / (st->lheight + TXT_LINE_SPACING); if (st->showlinenrs) x -= TXT_OFFSET + TEXTXLOC; else x -= TXT_OFFSET; @@ -2636,7 +2520,7 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, int int w; if (sel) { linep = &text->sell; charp = &text->selc; } - else { linep = &text->curl; charp = &text->curc; } + else { linep = &text->curl; charp = &text->curc; } y -= txt_get_span(text->lines.first, *linep) - st->top; @@ -2696,7 +2580,6 @@ static void text_cursor_set_exit(bContext *C, wmOperator *op) SpaceText *st = CTX_wm_space_text(C); Text *text = st->text; SetSelection *ssel = op->customdata; - int linep2, charp2; char *buffer; if (txt_has_sel(text)) { @@ -2705,12 +2588,6 @@ static void text_cursor_set_exit(bContext *C, wmOperator *op) MEM_freeN(buffer); } - linep2 = txt_get_span(st->text->lines.first, st->text->sell); - charp2 = st->text->selc; - - if (ssel->sell != linep2 || ssel->selc != charp2) - txt_undo_add_toop(st->text, UNDO_STO, ssel->sell, ssel->selc, linep2, charp2); - text_update_cursor_moved(C); WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); @@ -2786,19 +2663,12 @@ void TEXT_OT_selection_set(wmOperatorType *ot) static int text_cursor_set_exec(bContext *C, wmOperator *op) { SpaceText *st = CTX_wm_space_text(C); - Text *text = st->text; ARegion *ar = CTX_wm_region(C); int x = RNA_int_get(op->ptr, "x"); int y = RNA_int_get(op->ptr, "y"); - int oldl, oldc; - - oldl = txt_get_span(text->lines.first, text->curl); - oldc = text->curc; text_cursor_set_to_pos(st, ar, x, y, 0); - txt_undo_add_toop(text, UNDO_CTO, oldl, oldc, txt_get_span(text->lines.first, text->curl), text->curc); - text_update_cursor_moved(C); WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); @@ -2945,7 +2815,7 @@ static int text_insert_invoke(bContext *C, wmOperator *op, wmEvent *event) size_t len; if (event->utf8_buf[0]) { - len = BLI_str_utf8_size(event->utf8_buf); + len = BLI_str_utf8_size_safe(event->utf8_buf); memcpy(str, event->utf8_buf, len); } else { @@ -2990,14 +2860,13 @@ void TEXT_OT_insert(wmOperatorType *ot) /* mode */ #define TEXT_FIND 0 #define TEXT_REPLACE 1 -#define TEXT_MARK_ALL 2 static int text_find_and_replace(bContext *C, wmOperator *op, short mode) { Main *bmain = CTX_data_main(C); SpaceText *st = CTX_wm_space_text(C); - Text *start = NULL, *text = st->text; - int flags, first = 1; + Text *text = st->text; + int flags; int found = 0; char *tmp; @@ -3006,79 +2875,48 @@ static int text_find_and_replace(bContext *C, wmOperator *op, short mode) flags = st->flags; if (flags & ST_FIND_ALL) - flags ^= ST_FIND_WRAP; + flags &= ~ST_FIND_WRAP; - do { - int proceed = 0; + /* Replace current */ + if (mode != TEXT_FIND && txt_has_sel(text)) { + tmp = txt_sel_to_buf(text); - if (first) { - if (text->markers.first) + if (flags & ST_MATCH_CASE) found = strcmp(st->findstr, tmp) == 0; + else found = BLI_strcasecmp(st->findstr, tmp) == 0; + + if (found) { + if (mode == TEXT_REPLACE) { + txt_insert_buf(text, st->replacestr); + if (text->curl && text->curl->format) { + MEM_freeN(text->curl->format); + text->curl->format = NULL; + } + text_update_cursor_moved(C); WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - - txt_clear_markers(text, TMARK_GRP_FINDALL, 0); - } - - first = 0; - - /* Replace current */ - if (mode != TEXT_FIND && txt_has_sel(text)) { - tmp = txt_sel_to_buf(text); - - if (flags & ST_MATCH_CASE) proceed = strcmp(st->findstr, tmp) == 0; - else proceed = BLI_strcasecmp(st->findstr, tmp) == 0; - - if (proceed) { - if (mode == TEXT_REPLACE) { - txt_insert_buf(text, st->replacestr); - if (text->curl && text->curl->format) { - MEM_freeN(text->curl->format); - text->curl->format = NULL; - } - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - text_drawcache_tag_update(CTX_wm_space_text(C), 1); - } - else if (mode == TEXT_MARK_ALL) { - unsigned char color[4]; - UI_GetThemeColor4ubv(TH_SHADE2, color); - - if (txt_find_marker(text, text->curl, text->selc, TMARK_GRP_FINDALL, 0)) { - if (tmp) MEM_freeN(tmp), tmp = NULL; - break; - } - - txt_add_marker(text, text->curl, text->curc, text->selc, color, TMARK_GRP_FINDALL, TMARK_EDITALL); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - } + text_drawcache_tag_update(CTX_wm_space_text(C), 1); } - MEM_freeN(tmp); - tmp = NULL; } + MEM_freeN(tmp); + tmp = NULL; + } - /* Find next */ - if (txt_find_string(text, st->findstr, flags & ST_FIND_WRAP, flags & ST_MATCH_CASE)) { - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text); - } - else if (flags & ST_FIND_ALL) { - if (text == start) break; - if (!start) start = text; - if (text->id.next) - text = st->text = text->id.next; - else - text = st->text = bmain->text.first; - txt_move_toline(text, 0, 0); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text); - first = 1; - } - else { - if (!found && !proceed) BKE_reportf(op->reports, RPT_ERROR, "Text not found: %s", st->findstr); - break; - } - found = 1; - } while (mode == TEXT_MARK_ALL); + /* Find next */ + if (txt_find_string(text, st->findstr, flags & ST_FIND_WRAP, flags & ST_MATCH_CASE)) { + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text); + } + else if (flags & ST_FIND_ALL) { + if (text->id.next) + text = st->text = text->id.next; + else + text = st->text = bmain->text.first; + txt_move_toline(text, 0, 0); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text); + } + else { + if (!found) BKE_reportf(op->reports, RPT_ERROR, "Text not found: %s", st->findstr); + } return OPERATOR_FINISHED; } @@ -3119,25 +2957,6 @@ void TEXT_OT_replace(wmOperatorType *ot) ot->poll = text_space_edit_poll; } -/******************* mark all operator *********************/ - -static int text_mark_all_exec(bContext *C, wmOperator *op) -{ - return text_find_and_replace(C, op, TEXT_MARK_ALL); -} - -void TEXT_OT_mark_all(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Mark All"; - ot->idname = "TEXT_OT_mark_all"; - ot->description = "Mark all specified text"; - - /* api callbacks */ - ot->exec = text_mark_all_exec; - ot->poll = text_space_edit_poll; -} - /******************* find set selected *********************/ static int text_find_set_selected_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/space_text/text_python.c b/source/blender/editors/space_text/text_python.c index 966afe22e42..4c9b4b900cc 100644 --- a/source/blender/editors/space_text/text_python.c +++ b/source/blender/editors/space_text/text_python.c @@ -359,177 +359,3 @@ static short UNUSED_FUNCTION(do_texttools) (SpaceText * st, char ascii, unsigned return swallow; } - -static short UNUSED_FUNCTION(do_textmarkers) (SpaceText * st, char ascii, unsigned short evnt, short val) -{ - Text *text; - TextMarker *marker, *mrk, *nxt; - int c, s, draw = 0, swallow = 0; - int qual = 0; // XXX - - text = st->text; - if (!text || text->id.lib || text->curl != text->sell) return 0; - - marker = txt_find_marker(text, text->sell, text->selc, 0, 0); - if (marker && (marker->start > text->curc || marker->end < text->curc)) - marker = NULL; - - if (!marker) { - /* Find the next temporary marker */ - if (evnt == TABKEY) { - int lineno = txt_get_span(text->lines.first, text->curl); - mrk = text->markers.first; - while (mrk) { - if (!marker && (mrk->flags & TMARK_TEMP)) marker = mrk; - if ((mrk->flags & TMARK_TEMP) && (mrk->lineno > lineno || (mrk->lineno == lineno && mrk->end > text->curc))) { - marker = mrk; - break; - } - mrk = mrk->next; - } - if (marker) { - txt_move_to(text, marker->lineno, marker->start, 0); - txt_move_to(text, marker->lineno, marker->end, 1); - // XXX text_update_cursor_moved(C); - // XXX WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text); - evnt = ascii = val = 0; - draw = 1; - swallow = 1; - } - } - else if (evnt == ESCKEY) { - if (txt_clear_markers(text, 0, TMARK_TEMP)) swallow = 1; - else if (txt_clear_markers(text, 0, 0)) swallow = 1; - else return 0; - evnt = ascii = val = 0; - draw = 1; - } - if (!swallow) return 0; - } - - if (ascii) { - if (marker->flags & TMARK_EDITALL) { - c = text->curc - marker->start; - s = text->selc - marker->start; - if (s < 0 || s > marker->end - marker->start) return 0; - - mrk = txt_next_marker(text, marker); - while (mrk) { - nxt = txt_next_marker(text, mrk); /* mrk may become invalid */ - txt_move_to(text, mrk->lineno, mrk->start + c, 0); - if (s != c) txt_move_to(text, mrk->lineno, mrk->start + s, 1); - if (st->overwrite) { - if (txt_replace_char(text, ascii)) - text_update_line_edited(st->text->curl); - } - else { - if (txt_add_char(text, ascii)) { - text_update_line_edited(st->text->curl); - } - } - - if (mrk == marker || mrk == nxt) break; - mrk = nxt; - } - swallow = 1; - draw = 1; - } - } - else if (val) { - switch (evnt) { - case BACKSPACEKEY: - if (marker->flags & TMARK_EDITALL) { - c = text->curc - marker->start; - s = text->selc - marker->start; - if (s < 0 || s > marker->end - marker->start) return 0; - - mrk = txt_next_marker(text, marker); - while (mrk) { - nxt = txt_next_marker(text, mrk); /* mrk may become invalid */ - txt_move_to(text, mrk->lineno, mrk->start + c, 0); - if (s != c) txt_move_to(text, mrk->lineno, mrk->start + s, 1); - txt_backspace_char(text); - text_update_line_edited(st->text->curl); - if (mrk == marker || mrk == nxt) break; - mrk = nxt; - } - swallow = 1; - draw = 1; - } - break; - case DELKEY: - if (marker->flags & TMARK_EDITALL) { - c = text->curc - marker->start; - s = text->selc - marker->start; - if (s < 0 || s > marker->end - marker->start) return 0; - - mrk = txt_next_marker(text, marker); - while (mrk) { - nxt = txt_next_marker(text, mrk); /* mrk may become invalid */ - txt_move_to(text, mrk->lineno, mrk->start + c, 0); - if (s != c) txt_move_to(text, mrk->lineno, mrk->start + s, 1); - txt_delete_char(text); - text_update_line_edited(st->text->curl); - if (mrk == marker || mrk == nxt) break; - mrk = nxt; - } - swallow = 1; - draw = 1; - } - break; - case TABKEY: - if (qual & LR_SHIFTKEY) { - nxt = marker->prev; - if (!nxt) nxt = text->markers.last; - } - else { - nxt = marker->next; - if (!nxt) nxt = text->markers.first; - } - if (marker->flags & TMARK_TEMP) { - if (nxt == marker) nxt = NULL; - BLI_freelinkN(&text->markers, marker); - } - mrk = nxt; - if (mrk) { - txt_move_to(text, mrk->lineno, mrk->start, 0); - txt_move_to(text, mrk->lineno, mrk->end, 1); - // XXX text_update_cursor_moved(C); - // XXX WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text); - } - swallow = 1; - draw = 1; - break; - - /* Events that should clear markers */ - case UKEY: if (!(qual & LR_ALTKEY)) break; - case ZKEY: if (evnt == ZKEY && !(qual & LR_CTRLKEY)) break; - case RETKEY: - case ESCKEY: - if (marker->flags & (TMARK_EDITALL | TMARK_TEMP)) - txt_clear_markers(text, marker->group, 0); - else - BLI_freelinkN(&text->markers, marker); - swallow = 1; - draw = 1; - break; - case RIGHTMOUSE: /* Marker context menu? */ - case LEFTMOUSE: - break; - case FKEY: /* Allow find */ - if (qual & LR_SHIFTKEY) swallow = 1; - break; - - default: - if (qual != 0 && qual != LR_SHIFTKEY) - swallow = 1; /* Swallow all other shortcut events */ - } - } - - if (draw) { - // XXX redraw_alltext(); - } - - return swallow; -} - diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index cb5556396dd..0ecde350b00 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -51,6 +51,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_effect.h" +#include "BKE_global.h" #include "BKE_image.h" #include "BKE_material.h" #include "BKE_paint.h" @@ -728,7 +729,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl) BKE_bproperty_set_valstr(prop, string); characters = strlen(string); - if (!BKE_image_get_ibuf(mtpoly->tpage, NULL)) + if (!BKE_image_has_ibuf(mtpoly->tpage, NULL)) characters = 0; if (!mf_smooth) { @@ -965,7 +966,7 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Mesh *me = ob->data; TexMatCallback data = {scene, ob, me, dm}; int (*set_face_cb)(void *, int); - int glsl; + int glsl, picking = (G.f & G_PICKSEL); /* face hiding callback depending on mode */ if (ob == scene->obedit) @@ -976,11 +977,11 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, set_face_cb = NULL; /* test if we can use glsl */ - glsl = (v3d->drawtype == OB_MATERIAL) && GPU_glsl_support(); + glsl = (v3d->drawtype == OB_MATERIAL) && GPU_glsl_support() && !picking; GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); - if (glsl) { + if (glsl || picking) { /* draw glsl */ dm->drawMappedFacesMat(dm, tex_mat_set_material_cb, diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index f100f003ff5..5ac7327b93b 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -229,7 +229,10 @@ static int check_alpha_pass(Base *base) if (G.f & G_PICKSEL) return 0; - + + if (base->object->mode & OB_MODE_ALL_PAINT) + return 0; + return (base->object->dtx & OB_DRAWTRANSP); } @@ -530,7 +533,7 @@ void drawaxes(float size, char drawtype) static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4]) { Image *ima = (Image *)ob->data; - ImBuf *ibuf = ima ? BKE_image_get_ibuf(ima, NULL) : NULL; + ImBuf *ibuf = ima ? BKE_image_acquire_ibuf(ima, NULL, NULL) : NULL; float scale, ofs_x, ofs_y, sca_x, sca_y; int ima_x, ima_y; @@ -615,6 +618,8 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char /* Reset GL settings */ glMatrixMode(GL_MODELVIEW); glPopMatrix(); + + BKE_image_release_ibuf(ima, ibuf, NULL); } static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, float tmat[][4]) @@ -2577,7 +2582,7 @@ static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitS BMIter iter; int i; - /* make the precision of the pronted value proportionate to the gridsize */ + /* make the precision of the display value proportionate to the gridsize */ if (grid < 0.01f) conv_float = "%.6g"; else if (grid < 0.1f) conv_float = "%.5g"; @@ -3600,9 +3605,12 @@ static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, B return 0; } -/* returns 1 when nothing was drawn */ -static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dt, const short dflag, const unsigned char ob_wire_col[4]) +/** + * Only called by #drawDispList + * \return 1 when nothing was drawn + */ +static int drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, + const short dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; ListBase *lb = NULL; @@ -3610,20 +3618,9 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas Curve *cu; const short render_only = (v3d->flag2 & V3D_RENDER_OVERRIDE); const short solid = (dt > OB_WIRE); - int retval = 0; - - /* backface culling */ - if (v3d->flag2 & V3D_BACKFACE_CULLING) { - /* not all displists use same in/out normal direction convention */ - glEnable(GL_CULL_FACE); - glCullFace((ob->type == OB_MBALL) ? GL_BACK : GL_FRONT); - } if (drawCurveDerivedMesh(scene, v3d, rv3d, base, dt) == 0) { - if (v3d->flag2 & V3D_BACKFACE_CULLING) - glDisable(GL_CULL_FACE); - - return 0; + return FALSE; } switch (ob->type) { @@ -3635,7 +3632,9 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas if (solid) { dl = lb->first; - if (dl == NULL) return 1; + if (dl == NULL) { + return TRUE; + } if (dl->nors == NULL) BKE_displist_normals_add(lb); index3_nors_incr = 0; @@ -3669,9 +3668,11 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas } else { if (!render_only || (render_only && BKE_displist_has_faces(lb))) { + int retval; draw_index_wire = 0; retval = drawDispListwire(lb); draw_index_wire = 1; + return retval; } } break; @@ -3681,7 +3682,9 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas if (solid) { dl = lb->first; - if (dl == NULL) return 1; + if (dl == NULL) { + return TRUE; + } if (dl->nors == NULL) BKE_displist_normals_add(lb); @@ -3697,7 +3700,7 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas } } else { - retval = drawDispListwire(lb); + return drawDispListwire(lb); } break; case OB_MBALL: @@ -3705,7 +3708,9 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas if (BKE_mball_is_basis(ob)) { lb = &ob->disp; if (lb->first == NULL) BKE_displist_make_mball(scene, ob); - if (lb->first == NULL) return 1; + if (lb->first == NULL) { + return TRUE; + } if (solid) { @@ -3722,14 +3727,31 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas } else { /* MetaBalls use DL_INDEX4 type of DispList */ - retval = drawDispListwire(lb); + return drawDispListwire(lb); } } break; } - - if (v3d->flag2 & V3D_BACKFACE_CULLING) + + return FALSE; +} +static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, + const short dt, const short dflag, const unsigned char ob_wire_col[4]) +{ + int retval; + + /* backface culling */ + if (v3d->flag2 & V3D_BACKFACE_CULLING) { + /* not all displists use same in/out normal direction convention */ + glEnable(GL_CULL_FACE); + glCullFace((base->object->type == OB_MBALL) ? GL_BACK : GL_FRONT); + } + + retval = drawDispList_nobackface(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + + if (v3d->flag2 & V3D_BACKFACE_CULLING) { glDisable(GL_CULL_FACE); + } return retval; } diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 6818c78bbd6..1c31cd23e33 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -702,6 +702,7 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn) case NC_GEOM: switch (wmn->data) { case ND_DATA: + case ND_VERTEX_GROUP: case ND_SELECT: ED_region_tag_redraw(ar); break; @@ -723,6 +724,7 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn) case NC_MATERIAL: switch (wmn->data) { case ND_SHADING_DRAW: + case ND_SHADING_LINKS: ED_region_tag_redraw(ar); break; } @@ -920,6 +922,7 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn) case NC_GEOM: switch (wmn->data) { case ND_DATA: + case ND_VERTEX_GROUP: case ND_SELECT: ED_region_tag_redraw(ar); break; @@ -945,7 +948,7 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn) ED_region_tag_redraw(ar); break; case NC_GPENCIL: - if (wmn->data == ND_DATA) + if (wmn->data == ND_DATA || wmn->action == NA_EDITED) ED_region_tag_redraw(ar); break; } @@ -1119,16 +1122,21 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes return 1; } else if (CTX_data_equals(member, "active_base")) { - if (scene->basact && (scene->basact->lay & lay)) - if ((scene->basact->object->restrictflag & OB_RESTRICT_VIEW) == 0) + if (scene->basact && (scene->basact->lay & lay)) { + Object *ob = scene->basact->object; + /* if hidden but in edit mode, we still display, can happen with animation */ + if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT)) CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, scene->basact); + } return 1; } else if (CTX_data_equals(member, "active_object")) { - if (scene->basact && (scene->basact->lay & lay)) - if ((scene->basact->object->restrictflag & OB_RESTRICT_VIEW) == 0) + if (scene->basact && (scene->basact->lay & lay)) { + Object *ob = scene->basact->object; + if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT)) CTX_data_id_pointer_set(result, &scene->basact->object->id); + } return 1; } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 4d4fad47698..51261f4c341 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -95,6 +95,16 @@ #include "view3d_intern.h" /* own include */ +/* handy utility for drawing shapes in the viewport for arbitrary code. + * could add lines and points too */ +// #define DEBUG_DRAW +#ifdef DEBUG_DRAW +static void bl_debug_draw(void); +/* add these locally when using these functions for testing */ +extern void bl_debug_draw_quad_clear(void); +extern void bl_debug_draw_quad_add(const float v0[3], const float v1[3], const float v2[3], const float v3[3]); +extern void bl_debug_draw_edge_add(const float v0[3], const float v1[3]); +#endif static void star_stuff_init_func(void) { @@ -441,10 +451,9 @@ static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char ** } #undef GRID_MIN_PX -float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit) +/** could move this elsewhere, but tied into #ED_view3d_grid_scale */ +float ED_scene_grid_scale(Scene *scene, const char **grid_unit) { - float grid_scale = v3d->grid; - /* apply units */ if (scene->unit.system) { void *usys; @@ -456,11 +465,16 @@ float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit) int i = bUnit_GetBaseUnit(usys); if (grid_unit) *grid_unit = bUnit_GetNameDisplay(usys, i); - grid_scale = (grid_scale * (float)bUnit_GetScaler(usys, i)) / scene->unit.scale_length; + return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length; } } - return grid_scale; + return 1.0f; +} + +float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit) +{ + return v3d->grid * ED_scene_grid_scale(scene, grid_unit); } static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit) @@ -545,12 +559,8 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit) } } } - - - - - if (v3d->zbuf && scene->obedit) glDepthMask(1); + if (v3d->zbuf && scene->obedit) glDepthMask(1); } static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d) @@ -600,8 +610,8 @@ static void draw_view_axis(RegionView3D *rv3d) mul_qt_v3(rv3d->viewquat, vec); dx = vec[0] * k; dy = vec[1] * k; - - glColor4ub(220, 0, 0, bright); + + UI_ThemeColorShadeAlpha(TH_AXIS_X, 0, bright); glBegin(GL_LINES); glVertex2f(start, start + ydisp); glVertex2f(start + dx, start + dy + ydisp); @@ -620,8 +630,8 @@ static void draw_view_axis(RegionView3D *rv3d) mul_qt_v3(rv3d->viewquat, vec); dx = vec[0] * k; dy = vec[1] * k; - - glColor4ub(0, 220, 0, bright); + + UI_ThemeColorShadeAlpha(TH_AXIS_Y, 0, bright); glBegin(GL_LINES); glVertex2f(start, start + ydisp); glVertex2f(start + dx, start + dy + ydisp); @@ -640,7 +650,7 @@ static void draw_view_axis(RegionView3D *rv3d) dx = vec[0] * k; dy = vec[1] * k; - glColor4ub(30, 30, 220, bright); + UI_ThemeColorShadeAlpha(TH_AXIS_Z, 0, bright); glBegin(GL_LINES); glVertex2f(start, start + ydisp); glVertex2f(start + dx, start + dy + ydisp); @@ -1218,11 +1228,11 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) hmargin = 0.1f * (x2 - x1); vmargin = 0.05f * (y2 - y1); - uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1+vmargin, x2 - hmargin, y2 - vmargin, 2.0f); + uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1 + vmargin, x2 - hmargin, y2 - vmargin, 2.0f); hmargin = 0.035f * (x2 - x1); vmargin = 0.035f * (y2 - y1); - uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1+vmargin, x2 - hmargin, y2 - vmargin, 2.0f); + uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1 + vmargin, x2 - hmargin, y2 - vmargin, 2.0f); } if (ca && (ca->flag & CAM_SHOWSENSOR)) { /* determine sensor fit, and get sensor x/y, for auto fit we @@ -1416,8 +1426,8 @@ ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, ibuf = IMB_allocImBuf((xmaxc - xminc + 1), (ymaxc - yminc + 1), 32, IB_rect); - view3d_validate_backbuf(vc); - + view3d_validate_backbuf(vc); + glReadPixels(vc->ar->winrct.xmin + xminc, vc->ar->winrct.ymin + yminc, (xmaxc - xminc + 1), @@ -1565,7 +1575,8 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, ibuf = NULL; /* frame is out of range, dont show */ } else { - ibuf = BKE_image_get_ibuf(ima, &bgpic->iuser); + ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, NULL); + freeibuf = ibuf; } image_aspect[0] = ima->aspx; @@ -1924,10 +1935,17 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas for (; dob; dob_prev = dob, dob = dob_next, dob_next = dob_next ? dupli_step(dob_next->next) : NULL) { tbase.object = dob->ob; - /* extra service: draw the duplicator in drawtype of parent */ - /* MIN2 for the drawtype to allow bounding box objects in groups for lods */ - dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt); - dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx; + /* extra service: draw the duplicator in drawtype of parent, minimum taken + * to allow e.g. boundbox box objects in groups for LOD */ + dt = tbase.object->dt; + tbase.object->dt = MIN2(tbase.object->dt, base->object->dt); + + /* inherit draw extra, but not if a boundbox under the assumption that this + * is intended to speed up drawing, and drawing extra (especially wire) can + * slow it down too much */ + dtx = tbase.object->dtx; + if (tbase.object->dt != OB_BOUNDBOX) + tbase.object->dtx = base->object->dtx; /* negative scale flag has to propagate */ transflag = tbase.object->transflag; @@ -2989,10 +3007,11 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const v3d->zbuf = FALSE; /* enables anti-aliasing for 3D view drawing */ -#if 0 - if (!(U.gameflags & USER_DISABLE_AA)) + if (U.ogl_multisamples != USER_MULTISAMPLE_NONE) { + // if (!(U.gameflags & USER_DISABLE_AA)) glEnable(GL_MULTISAMPLE_ARB); -#endif + } + /* needs to be done always, gridview is adjusted in drawgrid() now */ rv3d->gridview = v3d->grid; @@ -3105,12 +3124,13 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const BIF_draw_manipulator(C); -#if 0 /* Disable back anti-aliasing */ - if (!(U.gameflags & USER_DISABLE_AA)) + if (U.ogl_multisamples != USER_MULTISAMPLE_NONE) { + // if (!(U.gameflags & USER_DISABLE_AA)) glDisable(GL_MULTISAMPLE_ARB); -#endif + } + if (v3d->zbuf) { v3d->zbuf = FALSE; glDisable(GL_DEPTH_TEST); @@ -3210,6 +3230,9 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar) /* draw viewport using opengl */ if (v3d->drawtype != OB_RENDER || !view3d_main_area_do_render_draw(C) || draw_border) { view3d_main_area_draw_objects(C, ar, &grid_unit); +#ifdef DEBUG_DRAW + bl_debug_draw(); +#endif ED_region_pixelspace(ar); } @@ -3222,3 +3245,76 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar) v3d->flag |= V3D_INVALID_BACKBUF; } +#ifdef DEBUG_DRAW +/* debug drawing */ +#define _DEBUG_DRAW_QUAD_TOT 1024 +#define _DEBUG_DRAW_EDGE_TOT 1024 +static float _bl_debug_draw_quads[_DEBUG_DRAW_QUAD_TOT][4][3]; +static int _bl_debug_draw_quads_tot = 0; +static float _bl_debug_draw_edges[_DEBUG_DRAW_QUAD_TOT][2][3]; +static int _bl_debug_draw_edges_tot = 0; + +void bl_debug_draw_quad_clear(void) +{ + _bl_debug_draw_quads_tot = 0; + _bl_debug_draw_edges_tot = 0; +} +void bl_debug_draw_quad_add(const float v0[3], const float v1[3], const float v2[3], const float v3[3]) +{ + if (_bl_debug_draw_quads_tot >= _DEBUG_DRAW_QUAD_TOT) { + printf("%s: max quad count hit %d!", __func__, _bl_debug_draw_quads_tot); + } + else { + float *pt = &_bl_debug_draw_quads[_bl_debug_draw_quads_tot][0][0]; + copy_v3_v3(pt, v0); pt += 3; + copy_v3_v3(pt, v1); pt += 3; + copy_v3_v3(pt, v2); pt += 3; + copy_v3_v3(pt, v3); pt += 3; + _bl_debug_draw_quads_tot++; + } +} +void bl_debug_draw_edge_add(const float v0[3], const float v1[3]) +{ + if (_bl_debug_draw_quads_tot >= _DEBUG_DRAW_EDGE_TOT) { + printf("%s: max edge count hit %d!", __func__, _bl_debug_draw_edges_tot); + } + else { + float *pt = &_bl_debug_draw_edges[_bl_debug_draw_edges_tot][0][0]; + copy_v3_v3(pt, v0); pt += 3; + copy_v3_v3(pt, v1); pt += 3; + _bl_debug_draw_edges_tot++; + } +} +static void bl_debug_draw(void) +{ + if (_bl_debug_draw_quads_tot) { + int i; + cpack(0x00FF0000); + glBegin(GL_LINE_LOOP); + for (i = 0; i < _bl_debug_draw_quads_tot; i ++) { + glVertex3fv(_bl_debug_draw_quads[i][0]); + glVertex3fv(_bl_debug_draw_quads[i][1]); + glVertex3fv(_bl_debug_draw_quads[i][2]); + glVertex3fv(_bl_debug_draw_quads[i][3]); + } + glEnd(); + } + if (_bl_debug_draw_edges_tot) { + int i; + cpack(0x00FFFF00); + glBegin(GL_LINES); + for (i = 0; i < _bl_debug_draw_edges_tot; i ++) { + glVertex3fv(_bl_debug_draw_edges[i][0]); + glVertex3fv(_bl_debug_draw_edges[i][1]); + } + glEnd(); + glPointSize(4.0); + glBegin(GL_POINTS); + for (i = 0; i < _bl_debug_draw_edges_tot; i ++) { + glVertex3fv(_bl_debug_draw_edges[i][0]); + glVertex3fv(_bl_debug_draw_edges[i][1]); + } + glEnd(); + } +} +#endif diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 36d7341f2f2..d45013c40d9 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -992,8 +992,10 @@ void ndof_to_quat(struct wmNDOFMotionData *ndof, float q[4]) * -- zooming * -- panning in rotationally-locked views */ -static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) { + ViewOpsData *vod = op->customdata; + if (event->type != NDOF_MOTION) return OPERATOR_CANCELLED; else { @@ -1074,6 +1076,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event rot[1] = rot[2] = 0.0; rot[3] = sin(angle); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); + } else { float rot[4]; @@ -1088,6 +1091,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event if (U.ndof_flag & NDOF_ROTATE_INVERT_AXIS) axis[1] = -axis[1]; + /* transform rotation axis from view to world coordinates */ mul_qt_v3(view_inv, axis); @@ -1100,7 +1104,22 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event /* apply rotation */ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); - + + } + + /* rotate around custom center */ + if (vod && vod->use_dyn_ofs) { + float q1[4]; + + /* compute the post multiplication quat, to rotate the offset correctly */ + conjugate_qt_qt(q1, vod->oldquat); + mul_qt_qtqt(q1, q1, rv3d->viewquat); + + conjugate_qt(q1); /* conj == inv for unit quat */ + copy_v3_v3(rv3d->ofs, vod->ofs); + sub_v3_v3(rv3d->ofs, vod->dyn_ofs); + mul_qt_v3(q1, rv3d->ofs); + add_v3_v3(rv3d->ofs, vod->dyn_ofs); } } } @@ -1267,6 +1286,9 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event) float axis[3]; #endif + /* inverse view */ + invert_qt_qt(view_inv, rv3d->viewquat); + if (U.ndof_flag & NDOF_PANX_INVERT_AXIS) pan_vec[0] = -lateral_sensitivity * ndof->tvec[0]; else @@ -1285,12 +1307,11 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event) mul_v3_fl(pan_vec, speed * dt); /* transform motion from view to world coordinates */ - invert_qt_qt(view_inv, rv3d->viewquat); mul_qt_v3(view_inv, pan_vec); /* move center of view opposite of hand motion (this is camera mode, not object mode) */ sub_v3_v3(rv3d->ofs, pan_vec); - + if (U.ndof_flag & NDOF_TURNTABLE) { /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */ float angle, rot[4]; @@ -1350,8 +1371,24 @@ static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event) /* apply rotation */ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); - + } + + /* rotate around custom center */ + if (vod && vod->use_dyn_ofs) { + float q1[4]; + + /* compute the post multiplication quat, to rotate the offset correctly */ + conjugate_qt_qt(q1, vod->oldquat); + mul_qt_qtqt(q1, q1, rv3d->viewquat); + + conjugate_qt(q1); /* conj == inv for unit quat */ + copy_v3_v3(rv3d->ofs, vod->ofs); + sub_v3_v3(rv3d->ofs, vod->dyn_ofs); + mul_qt_v3(q1, rv3d->ofs); + add_v3_v3(rv3d->ofs, vod->dyn_ofs); + } + } ED_view3d_camera_lock_sync(v3d, rv3d); @@ -1616,7 +1653,7 @@ static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my) } -static void viewzoom_apply(ViewOpsData *vod, int x, int y, const short viewzoom, const short zoom_invert) +static void viewzoom_apply(ViewOpsData *vod, const int x, const int y, const short viewzoom, const short zoom_invert) { float zfac = 1.0; short use_cam_zoom; @@ -1637,10 +1674,10 @@ static void viewzoom_apply(ViewOpsData *vod, int x, int y, const short viewzoom, float fac; if (U.uiflag & USER_ZOOM_HORIZ) { - fac = (float)(x - vod->origx); + fac = (float)(vod->origx - x); } else { - fac = (float)(y - vod->origy); + fac = (float)(vod->origy - y); } if (zoom_invert) { @@ -2187,10 +2224,24 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar, /* fix up zoom distance if needed */ if (rv3d->is_persp) { - if (size <= v3d->near * 1.5f) { - /* do not zoom closer than the near clipping plane */ - size = v3d->near * 1.5f; + float lens, sensor_size; + /* offset the view based on the lens */ + if (rv3d->persp == RV3D_CAMOB && ED_view3d_camera_lock_check(v3d, rv3d)) { + CameraParams params; + BKE_camera_params_init(¶ms); + BKE_camera_params_from_object(¶ms, v3d->camera); + + lens = params.lens; + sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y); } + else { + lens = v3d->lens; + sensor_size = DEFAULT_SENSOR_WIDTH; + } + size = ED_view3d_radius_to_persp_dist(focallength_to_fov(lens, sensor_size), size / 2.0f) * VIEW3D_MARGIN; + + /* do not zoom closer than the near clipping plane */ + size = max_ff(size, v3d->near * 1.5f); } else { /* ortho */ if (size < 0.0001f) { @@ -2199,7 +2250,7 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar, } else { /* adjust zoom so it looks nicer */ - size *= 0.7f; + size = ED_view3d_radius_to_ortho_dist(v3d->lens, size / 2.0f) * VIEW3D_MARGIN; } } } diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index 5aee90f0860..cddfae53f6f 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -369,8 +369,6 @@ static int initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *event } /* store the original camera loc and rot */ - /* TODO. axis angle etc */ - fly->obtfm = BKE_object_tfm_backup(ob_back); BKE_object_where_is_calc(fly->scene, fly->v3d->camera); diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index d8fcc7e12e7..79bf003a563 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -310,21 +310,14 @@ static char *view3d_modeselect_pup(Scene *scene) return (string); } - static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event) { wmWindow *win = CTX_wm_window(C); - ToolSettings *ts = CTX_data_tool_settings(C); ScrArea *sa = CTX_wm_area(C); View3D *v3d = sa->spacedata.first; - Object *obedit = CTX_data_edit_object(C); - BMEditMesh *em = NULL; - int ctrl = win->eventstate->ctrl, shift = win->eventstate->shift; + const int ctrl = win->eventstate->ctrl, shift = win->eventstate->shift; PointerRNA props_ptr; - - if (obedit && obedit->type == OB_MESH) { - em = BMEdit_FromObject(obedit); - } + /* watch it: if sa->win does not exist, check that when calling direct drawing routines */ switch (event) { @@ -336,42 +329,17 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event) break; case B_SEL_VERT: - if (em) { - if (shift == 0 || em->selectmode == 0) - em->selectmode = SCE_SELECT_VERTEX; - ts->selectmode = em->selectmode; - EDBM_selectmode_set(em); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + if (EDBM_selectmode_toggle(C, SCE_SELECT_VERTEX, -1, shift, ctrl)) { ED_undo_push(C, "Selectmode Set: Vertex"); } break; case B_SEL_EDGE: - if (em) { - if (shift == 0 || em->selectmode == 0) { - if ((em->selectmode ^ SCE_SELECT_EDGE) == SCE_SELECT_VERTEX) { - if (ctrl) EDBM_selectmode_convert(em, SCE_SELECT_VERTEX, SCE_SELECT_EDGE); - } - em->selectmode = SCE_SELECT_EDGE; - } - ts->selectmode = em->selectmode; - EDBM_selectmode_set(em); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + if (EDBM_selectmode_toggle(C, SCE_SELECT_EDGE, -1, shift, ctrl)) { ED_undo_push(C, "Selectmode Set: Edge"); } break; case B_SEL_FACE: - if (em) { - if (shift == 0 || em->selectmode == 0) { - if (((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || - ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)) - { - if (ctrl) EDBM_selectmode_convert(em, (ts->selectmode ^ SCE_SELECT_FACE), SCE_SELECT_FACE); - } - em->selectmode = SCE_SELECT_FACE; - } - ts->selectmode = em->selectmode; - EDBM_selectmode_set(em); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + if (EDBM_selectmode_toggle(C, SCE_SELECT_FACE, -1, shift, ctrl)) { ED_undo_push(C, "Selectmode Set: Face"); } break; @@ -430,9 +398,15 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C) row = uiLayoutRow(layout, TRUE); block = uiLayoutGetBlock(row); - uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Vertex select - Shift-Click for multiple modes"); - uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Edge select - Shift-Click for multiple modes"); - uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Face select - Shift-Click for multiple modes"); + uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, + 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, + "Vertex select - Shift-Click for multiple modes"); + uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, + 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, + "Edge select - Shift-Click for multiple modes, Ctrl-Click expands selection"); + uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, + 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, + "Face select - Shift-Click for multiple modes, Ctrl-Click expands selection"); } } diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index b928e060ca0..37607729d0d 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -20,7 +20,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/editors/object/view3d_iterators.c +/** \file blender/editors/space_view3d/view3d_iterators.c * \ingroup spview3d */ diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 73f1563417c..6105b5e4eb5 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -274,8 +274,8 @@ void view3d_keymap(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle_enum", ZKEY, KM_PRESS, KM_ALT, 0); RNA_string_set(kmi->ptr, "data_path", "space_data.viewport_shade"); - RNA_string_set(kmi->ptr, "value_1", "TEXTURED"); - RNA_string_set(kmi->ptr, "value_2", "SOLID"); + RNA_string_set(kmi->ptr, "value_1", "SOLID"); + RNA_string_set(kmi->ptr, "value_2", "TEXTURED"); /* selection*/ kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_select", SELECTMOUSE, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index 6ba05abae9a..34b983f83df 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -296,7 +296,7 @@ void ED_view3d_win_to_ray(ARegion *ar, View3D *v3d, const float mval[2], float r { float ray_end[3]; - ED_view3d_win_to_segment_clip(ar, v3d, mval, ray_start, ray_end); + ED_view3d_win_to_segment(ar, v3d, mval, ray_start, ray_end); sub_v3_v3v3(ray_normal, ray_end, ray_start); normalize_v3(ray_normal); } @@ -419,19 +419,7 @@ void ED_view3d_win_to_vector(ARegion *ar, const float mval[2], float out[3]) normalize_v3(out); } -/** - * Calculate a 3d segment from 2d window coordinates. - * This ray_start is located at the viewpoint, ray_end is a far point. - * ray_start and ray_end are clipped by the view near and far limits - * so points along this line are always in view. - * In orthographic view all resulting segments will be parallel. - * \param ar The region (used for the window width and height). - * \param v3d The 3d viewport (used for near and far clipping range). - * \param mval The area relative 2d location (such as event->mval, converted into float[2]). - * \param ray_start The world-space starting point of the segment. - * \param ray_end The world-space end point of the segment. - */ -void ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]) +void ED_view3d_win_to_segment(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]) { RegionView3D *rv3d = ar->regiondata; @@ -455,14 +443,46 @@ void ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2] madd_v3_v3v3fl(ray_start, vec, rv3d->viewinv[2], 1000.0f); madd_v3_v3v3fl(ray_end, vec, rv3d->viewinv[2], -1000.0f); } +} + +/** + * Calculate a 3d segment from 2d window coordinates. + * This ray_start is located at the viewpoint, ray_end is a far point. + * ray_start and ray_end are clipped by the view near and far limits + * so points along this line are always in view. + * In orthographic view all resulting segments will be parallel. + * \param ar The region (used for the window width and height). + * \param v3d The 3d viewport (used for near and far clipping range). + * \param mval The area relative 2d location (such as event->mval, converted into float[2]). + * \param ray_start The world-space starting point of the segment. + * \param ray_end The world-space end point of the segment. + * \return success, FALSE if the segment is totally clipped. + */ +int ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]) +{ + RegionView3D *rv3d = ar->regiondata; + ED_view3d_win_to_segment(ar, v3d, mval, ray_start, ray_end); /* clipping */ if (rv3d->rflag & RV3D_CLIPPING) { + /* if the ray is totally clipped, + * restore the original values but return FALSE + * caller can choose what to do */ + float tray_start[3] = {UNPACK3(ray_start)}; + float tray_end[3] = {UNPACK3(ray_end)}; int a; for (a = 0; a < 4; a++) { - clip_line_plane(ray_start, ray_end, rv3d->clip[a]); + if (clip_line_plane(tray_start, tray_end, rv3d->clip[a]) == FALSE) { + return FALSE; + } } + + /* copy in clipped values */ + copy_v3_v3(ray_start, tray_start); + copy_v3_v3(ray_end, tray_end); } + + return TRUE; } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 43626b058d6..cffa53b5dfb 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -221,7 +221,7 @@ static void edbm_backbuf_check_and_select_faces(BMEditMesh *em, int select) } -/* object mode, EM_ prefix is confusing here, rename? */ +/* object mode, edbm_ prefix is confusing here, rename? */ static void edbm_backbuf_check_and_select_verts_obmode(Mesh *me, int select) { MVert *mv = me->mvert; @@ -237,8 +237,8 @@ static void edbm_backbuf_check_and_select_verts_obmode(Mesh *me, int select) } } } -/* object mode, EM_ prefix is confusing here, rename? */ +/* object mode, edbm_ prefix is confusing here, rename? */ static void edbm_backbuf_check_and_select_tfaces(Mesh *me, int select) { MPoly *mpoly = me->mpoly; @@ -1064,11 +1064,11 @@ static EnumPropertyItem *object_select_menu_enum_itemf(bContext *C, PointerRNA * static int object_select_menu_exec(bContext *C, wmOperator *op) { int name_index = RNA_enum_get(op->ptr, "name"); - short extend = RNA_boolean_get(op->ptr, "extend"); + short toggle = RNA_boolean_get(op->ptr, "toggle"); short changed = 0; const char *name = object_mouse_select_menu_data[name_index].idname; - if (!extend) { + if (!toggle) { CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { if (base->flag & SELECT) { @@ -1125,7 +1125,7 @@ void VIEW3D_OT_select_menu(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN); ot->prop = prop; - RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first"); + RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first"); } static void deselectall_except(Scene *scene, Base *b) /* deselect all except b */ @@ -1141,7 +1141,7 @@ static void deselectall_except(Scene *scene, Base *b) /* deselect all except b } } -static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int *buffer, int hits, const int mval[2], short extend) +static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int *buffer, int hits, const int mval[2], short toggle) { short baseCount = 0; short ok; @@ -1207,7 +1207,7 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int PointerRNA ptr; WM_operator_properties_create(&ptr, "VIEW3D_OT_select_menu"); - RNA_boolean_set(&ptr, "extend", extend); + RNA_boolean_set(&ptr, "toggle", toggle); WM_operator_name_call(C, "VIEW3D_OT_select_menu", WM_OP_INVOKE_DEFAULT, &ptr); WM_operator_properties_free(&ptr); } @@ -1440,7 +1440,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese /* note; shift+alt goes to group-flush-selecting */ if (enumerate) { - basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, extend); + basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, toggle); } else { base = startbase; @@ -1480,7 +1480,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese /* note; shift+alt goes to group-flush-selecting */ if (has_bones == 0 && enumerate) { - basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, extend); + basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, toggle); } else { basact = mouse_select_eval_buffer(&vc, buffer, hits, mval, startbase, has_bones); diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c index d36b0085acb..bfeb56036e6 100644 --- a/source/blender/editors/space_view3d/view3d_toolbar.c +++ b/source/blender/editors/space_view3d/view3d_toolbar.c @@ -176,7 +176,7 @@ static uiBlock *tool_search_menu(bContext *C, ARegion *ar, void *arg_listbase) uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_SEARCH_MENU); /* fake button, it holds space for search items */ - uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); + uiDefBut(block, LABEL, 0, "", 10, 15, uiSearchBoxWidth(), uiSearchBoxHeight(), NULL, 0, 0, 0, 0, NULL); but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, 150, 19, 0, 0, ""); uiButSetSearchFunc(but, operator_search_cb, arg_listbase, operator_call_cb, NULL); diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index c16f04f01f3..ef15c1e734e 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -247,9 +247,9 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera copy_qt_qt(rv3d->viewquat, sms.new_quat); rv3d->dist = sms.new_dist; v3d->lens = sms.new_lens; - } - ED_view3d_camera_lock_sync(v3d, rv3d); + ED_view3d_camera_lock_sync(v3d, rv3d); + } if (rv3d->viewlock & RV3D_BOXVIEW) view3d_boxview_copy(sa, ar); @@ -323,8 +323,14 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent if (rv3d->viewlock & RV3D_BOXVIEW) view3d_boxview_copy(CTX_wm_area(C), CTX_wm_region(C)); - + + /* note: this doesn't work right because the v3d->lens is now used in ortho mode r51636, + * when switching camera in quad-view the other ortho views would zoom & reset. */ +#if 0 WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); +#else + ED_region_tag_redraw(CTX_wm_region(C)); +#endif return OPERATOR_FINISHED; } @@ -1028,7 +1034,8 @@ static int view3d_localview_init(Main *bmain, Scene *scene, ScrArea *sa, ReportL { View3D *v3d = sa->spacedata.first; Base *base; - float size = 0.0, min[3], max[3], box[3]; + float min[3], max[3], box[3]; + float size = 0.0f, size_persp = 0.0f, size_ortho = 0.0f; unsigned int locallay; int ok = FALSE; @@ -1068,7 +1075,13 @@ static int view3d_localview_init(Main *bmain, Scene *scene, ScrArea *sa, ReportL box[1] = (max[1] - min[1]); box[2] = (max[2] - min[2]); size = MAX3(box[0], box[1], box[2]); - if (size <= 0.01f) size = 0.01f; + + /* do not zoom closer than the near clipping plane */ + size = max_ff(size, v3d->near * 1.5f); + + /* perspective size (we always switch out of camera view so no need to use its lens size) */ + size_persp = ED_view3d_radius_to_persp_dist(focallength_to_fov(v3d->lens, DEFAULT_SENSOR_WIDTH), size / 2.0f) * VIEW3D_MARGIN; + size_ortho = ED_view3d_radius_to_ortho_dist(v3d->lens, size / 2.0f) * VIEW3D_MARGIN; } if (ok == TRUE) { @@ -1085,14 +1098,20 @@ static int view3d_localview_init(Main *bmain, Scene *scene, ScrArea *sa, ReportL rv3d->localvd = MEM_mallocN(sizeof(RegionView3D), "localview region"); memcpy(rv3d->localvd, rv3d, sizeof(RegionView3D)); - rv3d->ofs[0] = -(min[0] + max[0]) / 2.0f; - rv3d->ofs[1] = -(min[1] + max[1]) / 2.0f; - rv3d->ofs[2] = -(min[2] + max[2]) / 2.0f; + mid_v3_v3v3(v3d->cursor, min, max); + negate_v3_v3(rv3d->ofs, v3d->cursor); + + if (rv3d->persp == RV3D_CAMOB) { + rv3d->persp = RV3D_PERSP; + } - rv3d->dist = size; /* perspective should be a bit farther away to look nice */ - if (rv3d->persp == RV3D_ORTHO) - rv3d->dist *= 0.7f; + if (rv3d->persp != RV3D_ORTHO) { + rv3d->dist = size_persp; + } + else { + rv3d->dist = size_ortho; + } /* correction for window aspect ratio */ if (ar->winy > 2 && ar->winx > 2) { @@ -1100,12 +1119,6 @@ static int view3d_localview_init(Main *bmain, Scene *scene, ScrArea *sa, ReportL if (asp < 1.0f) asp = 1.0f / asp; rv3d->dist *= asp; } - - if (rv3d->persp == RV3D_CAMOB) rv3d->persp = RV3D_PERSP; - - v3d->cursor[0] = -rv3d->ofs[0]; - v3d->cursor[1] = -rv3d->ofs[1]; - v3d->cursor[2] = -rv3d->ofs[2]; } } @@ -1511,7 +1524,7 @@ static void UNUSED_FUNCTION(view3d_align_axis_to_vector)(View3D *v3d, RegionView } } -float ED_view3d_pixel_size(struct RegionView3D *rv3d, const float co[3]) +float ED_view3d_pixel_size(RegionView3D *rv3d, const float co[3]) { return (rv3d->persmat[3][3] + ( rv3d->persmat[0][3] * co[0] + @@ -1520,6 +1533,16 @@ float ED_view3d_pixel_size(struct RegionView3D *rv3d, const float co[3]) ) * rv3d->pixsize; } +float ED_view3d_radius_to_persp_dist(const float angle, const float radius) +{ + return (radius / 2.0f) * fabsf(1.0f / cosf((((float)M_PI) - angle) / 2.0f)); +} + +float ED_view3d_radius_to_ortho_dist(const float lens, const float radius) +{ + return radius / (DEFAULT_SENSOR_WIDTH / lens); +} + /* view matrix properties utilities */ /* unused */ diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt index 05a4f6f4ce5..ec114bc3019 100644 --- a/source/blender/editors/transform/CMakeLists.txt +++ b/source/blender/editors/transform/CMakeLists.txt @@ -25,6 +25,7 @@ set(INC ../../blenlib ../../blenloader ../../bmesh + ../../ikplugin ../../makesdna ../../makesrna ../../windowmanager diff --git a/source/blender/editors/transform/SConscript b/source/blender/editors/transform/SConscript index dbf6179035c..9cf36a2d970 100644 --- a/source/blender/editors/transform/SConscript +++ b/source/blender/editors/transform/SConscript @@ -6,7 +6,7 @@ sources = env.Glob('*.c') incs = '../include ../../blenfont ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../render/extern/include' -incs += ' ../../gpu ../../makesrna ../../blenloader ../../bmesh' +incs += ' ../../gpu ../../makesrna ../../blenloader ../../bmesh ../../ikplugin' defs = [] diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 245241763fd..6145fec7e51 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -526,6 +526,10 @@ static void viewRedrawPost(bContext *C, TransInfo *t) /* if autokeying is enabled, send notifiers that keyframes were added */ if (IS_AUTOKEY_ON(t->scene)) WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + + /* redraw UV editor */ + if (t->mode == TFM_EDGE_SLIDE && (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) + WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); /* XXX temp, first hack to get auto-render in compositor work (ton) */ WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, CTX_data_scene(C)); @@ -1223,8 +1227,10 @@ int transformEvent(TransInfo *t, wmEvent *event) break; case LEFTALTKEY: case RIGHTALTKEY: - if (t->spacetype == SPACE_SEQ) + if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) { t->flag |= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + } break; default: @@ -1262,8 +1268,10 @@ int transformEvent(TransInfo *t, wmEvent *event) // break; case LEFTALTKEY: case RIGHTALTKEY: - if (t->spacetype == SPACE_SEQ) + if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) { t->flag &= ~T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + } break; default: @@ -2419,6 +2427,8 @@ static void constraintSizeLim(TransInfo *t, TransData *td) bConstraintTypeInfo *cti = get_constraint_typeinfo(CONSTRAINT_TYPE_SIZELIMIT); bConstraintOb cob = {NULL}; bConstraint *con; + float size_sign[3], size_abs[3]; + int i; /* Make a temporary bConstraintOb for using these limit constraints * - they only care that cob->matrix is correctly set ;-) @@ -2432,8 +2442,14 @@ static void constraintSizeLim(TransInfo *t, TransData *td) /* Reset val if SINGLESIZE but using a constraint */ if (td->flag & TD_SINGLESIZE) return; + + /* separate out sign to apply back later */ + for (i = 0; i < 3; i++) { + size_sign[i] = signf(td->ext->size[i]); + size_abs[i] = fabsf(td->ext->size[i]); + } - size_to_mat4(cob.matrix, td->ext->size); + size_to_mat4(cob.matrix, size_abs); } /* Evaluate valid constraints */ @@ -2481,7 +2497,9 @@ static void constraintSizeLim(TransInfo *t, TransData *td) if (td->flag & TD_SINGLESIZE) return; + /* extrace scale from matrix and apply back sign */ mat4_to_size(td->ext->size, cob.matrix); + mul_v3_v3(td->ext->size, size_sign); } } } @@ -2852,11 +2870,21 @@ static void headerResize(TransInfo *t, float vec[3], char *str) (void)spos; } -#define SIGN(a) (a<-FLT_EPSILON ? 1 : a>FLT_EPSILON ? 2 : 3) -#define VECSIGNFLIP(a, b) ((SIGN(a[0]) & SIGN(b[0])) == 0 || (SIGN(a[1]) & SIGN(b[1])) == 0 || (SIGN(a[2]) & SIGN(b[2])) == 0) +/* FLT_EPSILON is too small [#29633], 0.0000001f starts to flip */ +#define TX_FLIP_EPS 0.00001f +BLI_INLINE int tx_sign(const float a) +{ + return (a < -TX_FLIP_EPS ? 1 : a > TX_FLIP_EPS ? 2 : 3); +} +BLI_INLINE int tx_vec_sign_flip(const float a[3], const float b[3]) +{ + return ((tx_sign(a[0]) & tx_sign(b[0])) == 0 || + (tx_sign(a[1]) & tx_sign(b[1])) == 0 || + (tx_sign(a[2]) & tx_sign(b[2])) == 0); +} /* smat is reference matrix, only scaled */ -static void TransMat3ToSize(float mat[][3], float smat[][3], float *size) +static void TransMat3ToSize(float mat[][3], float smat[][3], float size[3]) { float vec[3]; @@ -2868,9 +2896,9 @@ static void TransMat3ToSize(float mat[][3], float smat[][3], float *size) size[2] = normalize_v3(vec); /* first tried with dotproduct... but the sign flip is crucial */ - if (VECSIGNFLIP(mat[0], smat[0]) ) size[0] = -size[0]; - if (VECSIGNFLIP(mat[1], smat[1]) ) size[1] = -size[1]; - if (VECSIGNFLIP(mat[2], smat[2]) ) size[2] = -size[2]; + if (tx_vec_sign_flip(mat[0], smat[0]) ) size[0] = -size[0]; + if (tx_vec_sign_flip(mat[1], smat[1]) ) size[1] = -size[1]; + if (tx_vec_sign_flip(mat[2], smat[2]) ) size[2] = -size[2]; } @@ -3947,10 +3975,8 @@ void initShrinkFatten(TransInfo *t) } - int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) { - float vec[3]; float distance; int i; char str[64]; @@ -3978,17 +4004,20 @@ int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) t->values[0] = -distance; for (i = 0; i < t->total; i++, td++) { + float tdistance; /* temp dist */ if (td->flag & TD_NOACTION) break; if (td->flag & TD_SKIP) continue; - copy_v3_v3(vec, td->axismtx[2]); - mul_v3_fl(vec, distance); - mul_v3_fl(vec, td->factor); + /* get the final offset */ + tdistance = distance * td->factor; + if (td->ext && (t->flag & T_ALT_TRANSFORM)) { + tdistance *= td->ext->isize[0]; /* shell factor */ + } - add_v3_v3v3(td->loc, td->iloc, vec); + madd_v3_v3v3fl(td->loc, td->iloc, td->axismtx[2], tdistance); } recalcData(t); @@ -4847,14 +4876,9 @@ static void calcNonProportionalEdgeSlide(TransInfo *t, SlideData *sld, const flo float dist = 0; float min_dist = FLT_MAX; - float up_p[3]; - float dw_p[3]; - for (i = 0; i < sld->totsv; i++, sv++) { /* Set length */ - add_v3_v3v3(up_p, sv->origvert.co, sv->upvec); - add_v3_v3v3(dw_p, sv->origvert.co, sv->downvec); - sv->edge_len = len_v3v3(dw_p, up_p); + sv->edge_len = len_v3v3(sv->upvec, sv->downvec); mul_v3_m4v3(v_proj, t->obedit->obmat, sv->v->co); if (ED_view3d_project_float_global(t->ar, v_proj, v_proj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { @@ -5595,7 +5619,6 @@ static int doEdgeSlide(TransInfo *t, float perc) { SlideData *sld = t->customData; TransDataSlideVert *svlist = sld->sv, *sv; - float vec[3]; int i; sld->perc = perc; @@ -5603,6 +5626,7 @@ static int doEdgeSlide(TransInfo *t, float perc) if (sld->is_proportional == TRUE) { for (i = 0; i < sld->totsv; i++, sv++) { + float vec[3]; if (perc > 0.0f) { copy_v3_v3(vec, sv->upvec); mul_v3_fl(vec, perc); @@ -5620,20 +5644,29 @@ static int doEdgeSlide(TransInfo *t, float perc) * Implementation note, non proportional mode ignores the starting positions and uses only the * up/down verts, this could be changed/improved so the distance is still met but the verts are moved along * their original path (which may not be straight), however how it works now is OK and matches 2.4x - Campbell + * + * \note len_v3v3(curr_sv->upvec, curr_sv->downvec) + * is the same as the distance between the original vert locations, same goes for the lines below. */ TransDataSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; - const float curr_length_perc = len_v3v3(curr_sv->up->co, curr_sv->down->co) * - (((sld->flipped_vtx ? perc : -perc) + 1.0f) / 2.0f); + const float curr_length_perc = curr_sv->edge_len * (((sld->flipped_vtx ? perc : -perc) + 1.0f) / 2.0f); + + float down_co[3]; + float up_co[3]; for (i = 0; i < sld->totsv; i++, sv++) { - const float sv_length = len_v3v3(sv->up->co, sv->down->co); - const float fac = min_ff(sv_length, curr_length_perc) / sv_length; + if (sv->edge_len > FLT_EPSILON) { + const float fac = min_ff(sv->edge_len, curr_length_perc) / sv->edge_len; - if (sld->flipped_vtx) { - interp_v3_v3v3(sv->v->co, sv->down->co, sv->up->co, fac); - } - else { - interp_v3_v3v3(sv->v->co, sv->up->co, sv->down->co, fac); + add_v3_v3v3(up_co, sv->origvert.co, sv->upvec); + add_v3_v3v3(down_co, sv->origvert.co, sv->downvec); + + if (sld->flipped_vtx) { + interp_v3_v3v3(sv->v->co, down_co, up_co, fac); + } + else { + interp_v3_v3v3(sv->v->co, up_co, down_co, fac); + } } } } diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 1f9775821d1..bc959a772d6 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -197,6 +197,7 @@ typedef struct TransDataSlideVert { float edge_len; + /* add origvert.co to get the original locations */ float upvec[3], downvec[3]; int loop_nr; diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 311cb5ee94d..947bdf53bee 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -150,8 +150,8 @@ static void postConstraintChecks(TransInfo *t, float vec[3], float pvec[3]) if (hasNumInput(&t->num)) { applyNumInput(&t->num, vec); - removeAspectRatio(t, vec); constraintNumInput(t, vec); + removeAspectRatio(t, vec); } /* autovalues is operator param, use that directly but not if snapping is forced */ diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index f6b888d4881..51efa2b0e40 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -91,6 +91,7 @@ #include "BKE_tracking.h" #include "BKE_mask.h" +#include "BIK_api.h" #include "ED_anim_api.h" #include "ED_armature.h" @@ -773,6 +774,9 @@ static void pose_grab_with_ik_clear(Object *ob) if (con->type == CONSTRAINT_TYPE_KINEMATIC) { data = con->data; if (data->flag & CONSTRAINT_IK_TEMP) { + /* iTaSC needs clear for removed constraints */ + BIK_clear_data(ob->pose); + BLI_remlink(&pchan->constraints, con); MEM_freeN(con->data); MEM_freeN(con); @@ -839,7 +843,7 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan) } else data->flag = CONSTRAINT_IK_TIP; - data->flag |= CONSTRAINT_IK_TEMP | CONSTRAINT_IK_AUTO; + data->flag |= CONSTRAINT_IK_TEMP | CONSTRAINT_IK_AUTO | CONSTRAINT_IK_POS; copy_v3_v3(data->grabtarget, pchan->pose_tail); data->rootbone = 0; /* watch-it! has to be 0 here, since we're still on the same bone for the first time through the loop [#25885] */ @@ -933,6 +937,10 @@ static short pose_grab_with_ik(Object *ob) } } + /* iTaSC needs clear for new IK constraints */ + if (tot_ik) + BIK_clear_data(ob->pose); + return (tot_ik) ? 1 : 0; } @@ -1917,6 +1925,10 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx tx->size = vs->radius; td->val = vs->radius; } + else if (t->mode == TFM_SHRINKFATTEN) { + td->ext = tx; + tx->isize[0] = BM_vert_calc_shell_factor(eve); + } } static void createTransEditVerts(TransInfo *t) @@ -2029,7 +2041,11 @@ static void createTransEditVerts(TransInfo *t) else t->total = countsel; tob = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Mesh EditMode)"); - if (t->mode == TFM_SKIN_RESIZE) { + if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) { + /* warning, this is overkill, we only need 2 extra floats, + * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill + * since we may not use the 'alt' transform mode to maintain shell thickness, + * but with generic transform code its hard to lazy init vars */ tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "TransObData ext"); } @@ -2478,7 +2494,7 @@ int clipUVTransform(TransInfo *t, float *vec, int resize) max[0] = aspx; max[1] = aspy; for (a = 0, td = t->data; a < t->total; a++, td++) { - DO_MINMAX2(td->loc, min, max); + minmax_v2v2_v2(min, max, td->loc); } if (resize) { @@ -5029,9 +5045,10 @@ static void special_aftertrans_update__mask(bContext *C, TransInfo *t) if (t->scene->nodetree) { /* tracks can be used for stabilization nodes, * flush update for such nodes */ - //if (nodeUpdateID(t->scene->nodetree, &mask->id)) { + //if (nodeUpdateID(t->scene->nodetree, &mask->id)) + { WM_event_add_notifier(C, NC_MASK | ND_DATA, &mask->id); - //} + } } /* TODO - dont key all masks... */ diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index 0780b8f90b5..a3f45acc02e 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -744,7 +744,7 @@ static char axisBlendAngle(float angle) return (char)(255.0f * (angle - 5) / 15.0f); } -/* three colors can be set; +/* three colors can be set: * gray for ghosting * moving: in transform theme color * else the red/green/blue @@ -776,15 +776,13 @@ static void manipulator_setcolor(View3D *v3d, char axis, int colcode, unsigned c } break; case 'X': - col[0] = 220; + UI_GetThemeColor3ubv(TH_AXIS_X, col); break; case 'Y': - col[1] = 220; + UI_GetThemeColor3ubv(TH_AXIS_Y, col); break; case 'Z': - col[0] = 30; - col[1] = 30; - col[2] = 220; + UI_GetThemeColor3ubv(TH_AXIS_Z, col); break; default: BLI_assert(!"invalid axis arg"); diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index a6fb7e7ed00..2d95e2ecdc6 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -408,9 +408,15 @@ static void initSnappingMode(TransInfo *t) t->tsnap.mode = ts->snap_node_mode; } + else if (t->spacetype == SPACE_IMAGE) { + /* force project off when not supported */ + t->tsnap.project = 0; + + t->tsnap.mode = ts->snap_uv_mode; + } else { /* force project off when not supported */ - if (t->spacetype == SPACE_IMAGE || ts->snap_mode != SCE_SNAP_MODE_FACE) + if (ts->snap_mode != SCE_SNAP_MODE_FACE) t->tsnap.project = 0; t->tsnap.mode = ts->snap_mode; diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c index b73f5fa0869..0ec16ead35d 100644 --- a/source/blender/editors/util/numinput.c +++ b/source/blender/editors/util/numinput.c @@ -130,6 +130,9 @@ short hasNumInput(NumInput *n) return 0; } +/** + * \warning \a vec must be set beforehand otherwise we risk uninitialized vars. + */ void applyNumInput(NumInput *n, float *vec) { short i, j; diff --git a/source/blender/editors/uvedit/uvedit_buttons.c b/source/blender/editors/uvedit/uvedit_buttons.c index fa39a52444b..1c32c01b8f0 100644 --- a/source/blender/editors/uvedit/uvedit_buttons.c +++ b/source/blender/editors/uvedit/uvedit_buttons.c @@ -94,14 +94,19 @@ static int uvedit_center(Scene *scene, BMEditMesh *em, Image *ima, float center[ return tot; } -static void uvedit_translate(Scene *scene, BMEditMesh *em, Image *UNUSED(ima), float delta[2]) +static void uvedit_translate(Scene *scene, BMEditMesh *em, Image *ima, float delta[2]) { BMFace *f; BMLoop *l; BMIter iter, liter; MLoopUV *luv; + MTexPoly *tf; BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) { + tf = CustomData_bmesh_get(&em->bm->pdata, f->head.data, CD_MTEXPOLY); + if (!uvedit_face_visible_test(scene, ima, f, tf)) + continue; + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); if (uvedit_uv_select_test(em, scene, l)) { diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index e860d486ea3..a384c777aab 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -224,7 +224,9 @@ void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *im BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); - if (uvedit_face_visible_test(scene, previma, efa, tf)) { + if (uvedit_face_visible_test(scene, previma, efa, tf) && + (selected == TRUE || uvedit_face_select_test(scene, em, efa))) + { if (ima) { tf->tpage = ima; @@ -616,7 +618,7 @@ int ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float r_min[2], f BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - DO_MINMAX2(luv->uv, r_min, r_max); + minmax_v2v2_v2(r_min, r_max, luv->uv); sel = 1; } } @@ -1327,7 +1329,7 @@ static void weld_align_uv(bContext *C, int tool) BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - DO_MINMAX2(luv->uv, min, max); + minmax_v2v2_v2(min, max, luv->uv); } } } @@ -1553,7 +1555,170 @@ static void UV_OT_align(wmOperatorType *ot) /* properties */ RNA_def_enum(ot->srna, "axis", axis_items, 'a', "Axis", "Axis to align UV locations on"); } +/* ******************** weld near operator **************** */ +typedef struct UVvert { + MLoopUV *uv_loop; + int weld; +} UVvert; + +static int remove_doubles_exec(bContext *C, wmOperator *op) +{ + const float threshold = RNA_float_get(op->ptr, "threshold"); + const int use_unselected = RNA_boolean_get(op->ptr, "use_unselected"); + + SpaceImage *sima; + Scene *scene; + Object *obedit; + Image *ima; + BMEditMesh *em; + MTexPoly *tf; + int uv_a_index; + int uv_b_index; + float *uv_a; + float *uv_b; + + BMIter iter, liter; + BMFace *efa; + BMLoop *l; + + sima = CTX_wm_space_image(C); + scene = CTX_data_scene(C); + obedit = CTX_data_edit_object(C); + em = BMEdit_FromObject(obedit); + ima = CTX_data_edit_image(C); + + if (use_unselected == FALSE) { + UVvert *vert_arr = NULL; + BLI_array_declare(vert_arr); + MLoopUV **loop_arr = NULL; + BLI_array_declare(loop_arr); + + /* TODO, use qsort as with MESH_OT_remove_doubles, this isn't optimal */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if (!uvedit_face_visible_test(scene, ima, efa, tf)) + continue; + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (uvedit_uv_select_test(em, scene, l)) { + MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + UVvert vert; + vert.uv_loop = luv; + vert.weld = FALSE; + BLI_array_append(vert_arr, vert); + } + + } + } + + for (uv_a_index = 0; uv_a_index < BLI_array_count(vert_arr); uv_a_index++) { + if (vert_arr[uv_a_index].weld == FALSE) { + float uv_min[2]; + float uv_max[2]; + + BLI_array_empty(loop_arr); + BLI_array_append(loop_arr, vert_arr[uv_a_index].uv_loop); + + uv_a = vert_arr[uv_a_index].uv_loop->uv; + + copy_v2_v2(uv_max, uv_a); + copy_v2_v2(uv_min, uv_a); + + vert_arr[uv_a_index].weld = TRUE; + for (uv_b_index = uv_a_index + 1; uv_b_index < BLI_array_count(vert_arr); uv_b_index++) { + uv_b = vert_arr[uv_b_index].uv_loop->uv; + if ((vert_arr[uv_b_index].weld == FALSE) && + (len_manhattan_v2v2(uv_a, uv_b) < threshold)) + { + minmax_v2v2_v2(uv_max, uv_min, uv_b); + BLI_array_append(loop_arr, vert_arr[uv_b_index].uv_loop); + vert_arr[uv_b_index].weld = TRUE; + } + } + if (BLI_array_count(loop_arr)) { + float uv_mid[2]; + mid_v2_v2v2(uv_mid, uv_min, uv_max); + for (uv_b_index = 0; uv_b_index < BLI_array_count(loop_arr); uv_b_index++) { + copy_v2_v2(loop_arr[uv_b_index]->uv, uv_mid); + } + } + } + } + + BLI_array_free(vert_arr); + BLI_array_free(loop_arr); + } + else { + /* selected -> unselected + * + * No need to use 'UVvert' here */ + MLoopUV **loop_arr = NULL; + BLI_array_declare(loop_arr); + MLoopUV **loop_arr_unselected = NULL; + BLI_array_declare(loop_arr_unselected); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if (!uvedit_face_visible_test(scene, ima, efa, tf)) + continue; + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + if (uvedit_uv_select_test(em, scene, l)) { + BLI_array_append(loop_arr, luv); + } + else { + BLI_array_append(loop_arr_unselected, luv); + } + } + } + + for (uv_a_index = 0; uv_a_index < BLI_array_count(loop_arr); uv_a_index++) { + float dist_best = FLT_MAX, dist; + float *uv_best = NULL; + + uv_a = loop_arr[uv_a_index]->uv; + for (uv_b_index = 0; uv_b_index < BLI_array_count(loop_arr_unselected); uv_b_index++) { + uv_b = loop_arr_unselected[uv_b_index]->uv; + dist = len_manhattan_v2v2(uv_a, uv_b); + if ((dist < threshold) && (dist < dist_best)) { + uv_best = uv_b; + dist_best = dist; + } + } + if (uv_best) { + copy_v2_v2(uv_a, uv_best); + } + } + + BLI_array_free(loop_arr); + BLI_array_free(loop_arr_unselected); + } + + uvedit_live_unwrap_update(sima, scene, obedit); + DAG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +static void UV_OT_remove_doubles(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Doubles UV"; + ot->description = "Selected UV vertices that are within a radius of each other are welded together"; + ot->idname = "UV_OT_remove_doubles"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = remove_doubles_exec; + ot->poll = ED_operator_uvedit; + + RNA_def_float(ot->srna, "threshold", 0.02f, 0.0f, 10.0f, + "Merge Distance", "Maximum distance between welded vertices", 0.0f, 1.0f); + RNA_def_boolean(ot->srna, "use_unselected", 0, "Unselected", "Merge selected to other unselected vertices"); +} /* ******************** weld operator **************** */ static int weld_exec(bContext *C, wmOperator *UNUSED(op)) @@ -2504,10 +2669,12 @@ static void uv_faces_do_sticky(SpaceImage *sima, Scene *scene, Object *obedit, s else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - if (select) + if (select) { uvedit_face_select_enable(scene, em, efa, FALSE); - else + } + else { uvedit_face_select_disable(scene, em, efa); + } } } } @@ -2529,7 +2696,10 @@ static int border_select_exec(bContext *C, wmOperator *op) MLoopUV *luv; rcti rect; rctf rectf; - int change, pinned, select, faces, extend; + int change, pinned, select, extend; + const int use_face_center = (ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_FACE) : + (ts->uv_selectmode == UV_SELECT_FACE); /* get rectangle from operator */ WM_operator_properties_border_to_rcti(op, &rect); @@ -2544,14 +2714,9 @@ static int border_select_exec(bContext *C, wmOperator *op) if (!extend) select_all_perform(scene, ima, em, SEL_DESELECT); - - if (ts->uv_flag & UV_SYNC_SELECTION) - faces = (ts->selectmode == SCE_SELECT_FACE); - else - faces = (ts->uv_selectmode == UV_SELECT_FACE); /* do actual selection */ - if (faces && !pinned) { + if (use_face_center && !pinned) { /* handle face selection mode */ float cent[2]; @@ -2572,8 +2737,9 @@ static int border_select_exec(bContext *C, wmOperator *op) } /* (de)selects all tagged faces and deals with sticky modes */ - if (change) + if (change) { uv_faces_do_sticky(sima, scene, obedit, select); + } } else { /* other selection modes */ @@ -2642,19 +2808,19 @@ static void UV_OT_select_border(wmOperatorType *ot) /* ******************** circle select operator **************** */ -static int select_uv_inside_ellipse(BMEditMesh *em, SpaceImage *UNUSED(sima), Scene *scene, int select, - float *offset, float *ell, BMLoop *l, MLoopUV *luv) +static int uv_inside_circle(const float uv[2], const float offset[2], const float ellipse[2]) { /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ - float x, y, r2, *uv; + float x, y; + x = (uv[0] - offset[0]) * ellipse[0]; + y = (uv[1] - offset[1]) * ellipse[1]; + return ((x * x + y * y) < 1.0f); +} - uv = luv->uv; - - x = (uv[0] - offset[0]) * ell[0]; - y = (uv[1] - offset[1]) * ell[1]; - - r2 = x * x + y * y; - if (r2 < 1.0f) { +static int select_uv_inside_ellipse(BMEditMesh *em, Scene *scene, const int select, + const float offset[2], const float ellipse[2], BMLoop *l, MLoopUV *luv) +{ + if (uv_inside_circle(luv->uv, offset, ellipse)) { if (select) uvedit_uv_select_enable(em, scene, l, FALSE); else uvedit_uv_select_disable(em, scene, l); return TRUE; @@ -2680,6 +2846,9 @@ static int circle_select_exec(bContext *C, wmOperator *op) float zoomx, zoomy, offset[2], ellipse[2]; int gesture_mode = RNA_int_get(op->ptr, "gesture_mode"); int change = FALSE; + const int use_face_center = (ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_FACE) : + (ts->uv_selectmode == UV_SELECT_FACE); /* get operator properties */ select = (gesture_mode == GESTURE_MODAL_SELECT); @@ -2698,10 +2867,32 @@ static int circle_select_exec(bContext *C, wmOperator *op) UI_view2d_region_to_view(&ar->v2d, x, y, &offset[0], &offset[1]); /* do selection */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - change |= select_uv_inside_ellipse(em, sima, scene, select, offset, ellipse, l, luv); + if (use_face_center) { + change = FALSE; + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_elem_flag_disable(efa, BM_ELEM_TAG); + /* assume not touched */ + if ((select) != (uvedit_face_select_test(scene, em, efa))) { + float cent[2]; + uv_poly_center(em, efa, cent); + if (uv_inside_circle(cent, offset, ellipse)) { + BM_elem_flag_enable(efa, BM_ELEM_TAG); + change = TRUE; + } + } + } + + /* (de)selects all tagged faces and deals with sticky modes */ + if (change) { + uv_faces_do_sticky(sima, scene, obedit, select); + } + } + else { + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + change |= select_uv_inside_ellipse(em, scene, select, offset, ellipse, l, luv); + } } } @@ -2743,12 +2934,16 @@ static void UV_OT_circle_select(wmOperatorType *ot) static int do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short moves, short select) { + SpaceImage *sima = CTX_wm_space_image(C); Image *ima = CTX_data_edit_image(C); ARegion *ar = CTX_wm_region(C); Object *obedit = CTX_data_edit_object(C); Scene *scene = CTX_data_scene(C); ToolSettings *ts = scene->toolsettings; BMEditMesh *em = BMEdit_FromObject(obedit); + const int use_face_center = (ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_FACE) : + (ts->uv_selectmode == UV_SELECT_FACE); BMIter iter, liter; @@ -2760,9 +2955,10 @@ static int do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mov BLI_lasso_boundbox(&rect, mcords, moves); - if (ts->uv_selectmode == UV_SELECT_FACE) { /* Face Center Sel */ + if (use_face_center) { /* Face Center Sel */ change = FALSE; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_elem_flag_disable(efa, BM_ELEM_TAG); /* assume not touched */ if ((select) != (uvedit_face_select_test(scene, em, efa))) { float cent[2]; @@ -2771,11 +2967,16 @@ static int do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mov if (BLI_rcti_isect_pt_v(&rect, screen_uv) && BLI_lasso_is_point_inside(mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED)) { - uvedit_face_select_enable(scene, em, efa, FALSE); + BM_elem_flag_enable(efa, BM_ELEM_TAG); change = TRUE; } } } + + /* (de)selects all tagged faces and deals with sticky modes */ + if (change) { + uv_faces_do_sticky(sima, scene, obedit, select); + } } else { /* Vert Sel */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { @@ -3232,7 +3433,7 @@ static int hide_exec(bContext *C, wmOperator *op) MTexPoly *tf; int swap = RNA_boolean_get(op->ptr, "unselected"); Image *ima = sima ? sima->image : NULL; - int facemode = (ts->uv_selectmode == UV_SELECT_FACE); + const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE); if (ts->uv_flag & UV_SYNC_SELECTION) { EDBM_mesh_hide(em, swap); @@ -3262,7 +3463,7 @@ static int hide_exec(bContext *C, wmOperator *op) if (hide) { /* note, a special case for edges could be used, * for now edges act like verts and get flushed */ - if (facemode) { + if (use_face_center) { if (em->selectmode == SCE_SELECT_FACE) { /* check that every UV is selected */ if (bm_face_is_all_uv_sel(em->bm, efa, TRUE) == !swap) { @@ -3280,8 +3481,6 @@ static int hide_exec(bContext *C, wmOperator *op) } } if (!swap) uvedit_face_select_disable(scene, em, efa); - - } } else if (em->selectmode == SCE_SELECT_FACE) { @@ -3344,8 +3543,8 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) BMLoop *l; BMIter iter, liter; MLoopUV *luv; - int facemode = (ts->uv_selectmode == UV_SELECT_FACE); - int stickymode = sima ? (sima->sticky != SI_STICKY_DISABLE) : 1; + const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE); + const int stickymode = sima ? (sima->sticky != SI_STICKY_DISABLE) : 1; /* note on tagging, selecting faces needs to be delayed so it doesn't select the verts and * confuse our checks on selected verts. */ @@ -3357,7 +3556,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } - if (facemode) { + if (use_face_center) { if (em->selectmode == SCE_SELECT_FACE) { BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { BM_elem_flag_disable(efa, BM_ELEM_TAG); @@ -3776,6 +3975,7 @@ void ED_operatortypes_uvedit(void) WM_operatortype_append(UV_OT_seams_from_islands); WM_operatortype_append(UV_OT_mark_seam); WM_operatortype_append(UV_OT_weld); + WM_operatortype_append(UV_OT_remove_doubles); WM_operatortype_append(UV_OT_pin); WM_operatortype_append(UV_OT_average_islands_scale); diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c index 5b6125b558b..8703234122a 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.c +++ b/source/blender/editors/uvedit/uvedit_parametrizer.c @@ -450,7 +450,7 @@ static void p_chart_uv_bbox(PChart *chart, float minv[2], float maxv[2]) INIT_MINMAX2(minv, maxv); for (v = chart->verts; v; v = v->nextlink) { - DO_MINMAX2(v->uv, minv, maxv); + minmax_v2v2_v2(minv, maxv, v->uv); } } @@ -3891,9 +3891,9 @@ static void p_smooth(PChart *chart) INIT_MINMAX2(fmin, fmax); - DO_MINMAX2(e1->vert->uv, fmin, fmax); - DO_MINMAX2(e2->vert->uv, fmin, fmax); - DO_MINMAX2(e3->vert->uv, fmin, fmax); + minmax_v2v2_v2(fmin, fmax, e1->vert->uv); + minmax_v2v2_v2(fmin, fmax, e2->vert->uv); + minmax_v2v2_v2(fmin, fmax, e3->vert->uv); bx1 = (int)((fmin[0] - minv[0]) * invmedian); by1 = (int)((fmin[1] - minv[1]) * invmedian); diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index b1945c37048..4ca642690c4 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -1072,17 +1072,23 @@ static int stitch_init(bContext *C, wmOperator *op) BMEditMesh *em; GHashIterator *ghi; UvEdge *all_edges; - StitchState *state = MEM_mallocN(sizeof(StitchState), "stitch state"); + StitchState *state; Scene *scene = CTX_data_scene(C); ToolSettings *ts = scene->toolsettings; + ARegion *ar = CTX_wm_region(C); Object *obedit = CTX_data_edit_object(C); - op->customdata = state; + if (!ar) + return 0; + + state = MEM_mallocN(sizeof(StitchState), "stitch state"); if (!state) return 0; + op->customdata = state; + /* initialize state */ state->use_limit = RNA_boolean_get(op->ptr, "use_limit"); state->limit_dist = RNA_float_get(op->ptr, "limit"); @@ -1091,7 +1097,7 @@ static int stitch_init(bContext *C, wmOperator *op) state->static_island = RNA_int_get(op->ptr, "static_island"); state->midpoints = RNA_boolean_get(op->ptr, "midpoint_snap"); state->clear_seams = RNA_boolean_get(op->ptr, "clear_seams"); - state->draw_handle = ED_region_draw_cb_activate(CTX_wm_region(C)->type, stitch_draw, NULL, REGION_DRAW_POST_VIEW); + state->draw_handle = ED_region_draw_cb_activate(ar->type, stitch_draw, NULL, REGION_DRAW_POST_VIEW); /* in uv synch selection, all uv's are visible */ if (ts->uv_flag & UV_SYNC_SELECTION) { state->element_map = EDBM_uv_element_map_create(state->em, 0, 1); @@ -1444,18 +1450,22 @@ static int stitch_modal(bContext *C, wmOperator *op, wmEvent *event) } case PADENTER: case RETKEY: - if (stitch_process_data(stitch_state, scene, 1)) { - stitch_exit(C, op, 1); - return OPERATOR_FINISHED; + if (event->val == KM_PRESS) { + if (stitch_process_data(stitch_state, scene, 1)) { + stitch_exit(C, op, 1); + return OPERATOR_FINISHED; + } + else { + return stitch_cancel(C, op); + } } else { - return stitch_cancel(C, op); + return OPERATOR_PASS_THROUGH; } - /* Increase limit */ case PADPLUSKEY: case WHEELUPMOUSE: - if (event->alt) { + if (event->val == KM_PRESS && event->alt) { stitch_state->limit_dist += 0.01f; if (!stitch_process_data(stitch_state, scene, 0)) { return stitch_cancel(C, op); @@ -1468,7 +1478,7 @@ static int stitch_modal(bContext *C, wmOperator *op, wmEvent *event) /* Decrease limit */ case PADMINUS: case WHEELDOWNMOUSE: - if (event->alt) { + if (event->val == KM_PRESS && event->alt) { stitch_state->limit_dist -= 0.01f; stitch_state->limit_dist = MAX2(0.01f, stitch_state->limit_dist); if (!stitch_process_data(stitch_state, scene, 0)) { diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index f615902eedf..1f3f21967f4 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -232,7 +232,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh BLI_srand(0); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - ScanFillVert *sf_vert, *sf_vert_last, *sf_vert_first; + ScanFillVert *sf_vert = NULL, *sf_vert_last, *sf_vert_first; ScanFillFace *sf_tri; ParamKey key, vkeys[4]; ParamBool pin[4], select[4]; @@ -306,7 +306,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert); - BLI_scanfill_calc_ex(&sf_ctx, TRUE, efa->no); + BLI_scanfill_calc_ex(&sf_ctx, 0, efa->no); for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { int i; ls[0] = sf_tri->v1->tmp.p; @@ -1089,7 +1089,7 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - DO_MINMAX2(luv->uv, min, max); + minmax_v2v2_v2(min, max, luv->uv); } } @@ -1414,7 +1414,7 @@ static void uv_map_mirror(BMEditMesh *em, BMFace *efa, MTexPoly *UNUSED(tf)) BMIter liter; MLoopUV *luv; float **uvs = NULL; - BLI_array_fixedstack_declare(uvs, BM_NGON_STACK_SIZE, efa->len, __func__); + BLI_array_fixedstack_declare(uvs, BM_DEFAULT_NGON_STACK_SIZE, efa->len, __func__); float dx; int i, mi; diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 97e8b756d08..c46230de8bf 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -110,7 +110,6 @@ GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data); GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, int isdata); GPUNodeLink *GPU_texture(int size, float *pixels); GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex, int dynamictype, void *data); -GPUNodeLink *GPU_socket(GPUNodeStack *sock); GPUNodeLink *GPU_builtin(GPUBuiltin builtin); int GPU_link(GPUMaterial *mat, const char *name, ...); diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript index f7ed9effc7a..9b8a86eac15 100644 --- a/source/blender/gpu/SConscript +++ b/source/blender/gpu/SConscript @@ -27,7 +27,6 @@ sources.extend(( os.path.join(env['DATA_SOURCES'], "gpu_shader_vertex.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_frag.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_vert.glsl.c"), - os.path.join(env['DATA_SOURCES'], "gpu_shader_material.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_frag.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_vert.glsl.c"), )) diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index b4490e656f3..4432627ee7e 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -1148,15 +1148,6 @@ GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, int dynamictype, void *data) return link; } -GPUNodeLink *GPU_socket(GPUNodeStack *sock) -{ - GPUNodeLink *link = GPU_node_link_create(0); - - link->socket= sock; - - return link; -} - GPUNodeLink *GPU_builtin(GPUBuiltin builtin) { GPUNodeLink *link = GPU_node_link_create(0); diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 7bd72430969..d466e59452b 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -318,7 +318,7 @@ static void gpu_make_repbind(Image *ima) { ImBuf *ibuf; - ibuf = BKE_image_get_ibuf(ima, NULL); + ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ibuf==NULL) return; @@ -333,6 +333,8 @@ static void gpu_make_repbind(Image *ima) if (ima->totbind>1) ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind"); + + BKE_image_release_ibuf(ima, ibuf, NULL); } static void gpu_clear_tpage(void) @@ -479,7 +481,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int return 0; /* check if we have a valid image buffer */ - ibuf= BKE_image_get_ibuf(ima, iuser); + ibuf= BKE_image_acquire_ibuf(ima, iuser, NULL); if (ibuf==NULL) return 0; @@ -574,6 +576,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int if (*bind != 0) { /* enable opengl drawing with textures */ glBindTexture(GL_TEXTURE_2D, *bind); + BKE_image_release_ibuf(ima, ibuf, NULL); return *bind; } @@ -635,6 +638,8 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int if (srgb_frect) MEM_freeN(srgb_frect); + BKE_image_release_ibuf(ima, ibuf, NULL); + return *bind; } @@ -722,8 +727,8 @@ int GPU_upload_dxt_texture(ImBuf *ibuf) GLint format = 0; int blocksize, height, width, i, size, offset = 0; - height = ibuf->x; - width = ibuf->y; + width = ibuf->x; + height = ibuf->y; if (GLEW_EXT_texture_compression_s3tc) { if (ibuf->dds_data.fourcc == FOURCC_DXT1) @@ -896,7 +901,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h) { ImBuf *ibuf; - ibuf = BKE_image_get_ibuf(ima, NULL); + ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ima->repbind || (GPU_get_mipmap() && !GTS.gpu_mipmap) || !ima->bindcode || !ibuf || (!is_power_of_2_i(ibuf->x) || !is_power_of_2_i(ibuf->y)) || @@ -935,6 +940,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h) ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; } + BKE_image_release_ibuf(ima, ibuf, NULL); return; } @@ -959,6 +965,8 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h) ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; } } + + BKE_image_release_ibuf(ima, ibuf, NULL); } void GPU_update_images_framechange(void) diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index cef664437b7..7a0ac29c9ab 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -253,6 +253,9 @@ static void GPU_print_framebuffer_error(GLenum status, char err_out[256]) switch (status) { case GL_FRAMEBUFFER_COMPLETE_EXT: break; + case GL_INVALID_OPERATION: + err= "Invalid operation"; + break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: err= "Incomplete attachment"; break; @@ -754,6 +757,7 @@ int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err { GLenum status; GLenum attachment; + GLenum error; if (tex->depth) attachment = GL_DEPTH_ATTACHMENT_EXT; @@ -766,6 +770,14 @@ int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, tex->target, tex->bindcode, 0); + error = glGetError(); + + if (error == GL_INVALID_OPERATION) { + GPU_framebuffer_restore(); + GPU_print_framebuffer_error(error, err_out); + return 0; + } + if (tex->depth) { glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index ef73764753c..9c48f74bf5f 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -1165,13 +1165,14 @@ static void do_material_tex(GPUShadeInput *shi) // resolve texture resolution if ( (mtex->texflag & MTEX_BUMP_TEXTURESPACE) || found_deriv_map ) { - ImBuf *ibuf= BKE_image_get_ibuf(tex->ima, &tex->iuser); + ImBuf *ibuf= BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); ima_x= 512.0f; ima_y= 512.f; // prevent calling textureSize, glsl 1.3 only if (ibuf) { ima_x= ibuf->x; ima_y= ibuf->y; aspect = ((float) ima_y) / ima_x; } + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } // The negate on norfac is done because the @@ -1496,6 +1497,16 @@ static GPUNodeLink *GPU_blender_material(GPUMaterial *mat, Material *ma) return shr.combined; } +static GPUNodeLink *gpu_material_diffuse_bsdf(GPUMaterial *mat, Material *ma) +{ + static float roughness = 0.0f; + GPUNodeLink *outlink; + + GPU_link(mat, "node_bsdf_diffuse", GPU_uniform(&ma->r), GPU_uniform(&roughness), GPU_builtin(GPU_VIEW_NORMAL), &outlink); + + return outlink; +} + GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma) { GPUMaterial *mat; @@ -1515,8 +1526,15 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma) ntreeGPUMaterialNodes(ma->nodetree, mat); } else { - /* create material */ - outlink = GPU_blender_material(mat, ma); + if(BKE_scene_use_new_shading_nodes(scene)) { + /* create simple diffuse material instead of nodes */ + outlink = gpu_material_diffuse_bsdf(mat, ma); + } + else { + /* create blender material */ + outlink = GPU_blender_material(mat, ma); + } + GPU_material_output_link(mat, outlink); } diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index b930058864c..9a238e979fa 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -4,6 +4,21 @@ float exp_blender(float f) return pow(2.71828182846, f); } +float compatible_pow(float x, float y) +{ + /* glsl pow doesn't accept negative x */ + if(x < 0.0) { + if(mod(-y, 2.0) == 0.0) + return pow(-x, y); + else + return -pow(-x, y); + } + else if(x == 0.0) + return 0.0; + + return pow(x, y); +} + void rgb_to_hsv(vec4 rgb, out vec4 outcol) { float cmax, cmin, h, s, v, cdelta; @@ -212,10 +227,17 @@ void math_atan(float val, out float outval) void math_pow(float val1, float val2, out float outval) { - if (val1 >= 0.0) - outval = pow(val1, val2); - else - outval = 0.0; + if (val1 >= 0.0) { + outval = compatible_pow(val1, val2); + } + else { + float val2_mod_1 = mod(abs(val2), 1.0); + + if (val2_mod_1 > 0.999 || val2_mod_1 < 0.001) + outval = compatible_pow(val1, floor(val2 + 0.5)); + else + outval = 0.0; + } } void math_log(float val1, float val2, out float outval) diff --git a/source/blender/gpu/shaders/gpu_shader_vertex.glsl b/source/blender/gpu/shaders/gpu_shader_vertex.glsl index a86431bdd7a..574455e42b3 100644 --- a/source/blender/gpu/shaders/gpu_shader_vertex.glsl +++ b/source/blender/gpu/shaders/gpu_shader_vertex.glsl @@ -10,3 +10,11 @@ void main() varnormal = normalize(gl_NormalMatrix * gl_Normal); gl_Position = gl_ProjectionMatrix * co; + // Setting gl_ClipVertex is necessary to get glClipPlane working on NVIDIA graphic cards. + // gl_ClipVertex works only on NVIDIA graphic cards so we have to check with + // __GLSL_CG_DATA_TYPES if a NVIDIA graphic card is used (Cg support). + // gl_ClipVerte is supported up to GLSL 1.20. + #ifdef __GLSL_CG_DATA_TYPES + gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; + #endif + diff --git a/source/blender/ikplugin/intern/ikplugin_api.c b/source/blender/ikplugin/intern/ikplugin_api.c index 08d2789451c..507d54d7526 100644 --- a/source/blender/ikplugin/intern/ikplugin_api.c +++ b/source/blender/ikplugin/intern/ikplugin_api.c @@ -79,12 +79,14 @@ static IKPlugin ikplugin_tab[] = { itasc_update_param, itasc_test_constraint, }, - #endif +#endif + + { NULL } }; static IKPlugin *get_plugin(bPose *pose) { - if (!pose || pose->iksolver < 0 || pose->iksolver >= (sizeof(ikplugin_tab) / sizeof(IKPlugin))) + if (!pose || pose->iksolver < 0 || pose->iksolver > (sizeof(ikplugin_tab) / sizeof(IKPlugin) - 2)) return NULL; return &ikplugin_tab[pose->iksolver]; diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c index af15333ece5..ca81f4c915a 100644 --- a/source/blender/ikplugin/intern/iksolver_plugin.c +++ b/source/blender/ikplugin/intern/iksolver_plugin.c @@ -379,6 +379,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree) copy_v3_v3(goalpos, goal[3]); copy_m3_m4(goalrot, goal); + normalize_m3(goalrot); /* same for pole vector target */ if (data->poletar) { @@ -433,7 +434,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree) iktarget = iktree[target->tip]; - if (data->weight != 0.0f) { + if ((data->flag & CONSTRAINT_IK_POS) && data->weight != 0.0f) { if (poleconstrain) IK_SolverSetPoleVectorConstraint(solver, iktarget, goalpos, polepos, data->poleangle, (poleangledata == data)); diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp index 5cf762af3e8..903080d5b79 100644 --- a/source/blender/ikplugin/intern/itasc_plugin.cpp +++ b/source/blender/ikplugin/intern/itasc_plugin.cpp @@ -1636,7 +1636,7 @@ static void execute_scene(Scene *blscene, IK_Scene *ikscene, bItasc *ikparam, fl // compute constraint error for (i = ikscene->targets.size(); i > 0; --i) { IK_Target *iktarget = ikscene->targets[i - 1]; - if (!(iktarget->blenderConstraint->flag & CONSTRAINT_OFF)) { + if (!(iktarget->blenderConstraint->flag & CONSTRAINT_OFF) && iktarget->constraint) { unsigned int nvalues; const iTaSC::ConstraintValues *values; values = iktarget->constraint->getControlParameters(&nvalues); diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index 5b64416c309..8dfdbd4fddc 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -821,6 +821,14 @@ static int ffmpeg_decode_video_frame(struct anim *anim) } if (rval == AVERROR_EOF) { + /* this sets size and data fields to zero, + which is necessary to decode the remaining data + in the decoder engine after EOF. It also prevents a memory + leak, since av_read_frame spills out a full size packet even + on EOF... (and: it's save to call on NULL packets) */ + + av_free_packet(&anim->next_packet); + anim->next_packet.size = 0; anim->next_packet.data = 0; diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c index d20c6dec9d3..c8bc3f8ebb8 100644 --- a/source/blender/imbuf/intern/cineon/cineon_dpx.c +++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c @@ -139,9 +139,19 @@ static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon if (ibuf->rect_float != 0 && bitspersample != 8) { /* don't use the float buffer to save 8 bpp picture to prevent color banding (there's no dithering algorithm behing the logImageSetDataRGBA function) */ - IMB_flipy(ibuf); - rvalue = (logImageSetDataRGBA(logImage, ibuf->rect_float, 1) == 0); - IMB_flipy(ibuf); + + fbuf = (float *)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), "fbuf in imb_save_dpx_cineon"); + + for (y = 0; y < ibuf->y; y++) { + float *dst_ptr = fbuf + 4 * ((ibuf->y - y - 1) * ibuf->x); + float *src_ptr = ibuf->rect_float + 4 * (y * ibuf->x); + + memcpy(dst_ptr, src_ptr, 4 * ibuf->x * sizeof(float)); + } + + rvalue = (logImageSetDataRGBA(logImage, fbuf, 1) == 0); + + MEM_freeN(fbuf); } else { if (ibuf->rect == 0) diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c index 9926d8c8562..3049a5be514 100644 --- a/source/blender/imbuf/intern/cineon/cineonlib.c +++ b/source/blender/imbuf/intern/cineon/cineonlib.c @@ -188,7 +188,7 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t } else { if (verbose) printf("Cineon: Bad magic number %lu in \"%s\".\n", - (uintptr_t)header.fileHeader.magic_num, byteStuff); + (unsigned long)header.fileHeader.magic_num, byteStuff); logImageClose(cineon); return 0; } diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c index aedce52a7bf..4c9b5e620dd 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.c +++ b/source/blender/imbuf/intern/cineon/dpxlib.c @@ -457,7 +457,7 @@ LogImageFile *dpxCreate(const char *filename, int width, int height, int bitsPer } /* Header should be rounded to next 8k block - 6044 = 8092 - sizeof(DpxMainHeader) */ + * 6044 = 8092 - sizeof(DpxMainHeader) */ memset(&pad, 0, 6044); if (fwrite(&pad, 6044, 1, dpx->file) == 0) { if (verbose) printf("DPX: Couldn't write image header\n"); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 6581987aed7..1c68a466ade 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -164,7 +164,7 @@ typedef struct ColormanageProcessor { * but they holds indexes of all transformations and color spaces, not * their names. * - * This helps avoid extra colorsmace / display / view lookup without + * This helps avoid extra colorspace / display / view lookup without * requiring to pass all variables which affects on display buffer * to color management cache system and keeps calls small and nice. */ @@ -890,7 +890,7 @@ void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace) { ColorSpace *colorspace = colormanage_colorspace_get_named(from_colorspace); - if (colorspace->is_data) { + if (colorspace && colorspace->is_data) { ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; return; } @@ -1083,7 +1083,7 @@ void IMB_colormanagement_check_is_data(ImBuf *ibuf, const char *name) { ColorSpace *colorspace = colormanage_colorspace_get_named(name); - if (colorspace->is_data) + if (colorspace && colorspace->is_data) ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; else ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; @@ -1095,7 +1095,7 @@ void IMB_colormanagement_assign_float_colorspace(ImBuf *ibuf, const char *name) ibuf->float_colorspace = colorspace; - if (colorspace->is_data) + if (colorspace && colorspace->is_data) ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; else ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; @@ -1107,7 +1107,7 @@ void IMB_colormanagement_assign_rect_colorspace(ImBuf *ibuf, const char *name) ibuf->rect_colorspace = colorspace; - if (colorspace->is_data) + if (colorspace && colorspace->is_data) ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; else ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; @@ -2385,7 +2385,7 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, const ColorManagedDisplaySettings *display_settings, int xmin, int ymin, int xmax, int ymax, int update_orig_byte_buffer) { - if ((ibuf->rect && ibuf->rect_float) || update_orig_byte_buffer) { + if ((ibuf->rect && ibuf->rect_float) || update_orig_byte_buffer) { /* update byte buffer created by legacy color management */ unsigned char *rect = (unsigned char *) ibuf->rect; @@ -2465,7 +2465,8 @@ ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManag } display_space = display_transform_get_colorspace(applied_view_settings, display_settings); - cm_processor->is_data_result = display_space->is_data; + if (display_space) + 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); diff --git a/source/blender/imbuf/intern/dds/BlockDXT.h b/source/blender/imbuf/intern/dds/BlockDXT.h index 9b90b744b67..7e5a1e504b8 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.h +++ b/source/blender/imbuf/intern/dds/BlockDXT.h @@ -147,7 +147,7 @@ struct BlockDXT3 struct AlphaBlockDXT5 { // uint64 unions do not compile on all platforms - /* +#if 0 union { struct { uint64 alpha0 : 8; // 8 @@ -171,26 +171,26 @@ struct AlphaBlockDXT5 }; uint64 u; }; - */ +#endif uint64 u; - uint8 alpha0() const { return u & 0xffLL; }; - uint8 alpha1() const { return (u >> 8) & 0xffLL; }; - uint8 bits0() const { return (u >> 16) & 0x7LL; }; - uint8 bits1() const { return (u >> 19) & 0x7LL; }; - uint8 bits2() const { return (u >> 22) & 0x7LL; }; - uint8 bits3() const { return (u >> 25) & 0x7LL; }; - uint8 bits4() const { return (u >> 28) & 0x7LL; }; - uint8 bits5() const { return (u >> 31) & 0x7LL; }; - uint8 bits6() const { return (u >> 34) & 0x7LL; }; - uint8 bits7() const { return (u >> 37) & 0x7LL; }; - uint8 bits8() const { return (u >> 40) & 0x7LL; }; - uint8 bits9() const { return (u >> 43) & 0x7LL; }; - uint8 bitsA() const { return (u >> 46) & 0x7LL; }; - uint8 bitsB() const { return (u >> 49) & 0x7LL; }; - uint8 bitsC() const { return (u >> 52) & 0x7LL; }; - uint8 bitsD() const { return (u >> 55) & 0x7LL; }; - uint8 bitsE() const { return (u >> 58) & 0x7LL; }; - uint8 bitsF() const { return (u >> 61) & 0x7LL; }; + uint8 alpha0() const { return u & 0xffLL; } + uint8 alpha1() const { return (u >> 8) & 0xffLL; } + uint8 bits0() const { return (u >> 16) & 0x7LL; } + uint8 bits1() const { return (u >> 19) & 0x7LL; } + uint8 bits2() const { return (u >> 22) & 0x7LL; } + uint8 bits3() const { return (u >> 25) & 0x7LL; } + uint8 bits4() const { return (u >> 28) & 0x7LL; } + uint8 bits5() const { return (u >> 31) & 0x7LL; } + uint8 bits6() const { return (u >> 34) & 0x7LL; } + uint8 bits7() const { return (u >> 37) & 0x7LL; } + uint8 bits8() const { return (u >> 40) & 0x7LL; } + uint8 bits9() const { return (u >> 43) & 0x7LL; } + uint8 bitsA() const { return (u >> 46) & 0x7LL; } + uint8 bitsB() const { return (u >> 49) & 0x7LL; } + uint8 bitsC() const { return (u >> 52) & 0x7LL; } + uint8 bitsD() const { return (u >> 55) & 0x7LL; } + uint8 bitsE() const { return (u >> 58) & 0x7LL; } + uint8 bitsF() const { return (u >> 61) & 0x7LL; } void evaluatePalette(uint8 alpha[8]) const; void evaluatePalette8(uint8 alpha[8]) const; diff --git a/source/blender/imbuf/intern/dds/FlipDXT.cpp b/source/blender/imbuf/intern/dds/FlipDXT.cpp index ee7a0ebb2f7..05821b27ca6 100644 --- a/source/blender/imbuf/intern/dds/FlipDXT.cpp +++ b/source/blender/imbuf/intern/dds/FlipDXT.cpp @@ -140,10 +140,10 @@ static void FlipDXT5BlockFull(uint8_t *block) unsigned int line_2_3 = block[5] + 256 * (block[6] + 256 * block[7]); // swap lines 0 and 1 in line_0_1. unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) | - ((line_0_1 & 0xfff000) >> 12); + ((line_0_1 & 0xfff000) >> 12); // swap lines 2 and 3 in line_2_3. unsigned int line_3_2 = ((line_2_3 & 0x000fff) << 12) | - ((line_2_3 & 0xfff000) >> 12); + ((line_2_3 & 0xfff000) >> 12); block[2] = line_3_2 & 0xff; block[3] = (line_3_2 & 0xff00) >> 8; @@ -162,7 +162,7 @@ static void FlipDXT5BlockHalf(uint8_t *block) // See layout above. unsigned int line_0_1 = block[2] + 256 * (block[3] + 256 * block[4]); unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) | - ((line_0_1 & 0xfff000) >> 12); + ((line_0_1 & 0xfff000) >> 12); block[2] = line_1_0 & 0xff; block[3] = (line_1_0 & 0xff00) >> 8; block[4] = (line_1_0 & 0xff0000) >> 8; diff --git a/source/blender/imbuf/intern/dds/SConscript b/source/blender/imbuf/intern/dds/SConscript index d5a613f5981..475d21135aa 100644 --- a/source/blender/imbuf/intern/dds/SConscript +++ b/source/blender/imbuf/intern/dds/SConscript @@ -3,16 +3,17 @@ Import ('env') source_files = ['dds_api.cpp', 'DirectDrawSurface.cpp', 'Stream.cpp', 'BlockDXT.cpp', 'ColorBlock.cpp', 'Image.cpp', 'FlipDXT.cpp'] -incs = ['.', - '../../', - '../..', +incs = [ + '.', '..', + '../..', '../../../makesdna', '../../../blenkernel', '../../../blenlib', 'intern/include', '#/intern/guardedalloc', - '#/intern/utfconv'] + '#/intern/utfconv' + ] defs = ['WITH_DDS'] diff --git a/source/blender/imbuf/intern/dds/Stream.h b/source/blender/imbuf/intern/dds/Stream.h index 7fed4ca89e7..a1ac49b58da 100644 --- a/source/blender/imbuf/intern/dds/Stream.h +++ b/source/blender/imbuf/intern/dds/Stream.h @@ -35,7 +35,7 @@ struct Stream unsigned char *mem; // location in memory unsigned int size; // size unsigned int pos; // current position - Stream(unsigned char *m, unsigned int s) : mem(m), size(s), pos(0) {}; + Stream(unsigned char *m, unsigned int s) : mem(m), size(s), pos(0) {} unsigned int seek(unsigned int p); }; diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 55c1b02e90b..f049c404e2d 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -196,7 +196,7 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, { float tmp[4]; int x, y; - DitherContext *di; + DitherContext *di = NULL; /* we need valid profiles */ BLI_assert(profile_to != IB_PROFILE_NONE); @@ -583,23 +583,23 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w if (is_data) { /* exception for non-color data, just copy float */ IMB_buffer_float_from_float(buffer, rect_float, - ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, 0, - w, h, w, ibuf->x); + ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, 0, + w, h, w, ibuf->x); /* and do color space conversion to byte */ IMB_buffer_byte_from_float(rect_byte, rect_float, - 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide, - w, h, ibuf->x, w); + 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide, + w, h, ibuf->x, w); } else { IMB_buffer_float_from_float(buffer, rect_float, - ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide, - w, h, w, ibuf->x); + ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide, + w, h, w, ibuf->x); /* XXX: need to convert to image buffer's rect space */ IMB_buffer_byte_from_float(rect_byte, buffer, - 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0, - w, h, ibuf->x, w); + 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0, + w, h, ibuf->x, w); } /* ensure user flag is reset */ diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c index 57fbce710a1..a185c4ee3e0 100644 --- a/source/blender/imbuf/intern/imageprocess.c +++ b/source/blender/imbuf/intern/imageprocess.c @@ -43,6 +43,7 @@ #include "BLI_utildefines.h" #include "BLI_threads.h" #include "BLI_listbase.h" +#include "BLI_math.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -95,132 +96,15 @@ static void pixel_from_buffer(struct ImBuf *ibuf, unsigned char **outI, float ** *outF = ibuf->rect_float + offset; } -/************************************************************************** - * INTERPOLATIONS - * - * Reference and docs: - * http://wiki.blender.org/index.php/User:Damiles#Interpolations_Algorithms - ***************************************************************************/ - -/* BICUBIC Interpolation functions - * More info: http://wiki.blender.org/index.php/User:Damiles#Bicubic_pixel_interpolation - * function assumes out to be zero'ed, only does RGBA */ - -static float P(float k) -{ - float p1, p2, p3, p4; - p1 = MAX2(k + 2.0f, 0); - p2 = MAX2(k + 1.0f, 0); - p3 = MAX2(k, 0); - p4 = MAX2(k - 1.0f, 0); - return (float)(1.0f / 6.0f) * (p1 * p1 * p1 - 4.0f * p2 * p2 * p2 + 6.0f * p3 * p3 * p3 - 4.0f * p4 * p4 * p4); -} - - -#if 0 -/* older, slower function, works the same as above */ -static float P(float k) -{ - return (float)(1.0f / 6.0f) * (pow(MAX2(k + 2.0f, 0), 3.0f) - 4.0f * pow(MAX2(k + 1.0f, 0), 3.0f) + 6.0f * pow(MAX2(k, 0), 3.0f) - 4.0f * pow(MAX2(k - 1.0f, 0), 3.0f)); -} -#endif +/* BICUBIC Interpolation */ void bicubic_interpolation_color(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) { - int i, j, n, m, x1, y1; - unsigned char *dataI; - float a, b, w, wx, wy[4], outR, outG, outB, outA, *dataF; - - /* sample area entirely outside image? */ - if (ceil(u) < 0 || floor(u) > in->x - 1 || ceil(v) < 0 || floor(v) > in->y - 1) { - return; - } - - /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ - - i = (int)floor(u); - j = (int)floor(v); - a = u - i; - b = v - j; - - outR = outG = outB = outA = 0.0f; - -/* Optimized and not so easy to read */ - - /* avoid calling multiple times */ - wy[0] = P(b - (-1)); - wy[1] = P(b - 0); - wy[2] = P(b - 1); - wy[3] = P(b - 2); - - for (n = -1; n <= 2; n++) { - x1 = i + n; - CLAMP(x1, 0, in->x - 1); - wx = P(n - a); - for (m = -1; m <= 2; m++) { - y1 = j + m; - CLAMP(y1, 0, in->y - 1); - /* normally we could do this */ - /* w = P(n-a) * P(b-m); */ - /* except that would call P() 16 times per pixel therefor pow() 64 times, better precalc these */ - w = wx * wy[m + 1]; - - if (outF) { - dataF = in->rect_float + in->x * y1 * 4 + 4 * x1; - outR += dataF[0] * w; - outG += dataF[1] * w; - outB += dataF[2] * w; - outA += dataF[3] * w; - } - if (outI) { - dataI = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x1; - outR += dataI[0] * w; - outG += dataI[1] * w; - outB += dataI[2] * w; - outA += dataI[3] * w; - } - } - } - -/* Done with optimized part */ - -#if 0 - /* older, slower function, works the same as above */ - for (n = -1; n <= 2; n++) { - for (m = -1; m <= 2; m++) { - x1 = i + n; - y1 = j + m; - if (x1 > 0 && x1 < in->x && y1 > 0 && y1 < in->y) { - if (do_float) { - dataF = in->rect_float + in->x * y1 * 4 + 4 * x1; - outR += dataF[0] * P(n - a) * P(b - m); - outG += dataF[1] * P(n - a) * P(b - m); - outB += dataF[2] * P(n - a) * P(b - m); - outA += dataF[3] * P(n - a) * P(b - m); - } - if (do_rect) { - dataI = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x1; - outR += dataI[0] * P(n - a) * P(b - m); - outG += dataI[1] * P(n - a) * P(b - m); - outB += dataI[2] * P(n - a) * P(b - m); - outA += dataI[3] * P(n - a) * P(b - m); - } - } - } - } -#endif - - if (outI) { - outI[0] = (int)outR; - outI[1] = (int)outG; - outI[2] = (int)outB; - outI[3] = (int)outA; - } if (outF) { - outF[0] = outR; - outF[1] = outG; - outF[2] = outB; - outF[3] = outA; + BLI_bicubic_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v); + } + else { + BLI_bicubic_interpolation_char((unsigned char*) in->rect, outI, in->x, in->y, 4, u, v); } } @@ -239,77 +123,14 @@ void bicubic_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, in bicubic_interpolation_color(in, outI, outF, u, v); } -/* function assumes out to be zero'ed, only does RGBA */ /* BILINEAR INTERPOLATION */ void bilinear_interpolation_color(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) { - float *row1, *row2, *row3, *row4, a, b; - unsigned char *row1I, *row2I, *row3I, *row4I; - float a_b, ma_b, a_mb, ma_mb; - float empty[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - unsigned char emptyI[4] = {0, 0, 0, 0}; - int y1, y2, x1, x2; - - - /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ - - x1 = (int)floor(u); - x2 = (int)ceil(u); - y1 = (int)floor(v); - y2 = (int)ceil(v); - - /* sample area entirely outside image? */ - if (x2 < 0 || x1 > in->x - 1 || y2 < 0 || y1 > in->y - 1) { - return; - } - if (outF) { - /* sample including outside of edges of image */ - if (x1 < 0 || y1 < 0) row1 = empty; - else row1 = in->rect_float + in->x * y1 * 4 + 4 * x1; - - if (x1 < 0 || y2 > in->y - 1) row2 = empty; - else row2 = in->rect_float + in->x * y2 * 4 + 4 * x1; - - if (x2 > in->x - 1 || y1 < 0) row3 = empty; - else row3 = in->rect_float + in->x * y1 * 4 + 4 * x2; - - if (x2 > in->x - 1 || y2 > in->y - 1) row4 = empty; - else row4 = in->rect_float + in->x * y2 * 4 + 4 * x2; - - a = u - floorf(u); - b = v - floorf(v); - a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); - - outF[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; - outF[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; - outF[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; - outF[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; + BLI_bilinear_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v); } - if (outI) { - /* sample including outside of edges of image */ - if (x1 < 0 || y1 < 0) row1I = emptyI; - else row1I = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x1; - - if (x1 < 0 || y2 > in->y - 1) row2I = emptyI; - else row2I = (unsigned char *)in->rect + in->x * y2 * 4 + 4 * x1; - - if (x2 > in->x - 1 || y1 < 0) row3I = emptyI; - else row3I = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x2; - - if (x2 > in->x - 1 || y2 > in->y - 1) row4I = emptyI; - else row4I = (unsigned char *)in->rect + in->x * y2 * 4 + 4 * x2; - - a = u - floorf(u); - b = v - floorf(v); - a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); - - /* need to add 0.5 to avoid rounding down (causes darken with the smear brush) - * tested with white images and this should not wrap back to zero */ - outI[0] = (ma_mb * row1I[0] + a_mb * row3I[0] + ma_b * row2I[0] + a_b * row4I[0]) + 0.5f; - outI[1] = (ma_mb * row1I[1] + a_mb * row3I[1] + ma_b * row2I[1] + a_b * row4I[1]) + 0.5f; - outI[2] = (ma_mb * row1I[2] + a_mb * row3I[2] + ma_b * row2I[2] + a_b * row4I[2]) + 0.5f; - outI[3] = (ma_mb * row1I[3] + a_mb * row3I[3] + ma_b * row2I[3] + a_b * row4I[3]) + 0.5f; + else { + BLI_bilinear_interpolation_char((unsigned char*) in->rect, outI, in->x, in->y, 4, u, v); } } diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index 5dda33dfd62..277f50bcdbc 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -872,7 +872,7 @@ static void index_rebuild_ffmpeg_proc_decoded_frame( context->frameno = floor((pts - context->start_pts) * context->pts_time_base * - context->frame_rate + 0.5f); + context->frame_rate + 0.5); /* decoding starts *always* on I-Frames, * so: P-Frames won't work, even if all the @@ -912,6 +912,8 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context, AVPacket next_packet; uint64_t stream_size; + memset(&next_packet, 0, sizeof(AVPacket)); + in_frame = avcodec_alloc_frame(); stream_size = avio_size(context->iFormatCtx->pb); @@ -959,12 +961,13 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context, * according to ffmpeg docs using 0-size packets. * * At least, if we haven't already stopped... */ + + /* this creates the 0-size packet and prevents a memory leak. */ + av_free_packet(&next_packet); + if (!*stop) { int frame_finished; - next_packet.size = 0; - next_packet.data = 0; - do { frame_finished = 0; diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c index 692ba3c49ea..3a2bf99c75c 100644 --- a/source/blender/imbuf/intern/jp2.c +++ b/source/blender/imbuf/intern/jp2.c @@ -41,7 +41,7 @@ #include "openjpeg.h" -#define JP2_FILEHEADER_SIZE 14 +// #define JP2_FILEHEADER_SIZE 14 /* UNUSED */ static char JP2_HEAD[] = {0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A}; static char J2K_HEAD[] = {0xFF, 0x4F, 0xFF, 0x51, 0x00}; @@ -387,8 +387,8 @@ BLI_INLINE int DOWNSAMPLE_FLOAT_TO_16BIT(const float _val) /* * 2048x1080 (2K) at 24 fps or 48 fps, or 4096x2160 (4K) at 24 fps; 3x12 bits per pixel, XYZ color space * - * - In 2K, for Scope (2.39:1) presentation 2048x858 pixels of the imager is used - * - In 2K, for Flat (1.85:1) presentation 1998x1080 pixels of the imager is used + * - In 2K, for Scope (2.39:1) presentation 2048x858 pixels of the image is used + * - In 2K, for Flat (1.85:1) presentation 1998x1080 pixels of the image is used */ /* ****************************** COPIED FROM image_to_j2k.c */ diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c index 61275a8937c..758617bdd48 100644 --- a/source/blender/imbuf/intern/jpeg.c +++ b/source/blender/imbuf/intern/jpeg.c @@ -235,19 +235,19 @@ static void memory_source(j_decompress_ptr cinfo, unsigned char *buffer, size_t */ #define INPUT_BYTE(cinfo, V, action) \ MAKESTMT(MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V = GETJOCTET(*next_input_byte++); ) + bytes_in_buffer--; \ + V = GETJOCTET(*next_input_byte++); ) /* As above, but read two bytes interpreted as an unsigned 16-bit integer. * V should be declared unsigned int or perhaps INT32. */ #define INPUT_2BYTES(cinfo, V, action) \ MAKESTMT(MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ - MAKE_BYTE_AVAIL(cinfo, action); \ - bytes_in_buffer--; \ - V += GETJOCTET(*next_input_byte++); ) + bytes_in_buffer--; \ + V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ + MAKE_BYTE_AVAIL(cinfo, action); \ + bytes_in_buffer--; \ + V += GETJOCTET(*next_input_byte++); ) static boolean @@ -348,25 +348,12 @@ static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int fla g = *buffer++; b = *buffer++; k = *buffer++; - - k = 255 - k; - r -= k; - if (r & 0xffffff00) { - if (r < 0) r = 0; - else r = 255; - } - g -= k; - if (g & 0xffffff00) { - if (g < 0) g = 0; - else g = 255; - } - b -= k; - if (b & 0xffffff00) { - if (b < 0) b = 0; - else b = 255; - } - - rect[3] = 255 - k; + + r = (r * k) / 255; + g = (g * k) / 255; + b = (b * k) / 255; + + rect[3] = 255; rect[2] = b; rect[1] = g; rect[0] = r; diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 60c6e184070..da7b31cc2ba 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -72,21 +72,6 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void) #include -#if defined(_WIN32) && !defined(FREE_WINDOWS) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#else #include #include #include @@ -100,7 +85,6 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void) #include #include #include -#endif using namespace Imf; using namespace Imath; @@ -881,7 +865,7 @@ void IMB_exr_close(void *handle) /* get a substring from the end of the name, separated by '.' */ static int imb_exr_split_token(const char *str, const char *end, const char **token) { - int maxlen = end - str; + ptrdiff_t maxlen = end - str; int len = 0; while (len < maxlen && *(end - len - 1) != '.') { len++; @@ -1183,7 +1167,7 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char frameBuffer.insert(exr_rgba_channelname(file, "B"), Slice(Imf::FLOAT, (char *) (first + 2), xstride, ystride)); - /* 1.0 is fill value, this still neesd to be assigned even when (is_alpha == 0) */ + /* 1.0 is fill value, this still needs to be assigned even when (is_alpha == 0) */ frameBuffer.insert(exr_rgba_channelname(file, "A"), Slice(Imf::FLOAT, (char *) (first + 3), xstride, ystride, 1, 1, 1.0f)); diff --git a/source/blender/imbuf/intern/openexr/openexr_multi.h b/source/blender/imbuf/intern/openexr/openexr_multi.h index 78071975c72..376d2401b1c 100644 --- a/source/blender/imbuf/intern/openexr/openexr_multi.h +++ b/source/blender/imbuf/intern/openexr/openexr_multi.h @@ -35,10 +35,10 @@ /* experiment with more advanced exr api */ -/* Note: as for now openexr only supports 32 chars in channel names. - * This api also supports max 8 channels per pass now. easy to fix! */ -#define EXR_LAY_MAXNAME 51 -#define EXR_PASS_MAXNAME 11 +/* XXX layer+pass name max 64? */ +/* This api also supports max 8 channels per pass now. easy to fix! */ +#define EXR_LAY_MAXNAME 64 +#define EXR_PASS_MAXNAME 64 #define EXR_TOT_MAXNAME 64 #define EXR_PASS_MAXCHAN 8 diff --git a/source/blender/imbuf/intern/openexr/openexr_stub.cpp b/source/blender/imbuf/intern/openexr/openexr_stub.cpp index 7262656d4e8..21fa878c08a 100644 --- a/source/blender/imbuf/intern/openexr/openexr_stub.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_stub.cpp @@ -33,25 +33,25 @@ #include "openexr_multi.h" -void * IMB_exr_get_handle (void) {return NULL;} -void IMB_exr_add_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } +void *IMB_exr_get_handle (void) {return NULL;} +void IMB_exr_add_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } -int IMB_exr_begin_read (void *handle, const char *filename, int *width, int *height) { (void)handle; (void)filename; (void)width; (void)height; return 0;} -int IMB_exr_begin_write (void *handle, const char *filename, int width, int height, int compress) { (void)handle; (void)filename; (void)width; (void)height; (void)compress; return 0;} -void IMB_exrtile_begin_write (void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley) { (void)handle; (void)filename; (void)mipmap; (void)width; (void)height; (void)tilex; (void)tiley; } +int IMB_exr_begin_read (void *handle, const char *filename, int *width, int *height) { (void)handle; (void)filename; (void)width; (void)height; return 0;} +int IMB_exr_begin_write (void *handle, const char *filename, int width, int height, int compress) { (void)handle; (void)filename; (void)width; (void)height; (void)compress; return 0;} +void IMB_exrtile_begin_write (void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley) { (void)handle; (void)filename; (void)mipmap; (void)width; (void)height; (void)tilex; (void)tiley; } -void IMB_exr_set_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } +void IMB_exr_set_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } -void IMB_exr_read_channels (void *handle) { (void)handle; } -void IMB_exr_write_channels (void *handle) { (void)handle; } -void IMB_exrtile_write_channels (void *handle, int partx, int party, int level) { (void)handle; (void)partx; (void)party; (void)level; } -void IMB_exrtile_clear_channels (void *handle) { (void)handle; } +void IMB_exr_read_channels (void *handle) { (void)handle; } +void IMB_exr_write_channels (void *handle) { (void)handle; } +void IMB_exrtile_write_channels (void *handle, int partx, int party, int level) { (void)handle; (void)partx; (void)party; (void)level; } +void IMB_exrtile_clear_channels (void *handle) { (void)handle; } -void IMB_exr_multilayer_convert (void *handle, void *base, - void * (*addlayer)(void *base, const char *str), - void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id)) - { - (void)handle; (void)base; (void)addlayer; (void)addpass; - } +void IMB_exr_multilayer_convert (void *handle, void *base, + void * (*addlayer)(void *base, const char *str), + void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id)) +{ + (void)handle; (void)base; (void)addlayer; (void)addpass; +} -void IMB_exr_close (void *handle) { (void)handle; } +void IMB_exr_close (void *handle) { (void)handle; } diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c index 72cec0e3749..03ed1bb8008 100644 --- a/source/blender/imbuf/intern/radiance_hdr.c +++ b/source/blender/imbuf/intern/radiance_hdr.c @@ -65,7 +65,6 @@ #define BLU 2 #define EXP 3 #define COLXS 128 -#define STR_MAX 540 typedef unsigned char RGBE[4]; typedef float fCOLOR[3]; diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index 5669a4cc45d..be20c80bdec 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -176,7 +176,7 @@ ImBuf *IMB_testiffname(const char *filepath, int flags) ImBuf *ibuf; int file; char filepath_tx[IB_FILENAME_SIZE]; - char colorspace[IM_MAX_SPACE]; + char colorspace[IM_MAX_SPACE] = "\0"; imb_cache_filename(filepath_tx, filepath, flags); diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c index 8e072361583..d2b0645cf93 100644 --- a/source/blender/imbuf/intern/rectop.c +++ b/source/blender/imbuf/intern/rectop.c @@ -587,7 +587,7 @@ void IMB_rectfill_area(struct ImBuf *ibuf, const float col[4], int x1, int y1, i { if (!ibuf) return; buf_rectfill_area((unsigned char *) ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, col, display, - x1, y1, x2, y2); + x1, y1, x2, y2); } diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c index 527f334d6a4..1e701b8d615 100644 --- a/source/blender/imbuf/intern/scaling.c +++ b/source/blender/imbuf/intern/scaling.c @@ -331,13 +331,13 @@ void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1) for (y = ibuf2->y; y > 0; y--) { p2f = p1f + (ibuf1->x << 2); for (x = ibuf2->x; x > 0; x--) { - destf[0] = 0.25f * (p1f[0] + p2f[0] + p1f[4] + p2f[4]); - destf[1] = 0.25f * (p1f[1] + p2f[1] + p1f[5] + p2f[5]); - destf[2] = 0.25f * (p1f[2] + p2f[2] + p1f[6] + p2f[6]); - destf[3] = 0.25f * (p1f[3] + p2f[3] + p1f[7] + p2f[7]); - p1f += 8; - p2f += 8; - destf += 4; + destf[0] = 0.25f * (p1f[0] + p2f[0] + p1f[4] + p2f[4]); + destf[1] = 0.25f * (p1f[1] + p2f[1] + p1f[5] + p2f[5]); + destf[2] = 0.25f * (p1f[2] + p2f[2] + p1f[6] + p2f[6]); + destf[3] = 0.25f * (p1f[3] + p2f[3] + p1f[7] + p2f[7]); + p1f += 8; + p2f += 8; + destf += 4; } p1f = p2f; if (ibuf1->x & 1) p1f += 4; @@ -1467,10 +1467,10 @@ struct ImBuf *IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int return ibuf; } - if (newx < ibuf->x) if (newx) scaledownx(ibuf, newx); - if (newy < ibuf->y) if (newy) scaledowny(ibuf, newy); - if (newx > ibuf->x) if (newx) scaleupx(ibuf, newx); - if (newy > ibuf->y) if (newy) scaleupy(ibuf, newy); + if (newx && (newx < ibuf->x)) scaledownx(ibuf, newx); + if (newy && (newy < ibuf->y)) scaledowny(ibuf, newy); + if (newx && (newx > ibuf->x)) scaleupx(ibuf, newx); + if (newy && (newy > ibuf->y)) scaleupy(ibuf, newy); return(ibuf); } diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index fe138a71a4a..42fb0c79b62 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -228,16 +228,27 @@ static int isqtime(const char *name) #ifdef WITH_FFMPEG +#ifdef _MSC_VER +#define va_copy(dst, src) ((dst) = (src)) +#endif + /* BLI_vsnprintf in ffmpeg_log_callback() causes invalid warning */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmissing-format-attribute" +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmissing-format-attribute" +#endif static char ffmpeg_last_error[1024]; static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_list arg) { if (ELEM(level, AV_LOG_FATAL, AV_LOG_ERROR)) { - size_t n = BLI_vsnprintf(ffmpeg_last_error, sizeof(ffmpeg_last_error), format, arg); + size_t n; + va_list arg2; + + va_copy(arg2, arg); + + n = BLI_vsnprintf(ffmpeg_last_error, sizeof(ffmpeg_last_error), format, arg2); /* strip trailing \n */ ffmpeg_last_error[n - 1] = '\0'; @@ -249,7 +260,9 @@ static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_lis } } -#pragma GCC diagnostic pop +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif void IMB_ffmpeg_init(void) { diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index d8d1ad78451..f227af78dab 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -372,7 +372,7 @@ typedef enum ePose_Flags { /* bPose->iksolver and bPose->ikparam->iksolver */ typedef enum ePose_IKSolverType { - IKSOLVER_LEGACY = 0, + IKSOLVER_STANDARD = 0, IKSOLVER_ITASC = 1 } ePose_IKSolverType; diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 3cf84648ea6..deb9902c35d 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -201,8 +201,8 @@ typedef struct Curve { float twist_smooth, smallcaps_scale; int pathlen; - short pad, totcol; - short flag, bevresol; + short bevresol, totcol; + int flag; float width, ext1, ext2; /* default */ @@ -269,6 +269,7 @@ typedef struct Curve { #define CU_PATH_RADIUS 4096 /* make use of the path radius if this is enabled (default for new curves) */ #define CU_DEFORM_FILL 8192 /* fill 2d curve after deformation */ #define CU_FILL_CAPS 16384 /* fill bevel caps */ +#define CU_MAP_TAPER 32768 /* map taper object to bevelled area */ /* twist mode */ #define CU_TWIST_Z_UP 0 diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 100968e7257..b64fc08a47a 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -41,6 +41,7 @@ typedef struct bGPDspoint { float x, y, z; /* co-ordinates of point (usually 2d, but can be 3d as well) */ float pressure; /* pressure of input device (from 0 to 1) at this point */ + float time; /* seconds since start of stroke */ } bGPDspoint; /* Grease-Pencil Annotations - 'Stroke' @@ -49,12 +50,14 @@ typedef struct bGPDspoint { */ typedef struct bGPDstroke { struct bGPDstroke *next, *prev; - bGPDspoint *points; /* array of data-points for stroke */ + void *pad; /* keep 4 pointers at the beginning, padding for 'inittime' is tricky 64/32bit */ int totpoints; /* number of data-points in array */ short thickness; /* thickness of stroke (currently not used) */ short flag; /* various settings about this stroke */ + + double inittime; /* Init time of stroke */ } bGPDstroke; /* bGPDstroke->flag */ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index c9e929ce41b..3875a0d5799 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -76,6 +76,7 @@ typedef enum ModifierType { eModifierType_Remesh = 41, eModifierType_Skin = 42, eModifierType_LaplacianSmooth = 43, + eModifierType_Triangulate = 44, NUM_MODIFIER_TYPES } ModifierType; @@ -665,7 +666,8 @@ typedef struct ShrinkwrapModifierData { float keepDist; /* distance offset to keep from mesh/projection point */ short shrinkType; /* shrink type projection */ short shrinkOpts; /* shrink options */ - char projAxis; /* axis to project over */ + float projLimit; /* limit the projection ray cast */ + char projAxis; /* axis to project over */ /* * if using projection over vertex normal this controls the @@ -674,7 +676,7 @@ typedef struct ShrinkwrapModifierData { */ char subsurfLevels; - char pad[6]; + char pad[2]; } ShrinkwrapModifierData; @@ -1113,11 +1115,23 @@ enum { MOD_SKIN_SMOOTH_SHADING = 1 }; +/* Triangulate modifier */ + +typedef struct TriangulateModifierData { + ModifierData modifier; + int flag; + int pad; +} TriangulateModifierData; + +enum { + MOD_TRIANGULATE_BEAUTY = (1 << 0), +}; + /* Smooth modifier flags */ #define MOD_LAPLACIANSMOOTH_X (1<<1) #define MOD_LAPLACIANSMOOTH_Y (1<<2) #define MOD_LAPLACIANSMOOTH_Z (1<<3) -#define MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION (1<<4) +#define MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME (1 << 4) typedef struct LaplacianSmoothModifierData { ModifierData modifier; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index c73ba87754f..a05ff66e683 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -118,7 +118,8 @@ typedef struct bNodeSocket { #define SOCK_BOOLEAN 4 #define SOCK_MESH 5 #define SOCK_INT 6 -#define NUM_SOCKET_TYPES 7 /* must be last! */ +#define SOCK_STRING 7 +#define NUM_SOCKET_TYPES 8 /* must be last! */ /* socket side (input/output) */ #define SOCK_IN 1 @@ -293,7 +294,8 @@ typedef struct bNodeTree { void (*progress)(void *, float progress); void (*stats_draw)(void *, char *str); int (*test_break)(void *); - void *tbh, *prh, *sdh; + void (*update_draw)(void *); + void *tbh, *prh, *sdh, *udh; } bNodeTree; @@ -353,6 +355,11 @@ typedef struct bNodeSocketValueRGBA { float value[4]; } bNodeSocketValueRGBA; +typedef struct bNodeSocketValueString { + int subtype; + int pad; + char value[1024]; /* 1024 = FILEMAX */ +} bNodeSocketValueString; /* data structs, for node->storage */ enum { @@ -716,6 +723,17 @@ typedef struct NodeShaderScript { IDProperty *prop; } NodeShaderScript; +typedef struct NodeShaderTangent { + int direction_type; + int axis; + char uv_map[64]; +} NodeShaderTangent; + +typedef struct NodeShaderNormalMap { + int space; + char uv_map[64]; +} NodeShaderNormalMap; + /* script node mode */ #define NODE_SCRIPT_INTERNAL 0 #define NODE_SCRIPT_EXTERNAL 1 @@ -800,6 +818,20 @@ typedef struct NodeShaderScript { #define SHD_PROJ_FLAT 0 #define SHD_PROJ_BOX 1 +/* tangent */ +#define SHD_TANGENT_RADIAL 0 +#define SHD_TANGENT_UVMAP 1 + +/* tangent */ +#define SHD_TANGENT_AXIS_X 0 +#define SHD_TANGENT_AXIS_Y 1 +#define SHD_TANGENT_AXIS_Z 2 + +/* normal map space */ +#define SHD_NORMAL_MAP_TANGENT 0 +#define SHD_NORMAL_MAP_OBJECT 1 +#define SHD_NORMAL_MAP_WORLD 2 + /* blur node */ #define CMP_NODE_BLUR_ASPECT_NONE 0 #define CMP_NODE_BLUR_ASPECT_Y 1 diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 29f6499986c..89328c33674 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -297,22 +297,19 @@ typedef struct ObHook { typedef struct DupliObject { struct DupliObject *next, *prev; struct Object *ob; - unsigned int origlay; - int index; + unsigned int origlay, pad; float mat[4][4], omat[4][4]; float orco[3], uv[2]; short type; /* from Object.transflag */ char no_draw, animated; - /* Lowest-level particle index. - * Note: This is needed for particle info in shaders. - * Otherwise dupli groups in particle systems would override the - * index value from higher dupli levels. Would be nice to have full generic access - * to all dupli levels somehow, but for now this should cover most use-cases. - */ - int particle_index; - int pad; + /* persistent identifier for a dupli object, for inter-frame matching of + * objects with motion blur, or inter-update matching for syncing */ + int persistent_id[8]; /* MAX_DUPLI_RECUR */ + + /* particle this dupli was generated from */ + struct ParticleSystem *particle_system; } DupliObject; /* **************** OBJECT ********************* */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 1479d5268ed..1599b71d832 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1009,7 +1009,7 @@ typedef struct ToolSettings { /* Transform */ char snap_mode, snap_node_mode; - char pad3; + char snap_uv_mode; short snap_flag, snap_target; short proportional, prop_mode; char proportional_objects; /* proportional edit, object mode */ @@ -1187,11 +1187,13 @@ typedef struct Scene { /* Use the same flag for autothreads */ #define R_FIXED_THREADS 0x80000 -#define R_SPEED 0x100000 -#define R_SSS 0x200000 -#define R_NO_OVERWRITE 0x400000 /* skip existing files */ -#define R_TOUCH 0x800000 /* touch files before rendering */ -#define R_SIMPLIFY 0x1000000 +#define R_SPEED 0x100000 +#define R_SSS 0x200000 +#define R_NO_OVERWRITE 0x400000 /* skip existing files */ +#define R_TOUCH 0x800000 /* touch files before rendering */ +#define R_SIMPLIFY 0x1000000 +#define R_EDGE_FRS 0x2000000 /* R_EDGE reserved for Freestyle */ +#define R_PERSISTENT_DATA 0x4000000 /* keep data around for re-render */ /* seq_flag */ #define R_SEQ_GL_PREV 1 @@ -1327,46 +1329,46 @@ typedef struct Scene { #define TESTBASE(v3d, base) ( \ ((base)->flag & SELECT) && \ ((base)->lay & v3d->lay) && \ - (((base)->object->restrictflag & OB_RESTRICT_VIEW)==0) ) + (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0)) #define TESTBASELIB(v3d, base) ( \ ((base)->flag & SELECT) && \ ((base)->lay & v3d->lay) && \ - ((base)->object->id.lib==NULL) && \ - (((base)->object->restrictflag & OB_RESTRICT_VIEW)==0) ) + ((base)->object->id.lib == NULL) && \ + (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0)) #define TESTBASELIB_BGMODE(v3d, scene, base) ( \ ((base)->flag & SELECT) && \ ((base)->lay & (v3d ? v3d->lay : scene->lay)) && \ - ((base)->object->id.lib==NULL) && \ - (((base)->object->restrictflag & OB_RESTRICT_VIEW)==0) ) + ((base)->object->id.lib == NULL) && \ + (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0)) #define BASE_EDITABLE_BGMODE(v3d, scene, base) ( \ ((base)->lay & (v3d ? v3d->lay : scene->lay)) && \ - ((base)->object->id.lib==NULL) && \ - (((base)->object->restrictflag & OB_RESTRICT_VIEW)==0)) + ((base)->object->id.lib == NULL) && \ + (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0)) #define BASE_SELECTABLE(v3d, base) ( \ (base->lay & v3d->lay) && \ - (base->object->restrictflag & (OB_RESTRICT_SELECT|OB_RESTRICT_VIEW))==0 ) + (base->object->restrictflag & (OB_RESTRICT_SELECT | OB_RESTRICT_VIEW)) == 0) #define BASE_VISIBLE(v3d, base) ( \ (base->lay & v3d->lay) && \ - (base->object->restrictflag & OB_RESTRICT_VIEW)==0 ) + (base->object->restrictflag & OB_RESTRICT_VIEW) == 0) #define FIRSTBASE scene->base.first #define LASTBASE scene->base.last #define BASACT (scene->basact) -#define OBACT (BASACT? BASACT->object: NULL) +#define OBACT (BASACT ? BASACT->object: NULL) #define V3D_CAMERA_LOCAL(v3d) ((!(v3d)->scenelock && (v3d)->camera) ? (v3d)->camera : NULL) #define V3D_CAMERA_SCENE(scene, v3d) ((!(v3d)->scenelock && (v3d)->camera) ? (v3d)->camera : (scene)->camera) -#define CFRA (scene->r.cfra) -#define SUBFRA (scene->r.subframe) -#define SFRA (scene->r.sfra) -#define EFRA (scene->r.efra) -#define PRVRANGEON (scene->r.flag & SCER_PRV_RANGE) -#define PSFRA ((PRVRANGEON) ? (scene->r.psfra) : (scene->r.sfra)) -#define PEFRA ((PRVRANGEON) ? (scene->r.pefra) : (scene->r.efra)) -#define FRA2TIME(a) ((((double) scene->r.frs_sec_base) * (double)(a)) / (double)scene->r.frs_sec) -#define TIME2FRA(a) ((((double) scene->r.frs_sec) * (double)(a)) / (double)scene->r.frs_sec_base) -#define FPS (((double) scene->r.frs_sec) / (double)scene->r.frs_sec_base) +#define CFRA (scene->r.cfra) +#define SUBFRA (scene->r.subframe) +#define SFRA (scene->r.sfra) +#define EFRA (scene->r.efra) +#define PRVRANGEON (scene->r.flag & SCER_PRV_RANGE) +#define PSFRA ((PRVRANGEON) ? (scene->r.psfra) : (scene->r.sfra)) +#define PEFRA ((PRVRANGEON) ? (scene->r.pefra) : (scene->r.efra)) +#define FRA2TIME(a) ((((double) scene->r.frs_sec_base) * (double)(a)) / (double)scene->r.frs_sec) +#define TIME2FRA(a) ((((double) scene->r.frs_sec) * (double)(a)) / (double)scene->r.frs_sec_base) +#define FPS (((double) scene->r.frs_sec) / (double)scene->r.frs_sec_base) /* base->flag is in DNA_object_types.h */ @@ -1444,9 +1446,9 @@ typedef struct Scene { /* Paint.flags */ typedef enum { - PAINT_SHOW_BRUSH = (1<<0), - PAINT_FAST_NAVIGATE = (1<<1), - PAINT_SHOW_BRUSH_ON_SURFACE = (1<<2), + PAINT_SHOW_BRUSH = (1 << 0), + PAINT_FAST_NAVIGATE = (1 << 1), + PAINT_SHOW_BRUSH_ON_SURFACE = (1 << 2), } PaintFlags; /* Sculpt.flags */ @@ -1598,4 +1600,4 @@ typedef enum SculptFlags { } #endif -#endif +#endif /* __DNA_SCENE_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_text_types.h b/source/blender/makesdna/DNA_text_types.h index cf26dae402d..6ce883905d4 100644 --- a/source/blender/makesdna/DNA_text_types.h +++ b/source/blender/makesdna/DNA_text_types.h @@ -44,15 +44,6 @@ typedef struct TextLine { int len, blen; /* blen unused */ } TextLine; -typedef struct TextMarker { - struct TextMarker *next, *prev; - - int lineno, start, end, pad1; /* line number and start/end character indices */ - - int group, flags; /* see BKE_text.h for flag defines */ - unsigned char color[4], pad[4]; /* draw color of the marker */ -} TextMarker; - typedef struct Text { ID id; @@ -63,7 +54,6 @@ typedef struct Text { ListBase lines; TextLine *curl, *sell; int curc, selc; - ListBase markers; char *undo_buf; int undo_pos, undo_len; @@ -78,7 +68,6 @@ typedef struct Text { /* text flags */ #define TXT_ISDIRTY 0x0001 -#define TXT_DEPRECATED 0x0004 /* deprecated ISTMP flag */ #define TXT_ISMEM 0x0004 #define TXT_ISEXT 0x0008 #define TXT_ISSCRIPT 0x0010 /* used by space handler scriptlinks */ diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 9c80d30bca4..12819303b26 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -163,7 +163,7 @@ typedef struct MovieTrackingSettings { /* ** reconstruction settings ** */ int keyframe1 DNA_DEPRECATED, - keyframe2 DNA_DEPRECATED; /* two keyframes for reconstrution initialization + keyframe2 DNA_DEPRECATED; /* two keyframes for reconstruction initialization * were moved to per-tracking object settings */ @@ -228,7 +228,7 @@ typedef struct MovieTrackingObject { MovieTrackingReconstruction reconstruction; /* reconstruction data for this object */ /* reconstruction options */ - int keyframe1, keyframe2; /* two keyframes for reconstrution initialization */ + int keyframe1, keyframe2; /* two keyframes for reconstruction initialization */ } MovieTrackingObject; typedef struct MovieTrackingStats { diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 2256968da56..2e2f65dbec7 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -162,7 +162,8 @@ typedef struct ThemeUI { char iconfile[256]; // FILE_MAXFILE length float icon_alpha; - float pad; + /* Axis Colors */ + char xaxis[4], yaxis[4], zaxis[4]; } ThemeUI; /* try to put them all in one, if needed a special struct can be created as well @@ -417,9 +418,11 @@ typedef struct UserDef { float ndof_sensitivity; /* overall sensitivity of 3D mouse */ float ndof_orbit_sensitivity; - float pad4; int ndof_flag; /* flags for 3D mouse */ + short ogl_multisamples; /* amount of samples for OpenGL FSA, if zero no FSA */ + short pad4; + float glalphaclip; short autokey_mode; /* autokeying mode */ @@ -597,7 +600,7 @@ typedef enum eOpenGL_RenderingOptions { /* backwards compatibilty in do_versions! */ USER_DISABLE_MIPMAP = (1 << 2), USER_DISABLE_VBO = (1 << 3), - USER_DISABLE_AA = (1 << 4), + /* USER_DISABLE_AA = (1 << 4), */ /* DEPRECATED */ } eOpenGL_RenderingOptions; /* wm draw method */ @@ -702,6 +705,17 @@ typedef enum eCompute_Device_Type { USER_COMPUTE_DEVICE_CUDA = 2, } eCompute_Device_Type; + +typedef enum eMultiSample_Type { + USER_MULTISAMPLE_NONE = 0, + USER_MULTISAMPLE_2 = 2, + USER_MULTISAMPLE_4 = 4, + USER_MULTISAMPLE_8 = 8, + USER_MULTISAMPLE_16 = 16, +} eMultiSample_Type; + + + #ifdef __cplusplus } #endif diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index bef5e5cc161..fa0b313a120 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -1001,7 +1001,7 @@ static int make_structDNA(char *baseDirectory, FILE *file) /* FOR DEBUG */ if (debugSDNA > 1) { int a, b; -/* short *elem; */ + /* short *elem; */ short num_types; printf("nr_names %d nr_types %d nr_structs %d\n", nr_names, nr_types, nr_structs); diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 5f667db4425..0e5f9c5fa5f 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -148,6 +148,7 @@ extern StructRNA RNA_CompositorNodeLevels; extern StructRNA RNA_CompositorNodeLumaMatte; extern StructRNA RNA_CompositorNodeMapUV; extern StructRNA RNA_CompositorNodeMapValue; +extern StructRNA RNA_CompositorNodeMapRange; extern StructRNA RNA_CompositorNodeMath; extern StructRNA RNA_CompositorNodeMask; extern StructRNA RNA_CompositorNodeMixRGB; @@ -525,7 +526,6 @@ extern StructRNA RNA_TextBox; extern StructRNA RNA_TextCharacterFormat; extern StructRNA RNA_TextCurve; extern StructRNA RNA_TextLine; -extern StructRNA RNA_TextMarker; extern StructRNA RNA_Texture; extern StructRNA RNA_TextureNode; extern StructRNA RNA_TextureNodeBricks; @@ -862,6 +862,7 @@ int RNA_path_resolve_full(PointerRNA *ptr, const char *path, char *RNA_path_from_ID_to_struct(PointerRNA *ptr); char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop); +char *RNA_path_from_ID_python(struct ID *id); /* Quick name based property access * @@ -1053,6 +1054,11 @@ __attribute__ ((format(printf, 1, 2))) #endif ; +/* Equals test (skips pointers and collections) */ + +int RNA_property_equals(struct PointerRNA *a, struct PointerRNA *b, struct PropertyRNA *prop); +int RNA_struct_equals(struct PointerRNA *a, struct PointerRNA *b); + #ifdef __cplusplus } #endif diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 7c4ce3d18d7..6fa53f4e029 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -80,13 +80,15 @@ static void rna_generate_static_parameter_prototypes(FILE *f, StructRNA *srna, F const char *name_override, int close_prototype); /* helpers */ -#define WRITE_COMMA { \ +#define WRITE_COMMA \ + { \ if (!first) \ fprintf(f, ", "); \ first = 0; \ } (void)0 -#define WRITE_PARAM(param) { \ +#define WRITE_PARAM(param) \ + { \ WRITE_COMMA; \ fprintf(f, param); \ } @@ -1221,6 +1223,89 @@ static char *rna_def_property_lookup_int_func(FILE *f, StructRNA *srna, Property return func; } +static char *rna_def_property_lookup_string_func(FILE *f, StructRNA *srna, PropertyRNA *prop, PropertyDefRNA *dp, + const char *manualfunc, const char *item_type) +{ + char *func; + StructRNA *item_srna, *item_name_base; + PropertyRNA *item_name_prop; + const int namebuflen = 1024; + + if (prop->flag & PROP_IDPROPERTY && manualfunc == NULL) + return NULL; + + if (!manualfunc) { + if (!dp->dnastructname || !dp->dnaname) + return NULL; + + /* only supported for collection items with name properties */ + item_srna = rna_find_struct(item_type); + if (item_srna && item_srna->nameproperty) { + item_name_prop = item_srna->nameproperty; + item_name_base = item_srna; + while (item_name_base->base && item_name_base->base->nameproperty == item_name_prop) + item_name_base = item_name_base->base; + } + else + return NULL; + } + + func = rna_alloc_function_name(srna->identifier, rna_safe_id(prop->identifier), "lookup_string"); + + fprintf(f, "int %s(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)\n", func); + fprintf(f, "{\n"); + + if (manualfunc) { + fprintf(f, " return %s(ptr, key, r_ptr);\n", manualfunc); + fprintf(f, "}\n\n"); + return func; + } + + /* XXX extern declaration could be avoid by including RNA_blender.h, but this has lots of unknown + * DNA types in functions, leading to conflicting function signatures. + */ + fprintf(f, " extern int %s_%s_length(PointerRNA *);\n", item_name_base->identifier, rna_safe_id(item_name_prop->identifier)); + fprintf(f, " extern void %s_%s_get(PointerRNA *, char *);\n\n", item_name_base->identifier, rna_safe_id(item_name_prop->identifier)); + + fprintf(f, " int found= 0;\n"); + fprintf(f, " CollectionPropertyIterator iter;\n"); + fprintf(f, " char namebuf[%d];\n", namebuflen); + fprintf(f, " char *name;\n\n"); + + fprintf(f, " %s_%s_begin(&iter, ptr);\n\n", srna->identifier, rna_safe_id(prop->identifier)); + + fprintf(f, " while (iter.valid) {\n"); + fprintf(f, " int namelen = %s_%s_length(&iter.ptr);\n", item_name_base->identifier, rna_safe_id(item_name_prop->identifier)); + fprintf(f, " if (namelen < %d) {\n", namebuflen); + fprintf(f, " %s_%s_get(&iter.ptr, namebuf);\n", item_name_base->identifier, rna_safe_id(item_name_prop->identifier)); + fprintf(f, " if (strcmp(namebuf, key) == 0) {\n"); + fprintf(f, " found = 1;\n"); + fprintf(f, " *r_ptr = iter.ptr;\n"); + fprintf(f, " break;\n"); + fprintf(f, " }\n"); + fprintf(f, " }\n"); + fprintf(f, " else {\n"); + fprintf(f, " name = MEM_mallocN(namelen+1, \"name string\");\n"); + fprintf(f, " %s_%s_get(&iter.ptr, name);\n", item_name_base->identifier, rna_safe_id(item_name_prop->identifier)); + fprintf(f, " if (strcmp(name, key) == 0) {\n"); + fprintf(f, " MEM_freeN(name);\n\n"); + fprintf(f, " found = 1;\n"); + fprintf(f, " *r_ptr = iter.ptr;\n"); + fprintf(f, " break;\n"); + fprintf(f, " }\n"); + fprintf(f, " else\n"); + fprintf(f, " MEM_freeN(name);\n"); + fprintf(f, " }\n"); + fprintf(f, " %s_%s_next(&iter);\n", srna->identifier, rna_safe_id(prop->identifier)); + fprintf(f, " }\n"); + fprintf(f, " %s_%s_end(&iter);\n\n", srna->identifier, rna_safe_id(prop->identifier)); + + fprintf(f, " return found;\n"); + fprintf(f, "}\n\n"); + + return func; +} + static char *rna_def_property_next_func(FILE *f, StructRNA *srna, PropertyRNA *prop, PropertyDefRNA *UNUSED(dp), const char *manualfunc) { @@ -1401,6 +1486,7 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) { CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; const char *nextfunc = (const char *)cprop->next; + const char *item_type = (const char *)cprop->item_type; if (dp->dnatype && strcmp(dp->dnatype, "ListBase") == 0) { /* pass */ @@ -1424,6 +1510,8 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) cprop->end = (void *)rna_def_property_end_func(f, srna, prop, dp, (const char *)cprop->end); cprop->lookupint = (void *)rna_def_property_lookup_int_func(f, srna, prop, dp, (const char *)cprop->lookupint, nextfunc); + cprop->lookupstring = (void *)rna_def_property_lookup_string_func(f, srna, prop, dp, + (const char *)cprop->lookupstring, item_type); if (!(prop->flag & PROP_IDPROPERTY)) { if (!cprop->begin) { @@ -3169,6 +3257,8 @@ static void rna_generate(BlenderRNA *brna, FILE *f, const char *filename, const fprintf(f, "#include \n\n"); fprintf(f, "#include \n\n"); + fprintf(f, "#include \"MEM_guardedalloc.h\"\n\n"); + fprintf(f, "#include \"DNA_ID.h\"\n"); fprintf(f, "#include \"DNA_scene_types.h\"\n"); @@ -3579,10 +3669,10 @@ static void rna_generate_header_class_cpp(StructDefRNA *ds, FILE *f) fprintf(f, "class %s : public %s {\n", srna->identifier, (srna->base) ? srna->base->identifier : "Pointer"); fprintf(f, "public:\n"); fprintf(f, "\t%s(const PointerRNA &ptr_arg) :\n\t\t%s(ptr_arg)", srna->identifier, - (srna->base) ? srna->base->identifier : "Pointer"); + (srna->base) ? srna->base->identifier : "Pointer"); for (dp = ds->cont.properties.first; dp; dp = dp->next) if (rna_is_collection_prop(dp->prop)) - fprintf(f, ",\n\t\t%s(ptr_arg)", dp->prop->identifier); + fprintf(f, ",\n\t\t%s(ptr_arg)", dp->prop->identifier); fprintf(f, "\n\t\t{}\n\n"); for (dp = ds->cont.properties.first; dp; dp = dp->next) diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 1fe46342819..488dbffc3db 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -46,6 +46,7 @@ #include "BKE_animsys.h" #include "BKE_context.h" +#include "BKE_idcode.h" #include "BKE_idprop.h" #include "BKE_main.h" #include "BKE_report.h" @@ -1224,10 +1225,10 @@ void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA if (prop->translation_context) nitem[i].name = BLF_pgettext(prop->translation_context, nitem[i].name); else - nitem[i].name = BLF_gettext(nitem[i].name); + nitem[i].name = BLF_pgettext(NULL, nitem[i].name); } if (nitem[i].description) - nitem[i].description = BLF_gettext(nitem[i].description); + nitem[i].description = BLF_pgettext(NULL, nitem[i].description); } *item = nitem; @@ -2551,7 +2552,10 @@ PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop) pprop = (PointerPropertyRNA *)prop; /* for groups, data is idprop itself */ - return rna_pointer_inherit_refine(ptr, pprop->type, idprop); + if (pprop->typef) + return rna_pointer_inherit_refine(ptr, pprop->typef(ptr), idprop); + else + return rna_pointer_inherit_refine(ptr, pprop->type, idprop); } else if (pprop->get) { return pprop->get(ptr); @@ -4011,12 +4015,15 @@ static char *rna_idp_path(PointerRNA *ptr, IDProperty *haystack, IDProperty *nee BLI_assert(haystack->type == IDP_GROUP); link.up = parent_link; + /* always set both name and index, + * else a stale value might get used */ link.name = NULL; link.index = -1; for (i = 0, iter = haystack->data.group.first; iter; iter = iter->next, i++) { if (needle == iter) { /* found! */ link.name = iter->name; + link.index = -1; path = rna_idp_path_create(&link); break; } @@ -4026,6 +4033,7 @@ static char *rna_idp_path(PointerRNA *ptr, IDProperty *haystack, IDProperty *nee PointerRNA child_ptr = RNA_pointer_get(ptr, iter->name); if (child_ptr.type) { link.name = iter->name; + link.index = -1; if ((path = rna_idp_path(&child_ptr, iter, needle, &link))) { break; } @@ -4143,16 +4151,32 @@ char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop) path = BLI_sprintfN(is_rna ? "%s.%s" : "%s[\"%s\"]", ptrpath, propname); MEM_freeN(ptrpath); } - else { + else if (RNA_struct_is_ID(ptr->type)) { if (is_rna) path = BLI_strdup(propname); else path = BLI_sprintfN("[\"%s\"]", propname); } + else { + path = NULL; + } return path; } +/** + * Get the ID as a python representation, eg: + * bpy.data.foo["bar"] + */ +char *RNA_path_from_ID_python(ID *id) +{ + char id_esc[(sizeof(id->name) - 2) * 2]; + + BLI_strescape(id_esc, id->name + 2, sizeof(id_esc)); + + return BLI_sprintfN("bpy.data.%s[\"%s\"]", BKE_idcode_to_name_plural(GS(id->name)), id_esc); +} + /* Quick name based property access */ int RNA_boolean_get(PointerRNA *ptr, const char *name) @@ -5714,7 +5738,7 @@ int RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, i /* get the length of the array to work with */ len = RNA_property_array_length(ptr, prop); - fromlen = RNA_property_array_length(ptr, prop); + fromlen = RNA_property_array_length(fromptr, prop); if (len != fromlen) return 0; @@ -5828,3 +5852,146 @@ void _RNA_warning(const char *format, ...) } #endif } + +int RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop) +{ + /* get the length of the array to work with */ + int len = RNA_property_array_length(a, prop); + int fromlen = RNA_property_array_length(b, prop); + + if (len != fromlen) + return 0; + + /* get and set the default values as appropriate for the various types */ + switch (RNA_property_type(prop)) { + case PROP_BOOLEAN: { + if (len) { + int fixed_a[16], fixed_b[16]; + int *array_a, *array_b; + int equals; + + array_a = (len > 16)? MEM_callocN(sizeof(int) * len, "RNA equals"): fixed_a; + array_b = (len > 16)? MEM_callocN(sizeof(int) * len, "RNA equals"): fixed_b; + + RNA_property_boolean_get_array(a, prop, array_a); + RNA_property_boolean_get_array(b, prop, array_b); + + equals = memcmp(array_a, array_b, sizeof(int) * len) == 0; + + if (array_a != fixed_a) MEM_freeN(array_a); + if (array_b != fixed_b) MEM_freeN(array_b); + + return equals; + } + else { + int value = RNA_property_boolean_get(a, prop); + return value == RNA_property_boolean_get(b, prop); + } + } + + case PROP_INT: { + if (len) { + int fixed_a[16], fixed_b[16]; + int *array_a, *array_b; + int equals; + + array_a = (len > 16)? MEM_callocN(sizeof(int) * len, "RNA equals"): fixed_a; + array_b = (len > 16)? MEM_callocN(sizeof(int) * len, "RNA equals"): fixed_b; + + RNA_property_int_get_array(a, prop, array_a); + RNA_property_int_get_array(b, prop, array_b); + + equals = memcmp(array_a, array_b, sizeof(int) * len) == 0; + + if (array_a != fixed_a) MEM_freeN(array_a); + if (array_b != fixed_b) MEM_freeN(array_b); + + return equals; + } + else { + int value = RNA_property_int_get(a, prop); + return value == RNA_property_int_get(b, prop); + } + } + + case PROP_FLOAT: { + if (len) { + float fixed_a[16], fixed_b[16]; + float *array_a, *array_b; + int equals; + + array_a = (len > 16)? MEM_callocN(sizeof(float) * len, "RNA equals"): fixed_a; + array_b = (len > 16)? MEM_callocN(sizeof(float) * len, "RNA equals"): fixed_b; + + RNA_property_float_get_array(a, prop, array_a); + RNA_property_float_get_array(b, prop, array_b); + + equals = memcmp(array_a, array_b, sizeof(float) * len) == 0; + + if (array_a != fixed_a) MEM_freeN(array_a); + if (array_b != fixed_b) MEM_freeN(array_b); + + return equals; + } + else { + float value = RNA_property_float_get(a, prop); + return value == RNA_property_float_get(b, prop); + } + } + + case PROP_ENUM: { + int value = RNA_property_enum_get(a, prop); + return value == RNA_property_enum_get(b, prop); + } + + case PROP_STRING: { + char fixed_a[128], fixed_b[128]; + int len_a, len_b; + char *value_a = RNA_property_string_get_alloc(a, prop, fixed_a, sizeof(fixed_a), &len_a); + char *value_b = RNA_property_string_get_alloc(b, prop, fixed_b, sizeof(fixed_b), &len_b); + int equals = strcmp(value_a, value_b) == 0; + + if (value_a != fixed_a) MEM_freeN(value_a); + if (value_b != fixed_b) MEM_freeN(value_b); + + return equals; + } + + default: + break; + } + + return 1; +} + +int RNA_struct_equals(PointerRNA *a, PointerRNA *b) +{ + CollectionPropertyIterator iter; +// CollectionPropertyRNA *citerprop; /* UNUSED */ + PropertyRNA *iterprop; + int equals = 1; + + if (a == NULL && b == NULL) + return 1; + else if (a == NULL || b == NULL) + return 0; + else if (a->type != b->type) + return 0; + + iterprop = RNA_struct_iterator_property(a->type); +// citerprop = (CollectionPropertyRNA *)rna_ensure_property(iterprop); /* UNUSED */ + + RNA_property_collection_begin(a, iterprop, &iter); + for (; iter.valid; RNA_property_collection_next(&iter)) { + PropertyRNA *prop = iter.ptr.data; + + if (!RNA_property_equals(a, b, prop)) { + equals = 0; + break; + } + } + RNA_property_collection_end(&iter); + + return equals; +} + diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index ba1aca2baba..1f9503f1cc9 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -46,9 +46,13 @@ #ifdef RNA_RUNTIME -#include "ED_keyframing.h" +#include "BLI_math_base.h" + #include "BKE_fcurve.h" +#include "ED_keyframing.h" + + static void rna_ActionGroup_channels_next(CollectionPropertyIterator *iter) { ListBaseIterator *internal = iter->internal; @@ -191,8 +195,7 @@ static void rna_Action_active_pose_marker_index_range(PointerRNA *ptr, int *min, bAction *act = (bAction *)ptr->data; *min = 0; - *max = BLI_countlist(&act->markers) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&act->markers) - 1); } diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c index b1fdfccd0be..b653289e44d 100644 --- a/source/blender/makesrna/intern/rna_actuator.c +++ b/source/blender/makesrna/intern/rna_actuator.c @@ -973,13 +973,13 @@ static void rna_def_sound_actuator(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.0, 1.0, 1, 2); RNA_def_property_range(prop, 0.0, 2.0); RNA_def_property_ui_text(prop, "Volume", "Initial volume of the sound"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); RNA_def_property_update(prop, NC_LOGIC, NULL); prop = RNA_def_property(srna, "pitch", PROP_FLOAT, PROP_NONE); RNA_def_property_ui_range(prop, -12.0, 12.0, 1, 2); RNA_def_property_ui_text(prop, "Pitch", "Pitch of the sound"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); RNA_def_property_update(prop, NC_LOGIC, NULL); /* floats - 3D Parameters */ diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index ce884fa4ecc..7229dddf6d6 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -54,6 +54,8 @@ EnumPropertyItem keyingset_path_grouping_items[] = { #ifdef RNA_RUNTIME +#include "BLI_math_base.h" + #include "BKE_animsys.h" #include "BKE_fcurve.h" #include "BKE_nla.h" @@ -296,6 +298,43 @@ static void rna_ksPath_RnaPath_set(PointerRNA *ptr, const char *value) /* ****************************** */ +static void rna_KeyingSet_name_set(PointerRNA *ptr, const char *value) +{ + KeyingSet *ks = (KeyingSet *)ptr->data; + + /* update names of corresponding groups if name changes */ + if (strcmp(ks->name, value)) { + KS_Path *ksp; + + for (ksp = ks->paths.first; ksp; ksp = ksp->next) { + if ((ksp->groupmode == KSP_GROUP_KSNAME) && (ksp->id)) { + AnimData *adt = BKE_animdata_from_id(ksp->id); + + /* TODO: NLA strips? */ + if (adt && adt->action) { + bActionGroup *agrp; + + /* lazy check - should really find the F-Curve for the affected path and check its group + * but this way should be faster and work well for most cases, as long as there are no + * conflicts + */ + for (agrp = adt->action->groups.first; agrp; agrp = agrp->next) { + if (strcmp(ks->name, agrp->name) == 0) { + /* there should only be one of these in the action, so can stop... */ + BLI_strncpy(agrp->name, value, sizeof(agrp->name)); + break; + } + } + } + } + } + } + + /* finally, update name to new value */ + BLI_strncpy(ks->name, value, sizeof(ks->name)); +} + + static int rna_KeyingSet_active_ksPath_editable(PointerRNA *ptr) { KeyingSet *ks = (KeyingSet *)ptr->data; @@ -334,8 +373,7 @@ static void rna_KeyingSet_active_ksPath_index_range(PointerRNA *ptr, int *min, i KeyingSet *ks = (KeyingSet *)ptr->data; *min = 0; - *max = BLI_countlist(&ks->paths) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&ks->paths) - 1); } static PointerRNA rna_KeyingSet_typeinfo_get(PointerRNA *ptr) @@ -430,7 +468,7 @@ static void rna_NlaTrack_remove(AnimData *adt, bContext *C, ReportList *reports, NlaTrack *track = track_ptr->data; if (BLI_findindex(&adt->nla_tracks, track) == -1) { - BKE_reportf(reports, RPT_ERROR, "NlaTrack '%s' can't be removed", track->name); + BKE_reportf(reports, RPT_ERROR, "NlaTrack '%s' cannot be removed", track->name); return; } @@ -721,19 +759,20 @@ static void rna_def_keyingset(BlenderRNA *brna) srna = RNA_def_struct(brna, "KeyingSet", NULL); RNA_def_struct_ui_text(srna, "Keying Set", "Settings that should be keyframed together"); - /* Id/Label. */ + /* Id/Label */ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "idname"); RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP); RNA_def_property_ui_text(prop, "ID Name", KEYINGSET_IDNAME_DOC); - RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_RENAME, NULL); +/* RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_RENAME, NULL); */ /* NOTE: disabled, as ID name shouldn't be editable */ prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "name"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_KeyingSet_name_set"); RNA_def_property_ui_text(prop, "UI Name", ""); RNA_def_struct_ui_icon(srna, ICON_KEYINGSET); RNA_def_struct_name_property(srna, prop); -/* RNA_def_property_update(prop, NC_SCENE|ND_KEYINGSET|NA_RENAME, NULL);*/ + RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_RENAME, NULL); prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_TRANSLATE); RNA_def_property_string_sdna(prop, NULL, "description"); diff --git a/source/blender/makesrna/intern/rna_boid.c b/source/blender/makesrna/intern/rna_boid.c index 8e45da50e9b..3da718afd1c 100644 --- a/source/blender/makesrna/intern/rna_boid.c +++ b/source/blender/makesrna/intern/rna_boid.c @@ -80,6 +80,8 @@ EnumPropertyItem boidruleset_type_items[] = { #ifdef RNA_RUNTIME +#include "BLI_math_base.h" + #include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_particle.h" @@ -157,8 +159,7 @@ static void rna_BoidState_active_boid_rule_index_range(PointerRNA *ptr, int *min { BoidState *state = (BoidState *)ptr->data; *min = 0; - *max = BLI_countlist(&state->rules) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&state->rules) - 1); } static int rna_BoidState_active_boid_rule_index_get(PointerRNA *ptr) @@ -224,8 +225,7 @@ static void rna_BoidSettings_active_boid_state_index_range(PointerRNA *ptr, int { BoidSettings *boids = (BoidSettings *)ptr->data; *min = 0; - *max = BLI_countlist(&boids->states) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&boids->states) - 1); } static int rna_BoidSettings_active_boid_state_index_get(PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index e96ed4f38d3..7bdebd620ee 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -146,8 +146,8 @@ static int rna_SculptCapabilities_has_overlay_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return ELEM(br->mtex.brush_map_mode, - MTEX_MAP_MODE_VIEW, - MTEX_MAP_MODE_TILED); + MTEX_MAP_MODE_VIEW, + MTEX_MAP_MODE_TILED); } static int rna_SculptCapabilities_has_persistence_get(PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index f534864e65a..5752fd318c7 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -503,6 +503,10 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *UNUSED(bmain) BKE_movieclip_reload(clip); + /* all sequencers for now, we don't know which scenes are using this clip as a strip */ + BKE_sequencer_cache_cleanup(); + BKE_sequencer_preprocessed_cache_cleanup(); + WM_main_add_notifier(NC_MOVIECLIP | ND_DISPLAY, &clip->id); WM_main_add_notifier(NC_MOVIECLIP | NA_EDITED, &clip->id); } diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 7b6b629ca82..30a9bfd81f6 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -614,7 +614,7 @@ static void rna_def_constraint_kinematic(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update"); prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE); - RNA_def_property_range(prop, 1, 10000); + RNA_def_property_range(prop, 0, 10000); RNA_def_property_ui_text(prop, "Iterations", "Maximum number of solving iterations"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index 35699c6ef3f..21aed20ccc3 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -242,16 +242,14 @@ static void rna_Curve_material_index_range(PointerRNA *ptr, int *min, int *max, { Curve *cu = (Curve *)ptr->id.data; *min = 0; - *max = cu->totcol - 1; - *max = MAX2(0, *max); + *max = max_ii(0, cu->totcol - 1); } static void rna_Curve_active_textbox_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax) { Curve *cu = (Curve *)ptr->id.data; *min = 0; - *max = cu->totbox - 1; - *max = MAX2(0, *max); + *max = max_ii(0, cu->totbox - 1); } @@ -1424,6 +1422,11 @@ static void rna_def_curve(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Fill Caps", "Fill caps for beveled curves"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); + prop = RNA_def_property(srna, "use_map_taper", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_MAP_TAPER); + RNA_def_property_ui_text(prop, "Map Taper", "Map effect of taper object on actually beveled curve"); + RNA_def_property_update(prop, 0, "rna_Curve_update_data"); + /* texture space */ prop = RNA_def_property(srna, "use_auto_texspace", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "texflag", CU_AUTOSPACE); diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index f8af2427827..9fedbee41ff 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -113,7 +113,7 @@ static void rna_Image_fields_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE); } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); } static void rna_Image_free_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) @@ -187,8 +187,12 @@ static EnumPropertyItem *rna_Image_source_itemf(bContext *UNUSED(C), PointerRNA static int rna_Image_file_format_get(PointerRNA *ptr) { Image *image = (Image *)ptr->data; - ImBuf *ibuf = BKE_image_get_ibuf(image, NULL); - return BKE_ftype_to_imtype(ibuf ? ibuf->ftype : 0); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); + int imtype = BKE_ftype_to_imtype(ibuf ? ibuf->ftype : 0); + + BKE_image_release_ibuf(image, ibuf, NULL); + + return imtype; } static void rna_Image_file_format_set(PointerRNA *ptr, int value) @@ -199,12 +203,13 @@ static void rna_Image_file_format_set(PointerRNA *ptr, int value) int ftype = BKE_imtype_to_ftype(value); #if 0 - ibuf = BKE_image_get_ibuf(image, NULL); + ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (ibuf) ibuf->ftype = ftype; #endif /* to be safe change all buffer file types */ + /* TODO: this is never threadsafe */ for (ibuf = image->ibufs.first; ibuf; ibuf = ibuf->next) { ibuf->ftype = ftype; } @@ -237,7 +242,7 @@ static void rna_Image_size_get(PointerRNA *ptr, int *values) values[1] = 0; } - BKE_image_release_ibuf(im, lock); + BKE_image_release_ibuf(im, ibuf, lock); } static void rna_Image_resolution_get(PointerRNA *ptr, float *values) @@ -256,7 +261,7 @@ static void rna_Image_resolution_get(PointerRNA *ptr, float *values) values[1] = 0; } - BKE_image_release_ibuf(im, lock); + BKE_image_release_ibuf(im, ibuf, lock); } static void rna_Image_resolution_set(PointerRNA *ptr, const float *values) @@ -271,7 +276,7 @@ static void rna_Image_resolution_set(PointerRNA *ptr, const float *values) ibuf->ppm[1] = values[1]; } - BKE_image_release_ibuf(im, lock); + BKE_image_release_ibuf(im, ibuf, lock); } static int rna_Image_depth_get(PointerRNA *ptr) @@ -290,7 +295,7 @@ static int rna_Image_depth_get(PointerRNA *ptr) else planes = ibuf->planes; - BKE_image_release_ibuf(im, lock); + BKE_image_release_ibuf(im, ibuf, lock); return planes; } @@ -317,7 +322,7 @@ static int rna_Image_pixels_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY else length[0] = 0; - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); return length[0]; } @@ -343,7 +348,7 @@ static void rna_Image_pixels_get(PointerRNA *ptr, float *values) } } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); } static void rna_Image_pixels_set(PointerRNA *ptr, const float *values) @@ -369,7 +374,7 @@ static void rna_Image_pixels_set(PointerRNA *ptr, const float *values) ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID; } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); } #else diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index cb5c515ce1f..686e6c80f1d 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -99,7 +99,7 @@ static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports IMB_freeImBuf(write_ibuf); } - BKE_image_release_ibuf(image, lock); + BKE_image_release_ibuf(image, ibuf, lock); } else { BKE_report(reports, RPT_ERROR, "Scene not in context, could not get save parameters"); @@ -108,7 +108,7 @@ static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports static void rna_Image_save(Image *image, ReportList *reports) { - ImBuf *ibuf = BKE_image_get_ibuf(image, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (ibuf) { char filename[FILE_MAX]; BLI_strncpy(filename, image->name, sizeof(filename)); @@ -136,11 +136,13 @@ static void rna_Image_save(Image *image, ReportList *reports) else { BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2); } + + BKE_image_release_ibuf(image, ibuf, NULL); } static void rna_Image_pack(Image *image, ReportList *reports, int as_png) { - ImBuf *ibuf = BKE_image_get_ibuf(image, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) { BKE_report(reports, RPT_ERROR, "Cannot pack edited image from disk, only as internal PNG"); @@ -153,6 +155,8 @@ static void rna_Image_pack(Image *image, ReportList *reports, int as_png) image->packedfile = newPackedFile(reports, image->name, ID_BLEND_PATH(G.main, &image->id)); } } + + BKE_image_release_ibuf(image, ibuf, NULL); } static void rna_Image_unpack(Image *image, ReportList *reports, int method) @@ -177,7 +181,7 @@ static void rna_Image_reload(Image *image) static void rna_Image_update(Image *image, ReportList *reports) { - ImBuf *ibuf = BKE_image_get_ibuf(image, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (ibuf == NULL) { BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2); @@ -188,6 +192,8 @@ static void rna_Image_update(Image *image, ReportList *reports) IMB_rect_from_float(ibuf); ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + + BKE_image_release_ibuf(image, ibuf, NULL); } static void rna_Image_scale(Image *image, ReportList *reports, int width, int height) @@ -206,10 +212,11 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int filter, int if (*bind) return error; - ibuf = BKE_image_get_ibuf(image, NULL); + ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (ibuf == NULL || ibuf->rect == NULL) { BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2); + BKE_image_release_ibuf(image, ibuf, NULL); return (int)GL_INVALID_OPERATION; } @@ -238,6 +245,8 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int filter, int image->bindcode = 0; } + BKE_image_release_ibuf(image, ibuf, NULL); + return error; } diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c index 9d63e0e687d..af39500442d 100644 --- a/source/blender/makesrna/intern/rna_lamp.c +++ b/source/blender/makesrna/intern/rna_lamp.c @@ -421,7 +421,7 @@ static void rna_def_lamp(BlenderRNA *brna) /* textures */ rna_def_mtex_common(brna, srna, "rna_Lamp_mtex_begin", "rna_Lamp_active_texture_get", - "rna_Lamp_active_texture_set", NULL, "LampTextureSlot", "LampTextureSlots", "rna_Lamp_update"); + "rna_Lamp_active_texture_set", NULL, "LampTextureSlot", "LampTextureSlots", "rna_Lamp_draw_update"); } static void rna_def_lamp_falloff(StructRNA *srna) diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index 56caa254a59..3f23a376ea3 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -158,8 +158,7 @@ static void rna_Mask_layer_active_index_range(PointerRNA *ptr, int *min, int *ma Mask *mask = (Mask *)ptr->id.data; *min = 0; - *max = mask->masklay_tot - 1; - *max = MAX2(0, *max); + *max = max_ii(0, mask->masklay_tot - 1); *softmin = *min; *softmax = *max; diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 9232ae098ea..1221b84372c 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -2121,13 +2121,13 @@ void rna_def_mtex_common(BlenderRNA *brna, StructRNA *srna, const char *begin, RNA_def_property_editable_func(prop, activeeditable); RNA_def_property_pointer_funcs(prop, activeget, activeset, NULL, NULL); RNA_def_property_ui_text(prop, "Active Texture", "Active texture slot being displayed"); - RNA_def_property_update(prop, 0, update); + RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, update); prop = RNA_def_property(srna, "active_texture_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "texact"); RNA_def_property_range(prop, 0, MAX_MTEX - 1); RNA_def_property_ui_text(prop, "Active Texture Index", "Index of active texture slot"); - RNA_def_property_update(prop, 0, update); + RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, update); } #endif diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index f0b84332d07..287995e0aa6 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -1010,8 +1010,7 @@ static void rna_MeshPoly_material_index_range(PointerRNA *ptr, int *min, int *ma { Mesh *me = rna_mesh(ptr); *min = 0; - *max = me->totcol - 1; - *max = MAX2(0, *max); + *max = max_ii(0, me->totcol - 1); } static int rna_MeshVertex_index_get(PointerRNA *ptr) @@ -2810,7 +2809,7 @@ static void rna_def_mesh(BlenderRNA *brna) prop = RNA_def_property(srna, "skin_vertices", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "vdata.layers", "vdata.totlayer"); RNA_def_property_collection_funcs(prop, "rna_Mesh_skin_vertices_begin", NULL, NULL, NULL, - "rna_Mesh_skin_vertices_length", NULL, NULL, NULL); + "rna_Mesh_skin_vertices_length", NULL, NULL, NULL); RNA_def_property_struct_type(prop, "MeshSkinVertexLayer"); RNA_def_property_ui_text(prop, "Skin Vertices", "All skin vertices"); rna_def_skin_vertices(brna, prop); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 8eca7162d39..a2b0945fb46 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -78,6 +78,7 @@ EnumPropertyItem modifier_type_items[] = { {eModifierType_Skin, "SKIN", ICON_MOD_SKIN, "Skin", ""}, {eModifierType_Solidify, "SOLIDIFY", ICON_MOD_SOLIDIFY, "Solidify", ""}, {eModifierType_Subsurf, "SUBSURF", ICON_MOD_SUBSURF, "Subdivision Surface", ""}, + {eModifierType_Triangulate, "TRIANGULATE", ICON_MOD_TRIANGULATE, "Triangulate", ""}, {0, "", 0, N_("Deform"), ""}, {eModifierType_Armature, "ARMATURE", ICON_MOD_ARMATURE, "Armature", ""}, {eModifierType_Cast, "CAST", ICON_MOD_CAST, "Cast", ""}, @@ -213,6 +214,8 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr) return &RNA_SkinModifier; case eModifierType_LaplacianSmooth: return &RNA_LaplacianSmoothModifier; + case eModifierType_Triangulate: + return &RNA_TriangulateModifier; default: return &RNA_Modifier; } @@ -481,8 +484,7 @@ static void rna_MultiresModifier_level_range(PointerRNA *ptr, int *min, int *max MultiresModifierData *mmd = (MultiresModifierData *)ptr->data; *min = 0; - *max = mmd->totlvl; /* intentionally _not_ -1 */ - *max = MAX2(0, *max); + *max = max_ii(0, mmd->totlvl); /* intentionally _not_ -1 */ } static int rna_MultiresModifier_external_get(PointerRNA *ptr) @@ -1815,7 +1817,7 @@ static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "use_volume_preserve", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME); RNA_def_property_ui_text(prop, "Preserve Volume", "Apply volume preservation after smooth"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); @@ -2205,6 +2207,7 @@ static void rna_def_modifier_smoke(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, prop_smoke_type_items); RNA_def_property_ui_text(prop, "Type", ""); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, 0, "rna_Smoke_set_type"); } @@ -2401,6 +2404,13 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Offset", "Distance to keep from the target"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "project_limit", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "projLimit"); + RNA_def_property_range(prop, 0.0, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 100, 1, 2); + RNA_def_property_ui_text(prop, "Project Limit", "Limit the distance used for projection (zero disables)"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "use_project_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "projAxis", MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS); RNA_def_property_ui_text(prop, "X", ""); @@ -3355,6 +3365,22 @@ static void rna_def_modifier_skin(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Modifier_update"); } +static void rna_def_modifier_triangulate(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "TriangulateModifier", "Modifier"); + RNA_def_struct_ui_text(srna, "Triangulate Modifier", "Triangulate Mesh"); + RNA_def_struct_sdna(srna, "TriangulateModifierData"); + RNA_def_struct_ui_icon(srna, ICON_MOD_TRIANGULATE); + + prop = RNA_def_property(srna, "use_beauty", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_TRIANGULATE_BEAUTY); + RNA_def_property_ui_text(prop, "Beauty Subdivide", "Subdivide across shortest diagonal"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); +} + void RNA_def_modifier(BlenderRNA *brna) { StructRNA *srna; @@ -3462,6 +3488,7 @@ void RNA_def_modifier(BlenderRNA *brna) rna_def_modifier_remesh(brna); rna_def_modifier_skin(brna); rna_def_modifier_laplaciansmooth(brna); + rna_def_modifier_triangulate(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index ece5c82f747..1da9a450c2c 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -92,6 +92,7 @@ EnumPropertyItem node_socket_type_items[] = { {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""}, {SOCK_MESH, "MESH", 0, "Mesh", ""}, {SOCK_INT, "INT", 0, "Int", ""}, + {SOCK_STRING, "STRING", 0, "String", ""}, {0, NULL, 0, NULL, NULL} }; @@ -192,6 +193,10 @@ EnumPropertyItem prop_wave_items[] = { SUBTYPE(FLOAT, Float, TIME, Time) \ SUBTYPE(FLOAT, Float, DISTANCE, Distance) +#define NODE_DEFINE_SUBTYPES_STRING \ + SUBTYPE(STRING, String, NONE, None) \ + SUBTYPE(STRING, String, FILEPATH, Filepath) + #define NODE_DEFINE_SUBTYPES_VECTOR \ SUBTYPE(VECTOR, Vector, NONE, None) \ SUBTYPE(VECTOR, Vector, TRANSLATION, Translation) \ @@ -204,7 +209,8 @@ EnumPropertyItem prop_wave_items[] = { #define NODE_DEFINE_SUBTYPES \ NODE_DEFINE_SUBTYPES_INT \ NODE_DEFINE_SUBTYPES_FLOAT \ - NODE_DEFINE_SUBTYPES_VECTOR + NODE_DEFINE_SUBTYPES_STRING \ + NODE_DEFINE_SUBTYPES_VECTOR \ #ifdef RNA_RUNTIME @@ -214,6 +220,7 @@ EnumPropertyItem prop_wave_items[] = { #include "ED_node.h" +#include "RE_engine.h" #include "RE_pipeline.h" #include "DNA_scene_types.h" @@ -292,6 +299,9 @@ static StructRNA *rna_NodeSocket_refine(PointerRNA *ptr) case SOCK_VECTOR: NODE_DEFINE_SUBTYPES_VECTOR break; + case SOCK_STRING: + NODE_DEFINE_SUBTYPES_STRING + break; case SOCK_RGBA: return &RNA_NodeSocketRGBA; case SOCK_SHADER: @@ -1124,6 +1134,22 @@ static IDProperty *rna_ShaderNodeScript_idprops(PointerRNA *ptr, int create) return nss->prop; } +static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNode *node = (bNode *)ptr->data; + RenderEngineType *engine_type = RE_engines_find(scene->r.engine); + + if (engine_type && engine_type->update_script_node) { + /* auto update node */ + RenderEngine *engine = RE_engine_create(engine_type); + engine_type->update_script_node(engine, ntree, node); + RE_engine_free(engine); + } + + node_update(bmain, scene, ntree, node); +} + #else static EnumPropertyItem prop_image_layer_items[] = { @@ -1166,7 +1192,7 @@ static EnumPropertyItem node_glossy_items[] = { static EnumPropertyItem node_script_mode_items[] = { {NODE_SCRIPT_INTERNAL, "INTERNAL", 0, "Internal", "Use internal text datablock"}, - {NODE_SCRIPT_EXTERNAL, "EXTERNAL", 0, "External", "Use external .osl or oso file"}, + {NODE_SCRIPT_EXTERNAL, "EXTERNAL", 0, "External", "Use external .osl or .oso file"}, {0, NULL, 0, NULL, NULL} }; @@ -1195,7 +1221,7 @@ typedef struct NodeInfo { static NodeInfo nodes[MaxNodes]; static void reg_node(int ID, int category, const char *enum_name, const char *struct_name, - const char *base_name, const char *ui_name, const char *ui_desc) + const char *base_name, const char *ui_name, const char *ui_desc) { NodeInfo *ni = nodes + ID; @@ -1275,6 +1301,14 @@ static void alloc_node_type_items(EnumPropertyItem *items, int category) item++; + item->value = NODE_FRAME; + item->identifier = "FRAME"; + item->icon = 0; + item->name = "Frame"; + item->description = ""; + + item++; + /* NOTE!, increase 'count' when adding items here */ memset(item, 0, sizeof(EnumPropertyItem)); @@ -1842,6 +1876,67 @@ static void def_glossy(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_sh_normal_map(StructRNA *srna) +{ + static EnumPropertyItem prop_space_items[] = { + {SHD_NORMAL_MAP_TANGENT, "TANGENT", 0, "Tangent Space", "Tangent space normal mapping"}, + {SHD_NORMAL_MAP_OBJECT, "OBJECT", 0, "Object Space", "Object space normal mapping"}, + {SHD_NORMAL_MAP_WORLD, "WORLD", 0, "World Space", "World space normal mapping"}, + {0, NULL, 0, NULL, NULL} + }; + + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeShaderNormalMap", "storage"); + + prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_space_items); + RNA_def_property_ui_text(prop, "Space", "Space of the input normal"); + RNA_def_property_update(prop, 0, "rna_Node_update"); + + prop = RNA_def_property(srna, "uv_map", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "UV Map", "UV Map for tangent space maps"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + RNA_def_struct_sdna_from(srna, "bNode", NULL); +} + +static void def_sh_tangent(StructRNA *srna) +{ + static EnumPropertyItem prop_direction_type_items[] = { + {SHD_TANGENT_RADIAL, "RADIAL", 0, "Radial", "Radial tangent around the X, Y or Z axis"}, + {SHD_TANGENT_UVMAP, "UV_MAP", 0, "UV Map", "Tangent from UV map"}, + {0, NULL, 0, NULL, NULL} + }; + + static EnumPropertyItem prop_axis_items[] = { + {SHD_TANGENT_AXIS_X, "X", 0, "X", "X axis"}, + {SHD_TANGENT_AXIS_Y, "Y", 0, "Y", "Y axis"}, + {SHD_TANGENT_AXIS_Z, "Z", 0, "Z", "Z axis"}, + {0, NULL, 0, NULL, NULL} + }; + + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeShaderTangent", "storage"); + + prop = RNA_def_property(srna, "direction_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_direction_type_items); + RNA_def_property_ui_text(prop, "Direction", "Method to use for the tangent"); + RNA_def_property_update(prop, 0, "rna_Node_update"); + + prop = RNA_def_property(srna, "axis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_axis_items); + RNA_def_property_ui_text(prop, "Axis", "Axis for radial tangents"); + RNA_def_property_update(prop, 0, "rna_Node_update"); + + prop = RNA_def_property(srna, "uv_map", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "UV Map", "UV Map for tangent generated from UV"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + RNA_def_struct_sdna_from(srna, "bNode", NULL); +} + static void def_sh_script(StructRNA *srna) { FunctionRNA *func; @@ -1852,14 +1947,14 @@ static void def_sh_script(StructRNA *srna) RNA_def_property_struct_type(prop, "Text"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); RNA_def_property_ui_text(prop, "Script", "Internal shader script to define the shader"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeScript_update"); RNA_def_struct_sdna_from(srna, "NodeShaderScript", "storage"); RNA_def_struct_idprops_func(srna, "rna_ShaderNodeScript_idprops"); prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH); RNA_def_property_ui_text(prop, "File Path", "Shader script path"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeScript_update"); prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_funcs(prop, NULL, "rna_ShaderNodeScript_mode_set", NULL); @@ -1869,11 +1964,12 @@ static void def_sh_script(StructRNA *srna) prop = RNA_def_property(srna, "use_auto_update", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_SCRIPT_AUTO_UPDATE); - RNA_def_property_ui_text(prop, "Auto Update", "Automatically updates the shader when the .osl file changes - external scripts only"); + RNA_def_property_ui_text(prop, "Auto Update", + "Automatically update the shader when the .osl file changes (external scripts only)"); prop = RNA_def_property(srna, "bytecode", PROP_STRING, PROP_NONE); - RNA_def_property_string_funcs(prop, "rna_ShaderNodeScript_bytecode_get", - "rna_ShaderNodeScript_bytecode_length", "rna_ShaderNodeScript_bytecode_set"); + RNA_def_property_string_funcs(prop, "rna_ShaderNodeScript_bytecode_get", "rna_ShaderNodeScript_bytecode_length", + "rna_ShaderNodeScript_bytecode_set"); RNA_def_property_ui_text(prop, "Bytecode", "Compile bytecode for shader script node"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); @@ -2103,6 +2199,16 @@ static void def_cmp_map_value(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_cmp_map_range(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "use_clamp", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1); + RNA_def_property_ui_text(prop, "Clamp", "Clamp result of the node to 0..1 range"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + static void def_cmp_vector_blur(StructRNA *srna) { PropertyRNA *prop; @@ -4464,6 +4570,20 @@ static void rna_def_node_socket_subtype(BlenderRNA *brna, int type, int subtype, RNA_def_property_ui_text(prop, "Default Value", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update"); break; + case SOCK_STRING: + RNA_def_struct_sdna_from(srna, "bNodeSocketValueString", "default_value"); + + prop = RNA_def_property(srna, "subtype", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "subtype"); + RNA_def_property_enum_items(prop, subtype_items); + RNA_def_property_ui_text(prop, "Subtype", "Subtype defining the socket value details"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update"); + + prop = RNA_def_property(srna, "default_value", PROP_STRING, PROP_FILEPATH); + RNA_def_property_string_sdna(prop, NULL, "value"); + RNA_def_property_ui_text(prop, "Default Value", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update"); + break; } /* XXX need to reset the from-type here, so subtype subclasses cast correctly! (RNA bug) */ @@ -4531,18 +4651,22 @@ static void rna_def_node(BlenderRNA *brna) prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_SELECT); RNA_def_property_ui_text(prop, "Select", ""); + RNA_def_property_update(prop, NC_NODE | NA_SELECTED, NULL); prop = RNA_def_property(srna, "show_options", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_OPTIONS); RNA_def_property_ui_text(prop, "Show Options", ""); + RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL); prop = RNA_def_property(srna, "show_preview", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_PREVIEW); RNA_def_property_ui_text(prop, "Show Preview", ""); + RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL); prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_HIDDEN); RNA_def_property_ui_text(prop, "Hide", ""); + RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL); prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_MUTED); diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index c45c9b71442..14cdbc6cf7d 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -65,12 +65,14 @@ DefNode( ShaderNode, SH_NODE_LAYER_WEIGHT, 0, "LA DefNode( ShaderNode, SH_NODE_MIX_SHADER, 0, "MIX_SHADER", MixShader, "Mix Shader", "" ) DefNode( ShaderNode, SH_NODE_ADD_SHADER, 0, "ADD_SHADER", AddShader, "Add Shader", "" ) DefNode( ShaderNode, SH_NODE_ATTRIBUTE, def_sh_attribute, "ATTRIBUTE", Attribute, "Attribute", "" ) +DefNode( ShaderNode, SH_NODE_AMBIENT_OCCLUSION, 0, "AMBIENT_OCCLUSION", AmbientOcclusion, "Ambient Occlusion", "" ) DefNode( ShaderNode, SH_NODE_BACKGROUND, 0, "BACKGROUND", Background, "Background", "" ) DefNode( ShaderNode, SH_NODE_HOLDOUT, 0, "HOLDOUT", Holdout, "Holdout", "" ) DefNode( ShaderNode, SH_NODE_BSDF_ANISOTROPIC, 0, "BSDF_ANISOTROPIC", BsdfAnisotropic, "Anisotropic Bsdf", "" ) DefNode( ShaderNode, SH_NODE_BSDF_DIFFUSE, 0, "BSDF_DIFFUSE", BsdfDiffuse, "Diffuse Bsdf", "" ) DefNode( ShaderNode, SH_NODE_BSDF_GLOSSY, def_glossy, "BSDF_GLOSSY", BsdfGlossy, "Glossy Bsdf", "" ) DefNode( ShaderNode, SH_NODE_BSDF_GLASS, def_glossy, "BSDF_GLASS", BsdfGlass, "Glass Bsdf", "" ) +DefNode( ShaderNode, SH_NODE_BSDF_REFRACTION, def_glossy, "BSDF_REFRACTION", BsdfRefraction, "Refraction Bsdf", "" ) 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", "" ) @@ -82,7 +84,9 @@ DefNode( ShaderNode, SH_NODE_LIGHT_PATH, 0, "LI DefNode( ShaderNode, SH_NODE_LIGHT_FALLOFF, 0, "LIGHT_FALLOFF", LightFalloff, "Light Falloff", "" ) DefNode( ShaderNode, SH_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "" ) DefNode( ShaderNode, SH_NODE_PARTICLE_INFO, 0, "PARTICLE_INFO", ParticleInfo, "Particle Info", "" ) -DefNode( ShaderNode, SH_NODE_BUMP, 0, "BUMP", BumpNode, "Bump", "" ) +DefNode( ShaderNode, SH_NODE_BUMP, 0, "BUMP", Bump, "Bump", "" ) +DefNode( ShaderNode, SH_NODE_NORMAL_MAP, def_sh_normal_map, "NORMAL_MAP", NormalMap, "Normal Map", "" ) +DefNode( ShaderNode, SH_NODE_TANGENT, def_sh_tangent, "TANGENT", Tangent, "Tangent", "" ) DefNode( ShaderNode, SH_NODE_SCRIPT, def_sh_script, "SCRIPT", Script, "Script", "" ) DefNode( ShaderNode, SH_NODE_TEX_IMAGE, def_sh_tex_image, "TEX_IMAGE", TexImage, "Image Texture", "" ) DefNode( ShaderNode, SH_NODE_TEX_ENVIRONMENT, def_sh_tex_environment, "TEX_ENVIRONMENT", TexEnvironment, "Environment Texture","" ) @@ -110,6 +114,7 @@ DefNode( CompositorNode, CMP_NODE_ALPHAOVER, def_cmp_alpha_over, "ALPHA DefNode( CompositorNode, CMP_NODE_BLUR, def_cmp_blur, "BLUR", Blur, "Blur", "" ) DefNode( CompositorNode, CMP_NODE_FILTER, def_cmp_filter, "FILTER", Filter, "Filter", "" ) DefNode( CompositorNode, CMP_NODE_MAP_VALUE, def_cmp_map_value, "MAP_VALUE", MapValue, "Map Value", "" ) +DefNode( CompositorNode, CMP_NODE_MAP_RANGE, def_cmp_map_range, "MAP_RANGE", MapRange, "Map Range", "" ) DefNode( CompositorNode, CMP_NODE_TIME, def_time, "TIME", Time, "Time", "" ) DefNode( CompositorNode, CMP_NODE_VECBLUR, def_cmp_vector_blur, "VECBLUR", VecBlur, "Vector Blur", "" ) DefNode( CompositorNode, CMP_NODE_SEPRGBA, 0, "SEPRGBA", SepRGBA, "Separate RGBA", "" ) diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 10f361ef1bd..1d08ea97b79 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -94,6 +94,15 @@ static EnumPropertyItem parent_type_items[] = { {0, NULL, 0, NULL, NULL} }; +static EnumPropertyItem dupli_items[] = { + {0, "NONE", 0, "None", ""}, + {OB_DUPLIFRAMES, "FRAMES", 0, "Frames", "Make copy of object for every frame"}, + {OB_DUPLIVERTS, "VERTS", 0, "Verts", "Duplicate child objects on all vertices"}, + {OB_DUPLIFACES, "FACES", 0, "Faces", "Duplicate child objects on all faces"}, + {OB_DUPLIGROUP, "GROUP", 0, "Group", "Enable group instancing"}, + {0, NULL, 0, NULL, NULL} +}; + static EnumPropertyItem collision_bounds_items[] = { {OB_BOUND_BOX, "BOX", 0, "Box", ""}, {OB_BOUND_SPHERE, "SPHERE", 0, "Sphere", ""}, @@ -547,8 +556,7 @@ static void rna_Object_active_vertex_group_index_range(PointerRNA *ptr, int *min Object *ob = (Object *)ptr->id.data; *min = 0; - *max = BLI_countlist(&ob->defbase) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&ob->defbase) - 1); } void rna_object_vgroup_name_index_get(PointerRNA *ptr, char *value, int index) @@ -658,7 +666,7 @@ static void rna_Object_active_material_index_range(PointerRNA *ptr, int *min, in { Object *ob = (Object *)ptr->id.data; *min = 0; - *max = MAX2(ob->totcol - 1, 0); + *max = max_ii(ob->totcol - 1, 0); } /* returns active base material */ @@ -684,8 +692,7 @@ static void rna_Object_active_particle_system_index_range(PointerRNA *ptr, int * { Object *ob = (Object *)ptr->id.data; *min = 0; - *max = BLI_countlist(&ob->particlesystem) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&ob->particlesystem) - 1); } static int rna_Object_active_particle_system_index_get(PointerRNA *ptr) @@ -1421,6 +1428,12 @@ int rna_Camera_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value) return ((Object *)value.id.data)->type == OB_CAMERA; } +int rna_DupliObject_index_get(PointerRNA *ptr) +{ + DupliObject *dob = (DupliObject *)ptr->data; + return dob->persistent_id[0]; +} + #else static int rna_matrix_dimsize_4x4[] = {4, 4}; @@ -1639,21 +1652,23 @@ static void rna_def_object_game_settings(BlenderRNA *brna) RNA_def_property_range(prop, 0.0, 1000.0); RNA_def_property_ui_text(prop, "Velocity Max", "Clamp velocity to this maximum speed"); + /* Character physics */ prop = RNA_def_property(srna, "step_height", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "step_height"); - RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_range(prop, 0.01, 1.0); RNA_def_property_ui_text(prop, "Step Height", "Maximum height of steps the character can run over"); prop = RNA_def_property(srna, "jump_speed", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "jump_speed"); RNA_def_property_range(prop, 0.0, 1000.0); - RNA_def_property_ui_text(prop, "Jump Force", "Upward velocity applied to the character when jumping (with the Motion actuator)"); + RNA_def_property_ui_text(prop, "Jump Force", "Upward velocity applied to the character when jumping"); prop = RNA_def_property(srna, "fall_speed", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "fall_speed"); RNA_def_property_range(prop, 0.0, 1000.0); RNA_def_property_ui_text(prop, "Fall Speed Max", "Maximum speed at which the character will fall"); + /* Collision Masks */ prop = RNA_def_property(srna, "collision_group", PROP_BOOLEAN, PROP_LAYER_MEMBER); RNA_def_property_boolean_sdna(prop, NULL, "col_group", 1); RNA_def_property_array(prop, OB_MAX_COL_MASKS); @@ -2013,15 +2028,7 @@ static void rna_def_object(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; - static EnumPropertyItem dupli_items[] = { - {0, "NONE", 0, "None", ""}, - {OB_DUPLIFRAMES, "FRAMES", 0, "Frames", "Make copy of object for every frame"}, - {OB_DUPLIVERTS, "VERTS", 0, "Verts", "Duplicate child objects on all vertices"}, - {OB_DUPLIFACES, "FACES", 0, "Faces", "Duplicate child objects on all faces"}, - {OB_DUPLIGROUP, "GROUP", 0, "Group", "Enable group instancing"}, - {0, NULL, 0, NULL, NULL} - }; - + /* XXX: this RNA enum define is currently duplicated for objects, * since there is some text here which is not applicable */ static EnumPropertyItem prop_rotmode_items[] = { @@ -2168,7 +2175,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_int_funcs(prop, "rna_Object_active_material_index_get", "rna_Object_active_material_index_set", "rna_Object_active_material_index_range"); RNA_def_property_ui_text(prop, "Active Material Index", "Index of active material slot"); - RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, NULL); + RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, NULL); /* transform */ prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_TRANSLATION); @@ -2655,25 +2662,31 @@ static void rna_def_dupli_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Hide", "Don't show dupli object in viewport or render"); prop = RNA_def_property(srna, "index", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "index"); + RNA_def_property_int_funcs(prop, "rna_DupliObject_index_get", NULL, NULL); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); RNA_def_property_ui_text(prop, "Index", "Index in the lowest-level dupli list"); - - prop = RNA_def_property(srna, "particle_index", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "particle_index"); + + prop = RNA_def_property(srna, "persistent_id", PROP_INT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Particle Index", "Index in the lowest-level particle dupli list"); + RNA_def_property_ui_text(prop, "Persistent ID", "Persistent identifier for inter-frame matching of objects with motion blur"); + + prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Particle System", "Particle system that this dupli object was instanced from"); prop = RNA_def_property(srna, "orco", PROP_FLOAT, PROP_TRANSLATION); - RNA_def_property_float_sdna(prop, NULL, "orco"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); RNA_def_property_ui_text(prop, "Generated Coordinates", "Generated coordinates in parent object space"); prop = RNA_def_property(srna, "uv", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "uv"); RNA_def_property_array(prop, 2); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); RNA_def_property_ui_text(prop, "UV Coordinates", "UV coordinates in parent object space"); + + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, dupli_items); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Dupli Type", "Duplicator type that generated this dupli object"); } static void rna_def_object_base(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index f47b864d25a..6d7187da7d9 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -51,6 +51,9 @@ static EnumPropertyItem effector_shape_items[] = { #ifdef RNA_RUNTIME +#include "BLI_math_base.h" + + /* type specific return values only used from functions */ static EnumPropertyItem curve_shape_items[] = { {PFIELD_SHAPE_POINT, "POINT", 0, "Point", ""}, @@ -239,8 +242,7 @@ static void rna_Cache_active_point_cache_index_range(PointerRNA *ptr, int *min, for (pid = pidlist.first; pid; pid = pid->next) { if (pid->cache == cache) { - *max = BLI_countlist(pid->ptcaches) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(pid->ptcaches) - 1); break; } } diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 9ba2a062791..6825d3d781d 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -530,8 +530,7 @@ static void rna_ParticleSystem_active_particle_target_index_range(PointerRNA *pt { ParticleSystem *psys = (ParticleSystem *)ptr->data; *min = 0; - *max = BLI_countlist(&psys->targets) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&psys->targets) - 1); } static int rna_ParticleSystem_active_particle_target_index_get(PointerRNA *ptr) @@ -670,8 +669,7 @@ static void rna_ParticleDupliWeight_active_index_range(PointerRNA *ptr, int *min { ParticleSettings *part = (ParticleSettings *)ptr->id.data; *min = 0; - *max = BLI_countlist(&part->dupliweights) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&part->dupliweights) - 1); } static int rna_ParticleDupliWeight_active_index_get(PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index c29537378dd..5c90fb8787c 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -381,13 +381,7 @@ static void rna_PoseChannel_bone_group_index_range(PointerRNA *ptr, int *min, in bPose *pose = (ob) ? ob->pose : NULL; *min = 0; - - if (pose) { - *max = BLI_countlist(&pose->agroups) - 1; - *max = MAX2(0, *max); - } - else - *max = 0; + *max = pose ? max_ii(0, BLI_countlist(&pose->agroups) - 1) : 0; } static PointerRNA rna_Pose_active_bone_group_get(PointerRNA *ptr) @@ -419,8 +413,7 @@ static void rna_Pose_active_bone_group_index_range(PointerRNA *ptr, int *min, in bPose *pose = (bPose *)ptr->data; *min = 0; - *max = BLI_countlist(&pose->agroups) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&pose->agroups) - 1); } #if 0 @@ -682,7 +675,7 @@ static void rna_def_bone_group(BlenderRNA *brna) } static EnumPropertyItem prop_iksolver_items[] = { - {IKSOLVER_LEGACY, "LEGACY", 0, "Legacy", "Original IK solver"}, + {IKSOLVER_STANDARD, "LEGACY", 0, "Standard", "Original IK solver"}, {IKSOLVER_ITASC, "ITASC", 0, "iTaSC", "Multi constraint, stateful IK solver"}, {0, NULL, 0, NULL, NULL} }; @@ -1133,7 +1126,7 @@ static void rna_def_pose_itasc(BlenderRNA *brna) prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "numiter"); - RNA_def_property_range(prop, 1.f, 1000.f); + RNA_def_property_range(prop, 0, 1000); RNA_def_property_ui_text(prop, "Iterations", "Maximum number of iterations for convergence in case of reiteration"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Itasc_update"); @@ -1228,8 +1221,7 @@ static void rna_def_pose_ikparam(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "iksolver"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_enum_items(prop, prop_iksolver_items); - RNA_def_property_ui_text(prop, "IK Solver", - "IK solver for which these parameters are defined, 0 for Legacy, 1 for iTaSC"); + RNA_def_property_ui_text(prop, "IK Solver", "IK solver for which these parameters are defined"); } /* pose.bone_groups */ @@ -1292,8 +1284,7 @@ static void rna_def_pose(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "iksolver"); RNA_def_property_enum_funcs(prop, NULL, "rna_Pose_ik_solver_set", NULL); RNA_def_property_enum_items(prop, prop_iksolver_items); - RNA_def_property_ui_text(prop, "IK Solver", - "Selection of IK solver for IK chain, current choice is 0 for Legacy, 1 for iTaSC"); + RNA_def_property_ui_text(prop, "IK Solver", "Selection of IK solver for IK chain"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_ik_solver_update"); prop = RNA_def_property(srna, "ik_param", PROP_POINTER, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 69bb1cc98ff..6f3a483cf7e 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -145,6 +145,11 @@ EnumPropertyItem snap_node_element_items[] = { {0, NULL, 0, NULL, NULL} }; +EnumPropertyItem snap_uv_element_items[] = { + {SCE_SNAP_MODE_INCREMENT, "INCREMENT", ICON_SNAP_INCREMENT, "Increment", "Snap to increments of grid"}, + {SCE_SNAP_MODE_VERTEX, "VERTEX", ICON_SNAP_VERTEX, "Vertex", "Snap to vertices"}, + {0, NULL, 0, NULL, NULL} +}; /* workaround for duplicate enums, * have each enum line as a defne then conditionally set it or not @@ -1002,8 +1007,7 @@ static void rna_RenderSettings_active_layer_index_range(PointerRNA *ptr, int *mi RenderData *rd = (RenderData *)ptr->data; *min = 0; - *max = BLI_countlist(&rd->layers) - 1; - *max = MAX2(0, *max); + *max = max_ii(0, BLI_countlist(&rd->layers) - 1); } static PointerRNA rna_RenderSettings_active_layer_get(PointerRNA *ptr) @@ -1124,6 +1128,12 @@ static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value) } } +static char *rna_SceneRenderLayer_path(PointerRNA *ptr) +{ + SceneRenderLayer *srl = (SceneRenderLayer*)ptr->data; + return BLI_sprintfN("render.layers[\"%s\"]", srl->name); +} + static int rna_RenderSettings_multiple_engines_get(PointerRNA *UNUSED(ptr)) { return (BLI_countlist(&R_engines) > 1); @@ -1255,6 +1265,12 @@ static void rna_Scene_simplify_update(Main *bmain, Scene *scene, PointerRNA *ptr rna_Scene_use_simplify_update(bmain, scene, ptr); } +static void rna_Scene_use_persistent_data_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr)) +{ + if (!(scene->r.mode & R_PERSISTENT_DATA)) + RE_FreePersistentData(); +} + static int rna_Scene_use_audio_get(PointerRNA *ptr) { Scene *scene = (Scene *)ptr->data; @@ -1631,6 +1647,13 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_enum_items(prop, snap_node_element_items); RNA_def_property_ui_text(prop, "Snap Node Element", "Type of element to snap to"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + + /* image editor uses own set of snap modes */ + prop = RNA_def_property(srna, "snap_uv_element", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "snap_uv_mode"); + RNA_def_property_enum_items(prop, snap_uv_element_items); + RNA_def_property_ui_text(prop, "Snap UV Element", "Type of element to snap to"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ prop = RNA_def_property(srna, "snap_target", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "snap_target"); @@ -2770,6 +2793,7 @@ static void rna_def_scene_render_layer(BlenderRNA *brna) srna = RNA_def_struct(brna, "SceneRenderLayer", NULL); RNA_def_struct_ui_text(srna, "Scene Render Layer", "Render layer"); RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS); + RNA_def_struct_path_func(srna, "rna_SceneRenderLayer_path"); rna_def_render_layer_common(srna, 1); } @@ -3126,7 +3150,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Volume", "Audio volume"); - RNA_def_property_translation_context(prop, "Audio"); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); #endif @@ -3949,6 +3973,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop = RNA_def_property(srna, "use_sequencer_gl_preview", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "seq_flag", R_SEQ_GL_PREV); RNA_def_property_ui_text(prop, "Sequencer OpenGL", ""); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SceneSequencer_update"); #if 0 /* see R_SEQ_GL_REND comment */ prop = RNA_def_property(srna, "use_sequencer_gl_render", PROP_BOOLEAN, PROP_NONE); @@ -4037,6 +4062,12 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "simplify_flag", R_SIMPLE_NO_TRIANGULATE); RNA_def_property_ui_text(prop, "Skip Quad to Triangles", "Disable non-planar quads being triangulated"); + /* persistent data */ + prop = RNA_def_property(srna, "use_persistent_data", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "mode", R_PERSISTENT_DATA); + RNA_def_property_ui_text(prop, "Persistent Data", "Keep render data around for faster re-renders"); + RNA_def_property_update(prop, 0, "rna_Scene_use_persistent_data_update"); + /* Scene API */ RNA_api_scene_render(srna); } @@ -4541,7 +4572,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "audio.volume"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Volume", "Audio volume"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); RNA_def_property_update(prop, NC_SCENE, NULL); RNA_def_property_float_funcs(prop, NULL, "rna_Scene_volume_set", NULL); diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 63253153699..012767b5845 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -62,12 +62,16 @@ static void rna_Scene_frame_set(Scene *scene, int frame, float subframe) BKE_scene_update_for_newframe(G.main, scene, (1 << 20) - 1); BKE_scene_camera_switch_update(scene); - /* cant use NC_SCENE|ND_FRAME because this causes wm_event_do_notifiers to call - * BKE_scene_update_for_newframe which will loose any un-keyed changes [#24690] */ - /* WM_main_add_notifier(NC_SCENE|ND_FRAME, scene); */ - - /* instead just redraw the views */ - WM_main_add_notifier(NC_WINDOW, NULL); + /* don't do notifier when we're rendering, avoid some viewport crashes + * redrawing while the data is being modified for render */ + if (!G.is_rendering) { + /* cant use NC_SCENE|ND_FRAME because this causes wm_event_do_notifiers to call + * BKE_scene_update_for_newframe which will loose any un-keyed changes [#24690] */ + /* WM_main_add_notifier(NC_SCENE|ND_FRAME, scene); */ + + /* instead just redraw the views */ + WM_main_add_notifier(NC_WINDOW, NULL); + } } static void rna_Scene_update_tagged(Scene *scene) diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index c2fa64698e4..18a9b9683f8 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -1875,7 +1875,7 @@ static void rna_def_sound(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "volume"); RNA_def_property_range(prop, 0.0f, 100.0f); RNA_def_property_ui_text(prop, "Volume", "Playback volume of the sound"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_volume_set", NULL); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); @@ -1883,7 +1883,7 @@ static void rna_def_sound(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "pitch"); RNA_def_property_range(prop, 0.1f, 10.0f); RNA_def_property_ui_text(prop, "Pitch", "Playback pitch of the sound"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_pitch_set", NULL); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 962a92223eb..2b2e8d97499 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -598,7 +598,7 @@ static EnumPropertyItem *rna_SpaceImageEditor_draw_channels_itemf(bContext *UNUS alpha = ibuf && (ibuf->channels == 4); zbuf = ibuf && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1)); - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); if (alpha && zbuf) return draw_channels_items; @@ -678,7 +678,7 @@ static void rna_SpaceImageEditor_scopes_update(Main *UNUSED(bmain), Scene *scene scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings); WM_main_add_notifier(NC_IMAGE, sima->image); } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); } /* Space Text Editor */ @@ -2976,10 +2976,9 @@ static void rna_def_space_node(BlenderRNA *brna) {SNODE_USE_ALPHA, "COLOR_ALPHA", ICON_IMAGE_RGB_ALPHA, "Color and Alpha", "Draw image with RGB colors and alpha transparency"}, {SNODE_SHOW_ALPHA, "ALPHA", ICON_IMAGE_ALPHA, "Alpha", "Draw alpha transparency channel"}, - /* XXX, we could use better icons here */ - {SNODE_SHOW_R, "RED", ICON_COLOR, "Red", ""}, - {SNODE_SHOW_G, "GREEN", ICON_COLOR, "Green", ""}, - {SNODE_SHOW_B, "BLUE", ICON_COLOR, "Blue", ""}, + {SNODE_SHOW_R, "RED", ICON_COLOR_RED, "Red", ""}, + {SNODE_SHOW_G, "GREEN", ICON_COLOR_GREEN, "Green", ""}, + {SNODE_SHOW_B, "BLUE", ICON_COLOR_BLUE, "Blue", ""}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_speaker.c b/source/blender/makesrna/intern/rna_speaker.c index a160aaf94e2..139582104ee 100644 --- a/source/blender/makesrna/intern/rna_speaker.c +++ b/source/blender/makesrna/intern/rna_speaker.c @@ -152,7 +152,7 @@ static void rna_def_speaker(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "volume"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Volume", "How loud the sound is"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_volume_set", NULL); */ /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */ @@ -160,7 +160,7 @@ static void rna_def_speaker(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "pitch"); RNA_def_property_range(prop, 0.1f, 10.0f); RNA_def_property_ui_text(prop, "Pitch", "Playback pitch of the sound"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_pitch_set", NULL); */ /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */ diff --git a/source/blender/makesrna/intern/rna_text.c b/source/blender/makesrna/intern/rna_text.c index e46373b250c..b1637ef4c8a 100644 --- a/source/blender/makesrna/intern/rna_text.c +++ b/source/blender/makesrna/intern/rna_text.c @@ -129,49 +129,6 @@ static void rna_def_text_line(BlenderRNA *brna) RNA_def_property_update(prop, NC_TEXT | NA_EDITED, NULL); } -static void rna_def_text_marker(BlenderRNA *brna) -{ - StructRNA *srna; - PropertyRNA *prop; - - srna = RNA_def_struct(brna, "TextMarker", NULL); - RNA_def_struct_ui_text(srna, "Text Marker", "Marker highlighting a portion of text in a Text datablock"); - - prop = RNA_def_property(srna, "line", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "lineno"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Line", "Line in which the marker is located"); - - prop = RNA_def_property(srna, "character_index_start", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "start"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Start", "Start position of the marker in the line"); - - prop = RNA_def_property(srna, "character_index_end", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "end"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "End", "Start position of the marker in the line"); - - prop = RNA_def_property(srna, "group", PROP_INT, PROP_UNSIGNED); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_range(prop, 0, (int)0xFFFF); - RNA_def_property_ui_text(prop, "Group", ""); - - prop = RNA_def_property(srna, "is_temporary", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flags", TMARK_TEMP); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Temporary", "Marker is temporary"); - - prop = RNA_def_property(srna, "use_edit_all", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flags", TMARK_EDITALL); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Edit All", "Edit all markers of the same group as one"); - - prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA); - RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_text(prop, "Color", "Color to display the marker with"); -} - static void rna_def_text(BlenderRNA *brna) { StructRNA *srna; @@ -241,17 +198,12 @@ static void rna_def_text(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Selection End Character", "Index of character after end of selection in the selection end line"); - prop = RNA_def_property(srna, "markers", PROP_COLLECTION, PROP_NONE); - RNA_def_property_struct_type(prop, "TextMarker"); - RNA_def_property_ui_text(prop, "Markers", "Text markers highlighting part of the text"); - RNA_api_text(srna); } void RNA_def_text(BlenderRNA *brna) { rna_def_text_line(brna); - rna_def_text_marker(brna); rna_def_text(brna); } diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index e77c5d13a6b..bdf9fa4e436 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -46,6 +46,9 @@ #include "BKE_node.h" +#include "WM_api.h" +#include "WM_types.h" + EnumPropertyItem texture_filter_items[] = { {TXF_BOX, "BOX", 0, "Box", ""}, {TXF_EWA, "EWA", 0, "EWA", ""}, @@ -110,9 +113,6 @@ EnumPropertyItem blend_type_items[] = { #include "ED_node.h" -#include "WM_api.h" -#include "WM_types.h" - static StructRNA *rna_Texture_refine(struct PointerRNA *ptr) { Tex *tex = (Tex *)ptr->data; @@ -233,6 +233,7 @@ void rna_TextureSlot_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRN break; case ID_LA: WM_main_add_notifier(NC_LAMP | ND_LIGHTING, id); + WM_main_add_notifier(NC_LAMP | ND_LIGHTING_DRAW, id); break; case ID_BR: WM_main_add_notifier(NC_BRUSH, id); @@ -263,19 +264,24 @@ char *rna_TextureSlot_path(PointerRNA *ptr) * may be used multiple times in the same stack */ if (ptr->id.data) { - PointerRNA id_ptr; - PropertyRNA *prop; - - /* find the 'textures' property of the ID-struct */ - RNA_id_pointer_create(ptr->id.data, &id_ptr); - prop = RNA_struct_find_property(&id_ptr, "texture_slots"); - - /* get an iterator for this property, and try to find the relevant index */ - if (prop) { - int index = RNA_property_collection_lookup_index(&id_ptr, prop, ptr); - - if (index >= 0) - return BLI_sprintfN("texture_slots[%d]", index); + if (GS(((ID *)ptr->id.data)->name) == ID_BR) { + return BLI_strdup("texture_slot"); + } + else { + PointerRNA id_ptr; + PropertyRNA *prop; + + /* find the 'textures' property of the ID-struct */ + RNA_id_pointer_create(ptr->id.data, &id_ptr); + prop = RNA_struct_find_property(&id_ptr, "texture_slots"); + + /* get an iterator for this property, and try to find the relevant index */ + if (prop) { + int index = RNA_property_collection_lookup_index(&id_ptr, prop, ptr); + + if (index >= 0) + return BLI_sprintfN("texture_slots[%d]", index); + } } } @@ -602,7 +608,7 @@ static void rna_def_mtex(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Texture"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Texture", "Texture datablock used by this texture slot"); - RNA_def_property_update(prop, 0, "rna_TextureSlot_update"); + RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, "rna_TextureSlot_update"); prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, "rna_TextureSlot_name_get", "rna_TextureSlot_name_length", NULL); diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 51b50f78e66..4aefaf991d2 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -120,8 +120,7 @@ static void rna_tracking_active_object_index_range(PointerRNA *ptr, int *min, in MovieClip *clip = (MovieClip *)ptr->id.data; *min = 0; - *max = clip->tracking.tot_object - 1; - *max = MAX2(0, *max); + *max = max_ii(0, clip->tracking.tot_object - 1); } static PointerRNA rna_tracking_active_track_get(PointerRNA *ptr) @@ -263,8 +262,7 @@ static void rna_tracking_stabTracks_active_index_range(PointerRNA *ptr, int *min MovieClip *clip = (MovieClip *)ptr->id.data; *min = 0; - *max = clip->tracking.stabilization.tot_track - 1; - *max = MAX2(0, *max); + *max = max_ii(0, clip->tracking.stabilization.tot_track - 1); } static void rna_tracking_flushUpdate(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) @@ -452,7 +450,7 @@ static void rna_trackingObject_remove(MovieTracking *tracking, ReportList *repor { MovieTrackingObject *object = object_ptr->data; if (BKE_tracking_object_delete(tracking, object) == FALSE) { - BKE_reportf(reports, RPT_ERROR, "MovieTracking '%s' can't be removed", object->name); + BKE_reportf(reports, RPT_ERROR, "MovieTracking '%s' cannot be removed", object->name); return; } @@ -579,13 +577,16 @@ static void rna_def_trackingSettings(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_float_default(prop, 0.001f); RNA_def_property_range(prop, 0, FLT_MAX); - RNA_def_property_ui_text(prop, "Success Threshold", "Threshold value of reconstruction error which is still considered successful"); + RNA_def_property_ui_text(prop, "Success Threshold", + "Threshold value of reconstruction error which is still considered successful"); /* use fallback reconstruction */ prop = RNA_def_property(srna, "use_fallback_reconstruction", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_boolean_sdna(prop, NULL, "reconstruction_flag", TRACKING_USE_FALLBACK_RECONSTRUCTION); - RNA_def_property_ui_text(prop, "Use Fallback", "Use fallback reconstruction algorithm in cases main reconstruction algorithm failed. Could give better solution with bad tracks"); + RNA_def_property_ui_text(prop, "Use Fallback", + "Use fallback reconstruction algorithm in cases main reconstruction algorithm failed " + "(could give better solution with bad tracks)"); /* intrinsics refinement during bundle adjustment */ prop = RNA_def_property(srna, "refine_intrinsics", PROP_ENUM, PROP_NONE); @@ -636,7 +637,8 @@ static void rna_def_trackingSettings(BlenderRNA *brna) prop = RNA_def_property(srna, "use_tripod_solver", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_boolean_sdna(prop, NULL, "motion_flag", TRACKING_MOTION_TRIPOD); - RNA_def_property_ui_text(prop, "Tripod Motion", "Use special solver to track a stable camera position, such as a tripod"); + RNA_def_property_ui_text(prop, "Tripod Motion", + "Use special solver to track a stable camera position, such as a tripod"); /* default_limit_frames */ prop = RNA_def_property(srna, "default_frames_limit", PROP_INT, PROP_NONE); @@ -676,7 +678,9 @@ static void rna_def_trackingSettings(BlenderRNA *brna) /* default_use_brute */ prop = RNA_def_property(srna, "use_default_mask", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "default_algorithm_flag", TRACK_ALGORITHM_FLAG_USE_MASK); - RNA_def_property_ui_text(prop, "Use Mask", "Use a grease pencil datablock as a mask to use only specified areas of pattern when tracking"); + RNA_def_property_ui_text(prop, "Use Mask", + "Use a grease pencil datablock as a mask to use only specified areas of pattern " + "when tracking"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); /* default_use_normalization */ @@ -1013,7 +1017,9 @@ static void rna_def_trackingTrack(BlenderRNA *brna) /* use_brute */ prop = RNA_def_property(srna, "use_mask", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "algorithm_flag", TRACK_ALGORITHM_FLAG_USE_MASK); - RNA_def_property_ui_text(prop, "Use Mask", "Use a grease pencil datablock as a mask to use only specified areas of pattern when tracking"); + RNA_def_property_ui_text(prop, "Use Mask", + "Use a grease pencil datablock as a mask to use only specified areas of pattern " + "when tracking"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); /* use_normalization */ @@ -1460,7 +1466,8 @@ static void rna_def_trackingDopesheet(BlenderRNA *brna) {TRACKING_DOPE_SORT_NAME, "NAME", 0, "Name", "Sort channels by their names"}, {TRACKING_DOPE_SORT_LONGEST, "LONGEST", 0, "Longest", "Sort channels by longest tracked segment"}, {TRACKING_DOPE_SORT_TOTAL, "TOTAL", 0, "Total", "Sort channels by overall amount of tracked segments"}, - {TRACKING_DOPE_SORT_AVERAGE_ERROR, "AVERAGE_ERROR", 0, "Average Error", "Sort channels by average reprojection error of tracks after solve"}, + {TRACKING_DOPE_SORT_AVERAGE_ERROR, "AVERAGE_ERROR", 0, "Average Error", + "Sort channels by average reprojection error of tracks after solve"}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 2a8f1b90d4e..548539e3395 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -390,7 +390,7 @@ void RNA_api_ui_layout(StructRNA *srna) parm = RNA_def_int(func, "active_layer", 0, 0, INT_MAX, "Active Layer", "", 0, INT_MAX); RNA_def_property_flag(parm, PROP_REQUIRED); - func = RNA_def_function(srna, "template_color_wheel", "uiTemplateColorWheel"); + func = RNA_def_function(srna, "template_color_picker", "uiTemplateColorPicker"); RNA_def_function_ui_description(func, "Item. A color wheel widget to pick colors"); api_ui_item_rna_common(func); RNA_def_boolean(func, "value_slider", 0, "", "Display the value slider to the right of the color wheel"); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 415d5308d85..7be34c398ae 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -395,7 +395,7 @@ static EnumPropertyItem *rna_userdef_compute_device_itemf(bContext *UNUSED(C), P int a; if (devices) { - for (a = 0; devices[a].name; a++) { + for (a = 0; devices[a].identifier[0]; a++) { tmp.value = devices[a].value; tmp.identifier = devices[a].identifier; tmp.name = devices[a].name; @@ -770,6 +770,25 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna) prop = RNA_def_property(srna, "icon_alpha", PROP_FLOAT, PROP_FACTOR); RNA_def_property_ui_text(prop, "Icon Alpha", "Transparency of icons in the interface, to reduce contrast"); RNA_def_property_update(prop, 0, "rna_userdef_update"); + + /* axis */ + prop = RNA_def_property(srna, "axis_x", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "xaxis"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "X Axis", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "axis_y", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "yaxis"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Y Axis", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "axis_z", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "zaxis"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Z Axis", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); } static void rna_def_userdef_theme_space_generic(BlenderRNA *brna) @@ -2999,6 +3018,15 @@ static void rna_def_userdef_system(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem multi_sample_levels[] = { + {USER_MULTISAMPLE_NONE, "NONE", 0, "No MultiSample", "Do not use OpenGL MultiSample"}, + {USER_MULTISAMPLE_2, "2", 0, "MultiSample: 2", "Use 2x OpenGL MultiSample (requires restart)"}, + {USER_MULTISAMPLE_4, "4", 0, "MultiSample: 4", "Use 4x OpenGL MultiSample (requires restart)"}, + {USER_MULTISAMPLE_8, "8", 0, "MultiSample: 8", "Use 8x OpenGL MultiSample (requires restart)"}, + {USER_MULTISAMPLE_16, "16", 0, "MultiSample: 16", "Use 16x OpenGL MultiSample (requires restart)"}, + {0, NULL, 0, NULL, NULL} + }; + #if 0 /* hardcoded here, could become dynamic somehow */ /* locale according to http://www.roseindia.net/tutorials/I18N/locales-list.shtml */ @@ -3143,6 +3171,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_enum_items(prop, color_picker_types); RNA_def_property_enum_sdna(prop, NULL, "color_picker_type"); RNA_def_property_ui_text(prop, "Color Picker Type", "Different styles of displaying the color picker widget"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); prop = RNA_def_property(srna, "use_preview_images", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ALLWINCODECS); @@ -3207,10 +3236,12 @@ static void rna_def_userdef_system(BlenderRNA *brna) /* this isn't essential but nice to check if VBO draws any differently */ RNA_def_property_update(prop, NC_WINDOW, NULL); +#if 0 prop = RNA_def_property(srna, "use_antialiasing", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_AA); RNA_def_property_ui_text(prop, "Anti-aliasing", "Use anti-aliasing for the 3D view (may impact redraw performance)"); +#endif prop = RNA_def_property(srna, "anisotropic_filter", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "anisotropic_filter"); @@ -3292,6 +3323,12 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Text Anti-aliasing", "Draw user interface text anti-aliased"); RNA_def_property_update(prop, 0, "rna_userdef_text_update"); + /* Full scene anti-aliasing */ + prop = RNA_def_property(srna, "multi_sample", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "ogl_multisamples"); + RNA_def_property_enum_items(prop, multi_sample_levels); + RNA_def_property_ui_text(prop, "MultiSample", "Enable OpenGL multi-sampling, only for systems that support it, requires restart"); + #ifdef WITH_CYCLES prop = RNA_def_property(srna, "compute_device_type", PROP_ENUM, PROP_NONE); RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT); @@ -3421,10 +3458,10 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_SHOW_GUIDE); RNA_def_property_ui_text(prop, "Show Navigation Guide", "Display the center and axis during rotation"); /* TODO: update description when fly-mode visuals are in place ("projected position in fly mode")*/ - + /* 3D view */ prop = RNA_def_property(srna, "ndof_view_rotate_method", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "ndof_flag"); RNA_def_property_enum_items(prop, ndof_view_rotation_items); RNA_def_property_ui_text(prop, "NDOF View Rotation", "Rotation style in the viewport"); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index e5f44644f7a..f83410e7cc1 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -555,7 +555,7 @@ static void rna_Window_screen_set(PointerRNA *ptr, PointerRNA value) if (value.data == NULL) return; - /* exception: can't set screens inside of area/region handers */ + /* exception: can't set screens inside of area/region handlers */ win->newscreen = value.data; } @@ -563,8 +563,8 @@ static void rna_Window_screen_update(bContext *C, PointerRNA *ptr) { wmWindow *win = (wmWindow *)ptr->data; - /* exception: can't set screens inside of area/region handers, and must - * use context so notifier gets to the right window */ + /* exception: can't set screens inside of area/region handlers, + * and must use context so notifier gets to the right window */ if (win->newscreen) { WM_event_add_notifier(C, NC_SCREEN | ND_SCREENBROWSE, win->newscreen); win->newscreen = NULL; diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index 116e07073cd..b7895cc0e2d 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -158,7 +158,7 @@ static void rna_KeyMap_item_remove(wmKeyMap *km, ReportList *reports, PointerRNA wmKeyMapItem *kmi = kmi_ptr->data; if (WM_keymap_remove_item(km, kmi) == FALSE) { - BKE_reportf(reports, RPT_ERROR, "KeyMapItem '%s' can't be removed from '%s'", kmi->idname, km->idname); + BKE_reportf(reports, RPT_ERROR, "KeyMapItem '%s' cannot be removed from '%s'", kmi->idname, km->idname); return; } @@ -195,7 +195,7 @@ static void rna_KeyConfig_remove(wmWindowManager *wm, ReportList *reports, Point wmKeyConfig *keyconf = keyconf_ptr->data; if (WM_keyconfig_remove(wm, keyconf) == FALSE) { - BKE_reportf(reports, RPT_ERROR, "KeyConfig '%s' can't be removed", keyconf->idname); + BKE_reportf(reports, RPT_ERROR, "KeyConfig '%s' cannot be removed", keyconf->idname); return; } diff --git a/source/blender/makesrna/rna_cleanup/rna_cleaner.py b/source/blender/makesrna/rna_cleanup/rna_cleaner.py index 0231e57fcfd..8b4b10c490e 100755 --- a/source/blender/makesrna/rna_cleanup/rna_cleaner.py +++ b/source/blender/makesrna/rna_cleanup/rna_cleaner.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 """ This script is used to help cleaning RNA api. diff --git a/source/blender/makesrna/rna_cleanup/rna_cleaner_merge.py b/source/blender/makesrna/rna_cleanup/rna_cleaner_merge.py index 75851105991..17ea5f9b0bd 100755 --- a/source/blender/makesrna/rna_cleanup/rna_cleaner_merge.py +++ b/source/blender/makesrna/rna_cleanup/rna_cleaner_merge.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.2 +#!/usr/bin/env python3 import sys diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 3a7066ff41a..cf3bb05849a 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -94,6 +94,7 @@ set(SRC intern/MOD_weightvgedit.c intern/MOD_weightvgmix.c intern/MOD_weightvgproximity.c + intern/MOD_triangulate.c MOD_modifiertypes.h intern/MOD_boolean_util.h diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h index a4817ff775d..290ba193567 100644 --- a/source/blender/modifiers/MOD_modifiertypes.h +++ b/source/blender/modifiers/MOD_modifiertypes.h @@ -76,6 +76,7 @@ extern ModifierTypeInfo modifierType_DynamicPaint; extern ModifierTypeInfo modifierType_Remesh; extern ModifierTypeInfo modifierType_Skin; extern ModifierTypeInfo modifierType_LaplacianSmooth; +extern ModifierTypeInfo modifierType_Triangulate; /* MOD_util.c */ void modifier_type_init(ModifierTypeInfo *types[]); diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 7219038b087..7ab3a5df531 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -58,7 +58,7 @@ static void initData(ModifierData *md) { ArmatureModifierData *amd = (ArmatureModifierData *) md; - amd->deformflag = ARM_DEF_ENVELOPE | ARM_DEF_VGROUP; + amd->deformflag = ARM_DEF_VGROUP; } static void copyData(ModifierData *md, ModifierData *target) diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index b9dd37ac50c..3ca2c364345 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -178,14 +178,14 @@ static int *find_doubles_index_map(BMesh *bm, BMOperator *dupe_op, amd->merge_dist, dupe_op, "geom"); BMO_op_exec(bm, &find_op); - + i = 0; - BMO_ITER (ele, &oiter, bm, dupe_op, "geom", BM_ALL) { + BMO_ITER (ele, &oiter, dupe_op->slots_in, "geom", BM_ALL) { BM_elem_index_set(ele, i); /* set_dirty */ i++; } - BMO_ITER (ele, &oiter, bm, dupe_op, "newout", BM_ALL) { + BMO_ITER (ele, &oiter, dupe_op->slots_out, "geom.out", BM_ALL) { BM_elem_index_set(ele, i); /* set_dirty */ i++; } @@ -197,7 +197,7 @@ static int *find_doubles_index_map(BMesh *bm, BMOperator *dupe_op, index_map = MEM_callocN(sizeof(int) * (*index_map_length), "index_map"); /*element type argument doesn't do anything here*/ - BMO_ITER (v, &oiter, bm, &find_op, "targetmapout", 0) { + BMO_ITER (v, &oiter, find_op.slots_out, "targetmap.out", 0) { v2 = BMO_iter_map_value_p(&oiter); index_map[BM_elem_index_get(v)] = BM_elem_index_get(v2) + 1; @@ -218,9 +218,10 @@ static int *find_doubles_index_map(BMesh *bm, BMOperator *dupe_op, static void bm_merge_dm_transform(BMesh *bm, DerivedMesh *dm, float mat[4][4], const ArrayModifierData *amd, BMOperator *dupe_op, - const char *dupe_slot_name, + BMOpSlot dupe_op_slot_args[BMO_OP_MAX_SLOTS], const char *dupe_slot_name, BMOperator *weld_op) { + const int is_input = (dupe_op->slots_in == dupe_op_slot_args); BMVert *v, *v2, *v3; BMIter iter; @@ -234,14 +235,27 @@ static void bm_merge_dm_transform(BMesh *bm, DerivedMesh *dm, float mat[4][4], BMOIter oiter; BMOperator find_op; + BMOpSlot *slot_targetmap; BMO_op_initf(bm, &find_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), - "find_doubles verts=%Hv dist=%f keep_verts=%s", + is_input ? /* ugh */ + "find_doubles verts=%Hv dist=%f keep_verts=%s" : + "find_doubles verts=%Hv dist=%f keep_verts=%S", BM_ELEM_TAG, amd->merge_dist, dupe_op, dupe_slot_name); /* append the dupe's geom to the findop input verts */ - BMO_slot_buffer_append(&find_op, "verts", dupe_op, dupe_slot_name); + if (is_input) { + BMO_slot_buffer_append(&find_op, slots_in, "verts", + dupe_op, slots_in, dupe_slot_name); + } + else if (dupe_op->slots_out == dupe_op_slot_args) { + BMO_slot_buffer_append(&find_op, slots_in, "verts", + dupe_op, slots_out, dupe_slot_name); + } + else { + BLI_assert(0); + } /* transform and tag verts */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { @@ -253,15 +267,17 @@ static void bm_merge_dm_transform(BMesh *bm, DerivedMesh *dm, float mat[4][4], BMO_op_exec(bm, &find_op); + slot_targetmap = BMO_slot_get(weld_op->slots_in, "targetmap"); + /* add new merge targets to weld operator */ - BMO_ITER (v, &oiter, bm, &find_op, "targetmapout", 0) { + BMO_ITER (v, &oiter, find_op.slots_out, "targetmap.out", 0) { v2 = BMO_iter_map_value_p(&oiter); /* check in case the target vertex (v2) is already marked * for merging */ - while ((v3 = BMO_slot_map_ptr_get(bm, weld_op, "targetmap", v2))) { + while ((v3 = BMO_slot_map_elem_get(slot_targetmap, v2))) { v2 = v3; } - BMO_slot_map_ptr_insert(bm, weld_op, "targetmap", v, v2); + BMO_slot_map_elem_insert(weld_op, slot_targetmap, v, v2); } BMO_op_finish(bm, &find_op); @@ -286,6 +302,7 @@ static void merge_first_last(BMesh *bm, BMOperator find_op; BMOIter oiter; BMVert *v, *v2; + BMOpSlot *slot_targetmap; BMO_op_initf(bm, &find_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "find_doubles verts=%s dist=%f keep_verts=%s", @@ -293,14 +310,16 @@ static void merge_first_last(BMesh *bm, dupe_first, "geom"); /* append the last dupe's geom to the findop input verts */ - BMO_slot_buffer_append(&find_op, "verts", dupe_last, "newout"); + BMO_slot_buffer_append(&find_op, slots_in, "verts", + dupe_last, slots_out, "geom.out"); BMO_op_exec(bm, &find_op); /* add new merge targets to weld operator */ - BMO_ITER (v, &oiter, bm, &find_op, "targetmapout", 0) { + slot_targetmap = BMO_slot_get(weld_op->slots_in, "targetmap"); + BMO_ITER (v, &oiter, find_op.slots_out, "targetmap.out", 0) { v2 = BMO_iter_map_value_p(&oiter); - BMO_slot_map_ptr_insert(bm, weld_op, "targetmap", v, v2); + BMO_slot_map_elem_insert(weld_op, slot_targetmap, v, v2); } BMO_op_finish(bm, &find_op); @@ -325,6 +344,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, int *indexMap = NULL; DerivedMesh *start_cap = NULL, *end_cap = NULL; MVert *src_mvert; + BMOpSlot *slot_targetmap = NULL; /* for weldop */ /* need to avoid infinite recursion here */ if (amd->start_cap && amd->start_cap != ob) @@ -408,13 +428,17 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, * cleaner way to do this. One possibility: a "mirror" BMOp would * certainly help by compressing it all into one top-level BMOp that * executes a lot of second-level BMOps. */ + BM_mesh_elem_toolflags_ensure(bm); BMO_push(bm, NULL); bmesh_edit_begin(bm, 0); - if (amd->flags & MOD_ARR_MERGE) + if (amd->flags & MOD_ARR_MERGE) { BMO_op_init(bm, &weld_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "weld_verts"); + slot_targetmap = BMO_slot_get(weld_op.slots_in, "targetmap"); + } + BMO_op_initf(bm, &dupe_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "duplicate geom=%avef"); first_dupe_op = dupe_op; @@ -422,18 +446,18 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, for (j = 0; j < count - 1; j++) { BMVert *v, *v2, *v3; BMOpSlot *geom_slot; - BMOpSlot *newout_slot; + BMOpSlot *geom_out_slot; BMOIter oiter; if (j != 0) { BMO_op_initf(bm, &dupe_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), - "duplicate geom=%s", &old_dupe_op, "newout"); + "duplicate geom=%S", &old_dupe_op, "geom.out"); } BMO_op_exec(bm, &dupe_op); - geom_slot = BMO_slot_get(&dupe_op, "geom"); - newout_slot = BMO_slot_get(&dupe_op, "newout"); + geom_slot = BMO_slot_get(dupe_op.slots_in, "geom"); + geom_out_slot = BMO_slot_get(dupe_op.slots_out, "geom.out"); if ((amd->flags & MOD_ARR_MERGEFINAL) && j == 0) { int first_geom_bytes = sizeof(BMVert *) * geom_slot->len; @@ -445,7 +469,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, } /* apply transformation matrix */ - BMO_ITER (v, &oiter, bm, &dupe_op, "newout", BM_VERT) { + BMO_ITER (v, &oiter, dupe_op.slots_out, "geom.out", BM_VERT) { mul_m4_v3(offset, v->co); } @@ -464,17 +488,17 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, for (i = 0; i < index_len; i++) { if (!indexMap[i]) continue; - /* merge v (from 'newout') into v2 (from old 'geom') */ - v = _E(newout_slot, i - geom_slot->len); + /* merge v (from 'geom.out') into v2 (from old 'geom') */ + v = _E(geom_out_slot, i - geom_slot->len); v2 = _E(geom_slot, indexMap[i] - 1); /* check in case the target vertex (v2) is already marked * for merging */ - while ((v3 = BMO_slot_map_ptr_get(bm, &weld_op, "targetmap", v2))) { + while ((v3 = BMO_slot_map_elem_get(slot_targetmap, v2))) { v2 = v3; } - BMO_slot_map_ptr_insert(bm, &weld_op, "targetmap", v, v2); + BMO_slot_map_elem_insert(&weld_op, slot_targetmap, v, v2); } #undef _E @@ -510,14 +534,15 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, float startoffset[4][4]; invert_m4_m4(startoffset, offset); bm_merge_dm_transform(bm, start_cap, startoffset, amd, - &first_dupe_op, "geom", &weld_op); + &first_dupe_op, first_dupe_op.slots_in, "geom", &weld_op); } if (end_cap) { float endoffset[4][4]; mult_m4_m4m4(endoffset, offset, final_offset); bm_merge_dm_transform(bm, end_cap, endoffset, amd, - &dupe_op, count == 1 ? "geom" : "newout", &weld_op); + &dupe_op, (count == 1) ? dupe_op.slots_in : dupe_op.slots_out, + (count == 1) ? "geom" : "geom.out", &weld_op); } } /* done capping */ diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index 3e3bcb73491..59befe4db05 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -92,20 +92,15 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) #ifdef USE_BM_BEVEL_OP_AS_MOD -#define EDGE_MARK 1 - /* BMESH_TODO * - * this bevel calls the operator which is missing many of the options - * which the bevel modifier in trunk has. + * this bevel calls the new bevel code (added since 2.64) + * which is missing many of the options which the bevel modifier from 2.4x has. * - no vertex bevel * - no weight bevel * * These will need to be added to the bmesh operator. - * - campbell - * - * note: this code is very close to MOD_edgesplit.c. - * note: if 0'd code from trunk included below. + * - campbell */ static DerivedMesh *applyModifier(ModifierData *md, struct Object *UNUSED(ob), DerivedMesh *dm, @@ -116,22 +111,20 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *UNUSED(ob), BMIter iter; BMEdge *e; BevelModifierData *bmd = (BevelModifierData *) md; - float threshold = cos((bmd->bevel_angle + 0.00001f) * M_PI / 180.0f); + const float threshold = cosf((bmd->bevel_angle + 0.00001f) * (float)M_PI / 180.0f); + const int segments = 16; /* XXX */ bm = DM_to_bmesh(dm); - BM_mesh_normals_update(bm, FALSE); - BMO_push(bm, NULL); - if (bmd->lim_flags & BME_BEVEL_ANGLE) { BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { /* check for 1 edge having 2 face users */ - BMLoop *l1, *l2; - if ((l1 = e->l) && - (l2 = e->l->radial_next) != l1) - { - if (dot_v3v3(l1->f->no, l2->f->no) < threshold) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); + BMLoop *l_a, *l_b; + if (BM_edge_loop_pair(e, &l_a, &l_b)) { + if (dot_v3v3(l_a->f->no, l_b->f->no) < threshold) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + BM_elem_flag_enable(e->v1, BM_ELEM_TAG); + BM_elem_flag_enable(e->v2, BM_ELEM_TAG); } } } @@ -139,18 +132,23 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *UNUSED(ob), else { /* crummy, is there a way just to operator on all? - campbell */ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); + if (BM_edge_is_manifold(e)) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + BM_elem_flag_enable(e->v1, BM_ELEM_TAG); + BM_elem_flag_enable(e->v2, BM_ELEM_TAG); + } } } - BMO_op_callf(bm, BMO_FLAG_DEFAULTS, - "bevel geom=%fe percent=%f use_even=%b use_dist=%b", - EDGE_MARK, bmd->value, (bmd->flags & BME_BEVEL_EVEN) != 0, (bmd->flags & BME_BEVEL_DIST) != 0); - BMO_pop(bm); + BM_mesh_bevel(bm, bmd->value, segments); result = CDDM_from_bmesh(bm, TRUE); + + BLI_assert(bm->toolflagpool == NULL); /* make sure we never alloc'd this */ BM_mesh_free(bm); + CDDM_calc_normals(result); + return result; } diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index dc29e59d549..28cdfa810fa 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -145,12 +145,14 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, if (dmd->flag & MOD_DECIM_FLAG_INVERT_VGROUP) { for (i = 0; i < vert_tot; i++) { - vweights[i] = 1.0f - defvert_find_weight(&dvert[i], defgrp_index); + const float f = 1.0f - defvert_find_weight(&dvert[i], defgrp_index); + vweights[i] = f > BM_MESH_DECIM_WEIGHT_EPS ? (1.0f / f) : BM_MESH_DECIM_WEIGHT_MAX; } } else { for (i = 0; i < vert_tot; i++) { - vweights[i] = defvert_find_weight(&dvert[i], defgrp_index); + const float f = defvert_find_weight(&dvert[i], defgrp_index); + vweights[i] = f > BM_MESH_DECIM_WEIGHT_EPS ? (1.0f / f) : BM_MESH_DECIM_WEIGHT_MAX; } } } @@ -186,6 +188,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, /* update for display only */ dmd->face_count = bm->totface; result = CDDM_from_bmesh(bm, FALSE); + BLI_assert(bm->toolflagpool == NULL); /* make sure we never alloc'd this */ BM_mesh_free(bm); #ifdef USE_TIMEIT diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index 21717d07fef..ec81c5ce699 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -67,8 +67,7 @@ static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Obj float threshold = cosf((emd->split_angle + 0.00001f) * (float)M_PI / 180.0f); bm = DM_to_bmesh(dm); - - BMO_push(bm, NULL); + BM_mesh_elem_toolflags_ensure(bm); if (emd->flags & MOD_EDGESPLIT_FROMANGLE) { BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { @@ -103,8 +102,6 @@ static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Obj BMO_op_callf(bm, BMO_FLAG_DEFAULTS, "split_edges edges=%fe", EDGE_MARK); - - BMO_pop(bm); /* BM_mesh_validate(bm); */ /* for troubleshooting */ diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index 92ad6faa3ce..1298d281de8 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -205,7 +205,8 @@ static MFace *get_dface(DerivedMesh *dm, DerivedMesh *split, int cur, int i, MFa return df; } -#define SET_VERTS(a, b, c, d) { \ +#define SET_VERTS(a, b, c, d) \ + { \ v[0] = mf->v##a; uv[0] = a - 1; \ v[1] = mf->v##b; uv[1] = b - 1; \ v[2] = mf->v##c; uv[2] = c - 1; \ diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.c b/source/blender/modifiers/intern/MOD_fluidsim_util.c index 47523286229..13d409dc941 100644 --- a/source/blender/modifiers/intern/MOD_fluidsim_util.c +++ b/source/blender/modifiers/intern/MOD_fluidsim_util.c @@ -426,7 +426,11 @@ static DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams) { int displaymode = 0; - int curFrame = framenr - 1 /*scene->r.sfra*/; /* start with 0 at start frame */ + + int curFrame = framenr /* - 1 */ /*scene->r.sfra*/; /* start with 0 at start frame */ + /* why start with 0 as start frame?? Animations + time are frozen for frame 0 anyway. (See physics_fluid.c for that. - DG */ + /* If we start with frame 0, we need to remap all animation channels, too, because they will all be 1 frame late if using frame-1! - DG */ + char targetFile[FILE_MAX]; FluidsimSettings *fss = fluidmd->fss; DerivedMesh *dm = NULL; diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c index 6f6589d4d14..266226040a3 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -199,7 +199,7 @@ static void init_data(ModifierData *md) smd->lambda = 0.00001f; smd->lambda_border = 0.00005f; smd->repeat = 1; - smd->flag = MOD_LAPLACIANSMOOTH_X | MOD_LAPLACIANSMOOTH_Y | MOD_LAPLACIANSMOOTH_Z | MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION; + smd->flag = MOD_LAPLACIANSMOOTH_X | MOD_LAPLACIANSMOOTH_Y | MOD_LAPLACIANSMOOTH_Z | MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME; smd->defgrp_name[0] = '\0'; } @@ -511,7 +511,7 @@ static void validate_solution(LaplacianSystem *sys, short flag) float leni, lene; float vini, vend; float *vi1, *vi2, ve1[3], ve2[3]; - if (flag & MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION) { + if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) { vini = compute_volume(sys->vertexCos, sys->mfaces, sys->numFaces); } for (i = 0; i < sys->numEdges; i++) { @@ -545,7 +545,7 @@ static void validate_solution(LaplacianSystem *sys, short flag) } } } - if (flag & MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION) { + if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) { vend = compute_volume(sys->vertexCos, sys->mfaces, sys->numFaces); volume_preservation(sys, vini, vend, flag); } diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 8a4d70da6e8..a73d52a0a63 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -249,14 +249,14 @@ static int build_hull(SkinOutput *so, Frame **frames, int totframe) } /* Apply face attributes to hull output */ - BMO_ITER (f, &oiter, bm, &op, "geomout", BM_FACE) { + BMO_ITER (f, &oiter, op.slots_out, "geom.out", BM_FACE) { if (so->smd->flag & MOD_SKIN_SMOOTH_SHADING) BM_elem_flag_enable(f, BM_ELEM_SMOOTH); f->mat_nr = so->mat_nr; } /* Mark interior frames */ - BMO_ITER (v, &oiter, bm, &op, "interior_geom", BM_VERT) { + BMO_ITER (v, &oiter, op.slots_out, "geom_interior.out", BM_VERT) { for (i = 0; i < totframe; i++) { Frame *frame = frames[i]; @@ -309,7 +309,7 @@ static int build_hull(SkinOutput *so, Frame **frames, int totframe) /* Check if removing triangles above will create wire triangles, * mark them too */ - BMO_ITER (e, &oiter, bm, &op, "geomout", BM_EDGE) { + BMO_ITER (e, &oiter, op.slots_out, "geom.out", BM_EDGE) { int is_wire = TRUE; BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) { if (!BM_elem_flag_test(f, BM_ELEM_TAG)) { @@ -537,6 +537,7 @@ static int connection_node_mat(float mat[3][3], int v, const MeshElemMap *emap, /* Get axis and angle to rotate frame by */ angle = angle_normalized_v3v3(ine[0], oute[0]) / 2.0f; cross_v3_v3v3(axis, ine[0], oute[0]); + normalize_v3(axis); /* Build frame matrix (don't care about X axis here) */ copy_v3_v3(mat[0], ine[0]); @@ -644,8 +645,8 @@ typedef struct { } EdgeStackElem; static void build_emats_stack(BLI_Stack *stack, int *visited_e, EMat *emat, - const MeshElemMap *emap, const MEdge *medge, - const MVertSkin *vs, const MVert *mvert) + const MeshElemMap *emap, const MEdge *medge, + const MVertSkin *vs, const MVert *mvert) { EdgeStackElem stack_elem; float axis[3], angle; @@ -673,7 +674,7 @@ static void build_emats_stack(BLI_Stack *stack, int *visited_e, EMat *emat, /* If parent is a branch node, start a new edge chain */ if (parent_is_branch) { calc_edge_mat(emat[e].mat, mvert[parent_v].co, - mvert[v].co); + mvert[v].co); } else { /* Build edge matrix guided by parent matrix */ @@ -940,18 +941,18 @@ static void add_poly(SkinOutput *so, BLI_assert(v3 != v4); BLI_assert(v1 && v2 && v3); - edges[0] = BM_edge_create(so->bm, v1, v2, NULL, TRUE); - edges[1] = BM_edge_create(so->bm, v2, v3, NULL, TRUE); + edges[0] = BM_edge_create(so->bm, v1, v2, NULL, BM_CREATE_NO_DOUBLE); + edges[1] = BM_edge_create(so->bm, v2, v3, NULL, BM_CREATE_NO_DOUBLE); if (v4) { - edges[2] = BM_edge_create(so->bm, v3, v4, NULL, TRUE); - edges[3] = BM_edge_create(so->bm, v4, v1, NULL, TRUE); + edges[2] = BM_edge_create(so->bm, v3, v4, NULL, BM_CREATE_NO_DOUBLE); + edges[3] = BM_edge_create(so->bm, v4, v1, NULL, BM_CREATE_NO_DOUBLE); } else { - edges[2] = BM_edge_create(so->bm, v3, v1, NULL, TRUE); + edges[2] = BM_edge_create(so->bm, v3, v1, NULL, BM_CREATE_NO_DOUBLE); edges[3] = NULL; } - f = BM_face_create(so->bm, verts, edges, v4 ? 4 : 3, TRUE); + f = BM_face_create(so->bm, verts, edges, v4 ? 4 : 3, BM_CREATE_NO_DOUBLE); if (so->smd->flag & MOD_SKIN_SMOOTH_SHADING) BM_elem_flag_enable(f, BM_ELEM_SMOOTH); f->mat_nr = so->mat_nr; @@ -959,12 +960,12 @@ static void add_poly(SkinOutput *so, static void connect_frames(SkinOutput *so, BMVert *frame1[4], - BMVert *frame2[4]) +BMVert *frame2[4]) { BMVert *q[4][4] = {{frame2[0], frame2[1], frame1[1], frame1[0]}, - {frame2[1], frame2[2], frame1[2], frame1[1]}, - {frame2[2], frame2[3], frame1[3], frame1[2]}, - {frame2[3], frame2[0], frame1[0], frame1[3]}}; + {frame2[1], frame2[2], frame1[2], frame1[1]}, + {frame2[2], frame2[3], frame1[3], frame1[2]}, + {frame2[3], frame2[0], frame1[0], frame1[3]}}; float p[3], no[3]; int i, swap; @@ -995,7 +996,7 @@ static void output_frames(BMesh *bm, f = &sn->frames[i]; for (j = 0; j < 4; j++) { if (!f->merge[j].frame) { - BMVert *v = f->verts[j] = BM_vert_create(bm, f->co[j], NULL); + BMVert *v = f->verts[j] = BM_vert_create(bm, f->co[j], NULL, 0); if (input_dvert) { MDeformVert *dv; @@ -1079,17 +1080,20 @@ static BMFace *collapse_face_corners(BMesh *bm, BMFace *f, int n, BMOperator op; BMIter iter; int i; + BMOpSlot *slot_targetmap; shortest_edge = BM_face_find_shortest_loop(f)->e; BMO_op_initf(bm, &op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "weld_verts"); + slot_targetmap = BMO_slot_get(op.slots_in, "targetmap"); + /* Note: could probably calculate merges in one go to be * faster */ v_safe = shortest_edge->v1; v_merge = shortest_edge->v2; mid_v3_v3v3(v_safe->co, v_safe->co, v_merge->co); - BMO_slot_map_ptr_insert(bm, &op, "targetmap", v_merge, v_safe); + BMO_slot_map_elem_insert(&op, slot_targetmap, v_merge, v_safe); BMO_op_exec(bm, &op); BMO_op_finish(bm, &op); @@ -1215,6 +1219,7 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f BMOIter oiter; BMOperator op; int i, best_order[4]; + BMOpSlot *slot_targetmap; BLI_assert(split_face->len >= 3); @@ -1228,7 +1233,7 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f /* Update split face (should only be one new face created * during extrusion) */ split_face = NULL; - BMO_ITER (f, &oiter, bm, &op, "faceout", BM_FACE) { + BMO_ITER (f, &oiter, op.slots_out, "faces.out", BM_FACE) { BLI_assert(!split_face); split_face = f; } @@ -1246,7 +1251,7 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f BM_elem_flag_enable(longest_edge, BM_ELEM_TAG); BMO_op_callf(bm, BMO_FLAG_DEFAULTS, - "subdivide_edges edges=%he numcuts=%i quadcornertype=%i", + "subdivide_edges edges=%he cuts=%i quad_corner_type=%i", BM_ELEM_TAG, 1, SUBD_STRAIGHT_CUT); } else if (split_face->len > 4) { @@ -1280,9 +1285,9 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f BM_face_kill(bm, split_face); BMO_op_init(bm, &op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "weld_verts"); + slot_targetmap = BMO_slot_get(op.slots_in, "targetmap"); for (i = 0; i < 4; i++) { - BMO_slot_map_ptr_insert(bm, &op, "targetmap", - verts[i], frame->verts[best_order[i]]); + BMO_slot_map_elem_insert(&op, slot_targetmap, verts[i], frame->verts[best_order[i]]); } BMO_op_exec(bm, &op); BMO_op_finish(bm, &op); @@ -1304,7 +1309,7 @@ static void skin_hole_detach_partially_attached_frame(BMesh *bm, Frame *frame) /* Detach everything */ for (i = 0; i < totattached; i++) { BMVert **av = &frame->verts[attached[i]]; - (*av) = BM_vert_create(bm, (*av)->co, *av); + (*av) = BM_vert_create(bm, (*av)->co, *av, 0); } } @@ -1354,24 +1359,6 @@ static void add_quad_from_tris(SkinOutput *so, BMEdge *e, BMFace *adj[2]) add_poly(so, quad[0], quad[1], quad[2], quad[3]); } -/* Returns the number of faces that are adjacent to both f1 and f2 */ -static int BM_face_share_face_count(BMFace *f1, BMFace *f2) -{ - BMIter iter1, iter2; - BMEdge *e; - BMFace *f; - int count = 0; - - BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) { - BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) { - if (f != f1 && f != f2 && BM_face_share_edge_count(f, f2)) - count++; - } - } - - return count; -} - static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd) { BMIter iter; @@ -1434,7 +1421,7 @@ static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd) * share a border with another face, output as a quad */ if (!BM_elem_flag_test(adj[0], BM_ELEM_TAG) && !BM_elem_flag_test(adj[1], BM_ELEM_TAG) && - !BM_face_share_face_count(adj[0], adj[1])) + !BM_face_share_face_check(adj[0], adj[1])) { add_quad_from_tris(so, e, adj); BM_elem_flag_enable(adj[0], BM_ELEM_TAG); diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index cc77d73a736..75e54d77b15 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -207,9 +207,10 @@ BLI_INLINE void madd_v3v3short_fl(float r[3], const short a[3], const float f) r[2] += (float)a[2] * f; } -static DerivedMesh *applyModifier(ModifierData *md, Object *ob, - DerivedMesh *dm, - ModifierApplyFlag UNUSED(flag)) +static DerivedMesh *applyModifier( + ModifierData *md, Object *ob, + DerivedMesh *dm, + ModifierApplyFlag UNUSED(flag)) { int i; DerivedMesh *result; @@ -749,6 +750,10 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, CDDM_calc_normals(result); } + if (numFaces == 0 && numEdges != 0) { + modifier_setError(md, "Faces needed for useful output"); + } + return result; } diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c new file mode 100644 index 00000000000..645fd5eb2cf --- /dev/null +++ b/source/blender/modifiers/intern/MOD_triangulate.c @@ -0,0 +1,144 @@ +/* + * ***** 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. + * + * Contributor(s): Antony Riakiotakis + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +/** \file blender/modifiers/intern/MOD_triangulate.c + * \ingroup modifiers + */ + +#include "DNA_object_types.h" + +#include "BLI_utildefines.h" + +#include "BKE_cdderivedmesh.h" +#include "BKE_modifier.h" +#include "BKE_tessmesh.h" + +/* triangulation modifier, directly calls the bmesh operator */ + +static DerivedMesh *triangulate_dm(DerivedMesh *dm, const int flag) +{ + DerivedMesh *result; + BMesh *bm; + int total_edges, i; + MEdge *me; + + bm = DM_to_bmesh(dm); + + BM_mesh_elem_toolflags_ensure(bm); + BMO_push(bm, NULL); + + BMO_op_callf(bm, BMO_FLAG_DEFAULTS, + "triangulate faces=%af use_beauty=%b", + (flag & MOD_TRIANGULATE_BEAUTY)); + BMO_pop(bm); + + result = CDDM_from_bmesh(bm, FALSE); + BM_mesh_free(bm); + + total_edges = result->getNumEdges(result); + me = CDDM_get_edges(result); + + /* force drawing of all edges (seems to be omitted in CDDM_from_bmesh) */ + for (i = 0; i < total_edges; i++, me++) + me->flag |= ME_EDGEDRAW | ME_EDGERENDER; + + CDDM_calc_normals(result); + + return result; +} + + +static void initData(ModifierData *md) +{ + TriangulateModifierData *tmd = (TriangulateModifierData *)md; + + /* Enable in editmode by default */ + md->mode |= eModifierMode_Editmode; + tmd->flag = MOD_TRIANGULATE_BEAUTY; +} + + +static void copyData(ModifierData *md, ModifierData *target) +{ + TriangulateModifierData *smd = (TriangulateModifierData *) md; + TriangulateModifierData *tsmd = (TriangulateModifierData *) target; + + *tsmd = *smd; +} + +static DerivedMesh *applyModifierEM(ModifierData *md, + Object *UNUSED(ob), + struct BMEditMesh *UNUSED(em), + DerivedMesh *dm) +{ + TriangulateModifierData *tmd = (TriangulateModifierData *)md; + DerivedMesh *result; + if (!(result = triangulate_dm(dm, tmd->flag))) { + return dm; + } + + return result; +} + +static DerivedMesh *applyModifier(ModifierData *md, + Object *UNUSED(ob), + DerivedMesh *dm, + ModifierApplyFlag UNUSED(flag)) +{ + TriangulateModifierData *tmd = (TriangulateModifierData *)md; + DerivedMesh *result; + if (!(result = triangulate_dm(dm, tmd->flag))) { + return dm; + } + + return result; +} + +ModifierTypeInfo modifierType_Triangulate = { + /* name */ "Triangulate", + /* structName */ "TriangulateModifierData", + /* structSize */ sizeof(TriangulateModifierData), + /* type */ eModifierTypeType_Constructive, + /* flags */ eModifierTypeFlag_AcceptsMesh | + eModifierTypeFlag_SupportsEditmode | + eModifierTypeFlag_SupportsMapping | + eModifierTypeFlag_EnableInEditmode | + eModifierTypeFlag_AcceptsCVs, + + /* copyData */ copyData, + /* deformVerts */ NULL, + /* deformMatrices */ NULL, + /* deformVertsEM */ NULL, + /* deformMatricesEM */ NULL, + /* applyModifier */ applyModifier, + /* applyModifierEM */ applyModifierEM, + /* initData */ initData, + /* requiredDataMask */ NULL, //requiredDataMask, + /* freeData */ NULL, + /* isDisabled */ NULL, + /* updateDepgraph */ NULL, + /* dependsOnTime */ NULL, + /* dependsOnNormals */ NULL, + /* foreachObjectLink */ NULL, + /* foreachIDLink */ NULL, +}; diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index 3b769a30994..a27d5e5e03b 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -278,5 +278,6 @@ void modifier_type_init(ModifierTypeInfo *types[]) INIT_TYPE(Remesh); INIT_TYPE(Skin); INIT_TYPE(LaplacianSmooth); + INIT_TYPE(Triangulate); #undef INIT_TYPE } diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 323a534c989..141a3680df2 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -84,6 +84,7 @@ set(SRC composite/nodes/node_composite_lummaMatte.c composite/nodes/node_composite_mapUV.c composite/nodes/node_composite_mapValue.c + composite/nodes/node_composite_mapRange.c composite/nodes/node_composite_math.c composite/nodes/node_composite_mask.c composite/nodes/node_composite_mixrgb.c @@ -122,7 +123,6 @@ set(SRC composite/nodes/node_composite_pixelate.c composite/node_composite_tree.c - composite/node_composite_util.c shader/nodes/node_shader_camera.c shader/nodes/node_shader_common.c @@ -145,36 +145,40 @@ set(SRC shader/nodes/node_shader_valToRgb.c shader/nodes/node_shader_value.c shader/nodes/node_shader_vectMath.c + shader/nodes/node_shader_add_shader.c + shader/nodes/node_shader_ambient_occlusion.c shader/nodes/node_shader_attribute.c shader/nodes/node_shader_background.c shader/nodes/node_shader_bsdf_anisotropic.c shader/nodes/node_shader_bsdf_diffuse.c - shader/nodes/node_shader_bsdf_glossy.c shader/nodes/node_shader_bsdf_glass.c + shader/nodes/node_shader_bsdf_glossy.c + shader/nodes/node_shader_bsdf_refraction.c shader/nodes/node_shader_bsdf_translucent.c shader/nodes/node_shader_bsdf_transparent.c shader/nodes/node_shader_bsdf_velvet.c shader/nodes/node_shader_bump.c shader/nodes/node_shader_emission.c shader/nodes/node_shader_fresnel.c - shader/nodes/node_shader_layer_weight.c shader/nodes/node_shader_geometry.c shader/nodes/node_shader_holdout.c - shader/nodes/node_shader_volume_transparent.c - shader/nodes/node_shader_volume_isotropic.c - shader/nodes/node_shader_light_path.c + shader/nodes/node_shader_layer_weight.c shader/nodes/node_shader_light_falloff.c - shader/nodes/node_shader_object_info.c - shader/nodes/node_shader_script.c - shader/nodes/node_shader_particle_info.c + shader/nodes/node_shader_light_path.c shader/nodes/node_shader_mix_shader.c - shader/nodes/node_shader_add_shader.c + shader/nodes/node_shader_normal_map.c + shader/nodes/node_shader_object_info.c shader/nodes/node_shader_output_lamp.c shader/nodes/node_shader_output_material.c shader/nodes/node_shader_output_world.c - shader/nodes/node_shader_tex_gradient.c + shader/nodes/node_shader_particle_info.c + shader/nodes/node_shader_script.c + shader/nodes/node_shader_tangent.c + shader/nodes/node_shader_tex_brick.c + shader/nodes/node_shader_tex_checker.c shader/nodes/node_shader_tex_coord.c shader/nodes/node_shader_tex_environment.c + shader/nodes/node_shader_tex_gradient.c shader/nodes/node_shader_tex_image.c shader/nodes/node_shader_tex_magic.c shader/nodes/node_shader_tex_musgrave.c @@ -182,8 +186,8 @@ set(SRC shader/nodes/node_shader_tex_sky.c shader/nodes/node_shader_tex_voronoi.c shader/nodes/node_shader_tex_wave.c - shader/nodes/node_shader_tex_checker.c - shader/nodes/node_shader_tex_brick.c + shader/nodes/node_shader_volume_isotropic.c + shader/nodes/node_shader_volume_transparent.c shader/node_shader_tree.c shader/node_shader_util.c @@ -218,7 +222,6 @@ set(SRC intern/node_common.c intern/node_socket.c - composite/node_composite_util.h shader/node_shader_util.h texture/node_texture_util.h @@ -231,6 +234,13 @@ set(SRC intern/node_common.h ) +if(WITH_COMPOSITOR_LEGACY) + list(APPEND SRC + composite/node_composite_util.h + composite/node_composite_util.c + ) +endif() + if(WITH_PYTHON) list(APPEND INC ../python diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index ee67ac88085..6d60ac0bb58 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -40,8 +40,6 @@ extern bNodeTreeType ntreeType_Composite; /* ****************** types array for all composite nodes ****************** */ void register_node_type_cmp_group(struct bNodeTreeType *ttype); -void register_node_type_cmp_forloop(struct bNodeTreeType *ttype); -void register_node_type_cmp_whileloop(struct bNodeTreeType *ttype); void register_node_type_cmp_rlayers(struct bNodeTreeType *ttype); void register_node_type_cmp_image(struct bNodeTreeType *ttype); @@ -72,6 +70,7 @@ void register_node_type_cmp_huecorrect(struct bNodeTreeType *ttype); void register_node_type_cmp_normal(struct bNodeTreeType *ttype); void register_node_type_cmp_curve_vec(struct bNodeTreeType *ttype); void register_node_type_cmp_map_value(struct bNodeTreeType *ttype); +void register_node_type_cmp_map_range(struct bNodeTreeType *ttype); void register_node_type_cmp_normalize(struct bNodeTreeType *ttype); void register_node_type_cmp_filter(struct bNodeTreeType *ttype); diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 66ab15ce29f..74135776c9c 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -41,8 +41,6 @@ extern struct bNodeTreeType ntreeType_Shader; /* ****************** types array for all shaders ****************** */ void register_node_type_sh_group(struct bNodeTreeType *ttype); -void register_node_type_sh_forloop(struct bNodeTreeType *ttype); -void register_node_type_sh_whileloop(struct bNodeTreeType *ttype); void register_node_type_sh_output(struct bNodeTreeType *ttype); void register_node_type_sh_material(struct bNodeTreeType *ttype); @@ -81,11 +79,15 @@ void register_node_type_sh_layer_weight(struct bNodeTreeType *ttype); void register_node_type_sh_tex_coord(struct bNodeTreeType *ttype); void register_node_type_sh_particle_info(struct bNodeTreeType *ttype); void register_node_type_sh_script(struct bNodeTreeType *ttype); +void register_node_type_sh_normal_map(struct bNodeTreeType *ttype); +void register_node_type_sh_tangent(struct bNodeTreeType *ttype); +void register_node_type_sh_ambient_occlusion(struct bNodeTreeType *ttype); void register_node_type_sh_background(struct bNodeTreeType *ttype); void register_node_type_sh_bsdf_diffuse(struct bNodeTreeType *ttype); void register_node_type_sh_bsdf_glossy(struct bNodeTreeType *ttype); void register_node_type_sh_bsdf_glass(struct bNodeTreeType *ttype); +void register_node_type_sh_bsdf_refraction(struct bNodeTreeType *ttype); void register_node_type_sh_bsdf_translucent(struct bNodeTreeType *ttype); void register_node_type_sh_bsdf_transparent(struct bNodeTreeType *ttype); void register_node_type_sh_bsdf_velvet(struct bNodeTreeType *ttype); diff --git a/source/blender/nodes/NOD_socket.h b/source/blender/nodes/NOD_socket.h index f41be2bb7d9..b14f7c4e884 100644 --- a/source/blender/nodes/NOD_socket.h +++ b/source/blender/nodes/NOD_socket.h @@ -60,6 +60,7 @@ void node_socket_set_default_value_vector(void *default_value, PropertySubType s void node_socket_set_default_value_rgba(void *default_value, float r, float g, float b, float a); void node_socket_set_default_value_shader(void *default_value); void node_socket_set_default_value_mesh(void *default_value); +void node_socket_set_default_value_string(void *default_value, PropertySubType subtype, const char *value); struct bNodeSocket *node_add_input_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp); struct bNodeSocket *node_add_output_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp); diff --git a/source/blender/nodes/NOD_texture.h b/source/blender/nodes/NOD_texture.h index 7722580d136..a1be9963b8a 100644 --- a/source/blender/nodes/NOD_texture.h +++ b/source/blender/nodes/NOD_texture.h @@ -40,8 +40,6 @@ extern bNodeTreeType ntreeType_Texture; /* ****************** types array for all texture nodes ****************** */ void register_node_type_tex_group(struct bNodeTreeType *ttype); -void register_node_type_tex_forloop(struct bNodeTreeType *ttype); -void register_node_type_tex_whileloop(struct bNodeTreeType *ttype); void register_node_type_tex_math(struct bNodeTreeType *ttype); void register_node_type_tex_mix_rgb(struct bNodeTreeType *ttype); diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index 9a7e587ff56..03462738d58 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -719,6 +719,16 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int rendering, int /* *********************************************** */ +static void set_output_visible(bNode *node, int passflag, int index, int pass) +{ + bNodeSocket *sock = BLI_findlink(&node->outputs, index); + /* clear the SOCK_HIDDEN flag as well, in case a socket was hidden before */ + if (passflag & pass) + sock->flag &= ~(SOCK_HIDDEN | SOCK_UNAVAIL); + else + sock->flag |= SOCK_UNAVAIL; +} + /* clumsy checking... should do dynamic outputs once */ static void force_hidden_passes(bNode *node, int passflag) { @@ -727,68 +737,35 @@ static void force_hidden_passes(bNode *node, int passflag) for (sock= node->outputs.first; sock; sock= sock->next) sock->flag &= ~SOCK_UNAVAIL; - if (!(passflag & SCE_PASS_COMBINED)) { - sock= BLI_findlink(&node->outputs, RRES_OUT_IMAGE); - sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_ALPHA); - sock->flag |= SOCK_UNAVAIL; - } + set_output_visible(node, passflag, RRES_OUT_IMAGE, SCE_PASS_COMBINED); + set_output_visible(node, passflag, RRES_OUT_ALPHA, SCE_PASS_COMBINED); - sock= BLI_findlink(&node->outputs, RRES_OUT_Z); - if (!(passflag & SCE_PASS_Z)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_NORMAL); - if (!(passflag & SCE_PASS_NORMAL)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_VEC); - if (!(passflag & SCE_PASS_VECTOR)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_UV); - if (!(passflag & SCE_PASS_UV)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_RGBA); - if (!(passflag & SCE_PASS_RGBA)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_DIFF); - if (!(passflag & SCE_PASS_DIFFUSE)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_SPEC); - if (!(passflag & SCE_PASS_SPEC)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_SHADOW); - if (!(passflag & SCE_PASS_SHADOW)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_AO); - if (!(passflag & SCE_PASS_AO)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_REFLECT); - if (!(passflag & SCE_PASS_REFLECT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_REFRACT); - if (!(passflag & SCE_PASS_REFRACT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_INDIRECT); - if (!(passflag & SCE_PASS_INDIRECT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXOB); - if (!(passflag & SCE_PASS_INDEXOB)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXMA); - if (!(passflag & SCE_PASS_INDEXMA)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_MIST); - if (!(passflag & SCE_PASS_MIST)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_EMIT); - if (!(passflag & SCE_PASS_EMIT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_ENV); - if (!(passflag & SCE_PASS_ENVIRONMENT)) sock->flag |= SOCK_UNAVAIL; - - sock= BLI_findlink(&node->outputs, RRES_OUT_DIFF_DIRECT); - if (!(passflag & SCE_PASS_DIFFUSE_DIRECT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_DIFF_INDIRECT); - if (!(passflag & SCE_PASS_DIFFUSE_INDIRECT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_DIFF_COLOR); - if (!(passflag & SCE_PASS_DIFFUSE_COLOR)) sock->flag |= SOCK_UNAVAIL; - - sock= BLI_findlink(&node->outputs, RRES_OUT_GLOSSY_DIRECT); - if (!(passflag & SCE_PASS_GLOSSY_DIRECT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_GLOSSY_INDIRECT); - if (!(passflag & SCE_PASS_GLOSSY_INDIRECT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_GLOSSY_COLOR); - if (!(passflag & SCE_PASS_GLOSSY_COLOR)) sock->flag |= SOCK_UNAVAIL; - - sock= BLI_findlink(&node->outputs, RRES_OUT_TRANSM_DIRECT); - if (!(passflag & SCE_PASS_TRANSM_DIRECT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_TRANSM_INDIRECT); - if (!(passflag & SCE_PASS_TRANSM_INDIRECT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_TRANSM_COLOR); - if (!(passflag & SCE_PASS_TRANSM_COLOR)) sock->flag |= SOCK_UNAVAIL; + set_output_visible(node, passflag, RRES_OUT_Z, SCE_PASS_Z); + set_output_visible(node, passflag, RRES_OUT_NORMAL, SCE_PASS_NORMAL); + set_output_visible(node, passflag, RRES_OUT_VEC, SCE_PASS_VECTOR); + set_output_visible(node, passflag, RRES_OUT_UV, SCE_PASS_UV); + set_output_visible(node, passflag, RRES_OUT_RGBA, SCE_PASS_RGBA); + set_output_visible(node, passflag, RRES_OUT_DIFF, SCE_PASS_DIFFUSE); + set_output_visible(node, passflag, RRES_OUT_SPEC, SCE_PASS_SPEC); + set_output_visible(node, passflag, RRES_OUT_SHADOW, SCE_PASS_SHADOW); + set_output_visible(node, passflag, RRES_OUT_AO, SCE_PASS_AO); + set_output_visible(node, passflag, RRES_OUT_REFLECT, SCE_PASS_REFLECT); + set_output_visible(node, passflag, RRES_OUT_REFRACT, SCE_PASS_REFRACT); + set_output_visible(node, passflag, RRES_OUT_INDIRECT, SCE_PASS_INDIRECT); + set_output_visible(node, passflag, RRES_OUT_INDEXOB, SCE_PASS_INDEXOB); + set_output_visible(node, passflag, RRES_OUT_INDEXMA, SCE_PASS_INDEXMA); + set_output_visible(node, passflag, RRES_OUT_MIST, SCE_PASS_MIST); + set_output_visible(node, passflag, RRES_OUT_EMIT, SCE_PASS_EMIT); + set_output_visible(node, passflag, RRES_OUT_ENV, SCE_PASS_ENVIRONMENT); + set_output_visible(node, passflag, RRES_OUT_DIFF_DIRECT, SCE_PASS_DIFFUSE_DIRECT); + set_output_visible(node, passflag, RRES_OUT_DIFF_INDIRECT, SCE_PASS_DIFFUSE_INDIRECT); + set_output_visible(node, passflag, RRES_OUT_DIFF_COLOR, SCE_PASS_DIFFUSE_COLOR); + set_output_visible(node, passflag, RRES_OUT_GLOSSY_DIRECT, SCE_PASS_GLOSSY_DIRECT); + set_output_visible(node, passflag, RRES_OUT_GLOSSY_INDIRECT, SCE_PASS_GLOSSY_INDIRECT); + set_output_visible(node, passflag, RRES_OUT_GLOSSY_COLOR, SCE_PASS_GLOSSY_COLOR); + set_output_visible(node, passflag, RRES_OUT_TRANSM_DIRECT, SCE_PASS_TRANSM_DIRECT); + set_output_visible(node, passflag, RRES_OUT_TRANSM_INDIRECT, SCE_PASS_TRANSM_INDIRECT); + set_output_visible(node, passflag, RRES_OUT_TRANSM_COLOR, SCE_PASS_TRANSM_COLOR); } /* based on rules, force sockets hidden always */ diff --git a/source/blender/nodes/composite/nodes/node_composite_blur.c b/source/blender/nodes/composite/nodes/node_composite_blur.c index b9b2406631b..eb7f7763afb 100644 --- a/source/blender/nodes/composite/nodes/node_composite_blur.c +++ b/source/blender/nodes/composite/nodes/node_composite_blur.c @@ -726,7 +726,9 @@ static void node_composit_exec_blur(void *data, bNode *node, bNodeStack **in, bN static void node_composit_init_blur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { - node->storage = MEM_callocN(sizeof(NodeBlurData), "node blur data"); + NodeBlurData *data = MEM_callocN(sizeof(NodeBlurData), "node blur data"); + data->filtertype = R_FILTER_GAUSS; + node->storage = data; } void register_node_type_cmp_blur(bNodeTreeType *ttype) diff --git a/source/blender/nodes/composite/nodes/node_composite_colorSpill.c b/source/blender/nodes/composite/nodes/node_composite_colorSpill.c index e8965d50b47..44a5ac9e968 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorSpill.c +++ b/source/blender/nodes/composite/nodes/node_composite_colorSpill.c @@ -29,12 +29,8 @@ * \ingroup cmpnodes */ - - #include "node_composite_util.h" -#define AVG(a, b) ((a + b) / 2) - /* ******************* Color Spill Supression ********************************* */ static bNodeSocketTemplate cmp_node_color_spill_in[] = { {SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, @@ -49,6 +45,9 @@ static bNodeSocketTemplate cmp_node_color_spill_out[] = { #ifdef WITH_COMPOSITOR_LEGACY +#define AVG(a, b) ((a + b) / 2) + + static void do_simple_spillmap_red(bNode *node, float* out, float *in) { NodeColorspill *ncs; diff --git a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c index e9d26ebebbc..df49e537788 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c +++ b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c @@ -49,14 +49,14 @@ static bNodeSocketTemplate cmp_node_colorbalance_out[] = { #ifdef WITH_COMPOSITOR_LEGACY /* this function implements ASC-CDL according to the spec at http://www.asctech.org/ - Slope - S = in * slope - Offset - O = S + offset - = (in * slope) + offset - Power - out = Clamp(O) ^ power - = Clamp((in * slope) + offset) ^ power + * Slope + * S = in * slope + * Offset + * O = S + offset + * = (in * slope) + offset + * Power + * out = Clamp(O) ^ power + * = Clamp((in * slope) + offset) ^ power */ DO_INLINE float colorbalance_cdl(float in, float offset, float power, float slope) { diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 150382c1f8f..88d78df190f 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -173,9 +173,10 @@ static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node) Image *ima= (Image *)node->id; if (ima) { ImageUser *iuser= node->storage; + ImBuf *ibuf; /* make sure ima->type is correct */ - BKE_image_get_ibuf(ima, iuser); + ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if (ima->rr) { RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer); @@ -191,6 +192,8 @@ static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node) } else cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA|RRES_OUT_Z); + + BKE_image_release_ibuf(ima, ibuf, NULL); } else cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA); @@ -312,7 +315,7 @@ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc) } /* note: this function is used for multilayer too, to ensure uniform - * handling with BKE_image_get_ibuf() */ + * handling with BKE_image_acquire_ibuf() */ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser) { ImBuf *ibuf; @@ -322,7 +325,7 @@ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *i float *rect; int alloc= FALSE; - ibuf= BKE_image_get_ibuf(ima, iuser); + ibuf= BKE_image_acquire_ibuf(ima, iuser, NULL); if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) { return NULL; } @@ -374,12 +377,15 @@ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *i } } #endif + + BKE_image_release_ibuf(ima, ibuf, NULL); + return stackbuf; } static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd) { - ImBuf *ibuf= BKE_image_get_ibuf((Image *)node->id, node->storage); + ImBuf *ibuf= BKE_image_acquire_ibuf((Image *)node->id, node->storage, NULL); CompBuf *zbuf= NULL; if (ibuf && ibuf->zbuf_float) { @@ -391,6 +397,9 @@ static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd) zbuf->rect= ibuf->zbuf_float; } } + + BKE_image_release_ibuf((Image *)node->id, ibuf, NULL); + return zbuf; } @@ -418,13 +427,14 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSE RenderData *rd= data; Image *ima= (Image *)node->id; ImageUser *iuser= (ImageUser *)node->storage; + ImBuf *ibuf = NULL; /* first set the right frame number in iuser */ BKE_image_user_frame_calc(iuser, rd->cfra, 0); /* force a load, we assume iuser index will be set OK anyway */ if (ima->type==IMA_TYPE_MULTILAYER) - BKE_image_get_ibuf(ima, iuser); + ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if (ima->type==IMA_TYPE_MULTILAYER && ima->rr) { RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer); @@ -505,6 +515,8 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSE generate_preview(data, node, stackbuf); } } + + BKE_image_release_ibuf(ima, ibuf, NULL); } } diff --git a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c index e16b7e5d885..96e905827cb 100644 --- a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c +++ b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c @@ -96,22 +96,25 @@ static void compute_gradient_screen(RenderData *rd, NodeKeyingScreenData *keying int j; zero_v3(site->color); - for (j = 0; j < pattern_ibuf->x * pattern_ibuf->y; j++) { - if (pattern_ibuf->rect_float) { - add_v3_v3(site->color, &pattern_ibuf->rect_float[4 * j]); - } - else { - unsigned char *rrgb = (unsigned char *)pattern_ibuf->rect; - site->color[0] += srgb_to_linearrgb((float)rrgb[4 * j + 0] / 255.0f); - site->color[1] += srgb_to_linearrgb((float)rrgb[4 * j + 1] / 255.0f); - site->color[2] += srgb_to_linearrgb((float)rrgb[4 * j + 2] / 255.0f); + if (pattern_ibuf) { + for (j = 0; j < pattern_ibuf->x * pattern_ibuf->y; j++) { + if (pattern_ibuf->rect_float) { + add_v3_v3(site->color, &pattern_ibuf->rect_float[4 * j]); + } + else { + unsigned char *rrgb = (unsigned char *)pattern_ibuf->rect; + + site->color[0] += srgb_to_linearrgb((float)rrgb[4 * j + 0] / 255.0f); + site->color[1] += srgb_to_linearrgb((float)rrgb[4 * j + 1] / 255.0f); + site->color[2] += srgb_to_linearrgb((float)rrgb[4 * j + 2] / 255.0f); + } } + + mul_v3_fl(site->color, 1.0f / (pattern_ibuf->x * pattern_ibuf->y)); + IMB_freeImBuf(pattern_ibuf); } - mul_v3_fl(site->color, 1.0f / (pattern_ibuf->x * pattern_ibuf->y)); - IMB_freeImBuf(pattern_ibuf); - site->co[0] = marker->pos[0] * screenbuf->x; site->co[1] = marker->pos[1] * screenbuf->y; diff --git a/source/blender/nodes/composite/nodes/node_composite_mapRange.c b/source/blender/nodes/composite/nodes/node_composite_mapRange.c new file mode 100644 index 00000000000..f96e133b19f --- /dev/null +++ b/source/blender/nodes/composite/nodes/node_composite_mapRange.c @@ -0,0 +1,58 @@ +/* + * ***** 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) 2006 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/composite/nodes/node_composite_mapRange.c + * \ingroup cmpnodes + */ + + +#include "node_composite_util.h" + +/* **************** MAP VALUE ******************** */ +static bNodeSocketTemplate cmp_node_map_range_in[] = { + { SOCK_FLOAT, 1, N_("Value"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, + { SOCK_FLOAT, 1, N_("From Min"), 0.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + { SOCK_FLOAT, 1, N_("From Max"), 1.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + { SOCK_FLOAT, 1, N_("To Min"), 0.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + { SOCK_FLOAT, 1, N_("To Max"), 1.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + { -1, 0, "" } +}; +static bNodeSocketTemplate cmp_node_map_range_out[] = { + { SOCK_FLOAT, 0, N_("Value")}, + { -1, 0, "" } +}; + +void register_node_type_cmp_map_range(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, CMP_NODE_MAP_RANGE, "Map Range", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + node_type_socket_templates(&ntype, cmp_node_map_range_in, cmp_node_map_range_out); + node_type_size(&ntype, 120, 60, 150); + + nodeRegisterType(ttype, &ntype); +} diff --git a/source/blender/nodes/composite/nodes/node_composite_math.c b/source/blender/nodes/composite/nodes/node_composite_math.c index bbd44c58314..5bc67adf5fb 100644 --- a/source/blender/nodes/composite/nodes/node_composite_math.c +++ b/source/blender/nodes/composite/nodes/node_composite_math.c @@ -103,7 +103,7 @@ static void do_math(bNode *node, float *out, float *in, float *in2) out[0] = pow(in[0], in2[0]); } else { - float y_mod_1 = ABS(fmod(in2[0], 1)); + float y_mod_1 = fabsf(fmodf(in2[0], 1.0f)); /* if input value is not nearly an integer, fall back to zero, nicer than straight rounding */ if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) { diff --git a/source/blender/nodes/composite/nodes/node_composite_normal.c b/source/blender/nodes/composite/nodes/node_composite_normal.c index 93fd7ca1c1b..d104e8f03e6 100644 --- a/source/blender/nodes/composite/nodes/node_composite_normal.c +++ b/source/blender/nodes/composite/nodes/node_composite_normal.c @@ -40,7 +40,7 @@ static bNodeSocketTemplate cmp_node_normal_in[] = { }; static bNodeSocketTemplate cmp_node_normal_out[] = { - { SOCK_VECTOR, 0, N_("Normal")}, + { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION}, { SOCK_FLOAT, 0, N_("Dot")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c index 656e2a72c03..214617c91e5 100644 --- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c +++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c @@ -242,7 +242,7 @@ static void exec_output_file_singlelayer(RenderData *rd, bNode *node, bNodeStack ImageFormatData *format = (sockdata->use_node_format ? &nimf->format : &sockdata->format); char path[FILE_MAX]; char filename[FILE_MAX]; - CompBuf *cbuf; + CompBuf *cbuf = NULL; ImBuf *ibuf; switch (format->planes) { diff --git a/source/blender/nodes/composite/nodes/node_composite_splitViewer.c b/source/blender/nodes/composite/nodes/node_composite_splitViewer.c index 73cf039c6df..41fb0e822ed 100644 --- a/source/blender/nodes/composite/nodes/node_composite_splitViewer.c +++ b/source/blender/nodes/composite/nodes/node_composite_splitViewer.c @@ -77,7 +77,7 @@ static void node_composit_exec_splitviewer(void *data, bNode *node, bNodeStack * ibuf= BKE_image_acquire_ibuf(ima, node->storage, &lock); if (ibuf==NULL) { printf("node_composit_exec_viewer error\n"); - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); return; } @@ -128,7 +128,7 @@ static void node_composit_exec_splitviewer(void *data, bNode *node, bNodeStack * composit3_pixel_processor(node, cbuf, buf1, in[0]->vec, buf2, in[1]->vec, mask, NULL, do_copy_split_rgba, CB_RGBA, CB_RGBA, CB_VAL); - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); generate_preview(data, node, cbuf); free_compbuf(cbuf); diff --git a/source/blender/nodes/composite/nodes/node_composite_viewer.c b/source/blender/nodes/composite/nodes/node_composite_viewer.c index 938f75cf3f5..1c27cc21b06 100644 --- a/source/blender/nodes/composite/nodes/node_composite_viewer.c +++ b/source/blender/nodes/composite/nodes/node_composite_viewer.c @@ -62,7 +62,7 @@ static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in, ibuf = BKE_image_acquire_ibuf(ima, node->storage, &lock); if (ibuf == NULL) { printf("node_composit_exec_viewer error\n"); - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); return; } @@ -112,7 +112,7 @@ static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in, free_compbuf(zbuf); } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); generate_preview(data, node, cbuf); free_compbuf(cbuf); diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c index 8e49484d1eb..69256fafc3d 100644 --- a/source/blender/nodes/intern/node_socket.c +++ b/source/blender/nodes/intern/node_socket.c @@ -41,6 +41,7 @@ #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLI_string.h" #include "BKE_DerivedMesh.h" #include "BKE_node.h" @@ -157,6 +158,20 @@ static bNodeSocketType node_socket_type_mesh = { /* buttonfunc */ NULL, }; +/****************** STRING ******************/ + +static bNodeSocketType node_socket_type_string = { + /* type */ SOCK_STRING, + /* ui_name */ "String", + /* ui_description */ "String", + /* ui_icon */ 0, + /* ui_color */ {255, 255, 255, 255}, + + /* value_structname */ "bNodeSocketValueString", + /* value_structsize */ sizeof(bNodeSocketValueString), + + /* buttonfunc */ NULL, +}; void node_socket_type_init(bNodeSocketType *types[]) { @@ -169,6 +184,7 @@ void node_socket_type_init(bNodeSocketType *types[]) INIT_TYPE(boolean); INIT_TYPE(shader); INIT_TYPE(mesh); + INIT_TYPE(string); #undef INIT_TYPE } @@ -218,6 +234,9 @@ void node_socket_init_default_value(int type, void *default_value) case SOCK_MESH: node_socket_set_default_value_mesh(default_value); break; + case SOCK_STRING: + node_socket_set_default_value_string(default_value, PROP_NONE, (char *)""); + break; } } @@ -265,6 +284,13 @@ void node_socket_set_default_value_rgba(void *default_value, float r, float g, f val->value[3] = a; } +void node_socket_set_default_value_string(void *default_value, PropertySubType subtype, const char *value) +{ + bNodeSocketValueString *val = default_value; + val->subtype = subtype; + BLI_strncpy(val->value, value, 1024);//FILE_MAX +} + void node_socket_set_default_value_shader(void *UNUSED(default_value)) { } @@ -282,12 +308,14 @@ void node_socket_copy_default_value(int type, void *to_default_value, void *from bNodeSocketValueBoolean *frombool= (bNodeSocketValueBoolean*)from_default_value; bNodeSocketValueVector *fromvector= (bNodeSocketValueVector*)from_default_value; bNodeSocketValueRGBA *fromrgba= (bNodeSocketValueRGBA*)from_default_value; + bNodeSocketValueString *fromstring= (bNodeSocketValueString*)from_default_value; bNodeSocketValueFloat *tofloat= (bNodeSocketValueFloat*)to_default_value; bNodeSocketValueInt *toint= (bNodeSocketValueInt*)to_default_value; bNodeSocketValueBoolean *tobool= (bNodeSocketValueBoolean*)to_default_value; bNodeSocketValueVector *tovector= (bNodeSocketValueVector*)to_default_value; bNodeSocketValueRGBA *torgba= (bNodeSocketValueRGBA*)to_default_value; + bNodeSocketValueString *tostring= (bNodeSocketValueString*)to_default_value; switch (type) { case SOCK_FLOAT: @@ -305,6 +333,9 @@ void node_socket_copy_default_value(int type, void *to_default_value, void *from case SOCK_RGBA: *torgba = *fromrgba; break; + case SOCK_STRING: + *tostring = *fromstring; + break; } } @@ -442,6 +473,35 @@ void node_socket_convert_default_value(int to_type, void *to_default_value, int } } +static void node_socket_set_minmax_subtype(bNodeSocket *sock, struct bNodeSocketTemplate *stemp) +{ + switch (sock->type) { + case SOCK_FLOAT: + { + bNodeSocketValueFloat *dval= sock->default_value; + dval->min = stemp->min; + dval->max = stemp->max; + dval->subtype = stemp->subtype; + break; + } + case SOCK_INT: + { + bNodeSocketValueInt *dval= sock->default_value; + dval->min = stemp->min; + dval->max = stemp->max; + dval->subtype = stemp->subtype; + break; + } + case SOCK_VECTOR: + { + bNodeSocketValueVector *dval= sock->default_value; + dval->min = stemp->min; + dval->max = stemp->max; + dval->subtype = stemp->subtype; + break; + } + } +} struct bNodeSocket *node_add_input_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp) { @@ -470,6 +530,9 @@ struct bNodeSocket *node_add_input_from_template(struct bNodeTree *ntree, struct case SOCK_MESH: node_socket_set_default_value_mesh(sock->default_value); break; + case SOCK_STRING: + node_socket_set_default_value_string(sock->default_value, stemp->subtype, (char *)""); + break; } return sock; @@ -478,6 +541,7 @@ struct bNodeSocket *node_add_input_from_template(struct bNodeTree *ntree, struct struct bNodeSocket *node_add_output_from_template(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocketTemplate *stemp) { bNodeSocket *sock = nodeAddSocket(ntree, node, SOCK_OUT, stemp->name, stemp->type); + node_socket_set_minmax_subtype(sock, stemp); return sock; } @@ -498,32 +562,7 @@ static bNodeSocket *verify_socket_template(bNodeTree *ntree, bNode *node, int in /* Copy the property range and subtype parameters in case the template changed. * NOT copying the actual value here, only button behavior changes! */ - switch (sock->type) { - case SOCK_FLOAT: - { - bNodeSocketValueFloat *dval= sock->default_value; - dval->min = stemp->min; - dval->max = stemp->max; - dval->subtype = stemp->subtype; - break; - } - case SOCK_INT: - { - bNodeSocketValueInt *dval= sock->default_value; - dval->min = stemp->min; - dval->max = stemp->max; - dval->subtype = stemp->subtype; - break; - } - case SOCK_VECTOR: - { - bNodeSocketValueVector *dval= sock->default_value; - dval->min = stemp->min; - dval->max = stemp->max; - dval->subtype = stemp->subtype; - break; - } - } + node_socket_set_minmax_subtype(sock, stemp); BLI_remlink(socklist, sock); diff --git a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c new file mode 100644 index 00000000000..7dfefc9ece0 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c @@ -0,0 +1,63 @@ +/* + * ***** 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_ambient_occlusion_in[] = { + { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_ambient_occlusion_out[] = { + { SOCK_SHADER, 0, N_("AO")}, + { -1, 0, "" } +}; + +static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "node_ambient_occlusion", in, out, GPU_builtin(GPU_VIEW_NORMAL)); +} + +/* node type definition */ +void register_node_type_sh_ambient_occlusion(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, SH_NODE_AMBIENT_OCCLUSION, "Ambient Occlusion", NODE_CLASS_SHADER, 0); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, sh_node_ambient_occlusion_in, sh_node_ambient_occlusion_out); + node_type_size(&ntype, 150, 60, 200); + node_type_init(&ntype, NULL); + node_type_storage(&ntype, "", NULL, NULL); + node_type_exec(&ntype, NULL); + node_type_gpu(&ntype, node_shader_gpu_ambient_occlusion); + + nodeRegisterType(ttype, &ntype); +} + diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c new file mode 100644 index 00000000000..99e66e39002 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c @@ -0,0 +1,68 @@ +/* + * ***** 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_bsdf_refraction_in[] = { + { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("IOR"), 1.45f, 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_bsdf_refraction_out[] = { + { SOCK_SHADER, 0, N_("BSDF")}, + { -1, 0, "" } +}; + +static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +{ + if (!in[3].link) + in[3].link = GPU_builtin(GPU_VIEW_NORMAL); + + return GPU_stack_link(mat, "node_bsdf_refraction", in, out); +} + +/* node type definition */ +void register_node_type_sh_bsdf_refraction(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, SH_NODE_BSDF_REFRACTION, "Refraction BSDF", NODE_CLASS_SHADER, NODE_OPTIONS); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, sh_node_bsdf_refraction_in, sh_node_bsdf_refraction_out); + node_type_size(&ntype, 150, 60, 200); + node_type_init(&ntype, NULL); + node_type_storage(&ntype, "", NULL, NULL); + node_type_exec(&ntype, NULL); + node_type_gpu(&ntype, node_shader_gpu_bsdf_refraction); + + nodeRegisterType(ttype, &ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.c b/source/blender/nodes/shader/nodes/node_shader_bump.c index 24ed825c36e..b0605f9b248 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bump.c +++ b/source/blender/nodes/shader/nodes/node_shader_bump.c @@ -36,7 +36,7 @@ /* **************** BUMP ******************** */ static bNodeSocketTemplate sh_node_bump_in[] = { - { SOCK_FLOAT, 1, "Strength", 0.1f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, + { SOCK_FLOAT, 1, "Strength", 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f}, { SOCK_FLOAT, 1, "Height", 1.0f, 1.0f, 1.0f, 1.0f, -1000.0f, 1000.0f, PROP_NONE, SOCK_HIDE_VALUE}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_material.c b/source/blender/nodes/shader/nodes/node_shader_material.c index bccf6d349cf..2902bf143c8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_material.c +++ b/source/blender/nodes/shader/nodes/node_shader_material.c @@ -85,7 +85,7 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, float col[4]; bNodeSocket *sock; char hasinput[NUM_MAT_IN] = {'\0'}; - int i; + int i, mode; /* note: cannot use the in[]->hasinput flags directly, as these are not necessarily * the constant input stack values (e.g. in case material node is inside a group). @@ -142,10 +142,18 @@ static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, nodestack_get_vec(&shi->translucency, SOCK_FLOAT, in[MAT_IN_TRANSLUCENCY]); } + /* make alpha output give results even if transparency is only enabled on + * the material linked in this not and not on the parent material */ + mode = shi->mode; + if(shi->mat->mode & MA_TRANSP) + shi->mode |= MA_TRANSP; + shi->nodes= 1; /* temp hack to prevent trashadow recursion */ node_shader_lamp_loop(shi, &shrnode); /* clears shrnode */ shi->nodes= 0; + shi->mode = mode; + /* write to outputs */ if (node->custom1 & SH_NODE_MAT_DIFF) { copy_v3_v3(col, shrnode.combined); diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c index 9dc900e6bd4..0b71a3f13b4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_math.c +++ b/source/blender/nodes/shader/nodes/node_shader_math.c @@ -142,7 +142,7 @@ bNodeStack **out) out[0]->vec[0] = pow(in[0]->vec[0], in[1]->vec[0]); } else { - float y_mod_1 = ABS(fmod(in[1]->vec[0], 1)); + float y_mod_1 = fabsf(fmodf(in[1]->vec[0], 1.0f)); /* if input value is not nearly an integer, fall back to zero, nicer than straight rounding */ if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) { @@ -225,8 +225,7 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUN case 13: case 15: case 16: - GPU_stack_link(mat, names[node->custom1], NULL, out, - GPU_socket(&in[0]), GPU_socket(&in[1])); + GPU_stack_link(mat, names[node->custom1], in, out); break; case 4: case 5: @@ -235,10 +234,20 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUN case 8: case 9: case 14: - if (in[0].hasinput || !in[1].hasinput) - GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[0])); - else - GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[1])); + if (in[0].hasinput || !in[1].hasinput) { + /* use only first item and terminator */ + GPUNodeStack tmp_in[2]; + memcpy(&tmp_in[0], &in[0], sizeof(GPUNodeStack)); + memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack)); + GPU_stack_link(mat, names[node->custom1], tmp_in, out); + } + else { + /* use only second item and terminator */ + GPUNodeStack tmp_in[2]; + memcpy(&tmp_in[0], &in[1], sizeof(GPUNodeStack)); + memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack)); + GPU_stack_link(mat, names[node->custom1], tmp_in, out); + } break; default: return 0; diff --git a/source/blender/nodes/shader/nodes/node_shader_normal.c b/source/blender/nodes/shader/nodes/node_shader_normal.c index 98a56c85279..0ad58d6af76 100644 --- a/source/blender/nodes/shader/nodes/node_shader_normal.c +++ b/source/blender/nodes/shader/nodes/node_shader_normal.c @@ -34,12 +34,12 @@ /* **************** NORMAL ******************** */ static bNodeSocketTemplate sh_node_normal_in[] = { - { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE}, + { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION}, { -1, 0, "" } }; static bNodeSocketTemplate sh_node_normal_out[] = { - { SOCK_VECTOR, 0, N_("Normal")}, + { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION}, { SOCK_FLOAT, 0, N_("Dot")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c new file mode 100644 index 00000000000..6a4eb9d81df --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c @@ -0,0 +1,70 @@ +/* + * ***** 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_normal_map_in[] = { + { SOCK_FLOAT, 1, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f}, + { SOCK_RGBA, 1, N_("Color"), 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_normal_map_out[] = { + { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void node_shader_init_normal_map(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +{ + NodeShaderNormalMap *attr = MEM_callocN(sizeof(NodeShaderNormalMap), "NodeShaderNormalMap"); + node->storage = attr; +} + +static int gpu_shader_normal_map(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "node_normal_map", in, out, GPU_builtin(GPU_VIEW_NORMAL)); +} + +/* node type definition */ +void register_node_type_sh_normal_map(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, SH_NODE_NORMAL_MAP, "Normal Map", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, sh_node_normal_map_in, sh_node_normal_map_out); + node_type_size(&ntype, 250, 60, 250); + node_type_init(&ntype, node_shader_init_normal_map); + node_type_storage(&ntype, "NodeShaderNormalMap", node_free_standard_storage, node_copy_standard_storage); + node_type_exec(&ntype, NULL); + node_type_gpu(&ntype, gpu_shader_normal_map); + + nodeRegisterType(ttype, &ntype); +} + diff --git a/source/blender/nodes/shader/nodes/node_shader_script.c b/source/blender/nodes/shader/nodes/node_shader_script.c index d4c2d188ffa..b5563658a64 100644 --- a/source/blender/nodes/shader/nodes/node_shader_script.c +++ b/source/blender/nodes/shader/nodes/node_shader_script.c @@ -64,7 +64,7 @@ static void node_copy_script(bNode *orig_node, bNode *new_node) NodeShaderScript *orig_nss = orig_node->storage; NodeShaderScript *new_nss = MEM_dupallocN(orig_nss); - if(orig_nss->bytecode) + if (orig_nss->bytecode) new_nss->bytecode = MEM_dupallocN(orig_nss->bytecode); if (orig_nss->prop) diff --git a/source/blender/nodes/shader/nodes/node_shader_tangent.c b/source/blender/nodes/shader/nodes/node_shader_tangent.c new file mode 100644 index 00000000000..6c0d6d7cd9f --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_tangent.c @@ -0,0 +1,60 @@ +/* + * ***** 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_tangent_out[] = { + { SOCK_VECTOR, 0, N_("Tangent"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static void node_shader_init_tangent(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) +{ + NodeShaderTangent *attr = MEM_callocN(sizeof(NodeShaderTangent), "NodeShaderTangent"); + attr->axis = SHD_TANGENT_AXIS_Z; + node->storage = attr; +} + +/* node type definition */ +void register_node_type_sh_tangent(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, SH_NODE_TANGENT, "Tangent", NODE_CLASS_INPUT, NODE_OPTIONS); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, NULL, sh_node_tangent_out); + node_type_size(&ntype, 150, 60, 200); + node_type_init(&ntype, node_shader_init_tangent); + node_type_storage(&ntype, "NodeShaderTangent", node_free_standard_storage, node_copy_standard_storage); + node_type_exec(&ntype, NULL); + node_type_gpu(&ntype, NULL); + + nodeRegisterType(ttype, &ntype); +} + diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c index abe8e0190c8..d2d0870e2ed 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -75,12 +75,13 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, GPUNod ret = GPU_stack_link(mat, "node_tex_environment", in, out, GPU_image(ima, iuser, isdata)); if (ret) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && GPU_material_do_color_management(mat)) { GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); } + BKE_image_release_ibuf(ima, ibuf, NULL); } return ret; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index 9b17f76bd47..49b38434246 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -75,12 +75,13 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, GPUNodeStack ret = GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata)); if (ret) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && GPU_material_do_color_management(mat)) { GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); } + BKE_image_release_ibuf(ima, ibuf, NULL); } return ret; diff --git a/source/blender/nodes/shader/nodes/node_shader_texture.c b/source/blender/nodes/shader/nodes/node_shader_texture.c index 6d1b3ff6dba..b77c7d07407 100644 --- a/source/blender/nodes/shader/nodes/node_shader_texture.c +++ b/source/blender/nodes/shader/nodes/node_shader_texture.c @@ -128,12 +128,13 @@ static int gpu_shader_texture(GPUMaterial *mat, bNode *node, GPUNodeStack *in, G int ret = GPU_stack_link(mat, "texture_image", in, out, texlink); if (ret) { - ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) ==0 && GPU_material_do_color_management(mat)) { GPU_link(mat, "srgb_to_linearrgb", out[1].link, &out[1].link); } + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } return ret; diff --git a/source/blender/nodes/shader/nodes/node_shader_vectMath.c b/source/blender/nodes/shader/nodes/node_shader_vectMath.c index 2d9f1903c5b..3e00421ddf0 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vectMath.c +++ b/source/blender/nodes/shader/nodes/node_shader_vectMath.c @@ -114,14 +114,23 @@ static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, case 2: case 3: case 4: - GPU_stack_link(mat, names[node->custom1], NULL, out, - GPU_socket(&in[0]), GPU_socket(&in[1])); + GPU_stack_link(mat, names[node->custom1], in, out); break; case 5: - if (in[0].hasinput || !in[1].hasinput) - GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[0])); - else - GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[1])); + if (in[0].hasinput || !in[1].hasinput) { + /* use only first item and terminator */ + GPUNodeStack tmp_in[2]; + memcpy(&tmp_in[0], &in[0], sizeof(GPUNodeStack)); + memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack)); + GPU_stack_link(mat, names[node->custom1], tmp_in, out); + } + else { + /* use only second item and terminator */ + GPUNodeStack tmp_in[2]; + memcpy(&tmp_in[0], &in[1], sizeof(GPUNodeStack)); + memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack)); + GPU_stack_link(mat, names[node->custom1], tmp_in, out); + } break; default: return 0; diff --git a/source/blender/nodes/texture/nodes/node_texture_image.c b/source/blender/nodes/texture/nodes/node_texture_image.c index f3fdaf0bb64..2ef1669a266 100644 --- a/source/blender/nodes/texture/nodes/node_texture_image.c +++ b/source/blender/nodes/texture/nodes/node_texture_image.c @@ -46,7 +46,7 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNUSED(i ImageUser *iuser= (ImageUser *)node->storage; if ( ima ) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if ( ibuf ) { float xsize, ysize; float xoff, yoff; @@ -77,6 +77,8 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNUSED(i result = ibuf->rect_float + py*ibuf->x*4 + px*4; copy_v4_v4(out, result); + + BKE_image_release_ibuf(ima, ibuf, NULL); } } } diff --git a/source/blender/python/bmesh/CMakeLists.txt b/source/blender/python/bmesh/CMakeLists.txt index 032a914fb70..ccabe572ce5 100644 --- a/source/blender/python/bmesh/CMakeLists.txt +++ b/source/blender/python/bmesh/CMakeLists.txt @@ -34,6 +34,7 @@ set(INC_SYS set(SRC bmesh_py_api.c bmesh_py_ops.c + bmesh_py_ops_call.c bmesh_py_types.c bmesh_py_types_customdata.c bmesh_py_types_meshdata.c @@ -42,6 +43,7 @@ set(SRC bmesh_py_api.h bmesh_py_ops.h + bmesh_py_ops_call.h bmesh_py_types.h bmesh_py_types_customdata.h bmesh_py_types_meshdata.h diff --git a/source/blender/python/bmesh/bmesh_py_api.c b/source/blender/python/bmesh/bmesh_py_api.c index e02efc79da0..18f5d895132 100644 --- a/source/blender/python/bmesh/bmesh_py_api.c +++ b/source/blender/python/bmesh/bmesh_py_api.c @@ -51,7 +51,6 @@ #include "bmesh_py_api.h" /* own include */ - PyDoc_STRVAR(bpy_bm_new_doc, ".. method:: new()\n" "\n" @@ -73,6 +72,8 @@ PyDoc_STRVAR(bpy_bm_from_edit_mesh_doc, "\n" " Return a BMesh from this mesh, currently the mesh must already be in editmode.\n" "\n" +" :arg mesh: The editmode mesh.\n" +" :type mesh: :class:`bpy.types.Mesh`\n" " :return: the BMesh associated with this mesh.\n" " :rtype: :class:`bmesh.types.BMesh`\n" ); @@ -96,22 +97,62 @@ static PyObject *bpy_bm_from_edit_mesh(PyObject *UNUSED(self), PyObject *value) return BPy_BMesh_CreatePyObject(bm, BPY_BMFLAG_IS_WRAPPED); } +PyDoc_STRVAR(bpy_bm_update_edit_mesh_doc, +".. method:: update_edit_mesh(mesh, tessface=True)\n" +"\n" +" Update the mesh after changes to the BMesh in editmode, \n" +" optionally recalculating n-gon tessellation.\n" +"\n" +" :arg mesh: The editmode mesh.\n" +" :type mesh: :class:`bpy.types.Mesh`\n" +" :arg tessface: Option to recalculate n-gon tessellation.\n" +" :type tessface: boolean\n" +); +static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args) +{ + PyObject *py_me; + Mesh *me; + int do_tessface = TRUE; + + if (!PyArg_ParseTuple(args, "O|i:update_edit_mesh", &py_me, &do_tessface)) { + return NULL; + } + + me = PyC_RNA_AsPointer(py_me, "Mesh"); + + if (me == NULL) { + return NULL; + } + + if (me->edit_btmesh == NULL) { + PyErr_SetString(PyExc_ValueError, + "The mesh must be in editmode"); + return NULL; + } + + { + /* XXX, not great - infact this function could just not use the context at all + * postpone that change until after release: BMESH_TODO - campbell */ + extern struct bContext *BPy_GetContext(void); + extern void EDBM_update_generic(struct bContext *C, BMEditMesh *em, const short do_tessface); + + struct bContext *C = BPy_GetContext(); + EDBM_update_generic(C, me->edit_btmesh, do_tessface); + } + + Py_RETURN_NONE; +} + static struct PyMethodDef BPy_BM_methods[] = { {"new", (PyCFunction)bpy_bm_new, METH_NOARGS, bpy_bm_new_doc}, {"from_edit_mesh", (PyCFunction)bpy_bm_from_edit_mesh, METH_O, bpy_bm_from_edit_mesh_doc}, + {"update_edit_mesh", (PyCFunction)bpy_bm_update_edit_mesh, METH_VARARGS, bpy_bm_update_edit_mesh_doc}, {NULL, NULL, 0, NULL} }; PyDoc_STRVAR(BPy_BM_doc, "This module provides access to blenders bmesh data structures.\n" "\n" -"\n" -"Submodules:\n" -"\n" -"* :mod:`bmesh.utils`\n" -"* :mod:`bmesh.types`\n" -"\n" -"\n" ".. include:: include__bmesh.rst\n" ); static struct PyModuleDef BPy_BM_module_def = { diff --git a/source/blender/python/bmesh/bmesh_py_ops.c b/source/blender/python/bmesh/bmesh_py_ops.c index fb5b94249e6..0a2091af5df 100644 --- a/source/blender/python/bmesh/bmesh_py_ops.c +++ b/source/blender/python/bmesh/bmesh_py_ops.c @@ -38,39 +38,19 @@ #include "../generic/py_capi_utils.h" -#include "../mathutils/mathutils.h" - #include "bmesh.h" +#include "bmesh_py_ops_call.h" #include "bmesh_py_ops.h" /* own include */ #include "bmesh_py_types.h" -#include "bmesh_py_utils.h" /* own include */ - -static int bpy_bm_op_as_py_error(BMesh *bm) -{ - if (BMO_error_occurred(bm)) { - const char *errmsg; - if (BMO_error_get(bm, &errmsg, NULL)) { - PyErr_Format(PyExc_RuntimeError, - "bmesh operator: %.200s", - errmsg); - return -1; - } - } - return 0; -} +#include "bmesh_py_utils.h" /* bmesh operator 'bmesh.ops.*' callable types * ******************************************* */ PyTypeObject bmesh_op_Type; -typedef struct { - PyObject_HEAD /* required python macro */ - const char *opname; -} BPy_BMeshOpFunc; - static PyObject *bpy_bmesh_op_CreatePyObject(const char *opname) { BPy_BMeshOpFunc *self = PyObject_New(BPy_BMeshOpFunc, &bmesh_op_Type); @@ -88,243 +68,6 @@ static PyObject *bpy_bmesh_op_repr(BPy_BMeshOpFunc *self) } -static PyObject *pyrna_op_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw) -{ - BPy_BMesh *py_bm; - BMesh *bm; - - BMOperator bmop; - - if ((PyTuple_GET_SIZE(args) == 1) && - (py_bm = (BPy_BMesh *)PyTuple_GET_ITEM(args, 0)) && - (BPy_BMesh_Check(py_bm)) - ) - { - BPY_BM_CHECK_OBJ(py_bm); - bm = py_bm->bm; - } - else { - PyErr_SetString(PyExc_TypeError, - "calling a bmesh operator expects a single BMesh (non keyword) " - "as the first argument"); - return NULL; - } - - /* TODO - error check this!, though we do the error check on attribute access */ - /* TODO - make flags optional */ - BMO_op_init(bm, &bmop, BMO_FLAG_DEFAULTS, self->opname); - - if (kw && PyDict_Size(kw) > 0) { - /* setup properties, see bpy_rna.c: pyrna_py_to_prop() - * which shares this logic for parsing properties */ - - PyObject *key, *value; - Py_ssize_t pos = 0; - while (PyDict_Next(kw, &pos, &key, &value)) { - const char *slot_name = _PyUnicode_AsString(key); - BMOpSlot *slot = BMO_slot_get(&bmop, slot_name); - - if (slot == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s: keyword \"%.200s\" is invalid for this operator", - self->opname, slot_name); - return NULL; - } - - /* now assign the value */ - switch (slot->slot_type) { - case BMO_OP_SLOT_BOOL: - { - int param; - - param = PyLong_AsLong(value); - - if (param < 0) { - PyErr_Format(PyExc_TypeError, - "%.200s: keyword \"%.200s\" expected True/False or 0/1, not %.200s", - self->opname, slot_name, Py_TYPE(value)->tp_name); - return NULL; - } - else { - slot->data.i = param; - } - - break; - } - case BMO_OP_SLOT_INT: - { - int overflow; - long param = PyLong_AsLongAndOverflow(value, &overflow); - if (overflow || (param > INT_MAX) || (param < INT_MIN)) { - PyErr_Format(PyExc_ValueError, - "%.200s: keyword \"%.200s\" value not in 'int' range " - "(" STRINGIFY(INT_MIN) ", " STRINGIFY(INT_MAX) ")", - self->opname, slot_name, Py_TYPE(value)->tp_name); - return NULL; - } - else if (param == -1 && PyErr_Occurred()) { - PyErr_Format(PyExc_TypeError, - "%.200s: keyword \"%.200s\" expected an int, not %.200s", - self->opname, slot_name, Py_TYPE(value)->tp_name); - return NULL; - } - else { - slot->data.i = (int)param; - } - break; - } - case BMO_OP_SLOT_FLT: - { - float param = PyFloat_AsDouble(value); - if (param == -1 && PyErr_Occurred()) { - PyErr_Format(PyExc_TypeError, - "%.200s: keyword \"%.200s\" expected a float, not %.200s", - self->opname, slot_name, Py_TYPE(value)->tp_name); - return NULL; - } - else { - slot->data.f = param; - } - break; - } - case BMO_OP_SLOT_MAT: - { - /* XXX - BMesh operator design is crappy here, operator slot should define matrix size, - * not the caller! */ - unsigned short size; - if (!MatrixObject_Check(value)) { - PyErr_Format(PyExc_TypeError, - "%.200s: keyword \"%.200s\" expected a Matrix, not %.200s", - self->opname, slot_name, Py_TYPE(value)->tp_name); - return NULL; - } - else if (BaseMath_ReadCallback((MatrixObject *)value) == -1) { - return NULL; - } - else if (((size = ((MatrixObject *)value)->num_col) != ((MatrixObject *)value)->num_row) || - (ELEM(size, 3, 4) == FALSE)) - { - PyErr_Format(PyExc_TypeError, - "%.200s: keyword \"%.200s\" expected a 3x3 or 4x4 matrix Matrix", - self->opname, slot_name); - return NULL; - } - - BMO_slot_mat_set(&bmop, slot_name, ((MatrixObject *)value)->matrix, size); - break; - } - case BMO_OP_SLOT_VEC: - { - /* passing slot name here is a bit non-descriptive */ - if (mathutils_array_parse(slot->data.vec, 3, 3, value, slot_name) == -1) { - return NULL; - } - break; - } - case BMO_OP_SLOT_ELEMENT_BUF: - { - /* there are many ways we could interpret arguments, for now... - * - verts/edges/faces from the mesh direct, - * this way the operator takes every item. - * - `TODO` a plain python sequence (list) of elements. - * - `TODO` an iterator. eg. - * face.verts - * - `TODO` (type, flag) pair, eg. - * ('VERT', {'TAG'}) - */ - -#define BPY_BM_GENERIC_MESH_TEST(type_string) \ - if (((BPy_BMGeneric *)value)->bm != bm) { \ - PyErr_Format(PyExc_NotImplementedError, \ - "%.200s: keyword \"%.200s\" " type_string " are from another bmesh", \ - self->opname, slot_name, slot->slot_type); \ - return NULL; \ - } (void)0 - - if (BPy_BMVertSeq_Check(value)) { - BPY_BM_GENERIC_MESH_TEST("verts"); - BMO_slot_buffer_from_all(bm, &bmop, slot_name, BM_VERT); - } - else if (BPy_BMEdgeSeq_Check(value)) { - BPY_BM_GENERIC_MESH_TEST("edges"); - BMO_slot_buffer_from_all(bm, &bmop, slot_name, BM_EDGE); - } - else if (BPy_BMFaceSeq_Check(value)) { - BPY_BM_GENERIC_MESH_TEST("faces"); - BMO_slot_buffer_from_all(bm, &bmop, slot_name, BM_FACE); - } - else if (BPy_BMElemSeq_Check(value)) { - BMIter iter; - BMHeader *ele; - int tot; - unsigned int i; - - BPY_BM_GENERIC_MESH_TEST("elements"); - - /* this will loop over all elements which is a shame but - * we need to know this before alloc */ - /* calls bpy_bmelemseq_length() */ - tot = Py_TYPE(value)->tp_as_sequence->sq_length((PyObject *)self); - - BMO_slot_buffer_alloc(&bmop, slot_name, tot); - - i = 0; - BM_ITER_BPY_BM_SEQ (ele, &iter, ((BPy_BMElemSeq *)value)) { - ((void **)slot->data.buf)[i] = (void *)ele; - i++; - } - } - /* keep this last */ - else if (PySequence_Check(value)) { - BMElem **elem_array = NULL; - Py_ssize_t elem_array_len; - - elem_array = BPy_BMElem_PySeq_As_Array(&bm, value, 0, PY_SSIZE_T_MAX, - &elem_array_len, BM_VERT | BM_EDGE | BM_FACE, - TRUE, TRUE, slot_name); - - /* error is set above */ - if (elem_array == NULL) { - return NULL; - } - - BMO_slot_buffer_alloc(&bmop, slot_name, elem_array_len); - memcpy(slot->data.buf, elem_array, sizeof(void *) * elem_array_len); - PyMem_FREE(elem_array); - } - else { - PyErr_Format(PyExc_TypeError, - "%.200s: keyword \"%.200s\" expected " - "a bmesh sequence, list, (htype, flag) pair, not %.200s", - self->opname, slot_name, Py_TYPE(value)->tp_name); - return NULL; - } - -#undef BPY_BM_GENERIC_MESH_TEST - - break; - } - default: - /* TODO --- many others */ - PyErr_Format(PyExc_NotImplementedError, - "%.200s: keyword \"%.200s\" type %d not working yet!", - self->opname, slot_name, slot->slot_type); - return NULL; - break; - } - } - } - - BMO_op_exec(bm, &bmop); - BMO_op_finish(bm, &bmop); - - if (bpy_bm_op_as_py_error(bm) == -1) { - return NULL; - } - - Py_RETURN_NONE; -} - PyTypeObject bmesh_op_Type = { PyVarObject_HEAD_INIT(NULL, 0) @@ -348,7 +91,7 @@ PyTypeObject bmesh_op_Type = { /* More standard operations (here for binary compatibility) */ NULL, /* hashfunc tp_hash; */ - (ternaryfunc)pyrna_op_call, /* ternaryfunc tp_call; */ + (ternaryfunc)BPy_BMO_call, /* ternaryfunc tp_call; */ NULL, /* reprfunc tp_str; */ /* will only use these if this is a subtype of a py class */ @@ -409,41 +152,41 @@ PyTypeObject bmesh_op_Type = { /* bmesh fake module 'bmesh.ops' * ***************************** */ -static PyObject *bpy_bmesh_fmod_getattro(PyObject *UNUSED(self), PyObject *pyname) +static PyObject *bpy_bmesh_ops_fakemod_getattro(PyObject *UNUSED(self), PyObject *pyname) { - const unsigned int tot = bmesh_total_ops; + const unsigned int tot = bmo_opdefines_total; unsigned int i; - const char *name = _PyUnicode_AsString(pyname); + const char *opname = _PyUnicode_AsString(pyname); for (i = 0; i < tot; i++) { - if (strcmp(opdefines[i]->name, name) == 0) { - return bpy_bmesh_op_CreatePyObject(opdefines[i]->name); + if (strcmp(bmo_opdefines[i]->opname, opname) == 0) { + return bpy_bmesh_op_CreatePyObject(opname); } } PyErr_Format(PyExc_AttributeError, "BMeshOpsModule: operator \"%.200s\" doesn't exist", - name); + opname); return NULL; } -static PyObject *bpy_bmesh_fmod_dir(PyObject *UNUSED(self)) +static PyObject *bpy_bmesh_ops_fakemod_dir(PyObject *UNUSED(self)) { - const unsigned int tot = bmesh_total_ops; + const unsigned int tot = bmo_opdefines_total; unsigned int i; PyObject *ret; - ret = PyList_New(bmesh_total_ops); + ret = PyList_New(bmo_opdefines_total); for (i = 0; i < tot; i++) { - PyList_SET_ITEM(ret, i, PyUnicode_FromString(opdefines[i]->name)); + PyList_SET_ITEM(ret, i, PyUnicode_FromString(bmo_opdefines[i]->opname)); } return ret; } -static struct PyMethodDef bpy_bmesh_fmod_methods[] = { - {"__dir__", (PyCFunction)bpy_bmesh_fmod_dir, METH_NOARGS, NULL}, +static struct PyMethodDef bpy_bmesh_ops_fakemod_methods[] = { + {"__dir__", (PyCFunction)bpy_bmesh_ops_fakemod_dir, METH_NOARGS, NULL}, {NULL, NULL, 0, NULL} }; @@ -473,7 +216,7 @@ static PyTypeObject bmesh_ops_fakemod_Type = { NULL, /* reprfunc tp_str; */ /* will only use these if this is a subtype of a py class */ - bpy_bmesh_fmod_getattro, /* getattrofunc tp_getattro; */ + bpy_bmesh_ops_fakemod_getattro, /* getattrofunc tp_getattro; */ NULL, /* setattrofunc tp_setattro; */ /* Functions to access object as input/output buffer */ @@ -502,7 +245,7 @@ static PyTypeObject bmesh_ops_fakemod_Type = { NULL, /* iternextfunc tp_iternext; */ /*** Attribute descriptor and subclassing stuff ***/ - bpy_bmesh_fmod_methods, /* struct PyMethodDef *tp_methods; */ + bpy_bmesh_ops_fakemod_methods, /* struct PyMethodDef *tp_methods; */ NULL, /* struct PyMemberDef *tp_members; */ NULL, /* struct PyGetSetDef *tp_getset; */ NULL, /* struct _typeobject *tp_base; */ diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c new file mode 100644 index 00000000000..ded35363287 --- /dev/null +++ b/source/blender/python/bmesh/bmesh_py_ops_call.c @@ -0,0 +1,783 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/bmesh/bmesh_py_ops_call.c + * \ingroup pybmesh + * + * This file provides __call__ aka BPy_BMO_call for + * the bmesh operatorand has been given its own file + * because argument conversion is involved. + */ + +#include + +#include "BLI_utildefines.h" + +#include "../mathutils/mathutils.h" + +#include "bmesh.h" + +#include "bmesh_py_ops.h" +#include "bmesh_py_ops_call.h" /* own include */ + +#include "bmesh_py_types.h" +#include "bmesh_py_utils.h" + +static int bpy_bm_op_as_py_error(BMesh *bm) +{ + if (BMO_error_occurred(bm)) { + const char *errmsg; + if (BMO_error_get(bm, &errmsg, NULL)) { + PyErr_Format(PyExc_RuntimeError, + "bmesh operator: %.200s", + errmsg); + return -1; + } + } + return 0; +} + +/** + * \brief Utility function to check BMVert/BMEdge/BMFace's + * + * \param value + * \param bm Check the \a value against this. + * \param htype Test \a value matches this type. + * \param descr Description text. + */ +static int bpy_slot_from_py_elem_check(BPy_BMElem *value, BMesh *bm, const char htype, + /* for error messages */ + const char *opname, const char *slot_name, const char *descr) +{ + if (!BPy_BMElem_Check(value) || + !(value->ele->head.htype & htype)) + { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" %.200s, expected a %.200s not *.200s", + opname, slot_name, descr, + BPy_BMElem_StringFromHType(htype), + Py_TYPE(value)->tp_name); + return -1; + } + else if (value->bm == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" %.200s invalidated element", + opname, slot_name, descr); + return -1; + } + else if (value->bm != bm) { /* we may want to make this check optional by setting 'bm' to NULL */ + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" %.200s invalidated element", + opname, slot_name, descr); + return -1; + } + return 0; +} + +/** + * \brief Utility function to check BMVertSeq/BMEdgeSeq/BMFaceSeq's + * + * \param value Caller must check its a BMeshSeq + * \param bm Check the \a value against this. + * \param htype_py The type(s) of \a value. + * \param htype_bmo The type(s) supported by the target slot. + * \param descr Description text. + */ +static int bpy_slot_from_py_elemseq_check(BPy_BMGeneric *value, BMesh *bm, + const char htype_py, const char htype_bmo, + /* for error messages */ + const char *opname, const char *slot_name, const char *descr) +{ + if (value->bm == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" %.200s, invalidated sequence", + opname, slot_name, descr); + return -1; + } + else if (value->bm != bm) { /* we may want to make this check optional by setting 'bm' to NULL */ + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" %.200s, invalidated sequence", + opname, slot_name, descr); + return -1; + } + else if ((htype_py & htype_bmo) == 0) { + char str_bmo[32]; + char str_py[32]; + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" %.200s, expected " + "a sequence of %.200s not %.200s", + opname, slot_name, descr, + BPy_BMElem_StringFromHType_ex(htype_bmo, str_bmo), + BPy_BMElem_StringFromHType_ex(htype_py, str_py)); + return -1; + } + + return 0; +} + +/** + * Use for giving py args to an operator. + */ +static int bpy_slot_from_py(BMesh *bm, BMOperator *bmop, BMOpSlot *slot, PyObject *value, + /* the are just for exception messages */ + const char *opname, const char *slot_name) +{ + switch (slot->slot_type) { + case BMO_OP_SLOT_BOOL: + { + int param; + + param = PyLong_AsLong(value); + + if (param < 0) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected True/False or 0/1, not %.200s", + opname, slot_name, Py_TYPE(value)->tp_name); + return -1; + } + else { + BMO_SLOT_AS_BOOL(slot) = param; + } + + break; + } + case BMO_OP_SLOT_INT: + { + int overflow; + long param = PyLong_AsLongAndOverflow(value, &overflow); + if (overflow || (param > INT_MAX) || (param < INT_MIN)) { + PyErr_Format(PyExc_ValueError, + "%.200s: keyword \"%.200s\" value not in 'int' range " + "(" STRINGIFY(INT_MIN) ", " STRINGIFY(INT_MAX) ")", + opname, slot_name, Py_TYPE(value)->tp_name); + return -1; + } + else if (param == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected an int, not %.200s", + opname, slot_name, Py_TYPE(value)->tp_name); + return -1; + } + else { + BMO_SLOT_AS_INT(slot) = (int)param; + } + break; + } + case BMO_OP_SLOT_FLT: + { + float param = PyFloat_AsDouble(value); + if (param == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected a float, not %.200s", + opname, slot_name, Py_TYPE(value)->tp_name); + return -1; + } + else { + BMO_SLOT_AS_FLOAT(slot) = param; + } + break; + } + case BMO_OP_SLOT_MAT: + { + /* XXX - BMesh operator design is crappy here, operator slot should define matrix size, + * not the caller! */ + unsigned short size; + if (!MatrixObject_Check(value)) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected a Matrix, not %.200s", + opname, slot_name, Py_TYPE(value)->tp_name); + return -1; + } + else if (BaseMath_ReadCallback((MatrixObject *)value) == -1) { + return -1; + } + else if (((size = ((MatrixObject *)value)->num_col) != ((MatrixObject *)value)->num_row) || + (ELEM(size, 3, 4) == FALSE)) + { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected a 3x3 or 4x4 matrix Matrix", + opname, slot_name); + return -1; + } + + BMO_slot_mat_set(bmop, bmop->slots_in, slot_name, ((MatrixObject *)value)->matrix, size); + break; + } + case BMO_OP_SLOT_VEC: + { + /* passing slot name here is a bit non-descriptive */ + if (mathutils_array_parse(BMO_SLOT_AS_VECTOR(slot), 3, 3, value, slot_name) == -1) { + return -1; + } + break; + } + case BMO_OP_SLOT_ELEMENT_BUF: + { + if (slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) { + if (bpy_slot_from_py_elem_check((BPy_BMElem *)value, bm, (slot->slot_subtype.elem & BM_ALL_NOLOOP), + opname, slot_name, "single element") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + BMO_slot_buffer_from_single(bmop, slot, &((BPy_BMElem *)value)->ele->head); + } + else { + /* there are many ways we could interpret arguments, for now... + * - verts/edges/faces from the mesh direct, + * this way the operator takes every item. + * - `TODO` a plain python sequence (list) of elements. + * - `TODO` an iterator. eg. + * face.verts + * - `TODO` (type, flag) pair, eg. + * ('VERT', {'TAG'}) + */ + + if (BPy_BMVertSeq_Check(value)) { + if (bpy_slot_from_py_elemseq_check((BPy_BMGeneric *)value, bm, + BM_VERT, (slot->slot_subtype.elem & BM_ALL_NOLOOP), + opname, slot_name, "element buffer") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + BMO_slot_buffer_from_all(bm, bmop, bmop->slots_in, slot_name, BM_VERT); + } + else if (BPy_BMEdgeSeq_Check(value)) { + if (bpy_slot_from_py_elemseq_check((BPy_BMGeneric *)value, bm, + BM_EDGE, (slot->slot_subtype.elem & BM_ALL_NOLOOP), + opname, slot_name, "element buffer") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + BMO_slot_buffer_from_all(bm, bmop, bmop->slots_in, slot_name, BM_EDGE); + } + else if (BPy_BMFaceSeq_Check(value)) { + if (bpy_slot_from_py_elemseq_check((BPy_BMGeneric *)value, bm, + BM_FACE, (slot->slot_subtype.elem & BM_ALL_NOLOOP), + opname, slot_name, "element buffer") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + BMO_slot_buffer_from_all(bm, bmop, bmop->slots_in, slot_name, BM_FACE); + } + + else if (BPy_BMElemSeq_Check(value)) { + BMIter iter; + BMHeader *ele; + int tot; + unsigned int i; + + if (bpy_slot_from_py_elemseq_check((BPy_BMGeneric *)value, bm, + bm_iter_itype_htype_map[((BPy_BMElemSeq *)value)->itype], + (slot->slot_subtype.elem & BM_ALL_NOLOOP), + opname, slot_name, "element buffer") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + /* this will loop over all elements which is a shame but + * we need to know this before alloc */ + /* calls bpy_bmelemseq_length() */ + tot = Py_TYPE(value)->tp_as_sequence->sq_length(value); + + BMO_slot_buffer_alloc(bmop, bmop->slots_in, slot_name, tot); + + i = 0; + BM_ITER_BPY_BM_SEQ (ele, &iter, ((BPy_BMElemSeq *)value)) { + slot->data.buf[i] = ele; + i++; + } + } + /* keep this last */ + else if (PySequence_Check(value)) { + BMElem **elem_array = NULL; + Py_ssize_t elem_array_len; + + elem_array = BPy_BMElem_PySeq_As_Array(&bm, value, 0, PY_SSIZE_T_MAX, + &elem_array_len, (slot->slot_subtype.elem & BM_ALL_NOLOOP), + TRUE, TRUE, slot_name); + + /* error is set above */ + if (elem_array == NULL) { + return -1; + } + + BMO_slot_buffer_alloc(bmop, bmop->slots_in, slot_name, elem_array_len); + memcpy(slot->data.buf, elem_array, sizeof(void *) * elem_array_len); + PyMem_FREE(elem_array); + } + else { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected " + "a bmesh sequence, list, (htype, flag) pair, not %.200s", + opname, slot_name, Py_TYPE(value)->tp_name); + return -1; + } + } + break; + } + case BMO_OP_SLOT_MAPPING: + { + /* first check types */ + if (slot->slot_subtype.map != BMO_OP_SLOT_SUBTYPE_MAP_EMPTY) { + if (!PyDict_Check(value)) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected " + "a dict, not %.200s", + opname, slot_name, Py_TYPE(value)->tp_name); + return -1; + } + } + else { + if (!PySet_Check(value)) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected " + "a set, not %.200s", + opname, slot_name, Py_TYPE(value)->tp_name); + return -1; + } + } + + switch (slot->slot_subtype.map) { + case BMO_OP_SLOT_SUBTYPE_MAP_ELEM: + { + if (PyDict_Size(value) > 0) { + PyObject *arg_key, *arg_value; + Py_ssize_t arg_pos = 0; + while (PyDict_Next(value, &arg_pos, &arg_key, &arg_value)) { + if (bpy_slot_from_py_elem_check((BPy_BMElem *)arg_key, bm, BM_ALL_NOLOOP, + opname, slot_name, "invalid key in dict") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + if (bpy_slot_from_py_elem_check((BPy_BMElem *)arg_value, bm, BM_ALL_NOLOOP, + opname, slot_name, "invalid value in dict") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + BMO_slot_map_elem_insert(bmop, slot, + ((BPy_BMElem *)arg_key)->ele, ((BPy_BMElem *)arg_value)->ele); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_FLT: + { + if (PyDict_Size(value) > 0) { + PyObject *arg_key, *arg_value; + Py_ssize_t arg_pos = 0; + while (PyDict_Next(value, &arg_pos, &arg_key, &arg_value)) { + float value_f; + + if (bpy_slot_from_py_elem_check((BPy_BMElem *)arg_key, bm, BM_ALL_NOLOOP, + opname, slot_name, "invalid key in dict") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + value_f = PyFloat_AsDouble(arg_value); + + if (value_f == -1.0f && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected " + "a dict with float values, not %.200s", + opname, slot_name, Py_TYPE(arg_value)->tp_name); + return -1; + } + + BMO_slot_map_float_insert(bmop, slot, + ((BPy_BMElem *)arg_key)->ele, value_f); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_INT: + { + if (PyDict_Size(value) > 0) { + PyObject *arg_key, *arg_value; + Py_ssize_t arg_pos = 0; + while (PyDict_Next(value, &arg_pos, &arg_key, &arg_value)) { + int value_i; + + if (bpy_slot_from_py_elem_check((BPy_BMElem *)arg_key, bm, BM_ALL_NOLOOP, + opname, slot_name, "invalid key in dict") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + value_i = PyLong_AsLong(arg_value); + + if (value_i == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected " + "a dict with int values, not %.200s", + opname, slot_name, Py_TYPE(arg_value)->tp_name); + return -1; + } + + BMO_slot_map_int_insert(bmop, slot, + ((BPy_BMElem *)arg_key)->ele, value_i); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_BOOL: + { + if (PyDict_Size(value) > 0) { + PyObject *arg_key, *arg_value; + Py_ssize_t arg_pos = 0; + while (PyDict_Next(value, &arg_pos, &arg_key, &arg_value)) { + int value_i; + + if (bpy_slot_from_py_elem_check((BPy_BMElem *)arg_key, bm, BM_ALL_NOLOOP, + opname, slot_name, "invalid key in dict") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + value_i = PyLong_AsLong(arg_value); + + if (value_i == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" expected " + "a dict with bool values, not %.200s", + opname, slot_name, Py_TYPE(arg_value)->tp_name); + return -1; + } + + BMO_slot_map_bool_insert(bmop, slot, + ((BPy_BMElem *)arg_key)->ele, value_i != 0); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_EMPTY: + { + if (PySet_Size(value) > 0) { + PyObject *arg_key; + Py_ssize_t arg_pos = 0; + Py_ssize_t arg_hash = 0; + while (_PySet_NextEntry(value, &arg_pos, &arg_key, &arg_hash)) { + + if (bpy_slot_from_py_elem_check((BPy_BMElem *)arg_key, bm, BM_ALL_NOLOOP, + opname, slot_name, "invalid key in set") == -1) + { + return -1; /* error is set in bpy_slot_from_py_elem_check() */ + } + + BMO_slot_map_empty_insert(bmop, slot, + ((BPy_BMElem *)arg_key)->ele); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL: + { + /* can't convert from these */ + PyErr_Format(PyExc_NotImplementedError, + "This arguments mapping subtype %d is not supported", slot->slot_subtype); + return -1; + } + } + } + default: + /* TODO --- many others */ + PyErr_Format(PyExc_NotImplementedError, + "%.200s: keyword \"%.200s\" type %d not working yet!", + opname, slot_name, slot->slot_type); + return -1; + } + + /* all is well */ + return 0; +} + +/** + * Use for getting return values from an operator thats already executed. + * + * \note Don't throw any exceptions and should always return a valid (PyObject *). + */ +static PyObject* bpy_slot_to_py(BMesh *bm, BMOpSlot *slot) +{ + PyObject *item = NULL; + + /* keep switch in same order as above */ + switch (slot->slot_type) { + case BMO_OP_SLOT_BOOL: + item = PyBool_FromLong((BMO_SLOT_AS_BOOL(slot))); + break; + case BMO_OP_SLOT_INT: + item = PyLong_FromLong(BMO_SLOT_AS_INT(slot)); + break; + case BMO_OP_SLOT_FLT: + item = PyFloat_FromDouble((double)BMO_SLOT_AS_FLOAT(slot)); + break; + case BMO_OP_SLOT_MAT: + item = Matrix_CreatePyObject((float *)BMO_SLOT_AS_MATRIX(slot), 4, 4, Py_NEW, NULL); + break; + case BMO_OP_SLOT_VEC: + item = Vector_CreatePyObject(BMO_SLOT_AS_VECTOR(slot), slot->len, Py_NEW, NULL); + break; + case BMO_OP_SLOT_PTR: + BLI_assert(0); /* currently we don't have any pointer return values in use */ + item = (Py_INCREF(Py_None), Py_None); + break; + case BMO_OP_SLOT_ELEMENT_BUF: + { + if (slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) { + BMHeader *ele = BMO_slot_buffer_get_single(slot); + item = ele ? BPy_BMElem_CreatePyObject(bm, ele) : (Py_INCREF(Py_None), Py_None); + } + else { + const int size = slot->len; + void **buffer = BMO_SLOT_AS_BUFFER(slot); + int j; + + item = PyList_New(size); + for (j = 0; j < size; j++) { + BMHeader *ele = buffer[j]; + PyList_SET_ITEM(item, j, BPy_BMElem_CreatePyObject(bm, ele)); + } + } + break; + } + case BMO_OP_SLOT_MAPPING: + { + GHash *slot_hash = BMO_SLOT_AS_GHASH(slot); + GHashIterator hash_iter; + + switch (slot->slot_subtype.map) { + case BMO_OP_SLOT_SUBTYPE_MAP_ELEM: + { + item = PyDict_New(); + if (slot_hash) { + GHASH_ITER (hash_iter, slot_hash) { + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); + BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter); + + PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); + PyObject *py_val = BPy_BMElem_CreatePyObject(bm, *(void **)BMO_OP_SLOT_MAPPING_DATA(ele_val)); + + PyDict_SetItem(item, py_key, py_val); + Py_DECREF(py_key); + Py_DECREF(py_val); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_FLT: + { + item = PyDict_New(); + if (slot_hash) { + GHASH_ITER (hash_iter, slot_hash) { + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); + BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter); + + PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); + PyObject *py_val = PyFloat_FromDouble(*(float *)BMO_OP_SLOT_MAPPING_DATA(ele_val)); + + PyDict_SetItem(item, py_key, py_val); + Py_DECREF(py_key); + Py_DECREF(py_val); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_INT: + { + item = PyDict_New(); + if (slot_hash) { + GHASH_ITER (hash_iter, slot_hash) { + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); + BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter); + + PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); + PyObject *py_val = PyLong_FromLong(*(int *)BMO_OP_SLOT_MAPPING_DATA(ele_val)); + + PyDict_SetItem(item, py_key, py_val); + Py_DECREF(py_key); + Py_DECREF(py_val); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_BOOL: + { + item = PyDict_New(); + if (slot_hash) { + GHASH_ITER (hash_iter, slot_hash) { + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); + BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter); + + PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); + PyObject *py_val = PyBool_FromLong(*(int *)BMO_OP_SLOT_MAPPING_DATA(ele_val)); + + PyDict_SetItem(item, py_key, py_val); + Py_DECREF(py_key); + Py_DECREF(py_val); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_EMPTY: + { + item = PySet_New(NULL); + if (slot_hash) { + GHASH_ITER (hash_iter, slot_hash) { + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); + + PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); + + PySet_Add(item, py_key); + + Py_DECREF(py_key); + } + } + break; + } + case BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL: + /* can't convert from these */ + item = (Py_INCREF(Py_None), Py_None); + break; + } + break; + } + } + BLI_assert(item != NULL); + + return item; +} + +/** + * This is the __call__ for bmesh.ops.xxx() + */ +PyObject *BPy_BMO_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw) +{ + PyObject *ret; + BPy_BMesh *py_bm; + BMesh *bm; + + BMOperator bmop; + + if ((PyTuple_GET_SIZE(args) == 1) && + (py_bm = (BPy_BMesh *)PyTuple_GET_ITEM(args, 0)) && + (BPy_BMesh_Check(py_bm)) + ) + { + BPY_BM_CHECK_OBJ(py_bm); + bm = py_bm->bm; + } + else { + PyErr_SetString(PyExc_TypeError, + "calling a bmesh operator expects a single BMesh (non keyword) " + "as the first argument"); + return NULL; + } + + /* TODO - error check this!, though we do the error check on attribute access */ + /* TODO - make flags optional */ + BMO_op_init(bm, &bmop, BMO_FLAG_DEFAULTS, self->opname); + + if (kw && PyDict_Size(kw) > 0) { + /* setup properties, see bpy_rna.c: pyrna_py_to_prop() + * which shares this logic for parsing properties */ + + PyObject *key, *value; + Py_ssize_t pos = 0; + while (PyDict_Next(kw, &pos, &key, &value)) { + const char *slot_name = _PyUnicode_AsString(key); + BMOpSlot *slot; + + if (!BMO_slot_exists(bmop.slots_in, slot_name)) { + PyErr_Format(PyExc_TypeError, + "%.200s: keyword \"%.200s\" is invalid for this operator", + self->opname, slot_name); + BMO_op_finish(bm, &bmop); + return NULL; + } + + slot = BMO_slot_get(bmop.slots_in, slot_name); + + /* now assign the value */ + if (bpy_slot_from_py(bm, &bmop, slot, value, + self->opname, slot_name) == -1) + { + BMO_op_finish(bm, &bmop); + return NULL; + } + } + } + + BMO_op_exec(bm, &bmop); + + /* from here until the end of the function, no returns, just set 'ret' */ + if (UNLIKELY(bpy_bm_op_as_py_error(bm) == -1)) { + ret = NULL; /* exception raised above */ + } + else if (bmop.slots_out[0].slot_name == NULL) { + ret = (Py_INCREF(Py_None), Py_None); + } + else { + /* build return value */ + int i; + ret = PyDict_New(); + + for (i = 0; bmop.slots_out[i].slot_name; i++) { + // BMOpDefine *op_def = opdefines[bmop.type]; + // BMOSlotType *slot_type = op_def->slot_types_out[i]; + BMOpSlot *slot = &bmop.slots_out[i]; + PyObject *item; + + /* this function doesn't throw exceptions */ + item = bpy_slot_to_py(bm, slot); + if (item == NULL) { + item = (Py_INCREF(Py_None), Py_None); + } + +#if 1 + /* temp code, strip off '.out' while we keep this convention */ + { + char slot_name_strip[MAX_SLOTNAME]; + char *ch = strchr(slot->slot_name, '.'); /* can't fail! */ + int tot = ch - slot->slot_name; + BLI_assert(ch != NULL); + memcpy(slot_name_strip, slot->slot_name, tot); + slot_name_strip[tot] = '\0'; + PyDict_SetItemString(ret, slot_name_strip, item); + } +#else + PyDict_SetItemString(ret, slot->slot_name, item); +#endif + Py_DECREF(item); + } + } + + BMO_op_finish(bm, &bmop); + return ret; +} diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.h b/source/blender/python/bmesh/bmesh_py_ops_call.h new file mode 100644 index 00000000000..d350aec8f7f --- /dev/null +++ b/source/blender/python/bmesh/bmesh_py_ops_call.h @@ -0,0 +1,41 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/bmesh/bmesh_py_ops_call.h + * \ingroup pybmesh + */ + +#ifndef __BMESH_PY_OPS_CALL_H__ +#define __BMESH_PY_OPS_CALL_H__ + +typedef struct { + PyObject_HEAD /* required python macro */ + const char *opname; +} BPy_BMeshOpFunc; + + +PyObject *BPy_BMO_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw); + +#endif /* __BMESH_PY_OPS_CALL_H__ */ diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 2cae10101d1..5db9962e690 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -541,12 +541,30 @@ static PyObject *bpy_bmloop_link_loop_prev_get(BPy_BMLoop *self) return BPy_BMLoop_CreatePyObject(self->bm, self->l->prev); } +PyDoc_STRVAR(bpy_bmloop_link_loop_radial_next_doc, +"The next loop around the edge (read-only).\n\n:type: :class:`BMLoop`" +); +static PyObject *bpy_bmloop_link_loop_radial_next_get(BPy_BMLoop *self) +{ + BPY_BM_CHECK_OBJ(self); + return BPy_BMLoop_CreatePyObject(self->bm, self->l->radial_next); +} + +PyDoc_STRVAR(bpy_bmloop_link_loop_radial_prev_doc, +"The previous loop around the edge (read-only).\n\n:type: :class:`BMLoop`" +); +static PyObject *bpy_bmloop_link_loop_radial_prev_get(BPy_BMLoop *self) +{ + BPY_BM_CHECK_OBJ(self); + return BPy_BMLoop_CreatePyObject(self->bm, self->l->radial_prev); +} + /* ElemSeq * ^^^^^^^ */ /* note: use for bmvert/edge/face/loop seq's use these, not bmelemseq directly */ PyDoc_STRVAR(bpy_bmelemseq_layers_doc, -"blah blah (read-only).\n\n:type: :class:`BMLayerAccess`" +"custom-data layers (read-only).\n\n:type: :class:`BMLayerAccess`" ); static PyObject *bpy_bmelemseq_layers_get(BPy_BMElemSeq *self, void *htype) { @@ -555,6 +573,46 @@ static PyObject *bpy_bmelemseq_layers_get(BPy_BMElemSeq *self, void *htype) return BPy_BMLayerAccess_CreatePyObject(self->bm, GET_INT_FROM_POINTER(htype)); } +/* FaceSeq + * ^^^^^^^ */ + +PyDoc_STRVAR(bpy_bmfaceseq_active_doc, +"active face.\n\n:type: :class:`BMFace` or None" +); +static PyObject *bpy_bmfaceseq_active_get(BPy_BMElemSeq *self, void *UNUSED(closure)) +{ + BMesh *bm = self->bm; + BPY_BM_CHECK_OBJ(self); + + if (bm->act_face) { + return BPy_BMElem_CreatePyObject(bm, (BMHeader *)bm->act_face); + } + else { + Py_RETURN_NONE; + } +} + +static int bpy_bmfaceseq_active_set(BPy_BMElem *self, PyObject *value, void *UNUSED(closure)) +{ + BMesh *bm = self->bm; + if (value == Py_None) { + bm->act_face = NULL; + return 0; + } + else if (BPy_BMFace_Check(value)) { + BPY_BM_CHECK_SOURCE_INT(value, bm, "faces.active = f"); + + bm->act_face = ((BPy_BMFace *)value)->f; + return 0; + } + else { + PyErr_Format(PyExc_TypeError, + "faces.active = f: expected BMFace or None, not %.200s", + Py_TYPE(value)->tp_name); + return -1; + } +} + static PyGetSetDef bpy_bmesh_getseters[] = { {(char *)"verts", (getter)bpy_bmvertseq_get, (setter)NULL, (char *)bpy_bmvertseq_doc, NULL}, {(char *)"edges", (getter)bpy_bmedgeseq_get, (setter)NULL, (char *)bpy_bmedgeseq_doc, NULL}, @@ -659,6 +717,8 @@ static PyGetSetDef bpy_bmloop_getseters[] = { {(char *)"link_loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmloops_link_loops_doc, (void *)BM_LOOPS_OF_LOOP}, {(char *)"link_loop_next", (getter)bpy_bmloop_link_loop_next_get, (setter)NULL, (char *)bpy_bmloop_link_loop_next_doc, NULL}, {(char *)"link_loop_prev", (getter)bpy_bmloop_link_loop_prev_get, (setter)NULL, (char *)bpy_bmloop_link_loop_prev_doc, NULL}, + {(char *)"link_loop_radial_next", (getter)bpy_bmloop_link_loop_radial_next_get, (setter)NULL, (char *)bpy_bmloop_link_loop_radial_next_doc, NULL}, + {(char *)"link_loop_radial_prev", (getter)bpy_bmloop_link_loop_radial_prev_get, (setter)NULL, (char *)bpy_bmloop_link_loop_radial_prev_doc, NULL}, /* readonly checks */ {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL}, @@ -668,7 +728,7 @@ static PyGetSetDef bpy_bmloop_getseters[] = { static PyGetSetDef bpy_bmvertseq_getseters[] = { {(char *)"layers", (getter)bpy_bmelemseq_layers_get, (setter)NULL, (char *)bpy_bmelemseq_layers_doc, (void *)BM_VERT}, - {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; static PyGetSetDef bpy_bmedgeseq_getseters[] = { {(char *)"layers", (getter)bpy_bmelemseq_layers_get, (setter)NULL, (char *)bpy_bmelemseq_layers_doc, (void *)BM_EDGE}, @@ -676,6 +736,8 @@ static PyGetSetDef bpy_bmedgeseq_getseters[] = { }; static PyGetSetDef bpy_bmfaceseq_getseters[] = { {(char *)"layers", (getter)bpy_bmelemseq_layers_get, (setter)NULL, (char *)bpy_bmelemseq_layers_doc, (void *)BM_FACE}, + /* face only */ + {(char *)"active", (getter)bpy_bmfaceseq_active_get, (setter)bpy_bmfaceseq_active_set, (char *)bpy_bmfaceseq_active_doc, NULL}, {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; static PyGetSetDef bpy_bmloopseq_getseters[] = { @@ -801,34 +863,92 @@ static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args) Py_RETURN_NONE; } -/* note: rna_Object_to_mesh() also has apply_modifiers arg that works the same way */ PyDoc_STRVAR(bpy_bmesh_from_object_doc, -".. method:: from_object(mesh, apply_modifiers=True)\n" +".. method:: from_object(object, scene, deform=True, render=False, cage=False)\n" "\n" -" Initialize this bmesh from existing object datablock.\n" +" Initialize this bmesh from existing object datablock (currently only meshes are supported).\n" "\n" " :arg object: The object data to load.\n" " :type object: :class:`Object`\n" -" :arg apply_modifiers: Use the final display mesh rather then the deformed cage.\n" -" :type apply_modifiers: boolean\n" +" :arg deform: Apply deformation modifiers.\n" +" :type deform: boolean\n" +" :arg render: Use render settings.\n" +" :type render: boolean\n" +" :arg cage: Get the mesh as a deformed cage.\n" +" :type cage: boolean\n" ); static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args) { PyObject *py_object; + PyObject *py_scene; Object *ob; + struct Scene *scene; BMesh *bm; - int apply_modifiers = TRUE; + int use_deform = TRUE; + int use_render = FALSE; + int use_cage = FALSE; DerivedMesh *dm; + const int mask = CD_MASK_BMESH; BPY_BM_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "O|i:from_object", &py_object, &apply_modifiers) || - !(ob = PyC_RNA_AsPointer(py_object, "Object"))) + if (!PyArg_ParseTuple(args, "OO|iii:from_object", &py_object, &py_scene, &use_render, &use_cage) || + !(ob = PyC_RNA_AsPointer(py_object, "Object")) || + !(scene = PyC_RNA_AsPointer(py_scene, "Scene"))) { return NULL; } - dm = apply_modifiers ? ob->derivedFinal : ob->derivedDeform; + if (ob->type != OB_MESH) { + PyErr_SetString(PyExc_ValueError, + "from_object(...): currently only mesh objects are supported"); + return NULL; + } + + /* Write the display mesh into the dummy mesh */ + if (use_deform) { + if (use_render) { + if (use_cage) { + PyErr_SetString(PyExc_ValueError, + "from_object(...): cage arg is unsupported when (render=True)"); + return NULL; + } + else { + dm = mesh_create_derived_render(scene, ob, mask); + } + } + else { + if (use_cage) { + dm = mesh_get_derived_deform(scene, ob, mask); /* ob->derivedDeform */ + } + else { + dm = mesh_get_derived_final(scene, ob, mask); /* ob->derivedFinal */ + } + } + } + else { + /* !use_deform */ + if (use_render) { + if (use_cage) { + PyErr_SetString(PyExc_ValueError, + "from_object(...): cage arg is unsupported when (render=True)"); + return NULL; + } + else { + dm = mesh_create_derived_no_deform_render(scene, ob, NULL, mask); + } + } + else { + if (use_cage) { + PyErr_SetString(PyExc_ValueError, + "from_object(...): cage arg is unsupported when (deform=False, render=False)"); + return NULL; + } + else { + dm = mesh_create_derived_no_deform(scene, ob, NULL, mask); + } + } + } if (dm == NULL) { PyErr_Format(PyExc_ValueError, @@ -840,6 +960,8 @@ static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args) DM_to_bmesh_ex(dm, bm); + dm->release(dm); + Py_RETURN_NONE; } @@ -1172,13 +1294,7 @@ static PyObject *bpy_bmvert_copy_from_face_interp(BPy_BMVert *self, PyObject *ar else { BMesh *bm = self->bm; - BPY_BM_CHECK_OBJ(py_face); - - if (py_face->bm != bm) { - PyErr_SetString(PyExc_ValueError, - "BMVert.copy_from_face_interp(face): face is from another mesh"); - return NULL; - } + BPY_BM_CHECK_SOURCE_OBJ(py_face, bm, "copy_from_face_interp()"); BM_vert_interp_from_face(bm, self->v, py_face->f); @@ -1312,13 +1428,7 @@ static PyObject *bpy_bmedge_other_vert(BPy_BMEdge *self, BPy_BMVert *value) return NULL; } - BPY_BM_CHECK_OBJ(value); - - if (self->bm != value->bm) { - PyErr_SetString(PyExc_ValueError, - "BMEdge.other_vert(vert): vert is from another mesh"); - return NULL; - } + BPY_BM_CHECK_SOURCE_OBJ(value, self->bm, "BMEdge.other_vert(vert)"); other = BM_edge_other_vert(self->e, value->v); @@ -1372,13 +1482,7 @@ static PyObject *bpy_bmface_copy_from_face_interp(BPy_BMFace *self, PyObject *ar else { BMesh *bm = self->bm; - BPY_BM_CHECK_OBJ(py_face); - - if (py_face->bm != bm) { - PyErr_SetString(PyExc_ValueError, - "BMFace.copy_from_face_interp(face): face is from another mesh"); - return NULL; - } + BPY_BM_CHECK_SOURCE_OBJ(py_face, bm, "BMFace.copy_from_face_interp(face)"); BM_face_interp_from_face(bm, self->f, py_face->f); @@ -1544,13 +1648,7 @@ static PyObject *bpy_bmloop_copy_from_face_interp(BPy_BMLoop *self, PyObject *ar else { BMesh *bm = self->bm; - BPY_BM_CHECK_OBJ(py_face); - - if (py_face->bm != bm) { - PyErr_SetString(PyExc_ValueError, - "BMLoop.copy_from_face_interp(face): face is from another mesh"); - return NULL; - } + BPY_BM_CHECK_SOURCE_OBJ(py_face, bm, "BMLoop.copy_from_face_interp(face)"); BM_loop_interp_from_face(bm, self->l, py_face->f, do_vertex, do_multires); @@ -1648,7 +1746,7 @@ static PyObject *bpy_bmvertseq_new(BPy_BMElemSeq *self, PyObject *args) return NULL; } - v = BM_vert_create(bm, co, NULL); + v = BM_vert_create(bm, co, NULL, 0); if (v == NULL) { PyErr_SetString(PyExc_ValueError, @@ -1717,7 +1815,7 @@ static PyObject *bpy_bmedgeseq_new(BPy_BMElemSeq *self, PyObject *args) goto cleanup; } - e = BM_edge_create(bm, vert_array[0], vert_array[1], NULL, FALSE); + e = BM_edge_create(bm, vert_array[0], vert_array[1], NULL, 0); if (e == NULL) { PyErr_SetString(PyExc_ValueError, @@ -1790,7 +1888,7 @@ static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args) } /* check if the face exists */ - if (BM_face_exists(bm, vert_array, vert_seq_len, NULL)) { + if (BM_face_exists(vert_array, vert_seq_len, NULL)) { PyErr_SetString(PyExc_ValueError, "faces.new(verts): face already exists"); goto cleanup; @@ -1803,10 +1901,10 @@ static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args) /* ensure edges */ for (i = vert_seq_len - 1, i_next = 0; i_next < vert_seq_len; (i = i_next++)) { - edge_array[i] = BM_edge_create(bm, vert_array[i], vert_array[i_next], NULL, TRUE); + edge_array[i] = BM_edge_create(bm, vert_array[i], vert_array[i_next], NULL, BM_CREATE_NO_DOUBLE); } - f_new = BM_face_create(bm, vert_array, edge_array, vert_seq_len, FALSE); + f_new = BM_face_create(bm, vert_array, edge_array, vert_seq_len, 0); if (UNLIKELY(f_new == NULL)) { PyErr_SetString(PyExc_ValueError, @@ -1846,13 +1944,7 @@ static PyObject *bpy_bmvertseq_remove(BPy_BMElemSeq *self, BPy_BMVert *value) else { BMesh *bm = self->bm; - BPY_BM_CHECK_OBJ(value); - - if (value->bm != bm) { - PyErr_SetString(PyExc_ValueError, - "verts.remove(vert): vert is from another mesh"); - return NULL; - } + BPY_BM_CHECK_SOURCE_OBJ(value, bm, "verts.remove(vert)"); BM_vert_kill(bm, value->v); bpy_bm_generic_invalidate((BPy_BMGeneric *)value); @@ -1876,13 +1968,7 @@ static PyObject *bpy_bmedgeseq_remove(BPy_BMElemSeq *self, BPy_BMEdge *value) else { BMesh *bm = self->bm; - BPY_BM_CHECK_OBJ(value); - - if (value->bm != bm) { - PyErr_SetString(PyExc_ValueError, - "edges.remove(edge): edge is from another mesh"); - return NULL; - } + BPY_BM_CHECK_SOURCE_OBJ(value, bm, "edges.remove(edges)"); BM_edge_kill(bm, value->e); bpy_bm_generic_invalidate((BPy_BMGeneric *)value); @@ -1906,13 +1992,7 @@ static PyObject *bpy_bmfaceseq_remove(BPy_BMElemSeq *self, BPy_BMFace *value) else { BMesh *bm = self->bm; - BPY_BM_CHECK_OBJ(value); - - if (value->bm != bm) { - PyErr_SetString(PyExc_ValueError, - "faces.remove(face): face is from another mesh"); - return NULL; - } + BPY_BM_CHECK_SOURCE_OBJ(value, bm, "faces.remove(face)"); BM_face_kill(bm, value->f); bpy_bm_generic_invalidate((BPy_BMGeneric *)value); @@ -2012,7 +2092,7 @@ static PyObject *bpy_bmfaceseq_get__method(BPy_BMElemSeq *self, PyObject *args) return NULL; } - if (BM_face_exists(bm, vert_array, vert_seq_len, &f)) { + if (BM_face_exists(vert_array, vert_seq_len, &f)) { ret = BPy_BMFace_CreatePyObject(bm, f); } else { @@ -2972,7 +3052,8 @@ void BPy_BM_init_types(void) BPy_BMLoopSeq_Type.tp_methods = bpy_bmloopseq_methods; BPy_BMIter_Type.tp_methods = NULL; - + /*BPy_BMElem_Check() uses bpy_bm_elem_hash() to check types. + * if this changes update the macro */ BPy_BMesh_Type.tp_hash = bpy_bm_hash; BPy_BMVert_Type.tp_hash = bpy_bm_elem_hash; BPy_BMEdge_Type.tp_hash = bpy_bm_elem_hash; @@ -3306,6 +3387,7 @@ PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele) case BM_LOOP: return BPy_BMLoop_CreatePyObject(bm, (BMLoop *)ele); default: + BLI_assert(0); PyErr_SetString(PyExc_SystemError, "internal error"); return NULL; } @@ -3339,6 +3421,21 @@ int bpy_bm_generic_valid_check(BPy_BMGeneric *self) } } +int bpy_bm_generic_valid_check_source(BPy_BMGeneric *self, BMesh *bm_source, const char *error_prefix) +{ + int ret = bpy_bm_generic_valid_check(self); + if (LIKELY(ret == 0)) { + if (UNLIKELY(self->bm != bm_source)) { + /* could give more info here */ + PyErr_Format(PyExc_ValueError, + "%.200s: BMesh data of type %.200s is from another mesh", + error_prefix, Py_TYPE(self)->tp_name); + ret = -1; + } + } + return ret; +} + void bpy_bm_generic_invalidate(BPy_BMGeneric *self) { self->bm = NULL; diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h index df5231a4b1b..d15918a3c11 100644 --- a/source/blender/python/bmesh/bmesh_py_types.h +++ b/source/blender/python/bmesh/bmesh_py_types.h @@ -55,6 +55,8 @@ extern PyTypeObject BPy_BMIter_Type; #define BPy_BMFaceSeq_Check(v) (Py_TYPE(v) == &BPy_BMFaceSeq_Type) #define BPy_BMLoopSeq_Check(v) (Py_TYPE(v) == &BPy_BMLoopSeq_Type) #define BPy_BMIter_Check(v) (Py_TYPE(v) == &BPy_BMIter_Type) +/* trick since we know they share a hash function */ +#define BPy_BMElem_Check(v) (Py_TYPE(v)->tp_hash == BPy_BMVert_Type.tp_hash) /* cast from _any_ bmesh type - they all have BMesh first */ typedef struct BPy_BMGeneric { @@ -156,9 +158,6 @@ PyObject *BPy_BMIter_CreatePyObject(BMesh *bm); PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele); /* just checks type and creates v/e/f/l */ -int bpy_bm_generic_valid_check(BPy_BMGeneric *self); -void bpy_bm_generic_invalidate(BPy_BMGeneric *self); - void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, const char htype, const char do_unique_check, const char do_bm_check, @@ -169,9 +168,20 @@ int BPy_BMElem_CheckHType(PyTypeObject *type, const char htype); char *BPy_BMElem_StringFromHType_ex(const char htype, char ret[32]); char *BPy_BMElem_StringFromHType(const char htype); +void bpy_bm_generic_invalidate(BPy_BMGeneric *self); +int bpy_bm_generic_valid_check(BPy_BMGeneric *self); +int bpy_bm_generic_valid_check_source(BPy_BMGeneric *self, BMesh *bm_source, const char *error_prefix); -#define BPY_BM_CHECK_OBJ(obj) if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { return NULL; } (void)0 -#define BPY_BM_CHECK_INT(obj) if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { return -1; } (void)0 +#define BPY_BM_CHECK_OBJ(obj) \ + if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { return NULL; } (void)0 +#define BPY_BM_CHECK_INT(obj) \ + if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { return -1; } (void)0 + +/* macros like BPY_BM_CHECK_OBJ/BPY_BM_CHECK_INT that ensure we're from the right BMesh */ +#define BPY_BM_CHECK_SOURCE_OBJ(obj, bm, errmsg) \ + if (UNLIKELY(bpy_bm_generic_valid_check_source((BPy_BMGeneric *)obj, bm, errmsg) == -1)) { return NULL; } (void)0 +#define BPY_BM_CHECK_SOURCE_INT(obj, bm, errmsg) \ + if (UNLIKELY(bpy_bm_generic_valid_check_source((BPy_BMGeneric *)obj, bm, errmsg) == -1)) { return -1; } (void)0 #define BPY_BM_IS_VALID(obj) (LIKELY((obj)->bm != NULL)) diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c index 1fea12d105c..fd31f3c40cc 100644 --- a/source/blender/python/bmesh/bmesh_py_types_customdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c @@ -262,16 +262,10 @@ static PyObject *bpy_bmlayeritem_copy_from(BPy_BMLayerItem *self, BPy_BMLayerIte } BPY_BM_CHECK_OBJ(self); - BPY_BM_CHECK_OBJ(value); + BPY_BM_CHECK_SOURCE_OBJ(value, self->bm, "layer.copy_from()"); - if (self->bm != value->bm) { - PyErr_SetString(PyExc_ValueError, - "layer.copy_from(): layer is from another mesh"); - return NULL; - } - - else if ((self->htype != value->htype) || - (self->type != value->type)) + if ((self->htype != value->htype) || + (self->type != value->type)) { PyErr_SetString(PyExc_ValueError, "layer.copy_from(other): layer type mismatch"); @@ -981,7 +975,7 @@ PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer) } case CD_PROP_INT: { - ret = PyLong_FromSsize_t((Py_ssize_t)(*(int *)value)); + ret = PyLong_FromLong(*(int *)value); break; } case CD_PROP_STR: @@ -1060,7 +1054,7 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj } case CD_PROP_INT: { - int tmp_val = PyLong_AsSsize_t(py_value); + int tmp_val = PyLong_AsLong(py_value); if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) { PyErr_Format(PyExc_TypeError, "expected an int, not a %.200s", Py_TYPE(py_value)->tp_name); ret = -1; diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c index 8316d33ea38..b0870578f5a 100644 --- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c @@ -527,7 +527,7 @@ static PyObject *bpy_bmdeformvert_keys(BPy_BMDeformVert *self) ret = PyList_New(self->data->totweight); for (i = 0; i < self->data->totweight; i++, dw++) { - PyList_SET_ITEM(ret, i, PyLong_FromSsize_t(dw->def_nr)); + PyList_SET_ITEM(ret, i, PyLong_FromLong(dw->def_nr)); } return ret; @@ -576,7 +576,7 @@ static PyObject *bpy_bmdeformvert_items(BPy_BMDeformVert *self) for (i = 0; i < self->data->totweight; i++, dw++) { item = PyTuple_New(2); - PyTuple_SET_ITEM(item, 0, PyLong_FromSsize_t(dw->def_nr)); + PyTuple_SET_ITEM(item, 0, PyLong_FromLong(dw->def_nr)); PyTuple_SET_ITEM(item, 1, PyFloat_FromDouble(dw->weight)); PyList_SET_ITEM(ret, i, item); diff --git a/source/blender/python/bmesh/bmesh_py_types_select.c b/source/blender/python/bmesh/bmesh_py_types_select.c index 2ff731559d1..dfcfbeb0ab5 100644 --- a/source/blender/python/bmesh/bmesh_py_types_select.c +++ b/source/blender/python/bmesh/bmesh_py_types_select.c @@ -114,13 +114,7 @@ static PyObject *bpy_bmeditselseq_add(BPy_BMEditSelSeq *self, BPy_BMElem *value) return NULL; } - BPY_BM_CHECK_OBJ(value); - - if (self->bm != value->bm) { - PyErr_SetString(PyExc_ValueError, - "Element is not from this mesh"); - return NULL; - } + BPY_BM_CHECK_SOURCE_OBJ(value, self->bm, "select_history.add()"); BM_select_history_store(self->bm, value->ele); @@ -145,11 +139,9 @@ static PyObject *bpy_bmeditselseq_remove(BPy_BMEditSelSeq *self, BPy_BMElem *val return NULL; } - BPY_BM_CHECK_OBJ(value); + BPY_BM_CHECK_SOURCE_OBJ(value, self->bm, "select_history.remove()"); - if ((self->bm != value->bm) || - (BM_select_history_remove(self->bm, value->ele) == FALSE)) - { + if (BM_select_history_remove(self->bm, value->ele) == FALSE) { PyErr_SetString(PyExc_ValueError, "Element not found in selection history"); return NULL; diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c index b70df53aff0..f85c3347104 100644 --- a/source/blender/python/bmesh/bmesh_py_utils.c +++ b/source/blender/python/bmesh/bmesh_py_utils.c @@ -557,16 +557,10 @@ static PyObject *bpy_bm_utils_face_vert_separate(PyObject *UNUSED(self), PyObjec return NULL; } - BPY_BM_CHECK_OBJ(py_face); - BPY_BM_CHECK_OBJ(py_vert); - bm = py_face->bm; - if (bm != py_vert->bm) { - PyErr_SetString(PyExc_ValueError, - "mesh elements are from different meshes"); - return NULL; - } + BPY_BM_CHECK_OBJ(py_face); + BPY_BM_CHECK_SOURCE_OBJ(py_vert, bm, "face_vert_separate()"); l = BM_face_vert_share_loop(py_face->f, py_vert->v); diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c index a10bfef2a8d..22b9c1a2208 100644 --- a/source/blender/python/generic/bgl.c +++ b/source/blender/python/generic/bgl.c @@ -613,15 +613,15 @@ static PyObject *Buffer_repr(Buffer *self) } -BGL_Wrap(2, Accum, void, (GLenum, GLfloat)) -BGL_Wrap(1, ActiveTexture, void, (GLenum)) -BGL_Wrap(2, AlphaFunc, void, (GLenum, GLclampf)) +BGL_Wrap(2, Accum, void, (GLenum, GLfloat)) +BGL_Wrap(1, ActiveTexture, void, (GLenum)) +BGL_Wrap(2, AlphaFunc, void, (GLenum, GLclampf)) BGL_Wrap(3, AreTexturesResident, GLboolean, (GLsizei, GLuintP, GLbooleanP)) BGL_Wrap(2, AttachShader, void, (GLuint, GLuint)) -BGL_Wrap(1, Begin, void, (GLenum)) -BGL_Wrap(2, BindTexture, void, (GLenum, GLuint)) -BGL_Wrap(7, Bitmap, void, (GLsizei, GLsizei, GLfloat, - GLfloat, GLfloat, GLfloat, GLubyteP)) +BGL_Wrap(1, Begin, void, (GLenum)) +BGL_Wrap(2, BindTexture, void, (GLenum, GLuint)) +BGL_Wrap(7, Bitmap, void, (GLsizei, GLsizei, GLfloat, + GLfloat, GLfloat, GLfloat, GLubyteP)) BGL_Wrap(2, BlendFunc, void, (GLenum, GLenum)) BGL_Wrap(1, CallList, void, (GLuint)) BGL_Wrap(3, CallLists, void, (GLsizei, GLenum, GLvoidP)) @@ -675,7 +675,7 @@ BGL_Wrap(1, CullFace, void, (GLenum)) BGL_Wrap(2, DeleteLists, void, (GLuint, GLsizei)) BGL_Wrap(1, DeleteProgram, void, (GLuint)) BGL_Wrap(1, DeleteShader, void, (GLuint)) -BGL_Wrap(2, DeleteTextures, void, (GLsizei, GLuintP)) +BGL_Wrap(2, DeleteTextures, void, (GLsizei, GLuintP)) BGL_Wrap(1, DepthFunc, void, (GLenum)) BGL_Wrap(1, DepthMask, void, (GLboolean)) BGL_Wrap(2, DepthRange, void, (GLclampd, GLclampd)) @@ -773,7 +773,7 @@ BGL_Wrap(3, Lighti, void, (GLenum, GLenum, GLint)) BGL_Wrap(3, Lightiv, void, (GLenum, GLenum, GLintP)) BGL_Wrap(2, LineStipple, void, (GLint, GLushort)) BGL_Wrap(1, LineWidth, void, (GLfloat)) -BGL_Wrap(1, LinkProgram, void, (GLuint)) +BGL_Wrap(1, LinkProgram, void, (GLuint)) BGL_Wrap(1, ListBase, void, (GLuint)) BGL_Wrap(1, LoadIdentity, void, (void)) BGL_Wrap(1, LoadMatrixd, void, (GLdoubleP)) @@ -1907,9 +1907,9 @@ PyObject *BPyInit_bgl(void) return submodule; } -static PyObject *Method_ShaderSource (PyObject *UNUSED(self), PyObject *args) +static PyObject *Method_ShaderSource(PyObject *UNUSED(self), PyObject *args) { - int shader; + unsigned int shader; char *source; if (!PyArg_ParseTuple(args, "Is", &shader, &source)) diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c index b9ef4b056ad..8d146bedb48 100644 --- a/source/blender/python/generic/bpy_internal_import.c +++ b/source/blender/python/generic/bpy_internal_import.c @@ -1,4 +1,4 @@ -/* +/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -56,8 +56,22 @@ static ListBase bpy_import_main_list; static PyMethodDef bpy_import_meth; static PyMethodDef bpy_reload_meth; +static PyObject *imp_reload_orig = NULL; /* 'builtins' is most likely PyEval_GetBuiltins() */ + +/** + * \note to the discerning developer, yes - this is nasty + * monkey-patching our own import into Python's builtin 'imp' module. + * + * However Python's alternative is to use import hooks, + * which are implemented in a way that we can't use our own importer as a + * fall-back (instead we must try and fail - raise an exception evert time). + * Since importing from blenders text-blocks is not the common case + * I prefer to use Pythons import by default and fall-back to + * Blenders - which we can only do by intercepting import calls I'm afraid. + * - Campbell + */ void bpy_import_init(PyObject *builtins) { PyObject *item; @@ -69,7 +83,13 @@ void bpy_import_init(PyObject *builtins) * XXX, use import hooks */ mod = PyImport_ImportModuleLevel((char *)"imp", NULL, NULL, NULL, 0); if (mod) { - PyDict_SetItemString(PyModule_GetDict(mod), "reload", item = PyCFunction_New(&bpy_reload_meth, NULL)); Py_DECREF(item); + PyObject *mod_dict = PyModule_GetDict(mod); + + /* blender owns the function */ + imp_reload_orig = PyDict_GetItemString(mod_dict, "reload"); + Py_INCREF(imp_reload_orig); + + PyDict_SetItemString(mod_dict, "reload", item = PyCFunction_New(&bpy_reload_meth, NULL)); Py_DECREF(item); Py_DECREF(mod); } else { @@ -309,7 +329,12 @@ static PyObject *blender_reload(PyObject *UNUSED(self), PyObject *module) int found = 0; /* try reimporting from file */ - newmodule = PyImport_ReloadModule(module); + + /* in Py3.3 this just calls imp.reload() which we overwrite, causing recursive calls */ + //newmodule = PyImport_ReloadModule(module); + + newmodule = PyObject_CallFunctionObjArgs(imp_reload_orig, module, NULL); + if (newmodule) return newmodule; diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index 529b2e708ad..53112d46098 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -249,7 +249,7 @@ static int BPy_IDGroup_SetName(BPy_IDProperty *self, PyObject *value, void *UNUS #if 0 static PyObject *BPy_IDGroup_GetType(BPy_IDProperty *self) { - return PyLong_FromSsize_t(self->prop->type); + return PyLong_FromLong(self->prop->type); } #endif @@ -351,7 +351,7 @@ const char *BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty prop = IDP_New(IDP_DOUBLE, &val, name); } else if (PyLong_Check(ob)) { - val.i = (int) PyLong_AsSsize_t(ob); + val.i = (int)PyLong_AsLong(ob); prop = IDP_New(IDP_INT, &val, name); } else if (PyUnicode_Check(ob)) { @@ -409,7 +409,7 @@ const char *BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty prop = IDP_New(IDP_ARRAY, &val, name); for (i = 0; i < val.array.len; i++) { item = PySequence_Fast_GET_ITEM(ob_seq_fast, i); - ((int *)IDP_Array(prop))[i] = (int)PyLong_AsSsize_t(item); + ((int *)IDP_Array(prop))[i] = (int)PyLong_AsLong(item); } break; case IDP_IDPARRAY: @@ -1072,7 +1072,7 @@ static int BPy_IDArray_SetItem(BPy_IDArray *self, int index, PyObject *value) ((double *)IDP_Array(self->prop))[index] = d; break; case IDP_INT: - i = PyLong_AsSsize_t(value); + i = PyLong_AsLong(value); if (i == -1 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "expected an int type"); return -1; diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 3b8193c422d..f62fdaf09db 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -83,13 +83,13 @@ int PyC_AsArray(void *array, PyObject *value, const Py_ssize_t length, /* could use is_double for 'long int' but no use now */ int *array_int = array; for (i = 0; i < length; i++) { - array_int[i] = PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i)); + array_int[i] = PyLong_AsLong(PySequence_Fast_GET_ITEM(value_fast, i)); } } else if (type == &PyBool_Type) { int *array_bool = array; for (i = 0; i < length; i++) { - array_bool[i] = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i)) != 0); + array_bool[i] = (PyLong_AsLong(PySequence_Fast_GET_ITEM(value_fast, i)) != 0); } } else { @@ -504,7 +504,7 @@ void PyC_SetHomePath(const char *py_path_bundle) * but current Python lib (release 3.1.1) doesn't handle these correctly */ if (strchr(py_path_bundle, ':')) printf("Warning : Blender application is located in a path containing : or / chars\ - \nThis may make python import function fail\n"); + \nThis may make python import function fail\n"); #endif @@ -567,7 +567,7 @@ void PyC_RunQuicky(const char *filepath, int n, ...) ret = PyObject_CallFunction(calcsize, (char *)"s", format); if (ret) { - sizes[i] = PyLong_AsSsize_t(ret); + sizes[i] = PyLong_AsLong(ret); Py_DECREF(ret); ret = PyObject_CallFunction(unpack, (char *)"sy#", format, (char *)ptr, sizes[i]); } diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index a8aa7269b72..b1eeff8b3ae 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -195,12 +195,12 @@ PyDoc_STRVAR(bpy_app_debug_value_doc, ); static PyObject *bpy_app_debug_value_get(PyObject *UNUSED(self), void *UNUSED(closure)) { - return PyLong_FromSsize_t(G.debug_value); + return PyLong_FromLong(G.debug_value); } static int bpy_app_debug_value_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure)) { - int param = PyLong_AsSsize_t(value); + int param = PyLong_AsLong(value); if (param == -1 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "bpy.app.debug_value can only be set to a whole number"); diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 94cbee383ea..cdecf64c93c 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -268,6 +268,23 @@ void BPY_python_start(int argc, const char **argv) Py_Initialize(); + /* THIS IS BAD: see http://bugs.python.org/issue16129 */ +#if 1 + /* until python provides a reliable way to set the env var */ + PyRun_SimpleString("import sys, io\n" + "sys.__backup_stdio__ = sys.__stdout__, sys.__stderr__\n" /* else we loose the FD's [#32720] */ + "sys.__stdout__ = sys.stdout = io.TextIOWrapper(io.open(sys.stdout.fileno(), 'wb', -1), " + "encoding='utf-8', errors='surrogateescape', newline='\\n', line_buffering=True)\n" + "sys.__stderr__ = sys.stderr = io.TextIOWrapper(io.open(sys.stderr.fileno(), 'wb', -1), " + "encoding='utf-8', errors='surrogateescape', newline='\\n', line_buffering=True)\n"); + if (PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + } +#endif + /* end the baddness */ + + // PySys_SetArgv(argc, argv); /* broken in py3, not a huge deal */ /* sigh, why do python guys not have a (char **) version anymore? */ { @@ -601,7 +618,7 @@ int BPY_button_exec(bContext *C, const char *expr, double *value, const short ve } } - PyC_MainModule_Backup(&main_mod); + PyC_MainModule_Restore(main_mod); bpy_context_clear(C, &gilstate); diff --git a/source/blender/python/intern/bpy_intern_string.c b/source/blender/python/intern/bpy_intern_string.c index 7c8291d62d3..70ea57bb33f 100644 --- a/source/blender/python/intern/bpy_intern_string.c +++ b/source/blender/python/intern/bpy_intern_string.c @@ -38,6 +38,8 @@ PyObject *bpy_intern_str_bl_rna; PyObject *bpy_intern_str_order; PyObject *bpy_intern_str_attr; PyObject *bpy_intern_str___slots__; +PyObject *bpy_intern_str___name__; +PyObject *bpy_intern_str___doc__; void bpy_intern_string_init(void) { @@ -47,6 +49,8 @@ void bpy_intern_string_init(void) bpy_intern_str_order = PyUnicode_FromString("order"); bpy_intern_str_attr = PyUnicode_FromString("attr"); bpy_intern_str___slots__ = PyUnicode_FromString("__slots__"); + bpy_intern_str___name__ = PyUnicode_FromString("__name__"); + bpy_intern_str___doc__ = PyUnicode_FromString("__doc__"); } void bpy_intern_string_exit(void) @@ -57,4 +61,6 @@ void bpy_intern_string_exit(void) Py_DECREF(bpy_intern_str_order); Py_DECREF(bpy_intern_str_attr); Py_DECREF(bpy_intern_str___slots__); + Py_DECREF(bpy_intern_str___name__); + Py_DECREF(bpy_intern_str___doc__); } diff --git a/source/blender/python/intern/bpy_intern_string.h b/source/blender/python/intern/bpy_intern_string.h index dc7af735743..0b7ca2cd47b 100644 --- a/source/blender/python/intern/bpy_intern_string.h +++ b/source/blender/python/intern/bpy_intern_string.h @@ -33,3 +33,5 @@ extern PyObject *bpy_intern_str_bl_rna; extern PyObject *bpy_intern_str_order; extern PyObject *bpy_intern_str_attr; extern PyObject *bpy_intern_str___slots__; +extern PyObject *bpy_intern_str___name__; +extern PyObject *bpy_intern_str___doc__; diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index eaaced416fe..a0df8988068 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -1344,7 +1344,7 @@ PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) ret = PyBool_FromLong(RNA_property_boolean_get(ptr, prop)); break; case PROP_INT: - ret = PyLong_FromSsize_t((Py_ssize_t)RNA_property_int_get(ptr, prop)); + ret = PyLong_FromLong(RNA_property_int_get(ptr, prop)); break; case PROP_FLOAT: ret = PyFloat_FromDouble(RNA_property_float_get(ptr, prop)); @@ -2371,7 +2371,7 @@ static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, Po RNA_property_int_get_array(ptr, prop, values); for (count = start; count < stop; count++) - PyTuple_SET_ITEM(tuple, count - start, PyLong_FromSsize_t(values[count])); + PyTuple_SET_ITEM(tuple, count - start, PyLong_FromLong(values[count])); if (values != values_stack) { PyMem_FREE(values); @@ -4077,7 +4077,7 @@ static PyObject *pyrna_prop_collection_items(BPy_PropertyRNA *self) } else { /* a bit strange but better then returning an empty list */ - PyTuple_SET_ITEM(item, 0, PyLong_FromSsize_t(i)); + PyTuple_SET_ITEM(item, 0, PyLong_FromLong(i)); } PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&itemptr)); @@ -4256,7 +4256,7 @@ static PyObject *pyrna_prop_collection_find(BPy_PropertyRNA *self, PyObject *key } RNA_PROP_END; - return PyLong_FromSsize_t(index); + return PyLong_FromLong(index); } static void foreach_attr_type(BPy_PropertyRNA *self, const char *attr, @@ -4463,13 +4463,13 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) switch (raw_type) { case PROP_RAW_CHAR: - item = PyLong_FromSsize_t((Py_ssize_t) ((char *)array)[i]); + item = PyLong_FromLong((long) ((char *)array)[i]); break; case PROP_RAW_SHORT: - item = PyLong_FromSsize_t((Py_ssize_t) ((short *)array)[i]); + item = PyLong_FromLong((long) ((short *)array)[i]); break; case PROP_RAW_INT: - item = PyLong_FromSsize_t((Py_ssize_t) ((int *)array)[i]); + item = PyLong_FromLong((long) ((int *)array)[i]); break; case PROP_RAW_FLOAT: item = PyFloat_FromDouble((double) ((float *)array)[i]); @@ -4756,7 +4756,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat case PROP_INT: ret = PyTuple_New(len); for (a = 0; a < len; a++) - PyTuple_SET_ITEM(ret, a, PyLong_FromSsize_t((Py_ssize_t)((int *)data)[a])); + PyTuple_SET_ITEM(ret, a, PyLong_FromLong(((int *)data)[a])); break; case PROP_FLOAT: switch (RNA_property_subtype(prop)) { @@ -4797,7 +4797,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat ret = PyBool_FromLong(*(int *)data); break; case PROP_INT: - ret = PyLong_FromSsize_t((Py_ssize_t)*(int *)data); + ret = PyLong_FromLong(*(int *)data); break; case PROP_FLOAT: ret = PyFloat_FromDouble(*(float *)data); @@ -6883,8 +6883,8 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v /* Sneaky workaround to use the class name as the bl_idname */ #define BPY_REPLACEMENT_STRING(rna_attr, py_attr) \ - if (strcmp(identifier, rna_attr) == 0) { \ - item = PyObject_GetAttrString(py_class, py_attr); \ + (strcmp(identifier, rna_attr) == 0) { \ + item = PyObject_GetAttr(py_class, py_attr); \ if (item && item != Py_None) { \ if (pyrna_py_to_prop(dummyptr, prop, NULL, \ item, "validating class:") != 0) \ @@ -6894,11 +6894,10 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v } \ } \ Py_XDECREF(item); \ - } (void)0 + } /* intendionally allow else here */ - - BPY_REPLACEMENT_STRING("bl_idname", "__name__"); - BPY_REPLACEMENT_STRING("bl_description", "__doc__"); + if BPY_REPLACEMENT_STRING("bl_idname", bpy_intern_str___name__) + else if BPY_REPLACEMENT_STRING("bl_description", bpy_intern_str___doc__) #undef BPY_REPLACEMENT_STRING @@ -6912,10 +6911,11 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v PyErr_Clear(); } else { - Py_DECREF(item); /* no need to keep a ref, the class owns it */ - - if (pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class:") != 0) + if (pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class:") != 0) { + Py_DECREF(item); return -1; + } + Py_DECREF(item); } } diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c index e66d8f05309..62c0ced9eab 100644 --- a/source/blender/python/intern/bpy_rna_array.c +++ b/source/blender/python/intern/bpy_rna_array.c @@ -507,7 +507,7 @@ static void py_to_float(PyObject *py, char *data) static void py_to_int(PyObject *py, char *data) { - *(int *)data = (int)PyLong_AsSsize_t(py); + *(int *)data = (int)PyLong_AsLong(py); } static void py_to_bool(PyObject *py, char *data) @@ -609,7 +609,7 @@ PyObject *pyrna_array_index(PointerRNA *ptr, PropertyRNA *prop, int index) item = PyBool_FromLong(RNA_property_boolean_get_index(ptr, prop, index)); break; case PROP_INT: - item = PyLong_FromSsize_t(RNA_property_int_get_index(ptr, prop, index)); + item = PyLong_FromLong(RNA_property_int_get_index(ptr, prop, index)); break; default: PyErr_SetString(PyExc_TypeError, "not an array type"); @@ -766,7 +766,7 @@ int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value) case PROP_BOOLEAN: case PROP_INT: { - int value_i = PyLong_AsSsize_t(value); + int value_i = PyLong_AsLong(value); if (value_i == -1 && PyErr_Occurred()) { PyErr_Clear(); return 0; diff --git a/source/blender/python/intern/bpy_traceback.c b/source/blender/python/intern/bpy_traceback.c index f7aa6e0880b..48bf65a841b 100644 --- a/source/blender/python/intern/bpy_traceback.c +++ b/source/blender/python/intern/bpy_traceback.c @@ -39,70 +39,80 @@ static const char *traceback_filepath(PyTracebackObject *tb, PyObject **coerce) return PyBytes_AS_STRING((*coerce = PyUnicode_EncodeFSDefault(tb->tb_frame->f_code->co_filename))); } -/* copied from pythonrun.c, 3.2.0 */ +/* copied from pythonrun.c, 3.3.0 */ static int parse_syntax_error(PyObject *err, PyObject **message, const char **filename, int *lineno, int *offset, const char **text) { long hold; PyObject *v; + _Py_IDENTIFIER(msg); + _Py_IDENTIFIER(filename); + _Py_IDENTIFIER(lineno); + _Py_IDENTIFIER(offset); + _Py_IDENTIFIER(text); - /* old style errors */ - if (PyTuple_Check(err)) - return PyArg_ParseTuple(err, "O(ziiz)", message, filename, - lineno, offset, text); + *message = NULL; /* new style errors. `err' is an instance */ - - if (!(v = PyObject_GetAttrString(err, "msg"))) + *message = _PyObject_GetAttrId(err, &PyId_msg); + if (!*message) goto finally; - *message = v; - if (!(v = PyObject_GetAttrString(err, "filename"))) + v = _PyObject_GetAttrId(err, &PyId_filename); + if (!v) goto finally; - if (v == Py_None) + if (v == Py_None) { + Py_DECREF(v); *filename = NULL; - else if (!(*filename = _PyUnicode_AsString(v))) - goto finally; + } + else { + *filename = _PyUnicode_AsString(v); + Py_DECREF(v); + if (!*filename) + goto finally; + } - Py_DECREF(v); - if (!(v = PyObject_GetAttrString(err, "lineno"))) + v = _PyObject_GetAttrId(err, &PyId_lineno); + if (!v) goto finally; hold = PyLong_AsLong(v); Py_DECREF(v); - v = NULL; if (hold < 0 && PyErr_Occurred()) goto finally; *lineno = (int)hold; - if (!(v = PyObject_GetAttrString(err, "offset"))) + v = _PyObject_GetAttrId(err, &PyId_offset); + if (!v) goto finally; if (v == Py_None) { *offset = -1; Py_DECREF(v); - v = NULL; - } - else { + } else { hold = PyLong_AsLong(v); Py_DECREF(v); - v = NULL; if (hold < 0 && PyErr_Occurred()) goto finally; *offset = (int)hold; } - if (!(v = PyObject_GetAttrString(err, "text"))) + v = _PyObject_GetAttrId(err, &PyId_text); + if (!v) goto finally; - if (v == Py_None) + if (v == Py_None) { + Py_DECREF(v); *text = NULL; - else if (!PyUnicode_Check(v) || - !(*text = _PyUnicode_AsString(v))) - goto finally; - Py_DECREF(v); + } + else { + *text = _PyUnicode_AsString(v); + Py_DECREF(v); + if (!*text) + goto finally; + } return 1; finally: - Py_XDECREF(v); + Py_XDECREF(*message); return 0; } /* end copied function! */ diff --git a/source/blender/python/intern/bpy_util.h b/source/blender/python/intern/bpy_util.h index 6aa50cf88de..b5f679b741f 100644 --- a/source/blender/python/intern/bpy_util.h +++ b/source/blender/python/intern/bpy_util.h @@ -27,16 +27,8 @@ #ifndef __BPY_UTIL_H__ #define __BPY_UTIL_H__ -#if PY_VERSION_HEX < 0x03020000 -# error "Python 3.2 or greater is required, you'll need to update your python." -#endif - #if PY_VERSION_HEX < 0x03030000 -# ifdef _MSC_VER -# pragma message("Python 3.2 will be deprecated soon, upgrade to Python 3.3.") -# else -# warning "Python 3.2 will be deprecated soon, upgrade to Python 3.3." -# endif +# error "Python 3.3 or greater is required, you'll need to update your python." #endif struct EnumPropertyItem; diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c index a4a4010005a..202598233b6 100644 --- a/source/blender/python/mathutils/mathutils.c +++ b/source/blender/python/mathutils/mathutils.c @@ -35,7 +35,10 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -#include "BLI_dynstr.h" + +#ifndef MATH_STANDALONE +# include "BLI_dynstr.h" +#endif PyDoc_STRVAR(M_Mathutils_doc, "This module provides access to matrices, eulers, quaternions and vectors." @@ -302,7 +305,7 @@ int EXPP_FloatsAreEqual(float af, float bf, int maxDiff) /*---------------------- EXPP_VectorsAreEqual ------------------------- * Builds on EXPP_FloatsAreEqual to test vectors */ -int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps) +int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps) { int x; for (x = 0; x < size; x++) { @@ -312,6 +315,7 @@ int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps) return 1; } +#ifndef MATH_STANDALONE /* dynstr as python string utility funcions, frees 'ds'! */ PyObject *mathutils_dynstr_to_py(struct DynStr *ds) { @@ -324,6 +328,7 @@ PyObject *mathutils_dynstr_to_py(struct DynStr *ds) PyMem_Free(ds_buf); return ret; } +#endif /* silly function, we dont use arg. just check its compatible with __deepcopy__ */ int mathutils_deepcopy_args_check(PyObject *args) diff --git a/source/blender/python/mathutils/mathutils.h b/source/blender/python/mathutils/mathutils.h index d4673d14823..7b03b149459 100644 --- a/source/blender/python/mathutils/mathutils.h +++ b/source/blender/python/mathutils/mathutils.h @@ -74,7 +74,7 @@ void BaseMathObject_dealloc(BaseMathObject * self); PyMODINIT_FUNC PyInit_mathutils(void); int EXPP_FloatsAreEqual(float A, float B, int floatSteps); -int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps); +int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps); #define Py_NEW 1 #define Py_WRAP 2 @@ -120,8 +120,11 @@ int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error int column_vector_multiplication(float rvec[4], VectorObject *vec, MatrixObject *mat); +#ifndef MATH_STANDALONE /* dynstr as python string utility funcions */ PyObject *mathutils_dynstr_to_py(struct DynStr *ds); +#endif + int mathutils_deepcopy_args_check(PyObject *args); #endif /* __MATHUTILS_H__ */ diff --git a/source/blender/python/mathutils/mathutils_Color.c b/source/blender/python/mathutils/mathutils_Color.c index f16b488f9d0..4a29e72418b 100644 --- a/source/blender/python/mathutils/mathutils_Color.c +++ b/source/blender/python/mathutils/mathutils_Color.c @@ -31,7 +31,10 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -#include "BLI_dynstr.h" + +#ifndef MATH_STANDALONE +# include "BLI_dynstr.h" +#endif #define COLOR_SIZE 3 @@ -131,6 +134,7 @@ static PyObject *Color_repr(ColorObject *self) return ret; } +#ifndef MATH_STANDALONE static PyObject *Color_str(ColorObject *self) { DynStr *ds; @@ -145,6 +149,7 @@ static PyObject *Color_str(ColorObject *self) return mathutils_dynstr_to_py(ds); /* frees ds */ } +#endif /* ------------------------tp_richcmpr */ /* returns -1 exception, 0 false, 1 true */ @@ -820,7 +825,11 @@ PyTypeObject color_Type = { &Color_AsMapping, /* tp_as_mapping */ NULL, /* tp_hash */ NULL, /* tp_call */ +#ifndef MATH_STANDALONE (reprfunc) Color_str, /* tp_str */ +#else + NULL, /* tp_str */ +#endif NULL, /* tp_getattro */ NULL, /* tp_setattro */ NULL, /* tp_as_buffer */ diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c index 829d3ee27e1..1be8a5efe28 100644 --- a/source/blender/python/mathutils/mathutils_Euler.c +++ b/source/blender/python/mathutils/mathutils_Euler.c @@ -35,7 +35,10 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -#include "BLI_dynstr.h" + +#ifndef MATH_STANDALONE +# include "BLI_dynstr.h" +#endif #define EULER_SIZE 3 @@ -323,6 +326,7 @@ static PyObject *Euler_repr(EulerObject *self) return ret; } +#ifndef MATH_STANDALONE static PyObject *Euler_str(EulerObject *self) { DynStr *ds; @@ -337,6 +341,7 @@ static PyObject *Euler_str(EulerObject *self) return mathutils_dynstr_to_py(ds); /* frees ds */ } +#endif static PyObject *Euler_richcmpr(PyObject *a, PyObject *b, int op) { @@ -663,7 +668,11 @@ PyTypeObject euler_Type = { &Euler_AsMapping, /* tp_as_mapping */ NULL, /* tp_hash */ NULL, /* tp_call */ +#ifndef MATH_STANDALONE (reprfunc) Euler_str, /* tp_str */ +#else + NULL, /* tp_str */ +#endif NULL, /* tp_getattro */ NULL, /* tp_setattro */ NULL, /* tp_as_buffer */ diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index 64112024dd1..05306f230d1 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -35,7 +35,10 @@ #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_string.h" -#include "BLI_dynstr.h" + +#ifndef MATH_STANDALONE +# include "BLI_dynstr.h" +#endif typedef enum eMatrixAccess_t { MAT_ACCESS_ROW, @@ -1647,6 +1650,7 @@ static PyObject *Matrix_repr(MatrixObject *self) return NULL; } +#ifndef MATH_STANDALONE static PyObject *Matrix_str(MatrixObject *self) { DynStr *ds; @@ -1682,6 +1686,7 @@ static PyObject *Matrix_str(MatrixObject *self) return mathutils_dynstr_to_py(ds); /* frees ds */ } +#endif static PyObject *Matrix_richcmpr(PyObject *a, PyObject *b, int op) { @@ -2418,7 +2423,11 @@ PyTypeObject matrix_Type = { &Matrix_AsMapping, /*tp_as_mapping*/ NULL, /*tp_hash*/ NULL, /*tp_call*/ +#ifndef MATH_STANDALONE (reprfunc) Matrix_str, /*tp_str*/ +#else + NULL, /*tp_str*/ +#endif NULL, /*tp_getattro*/ NULL, /*tp_setattro*/ NULL, /*tp_as_buffer*/ diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index cda39932610..c28631e5045 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -35,7 +35,10 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -#include "BLI_dynstr.h" + +#ifndef MATH_STANDALONE +# include "BLI_dynstr.h" +#endif #define QUAT_SIZE 4 @@ -496,6 +499,7 @@ static PyObject *Quaternion_repr(QuaternionObject *self) return ret; } +#ifndef MATH_STANDALONE static PyObject *Quaternion_str(QuaternionObject *self) { DynStr *ds; @@ -510,6 +514,7 @@ static PyObject *Quaternion_str(QuaternionObject *self) return mathutils_dynstr_to_py(ds); /* frees ds */ } +#endif static PyObject *Quaternion_richcmpr(PyObject *a, PyObject *b, int op) { @@ -1202,7 +1207,11 @@ PyTypeObject quaternion_Type = { &Quaternion_AsMapping, /* tp_as_mapping */ NULL, /* tp_hash */ NULL, /* tp_call */ +#ifndef MATH_STANDALONE (reprfunc) Quaternion_str, /* tp_str */ +#else + NULL, /* tp_str */ +#endif NULL, /* tp_getattro */ NULL, /* tp_setattro */ NULL, /* tp_as_buffer */ diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index 19be2b6a62e..f8159f6f187 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -35,7 +35,10 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -#include "BLI_dynstr.h" + +#ifndef MATH_STANDALONE +# include "BLI_dynstr.h" +#endif #define MAX_DIMENSIONS 4 @@ -1231,6 +1234,7 @@ static PyObject *Vector_repr(VectorObject *self) return ret; } +#ifndef MATH_STANDALONE static PyObject *Vector_str(VectorObject *self) { int i; @@ -1252,7 +1256,7 @@ static PyObject *Vector_str(VectorObject *self) return mathutils_dynstr_to_py(ds); /* frees ds */ } - +#endif /* Sequence Protocol */ /* sequence length len(vector) */ @@ -2784,7 +2788,7 @@ static struct PyMethodDef Vector_methods[] = { /* Note * Py_TPFLAGS_CHECKTYPES allows us to avoid casting all types to Vector when coercing * but this means for eg that - * (vec * mat) and (mat * vec) both get sent to Vector_mul and it neesd to sort out the order + * (vec * mat) and (mat * vec) both get sent to Vector_mul and it needs to sort out the order */ PyDoc_STRVAR(vector_doc, @@ -2816,7 +2820,11 @@ PyTypeObject vector_Type = { NULL, /* hashfunc tp_hash; */ NULL, /* ternaryfunc tp_call; */ +#ifndef MATH_STANDALONE (reprfunc)Vector_str, /* reprfunc tp_str; */ +#else + NULL, /* reprfunc tp_str; */ +#endif NULL, /* getattrofunc tp_getattro; */ NULL, /* setattrofunc tp_setattro; */ diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c index 22317636faa..1db0538eb07 100644 --- a/source/blender/python/mathutils/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -973,12 +973,14 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a float n1n2[3], n2n3[3], n3n1[3]; float potentialVertex[3]; - char *planes_used = MEM_callocN(sizeof(char) * len, __func__); + char *planes_used = PyMem_Malloc(sizeof(char) * len); /* python */ PyObject *py_verts = PyList_New(0); PyObject *py_plene_index = PyList_New(0); + memset(planes_used, 0, sizeof(char) * len); + for (i = 0; i < len; i++) { const float *N1 = planes[i]; for (j = i + 1; j < len; j++) { @@ -1031,7 +1033,7 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a Py_DECREF(item); } } - MEM_freeN(planes_used); + PyMem_Free(planes_used); { PyObject *ret = PyTuple_New(2); diff --git a/source/blender/quicktime/quicktime_export.h b/source/blender/quicktime/quicktime_export.h index cef4cb8c2a6..a3469ddafde 100644 --- a/source/blender/quicktime/quicktime_export.h +++ b/source/blender/quicktime/quicktime_export.h @@ -87,8 +87,8 @@ void makeqtstring(struct RenderData *rd, char *string); //for playanim.c -#if (defined(USE_QTKIT) && defined(MAC_OS_X_VERSION_10_6) && __LP64__) -//Include the quicktime codec types constants that are missing in QTKitDefines.h in 10.6 / 64bit +#if (defined(USE_QTKIT) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 && __LP64__) +//Include the quicktime codec types constants that are missing in QTKitDefines.h enum { kRawCodecType = 'raw ', kCinepakCodecType = 'cvid', diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index 1331c287d7c..d2ffc3a0e26 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -60,6 +60,7 @@ struct Scene; #define RE_ENGINE_PREVIEW 2 #define RE_ENGINE_DO_DRAW 4 #define RE_ENGINE_DO_UPDATE 8 +#define RE_ENGINE_RENDERING 16 extern ListBase R_engines; diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 984b1a8e651..ecdd1774221 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -170,6 +170,8 @@ void RE_FreeRender (struct Render *re); void RE_FreeAllRender (void); /* only call on file load */ void RE_FreeAllRenderResults(void); +/* for external render engines that can keep persistent data */ +void RE_FreePersistentData(void); /* get results and statistics */ void RE_FreeRenderResult(struct RenderResult *rr); diff --git a/source/blender/render/intern/include/initrender.h b/source/blender/render/intern/include/initrender.h index 43ab9552194..73dc29c8feb 100644 --- a/source/blender/render/intern/include/initrender.h +++ b/source/blender/render/intern/include/initrender.h @@ -40,8 +40,9 @@ struct Object; void free_sample_tables(Render *re); void make_sample_tables(Render *re); -void initparts(Render *re, int do_crop); -void freeparts(Render *re); +void RE_parts_clamp(Render *re); +void RE_parts_init(Render *re, int do_crop); +void RE_parts_free(Render *re); #endif /* __INITRENDER_H__ */ diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 825fe2ff4d0..6ed8d6a7b6c 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -59,6 +59,7 @@ struct RenderBuckets; struct ObjectInstanceRen; struct RayObject; struct RayFace; +struct RenderEngine; struct ReportList; struct Main; @@ -183,6 +184,9 @@ struct Render ListBase parts; + /* render engine */ + struct RenderEngine *engine; + /* octree tables and variables for raytrace */ struct RayObject *raytree; struct RayFace *rayfaces; diff --git a/source/blender/render/intern/raytrace/rayobject_internal.h b/source/blender/render/intern/raytrace/rayobject_internal.h index 92ac39909a8..aa8ab8c3da4 100644 --- a/source/blender/render/intern/raytrace/rayobject_internal.h +++ b/source/blender/render/intern/raytrace/rayobject_internal.h @@ -92,7 +92,7 @@ int RE_rayobjectcontrol_test_break(RayObjectControl *c); * eg.: on render code) * * 0 means it's reserved and has it own meaning inside each ray acceleration structure - * (this way each structure can use the allign offset to determine if a node represents a + * (this way each structure can use the align offset to determine if a node represents a * RayObject primitive, which can be used to save memory) */ diff --git a/source/blender/render/intern/raytrace/rayobject_octree.cpp b/source/blender/render/intern/raytrace/rayobject_octree.cpp index 77e9dc9d8fd..afb8fe6c3b5 100644 --- a/source/blender/render/intern/raytrace/rayobject_octree.cpp +++ b/source/blender/render/intern/raytrace/rayobject_octree.cpp @@ -1026,7 +1026,7 @@ static int RE_rayobject_octree_intersect(RayObject *tree, Isect *is) labdao = ddalabda; - /* traversing ocree nodes need careful detection of smallest values, with proper + /* traversing octree nodes need careful detection of smallest values, with proper * exceptions for equal labdas */ eqval = (labdax == labday); if (labday == labdaz) eqval += 2; diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp index bae65c492f4..4195b103811 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp @@ -435,7 +435,7 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) /* * Helper code * PARTITION code / used on mean-split - * basicly this a std::nth_element (like on C++ STL algorithm) + * basically this a std::nth_element (like on C++ STL algorithm) */ #if 0 static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis) diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index e305f434ebb..386086333e0 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -125,7 +125,9 @@ #define FLT_EPSILON10 1.19209290e-06F /* could enable at some point but for now there are far too many conversions */ -#pragma GCC diagnostic ignored "-Wdouble-promotion" +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif /* ------------------------------------------------------------------------- */ @@ -1705,8 +1707,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem totface= psmd->dm->getNumTessFaces(psmd->dm); index_mf_to_mpoly = psmd->dm->getTessFaceDataArray(psmd->dm, CD_ORIGINDEX); index_mp_to_orig = psmd->dm->getPolyDataArray(psmd->dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == FALSE) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } for (a=0; atotbound = max_ii(strandbuf->totbound, (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a): a); @@ -4296,7 +4298,7 @@ static void finalize_render_object(Render *re, ObjectRen *obr, int timeoffset) /* compute average bounding box of strandpoint itself (width) */ if (obr->strandbuf->flag & R_STRAND_B_UNITS) - obr->strandbuf->maxwidth= MAX2(obr->strandbuf->ma->strand_sta, obr->strandbuf->ma->strand_end); + obr->strandbuf->maxwidth = max_ff(obr->strandbuf->ma->strand_sta, obr->strandbuf->ma->strand_end); else obr->strandbuf->maxwidth= 0.0f; @@ -4501,7 +4503,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject * ParticleSystem *psys; int show_emitter, allow_render= 1, index, psysindex, i; - index= (dob)? dob->index: 0; + index= (dob)? dob->persistent_id[0]: 0; /* the emitter has to be processed first (render levels of modifiers) */ /* so here we only check if the emitter should be rendered */ @@ -4900,7 +4902,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp if (dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, 0))) { mult_m4_m4m4(mat, re->viewmat, dob->mat); /* ob = particle system, use that layer */ - obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, 0, mat, ob->lay); + obi= RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], 0, mat, ob->lay); /* fill in instance variables for texturing */ set_dupli_tex_mat(re, obi, dob); @@ -4927,7 +4929,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp if (dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, psysindex))) { if (obi == NULL) mult_m4_m4m4(mat, re->viewmat, dob->mat); - obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, psysindex++, mat, obd->lay); + obi= RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], psysindex++, mat, obd->lay); set_dupli_tex_mat(re, obi, dob); if (dob->type != OB_DUPLIGROUP) { diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index 28f70211a9c..c3126e57b53 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -687,11 +687,12 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o env->ima = tex->ima; if (env->ima && env->ima->ok) { if (env->cube[1] == NULL) { - ImBuf *ibuf_ima = BKE_image_get_ibuf(env->ima, NULL); + ImBuf *ibuf_ima = BKE_image_acquire_ibuf(env->ima, NULL, NULL); if (ibuf_ima) envmap_split_ima(env, ibuf_ima); else env->ok = 0; + BKE_image_release_ibuf(env->ima, ibuf_ima, NULL); } } } diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 4ec19fa729f..6fdf11ba48c 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -306,7 +306,7 @@ void RE_engine_report(RenderEngine *engine, int type, const char *msg) if (re) BKE_report(engine->re->reports, type, msg); - else if(engine->reports) + else if (engine->reports) BKE_report(engine->reports, type, msg); } @@ -316,6 +316,7 @@ int RE_engine_render(Render *re, int do_all) { RenderEngineType *type = RE_engines_find(re->r.engine); RenderEngine *engine; + int persistent_data = re->r.mode & R_PERSISTENT_DATA; /* verify if we can render */ if (!type->render) @@ -349,7 +350,18 @@ int RE_engine_render(Render *re, int do_all) re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0; /* render */ - engine = RE_engine_create(type); + engine = re->engine; + + if (!engine) { + engine = RE_engine_create(type); + + if (persistent_data) + re->engine = engine; + } + + engine->flag |= RE_ENGINE_RENDERING; + + /* TODO: actually link to a parent which shouldn't happen */ engine->re = re; if (re->flag & R_ANIMATION) @@ -364,7 +376,7 @@ int RE_engine_render(Render *re, int do_all) if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_PREVIEWBUTS)) == 0) BKE_scene_update_for_newframe(re->main, re->scene, re->lay); - initparts(re, FALSE); + RE_parts_init(re, FALSE); engine->tile_x = re->partx; engine->tile_y = re->party; @@ -377,19 +389,25 @@ int RE_engine_render(Render *re, int do_all) if (type->render) type->render(engine, re->scene); + engine->tile_x = 0; + engine->tile_y = 0; + engine->flag &= ~RE_ENGINE_RENDERING; + + render_result_free_list(&engine->fullresult, engine->fullresult.first); + + /* re->engine becomes zero if user changed active render engine during render */ + if (!persistent_data || !re->engine) { + RE_engine_free(engine); + re->engine = NULL; + } + if (re->result->do_exr_tile) { BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); render_result_exr_file_end(re); BLI_rw_mutex_unlock(&re->resultmutex); } - engine->tile_x = 0; - engine->tile_y = 0; - freeparts(re); - - render_result_free_list(&engine->fullresult, engine->fullresult.first); - - RE_engine_free(engine); + RE_parts_free(re); if (BKE_reports_contain(re->reports, RPT_ERROR)) G.is_break = TRUE; diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index db1454fd82f..cd06839b004 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -124,13 +124,16 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul /* hack for icon render */ if (ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD)) return retval; - - ibuf= BKE_image_get_ibuf(ima, &tex->iuser); + + ibuf= BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); ima->flag|= IMA_USED_FOR_RENDER; } - if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) + if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; + } /* setup mapping */ if (tex->imaflag & TEX_IMAROT) { @@ -155,11 +158,17 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul /* pass */ } else { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; } } if ( (tex->flag & TEX_CHECKER_EVEN)==0) { - if ((xs+ys) & 1) return retval; + if ((xs+ys) & 1) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + return retval; + } } /* scale around center, (0.5, 0.5) */ if (tex->checkerdist<1.0f) { @@ -173,11 +182,15 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul if (tex->extend == TEX_CLIPCUBE) { if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0f || texvec[2]>1.0f) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; } } else if ( tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) { if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; } } @@ -287,6 +300,9 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul texres->tb*= fx; } + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + BRICONTRGB; return retval; @@ -1056,10 +1072,14 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex if (ima) { /* hack for icon render */ if ((ima->ibufs.first == NULL) && (R.r.scemode & R_NO_IMAGE_LOAD)) return retval; - ibuf = BKE_image_get_ibuf(ima, &tex->iuser); + ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); } - if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) return retval; + if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + return retval; + } if (ima) { ima->flag |= IMA_USED_FOR_RENDER; @@ -1172,8 +1192,16 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex } } else { - if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) return retval; - if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) return retval; + if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + return retval; + } + if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + return retval; + } fx -= xs; fy -= ys; } @@ -1189,10 +1217,18 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex } if (tex->extend == TEX_CLIPCUBE) { - if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f || texvec[2] < -1.f || texvec[2] > 1.f) return retval; + if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f || texvec[2] < -1.f || texvec[2] > 1.f) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + return retval; + } } else if (tex->extend == TEX_CLIP || tex->extend == TEX_CHECKER) { - if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f) return retval; + if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + return retval; + } } else { if (tex->extend == TEX_EXTEND) { @@ -1413,6 +1449,9 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex texres->tb *= fx; } + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + BRICONTRGB; return retval; @@ -1449,12 +1488,15 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const if (ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD)) return retval; - ibuf= BKE_image_get_ibuf(ima, &tex->iuser); + ibuf= BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); ima->flag|= IMA_USED_FOR_RENDER; } - if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) + if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; + } /* mipmap test */ image_mipmap_test(tex, ibuf); @@ -1565,11 +1607,15 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const /* pass */ } else { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; } } if ( (tex->flag & TEX_CHECKER_EVEN)==0) { if ((xs + ys) & 1) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; } } @@ -1605,11 +1651,15 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const if (tex->extend == TEX_CLIPCUBE) { if (fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f || texvec[2]<-1.0f || texvec[2]>1.0f) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; } } else if (tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) { if (fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; } } @@ -1804,6 +1854,9 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const mul_v3_fl(&texres->tr, 1.0f / texres->ta); } + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + BRICONTRGB; return retval; @@ -1812,7 +1865,7 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const void image_sample(Image *ima, float fx, float fy, float dx, float dy, float result[4]) { TexResult texres; - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL); if (UNLIKELY(ibuf == NULL)) { zero_v4(result); @@ -1830,6 +1883,8 @@ void image_sample(Image *ima, float fx, float fy, float dx, float dy, float resu ibuf->rect-= (ibuf->x*ibuf->y); ima->flag|= IMA_USED_FOR_RENDER; + + BKE_image_release_ibuf(ima, ibuf, NULL); } void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float result[4]) diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c index b2cf8db7995..3ea74abbcc2 100644 --- a/source/blender/render/intern/source/initrender.c +++ b/source/blender/render/intern/source/initrender.c @@ -525,7 +525,7 @@ void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, flo /* ~~~~~~~~~~~~~~~~ part (tile) calculus ~~~~~~~~~~~~~~~~~~~~~~ */ -void freeparts(Render *re) +void RE_parts_free(Render *re) { RenderPart *part = re->parts.first; @@ -537,12 +537,19 @@ void freeparts(Render *re) BLI_freelistN(&re->parts); } -void initparts(Render *re, int do_crop) +void RE_parts_clamp(Render *re) +{ + /* part size */ + re->partx = min_ii(re->r.tilex, re->rectx); + re->party = min_ii(re->r.tiley, re->recty); +} + +void RE_parts_init(Render *re, int do_crop) { int nr, xd, yd, partx, party, xparts, yparts; int xminb, xmaxb, yminb, ymaxb; - freeparts(re); + RE_parts_free(re); /* this is render info for caller, is not reset when parts are freed! */ re->i.totpart = 0; @@ -555,13 +562,10 @@ void initparts(Render *re, int do_crop) xmaxb = re->disprect.xmax; ymaxb = re->disprect.ymax; - /* part size */ - partx = min_ii(re->r.tilex, re->rectx); - party = min_ii(re->r.tiley, re->recty); - - re->partx = partx; - re->party = party; - + RE_parts_clamp(re); + + partx = re->partx; + party = re->party; /* part count */ xparts = (re->rectx + partx - 1) / partx; yparts = (re->recty + party - 1) / party; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 7ef3aecad08..6b5b9716f3b 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -63,6 +63,7 @@ #include "BLI_string.h" #include "BLI_path_util.h" #include "BLI_fileops.h" +#include "BLI_threads.h" #include "BLI_rand.h" #include "BLI_callbacks.h" @@ -244,6 +245,7 @@ Render *RE_GetRender(const char *name) return re; } + /* if you want to know exactly what has been done */ RenderResult *RE_AcquireResultRead(Render *re) { @@ -387,6 +389,9 @@ void RE_InitRenderCB(Render *re) /* only call this while you know it will remove the link too */ void RE_FreeRender(Render *re) { + if (re->engine) + RE_engine_free(re->engine); + BLI_rw_mutex_end(&re->resultmutex); free_renderdata_tables(re); @@ -421,6 +426,22 @@ void RE_FreeAllRenderResults(void) } } +void RE_FreePersistentData(void) +{ + Render *re; + + /* render engines can be kept around for quick re-render, this clears all */ + for (re = RenderGlobal.renderlist.first; re; re = re->next) { + if (re->engine) { + /* if engine is currently rendering, just tag it to be freed when render is finished */ + if (!(re->engine->flag & RE_ENGINE_RENDERING)) + RE_engine_free(re->engine); + + re->engine = NULL; + } + } +} + /* ********* initialize state ******** */ @@ -672,7 +693,7 @@ static void *do_part_thread(void *pa_v) /* calculus for how much 1 pixel rendered should rotate the 3d geometry */ /* is not that simple, needs to be corrected for errors of larger viewplane sizes */ -/* called in initrender.c, initparts() and convertblender.c, for speedvectors */ +/* called in initrender.c, RE_parts_init() and convertblender.c, for speedvectors */ float panorama_pixel_rot(Render *re) { float psize, phi, xfac; @@ -815,7 +836,7 @@ static void threaded_tile_processor(Render *re) /* warning; no return here without closing exr file */ - initparts(re, TRUE); + RE_parts_init(re, TRUE); if (re->result->do_exr_tile) render_result_exr_file_begin(re); @@ -907,7 +928,7 @@ static void threaded_tile_processor(Render *re) g_break = 0; BLI_end_threads(&threads); - freeparts(re); + RE_parts_free(re); re->viewplane = viewplane; /* restore viewplane, modified by pano render */ } @@ -926,6 +947,7 @@ static void do_render_3d(Render *re) return; /* internal */ + RE_parts_clamp(re); // re->cfra= cfra; /* <- unused! */ re->scene->r.subframe = re->mblur_offs + re->field_offs; @@ -2507,8 +2529,8 @@ int RE_WriteEnvmapResult(struct ReportList *reports, Scene *scene, EnvMap *env, if (env->type == ENV_CUBE) { for (i = 0; i < 12; i += 2) { - maxX = MAX2(maxX, layout[i] + 1); - maxY = MAX2(maxY, layout[i + 1] + 1); + maxX = max_ii(maxX, (int)layout[i] + 1); + maxY = max_ii(maxY, (int)layout[i + 1] + 1); } ibuf = IMB_allocImBuf(maxX * dx, maxY * dx, 24, IB_rectfloat); diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index c507d6595e0..e6daa5f9094 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -1233,11 +1233,13 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os rgbnor = multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output); if (mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) { - ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); /* don't linearize float buffers, assumed to be linear */ if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace); + + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } } else { @@ -1264,11 +1266,13 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os rgbnor= multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres, thread, which_output); { - ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); /* don't linearize float buffers, assumed to be linear */ if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace); + + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } } @@ -1723,11 +1727,12 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, if (!shi->osatex && (tex->type == TEX_IMAGE) && tex->ima) { /* in case we have no proper derivatives, fall back to * computing du/dv it based on image size */ - ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); if (ibuf) { du = 1.f/(float)ibuf->x; dv = 1.f/(float)ibuf->y; } + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } else if (shi->osatex) { /* we have derivatives, can compute proper du/dv */ @@ -1900,12 +1905,13 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T /* resolve image dimensions */ if (found_deriv_map || (mtex->texflag&MTEX_BUMP_TEXTURESPACE)!=0) { - ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); if (ibuf) { dimx = ibuf->x; dimy = ibuf->y; aspect = ((float) dimy) / dimx; } + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } if (found_deriv_map) { @@ -2396,11 +2402,13 @@ void do_material_tex(ShadeInput *shi, Render *re) /* inverse gamma correction */ if (tex->type==TEX_IMAGE) { Image *ima = tex->ima; - ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); /* don't linearize float buffers, assumed to be linear */ if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace); + + BKE_image_release_ibuf(ima, ibuf, NULL); } if (mtex->mapto & MAP_COL) { @@ -2928,11 +2936,13 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4]) /* inverse gamma correction */ if (mtex->tex->type==TEX_IMAGE) { Image *ima = mtex->tex->ima; - ImBuf *ibuf = BKE_image_get_ibuf(ima, &mtex->tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &mtex->tex->iuser, NULL); /* don't linearize float buffers, assumed to be linear */ if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace); + + BKE_image_release_ibuf(ima, ibuf, NULL); } fact= texres.tin*mtex->colfac; @@ -3147,11 +3157,13 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h /* inverse gamma correction */ if (tex->type==TEX_IMAGE) { Image *ima = tex->ima; - ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); /* don't linearize float buffers, assumed to be linear */ if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace); + + BKE_image_release_ibuf(ima, ibuf, NULL); } if (mtex->mapto & WOMAP_HORIZ) { @@ -3361,11 +3373,13 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r /* inverse gamma correction */ if (tex->type==TEX_IMAGE) { Image *ima = tex->ima; - ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); /* don't linearize float buffers, assumed to be linear */ if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace); + + BKE_image_release_ibuf(ima, ibuf, NULL); } /* lamp colors were premultiplied with this */ diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 9fe2620747c..3431c3ff5de 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -2506,21 +2506,26 @@ static int get_next_bake_face(BakeShade *bs) if (tface && tface->tpage) { Image *ima= tface->tpage; - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL); const float vec_alpha[4]= {0.0f, 0.0f, 0.0f, 0.0f}; const float vec_solid[4]= {0.0f, 0.0f, 0.0f, 1.0f}; if (ibuf==NULL) continue; - if (ibuf->rect==NULL && ibuf->rect_float==NULL) + if (ibuf->rect==NULL && ibuf->rect_float==NULL) { + BKE_image_release_ibuf(ima, ibuf, NULL); continue; + } - if (ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4)) + if (ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4)) { + BKE_image_release_ibuf(ima, ibuf, NULL); continue; + } if (ima->flag & IMA_USED_FOR_RENDER) { ima->id.flag &= ~LIB_DOIT; + BKE_image_release_ibuf(ima, ibuf, NULL); continue; } @@ -2548,6 +2553,9 @@ static int get_next_bake_face(BakeShade *bs) v++; BLI_unlock_thread(LOCK_CUSTOM1); + + BKE_image_release_ibuf(ima, ibuf, NULL); + return 1; } } @@ -2571,8 +2579,10 @@ static void shade_tface(BakeShade *bs) /* check valid zspan */ if (ima!=bs->ima) { + BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL); + bs->ima= ima; - bs->ibuf= BKE_image_get_ibuf(ima, NULL); + bs->ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL); /* note, these calls only free/fill contents of zspan struct, not zspan itself */ zbuf_free_span(bs->zspan); zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y, R.clipcrop); @@ -2638,7 +2648,9 @@ static void *do_bake_thread(void *bs_v) *bs->do_update= TRUE; } bs->ready= 1; - + + BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL); + return NULL; } @@ -2689,12 +2701,13 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up /* baker uses this flag to detect if image was initialized */ for (ima= G.main->image.first; ima; ima= ima->id.next) { - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL); ima->id.flag |= LIB_DOIT; ima->flag&= ~IMA_USED_FOR_RENDER; if (ibuf) { ibuf->userdata = NULL; /* use for masking if needed */ } + BKE_image_release_ibuf(ima, ibuf, NULL); } BLI_init_threads(&threads, do_bake_thread, re->r.threads); @@ -2747,7 +2760,7 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up /* filter and refresh images */ for (ima= G.main->image.first; ima; ima= ima->id.next) { if ((ima->id.flag & LIB_DOIT)==0) { - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL); if (ima->flag & IMA_USED_FOR_RENDER) result= BAKE_RESULT_FEEDBACK_LOOP; @@ -2758,6 +2771,7 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, re->r.bake_filter); ibuf->userflags |= IB_BITMAPDIRTY; + BKE_image_release_ibuf(ima, ibuf, NULL); } } diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 7a7602dcce2..44daaf516e1 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -1179,30 +1179,36 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater /* -------------------------- operations on entire database ----------------------- */ /* ugly function for halos in panorama */ -static int panotestclip(Render *re, int do_pano, float *v) +static int panotestclip(Render *re, int do_pano, float v[4]) { - /* to be used for halos en infos */ - float abs4; - short c=0; - int xparts = (re->rectx + re->partx - 1) / re->partx; + /* part size (ensure we run RE_parts_clamp first) */ + BLI_assert(re->partx == min_ii(re->r.tilex, re->rectx)); + BLI_assert(re->party == min_ii(re->r.tiley, re->recty)); if (do_pano == FALSE) { return testclip(v); } + else { + /* to be used for halos en infos */ + float abs4; + short c = 0; - abs4= fabs(v[3]); + int xparts = (re->rectx + re->partx - 1) / re->partx; - if (v[2]< -abs4) c=16; /* this used to be " if (v[2]<0) ", see clippz() */ - else if (v[2]> abs4) c+= 32; + abs4= fabsf(v[3]); - if ( v[1]>abs4) c+=4; - else if ( v[1]< -abs4) c+=8; + if (v[2]< -abs4) c=16; /* this used to be " if (v[2]<0) ", see clippz() */ + else if (v[2]> abs4) c+= 32; - abs4*= xparts; - if ( v[0]>abs4) c+=2; - else if ( v[0]< -abs4) c+=1; + if ( v[1]>abs4) c+=4; + else if ( v[1]< -abs4) c+=8; - return c; + abs4*= xparts; + if ( v[0]>abs4) c+=2; + else if ( v[0]< -abs4) c+=1; + + return c; + } } /** diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c index c37f48bc329..a7f6b40981d 100644 --- a/source/blender/render/intern/source/shadbuf.c +++ b/source/blender/render/intern/source/shadbuf.c @@ -637,7 +637,7 @@ static void shadowbuf_autoclip(Render *re, LampRen *lar) maxtotvert= 0; for (obr=re->objecttable.first; obr; obr=obr->next) - maxtotvert= MAX2(obr->totvert, maxtotvert); + maxtotvert = max_ii(obr->totvert, maxtotvert); clipflag= MEM_callocN(sizeof(char)*maxtotvert, "autoclipflag"); diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 77602edf955..597196f464b 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -58,7 +58,9 @@ #include "shading.h" /* own include */ /* could enable at some point but for now there are far too many conversions */ -#pragma GCC diagnostic ignored "-Wdouble-promotion" +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ diff --git a/source/blender/render/intern/source/sunsky.c b/source/blender/render/intern/source/sunsky.c index e4a42fcd675..e812b99287c 100644 --- a/source/blender/render/intern/source/sunsky.c +++ b/source/blender/render/intern/source/sunsky.c @@ -118,8 +118,8 @@ static void DirectionToThetaPhi(float *toSun, float *theta, float *phi) /** * PerezFunction: - * compute perez function value based on input paramters - * */ + * compute perez function value based on input parameters + */ static float PerezFunction(struct SunSky *sunsky, const float *lam, float theta, float gamma, float lvz) { float den, num; diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c index b486407c61c..77d6644479a 100644 --- a/source/blender/render/intern/source/voxeldata.c +++ b/source/blender/render/intern/source/voxeldata.c @@ -157,10 +157,10 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex) /* find the first valid ibuf and use it to initialize the resolution of the data set */ /* need to do this in advance so we know how much memory to allocate */ - ibuf = BKE_image_get_ibuf(ima, &iuser); + ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); while (!ibuf && (iuser.framenr < iuser.frames)) { iuser.framenr++; - ibuf = BKE_image_get_ibuf(ima, &iuser); + ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); } if (!ibuf) return; if (!ibuf->rect_float) IMB_float_from_rect(ibuf); @@ -175,7 +175,8 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex) /* get a new ibuf for each frame */ if (z > 0) { iuser.framenr++; - ibuf = BKE_image_get_ibuf(ima, &iuser); + BKE_image_release_ibuf(ima, ibuf, NULL); + ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); if (!ibuf) break; if (!ibuf->rect_float) IMB_float_from_rect(ibuf); } @@ -191,7 +192,9 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex) BKE_image_free_anim_ibufs(ima, iuser.framenr); } - + + BKE_image_release_ibuf(ima, ibuf, NULL); + vd->ok = 1; return; } @@ -265,7 +268,7 @@ static void init_frame_smoke(VoxelData *vd, float cfra) /* map velocities between 0 and 0.3f */ for (i = 0; i < totRes; i++) { - vd->dataset[i] = sqrt(xvel[i] * xvel[i] + yvel[i] * yvel[i] + zvel[i] * zvel[i]) * 3.0f; + vd->dataset[i] = sqrtf(xvel[i] * xvel[i] + yvel[i] * yvel[i] + zvel[i] * zvel[i]) * 3.0f; } } diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 62bf9ac2005..c52fb84a7f8 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -77,7 +77,9 @@ #include "zbuf.h" /* could enable at some point but for now there are far too many conversions */ -#pragma GCC diagnostic ignored "-Wdouble-promotion" +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index b9a4e720230..8d885bf6d6f 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -106,7 +106,7 @@ int WM_homefile_read_exec(struct bContext *C, struct wmOperator *op); int WM_homefile_read(struct bContext *C, struct ReportList *reports, short from_memory); int WM_homefile_write_exec(struct bContext *C, struct wmOperator *op); void WM_file_read(struct bContext *C, const char *filepath, struct ReportList *reports); -int WM_file_write(struct bContext *C, const char *target, int fileflags, struct ReportList *reports, int copy); +int WM_file_write(struct bContext *C, const char *target, int fileflags, struct ReportList *reports); void WM_autosave_init(struct wmWindowManager *wm); /* mouse cursors */ @@ -171,6 +171,7 @@ void WM_event_timer_sleep(struct wmWindowManager *wm, struct wmWindow *win, str /* operator api, default callbacks */ /* invoke callback, uses enum property named "type" */ +int WM_operator_view3d_distance_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_menu_invoke (struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); /* invoke callback, confirm menu + exec */ @@ -181,6 +182,7 @@ int WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const char imt /* poll callback, context checks */ int WM_operator_winactive (struct bContext *C); /* invoke callback, exec + redo popup */ +int WM_operator_props_popup_call(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_operator_props_popup (struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_operator_props_dialog_popup (struct bContext *C, struct wmOperator *op, int width, int height); int WM_operator_redo_popup (struct bContext *C, struct wmOperator *op); @@ -320,9 +322,9 @@ enum { WM_JOB_SUSPEND = (1 << 3) }; -/* identifying jobs by owner alone is unreliable, this isnt saved, order can change */ +/* identifying jobs by owner alone is unreliable, this isnt saved, order can change (keep 0 for 'any') */ enum { - WM_JOB_TYPE_ANY = -1, + WM_JOB_TYPE_ANY = 0, WM_JOB_TYPE_COMPOSITE, WM_JOB_TYPE_RENDER, WM_JOB_TYPE_RENDER_PREVIEW, /* UI preview */ @@ -359,8 +361,9 @@ void WM_jobs_start(struct wmWindowManager *wm, struct wmJob *); void WM_jobs_stop(struct wmWindowManager *wm, void *owner, void *startjob); void WM_jobs_kill(struct wmWindowManager *wm, void *owner, void (*)(void *, short int *, short int *, float *)); void WM_jobs_kill_all(struct wmWindowManager *wm); - void WM_jobs_kill_all_except(struct wmWindowManager *wm, void *owner); - +void WM_jobs_kill_all_except(struct wmWindowManager *wm, void *owner); +void WM_jobs_kill_type(struct wmWindowManager *wm, int job_type); + int WM_jobs_has_running(struct wmWindowManager *wm); /* clipboard */ diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 094df73bbd9..347f46c8166 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -300,6 +300,7 @@ typedef struct wmNotifier { /* NC_MATERIAL Material */ #define ND_SHADING (30<<16) #define ND_SHADING_DRAW (31<<16) +#define ND_SHADING_LINKS (32<<16) /* NC_LAMP Lamp */ #define ND_LIGHTING (40<<16) @@ -326,6 +327,7 @@ typedef struct wmNotifier { /* Mesh, Curve, MetaBall, Armature, .. */ #define ND_SELECT (90<<16) #define ND_DATA (91<<16) +#define ND_VERTEX_GROUP (92<<16) /* NC_NODE Nodes */ diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 66bb321e832..a92ed65392c 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -84,7 +84,7 @@ static void wm_paintcursor_draw(bContext *C, ARegion *ar) bScreen *screen = win->screen; wmPaintCursor *pc; - if (screen->subwinactive == ar->swinid) { + if (ar->swinid && screen->subwinactive == ar->swinid) { for (pc = wm->paintcursors.first; pc; pc = pc->next) { if (pc->poll == NULL || pc->poll(C)) { ARegion *ar_other = CTX_wm_region(C); @@ -631,7 +631,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win) if (paintcursor && wm->paintcursors.first) { for (sa = screen->areabase.first; sa; sa = sa->next) { for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->swinid == screen->subwinactive) { + if (ar->swinid && ar->swinid == screen->subwinactive) { CTX_wm_area_set(C, sa); CTX_wm_region_set(C, ar); @@ -711,12 +711,14 @@ static int wm_automatic_draw_method(wmWindow *win) if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE)) return USER_DRAW_OVERLAP; /* also Intel drivers are slow */ +#if 0 /* 2.64 BCon3 period, let's try if intel now works... */ else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_UNIX, GPU_DRIVER_ANY)) return USER_DRAW_OVERLAP; else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_ANY)) return USER_DRAW_OVERLAP_FLIP; else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_MAC, GPU_DRIVER_ANY)) return USER_DRAW_OVERLAP_FLIP; +#endif /* Windows software driver darkens color on each redraw */ else if (GPU_type_matches(GPU_DEVICE_SOFTWARE, GPU_OS_WIN, GPU_DRIVER_SOFTWARE)) return USER_DRAW_OVERLAP_FLIP; @@ -751,6 +753,15 @@ void wm_draw_update(bContext *C) GPU_free_unused_buffers(); for (win = wm->windows.first; win; win = win->next) { + int state = GHOST_GetWindowState(win->ghostwin);; + + if (state == GHOST_kWindowStateMinimized) { + /* do not update minimized windows, it gives issues on intel drivers (see [#33223]) + * anyway, it seems logical to skip update for invisile windows + */ + continue; + } + if (win->drawmethod != U.wmdrawmethod) { wm_draw_window_clear(win); win->drawmethod = U.wmdrawmethod; diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index fee94b95a6a..c0e3b19c716 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -135,6 +135,7 @@ static int wm_test_duplicate_notifier(wmWindowManager *wm, unsigned int type, vo /* XXX: in future, which notifiers to send to other windows? */ void WM_event_add_notifier(const bContext *C, unsigned int type, void *reference) { + ARegion *ar; wmNotifier *note = MEM_callocN(sizeof(wmNotifier), "notifier"); note->wm = CTX_wm_manager(C); @@ -142,8 +143,9 @@ void WM_event_add_notifier(const bContext *C, unsigned int type, void *reference note->window = CTX_wm_window(C); - if (CTX_wm_region(C)) - note->swinid = CTX_wm_region(C)->swinid; + ar = CTX_wm_region(C); + if (ar) + note->swinid = ar->swinid; note->category = type & NOTE_CATEGORY; note->data = type & NOTE_DATA; @@ -340,7 +342,7 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve int retval; /* UI code doesn't handle return values - it just always returns break. - to make the DBL_CLICK conversion work, we just don't send this to UI */ + * to make the DBL_CLICK conversion work, we just don't send this to UI */ if (event->val == KM_DBL_CLICK) return WM_HANDLER_CONTINUE; @@ -1279,74 +1281,6 @@ int WM_userdef_event_map(int kmitype) return kmitype; } -static void wm_eventemulation(wmEvent *event) -{ - /* Store last mmb event value to make emulation work when modifier keys are released first. */ - static int mmb_emulated = 0; /* this should be in a data structure somwhere */ - - /* middlemouse emulation */ - if (U.flag & USER_TWOBUTTONMOUSE) { - if (event->type == LEFTMOUSE) { - - if (event->val == KM_PRESS && event->alt) { - event->type = MIDDLEMOUSE; - event->alt = 0; - mmb_emulated = 1; - } - else if (event->val == KM_RELEASE) { - /* only send middle-mouse release if emulated */ - if (mmb_emulated) { - event->type = MIDDLEMOUSE; - event->alt = 0; - } - mmb_emulated = 0; - } - } - - } - -#ifdef __APPLE__ - - /* rightmouse emulation */ - if (U.flag & USER_TWOBUTTONMOUSE) { - if (event->type == LEFTMOUSE) { - - if (event->val == KM_PRESS && event->oskey) { - event->type = RIGHTMOUSE; - event->oskey = 0; - mmb_emulated = 1; - } - else if (event->val == KM_RELEASE) { - if (mmb_emulated) { - event->oskey = RIGHTMOUSE; - event->alt = 0; - } - mmb_emulated = 0; - } - } - - } -#endif - - /* numpad emulation */ - if (U.flag & USER_NONUMPAD) { - switch (event->type) { - case ZEROKEY: event->type = PAD0; break; - case ONEKEY: event->type = PAD1; break; - case TWOKEY: event->type = PAD2; break; - case THREEKEY: event->type = PAD3; break; - case FOURKEY: event->type = PAD4; break; - case FIVEKEY: event->type = PAD5; break; - case SIXKEY: event->type = PAD6; break; - case SEVENKEY: event->type = PAD7; break; - case EIGHTKEY: event->type = PAD8; break; - case NINEKEY: event->type = PAD9; break; - case MINUSKEY: event->type = PADMINUS; break; - case EQUALKEY: event->type = PADPLUSKEY; break; - case BACKSLASHKEY: event->type = PADSLASHKEY; break; - } - } -} static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) { @@ -1356,9 +1290,9 @@ static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) /* the matching rules */ if (kmitype == KM_TEXTINPUT) - if (winevent->val == KM_PRESS) { // prevent double clicks + if (winevent->val == KM_PRESS) { /* prevent double clicks */ /* NOT using ISTEXTINPUT anymore because (at least on Windows) some key codes above 255 - could have printable ascii keys - BUG [#30479] */ + * could have printable ascii keys - BUG [#30479] */ if (ISKEYBOARD(winevent->type) && (winevent->ascii || winevent->utf8_buf[0])) return 1; } @@ -1378,7 +1312,8 @@ static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) if (kmi->oskey != KM_ANY) if (winevent->oskey != kmi->oskey && !(winevent->oskey & kmi->oskey)) return 0; - if (winevent->keymodifier != kmi->keymodifier) return 0; + if (kmi->keymodifier) + if (winevent->keymodifier != kmi->keymodifier) return 0; return 1; @@ -1618,8 +1553,8 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa if (handler->op->reports->list.first) { /* FIXME, temp setting window, this is really bad! - * only have because lib linking errors need to be seen by users :( - * it can be removed without breaking anything but then no linking errors - campbell */ + * only have because lib linking errors need to be seen by users :( + * it can be removed without breaking anything but then no linking errors - campbell */ wmWindow *win_prev = CTX_wm_window(C); ScrArea *area_prev = CTX_wm_area(C); ARegion *ar_prev = CTX_wm_region(C); @@ -2113,8 +2048,6 @@ void wm_event_do_handlers(bContext *C) } #endif - wm_eventemulation(event); - CTX_wm_window_set(C, win); /* we let modal handlers get active area/region, also wm_paintcursor_test needs it */ @@ -2616,6 +2549,75 @@ static int convert_key(GHOST_TKey key) } } +static void wm_eventemulation(wmEvent *event) +{ + /* Store last mmb event value to make emulation work when modifier keys are released first. */ + static int mmb_emulated = 0; /* this should be in a data structure somwhere */ + + /* middlemouse emulation */ + if (U.flag & USER_TWOBUTTONMOUSE) { + if (event->type == LEFTMOUSE) { + + if (event->val == KM_PRESS && event->alt) { + event->type = MIDDLEMOUSE; + event->alt = 0; + mmb_emulated = 1; + } + else if (event->val == KM_RELEASE) { + /* only send middle-mouse release if emulated */ + if (mmb_emulated) { + event->type = MIDDLEMOUSE; + event->alt = 0; + } + mmb_emulated = 0; + } + } + + } + +#ifdef __APPLE__ + + /* rightmouse emulation */ + if (U.flag & USER_TWOBUTTONMOUSE) { + if (event->type == LEFTMOUSE) { + + if (event->val == KM_PRESS && event->oskey) { + event->type = RIGHTMOUSE; + event->oskey = 0; + mmb_emulated = 1; + } + else if (event->val == KM_RELEASE) { + if (mmb_emulated) { + event->oskey = RIGHTMOUSE; + event->alt = 0; + } + mmb_emulated = 0; + } + } + + } +#endif + + /* numpad emulation */ + if (U.flag & USER_NONUMPAD) { + switch (event->type) { + case ZEROKEY: event->type = PAD0; break; + case ONEKEY: event->type = PAD1; break; + case TWOKEY: event->type = PAD2; break; + case THREEKEY: event->type = PAD3; break; + case FOURKEY: event->type = PAD4; break; + case FIVEKEY: event->type = PAD5; break; + case SIXKEY: event->type = PAD6; break; + case SEVENKEY: event->type = PAD7; break; + case EIGHTKEY: event->type = PAD8; break; + case NINEKEY: event->type = PAD9; break; + case MINUSKEY: event->type = PADMINUS; break; + case EQUALKEY: event->type = PADPLUSKEY; break; + case BACKSLASHKEY: event->type = PADSLASHKEY; break; + } + } +} + /* adds customdata to event */ static void update_tablet_data(wmWindow *win, wmEvent *event) { @@ -2731,47 +2733,45 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U event = *evt; switch (type) { - /* mouse move */ + /* mouse move, also to inactive window (X11 does this) */ case GHOST_kEventCursorMove: { - if (win->active) { - GHOST_TEventCursorData *cd = customdata; - wmEvent *lastevent = win->queue.last; - int cx, cy; - - GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy); - evt->x = cx; - evt->y = (win->sizey - 1) - cy; - - event.x = evt->x; - event.y = evt->y; + GHOST_TEventCursorData *cd = customdata; + wmEvent *lastevent = win->queue.last; + int cx, cy; + + GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy); + evt->x = cx; + evt->y = (win->sizey - 1) - cy; + + event.x = evt->x; + event.y = evt->y; - event.type = MOUSEMOVE; + event.type = MOUSEMOVE; - /* some painting operators want accurate mouse events, they can - * handle in between mouse move moves, others can happily ignore - * them for better performance */ - if (lastevent && lastevent->type == MOUSEMOVE) - lastevent->type = INBETWEEN_MOUSEMOVE; + /* some painting operators want accurate mouse events, they can + * handle in between mouse move moves, others can happily ignore + * them for better performance */ + if (lastevent && lastevent->type == MOUSEMOVE) + lastevent->type = INBETWEEN_MOUSEMOVE; - update_tablet_data(win, &event); - wm_event_add(win, &event); + update_tablet_data(win, &event); + wm_event_add(win, &event); + + /* also add to other window if event is there, this makes overdraws disappear nicely */ + /* it remaps mousecoord to other window in event */ + owin = wm_event_cursor_other_windows(wm, win, &event); + if (owin) { + wmEvent oevent = *(owin->eventstate); - /* also add to other window if event is there, this makes overdraws disappear nicely */ - /* it remaps mousecoord to other window in event */ - owin = wm_event_cursor_other_windows(wm, win, &event); - if (owin) { - wmEvent oevent = *(owin->eventstate); - - oevent.x = owin->eventstate->x = event.x; - oevent.y = owin->eventstate->y = event.y; - oevent.type = MOUSEMOVE; - - update_tablet_data(owin, &oevent); - wm_event_add(owin, &oevent); - } + oevent.x = owin->eventstate->x = event.x; + oevent.y = owin->eventstate->y = event.y; + oevent.type = MOUSEMOVE; + update_tablet_data(owin, &oevent); + wm_event_add(owin, &oevent); } + break; } case GHOST_kEventTrackpad: @@ -2827,6 +2827,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U else event.type = MIDDLEMOUSE; + wm_eventemulation(&event); + /* copy previous state to prev event state (two old!) */ evt->prevval = evt->val; evt->prevtype = evt->type; @@ -2892,6 +2894,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U memcpy(event.utf8_buf, kd->utf8_buf, sizeof(event.utf8_buf)); /* might be not null terminated*/ event.val = (type == GHOST_kEventKeyDown) ? KM_PRESS : KM_RELEASE; + wm_eventemulation(&event); + /* copy previous state to prev event state (two old!) */ evt->prevval = evt->val; evt->prevtype = evt->type; @@ -2980,9 +2984,13 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U if (event.keymodifier == UNKNOWNKEY) event.keymodifier = 0; - /* if test_break set, it catches this. XXX Keep global for now? */ - if (event.type == ESCKEY && event.val == KM_PRESS) + /* if test_break set, it catches this. Do not set with modifier presses. XXX Keep global for now? */ + if ((event.type == ESCKEY && event.val == KM_PRESS) && + /* check other modifiers because ms-windows uses these to bring up the task manager */ + (event.shift == 0 && event.ctrl == 0 && event.alt == 0)) + { G.is_break = TRUE; + } /* double click test - only for press */ if (event.val == KM_PRESS) { diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 6124b03778d..0e4af46d0fc 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -762,7 +762,7 @@ int write_crash_blend(void) } } -int WM_file_write(bContext *C, const char *target, int fileflags, ReportList *reports, int copy) +int WM_file_write(bContext *C, const char *target, int fileflags, ReportList *reports) { Library *li; int len; @@ -818,7 +818,7 @@ int WM_file_write(bContext *C, const char *target, int fileflags, ReportList *re fileflags |= G_FILE_HISTORY; /* write file history */ if (BLO_write_file(CTX_data_main(C), filepath, fileflags, reports, thumb)) { - if (!copy) { + if (!(fileflags & G_FILE_SAVE_COPY)) { G.relbase_valid = 1; BLI_strncpy(G.main->name, filepath, sizeof(G.main->name)); /* is guaranteed current file */ diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index b3ffb80243a..a80386e9860 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -255,7 +255,7 @@ static void draw_filled_lasso(wmGesture *gt) if (sf_vert_first) { const float zvec[3] = {0.0f, 0.0f, 1.0f}; BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert); - BLI_scanfill_calc_ex(&sf_ctx, FALSE, zvec); + BLI_scanfill_calc_ex(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES, zvec); glEnable(GL_BLEND); glColor4f(1.0, 1.0, 1.0, 0.05); diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c index 42d721327b6..3c3e2c0feaa 100644 --- a/source/blender/windowmanager/intern/wm_jobs.c +++ b/source/blender/windowmanager/intern/wm_jobs.c @@ -131,31 +131,34 @@ struct wmJob { }; /* finds: - * 1st priority: job with same owner and name - * 2nd priority: job with same owner + * if type, compare for it, otherwise any matching job */ -static wmJob *wm_job_find(wmWindowManager *wm, void *owner, const char *name) +static wmJob *wm_job_find(wmWindowManager *wm, void *owner, const int job_type) { - wmJob *wm_job, *found = NULL; + wmJob *wm_job; for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) if (wm_job->owner == owner) { - found = wm_job; - if (name && strcmp(wm_job->name, name) == 0) + + if (job_type) { + if ( wm_job->job_type == job_type) + return wm_job; + } + else return wm_job; } - return found; + return NULL; } /* ******************* public API ***************** */ /* returns current or adds new job, but doesnt run it */ -/* every owner only gets a single job, adding a new one will stop running stop and +/* every owner only gets a single job, adding a new one will stop running job and * when stopped it starts the new one */ wmJob *WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner, const char *name, int flag, int job_type) { - wmJob *wm_job = wm_job_find(wm, owner, name); + wmJob *wm_job = wm_job_find(wm, owner, job_type); if (wm_job == NULL) { wm_job = MEM_callocN(sizeof(wmJob), "new job"); @@ -167,7 +170,11 @@ wmJob *WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner, const char * wm_job->job_type = job_type; BLI_strncpy(wm_job->name, name, sizeof(wm_job->name)); } + /* else: a running job, be careful */ + /* prevent creating a job with an invalid type */ + BLI_assert(wm_job->job_type != WM_JOB_TYPE_ANY); + return wm_job; } @@ -192,7 +199,7 @@ int WM_jobs_test(wmWindowManager *wm, void *owner, int job_type) float WM_jobs_progress(wmWindowManager *wm, void *owner) { - wmJob *wm_job = wm_job_find(wm, owner, NULL); + wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY); if (wm_job && wm_job->flag & WM_JOB_PROGRESS) return wm_job->progress; @@ -202,7 +209,7 @@ float WM_jobs_progress(wmWindowManager *wm, void *owner) char *WM_jobs_name(wmWindowManager *wm, void *owner) { - wmJob *wm_job = wm_job_find(wm, owner, NULL); + wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY); if (wm_job) return wm_job->name; @@ -398,15 +405,29 @@ void WM_jobs_kill_all(wmWindowManager *wm) /* wait until every job ended, except for one owner (used in undo to keep screen job alive) */ void WM_jobs_kill_all_except(wmWindowManager *wm, void *owner) { - wmJob *wm_job; + wmJob *wm_job, *next_job; - for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { + for (wm_job = wm->jobs.first; wm_job; wm_job = next_job) { + next_job = wm_job->next; + if (wm_job->owner != owner) wm_jobs_kill_job(wm, wm_job); } } +void WM_jobs_kill_type(struct wmWindowManager *wm, int job_type) +{ + wmJob *wm_job, *next_job; + + for (wm_job = wm->jobs.first; wm_job; wm_job = next_job) { + next_job = wm_job->next; + + if (wm_job->job_type == job_type) + wm_jobs_kill_job(wm, wm_job); + } +} + /* signal job(s) from this owner or callback to stop, timer is required to get handled */ void WM_jobs_stop(wmWindowManager *wm, void *owner, void *startjob) { diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 7aa2b403897..3739462ac2c 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -101,11 +101,8 @@ static int wm_keymap_item_equals_result(wmKeyMapItem *a, wmKeyMapItem *b) if (strcmp(a->idname, b->idname) != 0) return 0; - if (!((a->ptr == NULL && b->ptr == NULL) || - (a->ptr && b->ptr && IDP_EqualsProperties(a->ptr->data, b->ptr->data)))) - { + if (!RNA_struct_equals(a->ptr, b->ptr)) return 0; - } if ((a->flag & KMI_INACTIVE) != (b->flag & KMI_INACTIVE)) return 0; @@ -395,7 +392,7 @@ int WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi) } BLI_freelinkN(&keymap->items, kmi); - WM_keyconfig_update_tag(keymap, kmi); + WM_keyconfig_update_tag(keymap, NULL); return TRUE; } else { @@ -545,7 +542,7 @@ static wmKeyMap *wm_keymap_patch_update(ListBase *lb, wmKeyMap *defaultmap, wmKe /* copy new keymap from an existing one */ if (usermap && !(usermap->flag & KEYMAP_DIFF)) { - /* for compatibiltiy with old user preferences with non-diff + /* for compatibility with old user preferences with non-diff * keymaps we override the original entirely */ wmKeyMapItem *kmi, *orig_kmi; diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 2ef33aa5964..8a0701b1063 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -72,6 +72,7 @@ #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" /* BKE_ST_MAXNAME */ +#include "BKE_utildefines.h" #include "BKE_idcode.h" @@ -86,6 +87,7 @@ #include "ED_screen.h" #include "ED_util.h" #include "ED_object.h" +#include "ED_view3d.h" #include "RNA_access.h" #include "RNA_define.h" @@ -623,7 +625,7 @@ void WM_operator_properties_sanitize(PointerRNA *ptr, const short no_context) /** set all props to their default, * \param do_update Only update un-initialized props. * - * \note, theres nothing spesific to operators here. + * \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) @@ -688,6 +690,35 @@ void WM_operator_properties_free(PointerRNA *ptr) /* ************ default op callbacks, exported *********** */ +int WM_operator_view3d_distance_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *UNUSED(event)) +{ + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + + const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, NULL) : ED_scene_grid_scale(scene, NULL); + + /* always run, so the values are initialized, + * otherwise we may get differ behavior when (dia != 1.0) */ + RNA_STRUCT_BEGIN(op->ptr, prop) + { + if (RNA_property_type(prop) == PROP_FLOAT) { + PropertySubType pstype = RNA_property_subtype(prop); + if (pstype == PROP_DISTANCE) { + /* we don't support arrays yet */ + BLI_assert(RNA_property_array_check(prop) == FALSE); + /* initialize */ + if (!RNA_property_is_set_ex(op->ptr, prop, FALSE)) { + const float value = RNA_property_float_get_default(op->ptr, prop) * dia; + RNA_property_float_set(op->ptr, prop, value); + } + } + } + } + RNA_STRUCT_END; + + return op->type->exec(C, op); +} + /* invoke callback, uses enum property named "type" */ int WM_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { @@ -792,7 +823,7 @@ static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg_op) uiButSetSearchFunc(but, operator_enum_search_cb, op->type, operator_enum_call_cb, NULL); /* fake button, it holds space for search items */ - uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxhHeight(), 9 * UI_UNIT_X, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); + 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); @@ -903,6 +934,8 @@ void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type, prop = RNA_def_boolean(ot->srna, "filter_blender", (filter & BLENDERFILE), "Filter .blend files", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "filter_backup", (filter & BLENDERFILE_BACKUP), "Filter .blend files", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, "filter_image", (filter & IMAGEFILE), "Filter image files", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_boolean(ot->srna, "filter_movie", (filter & MOVIEFILE), "Filter movie files", ""); @@ -1022,6 +1055,23 @@ wmOperator *WM_operator_last_redo(const bContext *C) return op; } +static void wm_block_redo_cb(bContext *C, void *arg_op, int UNUSED(arg_event)) +{ + wmOperator *op = arg_op; + + if (op == WM_operator_last_redo(C)) { + /* operator was already executed once? undo & repeat */ + ED_undo_operator_repeat(C, op); + } + else { + /* operator not executed yet, call it */ + ED_undo_push_op(C, op); + wm_operator_register(C, op); + + WM_operator_repeat(C, op); + } +} + static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) { wmOperator *op = arg_op; @@ -1029,7 +1079,6 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) uiLayout *layout; uiStyle *style = UI_GetStyle(); int width = 300; - block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); uiBlockClearFlag(block, UI_BLOCK_LOOP); @@ -1039,11 +1088,12 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) * ui_apply_but_funcs_after calls ED_undo_operator_repeate_cb and crashes */ assert(op->type->flag & OPTYPE_REGISTER); - uiBlockSetHandleFunc(block, ED_undo_operator_repeat_cb_evt, arg_op); + uiBlockSetHandleFunc(block, wm_block_redo_cb, arg_op); layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, width, UI_UNIT_Y, style); - if (!WM_operator_check_ui_enabled(C, op->type->name)) - uiLayoutSetEnabled(layout, FALSE); + if (op == WM_operator_last_redo(C)) + if (!WM_operator_check_ui_enabled(C, op->type->name)) + uiLayoutSetEnabled(layout, FALSE); if (op->type->flag & OPTYPE_MACRO) { for (op = op->macro.first; op; op = op->next) { @@ -1055,7 +1105,6 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE); } - uiPopupBoundsBlock(block, 4, 0, 0); uiEndBlock(C, block); @@ -1183,6 +1232,8 @@ static void wm_operator_ui_popup_ok(struct bContext *C, void *arg, int retval) if (op && retval > 0) WM_operator_call(C, op); + + MEM_freeN(data); } int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height) @@ -1196,24 +1247,45 @@ int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height) return OPERATOR_RUNNING_MODAL; } -/* operator menu needs undo, for redo callback */ -int WM_operator_props_popup(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +/** + * For use by #WM_operator_props_popup_call, #WM_operator_props_popup only. + * + * \note operator menu needs undo flag enabled , for redo callback */ +static int wm_operator_props_popup_ex(bContext *C, wmOperator *op, const int do_call) { - if ((op->type->flag & OPTYPE_REGISTER) == 0) { BKE_reportf(op->reports, RPT_ERROR, "Operator '%s' does not have register enabled, incorrect invoke function", op->type->idname); return OPERATOR_CANCELLED; } - - ED_undo_push_op(C, op); - wm_operator_register(C, op); + + /* if we don't have global undo, we can't do undo push for automatic redo, + * so we require manual OK clicking in this popup */ + if (!(U.uiflag & USER_GLOBALUNDO)) + return WM_operator_props_dialog_popup(C, op, 300, UI_UNIT_Y); uiPupBlock(C, wm_block_create_redo, op); + if (do_call) + wm_block_redo_cb(C, op, 0); + return OPERATOR_RUNNING_MODAL; } +/* Same as WM_operator_props_popup but call the operator first, + * This way - the button values correspond to the result of the operator. + * Without this, first access to a button will make the result jump, + * see [#32452] */ +int WM_operator_props_popup_call(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +{ + return wm_operator_props_popup_ex(C, op, TRUE); +} + +int WM_operator_props_popup(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +{ + return wm_operator_props_popup_ex(C, op, FALSE); +} + int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, int height) { wmOpPopUp *data = MEM_callocN(sizeof(wmOpPopUp), "WM_operator_props_dialog_popup"); @@ -1277,6 +1349,31 @@ static void WM_OT_debug_menu(wmOperatorType *ot) RNA_def_int(ot->srna, "debug_value", 0, SHRT_MIN, SHRT_MAX, "Debug Value", "", -10000, 10000); } +/* ***************** Operator defaults ************************* */ +static int wm_operator_defaults_exec(bContext *C, wmOperator *op) +{ + PointerRNA ptr = CTX_data_pointer_get_type(C, "active_operator", &RNA_Operator); + + if (!ptr.data) { + BKE_report(op->reports, RPT_ERROR, "No operator in context"); + return OPERATOR_CANCELLED; + } + + WM_operator_properties_reset((wmOperator *)ptr.data); + return OPERATOR_FINISHED; +} + +/* used by operator preset menu. pre-2.65 this was a 'Reset' button */ +static void WM_OT_operator_defaults(wmOperatorType *ot) +{ + ot->name = "Restore Defaults"; + ot->idname = "WM_OT_operator_defaults"; + ot->description = "Set the active operator to its default values"; + + ot->exec = wm_operator_defaults_exec; + + ot->flag = OPTYPE_INTERNAL; +} /* ***************** Splash Screen ************************* */ @@ -1332,6 +1429,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar int i; MenuType *mt = WM_menutype_find("USERPREF_MT_splash", TRUE); char url[96]; + char file [FILE_MAX]; #ifndef WITH_HEADLESS extern char datatoc_splash_png[]; @@ -1397,7 +1495,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar uiItemL(col, "Links", ICON_NONE); uiItemStringO(col, IFACE_("Donations"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/blenderorg/blender-foundation/donation-payment"); uiItemStringO(col, IFACE_("Credits"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/development/credits"); - uiItemStringO(col, IFACE_("Release Log"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/development/release-logs/blender-264"); + uiItemStringO(col, IFACE_("Release Log"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/development/release-logs/blender-265"); uiItemStringO(col, IFACE_("Manual"), ICON_URL, "WM_OT_url_open", "url", "http://wiki.blender.org/index.php/Doc:2.6/Manual"); uiItemStringO(col, IFACE_("Blender Website"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org"); uiItemStringO(col, IFACE_("User Community"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/community/user-community"); @@ -1419,7 +1517,11 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar uiItemL(col, IFACE_("Recent"), ICON_NONE); for (recent = G.recent_files.first, i = 0; (i < 5) && (recent); recent = recent->next, i++) { - uiItemStringO(col, BLI_path_basename(recent->filepath), ICON_FILE_BLEND, "WM_OT_open_mainfile", "filepath", recent->filepath); + BLI_split_file_part(recent->filepath, file, sizeof(file)); + if (BLO_has_bfile_extension(file)) + uiItemStringO(col, BLI_path_basename(recent->filepath), ICON_FILE_BLEND, "WM_OT_open_mainfile", "filepath", recent->filepath); + else + uiItemStringO(col, BLI_path_basename(recent->filepath), ICON_FILE_BACKUP, "WM_OT_open_mainfile", "filepath", recent->filepath); } uiItemS(col); @@ -1451,49 +1553,6 @@ static void WM_OT_splash(wmOperatorType *ot) /* ***************** Search menu ************************* */ -static void operator_call_cb(struct bContext *C, void *UNUSED(arg1), void *arg2) -{ - wmOperatorType *ot = arg2; - - if (ot) - WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, NULL); -} - -static void operator_search_cb(const struct bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items) -{ - GHashIterator *iter = WM_operatortype_iter(); - - for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) { - wmOperatorType *ot = BLI_ghashIterator_getValue(iter); - - if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0) - continue; - - if (BLI_strcasestr(ot->name, str)) { - if (WM_operator_poll((bContext *)C, ot)) { - char name[256]; - int len = strlen(ot->name); - - /* display name for menu, can hold hotkey */ - BLI_strncpy(name, ot->name, sizeof(name)); - - /* check for hotkey */ - if (len < sizeof(name) - 6) { - if (WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, TRUE, - &name[len + 1], sizeof(name) - len - 1)) - { - name[len] = '|'; - } - } - - if (0 == uiSearchItemAdd(items, name, ot, 0)) - break; - } - } - } - BLI_ghashIterator_free(iter); -} - static uiBlock *wm_block_search_menu(bContext *C, ARegion *ar, void *UNUSED(arg_op)) { static char search[256] = ""; @@ -1506,10 +1565,10 @@ static uiBlock *wm_block_search_menu(bContext *C, ARegion *ar, void *UNUSED(arg_ 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, operator_search_cb, NULL, operator_call_cb, NULL); + uiOperatorSearch_But(but); /* fake button, it holds space for search items */ - uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxhHeight(), 9 * UI_UNIT_X, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); + 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); @@ -2070,7 +2129,6 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op) { char path[FILE_MAX]; int fileflags; - int copy = 0; save_set_compress(op); @@ -2080,29 +2138,27 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op) BLI_strncpy(path, G.main->name, FILE_MAX); untitled(path); } - - if (RNA_struct_property_is_set(op->ptr, "copy")) - copy = RNA_boolean_get(op->ptr, "copy"); fileflags = G.fileflags; /* set compression flag */ - if (RNA_boolean_get(op->ptr, "compress")) fileflags |= G_FILE_COMPRESS; - else fileflags &= ~G_FILE_COMPRESS; - if (RNA_boolean_get(op->ptr, "relative_remap")) fileflags |= G_FILE_RELATIVE_REMAP; - else fileflags &= ~G_FILE_RELATIVE_REMAP; + BKE_BIT_TEST_SET(fileflags, RNA_boolean_get(op->ptr, "compress"), + G_FILE_COMPRESS); + BKE_BIT_TEST_SET(fileflags, RNA_boolean_get(op->ptr, "relative_remap"), + G_FILE_RELATIVE_REMAP); + BKE_BIT_TEST_SET(fileflags, + (RNA_struct_property_is_set(op->ptr, "copy") && + RNA_boolean_get(op->ptr, "copy")), + G_FILE_SAVE_COPY); + #ifdef USE_BMESH_SAVE_AS_COMPAT - /* property only exists for 'Save As' */ - if (RNA_struct_find_property(op->ptr, "use_mesh_compat")) { - if (RNA_boolean_get(op->ptr, "use_mesh_compat")) fileflags |= G_FILE_MESH_COMPAT; - else fileflags &= ~G_FILE_MESH_COMPAT; - } - else { - fileflags &= ~G_FILE_MESH_COMPAT; - } + BKE_BIT_TEST_SET(fileflags, + (RNA_struct_find_property(op->ptr, "use_mesh_compat") && + RNA_boolean_get(op->ptr, "use_mesh_compat")), + G_FILE_MESH_COMPAT); #endif - if (WM_file_write(C, path, fileflags, op->reports, copy) != 0) + if (WM_file_write(C, path, fileflags, op->reports) != 0) return OPERATOR_CANCELLED; WM_event_add_notifier(C, NC_WM | ND_FILESAVE, NULL); @@ -3743,6 +3799,7 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_memory_statistics); WM_operatortype_append(WM_OT_dependency_relations); WM_operatortype_append(WM_OT_debug_menu); + WM_operatortype_append(WM_OT_operator_defaults); WM_operatortype_append(WM_OT_splash); WM_operatortype_append(WM_OT_search_menu); WM_operatortype_append(WM_OT_call_menu); diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index 96bbedfee1b..8b387196da7 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -61,6 +61,7 @@ #include "BKE_blender.h" #include "BKE_global.h" +#include "BKE_image.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -74,17 +75,19 @@ #include "WM_api.h" /* only for WM_main_playanim */ +struct PlayState; +static void playanim_window_zoom(const struct PlayState *ps, const float zoom_offset); + typedef struct PlayState { /* playback state */ short direction; - short next; + short next_frame; short once; short turbo; short pingpong; short noskip; short sstep; - short pause; short wait2; short stopped; short go; @@ -132,6 +135,7 @@ typedef enum eWS_Qual { WS_QUAL_ALT = (WS_QUAL_LALT | WS_QUAL_RALT), WS_QUAL_LCTRL = (1 << 4), WS_QUAL_RCTRL = (1 << 5), + WS_QUAL_CTRL = (WS_QUAL_LCTRL | WS_QUAL_RCTRL), WS_QUAL_LMOUSE = (1 << 16), WS_QUAL_MMOUSE = (1 << 17), WS_QUAL_RMOUSE = (1 << 18), @@ -179,27 +183,12 @@ static void playanim_event_qual_update(void) /* Alt */ GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftAlt, &val); - if (val) g_WS.qual |= WS_QUAL_LCTRL; - else g_WS.qual &= ~WS_QUAL_LCTRL; + if (val) g_WS.qual |= WS_QUAL_LALT; + else g_WS.qual &= ~WS_QUAL_LALT; GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyRightAlt, &val); - if (val) g_WS.qual |= WS_QUAL_RCTRL; - else g_WS.qual &= ~WS_QUAL_RCTRL; - - /* LMB */ - GHOST_GetButtonState(g_WS.ghost_system, GHOST_kButtonMaskLeft, &val); - if (val) g_WS.qual |= WS_QUAL_LMOUSE; - else g_WS.qual &= ~WS_QUAL_LMOUSE; - - /* MMB */ - GHOST_GetButtonState(g_WS.ghost_system, GHOST_kButtonMaskMiddle, &val); - if (val) g_WS.qual |= WS_QUAL_MMOUSE; - else g_WS.qual &= ~WS_QUAL_MMOUSE; - - /* RMB */ - GHOST_GetButtonState(g_WS.ghost_system, GHOST_kButtonMaskRight, &val); - if (val) g_WS.qual |= WS_QUAL_RMOUSE; - else g_WS.qual &= ~WS_QUAL_RMOUSE; + if (val) g_WS.qual |= WS_QUAL_RALT; + else g_WS.qual &= ~WS_QUAL_RALT; } typedef struct PlayAnimPict { @@ -218,6 +207,21 @@ static int fromdisk = FALSE; static float zoomx = 1.0, zoomy = 1.0; static double ptottime = 0.0, swaptime = 0.04; +static PlayAnimPict *playanim_step(PlayAnimPict *playanim, int step) +{ + if (step > 0) { + while (step-- && playanim) { + playanim = playanim->next; + } + } + else if (step < 0) { + while (step++ && playanim) { + playanim = playanim->prev; + } + } + return playanim; +} + static int pupdate_time(void) { static double ltime; @@ -234,7 +238,7 @@ static void playanim_toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fon { if (ibuf == NULL) { - printf("no ibuf !\n"); + printf("%s: no ibuf for picture '%s'\n", __func__, picture ? picture->name : ""); return; } if (ibuf->rect == NULL && ibuf->rect_float) { @@ -432,6 +436,11 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) ps->stopped = FALSE; } + if (ps->wait2) { + pupdate_time(); + ptottime = 0; + } + switch (type) { case GHOST_kEventKeyDown: case GHOST_kEventKeyUp: @@ -446,33 +455,42 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) case GHOST_kKeyP: if (val) ps->pingpong = !ps->pingpong; break; + case GHOST_kKey1: case GHOST_kKeyNumpad1: if (val) swaptime = ps->fstep / 60.0; break; + case GHOST_kKey2: case GHOST_kKeyNumpad2: if (val) swaptime = ps->fstep / 50.0; break; + case GHOST_kKey3: case GHOST_kKeyNumpad3: if (val) swaptime = ps->fstep / 30.0; break; + case GHOST_kKey4: case GHOST_kKeyNumpad4: if (g_WS.qual & WS_QUAL_SHIFT) swaptime = ps->fstep / 24.0; else swaptime = ps->fstep / 25.0; break; + case GHOST_kKey5: case GHOST_kKeyNumpad5: if (val) swaptime = ps->fstep / 20.0; break; + case GHOST_kKey6: case GHOST_kKeyNumpad6: if (val) swaptime = ps->fstep / 15.0; break; + case GHOST_kKey7: case GHOST_kKeyNumpad7: if (val) swaptime = ps->fstep / 12.0; break; + case GHOST_kKey8: case GHOST_kKeyNumpad8: if (val) swaptime = ps->fstep / 10.0; break; + case GHOST_kKey9: case GHOST_kKeyNumpad9: if (val) swaptime = ps->fstep / 6.0; break; @@ -482,10 +500,10 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) ps->wait2 = FALSE; if (g_WS.qual & WS_QUAL_SHIFT) { ps->picture = picsbase.first; - ps->next = 0; + ps->next_frame = 0; } else { - ps->next = -1; + ps->next_frame = -1; } } break; @@ -493,10 +511,10 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) if (val) { ps->wait2 = FALSE; if (g_WS.qual & WS_QUAL_SHIFT) { - ps->next = ps->direction = -1; + ps->next_frame = ps->direction = -1; } else { - ps->next = -10; + ps->next_frame = -10; ps->sstep = TRUE; } } @@ -507,10 +525,10 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) ps->wait2 = FALSE; if (g_WS.qual & WS_QUAL_SHIFT) { ps->picture = picsbase.last; - ps->next = 0; + ps->next_frame = 0; } else { - ps->next = 1; + ps->next_frame = 1; } } break; @@ -518,10 +536,10 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) if (val) { ps->wait2 = FALSE; if (g_WS.qual & WS_QUAL_SHIFT) { - ps->next = ps->direction = 1; + ps->next_frame = ps->direction = 1; } else { - ps->next = 10; + ps->next_frame = 10; ps->sstep = TRUE; } } @@ -532,35 +550,15 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) if (val) { if (g_WS.qual & WS_QUAL_SHIFT) { if (ps->curframe_ibuf) - printf(" Name: %s | Speed: %.2f frames/s\n", ps->curframe_ibuf->name, ps->fstep / swaptime); + printf(" Name: %s | Speed: %.2f frames/s\n", + ps->curframe_ibuf->name, ps->fstep / swaptime); } else { swaptime = ps->fstep / 5.0; } } break; - case GHOST_kKeyEqual: - if (val) { - if (g_WS.qual & WS_QUAL_SHIFT) { - ps->pause++; - printf("pause:%d\n", ps->pause); - } - else { - swaptime /= 1.1; - } - } - break; - case GHOST_kKeyMinus: - if (val) { - if (g_WS.qual & WS_QUAL_SHIFT) { - ps->pause--; - printf("pause:%d\n", ps->pause); - } - else { - swaptime *= 1.1; - } - } - break; + case GHOST_kKey0: case GHOST_kKeyNumpad0: if (val) { if (ps->once) { @@ -579,6 +577,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) ps->wait2 = ps->sstep = FALSE; } break; + case GHOST_kKeyPeriod: case GHOST_kKeyNumpadPeriod: if (val) { if (ps->sstep) ps->wait2 = FALSE; @@ -588,29 +587,28 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) } } break; + case GHOST_kKeyEqual: case GHOST_kKeyNumpadPlus: + { if (val == 0) break; - zoomx += 2.0f; - zoomy += 2.0f; - /* no break??? - is this intentional? - campbell XXX25 */ + if (g_WS.qual & WS_QUAL_CTRL) { + playanim_window_zoom(ps, 1.0f); + } + else { + swaptime /= 1.1; + } + break; + } + case GHOST_kKeyMinus: case GHOST_kKeyNumpadMinus: { - int sizex, sizey; - /* int ofsx, ofsy; */ /* UNUSED */ - if (val == 0) break; - if (zoomx > 1.0f) zoomx -= 1.0f; - if (zoomy > 1.0f) zoomy -= 1.0f; - // playanim_window_get_position(&ofsx, &ofsy); - playanim_window_get_size(&sizex, &sizey); - /* ofsx += sizex / 2; */ /* UNUSED */ - /* ofsy += sizey / 2; */ /* UNUSED */ - sizex = zoomx * ps->ibufx; - sizey = zoomy * ps->ibufy; - /* ofsx -= sizex / 2; */ /* UNUSED */ - /* ofsy -= sizey / 2; */ /* UNUSED */ - // window_set_position(g_WS.ghost_window,sizex,sizey); - GHOST_SetClientSize(g_WS.ghost_window, sizex, sizey); + if (g_WS.qual & WS_QUAL_CTRL) { + playanim_window_zoom(ps, -1.0f); + } + else { + swaptime *= 1.1; + } break; } case GHOST_kKeyEsc: @@ -621,6 +619,44 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) } break; } + case GHOST_kEventButtonDown: + case GHOST_kEventButtonUp: + { + GHOST_TEventButtonData *bd = GHOST_GetEventData(evt); + int cx, cy, sizex, sizey, inside_window; + + GHOST_GetCursorPosition(g_WS.ghost_system, &cx, &cy); + GHOST_ScreenToClient(g_WS.ghost_window, cx, cy, &cx, &cy); + playanim_window_get_size(&sizex, &sizey); + + inside_window = (cx >= 0 && cx < sizex && cy >= 0 && cy <= sizey); + + if (bd->button == GHOST_kButtonMaskLeft) { + if (type == GHOST_kEventButtonDown) { + if (inside_window) + g_WS.qual |= WS_QUAL_LMOUSE; + } + else + g_WS.qual &= ~WS_QUAL_LMOUSE; + } + else if (bd->button == GHOST_kButtonMaskMiddle) { + if (type == GHOST_kEventButtonDown) { + if (inside_window) + g_WS.qual |= WS_QUAL_MMOUSE; + } + else + g_WS.qual &= ~WS_QUAL_MMOUSE; + } + else if (bd->button == GHOST_kButtonMaskRight) { + if (type == GHOST_kEventButtonDown) { + if (inside_window) + g_WS.qual |= WS_QUAL_RMOUSE; + } + else + g_WS.qual &= ~WS_QUAL_RMOUSE; + } + break; + } case GHOST_kEventCursorMove: { if (g_WS.qual & WS_QUAL_LMOUSE) { @@ -648,10 +684,15 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) } ps->sstep = TRUE; ps->wait2 = FALSE; - ps->next = 0; + ps->next_frame = 0; } break; } + case GHOST_kEventWindowActivate: + case GHOST_kEventWindowDeactivate: { + g_WS.qual &= ~WS_QUAL_MOUSE; + break; + } case GHOST_kEventWindowSize: case GHOST_kEventWindowMove: { @@ -716,6 +757,25 @@ static void playanim_window_open(const char *title, int posx, int posy, int size FALSE /* no stereo */, FALSE); } +static void playanim_window_zoom(const PlayState *ps, const float zoom_offset) +{ + int sizex, sizey; + /* int ofsx, ofsy; */ /* UNUSED */ + + if (zoomx + zoom_offset > 0.0f) zoomx += zoom_offset; + if (zoomy + zoom_offset > 0.0f) zoomy += zoom_offset; + + // playanim_window_get_position(&ofsx, &ofsy); + playanim_window_get_size(&sizex, &sizey); + /* ofsx += sizex / 2; */ /* UNUSED */ + /* ofsy += sizey / 2; */ /* UNUSED */ + sizex = zoomx * ps->ibufx; + sizey = zoomy * ps->ibufy; + /* ofsx -= sizex / 2; */ /* UNUSED */ + /* ofsy -= sizey / 2; */ /* UNUSED */ + // window_set_position(g_WS.ghost_window,sizex,sizey); + GHOST_SetClientSize(g_WS.ghost_window, sizex, sizey); +} void WM_main_playanim(int argc, const char **argv) { @@ -736,13 +796,12 @@ void WM_main_playanim(int argc, const char **argv) /* ps.doubleb = TRUE;*/ /* UNUSED */ ps.go = TRUE; ps.direction = TRUE; - ps.next = TRUE; + ps.next_frame = 1; ps.once = FALSE; ps.turbo = FALSE; ps.pingpong = FALSE; ps.noskip = FALSE; ps.sstep = FALSE; - ps.pause = FALSE; ps.wait2 = FALSE; ps.stopped = FALSE; ps.picture = NULL; @@ -939,6 +998,7 @@ void WM_main_playanim(int argc, const char **argv) if (ptottime > 0.0) ptottime = 0.0; while (ps.picture) { + int hasevent; #ifndef USE_IMB_CACHE if (ibuf != NULL && ibuf->ftype == 0) IMB_freeImBuf(ibuf); #endif @@ -989,22 +1049,25 @@ void WM_main_playanim(int argc, const char **argv) } } - ps.next = ps.direction; + ps.next_frame = ps.direction; - { - int hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0); + while ((hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0) || ps.wait2 != 0)) { if (hasevent) { GHOST_DispatchEvents(g_WS.ghost_system); } - } - - /* XXX25 - we should not have to do this, but it makes scrubbing functional! */ - if (g_WS.qual & WS_QUAL_LMOUSE) { - ps.next = 0; - } - else { - ps.sstep = 0; + if (ps.wait2) { + if (hasevent) { + if (ibuf) { + while (pupdate_time()) PIL_sleep_ms(1); + ptottime -= swaptime; + playanim_toscreen(ps.picture, ibuf, ps.fontid, ps.fstep); + } + } + } + if (!ps.go) { + break; + } } ps.wait2 = ps.sstep; @@ -1015,15 +1078,10 @@ void WM_main_playanim(int argc, const char **argv) pupdate_time(); - if (ps.picture && ps.next) { + if (ps.picture && ps.next_frame) { /* always at least set one step */ while (ps.picture) { - if (ps.next < 0) { - ps.picture = ps.picture->prev; - } - else { - ps.picture = ps.picture->next; - } + ps.picture = playanim_step(ps.picture, ps.next_frame); if (ps.once && ps.picture != NULL) { if (ps.picture->next == NULL) { @@ -1038,12 +1096,7 @@ void WM_main_playanim(int argc, const char **argv) ptottime -= swaptime; } if (ps.picture == NULL && ps.sstep) { - if (ps.next < 0) { - ps.picture = picsbase.last; - } - else if (ps.next > 0) { - ps.picture = picsbase.first; - } + ps.picture = playanim_step(ps.picture, ps.next_frame); } } if (ps.go == FALSE) { @@ -1082,6 +1135,7 @@ void WM_main_playanim(int argc, const char **argv) /* we still miss freeing a lot!, * but many areas could skip initialization too for anim play */ IMB_exit(); + BKE_images_exit(); BLF_exit(); #endif GHOST_DisposeWindow(g_WS.ghost_system, g_WS.ghost_window); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 616567e8184..09f7e1692d9 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -333,8 +333,14 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win) static void wm_window_add_ghostwindow(const char *title, wmWindow *win) { GHOST_WindowHandle ghostwin; + static int multisamples = -1; int scr_w, scr_h, posy; + /* force setting multisamples only once, it requires restart - and you cannot + * mix it, either all windows have it, or none (tested in OSX opengl) */ + if (multisamples == -1) + multisamples = U.ogl_multisamples; + wm_get_screensize(&scr_w, &scr_h); posy = (scr_h - win->posy - win->sizey); @@ -345,7 +351,7 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win) (GHOST_TWindowState)win->windowstate, GHOST_kDrawingContextTypeOpenGL, 0 /* no stereo */, - 0 /* no AA */); + multisamples /* AA */); if (ghostwin) { /* needed so we can detect the graphics card below */ @@ -373,7 +379,6 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win) /* standard state vars for window */ glEnable(GL_SCISSOR_TEST); - GPU_state_init(); } } @@ -749,6 +754,11 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr state = GHOST_GetWindowState(win->ghostwin); win->windowstate = state; + /* stop screencast if resize */ + if (type == GHOST_kEventWindowSize) { + WM_jobs_stop(CTX_wm_manager(C), win->screen, NULL); + } + /* win32: gives undefined window size when minimized */ if (state != GHOST_kWindowStateMinimized) { GHOST_RectangleHandle client_rect; diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index ca0e9659a22..4d3d6ef89d9 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -285,9 +285,9 @@ enum { /* for event checks */ /* only used for KM_TEXTINPUT, so assume that we want all user-inputtable ascii codes included */ - /* UNUSED - see wm_eventmatch - BUG [#30479] -#define ISTEXTINPUT(event) (event >= ' ' && event <= 255) - */ + /* UNUSED - see wm_eventmatch - BUG [#30479] */ +// #define ISTEXTINPUT(event) (event >= ' ' && event <= 255) + /* test whether the event is a key on the keyboard */ #define ISKEYBOARD(event) (event >= ' ' && event <= 320) diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index 828b7f5066c..85bb07d6e83 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -60,7 +60,7 @@ elseif(APPLE) add_executable(blenderplayer ${EXETYPE} bad_level_call_stubs/stubs.c) # setup Info.plist execute_process(COMMAND date "+%Y-%m-%d" OUTPUT_VARIABLE BLENDER_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) - set(PLAYER_SOURCEDIR ${CMAKE_SOURCE_DIR}/source/darwin/blenderplayer.app) + set(PLAYER_SOURCEDIR ${CMAKE_SOURCE_DIR}/release/darwin/blenderplayer.app) set(PLAYER_SOURCEINFO ${PLAYER_SOURCEDIR}/Contents/Info.plist) set_target_properties(blenderplayer PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${PLAYER_SOURCEINFO} @@ -191,6 +191,10 @@ endif() list(APPEND BLENDER_SORTED_LIBS bf_intern_guardedalloc_cpp) endif() + if(WITH_INTERNATIONAL) + list(APPEND BLENDER_SORTED_LIBS bf_intern_locale) + endif() + foreach(SORTLIB ${BLENDER_SORTED_LIBS}) set(REMLIB ${SORTLIB}) foreach(SEARCHLIB ${BLENDER_LINK_LIBS}) diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 5550cc69f89..5e38dad74ed 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -422,7 +422,7 @@ void uiTemplateEditModeSelection(struct uiLayout *layout, struct bContext *C) {} void uiTemplateTextureImage(struct uiLayout *layout, struct bContext *C, struct Tex *tex) {} void uiTemplateImage(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, struct PointerRNA *userptr, int compact) {} void uiTemplateDopeSheetFilter(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr) {} -void uiTemplateColorWheel(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int value_slider) {} +void uiTemplateColorPicker(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int value_slider) {} void uiTemplateHistogram(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int expand) {} void uiTemplateReportsBanner(struct uiLayout *layout, struct bContext *C, struct wmOperator *op) {} void uiTemplateWaveform(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int expand) {} @@ -461,6 +461,8 @@ ListBase R_engines = {NULL, NULL}; void RE_engine_free(struct RenderEngine *engine) {} struct RenderEngineType *RE_engines_find(const char *idname) { return NULL; } void RE_engine_update_memory_stats(struct RenderEngine *engine, float mem_used, float mem_peak) {}; +struct RenderEngine *RE_engine_create(struct RenderEngineType *type) { return NULL; }; +void RE_FreePersistentData(void) {} /* python */ struct wmOperatorType *WM_operatortype_find(const char *idname, int quiet) {return (struct wmOperatorType *) NULL;} diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index c06669c3ac2..b66c000ac89 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -469,30 +469,19 @@ elseif(WIN32) DESTINATION ${TARGETDIR} ) - if(WITH_INTERNATIONAL AND (NOT WITH_MINGW64)) - install( - FILES ${LIBDIR}/gettext/lib/gnu_gettext.dll - DESTINATION ${TARGETDIR} - ) - - if(NOT CMAKE_CL_64) - install( - FILES ${LIBDIR}/iconv/lib/iconv.dll - DESTINATION ${TARGETDIR} - ) - endif() - endif() - if(WITH_PYTHON) set_lib_path(PYLIB "python") + + STRING(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) + install( - FILES ${PYLIB}/lib/python32.dll + FILES ${PYLIB}/lib/python${_PYTHON_VERSION_NO_DOTS}.dll DESTINATION ${TARGETDIR} CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel ) install( - FILES ${PYLIB}/lib/python32_d.dll + FILES ${PYLIB}/lib/python${_PYTHON_VERSION_NO_DOTS}_d.dll DESTINATION ${TARGETDIR} CONFIGURATIONS Debug ) @@ -516,10 +505,10 @@ elseif(WIN32) " if(\"\${CMAKE_INSTALL_CONFIG_NAME}\" STREQUAL \"Debug\") execute_process(COMMAND \"${CMAKE_COMMAND}\" -E chdir \"${TARGETDIR_VER}/python/lib\" - \"${CMAKE_COMMAND}\" -E tar xzfv \"${LIBDIR}/release/python32_d.tar.gz\") + \"${CMAKE_COMMAND}\" -E tar xzfv \"${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_d.tar.gz\") else() execute_process(COMMAND \"${CMAKE_COMMAND}\" -E chdir \"${TARGETDIR_VER}/python/lib\" - \"${CMAKE_COMMAND}\" -E tar xzfv \"${LIBDIR}/release/python32.tar.gz\") + \"${CMAKE_COMMAND}\" -E tar xzfv \"${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}.tar.gz\") endif() " ) @@ -527,10 +516,12 @@ elseif(WIN32) # doesnt work, todo # install(CODE "execute_process(COMMAND find ${TARGETDIR}/${BLENDER_VERSION}/python/lib/ -name '*.so' -exec strip -s {} '\;')") endif() + + unset(_PYTHON_VERSION_NO_DOTS) endif() if(CMAKE_CL_64) - # gettext and png are statically linked on win64 + # png is statically linked on win64 install( FILES ${LIBDIR}/zlib/lib/zlib.dll DESTINATION ${TARGETDIR} @@ -632,18 +623,7 @@ elseif(WIN32) install( # x86 builds can run on x64 Windows, so this is required at all times FILES ${LIBDIR}/thumbhandler/lib/BlendThumb64.dll DESTINATION ${TARGETDIR} - ) - - if(WITH_OPENIMAGEIO) - if(NOT MINGW) - set(OIIOBIN ${LIBDIR}/openimageio) - install( - FILES - ${OIIOBIN}/bin/OpenImageIO.dll - DESTINATION ${TARGETDIR} - ) - endif() - endif() + ) if(WITH_OPENCOLORIO) set(OCIOBIN ${LIBDIR}/opencolorio/bin) @@ -681,7 +661,7 @@ elseif(APPLE) ) endmacro() - set(OSX_APP_SOURCEDIR ${CMAKE_SOURCE_DIR}/source/darwin/blender.app) + set(OSX_APP_SOURCEDIR ${CMAKE_SOURCE_DIR}/release/darwin/blender.app) # setup Info.plist execute_process(COMMAND date "+%Y-%m-%d" OUTPUT_VARIABLE BLENDER_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) @@ -740,7 +720,7 @@ elseif(APPLE) # install blenderplayer bundle - copy of blender.app above. re-using macros et al # note we are using OSX Bundle as base and copying Blender dummy bundle on top of it if(WITH_GAMEENGINE AND WITH_PLAYER) - set(OSX_APP_PLAYER_SOURCEDIR ${CMAKE_SOURCE_DIR}/source/darwin/blenderplayer.app) + set(OSX_APP_PLAYER_SOURCEDIR ${CMAKE_SOURCE_DIR}/release/darwin/blenderplayer.app) set(PLAYER_SOURCEINFO ${OSX_APP_PLAYER_SOURCEDIR}/Contents/Info.plist) set(PLAYER_TARGETDIR_VER ${TARGETDIR}/blenderplayer.app/Contents/MacOS/${BLENDER_VERSION}) @@ -987,6 +967,10 @@ endif() list_insert_after(BLENDER_SORTED_LIBS "cycles_kernel" "cycles_kernel_osl") endif() + if(WITH_INTERNATIONAL) + list(APPEND BLENDER_SORTED_LIBS bf_intern_locale) + endif() + foreach(SORTLIB ${BLENDER_SORTED_LIBS}) set(REMLIB ${SORTLIB}) foreach(SEARCHLIB ${BLENDER_LINK_LIBS}) diff --git a/source/creator/blender.map b/source/creator/blender.map new file mode 100644 index 00000000000..928d0c2d904 --- /dev/null +++ b/source/creator/blender.map @@ -0,0 +1,16 @@ + +/* on Linux we exclude LLVM symbols, they conflict with Mesa llvmpipe + * we also keep boost's symbols local, since some python modules could + * be using boost as well (mainly that's for lux render) + */ + +{ +global: + *; + *_boost*; +local: + *llvm*; + *LLVM*; + *boost*; +}; + diff --git a/source/creator/creator.c b/source/creator/creator.c index ca3deaf70a4..0f1207a9a88 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -1077,7 +1077,9 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle) "\n\t\t-p \tOpen with lower left corner at , " "\n\t\t-m\t\tRead from disk (Don't buffer)" "\n\t\t-f \t\tSpecify FPS to start with" - "\n\t\t-j \tSet frame step to "; + "\n\t\t-j \tSet frame step to " + "\n\t\t-s \tPlay from " + "\n\t\t-e \tPlay until "; static char game_doc[] = "Game Engine specific options" "\n\t-g fixedtime\t\tRun on 50 hertz without dropping frames" @@ -1270,6 +1272,7 @@ int main(int argc, const char **argv) initglobals(); /* blender.c */ IMB_init(); + BKE_images_init(); #ifdef WITH_FFMPEG IMB_ffmpeg_init(); diff --git a/source/creator/osx_locals.map b/source/creator/osx_locals.map new file mode 100644 index 00000000000..c3dd8b62792 --- /dev/null +++ b/source/creator/osx_locals.map @@ -0,0 +1,3 @@ +## The symbols will be treated as if they were marked as __private_extern__ +## (aka visibility=hidden) and will not be global in the output file +*boost* diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp index 7c4c759e361..00836fa8ecb 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp @@ -95,35 +95,29 @@ static void DisableForText() { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); /* needed for texture fonts otherwise they render as wireframe */ - if (glIsEnabled(GL_BLEND)) glDisable(GL_BLEND); - if (glIsEnabled(GL_ALPHA_TEST)) glDisable(GL_ALPHA_TEST); + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); - if (glIsEnabled(GL_LIGHTING)) { - glDisable(GL_LIGHTING); - glDisable(GL_COLOR_MATERIAL); - } + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); if (GLEW_ARB_multitexture) { for (int i=0; i KX_BEGINMOUSE && kxevent < KX_ENDMOUSEBUTTONS) { - if (val == KM_PRESS) + if (val == KM_PRESS || val == KM_DBL_CLICK) { m_eventStatusTables[m_currentTable][kxevent].m_eventval = val ; //??? diff --git a/source/gameengine/Converter/BL_ArmatureChannel.cpp b/source/gameengine/Converter/BL_ArmatureChannel.cpp index 7cf895255ba..11e90e1797d 100644 --- a/source/gameengine/Converter/BL_ArmatureChannel.cpp +++ b/source/gameengine/Converter/BL_ArmatureChannel.cpp @@ -95,7 +95,7 @@ BL_ArmatureChannel::~BL_ArmatureChannel() // PYTHON PyMethodDef BL_ArmatureChannel::Methods[] = { - {NULL,NULL} //Sentinel + {NULL,NULL} //Sentinel }; // order of definition of attributes, must match Attributes[] array diff --git a/source/gameengine/Converter/BL_ArmatureConstraint.cpp b/source/gameengine/Converter/BL_ArmatureConstraint.cpp index b8ad117a220..379be91b523 100644 --- a/source/gameengine/Converter/BL_ArmatureConstraint.cpp +++ b/source/gameengine/Converter/BL_ArmatureConstraint.cpp @@ -246,7 +246,7 @@ void BL_ArmatureConstraint::SetSubtarget(KX_GameObject* subtarget) // PYTHON PyMethodDef BL_ArmatureConstraint::Methods[] = { - {NULL,NULL} //Sentinel + {NULL,NULL} //Sentinel }; // order of definition of attributes, must match Attributes[] array diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index ed97b9ff73f..1f1c404efcb 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -639,7 +639,6 @@ PyTypeObject BL_ArmatureObject::Type = { }; PyMethodDef BL_ArmatureObject::Methods[] = { - KX_PYMETHODTABLE_NOARGS(BL_ArmatureObject, update), {NULL,NULL} //Sentinel }; diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 58ae415e9d3..eb695e624e4 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -423,64 +423,55 @@ static void SetDefaultLightMode(Scene* scene) // -- -static void GetRGB(short type, - MFace* mface, - MCol* mmcol, - Material *mat, - unsigned int &c0, - unsigned int &c1, - unsigned int &c2, - unsigned int &c3) +static void GetRGB( + const bool use_mcol, + MFace *mface, + MCol *mmcol, + Material *mat, + unsigned int &c0, + unsigned int &c1, + unsigned int &c2, + unsigned int &c3) { unsigned int color = 0xFFFFFFFFL; - switch (type) { - case 0: // vertex colors - { - if (mmcol) { - c0 = KX_Mcol2uint_new(mmcol[0]); - c1 = KX_Mcol2uint_new(mmcol[1]); - c2 = KX_Mcol2uint_new(mmcol[2]); - if (mface->v4) - c3 = KX_Mcol2uint_new(mmcol[3]); - } - else { // backup white - c0 = KX_rgbaint2uint_new(color); - c1 = KX_rgbaint2uint_new(color); - c2 = KX_rgbaint2uint_new(color); - if (mface->v4) - c3 = KX_rgbaint2uint_new( color ); - } - } break; - - - case 1: // material rgba - { - if (mat) { - union { - unsigned char cp[4]; - unsigned int integer; - } col_converter; - col_converter.cp[3] = (unsigned char) (mat->r * 255.0f); - col_converter.cp[2] = (unsigned char) (mat->g * 255.0f); - col_converter.cp[1] = (unsigned char) (mat->b * 255.0f); - col_converter.cp[0] = (unsigned char) (mat->alpha * 255.0f); - color = col_converter.integer; - } + if (use_mcol) { + // vertex colors + + if (mmcol) { + c0 = KX_Mcol2uint_new(mmcol[0]); + c1 = KX_Mcol2uint_new(mmcol[1]); + c2 = KX_Mcol2uint_new(mmcol[2]); + if (mface->v4) + c3 = KX_Mcol2uint_new(mmcol[3]); + } + else { // backup white c0 = KX_rgbaint2uint_new(color); c1 = KX_rgbaint2uint_new(color); c2 = KX_rgbaint2uint_new(color); if (mface->v4) - c3 = KX_rgbaint2uint_new(color); - } break; - - default: // white - { - c0 = KX_rgbaint2uint_new(color); - c1 = KX_rgbaint2uint_new(color); - c2 = KX_rgbaint2uint_new(color); - if (mface->v4) - c3 = KX_rgbaint2uint_new(color); - } break; + c3 = KX_rgbaint2uint_new( color ); + } + } + else { + // material rgba + if (mat) { + union { + unsigned char cp[4]; + unsigned int integer; + } col_converter; + col_converter.cp[3] = (unsigned char) (mat->r * 255.0f); + col_converter.cp[2] = (unsigned char) (mat->g * 255.0f); + col_converter.cp[1] = (unsigned char) (mat->b * 255.0f); + col_converter.cp[0] = (unsigned char) (mat->alpha * 255.0f); + color = col_converter.integer; + } + // backup white is fallback + + c0 = KX_rgbaint2uint_new(color); + c1 = KX_rgbaint2uint_new(color); + c2 = KX_rgbaint2uint_new(color); + if (mface->v4) + c3 = KX_rgbaint2uint_new(color); } } @@ -489,6 +480,45 @@ typedef struct MTF_localLayer { const char *name; } MTF_localLayer; +static void tface_to_uv_bge(const MFace *mface, const MTFace *tface, MT_Point2 uv[4]) +{ + uv[0].setValue(tface->uv[0]); + uv[1].setValue(tface->uv[1]); + uv[2].setValue(tface->uv[2]); + if (mface->v4) { + uv[3].setValue(tface->uv[3]); + } +} + +static void GetUV( + MFace *mface, + MTFace *tface, + MTF_localLayer *layers, + const int layer_uv[2], + MT_Point2 uv[4], + MT_Point2 uv2[4]) +{ + bool validface = (tface != NULL); + + uv2[0] = uv2[1] = uv2[2] = uv2[3] = MT_Point2(0.0f, 0.0f); + + /* No material, what to do? let's see what is in the UV and set the material accordingly + * light and visible is always on */ + if (layer_uv[0] != -1) { + tface_to_uv_bge(mface, layers[layer_uv[0]].face, uv); + if (layer_uv[1] != -1) { + tface_to_uv_bge(mface, layers[layer_uv[1]].face, uv2); + } + } + else if (validface) { + tface_to_uv_bge(mface, tface, uv); + } + else { + // nothing at all + uv[0] = uv[1] = uv[2] = uv[3] = MT_Point2(0.0f, 0.0f); + } +} + // ------------------------------------ static bool ConvertMaterial( BL_Material *material, @@ -496,30 +526,25 @@ static bool ConvertMaterial( MTFace* tface, const char *tfaceName, MFace* mface, - MCol* mmcol, + MCol* mmcol, /* only for text, use first mcol, weak */ MTF_localLayer *layers, - bool glslmat) + int layer_uv[2], + const bool glslmat) { material->Initialize(); int numchan = -1, texalpha = 0; bool validmat = (mat!=0); bool validface = (tface!=0); - short type = 0; - if ( validmat ) - type = 1; // material color - material->IdMode = DEFAULT_BLENDER; material->glslmat = (validmat)? glslmat: false; material->materialindex = mface->mat_nr; + /* default value for being unset */ + layer_uv[0] = layer_uv[1] = -1; + // -------------------------------- if (validmat) { - - // use vertex colors by explicitly setting - if (mat->mode &MA_VERTEXCOLP || glslmat) - type = 0; - // use lighting? material->ras_mode |= ( mat->mode & MA_SHLESS )?0:USE_LIGHT; material->ras_mode |= ( mat->game.flag & GEMAT_BACKCULL )?0:TWOSIDED; @@ -772,33 +797,19 @@ static bool ConvertMaterial( // No material - old default TexFace properties material->ras_mode |= USE_LIGHT; } - MT_Point2 uv[4]; - MT_Point2 uv2[4]; - const char *uvName = "", *uv2Name = ""; - - uv2[0] = uv2[1] = uv2[2] = uv2[3] = MT_Point2(0.0f, 0.0f); + const char *uvName = "", *uv2Name = ""; /* No material, what to do? let's see what is in the UV and set the material accordingly * light and visible is always on */ if ( validface ) { material->tile = tface->tile; - - uv[0].setValue(tface->uv[0]); - uv[1].setValue(tface->uv[1]); - uv[2].setValue(tface->uv[2]); - - if (mface->v4) - uv[3].setValue(tface->uv[3]); - uvName = tfaceName; } else { // nothing at all material->alphablend = GEMAT_SOLID; material->tile = 0; - - uv[0] = uv[1] = uv[2] = uv[3] = MT_Point2(0.0f, 0.0f); } if (validmat && validface) { @@ -816,49 +827,30 @@ static bool ConvertMaterial( } // get uv sets - if (validmat) - { + if (validmat) { bool isFirstSet = true; // only two sets implemented, but any of the eight // sets can make up the two layers - for (int vind = 0; vindnum_enabled; vind++) - { + for (int vind = 0; vindnum_enabled; vind++) { BL_Mapping &map = material->mapping[vind]; - if (map.uvCoName.IsEmpty()) + if (map.uvCoName.IsEmpty()) { isFirstSet = false; - else - { - for (int lay=0; layuv[0]); - uvSet[1].setValue(layer.face->uv[1]); - uvSet[2].setValue(layer.face->uv[2]); - - if (mface->v4) - uvSet[3].setValue(layer.face->uv[3]); - else - uvSet[3].setValue(0.0f, 0.0f); - - if (isFirstSet) - { - uv[0] = uvSet[0]; uv[1] = uvSet[1]; - uv[2] = uvSet[2]; uv[3] = uvSet[3]; + if (strcmp(map.uvCoName.ReadPtr(), layer.name)==0) { + if (isFirstSet) { + layer_uv[0] = lay; isFirstSet = false; uvName = layer.name; } - else if (strcmp(layer.name, uvName) != 0) - { - uv2[0] = uvSet[0]; uv2[1] = uvSet[1]; - uv2[2] = uvSet[2]; uv2[3] = uvSet[3]; + else if (strcmp(layer.name, uvName) != 0) { + layer_uv[1] = lay; map.mapping |= USECUSTOMUV; uv2Name = layer.name; } @@ -868,21 +860,11 @@ static bool ConvertMaterial( } } - unsigned int rgb[4]; - GetRGB(type,mface,mmcol,mat,rgb[0],rgb[1],rgb[2], rgb[3]); - - // swap the material color, so MCol on bitmap font works - if (validmat && type==1 && (mat->game.flag & GEMAT_TEXT)) - { - rgb[0] = KX_rgbaint2uint_new(rgb[0]); - rgb[1] = KX_rgbaint2uint_new(rgb[1]); - rgb[2] = KX_rgbaint2uint_new(rgb[2]); - rgb[3] = KX_rgbaint2uint_new(rgb[3]); + if (validmat && mmcol) { /* color is only for text */ + material->m_mcol = *(unsigned int *)mmcol; } - - material->SetConversionRGB(rgb); - material->SetConversionUV(uvName, uv); - material->SetConversionUV2(uv2Name, uv2); + material->SetUVLayerName(uvName); + material->SetUVLayerName2(uv2Name); if (validmat) material->matname =(mat->id.name); @@ -928,6 +910,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, // Extract avaiable layers MTF_localLayer *layers = new MTF_localLayer[MAX_MTFACE]; + int layer_uv[2]; /* store uv1, uv2 layers */ for (int lay=0; layGetMaterials()) { + const bool is_bl_mat_new = (bl_mat == NULL); + //const bool is_kx_blmat_new = (kx_blmat == NULL); + const bool glslmat = converter->GetGLSLMaterials(); + const bool use_mcol = ma ? (ma->mode & MA_VERTEXCOLP || glslmat) : true; /* do Blender Multitexture and Blender GLSL materials */ - unsigned int rgb[4]; - MT_Point2 uv[4]; + MT_Point2 uv_1[4]; + MT_Point2 uv_2[4]; /* first is the BL_Material */ - if (!bl_mat) + if (!bl_mat) { bl_mat = new BL_Material(); - ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol, - layers, converter->GetGLSLMaterials()); + } - /* vertex colors and uv's were stored in bl_mat temporarily */ - bl_mat->GetConversionRGB(rgb); - rgb0 = rgb[0]; rgb1 = rgb[1]; - rgb2 = rgb[2]; rgb3 = rgb[3]; + /* only */ + if (is_bl_mat_new || (bl_mat->material != ma)) { + ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol, + layers, layer_uv, glslmat); + } - bl_mat->GetConversionUV(uv); - uv0 = uv[0]; uv1 = uv[1]; - uv2 = uv[2]; uv3 = uv[3]; + /* vertex colors and uv's from the faces */ + GetRGB(use_mcol, mface, mcol, ma, rgb0, rgb1, rgb2, rgb3); + GetUV(mface, tface, layers, layer_uv, uv_1, uv_2); - bl_mat->GetConversionUV2(uv); - uv20 = uv[0]; uv21 = uv[1]; - uv22 = uv[2]; uv23 = uv[3]; + uv0 = uv_1[0]; uv1 = uv_1[1]; + uv2 = uv_1[2]; uv3 = uv_1[3]; + + uv20 = uv_2[0]; uv21 = uv_2[1]; + uv22 = uv_2[2]; uv23 = uv_2[3]; /* then the KX_BlenderMaterial */ if (kx_blmat == NULL) kx_blmat = new KX_BlenderMaterial(); - kx_blmat->Initialize(scene, bl_mat, (ma?&ma->game:NULL)); + //if (is_kx_blmat_new || !kx_blmat->IsMaterial(bl_mat)) { + kx_blmat->Initialize(scene, bl_mat, (ma ? &ma->game : NULL)); + //} + polymat = static_cast(kx_blmat); } else { diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 30a4209965e..d1684db0f5a 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -103,6 +103,7 @@ extern "C" #include "KX_MeshProxy.h" #include "RAS_MeshObject.h" extern "C" { + #include "PIL_time.h" #include "BKE_context.h" #include "BLO_readfile.h" #include "BKE_idcode.h" @@ -957,10 +958,12 @@ static void load_datablocks(Main *main_newlib, BlendHandle *bpy_openlib, const c bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options) { Main *main_newlib; /* stored as a dynamic 'main' until we free it */ - int idcode= BKE_idcode_from_name(group); + const int idcode = BKE_idcode_from_name(group); ReportList reports; static char err_local[255]; - + +// TIMEIT_START(bge_link_blend_file); + /* only scene and mesh supported right now */ if (idcode!=ID_SCE && idcode!=ID_ME &&idcode!=ID_AC) { snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group); @@ -1059,7 +1062,9 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha } } } - + +// TIMEIT_END(bge_link_blend_file); + return true; } diff --git a/source/gameengine/Converter/SConscript b/source/gameengine/Converter/SConscript index bfd44dc90fc..b9c70910283 100644 --- a/source/gameengine/Converter/SConscript +++ b/source/gameengine/Converter/SConscript @@ -11,7 +11,7 @@ incs += ' #source/gameengine/BlenderRoutines #source/blender/imbuf' incs += ' #intern/moto/include #source/gameengine/Ketsji #source/gameengine/Ketsji/KXNetwork' incs += ' #source/blender/blenlib #source/blender/blenkernel #source/blender' incs += ' #source/blender/editors/include #source/blender/makesdna #source/gameengine/Rasterizer' -incs += ' #source/gameengine/Rasterizer/RAS_OpenGLRasterizer #source/gameengine/GameLogic' +incs += ' #source/gameengine/GameLogic' incs += ' #source/gameengine/Expressions #source/gameengine/Network #source/gameengine/SceneGraph' incs += ' #source/gameengine/Physics/common #source/gameengine/Physics/Bullet' incs += ' #source/gameengine/Physics/Dummy' diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/IntValue.cpp index cb6bc556bab..2cacea98467 100644 --- a/source/gameengine/Expressions/IntValue.cpp +++ b/source/gameengine/Expressions/IntValue.cpp @@ -286,7 +286,7 @@ cInt CIntValue::GetInt() double CIntValue::GetNumber() { - return (float) m_int; + return (double) m_int; } @@ -323,9 +323,6 @@ void CIntValue::SetValue(CValue* newval) #ifdef WITH_PYTHON PyObject *CIntValue::ConvertValueToPython() { - if ((m_int > INT_MIN) && (m_int < INT_MAX)) - return PyLong_FromSsize_t(m_int); - else - return PyLong_FromLongLong(m_int); + return PyLong_FromLongLong(m_int); } #endif // WITH_PYTHON diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp index 8cff5a01c0e..5f97b03fed4 100644 --- a/source/gameengine/Expressions/ListValue.cpp +++ b/source/gameengine/Expressions/ListValue.cpp @@ -365,7 +365,7 @@ static PyObject *listvalue_mapping_subscript(PyObject *self, PyObject *key) } } else if (PyIndex_Check(key)) { - int index = PyLong_AsSsize_t(key); + Py_ssize_t index = PyLong_AsSsize_t(key); return listvalue_buffer_item(self, index); /* wont add a ref */ } else if (PySlice_Check(key)) { @@ -602,10 +602,10 @@ PyObject *CListValue::Pyindex(PyObject *value) int numelem = GetCount(); for (int i=0;iRelease(); - return PyLong_FromSsize_t(numfound); + return PyLong_FromLong(numfound); } /* Matches python dict.get(key, [default]) */ diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index bb1d0a31c1f..11b00b7bbf5 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -259,7 +259,7 @@ void PyObjectPlus::py_base_dealloc(PyObject *self) // python wrapper * PyObjectPlus Methods -- Every class, even the abstract one should have a Methods ------------------------------*/ PyMethodDef PyObjectPlus::Methods[] = { - {NULL, NULL} /* Sentinel */ + {NULL, NULL} /* Sentinel */ }; #define BGE_PY_ATTR_INVALID (&(PyObjectPlus::Attributes[0])) @@ -311,14 +311,14 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * { bool *val = reinterpret_cast(ptr); ptr += sizeof(bool); - PyList_SET_ITEM(resultlist,i,PyLong_FromSsize_t(*val)); + PyList_SET_ITEM(resultlist,i,PyBool_FromLong(*val)); break; } case KX_PYATTRIBUTE_TYPE_SHORT: { short int *val = reinterpret_cast(ptr); ptr += sizeof(short int); - PyList_SET_ITEM(resultlist,i,PyLong_FromSsize_t(*val)); + PyList_SET_ITEM(resultlist,i,PyLong_FromLong(*val)); break; } case KX_PYATTRIBUTE_TYPE_ENUM: @@ -333,7 +333,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * { int *val = reinterpret_cast(ptr); ptr += sizeof(int); - PyList_SET_ITEM(resultlist,i,PyLong_FromSsize_t(*val)); + PyList_SET_ITEM(resultlist,i,PyLong_FromLong(*val)); break; } case KX_PYATTRIBUTE_TYPE_FLOAT: @@ -381,17 +381,17 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * } if (attrdef->m_imax) bval = !bval; - return PyLong_FromSsize_t(bval); + return PyBool_FromLong(bval); } case KX_PYATTRIBUTE_TYPE_BOOL: { bool *val = reinterpret_cast(ptr); - return PyLong_FromSsize_t(*val); + return PyBool_FromLong(*val); } case KX_PYATTRIBUTE_TYPE_SHORT: { short int *val = reinterpret_cast(ptr); - return PyLong_FromSsize_t(*val); + return PyLong_FromLong(*val); } case KX_PYATTRIBUTE_TYPE_ENUM: // enum are like int, just make sure the field size is the same @@ -403,7 +403,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * case KX_PYATTRIBUTE_TYPE_INT: { int *val = reinterpret_cast(ptr); - return PyLong_FromSsize_t(*val); + return PyLong_FromLong(*val); } case KX_PYATTRIBUTE_TYPE_FLOAT: { @@ -486,8 +486,8 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * static bool py_check_attr_float(float *var, PyObject *value, const PyAttributeDef *attrdef) { - double val = PyFloat_AsDouble(value); - if (val == -1.0 && PyErr_Occurred()) + float val = PyFloat_AsDouble(value); + if (val == -1.0f && PyErr_Occurred()) { PyErr_Format(PyExc_TypeError, "expected float value for attribute \"%s\"", attrdef->m_name); return false; @@ -583,7 +583,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt ptr += sizeof(bool); if (PyLong_Check(item)) { - *var = (PyLong_AsSsize_t(item) != 0); + *var = (PyLong_AsLong(item) != 0); } else if (PyBool_Check(item)) { @@ -602,7 +602,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt ptr += sizeof(short int); if (PyLong_Check(item)) { - long val = PyLong_AsSsize_t(item); + int val = PyLong_AsLong(item); if (attrdef->m_clamp) { if (val < attrdef->m_imin) @@ -638,7 +638,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt ptr += sizeof(int); if (PyLong_Check(item)) { - long val = PyLong_AsSsize_t(item); + int val = PyLong_AsLong(item); if (attrdef->m_clamp) { if (val < attrdef->m_imin) @@ -664,13 +664,13 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt { float *var = reinterpret_cast(ptr); ptr += sizeof(float); - double val = PyFloat_AsDouble(item); - if (val == -1.0 && PyErr_Occurred()) + float val = PyFloat_AsDouble(item); + if (val == -1.0f && PyErr_Occurred()) { PyErr_Format(PyExc_TypeError, "expected a float for attribute \"%s\"", attrdef->m_name); goto UNDO_AND_ERROR; } - else if (attrdef->m_clamp) + else if (attrdef->m_clamp) { if (val < attrdef->m_fmin) val = attrdef->m_fmin; @@ -786,7 +786,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt bool *var = reinterpret_cast(ptr); if (PyLong_Check(value)) { - *var = (PyLong_AsSsize_t(value) != 0); + *var = (PyLong_AsLong(value) != 0); } else if (PyBool_Check(value)) { @@ -804,7 +804,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt bool bval; if (PyLong_Check(value)) { - bval = (PyLong_AsSsize_t(value) != 0); + bval = (PyLong_AsLong(value) != 0); } else if (PyBool_Check(value)) { @@ -847,7 +847,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt short int *var = reinterpret_cast(ptr); if (PyLong_Check(value)) { - long val = PyLong_AsSsize_t(value); + int val = PyLong_AsLong(value); if (attrdef->m_clamp) { if (val < attrdef->m_imin) @@ -882,7 +882,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt int *var = reinterpret_cast(ptr); if (PyLong_Check(value)) { - long val = PyLong_AsSsize_t(value); + int val = PyLong_AsLong(value); if (attrdef->m_clamp) { if (val < attrdef->m_imin) @@ -985,10 +985,10 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt for (int i=0; i<3; i++) { item = PySequence_GetItem(value, i); /* new ref */ - double val = PyFloat_AsDouble(item); + float val = PyFloat_AsDouble(item); Py_DECREF(item); item = NULL; - if (val == -1.0 && PyErr_Occurred()) + if (val == -1.0f && PyErr_Occurred()) { PyErr_Format(PyExc_TypeError, "expected a sequence of 3 floats for attribute \"%s\"", attrdef->m_name); goto RESTORE_AND_ERROR; diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 83b7c8c8771..37e26e88750 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -526,7 +526,7 @@ typedef struct KX_PYATTRIBUTE_DEF { /*------------------------------ * PyObjectPlus -------------------------------*/ + *------------------------------ */ typedef PyTypeObject *PyParentObject; /* Define the PyParent Object */ #else // WITH_PYTHON diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp index 57f7dd64287..f922e617367 100644 --- a/source/gameengine/GameLogic/SCA_IController.cpp +++ b/source/gameengine/GameLogic/SCA_IController.cpp @@ -241,7 +241,7 @@ PyAttributeDef SCA_IController::Attributes[] = { PyObject *SCA_IController::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_IController* self = static_cast(self_v); - return PyLong_FromSsize_t(self->m_statemask); + return PyLong_FromLong(self->m_statemask); } PyObject *SCA_IController::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index ab0e6c5edcb..34fa1c98a73 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -202,7 +202,7 @@ PyTypeObject SCA_ILogicBrick::Type = { }; PyMethodDef SCA_ILogicBrick::Methods[] = { - {NULL,NULL} //Sentinel + {NULL,NULL} //Sentinel }; PyAttributeDef SCA_ILogicBrick::Attributes[] = { @@ -256,7 +256,7 @@ bool SCA_ILogicBrick::PyArgToBool(int boolArg) PyObject *SCA_ILogicBrick::BoolToPyArg(bool boolarg) { - return PyLong_FromSsize_t(boolarg? KX_TRUE: KX_FALSE); + return PyLong_FromLong(boolarg ? KX_TRUE: KX_FALSE); } #endif // WITH_PYTHON diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index bfb78abef04..1cb17af8325 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -383,16 +383,16 @@ PyAttributeDef SCA_ISensor::Attributes[] = { PyObject *SCA_ISensor::pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_ISensor* self = static_cast(self_v); - int retval = 0; + bool retval = false; if (SCA_PythonController::m_sCurrentController) retval = SCA_PythonController::m_sCurrentController->IsTriggered(self); - return PyLong_FromSsize_t(retval); + return PyBool_FromLong(retval); } PyObject *SCA_ISensor::pyattr_get_positive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_ISensor* self = static_cast(self_v); - return PyLong_FromSsize_t(self->GetState()); + return PyBool_FromLong(self->GetState()); } PyObject *SCA_ISensor::pyattr_get_status(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -414,7 +414,7 @@ PyObject *SCA_ISensor::pyattr_get_status(void *self_v, const KX_PYATTRIBUTE_DEF { status = 3; } - return PyLong_FromSsize_t(status); + return PyLong_FromLong(status); } PyObject *SCA_ISensor::pyattr_get_posTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index 0c4dcae16f7..c7e31f75306 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -319,7 +319,7 @@ PyObject *SCA_JoystickSensor::PyGetButtonActiveList( ) if (joy) { for (i=0; i < joy->GetNumberOfButtons(); i++) { if (joy->aButtonPressIsPositive(i)) { - value = PyLong_FromSsize_t(i); + value = PyLong_FromLong(i); PyList_Append(ls, value); Py_DECREF(value); } @@ -355,7 +355,7 @@ PyObject *SCA_JoystickSensor::pyattr_get_axis_values(void *self_v, const KX_PYAT PyObject *list= PyList_New(axis_index); while (axis_index--) { - PyList_SET_ITEM(list, axis_index, PyLong_FromSsize_t(joy->GetAxisPosition(axis_index))); + PyList_SET_ITEM(list, axis_index, PyLong_FromLong(joy->GetAxisPosition(axis_index))); } return list; @@ -371,7 +371,7 @@ PyObject *SCA_JoystickSensor::pyattr_get_axis_single(void *self_v, const KX_PYAT return NULL; } - return PyLong_FromSsize_t(joy->GetAxisPosition(self->m_axis-1)); + return PyLong_FromLong(joy->GetAxisPosition(self->m_axis-1)); } PyObject *SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -383,7 +383,7 @@ PyObject *SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATT PyObject *list= PyList_New(hat_index); while (hat_index--) { - PyList_SET_ITEM(list, hat_index, PyLong_FromSsize_t(joy->GetHat(hat_index))); + PyList_SET_ITEM(list, hat_index, PyLong_FromLong(joy->GetHat(hat_index))); } return list; @@ -394,28 +394,28 @@ PyObject *SCA_JoystickSensor::pyattr_get_hat_single(void *self_v, const KX_PYATT SCA_JoystickSensor* self = static_cast(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); - return PyLong_FromSsize_t(joy->GetHat(self->m_hat-1)); + return PyLong_FromLong(joy->GetHat(self->m_hat-1)); } PyObject *SCA_JoystickSensor::pyattr_get_num_axis(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_JoystickSensor* self = static_cast(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); - return PyLong_FromSsize_t( joy ? joy->GetNumberOfAxes() : 0 ); + return PyLong_FromLong( joy ? joy->GetNumberOfAxes() : 0 ); } PyObject *SCA_JoystickSensor::pyattr_get_num_buttons(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_JoystickSensor* self = static_cast(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); - return PyLong_FromSsize_t( joy ? joy->GetNumberOfButtons() : 0 ); + return PyLong_FromLong( joy ? joy->GetNumberOfButtons() : 0 ); } PyObject *SCA_JoystickSensor::pyattr_get_num_hats(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_JoystickSensor* self = static_cast(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); - return PyLong_FromSsize_t( joy ? joy->GetNumberOfHats() : 0 ); + return PyLong_FromLong( joy ? joy->GetNumberOfHats() : 0 ); } PyObject *SCA_JoystickSensor::pyattr_get_connected(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index b3346270b61..7005ea1ba5b 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -439,17 +439,18 @@ KX_PYMETHODDEF_DOC_O(SCA_KeyboardSensor, getKeyStatus, return NULL; } - int keycode = PyLong_AsSsize_t(value); + SCA_IInputDevice::KX_EnumInputs keycode = (SCA_IInputDevice::KX_EnumInputs)PyLong_AsLong(value); - if ((keycode < SCA_IInputDevice::KX_BEGINKEY) - || (keycode > SCA_IInputDevice::KX_ENDKEY)) { + if ((keycode < SCA_IInputDevice::KX_BEGINKEY) || + (keycode > SCA_IInputDevice::KX_ENDKEY)) + { PyErr_SetString(PyExc_AttributeError, "sensor.getKeyStatus(int): Keyboard Sensor, invalid keycode specified!"); return NULL; } SCA_IInputDevice* inputdev = ((SCA_KeyboardManager *)m_eventmgr)->GetInputDevice(); - const SCA_InputEvent & inevent = inputdev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) keycode); - return PyLong_FromSsize_t(inevent.m_status); + const SCA_InputEvent & inevent = inputdev->GetEventValue(keycode); + return PyLong_FromLong(inevent.m_status); } /* ------------------------------------------------------------------------- */ @@ -509,8 +510,8 @@ PyObject *SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBU if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) { PyObject *keypair = PyList_New(2); - PyList_SET_ITEM(keypair,0,PyLong_FromSsize_t(i)); - PyList_SET_ITEM(keypair,1,PyLong_FromSsize_t(inevent.m_status)); + PyList_SET_ITEM(keypair,0,PyLong_FromLong(i)); + PyList_SET_ITEM(keypair,1,PyLong_FromLong(inevent.m_status)); PyList_Append(resultlist,keypair); } } diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index 51e0bc6550b..a7cf4963f04 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -250,17 +250,18 @@ KX_PYMETHODDEF_DOC_O(SCA_MouseSensor, getButtonStatus, { if (PyLong_Check(value)) { - int button = PyLong_AsSsize_t(value); + SCA_IInputDevice::KX_EnumInputs button = (SCA_IInputDevice::KX_EnumInputs)PyLong_AsLong(value); - if ((button < SCA_IInputDevice::KX_LEFTMOUSE) - || (button > SCA_IInputDevice::KX_RIGHTMOUSE)) { + if ((button < SCA_IInputDevice::KX_LEFTMOUSE) || + (button > SCA_IInputDevice::KX_RIGHTMOUSE)) + { PyErr_SetString(PyExc_ValueError, "sensor.getButtonStatus(int): Mouse Sensor, invalid button specified!"); return NULL; } SCA_IInputDevice* mousedev = ((SCA_MouseManager *)m_eventmgr)->GetInputDevice(); - const SCA_InputEvent& event = mousedev->GetEventValue((SCA_IInputDevice::KX_EnumInputs) button); - return PyLong_FromSsize_t(event.m_status); + const SCA_InputEvent& event = mousedev->GetEventValue(button); + return PyLong_FromLong(event.m_status); } Py_RETURN_NONE; diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp index 5dd4cc501ca..f02ac495233 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp +++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp @@ -126,7 +126,6 @@ bool SCA_PropertySensor::Evaluate() bool SCA_PropertySensor::CheckPropertyCondition() { - m_recentresult=false; bool result=false; bool reverse = false; @@ -153,13 +152,11 @@ bool SCA_PropertySensor::CheckPropertyCondition() */ if (result==false && dynamic_cast(orgprop) != NULL) { float f; - - if (EOF == sscanf(m_checkpropval.ReadPtr(), "%f", &f)) - { - //error + if (sscanf(m_checkpropval.ReadPtr(), "%f", &f) == 1) { + result = (f == ((CFloatValue *)orgprop)->GetFloat()); } else { - result = (f == ((CFloatValue *)orgprop)->GetFloat()); + /* error */ } } /* end patch */ @@ -174,7 +171,7 @@ bool SCA_PropertySensor::CheckPropertyCondition() case KX_PROPSENSOR_EXPRESSION: { - /* +#if 0 if (m_rightexpr) { CValue* resultval = m_rightexpr->Calculate(); @@ -189,7 +186,7 @@ bool SCA_PropertySensor::CheckPropertyCondition() result = resultval->GetNumber() != 0; } } - */ +#endif break; } case KX_PROPSENSOR_INTERVAL: @@ -197,7 +194,16 @@ bool SCA_PropertySensor::CheckPropertyCondition() CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname); if (!orgprop->IsError()) { - float val = orgprop->GetText().ToFloat(), min = m_checkpropval.ToFloat(), max = m_checkpropmaxval.ToFloat(); + const float min = m_checkpropval.ToFloat(); + const float max = m_checkpropmaxval.ToFloat(); + float val; + + if (dynamic_cast(orgprop) == NULL) { + val = orgprop->GetNumber(); + } + else { + val = orgprop->GetText().ToFloat(); + } result = (min <= val) && (val <= max); } diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index ece9d7b6c8f..c2b1470ae7a 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -168,12 +168,16 @@ void SCA_PythonController::SetNamespace(PyObject* pythondictionary) } #endif -int SCA_PythonController::IsTriggered(class SCA_ISensor* sensor) +bool SCA_PythonController::IsTriggered(class SCA_ISensor* sensor) { if (std::find(m_triggeredSensors.begin(), m_triggeredSensors.end(), sensor) != m_triggeredSensors.end()) - return 1; - return 0; + { + return true; + } + else { + return false; + } } #ifdef WITH_PYTHON diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h index f1f10d22711..d2549318c2e 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.h +++ b/source/gameengine/GameLogic/SCA_PythonController.h @@ -90,7 +90,7 @@ class SCA_PythonController : public SCA_IController void SetDebug(bool debug) { m_debug = debug; } void AddTriggeredSensor(class SCA_ISensor* sensor) { m_triggeredSensors.push_back(sensor); } - int IsTriggered(class SCA_ISensor* sensor); + bool IsTriggered(class SCA_ISensor* sensor); bool Compile(); bool Import(); void ErrorPrint(const char *error_msg); diff --git a/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp b/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp index 42cda9433b8..19aae46f2a3 100644 --- a/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp +++ b/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp @@ -117,7 +117,7 @@ PyObject *SCA_PythonKeyboard::pyattr_get_events(void *self_v, const KX_PYATTRIBU { const SCA_InputEvent & inevent = self->m_keyboard->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i); - PyDict_SetItem(self->m_event_dict, PyLong_FromSsize_t(i), PyLong_FromSsize_t(inevent.m_status)); + PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status)); } Py_INCREF(self->m_event_dict); return self->m_event_dict; @@ -134,7 +134,7 @@ PyObject *SCA_PythonKeyboard::pyattr_get_active_events(void *self_v, const KX_PY const SCA_InputEvent & inevent = self->m_keyboard->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i); if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) - PyDict_SetItem(self->m_event_dict, PyLong_FromSsize_t(i), PyLong_FromSsize_t(inevent.m_status)); + PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status)); } Py_INCREF(self->m_event_dict); return self->m_event_dict; diff --git a/source/gameengine/GameLogic/SCA_PythonMouse.cpp b/source/gameengine/GameLogic/SCA_PythonMouse.cpp index 0806bda072b..1617f714113 100644 --- a/source/gameengine/GameLogic/SCA_PythonMouse.cpp +++ b/source/gameengine/GameLogic/SCA_PythonMouse.cpp @@ -100,7 +100,7 @@ PyObject *SCA_PythonMouse::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_ { const SCA_InputEvent & inevent = self->m_mouse->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i); - PyDict_SetItem(self->m_event_dict, PyLong_FromSsize_t(i), PyLong_FromSsize_t(inevent.m_status)); + PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status)); } Py_INCREF(self->m_event_dict); return self->m_event_dict; @@ -117,7 +117,7 @@ PyObject *SCA_PythonMouse::pyattr_get_active_events(void *self_v, const KX_PYATT const SCA_InputEvent & inevent = self->m_mouse->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i); if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) - PyDict_SetItem(self->m_event_dict, PyLong_FromSsize_t(i), PyLong_FromSsize_t(inevent.m_status)); + PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status)); } Py_INCREF(self->m_event_dict); return self->m_event_dict; diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp index 2d51a45fe55..5568072abcf 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp @@ -220,11 +220,11 @@ bool SCA_RandomActuator::Update() * this will be quite sufficient here. */ do { - x = 2.0 * m_base->DrawFloat() - 1.0; - y = 2.0 * m_base->DrawFloat() - 1.0; - s = x*x + y*y; - } while ( (s >= 1.0) || (s == 0.0) ); - t = x * sqrt( (-2.0 * log(s)) / s); + x = 2.0f * m_base->DrawFloat() - 1.0f; + y = 2.0f * m_base->DrawFloat() - 1.0f; + s = x * x + y * y; + } while ((s >= 1.0f) || (s == 0.0f)); + t = x * sqrtf((-2.0 * log(s)) / s); tmpval = new CFloatValue(m_parameter1 + m_parameter2 * t); } } @@ -363,17 +363,17 @@ PyAttributeDef SCA_RandomActuator::Attributes[] = { PyObject *SCA_RandomActuator::pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { SCA_RandomActuator* act = static_cast(self); - return PyLong_FromSsize_t(act->m_base->GetSeed()); + return PyLong_FromLong(act->m_base->GetSeed()); } int SCA_RandomActuator::pyattr_set_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { SCA_RandomActuator* act = static_cast(self); - if (PyLong_Check(value)) { - int ival = PyLong_AsSsize_t(value); - act->m_base->SetSeed(ival); + if (PyLong_Check(value)) { + act->m_base->SetSeed(PyLong_AsLong(value)); return PY_SET_ATTR_SUCCESS; - } else { + } + else { PyErr_SetString(PyExc_TypeError, "actuator.seed = int: Random Actuator, expected an integer"); return PY_SET_ATTR_FAIL; } diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp index 7199ee6cf22..4e93556453a 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp +++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp @@ -168,7 +168,7 @@ PyAttributeDef SCA_RandomSensor::Attributes[] = { PyObject *SCA_RandomSensor::pyattr_get_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_RandomSensor* self = static_cast(self_v); - return PyLong_FromSsize_t(self->m_basegenerator->GetSeed()); + return PyLong_FromLong(self->m_basegenerator->GetSeed()); } int SCA_RandomSensor::pyattr_set_seed(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -178,7 +178,7 @@ int SCA_RandomSensor::pyattr_set_seed(void *self_v, const KX_PYATTRIBUTE_DEF *at PyErr_SetString(PyExc_TypeError, "sensor.seed = int: Random Sensor, expected an integer"); return PY_SET_ATTR_FAIL; } - self->m_basegenerator->SetSeed(PyLong_AsSsize_t(value)); + self->m_basegenerator->SetSeed(PyLong_AsLong(value)); return PY_SET_ATTR_SUCCESS; } diff --git a/source/gameengine/GamePlayer/common/SConscript b/source/gameengine/GamePlayer/common/SConscript index d5e1f081d21..6a1f47c51af 100644 --- a/source/gameengine/GamePlayer/common/SConscript +++ b/source/gameengine/GamePlayer/common/SConscript @@ -31,7 +31,6 @@ incs = ['.', '#source/blender', '#source/blender/include', '#source/blender/makesdna', - '#source/gameengine/BlenderRoutines', '#source/gameengine/Rasterizer', '#source/gameengine/GameLogic', '#source/gameengine/Expressions', diff --git a/source/gameengine/GamePlayer/common/bmfont.cpp b/source/gameengine/GamePlayer/common/bmfont.cpp index fe6f2187138..8ffbe757222 100644 --- a/source/gameengine/GamePlayer/common/bmfont.cpp +++ b/source/gameengine/GamePlayer/common/bmfont.cpp @@ -73,9 +73,6 @@ void printfGlyph(bmGlyph * glyph) } */ -#define MAX2(x,y) ( (x)>(y) ? (x) : (y) ) -#define MAX3(x,y,z) MAX2( MAX2((x),(y)) , (z) ) - void calcAlpha(ImBuf * ibuf) { int i; diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index 40b52c3212a..92db1fe790e 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -555,7 +555,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) bool showPhysics = (gm->flag & GAME_SHOW_PHYSICS); SYS_WriteCommandLineInt(syshandle, "show_physics", showPhysics); - bool fixed_framerate= (SYS_GetCommandLineInt(syshandle, "fixed_framerate", fixedFr) != 0); + bool fixed_framerate= (SYS_GetCommandLineInt(syshandle, "fixedtime", fixedFr) != 0); bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0); bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", gm->flag & GAME_DISPLAY_LISTS) != 0); bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 1) != 0); diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 725c23c60e3..a82f9ce1779 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -60,6 +60,7 @@ extern "C" #include "BKE_blender.h" #include "BKE_global.h" #include "BKE_icons.h" +#include "BKE_image.h" #include "BKE_node.h" #include "BKE_report.h" #include "BKE_library.h" @@ -172,7 +173,7 @@ static BOOL scr_saver_init(int argc, char **argv) #endif /* WIN32 */ -void usage(const char* program, bool isBlenderPlayer) +static void usage(const char* program, bool isBlenderPlayer) { const char * consoleoption; const char * example_filename = ""; @@ -332,7 +333,7 @@ static BlendFileData *load_game_data(const char *progname, char *filename = NULL return bfd; } -bool GPG_NextFrame(GHOST_ISystem* system, GPG_Application *app, int &exitcode, STR_String &exitstring, GlobalSettings *gs) +static bool GPG_NextFrame(GHOST_ISystem* system, GPG_Application *app, int &exitcode, STR_String &exitstring, GlobalSettings *gs) { bool run = true; system->processEvents(false); @@ -352,7 +353,7 @@ struct GPG_NextFrameState { GlobalSettings *gs; } gpg_nextframestate; -int GPG_PyNextFrame(void *state0) +static int GPG_PyNextFrame(void *state0) { GPG_NextFrameState *state = (GPG_NextFrameState *) state0; int exitcode; @@ -446,11 +447,11 @@ int main(int argc, char** argv) G.main = NULL; IMB_init(); + BKE_images_init(); // Setup builtin font for BLF (mostly copied from creator.c, wm_init_exit.c and interface_style.c) BLF_init(11, U.dpi); BLF_lang_init(); - BLF_lang_encoding(""); BLF_lang_set(""); BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size); @@ -755,6 +756,7 @@ int main(int argc, char** argv) } GPU_set_anisotropic(U.anisotropic_filter); + GPU_set_gpu_mipmapping(U.use_gpu_mipmap); // Create the system if (GHOST_ISystem::createSystem() == GHOST_kSuccess) @@ -1068,6 +1070,7 @@ int main(int argc, char** argv) #endif IMB_exit(); + BKE_images_exit(); free_nodesystem(); SYS_DeleteSystem(syshandle); diff --git a/source/gameengine/GamePlayer/ghost/SConscript b/source/gameengine/GamePlayer/ghost/SConscript index 9fb0f053ed8..fb046d0fdf8 100644 --- a/source/gameengine/GamePlayer/ghost/SConscript +++ b/source/gameengine/GamePlayer/ghost/SConscript @@ -26,7 +26,6 @@ incs = ['.', '#source/blender/include', '#source/blender/makesdna', '#source/blender/makesrna', - '#source/gameengine/BlenderRoutines', '#source/gameengine/Rasterizer', '#source/gameengine/GameLogic', '#source/gameengine/Expressions', diff --git a/source/gameengine/Ketsji/BL_Material.cpp b/source/gameengine/Ketsji/BL_Material.cpp index 4c7518769e1..0954aa0f7ab 100644 --- a/source/gameengine/Ketsji/BL_Material.cpp +++ b/source/gameengine/Ketsji/BL_Material.cpp @@ -36,10 +36,7 @@ BL_Material::BL_Material() void BL_Material::Initialize() { - rgb[0] = 0; - rgb[1] = 0; - rgb[2] = 0; - rgb[3] = 0; + m_mcol = 0xFFFFFFFFL; IdMode = 0; ras_mode = 0; glslmat = 0; @@ -66,11 +63,6 @@ void BL_Material::Initialize() share = false; int i; - for (i=0; i<4; i++) - { - uv[i] = MT_Point2(0.f,1.f); - uv2[i] = MT_Point2(0.f, 1.f); - } for (i=0; i 1 ) diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h index b67bd95f878..ef180ed2126 100644 --- a/source/gameengine/Ketsji/BL_Material.h +++ b/source/gameengine/Ketsji/BL_Material.h @@ -87,22 +87,13 @@ public: MTFace tface; /* copy of the derived meshes tface */ Image* img[MAXTEX]; EnvMap* cubemap[MAXTEX]; - - unsigned int rgb[4]; - MT_Point2 uv[4]; - MT_Point2 uv2[4]; + unsigned int m_mcol; /* for text color (only) */ STR_String uvName; STR_String uv2Name; - void SetConversionRGB(unsigned int *rgb); - void GetConversionRGB(unsigned int *rgb); - - void SetConversionUV(const STR_String& name, MT_Point2 *uv); - void GetConversionUV(MT_Point2 *uv); - - void SetConversionUV2(const STR_String& name, MT_Point2 *uv); - void GetConversionUV2(MT_Point2 *uv); + void SetUVLayerName(const STR_String &name); + void SetUVLayerName2(const STR_String &name); void SetSharedMaterial(bool v); bool IsShared(); diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index fb8e7beb157..4a74024b5bb 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -571,41 +571,39 @@ void BL_Shader::Update( const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) } -int BL_Shader::GetAttribLocation(const STR_String& name) +int BL_Shader::GetAttribLocation(const char *name) { - if ( GLEW_ARB_fragment_shader && - GLEW_ARB_vertex_shader && - GLEW_ARB_shader_objects - ) + if (GLEW_ARB_fragment_shader && + GLEW_ARB_vertex_shader && + GLEW_ARB_shader_objects) { - return glGetAttribLocationARB(mShader, name.ReadPtr()); + return glGetAttribLocationARB(mShader, name); } return -1; } -void BL_Shader::BindAttribute(const STR_String& attr, int loc) +void BL_Shader::BindAttribute(const char *attr, int loc) { - if ( GLEW_ARB_fragment_shader && - GLEW_ARB_vertex_shader && - GLEW_ARB_shader_objects - ) + if (GLEW_ARB_fragment_shader && + GLEW_ARB_vertex_shader && + GLEW_ARB_shader_objects ) { - glBindAttribLocationARB(mShader, loc, attr.ReadPtr()); + glBindAttribLocationARB(mShader, loc, attr); } } -int BL_Shader::GetUniformLocation(const STR_String& name) +int BL_Shader::GetUniformLocation(const char *name) { if ( GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && - GLEW_ARB_shader_objects + GLEW_ARB_shader_objects ) { MT_assert(mShader!=0); - int location = glGetUniformLocationARB(mShader, name.ReadPtr()); + int location = glGetUniformLocationARB(mShader, name); if (location == -1) - spit("Invalid uniform value: " << name.ReadPtr() << "."); + spit("Invalid uniform value: " << name << "."); return location; } @@ -851,7 +849,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, delSource, "delSource( )" ) KX_PYMETHODDEF_DOC( BL_Shader, isValid, "isValid()" ) { - return PyLong_FromSsize_t( ( mShader !=0 && mOk ) ); + return PyBool_FromLong(( mShader !=0 && mOk )); } KX_PYMETHODDEF_DOC( BL_Shader, getVertexProg, "getVertexProg( )" ) @@ -900,7 +898,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" ) Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; int index=-1; if (PyArg_ParseTuple(args, "si:setSampler", &uniform, &index)) { @@ -941,7 +939,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" ) Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; float value=0; if (PyArg_ParseTuple(args, "sf:setUniform1f", &uniform, &value )) { @@ -965,7 +963,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f, "setUniform2f(name, fx, fy)") if (mError) { Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; float array[2] = {0, 0}; if (PyArg_ParseTuple(args, "sff:setUniform2f", &uniform, &array[0],&array[1] )) { @@ -989,7 +987,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ") if (mError) { Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; float array[3] = {0, 0, 0}; if (PyArg_ParseTuple(args, "sfff:setUniform3f", &uniform, &array[0],&array[1],&array[2])) { @@ -1014,7 +1012,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) " if (mError) { Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; float array[4] = {0, 0, 0, 0}; if (PyArg_ParseTuple(args, "sffff:setUniform4f", &uniform, &array[0],&array[1],&array[2], &array[3])) { @@ -1038,7 +1036,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" ) if (mError) { Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; int value=0; if (PyArg_ParseTuple(args, "si:setUniform1i", &uniform, &value )) { @@ -1062,7 +1060,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i, "setUniform2i(name, ix, iy)") if (mError) { Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; int array[2] = {0, 0}; if (PyArg_ParseTuple(args, "sii:setUniform2i", &uniform, &array[0],&array[1] )) { @@ -1087,7 +1085,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ") Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; int array[3] = {0, 0, 0}; if (PyArg_ParseTuple(args, "siii:setUniform3i", &uniform, &array[0],&array[1],&array[2])) { @@ -1110,7 +1108,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) " if (mError) { Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; int array[4] = {0, 0, 0, 0}; if (PyArg_ParseTuple(args, "siiii:setUniform4i", &uniform, &array[0],&array[1],&array[2], &array[3] )) { @@ -1226,7 +1224,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( uniform_name, (list2 for (unsigned int i=0; (iok = 0; @@ -128,6 +128,7 @@ bool BL_Texture::InitFromImage(int unit, Image *img, bool mipmap) if (mTexture != 0) { glBindTexture(GL_TEXTURE_2D, mTexture ); Validate(); + BKE_image_release_ibuf(img, ibuf, NULL); return mOk; } @@ -140,6 +141,7 @@ bool BL_Texture::InitFromImage(int unit, Image *img, bool mipmap) mTexture = mapLook->second.gl_texture; glBindTexture(GL_TEXTURE_2D, mTexture); mOk = IsValid(); + BKE_image_release_ibuf(img, ibuf, NULL); return mOk; } } @@ -166,6 +168,9 @@ bool BL_Texture::InitFromImage(int unit, Image *img, bool mipmap) glDisable(GL_TEXTURE_2D); ActivateUnit(0); Validate(); + + BKE_image_release_ibuf(img, ibuf, NULL); + return mOk; } @@ -251,7 +256,7 @@ bool BL_Texture::InitCubeMap(int unit, EnvMap *cubemap) return mOk; } - ImBuf *ibuf= BKE_image_get_ibuf(cubemap->ima, NULL); + ImBuf *ibuf= BKE_image_acquire_ibuf(cubemap->ima, NULL, NULL); if (ibuf==0) { cubemap->ima->ok = 0; @@ -274,6 +279,7 @@ bool BL_Texture::InitCubeMap(int unit, EnvMap *cubemap) mTexture = mapLook->second.gl_texture; glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mTexture); mOk = IsValid(); + BKE_image_release_ibuf(cubemap->ima, ibuf, NULL); return mOk; } } @@ -307,6 +313,7 @@ bool BL_Texture::InitCubeMap(int unit, EnvMap *cubemap) my_free_envmapdata(cubemap); mOk = false; + BKE_image_release_ibuf(cubemap->ima, ibuf, NULL); return mOk; } @@ -341,6 +348,9 @@ bool BL_Texture::InitCubeMap(int unit, EnvMap *cubemap) ActivateUnit(0); mOk = IsValid(); + + BKE_image_release_ibuf(cubemap->ima, ibuf, NULL); + return mOk; } @@ -646,9 +656,11 @@ int BL_Texture::GetPow2(int n) void BL_Texture::SplitEnvMap(EnvMap *map) { if (!map || !map->ima || (map->ima && !map->ima->ok)) return; - ImBuf *ibuf= BKE_image_get_ibuf(map->ima, NULL); - if (ibuf) + ImBuf *ibuf= BKE_image_acquire_ibuf(map->ima, NULL, NULL); + if (ibuf) { my_envmap_split_ima(map, ibuf); + BKE_image_release_ibuf(map->ima, ibuf, NULL); + } } unsigned int BL_Texture::mDisableState = 0; diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt index 2eada3e5071..524a38a4c26 100644 --- a/source/gameengine/Ketsji/CMakeLists.txt +++ b/source/gameengine/Ketsji/CMakeLists.txt @@ -101,7 +101,6 @@ set(SRC KX_ObstacleSimulation.cpp KX_OrientationInterpolator.cpp KX_ParentActuator.cpp - KX_PhysicsObjectWrapper.cpp KX_PolyProxy.cpp KX_PolygonMaterial.cpp KX_PositionInterpolator.cpp @@ -184,7 +183,6 @@ set(SRC KX_OrientationInterpolator.h KX_ParentActuator.h KX_PhysicsEngineEnums.h - KX_PhysicsObjectWrapper.h KX_PhysicsPropertiesobsolete.h KX_PolyProxy.h KX_PolygonMaterial.h diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 2154beeb205..20c36c2cc44 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -124,7 +124,7 @@ MTFace* KX_BlenderMaterial::GetMTFace(void) const unsigned int* KX_BlenderMaterial::GetMCol(void) const { // fonts on polys - return mMaterial->rgb; + return &mMaterial->m_mcol; } void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const @@ -138,6 +138,11 @@ void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const RAS_IPolyMaterial::GetMaterialRGBAColor(rgba); } +bool KX_BlenderMaterial::IsMaterial(const BL_Material *bl_mat) const +{ + return (mMaterial == bl_mat); +} + Material *KX_BlenderMaterial::GetBlenderMaterial() const { return mMaterial->material; @@ -844,7 +849,7 @@ PyObject *KX_BlenderMaterial::pyattr_get_shader(void *self_v, const KX_PYATTRIBU PyObject *KX_BlenderMaterial::pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_BlenderMaterial* self = static_cast(self_v); - return PyLong_FromSsize_t(self->GetMaterialIndex()); + return PyLong_FromLong(self->GetMaterialIndex()); } PyObject *KX_BlenderMaterial::pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -926,7 +931,7 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()") { - return PyLong_FromSsize_t( GetMaterialIndex() ); + return PyLong_FromLong(GetMaterialIndex()); } KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getTexture, "getTexture( index )" ) diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index 1653669ebcc..7bc9c7c3863 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -76,6 +76,8 @@ public: TCachingInfo& cachingInfo )const; + /* mMaterial is private, but need this for conversion */ + bool IsMaterial(const BL_Material *bl_mat) const; Material* GetBlenderMaterial() const; MTFace* GetMTFace(void) const; unsigned int* GetMCol(void) const; diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index 39b0a24865e..e56dbfdcac8 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -593,7 +593,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, sphereInsideFrustum, MT_Point3 center; if (PyVecTo(pycenter, center)) { - return PyLong_FromSsize_t(SphereInsideFrustum(center, radius)); /* new ref */ + return PyLong_FromLong(SphereInsideFrustum(center, radius)); /* new ref */ } } @@ -644,7 +644,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, boxInsideFrustum, return NULL; } - return PyLong_FromSsize_t(BoxInsideFrustum(box)); /* new ref */ + return PyLong_FromLong(BoxInsideFrustum(box)); /* new ref */ } KX_PYMETHODDEF_DOC_O(KX_Camera, pointInsideFrustum, @@ -666,7 +666,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, pointInsideFrustum, MT_Point3 point; if (PyVecTo(value, point)) { - return PyLong_FromSsize_t(PointInsideFrustum(point)); /* new ref */ + return PyLong_FromLong(PointInsideFrustum(point)); /* new ref */ } PyErr_SetString(PyExc_TypeError, "camera.pointInsideFrustum(point): KX_Camera, expected point argument."); @@ -869,11 +869,11 @@ PyObject *KX_Camera::pyattr_get_world_to_camera(void *self_v, const KX_PYATTRIBU PyObject *KX_Camera::pyattr_get_INSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ return PyLong_FromSsize_t(INSIDE); } +{ return PyLong_FromLong(INSIDE); } PyObject *KX_Camera::pyattr_get_OUTSIDE(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ return PyLong_FromSsize_t(OUTSIDE); } +{ return PyLong_FromLong(OUTSIDE); } PyObject *KX_Camera::pyattr_get_INTERSECT(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ return PyLong_FromSsize_t(INTERSECT); } +{ return PyLong_FromLong(INTERSECT); } bool ConvertPythonToCamera(PyObject *value, KX_Camera **object, bool py_none_ok, const char *error_prefix) diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index a37b1b0c396..59ca0d8d326 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -388,8 +388,8 @@ PyAttributeDef KX_CameraActuator::Attributes[] = { KX_PYATTRIBUTE_FLOAT_RW("min",-FLT_MAX,FLT_MAX,KX_CameraActuator,m_minHeight), KX_PYATTRIBUTE_FLOAT_RW("max",-FLT_MAX,FLT_MAX,KX_CameraActuator,m_maxHeight), KX_PYATTRIBUTE_FLOAT_RW("height",-FLT_MAX,FLT_MAX,KX_CameraActuator,m_height), - KX_PYATTRIBUTE_SHORT_RW("axis", 0, 3, true, KX_CameraActuator,m_axis), - KX_PYATTRIBUTE_RW_FUNCTION("object", KX_CameraActuator, pyattr_get_object, pyattr_set_object), + KX_PYATTRIBUTE_SHORT_RW("axis", 0, 5, true, KX_CameraActuator, m_axis), + KX_PYATTRIBUTE_RW_FUNCTION("object", KX_CameraActuator, pyattr_get_object, pyattr_set_object), KX_PYATTRIBUTE_FLOAT_RW("damping",0.f,10.f,KX_CameraActuator,m_damping), {NULL} }; diff --git a/source/gameengine/Ketsji/KX_CharacterWrapper.h b/source/gameengine/Ketsji/KX_CharacterWrapper.h index cc99aba99f6..3b0058aca6f 100644 --- a/source/gameengine/Ketsji/KX_CharacterWrapper.h +++ b/source/gameengine/Ketsji/KX_CharacterWrapper.h @@ -32,4 +32,4 @@ private: PHY_ICharacter* m_character; }; -#endif //__KX_CHARACTERWRAPPER_H__ +#endif /* __KX_CHARACTERWRAPPER_H__ */ diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp index 662db974ee8..e09449c4f1d 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp @@ -52,7 +52,7 @@ KX_ConstraintWrapper::~KX_ConstraintWrapper() PyObject *KX_ConstraintWrapper::PyGetConstraintId() { - return PyLong_FromSsize_t(m_constraintId); + return PyLong_FromLong(m_constraintId); } diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp index fca407f6398..9f530f80e37 100644 --- a/source/gameengine/Ketsji/KX_Dome.cpp +++ b/source/gameengine/Ketsji/KX_Dome.cpp @@ -1,25 +1,27 @@ /* - * ----------------------------------------------------------------------------- + * ***** BEGIN GPL LICENSE BLOCK ***** * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser 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 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 Lesser General Public License for more details. + * 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 Lesser General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307, USA, or go to - * http://www.gnu.org/copyleft/lesser.txt. + * 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. * * Contributor(s): Dalai Felinto * * This code is originally inspired on some of the ideas and codes from Paul Bourke. - * Developed as part of a Research and Development project for SAT - La Société des arts technologiques. - * ----------------------------------------------------------------------------- + * Developed as part of a Research and Development project for + * SAT - La Société des arts technologiques. + * + * ***** END GPL LICENSE BLOCK ***** */ /** \file gameengine/Ketsji/KX_Dome.cpp diff --git a/source/gameengine/Ketsji/KX_Dome.h b/source/gameengine/Ketsji/KX_Dome.h index 17eec3a5fcb..3bc90bf6c35 100644 --- a/source/gameengine/Ketsji/KX_Dome.h +++ b/source/gameengine/Ketsji/KX_Dome.h @@ -1,26 +1,28 @@ /* ------------------------------------------------------------------------------ - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. - -Contributor(s): Dalai Felinto - -This source uses some of the ideas and code from Paul Bourke. -Developed as part of a Research and Development project for SAT - La Société des arts technologiques. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Contributor(s): Dalai Felinto + * + * This source uses some of the ideas and code from Paul Bourke. + * Developed as part of a Research and Development project for + * SAT - La Société des arts technologiques. + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file KX_Dome.h * \ingroup ketsji diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index a669f4346ea..c7f6954fd6c 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -99,6 +99,7 @@ KX_GameObject::KX_GameObject( m_bSuspendDynamics(false), m_bUseObjectColor(false), m_bIsNegativeScaling(false), + m_objectColor(1.0, 1.0, 1.0, 1.0), m_bVisible(true), m_bCulled(true), m_bOccluder(false), @@ -1692,8 +1693,8 @@ PyMethodDef KX_GameObject::Methods[] = { PyAttributeDef KX_GameObject::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("name", KX_GameObject, pyattr_get_name), KX_PYATTRIBUTE_RO_FUNCTION("parent", KX_GameObject, pyattr_get_parent), - KX_PYATTRIBUTE_RO_FUNCTION("group_children", KX_GameObject, pyattr_get_group_children), - KX_PYATTRIBUTE_RO_FUNCTION("group_parent", KX_GameObject, pyattr_get_group_parent), + KX_PYATTRIBUTE_RO_FUNCTION("groupMembers", KX_GameObject, pyattr_get_group_members), + KX_PYATTRIBUTE_RO_FUNCTION("groupObject", KX_GameObject, pyattr_get_group_object), KX_PYATTRIBUTE_RO_FUNCTION("scene", KX_GameObject, pyattr_get_scene), KX_PYATTRIBUTE_RO_FUNCTION("life", KX_GameObject, pyattr_get_life), KX_PYATTRIBUTE_RW_FUNCTION("mass", KX_GameObject, pyattr_get_mass, pyattr_set_mass), @@ -1990,7 +1991,7 @@ PyObject *KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DE Py_RETURN_NONE; } -PyObject *KX_GameObject::pyattr_get_group_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_group_members(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self = static_cast(self_v); CListValue* instances = self->GetInstanceObjects(); @@ -2011,7 +2012,7 @@ PyObject* KX_GameObject::pyattr_get_scene(void *self_v, const KX_PYATTRIBUTE_DEF Py_RETURN_NONE; } -PyObject *KX_GameObject::pyattr_get_group_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject *KX_GameObject::pyattr_get_group_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self = static_cast(self_v); KX_GameObject* pivot = self->GetDupliGroupObject(); @@ -2474,13 +2475,13 @@ PyObject *KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF KX_GameObject* self = static_cast(self_v); int state = 0; state |= self->GetState(); - return PyLong_FromSsize_t(state); + return PyLong_FromLong(state); } int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_GameObject* self = static_cast(self_v); - int state_i = PyLong_AsSsize_t(value); + int state_i = PyLong_AsLong(value); unsigned int state = 0; if (state_i == -1 && PyErr_Occurred()) { @@ -2896,7 +2897,7 @@ PyObject *KX_GameObject::PyGetPhysicsId() { physid= (uint_ptr)ctrl->GetUserData(); } - return PyLong_FromSsize_t((long)physid); + return PyLong_FromLong((long)physid); } PyObject *KX_GameObject::PyGetPropertyNames() diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index d5ae13eb702..e71af674a79 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -989,8 +989,8 @@ public: static PyObject* pyattr_get_name(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_group_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_group_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_group_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_group_members(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_scene(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 0ab7b9ec9e5..a12e12ccef2 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -534,29 +534,27 @@ bool KX_KetsjiEngine::NextFrame() { double timestep = 1.0/m_ticrate; double framestep = timestep; -// static hidden::Clock sClock; + // static hidden::Clock sClock; -m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(),true); + m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(),true); -//float dt = sClock.getTimeMicroseconds() * 0.000001f; -//sClock.reset(); + //float dt = sClock.getTimeMicroseconds() * 0.000001f; + //sClock.reset(); -if (m_bFixedTime) - m_clockTime += timestep; -else -{ - -// m_clockTime += dt; - m_clockTime = m_kxsystem->GetTimeInSeconds(); -} + if (m_bFixedTime) { + m_clockTime += timestep; + } + else { + // m_clockTime += dt; + m_clockTime = m_kxsystem->GetTimeInSeconds(); + } double deltatime = m_clockTime - m_frameTime; if (deltatime<0.f) { - printf("problem with clock\n"); - deltatime = 0.f; - m_clockTime = 0.f; - m_frameTime = 0.f; + // We got here too quickly, which means there is nothing todo, just return and don't render. + // Not sure if this is the best fix, but it seems to stop the jumping framerate issue (#33088) + return false; } diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index a4e90cb1e83..cf58d18838a 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -372,11 +372,11 @@ PyObject *KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUT const char* type = attrdef->m_name; if (!strcmp(type, "SPOT")) { - retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_SPOT); + retvalue = PyLong_FromLong(RAS_LightObject::LIGHT_SPOT); } else if (!strcmp(type, "SUN")) { - retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_SUN); + retvalue = PyLong_FromLong(RAS_LightObject::LIGHT_SUN); } else if (!strcmp(type, "NORMAL")) { - retvalue = PyLong_FromSsize_t(RAS_LightObject::LIGHT_NORMAL); + retvalue = PyLong_FromLong(RAS_LightObject::LIGHT_NORMAL); } else { /* should never happen */ @@ -390,13 +390,13 @@ PyObject *KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUT PyObject *KX_LightObject::pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_LightObject* self = static_cast(self_v); - return PyLong_FromSsize_t(self->m_lightobj.m_type); + return PyLong_FromLong(self->m_lightobj.m_type); } int KX_LightObject::pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_LightObject* self = static_cast(self_v); - int val = PyLong_AsSsize_t(value); + const int val = PyLong_AsLong(value); if ((val==-1 && PyErr_Occurred()) || val<0 || val>2) { PyErr_SetString(PyExc_ValueError, "light.type= val: KX_LightObject, expected an int between 0 and 2"); return PY_SET_ATTR_FAIL; diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index 87c366046ad..d83e98d4712 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -70,13 +70,15 @@ PyTypeObject KX_MeshProxy::Type = { }; PyMethodDef KX_MeshProxy::Methods[] = { -{"getMaterialName", (PyCFunction)KX_MeshProxy::sPyGetMaterialName,METH_VARARGS}, -{"getTextureName", (PyCFunction)KX_MeshProxy::sPyGetTextureName,METH_VARARGS}, -{"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS}, -{"getVertex", (PyCFunction)KX_MeshProxy::sPyGetVertex,METH_VARARGS}, -{"getPolygon", (PyCFunction)KX_MeshProxy::sPyGetPolygon,METH_VARARGS}, -//{"getIndexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetIndexArrayLength,METH_VARARGS}, - {NULL,NULL} //Sentinel + {"getMaterialName", (PyCFunction)KX_MeshProxy::sPyGetMaterialName,METH_VARARGS}, + {"getTextureName", (PyCFunction)KX_MeshProxy::sPyGetTextureName,METH_VARARGS}, + {"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS}, + {"getVertex", (PyCFunction)KX_MeshProxy::sPyGetVertex,METH_VARARGS}, + {"getPolygon", (PyCFunction)KX_MeshProxy::sPyGetPolygon,METH_VARARGS}, + {"transform", (PyCFunction)KX_MeshProxy::sPyTransform,METH_VARARGS}, + {"transformUV", (PyCFunction)KX_MeshProxy::sPyTransformUV,METH_VARARGS}, + //{"getIndexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetIndexArrayLength,METH_VARARGS}, + {NULL,NULL} //Sentinel }; PyAttributeDef KX_MeshProxy::Attributes[] = { @@ -170,7 +172,7 @@ PyObject *KX_MeshProxy::PyGetVertexArrayLength(PyObject *args, PyObject *kwds) length = m_meshobj->NumVertices(mat); } - return PyLong_FromSsize_t(length); + return PyLong_FromLong(length); } @@ -218,6 +220,160 @@ PyObject *KX_MeshProxy::PyGetPolygon(PyObject *args, PyObject *kwds) return polyob; } +PyObject *KX_MeshProxy::PyTransform(PyObject *args, PyObject *kwds) +{ + int matindex; + PyObject *pymat; + bool ok = false; + + MT_Matrix4x4 transform; + + if (!PyArg_ParseTuple(args,"iO:transform", &matindex, &pymat) || + !PyMatTo(pymat, transform)) + { + return NULL; + } + + MT_Matrix4x4 ntransform = transform.inverse().transposed(); + ntransform[0][3] = ntransform[1][3] = ntransform[2][3] = 0.0f; + + /* transform mesh verts */ + unsigned int mit_index = 0; + for (list::iterator mit = m_meshobj->GetFirstMaterial(); + (mit != m_meshobj->GetLastMaterial()); + ++mit, ++mit_index) + { + if (matindex == -1) { + /* always transform */ + } + else if (matindex == mit_index) { + /* we found the right index! */ + } + else { + continue; + } + + RAS_MeshSlot *slot = mit->m_baseslot; + RAS_MeshSlot::iterator it; + ok = true; + + for (slot->begin(it); !slot->end(it); slot->next(it)) { + size_t i; + for (i = it.startvertex; i < it.endvertex; i++) { + RAS_TexVert *vert = &it.vertex[i]; + vert->Transform(transform, ntransform); + } + } + + /* if we set a material index, quit when done */ + if (matindex == mit_index) { + break; + } + } + + if (ok == false) { + PyErr_Format(PyExc_ValueError, + "mesh.transform(...): invalid material index %d", matindex); + return NULL; + } + + m_meshobj->SetMeshModified(true); + + Py_RETURN_NONE; +} + +PyObject *KX_MeshProxy::PyTransformUV(PyObject *args, PyObject *kwds) +{ + int matindex; + PyObject *pymat; + int uvindex = -1; + int uvindex_from = -1; + bool ok = false; + + MT_Matrix4x4 transform; + + if (!PyArg_ParseTuple(args,"iO|iii:transformUV", &matindex, &pymat, &uvindex, &uvindex_from) || + !PyMatTo(pymat, transform)) + { + return NULL; + } + + if (uvindex < -1 || uvindex > 1) { + PyErr_Format(PyExc_ValueError, + "mesh.transformUV(...): invalid uv_index %d", uvindex); + return NULL; + } + if (uvindex_from < -1 || uvindex_from > 1 || uvindex == -1) { + PyErr_Format(PyExc_ValueError, + "mesh.transformUV(...): invalid uv_index_from %d", uvindex); + return NULL; + } + if (uvindex_from == uvindex) { + uvindex_from = -1; + } + + /* transform mesh verts */ + unsigned int mit_index = 0; + for (list::iterator mit = m_meshobj->GetFirstMaterial(); + (mit != m_meshobj->GetLastMaterial()); + ++mit, ++mit_index) + { + if (matindex == -1) { + /* always transform */ + } + else if (matindex == mit_index) { + /* we found the right index! */ + } + else { + continue; + } + + RAS_MeshSlot *slot = mit->m_baseslot; + RAS_MeshSlot::iterator it; + ok = true; + + for (slot->begin(it); !slot->end(it); slot->next(it)) { + size_t i; + + for (i = it.startvertex; i < it.endvertex; i++) { + RAS_TexVert *vert = &it.vertex[i]; + if (uvindex_from != -1) { + if (uvindex_from == 0) vert->SetUV2(vert->getUV1()); + else vert->SetUV1(vert->getUV2()); + } + + switch (uvindex) { + case 0: + vert->TransformUV1(transform); + break; + case 1: + vert->TransformUV2(transform); + break; + case -1: + vert->TransformUV1(transform); + vert->TransformUV2(transform); + break; + } + } + } + + /* if we set a material index, quit when done */ + if (matindex == mit_index) { + break; + } + } + + if (ok == false) { + PyErr_Format(PyExc_ValueError, + "mesh.transformUV(...): invalid material index %d", matindex); + return NULL; + } + + m_meshobj->SetMeshModified(true); + + Py_RETURN_NONE; +} + PyObject *KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_MeshProxy* self = static_cast(self_v); @@ -250,13 +406,13 @@ PyObject *KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_ PyObject * KX_MeshProxy::pyattr_get_numMaterials(void * selfv, const KX_PYATTRIBUTE_DEF * attrdef) { KX_MeshProxy * self = static_cast (selfv); - return PyLong_FromSsize_t(self->m_meshobj->NumMaterials()); + return PyLong_FromLong(self->m_meshobj->NumMaterials()); } PyObject * KX_MeshProxy::pyattr_get_numPolygons(void * selfv, const KX_PYATTRIBUTE_DEF * attrdef) { KX_MeshProxy * self = static_cast (selfv); - return PyLong_FromSsize_t(self->m_meshobj->NumPolygons()); + return PyLong_FromLong(self->m_meshobj->NumPolygons()); } /* a close copy of ConvertPythonToGameObject but for meshes */ diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h index 98e73aa626f..5366634ef98 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.h +++ b/source/gameengine/Ketsji/KX_MeshProxy.h @@ -71,8 +71,10 @@ public: KX_PYMETHOD(KX_MeshProxy,GetVertexArrayLength); KX_PYMETHOD(KX_MeshProxy,GetVertex); KX_PYMETHOD(KX_MeshProxy,GetPolygon); + KX_PYMETHOD(KX_MeshProxy,Transform); + KX_PYMETHOD(KX_MeshProxy,TransformUV); - static PyObject* pyattr_get_materials(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_materials(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject *pyattr_get_numMaterials(void * self, const KX_PYATTRIBUTE_DEF * attrdef); static PyObject *pyattr_get_numPolygons(void * self, const KX_PYATTRIBUTE_DEF * attrdef); }; diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index e5f7ea22b36..931039bc54c 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -529,7 +529,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitX(void *self_v, const KX_PYATTRIBUTE { self->m_drot[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)); self->m_dloc[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)); - self->m_bitLocalFlag.Torque = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0); + self->m_bitLocalFlag.Torque = (PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0); if (!PyErr_Occurred()) { @@ -565,7 +565,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitY(void *self_v, const KX_PYATTRIBUTE { self->m_drot[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)); self->m_dloc[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)); - self->m_bitLocalFlag.DLoc = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0); + self->m_bitLocalFlag.DLoc = (PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0); if (!PyErr_Occurred()) { @@ -601,7 +601,7 @@ int KX_ObjectActuator::pyattr_set_forceLimitZ(void *self_v, const KX_PYATTRIBUTE { self->m_drot[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)); self->m_dloc[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)); - self->m_bitLocalFlag.DRot = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0); + self->m_bitLocalFlag.DRot = (PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0); if (!PyErr_Occurred()) { diff --git a/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp b/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp index 99d9fc7f9ee..8798f42fa07 100644 --- a/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp +++ b/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp @@ -1,6 +1,4 @@ /* - * Simulation for obstacle avoidance behavior - * * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -22,6 +20,12 @@ * ***** END GPL LICENSE BLOCK ***** */ +/** \file gameengine/Ketsji/KX_ObstacleSimulation.cpp + * \ingroup ketsji + * + * Simulation for obstacle avoidance behavior + */ + #include "KX_ObstacleSimulation.h" #include "KX_NavMeshObject.h" #include "KX_PythonInit.h" diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp deleted file mode 100644 index f18c35c0c78..00000000000 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp - * \ingroup ketsji - */ - - -#include "PyObjectPlus.h" - -#include "KX_PhysicsObjectWrapper.h" -#include "PHY_IPhysicsEnvironment.h" -#include "PHY_IPhysicsController.h" - -KX_PhysicsObjectWrapper::KX_PhysicsObjectWrapper( - PHY_IPhysicsController* ctrl, - PHY_IPhysicsEnvironment* physenv) : - PyObjectPlus(), - m_ctrl(ctrl), - m_physenv(physenv) -{ -} - -KX_PhysicsObjectWrapper::~KX_PhysicsObjectWrapper() -{ -} - -#ifdef WITH_PYTHON - -PyObject *KX_PhysicsObjectWrapper::PySetPosition(PyObject *args) -{ - float x,y,z; - if (PyArg_ParseTuple(args,"fff:setPosition",&x,&y,&z)) - { - m_ctrl->setPosition(x,y,z); - } - else { - return NULL; - } - Py_RETURN_NONE; -} - - -PyObject *KX_PhysicsObjectWrapper::PySetLinearVelocity(PyObject *args) -{ - float x,y,z; - int local; - if (PyArg_ParseTuple(args,"fffi:setLinearVelocity",&x,&y,&z,&local)) - { - m_ctrl->SetLinearVelocity(x,y,z,local != 0); - } - else { - return NULL; - } - Py_RETURN_NONE; -} - -PyObject *KX_PhysicsObjectWrapper::PySetAngularVelocity(PyObject *args) -{ - float x,y,z; - int local; - if (PyArg_ParseTuple(args,"fffi:setAngularVelocity",&x,&y,&z,&local)) - { - m_ctrl->SetAngularVelocity(x,y,z,local != 0); - } - else { - return NULL; - } - Py_RETURN_NONE; -} - -PyObject* KX_PhysicsObjectWrapper::PySetActive(PyObject *args) -{ - int active; - if (PyArg_ParseTuple(args,"i:setActive",&active)) - { - m_ctrl->SetActive(active!=0); - } - else { - return NULL; - } - Py_RETURN_NONE; -} - - -PyAttributeDef KX_PhysicsObjectWrapper::Attributes[] = { - { NULL } //Sentinel -}; - -//python specific stuff -PyTypeObject KX_PhysicsObjectWrapper::Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "KX_PhysicsObjectWrapper", - sizeof(PyObjectPlus_Proxy), - 0, - py_base_dealloc, - 0, - 0, - 0, - 0, - py_base_repr, - 0,0,0,0,0,0,0,0,0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - 0,0,0,0,0,0,0, - Methods, - 0, - 0, - &PyObjectPlus::Type, - 0,0,0,0,0,0, - py_base_new -}; - -PyMethodDef KX_PhysicsObjectWrapper::Methods[] = { - {"setPosition",(PyCFunction) KX_PhysicsObjectWrapper::sPySetPosition, METH_VARARGS}, - {"setLinearVelocity",(PyCFunction) KX_PhysicsObjectWrapper::sPySetLinearVelocity, METH_VARARGS}, - {"setAngularVelocity",(PyCFunction) KX_PhysicsObjectWrapper::sPySetAngularVelocity, METH_VARARGS}, - {"setActive",(PyCFunction) KX_PhysicsObjectWrapper::sPySetActive, METH_VARARGS}, - {NULL,NULL} //Sentinel -}; - -#endif diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h deleted file mode 100644 index 171416c5e8f..00000000000 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file KX_PhysicsObjectWrapper.h - * \ingroup ketsji - */ - -#ifndef __KX_PHYSICSOBJECTWRAPPER_H__ -#define __KX_PHYSICSOBJECTWRAPPER_H__ - -#include "Value.h" -#include "PHY_DynamicTypes.h" - -class KX_PhysicsObjectWrapper : public PyObjectPlus -{ - Py_Header -public: - KX_PhysicsObjectWrapper(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsEnvironment* physenv); - virtual ~KX_PhysicsObjectWrapper(); - -#ifdef WITH_PYTHON - - KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetPosition); - KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetLinearVelocity); - KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetAngularVelocity); - KX_PYMETHOD_VARARGS(KX_PhysicsObjectWrapper,SetActive); - -#endif /* WITH_PYTHON */ - -private: - class PHY_IPhysicsController* m_ctrl; - PHY_IPhysicsEnvironment* m_physenv; -}; - -#endif /* __KX_PHYSICSOBJECTWRAPPER_H__ */ diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp index 465e91ffb32..840ffdde165 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.cpp +++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp @@ -140,21 +140,21 @@ PyObject *KX_PolyProxy::pyattr_get_v1(void *self_v, const KX_PYATTRIBUTE_DEF *at { KX_PolyProxy* self = static_cast(self_v); - return PyLong_FromSsize_t(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 0)); + return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 0)); } PyObject *KX_PolyProxy::pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_PolyProxy* self = static_cast(self_v); - return PyLong_FromSsize_t(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 1)); + return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 1)); } PyObject *KX_PolyProxy::pyattr_get_v3(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_PolyProxy* self = static_cast(self_v); - return PyLong_FromSsize_t(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 2)); + return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 2)); } PyObject *KX_PolyProxy::pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -163,9 +163,9 @@ PyObject *KX_PolyProxy::pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *at if (3 < self->m_polygon->VertexCount()) { - return PyLong_FromSsize_t(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 3)); + return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbs(self->m_mesh, 3)); } - return PyLong_FromSsize_t(0); + return PyLong_FromLong(0); } PyObject *KX_PolyProxy::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -192,25 +192,25 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialIndex, // found it break; } - return PyLong_FromSsize_t(matid); + return PyLong_FromLong(matid); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getNumVertex, "getNumVertex() : returns the number of vertex of the polygon, 3 or 4\n") { - return PyLong_FromSsize_t(m_polygon->VertexCount()); + return PyLong_FromLong(m_polygon->VertexCount()); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, isVisible, "isVisible() : returns whether the polygon is visible or not\n") { - return PyLong_FromSsize_t(m_polygon->IsVisible()); + return PyLong_FromLong(m_polygon->IsVisible()); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, isCollider, "isCollider() : returns whether the polygon is receives collision or not\n") { - return PyLong_FromSsize_t(m_polygon->IsCollider()); + return PyLong_FromLong(m_polygon->IsCollider()); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterialName, @@ -243,9 +243,9 @@ KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex, } if (index < m_polygon->VertexCount()) { - return PyLong_FromSsize_t(m_polygon->GetVertexOffsetAbs(m_mesh, index)); + return PyLong_FromLong(m_polygon->GetVertexOffsetAbs(m_mesh, index)); } - return PyLong_FromSsize_t(0); + return PyLong_FromLong(0); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMesh, diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index 36c94dc997b..f157d9ed20a 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -109,7 +109,7 @@ void KX_PolygonMaterial::Initialize( m_mcol = *mcol; } else { - memset(&m_mcol, 0, sizeof(m_mcol)); + m_mcol = 0; } m_material = ma; @@ -146,7 +146,7 @@ bool KX_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingI PyObject *ret = PyObject_CallMethod(m_pymaterial, (char *)"activate", (char *)"(NNO)", pyRasty, pyCachingInfo, (PyObject *) this->m_proxy); if (ret) { - bool value = PyLong_AsSsize_t(ret); + bool value = PyLong_AsLong(ret); Py_DECREF(ret); dopass = value; } @@ -266,8 +266,6 @@ PyAttributeDef KX_PolygonMaterial::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("tface", KX_PolygonMaterial, pyattr_get_tface), /* How the heck is this even useful??? - Campbell */ KX_PYATTRIBUTE_RO_FUNCTION("gl_texture", KX_PolygonMaterial, pyattr_get_gl_texture), /* could be called 'bindcode' */ - - /* triangle used to be an attribute, removed for 2.49, nobody should be using it */ { NULL } //Sentinel }; @@ -381,7 +379,7 @@ PyObject *KX_PolygonMaterial::pyattr_get_gl_texture(void *self_v, const KX_PYATT if (self->m_tface.tpage) bindcode= self->m_tface.tpage->bindcode; - return PyLong_FromSsize_t(bindcode); + return PyLong_FromLong(bindcode); } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index 89bfb4ff9fb..2ce8f480c1c 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -60,7 +60,7 @@ class KX_PolygonMaterial : public PyObjectPlus, public RAS_IPolyMaterial private: /** Blender texture face structure. */ mutable MTFace m_tface; - mutable unsigned int m_mcol; + mutable unsigned int m_mcol; /* for text color (only) */ Material* m_material; #ifdef WITH_PYTHON diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index 4475ac8ec96..9bb09d56de6 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -34,7 +34,6 @@ #include "KX_ConstraintWrapper.h" #include "KX_VehicleWrapper.h" #include "KX_CharacterWrapper.h" -#include "KX_PhysicsObjectWrapper.h" #include "PHY_IPhysicsController.h" #include "PHY_IVehicle.h" #include "PHY_DynamicTypes.h" @@ -51,7 +50,7 @@ #ifdef WITH_PYTHON // macro copied from KX_PythonInit.cpp -#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyLong_FromSsize_t(name2)); Py_DECREF(item) +#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyLong_FromLong(name2)); Py_DECREF(item) // nasty glob variable to connect scripting language // if there is a better way (without global), please do so! @@ -729,7 +728,7 @@ PyObject *initPythonConstraintBinding() KX_MACRO_addTypesToDict(d, DBG_PROFILETIMINGS, btIDebugDraw::DBG_ProfileTimings); KX_MACRO_addTypesToDict(d, DBG_ENABLESATCOMPARISION, btIDebugDraw::DBG_EnableSatComparison); KX_MACRO_addTypesToDict(d, DBG_DISABLEBULLETLCP, btIDebugDraw::DBG_DisableBulletLCP); - KX_MACRO_addTypesToDict(d, DBG_ENABLECDD, btIDebugDraw::DBG_EnableCCD); + KX_MACRO_addTypesToDict(d, DBG_ENABLECCD, btIDebugDraw::DBG_EnableCCD); KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTS, btIDebugDraw::DBG_DrawConstraints); KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTLIMITS, btIDebugDraw::DBG_DrawConstraintLimits); KX_MACRO_addTypesToDict(d, DBG_FASTWIREFRAME, btIDebugDraw::DBG_FastWireframe); diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 7f6655861f1..996be97c474 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -193,10 +193,10 @@ static PyObject *gp_OrigPythonSysPath= NULL; static PyObject *gp_OrigPythonSysModules= NULL; /* Macro for building the keyboard translation */ -//#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyLong_FromSsize_t(SCA_IInputDevice::KX_##name)) -#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, item=PyLong_FromSsize_t(name)); Py_DECREF(item) +//#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, PyLong_FromLong(SCA_IInputDevice::KX_##name)) +#define KX_MACRO_addToDict(dict, name) PyDict_SetItemString(dict, #name, item=PyLong_FromLong(name)); Py_DECREF(item) /* For the defines for types from logic bricks, we do stuff explicitly... */ -#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyLong_FromSsize_t(name2)); Py_DECREF(item) +#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyLong_FromLong(name2)); Py_DECREF(item) // temporarily python stuff, will be put in another place later ! @@ -429,7 +429,7 @@ static PyObject *gPySetExitKey(PyObject *, PyObject *args) static PyObject *gPyGetExitKey(PyObject *) { - return PyLong_FromSsize_t(KX_KetsjiEngine::GetExitKey()); + return PyLong_FromLong(KX_KetsjiEngine::GetExitKey()); } static PyObject *gPySetMaxLogicFrame(PyObject *, PyObject *args) @@ -444,7 +444,7 @@ static PyObject *gPySetMaxLogicFrame(PyObject *, PyObject *args) static PyObject *gPyGetMaxLogicFrame(PyObject *) { - return PyLong_FromSsize_t(KX_KetsjiEngine::GetMaxLogicFrame()); + return PyLong_FromLong(KX_KetsjiEngine::GetMaxLogicFrame()); } static PyObject *gPySetMaxPhysicsFrame(PyObject *, PyObject *args) @@ -459,7 +459,7 @@ static PyObject *gPySetMaxPhysicsFrame(PyObject *, PyObject *args) static PyObject *gPyGetMaxPhysicsFrame(PyObject *) { - return PyLong_FromSsize_t(KX_KetsjiEngine::GetMaxPhysicsFrame()); + return PyLong_FromLong(KX_KetsjiEngine::GetMaxPhysicsFrame()); } static PyObject *gPySetPhysicsTicRate(PyObject *, PyObject *args) @@ -862,14 +862,14 @@ static struct PyMethodDef game_methods[] = { static PyObject *gPyGetWindowHeight(PyObject *, PyObject *args) { - return PyLong_FromSsize_t((gp_Canvas ? gp_Canvas->GetHeight() : 0)); + return PyLong_FromLong((gp_Canvas ? gp_Canvas->GetHeight() : 0)); } static PyObject *gPyGetWindowWidth(PyObject *, PyObject *args) { - return PyLong_FromSsize_t((gp_Canvas ? gp_Canvas->GetWidth() : 0)); + return PyLong_FromLong((gp_Canvas ? gp_Canvas->GetWidth() : 0)); } @@ -1203,7 +1203,7 @@ static PyObject *gPyGetGLSLMaterialSetting(PyObject *, } enabled = ((gs->glslflag & flag) != 0); - return PyLong_FromSsize_t(enabled); + return PyLong_FromLong(enabled); } #define KX_TEXFACE_MATERIAL 0 @@ -1246,7 +1246,7 @@ static PyObject *gPyGetMaterialType(PyObject *) else flag = KX_TEXFACE_MATERIAL; - return PyLong_FromSsize_t(flag); + return PyLong_FromLong(flag); } static PyObject *gPySetAnisotropicFiltering(PyObject *, PyObject *args) @@ -1688,6 +1688,7 @@ PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack KX_MACRO_addTypesToDict(d, KX_ACT_ARMATURE_DISABLE, ACT_ARM_DISABLE); KX_MACRO_addTypesToDict(d, KX_ACT_ARMATURE_SETTARGET, ACT_ARM_SETTARGET); KX_MACRO_addTypesToDict(d, KX_ACT_ARMATURE_SETWEIGHT, ACT_ARM_SETWEIGHT); + KX_MACRO_addTypesToDict(d, KX_ACT_ARMATURE_SETINFLUENCE, ACT_ARM_SETINFLUENCE); /* BL_Armature Channel rotation_mode */ KX_MACRO_addTypesToDict(d, ROT_MODE_QUAT, ROT_MODE_QUAT); diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp index 805b9ce2fc2..971730672db 100644 --- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp +++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp @@ -40,6 +40,7 @@ #include "BL_ArmatureConstraint.h" #include "BL_ArmatureObject.h" #include "BL_ArmatureChannel.h" +#include "KX_ArmatureSensor.h" #include "KX_BlenderMaterial.h" #include "KX_CameraActuator.h" #include "KX_CharacterWrapper.h" @@ -54,7 +55,6 @@ #include "KX_NetworkMessageSensor.h" #include "KX_ObjectActuator.h" #include "KX_ParentActuator.h" -#include "KX_PhysicsObjectWrapper.h" #include "KX_PolyProxy.h" #include "KX_PolygonMaterial.h" #include "KX_PythonSeq.h" @@ -185,8 +185,10 @@ void initPyTypes(void) PyType_Ready_Attr(dict, BL_ArmatureConstraint, init_getset); PyType_Ready_AttrPtr(dict, BL_ArmatureBone, init_getset); PyType_Ready_AttrPtr(dict, BL_ArmatureChannel, init_getset); + // PyType_Ready_Attr(dict, CPropValue, init_getset); // doesn't use Py_Header PyType_Ready_Attr(dict, CListValue, init_getset); PyType_Ready_Attr(dict, CValue, init_getset); + PyType_Ready_Attr(dict, KX_ArmatureSensor, init_getset); PyType_Ready_Attr(dict, KX_BlenderMaterial, init_getset); PyType_Ready_Attr(dict, KX_Camera, init_getset); PyType_Ready_Attr(dict, KX_CameraActuator, init_getset); @@ -205,7 +207,6 @@ void initPyTypes(void) PyType_Ready_Attr(dict, KX_NetworkMessageSensor, init_getset); PyType_Ready_Attr(dict, KX_ObjectActuator, init_getset); PyType_Ready_Attr(dict, KX_ParentActuator, init_getset); - PyType_Ready_Attr(dict, KX_PhysicsObjectWrapper, init_getset); PyType_Ready_Attr(dict, KX_PolyProxy, init_getset); PyType_Ready_Attr(dict, KX_PolygonMaterial, init_getset); PyType_Ready_Attr(dict, KX_RadarSensor, init_getset); @@ -228,6 +229,7 @@ void initPyTypes(void) PyType_Ready_Attr(dict, PyObjectPlus, init_getset); PyType_Ready_Attr(dict, SCA_2DFilterActuator, init_getset); PyType_Ready_Attr(dict, SCA_ANDController, init_getset); + // PyType_Ready_Attr(dict, SCA_Actuator, init_getset); // doesn't use Py_Header PyType_Ready_Attr(dict, SCA_ActuatorSensor, init_getset); PyType_Ready_Attr(dict, SCA_AlwaysSensor, init_getset); PyType_Ready_Attr(dict, SCA_DelaySensor, init_getset); diff --git a/source/gameengine/Ketsji/KX_PythonSeq.cpp b/source/gameengine/Ketsji/KX_PythonSeq.cpp index 6b4d88709e8..f0e11645bc1 100644 --- a/source/gameengine/Ketsji/KX_PythonSeq.cpp +++ b/source/gameengine/Ketsji/KX_PythonSeq.cpp @@ -100,7 +100,7 @@ static Py_ssize_t KX_PythonSeq_len( PyObject *self ) } } -static PyObject *KX_PythonSeq_getIndex(PyObject *self, int index) +static PyObject *KX_PythonSeq_getIndex(PyObject *self, Py_ssize_t index) { PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); @@ -273,8 +273,8 @@ static PyObject * KX_PythonSeq_subscript(PyObject *self, PyObject *key) return NULL; } - if (PyLong_Check(key)) { - return KX_PythonSeq_getIndex(self, PyLong_AsSsize_t( key )); + if (PyIndex_Check(key)) { + return KX_PythonSeq_getIndex(self, PyLong_AsSsize_t(key)); } else if ( PyUnicode_Check(key) ) { const char *name = _PyUnicode_AsString(key); diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index d850168afdf..56dccc1d045 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -190,8 +190,8 @@ PyTypeObject KX_SCA_AddObjectActuator::Type = { }; PyMethodDef KX_SCA_AddObjectActuator::Methods[] = { - {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_NOARGS,"instantAddObject() : immediately add object without delay\n"}, - {NULL,NULL} //Sentinel + {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_NOARGS, NULL}, + {NULL,NULL} //Sentinel }; PyAttributeDef KX_SCA_AddObjectActuator::Attributes[] = { diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp index e6209d2d47b..81c9dc91603 100644 --- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp @@ -113,7 +113,7 @@ PyTypeObject KX_SCA_EndObjectActuator::Type = { }; PyMethodDef KX_SCA_EndObjectActuator::Methods[] = { - {NULL,NULL} //Sentinel + {NULL,NULL} //Sentinel }; PyAttributeDef KX_SCA_EndObjectActuator::Attributes[] = { diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 96b4a21a36c..72be5f57b95 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -55,7 +55,7 @@ #include "SCA_BasicEventManager.h" #include "KX_Camera.h" #include "SCA_JoystickManager.h" - +#include "KX_PyMath.h" #include "RAS_MeshObject.h" #include "RAS_IRasterizer.h" @@ -1706,6 +1706,17 @@ void KX_Scene::SetGravity(const MT_Vector3& gravity) GetPhysicsEnvironment()->setGravity(gravity[0],gravity[1],gravity[2]); } +MT_Vector3 KX_Scene::GetGravity() +{ + PHY__Vector3 gravity; + MT_Vector3 vec; + + GetPhysicsEnvironment()->getGravity(gravity); + vec = gravity.m_vec; + + return vec; +} + void KX_Scene::SetSceneConverter(class KX_BlenderSceneConverter* sceneConverter) { m_sceneConverter = sceneConverter; @@ -2270,6 +2281,25 @@ int KX_Scene::pyattr_set_drawing_callback_post(void *self_v, const KX_PYATTRIBUT return PY_SET_ATTR_SUCCESS; } +PyObject *KX_Scene::pyattr_get_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Scene* self = static_cast(self_v); + + return PyObjectFrom(self->GetGravity()); +} + +int KX_Scene::pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_Scene* self = static_cast(self_v); + + MT_Vector3 vec; + if (!PyVecTo(value, vec)) + return PY_SET_ATTR_FAIL; + + self->SetGravity(vec); + return PY_SET_ATTR_SUCCESS; +} + PyAttributeDef KX_Scene::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("name", KX_Scene, pyattr_get_name), KX_PYATTRIBUTE_RO_FUNCTION("objects", KX_Scene, pyattr_get_objects), @@ -2280,6 +2310,7 @@ PyAttributeDef KX_Scene::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("active_camera", KX_Scene, pyattr_get_active_camera, pyattr_set_active_camera), KX_PYATTRIBUTE_RW_FUNCTION("pre_draw", KX_Scene, pyattr_get_drawing_callback_pre, pyattr_set_drawing_callback_pre), KX_PYATTRIBUTE_RW_FUNCTION("post_draw", KX_Scene, pyattr_get_drawing_callback_post, pyattr_set_drawing_callback_post), + KX_PYATTRIBUTE_RW_FUNCTION("gravity", KX_Scene, pyattr_get_gravity, pyattr_set_gravity), KX_PYATTRIBUTE_BOOL_RO("suspended", KX_Scene, m_suspend), KX_PYATTRIBUTE_BOOL_RO("activity_culling", KX_Scene, m_activity_culling), KX_PYATTRIBUTE_FLOAT_RW("activity_culling_radius", 0.5f, FLT_MAX, KX_Scene, m_activity_box_radius), diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index c2e468e6da6..29473949535 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -573,6 +573,7 @@ public: void SetPhysicsEnvironment(class PHY_IPhysicsEnvironment* physEnv); void SetGravity(const MT_Vector3& gravity); + MT_Vector3 GetGravity(); short GetAnimationFPS(); @@ -616,6 +617,8 @@ public: static int pyattr_set_drawing_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_drawing_callback_post(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_gravity(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); virtual PyObject *py_repr(void) { return PyUnicode_From_STR_String(GetName()); } diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index b5d6f11a2d5..9cc91a33886 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -126,13 +126,13 @@ PyObject *KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject *args) PyObject *KX_VehicleWrapper::PyGetNumWheels(PyObject *args) { - return PyLong_FromSsize_t(m_vehicle->GetNumWheels()); + return PyLong_FromLong(m_vehicle->GetNumWheels()); } PyObject *KX_VehicleWrapper::PyGetConstraintId(PyObject *args) { - return PyLong_FromSsize_t(m_vehicle->GetUserConstraintId()); + return PyLong_FromLong(m_vehicle->GetUserConstraintId()); } @@ -263,7 +263,7 @@ PyObject *KX_VehicleWrapper::PySetSteeringValue(PyObject *args) PyObject *KX_VehicleWrapper::PyGetConstraintType(PyObject *args) { - return PyLong_FromSsize_t(m_vehicle->GetUserConstraintType()); + return PyLong_FromLong(m_vehicle->GetUserConstraintType()); } diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index dabb79b357d..2354359af18 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -61,19 +61,19 @@ PyTypeObject KX_VertexProxy::Type = { }; PyMethodDef KX_VertexProxy::Methods[] = { -{"getXYZ", (PyCFunction)KX_VertexProxy::sPyGetXYZ,METH_NOARGS}, -{"setXYZ", (PyCFunction)KX_VertexProxy::sPySetXYZ,METH_O}, -{"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV,METH_NOARGS}, -{"setUV", (PyCFunction)KX_VertexProxy::sPySetUV,METH_O}, + {"getXYZ", (PyCFunction)KX_VertexProxy::sPyGetXYZ,METH_NOARGS}, + {"setXYZ", (PyCFunction)KX_VertexProxy::sPySetXYZ,METH_O}, + {"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV1, METH_NOARGS}, + {"setUV", (PyCFunction)KX_VertexProxy::sPySetUV1, METH_O}, -{"getUV2", (PyCFunction)KX_VertexProxy::sPyGetUV2,METH_NOARGS}, -{"setUV2", (PyCFunction)KX_VertexProxy::sPySetUV2,METH_VARARGS}, + {"getUV2", (PyCFunction)KX_VertexProxy::sPyGetUV2,METH_NOARGS}, + {"setUV2", (PyCFunction)KX_VertexProxy::sPySetUV2,METH_VARARGS}, -{"getRGBA", (PyCFunction)KX_VertexProxy::sPyGetRGBA,METH_NOARGS}, -{"setRGBA", (PyCFunction)KX_VertexProxy::sPySetRGBA,METH_O}, -{"getNormal", (PyCFunction)KX_VertexProxy::sPyGetNormal,METH_NOARGS}, -{"setNormal", (PyCFunction)KX_VertexProxy::sPySetNormal,METH_O}, - {NULL,NULL} //Sentinel + {"getRGBA", (PyCFunction)KX_VertexProxy::sPyGetRGBA,METH_NOARGS}, + {"setRGBA", (PyCFunction)KX_VertexProxy::sPySetRGBA,METH_O}, + {"getNormal", (PyCFunction)KX_VertexProxy::sPyGetNormal,METH_NOARGS}, + {"setNormal", (PyCFunction)KX_VertexProxy::sPySetNormal,METH_O}, + {NULL,NULL} //Sentinel }; PyAttributeDef KX_VertexProxy::Attributes[] = { @@ -247,7 +247,7 @@ int KX_VertexProxy::pyattr_set_u(void *self_v, const struct KX_PYATTRIBUTE_DEF * float val = PyFloat_AsDouble(value); MT_Point2 uv = self->m_vertex->getUV1(); uv[0] = val; - self->m_vertex->SetUV(uv); + self->m_vertex->SetUV1(uv); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -262,7 +262,7 @@ int KX_VertexProxy::pyattr_set_v(void *self_v, const struct KX_PYATTRIBUTE_DEF * float val = PyFloat_AsDouble(value); MT_Point2 uv = self->m_vertex->getUV1(); uv[1] = val; - self->m_vertex->SetUV(uv); + self->m_vertex->SetUV1(uv); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -389,9 +389,8 @@ int KX_VertexProxy::pyattr_set_UV(void *self_v, const struct KX_PYATTRIBUTE_DEF if (PySequence_Check(value)) { MT_Point2 vec; - if (PyVecTo(value, vec)) - { - self->m_vertex->SetUV(vec); + if (PyVecTo(value, vec)) { + self->m_vertex->SetUV1(vec); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -495,13 +494,13 @@ PyObject *KX_VertexProxy::PySetNormal(PyObject *value) PyObject *KX_VertexProxy::PyGetRGBA() { int *rgba = (int *) m_vertex->getRGBA(); - return PyLong_FromSsize_t(*rgba); + return PyLong_FromLong(*rgba); } PyObject *KX_VertexProxy::PySetRGBA(PyObject *value) { if (PyLong_Check(value)) { - int rgba = PyLong_AsSsize_t(value); + int rgba = PyLong_AsLong(value); m_vertex->SetRGBA(rgba); m_mesh->SetMeshModified(true); Py_RETURN_NONE; @@ -521,18 +520,18 @@ PyObject *KX_VertexProxy::PySetRGBA(PyObject *value) } -PyObject *KX_VertexProxy::PyGetUV() +PyObject *KX_VertexProxy::PyGetUV1() { return PyObjectFrom(MT_Vector2(m_vertex->getUV1())); } -PyObject *KX_VertexProxy::PySetUV(PyObject *value) +PyObject *KX_VertexProxy::PySetUV1(PyObject *value) { MT_Point2 vec; if (!PyVecTo(value, vec)) return NULL; - m_vertex->SetUV(vec); + m_vertex->SetUV1(vec); m_mesh->SetMeshModified(true); Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h index 6e193d35b4c..4247d138a66 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.h +++ b/source/gameengine/Ketsji/KX_VertexProxy.h @@ -92,8 +92,8 @@ public: KX_PYMETHOD_NOARGS(KX_VertexProxy,GetXYZ); KX_PYMETHOD_O(KX_VertexProxy,SetXYZ); - KX_PYMETHOD_NOARGS(KX_VertexProxy,GetUV); - KX_PYMETHOD_O(KX_VertexProxy,SetUV); + KX_PYMETHOD_NOARGS(KX_VertexProxy,GetUV1); + KX_PYMETHOD_O(KX_VertexProxy,SetUV1); KX_PYMETHOD_NOARGS(KX_VertexProxy,GetUV2); KX_PYMETHOD_VARARGS(KX_VertexProxy,SetUV2); diff --git a/source/gameengine/Network/NG_NetworkDeviceInterface.h b/source/gameengine/Network/NG_NetworkDeviceInterface.h index 48edbdfc7fe..6da478ecda5 100644 --- a/source/gameengine/Network/NG_NetworkDeviceInterface.h +++ b/source/gameengine/Network/NG_NetworkDeviceInterface.h @@ -43,8 +43,8 @@ private: // candidates for shared/common implementation class bool m_online; public: - NG_NetworkDeviceInterface() {}; - virtual ~NG_NetworkDeviceInterface() {}; + NG_NetworkDeviceInterface() {} + virtual ~NG_NetworkDeviceInterface() {} virtual void NextFrame()=0; diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 8d587cf39f6..6c6ce94d8d5 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -1507,8 +1507,8 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, /* double lookup */ const int *index_mf_to_mpoly = (const int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == false) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH; @@ -1816,8 +1816,8 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA /* double lookup */ const int *index_mf_to_mpoly = (const int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); - if ((index_mf_to_mpoly && index_mp_to_orig) == false) { - index_mf_to_mpoly = index_mp_to_orig = NULL; + if (index_mf_to_mpoly == NULL) { + index_mp_to_orig = NULL; } MFace *mf; diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp index d1a8143fa88..d1fabba18f9 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp @@ -85,8 +85,9 @@ void DummyPhysicsEnvironment::setGravity(float x,float y,float z) { } - - +void DummyPhysicsEnvironment::getGravity(PHY__Vector3& grav) +{ +} diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h index 233c4412d9e..5ce34bdf7cf 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h @@ -56,6 +56,7 @@ public: virtual float getFixedTimeStep(); virtual void setGravity(float x,float y,float z); + virtual void getGravity(PHY__Vector3& grav); virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type, float pivotX,float pivotY,float pivotZ, diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h index 077d225903c..bfbe570ad0c 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h @@ -143,6 +143,7 @@ class PHY_IPhysicsEnvironment virtual void setUseEpa(bool epa) {} virtual void setGravity(float x,float y,float z)=0; + virtual void getGravity(PHY__Vector3& grav) = 0; virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type, float pivotX,float pivotY,float pivotZ, diff --git a/source/gameengine/Rasterizer/RAS_ICanvas.h b/source/gameengine/Rasterizer/RAS_ICanvas.h index 53195d79768..60b9f052075 100644 --- a/source/gameengine/Rasterizer/RAS_ICanvas.h +++ b/source/gameengine/Rasterizer/RAS_ICanvas.h @@ -59,7 +59,7 @@ public: virtual ~RAS_ICanvas( ) { - }; + } virtual void diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h index 16ecffb9a32..4c72f128817 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h @@ -189,6 +189,8 @@ class RAS_MeshMaterial public: RAS_MeshSlot *m_baseslot; class RAS_MaterialBucket *m_bucket; + + /* the KX_GameObject is used as a key here */ CTR_Map m_slots; diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript index 5f3af7360ff..63b28a90412 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript @@ -8,7 +8,7 @@ defs = [ 'GLEW_STATIC' ] incs = '. #intern/string #intern/moto/include #source/gameengine/Rasterizer #source/gameengine/BlenderRoutines ' incs += ' #intern/container #source/blender/gpu #extern/glew/include ' + env['BF_OPENGL_INC'] incs += ' #source/blender/gameengine/Ketsji #source/gameengine/SceneGraph #source/blender/makesdna #source/blender/blenkernel' -incs += ' #intern/guardedalloc #source/blender/blenlib #source/gameengine/BlenderRoutines' +incs += ' #intern/guardedalloc #source/blender/blenlib' if env['WITH_BF_CXX_GUARDEDALLOC']: defs.append('WITH_CXX_GUARDEDALLOC') diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp index b60fae73e2a..945644ff3e6 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.cpp +++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp @@ -63,10 +63,10 @@ const MT_Point3& RAS_TexVert::xyz() void RAS_TexVert::SetRGBA(const MT_Vector4& rgba) { unsigned char *colp = (unsigned char*) &m_rgba; - colp[0] = (unsigned char) (rgba[0]*255.0f); - colp[1] = (unsigned char) (rgba[1]*255.0f); - colp[2] = (unsigned char) (rgba[2]*255.0f); - colp[3] = (unsigned char) (rgba[3]*255.0f); + colp[0] = (unsigned char) (rgba[0] * 255.0); + colp[1] = (unsigned char) (rgba[1] * 255.0); + colp[2] = (unsigned char) (rgba[2] * 255.0); + colp[3] = (unsigned char) (rgba[3] * 255.0); } @@ -75,21 +75,32 @@ void RAS_TexVert::SetXYZ(const MT_Point3& xyz) xyz.getValue(m_localxyz); } -void RAS_TexVert::SetXYZ(const float *xyz) +void RAS_TexVert::SetXYZ(const float xyz[3]) { m_localxyz[0] = xyz[0]; m_localxyz[1] = xyz[1]; m_localxyz[2] = xyz[2]; } -void RAS_TexVert::SetUV(const MT_Point2& uv) +void RAS_TexVert::SetUV1(const MT_Point2& uv) { uv.getValue(m_uv1); } +void RAS_TexVert::SetUV1(const float uv[3]) +{ + m_uv1[0] = uv[0]; + m_uv1[1] = uv[1]; +} + void RAS_TexVert::SetUV2(const MT_Point2& uv) { uv.getValue(m_uv2); } +void RAS_TexVert::SetUV2(const float uv[3]) +{ + m_uv2[0] = uv[0]; + m_uv2[1] = uv[1]; +} void RAS_TexVert::SetRGBA(const unsigned int rgba) { @@ -151,3 +162,12 @@ void RAS_TexVert::Transform(const MT_Matrix4x4& mat, const MT_Matrix4x4& nmat) SetTangent((nmat*MT_Vector4(m_tangent[0], m_tangent[1], m_tangent[2], 1.0)).getValue()); } +void RAS_TexVert::TransformUV1(const MT_Matrix4x4& mat) +{ + SetUV1((mat * MT_Vector4(m_uv1[0], m_uv1[1], 0.0, 1.0)).getValue()); +} + +void RAS_TexVert::TransformUV2(const MT_Matrix4x4& mat) +{ + SetUV2((mat * MT_Vector4(m_uv2[0], m_uv2[1], 0.0, 1.0)).getValue()); +} diff --git a/source/gameengine/Rasterizer/RAS_TexVert.h b/source/gameengine/Rasterizer/RAS_TexVert.h index 889769da5ed..98ea4dd60aa 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.h +++ b/source/gameengine/Rasterizer/RAS_TexVert.h @@ -122,9 +122,11 @@ public: } void SetXYZ(const MT_Point3& xyz); - void SetXYZ(const float *xyz); - void SetUV(const MT_Point2& uv); + void SetXYZ(const float xyz[3]); + void SetUV1(const MT_Point2& uv); void SetUV2(const MT_Point2& uv); + void SetUV1(const float uv[2]); + void SetUV2(const float uv[2]); void SetRGBA(const unsigned int rgba); void SetNormal(const MT_Vector3& normal); @@ -137,6 +139,8 @@ public: void Transform(const class MT_Matrix4x4& mat, const class MT_Matrix4x4& nmat); + void TransformUV1(const MT_Matrix4x4& mat); + void TransformUV2(const MT_Matrix4x4& mat); // compare two vertices, to test if they can be shared, used for // splitting up based on uv's, colors, etc diff --git a/source/gameengine/SceneGraph/SG_IObject.h b/source/gameengine/SceneGraph/SG_IObject.h index 885eb8e1e90..72a04064834 100644 --- a/source/gameengine/SceneGraph/SG_IObject.h +++ b/source/gameengine/SceneGraph/SG_IObject.h @@ -127,8 +127,8 @@ struct SG_Callbacks m_schedulefunc(NULL), m_reschedulefunc(NULL) { - }; - + } + SG_Callbacks( SG_ReplicationNewCallback repfunc, SG_DestructionNewCallback destructfunc, @@ -142,7 +142,7 @@ struct SG_Callbacks m_schedulefunc(schedulefunc), m_reschedulefunc(reschedulefunc) { - }; + } SG_ReplicationNewCallback m_replicafunc; SG_DestructionNewCallback m_destructionfunc; @@ -152,8 +152,8 @@ struct SG_Callbacks }; /** -base object that can be part of the scenegraph. -*/ + * base object that can be part of the scenegraph. + */ class SG_IObject : public SG_QList { private : diff --git a/source/gameengine/VideoTexture/BlendType.h b/source/gameengine/VideoTexture/BlendType.h index e19aadc49d2..28eebe07789 100644 --- a/source/gameengine/VideoTexture/BlendType.h +++ b/source/gameengine/VideoTexture/BlendType.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2006 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2006 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file BlendType.h * \ingroup bgevideotex */ - + #ifndef __BLENDTYPE_H__ #define __BLENDTYPE_H__ diff --git a/source/gameengine/VideoTexture/Common.h b/source/gameengine/VideoTexture/Common.h index e6e0ffa1ebc..90f7e66452a 100644 --- a/source/gameengine/VideoTexture/Common.h +++ b/source/gameengine/VideoTexture/Common.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2006 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2006 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file VideoTexture/Common.h * \ingroup bgevideotex */ - + #if defined WIN32 #define WINDOWS_LEAN_AND_MEAN #endif diff --git a/source/gameengine/VideoTexture/Exception.cpp b/source/gameengine/VideoTexture/Exception.cpp index 8609cd73875..8b8918d8141 100644 --- a/source/gameengine/VideoTexture/Exception.cpp +++ b/source/gameengine/VideoTexture/Exception.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2006 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2006 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/Exception.cpp * \ingroup bgevideotex diff --git a/source/gameengine/VideoTexture/Exception.h b/source/gameengine/VideoTexture/Exception.h index bc08742de8d..e0c1fdd568d 100644 --- a/source/gameengine/VideoTexture/Exception.h +++ b/source/gameengine/VideoTexture/Exception.h @@ -1,30 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2006 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ - + * ***** 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. + * + * Copyright (c) 2006 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file Exception.h * \ingroup bgevideotex */ - + #ifndef __EXCEPTION_H__ #define __EXCEPTION_H__ diff --git a/source/gameengine/VideoTexture/FilterBase.cpp b/source/gameengine/VideoTexture/FilterBase.cpp index 6ec5e237ac2..a232bcc1201 100644 --- a/source/gameengine/VideoTexture/FilterBase.cpp +++ b/source/gameengine/VideoTexture/FilterBase.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/FilterBase.cpp * \ingroup bgevideotex diff --git a/source/gameengine/VideoTexture/FilterBase.h b/source/gameengine/VideoTexture/FilterBase.h index 98bc495375a..f8fe2c772f0 100644 --- a/source/gameengine/VideoTexture/FilterBase.h +++ b/source/gameengine/VideoTexture/FilterBase.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file FilterBase.h * \ingroup bgevideotex */ - + #ifndef __FILTERBASE_H__ #define __FILTERBASE_H__ diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.cpp b/source/gameengine/VideoTexture/FilterBlueScreen.cpp index 8559e8f87f4..662ecabd283 100644 --- a/source/gameengine/VideoTexture/FilterBlueScreen.cpp +++ b/source/gameengine/VideoTexture/FilterBlueScreen.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/FilterBlueScreen.cpp * \ingroup bgevideotex @@ -83,18 +87,21 @@ static PyObject *getColor (PyFilter *self, void *closure) static int setColor (PyFilter *self, PyObject *value, void *closure) { // check validity of parameter - if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 3 - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1)) - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 2))) + if (value == NULL || + !(PyTuple_Check(value) || PyList_Check(value)) || + PySequence_Fast_GET_SIZE(value) != 3 || + !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) || + !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1)) || + !PyLong_Check(PySequence_Fast_GET_ITEM(value, 2))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 3 ints"); return -1; } // set color - getFilter(self)->setColor((unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), - (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))), - (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)))); + getFilter(self)->setColor( + (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 0))), + (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 1))), + (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 2)))); // success return 0; } @@ -110,16 +117,19 @@ static PyObject *getLimits (PyFilter *self, void *closure) static int setLimits (PyFilter *self, PyObject *value, void *closure) { // check validity of parameter - if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 2 - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) + if (value == NULL || + !(PyTuple_Check(value) || PyList_Check(value)) || + PySequence_Fast_GET_SIZE(value) != 2 || + !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) || + !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints"); return -1; } // set limits - getFilter(self)->setLimits((unsigned short)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), - (unsigned short)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1)))); + getFilter(self)->setLimits( + (unsigned short)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 0))), + (unsigned short)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 1)))); // success return 0; } @@ -159,14 +169,14 @@ PyTypeObject FilterBlueScreenType = 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/ "Filter for Blue Screen objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - NULL, /* tp_methods */ - 0, /* tp_members */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + NULL, /* tp_methods */ + 0, /* tp_members */ filterBSGetSets, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.h b/source/gameengine/VideoTexture/FilterBlueScreen.h index 28ab16d966e..5a90590a39d 100644 --- a/source/gameengine/VideoTexture/FilterBlueScreen.h +++ b/source/gameengine/VideoTexture/FilterBlueScreen.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of blendTex library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of blendTex library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file FilterBlueScreen.h * \ingroup bgevideotex */ - + #ifndef __FILTERBLUESCREEN_H__ #define __FILTERBLUESCREEN_H__ diff --git a/source/gameengine/VideoTexture/FilterColor.cpp b/source/gameengine/VideoTexture/FilterColor.cpp index 35a6414f383..e4101b5587d 100644 --- a/source/gameengine/VideoTexture/FilterColor.cpp +++ b/source/gameengine/VideoTexture/FilterColor.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/FilterColor.cpp * \ingroup bgevideotex @@ -147,7 +151,7 @@ static int setMatrix (PyFilter *self, PyObject *value, void *closure) valid = PyLong_Check(PySequence_Fast_GET_ITEM(row, c)); // if it is valid, save it in matrix if (valid) - mat[r][c] = short(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(row, c))); + mat[r][c] = short(PyLong_AsLong(PySequence_Fast_GET_ITEM(row, c))); } } // if parameter is not valid, report error @@ -280,7 +284,7 @@ static int setLevels (PyFilter *self, PyObject *value, void *closure) valid = PyLong_Check(PySequence_Fast_GET_ITEM(row, c)); // if it is valid, save it in matrix if (valid) - lev[r][c] = (unsigned short)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(row, c))); + lev[r][c] = (unsigned short)(PyLong_AsLong(PySequence_Fast_GET_ITEM(row, c))); } } // if parameter is not valid, report error diff --git a/source/gameengine/VideoTexture/FilterColor.h b/source/gameengine/VideoTexture/FilterColor.h index cd61900bbda..350f7270874 100644 --- a/source/gameengine/VideoTexture/FilterColor.h +++ b/source/gameengine/VideoTexture/FilterColor.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of blendTex library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of blendTex library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file FilterColor.h * \ingroup bgevideotex */ - + #ifndef __FILTERCOLOR_H__ #define __FILTERCOLOR_H__ diff --git a/source/gameengine/VideoTexture/FilterNormal.cpp b/source/gameengine/VideoTexture/FilterNormal.cpp index 03c500a7e14..ba963d93079 100644 --- a/source/gameengine/VideoTexture/FilterNormal.cpp +++ b/source/gameengine/VideoTexture/FilterNormal.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/FilterNormal.cpp * \ingroup bgevideotex @@ -81,7 +85,7 @@ static int setColor (PyFilter *self, PyObject *value, void *closure) return -1; } // set color index - getFilter(self)->setColor((unsigned short)(PyLong_AsSsize_t(value))); + getFilter(self)->setColor((unsigned short)(PyLong_AsLong(value))); // success return 0; } diff --git a/source/gameengine/VideoTexture/FilterNormal.h b/source/gameengine/VideoTexture/FilterNormal.h index 19664e8b5f2..b21afb3ec26 100644 --- a/source/gameengine/VideoTexture/FilterNormal.h +++ b/source/gameengine/VideoTexture/FilterNormal.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of blendTex library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of blendTex library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file FilterNormal.h * \ingroup bgevideotex */ - + #ifndef __FILTERNORMAL_H__ #define __FILTERNORMAL_H__ diff --git a/source/gameengine/VideoTexture/FilterSource.cpp b/source/gameengine/VideoTexture/FilterSource.cpp index e5fe4711cff..1fac87f2b04 100644 --- a/source/gameengine/VideoTexture/FilterSource.cpp +++ b/source/gameengine/VideoTexture/FilterSource.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/FilterSource.cpp * \ingroup bgevideotex diff --git a/source/gameengine/VideoTexture/FilterSource.h b/source/gameengine/VideoTexture/FilterSource.h index cb9e22a133d..f1d2615ee32 100644 --- a/source/gameengine/VideoTexture/FilterSource.h +++ b/source/gameengine/VideoTexture/FilterSource.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of blendTex library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of blendTex library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file FilterSource.h * \ingroup bgevideotex */ - + #ifndef __FILTERSOURCE_H__ #define __FILTERSOURCE_H__ diff --git a/source/gameengine/VideoTexture/ImageBase.cpp b/source/gameengine/VideoTexture/ImageBase.cpp index de54d8e8940..3b6dec21e52 100644 --- a/source/gameengine/VideoTexture/ImageBase.cpp +++ b/source/gameengine/VideoTexture/ImageBase.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/ImageBase.cpp * \ingroup bgevideotex diff --git a/source/gameengine/VideoTexture/ImageBase.h b/source/gameengine/VideoTexture/ImageBase.h index a9f25f61406..3bb9c8cb090 100644 --- a/source/gameengine/VideoTexture/ImageBase.h +++ b/source/gameengine/VideoTexture/ImageBase.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of blendTex library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of blendTex library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file ImageBase.h * \ingroup bgevideotex */ - + #ifndef __IMAGEBASE_H__ #define __IMAGEBASE_H__ diff --git a/source/gameengine/VideoTexture/ImageBuff.cpp b/source/gameengine/VideoTexture/ImageBuff.cpp index eec0bccbe56..1593a08bb4b 100644 --- a/source/gameengine/VideoTexture/ImageBuff.cpp +++ b/source/gameengine/VideoTexture/ImageBuff.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/ImageBuff.cpp * \ingroup bgevideotex diff --git a/source/gameengine/VideoTexture/ImageBuff.h b/source/gameengine/VideoTexture/ImageBuff.h index b2bdbc17dc9..19299506747 100644 --- a/source/gameengine/VideoTexture/ImageBuff.h +++ b/source/gameengine/VideoTexture/ImageBuff.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file ImageBuff.h * \ingroup bgevideotex */ - + #ifndef __IMAGEBUFF_H__ #define __IMAGEBUFF_H__ diff --git a/source/gameengine/VideoTexture/ImageMix.cpp b/source/gameengine/VideoTexture/ImageMix.cpp index f09454a517b..27c4fed6fe6 100644 --- a/source/gameengine/VideoTexture/ImageMix.cpp +++ b/source/gameengine/VideoTexture/ImageMix.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/ImageMix.cpp * \ingroup bgevideotex diff --git a/source/gameengine/VideoTexture/ImageMix.h b/source/gameengine/VideoTexture/ImageMix.h index 2746635c611..712efde7dd4 100644 --- a/source/gameengine/VideoTexture/ImageMix.h +++ b/source/gameengine/VideoTexture/ImageMix.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file ImageMix.h * \ingroup bgevideotex */ - + #ifndef __IMAGEMIX_H__ #define __IMAGEMIX_H__ diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index 85857165403..f778f840864 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/ImageRender.cpp * \ingroup bgevideotex @@ -356,10 +360,11 @@ static int setBackground (PyImage *self, PyObject *value, void *closure) return -1; } // set background color - getImageRender(self)->setBackground((unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), - (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))), - (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2))), - (unsigned char)(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 3)))); + getImageRender(self)->setBackground( + (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 0))), + (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 1))), + (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 2))), + (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 3)))); // success return 0; } @@ -375,7 +380,7 @@ static PyMethodDef imageRenderMethods[] = static PyGetSetDef imageRenderGetSets[] = { {(char*)"background", (getter)getBackground, (setter)setBackground, (char*)"background color", NULL}, - // attribute from ImageViewport + // attribute from ImageViewport {(char*)"capsize", (getter)ImageViewport_getCaptureSize, (setter)ImageViewport_setCaptureSize, (char*)"size of render area", NULL}, {(char*)"alpha", (getter)ImageViewport_getAlpha, (setter)ImageViewport_setAlpha, (char*)"use alpha in texture", NULL}, {(char*)"whole", (getter)ImageViewport_getWhole, (setter)ImageViewport_setWhole, (char*)"use whole viewport to render", NULL}, diff --git a/source/gameengine/VideoTexture/ImageRender.h b/source/gameengine/VideoTexture/ImageRender.h index df6337e1c24..27882a9d117 100644 --- a/source/gameengine/VideoTexture/ImageRender.h +++ b/source/gameengine/VideoTexture/ImageRender.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file ImageRender.h * \ingroup bgevideotex */ - + #ifndef __IMAGERENDER_H__ #define __IMAGERENDER_H__ diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp index af44e394fce..5fc388bdefb 100644 --- a/source/gameengine/VideoTexture/ImageViewport.cpp +++ b/source/gameengine/VideoTexture/ImageViewport.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/ImageViewport.cpp * \ingroup bgevideotex @@ -85,7 +89,7 @@ void ImageViewport::setWhole (bool whole) setPosition(); } -void ImageViewport::setCaptureSize (short * size) +void ImageViewport::setCaptureSize (short size[2]) { m_whole = false; if (size == NULL) @@ -105,7 +109,7 @@ void ImageViewport::setCaptureSize (short * size) } // set position of capture rectangle -void ImageViewport::setPosition (GLint * pos) +void ImageViewport::setPosition (GLint pos[2]) { // if new position is not provided, use existing position if (pos == NULL) pos = m_position; @@ -254,25 +258,30 @@ int ImageViewport_setAlpha (PyImage *self, PyObject *value, void *closure) // get position static PyObject *ImageViewport_getPosition (PyImage *self, void *closure) { - return Py_BuildValue("(ii)", getImageViewport(self)->getPosition()[0], - getImageViewport(self)->getPosition()[1]); + GLint *pos = getImageViewport(self)->getPosition(); + PyObject *ret = PyTuple_New(2); + PyTuple_SET_ITEM(ret, 0, PyLong_FromLong(pos[0])); + PyTuple_SET_ITEM(ret, 1, PyLong_FromLong(pos[1])); + return ret; } // set position static int ImageViewport_setPosition (PyImage *self, PyObject *value, void *closure) { // check validity of parameter - if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 2 - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) + if (value == NULL || + !(PyTuple_Check(value) || PyList_Check(value)) || + PySequence_Fast_GET_SIZE(value) != 2 || + !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) || + !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints"); return -1; } // set position - GLint pos [] = { - GLint(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), - GLint(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))) + GLint pos[2] = { + GLint(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 0))), + GLint(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 1))) }; getImageViewport(self)->setPosition(pos); // success @@ -282,25 +291,30 @@ static int ImageViewport_setPosition (PyImage *self, PyObject *value, void *clos // get capture size PyObject *ImageViewport_getCaptureSize (PyImage *self, void *closure) { - return Py_BuildValue("(ii)", getImageViewport(self)->getCaptureSize()[0], - getImageViewport(self)->getCaptureSize()[1]); + short *size = getImageViewport(self)->getCaptureSize(); + PyObject *ret = PyTuple_New(2); + PyTuple_SET_ITEM(ret, 0, PyLong_FromLong(size[0])); + PyTuple_SET_ITEM(ret, 1, PyLong_FromLong(size[1])); + return ret; } // set capture size int ImageViewport_setCaptureSize (PyImage *self, PyObject *value, void *closure) { // check validity of parameter - if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 2 - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) + if (value == NULL || + !(PyTuple_Check(value) || PyList_Check(value)) || + PySequence_Fast_GET_SIZE(value) != 2 || + !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) || + !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) { PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 ints"); return -1; } // set capture size - short size [] = { - short(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 0))), - short(PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 1))) + short size[2] = { + short(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 0))), + short(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 1))) }; try { diff --git a/source/gameengine/VideoTexture/ImageViewport.h b/source/gameengine/VideoTexture/ImageViewport.h index 198655c6ebf..5afd4654d62 100644 --- a/source/gameengine/VideoTexture/ImageViewport.h +++ b/source/gameengine/VideoTexture/ImageViewport.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file ImageViewport.h * \ingroup bgevideotex */ - + #ifndef __IMAGEVIEWPORT_H__ #define __IMAGEVIEWPORT_H__ @@ -56,12 +60,12 @@ public: /// get capture size in viewport short * getCaptureSize (void) { return m_capSize; } /// set capture size in viewport - void setCaptureSize (short * size = NULL); + void setCaptureSize (short size[2] = NULL); /// get position in viewport GLint * getPosition (void) { return m_position; } /// set position in viewport - void setPosition (GLint * pos = NULL); + void setPosition (GLint pos[2] = NULL); protected: /// frame buffer rectangle diff --git a/source/gameengine/VideoTexture/PyTypeList.cpp b/source/gameengine/VideoTexture/PyTypeList.cpp index 9fe98544961..96ac1cc5b6b 100644 --- a/source/gameengine/VideoTexture/PyTypeList.cpp +++ b/source/gameengine/VideoTexture/PyTypeList.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of blendTex library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of blendTex library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/PyTypeList.cpp * \ingroup bgevideotex diff --git a/source/gameengine/VideoTexture/PyTypeList.h b/source/gameengine/VideoTexture/PyTypeList.h index 4872b3c3d5c..b36f11ed75a 100644 --- a/source/gameengine/VideoTexture/PyTypeList.h +++ b/source/gameengine/VideoTexture/PyTypeList.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of blendTex library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of blendTex library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file PyTypeList.h * \ingroup bgevideotex */ - + #ifndef __PYTYPELIST_H__ #define __PYTYPELIST_H__ diff --git a/source/gameengine/VideoTexture/Texture.cpp b/source/gameengine/VideoTexture/Texture.cpp index f58d17f949c..98d36d19ddf 100644 --- a/source/gameengine/VideoTexture/Texture.cpp +++ b/source/gameengine/VideoTexture/Texture.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/Texture.cpp * \ingroup bgevideotex diff --git a/source/gameengine/VideoTexture/Texture.h b/source/gameengine/VideoTexture/Texture.h index cc265725b29..157eea56c09 100644 --- a/source/gameengine/VideoTexture/Texture.h +++ b/source/gameengine/VideoTexture/Texture.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2006 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2006 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file VideoTexture/Texture.h * \ingroup bgevideotex */ - + #ifndef __TEXTURE_H__ #define __TEXTURE_H__ diff --git a/source/gameengine/VideoTexture/VideoBase.cpp b/source/gameengine/VideoTexture/VideoBase.cpp index 1eb2e830d37..576e358fe75 100644 --- a/source/gameengine/VideoTexture/VideoBase.cpp +++ b/source/gameengine/VideoTexture/VideoBase.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/VideoBase.cpp * \ingroup bgevideotex @@ -180,7 +184,7 @@ int Video_setRepeat(PyImage *self, PyObject *value, void *closure) return -1; } // set repeat - getVideo(self)->setRepeat(int(PyLong_AsSsize_t(value))); + getVideo(self)->setRepeat(int(PyLong_AsLong(value))); // success return 0; } diff --git a/source/gameengine/VideoTexture/VideoBase.h b/source/gameengine/VideoTexture/VideoBase.h index 4cf913d755d..9880165c198 100644 --- a/source/gameengine/VideoTexture/VideoBase.h +++ b/source/gameengine/VideoTexture/VideoBase.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file VideoBase.h * \ingroup bgevideotex */ - + #ifndef __VIDEOBASE_H__ #define __VIDEOBASE_H__ diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp index 3f42d5c4fed..8976a21376a 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp +++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/VideoFFmpeg.cpp * \ingroup bgevideotex @@ -1138,7 +1142,7 @@ static int VideoFFmpeg_setPreseek(PyImage *self, PyObject *value, void *closure) return -1; } // set preseek - getFFmpeg(self)->setPreseek(PyLong_AsSsize_t(value)); + getFFmpeg(self)->setPreseek(PyLong_AsLong(value)); // success return 0; } diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.h b/source/gameengine/VideoTexture/VideoFFmpeg.h index d5b575851ee..92043bb1f74 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.h +++ b/source/gameengine/VideoTexture/VideoFFmpeg.h @@ -1,29 +1,33 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2007 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2007 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file VideoFFmpeg.h * \ingroup bgevideotex */ - + #ifndef __VIDEOFFMPEG_H__ #define __VIDEOFFMPEG_H__ diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp index dd9d83c043f..72415026bb9 100644 --- a/source/gameengine/VideoTexture/blendVideoTex.cpp +++ b/source/gameengine/VideoTexture/blendVideoTex.cpp @@ -1,24 +1,28 @@ /* ------------------------------------------------------------------------------ -This source file is part of VideoTexture library - -Copyright (c) 2006 The Zdeno Ash Miklas - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU Lesser 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place - Suite 330, Boston, MA 02111-1307, USA, or go to -http://www.gnu.org/copyleft/lesser.txt. ------------------------------------------------------------------------------ -*/ + * ***** 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. + * + * Copyright (c) 2006 The Zdeno Ash Miklas + * + * This source file is part of VideoTexture library + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ /** \file gameengine/VideoTexture/blendVideoTex.cpp * \ingroup bgevideotex diff --git a/source/tests/bl_rst_completeness.py b/source/tests/bl_rst_completeness.py new file mode 100644 index 00000000000..e9e2779bda8 --- /dev/null +++ b/source/tests/bl_rst_completeness.py @@ -0,0 +1,159 @@ +# ##### 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. +# +# ##### END GPL LICENSE BLOCK ##### + +# + +# run this script in the game engine. +# or on the command line with... +# ./blender.bin --background -noaudio --python source/tests/bl_rst_completeness.py + +# Paste this into the bge and run on an always actuator. +''' +filepath = "/dsk/data/src/blender/blender/source/tests/bl_rst_completeness.py" +exec(compile(open(filepath).read(), filepath, 'exec')) +''' + +import os + +THIS_DIR = os.path.dirname(__file__) +RST_DIR = os.path.normpath(os.path.join(THIS_DIR, "..", "..", "doc", "python_api", "rst")) + +import sys +sys.path.append(THIS_DIR) + +import rst_to_doctree_mini + +try: + import bge +except: + bge = None + +# (file, module) +modules = ( + ("bge.constraints.rst", "bge.constraints", False), + ("bge.events.rst", "bge.events", False), + ("bge.logic.rst", "bge.logic", False), + ("bge.render.rst", "bge.render", False), + ("bge.texture.rst", "bge.texture", False), + ("bge.types.rst", "bge.types", False), + + ("bgl.rst", "bgl", True), + ("gpu.rst", "gpu", False), +) + +def is_directive_pydata(filepath, directive): + if directive.type in {"function", "method", "class", "attribute", "data"}: + return True + elif directive.type in {"module", "note", "warning", "code-block", "hlist", "seealso"}: + return False + elif directive.type in {"literalinclude"}: # TODO + return False + else: + print(directive_to_str(filepath, directive), end=" ") + print("unknown directive type %r" % directive.type) + return False + + +def directive_to_str(filepath, directive): + return "%s:%d:%d:" % (filepath, directive.line + 1, directive.indent) + + +def directive_members_dict(filepath, directive_members): + return {directive.value_strip: directive for directive in directive_members + if is_directive_pydata(filepath, directive)} + + +def module_validate(filepath, mod, mod_name, doctree, partial_ok): + # RST member missing from MODULE ??? + for directive in doctree: + # print(directive.type) + if is_directive_pydata(filepath, directive): + attr = directive.value_strip + has_attr = hasattr(mod, attr) + ok = False + if not has_attr: + # so we can have glNormal docs cover glNormal3f + if partial_ok: + for s in dir(mod): + if s.startswith(attr): + ok = True + break + + if not ok: + print(directive_to_str(filepath, directive), end=" ") + print("rst contains non existing member %r" % attr) + + # if its a class, scan down the class... + # print(directive.type) + if has_attr: + if directive.type == "class": + cls = getattr(mod, attr) + # print("directive: ", directive) + for directive_child in directive.members: + # print("directive_child: ", directive_child) + if is_directive_pydata(filepath, directive_child): + attr_child = directive_child.value_strip + if attr_child not in cls.__dict__: + attr_id = "%s.%s" % (attr, attr_child) + print(directive_to_str(filepath, directive_child), end=" ") + print("rst contains non existing class member %r" % attr_id) + + + # MODULE member missing from RST ??? + doctree_dict = directive_members_dict(filepath, doctree) + for attr in dir(mod): + if attr.startswith("_"): + continue + + directive = doctree_dict.get(attr) + if directive is None: + print("module contains undocumented member %r from %r" % ("%s.%s" % (mod_name, attr), filepath)) + else: + if directive.type == "class": + directive_dict = directive_members_dict(filepath, directive.members) + cls = getattr(mod, attr) + for attr_child in cls.__dict__.keys(): + if attr_child.startswith("_"): + continue + if attr_child not in directive_dict: + attr_id = "%s.%s.%s" % (mod_name, attr, attr_child), filepath + print("module contains undocumented member %r from %r" % attr_id) + + +def main(): + + if bge is None: + print("Skipping BGE modules!") + + for filename, modname, partial_ok in modules: + if bge is None and modname.startswith("bge"): + continue + + filepath = os.path.join(RST_DIR, filename) + if not os.path.exists(filepath): + raise Exception("%r not found" % filepath) + + doctree = rst_to_doctree_mini.parse_rst_py(filepath) + __import__(modname) + mod = sys.modules[modname] + + module_validate(filepath, mod, modname, doctree, partial_ok) + + +if __name__ == "__main__": + main() diff --git a/source/tests/bl_run_operators.py b/source/tests/bl_run_operators.py index f792b83a8cd..5bb25537458 100644 --- a/source/tests/bl_run_operators.py +++ b/source/tests/bl_run_operators.py @@ -35,13 +35,16 @@ op_blacklist = ( "*.open_*", "*.link_append", "render.render", + "render.play_rendered_anim", "*.*_export", "*.*_import", "wm.blenderplayer_start", "wm.url_open", "wm.doc_view", "wm.path_open", - "help.operator_cheat_sheet", + "wm.theme_install", + "wm.context_*", + "wm.operator_cheat_sheet", "wm.keyconfig_test", # just annoying - but harmless "wm.memory_statistics", # another annoying one "console.*", # just annoying - but harmless diff --git a/source/tests/rst_to_doctree_mini.py b/source/tests/rst_to_doctree_mini.py new file mode 100644 index 00000000000..181037299cf --- /dev/null +++ b/source/tests/rst_to_doctree_mini.py @@ -0,0 +1,91 @@ +# ##### 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. +# +# ##### END GPL LICENSE BLOCK ##### + +# + +# Module with function to extract a doctree from an reStructuredText file. +# Named 'Mini' because we only parse the minimum data needed to check +# Python classes, methods and attributes match up to those in existing modules. +# (To test for documentation completeness) + +# note: literalinclude's are not followed. +# could be nice to add but not really needed either right now. + +import collections + +Directive = collections.namedtuple('Directive', + ("type", + "value", + "value_strip", + "line", + "indent", + "members")) + + +def parse_rst_py(filepath): + import re + + # Get the prefix assuming the line is lstrip()'d + # ..foo:: bar + # --> + # ("foo", "bar") + re_prefix = re.compile(r"^\.\.\s([a-zA-Z09\-]+)::\s*(.*)\s*$") + + tree = collections.defaultdict(list) + indent_map = {} + indent_prev = 0 + f = open(filepath, encoding="utf-8") + indent_lists = [] + for i, line in enumerate(f): + line_strip = line.lstrip() + # ^\.\.\s[a-zA-Z09\-]+::.*$ + #if line.startswith(".. "): + march = re_prefix.match(line_strip) + + if march: + directive, value = march.group(1, 2) + indent = len(line) - len(line_strip) + value_strip = value.replace("(", " ").split() + value_strip = value_strip[0] if value_strip else "" + + item = Directive(type=directive, + value=value, + value_strip=value_strip, + line=i, + indent=indent, + members=[]) + + tree[indent].append(item) + if indent_prev < indent: + indent_map[indent] = indent_prev + if indent > 0: + tree[indent_map[indent]][-1].members.append(item) + indent_prev = indent + f.close() + + return tree[0] + + +if __name__ == "__main__": + # not intended use, but may as well print rst files passed as a test. + import sys + for arg in sys.argv: + if arg.lower().endswith((".txt", ".rst")): + items = parse_rst_py(arg) + for i in items: + print(i) From ec870eb2144391dbf0aed9d23b4e79c9dd982003 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 10 Dec 2012 16:38:13 +0000 Subject: [PATCH 159/160] code cleanup: camera tracking - Moved keyframes and refirement flags into reconstruction options structure - Moved distortion coefficients and other camera intrinsics into own structure - Cleaned up reconstruction functions in libmv c-api --- extern/libmv/libmv-capi.cpp | 128 +++++++++++++------- extern/libmv/libmv-capi.h | 38 ++++-- source/blender/blenkernel/intern/tracking.c | 48 +++++--- 3 files changed, 140 insertions(+), 74 deletions(-) diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index 8e483abd386..ffe4b6ebf3d 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -552,40 +552,78 @@ static void libmv_solveRefineIntrinsics(libmv::Tracks *tracks, libmv::CameraIntr reconstruction, intrinsics); } -libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyframe1, int keyframe2, - int refine_intrinsics, double focal_length, double principal_x, double principal_y, - double k1, double k2, double k3, struct libmv_reconstructionOptions *options, - reconstruct_progress_update_cb progress_update_callback, void *callback_customdata) +static void cameraIntrinsicsFromOptions(libmv::CameraIntrinsics *camera_intrinsics, + libmv_cameraIntrinsicsOptions *camera_intrinsics_options) +{ + camera_intrinsics->SetFocalLength(camera_intrinsics_options->focal_length, + camera_intrinsics_options->focal_length); + + camera_intrinsics->SetPrincipalPoint(camera_intrinsics_options->principal_point_x, + camera_intrinsics_options->principal_point_y); + + camera_intrinsics->SetRadialDistortion(camera_intrinsics_options->k1, + camera_intrinsics_options->k2, + camera_intrinsics_options->k3); +} + +static libmv::Tracks getNormalizedTracks(libmv::Tracks *tracks, libmv::CameraIntrinsics *camera_intrinsics) +{ + libmv::vector markers = tracks->AllMarkers(); + + for (int i = 0; i < markers.size(); ++i) { + camera_intrinsics->InvertIntrinsics(markers[i].x, markers[i].y, + &(markers[i].x), &(markers[i].y)); + } + + return libmv::Tracks(markers); +} + +static void finishReconstruction(libmv::Tracks *tracks, libmv::CameraIntrinsics *camera_intrinsics, + libmv_Reconstruction *libmv_reconstruction, + reconstruct_progress_update_cb progress_update_callback, + void *callback_customdata) { - /* Invert the camera intrinsics. */ - libmv::vector markers = ((libmv::Tracks*)tracks)->AllMarkers(); - libmv_Reconstruction *libmv_reconstruction = new libmv_Reconstruction(); libmv::EuclideanReconstruction *reconstruction = &libmv_reconstruction->reconstruction; - libmv::CameraIntrinsics *intrinsics = &libmv_reconstruction->intrinsics; - libmv::ReconstructionOptions reconstruction_options; + + /* reprojection error calculation */ + progress_update_callback(callback_customdata, 1.0, "Finishing solution"); + libmv_reconstruction->tracks = *tracks; + libmv_reconstruction->error = libmv::EuclideanReprojectionError(*tracks, *reconstruction, *camera_intrinsics); +} + +libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *libmv_tracks, + libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options, + libmv_reconstructionOptions *libmv_reconstruction_options, + reconstruct_progress_update_cb progress_update_callback, + void *callback_customdata) +{ + libmv_Reconstruction *libmv_reconstruction = new libmv_Reconstruction(); + + libmv::Tracks *tracks = ((libmv::Tracks *) libmv_tracks); + libmv::EuclideanReconstruction *reconstruction = &libmv_reconstruction->reconstruction; + libmv::CameraIntrinsics *camera_intrinsics = &libmv_reconstruction->intrinsics; ReconstructUpdateCallback update_callback = ReconstructUpdateCallback(progress_update_callback, callback_customdata); - intrinsics->SetFocalLength(focal_length, focal_length); - intrinsics->SetPrincipalPoint(principal_x, principal_y); - intrinsics->SetRadialDistortion(k1, k2, k3); + cameraIntrinsicsFromOptions(camera_intrinsics, libmv_camera_intrinsics_options); - reconstruction_options.success_threshold = options->success_threshold; - reconstruction_options.use_fallback_reconstruction = options->use_fallback_reconstruction; + /* Invert the camera intrinsics */ + libmv::Tracks normalized_tracks = getNormalizedTracks(tracks, camera_intrinsics); - for (int i = 0; i < markers.size(); ++i) { - intrinsics->InvertIntrinsics(markers[i].x, - markers[i].y, - &(markers[i].x), - &(markers[i].y)); - } + /* actual reconstruction */ + libmv::ReconstructionOptions reconstruction_options; + reconstruction_options.success_threshold = libmv_reconstruction_options->success_threshold; + reconstruction_options.use_fallback_reconstruction = libmv_reconstruction_options->use_fallback_reconstruction; - libmv::Tracks normalized_tracks(markers); + int keyframe1 = libmv_reconstruction_options->keyframe1, + keyframe2 = libmv_reconstruction_options->keyframe2; LG << "frames to init from: " << keyframe1 << " " << keyframe2; + libmv::vector keyframe_markers = normalized_tracks.MarkersForTracksInBothImages(keyframe1, keyframe2); + LG << "number of markers for init: " << keyframe_markers.size(); update_callback.invoke(0, "Initial reconstruction"); @@ -595,49 +633,45 @@ libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyfra libmv::EuclideanCompleteReconstruction(reconstruction_options, normalized_tracks, reconstruction, &update_callback); - if (refine_intrinsics) { - libmv_solveRefineIntrinsics((libmv::Tracks *)tracks, intrinsics, reconstruction, - refine_intrinsics, progress_update_callback, callback_customdata); + /* refinement */ + if (libmv_reconstruction_options->refine_intrinsics) { + libmv_solveRefineIntrinsics((libmv::Tracks *)tracks, camera_intrinsics, reconstruction, + libmv_reconstruction_options->refine_intrinsics, + progress_update_callback, callback_customdata); } - progress_update_callback(callback_customdata, 1.0, "Finishing solution"); - libmv_reconstruction->tracks = *(libmv::Tracks *)tracks; - libmv_reconstruction->error = libmv::EuclideanReprojectionError(*(libmv::Tracks *)tracks, *reconstruction, *intrinsics); + /* finish reconstruction */ + finishReconstruction(tracks, camera_intrinsics, libmv_reconstruction, + progress_update_callback, callback_customdata); return (libmv_Reconstruction *)libmv_reconstruction; } -struct libmv_Reconstruction *libmv_solveModal(struct libmv_Tracks *tracks, double focal_length, - double principal_x, double principal_y, double k1, double k2, double k3, - reconstruct_progress_update_cb progress_update_callback, void *callback_customdata) +struct libmv_Reconstruction *libmv_solveModal(struct libmv_Tracks *libmv_tracks, + libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options, + reconstruct_progress_update_cb progress_update_callback, + void *callback_customdata) { - /* Invert the camera intrinsics. */ - libmv::vector markers = ((libmv::Tracks*)tracks)->AllMarkers(); libmv_Reconstruction *libmv_reconstruction = new libmv_Reconstruction(); + + libmv::Tracks *tracks = ((libmv::Tracks *) libmv_tracks); libmv::EuclideanReconstruction *reconstruction = &libmv_reconstruction->reconstruction; - libmv::CameraIntrinsics *intrinsics = &libmv_reconstruction->intrinsics; + libmv::CameraIntrinsics *camera_intrinsics = &libmv_reconstruction->intrinsics; ReconstructUpdateCallback update_callback = ReconstructUpdateCallback(progress_update_callback, callback_customdata); - intrinsics->SetFocalLength(focal_length, focal_length); - intrinsics->SetPrincipalPoint(principal_x, principal_y); - intrinsics->SetRadialDistortion(k1, k2, k3); + cameraIntrinsicsFromOptions(camera_intrinsics, libmv_camera_intrinsics_options); - for (int i = 0; i < markers.size(); ++i) { - intrinsics->InvertIntrinsics(markers[i].x, - markers[i].y, - &(markers[i].x), - &(markers[i].y)); - } - - libmv::Tracks normalized_tracks(markers); + /* Invert the camera intrinsics */ + libmv::Tracks normalized_tracks = getNormalizedTracks(tracks, camera_intrinsics); + /* actual reconstruction */ libmv::ModalSolver(normalized_tracks, reconstruction, &update_callback); - progress_update_callback(callback_customdata, 1.0, "Finishing solution"); - libmv_reconstruction->tracks = *(libmv::Tracks *)tracks; - libmv_reconstruction->error = libmv::EuclideanReprojectionError(*(libmv::Tracks *)tracks, *reconstruction, *intrinsics); + /* finish reconstruction */ + finishReconstruction(tracks, camera_intrinsics, libmv_reconstruction, + progress_update_callback, callback_customdata); return (libmv_Reconstruction *)libmv_reconstruction; } diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h index e5885e7addf..317f5520aa9 100644 --- a/extern/libmv/libmv-capi.h +++ b/extern/libmv/libmv-capi.h @@ -86,28 +86,40 @@ void libmv_tracksInsert(struct libmv_Tracks *libmv_tracks, int image, int track, void libmv_tracksDestroy(struct libmv_Tracks *libmv_tracks); /* Reconstruction solver */ -#define LIBMV_REFINE_FOCAL_LENGTH (1<<0) -#define LIBMV_REFINE_PRINCIPAL_POINT (1<<1) -#define LIBMV_REFINE_RADIAL_DISTORTION_K1 (1<<2) -#define LIBMV_REFINE_RADIAL_DISTORTION_K2 (1<<4) -/* TODO: make keyframes/distortion model a part of options? */ -struct libmv_reconstructionOptions { +#define LIBMV_REFINE_FOCAL_LENGTH (1 << 0) +#define LIBMV_REFINE_PRINCIPAL_POINT (1 << 1) +#define LIBMV_REFINE_RADIAL_DISTORTION_K1 (1 << 2) +#define LIBMV_REFINE_RADIAL_DISTORTION_K2 (1 << 4) + +typedef struct libmv_cameraIntrinsicsOptions { + double focal_length; + double principal_point_x, principal_point_y; + double k1, k2, k3; + double p1, p2; +} libmv_cameraIntrinsicsOptions; + +typedef struct libmv_reconstructionOptions { + int keyframe1, keyframe2; + int refine_intrinsics; + double success_threshold; int use_fallback_reconstruction; -}; +} libmv_reconstructionOptions; typedef void (*reconstruct_progress_update_cb) (void *customdata, double progress, const char *message); int libmv_refineParametersAreValid(int parameters); -struct libmv_Reconstruction *libmv_solveReconstruction(struct libmv_Tracks *tracks, int keyframe1, int keyframe2, - int refine_intrinsics, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, - struct libmv_reconstructionOptions *options, reconstruct_progress_update_cb progress_update_callback, +struct libmv_Reconstruction *libmv_solveReconstruction(struct libmv_Tracks *libmv_tracks, + libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options, + libmv_reconstructionOptions *libmv_reconstruction_options, + reconstruct_progress_update_cb progress_update_callback, + void *callback_customdata); +struct libmv_Reconstruction *libmv_solveModal(struct libmv_Tracks *libmv_tracks, + libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options, + reconstruct_progress_update_cb progress_update_callback, void *callback_customdata); -struct libmv_Reconstruction *libmv_solveModal(struct libmv_Tracks *tracks, double focal_length, - double principal_x, double principal_y, double k1, double k2, double k3, - reconstruct_progress_update_cb progress_update_callback, void *callback_customdata); int libmv_reporojectionPointForTrack(struct libmv_Reconstruction *libmv_reconstruction, int track, double pos[3]); double libmv_reporojectionErrorForTrack(struct libmv_Reconstruction *libmv_reconstruction, int track); double libmv_reporojectionErrorForImage(struct libmv_Reconstruction *libmv_reconstruction, int image); diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 30b48401046..16415258eb5 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -2932,6 +2932,31 @@ static void reconstruct_update_solve_cb(void *customdata, double progress, const BLI_snprintf(progressdata->stats_message, progressdata->message_size, "Solving camera | %s", message); } + +static void camraIntrincicsOptionsFromContext(libmv_cameraIntrinsicsOptions *camera_intrinsics_options, + MovieReconstructContext *context) +{ + camera_intrinsics_options->focal_length = context->focal_length; + + camera_intrinsics_options->principal_point_x = context->principal_point[0]; + camera_intrinsics_options->principal_point_y = context->principal_point[1]; + + camera_intrinsics_options->k1 = context->k1; + camera_intrinsics_options->k2 = context->k2; + camera_intrinsics_options->k3 = context->k3; +} + +static void reconstructionOptionsFromContext(libmv_reconstructionOptions *reconstruction_options, + MovieReconstructContext *context) +{ + reconstruction_options->keyframe1 = context->keyframe1; + reconstruction_options->keyframe2 = context->keyframe2; + + reconstruction_options->refine_intrinsics = context->refine_flags; + + reconstruction_options->success_threshold = context->success_threshold; + reconstruction_options->use_fallback_reconstruction = context->use_fallback_reconstruction; +} #endif void BKE_tracking_reconstruction_solve(MovieReconstructContext *context, short *stop, short *do_update, @@ -2942,32 +2967,27 @@ void BKE_tracking_reconstruction_solve(MovieReconstructContext *context, short * ReconstructProgressData progressdata; + libmv_cameraIntrinsicsOptions camera_intrinsics_options; + libmv_reconstructionOptions reconstruction_options; + progressdata.stop = stop; progressdata.do_update = do_update; progressdata.progress = progress; progressdata.stats_message = stats_message; progressdata.message_size = message_size; + camraIntrincicsOptionsFromContext(&camera_intrinsics_options, context); + reconstructionOptionsFromContext(&reconstruction_options, context); + if (context->motion_flag & TRACKING_MOTION_MODAL) { context->reconstruction = libmv_solveModal(context->tracks, - context->focal_length, - context->principal_point[0], context->principal_point[1], - context->k1, context->k2, context->k3, + &camera_intrinsics_options, reconstruct_update_solve_cb, &progressdata); } else { - struct libmv_reconstructionOptions options; - - options.success_threshold = context->success_threshold; - options.use_fallback_reconstruction = context->use_fallback_reconstruction; - context->reconstruction = libmv_solveReconstruction(context->tracks, - context->keyframe1, context->keyframe2, - context->refine_flags, - context->focal_length, - context->principal_point[0], context->principal_point[1], - context->k1, context->k2, context->k3, - &options, + &camera_intrinsics_options, + &reconstruction_options, reconstruct_update_solve_cb, &progressdata); } From 5137b5a146e9ed701f2b41bcd7cb08a6251e9601 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 10 Dec 2012 16:38:28 +0000 Subject: [PATCH 160/160] Camera tracking: libmv distortion API now also uses camera intrinsics structure instead of passing all the parameters to every function. Makes it much easier to tweak distortion model. --- extern/libmv/libmv-capi.cpp | 162 +++++++++++--------- extern/libmv/libmv-capi.h | 34 ++-- source/blender/blenkernel/intern/tracking.c | 54 +++++-- 3 files changed, 144 insertions(+), 106 deletions(-) diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index ffe4b6ebf3d..41235523179 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -564,6 +564,9 @@ static void cameraIntrinsicsFromOptions(libmv::CameraIntrinsics *camera_intrinsi camera_intrinsics->SetRadialDistortion(camera_intrinsics_options->k1, camera_intrinsics_options->k2, camera_intrinsics_options->k3); + + camera_intrinsics->SetImageSize(camera_intrinsics_options->image_width, + camera_intrinsics_options->image_height); } static libmv::Tracks getNormalizedTracks(libmv::Tracks *tracks, libmv::CameraIntrinsics *camera_intrinsics) @@ -897,17 +900,13 @@ struct libmv_CameraIntrinsics *libmv_ReconstructionExtractIntrinsics(struct libm return (struct libmv_CameraIntrinsics *)&libmv_Reconstruction->intrinsics; } -struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNew(double focal_length, double principal_x, double principal_y, - double k1, double k2, double k3, int width, int height) +struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNew(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options) { - libmv::CameraIntrinsics *intrinsics= new libmv::CameraIntrinsics(); + libmv::CameraIntrinsics *camera_intrinsics = new libmv::CameraIntrinsics(); - intrinsics->SetFocalLength(focal_length, focal_length); - intrinsics->SetPrincipalPoint(principal_x, principal_y); - intrinsics->SetRadialDistortion(k1, k2, k3); - intrinsics->SetImageSize(width, height); + cameraIntrinsicsFromOptions(camera_intrinsics, libmv_camera_intrinsics_options); - return (struct libmv_CameraIntrinsics *) intrinsics; + return (struct libmv_CameraIntrinsics *) camera_intrinsics; } struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsCopy(struct libmv_CameraIntrinsics *libmvIntrinsics) @@ -925,40 +924,63 @@ void libmv_CameraIntrinsicsDestroy(struct libmv_CameraIntrinsics *libmvIntrinsic delete intrinsics; } -void libmv_CameraIntrinsicsUpdate(struct libmv_CameraIntrinsics *libmvIntrinsics, double focal_length, - double principal_x, double principal_y, double k1, double k2, double k3, int width, int height) +void libmv_CameraIntrinsicsUpdate(struct libmv_CameraIntrinsics *libmv_intrinsics, + libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options) { - libmv::CameraIntrinsics *intrinsics = (libmv::CameraIntrinsics *) libmvIntrinsics; + libmv::CameraIntrinsics *camera_intrinsics = (libmv::CameraIntrinsics *) libmv_intrinsics; - if (intrinsics->focal_length() != focal_length) - intrinsics->SetFocalLength(focal_length, focal_length); + double focal_length = libmv_camera_intrinsics_options->focal_length; + double principal_x = libmv_camera_intrinsics_options->principal_point_x; + double principal_y = libmv_camera_intrinsics_options->principal_point_y; + double k1 = libmv_camera_intrinsics_options->k1; + double k2 = libmv_camera_intrinsics_options->k2; + double k3 = libmv_camera_intrinsics_options->k3; + int image_width = libmv_camera_intrinsics_options->image_width; + int image_height = libmv_camera_intrinsics_options->image_height; - if (intrinsics->principal_point_x() != principal_x || intrinsics->principal_point_y() != principal_y) - intrinsics->SetPrincipalPoint(principal_x, principal_y); + /* try avoid unnecessary updates so pre-computed distortion grids are not freed */ - if (intrinsics->k1() != k1 || intrinsics->k2() != k2 || intrinsics->k3() != k3) - intrinsics->SetRadialDistortion(k1, k2, k3); + if (camera_intrinsics->focal_length() != focal_length) + camera_intrinsics->SetFocalLength(focal_length, focal_length); - if (intrinsics->image_width() != width || intrinsics->image_height() != height) - intrinsics->SetImageSize(width, height); + if (camera_intrinsics->principal_point_x() != principal_x || + camera_intrinsics->principal_point_y() != principal_y) + { + camera_intrinsics->SetPrincipalPoint(principal_x, principal_y); + } + + if (camera_intrinsics->k1() != k1 || + camera_intrinsics->k2() != k2 || + camera_intrinsics->k3() != k3) + { + camera_intrinsics->SetRadialDistortion(k1, k2, k3); + } + + if (camera_intrinsics->image_width() != image_width || + camera_intrinsics->image_height() != image_height) + { + camera_intrinsics->SetImageSize(image_width, image_height); + } } -void libmv_CameraIntrinsicsExtract(struct libmv_CameraIntrinsics *libmvIntrinsics, double *focal_length, - double *principal_x, double *principal_y, double *k1, double *k2, double *k3, int *width, int *height) { - libmv::CameraIntrinsics *intrinsics= (libmv::CameraIntrinsics *) libmvIntrinsics; - *focal_length = intrinsics->focal_length(); - *principal_x = intrinsics->principal_point_x(); - *principal_y = intrinsics->principal_point_y(); - *k1 = intrinsics->k1(); - *k2 = intrinsics->k2(); +void libmv_CameraIntrinsicsExtract(struct libmv_CameraIntrinsics *libmv_intrinsics, double *focal_length, + double *principal_x, double *principal_y, double *k1, double *k2, double *k3, int *width, int *height) +{ + libmv::CameraIntrinsics *camera_intrinsics = (libmv::CameraIntrinsics *) libmv_intrinsics; + + *focal_length = camera_intrinsics->focal_length(); + *principal_x = camera_intrinsics->principal_point_x(); + *principal_y = camera_intrinsics->principal_point_y(); + *k1 = camera_intrinsics->k1(); + *k2 = camera_intrinsics->k2(); } -void libmv_CameraIntrinsicsUndistortByte(struct libmv_CameraIntrinsics *libmvIntrinsics, +void libmv_CameraIntrinsicsUndistortByte(struct libmv_CameraIntrinsics *libmv_intrinsics, unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels) { - libmv::CameraIntrinsics *intrinsics = (libmv::CameraIntrinsics *) libmvIntrinsics; + libmv::CameraIntrinsics *camera_intrinsics = (libmv::CameraIntrinsics *) libmv_intrinsics; - intrinsics->Undistort(src, dst, width, height, overscan, channels); + camera_intrinsics->Undistort(src, dst, width, height, overscan, channels); } void libmv_CameraIntrinsicsUndistortFloat(struct libmv_CameraIntrinsics *libmvIntrinsics, @@ -986,85 +1008,77 @@ void libmv_CameraIntrinsicsDistortFloat(struct libmv_CameraIntrinsics *libmvIntr /* ************ distortion ************ */ -void libmv_undistortByte(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, - unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels) +void libmv_undistortByte(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options, + unsigned char *src, unsigned char *dst, int width, int height, + float overscan, int channels) { - libmv::CameraIntrinsics intrinsics; + libmv::CameraIntrinsics camera_intrinsics; - intrinsics.SetFocalLength(focal_length, focal_length); - intrinsics.SetPrincipalPoint(principal_x, principal_y); - intrinsics.SetRadialDistortion(k1, k2, k3); + cameraIntrinsicsFromOptions(&camera_intrinsics, libmv_camera_intrinsics_options); - intrinsics.Undistort(src, dst, width, height, overscan, channels); + camera_intrinsics.Undistort(src, dst, width, height, overscan, channels); } -void libmv_undistortFloat(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, - float *src, float *dst, int width, int height, float overscan, int channels) +void libmv_undistortFloat(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options, + float *src, float *dst, int width, int height, + float overscan, int channels) { - libmv::CameraIntrinsics intrinsics; + libmv::CameraIntrinsics camera_intrinsics; - intrinsics.SetFocalLength(focal_length, focal_length); - intrinsics.SetPrincipalPoint(principal_x, principal_y); - intrinsics.SetRadialDistortion(k1, k2, k3); + cameraIntrinsicsFromOptions(&camera_intrinsics, libmv_camera_intrinsics_options); - intrinsics.Undistort(src, dst, width, height, overscan, channels); + camera_intrinsics.Undistort(src, dst, width, height, overscan, channels); } -void libmv_distortByte(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, - unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels) +void libmv_distortByte(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options, + unsigned char *src, unsigned char *dst, int width, int height, + float overscan, int channels) { - libmv::CameraIntrinsics intrinsics; + libmv::CameraIntrinsics camera_intrinsics; - intrinsics.SetFocalLength(focal_length, focal_length); - intrinsics.SetPrincipalPoint(principal_x, principal_y); - intrinsics.SetRadialDistortion(k1, k2, k3); + cameraIntrinsicsFromOptions(&camera_intrinsics, libmv_camera_intrinsics_options); - intrinsics.Distort(src, dst, width, height, overscan, channels); + camera_intrinsics.Distort(src, dst, width, height, overscan, channels); } -void libmv_distortFloat(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, - float *src, float *dst, int width, int height, float overscan, int channels) +void libmv_distortFloat(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options, + float *src, float *dst, int width, int height, + float overscan, int channels) { - libmv::CameraIntrinsics intrinsics; + libmv::CameraIntrinsics camera_intrinsics; - intrinsics.SetFocalLength(focal_length, focal_length); - intrinsics.SetPrincipalPoint(principal_x, principal_y); - intrinsics.SetRadialDistortion(k1, k2, k3); + cameraIntrinsicsFromOptions(&camera_intrinsics, libmv_camera_intrinsics_options); - intrinsics.Distort(src, dst, width, height, overscan, channels); + camera_intrinsics.Distort(src, dst, width, height, overscan, channels); } /* ************ utils ************ */ -void libmv_applyCameraIntrinsics(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, - double x, double y, double *x1, double *y1) +void libmv_applyCameraIntrinsics(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options, + double x, double y, double *x1, double *y1) { - libmv::CameraIntrinsics intrinsics; + libmv::CameraIntrinsics camera_intrinsics; - intrinsics.SetFocalLength(focal_length, focal_length); - intrinsics.SetPrincipalPoint(principal_x, principal_y); - intrinsics.SetRadialDistortion(k1, k2, k3); + cameraIntrinsicsFromOptions(&camera_intrinsics, libmv_camera_intrinsics_options); - if(focal_length) { + if (libmv_camera_intrinsics_options->focal_length) { /* do a lens undistortion if focal length is non-zero only */ - intrinsics.ApplyIntrinsics(x, y, x1, y1); + camera_intrinsics.ApplyIntrinsics(x, y, x1, y1); } } -void libmv_InvertIntrinsics(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, - double x, double y, double *x1, double *y1) +void libmv_InvertIntrinsics(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options, + double x, double y, double *x1, double *y1) { - libmv::CameraIntrinsics intrinsics; + libmv::CameraIntrinsics camera_intrinsics; - intrinsics.SetFocalLength(focal_length, focal_length); - intrinsics.SetPrincipalPoint(principal_x, principal_y); - intrinsics.SetRadialDistortion(k1, k2, k3); + cameraIntrinsicsFromOptions(&camera_intrinsics, libmv_camera_intrinsics_options); - if(focal_length) { + if (libmv_camera_intrinsics_options->focal_length) { /* do a lens distortion if focal length is non-zero only */ - intrinsics.InvertIntrinsics(x, y, x1, y1); + camera_intrinsics.InvertIntrinsics(x, y, x1, y1); } } diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h index 317f5520aa9..9ffa3e1a110 100644 --- a/extern/libmv/libmv-capi.h +++ b/extern/libmv/libmv-capi.h @@ -97,6 +97,7 @@ typedef struct libmv_cameraIntrinsicsOptions { double principal_point_x, principal_point_y; double k1, k2, k3; double p1, p2; + int image_width, image_height; } libmv_cameraIntrinsicsOptions; typedef struct libmv_reconstructionOptions { @@ -139,46 +140,45 @@ void libmv_destroyFeatures(struct libmv_Features *libmv_features); /* camera intrinsics */ struct libmv_CameraIntrinsics *libmv_ReconstructionExtractIntrinsics(struct libmv_Reconstruction *libmv_Reconstruction); -struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNew(double focal_length, double principal_x, double principal_y, - double k1, double k2, double k3, int width, int height); +struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNew(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options); -struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsCopy(struct libmv_CameraIntrinsics *libmvIntrinsics); +struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsCopy(struct libmv_CameraIntrinsics *libmv_intrinsics); -void libmv_CameraIntrinsicsDestroy(struct libmv_CameraIntrinsics *libmvIntrinsics); +void libmv_CameraIntrinsicsDestroy(struct libmv_CameraIntrinsics *libmv_intrinsics); -void libmv_CameraIntrinsicsUpdate(struct libmv_CameraIntrinsics *libmvIntrinsics, double focal_length, - double principal_x, double principal_y, double k1, double k2, double k3, int width, int height); +void libmv_CameraIntrinsicsUpdate(struct libmv_CameraIntrinsics *libmv_intrinsics, + libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options); -void libmv_CameraIntrinsicsExtract(struct libmv_CameraIntrinsics *libmvIntrinsics, double *focal_length, +void libmv_CameraIntrinsicsExtract(struct libmv_CameraIntrinsics *libmv_intrinsics, double *focal_length, double *principal_x, double *principal_y, double *k1, double *k2, double *k3, int *width, int *height); -void libmv_CameraIntrinsicsUndistortByte(struct libmv_CameraIntrinsics *libmvIntrinsics, +void libmv_CameraIntrinsicsUndistortByte(struct libmv_CameraIntrinsics *libmv_intrinsics, unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels); -void libmv_CameraIntrinsicsUndistortFloat(struct libmv_CameraIntrinsics *libmvIntrinsics, +void libmv_CameraIntrinsicsUndistortFloat(struct libmv_CameraIntrinsics *libmv_intrinsics, float *src, float *dst, int width, int height, float overscan, int channels); -void libmv_CameraIntrinsicsDistortByte(struct libmv_CameraIntrinsics *libmvIntrinsics, +void libmv_CameraIntrinsicsDistortByte(struct libmv_CameraIntrinsics *libmv_intrinsics, unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels); -void libmv_CameraIntrinsicsDistortFloat(struct libmv_CameraIntrinsics *libmvIntrinsics, +void libmv_CameraIntrinsicsDistortFloat(struct libmv_CameraIntrinsics *libmv_intrinsics, float *src, float *dst, int width, int height, float overscan, int channels); /* dsitortion */ -void libmv_undistortByte(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, +void libmv_undistortByte(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options, unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels); -void libmv_undistortFloat(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, +void libmv_undistortFloat(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options, float *src, float *dst, int width, int height, float overscan, int channels); -void libmv_distortByte(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, +void libmv_distortByte(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options, unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels); -void libmv_distortFloat(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, +void libmv_distortFloat(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options, float *src, float *dst, int width, int height, float overscan, int channels); /* utils */ -void libmv_applyCameraIntrinsics(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, +void libmv_applyCameraIntrinsics(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options, double x, double y, double *x1, double *y1); -void libmv_InvertIntrinsics(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, +void libmv_InvertIntrinsics(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options, double x, double y, double *x1, double *y1); /* point clouds */ diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 16415258eb5..5e8ef23e000 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1426,6 +1426,27 @@ void BKE_tracking_camera_get_reconstructed_interpolate(MovieTracking *tracking, /*********************** Distortion/Undistortion *************************/ +#ifdef WITH_LIBMV +static void cameraIntrinscisOptionsFromTracking(libmv_cameraIntrinsicsOptions *camera_intrinsics_options, + MovieTracking *tracking, int calibration_width, int calibration_height) +{ + MovieTrackingCamera *camera = &tracking->camera; + float aspy = 1.0f / tracking->camera.pixel_aspect; + + camera_intrinsics_options->focal_length = camera->focal; + + camera_intrinsics_options->principal_point_x = camera->principal[0]; + camera_intrinsics_options->principal_point_y = camera->principal[1] * aspy; + + camera_intrinsics_options->k1 = camera->k1; + camera_intrinsics_options->k2 = camera->k2; + camera_intrinsics_options->k3 = camera->k3; + + camera_intrinsics_options->image_width = calibration_width; + camera_intrinsics_options->image_height = (double) calibration_height * aspy; +} +#endif + MovieDistortion *BKE_tracking_distortion_new(void) { MovieDistortion *distortion; @@ -1438,21 +1459,17 @@ MovieDistortion *BKE_tracking_distortion_new(void) void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking, int calibration_width, int calibration_height) { - MovieTrackingCamera *camera = &tracking->camera; - float aspy = 1.0f / tracking->camera.pixel_aspect; - #ifdef WITH_LIBMV + libmv_cameraIntrinsicsOptions camera_intrinsics_options; + + cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking, + calibration_width, calibration_height); + if (!distortion->intrinsics) { - distortion->intrinsics = libmv_CameraIntrinsicsNew(camera->focal, - camera->principal[0], camera->principal[1] * aspy, - camera->k1, camera->k2, camera->k3, - calibration_width, calibration_height * aspy); + distortion->intrinsics = libmv_CameraIntrinsicsNew(&camera_intrinsics_options); } else { - libmv_CameraIntrinsicsUpdate(distortion->intrinsics, camera->focal, - camera->principal[0], camera->principal[1] * aspy, - camera->k1, camera->k2, camera->k3, - calibration_width, calibration_height * aspy); + libmv_CameraIntrinsicsUpdate(distortion->intrinsics, &camera_intrinsics_options); } #else (void) distortion; @@ -1540,15 +1557,17 @@ void BKE_tracking_distort_v2(MovieTracking *tracking, const float co[2], float r MovieTrackingCamera *camera = &tracking->camera; #ifdef WITH_LIBMV + libmv_cameraIntrinsicsOptions camera_intrinsics_options; double x, y; float aspy = 1.0f / tracking->camera.pixel_aspect; + cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking, 0, 0); + /* normalize coords */ x = (co[0] - camera->principal[0]) / camera->focal; y = (co[1] - camera->principal[1] * aspy) / camera->focal; - libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy, - camera->k1, camera->k2, camera->k3, x, y, &x, &y); + libmv_applyCameraIntrinsics(&camera_intrinsics_options, x, y, &x, &y); /* result is in image coords already */ r_co[0] = x; @@ -1565,11 +1584,13 @@ void BKE_tracking_undistort_v2(MovieTracking *tracking, const float co[2], float MovieTrackingCamera *camera = &tracking->camera; #ifdef WITH_LIBMV + libmv_cameraIntrinsicsOptions camera_intrinsics_options; double x = co[0], y = co[1]; float aspy = 1.0f / tracking->camera.pixel_aspect; - libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy, - camera->k1, camera->k2, camera->k3, x, y, &x, &y); + cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking, 0, 0); + + libmv_InvertIntrinsics(&camera_intrinsics_options, x, y, &x, &y); r_co[0] = x * camera->focal + camera->principal[0]; r_co[1] = y * camera->focal + camera->principal[1] * aspy; @@ -2944,6 +2965,9 @@ static void camraIntrincicsOptionsFromContext(libmv_cameraIntrinsicsOptions *cam camera_intrinsics_options->k1 = context->k1; camera_intrinsics_options->k2 = context->k2; camera_intrinsics_options->k3 = context->k3; + + camera_intrinsics_options->image_width = 0; + camera_intrinsics_options->image_height = 0; } static void reconstructionOptionsFromContext(libmv_reconstructionOptions *reconstruction_options,

        For more information, visit blender.org.

      For more information, visit blender.org.

  5. 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

    t-$w){|g=@Qs-m{i}-T49b6?z2TE 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 lexY?vMe5o3 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

    4e)fk7L3!PLJATbu3QN^yU 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�*NYpdnkIRc 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%0Ao;oG5@F^-f)%%b9I1(RBfFYCXp|ABFSXD>c~ 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[i], text->undo_buf[i + 1], text->undo_buf[i + 2]); i += 3; break; - case UNDO_INSERT_4: case UNDO_BS_4: case UNDO_DEL_4: { + case UNDO_INSERT_4: case UNDO_BS_4: case UNDO_DEL_4: + { unsigned int uc; char c[BLI_UTF8_MAX + 1]; size_t c_len; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index cd07ac3b9ed..bd25ff8c6e6 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -177,58 +177,71 @@ static AVFrame *alloc_picture(int pix_fmt, int width, int height) static const char **get_file_extensions(int format) { switch (format) { - case FFMPEG_DV: { + case FFMPEG_DV: + { static const char *rv[] = { ".dv", NULL }; return rv; } - case FFMPEG_MPEG1: { + case FFMPEG_MPEG1: + { static const char *rv[] = { ".mpg", ".mpeg", NULL }; return rv; } - case FFMPEG_MPEG2: { + case FFMPEG_MPEG2: + { static const char *rv[] = { ".dvd", ".vob", ".mpg", ".mpeg", NULL }; return rv; } - case FFMPEG_MPEG4: { + case FFMPEG_MPEG4: + { static const char *rv[] = { ".mp4", ".mpg", ".mpeg", NULL }; return rv; } - case FFMPEG_AVI: { + case FFMPEG_AVI: + { static const char *rv[] = { ".avi", NULL }; return rv; } - case FFMPEG_MOV: { + case FFMPEG_MOV: + { static const char *rv[] = { ".mov", NULL }; return rv; } - case FFMPEG_H264: { + case FFMPEG_H264: + { /* FIXME: avi for now... */ static const char *rv[] = { ".avi", NULL }; return rv; } - case FFMPEG_XVID: { + case FFMPEG_XVID: + { /* FIXME: avi for now... */ static const char *rv[] = { ".avi", NULL }; return rv; } - case FFMPEG_FLV: { + case FFMPEG_FLV: + { static const char *rv[] = { ".flv", NULL }; return rv; } - case FFMPEG_MKV: { + case FFMPEG_MKV: + { static const char *rv[] = { ".mkv", NULL }; return rv; } - case FFMPEG_OGG: { + case FFMPEG_OGG: + { static const char *rv[] = { ".ogg", ".ogv", NULL }; return rv; } - case FFMPEG_MP3: { + case FFMPEG_MP3: + { static const char *rv[] = { ".mp3", NULL }; return rv; } - case FFMPEG_WAV: { + case FFMPEG_WAV: + { static const char *rv[] = { ".wav", NULL }; return rv; } diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index 4a89776a52e..886ed6f495d 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -164,7 +164,10 @@ #endif #ifndef CLAMP -# define CLAMP(a, b, c) if ((a) < (b)) (a) = (b); else if ((a) > (c)) (a) = (c) +# define CLAMP(a, b, c) { \ + if ((a) < (b)) (a) = (b); \ + else if ((a) > (c)) (a) = (c); \ +} (void)0 #endif #ifdef __BLI_MATH_INLINE_H__ diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index c11d8ed55be..29097a4c6c3 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -198,7 +198,10 @@ #define INPR(v1, v2) ( (v1)[0] * (v2)[0] + (v1)[1] * (v2)[1] + (v1)[2] * (v2)[2]) /* some misc stuff.... */ -#define CLAMP(a, b, c) if ((a) < (b)) (a) = (b); else if ((a) > (c)) (a) = (c) +#define CLAMP(a, b, c) { \ + if ((a) < (b)) (a) = (b); \ + else if ((a) > (c)) (a) = (c); \ +} (void)0 #define CLAMPIS(a, b, c) ((a) < (b) ? (b) : (a) > (c) ? (c) : (a)) #define CLAMPTEST(a, b, c) \ diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index c449dec1b6c..76aa8d55b5e 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -86,8 +86,9 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example) /* exception: don't copy the original shapekey index */ keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX); - if(keyi) + if (keyi) { *keyi = ORIGINDEX_NONE; + } } BM_CHECK_ELEMENT(v); @@ -357,14 +358,16 @@ int bmesh_elem_check(void *element, const char htype) return 2; switch (htype) { - case BM_VERT: { + case BM_VERT: + { BMVert *v = element; if (v->e && v->e->head.htype != BM_EDGE) { err |= 4; } break; } - case BM_EDGE: { + case BM_EDGE: + { BMEdge *e = element; if (e->l && e->l->head.htype != BM_LOOP) err |= 8; @@ -383,7 +386,8 @@ int bmesh_elem_check(void *element, const char htype) err |= 128; break; } - case BM_LOOP: { + case BM_LOOP: + { BMLoop *l = element, *l2; int i; @@ -423,7 +427,8 @@ int bmesh_elem_check(void *element, const char htype) break; } - case BM_FACE: { + case BM_FACE: + { BMFace *f = element; BMLoop *l_iter; BMLoop *l_first; diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 0f2dc7041fa..53b95c97c8b 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -1417,7 +1417,8 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v case '=': case '%': break; - case 'm': { + case 'm': + { int size, c; c = NEXT_CHAR(fmt); @@ -1431,12 +1432,14 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v state = 1; break; } - case 'v': { + case 'v': + { BMO_slot_vec_set(op, slot_name, va_arg(vlist, float *)); state = 1; break; } - case 'e': { + case 'e': + { BMHeader *ele = va_arg(vlist, void *); BMOpSlot *slot = BMO_slot_get(op, slot_name); @@ -1447,7 +1450,8 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v state = 1; break; } - case 's': { + case 's': + { BMOperator *op2 = va_arg(vlist, void *); const char *slot_name2 = va_arg(vlist, char *); diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp index be5936b495e..d23ed245844 100644 --- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp +++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp @@ -110,7 +110,7 @@ void OpenCLDevice::COM_clAttachSizeToKernelParameter(cl_kernel kernel, int offse { if (offsetIndex != -1) { cl_int error; - cl_int2 offset = {operation->getWidth(), operation->getHeight()}; + cl_int2 offset = {(cl_int)operation->getWidth(), (cl_int)operation->getHeight()}; error = clSetKernelArg(kernel, offsetIndex, sizeof(cl_int2), &offset); if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } @@ -127,7 +127,7 @@ void OpenCLDevice::COM_clAttachOutputMemoryBufferToKernelParameter(cl_kernel ker void OpenCLDevice::COM_clEnqueueRange(cl_kernel kernel, MemoryBuffer *outputMemoryBuffer) { cl_int error; - const size_t size[] = {outputMemoryBuffer->getWidth(), outputMemoryBuffer->getHeight()}; + const size_t size[] = {(size_t)outputMemoryBuffer->getWidth(), (size_t)outputMemoryBuffer->getHeight()}; error = clEnqueueNDRangeKernel(this->m_queue, kernel, 2, NULL, size, 0, 0, 0, NULL); if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } @@ -144,7 +144,10 @@ void OpenCLDevice::COM_clEnqueueRange(cl_kernel kernel, MemoryBuffer *outputMemo size_t size[2]; cl_int2 offset; - if (this->m_vendorID == NVIDIA) {localSize = 32;} + if (this->m_vendorID == NVIDIA) { + localSize = 32; + } + bool breaked = false; for (offsety = 0; offsety < height && (!breaked); offsety += localSize) { offset[1] = offsety; @@ -154,6 +157,7 @@ void OpenCLDevice::COM_clEnqueueRange(cl_kernel kernel, MemoryBuffer *outputMemo else { size[1] = height - offsety; } + for (offsetx = 0; offsetx < width && (!breaked); offsetx += localSize) { if (offsetx + localSize < width) { size[0] = localSize; diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 54b391bca6b..dcd652a6590 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1791,8 +1791,8 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle button_activate_state(C, but, BUTTON_STATE_EXIT); retval = WM_UI_HANDLER_BREAK; break; - case LEFTMOUSE: { - + case LEFTMOUSE: + { /* exit on LMB only on RELEASE for searchbox, to mimic other popups, and allow multiple menu levels */ if (data->searchbox) inbox = ui_searchbox_inside(data->searchbox, event->x, event->y); @@ -1958,7 +1958,8 @@ static void ui_do_but_textedit_select(bContext *C, uiBlock *block, uiBut *but, u int mx, my, retval = WM_UI_HANDLER_CONTINUE; switch (event->type) { - case MOUSEMOVE: { + case MOUSEMOVE: + { mx = event->x; my = event->y; ui_window_to_block(data->region, block, &mx, &my); @@ -5704,7 +5705,8 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) } break; - case TIMER: { + case TIMER: + { /* handle tooltip timer */ if (event->customdata == data->tooltiptimer) { WM_event_remove_timer(data->wm, data->window, data->tooltiptimer); @@ -5781,9 +5783,11 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) } else if (data->state == BUTTON_STATE_WAIT_FLASH) { switch (event->type) { - case TIMER: { - if (event->customdata == data->flashtimer) + case TIMER: + { + if (event->customdata == data->flashtimer) { button_activate_state(C, but, BUTTON_STATE_EXIT); + } } } @@ -5793,21 +5797,25 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) /* check for exit because of mouse-over another button */ switch (event->type) { case MOUSEMOVE: - - if (data->menu && data->menu->region) - if (ui_mouse_inside_region(data->menu->region, event->x, event->y)) - break; - - { - uiBut *bt = ui_but_find_mouse_over(ar, event->x, event->y); + { + uiBut *bt; - if (bt && bt->active != data) { - if (but->type != COL) /* exception */ - data->cancel = 1; - button_activate_state(C, but, BUTTON_STATE_EXIT); + if (data->menu && data->menu->region) { + if (ui_mouse_inside_region(data->menu->region, event->x, event->y)) { + break; } - break; } + + bt = ui_but_find_mouse_over(ar, event->x, event->y); + + if (bt && bt->active != data) { + if (but->type != COL) { /* exception */ + data->cancel = 1; + } + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + break; + } } ui_do_button(C, block, but, event); diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 8ff8e0824d6..faaf09e83b6 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -102,7 +102,8 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind else but = uiDefButR_prop(block, TEX, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); break; - case PROP_POINTER: { + case PROP_POINTER: + { PointerRNA pptr; pptr = RNA_property_pointer_get(ptr, prop); @@ -115,7 +116,8 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind but = uiDefIconTextButR_prop(block, IDPOIN, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); break; } - case PROP_COLLECTION: { + case PROP_COLLECTION: + { char text[256]; BLI_snprintf(text, sizeof(text), IFACE_("%d items"), RNA_property_collection_length(ptr, prop)); but = uiDefBut(block, LABEL, 0, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, NULL); diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index d2806233fa9..4d4a890300f 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -464,6 +464,8 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event) dist = FLT_MAX; + /* in the loop below we find the best vertex to drag based on its connected geometry, + * either by its face corner, or connected edge (when no faces are attached) */ for (i = 0; i < vout_len; i++) { if (BM_vert_is_wire(vout[i]) == FALSE) { @@ -473,7 +475,8 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event) float l_mid_co[3]; BM_loop_calc_face_tangent(l, l_mid_co); - /* scale to average of surrounding edge size, only needs to be approx */ + /* scale to average of surrounding edge size, only needs to be approx, but should + * be roughly equivalent to the check below which uses the middle of the edge. */ mul_v3_fl(l_mid_co, (BM_edge_calc_length(l->e) + BM_edge_calc_length(l->prev->e)) / 2.0f); add_v3_v3(l_mid_co, v->co); diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index 7870e64228a..4ffa99319c4 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -70,7 +70,8 @@ typedef struct SceneStats { static void stats_object(Object *ob, int sel, int totob, SceneStats *stats) { switch (ob->type) { - case OB_MESH: { + case OB_MESH: + { /* we assume derivedmesh is already built, this strictly does stats now. */ DerivedMesh *dm = ob->derivedFinal; int totvert, totedge, totface; @@ -101,7 +102,8 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats) break; case OB_SURF: case OB_CURVE: - case OB_FONT: { + case OB_FONT: + { int tot = 0, totf = 0; stats->totcurve += totob; @@ -121,7 +123,8 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats) } break; } - case OB_MBALL: { + case OB_MBALL: + { int tot = 0, totf = 0; BKE_displist_count(&ob->disp, &tot, &totf); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 3455e0b219c..d84a641e3aa 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1327,8 +1327,9 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE); uiItemR(layout, ptr, "projection", 0, "", ICON_NONE); - if(RNA_enum_get(ptr, "projection") == SHD_PROJ_BOX) + if (RNA_enum_get(ptr, "projection") == SHD_PROJ_BOX) { uiItemR(layout, ptr, "projection_blend", 0, "Blend", ICON_NONE); + } /* note: image user properties used directly here, unlike compositor image node, * which redefines them in the node struct RNA to get proper updates. diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index fbae8b17ebf..90ad1452356 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -309,7 +309,8 @@ void ED_node_shader_default(Scene *scene, ID *id) ntree = ntreeAddTree("Shader Nodetree", NTREE_SHADER, 0); switch (GS(id->name)) { - case ID_MA: { + case ID_MA: + { Material *ma = (Material *)id; ma->nodetree = ntree; @@ -326,7 +327,8 @@ void ED_node_shader_default(Scene *scene, ID *id) strength = 0.0f; break; } - case ID_WO: { + case ID_WO: + { World *wo = (World *)id; wo->nodetree = ntree; @@ -337,7 +339,8 @@ void ED_node_shader_default(Scene *scene, ID *id) strength = 1.0f; break; } - case ID_LA: { + case ID_LA: + { Lamp *la = (Lamp *)id; la->nodetree = ntree; diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index 12c221b9273..fec7366ee73 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -560,7 +560,8 @@ static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event) case LEFTMOUSE: case RIGHTMOUSE: - case MIDDLEMOUSE: { + case MIDDLEMOUSE: + { for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) { link = linkdata->data; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 68cc1c8e9b6..a21f8fd5f34 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -5363,7 +5363,8 @@ int handleEventEdgeSlide(struct TransInfo *t, struct wmEvent *event) return 1; } break; - case FKEY: { + case FKEY: + { if (event->val == KM_PRESS) { if (sld->is_proportional == FALSE) { sld->flipped_vtx = !sld->flipped_vtx; @@ -5372,13 +5373,16 @@ int handleEventEdgeSlide(struct TransInfo *t, struct wmEvent *event) } break; } - case EVT_MODAL_MAP: { + case EVT_MODAL_MAP: + { switch (event->val) { - case TFM_MODAL_EDGESLIDE_DOWN: { + case TFM_MODAL_EDGESLIDE_DOWN: + { sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv; break; } - case TFM_MODAL_EDGESLIDE_UP: { + case TFM_MODAL_EDGESLIDE_UP: + { sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv; break; } diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index 9092d59c351..16dbd0823da 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -801,6 +801,34 @@ static int ffmpeg_decode_video_frame(struct anim *anim) anim->next_packet.stream_index = -1; } + if (rval == AVERROR_EOF) { + anim->next_packet.size = 0; + anim->next_packet.data = 0; + + anim->pFrameComplete = 0; + + avcodec_decode_video2( + anim->pCodecCtx, + anim->pFrame, &anim->pFrameComplete, + &anim->next_packet); + + if (anim->pFrameComplete) { + anim->next_pts = av_get_pts_from_frame( + anim->pFormatCtx, anim->pFrame); + + av_log(anim->pFormatCtx, + AV_LOG_DEBUG, + " FRAME DONE (after EOF): next_pts=%lld " + "pkt_pts=%lld, guessed_pts=%lld\n", + (anim->pFrame->pts == AV_NOPTS_VALUE) ? + -1 : (long long int)anim->pFrame->pts, + (anim->pFrame->pkt_pts == AV_NOPTS_VALUE) ? + -1 : (long long int)anim->pFrame->pkt_pts, + (long long int)anim->next_pts); + rval = 0; + } + } + if (rval < 0) { anim->next_packet.stream_index = -1; diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index 458f0198aed..ea493e277f3 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -723,6 +723,17 @@ typedef struct FFmpegIndexBuilderContext { IMB_Timecode_Type tcs_in_use; IMB_Proxy_Size proxy_sizes_in_use; + + unsigned long long seek_pos; + unsigned long long last_seek_pos; + unsigned long long seek_pos_dts; + unsigned long long seek_pos_pts; + unsigned long long last_seek_pos_dts; + unsigned long long start_pts; + double frame_rate; + double pts_time_base; + int frameno, frameno_gapless; + int start_pts_set; } FFmpegIndexBuilderContext; static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, IMB_Timecode_Type tcs_in_use, @@ -839,20 +850,63 @@ static void index_rebuild_ffmpeg_finish(FFmpegIndexBuilderContext *context, int MEM_freeN(context); } +static void index_rebuild_ffmpeg_proc_decoded_frame( + FFmpegIndexBuilderContext *context, + AVPacket * curr_packet, + AVFrame *in_frame) +{ + int i; + unsigned long long s_pos = context->seek_pos; + unsigned long long s_dts = context->seek_pos_dts; + unsigned long long pts = av_get_pts_from_frame(context->iFormatCtx, in_frame); + + for (i = 0; i < context->num_proxy_sizes; i++) { + add_to_proxy_output_ffmpeg(context->proxy_ctx[i], in_frame); + } + + if (!context->start_pts_set) { + context->start_pts = pts; + context->start_pts_set = TRUE; + } + + context->frameno = floor((pts - context->start_pts) + * context->pts_time_base + * context->frame_rate + 0.5f); + + /* decoding starts *always* on I-Frames, + * so: P-Frames won't work, even if all the + * information is in place, when we seek + * to the I-Frame presented *after* the P-Frame, + * but located before the P-Frame within + * the stream */ + + if (pts < context->seek_pos_pts) { + s_pos = context->last_seek_pos; + s_dts = context->last_seek_pos_dts; + } + + for (i = 0; i < context->num_indexers; i++) { + if (context->tcs_in_use & tc_types[i]) { + int tc_frameno = context->frameno; + + if (tc_types[i] == IMB_TC_RECORD_RUN_NO_GAPS) + tc_frameno = context->frameno_gapless; + + IMB_index_builder_proc_frame( + context->indexer[i], + curr_packet->data, + curr_packet->size, + tc_frameno, + s_pos, s_dts, pts); + } + } + + context->frameno_gapless++; +} + static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context, short *stop, short *do_update, float *progress) { - int i; - unsigned long long seek_pos = 0; - unsigned long long last_seek_pos = 0; - unsigned long long seek_pos_dts = 0; - unsigned long long seek_pos_pts = 0; - unsigned long long last_seek_pos_dts = 0; - unsigned long long start_pts = 0; - double frame_rate; - double pts_time_base; - int frameno = 0, frameno_gapless = 0; - int start_pts_set = FALSE; AVFrame *in_frame = 0; AVPacket next_packet; uint64_t stream_size; @@ -861,8 +915,8 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context, stream_size = avio_size(context->iFormatCtx->pb); - frame_rate = av_q2d(context->iStream->r_frame_rate); - pts_time_base = av_q2d(context->iStream->time_base); + context->frame_rate = av_q2d(context->iStream->r_frame_rate); + context->pts_time_base = av_q2d(context->iStream->time_base); while (av_read_frame(context->iFormatCtx, &next_packet) >= 0) { int frame_finished = 0; @@ -881,11 +935,11 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context, if (next_packet.stream_index == context->videoStream) { if (next_packet.flags & AV_PKT_FLAG_KEY) { - last_seek_pos = seek_pos; - last_seek_pos_dts = seek_pos_dts; - seek_pos = next_packet.pos; - seek_pos_dts = next_packet.dts; - seek_pos_pts = next_packet.pts; + context->last_seek_pos = context->seek_pos; + context->last_seek_pos_dts = context->seek_pos_dts; + context->seek_pos = next_packet.pos; + context->seek_pos_dts = next_packet.dts; + context->seek_pos_pts = next_packet.pts; } avcodec_decode_video2( @@ -894,56 +948,36 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context, } if (frame_finished) { - unsigned long long s_pos = seek_pos; - unsigned long long s_dts = seek_pos_dts; - unsigned long long pts = av_get_pts_from_frame(context->iFormatCtx, in_frame); - - for (i = 0; i < context->num_proxy_sizes; i++) { - add_to_proxy_output_ffmpeg( - context->proxy_ctx[i], in_frame); - } - - if (!start_pts_set) { - start_pts = pts; - start_pts_set = TRUE; - } - - frameno = floor((pts - start_pts) * - pts_time_base * frame_rate + 0.5f); - - /* decoding starts *always* on I-Frames, - * so: P-Frames won't work, even if all the - * information is in place, when we seek - * to the I-Frame presented *after* the P-Frame, - * but located before the P-Frame within - * the stream */ - - if (pts < seek_pos_pts) { - s_pos = last_seek_pos; - s_dts = last_seek_pos_dts; - } - - for (i = 0; i < context->num_indexers; i++) { - if (context->tcs_in_use & tc_types[i]) { - int tc_frameno = frameno; - - if (tc_types[i] == IMB_TC_RECORD_RUN_NO_GAPS) - tc_frameno = frameno_gapless; - - IMB_index_builder_proc_frame( - context->indexer[i], - next_packet.data, - next_packet.size, - tc_frameno, - s_pos, s_dts, pts); - } - } - - frameno_gapless++; + index_rebuild_ffmpeg_proc_decoded_frame( + context, &next_packet, in_frame); } av_free_packet(&next_packet); } + /* process pictures still stuck in decoder engine after EOF + according to ffmpeg docs using 0-size packets. + + At least, if we haven't already stopped... */ + if (!*stop) { + int frame_finished; + + next_packet.size = 0; + next_packet.data = 0; + + do { + frame_finished = 0; + + avcodec_decode_video2( + context->iCodecCtx, in_frame, &frame_finished, + &next_packet); + + if (frame_finished) { + index_rebuild_ffmpeg_proc_decoded_frame( + context, &next_packet, in_frame); + } + } while (frame_finished); + } + av_free(in_frame); return 1; diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index d2ff8d13124..ef3c7f42e96 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -532,7 +532,8 @@ static char *rna_def_property_get_func(FILE *f, StructRNA *srna, PropertyRNA *pr func = rna_alloc_function_name(srna->identifier, rna_safe_id(prop->identifier), "get"); switch (prop->type) { - case PROP_STRING: { + case PROP_STRING: + { StringPropertyRNA *sprop = (StringPropertyRNA *)prop; fprintf(f, "void %s(PointerRNA *ptr, char *value)\n", func); fprintf(f, "{\n"); @@ -565,7 +566,8 @@ static char *rna_def_property_get_func(FILE *f, StructRNA *srna, PropertyRNA *pr fprintf(f, "}\n\n"); break; } - case PROP_POINTER: { + case PROP_POINTER: + { fprintf(f, "PointerRNA %s(PointerRNA *ptr)\n", func); fprintf(f, "{\n"); if (manualfunc) { @@ -584,7 +586,8 @@ static char *rna_def_property_get_func(FILE *f, StructRNA *srna, PropertyRNA *pr fprintf(f, "}\n\n"); break; } - case PROP_COLLECTION: { + case PROP_COLLECTION: + { CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; fprintf(f, "static PointerRNA %s(CollectionPropertyIterator *iter)\n", func); @@ -785,7 +788,8 @@ static char *rna_def_property_set_func(FILE *f, StructRNA *srna, PropertyRNA *pr func = rna_alloc_function_name(srna->identifier, rna_safe_id(prop->identifier), "set"); switch (prop->type) { - case PROP_STRING: { + case PROP_STRING: + { StringPropertyRNA *sprop = (StringPropertyRNA *)prop; fprintf(f, "void %s(PointerRNA *ptr, const char *value)\n", func); fprintf(f, "{\n"); @@ -817,7 +821,8 @@ static char *rna_def_property_set_func(FILE *f, StructRNA *srna, PropertyRNA *pr fprintf(f, "}\n\n"); break; } - case PROP_POINTER: { + case PROP_POINTER: + { fprintf(f, "void %s(PointerRNA *ptr, PointerRNA value)\n", func); fprintf(f, "{\n"); if (manualfunc) { @@ -1275,7 +1280,8 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) prop = dp->prop; switch (prop->type) { - case PROP_BOOLEAN: { + case PROP_BOOLEAN: + { BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop; if (!prop->arraydimension) { @@ -1291,7 +1297,8 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) } break; } - case PROP_INT: { + case PROP_INT: + { IntPropertyRNA *iprop = (IntPropertyRNA *)prop; if (!prop->arraydimension) { @@ -1310,7 +1317,8 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) } break; } - case PROP_FLOAT: { + case PROP_FLOAT: + { FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop; if (!prop->arraydimension) { @@ -1329,14 +1337,16 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) } break; } - case PROP_ENUM: { + case PROP_ENUM: + { EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop; eprop->get = (void *)rna_def_property_get_func(f, srna, prop, dp, (const char *)eprop->get); eprop->set = (void *)rna_def_property_set_func(f, srna, prop, dp, (const char *)eprop->set); break; } - case PROP_STRING: { + case PROP_STRING: + { StringPropertyRNA *sprop = (StringPropertyRNA *)prop; sprop->get = (void *)rna_def_property_get_func(f, srna, prop, dp, (const char *)sprop->get); @@ -1344,7 +1354,8 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) sprop->set = (void *)rna_def_property_set_func(f, srna, prop, dp, (const char *)sprop->set); break; } - case PROP_POINTER: { + case PROP_POINTER: + { PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; pprop->get = (void *)rna_def_property_get_func(f, srna, prop, dp, (const char *)pprop->get); @@ -1356,7 +1367,8 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) } break; } - case PROP_COLLECTION: { + case PROP_COLLECTION: + { CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; const char *nextfunc = (const char *)cprop->next; @@ -1421,7 +1433,8 @@ static void rna_def_property_funcs_header(FILE *f, StructRNA *srna, PropertyDefR switch (prop->type) { case PROP_BOOLEAN: - case PROP_INT: { + case PROP_INT: + { if (!prop->arraydimension) { fprintf(f, "int %sget(PointerRNA *ptr);\n", func); /*fprintf(f, "void %sset(PointerRNA *ptr, int value);\n", func); */ @@ -1436,7 +1449,8 @@ static void rna_def_property_funcs_header(FILE *f, StructRNA *srna, PropertyDefR } break; } - case PROP_FLOAT: { + case PROP_FLOAT: + { if (!prop->arraydimension) { fprintf(f, "float %sget(PointerRNA *ptr);\n", func); /*fprintf(f, "void %sset(PointerRNA *ptr, float value);\n", func); */ @@ -1451,7 +1465,8 @@ static void rna_def_property_funcs_header(FILE *f, StructRNA *srna, PropertyDefR } break; } - case PROP_ENUM: { + case PROP_ENUM: + { EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop; int i; @@ -1471,7 +1486,8 @@ static void rna_def_property_funcs_header(FILE *f, StructRNA *srna, PropertyDefR break; } - case PROP_STRING: { + case PROP_STRING: + { StringPropertyRNA *sprop = (StringPropertyRNA *)prop; if (sprop->maxlength) { @@ -1484,12 +1500,14 @@ static void rna_def_property_funcs_header(FILE *f, StructRNA *srna, PropertyDefR break; } - case PROP_POINTER: { + case PROP_POINTER: + { fprintf(f, "PointerRNA %sget(PointerRNA *ptr);\n", func); /*fprintf(f, "void %sset(PointerRNA *ptr, PointerRNA value);\n", func); */ break; } - case PROP_COLLECTION: { + case PROP_COLLECTION: + { fprintf(f, "void %sbegin(CollectionPropertyIterator *iter, PointerRNA *ptr);\n", func); fprintf(f, "void %snext(CollectionPropertyIterator *iter);\n", func); fprintf(f, "void %send(CollectionPropertyIterator *iter);\n", func); @@ -1520,28 +1538,32 @@ static void rna_def_property_funcs_header_cpp(FILE *f, StructRNA *srna, Property fprintf(f, "\t/* */\n"); switch (prop->type) { - case PROP_BOOLEAN: { + case PROP_BOOLEAN: + { if (!prop->arraydimension) fprintf(f, "\tinline bool %s(void);", rna_safe_id(prop->identifier)); else if (prop->totarraylength) fprintf(f, "\tinline Array %s(void);", prop->totarraylength, rna_safe_id(prop->identifier)); break; } - case PROP_INT: { + case PROP_INT: + { if (!prop->arraydimension) fprintf(f, "\tinline int %s(void);", rna_safe_id(prop->identifier)); else if (prop->totarraylength) fprintf(f, "\tinline Array %s(void);", prop->totarraylength, rna_safe_id(prop->identifier)); break; } - case PROP_FLOAT: { + case PROP_FLOAT: + { if (!prop->arraydimension) fprintf(f, "\tinline float %s(void);", rna_safe_id(prop->identifier)); else if (prop->totarraylength) fprintf(f, "\tinline Array %s(void);", prop->totarraylength, rna_safe_id(prop->identifier)); break; } - case PROP_ENUM: { + case PROP_ENUM: + { EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop; int i; @@ -1559,11 +1581,13 @@ static void rna_def_property_funcs_header_cpp(FILE *f, StructRNA *srna, Property fprintf(f, "\tinline %s_enum %s(void);", rna_safe_id(prop->identifier), rna_safe_id(prop->identifier)); break; } - case PROP_STRING: { + case PROP_STRING: + { fprintf(f, "\tinline std::string %s(void);", rna_safe_id(prop->identifier)); break; } - case PROP_POINTER: { + case PROP_POINTER: + { PointerPropertyRNA *pprop = (PointerPropertyRNA *)dp->prop; if (pprop->type) @@ -1572,7 +1596,8 @@ static void rna_def_property_funcs_header_cpp(FILE *f, StructRNA *srna, Property fprintf(f, "\tinline %s %s(void);", "UnknownType", rna_safe_id(prop->identifier)); break; } - case PROP_COLLECTION: { + case PROP_COLLECTION: + { CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)dp->prop; if (cprop->item_type) @@ -1598,7 +1623,8 @@ static void rna_def_property_funcs_impl_cpp(FILE *f, StructRNA *srna, PropertyDe return; switch (prop->type) { - case PROP_BOOLEAN: { + case PROP_BOOLEAN: + { if (!prop->arraydimension) fprintf(f, "\tBOOLEAN_PROPERTY(%s, %s)", srna->identifier, rna_safe_id(prop->identifier)); else if (prop->totarraylength) @@ -1606,7 +1632,8 @@ static void rna_def_property_funcs_impl_cpp(FILE *f, StructRNA *srna, PropertyDe rna_safe_id(prop->identifier)); break; } - case PROP_INT: { + case PROP_INT: + { if (!prop->arraydimension) fprintf(f, "\tINT_PROPERTY(%s, %s)", srna->identifier, rna_safe_id(prop->identifier)); else if (prop->totarraylength) @@ -1614,7 +1641,8 @@ static void rna_def_property_funcs_impl_cpp(FILE *f, StructRNA *srna, PropertyDe rna_safe_id(prop->identifier)); break; } - case PROP_FLOAT: { + case PROP_FLOAT: + { if (!prop->arraydimension) fprintf(f, "\tFLOAT_PROPERTY(%s, %s)", srna->identifier, rna_safe_id(prop->identifier)); else if (prop->totarraylength) @@ -1622,17 +1650,20 @@ static void rna_def_property_funcs_impl_cpp(FILE *f, StructRNA *srna, PropertyDe rna_safe_id(prop->identifier)); break; } - case PROP_ENUM: { + case PROP_ENUM: + { fprintf(f, "\tENUM_PROPERTY(%s_enum, %s, %s)", rna_safe_id(prop->identifier), srna->identifier, rna_safe_id(prop->identifier)); break; } - case PROP_STRING: { + case PROP_STRING: + { fprintf(f, "\tSTRING_PROPERTY(%s, %s)", srna->identifier, rna_safe_id(prop->identifier)); break; } - case PROP_POINTER: { + case PROP_POINTER: + { PointerPropertyRNA *pprop = (PointerPropertyRNA *)dp->prop; if (pprop->type) @@ -1643,7 +1674,8 @@ static void rna_def_property_funcs_impl_cpp(FILE *f, StructRNA *srna, PropertyDe rna_safe_id(prop->identifier)); break; } - case PROP_COLLECTION: { + case PROP_COLLECTION: + { #if 0 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)dp->prop; @@ -2218,7 +2250,8 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr } switch (prop->type) { - case PROP_ENUM: { + case PROP_ENUM: + { EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop; int i, defaultfound = 0, totflag = 0; @@ -2270,7 +2303,8 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr } break; } - case PROP_BOOLEAN: { + case PROP_BOOLEAN: + { BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop; unsigned int i; @@ -2291,7 +2325,8 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr } break; } - case PROP_INT: { + case PROP_INT: + { IntPropertyRNA *iprop = (IntPropertyRNA *)prop; unsigned int i; @@ -2312,7 +2347,8 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr } break; } - case PROP_FLOAT: { + case PROP_FLOAT: + { FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop; unsigned int i; @@ -2380,7 +2416,8 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr fprintf(f, "},\n"); switch (prop->type) { - case PROP_BOOLEAN: { + case PROP_BOOLEAN: + { BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop; fprintf(f, "\t%s, %s, %s, %s, %d, ", rna_function_string(bprop->get), @@ -2393,7 +2430,8 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr else fprintf(f, "NULL\n"); break; } - case PROP_INT: { + case PROP_INT: + { IntPropertyRNA *iprop = (IntPropertyRNA *)prop; fprintf(f, "\t%s, %s, %s, %s, %s,\n\t", rna_function_string(iprop->get), @@ -2412,7 +2450,8 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr else fprintf(f, "NULL\n"); break; } - case PROP_FLOAT: { + case PROP_FLOAT: + { FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop; fprintf(f, "\t%s, %s, %s, %s, %s, ", rna_function_string(fprop->get), @@ -2432,7 +2471,8 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr else fprintf(f, "NULL\n"); break; } - case PROP_STRING: { + case PROP_STRING: + { StringPropertyRNA *sprop = (StringPropertyRNA *)prop; fprintf(f, "\t%s, %s, %s, %d, ", rna_function_string(sprop->get), @@ -2442,7 +2482,8 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr rna_print_c_string(f, sprop->defaultvalue); fprintf(f, "\n"); break; } - case PROP_ENUM: { + case PROP_ENUM: + { EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop; fprintf(f, "\t%s, %s, %s, NULL, ", rna_function_string(eprop->get), @@ -2455,7 +2496,8 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr fprintf(f, "%d, %d\n", eprop->totitem, eprop->defaultvalue); break; } - case PROP_POINTER: { + case PROP_POINTER: + { PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; fprintf(f, "\t%s, %s, %s, %s,", rna_function_string(pprop->get), rna_function_string(pprop->set), @@ -2465,7 +2507,8 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr else fprintf(f, "NULL\n"); break; } - case PROP_COLLECTION: { + case PROP_COLLECTION: + { CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; fprintf(f, "\t%s, %s, %s, %s, %s, %s, %s, %s, ", rna_function_string(cprop->begin), diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index ec4da311686..d36c0bbaf4a 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -3192,19 +3192,22 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro /* handle conversions */ if (set) { switch (itemtype) { - case PROP_BOOLEAN: { + case PROP_BOOLEAN: + { int b; RAW_GET(int, b, in, a); RNA_property_boolean_set(&itemptr, iprop, b); break; } - case PROP_INT: { + case PROP_INT: + { int i; RAW_GET(int, i, in, a); RNA_property_int_set(&itemptr, iprop, i); break; } - case PROP_FLOAT: { + case PROP_FLOAT: + { float f; RAW_GET(float, f, in, a); RNA_property_float_set(&itemptr, iprop, f); @@ -3216,17 +3219,20 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro } else { switch (itemtype) { - case PROP_BOOLEAN: { + case PROP_BOOLEAN: + { int b = RNA_property_boolean_get(&itemptr, iprop); RAW_SET(int, in, a, b); break; } - case PROP_INT: { + case PROP_INT: + { int i = RNA_property_int_get(&itemptr, iprop); RAW_SET(int, in, a, i); break; } - case PROP_FLOAT: { + case PROP_FLOAT: + { float f = RNA_property_float_get(&itemptr, iprop); RAW_SET(float, in, a, f); break; @@ -3251,19 +3257,22 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro /* handle conversions */ if (set) { switch (itemtype) { - case PROP_BOOLEAN: { + case PROP_BOOLEAN: + { for (j = 0; j < itemlen; j++, a++) RAW_GET(int, ((int *)tmparray)[j], in, a); RNA_property_boolean_set_array(&itemptr, iprop, tmparray); break; } - case PROP_INT: { + case PROP_INT: + { for (j = 0; j < itemlen; j++, a++) RAW_GET(int, ((int *)tmparray)[j], in, a); RNA_property_int_set_array(&itemptr, iprop, tmparray); break; } - case PROP_FLOAT: { + case PROP_FLOAT: + { for (j = 0; j < itemlen; j++, a++) RAW_GET(float, ((float *)tmparray)[j], in, a); RNA_property_float_set_array(&itemptr, iprop, tmparray); @@ -3275,19 +3284,22 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro } else { switch (itemtype) { - case PROP_BOOLEAN: { + case PROP_BOOLEAN: + { RNA_property_boolean_get_array(&itemptr, iprop, tmparray); for (j = 0; j < itemlen; j++, a++) RAW_SET(int, in, a, ((int *)tmparray)[j]); break; } - case PROP_INT: { + case PROP_INT: + { RNA_property_int_get_array(&itemptr, iprop, tmparray); for (j = 0; j < itemlen; j++, a++) RAW_SET(int, in, a, ((int *)tmparray)[j]); break; } - case PROP_FLOAT: { + case PROP_FLOAT: + { RNA_property_float_get_array(&itemptr, iprop, tmparray); for (j = 0; j < itemlen; j++, a++) RAW_SET(float, in, a, ((float *)tmparray)[j]); @@ -3301,17 +3313,20 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro else { if (set) { switch (itemtype) { - case PROP_BOOLEAN: { + case PROP_BOOLEAN: + { RNA_property_boolean_set_array(&itemptr, iprop, &((int *)in.array)[a]); a += itemlen; break; } - case PROP_INT: { + case PROP_INT: + { RNA_property_int_set_array(&itemptr, iprop, &((int *)in.array)[a]); a += itemlen; break; } - case PROP_FLOAT: { + case PROP_FLOAT: + { RNA_property_float_set_array(&itemptr, iprop, &((float *)in.array)[a]); a += itemlen; break; @@ -3322,17 +3337,20 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro } else { switch (itemtype) { - case PROP_BOOLEAN: { + case PROP_BOOLEAN: + { RNA_property_boolean_get_array(&itemptr, iprop, &((int *)in.array)[a]); a += itemlen; break; } - case PROP_INT: { + case PROP_INT: + { RNA_property_int_get_array(&itemptr, iprop, &((int *)in.array)[a]); a += itemlen; break; } - case PROP_FLOAT: { + case PROP_FLOAT: + { RNA_property_float_get_array(&itemptr, iprop, &((float *)in.array)[a]); a += itemlen; break; @@ -4924,7 +4942,8 @@ ParameterList *RNA_parameter_list_create(ParameterList *parms, PointerRNA *UNUSE case PROP_ENUM: memcpy(data, &((EnumPropertyRNA *)parm)->defaultvalue, size); break; - case PROP_STRING: { + case PROP_STRING: + { const char *defvalue = ((StringPropertyRNA *)parm)->defaultvalue; if (defvalue && defvalue[0]) { /* causes bug [#29988], possibly this is only correct for thick wrapped diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index 0320c0d7142..45092d09ce1 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -926,7 +926,8 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier } } break; - case PROP_INT: { + case PROP_INT: + { IntPropertyRNA *iprop = (IntPropertyRNA *)prop; iprop->hardmin = (subtype == PROP_UNSIGNED) ? 0 : INT_MIN; @@ -937,7 +938,8 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier iprop->step = 1; break; } - case PROP_FLOAT: { + case PROP_FLOAT: + { FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop; fprop->hardmin = (subtype == PROP_UNSIGNED) ? 0.0f : -FLT_MAX; @@ -959,7 +961,8 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier fprop->precision = 3; break; } - case PROP_STRING: { + case PROP_STRING: + { StringPropertyRNA *sprop = (StringPropertyRNA *)prop; sprop->defaultvalue = ""; @@ -1009,19 +1012,22 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier RNA_def_property_boolean_sdna(prop, NULL, identifier, 0); DefRNA.silent = 0; break; - case PROP_INT: { + case PROP_INT: + { DefRNA.silent = 1; RNA_def_property_int_sdna(prop, NULL, identifier); DefRNA.silent = 0; break; } - case PROP_FLOAT: { + case PROP_FLOAT: + { DefRNA.silent = 1; RNA_def_property_float_sdna(prop, NULL, identifier); DefRNA.silent = 0; break; } - case PROP_STRING: { + case PROP_STRING: + { DefRNA.silent = 1; RNA_def_property_string_sdna(prop, NULL, identifier); DefRNA.silent = 0; @@ -1173,14 +1179,16 @@ void RNA_def_property_ui_range(PropertyRNA *prop, double min, double max, double StructRNA *srna = DefRNA.laststruct; switch (prop->type) { - case PROP_INT: { + case PROP_INT: + { IntPropertyRNA *iprop = (IntPropertyRNA *)prop; iprop->softmin = (int)min; iprop->softmax = (int)max; iprop->step = (int)step; break; } - case PROP_FLOAT: { + case PROP_FLOAT: + { FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop; fprop->softmin = (float)min; fprop->softmax = (float)max; @@ -1201,7 +1209,8 @@ void RNA_def_property_range(PropertyRNA *prop, double min, double max) StructRNA *srna = DefRNA.laststruct; switch (prop->type) { - case PROP_INT: { + case PROP_INT: + { IntPropertyRNA *iprop = (IntPropertyRNA *)prop; iprop->hardmin = (int)min; iprop->hardmax = (int)max; @@ -1209,7 +1218,8 @@ void RNA_def_property_range(PropertyRNA *prop, double min, double max) iprop->softmax = MIN2((int)max, iprop->hardmax); break; } - case PROP_FLOAT: { + case PROP_FLOAT: + { FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop; fprop->hardmin = (float)min; fprop->hardmax = (float)max; @@ -1234,12 +1244,14 @@ void RNA_def_property_struct_type(PropertyRNA *prop, const char *type) } switch (prop->type) { - case PROP_POINTER: { + case PROP_POINTER: + { PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; pprop->type = (StructRNA *)type; break; } - case PROP_COLLECTION: { + case PROP_COLLECTION: + { CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; cprop->item_type = (StructRNA *)type; break; @@ -1262,7 +1274,8 @@ void RNA_def_property_struct_runtime(PropertyRNA *prop, StructRNA *type) } switch (prop->type) { - case PROP_POINTER: { + case PROP_POINTER: + { PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; pprop->type = type; @@ -1271,7 +1284,8 @@ void RNA_def_property_struct_runtime(PropertyRNA *prop, StructRNA *type) break; } - case PROP_COLLECTION: { + case PROP_COLLECTION: + { CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; cprop->item_type = type; break; @@ -1290,7 +1304,8 @@ void RNA_def_property_enum_items(PropertyRNA *prop, const EnumPropertyItem *item int i, defaultfound = 0; switch (prop->type) { - case PROP_ENUM: { + case PROP_ENUM: + { EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop; eprop->item = (EnumPropertyItem *)item; eprop->totitem = 0; @@ -1325,7 +1340,8 @@ void RNA_def_property_string_maxlength(PropertyRNA *prop, int maxlength) StructRNA *srna = DefRNA.laststruct; switch (prop->type) { - case PROP_STRING: { + case PROP_STRING: + { StringPropertyRNA *sprop = (StringPropertyRNA *)prop; sprop->maxlength = maxlength; break; @@ -1342,7 +1358,8 @@ void RNA_def_property_boolean_default(PropertyRNA *prop, int value) StructRNA *srna = DefRNA.laststruct; switch (prop->type) { - case PROP_BOOLEAN: { + case PROP_BOOLEAN: + { BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop; bprop->defaultvalue = value; break; @@ -1359,7 +1376,8 @@ void RNA_def_property_boolean_array_default(PropertyRNA *prop, const int *array) StructRNA *srna = DefRNA.laststruct; switch (prop->type) { - case PROP_BOOLEAN: { + case PROP_BOOLEAN: + { BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop; bprop->defaultarray = array; break; @@ -1376,7 +1394,8 @@ void RNA_def_property_int_default(PropertyRNA *prop, int value) StructRNA *srna = DefRNA.laststruct; switch (prop->type) { - case PROP_INT: { + case PROP_INT: + { IntPropertyRNA *iprop = (IntPropertyRNA *)prop; iprop->defaultvalue = value; break; @@ -1393,7 +1412,8 @@ void RNA_def_property_int_array_default(PropertyRNA *prop, const int *array) StructRNA *srna = DefRNA.laststruct; switch (prop->type) { - case PROP_INT: { + case PROP_INT: + { IntPropertyRNA *iprop = (IntPropertyRNA *)prop; iprop->defaultarray = array; break; @@ -1410,7 +1430,8 @@ void RNA_def_property_float_default(PropertyRNA *prop, float value) StructRNA *srna = DefRNA.laststruct; switch (prop->type) { - case PROP_FLOAT: { + case PROP_FLOAT: + { FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop; fprop->defaultvalue = value; break; @@ -1427,7 +1448,8 @@ void RNA_def_property_float_array_default(PropertyRNA *prop, const float *array) StructRNA *srna = DefRNA.laststruct; switch (prop->type) { - case PROP_FLOAT: { + case PROP_FLOAT: + { FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop; fprop->defaultarray = array; /* WARNING, this array must not come from the stack and lost */ break; @@ -1444,7 +1466,8 @@ void RNA_def_property_string_default(PropertyRNA *prop, const char *value) StructRNA *srna = DefRNA.laststruct; switch (prop->type) { - case PROP_STRING: { + case PROP_STRING: + { StringPropertyRNA *sprop = (StringPropertyRNA *)prop; sprop->defaultvalue = value; break; @@ -1462,7 +1485,8 @@ void RNA_def_property_enum_default(PropertyRNA *prop, int value) int i, defaultfound = 0; switch (prop->type) { - case PROP_ENUM: { + case PROP_ENUM: + { EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop; eprop->defaultvalue = value; @@ -1945,7 +1969,8 @@ void RNA_def_property_boolean_funcs(PropertyRNA *prop, const char *get, const ch } switch (prop->type) { - case PROP_BOOLEAN: { + case PROP_BOOLEAN: + { BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop; if (prop->arraydimension) { @@ -1975,7 +2000,8 @@ void RNA_def_property_int_funcs(PropertyRNA *prop, const char *get, const char * } switch (prop->type) { - case PROP_INT: { + case PROP_INT: + { IntPropertyRNA *iprop = (IntPropertyRNA *)prop; if (prop->arraydimension) { @@ -2006,7 +2032,8 @@ void RNA_def_property_float_funcs(PropertyRNA *prop, const char *get, const char } switch (prop->type) { - case PROP_FLOAT: { + case PROP_FLOAT: + { FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop; if (prop->arraydimension) { @@ -2037,7 +2064,8 @@ void RNA_def_property_enum_funcs(PropertyRNA *prop, const char *get, const char } switch (prop->type) { - case PROP_ENUM: { + case PROP_ENUM: + { EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop; if (get) eprop->get = (PropEnumGetFunc)get; @@ -2062,7 +2090,8 @@ void RNA_def_property_string_funcs(PropertyRNA *prop, const char *get, const cha } switch (prop->type) { - case PROP_STRING: { + case PROP_STRING: + { StringPropertyRNA *sprop = (StringPropertyRNA *)prop; if (get) sprop->get = (PropStringGetFunc)get; @@ -2088,7 +2117,8 @@ void RNA_def_property_pointer_funcs(PropertyRNA *prop, const char *get, const ch } switch (prop->type) { - case PROP_POINTER: { + case PROP_POINTER: + { PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; if (get) pprop->get = (PropPointerGetFunc)get; @@ -2116,7 +2146,8 @@ void RNA_def_property_collection_funcs(PropertyRNA *prop, const char *begin, con } switch (prop->type) { - case PROP_COLLECTION: { + case PROP_COLLECTION: + { CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; if (begin) cprop->begin = (PropCollectionBeginFunc)begin; @@ -2742,7 +2773,8 @@ int rna_parameter_size(PropertyRNA *parm) } else return sizeof(char *); - case PROP_POINTER: { + case PROP_POINTER: + { #ifdef RNA_RUNTIME if (parm->flag & PROP_RNAPTR) return sizeof(PointerRNA); @@ -2889,7 +2921,8 @@ void RNA_def_property_duplicate_pointers(StructOrFunctionRNA *cont_, PropertyRNA if (prop->description) prop->description = BLI_strdup(prop->description); switch (prop->type) { - case PROP_BOOLEAN: { + case PROP_BOOLEAN: + { BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop; if (bprop->defaultarray) { @@ -2899,7 +2932,8 @@ void RNA_def_property_duplicate_pointers(StructOrFunctionRNA *cont_, PropertyRNA } break; } - case PROP_INT: { + case PROP_INT: + { IntPropertyRNA *iprop = (IntPropertyRNA *)prop; if (iprop->defaultarray) { @@ -2909,7 +2943,8 @@ void RNA_def_property_duplicate_pointers(StructOrFunctionRNA *cont_, PropertyRNA } break; } - case PROP_ENUM: { + case PROP_ENUM: + { EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop; if (eprop->item) { @@ -2928,7 +2963,8 @@ void RNA_def_property_duplicate_pointers(StructOrFunctionRNA *cont_, PropertyRNA } break; } - case PROP_FLOAT: { + case PROP_FLOAT: + { FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop; if (fprop->defaultarray) { @@ -2938,7 +2974,8 @@ void RNA_def_property_duplicate_pointers(StructOrFunctionRNA *cont_, PropertyRNA } break; } - case PROP_STRING: { + case PROP_STRING: + { StringPropertyRNA *sprop = (StringPropertyRNA *)prop; if (sprop->defaultvalue) sprop->defaultvalue = BLI_strdup(sprop->defaultvalue); @@ -2966,25 +3003,29 @@ void RNA_def_property_free_pointers(PropertyRNA *prop) MEM_freeN(prop->py_data); switch (prop->type) { - case PROP_BOOLEAN: { + case PROP_BOOLEAN: + { BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop; if (bprop->defaultarray) MEM_freeN((void *)bprop->defaultarray); break; } - case PROP_INT: { + case PROP_INT: + { IntPropertyRNA *iprop = (IntPropertyRNA *)prop; if (iprop->defaultarray) MEM_freeN((void *)iprop->defaultarray); break; } - case PROP_FLOAT: { + case PROP_FLOAT: + { FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop; if (fprop->defaultarray) MEM_freeN((void *)fprop->defaultarray); break; } - case PROP_ENUM: { + case PROP_ENUM: + { EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop; for (a = 0; a < eprop->totitem; a++) { @@ -2999,7 +3040,8 @@ void RNA_def_property_free_pointers(PropertyRNA *prop) if (eprop->item) MEM_freeN((void *)eprop->item); break; } - case PROP_STRING: { + case PROP_STRING: + { StringPropertyRNA *sprop = (StringPropertyRNA *)prop; if (sprop->defaultvalue) MEM_freeN((void *)sprop->defaultvalue); diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 7ab359661c5..5bf1cc281ad 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -84,7 +84,8 @@ Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_ switch (ob->type) { case OB_FONT: case OB_CURVE: - case OB_SURF: { + case OB_SURF: + { ListBase dispbase = {NULL, NULL}; DerivedMesh *derivedFinal = NULL; int uv_from_orco; @@ -163,7 +164,8 @@ Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_ break; } - case OB_MBALL: { + case OB_MBALL: + { /* metaballs don't have modifiers, so just convert to mesh */ Object *basis_ob = BKE_mball_basis_find(sce, ob); /* todo, re-generatre for render-res */ diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index f753ff680fd..7f8c6951620 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2982,7 +2982,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) /* locale according to http://www.roseindia.net/tutorials/I18N/locales-list.shtml */ /* if you edit here, please also edit the source/blender/blenfont/intern/blf_lang.c 's locales */ /* Note: As this list is in alphabetical order, and not defined order, - * here is the highest define currently in use: 32 (Brazilian Portuguese). */ + * here is the highest define currently in use: 33 (Hebrew). */ static EnumPropertyItem language_items[] = { { 0, "", 0, N_("Nearly done"), ""}, { 0, "DEFAULT", 0, "Default (Default)", ""}, @@ -3008,6 +3008,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) { 6, "FINNISH", 0, "Finnish (Suomi)", "fi_FI"}, { 5, "GERMAN", 0, "German (Deutsch)", "de_DE"}, {23, "GREEK", 0, "Greek (Ελληνικά)", "el_GR"}, + {33, "HEBREW", 0, "Hebrew (עִבְרִית)", "he_IL"}, {31, "HUNGARIAN", 0, "Hungarian (magyar)", "hu_HU"}, {27, "INDONESIAN", 0, "Indonesian (Bahasa indonesia)", "id_ID"}, {29, "KYRGYZ", 0, "Kyrgyz (Кыргыз тили)", "ky_KG"}, diff --git a/source/blender/nodes/composite/nodes/node_composite_channelMatte.c b/source/blender/nodes/composite/nodes/node_composite_channelMatte.c index cda6fa85d74..06b77de463b 100644 --- a/source/blender/nodes/composite/nodes/node_composite_channelMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_channelMatte.c @@ -82,15 +82,18 @@ static void do_channel_matte(bNode *node, float *out, float *in) } case 1: { /* Alpha=G-MAX(R, B) */ switch (node->custom2) { - case 1: { + case 1: + { alpha=in[0]-MAX2(in[1], in[2]); break; } - case 2: { + case 2: + { alpha=in[1]-MAX2(in[0], in[2]); break; } - case 3: { + case 3: + { alpha=in[2]-MAX2(in[0], in[1]); break; } diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c index ce11545c90d..45b767c6eda 100644 --- a/source/blender/python/generic/bgl.c +++ b/source/blender/python/generic/bgl.c @@ -44,7 +44,7 @@ #include "BLI_utildefines.h" static PyObject *Buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds); -static PyObject *Method_ShaderSource (PyObject *self, PyObject *args); +static PyObject *Method_ShaderSource(PyObject *self, PyObject *args); /* Buffer sequence methods */ diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index dee9d036891..17f17baba0e 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2708,7 +2708,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U switch (type) { /* mouse move */ - case GHOST_kEventCursorMove: { + case GHOST_kEventCursorMove: + { if (win->active) { GHOST_TEventCursorData *cd = customdata; wmEvent *lastevent = win->queue.last; @@ -2751,7 +2752,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U } break; } - case GHOST_kEventTrackpad: { + case GHOST_kEventTrackpad: + { GHOST_TEventTrackpadData *pd = customdata; switch (pd->subtype) { case GHOST_kTrackpadEventMagnify: @@ -2783,7 +2785,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U } /* mouse button */ case GHOST_kEventButtonDown: - case GHOST_kEventButtonUp: { + case GHOST_kEventButtonUp: + { GHOST_TEventButtonData *bd = customdata; event.val = (type == GHOST_kEventButtonDown) ? KM_PRESS : KM_RELEASE; @@ -2831,7 +2834,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U } /* keyboard */ case GHOST_kEventKeyDown: - case GHOST_kEventKeyUp: { + case GHOST_kEventKeyUp: + { GHOST_TEventKeyData *kd = customdata; event.type = convert_key(kd->key); event.ascii = kd->ascii; @@ -2915,7 +2919,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U break; } - case GHOST_kEventWheel: { + case GHOST_kEventWheel: + { GHOST_TEventWheelData *wheelData = customdata; if (wheelData->z > 0) @@ -2928,7 +2933,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U break; } - case GHOST_kEventTimer: { + case GHOST_kEventTimer: + { event.type = TIMER; event.custom = EVT_DATA_TIMER; event.customdata = customdata; @@ -2937,7 +2943,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U break; } - case GHOST_kEventNDOFMotion: { + case GHOST_kEventNDOFMotion: + { event.type = NDOF_MOTION; attach_ndof_data(&event, customdata); wm_event_add(win, &event); @@ -2947,7 +2954,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U break; } - case GHOST_kEventNDOFButton: { + case GHOST_kEventNDOFButton: + { GHOST_TEventNDOFButtonData *e = customdata; event.type = NDOF_BUTTON_NONE + e->button; @@ -2973,12 +2981,12 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U case GHOST_kNumEventTypes: break; - case GHOST_kEventWindowDeactivate: { + case GHOST_kEventWindowDeactivate: + { event.type = WINDEACTIVATE; wm_event_add(win, &event); break; - } } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index b83b93454e6..59c8235faf0 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -724,11 +724,13 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr break; } - case GHOST_kEventWindowClose: { + case GHOST_kEventWindowClose: + { wm_window_close(C, wm, win); break; } - case GHOST_kEventWindowUpdate: { + case GHOST_kEventWindowUpdate: + { if (G.debug & G_DEBUG_EVENTS) { printf("%s: ghost redraw %d\n", __func__, win->winid); } @@ -739,7 +741,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr break; } case GHOST_kEventWindowSize: - case GHOST_kEventWindowMove: { + case GHOST_kEventWindowMove: + { GHOST_TWindowState state; state = GHOST_GetWindowState(win->ghostwin); win->windowstate = state; diff --git a/source/darwin/blender.app/Contents/Info.plist b/source/darwin/blender.app/Contents/Info.plist index 37920dc8181..064ffe5bc3f 100644 --- a/source/darwin/blender.app/Contents/Info.plist +++ b/source/darwin/blender.app/Contents/Info.plist @@ -48,5 +48,7 @@ OMP_NUM_THREADS 4 + NSPrincipalClass + NSApplication diff --git a/source/darwin/blenderplayer.app/Contents/Info.plist b/source/darwin/blenderplayer.app/Contents/Info.plist index 54364d18866..c7b9ceb568e 100644 --- a/source/darwin/blenderplayer.app/Contents/Info.plist +++ b/source/darwin/blenderplayer.app/Contents/Info.plist @@ -1,33 +1,27 @@ - - + + CFBundleInfoDictionaryVersion 6.0 - CFBundleExecutable blenderplayer - CFBundlePackageType APPL CFBundleSignature ???? - CFBundleIconFile blender player icon.icns - CFBundleName BlenderPlayer CFBundleIdentifier org.blenderfoundation.blenderplayer - CFBundleVersion ${MACOSX_BUNDLE_LONG_VERSION_STRING}, Blender Foundation CFBundleShortVersionString ${MACOSX_BUNDLE_SHORT_VERSION_STRING} CFBundleGetInfoString ${MACOSX_BUNDLE_LONG_VERSION_STRING}, Blender Foundation - CFBundleDocumentTypes @@ -49,5 +43,7 @@ + NSPrincipalClass + NSApplication From f1a498acee1697a385992a0f01bfdc17dc64163d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 9 Sep 2012 08:33:42 +0000 Subject: [PATCH 124/160] Merging r50478 through r50483 from trunk into soc-2011-tomato --- source/blender/blenkernel/intern/action.c | 2 +- source/blender/blenkernel/intern/blender.c | 68 +++++++++++++------ source/blender/blenkernel/intern/constraint.c | 4 +- source/blender/editors/gpencil/drawgpencil.c | 8 +-- .../blender/editors/gpencil/gpencil_paint.c | 9 ++- source/blender/editors/interface/interface.c | 7 +- .../editors/interface/interface_handlers.c | 33 ++++++--- .../editors/interface/interface_icons.c | 2 +- .../editors/interface/interface_intern.h | 2 +- .../editors/interface/interface_regions.c | 4 +- source/blender/editors/interface/view2d.c | 6 +- source/blender/editors/interface/view2d_ops.c | 12 ++-- source/blender/editors/mesh/editface.c | 4 +- .../editors/object/object_constraint.c | 12 ++-- .../blender/editors/object/object_relations.c | 2 +- source/blender/editors/object/object_vgroup.c | 4 +- source/blender/editors/screen/screen_edit.c | 2 +- .../editors/sculpt_paint/paint_vertex.c | 10 +-- .../editors/space_action/action_select.c | 8 +-- .../blender/editors/space_graph/graph_draw.c | 18 ++--- .../editors/space_graph/graph_select.c | 2 +- .../blender/editors/space_image/image_ops.c | 2 +- .../editors/space_logic/logic_window.c | 24 +++++-- source/blender/editors/space_nla/nla_select.c | 8 +-- source/blender/editors/space_node/node_edit.c | 2 +- .../editors/space_outliner/outliner_draw.c | 4 +- .../editors/space_outliner/outliner_tree.c | 6 +- .../editors/space_sequencer/sequencer_edit.c | 8 +-- .../editors/space_view3d/drawarmature.c | 33 +++++---- .../blender/editors/space_view3d/drawobject.c | 60 ++++++++-------- .../editors/space_view3d/view3d_edit.c | 12 ++-- .../editors/space_view3d/view3d_header.c | 6 +- .../editors/space_view3d/view3d_select.c | 6 +- .../editors/space_view3d/view3d_view.c | 2 +- 34 files changed, 226 insertions(+), 166 deletions(-) diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 6a8ddd8e00a..3e5dff74f3b 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -810,7 +810,7 @@ void framechange_poses_clear_unkeyed(void) /* TODO: proxies may/may not be correctly handled here... (this needs checking) */ for (ob = G.main->object.first; ob; ob = ob->id.next) { /* we only need to do this on objects with a pose */ - if ( (pose = ob->pose) ) { + if ((pose = ob->pose)) { for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { if (pchan->bone) pchan->bone->flag &= ~BONE_UNKEYED; diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 02ce3a36b14..2f66dbde97c 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -44,7 +44,8 @@ #include #include #include -#include // for open +#include /* for open */ +#include #include "MEM_guardedalloc.h" @@ -518,8 +519,13 @@ void BKE_write_undo(bContext *C, const char *name) int nr /*, success */ /* UNUSED */; UndoElem *uel; - if ( (U.uiflag & USER_GLOBALUNDO) == 0) return; - if (U.undosteps == 0) return; + if ((U.uiflag & USER_GLOBALUNDO) == 0) { + return; + } + + if (U.undosteps == 0) { + return; + } /* remove all undos after (also when curundo == NULL) */ while (undobase.last != curundo) { @@ -720,38 +726,60 @@ void BKE_undo_save_quit(void) { UndoElem *uel; MemFileChunk *chunk; - int file; char str[FILE_MAX]; - - if ( (U.uiflag & USER_GLOBALUNDO) == 0) return; - + const int flag = O_BINARY + O_WRONLY + O_CREAT + O_TRUNC + O_EXCL; + int file; + + if ((U.uiflag & USER_GLOBALUNDO) == 0) { + return; + } + uel = curundo; if (uel == NULL) { - printf("No undo buffer to save recovery file\n"); + fprintf(stderr, "No undo buffer to save recovery file\n"); return; } - + /* no undo state to save */ - if (undobase.first == undobase.last) return; - + if (undobase.first == undobase.last) { + return; + } + + /* save the undo state as quit.blend */ BLI_make_file_string("/", str, BLI_temporary_dir(), "quit.blend"); - file = BLI_open(str, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666); + /* first try create the file, if it exists call without 'O_CREAT', + * to avoid writing to a symlink - use 'O_EXCL' (CVE-2008-1103) */ + errno = 0; + file = BLI_open(str, flag, 0666); if (file == -1) { - //XXX error("Unable to save %s, check you have permissions", str); + if (errno == EEXIST) { + errno = 0; + file = BLI_open(str, flag & ~O_CREAT, 0666); + } + } + + if (file == -1) { + fprintf(stderr, "Unable to save '%s': %s\n", + str, errno ? strerror(errno) : "Unknown error opening file"); return; } - chunk = uel->memfile.chunks.first; - while (chunk) { - if (write(file, chunk->buf, chunk->size) != chunk->size) break; - chunk = chunk->next; + for (chunk = uel->memfile.chunks.first; chunk; chunk = chunk->next) { + if (write(file, chunk->buf, chunk->size) != chunk->size) { + break; + } } - + close(file); - if (chunk) ; //XXX error("Unable to save %s, internal error", str); - else printf("Saved session recovery to %s\n", str); + if (chunk) { + fprintf(stderr, "Unable to save '%s': %s\n", + str, errno ? strerror(errno) : "Unknown error writing file"); + } + else { + printf("Saved session recovery to '%s'\n", str); + } } /* sets curscene */ diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 391891d3985..8d7f4e4117a 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -4292,8 +4292,8 @@ bConstraintTypeInfo *get_constraint_typeinfo(int type) } /* only return for valid types */ - if ( (type >= CONSTRAINT_TYPE_NULL) && - (type < NUM_CONSTRAINT_TYPES) ) + if ((type >= CONSTRAINT_TYPE_NULL) && + (type < NUM_CONSTRAINT_TYPES)) { /* there shouldn't be any segfaults here... */ return constraintsTypeInfo[type]; diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 7906d632f86..5a94d54f329 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -177,8 +177,8 @@ static void gp_draw_stroke_point(bGPDspoint *points, short thickness, short dfla /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, simple dot looks ok * - also mandatory in if Image Editor 'image-based' dot */ - if ( (thickness < GP_DRAWTHICKNESS_SPECIAL) || - ((dflag & GP_DRAWDATA_IEDITHACK) && (sflag & GP_STROKE_2DSPACE)) ) + if ((thickness < GP_DRAWTHICKNESS_SPECIAL) || + ((dflag & GP_DRAWDATA_IEDITHACK) && (sflag & GP_STROKE_2DSPACE))) { glBegin(GL_POINTS); glVertex2fv(co); @@ -253,8 +253,8 @@ static void gp_draw_stroke(bGPDspoint *points, int totpoints, short thickness_s, /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, 'smooth' opengl lines look better * - 'smooth' opengl lines are also required if Image Editor 'image-based' stroke */ - if ( (thickness < GP_DRAWTHICKNESS_SPECIAL) || - ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) ) + if ((thickness < GP_DRAWTHICKNESS_SPECIAL) || + ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D))) { bGPDspoint *pt; int i; diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index e4bfbea75b0..dfd2783fad6 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -778,7 +778,8 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) } /* eraser tool - check if part of stroke occurs within last segment drawn by eraser */ -static short gp_stroke_eraser_strokeinside(int mval[], int UNUSED(mvalo[]), short rad, short x0, short y0, short x1, short y1) +static short gp_stroke_eraser_strokeinside(const int mval[], const int UNUSED(mvalo[]), + int rad, int x0, int y0, int x1, int y1) { /* simple within-radius check for now */ if (edge_inside_circle(mval[0], mval[1], rad, x0, y0, x1, y1)) @@ -790,7 +791,9 @@ static short gp_stroke_eraser_strokeinside(int mval[], int UNUSED(mvalo[]), shor /* eraser tool - evaluation per stroke */ // TODO: this could really do with some optimization (KD-Tree/BVH?) -static void gp_stroke_eraser_dostroke(tGPsdata *p, int mval[], int mvalo[], short rad, rcti *rect, bGPDframe *gpf, bGPDstroke *gps) +static void gp_stroke_eraser_dostroke(tGPsdata *p, + const int mval[], const int mvalo[], + short rad, const rcti *rect, bGPDframe *gpf, bGPDstroke *gps) { bGPDspoint *pt1, *pt2; int x0 = 0, y0 = 0, x1 = 0, y1 = 0; @@ -827,7 +830,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, int mval[], int mvalo[], shor /* do boundbox check first */ if (BLI_rcti_isect_pt(rect, x0, y0)) { /* only check if point is inside */ - if ( ((x0 - mval[0]) * (x0 - mval[0]) + (y0 - mval[1]) * (y0 - mval[1])) <= rad * rad) { + if (((x0 - mval[0]) * (x0 - mval[0]) + (y0 - mval[1]) * (y0 - mval[1])) <= rad * rad) { /* free stroke */ MEM_freeN(gps->points); BLI_freelinkN(&gpf->strokes, gps); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index f97b9864539..515db9559ae 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -134,7 +134,7 @@ void ui_block_to_window(const ARegion *ar, uiBlock *block, int *x, int *y) *y = (int)(fy + 0.5f); } -void ui_block_to_window_rct(const ARegion *ar, uiBlock *block, rctf *graph, rcti *winr) +void ui_block_to_window_rct(const ARegion *ar, uiBlock *block, const rctf *graph, rcti *winr) { rctf tmpr; @@ -1242,8 +1242,7 @@ void ui_delete_linkline(uiLinkLine *line, uiBut *but) else { b = 0; for (a = 0; a < (*(link->totlink)); a++) { - - if ( (*(link->ppoin))[a] != line->to->poin) { + if ((*(link->ppoin))[a] != line->to->poin) { (*(link->ppoin))[b] = (*(link->ppoin))[a]; b++; } @@ -2468,7 +2467,7 @@ static void ui_block_do_align_but(uiBut *first, short nr) flag |= UI_BUT_ALIGN_TOP; } - if ( (flag & UI_BUT_ALIGN_TOP) == 0) { /* stil top row */ + if ((flag & UI_BUT_ALIGN_TOP) == 0) { /* stil top row */ if (prev) { if (next && buts_are_horiz(but, next)) flag = UI_BUT_ALIGN_DOWN | UI_BUT_ALIGN_LEFT | UI_BUT_ALIGN_RIGHT; diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index dcd652a6590..787e79fe8b6 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -81,6 +81,8 @@ static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to); static void ui_add_link(bContext *C, uiBut *from, uiBut *to); +static int ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *menu, int mx, int my); + /***************** structs and defines ****************/ #define BUTTON_TOOLTIP_DELAY 0.500 @@ -755,7 +757,7 @@ static void ui_delete_active_linkline(uiBlock *block) b = 0; for (a = 0; a < (*(link->totlink)); a++) { - if ( (*(link->ppoin))[a] != line->to->poin) { + if ((*(link->ppoin))[a] != line->to->poin) { (*(link->ppoin))[b] = (*(link->ppoin))[a]; b++; } @@ -866,7 +868,7 @@ static void ui_add_link(bContext *C, uiBut *from, uiBut *to) void **oldppoin; int a; - if ( (line = ui_is_a_link(from, to)) ) { + if ((line = ui_is_a_link(from, to))) { line->flag |= UI_SELECT; ui_delete_active_linkline(from->block); return; @@ -5798,22 +5800,35 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) switch (event->type) { case MOUSEMOVE: { - uiBut *bt; + /* if the mouse is over the button, do nothing */ + if (ui_mouse_inside_button(data->region, but, event->x, event->y)) { + break; + } + /* if the mouse is over the menu, also do nothing */ if (data->menu && data->menu->region) { if (ui_mouse_inside_region(data->menu->region, event->x, event->y)) { break; } - } + else { + /* make a rectangle between the menu and the button that opened it, + * this avoids any space between them exiting the popup. see [#29072] - campbell */ + rctf rct_all = but->rect; + rctf rct_win; - bt = ui_but_find_mouse_over(ar, event->x, event->y); + ui_block_to_window_fl(ar, block, &rct_all.xmin, &rct_all.ymin); + ui_block_to_window_fl(ar, block, &rct_all.xmax, &rct_all.ymax); - if (bt && bt->active != data) { - if (but->type != COL) { /* exception */ - data->cancel = 1; + BLI_rctf_rcti_copy(&rct_win, &data->menu->region->winrct); + BLI_rctf_union(&rct_all, &rct_win); + + if (BLI_rctf_isect_pt(&rct_all, event->x, event->y)) { + break; + } } - button_activate_state(C, but, BUTTON_STATE_EXIT); } + + button_activate_state(C, but, BUTTON_STATE_EXIT); break; } } diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 1871f3c8336..e825ff7880d 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -620,7 +620,7 @@ static void init_iconfile_list(struct ListBase *list) if (restoredir && !chdir(olddir)) {} /* fix warning about checking return value */ for (i = 0; i < totfile; i++) { - if ( (dir[i].type & S_IFREG) ) { + if ((dir[i].type & S_IFREG)) { char *filename = dir[i].relname; if (BLI_testextensie(filename, ".png")) { diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index d39fbbf7e61..e728c861933 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -348,7 +348,7 @@ void ui_fontscale(short *points, float aspect); extern void ui_block_to_window_fl(const struct ARegion *ar, uiBlock *block, float *x, float *y); extern void ui_block_to_window(const struct ARegion *ar, uiBlock *block, int *x, int *y); -extern void ui_block_to_window_rct(const struct ARegion *ar, uiBlock *block, rctf *graph, rcti *winr); +extern void ui_block_to_window_rct(const struct ARegion *ar, uiBlock *block, const rctf *graph, rcti *winr); extern void ui_window_to_block_fl(const struct ARegion *ar, uiBlock *block, float *x, float *y); extern void ui_window_to_block(const struct ARegion *ar, uiBlock *block, int *x, int *y); extern void ui_window_to_region(const ARegion *ar, int *x, int *y); diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 301aea896bc..a4f1067d069 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -2021,8 +2021,8 @@ static void picker_new_hide_reveal(uiBlock *block, short colormode) /* tag buttons */ for (bt = block->buttons.first; bt; bt = bt->next) { - if (bt->func == do_picker_rna_cb && bt->type == NUMSLI) { - /* RGB sliders (color circle is always shown) */ + if (bt->func == do_picker_rna_cb && bt->type == NUMSLI && bt->rnaindex != 3) { + /* RGB sliders (color circle and alpha are always shown) */ if (colormode == 0) bt->flag &= ~UI_HIDDEN; else bt->flag |= UI_HIDDEN; } diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index c3059b8d575..0f1d1a24dcb 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -544,7 +544,7 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize) curheight = BLI_RCT_SIZE_Y(cur); /* width */ - if ( (curwidth > totwidth) && !(v2d->keepzoom & (V2D_KEEPZOOM | V2D_LOCKZOOM_X | V2D_LIMITZOOM)) ) { + if ((curwidth > totwidth) && !(v2d->keepzoom & (V2D_KEEPZOOM | V2D_LOCKZOOM_X | V2D_LIMITZOOM))) { /* if zoom doesn't have to be maintained, just clamp edges */ if (cur->xmin < tot->xmin) cur->xmin = tot->xmin; if (cur->xmax > tot->xmax) cur->xmax = tot->xmax; @@ -627,7 +627,7 @@ void UI_view2d_curRect_validate_resize(View2D *v2d, int resize) } /* height */ - if ( (curheight > totheight) && !(v2d->keepzoom & (V2D_KEEPZOOM | V2D_LOCKZOOM_Y | V2D_LIMITZOOM)) ) { + if ((curheight > totheight) && !(v2d->keepzoom & (V2D_KEEPZOOM | V2D_LOCKZOOM_Y | V2D_LIMITZOOM))) { /* if zoom doesn't have to be maintained, just clamp edges */ if (cur->ymin < tot->ymin) cur->ymin = tot->ymin; if (cur->ymax > tot->ymax) cur->ymax = tot->ymax; @@ -1874,7 +1874,7 @@ void UI_view2d_listview_view_to_cell(View2D *v2d, short columnwidth, short rowhe const int y = (int)(floorf(fabsf(viewy) + 0.5f) - starty); /* sizes must not be negative */ - if ( (v2d == NULL) || ((columnwidth <= 0) && (rowheight <= 0)) ) { + if ((v2d == NULL) || ((columnwidth <= 0) && (rowheight <= 0))) { if (column) *column = 0; if (row) *row = 0; diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 5b19bb2d3c9..99313edc289 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -1719,8 +1719,8 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, wmEvent *event) * NOTE: see view2d.c for latest conditions, and keep this in sync with that */ if (ELEM(vsm->zone, SCROLLHANDLE_MIN, SCROLLHANDLE_MAX)) { - if ( ((vsm->scroller == 'h') && (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) == 0) || - ((vsm->scroller == 'v') && (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) == 0) ) + if (((vsm->scroller == 'h') && (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) == 0) || + ((vsm->scroller == 'v') && (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) == 0)) { /* switch to bar (i.e. no scaling gets handled) */ vsm->zone = SCROLLHANDLE_BAR; @@ -1729,8 +1729,8 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, wmEvent *event) /* check if zone is inappropriate (i.e. 'bar' but panning is banned), so cannot continue */ if (vsm->zone == SCROLLHANDLE_BAR) { - if ( ((vsm->scroller == 'h') && (v2d->keepofs & V2D_LOCKOFS_X)) || - ((vsm->scroller == 'v') && (v2d->keepofs & V2D_LOCKOFS_Y)) ) + if (((vsm->scroller == 'h') && (v2d->keepofs & V2D_LOCKOFS_X)) || + ((vsm->scroller == 'v') && (v2d->keepofs & V2D_LOCKOFS_Y))) { /* free customdata initialized */ scroller_activate_exit(C, op); @@ -1741,8 +1741,8 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, wmEvent *event) } /* zone is also inappropriate if scroller is not visible... */ - if ( ((vsm->scroller == 'h') && (v2d->scroll & (V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_HORIZONTAL_FULLR))) || - ((vsm->scroller == 'v') && (v2d->scroll & (V2D_SCROLL_VERTICAL_HIDE | V2D_SCROLL_VERTICAL_FULLR))) ) + if (((vsm->scroller == 'h') && (v2d->scroll & (V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_HORIZONTAL_FULLR))) || + ((vsm->scroller == 'v') && (v2d->scroll & (V2D_SCROLL_VERTICAL_HIDE | V2D_SCROLL_VERTICAL_FULLR))) ) { /* free customdata initialized */ scroller_activate_exit(C, op); diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 4e30cff5fde..94e10b53b29 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -137,10 +137,10 @@ void paintface_hide(Object *ob, const int unselected) while (a--) { if ((mpoly->flag & ME_HIDE) == 0) { if (unselected) { - if ( (mpoly->flag & ME_FACE_SEL) == 0) mpoly->flag |= ME_HIDE; + if ((mpoly->flag & ME_FACE_SEL) == 0) mpoly->flag |= ME_HIDE; } else { - if ( (mpoly->flag & ME_FACE_SEL)) mpoly->flag |= ME_HIDE; + if ((mpoly->flag & ME_FACE_SEL)) mpoly->flag |= ME_HIDE; } } if (mpoly->flag & ME_HIDE) mpoly->flag &= ~ME_FACE_SEL; diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 08ba6a1e682..1ef7c12b409 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -1392,9 +1392,9 @@ static short get_new_constraint_target(bContext *C, int con_type, Object **tar_o /* just use the first object we encounter (that isn't the active object) * and which fulfills the criteria for the object-target that we've got */ - if ( (ob != obact) && - ((!only_curve) || (ob->type == OB_CURVE)) && - ((!only_mesh) || (ob->type == OB_MESH)) ) + if ((ob != obact) && + ((!only_curve) || (ob->type == OB_CURVE)) && + ((!only_mesh) || (ob->type == OB_MESH))) { /* set target */ *tar_ob = ob; @@ -1478,15 +1478,15 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase if (type == CONSTRAINT_TYPE_NULL) { return OPERATOR_CANCELLED; } - if ( (type == CONSTRAINT_TYPE_RIGIDBODYJOINT) && (list != &ob->constraints) ) { + if ((type == CONSTRAINT_TYPE_RIGIDBODYJOINT) && (list != &ob->constraints)) { BKE_report(op->reports, RPT_ERROR, "Rigid Body Joint Constraint can only be added to Objects"); return OPERATOR_CANCELLED; } - if ( (type == CONSTRAINT_TYPE_KINEMATIC) && ((!pchan) || (list != &pchan->constraints)) ) { + if ((type == CONSTRAINT_TYPE_KINEMATIC) && ((!pchan) || (list != &pchan->constraints))) { BKE_report(op->reports, RPT_ERROR, "IK Constraint can only be added to Bones"); return OPERATOR_CANCELLED; } - if ( (type == CONSTRAINT_TYPE_SPLINEIK) && ((!pchan) || (list != &pchan->constraints)) ) { + if ((type == CONSTRAINT_TYPE_SPLINEIK) && ((!pchan) || (list != &pchan->constraints))) { BKE_report(op->reports, RPT_ERROR, "Spline IK Constraint can only be added to Bones"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index d8c964ff2df..cafc7ce9300 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1518,7 +1518,7 @@ static void single_object_users(Scene *scene, View3D *v3d, int flag) */ ob->id.newid = NULL; - if ( (base->flag & flag) == flag) { + if ((base->flag & flag) == flag) { if (ob->id.lib == NULL && ob->id.us > 1) { /* base gets copy of object */ obn = BKE_object_copy(ob); diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index c8ba9240db3..b31d2b8b076 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -1542,8 +1542,8 @@ void ED_vgroup_mirror(Object *ob, const short mirror_weights, const short flip_v int *flip_map, flip_map_len; const int def_nr = ob->actdef - 1; - if ( (mirror_weights == 0 && flip_vgroups == 0) || - (BLI_findlink(&ob->defbase, def_nr) == NULL) ) + if ((mirror_weights == 0 && flip_vgroups == 0) || + (BLI_findlink(&ob->defbase, def_nr) == NULL)) { return; } diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index adffb97c16f..3642cc0d8d4 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1471,7 +1471,7 @@ void ED_screen_set_scene(bContext *C, bScreen *screen, Scene *scene) /* are there cameras in the views that are not in the scene? */ for (sc = CTX_data_main(C)->screen.first; sc; sc = sc->id.next) { - if ( (U.flag & USER_SCENEGLOBAL) || sc == screen) { + if ((U.flag & USER_SCENEGLOBAL) || sc == screen) { ScrArea *sa = sc->areabase.first; while (sa) { SpaceLink *sl = sa->spacedata.first; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index c52bae215ec..ba440e98290 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -1639,9 +1639,9 @@ static int apply_mp_locks_normalize(Mesh *me, const WeightPaintInfo *wpi, dv_test.totweight = dv->totweight; /* do not multi-paint if a locked group is selected or the active group is locked * !lock_flags[dw->def_nr] helps if nothing is selected, but active group is locked */ - if ( (wpi->lock_flags == NULL) || - ((wpi->lock_flags[dw->def_nr] == FALSE) && /* def_nr range has to be checked for by caller */ - has_locked_group_selected(wpi->defbase_tot, wpi->defbase_sel, wpi->lock_flags) == FALSE)) + if ((wpi->lock_flags == NULL) || + ((wpi->lock_flags[dw->def_nr] == FALSE) && /* def_nr range has to be checked for by caller */ + has_locked_group_selected(wpi->defbase_tot, wpi->defbase_sel, wpi->lock_flags) == FALSE)) { if (wpi->do_multipaint && wpi->defbase_tot_sel > 1) { if (change && change != 1) { @@ -1787,8 +1787,8 @@ static void do_weight_paint_vertex( /* If there are no locks or multipaint, * then there is no need to run the more complicated checks */ - if ( (do_multipaint_totsel == FALSE) && - (wpi->lock_flags == NULL || has_locked_group(dv, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags) == FALSE)) + if ((do_multipaint_totsel == FALSE) && + (wpi->lock_flags == NULL || has_locked_group(dv, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags) == FALSE)) { dw->weight = wpaint_blend(wp, dw->weight, dw_prev->weight, alpha, paintweight, wpi->brush_alpha_value, wpi->do_flip, FALSE); diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index c9f765ac3db..9ab79d73e76 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -255,8 +255,8 @@ static void borderselect_action(bAnimContext *ac, rcti rect, short mode, short s } /* perform vertical suitability check (if applicable) */ - if ( (mode == ACTKEYS_BORDERSEL_FRAMERANGE) || - !((ymax < rectf.ymin) || (ymin > rectf.ymax)) ) + if ((mode == ACTKEYS_BORDERSEL_FRAMERANGE) || + !((ymax < rectf.ymin) || (ymin > rectf.ymax))) { /* loop over data selecting */ if (ale->type == ANIMTYPE_GPLAYER) @@ -802,8 +802,8 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se TimeMarker *marker; for (marker = markers->first; marker; marker = marker->next) { - if ( ((leftright == ACTKEYS_LRSEL_LEFT) && (marker->frame < CFRA)) || - ((leftright == ACTKEYS_LRSEL_RIGHT) && (marker->frame >= CFRA)) ) + if (((leftright == ACTKEYS_LRSEL_LEFT) && (marker->frame < CFRA)) || + ((leftright == ACTKEYS_LRSEL_RIGHT) && (marker->frame >= CFRA))) { marker->flag |= SELECT; } diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index ad97b7853c4..e4bda15bc7d 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -235,7 +235,7 @@ static void draw_fcurve_vertices_handles(FCurve *fcu, SpaceIpo *sipo, View2D *v2 * if a Graph Editor option to only show handles of selected keys is on. */ if (!sel_handle_only || BEZSELECTED(bezt) ) { - if ( (!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ)) ) { + if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) { if ((bezt->f1 & SELECT) == sel) /* && v2d->cur.xmin < bezt->vec[0][0] < v2d->cur.xmax)*/ draw_fcurve_handle_control(bezt->vec[0][0], bezt->vec[0][1], xscale, yscale, hsize); } @@ -378,8 +378,8 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu) } else { /* only draw first handle if previous segment was had handles, and selection is ok */ - if ( ((bezt->f1 & SELECT) == sel) && - ( (!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ)) ) ) + if (((bezt->f1 & SELECT) == sel) && + ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ)))) { fp = bezt->vec[0]; UI_GetThemeColor3ubv(basecol + bezt->h1, col); @@ -390,8 +390,8 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu) } /* only draw second handle if this segment is bezier, and selection is ok */ - if ( ((bezt->f3 & SELECT) == sel) && - (bezt->ipo == BEZT_IPO_BEZ) ) + if (((bezt->f3 & SELECT) == sel) && + (bezt->ipo == BEZT_IPO_BEZ)) { fp = bezt->vec[1]; UI_GetThemeColor3ubv(basecol + bezt->h2, col); @@ -846,11 +846,11 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid /* 1) draw curve line */ { /* set color/drawing style for curve itself */ - if ( ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) || (fcu->flag & FCURVE_PROTECTED) ) { + if (((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) || (fcu->flag & FCURVE_PROTECTED)) { /* protected curves (non editable) are drawn with dotted lines */ setlinestyle(2); } - if ( ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) || (fcu->flag & FCURVE_MUTED) ) { + if (((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) || (fcu->flag & FCURVE_MUTED)) { /* muted curves are drawn in a grayish hue */ // XXX should we have some variations? UI_ThemeColorShade(TH_HEADER, 50); @@ -878,7 +878,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid */ draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid); } - else if ( ((fcu->bezt) || (fcu->fpt)) && (fcu->totvert) ) { + else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) { /* just draw curve based on defined data (i.e. no modifiers) */ if (fcu->bezt) draw_fcurve_curve_bezts(ac, ale->id, fcu, &ar->v2d); @@ -908,7 +908,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid } } } - else if ( ((fcu->bezt) || (fcu->fpt)) && (fcu->totvert) ) { + else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) { /* apply unit mapping */ ANIM_unit_mapping_apply_fcurve(ac->scene, ale->id, fcu, 0); diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 32abad86828..633f2b72cf6 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -942,7 +942,7 @@ static void nearest_fcurve_vert_store(ListBase *matches, View2D *v2d, FCurve *fc /* if there is already a point for the F-Curve, check if this point is closer than that was */ if ((nvi) && (nvi->fcu == fcu)) { /* replace if we are closer, or if equal and that one wasn't selected but we are... */ - if ( (nvi->dist > dist) || ((nvi->sel == 0) && BEZSELECTED(bezt)) ) + if ((nvi->dist > dist) || ((nvi->sel == 0) && BEZSELECTED(bezt))) replace = 1; } /* add new if not replacing... */ diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 44cb3ae578f..05b5d5b0066 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1161,7 +1161,7 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima, /* check for empty path */ if (guess_path && simopts->filepath[0] == 0) { - if ( (G.ima[0] == '/') && (G.ima[1] == '/') && (G.ima[2] == '\0') ) { + if ((G.ima[0] == '/') && (G.ima[1] == '/') && (G.ima[2] == '\0')) { BLI_strncpy(simopts->filepath, "//untitled", FILE_MAX); } else { diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index 12823de60d2..a042145309d 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -878,7 +878,7 @@ static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisf } /* 4th case: select actuator when controller selected */ - if ( (scavisflag & (BUTS_ACT_LINK|BUTS_ACT_STATE)) && (ob->scavisflag & OB_VIS_CONT)) { + if ((scavisflag & (BUTS_ACT_LINK|BUTS_ACT_STATE)) && (ob->scavisflag & OB_VIS_CONT)) { cont= ob->controllers.first; while (cont) { for (a=0; atotlinks; a++) { @@ -921,7 +921,7 @@ static ID **get_selected_and_linked_obs(bContext *C, short *count, short scavisf } while (ob) { - if ( (ob->scavisflag) && (ob != obact)) { + if ((ob->scavisflag) && (ob != obact)) { idar[nr]= (ID *)ob; nr++; } @@ -4539,7 +4539,9 @@ static void logic_buttons_new(bContext *C, ARegion *ar) ob= (Object *)idar[a]; /* only draw the controller common header if "use_visible" */ - if ( (ob->scavisflag & OB_VIS_CONT) == 0) continue; + if ( (ob->scavisflag & OB_VIS_CONT) == 0) { + continue; + } /* Drawing the Controller Header common to all Selected Objects */ @@ -4707,7 +4709,9 @@ static void logic_buttons_new(bContext *C, ARegion *ar) ob= (Object *)idar[a]; /* only draw the actuator common header if "use_visible" */ - if ( (ob->scavisflag & OB_VIS_ACT) == 0) continue; + if ((ob->scavisflag & OB_VIS_ACT) == 0) { + continue; + } row = uiLayoutRow(layout, TRUE); uiDefButBitS(block, TOG, OB_SHOWACT, B_REDR, ob->id.name+2, (short)(xco-10), yco, (short)(width-30), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, "Object name, click to show/hide actuators"); @@ -4834,7 +4838,9 @@ void logic_buttons(bContext *C, ARegion *ar) ob= (Object *)idar[a]; // uiClearButLock(); // uiSetButLock(BKE_object_is_libdata(ob), ERROR_LIBDATA_MESSAGE); - if ( (ob->scavisflag & OB_VIS_CONT) == 0) continue; + if ((ob->scavisflag & OB_VIS_CONT) == 0) { + continue; + } /* presume it is only objects for now */ uiBlockBeginAlign(block); @@ -4972,7 +4978,9 @@ void logic_buttons(bContext *C, ARegion *ar) // uiClearButLock(); // uiSetButLock(BKE_object_is_libdata(ob), ERROR_LIBDATA_MESSAGE); - if ( (ob->scavisflag & OB_VIS_SENS) == 0) continue; + if ((ob->scavisflag & OB_VIS_SENS) == 0) { + continue; + } /* presume it is only objects for now */ uiBlockBeginAlign(block); @@ -5052,7 +5060,9 @@ void logic_buttons(bContext *C, ARegion *ar) ob= (Object *)idar[a]; // uiClearButLock(); // uiSetButLock(BKE_object_is_libdata(ob), ERROR_LIBDATA_MESSAGE); - if ( (ob->scavisflag & OB_VIS_ACT) == 0) continue; + if ((ob->scavisflag & OB_VIS_ACT) == 0) { + continue; + } /* presume it is only objects for now */ uiBlockBeginAlign(block); diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index e7610210881..222c2414fcb 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -245,8 +245,8 @@ static void borderselect_nla_strips(bAnimContext *ac, rcti rect, short mode, sho ymin = ymax - NLACHANNEL_STEP(snla); /* perform vertical suitability check (if applicable) */ - if ( (mode == NLA_BORDERSEL_FRAMERANGE) || - !((ymax < rectf.ymin) || (ymin > rectf.ymax)) ) + if ((mode == NLA_BORDERSEL_FRAMERANGE) || + !((ymax < rectf.ymin) || (ymin > rectf.ymax))) { /* loop over data selecting (only if NLA-Track) */ if (ale->type == ANIMTYPE_NLATRACK) { @@ -255,8 +255,8 @@ static void borderselect_nla_strips(bAnimContext *ac, rcti rect, short mode, sho /* only select strips if they fall within the required ranges (if applicable) */ for (strip = nlt->strips.first; strip; strip = strip->next) { - if ( (mode == NLA_BORDERSEL_CHANNELS) || - BKE_nlastrip_within_bounds(strip, rectf.xmin, rectf.xmax)) + if ((mode == NLA_BORDERSEL_CHANNELS) || + BKE_nlastrip_within_bounds(strip, rectf.xmin, rectf.xmax)) { /* set selection */ ACHANNEL_SET_FLAG(strip, selectmode, NLASTRIP_FLAG_SELECT); diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 90ad1452356..9e04bd36a1f 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -1459,7 +1459,7 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag) if (toggle_flag == NODE_OPTIONS && (node->typeinfo->flag & NODE_OPTIONS) == 0) continue; - if ( (tot_eq && tot_neq) || tot_eq == 0) + if ((tot_eq && tot_neq) || tot_eq == 0) node->flag |= toggle_flag; else node->flag &= ~toggle_flag; diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 42fdd5173d4..21e06f00d8e 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1273,8 +1273,8 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene * we don't expand items when searching in the datablocks but we * still want to highlight any filter matches. */ - if ( (SEARCHING_OUTLINER(soops) || (soops->outlinevis == SO_DATABLOCKS && soops->search_string[0] != 0)) && - (tselem->flag & TSE_SEARCHMATCH)) + if ((SEARCHING_OUTLINER(soops) || (soops->outlinevis == SO_DATABLOCKS && soops->search_string[0] != 0)) && + (tselem->flag & TSE_SEARCHMATCH)) { char col[4]; UI_GetThemeColorType4ubv(TH_MATCH, SPACE_OUTLINER, col); diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 63907f530eb..3e1ce1fea6e 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -1216,8 +1216,8 @@ static int treesort_obtype_alpha(const void *v1, const void *v2) else { /* 2nd we check ob type */ if (x1->idcode == ID_OB && x2->idcode == ID_OB) { - if ( ((Object *)x1->id)->type > ((Object *)x2->id)->type) return 1; - else if ( ((Object *)x1->id)->type > ((Object *)x2->id)->type) return -1; + if (((Object *)x1->id)->type > ((Object *)x2->id)->type) return 1; + else if (((Object *)x1->id)->type > ((Object *)x2->id)->type) return -1; else return 0; } else { @@ -1243,7 +1243,7 @@ static void outliner_sort(SpaceOops *soops, ListBase *lb) tselem = TREESTORE(te); /* sorting rules; only object lists or deformgroups */ - if ( (tselem->type == TSE_DEFGROUP) || (tselem->type == 0 && te->idcode == ID_OB)) { + if ((tselem->type == TSE_DEFGROUP) || (tselem->type == 0 && te->idcode == ID_OB)) { /* count first */ for (te = lb->first; te; te = te->next) totelem++; diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 251806ea358..08c4cff332f 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -381,8 +381,8 @@ Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[ while (seq) { if (seq->machine == (int)y) { /* check for both normal strips, and strips that have been flipped horizontally */ - if ( ((seq->startdisp < seq->enddisp) && (seq->startdisp <= x && seq->enddisp >= x)) || - ((seq->startdisp > seq->enddisp) && (seq->startdisp >= x && seq->enddisp <= x)) ) + if (((seq->startdisp < seq->enddisp) && (seq->startdisp <= x && seq->enddisp >= x)) || + ((seq->startdisp > seq->enddisp) && (seq->startdisp >= x && seq->enddisp <= x)) ) { if (BKE_sequence_tx_test(seq)) { @@ -2447,7 +2447,7 @@ static Sequence *sequence_find_parent(Scene *scene, Sequence *child) if (ed == NULL) return NULL; for (seq = ed->seqbasep->first; seq; seq = seq->next) { - if ( (seq != child) && seq_is_parent(seq, child) ) { + if ((seq != child) && seq_is_parent(seq, child)) { parent = seq; break; } @@ -2563,7 +2563,7 @@ static int sequencer_rendersize_exec(bContext *C, wmOperator *UNUSED(op)) if (se) { // prevent setting the render size if sequence values aren't initialized - if ( (se->orig_width > 0) && (se->orig_height > 0) ) { + if ((se->orig_width > 0) && (se->orig_height > 0)) { scene->r.xsch = se->orig_width; scene->r.ysch = se->orig_height; WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index 4472ff280e9..ecce12b8cba 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -272,7 +272,7 @@ static short set_pchan_glColor(short colCode, int boneflag, short constflag) case PCHAN_COLOR_LINEBONE: { /* inner part in background color or constraint */ - if ( (constflag) && ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS)) ) { + if ((constflag) && ((bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS))) { if (constflag & PCHAN_HAS_TARGET) glColor3ub(255, 150, 0); else if (constflag & PCHAN_HAS_IK) glColor3ub(255, 255, 0); else if (constflag & PCHAN_HAS_SPLINEIK) glColor3ub(200, 255, 0); @@ -1540,7 +1540,7 @@ static void draw_pose_dofs(Object *ob) for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { bone = pchan->bone; - if ( (bone) && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) { + if ((bone != NULL) && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) { if (bone->flag & BONE_SELECTED) { if (bone->layer & arm->layer) { if (pchan->ikflag & (BONE_IK_XLIMIT | BONE_IK_ZLIMIT)) { @@ -1701,8 +1701,8 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] * NOTE: this is the only case with (NO_DEFORM == 0) flag, as this is for envelope influence drawing */ - if ( (bone->flag & (BONE_HIDDEN_P | BONE_NO_DEFORM | BONE_HIDDEN_PG)) == 0 && - ((G.f & G_PICKSEL) == 0 || (bone->flag & BONE_UNSELECTABLE) == 0) ) + if (((bone->flag & (BONE_HIDDEN_P | BONE_NO_DEFORM | BONE_HIDDEN_PG)) == 0) && + ((G.f & G_PICKSEL) == 0 || (bone->flag & BONE_UNSELECTABLE) == 0)) { if (bone->flag & (BONE_SELECTED)) { if (bone->layer & arm->layer) @@ -1732,8 +1732,8 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, arm->layer_used |= bone->layer; /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] */ - if ( (bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0 && - ((G.f & G_PICKSEL) == 0 || (bone->flag & BONE_UNSELECTABLE) == 0) ) + if (((bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0) && + ((G.f & G_PICKSEL) == 0 || (bone->flag & BONE_UNSELECTABLE) == 0)) { if (bone->layer & arm->layer) { int use_custom = (pchan->custom) && !(arm->flag & ARM_NO_CUSTOM); @@ -1748,8 +1748,9 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* catch exception for bone with hidden parent */ flag = bone->flag; - if ( (bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) ) + if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) { flag &= ~BONE_CONNECTED; + } /* set temporary flag for drawing bone as active, but only if selected */ if (bone == arm->act_bone) @@ -1819,8 +1820,8 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, bone = pchan->bone; /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] */ - if ( (bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0 && - ((G.f & G_PICKSEL) == 0 || (bone->flag & BONE_UNSELECTABLE) == 0) ) + if (((bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0) && + ((G.f & G_PICKSEL) == 0 || (bone->flag & BONE_UNSELECTABLE) == 0) ) { if (bone->layer & arm->layer) { if (pchan->custom) { @@ -1895,8 +1896,8 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, arm->layer_used |= bone->layer; /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] */ - if ( (bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0 && - ((G.f & G_PICKSEL) == 0 || (bone->flag & BONE_UNSELECTABLE) == 0) ) + if (((bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0) && + ((G.f & G_PICKSEL) == 0 || (bone->flag & BONE_UNSELECTABLE) == 0)) { if (bone->layer & arm->layer) { const short constflag = pchan->constflag; @@ -1904,7 +1905,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, /* Draw a line from our root to the parent's tip * - only if V3D_HIDE_HELPLINES is enabled... */ - if ( (do_dashed & 2) && ((bone->flag & BONE_CONNECTED) == 0) ) { + if ((do_dashed & 2) && ((bone->flag & BONE_CONNECTED) == 0)) { if (arm->flag & ARM_POSEMODE) { glLoadName(index & 0xFFFF); /* object tag, for bordersel optim */ UI_ThemeColor(TH_WIRE); @@ -2047,7 +2048,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } /* Draw additional axes on the bone tail */ - if ( (arm->flag & ARM_DRAWAXES) && (arm->flag & ARM_POSEMODE) ) { + if ((arm->flag & ARM_DRAWAXES) && (arm->flag & ARM_POSEMODE)) { glPushMatrix(); copy_m4_m4(bmat, pchan->pose_mat); bone_matrix_translate_y(bmat, pchan->bone->length); @@ -2134,8 +2135,9 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt) /* catch exception for bone with hidden parent */ flag = eBone->flag; - if ( (eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent)) + if ((eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent)) { flag &= ~BONE_CONNECTED; + } /* set temporary flag for drawing bone as active, but only if selected */ if (eBone == arm->act_edbone) @@ -2176,8 +2178,9 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt) /* catch exception for bone with hidden parent */ flag = eBone->flag; - if ( (eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent)) + if ((eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent)) { flag &= ~BONE_CONNECTED; + } /* set temporary flag for drawing bone as active, but only if selected */ if (eBone == arm->act_edbone) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 9ebd2351142..90da3824870 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -2888,7 +2888,7 @@ static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d, if (ts->selectmode == SCE_SELECT_FACE) { draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act); } - else if ( (me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE) ) { + else if ((me->drawflag & ME_DRAWEDGES) || (ts->selectmode & SCE_SELECT_EDGE)) { if (cageDM->drawMappedEdgesInterp && (ts->selectmode & SCE_SELECT_VERTEX)) { glShadeModel(GL_SMOOTH); draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol); @@ -3317,8 +3317,8 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, draw_dm_vert_normals(em, scene, ob, cageDM); } - if ( (me->drawflag & (ME_DRAWEXTRA_EDGELEN | ME_DRAWEXTRA_FACEAREA | ME_DRAWEXTRA_FACEANG)) && - !(v3d->flag2 & V3D_RENDER_OVERRIDE)) + if ((me->drawflag & (ME_DRAWEXTRA_EDGELEN | ME_DRAWEXTRA_FACEAREA | ME_DRAWEXTRA_FACEANG)) && + !(v3d->flag2 & V3D_RENDER_OVERRIDE)) { draw_em_measure_stats(v3d, ob, em, &scene->unit); } @@ -3415,14 +3415,14 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D else if (dt == OB_WIRE || totface == 0) { draw_wire = OBDRAW_WIRE_ON; /* draw wire only, no depth buffer stuff */ } - else if ( ((is_obact && ob->mode & OB_MODE_TEXTURE_PAINT)) || - check_object_draw_texture(scene, v3d, dt)) + else if (((is_obact && ob->mode & OB_MODE_TEXTURE_PAINT)) || + check_object_draw_texture(scene, v3d, dt)) { - if ( (v3d->flag & V3D_SELECT_OUTLINE) && - ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && - !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) && - (draw_wire == OBDRAW_WIRE_OFF)) + if ((v3d->flag & V3D_SELECT_OUTLINE) && + ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && + (base->flag & SELECT) && + !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) && + (draw_wire == OBDRAW_WIRE_OFF)) { draw_mesh_object_outline(v3d, ob, dm); } @@ -3460,11 +3460,11 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D const float spec[4] = {0.47f, 0.47f, 0.47f, 0.47f}; /* draw outline */ - if ( (v3d->flag & V3D_SELECT_OUTLINE) && - ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && - (draw_wire == OBDRAW_WIRE_OFF) && - (ob->sculpt == NULL)) + if ((v3d->flag & V3D_SELECT_OUTLINE) && + ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && + (base->flag & SELECT) && + (draw_wire == OBDRAW_WIRE_OFF) && + (ob->sculpt == NULL)) { draw_mesh_object_outline(v3d, ob, dm); } @@ -3492,11 +3492,11 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D else { Paint *p; - if ( (v3d->flag & V3D_SELECT_OUTLINE) && - ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && - (draw_wire == OBDRAW_WIRE_OFF) && - (ob->sculpt == NULL)) + if ((v3d->flag & V3D_SELECT_OUTLINE) && + ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && + (base->flag & SELECT) && + (draw_wire == OBDRAW_WIRE_OFF) && + (ob->sculpt == NULL)) { draw_mesh_object_outline(v3d, ob, dm); } @@ -4347,7 +4347,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv timestep = psys_get_timestep(&sim); - if ( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) { + if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) { float mat[4][4]; mult_m4_m4m4(mat, ob->obmat, psys->imat); glMultMatrixf(mat); @@ -4893,7 +4893,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv pdd->ma_col = NULL; } - if ( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) { + if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) { glLoadMatrixf(rv3d->viewmat); } } @@ -5253,7 +5253,7 @@ static void tekenhandlesN(Nurb *nu, short sel, short hide_handles) a = nu->pntsu; while (a--) { if (bezt->hide == 0) { - if ( (bezt->f2 & SELECT) == sel) { + if ((bezt->f2 & SELECT) == sel) { fp = bezt->vec[0]; glColor3ubv(handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]); @@ -5264,14 +5264,14 @@ static void tekenhandlesN(Nurb *nu, short sel, short hide_handles) glVertex3fv(fp + 3); glVertex3fv(fp + 6); } - else if ( (bezt->f1 & SELECT) == sel) { + else if ((bezt->f1 & SELECT) == sel) { fp = bezt->vec[0]; glColor3ubv(handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]); glVertex3fv(fp); glVertex3fv(fp + 3); } - else if ( (bezt->f3 & SELECT) == sel) { + else if ((bezt->f3 & SELECT) == sel) { fp = bezt->vec[1]; glColor3ubv(handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]); @@ -5506,7 +5506,7 @@ static void draw_editnurb(Object *ob, Nurb *nurb, int sel) for (a = nu->pntsu - 1; a > 0; a--, bp++) { if (bp->hide == 0 && bp1->hide == 0) { if (sel) { - if ( (bp->f1 & SELECT) && (bp1->f1 & SELECT) ) { + if ((bp->f1 & SELECT) && (bp1->f1 & SELECT)) { UI_ThemeColor(TH_NURB_SEL_ULINE); glBegin(GL_LINE_STRIP); @@ -5541,7 +5541,7 @@ static void draw_editnurb(Object *ob, Nurb *nurb, int sel) for (a = nu->pntsv - 1; a > 0; a--, bp += ofs) { if (bp->hide == 0 && bp1->hide == 0) { if (sel) { - if ( (bp->f1 & SELECT) && (bp1->f1 & SELECT) ) { + if ((bp->f1 & SELECT) && (bp1->f1 & SELECT)) { UI_ThemeColor(TH_NURB_SEL_VLINE); glBegin(GL_LINE_STRIP); @@ -6930,9 +6930,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } /* draw edit particles last so that they can draw over child particles */ - if ( (warning_recursive == 0) && - (dflag & DRAW_PICKING) == 0 && - (!scene->obedit)) + if ((warning_recursive == 0) && + (dflag & DRAW_PICKING) == 0 && + (!scene->obedit)) { if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) { diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 17f1081f5c4..7accdb0c0e4 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -2733,12 +2733,12 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } /* convert border to 3d coordinates */ - if ( (!gluUnProject(cent[0], cent[1], depth_close, - mats.modelview, mats.projection, (GLint *)mats.viewport, - &p[0], &p[1], &p[2])) || - (!gluUnProject((double)rect.xmin, (double)rect.ymin, depth_close, - mats.modelview, mats.projection, (GLint *)mats.viewport, - &p_corner[0], &p_corner[1], &p_corner[2]))) + if ((!gluUnProject(cent[0], cent[1], depth_close, + mats.modelview, mats.projection, (GLint *)mats.viewport, + &p[0], &p[1], &p[2])) || + (!gluUnProject((double)rect.xmin, (double)rect.ymin, depth_close, + mats.modelview, mats.projection, (GLint *)mats.viewport, + &p_corner[0], &p_corner[1], &p_corner[2]))) { return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 465279ee6ed..fd43333acfe 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -370,7 +370,7 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event) case B_SEL_EDGE: if (em) { if (shift == 0 || em->selectmode == 0) { - if ( (em->selectmode ^ SCE_SELECT_EDGE) == SCE_SELECT_VERTEX) { + if ((em->selectmode ^ SCE_SELECT_EDGE) == SCE_SELECT_VERTEX) { if (ctrl) EDBM_selectmode_convert(em, SCE_SELECT_VERTEX, SCE_SELECT_EDGE); } em->selectmode = SCE_SELECT_EDGE; @@ -384,7 +384,9 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event) case B_SEL_FACE: if (em) { if (shift == 0 || em->selectmode == 0) { - if ( ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)) { + if (((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || + ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)) + { if (ctrl) EDBM_selectmode_convert(em, (ts->selectmode ^ SCE_SELECT_FACE), SCE_SELECT_FACE); } em->selectmode = SCE_SELECT_FACE; diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index fa431e89d80..5712144caf1 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1527,10 +1527,10 @@ int edge_inside_circle(int centx, int centy, int rad, int x1, int y1, int x2, in int radsq = rad * rad; /* check points in circle itself */ - if ( (x1 - centx) * (x1 - centx) + (y1 - centy) * (y1 - centy) <= radsq) { + if ((x1 - centx) * (x1 - centx) + (y1 - centy) * (y1 - centy) <= radsq) { return TRUE; } - else if ( (x2 - centx) * (x2 - centx) + (y2 - centy) * (y2 - centy) <= radsq) { + else if ((x2 - centx) * (x2 - centx) + (y2 - centy) * (y2 - centy) <= radsq) { return TRUE; } else { @@ -2467,7 +2467,7 @@ static void armature_circle_select(ViewContext *vc, int select, const int mval[2 /* only if the endpoints didn't get selected, deal with the middle of the bone too */ /* XXX should we just do this always? */ - if ( (didpoint == 0) && edge_inside_circle(mval[0], mval[1], rad, sco1[0], sco1[1], sco2[0], sco2[1]) ) { + if ((didpoint == 0) && edge_inside_circle(mval[0], mval[1], rad, sco1[0], sco1[1], sco2[0], sco2[1])) { if (select) ebone->flag |= BONE_TIPSEL | BONE_ROOTSEL | BONE_SELECTED; else diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 1d40ae280b7..c25bb80bfde 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -1653,7 +1653,7 @@ static void game_set_commmandline_options(GameData *gm) SYS_SystemHandle syshandle; int test; - if ( (syshandle = SYS_GetSystem()) ) { + if ((syshandle = SYS_GetSystem())) { /* User defined settings */ test = (U.gameflags & USER_DISABLE_MIPMAP); GPU_set_mipmap(!test); From 832841d50fefa4868f3eaed0959029b18347d72f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 10 Sep 2012 10:58:59 +0000 Subject: [PATCH 125/160] Merging r50484 through r50501 from trunk into soc-2011-tomato --- CMakeLists.txt | 75 +++++ build_files/cmake/macros.cmake | 3 + intern/cycles/cmake/external_libs.cmake | 26 -- intern/cycles/kernel/osl/CMakeLists.txt | 4 - .../bl_operators/screen_play_rendered_anim.py | 7 +- source/blender/blenkernel/BKE_blender.h | 2 + source/blender/blenkernel/BKE_tessmesh.h | 6 +- source/blender/blenkernel/intern/anim.c | 4 +- source/blender/blenkernel/intern/blender.c | 3 +- source/blender/blenkernel/intern/constraint.c | 3 +- .../blenkernel/intern/editderivedmesh.c | 6 + .../blender/editors/gpencil/gpencil_paint.c | 1 - source/blender/editors/gpencil/gpencil_undo.c | 9 +- source/blender/editors/include/UI_interface.h | 109 +++--- source/blender/editors/interface/interface.c | 68 ++-- .../editors/interface/interface_handlers.c | 310 +++++++++++------- .../editors/interface/interface_intern.h | 20 +- .../editors/interface/interface_regions.c | 17 +- source/blender/editors/mesh/editmesh_add.c | 36 +- source/blender/editors/mesh/editmesh_select.c | 3 +- source/blender/editors/mesh/editmesh_slide.c | 4 +- source/blender/editors/mesh/editmesh_utils.c | 3 +- .../editors/sculpt_paint/paint_image.c | 4 +- .../blender/editors/sculpt_paint/paint_undo.c | 8 +- .../editors/space_view3d/view3d_snap.c | 11 +- source/blender/editors/transform/transform.c | 3 +- .../transform/transform_orientations.c | 3 +- source/blender/editors/util/editmode_undo.c | 8 +- source/blender/editors/util/undo.c | 6 +- source/blender/gpu/GPU_material.h | 2 + source/blender/gpu/intern/gpu_material.c | 15 +- source/blender/imbuf/intern/rectop.c | 32 +- source/blender/makesdna/DNA_mesh_types.h | 3 +- .../nodes/node_shader_tex_environment.c | 3 + .../shader/nodes/node_shader_tex_image.c | 3 + source/creator/CMakeLists.txt | 1 - 36 files changed, 490 insertions(+), 331 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b6bb3f44bd..7a822143939 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -691,6 +691,31 @@ if(UNIX AND NOT APPLE) endif() endif() + if(WITH_CYCLES_OSL) + set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation") + + message(STATUS "CYCLES_OSL = ${CYCLES_OSL}") + + find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib) + find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib) + find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib) + # WARNING! depends on correct order of OSL libs linking + list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} ${OSL_LIB_EXEC} ${OSL_LIB_QUERY}) + find_path(OSL_INCLUDES OSL/oslclosure.h PATHS ${CYCLES_OSL}/include) + find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin) + + if(OSL_INCLUDES AND OSL_LIBRARIES AND OSL_COMPILER) + set(OSL_FOUND TRUE) + message(STATUS "OSL includes = ${OSL_INCLUDES}") + message(STATUS "OSL library = ${OSL_LIBRARIES}") + message(STATUS "OSL compiler = ${OSL_COMPILER}") + else() + message(STATUS "OSL not found") + endif() + + include_directories(${OSL_INCLUDES}) + endif() + # OpenSuse needs lutil, ArchLinux not, for now keep, can avoid by using --as-needed set(PLATFORM_LINKLIBS "-lutil -lc -lm -lpthread -lstdc++") @@ -835,6 +860,31 @@ elseif(WIN32) add_definitions(-D__SSE__ -D__MMX__) endif() + if(WITH_CYCLES_OSL) + set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation") + + message(STATUS "CYCLES_OSL = ${CYCLES_OSL}") + + find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib) + find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib) + find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib) + # WARNING! depends on correct order of OSL libs linking + list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} ${OSL_LIB_EXEC} ${OSL_LIB_QUERY}) + find_path(OSL_INCLUDES OSL/oslclosure.h PATHS ${CYCLES_OSL}/include) + find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin) + + if(OSL_INCLUDES AND OSL_LIBRARIES AND OSL_COMPILER) + set(OSL_FOUND TRUE) + message(STATUS "OSL includes = ${OSL_INCLUDES}") + message(STATUS "OSL library = ${OSL_LIBRARIES}") + message(STATUS "OSL compiler = ${OSL_COMPILER}") + else() + message(STATUS "OSL not found") + endif() + + include_directories(${OSL_INCLUDES}) + endif() + if(MSVC) set(PLATFORM_LINKLIBS ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 advapi32 shfolder shell32 ole32 oleaut32 uuid) @@ -1475,6 +1525,31 @@ elseif(APPLE) set(OPENCOLORIO_DEFINITIONS "-DOCIO_STATIC_BUILD") endif() + if(WITH_CYCLES_OSL) + set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation") + + message(STATUS "CYCLES_OSL = ${CYCLES_OSL}") + + find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib) + find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib) + find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib) + # WARNING! depends on correct order of OSL libs linking + list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} ${OSL_LIB_EXEC} ${OSL_LIB_QUERY}) + find_path(OSL_INCLUDES OSL/oslclosure.h PATHS ${CYCLES_OSL}/include) + find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin) + + if(OSL_INCLUDES AND OSL_LIBRARIES AND OSL_COMPILER) + set(OSL_FOUND TRUE) + message(STATUS "OSL includes = ${OSL_INCLUDES}") + message(STATUS "OSL library = ${OSL_LIBRARIES}") + message(STATUS "OSL compiler = ${OSL_COMPILER}") + else() + message(STATUS "OSL not found") + endif() + + include_directories(${OSL_INCLUDES}) + endif() + set(EXETYPE MACOSX_BUNDLE) set(CMAKE_C_FLAGS_DEBUG "-fno-strict-aliasing -g") diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index f14e9204732..057a1105b73 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -373,6 +373,9 @@ macro(setup_liblinks if(WITH_MOD_CLOTH_ELTOPO) target_link_libraries(${target} ${LAPACK_LIBRARIES}) endif() + if(WITH_CYCLES_OSL) + target_link_libraries(${target} ${OSL_LIBRARIES}) + endif() if(WIN32 AND NOT UNIX) target_link_libraries(${target} ${PTHREADS_LIBRARIES}) endif() diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake index 4f547a5b644..332d3d74715 100644 --- a/intern/cycles/cmake/external_libs.cmake +++ b/intern/cycles/cmake/external_libs.cmake @@ -17,32 +17,6 @@ else() set(CYCLES_GLEW_LIBRARY extern_glew) endif() -########################################################################### -# OpenShadingLanguage - -if(WITH_CYCLES_OSL) - - set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation") - - message(STATUS "CYCLES_OSL = ${CYCLES_OSL}") - - find_library(OSL_LIBRARIES NAMES oslexec oslcomp oslquery PATHS ${CYCLES_OSL}/lib ${CYCLES_OSL}/dist) - find_path(OSL_INCLUDES OSL/oslclosure.h PATHS ${CYCLES_OSL}/include ${CYCLES_OSL}/dist) - find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin ${CYCLES_OSL}/dist) - - if(OSL_INCLUDES AND OSL_LIBRARIES AND OSL_COMPILER) - set(OSL_FOUND TRUE) - message(STATUS "OSL includes = ${OSL_INCLUDES}") - message(STATUS "OSL library = ${OSL_LIBRARIES}") - message(STATUS "OSL compiler = ${OSL_COMPILER}") - else() - message(STATUS "OSL not found") - endif() - - include_directories(${OSL_INCLUDES} ${OSL_INCLUDES}/OSL ${OSL_INCLUDES}/../../../src/liboslexec) - -endif() - ########################################################################### # Partio diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt index ea675456e6d..d4ea8b12f5a 100644 --- a/intern/cycles/kernel/osl/CMakeLists.txt +++ b/intern/cycles/kernel/osl/CMakeLists.txt @@ -43,7 +43,3 @@ include_directories(${INC}) add_library(cycles_kernel_osl ${SRC} ${HEADER_SRC}) add_subdirectory(nodes) - -if(WITH_CYCLES_OSL) - target_link_libraries(cycles_kernel_osl ${OSL_LIBRARIES}) -endif() diff --git a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py index b4733ac9d87..f00b92beeed 100644 --- a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py +++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py @@ -104,11 +104,14 @@ class PlayRenderedAnim(Operator): file = ("".join((c if file_b[i] == c else "#") for i, c in enumerate(file_a))) + del file_a, file_b, frame_tmp + file = bpy.path.abspath(file) # expand '//' else: # works for movies and images file = rd.frame_path(frame=scene.frame_start) - - file = bpy.path.abspath(file) # expand '//' + file = bpy.path.abspath(file) # expand '//' + if not os.path.exists(file): + self.report({'WARNING'}, "File %r not found" % file) cmd = [player_path] # extra options, fps controls etc. diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 0e7bdbbb4dd..1e67027ae8c 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -83,6 +83,8 @@ void BKE_userdef_free(void); void set_blender_test_break_cb(void (*func)(void) ); int blender_test_break(void); +#define BKE_UNDO_STR_MAX 64 + /* global undo */ extern void BKE_write_undo(struct bContext *C, const char *name); extern void BKE_undo_step(struct bContext *C, int step); diff --git a/source/blender/blenkernel/BKE_tessmesh.h b/source/blender/blenkernel/BKE_tessmesh.h index 3a806651d61..dea5e726671 100644 --- a/source/blender/blenkernel/BKE_tessmesh.h +++ b/source/blender/blenkernel/BKE_tessmesh.h @@ -72,10 +72,12 @@ typedef struct BMEditMesh { short selectmode; short mat_nr; - /*Mesh structure this editmesh came from, if it came from one*/ - struct Mesh *me; + /* Object this editmesh came from (if it came from one) */ struct Object *ob; + /* Unused for now, we could bring it back and assign in the same way 'ob' is */ + // struct Mesh *me; + /*temp variables for x-mirror editing*/ int mirror_cdlayer; /* -1 is invalid */ int mirr_free_arrays; diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index f9954ff1dd0..4f68ab82329 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -924,7 +924,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl /* simple preventing of too deep nested groups */ if (level > MAX_DUPLI_RECUR) return; - em = me->edit_btmesh; + em = BMEdit_FromObject(par); if (em) { dm = editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); @@ -1050,7 +1050,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa if (level > MAX_DUPLI_RECUR) return; copy_m4_m4(pmat, par->obmat); - em = me->edit_btmesh; + em = BMEdit_FromObject(par); if (em) { dm = editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 2f66dbde97c..9145c4af850 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -469,11 +469,10 @@ int blender_test_break(void) #define UNDO_DISK 0 -#define MAXUNDONAME 64 typedef struct UndoElem { struct UndoElem *next, *prev; char str[FILE_MAX]; - char name[MAXUNDONAME]; + char name[BKE_UNDO_STR_MAX]; MemFile memfile; uintptr_t undosize; } UndoElem; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 8d7f4e4117a..6b9e0921c3b 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -416,8 +416,7 @@ void constraint_mat_convertspace(Object *ob, bPoseChannel *pchan, float mat[][4] static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[][4]) { DerivedMesh *dm = NULL; - Mesh *me = ob->data; - BMEditMesh *em = me->edit_btmesh; + BMEditMesh *em = BMEdit_FromObject(ob); float vec[3] = {0.0f, 0.0f, 0.0f}; float normal[3] = {0.0f, 0.0f, 0.0f}, plane[3]; float imat[3][3], tmat[3][3]; diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index c6ba6a0d841..befec1907da 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -1747,5 +1747,11 @@ DerivedMesh *getEditDerivedBMesh(BMEditMesh *em, BMEditMesh *BMEdit_FromObject(Object *ob) { BLI_assert(ob->type == OB_MESH); + /* sanity check */ +#ifndef NDEBUG + if (((Mesh *)ob->data)->edit_btmesh) { + BLI_assert(((Mesh *)ob->data)->edit_btmesh->ob == ob); + } +#endif return ((Mesh *)ob->data)->edit_btmesh; } diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index dfd2783fad6..4e281b96fc3 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -27,7 +27,6 @@ * \ingroup edgpencil */ - #include #include #include diff --git a/source/blender/editors/gpencil/gpencil_undo.c b/source/blender/editors/gpencil/gpencil_undo.c index 61f7e1bb86f..fa9f5196866 100644 --- a/source/blender/editors/gpencil/gpencil_undo.c +++ b/source/blender/editors/gpencil/gpencil_undo.c @@ -25,6 +25,10 @@ * ***** END GPL LICENSE BLOCK ***** */ +/** \file blender/editors/gpencil/gpencil_undo.c + * \ingroup edgpencil + */ + #include #include @@ -34,6 +38,7 @@ #include "DNA_listBase.h" #include "DNA_windowmanager_types.h" +#include "BKE_blender.h" #include "BKE_context.h" #include "BKE_gpencil.h" @@ -46,12 +51,10 @@ #include "gpencil_intern.h" -#define MAXUNDONAME 64 - typedef struct bGPundonode { struct bGPundonode *next, *prev; - char name[MAXUNDONAME]; + char name[BKE_UNDO_STR_MAX]; struct bGPdata *gpd; } bGPundonode; diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 12ab4166bc8..84ab68a9b6b 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -199,58 +199,60 @@ typedef struct uiLayout uiLayout; #define BUTPOIN (FLO | SHO | CHA) /* assigned to but->type, OR'd with the flags above when passing args */ -#define BUT (1 << 9) -#define ROW (2 << 9) -#define TOG (3 << 9) -#define SLI (4 << 9) -#define NUM (5 << 9) -#define TEX (6 << 9) -#define TOG3 (7 << 9) -#define TOGR (8 << 9) -#define TOGN (9 << 9) -#define LABEL (10 << 9) -#define MENU (11 << 9) -#define ICONROW (12 << 9) -#define ICONTOG (13 << 9) -#define NUMSLI (14 << 9) -#define COL (15 << 9) -#define IDPOIN (16 << 9) -#define HSVSLI (17 << 9) -#define SCROLL (18 << 9) -#define BLOCK (19 << 9) -#define BUTM (20 << 9) -#define SEPR (21 << 9) -#define LINK (22 << 9) -#define INLINK (23 << 9) -#define KEYEVT (24 << 9) -#define ICONTEXTROW (25 << 9) -#define HSVCUBE (26 << 9) -#define PULLDOWN (27 << 9) -#define ROUNDBOX (28 << 9) -#define CHARTAB (29 << 9) -#define BUT_COLORBAND (30 << 9) -#define BUT_NORMAL (31 << 9) -#define BUT_CURVE (32 << 9) -#define BUT_TOGDUAL (33 << 9) -#define ICONTOGN (34 << 9) -#define FTPREVIEW (35 << 9) -#define NUMABS (36 << 9) -#define TOGBUT (37 << 9) -#define OPTION (38 << 9) -#define OPTIONN (39 << 9) -#define TRACKPREVIEW (40 << 9) -/* buttons with value >= SEARCH_MENU don't get undo pushes */ -#define SEARCH_MENU (41 << 9) -#define BUT_EXTRA (42 << 9) -#define HSVCIRCLE (43 << 9) -#define LISTBOX (44 << 9) -#define LISTROW (45 << 9) -#define HOTKEYEVT (46 << 9) -#define BUT_IMAGE (47 << 9) -#define HISTOGRAM (48 << 9) -#define WAVEFORM (49 << 9) -#define VECTORSCOPE (50 << 9) -#define PROGRESSBAR (51 << 9) +typedef enum { + BUT = (1 << 9), + ROW = (2 << 9), + TOG = (3 << 9), + SLI = (4 << 9), + NUM = (5 << 9), + TEX = (6 << 9), + TOG3 = (7 << 9), + TOGR = (8 << 9), + TOGN = (9 << 9), + LABEL = (10 << 9), + MENU = (11 << 9), + ICONROW = (12 << 9), + ICONTOG = (13 << 9), + NUMSLI = (14 << 9), + COL = (15 << 9), + IDPOIN = (16 << 9), + HSVSLI = (17 << 9), + SCROLL = (18 << 9), + BLOCK = (19 << 9), + BUTM = (20 << 9), + SEPR = (21 << 9), + LINK = (22 << 9), + INLINK = (23 << 9), + KEYEVT = (24 << 9), + ICONTEXTROW = (25 << 9), + HSVCUBE = (26 << 9), + PULLDOWN = (27 << 9), + ROUNDBOX = (28 << 9), + CHARTAB = (29 << 9), + BUT_COLORBAND = (30 << 9), + BUT_NORMAL = (31 << 9), + BUT_CURVE = (32 << 9), + BUT_TOGDUAL = (33 << 9), + ICONTOGN = (34 << 9), + /* FTPREVIEW = (35 << 9), */ /* UNUSED */ + NUMABS = (36 << 9), + TOGBUT = (37 << 9), + OPTION = (38 << 9), + OPTIONN = (39 << 9), + TRACKPREVIEW = (40 << 9), + /* buttons with value >= SEARCH_MENU don't get undo pushes */ + SEARCH_MENU = (41 << 9), + BUT_EXTRA = (42 << 9), + HSVCIRCLE = (43 << 9), + LISTBOX = (44 << 9), + LISTROW = (45 << 9), + HOTKEYEVT = (46 << 9), + BUT_IMAGE = (47 << 9), + HISTOGRAM = (48 << 9), + WAVEFORM = (49 << 9), + VECTORSCOPE = (50 << 9), + PROGRESSBAR = (51 << 9) +} eButType; #define BUTTYPE (63 << 9) @@ -395,7 +397,8 @@ void uiBlockBeginAlign(uiBlock *block); void uiBlockEndAlign(uiBlock *block); /* block bounds/position calculation */ -enum { +typedef enum { + UI_BLOCK_BOUNDS_NONE = 0, UI_BLOCK_BOUNDS = 1, UI_BLOCK_BOUNDS_TEXT, UI_BLOCK_BOUNDS_POPUP_MOUSE, diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 515db9559ae..718ed40cad9 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -317,7 +317,7 @@ static void ui_centered_bounds_block(const bContext *C, uiBlock *block) ui_bounds_block(block); } -static void ui_popup_bounds_block(const bContext *C, uiBlock *block, int bounds_calc) +static void ui_popup_bounds_block(const bContext *C, uiBlock *block, eBlockBoundsCalc bounds_calc) { wmWindow *window = CTX_wm_window(C); int startx, starty, endx, endy, width, height, oldwidth, oldheight; @@ -388,21 +388,21 @@ void uiBoundsBlock(uiBlock *block, int addval) return; block->bounds = addval; - block->dobounds = UI_BLOCK_BOUNDS; + block->bounds_type = UI_BLOCK_BOUNDS; } /* used for pulldowns */ void uiTextBoundsBlock(uiBlock *block, int addval) { block->bounds = addval; - block->dobounds = UI_BLOCK_BOUNDS_TEXT; + block->bounds_type = UI_BLOCK_BOUNDS_TEXT; } /* used for block popups */ void uiPopupBoundsBlock(uiBlock *block, int addval, int mx, int my) { block->bounds = addval; - block->dobounds = UI_BLOCK_BOUNDS_POPUP_MOUSE; + block->bounds_type = UI_BLOCK_BOUNDS_POPUP_MOUSE; block->mx = mx; block->my = my; } @@ -411,7 +411,7 @@ void uiPopupBoundsBlock(uiBlock *block, int addval, int mx, int my) void uiMenuPopupBoundsBlock(uiBlock *block, int addval, int mx, int my) { block->bounds = addval; - block->dobounds = UI_BLOCK_BOUNDS_POPUP_MENU; + block->bounds_type = UI_BLOCK_BOUNDS_POPUP_MENU; block->mx = mx; block->my = my; } @@ -420,7 +420,7 @@ void uiMenuPopupBoundsBlock(uiBlock *block, int addval, int mx, int my) void uiCenteredBoundsBlock(uiBlock *block, int addval) { block->bounds = addval; - block->dobounds = UI_BLOCK_BOUNDS_POPUP_CENTER; + block->bounds_type = UI_BLOCK_BOUNDS_POPUP_CENTER; } void uiExplicitBoundsBlock(uiBlock *block, int minx, int miny, int maxx, int maxy) @@ -429,7 +429,7 @@ void uiExplicitBoundsBlock(uiBlock *block, int minx, int miny, int maxx, int max block->rect.ymin = miny; block->rect.xmax = maxx; block->rect.ymax = maxy; - block->dobounds = 0; + block->bounds_type = UI_BLOCK_BOUNDS_NONE; } /* ************** LINK LINE DRAWING ************* */ @@ -934,21 +934,45 @@ void uiEndBlock(const bContext *C, uiBlock *block) } /* handle pending stuff */ - if (block->layouts.first) uiBlockLayoutResolve(block, NULL, NULL); + if (block->layouts.first) { + uiBlockLayoutResolve(block, NULL, NULL); + } ui_block_do_align(block); if ((block->flag & UI_BLOCK_LOOP) && (block->flag & UI_BLOCK_NUMSELECT)) { ui_menu_block_set_keyaccels(block); /* could use a different flag to check */ } - if (block->flag & UI_BLOCK_LOOP) ui_menu_block_set_keymaps(C, block); + + if (block->flag & UI_BLOCK_LOOP) { + ui_menu_block_set_keymaps(C, block); + } /* after keymaps! */ - if (block->dobounds == UI_BLOCK_BOUNDS) ui_bounds_block(block); - else if (block->dobounds == UI_BLOCK_BOUNDS_TEXT) ui_text_bounds_block(block, 0.0f); - else if (block->dobounds == UI_BLOCK_BOUNDS_POPUP_CENTER) ui_centered_bounds_block(C, block); - else if (block->dobounds) ui_popup_bounds_block(C, block, block->dobounds); + switch (block->bounds_type) { + case UI_BLOCK_BOUNDS_NONE: + break; + case UI_BLOCK_BOUNDS: + ui_bounds_block(block); + break; + case UI_BLOCK_BOUNDS_TEXT: + ui_text_bounds_block(block, 0.0f); + break; + case UI_BLOCK_BOUNDS_POPUP_CENTER: + ui_centered_bounds_block(C, block); + break; - if (block->rect.xmin == 0.0f && block->rect.xmax == 0.0f) uiBoundsBlock(block, 0); - if (block->flag & UI_BUT_ALIGN) uiBlockEndAlign(block); + /* fallback */ + case UI_BLOCK_BOUNDS_POPUP_MOUSE: + case UI_BLOCK_BOUNDS_POPUP_MENU: + ui_popup_bounds_block(C, block, block->bounds_type); + break; + } + + if (block->rect.xmin == 0.0f && block->rect.xmax == 0.0f) { + uiBoundsBlock(block, 0); + } + if (block->flag & UI_BUT_ALIGN) { + uiBlockEndAlign(block); + } block->endblock = 1; } @@ -2215,6 +2239,10 @@ void ui_check_but(uiBut *but) but->iconadd = (int)value - (int)(but->hardmin); } break; + + /* quiet warnings for unhandled types */ + default: + break; } @@ -2536,11 +2564,13 @@ void ui_block_do_align(uiBlock *block) /* skip with same number */ for (; but && but->alignnr == nr; but = but->next) ; - if (!but) + if (!but) { break; + } } - else + else { but = but->next; + } } } @@ -2556,7 +2586,7 @@ void ui_block_do_align(uiBlock *block) * 1,2,3, and a maximum of 4, all greater values will be clamped to 4. */ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str, - int x, int y, short width, short height, + int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip) { uiBut *but; @@ -2648,7 +2678,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str, /* keep track of UI_interface.h */ if (ELEM7(but->type, BLOCK, BUT, LABEL, PULLDOWN, ROUNDBOX, LISTBOX, BUTM)) ; - else if (ELEM3(but->type, SCROLL, SEPR, FTPREVIEW)) ; + else if (ELEM(but->type, SCROLL, SEPR /* , FTPREVIEW */ )) ; else if (but->type >= SEARCH_MENU) ; else but->flag |= UI_BUT_UNDO; diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 787e79fe8b6..17486edd07f 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -54,6 +54,7 @@ #include "PIL_time.h" +#include "BKE_blender.h" #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_idprop.h" @@ -81,8 +82,6 @@ static void ui_add_smart_controller(bContext *C, uiBut *from, uiBut *to); static void ui_add_link(bContext *C, uiBut *from, uiBut *to); -static int ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *menu, int mx, int my); - /***************** structs and defines ****************/ #define BUTTON_TOOLTIP_DELAY 0.500 @@ -122,8 +121,10 @@ typedef struct uiHandleButtonData { /* overall state */ uiHandleButtonState state; - int cancel, escapecancel, retval; - int applied, appliedinteractive; + int retval; + /* booleans (could be made into flags) */ + char cancel, escapecancel; + char applied, appliedinteractive; wmTimer *flashtimer; /* edited value */ @@ -195,7 +196,7 @@ typedef struct uiAfterFunc { bContextStore *context; - char undostr[512]; + char undostr[BKE_UNDO_STR_MAX]; int autokey; } uiAfterFunc; @@ -463,7 +464,7 @@ static void ui_apply_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data) ui_apply_but_func(C, but); data->retval = but->retval; - data->applied = 1; + data->applied = TRUE; } static void ui_apply_but_BUTM(bContext *C, uiBut *but, uiHandleButtonData *data) @@ -472,7 +473,7 @@ static void ui_apply_but_BUTM(bContext *C, uiBut *but, uiHandleButtonData *data) ui_apply_but_func(C, but); data->retval = but->retval; - data->applied = 1; + data->applied = TRUE; } static void ui_apply_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data) @@ -483,7 +484,7 @@ static void ui_apply_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data ui_check_but(but); ui_apply_but_func(C, but); data->retval = but->retval; - data->applied = 1; + data->applied = TRUE; } static void ui_apply_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data) @@ -542,7 +543,7 @@ static void ui_apply_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data) ui_apply_but_func(C, but); data->retval = but->retval; - data->applied = 1; + data->applied = TRUE; } static void ui_apply_but_ROW(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data) @@ -559,7 +560,7 @@ static void ui_apply_but_ROW(bContext *C, uiBlock *block, uiBut *but, uiHandleBu ui_apply_but_func(C, but); data->retval = but->retval; - data->applied = 1; + data->applied = TRUE; } static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data) @@ -578,7 +579,7 @@ static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data) ui_apply_but_func(C, but); data->retval = but->retval; - data->applied = 1; + data->applied = TRUE; } static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data) @@ -588,7 +589,7 @@ static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data) data->value = ui_get_but_val(but); } else { - data->cancel = 1; + data->cancel = TRUE; return; } } @@ -599,7 +600,7 @@ static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data) ui_apply_but_func(C, but); data->retval = but->retval; - data->applied = 1; + data->applied = TRUE; } static void ui_apply_but_TOG3(bContext *C, uiBut *but, uiHandleButtonData *data) @@ -634,7 +635,7 @@ static void ui_apply_but_TOG3(bContext *C, uiBut *but, uiHandleButtonData *data) ui_check_but(but); ui_apply_but_func(C, but); data->retval = but->retval; - data->applied = 1; + data->applied = TRUE; } static void ui_apply_but_VEC(bContext *C, uiBut *but, uiHandleButtonData *data) @@ -644,21 +645,21 @@ static void ui_apply_but_VEC(bContext *C, uiBut *but, uiHandleButtonData *data) ui_apply_but_func(C, but); data->retval = but->retval; - data->applied = 1; + data->applied = TRUE; } static void ui_apply_but_COLORBAND(bContext *C, uiBut *but, uiHandleButtonData *data) { ui_apply_but_func(C, but); data->retval = but->retval; - data->applied = 1; + data->applied = TRUE; } static void ui_apply_but_CURVE(bContext *C, uiBut *but, uiHandleButtonData *data) { ui_apply_but_func(C, but); data->retval = but->retval; - data->applied = 1; + data->applied = TRUE; } static void ui_apply_but_IDPOIN(bContext *C, uiBut *but, uiHandleButtonData *data) @@ -667,7 +668,7 @@ static void ui_apply_but_IDPOIN(bContext *C, uiBut *but, uiHandleButtonData *dat ui_check_but(but); ui_apply_but_func(C, but); data->retval = but->retval; - data->applied = 1; + data->applied = TRUE; } #ifdef WITH_INTERNATIONAL @@ -675,7 +676,7 @@ static void ui_apply_but_CHARTAB(bContext *C, uiBut *but, uiHandleButtonData *da { ui_apply_but_func(C, but); data->retval = but->retval; - data->applied = 1; + data->applied = TRUE; } #endif @@ -712,7 +713,7 @@ static int ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data, wmDrag *drag; button_activate_state(C, but, BUTTON_STATE_EXIT); - data->cancel = 1; + data->cancel = TRUE; drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but)); if (but->imb) @@ -731,13 +732,10 @@ static void ui_delete_active_linkline(uiBlock *block) uiLink *link; uiLinkLine *line, *nline; int a, b; - - but = block->buttons.first; - while (but) { + + for (but = block->buttons.first; but; but = but->next) { if (but->type == LINK && but->link) { - line = but->link->lines.first; - while (line) { - + for (line = but->link->lines.first; line; line = nline) { nline = line->next; if (line->flag & UI_SELECT) { @@ -771,10 +769,8 @@ static void ui_delete_active_linkline(uiBlock *block) MEM_freeN(line); } - line = nline; } } - but = but->next; } } @@ -786,10 +782,10 @@ static uiLinkLine *ui_is_a_link(uiBut *from, uiBut *to) link = from->link; if (link) { - line = link->lines.first; - while (line) { - if (line->from == from && line->to == to) return line; - line = line->next; + for (line = link->lines.first; line; line = line->next) { + if (line->from == from && line->to == to) { + return line; + } } } return NULL; @@ -931,35 +927,35 @@ static void ui_apply_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data) ui_apply_but_func(C, but); data->retval = but->retval; } - data->applied = 1; + data->applied = TRUE; } static void ui_apply_but_IMAGE(bContext *C, uiBut *but, uiHandleButtonData *data) { ui_apply_but_func(C, but); data->retval = but->retval; - data->applied = 1; + data->applied = TRUE; } static void ui_apply_but_HISTOGRAM(bContext *C, uiBut *but, uiHandleButtonData *data) { ui_apply_but_func(C, but); data->retval = but->retval; - data->applied = 1; + data->applied = TRUE; } static void ui_apply_but_WAVEFORM(bContext *C, uiBut *but, uiHandleButtonData *data) { ui_apply_but_func(C, but); data->retval = but->retval; - data->applied = 1; + data->applied = TRUE; } static void ui_apply_but_TRACKPREVIEW(bContext *C, uiBut *but, uiHandleButtonData *data) { ui_apply_but_func(C, but); data->retval = but->retval; - data->applied = 1; + data->applied = TRUE; } @@ -990,10 +986,12 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut else { /* we avoid applying interactive edits a second time * at the end with the appliedinteractive flag */ - if (interactive) - data->appliedinteractive = 1; - else if (data->appliedinteractive) + if (interactive) { + data->appliedinteractive = TRUE; + } + else if (data->appliedinteractive) { return; + } } /* ensures we are writing actual values */ @@ -1219,7 +1217,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING); BLI_strncpy(buf, active_data->str, UI_MAX_DRAW_STR); WM_clipboard_text_set(active_data->str, 0); - active_data->cancel = 1; + active_data->cancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); } else { @@ -1322,7 +1320,10 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho while (i > 0) { if (BLI_str_cursor_step_prev_utf8(origstr, but->ofs, &i)) { - if (BLF_width(fstyle->uifont_id, origstr + i) > (startx - x) * 0.25f) break; // 0.25 == scale factor for less sensitivity + /* 0.25 == scale factor for less sensitivity */ + if (BLF_width(fstyle->uifont_id, origstr + i) > (startx - x) * 0.25f) { + break; + } } else { break; /* unlikely but possible */ @@ -1385,7 +1386,7 @@ static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data, else if (x < data->selstartx) data->selextend = EXTEND_LEFT; ui_textedit_set_cursor_pos(but, data, x); - + if (data->selextend == EXTEND_RIGHT) but->selend = but->pos; if (data->selextend == EXTEND_LEFT) but->selsta = but->pos; @@ -1439,7 +1440,8 @@ static int ui_textedit_type_ascii(uiBut *but, uiHandleButtonData *data, char asc return ui_textedit_type_buf(but, data, buf, 1); } -static void ui_textedit_move(uiBut *but, uiHandleButtonData *data, strCursorJumpDirection direction, int select, strCursorJumpType jump) +static void ui_textedit_move(uiBut *but, uiHandleButtonData *data, strCursorJumpDirection direction, + int select, strCursorJumpType jump) { const char *str = data->str; const int len = strlen(str); @@ -1788,8 +1790,8 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle break; case RIGHTMOUSE: case ESCKEY: - data->cancel = 1; - data->escapecancel = 1; + data->cancel = TRUE; + data->escapecancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); retval = WM_UI_HANDLER_BREAK; break; @@ -1815,7 +1817,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle else if (inbox == 0) { /* if searchbox, click outside will cancel */ if (data->searchbox) - data->cancel = data->escapecancel = 1; + data->cancel = data->escapecancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); retval = WM_UI_HANDLER_BREAK; } @@ -1845,11 +1847,13 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle } break; case RIGHTARROWKEY: - ui_textedit_move(but, data, STRCUR_DIR_NEXT, event->shift, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE); + ui_textedit_move(but, data, STRCUR_DIR_NEXT, + event->shift, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE); retval = WM_UI_HANDLER_BREAK; break; case LEFTARROWKEY: - ui_textedit_move(but, data, STRCUR_DIR_PREV, event->shift, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE); + ui_textedit_move(but, data, STRCUR_DIR_PREV, + event->shift, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE); retval = WM_UI_HANDLER_BREAK; break; case DOWNARROWKEY: @@ -1859,7 +1863,8 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle } /* pass on purposedly */ case ENDKEY: - ui_textedit_move(but, data, STRCUR_DIR_NEXT, event->shift, STRCUR_JUMP_ALL); + ui_textedit_move(but, data, STRCUR_DIR_NEXT, + event->shift, STRCUR_JUMP_ALL); retval = WM_UI_HANDLER_BREAK; break; case UPARROWKEY: @@ -1869,7 +1874,8 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle } /* pass on purposedly */ case HOMEKEY: - ui_textedit_move(but, data, STRCUR_DIR_PREV, event->shift, STRCUR_JUMP_ALL); + ui_textedit_move(but, data, STRCUR_DIR_PREV, + event->shift, STRCUR_JUMP_ALL); retval = WM_UI_HANDLER_BREAK; break; case PADENTER: @@ -1878,12 +1884,14 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle retval = WM_UI_HANDLER_BREAK; break; case DELKEY: - changed = ui_textedit_delete(but, data, 1, event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE); + changed = ui_textedit_delete(but, data, 1, + event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE); retval = WM_UI_HANDLER_BREAK; break; case BACKSPACEKEY: - changed = ui_textedit_delete(but, data, 0, event->shift ? STRCUR_JUMP_ALL : (event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE)); + changed = ui_textedit_delete(but, data, 0, + event->shift ? STRCUR_JUMP_ALL : (event->ctrl ? STRCUR_JUMP_DELIM : STRCUR_JUMP_NONE)); retval = WM_UI_HANDLER_BREAK; break; @@ -2092,6 +2100,10 @@ static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data handlefunc = ui_block_func_COL; arg = but; break; + + /* quiet warnings for unhandled types */ + default: + break; } if (func || handlefunc) { @@ -2145,7 +2157,7 @@ static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, wmEv else if (data->state == BUTTON_STATE_WAIT_RELEASE) { if (event->type == LEFTMOUSE && event->val != KM_PRESS) { if (!(but->flag & UI_SELECT)) - data->cancel = 1; + data->cancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); return WM_UI_HANDLER_BREAK; } @@ -2176,7 +2188,7 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data if (but->flag & UI_BUT_IMMEDIATE) ui_set_but_val(but, 0); else - data->cancel = 1; + data->cancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); return WM_UI_HANDLER_BREAK; } @@ -2198,14 +2210,14 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data if (WM_key_event_string(event->type)[0]) ui_set_but_val(but, event->type); else - data->cancel = 1; + data->cancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); return WM_UI_HANDLER_BREAK; } else if (event->type == ESCKEY) { - data->cancel = 1; - data->escapecancel = 1; + data->cancel = TRUE; + data->escapecancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); } @@ -2231,7 +2243,7 @@ static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, w if (WM_key_event_string(event->type)[0]) ui_set_but_val(but, event->type); else - data->cancel = 1; + data->cancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); } @@ -2579,8 +2591,8 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton } else if (data->state == BUTTON_STATE_NUM_EDITING) { if (event->type == ESCKEY) { - data->cancel = 1; - data->escapecancel = 1; + data->cancel = TRUE; + data->escapecancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); } else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { @@ -2630,7 +2642,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton if (temp >= softmin && temp <= softmax) data->value = (double)temp; else - data->cancel = 1; + data->cancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); } @@ -2641,7 +2653,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton if (temp >= softmin && temp <= softmax) data->value = (double)temp; else - data->cancel = 1; + data->cancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); } @@ -2801,8 +2813,8 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton } else if (data->state == BUTTON_STATE_NUM_EDITING) { if (event->type == ESCKEY) { - data->cancel = 1; - data->escapecancel = 1; + data->cancel = TRUE; + data->escapecancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); } else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { @@ -2860,7 +2872,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton if (temp >= softmin && temp <= softmax) data->value = temp; else - data->cancel = 1; + data->cancel = TRUE; } else { if (f < tempf) tempf -= 0.01f; @@ -2869,7 +2881,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton if (tempf >= softmin && tempf <= softmax) data->value = tempf; else - data->cancel = 1; + data->cancel = TRUE; } button_activate_state(C, but, BUTTON_STATE_EXIT); @@ -2918,8 +2930,8 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut } else if (data->state == BUTTON_STATE_NUM_EDITING) { if (event->type == ESCKEY) { - data->cancel = 1; - data->escapecancel = 1; + data->cancel = TRUE; + data->escapecancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); } else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { @@ -3021,7 +3033,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wm /* outside icon quit, not needed if drag activated */ if (0 == ui_but_mouse_inside_icon(but, data->region, event)) { button_activate_state(C, but, BUTTON_STATE_EXIT); - data->cancel = 1; + data->cancel = TRUE; return WM_UI_HANDLER_BREAK; } @@ -3332,8 +3344,8 @@ static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleBu } else if (data->state == BUTTON_STATE_NUM_EDITING) { if (event->type == ESCKEY) { - data->cancel = 1; - data->escapecancel = 1; + data->cancel = TRUE; + data->escapecancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); } else if (event->type == MOUSEMOVE) { @@ -3512,8 +3524,8 @@ static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandle } else if (data->state == BUTTON_STATE_NUM_EDITING) { if (event->type == ESCKEY) { - data->cancel = 1; - data->escapecancel = 1; + data->cancel = TRUE; + data->escapecancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); } /* XXX hardcoded keymap check.... */ @@ -3805,7 +3817,7 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt } else { /* move the view */ - data->cancel = 1; + data->cancel = TRUE; } data->dragsel = sel; @@ -3927,8 +3939,8 @@ static int ui_do_but_HISTOGRAM(bContext *C, uiBlock *block, uiBut *but, uiHandle } else if (data->state == BUTTON_STATE_NUM_EDITING) { if (event->type == ESCKEY) { - data->cancel = 1; - data->escapecancel = 1; + data->cancel = TRUE; + data->escapecancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); } else if (event->type == MOUSEMOVE) { @@ -4010,8 +4022,8 @@ static int ui_do_but_WAVEFORM(bContext *C, uiBlock *block, uiBut *but, uiHandleB } else if (data->state == BUTTON_STATE_NUM_EDITING) { if (event->type == ESCKEY) { - data->cancel = 1; - data->escapecancel = 1; + data->cancel = TRUE; + data->escapecancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); } else if (event->type == MOUSEMOVE) { @@ -4077,8 +4089,8 @@ static int ui_do_but_VECTORSCOPE(bContext *C, uiBlock *block, uiBut *but, uiHand } else if (data->state == BUTTON_STATE_NUM_EDITING) { if (event->type == ESCKEY) { - data->cancel = 1; - data->escapecancel = 1; + data->cancel = TRUE; + data->escapecancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); } else if (event->type == MOUSEMOVE) { @@ -4220,7 +4232,7 @@ static int ui_do_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data, wmE if (event->type == LEFTMOUSE && event->val != KM_PRESS) { if (!(but->flag & UI_SELECT)) - data->cancel = 1; + data->cancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); return WM_UI_HANDLER_BREAK; } @@ -4294,8 +4306,8 @@ static int ui_do_but_TRACKPREVIEW(bContext *C, uiBlock *block, uiBut *but, uiHan } else if (data->state == BUTTON_STATE_NUM_EDITING) { if (event->type == ESCKEY) { - data->cancel = 1; - data->escapecancel = 1; + data->cancel = TRUE; + data->escapecancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); } else if (event->type == MOUSEMOVE) { @@ -4747,7 +4759,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) ui_but_drop(C, event, but, data); } /* handle keyframing */ - else if (event->type == IKEY && !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey) && event->val == KM_PRESS) { + else if ((event->type == IKEY) && + !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey) && + (event->val == KM_PRESS)) + { if (event->alt) { if (event->shift) { ui_but_anim_clear_keyframe(C); @@ -4765,7 +4780,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) return WM_UI_HANDLER_BREAK; } /* handle drivers */ - else if (event->type == DKEY && !ELEM3(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) && event->val == KM_PRESS) { + else if ((event->type == DKEY) && + !ELEM3(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) && + (event->val == KM_PRESS)) + { if (event->alt) ui_but_anim_remove_driver(C); else @@ -4776,7 +4794,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) return WM_UI_HANDLER_BREAK; } /* handle keyingsets */ - else if (event->type == KKEY && !ELEM3(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) && event->val == KM_PRESS) { + else if ((event->type == KKEY) && + !ELEM3(KM_MOD_FIRST, event->ctrl, event->oskey, event->shift) && + (event->val == KM_PRESS)) + { if (event->alt) ui_but_anim_remove_keyingset(C); else @@ -4912,6 +4933,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) case CHARTAB: retval = ui_do_but_CHARTAB(C, block, but, data, event); break; +#else + /* do nothing */ + case CHARTAB: + break; #endif case LINK: @@ -4921,6 +4946,11 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) case TRACKPREVIEW: retval = ui_do_but_TRACKPREVIEW(C, block, but, data, event); break; + + /* quiet warnings for unhandled types */ + case SEPR: + case BUT_EXTRA: + break; } return retval; @@ -5197,17 +5227,33 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s /* automatic open pulldown block timer */ if (ELEM3(but->type, BLOCK, PULLDOWN, ICONTEXTROW)) { - if (data->used_mouse && !data->autoopentimer) { + if ((data->used_mouse == TRUE) && + (data->autoopentimer == FALSE) && + /* don't popup the first time, + * see description on this member for info */ + (but->block->auto_is_first_event == FALSE)) + { int time; - if (but->block->auto_open == TRUE) time = 1; // test for toolbox - else if ((but->block->flag & UI_BLOCK_LOOP && but->type != BLOCK) || but->block->auto_open == TRUE) time = 5 * U.menuthreshold2; - else if (U.uiflag & USER_MENUOPENAUTO) time = 5 * U.menuthreshold1; - else time = -1; + if (but->block->auto_open == TRUE) { /* test for toolbox */ + time = 1; + } + else if ((but->block->flag & UI_BLOCK_LOOP && but->type != BLOCK) || but->block->auto_open == TRUE) { + time = 5 * U.menuthreshold2; + } + else if (U.uiflag & USER_MENUOPENAUTO) { + time = 5 * U.menuthreshold1; + } + else { + time = -1; /* do nothing */ + } - if (time >= 0) + if (time >= 0) { data->autoopentimer = WM_event_add_timer(data->wm, data->window, TIMER, 0.02 * (double)time); + } } + + but->block->auto_is_first_event = FALSE; } } else { @@ -5299,7 +5345,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA /* XXX curve is temp */ } else { - data->interactive = 1; + data->interactive = TRUE; } data->state = BUTTON_STATE_INIT; @@ -5428,7 +5474,7 @@ void ui_button_active_free(const bContext *C, uiBut *but) * case cleanly anyway in case it happens */ if (but->active) { data = but->active; - data->cancel = 1; + data->cancel = TRUE; button_activate_exit((bContext *)C, data, but, 0, 1); } } @@ -5658,7 +5704,7 @@ static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiBu oldbut = ui_but_find_activated(ar); if (oldbut) { data = oldbut->active; - data->cancel = 1; + data->cancel = TRUE; button_activate_exit(C, data, oldbut, 0, 0); } @@ -5686,18 +5732,18 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) switch (event->type) { case WINDEACTIVATE: case EVT_BUT_CANCEL: - data->cancel = 1; + data->cancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); retval = WM_UI_HANDLER_CONTINUE; break; case MOUSEMOVE: /* verify if we are still over the button, if not exit */ if (!ui_mouse_inside_button(ar, but, event->x, event->y)) { - data->cancel = 1; + data->cancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); } else if (ui_but_find_mouse_over(ar, event->x, event->y) != but) { - data->cancel = 1; + data->cancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); } else if (event->x != event->prevx || event->y != event->prevy) { @@ -5746,7 +5792,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) else if (data->state == BUTTON_STATE_WAIT_RELEASE) { switch (event->type) { case WINDEACTIVATE: - data->cancel = 1; + data->cancel = TRUE; button_activate_state(C, but, BUTTON_STATE_EXIT); break; @@ -5762,18 +5808,18 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) if (ui_mouse_inside_button(ar, but, event->x, event->y)) { if (!(but->flag & UI_SELECT)) { but->flag |= (UI_SELECT | UI_ACTIVE); - data->cancel = 0; + data->cancel = FALSE; ED_region_tag_redraw(data->region); } } else { if (but->flag & UI_SELECT) { but->flag &= ~(UI_SELECT | UI_ACTIVE); - data->cancel = 1; + data->cancel = TRUE; ED_region_tag_redraw(data->region); } } - } + } break; default: /* otherwise catch mouse release event */ @@ -5828,6 +5874,9 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) } } + if (but->type != COL) { /* exception */ + data->cancel = TRUE; + } button_activate_state(C, but, BUTTON_STATE_EXIT); break; } @@ -5942,8 +5991,12 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut * } if (menu->menuretval & UI_RETURN_UPDATE) { - if (data->interactive) ui_apply_button(C, but->block, but, data, 1); - else ui_check_but(but); + if (data->interactive) { + ui_apply_button(C, but->block, but, data, TRUE); + } + else { + ui_check_but(but); + } menu->menuretval = 0; } @@ -5951,7 +6004,7 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut * /* now change button state or exit, which will close the submenu */ if ((menu->menuretval & UI_RETURN_OK) || (menu->menuretval & UI_RETURN_CANCEL)) { if (menu->menuretval != UI_RETURN_OK) - data->cancel = 1; + data->cancel = TRUE; button_activate_exit(C, data, but, 1, 0); } @@ -5966,7 +6019,7 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut * button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT); } else { - data->cancel = 1; + data->cancel = TRUE; button_activate_exit(C, data, but, 1, 0); } } @@ -5987,7 +6040,7 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut * static void ui_mouse_motion_towards_init(uiPopupBlockHandle *menu, int mx, int my, int force) { if (!menu->dotowards || force) { - menu->dotowards = 1; + menu->dotowards = TRUE; menu->towardsx = mx; menu->towardsy = my; @@ -6003,7 +6056,9 @@ static int ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *men float p1[2], p2[2], p3[2], p4[2], oldp[2], newp[2]; int closer; - if (!menu->dotowards) return 0; + if (!menu->dotowards) { + return 0; + } /* verify that we are moving towards one of the edges of the * menu block, in other words, in the triangle formed by the @@ -6035,11 +6090,11 @@ static int ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *men isect_point_tri_v2(newp, oldp, p4, p1)); if (!closer) - menu->dotowards = 0; + menu->dotowards = FALSE; /* 1 second timer */ if (PIL_check_seconds_timer() - menu->towardstime > BUTTON_MOUSE_TOWARDS_THRESH) - menu->dotowards = 0; + menu->dotowards = FALSE; return menu->dotowards; } @@ -6195,7 +6250,9 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle case WHEELUPMOUSE: case WHEELDOWNMOUSE: /* arrowkeys: only handle for block_loop blocks */ - if (event->alt || event->shift || event->ctrl || event->oskey) ; + if (event->alt || event->shift || event->ctrl || event->oskey) { + /* pass */ + } else if (inside || (block->flag & UI_BLOCK_LOOP)) { if (event->val == KM_PRESS) { but = ui_but_find_activated(ar); @@ -6244,8 +6301,9 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle } } - if (bt) + if (bt) { ui_handle_button_activate(C, ar, bt, BUTTON_ACTIVATE); + } } } @@ -6280,7 +6338,7 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle count = 0; for (but = block->buttons.first; but; but = but->next) { - int doit = 0; + int doit = FALSE; if (but->type != LABEL && but->type != SEPR) count++; @@ -6289,19 +6347,29 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle if (but->rnapoin.data && but->rnaprop) { if (ELEM(RNA_property_subtype(but->rnaprop), PROP_LAYER, PROP_LAYER_MEMBER)) { if (but->rnaindex == act - 1) - doit = 1; + doit = TRUE; } } /* exception for menus like layer buts, with button aligning they're not drawn in order */ else if (but->type == TOGR) { if (but->bitnr == act - 1) - doit = 1; + doit = TRUE; + } + else if (count == act) { + doit = TRUE; } - else if (count == act) - doit = 1; if (doit) { - ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_APPLY); + /* activate buttons but open menu's */ + uiButtonActivateType activate; + if (but->type == PULLDOWN) { + activate = BUTTON_ACTIVATE_OPEN; + } + else { + activate = BUTTON_ACTIVATE_APPLY; + } + + ui_handle_button_activate(C, ar, but, activate); break; } } @@ -6439,7 +6507,9 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle * buttons inside this region. disabled inside check .. not sure * anymore why it was there? but it meant enter didn't work * for example when mouse was not over submenu */ - if ((/*inside &&*/ (!menu->menuretval || (menu->menuretval & UI_RETURN_UPDATE)) && retval == WM_UI_HANDLER_CONTINUE) || event->type == TIMER) { + if ((event->type == TIMER) || + (/*inside &&*/ (!menu->menuretval || (menu->menuretval & UI_RETURN_UPDATE)) && retval == WM_UI_HANDLER_CONTINUE)) + { but = ui_but_find_activated(ar); if (but) { diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index e728c861933..a5e4fa5890f 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -159,8 +159,8 @@ typedef struct { struct uiBut { struct uiBut *next, *prev; int flag, drawflag; - short type, pointype, bit, bitnr, retval, strwidth, ofs, pos, selsta, selend, alignnr; - short pad1; + eButType type; + short pointype, bit, bitnr, retval, strwidth, ofs, pos, selsta, selend, alignnr; char *str; char strdata[UI_MAX_NAME_STR]; @@ -305,7 +305,17 @@ struct uiBlock { char direction; char dt; /* drawtype: UI_EMBOSS, UI_EMBOSSN ... etc, copied to buttons */ char auto_open; - char _pad[7]; + + /* this setting is used so newly opened menu's dont popout the first item under the mouse, + * the reasoning behind this is because of muscle memory for opening menus. + * + * Without this, the first time opening a Submenu and activating an item in it will be 2 steps, + * but the second time the same item is accessed the menu memory would auto activate the + * last used menu and the key intended to select that submenu ends up being passed into the submenu. + * - Campbell + */ + char auto_is_first_event; + char _pad[6]; double auto_open_last; const char *lockstr; @@ -316,7 +326,8 @@ struct uiBlock { char endblock; /* uiEndBlock done? */ float xofs, yofs; /* offset to parent button */ - int dobounds, mx, my; /* for doing delayed */ + eBlockBoundsCalc bounds_type; /* for doing delayed */ + int mx, my; int bounds, minbounds; /* for doing delayed */ rctf safety; /* pulldowns, to detect outside, can differ per case how it is created */ @@ -529,4 +540,3 @@ int ui_but_anim_expression_create(uiBut *but, const char *str); void ui_but_anim_autokey(struct bContext *C, uiBut *but, struct Scene *scene, float cfra); #endif - diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index a4f1067d069..bebc80cbfc3 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -1648,6 +1648,18 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut ar->regiondata = handle; + /* set UI_BLOCK_NUMSELECT before uiEndBlock() so we get alphanumeric keys assigned */ + if (but) { + if (but->type == PULLDOWN) { + block->flag |= UI_BLOCK_NUMSELECT; + } + } + else { + block->flag |= UI_BLOCK_POPUP | UI_BLOCK_NUMSELECT; + } + + block->flag |= UI_BLOCK_LOOP; + if (!block->endblock) uiEndBlock(C, block); @@ -1665,7 +1677,6 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut saferct = MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct"); saferct->safety = block->safety; BLI_addhead(&block->saferct, saferct); - block->flag |= UI_BLOCK_POPUP | UI_BLOCK_NUMSELECT; } /* clip block with window boundary */ @@ -1680,8 +1691,6 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut ar->winrct.ymax = block->rect.ymax + MENU_TOP; ui_block_translate(block, -ar->winrct.xmin, -ar->winrct.ymin); - - block->flag |= UI_BLOCK_LOOP; /* adds subwindow */ ED_region_init(C, ar); @@ -2427,6 +2436,7 @@ uiPopupBlockHandle *ui_popup_menu_create(bContext *C, ARegion *butregion, uiBut uiPopupMenu *pup; pup = MEM_callocN(sizeof(uiPopupMenu), __func__); pup->block = uiBeginBlock(C, NULL, __func__, UI_EMBOSSP); + pup->block->flag |= UI_BLOCK_NUMSELECT; /* default menus to numselect */ pup->layout = uiBlockLayout(pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, style); pup->slideout = (but && (but->block->flag & UI_BLOCK_LOOP)); pup->but = but; @@ -2492,6 +2502,7 @@ uiPopupMenu *uiPupMenuBegin(bContext *C, const char *title, int icon) pup->block = uiBeginBlock(C, NULL, __func__, UI_EMBOSSP); pup->block->flag |= UI_BLOCK_POPUP_MEMORY; pup->block->puphash = ui_popup_menu_hash(title); + pup->block->auto_is_first_event = TRUE; pup->layout = uiBlockLayout(pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, style); uiLayoutSetOperatorContext(pup->layout, WM_OP_EXEC_REGION_WIN); diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index 9cbd9e0b7da..8b032bb1a3d 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -97,7 +97,6 @@ static void make_prim_finish(bContext *C, int *state, int enter_editmode) static int add_primitive_plane_exec(bContext *C, wmOperator *op) { Object *obedit; - Mesh *me; BMEditMesh *em; float loc[3], rot[3], mat[4][4], dia; int enter_editmode; @@ -108,8 +107,7 @@ static int add_primitive_plane_exec(bContext *C, wmOperator *op) make_prim_init(C, "Plane", &dia, mat, &state, loc, rot, layer); obedit = CTX_data_edit_object(C); - me = obedit->data; - em = me->edit_btmesh; + em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf(em, op, "vertout", "create_grid xsegments=%i ysegments=%i size=%f mat=%m4", 1, 1, dia, mat)) @@ -143,7 +141,6 @@ void MESH_OT_primitive_plane_add(wmOperatorType *ot) static int add_primitive_cube_exec(bContext *C, wmOperator *op) { Object *obedit; - Mesh *me; BMEditMesh *em; float loc[3], rot[3], mat[4][4], dia; int enter_editmode; @@ -154,8 +151,7 @@ static int add_primitive_cube_exec(bContext *C, wmOperator *op) make_prim_init(C, "Cube", &dia, mat, &state, loc, rot, layer); obedit = CTX_data_edit_object(C); - me = obedit->data; - em = me->edit_btmesh; + em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf(em, op, "vertout", "create_cube mat=%m4 size=%f", mat, dia * 2.0f)) { return OPERATOR_CANCELLED; @@ -194,7 +190,6 @@ static const EnumPropertyItem fill_type_items[] = { static int add_primitive_circle_exec(bContext *C, wmOperator *op) { Object *obedit; - Mesh *me; BMEditMesh *em; float loc[3], rot[3], mat[4][4], dia; int enter_editmode; @@ -208,8 +203,7 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op) make_prim_init(C, "Circle", &dia, mat, &state, loc, rot, layer); obedit = CTX_data_edit_object(C); - me = obedit->data; - em = me->edit_btmesh; + em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf(em, op, "vertout", "create_circle segments=%i diameter=%f cap_ends=%b cap_tris=%b mat=%m4", @@ -253,7 +247,6 @@ void MESH_OT_primitive_circle_add(wmOperatorType *ot) static int add_primitive_cylinder_exec(bContext *C, wmOperator *op) { Object *obedit; - Mesh *me; BMEditMesh *em; float loc[3], rot[3], mat[4][4], dia; int enter_editmode; @@ -267,8 +260,7 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op) make_prim_init(C, "Cylinder", &dia, mat, &state, loc, rot, layer); obedit = CTX_data_edit_object(C); - me = obedit->data; - em = me->edit_btmesh; + em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf( em, op, "vertout", @@ -318,7 +310,6 @@ void MESH_OT_primitive_cylinder_add(wmOperatorType *ot) static int add_primitive_cone_exec(bContext *C, wmOperator *op) { Object *obedit; - Mesh *me; BMEditMesh *em; float loc[3], rot[3], mat[4][4], dia; int enter_editmode; @@ -332,8 +323,7 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op) make_prim_init(C, "Cone", &dia, mat, &state, loc, rot, layer); obedit = CTX_data_edit_object(C); - me = obedit->data; - em = me->edit_btmesh; + em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf( em, op, "vertout", @@ -382,7 +372,6 @@ void MESH_OT_primitive_cone_add(wmOperatorType *ot) static int add_primitive_grid_exec(bContext *C, wmOperator *op) { Object *obedit; - Mesh *me; BMEditMesh *em; float loc[3], rot[3], mat[4][4], dia; int enter_editmode; @@ -393,8 +382,7 @@ static int add_primitive_grid_exec(bContext *C, wmOperator *op) make_prim_init(C, "Grid", &dia, mat, &state, loc, rot, layer); obedit = CTX_data_edit_object(C); - me = obedit->data; - em = me->edit_btmesh; + em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf(em, op, "vertout", "create_grid xsegments=%i ysegments=%i size=%f mat=%m4", @@ -438,7 +426,6 @@ void MESH_OT_primitive_grid_add(wmOperatorType *ot) static int add_primitive_monkey_exec(bContext *C, wmOperator *op) { Object *obedit; - Mesh *me; BMEditMesh *em; float loc[3], rot[3], mat[4][4], dia; int enter_editmode; @@ -452,8 +439,7 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op) make_prim_init(C, "Monkey", &dia, mat, &state, loc, rot, layer); obedit = CTX_data_edit_object(C); - me = obedit->data; - em = me->edit_btmesh; + em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf(em, op, "vertout", "create_monkey mat=%m4", mat)) { return OPERATOR_CANCELLED; @@ -484,7 +470,6 @@ void MESH_OT_primitive_monkey_add(wmOperatorType *ot) static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op) { Object *obedit; - Mesh *me; BMEditMesh *em; float loc[3], rot[3], mat[4][4], dia; int enter_editmode; @@ -495,8 +480,7 @@ static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op) make_prim_init(C, "Sphere", &dia, mat, &state, loc, rot, layer); obedit = CTX_data_edit_object(C); - me = obedit->data; - em = me->edit_btmesh; + em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf(em, op, "vertout", "create_uvsphere segments=%i revolutions=%i diameter=%f mat=%m4", @@ -540,7 +524,6 @@ void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot) static int add_primitive_icosphere_exec(bContext *C, wmOperator *op) { Object *obedit; - Mesh *me; BMEditMesh *em; float loc[3], rot[3], mat[4][4], dia; int enter_editmode; @@ -551,8 +534,7 @@ static int add_primitive_icosphere_exec(bContext *C, wmOperator *op) make_prim_init(C, "Icosphere", &dia, mat, &state, loc, rot, layer); obedit = CTX_data_edit_object(C); - me = obedit->data; - em = me->edit_btmesh; + em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf( em, op, "vertout", diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index c8b86354cb8..3ac011550be 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2296,8 +2296,7 @@ void em_setup_viewcontext(bContext *C, ViewContext *vc) view3d_set_viewcontext(C, vc); if (vc->obedit) { - Mesh *me = vc->obedit->data; - vc->em = me->edit_btmesh; + vc->em = BMEdit_FromObject(vc->obedit); } } diff --git a/source/blender/editors/mesh/editmesh_slide.c b/source/blender/editors/mesh/editmesh_slide.c index 40c1ea7eff2..86ea5bc8651 100644 --- a/source/blender/editors/mesh/editmesh_slide.c +++ b/source/blender/editors/mesh/editmesh_slide.c @@ -208,7 +208,7 @@ static void vtx_slide_confirm(bContext *C, wmOperator *op) other = BM_edge_other_vert(vso->sel_edge, vso->start_vtx); } - if (em->me->editflag & ME_EDIT_MIRROR_X) { + if (((Mesh *)em->ob->data)->editflag & ME_EDIT_MIRROR_X) { EDBM_verts_mirror_cache_begin(em, TRUE); mirr_vtx = EDBM_verts_mirror_get(em, vso->start_vtx); @@ -255,7 +255,7 @@ static void vtx_slide_confirm(bContext *C, wmOperator *op) BM_select_history_store(em->bm, vso->start_vtx); } - if (em->me->editflag & ME_EDIT_MIRROR_X) { + if (((Mesh *)em->ob->data)->editflag & ME_EDIT_MIRROR_X) { EDBM_verts_mirror_cache_end(em); } diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 290ef3baba3..03e2f2691a8 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -345,7 +345,6 @@ void EDBM_mesh_make(ToolSettings *ts, Scene *UNUSED(scene), Object *ob) me->edit_btmesh->selectmode = me->edit_btmesh->bm->selectmode = ts->selectmode; me->edit_btmesh->mat_nr = (ob->actcol > 0) ? ob->actcol - 1 : 0; - me->edit_btmesh->me = me; me->edit_btmesh->ob = ob; } @@ -1056,7 +1055,7 @@ static BMVert *cache_mirr_intptr_as_bmvert(intptr_t *index_lookup, int index) #define BM_CD_LAYER_ID "__mirror_index" void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const short use_select) { - Mesh *me = em->me; + Mesh *me = (Mesh *)em->ob->data; BMesh *bm = em->bm; BMIter iter; BMVert *v; diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index b05766d3201..9fc60fff913 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -3697,7 +3697,7 @@ typedef struct ProjectHandle { int thread_index; } ProjectHandle; -static void blend_color_mix(unsigned char *cp, const unsigned char *cp1, const unsigned char *cp2, const int fac) +static void blend_color_mix(unsigned char cp[4], const unsigned char cp1[4], const unsigned char cp2[4], const int fac) { /* this and other blending modes previously used >>8 instead of /255. both * are not equivalent (>>8 is /256), and the former results in rounding @@ -3710,7 +3710,7 @@ static void blend_color_mix(unsigned char *cp, const unsigned char *cp1, const u cp[3] = (mfac * cp1[3] + fac * cp2[3]) / 255; } -static void blend_color_mix_float(float *cp, const float *cp1, const float *cp2, const float fac) +static void blend_color_mix_float(float cp[4], const float cp1[4], const float cp2[4], const float fac) { const float mfac = 1.0f - fac; cp[0] = mfac * cp1[0] + fac * cp2[0]; diff --git a/source/blender/editors/sculpt_paint/paint_undo.c b/source/blender/editors/sculpt_paint/paint_undo.c index 8e6c87c1510..f5b9aa742c6 100644 --- a/source/blender/editors/sculpt_paint/paint_undo.c +++ b/source/blender/editors/sculpt_paint/paint_undo.c @@ -23,7 +23,6 @@ * \brief Undo system for painting and sculpting. */ - #include #include @@ -35,7 +34,7 @@ #include "DNA_userdef_types.h" - +#include "BKE_blender.h" #include "BKE_context.h" #include "BKE_global.h" @@ -43,11 +42,9 @@ #include "paint_intern.h" -#define MAXUNDONAME 64 - typedef struct UndoElem { struct UndoElem *next, *prev; - char name[MAXUNDONAME]; + char name[BKE_UNDO_STR_MAX]; uintptr_t undosize; ListBase elems; @@ -272,4 +269,3 @@ void ED_undo_paint_free(void) undo_stack_free(&ImageUndoStack); undo_stack_free(&MeshUndoStack); } - diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index fc97b9bbb36..4ca9bd95485 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -101,8 +101,8 @@ static void special_transvert_update(Object *obedit) DAG_id_tag_update(obedit->data, 0); if (obedit->type == OB_MESH) { - Mesh *me = obedit->data; - BM_mesh_normals_update(me->edit_btmesh->bm, TRUE); /* does face centers too */ + BMEditMesh *em = BMEdit_FromObject(obedit); + BM_mesh_normals_update(em->bm, TRUE); /* does face centers too */ } else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { Curve *cu = obedit->data; @@ -229,8 +229,7 @@ static void make_trans_verts(Object *obedit, float min[3], float max[3], int mod zero_v3(centroid); if (obedit->type == OB_MESH) { - Mesh *me = obedit->data; - BMEditMesh *em = me->edit_btmesh; + BMEditMesh *em = BMEdit_FromObject(obedit); BMesh *bm = em->bm; BMIter iter; void *userdata[2] = {em, NULL}; @@ -992,11 +991,11 @@ static int snap_curs_to_active(bContext *C, wmOperator *UNUSED(op)) if (obedit) { if (obedit->type == OB_MESH) { + BMEditMesh *em = BMEdit_FromObject(obedit); /* check active */ - Mesh *me = obedit->data; BMEditSelection ese; - if (BM_select_history_active_get(me->edit_btmesh->bm, &ese)) { + if (BM_select_history_active_get(em->bm, &ese)) { BM_editselection_center(&ese, curs); } diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index a21f8fd5f34..23af0d6f8d6 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -4753,8 +4753,7 @@ static void calcNonProportionalEdgeSlide(TransInfo *t, SlideData *sld, const flo static int createSlideVerts(TransInfo *t) { - Mesh *me = t->obedit->data; - BMEditMesh *em = me->edit_btmesh; + BMEditMesh *em = BMEdit_FromObject(t->obedit); BMesh *bm = em->bm; BMIter iter, iter2; BMEdge *e, *e1; diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 237f6b35eb0..a155ff7786a 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -565,8 +565,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], ob = obedit; if (ob->type == OB_MESH) { - Mesh *me = ob->data; - BMEditMesh *em = me->edit_btmesh; + BMEditMesh *em = BMEdit_FromObject(ob); BMVert *eve; BMEditSelection ese; float vec[3] = {0, 0, 0}; diff --git a/source/blender/editors/util/editmode_undo.c b/source/blender/editors/util/editmode_undo.c index 18610d57bbd..9a3b0476205 100644 --- a/source/blender/editors/util/editmode_undo.c +++ b/source/blender/editors/util/editmode_undo.c @@ -29,8 +29,6 @@ * \ingroup edutil */ - - #include #include #include @@ -44,7 +42,7 @@ #include "BLI_dynstr.h" #include "BLI_utildefines.h" - +#include "BKE_blender.h" #include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_global.h" @@ -82,8 +80,6 @@ static void error(const char *UNUSED(arg)) {} /* ****** XXX ***** */ - -#define MAXUNDONAME 64 typedef struct UndoElem { struct UndoElem *next, *prev; ID id; // copy of editmode object ID @@ -91,7 +87,7 @@ typedef struct UndoElem { int type; // type of edited object void *undodata; uintptr_t undosize; - char name[MAXUNDONAME]; + char name[BKE_UNDO_STR_MAX]; void * (*getdata)(bContext * C); void (*freedata)(void *); void (*to_editmode)(void *, void *, void *); diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c index 4213ff68cf2..2ffad3ad796 100644 --- a/source/blender/editors/util/undo.c +++ b/source/blender/editors/util/undo.c @@ -74,8 +74,6 @@ #include "util_intern.h" -#define MAXUNDONAME 64 /* XXX, make common define */ - /* ***************** generic undo system ********************* */ void ED_undo_push(bContext *C, const char *str) @@ -283,7 +281,7 @@ static int ed_undo_exec(bContext *C, wmOperator *UNUSED(op)) static int ed_undo_push_exec(bContext *C, wmOperator *op) { - char str[MAXUNDONAME]; + char str[BKE_UNDO_STR_MAX]; RNA_string_get(op->ptr, "message", str); ED_undo_push(C, str); return OPERATOR_FINISHED; @@ -321,7 +319,7 @@ void ED_OT_undo_push(wmOperatorType *ot) ot->flag = OPTYPE_INTERNAL; - RNA_def_string(ot->srna, "message", "Add an undo step *function may be moved*", MAXUNDONAME, "Undo Message", ""); + RNA_def_string(ot->srna, "message", "Add an undo step *function may be moved*", BKE_UNDO_STR_MAX, "Undo Message", ""); } void ED_OT_redo(wmOperatorType *ot) diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 856b1f83001..baa557c3484 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -135,6 +135,8 @@ int GPU_material_bound(GPUMaterial *material); void GPU_material_vertex_attributes(GPUMaterial *material, struct GPUVertexAttribs *attrib); +int GPU_material_do_color_management(GPUMaterial *mat); + /* Exported shading */ typedef struct GPUShadeInput { diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index c831b92936f..61be4057843 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -387,7 +387,7 @@ void gpu_material_add_node(GPUMaterial *material, GPUNode *node) /* Code generation */ -static int gpu_do_color_management(GPUMaterial *mat) +int GPU_material_do_color_management(GPUMaterial *mat) { return ((mat->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) && !((mat->scene->gm.flag & GAME_GLSL_NO_COLOR_MANAGEMENT))); @@ -1076,7 +1076,7 @@ static void do_material_tex(GPUShadeInput *shi) } if (tex->type==TEX_IMAGE) - if (gpu_do_color_management(mat)) + if (GPU_material_do_color_management(mat)) GPU_link(mat, "srgb_to_linearrgb", tcol, &tcol); if (mtex->mapto & MAP_COL) { @@ -1372,7 +1372,7 @@ void GPU_shadeinput_set(GPUMaterial *mat, Material *ma, GPUShadeInput *shi) GPU_link(mat, "set_value", GPU_uniform(&ma->amb), &shi->amb); GPU_link(mat, "shade_view", GPU_builtin(GPU_VIEW_POSITION), &shi->view); GPU_link(mat, "vcol_attribute", GPU_attribute(CD_MCOL, ""), &shi->vcol); - if (gpu_do_color_management(mat)) + if (GPU_material_do_color_management(mat)) GPU_link(mat, "srgb_to_linearrgb", shi->vcol, &shi->vcol); GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref); } @@ -1516,12 +1516,9 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma) GPU_material_output_link(mat, outlink); } - if (!BKE_scene_use_new_shading_nodes(scene)) { - if (gpu_do_color_management(mat)) - if (mat->outlink) - GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink); - } - + if (GPU_material_do_color_management(mat)) + if (mat->outlink) + GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink); GPU_material_construct_end(mat); diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c index ab805ea6666..c3e23246638 100644 --- a/source/blender/imbuf/intern/rectop.c +++ b/source/blender/imbuf/intern/rectop.c @@ -46,19 +46,19 @@ /* blend modes */ -static void blend_color_mix(char *cp, char *cp1, char *cp2, int fac) +static void blend_color_mix(char cp[3], const char cp1[3], const char cp2[3], const int fac) { /* this and other blending modes previously used >>8 instead of /255. both * are not equivalent (>>8 is /256), and the former results in rounding * errors that can turn colors black fast after repeated blending */ - int mfac = 255 - fac; + const int mfac = 255 - fac; cp[0] = (mfac * cp1[0] + fac * cp2[0]) / 255; cp[1] = (mfac * cp1[1] + fac * cp2[1]) / 255; cp[2] = (mfac * cp1[2] + fac * cp2[2]) / 255; } -static void blend_color_add(char *cp, char *cp1, char *cp2, int fac) +static void blend_color_add(char cp[3], const char cp1[3], const char cp2[3], const int fac) { int temp; @@ -70,7 +70,7 @@ static void blend_color_add(char *cp, char *cp1, char *cp2, int fac) if (temp > 254) cp[2] = 255; else cp[2] = temp; } -static void blend_color_sub(char *cp, char *cp1, char *cp2, int fac) +static void blend_color_sub(char cp[3], const char cp1[3], const char cp2[3], const int fac) { int temp; @@ -82,7 +82,7 @@ static void blend_color_sub(char *cp, char *cp1, char *cp2, int fac) if (temp < 0) cp[2] = 0; else cp[2] = temp; } -static void blend_color_mul(char *cp, char *cp1, char *cp2, int fac) +static void blend_color_mul(char cp[3], const char cp1[3], const char cp2[3], const int fac) { int mfac = 255 - fac; @@ -92,7 +92,7 @@ static void blend_color_mul(char *cp, char *cp1, char *cp2, int fac) cp[2] = (mfac * cp1[2] + fac * ((cp1[2] * cp2[2]) / 255)) / 255; } -static void blend_color_lighten(char *cp, char *cp1, char *cp2, int fac) +static void blend_color_lighten(char cp[3], const char cp1[3], const char cp2[3], const int fac) { /* See if are lighter, if so mix, else don't do anything. * if the paint col is darker then the original, then ignore */ @@ -101,11 +101,12 @@ static void blend_color_lighten(char *cp, char *cp1, char *cp2, int fac) cp[1] = cp1[1]; cp[2] = cp1[2]; } - else + else { blend_color_mix(cp, cp1, cp2, fac); + } } -static void blend_color_darken(char *cp, char *cp1, char *cp2, int fac) +static void blend_color_darken(char cp[3], const char cp1[3], const char cp2[3], const int fac) { /* See if were darker, if so mix, else don't do anything. * if the paint col is brighter then the original, then ignore */ @@ -114,8 +115,9 @@ static void blend_color_darken(char *cp, char *cp1, char *cp2, int fac) cp[1] = cp1[1]; cp[2] = cp1[2]; } - else + else { blend_color_mix(cp, cp1, cp2, fac); + } } unsigned int IMB_blend_color(unsigned int src1, unsigned int src2, int fac, IMB_BlendMode mode) @@ -162,7 +164,7 @@ unsigned int IMB_blend_color(unsigned int src1, unsigned int src2, int fac, IMB_ return dst; } -static void blend_color_mix_float(float *cp, float *cp1, float *cp2, float fac) +static void blend_color_mix_float(float cp[3], const float cp1[3], const float cp2[3], const float fac) { float mfac = 1.0f - fac; cp[0] = mfac * cp1[0] + fac * cp2[0]; @@ -170,7 +172,7 @@ static void blend_color_mix_float(float *cp, float *cp1, float *cp2, float fac) cp[2] = mfac * cp1[2] + fac * cp2[2]; } -static void blend_color_add_float(float *cp, float *cp1, float *cp2, float fac) +static void blend_color_add_float(float cp[3], const float cp1[3], const float cp2[3], const float fac) { cp[0] = cp1[0] + fac * cp2[0]; cp[1] = cp1[1] + fac * cp2[1]; @@ -181,7 +183,7 @@ static void blend_color_add_float(float *cp, float *cp1, float *cp2, float fac) if (cp[2] > 1.0f) cp[2] = 1.0f; } -static void blend_color_sub_float(float *cp, float *cp1, float *cp2, float fac) +static void blend_color_sub_float(float cp[3], const float cp1[3], const float cp2[3], const float fac) { cp[0] = cp1[0] - fac * cp2[0]; cp[1] = cp1[1] - fac * cp2[1]; @@ -192,7 +194,7 @@ static void blend_color_sub_float(float *cp, float *cp1, float *cp2, float fac) if (cp[2] < 0.0f) cp[2] = 0.0f; } -static void blend_color_mul_float(float *cp, float *cp1, float *cp2, float fac) +static void blend_color_mul_float(float cp[3], const float cp1[3], const float cp2[3], const float fac) { float mfac = 1.0f - fac; @@ -201,7 +203,7 @@ static void blend_color_mul_float(float *cp, float *cp1, float *cp2, float fac) cp[2] = mfac * cp1[2] + fac * (cp1[2] * cp2[2]); } -static void blend_color_lighten_float(float *cp, float *cp1, float *cp2, float fac) +static void blend_color_lighten_float(float cp[3], const float cp1[3], const float cp2[3], const float fac) { /* See if are lighter, if so mix, else don't do anything. * if the pafloat col is darker then the original, then ignore */ @@ -214,7 +216,7 @@ static void blend_color_lighten_float(float *cp, float *cp1, float *cp2, float f blend_color_mix_float(cp, cp1, cp2, fac); } -static void blend_color_darken_float(float *cp, float *cp1, float *cp2, float fac) +static void blend_color_darken_float(float cp[3], const float cp1[3], const float cp2[3], const float fac) { /* See if were darker, if so mix, else don't do anything. * if the pafloat col is brighter then the original, then ignore */ diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 5d55bb8a4db..e584cfd76ac 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -92,7 +92,8 @@ typedef struct Mesh { struct MCol *mcol; struct MSticky *msticky; struct Mesh *texcomesh; - + + /* When the object is available, the preferred access method is: BMEdit_FromObject(ob) */ struct BMEditMesh *edit_btmesh; /* not saved in file! */ struct CustomData vdata, edata, fdata; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c index e857d0571cd..ace0f0c8774 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -69,6 +69,9 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, GPUNod node_shader_gpu_tex_mapping(mat, node, in, out); + if (out[0].link && GPU_material_do_color_management(mat)) + GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); + return GPU_stack_link(mat, "node_tex_environment", in, out, GPU_image(ima, iuser, ncd)); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index c492fe9efc7..d6c757222b9 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -69,6 +69,9 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, GPUNodeStack node_shader_gpu_tex_mapping(mat, node, in, out); + if (out[0].link && GPU_material_do_color_management(mat)) + GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); + return GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, ncd)); } diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 439f528c0ef..3356091b97f 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -810,7 +810,6 @@ if(WITH_CYCLES) cycles_kernel cycles_util cycles_subd) - if(WITH_CYCLES_OSL) list(APPEND BLENDER_LINK_LIBS cycles_kernel_osl) endif() From b0605eed2c9f6424c8d8ae4dc053639ece130831 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 10 Sep 2012 11:46:15 +0000 Subject: [PATCH 126/160] Color Management: finish pipeline changes This commit hopefully finishes color management pipeline changes, implements some missed functionality and fixes some bugs. Mainly changes are related on getting rid of old Color Management flag which became counter-intuitive in conjunction with OpenColorIO. Now color management is always assuming to be enabled and non-color managed pipeline is emulated using display device called None. This display has got single view which is basically NO-OP (raw) transformation, not applying any tone curve and displays colors AS-IS. In most cases it behaves the same as disabling Color Management in shading panel, but there is at least one known difference in behavior: compositor and sequence editors would output images in linear space, not in sRGB as it used to be before. It'll be quite tricky to make this behave in exactly the same way as it used to, and not sure if we really need to do it. 3D viewport is supposed to be working in sRGB space, no tonemaps would be applied there. This is another case where compatibility breaks in comparison with old color management pipeline, but supporting display transformation would be tricky since it'll also be needed to make GLSL shaders, textures and so be aware of display transform. Interface is now aware of display transformation, but it only uses default display view, no exposure, gamma or curve mapping is supported there. This is so color widgets could apply display transformation in both directions. Such behavior is a bit counter-intuitive, but it's currently the only way to make color picking working smoothly. In theory we'll need to support color picking color space, but it'll be also a bit tricky since in Blender display transform is configurable from the interface and could be used for artistics needs and in such design it's not possible to figure out invertable color space which could be used for color picking. In other software it's not so big issue since all color spaces, display transform and so are strictly defined by pipeline and in this case it is possible to define color picking space which would be close enough to display space. Sequencer's color space now could be configured from the interface -- it's settings are situated in Scene buttons, Color Management panel. Default space is sRGB. It was made configurable because we used vd16 color space during Mango which was close to Film view used by grading department. Sequencer will convert float buffers to this color space before operating with them hopefully giving better results. Byte buffers wouldn't be converted to this color space an they'll be handled in their own colors[ace. Converting them to sequencer's working space would lead to precision loss without much visible benefits. It shouldn't be an issue since float and byte images would never be blended together -- byte image would be converted to float first if it's needed to be blended with float image. Byte buffers now allowed to be color managed. This was needed to make code in such areas as baking and rendering don't have hardcoded linear to sRGB conversions, making things more clear from code point of view. Input color space is now assigning on image/movie clip load and default roles are used for this. So for float images default space would be rec709 and for byte images default space would be sRGB. Added Non-Color color space which is aimed to be used for such things as normal/heights maps. It's currently the same as raw colorspace, just has got more clear naming for users. Probably we'll also need to make it not affected by display transformation. Think this is all main pipeline-related changes, more details would be there: http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management Other changes and fixes: - Lots of internal code clean up in color management module. - Made OpenColorIO module using guarded memory allocation. This allowed to fix couple of memory leaks and would help preventing leaks in the future. - Made sure color unpremultiply and dither are supported by all OpenColorIO defined color transformations. - Made compositor's preview images be aware of display transformation. Legacy compositor still uses old Color Management flags, but likely we'll disable compositor for the release and remove legacy code soon, so don't think we'll need to spend time on porting that code to new color management system. - Made OpenGL rendering be aware of display transform when saving render result. Now it behaves in the same way as regular rendering. TODO: - HSV widgets are using linear rgb/sRGB conversions for single channel, not sure how this should be ported to new color pipeline. - Image stamp would use hardcoded linear rgb to sRGB conversion for filling rectangles. Probably it should use default display view for this instead, would check this with Brecht. - Get rid of None color space which was only used for compatibility reasons. - Made it more clear which color spaces could be used as input space. - There're also some remained TODO's in the code marked as OCIO_TODO, but wouldn't consider them as stoppers for at least this commit. --- intern/opencolorio/CMakeLists.txt | 2 +- intern/opencolorio/SConscript | 2 +- intern/opencolorio/ocio_capi.cpp | 51 +- intern/opencolorio/ocio_capi.h | 10 +- release/datafiles/colormanagement/config.ocio | 35 +- .../startup/bl_ui/properties_render.py | 5 +- .../scripts/startup/bl_ui/properties_scene.py | 15 +- source/blender/blenkernel/BKE_colortools.h | 7 +- source/blender/blenkernel/BKE_node.h | 5 +- source/blender/blenkernel/BKE_scene.h | 2 + source/blender/blenkernel/BKE_sequencer.h | 12 +- source/blender/blenkernel/intern/colortools.c | 35 +- source/blender/blenkernel/intern/image.c | 15 +- source/blender/blenkernel/intern/scene.c | 25 + source/blender/blenkernel/intern/seqeffects.c | 6 +- source/blender/blenkernel/intern/sequencer.c | 109 +- source/blender/blenloader/intern/readfile.c | 15 + source/blender/compositor/COM_compositor.h | 15 +- .../intern/COM_CompositorContext.cpp | 12 +- .../compositor/intern/COM_CompositorContext.h | 26 +- .../compositor/intern/COM_ExecutionSystem.cpp | 6 +- .../compositor/intern/COM_ExecutionSystem.h | 4 +- source/blender/compositor/intern/COM_Node.cpp | 8 +- source/blender/compositor/intern/COM_Node.h | 4 +- .../compositor/intern/COM_compositor.cpp | 8 +- .../blender/compositor/nodes/COM_BlurNode.cpp | 8 +- .../compositor/nodes/COM_BokehImageNode.cpp | 2 +- .../compositor/nodes/COM_ChannelMatteNode.cpp | 2 +- .../compositor/nodes/COM_ChromaMatteNode.cpp | 2 +- .../compositor/nodes/COM_ColorMatteNode.cpp | 2 +- .../compositor/nodes/COM_CompositorNode.cpp | 2 +- .../compositor/nodes/COM_DespeckleNode.cpp | 2 +- .../nodes/COM_DifferenceMatteNode.cpp | 2 +- .../compositor/nodes/COM_DilateErodeNode.cpp | 2 +- .../nodes/COM_DistanceMatteNode.cpp | 2 +- .../compositor/nodes/COM_FilterNode.cpp | 2 +- .../compositor/nodes/COM_ImageNode.cpp | 4 +- .../nodes/COM_LuminanceMatteNode.cpp | 2 +- .../blender/compositor/nodes/COM_MixNode.cpp | 2 +- .../compositor/nodes/COM_MovieClipNode.cpp | 22 +- .../compositor/nodes/COM_OutputFileNode.cpp | 7 +- .../compositor/nodes/COM_RenderLayersNode.cpp | 62 +- .../compositor/nodes/COM_RenderLayersNode.h | 2 +- .../compositor/nodes/COM_SplitViewerNode.cpp | 7 +- .../compositor/nodes/COM_TextureNode.cpp | 2 +- .../compositor/nodes/COM_ViewerNode.cpp | 7 +- .../operations/COM_OutputFileOperation.cpp | 12 +- .../operations/COM_OutputFileOperation.h | 7 +- .../operations/COM_PreviewOperation.cpp | 13 +- .../operations/COM_PreviewOperation.h | 5 +- .../operations/COM_SplitViewerOperation.cpp | 18 +- .../operations/COM_ViewerBaseOperation.cpp | 11 +- .../operations/COM_ViewerBaseOperation.h | 12 +- .../operations/COM_ViewerOperation.cpp | 16 +- source/blender/editors/include/ED_view3d.h | 8 +- source/blender/editors/interface/interface.c | 30 +- .../editors/interface/interface_draw.c | 13 +- .../editors/interface/interface_handlers.c | 12 +- .../editors/interface/interface_intern.h | 9 + .../blender/editors/interface/interface_ops.c | 20 +- .../editors/interface/interface_regions.c | 31 +- .../editors/interface/interface_widgets.c | 16 +- source/blender/editors/object/object_bake.c | 10 +- .../blender/editors/render/render_internal.c | 18 +- source/blender/editors/render/render_opengl.c | 54 +- .../blender/editors/render/render_preview.c | 29 +- .../editors/sculpt_paint/paint_image.c | 20 +- .../editors/space_image/image_buttons.c | 12 +- .../blender/editors/space_image/image_draw.c | 4 +- .../blender/editors/space_image/image_ops.c | 9 +- .../blender/editors/space_image/space_image.c | 4 +- source/blender/editors/space_node/node_edit.c | 5 +- .../editors/space_sequencer/sequencer_view.c | 2 +- .../blender/editors/space_view3d/drawmesh.c | 10 +- .../editors/space_view3d/view3d_draw.c | 46 +- source/blender/gpu/intern/gpu_draw.c | 7 +- source/blender/gpu/intern/gpu_material.c | 8 +- source/blender/imbuf/IMB_colormanagement.h | 80 +- source/blender/imbuf/IMB_imbuf_types.h | 15 +- .../imbuf/intern/IMB_colormanagement_intern.h | 13 +- source/blender/imbuf/intern/allocimbuf.c | 6 +- source/blender/imbuf/intern/colormanagement.c | 2429 ++++++++++------- source/blender/makesdna/DNA_color_types.h | 2 +- source/blender/makesdna/DNA_scene_types.h | 3 +- .../blender/makesrna/intern/rna_image_api.c | 18 +- source/blender/makesrna/intern/rna_scene.c | 38 +- source/blender/makesrna/intern/rna_space.c | 2 +- .../nodes/composite/node_composite_tree.c | 8 +- .../nodes/composite/node_composite_util.c | 3 + .../composite/nodes/node_composite_image.c | 3 + .../nodes/node_composite_outputFile.c | 3 + .../render/intern/include/render_result.h | 6 +- source/blender/render/intern/source/envmap.c | 3 +- .../blender/render/intern/source/pipeline.c | 11 +- .../render/intern/source/render_result.c | 31 +- .../render/intern/source/render_texture.c | 21 +- .../blender/render/intern/source/rendercore.c | 12 +- .../blender/render/intern/source/shadeinput.c | 9 +- .../blender/windowmanager/intern/wm_files.c | 4 +- 99 files changed, 2284 insertions(+), 1486 deletions(-) diff --git a/intern/opencolorio/CMakeLists.txt b/intern/opencolorio/CMakeLists.txt index 3ad2e91287b..131a829017b 100644 --- a/intern/opencolorio/CMakeLists.txt +++ b/intern/opencolorio/CMakeLists.txt @@ -29,7 +29,7 @@ set(INC ) set(INC_SYS - + ../guardedalloc ) set(SRC diff --git a/intern/opencolorio/SConscript b/intern/opencolorio/SConscript index ef814ed1509..4860d94947e 100644 --- a/intern/opencolorio/SConscript +++ b/intern/opencolorio/SConscript @@ -4,7 +4,7 @@ Import('env') sources = env.Glob('*.cpp') -incs = '.' +incs = '. ../guardedalloc' incs += ' ' + env['BF_OCIO_INC'] if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): diff --git a/intern/opencolorio/ocio_capi.cpp b/intern/opencolorio/ocio_capi.cpp index 6fec1185bd5..6fb719dfc35 100644 --- a/intern/opencolorio/ocio_capi.cpp +++ b/intern/opencolorio/ocio_capi.cpp @@ -28,6 +28,7 @@ #include +#include "MEM_guardedalloc.h" #define OCIO_CAPI_IMPLEMENTATION #include "ocio_capi.h" @@ -39,6 +40,13 @@ # define OCIO_abort() abort() #endif +#if defined(_MSC_VER) +# define __func__ __FUNCTION__ +#endif + +#define MEM_NEW(type) new(MEM_mallocN(sizeof(type), __func__)) type() +#define MEM_DELETE(what, type) { what->~type(); MEM_freeN(what); } (void)0 + static void OCIO_reportError(const char *err) { std::cerr << "OpenColorIO Error: " << err << std::endl; @@ -53,7 +61,8 @@ static void OCIO_reportException(Exception &exception) ConstConfigRcPtr *OCIO_getCurrentConfig(void) { - ConstConfigRcPtr *config = new ConstConfigRcPtr(); + ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr); + try { *config = GetCurrentConfig(); @@ -79,7 +88,7 @@ void OCIO_setCurrentConfig(const ConstConfigRcPtr *config) ConstConfigRcPtr *OCIO_configCreateFromEnv(void) { - ConstConfigRcPtr *config = new ConstConfigRcPtr(); + ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr); try { *config = Config::CreateFromEnv(); @@ -97,7 +106,7 @@ ConstConfigRcPtr *OCIO_configCreateFromEnv(void) ConstConfigRcPtr *OCIO_configCreateFromFile(const char *filename) { - ConstConfigRcPtr *config = new ConstConfigRcPtr(); + ConstConfigRcPtr *config = MEM_NEW(ConstConfigRcPtr); try { *config = Config::CreateFromFile(filename); @@ -114,7 +123,7 @@ ConstConfigRcPtr *OCIO_configCreateFromFile(const char *filename) void OCIO_configRelease(ConstConfigRcPtr *config) { - delete config; + MEM_DELETE(config, ConstConfigRcPtr); } int OCIO_configGetNumColorSpaces(ConstConfigRcPtr *config) @@ -143,7 +152,7 @@ const char *OCIO_configGetColorSpaceNameByIndex(ConstConfigRcPtr *config, int in ConstColorSpaceRcPtr *OCIO_configGetColorSpace(ConstConfigRcPtr *config, const char *name) { - ConstColorSpaceRcPtr *cs = new ConstColorSpaceRcPtr(); + ConstColorSpaceRcPtr *cs = MEM_NEW(ConstColorSpaceRcPtr); try { *cs = (*config)->getColorSpace(name); @@ -153,7 +162,7 @@ ConstColorSpaceRcPtr *OCIO_configGetColorSpace(ConstConfigRcPtr *config, const c } catch (Exception &exception) { OCIO_reportException(exception); - delete cs; + MEM_DELETE(cs, ConstColorSpaceRcPtr); } return NULL; @@ -257,12 +266,12 @@ const char *OCIO_configGetDisplayColorSpaceName(ConstConfigRcPtr *config, const void OCIO_colorSpaceRelease(ConstColorSpaceRcPtr *cs) { - delete cs; + MEM_DELETE(cs, ConstColorSpaceRcPtr); } ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(ConstConfigRcPtr *config, const char *srcName, const char *dstName) { - ConstProcessorRcPtr *p = new ConstProcessorRcPtr(); + ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr); try { *p = (*config)->getProcessor(srcName, dstName); @@ -279,7 +288,7 @@ ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(ConstConfigRcPtr *config, ConstProcessorRcPtr *OCIO_configGetProcessor(ConstConfigRcPtr *config, ConstTransformRcPtr *transform) { - ConstProcessorRcPtr *p = new ConstProcessorRcPtr(); + ConstProcessorRcPtr *p = MEM_NEW(ConstProcessorRcPtr); try { *p = (*config)->getProcessor(*transform); @@ -367,7 +376,8 @@ void OCIO_processorApplyRGBA_predivide(ConstProcessorRcPtr *processor, float *pi void OCIO_processorRelease(ConstProcessorRcPtr *p) { - delete p; + p->~ConstProcessorRcPtr(); + MEM_freeN(p); } const char *OCIO_colorSpaceGetName(ConstColorSpaceRcPtr *cs) @@ -387,7 +397,7 @@ const char *OCIO_colorSpaceGetFamily(ConstColorSpaceRcPtr *cs) DisplayTransformRcPtr *OCIO_createDisplayTransform(void) { - DisplayTransformRcPtr *dt = new DisplayTransformRcPtr(); + DisplayTransformRcPtr *dt = MEM_NEW(DisplayTransformRcPtr); *dt = DisplayTransform::Create(); @@ -421,15 +431,15 @@ void OCIO_displayTransformSetLinearCC(DisplayTransformRcPtr *dt, ConstTransformR void OCIO_displayTransformRelease(DisplayTransformRcPtr *dt) { - delete dt; - dt = NULL; + MEM_DELETE(dt, DisplayTransformRcPtr); } PackedImageDesc *OCIO_createPackedImageDesc(float *data, long width, long height, long numChannels, - long chanStrideBytes, long xStrideBytes, long yStrideBytes) + long chanStrideBytes, long xStrideBytes, long yStrideBytes) { try { - PackedImageDesc *id = new PackedImageDesc(data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes); + void *mem = MEM_mallocN(sizeof(PackedImageDesc), __func__); + PackedImageDesc *id = new(mem) PackedImageDesc(data, width, height, numChannels, chanStrideBytes, xStrideBytes, yStrideBytes); return id; } @@ -442,13 +452,12 @@ PackedImageDesc *OCIO_createPackedImageDesc(float *data, long width, long height void OCIO_packedImageDescRelease(PackedImageDesc* id) { - delete id; - id = NULL; + MEM_DELETE(id, PackedImageDesc); } ExponentTransformRcPtr *OCIO_createExponentTransform(void) { - ExponentTransformRcPtr *et = new ExponentTransformRcPtr(); + ExponentTransformRcPtr *et = MEM_NEW(ExponentTransformRcPtr); *et = ExponentTransform::Create(); @@ -462,12 +471,12 @@ void OCIO_exponentTransformSetValue(ExponentTransformRcPtr *et, const float *exp void OCIO_exponentTransformRelease(ExponentTransformRcPtr *et) { - delete et; + MEM_DELETE(et, ExponentTransformRcPtr); } MatrixTransformRcPtr *OCIO_createMatrixTransform(void) { - MatrixTransformRcPtr *mt = new MatrixTransformRcPtr(); + MatrixTransformRcPtr *mt = MEM_NEW(MatrixTransformRcPtr); *mt = MatrixTransform::Create(); @@ -481,7 +490,7 @@ void OCIO_matrixTransformSetValue(MatrixTransformRcPtr *mt, const float *m44, co void OCIO_matrixTransformRelease(MatrixTransformRcPtr *mt) { - delete mt; + MEM_DELETE(mt, MatrixTransformRcPtr); } void OCIO_matrixTransformScale(float * m44, float * offset4, const float *scale4f) diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index c3830f3fc72..11973bcadf0 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -39,10 +39,12 @@ extern "C" { #ifndef OCIO_CAPI_IMPLEMENTATION - #define OCIO_ROLE_SCENE_LINEAR "scene_linear" - #define OCIO_ROLE_COLOR_PICKING "color_picking" - #define OCIO_ROLE_TEXTURE_PAINT "texture_paint" - #define OCIO_ROLE_SEQUENCER "sequencer" + #define OCIO_ROLE_SCENE_LINEAR "scene_linear" + #define OCIO_ROLE_COLOR_PICKING "color_picking" + #define OCIO_ROLE_TEXTURE_PAINT "texture_paint" + #define OCIO_ROLE_DEFAULT_BYTE "default_byte" + #define OCIO_ROLE_DEFAULT_FLOAT "default_float" + #define OCIO_ROLE_DEFAULT_SEQUENCER "default_sequencer" OCIO_DECLARE_HANDLE(ConstConfigRcPtr); OCIO_DECLARE_HANDLE(ConstColorSpaceRcPtr); diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio index 674c2adba0f..e8fb03b6f8e 100644 --- a/release/datafiles/colormanagement/config.ocio +++ b/release/datafiles/colormanagement/config.ocio @@ -1,3 +1,7 @@ +# OpenCOlorIO configuration file for Blender +# +# Based on aces, nuke-default and spi configurations from OpenColorIO-Config + ocio_profile_version: 1 search_path: luts @@ -7,11 +11,23 @@ luma: [0.2126, 0.7152, 0.0722] description: RRT version ut33 roles: - color_picking: raw reference: aces + + # Internal scene linear space scene_linear: rec709 + + # Default color space for byte image + default_byte: sRGB + + # Default color space for float images + default_float: rec709 + + # Default color space sequencer is working in + default_sequencer: sRGB + + # Color spaces for color picking and exture painting (not internally supported yet) + color_picking: raw texture_paint: raw - sequencer: vd16 displays: sRGB: @@ -33,8 +49,10 @@ displays: - ! {name: DCI, colorspace: dci_xyz} - ! {name: Raw, colorspace: raw} - ! {name: Log, colorspace: adx10} + None: + - ! {name: Default, colorspace: raw} -active_displays: [sRGB, P3DCI, Rec709, XYZ] +active_displays: [sRGB, P3DCI, Rec709, XYZ, None] active_views: [Default, RRT, Raw, Log] colorspaces: @@ -238,3 +256,14 @@ colorspaces: children: - ! {src: vd16.spi1d, interpolation: nearest} - ! {src: rec709_to_aces.spimtx, interpolation: linear} + + - ! + name: Non-Color + family: raw + description: | + Color space used for images which contains non-color data (i,e, normal maps) + equalitygroup: + bitdepth: 32f + isdata: true + allocation: uniform + allocationvars: [0, 1] diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index 8b632ef8891..b777fcddcf2 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -316,10 +316,7 @@ class RENDER_PT_shading(RenderButtonsPanel, Panel): col = split.column() col.prop(rd, "use_raytrace", text="Ray Tracing") - col.prop(rd, "use_color_management") - sub = col.row() - sub.active = rd.use_color_management == True - sub.prop(rd, "use_color_unpremultiply") + col.prop(rd, "use_color_unpremultiply") col.prop(rd, "alpha_mode", text="Alpha") diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py index fcfd29c0b27..2ccdb9cee26 100644 --- a/release/scripts/startup/bl_ui/properties_scene.py +++ b/release/scripts/startup/bl_ui/properties_scene.py @@ -242,8 +242,19 @@ class SCENE_PT_color_management(Panel): scene = context.scene - layout.prop(scene.display_settings, "display_device") - layout.template_colormanaged_view_settings(scene, "view_settings") + col = layout.column() + col.label(text="Display:") + col.prop(scene.display_settings, "display_device") + + col = layout.column() + col.separator() + col.label(text="Render:") + col.template_colormanaged_view_settings(scene, "view_settings") + + col = layout.column() + col.separator() + col.label(text="Sequencer:") + col.prop(scene.sequencer_colorspace_settings, "name") class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, Panel): diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index 7c2c9bb62ce..d19c57b0d5b 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -92,8 +92,11 @@ void curvemapping_do_ibuf(struct CurveMapping *cumap, struct ImBu void curvemapping_premultiply(struct CurveMapping *cumap, int restore); -void BKE_histogram_update_sample_line(struct Histogram *hist, struct ImBuf *ibuf, const short use_color_management); -void scopes_update(struct Scopes *scopes, struct ImBuf *ibuf, int use_color_management); +void BKE_histogram_update_sample_line(struct Histogram *hist, struct ImBuf *ibuf, + const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings); +void scopes_update(struct Scopes *scopes, struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings); void scopes_free(struct Scopes *scopes); void scopes_new(struct Scopes *scopes); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 438d5110666..6ad2ad924e2 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -64,6 +64,8 @@ struct Tex; struct SpaceNode; struct ARegion; struct Object; +struct ColorManagedViewSettings; +struct ColorManagedDisplaySettings; /* ************** NODE TYPE DEFINITIONS ***** */ @@ -725,7 +727,8 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria struct CompBuf; struct bNodeTreeExec *ntreeCompositBeginExecTree(struct bNodeTree *ntree, int use_tree_data); void ntreeCompositEndExecTree(struct bNodeTreeExec *exec, int use_tree_data); -void ntreeCompositExecTree(struct bNodeTree *ntree, struct RenderData *rd, int rendering, int do_previews); +void ntreeCompositExecTree(struct bNodeTree *ntree, struct RenderData *rd, int rendering, int do_previews, + const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings); void ntreeCompositTagRender(struct Scene *sce); int ntreeCompositTagAnimated(struct bNodeTree *ntree); void ntreeCompositTagGenerators(struct bNodeTree *ntree); diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index bce4243190a..023b7e85c40 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -108,6 +108,8 @@ float get_render_aosss_error(struct RenderData *r, float error); int BKE_scene_use_new_shading_nodes(struct Scene *scene); +void BKE_scene_disable_color_management(struct Scene *scene); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 5bef0b2a771..81fb936f244 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -176,6 +176,16 @@ struct ImBuf *BKE_sequencer_give_ibuf_direct(SeqRenderData context, float cfra, struct ImBuf *BKE_sequencer_give_ibuf_seqbase(SeqRenderData context, float cfra, int chan_shown, struct ListBase *seqbasep); void BKE_sequencer_give_ibuf_prefetch_request(SeqRenderData context, float cfra, int chan_shown); +/* ********************************************************************** + * sequencer.c + * + * sequencer color space functions + * ********************************************************************** */ + +void BKE_sequencer_imbuf_to_sequencer_space(struct Scene *scene, struct ImBuf *ibuf, int make_float); +void BKE_sequencer_imbuf_from_sequencer_space(struct Scene *scene, struct ImBuf *ibuf); +void BKE_sequencer_pixel_from_sequencer_space_v4(struct Scene *scene, float pixel[4]); + /* ********************************************************************** * sequencer scene functions * ********************************************************************** */ @@ -349,7 +359,7 @@ struct Sequence *BKE_sequencer_add_sound_strip(struct bContext *C, ListBase *seq struct Sequence *BKE_sequencer_add_movie_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); /* view3d draw callback, run when not in background view */ -typedef struct ImBuf *(*SequencerDrawView)(struct Scene *, struct Object *, int, int, unsigned int, int, int, char[256]); +typedef struct ImBuf *(*SequencerDrawView)(struct Scene *, struct Object *, int, int, unsigned int, int, int, int, char[256]); extern SequencerDrawView sequencer_view3d_cb; /* copy/paste */ diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 65bffe42a1e..27651ac1731 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -998,7 +998,8 @@ static void save_sample_line(Scopes *scopes, const int idx, const float fx, cons } } -void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const short use_color_management) +void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) { int i, x, y; float *fp; @@ -1010,6 +1011,8 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const short int y1 = 0.5f + hist->co[0][1] * ibuf->y; int y2 = 0.5f + hist->co[1][1] * ibuf->y; + struct ColormanageProcessor *cm_processor = NULL; + hist->channels = 3; hist->x_resolution = 256; hist->xmax = 1.0f; @@ -1017,6 +1020,9 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const short if (ibuf->rect == NULL && ibuf->rect_float == NULL) return; + if (ibuf->rect_float) + cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); + /* persistent draw */ hist->flag |= HISTO_FLAG_SAMPLELINE; /* keep drawing the flag after */ @@ -1031,10 +1037,8 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const short if (ibuf->rect_float) { fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x)); - if (use_color_management) - linearrgb_to_srgb_v3_v3(rgb, fp); - else - copy_v3_v3(rgb, fp); + copy_v3_v3(rgb, fp); + IMB_colormanagement_processor_apply_v3(cm_processor, rgb); hist->data_luma[i] = rgb_to_luma(rgb); hist->data_r[i] = rgb[0]; @@ -1052,9 +1056,13 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const short } } } + + if (cm_processor) + IMB_colormanagement_processor_free(cm_processor); } -void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) +void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) { int x, y, c; unsigned int n, nl; @@ -1067,6 +1075,8 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) int ycc_mode = -1; const short is_float = (ibuf->rect_float != NULL); + struct ColormanageProcessor *cm_processor = NULL; + if (ibuf->rect == NULL && ibuf->rect_float == NULL) return; if (scopes->ok == 1) return; @@ -1136,6 +1146,9 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) else rc = (unsigned char *)ibuf->rect; + if (ibuf->rect_float) + cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); + for (y = 0; y < ibuf->y; y++) { if (savedlines < scopes->sample_lines && y >= ((savedlines) * ibuf->y) / (scopes->sample_lines + 1)) { saveline = 1; @@ -1146,11 +1159,8 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) for (x = 0; x < ibuf->x; x++) { if (is_float) { - if (use_color_management) - linearrgb_to_srgb_v3_v3(rgba, rf); - else - copy_v3_v3(rgba, rf); - rgba[3] = rf[3]; + copy_v4_v4(rgba, rf); + IMB_colormanagement_processor_apply_v4(cm_processor, rgba); } else { for (c = 0; c < 4; c++) @@ -1221,6 +1231,9 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management) MEM_freeN(bin_b); MEM_freeN(bin_a); + if (cm_processor) + IMB_colormanagement_processor_free(cm_processor); + scopes->ok = 1; } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index a0839a502b7..3d1133b7475 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -301,6 +301,12 @@ static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int frame) else ibuf->flags &= ~IB_cm_predivide; + if (ima->source == IMA_SRC_GENERATED) { + /* for other image types spaces are set by image_initialize_after_load */ + + IMB_colormanagement_imbuf_assign_spaces(ibuf, &ima->colorspace_settings); + } + /* this function accepts (link == NULL) */ BLI_insertlinkbefore(&ima->ibufs, link, ibuf); @@ -1499,7 +1505,9 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* this could be an argument if we want to operate on non linear float imbuf's * for now though this is only used for renders which use scene settings */ - const int do_color_management = (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) != 0; + + /* OCIO_TODO: for now harcode sRGB to linearrgb conversion, need to be fixed ASAP */ + const int do_color_management = TRUE; #define BUFF_MARGIN_X 2 #define BUFF_MARGIN_Y 1 @@ -2586,7 +2594,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ /* invalidate color managed buffers if render result changed */ BLI_lock_thread(LOCK_COLORMANAGE); if (ibuf->x != rres.rectx || ibuf->y != rres.recty || ibuf->rect_float != rectf) { - IMB_display_buffer_invalidate(ibuf); + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; } ibuf->x = rres.rectx; @@ -2626,8 +2634,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ BLI_unlock_thread(LOCK_COLORMANAGE); - /* since its possible to access the buffer from the image directly, set the profile [#25073] */ - ibuf->profile = (iuser->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_NONE; + ibuf->profile = IB_PROFILE_LINEAR_RGB; ibuf->dither = dither; if (iuser->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE) { diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 1bd8f3dfcd2..2dec72560a2 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -77,6 +77,8 @@ #include "RE_engine.h" +#include "IMB_colormanagement.h" + //XXX #include "BIF_previewrender.h" //XXX #include "BIF_editseq.h" @@ -384,7 +386,14 @@ Scene *BKE_scene_add(const char *name) sce->r.frs_sec_base = 1; sce->r.edgeint = 10; sce->r.ocres = 128; + + /* OCIO_TODO: for forwards compatibiliy only, so if no tonecurve are used, + * images would look in the same way as in current blender + * + * perhaps at some point should be completely deprecated? + */ sce->r.color_mgt_flag |= R_COLOR_MANAGEMENT; + sce->r.gauss = 1.0; /* deprecated but keep for upwards compat */ @@ -1255,3 +1264,19 @@ void BKE_scene_base_flag_from_objects(struct Scene *scene) base = base->next; } } + +void BKE_scene_disable_color_management(Scene *scene) +{ + ColorManagedDisplaySettings *display_settings = &scene->display_settings; + ColorManagedViewSettings *view_settings = &scene->view_settings; + const char *view; + + /* NOTE: None display with Default view should always exist in OCIO configuration, otherwise it wouldn't work as expected */ + BLI_strncpy(display_settings->display_device, "None", sizeof(display_settings->display_device)); + + view = IMB_colormanagement_view_get_default_name(display_settings->display_device); + + if (view) { + BLI_strncpy(view_settings->view_transform, view, sizeof(view_settings->view_transform)); + } +} diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index acf38ace00a..eaf3ec384c8 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -120,13 +120,13 @@ static ImBuf *prepare_effect_imbufs(SeqRenderData context, ImBuf *ibuf1, ImBuf * } if (ibuf1 && !ibuf1->rect_float && out->rect_float) { - IMB_colormanagement_imbuf_to_sequencer_space(ibuf1, TRUE); + BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf1, TRUE); } if (ibuf2 && !ibuf2->rect_float && out->rect_float) { - IMB_colormanagement_imbuf_to_sequencer_space(ibuf2, TRUE); + BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf2, TRUE); } if (ibuf3 && !ibuf3->rect_float && out->rect_float) { - IMB_colormanagement_imbuf_to_sequencer_space(ibuf3, TRUE); + BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf3, TRUE); } if (ibuf1 && !ibuf1->rect && !out->rect_float) { diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 611b175c9ef..5e79de7b4cd 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -309,6 +309,94 @@ void BKE_sequencer_editing_free(Scene *scene) scene->ed = NULL; } +/*********************** Sequencer color space functions *************************/ + +void BKE_sequencer_imbuf_assign_spaces(Scene *scene, ImBuf *ibuf) +{ + IMB_colormanagement_imbuf_assign_spaces(ibuf, NULL); + IMB_colormanagement_imbuf_assign_float_space(ibuf, &scene->sequencer_colorspace_settings); +} + +void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_float) +{ + const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); + const char *to_colorspace = scene->sequencer_colorspace_settings.name; + int predivide = ibuf->flags & IB_cm_predivide; + + if (!ibuf->rect_float) { + if (make_float && ibuf->rect) { + /* when converting byte buffer to float in sequencer we need to make float + * buffer be in sequencer's working space, which is currently only doable + * from linear space. + * + */ + + /* + * OCIO_TODO: would be nice to support direct single transform from byte to sequencer's + */ + + IMB_colormanagement_imbuf_float_from_rect(ibuf); + } + else { + /* if there's only byte buffer in image it's already in compositor's working space, + * nothing to do here + */ + + return; + } + } + + if (from_colorspace && from_colorspace[0] != '\0') { + if (ibuf->rect) + imb_freerectImBuf(ibuf); + + IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, + from_colorspace, to_colorspace, predivide); + + ibuf->profile = IB_PROFILE_SRGB; + } + else { + /* if no color management enables fallback to legacy conversion */ + IMB_convert_profile(ibuf, IB_PROFILE_NONE); + } +} + +void BKE_sequencer_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf) +{ + const char *from_colorspace = scene->sequencer_colorspace_settings.name; + const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); + + if (!ibuf->rect_float) + return; + + if (to_colorspace && to_colorspace[0] != '\0') { + int predivide = ibuf->flags & IB_cm_predivide; + + IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, + from_colorspace, to_colorspace, predivide); + + ibuf->profile = IB_PROFILE_LINEAR_RGB; + } + else { + /* if no color management enables fallback to legacy conversion */ + IMB_convert_profile(ibuf, IB_PROFILE_LINEAR_RGB); + } +} + +void BKE_sequencer_pixel_from_sequencer_space_v4(struct Scene *scene, float pixel[4]) +{ + const char *from_colorspace = scene->sequencer_colorspace_settings.name; + const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); + + if (to_colorspace && to_colorspace[0] != '\0') { + IMB_colormanagement_transform_v4(pixel, from_colorspace, to_colorspace); + } + else { + /* if no color management enables fallback to legacy conversion */ + srgb_to_linearrgb_v4(pixel, pixel); + } +} + /*********************** sequencer pipeline functions *************************/ SeqRenderData BKE_sequencer_new_render_data(Main *bmain, Scene *scene, int rectx, int recty, int preview_render_size) @@ -1220,7 +1308,12 @@ static ImBuf *seq_proxy_fetch(SeqRenderData context, Sequence *seq, int cfra) } if (BLI_exists(name)) { - return IMB_loadiffname(name, IB_rect); + ImBuf *ibuf = IMB_loadiffname(name, IB_rect); + + if (ibuf) + BKE_sequencer_imbuf_assign_spaces(context.scene, ibuf); + + return ibuf; } else { return NULL; @@ -1828,7 +1921,7 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, if (seq->flag & SEQ_MAKE_FLOAT) { if (!ibuf->rect_float) { - IMB_colormanagement_imbuf_to_sequencer_space(ibuf, TRUE); + BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf, TRUE); } if (ibuf->rect) { @@ -1895,6 +1988,8 @@ static void copy_to_ibuf_still(SeqRenderData context, Sequence *seq, float nr, I * changing the cached image... */ ibuf = IMB_dupImBuf(ibuf); + BKE_sequencer_imbuf_assign_spaces(context.scene, ibuf); + if (nr == 0) { BKE_sequencer_cache_put(context, seq, seq->start, SEQ_STRIPELEM_IBUF_STARTSTILL, ibuf); } @@ -2309,7 +2404,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float /* opengl offscreen render */ BKE_scene_update_for_newframe(context.bmain, scene, scene->lay); ibuf = sequencer_view3d_cb(scene, camera, context.rectx, context.recty, - IB_rect, context.scene->r.seq_prev_type, TRUE, err_out); + IB_rect, context.scene->r.seq_prev_type, TRUE, FALSE, err_out); if (ibuf == NULL) { fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out); } @@ -2341,7 +2436,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float /* float buffers in the sequencer are not linear */ ibuf->profile = IB_PROFILE_LINEAR_RGB; - IMB_colormanagement_imbuf_to_sequencer_space(ibuf, FALSE); + BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf, FALSE); } else if (rres.rect32) { ibuf = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect); @@ -2448,7 +2543,7 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo /* all sequencer color is done in SRGB space, linear gives odd crossfades */ if (ibuf->profile == IB_PROFILE_LINEAR_RGB) - IMB_colormanagement_imbuf_to_sequencer_space(ibuf, FALSE); + BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf, FALSE); copy_to_ibuf_still(context, seq, nr, ibuf); @@ -2496,6 +2591,7 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo case SEQ_TYPE_MOVIECLIP: { ibuf = seq_render_movieclip_strip(context, seq, nr); + BKE_sequencer_imbuf_assign_spaces(context.scene, ibuf); if (ibuf && use_preprocess) { ImBuf *i = IMB_dupImBuf(ibuf); @@ -2519,6 +2615,9 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo } } + if (ibuf) + BKE_sequencer_imbuf_assign_spaces(context.scene, ibuf); + return ibuf; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 65d29c1144b..115c14111a8 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7923,6 +7923,21 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + /* color management pipeline changes compatibility code */ + { + Scene *scene; + + for (scene = main->scene.first; scene; scene = scene->id.next) { + if ((scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) == 0) { + ColorManagedDisplaySettings *display_settings = &scene->display_settings; + + if (display_settings->display_device[0] == 0) { + BKE_scene_disable_color_management(scene); + } + } + } + } + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */ diff --git a/source/blender/compositor/COM_compositor.h b/source/blender/compositor/COM_compositor.h index f35bf71392c..a64583b68ff 100644 --- a/source/blender/compositor/COM_compositor.h +++ b/source/blender/compositor/COM_compositor.h @@ -24,6 +24,7 @@ extern "C" { #endif +#include "DNA_color_types.h" #include "DNA_node_types.h" /** @@ -299,8 +300,20 @@ extern "C" { * * - output nodes can have different priorities in the WorkScheduler. * This is implemented in the COM_execute function. + * + * @param viewSettings + * reference to view settings used for color management + * + * @param displaySettings + * reference to display settings used for color management + * + * OCIO_TODO: this options only used in rare cases, namely in output file node, + * so probably this settings could be passed in a nicer way. + * should be checked further, probably it'll be also needed for preview + * generation in display space */ -void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering); +void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering, + const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings); /** * @brief Deinitialize the compositor caches and allocated memory. diff --git a/source/blender/compositor/intern/COM_CompositorContext.cpp b/source/blender/compositor/intern/COM_CompositorContext.cpp index fbdb4cd6b28..e1cc25d028a 100644 --- a/source/blender/compositor/intern/COM_CompositorContext.cpp +++ b/source/blender/compositor/intern/COM_CompositorContext.cpp @@ -31,6 +31,8 @@ CompositorContext::CompositorContext() this->m_hasActiveOpenCLDevices = false; this->m_activegNode = NULL; this->m_fastCalculation = false; + this->m_viewSettings = NULL; + this->m_displaySettings = NULL; } const int CompositorContext::getFramenumber() const @@ -42,13 +44,3 @@ const int CompositorContext::getFramenumber() const return -1; /* this should never happen */ } } - -const int CompositorContext::isColorManaged() const -{ - if (this->m_rd) { - return this->m_rd->color_mgt_flag & R_COLOR_MANAGEMENT; - } - else { - return 0; /* this should never happen */ - } -} diff --git a/source/blender/compositor/intern/COM_CompositorContext.h b/source/blender/compositor/intern/COM_CompositorContext.h index 2f6abf39985..2f5e8c0648d 100644 --- a/source/blender/compositor/intern/COM_CompositorContext.h +++ b/source/blender/compositor/intern/COM_CompositorContext.h @@ -27,6 +27,7 @@ #include "BKE_text.h" #include #include "DNA_node_types.h" +#include "DNA_color_types.h" #include "BLI_rect.h" #include "DNA_scene_types.h" #include "COM_defines.h" @@ -79,6 +80,9 @@ private: */ bool m_fastCalculation; + /* @brief color management settings */ + const ColorManagedViewSettings *m_viewSettings; + const ColorManagedDisplaySettings *m_displaySettings; public: /** * @brief constructor initializes the context with default values. @@ -125,6 +129,26 @@ public: */ const RenderData *getRenderData() const { return this->m_rd; } + /** + * @brief set view settings of color color management + */ + void setViewSettings(const ColorManagedViewSettings *viewSettings) { this->m_viewSettings = viewSettings; } + + /** + * @brief get view settings of color color management + */ + const ColorManagedViewSettings *getViewSettings() const { return this->m_viewSettings; } + + /** + * @brief set display settings of color color management + */ + void setDisplaySettings(const ColorManagedDisplaySettings *displaySettings) { this->m_displaySettings = displaySettings; } + + /** + * @brief get display settings of color color management + */ + const ColorManagedDisplaySettings *getDisplaySettings() const { return this->m_displaySettings; } + /** * @brief set the quality */ @@ -152,8 +176,6 @@ public: int getChunksize() { return this->getbNodeTree()->chunksize; } - const int isColorManaged() const; - void setFastCalculation(bool fastCalculation) {this->m_fastCalculation = fastCalculation;} bool isFastCalculation() {return this->m_fastCalculation;} }; diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp index 801505e9d39..a13717c9d86 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp @@ -44,7 +44,8 @@ #include "MEM_guardedalloc.h" #endif -ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool rendering, bool fastcalculation) +ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool rendering, bool fastcalculation, + const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings) { this->m_context.setbNodeTree(editingtree); this->m_context.setFastCalculation(fastcalculation); @@ -69,6 +70,9 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re ExecutionSystemHelper::addbNodeTree(*this, 0, editingtree, NULL); this->m_context.setRenderData(rd); + this->m_context.setViewSettings(viewSettings); + this->m_context.setDisplaySettings(displaySettings); + this->convertToOperations(); this->groupOperations(); /* group operations in ExecutionGroups */ unsigned int index; diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.h b/source/blender/compositor/intern/COM_ExecutionSystem.h index 39e7bc80279..56a60bf7a03 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.h +++ b/source/blender/compositor/intern/COM_ExecutionSystem.h @@ -25,6 +25,7 @@ class ExecutionGroup; #ifndef _COM_ExecutionSystem_h #define _COM_ExecutionSystem_h +#include "DNA_color_types.h" #include "DNA_node_types.h" #include #include "COM_Node.h" @@ -156,7 +157,8 @@ public: * @param editingtree [bNodeTree *] * @param rendering [true false] */ - ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool rendering, bool fastcalculation); + ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool rendering, bool fastcalculation, + const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings); /** * Destructor diff --git a/source/blender/compositor/intern/COM_Node.cpp b/source/blender/compositor/intern/COM_Node.cpp index 50393d14f35..5922b0e6b08 100644 --- a/source/blender/compositor/intern/COM_Node.cpp +++ b/source/blender/compositor/intern/COM_Node.cpp @@ -75,12 +75,12 @@ void Node::addSetValueOperation(ExecutionSystem *graph, InputSocket *inputsocket graph->addOperation(operation); } -void Node::addPreviewOperation(ExecutionSystem *system, OutputSocket *outputSocket) +void Node::addPreviewOperation(ExecutionSystem *system, CompositorContext *context, OutputSocket *outputSocket) { if (this->isInActiveGroup()) { if (!(this->getbNode()->flag & NODE_HIDDEN)) { // do not calculate previews of hidden nodes. if (this->getbNode()->flag & NODE_PREVIEW) { - PreviewOperation *operation = new PreviewOperation(); + PreviewOperation *operation = new PreviewOperation(context->getViewSettings(), context->getDisplaySettings()); system->addOperation(operation); operation->setbNode(this->getbNode()); operation->setbNodeTree(system->getContext().getbNodeTree()); @@ -90,11 +90,11 @@ void Node::addPreviewOperation(ExecutionSystem *system, OutputSocket *outputSock } } -void Node::addPreviewOperation(ExecutionSystem *system, InputSocket *inputSocket) +void Node::addPreviewOperation(ExecutionSystem *system, CompositorContext *context, InputSocket *inputSocket) { if (inputSocket->isConnected() && this->isInActiveGroup()) { OutputSocket *outputsocket = inputSocket->getConnection()->getFromSocket(); - this->addPreviewOperation(system, outputsocket); + this->addPreviewOperation(system, context, outputsocket); } } diff --git a/source/blender/compositor/intern/COM_Node.h b/source/blender/compositor/intern/COM_Node.h index 7ce40e3cb34..bfccd069ad1 100644 --- a/source/blender/compositor/intern/COM_Node.h +++ b/source/blender/compositor/intern/COM_Node.h @@ -135,8 +135,8 @@ public: */ OutputSocket *findOutputSocketBybNodeSocket(bNodeSocket *socket); protected: - void addPreviewOperation(ExecutionSystem *system, InputSocket *inputSocket); - void addPreviewOperation(ExecutionSystem *system, OutputSocket *outputSocket); + void addPreviewOperation(ExecutionSystem *system, CompositorContext *context, InputSocket *inputSocket); + void addPreviewOperation(ExecutionSystem *system, CompositorContext *context, OutputSocket *outputSocket); bNodeSocket *getEditorInputSocket(int editorNodeInputSocketIndex); bNodeSocket *getEditorOutputSocket(int editorNodeOutputSocketIndex); diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp index cb9166c929d..5cfcd83f8f1 100644 --- a/source/blender/compositor/intern/COM_compositor.cpp +++ b/source/blender/compositor/intern/COM_compositor.cpp @@ -42,7 +42,9 @@ void intern_freeCompositorCaches() deintializeDistortionCache(); } -void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering) +void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering, + const ColorManagedViewSettings *viewSettings, + const ColorManagedDisplaySettings *displaySettings) { /* initialize mutex, TODO this mutex init is actually not thread safe and * should be done somewhere as part of blender startup, all the other @@ -71,7 +73,7 @@ void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering) bool twopass = (editingtree->flag & NTREE_TWO_PASS) > 0 && !rendering; /* initialize execution system */ if (twopass) { - ExecutionSystem *system = new ExecutionSystem(rd, editingtree, rendering, twopass); + ExecutionSystem *system = new ExecutionSystem(rd, editingtree, rendering, twopass, viewSettings, displaySettings); system->execute(); delete system; @@ -84,7 +86,7 @@ void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering) } - ExecutionSystem *system = new ExecutionSystem(rd, editingtree, rendering, false); + ExecutionSystem *system = new ExecutionSystem(rd, editingtree, rendering, false, viewSettings, displaySettings); system->execute(); delete system; diff --git a/source/blender/compositor/nodes/COM_BlurNode.cpp b/source/blender/compositor/nodes/COM_BlurNode.cpp index e39ef2b3f23..4f120ea5a6e 100644 --- a/source/blender/compositor/nodes/COM_BlurNode.cpp +++ b/source/blender/compositor/nodes/COM_BlurNode.cpp @@ -57,7 +57,7 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co this->getInputSocket(1)->relinkConnections(operationfgb->getInputSocket(1), 1, graph); this->getOutputSocket(0)->relinkConnections(operationfgb->getOutputSocket(0)); graph->addOperation(operationfgb); - addPreviewOperation(graph, operationfgb->getOutputSocket()); + addPreviewOperation(graph, context, operationfgb->getOutputSocket()); } else if (editorNode->custom1 & CMP_NODEFLAG_BLUR_VARIABLE_SIZE) { MathAddOperation *clamp = new MathAddOperation(); @@ -97,7 +97,7 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co addLink(graph, operationy->getOutputSocket(), operation->getInputSocket(1)); graph->addOperation(operation); this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); - addPreviewOperation(graph, operation->getOutputSocket()); + addPreviewOperation(graph, context, operation->getOutputSocket()); } else if (!data->bokeh) { GaussianXBlurOperation *operationx = new GaussianXBlurOperation(); @@ -115,7 +115,7 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co graph->addOperation(operationy); addLink(graph, operationx->getOutputSocket(), operationy->getInputSocket(0)); addLink(graph, operationx->getInputSocket(1)->getConnection()->getFromSocket(), operationy->getInputSocket(1)); - addPreviewOperation(graph, operationy->getOutputSocket()); + addPreviewOperation(graph, context, operationy->getOutputSocket()); if (!connectedSizeSocket) { operationx->setSize(size); @@ -131,7 +131,7 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co operation->setQuality(quality); graph->addOperation(operation); this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); - addPreviewOperation(graph, operation->getOutputSocket()); + addPreviewOperation(graph, context, operation->getOutputSocket()); if (!connectedSizeSocket) { operation->setSize(size); diff --git a/source/blender/compositor/nodes/COM_BokehImageNode.cpp b/source/blender/compositor/nodes/COM_BokehImageNode.cpp index f6abbbb9a9a..a89ed9e0c64 100644 --- a/source/blender/compositor/nodes/COM_BokehImageNode.cpp +++ b/source/blender/compositor/nodes/COM_BokehImageNode.cpp @@ -35,5 +35,5 @@ void BokehImageNode::convertToOperations(ExecutionSystem *graph, CompositorConte this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0)); graph->addOperation(operation); operation->setData((NodeBokehImage *)this->getbNode()->storage); - addPreviewOperation(graph, operation->getOutputSocket(0)); + addPreviewOperation(graph, context, operation->getOutputSocket(0)); } diff --git a/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp b/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp index eab921863e9..c1511ee611b 100644 --- a/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp @@ -84,7 +84,7 @@ void ChannelMatteNode::convertToOperations(ExecutionSystem *graph, CompositorCon graph->addOperation(operationAlpha); addLink(graph, operation->getOutputSocket(), operationAlpha->getInputSocket(1)); - addPreviewOperation(graph, operationAlpha->getOutputSocket()); + addPreviewOperation(graph, context, operationAlpha->getOutputSocket()); if (outputSocketImage->isConnected()) { outputSocketImage->relinkConnections(operationAlpha->getOutputSocket()); diff --git a/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp b/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp index 0fb09157351..4c4b77ba6cc 100644 --- a/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp @@ -65,7 +65,7 @@ void ChromaMatteNode::convertToOperations(ExecutionSystem *graph, CompositorCont addLink(graph, operation->getOutputSocket(), operationAlpha->getInputSocket(1)); graph->addOperation(operationAlpha); - addPreviewOperation(graph, operationAlpha->getOutputSocket()); + addPreviewOperation(graph, context, operationAlpha->getOutputSocket()); if (outputSocketImage->isConnected()) { outputSocketImage->relinkConnections(operationAlpha->getOutputSocket()); diff --git a/source/blender/compositor/nodes/COM_ColorMatteNode.cpp b/source/blender/compositor/nodes/COM_ColorMatteNode.cpp index 38ab6ba8da2..54e6762961b 100644 --- a/source/blender/compositor/nodes/COM_ColorMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_ColorMatteNode.cpp @@ -62,7 +62,7 @@ void ColorMatteNode::convertToOperations(ExecutionSystem *graph, CompositorConte addLink(graph, operationRGBToHSV_Image->getInputSocket(0)->getConnection()->getFromSocket(), operationAlpha->getInputSocket(0)); addLink(graph, operation->getOutputSocket(), operationAlpha->getInputSocket(1)); graph->addOperation(operationAlpha); - addPreviewOperation(graph, operationAlpha->getOutputSocket()); + addPreviewOperation(graph, context, operationAlpha->getOutputSocket()); if (outputSocketImage->isConnected()) { outputSocketImage->relinkConnections(operationAlpha->getOutputSocket()); diff --git a/source/blender/compositor/nodes/COM_CompositorNode.cpp b/source/blender/compositor/nodes/COM_CompositorNode.cpp index d0d66a81c77..e3313750e66 100644 --- a/source/blender/compositor/nodes/COM_CompositorNode.cpp +++ b/source/blender/compositor/nodes/COM_CompositorNode.cpp @@ -45,5 +45,5 @@ void CompositorNode::convertToOperations(ExecutionSystem *graph, CompositorConte alphaSocket->relinkConnections(compositorOperation->getInputSocket(1)); depthSocket->relinkConnections(compositorOperation->getInputSocket(2)); graph->addOperation(compositorOperation); - addPreviewOperation(graph, compositorOperation->getInputSocket(0)); + addPreviewOperation(graph, context, compositorOperation->getInputSocket(0)); } diff --git a/source/blender/compositor/nodes/COM_DespeckleNode.cpp b/source/blender/compositor/nodes/COM_DespeckleNode.cpp index 603ddcd1389..a97714c870e 100644 --- a/source/blender/compositor/nodes/COM_DespeckleNode.cpp +++ b/source/blender/compositor/nodes/COM_DespeckleNode.cpp @@ -44,7 +44,7 @@ void DespeckleNode::convertToOperations(ExecutionSystem *graph, CompositorContex inputImageSocket->relinkConnections(operation->getInputSocket(0), 1, graph); inputSocket->relinkConnections(operation->getInputSocket(1), 0, graph); outputSocket->relinkConnections(operation->getOutputSocket()); - addPreviewOperation(graph, operation->getOutputSocket(0)); + addPreviewOperation(graph, context, operation->getOutputSocket(0)); graph->addOperation(operation); } diff --git a/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp b/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp index 6dca049a6ae..b5ad07be319 100644 --- a/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp @@ -51,5 +51,5 @@ void DifferenceMatteNode::convertToOperations(ExecutionSystem *graph, Compositor addLink(graph, operationSet->getOutputSocket(), operation->getInputSocket(1)); outputSocketImage->relinkConnections(operation->getOutputSocket()); graph->addOperation(operation); - addPreviewOperation(graph, operation->getOutputSocket()); + addPreviewOperation(graph, context, operation->getOutputSocket()); } diff --git a/source/blender/compositor/nodes/COM_DilateErodeNode.cpp b/source/blender/compositor/nodes/COM_DilateErodeNode.cpp index cecc3bf6e86..5bd2f78d8a6 100644 --- a/source/blender/compositor/nodes/COM_DilateErodeNode.cpp +++ b/source/blender/compositor/nodes/COM_DilateErodeNode.cpp @@ -106,7 +106,7 @@ void DilateErodeNode::convertToOperations(ExecutionSystem *graph, CompositorCont graph->addOperation(operationy); addLink(graph, operationx->getOutputSocket(), operationy->getInputSocket(0)); // addLink(graph, operationx->getInputSocket(1)->getConnection()->getFromSocket(), operationy->getInputSocket(1)); // no size input yet - addPreviewOperation(graph, operationy->getOutputSocket()); + addPreviewOperation(graph, context, operationy->getOutputSocket()); /* TODO? */ /* see gaussian blue node for original usage */ diff --git a/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp b/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp index 87e7b9d0788..782c897f6fb 100644 --- a/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp @@ -77,7 +77,7 @@ void DistanceMatteNode::convertToOperations(ExecutionSystem *graph, CompositorCo addLink(graph, operation->getOutputSocket(), operationAlpha->getInputSocket(1)); graph->addOperation(operationAlpha); - addPreviewOperation(graph, operationAlpha->getOutputSocket()); + addPreviewOperation(graph, context, operationAlpha->getOutputSocket()); if (outputSocketImage->isConnected()) { outputSocketImage->relinkConnections(operationAlpha->getOutputSocket()); diff --git a/source/blender/compositor/nodes/COM_FilterNode.cpp b/source/blender/compositor/nodes/COM_FilterNode.cpp index 021ec6c2508..990cdb480ca 100644 --- a/source/blender/compositor/nodes/COM_FilterNode.cpp +++ b/source/blender/compositor/nodes/COM_FilterNode.cpp @@ -77,7 +77,7 @@ void FilterNode::convertToOperations(ExecutionSystem *graph, CompositorContext * inputImageSocket->relinkConnections(operation->getInputSocket(0), 1, graph); inputSocket->relinkConnections(operation->getInputSocket(1), 0, graph); outputSocket->relinkConnections(operation->getOutputSocket()); - addPreviewOperation(graph, operation->getOutputSocket(0)); + addPreviewOperation(graph, context, operation->getOutputSocket(0)); graph->addOperation(operation); } diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp index 2d13ffb82b6..4ebd28d710a 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.cpp +++ b/source/blender/compositor/nodes/COM_ImageNode.cpp @@ -111,7 +111,7 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c break; } if (index == 0 && operation) { - addPreviewOperation(graph, operation->getOutputSocket()); + addPreviewOperation(graph, context, operation->getOutputSocket()); } } } @@ -134,7 +134,7 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c operation->setImageUser(imageuser); operation->setFramenumber(framenumber); graph->addOperation(operation); - addPreviewOperation(graph, operation->getOutputSocket()); + addPreviewOperation(graph, context, operation->getOutputSocket()); } if (numberOfOutputs > 1) { diff --git a/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp b/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp index be949e2cacb..4656e00b006 100644 --- a/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp @@ -55,7 +55,7 @@ void LuminanceMatteNode::convertToOperations(ExecutionSystem *graph, CompositorC addLink(graph, rgbToYUV->getInputSocket(0)->getConnection()->getFromSocket(), operation->getInputSocket(0)); addLink(graph, operationSet->getOutputSocket(), operation->getInputSocket(1)); graph->addOperation(operation); - addPreviewOperation(graph, operation->getOutputSocket()); + addPreviewOperation(graph, context, operation->getOutputSocket()); if (outputSocketImage->isConnected()) { outputSocketImage->relinkConnections(operation->getOutputSocket()); diff --git a/source/blender/compositor/nodes/COM_MixNode.cpp b/source/blender/compositor/nodes/COM_MixNode.cpp index 7aeaaf56c98..ab4e464327d 100644 --- a/source/blender/compositor/nodes/COM_MixNode.cpp +++ b/source/blender/compositor/nodes/COM_MixNode.cpp @@ -128,7 +128,7 @@ void MixNode::convertToOperations(ExecutionSystem *graph, CompositorContext *con color1Socket->relinkConnections(convertProg->getInputSocket(1), 1, graph); color2Socket->relinkConnections(convertProg->getInputSocket(2), 2, graph); outputSocket->relinkConnections(convertProg->getOutputSocket(0)); - addPreviewOperation(graph, convertProg->getOutputSocket(0)); + addPreviewOperation(graph, context, convertProg->getOutputSocket(0)); convertProg->getInputSocket(2)->setResizeMode(color2Socket->getResizeMode()); diff --git a/source/blender/compositor/nodes/COM_MovieClipNode.cpp b/source/blender/compositor/nodes/COM_MovieClipNode.cpp index 6d5b9bba8aa..5d5e68fba37 100644 --- a/source/blender/compositor/nodes/COM_MovieClipNode.cpp +++ b/source/blender/compositor/nodes/COM_MovieClipNode.cpp @@ -62,25 +62,9 @@ void MovieClipNode::convertToOperations(ExecutionSystem *graph, CompositorContex // always connect the output image MovieClipOperation *operation = new MovieClipOperation(); - if (ibuf && context->isColorManaged() && ibuf->profile == IB_PROFILE_NONE) { - ConvertColorProfileOperation *converter = new ConvertColorProfileOperation(); - converter->setFromColorProfile(IB_PROFILE_LINEAR_RGB); - converter->setToColorProfile(IB_PROFILE_SRGB); - addLink(graph, operation->getOutputSocket(), converter->getInputSocket(0)); - addPreviewOperation(graph, converter->getOutputSocket()); - if (outputMovieClip->isConnected()) { - outputMovieClip->relinkConnections(converter->getOutputSocket()); - } - graph->addOperation(converter); - if (ibuf) { - converter->setPredivided(ibuf->flags & IB_cm_predivide); - } - } - else { - addPreviewOperation(graph, operation->getOutputSocket()); - if (outputMovieClip->isConnected()) { - outputMovieClip->relinkConnections(operation->getOutputSocket()); - } + addPreviewOperation(graph, context, operation->getOutputSocket()); + if (outputMovieClip->isConnected()) { + outputMovieClip->relinkConnections(operation->getOutputSocket()); } operation->setMovieClip(movieClip); diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.cpp b/source/blender/compositor/nodes/COM_OutputFileNode.cpp index b8cee29fee6..921b9e63a73 100644 --- a/source/blender/compositor/nodes/COM_OutputFileNode.cpp +++ b/source/blender/compositor/nodes/COM_OutputFileNode.cpp @@ -62,7 +62,7 @@ void OutputFileNode::convertToOperations(ExecutionSystem *graph, CompositorConte input->relinkConnections(outputOperation->getInputSocket(i)); } } - if (hasConnections) addPreviewOperation(graph, outputOperation->getInputSocket(0)); + if (hasConnections) addPreviewOperation(graph, context, outputOperation->getInputSocket(0)); graph->addOperation(outputOperation); } @@ -80,11 +80,12 @@ void OutputFileNode::convertToOperations(ExecutionSystem *graph, CompositorConte BLI_join_dirfile(path, FILE_MAX, storage->base_path, sockdata->path); OutputSingleLayerOperation *outputOperation = new OutputSingleLayerOperation( - context->getRenderData(), context->getbNodeTree(), input->getDataType(), format, path); + context->getRenderData(), context->getbNodeTree(), input->getDataType(), format, path, + context->getViewSettings(), context->getDisplaySettings()); input->relinkConnections(outputOperation->getInputSocket(0)); graph->addOperation(outputOperation); if (!previewAdded) { - addPreviewOperation(graph, outputOperation->getInputSocket(0)); + addPreviewOperation(graph, context, outputOperation->getInputSocket(0)); previewAdded = true; } } diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp index dfb46af841c..b57e99754d6 100644 --- a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp +++ b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp @@ -52,7 +52,7 @@ RenderLayersNode::RenderLayersNode(bNode *editorNode) : Node(editorNode) /* pass */ } -void RenderLayersNode::testSocketConnection(ExecutionSystem *system, int outputSocketNumber, RenderLayersBaseProg *operation) +void RenderLayersNode::testSocketConnection(ExecutionSystem *system, CompositorContext *context, int outputSocketNumber, RenderLayersBaseProg *operation) { OutputSocket *outputSocket = this->getOutputSocket(outputSocketNumber); Scene *scene = (Scene *)this->getbNode()->id; @@ -64,7 +64,7 @@ void RenderLayersNode::testSocketConnection(ExecutionSystem *system, int outputS outputSocket->relinkConnections(operation->getOutputSocket()); system->addOperation(operation); if (outputSocketNumber == 0) { // only do for image socket if connected - addPreviewOperation(system, operation->getOutputSocket()); + addPreviewOperation(system, context, operation->getOutputSocket()); } } else { @@ -72,7 +72,7 @@ void RenderLayersNode::testSocketConnection(ExecutionSystem *system, int outputS system->addOperation(operation); operation->setScene(scene); operation->setLayerId(layerId); - addPreviewOperation(system, operation->getOutputSocket()); + addPreviewOperation(system, context, operation->getOutputSocket()); } else { delete operation; @@ -82,34 +82,34 @@ void RenderLayersNode::testSocketConnection(ExecutionSystem *system, int outputS void RenderLayersNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) { - testSocketConnection(graph, 0, new RenderLayersColorProg()); - testSocketConnection(graph, 1, new RenderLayersAlphaProg()); - testSocketConnection(graph, 2, new RenderLayersDepthProg()); - testSocketConnection(graph, 3, new RenderLayersNormalOperation()); - testSocketConnection(graph, 4, new RenderLayersUVOperation()); - testSocketConnection(graph, 5, new RenderLayersSpeedOperation()); - testSocketConnection(graph, 6, new RenderLayersColorOperation()); - testSocketConnection(graph, 7, new RenderLayersDiffuseOperation()); - testSocketConnection(graph, 8, new RenderLayersSpecularOperation()); - testSocketConnection(graph, 9, new RenderLayersShadowOperation()); - testSocketConnection(graph, 10, new RenderLayersAOOperation()); - testSocketConnection(graph, 11, new RenderLayersReflectionOperation()); - testSocketConnection(graph, 12, new RenderLayersRefractionOperation()); - testSocketConnection(graph, 13, new RenderLayersIndirectOperation()); - testSocketConnection(graph, 14, new RenderLayersObjectIndexOperation()); - testSocketConnection(graph, 15, new RenderLayersMaterialIndexOperation()); - testSocketConnection(graph, 16, new RenderLayersMistOperation()); - testSocketConnection(graph, 17, new RenderLayersEmitOperation()); - testSocketConnection(graph, 18, new RenderLayersEnvironmentOperation()); + testSocketConnection(graph, context, 0, new RenderLayersColorProg()); + testSocketConnection(graph, context, 1, new RenderLayersAlphaProg()); + testSocketConnection(graph, context, 2, new RenderLayersDepthProg()); + testSocketConnection(graph, context, 3, new RenderLayersNormalOperation()); + testSocketConnection(graph, context, 4, new RenderLayersUVOperation()); + testSocketConnection(graph, context, 5, new RenderLayersSpeedOperation()); + testSocketConnection(graph, context, 6, new RenderLayersColorOperation()); + testSocketConnection(graph, context, 7, new RenderLayersDiffuseOperation()); + testSocketConnection(graph, context, 8, new RenderLayersSpecularOperation()); + testSocketConnection(graph, context, 9, new RenderLayersShadowOperation()); + testSocketConnection(graph, context, 10, new RenderLayersAOOperation()); + testSocketConnection(graph, context, 11, new RenderLayersReflectionOperation()); + testSocketConnection(graph, context, 12, new RenderLayersRefractionOperation()); + testSocketConnection(graph, context, 13, new RenderLayersIndirectOperation()); + testSocketConnection(graph, context, 14, new RenderLayersObjectIndexOperation()); + testSocketConnection(graph, context, 15, new RenderLayersMaterialIndexOperation()); + testSocketConnection(graph, context, 16, new RenderLayersMistOperation()); + testSocketConnection(graph, context, 17, new RenderLayersEmitOperation()); + testSocketConnection(graph, context, 18, new RenderLayersEnvironmentOperation()); // cycles passes - testSocketConnection(graph, 19, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_DIRECT)); - testSocketConnection(graph, 20, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_INDIRECT)); - testSocketConnection(graph, 21, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_COLOR)); - testSocketConnection(graph, 22, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_DIRECT)); - testSocketConnection(graph, 23, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_INDIRECT)); - testSocketConnection(graph, 24, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_COLOR)); - testSocketConnection(graph, 25, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_DIRECT)); - testSocketConnection(graph, 26, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_INDIRECT)); - testSocketConnection(graph, 27, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_COLOR)); + testSocketConnection(graph, context, 19, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_DIRECT)); + testSocketConnection(graph, context, 20, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_INDIRECT)); + testSocketConnection(graph, context, 21, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_COLOR)); + testSocketConnection(graph, context, 22, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_DIRECT)); + testSocketConnection(graph, context, 23, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_INDIRECT)); + testSocketConnection(graph, context, 24, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_COLOR)); + testSocketConnection(graph, context, 25, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_DIRECT)); + testSocketConnection(graph, context, 26, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_INDIRECT)); + testSocketConnection(graph, context, 27, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_COLOR)); } diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.h b/source/blender/compositor/nodes/COM_RenderLayersNode.h index 32672c8ba2d..9bd74624b0c 100644 --- a/source/blender/compositor/nodes/COM_RenderLayersNode.h +++ b/source/blender/compositor/nodes/COM_RenderLayersNode.h @@ -33,5 +33,5 @@ public: RenderLayersNode(bNode *editorNode); void convertToOperations(ExecutionSystem *graph, CompositorContext *context); private: - void testSocketConnection(ExecutionSystem *graph, int outputSocketNumber, RenderLayersBaseProg *operation); + void testSocketConnection(ExecutionSystem *graph, CompositorContext *context, int outputSocketNumber, RenderLayersBaseProg *operation); }; diff --git a/source/blender/compositor/nodes/COM_SplitViewerNode.cpp b/source/blender/compositor/nodes/COM_SplitViewerNode.cpp index 388466cee3c..37b888becca 100644 --- a/source/blender/compositor/nodes/COM_SplitViewerNode.cpp +++ b/source/blender/compositor/nodes/COM_SplitViewerNode.cpp @@ -39,13 +39,14 @@ void SplitViewerNode::convertToOperations(ExecutionSystem *graph, CompositorCont ImageUser *imageUser = (ImageUser *) this->getbNode()->storage; if (image1Socket->isConnected() && image2Socket->isConnected()) { SplitViewerOperation *splitViewerOperation = new SplitViewerOperation(); - splitViewerOperation->setColorManagement(context->getRenderData()->color_mgt_flag & R_COLOR_MANAGEMENT); - splitViewerOperation->setColorPredivide(context->getRenderData()->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE); splitViewerOperation->setImage(image); splitViewerOperation->setImageUser(imageUser); splitViewerOperation->setActive((this->getbNode()->flag & NODE_DO_OUTPUT) && this->isInActiveGroup()); splitViewerOperation->setSplitPercentage(this->getbNode()->custom1); + splitViewerOperation->setViewSettings(context->getViewSettings()); + splitViewerOperation->setDisplaySettings(context->getDisplaySettings()); + /* defaults - the viewer node has these options but not exposed for split view * we could use the split to define an area of interest on one axis at least */ splitViewerOperation->setChunkOrder(COM_ORDER_OF_CHUNKS_DEFAULT); @@ -55,7 +56,7 @@ void SplitViewerNode::convertToOperations(ExecutionSystem *graph, CompositorCont splitViewerOperation->setXSplit(!this->getbNode()->custom2); image1Socket->relinkConnections(splitViewerOperation->getInputSocket(0), 0, graph); image2Socket->relinkConnections(splitViewerOperation->getInputSocket(1), 1, graph); - addPreviewOperation(graph, splitViewerOperation->getInputSocket(0)); + addPreviewOperation(graph, context, splitViewerOperation->getInputSocket(0)); graph->addOperation(splitViewerOperation); } } diff --git a/source/blender/compositor/nodes/COM_TextureNode.cpp b/source/blender/compositor/nodes/COM_TextureNode.cpp index b035e0a392c..5b386a504e4 100644 --- a/source/blender/compositor/nodes/COM_TextureNode.cpp +++ b/source/blender/compositor/nodes/COM_TextureNode.cpp @@ -40,7 +40,7 @@ void TextureNode::convertToOperations(ExecutionSystem *system, CompositorContext operation->setTexture(texture); operation->setRenderData(context->getRenderData()); system->addOperation(operation); - addPreviewOperation(system, operation->getOutputSocket()); + addPreviewOperation(system, context, operation->getOutputSocket()); if (this->getOutputSocket(0)->isConnected()) { TextureAlphaOperation *alphaOperation = new TextureAlphaOperation(); diff --git a/source/blender/compositor/nodes/COM_ViewerNode.cpp b/source/blender/compositor/nodes/COM_ViewerNode.cpp index 88ce0ff2016..d67e9e274b0 100644 --- a/source/blender/compositor/nodes/COM_ViewerNode.cpp +++ b/source/blender/compositor/nodes/COM_ViewerNode.cpp @@ -40,8 +40,6 @@ void ViewerNode::convertToOperations(ExecutionSystem *graph, CompositorContext * ImageUser *imageUser = (ImageUser *) this->getbNode()->storage; bNode *editorNode = this->getbNode(); ViewerOperation *viewerOperation = new ViewerOperation(); - viewerOperation->setColorManagement(context->getRenderData()->color_mgt_flag & R_COLOR_MANAGEMENT); - viewerOperation->setColorPredivide(context->getRenderData()->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE); viewerOperation->setbNodeTree(context->getbNodeTree()); viewerOperation->setImage(image); viewerOperation->setImageUser(imageUser); @@ -50,6 +48,9 @@ void ViewerNode::convertToOperations(ExecutionSystem *graph, CompositorContext * viewerOperation->setCenterX(editorNode->custom3); viewerOperation->setCenterY(editorNode->custom4); + viewerOperation->setViewSettings(context->getViewSettings()); + viewerOperation->setDisplaySettings(context->getDisplaySettings()); + viewerOperation->setResolutionInputSocketIndex(0); if (!imageSocket->isConnected()) { @@ -62,5 +63,5 @@ void ViewerNode::convertToOperations(ExecutionSystem *graph, CompositorContext * alphaSocket->relinkConnections(viewerOperation->getInputSocket(1)); depthSocket->relinkConnections(viewerOperation->getInputSocket(2)); graph->addOperation(viewerOperation); - addPreviewOperation(graph, viewerOperation->getInputSocket(0)); + addPreviewOperation(graph, context, viewerOperation->getInputSocket(0)); } diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp index b72875ab2f9..21ecfdb5272 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.cpp +++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp @@ -31,9 +31,12 @@ #include "BKE_global.h" #include "BKE_main.h" +#include "DNA_color_types.h" + extern "C" { #include "MEM_guardedalloc.h" #include "IMB_imbuf.h" + #include "IMB_colormanagement.h" #include "IMB_imbuf_types.h" } @@ -91,7 +94,8 @@ static void write_buffer_rect(rcti *rect, const bNodeTree *tree, OutputSingleLayerOperation::OutputSingleLayerOperation( - const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path) + const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path, + const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings) { this->m_rd = rd; this->m_tree = tree; @@ -104,6 +108,9 @@ OutputSingleLayerOperation::OutputSingleLayerOperation( this->m_format = format; BLI_strncpy(this->m_path, path, sizeof(this->m_path)); + + this->m_viewSettings = viewSettings; + this->m_displaySettings = displaySettings; } void OutputSingleLayerOperation::initExecution() @@ -131,8 +138,7 @@ void OutputSingleLayerOperation::deinitExecution() ibuf->mall |= IB_rectfloat; ibuf->dither = this->m_rd->dither_intensity; - if (this->m_rd->color_mgt_flag & R_COLOR_MANAGEMENT) - ibuf->profile = IB_PROFILE_LINEAR_RGB; + IMB_display_buffer_to_imbuf_rect(ibuf, m_viewSettings, m_displaySettings); BKE_makepicstring(filename, this->m_path, bmain->name, this->m_rd->cfra, this->m_format->imtype, (this->m_rd->scemode & R_EXTENSION), true); diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.h b/source/blender/compositor/operations/COM_OutputFileOperation.h index 532242c97ce..69d1ad48ced 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.h +++ b/source/blender/compositor/operations/COM_OutputFileOperation.h @@ -28,6 +28,8 @@ #include "BLI_rect.h" #include "BLI_path_util.h" +#include "DNA_color_types.h" + #include "intern/openexr/openexr_multi.h" /* Writes the image to a single-layer file. */ @@ -43,8 +45,11 @@ private: DataType m_datatype; SocketReader *m_imageInput; + const ColorManagedViewSettings *m_viewSettings; + const ColorManagedDisplaySettings *m_displaySettings; public: - OutputSingleLayerOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path); + OutputSingleLayerOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path, + const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings); void executeRegion(rcti *rect, unsigned int tileNumber); bool isOutputOperation(bool rendering) const { return true; } diff --git a/source/blender/compositor/operations/COM_PreviewOperation.cpp b/source/blender/compositor/operations/COM_PreviewOperation.cpp index aff374cdded..6e58b277f66 100644 --- a/source/blender/compositor/operations/COM_PreviewOperation.cpp +++ b/source/blender/compositor/operations/COM_PreviewOperation.cpp @@ -35,16 +35,19 @@ extern "C" { #include "MEM_guardedalloc.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" + #include "IMB_colormanagement.h" } -PreviewOperation::PreviewOperation() : NodeOperation() +PreviewOperation::PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings) : NodeOperation() { this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); this->m_outputBuffer = NULL; this->m_input = NULL; this->m_divider = 1.0f; this->m_node = NULL; + this->m_viewSettings = viewSettings; + this->m_displaySettings = displaySettings; } void PreviewOperation::initExecution() @@ -82,6 +85,10 @@ void PreviewOperation::executeRegion(rcti *rect, unsigned int tileNumber) { int offset; float color[4]; + struct ColormanageProcessor *cm_processor; + + cm_processor = IMB_colormanagement_display_processor_new(this->m_viewSettings, this->m_displaySettings); + for (int y = rect->ymin; y < rect->ymax; y++) { offset = (y * getWidth() + rect->xmin) * 4; for (int x = rect->xmin; x < rect->xmax; x++) { @@ -93,11 +100,13 @@ void PreviewOperation::executeRegion(rcti *rect, unsigned int tileNumber) color[2] = 0.0f; color[3] = 1.0f; this->m_input->read(color, rx, ry, COM_PS_NEAREST); - linearrgb_to_srgb_v4(color, color); + IMB_colormanagement_processor_apply_v4(cm_processor, color); F4TOCHAR4(color, this->m_outputBuffer + offset); offset += 4; } } + + IMB_colormanagement_processor_free(cm_processor); } bool PreviewOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) { diff --git a/source/blender/compositor/operations/COM_PreviewOperation.h b/source/blender/compositor/operations/COM_PreviewOperation.h index ffd80ff27af..9e774d0e41b 100644 --- a/source/blender/compositor/operations/COM_PreviewOperation.h +++ b/source/blender/compositor/operations/COM_PreviewOperation.h @@ -24,6 +24,7 @@ #define _COM_PreviewOperation_h #include "COM_NodeOperation.h" #include "DNA_image_types.h" +#include "DNA_color_types.h" #include "BLI_rect.h" class PreviewOperation : public NodeOperation { @@ -37,8 +38,10 @@ protected: SocketReader *m_input; float m_divider; + const ColorManagedViewSettings *m_viewSettings; + const ColorManagedDisplaySettings *m_displaySettings; public: - PreviewOperation(); + PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings); bool isOutputOperation(bool rendering) const { return true; } void initExecution(); void deinitExecution(); diff --git a/source/blender/compositor/operations/COM_SplitViewerOperation.cpp b/source/blender/compositor/operations/COM_SplitViewerOperation.cpp index d59d1f9f10d..7325e32a863 100644 --- a/source/blender/compositor/operations/COM_SplitViewerOperation.cpp +++ b/source/blender/compositor/operations/COM_SplitViewerOperation.cpp @@ -62,7 +62,6 @@ void SplitViewerOperation::deinitExecution() void SplitViewerOperation::executeRegion(rcti *rect, unsigned int tileNumber) { float *buffer = this->m_outputBuffer; - unsigned char *bufferDisplay = this->m_outputBufferDisplay; if (!buffer) return; int x1 = rect->xmin; @@ -76,7 +75,6 @@ void SplitViewerOperation::executeRegion(rcti *rect, unsigned int tileNumber) for (y = y1; y < y2; y++) { for (x = x1; x < x2; x++) { bool image1; - float srgb[4]; image1 = this->m_xSplit ? x > perc : y > perc; if (image1) { this->m_image1Input->read(&(buffer[offset]), x, y, COM_PS_NEAREST); @@ -84,21 +82,7 @@ void SplitViewerOperation::executeRegion(rcti *rect, unsigned int tileNumber) else { this->m_image2Input->read(&(buffer[offset]), x, y, COM_PS_NEAREST); } - /// @todo: linear conversion only when scene color management is selected, also check predivide. - if (this->m_doColorManagement) { - if (this->m_doColorPredivide) { - linearrgb_to_srgb_predivide_v4(srgb, buffer + offset); - } - else { - linearrgb_to_srgb_v4(srgb, buffer + offset); - } - } - else { - copy_v4_v4(srgb, buffer + offset); - } - - rgba_float_to_uchar(bufferDisplay + offset, srgb); - + offset += 4; } offset += (this->getWidth() - (x2 - x1)) * 4; diff --git a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp index 1d913b96196..d9ca131721f 100644 --- a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp @@ -44,10 +44,10 @@ ViewerBaseOperation::ViewerBaseOperation() : NodeOperation() this->setImageUser(NULL); this->m_outputBuffer = NULL; this->m_depthBuffer = NULL; - this->m_outputBufferDisplay = NULL; this->m_active = false; - this->m_doColorManagement = true; this->m_doDepthBuffer = false; + this->m_viewSettings = NULL; + this->m_displaySettings = NULL; } void ViewerBaseOperation::initExecution() @@ -71,11 +71,10 @@ void ViewerBaseOperation::initImage() IMB_freezbuffloatImBuf(ibuf); ibuf->x = getWidth(); ibuf->y = getHeight(); - imb_addrectImBuf(ibuf); imb_addrectfloatImBuf(ibuf); anImage->ok = IMA_OK_LOADED; - IMB_display_buffer_invalidate(ibuf); + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; BLI_unlock_thread(LOCK_DRAW_IMAGE); } @@ -88,7 +87,6 @@ void ViewerBaseOperation::initImage() /* now we combine the input with ibuf */ this->m_outputBuffer = ibuf->rect_float; - this->m_outputBufferDisplay = (unsigned char *)ibuf->rect; /* needed for display buffer update * @@ -107,7 +105,8 @@ void ViewerBaseOperation::initImage() } void ViewerBaseOperation:: updateImage(rcti *rect) { - IMB_partial_display_buffer_update(this->m_ibuf, this->m_outputBuffer, getWidth(), 0, 0, + IMB_partial_display_buffer_update(this->m_ibuf, this->m_outputBuffer, NULL, getWidth(), 0, 0, + this->m_viewSettings, this->m_displaySettings, rect->xmin, rect->ymin, rect->xmax, rect->ymax); WM_main_add_notifier(NC_WINDOW | ND_DRAW, NULL); diff --git a/source/blender/compositor/operations/COM_ViewerBaseOperation.h b/source/blender/compositor/operations/COM_ViewerBaseOperation.h index 383f69b7cfc..f7d479eb3b8 100644 --- a/source/blender/compositor/operations/COM_ViewerBaseOperation.h +++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.h @@ -30,7 +30,6 @@ class ViewerBaseOperation : public NodeOperation { protected: float *m_outputBuffer; float *m_depthBuffer; - unsigned char *m_outputBufferDisplay; Image *m_image; ImageUser *m_imageUser; void *m_lock; @@ -38,11 +37,12 @@ protected: float m_centerX; float m_centerY; OrderOfChunks m_chunkOrder; - bool m_doColorManagement; - bool m_doColorPredivide; bool m_doDepthBuffer; ImBuf *m_ibuf; + const ColorManagedViewSettings *m_viewSettings; + const ColorManagedDisplaySettings *m_displaySettings; + public: bool isOutputOperation(bool rendering) const { return isActiveViewerOutput(); } void initExecution(); @@ -58,10 +58,10 @@ public: float getCenterY() { return this->m_centerY; } OrderOfChunks getChunkOrder() { return this->m_chunkOrder; } const CompositorPriority getRenderPriority() const; - void setColorManagement(bool doColorManagement) { this->m_doColorManagement = doColorManagement; } - void setColorPredivide(bool doColorPredivide) { this->m_doColorPredivide = doColorPredivide; } bool isViewerOperation() { return true; } - + + void setViewSettings(const ColorManagedViewSettings *viewSettings) { this->m_viewSettings = viewSettings; } + void setDisplaySettings(const ColorManagedDisplaySettings *displaySettings) { this->m_displaySettings = displaySettings; } protected: ViewerBaseOperation(); void updateImage(rcti *rect); diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cpp b/source/blender/compositor/operations/COM_ViewerOperation.cpp index b85b86bddc3..576d5da4d74 100644 --- a/source/blender/compositor/operations/COM_ViewerOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerOperation.cpp @@ -72,7 +72,6 @@ void ViewerOperation::executeRegion(rcti *rect, unsigned int tileNumber) { float *buffer = this->m_outputBuffer; float *depthbuffer = this->m_depthBuffer; - unsigned char *bufferDisplay = this->m_outputBufferDisplay; if (!buffer) return; const int x1 = rect->xmin; const int y1 = rect->ymin; @@ -82,7 +81,7 @@ void ViewerOperation::executeRegion(rcti *rect, unsigned int tileNumber) const int offsetadd4 = offsetadd * 4; int offset = (y1 * this->getWidth() + x1); int offset4 = offset * 4; - float alpha[4], srgb[4], depth[4]; + float alpha[4], depth[4]; int x; int y; bool breaked = false; @@ -98,19 +97,6 @@ void ViewerOperation::executeRegion(rcti *rect, unsigned int tileNumber) this->m_depthInput->read(depth, x, y, COM_PS_NEAREST); depthbuffer[offset] = depth[0]; } - if (this->m_doColorManagement) { - if (this->m_doColorPredivide) { - linearrgb_to_srgb_predivide_v4(srgb, buffer + offset4); - } - else { - linearrgb_to_srgb_v4(srgb, buffer + offset4); - } - } - else { - copy_v4_v4(srgb, buffer + offset4); - } - - rgba_float_to_uchar(bufferDisplay + offset4, srgb); offset ++; offset4 += 4; diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 7f40024a056..b1bccfa32c5 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -282,10 +282,12 @@ int ED_view3d_scene_layer_set(int lay, const int *values, int *active); int ED_view3d_context_activate(struct bContext *C); void ED_view3d_draw_offscreen(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, - int winx, int winy, float viewmat[][4], float winmat[][4], int do_bgpic); + int winx, int winy, float viewmat[][4], float winmat[][4], int do_bgpic, int colormanage_background); -struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, unsigned int flag, int draw_background, char err_out[256]); -struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Scene *scene, struct Object *camera, int width, int height, unsigned int flag, int drawtype, int draw_background, char err_out[256]); +struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, unsigned int flag, + int draw_background, int colormanage_background, char err_out[256]); +struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Scene *scene, struct Object *camera, int width, int height, unsigned int flag, int drawtype, + int draw_background, int colormanage_background, char err_out[256]); struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 718ed40cad9..a878632156f 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -75,6 +75,8 @@ #include "BPY_extern.h" +#include "IMB_colormanagement.h" + #include "interface_intern.h" #define MENU_WIDTH 120 @@ -2137,7 +2139,14 @@ uiBlock *uiBeginBlock(const bContext *C, ARegion *region, const char *name, shor block->evil_C = (void *)C; /* XXX */ if (scn) { - block->color_profile = (scn->r.color_mgt_flag & R_COLOR_MANAGEMENT); + block->color_profile = TRUE; + + /* store display device name, don't lookup for transformations yet + * block could be used for non-color displays where looking up for transformation + * would slow down redraw, so only lookup for actual transform when it's indeed + * needed + */ + block->display_device = scn->display_settings.display_device; /* copy to avoid crash when scene gets deleted with ui still open */ block->unit = MEM_mallocN(sizeof(scn->unit), "UI UnitSettings"); @@ -2574,6 +2583,25 @@ void ui_block_do_align(uiBlock *block) } } +struct ColorManagedDisplay *ui_block_display_get(uiBlock *block) +{ + return IMB_colormanagement_display_get_named(block->display_device); +} + +void ui_block_to_display_space_v3(uiBlock *block, float pixel[3]) +{ + struct ColorManagedDisplay *display = ui_block_display_get(block); + + IMB_colormanagement_scene_linear_to_display_v3(pixel, display); +} + +void ui_block_to_scene_linear_v3(uiBlock *block, float pixel[3]) +{ + struct ColorManagedDisplay *display = ui_block_display_get(block); + + IMB_colormanagement_display_to_scene_linear_v3(pixel, display); +} + /** * \brief ui_def_but is the function that draws many button types * diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 77dbbc878a7..f535c3c3e2a 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -48,6 +48,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "IMB_colormanagement.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -1110,10 +1111,14 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect) float v3[2], v1[2], v2[2], v1a[2], v2a[2]; int a; float pos, colf[4] = {0, 0, 0, 0}; /* initialize in case the colorband isn't valid */ - + struct ColorManagedDisplay *display = NULL; + coba = (ColorBand *)(but->editcoba ? but->editcoba : but->poin); if (coba == NULL) return; - + + if (but->block->color_profile) + display = ui_block_display_get(but->block); + x1 = rect->xmin; y1 = rect->ymin; sizex = rect->xmax - x1; @@ -1146,8 +1151,8 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect) for (a = 1; a <= sizex; a++) { pos = ((float)a) / (sizex - 1); do_colorband(coba, pos, colf); - if (but->block->color_profile != BLI_PR_NONE) - linearrgb_to_srgb_v3_v3(colf, colf); + if (display) + IMB_colormanagement_scene_linear_to_display_v3(colf, display); v1[0] = v2[0] = x1 + a; diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 17486edd07f..a1a6e34f7b4 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -3158,7 +3158,7 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, if (but->rnaprop) { if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) - color_profile = BLI_PR_NONE; + color_profile = FALSE; } ui_get_but_vectorf(but, rgb); @@ -3200,8 +3200,10 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, /* exception only for value strip - use the range set in but->min/max */ hsv[2] = y * (but->softmax - but->softmin) + but->softmin; - if (color_profile) + if (color_profile) { + /* OCIO_TODO: how to handle this situation? */ hsv[2] = srgb_to_linearrgb(hsv[2]); + } if (hsv[2] > but->softmax) hsv[2] = but->softmax; @@ -3229,7 +3231,7 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, wmNDOF if (but->rnaprop) { if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) - color_profile = BLI_PR_NONE; + color_profile = FALSE; } ui_get_but_vectorf(but, rgb); @@ -3263,8 +3265,10 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, wmNDOF /* exception only for value strip - use the range set in but->min/max */ hsv[2] += ndof->rx * sensitivity; - if (color_profile) + if (color_profile) { + /* OCIO_TODO: how to handle this situation? */ hsv[2] = srgb_to_linearrgb(hsv[2]); + } CLAMP(hsv[2], but->softmin, but->softmax); default: diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index a5e4fa5890f..6999f8e2325 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -342,7 +342,12 @@ struct uiBlock { struct UnitSettings *unit; /* unit system, used a lot for numeric buttons so include here rather then fetching through the scene every time. */ float _hsv[3]; /* XXX, only access via ui_block_hsv_get() */ + char color_profile; /* color profile for correcting linear colors for display */ + + char *display_device; /* display devide name used to display this block, + * used by color widgets to transform colors from/to scene linear + */ }; typedef struct uiSafetyRct { @@ -392,6 +397,10 @@ extern void ui_bounds_block(uiBlock *block); extern void ui_block_translate(uiBlock *block, int x, int y); extern void ui_block_do_align(uiBlock *block); +extern struct ColorManagedDisplay *ui_block_display_get(uiBlock *block); +void ui_block_to_display_space_v3(uiBlock *block, float pixel[3]); +void ui_block_to_scene_linear_v3(uiBlock *block, float pixel[3]); + /* interface_regions.c */ struct uiPopupBlockHandle { diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index e8b8959fd43..72779234bae 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -58,6 +58,8 @@ #include "UI_interface.h" +#include "IMB_colormanagement.h" + #include "interface_intern.h" #include "WM_api.h" @@ -75,7 +77,7 @@ /* ********************************************************** */ typedef struct Eyedropper { - short do_color_management; + struct ColorManagedDisplay *display; PointerRNA ptr; PropertyRNA *prop; @@ -89,8 +91,6 @@ typedef struct Eyedropper { static int eyedropper_init(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - const int color_manage = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT; - Eyedropper *eye; op->customdata = eye = MEM_callocN(sizeof(Eyedropper), "Eyedropper"); @@ -106,7 +106,12 @@ static int eyedropper_init(bContext *C, wmOperator *op) return FALSE; } - eye->do_color_management = (color_manage && RNA_property_subtype(eye->prop) == PROP_COLOR); + if (RNA_property_subtype(eye->prop) == PROP_COLOR) { + const char *display_device; + + display_device = scene->display_settings.display_device; + eye->display = IMB_colormanagement_display_get_named(display_device); + } return TRUE; } @@ -194,9 +199,10 @@ static void eyedropper_color_set(bContext *C, Eyedropper *eye, const float col[3 /* to maintain alpha */ RNA_property_float_get_array(&eye->ptr, eye->prop, col_conv); - /* convert from screen (srgb) space to linear rgb space */ - if (eye->do_color_management) { - srgb_to_linearrgb_v3_v3(col_conv, col); + /* convert from display space to linear rgb space */ + if (eye->display) { + copy_v3_v3(col_conv, col); + IMB_colormanagement_display_to_scene_linear_v3(col_conv, eye->display); } else { copy_v3_v3(col_conv, col); diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index bebc80cbfc3..ea0838cf7df 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -66,6 +66,8 @@ #include "ED_screen.h" +#include "IMB_colormanagement.h" + #include "interface_intern.h" #define MENU_SEPR_HEIGHT 6 @@ -1900,11 +1902,15 @@ static void ui_update_block_buts_rgb(uiBlock *block, const float rgb[3]) { uiBut *bt; float *hsv = ui_block_hsv_get(block); + struct ColorManagedDisplay *display = NULL; /* this is to keep the H and S value when V is equal to zero * and we are working in HSV mode, of course! */ rgb_to_hsv_compat_v(rgb, hsv); + + if (block->color_profile) + display = ui_block_display_get(block); /* this updates button strings, is hackish... but button pointers are on stack of caller function */ for (bt = block->buttons.first; bt; bt = bt->next) { @@ -1920,12 +1926,11 @@ static void ui_update_block_buts_rgb(uiBlock *block, const float rgb[3]) /* Hex code is assumed to be in sRGB space (coming from other applications, web, etc) */ - if (block->color_profile == BLI_PR_NONE) { - copy_v3_v3(rgb_gamma, rgb); - } - else { - /* make an sRGB version, for Hex code */ - linearrgb_to_srgb_v3_v3(rgb_gamma, rgb); + copy_v3_v3(rgb_gamma, rgb); + + if (display) { + /* make a display version, for Hex code */ + IMB_colormanagement_scene_linear_to_display_v3(rgb_gamma, display); } if (rgb_gamma[0] > 1.0f) rgb_gamma[0] = modf(rgb_gamma[0], &intpart); @@ -2004,9 +2009,9 @@ static void do_hex_rna_cb(bContext *UNUSED(C), void *bt1, void *hexcl) hex_to_rgb(hexcol, rgb, rgb + 1, rgb + 2); /* Hex code is assumed to be in sRGB space (coming from other applications, web, etc) */ - if (but->block->color_profile != BLI_PR_NONE) { + if (but->block->color_profile) { /* so we need to linearise it for Blender */ - srgb_to_linearrgb_v3_v3(rgb, rgb); + ui_block_to_scene_linear_v3(but->block, rgb); } ui_update_block_buts_rgb(but->block, rgb); @@ -2114,14 +2119,16 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper /* existence of profile means storage is in linear color space, with display correction */ /* XXX That tip message is not use anywhere! */ - if (block->color_profile == BLI_PR_NONE) { + if (!block->color_profile) { BLI_strncpy(tip, N_("Value in Display Color Space"), sizeof(tip)); copy_v3_v3(rgb_gamma, rgba); } else { BLI_strncpy(tip, N_("Value in Linear RGB Color Space"), sizeof(tip)); - /* make an sRGB version, for Hex code */ - linearrgb_to_srgb_v3_v3(rgb_gamma, rgba); + + /* make a display version, for Hex code */ + copy_v3_v3(rgb_gamma, rgba); + ui_block_to_display_space_v3(block, rgb_gamma); } /* sneaky way to check for alpha */ @@ -2246,7 +2253,7 @@ uiBlock *ui_block_func_COL(bContext *C, uiPopupBlockHandle *handle, void *arg_bu if (but->rnaprop) { if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) { - block->color_profile = BLI_PR_NONE; + block->color_profile = FALSE; } } diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 9131c2744cd..522c567e27f 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1872,7 +1872,7 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, rcti *rect) int color_profile = but->block->color_profile; if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) - color_profile = BLI_PR_NONE; + color_profile = FALSE; radstep = 2.0f * (float)M_PI / (float)tot; centx = BLI_RCT_CENTER_X_FL(rect); @@ -1894,8 +1894,10 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, rcti *rect) * Useful for color correction tools where you're only interested in hue. */ if (but->flag & UI_BUT_COLOR_LOCK) hsv[2] = 1.f; - else if (color_profile) + else if (color_profile) { + /* OCIO_TODO: how to handle this situation? */ hsv[2] = linearrgb_to_srgb(hsv[2]); + } hsv_to_rgb(0.f, 0.f, hsv[2], colcent, colcent + 1, colcent + 2); @@ -2137,14 +2139,16 @@ static void ui_draw_but_HSV_v(uiBut *but, rcti *rect) int color_profile = but->block->color_profile; if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) - color_profile = BLI_PR_NONE; + color_profile = FALSE; ui_get_but_vectorf(but, rgb); rgb_to_hsv_v(rgb, hsv); v = hsv[2]; - if (color_profile) + if (color_profile) { + /* OCIO_TODO: how to handle this situation? */ v = linearrgb_to_srgb(v); + } /* map v from property range to [0,1] */ range = but->softmax - but->softmin; @@ -2529,7 +2533,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat if (but->rnaprop) { if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) - color_profile = BLI_PR_NONE; + color_profile = FALSE; if (RNA_property_array_length(&but->rnapoin, but->rnaprop) == 4) { col[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3); @@ -2557,7 +2561,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat } if (color_profile) - linearrgb_to_srgb_v3_v3(col, col); + ui_block_to_display_space_v3(but->block, col); rgba_float_to_uchar((unsigned char *)wcol->inner, col); diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index 59cc782f3eb..f9b01a56b95 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -69,6 +69,7 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "IMB_colormanagement.h" #include "GPU_draw.h" /* GPU_free_image */ @@ -685,7 +686,7 @@ static void apply_heights_data(void *bake_data) } } - ibuf->userflags = IB_RECT_INVALID; + ibuf->userflags = IB_RECT_INVALID | IB_DISPLAY_BUFFER_INVALID; } static void free_heights_data(void *bake_data) @@ -769,6 +770,8 @@ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, char *rrgb = (char *)ibuf->rect + pixel * 4; rrgb[3] = 255; } + + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; } /* MultiresBake callback for normals' baking @@ -826,6 +829,8 @@ static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, rgb_float_to_uchar(rrgb, vec); rrgb[3] = 255; } + + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; } static void count_images(MultiresBakeRender *bkr) @@ -895,7 +900,7 @@ static void finish_images(MultiresBakeRender *bkr) RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, bkr->bake_filter); - ibuf->userflags |= IB_BITMAPDIRTY; + ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID;; if (ibuf->rect_float) ibuf->userflags |= IB_RECT_INVALID; @@ -1366,6 +1371,7 @@ static void finish_bake_internal(BakeRender *bkr) ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); if (ibuf) { if (ibuf->userflags & IB_BITMAPDIRTY) { + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; GPU_free_image(ima); imb_freemipmapImBuf(ibuf); } diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 04a43c4611f..ebacac917e8 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -79,7 +79,7 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat { float *rectf = NULL; int ymin, ymax, xmin, xmax; - int rymin, rxmin, predivide, profile_from; + int rymin, rxmin; unsigned char *rectc; /* if renrect argument, we only refresh scanlines */ @@ -139,20 +139,8 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat rectf += 4 * (rr->rectx * ymin + xmin); rectc = (unsigned char *)(ibuf->rect + ibuf->x * rymin + rxmin); - if (scene && (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)) { - profile_from = IB_PROFILE_LINEAR_RGB; - predivide = (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE); - } - else { - profile_from = IB_PROFILE_SRGB; - predivide = 0; - } - - IMB_buffer_byte_from_float(rectc, rectf, - 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide, - xmax, ymax, ibuf->x, rr->rectx); - - IMB_partial_display_buffer_update(ibuf, rectf, rr->rectx, rxmin, rymin, + IMB_partial_display_buffer_update(ibuf, rectf, NULL, rr->rectx, rxmin, rymin, + &scene->view_settings, &scene->display_settings, rxmin, rymin, rxmin + xmax, rymin + ymax); } diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 55df1caf3eb..3217acaef16 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -63,6 +63,7 @@ #include "RE_pipeline.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "IMB_colormanagement.h" #include "RNA_access.h" #include "RNA_define.h" @@ -181,7 +182,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) } if ((scene->r.mode & R_OSA) == 0) { - ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE, FALSE); GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, rr->rectf); } else { @@ -195,7 +196,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) BLI_jitter_init(jit_ofs[0], scene->r.osa); /* first sample buffer, also initializes 'rv3d->persmat' */ - ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE, FALSE); GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, accum_buffer); /* skip the first sample */ @@ -205,7 +206,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) (jit_ofs[j][0] * 2.0f) / sizex, (jit_ofs[j][1] * 2.0f) / sizey); - ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, TRUE); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, TRUE, FALSE); GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, accum_tmp); add_vn_vn(accum_buffer, accum_tmp, sizex * sizey * sizeof(float)); } @@ -221,7 +222,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) else { /* shouldnt suddenly give errors mid-render but possible */ char err_out[256] = "unknown"; - ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey, IB_rectfloat, OB_SOLID, TRUE, err_out); + ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey, IB_rectfloat, OB_SOLID, TRUE, FALSE, err_out); camera = scene->camera; if (ibuf_view) { @@ -241,18 +242,14 @@ static void screen_opengl_render_apply(OGLRender *oglrender) /* note on color management: * * OpenGL renders into sRGB colors, but render buffers are expected to be - * linear if color management is enabled. So we convert to linear here, so - * the conversion back to bytes using the color management flag can make it - * sRGB again, and so that e.g. openexr saving also saves the correct linear - * float buffer. */ + * linear So we convert to linear here, so the conversion back to bytes can make it + * sRGB (or other display space) again, and so that e.g. openexr saving also saves the + * correct linear float buffer. + */ - if (oglrender->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) { - int predivide = 0; /* no alpha */ - - IMB_buffer_float_from_float(rr->rectf, rr->rectf, - 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide, - oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex); - } + IMB_buffer_float_from_float(rr->rectf, rr->rectf, + 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, FALSE, + oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex); RE_ReleaseResult(oglrender->re); @@ -536,12 +533,28 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock); if (ibuf) { + int needs_free = FALSE; + + if (is_movie || !BKE_imtype_supports_float(scene->r.im_format.imtype)) { + ImBuf *colormanage_ibuf = IMB_dupImBuf(ibuf); + + IMB_display_buffer_to_imbuf_rect(colormanage_ibuf, &scene->view_settings, &scene->display_settings); + imb_freerectfloatImBuf(colormanage_ibuf); + + // IMB_freeImBuf(ibuf); /* owned by the image */ + ibuf = colormanage_ibuf; + needs_free = TRUE; + } + /* color -> grayscale */ /* editing directly would alter the render view */ if (scene->r.im_format.planes == R_IMF_PLANES_BW) { - ImBuf *ibuf_bw = IMB_dupImBuf(ibuf); + ImBuf *ibuf_bw = IMB_dupImBuf(ibuf); IMB_color_to_bw(ibuf_bw); - // IMB_freeImBuf(ibuf); /* owned by the image */ + + if (needs_free) + IMB_freeImBuf(ibuf); + ibuf = ibuf_bw; } else { @@ -551,6 +564,13 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) ibuf_cpy->rect = ibuf->rect; ibuf_cpy->rect_float = ibuf->rect_float; ibuf_cpy->zbuf_float = ibuf->zbuf_float; + + if (needs_free) { + ibuf_cpy->mall = ibuf->mall; + ibuf->mall = 0; + IMB_freeImBuf(ibuf); + } + ibuf = ibuf_cpy; } diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 068a7aaa50a..38117aae4c5 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -64,6 +64,7 @@ #include "BKE_brush.h" #include "BKE_context.h" +#include "BKE_colortools.h" #include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_idprop.h" @@ -75,11 +76,13 @@ #include "BKE_material.h" #include "BKE_node.h" #include "BKE_object.h" +#include "BKE_scene.h" #include "BKE_texture.h" #include "BKE_world.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "IMB_colormanagement.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -254,6 +257,10 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre } sce->r.color_mgt_flag = scene->r.color_mgt_flag; + BKE_color_managed_display_settings_copy(&sce->display_settings, &scene->display_settings); + + BKE_color_managed_view_settings_free(&sce->view_settings); + BKE_color_managed_view_settings_copy(&sce->view_settings, &scene->view_settings); /* prevent overhead for small renders and icons (32) */ if (id && sp->sizex < 40) @@ -263,7 +270,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre /* exception: don't color manage texture previews or icons */ if ((id && sp->pr_method == PR_ICON_RENDER) || id_type == ID_TE) - sce->r.color_mgt_flag &= ~R_COLOR_MANAGEMENT; + BKE_scene_disable_color_management(sce); if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO) sce->r.alphamode = R_ALPHAPREMUL; @@ -481,7 +488,7 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int if (id && GS(id->name) != ID_TE) { /* exception: don't color manage texture previews - show the raw values */ if (sce) { - do_gamma_correct = sce->r.color_mgt_flag & R_COLOR_MANAGEMENT; + do_gamma_correct = TRUE; do_predivide = sce->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE; } } @@ -514,15 +521,25 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int /* temporary conversion to byte for drawing */ float fx = rect->xmin + offx; float fy = rect->ymin; - int profile_from = (do_gamma_correct) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB; int dither = 0; unsigned char *rect_byte; rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect"); - IMB_buffer_byte_from_float(rect_byte, rres.rectf, - 4, dither, IB_PROFILE_SRGB, profile_from, do_predivide, - rres.rectx, rres.recty, rres.rectx, rres.rectx); + if (do_gamma_correct) { + IMB_display_buffer_transform_apply(rect_byte, rres.rectf, rres.rectx, rres.recty, 4, + &sce->view_settings, &sce->display_settings, do_predivide); + + } + else { + /* OCIO_TODO: currently seems an exception for textures, + * but is it indeed expected behavior, or textures should be + * color managed as well? + */ + IMB_buffer_byte_from_float(rect_byte, rres.rectf, + 4, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, do_predivide, + rres.rectx, rres.recty, rres.rectx, rres.rectx); + } glaDrawPixelsSafe(fx, fy, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect_byte); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 9fc60fff913..adb1829703c 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -141,7 +141,7 @@ #define IMAPAINT_TILE_SIZE (1 << IMAPAINT_TILE_BITS) #define IMAPAINT_TILE_NUMBER(size) (((size) + IMAPAINT_TILE_SIZE - 1) >> IMAPAINT_TILE_BITS) -static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint); +static void imapaint_image_update(Scene *scene, SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint); typedef struct ImagePaintState { @@ -512,7 +512,7 @@ static void image_undo_restore(bContext *C, ListBase *lb) ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */ if (ibuf->mipmap[0]) ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */ - + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; } IMB_freeImBuf(tmpibuf); @@ -3595,7 +3595,7 @@ static int project_image_refresh_tagged(ProjPaintState *ps) pr = &(projIma->partRedrawRect[i]); if (pr->x2 != -1) { /* TODO - use 'enabled' ? */ imapaintpartial = *pr; - imapaint_image_update(NULL, projIma->ima, projIma->ibuf, 1); /*last 1 is for texpaint*/ + imapaint_image_update(NULL, NULL, projIma->ima, projIma->ibuf, 1); /*last 1 is for texpaint*/ redraw = 1; } } @@ -4224,13 +4224,17 @@ static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, IMB_freeImBuf(tmpibuf); } -static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint) +static void imapaint_image_update(Scene *scene, SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint) { - if (ibuf->rect_float) { - IMB_partial_display_buffer_update(ibuf, ibuf->rect_float, ibuf->x, 0, 0, + if (scene) { + IMB_partial_display_buffer_update(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect, ibuf->x, 0, 0, + &scene->view_settings, &scene->display_settings, imapaintpartial.x1, imapaintpartial.y1, imapaintpartial.x2, imapaintpartial.y2); } + else { + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + } if (ibuf->mipmap[0]) ibuf->userflags |= IB_MIPMAP_INVALID; @@ -4592,7 +4596,7 @@ static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, ibuf->profile == IB_PROFILE_LINEAR_RGB)) { if (update) - imapaint_image_update(s->sima, image, ibuf, texpaint); + imapaint_image_update(s->scene, s->sima, image, ibuf, texpaint); return 1; } else return 0; @@ -5867,7 +5871,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) if (w > maxsize) w = maxsize; if (h > maxsize) h = maxsize; - ibuf = ED_view3d_draw_offscreen_imbuf(CTX_data_scene(C), CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, FALSE, err_out); + ibuf = ED_view3d_draw_offscreen_imbuf(CTX_data_scene(C), CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, FALSE, FALSE, err_out); if (!ibuf) { /* Mostly happens when OpenGL offscreen buffer was failed to create, */ /* but could be other reasons. Should be handled in the future. nazgul */ diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 90c6a5ef509..0b937e3054b 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -193,6 +193,7 @@ void image_preview_event(int event) } if (exec && G.scene->nodetree) { + Scene *scene = G.scene; /* should work when no node editor in screen..., so we execute right away */ ntreeCompositTagGenerators(G.scene->nodetree); @@ -203,7 +204,7 @@ void image_preview_event(int event) BIF_store_spare(); - ntreeCompositExecTree(G.scene->nodetree, &G.scene->r, 1); /* 1 is do_previews */ + ntreeCompositExecTree(scene->nodetree, &scene->r, 1, &scene->view_settings, &scene->display_settings); /* 1 is do_previews */ G.scene->nodetree->timecursor = NULL; G.scene->nodetree->test_break = NULL; @@ -689,13 +690,10 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char } } - if (ima->source != IMA_SRC_GENERATED) { - /* OCIO_TODO: color space transformation for byte images is not implemented yet */ - if (ibuf && ibuf->rect_float) { - col = uiLayoutColumn(layout, FALSE); - uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings"); - } + col = uiLayoutColumn(layout, FALSE); + uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings"); + if (ima->source != IMA_SRC_GENERATED) { if (compact == 0) { /* background image view doesnt need these */ uiItemS(layout); diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 512921262f0..7603ba63980 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -195,7 +195,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int channel if (color_manage && channels == 4) { float pixel[4]; - IMB_display_buffer_pixel(pixel, fp, &scene->view_settings, &scene->display_settings); + IMB_colormanagement_pixel_to_display_space_v4(pixel, fp, &scene->view_settings, &scene->display_settings); BLI_snprintf(str, sizeof(str), " | CM R:%-.4f G:%-.4f B:%-.4f", pixel[0], pixel[1], pixel[2]); BLF_position(blf_mono_font, dx, 6, 0); @@ -245,7 +245,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int channel } if (color_manage) { - IMB_display_buffer_pixel(finalcol, col, &scene->view_settings, &scene->display_settings); + IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, &scene->view_settings, &scene->display_settings); } else { copy_v4_v4(finalcol, col); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 05b5d5b0066..f9ab458d26b 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1649,8 +1649,10 @@ static int image_new_exec(bContext *C, wmOperator *op) RNA_float_get_array(op->ptr, "color", color); alpha = RNA_boolean_get(op->ptr, "alpha"); - if (!floatbuf && scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) + if (!floatbuf) { + /* OCIO_TODO: perhaps we need to convert to display space, not just to sRGB */ linearrgb_to_srgb_v3_v3(color, color); + } if (!alpha) color[3] = 1.0f; @@ -2263,7 +2265,7 @@ static int image_sample_line_exec(bContext *C, wmOperator *op) hist->co[1][0] = x2f; hist->co[1][1] = y2f; - BKE_histogram_update_sample_line(hist, ibuf, (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) != 0); + BKE_histogram_update_sample_line(hist, ibuf, &scene->view_settings, &scene->display_settings); /* reset y zoom */ hist->ymax = 1.0f; @@ -2358,7 +2360,8 @@ static int image_record_composite_apply(bContext *C, wmOperator *op) BKE_image_all_free_anim_ibufs(scene->r.cfra); ntreeCompositTagAnimated(scene->nodetree); - ntreeCompositExecTree(scene->nodetree, &scene->r, 0, scene->r.cfra != rcd->old_cfra); /* 1 is no previews */ + ntreeCompositExecTree(scene->nodetree, &scene->r, 0, scene->r.cfra != rcd->old_cfra, + &scene->view_settings, &scene->display_settings); /* 1 is no previews */ ED_area_tag_redraw(CTX_wm_area(C)); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 970f9d6d35d..d9b92579324 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -770,9 +770,9 @@ static void image_scope_area_draw(const bContext *C, ARegion *ar) 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->r.color_mgt_flag & R_COLOR_MANAGEMENT); + BKE_histogram_update_sample_line(&sima->sample_line_hist, ibuf, &scene->view_settings, &scene->display_settings); } - scopes_update(&sima->scopes, ibuf, scene->r.color_mgt_flag & R_COLOR_MANAGEMENT); + scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings); } ED_space_image_release_buffer(sima, lock); diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 9e04bd36a1f..cc386da2e93 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -148,8 +148,9 @@ static void compo_startjob(void *cjv, short *stop, short *do_update, float *prog { CompoJob *cj = cjv; bNodeTree *ntree = cj->localtree; + Scene *scene = cj->scene; - if (cj->scene->use_nodes == FALSE) + if (scene->use_nodes == FALSE) return; cj->stop = stop; @@ -165,7 +166,7 @@ static void compo_startjob(void *cjv, short *stop, short *do_update, float *prog // XXX BIF_store_spare(); - ntreeCompositExecTree(ntree, &cj->scene->r, 0, 1); /* 1 is do_previews */ + ntreeCompositExecTree(ntree, &cj->scene->r, 0, 1, &scene->view_settings, &scene->display_settings); /* 1 is do_previews */ ntree->test_break = NULL; ntree->stats_draw = NULL; diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index bb8242866bb..af9ef34c2f2 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -146,7 +146,7 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->colfp = info->colf; /* sequencer's image buffers are in non-linear space, need to make them linear */ - IMB_colormanagement_pixel_from_sequencer_space(info->colf); + BKE_sequencer_pixel_from_sequencer_space_v4(scene, info->colf); info->color_manage = TRUE; } diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index da93e07748a..2e542737494 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -372,7 +372,15 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O Gtexdraw.ob = ob; Gtexdraw.is_tex = is_tex; - Gtexdraw.color_profile = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT; + + /* OCIO_TODO: for now assume OpenGL is always doing color management and working in sRGB space + * supporting for real display conversion could be nice here, but it's a bit challenging + * since all the shaders should be aware of such a transform + * perhaps this flag could be completely removed before release in separated commit and + * be re-implemented if real display transform would be needed + */ + Gtexdraw.color_profile = TRUE; + memcpy(Gtexdraw.obcol, obcol, sizeof(obcol)); set_draw_settings_cached(1, NULL, NULL, Gtexdraw); glShadeModel(GL_SMOOTH); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 3f8a69fcc93..5fbf1971349 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -69,6 +69,7 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "IMB_colormanagement.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -2375,7 +2376,7 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d) mult_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat); invert_m4_m4(rv3d.persinv, rv3d.viewinv); - ED_view3d_draw_offscreen(scene, v3d, &ar, winsize, winsize, viewmat, winmat, FALSE); + ED_view3d_draw_offscreen(scene, v3d, &ar, winsize, winsize, viewmat, winmat, FALSE, FALSE); GPU_lamp_shadow_buffer_unbind(shadow->lamp); v3d->drawtype = drawtype; @@ -2514,7 +2515,7 @@ static void view3d_main_area_setup_view(Scene *scene, View3D *v3d, ARegion *ar, void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy, float viewmat[][4], float winmat[][4], - int do_bgpic) + int do_bgpic, int colormanage_background) { RegionView3D *rv3d = ar->regiondata; Base *base; @@ -2553,10 +2554,25 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, /* set background color, fallback on the view background color * (if active clip is set but frame is failed to load fallback to horizon color as background) */ if (scene->world) { - if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) + /* NOTE: currently OpenGL is supposed to always work in sRGB space and do not + * apply any tonemaps since it's really tricky to support for all features (GLSL, textures, etc) + * but due to compatibility issues background is being affected display transform, so we can + * emulate behavior of disabled colro management + * but this function is also used for sequencer's scene strips which shouldn't be affected by + * tonemaps now and should be purely sRGB, that's why we've got this colormanage_background + * we can drop this flag in cost of some compatibility loss -- background wouldn't be + * color managed in 3d viewport + * same goes to opengl rendering, where color profile should be applied as very final step + */ + + if (colormanage_background) { + IMB_colormanagement_pixel_to_display_space_v3(backcol, &scene->world->horr, &scene->view_settings, + &scene->display_settings); + } + else { linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr); - else - copy_v3_v3(backcol, &scene->world->horr); + } + glClearColor(backcol[0], backcol[1], backcol[2], 0.0); } else { @@ -2661,7 +2677,8 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, /* utility func for ED_view3d_draw_offscreen */ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, - int sizex, int sizey, unsigned int flag, int draw_background, char err_out[256]) + int sizex, int sizey, unsigned int flag, int draw_background, + int colormanage_background, char err_out[256]) { RegionView3D *rv3d = ar->regiondata; ImBuf *ibuf; @@ -2686,10 +2703,10 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, BKE_camera_params_compute_viewplane(¶ms, sizex, sizey, scene->r.xasp, scene->r.yasp); BKE_camera_params_compute_matrix(¶ms); - ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, params.winmat, draw_background); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, params.winmat, draw_background, colormanage_background); } else { - ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background, colormanage_background); } /* read in pixels & stamp */ @@ -2714,7 +2731,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, /* creates own 3d views, used by the sequencer */ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int width, int height, - unsigned int flag, int drawtype, int draw_background, char err_out[256]) + unsigned int flag, int drawtype, int draw_background, + int colormanage_background, char err_out[256]) { View3D v3d = {NULL}; ARegion ar = {NULL}; @@ -2753,7 +2771,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int w mult_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat); invert_m4_m4(rv3d.persinv, rv3d.viewinv); - return ED_view3d_draw_offscreen_imbuf(scene, &v3d, &ar, width, height, flag, draw_background, err_out); + return ED_view3d_draw_offscreen_imbuf(scene, &v3d, &ar, width, height, flag, + draw_background, colormanage_background, err_out); // seq_view3d_cb(scene, cfra, render_size, seqrectx, seqrecty); } @@ -2936,10 +2955,9 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const /* clear background */ if ((v3d->flag2 & V3D_RENDER_OVERRIDE) && scene->world) { - if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) - linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr); - else - copy_v3_v3(backcol, &scene->world->horr); + IMB_colormanagement_pixel_to_display_space_v3(backcol, &scene->world->horr, &scene->view_settings, + &scene->display_settings); + glClearColor(backcol[0], backcol[1], backcol[2], 0.0); } else diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 4314a784511..95e2889f23c 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -1197,7 +1197,12 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O GPUMaterial *gpumat; GPUBlendMode alphablend; int a; - int gamma = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT; + + /* OCIO_TODO: assume color management is always enabled. could be nice to support real display transform here, + * but that's not so important and could be done later + */ + int gamma = TRUE; + int new_shading_nodes = BKE_scene_use_new_shading_nodes(scene); /* initialize state */ diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 61be4057843..dd92b561235 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -389,8 +389,12 @@ void gpu_material_add_node(GPUMaterial *material, GPUNode *node) int GPU_material_do_color_management(GPUMaterial *mat) { - return ((mat->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) && - !((mat->scene->gm.flag & GAME_GLSL_NO_COLOR_MANAGEMENT))); + /* OCIO_TODO: for now assume scene always does color management. probably could be + * improved in the future to support real display transform + * also probably we'll need to get rid ofgame engine's color management flag + */ + + return !((mat->scene->gm.flag & GAME_GLSL_NO_COLOR_MANAGEMENT)); } static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **lv, GPUNodeLink **dist) diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 2df67b6912c..0dc826439c4 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -37,6 +37,7 @@ struct bContext; struct ColorManagedColorspaceSettings; struct ColorManagedDisplaySettings; struct ColorManagedViewSettings; +struct ColormanageProcessor; struct EnumPropertyItem; struct ImBuf; struct Main; @@ -45,6 +46,9 @@ struct PartialBufferUpdateContext; struct wmWindow; struct Scene; +struct ColorSpace; +struct ColorManagedDisplay; + /* ** Initialization / De-initialization ** */ void IMB_colormanagement_init(void); @@ -57,17 +61,39 @@ void IMB_colormanagement_check_file_config(struct Main *bmain); void IMB_colormanagement_validate_settings(struct ColorManagedDisplaySettings *display_settings, struct ColorManagedViewSettings *view_settings); -/* ** Color space transformation functions ** */ -void IMB_colormanagement_colorspace_transform(float *buffer, int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace, - int predivide); +const char *IMB_colormanagement_role_colorspace_name_get(int role); +void IMB_colormanagement_imbuf_float_from_rect(struct ImBuf *ibuf); -void IMB_colormanagement_pixel_to_role(float pixel[4], int role); -void IMB_colormanagement_pixel_from_role(float pixel[4], int role); +/* ** Color space transformation functions ** */ +void IMB_colormanagement_transform(float *buffer, int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace, int predivide); +void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace, int predivide); +void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace); + +void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], struct ColorSpace *colorspace); +void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], struct ColorSpace *colorspace); + +void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, int predivide); + +void IMB_colormanagement_scene_linear_to_display_v3(float pixel[3], struct ColorManagedDisplay *display); +void IMB_colormanagement_display_to_scene_linear_v3(float pixel[3], struct ColorManagedDisplay *display); + +void IMB_colormanagement_pixel_to_display_space_v4(float result[4], const float pixel[4], const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings); + +void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float pixel[3], const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings); + +void IMB_colormanagement_pixel_to_role_v4(float pixel[4], int role); +void IMB_colormanagement_pixel_from_role_v4(float pixel[4], int role); void IMB_colormanagement_imbuf_to_role(struct ImBuf *ibuf, int role); void IMB_colormanagement_imbuf_from_role(struct ImBuf *ibuf, int role); +void IMB_colormanagement_imbuf_assign_spaces(struct ImBuf *ibuf, struct ColorManagedColorspaceSettings *colorspace_settings); +void IMB_colormanagement_imbuf_assign_float_space(struct ImBuf *ibuf, struct ColorManagedColorspaceSettings *colorspace_settings); + void IMB_colormanagement_imbuf_make_scene_linear(struct ImBuf *ibuf, struct ColorManagedColorspaceSettings *colorspace_settings); void IMB_colormanagement_imbuf_make_display_space(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, @@ -75,26 +101,24 @@ void IMB_colormanagement_imbuf_make_display_space(struct ImBuf *ibuf, const stru /* ** Public display buffers interfaces ** */ -void IMB_colormanage_cache_free(struct ImBuf *ibuf); - unsigned char *IMB_display_buffer_acquire(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, void **cache_handle); unsigned char *IMB_display_buffer_acquire_ctx(const struct bContext *C, struct ImBuf *ibuf, void **cache_handle); -void IMB_display_buffer_pixel(float result[4], const float pixel[4], const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings); - void IMB_display_buffer_to_imbuf_rect(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings); -void IMB_display_buffer_release(void *cache_handle); +void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *linear_buffer, int width, int height, + int channels, const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings, int predivide); -void IMB_display_buffer_invalidate(struct ImBuf *ibuf); +void IMB_display_buffer_release(void *cache_handle); /* ** Display funcrions ** */ int IMB_colormanagement_display_get_named_index(const char *name); const char *IMB_colormanagement_display_get_indexed_name(int index); const char *IMB_colormanagement_display_get_default_name(void); +struct ColorManagedDisplay *IMB_colormanagement_display_get_named(const char *name); /* ** View funcrions ** */ int IMB_colormanagement_view_get_named_index(const char *name); @@ -103,6 +127,7 @@ const char *IMB_colormanagement_view_get_indexed_name(int index); /* ** Color space functions ** */ int IMB_colormanagement_colorspace_get_named_index(const char *name); const char *IMB_colormanagement_colorspace_get_indexed_name(int index); +const char *IMB_colormanagement_view_get_default_name(const char *display_name); /* ** RNA helper functions ** */ void IMB_colormanagement_display_items_add(struct EnumPropertyItem **items, int *totitem); @@ -110,26 +135,29 @@ void IMB_colormanagement_view_items_add(struct EnumPropertyItem **items, int *to void IMB_colormanagement_colorspace_items_add(struct EnumPropertyItem **items, int *totitem); /* ** Tile-based buffer management ** */ -void IMB_partial_display_buffer_update(struct ImBuf *ibuf, const float *linear_buffer, - int stride, int offset_x, int offset_y, +void IMB_partial_display_buffer_update(struct ImBuf *ibuf, const float *linear_buffer, const unsigned char *buffer_byte, + int stride, int offset_x, int offset_y, const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings, int xmin, int ymin, int xmax, int ymax); -/* ** Area-specific functions ** */ - -/* Sequencer */ - -void IMB_colormanagement_imbuf_to_sequencer_space(struct ImBuf *ibuf, int make_float); -void IMB_colormanagement_imbuf_from_sequencer_space(struct ImBuf *ibuf); - -void IMB_colormanagement_pixel_from_sequencer_space(float pixel[4]); - +/* ** Pixel processor functions ** */ +struct ColormanageProcessor *IMB_colormanagement_display_processor_new(const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings); +struct ColormanageProcessor *IMB_colormanagement_colorspace_processor_new(const char *from_colorspace, const char *to_colorspace); +void IMB_colormanagement_processor_apply_v4(struct ColormanageProcessor *cm_processor, float pixel[4]); +void IMB_colormanagement_processor_apply_v3(struct ColormanageProcessor *cm_processor, float pixel[3]); +void IMB_colormanagement_processor_apply(struct ColormanageProcessor *cm_processor, float *buffer, int width, int height, + int channels, int predivide); +void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processor); /* Roles */ enum { COLOR_ROLE_SCENE_LINEAR = 0, COLOR_ROLE_COLOR_PICKING, COLOR_ROLE_TEXTURE_PAINTING, - COLOR_ROLE_SEQUENCER, + COLOR_ROLE_DEFAULT_SEQUENCER, + COLOR_ROLE_DEFAULT_BYTE, + COLOR_ROLE_DEFAULT_FLOAT, }; -#endif // IMB_COLORMANAGEMENT_H +#endif /* IMB_COLORMANAGEMENT_H */ diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 9466be12b08..428bd401754 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -128,8 +128,10 @@ typedef struct ImBuf { unsigned int encodedbuffersize; /* Size of encodedbuffer */ /* color management */ - int colormanage_flags; - unsigned int *display_buffer_flags; /* array of per-display display buffers dirty flags */ + int colormanage_flags; /* color management flags field */ + struct ColorSpace *rect_colorspace; /* color space of byte buffer */ + struct ColorSpace *float_colorspace; /* color space of float buffer, used by sequencer only */ + unsigned int *display_buffer_flags; /* array of per-display display buffers dirty flags */ struct ColormanageCache *colormanage_cache; /* cache used by color management */ /* information for compressed textures */ @@ -141,10 +143,11 @@ typedef struct ImBuf { * \brief userflags: Flags used internally by blender for imagebuffers */ -#define IB_BITMAPFONT (1 << 0) /* this image is a font */ -#define IB_BITMAPDIRTY (1 << 1) /* image needs to be saved is not the same as filename */ -#define IB_MIPMAP_INVALID (1 << 2) /* image mipmaps are invalid, need recreate */ -#define IB_RECT_INVALID (1 << 3) /* float buffer changed, needs recreation of byte rect */ +#define IB_BITMAPFONT (1 << 0) /* this image is a font */ +#define IB_BITMAPDIRTY (1 << 1) /* image needs to be saved is not the same as filename */ +#define IB_MIPMAP_INVALID (1 << 2) /* image mipmaps are invalid, need recreate */ +#define IB_RECT_INVALID (1 << 3) /* float buffer changed, needs recreation of byte rect */ +#define IB_DISPLAY_BUFFER_INVALID (1 << 4) /* either float or byte buffer changed, need to re-calculate display buffers */ /** * \name Imbuf Component flags diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index 628a96d9030..8dd02b97093 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -35,11 +35,16 @@ #define BCM_CONFIG_FILE "config.ocio" +struct ConstProcessorRcPtr; + typedef struct ColorSpace { struct ColorSpace *next, *prev; int index; char name[64]; char description[64]; + + struct ConstProcessorRcPtr *to_scene_linear; + struct ConstProcessorRcPtr *from_scene_linear; } ColorSpace; typedef struct ColorManagedDisplay { @@ -47,6 +52,9 @@ typedef struct ColorManagedDisplay { int index; char name[64]; ListBase views; + + struct ConstProcessorRcPtr *to_scene_linear; + struct ConstProcessorRcPtr *from_scene_linear; } ColorManagedDisplay; typedef struct ColorManagedView { @@ -55,11 +63,14 @@ typedef struct ColorManagedView { char name[64]; } ColorManagedView; +void colormanage_cache_free(struct ImBuf *ibuf); + struct ColorManagedDisplay *colormanage_display_get_default(void); struct ColorManagedDisplay *colormanage_display_add(const char *name); struct ColorManagedDisplay *colormanage_display_get_named(const char *name); struct ColorManagedDisplay *colormanage_display_get_indexed(int index); +const char *colormanage_view_get_default_name(const ColorManagedDisplay *display); struct ColorManagedView *colormanage_view_get_default(const ColorManagedDisplay *display); struct ColorManagedView *colormanage_view_add(const char *name); struct ColorManagedView *colormanage_view_get_indexed(int index); @@ -69,4 +80,4 @@ struct ColorSpace *colormanage_colorspace_add(const char *name, const char *desc struct ColorSpace *colormanage_colorspace_get_named(const char *name); struct ColorSpace *colormanage_colorspace_get_indexed(int index); -#endif // IMB_COLORMANAGEMENT_INTERN_H +#endif /* IMB_COLORMANAGEMENT_INTERN_H */ diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index bee4758dd07..32c14e3a8b7 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -41,7 +41,7 @@ #include "IMB_allocimbuf.h" #include "IMB_filetype.h" #include "IMB_metadata.h" -#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" #include "imbuf.h" @@ -163,7 +163,7 @@ void IMB_freeImBuf(ImBuf *ibuf) IMB_freezbuffloatImBuf(ibuf); freeencodedbufferImBuf(ibuf); IMB_metadata_free(ibuf); - IMB_colormanage_cache_free(ibuf); + colormanage_cache_free(ibuf); if (ibuf->dds_data.data != NULL) { free(ibuf->dds_data.data); /* dds_data.data is allocated by DirectDrawSurface::readData(), so don't use MEM_freeN! */ @@ -358,7 +358,7 @@ ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar planes, unsigned int ibuf->ftype = TGA; ibuf->channels = 4; /* float option, is set to other values when buffers get assigned */ ibuf->ppm[0] = ibuf->ppm[1] = IMB_DPI_DEFAULT / 0.0254; /* IMB_DPI_DEFAULT -> pixels-per-meter */ - + if (flags & IB_rect) { if (imb_addrectImBuf(ibuf) == FALSE) { IMB_freeImBuf(ibuf); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index f394f845769..8ce81053c77 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -74,15 +74,16 @@ typedef struct ConstProcessorRcPtr { /*********************** Global declarations *************************/ -/* define this to allow byte buffers be color managed */ -#undef COLORMANAGE_BYTE_BUFFER +#define MAX_COLORSPACE_NAME 64 /* ** list of all supported color spaces, displays and views */ #ifdef WITH_OCIO -static char global_role_scene_linear[64]; -static char global_role_color_picking[64]; -static char global_role_texture_painting[64]; -static char global_role_sequencer[64]; +static char global_role_scene_linear[MAX_COLORSPACE_NAME]; +static char global_role_color_picking[MAX_COLORSPACE_NAME]; +static char global_role_texture_painting[MAX_COLORSPACE_NAME]; +static char global_role_default_byte[MAX_COLORSPACE_NAME]; +static char global_role_default_float[MAX_COLORSPACE_NAME]; +static char global_role_default_sequencer[MAX_COLORSPACE_NAME]; #endif static ListBase global_colorspaces = {NULL}; @@ -93,6 +94,19 @@ static int global_tot_colorspace = 0; static int global_tot_display = 0; static int global_tot_view = 0; +typedef struct ColormanageProcessor { + ConstProcessorRcPtr *processor; + CurveMapping *curve_mapping; + +#ifndef WITH_OCIO + /* this callback is only used in cases when Blender was build without OCIO + * and aimed to preserve compatibility with previous Blender versions + */ + void (*display_transform_cb_v3) (float result[3], const float pixel[3]); + void (*display_transform_predivide_cb_v4) (float result[4], const float pixel[4]); +#endif +} ColormanageProcessor; + /*********************** Color managed cache *************************/ /* Cache Implementation Notes @@ -237,9 +251,8 @@ static int colormanage_hashcmp(const void *av, const void *bv) static struct MovieCache *colormanage_moviecache_ensure(ImBuf *ibuf) { - if (!ibuf->colormanage_cache) { + if (!ibuf->colormanage_cache) ibuf->colormanage_cache = MEM_callocN(sizeof(ColormanageCache), "imbuf colormanage cache"); - } if (!ibuf->colormanage_cache->moviecache) { struct MovieCache *moviecache; @@ -255,9 +268,8 @@ static struct MovieCache *colormanage_moviecache_ensure(ImBuf *ibuf) static void colormanage_cachedata_set(ImBuf *ibuf, ColormnaageCacheData *data) { - if (!ibuf->colormanage_cache) { + if (!ibuf->colormanage_cache) ibuf->colormanage_cache = MEM_callocN(sizeof(ColormanageCache), "imbuf colormanage cache"); - } ibuf->colormanage_cache->data = data; } @@ -296,7 +308,7 @@ static ImBuf *colormanage_cache_get_ibuf(ImBuf *ibuf, ColormanageCacheKey *key, struct MovieCache *moviecache = colormanage_moviecache_get(ibuf); if (!moviecache) { - /* if there's no moviecache it means no color management was applied before */ + /* if there's no moviecache it means no color management was applied on given image buffer before */ return NULL; } @@ -341,7 +353,7 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV * in cache separately. buffer which were used only different exposure/gamma * are re-suing the same cached buffer * - * check here which exposure/gamma was used for cached buffer and if they're + * check here which exposure/gamma/curve was used for cached buffer and if they're * different from requested buffer should be re-generated */ cache_data = colormanage_cachedata_get(cache_ibuf); @@ -406,30 +418,6 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting IMB_moviecache_put(moviecache, &key, cache_ibuf); } - -static unsigned char *colormanage_cache_get_cache_data(ImBuf *ibuf, const ColormanageCacheViewSettings *view_settings, - const ColormanageCacheDisplaySettings *display_settings, - void **cache_handle, float *exposure, float *gamma) -{ - ColormanageCacheKey key; - ColormnaageCacheData *cache_data; - ImBuf *cache_ibuf; - - colormanage_settings_to_key(&key, view_settings, display_settings); - - cache_ibuf = colormanage_cache_get_ibuf(ibuf, &key, cache_handle); - - if (cache_ibuf) { - cache_data = colormanage_cachedata_get(cache_ibuf); - - *exposure = cache_data->exposure; - *gamma = cache_data->gamma; - - return (unsigned char *) cache_ibuf->rect; - } - - return NULL; -} #endif static void colormanage_cache_handle_release(void *cache_handle) @@ -442,8 +430,7 @@ static void colormanage_cache_handle_release(void *cache_handle) /*********************** Initialization / De-initialization *************************/ #ifdef WITH_OCIO -static void colormanage_role_color_space_name_get(ConstConfigRcPtr *config, char *colorspace_name, - int max_colorspace_name, const char *role, const char *role_name) +static void colormanage_role_color_space_name_get(ConstConfigRcPtr *config, char *colorspace_name, const char *role) { ConstColorSpaceRcPtr *ociocs; @@ -452,11 +439,12 @@ static void colormanage_role_color_space_name_get(ConstConfigRcPtr *config, char if (ociocs) { const char *name = OCIO_colorSpaceGetName(ociocs); - BLI_strncpy(colorspace_name, name, max_colorspace_name); + /* assume function was called with buffer properly allocated to MAX_COLORSPACE_NAME chars */ + BLI_strncpy(colorspace_name, name, MAX_COLORSPACE_NAME); OCIO_colorSpaceRelease(ociocs); } else { - printf("Blender color management: Error could not find %s role.\n", role_name); + printf("Blender color management: Error could not find role %s role.\n", role); } } @@ -466,17 +454,12 @@ static void colormanage_load_config(ConstConfigRcPtr *config) const char *name; /* get roles */ - colormanage_role_color_space_name_get(config, global_role_scene_linear, sizeof(global_role_scene_linear), - OCIO_ROLE_SCENE_LINEAR, "scene linear"); - - colormanage_role_color_space_name_get(config, global_role_color_picking, sizeof(global_role_color_picking), - OCIO_ROLE_COLOR_PICKING, "color picking"); - - colormanage_role_color_space_name_get(config, global_role_texture_painting, sizeof(global_role_texture_painting), - OCIO_ROLE_TEXTURE_PAINT, "texture painting"); - - colormanage_role_color_space_name_get(config, global_role_sequencer, sizeof(global_role_sequencer), - OCIO_ROLE_SEQUENCER, "sequencer"); + colormanage_role_color_space_name_get(config, global_role_scene_linear, OCIO_ROLE_SCENE_LINEAR); + colormanage_role_color_space_name_get(config, global_role_color_picking, OCIO_ROLE_COLOR_PICKING); + colormanage_role_color_space_name_get(config, global_role_texture_painting, OCIO_ROLE_TEXTURE_PAINT); + colormanage_role_color_space_name_get(config, global_role_default_sequencer, OCIO_ROLE_DEFAULT_SEQUENCER); + colormanage_role_color_space_name_get(config, global_role_default_byte, OCIO_ROLE_DEFAULT_BYTE); + colormanage_role_color_space_name_get(config, global_role_default_float, OCIO_ROLE_DEFAULT_FLOAT); /* load colorspaces */ tot_colorspace = OCIO_configGetNumColorSpaces(config); @@ -535,39 +518,46 @@ void colormanage_free_config(void) { ColorSpace *colorspace; ColorManagedDisplay *display; - ColorManagedView *view; + /* free color spaces */ colorspace = global_colorspaces.first; while (colorspace) { ColorSpace *colorspace_next = colorspace->next; + /* free precomputer processors */ + if (colorspace->to_scene_linear) + OCIO_processorRelease((ConstProcessorRcPtr *) colorspace->to_scene_linear); + + if (colorspace->from_scene_linear) + OCIO_processorRelease((ConstProcessorRcPtr *) colorspace->from_scene_linear); + + /* free color space itself */ MEM_freeN(colorspace); + colorspace = colorspace_next; } + /* free displays */ display = global_displays.first; while (display) { ColorManagedDisplay *display_next = display->next; - LinkData *display_view = display->views.first; - while (display_view) { - LinkData *display_view_next = display_view->next; + /* free precomputer processors */ + if (display->to_scene_linear) + OCIO_processorRelease((ConstProcessorRcPtr *) display->to_scene_linear); - MEM_freeN(display_view); - display_view = display_view_next; - } + if (display->from_scene_linear) + OCIO_processorRelease((ConstProcessorRcPtr *) display->from_scene_linear); + + /* free list of views */ + BLI_freelistN(&display->views); MEM_freeN(display); display = display_next; } - view = global_views.first; - while (view) { - ColorManagedView *view_next = view->next; - - MEM_freeN(view); - view = view_next; - } + /* free views */ + BLI_freelistN(&global_views); } #endif @@ -581,10 +571,10 @@ void IMB_colormanagement_init(void) ocio_env = getenv("OCIO"); - if (ocio_env) { + if (ocio_env) config = OCIO_configCreateFromEnv(); - } - else { + + if (config == NULL) { configdir = BLI_get_folder(BLENDER_DATAFILES, "colormanagement"); if (configdir) { @@ -601,7 +591,6 @@ void IMB_colormanagement_init(void) } OCIO_configRelease(config); - #endif BLI_init_srgb_conversion(); @@ -614,624 +603,9 @@ void IMB_colormanagement_exit(void) #endif } -/*********************** Threaded display buffer transform routines *************************/ +/*********************** Internal functions *************************/ -#ifdef WITH_OCIO -typedef struct DisplayBufferThread { - CurveMapping *curve_mapping; - void *processor; - - float *buffer; - unsigned char *byte_buffer; - - float *display_buffer; - unsigned char *display_buffer_byte; - - int width; - int start_line; - int tot_line; - - int channels; - int dither; - int predivide; - - int nolinear_float; -} DisplayBufferThread; - -typedef struct DisplayBufferInitData { - ImBuf *ibuf; - CurveMapping *curve_mapping; - void *processor; - float *buffer; - unsigned char *byte_buffer; - - float *display_buffer; - unsigned char *display_buffer_byte; - - int width; -} DisplayBufferInitData; - -static void display_buffer_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v) -{ - DisplayBufferThread *handle = (DisplayBufferThread *) handle_v; - DisplayBufferInitData *init_data = (DisplayBufferInitData *) init_data_v; - ImBuf *ibuf = init_data->ibuf; - CurveMapping *curve_mapping = init_data->curve_mapping; - - int predivide = ibuf->flags & IB_cm_predivide; - int channels = ibuf->channels; - int dither = ibuf->dither; - - int offset = channels * start_line * ibuf->x; - - memset(handle, 0, sizeof(DisplayBufferThread)); - - handle->processor = init_data->processor; - - if (init_data->buffer) - handle->buffer = init_data->buffer + offset; - - if (init_data->byte_buffer) - handle->byte_buffer = init_data->byte_buffer + offset; - - if (init_data->display_buffer) - handle->display_buffer = init_data->display_buffer + offset; - - if (init_data->display_buffer_byte) - handle->display_buffer_byte = init_data->display_buffer_byte + offset; - - handle->width = ibuf->x; - - handle->start_line = start_line; - handle->tot_line = tot_line; - - handle->channels = channels; - handle->dither = dither; - handle->predivide = predivide; - handle->curve_mapping = curve_mapping; - - handle->nolinear_float = ibuf->colormanage_flags & IMB_COLORMANAGE_NOLINEAR_FLOAT; -} - -static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned char *byte_buffer, - float *display_buffer, unsigned char *display_buffer_byte, - CurveMapping *curve_mapping, void *processor, void *(do_thread) (void *)) -{ - DisplayBufferInitData init_data; - - init_data.ibuf = ibuf; - init_data.curve_mapping = curve_mapping; - init_data.processor = processor; - init_data.buffer = buffer; - init_data.byte_buffer = byte_buffer; - init_data.display_buffer = display_buffer; - init_data.display_buffer_byte = display_buffer_byte; - - IMB_processor_apply_threaded(ibuf->y, sizeof(DisplayBufferThread), &init_data, - display_buffer_init_handle, do_thread); -} - -static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) -{ - float *linear_buffer = NULL; - - int channels = handle->channels; - int width = handle->width; - int height = handle->tot_line; - - int buffer_size = channels * width * height; - - int predivide = handle->predivide; - - linear_buffer = MEM_callocN(buffer_size * sizeof(float), "color conversion linear buffer"); - - if (!handle->buffer) { - unsigned char *byte_buffer = handle->byte_buffer; - - /* OCIO_TODO: for now assume byte buffers are in sRGB space, - * in the future it shall use color space specified - * by user - */ - IMB_buffer_float_from_byte(linear_buffer, byte_buffer, - IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, - predivide, width, height, width, width); - } - else if (handle->nolinear_float) { - /* currently float is non-linear only in sequencer, which is working - * in it's own color space even to handle float buffers, so we need to ensure - * float buffer is in linear space before applying all the view transformations - */ - - const char *from_colorspace = global_role_sequencer; - const char *to_colorspace = global_role_scene_linear; - - memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float)); - - IMB_colormanagement_colorspace_transform(linear_buffer, width, height, channels, - from_colorspace, to_colorspace, predivide); - } - else { - /* some processors would want to modify float original buffer - * before converting it into display byte buffer, so we need to - * make sure original's ImBuf buffers wouldn't be modified by - * using duplicated buffer here - * - * NOTE: MEM_dupallocN can't be used because buffer could be - * specified as an offset inside allocated buffer - */ - - memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float)); - } - - return linear_buffer; -} - -static void *do_display_buffer_apply_thread(void *handle_v) -{ - DisplayBufferThread *handle = (DisplayBufferThread *) handle_v; - CurveMapping *curve_mapping = handle->curve_mapping; - ConstProcessorRcPtr *processor = (ConstProcessorRcPtr *) handle->processor; - PackedImageDesc *img; - float *buffer = handle->buffer; - float *display_buffer = handle->display_buffer; - unsigned char *display_buffer_byte = handle->display_buffer_byte; - int channels = handle->channels; - int width = handle->width; - int height = handle->tot_line; - int dither = handle->dither; - int predivide = handle->predivide; - - float *linear_buffer = display_buffer_apply_get_linear_buffer(handle); - - if (curve_mapping) { - int x, y; - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - float *pixel = linear_buffer + channels * (y * width + x); - - if (channels == 1) { - pixel[0] = curvemap_evaluateF(curve_mapping->cm, pixel[0]); - } - else if (channels == 2) { - pixel[0] = curvemap_evaluateF(curve_mapping->cm, pixel[0]); - pixel[1] = curvemap_evaluateF(curve_mapping->cm, pixel[1]); - } - else { - curvemapping_evaluate_premulRGBF(curve_mapping, pixel, pixel); - } - } - } - } - - img = OCIO_createPackedImageDesc(linear_buffer, width, height, channels, sizeof(float), - channels * sizeof(float), channels * sizeof(float) * width); - - if (predivide) - OCIO_processorApply_predivide(processor, img); - else - OCIO_processorApply(processor, img); - - OCIO_packedImageDescRelease(img); - - if (display_buffer_byte) { - /* do conversion */ - IMB_buffer_byte_from_float(display_buffer_byte, linear_buffer, - channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, - predivide, width, height, width, width); - } - - if (display_buffer) { - memcpy(display_buffer, linear_buffer, width * height * channels * sizeof(float)); - } - - if (linear_buffer != buffer) - MEM_freeN(linear_buffer); - - return NULL; -} - -static ConstProcessorRcPtr *create_display_buffer_processor(const char *view_transform, const char *display, - float exposure, float gamma) -{ - ConstConfigRcPtr *config = OCIO_getCurrentConfig(); - DisplayTransformRcPtr *dt; - ExponentTransformRcPtr *et; - MatrixTransformRcPtr *mt; - ConstProcessorRcPtr *processor; - - float exponent = 1.0f / MAX2(FLT_EPSILON, gamma); - const float exponent4f[] = {exponent, exponent, exponent, exponent}; - - float gain = powf(2.0f, exposure); - const float scale4f[] = {gain, gain, gain, gain}; - float m44[16], offset4[4]; - - if (!config) { - /* there's no valid OCIO configuration, can't create processor */ - - return NULL; - } - - dt = OCIO_createDisplayTransform(); - - /* assuming handling buffer was already converted to scene linear space */ - OCIO_displayTransformSetInputColorSpaceName(dt, global_role_scene_linear); - OCIO_displayTransformSetView(dt, view_transform); - OCIO_displayTransformSetDisplay(dt, display); - - /* fstop exposure control */ - OCIO_matrixTransformScale(m44, offset4, scale4f); - mt = OCIO_createMatrixTransform(); - OCIO_matrixTransformSetValue(mt, m44, offset4); - OCIO_displayTransformSetLinearCC(dt, (ConstTransformRcPtr *) mt); - - /* post-display gamma transform */ - et = OCIO_createExponentTransform(); - OCIO_exponentTransformSetValue(et, exponent4f); - OCIO_displayTransformSetDisplayCC(dt, (ConstTransformRcPtr *) et); - - processor = OCIO_configGetProcessor(config, (ConstTransformRcPtr *) dt); - - OCIO_exponentTransformRelease(et); - OCIO_displayTransformRelease(dt); - OCIO_configRelease(config); - - return processor; -} - -static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_buffer, unsigned char *display_buffer_byte, - const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) -{ - ConstProcessorRcPtr *processor; - const float gamma = view_settings->gamma; - const float exposure = view_settings->exposure; - const char *view_transform = view_settings->view_transform; - const char *display = display_settings->display_device; - - processor = create_display_buffer_processor(view_transform, display, exposure, gamma); - - if (processor) { - CurveMapping *curve_mapping = NULL; - - if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) { - curve_mapping = view_settings->curve_mapping; - - curvemapping_premultiply(curve_mapping, FALSE); - } - - display_buffer_apply_threaded(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect, - display_buffer, display_buffer_byte, curve_mapping, processor, - do_display_buffer_apply_thread); - - if (curve_mapping) - curvemapping_premultiply(curve_mapping, TRUE); - } - - OCIO_processorRelease(processor); -} - -static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *display_buffer, - const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) -{ - colormanage_display_buffer_process_ex(ibuf, NULL, display_buffer, view_settings, display_settings); -} - -/*********************** Threaded color space transform routines *************************/ - -typedef struct ColorspaceTransformThread { - void *processor; - float *buffer; - int width; - int start_line; - int tot_line; - int channels; - int predivide; -} ColorspaceTransformThread; - -typedef struct ColorspaceTransformInit { - void *processor; - float *buffer; - int width; - int height; - int channels; - int predivide; -} ColorspaceTransformInitData; - -static void colorspace_transform_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v) -{ - ColorspaceTransformThread *handle = (ColorspaceTransformThread *) handle_v; - ColorspaceTransformInitData *init_data = (ColorspaceTransformInitData *) init_data_v; - - int channels = init_data->channels; - int width = init_data->width; - int predivide = init_data->predivide; - - int offset = channels * start_line * width; - - memset(handle, 0, sizeof(ColorspaceTransformThread)); - - handle->processor = init_data->processor; - - handle->buffer = init_data->buffer + offset; - - handle->width = width; - - handle->start_line = start_line; - handle->tot_line = tot_line; - - handle->channels = channels; - handle->predivide = predivide; -} - -static void colorspace_transform_apply_threaded(float *buffer, int width, int height, int channels, - void *processor, int predivide, void *(do_thread) (void *)) -{ - ColorspaceTransformInitData init_data; - - init_data.processor = processor; - init_data.buffer = buffer; - init_data.width = width; - init_data.height = height; - init_data.channels = channels; - init_data.predivide = predivide; - - IMB_processor_apply_threaded(height, sizeof(ColorspaceTransformThread), &init_data, - colorspace_transform_init_handle, do_thread); -} - -static void *do_color_space_transform_thread(void *handle_v) -{ - ColorspaceTransformThread *handle = (ColorspaceTransformThread *) handle_v; - ConstProcessorRcPtr *processor = (ConstProcessorRcPtr *) handle->processor; - PackedImageDesc *img; - float *buffer = handle->buffer; - int channels = handle->channels; - int width = handle->width; - int height = handle->tot_line; - int predivide = handle->predivide; - - img = OCIO_createPackedImageDesc(buffer, width, height, channels, sizeof(float), - channels * sizeof(float), channels * sizeof(float) * width); - - if (predivide) - OCIO_processorApply_predivide(processor, img); - else - OCIO_processorApply(processor, img); - - OCIO_packedImageDescRelease(img); - - return NULL; -} - -static ConstProcessorRcPtr *create_colorspace_transform_processor(const char *from_colorspace, - const char *to_colorspace) -{ - ConstConfigRcPtr *config = OCIO_getCurrentConfig(); - ConstProcessorRcPtr *processor; - - processor = OCIO_configGetProcessorWithNames(config, from_colorspace, to_colorspace); - - return processor; -} -#endif - -void IMB_colormanagement_colorspace_transform(float *buffer, int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace, - int predivide) -{ -#ifdef WITH_OCIO - ConstProcessorRcPtr *processor; - - if (!strcmp(from_colorspace, "NONE")) { - return; - } - - if (!strcmp(from_colorspace, to_colorspace)) { - /* if source and destination color spaces are identical, skip - * threading overhead and simply do nothing - */ - return; - } - - processor = create_colorspace_transform_processor(from_colorspace, to_colorspace); - - if (processor) { - colorspace_transform_apply_threaded(buffer, width, height, channels, processor, predivide, - do_color_space_transform_thread); - - OCIO_processorRelease(processor); - } -#else - (void) buffer; - (void) width; - (void) height; - (void) channels; - (void) from_colorspace; - (void) to_colorspace; -#endif -} - -#ifdef WITH_OCIO -static char *role_colorspace_name_get(int role) -{ - switch (role) { - case COLOR_ROLE_SCENE_LINEAR: - return global_role_scene_linear; - break; - case COLOR_ROLE_COLOR_PICKING: - return global_role_color_picking; - break; - case COLOR_ROLE_TEXTURE_PAINTING: - return global_role_texture_painting; - break; - case COLOR_ROLE_SEQUENCER: - return global_role_sequencer; - break; - default: - printf("Unknown role was passed to %s\n", __func__); - BLI_assert(0); - } - - return NULL; -} -#endif - -void IMB_colormanagement_imbuf_to_role(ImBuf *ibuf, int role) -{ -#ifdef WITH_OCIO - if (ibuf->rect_float) { - const char *from_colorspace = global_role_scene_linear; - const char *to_colorspace = role_colorspace_name_get(role); - int predivide = ibuf->flags & IB_cm_predivide; - - if (ibuf->rect) - imb_freerectImBuf(ibuf); - - IMB_colormanagement_colorspace_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace, predivide); - } -#else - (void) ibuf; - (void) role; -#endif -} - -void IMB_colormanagement_imbuf_from_role(ImBuf *ibuf, int role) -{ -#ifdef WITH_OCIO - if (ibuf->rect_float) { - const char *from_colorspace = role_colorspace_name_get(role); - const char *to_colorspace = global_role_scene_linear; - int predivide = ibuf->flags & IB_cm_predivide; - - if (ibuf->rect) - imb_freerectImBuf(ibuf); - - IMB_colormanagement_colorspace_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace, predivide); - } -#else - (void) ibuf; - (void) role; -#endif -} - -void IMB_colormanagement_pixel_to_role(float pixel[4], int role) -{ -#ifdef WITH_OCIO - ConstProcessorRcPtr *processor; - const char *from_colorspace = global_role_scene_linear; - const char *to_colorspace = role_colorspace_name_get(role); - - processor = create_colorspace_transform_processor(from_colorspace, to_colorspace); - - if (processor) { - OCIO_processorApplyRGBA(processor, pixel); - - OCIO_processorRelease(processor); - } -#else - (void) pixel; - (void) role; -#endif -} - -void IMB_colormanagement_pixel_from_role(float pixel[4], int role) -{ -#ifdef WITH_OCIO - ConstProcessorRcPtr *processor; - const char *from_colorspace = role_colorspace_name_get(role); - const char *to_colorspace = global_role_scene_linear; - - processor = create_colorspace_transform_processor(from_colorspace, to_colorspace); - - if (processor) { - OCIO_processorApplyRGBA(processor, pixel); - - OCIO_processorRelease(processor); - } -#else - (void) pixel; - (void) role; -#endif -} - -void IMB_colormanagement_imbuf_make_scene_linear(ImBuf *ibuf, ColorManagedColorspaceSettings *colorspace_settings) -{ -#ifdef WITH_OCIO - if (ibuf->rect_float) { - const char *from_colorspace = colorspace_settings->name; - const char *to_colorspace = global_role_scene_linear; - int predivide = ibuf->flags & IB_cm_predivide; - - IMB_colormanagement_colorspace_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace, predivide); - } -#else - (void) ibuf; - (void) colorspace_settings; -#endif -} - -void IMB_colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) -{ -#ifdef WITH_OCIO - /* OCIO_TODO: byte buffer management is not supported here yet */ - if (!ibuf->rect_float) - return; - - if (global_tot_display == 0 || global_tot_view == 0) { - IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float, ibuf->channels, IB_PROFILE_LINEAR_RGB, ibuf->profile, - ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x); - } - else { - colormanage_display_buffer_process_ex(ibuf, ibuf->rect_float, NULL, view_settings, display_settings); - } -#else - (void) view_settings; - (void) display_settings; - - IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float, ibuf->channels, IB_PROFILE_LINEAR_RGB, ibuf->profile, - ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x); -#endif -} - -#ifdef WITH_OCIO -static void colormanage_flags_allocate(ImBuf *ibuf) -{ - if (global_tot_display == 0) - return; - - ibuf->display_buffer_flags = MEM_callocN(sizeof(unsigned int) * global_tot_display, "imbuf display_buffer_flags"); -} -#endif - -static void imbuf_verify_float(ImBuf *ibuf) -{ - /* multiple threads could request for display buffer at once and in case - * view transform is not used it'll lead to display buffer calculated - * several times - * it is harmless, but would take much more time (assuming thread lock - * happens faster than running float->byte conversion for average image) - */ - BLI_lock_thread(LOCK_COLORMANAGE); - - if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID))) { - IMB_rect_from_float(ibuf); - - ibuf->userflags &= ~IB_RECT_INVALID; - } - - BLI_unlock_thread(LOCK_COLORMANAGE); -} - -/*********************** Public display buffers interfaces *************************/ - -void IMB_colormanage_cache_free(ImBuf *ibuf) +void colormanage_cache_free(ImBuf *ibuf) { if (ibuf->display_buffer_flags) { MEM_freeN(ibuf->display_buffer_flags); @@ -1257,98 +631,8 @@ void IMB_colormanage_cache_free(ImBuf *ibuf) } } -unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings, void **cache_handle) -{ - *cache_handle = NULL; - -#ifdef WITH_OCIO - - if (!ibuf->x || !ibuf->y) - return NULL; - -#if !defined(COLORMANAGE_BYTE_BUFFER) - if (!ibuf->rect_float) { - imbuf_verify_float(ibuf); - - return (unsigned char *) ibuf->rect; - } -#endif - - if (global_tot_display == 0 || global_tot_view == 0) { - /* currently only view-transformation is allowed, input and display - * spaces are hard-coded, so if there's no view transform applying - * it's safe to suppose standard byte buffer is used for display - */ - - imbuf_verify_float(ibuf); - - return (unsigned char *) ibuf->rect; - } - else { - unsigned char *display_buffer; - int buffer_size; - ColormanageCacheViewSettings cache_view_settings; - ColormanageCacheDisplaySettings cache_display_settings; - - if (ibuf->userflags & IB_RECT_INVALID) { - /* if byte buffer is marked as invalid, it means that float buffer was modified - * and display buffer should be updated - * mark all existing color managed display buffers as invalid, also free - * legacy byte buffer to be sure all users would re-calculate display buffers - * after removing RECT_INVALID flag - */ - - IMB_display_buffer_invalidate(ibuf); - - if (ibuf->rect) - imb_freerectImBuf(ibuf); - - ibuf->userflags &= ~IB_RECT_INVALID; - } - - colormanage_view_settings_to_cache(&cache_view_settings, view_settings); - colormanage_display_settings_to_cache(&cache_display_settings, display_settings); - - BLI_lock_thread(LOCK_COLORMANAGE); - - /* ensure color management bit fields exists */ - if (!ibuf->display_buffer_flags) - colormanage_flags_allocate(ibuf); - - display_buffer = colormanage_cache_get(ibuf, &cache_view_settings, &cache_display_settings, cache_handle); - - if (display_buffer) { - BLI_unlock_thread(LOCK_COLORMANAGE); - return display_buffer; - } - - buffer_size = ibuf->channels * ibuf->x * ibuf->y * sizeof(float); - display_buffer = MEM_callocN(buffer_size, "imbuf display buffer"); - - colormanage_display_buffer_process(ibuf, display_buffer, view_settings, display_settings); - - colormanage_cache_put(ibuf, &cache_view_settings, &cache_display_settings, display_buffer, cache_handle); - - BLI_unlock_thread(LOCK_COLORMANAGE); - - return display_buffer; - } -#else - /* no OCIO support, simply return byte buffer which was - * generated from float buffer (if any) using standard - * profiles without applying any view / display transformation */ - - (void) view_settings; - (void) display_settings; - - imbuf_verify_float(ibuf); - - return (unsigned char*) ibuf->rect; -#endif -} - -static void display_transform_settings_get(const bContext *C, ColorManagedViewSettings **view_settings_r, ColorManagedDisplaySettings **display_settings_r) +static void display_transform_get_from_ctx(const bContext *C, ColorManagedViewSettings **view_settings_r, + ColorManagedDisplaySettings **display_settings_r) { Scene *scene = CTX_data_scene(C); @@ -1356,114 +640,185 @@ static void display_transform_settings_get(const bContext *C, ColorManagedViewSe *display_settings_r = &scene->display_settings; } -unsigned char *IMB_display_buffer_acquire_ctx(const bContext *C, ImBuf *ibuf, void **cache_handle) -{ - ColorManagedViewSettings *view_settings; - ColorManagedDisplaySettings *display_settings; - - display_transform_settings_get(C, &view_settings, &display_settings); - - return IMB_display_buffer_acquire(ibuf, view_settings, display_settings, cache_handle); -} - -void IMB_display_buffer_pixel(float result[4], const float pixel[4], const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) -{ #ifdef WITH_OCIO +static ConstProcessorRcPtr *create_display_buffer_processor(const char *view_transform, const char *display, + float exposure, float gamma) +{ + ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + DisplayTransformRcPtr *dt; ConstProcessorRcPtr *processor; - const float gamma = view_settings->gamma; - const float exposure = view_settings->exposure; - const char *view_transform = view_settings->view_transform; - const char *display = display_settings->display_device; - copy_v4_v4(result, pixel); + if (!config) { + /* there's no valid OCIO configuration, can't create processor */ - processor = create_display_buffer_processor(view_transform, display, exposure, gamma); - - if (processor) { - - if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) { - CurveMapping *curve_mapping = NULL; - - /* curve mapping could be used meanwhile to compute display buffer, - * so need to lock here to be sure we're not changing curve mapping - * from separated threads - */ - BLI_lock_thread(LOCK_COLORMANAGE); - - curve_mapping = view_settings->curve_mapping; - - curvemapping_premultiply(curve_mapping, FALSE); - - curvemapping_evaluate_premulRGBF(curve_mapping, result, result); - OCIO_processorApplyRGBA(processor, result); - - curvemapping_premultiply(curve_mapping, TRUE); - - BLI_unlock_thread(LOCK_COLORMANAGE); - } - else { - OCIO_processorApplyRGBA(processor, result); - } + return NULL; } -#else - (void) view_settings; - (void) display_settings; - copy_v4_v4(result, pixel); -#endif + dt = OCIO_createDisplayTransform(); + + /* assuming handling buffer was already converted to scene linear space */ + OCIO_displayTransformSetInputColorSpaceName(dt, global_role_scene_linear); + OCIO_displayTransformSetView(dt, view_transform); + OCIO_displayTransformSetDisplay(dt, display); + + /* fstop exposure control */ + if (exposure != 0.0f) { + MatrixTransformRcPtr *mt; + float gain = powf(2.0f, exposure); + const float scale4f[] = {gain, gain, gain, gain}; + float m44[16], offset4[4]; + + OCIO_matrixTransformScale(m44, offset4, scale4f); + mt = OCIO_createMatrixTransform(); + OCIO_matrixTransformSetValue(mt, m44, offset4); + OCIO_displayTransformSetLinearCC(dt, (ConstTransformRcPtr *) mt); + + OCIO_matrixTransformRelease(mt); + } + + /* post-display gamma transform */ + if (gamma != 1.0f) { + ExponentTransformRcPtr *et; + float exponent = 1.0f / MAX2(FLT_EPSILON, gamma); + const float exponent4f[] = {exponent, exponent, exponent, exponent}; + + et = OCIO_createExponentTransform(); + OCIO_exponentTransformSetValue(et, exponent4f); + OCIO_displayTransformSetDisplayCC(dt, (ConstTransformRcPtr *) et); + + OCIO_exponentTransformRelease(et); + } + + processor = OCIO_configGetProcessor(config, (ConstTransformRcPtr *) dt); + + OCIO_displayTransformRelease(dt); + OCIO_configRelease(config); + + return processor; } -/* covert float buffer to display space and store it in image buffer's byte array */ -void IMB_display_buffer_to_imbuf_rect(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) +static ConstProcessorRcPtr *create_colorspace_transform_processor(const char *from_colorspace, + const char *to_colorspace) { -#ifdef WITH_OCIO + ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + ConstProcessorRcPtr *processor; -#if !defined(COLORMANAGE_BYTE_BUFFER) - if (!ibuf->rect_float) - return; -#endif + if (!config) { + /* there's no valid OCIO configuration, can't create processor */ - if (global_tot_display == 0 || global_tot_view == 0) { - imbuf_verify_float(ibuf); + return NULL; } - else { - if (!ibuf->rect) { - imb_addrectImBuf(ibuf); - } - colormanage_display_buffer_process(ibuf, (unsigned char *) ibuf->rect, view_settings, display_settings); - } -#else - (void) view_settings; - (void) display_settings; + processor = OCIO_configGetProcessorWithNames(config, from_colorspace, to_colorspace); - imbuf_verify_float(ibuf); -#endif + OCIO_configRelease(config); + + return processor; } -void IMB_display_buffer_release(void *cache_handle) +static ConstProcessorRcPtr *colorspace_to_scene_linear_processor(ColorSpace *colorspace) { - if (cache_handle) { + if (colorspace->to_scene_linear == NULL) { BLI_lock_thread(LOCK_COLORMANAGE); - colormanage_cache_handle_release(cache_handle); + if (colorspace->to_scene_linear == NULL) { + ConstProcessorRcPtr *to_scene_linear; + to_scene_linear = create_colorspace_transform_processor(colorspace->name, global_role_scene_linear); + colorspace->to_scene_linear = (struct ConstProcessorRcPtr *) to_scene_linear; + } BLI_unlock_thread(LOCK_COLORMANAGE); } + + return (ConstProcessorRcPtr *) colorspace->to_scene_linear; } -void IMB_display_buffer_invalidate(ImBuf *ibuf) +static ConstProcessorRcPtr *colorspace_from_scene_linear_processor(ColorSpace *colorspace) { - /* if there's no display_buffer_flags this means there's no color managed - * buffers created for this imbuf, no need to invalidate - */ - if (ibuf->display_buffer_flags) { - memset(ibuf->display_buffer_flags, 0, global_tot_display * sizeof(unsigned int)); + if (colorspace->from_scene_linear == NULL) { + BLI_lock_thread(LOCK_COLORMANAGE); + + if (colorspace->from_scene_linear == NULL) { + ConstProcessorRcPtr *from_scene_linear; + from_scene_linear = create_colorspace_transform_processor(global_role_scene_linear, colorspace->name); + colorspace->from_scene_linear = (struct ConstProcessorRcPtr *) from_scene_linear; + } + + BLI_unlock_thread(LOCK_COLORMANAGE); + } + + return (ConstProcessorRcPtr *) colorspace->from_scene_linear; +} + +static ConstProcessorRcPtr *display_from_scene_linear_processor(ColorManagedDisplay *display) +{ + if (display->from_scene_linear == NULL) { + BLI_lock_thread(LOCK_COLORMANAGE); + + if (display->from_scene_linear == NULL) { + const char *view_name = colormanage_view_get_default_name(display); + ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + ConstProcessorRcPtr *processor = NULL; + + if (view_name && config) { + const char *view_colorspace = OCIO_configGetDisplayColorSpaceName(config, display->name, view_name); + processor = OCIO_configGetProcessorWithNames(config, global_role_scene_linear, view_colorspace); + + OCIO_configRelease(config); + } + + display->from_scene_linear = (struct ConstProcessorRcPtr *) processor; + } + + BLI_unlock_thread(LOCK_COLORMANAGE); + } + + return (ConstProcessorRcPtr *) display->from_scene_linear; +} + +static ConstProcessorRcPtr *display_to_scene_linear_processor(ColorManagedDisplay *display) +{ + if (display->to_scene_linear == NULL) { + BLI_lock_thread(LOCK_COLORMANAGE); + + if (display->to_scene_linear == NULL) { + const char *view_name = colormanage_view_get_default_name(display); + ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + ConstProcessorRcPtr *processor = NULL; + + if (view_name && config) { + const char *view_colorspace = OCIO_configGetDisplayColorSpaceName(config, display->name, view_name); + processor = OCIO_configGetProcessorWithNames(config, view_colorspace, global_role_scene_linear); + + OCIO_configRelease(config); + } + + display->to_scene_linear = (struct ConstProcessorRcPtr *) processor; + } + + BLI_unlock_thread(LOCK_COLORMANAGE); + } + + return (ConstProcessorRcPtr *) display->to_scene_linear; +} +#endif + +static void curve_mapping_apply_pixel(CurveMapping *curve_mapping, float *pixel, int channels) +{ + if (channels == 1) { + pixel[0] = curvemap_evaluateF(curve_mapping->cm, pixel[0]); + } + else if (channels == 2) { + pixel[0] = curvemap_evaluateF(curve_mapping->cm, pixel[0]); + pixel[1] = curvemap_evaluateF(curve_mapping->cm, pixel[1]); + } + else { + curvemapping_evaluate_premulRGBF(curve_mapping, pixel, pixel); } } +/*********************** Generic functions *************************/ + #ifdef WITH_OCIO static void colormanage_check_display_settings(ColorManagedDisplaySettings *display_settings, const char *what, const ColorManagedDisplay *default_display) @@ -1475,7 +830,7 @@ static void colormanage_check_display_settings(ColorManagedDisplaySettings *disp ColorManagedDisplay *display = colormanage_display_get_named(display_settings->display_device); if (!display) { - printf("Blender color management: display \"%s\" used by %s not found, setting to default (\"%s\").\n", + printf("Color management: display \"%s\" used by %s not found, setting to default (\"%s\").\n", display_settings->display_device, what, default_display->name); BLI_strncpy(display_settings->display_device, default_display->name, @@ -1484,7 +839,8 @@ static void colormanage_check_display_settings(ColorManagedDisplaySettings *disp } } -static void colormanage_check_view_settings(ColorManagedDisplaySettings *display_settings, ColorManagedViewSettings *view_settings, const char *what) +static void colormanage_check_view_settings(ColorManagedDisplaySettings *display_settings, + ColorManagedViewSettings *view_settings, const char *what) { ColorManagedDisplay *display; ColorManagedView *default_view; @@ -1504,7 +860,7 @@ static void colormanage_check_view_settings(ColorManagedDisplaySettings *display default_view = colormanage_view_get_default(display); if (default_view) { - printf("Blender color management: %s view \"%s\" not found, setting default \"%s\".\n", + printf("Color management: %s view \"%s\" not found, setting default \"%s\".\n", what, view_settings->view_transform, default_view->name); BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform)); @@ -1531,7 +887,7 @@ static void colormanage_check_colorspace_settings(ColorManagedColorspaceSettings ColorSpace *colorspace = colormanage_colorspace_get_named(colorspace_settings->name); if (!colorspace) { - printf("Blender color management: %s colorspace \"%s\" not found, setting NONE instead.\n", + printf("Color management: %s colorspace \"%s\" not found, setting NONE instead.\n", what, colorspace_settings->name); BLI_strncpy(colorspace_settings->name, "NONE", sizeof(colorspace_settings->name)); @@ -1559,8 +915,17 @@ void IMB_colormanagement_check_file_config(Main *bmain) } for (scene = bmain->scene.first; scene; scene = scene->id.next) { + ColorManagedColorspaceSettings *sequencer_colorspace_settings; + colormanage_check_display_settings(&scene->display_settings, "scene", default_display); colormanage_check_view_settings(&scene->display_settings, &scene->view_settings, "scene"); + + sequencer_colorspace_settings = &scene->sequencer_colorspace_settings; + + if (sequencer_colorspace_settings->name[0] == '\0') { + BLI_strncpy(sequencer_colorspace_settings->name, global_role_default_sequencer, MAX_COLORSPACE_NAME); + } + colormanage_check_colorspace_settings(sequencer_colorspace_settings, "sequencer"); } /* ** check input color space settings ** */ @@ -1603,6 +968,926 @@ void IMB_colormanagement_validate_settings(ColorManagedDisplaySettings *display_ #endif } +const char *IMB_colormanagement_role_colorspace_name_get(int role) +{ +#ifdef WITH_OCIO + switch (role) { + case COLOR_ROLE_SCENE_LINEAR: + return global_role_scene_linear; + break; + case COLOR_ROLE_COLOR_PICKING: + return global_role_color_picking; + break; + case COLOR_ROLE_TEXTURE_PAINTING: + return global_role_texture_painting; + break; + case COLOR_ROLE_DEFAULT_SEQUENCER: + return global_role_default_sequencer; + break; + case COLOR_ROLE_DEFAULT_FLOAT: + return global_role_default_float; + break; + case COLOR_ROLE_DEFAULT_BYTE: + return global_role_default_byte; + break; + default: + printf("Unknown role was passed to %s\n", __func__); + BLI_assert(0); + } +#else + (void) role; +#endif + + return NULL; +} + +void IMB_colormanagement_imbuf_float_from_rect(ImBuf *ibuf) +{ + int predivide = ibuf->flags & IB_cm_predivide; + + if (ibuf->rect == NULL) + return; + + if (ibuf->rect_float == NULL) { + if (imb_addrectfloatImBuf(ibuf) == 0) + return; + } + + /* first, create float buffer in non-linear space */ + IMB_buffer_float_from_byte(ibuf->rect_float, (unsigned char *) ibuf->rect, IB_PROFILE_SRGB, IB_PROFILE_SRGB, + FALSE, ibuf->x, ibuf->y, ibuf->x, ibuf->x); + + /* then make float be in linear space */ + IMB_colormanagement_colorspace_to_scene_linear(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, + ibuf->rect_colorspace, predivide); +} + +/*********************** Threaded display buffer transform routines *************************/ + +#ifdef WITH_OCIO +typedef struct DisplayBufferThread { + ColormanageProcessor *cm_processor; + + float *buffer; + unsigned char *byte_buffer; + + float *display_buffer; + unsigned char *display_buffer_byte; + + int width; + int start_line; + int tot_line; + + int channels; + float dither; + int predivide; + + int nolinear_float; + + const char *byte_colorspace; + const char *float_colorspace; +} DisplayBufferThread; + +typedef struct DisplayBufferInitData { + ImBuf *ibuf; + ColormanageProcessor *cm_processor; + float *buffer; + unsigned char *byte_buffer; + + float *display_buffer; + unsigned char *display_buffer_byte; + + int width; + + const char *byte_colorspace; + const char *float_colorspace; +} DisplayBufferInitData; + +static void display_buffer_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v) +{ + DisplayBufferThread *handle = (DisplayBufferThread *) handle_v; + DisplayBufferInitData *init_data = (DisplayBufferInitData *) init_data_v; + ImBuf *ibuf = init_data->ibuf; + + int predivide = ibuf->flags & IB_cm_predivide; + int channels = ibuf->channels; + float dither = ibuf->dither; + + int offset = channels * start_line * ibuf->x; + + memset(handle, 0, sizeof(DisplayBufferThread)); + + handle->cm_processor = init_data->cm_processor; + + if (init_data->buffer) + handle->buffer = init_data->buffer + offset; + + if (init_data->byte_buffer) + handle->byte_buffer = init_data->byte_buffer + offset; + + if (init_data->display_buffer) + handle->display_buffer = init_data->display_buffer + offset; + + if (init_data->display_buffer_byte) + handle->display_buffer_byte = init_data->display_buffer_byte + offset; + + handle->width = ibuf->x; + + handle->start_line = start_line; + handle->tot_line = tot_line; + + handle->channels = channels; + handle->dither = dither; + handle->predivide = predivide; + + handle->byte_colorspace = init_data->byte_colorspace; + handle->float_colorspace = init_data->float_colorspace; + + handle->nolinear_float = ibuf->colormanage_flags & IMB_COLORMANAGE_NOLINEAR_FLOAT; +} + +static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) +{ + float *linear_buffer = NULL; + + int channels = handle->channels; + int width = handle->width; + int height = handle->tot_line; + + int buffer_size = channels * width * height; + + int predivide = handle->predivide; + + linear_buffer = MEM_callocN(buffer_size * sizeof(float), "color conversion linear buffer"); + + if (!handle->buffer) { + unsigned char *byte_buffer = handle->byte_buffer; + + const char *from_colorspace = handle->byte_colorspace; + const char *to_colorspace = global_role_scene_linear; + + float *fp; + unsigned char *cp; + int i; + + /* first convert byte buffer to float, keep in image space */ + for (i = 0, fp = linear_buffer, cp = byte_buffer; + i < channels * width * height; + i++, fp++, cp++) + { + *fp = (float)(*cp) / 255.0f; + } + + /* convert float buffer to scene linear space */ + IMB_colormanagement_transform(linear_buffer, width, height, channels, + from_colorspace, to_colorspace, predivide); + } + else if (handle->nolinear_float) { + /* currently float is non-linear only in sequencer, which is working + * in it's own color space even to handle float buffers. + * This color space is the same for byte and float images. + * Need to convert float buffer to linear space before applying display transform + */ + + const char *from_colorspace = handle->float_colorspace; + const char *to_colorspace = global_role_scene_linear; + + memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float)); + + IMB_colormanagement_transform(linear_buffer, width, height, channels, + from_colorspace, to_colorspace, predivide); + } + else { + /* some processors would want to modify float original buffer + * before converting it into display byte buffer, so we need to + * make sure original's ImBuf buffers wouldn't be modified by + * using duplicated buffer here + * + * NOTE: MEM_dupallocN can't be used because buffer could be + * specified as an offset inside allocated buffer + */ + + memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float)); + } + + return linear_buffer; +} + +static void *do_display_buffer_apply_thread(void *handle_v) +{ + DisplayBufferThread *handle = (DisplayBufferThread *) handle_v; + ColormanageProcessor *cm_processor = handle->cm_processor; + float *buffer = handle->buffer; + float *display_buffer = handle->display_buffer; + unsigned char *display_buffer_byte = handle->display_buffer_byte; + int channels = handle->channels; + int width = handle->width; + int height = handle->tot_line; + float dither = handle->dither; + int predivide = handle->predivide; + + float *linear_buffer = display_buffer_apply_get_linear_buffer(handle); + + /* apply processor */ + IMB_colormanagement_processor_apply(cm_processor, linear_buffer, width, height, channels, predivide); + + /* copy result to output buffers */ + if (display_buffer_byte) { + /* do conversion */ + IMB_buffer_byte_from_float(display_buffer_byte, linear_buffer, + channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, + predivide, width, height, width, width); + } + + if (display_buffer) + memcpy(display_buffer, linear_buffer, width * height * channels * sizeof(float)); + + if (linear_buffer != buffer) + MEM_freeN(linear_buffer); + + return NULL; +} + +static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned char *byte_buffer, float *display_buffer, + unsigned char *display_buffer_byte, ColormanageProcessor *cm_processor) +{ + DisplayBufferInitData init_data; + + init_data.ibuf = ibuf; + init_data.cm_processor = cm_processor; + init_data.buffer = buffer; + init_data.byte_buffer = byte_buffer; + init_data.display_buffer = display_buffer; + init_data.display_buffer_byte = display_buffer_byte; + + if (ibuf->rect_colorspace != NULL) { + init_data.byte_colorspace = ibuf->rect_colorspace->name; + } + else { + /* happens for viewer images, which are not so simple to determine where to + * set image buffer's color spaces + */ + init_data.byte_colorspace = global_role_default_byte; + } + + if (ibuf->float_colorspace != NULL) { + /* sequencer stores float buffers in non-linear space */ + init_data.float_colorspace = ibuf->float_colorspace->name; + } + else { + init_data.float_colorspace = NULL; + } + + IMB_processor_apply_threaded(ibuf->y, sizeof(DisplayBufferThread), &init_data, + display_buffer_init_handle, do_display_buffer_apply_thread); +} + +static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_buffer, unsigned char *display_buffer_byte, + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) +{ + ColormanageProcessor *cm_processor; + + cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); + + display_buffer_apply_threaded(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect, + display_buffer, display_buffer_byte, cm_processor); + + IMB_colormanagement_processor_free(cm_processor); +} + +static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *display_buffer, + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) +{ + colormanage_display_buffer_process_ex(ibuf, NULL, display_buffer, view_settings, display_settings); +} +#endif + +/*********************** Threaded processor transform routines *************************/ + +typedef struct ProcessorTransformThread { + ColormanageProcessor *cm_processor; + float *buffer; + int width; + int start_line; + int tot_line; + int channels; + int predivide; +} ProcessorTransformThread; + +typedef struct ProcessorTransformInit { + ColormanageProcessor *cm_processor; + float *buffer; + int width; + int height; + int channels; + int predivide; +} ProcessorTransformInitData; + +static void processor_transform_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v) +{ + ProcessorTransformThread *handle = (ProcessorTransformThread *) handle_v; + ProcessorTransformInitData *init_data = (ProcessorTransformInitData *) init_data_v; + + int channels = init_data->channels; + int width = init_data->width; + int predivide = init_data->predivide; + + int offset = channels * start_line * width; + + memset(handle, 0, sizeof(ProcessorTransformThread)); + + handle->cm_processor = init_data->cm_processor; + + handle->buffer = init_data->buffer + offset; + + handle->width = width; + + handle->start_line = start_line; + handle->tot_line = tot_line; + + handle->channels = channels; + handle->predivide = predivide; +} + +static void *do_processor_transform_thread(void *handle_v) +{ + ProcessorTransformThread *handle = (ProcessorTransformThread *) handle_v; + float *buffer = handle->buffer; + int channels = handle->channels; + int width = handle->width; + int height = handle->tot_line; + int predivide = handle->predivide; + + IMB_colormanagement_processor_apply(handle->cm_processor, buffer, width, height, channels, predivide); + + return NULL; +} + +static void processor_transform_apply_threaded(float *buffer, int width, int height, int channels, + ColormanageProcessor *cm_processor, int predivide) +{ + ProcessorTransformInitData init_data; + + init_data.cm_processor = cm_processor; + init_data.buffer = buffer; + init_data.width = width; + init_data.height = height; + init_data.channels = channels; + init_data.predivide = predivide; + + IMB_processor_apply_threaded(height, sizeof(ProcessorTransformThread), &init_data, + processor_transform_init_handle, do_processor_transform_thread); +} + +/*********************** Color space transformation functions *************************/ + +/* convert the whole buffer from specified by name color space to another - internal implementation */ +static void colormanagement_transform_ex(float *buffer, int width, int height, int channels, const char *from_colorspace, + const char *to_colorspace, int predivide, int do_threaded) +{ + ColormanageProcessor *cm_processor; + + if (!strcmp(from_colorspace, "NONE")) { + return; + } + + if (!strcmp(from_colorspace, to_colorspace)) { + /* if source and destination color spaces are identical, skip + * threading overhead and simply do nothing + */ + return; + } + + cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace); + + if (do_threaded) + processor_transform_apply_threaded(buffer, width, height, channels, cm_processor, predivide); + else + IMB_colormanagement_processor_apply(cm_processor, buffer, width, height, channels, predivide); + + IMB_colormanagement_processor_free(cm_processor); +} + +/* convert the whole buffer from specified by name color space to another */ +void IMB_colormanagement_transform(float *buffer, int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace, int predivide) +{ + colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, FALSE); +} + +/* convert the whole buffer from specified by name color space to another + * will do threaded conversion + */ +void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace, int predivide) +{ + colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, TRUE); +} + +void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace) +{ + ColormanageProcessor *cm_processor; + + if (!strcmp(from_colorspace, "NONE")) { + return; + } + + if (!strcmp(from_colorspace, to_colorspace)) { + /* if source and destination color spaces are identical, skip + * threading overhead and simply do nothing + */ + return; + } + + cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace); + + IMB_colormanagement_processor_apply_v4(cm_processor, pixel); + + IMB_colormanagement_processor_free(cm_processor); +} + +/* convert pixel from specified by descriptor color space to scene linear + * used by performance-critical areas such as renderer and baker + */ +void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], ColorSpace *colorspace) +{ +#ifdef WITH_OCIO + ConstProcessorRcPtr *processor; + + if (!colorspace) { + /* OCIO_TODO: make sure it never happens */ + + printf("%s: perform conversion from unknown color space\n", __func__); + + return; + } + + processor = colorspace_to_scene_linear_processor(colorspace); + + if (processor) + OCIO_processorApplyRGB(processor, pixel); +#else + (void) pixel; + (void) colorspace; +#endif +} + +/* same as above, but converts colors in opposite direction */ +void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], ColorSpace *colorspace) +{ +#ifdef WITH_OCIO + ConstProcessorRcPtr *processor; + + if (!colorspace) { + /* OCIO_TODO: make sure it never happens */ + + printf("%s: perform conversion from unknown color space\n", __func__); + + return; + } + + processor = colorspace_from_scene_linear_processor(colorspace); + + if (processor) + OCIO_processorApplyRGB(processor, pixel); + +#else + (void) pixel; + (void) colorspace; +#endif +} + +void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, int predivide) +{ +#ifdef WITH_OCIO + ConstProcessorRcPtr *processor; + + if (!colorspace) { + /* OCIO_TODO: make sure it never happens */ + + printf("%s: perform conversion from unknown color space\n", __func__); + + return; + } + + processor = colorspace_to_scene_linear_processor(colorspace); + + if (processor) { + PackedImageDesc *img; + + img = OCIO_createPackedImageDesc(buffer, width, height, channels, sizeof(float), + channels * sizeof(float), channels * sizeof(float) * width); + + if (predivide) + OCIO_processorApply_predivide(processor, img); + else + OCIO_processorApply(processor, img); + + OCIO_packedImageDescRelease(img); + } +#else + (void) buffer; + (void) channels; + (void) width; + (void) height; + (void) colorspace; + (void) predivide; +#endif +} + +/* convert pixel from scene linear to display space using default view + * used by performance-critical areas such as color-related widgets where we want to reduce + * amount of per-widget allocations + */ +void IMB_colormanagement_scene_linear_to_display_v3(float pixel[3], ColorManagedDisplay *display) +{ +#ifdef WITH_OCIO + ConstProcessorRcPtr *processor; + + processor = display_from_scene_linear_processor(display); + + if (processor) + OCIO_processorApplyRGB(processor, pixel); +#else + (void) pixel; + (void) display; +#endif +} + +/* same as above, but converts color in opposite direction */ +void IMB_colormanagement_display_to_scene_linear_v3(float pixel[3], ColorManagedDisplay *display) +{ +#ifdef WITH_OCIO + ConstProcessorRcPtr *processor; + + processor = display_to_scene_linear_processor(display); + + if (processor) + OCIO_processorApplyRGB(processor, pixel); +#else + (void) pixel; + (void) display; +#endif +} + +void IMB_colormanagement_pixel_to_display_space_v4(float result[4], const float pixel[4], + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) +{ + ColormanageProcessor *cm_processor; + + copy_v4_v4(result, pixel); + + cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); + IMB_colormanagement_processor_apply_v4(cm_processor, result); + IMB_colormanagement_processor_free(cm_processor); +} + +void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float pixel[3], + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) +{ + ColormanageProcessor *cm_processor; + + copy_v3_v3(result, pixel); + + cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); + IMB_colormanagement_processor_apply_v3(cm_processor, result); + IMB_colormanagement_processor_free(cm_processor); +} + +void IMB_colormanagement_imbuf_to_role(ImBuf *ibuf, int role) +{ +#ifdef WITH_OCIO + if (ibuf->rect_float) { + const char *from_colorspace = global_role_scene_linear; + const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(role); + int predivide = ibuf->flags & IB_cm_predivide; + + if (ibuf->rect) + imb_freerectImBuf(ibuf); + + IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, + from_colorspace, to_colorspace, predivide); + } +#else + (void) ibuf; + (void) role; +#endif +} + +void IMB_colormanagement_imbuf_from_role(ImBuf *ibuf, int role) +{ +#ifdef WITH_OCIO + if (ibuf->rect_float) { + const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(role); + const char *to_colorspace = global_role_scene_linear; + int predivide = ibuf->flags & IB_cm_predivide; + + if (ibuf->rect) + imb_freerectImBuf(ibuf); + + IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, + from_colorspace, to_colorspace, predivide); + } +#else + (void) ibuf; + (void) role; +#endif +} + +void IMB_colormanagement_pixel_to_role_v4(float pixel[4], int role) +{ +#ifdef WITH_OCIO + ConstProcessorRcPtr *processor; + const char *from_colorspace = global_role_scene_linear; + const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(role); + + processor = create_colorspace_transform_processor(from_colorspace, to_colorspace); + + if (processor) { + OCIO_processorApplyRGBA(processor, pixel); + + OCIO_processorRelease(processor); + } +#else + (void) pixel; + (void) role; +#endif +} + +void IMB_colormanagement_pixel_from_role_v4(float pixel[4], int role) +{ +#ifdef WITH_OCIO + ConstProcessorRcPtr *processor; + const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(role); + const char *to_colorspace = global_role_scene_linear; + + processor = create_colorspace_transform_processor(from_colorspace, to_colorspace); + + if (processor) { + OCIO_processorApplyRGBA(processor, pixel); + + OCIO_processorRelease(processor); + } +#else + (void) pixel; + (void) role; +#endif +} + +void IMB_colormanagement_imbuf_assign_spaces(ImBuf *ibuf, ColorManagedColorspaceSettings *colorspace_settings) +{ +#ifdef WITH_OCIO + /* OCIO_TODO: get rid of NONE color space */ + if (colorspace_settings) { + if (colorspace_settings->name[0] == 0 || !strcmp(colorspace_settings->name, "NONE")) { + /* when opening new image, assign it's color space based on default roles */ + + if (ibuf->rect_float) + BLI_strncpy(colorspace_settings->name, global_role_default_float, MAX_COLORSPACE_NAME); + else + BLI_strncpy(colorspace_settings->name, global_role_default_byte, MAX_COLORSPACE_NAME); + } + + ibuf->rect_colorspace = colormanage_colorspace_get_named(colorspace_settings->name); + } + else { + if (ibuf->rect_float) + ibuf->rect_colorspace = colormanage_colorspace_get_named(global_role_default_float); + else + ibuf->rect_colorspace = colormanage_colorspace_get_named(global_role_default_byte); + } +#else + (void) ibuf; + (void) colorspace_settings; +#endif +} + +void IMB_colormanagement_imbuf_assign_float_space(ImBuf *ibuf, ColorManagedColorspaceSettings *colorspace_settings) +{ + ibuf->float_colorspace = colormanage_colorspace_get_named(colorspace_settings->name); +} + +void IMB_colormanagement_imbuf_make_scene_linear(ImBuf *ibuf, ColorManagedColorspaceSettings *colorspace_settings) +{ +#ifdef WITH_OCIO + /* for byte buffers only store it's color space, no affect on buffer itself + * that's because of precision issues of bytes + */ + IMB_colormanagement_imbuf_assign_spaces(ibuf, colorspace_settings); + + /* convert float buffer to scene linear space */ + if (ibuf->rect_float) { + const char *from_colorspace = colorspace_settings->name; + const char *to_colorspace = global_role_scene_linear; + int predivide = ibuf->flags & IB_cm_predivide; + + IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, + from_colorspace, to_colorspace, predivide); + } +#else + (void) ibuf; + (void) colorspace_settings; +#endif +} + +void IMB_colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) +{ +#ifdef WITH_OCIO + /* OCIO_TODO: byte buffer management is not supported here yet */ + if (!ibuf->rect_float) + return; + + if (global_tot_display == 0 || global_tot_view == 0) { + IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float, ibuf->channels, IB_PROFILE_LINEAR_RGB, ibuf->profile, + ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x); + } + else { + colormanage_display_buffer_process_ex(ibuf, ibuf->rect_float, NULL, view_settings, display_settings); + } +#else + (void) view_settings; + (void) display_settings; + + IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float, ibuf->channels, IB_PROFILE_LINEAR_RGB, ibuf->profile, + ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x); +#endif +} + +static void imbuf_verify_float(ImBuf *ibuf) +{ + /* multiple threads could request for display buffer at once and in case + * view transform is not used it'll lead to display buffer calculated + * several times + * it is harmless, but would take much more time (assuming thread lock + * happens faster than running float->byte conversion for average image) + */ + BLI_lock_thread(LOCK_COLORMANAGE); + + if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID))) { + IMB_rect_from_float(ibuf); + + ibuf->userflags &= ~IB_RECT_INVALID; + } + + BLI_unlock_thread(LOCK_COLORMANAGE); +} + +/*********************** Public display buffers interfaces *************************/ + +/* acquire display buffer for given image buffer using specified view and display settings */ +unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, void **cache_handle) +{ + *cache_handle = NULL; + + if (!ibuf->x || !ibuf->y) + return NULL; + + if (global_tot_display == 0 || global_tot_view == 0) { + /* if there's no view transform or display transforms, fallback to standard sRGB/linear conversion + * the same logic would be used if OCIO is disabled + */ + + imbuf_verify_float(ibuf); + + return (unsigned char *) ibuf->rect; + } +#ifdef WITH_OCIO + else { + unsigned char *display_buffer; + int buffer_size; + ColormanageCacheViewSettings cache_view_settings; + ColormanageCacheDisplaySettings cache_display_settings; + + colormanage_view_settings_to_cache(&cache_view_settings, view_settings); + colormanage_display_settings_to_cache(&cache_display_settings, display_settings); + + BLI_lock_thread(LOCK_COLORMANAGE); + + /* ensure color management bit fields exists */ + if (!ibuf->display_buffer_flags) { + if (global_tot_display) + ibuf->display_buffer_flags = MEM_callocN(sizeof(unsigned int) * global_tot_display, "imbuf display_buffer_flags"); + } + else if (ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) { + /* all display buffers were marked as invalid from other areas, + * now propagate this flag to internal color management routines + */ + memset(ibuf->display_buffer_flags, 0, global_tot_display * sizeof(unsigned int)); + + ibuf->userflags &= ~IB_DISPLAY_BUFFER_INVALID; + } + + display_buffer = colormanage_cache_get(ibuf, &cache_view_settings, &cache_display_settings, cache_handle); + + if (display_buffer) { + BLI_unlock_thread(LOCK_COLORMANAGE); + return display_buffer; + } + + buffer_size = ibuf->channels * ibuf->x * ibuf->y * sizeof(float); + display_buffer = MEM_callocN(buffer_size, "imbuf display buffer"); + + colormanage_display_buffer_process(ibuf, display_buffer, view_settings, display_settings); + + colormanage_cache_put(ibuf, &cache_view_settings, &cache_display_settings, display_buffer, cache_handle); + + BLI_unlock_thread(LOCK_COLORMANAGE); + + return display_buffer; + } +#else + (void) view_settings; + (void) display_settings; + + return NULL; +#endif +} + +/* same as IMB_display_buffer_acquire but gets view and display settings from context */ +unsigned char *IMB_display_buffer_acquire_ctx(const bContext *C, ImBuf *ibuf, void **cache_handle) +{ + ColorManagedViewSettings *view_settings; + ColorManagedDisplaySettings *display_settings; + + display_transform_get_from_ctx(C, &view_settings, &display_settings); + + return IMB_display_buffer_acquire(ibuf, view_settings, display_settings, cache_handle); +} + +/* covert float buffer to display space and store it in image buffer's byte array */ +void IMB_display_buffer_to_imbuf_rect(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) +{ +#ifdef WITH_OCIO + if (global_tot_display == 0 || global_tot_view == 0) { + imbuf_verify_float(ibuf); + } + else { + if (!ibuf->rect) { + imb_addrectImBuf(ibuf); + } + + colormanage_display_buffer_process(ibuf, (unsigned char *) ibuf->rect, view_settings, display_settings); + } +#else + (void) view_settings; + (void) display_settings; + + imbuf_verify_float(ibuf); +#endif +} + +void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *linear_buffer, int width, int height, + int channels, const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, int predivide) +{ +#ifdef WITH_OCIO + if (global_tot_display == 0 || global_tot_view == 0) { + IMB_buffer_byte_from_float(display_buffer, linear_buffer, 4, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, FALSE, + width, height, width, width); + } + else { + float *buffer; + ColormanageProcessor *cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); + + buffer = MEM_callocN(channels * width * height * sizeof(float), "display transform temp buffer"); + memcpy(buffer, linear_buffer, channels * width * height * sizeof(float)); + + IMB_colormanagement_processor_apply(cm_processor, buffer, width, height, channels, predivide); + + IMB_colormanagement_processor_free(cm_processor); + + IMB_buffer_byte_from_float(display_buffer, buffer, channels, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_SRGB, + FALSE, width, height, width, width); + + MEM_freeN(buffer); + } +#else + (void) view_settings; + (void) display_settings; + + IMB_buffer_byte_from_float(display_buffer, linear_buffer, channels, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide, + width, height, width, width); +#endif +} + +void IMB_display_buffer_release(void *cache_handle) +{ + if (cache_handle) { + BLI_lock_thread(LOCK_COLORMANAGE); + + colormanage_cache_handle_release(cache_handle); + + BLI_unlock_thread(LOCK_COLORMANAGE); + } +} + /*********************** Display functions *************************/ #ifdef WITH_OCIO @@ -1705,10 +1990,16 @@ const char *IMB_colormanagement_display_get_default_name(void) #endif } +/* used by performance-critical pixel processing areas, such as color widgets */ +ColorManagedDisplay *IMB_colormanagement_display_get_named(const char *name) +{ + return colormanage_display_get_named(name); +} + /*********************** View functions *************************/ #ifdef WITH_OCIO -ColorManagedView *colormanage_view_get_default(const ColorManagedDisplay *display) +const char *colormanage_view_get_default_name(const ColorManagedDisplay *display) { ConstConfigRcPtr *config = OCIO_getCurrentConfig(); const char *name; @@ -1723,7 +2014,14 @@ ColorManagedView *colormanage_view_get_default(const ColorManagedDisplay *displa OCIO_configRelease(config); - if (name[0] == '\0') + return name; +} + +ColorManagedView *colormanage_view_get_default(const ColorManagedDisplay *display) +{ + const char *name = colormanage_view_get_default_name(display); + + if (!name || name[0] == '\0') return NULL; return colormanage_view_get_named(name); @@ -1786,6 +2084,22 @@ const char *IMB_colormanagement_view_get_indexed_name(int index) return "NONE"; } +const char *IMB_colormanagement_view_get_default_name(const char *display_name) +{ +#if WITH_OCIO + ColorManagedDisplay *display = colormanage_display_get_named(display_name); + ColorManagedView *view = colormanage_view_get_default(display); + + if (view) { + return view->name; + } +#else + (void) display_name; +#endif + + return NULL; +} + /*********************** Color space functions *************************/ static void colormanage_description_strip(char *description) @@ -1949,222 +2263,283 @@ void IMB_colormanagement_colorspace_items_add(EnumPropertyItem **items, int *tot * Partial display update is supposed to be used by such areas as * compositor and renderer, This areas are calculating tiles of the * images and because of performance reasons only this tiles should - * be color managed when they finished to be calculated. This gives - * nice visual feedback without slowing things down. + * be color managed. + * This gives nice visual feedback without slowing things down. * - * Updating happens for all display buffers generated for given - * ImBuf at the time function is being called. + * Updating happens for active display transformation only, all + * the rest buffers would be marked as dirty */ -static void partial_buffer_update_rect(unsigned char *display_buffer, const float *linear_buffer, int display_stride, - int linear_stride, int linear_offset_x, int linear_offset_y, - int channels, int dither, int predivide, int profile_from, - ConstProcessorRcPtr *processor, int xmin, int ymin, int xmax, int ymax) +#ifdef WITH_OCIO +static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffer, const float *linear_buffer, + const unsigned char *byte_buffer, int display_stride, int linear_stride, + int linear_offset_x, int linear_offset_y, ColormanageProcessor *cm_processor, + int xmin, int ymin, int xmax, int ymax) { int x, y; + int channels = ibuf->channels; + int predivide = ibuf->flags & IB_cm_predivide; + float dither = ibuf->dither; + ColorSpace *rect_colorspace = ibuf->rect_colorspace; + float *display_buffer_float = NULL; + int width = xmax - xmin; + int height = ymax - ymin; - (void) processor; /* silent down compiler when building without OCIO */ - - if (profile_from == IB_PROFILE_NONE) - profile_from = IB_PROFILE_SRGB; + if (dither != 0.0f) { + display_buffer_float = MEM_callocN(channels * width * height * sizeof(float), "display buffer for dither"); + } for (y = ymin; y < ymax; y++) { for (x = xmin; x < xmax; x++) { int display_index = (y * display_stride + x) * channels; int linear_index = ((y - linear_offset_y) * linear_stride + (x - linear_offset_x)) * channels; + float pixel[4]; -#ifdef WITH_OCIO - if (processor) { - float pixel[4]; - + if (linear_buffer) { copy_v4_v4(pixel, (float *) linear_buffer + linear_index); - - if (predivide) - OCIO_processorApplyRGBA_predivide(processor, pixel); - else - OCIO_processorApplyRGBA(processor, pixel); - - rgba_float_to_uchar(display_buffer + display_index, pixel); } + else if (byte_buffer) { + rgba_uchar_to_float(pixel, byte_buffer + linear_index); + + IMB_colormanagement_colorspace_to_scene_linear_v3(pixel, rect_colorspace); + } + + if (predivide) + IMB_colormanagement_processor_apply_v4(cm_processor, pixel); else -#endif - { - IMB_buffer_byte_from_float(display_buffer + display_index, linear_buffer + linear_index, channels, - dither, IB_PROFILE_SRGB, profile_from, predivide, 1, 1, 1, 1); + IMB_colormanagement_processor_apply_v4(cm_processor, pixel); + + if (display_buffer_float) { + int index = ((y - ymin) * width + (x - xmin)) * channels; + + copy_v4_v4(display_buffer_float + index, pixel); + } + else { + rgba_float_to_uchar(display_buffer + display_index, pixel); } } } -} -void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, int stride, int offset_x, int offset_y, + if (display_buffer_float) { + int display_index = (ymin * display_stride + xmin) * channels; + + IMB_buffer_byte_from_float(display_buffer + display_index, display_buffer_float, channels, dither, + IB_PROFILE_SRGB, IB_PROFILE_SRGB, FALSE, width, height, display_stride, width); + + MEM_freeN(display_buffer_float); + } +} +#endif + +void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, const unsigned char *byte_buffer, + int stride, int offset_x, int offset_y, const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, int xmin, int ymin, int xmax, int ymax) { - int channels = ibuf->channels; - int predivide = ibuf->flags & IB_cm_predivide; - int dither = ibuf->dither; - int profile_from = ibuf->profile; - int display; - int *display_buffer_flags; - -#ifdef WITH_OCIO - - BLI_lock_thread(LOCK_COLORMANAGE); - if (ibuf->rect && ibuf->rect_float) { /* update byte buffer created by legacy color management */ - partial_buffer_update_rect((unsigned char *) ibuf->rect, linear_buffer, ibuf->x, stride, offset_x, offset_y, - channels, dither, predivide, profile_from, NULL, xmin, ymin, xmax, ymax); + + unsigned char *rect = (unsigned char *) ibuf->rect; + int predivide = ibuf->flags & IB_cm_predivide; + int channels = ibuf->channels; + int profile_from = ibuf->profile; + int width = xmax - xmin; + int height = ymax - ymin; + int rect_index = (ymin * ibuf->x + xmin) * channels; + int linear_index = ((ymin - offset_y) * stride + (xmin - offset_x)) * channels; + + if (profile_from == IB_PROFILE_NONE) + profile_from = IB_PROFILE_LINEAR_RGB; + + IMB_buffer_byte_from_float(rect + rect_index, linear_buffer + linear_index, channels, ibuf->dither, + IB_PROFILE_SRGB, profile_from, predivide, width, height, ibuf->x, stride); } - if (!ibuf->display_buffer_flags) { - /* there's no cached display buffers, so no need to iterate though bit fields */ +#ifdef WITH_OCIO + if (ibuf->display_buffer_flags) { + ColormanageCacheViewSettings cache_view_settings; + ColormanageCacheDisplaySettings cache_display_settings; + void *cache_handle = NULL; + unsigned char *display_buffer = NULL; + int view_flag, display_index, buffer_width; + + colormanage_view_settings_to_cache(&cache_view_settings, view_settings); + colormanage_display_settings_to_cache(&cache_display_settings, display_settings); + + view_flag = 1 << (cache_view_settings.view - 1); + display_index = cache_display_settings.display - 1; + + BLI_lock_thread(LOCK_COLORMANAGE); + if ((ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) == 0) + display_buffer = colormanage_cache_get(ibuf, &cache_view_settings, &cache_display_settings, &cache_handle); + + /* in some rare cases buffer's dimension could be changing directly from + * different thread + * this i.e. happens when image editor acquires render result + */ + buffer_width = ibuf->x; + + /* mark all other buffers as invalid */ + memset(ibuf->display_buffer_flags, 0, global_tot_display * sizeof(unsigned int)); + ibuf->display_buffer_flags[display_index] |= view_flag; BLI_unlock_thread(LOCK_COLORMANAGE); - return; - } + if (display_buffer) { + ColormanageProcessor *cm_processor; - /* make a copy of flags, so other areas could calculate new display buffers - * and they'll be properly handled later - */ - display_buffer_flags = MEM_dupallocN(ibuf->display_buffer_flags); + cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); - BLI_unlock_thread(LOCK_COLORMANAGE); + partial_buffer_update_rect(ibuf, display_buffer, linear_buffer, byte_buffer, buffer_width, stride, + offset_x, offset_y, cm_processor, xmin, ymin, xmax, ymax); - for (display = 0; display < global_tot_display; display++) { - ColormanageCacheDisplaySettings display_settings = {0}; - int display_index = display + 1; /* displays in configuration are 1-based */ - const char *display_name = IMB_colormanagement_display_get_indexed_name(display_index); - int view_flags = display_buffer_flags[display]; - int view = 0; + IMB_colormanagement_processor_free(cm_processor); - display_settings.display = display_index; - - while (view_flags != 0) { - if (view_flags % 2 == 1) { - ColormanageCacheViewSettings view_settings = {0}; - unsigned char *display_buffer; - void *cache_handle = NULL; - int view_index = view + 1; /* views in configuration are 1-based */ - float exposure, gamma; - int buffer_width; - - view_settings.view = view_index; - - BLI_lock_thread(LOCK_COLORMANAGE); - display_buffer = colormanage_cache_get_cache_data(ibuf, &view_settings, &display_settings, - &cache_handle, &exposure, &gamma); - - /* in some rare cases buffer's dimension could be changing directly from - * different thread - * this i.e. happens when image editor acquires render result - */ - buffer_width = ibuf->x; - BLI_unlock_thread(LOCK_COLORMANAGE); - - if (display_buffer) { - const char *view_name = IMB_colormanagement_view_get_indexed_name(view_index); - ConstProcessorRcPtr *processor = NULL; - - processor = create_display_buffer_processor(view_name, display_name, exposure, gamma); - - partial_buffer_update_rect(display_buffer, linear_buffer, buffer_width, stride, - offset_x, offset_y, channels, dither, predivide, profile_from, - processor, xmin, ymin, xmax, ymax); - - if (processor) - OCIO_processorRelease(processor); - } - - IMB_display_buffer_release(cache_handle); - } - - view_flags /= 2; - view++; + IMB_display_buffer_release(cache_handle); } } - - MEM_freeN(display_buffer_flags); #else - (void) display; - (void) display_buffer_flags; + (void) byte_buffer; + (void) view_settings; + (void) display_settings; #endif } -/*********************** Area-specific functions *************************/ +/*********************** Pixel processor functions *************************/ -/* ** Sequencer ** */ - -void IMB_colormanagement_imbuf_to_sequencer_space(ImBuf *ibuf, int make_float) +ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) { - (void) make_float; + ColormanageProcessor *cm_processor; - if (!ibuf->rect_float) { - if (make_float && ibuf->rect) { - /* when converting byte buffer to float in sequencer we need to make float - * buffer be in sequencer's working space, which is currently only doable - * from linear space. - * - */ + cm_processor = MEM_callocN(sizeof(ColormanageProcessor), "colormanagement processor"); - /* - * OCIO_TODO: would be nice to support direct single transform from byte to sequencer's - */ +#ifdef WITH_OCIO + cm_processor->processor = create_display_buffer_processor(view_settings->view_transform, display_settings->display_device, + view_settings->exposure, view_settings->gamma); - ibuf->profile = IB_PROFILE_SRGB; - IMB_float_from_rect(ibuf); - } - else { - /* if there's only byte buffer in image it's already in compositor's working space, - * nothing to do here - */ + if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) { + cm_processor->curve_mapping = curvemapping_copy(view_settings->curve_mapping); + curvemapping_premultiply(cm_processor->curve_mapping, FALSE); + } +#else + (void) view_settings; + (void) display_settings; - return; + /* assume input is in linear space and color management is always enabled + * seams to be quite reasonable behavior in cases there's no OCIO + */ + cm_processor->display_transform_cb_v3 = linearrgb_to_srgb_v3_v3; + cm_processor->display_transform_predivide_cb_v4 = linearrgb_to_srgb_predivide_v4; +#endif + + return cm_processor; +} + +ColormanageProcessor *IMB_colormanagement_colorspace_processor_new(const char *from_colorspace, const char *to_colorspace) +{ + ColormanageProcessor *cm_processor; + + cm_processor = MEM_callocN(sizeof(ColormanageProcessor), "colormanagement processor"); + +#ifdef WITH_OCIO + cm_processor->processor = create_colorspace_transform_processor(from_colorspace, to_colorspace); +#else + (void) from_colorspace; + (void) to_colorspace; +#endif + + return cm_processor; +} + +void IMB_colormanagement_processor_apply_v4(ColormanageProcessor *cm_processor, float pixel[4]) +{ + if (cm_processor->curve_mapping) + curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel); + +#ifdef WITH_OCIO + OCIO_processorApplyRGBA(cm_processor->processor, pixel); +#else + if (cm_processor->display_transform_cb_v3) + cm_processor->display_transform_cb_v3(pixel, pixel); +#endif +} + +void IMB_colormanagement_processor_apply_v3(ColormanageProcessor *cm_processor, float pixel[3]) +{ + if (cm_processor->curve_mapping) + curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel); + +#ifdef WITH_OCIO + OCIO_processorApplyRGB(cm_processor->processor, pixel); +#else + if (cm_processor->display_transform_cb_v3) + cm_processor->display_transform_cb_v3(pixel, pixel); +#endif +} + +void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, float *buffer, int width, int height, + int channels, int predivide) +{ + /* apply curve mapping */ + if (cm_processor->curve_mapping) { + int x, y; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + float *pixel = buffer + channels * (y * width + x); + + curve_mapping_apply_pixel(cm_processor->curve_mapping, pixel, channels); + } } } #ifdef WITH_OCIO - if (global_role_sequencer[0]) { - IMB_colormanagement_imbuf_to_role(ibuf, COLOR_ROLE_SEQUENCER); - - ibuf->profile = IB_PROFILE_NONE; - } - else -#endif { - /* if no sequencer's working space defined fallback to legacy sRGB space */ - IMB_convert_profile(ibuf, IB_PROFILE_NONE); + PackedImageDesc *img; + + /* apply OCIO processor */ + img = OCIO_createPackedImageDesc(buffer, width, height, channels, sizeof(float), + channels * sizeof(float), channels * sizeof(float) * width); + + if (predivide) + OCIO_processorApply_predivide(cm_processor->processor, img); + else + OCIO_processorApply(cm_processor->processor, img); + + OCIO_packedImageDescRelease(img); } +#else + if (cm_processor->display_transform_cb_v3) { + int x, y; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + float *pixel = buffer + channels * (y * width + x); + + if (channels == 3) { + cm_processor->display_transform_cb_v3(pixel, pixel); + } + else if (channels == 4) { + if (!predivide) + cm_processor->display_transform_predivide_cb_v4(pixel, pixel); + else + cm_processor->display_transform_cb_v3(pixel, pixel); + } + } + } + } +#endif } -void IMB_colormanagement_imbuf_from_sequencer_space(ImBuf *ibuf) -{ - if (!ibuf->rect_float) - return; - -#ifdef WITH_OCIO - if (global_role_sequencer[0]) { - IMB_colormanagement_imbuf_from_role(ibuf, COLOR_ROLE_SEQUENCER); - ibuf->profile = IB_PROFILE_LINEAR_RGB; - } - else -#endif - { - /* if no sequencer's working space defined fallback to legacy sRGB space */ - - IMB_convert_profile(ibuf, IB_PROFILE_LINEAR_RGB); - } -} - -void IMB_colormanagement_pixel_from_sequencer_space(float pixel[4]) +void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor) { #ifdef WITH_OCIO - if (global_role_sequencer[0]) { - IMB_colormanagement_pixel_from_role(pixel, COLOR_ROLE_SEQUENCER); - } - else + if (cm_processor->curve_mapping) + curvemapping_free(cm_processor->curve_mapping); + + OCIO_processorRelease(cm_processor->processor); #endif - { - srgb_to_linearrgb_v4(pixel, pixel); - } + + MEM_freeN(cm_processor); } diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h index dfba83618dc..32a0629c338 100644 --- a/source/blender/makesdna/DNA_color_types.h +++ b/source/blender/makesdna/DNA_color_types.h @@ -174,7 +174,7 @@ typedef struct ColorManagedDisplaySettings { } ColorManagedDisplaySettings; typedef struct ColorManagedColorspaceSettings { - char name[64]; + char name[64]; /* MAX_COLORSPACE_NAME */ } ColorManagedColorspaceSettings; /* ColorManagedViewSettings->flag */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 639c1cd5fb2..e3a8863714a 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1141,6 +1141,7 @@ typedef struct Scene { /* Color Management */ ColorManagedViewSettings view_settings; ColorManagedDisplaySettings display_settings; + ColorManagedColorspaceSettings sequencer_colorspace_settings; } Scene; @@ -1262,7 +1263,7 @@ typedef struct Scene { #define R_ALPHAKEY 2 /* color_mgt_flag */ -#define R_COLOR_MANAGEMENT (1 << 0) +#define R_COLOR_MANAGEMENT (1 << 0) /* deprecated, should only be used in versioning code only */ #define R_COLOR_MANAGEMENT_PREDIVIDE (1 << 1) /* subimtype, flag options for imtype */ diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index fa3f8d69c47..8c071ac3411 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -50,6 +50,7 @@ #include "BKE_global.h" /* grr: G.main->name */ #include "IMB_imbuf.h" +#include "IMB_colormanagement.h" #include "BIF_gl.h" #include "GPU_draw.h" @@ -80,16 +81,17 @@ static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports BKE_reportf(reports, RPT_ERROR, "Couldn't acquire buffer from image"); } else { - /* temp swap out the color */ - const unsigned char imb_planes_back = ibuf->planes; - const float dither_back = ibuf->dither; - ibuf->planes = scene->r.im_format.planes; - ibuf->dither = scene->r.dither_intensity; - if (!BKE_imbuf_write(ibuf, path, &scene->r.im_format)) { + ImBuf *write_ibuf = IMB_dupImBuf(ibuf); + + IMB_display_buffer_to_imbuf_rect(write_ibuf, &scene->view_settings, &scene->display_settings); + + write_ibuf->planes = scene->r.im_format.planes; + write_ibuf->dither = scene->r.dither_intensity; + + if (!BKE_imbuf_write(write_ibuf, path, &scene->r.im_format)) { BKE_reportf(reports, RPT_ERROR, "Couldn't write image: %s", path); } - ibuf->planes = imb_planes_back; - ibuf->dither = dither_back; + IMB_freeImBuf(write_ibuf); } BKE_image_release_ibuf(image, lock); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index c58271bb4bc..0227d9c1554 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1093,34 +1093,6 @@ static void rna_Scene_glsl_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi DAG_id_tag_update(&scene->id, 0); } -static void rna_RenderSettings_color_management_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) -{ - /* reset image nodes */ - Scene *scene = (Scene *)ptr->id.data; - bNodeTree *ntree = scene->nodetree; - bNode *node; - - if (ntree && scene->use_nodes) { - /* images are freed here, stop render and preview threads, until - * Image is threadsafe. when we are changing this property from a - * python script in the render thread, don't stop own thread */ - if (BLI_thread_is_main()) - WM_jobs_stop_all(bmain->wm.first); - - for (node = ntree->nodes.first; node; node = node->next) { - if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_IMAGE)) { - ED_node_changed_update(&scene->id, node); - WM_main_add_notifier(NC_NODE | NA_EDITED, node); - - if (node->type == CMP_NODE_IMAGE) - BKE_image_signal((Image *)node->id, NULL, IMA_SIGNAL_FREE); - } - } - } - - rna_Scene_glsl_update(bmain, scene, ptr); -} - static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value) { Scene *scene = (Scene *)ptr->id.data; @@ -3709,11 +3681,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna) "editor pipeline, if sequencer strips exist"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - prop = RNA_def_property(srna, "use_color_management", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "color_mgt_flag", R_COLOR_MANAGEMENT); - RNA_def_property_ui_text(prop, "Color Management", "Use linear workflow - gamma corrected imaging pipeline"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_RenderSettings_color_management_update"); - prop = RNA_def_property(srna, "use_color_unpremultiply", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "color_mgt_flag", R_COLOR_MANAGEMENT_PREDIVIDE); RNA_def_property_ui_text(prop, "Color Unpremultiply", @@ -4596,6 +4563,11 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_struct_type(prop, "ColorManagedDisplaySettings"); RNA_def_property_ui_text(prop, "Display Settings", "Settings of device saved image would be displayed on"); + prop = RNA_def_property(srna, "sequencer_colorspace_settings", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "sequencer_colorspace_settings"); + RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings"); + RNA_def_property_ui_text(prop, "Sequencer Colorspace Settings", "Settings of color space sequencer is working in"); + /* Nestled Data */ rna_def_tool_settings(brna); rna_def_unified_paint_settings(brna); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 80860dbdf26..05cd85bc58e 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -666,7 +666,7 @@ static void rna_SpaceImageEditor_scopes_update(Main *UNUSED(bmain), Scene *scene ibuf = ED_space_image_acquire_buffer(sima, &lock); if (ibuf) { - scopes_update(&sima->scopes, ibuf, scene->r.color_mgt_flag & R_COLOR_MANAGEMENT); + scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings); WM_main_add_notifier(NC_IMAGE, sima->image); } ED_space_image_release_buffer(sima, lock); diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index 07db1ce1a18..f8626d36e87 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -33,6 +33,7 @@ #include #include "DNA_anim_types.h" +#include "DNA_color_types.h" #include "DNA_scene_types.h" #include "DNA_node_types.h" @@ -693,7 +694,9 @@ static void ntreeCompositExecTreeOld(bNodeTree *ntree, RenderData *rd, int do_pr void *COM_linker_hack = NULL; -void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int rendering, int do_preview) +void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int rendering, int do_preview, + const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) { #ifdef WITH_COMPOSITOR #ifdef WITH_COMPOSITOR_LEGACY @@ -704,10 +707,11 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int rendering, int else #endif { - COM_execute(rd, ntree, rendering); + COM_execute(rd, ntree, rendering, view_settings, display_settings); } #else (void)ntree, (void)rd, (void)rendering, (void)do_preview; + (void)view_settings, (void)display_settings; #endif (void)do_preview; diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c index 2277c5a2836..fe4eebc9492 100644 --- a/source/blender/nodes/composite/node_composite_util.c +++ b/source/blender/nodes/composite/node_composite_util.c @@ -606,6 +606,9 @@ static CompBuf *generate_procedural_preview(CompBuf *cbuf, int newx, int newy) return outbuf; } +/* OCIO_TODO: this function is only used by legacy compositor system only, which would likely be removed soon, + * keep check for old color management flag for now + */ void generate_preview(void *data, bNode *node, CompBuf *stackbuf) { RenderData *rd= data; diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 96a92055ca9..5861f072cb7 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -290,6 +290,9 @@ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc) *alloc= FALSE; + /* OCIO_TODO: this is a part of legacy compositor system, don't bother with porting this code + * to new color management system since this code would likely be simply removed soon + */ if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) { if (ibuf->profile != IB_PROFILE_NONE) { rect= ibuf->rect_float; diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c index 2d9b9348668..06d24e46ce5 100644 --- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c +++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c @@ -267,6 +267,9 @@ static void exec_output_file_singlelayer(RenderData *rd, bNode *node, bNodeStack ibuf->rect_float = cbuf->rect; ibuf->dither = rd->dither_intensity; + /* OCIO_TODO: this is a part of legacy compositor, which likely would be removed before next release + * keep old color management flag untouched for now + */ if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) ibuf->profile = IB_PROFILE_LINEAR_RGB; diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h index 303d4094f8e..999fb24ba32 100644 --- a/source/blender/render/intern/include/render_result.h +++ b/source/blender/render/intern/include/render_result.h @@ -47,6 +47,8 @@ struct RenderLayer; struct RenderResult; struct Scene; struct rcti; +struct ColorManagedDisplaySettings; +struct ColorManagedViewSettings; /* New */ @@ -90,7 +92,9 @@ void render_result_rect_from_ibuf(struct RenderResult *rr, struct RenderData *rd void render_result_rect_fill_zero(struct RenderResult *rr); void render_result_rect_get_pixels(struct RenderResult *rr, struct RenderData *rd, - unsigned int *rect, int rectx, int recty); + unsigned int *rect, int rectx, int recty, + const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings); #endif /* __RENDER_RESULT_H__ */ diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index 26bd482af69..c6e225cfa0c 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -472,8 +472,7 @@ static void render_envmap(Render *re, EnvMap *env) ibuf = IMB_allocImBuf(envre->rectx, envre->recty, 24, IB_rect | IB_rectfloat); memcpy(ibuf->rect_float, rl->rectf, ibuf->channels * ibuf->x * ibuf->y * sizeof(float)); - if (re->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) - ibuf->profile = IB_PROFILE_LINEAR_RGB; + ibuf->profile = IB_PROFILE_LINEAR_RGB; /* envmap renders without alpha */ alpha = ibuf->rect_float + 3; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 7b0629063a6..069062b5bc6 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -334,7 +334,7 @@ void RE_ResultGet32(Render *re, unsigned int *rect) RenderResult rres; RE_AcquireResultImage(re, &rres); - render_result_rect_get_pixels(&rres, &re->r, rect, re->rectx, re->recty); + render_result_rect_get_pixels(&rres, &re->r, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings); RE_ReleaseResultImage(re); } @@ -1435,7 +1435,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) ntreeCompositTagRender(re->scene); ntreeCompositTagAnimated(ntree); - ntreeCompositExecTree(ntree, &re->r, 1, G.background == 0); + ntreeCompositExecTree(ntree, &re->r, 1, G.background == 0, &re->scene->view_settings, &re->scene->display_settings); } /* ensure we get either composited result or the active layer */ @@ -1599,7 +1599,7 @@ static void do_render_composite_fields_blur_3d(Render *re) if (re->r.scemode & R_FULL_SAMPLE) do_merge_fullsample(re, ntree); else { - ntreeCompositExecTree(ntree, &re->r, 1, G.background == 0); + ntreeCompositExecTree(ntree, &re->r, 1, G.background == 0, &re->scene->view_settings, &re->scene->display_settings); } ntree->stats_draw = NULL; @@ -1679,7 +1679,7 @@ static void do_render_seq(Render *re) ibuf = IMB_dupImBuf(out); IMB_freeImBuf(out); - IMB_colormanagement_imbuf_from_sequencer_space(ibuf); + BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf); recurs_depth--; @@ -2500,8 +2500,7 @@ int RE_WriteEnvmapResult(struct ReportList *reports, Scene *scene, EnvMap *env, return 0; } - if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) - ibuf->profile = IB_PROFILE_LINEAR_RGB; + IMB_display_buffer_to_imbuf_rect(ibuf, &scene->view_settings, &scene->display_settings); /* to save, we first get absolute path */ BLI_strncpy(filepath, relpath, sizeof(filepath)); diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 509266bdc33..b7019640544 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -50,6 +50,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "IMB_colormanagement.h" #include "intern/openexr/openexr_multi.h" @@ -1081,18 +1082,18 @@ ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd) /* float factor for random dither, imbuf takes care of it */ ibuf->dither = rd->dither_intensity; - /* prepare to gamma correct to sRGB color space */ - if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) { - /* sequence editor can generate 8bpc render buffers */ - if (ibuf->rect) { - ibuf->profile = IB_PROFILE_SRGB; - if (BKE_imtype_valid_depths(rd->im_format.imtype) & (R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_24 | R_IMF_CHAN_DEPTH_32)) - IMB_float_from_rect(ibuf); - } - else { - ibuf->profile = IB_PROFILE_LINEAR_RGB; + /* prepare to gamma correct to sRGB color space + * note that sequence editor can generate 8bpc render buffers + */ + if (ibuf->rect) { + ibuf->profile = IB_PROFILE_SRGB; + if (BKE_imtype_valid_depths(rd->im_format.imtype) & (R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_24 | R_IMF_CHAN_DEPTH_32)) { + IMB_colormanagement_imbuf_float_from_rect(ibuf); } } + else { + ibuf->profile = IB_PROFILE_LINEAR_RGB; + } /* color -> grayscale */ /* editing directly would alter the render view */ @@ -1145,19 +1146,17 @@ void render_result_rect_fill_zero(RenderResult *rr) rr->rect32 = MEM_callocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect"); } -void render_result_rect_get_pixels(RenderResult *rr, RenderData *rd, unsigned int *rect, int rectx, int recty) +void render_result_rect_get_pixels(RenderResult *rr, RenderData *rd, unsigned int *rect, int rectx, int recty, + const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { if (rr->rect32) { memcpy(rect, rr->rect32, sizeof(int) * rr->rectx * rr->recty); } else if (rr->rectf) { - int profile_from = (rd->color_mgt_flag & R_COLOR_MANAGEMENT) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB; int predivide = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE); - int dither = 0; - IMB_buffer_byte_from_float((unsigned char *)rect, rr->rectf, - 4, dither, IB_PROFILE_SRGB, profile_from, predivide, - rr->rectx, rr->recty, rr->rectx, rr->rectx); + IMB_display_buffer_transform_apply((unsigned char *) rect, rr->rectf, rr->rectx, rr->recty, 4, + view_settings, display_settings, predivide); } else /* else fill with black */ diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index cbe8cc81451..f7e3a9ddc39 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -50,6 +50,7 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "IMB_colormanagement.h" #include "BKE_colortools.h" #include "BKE_image.h" @@ -1224,8 +1225,8 @@ int multitex_nodes(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); /* don't linearize float buffers, assumed to be linear */ - if (ibuf && !(ibuf->rect_float) && R.r.color_mgt_flag & R_COLOR_MANAGEMENT) - srgb_to_linearrgb_v3_v3(&texres->tr, &texres->tr); + if (ibuf && !(ibuf->rect_float)) + IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace); } } else { @@ -2376,8 +2377,8 @@ void do_material_tex(ShadeInput *shi, Render *re) ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser); /* don't linearize float buffers, assumed to be linear */ - if (ibuf && !(ibuf->rect_float) && re->r.color_mgt_flag & R_COLOR_MANAGEMENT) - srgb_to_linearrgb_v3_v3(tcol, tcol); + if (ibuf && !(ibuf->rect_float)) + IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace); } if (mtex->mapto & MAP_COL) { @@ -2888,8 +2889,8 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4]) ImBuf *ibuf = BKE_image_get_ibuf(ima, &mtex->tex->iuser); /* don't linearize float buffers, assumed to be linear */ - if (ibuf && !(ibuf->rect_float) && R.r.color_mgt_flag & R_COLOR_MANAGEMENT) - srgb_to_linearrgb_v3_v3(&texres.tr, &texres.tr); + if (ibuf && !(ibuf->rect_float)) + IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace); } fact= texres.tin*mtex->colfac; @@ -3103,8 +3104,8 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser); /* don't linearize float buffers, assumed to be linear */ - if (ibuf && !(ibuf->rect_float) && R.r.color_mgt_flag & R_COLOR_MANAGEMENT) - srgb_to_linearrgb_v3_v3(tcol, tcol); + if (ibuf && !(ibuf->rect_float)) + IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace); } if (mtex->mapto & WOMAP_HORIZ) { @@ -3317,8 +3318,8 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser); /* don't linearize float buffers, assumed to be linear */ - if (ibuf && !(ibuf->rect_float) && R.r.color_mgt_flag & R_COLOR_MANAGEMENT) - srgb_to_linearrgb_v3_v3(&texres.tr, &texres.tr); + if (ibuf && !(ibuf->rect_float)) + IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace); } /* lamp colors were premultiplied with this */ diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index c009c7b7394..34ff4d63e99 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -62,6 +62,7 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "IMB_colormanagement.h" /* local include */ #include "rayintersection.h" @@ -1993,6 +1994,8 @@ typedef struct BakeShade { float dxco[3], dyco[3]; short *do_update; + + struct ColorSpace *rect_colorspace; } BakeShade; static void bake_set_shade_input(ObjectInstanceRen *obi, VlakRen *vlr, ShadeInput *shi, int quad, int UNUSED(isect), int x, int y, float u, float v) @@ -2168,8 +2171,12 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua else { unsigned char *col= (unsigned char *)(bs->rect + bs->rectx*y + x); - if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE) && (R.r.color_mgt_flag & R_COLOR_MANAGEMENT)) { - linearrgb_to_srgb_uchar3(col, shr.combined); + if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) { + float rgb[3]; + + copy_v3_v3(rgb, shr.combined); + IMB_colormanagement_scene_linear_to_colorspace_v3(rgb, bs->rect_colorspace); + rgb_float_to_uchar(col, rgb); } else { rgb_float_to_uchar(col, shr.combined); @@ -2503,6 +2510,7 @@ static void shade_tface(BakeShade *bs) bs->rectx= bs->ibuf->x; bs->recty= bs->ibuf->y; bs->rect= bs->ibuf->rect; + bs->rect_colorspace= bs->ibuf->rect_colorspace; bs->rect_float= bs->ibuf->rect_float; bs->quad= 0; diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index bbdcfbb5a73..d1d2c66985e 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -1325,7 +1325,14 @@ void shade_input_initialize(ShadeInput *shi, RenderPart *pa, RenderLayer *rl, in shi->sample = sample; shi->thread = pa->thread; shi->do_preview = (R.r.scemode & R_MATNODE_PREVIEW) != 0; - shi->do_manage = (R.r.color_mgt_flag & R_COLOR_MANAGEMENT); + + /* OCIO_TODO: for now assume color management is always enabled and vertes colors are in sRGB space + * probably would be nice to have this things configurable, but for now it should work + * also probably this flag could be removed (in separated commit) before the release + * since it's not actually meaningful anymore + */ + shi->do_manage = TRUE; + shi->lay = rl->lay; shi->layflag = rl->layflag; shi->passflag = rl->passflag; diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 48b552acf26..266b0d0357f 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -700,11 +700,11 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt) if (scene->camera) { ibuf = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2, - IB_rect, OB_SOLID, FALSE, err_out); + IB_rect, OB_SOLID, FALSE, FALSE, err_out); } else { ibuf = ED_view3d_draw_offscreen_imbuf(scene, v3d, ar, BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2, - IB_rect, FALSE, err_out); + IB_rect, FALSE, FALSE, err_out); } if (ibuf) { From ce3566a4cb3d328c646a2876b14530db9dc6a014 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 10 Sep 2012 14:47:47 +0000 Subject: [PATCH 127/160] Color Management: add View as Render to image datablocks This is need since some images (like normal maps, textures and so) would want to be viewed without any tone map applied on them. On the same time it's possible that some images would want to be affected by tone maps, and renders would always want to be affected by tone maps. After long discussion with Brecht we decided less painful and most clear way would be to simply add "View as Render" option to image datablocks. If this option is enabled for image, both settings from Display and Render blocks of color management settings would be applied on display. If this option is disabled, only display transform with default view and no exposure/gamma/curves would be applied. Render result and compositor viewers would always have "View as Render" enabled. There's separated setting when image is saving which says whether saved image should be affected by render part of color management settings. This option is enabled by default for render result/node viewer and disabled by default for all the rest images. This option wouldn't have affect when saving to float formats such as EXR. --- source/blender/blenkernel/intern/image.c | 3 + source/blender/blenloader/intern/readfile.c | 6 ++ source/blender/editors/include/ED_image.h | 2 +- .../editors/space_image/image_buttons.c | 1 + .../blender/editors/space_image/image_draw.c | 23 +++++-- .../blender/editors/space_image/image_ops.c | 37 ++++++++-- source/blender/editors/space_node/node_view.c | 2 +- .../editors/space_sequencer/sequencer_view.c | 2 +- source/blender/imbuf/intern/colormanagement.c | 67 +++++++++++++++++-- source/blender/makesdna/DNA_image_types.h | 1 + source/blender/makesrna/intern/rna_image.c | 5 ++ 11 files changed, 125 insertions(+), 24 deletions(-) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 3d1133b7475..f077fcfbfb3 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -246,6 +246,9 @@ static Image *image_alloc(const char *name, short source, short type) ima->source = source; ima->type = type; + if (source == IMA_SRC_VIEWER) + ima->flag |= IMA_VIEW_AS_RENDER; + BKE_color_managed_colorspace_settings_init(&ima->colorspace_settings); } return ima; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 115c14111a8..0428e88c539 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7926,6 +7926,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) /* color management pipeline changes compatibility code */ { Scene *scene; + Image *ima; for (scene = main->scene.first; scene; scene = scene->id.next) { if ((scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) == 0) { @@ -7936,6 +7937,11 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } } + + for (ima = main->image.first; ima; ima = ima->id.next) { + if (ima->source == IMA_SRC_VIEWER) + ima->flag |= IMA_VIEW_AS_RENDER; + } } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index 70fea4a45fb..8738c2a1a2c 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -80,7 +80,7 @@ int ED_space_image_maskedit_mask_poll(struct bContext *C); /* UI level image (texture) updating... render calls own stuff (too) */ void ED_image_update_frame(const struct Main *mainp, int cfra); -void ED_image_draw_info(struct Scene *scene, struct ARegion *ar, int color_manage, int channels, int x, int y, +void ED_image_draw_info(struct Scene *scene, struct ARegion *ar, int color_manage, int use_default_view, int channels, int x, int y, const unsigned char cp[4], const float fp[4], int *zp, float *zpf); #endif /* __ED_IMAGE_H__ */ diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 0b937e3054b..c372973b7b0 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -692,6 +692,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char col = uiLayoutColumn(layout, FALSE); uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings"); + uiItemR(col, &imaptr, "view_as_render", 0, NULL, ICON_NONE); if (ima->source != IMA_SRC_GENERATED) { if (compact == 0) { /* background image view doesnt need these */ diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 7603ba63980..638a2ac6681 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -94,7 +94,7 @@ static void draw_render_info(Scene *scene, Image *ima, ARegion *ar) } /* used by node view too */ -void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int channels, int x, int y, +void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_default_view, int channels, int x, int y, const unsigned char cp[4], const float fp[4], int *zp, float *zpf) { char str[256]; @@ -195,7 +195,10 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int channel if (color_manage && channels == 4) { float pixel[4]; - IMB_colormanagement_pixel_to_display_space_v4(pixel, fp, &scene->view_settings, &scene->display_settings); + if (use_default_view) + IMB_colormanagement_pixel_to_display_space_v4(pixel, fp, NULL, &scene->display_settings); + else + IMB_colormanagement_pixel_to_display_space_v4(pixel, fp, &scene->view_settings, &scene->display_settings); BLI_snprintf(str, sizeof(str), " | CM R:%-.4f G:%-.4f B:%-.4f", pixel[0], pixel[1], pixel[2]); BLF_position(blf_mono_font, dx, 6, 0); @@ -245,7 +248,10 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int channel } if (color_manage) { - IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, &scene->view_settings, &scene->display_settings); + if (use_default_view) + IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, NULL, &scene->display_settings); + else + IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, &scene->view_settings, &scene->display_settings); } else { copy_v4_v4(finalcol, col); @@ -491,7 +497,8 @@ static unsigned int *get_part_from_buffer(unsigned int *buffer, int width, short static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy) { - unsigned int *display_buffer, *rect; + unsigned char *display_buffer; + unsigned int *rect; int dx, dy, sx, sy, x, y; void *cache_handle; @@ -499,8 +506,10 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene, if (ima->xrep < 1) return; if (ima->yrep < 1) return; - display_buffer = (unsigned int *) IMB_display_buffer_acquire(ibuf, &scene->view_settings, - &scene->display_settings, &cache_handle); + if (ima->flag & IMA_VIEW_AS_RENDER) + display_buffer = IMB_display_buffer_acquire(ibuf, &scene->view_settings, &scene->display_settings, &cache_handle); + else + display_buffer = IMB_display_buffer_acquire(ibuf, NULL, &scene->display_settings, &cache_handle); if (!display_buffer) return; @@ -515,7 +524,7 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene, dy = ibuf->y / ima->yrep; sx = (sima->curtile % ima->xrep) * dx; sy = (sima->curtile / ima->xrep) * dy; - rect = get_part_from_buffer(display_buffer, ibuf->x, sx, sy, sx + dx, sy + dy); + rect = get_part_from_buffer((unsigned int*)display_buffer, ibuf->x, sx, sy, sx + dx, sy + dy); /* draw repeated */ for (sy = 0; sy + dy <= ibuf->y; sy += dy) { diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index f9ab458d26b..6ec852b703c 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1183,6 +1183,8 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima, static void save_image_options_from_op(SaveImageOptions *simopts, wmOperator *op) { if (op->customdata) { + BKE_color_managed_view_settings_free(&simopts->im_format.view_settings); + simopts->im_format = *(ImageFormatData *)op->customdata; } @@ -1195,13 +1197,15 @@ static void save_image_options_from_op(SaveImageOptions *simopts, wmOperator *op static void save_image_options_to_op(SaveImageOptions *simopts, wmOperator *op) { if (op->customdata) { + BKE_color_managed_view_settings_free(&((ImageFormatData *)op->customdata)->view_settings); + *(ImageFormatData *)op->customdata = simopts->im_format; } RNA_string_set(op->ptr, "filepath", simopts->filepath); } -static ImBuf *save_image_colormanaged_imbuf_acquire(ImBuf *ibuf, SaveImageOptions *simopts, void **cache_handle) +static ImBuf *save_image_colormanaged_imbuf_acquire(ImBuf *ibuf, SaveImageOptions *simopts, int save_as_render, void **cache_handle) { ImageFormatData *imf = &simopts->im_format; ImBuf *colormanaged_ibuf; @@ -1211,8 +1215,12 @@ static ImBuf *save_image_colormanaged_imbuf_acquire(ImBuf *ibuf, SaveImageOption do_colormanagement = !BKE_imtype_supports_float(imf->imtype); if (do_colormanagement) { - unsigned char *display_buffer = - IMB_display_buffer_acquire(ibuf, &imf->view_settings, &imf->display_settings, cache_handle); + unsigned char *display_buffer; + + if (save_as_render) + display_buffer = IMB_display_buffer_acquire(ibuf, &imf->view_settings, &imf->display_settings, cache_handle); + else + display_buffer = IMB_display_buffer_acquire(ibuf, NULL, &imf->display_settings, cache_handle); if (*cache_handle) { colormanaged_ibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, 0); @@ -1247,6 +1255,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI const char *relbase = ID_BLEND_PATH(CTX_data_main(C), &ima->id); const short relative = (RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path")); const short save_copy = (RNA_struct_find_property(op->ptr, "copy") && RNA_boolean_get(op->ptr, "copy")); + const short save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") && RNA_boolean_get(op->ptr, "save_as_render")); short ok = FALSE; /* old global to ensure a 2nd save goes to same dir */ @@ -1271,7 +1280,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI } } - colormanaged_ibuf = save_image_colormanaged_imbuf_acquire(ibuf, simopts, &cache_handle); + colormanaged_ibuf = save_image_colormanaged_imbuf_acquire(ibuf, simopts, save_as_render, &cache_handle); if (simopts->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) { Scene *scene = CTX_data_scene(C); @@ -1350,6 +1359,9 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI static void image_save_as_free(wmOperator *op) { if (op->customdata) { + ImageFormatData *im_format = (ImageFormatData *)op->customdata; + BKE_color_managed_view_settings_free(&im_format->view_settings); + MEM_freeN(op->customdata); op->customdata = NULL; } @@ -1402,6 +1414,11 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(eve RNA_boolean_set(op->ptr, "copy", TRUE); } + if (ima->source == IMA_SRC_VIEWER) + RNA_boolean_set(op->ptr, "save_as_render", TRUE); + else + RNA_boolean_set(op->ptr, "save_as_render", FALSE); + op->customdata = MEM_mallocN(sizeof(simopts.im_format), __func__); memcpy(op->customdata, &simopts.im_format, sizeof(simopts.im_format)); @@ -1437,7 +1454,7 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op) /* image template */ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &ptr); - uiTemplateImageSettings(layout, &ptr, TRUE); + uiTemplateImageSettings(layout, &ptr, FALSE); /* main draw call */ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); @@ -1465,6 +1482,7 @@ void IMAGE_OT_save_as(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ + RNA_def_boolean(ot->srna, "save_as_render", 0, "Save As Render", "Apply render part of display transform when saving byte image"); RNA_def_boolean(ot->srna, "copy", 0, "Copy", "Create a new image file without modifying the current image in blender"); WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE | MOVIEFILE, FILE_SPECIAL, FILE_SAVE, @@ -1989,6 +2007,7 @@ typedef struct ImageSampleInfo { int draw; int color_manage; + int use_default_view; } ImageSampleInfo; static void image_sample_draw(const bContext *C, ARegion *ar, void *arg_info) @@ -1997,7 +2016,8 @@ static void image_sample_draw(const bContext *C, ARegion *ar, void *arg_info) if (info->draw) { Scene *scene = CTX_data_scene(C); - ED_image_draw_info(scene, ar, info->color_manage, info->channels, info->x, info->y, info->colp, info->colfp, info->zp, info->zfp); + ED_image_draw_info(scene, ar, info->color_manage, info->use_default_view, info->channels, + info->x, info->y, info->colp, info->colfp, info->zp, info->zfp); } } @@ -2070,6 +2090,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) float *fp; unsigned char *cp; int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y); + Image *image = ED_space_image(sima); CLAMP(x, 0, ibuf->x - 1); CLAMP(y, 0, ibuf->y - 1); @@ -2083,7 +2104,9 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->colfp = NULL; info->zp = NULL; info->zfp = NULL; - + + info->use_default_view = (image->flag & IMA_VIEW_AS_RENDER) ? FALSE : TRUE; + if (ibuf->rect) { cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x); diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index e86d2b4eb5f..9e3a537fb5b 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -341,7 +341,7 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) ImageSampleInfo *info = arg_info; if (info->draw) { - ED_image_draw_info(scene, ar, info->color_manage, info->channels, + ED_image_draw_info(scene, ar, info->color_manage, FALSE, info->channels, info->x, info->y, info->col, info->colf, NULL, NULL /* zbuf - unused for nodes */ ); diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index af9ef34c2f2..c357a05936a 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -80,7 +80,7 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) ImageSampleInfo *info = arg_info; if (info->draw) { - ED_image_draw_info(scene, ar, info->color_manage, info->channels, + ED_image_draw_info(scene, ar, info->color_manage, FALSE, info->channels, info->x, info->y, info->colp, info->colfp, NULL, NULL); } } diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 8ce81053c77..d67536b65bd 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -635,9 +635,15 @@ static void display_transform_get_from_ctx(const bContext *C, ColorManagedViewSe ColorManagedDisplaySettings **display_settings_r) { Scene *scene = CTX_data_scene(C); + SpaceImage *sima = CTX_wm_space_image(C); *view_settings_r = &scene->view_settings; *display_settings_r = &scene->display_settings; + + if (sima) { + if ((sima->image->flag & IMA_VIEW_AS_RENDER) == 0) + *view_settings_r = NULL; + } } #ifdef WITH_OCIO @@ -801,6 +807,26 @@ static ConstProcessorRcPtr *display_to_scene_linear_processor(ColorManagedDispla return (ConstProcessorRcPtr *) display->to_scene_linear; } + +static void init_default_view_settings(const ColorManagedDisplaySettings *display_settings, + ColorManagedViewSettings *view_settings) +{ + ColorManagedDisplay *display; + ColorManagedView *default_view; + + display = colormanage_display_get_named(display_settings->display_device); + default_view = colormanage_view_get_default(display); + + if (default_view) + BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform)); + else + view_settings->view_transform[0] = '\0'; + + view_settings->flag = 0; + view_settings->gamma = 1.0f; + view_settings->exposure = 0.0f; + view_settings->curve_mapping = NULL; +} #endif static void curve_mapping_apply_pixel(CurveMapping *curve_mapping, float *pixel, int channels) @@ -1763,8 +1789,22 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet int buffer_size; ColormanageCacheViewSettings cache_view_settings; ColormanageCacheDisplaySettings cache_display_settings; + ColorManagedViewSettings default_view_settings; + const ColorManagedViewSettings *applied_view_settings; - colormanage_view_settings_to_cache(&cache_view_settings, view_settings); + if (view_settings) { + applied_view_settings = view_settings; + } + else { + /* if no view settings were specified, use default display transformation + * this happens for images which don't want to be displayed with render settings + */ + + init_default_view_settings(display_settings, &default_view_settings); + applied_view_settings = &default_view_settings; + } + + colormanage_view_settings_to_cache(&cache_view_settings, applied_view_settings); colormanage_display_settings_to_cache(&cache_display_settings, display_settings); BLI_lock_thread(LOCK_COLORMANAGE); @@ -1793,7 +1833,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet buffer_size = ibuf->channels * ibuf->x * ibuf->y * sizeof(float); display_buffer = MEM_callocN(buffer_size, "imbuf display buffer"); - colormanage_display_buffer_process(ibuf, display_buffer, view_settings, display_settings); + colormanage_display_buffer_process(ibuf, display_buffer, applied_view_settings, display_settings); colormanage_cache_put(ibuf, &cache_view_settings, &cache_display_settings, display_buffer, cache_handle); @@ -2415,12 +2455,25 @@ ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManag cm_processor = MEM_callocN(sizeof(ColormanageProcessor), "colormanagement processor"); #ifdef WITH_OCIO - cm_processor->processor = create_display_buffer_processor(view_settings->view_transform, display_settings->display_device, - view_settings->exposure, view_settings->gamma); + { + ColorManagedViewSettings default_view_settings; + const ColorManagedViewSettings *applied_view_settings; - if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) { - cm_processor->curve_mapping = curvemapping_copy(view_settings->curve_mapping); - curvemapping_premultiply(cm_processor->curve_mapping, FALSE); + if (view_settings) { + applied_view_settings = view_settings; + } + else { + init_default_view_settings(display_settings, &default_view_settings); + applied_view_settings = &default_view_settings; + } + + cm_processor->processor = create_display_buffer_processor(applied_view_settings->view_transform, display_settings->display_device, + applied_view_settings->exposure, applied_view_settings->gamma); + + if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) { + cm_processor->curve_mapping = curvemapping_copy(applied_view_settings->curve_mapping); + curvemapping_premultiply(cm_processor->curve_mapping, FALSE); + } } #else (void) view_settings; diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index a6f686d9e31..38058dbb699 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -127,6 +127,7 @@ typedef struct Image { #define IMA_CM_PREDIVIDE 256 #define IMA_USED_FOR_RENDER 512 #define IMA_USER_FRAME_IN_RANGE 1024 /* for image user, but these flags are mixed */ +#define IMA_VIEW_AS_RENDER 2048 /* Image.tpageflag */ #define IMA_TILES 1 diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index 0c3814f72d6..495d60df49c 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -513,6 +513,11 @@ static void rna_def_image(BlenderRNA *brna) "to avoid fringing for images with light backgrounds"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_free_update"); + prop = RNA_def_property(srna, "view_as_render", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_VIEW_AS_RENDER); + RNA_def_property_ui_text(prop, "View as Render", "Apply render part of display transformation when displaying this image on the screen"); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL); + prop = RNA_def_property(srna, "is_dirty", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_Image_dirty_get", NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); From 3e881745e58a4c93585b448f6750bccec35ffaa3 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 10 Sep 2012 16:30:15 +0000 Subject: [PATCH 128/160] Color Management: resolve TODOs related on HSV widgets --- .../editors/interface/interface_handlers.c | 30 ++++++++++--------- .../editors/interface/interface_widgets.c | 22 +++++++------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index a1a6e34f7b4..b47dc661e50 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -3163,8 +3163,10 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, ui_get_but_vectorf(but, rgb); - rgb_to_hsv_compat_v(rgb, hsv); + if (color_profile && (int)but->a1) + ui_block_to_display_space_v3(but->block, rgb); + rgb_to_hsv_compat_v(rgb, hsv); /* relative position within box */ x = ((float)mx_fl - but->rect.xmin) / BLI_RCT_SIZE_X(&but->rect); @@ -3200,19 +3202,16 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx, /* exception only for value strip - use the range set in but->min/max */ hsv[2] = y * (but->softmax - but->softmin) + but->softmin; - if (color_profile) { - /* OCIO_TODO: how to handle this situation? */ - hsv[2] = srgb_to_linearrgb(hsv[2]); - } - - if (hsv[2] > but->softmax) - hsv[2] = but->softmax; break; default: assert(!"invalid hsv type"); } hsv_to_rgb_v(hsv, rgb); + + if (color_profile && (int)but->a1) + ui_block_to_scene_linear_v3(but->block, rgb); + copy_v3_v3(data->vec, rgb); data->draglastx = mx; @@ -3235,6 +3234,10 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, wmNDOF } ui_get_but_vectorf(but, rgb); + + if (color_profile && (int)but->a1) + ui_block_to_display_space_v3(but->block, rgb); + rgb_to_hsv_compat_v(rgb, hsv); switch ((int)but->a1) { @@ -3265,17 +3268,16 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, wmNDOF /* exception only for value strip - use the range set in but->min/max */ hsv[2] += ndof->rx * sensitivity; - if (color_profile) { - /* OCIO_TODO: how to handle this situation? */ - hsv[2] = srgb_to_linearrgb(hsv[2]); - } - CLAMP(hsv[2], but->softmin, but->softmax); default: assert(!"invalid hsv type"); } - + hsv_to_rgb_v(hsv, rgb); + + if (color_profile && (int)but->a1) + ui_block_to_scene_linear_v3(but->block, rgb); + copy_v3_v3(data->vec, rgb); ui_set_but_vectorf(but, data->vec); } diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 522c567e27f..ee22393c08f 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1885,19 +1885,20 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, rcti *rect) /* color */ ui_get_but_vectorf(but, rgb); - copy_v3_v3(hsv, ui_block_hsv_get(but->block)); + /* copy_v3_v3(hsv, ui_block_hsv_get(but->block)); */ /* UNUSED */ + + rgb_to_hsv_compat_v(rgb, hsvo); + + if (color_profile) + ui_block_to_display_space_v3(but->block, rgb); + rgb_to_hsv_compat_v(rgb, hsv); - copy_v3_v3(hsvo, hsv); /* exception: if 'lock' is set * lock the value of the color wheel to 1. * Useful for color correction tools where you're only interested in hue. */ if (but->flag & UI_BUT_COLOR_LOCK) hsv[2] = 1.f; - else if (color_profile) { - /* OCIO_TODO: how to handle this situation? */ - hsv[2] = linearrgb_to_srgb(hsv[2]); - } hsv_to_rgb(0.f, 0.f, hsv[2], colcent, colcent + 1, colcent + 2); @@ -2142,14 +2143,13 @@ static void ui_draw_but_HSV_v(uiBut *but, rcti *rect) color_profile = FALSE; ui_get_but_vectorf(but, rgb); + + if (color_profile) + ui_block_to_display_space_v3(but->block, rgb); + rgb_to_hsv_v(rgb, hsv); v = hsv[2]; - if (color_profile) { - /* OCIO_TODO: how to handle this situation? */ - v = linearrgb_to_srgb(v); - } - /* map v from property range to [0,1] */ range = but->softmax - but->softmin; v = (v - but->softmin) / range; From 74885d1d8465fd6b941f09a194b484013ef097c0 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 10 Sep 2012 17:24:48 +0000 Subject: [PATCH 129/160] Color Management: port image stamp to new color management system Use the same approach as interface does by using default view which is supposed to be invertible to convert color from display space to scene linear. --- source/blender/blenfont/BLF_api.h | 3 +- source/blender/blenfont/CMakeLists.txt | 1 + source/blender/blenfont/SConscript | 2 +- source/blender/blenfont/intern/blf.c | 5 ++- source/blender/blenfont/intern/blf_font.c | 9 ++++-- .../blenfont/intern/blf_internal_types.h | 4 +-- source/blender/blenkernel/intern/image.c | 32 ++++++++++--------- source/blender/blenkernel/intern/image_gen.c | 6 +++- source/blender/imbuf/IMB_imbuf.h | 6 ++-- source/blender/imbuf/intern/rectop.c | 16 +++++----- 10 files changed, 48 insertions(+), 36 deletions(-) diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index 0732e02b5fc..ce10951d6ff 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -33,6 +33,7 @@ #define __BLF_API_H__ struct rctf; +struct ColorManagedDisplay; int BLF_init(int points, int dpi); void BLF_exit(void); @@ -151,7 +152,7 @@ void BLF_shadow_offset(int fontid, int x, int y); * * BLF_buffer(NULL, NULL, 0, 0, 0, FALSE); */ -void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int nch, int do_color_management); +void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int nch, struct ColorManagedDisplay *display); /* Set the color to be used for text. */ void BLF_buffer_col(int fontid, float r, float g, float b, float a); diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt index ebf9ff4db39..da60710a137 100644 --- a/source/blender/blenfont/CMakeLists.txt +++ b/source/blender/blenfont/CMakeLists.txt @@ -27,6 +27,7 @@ set(INC ../blenlib ../editors/include ../makesdna + ../imbuf ../../../intern/guardedalloc ) diff --git a/source/blender/blenfont/SConscript b/source/blender/blenfont/SConscript index c46960d2311..12badf2383b 100644 --- a/source/blender/blenfont/SConscript +++ b/source/blender/blenfont/SConscript @@ -4,7 +4,7 @@ Import ('env') sources = env.Glob('intern/*.c') -incs = '. intern #/intern/guardedalloc ../blenkernel ../blenlib ../makesdna ../editors/include' +incs = '. intern #/intern/guardedalloc ../blenkernel ../blenlib ../makesdna ,,/imbuf ../editors/include' incs += ' #/extern/glew/include' incs += ' ' + env['BF_FREETYPE_INC'] incs += ' ' + env['BF_GETTEXT_INC'] diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index d4739b37f93..92fcb576e7d 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -50,7 +50,6 @@ #include "blf_internal_types.h" #include "blf_internal.h" - /* Max number of font in memory. * Take care that now every font have a glyph cache per size/dpi, * so we don't need load the same font with different size, just @@ -746,7 +745,7 @@ void BLF_shadow_offset(int fontid, int x, int y) } } -void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int nch, int do_color_management) +void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int nch, struct ColorManagedDisplay *display) { FontBLF *font = BLF_get(fontid); @@ -756,7 +755,7 @@ void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int font->buf_info.w = w; font->buf_info.h = h; font->buf_info.ch = nch; - font->buf_info.do_color_management = do_color_management; + font->buf_info.display = display; } } diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index ab43804db8e..f4bfb22573b 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -53,6 +53,8 @@ #include "BIF_gl.h" #include "BLF_api.h" +#include "IMB_colormanagement.h" + #include "blf_internal_types.h" #include "blf_internal.h" @@ -245,11 +247,12 @@ void blf_font_buffer(FontBLF *font, const char *str) blf_font_ensure_ascii_table(font); /* another buffer specific call for color conversion */ - if (buf_info->do_color_management) { - srgb_to_linearrgb_v4(b_col_float, buf_info->col); + if (buf_info->display) { + copy_v4_v4(b_col_float, buf_info->col); + IMB_colormanagement_display_to_scene_linear_v3(b_col_float, buf_info->display); } else { - copy_v4_v4(b_col_float, buf_info->col); + srgb_to_linearrgb_v4(b_col_float, buf_info->col); } while (str[i]) { diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index 4c617da7583..1acc3dad4cf 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -145,8 +145,8 @@ typedef struct FontBufInfoBLF { /* number of channels. */ int ch; - /* is the float buffer linear */ - int do_color_management; + /* display device used for color management */ + struct ColorManagedDisplay *display; /* and the color, the alphas is get from the glyph! * color is srgb space */ diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index f077fcfbfb3..4e7b9db73e6 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1505,19 +1505,21 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec int x, y, y_ofs; float h_fixed; const int mono = blf_mono_font_render; // XXX + struct ColorManagedDisplay *display; + const char *display_device; /* this could be an argument if we want to operate on non linear float imbuf's * for now though this is only used for renders which use scene settings */ - /* OCIO_TODO: for now harcode sRGB to linearrgb conversion, need to be fixed ASAP */ - const int do_color_management = TRUE; - #define BUFF_MARGIN_X 2 #define BUFF_MARGIN_Y 1 if (!rect && !rectf) return; + display_device = scene->display_settings.display_device; + display = IMB_colormanagement_display_get_named(display_device); + stampdata(scene, camera, &stamp_data, 1); /* TODO, do_versions */ @@ -1527,7 +1529,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* set before return */ BLF_size(mono, scene->r.stamp_font_id, 72); - BLF_buffer(mono, rectf, rect, width, height, channels, do_color_management); + BLF_buffer(mono, rectf, rect, width, height, channels, display); BLF_buffer_col(mono, scene->r.fg_stamp[0], scene->r.fg_stamp[1], scene->r.fg_stamp[2], 1.0); pad = BLF_width_max(mono); @@ -1544,7 +1546,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec y -= h; /* also a little of space to the background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and draw the text. */ @@ -1561,7 +1563,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec y -= h; /* and space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); @@ -1577,7 +1579,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec y -= h; /* and space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); @@ -1593,7 +1595,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec y -= h; /* and space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); @@ -1608,7 +1610,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec BLF_width_and_height(mono, stamp_data.marker, &w, &h); h = h_fixed; /* extra space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ @@ -1624,7 +1626,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec BLF_width_and_height(mono, stamp_data.time, &w, &h); h = h_fixed; /* extra space for background */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, x - BUFF_MARGIN_X, y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ @@ -1639,7 +1641,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec BLF_width_and_height(mono, stamp_data.frame, &w, &h); h = h_fixed; /* extra space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ @@ -1654,7 +1656,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec BLF_width_and_height(mono, stamp_data.camera, &w, &h); h = h_fixed; /* extra space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.camera); @@ -1667,7 +1669,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec BLF_width_and_height(mono, stamp_data.cameralens, &w, &h); h = h_fixed; /* extra space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.cameralens); @@ -1680,7 +1682,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec x = width - w - 2; /* extra space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ @@ -1696,7 +1698,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec y = height - h; /* extra space for background. */ - buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management, + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c index 4d7013b9f73..37572eebed6 100644 --- a/source/blender/blenkernel/intern/image_gen.c +++ b/source/blender/blenkernel/intern/image_gen.c @@ -289,7 +289,11 @@ static void checker_board_text(unsigned char *rect, float *rect_float, int width BLF_size(mono, 54, 72); /* hard coded size! */ - BLF_buffer(mono, rect_float, rect, width, height, 4, TRUE); + /* OCIO_TODO: using NULL as display will assume using sRGB display + * this is correct since currently generated images are assumed to be in sRGB space, + * but this would probably needed to be fixed in some way + */ + BLF_buffer(mono, rect_float, rect, width, height, 4, NULL); for (y = 0; y < height; y += step) { text[1] = '1'; diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index d23d42ddd0c..71c8f197b0e 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -82,6 +82,8 @@ struct ImBuf; */ struct anim; +struct ColorManagedDisplay; + /** * * \attention Defined in allocimbuf.c @@ -478,12 +480,12 @@ void IMB_freezbuffloatImBuf(struct ImBuf *ibuf); * \attention Defined in rectop.c */ void IMB_rectfill(struct ImBuf *drect, const float col[4]); -void IMB_rectfill_area(struct ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2); +void IMB_rectfill_area(struct ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2, struct ColorManagedDisplay *display); void IMB_rectfill_alpha(struct ImBuf *ibuf, const float value); /* this should not be here, really, we needed it for operating on render data, IMB_rectfill_area calls it */ void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, - const float col[4], const int do_color_management, + const float col[4], struct ColorManagedDisplay *display, int x1, int y1, int x2, int y2); /* defined in metadata.c */ diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c index c3e23246638..a11f16d5669 100644 --- a/source/blender/imbuf/intern/rectop.c +++ b/source/blender/imbuf/intern/rectop.c @@ -42,6 +42,7 @@ #include "IMB_imbuf.h" #include "IMB_allocimbuf.h" +#include "IMB_colormanagement.h" /* blend modes */ @@ -486,7 +487,7 @@ void IMB_rectfill(struct ImBuf *drect, const float col[4]) void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, - const float col[4], const int do_color_management, + const float col[4], struct ColorManagedDisplay *display, int x1, int y1, int x2, int y2) { int i, j; @@ -553,11 +554,12 @@ void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, float col_conv[4]; float *pixel; - if (do_color_management) { - srgb_to_linearrgb_v4(col_conv, col); + if (display) { + copy_v4_v4(col_conv, col); + IMB_colormanagement_display_to_scene_linear_v3(col_conv, display); } else { - copy_v4_v4(col_conv, col); + srgb_to_linearrgb_v4(col_conv, col); } for (j = 0; j < y2 - y1; j++) { @@ -581,12 +583,10 @@ void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, } } -void IMB_rectfill_area(struct ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2) +void IMB_rectfill_area(struct ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2, struct ColorManagedDisplay *display) { - int do_color_management; if (!ibuf) return; - do_color_management = (ibuf->profile == IB_PROFILE_LINEAR_RGB); - buf_rectfill_area((unsigned char *) ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, col, do_color_management, + buf_rectfill_area((unsigned char *) ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, col, display, x1, y1, x2, y2); } From b4cac859e955c008c20683659e90f3fce62a7687 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 10 Sep 2012 17:38:48 +0000 Subject: [PATCH 130/160] Color management: get rid of hardcoded color space None --- source/blender/imbuf/intern/colormanagement.c | 16 ++++++---------- source/blender/makesrna/intern/rna_color.c | 11 +++++------ 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index d67536b65bd..086400ea9b1 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -904,9 +904,6 @@ static void colormanage_check_view_settings(ColorManagedDisplaySettings *display static void colormanage_check_colorspace_settings(ColorManagedColorspaceSettings *colorspace_settings, const char *what) { if (colorspace_settings->name[0] == '\0') { - BLI_strncpy(colorspace_settings->name, "NONE", sizeof(colorspace_settings->name)); - } - else if (!strcmp(colorspace_settings->name, "NONE")) { /* pass */ } else { @@ -916,7 +913,7 @@ static void colormanage_check_colorspace_settings(ColorManagedColorspaceSettings printf("Color management: %s colorspace \"%s\" not found, setting NONE instead.\n", what, colorspace_settings->name); - BLI_strncpy(colorspace_settings->name, "NONE", sizeof(colorspace_settings->name)); + BLI_strncpy(colorspace_settings->name, "", sizeof(colorspace_settings->name)); } } @@ -1375,7 +1372,7 @@ static void colormanagement_transform_ex(float *buffer, int width, int height, i { ColormanageProcessor *cm_processor; - if (!strcmp(from_colorspace, "NONE")) { + if (from_colorspace[0] == '\0') { return; } @@ -1416,7 +1413,7 @@ void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspac { ColormanageProcessor *cm_processor; - if (!strcmp(from_colorspace, "NONE")) { + if (from_colorspace[0] == '\0') { return; } @@ -1667,9 +1664,8 @@ void IMB_colormanagement_pixel_from_role_v4(float pixel[4], int role) void IMB_colormanagement_imbuf_assign_spaces(ImBuf *ibuf, ColorManagedColorspaceSettings *colorspace_settings) { #ifdef WITH_OCIO - /* OCIO_TODO: get rid of NONE color space */ if (colorspace_settings) { - if (colorspace_settings->name[0] == 0 || !strcmp(colorspace_settings->name, "NONE")) { + if (colorspace_settings->name[0] == '\0') { /* when opening new image, assign it's color space based on default roles */ if (ibuf->rect_float) @@ -2121,7 +2117,7 @@ const char *IMB_colormanagement_view_get_indexed_name(int index) return view->name; } - return "NONE"; + return NULL; } const char *IMB_colormanagement_view_get_default_name(const char *display_name) @@ -2225,7 +2221,7 @@ const char *IMB_colormanagement_colorspace_get_indexed_name(int index) return colorspace->name; } - return "NONE"; + return ""; } /*********************** RNA helper functions *************************/ diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 2ebac408b77..0edcad59577 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -37,11 +37,6 @@ #include "WM_api.h" #include "WM_types.h" -static EnumPropertyItem color_space_items[] = { - {0, "NONE", 0, "None", "Do not perform any color transform on load, treat colors as in scene linear space already"}, - {0, NULL, 0, NULL, NULL} -}; - #ifdef RNA_RUNTIME #include "RNA_access.h" @@ -461,7 +456,6 @@ static EnumPropertyItem *rna_ColorManagedColorspaceSettings_colorspace_itemf(bCo EnumPropertyItem *items = NULL; int totitem = 0; - RNA_enum_item_add(&items, &totitem, &color_space_items[0]); IMB_colormanagement_colorspace_items_add(&items, &totitem); RNA_enum_item_end(&items, &totitem); @@ -857,6 +851,11 @@ static void rna_def_colormanage(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem color_space_items[] = { + {0, "NONE", 0, "None", "Do not perform any color transform on load, treat colors as in scene linear space already"}, + {0, NULL, 0, NULL, NULL} + }; + /* ** Display Settings ** */ srna = RNA_def_struct(brna, "ColorManagedDisplaySettings", NULL); RNA_def_struct_ui_text(srna, "ColorManagedDisplaySettings", "Color management specific to display device"); From 96d20fe437363980101444b6a5c415e254eeda87 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 11 Sep 2012 07:56:47 +0000 Subject: [PATCH 131/160] Color Management: added check for invertibility of color spaces So now non-invertible color spaces can not be used as input color space for images and as working color space for sequencer. Currently have got two hard-coded families which are rrt and display. If color space belong to one of this families, it would be considered as non-invertible. Data color spaces are always considered invertible. If color space has got to_reference transformation, it'll be considered invertible. --- intern/opencolorio/ocio_capi.cpp | 28 ++++++++++++++++++- intern/opencolorio/ocio_capi.h | 2 ++ release/datafiles/colormanagement/config.ocio | 6 ++-- .../imbuf/intern/IMB_colormanagement_intern.h | 4 ++- source/blender/imbuf/intern/colormanagement.c | 11 ++++++-- 5 files changed, 44 insertions(+), 7 deletions(-) diff --git a/intern/opencolorio/ocio_capi.cpp b/intern/opencolorio/ocio_capi.cpp index 6fb719dfc35..ec8012cc30f 100644 --- a/intern/opencolorio/ocio_capi.cpp +++ b/intern/opencolorio/ocio_capi.cpp @@ -19,12 +19,14 @@ * All rights reserved. * * Contributor(s): Xavier Thomas - * Lukas Toene + * Lukas Toene, + * Sergey Sharybin * * ***** END GPL LICENSE BLOCK ***** */ #include +#include #include @@ -264,6 +266,30 @@ const char *OCIO_configGetDisplayColorSpaceName(ConstConfigRcPtr *config, const return NULL; } +int OCIO_colorSpaceIsInvertible(ConstColorSpaceRcPtr *cs) +{ + const char *family = (*cs)->getFamily(); + + if (!strcmp(family, "rrt") || !strcmp(family, "display")) { + /* assume display and rrt transformations are not invertible + * in fact some of them could be, but it doesn't make much sense to allow use them as invertible + */ + return false; + } + + if ((*cs)->isData()) { + /* data color spaces don't have transformation at all */ + return true; + } + + if ((*cs)->getTransform(COLORSPACE_DIR_TO_REFERENCE)) { + /* if there's defined transform to reference space, color space could be converted to scene linear */ + return true; + } + + return true; +} + void OCIO_colorSpaceRelease(ConstColorSpaceRcPtr *cs) { MEM_DELETE(cs, ConstColorSpaceRcPtr); diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index 11973bcadf0..f0edd25ac14 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -71,6 +71,8 @@ const char *OCIO_configGetColorSpaceNameByIndex(ConstConfigRcPtr *config, int in ConstColorSpaceRcPtr *OCIO_configGetColorSpace(ConstConfigRcPtr *config, const char *name); int OCIO_configGetIndexForColorSpace(ConstConfigRcPtr *config, const char *name); +int OCIO_colorSpaceIsInvertible(ConstColorSpaceRcPtr *cs); + void OCIO_colorSpaceRelease(ConstColorSpaceRcPtr *cs); const char *OCIO_configGetDefaultDisplay(ConstConfigRcPtr *config); diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio index e8fb03b6f8e..7eb406803ac 100644 --- a/release/datafiles/colormanagement/config.ocio +++ b/release/datafiles/colormanagement/config.ocio @@ -120,7 +120,7 @@ colorspaces: - ! name: nuke_rec709 - family: + family: display equalitygroup: bitdepth: 32f description: | @@ -186,7 +186,7 @@ colorspaces: - ! name: dci_xyz - family: + family: display equalitygroup: bitdepth: 16f description: | @@ -216,7 +216,7 @@ colorspaces: - ! name: srgb8 - family: srgb + family: display equalitygroup: bitdepth: 8ui description: | diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index 8dd02b97093..293314c3ccd 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -45,6 +45,8 @@ typedef struct ColorSpace { struct ConstProcessorRcPtr *to_scene_linear; struct ConstProcessorRcPtr *from_scene_linear; + + int is_invertible; } ColorSpace; typedef struct ColorManagedDisplay { @@ -76,7 +78,7 @@ struct ColorManagedView *colormanage_view_add(const char *name); struct ColorManagedView *colormanage_view_get_indexed(int index); struct ColorManagedView *colormanage_view_get_named(const char *name); -struct ColorSpace *colormanage_colorspace_add(const char *name, const char *description); +struct ColorSpace *colormanage_colorspace_add(const char *name, const char *description, int is_invertible); struct ColorSpace *colormanage_colorspace_get_named(const char *name); struct ColorSpace *colormanage_colorspace_get_indexed(int index); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 086400ea9b1..189071a763e 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -466,13 +466,15 @@ static void colormanage_load_config(ConstConfigRcPtr *config) for (index = 0 ; index < tot_colorspace; index++) { ConstColorSpaceRcPtr *ocio_colorspace; const char *description; + int is_invertible; name = OCIO_configGetColorSpaceNameByIndex(config, index); ocio_colorspace = OCIO_configGetColorSpace(config, name); description = OCIO_colorSpaceGetDescription(ocio_colorspace); + is_invertible = OCIO_colorSpaceIsInvertible(ocio_colorspace); - colormanage_colorspace_add(name, description); + colormanage_colorspace_add(name, description, is_invertible); OCIO_colorSpaceRelease(ocio_colorspace); } @@ -2158,7 +2160,7 @@ static void colormanage_description_strip(char *description) } } -ColorSpace *colormanage_colorspace_add(const char *name, const char *description) +ColorSpace *colormanage_colorspace_add(const char *name, const char *description, int is_invertible) { ColorSpace *colorspace; @@ -2173,6 +2175,8 @@ ColorSpace *colormanage_colorspace_add(const char *name, const char *description colormanage_description_strip(colorspace->description); } + colorspace->is_invertible = is_invertible; + BLI_addtail(&global_colorspaces, colorspace); global_tot_colorspace++; @@ -2279,6 +2283,9 @@ void IMB_colormanagement_colorspace_items_add(EnumPropertyItem **items, int *tot for (colorspace = global_colorspaces.first; colorspace; colorspace = colorspace->next) { EnumPropertyItem item; + if (!colorspace->is_invertible) + continue; + item.value = colorspace->index; item.name = colorspace->name; item.identifier = colorspace->name; From 07082fb7d0506284108060479472e7126af5c087 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 11 Sep 2012 09:07:46 +0000 Subject: [PATCH 132/160] Color Management: color space cleanup Hide all meaningless for Blender input color spaces and made naming for rest of them to match Blender's interface better. Not sure if we'll need to support logarithmic color space as input. Renamed P3DCI to DCI-P3 which seems to be more common naming. Also added Film view for DCI-P3 display. --- release/datafiles/colormanagement/config.ocio | 61 +- .../luts/colorworks_filmlg_to_p3.3dl | 4916 +++++++++++++++++ source/blender/imbuf/intern/colormanagement.c | 23 +- 3 files changed, 4973 insertions(+), 27 deletions(-) create mode 100644 release/datafiles/colormanagement/luts/colorworks_filmlg_to_p3.3dl diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio index 7eb406803ac..121c5b2055c 100644 --- a/release/datafiles/colormanagement/config.ocio +++ b/release/datafiles/colormanagement/config.ocio @@ -11,53 +11,54 @@ luma: [0.2126, 0.7152, 0.0722] description: RRT version ut33 roles: - reference: aces + reference: Linear ACES # Internal scene linear space - scene_linear: rec709 + scene_linear: Linear # Default color space for byte image default_byte: sRGB # Default color space for float images - default_float: rec709 + default_float: Linear # Default color space sequencer is working in default_sequencer: sRGB # Color spaces for color picking and exture painting (not internally supported yet) - color_picking: raw - texture_paint: raw + color_picking: Raw + texture_paint: Raw displays: sRGB: - ! {name: Default, colorspace: sRGB} - ! {name: RRT, colorspace: rrt_srgb} - ! {name: Film, colorspace: srgb8} - - ! {name: Raw, colorspace: raw} + - ! {name: Raw, colorspace: Raw} - ! {name: Log, colorspace: lg10} - P3DCI: + DCI-P3: - ! {name: RRT, colorspace: rrt_p3dci} - - ! {name: Raw, colorspace: raw} + - ! {name: Film, colorspace: p3dci8} + - ! {name: Raw, colorspace: Raw} - ! {name: Log, colorspace: adx10} Rec709: - ! {name: Default, colorspace: nuke_rec709} - ! {name: RRT, colorspace: rrt_rec709} XYZ: - - ! {name: Default, colorspace: xyz} + - ! {name: Default, colorspace: XYZ} - ! {name: RRT, colorspace: rrt_xyz} - ! {name: DCI, colorspace: dci_xyz} - - ! {name: Raw, colorspace: raw} + - ! {name: Raw, colorspace: Raw} - ! {name: Log, colorspace: adx10} None: - ! {name: Default, colorspace: raw} -active_displays: [sRGB, P3DCI, Rec709, XYZ, None] +active_displays: [sRGB, DCIP3, Rec709, XYZ, None] active_views: [Default, RRT, Raw, Log] colorspaces: - ! - name: aces + name: Linear ACES family: aces equalitygroup: bitdepth: 32f @@ -66,7 +67,7 @@ colorspaces: allocationvars: [-8.5, 5] - ! - name: raw + name: Raw family: raw equalitygroup: bitdepth: 32f @@ -76,7 +77,7 @@ colorspaces: - ! name: adx10 - family: adx + family: display equalitygroup: bitdepth: 10ui description: | @@ -94,12 +95,12 @@ colorspaces: - ! {src: adx_exp_to_aces.spimtx} - ! - name: rec709 + name: Linear family: equalitygroup: bitdepth: 32f description: | - Rec. 709 (Full Range), Blender native internal space + Rec. 709 (Full Range), Blender native linear space isdata: false allocation: uniform allocationvars: [-0.125, 1.125] @@ -160,7 +161,7 @@ colorspaces: - ! {src: rrt_ut33_p3dci.spi3d, interpolation: tetrahedral} - ! - name: xyz + name: XYZ family: equalitygroup: bitdepth: 32f @@ -202,11 +203,11 @@ colorspaces: - ! name: lg10 - family: lg + family: display equalitygroup: bitdepth: 10ui description: | - lg10 : conversion from film log + conversion from film log isdata: false allocation: uniform to_reference: ! @@ -220,12 +221,12 @@ colorspaces: equalitygroup: bitdepth: 8ui description: | - srgb8 :rgb display space for the srgb standard. + RGB display space for the sRGB standard. isdata: false allocation: uniform from_reference: ! children: - - ! {src: aces, dst: lg10} + - ! {src: Linear ACES, dst: lg10} - ! {src: spi_ocio_srgb_test.spi3d, interpolation: linear} - ! @@ -244,12 +245,12 @@ colorspaces: - ! {src: rec709_to_aces.spimtx, interpolation: nearest} - ! - name: vd16 + name: VD16 family: vd equalitygroup: bitdepth: 16ui description: | - vd16 : The simple video conversion from a gamma 2.2 srgb space + The simple video conversion from a gamma 2.2 sRGB space isdata: false allocation: uniform to_reference: ! @@ -267,3 +268,17 @@ colorspaces: isdata: true allocation: uniform allocationvars: [0, 1] + + - ! + name: p3dci8 + family: display + equalitygroup: + bitdepth: 8ui + description: | + p3dci8 :rgb display space for gamma 2.6 P3 projection. + isdata: false + allocation: uniform + from_reference: ! + children: + - ! {src: Linear ACES, dst: lg10} + - ! {src: colorworks_filmlg_to_p3.3dl, interpolation: linear} diff --git a/release/datafiles/colormanagement/luts/colorworks_filmlg_to_p3.3dl b/release/datafiles/colormanagement/luts/colorworks_filmlg_to_p3.3dl new file mode 100644 index 00000000000..db936eb7ce4 --- /dev/null +++ b/release/datafiles/colormanagement/luts/colorworks_filmlg_to_p3.3dl @@ -0,0 +1,4916 @@ +# Autodesk 3D Export from Truelight v3.0 + 0 64 128 192 256 320 384 448 512 576 640 704 768 832 896 960 1023 + 0 0 0 + 0 0 0 + 0 0 0 + 0 0 0 + 0 0 100 + 0 0 274 + 0 0 608 + 0 0 785 + 0 0 1010 + 0 0 1183 + 0 0 1349 + 0 0 1471 + 0 0 1638 + 0 0 1854 + 0 65 1989 + 0 451 2073 + 0 722 2132 + 0 0 0 + 0 0 0 + 0 0 0 + 0 0 0 + 0 0 303 + 0 0 419 + 0 0 656 + 0 0 846 + 0 0 1071 + 0 0 1250 + 0 0 1419 + 0 0 1549 + 0 0 1714 + 0 0 1920 + 0 146 2048 + 0 543 2129 + 0 820 2186 + 0 0 0 + 0 0 0 + 0 0 0 + 0 0 187 + 0 15 337 + 0 64 462 + 0 110 709 + 0 137 910 + 0 54 1141 + 0 140 1323 + 0 0 1500 + 0 21 1637 + 0 200 1797 + 0 470 1986 + 0 658 2106 + 0 813 2183 + 0 922 2238 + 0 13 0 + 0 82 0 + 0 134 0 + 0 132 235 + 0 199 382 + 0 224 503 + 0 275 764 + 0 306 981 + 0 304 1215 + 0 336 1407 + 0 293 1596 + 0 297 1733 + 0 478 1887 + 0 698 2060 + 0 847 2172 + 0 953 2246 + 0 1026 2297 + 0 209 0 + 0 250 0 + 0 277 194 + 0 283 274 + 0 314 420 + 0 353 552 + 0 396 822 + 0 438 1050 + 0 458 1290 + 0 491 1488 + 0 493 1691 + 0 519 1824 + 0 631 1965 + 0 837 2125 + 0 974 2234 + 0 1060 2301 + 0 1120 2349 + 0 283 0 + 0 349 133 + 0 381 230 + 0 374 307 + 0 423 467 + 0 444 600 + 0 513 884 + 0 560 1135 + 0 597 1382 + 0 635 1589 + 0 663 1806 + 0 695 1940 + 0 794 2067 + 0 985 2214 + 0 1105 2307 + 0 1180 2364 + 0 1232 2405 + 0 541 0 + 0 567 211 + 0 599 297 + 0 612 366 + 0 657 537 + 0 692 692 + 0 741 972 + 0 789 1230 + 0 827 1487 + 0 871 1702 + 0 913 1916 + 0 946 2055 + 0 1029 2178 + 0 1178 2303 + 0 1271 2382 + 0 1329 2431 + 0 1370 2465 + 0 688 0 + 0 718 268 + 0 746 339 + 0 764 408 + 0 816 589 + 0 865 753 + 0 935 1052 + 0 995 1324 + 0 1046 1595 + 0 1094 1814 + 0 1142 2037 + 0 1172 2173 + 0 1238 2283 + 0 1354 2387 + 0 1434 2455 + 0 1484 2497 + 0 1519 2527 + 0 934 0 + 0 955 310 + 0 985 400 + 0 1018 469 + 0 1064 643 + 0 1117 831 + 0 1200 1141 + 0 1267 1425 + 0 1334 1721 + 0 1379 1936 + 0 1437 2154 + 0 1454 2293 + 0 1504 2395 + 0 1577 2473 + 0 1631 2527 + 0 1670 2565 + 0 1698 2592 + 0 1117 0 + 0 1142 341 + 0 1173 435 + 0 1210 510 + 0 1256 689 + 0 1311 885 + 0 1393 1206 + 0 1470 1498 + 0 1545 1799 + 0 1594 2023 + 0 1649 2233 + 0 1673 2377 + 0 1710 2480 + 0 1767 2556 + 0 1803 2603 + 0 1825 2632 + 0 1845 2654 + 0 1309 125 + 0 1326 356 + 0 1357 457 + 0 1397 541 + 0 1443 720 + 0 1503 922 + 0 1593 1264 + 0 1677 1570 + 0 1760 1877 + 0 1804 2104 + 0 1850 2318 + 0 1875 2459 + 0 1903 2558 + 0 1938 2626 + 0 1960 2668 + 0 1973 2694 + 0 1987 2714 + 0 1399 171 + 0 1421 375 + 0 1450 478 + 0 1487 570 + 0 1540 771 + 0 1603 976 + 0 1692 1312 + 0 1776 1619 + 0 1849 1918 + 0 1897 2144 + 0 1943 2359 + 0 1969 2493 + 0 1995 2592 + 0 2027 2659 + 0 2048 2701 + 0 2061 2728 + 0 2071 2746 + 0 1496 237 + 0 1525 435 + 0 1558 553 + 0 1595 666 + 0 1657 898 + 0 1715 1099 + 0 1804 1426 + 0 1882 1722 + 0 1949 2011 + 0 1993 2226 + 0 2035 2428 + 0 2062 2551 + 0 2087 2636 + 0 2118 2701 + 0 2138 2744 + 0 2151 2770 + 0 2159 2788 + 0 1593 308 + 0 1628 505 + 0 1670 650 + 0 1711 789 + 0 1778 1055 + 0 1835 1260 + 0 1918 1572 + 0 1989 1851 + 0 2049 2127 + 0 2090 2329 + 0 2124 2509 + 0 2152 2617 + 0 2177 2702 + 0 2205 2749 + 0 2224 2790 + 0 2237 2816 + 0 2246 2835 + 0 1653 352 + 0 1693 549 + 0 1740 711 + 0 1784 866 + 0 1851 1140 + 0 1912 1367 + 0 1991 1667 + 0 2058 1939 + 0 2111 2199 + 0 2150 2394 + 0 2180 2560 + 0 2208 2664 + 0 2234 2743 + 0 2261 2790 + 0 2278 2819 + 0 2291 2846 + 0 2300 2864 + 0 1692 380 + 0 1734 577 + 0 1784 750 + 0 1831 915 + 0 1898 1195 + 0 1961 1435 + 0 2038 1727 + 0 2102 1996 + 0 2153 2249 + 0 2189 2435 + 0 2216 2594 + 0 2244 2697 + 0 2270 2769 + 0 2297 2816 + 0 2315 2846 + 0 2325 2864 + 0 2334 2883 + 0 1720 400 + 0 1763 597 + 0 1816 778 + 0 1864 950 + 0 1932 1234 + 0 1996 1484 + 0 2071 1771 + 0 2134 2037 + 0 2184 2287 + 0 2217 2468 + 0 2244 2623 + 0 2269 2720 + 0 2296 2788 + 0 2323 2835 + 0 2341 2865 + 0 2351 2883 + 0 2359 2896 + 0 0 0 + 0 0 0 + 0 0 0 + 0 0 0 + 0 0 262 + 0 0 380 + 0 0 627 + 0 0 807 + 0 0 1028 + 0 0 1205 + 0 0 1371 + 0 0 1498 + 0 0 1670 + 0 0 1892 + 0 83 2030 + 0 473 2117 + 0 745 2176 + 0 0 0 + 0 0 0 + 0 0 0 + 0 0 144 + 0 0 330 + 0 0 455 + 0 0 665 + 0 0 864 + 0 0 1085 + 0 0 1272 + 0 0 1439 + 0 0 1577 + 0 0 1748 + 0 0 1956 + 0 158 2086 + 0 557 2170 + 0 835 2227 + 0 0 0 + 0 0 0 + 0 0 0 + 0 11 223 + 0 68 364 + 0 110 499 + 0 130 711 + 0 145 928 + 0 104 1155 + 0 93 1348 + 0 0 1520 + 0 0 1665 + 0 23 1832 + 0 296 2025 + 0 530 2147 + 0 789 2226 + 0 933 2281 + 0 101 0 + 0 130 0 + 0 155 118 + 0 180 265 + 0 223 405 + 0 251 546 + 0 288 771 + 0 313 1004 + 0 328 1235 + 0 337 1436 + 0 334 1617 + 0 343 1760 + 0 484 1920 + 0 709 2098 + 0 861 2213 + 0 968 2288 + 0 1042 2341 + 0 265 0 + 0 285 0 + 0 296 205 + 0 318 305 + 0 342 442 + 0 382 596 + 0 415 833 + 0 454 1074 + 0 478 1312 + 0 502 1522 + 0 514 1712 + 0 538 1854 + 0 647 2000 + 0 854 2164 + 0 995 2275 + 0 1083 2344 + 0 1144 2392 + 0 368 0 + 0 406 134 + 0 431 255 + 0 441 343 + 0 479 493 + 0 507 645 + 0 561 901 + 0 602 1159 + 0 638 1406 + 0 671 1627 + 0 701 1827 + 0 732 1970 + 0 832 2104 + 0 1022 2256 + 0 1140 2350 + 0 1214 2409 + 0 1266 2450 + 0 584 0 + 0 598 210 + 0 613 305 + 0 636 394 + 0 670 548 + 0 710 722 + 0 759 985 + 0 811 1253 + 0 857 1511 + 0 900 1744 + 0 940 1941 + 0 971 2087 + 0 1055 2215 + 0 1210 2344 + 0 1307 2425 + 0 1368 2475 + 0 1409 2510 + 0 737 0 + 0 763 266 + 0 790 354 + 0 812 441 + 0 861 609 + 0 910 787 + 0 979 1069 + 0 1041 1351 + 0 1095 1621 + 0 1142 1854 + 0 1185 2061 + 0 1218 2207 + 0 1288 2322 + 0 1407 2430 + 0 1489 2501 + 0 1539 2545 + 0 1575 2576 + 0 982 0 + 0 997 304 + 0 1021 399 + 0 1054 493 + 0 1102 660 + 0 1158 861 + 0 1233 1154 + 0 1302 1446 + 0 1366 1736 + 0 1416 1969 + 0 1467 2173 + 0 1491 2324 + 0 1546 2435 + 0 1627 2521 + 0 1684 2578 + 0 1725 2616 + 0 1754 2643 + 0 1177 0 + 0 1199 333 + 0 1227 430 + 0 1262 530 + 0 1311 705 + 0 1369 916 + 0 1447 1220 + 0 1527 1525 + 0 1597 1817 + 0 1654 2063 + 0 1700 2262 + 0 1729 2416 + 0 1770 2526 + 0 1827 2605 + 0 1864 2654 + 0 1886 2684 + 0 1907 2707 + 0 1367 109 + 0 1378 347 + 0 1402 454 + 0 1442 560 + 0 1493 744 + 0 1556 962 + 0 1640 1279 + 0 1722 1592 + 0 1796 1889 + 0 1846 2133 + 0 1888 2341 + 0 1917 2490 + 0 1951 2596 + 0 1995 2669 + 0 2022 2715 + 0 2039 2743 + 0 2054 2764 + 0 1475 156 + 0 1495 364 + 0 1521 474 + 0 1557 590 + 0 1613 790 + 0 1679 1013 + 0 1760 1332 + 0 1841 1648 + 0 1911 1940 + 0 1968 2183 + 0 2009 2391 + 0 2038 2539 + 0 2066 2642 + 0 2097 2709 + 0 2119 2752 + 0 2136 2780 + 0 2147 2799 + 0 1581 222 + 0 1609 424 + 0 1641 549 + 0 1679 688 + 0 1740 910 + 0 1802 1138 + 0 1883 1447 + 0 1957 1753 + 0 2024 2039 + 0 2078 2270 + 0 2117 2466 + 0 2144 2600 + 0 2171 2693 + 0 2202 2758 + 0 2221 2799 + 0 2234 2825 + 0 2242 2843 + 0 1683 292 + 0 1715 495 + 0 1753 648 + 0 1798 810 + 0 1865 1066 + 0 1925 1298 + 0 2001 1598 + 0 2067 1883 + 0 2129 2157 + 0 2179 2373 + 0 2214 2551 + 0 2240 2665 + 0 2267 2757 + 0 2294 2806 + 0 2313 2847 + 0 2326 2873 + 0 2334 2891 + 0 1746 336 + 0 1781 539 + 0 1824 710 + 0 1873 887 + 0 1941 1156 + 0 2004 1400 + 0 2076 1696 + 0 2139 1972 + 0 2195 2231 + 0 2242 2438 + 0 2275 2604 + 0 2301 2713 + 0 2327 2798 + 0 2354 2846 + 0 2371 2877 + 0 2383 2902 + 0 2392 2921 + 0 1787 364 + 0 1823 567 + 0 1869 750 + 0 1921 936 + 0 1991 1213 + 0 2054 1465 + 0 2125 1759 + 0 2185 2030 + 0 2238 2282 + 0 2282 2480 + 0 2315 2640 + 0 2340 2747 + 0 2366 2823 + 0 2393 2872 + 0 2409 2902 + 0 2420 2921 + 0 2428 2940 + 0 1815 384 + 0 1853 587 + 0 1901 778 + 0 1955 972 + 0 2025 1253 + 0 2089 1513 + 0 2159 1803 + 0 2218 2072 + 0 2270 2320 + 0 2311 2513 + 0 2343 2669 + 0 2367 2771 + 0 2392 2842 + 0 2419 2891 + 0 2436 2921 + 0 2447 2940 + 0 2454 2953 + 0 0 0 + 0 0 0 + 0 0 0 + 0 0 0 + 0 0 289 + 0 0 409 + 0 0 649 + 0 0 830 + 0 0 1052 + 0 0 1228 + 0 0 1396 + 0 0 1525 + 0 0 1703 + 0 0 1932 + 0 113 2074 + 0 506 2162 + 0 781 2223 + 0 0 0 + 0 0 0 + 0 0 0 + 0 0 201 + 0 0 344 + 0 0 476 + 0 0 679 + 0 0 885 + 0 0 1108 + 0 0 1298 + 0 0 1466 + 0 0 1609 + 0 0 1786 + 0 0 2002 + 0 184 2135 + 0 587 2219 + 0 868 2278 + 0 0 0 + 0 0 0 + 0 12 0 + 0 60 242 + 0 81 369 + 0 131 525 + 0 131 711 + 0 137 949 + 0 77 1174 + 0 0 1374 + 0 0 1545 + 0 0 1696 + 0 0 1870 + 0 0 2071 + 0 263 2196 + 0 676 2276 + 0 964 2333 + 0 163 0 + 0 170 0 + 0 170 75 + 0 210 281 + 0 235 410 + 0 265 577 + 0 296 776 + 0 313 1030 + 0 338 1259 + 0 334 1466 + 0 345 1644 + 0 365 1791 + 0 489 1959 + 0 728 2144 + 0 887 2261 + 0 997 2338 + 0 1075 2392 + 152 295 0 + 0 309 0 + 0 297 200 + 0 334 320 + 0 345 440 + 0 400 631 + 0 417 843 + 0 462 1100 + 0 486 1341 + 0 506 1557 + 0 524 1740 + 0 551 1887 + 0 661 2038 + 0 880 2210 + 0 1027 2324 + 0 1119 2394 + 0 1183 2444 + 194 400 0 + 132 437 142 + 0 469 260 + 0 479 360 + 0 514 502 + 0 548 676 + 0 597 920 + 0 636 1187 + 0 671 1436 + 0 706 1668 + 0 732 1858 + 0 764 2005 + 0 869 2146 + 0 1067 2303 + 0 1188 2400 + 0 1263 2461 + 0 1315 2503 + 228 627 0 + 144 633 212 + 0 625 305 + 0 658 411 + 0 680 546 + 0 730 749 + 0 775 999 + 0 837 1278 + 0 886 1540 + 0 930 1787 + 0 968 1976 + 0 999 2123 + 0 1087 2258 + 0 1253 2392 + 0 1355 2475 + 0 1419 2526 + 0 1464 2562 + 274 784 0 + 150 810 265 + 0 838 355 + 0 861 461 + 0 909 622 + 0 958 816 + 0 1025 1087 + 0 1091 1383 + 0 1145 1654 + 0 1193 1898 + 0 1232 2095 + 0 1266 2250 + 0 1342 2371 + 0 1469 2482 + 0 1553 2556 + 0 1606 2601 + 0 1642 2634 + 233 1034 0 + 0 1047 301 + 0 1064 393 + 0 1102 508 + 0 1149 664 + 0 1208 888 + 0 1277 1170 + 0 1346 1472 + 0 1419 1766 + 0 1465 2009 + 0 1513 2207 + 0 1540 2362 + 0 1599 2485 + 0 1687 2577 + 0 1748 2636 + 0 1792 2675 + 0 1823 2702 + 0 1236 5 + 0 1258 326 + 0 1282 421 + 0 1320 544 + 0 1368 716 + 0 1433 946 + 0 1507 1236 + 0 1590 1558 + 0 1657 1844 + 0 1718 2106 + 0 1757 2301 + 0 1789 2459 + 0 1835 2577 + 0 1900 2659 + 0 1939 2709 + 0 1963 2741 + 0 1987 2765 + 0 1435 29 + 0 1445 340 + 0 1459 447 + 0 1507 572 + 0 1554 757 + 0 1622 995 + 0 1703 1301 + 0 1781 1620 + 0 1844 1904 + 0 1896 2161 + 0 1952 2381 + 0 1978 2533 + 0 2017 2646 + 0 2068 2722 + 0 2100 2769 + 0 2120 2799 + 0 2136 2820 + 0 1554 116 + 0 1576 352 + 0 1599 467 + 0 1638 602 + 0 1689 801 + 0 1759 1046 + 0 1834 1354 + 0 1922 1681 + 0 1984 1970 + 0 2043 2226 + 0 2081 2432 + 0 2114 2591 + 0 2143 2698 + 0 2176 2763 + 0 2200 2805 + 0 2220 2835 + 0 2233 2856 + 0 1668 191 + 0 1699 415 + 0 1733 545 + 0 1773 707 + 0 1828 917 + 0 1893 1175 + 0 1970 1473 + 0 2046 1787 + 0 2112 2072 + 0 2168 2315 + 0 2205 2512 + 0 2233 2653 + 0 2260 2754 + 0 2293 2817 + 0 2312 2858 + 0 2324 2883 + 0 2332 2901 + 0 1776 275 + 0 1810 489 + 0 1851 651 + 0 1899 834 + 0 1959 1078 + 0 2021 1340 + 0 2095 1630 + 0 2163 1916 + 0 2226 2192 + 0 2276 2416 + 0 2312 2602 + 0 2337 2717 + 0 2364 2818 + 0 2389 2867 + 0 2408 2906 + 0 2420 2932 + 0 2428 2949 + 0 1842 321 + 0 1878 535 + 0 1924 716 + 0 1977 911 + 0 2039 1176 + 0 2102 1440 + 0 2173 1733 + 0 2238 2008 + 0 2295 2267 + 0 2342 2479 + 0 2377 2658 + 0 2401 2766 + 0 2427 2857 + 0 2451 2906 + 0 2468 2937 + 0 2479 2962 + 0 2488 2980 + 258 1884 350 + 0 1921 564 + 0 1971 757 + 0 2026 961 + 0 2091 1238 + 0 2153 1505 + 0 2222 1798 + 0 2286 2069 + 0 2341 2318 + 0 2384 2520 + 0 2419 2694 + 0 2442 2802 + 0 2467 2882 + 0 2491 2931 + 0 2507 2962 + 0 2518 2981 + 0 2526 2999 + 494 1914 371 + 0 1952 585 + 0 2004 787 + 0 2062 996 + 0 2128 1283 + 0 2190 1551 + 0 2258 1845 + 0 2321 2112 + 0 2374 2355 + 0 2416 2554 + 0 2449 2723 + 0 2472 2827 + 0 2495 2900 + 0 2520 2949 + 0 2536 2980 + 0 2546 2999 + 0 2554 3013 + 0 0 0 + 0 0 0 + 0 0 0 + 0 0 0 + 0 0 277 + 0 0 392 + 0 0 662 + 0 0 851 + 0 0 1078 + 0 0 1257 + 0 0 1428 + 0 0 1560 + 0 0 1742 + 0 0 1978 + 0 138 2124 + 0 536 2214 + 0 814 2278 + 0 0 0 + 0 0 0 + 25 0 0 + 0 0 208 + 0 0 360 + 0 0 483 + 0 0 702 + 0 0 914 + 0 0 1141 + 0 0 1334 + 0 0 1505 + 0 0 1650 + 0 0 1831 + 0 0 2054 + 0 213 2191 + 0 620 2279 + 0 905 2340 + 83 12 0 + 198 59 0 + 208 80 0 + 143 113 250 + 85 140 396 + 0 167 535 + 0 173 746 + 0 179 983 + 0 146 1211 + 0 89 1413 + 0 0 1589 + 0 0 1740 + 0 0 1918 + 0 0 2125 + 0 296 2253 + 0 714 2336 + 0 1006 2395 + 181 179 0 + 246 211 0 + 245 222 169 + 196 245 290 + 148 277 437 + 0 292 586 + 0 328 810 + 0 340 1063 + 0 363 1296 + 0 363 1509 + 0 363 1690 + 0 379 1839 + 0 516 2008 + 0 764 2197 + 0 928 2318 + 0 1043 2397 + 0 1124 2453 + 289 320 0 + 290 345 0 + 287 352 218 + 241 376 330 + 178 396 470 + 0 436 644 + 0 460 877 + 0 499 1134 + 0 523 1381 + 0 542 1602 + 0 553 1788 + 0 579 1937 + 0 698 2089 + 0 926 2264 + 0 1077 2381 + 0 1171 2454 + 0 1238 2506 + 310 411 0 + 317 463 158 + 308 502 271 + 217 502 363 + 61 548 526 + 0 569 687 + 0 627 954 + 0 662 1225 + 0 700 1479 + 0 735 1714 + 0 760 1905 + 0 790 2054 + 0 902 2198 + 0 1111 2359 + 0 1239 2458 + 0 1319 2521 + 0 1375 2564 + 357 659 0 + 366 671 218 + 353 674 316 + 269 704 419 + 0 735 577 + 0 779 769 + 0 833 1038 + 0 888 1322 + 0 939 1587 + 0 980 1834 + 0 1017 2030 + 0 1047 2178 + 0 1143 2313 + 0 1319 2452 + 0 1425 2537 + 0 1490 2590 + 0 1536 2628 + 359 834 0 + 381 865 267 + 359 893 361 + 0 912 460 + 0 970 644 + 0 1012 832 + 0 1085 1125 + 0 1148 1426 + 0 1203 1702 + 0 1251 1947 + 0 1289 2149 + 0 1324 2309 + 0 1403 2432 + 0 1537 2545 + 0 1626 2620 + 0 1683 2667 + 0 1722 2700 + 424 1098 0 + 384 1117 299 + 196 1142 400 + 0 1177 512 + 0 1231 689 + 0 1283 909 + 0 1359 1210 + 0 1428 1518 + 0 1501 1814 + 0 1547 2062 + 0 1595 2269 + 0 1620 2422 + 0 1683 2546 + 0 1772 2641 + 0 1833 2701 + 0 1878 2742 + 0 1910 2770 + 417 1310 0 + 334 1338 320 + 0 1370 424 + 0 1404 546 + 0 1462 741 + 0 1523 968 + 0 1604 1278 + 0 1682 1603 + 0 1749 1892 + 0 1807 2156 + 0 1845 2363 + 0 1876 2524 + 0 1925 2640 + 0 1993 2722 + 0 2035 2774 + 0 2061 2807 + 0 2084 2832 + 399 1526 0 + 0 1540 329 + 0 1563 446 + 0 1607 573 + 0 1660 779 + 0 1721 1012 + 0 1805 1342 + 0 1880 1667 + 0 1938 1946 + 0 1995 2205 + 0 2056 2444 + 0 2080 2601 + 0 2119 2712 + 0 2171 2788 + 0 2202 2835 + 0 2221 2864 + 0 2238 2886 + 449 1652 0 + 60 1677 337 + 0 1705 465 + 0 1739 601 + 0 1795 825 + 0 1862 1068 + 0 1944 1395 + 0 2026 1726 + 0 2083 2015 + 0 2139 2275 + 0 2184 2491 + 0 2221 2657 + 0 2250 2763 + 0 2285 2829 + 0 2310 2872 + 0 2329 2901 + 0 2342 2922 + 543 1770 0 + 373 1804 400 + 0 1842 546 + 0 1875 711 + 0 1939 946 + 0 1999 1200 + 0 2081 1517 + 0 2155 1833 + 0 2219 2121 + 0 2272 2371 + 0 2309 2572 + 0 2338 2717 + 0 2365 2816 + 0 2399 2880 + 0 2421 2921 + 0 2435 2947 + 0 2445 2965 + 649 1879 0 + 499 1918 479 + 0 1963 656 + 0 2004 844 + 0 2073 1110 + 0 2131 1367 + 0 2209 1675 + 0 2275 1964 + 0 2336 2242 + 0 2385 2472 + 0 2420 2663 + 0 2444 2780 + 0 2471 2879 + 0 2495 2927 + 0 2517 2968 + 0 2531 2994 + 0 2541 3012 + 727 1948 96 + 601 1988 527 + 0 2038 723 + 0 2085 925 + 0 2154 1208 + 0 2214 1473 + 0 2289 1778 + 0 2353 2057 + 0 2409 2316 + 0 2454 2535 + 0 2489 2719 + 0 2512 2831 + 0 2538 2920 + 0 2562 2968 + 0 2578 2998 + 0 2591 3024 + 0 2601 3042 + 777 1992 235 + 666 2034 558 + 276 2085 766 + 0 2136 977 + 0 2206 1270 + 0 2267 1541 + 0 2341 1844 + 0 2404 2118 + 0 2456 2368 + 0 2498 2576 + 0 2533 2756 + 0 2556 2867 + 0 2580 2946 + 0 2605 2994 + 0 2620 3024 + 0 2630 3043 + 0 2640 3061 + 813 2024 336 + 713 2066 580 + 509 2120 797 + 0 2173 1015 + 0 2244 1315 + 0 2306 1590 + 0 2378 1892 + 0 2440 2163 + 0 2490 2405 + 0 2531 2610 + 0 2565 2785 + 0 2588 2893 + 0 2611 2965 + 0 2635 3013 + 0 2651 3043 + 0 2661 3062 + 0 2667 3075 + 134 0 0 + 257 0 0 + 281 0 0 + 226 0 0 + 173 0 304 + 146 0 426 + 0 0 685 + 0 0 882 + 0 0 1113 + 0 0 1296 + 0 0 1476 + 0 0 1612 + 0 0 1802 + 0 0 2049 + 0 182 2203 + 0 584 2295 + 0 865 2361 + 328 0 0 + 340 0 0 + 346 0 0 + 331 0 223 + 317 23 371 + 309 17 507 + 291 0 727 + 18 0 950 + 0 0 1180 + 0 0 1377 + 0 0 1555 + 0 0 1704 + 0 0 1891 + 0 0 2123 + 0 256 2268 + 0 667 2357 + 0 955 2420 + 374 119 0 + 387 138 0 + 381 135 0 + 373 167 265 + 351 179 401 + 345 207 563 + 136 207 771 + 245 221 1021 + 0 169 1255 + 0 54 1463 + 0 0 1646 + 0 0 1797 + 0 0 1979 + 0 16 2193 + 0 344 2327 + 0 765 2413 + 0 1060 2472 + 419 257 0 + 426 264 0 + 417 264 178 + 407 289 304 + 383 310 441 + 361 330 615 + 235 359 838 + 141 373 1102 + 0 385 1342 + 0 377 1561 + 0 382 1749 + 0 403 1904 + 0 536 2075 + 0 800 2266 + 0 978 2391 + 0 1100 2472 + 0 1185 2529 + 452 363 0 + 463 385 0 + 452 384 223 + 437 410 342 + 402 423 474 + 381 469 673 + 0 486 907 + 0 530 1176 + 0 546 1430 + 0 563 1657 + 0 577 1849 + 0 607 2002 + 0 730 2159 + 0 971 2338 + 0 1136 2457 + 0 1234 2531 + 0 1303 2583 + 497 469 0 + 508 514 165 + 505 551 277 + 475 556 378 + 443 597 536 + 392 625 720 + 0 674 990 + 0 712 1269 + 0 750 1535 + 0 785 1775 + 0 807 1972 + 0 840 2122 + 0 957 2270 + 0 1176 2435 + 0 1313 2538 + 0 1394 2601 + 0 1452 2645 + 596 712 0 + 586 725 218 + 553 726 320 + 530 761 433 + 471 792 586 + 390 843 801 + 0 894 1074 + 0 951 1368 + 0 999 1650 + 0 1042 1897 + 0 1080 2100 + 0 1109 2253 + 0 1207 2390 + 0 1396 2532 + 0 1514 2620 + 0 1584 2675 + 0 1633 2713 + 634 915 0 + 625 947 260 + 607 976 363 + 555 1001 475 + 485 1055 656 + 0 1102 867 + 0 1171 1166 + 0 1233 1476 + 0 1289 1765 + 0 1339 2017 + 0 1378 2223 + 0 1412 2385 + 0 1492 2513 + 0 1633 2629 + 0 1732 2706 + 0 1790 2753 + 0 1831 2787 + 696 1205 0 + 675 1222 281 + 633 1242 394 + 581 1284 520 + 416 1332 701 + 0 1391 943 + 0 1467 1253 + 0 1539 1573 + 0 1612 1877 + 0 1656 2130 + 0 1704 2348 + 0 1726 2502 + 0 1791 2630 + 0 1888 2724 + 0 1956 2786 + 0 2003 2827 + 0 2035 2855 + 748 1428 0 + 715 1456 293 + 661 1486 412 + 580 1527 552 + 0 1581 750 + 0 1648 1002 + 0 1725 1320 + 0 1803 1656 + 0 1867 1962 + 0 1926 2226 + 0 1965 2441 + 0 1996 2607 + 0 2045 2726 + 0 2115 2808 + 0 2158 2860 + 0 2186 2892 + 0 2211 2918 + 796 1672 0 + 756 1679 289 + 690 1695 430 + 569 1742 575 + 0 1791 787 + 0 1856 1047 + 0 1938 1384 + 0 2018 1722 + 0 2101 2049 + 0 2143 2302 + 0 2184 2519 + 0 2208 2681 + 0 2248 2796 + 0 2305 2873 + 0 2341 2920 + 0 2362 2950 + 0 2380 2972 + 847 1790 0 + 796 1811 290 + 715 1832 447 + 574 1872 601 + 0 1931 831 + 0 2004 1103 + 0 2080 1439 + 0 2162 1775 + 0 2230 2084 + 0 2288 2353 + 0 2328 2567 + 0 2363 2734 + 0 2390 2844 + 0 2422 2910 + 0 2446 2953 + 0 2467 2983 + 0 2482 3004 + 931 1907 0 + 871 1937 357 + 769 1969 533 + 95 2009 713 + 0 2071 951 + 0 2139 1233 + 0 2221 1561 + 0 2295 1885 + 0 2363 2188 + 0 2417 2447 + 0 2453 2647 + 0 2482 2792 + 0 2510 2895 + 0 2540 2959 + 0 2559 3001 + 0 2573 3026 + 0 2583 3044 + 1030 2014 0 + 967 2048 450 + 863 2090 650 + 181 2139 853 + 1 2204 1122 + 0 2269 1402 + 0 2347 1720 + 0 2414 2021 + 0 2479 2314 + 0 2527 2551 + 0 2561 2733 + 0 2582 2852 + 0 2610 2954 + 0 2631 3001 + 0 2651 3042 + 0 2664 3067 + 0 2674 3085 + 1092 2080 0 + 1027 2118 508 + 922 2165 724 + 263 2220 940 + 69 2287 1227 + 0 2351 1509 + 0 2426 1823 + 0 2492 2115 + 0 2551 2392 + 0 2596 2616 + 0 2628 2787 + 0 2648 2899 + 0 2673 2992 + 0 2694 3038 + 0 2708 3068 + 0 2721 3093 + 0 2731 3111 + 1130 2124 31 + 1067 2163 541 + 973 2214 768 + 613 2272 994 + 249 2341 1293 + 0 2406 1577 + 0 2478 1889 + 0 2543 2177 + 0 2599 2444 + 0 2641 2656 + 0 2673 2824 + 0 2693 2935 + 0 2715 3017 + 0 2737 3063 + 0 2750 3093 + 0 2760 3111 + 0 2769 3129 + 1156 2156 260 + 1096 2196 564 + 1009 2250 800 + 865 2309 1032 + 379 2379 1340 + 0 2446 1625 + 0 2515 1936 + 0 2580 2221 + 0 2634 2482 + 0 2675 2690 + 0 2706 2853 + 0 2725 2961 + 0 2746 3035 + 0 2767 3081 + 0 2781 3111 + 0 2790 3129 + 0 2797 3143 + 451 0 0 + 490 0 0 + 512 0 0 + 479 0 43 + 489 0 325 + 437 0 442 + 474 0 707 + 0 0 916 + 373 0 1151 + 0 0 1341 + 0 0 1527 + 0 0 1671 + 0 0 1868 + 0 0 2124 + 0 220 2283 + 0 628 2379 + 0 914 2447 + 549 99 0 + 545 86 0 + 541 82 0 + 533 108 235 + 529 117 387 + 513 120 526 + 512 89 754 + 456 36 988 + 384 0 1221 + 0 0 1427 + 0 0 1612 + 0 0 1764 + 0 0 1958 + 0 0 2199 + 0 301 2348 + 0 719 2441 + 0 1011 2505 + 598 224 0 + 585 214 0 + 563 198 105 + 568 224 276 + 557 233 417 + 541 252 585 + 529 259 801 + 495 259 1063 + 387 228 1301 + 0 97 1518 + 0 0 1706 + 0 0 1863 + 0 0 2050 + 0 53 2270 + 0 393 2409 + 0 822 2497 + 0 1122 2558 + 635 337 0 + 630 330 0 + 618 314 188 + 614 341 314 + 606 360 456 + 586 378 639 + 576 403 873 + 525 412 1147 + 368 421 1393 + 0 408 1624 + 0 410 1811 + 0 428 1978 + 0 572 2153 + 0 851 2351 + 0 1040 2479 + 0 1166 2562 + 0 1255 2620 + 671 439 0 + 673 448 0 + 664 436 229 + 657 465 353 + 643 474 490 + 632 521 697 + 602 538 943 + 553 576 1223 + 357 589 1482 + 0 603 1721 + 0 618 1916 + 0 649 2077 + 0 780 2241 + 0 1036 2424 + 0 1209 2547 + 0 1312 2622 + 0 1384 2674 + 714 543 0 + 722 577 162 + 724 609 281 + 705 615 388 + 699 653 553 + 668 680 745 + 645 731 1026 + 543 768 1318 + 0 807 1591 + 0 842 1841 + 0 863 2044 + 0 896 2203 + 0 1022 2353 + 0 1254 2522 + 0 1398 2628 + 0 1484 2692 + 0 1544 2738 + 824 785 0 + 816 799 211 + 795 802 319 + 786 837 442 + 763 870 602 + 729 921 828 + 658 970 1112 + 303 1024 1419 + 0 1074 1708 + 0 1114 1971 + 0 1153 2174 + 0 1184 2340 + 0 1286 2482 + 0 1487 2624 + 0 1613 2713 + 0 1686 2768 + 0 1738 2806 + 899 1011 0 + 894 1044 244 + 881 1076 359 + 853 1100 478 + 830 1154 672 + 757 1202 894 + 688 1273 1206 + 0 1335 1531 + 0 1393 1825 + 0 1446 2097 + 0 1481 2308 + 0 1513 2475 + 0 1595 2605 + 0 1742 2721 + 0 1843 2800 + 0 1905 2848 + 0 1948 2881 + 1006 1319 0 + 991 1335 248 + 966 1357 382 + 943 1402 520 + 886 1454 715 + 816 1516 971 + 68 1593 1293 + 0 1662 1628 + 0 1731 1940 + 0 1777 2207 + 0 1822 2431 + 0 1845 2595 + 0 1911 2724 + 0 2011 2820 + 0 2081 2882 + 0 2129 2924 + 0 2163 2953 + 1088 1568 0 + 1063 1599 239 + 1027 1633 392 + 995 1674 548 + 929 1728 761 + 806 1793 1029 + 67 1869 1361 + 0 1952 1714 + 0 2018 2028 + 0 2078 2311 + 0 2111 2524 + 0 2140 2702 + 0 2190 2823 + 0 2264 2905 + 0 2310 2957 + 0 2338 2989 + 0 2364 3015 + 1161 1818 0 + 1133 1826 169 + 1093 1840 401 + 1049 1887 567 + 971 1943 797 + 821 2012 1072 + 72 2092 1424 + 0 2171 1777 + 0 2259 2112 + 0 2306 2388 + 0 2346 2606 + 0 2369 2771 + 0 2407 2889 + 0 2460 2967 + 0 2493 3015 + 0 2516 3045 + 0 2534 3067 + 1221 1947 0 + 1184 1972 0 + 1132 1998 410 + 1079 2035 589 + 994 2092 839 + 816 2170 1128 + 72 2252 1480 + 0 2339 1835 + 0 2405 2149 + 0 2465 2442 + 0 2499 2657 + 0 2532 2826 + 0 2558 2937 + 0 2587 3003 + 0 2609 3046 + 0 2632 3076 + 0 2647 3097 + 1299 2060 0 + 1262 2096 0 + 1205 2132 502 + 1146 2170 707 + 1048 2233 960 + 874 2305 1260 + 146 2392 1603 + 0 2466 1945 + 0 2532 2250 + 0 2588 2526 + 0 2622 2731 + 0 2650 2881 + 0 2676 2985 + 0 2703 3048 + 0 2721 3089 + 0 2734 3115 + 0 2742 3133 + 1387 2164 0 + 1351 2204 0 + 1300 2250 634 + 1234 2298 855 + 1133 2363 1137 + 971 2431 1431 + 260 2512 1761 + 57 2578 2080 + 0 2641 2377 + 0 2690 2627 + 0 2722 2813 + 0 2743 2935 + 0 2769 3039 + 0 2787 3086 + 0 2805 3126 + 0 2817 3152 + 0 2826 3170 + 1443 2229 0 + 1407 2273 472 + 1359 2324 714 + 1289 2377 947 + 1191 2445 1247 + 1024 2512 1540 + 321 2588 1865 + 207 2652 2174 + 63 2709 2457 + 0 2754 2690 + 0 2786 2865 + 0 2805 2981 + 0 2827 3073 + 0 2846 3120 + 0 2858 3150 + 0 2870 3176 + 0 2878 3194 + 1482 2271 0 + 1445 2317 509 + 1397 2372 761 + 1324 2429 1003 + 1226 2498 1315 + 1073 2565 1609 + 321 2639 1931 + 207 2702 2235 + 63 2757 2510 + 0 2798 2731 + 0 2829 2901 + 0 2848 3015 + 0 2868 3097 + 0 2886 3144 + 0 2898 3174 + 0 2906 3192 + 0 2915 3210 + 1511 2302 0 + 1473 2349 536 + 1424 2406 795 + 1349 2467 1043 + 1251 2537 1363 + 1108 2603 1658 + 321 2675 1979 + 207 2738 2279 + 63 2791 2549 + 0 2831 2766 + 0 2860 2931 + 0 2879 3040 + 0 2896 3114 + 0 2915 3161 + 0 2927 3191 + 0 2935 3209 + 0 2941 3222 + 710 0 0 + 718 0 0 + 726 0 0 + 710 0 149 + 710 0 334 + 706 0 457 + 700 0 732 + 681 0 954 + 661 0 1200 + 670 0 1394 + 657 0 1588 + 669 0 1739 + 720 0 1945 + 811 0 2209 + 869 255 2374 + 878 672 2475 + 869 963 2545 + 768 141 0 + 762 173 0 + 758 186 55 + 753 181 244 + 750 190 398 + 747 191 544 + 748 189 782 + 741 147 1026 + 731 0 1272 + 736 0 1484 + 731 0 1678 + 735 0 1833 + 774 0 2034 + 853 0 2286 + 902 343 2443 + 907 772 2540 + 895 1069 2607 + 832 270 0 + 817 295 0 + 793 302 142 + 801 309 283 + 793 316 429 + 796 332 605 + 792 324 835 + 804 307 1103 + 790 265 1355 + 795 78 1578 + 782 0 1778 + 789 0 1942 + 809 0 2135 + 873 94 2363 + 914 449 2508 + 917 890 2601 + 904 1196 2665 + 887 381 0 + 874 389 0 + 853 388 194 + 859 402 322 + 855 415 469 + 860 431 661 + 857 449 908 + 859 459 1189 + 845 459 1450 + 842 437 1686 + 827 437 1885 + 824 453 2056 + 836 608 2239 + 886 902 2445 + 920 1104 2579 + 879 1243 2666 + 812 1337 2727 + 941 487 0 + 937 503 0 + 923 501 232 + 924 520 358 + 919 533 502 + 930 574 717 + 916 589 979 + 921 624 1267 + 889 638 1542 + 884 649 1784 + 854 663 1993 + 850 694 2161 + 843 833 2331 + 883 1104 2520 + 914 1288 2649 + 735 1400 2727 + 498 1476 2781 + 1009 612 0 + 1015 645 140 + 1016 675 282 + 1007 678 390 + 1013 719 565 + 1009 748 766 + 1006 798 1063 + 991 835 1364 + 953 872 1654 + 937 906 1905 + 888 923 2125 + 871 957 2295 + 853 1089 2451 + 883 1338 2623 + 902 1493 2731 + 726 1587 2797 + 496 1650 2844 + 1127 866 0 + 1128 886 192 + 1117 895 318 + 1119 929 445 + 1116 962 615 + 1114 1014 853 + 1088 1064 1154 + 1069 1116 1470 + 1020 1163 1775 + 983 1204 2045 + 928 1243 2262 + 878 1272 2432 + 463 1379 2583 + 488 1590 2729 + 504 1721 2820 + 508 1802 2876 + 508 1857 2915 + 1233 1111 0 + 1238 1150 211 + 1240 1186 350 + 1227 1208 475 + 1227 1268 682 + 1204 1320 919 + 1184 1391 1247 + 1132 1453 1585 + 1078 1507 1894 + 1015 1560 2171 + 813 1594 2402 + 468 1625 2575 + 470 1709 2709 + 488 1863 2829 + 496 1971 2909 + 498 2036 2959 + 498 2081 2993 + 1371 1460 0 + 1367 1477 2 + 1356 1500 360 + 1348 1546 510 + 1323 1601 721 + 1305 1663 993 + 1243 1740 1336 + 1200 1805 1682 + 1097 1880 2013 + 812 1926 2288 + 522 1971 2528 + 467 1991 2698 + 459 2058 2832 + 481 2164 2931 + 496 2238 2995 + 500 2289 3037 + 500 2323 3066 + 1476 1726 0 + 1468 1754 0 + 1455 1787 353 + 1442 1828 532 + 1413 1885 764 + 1372 1955 1049 + 1307 2035 1401 + 1224 2114 1765 + 1121 2176 2097 + 800 2236 2391 + 524 2271 2622 + 439 2301 2801 + 431 2352 2928 + 463 2427 3013 + 484 2474 3067 + 490 2503 3100 + 490 2530 3126 + 1574 1997 0 + 1557 2002 0 + 1534 2017 346 + 1514 2069 541 + 1483 2126 796 + 1438 2197 1091 + 1354 2283 1466 + 1265 2365 1831 + 1128 2448 2173 + 635 2492 2462 + 493 2538 2708 + 427 2557 2876 + 423 2594 2996 + 453 2646 3074 + 473 2679 3123 + 478 2699 3153 + 478 2718 3175 + 1641 2126 0 + 1623 2147 0 + 1595 2173 345 + 1565 2215 562 + 1527 2283 840 + 1475 2366 1147 + 1392 2446 1521 + 1277 2534 1890 + 1145 2601 2222 + 628 2661 2519 + 507 2695 2753 + 416 2726 2929 + 415 2749 3043 + 455 2774 3110 + 478 2795 3154 + 484 2816 3184 + 484 2830 3205 + 1719 2238 0 + 1699 2273 0 + 1668 2312 444 + 1635 2354 683 + 1586 2424 962 + 1539 2499 1281 + 1443 2587 1643 + 1345 2662 2000 + 774 2731 2324 + 699 2784 2603 + 597 2817 2825 + 527 2843 2980 + 509 2865 3088 + 547 2889 3153 + 572 2905 3195 + 579 2915 3221 + 579 2923 3239 + 1798 2337 0 + 1778 2377 0 + 1750 2427 596 + 1716 2479 842 + 1659 2548 1144 + 1612 2616 1456 + 1518 2698 1803 + 1437 2765 2136 + 866 2829 2448 + 810 2877 2702 + 731 2909 2906 + 695 2930 3030 + 676 2952 3138 + 693 2965 3188 + 717 2980 3229 + 724 2991 3255 + 724 2998 3273 + 1848 2398 0 + 1828 2443 0 + 1801 2499 691 + 1767 2557 942 + 1710 2626 1259 + 1655 2692 1568 + 1567 2768 1908 + 1484 2833 2230 + 923 2891 2526 + 879 2935 2763 + 815 2966 2956 + 787 2986 3073 + 781 3006 3170 + 798 3019 3220 + 808 3027 3251 + 815 3038 3276 + 815 3045 3294 + 1881 2439 0 + 1862 2486 240 + 1837 2545 747 + 1802 2608 1003 + 1745 2678 1331 + 1686 2743 1639 + 1606 2815 1975 + 1523 2879 2291 + 1173 2934 2579 + 1104 2974 2803 + 896 3005 2990 + 810 3024 3106 + 810 3042 3191 + 826 3055 3241 + 837 3063 3272 + 840 3070 3291 + 840 3077 3308 + 1907 2468 0 + 1887 2517 488 + 1864 2579 784 + 1827 2644 1046 + 1771 2715 1383 + 1709 2780 1690 + 1639 2850 2023 + 1556 2913 2335 + 1467 2966 2618 + 1378 3005 2839 + 1153 3034 3019 + 810 3053 3130 + 810 3068 3206 + 826 3082 3256 + 837 3090 3287 + 840 3096 3306 + 840 3101 3319 + 941 0 0 + 949 39 0 + 953 103 0 + 942 0 154 + 949 0 346 + 954 0 469 + 967 0 757 + 971 0 992 + 980 0 1244 + 998 0 1449 + 1008 0 1651 + 1029 0 1806 + 1119 0 2021 + 1247 0 2294 + 1328 293 2464 + 1378 720 2571 + 1413 1019 2645 + 1018 246 0 + 1020 259 0 + 1024 268 81 + 1021 264 251 + 1031 267 412 + 1038 247 559 + 1061 213 809 + 1072 91 1066 + 1089 0 1320 + 1099 0 1543 + 1113 0 1744 + 1128 0 1909 + 1209 0 2118 + 1320 0 2376 + 1389 384 2536 + 1434 823 2639 + 1466 1130 2711 + 1099 300 0 + 1100 318 0 + 1103 335 148 + 1104 334 290 + 1119 347 445 + 1127 348 621 + 1150 345 866 + 1166 323 1144 + 1178 274 1404 + 1189 8 1642 + 1195 0 1843 + 1210 0 2019 + 1283 0 2222 + 1375 134 2456 + 1434 497 2604 + 1474 950 2701 + 1502 1267 2769 + 1185 405 0 + 1189 419 0 + 1194 432 197 + 1194 438 328 + 1211 461 486 + 1219 469 679 + 1243 490 940 + 1256 492 1233 + 1268 492 1501 + 1277 471 1756 + 1279 464 1961 + 1290 476 2138 + 1352 649 2328 + 1424 957 2539 + 1474 1167 2676 + 1510 1315 2767 + 1535 1419 2831 + 1265 521 0 + 1276 547 0 + 1284 561 233 + 1284 571 364 + 1301 595 521 + 1316 627 735 + 1330 648 1013 + 1345 677 1313 + 1349 688 1595 + 1358 701 1857 + 1353 710 2071 + 1362 740 2249 + 1408 886 2423 + 1471 1171 2616 + 1516 1364 2747 + 1544 1484 2829 + 1564 1568 2887 + 1358 673 0 + 1377 709 111 + 1394 743 278 + 1386 743 391 + 1411 789 580 + 1419 815 784 + 1441 868 1095 + 1441 905 1411 + 1437 939 1709 + 1441 972 1979 + 1425 984 2204 + 1428 1016 2385 + 1470 1157 2550 + 1523 1419 2725 + 1556 1582 2834 + 1576 1684 2903 + 1591 1755 2951 + 1496 954 0 + 1512 977 138 + 1528 991 305 + 1531 1023 443 + 1552 1061 628 + 1563 1112 872 + 1573 1161 1189 + 1570 1216 1521 + 1563 1263 1833 + 1558 1302 2122 + 1541 1335 2348 + 1526 1364 2528 + 1547 1473 2681 + 1588 1689 2831 + 1614 1824 2925 + 1630 1908 2983 + 1642 1967 3024 + 1625 1216 0 + 1651 1259 133 + 1675 1302 328 + 1667 1325 464 + 1689 1389 692 + 1690 1440 937 + 1699 1513 1283 + 1682 1575 1641 + 1668 1628 1962 + 1656 1681 2254 + 1625 1709 2491 + 1603 1739 2678 + 1616 1826 2814 + 1641 1985 2935 + 1659 2096 3017 + 1669 2165 3068 + 1677 2213 3103 + 1794 1597 0 + 1808 1614 0 + 1825 1641 320 + 1822 1687 491 + 1829 1743 726 + 1826 1806 1009 + 1818 1886 1371 + 1800 1957 1734 + 1770 2026 2077 + 1750 2067 2373 + 1698 2106 2619 + 1674 2124 2798 + 1677 2192 2938 + 1700 2301 3037 + 1714 2377 3103 + 1722 2432 3146 + 1728 2469 3176 + 1917 1879 0 + 1932 1911 0 + 1948 1951 276 + 1943 1996 501 + 1948 2059 764 + 1935 2129 1064 + 1921 2205 1438 + 1891 2292 1821 + 1861 2356 2158 + 1825 2414 2474 + 1771 2443 2715 + 1736 2475 2907 + 1731 2521 3038 + 1746 2596 3124 + 1755 2642 3178 + 1760 2672 3211 + 1766 2702 3239 + 2031 2165 0 + 2036 2173 0 + 2041 2192 107 + 2031 2245 498 + 2034 2313 791 + 2016 2391 1102 + 1991 2476 1501 + 1951 2558 1886 + 1914 2639 2237 + 1872 2683 2541 + 1792 2727 2798 + 1762 2746 2979 + 1757 2779 3106 + 1770 2827 3187 + 1779 2856 3238 + 1784 2875 3270 + 1788 2893 3293 + 2100 2308 0 + 2110 2340 0 + 2117 2374 67 + 2097 2416 512 + 2098 2487 834 + 2081 2576 1158 + 2052 2656 1555 + 2000 2746 1944 + 1959 2805 2288 + 1914 2866 2605 + 1839 2897 2844 + 1805 2931 3033 + 1795 2946 3153 + 1798 2968 3225 + 1803 2986 3271 + 1808 3005 3303 + 1812 3017 3326 + 2170 2423 0 + 2179 2465 0 + 2188 2513 304 + 2161 2553 647 + 2156 2628 960 + 2133 2702 1296 + 2107 2794 1679 + 2056 2866 2053 + 2008 2930 2390 + 1963 2983 2687 + 1897 3014 2914 + 1866 3041 3080 + 1855 3061 3193 + 1859 3082 3262 + 1861 3095 3306 + 1862 3103 3334 + 1863 3109 3354 + 2241 2517 0 + 2249 2566 0 + 2253 2621 504 + 2229 2672 819 + 2211 2744 1148 + 2184 2812 1474 + 2159 2898 1840 + 2112 2961 2190 + 2067 3023 2514 + 2025 3069 2783 + 1973 3099 2992 + 1945 3119 3129 + 1933 3139 3241 + 1939 3150 3291 + 1941 3163 3335 + 1942 3172 3363 + 1943 3178 3382 + 2286 2576 0 + 2292 2628 0 + 2293 2688 628 + 2272 2746 927 + 2247 2818 1267 + 2217 2884 1591 + 2190 2963 1947 + 2146 3025 2284 + 2104 3081 2591 + 2063 3122 2843 + 2021 3152 3042 + 1993 3170 3171 + 1982 3188 3272 + 1988 3199 3322 + 1991 3206 3353 + 1993 3214 3380 + 1994 3220 3400 + 2314 2614 0 + 2320 2669 180 + 2319 2731 708 + 2299 2794 996 + 2271 2864 1344 + 2238 2930 1665 + 2210 3004 2015 + 2168 3066 2346 + 2127 3118 2645 + 2088 3156 2881 + 2050 3185 3074 + 2023 3204 3202 + 2014 3220 3292 + 2019 3231 3341 + 2022 3237 3372 + 2025 3242 3392 + 2026 3248 3411 + 2335 2641 0 + 2340 2698 417 + 2338 2763 765 + 2319 2828 1045 + 2287 2898 1399 + 2254 2964 1718 + 2224 3034 2064 + 2183 3096 2390 + 2143 3145 2684 + 2105 3182 2916 + 2068 3210 3102 + 2045 3229 3225 + 2037 3242 3306 + 2042 3253 3355 + 2045 3260 3386 + 2047 3264 3406 + 2049 3267 3419 + 1320 0 0 + 1310 0 0 + 1309 20 0 + 1309 0 150 + 1334 0 356 + 1353 0 496 + 1377 0 785 + 1394 0 1030 + 1421 0 1296 + 1444 0 1507 + 1463 0 1720 + 1480 0 1879 + 1588 0 2098 + 1776 0 2384 + 1879 331 2560 + 1941 763 2669 + 1983 1065 2746 + 1397 244 0 + 1382 238 0 + 1375 235 107 + 1383 239 259 + 1405 239 420 + 1425 223 581 + 1450 182 835 + 1471 0 1100 + 1495 0 1365 + 1512 0 1595 + 1533 0 1805 + 1555 0 1980 + 1649 0 2196 + 1816 0 2464 + 1910 429 2628 + 1968 872 2732 + 2009 1182 2806 + 1487 332 0 + 1467 331 0 + 1451 315 150 + 1470 330 300 + 1491 330 443 + 1512 343 643 + 1537 331 889 + 1564 312 1174 + 1584 244 1450 + 1595 0 1693 + 1620 0 1907 + 1637 0 2085 + 1715 0 2298 + 1860 158 2544 + 1946 544 2695 + 2003 1002 2793 + 2043 1322 2861 + 1593 464 0 + 1573 461 0 + 1557 450 198 + 1580 471 338 + 1602 481 486 + 1623 500 701 + 1647 513 965 + 1671 518 1264 + 1689 516 1548 + 1700 488 1806 + 1721 479 2028 + 1733 489 2211 + 1799 660 2412 + 1921 993 2630 + 1997 1216 2768 + 2049 1374 2860 + 2085 1486 2925 + 1690 581 0 + 1675 597 0 + 1665 592 226 + 1687 614 367 + 1711 628 517 + 1734 669 757 + 1753 680 1041 + 1776 712 1346 + 1791 718 1644 + 1802 728 1911 + 1821 738 2144 + 1828 769 2327 + 1880 919 2511 + 1988 1224 2711 + 2058 1427 2843 + 2101 1553 2924 + 2131 1641 2981 + 1808 742 0 + 1798 776 0 + 1798 806 270 + 1819 814 396 + 1848 852 580 + 1869 885 808 + 1894 930 1124 + 1906 966 1446 + 1918 992 1759 + 1925 1025 2037 + 1939 1038 2277 + 1940 1074 2462 + 1985 1217 2636 + 2079 1495 2819 + 2132 1662 2930 + 2163 1765 2999 + 2185 1837 3047 + 1968 1039 0 + 1955 1057 0 + 1948 1062 289 + 1976 1102 442 + 2000 1130 623 + 2019 1185 890 + 2039 1230 1215 + 2047 1286 1556 + 2058 1332 1886 + 2058 1368 2181 + 2064 1403 2426 + 2051 1429 2613 + 2080 1541 2775 + 2163 1773 2929 + 2208 1915 3022 + 2235 2004 3079 + 2254 2065 3119 + 2127 1331 0 + 2116 1366 0 + 2117 1405 296 + 2140 1436 456 + 2163 1493 686 + 2178 1541 954 + 2198 1612 1309 + 2199 1671 1670 + 2209 1730 2016 + 2199 1779 2313 + 2197 1808 2565 + 2176 1835 2756 + 2195 1927 2907 + 2256 2095 3033 + 2291 2205 3114 + 2311 2273 3164 + 2325 2321 3199 + 2328 1739 0 + 2302 1746 0 + 2296 1765 236 + 2320 1814 463 + 2340 1872 710 + 2349 1936 1024 + 2365 2020 1400 + 2357 2078 1770 + 2363 2157 2138 + 2342 2194 2444 + 2327 2237 2708 + 2302 2252 2891 + 2308 2321 3040 + 2347 2431 3146 + 2370 2507 3210 + 2386 2561 3251 + 2397 2598 3280 + 2452 2033 0 + 2432 2056 0 + 2425 2089 0 + 2444 2134 464 + 2465 2200 743 + 2467 2268 1077 + 2474 2357 1466 + 2459 2431 1855 + 2454 2500 2215 + 2427 2552 2537 + 2405 2583 2796 + 2378 2609 2991 + 2381 2663 3135 + 2412 2738 3232 + 2426 2780 3286 + 2434 2807 3319 + 2443 2836 3346 + 2588 2341 0 + 2558 2339 0 + 2545 2357 0 + 2567 2419 437 + 2591 2491 762 + 2589 2563 1113 + 2587 2655 1531 + 2560 2723 1922 + 2547 2805 2291 + 2510 2841 2605 + 2487 2895 2883 + 2456 2905 3066 + 2452 2940 3204 + 2470 2989 3294 + 2480 3018 3347 + 2485 3037 3379 + 2490 3053 3401 + 2646 2488 0 + 2628 2511 0 + 2619 2543 0 + 2631 2594 449 + 2644 2666 804 + 2643 2747 1167 + 2634 2832 1577 + 2606 2911 1977 + 2589 2978 2346 + 2553 3031 2670 + 2523 3065 2926 + 2494 3090 3117 + 2487 3112 3250 + 2498 3135 3330 + 2503 3150 3377 + 2508 3169 3409 + 2512 3182 3432 + 2707 2603 0 + 2696 2642 0 + 2696 2692 0 + 2700 2739 589 + 2703 2815 932 + 2697 2885 1308 + 2689 2981 1707 + 2657 3043 2091 + 2634 3114 2451 + 2600 3164 2760 + 2571 3196 3001 + 2542 3215 3171 + 2529 3236 3290 + 2539 3257 3366 + 2542 3266 3411 + 2543 3270 3438 + 2544 3273 3458 + 2760 2692 0 + 2753 2737 0 + 2760 2797 0 + 2762 2851 797 + 2750 2923 1135 + 2739 2988 1499 + 2730 3078 1878 + 2700 3133 2234 + 2671 3201 2576 + 2641 3246 2858 + 2615 3278 3078 + 2589 3292 3220 + 2575 3314 3339 + 2575 3322 3388 + 2578 3330 3431 + 2579 3334 3458 + 2580 3337 3478 + 2799 2750 0 + 2793 2798 0 + 2798 2860 94 + 2800 2920 916 + 2783 2990 1267 + 2767 3054 1617 + 2756 3136 1988 + 2726 3192 2331 + 2698 3253 2653 + 2669 3293 2914 + 2649 3326 3125 + 2622 3339 3259 + 2610 3357 3366 + 2610 3365 3415 + 2611 3371 3446 + 2612 3375 3473 + 2613 3378 3492 + 2825 2788 0 + 2818 2837 19 + 2822 2899 470 + 2825 2964 990 + 2805 3033 1352 + 2785 3096 1692 + 2772 3172 2058 + 2743 3230 2394 + 2716 3285 2706 + 2688 3322 2950 + 2670 3356 3155 + 2644 3370 3289 + 2633 3385 3383 + 2633 3393 3432 + 2634 3398 3463 + 2635 3402 3482 + 2636 3405 3501 + 2844 2815 0 + 2837 2865 249 + 2839 2928 740 + 2843 2995 1043 + 2820 3064 1413 + 2798 3126 1746 + 2783 3198 2108 + 2755 3258 2440 + 2729 3308 2745 + 2701 3345 2984 + 2683 3377 3181 + 2660 3392 3311 + 2650 3404 3395 + 2649 3412 3444 + 2651 3418 3475 + 2652 3421 3494 + 2652 3424 3508 + 1603 0 0 + 1596 0 0 + 1590 0 0 + 1595 0 187 + 1624 0 378 + 1656 0 509 + 1679 0 799 + 1703 0 1051 + 1732 0 1322 + 1757 0 1545 + 1779 0 1761 + 1801 0 1926 + 1907 0 2149 + 2095 0 2437 + 2212 346 2616 + 2286 784 2728 + 2337 1090 2806 + 1696 158 0 + 1693 140 0 + 1693 131 123 + 1702 135 269 + 1730 125 432 + 1758 47 591 + 1784 0 850 + 1810 0 1125 + 1832 0 1392 + 1844 0 1632 + 1867 0 1844 + 1896 0 2029 + 1995 0 2251 + 2164 0 2519 + 2270 447 2686 + 2339 897 2793 + 2386 1211 2868 + 1789 308 0 + 1790 305 0 + 1796 297 161 + 1810 306 308 + 1837 308 459 + 1862 316 652 + 1890 298 904 + 1921 274 1203 + 1936 0 1477 + 1939 0 1725 + 1966 0 1943 + 2000 0 2135 + 2090 0 2353 + 2234 27 2598 + 2326 566 2753 + 2387 1031 2854 + 2431 1355 2925 + 1897 464 0 + 1899 457 0 + 1906 446 196 + 1924 466 342 + 1954 479 498 + 1984 491 711 + 2011 505 981 + 2039 503 1291 + 2055 497 1578 + 2069 446 1846 + 2085 301 2068 + 2108 279 2267 + 2185 443 2469 + 2308 791 2684 + 2390 1105 2826 + 2446 1397 2922 + 2485 1523 2989 + 2003 604 0 + 2008 616 0 + 2017 612 224 + 2036 636 375 + 2066 650 533 + 2097 688 767 + 2123 697 1056 + 2150 727 1373 + 2163 733 1673 + 2181 740 1954 + 2193 751 2185 + 2212 777 2382 + 2270 927 2569 + 2378 1241 2768 + 2455 1458 2902 + 2503 1594 2986 + 2536 1685 3046 + 2136 777 0 + 2144 810 0 + 2159 842 263 + 2178 851 399 + 2209 894 592 + 2240 921 817 + 2265 966 1138 + 2288 997 1473 + 2299 1025 1788 + 2315 1057 2082 + 2324 1070 2323 + 2339 1102 2522 + 2385 1248 2696 + 2479 1528 2877 + 2538 1702 2991 + 2575 1811 3061 + 2601 1887 3111 + 2300 1092 0 + 2310 1109 0 + 2325 1112 270 + 2350 1153 439 + 2384 1184 629 + 2416 1237 896 + 2441 1282 1225 + 2460 1335 1583 + 2468 1380 1914 + 2479 1414 2224 + 2478 1447 2469 + 2483 1472 2673 + 2515 1584 2840 + 2586 1821 2990 + 2630 1969 3083 + 2658 2061 3141 + 2680 2125 3183 + 2481 1392 0 + 2495 1430 0 + 2516 1471 257 + 2536 1501 444 + 2565 1559 688 + 2598 1606 957 + 2616 1679 1320 + 2632 1739 1699 + 2635 1793 2045 + 2640 1841 2365 + 2630 1866 2614 + 2628 1894 2820 + 2641 1985 2971 + 2688 2152 3095 + 2723 2267 3179 + 2745 2339 3232 + 2763 2390 3268 + 2686 1812 0 + 2685 1822 0 + 2695 1840 0 + 2715 1892 444 + 2744 1949 709 + 2767 2014 1025 + 2787 2088 1406 + 2792 2152 1795 + 2792 2221 2158 + 2786 2261 2485 + 2768 2300 2747 + 2759 2320 2946 + 2767 2388 3098 + 2792 2499 3205 + 2811 2578 3274 + 2824 2635 3318 + 2839 2676 3350 + 2829 2125 0 + 2841 2157 0 + 2865 2195 0 + 2877 2238 420 + 2907 2309 729 + 2927 2384 1074 + 2937 2463 1474 + 2942 2545 1887 + 2929 2601 2247 + 2923 2665 2594 + 2892 2686 2846 + 2885 2718 3058 + 2884 2766 3203 + 2892 2833 3296 + 2897 2876 3354 + 2900 2902 3390 + 2911 2932 3419 + 2977 2449 0 + 2973 2454 0 + 2979 2472 0 + 2998 2529 382 + 3025 2599 751 + 3043 2678 1110 + 3043 2760 1536 + 3038 2836 1948 + 3019 2902 2317 + 3002 2948 2656 + 2976 2994 2928 + 2962 3013 3129 + 2955 3044 3268 + 2958 3089 3357 + 2960 3117 3413 + 2961 3134 3448 + 2968 3153 3474 + 3045 2609 0 + 3057 2644 0 + 3078 2685 0 + 3087 2731 374 + 3108 2801 781 + 3128 2891 1160 + 3120 2967 1585 + 3113 3053 2005 + 3088 3102 2376 + 3074 3166 2729 + 3039 3193 2982 + 3028 3229 3193 + 3014 3242 3324 + 3002 3255 3398 + 2998 3269 3447 + 2999 3286 3482 + 3003 3299 3507 + 3101 2727 0 + 3115 2774 0 + 3141 2831 0 + 3142 2874 522 + 3158 2948 908 + 3163 3022 1305 + 3165 3112 1714 + 3146 3179 2116 + 3124 3236 2482 + 3108 3294 2815 + 3076 3320 3054 + 3062 3346 3240 + 3052 3364 3362 + 3040 3376 3434 + 3033 3383 3480 + 3028 3388 3509 + 3031 3394 3531 + 3151 2817 0 + 3163 2867 0 + 3181 2926 0 + 3187 2979 746 + 3186 3049 1120 + 3183 3117 1498 + 3184 3203 1889 + 3162 3262 2260 + 3142 3320 2608 + 3123 3368 2906 + 3099 3395 3129 + 3082 3413 3280 + 3071 3431 3403 + 3064 3437 3453 + 3057 3444 3498 + 3052 3449 3527 + 3055 3455 3549 + 3183 2874 0 + 3193 2926 0 + 3206 2985 73 + 3214 3045 886 + 3205 3113 1264 + 3199 3180 1623 + 3194 3259 2005 + 3176 3319 2362 + 3154 3373 2687 + 3133 3414 2963 + 3114 3442 3177 + 3096 3459 3319 + 3084 3473 3429 + 3076 3479 3479 + 3072 3482 3510 + 3067 3487 3538 + 3070 3493 3560 + 3203 2910 0 + 3212 2963 0 + 3221 3024 443 + 3232 3087 975 + 3217 3154 1357 + 3210 3220 1703 + 3200 3294 2079 + 3184 3356 2429 + 3161 3406 2743 + 3139 3443 3000 + 3122 3473 3208 + 3105 3489 3350 + 3092 3500 3445 + 3084 3505 3495 + 3079 3509 3526 + 3077 3511 3545 + 3079 3517 3567 + 3218 2935 0 + 3228 2991 0 + 3240 3054 712 + 3250 3119 1035 + 3234 3186 1417 + 3222 3251 1760 + 3212 3322 2131 + 3196 3384 2476 + 3173 3432 2784 + 3149 3468 3034 + 3134 3496 3236 + 3118 3512 3372 + 3105 3522 3459 + 3097 3528 3509 + 3093 3531 3540 + 3090 3533 3560 + 3090 3536 3573 + 1900 0 0 + 1888 0 0 + 1883 0 0 + 1892 0 183 + 1924 0 371 + 1957 0 504 + 1979 0 808 + 2002 0 1067 + 2023 0 1344 + 2048 0 1570 + 2076 0 1797 + 2101 0 1967 + 2212 0 2193 + 2406 0 2479 + 2528 347 2658 + 2604 785 2770 + 2656 1091 2848 + 1984 0 0 + 1971 0 0 + 1966 0 146 + 1980 0 272 + 2010 0 436 + 2041 0 594 + 2066 0 862 + 2090 0 1139 + 2109 0 1414 + 2125 0 1658 + 2150 0 1876 + 2179 0 2063 + 2284 0 2289 + 2464 0 2559 + 2576 452 2727 + 2648 903 2835 + 2697 1219 2910 + 2082 239 0 + 2068 244 0 + 2060 233 179 + 2081 242 311 + 2109 236 466 + 2136 246 656 + 2162 165 920 + 2187 88 1217 + 2205 0 1497 + 2212 0 1749 + 2242 0 1976 + 2274 0 2170 + 2371 0 2390 + 2531 0 2637 + 2633 575 2794 + 2701 1042 2897 + 2747 1368 2968 + 2191 439 0 + 2177 441 0 + 2170 436 209 + 2193 450 345 + 2226 467 506 + 2257 475 713 + 2286 489 995 + 2312 485 1304 + 2332 458 1598 + 2345 0 1863 + 2369 0 2098 + 2390 0 2298 + 2475 7 2505 + 2611 363 2725 + 2702 794 2869 + 2764 1275 2965 + 2806 1543 3032 + 2306 602 0 + 2295 620 0 + 2290 618 232 + 2316 639 373 + 2347 653 540 + 2381 690 768 + 2408 697 1068 + 2434 729 1386 + 2455 732 1693 + 2470 740 1970 + 2491 743 2216 + 2505 773 2413 + 2570 930 2605 + 2691 1253 2808 + 2776 1475 2945 + 2829 1614 3031 + 2864 1710 3090 + 2457 786 0 + 2446 826 0 + 2447 859 264 + 2477 864 392 + 2507 906 593 + 2539 930 817 + 2564 973 1148 + 2585 1003 1484 + 2605 1031 1809 + 2617 1063 2099 + 2635 1069 2358 + 2642 1103 2556 + 2693 1253 2733 + 2800 1543 2918 + 2867 1724 3034 + 2909 1837 3106 + 2937 1915 3156 + 2628 1117 0 + 2617 1137 0 + 2612 1143 267 + 2644 1181 430 + 2678 1215 630 + 2710 1265 895 + 2734 1307 1234 + 2753 1359 1592 + 2769 1401 1935 + 2776 1435 2237 + 2785 1467 2500 + 2784 1493 2702 + 2823 1609 2874 + 2907 1849 3029 + 2960 1999 3126 + 2994 2092 3187 + 3015 2158 3228 + 2812 1433 0 + 2803 1471 0 + 2805 1507 236 + 2834 1532 425 + 2867 1595 683 + 2899 1637 952 + 2919 1711 1328 + 2933 1764 1706 + 2945 1819 2063 + 2946 1864 2378 + 2948 1892 2647 + 2940 1918 2850 + 2960 2011 3005 + 3018 2184 3137 + 3061 2304 3225 + 3088 2380 3280 + 3106 2431 3318 + 3026 1871 0 + 3006 1880 0 + 3003 1899 0 + 3037 1953 413 + 3069 2007 698 + 3094 2068 1018 + 3117 2143 1418 + 3120 2205 1807 + 3127 2272 2181 + 3117 2308 2501 + 3114 2353 2784 + 3102 2370 2983 + 3112 2438 3138 + 3139 2549 3248 + 3162 2630 3319 + 3180 2689 3367 + 3191 2729 3399 + 3180 2192 0 + 3171 2216 0 + 3172 2253 0 + 3199 2304 381 + 3229 2370 721 + 3252 2441 1066 + 3264 2518 1482 + 3268 2595 1894 + 3261 2652 2266 + 3250 2706 2605 + 3238 2738 2879 + 3227 2767 3089 + 3230 2816 3238 + 3245 2890 3337 + 3254 2936 3399 + 3260 2965 3438 + 3267 2996 3467 + 3354 2548 0 + 3325 2543 0 + 3316 2558 0 + 3352 2627 268 + 3374 2691 733 + 3394 2766 1098 + 3394 2846 1542 + 3388 2917 1957 + 3375 2981 2336 + 3356 3020 2672 + 3352 3080 2973 + 3336 3095 3175 + 3331 3125 3317 + 3335 3169 3407 + 3338 3196 3463 + 3340 3213 3498 + 3342 3231 3524 + 3417 2712 0 + 3403 2734 0 + 3401 2764 0 + 3427 2816 257 + 3443 2886 767 + 3465 2971 1150 + 3460 3044 1592 + 3454 3126 2015 + 3438 3181 2398 + 3419 3236 2743 + 3403 3273 3018 + 3388 3304 3230 + 3379 3319 3367 + 3376 3336 3447 + 3376 3351 3498 + 3378 3368 3533 + 3379 3381 3558 + 3465 2830 0 + 3460 2868 0 + 3465 2913 0 + 3481 2959 415 + 3493 3036 901 + 3503 3108 1296 + 3504 3193 1724 + 3490 3258 2131 + 3476 3320 2507 + 3456 3371 2835 + 3438 3403 3092 + 3423 3426 3277 + 3410 3443 3403 + 3406 3458 3480 + 3405 3468 3530 + 3404 3475 3561 + 3402 3478 3582 + 3503 2918 0 + 3501 2962 0 + 3508 3014 0 + 3525 3067 679 + 3522 3142 1117 + 3526 3210 1496 + 3525 3290 1903 + 3510 3348 2280 + 3495 3407 2637 + 3474 3450 2933 + 3458 3480 3171 + 3444 3498 3320 + 3431 3514 3446 + 3421 3519 3498 + 3419 3528 3546 + 3418 3535 3577 + 3416 3539 3598 + 3527 2973 0 + 3527 3021 0 + 3536 3076 54 + 3552 3135 844 + 3545 3209 1260 + 3542 3276 1627 + 3538 3350 2021 + 3524 3408 2385 + 3506 3461 2719 + 3486 3500 2995 + 3470 3529 3221 + 3456 3545 3361 + 3444 3559 3473 + 3434 3563 3524 + 3428 3566 3556 + 3426 3573 3587 + 3424 3576 3608 + 3542 3008 0 + 3544 3058 0 + 3553 3117 421 + 3569 3178 949 + 3559 3251 1352 + 3552 3318 1711 + 3547 3389 2097 + 3532 3447 2454 + 3514 3497 2777 + 3493 3531 3034 + 3478 3560 3253 + 3464 3576 3392 + 3453 3587 3490 + 3443 3592 3542 + 3436 3595 3574 + 3432 3597 3594 + 3430 3601 3615 + 3555 3033 0 + 3556 3085 0 + 3565 3145 686 + 3582 3209 1019 + 3568 3281 1418 + 3560 3348 1770 + 3552 3415 2151 + 3538 3474 2502 + 3520 3522 2819 + 3498 3556 3070 + 3483 3582 3281 + 3470 3598 3415 + 3459 3607 3502 + 3448 3612 3554 + 3442 3615 3586 + 3438 3617 3606 + 3436 3618 3620 + 2079 0 0 + 2074 0 0 + 2070 0 0 + 2078 0 211 + 2107 0 392 + 2138 0 520 + 2158 0 816 + 2181 0 1075 + 2201 0 1346 + 2226 0 1575 + 2252 0 1806 + 2286 0 1984 + 2396 0 2211 + 2586 0 2497 + 2706 341 2676 + 2782 779 2788 + 2835 1086 2866 + 2163 0 0 + 2162 0 0 + 2163 0 162 + 2175 0 282 + 2207 0 445 + 2239 0 603 + 2264 0 869 + 2291 0 1150 + 2310 0 1423 + 2331 0 1675 + 2353 0 1893 + 2387 0 2084 + 2489 0 2310 + 2661 0 2580 + 2770 448 2749 + 2842 899 2856 + 2892 1215 2932 + 2262 168 0 + 2266 144 0 + 2273 107 186 + 2288 126 319 + 2317 114 473 + 2348 114 663 + 2372 0 924 + 2402 0 1229 + 2417 0 1509 + 2436 0 1775 + 2454 0 1997 + 2489 0 2195 + 2581 0 2414 + 2734 0 2660 + 2833 575 2817 + 2901 1042 2919 + 2949 1369 2991 + 2379 427 0 + 2383 416 0 + 2389 396 209 + 2408 420 349 + 2437 433 510 + 2468 438 719 + 2493 450 997 + 2522 437 1312 + 2538 354 1607 + 2557 0 1883 + 2574 0 2113 + 2604 0 2321 + 2687 0 2528 + 2818 288 2746 + 2906 727 2890 + 2969 1208 2986 + 3012 1544 3054 + 2488 605 0 + 2494 615 0 + 2502 605 231 + 2522 633 379 + 2552 643 544 + 2586 679 774 + 2610 685 1069 + 2641 715 1394 + 2655 722 1702 + 2675 721 1988 + 2689 732 2228 + 2713 757 2434 + 2778 912 2627 + 2897 1244 2828 + 2979 1475 2965 + 3032 1614 3051 + 3070 1711 3111 + 2633 800 0 + 2641 833 0 + 2655 865 260 + 2676 875 399 + 2707 915 598 + 2741 935 822 + 2765 979 1149 + 2790 1007 1492 + 2803 1039 1817 + 2820 1064 2115 + 2830 1076 2368 + 2849 1107 2576 + 2898 1258 2754 + 3004 1545 2938 + 3071 1725 3054 + 3113 1838 3126 + 3142 1918 3177 + 2805 1134 0 + 2813 1150 0 + 2823 1149 254 + 2849 1194 432 + 2883 1224 631 + 2918 1271 897 + 2941 1312 1234 + 2965 1362 1601 + 2976 1405 1941 + 2989 1431 2253 + 2994 1468 2510 + 3005 1492 2723 + 3040 1609 2896 + 3119 1855 3051 + 3169 2007 3149 + 3202 2101 3209 + 3225 2167 3252 + 2995 1453 0 + 3007 1489 0 + 3023 1524 0 + 3047 1555 423 + 3081 1616 683 + 3115 1655 953 + 3134 1730 1328 + 3155 1784 1716 + 3159 1836 2068 + 3170 1880 2396 + 3166 1907 2659 + 3171 1933 2874 + 3186 2027 3029 + 3236 2200 3160 + 3275 2319 3248 + 3302 2395 3303 + 3320 2447 3341 + 3208 1889 0 + 3209 1902 0 + 3218 1920 0 + 3245 1973 409 + 3277 2025 697 + 3305 2084 1019 + 3325 2156 1414 + 3336 2222 1812 + 3336 2283 2180 + 3338 2322 2514 + 3332 2364 2792 + 3328 2382 3000 + 3336 2452 3158 + 3360 2568 3271 + 3380 2650 3343 + 3398 2709 3390 + 3411 2750 3424 + 3372 2216 0 + 3387 2253 0 + 3408 2297 0 + 3427 2344 359 + 3455 2408 710 + 3483 2480 1064 + 3492 2555 1480 + 3502 2632 1903 + 3489 2682 2271 + 3487 2740 2626 + 3472 2767 2894 + 3470 2797 3117 + 3469 2846 3267 + 3475 2919 3364 + 3480 2964 3425 + 3486 2993 3464 + 3494 3024 3494 + 3541 2576 0 + 3535 2580 0 + 3538 2597 0 + 3564 2659 234 + 3586 2723 725 + 3610 2799 1099 + 3612 2874 1540 + 3615 2949 1965 + 3599 3008 2345 + 3588 3051 2692 + 3577 3098 2980 + 3569 3118 3196 + 3562 3150 3341 + 3561 3198 3432 + 3561 3227 3489 + 3563 3244 3524 + 3566 3262 3551 + 3615 2755 0 + 3624 2786 0 + 3640 2826 0 + 3660 2878 0 + 3679 2945 746 + 3704 3030 1147 + 3698 3099 1592 + 3701 3189 2027 + 3678 3236 2409 + 3668 3294 2766 + 3648 3324 3036 + 3645 3360 3263 + 3630 3372 3400 + 3615 3381 3477 + 3609 3394 3528 + 3611 3411 3563 + 3612 3423 3588 + 3662 2878 0 + 3675 2921 0 + 3695 2974 0 + 3706 3020 0 + 3724 3095 880 + 3733 3166 1296 + 3735 3248 1724 + 3727 3318 2141 + 3708 3373 2513 + 3697 3427 2853 + 3677 3455 3109 + 3670 3482 3307 + 3658 3498 3436 + 3644 3507 3511 + 3636 3514 3559 + 3635 3520 3591 + 3634 3525 3612 + 3700 2972 0 + 3712 3018 0 + 3726 3072 0 + 3739 3128 318 + 3743 3201 1105 + 3746 3266 1498 + 3744 3344 1905 + 3732 3401 2286 + 3715 3456 2636 + 3703 3503 2942 + 3688 3533 3186 + 3679 3552 3346 + 3667 3568 3475 + 3656 3572 3529 + 3648 3578 3577 + 3647 3585 3608 + 3646 3589 3630 + 3724 3029 0 + 3735 3078 0 + 3747 3134 30 + 3762 3195 830 + 3759 3267 1260 + 3758 3332 1629 + 3751 3403 2026 + 3740 3460 2391 + 3722 3509 2714 + 3708 3550 2999 + 3696 3581 3234 + 3686 3599 3385 + 3674 3612 3500 + 3663 3616 3554 + 3656 3618 3588 + 3655 3625 3618 + 3654 3629 3640 + 3739 3064 0 + 3752 3116 0 + 3765 3174 397 + 3779 3239 935 + 3773 3310 1351 + 3768 3375 1713 + 3759 3442 2101 + 3749 3499 2459 + 3730 3545 2772 + 3716 3582 3039 + 3704 3612 3267 + 3694 3630 3417 + 3683 3641 3517 + 3672 3644 3572 + 3665 3647 3605 + 3661 3649 3625 + 3660 3653 3647 + 3750 3090 0 + 3764 3143 0 + 3777 3203 661 + 3792 3270 1011 + 3783 3340 1417 + 3776 3405 1773 + 3766 3470 2156 + 3755 3527 2508 + 3735 3571 2815 + 3721 3607 3075 + 3709 3635 3295 + 3700 3652 3440 + 3689 3661 3530 + 3678 3665 3584 + 3671 3668 3617 + 3667 3669 3637 + 3664 3671 3651 + 2221 0 0 + 2222 0 0 + 2218 0 96 + 2226 0 231 + 2254 0 411 + 2283 0 543 + 2302 0 837 + 2324 0 1096 + 2343 0 1368 + 2368 0 1597 + 2390 0 1826 + 2424 0 2007 + 2540 0 2241 + 2731 0 2529 + 2849 380 2707 + 2924 817 2819 + 2976 1123 2897 + 2308 0 0 + 2310 0 0 + 2313 0 180 + 2324 0 298 + 2355 0 455 + 2384 0 624 + 2411 0 890 + 2436 0 1170 + 2455 0 1446 + 2477 0 1699 + 2498 0 1919 + 2530 0 2109 + 2638 0 2340 + 2812 0 2611 + 2919 489 2780 + 2989 940 2887 + 3038 1255 2963 + 2403 36 0 + 2412 0 0 + 2425 0 199 + 2436 0 336 + 2470 0 475 + 2495 0 688 + 2524 0 943 + 2549 0 1247 + 2568 0 1534 + 2588 0 1799 + 2606 0 2028 + 2637 0 2224 + 2738 0 2444 + 2892 0 2690 + 2989 619 2846 + 3052 1085 2949 + 3097 1411 3020 + 2519 416 0 + 2528 411 0 + 2541 384 222 + 2555 410 367 + 2589 414 514 + 2614 435 743 + 2644 429 1016 + 2669 390 1332 + 2689 0 1633 + 2709 0 1909 + 2725 0 2144 + 2753 0 2348 + 2841 0 2557 + 2974 332 2776 + 3061 771 2919 + 3120 1252 3015 + 3162 1588 3082 + 2629 628 0 + 2641 635 0 + 2656 616 236 + 2672 649 390 + 2708 658 549 + 2733 698 797 + 2761 698 1089 + 2787 731 1413 + 2804 735 1725 + 2824 734 2011 + 2839 751 2257 + 2861 778 2460 + 2932 936 2655 + 3052 1269 2857 + 3134 1503 2993 + 3185 1650 3078 + 3221 1753 3138 + 2770 834 0 + 2785 872 0 + 2805 903 264 + 2819 915 413 + 2857 952 604 + 2882 977 845 + 2912 1017 1169 + 2932 1049 1509 + 2949 1079 1840 + 2965 1107 2136 + 2974 1120 2395 + 2991 1154 2598 + 3048 1300 2782 + 3155 1589 2966 + 3221 1768 3081 + 3263 1880 3153 + 3292 1958 3203 + 2944 1175 0 + 2958 1190 0 + 2976 1189 253 + 2996 1234 441 + 3035 1262 634 + 3062 1313 917 + 3091 1350 1251 + 3111 1403 1617 + 3125 1444 1964 + 3138 1469 2273 + 3144 1508 2536 + 3154 1534 2744 + 3197 1648 2922 + 3276 1892 3078 + 3325 2046 3175 + 3356 2142 3236 + 3378 2209 3278 + 3133 1496 0 + 3150 1537 0 + 3173 1574 0 + 3191 1604 434 + 3230 1665 684 + 3255 1707 974 + 3282 1779 1345 + 3296 1832 1726 + 3306 1882 2087 + 3315 1925 2409 + 3314 1954 2679 + 3317 1980 2887 + 3342 2071 3052 + 3393 2244 3184 + 3431 2362 3271 + 3454 2437 3326 + 3471 2488 3365 + 3350 1938 0 + 3358 1952 0 + 3375 1965 0 + 3397 2019 413 + 3434 2071 695 + 3454 2135 1038 + 3479 2205 1430 + 3486 2272 1829 + 3491 2332 2206 + 3493 2371 2537 + 3488 2412 2816 + 3483 2429 3020 + 3497 2491 3182 + 3521 2605 3295 + 3540 2687 3367 + 3554 2747 3414 + 3564 2790 3447 + 3512 2263 0 + 3530 2299 0 + 3558 2343 0 + 3571 2387 363 + 3606 2453 702 + 3622 2521 1082 + 3642 2602 1494 + 3644 2671 1914 + 3638 2725 2293 + 3636 2778 2641 + 3624 2808 2914 + 3621 2835 3130 + 3627 2882 3288 + 3635 2954 3386 + 3639 3000 3447 + 3641 3028 3485 + 3648 3060 3516 + 3673 2615 0 + 3676 2625 0 + 3688 2645 0 + 3707 2703 0 + 3736 2768 715 + 3751 2842 1114 + 3762 2920 1552 + 3759 2988 1975 + 3750 3049 2363 + 3740 3090 2708 + 3730 3138 2998 + 3721 3156 3209 + 3720 3184 3361 + 3720 3230 3452 + 3719 3260 3510 + 3719 3278 3545 + 3720 3297 3571 + 3746 2787 0 + 3760 2819 0 + 3782 2858 0 + 3795 2908 0 + 3823 2977 738 + 3835 3054 1164 + 3842 3132 1602 + 3838 3211 2033 + 3823 3265 2424 + 3814 3318 2777 + 3797 3350 3050 + 3791 3380 3269 + 3786 3398 3417 + 3772 3408 3495 + 3766 3421 3546 + 3765 3439 3582 + 3765 3452 3607 + 3798 2912 0 + 3818 2960 0 + 3849 3019 0 + 3856 3064 0 + 3880 3138 870 + 3883 3205 1310 + 3892 3289 1735 + 3881 3355 2154 + 3869 3414 2534 + 3858 3466 2872 + 3839 3492 3128 + 3832 3517 3322 + 3828 3536 3457 + 3815 3545 3533 + 3805 3550 3581 + 3799 3554 3611 + 3795 3556 3632 + 3835 3006 0 + 3855 3057 0 + 3879 3117 0 + 3889 3171 0 + 3899 3244 1096 + 3897 3306 1512 + 3902 3385 1917 + 3887 3438 2299 + 3876 3498 2657 + 3864 3541 2962 + 3849 3569 3205 + 3841 3587 3361 + 3837 3606 3497 + 3827 3610 3551 + 3817 3615 3598 + 3812 3619 3628 + 3807 3621 3650 + 3859 3064 0 + 3878 3118 0 + 3898 3178 42 + 3909 3239 318 + 3913 3310 1254 + 3908 3372 1643 + 3906 3444 2038 + 3893 3497 2405 + 3881 3550 2734 + 3867 3588 3018 + 3856 3618 3253 + 3847 3634 3400 + 3842 3649 3521 + 3832 3653 3576 + 3825 3656 3609 + 3819 3659 3639 + 3815 3662 3660 + 3874 3102 0 + 3893 3156 0 + 3911 3217 404 + 3923 3282 726 + 3921 3352 1356 + 3915 3414 1726 + 3909 3482 2115 + 3897 3536 2474 + 3883 3583 2790 + 3870 3619 3054 + 3860 3649 3285 + 3851 3665 3431 + 3845 3677 3537 + 3835 3681 3591 + 3828 3684 3625 + 3824 3685 3646 + 3820 3688 3667 + 3885 3129 0 + 3903 3184 0 + 3919 3245 665 + 3932 3313 1020 + 3927 3382 1429 + 3920 3445 1787 + 3912 3509 2171 + 3900 3564 2523 + 3884 3607 2832 + 3872 3642 3088 + 3862 3670 3310 + 3854 3687 3453 + 3848 3697 3548 + 3838 3701 3603 + 3831 3704 3636 + 3826 3705 3657 + 3823 3706 3672 + 2332 0 0 + 2334 0 0 + 2333 0 116 + 2338 0 240 + 2366 0 427 + 2396 0 562 + 2415 0 859 + 2438 0 1122 + 2454 0 1396 + 2477 0 1628 + 2497 0 1851 + 2530 0 2035 + 2646 0 2270 + 2839 0 2565 + 2958 436 2744 + 3033 873 2855 + 3085 1179 2934 + 2420 0 0 + 2423 0 0 + 2426 0 196 + 2435 0 309 + 2465 0 470 + 2493 0 641 + 2519 0 914 + 2543 0 1194 + 2561 0 1475 + 2582 0 1726 + 2601 0 1949 + 2632 0 2138 + 2740 0 2369 + 2920 0 2645 + 3028 550 2814 + 3097 1001 2921 + 3146 1316 2997 + 2513 31 0 + 2520 0 0 + 2530 0 220 + 2540 0 345 + 2574 0 492 + 2598 0 706 + 2626 0 970 + 2649 0 1269 + 2669 0 1564 + 2689 0 1823 + 2705 0 2059 + 2734 0 2254 + 2835 0 2475 + 2998 0 2721 + 3096 683 2877 + 3160 1149 2979 + 3204 1475 3051 + 2624 439 0 + 2633 442 0 + 2644 432 245 + 2656 449 376 + 2689 458 534 + 2714 482 761 + 2744 478 1042 + 2768 446 1357 + 2789 0 1664 + 2808 0 1934 + 2825 0 2176 + 2851 0 2377 + 2940 30 2585 + 3080 396 2804 + 3168 835 2947 + 3228 1316 3044 + 3269 1653 3111 + 2733 656 0 + 2746 669 0 + 2758 661 257 + 2773 687 397 + 2808 701 570 + 2834 740 815 + 2862 745 1116 + 2886 781 1439 + 2904 783 1754 + 2924 792 2036 + 2940 808 2289 + 2961 842 2490 + 3033 1000 2684 + 3159 1332 2885 + 3241 1566 3022 + 3292 1713 3107 + 3328 1815 3167 + 2873 870 0 + 2889 910 0 + 2906 940 280 + 2920 952 417 + 2958 992 622 + 2983 1018 866 + 3013 1059 1196 + 3033 1089 1536 + 3049 1118 1868 + 3066 1149 2160 + 3077 1169 2427 + 3093 1204 2629 + 3150 1350 2812 + 3262 1648 2994 + 3329 1828 3109 + 3370 1940 3181 + 3399 2019 3232 + 3051 1222 0 + 3065 1243 0 + 3081 1253 270 + 3100 1290 443 + 3138 1322 651 + 3165 1374 936 + 3193 1414 1279 + 3212 1470 1639 + 3227 1510 1993 + 3240 1541 2296 + 3247 1577 2567 + 3257 1608 2769 + 3299 1722 2947 + 3383 1952 3106 + 3433 2105 3203 + 3464 2201 3264 + 3485 2268 3306 + 3239 1550 0 + 3256 1592 0 + 3276 1630 0 + 3292 1656 432 + 3330 1717 698 + 3353 1763 991 + 3380 1834 1370 + 3393 1882 1745 + 3405 1936 2113 + 3413 1978 2429 + 3414 2009 2707 + 3418 2036 2909 + 3443 2127 3074 + 3498 2298 3208 + 3536 2417 3296 + 3560 2491 3350 + 3576 2543 3389 + 3454 1998 0 + 3463 2011 0 + 3478 2026 0 + 3498 2073 407 + 3532 2129 709 + 3552 2196 1053 + 3577 2270 1455 + 3584 2334 1851 + 3590 2396 2238 + 3592 2434 2561 + 3589 2474 2842 + 3584 2490 3040 + 3598 2552 3202 + 3624 2653 3315 + 3643 2734 3388 + 3657 2795 3434 + 3667 2837 3467 + 3615 2322 0 + 3628 2353 0 + 3648 2390 0 + 3663 2433 355 + 3695 2498 719 + 3710 2566 1096 + 3730 2650 1518 + 3732 2715 1930 + 3730 2773 2319 + 3726 2820 2655 + 3718 2855 2935 + 3714 2877 3142 + 3720 2925 3300 + 3736 2993 3404 + 3740 3038 3465 + 3743 3067 3503 + 3749 3098 3534 + 3766 2657 0 + 3769 2669 0 + 3781 2694 0 + 3799 2748 0 + 3828 2814 729 + 3843 2887 1126 + 3853 2966 1571 + 3851 3032 1991 + 3843 3091 2385 + 3834 3131 2722 + 3827 3182 3018 + 3817 3199 3223 + 3816 3228 3375 + 3821 3265 3468 + 3821 3293 3526 + 3821 3312 3561 + 3822 3330 3587 + 3838 2819 0 + 3849 2849 0 + 3864 2883 0 + 3880 2935 0 + 3906 3004 762 + 3918 3078 1177 + 3925 3156 1619 + 3921 3230 2043 + 3910 3289 2441 + 3901 3338 2783 + 3888 3375 3065 + 3880 3399 3274 + 3875 3417 3422 + 3872 3433 3508 + 3867 3446 3560 + 3866 3465 3595 + 3866 3478 3620 + 3889 2944 0 + 3908 2991 0 + 3931 3044 0 + 3940 3091 0 + 3963 3165 893 + 3966 3229 1324 + 3975 3314 1753 + 3964 3374 2165 + 3956 3439 2551 + 3944 3486 2878 + 3930 3517 3142 + 3921 3537 3327 + 3917 3555 3462 + 3915 3570 3546 + 3906 3576 3594 + 3900 3579 3625 + 3896 3582 3646 + 3927 3032 0 + 3946 3085 0 + 3970 3147 0 + 3979 3201 0 + 3991 3272 1116 + 3989 3333 1531 + 3996 3411 1936 + 3983 3464 2319 + 3974 3524 2681 + 3963 3566 2981 + 3949 3593 3221 + 3942 3610 3373 + 3938 3628 3509 + 3933 3633 3564 + 3924 3638 3611 + 3919 3642 3641 + 3914 3644 3663 + 3950 3091 0 + 3969 3146 0 + 3990 3208 63 + 4000 3268 335 + 4004 3338 1274 + 4001 3399 1662 + 4000 3470 2056 + 3989 3523 2424 + 3979 3576 2757 + 3967 3613 3037 + 3956 3641 3270 + 3948 3657 3412 + 3943 3672 3534 + 3939 3676 3589 + 3932 3679 3622 + 3926 3682 3652 + 3922 3685 3673 + 3966 3128 0 + 3984 3184 0 + 4002 3248 425 + 4013 3311 743 + 4013 3380 1376 + 4008 3441 1746 + 4003 3508 2134 + 3993 3561 2493 + 3981 3609 2814 + 3969 3643 3072 + 3960 3672 3301 + 3952 3688 3443 + 3947 3700 3549 + 3942 3704 3604 + 3935 3707 3638 + 3931 3708 3659 + 3927 3711 3680 + 3976 3155 0 + 3995 3212 0 + 4011 3276 686 + 4023 3342 1037 + 4019 3410 1449 + 4013 3471 1806 + 4006 3535 2189 + 3996 3589 2542 + 3982 3633 2855 + 3971 3667 3106 + 3961 3694 3327 + 3955 3710 3466 + 3949 3720 3561 + 3944 3724 3616 + 3938 3727 3649 + 3934 3728 3671 + 3931 3729 3685 + 2402 0 0 + 2405 0 0 + 2405 0 129 + 2409 0 246 + 2438 0 433 + 2466 0 575 + 2487 0 869 + 2508 0 1138 + 2523 0 1414 + 2546 0 1647 + 2563 0 1867 + 2597 0 2052 + 2713 0 2288 + 2906 0 2582 + 3027 470 2766 + 3101 908 2878 + 3153 1214 2956 + 2491 0 0 + 2494 0 0 + 2496 0 206 + 2505 0 315 + 2534 0 482 + 2562 0 649 + 2587 0 928 + 2610 0 1210 + 2628 0 1493 + 2648 0 1743 + 2666 0 1968 + 2697 0 2156 + 2804 0 2387 + 2984 0 2663 + 3096 587 2835 + 3165 1039 2943 + 3214 1354 3018 + 2582 0 0 + 2589 0 0 + 2596 0 233 + 2606 0 351 + 2639 0 512 + 2664 0 711 + 2691 0 988 + 2713 0 1285 + 2733 0 1583 + 2752 0 1839 + 2768 0 2079 + 2797 0 2274 + 2897 0 2494 + 3060 225 2740 + 3163 721 2897 + 3227 1189 2999 + 3272 1515 3071 + 2692 445 0 + 2700 455 0 + 2709 457 260 + 2720 468 382 + 2752 485 554 + 2779 505 768 + 2807 511 1059 + 2831 489 1373 + 2852 30 1683 + 2871 0 1950 + 2888 0 2196 + 2914 0 2396 + 3002 227 2604 + 3142 593 2823 + 3235 885 2966 + 3295 1356 3062 + 3337 1693 3129 + 2800 670 0 + 2812 688 0 + 2823 691 272 + 2836 711 402 + 2870 732 591 + 2898 766 823 + 2924 779 1132 + 2949 811 1455 + 2967 816 1773 + 2987 834 2052 + 3002 847 2309 + 3024 884 2509 + 3095 1046 2702 + 3221 1378 2903 + 3309 1607 3040 + 3360 1753 3125 + 3396 1856 3185 + 2937 893 0 + 2954 934 0 + 2970 964 290 + 2983 975 419 + 3021 1016 635 + 3048 1044 876 + 3076 1085 1213 + 3096 1116 1553 + 3112 1143 1885 + 3129 1176 2175 + 3142 1200 2447 + 3158 1235 2648 + 3215 1382 2831 + 3326 1680 3013 + 3396 1866 3127 + 3438 1978 3199 + 3467 2057 3250 + 3118 1252 0 + 3133 1276 0 + 3148 1293 281 + 3166 1326 445 + 3202 1362 668 + 3230 1410 943 + 3256 1455 1296 + 3276 1510 1657 + 3292 1551 2012 + 3304 1585 2310 + 3312 1621 2587 + 3322 1653 2788 + 3364 1769 2963 + 3448 1999 3121 + 3500 2142 3221 + 3531 2238 3281 + 3553 2305 3324 + 3306 1584 0 + 3323 1626 0 + 3341 1663 0 + 3357 1688 432 + 3392 1748 710 + 3417 1795 999 + 3442 1867 1385 + 3456 1916 1760 + 3469 1970 2130 + 3476 2009 2443 + 3478 2043 2726 + 3482 2070 2928 + 3507 2160 3090 + 3562 2332 3224 + 3603 2453 3311 + 3626 2527 3366 + 3643 2579 3404 + 3521 2033 0 + 3529 2048 0 + 3542 2066 0 + 3561 2108 404 + 3593 2166 724 + 3614 2232 1058 + 3637 2309 1470 + 3645 2373 1867 + 3652 2433 2256 + 3653 2471 2573 + 3651 2512 2857 + 3647 2528 3054 + 3661 2590 3213 + 3687 2691 3327 + 3708 2766 3401 + 3722 2826 3448 + 3732 2868 3480 + 3679 2358 0 + 3690 2387 0 + 3705 2419 0 + 3721 2462 350 + 3749 2526 741 + 3767 2595 1099 + 3784 2678 1532 + 3789 2746 1945 + 3787 2802 2335 + 3783 2846 2664 + 3778 2884 2948 + 3773 2906 3153 + 3779 2951 3307 + 3795 3020 3411 + 3804 3063 3476 + 3807 3091 3514 + 3814 3123 3545 + 3824 2683 0 + 3828 2697 0 + 3839 2725 0 + 3857 2776 0 + 3885 2844 745 + 3901 2916 1129 + 3910 2995 1582 + 3909 3061 2002 + 3901 3117 2399 + 3894 3156 2731 + 3888 3210 3031 + 3878 3227 3235 + 3877 3255 3384 + 3882 3292 3477 + 3885 3315 3536 + 3885 3333 3571 + 3886 3351 3598 + 3896 2841 0 + 3906 2872 0 + 3919 2905 0 + 3935 2956 0 + 3958 3025 788 + 3973 3099 1182 + 3977 3175 1631 + 3976 3251 2054 + 3966 3309 2453 + 3957 3355 2788 + 3947 3396 3075 + 3938 3418 3282 + 3933 3435 3427 + 3930 3450 3513 + 3930 3464 3569 + 3930 3482 3604 + 3930 3495 3629 + 3947 2964 0 + 3964 3010 0 + 3983 3060 0 + 3994 3108 0 + 4012 3181 924 + 4020 3246 1329 + 4025 3326 1766 + 4017 3391 2174 + 4010 3455 2562 + 3999 3498 2882 + 3988 3533 3151 + 3978 3551 3334 + 3974 3567 3466 + 3971 3582 3549 + 3969 3592 3603 + 3963 3595 3633 + 3959 3598 3654 + 3984 3052 0 + 4003 3104 0 + 4022 3163 0 + 4033 3218 0 + 4041 3288 1147 + 4043 3350 1537 + 4046 3424 1948 + 4036 3480 2329 + 4029 3539 2691 + 4017 3578 2984 + 4007 3609 3230 + 3999 3624 3380 + 3994 3640 3512 + 3989 3645 3567 + 3988 3654 3620 + 3982 3658 3650 + 3978 3660 3671 + 4008 3107 0 + 4027 3163 0 + 4047 3228 77 + 4057 3287 345 + 4062 3356 1287 + 4059 3416 1675 + 4059 3487 2068 + 4048 3539 2436 + 4041 3592 2772 + 4029 3628 3048 + 4018 3656 3280 + 4011 3671 3422 + 4007 3686 3541 + 4002 3691 3596 + 3999 3693 3631 + 3994 3697 3660 + 3989 3699 3682 + 4023 3145 0 + 4041 3202 0 + 4059 3267 439 + 4070 3330 753 + 4070 3398 1388 + 4066 3458 1759 + 4062 3524 2146 + 4052 3578 2505 + 4043 3625 2828 + 4031 3658 3084 + 4022 3687 3312 + 4015 3702 3453 + 4010 3714 3557 + 4006 3719 3612 + 4003 3721 3646 + 3999 3723 3667 + 3994 3725 3688 + 4034 3172 0 + 4052 3230 0 + 4068 3295 700 + 4080 3361 1047 + 4076 3428 1461 + 4071 3489 1819 + 4064 3552 2201 + 4055 3606 2554 + 4044 3649 2870 + 4033 3682 3118 + 4024 3708 3337 + 4018 3725 3475 + 4013 3734 3568 + 4008 3739 3623 + 4005 3741 3658 + 4001 3743 3679 + 3998 3744 3693 + 2447 0 0 + 2450 0 0 + 2451 0 138 + 2455 0 250 + 2484 0 437 + 2511 0 583 + 2533 0 876 + 2554 0 1149 + 2569 0 1425 + 2591 0 1659 + 2606 0 1878 + 2640 0 2062 + 2756 0 2299 + 2949 0 2594 + 3070 470 2778 + 3145 931 2893 + 3197 1237 2971 + 2536 0 0 + 2539 0 0 + 2542 0 211 + 2550 0 319 + 2580 0 488 + 2607 0 655 + 2632 0 935 + 2655 0 1221 + 2672 0 1503 + 2691 0 1755 + 2709 0 1980 + 2739 0 2168 + 2846 0 2398 + 3026 0 2674 + 3138 587 2847 + 3209 1063 2957 + 3258 1378 3032 + 2628 0 0 + 2634 0 0 + 2640 0 242 + 2650 0 355 + 2681 0 524 + 2708 0 715 + 2733 0 999 + 2756 0 1296 + 2775 0 1593 + 2793 0 1848 + 2809 0 2091 + 2838 0 2287 + 2937 0 2506 + 3100 225 2753 + 3203 721 2909 + 3271 1214 3013 + 3315 1540 3084 + 2736 444 0 + 2744 458 0 + 2751 469 268 + 2762 477 385 + 2794 500 566 + 2821 517 772 + 2849 530 1071 + 2872 526 1384 + 2892 327 1692 + 2912 249 1960 + 2928 0 2209 + 2954 0 2409 + 3041 478 2616 + 3181 844 2835 + 3275 1136 2979 + 3338 1383 3075 + 3380 1719 3142 + 2842 679 0 + 2855 701 0 + 2864 711 281 + 2877 727 406 + 2910 751 604 + 2938 782 828 + 2965 800 1143 + 2989 829 1466 + 3007 839 1784 + 3027 861 2062 + 3042 873 2322 + 3064 909 2522 + 3135 1076 2714 + 3261 1408 2915 + 3348 1636 3051 + 3403 1779 3137 + 3439 1882 3196 + 2979 907 0 + 2996 949 0 + 3011 979 296 + 3024 990 421 + 3061 1031 643 + 3089 1060 882 + 3116 1101 1224 + 3137 1132 1565 + 3153 1159 1896 + 3170 1194 2184 + 3183 1219 2459 + 3200 1254 2661 + 3256 1402 2843 + 3368 1700 3025 + 3437 1886 3139 + 3481 2003 3211 + 3510 2081 3261 + 3162 1271 0 + 3176 1298 0 + 3190 1319 288 + 3208 1348 445 + 3243 1388 678 + 3272 1434 947 + 3297 1482 1307 + 3318 1535 1668 + 3333 1578 2022 + 3345 1614 2319 + 3353 1649 2599 + 3364 1681 2800 + 3405 1798 2973 + 3489 2029 3132 + 3542 2172 3231 + 3575 2262 3293 + 3596 2329 3335 + 3348 1606 0 + 3365 1648 0 + 3383 1683 0 + 3399 1709 431 + 3433 1768 718 + 3458 1816 1004 + 3482 1887 1394 + 3497 1939 1771 + 3509 1990 2139 + 3516 2029 2452 + 3519 2065 2738 + 3523 2091 2940 + 3549 2182 3101 + 3604 2353 3234 + 3644 2474 3322 + 3669 2549 3376 + 3686 2601 3415 + 3564 2055 0 + 3571 2071 0 + 3584 2092 0 + 3602 2130 403 + 3631 2190 736 + 3653 2254 1061 + 3675 2334 1480 + 3684 2397 1877 + 3690 2456 2262 + 3691 2494 2578 + 3691 2536 2866 + 3686 2552 3063 + 3700 2614 3220 + 3726 2715 3333 + 3747 2790 3407 + 3764 2848 3457 + 3774 2890 3489 + 3721 2382 0 + 3730 2409 0 + 3742 2438 0 + 3759 2481 347 + 3784 2543 755 + 3804 2613 1102 + 3819 2695 1541 + 3825 2766 1954 + 3823 2820 2343 + 3820 2864 2670 + 3816 2903 2956 + 3811 2925 3162 + 3817 2969 3312 + 3832 3037 3416 + 3842 3080 3481 + 3848 3107 3522 + 3855 3139 3553 + 3861 2700 0 + 3865 2714 0 + 3877 2745 0 + 3895 2794 0 + 3921 2863 756 + 3938 2934 1131 + 3947 3014 1589 + 3946 3079 2010 + 3938 3135 2406 + 3932 3173 2736 + 3927 3228 3039 + 3917 3245 3243 + 3916 3272 3389 + 3921 3309 3483 + 3924 3332 3541 + 3926 3347 3578 + 3927 3365 3604 + 3933 2858 0 + 3944 2889 0 + 3956 2925 0 + 3972 2974 0 + 3995 3044 798 + 4010 3117 1184 + 4014 3194 1639 + 4013 3270 2061 + 4003 3326 2459 + 3995 3372 2794 + 3986 3413 3083 + 3978 3436 3290 + 3972 3452 3432 + 3969 3468 3519 + 3969 3482 3574 + 3971 3496 3611 + 3971 3509 3636 + 3984 2976 0 + 4000 3022 0 + 4016 3070 0 + 4028 3119 0 + 4044 3191 944 + 4054 3257 1332 + 4057 3335 1774 + 4052 3402 2181 + 4044 3463 2566 + 4034 3506 2885 + 4024 3543 3156 + 4015 3561 3339 + 4010 3575 3468 + 4007 3590 3551 + 4005 3599 3605 + 4004 3605 3639 + 4000 3608 3660 + 4021 3065 0 + 4039 3117 0 + 4055 3173 0 + 4067 3229 0 + 4072 3298 1166 + 4077 3360 1540 + 4078 3432 1956 + 4070 3491 2335 + 4063 3547 2696 + 4053 3586 2987 + 4043 3618 3236 + 4036 3635 3386 + 4030 3648 3514 + 4025 3653 3569 + 4024 3662 3622 + 4023 3668 3655 + 4019 3670 3677 + 4045 3120 0 + 4063 3176 0 + 4080 3238 77 + 4091 3298 345 + 4093 3366 1307 + 4093 3427 1678 + 4091 3495 2076 + 4083 3550 2443 + 4074 3600 2777 + 4064 3636 3051 + 4055 3666 3285 + 4048 3681 3428 + 4043 3694 3543 + 4038 3698 3598 + 4035 3701 3633 + 4034 3707 3666 + 4030 3710 3687 + 4060 3156 0 + 4078 3213 0 + 4095 3279 447 + 4095 3342 760 + 4095 3410 1396 + 4095 3469 1767 + 4095 3535 2153 + 4090 3588 2512 + 4082 3636 2837 + 4071 3668 3091 + 4062 3696 3318 + 4056 3712 3459 + 4051 3723 3562 + 4046 3728 3617 + 4044 3730 3651 + 4042 3732 3673 + 4038 3735 3694 + 4071 3183 0 + 4089 3241 0 + 4095 3307 708 + 4095 3373 1054 + 4095 3440 1469 + 4095 3500 1827 + 4095 3562 2209 + 4093 3616 2562 + 4083 3660 2878 + 4073 3692 3125 + 4064 3718 3344 + 4059 3734 3482 + 4053 3743 3573 + 4049 3748 3628 + 4046 3750 3662 + 4044 3752 3684 + 4041 3753 3699 + 2479 0 0 + 2483 0 0 + 2485 0 144 + 2488 0 252 + 2518 0 440 + 2543 0 590 + 2566 0 881 + 2586 0 1156 + 2602 0 1432 + 2623 0 1668 + 2639 0 1887 + 2671 0 2070 + 2787 0 2308 + 2980 0 2602 + 3101 470 2786 + 3176 931 2901 + 3229 1253 2982 + 2569 0 0 + 2572 0 0 + 2575 0 215 + 2583 0 322 + 2613 0 492 + 2640 0 659 + 2665 0 941 + 2687 0 1228 + 2704 0 1511 + 2723 0 1764 + 2740 0 1989 + 2770 0 2176 + 2877 0 2407 + 3056 0 2683 + 3168 587 2855 + 3240 1063 2965 + 3290 1396 3043 + 2661 0 0 + 2667 0 0 + 2672 0 249 + 2681 0 358 + 2712 0 533 + 2739 0 717 + 2764 0 1007 + 2786 0 1303 + 2805 0 1600 + 2823 0 1857 + 2839 0 2098 + 2867 0 2296 + 2965 0 2515 + 3129 225 2761 + 3232 721 2918 + 3300 1214 3021 + 3347 1559 3094 + 2768 442 0 + 2775 461 0 + 2782 477 274 + 2793 484 388 + 2823 511 575 + 2851 526 774 + 2878 545 1079 + 2902 553 1392 + 2922 542 1699 + 2941 456 1968 + 2957 58 2216 + 2983 0 2418 + 3069 660 2625 + 3210 1026 2844 + 3303 1318 2987 + 3367 1565 3084 + 3411 1737 3151 + 2873 685 0 + 2885 709 0 + 2895 725 288 + 2907 738 409 + 2939 765 614 + 2968 794 831 + 2994 816 1151 + 3018 843 1474 + 3036 855 1791 + 3056 877 2070 + 3071 892 2330 + 3093 928 2532 + 3163 1097 2722 + 3290 1429 2923 + 3377 1658 3060 + 3432 1800 3145 + 3471 1900 3205 + 3009 918 0 + 3026 961 0 + 3041 990 301 + 3053 1000 422 + 3090 1042 649 + 3119 1072 887 + 3146 1113 1231 + 3167 1145 1573 + 3182 1171 1904 + 3199 1205 2192 + 3213 1232 2466 + 3230 1269 2671 + 3286 1416 2852 + 3397 1715 3034 + 3467 1901 3148 + 3511 2017 3220 + 3541 2099 3269 + 3193 1285 0 + 3207 1313 0 + 3221 1338 293 + 3239 1365 446 + 3273 1407 686 + 3302 1450 951 + 3327 1501 1315 + 3347 1553 1676 + 3362 1598 2028 + 3375 1633 2328 + 3383 1670 2606 + 3394 1701 2810 + 3435 1820 2980 + 3519 2050 3139 + 3572 2194 3238 + 3605 2284 3300 + 3628 2347 3343 + 3379 1622 0 + 3396 1664 0 + 3413 1698 0 + 3429 1724 431 + 3462 1783 724 + 3488 1832 1008 + 3511 1902 1401 + 3526 1955 1778 + 3538 2004 2145 + 3546 2044 2460 + 3549 2080 2744 + 3553 2107 2949 + 3579 2197 3108 + 3634 2369 3242 + 3674 2490 3329 + 3699 2565 3384 + 3717 2618 3422 + 3595 2070 0 + 3602 2087 0 + 3613 2111 0 + 3631 2146 402 + 3658 2207 744 + 3682 2271 1063 + 3702 2352 1487 + 3712 2414 1885 + 3717 2472 2267 + 3719 2510 2584 + 3718 2552 2870 + 3715 2569 3070 + 3729 2632 3224 + 3755 2732 3337 + 3776 2808 3412 + 3793 2865 3461 + 3805 2906 3496 + 3751 2399 0 + 3761 2426 0 + 3772 2456 0 + 3788 2497 345 + 3813 2560 761 + 3833 2630 1104 + 3847 2714 1548 + 3854 2785 1962 + 3852 2839 2350 + 3849 2882 2679 + 3845 2922 2963 + 3840 2943 3169 + 3846 2986 3318 + 3862 3055 3422 + 3872 3098 3487 + 3878 3125 3528 + 3885 3152 3558 + 3891 2716 0 + 3894 2730 0 + 3903 2759 0 + 3922 2807 0 + 3947 2876 765 + 3965 2947 1133 + 3972 3026 1596 + 3973 3094 2017 + 3964 3148 2410 + 3959 3186 2743 + 3954 3240 3043 + 3945 3258 3249 + 3943 3285 3393 + 3948 3322 3486 + 3951 3345 3545 + 3953 3359 3581 + 3957 3376 3609 + 3960 2870 0 + 3971 2902 0 + 3983 2939 0 + 3999 2987 0 + 4021 3057 806 + 4037 3130 1186 + 4041 3207 1644 + 4039 3283 2067 + 4030 3339 2464 + 4023 3384 2800 + 4014 3425 3087 + 4006 3449 3296 + 4000 3465 3437 + 3997 3480 3523 + 3997 3494 3578 + 3999 3509 3615 + 4001 3519 3641 + 4011 2986 0 + 4026 3031 0 + 4040 3077 0 + 4053 3127 0 + 4068 3199 958 + 4079 3265 1335 + 4081 3341 1779 + 4077 3410 2186 + 4068 3469 2569 + 4060 3513 2889 + 4050 3548 3158 + 4042 3569 3344 + 4036 3581 3469 + 4033 3595 3552 + 4031 3605 3606 + 4030 3611 3640 + 4029 3615 3664 + 4048 3074 0 + 4065 3126 0 + 4079 3181 0 + 4092 3237 0 + 4095 3306 1181 + 4095 3368 1542 + 4095 3438 1962 + 4095 3500 2340 + 4087 3553 2699 + 4078 3593 2991 + 4069 3624 3237 + 4063 3642 3390 + 4056 3654 3516 + 4052 3658 3571 + 4050 3668 3623 + 4049 3674 3657 + 4048 3678 3680 + 4072 3130 0 + 4089 3185 0 + 4095 3245 77 + 4095 3306 345 + 4095 3374 1321 + 4095 3435 1681 + 4095 3501 2082 + 4095 3559 2447 + 4095 3606 2780 + 4089 3643 3055 + 4080 3671 3287 + 4075 3689 3432 + 4069 3700 3545 + 4064 3704 3600 + 4061 3707 3634 + 4060 3713 3667 + 4060 3717 3691 + 4087 3165 0 + 4095 3222 0 + 4095 3286 447 + 4095 3350 760 + 4095 3417 1410 + 4095 3477 1769 + 4095 3541 2159 + 4095 3597 2517 + 4095 3641 2840 + 4095 3675 3096 + 4088 3702 3320 + 4082 3719 3464 + 4077 3729 3563 + 4072 3733 3618 + 4070 3736 3653 + 4068 3738 3674 + 4067 3742 3698 + 4095 3191 0 + 4095 3250 0 + 4095 3316 714 + 4095 3381 1059 + 4095 3448 1475 + 4095 3508 1833 + 4095 3570 2214 + 4095 3624 2568 + 4095 3667 2884 + 4095 3699 3132 + 4093 3725 3350 + 4088 3741 3486 + 4083 3750 3577 + 4078 3754 3632 + 4076 3757 3666 + 4074 3759 3687 + 4072 3760 3703 + diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 189071a763e..360b325559d 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -444,7 +444,7 @@ static void colormanage_role_color_space_name_get(ConstConfigRcPtr *config, char OCIO_colorSpaceRelease(ociocs); } else { - printf("Blender color management: Error could not find role %s role.\n", role); + printf("Color management: Error could not find role %s role.\n", role); } } @@ -2162,10 +2162,10 @@ static void colormanage_description_strip(char *description) ColorSpace *colormanage_colorspace_add(const char *name, const char *description, int is_invertible) { - ColorSpace *colorspace; + ColorSpace *colorspace, *prev_space; + int counter = 1; colorspace = MEM_callocN(sizeof(ColorSpace), "ColorSpace"); - colorspace->index = global_tot_colorspace + 1; BLI_strncpy(colorspace->name, name, sizeof(colorspace->name)); @@ -2177,7 +2177,22 @@ ColorSpace *colormanage_colorspace_add(const char *name, const char *description colorspace->is_invertible = is_invertible; - BLI_addtail(&global_colorspaces, colorspace); + for (prev_space = global_colorspaces.first; prev_space; prev_space = prev_space->next) { + if (BLI_strcasecmp(prev_space->name, colorspace->name) > 0) + break; + + prev_space->index = counter++; + } + + if (!prev_space) + BLI_addtail(&global_colorspaces, colorspace); + else + BLI_insertlinkbefore(&global_colorspaces, prev_space, colorspace); + + colorspace->index = counter++; + for (; prev_space; prev_space = prev_space->next) { + prev_space->index = counter++; + } global_tot_colorspace++; From 777a49dfef19d954a000c5d7e422e8650c1854b5 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 11 Sep 2012 09:13:57 +0000 Subject: [PATCH 133/160] Merging r50502 through r50521 from trunk into soc-2011-tomato --- intern/cycles/render/session.cpp | 2 +- intern/string/STR_String.h | 50 +-- intern/string/intern/STR_String.cpp | 341 +++++++++--------- release/scripts/startup/bl_ui/space_image.py | 2 +- .../blender/blenkernel/intern/dynamicpaint.c | 6 +- source/blender/blenkernel/intern/fcurve.c | 8 +- source/blender/blenkernel/intern/softbody.c | 2 +- source/blender/blenlib/intern/scanfill.c | 14 +- source/blender/bmesh/intern/bmesh_core.c | 13 +- source/blender/bmesh/intern/bmesh_iterators.c | 34 ++ source/blender/bmesh/intern/bmesh_iterators.h | 17 +- source/blender/bmesh/intern/bmesh_queries.c | 50 +-- source/blender/editors/animation/keyframing.c | 5 +- source/blender/editors/mesh/editmesh_bvh.c | 5 - source/blender/editors/mesh/editmesh_select.c | 7 +- .../blender/editors/physics/particle_edit.c | 2 +- source/blender/editors/screen/screen_edit.c | 20 +- .../editors/sculpt_paint/paint_image.c | 48 ++- .../editors/transform/transform_conversions.c | 4 +- source/blender/python/intern/bpy_interface.c | 9 + .../blender/windowmanager/intern/wm_files.c | 5 + .../gameengine/Rasterizer/RAS_MeshObject.cpp | 8 +- 22 files changed, 359 insertions(+), 293 deletions(-) diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 2fb1f49e563..0efbcb8afd3 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -320,7 +320,7 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile) /* get next tile from manager */ Tile tile; - int device_num = device->device_number(tile_device); + int device_num = (params.background)? 0: device->device_number(tile_device); if(!tile_manager.next_tile(tile, device_num)) return false; diff --git a/intern/string/STR_String.h b/intern/string/STR_String.h index 98de5be9647..6e9f6007e0b 100644 --- a/intern/string/STR_String.h +++ b/intern/string/STR_String.h @@ -66,8 +66,8 @@ typedef const STR_String& rcSTR_String; typedef unsigned char byte; /** - * Smart String Value class. Is used by parser when an expression tree is build containing string. -*/ + * Smart String Value class. Is used by parser when an expression tree is build containing string. + */ class STR_String { @@ -85,16 +85,16 @@ public: explicit STR_String(dword val); explicit STR_String(float val); explicit STR_String(double val); - inline ~STR_String() { delete[] pData; } + inline ~STR_String() { delete[] this->m_data; } // Operations STR_String& Format(const char *fmt, ...); // Set formatted text to string STR_String& FormatAdd(const char *fmt, ...); // Add formatted text to string - inline void Clear() { Len = pData[0] = 0; } + inline void Clear() { this->m_len = this->m_data[0] = 0; } inline const STR_String & Reverse() { - for (int i1 = 0, i2 = Len - 1; i1 < i2; i1++, i2--) { - std::swap(pData[i1], pData[i2]); + for (int i1 = 0, i2 = this->m_len - 1; i1 < i2; i1++, i2--) { + std::swap(this->m_data[i1], this->m_data[i2]); } return *this; } @@ -102,28 +102,28 @@ public: // Properties bool IsUpper() const; bool IsLower() const; - inline bool IsEmpty() const { return Len == 0; } - inline int Length() const { return Len; } + inline bool IsEmpty() const { return this->m_len == 0; } + inline int Length() const { return this->m_len; } // Data access - inline STR_String& SetLength(int len) { AllocBuffer(len, true); Len=len; pData[len]=0; return *this; } - inline char GetAt(int pos) const { assertd(posm_len = len; this->m_data[len] = 0; return *this; } + inline char GetAt(int pos) const { assertd(posm_len); return this->m_data[pos]; } + inline void SetAt(int pos, char c) { assertd(posm_len); this->m_data[pos] = c; } inline void SetAt(int pos, rcSTR_String str); inline void SetAt(int pos, int num, rcSTR_String str); void Replace(int pos, rcSTR_String str); void Replace(int pos, int num, rcSTR_String str); // Substrings - inline STR_String Left(int num) const { num = (num < Len ? num:Len ); return STR_String(pData, num); } - inline STR_String Right(int num) const { num = (num < Len ? num:Len ); return STR_String(pData+Len-num, num); } - inline STR_String Mid(int pos, int num = INT_MAX) const { pos = (pos < Len ? pos:Len ); num = (num < (Len - pos) ? num : (Len - pos)); return STR_String(pData+pos, num); } + inline STR_String Left(int num) const { num = (num < this->m_len ? num:this->m_len ); return STR_String(this->m_data, num); } + inline STR_String Right(int num) const { num = (num < this->m_len ? num:this->m_len ); return STR_String(this->m_data + this->m_len - num, num); } + inline STR_String Mid(int pos, int num = INT_MAX) const { pos = (pos < this->m_len ? pos:this->m_len ); num = (num < (this->m_len - pos) ? num : (this->m_len - pos)); return STR_String(this->m_data + pos, num); } // Comparison int Compare(rcSTR_String rhs) const; int CompareNoCase(rcSTR_String rhs) const; - inline bool IsEqual(rcSTR_String rhs) const { return (Compare(rhs) == 0); } - inline bool IsEqualNoCase(rcSTR_String rhs) const { return (CompareNoCase(rhs) == 0); } + inline bool IsEqual(rcSTR_String rhs) const { return (Compare(rhs) == 0); } + inline bool IsEqualNoCase(rcSTR_String rhs) const { return (CompareNoCase(rhs) == 0); } // Search/replace int Find(char c, int pos = 0) const; @@ -148,12 +148,12 @@ public: STR_String& TrimQuotes(); // Conversions -// inline operator char*() { return pData; } - inline operator const char *() const { return pData; } - inline char *Ptr() { return pData; } - inline const char *ReadPtr() const { return pData; } - inline float ToFloat() const { float x=(float)(atof(pData)); return x; } - inline int ToInt() const { return atoi(pData); } +// inline operator char*() { return this->m_data; } + inline operator const char *() const { return this->m_data; } + inline char *Ptr() { return this->m_data; } + inline const char *ReadPtr() const { return this->m_data; } + inline float ToFloat() const { float x=(float)(atof(this->m_data)); return x; } + inline int ToInt() const { return atoi(this->m_data); } // Operators inline rcSTR_String operator=(const byte *rhs) { return Copy((const char *)rhs, strlen((const char *)rhs)); } @@ -198,9 +198,9 @@ protected: static bool isUpper(char c) { return (c>='A') && (c <= 'Z'); } static bool isSpace(char c) { return (c==' ') || (c=='\t'); } - char *pData; // -> STR_String data - int Len; // Data length - int Max; // Space in data buffer + char *m_data; // -> STR_String data + int m_len; //z Data length + int m_max; // Space in data buffer #ifdef WITH_CXX_GUARDEDALLOC diff --git a/intern/string/intern/STR_String.cpp b/intern/string/intern/STR_String.cpp index bea6e88cfff..4b2261e89f9 100644 --- a/intern/string/intern/STR_String.cpp +++ b/intern/string/intern/STR_String.cpp @@ -27,14 +27,9 @@ /** \file string/intern/STR_String.cpp * \ingroup string - */ - - -/** - + * * Copyright (C) 2001 NaN Technologies B.V. * This file was formerly known as: GEN_StdString.cpp. - * @date April, 25, 2001 */ #include @@ -51,17 +46,18 @@ Construction / destruction -------------------------------------------------------------------------------------------------*/ - +#define STR_STRING_SIZE_DEFAULT_WORD 32 /* default size for a new word */ +#define STR_STRING_SIZE_DEFAULT_CHAR 9 /* default size for a new char */ // // Construct an empty string // STR_String::STR_String() : - pData(new char[32]), - Len(0), - Max(32) + m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), + m_len(0), + m_max(STR_STRING_SIZE_DEFAULT_WORD) { - pData[0] = 0; + this->m_data[0] = 0; } @@ -70,12 +66,12 @@ STR_String::STR_String() : // Construct a string of one character // STR_String::STR_String(char c) : - pData(new char[9]), - Len(1), - Max(9) + m_data(new char[STR_STRING_SIZE_DEFAULT_CHAR]), + m_len(1), + m_max(STR_STRING_SIZE_DEFAULT_CHAR) { - pData[0] = c; - pData[1] = 0; + this->m_data[0] = c; + this->m_data[1] = 0; } @@ -84,13 +80,13 @@ STR_String::STR_String(char c) : // Construct a string of multiple repeating characters // STR_String::STR_String(char c, int len) : - pData(new char[len + 8]), - Len(len), - Max(len + 8) + m_data(new char[len + 8]), + m_len(len), + m_max(len + 8) { - assertd(pData != NULL); - memset(pData, c, len); - pData[len] = 0; + assertd(this->m_data != NULL); + memset(this->m_data, c, len); + this->m_data[len] = 0; } @@ -102,17 +98,17 @@ STR_String::STR_String(char c, int len) : STR_String::STR_String(const char *str) { if (str) { - Len = ::strlen(str); - Max = Len + 8; - pData = new char[Max]; - assertd(pData != NULL); - ::memcpy(pData, str, Len); - pData[Len] = 0; + this->m_len = ::strlen(str); + this->m_max = this->m_len + 8; + this->m_data = new char[this->m_max]; + assertd(this->m_data != NULL); + ::memcpy(this->m_data, str, this->m_len); + this->m_data[this->m_len] = 0; } else { - pData = 0; - Len = 0; - Max = 8; + this->m_data = 0; + this->m_len = 0; + this->m_max = 8; } } @@ -122,13 +118,13 @@ STR_String::STR_String(const char *str) // Construct a string from a pointer-to-ASCII-string and a length // STR_String::STR_String(const char *str, int len) : - pData(new char[len + 8]), - Len(len), - Max(len + 8) + m_data(new char[len + 8]), + m_len(len), + m_max(len + 8) { - assertd(pData != NULL); - memcpy(pData, str, len); - pData[len] = 0; + assertd(this->m_data != NULL); + memcpy(this->m_data, str, len); + this->m_data[len] = 0; } @@ -137,14 +133,14 @@ STR_String::STR_String(const char *str, int len) : // Construct a string from another string // STR_String::STR_String(rcSTR_String str) : - pData(new char[str.Length() + 8]), - Len(str.Length()), - Max(str.Length() + 8) + m_data(new char[str.Length() + 8]), + m_len(str.Length()), + m_max(str.Length() + 8) { - assertd(pData != NULL); - assertd(str.pData != NULL); - memcpy(pData, str.pData, str.Length()); - pData[str.Length()] = 0; + assertd(this->m_data != NULL); + assertd(str.this->m_data != NULL); + memcpy(this->m_data, str.ReadPtr(), str.Length()); + this->m_data[str.Length()] = 0; } @@ -153,14 +149,14 @@ STR_String::STR_String(rcSTR_String str) : // Construct a string from the first number of characters in another string // STR_String::STR_String(rcSTR_String str, int len) : - pData(new char[len + 8]), - Len(len), - Max(len + 8) + m_data(new char[len + 8]), + m_len(len), + m_max(len + 8) { - assertd(pData != NULL); - assertd(str.pData != NULL); - memcpy(pData, str.pData, str.Length()); - pData[str.Length()] = 0; + assertd(this->m_data != NULL); + assertd(str.this->m_data != NULL); + memcpy(this->m_data, str.ReadPtr(), str.Length()); + this->m_data[str.Length()] = 0; } @@ -169,14 +165,14 @@ STR_String::STR_String(rcSTR_String str, int len) : // Create a string by concatenating two sources // STR_String::STR_String(const char *src1, int len1, const char *src2, int len2) : - pData(new char[len1 + len2 + 8]), - Len(len1 + len2), - Max(len1 + len2 + 8) + m_data(new char[len1 + len2 + 8]), + m_len(len1 + len2), + m_max(len1 + len2 + 8) { - assertd(pData != NULL); - memcpy(pData, src1, len1); - memcpy(pData + len1, src2, len2); - pData[len1 + len2] = 0; + assertd(this->m_data != NULL); + memcpy(this->m_data, src1, len1); + memcpy(this->m_data + len1, src2, len2); + this->m_data[len1 + len2] = 0; } @@ -185,11 +181,11 @@ STR_String::STR_String(const char *src1, int len1, const char *src2, int len2) : // Create a string with an integer value // STR_String::STR_String(int val) : - pData(new char[32]), - Max(32) + m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), + m_max(STR_STRING_SIZE_DEFAULT_WORD) { - assertd(pData != NULL); - Len = sprintf(pData, "%d", val); + assertd(this->m_data != NULL); + this->m_len = sprintf(this->m_data, "%d", val); } @@ -199,11 +195,11 @@ STR_String::STR_String(int val) : // Create a string with a dword value // STR_String::STR_String(dword val) : - pData(new char[32]), - Max(32) + m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), + m_max(STR_STRING_SIZE_DEFAULT_WORD) { - assertd(pData != NULL); - Len = sprintf(pData, "%lu", val); + assertd(this->m_data != NULL); + this->m_len = sprintf(this->m_data, "%lu", val); } @@ -212,11 +208,11 @@ STR_String::STR_String(dword val) : // Create a string with a floating point value // STR_String::STR_String(float val) : - pData(new char[32]), - Max(32) + m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), + m_max(STR_STRING_SIZE_DEFAULT_WORD) { - assertd(pData != NULL); - Len = sprintf(pData, "%g", val); + assertd(this->m_data != NULL); + this->m_len = sprintf(this->m_data, "%g", val); } @@ -225,11 +221,11 @@ STR_String::STR_String(float val) : // Create a string with a double value // STR_String::STR_String(double val) : - pData(new char[32]), - Max(32) + m_data(new char[STR_STRING_SIZE_DEFAULT_WORD]), + m_max(STR_STRING_SIZE_DEFAULT_WORD) { - assertd(pData != NULL); - Len = sprintf(pData, "%g", val); + assertd(this->m_data != NULL); + this->m_len = sprintf(this->m_data, "%g", val); } @@ -246,17 +242,19 @@ STR_String::STR_String(double val) : void STR_String::AllocBuffer(int len, bool keep_contents) { // Check if we have enough space - if (len + 1 <= Max) return; + if (len + 1 <= this->m_max) return; // Reallocate string char *new_data = new char[len + 8]; - if (keep_contents) memcpy(new_data, pData, Len); - delete[] pData; + if (keep_contents) { + memcpy(new_data, this->m_data, this->m_len); + } + delete[] this->m_data; // Accept new data - Max = len + 8; - pData = new_data; - assertd(pData != NULL); + this->m_max = len + 8; + this->m_data = new_data; + assertd(this->m_data != NULL); } @@ -274,12 +272,12 @@ STR_String& STR_String::Format(const char *fmt, ...) { AllocBuffer(2048, false); - assertd(pData != NULL); + assertd(this->m_data != NULL); // Expand arguments and format to string va_list args; va_start(args, fmt); - Len = vsprintf(pData, fmt, args); - assertd(Len <= 2048); + this->m_len = vsprintf(this->m_data, fmt, args); + assertd(this->m_len <= 2048); va_end(args); return *this; @@ -294,12 +292,12 @@ STR_String& STR_String::FormatAdd(const char *fmt, ...) { AllocBuffer(2048, false); - assertd(pData != NULL); + assertd(this->m_data != NULL); // Expand arguments and format to string va_list args; va_start(args, fmt); - Len += vsprintf(pData + Len, fmt, args); - assertd(Len <= 2048); + this->m_len += vsprintf(this->m_data + this->m_len, fmt, args); + assertd(this->m_len <= 2048); va_end(args); return *this; @@ -318,8 +316,8 @@ STR_String& STR_String::FormatAdd(const char *fmt, ...) // bool STR_String::IsUpper() const { - for (int i = 0; i < Len; i++) - if (isLower(pData[i])) + for (int i = 0; i < this->m_len; i++) + if (isLower(this->m_data[i])) return false; return true; @@ -332,8 +330,8 @@ bool STR_String::IsUpper() const // bool STR_String::IsLower() const { - for (int i = 0; i < Len; i++) - if (isUpper(pData[i])) + for (int i = 0; i < this->m_len; i++) + if (isUpper(this->m_data[i])) return false; return true; @@ -353,10 +351,10 @@ bool STR_String::IsLower() const int STR_String::Find(char c, int pos) const { assertd(pos >= 0); - assertd(Len == 0 || pos < Len); - assertd(pData != NULL); - char *find_pos = strchr(pData + pos, c); - return (find_pos) ? (find_pos - pData) : -1; + assertd(this->m_len == 0 || pos < this->m_len); + assertd(this->m_data != NULL); + char *find_pos = strchr(this->m_data + pos, c); + return (find_pos) ? (find_pos - this->m_data) : -1; } @@ -367,10 +365,10 @@ int STR_String::Find(char c, int pos) const int STR_String::Find(const char *str, int pos) const { assertd(pos >= 0); - assertd(Len == 0 || pos < Len); - assertd(pData != NULL); - char *find_pos = strstr(pData + pos, str); - return (find_pos) ? (find_pos - pData) : -1; + assertd(this->m_len == 0 || pos < this->m_len); + assertd(this->m_data != NULL); + char *find_pos = strstr(this->m_data + pos, str); + return (find_pos) ? (find_pos - this->m_data) : -1; } @@ -381,10 +379,10 @@ int STR_String::Find(const char *str, int pos) const int STR_String::Find(rcSTR_String str, int pos) const { assertd(pos >= 0); - assertd(Len == 0 || pos < Len); - assertd(pData != NULL); - char *find_pos = strstr(pData + pos, str.ReadPtr()); - return (find_pos) ? (find_pos - pData) : -1; + assertd(this->m_len == 0 || pos < this->m_len); + assertd(this->m_data != NULL); + char *find_pos = strstr(this->m_data + pos, str.ReadPtr()); + return (find_pos) ? (find_pos - this->m_data) : -1; } @@ -394,9 +392,9 @@ int STR_String::Find(rcSTR_String str, int pos) const // int STR_String::RFind(char c) const { - assertd(pData != NULL); - char *pos = strrchr(pData, c); - return (pos) ? (pos - pData) : -1; + assertd(this->m_data != NULL); + char *pos = strrchr(this->m_data, c); + return (pos) ? (pos - this->m_data) : -1; } @@ -407,10 +405,10 @@ int STR_String::RFind(char c) const int STR_String::FindOneOf(const char *set, int pos) const { assertd(pos >= 0); - assertd(Len == 0 || pos < Len); - assertd(pData != NULL); - char *find_pos = strpbrk(pData + pos, set); - return (find_pos) ? (find_pos - pData) : -1; + assertd(this->m_len == 0 || pos < this->m_len); + assertd(this->m_data != NULL); + char *find_pos = strpbrk(this->m_data + pos, set); + return (find_pos) ? (find_pos - this->m_data) : -1; } @@ -425,16 +423,16 @@ void STR_String::Replace(int pos, rcSTR_String str) if (str.Length() < 1) { // Remove one character from the string - memcpy(pData + pos, pData + pos + 1, Len - pos); + memcpy(this->m_data + pos, this->m_data + pos + 1, this->m_len - pos); } else { // Insert zero or more characters into the string - AllocBuffer(Len + str.Length() - 1, true); - if (str.Length() != 1) memcpy(pData + pos + str.Length(), pData + pos + 1, Length() - pos); - memcpy(pData + pos, str.ReadPtr(), str.Length()); + AllocBuffer(this->m_len + str.Length() - 1, true); + if (str.Length() != 1) memcpy(this->m_data + pos + str.Length(), this->m_data + pos + 1, Length() - pos); + memcpy(this->m_data + pos, str.ReadPtr(), str.Length()); } - Len += str.Length() - 1; + this->m_len += str.Length() - 1; } @@ -451,17 +449,17 @@ void STR_String::Replace(int pos, int num, rcSTR_String str) if (str.Length() < num) { // Remove some data from the string by replacement - memcpy(pData + pos + str.Length(), pData + pos + num, Len - pos - num + 1); - memcpy(pData + pos, str.ReadPtr(), str.Length()); + memcpy(this->m_data + pos + str.Length(), this->m_data + pos + num, this->m_len - pos - num + 1); + memcpy(this->m_data + pos, str.ReadPtr(), str.Length()); } else { // Insert zero or more characters into the string - AllocBuffer(Len + str.Length() - num, true); - if (str.Length() != num) memcpy(pData + pos + str.Length(), pData + pos + num, Length() - pos - num + 1); - memcpy(pData + pos, str.ReadPtr(), str.Length()); + AllocBuffer(this->m_len + str.Length() - num, true); + if (str.Length() != num) memcpy(this->m_data + pos + str.Length(), this->m_data + pos + num, Length() - pos - num + 1); + memcpy(this->m_data + pos, str.ReadPtr(), str.Length()); } - Len += str.Length() - num; + this->m_len += str.Length() - num; } @@ -477,7 +475,7 @@ void STR_String::Replace(int pos, int num, rcSTR_String str) // int STR_String::Compare(rcSTR_String rhs) const { - return strcmp(pData, rhs.pData); + return strcmp(this->ReadPtr(), rhs.ReadPtr()); } @@ -488,9 +486,9 @@ int STR_String::Compare(rcSTR_String rhs) const int STR_String::CompareNoCase(rcSTR_String rhs) const { #ifdef WIN32 - return stricmp(pData, rhs.pData); + return stricmp(this->ReadPtr(), rhs.ReadPtr()); #else - return strcasecmp(pData, rhs.pData); + return strcasecmp(this->ReadPtr(), rhs.ReadPtr()); #endif } @@ -507,12 +505,12 @@ int STR_String::CompareNoCase(rcSTR_String rhs) const // STR_String& STR_String::Upper() { - assertd(pData != NULL); + assertd(this->m_data != NULL); #ifdef WIN32 - _strupr(pData); + _strupr(this->m_data); #else - for (int i = 0; i < Len; i++) - pData[i] = (pData[i] >= 'a' && pData[i] <= 'z') ? pData[i] + 'A' - 'a' : pData[i]; + for (int i = 0; i < this->m_len; i++) + this->m_data[i] = (this->m_data[i] >= 'a' && this->m_data[i] <= 'z') ? this->m_data[i] + 'A' - 'a' : this->m_data[i]; #endif return *this; } @@ -524,12 +522,12 @@ STR_String& STR_String::Upper() // STR_String& STR_String::Lower() { - assertd(pData != NULL); + assertd(this->m_data != NULL); #ifdef WIN32 - _strlwr(pData); + _strlwr(this->m_data); #else - for (int i = 0; i < Len; i++) - pData[i] = (pData[i] >= 'A' && pData[i] <= 'Z') ? pData[i] + 'a' - 'A' : pData[i]; + for (int i = 0; i < this->m_len; i++) + this->m_data[i] = (this->m_data[i] >= 'A' && this->m_data[i] <= 'Z') ? this->m_data[i] + 'a' - 'A' : this->m_data[i]; #endif return *this; } @@ -541,15 +539,15 @@ STR_String& STR_String::Lower() // STR_String& STR_String::Capitalize() { - assertd(pData != NULL); + assertd(this->m_data != NULL); #ifdef WIN32 - if (Len > 0) pData[0] = toupper(pData[0]); - if (Len > 1) _strlwr(pData + 1); + if (this->m_len > 0) this->m_data[0] = toupper(this->m_data[0]); + if (this->m_len > 1) _strlwr(this->m_data + 1); #else - if (Len > 0) - pData[0] = (pData[0] >= 'A' && pData[0] <= 'A') ? pData[0] + 'a' - 'A' : pData[0]; - for (int i = 1; i < Len; i++) - pData[i] = (pData[i] >= 'a' && pData[i] <= 'z') ? pData[i] + 'A' - 'a' : pData[i]; + if (this->m_len > 0) + this->m_data[0] = (this->m_data[0] >= 'A' && this->m_data[0] <= 'A') ? this->m_data[0] + 'a' - 'A' : this->m_data[0]; + for (int i = 1; i < this->m_len; i++) + this->m_data[i] = (this->m_data[i] >= 'a' && this->m_data[i] <= 'z') ? this->m_data[i] + 'A' - 'a' : this->m_data[i]; #endif return *this; } @@ -562,10 +560,10 @@ STR_String& STR_String::Capitalize() STR_String& STR_String::TrimLeft() { int skip; - assertd(pData != NULL); - for (skip = 0; isSpace(pData[skip]); skip++, Len--) + assertd(this->m_data != NULL); + for (skip = 0; isSpace(this->m_data[skip]); skip++, this->m_len--) {}; - memmove(pData, pData + skip, Len + 1); + memmove(this->m_data, this->m_data + skip, this->m_len + 1); return *this; } @@ -576,9 +574,9 @@ STR_String& STR_String::TrimLeft() // STR_String& STR_String::TrimRight() { - assertd(pData != NULL); - while (Len && isSpace(pData[Len - 1])) Len--; - pData[Len] = 0; + assertd(this->m_data != NULL); + while (this->m_len && isSpace(this->m_data[this->m_len - 1])) this->m_len--; + this->m_data[this->m_len] = 0; return *this; } @@ -602,10 +600,10 @@ STR_String& STR_String::Trim() STR_String& STR_String::TrimLeft(char *set) { int skip; - assertd(pData != NULL); - for (skip = 0; Len && strchr(set, pData[skip]); skip++, Len--) + assertd(this->m_data != NULL); + for (skip = 0; this->m_len && strchr(set, this->m_data[skip]); skip++, this->m_len--) {}; - memmove(pData, pData + skip, Len + 1); + memmove(this->m_data, this->m_data + skip, this->m_len + 1); return *this; } @@ -616,9 +614,9 @@ STR_String& STR_String::TrimLeft(char *set) // STR_String& STR_String::TrimRight(char *set) { - assertd(pData != NULL); - while (Len && strchr(set, pData[Len - 1])) Len--; - pData[Len] = 0; + assertd(this->m_data != NULL); + while (this->m_len && strchr(set, this->m_data[this->m_len - 1])) this->m_len--; + this->m_data[this->m_len] = 0; return *this; } @@ -642,11 +640,11 @@ STR_String& STR_String::Trim(char *set) STR_String& STR_String::TrimQuotes() { // Trim quotes if they are on both sides of the string - assertd(pData != NULL); - if ((Len >= 2) && (pData[0] == '\"') && (pData[Len - 1] == '\"')) + assertd(this->m_data != NULL); + if ((this->m_len >= 2) && (this->m_data[0] == '\"') && (this->m_data[this->m_len - 1] == '\"')) { - memmove(pData, pData + 1, Len - 2 + 1); - Len -= 2; + memmove(this->m_data, this->m_data + 1, this->m_len - 2 + 1); + this->m_len -= 2; } return *this; } @@ -666,12 +664,12 @@ rcSTR_String STR_String::Copy(const char *src, int len) { assertd(len >= 0); assertd(src); - assertd(pData != NULL); + assertd(this->m_data != NULL); AllocBuffer(len, false); - Len = len; - memcpy(pData, src, len); - pData[Len] = 0; + this->m_len = len; + memcpy(this->m_data, src, len); + this->m_data[this->m_len] = 0; return *this; } @@ -683,15 +681,15 @@ rcSTR_String STR_String::Copy(const char *src, int len) // rcSTR_String STR_String::Concat(const char *data, int len) { - assertd(Len >= 0); + assertd(this->m_len >= 0); assertd(len >= 0); assertd(data); - assertd(pData != NULL); + assertd(this->m_data != NULL); - AllocBuffer(Len + len, true); - memcpy(pData + Len, data, len); - Len += len; - pData[Len] = 0; + AllocBuffer(this->m_len + len, true); + memcpy(this->m_data + this->m_len, data, len); + this->m_len += len; + this->m_data[this->m_len] = 0; return *this; } @@ -702,8 +700,7 @@ std::vector STR_String::Explode(char c) const STR_String lcv = *this; std::vector uc; - while (lcv.Length()) - { + while (lcv.Length()) { int pos = lcv.Find(c); if (pos < 0) { uc.push_back(lcv); @@ -729,16 +726,16 @@ int STR_String::Serialize(pCStream stream) int ln; stream->Read(&ln, sizeof(ln)); AllocBuffer(ln, false); - stream->Read(pData, ln); - pData[ln] = '\0'; - Len = ln; + stream->Read(this->m_data, ln); + this->m_data[ln] = '\0'; + this->m_len = ln; } else { - stream->Write(&Len, sizeof(Len)); - stream->Write(pData, Len); + stream->Write(&this->m_len, sizeof(this->m_len)); + stream->Write(this->m_data, this->m_len); } - return Len + sizeof(Len); + return this->m_len + sizeof(this->m_len); } #endif diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 0b4d4cd19e4..5302ad9b471 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -774,7 +774,7 @@ class IMAGE_PT_paint_curve(BrushButtonsPanel, Panel): toolsettings = context.tool_settings.image_paint brush = toolsettings.brush - layout.template_curve_mapping(brush, "curve", type='COLOR') + layout.template_curve_mapping(brush, "curve") row = layout.row(align=True) row.operator("brush.curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH' diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 06807dfcbad..f47ac641cf9 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -2595,7 +2595,7 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, char *filenam int format = (surface->image_fileformat & MOD_DPAINT_IMGFORMAT_OPENEXR) ? R_IMF_IMTYPE_OPENEXR : R_IMF_IMTYPE_PNG; char output_file[FILE_MAX]; - if (!sData || !sData->type_data) { setError(surface->canvas, "Image save failed: Invalid surface."); return; } + if (!sData->type_data) { setError(surface->canvas, "Image save failed: Invalid surface."); return; } /* if selected format is openexr, but current build doesnt support one */ #ifndef WITH_OPENEXR if (format == R_IMF_IMTYPE_OPENEXR) format = R_IMF_IMTYPE_PNG; @@ -4800,7 +4800,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su PaintBakeData *bData = sData->bData; DynamicPaintCanvasSettings *canvas = surface->canvas; int ret = 1; - if (!sData || sData->total_points < 1) return 0; + if (sData->total_points < 1) return 0; dynamicPaint_surfacePreStep(surface, timescale); /* @@ -4875,7 +4875,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su /* Apply brush on the surface depending on it's collision type */ /* Particle brush: */ if (brush->collision == MOD_DPAINT_COL_PSYS) { - if (brush && brush->psys && brush->psys->part && brush->psys->part->type == PART_EMITTER && + if (brush->psys && brush->psys->part && brush->psys->part->type == PART_EMITTER && psys_check_enabled(brushObj, brush->psys)) { diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index b78ab9b28cd..5fea74d52de 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -74,12 +74,10 @@ void free_fcurve(FCurve *fcu) { if (fcu == NULL) return; - + /* free curve data */ - if (fcu) { - if (fcu->bezt) MEM_freeN(fcu->bezt); - if (fcu->fpt) MEM_freeN(fcu->fpt); - } + if (fcu->bezt) MEM_freeN(fcu->bezt); + if (fcu->fpt) MEM_freeN(fcu->fpt); /* free RNA-path, as this were allocated when getting the path string */ if (fcu->rna_path) diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 008dc332710..4a88bfbfdad 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -2291,7 +2291,7 @@ static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, flo /* done goal stuff */ /* gravitation */ - if (sb && scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { + if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { float gravity[3]; copy_v3_v3(gravity, scene->physics_settings.gravity); mul_v3_fl(gravity, sb_grav_force_scale(ob)*_final_mass(ob, bp)*sb->effector_weights->global_gravity); /* individual mass of node here */ diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index 4ce718aeb16..32afaba2b5c 100644 --- a/source/blender/blenlib/intern/scanfill.c +++ b/source/blender/blenlib/intern/scanfill.c @@ -423,12 +423,16 @@ static void testvertexnearedge(ScanFillContext *sf_ctx) for (eve = sf_ctx->fillvertbase.first; eve; eve = eve->next) { if (eve->h == 1) { - /* find the edge which has vertex eve */ - ed1 = sf_ctx->filledgebase.first; - while (ed1) { - if (ed1->v1 == eve || ed1->v2 == eve) break; - ed1 = ed1->next; + /* find the edge which has vertex eve, + * note: we _know_ this will crash if 'ed1' becomes NULL + * but this will never happen. */ + for (ed1 = sf_ctx->filledgebase.first; + !(ed1->v1 == eve || ed1->v2 == eve); + ed1 = ed1->next) + { + /* do nothing */ } + if (ed1->v1 == eve) { ed1->v1 = ed1->v2; ed1->v2 = eve; diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 76aa8d55b5e..4d10ef317f3 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -1798,18 +1798,21 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *vtarget) { BMEdge *e; - BMLoop *l; - BMIter liter; + + BMLoop **loops; + int i, loops_tot; /* verts already spliced */ if (v == vtarget) { return FALSE; } - /* retarget all the loops of v to vtarget */ - BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - l->v = vtarget; + /* we can't modify the vert while iterating so first allocate an array of loops */ + loops = BM_iter_as_arrayN(bm, BM_LOOPS_OF_VERT, v, &loops_tot); + for (i = 0; i < loops_tot; i++) { + loops[i]->v = vtarget; } + MEM_freeN(loops); /* move all the edges from v's disk to vtarget's disk */ while ((e = v->e)) { diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c index 8103ae1ee11..64920df6e20 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.c +++ b/source/blender/bmesh/intern/bmesh_iterators.c @@ -28,6 +28,8 @@ * See: bmesh_iterators_inlin.c too, some functions are here for speed reasons. */ +#include "MEM_guardedalloc.h" + #include "BLI_utildefines.h" #include "bmesh.h" @@ -104,6 +106,38 @@ int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, cons return i; } +/** + * \brief Iterator as Array + * + * Allocates a new array, has the advantage that you dont need to know the size ahead of time. + * + * Takes advantage of less common iterator usage to avoid counting twice, + * which you might end up doing when #BM_iter_as_array is used. + * + * Caller needs to free the array. + */ +void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len) +{ + BMIter iter; + + if (BM_iter_init(&iter, bm, itype, data) && iter.count > 0) { + BMElem *ele; + BMElem **array = MEM_mallocN(sizeof(ele) * iter.count, __func__); + int i; + + *r_len = iter.count; /* set before iterating */ + + for (ele = BM_iter_step(&iter), i = 0; ele; ele = BM_iter_step(&iter), i++) { + array[i] = ele; + } + return array; + } + else { + *r_len = 0; + return NULL; + } +} + /** * \brief Elem Iter Flag Count * diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h index 1361a91a692..8d0eeca31ed 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.h +++ b/source/blender/bmesh/intern/bmesh_iterators.h @@ -115,10 +115,19 @@ typedef struct BMIter { char itype; } BMIter; -void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index); -int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len); -int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const short value); -int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const short value); +void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) +#ifdef __GNUC__ +__attribute__((warn_unused_result)) +#endif +; +int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len); +void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len) +#ifdef __GNUC__ +__attribute__((warn_unused_result)) +#endif +; +int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const short value); +int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const short value); /* private for bmesh_iterators_inline.c */ void bmiter__vert_of_mesh_begin(struct BMIter *iter); diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index a9f146e4962..d850eb34477 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -470,31 +470,12 @@ int BM_edge_face_count(BMEdge *e) } /** - * Returns the number of faces around this vert + * Returns the number of faces around this vert + * length matches #BM_LOOPS_OF_VERT iterator */ int BM_vert_face_count(BMVert *v) { - int count = 0; - BMLoop *l; - BMIter iter; - - BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { - count++; - } - - return count; -#if 0 //this code isn't working - BMEdge *curedge = NULL; - - if (v->e) { - curedge = v->e; - do { - if (curedge->l) count += BM_edge_face_count(curedge); - curedge = bmesh_disk_edge_next(curedge, v); - } while (curedge != v->e); - } - return count; -#endif + return bmesh_disk_facevert_count(v); } /** @@ -503,22 +484,21 @@ int BM_vert_face_count(BMVert *v) */ int BM_vert_is_wire(BMVert *v) { - BMEdge *curedge; + if (v->e) { + BMEdge *e_first, *e_iter; - if (v->e == NULL) { + e_first = e_iter = v->e; + do { + if (e_iter->l) { + return FALSE; + } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); + + return TRUE; + } + else { return FALSE; } - - curedge = v->e; - do { - if (curedge->l) { - return FALSE; - } - - curedge = bmesh_disk_edge_next(curedge, v); - } while (curedge != v->e); - - return TRUE; } /** diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 3ef686910e6..8cd8cfaea51 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -164,10 +164,7 @@ FCurve *verify_fcurve(bAction *act, const char group[], PointerRNA *ptr, * - add if not found and allowed to add one * TODO: add auto-grouping support? how this works will need to be resolved */ - if (act) - fcu = list_find_fcurve(&act->curves, rna_path, array_index); - else - fcu = NULL; + fcu = list_find_fcurve(&act->curves, rna_path, array_index); if ((fcu == NULL) && (add)) { /* use default settings to make a F-Curve */ diff --git a/source/blender/editors/mesh/editmesh_bvh.c b/source/blender/editors/mesh/editmesh_bvh.c index 580592c02f6..0b7d396b696 100644 --- a/source/blender/editors/mesh/editmesh_bvh.c +++ b/source/blender/editors/mesh/editmesh_bvh.c @@ -398,11 +398,6 @@ int BMBVH_EdgeVisible(BMBVHTree *tree, BMEdge *e, ARegion *ar, View3D *v3d, Obje float end[3]; const float mval_f[2] = {ar->winx / 2.0f, ar->winy / 2.0f}; - - if (!ar) { - printf("error in BMBVH_EdgeVisible!\n"); - return 0; - } ED_view3d_win_to_segment_clip(ar, v3d, mval_f, origin, end); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 3ac011550be..dc5d1cea443 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -268,11 +268,14 @@ int EDBM_backbuf_border_mask_init(ViewContext *vc, int mcords[][2], short tot, s /* grab mask */ bufmask = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); - drm = bufmask->rect; + if (bufmask == NULL) { return 0; /* only when mem alloc fails, go crash somewhere else! */ } - + else { + drm = bufmask->rect; + } + /* build selection lookup */ selbuf = MEM_callocN(bm_vertoffs + 1, "selbuf"); diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 3ed31abca94..b7ce32aa10a 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -4135,7 +4135,7 @@ static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, if (cache && cache->flag & PTCACHE_DISK_CACHE) return; - if (psys == NULL && cache->mem_cache.first == NULL) + if (psys == NULL && (cache && cache->mem_cache.first == NULL)) return; if (!edit) { diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 3642cc0d8d4..11d32e11cd0 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1767,12 +1767,22 @@ void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync, sad->ar = CTX_wm_region(C); /* if startframe is larger than current frame, we put currentframe on startframe. * note: first frame then is not drawn! (ton) */ - if (scene->r.sfra > scene->r.cfra) { - sad->sfra = scene->r.cfra; - scene->r.cfra = scene->r.sfra; + if (PRVRANGEON) { + if (scene->r.psfra > scene->r.cfra) { + sad->sfra = scene->r.cfra; + scene->r.cfra = scene->r.psfra; + } + else + sad->sfra = scene->r.cfra; + } + else { + if (scene->r.sfra > scene->r.cfra) { + sad->sfra = scene->r.cfra; + scene->r.cfra = scene->r.sfra; + } + else + sad->sfra = scene->r.cfra; } - else - sad->sfra = scene->r.cfra; sad->redraws = redraws; sad->refresh = refresh; sad->flag |= (enable < 0) ? ANIMPLAY_FLAG_REVERSE : 0; diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index adb1829703c..29571a60cbf 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -1412,24 +1412,46 @@ static float project_paint_uvpixel_mask( /* calculate mask */ if (ps->do_mask_normal) { - MFace *mf = ps->dm_mface + face_index; - short *no1, *no2, *no3; + MFace *mf = &ps->dm_mface[face_index]; float no[3], angle; - no1 = ps->dm_mvert[mf->v1].no; - if (side == 1) { - no2 = ps->dm_mvert[mf->v3].no; - no3 = ps->dm_mvert[mf->v4].no; + if (mf->flag & ME_SMOOTH) { + short *no1, *no2, *no3; + no1 = ps->dm_mvert[mf->v1].no; + if (side == 1) { + no2 = ps->dm_mvert[mf->v3].no; + no3 = ps->dm_mvert[mf->v4].no; + } + else { + no2 = ps->dm_mvert[mf->v2].no; + no3 = ps->dm_mvert[mf->v3].no; + } + + no[0] = w[0] * no1[0] + w[1] * no2[0] + w[2] * no3[0]; + no[1] = w[0] * no1[1] + w[1] * no2[1] + w[2] * no3[1]; + no[2] = w[0] * no1[2] + w[1] * no2[2] + w[2] * no3[2]; + normalize_v3(no); } else { - no2 = ps->dm_mvert[mf->v2].no; - no3 = ps->dm_mvert[mf->v3].no; + /* incase the */ +#if 1 + /* normalizing per pixel isn't optimal, we could cache or check ps->*/ + if (mf->v4) + normal_quad_v3(no, + ps->dm_mvert[mf->v1].co, + ps->dm_mvert[mf->v2].co, + ps->dm_mvert[mf->v3].co, + ps->dm_mvert[mf->v4].co); + else + normal_tri_v3(no, + ps->dm_mvert[mf->v1].co, + ps->dm_mvert[mf->v2].co, + ps->dm_mvert[mf->v3].co); +#else + /* don't use because some modifiers dont have normal data (subsurf for eg) */ + copy_v3_v3(no, (float *)ps->dm->getTessFaceData(ps->dm, face_index, CD_NORMAL)); +#endif } - no[0] = w[0] * no1[0] + w[1] * no2[0] + w[2] * no3[0]; - no[1] = w[0] * no1[1] + w[1] * no2[1] + w[2] * no3[1]; - no[2] = w[0] * no1[2] + w[1] * no2[2] + w[2] * no3[2]; - normalize_v3(no); - /* now we can use the normal as a mask */ if (ps->is_ortho) { angle = angle_normalized_v3v3((float *)ps->viewDir, no); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index e635c4b3fb8..c1859407789 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -861,7 +861,7 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan) data->rootbone = 0; /* watch-it! has to be 0 here, since we're still on the same bone for the first time through the loop [#25885] */ /* we only include bones that are part of a continual connected chain */ - while (pchan) { + do { /* here, we set ik-settings for bone from pchan->protectflag */ // XXX: careful with quats/axis-angle rotations where we're locking 4d components if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP; @@ -876,7 +876,7 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan) pchan = pchan->parent; else pchan = NULL; - } + } while (pchan); /* make a copy of maximum chain-length */ data->max_rootbone = data->rootbone; diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 1c63ab512f2..9cd0bdd090a 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -163,8 +163,17 @@ void bpy_context_clear(bContext *UNUSED(C), PyGILState_STATE *gilstate) void BPY_text_free_code(Text *text) { if (text->compiled) { + PyGILState_STATE gilstate; + int use_gil = !PYC_INTERPRETER_ACTIVE; + + if (use_gil) + gilstate = PyGILState_Ensure(); + Py_DECREF((PyObject *)text->compiled); text->compiled = NULL; + + if (use_gil) + PyGILState_Release(gilstate); } } diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 266b0d0357f..eb6fabd03c6 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -489,6 +489,8 @@ int WM_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory char tstr[FILE_MAX]; int success = 0; + BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE); + G.relbase_valid = 0; if (!from_memory) { char *cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL); @@ -566,6 +568,9 @@ int WM_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory } #endif + /* important to do before NULL'ing the context */ + BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST); + WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL); /* in background mode the scene will stay NULL */ diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index 7da0be3a506..25afefbcc5a 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -536,18 +536,18 @@ void RAS_MeshObject::SortPolygons(RAS_MeshSlot& ms, const MT_Transform &transfor const MT_Vector3 pnorm(transform.getBasis()[2]); // unneeded: const MT_Scalar pval = transform.getOrigin()[2]; - vector slots(totpoly); + vector poly_slots(totpoly); /* get indices and z into temporary array */ for (j=0; j Date: Tue, 11 Sep 2012 10:34:19 +0000 Subject: [PATCH 134/160] Color Management: fix for wrong default color space and view --- source/blender/blenkernel/intern/colortools.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 27651ac1731..19c8c2cd632 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -1292,7 +1292,7 @@ void BKE_color_managed_view_settings_init(ColorManagedViewSettings *settings) * and proper versioning stuff is added. * for now use NONE to be compatible with all current files */ - BLI_strncpy(settings->view_transform, "NONE", sizeof(settings->view_transform)); + BLI_strncpy(settings->view_transform, "Default", sizeof(settings->view_transform)); settings->gamma = 1.0f; settings->exposure = 0.0f; @@ -1319,7 +1319,7 @@ void BKE_color_managed_view_settings_free(ColorManagedViewSettings *settings) void BKE_color_managed_colorspace_settings_init(ColorManagedColorspaceSettings *colorspace_settings) { - BLI_strncpy(colorspace_settings->name, "NONE", sizeof(colorspace_settings->name)); + BLI_strncpy(colorspace_settings->name, "", sizeof(colorspace_settings->name)); } void BKE_color_managed_colorspace_settings_copy(ColorManagedColorspaceSettings *colorspace_settings, From 5f512bec47cdfafd089fc1cff82cc343b87c7808 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 11 Sep 2012 12:35:25 +0000 Subject: [PATCH 135/160] Sequencer: added option to calculate modifiers in linear space It was really annoying mistake in original support of logarithmic color space for sequencer which made adjustment layers be working in linear space. Seems this was only an issue for modifiers in adjustment effect. Now all modifiers are applying in sequencer's color space (in fact, this was fixed in svn rev50275). To preserve compatibility of Mango grading added this option which probably wouldn't be used by others. --- release/scripts/startup/bl_ui/space_sequencer.py | 2 ++ source/blender/blenkernel/intern/seqmodifier.c | 9 +++++++++ source/blender/makesdna/DNA_sequence_types.h | 1 + source/blender/makesrna/intern/rna_sequencer.c | 5 +++++ 4 files changed, 17 insertions(+) diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index dd13b8a9b51..39c892930f4 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -884,6 +884,8 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel): strip = act_strip(context) sequencer = context.scene.sequence_editor + layout.prop(strip, "use_linear_modifiers") + layout.operator_menu_enum("sequencer.strip_modifier_add", "type") for mod in strip.modifiers: diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c index 6028b40756d..1fa009d22a0 100644 --- a/source/blender/blenkernel/intern/seqmodifier.c +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -581,6 +581,11 @@ ImBuf *BKE_sequence_modifier_apply_stack(SeqRenderData context, Sequence *seq, I SequenceModifierData *smd; ImBuf *processed_ibuf = ibuf; + if (seq->modifiers.first && (seq->flag & SEQ_USE_LINEAR_MODIFIERS)) { + processed_ibuf = IMB_dupImBuf(ibuf); + BKE_sequencer_imbuf_from_sequencer_space(context.scene, processed_ibuf); + } + for (smd = seq->modifiers.first; smd; smd = smd->next) { SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); @@ -605,6 +610,10 @@ ImBuf *BKE_sequence_modifier_apply_stack(SeqRenderData context, Sequence *seq, I } } + if (seq->modifiers.first && (seq->flag & SEQ_USE_LINEAR_MODIFIERS)) { + BKE_sequencer_imbuf_to_sequencer_space(context.scene, processed_ibuf, FALSE); + } + return processed_ibuf; } diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 913f416e6ea..4d259fad246 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -329,6 +329,7 @@ typedef struct SequencerScopes { #define SEQ_USE_PROXY_CUSTOM_FILE (1 << 21) #define SEQ_USE_EFFECT_DEFAULT_FADE (1 << 22) +#define SEQ_USE_LINEAR_MODIFIERS (1 << 23) // flags for whether those properties are animated or not #define SEQ_AUDIO_VOLUME_ANIMATED (1 << 24) diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index e3e467a9abb..b27148e964d 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -1433,6 +1433,11 @@ static void rna_def_sequence(BlenderRNA *brna) RNA_def_property_int_funcs(prop, NULL, "rna_Sequence_channel_set", NULL); /* overlap test */ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + prop = RNA_def_property(srna, "use_linear_modifiers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_LINEAR_MODIFIERS); + RNA_def_property_ui_text(prop, "Use Linear Modifiers", "Calculate modifiers in linear space instead of sequencer's space"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + /* blending */ prop = RNA_def_property(srna, "blend_type", PROP_ENUM, PROP_NONE); From 445020a153f9a69174abe70b91ea70ed7e913280 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 11 Sep 2012 16:28:01 +0000 Subject: [PATCH 136/160] Color Management: improve compatibility with old files with disabled color management Still not perfect compatibility, but making it better is a bit tricky now. --- source/blender/blenloader/intern/readfile.c | 22 ++++++++++++++++++- .../operations/COM_ImageOperation.cpp | 3 ++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 0428e88c539..dd945dd4cc0 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7927,20 +7927,40 @@ static void do_versions(FileData *fd, Library *lib, Main *main) { Scene *scene; Image *ima; + int colormanagement_disabled = FALSE; + /* make scenes which are not using color management have got None as display device, + * so they wouldn't perform linear-to-sRGB conversion on display + */ for (scene = main->scene.first; scene; scene = scene->id.next) { if ((scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) == 0) { ColorManagedDisplaySettings *display_settings = &scene->display_settings; if (display_settings->display_device[0] == 0) { BKE_scene_disable_color_management(scene); + } + + colormanagement_disabled = TRUE; } } for (ima = main->image.first; ima; ima = ima->id.next) { - if (ima->source == IMA_SRC_VIEWER) + if (ima->source == IMA_SRC_VIEWER) { ima->flag |= IMA_VIEW_AS_RENDER; + } + else if (colormanagement_disabled) { + /* if colormanagement not used, set image's color space to raw, so no sRGB->linear conversion + * would happen on display and render + * there's no clear way to check whether color management is enabled or not in render engine + * so set all images to raw if there's at least one scene with color management disabled + * this would still behave incorrect in cases when color management was used for only some + * of scenes, but such a setup is crazy anyway and think it's fair enough to break compatibility + * in that cases + */ + + BLI_strncpy(ima->colorspace_settings.name, "Raw", sizeof(ima->colorspace_settings.name)); + } } } diff --git a/source/blender/compositor/operations/COM_ImageOperation.cpp b/source/blender/compositor/operations/COM_ImageOperation.cpp index 4ec5643c0bb..4c454d90fb6 100644 --- a/source/blender/compositor/operations/COM_ImageOperation.cpp +++ b/source/blender/compositor/operations/COM_ImageOperation.cpp @@ -33,6 +33,7 @@ extern "C" { #include "RE_render_ext.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" + #include "IMB_colormanagement.h" } BaseImageOperation::BaseImageOperation() : NodeOperation() @@ -70,7 +71,7 @@ ImBuf *BaseImageOperation::getImBuf() } if (ibuf->rect_float == NULL) { - IMB_float_from_rect(ibuf); + IMB_colormanagement_imbuf_float_from_rect(ibuf); } return ibuf; } From a793c5bc4c0b31bfaa931c3d0ae0701b878fcb78 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 11 Sep 2012 18:41:32 +0000 Subject: [PATCH 137/160] Color Management: prevent abort when sequencer's color space is not found in OCIO configuration --- source/blender/imbuf/intern/colormanagement.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 360b325559d..5e3c445c7f0 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -947,10 +947,11 @@ void IMB_colormanagement_check_file_config(Main *bmain) sequencer_colorspace_settings = &scene->sequencer_colorspace_settings; + colormanage_check_colorspace_settings(sequencer_colorspace_settings, "sequencer"); + if (sequencer_colorspace_settings->name[0] == '\0') { BLI_strncpy(sequencer_colorspace_settings->name, global_role_default_sequencer, MAX_COLORSPACE_NAME); } - colormanage_check_colorspace_settings(sequencer_colorspace_settings, "sequencer"); } /* ** check input color space settings ** */ From 4f9ee399c09f62e9e6c359ef03b9d016a11d089d Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Thu, 13 Sep 2012 08:09:12 +0000 Subject: [PATCH 138/160] Fix typo in blenfont sconscript, broke compile --- source/blender/blenfont/SConscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenfont/SConscript b/source/blender/blenfont/SConscript index 12badf2383b..d3c7b1c2fcc 100644 --- a/source/blender/blenfont/SConscript +++ b/source/blender/blenfont/SConscript @@ -4,7 +4,7 @@ Import ('env') sources = env.Glob('intern/*.c') -incs = '. intern #/intern/guardedalloc ../blenkernel ../blenlib ../makesdna ,,/imbuf ../editors/include' +incs = '. intern #/intern/guardedalloc ../blenkernel ../blenlib ../makesdna ../imbuf ../editors/include' incs += ' #/extern/glew/include' incs += ' ' + env['BF_FREETYPE_INC'] incs += ' ' + env['BF_GETTEXT_INC'] From de7a57a242c5305216e917cb9ab3b870dd10de59 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 13 Sep 2012 11:13:13 +0000 Subject: [PATCH 139/160] Merging r50522 through r50572 from trunk into soc-2011-tomato --- build_files/cmake/macros.cmake | 10 +- extern/libmv/third_party/ceres/SConscript | 5 + .../ceres/internal/ceres/collections_port.h | 10 + intern/cycles/blender/addon/ui.py | 5 +- intern/cycles/blender/blender_session.cpp | 6 + intern/cycles/device/device.h | 1 + intern/cycles/device/device_cpu.cpp | 5 + intern/cycles/device/device_cuda.cpp | 5 + intern/cycles/device/device_multi.cpp | 8 + intern/cycles/device/device_opencl.cpp | 21 +- intern/cycles/render/session.cpp | 19 ++ intern/cycles/render/session.h | 3 + intern/cycles/util/util_opencl.cpp | 6 +- intern/cycles/util/util_task.cpp | 33 +-- .../bl_operators/screen_play_rendered_anim.py | 8 +- release/scripts/startup/bl_operators/wm.py | 29 ++- source/blender/blenkernel/BKE_anim.h | 1 + source/blender/blenkernel/BKE_image.h | 4 + source/blender/blenkernel/BKE_mask.h | 8 +- source/blender/blenkernel/BKE_movieclip.h | 7 +- source/blender/blenkernel/BKE_sequencer.h | 1 + source/blender/blenkernel/intern/action.c | 8 +- source/blender/blenkernel/intern/anim.c | 66 +++-- source/blender/blenkernel/intern/fcurve.c | 20 +- source/blender/blenkernel/intern/image.c | 37 +++ source/blender/blenkernel/intern/key.c | 16 +- source/blender/blenkernel/intern/mask.c | 42 ++- .../blenkernel/intern/mask_rasterize.c | 40 +++ source/blender/blenkernel/intern/movieclip.c | 12 +- source/blender/blenkernel/intern/object.c | 2 +- source/blender/blenkernel/intern/pointcache.c | 3 +- source/blender/blenkernel/intern/sequencer.c | 18 +- source/blender/blenlib/intern/math_geom.c | 4 +- source/blender/bmesh/intern/bmesh_core.c | 4 + source/blender/bmesh/intern/bmesh_iterators.c | 6 +- source/blender/bmesh/intern/bmesh_private.h | 20 +- source/blender/bmesh/intern/bmesh_structure.c | 26 +- source/blender/bmesh/operators/bmo_connect.c | 1 - source/blender/collada/DocumentExporter.cpp | 2 + source/blender/collada/GeometryExporter.cpp | 19 +- source/blender/collada/ImageExporter.cpp | 15 +- .../compositor/intern/COM_NodeOperation.cpp | 29 ++- .../COM_CombineChannelsOperation.cpp | 26 -- .../operations/COM_CombineChannelsOperation.h | 2 - .../blender/editors/animation/anim_markers.c | 5 +- source/blender/editors/include/ED_image.h | 4 +- source/blender/editors/include/ED_mask.h | 3 +- source/blender/editors/include/UI_interface.h | 21 +- source/blender/editors/interface/interface.c | 103 ++++---- .../editors/interface/interface_handlers.c | 32 ++- .../editors/interface/interface_intern.h | 12 +- .../editors/interface/interface_regions.c | 10 +- .../editors/interface/interface_utils.c | 2 +- .../editors/interface/interface_widgets.c | 8 +- source/blender/editors/mask/mask_add.c | 5 +- source/blender/editors/mask/mask_draw.c | 6 +- source/blender/editors/mask/mask_edit.c | 13 +- source/blender/editors/mask/mask_ops.c | 10 +- source/blender/editors/object/object_bake.c | 27 +- .../blender/editors/object/object_modifier.c | 2 +- .../blender/editors/space_clip/clip_editor.c | 2 +- .../blender/editors/space_clip/space_clip.c | 3 + source/blender/editors/space_file/file_ops.c | 22 +- .../blender/editors/space_file/space_file.c | 16 +- .../blender/editors/space_image/image_edit.c | 50 +--- .../blender/editors/space_image/image_ops.c | 2 +- .../blender/editors/space_image/space_image.c | 3 + .../editors/space_logic/logic_window.c | 10 +- source/blender/editors/space_node/drawnode.c | 2 +- .../blender/editors/space_node/node_header.c | 14 +- .../editors/space_sequencer/sequencer_draw.c | 2 + .../editors/space_sequencer/sequencer_edit.c | 16 +- source/blender/editors/transform/transform.c | 63 ++++- .../editors/transform/transform_conversions.c | 3 + .../editors/transform/transform_generics.c | 12 + source/blender/editors/util/undo.c | 3 +- .../editors/uvedit/uvedit_unwrap_ops.c | 6 +- source/blender/makesdna/DNA_view3d_types.h | 4 +- source/blender/makesrna/intern/rna_access.c | 3 +- source/blender/makesrna/intern/rna_sensor.c | 5 + source/blender/makesrna/intern/rna_space.c | 2 +- source/blender/makesrna/intern/rna_userdef.c | 1 + .../modifiers/intern/MOD_particleinstance.c | 246 ++++++++++-------- source/blender/modifiers/intern/MOD_screw.c | 2 +- .../render/intern/source/imagetexture.c | 2 + .../windowmanager/intern/wm_playanim.c | 16 +- source/gameengine/Ketsji/KX_Scene.cpp | 13 +- source/tests/bl_rna_wiki_reference.py | 70 +++++ source/tests/rna_info_dump.py | 2 +- 89 files changed, 958 insertions(+), 513 deletions(-) create mode 100644 source/tests/bl_rna_wiki_reference.py diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 057a1105b73..ad5e3155368 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -27,7 +27,10 @@ macro(list_insert_after list_id item_check item_add ) set(_index) - list(FIND ${list_id} "${item_check}" _index) + list(FIND "${list_id}" "${item_check}" _index) + if("${_index}" MATCHES "-1") + message(FATAL_ERROR "'${list_id}' doesn't contain '${item_check}'") + endif() math(EXPR _index "${_index} + 1") list(INSERT ${list_id} "${_index}" ${item_add}) unset(_index) @@ -37,7 +40,10 @@ macro(list_insert_before list_id item_check item_add ) set(_index) - list(FIND ${list_id} "${item_check}" _index) + list(FIND "${list_id}" "${item_check}" _index) + if("${_index}" MATCHES "-1") + message(FATAL_ERROR "'${list_id}' doesn't contain '${item_check}'") + endif() list(INSERT ${list_id} "${_index}" ${item_add}) unset(_index) endmacro() diff --git a/extern/libmv/third_party/ceres/SConscript b/extern/libmv/third_party/ceres/SConscript index 6b5f1b8d64d..c629fa00176 100644 --- a/extern/libmv/third_party/ceres/SConscript +++ b/extern/libmv/third_party/ceres/SConscript @@ -25,6 +25,11 @@ defs.append('CERES_RESTRICT_SCHUR_SPECIALIZATION') incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags' +# work around broken hashtable in 10.5 SDK +if env['OURPLATFORM'] == 'darwin' and env['WITH_BF_BOOST']: + incs += ' ' + env['BF_BOOST_INC'] + defs.append('CERES_HASH_BOOST') + if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): incs += ' ../msinttypes' diff --git a/extern/libmv/third_party/ceres/internal/ceres/collections_port.h b/extern/libmv/third_party/ceres/internal/ceres/collections_port.h index 6f8a830a85e..9dff0efe245 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/collections_port.h +++ b/extern/libmv/third_party/ceres/internal/ceres/collections_port.h @@ -33,6 +33,10 @@ #ifndef CERES_INTERNAL_COLLECTIONS_PORT_H_ #define CERES_INTERNAL_COLLECTIONS_PORT_H_ +#ifdef CERES_HASH_BOOST +#include +#include +#else #if defined(_MSC_VER) && _MSC_VER <= 1700 #include #include @@ -40,6 +44,8 @@ #include #include #endif +#endif + #include #include "ceres/integral_types.h" #include "ceres/internal/port.h" @@ -118,7 +124,11 @@ CERES_HASH_NAMESPACE_START // Hasher for STL pairs. Requires hashers for both members to be defined. template +#ifdef CERES_HASH_BOOST +struct hash { +#else struct hash > { +#endif size_t operator()(const pair& p) const { size_t h1 = hash()(p.first); size_t h2 = hash()(p.second); diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index bf44a558b1a..7486edf2319 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -53,19 +53,20 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel): scene = context.scene cscene = scene.cycles + device_type = context.user_preferences.system.compute_device_type split = layout.split() col = split.column() sub = col.column() - sub.active = cscene.device == 'CPU' + sub.enabled = (device_type == 'NONE' or cscene.device == 'CPU') sub.prop(cscene, "progressive") sub = col.column(align=True) sub.prop(cscene, "seed") sub.prop(cscene, "sample_clamp") - if cscene.progressive or cscene.device != 'CPU': + if cscene.progressive or (device_type != 'NONE' and cscene.device == 'GPU'): col = split.column() col.label(text="Samples:") sub = col.column(align=True) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 7b80c520e72..5930a2800bf 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -372,6 +372,12 @@ void BlenderSession::synchronize() return; } + /* if the session is still resetting the device come back later */ + if(session->resetting()) { + tag_update(); + return; + } + /* increase samples, but never decrease */ session->set_samples(session_params.samples); session->set_pause(BlenderSync::get_session_pause(b_scene, background)); diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index 2ee2e044618..8e3bc408399 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -115,6 +115,7 @@ public: virtual void task_add(DeviceTask& task) = 0; virtual void task_wait() = 0; virtual void task_cancel() = 0; + virtual bool task_cancelled() = 0; /* opengl drawing */ virtual void draw_pixels(device_memory& mem, int y, int w, int h, diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 4c54671b0d0..e2f612ee233 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -273,6 +273,11 @@ public: { task_pool.cancel(); } + + bool task_cancelled() + { + return task_pool.cancelled(); + } }; Device *device_cpu_create(DeviceInfo& info, int threads) diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index c8dcfdc2f3d..acc1086cc35 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -892,6 +892,11 @@ public: { task_pool.cancel(); } + + bool task_cancelled() + { + return task_pool.cancelled(); + } }; Device *device_cuda_create(DeviceInfo& info, bool background) diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp index 546ffe5e4b9..4923e5c9e66 100644 --- a/intern/cycles/device/device_multi.cpp +++ b/intern/cycles/device/device_multi.cpp @@ -312,6 +312,14 @@ public: foreach(SubDevice& sub, devices) sub.device->task_cancel(); } + + bool task_cancelled() + { + foreach(SubDevice& sub, devices) + if (sub.device->task_cancelled()) + return true; + return false; + } }; Device *device_multi_create(DeviceInfo& info, bool background) diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 3c78b4895ae..ed7229d49da 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -724,6 +724,11 @@ public: { task_pool.cancel(); } + + bool task_cancelled() + { + return task_pool.cancelled(); + } }; Device *device_opencl_create(DeviceInfo& info, bool background) @@ -734,29 +739,31 @@ Device *device_opencl_create(DeviceInfo& info, bool background) void device_opencl_info(vector& devices) { vector device_ids; - cl_uint num_devices; - cl_platform_id platform_id; - cl_uint num_platforms; + cl_uint num_devices = 0; + vector platform_ids; + cl_uint num_platforms = 0; /* get devices */ if(clGetPlatformIDs(0, NULL, &num_platforms) != CL_SUCCESS || num_platforms == 0) return; + + platform_ids.resize(num_platforms); - if(clGetPlatformIDs(1, &platform_id, NULL) != CL_SUCCESS) + if(clGetPlatformIDs(num_platforms, &platform_ids[0], NULL) != CL_SUCCESS) return; - if(clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU|CL_DEVICE_TYPE_ACCELERATOR, 0, NULL, &num_devices) != CL_SUCCESS) + if(clGetDeviceIDs(platform_ids[0], CL_DEVICE_TYPE_GPU|CL_DEVICE_TYPE_ACCELERATOR, 0, NULL, &num_devices) != CL_SUCCESS || num_devices == 0) return; device_ids.resize(num_devices); - if(clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU|CL_DEVICE_TYPE_ACCELERATOR, num_devices, &device_ids[0], NULL) != CL_SUCCESS) + if(clGetDeviceIDs(platform_ids[0], CL_DEVICE_TYPE_GPU|CL_DEVICE_TYPE_ACCELERATOR, num_devices, &device_ids[0], NULL) != CL_SUCCESS) return; /* add devices */ for(int num = 0; num < num_devices; num++) { cl_device_id device_id = device_ids[num]; - char name[1024]; + char name[1024] = "\0"; if(clGetDeviceInfo(device_id, CL_DEVICE_NAME, sizeof(name), &name, NULL) != CL_SUCCESS) continue; diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 0efbcb8afd3..05c57ba48ec 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -140,6 +140,12 @@ void Session::reset_gpu(BufferParams& buffer_params, int samples) pause_cond.notify_all(); } +bool Session::resetting_gpu() const +{ + /* no need to wait for gpu device */ + return false; +} + bool Session::draw_gpu(BufferParams& buffer_params) { /* block for buffer access */ @@ -290,6 +296,11 @@ void Session::reset_cpu(BufferParams& buffer_params, int samples) pause_cond.notify_all(); } +bool Session::resetting_cpu() const +{ + return device->task_cancelled(); +} + bool Session::draw_cpu(BufferParams& buffer_params) { thread_scoped_lock display_lock(display_mutex); @@ -584,6 +595,14 @@ void Session::reset(BufferParams& buffer_params, int samples) reset_cpu(buffer_params, samples); } +bool Session::resetting() const +{ + if(device_use_gl) + return resetting_gpu(); + else + return resetting_cpu(); +} + void Session::set_samples(int samples) { if(samples != params.samples) { diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 7b01357a2b7..e45753d22a0 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -116,6 +116,7 @@ public: bool ready_to_reset(); void reset(BufferParams& params, int samples); + bool resetting() const; void set_samples(int samples); void set_pause(bool pause); @@ -139,10 +140,12 @@ protected: void run_cpu(); bool draw_cpu(BufferParams& params); void reset_cpu(BufferParams& params, int samples); + bool resetting_cpu() const; void run_gpu(); bool draw_gpu(BufferParams& params); void reset_gpu(BufferParams& params, int samples); + bool resetting_gpu() const; bool acquire_tile(Device *tile_device, RenderTile& tile); void update_tile_sample(RenderTile& tile); diff --git a/intern/cycles/util/util_opencl.cpp b/intern/cycles/util/util_opencl.cpp index c9df9c2ff5c..40b637f5cb7 100644 --- a/intern/cycles/util/util_opencl.cpp +++ b/intern/cycles/util/util_opencl.cpp @@ -235,8 +235,10 @@ int clLibraryInit() __clewEnqueueBarrier = (PFNCLENQUEUEBARRIER )CLCC_DYNLIB_IMPORT(module, "clEnqueueBarrier"); __clewGetExtensionFunctionAddress = (PFNCLGETEXTENSIONFUNCTIONADDRESS )CLCC_DYNLIB_IMPORT(module, "clGetExtensionFunctionAddress"); - if(__clewGetPlatformIDs == NULL) - return 0; + if(__clewGetPlatformIDs == NULL) return 0; + if(__clewGetPlatformInfo == NULL) return 0; + if(__clewGetDeviceIDs == NULL) return 0; + if(__clewGetDeviceInfo == NULL) return 0; return 1; } diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp index ea0abd6f54f..2b209c135f4 100644 --- a/intern/cycles/util/util_task.cpp +++ b/intern/cycles/util/util_task.cpp @@ -38,6 +38,8 @@ TaskPool::~TaskPool() void TaskPool::push(Task *task, bool front) { + thread_scoped_lock num_lock(num_mutex); + TaskScheduler::Entry entry; entry.task = task; @@ -102,22 +104,17 @@ void TaskPool::wait_work() void TaskPool::cancel() { + thread_scoped_lock num_lock(num_mutex); + do_cancel = true; TaskScheduler::clear(this); - - { - thread_scoped_lock num_lock(num_mutex); - - while(num) - num_cond.wait(num_lock); - } - - do_cancel = false; } void TaskPool::stop() { + thread_scoped_lock num_lock(num_mutex); + TaskScheduler::clear(this); assert(num == 0); @@ -130,20 +127,20 @@ bool TaskPool::cancelled() void TaskPool::num_decrease(int done) { - num_mutex.lock(); num -= done; - assert(num >= 0); - if(num == 0) + + if(num == 0) { + do_cancel = false; + num_cond.notify_all(); - - num_mutex.unlock(); + } } void TaskPool::num_increase() { - thread_scoped_lock num_lock(num_mutex); num++; + num_cond.notify_all(); } @@ -239,7 +236,11 @@ void TaskScheduler::thread_run(int thread_id) delete entry.task; /* notify pool task was done */ - entry.pool->num_decrease(1); + { + /* not called from TaskPool, have to explicitly lock the mutex here */ + thread_scoped_lock num_lock(entry.pool->num_mutex); + entry.pool->num_decrease(1); + } } } diff --git a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py index f00b92beeed..32658d353d9 100644 --- a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py +++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py @@ -146,8 +146,14 @@ class PlayRenderedAnim(Operator): # launch it print("Executing command:\n %r" % " ".join(cmd)) + # workaround for boost 1.46, can be eventually removed. bug: [#32350] + env_copy = os.environ.copy() + if preset == 'INTERNAL': + env_copy["LC_ALL"] = "C" + # end workaround + try: - subprocess.Popen(cmd) + subprocess.Popen(cmd, env=env_copy) except Exception as e: self.report({'ERROR'}, "Couldn't run external animation player with command " diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index 513277a2099..07d4096632f 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -847,28 +847,35 @@ class WM_OT_doc_view_manual(Operator): doc_id = doc_id @staticmethod - def _find_reference(rna_id, url_mapping): - print("online manual check for: '%s'... " % rna_id) + def _find_reference(rna_id, url_mapping, verbose=True): + if verbose: + print("online manual check for: '%s'... " % rna_id) from fnmatch import fnmatch for pattern, url_suffix in url_mapping: if fnmatch(rna_id, pattern): - print(" match found: '%s' --> '%s'" % (pattern, url_suffix)) + if verbose: + print(" match found: '%s' --> '%s'" % (pattern, url_suffix)) return url_suffix - print("match not found") + if verbose: + print("match not found") return None + @staticmethod + def _lookup_rna_url(rna_id, verbose=True): + url = None + for prefix, url_manual_mapping in bpy.utils.manual_map(): + rna_ref = WM_OT_doc_view_manual._find_reference(rna_id, url_manual_mapping, verbose=verbose) + if rna_ref is not None: + url = prefix + rna_ref + break + return url + def execute(self, context): rna_id = _wm_doc_get_id(self.doc_id, do_url=False) if rna_id is None: return {'PASS_THROUGH'} - url = None - - for prefix, url_manual_mapping in bpy.utils.manual_map(): - rna_ref = self._find_reference(rna_id, url_manual_mapping) - if rna_ref is not None: - url = prefix + rna_ref - break + url = self._lookup_rna_url(rna_id) if url is None: self.report({'WARNING'}, "No reference available %r, " diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h index d1908fe7a3a..f506c67a36c 100644 --- a/source/blender/blenkernel/BKE_anim.h +++ b/source/blender/blenkernel/BKE_anim.h @@ -65,6 +65,7 @@ int where_on_path(struct Object *ob, float ctime, float vec[4], float dir[3], fl /* ---------------------------------------------------- */ /* Dupli-Geometry */ +struct ListBase *object_duplilist_ex(struct Scene *sce, struct Object *ob, int update); struct ListBase *object_duplilist(struct Scene *sce, struct Object *ob); void free_object_duplilist(struct ListBase *lb); int count_duplilist(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 6e0dec33453..4f1e48e345d 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -203,6 +203,10 @@ int BKE_image_scale(struct Image *image, int width, int height); /* check if texture has alpha (depth=32) */ int BKE_image_has_alpha(struct Image *image); +void BKE_image_get_size(struct Image *image, struct ImageUser *iuser, int *width, int *height); +void BKE_image_get_size_fl(struct Image *image, struct ImageUser *iuser, float size[2]); +void BKE_image_get_aspect(struct Image *image, float *aspx, float *aspy); + /* image_gen.c */ void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, int height, const float color[4]); void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int height, int width); diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 48615e638e8..9ce678d8988 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -28,6 +28,8 @@ #ifndef __BKE_MASK_H__ #define __BKE_MASK_H__ +struct ImageUser; +struct Image; struct ListBase; struct Main; struct Mask; @@ -103,10 +105,12 @@ struct Mask *BKE_mask_copy(struct Mask *mask); void BKE_mask_free(struct Mask *mask); void BKE_mask_unlink(struct Main *bmain, struct Mask *mask); -void BKE_mask_coord_from_movieclip(struct MovieClip *clip, struct MovieClipUser *user, float r_co[2], const float co[2]); void BKE_mask_coord_from_frame(float r_co[2], const float co[2], const float frame_size[2]); -void BKE_mask_coord_to_movieclip(struct MovieClip *clip, struct MovieClipUser *user, float r_co[2], const float co[2]); +void BKE_mask_coord_from_movieclip(struct MovieClip *clip, struct MovieClipUser *user, float r_co[2], const float co[2]); +void BKE_mask_coord_from_image(struct Image *image, struct ImageUser *iuser, float r_co[2], const float co[2]); void BKE_mask_coord_to_frame(float r_co[2], const float co[2], const float frame_size[2]); +void BKE_mask_coord_to_movieclip(struct MovieClip *clip, struct MovieClipUser *user, float r_co[2], const float co[2]); +void BKE_mask_coord_to_image(struct Image *image, struct ImageUser *iuser, float r_co[2], const float co[2]); /* parenting */ diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h index 739b63ca174..25d2678ea47 100644 --- a/source/blender/blenkernel/BKE_movieclip.h +++ b/source/blender/blenkernel/BKE_movieclip.h @@ -51,9 +51,10 @@ struct ImBuf *BKE_movieclip_get_postprocessed_ibuf(struct MovieClip *clip, struc struct ImBuf *BKE_movieclip_get_stable_ibuf(struct MovieClip *clip, struct MovieClipUser *user, float loc[2], float *scale, float *angle, int postprocess_flag); struct ImBuf *BKE_movieclip_get_ibuf_flag(struct MovieClip *clip, struct MovieClipUser *user, int flag, int cache_flag); void BKE_movieclip_get_size(struct MovieClip *clip, struct MovieClipUser *user, int *width, int *height); -int BKE_movieclip_get_duration(struct MovieClip *clip); -void BKE_movieclip_aspect(struct MovieClip *clip, float *aspx, float *aspy); -int BKE_movieclip_has_frame(struct MovieClip *clip, struct MovieClipUser *user); +void BKE_movieclip_get_size_fl(struct MovieClip *clip, struct MovieClipUser *user, float size[2]); +int BKE_movieclip_get_duration(struct MovieClip *clip); +void BKE_movieclip_get_aspect(struct MovieClip *clip, float *aspx, float *aspy); +int BKE_movieclip_has_frame(struct MovieClip *clip, struct MovieClipUser *user); void BKE_movieclip_user_set_frame(struct MovieClipUser *user, int framenr); void BKE_movieclip_update_scopes(struct MovieClip *clip, struct MovieClipUser *user, struct MovieClipScopes *scopes); diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 81fb936f244..0c571f62f0e 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -307,6 +307,7 @@ int BKE_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char int BKE_sequence_check_depend(struct Sequence *seq, struct Sequence *cur); void BKE_sequence_invalidate_cache(struct Scene *scene, struct Sequence *seq); +void BKE_sequence_invalidate_deendent(struct Scene *scene, struct Sequence *seq); void BKE_sequence_invalidate_cache_for_modifier(struct Scene *scene, struct Sequence *seq); void BKE_sequencer_update_sound_bounds_all(struct Scene *scene); diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 3e5dff74f3b..06bf5211abb 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -526,18 +526,12 @@ void BKE_pose_copy_data(bPose **dst, bPose *src, int copycon) bPose *outPose; bPoseChannel *pchan; ListBase listb; - + if (!src) { *dst = NULL; return; } - if (*dst == src) { - printf("BKE_pose_copy_data source and target are the same\n"); - *dst = NULL; - return; - } - outPose = MEM_callocN(sizeof(bPose), "pose"); BLI_duplicatelist(&outPose->chanbase, &src->chanbase); diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 4f68ab82329..1b301ba43b3 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -74,7 +74,8 @@ /* --------------------- */ /* forward declarations */ -static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, int level, int animated); +static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, + int level, short animated, short update); /* ******************************************************************** */ /* Animation Visualization */ @@ -699,7 +700,7 @@ int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float qua /* ******************************************************************** */ /* Dupli-Geometry */ -static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index, int par_index, int type, int animated) +static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index, int par_index, int type, short animated) { DupliObject *dob = MEM_callocN(sizeof(DupliObject), "dupliobject"); @@ -717,7 +718,8 @@ static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], i return dob; } -static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, int animated) +static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, + int level, short animated, short update) { DupliObject *dob; Group *group; @@ -731,8 +733,14 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde if (level > MAX_DUPLI_RECUR) return; /* handles animated groups, and */ + /* we need to check update for objects that are not in scene... */ - group_handle_recalc_and_update(scene, ob, group); + if (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); + } + animated = animated || group_is_animated(ob, group); for (go = group->gobject.first; go; go = go->next) { @@ -764,14 +772,14 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde if (go->ob->transflag & OB_DUPLI) { copy_m4_m4(dob->ob->obmat, dob->mat); - object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, par_index, level + 1, animated); + object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, par_index, level + 1, animated, update); copy_m4_m4(dob->ob->obmat, dob->omat); } } } } -static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, int animated) +static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, short animated) { extern int enable_cu_speed; /* object.c */ Object copyob; @@ -843,7 +851,8 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_ind typedef struct VertexDupliData { ID *id; /* scene or group, for recursive loops */ int level; - int animated; + short animated; + short update; ListBase *lb; float pmat[4][4]; float obmat[4][4]; /* Only used for dupliverts inside dupligroups, where the ob->obmat is modified */ @@ -899,12 +908,13 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], float tmpmat[4][4]; copy_m4_m4(tmpmat, vdd->ob->obmat); copy_m4_m4(vdd->ob->obmat, obmat); /* pretend we are really this mat */ - object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->par_index, vdd->level + 1, vdd->animated); + object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->par_index, vdd->level + 1, vdd->animated, vdd->update); copy_m4_m4(vdd->ob->obmat, tmpmat); } } -static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, int level, int animated) +static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, + int level, short animated, short update) { Object *ob, *ob_iter; Mesh *me = par->data; @@ -983,6 +993,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl vdd.id = id; vdd.level = level; vdd.animated = animated; + vdd.update = update; vdd.lb = lb; vdd.ob = ob; vdd.scene = scene; @@ -1027,7 +1038,8 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl dm->release(dm); } -static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, int level, int animated) +static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, + int level, short animated, short update) { Object *ob, *ob_iter; Base *base = NULL; @@ -1197,7 +1209,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa float tmpmat[4][4]; copy_m4_m4(tmpmat, ob->obmat); copy_m4_m4(ob->obmat, obmat); /* pretend we are really this mat */ - object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, par_index, level + 1, animated); + object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, par_index, level + 1, animated, update); copy_m4_m4(ob->obmat, tmpmat); } } @@ -1217,7 +1229,8 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa dm->release(dm); } -static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int UNUSED(par_index), ParticleSystem *psys, int level, int animated) +static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int UNUSED(par_index), ParticleSystem *psys, + int level, short animated, short update) { GroupObject *go; Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL; @@ -1300,7 +1313,9 @@ 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) { - group_handle_recalc_and_update(scene, par, part->dup_group); + if (update) { + group_handle_recalc_and_update(scene, par, part->dup_group); + } if (part->draw & PART_DRAW_COUNT_GR) { for (dw = part->dupliweights.first; dw; dw = dw->next) @@ -1555,7 +1570,7 @@ static Object *find_family_object(Object **obar, char *family, char ch) } -static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_index, int level, int animated) +static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_index, int level, short animated) { Object *ob, *obar[256] = {NULL}; Curve *cu; @@ -1603,7 +1618,8 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_inde /* ------------- */ -static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, int level, int animated) +static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, + int level, short animated, short update) { if ((ob->transflag & OB_DUPLI) == 0) return; @@ -1623,11 +1639,11 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas if (ob->transflag & OB_DUPLIPARTS) { ParticleSystem *psys = ob->particlesystem.first; for (; psys; psys = psys->next) - new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, psys, level + 1, animated); + new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, psys, level + 1, animated, update); } else if (ob->transflag & OB_DUPLIVERTS) { if (ob->type == OB_MESH) { - vertex_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated); + vertex_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated, update); } else if (ob->type == OB_FONT) { if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */ @@ -1637,7 +1653,7 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas } else if (ob->transflag & OB_DUPLIFACES) { if (ob->type == OB_MESH) - face_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated); + face_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated, update); } else if (ob->transflag & OB_DUPLIFRAMES) { if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */ @@ -1647,7 +1663,7 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas else if (ob->transflag & OB_DUPLIGROUP) { DupliObject *dob; - group_duplilist(duplilist, scene, ob, par_index, level + 1, animated); /* now recursive */ + group_duplilist(duplilist, scene, ob, par_index, level + 1, animated, update); /* now recursive */ if (level == 0) { for (dob = duplilist->first; dob; dob = dob->next) @@ -1659,14 +1675,22 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas /* Returns a list of DupliObject * note; group dupli's already set transform matrix. see note in group_duplilist() */ -ListBase *object_duplilist(Scene *sce, Object *ob) +ListBase *object_duplilist_ex(Scene *sce, Object *ob, int update) { ListBase *duplilist = MEM_mallocN(sizeof(ListBase), "duplilist"); duplilist->first = duplilist->last = NULL; - object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0, 0); + object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0, 0, update); return duplilist; } +/* note: previously updating was always done, this is why it defaults to be on + * but there are likely places it can be called without updating */ +ListBase *object_duplilist(Scene *sce, Object *ob) +{ + return object_duplilist_ex(sce, ob, TRUE); +} + + void free_object_duplilist(ListBase *lb) { DupliObject *dob; diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 5fea74d52de..2dbc63e6944 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -504,8 +504,8 @@ short calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, flo xmaxv = MAX3(xmaxv, bezt_last->vec[1][0], bezt_last->vec[2][0]); } else { - xminv = MIN2(xminv, bezt_first->vec[1][0]); - xmaxv = MAX2(xmaxv, bezt_last->vec[1][0]); + xminv = minf(xminv, bezt_first->vec[1][0]); + xmaxv = maxf(xmaxv, bezt_last->vec[1][0]); } } } @@ -521,8 +521,8 @@ short calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, flo ymaxv = MAX4(ymaxv, bezt->vec[1][1], bezt->vec[0][1], bezt->vec[2][1]); } else { - yminv = MIN2(yminv, bezt->vec[1][1]); - ymaxv = MAX2(ymaxv, bezt->vec[1][1]); + yminv = minf(yminv, bezt->vec[1][1]); + ymaxv = maxf(ymaxv, bezt->vec[1][1]); } foundvert = TRUE; @@ -533,8 +533,8 @@ short calc_fcurve_bounds(FCurve *fcu, float *xmin, float *xmax, float *ymin, flo else if (fcu->fpt) { /* frame range can be directly calculated from end verts */ if (xmin || xmax) { - xminv = MIN2(xminv, fcu->fpt[0].vec[0]); - xmaxv = MAX2(xmaxv, fcu->fpt[fcu->totvert - 1].vec[0]); + xminv = minf(xminv, fcu->fpt[0].vec[0]); + xmaxv = maxf(xmaxv, fcu->fpt[fcu->totvert - 1].vec[0]); } /* only loop over keyframes to find extents for values if needed */ @@ -591,15 +591,15 @@ void calc_fcurve_range(FCurve *fcu, float *start, float *end, if (bezt_first) { BLI_assert(bezt_last != NULL); - min = MIN2(min, bezt_first->vec[1][0]); - max = MAX2(max, bezt_last->vec[1][0]); + min = minf(min, bezt_first->vec[1][0]); + max = maxf(max, bezt_last->vec[1][0]); foundvert = TRUE; } } else if (fcu->fpt) { - min = MIN2(min, fcu->fpt[0].vec[0]); - max = MAX2(max, fcu->fpt[fcu->totvert - 1].vec[0]); + min = minf(min, fcu->fpt[0].vec[0]); + max = maxf(max, fcu->fpt[fcu->totvert - 1].vec[0]); foundvert = TRUE; } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 4e7b9db73e6..0949f54642d 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2977,3 +2977,40 @@ int BKE_image_has_alpha(struct Image *image) else return 0; } + +void BKE_image_get_size(Image *image, ImageUser *iuser, int *width, int *height) +{ + ImBuf *ibuf = NULL; + void *lock; + + ibuf = BKE_image_acquire_ibuf(image, iuser, &lock); + + if (ibuf && ibuf->x > 0 && ibuf->y > 0) { + *width = ibuf->x; + *height = ibuf->y; + } + else { + *width = IMG_SIZE_FALLBACK; + *height = IMG_SIZE_FALLBACK; + } + + BKE_image_release_ibuf(image, lock); +} + +void BKE_image_get_size_fl(Image *image, ImageUser *iuser, float size[2]) +{ + int width, height; + BKE_image_get_size(image, iuser, &width, &height); + + size[0] = (float)width; + size[1] = (float)height; + +} + +void BKE_image_get_aspect(Image *image, float *aspx, float *aspy) +{ + *aspx = 1.0; + + /* x is always 1 */ + *aspy = image->aspy / image->aspx; +} diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 17a3c595ea7..b79608342dd 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -691,8 +691,8 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const if (nu->bp) { step = nu->pntsu * nu->pntsv; - a1 = MAX2(a, start); - a2 = MIN2(a + step, end); + a1 = maxi(a, start); + a2 = mini(a + step, end); if (a1 < a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_MODE_BPOINT); } @@ -700,8 +700,8 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const step = 3 * nu->pntsu; /* exception because keys prefer to work with complete blocks */ - a1 = MAX2(a, start); - a2 = MIN2(a + step, end); + a1 = maxi(a, start); + a2 = mini(a + step, end); if (a1 < a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_MODE_BEZTRIPLE); } @@ -1217,7 +1217,7 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, const in remain = step; } - count = MIN2(remain, estep); + count = mini(remain, estep); if (mode == KEY_MODE_BEZTRIPLE) { count += 3 - count % 3; } @@ -1573,7 +1573,7 @@ void key_to_latt(KeyBlock *kb, Lattice *lt) fp = kb->data; tot = lt->pntsu * lt->pntsv * lt->pntsw; - tot = MIN2(kb->totelem, tot); + tot = mini(kb->totelem, tot); for (a = 0; a < tot; a++, fp += 3, bp++) { copy_v3_v3(bp->vec, fp); @@ -1645,7 +1645,7 @@ void key_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb) tot = BKE_nurbList_verts_count(nurb); - tot = MIN2(kb->totelem, tot); + tot = mini(kb->totelem, tot); while (nu && tot > 0) { @@ -1713,7 +1713,7 @@ void key_to_mesh(KeyBlock *kb, Mesh *me) mvert = me->mvert; fp = kb->data; - tot = MIN2(kb->totelem, me->totvert); + tot = mini(kb->totelem, me->totvert); for (a = 0; a < tot; a++, fp += 3, mvert++) { copy_v3_v3(mvert->co, fp); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index f73fb3879b8..06d063574a5 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -55,6 +55,7 @@ #include "BKE_sequencer.h" #include "BKE_tracking.h" #include "BKE_movieclip.h" +#include "BKE_image.h" static MaskSplinePoint *mask_spline_point_next(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point) { @@ -1010,14 +1011,26 @@ void BKE_mask_coord_from_frame(float r_co[2], const float co[2], const float fra } void BKE_mask_coord_from_movieclip(MovieClip *clip, MovieClipUser *user, float r_co[2], const float co[2]) { - int width, height; + float aspx, aspy; float frame_size[2]; /* scaling for the clip */ - BKE_movieclip_get_size(clip, user, &width, &height); + BKE_movieclip_get_size_fl(clip, user, frame_size); + BKE_movieclip_get_aspect(clip, &aspx, &aspy); - frame_size[0] = (float)width; - frame_size[1] = (float)height; + frame_size[1] *= (aspy / aspx); + + BKE_mask_coord_from_frame(r_co, co, frame_size); +} +void BKE_mask_coord_from_image(Image *image, ImageUser *iuser, float r_co[2], const float co[2]) +{ + float aspx, aspy; + float frame_size[2]; + + BKE_image_get_size_fl(image, iuser, frame_size); + BKE_image_get_aspect(image, &aspx, &aspy); + + frame_size[1] *= (aspy / aspx); BKE_mask_coord_from_frame(r_co, co, frame_size); } @@ -1040,14 +1053,27 @@ void BKE_mask_coord_to_frame(float r_co[2], const float co[2], const float frame } void BKE_mask_coord_to_movieclip(MovieClip *clip, MovieClipUser *user, float r_co[2], const float co[2]) { - int width, height; + float aspx, aspy; float frame_size[2]; /* scaling for the clip */ - BKE_movieclip_get_size(clip, user, &width, &height); + BKE_movieclip_get_size_fl(clip, user, frame_size); + BKE_movieclip_get_aspect(clip, &aspx, &aspy); - frame_size[0] = (float)width; - frame_size[1] = (float)height; + frame_size[1] /= (aspy / aspx); + + BKE_mask_coord_to_frame(r_co, co, frame_size); +} +void BKE_mask_coord_to_image(Image *image, ImageUser *iuser, float r_co[2], const float co[2]) +{ + float aspx, aspy; + float frame_size[2]; + + /* scaling for the clip */ + BKE_image_get_size_fl(image, iuser, frame_size); + BKE_image_get_aspect(image, &aspx, &aspy); + + frame_size[1] /= (aspy / aspx); BKE_mask_coord_to_frame(r_co, co, frame_size); } diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index eb96d6726b9..18617f0ef2e 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -26,6 +26,46 @@ /** \file blender/blenkernel/intern/mask_rasterize.c * \ingroup bke + * + * This module exposes a rasterizer that works as a black box - implementation details are confined to this file, + * + * The basic method to access is: + * - create & initialize a handle from a #Mask datablock. + * - execute pixel lookups. + * - free the handle. + * + * This file is admittedly a bit confusticated, in quite few areas speed was chosen over readability, + * though it is commented - so shouldn't be so hard to see whats going on. + * + * + * Implementation: + * + * To rasterize the mask its converted into geometry that use a ray-cast for each pixel lookup. + * + * Initially 'kdopbvh' was used but this ended up being too slow. + * + * To gain some extra speed we take advantage of a few shortcuts that can be made rasterizing masks specifically. + * - all triangles are known to be completely white - so no depth check is done on triangle intersection. + * - all quads are known to be feather outlines - the 1 and 0 depths are known by the vertex order in the quad, + * - there is no color - just a value for each mask pixel. + * - the mask spacial structure always maps to space 0-1 on X and Y axis. + * - bucketing is used to speed up lookups for geometry. + * + * Other Details: + * - used unsigned values all over for some extra speed on some arch's. + * - anti-aliasing is faked, just ensuring at least one pixel feather - avoids oversampling. + * - initializing the spacial structure doesn't need to be as optimized as pixel lookups are. + * - mask lookups need not be pixel aligned so any sub-pixel values from x/y (0 - 1), can be found. + * (perhaps masks can be used as a vector texture in 3D later on) + * + * + * Currently, to build the spacial structure we have to calculate the total number of faces ahead of time. + * + * This is getting a bit complicated with the addition of unfilled splines and end capping - + * If large changes are needed here we would be better off using an iterable + * BLI_mempool for triangles and converting to a contiguous array afterwards. + * + * - Campbell */ #include "MEM_guardedalloc.h" diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index aa7388abd58..e83e6974102 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1009,6 +1009,14 @@ void BKE_movieclip_get_size(MovieClip *clip, MovieClipUser *user, int *width, in IMB_freeImBuf(ibuf); } } +void BKE_movieclip_get_size_fl(MovieClip *clip, MovieClipUser *user, float size[2]) +{ + int width, height; + BKE_movieclip_get_size(clip, user, &width, &height); + + size[0] = (float)width; + size[1] = (float)height; +} int BKE_movieclip_get_duration(MovieClip *clip) { @@ -1019,9 +1027,9 @@ int BKE_movieclip_get_duration(MovieClip *clip) return clip->len; } -void BKE_movieclip_aspect(MovieClip *clip, float *aspx, float *aspy) +void BKE_movieclip_get_aspect(MovieClip *clip, float *aspx, float *aspy) { - *aspx = *aspy = 1.0; + *aspx = 1.0; /* x is always 1 */ *aspy = clip->aspy / clip->aspx / clip->tracking.camera.pixel_aspect; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index dfa3582cee8..5dfecfcb717 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2700,7 +2700,7 @@ void BKE_object_handle_update(Scene *scene, Object *ob) if (pid->cache->flag & PTCACHE_OUTDATED || (pid->cache->flag & PTCACHE_SIMULATION_VALID) == 0) { scene->physics_settings.quick_cache_step = scene->physics_settings.quick_cache_step ? - MIN2(scene->physics_settings.quick_cache_step, pid->cache->step) : + mini(scene->physics_settings.quick_cache_step, pid->cache->step) : pid->cache->step; } } diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 5e12b15a658..780528f4a0d 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -1029,7 +1029,8 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup if (scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) { ListBase *lb_dupli_ob; - if ((lb_dupli_ob=object_duplilist(scene, ob))) { + /* don't update the dupli groups, we only wan't their pid's */ + if ((lb_dupli_ob = object_duplilist_ex(scene, ob, FALSE))) { DupliObject *dob; for (dob= lb_dupli_ob->first; dob; dob= dob->next) { if (dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */ diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 5e79de7b4cd..e870ec5d8ee 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -3049,13 +3049,18 @@ int BKE_sequence_check_depend(Sequence *seq, Sequence *cur) return TRUE; } -static void sequence_invalidate_cache(Scene *scene, Sequence *seq, int invalidate_preprocess) +static void sequence_invalidate_cache(Scene *scene, Sequence *seq, int invalidate_self, int invalidate_preprocess) { Editing *ed = scene->ed; Sequence *cur; /* invalidate cache for current sequence */ - BKE_sequencer_cache_cleanup_sequence(seq); + if (invalidate_self) + BKE_sequencer_cache_cleanup_sequence(seq); + + /* if invalidation is invoked from sequence free routine, effectdata would be NULL here */ + if (seq->effectdata && seq->type == SEQ_TYPE_SPEED) + BKE_sequence_effect_speed_rebuild_map(scene, seq, TRUE); if (invalidate_preprocess) BKE_sequencer_preprocessed_cache_cleanup_sequence(seq); @@ -3076,12 +3081,17 @@ static void sequence_invalidate_cache(Scene *scene, Sequence *seq, int invalidat void BKE_sequence_invalidate_cache(Scene *scene, Sequence *seq) { - sequence_invalidate_cache(scene, seq, TRUE); + sequence_invalidate_cache(scene, seq, TRUE, TRUE); +} + +void BKE_sequence_invalidate_deendent(Scene *scene, Sequence *seq) +{ + sequence_invalidate_cache(scene, seq, FALSE, TRUE); } void BKE_sequence_invalidate_cache_for_modifier(Scene *scene, Sequence *seq) { - sequence_invalidate_cache(scene, seq, FALSE); + sequence_invalidate_cache(scene, seq, TRUE, FALSE); } void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, int for_render) diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 76f4f26b728..53e9a6b66cb 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -2229,7 +2229,7 @@ void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[ t2 = mean_value_half_tan_v3(co, vmid, vnext); len = len_v3v3(co, vmid); - w[i] = (t1 + t2) / len; + w[i] = (len != 0.0f)? (t1 + t2) / len: 0.0f; totweight += w[i]; } @@ -2257,7 +2257,7 @@ void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[ t2 = mean_value_half_tan_v2(co, vmid, vnext); len = len_v2v2(co, vmid); - w[i] = (t1 + t2) / len; + w[i] = (len != 0.0f)? (t1 + t2) / len: 0.0f; totweight += w[i]; } diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 4d10ef317f3..f03ce9b8543 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -340,6 +340,8 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, return f; } +#ifndef NDEBUG + /** * Check the element is valid. * @@ -476,6 +478,8 @@ int bmesh_elem_check(void *element, const char htype) return err; } +#endif /* NDEBUG */ + /** * low level function, only frees the vert, * doesn't change or adjust surrounding geometry diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c index 64920df6e20..726127fdcad 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.c +++ b/source/blender/bmesh/intern/bmesh_iterators.c @@ -123,12 +123,12 @@ void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len) if (BM_iter_init(&iter, bm, itype, data) && iter.count > 0) { BMElem *ele; BMElem **array = MEM_mallocN(sizeof(ele) * iter.count, __func__); - int i; + int i = 0; *r_len = iter.count; /* set before iterating */ - for (ele = BM_iter_step(&iter), i = 0; ele; ele = BM_iter_step(&iter), i++) { - array[i] = ele; + while ((ele = BM_iter_step(&iter))) { + array[i++] = ele; } return array; } diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h index 0827901f5c2..b3fe3676ab8 100644 --- a/source/blender/bmesh/intern/bmesh_private.h +++ b/source/blender/bmesh/intern/bmesh_private.h @@ -37,21 +37,21 @@ */ /* returns positive nonzero on error */ -int bmesh_elem_check(void *element, const char htype); -#define BM_CHECK_ELEMENT(el) \ +#ifdef NDEBUG + /* no error checking for release, + * it can take most of the CPU time when running some tools */ +# define BM_CHECK_ELEMENT(el) (void)(el) +#else +int bmesh_elem_check(void *element, const char htype); +# define BM_CHECK_ELEMENT(el) \ if (bmesh_elem_check(el, ((BMHeader *)el)->htype)) { \ printf("check_element failure, with code %i on line %i in file\n" \ " \"%s\"\n\n", \ - bmesh_elem_check(el, ((BMHeader *)el)->htype), \ + bmesh_elem_check(el, ((BMHeader *)el)->htype), \ __LINE__, __FILE__); \ - } - -#define BM_DISK_EDGE_LINK_GET(e, v) ( \ - ((v) == ((BMEdge *)(e))->v1) ? \ - &((e)->v1_disk_link) : \ - &((e)->v2_disk_link) \ - ) + } (void)0 +#endif int bmesh_radial_length(BMLoop *l); int bmesh_disk_count(BMVert *v); diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c index 2ff9e707b59..b58e61a3066 100644 --- a/source/blender/bmesh/intern/bmesh_structure.c +++ b/source/blender/bmesh/intern/bmesh_structure.c @@ -153,10 +153,22 @@ int bmesh_edge_swapverts(BMEdge *e, BMVert *orig, BMVert *newv) * advantage is that no intrinsic properties of the data structures are dependent upon the * cycle order and all non-manifold conditions are represented trivially. */ + +BLI_INLINE BMDiskLink *bmesh_disk_edge_link_from_vert(BMEdge *e, BMVert *v) +{ + if (v == e->v1) { + return &e->v1_disk_link; + } + else { + BLI_assert(v == e->v2); + return &e->v2_disk_link; + } +} + int bmesh_disk_edge_append(BMEdge *e, BMVert *v) { if (!v->e) { - BMDiskLink *dl1 = BM_DISK_EDGE_LINK_GET(e, v); + BMDiskLink *dl1 = bmesh_disk_edge_link_from_vert(e, v); v->e = e; dl1->next = dl1->prev = e; @@ -164,9 +176,9 @@ int bmesh_disk_edge_append(BMEdge *e, BMVert *v) else { BMDiskLink *dl1, *dl2, *dl3; - dl1 = BM_DISK_EDGE_LINK_GET(e, v); - dl2 = BM_DISK_EDGE_LINK_GET(v->e, v); - dl3 = dl2->prev ? BM_DISK_EDGE_LINK_GET(dl2->prev, v) : NULL; + dl1 = bmesh_disk_edge_link_from_vert(e, v); + dl2 = bmesh_disk_edge_link_from_vert(v->e, v); + dl3 = dl2->prev ? bmesh_disk_edge_link_from_vert(dl2->prev, v) : NULL; dl1->next = v->e; dl1->prev = dl2->prev; @@ -183,14 +195,14 @@ void bmesh_disk_edge_remove(BMEdge *e, BMVert *v) { BMDiskLink *dl1, *dl2; - dl1 = BM_DISK_EDGE_LINK_GET(e, v); + dl1 = bmesh_disk_edge_link_from_vert(e, v); if (dl1->prev) { - dl2 = BM_DISK_EDGE_LINK_GET(dl1->prev, v); + dl2 = bmesh_disk_edge_link_from_vert(dl1->prev, v); dl2->next = dl1->next; } if (dl1->next) { - dl2 = BM_DISK_EDGE_LINK_GET(dl1->next, v); + dl2 = bmesh_disk_edge_link_from_vert(dl1->next, v); dl2->prev = dl1->prev; } diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c index 3758ba739d1..1987294fc42 100644 --- a/source/blender/bmesh/operators/bmo_connect.c +++ b/source/blender/bmesh/operators/bmo_connect.c @@ -339,7 +339,6 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) goto cleanup; } - j = 0; if (vv1[0] == vv1[lenv1 - 1]) { lenv1--; } diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index baaa6dbeed2..7683ec1e9cd 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -163,6 +163,8 @@ void DocumentExporter::exportCurrentScene(Scene *sce) COLLADABU::NativeString(std::string(this->export_settings->filepath)); COLLADASW::StreamWriter sw(native_filename); + fprintf(stdout, "Collada export: %s\n", this->export_settings->filepath); + // open sw.startDocument(); diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp index c7ad2ff3975..27700444ba9 100644 --- a/source/blender/collada/GeometryExporter.cpp +++ b/source/blender/collada/GeometryExporter.cpp @@ -132,14 +132,17 @@ void GeometryExporter::operator()(Object *ob) createLooseEdgeList(ob, me, geom_id, norind); - // XXX slow - if (ob->totcol) { - for (int a = 0; a < ob->totcol; a++) { - createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind); + // Only create Polylists if number of faces > 0 + if (me->totface > 0) { + // XXX slow + if (ob->totcol) { + for (int a = 0; a < ob->totcol; a++) { + createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind); + } + } + else { + createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind); } - } - else { - createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind); } closeMesh(); @@ -248,7 +251,7 @@ void GeometryExporter::createPolylist(short material_index, // no faces using this material if (faces_in_polylist == 0) { - fprintf(stderr, "%s: no faces use material %d\n", id_name(ob).c_str(), material_index); + fprintf(stderr, "%s: material with index %d is not used.\n", id_name(ob).c_str(), material_index); return; } diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp index ef714f2561f..1af34bfa7b7 100644 --- a/source/blender/collada/ImageExporter.cpp +++ b/source/blender/collada/ImageExporter.cpp @@ -119,12 +119,15 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) // This image is already located on the file system. // But we want to create copies here. - // To avoid overwroting images with same file name but - // differenet source locations + // To move images into the same export directory. + // Note: If an image is already located in the export folder, + // then skip the copy (as it would result in a file copy error). - if (BLI_copy(source_path, export_path) != 0) { - fprintf(stderr, "Collada export: Cannot copy image:\n source:%s\ndest :%s\n", source_path, export_path); - return; + if (BLI_path_cmp(source_path, export_path) != 0) { + if (BLI_copy(source_path, export_path) != 0) { + fprintf(stderr, "Collada export: Cannot copy image:\n source:%s\ndest :%s\n", source_path, export_path); + return; + } } BLI_strncpy(export_path, export_file, sizeof(export_path)); @@ -132,7 +135,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) } else { - // Do not make any vopies, but use the source path directly as reference + // Do not make any copies, but use the source path directly as reference // to the original image BLI_strncpy(export_path, source_path, sizeof(export_path)); diff --git a/source/blender/compositor/intern/COM_NodeOperation.cpp b/source/blender/compositor/intern/COM_NodeOperation.cpp index bae884d713e..4ae114bd031 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.cpp +++ b/source/blender/compositor/intern/COM_NodeOperation.cpp @@ -124,19 +124,26 @@ bool NodeOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOper return false; } else { - unsigned int index; - vector &inputsockets = this->getInputSockets(); - - for (index = 0; index < inputsockets.size(); index++) { - InputSocket *inputsocket = inputsockets[index]; - if (inputsocket->isConnected()) { - NodeOperation *inputoperation = (NodeOperation *)inputsocket->getConnection()->getFromNode(); - bool result = inputoperation->determineDependingAreaOfInterest(input, readOperation, output); - if (result) { - return true; + rcti tempOutput; + bool first = true; + for (int i = 0 ; i < getNumberOfInputSockets() ; i ++) { + NodeOperation * inputOperation = this->getInputOperation(i); + if (inputOperation && inputOperation->determineDependingAreaOfInterest(input, readOperation, &tempOutput)) { + if (first) { + output->xmin = tempOutput.xmin; + output->ymin = tempOutput.ymin; + output->xmax = tempOutput.xmax; + output->ymax = tempOutput.ymax; + first = false; + } + else { + output->xmin = MIN2(output->xmin, tempOutput.xmin); + output->ymin = MIN2(output->ymin, tempOutput.ymin); + output->xmax = MAX2(output->xmax, tempOutput.xmax); + output->ymax = MAX2(output->ymax, tempOutput.ymax); } } } - return false; + return !first; } } diff --git a/source/blender/compositor/operations/COM_CombineChannelsOperation.cpp b/source/blender/compositor/operations/COM_CombineChannelsOperation.cpp index ded686bb5de..3ced0548bb8 100644 --- a/source/blender/compositor/operations/COM_CombineChannelsOperation.cpp +++ b/source/blender/compositor/operations/COM_CombineChannelsOperation.cpp @@ -37,31 +37,6 @@ CombineChannelsOperation::CombineChannelsOperation() : NodeOperation() this->m_inputChannel4Operation = NULL; } -bool CombineChannelsOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) -{ - rcti tempOutput; - bool first = true; - for (int i = 0 ; i < 4 ; i ++) { - NodeOperation * inputOperation = this->getInputOperation(i); - if (inputOperation->determineDependingAreaOfInterest(input, readOperation, &tempOutput)) { - if (first) { - output->xmin = tempOutput.xmin; - output->ymin = tempOutput.ymin; - output->xmax = tempOutput.xmax; - output->ymax = tempOutput.ymax; - first = false; - } - else { - output->xmin = MIN2(output->xmin, tempOutput.xmin); - output->ymin = MIN2(output->ymin, tempOutput.ymin); - output->xmax = MAX2(output->xmax, tempOutput.xmax); - output->ymax = MAX2(output->ymax, tempOutput.ymax); - } - } - } - return !first; -} - void CombineChannelsOperation::initExecution() { this->m_inputChannel1Operation = this->getInputSocketReader(0); @@ -82,7 +57,6 @@ void CombineChannelsOperation::deinitExecution() void CombineChannelsOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) { float input[4]; - /// @todo: remove if statements if (this->m_inputChannel1Operation) { this->m_inputChannel1Operation->read(input, x, y, sampler); output[0] = input[0]; diff --git a/source/blender/compositor/operations/COM_CombineChannelsOperation.h b/source/blender/compositor/operations/COM_CombineChannelsOperation.h index 460eb9bdcb1..7c8742b1557 100644 --- a/source/blender/compositor/operations/COM_CombineChannelsOperation.h +++ b/source/blender/compositor/operations/COM_CombineChannelsOperation.h @@ -37,8 +37,6 @@ public: void initExecution(); void deinitExecution(); - - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); }; #endif diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 95adaa01b94..445b684c261 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -1019,6 +1019,7 @@ static void select_timeline_marker_frame(ListBase *markers, int frame, unsigned static int ed_marker_select(bContext *C, wmEvent *evt, int extend, int camera) { ListBase *markers = ED_context_get_markers(C); + ARegion *ar = CTX_wm_region(C); View2D *v2d = UI_view2d_fromcontext(C); float viewx; int x, y, cfra; @@ -1026,8 +1027,8 @@ static int ed_marker_select(bContext *C, wmEvent *evt, int extend, int camera) if (markers == NULL) return OPERATOR_PASS_THROUGH; - x = evt->x - CTX_wm_region(C)->winrct.xmin; - y = evt->y - CTX_wm_region(C)->winrct.ymin; + x = evt->x - ar->winrct.xmin; + y = evt->y - ar->winrct.ymin; UI_view2d_region_to_view(v2d, x, y, &viewx, NULL); diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index 8738c2a1a2c..a50b33966c6 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -61,9 +61,7 @@ void ED_space_image_get_uv_aspect(struct SpaceImage *sima, float *aspx, float *a void ED_space_image_paint_update(struct wmWindowManager *wm, struct ToolSettings *settings); void ED_space_image_uv_sculpt_update(struct wmWindowManager *wm, struct ToolSettings *settings); -void ED_image_get_size(struct Image *ima, int *width, int *height); -void ED_image_get_aspect(struct Image *ima, float *aspx, float *aspy); -void ED_image_get_uv_aspect(struct Image *ima, float *aspx, float *aspy); +void ED_image_get_uv_aspect(struct Image *ima, struct ImageUser *iuser, float *aspx, float *aspy); void ED_image_mouse_pos(struct SpaceImage *sima, struct ARegion *ar, const int mval[2], float co[2]); void ED_image_point_pos(struct SpaceImage *sima, struct ARegion *ar, float x, float y, float *xr, float *yr); void ED_image_point_pos__reverse(struct SpaceImage *sima, struct ARegion *ar, const float co[2], float r_co[2]); diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index 88667729eee..8ebf932fd96 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -56,7 +56,8 @@ void ED_operatormacros_mask(void); void ED_mask_draw(const bContext *C, const char draw_flag, const char draw_type); void ED_mask_draw_region(struct Mask *mask, struct ARegion *ar, const char draw_flag, const char draw_type, - int width, int height, + const int width_i, const int height_i, + const float aspx, const float aspy, const short do_scale_applied, const short do_post_draw, float stabmat[4][4], const bContext *C); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 84ab68a9b6b..cf440cddb80 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -187,16 +187,17 @@ typedef struct uiLayout uiLayout; * - bit 8: for 'bit' * - bit 9-15: button type (now 6 bits, 64 types) * */ +typedef enum { + UI_BUT_POIN_CHAR = 32, + UI_BUT_POIN_SHORT = 64, + UI_BUT_POIN_INT = 96, + UI_BUT_POIN_FLOAT = 128, +/* UI_BUT_POIN_FUNCTION = 192, */ /*UNUSED*/ + UI_BUT_POIN_BIT = 256 /* OR'd with a bit index*/ +} eButPointerType; -#define CHA 32 -#define SHO 64 -#define INT 96 -#define FLO 128 -/*#define FUN 192*/ /*UNUSED*/ -#define BIT 256 - -/* button reqyires a pointer */ -#define BUTPOIN (FLO | SHO | CHA) +/* button requires a pointer */ +#define UI_BUT_POIN_TYPES (UI_BUT_POIN_FLOAT | UI_BUT_POIN_SHORT | UI_BUT_POIN_CHAR) /* assigned to but->type, OR'd with the flags above when passing args */ typedef enum { @@ -214,7 +215,7 @@ typedef enum { ICONROW = (12 << 9), ICONTOG = (13 << 9), NUMSLI = (14 << 9), - COL = (15 << 9), + COLOR = (15 << 9), IDPOIN = (16 << 9), HSVSLI = (17 << 9), SCROLL = (18 << 9), diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index a878632156f..c3f1080cecc 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -761,7 +761,7 @@ static void ui_menu_block_set_keyaccels(uiBlock *block) * fun first pass on all buttons so first word chars always get first priority */ for (but = block->buttons.first; but; but = but->next) { - if (!ELEM4(but->type, BUT, MENU, BLOCK, PULLDOWN) || (but->flag & UI_HIDDEN)) { + if (!ELEM5(but->type, BUT, BUTM, MENU, BLOCK, PULLDOWN) || (but->flag & UI_HIDDEN)) { /* pass */ } else if (but->menu_key == '\0') { @@ -1151,7 +1151,7 @@ static void ui_is_but_sel(uiBut *but, double *value) if (*value == (double)but->hardmax) is_push = 1; } break; - case COL: + case COLOR: is_push = 2; break; default: @@ -1311,13 +1311,13 @@ void ui_get_but_vectorf(uiBut *but, float vec[3]) vec[a] = RNA_property_float_get_index(&but->rnapoin, prop, a); } } - else if (but->pointype == CHA) { + else if (but->pointype == UI_BUT_POIN_CHAR) { char *cp = (char *)but->poin; vec[0] = ((float)cp[0]) / 255.0f; vec[1] = ((float)cp[1]) / 255.0f; vec[2] = ((float)cp[2]) / 255.0f; } - else if (but->pointype == FLO) { + else if (but->pointype == UI_BUT_POIN_FLOAT) { float *fp = (float *)but->poin; copy_v3_v3(vec, fp); } @@ -1357,13 +1357,13 @@ void ui_set_but_vectorf(uiBut *but, const float vec[3]) } } } - else if (but->pointype == CHA) { + else if (but->pointype == UI_BUT_POIN_CHAR) { char *cp = (char *)but->poin; cp[0] = (char)(0.5f + vec[0] * 255.0f); cp[1] = (char)(0.5f + vec[1] * 255.0f); cp[2] = (char)(0.5f + vec[2] * 255.0f); } - else if (but->pointype == FLO) { + else if (but->pointype == UI_BUT_POIN_FLOAT) { float *fp = (float *)but->poin; copy_v3_v3(fp, vec); } @@ -1371,7 +1371,7 @@ void ui_set_but_vectorf(uiBut *but, const float vec[3]) int ui_is_but_float(uiBut *but) { - if (but->pointype == FLO && but->poin) + if (but->pointype == UI_BUT_POIN_FLOAT && but->poin) return 1; if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_FLOAT) @@ -1467,16 +1467,16 @@ double ui_get_but_val(uiBut *but) case 'V': value = hsv[2]; break; } } - else if (but->pointype == CHA) { + else if (but->pointype == UI_BUT_POIN_CHAR) { value = *(char *)but->poin; } - else if (but->pointype == SHO) { + else if (but->pointype == UI_BUT_POIN_SHORT) { value = *(short *)but->poin; } - else if (but->pointype == INT) { + else if (but->pointype == UI_BUT_POIN_INT) { value = *(int *)but->poin; } - else if (but->pointype == FLO) { + else if (but->pointype == UI_BUT_POIN_FLOAT) { value = *(float *)but->poin; } @@ -1548,9 +1548,10 @@ void ui_set_but_val(uiBut *but, double value) } else { /* first do rounding */ - if (but->pointype == CHA) + if (but->pointype == UI_BUT_POIN_CHAR) { value = (char)floor(value + 0.5); - else if (but->pointype == SHO) { + } + else if (but->pointype == UI_BUT_POIN_SHORT) { /* gcc 3.2.1 seems to have problems * casting a double like 32772.0 to * a short so we cast to an int, then @@ -1564,9 +1565,9 @@ void ui_set_but_val(uiBut *but, double value) gcckludge = (int) floor(value + 0.5); value = (short)gcckludge; } - else if (but->pointype == INT) + else if (but->pointype == UI_BUT_POIN_INT) value = (int)floor(value + 0.5); - else if (but->pointype == FLO) { + else if (but->pointype == UI_BUT_POIN_FLOAT) { float fval = (float)value; if (fval >= -0.00001f && fval <= 0.00001f) fval = 0.0f; /* prevent negative zero */ value = fval; @@ -1575,13 +1576,13 @@ void ui_set_but_val(uiBut *but, double value) /* then set value with possible edit override */ if (but->editval) value = *but->editval = value; - else if (but->pointype == CHA) + else if (but->pointype == UI_BUT_POIN_CHAR) value = *((char *)but->poin) = (char)value; - else if (but->pointype == SHO) + else if (but->pointype == UI_BUT_POIN_SHORT) value = *((short *)but->poin) = (short)value; - else if (but->pointype == INT) + else if (but->pointype == UI_BUT_POIN_INT) value = *((int *)but->poin) = (int)value; - else if (but->pointype == FLO) + else if (but->pointype == UI_BUT_POIN_FLOAT) value = *((float *)but->poin) = (float)value; } @@ -2620,7 +2621,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str, uiBut *but; int slen; - if (type & BUTPOIN) { /* a pointer is required */ + if (type & UI_BUT_POIN_TYPES) { /* a pointer is required */ if (poin == NULL) return NULL; } @@ -2628,8 +2629,8 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str, but = MEM_callocN(sizeof(uiBut), "uiBut"); but->type = type & BUTTYPE; - but->pointype = type & BUTPOIN; - but->bit = type & BIT; + but->pointype = type & UI_BUT_POIN_TYPES; + but->bit = type & UI_BUT_POIN_BIT; but->bitnr = type & 31; but->icon = ICON_NONE; but->iconadd = 0; @@ -3102,40 +3103,40 @@ static uiBut *uiDefButBit(uiBlock *block, int type, int bit, int retval, const c return NULL; } else { - return uiDefBut(block, type | BIT | bitIdx, retval, str, x, y, width, height, poin, min, max, a1, a2, tip); + return uiDefBut(block, type | UI_BUT_POIN_BIT | bitIdx, retval, str, x, y, width, height, poin, min, max, a1, a2, tip); } } uiBut *uiDefButF(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefBut(block, type | FLO, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefBut(block, type | UI_BUT_POIN_FLOAT, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefButBitF(uiBlock *block, int type, int bit, int retval, const char *str, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefButBit(block, type | FLO, bit, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefButBit(block, type | UI_BUT_POIN_FLOAT, bit, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefButI(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefBut(block, type | INT, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefBut(block, type | UI_BUT_POIN_INT, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefButBitI(uiBlock *block, int type, int bit, int retval, const char *str, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefButBit(block, type | INT, bit, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefButBit(block, type | UI_BUT_POIN_INT, bit, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefButS(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefBut(block, type | SHO, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefBut(block, type | UI_BUT_POIN_SHORT, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefButBitS(uiBlock *block, int type, int bit, int retval, const char *str, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefButBit(block, type | SHO, bit, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefButBit(block, type | UI_BUT_POIN_SHORT, bit, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefButC(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefBut(block, type | CHA, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefBut(block, type | UI_BUT_POIN_CHAR, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefButBitC(uiBlock *block, int type, int bit, int retval, const char *str, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefButBit(block, type | CHA, bit, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefButBit(block, type | UI_BUT_POIN_CHAR, bit, retval, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefButR(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip) { @@ -3187,41 +3188,41 @@ static uiBut *uiDefIconButBit(uiBlock *block, int type, int bit, int retval, int return NULL; } else { - return uiDefIconBut(block, type | BIT | bitIdx, retval, icon, x, y, width, height, poin, min, max, a1, a2, tip); + return uiDefIconBut(block, type | UI_BUT_POIN_BIT | bitIdx, retval, icon, x, y, width, height, poin, min, max, a1, a2, tip); } } uiBut *uiDefIconButF(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefIconBut(block, type | FLO, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefIconBut(block, type | UI_BUT_POIN_FLOAT, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefIconButBitF(uiBlock *block, int type, int bit, int retval, int icon, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefIconButBit(block, type | FLO, bit, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefIconButBit(block, type | UI_BUT_POIN_FLOAT, bit, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefIconButI(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefIconBut(block, type | INT, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefIconBut(block, type | UI_BUT_POIN_INT, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefIconButBitI(uiBlock *block, int type, int bit, int retval, int icon, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefIconButBit(block, type | INT, bit, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefIconButBit(block, type | UI_BUT_POIN_INT, bit, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefIconButS(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefIconBut(block, type | SHO, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefIconBut(block, type | UI_BUT_POIN_SHORT, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefIconButBitS(uiBlock *block, int type, int bit, int retval, int icon, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefIconButBit(block, type | SHO, bit, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefIconButBit(block, type | UI_BUT_POIN_SHORT, bit, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefIconButC(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefIconBut(block, type | CHA, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefIconBut(block, type | UI_BUT_POIN_CHAR, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefIconButBitC(uiBlock *block, int type, int bit, int retval, int icon, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefIconButBit(block, type | CHA, bit, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefIconButBit(block, type | UI_BUT_POIN_CHAR, bit, retval, icon, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefIconButR(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip) { @@ -3266,41 +3267,41 @@ static uiBut *uiDefIconTextButBit(uiBlock *block, int type, int bit, int retval, return NULL; } else { - return uiDefIconTextBut(block, type | BIT | bitIdx, retval, icon, str, x, y, width, height, poin, min, max, a1, a2, tip); + return uiDefIconTextBut(block, type | UI_BUT_POIN_BIT | bitIdx, retval, icon, str, x, y, width, height, poin, min, max, a1, a2, tip); } } uiBut *uiDefIconTextButF(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefIconTextBut(block, type | FLO, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefIconTextBut(block, type | UI_BUT_POIN_FLOAT, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefIconTextButBitF(uiBlock *block, int type, int bit, int retval, int icon, const char *str, int x, int y, short width, short height, float *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefIconTextButBit(block, type | FLO, bit, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefIconTextButBit(block, type | UI_BUT_POIN_FLOAT, bit, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefIconTextButI(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefIconTextBut(block, type | INT, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefIconTextBut(block, type | UI_BUT_POIN_INT, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefIconTextButBitI(uiBlock *block, int type, int bit, int retval, int icon, const char *str, int x, int y, short width, short height, int *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefIconTextButBit(block, type | INT, bit, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefIconTextButBit(block, type | UI_BUT_POIN_INT, bit, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefIconTextButS(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefIconTextBut(block, type | SHO, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefIconTextBut(block, type | UI_BUT_POIN_SHORT, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefIconTextButBitS(uiBlock *block, int type, int bit, int retval, int icon, const char *str, int x, int y, short width, short height, short *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefIconTextButBit(block, type | SHO, bit, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefIconTextButBit(block, type | UI_BUT_POIN_SHORT, bit, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefIconTextButC(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefIconTextBut(block, type | CHA, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefIconTextBut(block, type | UI_BUT_POIN_CHAR, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefIconTextButBitC(uiBlock *block, int type, int bit, int retval, int icon, const char *str, int x, int y, short width, short height, char *poin, float min, float max, float a1, float a2, const char *tip) { - return uiDefIconTextButBit(block, type | CHA, bit, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); + return uiDefIconTextButBit(block, type | UI_BUT_POIN_CHAR, bit, retval, icon, str, x, y, width, height, (void *) poin, min, max, a1, a2, tip); } uiBut *uiDefIconTextButR(uiBlock *block, int type, int retval, int icon, const char *str, int x, int y, short width, short height, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip) { @@ -3698,7 +3699,7 @@ uiBut *uiDefIconBlockBut(uiBlock *block, uiBlockCreateFunc func, void *arg, int uiBut *uiDefKeyevtButS(uiBlock *block, int retval, const char *str, int x, int y, short width, short height, short *spoin, const char *tip) { - uiBut *but = ui_def_but(block, KEYEVT | SHO, retval, str, x, y, width, height, spoin, 0.0, 0.0, 0.0, 0.0, tip); + uiBut *but = ui_def_but(block, KEYEVT | UI_BUT_POIN_SHORT, retval, str, x, y, width, height, spoin, 0.0, 0.0, 0.0, 0.0, tip); ui_check_but(but); return but; } @@ -3707,7 +3708,7 @@ uiBut *uiDefKeyevtButS(uiBlock *block, int retval, const char *str, int x, int y /* modkeypoin will be set to KM_SHIFT, KM_ALT, KM_CTRL, KM_OSKEY bits */ uiBut *uiDefHotKeyevtButS(uiBlock *block, int retval, const char *str, int x, int y, short width, short height, short *keypoin, short *modkeypoin, const char *tip) { - uiBut *but = ui_def_but(block, HOTKEYEVT | SHO, retval, str, x, y, width, height, keypoin, 0.0, 0.0, 0.0, 0.0, tip); + uiBut *but = ui_def_but(block, HOTKEYEVT | UI_BUT_POIN_SHORT, retval, str, x, y, width, height, keypoin, 0.0, 0.0, 0.0, 0.0, tip); but->modifier_key = *modkeypoin; ui_check_but(but); return but; diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index b47dc661e50..f7b22098835 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -494,10 +494,12 @@ static void ui_apply_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data) /* local hack... */ if (but->type == BUT_TOGDUAL && data->togdual) { - if (but->pointype == SHO) + if (but->pointype == UI_BUT_POIN_SHORT) { but->poin += 2; - else if (but->pointype == INT) + } + else if (but->pointype == UI_BUT_POIN_INT) { but->poin += 4; + } } value = ui_get_but_val(but); @@ -534,10 +536,12 @@ static void ui_apply_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data) /* end local hack... */ if (but->type == BUT_TOGDUAL && data->togdual) { - if (but->pointype == SHO) + if (but->pointype == UI_BUT_POIN_SHORT) { but->poin -= 2; - else if (but->pointype == INT) + } + else if (but->pointype == UI_BUT_POIN_INT) { but->poin -= 4; + } } ui_apply_but_func(C, but); @@ -605,7 +609,7 @@ static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data) static void ui_apply_but_TOG3(bContext *C, uiBut *but, uiHandleButtonData *data) { - if (but->pointype == SHO) { + if (but->pointype == UI_BUT_POIN_SHORT) { short *sp = (short *)but->poin; if (UI_BITBUT_TEST(sp[1], but->bitnr)) { @@ -1049,7 +1053,7 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut case PULLDOWN: ui_apply_but_BLOCK(C, but, data); break; - case COL: + case COLOR: if (data->cancel) ui_apply_but_VEC(C, but, data); else @@ -1180,7 +1184,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, } /* RGB triple */ - else if (but->type == COL) { + else if (but->type == COLOR) { float rgb[3]; if (but->poin == NULL && but->rnapoin.data == NULL) ; @@ -2092,12 +2096,12 @@ static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data menufunc = ui_block_func_ICONTEXTROW; arg = but; break; - case COL: + case COLOR: ui_get_but_vectorf(but, data->origvec); copy_v3_v3(data->vec, data->origvec); but->editvec = data->vec; - handlefunc = ui_block_func_COL; + handlefunc = ui_block_func_COLOR; arg = but; break; @@ -3001,7 +3005,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, wm return WM_UI_HANDLER_BREAK; } } - else if (but->type == COL) { + else if (but->type == COLOR) { if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) { float *hsv = ui_block_hsv_get(but->block); float col[3]; @@ -4914,7 +4918,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) case BUTM: retval = ui_do_but_BUT(C, but, data, event); break; - case COL: + case COLOR: if (but->a1 == UI_GRAD_V_ALT) /* signal to prevent calling up color picker */ retval = ui_do_but_EXIT(C, but, data, event); else @@ -5880,7 +5884,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) } } - if (but->type != COL) { /* exception */ + if (but->type != COLOR) { /* exception */ data->cancel = TRUE; } button_activate_state(C, but, BUTTON_STATE_EXIT); @@ -5990,7 +5994,7 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut * /* copy over return values from the closing menu */ if ((menu->menuretval & UI_RETURN_OK) || (menu->menuretval & UI_RETURN_UPDATE)) { - if (but->type == COL) + if (but->type == COLOR) copy_v3_v3(data->vec, menu->retvec); else if (ELEM3(but->type, MENU, ICONROW, ICONTEXTROW)) data->value = menu->retvalue; @@ -6420,7 +6424,7 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle for (but = block->buttons.first; but; but = but->next) { if (but->menu_key == event->type) { - if (but->type == BUT) { + if (ELEM(but->type, BUT, BUTM)) { /* mainly for operator buttons */ ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_APPLY); } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 6999f8e2325..928e1671cee 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -94,8 +94,7 @@ typedef enum { UI_WTYPE_BOX, UI_WTYPE_SCROLL, UI_WTYPE_LISTITEM, - UI_WTYPE_PROGRESSBAR, - + UI_WTYPE_PROGRESSBAR } uiWidgetTypeEnum; /* panel limits */ @@ -133,7 +132,7 @@ typedef enum { /* bit button defines */ /* Bit operations */ -#define UI_BITBUT_TEST(a, b) ( ( (a) & 1 << (b) ) != 0) +#define UI_BITBUT_TEST(a, b) ( ( (a) & 1 << (b) ) != 0) #define UI_BITBUT_SET(a, b) ( (a) | 1 << (b) ) #define UI_BITBUT_CLR(a, b) ( (a) & ~(1 << (b)) ) /* bit-row */ @@ -159,8 +158,9 @@ typedef struct { struct uiBut { struct uiBut *next, *prev; int flag, drawflag; - eButType type; - short pointype, bit, bitnr, retval, strwidth, ofs, pos, selsta, selend, alignnr; + eButType type; + eButPointerType pointype; + short bit, bitnr, retval, strwidth, ofs, pos, selsta, selend, alignnr; char *str; char strdata[UI_MAX_NAME_STR]; @@ -430,7 +430,7 @@ struct uiPopupBlockHandle { float retvec[4]; }; -uiBlock *ui_block_func_COL(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but); +uiBlock *ui_block_func_COLOR(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but); void ui_block_func_ICONROW(struct bContext *C, uiLayout *layout, void *arg_but); void ui_block_func_ICONTEXTROW(struct bContext *C, uiLayout *layout, void *arg_but); diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index ea0838cf7df..2e88e3083a4 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -1808,11 +1808,11 @@ static void ui_block_func_MENUSTR(bContext *UNUSED(C), uiLayout *layout, void *a bt->flag = UI_TEXT_LEFT; } else if (entry->icon) { - uiDefIconTextButF(block, BUTM | FLO, B_NOP, entry->icon, entry->str, 0, 0, + uiDefIconTextButF(block, BUTM, B_NOP, entry->icon, entry->str, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, &handle->retvalue, (float) entry->retval, 0.0, 0, 0, ""); } else { - uiDefButF(block, BUTM | FLO, B_NOP, entry->str, 0, 0, + uiDefButF(block, BUTM, B_NOP, entry->str, 0, 0, UI_UNIT_X * 5, UI_UNIT_X, &handle->retvalue, (float) entry->retval, 0.0, 0, 0, ""); } } @@ -1830,7 +1830,7 @@ void ui_block_func_ICONROW(bContext *UNUSED(C), uiLayout *layout, void *arg_but) uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT); for (a = (int)but->hardmin; a <= (int)but->hardmax; a++) - uiDefIconButF(block, BUTM | FLO, B_NOP, but->icon + (a - but->hardmin), 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, + uiDefIconButF(block, BUTM, B_NOP, but->icon + (a - but->hardmin), 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, &handle->retvalue, (float)a, 0.0, 0, 0, ""); } @@ -1860,7 +1860,7 @@ void ui_block_func_ICONTEXTROW(bContext *UNUSED(C), uiLayout *layout, void *arg_ if (entry->sepr) uiItemS(layout); else - uiDefIconTextButF(block, BUTM | FLO, B_NOP, (short)((but->icon) + (entry->retval - but->hardmin)), entry->str, + uiDefIconTextButF(block, BUTM, B_NOP, (short)((but->icon) + (entry->retval - but->hardmin)), entry->str, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, &handle->retvalue, (float) entry->retval, 0.0, 0, 0, ""); } @@ -2244,7 +2244,7 @@ static int ui_picker_small_wheel_cb(const bContext *UNUSED(C), uiBlock *block, w return 0; } -uiBlock *ui_block_func_COL(bContext *C, uiPopupBlockHandle *handle, void *arg_but) +uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_but) { uiBut *but = arg_but; uiBlock *block; diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index faaf09e83b6..d363609fbd9 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -78,7 +78,7 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind if (arraylen && index == -1) { if (ELEM(RNA_property_subtype(prop), PROP_COLOR, PROP_COLOR_GAMMA)) - but = uiDefButR_prop(block, COL, 0, name, x1, y1, x2, y2, ptr, prop, 0, 0, 0, -1, -1, NULL); + but = uiDefButR_prop(block, COLOR, 0, name, x1, y1, x2, y2, ptr, prop, 0, 0, 0, -1, -1, NULL); } else if (RNA_property_subtype(prop) == PROP_PERCENTAGE || RNA_property_subtype(prop) == PROP_FACTOR) but = uiDefButR_prop(block, NUMSLI, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index ee22393c08f..8a7f2d9ca47 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1255,10 +1255,12 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB if (but->type == BUT_TOGDUAL) { int dualset = 0; - if (but->pointype == SHO) + if (but->pointype == UI_BUT_POIN_SHORT) { dualset = UI_BITBUT_TEST(*(((short *)but->poin) + 1), but->bitnr); - else if (but->pointype == INT) + } + else if (but->pointype == UI_BUT_POIN_INT) { dualset = UI_BITBUT_TEST(*(((int *)but->poin) + 1), but->bitnr); + } widget_draw_icon(but, ICON_DOT, dualset ? 1.0f : 0.25f, rect); } @@ -3158,7 +3160,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct wt = widget_type(UI_WTYPE_MENU_ITEM); break; - case COL: + case COLOR: wt = widget_type(UI_WTYPE_SWATCH); break; diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index b37f758596b..7fe1ac09df6 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -556,6 +556,7 @@ static int add_vertex_new(const bContext *C, Mask *mask, MaskLayer *masklay, con static int add_vertex_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; @@ -595,7 +596,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op) BKE_mask_calc_handle_point_auto(spline, point_other, FALSE); /* TODO: only update this spline */ - BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); + BKE_mask_update_display(mask, CFRA); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); return OPERATOR_FINISHED; @@ -617,7 +618,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op) } /* TODO: only update this spline */ - BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); + BKE_mask_update_display(mask, CFRA); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 00bbfcf3188..655458bd4cb 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -496,7 +496,8 @@ void ED_mask_draw(const bContext *C, * width, height are to match the values from ED_mask_get_size() */ void ED_mask_draw_region(Mask *mask, ARegion *ar, const char draw_flag, const char draw_type, - int width, int height, + const int width_i, const int height_i, /* convert directly into aspect corrected vars */ + const float aspx, const float aspy, const short do_scale_applied, const short do_post_draw, float stabmat[4][4], /* optional - only used by clip */ const bContext *C /* optional - only used when do_post_draw is set */ @@ -504,6 +505,9 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar, { struct View2D *v2d = &ar->v2d; + /* aspect always scales vertically in movie and image spaces */ + const float width = width_i, height = (float)height_i * (aspy / aspx); + int x, y; /* int w, h; */ float zoomx, zoomy; diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index 85a8ae11111..39a19bdaa5f 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -109,11 +109,9 @@ void ED_mask_mouse_pos(ScrArea *sa, ARegion *ar, const int mval[2], float co[2]) } case SPACE_IMAGE: { - float frame_size[2]; SpaceImage *sima = sa->spacedata.first; - ED_space_image_get_size_fl(sima, frame_size); ED_image_mouse_pos(sima, ar, mval, co); - BKE_mask_coord_from_frame(co, co, frame_size); + BKE_mask_coord_from_image(sima->image, &sima->iuser, co, co); break; } default: @@ -149,11 +147,9 @@ void ED_mask_point_pos(ScrArea *sa, ARegion *ar, float x, float y, float *xr, fl break; case SPACE_IMAGE: { - float frame_size[2]; SpaceImage *sima = sa->spacedata.first; - ED_space_image_get_size_fl(sima, frame_size); ED_image_point_pos(sima, ar, x, y, &co[0], &co[1]); - BKE_mask_coord_from_frame(co, co, frame_size); + BKE_mask_coord_from_image(sima->image, &sima->iuser, co, co); break; } default: @@ -192,13 +188,10 @@ void ED_mask_point_pos__reverse(ScrArea *sa, ARegion *ar, float x, float y, floa break; case SPACE_IMAGE: { - float frame_size[2]; SpaceImage *sima = sa->spacedata.first; - ED_space_image_get_size_fl(sima, frame_size); - co[0] = x; co[1] = y; - BKE_mask_coord_to_frame(co, co, frame_size); + BKE_mask_coord_to_image(sima->image, &sima->iuser, co, co); ED_image_point_pos__reverse(sima, ar, co, co); break; } diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 1df1e5a66fe..88fbb91edfb 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -915,6 +915,7 @@ static void delete_feather_points(MaskSplinePoint *point) static int delete_exec(bContext *C, wmOperator *UNUSED(op)) { + Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; @@ -1002,7 +1003,7 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) } /* TODO: only update edited splines */ - BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); + BKE_mask_update_display(mask, CFRA); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); @@ -1060,7 +1061,7 @@ static int mask_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) if (change) { /* TODO: only update this spline */ - BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); + BKE_mask_update_display(mask, CFRA); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); @@ -1126,7 +1127,7 @@ static int mask_normals_make_consistent_exec(bContext *C, wmOperator *UNUSED(op) if (change) { /* TODO: only update this spline */ - BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); + BKE_mask_update_display(mask, CFRA); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); @@ -1324,6 +1325,7 @@ void MASK_OT_hide_view_set(wmOperatorType *ot) static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op)) { + Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; int changed = FALSE; @@ -1351,7 +1353,7 @@ static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op)) if (changed) { /* TODO: only update edited splines */ - BKE_mask_update_display(mask, CTX_data_scene(C)->r.cfra); + BKE_mask_update_display(mask, CFRA); WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask); DAG_id_tag_update(&mask->id, 0); diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index f9b01a56b95..f03cb312e3e 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -1352,6 +1352,8 @@ static void init_bake_internal(BakeRender *bkr, bContext *C) static void finish_bake_internal(BakeRender *bkr) { + Image *ima; + RE_Database_Free(bkr->re); /* restore raytrace and AO */ @@ -1363,27 +1365,30 @@ static void finish_bake_internal(BakeRender *bkr) if (bkr->prev_r_raytrace == 0) bkr->scene->r.mode &= ~R_RAYTRACE; - if (bkr->result == BAKE_RESULT_OK) { - Image *ima; - /* force OpenGL reload and mipmap recalc */ - for (ima = G.main->image.first; ima; ima = ima->id.next) { + + /* force OpenGL reload and mipmap recalc */ + for (ima = G.main->image.first; ima; ima = ima->id.next) { + ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + + if (bkr->result == BAKE_RESULT_OK) { if (ima->ok == IMA_OK_LOADED) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); if (ibuf) { if (ibuf->userflags & IB_BITMAPDIRTY) { ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; GPU_free_image(ima); imb_freemipmapImBuf(ibuf); } - - /* freed when baking is done, but if its canceled we need to free here */ - if (ibuf->userdata) { - MEM_freeN(ibuf->userdata); - ibuf->userdata = NULL; - } } } } + + /* freed when baking is done, but if its canceled we need to free here */ + if (ibuf) { + if (ibuf->userdata) { + MEM_freeN(ibuf->userdata); + ibuf->userdata = NULL; + } + } } } diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 2b1492aa732..4858fdf1c35 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -1658,7 +1658,7 @@ static int skin_radii_equalize_exec(bContext *C, wmOperator *UNUSED(op)) void OBJECT_OT_skin_radii_equalize(wmOperatorType *ot) { ot->name = "Skin Radii Equalize"; - ot->description = "Make skin radii of selected vertices equal"; + ot->description = "Make skin radii of selected vertices equal on each axis"; ot->idname = "OBJECT_OT_skin_radii_equalize"; ot->poll = skin_edit_poll; diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index c730712deb2..0225758de48 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -158,7 +158,7 @@ void ED_space_clip_get_aspect(SpaceClip *sc, float *aspx, float *aspy) MovieClip *clip = ED_space_clip_get_clip(sc); if (clip) - BKE_movieclip_aspect(clip, aspx, aspy); + BKE_movieclip_get_aspect(clip, aspx, aspy); else *aspx = *aspy = 1.0f; diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index bb06104d442..7f43c404095 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -1131,10 +1131,13 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar) if (mask) { ScrArea *sa = CTX_wm_area(C); int width, height; + float aspx, aspy; ED_mask_get_size(sa, &width, &height); + ED_space_clip_get_aspect(sc, &aspx, &aspy); ED_mask_draw_region(mask, ar, sc->mask_info.draw_flag, sc->mask_info.draw_type, width, height, + aspx, aspy, TRUE, TRUE, sc->stabmat, C); } diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 878858c1acd..040f276940d 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -156,7 +156,7 @@ static FileSelection file_selection_get(bContext *C, const rcti *rect, short fil return sel; } -static FileSelect file_select_do(bContext *C, int selected_idx) +static FileSelect file_select_do(bContext *C, int selected_idx, short do_diropen) { FileSelect retval = FILE_SELECT_NOTHING; SpaceFile *sfile = CTX_wm_space_file(C); @@ -172,8 +172,12 @@ static FileSelect file_select_do(bContext *C, int selected_idx) params->active_file = selected_idx; if (S_ISDIR(file->type)) { + if (do_diropen == FALSE) { + params->file[0] = '\0'; + retval = FILE_SELECT_DIR; + } /* the path is too long and we are not going up! */ - if (strcmp(file->relname, "..") && strlen(params->dir) + strlen(file->relname) >= FILE_MAX) { + else if (strcmp(file->relname, "..") && strlen(params->dir) + strlen(file->relname) >= FILE_MAX) { // XXX error("Path too long, cannot enter this directory"); } else { @@ -202,7 +206,7 @@ static FileSelect file_select_do(bContext *C, int selected_idx) } -static FileSelect file_select(bContext *C, const rcti *rect, FileSelType select, short fill) +static FileSelect file_select(bContext *C, const rcti *rect, FileSelType select, short fill, short do_diropen) { SpaceFile *sfile = CTX_wm_space_file(C); FileSelect retval = FILE_SELECT_NOTHING; @@ -219,7 +223,7 @@ static FileSelect file_select(bContext *C, const rcti *rect, FileSelType select, if ((sel.last >= 0) && ((select == FILE_SEL_ADD) || (select == FILE_SEL_TOGGLE))) { /* Check last selection, if selected, act on the file or dir */ if (filelist_is_selected(sfile->files, sel.last, check_type)) { - retval = file_select_do(C, sel.last); + retval = file_select_do(C, sel.last, do_diropen); } } @@ -284,7 +288,7 @@ static int file_border_select_exec(bContext *C, wmOperator *op) BLI_rcti_isect(&(ar->v2d.mask), &rect, &rect); - ret = file_select(C, &rect, select ? FILE_SEL_ADD : FILE_SEL_REMOVE, 0); + ret = file_select(C, &rect, select ? FILE_SEL_ADD : FILE_SEL_REMOVE, FALSE, FALSE); if (FILE_SELECT_DIR == ret) { WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); } @@ -320,6 +324,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, wmEvent *event) rcti rect; int extend = RNA_boolean_get(op->ptr, "extend"); int fill = RNA_boolean_get(op->ptr, "fill"); + int do_diropen = RNA_boolean_get(op->ptr, "open"); if (ar->regiontype != RGN_TYPE_WINDOW) return OPERATOR_CANCELLED; @@ -333,7 +338,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, wmEvent *event) /* single select, deselect all selected first */ if (!extend) file_deselect_all(sfile, SELECTED_FILE); - ret = file_select(C, &rect, extend ? FILE_SEL_TOGGLE : FILE_SEL_ADD, fill); + ret = file_select(C, &rect, extend ? FILE_SEL_TOGGLE : FILE_SEL_ADD, fill, do_diropen); if (FILE_SELECT_DIR == ret) WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); else if (FILE_SELECT_FILE == ret) @@ -357,8 +362,9 @@ void FILE_OT_select(wmOperatorType *ot) ot->poll = ED_operator_file_active; /* rna */ - RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first"); - RNA_def_boolean(ot->srna, "fill", 0, "Fill", "Select everything beginning with the last selection"); + RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first"); + RNA_def_boolean(ot->srna, "fill", FALSE, "Fill", "Select everything beginning with the last selection"); + RNA_def_boolean(ot->srna, "open", TRUE, "Open", "Open a directory when selecting it"); } static int file_select_all_exec(bContext *C, wmOperator *UNUSED(op)) diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index fcf6f28b406..4b568b43695 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -284,8 +284,6 @@ static void file_main_area_init(wmWindowManager *wm, ARegion *ar) keymap = WM_keymap_find(wm->defaultconf, "File Browser Main", SPACE_FILE, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); - - } static void file_main_area_listener(ARegion *ar, wmNotifier *wmn) @@ -418,12 +416,26 @@ static void file_keymap(struct wmKeyConfig *keyconf) keymap = WM_keymap_find(keyconf, "File Browser Main", SPACE_FILE, 0); kmi = WM_keymap_add_item(keymap, "FILE_OT_execute", LEFTMOUSE, KM_DBL_CLICK, 0, 0); RNA_boolean_set(kmi->ptr, "need_active", TRUE); + + /* left mouse selects and opens */ WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, 0, 0); kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "extend", TRUE); kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "extend", TRUE); RNA_boolean_set(kmi->ptr, "fill", TRUE); + + /* right mouse selects without opening */ + kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_CLICK, 0, 0); + RNA_boolean_set(kmi->ptr, "open", FALSE); + kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_CLICK, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "extend", TRUE); + RNA_boolean_set(kmi->ptr, "open", FALSE); + kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_CLICK, KM_ALT, 0); + RNA_boolean_set(kmi->ptr, "extend", TRUE); + RNA_boolean_set(kmi->ptr, "fill", TRUE); + RNA_boolean_set(kmi->ptr, "open", FALSE); + WM_keymap_add_item(keymap, "FILE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "FILE_OT_refresh", PADPERIOD, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "FILE_OT_select_border", BKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index ac9883b411d..360cbc3f026 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -143,27 +143,6 @@ int ED_space_image_has_buffer(SpaceImage *sima) return has_buffer; } -void ED_image_get_size(Image *ima, int *width, int *height) -{ - ImBuf *ibuf = NULL; - void *lock; - - if (ima) - ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); - - if (ibuf && ibuf->x > 0 && ibuf->y > 0) { - *width = ibuf->x; - *height = ibuf->y; - } - else { - *width = IMG_SIZE_FALLBACK; - *height = IMG_SIZE_FALLBACK; - } - - if (ima) - BKE_image_release_ibuf(ima, lock); -} - void ED_space_image_get_size(SpaceImage *sima, int *width, int *height) { Scene *scene = sima->iuser.scene; @@ -205,23 +184,18 @@ void ED_space_image_get_size_fl(SpaceImage *sima, float size[2]) size[1] = size_i[1]; } -void ED_image_get_aspect(Image *ima, float *aspx, float *aspy) -{ - *aspx = *aspy = 1.0; - - if ((ima == NULL) || (ima->type == IMA_TYPE_R_RESULT) || (ima->type == IMA_TYPE_COMPOSITE) || - (ima->aspx == 0.0f || ima->aspy == 0.0f)) - { - return; - } - - /* x is always 1 */ - *aspy = ima->aspy / ima->aspx; -} void ED_space_image_get_aspect(SpaceImage *sima, float *aspx, float *aspy) { - ED_image_get_aspect(ED_space_image(sima), aspx, aspy); + Image *ima = sima->image; + if ((ima == NULL) || (ima->type == IMA_TYPE_R_RESULT) || (ima->type == IMA_TYPE_COMPOSITE) || + (ima->aspx == 0.0f || ima->aspy == 0.0f)) + { + *aspx = *aspy = 1.0; + } + else { + BKE_image_get_aspect(ima, aspx, aspy); + } } void ED_space_image_get_zoom(SpaceImage *sima, ARegion *ar, float *zoomx, float *zoomy) @@ -254,12 +228,12 @@ void ED_space_image_get_uv_aspect(SpaceImage *sima, float *aspx, float *aspy) } } -void ED_image_get_uv_aspect(Image *ima, float *aspx, float *aspy) +void ED_image_get_uv_aspect(Image *ima, ImageUser *iuser, float *aspx, float *aspy) { int w, h; - ED_image_get_aspect(ima, aspx, aspy); - ED_image_get_size(ima, &w, &h); + BKE_image_get_aspect(ima, aspx, aspy); + BKE_image_get_size(ima, iuser, &w, &h); *aspx *= (float)w; *aspy *= (float)h; diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 6ec852b703c..857d0179158 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -633,7 +633,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) ima = ED_space_image(sima); ED_space_image_get_size(sima, &width, &height); - ED_image_get_aspect(ima, &aspx, &aspy); + ED_space_image_get_aspect(sima, &aspx, &aspy); width = width * aspx; height = height * aspy; diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index d9b92579324..5b288bd6149 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -679,10 +679,13 @@ static void image_main_area_draw(const bContext *C, ARegion *ar) if (mask) { int width, height; + float aspx, aspy; ED_space_image_get_size(sima, &width, &height); + ED_space_image_get_aspect(sima, &aspx, &aspy); ED_mask_draw_region(mask, ar, sima->mask_info.draw_flag, sima->mask_info.draw_type, width, height, + aspx, aspy, TRUE, FALSE, NULL, C); diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index a042145309d..6ffac1dcd34 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -2162,7 +2162,7 @@ static short draw_actuatorbuttons(Main *bmain, Object *ob, bActuator *act, uiBlo 0.0, 1.0, 0, 0, "Sets the volume of this sound"); uiDefButF(block, NUM, 0, "Pitch:", xco+wval+10, yco-66, wval, 19, &sa->pitch, -12.0, 12.0, 0, 0, "Sets the pitch of this sound"); - uiDefButS(block, TOG | BIT, 0, "3D Sound", xco+10, yco-88, width-20, 19, + uiDefButS(block, TOG | UI_BUT_POIN_BIT, 0, "3D Sound", xco+10, yco-88, width-20, 19, &sa->flag, 0.0, 1.0, 0.0, 0.0, "Plays the sound positioned in 3D space"); if (sa->flag & ACT_SND_3D_SOUND) { uiDefButF(block, NUM, 0, "Minimum Gain: ", xco+10, yco-110, wval, 19, @@ -3398,7 +3398,13 @@ static void draw_sensor_message(uiLayout *layout, PointerRNA *ptr) static void draw_sensor_mouse(uiLayout *layout, PointerRNA *ptr) { - uiItemR(layout, ptr, "mouse_event", 0, NULL, ICON_NONE); + uiLayout *split; + + split = uiLayoutSplit(layout, 0.8f, FALSE); + uiItemR(split, ptr, "mouse_event", 0, NULL, ICON_NONE); + + if (RNA_enum_get(ptr, "mouse_event") == BL_SENS_MOUSE_MOUSEOVER_ANY) + uiItemR(split, ptr, "use_pulse", UI_ITEM_R_TOGGLE, NULL, ICON_NONE); } static void draw_sensor_near(uiLayout *layout, PointerRNA *ptr) diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index d84a641e3aa..91c91f5089f 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -172,7 +172,7 @@ static void node_socket_button_color(const bContext *C, uiBlock *block, int labelw = width - 40; RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr); - bt = uiDefButR(block, COL, B_NODE_EXEC, "", + bt = uiDefButR(block, COLOR, B_NODE_EXEC, "", x, y + 2, (labelw > 0 ? 40 : width), NODE_DY - 2, &ptr, "default_value", 0, 0, 0, -1, -1, NULL); if (node) diff --git a/source/blender/editors/space_node/node_header.c b/source/blender/editors/space_node/node_header.c index f461174d74f..e17961b6c7c 100644 --- a/source/blender/editors/space_node/node_header.c +++ b/source/blender/editors/space_node/node_header.c @@ -41,6 +41,7 @@ #include "BLF_translation.h" +#include "BKE_blender.h" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_main.h" @@ -64,7 +65,7 @@ static void do_node_add(bContext *C, bNodeTemplate *ntemp) SpaceNode *snode = CTX_wm_space_node(C); ScrArea *sa = CTX_wm_area(C); ARegion *ar; - bNode *node; + bNode *node, *node_new; /* get location to add node at mouse */ for (ar = sa->regionbase.first; ar; ar = ar->next) { @@ -84,7 +85,7 @@ static void do_node_add(bContext *C, bNodeTemplate *ntemp) else node->flag &= ~NODE_TEST; } - /* node= */ node_add_node(snode, bmain, scene, ntemp, snode->cursor[0], snode->cursor[1]); + node_new = node_add_node(snode, bmain, scene, ntemp, snode->cursor[0], snode->cursor[1]); /* select previous selection before autoconnect */ for (node = snode->edittree->nodes.first; node; node = node->next) { @@ -95,7 +96,14 @@ static void do_node_add(bContext *C, bNodeTemplate *ntemp) for (node = snode->edittree->nodes.first; node; node = node->next) { if (node->flag & NODE_TEST) node->flag &= ~NODE_SELECT; } - + + /* once this is called from an operator, this should be removed */ + if (node_new) { + char undostr[BKE_UNDO_STR_MAX]; + BLI_snprintf(undostr, sizeof(BKE_UNDO_STR_MAX), "Add Node %s", nodeLabel(node_new)); + BKE_write_undo(C, undostr); + } + snode_notify(C, snode); snode_dag_update(C, snode); } diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 7c5a1cca756..7363bf2fbd8 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1126,6 +1126,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq if (mask) { int width, height; + float aspx = 1.0f, aspy = 1.0f; // ED_mask_get_size(C, &width, &height); //Scene *scene = CTX_data_scene(C); @@ -1135,6 +1136,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq ED_mask_draw_region(mask, ar, 0, 0, /* TODO */ width, height, + aspx, aspy, FALSE, TRUE, NULL, C); } diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 08c4cff332f..f47eb339878 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -1141,12 +1141,16 @@ static int sequencer_mute_exec(bContext *C, wmOperator *op) for (seq = ed->seqbasep->first; seq; seq = seq->next) { if ((seq->flag & SEQ_LOCK) == 0) { if (selected) { /* mute unselected */ - if (seq->flag & SELECT) + if (seq->flag & SELECT) { seq->flag |= SEQ_MUTE; + BKE_sequence_invalidate_deendent(scene, seq); + } } else { - if ((seq->flag & SELECT) == 0) + if ((seq->flag & SELECT) == 0) { seq->flag |= SEQ_MUTE; + BKE_sequence_invalidate_deendent(scene, seq); + } } } } @@ -1188,12 +1192,16 @@ static int sequencer_unmute_exec(bContext *C, wmOperator *op) for (seq = ed->seqbasep->first; seq; seq = seq->next) { if ((seq->flag & SEQ_LOCK) == 0) { if (selected) { /* unmute unselected */ - if (seq->flag & SELECT) + if (seq->flag & SELECT) { seq->flag &= ~SEQ_MUTE; + BKE_sequence_invalidate_deendent(scene, seq); + } } else { - if ((seq->flag & SELECT) == 0) + if ((seq->flag & SELECT) == 0) { seq->flag &= ~SEQ_MUTE; + BKE_sequence_invalidate_deendent(scene, seq); + } } } } diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 23af0d6f8d6..a3fb4e851e2 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -65,6 +65,7 @@ #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_unit.h" +#include "BKE_mask.h" #include "ED_image.h" #include "ED_keyframing.h" @@ -228,9 +229,27 @@ void projectIntView(TransInfo *t, const float vec[3], int adr[2]) project_int_noclip(t->ar, vec, adr); } else if (t->spacetype == SPACE_IMAGE) { + SpaceImage *sima = t->sa->spacedata.first; + if (t->options & CTX_MASK) { + /* not working quite right, TODO (see below too) */ + float aspx, aspy; float v[2]; - ED_mask_point_pos__reverse(t->sa, t->ar, vec[0], vec[1], &v[0], &v[1]); + + ED_space_image_get_aspect(sima, &aspx, &aspy); + + copy_v2_v2(v, vec); + + v[0] = v[0] / aspx; + v[1] = v[1] / aspy; + + BKE_mask_coord_to_image(sima->image, &sima->iuser, v, v); + + v[0] = v[0] / aspx; + v[1] = v[1] / aspy; + + ED_image_point_pos__reverse(sima, t->ar, v, v); + adr[0] = v[0]; adr[1] = v[1]; } @@ -278,23 +297,41 @@ void projectIntView(TransInfo *t, const float vec[3], int adr[2]) adr[1] = out[1]; } else if (t->spacetype == SPACE_CLIP) { - float v[2]; - float aspx = 1.0f, aspy = 1.0f; + SpaceClip *sc = t->sa->spacedata.first; - copy_v2_v2(v, vec); + if (t->options & CTX_MASK) { + /* not working quite right, TODO (see above too) */ + float aspx, aspy; + float v[2]; - if (t->options & CTX_MOVIECLIP) { + ED_space_clip_get_aspect(sc, &aspx, &aspy); + + copy_v2_v2(v, vec); + + v[0] = v[0] / aspx; + v[1] = v[1] / aspy; + + BKE_mask_coord_to_movieclip(sc->clip, &sc->user, v, v); + + v[0] = v[0] / aspx; + v[1] = v[1] / aspy; + + ED_clip_point_stable_pos__reverse(sc, t->ar, v, v); + + adr[0] = v[0]; + adr[1] = v[1]; + } + else if (t->options & CTX_MOVIECLIP) { + float v[2], aspx, aspy; + + copy_v2_v2(v, vec); ED_space_clip_get_aspect_dimension_aware(t->sa->spacedata.first, &aspx, &aspy); - } - else if (t->options & CTX_MASK) { - /* MASKTODO - not working as expected */ - ED_space_clip_get_aspect(t->sa->spacedata.first, &aspx, &aspy); - } - v[0] /= aspx; - v[1] /= aspy; + v[0] /= aspx; + v[1] /= aspy; - UI_view2d_to_region_no_clip(t->view, v[0], v[1], adr, adr + 1); + UI_view2d_to_region_no_clip(t->view, v[0], v[1], adr, adr + 1); + } } else if (t->spacetype == SPACE_NODE) { UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], vec[1], adr, adr + 1); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index c1859407789..e7a2c1d8aa0 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -992,6 +992,9 @@ static void createTransPose(TransInfo *t, Object *ob) t->flag |= T_POSE; t->poseobj = ob; /* we also allow non-active objects to be transformed, in weightpaint */ + /* disable PET, its not usable in pose mode yet [#32444] */ + t->flag &= ~(T_PROP_EDIT | T_PROP_CONNECTED); + /* init trans data */ td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransPoseBone"); tdx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "TransPoseBoneExt"); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index bcebca52ce8..325dbe639b4 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -40,6 +40,7 @@ #include "DNA_armature_types.h" #include "DNA_lattice_types.h" #include "DNA_screen_types.h" +#include "DNA_sequence_types.h" #include "DNA_space_types.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" @@ -894,6 +895,17 @@ static void recalcData_view3d(TransInfo *t) /* helper for recalcData() - for sequencer transforms */ static void recalcData_sequencer(TransInfo *t) { + Editing *ed = BKE_sequencer_editing_get(t->scene, FALSE); + Sequence *seq; + + SEQ_BEGIN(ed, seq) + { + if (seq->flag & SELECT) { + BKE_sequence_invalidate_deendent(t->scene, seq); + } + } + SEQ_END + BKE_sequencer_preprocessed_cache_cleanup(); flushTransSeq(t); diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c index 2ffad3ad796..5eafc3e65a9 100644 --- a/source/blender/editors/util/undo.c +++ b/source/blender/editors/util/undo.c @@ -107,8 +107,7 @@ void ED_undo_push(bContext *C, const char *str) PE_undo_push(CTX_data_scene(C), str); } else { - if (U.uiflag & USER_GLOBALUNDO) - BKE_write_undo(C, str); + BKE_write_undo(C, str); } if (wm->file_saved) { diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index c1fb3ee3807..c95b2e85248 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -201,7 +201,7 @@ static ParamHandle *construct_param_handle(Scene *scene, BMEditMesh *em, float aspx, aspy; tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); - ED_image_get_uv_aspect(tf->tpage, &aspx, &aspy); + ED_image_get_uv_aspect(tf->tpage, NULL, &aspx, &aspy); if (aspx != aspy) param_aspect_ratio(handle, aspx, aspy); @@ -393,7 +393,7 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, BMEditMesh *e float aspx, aspy; tf = CustomData_bmesh_get(&em->bm->pdata, editFace->head.data, CD_MTEXPOLY); - ED_image_get_uv_aspect(tf->tpage, &aspx, &aspy); + ED_image_get_uv_aspect(tf->tpage, NULL, &aspx, &aspy); if (aspx != aspy) param_aspect_ratio(handle, aspx, aspy); @@ -1021,7 +1021,7 @@ static void correct_uv_aspect(BMEditMesh *em) MTexPoly *tf; tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); - ED_image_get_uv_aspect(tf->tpage, &aspx, &aspy); + ED_image_get_uv_aspect(tf->tpage, NULL, &aspx, &aspy); } if (aspx == aspy) diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index d730c7d9019..9da10381af0 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -133,11 +133,11 @@ typedef struct RegionView3D { short rflag; - /* last view */ + /* last view (use when switching out of camera view) */ float lviewquat[4]; short lpersp, lview; /* lpersp can never be set to 'RV3D_CAMOB' */ + float gridview; - float twangle[3]; diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index d36c0bbaf4a..4c1c377cb9f 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -1659,8 +1659,9 @@ void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, int value) IDP_Int(idprop) = value; rna_idproperty_touch(idprop); } - else if (bprop->set) + else if (bprop->set) { bprop->set(ptr, value); + } else if (prop->flag & PROP_EDITABLE) { IDPropertyTemplate val = {0}; IDProperty *group; diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c index 00e8ed5289f..314082dfd02 100644 --- a/source/blender/makesrna/intern/rna_sensor.c +++ b/source/blender/makesrna/intern/rna_sensor.c @@ -417,6 +417,11 @@ static void rna_def_mouse_sensor(BlenderRNA *brna) RNA_def_property_enum_items(prop, mouse_event_items); RNA_def_property_ui_text(prop, "Mouse Event", "Type of event this mouse sensor should trigger on"); RNA_def_property_update(prop, NC_LOGIC, NULL); + + prop = RNA_def_property(srna, "use_pulse", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SENS_MOUSE_FOCUS_PULSE); + RNA_def_property_ui_text(prop, "Pulse", "Moving the mouse over a different object generates a pulse"); + RNA_def_property_update(prop, NC_LOGIC, NULL); } static void rna_def_touch_sensor(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 05cd85bc58e..246f9fef98a 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -1541,7 +1541,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "near"); RNA_def_property_range(prop, 0.001f, FLT_MAX); RNA_def_property_float_default(prop, 0.1f); - RNA_def_property_ui_text(prop, "Clip Start", "3D View near clipping distance"); + RNA_def_property_ui_text(prop, "Clip Start", "3D View near clipping distance (perspective view only)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "clip_end", PROP_FLOAT, PROP_DISTANCE); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 7f8c6951620..666fa4d7b81 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -3265,6 +3265,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_enum_items(prop, compute_device_type_items); RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_userdef_compute_device_type_itemf"); RNA_def_property_ui_text(prop, "Compute Device Type", "Device to use for computation (rendering with Cycles)"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_PROPERTIES, NULL); prop = RNA_def_property(srna, "compute_device", PROP_ENUM, PROP_NONE); RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT); diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index c034832bfb4..e64e80efde3 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -105,6 +105,41 @@ static void foreachObjectLink(ModifierData *md, Object *ob, walk(userData, ob, &pimd->ob); } +static int particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p) +{ + ParticleData *pa; + + if (pimd->flag & eParticleInstanceFlag_Parents) { + if (p >= psys->totpart) { + if (psys->part->childtype == PART_CHILD_PARTICLES) { + pa = psys->particles + (psys->child + p - psys->totpart)->parent; + } + else { + pa = NULL; + } + } + else { + pa = psys->particles + p; + } + } + else { + if (psys->part->childtype == PART_CHILD_PARTICLES) { + pa = psys->particles + (psys->child + p)->parent; + } + else { + pa = NULL; + } + } + + if (pa) { + if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) return 1; + if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) return 1; + if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) return 1; + } + + return 0; +} + static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, ModifierApplyFlag UNUSED(flag)) @@ -113,11 +148,13 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md; ParticleSimulationData sim; ParticleSystem *psys = NULL; - ParticleData *pa = NULL, *pars = NULL; + ParticleData *pa = NULL; MPoly *mpoly, *orig_mpoly; MLoop *mloop, *orig_mloop; MVert *mvert, *orig_mvert; - int i, totvert, totpoly, totloop, maxvert, maxpoly, maxloop, totpart = 0, first_particle = 0; + int totvert, totpoly, totloop /* , totedge */; + int maxvert, maxpoly, maxloop, totpart = 0, first_particle = 0; + int k, p, p_skip; short track = ob->trackflag % 3, trackneg, axis = pimd->axis; float max_co = 0.0, min_co = 0.0, temp_co[3], cross[3]; float *size = NULL; @@ -153,7 +190,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, sim.psmd = psys_get_modifier(pimd->ob, psys); if (pimd->flag & eParticleInstanceFlag_UseSize) { - int p; float *si; si = size = MEM_callocN(totpart * sizeof(float), "particle size array"); @@ -171,15 +207,24 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, } } - pars = psys->particles; - totvert = dm->getNumVerts(dm); totpoly = dm->getNumPolys(dm); totloop = dm->getNumLoops(dm); + /* totedge = dm->getNumEdges(dm); */ /* UNUSED */ - maxvert = totvert * totpart; - maxpoly = totpoly * totpart; - maxloop = totloop * totpart; + /* count particles */ + maxvert = 0; + maxpoly = 0; + maxloop = 0; + + for (p = 0; p < totpart; p++) { + if (particle_skip(pimd, psys, p)) + continue; + + maxvert += totvert; + maxpoly += totpoly; + maxloop += totloop; + } psys->lattice = psys_get_lattice(&sim); @@ -191,127 +236,110 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, max_co = max_r[track]; } - result = CDDM_from_template(dm, maxvert, dm->getNumEdges(dm) * totpart, 0, maxloop, maxpoly); + result = CDDM_from_template(dm, maxvert, 0, 0, maxloop, maxpoly); mvert = result->getVertArray(result); orig_mvert = dm->getVertArray(dm); - for (i = 0; i < maxvert; i++) { - MVert *inMV; - MVert *mv = mvert + i; - ParticleKey state; - - inMV = orig_mvert + i % totvert; - DM_copy_vert_data(dm, result, i % totvert, i, 1); - *mv = *inMV; - - /*change orientation based on object trackflag*/ - copy_v3_v3(temp_co, mv->co); - mv->co[axis] = temp_co[track]; - mv->co[(axis + 1) % 3] = temp_co[(track + 1) % 3]; - mv->co[(axis + 2) % 3] = temp_co[(track + 2) % 3]; - - if ((psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && - (pimd->flag & eParticleInstanceFlag_Path)) - { - float ran = 0.0f; - if (pimd->random_position != 0.0f) { - BLI_srandom(psys->seed + (i / totvert) % totpart); - ran = pimd->random_position * BLI_frand(); - } - - if (pimd->flag & eParticleInstanceFlag_KeepShape) { - state.time = pimd->position * (1.0f - ran); - } - else { - state.time = (mv->co[axis] - min_co) / (max_co - min_co) * pimd->position * (1.0f - ran); - - if (trackneg) - state.time = 1.0f - state.time; - - mv->co[axis] = 0.0; - } - - psys_get_particle_on_path(&sim, first_particle + i / totvert, &state, 1); - - normalize_v3(state.vel); - - /* TODO: incremental rotations somehow */ - if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) { - unit_qt(state.rot); - } - else { - float temp[3] = {0.0f, 0.0f, 0.0f}; - temp[axis] = 1.0f; - - cross_v3_v3v3(cross, temp, state.vel); - - /* state.vel[axis] is the only component surviving from a dot product with the axis */ - axis_angle_to_quat(state.rot, cross, saacos(state.vel[axis])); - } - } - else { - state.time = -1.0; - psys_get_particle_state(&sim, first_particle + i / totvert, &state, 1); - } - - mul_qt_v3(state.rot, mv->co); - if (pimd->flag & eParticleInstanceFlag_UseSize) - mul_v3_fl(mv->co, size[i / totvert]); - add_v3_v3(mv->co, state.co); - } - mpoly = result->getPolyArray(result); orig_mpoly = dm->getPolyArray(dm); mloop = result->getLoopArray(result); orig_mloop = dm->getLoopArray(dm); - for (i = 0; i < maxpoly; i++) { - MPoly *inMP = orig_mpoly + i % totpoly; - MPoly *mp = mpoly + i; + for (p = 0, p_skip = 0; p < totpart; p++) { + /* skip particle? */ + if (particle_skip(pimd, psys, p)) + continue; - if (pimd->flag & eParticleInstanceFlag_Parents) { - if (i / totpoly >= psys->totpart) { - if (psys->part->childtype == PART_CHILD_PARTICLES) { - pa = psys->particles + (psys->child + i / totpoly - psys->totpart)->parent; + /* set vertices coordinates */ + for (k = 0; k < totvert; k++) { + ParticleKey state; + MVert *inMV; + MVert *mv = mvert + p_skip * totvert + k; + + inMV = orig_mvert + k; + DM_copy_vert_data(dm, result, k, p_skip * totvert + k, 1); + *mv = *inMV; + + /*change orientation based on object trackflag*/ + copy_v3_v3(temp_co, mv->co); + mv->co[axis] = temp_co[track]; + mv->co[(axis + 1) % 3] = temp_co[(track + 1) % 3]; + mv->co[(axis + 2) % 3] = temp_co[(track + 2) % 3]; + + /* get particle state */ + if ((psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && + (pimd->flag & eParticleInstanceFlag_Path)) + { + float ran = 0.0f; + if (pimd->random_position != 0.0f) { + BLI_srandom(psys->seed + p); + ran = pimd->random_position * BLI_frand(); + } + + if (pimd->flag & eParticleInstanceFlag_KeepShape) { + state.time = pimd->position * (1.0f - ran); } else { - pa = NULL; + state.time = (mv->co[axis] - min_co) / (max_co - min_co) * pimd->position * (1.0f - ran); + + if (trackneg) + state.time = 1.0f - state.time; + + mv->co[axis] = 0.0; + } + + psys_get_particle_on_path(&sim, first_particle + p, &state, 1); + + normalize_v3(state.vel); + + /* TODO: incremental rotations somehow */ + if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) { + unit_qt(state.rot); + } + else { + float temp[3] = {0.0f, 0.0f, 0.0f}; + temp[axis] = 1.0f; + + cross_v3_v3v3(cross, temp, state.vel); + + /* state.vel[axis] is the only component surviving from a dot product with the axis */ + axis_angle_to_quat(state.rot, cross, saacos(state.vel[axis])); } } else { - pa = pars + i / totpoly; + state.time = -1.0; + psys_get_particle_state(&sim, first_particle + p, &state, 1); } + + mul_qt_v3(state.rot, mv->co); + if (pimd->flag & eParticleInstanceFlag_UseSize) + mul_v3_fl(mv->co, size[p]); + add_v3_v3(mv->co, state.co); } - else { - if (psys->part->childtype == PART_CHILD_PARTICLES) { - pa = psys->particles + (psys->child + i / totpoly)->parent; - } - else { - pa = NULL; + + /* create polys and loops */ + for (k = 0; k < totpoly; k++) { + MPoly *inMP = orig_mpoly + k; + MPoly *mp = mpoly + p_skip * totpoly + k; + + DM_copy_poly_data(dm, result, k, p_skip * totpoly + k, 1); + *mp = *inMP; + mp->loopstart += p_skip * totloop; + + { + MLoop *inML = orig_mloop + inMP->loopstart; + MLoop *ml = mloop + mp->loopstart; + int j = mp->totloop; + + DM_copy_loop_data(dm, result, inMP->loopstart, mp->loopstart, j); + for (; j; j--, ml++, inML++) { + ml->v = inML->v + (p_skip * totvert); + } } } - if (pa) { - if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) continue; - if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) continue; - if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) continue; - } - - DM_copy_poly_data(dm, result, i % totpoly, i, 1); - *mp = *inMP; - mp->loopstart += (i / totpoly) * totloop; - - { - MLoop *inML = orig_mloop + inMP->loopstart; - MLoop *ml = mloop + mp->loopstart; - int j = mp->totloop; - - DM_copy_loop_data(dm, result, inMP->loopstart, mp->loopstart, j); - for (; j; j--, ml++, inML++) { - ml->v = inML->v + ((i / totpoly) * totvert); - } - } + p_skip++; } CDDM_calc_edges(result); diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index aed8a70a805..4fd2c658380 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -857,7 +857,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, mp_new->loopstart = mpoly_index * 4; mp_new->totloop = 4; - mp_new->flag = ME_SMOOTH; + mp_new->flag = mpoly_flag; origindex[mpoly_index] = ORIGINDEX_NONE; mp_new++; ml_new += 4; diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index e4fb87e8e4f..7f0484c8ee6 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -1054,6 +1054,8 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) return retval; + ima->flag |= IMA_USED_FOR_RENDER; + /* mipmap test */ image_mipmap_test(tex, ibuf); diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index b583c6fd7fe..e3867c0a32a 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -326,7 +326,11 @@ static void build_pict_list(char *first, int totframes, int fstep, int fontid) int file; file = open(filepath, O_BINARY | O_RDONLY, 0); - if (file < 0) return; + if (file < 0) { + /* print errno? */ + return; + } + picture = (PlayAnimPict *)MEM_callocN(sizeof(PlayAnimPict), "picture"); if (picture == NULL) { printf("Not enough memory for pict struct '%s'\n", filepath); @@ -700,11 +704,11 @@ void playanim_window_open(const char *title, int posx, int posy, int sizex, int inital_state = start_maximized ? GHOST_kWindowStateMaximized : GHOST_kWindowStateNormal; g_WS.ghost_window = GHOST_CreateWindow(g_WS.ghost_system, - title, - posx, posy, sizex, sizey, - inital_state, - GHOST_kDrawingContextTypeOpenGL, - FALSE /* no stereo */, FALSE); + title, + posx, posy, sizex, sizey, + inital_state, + GHOST_kDrawingContextTypeOpenGL, + FALSE /* no stereo */, FALSE); //if (ghostwin) { //if (win) { diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index f9fa0ae65f1..c1afed82b02 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -1727,11 +1727,6 @@ static void MergeScene_LogicBrick(SCA_ILogicBrick* brick, KX_Scene *to) brick->Replace_IScene(to); brick->Replace_NetworkScene(to->GetNetworkScene()); - SCA_ISensor *sensor= dynamic_cast(brick); - if (sensor) { - sensor->Replace_EventManager(logicmgr); - } - /* near sensors have physics controllers */ #ifdef USE_BULLET KX_TouchSensor *touch_sensor = dynamic_cast(brick); @@ -1739,6 +1734,14 @@ static void MergeScene_LogicBrick(SCA_ILogicBrick* brick, KX_Scene *to) touch_sensor->GetPhysicsController()->SetPhysicsEnvironment(to->GetPhysicsEnvironment()); } #endif + + // If we end up replacing a KX_TouchEventManager, we need to make sure + // physics controllers are properly in place. In other words, do this + // after merging physics controllers! + SCA_ISensor *sensor= dynamic_cast(brick); + if (sensor) { + sensor->Replace_EventManager(logicmgr); + } } #ifdef USE_BULLET diff --git a/source/tests/bl_rna_wiki_reference.py b/source/tests/bl_rna_wiki_reference.py new file mode 100644 index 00000000000..2018c4327a3 --- /dev/null +++ b/source/tests/bl_rna_wiki_reference.py @@ -0,0 +1,70 @@ +# ##### 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. +# +# ##### END GPL LICENSE BLOCK ##### + +# + +# Use for validating our wiki interlinking. +# ./blender.bin --background -noaudio --python source/tests/bl_rna_wiki_reference.py +# +# 1) test_lookup_coverage() -- ensure that we have lookups for _every_ RNA path +# 2) test_urls() -- ensure all the URL's are correct +# 3) test_language_coverage() -- ensure language lookup table is complete +# + +import bpy + +# a stripped down version of api_dump() in rna_info_dump.py + + +def test_lookup_coverage(): + + def rna_ids(): + + import rna_info + struct = rna_info.BuildRNAInfo()[0] + for struct_id, v in sorted(struct.items()): + props = [(prop.identifier, prop) for prop in v.properties] + for prop_id, prop in props: + yield "bpy.types.%s.%s" % (struct_id[1], prop_id) + + for submod_id in dir(bpy.ops): + for op_id in dir(getattr(bpy.ops, submod_id)): + yield "bpy.ops.%s.%s" % (submod_id, op_id) + + # check coverage + from bl_operators import wm + + for rna_id in rna_ids(): + url = wm.WM_OT_doc_view_manual._lookup_rna_url(rna_id, verbose=False) + print(rna_id, "->", url) + + +def test_urls(): + pass # TODO + + +def test_language_coverage(): + pass # TODO + + +def main(): + test_lookup_coverage() + test_language_coverage() + +if __name__ == "__main__": + main() diff --git a/source/tests/rna_info_dump.py b/source/tests/rna_info_dump.py index 293c02dfb84..615c3b035ce 100644 --- a/source/tests/rna_info_dump.py +++ b/source/tests/rna_info_dump.py @@ -19,7 +19,7 @@ # # Used for generating API diff's between releases -# ./blender.bin --background -noaudio --python release/test/rna_info_dump.py +# ./blender.bin --background -noaudio --python source/tests/rna_info_dump.py import bpy From f631ae9f46f0827dc79c3c199acc889eb6151882 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 13 Sep 2012 13:08:31 +0000 Subject: [PATCH 140/160] Color Management: fix segfault when configuration file is missing Also don't try to load configuration file from environment variable if it contains empty string. --- source/blender/imbuf/intern/colormanagement.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 5e3c445c7f0..c1cb8229be3 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -573,7 +573,7 @@ void IMB_colormanagement_init(void) ocio_env = getenv("OCIO"); - if (ocio_env) + if (ocio_env && ocio_env[0] != '\0') config = OCIO_configCreateFromEnv(); if (config == NULL) { @@ -590,9 +590,9 @@ void IMB_colormanagement_init(void) OCIO_setCurrentConfig(config); colormanage_load_config(config); - } - OCIO_configRelease(config); + OCIO_configRelease(config); + } #endif BLI_init_srgb_conversion(); From ad15c19ab946ff6cae65e0b64947da49edb8c3ba Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 13 Sep 2012 13:53:58 +0000 Subject: [PATCH 141/160] Merging r50573 through r50575 from trunk soc-2011-tomato --- source/blender/editors/space_image/image_edit.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index 360cbc3f026..79d01491df7 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -230,13 +230,19 @@ void ED_space_image_get_uv_aspect(SpaceImage *sima, float *aspx, float *aspy) void ED_image_get_uv_aspect(Image *ima, ImageUser *iuser, float *aspx, float *aspy) { - int w, h; + if (ima) { + int w, h; - BKE_image_get_aspect(ima, aspx, aspy); - BKE_image_get_size(ima, iuser, &w, &h); + BKE_image_get_aspect(ima, aspx, aspy); + BKE_image_get_size(ima, iuser, &w, &h); - *aspx *= (float)w; - *aspy *= (float)h; + *aspx *= (float)w; + *aspy *= (float)h; + } + else { + *aspx = 1.0f; + *aspy = 1.0f; + } } /* takes event->mval */ From 5badefa8cfafe0f6989594dbf827997a7a8597a1 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 13 Sep 2012 14:52:25 +0000 Subject: [PATCH 142/160] Color Management: fix crash when strip failed to render In this case sequencer would allocate empty image buffer which used to not to have assigned color spaces but it was marked as non-linear float. Assuming black would always be black in sequencer's color space no additional transformation for display is needed. Solved by removing NOLINEAR_FLOAT flag from image buffers and using check image buffer's float_colorspace for NULL when needed to check whether float buffer is linear or not. --- source/blender/blenkernel/intern/sequencer.c | 7 +++---- source/blender/imbuf/IMB_imbuf_types.h | 8 +------- source/blender/imbuf/intern/colormanagement.c | 6 +----- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index e870ec5d8ee..84881af8f16 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -2659,8 +2659,10 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) } } - if (ibuf == NULL) + if (ibuf == NULL) { ibuf = IMB_allocImBuf(context.rectx, context.recty, 32, IB_rect); + BKE_sequencer_imbuf_assign_spaces(context.scene, ibuf); + } if (ibuf->x != context.rectx || ibuf->y != context.recty) use_preprocess = TRUE; @@ -2739,7 +2741,6 @@ static ImBuf *seq_render_strip_stack(SeqRenderData context, ListBase *seqbasep, if (count == 1) { out = seq_render_strip(context, seq_arr[0], cfra); - out->colormanage_flags |= IMB_COLORMANAGE_NOLINEAR_FLOAT; BKE_sequencer_cache_put(context, seq_arr[0], cfra, SEQ_STRIPELEM_IBUF_COMP, out); @@ -2819,8 +2820,6 @@ static ImBuf *seq_render_strip_stack(SeqRenderData context, ListBase *seqbasep, BKE_sequencer_cache_put(context, seq_arr[i], cfra, SEQ_STRIPELEM_IBUF_COMP, out); } - out->colormanage_flags |= IMB_COLORMANAGE_NOLINEAR_FLOAT; - return out; } diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 428bd401754..cda43199be5 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -128,9 +128,8 @@ typedef struct ImBuf { unsigned int encodedbuffersize; /* Size of encodedbuffer */ /* color management */ - int colormanage_flags; /* color management flags field */ struct ColorSpace *rect_colorspace; /* color space of byte buffer */ - struct ColorSpace *float_colorspace; /* color space of float buffer, used by sequencer only */ + struct ColorSpace *float_colorspace; /* color space of float buffer, used by sequencer only */ unsigned int *display_buffer_flags; /* array of per-display display buffers dirty flags */ struct ColormanageCache *colormanage_cache; /* cache used by color management */ @@ -262,9 +261,4 @@ extern const char *imb_ext_image_qt[]; extern const char *imb_ext_movie[]; extern const char *imb_ext_audio[]; -/* ImBuf->colormanage_flags */ -enum { - IMB_COLORMANAGE_NOLINEAR_FLOAT = (1 << 0) -}; - #endif diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index c1cb8229be3..b88ff3cda47 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1068,8 +1068,6 @@ typedef struct DisplayBufferThread { float dither; int predivide; - int nolinear_float; - const char *byte_colorspace; const char *float_colorspace; } DisplayBufferThread; @@ -1128,8 +1126,6 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l handle->byte_colorspace = init_data->byte_colorspace; handle->float_colorspace = init_data->float_colorspace; - - handle->nolinear_float = ibuf->colormanage_flags & IMB_COLORMANAGE_NOLINEAR_FLOAT; } static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) @@ -1168,7 +1164,7 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) IMB_colormanagement_transform(linear_buffer, width, height, channels, from_colorspace, to_colorspace, predivide); } - else if (handle->nolinear_float) { + else if (handle->float_colorspace) { /* currently float is non-linear only in sequencer, which is working * in it's own color space even to handle float buffers. * This color space is the same for byte and float images. From 58da4a1760028dbf4b7f0df78ed3d897ba5690c2 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 14 Sep 2012 14:05:05 +0000 Subject: [PATCH 143/160] Merging r50576 through r50587 from trunk into soc-2011-tomato --- GNUmakefile | 4 + .../cmake/cmake_static_check_smatch.py | 73 ++++ intern/cycles/app/cycles_test.cpp | 3 + source/blender/avi/intern/avi.c | 10 +- source/blender/blenkernel/BKE_mask.h | 4 +- .../blender/blenkernel/intern/DerivedMesh.c | 2 +- source/blender/blenkernel/intern/fmodifier.c | 4 +- source/blender/blenkernel/intern/lattice.c | 2 +- source/blender/blenkernel/intern/library.c | 48 ++- source/blender/blenkernel/intern/mask.c | 8 +- source/blender/blenkernel/intern/sequencer.c | 2 +- .../operations/COM_MaskOperation.cpp | 2 +- .../editors/animation/keyframes_draw.c | 2 +- source/blender/editors/armature/poselib.c | 2 +- source/blender/editors/armature/poseobject.c | 20 +- source/blender/editors/include/UI_interface.h | 2 +- source/blender/editors/interface/interface.c | 13 +- .../editors/interface/interface_icons.c | 2 +- source/blender/editors/interface/resources.c | 2 +- source/blender/editors/mesh/editmesh_select.c | 26 +- source/blender/editors/mesh/meshtools.c | 18 +- .../blender/editors/physics/particle_object.c | 6 +- source/blender/editors/screen/screen_ops.c | 8 +- .../editors/sculpt_paint/paint_image.c | 4 +- .../editors/space_buttons/buttons_texture.c | 2 +- source/blender/editors/space_node/drawnode.c | 19 +- .../blender/editors/space_node/node_group.c | 2 +- .../blender/editors/space_view3d/drawobject.c | 2 +- .../editors/transform/transform_conversions.c | 3 + source/blender/editors/util/ed_util.c | 4 +- source/blender/imbuf/intern/filetype.c | 8 - source/blender/imbuf/intern/imbuf_cocoa.m | 384 ------------------ source/blender/imbuf/intern/iris.c | 12 +- source/blender/makesrna/intern/rna_main_api.c | 2 +- .../nodes/composite/node_composite_tree.c | 1 - .../render/intern/source/convertblender.c | 34 +- .../Rasterizer/RAS_2DFilterManager.cpp | 2 +- 37 files changed, 237 insertions(+), 505 deletions(-) create mode 100644 build_files/cmake/cmake_static_check_smatch.py delete mode 100644 source/blender/imbuf/intern/imbuf_cocoa.m diff --git a/GNUmakefile b/GNUmakefile index f48ac5c2e41..1f1de3f6b99 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -251,6 +251,10 @@ check_sparse: $(CMAKE_CONFIG) cd $(BUILD_DIR) ; python3.2 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_sparse.py +check_smatch: + $(CMAKE_CONFIG) + cd $(BUILD_DIR) ; python3.2 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_smatch.py + check_spelling_py: cd $(BUILD_DIR) ; PYTHONIOENCODING=utf_8 python3.2 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/release/scripts diff --git a/build_files/cmake/cmake_static_check_smatch.py b/build_files/cmake/cmake_static_check_smatch.py new file mode 100644 index 00000000000..779945b030a --- /dev/null +++ b/build_files/cmake/cmake_static_check_smatch.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3.2 + +# ***** 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. +# +# Contributor(s): Campbell Barton +# +# ***** END GPL LICENSE BLOCK ***** + +# + +CHECKER_IGNORE_PREFIX = [ + "extern", + "intern/moto", + ] + +CHECKER_BIN = "smatch" +CHECKER_ARGS = [ + "--full-path", + "--two-passes", + ] + +import project_source_info +import subprocess +import sys + + +def main(): + source_info = project_source_info.build_info(use_cxx=False, ignore_prefix_list=CHECKER_IGNORE_PREFIX) + + check_commands = [] + for c, inc_dirs, defs in source_info: + + cmd = ([CHECKER_BIN] + + CHECKER_ARGS + + [c] + + [("-I%s" % i) for i in inc_dirs] + + [("-D%s" % d) for d in defs] + ) + + check_commands.append((c, cmd)) + + def my_process(i, c, cmd): + percent = 100.0 * (i / (len(check_commands) - 1)) + percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" + + sys.stdout.flush() + sys.stdout.write("%s %s\n" % (percent_str, c)) + + return subprocess.Popen(cmd) + + process_functions = [] + for i, (c, cmd) in enumerate(check_commands): + process_functions.append((my_process, (i, c, cmd))) + + project_source_info.queue_processes(process_functions) + + +if __name__ == "__main__": + main() diff --git a/intern/cycles/app/cycles_test.cpp b/intern/cycles/app/cycles_test.cpp index 5ee351260c5..e921cc46fe4 100644 --- a/intern/cycles/app/cycles_test.cpp +++ b/intern/cycles/app/cycles_test.cpp @@ -272,6 +272,9 @@ static void options_parse(int argc, const char **argv) options.scene_params.shadingsystem = SceneParams::OSL; else if(ssname == "svm") options.scene_params.shadingsystem = SceneParams::SVM; + + /* Progressive rendering */ + options.session_params.progressive = true; /* find matching device */ DeviceType device_type = Device::type_from_string(devicename.c_str()); diff --git a/source/blender/avi/intern/avi.c b/source/blender/avi/intern/avi.c index 39424057faf..cda2cf303eb 100644 --- a/source/blender/avi/intern/avi.c +++ b/source/blender/avi/intern/avi.c @@ -734,9 +734,10 @@ AviError AVI_close(AviMovie *movie) fclose(movie->fp); - for (i = 0; i < movie->header->Streams; i++) { - if (movie->streams[i].sf != NULL) + for (i = 0; movie->header && (i < movie->header->Streams); i++) { + if (movie->streams && (movie->streams[i].sf != NULL)) { MEM_freeN(movie->streams[i].sf); + } } if (movie->header != NULL) @@ -1081,9 +1082,10 @@ AviError AVI_close_compress(AviMovie *movie) fclose(movie->fp); - for (i = 0; i < movie->header->Streams; i++) { - if (movie->streams[i].sf != NULL) + for (i = 0; movie->header && (i < movie->header->Streams); i++) { + if (movie->streams && (movie->streams[i].sf != NULL)) { MEM_freeN(movie->streams[i].sf); + } } if (movie->header != NULL) MEM_freeN(movie->header); diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 9ce678d8988..51e301fec80 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -102,8 +102,8 @@ struct Mask *BKE_mask_new(const char *name); struct Mask *BKE_mask_copy_nolib(struct Mask *mask); struct Mask *BKE_mask_copy(struct Mask *mask); -void BKE_mask_free(struct Mask *mask); -void BKE_mask_unlink(struct Main *bmain, struct Mask *mask); +void BKE_mask_free_nolib(struct Mask *mask); +void BKE_mask_free(struct Main *bmain, struct Mask *mask); void BKE_mask_coord_from_frame(float r_co[2], const float co[2], const float frame_size[2]); void BKE_mask_coord_from_movieclip(struct MovieClip *clip, struct MovieClipUser *user, float r_co[2], const float co[2]); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index a7f8e1bb161..8c0aea5723f 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2081,7 +2081,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D if ((*final_r)->type != DM_TYPE_EDITBMESH) { DM_ensure_tessface(*final_r); } - if (cage_r) { + if (cage_r && *cage_r) { if ((*cage_r)->type != DM_TYPE_EDITBMESH) { if (*cage_r != *final_r) { DM_ensure_tessface(*cage_r); diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c index 438188b1e2a..538d2469a93 100644 --- a/source/blender/blenkernel/intern/fmodifier.c +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -965,8 +965,8 @@ FModifierTypeInfo *get_fmodifier_typeinfo(int type) } /* only return for valid types */ - if ( (type >= FMODIFIER_TYPE_NULL) && - (type <= FMODIFIER_NUM_TYPES) ) + if ((type >= FMODIFIER_TYPE_NULL) && + (type < FMODIFIER_NUM_TYPES)) { /* there shouldn't be any segfaults here... */ return fmodifiersTypeInfo[type]; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 0e73d10fa5f..17e4103c7d3 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -488,7 +488,7 @@ static int where_on_path_deform(Object *ob, float ctime, float vec[4], float dir /* test for cyclic */ bl = cu->bev.first; if (!bl->nr) return 0; - if (bl && bl->poly > -1) cycl = 1; + if (bl->poly > -1) cycl = 1; if (cycl == 0) { ctime1 = CLAMPIS(ctime, 0.0f, 1.0f); diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index f8c1a35776a..45364f5aafa 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -800,6 +800,7 @@ static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata /* used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c */ void BKE_libblock_free(ListBase *lb, void *idv) { + Main *bmain = G.main; /* should eventually be an arg */ ID *id = idv; #ifdef WITH_PYTHON @@ -899,7 +900,7 @@ void BKE_libblock_free(ListBase *lb, void *idv) BKE_movieclip_free((MovieClip *)id); break; case ID_MSK: - BKE_mask_free((Mask *)id); + BKE_mask_free(bmain, (Mask *)id); break; } @@ -911,7 +912,7 @@ void BKE_libblock_free(ListBase *lb, void *idv) BLI_remlink(lb, id); /* this ID may be a driver target! */ - BKE_animdata_main_cb(G.main, animdata_dtar_clear_cb, (void *)id); + BKE_animdata_main_cb(bmain, animdata_dtar_clear_cb, (void *)id); MEM_freeN(id); } @@ -946,9 +947,52 @@ void free_main(Main *mainvar) ID *id; while ( (id = lb->first) ) { +#if 1 BKE_libblock_free(lb, id); +#else + /* errors freeing ID's can be hard to track down, + * enable this so valgrind will give the line number in its error log */ + switch (a) { + case 0: BKE_libblock_free(lb, id); break; + case 1: BKE_libblock_free(lb, id); break; + case 2: BKE_libblock_free(lb, id); break; + case 3: BKE_libblock_free(lb, id); break; + case 4: BKE_libblock_free(lb, id); break; + case 5: BKE_libblock_free(lb, id); break; + case 6: BKE_libblock_free(lb, id); break; + case 7: BKE_libblock_free(lb, id); break; + case 8: BKE_libblock_free(lb, id); break; + case 9: BKE_libblock_free(lb, id); break; + case 10: BKE_libblock_free(lb, id); break; + case 11: BKE_libblock_free(lb, id); break; + case 12: BKE_libblock_free(lb, id); break; + case 13: BKE_libblock_free(lb, id); break; + case 14: BKE_libblock_free(lb, id); break; + case 15: BKE_libblock_free(lb, id); break; + case 16: BKE_libblock_free(lb, id); break; + case 17: BKE_libblock_free(lb, id); break; + case 18: BKE_libblock_free(lb, id); break; + case 19: BKE_libblock_free(lb, id); break; + case 20: BKE_libblock_free(lb, id); break; + case 21: BKE_libblock_free(lb, id); break; + case 22: BKE_libblock_free(lb, id); break; + case 23: BKE_libblock_free(lb, id); break; + case 24: BKE_libblock_free(lb, id); break; + case 25: BKE_libblock_free(lb, id); break; + case 26: BKE_libblock_free(lb, id); break; + case 27: BKE_libblock_free(lb, id); break; + case 28: BKE_libblock_free(lb, id); break; + case 29: BKE_libblock_free(lb, id); break; + case 30: BKE_libblock_free(lb, id); break; + case 31: BKE_libblock_free(lb, id); break; + case 32: BKE_libblock_free(lb, id); break; + default: + BLI_assert(0); + } +#endif } } + a = set_listbasepointers(mainvar, lbarray); MEM_freeN(mainvar); } diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 06d063574a5..97b46d4829d 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -910,7 +910,8 @@ void BKE_mask_layer_free_list(ListBase *masklayers) } } -void BKE_mask_free(Mask *mask) +/** free for temp copy, but don't manage unlinking from other pointers */ +void BKE_mask_free_nolib(Mask *mask) { BKE_mask_layer_free_list(&mask->masklayers); } @@ -928,7 +929,7 @@ static void ntree_unlink_mask_cb(void *calldata, struct ID *UNUSED(owner_id), st } } -void BKE_mask_unlink(Main *bmain, Mask *mask) +void BKE_mask_free(Main *bmain, Mask *mask) { bScreen *scr; ScrArea *area; @@ -991,7 +992,8 @@ void BKE_mask_unlink(Main *bmain, Mask *mask) treetype->foreach_nodetree(bmain, (void *)mask, &ntree_unlink_mask_cb); } - BKE_libblock_free(&bmain->mask, mask); + /* free mask data */ + BKE_mask_layer_free_list(&mask->masklayers); } void BKE_mask_coord_from_frame(float r_co[2], const float co[2], const float frame_size[2]) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 84881af8f16..0d8b220dd00 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -2254,7 +2254,7 @@ static ImBuf *seq_render_mask(SeqRenderData context, Mask *mask, float nr, short BKE_maskrasterize_handle_init(mr_handle, mask_temp, context.rectx, context.recty, TRUE, TRUE, TRUE); - BKE_mask_free(mask_temp); + BKE_mask_free_nolib(mask_temp); MEM_freeN(mask_temp); BKE_maskrasterize_buffer(mr_handle, context.rectx, context.recty, maskbuf); diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp index a156dfc1d99..36b3f2023ae 100644 --- a/source/blender/compositor/operations/COM_MaskOperation.cpp +++ b/source/blender/compositor/operations/COM_MaskOperation.cpp @@ -93,7 +93,7 @@ void MaskOperation::initExecution() frame_iter += frame_step; } - BKE_mask_free(mask_temp); + BKE_mask_free_nolib(mask_temp); MEM_freeN(mask_temp); } } diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index 46537674e59..6c9105dde69 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -412,7 +412,7 @@ static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, DLRBT_Tree *beztTree, * -> firstly, handles must have same central value as each other * -> secondly, handles which control that section of the curve must be constant */ - if ((!prev) || (!beztn)) return; + if (prev == NULL) return; if (IS_EQF(beztn->vec[1][1], prev->vec[1][1]) == 0) return; if (IS_EQF(beztn->vec[1][1], beztn->vec[0][1]) == 0) return; if (IS_EQF(prev->vec[1][1], prev->vec[2][1]) == 0) return; diff --git a/source/blender/editors/armature/poselib.c b/source/blender/editors/armature/poselib.c index 23c987c3536..eea7424c59a 100644 --- a/source/blender/editors/armature/poselib.c +++ b/source/blender/editors/armature/poselib.c @@ -1006,7 +1006,7 @@ static void poselib_preview_apply(bContext *C, wmOperator *op) /* get search-string */ index = pld->search_cursor; - if (index >= 0 && index <= sizeof(tempstr) - 1) { + if (index >= 0 && index < sizeof(tempstr) - 1) { memcpy(&tempstr[0], &pld->searchstr[0], index); tempstr[index] = '|'; memcpy(&tempstr[index + 1], &pld->searchstr[index], (sizeof(tempstr) - 1) - index); diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index e4f1e6d3e8b..e9424a08b0c 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -2350,20 +2350,18 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op) for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) { pose_bone_do_paste(ob, pchan, only_select, 0); } - + /* free temp data - free manually as was copied without constraints */ - if (dummyPose) { - for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) { - if (pchan->prop) { - IDP_FreeProperty(pchan->prop); - MEM_freeN(pchan->prop); - } + for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) { + if (pchan->prop) { + IDP_FreeProperty(pchan->prop); + MEM_freeN(pchan->prop); } - - /* was copied without constraints */ - BLI_freelistN(&dummyPose->chanbase); - MEM_freeN(dummyPose); } + + /* was copied without constraints */ + BLI_freelistN(&dummyPose->chanbase); + MEM_freeN(dummyPose); } else { /* no animation, so just reset whole pose to rest pose diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index cf440cddb80..917153c9199 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -196,7 +196,7 @@ typedef enum { UI_BUT_POIN_BIT = 256 /* OR'd with a bit index*/ } eButPointerType; -/* button requires a pointer */ +/* requires (but->poin != NULL) */ #define UI_BUT_POIN_TYPES (UI_BUT_POIN_FLOAT | UI_BUT_POIN_SHORT | UI_BUT_POIN_CHAR) /* assigned to but->type, OR'd with the flags above when passing args */ diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index c3f1080cecc..7524e88d5ac 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -2620,10 +2620,17 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str, { uiBut *but; int slen; - - if (type & UI_BUT_POIN_TYPES) { /* a pointer is required */ - if (poin == NULL) + + /* we could do some more error checks here */ + if ((type & BUTTYPE) == LABEL) { + BLI_assert((poin != NULL || a1 != 0.0f || a2 != 0.0f || min != 0.0f || max != 0.0f) == FALSE); + } + + if (type & UI_BUT_POIN_TYPES) { /* a pointer is required */ + if (poin == NULL) { + BLI_assert(0); return NULL; + } } but = MEM_callocN(sizeof(uiBut), "uiBut"); diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index e825ff7880d..f6f12f98181 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -835,7 +835,7 @@ static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size) if (G.debug & G_DEBUG) printf("%s, error: requested preview image does not exist", __func__); } - if (!prv_img->rect[size]) { + else if (!prv_img->rect[size]) { prv_img->w[size] = render_size; prv_img->h[size] = render_size; prv_img->changed[size] = 1; diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index ed6b2e00119..b379a2e7b4c 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -944,7 +944,7 @@ void UI_SetTheme(int spacetype, int regionid) } } -bTheme *UI_GetTheme() +bTheme *UI_GetTheme(void) { return U.themes.first; } diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index dc5d1cea443..81776ff7f4f 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2324,25 +2324,19 @@ static int edbm_select_sharp_edges_exec(bContext *C, wmOperator *op) BMIter iter; BMEdge *e; BMLoop *l1, *l2; - float sharp = RNA_float_get(op->ptr, "sharpness"), angle; + const float sharp = RNA_float_get(op->ptr, "sharpness"); BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) || !e->l) - continue; + if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == FALSE && + BM_edge_loop_pair(e, &l1, &l2)) + { + /* edge has exactly two neighboring faces, check angle */ + const float angle = angle_normalized_v3v3(l1->f->no, l2->f->no); - l1 = e->l; - l2 = l1->radial_next; - - if (l1 == l2) - continue; - - /* edge has exactly two neighboring faces, check angle */ - angle = angle_normalized_v3v3(l1->f->no, l2->f->no); - - if (fabsf(angle) < sharp) { - BM_edge_select_set(em->bm, e, TRUE); + if (fabsf(angle) > sharp) { + BM_edge_select_set(em->bm, e, TRUE); + } } - } WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); @@ -2369,7 +2363,7 @@ void MESH_OT_edges_select_sharp(wmOperatorType *ot) /* props */ prop = RNA_def_float_rotation(ot->srna, "sharpness", 0, NULL, DEG2RADF(0.01f), DEG2RADF(180.0f), "Sharpness", "", DEG2RADF(1.0f), DEG2RADF(180.0f)); - RNA_def_property_float_default(prop, DEG2RADF(1.0f)); + RNA_def_property_float_default(prop, DEG2RADF(30.0f)); } static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 06dcac0505a..a7467ee4c79 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -442,18 +442,20 @@ int join_mesh_exec(bContext *C, wmOperator *op) } if (me->totpoly) { - /* make mapping for materials */ - for (a = 1; a <= base->object->totcol; a++) { - ma = give_current_material(base->object, a); + if (totmat) { + /* make mapping for materials */ + for (a = 1; a <= base->object->totcol; a++) { + ma = give_current_material(base->object, a); - for (b = 0; b < totcol; b++) { - if (ma == matar[b]) { - matmap[a - 1] = b; - break; + for (b = 0; b < totcol; b++) { + if (ma == matar[b]) { + matmap[a - 1] = b; + break; + } } } } - + CustomData_merge(&me->pdata, &pdata, CD_MASK_MESH, CD_DEFAULT, totpoly); CustomData_copy_data(&me->pdata, &pdata, 0, polyofs, me->totpoly); diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index b57500df719..a17d84af128 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -98,12 +98,14 @@ void OBJECT_OT_particle_system_add(wmOperatorType *ot) static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *ob= ED_object_context(C); + Object *ob = ED_object_context(C); Scene *scene = CTX_data_scene(C); - int mode_orig = ob->mode; + int mode_orig; + if (!scene || !ob) return OPERATOR_CANCELLED; + mode_orig = ob->mode; object_remove_particle_system(scene, ob); /* possible this isn't the active object diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 9f9d0bab15c..50a210e5d7c 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -1370,12 +1370,12 @@ static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event) if (event->type == EVT_ACTIONZONE_AREA) { sActionzoneData *sad = event->customdata; - if (sad->modifier > 0) { + if (sad == NULL || sad->modifier > 0) { return OPERATOR_PASS_THROUGH; } /* verify *sad itself */ - if (sad == NULL || sad->sa1 == NULL || sad->az == NULL) + if (sad->sa1 == NULL || sad->az == NULL) return OPERATOR_PASS_THROUGH; /* is this our *sad? if areas not equal it should be passed on */ @@ -2284,12 +2284,12 @@ static int area_join_invoke(bContext *C, wmOperator *op, wmEvent *event) if (event->type == EVT_ACTIONZONE_AREA) { sActionzoneData *sad = event->customdata; - if (sad->modifier > 0) { + if (sad == NULL || sad->modifier > 0) { return OPERATOR_PASS_THROUGH; } /* verify *sad itself */ - if (sad == NULL || sad->sa1 == NULL || sad->sa2 == NULL) + if (sad->sa1 == NULL || sad->sa2 == NULL) return OPERATOR_PASS_THROUGH; /* is this our *sad? if areas equal it should be passed on */ diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 29571a60cbf..386342d7b38 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -5381,8 +5381,8 @@ void ED_space_image_paint_update(wmWindowManager *wm, ToolSettings *settings) if (!imapaint->paintcursor) { imapaint->paintcursor = - WM_paint_cursor_activate(wm, image_paint_poll, - brush_drawcursor, NULL); + WM_paint_cursor_activate(wm, image_paint_poll, + brush_drawcursor, NULL); } } } diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index cdecda63432..0e82d8651f3 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -341,7 +341,7 @@ static void template_texture_user_menu(bContext *C, uiLayout *layout, void *UNUS { /* callback when opening texture user selection menu, to create buttons. */ SpaceButs *sbuts = CTX_wm_space_buts(C); - ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL; + ButsContextTexture *ct = sbuts->texuser; ButsTextureUser *user; uiBlock *block = uiLayoutGetBlock(layout); const char *last_category = NULL; diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 91c91f5089f..4fae060deb9 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -648,23 +648,22 @@ static void update_group_output_cb(bContext *UNUSED(C), void *UNUSED(snode_v), v static void draw_group_socket_name(SpaceNode *snode, bNode *gnode, bNodeSocket *sock, int in_out, float xoffset, float yoffset) { - bNodeTree *ngroup = (bNodeTree *)gnode->id; - uiBut *bt; - const char *ui_name = IFACE_(sock->name); - if (sock->flag & SOCK_DYNAMIC) { - bt = uiDefBut(gnode->block, TEX, 0, "", - sock->locx + xoffset, sock->locy + 1 + yoffset, 72, NODE_DY, - sock->name, 0, sizeof(sock->name), 0, 0, ""); + bNodeTree *ngroup = (bNodeTree *)gnode->id; + uiBut *but; + but = uiDefBut(gnode->block, TEX, 0, "", + sock->locx + xoffset, sock->locy + 1 + yoffset, 72, NODE_DY, + sock->name, 0, sizeof(sock->name), 0, 0, ""); if (in_out == SOCK_IN) - uiButSetFunc(bt, update_group_input_cb, snode, ngroup); + uiButSetFunc(but, update_group_input_cb, snode, ngroup); else - uiButSetFunc(bt, update_group_output_cb, snode, ngroup); + uiButSetFunc(but, update_group_output_cb, snode, ngroup); } else { + const char *ui_name = IFACE_(sock->name); uiDefBut(gnode->block, LABEL, 0, ui_name, sock->locx + xoffset, sock->locy + 1 + yoffset, 72, NODE_DY, - NULL, 0, sizeof(ui_name), 0, 0, ""); + NULL, 0, 0, 0, 0, ""); } } diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index 77583ae1325..b76cc05af5c 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -950,7 +950,7 @@ static int node_group_make_insert_selected(bNodeTree *ntree, bNode *gnode) int toselect = (link->tonode && (link->tonode->flag & NODE_SELECT) && link->tonode != gnode); linkn = link->next; - if (gnode && ((fromselect && link->tonode == gnode) || (toselect && link->fromnode == gnode))) { + if ((fromselect && link->tonode == gnode) || (toselect && link->fromnode == gnode)) { /* remove all links to/from the gnode. * this can remove link information, but there's no general way to preserve it. */ diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 90da3824870..d1f0d8fa25e 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -7232,7 +7232,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short setlinestyle(0); } } - else if ((curcon->flag & CONSTRAINT_EXPAND) && (cti) && (cti->get_constraint_targets)) { + else if ((curcon->flag & CONSTRAINT_EXPAND) && (cti->get_constraint_targets)) { cti->get_constraint_targets(curcon, &targets); for (ct = targets.first; ct; ct = ct->next) { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index e7a2c1d8aa0..181f9fe6036 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5609,6 +5609,9 @@ static void createTransNodeData(bContext *UNUSED(C), TransInfo *t) return; } + /* nodes dont support PET and probably never will */ + t->flag &= ~(T_PROP_EDIT | T_PROP_CONNECTED); + /* set transform flags on nodes */ for (node = snode->edittree->nodes.first; node; node = node->next) { if (node->flag & NODE_SELECT && is_node_parent_select(node) == FALSE) { diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index b0a2a24f25b..23d6b0a075e 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -89,7 +89,9 @@ void ED_editors_init(bContext *C) } /* image editor paint mode */ - ED_space_image_paint_update(wm, sce->toolsettings); + if (sce) { + ED_space_image_paint_update(wm, sce->toolsettings); + } } /* frees all editmode stuff */ diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c index 900bc7756f0..d67de3be68b 100644 --- a/source/blender/imbuf/intern/filetype.c +++ b/source/blender/imbuf/intern/filetype.c @@ -48,12 +48,6 @@ static int imb_ftype_default(ImFileType *type, ImBuf *ibuf) { return (ibuf->ftype & type->filetype); } -#if defined(__APPLE__) && defined(IMBUF_COCOA) -static int imb_ftype_cocoa(ImFileType *type, ImBuf *ibuf) -{ - return (ibuf->ftype & TIF); -} -#endif static int imb_ftype_iris(ImFileType *type, ImBuf *ibuf) { (void)type; @@ -83,8 +77,6 @@ ImFileType IMB_FILE_TYPES[] = { #endif #ifdef WITH_TIFF {imb_inittiff, NULL, imb_is_a_tiff, imb_ftype_default, imb_loadtiff, imb_savetiff, imb_loadtiletiff, 0, TIF}, -#elif defined(__APPLE__) && defined(IMBUF_COCOA) - {NULL, NULL, imb_is_a_cocoa, imb_ftype_cocoa, imb_imb_cocoaLoadImage, imb_savecocoa, NULL, 0, TIF}, #endif #ifdef WITH_HDR {NULL, NULL, imb_is_a_hdr, imb_ftype_default, imb_loadhdr, imb_savehdr, NULL, IM_FTYPE_FLOAT, RADHDR}, diff --git a/source/blender/imbuf/intern/imbuf_cocoa.m b/source/blender/imbuf/intern/imbuf_cocoa.m deleted file mode 100644 index d099c8af236..00000000000 --- a/source/blender/imbuf/intern/imbuf_cocoa.m +++ /dev/null @@ -1,384 +0,0 @@ -/* - * ***** 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. - * - * Contributor(s): Damien Plisson 10/2009 - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/imbuf/intern/imbuf_cocoa.m - * \ingroup imbuf - * - * Provides image file loading and saving for Blender, via Cocoa. - */ - -#include -#include -#import - -#include "imbuf.h" - -#include "IMB_cocoa.h" - -#include "BKE_global.h" -#include "BKE_colortools.h" - -#include "IMB_imbuf_types.h" -#include "IMB_imbuf.h" - -#include "IMB_allocimbuf.h" - - - -#pragma mark load/save functions - -/** - * Loads an image from the supplied buffer - * - * Loads any Core Graphics supported type - * Currently is : TIFF, BMP, JPEG, GIF, PNG, DIB, ICO, and various RAW formats - * - * \param mem: Memory containing the bitmap image - * \param size: Size of the mem buffer. - * \param flags: If flags has IB_test set then the file is not actually loaded, - * but all other operations take place. - * - * \return: A newly allocated ImBuf structure if successful, otherwise NULL. - */ -struct ImBuf *imb_cocoaLoadImage(unsigned char *mem, int size, int flags) -{ - struct ImBuf *ibuf = NULL; - NSSize bitmapSize; - uchar *rasterRGB = NULL; - uchar *rasterRGBA = NULL; - uchar *toIBuf = NULL; - int x, y, to_i, from_i; - NSData *data; - NSBitmapImageRep *bitmapImage; - NSBitmapImageRep *blBitmapFormatImageRGB,*blBitmapFormatImageRGBA; - NSAutoreleasePool *pool; - - pool = [[NSAutoreleasePool alloc] init]; - - data = [NSData dataWithBytes:mem length:size]; - bitmapImage = [[NSBitmapImageRep alloc] initWithData:data]; - - if (!bitmapImage) { - fprintf(stderr, "imb_cocoaLoadImage: error loading image\n"); - [pool drain]; - return NULL; - } - - bitmapSize.width = [bitmapImage pixelsWide]; - bitmapSize.height = [bitmapImage pixelsHigh]; - - /* Tell cocoa image resolution is same as current system one */ - [bitmapImage setSize:bitmapSize]; - - /* allocate the image buffer */ - ibuf = IMB_allocImBuf(bitmapSize.width, bitmapSize.height, 32/*RGBA*/, 0); - if (!ibuf) { - fprintf(stderr, - "imb_cocoaLoadImage: could not allocate memory for the image.\n"); - [bitmapImage release]; - [pool drain]; - return NULL; - } - - /* read in the image data */ - if (!(flags & IB_test)) { - - /* allocate memory for the ibuf->rect */ - imb_addrectImBuf(ibuf); - - /* Convert the image in a RGBA 32bit format */ - /* As Core Graphics does not support contextes with non premutliplied alpha, - we need to get alpha key values in a separate batch */ - - /* First get RGB values w/o Alpha to avoid pre-multiplication, 32bit but last byte is unused */ - blBitmapFormatImageRGB = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL - pixelsWide:bitmapSize.width - pixelsHigh:bitmapSize.height - bitsPerSample:8 samplesPerPixel:3 hasAlpha:NO isPlanar:NO - colorSpaceName:NSCalibratedRGBColorSpace - bitmapFormat:0 - bytesPerRow:4*bitmapSize.width - bitsPerPixel:32/*RGB format padded to 32bits*/]; - - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:blBitmapFormatImageRGB]]; - [bitmapImage draw]; - [NSGraphicsContext restoreGraphicsState]; - - rasterRGB = (uchar*)[blBitmapFormatImageRGB bitmapData]; - if (rasterRGB == NULL) { - [bitmapImage release]; - [blBitmapFormatImageRGB release]; - [pool drain]; - return NULL; - } - - /* Then get Alpha values by getting the RGBA image (that is premultiplied btw) */ - blBitmapFormatImageRGBA = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL - pixelsWide:bitmapSize.width - pixelsHigh:bitmapSize.height - bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES isPlanar:NO - colorSpaceName:NSCalibratedRGBColorSpace - bitmapFormat:0 - bytesPerRow:4*bitmapSize.width - bitsPerPixel:32/* RGBA */]; - - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:blBitmapFormatImageRGBA]]; - [bitmapImage draw]; - [NSGraphicsContext restoreGraphicsState]; - - rasterRGBA = (uchar*)[blBitmapFormatImageRGBA bitmapData]; - if (rasterRGBA == NULL) { - [bitmapImage release]; - [blBitmapFormatImageRGB release]; - [blBitmapFormatImageRGBA release]; - [pool drain]; - return NULL; - } - - /*Copy the image to ibuf, flipping it vertically*/ - toIBuf = (uchar*)ibuf->rect; - for (x = 0; x < bitmapSize.width; x++) { - for (y = 0; y < bitmapSize.height; y++) { - to_i = (bitmapSize.height-y-1)*bitmapSize.width + x; - from_i = y*bitmapSize.width + x; - - toIBuf[4*to_i] = rasterRGB[4*from_i]; /* R */ - toIBuf[4*to_i+1] = rasterRGB[4*from_i+1]; /* G */ - toIBuf[4*to_i+2] = rasterRGB[4*from_i+2]; /* B */ - toIBuf[4*to_i+3] = rasterRGBA[4*from_i+3]; /* A */ - } - } - - [blBitmapFormatImageRGB release]; - [blBitmapFormatImageRGBA release]; - } - - /* release the cocoa objects */ - [bitmapImage release]; - [pool drain]; - - if (ENDIAN_ORDER == B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf); - - ibuf->ftype = TIF; - ibuf->profile = IB_PROFILE_SRGB; - - /* return successfully */ - return (ibuf); -} - -/** - * Saves an image to a file. - * - * ImBuf structures with 1, 3 or 4 bytes per pixel (GRAY, RGB, RGBA - * respectively) are accepted, and interpreted correctly. - * - * Accepted formats: TIFF, GIF, BMP, PNG, JPEG, JPEG2000 - * - * \param ibuf: Image buffer. - * \param name: Name of the image file to create. - * \param flags: Currently largely ignored. - * - * \return: 1 if the function is successful, 0 on failure. - */ - -#define FTOUSHORT(val) ((val >= 1.0f-0.5f/65535)? 65535: (val <= 0.0f)? 0: (unsigned short)(val*65535.0f + 0.5f)) - -short imb_cocoaSaveImage(struct ImBuf *ibuf, char *name, int flags) -{ - uint16_t samplesperpixel, bitspersample; - unsigned char *from = NULL, *to = NULL; - unsigned short *to16 = NULL; - float *fromf = NULL; - int x, y, from_i, to_i, i; - int success; - BOOL hasAlpha; - NSString* colorSpace; - NSBitmapImageRep *blBitmapFormatImage; - NSData *dataToWrite; - NSDictionary *imageProperties; - - NSAutoreleasePool *pool; - - if (!ibuf) return FALSE; - if (!name) return FALSE; - - /* check for a valid number of bytes per pixel. Like the PNG writer, - * the TIFF writer supports 1, 3 or 4 bytes per pixel, corresponding - * to gray, RGB, RGBA respectively. */ - samplesperpixel = (uint16_t)((ibuf->planes + 7) >> 3); - switch (samplesperpixel) { - case 4: /*RGBA type*/ - hasAlpha = YES; - colorSpace = NSCalibratedRGBColorSpace; - break; - case 3: /*RGB type*/ - hasAlpha = NO; - colorSpace = NSCalibratedRGBColorSpace; - break; - case 1: - hasAlpha = NO; - colorSpace = NSCalibratedWhiteColorSpace; - break; - default: - fprintf(stderr, - "imb_cocoaSaveImage: unsupported number of bytes per " - "pixel: %d\n", samplesperpixel); - return (0); - } - - if((ibuf->ftype & TIF_16BIT) && ibuf->rect_float) - bitspersample = 16; - else - bitspersample = 8; - - pool = [[NSAutoreleasePool alloc] init]; - - /* Create bitmap image rep in blender format */ - blBitmapFormatImage = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL - pixelsWide:ibuf->x - pixelsHigh:ibuf->y - bitsPerSample:bitspersample samplesPerPixel:samplesperpixel hasAlpha:hasAlpha isPlanar:NO - colorSpaceName:colorSpace - bitmapFormat:NSAlphaNonpremultipliedBitmapFormat - bytesPerRow:(ibuf->x*bitspersample*samplesperpixel/8) - bitsPerPixel:(bitspersample*samplesperpixel)]; - if (!blBitmapFormatImage) { - [pool drain]; - return FALSE; - } - - /* setup pointers */ - if(bitspersample == 16) { - fromf = ibuf->rect_float; - to16 = (unsigned short*)[blBitmapFormatImage bitmapData]; - } - else { - from = (unsigned char*)ibuf->rect; - to = (unsigned char*)[blBitmapFormatImage bitmapData]; - } - - /* copy pixel data. While copying, we flip the image vertically. */ - for (x = 0; x < ibuf->x; x++) { - for (y = 0; y < ibuf->y; y++) { - from_i = 4*(y*ibuf->x+x); - to_i = samplesperpixel*((ibuf->y-y-1)*ibuf->x+x); - - if(bitspersample == 16) { - if (ibuf->profile == IB_PROFILE_SRGB) { - switch (samplesperpixel) { - case 4 /*RGBA*/: - to16[to_i] = FTOUSHORT(linearrgb_to_srgb(fromf[from_i])); - to16[to_i+1] = FTOUSHORT(linearrgb_to_srgb(fromf[from_i+1])); - to16[to_i+2] = FTOUSHORT(linearrgb_to_srgb(fromf[from_i+2])); - to16[to_i+3] = FTOUSHORT(fromf[from_i+3]); - break; - case 3 /*RGB*/: - to16[to_i] = FTOUSHORT(linearrgb_to_srgb(fromf[from_i])); - to16[to_i+1] = FTOUSHORT(linearrgb_to_srgb(fromf[from_i+1])); - to16[to_i+2] = FTOUSHORT(linearrgb_to_srgb(fromf[from_i+2])); - break; - case 1 /*BW*/: - to16[to_i] = FTOUSHORT(linearrgb_to_srgb(fromf[from_i])); - break; - } - } - else { - for (i = 0; i < samplesperpixel; i++, to_i++, from_i++) - to16[to_i] = FTOUSHORT(fromf[from_i]); - } - } - else { - /* 8bits per sample*/ - for (i = 0; i < samplesperpixel; i++, to_i++, from_i++) - to[to_i] = from[from_i]; - } - } - } - - /* generate file data */ - if (IS_tiff(ibuf)) { - dataToWrite = [blBitmapFormatImage TIFFRepresentationUsingCompression:NSTIFFCompressionLZW factor:1.0]; - } - else if (IS_png(ibuf)) { - imageProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:false], NSImageInterlaced, - nil]; - dataToWrite = [blBitmapFormatImage representationUsingType:NSPNGFileType properties:imageProperties]; - } - else if (IS_bmp(ibuf)) { - dataToWrite = [blBitmapFormatImage representationUsingType:NSBMPFileType properties:nil]; - } - else {/* JPEG by default */ - int quality; - - quality = ibuf->ftype & 0xff; - if (quality <= 0) quality = 90; /* Standard quality if wrong supplied*/ - if (quality > 100) quality = 100; - - imageProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithFloat:quality], NSImageCompressionFactor, - [NSNumber numberWithBool:true], NSImageProgressive, - nil]; - dataToWrite = [blBitmapFormatImage representationUsingType:NSJPEGFileType properties:imageProperties]; - } - - /* Write the file */ - success = [dataToWrite writeToFile:[NSString stringWithCString:name encoding:NSISOLatin1StringEncoding] - atomically:YES]; - - [blBitmapFormatImage release]; - [pool drain]; - - return success; -} - -#pragma mark format checking functions - -/* Currently, only tiff format is handled, so need to include here function that was previously in tiff.c */ - -/** - * Checks whether a given memory buffer contains a TIFF file. - * - * FIXME: Possible memory leak if mem is less than IMB_TIFF_NCB bytes long. - * However, changing this will require up-stream modifications. - * - * This method uses the format identifiers from: - * http://www.faqs.org/faqs/graphics/fileformats-faq/part4/section-9.html - * The first four bytes of big-endian and little-endian TIFF files - * respectively are (hex): - * 4d 4d 00 2a - * 49 49 2a 00 - * Note that TIFF files on *any* platform can be either big- or little-endian; - * it's not platform-specific. - * - * AFAICT, libtiff doesn't provide a method to do this automatically, and - * hence my manual comparison. - Jonathan Merritt (lancelet) 4th Sept 2005. - */ -#define IMB_TIFF_NCB 4 /* number of comparison bytes used */ -int imb_is_a_tiff(void *mem) -{ - char big_endian[IMB_TIFF_NCB] = { 0x4d, 0x4d, 0x00, 0x2a }; - char lil_endian[IMB_TIFF_NCB] = { 0x49, 0x49, 0x2a, 0x00 }; - - return ( (memcmp(big_endian, mem, IMB_TIFF_NCB) == 0) || - (memcmp(lil_endian, mem, IMB_TIFF_NCB) == 0) ); -} diff --git a/source/blender/imbuf/intern/iris.c b/source/blender/imbuf/intern/iris.c index e76a59905cb..13b0fc1b55a 100644 --- a/source/blender/imbuf/intern/iris.c +++ b/source/blender/imbuf/intern/iris.c @@ -522,15 +522,13 @@ struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags) } - if (ibuf) { - ibuf->ftype = IMAGIC; - ibuf->profile = IB_PROFILE_SRGB; + ibuf->ftype = IMAGIC; + ibuf->profile = IB_PROFILE_SRGB; - test_endian_zbuf(ibuf); + test_endian_zbuf(ibuf); - if (ibuf->rect) { - IMB_convert_rgba_to_abgr(ibuf); - } + if (ibuf->rect) { + IMB_convert_rgba_to_abgr(ibuf); } return(ibuf); diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 8a2374060cf..307982e4bb1 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -556,7 +556,7 @@ Mask *rna_Main_mask_new(Main *UNUSED(bmain), const char *name) void rna_Main_masks_remove(Main *bmain, Mask *mask) { - BKE_mask_unlink(bmain, mask); + BKE_mask_free(bmain, mask); BKE_libblock_free(&bmain->mask, mask); /* XXX python now has invalid pointer? */ } diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index f8626d36e87..c9960df1345 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -789,7 +789,6 @@ static void force_hidden_passes(bNode *node, int passflag) if (!(passflag & SCE_PASS_TRANSM_INDIRECT)) sock->flag |= SOCK_UNAVAIL; sock= BLI_findlink(&node->outputs, RRES_OUT_TRANSM_COLOR); if (!(passflag & SCE_PASS_TRANSM_COLOR)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_TRANSM_COLOR); } /* based on rules, force sockets hidden always */ diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index ebacdee0c97..2d694a3e274 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -246,32 +246,24 @@ void RE_make_stars(Render *re, Scene *scenev3d, void (*initfunc)(void), done++; } else { - mul_m4_v3(re->viewmat, vec); + if (re) + mul_m4_v3(re->viewmat, vec); /* in vec are global coordinates * calculate distance to camera * and using that, define the alpha */ - - { - float tx, ty, tz; - - tx = vec[0]; - ty = vec[1]; - tz = vec[2]; - - alpha = sqrt(tx * tx + ty * ty + tz * tz); - - if (alpha >= clipend) alpha = 0.0; - else if (alpha <= starmindist) alpha = 0.0; - else if (alpha <= 2.0f * starmindist) { - alpha = (alpha - starmindist) / starmindist; - } - else { - alpha -= 2.0f * starmindist; - alpha /= (clipend - 2.0f * starmindist); - alpha = 1.0f - alpha; - } + alpha = len_v3(vec); + + if (alpha >= clipend) alpha = 0.0; + else if (alpha <= starmindist) alpha = 0.0; + else if (alpha <= 2.0f * starmindist) { + alpha = (alpha - starmindist) / starmindist; + } + else { + alpha -= 2.0f * starmindist; + alpha /= (clipend - 2.0f * starmindist); + alpha = 1.0f - alpha; } diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp index 92c390efd39..06251cd2282 100644 --- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp +++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp @@ -431,7 +431,7 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas) // reverting to texunit 0, without this we get bug [#28462] glActiveTextureARB(GL_TEXTURE0); - glViewport(rect.GetLeft(), rect.GetBottom(), rect_width, rect.GetHeight()+1); + glViewport(rect.GetLeft(), rect.GetBottom(), rect_width, rect_height); glDisable(GL_DEPTH_TEST); // in case the previous material was wire From d7f55cff20ff31e80d95c7837e9b45205dea273f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 14 Sep 2012 14:36:47 +0000 Subject: [PATCH 144/160] Color Management: image buffer loading reworked Before this color space settings in image/movie clip data blocks defined space in which loaded image buffer is, based on whether this buffer contains float or byte buffer. This didn't work well for formats like 16bit PNG, which are in fact non-linear formats but were represented in Blender as float buffers. Now image buffer loader is responsible to set up input default color space for image/movie clip data blocks, which could be based on format itself only or on particular file properties. This means image/movie clip data blocks' input colorspace will be initialized at time first image buffer is loaded. This also resolves old confusing thing with image buffer's profile flag, which in could have been non-linear for image buffer which contained float buffer only -- this happened in mentioned case of 16 bit PNG format, i.e. Now float buffer would always be linear which should make it easier to get rid of image buffer's profile. --- source/blender/blenkernel/BKE_image.h | 4 +- source/blender/blenkernel/intern/image.c | 23 +-- source/blender/blenkernel/intern/movieclip.c | 17 +-- source/blender/blenkernel/intern/ocean.c | 7 +- source/blender/blenkernel/intern/sequencer.c | 24 ++-- source/blender/collada/ImageExporter.cpp | 2 +- .../editors/interface/interface_icons.c | 6 +- .../blender/editors/render/render_preview.c | 9 +- source/blender/editors/space_file/filelist.c | 2 +- .../blender/editors/space_image/image_ops.c | 12 +- source/blender/imbuf/IMB_colormanagement.h | 10 +- source/blender/imbuf/IMB_imbuf.h | 13 +- source/blender/imbuf/intern/IMB_anim.h | 1 + .../imbuf/intern/IMB_colormanagement_intern.h | 6 + source/blender/imbuf/intern/IMB_filetype.h | 25 ++-- source/blender/imbuf/intern/anim_movie.c | 33 ++++- source/blender/imbuf/intern/bmp.c | 7 +- .../blender/imbuf/intern/cineon/cineon_dpx.c | 15 +- source/blender/imbuf/intern/colormanagement.c | 133 +++++++++--------- source/blender/imbuf/intern/dds/dds_api.cpp | 11 +- source/blender/imbuf/intern/dds/dds_api.h | 4 +- source/blender/imbuf/intern/filetype.c | 30 ++-- source/blender/imbuf/intern/indexer.c | 3 +- source/blender/imbuf/intern/iris.c | 8 +- source/blender/imbuf/intern/jp2.c | 8 +- source/blender/imbuf/intern/jpeg.c | 9 +- .../imbuf/intern/openexr/openexr_api.cpp | 7 +- .../imbuf/intern/openexr/openexr_api.h | 2 +- source/blender/imbuf/intern/png.c | 37 ++--- source/blender/imbuf/intern/radiance_hdr.c | 7 +- source/blender/imbuf/intern/readimage.c | 38 +++-- source/blender/imbuf/intern/targa.c | 8 +- source/blender/imbuf/intern/thumbs.c | 11 +- source/blender/imbuf/intern/tiff.c | 8 +- source/blender/imbuf/intern/writeimage.c | 36 ++++- .../blender/makesrna/intern/rna_image_api.c | 2 + .../makesrna/intern/rna_sequencer_api.c | 3 +- .../blender/render/intern/source/pipeline.c | 3 +- .../windowmanager/intern/wm_operators.c | 2 +- .../windowmanager/intern/wm_playanim.c | 20 ++- 40 files changed, 385 insertions(+), 221 deletions(-) diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 4f1e48e345d..ac324b2af00 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -46,6 +46,8 @@ struct Object; struct ImageFormatData; struct Main; +#define IMA_MAX_SPACE 64 + /* call from library */ void BKE_image_free(struct Image *me); @@ -73,7 +75,7 @@ char BKE_imtype_from_arg(const char *arg); void BKE_imformat_defaults(struct ImageFormatData *im_format); void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const struct ImBuf *imbuf); -struct anim *openanim(const char *name, int flags, int streamindex); +struct anim *openanim(const char *name, int flags, int streamindex, char colorspace[IMA_MAX_SPACE]); void BKE_image_de_interlace(struct Image *ima, int odd); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 0949f54642d..ce3e99a0807 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -304,12 +304,6 @@ static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int frame) else ibuf->flags &= ~IB_cm_predivide; - if (ima->source == IMA_SRC_GENERATED) { - /* for other image types spaces are set by image_initialize_after_load */ - - IMB_colormanagement_imbuf_assign_spaces(ibuf, &ima->colorspace_settings); - } - /* this function accepts (link == NULL) */ BLI_insertlinkbefore(&ima->ibufs, link, ibuf); @@ -1910,12 +1904,12 @@ void BKE_makepicstring(char *string, const char *base, const char *relbase, int } /* used by sequencer too */ -struct anim *openanim(const char *name, int flags, int streamindex) +struct anim *openanim(const char *name, int flags, int streamindex, char colorspace[IMA_MAX_SPACE]) { struct anim *anim; struct ImBuf *ibuf; - anim = IMB_open_anim(name, flags, streamindex); + anim = IMB_open_anim(name, flags, streamindex, colorspace); if (anim == NULL) return NULL; ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); @@ -2224,9 +2218,6 @@ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr) /* common stuff to do with images after loading */ static void image_initialize_after_load(Image *ima, ImBuf *ibuf) { - /* make float buffer stored in ImBuf scene linear space */ - IMB_colormanagement_imbuf_make_scene_linear(ibuf, &ima->colorspace_settings); - /* preview is NULL when it has never been used as an icon before */ if (G.background == 0 && ima->preview == NULL) BKE_icon_changed(BKE_icon_getid(&ima->id)); @@ -2261,7 +2252,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) flag |= IB_premul; /* read ibuf */ - ibuf = IMB_loadiffname(name, flag); + ibuf = IMB_loadiffname(name, flag, ima->colorspace_settings.name); #if 0 if (ibuf) { @@ -2369,7 +2360,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) BKE_image_user_file_path(iuser, ima, str); /* FIXME: make several stream accessible in image editor, too*/ - ima->anim = openanim(str, IB_rect, 0); + ima->anim = openanim(str, IB_rect, 0, ima->colorspace_settings.name); /* let's initialize this user */ if (ima->anim && iuser && iuser->frames == 0) @@ -2420,8 +2411,8 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) flag = IB_rect | IB_multilayer; if (ima->flag & IMA_DO_PREMUL) flag |= IB_premul; - ibuf = IMB_ibImageFromMemory((unsigned char *)ima->packedfile->data, - ima->packedfile->size, flag, ""); + ibuf = IMB_ibImageFromMemory((unsigned char *)ima->packedfile->data, ima->packedfile->size, flag, + ima->colorspace_settings.name, ""); } else { flag = IB_rect | IB_multilayer | IB_metadata; @@ -2433,7 +2424,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) BKE_image_user_file_path(iuser, ima, str); /* read ibuf */ - ibuf = IMB_loadiffname(str, flag); + ibuf = IMB_loadiffname(str, flag, ima->colorspace_settings.name); } if (ibuf) { diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index e83e6974102..cd8b0e4e52c 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -199,19 +199,25 @@ static ImBuf *movieclip_load_sequence_file(MovieClip *clip, MovieClipUser *user, struct ImBuf *ibuf; char name[FILE_MAX]; int loadflag, use_proxy = FALSE; + char *colorspace; use_proxy = (flag & MCLIP_USE_PROXY) && user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL; if (use_proxy) { int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT; get_proxy_fname(clip, user->render_size, undistort, framenr, name); + + /* proxies were built using default color space settings */ + colorspace = NULL; } - else + else { get_sequence_fname(clip, framenr, name); + colorspace = clip->colorspace_settings.name; + } loadflag = IB_rect | IB_multilayer; /* read ibuf */ - ibuf = IMB_loadiffname(name, loadflag); + ibuf = IMB_loadiffname(name, loadflag, colorspace); return ibuf; } @@ -225,7 +231,7 @@ static void movieclip_open_anim_file(MovieClip *clip) BLI_path_abs(str, ID_BLEND_PATH(G.main, &clip->id)); /* FIXME: make several stream accessible in image editor, too */ - clip->anim = openanim(str, IB_rect, 0); + clip->anim = openanim(str, IB_rect, 0, clip->colorspace_settings.name); if (clip->anim) { if (clip->flag & MCLIP_USE_PROXY_CUSTOM_DIR) { @@ -781,11 +787,6 @@ static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip, MovieClipUser *u ibuf = movieclip_load_movie_file(clip, user, framenr, flag); } - if (ibuf) { - /* make float buffer stored in ImBuf scene linear space */ - IMB_colormanagement_imbuf_make_scene_linear(ibuf, &clip->colorspace_settings); - } - if (ibuf && (cache_flag & MOVIECLIP_CACHE_SKIP) == 0) put_imbuf_cache(clip, user, ibuf, flag); } diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index b862a824d50..46b89f76194 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -1117,19 +1117,20 @@ void BKE_simulate_ocean_cache(struct OceanCache *och, int frame) /* if image is already loaded in mem, return */ if (och->ibufs_disp[f] != NULL) return; + /* use default color spaces since we know for sure cache files were saved with default settings too */ cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_DISPLACE); - och->ibufs_disp[f] = IMB_loadiffname(string, 0); + och->ibufs_disp[f] = IMB_loadiffname(string, 0, NULL); //if (och->ibufs_disp[f] == NULL) printf("error loading %s\n", string); //else printf("loaded cache %s\n", string); cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_FOAM); - och->ibufs_foam[f] = IMB_loadiffname(string, 0); + och->ibufs_foam[f] = IMB_loadiffname(string, 0, NULL); //if (och->ibufs_foam[f] == NULL) printf("error loading %s\n", string); //else printf("loaded cache %s\n", string); cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_NORMAL); - och->ibufs_norm[f] = IMB_loadiffname(string, 0); + och->ibufs_norm[f] = IMB_loadiffname(string, 0, NULL); //if (och->ibufs_norm[f] == NULL) printf("error loading %s\n", string); //else printf("loaded cache %s\n", string); } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 0d8b220dd00..1d4efb01aa2 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -686,7 +686,9 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, int lock_range) BLI_path_abs(str, G.main->name); if (seq->anim) IMB_free_anim(seq->anim); - seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), seq->streamindex); + + /* OCIO_TODO: support configurable input space for strips */ + seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), seq->streamindex, NULL); if (!seq->anim) { return; @@ -1183,7 +1185,8 @@ static void seq_open_anim_file(Sequence *seq) seq->strip->dir, seq->strip->stripdata->name); BLI_path_abs(name, G.main->name); - seq->anim = openanim(name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), seq->streamindex); + /* OCIO_TODO: support configurable input space for strips */ + seq->anim = openanim(name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), seq->streamindex, NULL); if (seq->anim == NULL) { return; @@ -1289,8 +1292,9 @@ static ImBuf *seq_proxy_fetch(SeqRenderData context, Sequence *seq, int cfra) if (seq_proxy_get_fname(seq, cfra, render_size, name) == 0) { return NULL; } - - seq->strip->proxy->anim = openanim(name, IB_rect, 0); + + /* proxies are generated in default color space */ + seq->strip->proxy->anim = openanim(name, IB_rect, 0, NULL); } if (seq->strip->proxy->anim == NULL) { return NULL; @@ -1308,7 +1312,8 @@ static ImBuf *seq_proxy_fetch(SeqRenderData context, Sequence *seq, int cfra) } if (BLI_exists(name)) { - ImBuf *ibuf = IMB_loadiffname(name, IB_rect); + /* OCIO_TODO: support configurable spaces for strips */ + ImBuf *ibuf = IMB_loadiffname(name, IB_rect, NULL); if (ibuf) BKE_sequencer_imbuf_assign_spaces(context.scene, ibuf); @@ -1351,7 +1356,8 @@ static void seq_proxy_build_frame(SeqRenderData context, Sequence *seq, int cfra ibuf->planes = 24; BLI_make_existing_file(name); - + + /* OCIO_TODO: support per-strip color space settings */ ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat); if (ok == 0) { perror(name); @@ -2536,7 +2542,8 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo BLI_path_abs(name, G.main->name); } - if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect))) { + /* OCIO_TODO: support configurable space for image strips */ + if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect, NULL))) { /* we don't need both (speed reasons)! */ if (ibuf->rect_float && ibuf->rect) imb_freerectImBuf(ibuf); @@ -4046,7 +4053,8 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad BLI_strncpy(path, seq_load->path, sizeof(path)); BLI_path_abs(path, G.main->name); - an = openanim(path, IB_rect, 0); + /* OCIO_TODO: support configurable input space for strips */ + an = openanim(path, IB_rect, 0, NULL); if (an == NULL) return NULL; diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp index 1af34bfa7b7..41d3c790dd0 100644 --- a/source/blender/collada/ImageExporter.cpp +++ b/source/blender/collada/ImageExporter.cpp @@ -102,7 +102,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) // So we have to export it. The export will keep the image state intact, // so the exported file will not be associated with the image. - if (BKE_imbuf_write_as(imbuf, export_path, &imageFormat, true) == 0) { + if (BKE_imbuf_write_as(imbuf, export_path, &imageFormat, image->colorspace_settings.name, true) == 0) { fprintf(stderr, "Collada export: Cannot export image to:\n%s\n", export_path); return; } diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index f6f12f98181..0921107b8e6 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -466,7 +466,7 @@ static void init_brush_icons(void) { \ bbuf = IMB_ibImageFromMemory((unsigned char *)datatoc_ ##name## _png, \ datatoc_ ##name## _png_size, \ - IB_rect, ""); \ + IB_rect, NULL, ""); \ def_internal_icon(bbuf, icon_id, 0, 0, w, ICON_TYPE_BUFFER); \ IMB_freeImBuf(bbuf); \ } (void)0 @@ -520,7 +520,7 @@ static void init_internal_icons(void) char *icondir = BLI_get_folder(BLENDER_DATAFILES, "icons"); if (icondir) { BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile); - bbuf = IMB_loadiffname(iconfilestr, IB_rect); /* if the image is missing bbuf will just be NULL */ + bbuf = IMB_loadiffname(iconfilestr, IB_rect, NULL); /* if the image is missing bbuf will just be NULL */ if (bbuf && (bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H)) { printf("\n***WARNING***\nIcons file %s too small.\nUsing built-in Icons instead\n", iconfilestr); IMB_freeImBuf(bbuf); @@ -533,7 +533,7 @@ static void init_internal_icons(void) } if (bbuf == NULL) bbuf = IMB_ibImageFromMemory((unsigned char *)datatoc_blender_icons_png, - datatoc_blender_icons_png_size, IB_rect, ""); + datatoc_blender_icons_png_size, IB_rect, NULL, ""); if (bbuf) { /* free existing texture if any */ diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 38117aae4c5..4b8411ea8a1 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -118,7 +118,8 @@ ImBuf *get_brush_icon(Brush *brush) BLI_strncpy(path, brush->icon_filepath, sizeof(brush->icon_filepath)); BLI_path_abs(path, G.main->name); - brush->icon_imbuf = IMB_loadiffname(path, flags); + /* use default colorspaces for brushes */ + brush->icon_imbuf = IMB_loadiffname(path, flags, NULL); // otherwise lets try to find it in other directories if (!(brush->icon_imbuf)) { @@ -126,8 +127,10 @@ ImBuf *get_brush_icon(Brush *brush) BLI_make_file_string(G.main->name, path, folder, brush->icon_filepath); - if (path[0]) - brush->icon_imbuf = IMB_loadiffname(path, flags); + if (path[0]) { + /* use fefault color spaces */ + brush->icon_imbuf = IMB_loadiffname(path, flags, NULL); + } } if (brush->icon_imbuf) diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 337e13f7785..d3b4df05aa9 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -389,7 +389,7 @@ void filelist_init_icons(void) #ifdef WITH_HEADLESS bbuf = NULL; #else - bbuf = IMB_ibImageFromMemory((unsigned char *)datatoc_prvicons_png, datatoc_prvicons_png_size, IB_rect, ""); + bbuf = IMB_ibImageFromMemory((unsigned char *)datatoc_prvicons_png, datatoc_prvicons_png_size, IB_rect, NULL, ""); #endif if (bbuf) { for (y = 0; y < SPECIAL_IMG_ROWS; y++) { diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 857d0179158..563680f5743 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1212,15 +1212,12 @@ static ImBuf *save_image_colormanaged_imbuf_acquire(ImBuf *ibuf, SaveImageOption int do_colormanagement; *cache_handle = NULL; - do_colormanagement = !BKE_imtype_supports_float(imf->imtype); + do_colormanagement = save_as_render && !BKE_imtype_supports_float(imf->imtype); if (do_colormanagement) { unsigned char *display_buffer; - if (save_as_render) - display_buffer = IMB_display_buffer_acquire(ibuf, &imf->view_settings, &imf->display_settings, cache_handle); - else - display_buffer = IMB_display_buffer_acquire(ibuf, NULL, &imf->display_settings, cache_handle); + display_buffer = IMB_display_buffer_acquire(ibuf, &imf->view_settings, &imf->display_settings, cache_handle); if (*cache_handle) { colormanaged_ibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, 0); @@ -1295,7 +1292,8 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI BKE_image_release_renderresult(scene, ima); } else { - if (BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, &simopts->im_format, save_copy)) { + if (BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, &simopts->im_format, save_copy)) + { ok = TRUE; } } @@ -1334,6 +1332,8 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI if (relative) { BLI_path_rel(ima->name, relbase); /* only after saving */ } + + IMB_colormanagment_colorspace_from_ibuf_ftype(&ima->colorspace_settings, ibuf); } } else { diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 0dc826439c4..cd88371c0c0 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -88,17 +88,15 @@ void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float void IMB_colormanagement_pixel_to_role_v4(float pixel[4], int role); void IMB_colormanagement_pixel_from_role_v4(float pixel[4], int role); -void IMB_colormanagement_imbuf_to_role(struct ImBuf *ibuf, int role); -void IMB_colormanagement_imbuf_from_role(struct ImBuf *ibuf, int role); - void IMB_colormanagement_imbuf_assign_spaces(struct ImBuf *ibuf, struct ColorManagedColorspaceSettings *colorspace_settings); +void IMB_colormanagement_imbuf_assign_default_spaces(struct ImBuf *ibuf); void IMB_colormanagement_imbuf_assign_float_space(struct ImBuf *ibuf, struct ColorManagedColorspaceSettings *colorspace_settings); -void IMB_colormanagement_imbuf_make_scene_linear(struct ImBuf *ibuf, struct ColorManagedColorspaceSettings *colorspace_settings); - void IMB_colormanagement_imbuf_make_display_space(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings); +void IMB_colormanagement_imbuf_make_colorspace(struct ImBuf *ibuf, const char *to_colorspace, int flag); + /* ** Public display buffers interfaces ** */ unsigned char *IMB_display_buffer_acquire(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, @@ -129,6 +127,8 @@ int IMB_colormanagement_colorspace_get_named_index(const char *name); const char *IMB_colormanagement_colorspace_get_indexed_name(int index); const char *IMB_colormanagement_view_get_default_name(const char *display_name); +void IMB_colormanagment_colorspace_from_ibuf_ftype(struct ColorManagedColorspaceSettings *colorspace_settings, struct ImBuf *ibuf); + /* ** RNA helper functions ** */ void IMB_colormanagement_display_items_add(struct EnumPropertyItem **items, int *totitem); void IMB_colormanagement_view_items_add(struct EnumPropertyItem **items, int *totitem, const char *display_name); diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 71c8f197b0e..a8780d3f205 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -70,6 +70,8 @@ #ifndef __IMB_IMBUF_H__ #define __IMB_IMBUF_H__ +#define IM_MAX_SPACE 64 + /** * * \attention defined in ??? @@ -95,20 +97,19 @@ void IMB_exit(void); * * \attention Defined in readimage.c */ -struct ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, - int flags, const char *descr); +struct ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE], const char *descr); /** * * \attention Defined in readimage.c */ -struct ImBuf *IMB_testiffname(const char *filepath, int flags); +struct ImBuf *IMB_testiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE]); /** * * \attention Defined in readimage.c */ -struct ImBuf *IMB_loadiffname(const char *filepath, int flags); +struct ImBuf *IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE]); /** * @@ -247,7 +248,7 @@ int IMB_anim_get_fps(struct anim * anim, * * \attention Defined in anim_movie.c */ -struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex); +struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex, char colorspace[IM_MAX_SPACE]); void IMB_close_anim(struct anim *anim); void IMB_close_anim_proxies(struct anim *anim); @@ -419,7 +420,7 @@ void bilinear_interpolation_color_wrap(struct ImBuf *in, unsigned char *col, flo * * \attention defined in readimage.c */ -struct ImBuf *IMB_loadifffile(int file, int flags, const char *descr); +struct ImBuf *IMB_loadifffile(int file, int flags, char colorspace[IM_MAX_SPACE], const char *descr); /** * diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h index 571c54b9cb3..d5cc4929aed 100644 --- a/source/blender/imbuf/intern/IMB_anim.h +++ b/source/blender/imbuf/intern/IMB_anim.h @@ -191,6 +191,7 @@ struct anim { struct anim *proxy_anim[IMB_PROXY_MAX_SLOT]; struct anim_index *curr_idx[IMB_TC_MAX_SLOT]; + char colorspace[64]; }; #endif diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index 293314c3ccd..67c99d51fd4 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -36,6 +36,7 @@ #define BCM_CONFIG_FILE "config.ocio" struct ConstProcessorRcPtr; +struct ImBuf; typedef struct ColorSpace { struct ColorSpace *next, *prev; @@ -80,6 +81,11 @@ struct ColorManagedView *colormanage_view_get_named(const char *name); struct ColorSpace *colormanage_colorspace_add(const char *name, const char *description, int is_invertible); struct ColorSpace *colormanage_colorspace_get_named(const char *name); +struct ColorSpace *colormanage_colorspace_get_roled(int role); struct ColorSpace *colormanage_colorspace_get_indexed(int index); +void colorspace_set_default_role(char *colorspace, int size, int role); + +void colormanage_imbuf_make_linear(struct ImBuf *ibuf, const char *from_colorspace); + #endif /* IMB_COLORMANAGEMENT_INTERN_H */ diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h index 74d0a92f26b..56a03121409 100644 --- a/source/blender/imbuf/intern/IMB_filetype.h +++ b/source/blender/imbuf/intern/IMB_filetype.h @@ -40,12 +40,13 @@ typedef struct ImFileType { int (*is_a)(unsigned char *buf); int (*ftype)(struct ImFileType *type, struct ImBuf *ibuf); - struct ImBuf *(*load)(unsigned char *mem, size_t size, int flags); + struct ImBuf *(*load)(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); int (*save)(struct ImBuf *ibuf, const char *name, int flags); void (*load_tile)(struct ImBuf *ibuf, unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect); int flag; int filetype; + int default_save_role; } ImFileType; extern ImFileType IMB_FILE_TYPES[]; @@ -63,57 +64,57 @@ void imb_tile_cache_tile_free(struct ImBuf *ibuf, int tx, int ty); /* png */ int imb_is_a_png(unsigned char *buf); -struct ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags); +struct ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); int imb_savepng(struct ImBuf *ibuf, const char *name, int flags); /* targa */ int imb_is_a_targa(unsigned char *buf); -struct ImBuf *imb_loadtarga(unsigned char *mem, size_t size, int flags); +struct ImBuf *imb_loadtarga(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); int imb_savetarga(struct ImBuf * ibuf, const char *name, int flags); /* iris */ int imb_is_a_iris(unsigned char *mem); -struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags); +struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); int imb_saveiris(struct ImBuf * ibuf, const char *name, int flags); /* jp2 */ int imb_is_a_jp2(unsigned char *buf); -struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags); +struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); int imb_savejp2(struct ImBuf *ibuf, const char *name, int flags); /* jpeg */ int imb_is_a_jpeg(unsigned char *mem); int imb_savejpeg(struct ImBuf *ibuf, const char *name, int flags); -struct ImBuf * imb_load_jpeg (unsigned char * buffer, size_t size, int flags); +struct ImBuf * imb_load_jpeg (unsigned char * buffer, size_t size, int flags, char colorspace[IM_MAX_SPACE]); /* bmp */ int imb_is_a_bmp(unsigned char *buf); -struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags); +struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); int imb_savebmp(struct ImBuf *ibuf, const char *name, int flags); /* cocoa */ -struct ImBuf *imb_cocoaLoadImage(unsigned char *mem, size_t size, int flags); +struct ImBuf *imb_cocoaLoadImage(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); short imb_cocoaSaveImage(struct ImBuf *ibuf, const char *name, int flags); /* cineon */ int imb_savecineon(struct ImBuf *buf, const char *name, int flags); -struct ImBuf *imb_loadcineon(unsigned char *mem, size_t size, int flags); +struct ImBuf *imb_loadcineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); int imb_is_cineon(unsigned char *buf); /* dpx */ int imb_save_dpx(struct ImBuf *buf, const char *name, int flags); -struct ImBuf *imb_loaddpx(unsigned char *mem, size_t size, int flags); +struct ImBuf *imb_loaddpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); int imb_is_dpx(unsigned char *buf); /* hdr */ int imb_is_a_hdr(unsigned char *buf); -struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags); +struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); int imb_savehdr(struct ImBuf * ibuf, const char *name, int flags); /* tiff */ void imb_inittiff(void); int imb_is_a_tiff(unsigned char *buf); -struct ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags); +struct ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); void imb_loadtiletiff(struct ImBuf *ibuf, unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect); int imb_savetiff(struct ImBuf *ibuf, const char *name, int flags); diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index 16dbd0823da..fa8cc6c818a 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -113,6 +113,9 @@ #endif #endif +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" + int ismovie(const char *UNUSED(filepath)) { return 0; @@ -263,12 +266,20 @@ void IMB_close_anim_proxies(struct anim *anim) IMB_free_indices(anim); } -struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex) +struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex, char colorspace[IM_MAX_SPACE]) { struct anim *anim; anim = (struct anim *)MEM_callocN(sizeof(struct anim), "anim struct"); if (anim != NULL) { + if (colorspace) { + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + BLI_strncpy(anim->colorspace, colorspace, sizeof(anim->colorspace)); + } + else { + colorspace_set_default_role(anim->colorspace, sizeof(anim->colorspace), COLOR_ROLE_DEFAULT_BYTE); + } + BLI_strncpy(anim->name, name, sizeof(anim->name)); anim->ib_flags = ib_flags; anim->streamindex = streamindex; @@ -404,7 +415,7 @@ static ImBuf *avi_fetchibuf(struct anim *anim, int position) if (anim->pgf) { lpbi = AVIStreamGetFrame(anim->pgf, position + AVIStreamStart(anim->pavi[anim->firstvideo])); if (lpbi) { - ibuf = IMB_ibImageFromMemory((unsigned char *) lpbi, 100, IB_rect, ""); + ibuf = IMB_ibImageFromMemory((unsigned char *) lpbi, 100, IB_rect, anim->colorspace, ""); //Oh brother... } } @@ -433,7 +444,8 @@ static ImBuf *avi_fetchibuf(struct anim *anim, int position) } ibuf->profile = IB_PROFILE_SRGB; - + ibuf->rect_colorspace = colormanage_colorspace_get_named(anim->colorspace); + return ibuf; } @@ -1090,6 +1102,7 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_freeImBuf(anim->last_frame); anim->last_frame = IMB_allocImBuf(anim->x, anim->y, 32, IB_rect); + anim->last_frame->rect_colorspace = colormanage_colorspace_get_named(anim->colorspace); ffmpeg_postprocess(anim); @@ -1213,7 +1226,7 @@ static ImBuf *anim_getnew(struct anim *anim) switch (anim->curtype) { case ANIM_SEQUENCE: - ibuf = IMB_loadiffname(anim->name, anim->ib_flags); + ibuf = IMB_loadiffname(anim->name, anim->ib_flags, anim->colorspace); if (ibuf) { BLI_strncpy(anim->first, anim->name, sizeof(anim->first)); anim->duration = 1; @@ -1309,7 +1322,7 @@ struct ImBuf *IMB_anim_absolute(struct anim *anim, int position, pic = an_stringdec(anim->first, head, tail, &digits); pic += position; an_stringenc(anim->name, head, tail, digits, pic); - ibuf = IMB_loadiffname(anim->name, IB_rect); + ibuf = IMB_loadiffname(anim->name, IB_rect, anim->colorspace); if (ibuf) { anim->curposition = position; } @@ -1330,8 +1343,16 @@ struct ImBuf *IMB_anim_absolute(struct anim *anim, int position, #ifdef WITH_QUICKTIME case ANIM_QTIME: ibuf = qtime_fetchibuf(anim, position); - if (ibuf) + if (ibuf) { + if (ibuf->rect) { + /* OCIO_TODO: should happen in quicktime module, but it currently doesn't have access + * to color management's internals + */ + ibuf->rect_colorspace = colormanage_colorspace_get_named(anim->colorspace); + } + anim->curposition = position; + } break; #endif #ifdef WITH_FFMPEG diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c index 8fa468949e7..5e7b1b839e9 100644 --- a/source/blender/imbuf/intern/bmp.c +++ b/source/blender/imbuf/intern/bmp.c @@ -38,6 +38,9 @@ #include "IMB_allocimbuf.h" #include "IMB_filetype.h" +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" + /* some code copied from article on microsoft.com, copied * here for enhanced BMP support in the future * http://www.microsoft.com/msj/defaultframe.asp?page=/msj/0197/mfcp1/mfcp1.htm&nav=/msj/0197/newnav.htm @@ -115,7 +118,7 @@ int imb_is_a_bmp(unsigned char *buf) return checkbmp(buf); } -struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags) +struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { struct ImBuf *ibuf = NULL; BMPINFOHEADER bmi; @@ -127,6 +130,8 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags) if (checkbmp(mem) == 0) return(NULL); + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + if ((mem[0] == 'B') && (mem[1] == 'M')) { /* skip fileheader */ mem += BMP_FILEHEADER_SIZE; diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c index 182e0a7e29d..7705af13b1e 100644 --- a/source/blender/imbuf/intern/cineon/cineon_dpx.c +++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c @@ -44,6 +44,9 @@ #include "IMB_imbuf.h" #include "IMB_filetype.h" +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" + #include "BKE_global.h" #include "MEM_guardedalloc.h" @@ -63,7 +66,7 @@ static void cineon_conversion_parameters(LogImageByteConversionParameters *param } #endif -static ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int size, int flags) +static ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int size, int flags, char colorspace[IM_MAX_SPACE]) { ImBuf *ibuf; LogImageFile *image; @@ -72,6 +75,8 @@ static ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int size, int width, height, depth; float *frow; + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT); + logImageSetVerbose((G.debug & G_DEBUG) ? 1:0); image = logImageOpenFromMem(mem, size, use_cineon); @@ -202,10 +207,10 @@ int imb_is_cineon(unsigned char *buf) return cineonIsMemFileCineon(buf); } -ImBuf *imb_loadcineon(unsigned char *mem, size_t size, int flags) +ImBuf *imb_loadcineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { if (imb_is_cineon(mem)) - return imb_load_dpx_cineon(mem, 1, size, flags); + return imb_load_dpx_cineon(mem, 1, size, flags, colorspace); return NULL; } @@ -219,9 +224,9 @@ int imb_is_dpx(unsigned char *buf) return dpxIsMemFileCineon(buf); } -ImBuf *imb_loaddpx(unsigned char *mem, size_t size, int flags) +ImBuf *imb_loaddpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { if (imb_is_dpx(mem)) - return imb_load_dpx_cineon(mem, 0, size, flags); + return imb_load_dpx_cineon(mem, 0, size, flags, colorspace); return NULL; } diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index b88ff3cda47..292c7910dd8 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -45,6 +45,7 @@ #include "IMB_filter.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "IMB_filetype.h" #include "IMB_moviecache.h" #include "MEM_guardedalloc.h" @@ -845,6 +846,38 @@ static void curve_mapping_apply_pixel(CurveMapping *curve_mapping, float *pixel, } } +void colorspace_set_default_role(char *colorspace, int size, int role) +{ + if (colorspace && colorspace[0] == '\0') { + const char *role_colorspace; + + role_colorspace = IMB_colormanagement_role_colorspace_name_get(role); + + BLI_strncpy(colorspace, role_colorspace, size); + } +} + +void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace) +{ +#ifdef WITH_OCIO + if (ibuf->rect_float) { + const char *to_colorspace = global_role_scene_linear; + int predivide = ibuf->flags & IB_cm_predivide; + + if (ibuf->rect) + imb_freerectImBuf(ibuf); + + IMB_colormanagement_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, + from_colorspace, to_colorspace, predivide); + + ibuf->profile = IB_PROFILE_LINEAR_RGB; + } +#else + (void) ibuf; + (void) role; +#endif +} + /*********************** Generic functions *************************/ #ifdef WITH_OCIO @@ -1580,46 +1613,6 @@ void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float IMB_colormanagement_processor_free(cm_processor); } -void IMB_colormanagement_imbuf_to_role(ImBuf *ibuf, int role) -{ -#ifdef WITH_OCIO - if (ibuf->rect_float) { - const char *from_colorspace = global_role_scene_linear; - const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(role); - int predivide = ibuf->flags & IB_cm_predivide; - - if (ibuf->rect) - imb_freerectImBuf(ibuf); - - IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace, predivide); - } -#else - (void) ibuf; - (void) role; -#endif -} - -void IMB_colormanagement_imbuf_from_role(ImBuf *ibuf, int role) -{ -#ifdef WITH_OCIO - if (ibuf->rect_float) { - const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(role); - const char *to_colorspace = global_role_scene_linear; - int predivide = ibuf->flags & IB_cm_predivide; - - if (ibuf->rect) - imb_freerectImBuf(ibuf); - - IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace, predivide); - } -#else - (void) ibuf; - (void) role; -#endif -} - void IMB_colormanagement_pixel_to_role_v4(float pixel[4], int role) { #ifdef WITH_OCIO @@ -1687,34 +1680,16 @@ void IMB_colormanagement_imbuf_assign_spaces(ImBuf *ibuf, ColorManagedColorspace #endif } +void IMB_colormanagement_imbuf_assign_default_spaces(ImBuf *ibuf) +{ + IMB_colormanagement_imbuf_assign_spaces(ibuf, NULL); +} + void IMB_colormanagement_imbuf_assign_float_space(ImBuf *ibuf, ColorManagedColorspaceSettings *colorspace_settings) { ibuf->float_colorspace = colormanage_colorspace_get_named(colorspace_settings->name); } -void IMB_colormanagement_imbuf_make_scene_linear(ImBuf *ibuf, ColorManagedColorspaceSettings *colorspace_settings) -{ -#ifdef WITH_OCIO - /* for byte buffers only store it's color space, no affect on buffer itself - * that's because of precision issues of bytes - */ - IMB_colormanagement_imbuf_assign_spaces(ibuf, colorspace_settings); - - /* convert float buffer to scene linear space */ - if (ibuf->rect_float) { - const char *from_colorspace = colorspace_settings->name; - const char *to_colorspace = global_role_scene_linear; - int predivide = ibuf->flags & IB_cm_predivide; - - IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace, predivide); - } -#else - (void) ibuf; - (void) colorspace_settings; -#endif -} - void IMB_colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { @@ -1739,6 +1714,16 @@ void IMB_colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManage #endif } +void IMB_colormanagement_imbuf_make_colorspace(ImBuf *ibuf, const char *to_colorspace, int flag) +{ + int predivide = ibuf->flags & IB_cm_predivide; + + if (ibuf->rect_float && (flag & IB_rectfloat)) { + IMB_colormanagement_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, + global_role_scene_linear, to_colorspace, predivide); + } +} + static void imbuf_verify_float(ImBuf *ibuf) { /* multiple threads could request for display buffer at once and in case @@ -2208,6 +2193,13 @@ ColorSpace *colormanage_colorspace_get_named(const char *name) return NULL; } +ColorSpace *colormanage_colorspace_get_roled(int role) +{ + const char *role_colorspace = IMB_colormanagement_role_colorspace_name_get(role); + + return colormanage_colorspace_get_named(role_colorspace); +} + ColorSpace *colormanage_colorspace_get_indexed(int index) { /* display indices are 1-based */ @@ -2240,6 +2232,21 @@ const char *IMB_colormanagement_colorspace_get_indexed_name(int index) return ""; } +void IMB_colormanagment_colorspace_from_ibuf_ftype(ColorManagedColorspaceSettings *colorspace_settings, ImBuf *ibuf) +{ + ImFileType *type; + + for (type = IMB_FILE_TYPES; type->is_a; type++) { + if (type->save && type->ftype(type, ibuf)) { + const char *role_colorspace; + + role_colorspace = IMB_colormanagement_role_colorspace_name_get(type->default_save_role); + + BLI_strncpy(colorspace_settings->name, role_colorspace, sizeof(colorspace_settings->name)); + } + } +} + /*********************** RNA helper functions *************************/ void IMB_colormanagement_display_items_add(EnumPropertyItem **items, int *totitem) diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index 71313d4438f..676dde138d1 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -43,6 +43,9 @@ extern "C" { #include "IMB_imbuf.h" #include "IMB_allocimbuf.h" +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" + int imb_save_dds(struct ImBuf * ibuf, const char *name, int flags) { return(0); /* todo: finish this function */ @@ -79,7 +82,7 @@ int imb_is_a_dds(unsigned char *mem) // note: use at most first 32 bytes return(1); } -struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags) +struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { struct ImBuf * ibuf = 0; DirectDrawSurface dds(mem, size); /* reads header */ @@ -92,6 +95,12 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags) Color32 pixel; Color32 *pixels = 0; + /* OCIO_TODO: never was able to save DDS, so can'ttest loading + * but profile used to be set to sRGB and can't see rect_float here, so + * default byte space should work fine + */ + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + if (!imb_is_a_dds(mem)) return (0); diff --git a/source/blender/imbuf/intern/dds/dds_api.h b/source/blender/imbuf/intern/dds/dds_api.h index 589257816e0..2316fefce69 100644 --- a/source/blender/imbuf/intern/dds/dds_api.h +++ b/source/blender/imbuf/intern/dds/dds_api.h @@ -32,9 +32,11 @@ extern "C" { #endif +#include "../../IMB_imbuf.h" + int imb_save_dds(struct ImBuf *ibuf, const char *name, int flags); int imb_is_a_dds(unsigned char *mem); /* use only first 32 bytes of mem */ -struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags); +struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); #ifdef __cplusplus } diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c index d67de3be68b..ed4db50035d 100644 --- a/source/blender/imbuf/intern/filetype.c +++ b/source/blender/imbuf/intern/filetype.c @@ -30,6 +30,8 @@ #include "IMB_imbuf_types.h" #include "IMB_filetype.h" +#include "IMB_colormanagement.h" + #ifdef WITH_OPENEXR #include "openexr/openexr_api.h" #endif @@ -66,34 +68,34 @@ void quicktime_exit(void); #endif ImFileType IMB_FILE_TYPES[] = { - {NULL, NULL, imb_is_a_jpeg, imb_ftype_default, imb_load_jpeg, imb_savejpeg, NULL, 0, JPG}, - {NULL, NULL, imb_is_a_png, imb_ftype_default, imb_loadpng, imb_savepng, NULL, 0, PNG}, - {NULL, NULL, imb_is_a_bmp, imb_ftype_default, imb_bmp_decode, imb_savebmp, NULL, 0, BMP}, - {NULL, NULL, imb_is_a_targa, imb_ftype_default, imb_loadtarga, imb_savetarga, NULL, 0, TGA}, - {NULL, NULL, imb_is_a_iris, imb_ftype_iris, imb_loadiris, imb_saveiris, NULL, 0, IMAGIC}, + {NULL, NULL, imb_is_a_jpeg, imb_ftype_default, imb_load_jpeg, imb_savejpeg, NULL, 0, JPG, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_png, imb_ftype_default, imb_loadpng, imb_savepng, NULL, 0, PNG, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_bmp, imb_ftype_default, imb_bmp_decode, imb_savebmp, NULL, 0, BMP, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_targa, imb_ftype_default, imb_loadtarga, imb_savetarga, NULL, 0, TGA, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_iris, imb_ftype_iris, imb_loadiris, imb_saveiris, NULL, 0, IMAGIC, COLOR_ROLE_DEFAULT_BYTE}, #ifdef WITH_CINEON - {NULL, NULL, imb_is_dpx, imb_ftype_default, imb_loaddpx, imb_save_dpx, NULL, IM_FTYPE_FLOAT, DPX}, - {NULL, NULL, imb_is_cineon, imb_ftype_default, imb_loadcineon, imb_savecineon, NULL, IM_FTYPE_FLOAT, CINEON}, + {NULL, NULL, imb_is_dpx, imb_ftype_default, imb_loaddpx, imb_save_dpx, NULL, IM_FTYPE_FLOAT, DPX, COLOR_ROLE_DEFAULT_FLOAT}, + {NULL, NULL, imb_is_cineon, imb_ftype_default, imb_loadcineon, imb_savecineon, NULL, IM_FTYPE_FLOAT, CINEON, COLOR_ROLE_DEFAULT_FLOAT}, #endif #ifdef WITH_TIFF - {imb_inittiff, NULL, imb_is_a_tiff, imb_ftype_default, imb_loadtiff, imb_savetiff, imb_loadtiletiff, 0, TIF}, + {imb_inittiff, NULL, imb_is_a_tiff, imb_ftype_default, imb_loadtiff, imb_savetiff, imb_loadtiletiff, 0, TIF, COLOR_ROLE_DEFAULT_BYTE}, #endif #ifdef WITH_HDR - {NULL, NULL, imb_is_a_hdr, imb_ftype_default, imb_loadhdr, imb_savehdr, NULL, IM_FTYPE_FLOAT, RADHDR}, + {NULL, NULL, imb_is_a_hdr, imb_ftype_default, imb_loadhdr, imb_savehdr, NULL, IM_FTYPE_FLOAT, RADHDR, COLOR_ROLE_DEFAULT_FLOAT}, #endif #ifdef WITH_OPENEXR - {imb_initopenexr, NULL, imb_is_a_openexr, imb_ftype_default, imb_load_openexr, imb_save_openexr, NULL, IM_FTYPE_FLOAT, OPENEXR}, + {imb_initopenexr, NULL, imb_is_a_openexr, imb_ftype_default, imb_load_openexr, imb_save_openexr, NULL, IM_FTYPE_FLOAT, OPENEXR, COLOR_ROLE_DEFAULT_FLOAT}, #endif #ifdef WITH_OPENJPEG - {NULL, NULL, imb_is_a_jp2, imb_ftype_default, imb_jp2_decode, imb_savejp2, NULL, IM_FTYPE_FLOAT, JP2}, + {NULL, NULL, imb_is_a_jp2, imb_ftype_default, imb_jp2_decode, imb_savejp2, NULL, IM_FTYPE_FLOAT, JP2, COLOR_ROLE_DEFAULT_BYTE}, #endif #ifdef WITH_DDS - {NULL, NULL, imb_is_a_dds, imb_ftype_default, imb_load_dds, NULL, NULL, 0, DDS}, + {NULL, NULL, imb_is_a_dds, imb_ftype_default, imb_load_dds, NULL, NULL, 0, DDS, COLOR_ROLE_DEFAULT_BYTE}, #endif #ifdef WITH_QUICKTIME - {quicktime_init, quicktime_exit, imb_is_a_quicktime, imb_ftype_quicktime, imb_quicktime_decode, NULL, NULL, 0, QUICKTIME}, + {quicktime_init, quicktime_exit, imb_is_a_quicktime, imb_ftype_quicktime, imb_quicktime_decode, NULL, NULL, 0, QUICKTIME, COLOR_ROLE_DEFAULT_BYTE}, #endif - {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0} + {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0} }; void imb_filetypes_init(void) diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index ea493e277f3..97316c48621 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -1254,7 +1254,8 @@ struct anim *IMB_anim_open_proxy( get_proxy_filename(anim, preview_size, fname, FALSE); - anim->proxy_anim[i] = IMB_open_anim(fname, 0, 0); + /* proxies are generated in default color space */ + anim->proxy_anim[i] = IMB_open_anim(fname, 0, 0, NULL); anim->proxies_tried |= preview_size; diff --git a/source/blender/imbuf/intern/iris.c b/source/blender/imbuf/intern/iris.c index 13b0fc1b55a..58355937c80 100644 --- a/source/blender/imbuf/intern/iris.c +++ b/source/blender/imbuf/intern/iris.c @@ -42,6 +42,9 @@ #include "IMB_allocimbuf.h" #include "IMB_filetype.h" +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" + typedef struct { unsigned short imagic; /* stuff saved on disk . . */ unsigned short type; @@ -247,7 +250,7 @@ int imb_is_a_iris(unsigned char *mem) * */ -struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags) +struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { unsigned int *base, *lptr = NULL; float *fbase, *fptr = NULL; @@ -265,6 +268,9 @@ struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags) if (!imb_is_a_iris(mem)) return NULL; + /* OCIO_TODO: only tested with 1 byte per pixel, not sure how to test with other settings */ + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + /*printf("new iris\n");*/ file_data = mem; diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c index 1fe9a5ab522..b2221a77c54 100644 --- a/source/blender/imbuf/intern/jp2.c +++ b/source/blender/imbuf/intern/jp2.c @@ -36,6 +36,9 @@ #include "IMB_allocimbuf.h" #include "IMB_filetype.h" +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" + #include "openjpeg.h" #define JP2_FILEHEADER_SIZE 14 @@ -109,7 +112,7 @@ static void info_callback(const char *msg, void *client_data) } \ } (void)0 \ -struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags) +struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { struct ImBuf *ibuf = NULL; int use_float = FALSE; /* for precision higher then 8 use float */ @@ -137,6 +140,9 @@ struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags) if (!is_jp2 && !is_j2k) return(NULL); + /* both 8, 12 and 16 bit JP2Ks are default to standard byte colorspace */ + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + /* configure the event callbacks (not required) */ memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); event_mgr.error_handler = error_callback; diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c index 364950b99cb..59cf7903c67 100644 --- a/source/blender/imbuf/intern/jpeg.c +++ b/source/blender/imbuf/intern/jpeg.c @@ -48,6 +48,9 @@ #include "jpeglib.h" #include "jerror.h" +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" + #define IS_jpg(x) (x->ftype & JPG) #define IS_stdjpg(x) ((x->ftype & JPG_MSK) == JPG_STD) #define IS_vidjpg(x) ((x->ftype & JPG_MSK) == JPG_VID) @@ -442,14 +445,16 @@ next_stamp_marker: return(ibuf); } -ImBuf *imb_load_jpeg(unsigned char *buffer, size_t size, int flags) +ImBuf *imb_load_jpeg(unsigned char *buffer, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { struct jpeg_decompress_struct _cinfo, *cinfo = &_cinfo; struct my_error_mgr jerr; ImBuf *ibuf; if (!imb_is_a_jpeg(buffer)) return NULL; - + + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + cinfo->err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = jpeg_error; diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 26aab29b8dd..4dfa1686f9d 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -64,6 +64,9 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void) #include "IMB_allocimbuf.h" #include "IMB_metadata.h" +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" + #include "openexr_multi.h" } @@ -1129,13 +1132,15 @@ static int exr_is_multilayer(InputFile *file) return 0; } -struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags) +struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { struct ImBuf *ibuf = NULL; InputFile *file = NULL; if (imb_is_a_openexr(mem) == 0) return(NULL); + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT); + try { Mem_IStream *membuf = new Mem_IStream(mem, size); diff --git a/source/blender/imbuf/intern/openexr/openexr_api.h b/source/blender/imbuf/intern/openexr/openexr_api.h index d12fe2fc49f..3135795fb3f 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.h +++ b/source/blender/imbuf/intern/openexr/openexr_api.h @@ -50,7 +50,7 @@ int imb_is_a_openexr (unsigned char *mem); int imb_save_openexr (struct ImBuf *ibuf, const char *name, int flags); -struct ImBuf *imb_load_openexr (unsigned char *mem, size_t size, int flags); +struct ImBuf *imb_load_openexr (unsigned char *mem, size_t size, int flags, char *colorspace); #ifdef __cplusplus } diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c index 92cd9622849..7db34e24901 100644 --- a/source/blender/imbuf/intern/png.c +++ b/source/blender/imbuf/intern/png.c @@ -47,6 +47,9 @@ #include "IMB_metadata.h" #include "IMB_filetype.h" +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" + typedef struct PNGReadStruct { unsigned char *data; unsigned int size; @@ -302,7 +305,7 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) return(1); } -ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags) +ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { struct ImBuf *ibuf = NULL; png_structp png_ptr; @@ -317,11 +320,13 @@ ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags) unsigned char *from, *to; unsigned short *from16; float *to_float; - float tmp[4]; int i, bytesperpixel; if (imb_is_a_png(mem) == 0) return(NULL); + /* both 8 and 16 bit PNGs are default to standard byte colorspace */ + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { @@ -443,37 +448,33 @@ ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags) switch (bytesperpixel) { case 4: for (i = ibuf->x * ibuf->y; i > 0; i--) { - tmp[0] = from16[0] / 65535.0; - tmp[1] = from16[1] / 65535.0; - tmp[2] = from16[2] / 65535.0; - tmp[3] = from16[3] / 65535.0; - srgb_to_linearrgb_v4(to_float, tmp); + to_float[0] = from16[0] / 65535.0; + to_float[1] = from16[1] / 65535.0; + to_float[2] = from16[2] / 65535.0; + to_float[3] = from16[3] / 65535.0; to_float += 4; from16 += 4; } break; case 3: for (i = ibuf->x * ibuf->y; i > 0; i--) { - tmp[0] = from16[0] / 65535.0; - tmp[1] = from16[1] / 65535.0; - tmp[2] = from16[2] / 65535.0; - tmp[3] = 1.0; - srgb_to_linearrgb_v4(to_float, tmp); + to_float[0] = from16[0] / 65535.0; + to_float[1] = from16[1] / 65535.0; + to_float[2] = from16[2] / 65535.0; + to_float[3] = 1.0; to_float += 4; from16 += 3; } break; case 2: for (i = ibuf->x * ibuf->y; i > 0; i--) { - tmp[0] = tmp[1] = tmp[2] = from16[0] / 65535.0; - tmp[3] = from16[1] / 65535.0; - srgb_to_linearrgb_v4(to_float, tmp); + to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0; + to_float[3] = from16[1] / 65535.0; to_float += 4; from16 += 2; } break; case 1: for (i = ibuf->x * ibuf->y; i > 0; i--) { - tmp[0] = tmp[1] = tmp[2] = from16[0] / 65535.0; - tmp[3] = 1.0; - srgb_to_linearrgb_v4(to_float, tmp); + to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0; + to_float[3] = 1.0; to_float += 4; from16++; } break; diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c index 4cd50484a64..4eb6999c7b1 100644 --- a/source/blender/imbuf/intern/radiance_hdr.c +++ b/source/blender/imbuf/intern/radiance_hdr.c @@ -53,6 +53,9 @@ #include "IMB_allocimbuf.h" #include "IMB_filetype.h" +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" + /* needed constants */ #define MINELEN 8 #define MAXELEN 0x7fff @@ -171,7 +174,7 @@ int imb_is_a_hdr(unsigned char *buf) return 0; } -struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags) +struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { struct ImBuf *ibuf; RGBE *sline; @@ -184,6 +187,8 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags) char oriY[80], oriX[80]; if (imb_is_a_hdr((void *)mem)) { + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT); + /* find empty line, next line is resolution info */ for (x = 1; x < size; x++) { if ((mem[x - 1] == '\n') && (mem[x] == '\n')) { diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index 4bde71588b7..764c326d079 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -54,20 +54,42 @@ #include "IMB_imbuf.h" #include "IMB_filetype.h" -ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, const char *descr) +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" + +ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE], const char *descr) { ImBuf *ibuf; ImFileType *type; + char effective_colorspace[IM_MAX_SPACE] = ""; if (mem == NULL) { fprintf(stderr, "%s: NULL pointer\n", __func__); return NULL; } + if (colorspace) + BLI_strncpy(effective_colorspace, colorspace, sizeof(effective_colorspace)); + for (type = IMB_FILE_TYPES; type->is_a; type++) { if (type->load) { - ibuf = type->load(mem, size, flags); + ibuf = type->load(mem, size, flags, effective_colorspace); if (ibuf) { + if (colorspace) { + if (ibuf->rect) { + /* byte buffer is never internally converted to some standard space, + * store pointer to it's color space descriptor instead + */ + ibuf->rect_colorspace = colormanage_colorspace_get_named(colorspace); + } + + BLI_strncpy(colorspace, effective_colorspace, IM_MAX_SPACE); + } + + /* OCIO_TODO: in some cases it's faster to do threaded conversion, + * but how to distinguish such cases */ + colormanage_imbuf_make_linear(ibuf, effective_colorspace); + if (flags & IB_premul) { IMB_premultiply_alpha(ibuf); ibuf->flags |= IB_premul; @@ -83,7 +105,7 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, const c return NULL; } -ImBuf *IMB_loadifffile(int file, int flags, const char *descr) +ImBuf *IMB_loadifffile(int file, int flags, char colorspace[IM_MAX_SPACE], const char *descr) { ImBuf *ibuf; unsigned char *mem; @@ -99,7 +121,7 @@ ImBuf *IMB_loadifffile(int file, int flags, const char *descr) return NULL; } - ibuf = IMB_ibImageFromMemory(mem, size, flags, descr); + ibuf = IMB_ibImageFromMemory(mem, size, flags, colorspace, descr); if (munmap(mem, size)) fprintf(stderr, "%s: couldn't unmap file %s\n", __func__, descr); @@ -122,7 +144,7 @@ static void imb_cache_filename(char *filename, const char *name, int flags) BLI_strncpy(filename, name, IB_FILENAME_SIZE); } -ImBuf *IMB_loadiffname(const char *filepath, int flags) +ImBuf *IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE]) { ImBuf *ibuf; int file, a; @@ -133,7 +155,7 @@ ImBuf *IMB_loadiffname(const char *filepath, int flags) file = BLI_open(filepath_tx, O_BINARY | O_RDONLY, 0); if (file < 0) return NULL; - ibuf = IMB_loadifffile(file, flags, filepath_tx); + ibuf = IMB_loadifffile(file, flags, colorspace, filepath_tx); if (ibuf) { BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name)); @@ -148,7 +170,7 @@ ImBuf *IMB_loadiffname(const char *filepath, int flags) return ibuf; } -ImBuf *IMB_testiffname(const char *filepath, int flags) +ImBuf *IMB_testiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE]) { ImBuf *ibuf; int file; @@ -159,7 +181,7 @@ ImBuf *IMB_testiffname(const char *filepath, int flags) file = BLI_open(filepath_tx, O_BINARY | O_RDONLY, 0); if (file < 0) return NULL; - ibuf = IMB_loadifffile(file, flags | IB_test | IB_multilayer, filepath_tx); + ibuf = IMB_loadifffile(file, flags | IB_test | IB_multilayer, colorspace, filepath_tx); if (ibuf) { BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name)); diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c index 4df49386ce1..be99050f31e 100644 --- a/source/blender/imbuf/intern/targa.c +++ b/source/blender/imbuf/intern/targa.c @@ -46,6 +46,8 @@ #include "IMB_allocimbuf.h" #include "IMB_filetype.h" +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" /* this one is only def-ed once, strangely... related to GS? */ #define GSS(x) (((uchar *)(x))[1] << 8 | ((uchar *)(x))[0]) @@ -546,16 +548,18 @@ partial_load: } -ImBuf *imb_loadtarga(unsigned char *mem, size_t mem_size, int flags) +ImBuf *imb_loadtarga(unsigned char *mem, size_t mem_size, int flags, char colorspace[IM_MAX_SPACE]) { TARGA tga; struct ImBuf *ibuf; int col, count, size; unsigned int *rect, *cmap = NULL /*, mincol = 0*/, maxcol = 0; uchar *cp = (uchar *) &col; - + if (checktarga(&tga, mem) == 0) return(NULL); + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + if (flags & IB_test) ibuf = IMB_allocImBuf(tga.xsize, tga.ysize, tga.pixsize, 0); else ibuf = IMB_allocImBuf(tga.xsize, tga.ysize, (tga.pixsize + 0x7) & ~0x7, IB_rect); diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index 2a2aedb49ff..ff7218d649c 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -313,7 +313,7 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im img = IMB_loadblend_thumb(path); } else { - img = IMB_loadiffname(path, IB_rect | IB_metadata); + img = IMB_loadiffname(path, IB_rect | IB_metadata, NULL); } } @@ -326,7 +326,7 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im } else if (THB_SOURCE_MOVIE == source) { struct anim *anim = NULL; - anim = IMB_open_anim(path, IB_rect | IB_metadata, 0); + anim = IMB_open_anim(path, IB_rect | IB_metadata, 0, NULL); if (anim != NULL) { img = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); if (img == NULL) { @@ -376,6 +376,7 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im } img->ftype = PNG; img->planes = 32; + if (IMB_saveiff(img, temp, IB_rect | IB_metadata)) { #ifndef WIN32 chmod(temp, S_IRUSR | S_IWUSR); @@ -401,7 +402,7 @@ ImBuf *IMB_thumb_read(const char *path, ThumbSize size) return NULL; } if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) { - img = IMB_loadiffname(thumb, IB_rect | IB_metadata); + img = IMB_loadiffname(thumb, IB_rect | IB_metadata, NULL); } return img; @@ -456,10 +457,10 @@ ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source) if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) { if (BLI_path_ncmp(path, thumb, sizeof(thumb)) == 0) { - img = IMB_loadiffname(path, IB_rect); + img = IMB_loadiffname(path, IB_rect, NULL); } else { - img = IMB_loadiffname(thumb, IB_rect | IB_metadata); + img = IMB_loadiffname(thumb, IB_rect | IB_metadata, NULL); if (img) { char mtime[40]; if (!IMB_metadata_get_field(img, "Thumb::MTime", mtime, 40)) { diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c index ac5f5da8a67..4ee379258f1 100644 --- a/source/blender/imbuf/intern/tiff.c +++ b/source/blender/imbuf/intern/tiff.c @@ -57,6 +57,9 @@ #include "IMB_filetype.h" #include "IMB_filter.h" +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" + #include "tiffio.h" #ifdef WIN32 @@ -508,7 +511,7 @@ void imb_inittiff(void) * * \return: A newly allocated ImBuf structure if successful, otherwise NULL. */ -ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags) +ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { TIFF *image = NULL; ImBuf *ibuf = NULL, *hbuf; @@ -527,6 +530,9 @@ ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags) if (imb_is_a_tiff(mem) == 0) return NULL; + /* both 8 and 16 bit PNGs are default to standard byte colorspace */ + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + image = imb_tiff_client_open(&memFile, mem, size); if (image == NULL) { diff --git a/source/blender/imbuf/intern/writeimage.c b/source/blender/imbuf/intern/writeimage.c index 1c182e9784e..5d785e08212 100644 --- a/source/blender/imbuf/intern/writeimage.c +++ b/source/blender/imbuf/intern/writeimage.c @@ -38,8 +38,28 @@ #include "IMB_imbuf.h" #include "IMB_filetype.h" +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" + #include "imbuf.h" +static ImBuf *prepare_write_imbuf(ImFileType *type, ImBuf *ibuf) +{ + ImBuf *write_ibuf = ibuf; + + if (type->flag & IM_FTYPE_FLOAT) { + /* pass */ + } + else { + if (ibuf->rect == NULL && ibuf->rect_float) { + ibuf->rect_colorspace = colormanage_colorspace_get_roled(COLOR_ROLE_DEFAULT_BYTE); + IMB_rect_from_float(ibuf); + } + } + + return write_ibuf; +} + short IMB_saveiff(struct ImBuf *ibuf, const char *name, int flags) { ImFileType *type; @@ -49,11 +69,17 @@ short IMB_saveiff(struct ImBuf *ibuf, const char *name, int flags) for (type = IMB_FILE_TYPES; type->is_a; type++) { if (type->save && type->ftype(type, ibuf)) { - if (!(type->flag & IM_FTYPE_FLOAT)) { - if (ibuf->rect == NULL && ibuf->rect_float) - IMB_rect_from_float(ibuf); - } - return type->save(ibuf, name, flags); + ImBuf *write_ibuf; + short result = FALSE; + + write_ibuf = prepare_write_imbuf(type, ibuf); + + result = type->save(write_ibuf, name, flags); + + if (write_ibuf != ibuf) + IMB_freeImBuf(write_ibuf); + + return result; } } diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index 8c071ac3411..c66c0085763 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -120,6 +120,8 @@ static void rna_Image_save(Image *image, ReportList *reports) if (image->source == IMA_SRC_GENERATED) image->source = IMA_SRC_FILE; + IMB_colormanagment_colorspace_from_ibuf_ftype(&image->colorspace_settings, ibuf); + ibuf->userflags &= ~IB_BITMAPDIRTY; } else { diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index 549868e5ed0..ab1dfbf22b0 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -188,7 +188,8 @@ static Sequence *rna_Sequences_new_movie(ID *id, Editing *ed, ReportList *report Scene *scene = (Scene *)id; Sequence *seq; - struct anim *an = openanim(file, IB_rect, 0); + /* OCIO_TODO: support configurable color spaces for strips */ + struct anim *an = openanim(file, IB_rect, 0, NULL); if (an == NULL) { BKE_report(reports, RPT_ERROR, "Sequences.new_movie: unable to open movie file"); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 069062b5bc6..599d91333e6 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2411,7 +2411,8 @@ void RE_init_threadcount(Render *re) * x/y offsets are only used on a partial copy when dimensions don't match */ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char *filename, int x, int y) { - ImBuf *ibuf = IMB_loadiffname(filename, IB_rect); + /* OCIO_TODO: assume layer was saved in defaule color space */ + ImBuf *ibuf = IMB_loadiffname(filename, IB_rect, NULL); if (ibuf && (ibuf->rect || ibuf->rect_float)) { if (ibuf->x == layer->rectx && ibuf->y == layer->recty) { diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 0259146a9d3..1b76e71503c 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1296,7 +1296,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar extern int datatoc_splash_png_size; ImBuf *ibuf = IMB_ibImageFromMemory((unsigned char *)datatoc_splash_png, - datatoc_splash_png_size, IB_rect, ""); + datatoc_splash_png_size, IB_rect, NULL, ""); #else ImBuf *ibuf = NULL; #endif diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index e3867c0a32a..bbe5ddc72f2 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -279,7 +279,8 @@ static void build_pict_list(char *first, int totframes, int fstep, int fontid) struct anim *anim; if (IMB_isanim(first)) { - anim = IMB_open_anim(first, IB_rect, 0); + /* OCIO_TODO: support different input color space */ + anim = IMB_open_anim(first, IB_rect, 0, NULL); if (anim) { int pic; ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); @@ -378,12 +379,13 @@ static void build_pict_list(char *first, int totframes, int fstep, int fontid) pupdate_time(); if (ptottime > 1.0) { + /* OCIO_TODO: support different input color space */ if (picture->mem) { ibuf = IMB_ibImageFromMemory((unsigned char *)picture->mem, picture->size, - picture->IB_flags, picture->name); + picture->IB_flags, NULL, picture->name); } else { - ibuf = IMB_loadiffname(picture->name, picture->IB_flags); + ibuf = IMB_loadiffname(picture->name, picture->IB_flags, NULL); } if (ibuf) { playanim_toscreen(picture, ibuf, fontid); @@ -824,7 +826,8 @@ void playanim(int argc, const char **argv) } if (IMB_isanim(filepath)) { - anim = IMB_open_anim(filepath, IB_rect, 0); + /* OCIO_TODO: support different input color spaces */ + anim = IMB_open_anim(filepath, IB_rect, 0, NULL); if (anim) { ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); IMB_close_anim(anim); @@ -836,7 +839,8 @@ void playanim(int argc, const char **argv) } if (ibuf == NULL) { - ibuf = IMB_loadiffname(filepath, IB_rect); + /* OCIO_TODO: support different input color space */ + ibuf = IMB_loadiffname(filepath, IB_rect, NULL); } if (ibuf == NULL) { @@ -948,11 +952,13 @@ void playanim(int argc, const char **argv) ibuf = IMB_anim_absolute(ps.picture->anim, ps.picture->frame, IMB_TC_NONE, IMB_PROXY_NONE); } else if (ps.picture->mem) { + /* use correct colorspace here */ ibuf = IMB_ibImageFromMemory((unsigned char *) ps.picture->mem, ps.picture->size, - ps.picture->IB_flags, ps.picture->name); + ps.picture->IB_flags, NULL, ps.picture->name); } else { - ibuf = IMB_loadiffname(ps.picture->name, ps.picture->IB_flags); + /* use correct colorspace here */ + ibuf = IMB_loadiffname(ps.picture->name, ps.picture->IB_flags, NULL); } if (ibuf) { From a97ddb032861eb2242bae9df274cbc5a46b1ea40 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 14 Sep 2012 14:36:53 +0000 Subject: [PATCH 145/160] Color Management: remove unused functions --- source/blender/imbuf/IMB_colormanagement.h | 6 -- source/blender/imbuf/intern/colormanagement.c | 55 ------------------- 2 files changed, 61 deletions(-) diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index cd88371c0c0..e5632d41125 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -85,18 +85,12 @@ void IMB_colormanagement_pixel_to_display_space_v4(float result[4], const float void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float pixel[3], const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings); -void IMB_colormanagement_pixel_to_role_v4(float pixel[4], int role); -void IMB_colormanagement_pixel_from_role_v4(float pixel[4], int role); - void IMB_colormanagement_imbuf_assign_spaces(struct ImBuf *ibuf, struct ColorManagedColorspaceSettings *colorspace_settings); -void IMB_colormanagement_imbuf_assign_default_spaces(struct ImBuf *ibuf); void IMB_colormanagement_imbuf_assign_float_space(struct ImBuf *ibuf, struct ColorManagedColorspaceSettings *colorspace_settings); void IMB_colormanagement_imbuf_make_display_space(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings); -void IMB_colormanagement_imbuf_make_colorspace(struct ImBuf *ibuf, const char *to_colorspace, int flag); - /* ** Public display buffers interfaces ** */ unsigned char *IMB_display_buffer_acquire(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 292c7910dd8..260aef533b5 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1613,46 +1613,6 @@ void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float IMB_colormanagement_processor_free(cm_processor); } -void IMB_colormanagement_pixel_to_role_v4(float pixel[4], int role) -{ -#ifdef WITH_OCIO - ConstProcessorRcPtr *processor; - const char *from_colorspace = global_role_scene_linear; - const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(role); - - processor = create_colorspace_transform_processor(from_colorspace, to_colorspace); - - if (processor) { - OCIO_processorApplyRGBA(processor, pixel); - - OCIO_processorRelease(processor); - } -#else - (void) pixel; - (void) role; -#endif -} - -void IMB_colormanagement_pixel_from_role_v4(float pixel[4], int role) -{ -#ifdef WITH_OCIO - ConstProcessorRcPtr *processor; - const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(role); - const char *to_colorspace = global_role_scene_linear; - - processor = create_colorspace_transform_processor(from_colorspace, to_colorspace); - - if (processor) { - OCIO_processorApplyRGBA(processor, pixel); - - OCIO_processorRelease(processor); - } -#else - (void) pixel; - (void) role; -#endif -} - void IMB_colormanagement_imbuf_assign_spaces(ImBuf *ibuf, ColorManagedColorspaceSettings *colorspace_settings) { #ifdef WITH_OCIO @@ -1680,11 +1640,6 @@ void IMB_colormanagement_imbuf_assign_spaces(ImBuf *ibuf, ColorManagedColorspace #endif } -void IMB_colormanagement_imbuf_assign_default_spaces(ImBuf *ibuf) -{ - IMB_colormanagement_imbuf_assign_spaces(ibuf, NULL); -} - void IMB_colormanagement_imbuf_assign_float_space(ImBuf *ibuf, ColorManagedColorspaceSettings *colorspace_settings) { ibuf->float_colorspace = colormanage_colorspace_get_named(colorspace_settings->name); @@ -1714,16 +1669,6 @@ void IMB_colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManage #endif } -void IMB_colormanagement_imbuf_make_colorspace(ImBuf *ibuf, const char *to_colorspace, int flag) -{ - int predivide = ibuf->flags & IB_cm_predivide; - - if (ibuf->rect_float && (flag & IB_rectfloat)) { - IMB_colormanagement_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - global_role_scene_linear, to_colorspace, predivide); - } -} - static void imbuf_verify_float(ImBuf *ibuf) { /* multiple threads could request for display buffer at once and in case From 8e1138d7f61ea61a26e56c5bb21c65f4ed2a7801 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 14 Sep 2012 14:37:00 +0000 Subject: [PATCH 146/160] Color Management: re-implement OCIO-less build configuration Use OCIO stub file with hardcoded displays, views and color spaces. Intended to behave in the same way as old implementation, just it's now more clear code with much fewer ifdef checks. Also should make it possible to get rid of ibuf's profile flag. Thanks Brecht van Lommel for this patch! --- intern/CMakeLists.txt | 4 +- intern/SConscript | 3 +- intern/opencolorio/CMakeLists.txt | 43 +- intern/opencolorio/SConscript | 14 +- intern/opencolorio/ocio_capi_stub.cpp | 380 ++++++++++++++++++ source/blender/imbuf/CMakeLists.txt | 11 +- source/blender/imbuf/SConscript | 6 +- source/blender/imbuf/intern/colormanagement.c | 186 +-------- 8 files changed, 425 insertions(+), 222 deletions(-) create mode 100644 intern/opencolorio/ocio_capi_stub.cpp diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt index 1609bd35fa6..2551df6ba76 100644 --- a/intern/CMakeLists.txt +++ b/intern/CMakeLists.txt @@ -28,6 +28,7 @@ add_subdirectory(ghost) add_subdirectory(guardedalloc) add_subdirectory(moto) add_subdirectory(memutil) +add_subdirectory(opencolorio) add_subdirectory(opennl) add_subdirectory(mikktspace) add_subdirectory(raskter) @@ -74,6 +75,3 @@ if(WIN32) add_subdirectory(utfconv) endif() -if(WITH_OPENCOLORIO) - add_subdirectory(opencolorio) -endif() diff --git a/intern/SConscript b/intern/SConscript index f4771ccf6a7..3e40ef38705 100644 --- a/intern/SConscript +++ b/intern/SConscript @@ -11,6 +11,7 @@ SConscript(['audaspace/SConscript', 'decimation/SConscript', 'iksolver/SConscript', 'itasc/SConscript', + 'opencolorio/SConscript', 'opennl/SConscript', 'mikktspace/SConscript', 'smoke/SConscript', @@ -31,5 +32,3 @@ if env['WITH_BF_BOOLEAN']: if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-mingw', 'linuxcross', 'win64-vc'): SConscript(['utfconv/SConscript']) -if env['WITH_BF_OCIO']: - SConscript(['opencolorio/SConscript']) diff --git a/intern/opencolorio/CMakeLists.txt b/intern/opencolorio/CMakeLists.txt index 131a829017b..479bbd3ab0a 100644 --- a/intern/opencolorio/CMakeLists.txt +++ b/intern/opencolorio/CMakeLists.txt @@ -23,27 +23,40 @@ # # ***** END GPL LICENSE BLOCK ***** -set(INC - . - ${OPENCOLORIO_INCLUDE_DIRS} -) +if(WITH_OPENCOLORIO) + set(INC + . + ${OPENCOLORIO_INCLUDE_DIRS} + ) + + set(SRC + ocio_capi.cpp + ocio_capi.h + ) + + if(WIN32 AND NOT MINGW) + list(APPEND INC + ${BOOST_INCLUDE_DIR} + ) + endif() +else() + set(INC + . + ../../source/blender/blenlib + ) + + set(SRC + ocio_capi_stub.cpp + ocio_capi.h + ) +endif() set(INC_SYS ../guardedalloc ) -set(SRC - ocio_capi.cpp - ocio_capi.h -) - add_definitions( ) -if(WIN32 AND NOT MINGW) - list(APPEND INC - ${BOOST_INCLUDE_DIR} - ) -endif() - blender_add_lib(bf_intern_opencolorio "${SRC}" "${INC}" "${INC_SYS}") + diff --git a/intern/opencolorio/SConscript b/intern/opencolorio/SConscript index 4860d94947e..fec07662735 100644 --- a/intern/opencolorio/SConscript +++ b/intern/opencolorio/SConscript @@ -4,10 +4,16 @@ Import('env') sources = env.Glob('*.cpp') -incs = '. ../guardedalloc' -incs += ' ' + env['BF_OCIO_INC'] +incs = '. ../guardedalloc ../../source/blender/blenlib' -if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): - incs += ' ' + env['BF_BOOST_INC'] +if env['WITH_BF_OCIO']: + sources.remove('ocio_capi_stub.cpp') + + incs += ' ' + env['BF_OCIO_INC'] + + if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): + incs += ' ' + env['BF_BOOST_INC'] +else: + sources.remove('ocio_capi.cpp') env.BlenderLib( 'bf_intern_opencolorio', sources, Split(incs), [], libtype=['extern','player'], priority=[10, 185]) diff --git a/intern/opencolorio/ocio_capi_stub.cpp b/intern/opencolorio/ocio_capi_stub.cpp new file mode 100644 index 00000000000..a601cd3be91 --- /dev/null +++ b/intern/opencolorio/ocio_capi_stub.cpp @@ -0,0 +1,380 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Brecht van Lommel + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include + +#include "MEM_guardedalloc.h" +#include "BLI_math_color.h" + +namespace OCIO_NAMESPACE {}; + +#include "ocio_capi.h" + +#define CONFIG_DEFAULT ((ConstConfigRcPtr*)1) + +#define PROCESSOR_LINEAR_TO_SRGB ((ConstProcessorRcPtr*)1) +#define PROCESSOR_SRGB_TO_LINEAR ((ConstProcessorRcPtr*)2) +#define PROCESSOR_UNKNOWN ((ConstProcessorRcPtr*)3) + +#define COLORSPACE_LINEAR ((ConstColorSpaceRcPtr*)1) +#define COLORSPACE_SRGB ((ConstColorSpaceRcPtr*)2) + +typedef struct PackedImageDescription { + float *data; + long width; + long height; + long numChannels; + long chanStrideBytes; + long xStrideBytes; + long yStrideBytes; +} PackedImageDescription; + +ConstConfigRcPtr *OCIO_getCurrentConfig(void) +{ + return CONFIG_DEFAULT; +} + +void OCIO_setCurrentConfig(const ConstConfigRcPtr *) +{ +} + +ConstConfigRcPtr *OCIO_configCreateFromEnv(void) +{ + return CONFIG_DEFAULT; +} + +ConstConfigRcPtr *OCIO_configCreateFromFile(const char *) +{ + return CONFIG_DEFAULT; +} + +void OCIO_configRelease(ConstConfigRcPtr *) +{ +} + +int OCIO_configGetNumColorSpaces(ConstConfigRcPtr *) +{ + return 2; +} + +const char *OCIO_configGetColorSpaceNameByIndex(ConstConfigRcPtr *, int index) +{ + if (index == 0) + return "Linear"; + else if (index == 1) + return "sRGB"; + + return NULL; +} + +ConstColorSpaceRcPtr *OCIO_configGetColorSpace(ConstConfigRcPtr *, const char *name) +{ + if (strcmp(name, "scene_linear") == 0) + return COLORSPACE_LINEAR; + else if (strcmp(name, "color_picking") == 0) + return COLORSPACE_SRGB; + else if (strcmp(name, "texture_paint") == 0) + return COLORSPACE_LINEAR; + else if (strcmp(name, "default_byte") == 0) + return COLORSPACE_SRGB; + else if (strcmp(name, "default_float") == 0) + return COLORSPACE_LINEAR; + else if (strcmp(name, "default_sequencer") == 0) + return COLORSPACE_SRGB; + else if (strcmp(name, "Linear") == 0) + return COLORSPACE_LINEAR; + else if (strcmp(name, "sRGB") == 0) + return COLORSPACE_SRGB; + + return NULL; +} + +int OCIO_configGetIndexForColorSpace(ConstConfigRcPtr *config, const char *name) +{ + ConstColorSpaceRcPtr *cs = OCIO_configGetColorSpace(config, name); + + if (cs == COLORSPACE_LINEAR) + return 0; + else if (cs == COLORSPACE_SRGB) + return 1; + + return -1; +} + +const char *OCIO_configGetDefaultDisplay(ConstConfigRcPtr *) +{ + return "sRGB"; +} + +int OCIO_configGetNumDisplays(ConstConfigRcPtr* config) +{ + return 1; +} + +const char *OCIO_configGetDisplay(ConstConfigRcPtr *, int index) +{ + if (index == 0) + return "sRGB"; + + return NULL; +} + +const char *OCIO_configGetDefaultView(ConstConfigRcPtr *, const char *) +{ + return "Default"; +} + +int OCIO_configGetNumViews(ConstConfigRcPtr *, const char *) +{ + return 1; +} + +const char *OCIO_configGetView(ConstConfigRcPtr *, const char *, int index) +{ + if (index == 0) + return "Default"; + + return NULL; +} + +const char *OCIO_configGetDisplayColorSpaceName(ConstConfigRcPtr *, const char *, const char *) +{ + return "sRGB"; +} + +int OCIO_colorSpaceIsInvertible(ConstColorSpaceRcPtr *cs) +{ + return 1; +} + +void OCIO_colorSpaceRelease(ConstColorSpaceRcPtr *cs) +{ +} + +ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(ConstConfigRcPtr *config, const char *srcName, const char *dstName) +{ + ConstColorSpaceRcPtr *cs_src = OCIO_configGetColorSpace(config, srcName); + ConstColorSpaceRcPtr *cs_dst = OCIO_configGetColorSpace(config, dstName); + + if (cs_src == COLORSPACE_LINEAR && cs_dst == COLORSPACE_SRGB) + return PROCESSOR_LINEAR_TO_SRGB; + else if (cs_src == COLORSPACE_SRGB && cs_dst == COLORSPACE_LINEAR) + return PROCESSOR_SRGB_TO_LINEAR; + + return 0; +} + +ConstProcessorRcPtr *OCIO_configGetProcessor(ConstConfigRcPtr *, ConstTransformRcPtr *tfm) +{ + return (ConstProcessorRcPtr*)tfm; +} + +void OCIO_processorApply(ConstProcessorRcPtr *processor, PackedImageDesc *img) +{ + /* OCIO_TODO stride not respected, channels must be 3 or 4 */ + PackedImageDescription *desc = (PackedImageDescription*)img; + int channels = desc->numChannels; + float *pixels = desc->data; + int width = desc->width; + int height = desc->height; + int x, y; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + float *pixel = pixels + channels * (y * width + x); + + if (channels == 4) + OCIO_processorApplyRGBA(processor, pixel); + else if (channels == 3) + OCIO_processorApplyRGB(processor, pixel); + } + } +} + +void OCIO_processorApply_predivide(ConstProcessorRcPtr *processor, PackedImageDesc *img) +{ + /* OCIO_TODO stride not respected, channels must be 3 or 4 */ + PackedImageDescription *desc = (PackedImageDescription*)img; + int channels = desc->numChannels; + float *pixels = desc->data; + int width = desc->width; + int height = desc->height; + int x, y; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + float *pixel = pixels + channels * (y * width + x); + + if (channels == 4) + OCIO_processorApplyRGBA_predivide(processor, pixel); + else if (channels == 3) + OCIO_processorApplyRGB(processor, pixel); + } + } +} + +void OCIO_processorApplyRGB(ConstProcessorRcPtr *processor, float *pixel) +{ + if (processor == PROCESSOR_LINEAR_TO_SRGB) + linearrgb_to_srgb_v3_v3(pixel, pixel); + else if (processor == PROCESSOR_SRGB_TO_LINEAR) + srgb_to_linearrgb_v3_v3(pixel, pixel); +} + +void OCIO_processorApplyRGBA(ConstProcessorRcPtr *processor, float *pixel) +{ + if (processor == PROCESSOR_LINEAR_TO_SRGB) + linearrgb_to_srgb_v4(pixel, pixel); + else if (processor == PROCESSOR_SRGB_TO_LINEAR) + srgb_to_linearrgb_v4(pixel, pixel); +} + +void OCIO_processorApplyRGBA_predivide(ConstProcessorRcPtr *processor, float *pixel) +{ + if (pixel[3] == 1.0f || pixel[3] == 0.0f) { + OCIO_processorApplyRGBA(processor, pixel); + } + else { + float alpha, inv_alpha; + + alpha = pixel[3]; + inv_alpha = 1.0f / alpha; + + pixel[0] *= inv_alpha; + pixel[1] *= inv_alpha; + pixel[2] *= inv_alpha; + + OCIO_processorApplyRGBA(processor, pixel); + + pixel[0] *= alpha; + pixel[1] *= alpha; + pixel[2] *= alpha; + } +} + +void OCIO_processorRelease(ConstProcessorRcPtr *) +{ +} + +const char *OCIO_colorSpaceGetName(ConstColorSpaceRcPtr *cs) +{ + if (cs == COLORSPACE_LINEAR) + return "Linear"; + else if (cs == COLORSPACE_SRGB) + return "sRGB"; + + return NULL; +} + +const char *OCIO_colorSpaceGetDescription(ConstColorSpaceRcPtr *) +{ + return ""; +} + +const char *OCIO_colorSpaceGetFamily(ConstColorSpaceRcPtr *) +{ + return ""; +} + +DisplayTransformRcPtr *OCIO_createDisplayTransform(void) +{ + return (DisplayTransformRcPtr*)PROCESSOR_LINEAR_TO_SRGB; +} + +void OCIO_displayTransformSetInputColorSpaceName(DisplayTransformRcPtr *, const char *) +{ +} + +void OCIO_displayTransformSetDisplay(DisplayTransformRcPtr *, const char *) +{ +} + +void OCIO_displayTransformSetView(DisplayTransformRcPtr *, const char *) +{ +} + +void OCIO_displayTransformSetDisplayCC(DisplayTransformRcPtr *, ConstTransformRcPtr *) +{ +} + +void OCIO_displayTransformSetLinearCC(DisplayTransformRcPtr *, ConstTransformRcPtr *) +{ +} + +void OCIO_displayTransformRelease(DisplayTransformRcPtr *) +{ +} + +PackedImageDesc *OCIO_createPackedImageDesc(float *data, long width, long height, long numChannels, + long chanStrideBytes, long xStrideBytes, long yStrideBytes) +{ + PackedImageDescription *desc = (PackedImageDescription*)MEM_callocN(sizeof(PackedImageDescription), "PackedImageDescription"); + + desc->data = data; + desc->width = width; + desc->height = height; + desc->numChannels = numChannels; + desc->chanStrideBytes = chanStrideBytes; + desc->xStrideBytes = xStrideBytes; + desc->yStrideBytes = yStrideBytes; + + return (PackedImageDesc*)desc; +} + +void OCIO_packedImageDescRelease(PackedImageDesc* id) +{ + MEM_freeN(id); +} + +ExponentTransformRcPtr *OCIO_createExponentTransform(void) +{ + return (ExponentTransformRcPtr*)PROCESSOR_UNKNOWN; +} + +void OCIO_exponentTransformSetValue(ExponentTransformRcPtr *, const float *) +{ +} + +void OCIO_exponentTransformRelease(ExponentTransformRcPtr *) +{ +} + +MatrixTransformRcPtr *OCIO_createMatrixTransform(void) +{ + return (MatrixTransformRcPtr*)PROCESSOR_UNKNOWN; +} + +void OCIO_matrixTransformSetValue(MatrixTransformRcPtr *, const float *, const float *) +{ +} + +void OCIO_matrixTransformRelease(MatrixTransformRcPtr *) +{ +} + +void OCIO_matrixTransformScale(float * , float * , const float *) +{ +} + diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt index 9c707a459f2..8849265679a 100644 --- a/source/blender/imbuf/CMakeLists.txt +++ b/source/blender/imbuf/CMakeLists.txt @@ -183,14 +183,9 @@ if(WITH_IMAGE_HDR) add_definitions(-DWITH_HDR) endif() -if(WITH_OPENCOLORIO) - list(APPEND SRC - ) - list(APPEND INC - ../../../intern/opencolorio - ) - add_definitions(-DWITH_OCIO) -endif() +list(APPEND INC + ../../../intern/opencolorio +) if(WIN32) list(APPEND INC diff --git a/source/blender/imbuf/SConscript b/source/blender/imbuf/SConscript index 61cc5684356..976108cd84e 100644 --- a/source/blender/imbuf/SConscript +++ b/source/blender/imbuf/SConscript @@ -6,7 +6,7 @@ sources = env.Glob('intern/*.c') incs = '. ../makesdna ../makesrna #/intern/guardedalloc #/intern/memutil ../blenlib' incs += ' ../avi ../blenkernel ../blenloader' -incs += ' #/intern/ffmpeg' +incs += ' #/intern/ffmpeg #intern/opencolorio' incs += ' ' + env['BF_JPEG_INC'] incs += ' ' + env['BF_PNG_INC'] @@ -58,8 +58,4 @@ if env['WITH_BF_QUICKTIME']: incs += ' ../quicktime ' + env['BF_QUICKTIME_INC'] defs.append('WITH_QUICKTIME') -if env['WITH_BF_OCIO']: - defs.append('WITH_OCIO') - incs += ' #intern/opencolorio' - env.BlenderLib ( libname = 'bf_imbuf', sources = sources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [185,115] ) diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 260aef533b5..7548974f073 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -64,28 +64,19 @@ #include "RNA_define.h" -#ifdef WITH_OCIO -# include -#else -/* so function can accept processor and care about disabled OCIO inside */ -typedef struct ConstProcessorRcPtr { - int pad; -} ConstProcessorRcPtr; -#endif +#include /*********************** Global declarations *************************/ #define MAX_COLORSPACE_NAME 64 /* ** list of all supported color spaces, displays and views */ -#ifdef WITH_OCIO static char global_role_scene_linear[MAX_COLORSPACE_NAME]; static char global_role_color_picking[MAX_COLORSPACE_NAME]; static char global_role_texture_painting[MAX_COLORSPACE_NAME]; static char global_role_default_byte[MAX_COLORSPACE_NAME]; static char global_role_default_float[MAX_COLORSPACE_NAME]; static char global_role_default_sequencer[MAX_COLORSPACE_NAME]; -#endif static ListBase global_colorspaces = {NULL}; static ListBase global_displays = {NULL}; @@ -98,14 +89,6 @@ static int global_tot_view = 0; typedef struct ColormanageProcessor { ConstProcessorRcPtr *processor; CurveMapping *curve_mapping; - -#ifndef WITH_OCIO - /* this callback is only used in cases when Blender was build without OCIO - * and aimed to preserve compatibility with previous Blender versions - */ - void (*display_transform_cb_v3) (float result[3], const float pixel[3]); - void (*display_transform_predivide_cb_v4) (float result[4], const float pixel[4]); -#endif } ColormanageProcessor; /*********************** Color managed cache *************************/ @@ -222,7 +205,6 @@ static ColormnaageCacheData *colormanage_cachedata_get(const ImBuf *ibuf) return ibuf->colormanage_cache->data; } -#ifdef WITH_OCIO static unsigned int colormanage_hashhash(const void *key_v) { ColormanageCacheKey *key = (ColormanageCacheKey *)key_v; @@ -419,7 +401,6 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting IMB_moviecache_put(moviecache, &key, cache_ibuf); } -#endif static void colormanage_cache_handle_release(void *cache_handle) { @@ -430,7 +411,6 @@ static void colormanage_cache_handle_release(void *cache_handle) /*********************** Initialization / De-initialization *************************/ -#ifdef WITH_OCIO static void colormanage_role_color_space_name_get(ConstConfigRcPtr *config, char *colorspace_name, const char *role) { ConstColorSpaceRcPtr *ociocs; @@ -562,11 +542,9 @@ void colormanage_free_config(void) /* free views */ BLI_freelistN(&global_views); } -#endif void IMB_colormanagement_init(void) { -#ifdef WITH_OCIO const char *ocio_env; const char *configdir; char configfile[FILE_MAX]; @@ -594,16 +572,13 @@ void IMB_colormanagement_init(void) OCIO_configRelease(config); } -#endif BLI_init_srgb_conversion(); } void IMB_colormanagement_exit(void) { -#ifdef WITH_OCIO colormanage_free_config(); -#endif } /*********************** Internal functions *************************/ @@ -649,7 +624,6 @@ static void display_transform_get_from_ctx(const bContext *C, ColorManagedViewSe } } -#ifdef WITH_OCIO static ConstProcessorRcPtr *create_display_buffer_processor(const char *view_transform, const char *display, float exposure, float gamma) { @@ -830,7 +804,6 @@ static void init_default_view_settings(const ColorManagedDisplaySettings *displa view_settings->exposure = 0.0f; view_settings->curve_mapping = NULL; } -#endif static void curve_mapping_apply_pixel(CurveMapping *curve_mapping, float *pixel, int channels) { @@ -859,7 +832,6 @@ void colorspace_set_default_role(char *colorspace, int size, int role) void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace) { -#ifdef WITH_OCIO if (ibuf->rect_float) { const char *to_colorspace = global_role_scene_linear; int predivide = ibuf->flags & IB_cm_predivide; @@ -872,15 +844,10 @@ void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace) ibuf->profile = IB_PROFILE_LINEAR_RGB; } -#else - (void) ibuf; - (void) role; -#endif } /*********************** Generic functions *************************/ -#ifdef WITH_OCIO static void colormanage_check_display_settings(ColorManagedDisplaySettings *display_settings, const char *what, const ColorManagedDisplay *default_display) { @@ -954,11 +921,9 @@ static void colormanage_check_colorspace_settings(ColorManagedColorspaceSettings (void) what; } -#endif void IMB_colormanagement_check_file_config(Main *bmain) { -#ifdef WITH_OCIO Scene *scene; Image *image; MovieClip *clip; @@ -996,15 +961,11 @@ void IMB_colormanagement_check_file_config(Main *bmain) for (clip = bmain->movieclip.first; clip; clip = clip->id.next) { colormanage_check_colorspace_settings(&clip->colorspace_settings, "clip"); } -#else - (void) bmain; -#endif } void IMB_colormanagement_validate_settings(ColorManagedDisplaySettings *display_settings, ColorManagedViewSettings *view_settings) { -#ifdef WITH_OCIO ColorManagedDisplay *display; ColorManagedView *default_view; LinkData *view_link; @@ -1021,15 +982,10 @@ void IMB_colormanagement_validate_settings(ColorManagedDisplaySettings *display_ if (view_link == NULL) BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform)); -#else - (void) display_settings; - (void) view_settings; -#endif } const char *IMB_colormanagement_role_colorspace_name_get(int role) { -#ifdef WITH_OCIO switch (role) { case COLOR_ROLE_SCENE_LINEAR: return global_role_scene_linear; @@ -1053,9 +1009,6 @@ const char *IMB_colormanagement_role_colorspace_name_get(int role) printf("Unknown role was passed to %s\n", __func__); BLI_assert(0); } -#else - (void) role; -#endif return NULL; } @@ -1083,7 +1036,6 @@ void IMB_colormanagement_imbuf_float_from_rect(ImBuf *ibuf) /*********************** Threaded display buffer transform routines *************************/ -#ifdef WITH_OCIO typedef struct DisplayBufferThread { ColormanageProcessor *cm_processor; @@ -1317,7 +1269,6 @@ static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *displ { colormanage_display_buffer_process_ex(ibuf, NULL, display_buffer, view_settings, display_settings); } -#endif /*********************** Threaded processor transform routines *************************/ @@ -1468,7 +1419,6 @@ void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspac */ void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], ColorSpace *colorspace) { -#ifdef WITH_OCIO ConstProcessorRcPtr *processor; if (!colorspace) { @@ -1483,16 +1433,11 @@ void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], ColorSpac if (processor) OCIO_processorApplyRGB(processor, pixel); -#else - (void) pixel; - (void) colorspace; -#endif } /* same as above, but converts colors in opposite direction */ void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], ColorSpace *colorspace) { -#ifdef WITH_OCIO ConstProcessorRcPtr *processor; if (!colorspace) { @@ -1507,16 +1452,10 @@ void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], ColorSpac if (processor) OCIO_processorApplyRGB(processor, pixel); - -#else - (void) pixel; - (void) colorspace; -#endif } void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, int predivide) { -#ifdef WITH_OCIO ConstProcessorRcPtr *processor; if (!colorspace) { @@ -1542,14 +1481,6 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, in OCIO_packedImageDescRelease(img); } -#else - (void) buffer; - (void) channels; - (void) width; - (void) height; - (void) colorspace; - (void) predivide; -#endif } /* convert pixel from scene linear to display space using default view @@ -1558,33 +1489,23 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, in */ void IMB_colormanagement_scene_linear_to_display_v3(float pixel[3], ColorManagedDisplay *display) { -#ifdef WITH_OCIO ConstProcessorRcPtr *processor; processor = display_from_scene_linear_processor(display); if (processor) OCIO_processorApplyRGB(processor, pixel); -#else - (void) pixel; - (void) display; -#endif } /* same as above, but converts color in opposite direction */ void IMB_colormanagement_display_to_scene_linear_v3(float pixel[3], ColorManagedDisplay *display) { -#ifdef WITH_OCIO ConstProcessorRcPtr *processor; processor = display_to_scene_linear_processor(display); if (processor) OCIO_processorApplyRGB(processor, pixel); -#else - (void) pixel; - (void) display; -#endif } void IMB_colormanagement_pixel_to_display_space_v4(float result[4], const float pixel[4], @@ -1615,7 +1536,6 @@ void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float void IMB_colormanagement_imbuf_assign_spaces(ImBuf *ibuf, ColorManagedColorspaceSettings *colorspace_settings) { -#ifdef WITH_OCIO if (colorspace_settings) { if (colorspace_settings->name[0] == '\0') { /* when opening new image, assign it's color space based on default roles */ @@ -1634,10 +1554,6 @@ void IMB_colormanagement_imbuf_assign_spaces(ImBuf *ibuf, ColorManagedColorspace else ibuf->rect_colorspace = colormanage_colorspace_get_named(global_role_default_byte); } -#else - (void) ibuf; - (void) colorspace_settings; -#endif } void IMB_colormanagement_imbuf_assign_float_space(ImBuf *ibuf, ColorManagedColorspaceSettings *colorspace_settings) @@ -1648,7 +1564,6 @@ void IMB_colormanagement_imbuf_assign_float_space(ImBuf *ibuf, ColorManagedColor void IMB_colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { -#ifdef WITH_OCIO /* OCIO_TODO: byte buffer management is not supported here yet */ if (!ibuf->rect_float) return; @@ -1660,13 +1575,6 @@ void IMB_colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManage else { colormanage_display_buffer_process_ex(ibuf, ibuf->rect_float, NULL, view_settings, display_settings); } -#else - (void) view_settings; - (void) display_settings; - - IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float, ibuf->channels, IB_PROFILE_LINEAR_RGB, ibuf->profile, - ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x); -#endif } static void imbuf_verify_float(ImBuf *ibuf) @@ -1708,7 +1616,6 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet return (unsigned char *) ibuf->rect; } -#ifdef WITH_OCIO else { unsigned char *display_buffer; int buffer_size; @@ -1766,12 +1673,6 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet return display_buffer; } -#else - (void) view_settings; - (void) display_settings; - - return NULL; -#endif } /* same as IMB_display_buffer_acquire but gets view and display settings from context */ @@ -1789,7 +1690,6 @@ unsigned char *IMB_display_buffer_acquire_ctx(const bContext *C, ImBuf *ibuf, vo void IMB_display_buffer_to_imbuf_rect(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { -#ifdef WITH_OCIO if (global_tot_display == 0 || global_tot_view == 0) { imbuf_verify_float(ibuf); } @@ -1800,19 +1700,12 @@ void IMB_display_buffer_to_imbuf_rect(ImBuf *ibuf, const ColorManagedViewSetting colormanage_display_buffer_process(ibuf, (unsigned char *) ibuf->rect, view_settings, display_settings); } -#else - (void) view_settings; - (void) display_settings; - - imbuf_verify_float(ibuf); -#endif } void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *linear_buffer, int width, int height, int channels, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, int predivide) { -#ifdef WITH_OCIO if (global_tot_display == 0 || global_tot_view == 0) { IMB_buffer_byte_from_float(display_buffer, linear_buffer, 4, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, FALSE, width, height, width, width); @@ -1833,13 +1726,6 @@ void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *li MEM_freeN(buffer); } -#else - (void) view_settings; - (void) display_settings; - - IMB_buffer_byte_from_float(display_buffer, linear_buffer, channels, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide, - width, height, width, width); -#endif } void IMB_display_buffer_release(void *cache_handle) @@ -1855,7 +1741,6 @@ void IMB_display_buffer_release(void *cache_handle) /*********************** Display functions *************************/ -#ifdef WITH_OCIO ColorManagedDisplay *colormanage_display_get_default(void) { ConstConfigRcPtr *config = OCIO_getCurrentConfig(); @@ -1876,7 +1761,6 @@ ColorManagedDisplay *colormanage_display_get_default(void) return colormanage_display_get_named(display); } -#endif ColorManagedDisplay *colormanage_display_add(const char *name) { @@ -1946,13 +1830,9 @@ const char *IMB_colormanagement_display_get_indexed_name(int index) const char *IMB_colormanagement_display_get_default_name(void) { -#ifdef WITH_OCIO ColorManagedDisplay *display = colormanage_display_get_default(); return display->name; -#else - return NULL; -#endif } /* used by performance-critical pixel processing areas, such as color widgets */ @@ -1963,7 +1843,6 @@ ColorManagedDisplay *IMB_colormanagement_display_get_named(const char *name) /*********************** View functions *************************/ -#ifdef WITH_OCIO const char *colormanage_view_get_default_name(const ColorManagedDisplay *display) { ConstConfigRcPtr *config = OCIO_getCurrentConfig(); @@ -1991,7 +1870,6 @@ ColorManagedView *colormanage_view_get_default(const ColorManagedDisplay *displa return colormanage_view_get_named(name); } -#endif ColorManagedView *colormanage_view_add(const char *name) { @@ -2051,16 +1929,12 @@ const char *IMB_colormanagement_view_get_indexed_name(int index) const char *IMB_colormanagement_view_get_default_name(const char *display_name) { -#if WITH_OCIO ColorManagedDisplay *display = colormanage_display_get_named(display_name); ColorManagedView *view = colormanage_view_get_default(display); if (view) { return view->name; } -#else - (void) display_name; -#endif return NULL; } @@ -2277,7 +2151,6 @@ void IMB_colormanagement_colorspace_items_add(EnumPropertyItem **items, int *tot * the rest buffers would be marked as dirty */ -#ifdef WITH_OCIO static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffer, const float *linear_buffer, const unsigned char *byte_buffer, int display_stride, int linear_stride, int linear_offset_x, int linear_offset_y, ColormanageProcessor *cm_processor, @@ -2336,7 +2209,6 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe MEM_freeN(display_buffer_float); } } -#endif void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, const unsigned char *byte_buffer, int stride, int offset_x, int offset_y, const ColorManagedViewSettings *view_settings, @@ -2362,7 +2234,6 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, IB_PROFILE_SRGB, profile_from, predivide, width, height, ibuf->x, stride); } -#ifdef WITH_OCIO if (ibuf->display_buffer_flags) { ColormanageCacheViewSettings cache_view_settings; ColormanageCacheDisplaySettings cache_display_settings; @@ -2405,11 +2276,6 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, IMB_display_buffer_release(cache_handle); } } -#else - (void) byte_buffer; - (void) view_settings; - (void) display_settings; -#endif } /*********************** Pixel processor functions *************************/ @@ -2421,7 +2287,6 @@ ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManag cm_processor = MEM_callocN(sizeof(ColormanageProcessor), "colormanagement processor"); -#ifdef WITH_OCIO { ColorManagedViewSettings default_view_settings; const ColorManagedViewSettings *applied_view_settings; @@ -2442,16 +2307,6 @@ ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManag curvemapping_premultiply(cm_processor->curve_mapping, FALSE); } } -#else - (void) view_settings; - (void) display_settings; - - /* assume input is in linear space and color management is always enabled - * seams to be quite reasonable behavior in cases there's no OCIO - */ - cm_processor->display_transform_cb_v3 = linearrgb_to_srgb_v3_v3; - cm_processor->display_transform_predivide_cb_v4 = linearrgb_to_srgb_predivide_v4; -#endif return cm_processor; } @@ -2462,12 +2317,7 @@ ColormanageProcessor *IMB_colormanagement_colorspace_processor_new(const char *f cm_processor = MEM_callocN(sizeof(ColormanageProcessor), "colormanagement processor"); -#ifdef WITH_OCIO cm_processor->processor = create_colorspace_transform_processor(from_colorspace, to_colorspace); -#else - (void) from_colorspace; - (void) to_colorspace; -#endif return cm_processor; } @@ -2477,12 +2327,7 @@ void IMB_colormanagement_processor_apply_v4(ColormanageProcessor *cm_processor, if (cm_processor->curve_mapping) curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel); -#ifdef WITH_OCIO OCIO_processorApplyRGBA(cm_processor->processor, pixel); -#else - if (cm_processor->display_transform_cb_v3) - cm_processor->display_transform_cb_v3(pixel, pixel); -#endif } void IMB_colormanagement_processor_apply_v3(ColormanageProcessor *cm_processor, float pixel[3]) @@ -2490,12 +2335,7 @@ void IMB_colormanagement_processor_apply_v3(ColormanageProcessor *cm_processor, if (cm_processor->curve_mapping) curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel); -#ifdef WITH_OCIO OCIO_processorApplyRGB(cm_processor->processor, pixel); -#else - if (cm_processor->display_transform_cb_v3) - cm_processor->display_transform_cb_v3(pixel, pixel); -#endif } void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, float *buffer, int width, int height, @@ -2514,7 +2354,6 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, flo } } -#ifdef WITH_OCIO { PackedImageDesc *img; @@ -2529,37 +2368,14 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, flo OCIO_packedImageDescRelease(img); } -#else - if (cm_processor->display_transform_cb_v3) { - int x, y; - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - float *pixel = buffer + channels * (y * width + x); - - if (channels == 3) { - cm_processor->display_transform_cb_v3(pixel, pixel); - } - else if (channels == 4) { - if (!predivide) - cm_processor->display_transform_predivide_cb_v4(pixel, pixel); - else - cm_processor->display_transform_cb_v3(pixel, pixel); - } - } - } - } -#endif } void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor) { -#ifdef WITH_OCIO if (cm_processor->curve_mapping) curvemapping_free(cm_processor->curve_mapping); OCIO_processorRelease(cm_processor->processor); -#endif MEM_freeN(cm_processor); } From be5a35d91630bc0a4db9d655d9f0a8275b25c7ac Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 14 Sep 2012 14:37:19 +0000 Subject: [PATCH 147/160] Color Management: get rid of image buffer's profile flag Currently float buffers are always linear, space of byte buffer is defined by rect_colorspace property. Replaced logic of IMB_rect_from_float and IMB_float_from_rect to use this assumptions (before it was special function used in some areas only, now it's default behavior). Almost all functions from ImBuf module which are actually used are got rid from profile flag. Only remained issue is IMB_float_profile_ensure which only used by CIneon/DPX exporter which is broken for a while already. Need to be fixed separately. This also fixed clone brush when cloning byte image on top of float, before this result would be gamma-corrected twice. --- source/blender/blenkernel/intern/image.c | 5 - source/blender/blenkernel/intern/ocean.c | 2 - source/blender/blenkernel/intern/sequencer.c | 19 +-- source/blender/blenkernel/intern/tracking.c | 3 - .../operations/COM_ImageOperation.cpp | 2 +- source/blender/editors/render/render_opengl.c | 50 +++--- .../blender/editors/render/render_preview.c | 4 +- .../editors/sculpt_paint/paint_image.c | 22 +-- .../blender/editors/space_clip/clip_editor.c | 8 +- .../blender/editors/space_image/image_ops.c | 8 +- source/blender/editors/space_node/node_view.c | 11 +- source/blender/gpu/intern/gpu_draw.c | 8 +- source/blender/imbuf/IMB_colormanagement.h | 2 - source/blender/imbuf/IMB_imbuf.h | 1 - source/blender/imbuf/IMB_imbuf_types.h | 1 - .../imbuf/intern/IMB_colormanagement_intern.h | 1 + source/blender/imbuf/intern/allocimbuf.c | 3 + source/blender/imbuf/intern/anim_movie.c | 4 - source/blender/imbuf/intern/bmp.c | 1 - source/blender/imbuf/intern/colormanagement.c | 60 +------ source/blender/imbuf/intern/dds/dds_api.cpp | 1 - source/blender/imbuf/intern/divers.c | 137 +++++----------- source/blender/imbuf/intern/iris.c | 1 - source/blender/imbuf/intern/jp2.c | 147 +++++------------- source/blender/imbuf/intern/jpeg.c | 1 - .../imbuf/intern/openexr/openexr_api.cpp | 34 +--- source/blender/imbuf/intern/png.c | 4 - source/blender/imbuf/intern/radiance_hdr.c | 1 - source/blender/imbuf/intern/readimage.c | 2 +- source/blender/imbuf/intern/targa.c | 1 - source/blender/imbuf/intern/tiff.c | 7 +- .../composite/nodes/node_composite_image.c | 26 +--- .../nodes/node_composite_outputFile.c | 6 - source/blender/quicktime/apple/qtkit_import.m | 1 - .../quicktime/apple/quicktime_import.c | 2 - source/blender/render/intern/source/envmap.c | 2 - .../render/intern/source/render_result.c | 6 +- .../blender/render/intern/source/rendercore.c | 2 - 38 files changed, 159 insertions(+), 437 deletions(-) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index ce3e99a0807..f08af55c36e 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -612,12 +612,10 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char if (floatbuf) { ibuf = IMB_allocImBuf(width, height, depth, IB_rectfloat); rect_float = ibuf->rect_float; - ibuf->profile = IB_PROFILE_LINEAR_RGB; } else { ibuf = IMB_allocImBuf(width, height, depth, IB_rect); rect = (unsigned char *)ibuf->rect; - ibuf->profile = IB_PROFILE_SRGB; } BLI_strncpy(ibuf->name, name, sizeof(ibuf->name)); @@ -2330,7 +2328,6 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int f ibuf->flags |= IB_rectfloat; ibuf->mall = IB_rectfloat; ibuf->channels = rpass->channels; - ibuf->profile = IB_PROFILE_LINEAR_RGB; image_initialize_after_load(ima, ibuf); image_assign_ibuf(ima, ibuf, iuser ? iuser->multi_index : 0, frame); @@ -2481,7 +2478,6 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser) ibuf->rect_float = rpass->rect; ibuf->flags |= IB_rectfloat; ibuf->channels = rpass->channels; - ibuf->profile = IB_PROFILE_LINEAR_RGB; image_assign_ibuf(ima, ibuf, iuser ? iuser->multi_index : IMA_NO_INDEX, 0); } @@ -2630,7 +2626,6 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ BLI_unlock_thread(LOCK_COLORMANAGE); - ibuf->profile = IB_PROFILE_LINEAR_RGB; ibuf->dither = dither; if (iuser->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE) { diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 46b89f76194..4f3921936e8 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -1173,8 +1173,6 @@ void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(v ibuf_disp = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat); ibuf_normal = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat); - ibuf_disp->profile = ibuf_foam->profile = ibuf_normal->profile = IB_PROFILE_LINEAR_RGB; - BKE_simulate_ocean(o, och->time[i], och->wave_scale, och->chop_amount); /* add new foam */ diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 1d4efb01aa2..20db9d5e056 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -313,7 +313,6 @@ void BKE_sequencer_editing_free(Scene *scene) void BKE_sequencer_imbuf_assign_spaces(Scene *scene, ImBuf *ibuf) { - IMB_colormanagement_imbuf_assign_spaces(ibuf, NULL); IMB_colormanagement_imbuf_assign_float_space(ibuf, &scene->sequencer_colorspace_settings); } @@ -335,7 +334,7 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_ * OCIO_TODO: would be nice to support direct single transform from byte to sequencer's */ - IMB_colormanagement_imbuf_float_from_rect(ibuf); + IMB_float_from_rect(ibuf); } else { /* if there's only byte buffer in image it's already in compositor's working space, @@ -352,12 +351,6 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_ IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, predivide); - - ibuf->profile = IB_PROFILE_SRGB; - } - else { - /* if no color management enables fallback to legacy conversion */ - IMB_convert_profile(ibuf, IB_PROFILE_NONE); } } @@ -374,12 +367,6 @@ void BKE_sequencer_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf) IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, predivide); - - ibuf->profile = IB_PROFILE_LINEAR_RGB; - } - else { - /* if no color management enables fallback to legacy conversion */ - IMB_convert_profile(ibuf, IB_PROFILE_LINEAR_RGB); } } @@ -2441,7 +2428,6 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float } /* float buffers in the sequencer are not linear */ - ibuf->profile = IB_PROFILE_LINEAR_RGB; BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf, FALSE); } else if (rres.rect32) { @@ -2549,8 +2535,7 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo imb_freerectImBuf(ibuf); /* all sequencer color is done in SRGB space, linear gives odd crossfades */ - if (ibuf->profile == IB_PROFILE_LINEAR_RGB) - BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf, FALSE); + BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf, FALSE); copy_to_ibuf_still(context, seq, nr, ibuf); diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 2ed9d992c3f..c0c5c579133 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1627,7 +1627,6 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *sea float *mask = NULL; pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat); - pattern_ibuf->profile = IB_PROFILE_LINEAR_RGB; if (!search_ibuf->rect_float) { IMB_float_from_rect(search_ibuf); @@ -1722,7 +1721,6 @@ ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mov h = (marker->search_max[1] - marker->search_min[1]) * ibuf->y; searchibuf = IMB_allocImBuf(w, h, 32, ibuf->rect_float ? IB_rectfloat : IB_rect); - searchibuf->profile = ibuf->profile; IMB_rectcpy(searchibuf, ibuf, 0, 0, x, y, w, h); @@ -3317,7 +3315,6 @@ static ImBuf *stabilization_allocate_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int } else { cacheibuf = IMB_allocImBuf(srcibuf->x, srcibuf->y, srcibuf->planes, flags); - cacheibuf->profile = srcibuf->profile; } return cacheibuf; diff --git a/source/blender/compositor/operations/COM_ImageOperation.cpp b/source/blender/compositor/operations/COM_ImageOperation.cpp index 4c454d90fb6..fb3efbb67ed 100644 --- a/source/blender/compositor/operations/COM_ImageOperation.cpp +++ b/source/blender/compositor/operations/COM_ImageOperation.cpp @@ -71,7 +71,7 @@ ImBuf *BaseImageOperation::getImBuf() } if (ibuf->rect_float == NULL) { - IMB_colormanagement_imbuf_float_from_rect(ibuf); + IMB_float_from_rect(ibuf); } return ibuf; } diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 3217acaef16..d9618e89b68 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -144,22 +144,30 @@ static void screen_opengl_render_apply(OGLRender *oglrender) ibuf = BKE_sequencer_give_ibuf(context, CFRA, chanshown); if (ibuf) { + ImBuf *linear_ibuf; + BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y)); - if (ibuf->rect_float == NULL) { - /* internally sequencer working in sRGB space and stores both bytes and float - * buffers in sRGB space, but if byte->float onversion doesn't happen in sequencer - * (e.g. when adding image sequence/movie into sequencer) there'll be only - * byte buffer and profile will still indicate sRGB->linear space conversion is needed - * here we're ensure there'll be no conversion happen and float buffer would store - * linear frame (sergey) */ - ibuf->profile = IB_PROFILE_NONE; - IMB_float_from_rect(ibuf); + linear_ibuf = IMB_dupImBuf(ibuf); + IMB_freeImBuf(ibuf); + + if (linear_ibuf->rect_float == NULL) { + /* internally sequencer working in display space and stores both bytes and float buffers in that space. + * It is possible that byte->float onversion didn't happen in sequencer (e.g. when adding image sequence/movie + * into sequencer) there'll be only byte buffer. Create float buffer from existing byte buffer, making it linear + */ + + IMB_float_from_rect(linear_ibuf); + } + else { + /* ensure float buffer is in linear space, not in display space */ + BKE_sequencer_imbuf_from_sequencer_space(scene, linear_ibuf); } - memcpy(rr->rectf, ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey); - IMB_freeImBuf(ibuf); + memcpy(rr->rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey); + + IMB_freeImBuf(linear_ibuf); } } else if (view_context) { @@ -234,11 +242,6 @@ static void screen_opengl_render_apply(OGLRender *oglrender) } } - /* rr->rectf is now filled with image data */ - - if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) - BKE_stamp_buf(scene, camera, NULL, rr->rectf, rr->rectx, rr->recty, 4); - /* note on color management: * * OpenGL renders into sRGB colors, but render buffers are expected to be @@ -247,9 +250,18 @@ static void screen_opengl_render_apply(OGLRender *oglrender) * correct linear float buffer. */ - IMB_buffer_float_from_float(rr->rectf, rr->rectf, - 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, FALSE, - oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex); + 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, FALSE, + oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex); + } + + /* rr->rectf is now filled with image data */ + + if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) + BKE_stamp_buf(scene, camera, NULL, rr->rectf, rr->rectx, rr->recty, 4); RE_ReleaseResult(oglrender->re); diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 4b8411ea8a1..a829ef57b85 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -535,12 +535,12 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int } else { - /* OCIO_TODO: currently seems an exception for textures, + /* OCIO_TODO: currently seems an exception for textures (came fro mlegacish time), * but is it indeed expected behavior, or textures should be * color managed as well? */ IMB_buffer_byte_from_float(rect_byte, rres.rectf, - 4, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, do_predivide, + 4, dither, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, do_predivide, rres.rectx, rres.recty, rres.rectx, rres.rectx); } diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 386342d7b38..6f51c5a98e6 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -155,7 +155,6 @@ typedef struct ImagePaintState { Image *image; ImBuf *canvas; ImBuf *clonecanvas; - short clonefreefloat; char *warnpackedfile; char *warnmultifile; @@ -3947,7 +3946,7 @@ static void *do_projectpaint_thread(void *ph_v) last_projIma->touch = 1; is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0; - use_color_correction = (last_projIma->ibuf->profile == IB_PROFILE_LINEAR_RGB) ? 1 : 0; + use_color_correction = TRUE; } /* end copy */ @@ -4030,7 +4029,7 @@ static void *do_projectpaint_thread(void *ph_v) last_projIma->touch = 1; is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0; - use_color_correction = (last_projIma->ibuf->profile == IB_PROFILE_LINEAR_RGB) ? 1 : 0; + use_color_correction = TRUE; } /* end copy */ @@ -4580,15 +4579,7 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima) /* temporarily add float rect for cloning */ if (s->canvas->rect_float && !s->clonecanvas->rect_float) { - short profile = IB_PROFILE_NONE; - - /* Don't want to color manage, but don't disturb existing profiles */ - SWAP(short, s->clonecanvas->profile, profile); - IMB_float_from_rect(s->clonecanvas); - s->clonefreefloat = 1; - - SWAP(short, s->clonecanvas->profile, profile); } else if (!s->canvas->rect_float && !s->clonecanvas->rect) IMB_rect_from_float(s->clonecanvas); @@ -4597,10 +4588,8 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima) return 1; } -static void imapaint_canvas_free(ImagePaintState *s) +static void imapaint_canvas_free(ImagePaintState *UNUSED(s)) { - if (s->clonefreefloat) - imb_freerectfloatImBuf(s->clonecanvas); } static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, Image *image, short texpaint, float *uv, double time, int update, float pressure) @@ -4616,7 +4605,10 @@ static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, BKE_brush_painter_require_imbuf(painter, ((ibuf->rect_float) ? 1 : 0), 0, 0); - if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, ibuf->profile == IB_PROFILE_LINEAR_RGB)) { + /* OCIO_TODO: float buffers are now always linear, so always use color correction + * this should probably be changed when texture painting color space is supported + */ + if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, TRUE)) { if (update) imapaint_image_update(s->scene, s->sima, image, ibuf, texpaint); return 1; diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 0225758de48..f2a48f299cf 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -277,13 +277,7 @@ int ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r_ if (ibuf->rect_float) { fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x)); - /* IB_PROFILE_NONE is default but infact its linear */ - if (ELEM(ibuf->profile, IB_PROFILE_LINEAR_RGB, IB_PROFILE_NONE)) { - linearrgb_to_srgb_v3_v3(r_col, fp); - } - else { - copy_v3_v3(r_col, fp); - } + linearrgb_to_srgb_v3_v3(r_col, fp); ret = TRUE; } else if (ibuf->rect) { diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 563680f5743..616587b0b19 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -2047,13 +2047,7 @@ int ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], floa if (ibuf->rect_float) { fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x)); - - if (ELEM(ibuf->profile, IB_PROFILE_LINEAR_RGB, IB_PROFILE_NONE)) { - linearrgb_to_srgb_v3_v3(r_col, fp); - } - else { - copy_v3_v3(r_col, fp); - } + linearrgb_to_srgb_v3_v3(r_col, fp); ret = TRUE; } else if (ibuf->rect) { diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index 9e3a537fb5b..8e38247348f 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -381,12 +381,7 @@ int ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float if (ibuf->rect_float) { fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x)); /* IB_PROFILE_NONE is default but infact its linear */ - if (ELEM(ibuf->profile, IB_PROFILE_LINEAR_RGB, IB_PROFILE_NONE)) { - linearrgb_to_srgb_v3_v3(r_col, fp); - } - else { - copy_v3_v3(r_col, fp); - } + linearrgb_to_srgb_v3_v3(r_col, fp); ret = TRUE; } else if (ibuf->rect) { @@ -419,10 +414,6 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) } if (!ibuf->rect) { - if (info->color_manage) - ibuf->profile = IB_PROFILE_LINEAR_RGB; - else - ibuf->profile = IB_PROFILE_NONE; IMB_rect_from_float(ibuf); } diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 95e2889f23c..af52366c964 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -492,7 +492,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int } /* TODO unneeded when float images are correctly treated as linear always */ - if (!ncd && ibuf->profile == IB_PROFILE_LINEAR_RGB) + if (!ncd) do_color_management = TRUE; if (ibuf->rect==NULL) @@ -535,7 +535,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int if (do_color_management) { srgb_frect = MEM_mallocN(ibuf->x*ibuf->y*sizeof(float)*4, "floar_buf_col_cor"); IMB_buffer_float_from_float(srgb_frect, ibuf->rect_float, - ibuf->channels, IB_PROFILE_SRGB, ibuf->profile, 0, + ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, 0, ibuf->x, ibuf->y, ibuf->x, ibuf->x); /* clamp buffer colors to 1.0 to avoid artifacts due to glu for hdr images */ IMB_buffer_float_clamp(srgb_frect, ibuf->x, ibuf->y); @@ -560,7 +560,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int if (do_color_management) { frect = srgb_frect = MEM_mallocN(ibuf->x*ibuf->y*sizeof(*srgb_frect)*4, "floar_buf_col_cor"); IMB_buffer_float_from_float(srgb_frect, ibuf->rect_float, - ibuf->channels, IB_PROFILE_SRGB, ibuf->profile, 0, + ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, 0, ibuf->x, ibuf->y, ibuf->x, ibuf->x); /* clamp buffer colors to 1.0 to avoid artifacts due to glu for hdr images */ IMB_buffer_float_clamp(srgb_frect, ibuf->x, ibuf->y); @@ -901,7 +901,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h, int mipmap) glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows); /* if color correction is needed, we must update the part that needs updating. */ - if (ibuf->rect_float && (!U.use_16bit_textures || (ibuf->profile == IB_PROFILE_LINEAR_RGB))) { + if (ibuf->rect_float) { float *buffer = MEM_mallocN(w*h*sizeof(float)*4, "temp_texpaint_float_buf"); IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h); diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index e5632d41125..d09007985b0 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -62,7 +62,6 @@ void IMB_colormanagement_validate_settings(struct ColorManagedDisplaySettings *d struct ColorManagedViewSettings *view_settings); const char *IMB_colormanagement_role_colorspace_name_get(int role); -void IMB_colormanagement_imbuf_float_from_rect(struct ImBuf *ibuf); /* ** Color space transformation functions ** */ void IMB_colormanagement_transform(float *buffer, int width, int height, int channels, @@ -85,7 +84,6 @@ void IMB_colormanagement_pixel_to_display_space_v4(float result[4], const float void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float pixel[3], const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings); -void IMB_colormanagement_imbuf_assign_spaces(struct ImBuf *ibuf, struct ColorManagedColorspaceSettings *colorspace_settings); void IMB_colormanagement_imbuf_assign_float_space(struct ImBuf *ibuf, struct ColorManagedColorspaceSettings *colorspace_settings); void IMB_colormanagement_imbuf_make_display_space(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index a8780d3f205..1503b9f6f67 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -375,7 +375,6 @@ void IMB_partial_rect_from_float(struct ImBuf *ibuf, float *buffer, int x, int y void IMB_float_from_rect(struct ImBuf *ibuf); void IMB_float_from_rect_simple(struct ImBuf *ibuf); /* no profile conversion */ /* note, check that the conversion exists, only some are supported */ -void IMB_convert_profile(struct ImBuf *ibuf, int profile); float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc); void IMB_color_to_bw(struct ImBuf *ibuf); void IMB_saturation(struct ImBuf *ibuf, float sat); diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index cda43199be5..93e213dc486 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -101,7 +101,6 @@ typedef struct ImBuf { /* parameters used by conversion between byte and float */ float dither; /* random dither value, for conversion from float -> byte rect */ - short profile; /* color space/profile preset that the byte rect buffer represents */ /* mipmapping */ struct ImBuf *mipmap[IB_MIPMAP_LEVELS]; /* MipMap levels, a series of halved images */ diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index 67c99d51fd4..0c002b78848 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -86,6 +86,7 @@ struct ColorSpace *colormanage_colorspace_get_indexed(int index); void colorspace_set_default_role(char *colorspace, int size, int role); +void colormanage_imbuf_set_default_spaces(struct ImBuf *ibuf); void colormanage_imbuf_make_linear(struct ImBuf *ibuf, const char *from_colorspace); #endif /* IMB_COLORMANAGEMENT_INTERN_H */ diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index 32c14e3a8b7..69048274104 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -386,6 +386,9 @@ ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar planes, unsigned int return NULL; } } + + /* assign default spaces */ + colormanage_imbuf_set_default_spaces(ibuf); } return (ibuf); } diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index fa8cc6c818a..394f5169046 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -443,7 +443,6 @@ static ImBuf *avi_fetchibuf(struct anim *anim, int position) MEM_freeN(tmp); } - ibuf->profile = IB_PROFILE_SRGB; ibuf->rect_colorspace = colormanage_colorspace_get_named(anim->colorspace); return ibuf; @@ -646,8 +645,6 @@ static void ffmpeg_postprocess(struct anim *anim) ImBuf *ibuf = anim->last_frame; int filter_y = 0; - ibuf->profile = IB_PROFILE_SRGB; - if (!anim->pFrameComplete) { return; } @@ -1332,7 +1329,6 @@ struct ImBuf *IMB_anim_absolute(struct anim *anim, int position, if (ibuf) { anim->curposition = position; IMB_convert_rgba_to_abgr(ibuf); - ibuf->profile = IB_PROFILE_SRGB; } break; case ANIM_AVI: diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c index 5e7b1b839e9..df12f0b703e 100644 --- a/source/blender/imbuf/intern/bmp.c +++ b/source/blender/imbuf/intern/bmp.c @@ -200,7 +200,6 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char co if (ibuf) { ibuf->ftype = BMP; - ibuf->profile = IB_PROFILE_SRGB; } return(ibuf); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 7548974f073..7fa14dd6bd1 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -830,6 +830,11 @@ void colorspace_set_default_role(char *colorspace, int size, int role) } } +void colormanage_imbuf_set_default_spaces(ImBuf *ibuf) +{ + ibuf->rect_colorspace = colormanage_colorspace_get_named(global_role_default_byte); +} + void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace) { if (ibuf->rect_float) { @@ -841,8 +846,6 @@ void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace) IMB_colormanagement_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, predivide); - - ibuf->profile = IB_PROFILE_LINEAR_RGB; } } @@ -912,7 +915,7 @@ static void colormanage_check_colorspace_settings(ColorManagedColorspaceSettings ColorSpace *colorspace = colormanage_colorspace_get_named(colorspace_settings->name); if (!colorspace) { - printf("Color management: %s colorspace \"%s\" not found, setting NONE instead.\n", + printf("Color management: %s colorspace \"%s\" not found, will use default instead.\n", what, colorspace_settings->name); BLI_strncpy(colorspace_settings->name, "", sizeof(colorspace_settings->name)); @@ -1013,27 +1016,6 @@ const char *IMB_colormanagement_role_colorspace_name_get(int role) return NULL; } -void IMB_colormanagement_imbuf_float_from_rect(ImBuf *ibuf) -{ - int predivide = ibuf->flags & IB_cm_predivide; - - if (ibuf->rect == NULL) - return; - - if (ibuf->rect_float == NULL) { - if (imb_addrectfloatImBuf(ibuf) == 0) - return; - } - - /* first, create float buffer in non-linear space */ - IMB_buffer_float_from_byte(ibuf->rect_float, (unsigned char *) ibuf->rect, IB_PROFILE_SRGB, IB_PROFILE_SRGB, - FALSE, ibuf->x, ibuf->y, ibuf->x, ibuf->x); - - /* then make float be in linear space */ - IMB_colormanagement_colorspace_to_scene_linear(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - ibuf->rect_colorspace, predivide); -} - /*********************** Threaded display buffer transform routines *************************/ typedef struct DisplayBufferThread { @@ -1534,28 +1516,6 @@ void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float IMB_colormanagement_processor_free(cm_processor); } -void IMB_colormanagement_imbuf_assign_spaces(ImBuf *ibuf, ColorManagedColorspaceSettings *colorspace_settings) -{ - if (colorspace_settings) { - if (colorspace_settings->name[0] == '\0') { - /* when opening new image, assign it's color space based on default roles */ - - if (ibuf->rect_float) - BLI_strncpy(colorspace_settings->name, global_role_default_float, MAX_COLORSPACE_NAME); - else - BLI_strncpy(colorspace_settings->name, global_role_default_byte, MAX_COLORSPACE_NAME); - } - - ibuf->rect_colorspace = colormanage_colorspace_get_named(colorspace_settings->name); - } - else { - if (ibuf->rect_float) - ibuf->rect_colorspace = colormanage_colorspace_get_named(global_role_default_float); - else - ibuf->rect_colorspace = colormanage_colorspace_get_named(global_role_default_byte); - } -} - void IMB_colormanagement_imbuf_assign_float_space(ImBuf *ibuf, ColorManagedColorspaceSettings *colorspace_settings) { ibuf->float_colorspace = colormanage_colorspace_get_named(colorspace_settings->name); @@ -1569,7 +1529,7 @@ void IMB_colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManage return; if (global_tot_display == 0 || global_tot_view == 0) { - IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float, ibuf->channels, IB_PROFILE_LINEAR_RGB, ibuf->profile, + IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float, ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x); } else { @@ -2221,17 +2181,13 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, unsigned char *rect = (unsigned char *) ibuf->rect; int predivide = ibuf->flags & IB_cm_predivide; int channels = ibuf->channels; - int profile_from = ibuf->profile; int width = xmax - xmin; int height = ymax - ymin; int rect_index = (ymin * ibuf->x + xmin) * channels; int linear_index = ((ymin - offset_y) * stride + (xmin - offset_x)) * channels; - if (profile_from == IB_PROFILE_NONE) - profile_from = IB_PROFILE_LINEAR_RGB; - IMB_buffer_byte_from_float(rect + rect_index, linear_buffer + linear_index, channels, ibuf->dither, - IB_PROFILE_SRGB, profile_from, predivide, width, height, ibuf->x, stride); + IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide, width, height, ibuf->x, stride); } if (ibuf->display_buffer_flags) { diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index 676dde138d1..7aacbf20bae 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -142,7 +142,6 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags, char colo if (ibuf == 0) return(0); /* memory allocation failed */ ibuf->ftype = DDS; - ibuf->profile = IB_PROFILE_SRGB; ibuf->dds_data.fourcc = dds.fourCC(); ibuf->dds_data.nummipmaps = dds.mipmapCount(); diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 5ba08f1dd73..5e38c31f4c7 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -40,6 +40,9 @@ #include "IMB_imbuf.h" #include "IMB_allocimbuf.h" +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" + #include "MEM_guardedalloc.h" /**************************** Interlace/Deinterlace **************************/ @@ -522,32 +525,34 @@ void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from, void IMB_rect_from_float(ImBuf *ibuf) { int predivide = (ibuf->flags & IB_cm_predivide); - int profile_from; + float *buffer; + const char *from_colorspace; /* verify we have a float buffer */ if (ibuf->rect_float == NULL) return; /* create byte rect if it didn't exist yet */ - if (ibuf->rect == NULL) - imb_addrectImBuf(ibuf); - - /* determine profiles */ - if (ibuf->profile == IB_PROFILE_LINEAR_RGB) { - profile_from = IB_PROFILE_LINEAR_RGB; - } - else if (ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE)) { - profile_from = IB_PROFILE_SRGB; - } - else { - profile_from = IB_PROFILE_SRGB; /* should never happen */ - BLI_assert(0); + if (ibuf->rect == NULL) { + if (imb_addrectImBuf(ibuf) == 0) + return; } - /* do conversion */ - IMB_buffer_byte_from_float((uchar *)ibuf->rect, ibuf->rect_float, - ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide, - ibuf->x, ibuf->y, ibuf->x, ibuf->x); + if (ibuf->float_colorspace == NULL) + from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); + else + from_colorspace = ibuf->float_colorspace->name; + + buffer = MEM_dupallocN(ibuf->rect_float); + + /* first make float buffer in byte space */ + IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, ibuf->rect_colorspace->name, predivide); + + /* convert float to byte */ + IMB_buffer_byte_from_float((unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, + FALSE, ibuf->x, ibuf->y, ibuf->x, ibuf->x); + + MEM_freeN(buffer); /* ensure user flag is reset */ ibuf->userflags &= ~IB_RECT_INVALID; @@ -559,7 +564,7 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w float *rect_float; uchar *rect_byte; int predivide = (ibuf->flags & IB_cm_predivide); - int profile_from; + int profile_from = IB_PROFILE_LINEAR_RGB; /* verify we have a float buffer */ if (ibuf->rect_float == NULL || buffer == NULL) @@ -569,18 +574,6 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w if (ibuf->rect == NULL) imb_addrectImBuf(ibuf); - /* determine profiles */ - if (ibuf->profile == IB_PROFILE_LINEAR_RGB) { - profile_from = IB_PROFILE_LINEAR_RGB; - } - else if (ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE)) { - profile_from = IB_PROFILE_SRGB; - } - else { - profile_from = IB_PROFILE_SRGB; /* should never happen */ - BLI_assert(0); - } - /* do conversion */ rect_float = ibuf->rect_float + (x + y * ibuf->x) * ibuf->channels; rect_byte = (uchar *)ibuf->rect + (x + y * ibuf->x) * 4; @@ -589,6 +582,7 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide, w, h, w, ibuf->x); + /* XXX: need to convert to image buffer's rect space */ IMB_buffer_byte_from_float(rect_byte, buffer, 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0, w, h, ibuf->x, w); @@ -600,26 +594,23 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w void IMB_float_from_rect(ImBuf *ibuf) { int predivide = (ibuf->flags & IB_cm_predivide); - int profile_from; /* verify if we byte and float buffers */ if (ibuf->rect == NULL) return; - if (ibuf->rect_float == NULL) + if (ibuf->rect_float == NULL) { if (imb_addrectfloatImBuf(ibuf) == 0) return; - - /* determine profiles */ - if (ibuf->profile == IB_PROFILE_NONE) - profile_from = IB_PROFILE_LINEAR_RGB; - else - profile_from = IB_PROFILE_SRGB; - - /* do conversion */ - IMB_buffer_float_from_byte(ibuf->rect_float, (uchar *)ibuf->rect, - IB_PROFILE_LINEAR_RGB, profile_from, predivide, - ibuf->x, ibuf->y, ibuf->x, ibuf->x); + } + + /* first, create float buffer in non-linear space */ + IMB_buffer_float_from_byte(ibuf->rect_float, (unsigned char *) ibuf->rect, IB_PROFILE_SRGB, IB_PROFILE_SRGB, + FALSE, ibuf->x, ibuf->y, ibuf->x, ibuf->x); + + /* then make float be in linear space */ + IMB_colormanagement_colorspace_to_scene_linear(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, + ibuf->rect_colorspace, predivide); } /* no profile conversion */ @@ -635,63 +626,19 @@ void IMB_float_from_rect_simple(ImBuf *ibuf) ibuf->x, ibuf->y, ibuf->x, ibuf->x); } -void IMB_convert_profile(ImBuf *ibuf, int profile) -{ - int predivide = (ibuf->flags & IB_cm_predivide); - int profile_from, profile_to; - - if (ibuf->profile == profile) - return; - - /* determine profiles */ - if (ibuf->profile == IB_PROFILE_LINEAR_RGB) - profile_from = IB_PROFILE_LINEAR_RGB; - else if (ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE)) - profile_from = IB_PROFILE_SRGB; - else { - BLI_assert(0); - profile_from = IB_PROFILE_SRGB; /* dummy, should never happen */ - } - - if (profile == IB_PROFILE_LINEAR_RGB) - profile_to = IB_PROFILE_LINEAR_RGB; - else if (ELEM(profile, IB_PROFILE_SRGB, IB_PROFILE_NONE)) - profile_to = IB_PROFILE_SRGB; - else { - BLI_assert(0); - profile_to = IB_PROFILE_SRGB; /* dummy, should never happen */ - } - - /* do conversion */ - if (ibuf->rect_float) { - IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float, - 4, profile_to, profile_from, predivide, - ibuf->x, ibuf->y, ibuf->x, ibuf->x); - } - - if (ibuf->rect) { - IMB_buffer_byte_from_byte((uchar *)ibuf->rect, (uchar *)ibuf->rect, - profile_to, profile_from, predivide, - ibuf->x, ibuf->y, ibuf->x, ibuf->x); - } - - /* set new profile */ - ibuf->profile = profile; -} - /* use when you need to get a buffer with a certain profile * if the return */ + +/* OCIO_TODO: used only by Cineon/DPX exporter which is still broken, so can not guarantee + * this function is working properly + */ float *IMB_float_profile_ensure(ImBuf *ibuf, int profile, int *alloc) { int predivide = (ibuf->flags & IB_cm_predivide); - int profile_from, profile_to; - - /* determine profiles */ - if (ibuf->profile == IB_PROFILE_NONE) - profile_from = IB_PROFILE_LINEAR_RGB; - else - profile_from = IB_PROFILE_SRGB; + int profile_from = IB_PROFILE_LINEAR_RGB; + int profile_to; + /* determine profile */ if (profile == IB_PROFILE_NONE) profile_to = IB_PROFILE_LINEAR_RGB; else diff --git a/source/blender/imbuf/intern/iris.c b/source/blender/imbuf/intern/iris.c index 58355937c80..3fd25fff92f 100644 --- a/source/blender/imbuf/intern/iris.c +++ b/source/blender/imbuf/intern/iris.c @@ -529,7 +529,6 @@ struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colo } ibuf->ftype = IMAGIC; - ibuf->profile = IB_PROFILE_SRGB; test_endian_zbuf(ibuf); diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c index b2221a77c54..dd559c55402 100644 --- a/source/blender/imbuf/intern/jp2.c +++ b/source/blender/imbuf/intern/jp2.c @@ -647,136 +647,67 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) switch (prec) { case 8: /* Convert blenders float color channels to 8, 12 or 16bit ints */ if (numcomps == 4) { - if (ibuf->profile == IB_PROFILE_LINEAR_RGB) { - PIXEL_LOOPER_BEGIN(rect_float) - { - r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[2])); - a[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[3]); - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN(rect_float) - { - r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[0]); - g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[1]); - b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[2]); - a[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[3]); - } - PIXEL_LOOPER_END; + PIXEL_LOOPER_BEGIN(rect_float) + { + r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[2])); + a[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[3]); } + PIXEL_LOOPER_END; } else { - if (ibuf->profile == IB_PROFILE_LINEAR_RGB) { - PIXEL_LOOPER_BEGIN(rect_float) - { - r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[2])); - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN(rect_float) - { - r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[0]); - g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[1]); - b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[2]); - } - PIXEL_LOOPER_END; + PIXEL_LOOPER_BEGIN(rect_float) + { + r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[2])); } + PIXEL_LOOPER_END; } break; case 12: if (numcomps == 4) { - if (ibuf->profile == IB_PROFILE_LINEAR_RGB) { - PIXEL_LOOPER_BEGIN(rect_float) - { - r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[2])); - a[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[3]); - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN(rect_float) - { - r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[0]); - g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[1]); - b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[2]); - a[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[3]); - } - PIXEL_LOOPER_END; + PIXEL_LOOPER_BEGIN(rect_float) + { + r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[2])); + a[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[3]); } + PIXEL_LOOPER_END; } else { - if (ibuf->profile == IB_PROFILE_LINEAR_RGB) { - PIXEL_LOOPER_BEGIN(rect_float) - { - r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[2])); - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN(rect_float) - { - r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[0]); - g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[1]); - b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[2]); - } - PIXEL_LOOPER_END; + PIXEL_LOOPER_BEGIN(rect_float) + { + r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[2])); } + PIXEL_LOOPER_END; } break; case 16: if (numcomps == 4) { - if (ibuf->profile == IB_PROFILE_LINEAR_RGB) { - PIXEL_LOOPER_BEGIN(rect_float) - { - r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[2])); - a[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[3]); - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN(rect_float) - { - r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[0]); - g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[1]); - b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[2]); - a[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[3]); - } - PIXEL_LOOPER_END; + PIXEL_LOOPER_BEGIN(rect_float) + { + r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[2])); + a[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[3]); } + PIXEL_LOOPER_END; } else { - if (ibuf->profile == IB_PROFILE_LINEAR_RGB) { - PIXEL_LOOPER_BEGIN(rect_float) - { - r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[2])); - } - PIXEL_LOOPER_END; - } - else { - PIXEL_LOOPER_BEGIN(rect_float) - { - r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[0]); - g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[1]); - b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[2]); - } - PIXEL_LOOPER_END; + PIXEL_LOOPER_BEGIN(rect_float) + { + r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[2])); } + PIXEL_LOOPER_END; } break; } diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c index 59cf7903c67..691db96989d 100644 --- a/source/blender/imbuf/intern/jpeg.c +++ b/source/blender/imbuf/intern/jpeg.c @@ -438,7 +438,6 @@ next_stamp_marker: jpeg_destroy((j_common_ptr) cinfo); if (ibuf) { ibuf->ftype = ibuf_ftype; - ibuf->profile = IB_PROFILE_SRGB; } } diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 4dfa1686f9d..13078921d1c 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -382,30 +382,15 @@ static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags else { unsigned char *from; - if (ibuf->profile == IB_PROFILE_LINEAR_RGB) { - for (int i = ibuf->y - 1; i >= 0; i--) { - from = (unsigned char *)ibuf->rect + channels * i * width; + for (int i = ibuf->y - 1; i >= 0; i--) { + from = (unsigned char *)ibuf->rect + channels * i * width; - for (int j = ibuf->x; j > 0; j--) { - to->r = (float)(from[0]) / 255.0f; - to->g = (float)(from[1]) / 255.0f; - to->b = (float)(from[2]) / 255.0f; - to->a = (float)(channels >= 4) ? from[3] / 255.0f : 1.0f; - to++; from += 4; - } - } - } - else { - for (int i = ibuf->y - 1; i >= 0; i--) { - from = (unsigned char *)ibuf->rect + channels * i * width; - - for (int j = ibuf->x; j > 0; j--) { - to->r = srgb_to_linearrgb((float)from[0] / 255.0f); - to->g = srgb_to_linearrgb((float)from[1] / 255.0f); - to->b = srgb_to_linearrgb((float)from[2] / 255.0f); - to->a = channels >= 4 ? (float)from[3] / 255.0f : 1.0f; - to++; from += 4; - } + for (int j = ibuf->x; j > 0; j--) { + to->r = srgb_to_linearrgb((float)from[0] / 255.0f); + to->g = srgb_to_linearrgb((float)from[1] / 255.0f); + to->b = srgb_to_linearrgb((float)from[2] / 255.0f); + to->a = channels >= 4 ? (float)from[3] / 255.0f : 1.0f; + to++; from += 4; } } } @@ -1169,9 +1154,6 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, 0); ibuf->ftype = OPENEXR; - /* openEXR is linear as per EXR spec */ - ibuf->profile = IB_PROFILE_LINEAR_RGB; - if (!(flags & IB_test)) { if (is_multi) { /* only enters with IB_multilayer flag set */ /* constructs channels for reading, allocates memory in channels */ diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c index 7db34e24901..6310d8e105f 100644 --- a/source/blender/imbuf/intern/png.c +++ b/source/blender/imbuf/intern/png.c @@ -394,10 +394,6 @@ ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[I if (ibuf) { ibuf->ftype = PNG; - if (bit_depth == 16) - ibuf->profile = IB_PROFILE_LINEAR_RGB; - else - ibuf->profile = IB_PROFILE_SRGB; if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) { int unit_type; diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c index 4eb6999c7b1..5add372cd4e 100644 --- a/source/blender/imbuf/intern/radiance_hdr.c +++ b/source/blender/imbuf/intern/radiance_hdr.c @@ -212,7 +212,6 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags, char color if (ibuf == NULL) return NULL; ibuf->ftype = RADHDR; - ibuf->profile = IB_PROFILE_LINEAR_RGB; if (flags & IB_test) return ibuf; diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index 764c326d079..a1fa05d1098 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -80,7 +80,7 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char co /* byte buffer is never internally converted to some standard space, * store pointer to it's color space descriptor instead */ - ibuf->rect_colorspace = colormanage_colorspace_get_named(colorspace); + ibuf->rect_colorspace = colormanage_colorspace_get_named(effective_colorspace); } BLI_strncpy(colorspace, effective_colorspace, IM_MAX_SPACE); diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c index be99050f31e..7b6bca6d54f 100644 --- a/source/blender/imbuf/intern/targa.c +++ b/source/blender/imbuf/intern/targa.c @@ -565,7 +565,6 @@ ImBuf *imb_loadtarga(unsigned char *mem, size_t mem_size, int flags, char colors if (ibuf == NULL) return(NULL); ibuf->ftype = TGA; - ibuf->profile = IB_PROFILE_SRGB; mem = mem + 18 + tga.numid; cp[0] = 0xff; diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c index 4ee379258f1..932a4941a0a 100644 --- a/source/blender/imbuf/intern/tiff.c +++ b/source/blender/imbuf/intern/tiff.c @@ -467,8 +467,6 @@ static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image, int premul) _TIFFfree(sbuf); if (success) { - ibuf->profile = (bitspersample == 32) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB; - /* Code seems to be not needed for 16 bits tif, on PPC G5 OSX (ton) */ if (bitspersample < 16) if (ENDIAN_ORDER == B_ENDIAN) @@ -792,10 +790,7 @@ int imb_savetiff(ImBuf *ibuf, const char *name, int flags) /* convert from float source */ float rgb[4]; - if (ibuf->profile == IB_PROFILE_LINEAR_RGB) - linearrgb_to_srgb_v3_v3(rgb, &fromf[from_i]); - else - copy_v3_v3(rgb, &fromf[from_i]); + linearrgb_to_srgb_v3_v3(rgb, &fromf[from_i]); rgb[3] = fromf[from_i + 3]; diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 5861f072cb7..a50cfae550c 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -294,32 +294,16 @@ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc) * to new color management system since this code would likely be simply removed soon */ if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) { - if (ibuf->profile != IB_PROFILE_NONE) { - rect= ibuf->rect_float; - } - else { - rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image"); - - IMB_buffer_float_from_float(rect, ibuf->rect_float, - 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide, - ibuf->x, ibuf->y, ibuf->x, ibuf->x); - - *alloc= TRUE; - } + rect= ibuf->rect_float; } else { - if (ibuf->profile == IB_PROFILE_NONE) { - rect= ibuf->rect_float; - } - else { - rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image"); + rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image"); - IMB_buffer_float_from_float(rect, ibuf->rect_float, - 4, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide, - ibuf->x, ibuf->y, ibuf->x, ibuf->x); + IMB_buffer_float_from_float(rect, ibuf->rect_float, + 4, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide, + ibuf->x, ibuf->y, ibuf->x, ibuf->x); *alloc= TRUE; - } } return rect; diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c index 06d24e46ce5..656e2a72c03 100644 --- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c +++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c @@ -267,12 +267,6 @@ static void exec_output_file_singlelayer(RenderData *rd, bNode *node, bNodeStack ibuf->rect_float = cbuf->rect; ibuf->dither = rd->dither_intensity; - /* OCIO_TODO: this is a part of legacy compositor, which likely would be removed before next release - * keep old color management flag untouched for now - */ - if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) - ibuf->profile = IB_PROFILE_LINEAR_RGB; - /* get full path */ BLI_join_dirfile(path, FILE_MAX, nimf->base_path, sockdata->path); BKE_makepicstring(filename, path, bmain->name, rd->cfra, format->imtype, (rd->scemode & R_EXTENSION), TRUE); diff --git a/source/blender/quicktime/apple/qtkit_import.m b/source/blender/quicktime/apple/qtkit_import.m index e30b8331fc0..75b9056de1b 100644 --- a/source/blender/quicktime/apple/qtkit_import.m +++ b/source/blender/quicktime/apple/qtkit_import.m @@ -291,7 +291,6 @@ ImBuf * qtime_fetchibuf (struct anim *anim, int position) ibuf = nsImageToiBuf(frameImage,anim->x, anim->y); [pool drain]; - ibuf->profile = IB_PROFILE_SRGB; return ibuf; } diff --git a/source/blender/quicktime/apple/quicktime_import.c b/source/blender/quicktime/apple/quicktime_import.c index 5b13d77a030..e44eba2bfe0 100644 --- a/source/blender/quicktime/apple/quicktime_import.c +++ b/source/blender/quicktime/apple/quicktime_import.c @@ -392,8 +392,6 @@ ImBuf *qtime_fetchibuf(struct anim *anim, int position) } #endif - ibuf->profile = IB_PROFILE_SRGB; - IMB_flipy(ibuf); return ibuf; } diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index c6e225cfa0c..03eb21dfa23 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -472,8 +472,6 @@ static void render_envmap(Render *re, EnvMap *env) ibuf = IMB_allocImBuf(envre->rectx, envre->recty, 24, IB_rect | IB_rectfloat); memcpy(ibuf->rect_float, rl->rectf, ibuf->channels * ibuf->x * ibuf->y * sizeof(float)); - ibuf->profile = IB_PROFILE_LINEAR_RGB; - /* envmap renders without alpha */ alpha = ibuf->rect_float + 3; for (y = ibuf->x * ibuf->y - 1; y >= 0; y--, alpha += 4) diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index b7019640544..f11f84c9d3b 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -1086,14 +1086,10 @@ ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd) * note that sequence editor can generate 8bpc render buffers */ if (ibuf->rect) { - ibuf->profile = IB_PROFILE_SRGB; if (BKE_imtype_valid_depths(rd->im_format.imtype) & (R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_24 | R_IMF_CHAN_DEPTH_32)) { - IMB_colormanagement_imbuf_float_from_rect(ibuf); + IMB_float_from_rect(ibuf); } } - else { - ibuf->profile = IB_PROFILE_LINEAR_RGB; - } /* color -> grayscale */ /* editing directly would alter the render view */ diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 34ff4d63e99..97a05e6a4c9 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -2621,8 +2621,6 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up ima->flag&= ~IMA_USED_FOR_RENDER; if (ibuf) { ibuf->userdata = NULL; /* use for masking if needed */ - if (ibuf->rect_float) - ibuf->profile = IB_PROFILE_LINEAR_RGB; } } From 883b23d3324eb893b6dde14fdda29d55361a820c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 14 Sep 2012 14:49:40 +0000 Subject: [PATCH 148/160] Synchronize changes with trunk --- intern/cycles/kernel/svm/svm_brick.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/kernel/svm/svm_brick.h b/intern/cycles/kernel/svm/svm_brick.h index 50de19b825d..7e38ac84bf1 100644 --- a/intern/cycles/kernel/svm/svm_brick.h +++ b/intern/cycles/kernel/svm/svm_brick.h @@ -70,7 +70,7 @@ __device void svm_node_tex_brick(KernelGlobals *kg, ShaderData *sd, float *stack /* RNA properties */ uint offset_frequency, squash_frequency; - float tint = 0; + float tint = 0.0f; decode_node_uchar4(node.y, &co_offset, &color1_offset, &color2_offset, &mortar_offset); decode_node_uchar4(node.z, &scale_offset, &mortar_size_offset, &bias_offset, &brick_width_offset); From 7420bce4f638c17377d9a384b8ddd06b3f8769cf Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 14 Sep 2012 15:23:02 +0000 Subject: [PATCH 149/160] Merging r50598 through r50599 from trunk into soc-2011-tomato --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a822143939..39c1474529d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -133,7 +133,7 @@ option(WITH_GAMEENGINE "Enable Game Engine" ON) option(WITH_PLAYER "Build Player" OFF) option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ON) option(WITH_COMPOSITOR "Enable the tile based nodal compositor" ON) -option(WITH_COMPOSITOR_LEGACY "Enable legacy compositor" ON) +option(WITH_COMPOSITOR_LEGACY "Enable legacy compositor" OFF) # GHOST Windowing Library Options option(WITH_GHOST_DEBUG "Enable debugging output for the GHOST library" OFF) From a803f5d6d05159be5f94673c688dad32231c3d96 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 14 Sep 2012 16:43:07 +0000 Subject: [PATCH 150/160] Merging r50600 through r50601 from trunk into soc-2011-tomato --- source/blender/editors/interface/interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 7524e88d5ac..742aed4fbb1 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -2623,7 +2623,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str, /* we could do some more error checks here */ if ((type & BUTTYPE) == LABEL) { - BLI_assert((poin != NULL || a1 != 0.0f || a2 != 0.0f || min != 0.0f || max != 0.0f) == FALSE); + BLI_assert((poin != NULL || min != 0.0f || max != 0.0f || (a1 == 0.0f && a2 != 0.0f) || (a1 != 0.0f && a1 != 1.0f)) == FALSE); } if (type & UI_BUT_POIN_TYPES) { /* a pointer is required */ From beba8014e444d154124f3739f2f3edbf58c972e6 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 15 Sep 2012 06:24:48 +0000 Subject: [PATCH 151/160] Merging r50602 through r50617 form trunk into soc-2011-tomato --- CMakeLists.txt | 8 +- build_files/cmake/macros.cmake | 1 + intern/audaspace/intern/AUD_C-API.cpp | 578 ++++++++---------- intern/audaspace/intern/AUD_C-API.h | 166 ++--- intern/cycles/kernel/osl/nodes/CMakeLists.txt | 2 + .../kernel/osl/nodes/node_object_info.osl | 33 + .../kernel/osl/nodes/node_particle_info.osl | 39 ++ intern/cycles/kernel/osl/osl_globals.h | 2 +- intern/cycles/kernel/osl/osl_services.cpp | 235 +++++-- intern/cycles/kernel/osl/osl_services.h | 12 +- intern/ghost/intern/GHOST_WindowCarbon.cpp | 2 +- intern/ghost/intern/GHOST_WindowWin32.cpp | 29 +- intern/ghost/intern/GHOST_WindowWin32.h | 4 +- intern/mikktspace/mikktspace.c | 2 +- intern/raskter/raskter.c | 10 +- intern/utfconv/utfconv.c | 8 +- source/blender/blenkernel/BKE_colortools.h | 2 +- source/blender/blenkernel/BKE_customdata.h | 2 + source/blender/blenkernel/BKE_mask.h | 7 +- source/blender/blenkernel/CMakeLists.txt | 4 +- source/blender/blenkernel/intern/blender.c | 6 +- source/blender/blenkernel/intern/cloth.c | 35 +- .../blender/blenkernel/intern/dynamicpaint.c | 21 +- source/blender/blenkernel/intern/implicit.c | 18 +- source/blender/blenkernel/intern/mask.c | 5 +- .../blenkernel/intern/mask_rasterize.c | 6 +- source/blender/blenkernel/intern/movieclip.c | 6 +- source/blender/blenkernel/intern/object.c | 34 +- .../blenkernel/intern/particle_system.c | 5 +- .../blender/blenkernel/intern/seqmodifier.c | 32 +- source/blender/blenkernel/intern/smoke.c | 6 +- source/blender/blenkernel/intern/text.c | 24 - source/blender/blenkernel/intern/texture.c | 2 +- source/blender/blenkernel/intern/tracking.c | 4 +- .../blender/blenkernel/intern/writeffmpeg.c | 2 +- source/blender/blenlib/BLI_math_color.h | 2 + source/blender/blenlib/intern/math_color.c | 6 + source/blender/blenlib/intern/md5.c | 2 + source/blender/blenlib/intern/pbvh.c | 2 +- source/blender/blenlib/intern/voronoi.c | 12 +- source/blender/blenlib/intern/winstuff.c | 2 +- source/blender/blenloader/BLO_readfile.h | 3 + source/blender/blenloader/intern/readfile.c | 10 +- source/blender/bmesh/operators/bmo_dissolve.c | 2 +- source/blender/bmesh/operators/bmo_hull.c | 4 +- .../bmesh/operators/bmo_removedoubles.c | 2 +- .../blender/bmesh/operators/bmo_wireframe.c | 2 +- source/blender/bmesh/tools/BME_bevel.c | 10 +- source/blender/collada/ImageExporter.cpp | 5 +- source/blender/editors/animation/keyframing.c | 2 +- source/blender/editors/armature/poseobject.c | 5 +- source/blender/editors/include/ED_mask.h | 4 +- source/blender/editors/include/ED_sequencer.h | 2 +- source/blender/editors/include/ED_util.h | 2 + .../blender/editors/interface/interface_ops.c | 2 +- source/blender/editors/io/io_ops.c | 2 + source/blender/editors/mask/mask_editaction.c | 1 + source/blender/editors/object/object_add.c | 2 +- .../blender/editors/physics/physics_fluid.c | 4 +- .../editors/sculpt_paint/paint_image.c | 2 +- .../blender/editors/sculpt_paint/paint_ops.c | 2 +- .../editors/sculpt_paint/paint_stroke.c | 5 +- .../editors/sculpt_paint/paint_vertex.c | 2 +- .../blender/editors/sculpt_paint/sculpt_uv.c | 4 +- .../editors/space_clip/clip_graph_draw.c | 4 +- .../editors/space_clip/clip_graph_ops.c | 2 +- .../blender/editors/space_image/image_ops.c | 2 +- source/blender/editors/space_nla/nla_edit.c | 2 +- source/blender/editors/space_node/drawnode.c | 8 +- .../blender/editors/space_node/space_node.c | 1 + .../editors/space_sequencer/sequencer_ops.c | 1 + .../editors/space_sequencer/sequencer_view.c | 2 +- .../blender/editors/space_view3d/drawmesh.c | 6 +- .../editors/space_view3d/view3d_select.c | 2 +- source/blender/editors/uvedit/uvedit_ops.c | 2 +- source/blender/imbuf/intern/divers.c | 2 +- source/blender/imbuf/intern/indexer_dv.c | 2 +- source/blender/imbuf/intern/util.c | 2 +- .../modifiers/intern/MOD_weightvgproximity.c | 2 +- source/blender/nodes/intern/node_common.c | 2 +- source/blender/nodes/intern/node_util.h | 2 +- .../blender/nodes/texture/node_texture_util.h | 2 + source/blender/python/bmesh/bmesh_py_ops.c | 4 +- source/blender/python/intern/CMakeLists.txt | 1 + source/blender/python/intern/bpy.c | 4 +- source/blender/python/intern/bpy.h | 5 +- source/blender/python/intern/bpy_app_ffmpeg.c | 5 +- .../blender/python/intern/bpy_app_handlers.c | 2 + .../python/intern/bpy_interface_atexit.c | 1 + source/blender/python/intern/bpy_library.c | 3 +- source/blender/python/intern/bpy_library.h | 32 + source/blender/python/intern/bpy_rna.c | 18 +- source/blender/python/intern/bpy_rna.h | 4 + source/blender/python/intern/gpu.c | 3 +- source/blender/python/intern/stubs.c | 11 +- source/blender/render/intern/include/zbuf.h | 5 + .../render/intern/source/convertblender.c | 1 + .../render/intern/source/render_texture.c | 11 +- source/blender/render/intern/source/strand.c | 5 - .../render/intern/source/texture_ocean.c | 2 + source/blender/render/intern/source/zbuf.c | 6 +- source/blender/windowmanager/WM_api.h | 2 + .../windowmanager/intern/wm_init_exit.c | 3 +- .../windowmanager/intern/wm_operators.c | 2 +- .../windowmanager/intern/wm_playanim.c | 8 +- source/creator/creator.c | 5 +- 106 files changed, 918 insertions(+), 728 deletions(-) create mode 100644 intern/cycles/kernel/osl/nodes/node_object_info.osl create mode 100644 intern/cycles/kernel/osl/nodes/node_particle_info.osl create mode 100644 source/blender/python/intern/bpy_library.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 39c1474529d..83e094b4375 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1716,9 +1716,10 @@ if(CMAKE_COMPILER_IS_GNUCC) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_CAST_ALIGN -Wcast-align) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ERROR_DECLARATION_AFTER_STATEMENT -Werror=declaration-after-statement) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ERROR_IMPLICIT_FUNCTION_DECLARATION -Werror=implicit-function-declaration) - ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ERROR_RETURN_TYPE -Werror=return-type) + ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ERROR_RETURN_TYPE -Werror=return-type) # system headers sometimes do this, disable for now, was: -Werror=strict-prototypes - ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_STRICT_PROTOTYPES -Wstrict-prototypes) + ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_STRICT_PROTOTYPES -Wstrict-prototypes) + ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_MISSING_PROTOTYPES -Wmissing-prototypes) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_POINTER_ARITH -Wpointer-arith) @@ -1752,10 +1753,13 @@ if(CMAKE_COMPILER_IS_GNUCC) elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + # strange, clang complains these are not supported, but then yses them. ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ALL -Wall) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_AUTOLOGICAL_COMPARE -Wno-tautological-compare) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts) + ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_STRICT_PROTOTYPES -Wstrict-prototypes) + ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_MISSING_PROTOTYPES -Wmissing-prototypes) ADD_CHECK_C_COMPILER_FLAG(CXX_WARNINGS C_WARN_ALL -Wall) ADD_CHECK_C_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_AUTOLOGICAL_COMPARE -Wno-tautological-compare) diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index ad5e3155368..43cfb31c03c 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -476,6 +476,7 @@ macro(remove_strict_flags) if(CMAKE_COMPILER_IS_GNUCC) remove_cc_flag("-Wstrict-prototypes") + remove_cc_flag("-Wmissing-prototypes") remove_cc_flag("-Wunused-parameter") remove_cc_flag("-Wwrite-strings") remove_cc_flag("-Wundef") diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp index a7d37da0426..46bba237cff 100644 --- a/intern/audaspace/intern/AUD_C-API.cpp +++ b/intern/audaspace/intern/AUD_C-API.cpp @@ -99,11 +99,11 @@ typedef AUD_Reference AUD_SEntry; #include "AUD_C-API.h" #ifndef NULL -#define NULL 0 +# define NULL (void *)0 #endif static AUD_Reference AUD_device; -static AUD_I3DDevice* AUD_3ddevice; +static AUD_I3DDevice *AUD_3ddevice; void AUD_initOnce() { @@ -116,13 +116,12 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) { AUD_Reference dev; - if(!AUD_device.isNull()) + if (!AUD_device.isNull()) { AUD_exit(); + } - try - { - switch(device) - { + try { + switch(device) { case AUD_NULL_DEVICE: dev = new AUD_NULLDevice(); break; @@ -140,8 +139,7 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) case AUD_JACK_DEVICE: #ifdef __APPLE__ struct stat st; - if(stat("/Library/Frameworks/Jackmp.framework", &st) != 0) - { + if (stat("/Library/Frameworks/Jackmp.framework", &st) != 0) { printf("Warning: Jack Framework not installed\n"); // No break, fall through to default, to return false } @@ -159,7 +157,7 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) } AUD_device = dev; - AUD_3ddevice = dynamic_cast(AUD_device.get()); + AUD_3ddevice = dynamic_cast(AUD_device.get()); return true; } @@ -176,48 +174,44 @@ void AUD_exit() } #ifdef WITH_PYTHON -static PyObject* AUD_getCDevice(PyObject* self) +static PyObject *AUD_getCDevice(PyObject *self) { - if(!AUD_device.isNull()) - { - Device* device = (Device*)Device_empty(); - if(device != NULL) - { + if (!AUD_device.isNull()) { + Device *device = (Device *)Device_empty(); + if (device != NULL) { device->device = new AUD_Reference(AUD_device); - return (PyObject*)device; + return (PyObject *)device; } } Py_RETURN_NONE; } -static PyMethodDef meth_getcdevice[] = {{ "device", (PyCFunction)AUD_getCDevice, METH_NOARGS, - "device()\n\n" - "Returns the application's :class:`Device`.\n\n" - ":return: The application's :class:`Device`.\n" - ":rtype: :class:`Device`"}}; +static PyMethodDef meth_getcdevice[] = { + {"device", (PyCFunction)AUD_getCDevice, METH_NOARGS, + "device()\n\n" + "Returns the application's :class:`Device`.\n\n" + ":return: The application's :class:`Device`.\n" + ":rtype: :class:`Device`"} +}; extern "C" { -extern void* sound_get_factory(void* sound); +extern void *sound_get_factory(void *sound); } -static PyObject* AUD_getSoundFromPointer(PyObject* self, PyObject* args) +static PyObject *AUD_getSoundFromPointer(PyObject *self, PyObject *args) { long int lptr; - if(PyArg_Parse(args, "l:_sound_from_pointer", &lptr)) - { - if(lptr) - { - AUD_Reference* factory = (AUD_Reference*) sound_get_factory((void*) lptr); + if (PyArg_Parse(args, "l:_sound_from_pointer", &lptr)) { + if (lptr) { + AUD_Reference* factory = (AUD_Reference*) sound_get_factory((void *) lptr); - if(factory) - { - Factory* obj = (Factory*) Factory_empty(); - if(obj) - { + if (factory) { + Factory *obj = (Factory *)Factory_empty(); + if (obj) { obj->factory = new AUD_Reference(*factory); - return (PyObject*) obj; + return (PyObject *) obj; } } } @@ -226,44 +220,44 @@ static PyObject* AUD_getSoundFromPointer(PyObject* self, PyObject* args) Py_RETURN_NONE; } -static PyMethodDef meth_sound_from_pointer[] = {{ "_sound_from_pointer", (PyCFunction)AUD_getSoundFromPointer, METH_O, - "_sound_from_pointer(pointer)\n\n" - "Returns the corresponding :class:`Factory` object.\n\n" - ":arg pointer: The pointer to the bSound object as long.\n" - ":type pointer: long\n" - ":return: The corresponding :class:`Factory` object.\n" - ":rtype: :class:`Factory`"}}; +static PyMethodDef meth_sound_from_pointer[] = { + {"_sound_from_pointer", (PyCFunction)AUD_getSoundFromPointer, METH_O, + "_sound_from_pointer(pointer)\n\n" + "Returns the corresponding :class:`Factory` object.\n\n" + ":arg pointer: The pointer to the bSound object as long.\n" + ":type pointer: long\n" + ":return: The corresponding :class:`Factory` object.\n" + ":rtype: :class:`Factory`"} +}; -PyObject* AUD_initPython() +PyObject *AUD_initPython() { - PyObject* module = PyInit_aud(); - PyModule_AddObject(module, "device", (PyObject*)PyCFunction_New(meth_getcdevice, NULL)); - PyModule_AddObject(module, "_sound_from_pointer", (PyObject*)PyCFunction_New(meth_sound_from_pointer, NULL)); + PyObject *module = PyInit_aud(); + PyModule_AddObject(module, "device", (PyObject *)PyCFunction_New(meth_getcdevice, NULL)); + PyModule_AddObject(module, "_sound_from_pointer", (PyObject *)PyCFunction_New(meth_sound_from_pointer, NULL)); PyDict_SetItemString(PyImport_GetModuleDict(), "aud", module); return module; } -void* AUD_getPythonFactory(AUD_Sound* sound) +void *AUD_getPythonFactory(AUD_Sound *sound) { - if(sound) - { - Factory* obj = (Factory*) Factory_empty(); - if(obj) - { + if (sound) { + Factory *obj = (Factory *) Factory_empty(); + if (obj) { obj->factory = new AUD_Reference(*sound); - return (PyObject*) obj; + return (PyObject *) obj; } } return NULL; } -AUD_Sound* AUD_getPythonSound(void* sound) +AUD_Sound *AUD_getPythonSound(void *sound) { - Factory* factory = checkFactory((PyObject *)sound); + Factory *factory = checkFactory((PyObject *)sound); - if(!factory) + if (!factory) return NULL; return new AUD_Reference(*reinterpret_cast*>(factory->factory)); @@ -281,7 +275,7 @@ void AUD_unlock() AUD_device->unlock(); } -AUD_SoundInfo AUD_getInfo(AUD_Sound* sound) +AUD_SoundInfo AUD_getInfo(AUD_Sound *sound) { assert(sound); @@ -290,12 +284,10 @@ AUD_SoundInfo AUD_getInfo(AUD_Sound* sound) info.specs.rate = AUD_RATE_INVALID; info.length = 0.0f; - try - { + try { AUD_Reference reader = (*sound)->createReader(); - if(!reader.isNull()) - { + if (!reader.isNull()) { info.specs = reader->getSpecs(); info.length = reader->getLength() / (float) info.specs.rate; } @@ -307,24 +299,23 @@ AUD_SoundInfo AUD_getInfo(AUD_Sound* sound) return info; } -AUD_Sound* AUD_load(const char* filename) +AUD_Sound *AUD_load(const char *filename) { assert(filename); return new AUD_Sound(new AUD_FileFactory(filename)); } -AUD_Sound* AUD_loadBuffer(unsigned char* buffer, int size) +AUD_Sound *AUD_loadBuffer(unsigned char *buffer, int size) { assert(buffer); return new AUD_Sound(new AUD_FileFactory(buffer, size)); } -AUD_Sound* AUD_bufferSound(AUD_Sound* sound) +AUD_Sound *AUD_bufferSound(AUD_Sound *sound) { assert(sound); - try - { + try { return new AUD_Sound(new AUD_StreamBufferFactory(*sound)); } catch(AUD_Exception&) @@ -333,12 +324,11 @@ AUD_Sound* AUD_bufferSound(AUD_Sound* sound) } } -AUD_Sound* AUD_monoSound(AUD_Sound* sound) +AUD_Sound *AUD_monoSound(AUD_Sound *sound) { assert(sound); - try - { + try { AUD_DeviceSpecs specs; specs.channels = AUD_CHANNELS_MONO; specs.rate = AUD_RATE_INVALID; @@ -351,12 +341,11 @@ AUD_Sound* AUD_monoSound(AUD_Sound* sound) } } -AUD_Sound* AUD_delaySound(AUD_Sound* sound, float delay) +AUD_Sound *AUD_delaySound(AUD_Sound *sound, float delay) { assert(sound); - try - { + try { return new AUD_Sound(new AUD_DelayFactory(*sound, delay)); } catch(AUD_Exception&) @@ -365,12 +354,11 @@ AUD_Sound* AUD_delaySound(AUD_Sound* sound, float delay) } } -AUD_Sound* AUD_limitSound(AUD_Sound* sound, float start, float end) +AUD_Sound *AUD_limitSound(AUD_Sound *sound, float start, float end) { assert(sound); - try - { + try { return new AUD_Sound(new AUD_LimiterFactory(*sound, start, end)); } catch(AUD_Exception&) @@ -379,12 +367,11 @@ AUD_Sound* AUD_limitSound(AUD_Sound* sound, float start, float end) } } -AUD_Sound* AUD_pingpongSound(AUD_Sound* sound) +AUD_Sound *AUD_pingpongSound(AUD_Sound *sound) { assert(sound); - try - { + try { return new AUD_Sound(new AUD_PingPongFactory(*sound)); } catch(AUD_Exception&) @@ -393,12 +380,11 @@ AUD_Sound* AUD_pingpongSound(AUD_Sound* sound) } } -AUD_Sound* AUD_loopSound(AUD_Sound* sound) +AUD_Sound *AUD_loopSound(AUD_Sound *sound) { assert(sound); - try - { + try { return new AUD_Sound(new AUD_LoopFactory(*sound)); } catch(AUD_Exception&) @@ -407,12 +393,11 @@ AUD_Sound* AUD_loopSound(AUD_Sound* sound) } } -int AUD_setLoop(AUD_Handle* handle, int loops) +int AUD_setLoop(AUD_Handle *handle, int loops) { assert(handle); - try - { + try { return (*handle)->setLoopCount(loops); } catch(AUD_Exception&) @@ -422,12 +407,11 @@ int AUD_setLoop(AUD_Handle* handle, int loops) return false; } -AUD_Sound* AUD_rectifySound(AUD_Sound* sound) +AUD_Sound *AUD_rectifySound(AUD_Sound *sound) { assert(sound); - try - { + try { return new AUD_Sound(new AUD_RectifyFactory(*sound)); } catch(AUD_Exception&) @@ -436,20 +420,20 @@ AUD_Sound* AUD_rectifySound(AUD_Sound* sound) } } -void AUD_unload(AUD_Sound* sound) +void AUD_unload(AUD_Sound *sound) { assert(sound); delete sound; } -AUD_Handle* AUD_play(AUD_Sound* sound, int keep) +AUD_Handle *AUD_play(AUD_Sound *sound, int keep) { assert(sound); - try - { + try { AUD_Handle handle = AUD_device->play(*sound, keep); - if(!handle.isNull()) + if (!handle.isNull()) { return new AUD_Handle(handle); + } } catch(AUD_Exception&) { @@ -457,19 +441,19 @@ AUD_Handle* AUD_play(AUD_Sound* sound, int keep) return NULL; } -int AUD_pause(AUD_Handle* handle) +int AUD_pause(AUD_Handle *handle) { assert(handle); return (*handle)->pause(); } -int AUD_resume(AUD_Handle* handle) +int AUD_resume(AUD_Handle *handle) { assert(handle); return (*handle)->resume(); } -int AUD_stop(AUD_Handle* handle) +int AUD_stop(AUD_Handle *handle) { assert(handle); int result = (*handle)->stop(); @@ -477,34 +461,33 @@ int AUD_stop(AUD_Handle* handle) return result; } -int AUD_setKeep(AUD_Handle* handle, int keep) +int AUD_setKeep(AUD_Handle *handle, int keep) { assert(handle); return (*handle)->setKeep(keep); } -int AUD_seek(AUD_Handle* handle, float seekTo) +int AUD_seek(AUD_Handle *handle, float seekTo) { assert(handle); return (*handle)->seek(seekTo); } -float AUD_getPosition(AUD_Handle* handle) +float AUD_getPosition(AUD_Handle *handle) { assert(handle); return (*handle)->getPosition(); } -AUD_Status AUD_getStatus(AUD_Handle* handle) +AUD_Status AUD_getStatus(AUD_Handle *handle) { assert(handle); return (*handle)->getStatus(); } -int AUD_setListenerLocation(const float* location) +int AUD_setListenerLocation(const float location[3]) { - if(AUD_3ddevice) - { + if (AUD_3ddevice) { AUD_Vector3 v(location[0], location[1], location[2]); AUD_3ddevice->setListenerLocation(v); return true; @@ -513,10 +496,9 @@ int AUD_setListenerLocation(const float* location) return false; } -int AUD_setListenerVelocity(const float* velocity) +int AUD_setListenerVelocity(const float velocity[3]) { - if(AUD_3ddevice) - { + if (AUD_3ddevice) { AUD_Vector3 v(velocity[0], velocity[1], velocity[2]); AUD_3ddevice->setListenerVelocity(v); return true; @@ -525,10 +507,9 @@ int AUD_setListenerVelocity(const float* velocity) return false; } -int AUD_setListenerOrientation(const float* orientation) +int AUD_setListenerOrientation(const float orientation[4]) { - if(AUD_3ddevice) - { + if (AUD_3ddevice) { AUD_Quaternion q(orientation[3], orientation[0], orientation[1], orientation[2]); AUD_3ddevice->setListenerOrientation(q); return true; @@ -539,8 +520,7 @@ int AUD_setListenerOrientation(const float* orientation) int AUD_setSpeedOfSound(float speed) { - if(AUD_3ddevice) - { + if (AUD_3ddevice) { AUD_3ddevice->setSpeedOfSound(speed); return true; } @@ -550,8 +530,7 @@ int AUD_setSpeedOfSound(float speed) int AUD_setDopplerFactor(float factor) { - if(AUD_3ddevice) - { + if (AUD_3ddevice) { AUD_3ddevice->setDopplerFactor(factor); return true; } @@ -561,8 +540,7 @@ int AUD_setDopplerFactor(float factor) int AUD_setDistanceModel(AUD_DistanceModel model) { - if(AUD_3ddevice) - { + if (AUD_3ddevice) { AUD_3ddevice->setDistanceModel(model); return true; } @@ -570,13 +548,12 @@ int AUD_setDistanceModel(AUD_DistanceModel model) return false; } -int AUD_setSourceLocation(AUD_Handle* handle, const float* location) +int AUD_setSourceLocation(AUD_Handle *handle, const float location[3]) { assert(handle); AUD_Reference h(*handle); - if(!h.isNull()) - { + if (!h.isNull()) { AUD_Vector3 v(location[0], location[1], location[2]); return h->setSourceLocation(v); } @@ -584,13 +561,12 @@ int AUD_setSourceLocation(AUD_Handle* handle, const float* location) return false; } -int AUD_setSourceVelocity(AUD_Handle* handle, const float* velocity) +int AUD_setSourceVelocity(AUD_Handle *handle, const float velocity[3]) { assert(handle); AUD_Reference h(*handle); - if(!h.isNull()) - { + if (!h.isNull()) { AUD_Vector3 v(velocity[0], velocity[1], velocity[2]); return h->setSourceVelocity(v); } @@ -598,13 +574,12 @@ int AUD_setSourceVelocity(AUD_Handle* handle, const float* velocity) return false; } -int AUD_setSourceOrientation(AUD_Handle* handle, const float* orientation) +int AUD_setSourceOrientation(AUD_Handle *handle, const float orientation[4]) { assert(handle); AUD_Reference h(*handle); - if(!h.isNull()) - { + if (!h.isNull()) { AUD_Quaternion q(orientation[3], orientation[0], orientation[1], orientation[2]); return h->setSourceOrientation(q); } @@ -612,149 +587,137 @@ int AUD_setSourceOrientation(AUD_Handle* handle, const float* orientation) return false; } -int AUD_setRelative(AUD_Handle* handle, int relative) +int AUD_setRelative(AUD_Handle *handle, int relative) { assert(handle); AUD_Reference h(*handle); - if(!h.isNull()) - { + if (!h.isNull()) { return h->setRelative(relative); } return false; } -int AUD_setVolumeMaximum(AUD_Handle* handle, float volume) +int AUD_setVolumeMaximum(AUD_Handle *handle, float volume) { assert(handle); AUD_Reference h(*handle); - if(!h.isNull()) - { + if (!h.isNull()) { return h->setVolumeMaximum(volume); } return false; } -int AUD_setVolumeMinimum(AUD_Handle* handle, float volume) +int AUD_setVolumeMinimum(AUD_Handle *handle, float volume) { assert(handle); AUD_Reference h(*handle); - if(!h.isNull()) - { + if (!h.isNull()) { return h->setVolumeMinimum(volume); } return false; } -int AUD_setDistanceMaximum(AUD_Handle* handle, float distance) +int AUD_setDistanceMaximum(AUD_Handle *handle, float distance) { assert(handle); AUD_Reference h(*handle); - if(!h.isNull()) - { + if (!h.isNull()) { return h->setDistanceMaximum(distance); } return false; } -int AUD_setDistanceReference(AUD_Handle* handle, float distance) +int AUD_setDistanceReference(AUD_Handle *handle, float distance) { assert(handle); AUD_Reference h(*handle); - if(!h.isNull()) - { + if (!h.isNull()) { return h->setDistanceReference(distance); } return false; } -int AUD_setAttenuation(AUD_Handle* handle, float factor) +int AUD_setAttenuation(AUD_Handle *handle, float factor) { assert(handle); AUD_Reference h(*handle); - if(!h.isNull()) - { + if (!h.isNull()) { return h->setAttenuation(factor); } return false; } -int AUD_setConeAngleOuter(AUD_Handle* handle, float angle) +int AUD_setConeAngleOuter(AUD_Handle *handle, float angle) { assert(handle); AUD_Reference h(*handle); - if(!h.isNull()) - { + if (!h.isNull()) { return h->setConeAngleOuter(angle); } return false; } -int AUD_setConeAngleInner(AUD_Handle* handle, float angle) +int AUD_setConeAngleInner(AUD_Handle *handle, float angle) { assert(handle); AUD_Reference h(*handle); - if(!h.isNull()) - { + if (!h.isNull()) { return h->setConeAngleInner(angle); } return false; } -int AUD_setConeVolumeOuter(AUD_Handle* handle, float volume) +int AUD_setConeVolumeOuter(AUD_Handle *handle, float volume) { assert(handle); AUD_Reference h(*handle); - if(!h.isNull()) - { + if (!h.isNull()) { return h->setConeVolumeOuter(volume); } return false; } -int AUD_setSoundVolume(AUD_Handle* handle, float volume) +int AUD_setSoundVolume(AUD_Handle *handle, float volume) { assert(handle); - try - { + try { return (*handle)->setVolume(volume); } catch(AUD_Exception&) {} return false; } -int AUD_setSoundPitch(AUD_Handle* handle, float pitch) +int AUD_setSoundPitch(AUD_Handle *handle, float pitch) { assert(handle); - try - { + try { return (*handle)->setPitch(pitch); } catch(AUD_Exception&) {} return false; } -AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs) +AUD_Device *AUD_openReadDevice(AUD_DeviceSpecs specs) { - try - { + try { return new AUD_Device(new AUD_ReadDevice(specs)); } catch(AUD_Exception&) @@ -763,16 +726,14 @@ AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs) } } -AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek) +AUD_Handle *AUD_playDevice(AUD_Device *device, AUD_Sound *sound, float seek) { assert(device); assert(sound); - try - { + try { AUD_Handle handle = (*device)->play(*sound); - if(!handle.isNull()) - { + if (!handle.isNull()) { handle->seek(seek); return new AUD_Handle(handle); } @@ -783,12 +744,11 @@ AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek) return NULL; } -int AUD_setDeviceVolume(AUD_Device* device, float volume) +int AUD_setDeviceVolume(AUD_Device *device, float volume) { assert(device); - try - { + try { (*device)->setVolume(volume); return true; } @@ -797,13 +757,12 @@ int AUD_setDeviceVolume(AUD_Device* device, float volume) return false; } -int AUD_readDevice(AUD_Device* device, data_t* buffer, int length) +int AUD_readDevice(AUD_Device *device, data_t *buffer, int length) { assert(device); assert(buffer); - try - { + try { return (*device)->read(buffer, length); } catch(AUD_Exception&) @@ -812,12 +771,11 @@ int AUD_readDevice(AUD_Device* device, data_t* buffer, int length) } } -void AUD_closeReadDevice(AUD_Device* device) +void AUD_closeReadDevice(AUD_Device *device) { assert(device); - try - { + try { delete device; } catch(AUD_Exception&) @@ -825,10 +783,10 @@ void AUD_closeReadDevice(AUD_Device* device) } } -float* AUD_readSoundBuffer(const char* filename, float low, float high, - float attack, float release, float threshold, - int accumulate, int additive, int square, - float sthreshold, double samplerate, int* length) +float *AUD_readSoundBuffer(const char *filename, float low, float high, + float attack, float release, float threshold, + int accumulate, int additive, int square, + float sthreshold, double samplerate, int *length) { AUD_Buffer buffer; AUD_DeviceSpecs specs; @@ -840,33 +798,32 @@ float* AUD_readSoundBuffer(const char* filename, float low, float high, int position = 0; - try - { + try { AUD_Reference reader = file->createReader(); AUD_SampleRate rate = reader->getSpecs().rate; sound = new AUD_ChannelMapperFactory(file, specs); - if(high < rate) + if (high < rate) sound = new AUD_LowpassFactory(sound, high); - if(low > 0) + if (low > 0) sound = new AUD_HighpassFactory(sound, low); sound = new AUD_EnvelopeFactory(sound, attack, release, threshold, 0.1f); sound = new AUD_LinearResampleFactory(sound, specs); - if(square) + if (square) sound = new AUD_SquareFactory(sound, sthreshold); - if(accumulate) + if (accumulate) sound = new AUD_AccumulatorFactory(sound, additive); - else if(additive) + else if (additive) sound = new AUD_SumFactory(sound); reader = sound->createReader(); - if(reader.isNull()) + if (reader.isNull()) return NULL; int len; @@ -884,30 +841,28 @@ float* AUD_readSoundBuffer(const char* filename, float low, float high, return NULL; } - float* result = (float*)malloc(position * sizeof(float)); + float * result = (float *)malloc(position * sizeof(float)); memcpy(result, buffer.getBuffer(), position * sizeof(float)); *length = position; return result; } -static void pauseSound(AUD_Handle* handle) +static void pauseSound(AUD_Handle *handle) { assert(handle); (*handle)->pause(); } -AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds) +AUD_Handle *AUD_pauseAfter(AUD_Handle *handle, float seconds) { AUD_Reference silence = new AUD_SilenceFactory; AUD_Reference limiter = new AUD_LimiterFactory(silence, 0, seconds); AUD_device->lock(); - try - { + try { AUD_Handle handle2 = AUD_device->play(limiter); - if(!handle2.isNull()) - { + if (!handle2.isNull()) { handle2->setStopCallback((stopCallback)pauseSound, handle); AUD_device->unlock(); return new AUD_Handle(handle2); @@ -922,125 +877,127 @@ AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds) return NULL; } -AUD_Sound* AUD_createSequencer(float fps, int muted) +AUD_Sound *AUD_createSequencer(float fps, int muted) { // specs are changed at a later point! AUD_Specs specs; specs.channels = AUD_CHANNELS_STEREO; specs.rate = AUD_RATE_44100; - AUD_Sound* sequencer = new AUD_Sound(AUD_Reference(new AUD_SequencerFactory(specs, fps, muted))); + AUD_Sound *sequencer = new AUD_Sound(AUD_Reference(new AUD_SequencerFactory(specs, fps, muted))); return sequencer; } -void AUD_destroySequencer(AUD_Sound* sequencer) +void AUD_destroySequencer(AUD_Sound *sequencer) { delete sequencer; } -void AUD_setSequencerMuted(AUD_Sound* sequencer, int muted) +void AUD_setSequencerMuted(AUD_Sound *sequencer, int muted) { - dynamic_cast(sequencer->get())->mute(muted); + dynamic_cast(sequencer->get())->mute(muted); } -void AUD_setSequencerFPS(AUD_Sound* sequencer, float fps) +void AUD_setSequencerFPS(AUD_Sound *sequencer, float fps) { - dynamic_cast(sequencer->get())->setFPS(fps); + dynamic_cast(sequencer->get())->setFPS(fps); } -AUD_SEntry* AUD_addSequence(AUD_Sound* sequencer, AUD_Sound* sound, - float begin, float end, float skip) +AUD_SEntry *AUD_addSequence(AUD_Sound *sequencer, AUD_Sound *sound, + float begin, float end, float skip) { - if(!sound) - return new AUD_SEntry(((AUD_SequencerFactory*)sequencer->get())->add(AUD_Sound(), begin, end, skip)); - return new AUD_SEntry(((AUD_SequencerFactory*)sequencer->get())->add(*sound, begin, end, skip)); + if (!sound) + return new AUD_SEntry(((AUD_SequencerFactory *)sequencer->get())->add(AUD_Sound(), begin, end, skip)); + return new AUD_SEntry(((AUD_SequencerFactory *)sequencer->get())->add(*sound, begin, end, skip)); } -void AUD_removeSequence(AUD_Sound* sequencer, AUD_SEntry* entry) +void AUD_removeSequence(AUD_Sound *sequencer, AUD_SEntry *entry) { - dynamic_cast(sequencer->get())->remove(*entry); + dynamic_cast(sequencer->get())->remove(*entry); delete entry; } -void AUD_moveSequence(AUD_SEntry* entry, float begin, float end, float skip) +void AUD_moveSequence(AUD_SEntry *entry, float begin, float end, float skip) { (*entry)->move(begin, end, skip); } -void AUD_muteSequence(AUD_SEntry* entry, char mute) +void AUD_muteSequence(AUD_SEntry *entry, char mute) { (*entry)->mute(mute); } -void AUD_setRelativeSequence(AUD_SEntry* entry, char relative) +void AUD_setRelativeSequence(AUD_SEntry *entry, char relative) { (*entry)->setRelative(relative); } -void AUD_updateSequenceSound(AUD_SEntry* entry, AUD_Sound* sound) +void AUD_updateSequenceSound(AUD_SEntry *entry, AUD_Sound *sound) { - if(sound) + if (sound) (*entry)->setSound(*sound); else (*entry)->setSound(AUD_Sound()); } -void AUD_setSequenceAnimData(AUD_SEntry* entry, AUD_AnimateablePropertyType type, int frame, float* data, char animated) +void AUD_setSequenceAnimData(AUD_SEntry *entry, AUD_AnimateablePropertyType type, int frame, float *data, char animated) { - AUD_AnimateableProperty* prop = (*entry)->getAnimProperty(type); - if(animated) - { - if(frame >= 0) + AUD_AnimateableProperty *prop = (*entry)->getAnimProperty(type); + if (animated) { + if (frame >= 0) prop->write(data, frame, 1); } - else + else { prop->write(data); -} - -void AUD_setSequencerAnimData(AUD_Sound* sequencer, AUD_AnimateablePropertyType type, int frame, float* data, char animated) -{ - AUD_AnimateableProperty* prop = dynamic_cast(sequencer->get())->getAnimProperty(type); - if(animated) - { - if(frame >= 0) - prop->write(data, frame, 1); } - else - prop->write(data); } -void AUD_updateSequenceData(AUD_SEntry* entry, float volume_max, float volume_min, - float distance_max, float distance_reference, float attenuation, - float cone_angle_outer, float cone_angle_inner, float cone_volume_outer) +void AUD_setSequencerAnimData(AUD_Sound *sequencer, AUD_AnimateablePropertyType type, int frame, float *data, char animated) +{ + AUD_AnimateableProperty *prop = dynamic_cast(sequencer->get())->getAnimProperty(type); + if (animated) { + if (frame >= 0) { + prop->write(data, frame, 1); + } + } + else { + prop->write(data); + } +} + +void AUD_updateSequenceData(AUD_SEntry *entry, float volume_max, float volume_min, + float distance_max, float distance_reference, float attenuation, + float cone_angle_outer, float cone_angle_inner, float cone_volume_outer) { (*entry)->updateAll(volume_max, volume_min, distance_max, distance_reference, attenuation, - cone_angle_outer, cone_angle_inner, cone_volume_outer); + cone_angle_outer, cone_angle_inner, cone_volume_outer); } -void AUD_updateSequencerData(AUD_Sound* sequencer, float speed_of_sound, - float factor, AUD_DistanceModel model) +void AUD_updateSequencerData(AUD_Sound *sequencer, float speed_of_sound, + float factor, AUD_DistanceModel model) { - AUD_SequencerFactory* f = dynamic_cast(sequencer->get()); + AUD_SequencerFactory *f = dynamic_cast(sequencer->get()); f->setSpeedOfSound(speed_of_sound); f->setDopplerFactor(factor); f->setDistanceModel(model); } -void AUD_setSequencerDeviceSpecs(AUD_Sound* sequencer) +void AUD_setSequencerDeviceSpecs(AUD_Sound *sequencer) { - dynamic_cast(sequencer->get())->setSpecs(AUD_device->getSpecs().specs); + dynamic_cast(sequencer->get())->setSpecs(AUD_device->getSpecs().specs); } -void AUD_setSequencerSpecs(AUD_Sound* sequencer, AUD_Specs specs) +void AUD_setSequencerSpecs(AUD_Sound *sequencer, AUD_Specs specs) { - dynamic_cast(sequencer->get())->setSpecs(specs); + dynamic_cast(sequencer->get())->setSpecs(specs); } -void AUD_seekSequencer(AUD_Handle* handle, float time) +void AUD_seekSequencer(AUD_Handle *handle, float time) { #ifdef WITH_JACK - AUD_JackDevice* device = dynamic_cast(AUD_device.get()); - if(device) + AUD_JackDevice *device = dynamic_cast(AUD_device.get()); + if (device) { device->seekPlayback(time); + } else #endif { @@ -1049,12 +1006,13 @@ void AUD_seekSequencer(AUD_Handle* handle, float time) } } -float AUD_getSequencerPosition(AUD_Handle* handle) +float AUD_getSequencerPosition(AUD_Handle *handle) { #ifdef WITH_JACK - AUD_JackDevice* device = dynamic_cast(AUD_device.get()); - if(device) + AUD_JackDevice *device = dynamic_cast(AUD_device.get()); + if (device) { return device->getPlaybackPosition(); + } else #endif { @@ -1066,44 +1024,48 @@ float AUD_getSequencerPosition(AUD_Handle* handle) void AUD_startPlayback() { #ifdef WITH_JACK - AUD_JackDevice* device = dynamic_cast(AUD_device.get()); - if(device) + AUD_JackDevice *device = dynamic_cast(AUD_device.get()); + if (device) { device->startPlayback(); + } #endif } void AUD_stopPlayback() { #ifdef WITH_JACK - AUD_JackDevice* device = dynamic_cast(AUD_device.get()); - if(device) + AUD_JackDevice *device = dynamic_cast(AUD_device.get()); + if (device) { device->stopPlayback(); + } #endif } #ifdef WITH_JACK -void AUD_setSyncCallback(AUD_syncFunction function, void* data) +void AUD_setSyncCallback(AUD_syncFunction function, void *data) { - AUD_JackDevice* device = dynamic_cast(AUD_device.get()); - if(device) + AUD_JackDevice *device = dynamic_cast(AUD_device.get()); + if (device) { device->setSyncCallback(function, data); + } } #endif int AUD_doesPlayback() { #ifdef WITH_JACK - AUD_JackDevice* device = dynamic_cast(AUD_device.get()); - if(device) + AUD_JackDevice *device = dynamic_cast(AUD_device.get()); + if (device) { return device->doesPlayback(); + } #endif return -1; } -int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length, int samples_per_second) +int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second) { AUD_DeviceSpecs specs; - sample_t* buf; + sample_t *buf; AUD_Buffer aBuffer; specs.rate = AUD_RATE_INVALID; @@ -1120,8 +1082,7 @@ int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length, int samples_pe overallmax = 0; - for(int i = 0; i < length; i++) - { + for (int i = 0; i < length; i++) { len = floor(samplejump * (i+1)) - floor(samplejump * i); aBuffer.assureSize(len * AUD_SAMPLE_SIZE(specs)); @@ -1131,11 +1092,10 @@ int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length, int samples_pe max = min = *buf; power = *buf * *buf; - for(int j = 1; j < len; j++) - { - if(buf[j] < min) + for (int j = 1; j < len; j++) { + if (buf[j] < min) min = buf[j]; - if(buf[j] > max) + if (buf[j] > max) max = buf[j]; power += buf[j] * buf[j]; } @@ -1144,22 +1104,19 @@ int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length, int samples_pe buffer[i * 3 + 1] = max; buffer[i * 3 + 2] = sqrt(power) / len; - if(overallmax < max) + if (overallmax < max) overallmax = max; - if(overallmax < -min) + if (overallmax < -min) overallmax = -min; - if(eos) - { + if (eos) { length = i; break; } } - if(overallmax > 1.0f) - { - for(int i = 0; i < length * 3; i++) - { + if (overallmax > 1.0f) { + for (int i = 0; i < length * 3; i++) { buffer[i] /= overallmax; } } @@ -1167,48 +1124,46 @@ int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length, int samples_pe return length; } -AUD_Sound* AUD_copy(AUD_Sound* sound) +AUD_Sound *AUD_copy(AUD_Sound *sound) { return new AUD_Reference(*sound); } -void AUD_freeHandle(AUD_Handle* handle) +void AUD_freeHandle(AUD_Handle *handle) { delete handle; } -void* AUD_createSet() +void *AUD_createSet() { - return new std::set(); + return new std::set(); } -void AUD_destroySet(void* set) +void AUD_destroySet(void *set) { - delete reinterpret_cast*>(set); + delete reinterpret_cast*>(set); } -char AUD_removeSet(void* set, void* entry) +char AUD_removeSet(void *set, void *entry) { - if(set) - return reinterpret_cast*>(set)->erase(entry); + if (set) + return reinterpret_cast*>(set)->erase(entry); return 0; } -void AUD_addSet(void* set, void* entry) +void AUD_addSet(void *set, void *entry) { - if(entry) - reinterpret_cast*>(set)->insert(entry); + if (entry) + reinterpret_cast*>(set)->insert(entry); } -void* AUD_getSet(void* set) +void *AUD_getSet(void *set) { - if(set) - { - std::set* rset = reinterpret_cast*>(set); - if(!rset->empty()) - { - std::set::iterator it = rset->begin(); - void* result = *it; + if (set) { + std::set* rset = reinterpret_cast*>(set); + if (!rset->empty()) { + std::set::iterator it = rset->begin(); + void *result = *it; rset->erase(it); return result; } @@ -1217,11 +1172,10 @@ void* AUD_getSet(void* set) return NULL; } -const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate) +const char *AUD_mixdown(AUD_Sound *sound, unsigned int start, unsigned int length, unsigned int buffersize, const char *filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate) { - try - { - AUD_SequencerFactory* f = dynamic_cast(sound->get()); + try { + AUD_SequencerFactory *f = dynamic_cast(sound->get()); f->setSpecs(specs.specs); AUD_Reference reader = f->createQualityReader(); @@ -1237,11 +1191,10 @@ const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int lengt } } -const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate) +const char *AUD_mixdown_per_channel(AUD_Sound *sound, unsigned int start, unsigned int length, unsigned int buffersize, const char *filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate) { - try - { - AUD_SequencerFactory* f = dynamic_cast(sound->get()); + try { + AUD_SequencerFactory *f = dynamic_cast(sound->get()); f->setSpecs(specs.specs); @@ -1250,19 +1203,22 @@ const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsign int channels = specs.channels; specs.channels = AUD_CHANNELS_MONO; - for(int i = 0; i < channels; i++) - { + for (int i = 0; i < channels; i++) { std::stringstream stream; std::string fn = filename; size_t index = fn.find_last_of('.'); size_t index_slash = fn.find_last_of('/'); size_t index_backslash = fn.find_last_of('\\'); - if((index == std::string::npos) || - ((index < index_slash) && (index_slash != std::string::npos)) || - ((index < index_backslash) && (index_backslash != std::string::npos))) + + if ((index == std::string::npos) || + ((index < index_slash) && (index_slash != std::string::npos)) || + ((index < index_backslash) && (index_backslash != std::string::npos))) + { stream << filename << "_" << (i + 1); - else + } + else { stream << fn.substr(0, index) << "_" << (i + 1) << fn.substr(index); + } writers.push_back(AUD_FileWriter::createWriter(stream.str(), specs, format, codec, bitrate)); } @@ -1278,19 +1234,19 @@ const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsign } } -AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer, float volume, float start) +AUD_Device *AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound *sequencer, float volume, float start) { - try - { - AUD_ReadDevice* device = new AUD_ReadDevice(specs); + try { + AUD_ReadDevice *device = new AUD_ReadDevice(specs); device->setQuality(true); device->setVolume(volume); - dynamic_cast(sequencer->get())->setSpecs(specs.specs); + dynamic_cast(sequencer->get())->setSpecs(specs.specs); AUD_Handle handle = device->play(*sequencer); - if(!handle.isNull()) + if (!handle.isNull()) { handle->seek(start); + } return new AUD_Device(device); } @@ -1305,7 +1261,7 @@ AUD_Reference AUD_getDevice() return AUD_device; } -AUD_I3DDevice* AUD_get3DDevice() +AUD_I3DDevice *AUD_get3DDevice() { return AUD_3ddevice; } diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h index 6af0c648d0e..75e3456de9a 100644 --- a/intern/audaspace/intern/AUD_C-API.h +++ b/intern/audaspace/intern/AUD_C-API.h @@ -56,8 +56,8 @@ typedef struct typedef void AUD_Handle; typedef void AUD_Device; typedef void AUD_SEntry; - typedef float (*AUD_volumeFunction)(void*, void*, float); - typedef void (*AUD_syncFunction)(void*, int, float); + typedef float (*AUD_volumeFunction)(void *, void *, float); + typedef void (*AUD_syncFunction)(void *, int, float); #endif /** @@ -94,14 +94,14 @@ extern void AUD_unlock(void); * \param sound The sound to get the info about. * \return The AUD_SoundInfo structure with filled in data. */ -extern AUD_SoundInfo AUD_getInfo(AUD_Sound* sound); +extern AUD_SoundInfo AUD_getInfo(AUD_Sound *sound); /** * Loads a sound file. * \param filename The filename of the sound file. * \return A handle of the sound file. */ -extern AUD_Sound* AUD_load(const char* filename); +extern AUD_Sound *AUD_load(const char *filename); /** * Loads a sound file. @@ -109,21 +109,21 @@ extern AUD_Sound* AUD_load(const char* filename); * \param size The size of the buffer. * \return A handle of the sound file. */ -extern AUD_Sound* AUD_loadBuffer(unsigned char* buffer, int size); +extern AUD_Sound *AUD_loadBuffer(unsigned char *buffer, int size); /** * Buffers a sound. * \param sound The sound to buffer. * \return A handle of the sound buffer. */ -extern AUD_Sound* AUD_bufferSound(AUD_Sound* sound); +extern AUD_Sound *AUD_bufferSound(AUD_Sound *sound); /** * Rechannels the sound to be mono. * \param sound The sound to rechannel. * \return The mono sound. */ -extern AUD_Sound* AUD_monoSound(AUD_Sound* sound); +extern AUD_Sound *AUD_monoSound(AUD_Sound *sound); /** * Delays a sound. @@ -131,7 +131,7 @@ extern AUD_Sound* AUD_monoSound(AUD_Sound* sound); * \param delay The delay in seconds. * \return A handle of the delayed sound. */ -extern AUD_Sound* AUD_delaySound(AUD_Sound* sound, float delay); +extern AUD_Sound *AUD_delaySound(AUD_Sound *sound, float delay); /** * Limits a sound. @@ -140,21 +140,21 @@ extern AUD_Sound* AUD_delaySound(AUD_Sound* sound, float delay); * \param end The stop time in seconds. * \return A handle of the limited sound. */ -extern AUD_Sound* AUD_limitSound(AUD_Sound* sound, float start, float end); +extern AUD_Sound *AUD_limitSound(AUD_Sound *sound, float start, float end); /** * Ping pongs a sound. * \param sound The sound to ping pong. * \return A handle of the ping pong sound. */ -extern AUD_Sound* AUD_pingpongSound(AUD_Sound* sound); +extern AUD_Sound *AUD_pingpongSound(AUD_Sound *sound); /** * Loops a sound. * \param sound The sound to loop. * \return A handle of the looped sound. */ -extern AUD_Sound* AUD_loopSound(AUD_Sound* sound); +extern AUD_Sound *AUD_loopSound(AUD_Sound *sound); /** * Sets a remaining loop count of a looping sound that currently plays. @@ -162,20 +162,20 @@ extern AUD_Sound* AUD_loopSound(AUD_Sound* sound); * \param loops The count of remaining loops, -1 for infinity. * \return Whether the handle is valid. */ -extern int AUD_setLoop(AUD_Handle* handle, int loops); +extern int AUD_setLoop(AUD_Handle *handle, int loops); /** * Rectifies a sound. * \param sound The sound to rectify. * \return A handle of the rectified sound. */ -extern AUD_Sound* AUD_rectifySound(AUD_Sound* sound); +extern AUD_Sound *AUD_rectifySound(AUD_Sound *sound); /** * Unloads a sound of any type. * \param sound The handle of the sound. */ -extern void AUD_unload(AUD_Sound* sound); +extern void AUD_unload(AUD_Sound *sound); /** * Plays back a sound file. @@ -184,28 +184,28 @@ extern void AUD_unload(AUD_Sound* sound); * paused when its end has been reached. * \return A handle to the played back sound. */ -extern AUD_Handle* AUD_play(AUD_Sound* sound, int keep); +extern AUD_Handle *AUD_play(AUD_Sound *sound, int keep); /** * Pauses a played back sound. * \param handle The handle to the sound. * \return Whether the handle has been playing or not. */ -extern int AUD_pause(AUD_Handle* handle); +extern int AUD_pause(AUD_Handle *handle); /** * Resumes a paused sound. * \param handle The handle to the sound. * \return Whether the handle has been paused or not. */ -extern int AUD_resume(AUD_Handle* handle); +extern int AUD_resume(AUD_Handle *handle); /** * Stops a playing or paused sound. * \param handle The handle to the sound. * \return Whether the handle has been valid or not. */ -extern int AUD_stop(AUD_Handle* handle); +extern int AUD_stop(AUD_Handle *handle); /** * Sets the end behaviour of a playing or paused sound. @@ -214,7 +214,7 @@ extern int AUD_stop(AUD_Handle* handle); * paused when its end has been reached. * \return Whether the handle has been valid or not. */ -extern int AUD_setKeep(AUD_Handle* handle, int keep); +extern int AUD_setKeep(AUD_Handle *handle, int keep); /** * Seeks a playing or paused sound. @@ -222,7 +222,7 @@ extern int AUD_setKeep(AUD_Handle* handle, int keep); * \param seekTo From where the sound file should be played back in seconds. * \return Whether the handle has been valid or not. */ -extern int AUD_seek(AUD_Handle* handle, float seekTo); +extern int AUD_seek(AUD_Handle *handle, float seekTo); /** * Retrieves the playback position of a handle. @@ -230,32 +230,32 @@ extern int AUD_seek(AUD_Handle* handle, float seekTo); * \return The current playback position in seconds or 0.0 if the handle is * invalid. */ -extern float AUD_getPosition(AUD_Handle* handle); +extern float AUD_getPosition(AUD_Handle *handle); /** * Returns the status of a playing, paused or stopped sound. * \param handle The handle to the sound. * \return The status of the sound behind the handle. */ -extern AUD_Status AUD_getStatus(AUD_Handle* handle); +extern AUD_Status AUD_getStatus(AUD_Handle *handle); /** * Sets the listener location. * \param location The new location. */ -extern int AUD_setListenerLocation(const float* location); +extern int AUD_setListenerLocation(const float location[3]); /** * Sets the listener velocity. * \param velocity The new velocity. */ -extern int AUD_setListenerVelocity(const float* velocity); +extern int AUD_setListenerVelocity(const float velocity[3]); /** * Sets the listener orientation. * \param orientation The new orientation as quaternion. */ -extern int AUD_setListenerOrientation(const float* orientation); +extern int AUD_setListenerOrientation(const float orientation[4]); /** * Sets the speed of sound. @@ -284,7 +284,7 @@ extern int AUD_setDistanceModel(AUD_DistanceModel model); * \param location The new location. * \return Whether the action succeeded. */ -extern int AUD_setSourceLocation(AUD_Handle* handle, const float* location); +extern int AUD_setSourceLocation(AUD_Handle *handle, const float location[3]); /** * Sets the velocity of a source. @@ -292,7 +292,7 @@ extern int AUD_setSourceLocation(AUD_Handle* handle, const float* location); * \param velocity The new velocity. * \return Whether the action succeeded. */ -extern int AUD_setSourceVelocity(AUD_Handle* handle, const float* velocity); +extern int AUD_setSourceVelocity(AUD_Handle *handle, const float velocity[3]); /** * Sets the orientation of a source. @@ -300,7 +300,7 @@ extern int AUD_setSourceVelocity(AUD_Handle* handle, const float* velocity); * \param orientation The new orientation as quaternion. * \return Whether the action succeeded. */ -extern int AUD_setSourceOrientation(AUD_Handle* handle, const float* orientation); +extern int AUD_setSourceOrientation(AUD_Handle *handle, const float orientation[4]); /** * Sets whether the source location, velocity and orientation are relative @@ -309,7 +309,7 @@ extern int AUD_setSourceOrientation(AUD_Handle* handle, const float* orientation * \param relative Whether the source is relative. * \return Whether the action succeeded. */ -extern int AUD_setRelative(AUD_Handle* handle, int relative); +extern int AUD_setRelative(AUD_Handle *handle, int relative); /** * Sets the maximum volume of a source. @@ -317,7 +317,7 @@ extern int AUD_setRelative(AUD_Handle* handle, int relative); * \param volume The new maximum volume. * \return Whether the action succeeded. */ -extern int AUD_setVolumeMaximum(AUD_Handle* handle, float volume); +extern int AUD_setVolumeMaximum(AUD_Handle *handle, float volume); /** * Sets the minimum volume of a source. @@ -325,7 +325,7 @@ extern int AUD_setVolumeMaximum(AUD_Handle* handle, float volume); * \param volume The new minimum volume. * \return Whether the action succeeded. */ -extern int AUD_setVolumeMinimum(AUD_Handle* handle, float volume); +extern int AUD_setVolumeMinimum(AUD_Handle *handle, float volume); /** * Sets the maximum distance of a source. @@ -335,7 +335,7 @@ extern int AUD_setVolumeMinimum(AUD_Handle* handle, float volume); * \param distance The new maximum distance. * \return Whether the action succeeded. */ -extern int AUD_setDistanceMaximum(AUD_Handle* handle, float distance); +extern int AUD_setDistanceMaximum(AUD_Handle *handle, float distance); /** * Sets the reference distance of a source. @@ -343,7 +343,7 @@ extern int AUD_setDistanceMaximum(AUD_Handle* handle, float distance); * \param distance The new reference distance. * \return Whether the action succeeded. */ -extern int AUD_setDistanceReference(AUD_Handle* handle, float distance); +extern int AUD_setDistanceReference(AUD_Handle *handle, float distance); /** * Sets the attenuation of a source. @@ -352,7 +352,7 @@ extern int AUD_setDistanceReference(AUD_Handle* handle, float distance); * \param factor The new attenuation. * \return Whether the action succeeded. */ -extern int AUD_setAttenuation(AUD_Handle* handle, float factor); +extern int AUD_setAttenuation(AUD_Handle *handle, float factor); /** * Sets the outer angle of the cone of a source. @@ -360,7 +360,7 @@ extern int AUD_setAttenuation(AUD_Handle* handle, float factor); * \param angle The new outer angle of the cone. * \return Whether the action succeeded. */ -extern int AUD_setConeAngleOuter(AUD_Handle* handle, float angle); +extern int AUD_setConeAngleOuter(AUD_Handle *handle, float angle); /** * Sets the inner angle of the cone of a source. @@ -368,7 +368,7 @@ extern int AUD_setConeAngleOuter(AUD_Handle* handle, float angle); * \param angle The new inner angle of the cone. * \return Whether the action succeeded. */ -extern int AUD_setConeAngleInner(AUD_Handle* handle, float angle); +extern int AUD_setConeAngleInner(AUD_Handle *handle, float angle); /** * Sets the outer volume of the cone of a source. @@ -378,7 +378,7 @@ extern int AUD_setConeAngleInner(AUD_Handle* handle, float angle); * \param volume The new outer volume of the cone. * \return Whether the action succeeded. */ -extern int AUD_setConeVolumeOuter(AUD_Handle* handle, float volume); +extern int AUD_setConeVolumeOuter(AUD_Handle *handle, float volume); /** * Sets the volume of a played back sound. @@ -386,7 +386,7 @@ extern int AUD_setConeVolumeOuter(AUD_Handle* handle, float volume); * \param volume The new volume, must be between 0.0 and 1.0. * \return Whether the action succeeded. */ -extern int AUD_setSoundVolume(AUD_Handle* handle, float volume); +extern int AUD_setSoundVolume(AUD_Handle *handle, float volume); /** * Sets the pitch of a played back sound. @@ -394,14 +394,14 @@ extern int AUD_setSoundVolume(AUD_Handle* handle, float volume); * \param pitch The new pitch. * \return Whether the action succeeded. */ -extern int AUD_setSoundPitch(AUD_Handle* handle, float pitch); +extern int AUD_setSoundPitch(AUD_Handle *handle, float pitch); /** * Opens a read device, with which audio data can be read. * \param specs The specification of the audio data. * \return A device handle. */ -extern AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs); +extern AUD_Device *AUD_openReadDevice(AUD_DeviceSpecs specs); /** * Sets the main volume of a device. @@ -409,7 +409,7 @@ extern AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs); * \param volume The new volume, must be between 0.0 and 1.0. * \return Whether the action succeeded. */ -extern int AUD_setDeviceVolume(AUD_Device* device, float volume); +extern int AUD_setDeviceVolume(AUD_Device *device, float volume); /** * Plays back a sound file through a read device. @@ -418,7 +418,7 @@ extern int AUD_setDeviceVolume(AUD_Device* device, float volume); * \param seek The position where the sound should be seeked to. * \return A handle to the played back sound. */ -extern AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek); +extern AUD_Handle *AUD_playDevice(AUD_Device *device, AUD_Sound *sound, float seek); /** * Reads the next samples into the supplied buffer. @@ -429,23 +429,23 @@ extern AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float se * played back currently, in that case the buffer is filled with * silence. */ -extern int AUD_readDevice(AUD_Device* device, data_t* buffer, int length); +extern int AUD_readDevice(AUD_Device *device, data_t *buffer, int length); /** * Closes a read device. * \param device The read device. */ -extern void AUD_closeReadDevice(AUD_Device* device); +extern void AUD_closeReadDevice(AUD_Device *device); /** * Reads a sound file into a newly created float buffer. * The sound is therefore bandpassed, rectified and resampled. */ -extern float* AUD_readSoundBuffer(const char* filename, float low, float high, +extern float *AUD_readSoundBuffer(const char *filename, float low, float high, float attack, float release, float threshold, int accumulate, int additive, int square, float sthreshold, double samplerate, - int* length); + int *length); /** * Pauses a playing sound after a specific amount of time. @@ -453,7 +453,7 @@ extern float* AUD_readSoundBuffer(const char* filename, float low, float high, * \param seconds The time in seconds. * \return The silence handle. */ -extern AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds); +extern AUD_Handle *AUD_pauseAfter(AUD_Handle *handle, float seconds); /** * Creates a new sequenced sound scene. @@ -461,27 +461,27 @@ extern AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds); * \param muted Whether the scene is muted. * \return The new sound scene. */ -extern AUD_Sound* AUD_createSequencer(float fps, int muted); +extern AUD_Sound *AUD_createSequencer(float fps, int muted); /** * Deletes a sound scene. * \param sequencer The sound scene. */ -extern void AUD_destroySequencer(AUD_Sound* sequencer); +extern void AUD_destroySequencer(AUD_Sound *sequencer); /** * Sets the muting state of the scene. * \param sequencer The sound scene. * \param muted Whether the scene is muted. */ -extern void AUD_setSequencerMuted(AUD_Sound* sequencer, int muted); +extern void AUD_setSequencerMuted(AUD_Sound *sequencer, int muted); /** * Sets the scene's FPS. * \param sequencer The sound scene. * \param fps The new FPS. */ -extern void AUD_setSequencerFPS(AUD_Sound* sequencer, float fps); +extern void AUD_setSequencerFPS(AUD_Sound *sequencer, float fps); /** * Adds a new entry to the scene. @@ -492,7 +492,7 @@ extern void AUD_setSequencerFPS(AUD_Sound* sequencer, float fps); * \param skip How much seconds should be skipped at the beginning. * \return The entry added. */ -extern AUD_SEntry* AUD_addSequence(AUD_Sound* sequencer, AUD_Sound* sound, +extern AUD_SEntry *AUD_addSequence(AUD_Sound *sequencer, AUD_Sound *sound, float begin, float end, float skip); /** @@ -500,7 +500,7 @@ extern AUD_SEntry* AUD_addSequence(AUD_Sound* sequencer, AUD_Sound* sound, * \param sequencer The sound scene. * \param entry The entry to remove. */ -extern void AUD_removeSequence(AUD_Sound* sequencer, AUD_SEntry* entry); +extern void AUD_removeSequence(AUD_Sound *sequencer, AUD_SEntry *entry); /** * Moves the entry. @@ -509,14 +509,14 @@ extern void AUD_removeSequence(AUD_Sound* sequencer, AUD_SEntry* entry); * \param end The new end time or a negative value if unknown. * \param skip How many seconds to skip at the beginning. */ -extern void AUD_moveSequence(AUD_SEntry* entry, float begin, float end, float skip); +extern void AUD_moveSequence(AUD_SEntry *entry, float begin, float end, float skip); /** * Sets the muting state of the entry. * \param entry The sequenced entry. * \param mute Whether the entry should be muted or not. */ -extern void AUD_muteSequence(AUD_SEntry* entry, char mute); +extern void AUD_muteSequence(AUD_SEntry *entry, char mute); /** * Sets whether the entrie's location, velocity and orientation are relative @@ -525,14 +525,14 @@ extern void AUD_muteSequence(AUD_SEntry* entry, char mute); * \param relative Whether the source is relative. * \return Whether the action succeeded. */ -extern void AUD_setRelativeSequence(AUD_SEntry* entry, char relative); +extern void AUD_setRelativeSequence(AUD_SEntry *entry, char relative); /** * Sets the sound of the entry. * \param entry The sequenced entry. * \param sound The new sound. */ -extern void AUD_updateSequenceSound(AUD_SEntry* entry, AUD_Sound* sound); +extern void AUD_updateSequenceSound(AUD_SEntry *entry, AUD_Sound *sound); /** * Writes animation data to a sequenced entry. @@ -542,7 +542,7 @@ extern void AUD_updateSequenceSound(AUD_SEntry* entry, AUD_Sound* sound); * \param data The data to write. * \param animated Whether the attribute is animated. */ -extern void AUD_setSequenceAnimData(AUD_SEntry* entry, AUD_AnimateablePropertyType type, int frame, float* data, char animated); +extern void AUD_setSequenceAnimData(AUD_SEntry *entry, AUD_AnimateablePropertyType type, int frame, float *data, char animated); /** * Writes animation data to a sequenced entry. @@ -552,7 +552,7 @@ extern void AUD_setSequenceAnimData(AUD_SEntry* entry, AUD_AnimateablePropertyTy * \param data The data to write. * \param animated Whether the attribute is animated. */ -extern void AUD_setSequencerAnimData(AUD_Sound* sequencer, AUD_AnimateablePropertyType type, int frame, float* data, char animated); +extern void AUD_setSequencerAnimData(AUD_Sound *sequencer, AUD_AnimateablePropertyType type, int frame, float *data, char animated); /** * Updates all non-animated parameters of the entry. @@ -566,7 +566,7 @@ extern void AUD_setSequencerAnimData(AUD_Sound* sequencer, AUD_AnimateableProper * \param cone_angle_inner The inner cone opening angle. * \param cone_volume_outer The volume outside the outer cone. */ -extern void AUD_updateSequenceData(AUD_SEntry* entry, float volume_max, float volume_min, +extern void AUD_updateSequenceData(AUD_SEntry *entry, float volume_max, float volume_min, float distance_max, float distance_reference, float attenuation, float cone_angle_outer, float cone_angle_inner, float cone_volume_outer); @@ -577,7 +577,7 @@ extern void AUD_updateSequenceData(AUD_SEntry* entry, float volume_max, float vo * \param factor The doppler factor to control the effect's strength. * \param model The distance model for distance calculation. */ -extern void AUD_updateSequencerData(AUD_Sound* sequencer, float speed_of_sound, +extern void AUD_updateSequencerData(AUD_Sound *sequencer, float speed_of_sound, float factor, AUD_DistanceModel model); /** @@ -585,28 +585,28 @@ extern void AUD_updateSequencerData(AUD_Sound* sequencer, float speed_of_sound, * current playback device. * \param sequencer The sound scene. */ -extern void AUD_setSequencerDeviceSpecs(AUD_Sound* sequencer); +extern void AUD_setSequencerDeviceSpecs(AUD_Sound *sequencer); /** * Sets the audio output specification of the sound scene. * \param sequencer The sound scene. * \param specs The new specification. */ -extern void AUD_setSequencerSpecs(AUD_Sound* sequencer, AUD_Specs specs); +extern void AUD_setSequencerSpecs(AUD_Sound *sequencer, AUD_Specs specs); /** * Seeks sequenced sound scene playback. * \param handle Playback handle. * \param time Time in seconds to seek to. */ -extern void AUD_seekSequencer(AUD_Handle* handle, float time); +extern void AUD_seekSequencer(AUD_Handle *handle, float time); /** * Returns the current sound scene playback time. * \param handle Playback handle. * \return The playback time in seconds. */ -extern float AUD_getSequencerPosition(AUD_Handle* handle); +extern float AUD_getSequencerPosition(AUD_Handle *handle); /** * Starts the playback of jack transport if possible. @@ -624,7 +624,7 @@ extern void AUD_stopPlayback(void); * \param function The callback function. * \param data The data parameter for the callback. */ -extern void AUD_setSyncCallback(AUD_syncFunction function, void* data); +extern void AUD_setSyncCallback(AUD_syncFunction function, void *data); #endif /** @@ -641,32 +641,32 @@ extern int AUD_doesPlayback(void); * \param samples_per_second How many samples to read per second of the sound. * \return How many samples really have been read. Always <= length. */ -extern int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length, int samples_per_second); +extern int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second); /** * Copies a sound. * \param sound Sound to copy. * \return Copied sound. */ -extern AUD_Sound* AUD_copy(AUD_Sound* sound); +extern AUD_Sound *AUD_copy(AUD_Sound *sound); /** * Frees a handle. * \param channel Handle to free. */ -extern void AUD_freeHandle(AUD_Handle* channel); +extern void AUD_freeHandle(AUD_Handle *channel); /** * Creates a new set. * \return The new set. */ -extern void* AUD_createSet(void); +extern void *AUD_createSet(void); /** * Deletes a set. * \param set The set to delete. */ -extern void AUD_destroySet(void* set); +extern void AUD_destroySet(void *set); /** * Removes an entry from a set. @@ -674,21 +674,21 @@ extern void AUD_destroySet(void* set); * \param entry The entry to remove. * \return Whether the entry was in the set or not. */ -extern char AUD_removeSet(void* set, void* entry); +extern char AUD_removeSet(void *set, void *entry); /** * Adds a new entry to a set. * \param set The set work on. * \param entry The entry to add. */ -extern void AUD_addSet(void* set, void* entry); +extern void AUD_addSet(void *set, void *entry); /** * Removes one entry from a set and returns it. * \param set The set work on. * \return The entry or NULL if the set is empty. */ -extern void* AUD_getSet(void* set); +extern void *AUD_getSet(void *set); /** * Mixes a sound down into a file. @@ -703,7 +703,10 @@ extern void* AUD_getSet(void* set); * \param bitrate The bitrate for encoding. * \return An error message or NULL in case of success. */ -extern const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate); +extern const char *AUD_mixdown(AUD_Sound *sound, unsigned int start, unsigned int length, + unsigned int buffersize, const char *filename, + AUD_DeviceSpecs specs, AUD_Container format, + AUD_Codec codec, unsigned int bitrate); /** * Mixes a sound down into multiple files. @@ -718,7 +721,10 @@ extern const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned in * \param bitrate The bitrate for encoding. * \return An error message or NULL in case of success. */ -extern const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate); +extern const char *AUD_mixdown_per_channel(AUD_Sound *sound, unsigned int start, unsigned int length, + unsigned int buffersize, const char *filename, + AUD_DeviceSpecs specs, AUD_Container format, + AUD_Codec codec, unsigned int bitrate); /** * Opens a read device and prepares it for mixdown of the sound scene. @@ -728,7 +734,7 @@ extern const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, * \param start The start time of the mixdown in the sound scene. * \return The read device for the mixdown. */ -extern AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer, float volume, float start); +extern AUD_Device *AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound *sequencer, float volume, float start); #ifdef WITH_PYTHON /** @@ -736,14 +742,14 @@ extern AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* seque * \param sound The sound factory. * \return The python factory. */ -extern void* AUD_getPythonFactory(AUD_Sound* sound); +extern void *AUD_getPythonFactory(AUD_Sound *sound); /** * Retrieves the sound factory of a python factory. * \param sound The python factory. * \return The sound factory. */ -extern AUD_Sound* AUD_getPythonSound(void* sound); +extern AUD_Sound *AUD_getPythonSound(void *sound); #endif #ifdef __cplusplus @@ -763,7 +769,7 @@ AUD_Reference AUD_getDevice(); * Returns the current playback 3D device. * \return The playback 3D device. */ -AUD_I3DDevice* AUD_get3DDevice(); +AUD_I3DDevice *AUD_get3DDevice(); #endif #endif //__AUD_C_API_H__ diff --git a/intern/cycles/kernel/osl/nodes/CMakeLists.txt b/intern/cycles/kernel/osl/nodes/CMakeLists.txt index 08e9b9ee726..729d4dae1c9 100644 --- a/intern/cycles/kernel/osl/nodes/CMakeLists.txt +++ b/intern/cycles/kernel/osl/nodes/CMakeLists.txt @@ -38,9 +38,11 @@ set(SRC_OSL node_musgrave_texture.osl node_normal.osl node_noise_texture.osl + node_object_info.osl node_output_displacement.osl node_output_surface.osl node_output_volume.osl + node_particle_info.osl node_separate_rgb.osl node_sky_texture.osl node_texture_coordinate.osl diff --git a/intern/cycles/kernel/osl/nodes/node_object_info.osl b/intern/cycles/kernel/osl/nodes/node_object_info.osl new file mode 100644 index 00000000000..21e50d8a43e --- /dev/null +++ b/intern/cycles/kernel/osl/nodes/node_object_info.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_object_info( + output point Location = point(0.0, 0.0, 0.0), + output float ObjectIndex = 0.0, + output float MaterialIndex = 0.0, + output float Random = 0.0 + ) +{ + getattribute("std::object_location", Location); + getattribute("std::object_index", ObjectIndex); + getattribute("std::material_index", MaterialIndex); + getattribute("std::object_random", Random); +} + diff --git a/intern/cycles/kernel/osl/nodes/node_particle_info.osl b/intern/cycles/kernel/osl/nodes/node_particle_info.osl new file mode 100644 index 00000000000..aadc2812865 --- /dev/null +++ b/intern/cycles/kernel/osl/nodes/node_particle_info.osl @@ -0,0 +1,39 @@ +/* + * 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_particle_info( + output float Index = 0.0, + output float Age = 0.0, + output float Lifetime = 0.0, + output point Location = point(0.0, 0.0, 0.0), + output float Size = 0.0, + output vector Velocity = point(0.0, 0.0, 0.0), + output vector AngularVelocity = point(0.0, 0.0, 0.0) + ) +{ + getattribute("std::particle_index", Index); + getattribute("std::particle_age", Age); + getattribute("std::particle_lifetime", Lifetime); + getattribute("std::particle_location", Location); + getattribute("std::particle_size", Size); + getattribute("std::particle_velocity", Velocity); + getattribute("std::particle_angular_velocity", AngularVelocity); +} + diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h index 075c68824e6..8cbbfc8dbb1 100644 --- a/intern/cycles/kernel/osl/osl_globals.h +++ b/intern/cycles/kernel/osl/osl_globals.h @@ -36,7 +36,7 @@ struct OSLGlobals { /* use */ bool use; - /* shading system */ + /* shading system */ OSL::ShadingSystem *ss; OSLRenderServices *services; diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index a3f2c2ea369..f1deaa9db9d 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -179,55 +179,68 @@ bool OSLRenderServices::get_array_attribute(void *renderstate, bool derivatives, return false; } -static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, - const OSLGlobals::Attribute& attr, bool derivatives, void *val) +static void set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, void *val) { - if (attr.type == TypeDesc::TypeFloat) { - float *fval = (float *)val; - fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset, - (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || + type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) + { + float3 *fval = (float3 *)val; + fval[0] = f[0]; + if (derivatives) { + fval[1] = f[1]; + fval[2] = f[2]; + } } else { - /* todo: this won't work when float3 has w component */ - float3 *fval = (float3 *)val; - fval[0] = triangle_attribute_float3(kg, sd, attr.elem, attr.offset, - (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + float *fval = (float *)val; + fval[0] = average(f[0]); + if (derivatives) { + fval[1] = average(f[1]); + fval[2] = average(f[2]); + } } - - return true; } -static bool get_mesh_attribute_convert(KernelGlobals *kg, const ShaderData *sd, - const OSLGlobals::Attribute& attr, const TypeDesc& type, bool derivatives, void *val) +static void set_attribute_float(float f[3], TypeDesc type, bool derivatives, void *val) +{ + if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || + type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) + { + float3 *fval = (float3 *)val; + fval[0] = make_float3(f[0], f[0], f[0]); + if (derivatives) { + fval[1] = make_float3(f[1], f[2], f[1]); + fval[2] = make_float3(f[2], f[2], f[2]); + } + } + else { + float *fval = (float *)val; + fval[0] = f[0]; + if (derivatives) { + fval[1] = f[1]; + fval[2] = f[2]; + } + } +} + +static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OSLGlobals::Attribute& attr, + const TypeDesc& type, bool derivatives, void *val) { if (attr.type == TypeDesc::TypeFloat) { - float tmp[3]; - float3 *fval = (float3 *)val; - - get_mesh_attribute(kg, sd, attr, derivatives, tmp); - - fval[0] = make_float3(tmp[0], tmp[0], tmp[0]); - if (derivatives) { - fval[1] = make_float3(tmp[1], tmp[1], tmp[1]); - fval[2] = make_float3(tmp[2], tmp[2], tmp[2]); - } - + float fval[3]; + fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset, + (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + set_attribute_float(fval, type, derivatives, val); return true; } else if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector || attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) { - float3 tmp[3]; - float *fval = (float *)val; - - get_mesh_attribute(kg, sd, attr, derivatives, tmp); - - fval[0] = average(tmp[0]); - if (derivatives) { - fval[1] = average(tmp[1]); - fval[2] = average(tmp[2]); - } - + /* todo: this won't work when float3 has w component */ + float3 fval[3]; + fval[0] = triangle_attribute_float3(kg, sd, attr.elem, attr.offset, + (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + set_attribute_float3(fval, type, derivatives, val); return true; } else @@ -243,11 +256,116 @@ static void get_object_attribute(const OSLGlobals::Attribute& attr, bool derivat memset((char *)val + datasize, 0, datasize * 2); } +static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, + TypeDesc type, bool derivatives, void *val) +{ + /* Object Attributes */ + if (name == "std::object_location") { + float3 fval[3]; + fval[0] = object_location(kg, sd); + fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ + set_attribute_float3(fval, type, derivatives, val); + return true; + } + else if (name == "std::object_index") { + float fval[3]; + fval[0] = object_pass_id(kg, sd->object); + fval[1] = fval[2] = 0.0; /* derivates set to 0 */ + set_attribute_float(fval, type, derivatives, val); + return true; + } + else if (name == "std::material_index") { + float fval[3]; + fval[0] = shader_pass_id(kg, sd); + fval[1] = fval[2] = 0.0; /* derivates set to 0 */ + set_attribute_float(fval, type, derivatives, val); + return true; + } + else if (name == "std::object_random") { + float fval[3]; + fval[0] = object_random_number(kg, sd->object); + fval[1] = fval[2] = 0.0; /* derivates set to 0 */ + set_attribute_float(fval, type, derivatives, val); + return true; + } + + /* Particle Attributes */ + else if (name == "std::particle_index") { + float fval[3]; + uint particle_id = object_particle_id(kg, sd->object); + fval[0] = particle_index(kg, particle_id); + fval[1] = fval[2] = 0.0; /* derivates set to 0 */ + set_attribute_float(fval, type, derivatives, val); + return true; + } + else if (name == "std::particle_age") { + float fval[3]; + uint particle_id = object_particle_id(kg, sd->object); + fval[0] = particle_age(kg, particle_id); + fval[1] = fval[2] = 0.0; /* derivates set to 0 */ + set_attribute_float(fval, type, derivatives, val); + return true; + } + else if (name == "std::particle_lifetime") { + float fval[3]; + uint particle_id = object_particle_id(kg, sd->object); + fval[0] = particle_lifetime(kg, particle_id); + fval[1] = fval[2] = 0.0; /* derivates set to 0 */ + set_attribute_float(fval, type, derivatives, val); + return true; + } + else if (name == "std::particle_location") { + float3 fval[3]; + uint particle_id = object_particle_id(kg, sd->object); + fval[0] = particle_location(kg, particle_id); + fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ + set_attribute_float3(fval, type, derivatives, val); + return true; + } +#if 0 /* unsupported */ + else if (name == "std::particle_rotation") { + float4 fval[3]; + uint particle_id = object_particle_id(kg, sd->object); + fval[0] = particle_rotation(kg, particle_id); + fval[1] = fval[2] = make_float4(0.0, 0.0, 0.0, 0.0); /* derivates set to 0 */ + set_attribute_float4(fval, type, derivatives, val); + return true; + } +#endif + else if (name == "std::particle_size") { + float fval[3]; + uint particle_id = object_particle_id(kg, sd->object); + fval[0] = particle_size(kg, particle_id); + fval[1] = fval[2] = 0.0; /* derivates set to 0 */ + set_attribute_float(fval, type, derivatives, val); + return true; + } + else if (name == "std::particle_velocity") { + float3 fval[3]; + uint particle_id = object_particle_id(kg, sd->object); + fval[0] = particle_velocity(kg, particle_id); + fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ + set_attribute_float3(fval, type, derivatives, val); + return true; + } + else if (name == "std::particle_angular_velocity") { + float3 fval[3]; + uint particle_id = object_particle_id(kg, sd->object); + fval[0] = particle_angular_velocity(kg, particle_id); + fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ + set_attribute_float3(fval, type, derivatives, val); + return true; + } + + else + return false; +} + bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustring object_name, TypeDesc type, ustring name, void *val) { KernelGlobals *kg = kernel_globals; - const ShaderData *sd = (const ShaderData *)renderstate; + ShaderData *sd = (ShaderData *)renderstate; int object = sd->object; int tri = sd->prim; @@ -270,29 +388,23 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri OSLGlobals::AttributeMap& attribute_map = kg->osl.attribute_map[object]; OSLGlobals::AttributeMap::iterator it = attribute_map.find(name); - if (it == attribute_map.end()) - return false; - - /* type mistmatch? */ - const OSLGlobals::Attribute& attr = it->second; - - if (attr.elem != ATTR_ELEMENT_VALUE) { - /* triangle and vertex attributes */ - if (tri != ~0) { - if (attr.type == type || (attr.type == TypeDesc::TypeColor && - (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || type == TypeDesc::TypeNormal))) - { - return get_mesh_attribute(kg, sd, attr, derivatives, val); - } - else { - return get_mesh_attribute_convert(kg, sd, attr, type, derivatives, val); - } + if (it != attribute_map.end()) { + const OSLGlobals::Attribute& attr = it->second; + + if (attr.elem != ATTR_ELEMENT_VALUE) { + /* triangle and vertex attributes */ + if (tri != ~0) + return get_mesh_attribute(kg, sd, attr, type, derivatives, val); + } + else { + /* object attribute */ + get_object_attribute(attr, derivatives, val); + return true; } } else { - /* object attribute */ - get_object_attribute(attr, derivatives, val); - return true; + /* not found in attribute, check standard object info */ + return get_object_standard_attribute(kg, sd, name, type, derivatives, val); } return false; @@ -310,15 +422,16 @@ bool OSLRenderServices::has_userdata(ustring name, TypeDesc type, void *renderst } int OSLRenderServices::pointcloud_search(OSL::ShaderGlobals *sg, ustring filename, const OSL::Vec3 ¢er, - float radius, int max_points, bool sort, size_t *out_indices, float *out_distances, int derivs_offset) + float radius, int max_points, bool sort, + size_t *out_indices, float *out_distances, int derivs_offset) { - return 0; + return 0; } int OSLRenderServices::pointcloud_get(ustring filename, size_t *indices, int count, - ustring attr_name, TypeDesc attr_type, void *out_data) + ustring attr_name, TypeDesc attr_type, void *out_data) { - return 0; + return 0; } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h index 5ec8a8edf9e..790b02a8abc 100644 --- a/intern/cycles/kernel/osl/osl_services.h +++ b/intern/cycles/kernel/osl/osl_services.h @@ -56,22 +56,22 @@ public: bool get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform); bool get_matrix(OSL::Matrix44 &result, ustring from); - bool get_array_attribute(void *renderstate, bool derivatives, + bool get_array_attribute(void *renderstate, bool derivatives, ustring object, TypeDesc type, ustring name, int index, void *val); bool get_attribute(void *renderstate, bool derivatives, ustring object, TypeDesc type, ustring name, void *val); - bool get_userdata(bool derivatives, ustring name, TypeDesc type, + bool get_userdata(bool derivatives, ustring name, TypeDesc type, void *renderstate, void *val); bool has_userdata(ustring name, TypeDesc type, void *renderstate); - + int pointcloud_search(OSL::ShaderGlobals *sg, ustring filename, const OSL::Vec3 ¢er, - float radius, int max_points, bool sort, size_t *out_indices, - float *out_distances, int derivs_offset); + float radius, int max_points, bool sort, size_t *out_indices, + float *out_distances, int derivs_offset); int pointcloud_get(ustring filename, size_t *indices, int count, ustring attr_name, - TypeDesc attr_type, void *out_data); + TypeDesc attr_type, void *out_data); private: KernelGlobals *kernel_globals; diff --git a/intern/ghost/intern/GHOST_WindowCarbon.cpp b/intern/ghost/intern/GHOST_WindowCarbon.cpp index c7be02cc7af..99d8854667e 100644 --- a/intern/ghost/intern/GHOST_WindowCarbon.cpp +++ b/intern/ghost/intern/GHOST_WindowCarbon.cpp @@ -676,7 +676,7 @@ GHOST_TSuccess GHOST_WindowCarbon::setWindowCursorShape(GHOST_TStandardCursor sh return GHOST_kSuccess; } -#if 0 +#if 0 /* UNUSED */ /** Reverse the bits in a GHOST_TUns8 */ static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch) { diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 0e8ff438998..c9c902fca8b 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -20,7 +20,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Maarten Gribnau. * * ***** END GPL LICENSE BLOCK ***** */ @@ -29,13 +29,6 @@ * \ingroup GHOST */ - -/** - * Copyright (C) 2001 NaN Technologies B.V. - * \author Maarten Gribnau - * \date May 10, 2001 - */ - #include #include "GHOST_WindowWin32.h" #include "GHOST_SystemWin32.h" @@ -50,7 +43,7 @@ // MSVC6 still doesn't define M_PI #ifndef M_PI -#define M_PI 3.1415926536 +# define M_PI 3.1415926536 #endif // Some more multisample defines @@ -58,14 +51,14 @@ #define WGL_SAMPLES_ARB 0x2042 // win64 doesn't define GWL_USERDATA -#ifdef WIN32 -#ifndef GWL_USERDATA -#define GWL_USERDATA GWLP_USERDATA -#define GWL_WNDPROC GWLP_WNDPROC -#endif +#ifdef WIN32 /* why? - probably should remove */ +# ifndef GWL_USERDATA +# define GWL_USERDATA GWLP_USERDATA +# define GWL_WNDPROC GWLP_WNDPROC +# endif #endif -wchar_t *GHOST_WindowWin32::s_windowClassName = L"GHOST_WindowClass"; +const wchar_t *GHOST_WindowWin32::s_windowClassName = L"GHOST_WindowClass"; const int GHOST_WindowWin32::s_maxTitleLength = 128; HGLRC GHOST_WindowWin32::s_firsthGLRc = NULL; HDC GHOST_WindowWin32::s_firstHDC = NULL; @@ -149,7 +142,6 @@ GHOST_WindowWin32::GHOST_WindowWin32( m_tablet(0), m_maxPressure(0), m_multisample(numOfAASamples), - m_parentWindowHwnd(parentwindowhwnd), m_multisampleEnabled(msEnabled), m_msPixelFormat(msPixelFormat), //For recreation @@ -160,7 +152,8 @@ GHOST_WindowWin32::GHOST_WindowWin32( m_height(height), m_normal_state(GHOST_kWindowStateNormal), m_stereo(stereoVisual), - m_nextWindow(NULL) + m_nextWindow(NULL), + m_parentWindowHwnd(parentwindowhwnd) { OSVERSIONINFOEX versionInfo; bool hasMinVersionForTaskbar = false; @@ -1208,6 +1201,7 @@ static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch) return ch; } +#if 0 /* UNUSED */ /** Reverse the bits in a GHOST_TUns16 */ static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt) { @@ -1217,6 +1211,7 @@ static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt) shrt = ((shrt >> 8) & 0x00FF) | ((shrt << 8) & 0xFF00); return shrt; } +#endif GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY) diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index 3f52f9e22b0..9e4377b8225 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -236,7 +236,7 @@ public: * Returns the name of the window class. * \return The name of the window class. */ - static wchar_t *getWindowClassName() { + static const wchar_t *getWindowClassName() { return s_windowClassName; } @@ -355,7 +355,7 @@ protected: /** ITaskbarList3 structure for progress bar*/ ITaskbarList3 *m_Bar; - static wchar_t *s_windowClassName; + static const wchar_t *s_windowClassName; static const int s_maxTitleLength; /** WinTab dll handle */ diff --git a/intern/mikktspace/mikktspace.c b/intern/mikktspace/mikktspace.c index 0a3141d6782..a1ae6bd81c0 100644 --- a/intern/mikktspace/mikktspace.c +++ b/intern/mikktspace/mikktspace.c @@ -437,7 +437,7 @@ const int g_iCells = 2048; // it is IMPORTANT that this function is called to evaluate the hash since // inlining could potentially reorder instructions and generate different // results for the same effective input value fVal. -NOINLINE int FindGridCell(const float fMin, const float fMax, const float fVal) +static NOINLINE int FindGridCell(const float fMin, const float fMax, const float fVal) { const float fIndex = g_iCells * ((fVal-fMin)/(fMax-fMin)); const int iIndex = fIndex<0?0:((int)fIndex); diff --git a/intern/raskter/raskter.c b/intern/raskter/raskter.c index 659d01e2d82..875dfc8a63b 100644 --- a/intern/raskter/raskter.c +++ b/intern/raskter/raskter.c @@ -38,7 +38,7 @@ // this is needed for inlining behavior -#if defined _WIN32 +#if defined _MSC_VER # define DO_INLINE __inline #elif defined (__sun) || defined (__sun__) # define DO_INLINE @@ -819,7 +819,7 @@ int PLX_raskterize_feather(float(*base_verts)[2], int num_base_verts, float(*fea #ifndef __PLX__FAKE_AA__ -int get_range_expanded_pixel_coord(float normalized_value, int max_value) { +static int get_range_expanded_pixel_coord(float normalized_value, int max_value) { return (int)((normalized_value * (float)(max_value)) + 0.5f); } @@ -1395,7 +1395,7 @@ int PLX_antialias_buffer(float *buf, int buf_x, int buf_y) { #define SWAP_POLYVERT(a,b) point_temp[0]=(a)[0]; point_temp[1]=(a)[1]; (a)[0]=(b)[0]; (a)[1]=(b)[1]; (b)[0]=point_temp[0]; (b)[1]=point_temp[1]; #define __PLX_SMALL_COUNT__ 13 -void plx_floatsort(float(*f)[2], unsigned int n, int sortby) { +static void plx_floatsort(float(*f)[2], unsigned int n, int sortby) { unsigned int a; unsigned int b; unsigned int c; @@ -1474,7 +1474,7 @@ void plx_floatsort(float(*f)[2], unsigned int n, int sortby) { } } -int plx_find_lower_bound(float v, float(*a)[2], int num_feather_verts) { +static int plx_find_lower_bound(float v, float(*a)[2], int num_feather_verts) { int x; int l; int r; @@ -1502,7 +1502,7 @@ int plx_find_lower_bound(float v, float(*a)[2], int num_feather_verts) { } } -int plx_find_upper_bound(float v, float(*a)[2], int num_feather_verts) { +static int plx_find_upper_bound(float v, float(*a)[2], int num_feather_verts) { int x; int l; int r; diff --git a/intern/utfconv/utfconv.c b/intern/utfconv/utfconv.c index a9b2920111d..7f7a612528d 100644 --- a/intern/utfconv/utfconv.c +++ b/intern/utfconv/utfconv.c @@ -219,7 +219,9 @@ int conv_utf_8_to_16(const char *in8, wchar_t *out16, size_t size16) return err; } -int is_ascii(const char *in8) +/* UNUSED FUNCTIONS */ +#if 0 +static int is_ascii(const char *in8) { for (; *in8; in8++) if (0x80 & *in8) return 0; @@ -227,7 +229,7 @@ int is_ascii(const char *in8) return 1; } -void utf_8_cut_end(char *inout8, size_t maxcutpoint) +static void utf_8_cut_end(char *inout8, size_t maxcutpoint) { char *cur = inout8 + maxcutpoint; char cc; @@ -235,7 +237,7 @@ void utf_8_cut_end(char *inout8, size_t maxcutpoint) cc = *cur; } - +#endif char *alloc_utf_8_from_16(const wchar_t *in16, size_t add) diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index d19c57b0d5b..cd67059ea8c 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -42,7 +42,7 @@ struct Histogram; struct ImBuf; struct rctf; -#if defined _WIN32 +#if defined _MSC_VER # define DO_INLINE __inline #elif defined(__sun) || defined(__sun__) # define DO_INLINE diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 19dd67b88f8..33361b9921c 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -73,6 +73,8 @@ extern const CustomDataMask CD_MASK_FACECORNERS; #define CD_TYPE_AS_MASK(_type) (CustomDataMask)((CustomDataMask)1 << (CustomDataMask)(_type)) +void customData_mask_layers__print(CustomDataMask mask); + /** * Checks if the layer at physical offset \a layer_n (in data->layers) support math * the below operations. diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 51e301fec80..cc15ceecbac 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -131,6 +131,7 @@ void BKE_mask_get_handle_point_adjacent(struct MaskSpline *spline, struct MaskSp void BKE_mask_layer_calc_handles(struct MaskLayer *masklay); void BKE_mask_layer_calc_handles_deform(struct MaskLayer *masklay); void BKE_mask_calc_handles(struct Mask *mask); +void BKE_mask_update_deform(struct Mask *mask); void BKE_mask_spline_ensure_deform(struct MaskSpline *spline); /* animation */ @@ -163,10 +164,10 @@ void BKE_mask_layer_shape_changed_remove(struct MaskLayer *masklay, int index, i int BKE_mask_get_duration(struct Mask *mask); -#define MASKPOINT_ISSEL_ANY(p) ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f2) & SELECT) +#define MASKPOINT_ISSEL_ANY(p) ( ((p)->bezt.f1 | (p)->bezt.f2 | (p)->bezt.f3) & SELECT) #define MASKPOINT_ISSEL_KNOT(p) ( (p)->bezt.f2 & SELECT) -#define MASKPOINT_ISSEL_HANDLE_ONLY(p) ( (((p)->bezt.f1 | (p)->bezt.f2) & SELECT) && (((p)->bezt.f2 & SELECT) == 0) ) -#define MASKPOINT_ISSEL_HANDLE(p) ( (((p)->bezt.f1 | (p)->bezt.f2) & SELECT) ) +#define MASKPOINT_ISSEL_HANDLE_ONLY(p) ( (((p)->bezt.f1 | (p)->bezt.f3) & SELECT) && (((p)->bezt.f2 & SELECT) == 0) ) +#define MASKPOINT_ISSEL_HANDLE(p) ( (((p)->bezt.f1 | (p)->bezt.f3) & SELECT) ) #define MASKPOINT_SEL_ALL(p) { (p)->bezt.f1 |= SELECT; (p)->bezt.f2 |= SELECT; (p)->bezt.f3 |= SELECT; } (void)0 #define MASKPOINT_DESEL_ALL(p) { (p)->bezt.f1 &= ~SELECT; (p)->bezt.f2 &= ~SELECT; (p)->bezt.f3 &= ~SELECT; } (void)0 diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 576b79f899c..efdb80433c6 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -44,6 +44,7 @@ set(INC ../../../intern/mikktspace ../../../intern/opennl/extern ../../../intern/raskter + ../../../intern/smoke/extern # XXX - BAD LEVEL CALL WM_api.h ../windowmanager @@ -342,9 +343,6 @@ if(WITH_MOD_FLUID) endif() if(WITH_MOD_SMOKE) - list(APPEND INC - ../../../intern/smoke/extern - ) add_definitions(-DWITH_SMOKE) endif() diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 9145c4af850..99b788e80ce 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -92,7 +92,7 @@ #include "IMB_colormanagement.h" #ifdef WITH_PYTHON -#include "BPY_extern.h" +# include "BPY_extern.h" #endif Global G; @@ -219,8 +219,6 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath /* no load screens? */ if (mode) { /* comes from readfile.c */ - extern void lib_link_screen_restore(Main *, bScreen *, Scene *); - SWAP(ListBase, G.main->wm, bfd->main->wm); SWAP(ListBase, G.main->screen, bfd->main->screen); SWAP(ListBase, G.main->script, bfd->main->script); @@ -234,7 +232,7 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath if (curscreen) curscreen->scene = curscene; /* can run in bgmode */ /* clear_global will free G.main, here we can still restore pointers */ - lib_link_screen_restore(bfd->main, curscreen, curscene); + blo_lib_link_screen_restore(bfd->main, curscreen, curscene); } /* free G.main Main database */ diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index b0de7a5ea6c..4241756a109 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -50,36 +50,7 @@ #include "BKE_modifier.h" #include "BKE_pointcache.h" -#ifdef _WIN32 -void tstart( void ) -{} -void tend( void ) -{ -} -double tval( void ) -{ - return 0; -} -#else -#include -static struct timeval _tstart, _tend; -static struct timezone tz; -void tstart( void ) -{ - gettimeofday(&_tstart, &tz); -} -void tend(void) -{ - gettimeofday(&_tend, &tz); -} -double tval(void) -{ - double t1, t2; - t1 = ( double ) _tstart.tv_sec + ( double ) _tstart.tv_usec/ ( 1000*1000 ); - t2 = ( double ) _tend.tv_sec + ( double ) _tend.tv_usec/ ( 1000*1000 ); - return t2-t1; -} -#endif +// #include "PIL_time.h" /* timing for debug prints */ /* Our available solvers. */ // 255 is the magic reserved number, so NEVER try to put 255 solvers in here! @@ -410,13 +381,13 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul cloth_apply_vgroup ( clmd, result ); cloth_update_springs( clmd ); - tstart(); + // TIMEIT_START(cloth_step) /* call the solver. */ if (solvers [clmd->sim_parms->solver_type].solver) ret = solvers[clmd->sim_parms->solver_type].solver(ob, framenr, clmd, effectors); - tend(); + // TIMEIT_END(cloth_step) pdEndEffectors(&effectors); diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index f47ac641cf9..1cb29b90133 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -669,7 +669,7 @@ static void boundInsert(Bounds3D *b, float point[3]) } } -float getSurfaceDimension(PaintSurfaceData *sData) +static float getSurfaceDimension(PaintSurfaceData *sData) { Bounds3D *mb = &sData->bData->mesh_bounds; return MAX3((mb->max[0] - mb->min[0]), (mb->max[1] - mb->min[1]), (mb->max[2] - mb->min[2])); @@ -910,7 +910,7 @@ static void free_bakeData(PaintSurfaceData *data) } /* free surface data if it's not used anymore */ -void surface_freeUnusedData(DynamicPaintSurface *surface) +static void surface_freeUnusedData(DynamicPaintSurface *surface) { if (!surface->data) return; @@ -1368,7 +1368,7 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int for MEM_freeN(temp_data); } -void dynamicPaint_setInitialColor(DynamicPaintSurface *surface) +static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface) { PaintSurfaceData *sData = surface->data; PaintPoint *pPoint = (PaintPoint *)sData->type_data; @@ -1605,7 +1605,7 @@ static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, Deri /* * Apply canvas data to the object derived mesh */ -struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, +static DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *ob, DerivedMesh *dm) { @@ -1830,9 +1830,12 @@ void dynamicPaint_cacheUpdateFrames(DynamicPaintSurface *surface) } } -void canvas_copyDerivedMesh(DynamicPaintCanvasSettings *canvas, DerivedMesh *dm) +static void canvas_copyDerivedMesh(DynamicPaintCanvasSettings *canvas, DerivedMesh *dm) { - if (canvas->dm) canvas->dm->release(canvas->dm); + if (canvas->dm) { + canvas->dm->release(canvas->dm); + } + canvas->dm = CDDM_copy(dm); } @@ -2748,7 +2751,7 @@ static void dynamicPaint_freeBrushMaterials(BrushMaterials *bMats) /* * Get material diffuse color and alpha (including linked textures) in given coordinates */ -void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], float *alpha, Object *brushOb, const float volume_co[3], const float surface_co[3], int faceIndex, short isQuad, DerivedMesh *orcoDm) +static void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], float *alpha, Object *brushOb, const float volume_co[3], const float surface_co[3], int faceIndex, short isQuad, DerivedMesh *orcoDm) { Material *mat = bMats->mat; MFace *mface = orcoDm->getTessFaceArray(orcoDm); @@ -3953,7 +3956,7 @@ static void dynamicPaint_prepareAdjacencyData(DynamicPaintSurface *surface, int } /* find two adjacency points (closest_id) and influence (closest_d) to move paint towards when affected by a force */ -void surface_determineForceTargetPoints(PaintSurfaceData *sData, int index, float force[3], float closest_d[2], int closest_id[2]) +static void surface_determineForceTargetPoints(PaintSurfaceData *sData, int index, float force[3], float closest_d[2], int closest_id[2]) { BakeAdjPoint *bNeighs = sData->bData->bNeighs; int numOfNeighs = sData->adj_data->n_num[index]; @@ -4342,7 +4345,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force } } -void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescale) +static void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescale) { PaintSurfaceData *sData = surface->data; BakeAdjPoint *bNeighs = sData->bData->bNeighs; diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 1c6974b2615..fcc8b4322a0 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -50,6 +50,7 @@ #define CLOTH_OPENMP_LIMIT 512 +#if 0 /* debug timing */ #ifdef _WIN32 #include static LARGE_INTEGER _itstart, _itend; @@ -81,7 +82,7 @@ double itval(void) static struct timeval _itstart, _itend; static struct timezone itz; -void itstart(void) +static void itstart(void) { gettimeofday(&_itstart, &itz); } @@ -89,7 +90,7 @@ static void itend(void) { gettimeofday(&_itend, &itz); } -double itval(void) +static double itval(void) { double t1, t2; t1 = (double)_itstart.tv_sec + (double)_itstart.tv_usec/(1000*1000); @@ -97,6 +98,7 @@ double itval(void) return t2-t1; } #endif +#endif /* debug timing */ static float I[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; static float ZERO[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; @@ -1691,13 +1693,13 @@ static void simulate_implicit_euler(lfVector *Vnew, lfVector *UNUSED(lX), lfVect mul_bfmatrix_lfvector(dFdXmV, dFdX, lV); add_lfvectorS_lfvectorS(B, lF, dt, dFdXmV, (dt*dt), numverts); - - itstart(); - + + // itstart(); + cg_filtered(dV, A, B, z, S); /* conjugate gradient algorithm to solve Ax=b */ // cg_filtered_pre(dV, A, B, z, S, P, Pinv, bigI); - - itend(); + + // itend(); // printf("cg_filtered calc time: %f\n", (float)itval()); cp_lfvector(olddV, dV, numverts); @@ -1713,7 +1715,7 @@ static void simulate_implicit_euler(lfVector *Vnew, lfVector *UNUSED(lX), lfVect * (edge distance constraints) in a lagrangian solver. then add forces to help * guide the implicit solver to that state. this function is called after * collisions*/ -int cloth_calc_helper_forces(Object *UNUSED(ob), ClothModifierData * clmd, float (*initial_cos)[3], float UNUSED(step), float dt) +static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothModifierData * clmd, float (*initial_cos)[3], float UNUSED(step), float dt) { Cloth *cloth= clmd->clothObject; float (*cos)[3] = MEM_callocN(sizeof(float)*3*cloth->numverts, "cos cloth_calc_helper_forces"); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 97b46d4829d..3564071334c 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1112,7 +1112,8 @@ static int BKE_mask_evaluate_parent(MaskParent *parent, float ctime, float r_co[ return FALSE; } -int BKE_mask_evaluate_parent_delta(MaskParent *parent, float ctime, float r_delta[2]) +/* could make external but for now its only used internally */ +static int mask_evaluate_parent_delta(MaskParent *parent, float ctime, float r_delta[2]) { float parent_co[2]; @@ -1452,7 +1453,7 @@ void BKE_mask_layer_evaluate(MaskLayer *masklay, const float ctime, const int do *point_deform = *point; point_deform->uw = point->uw ? MEM_dupallocN(point->uw) : NULL; - if (BKE_mask_evaluate_parent_delta(&point->parent, ctime, delta)) { + if (mask_evaluate_parent_delta(&point->parent, ctime, delta)) { add_v2_v2(point_deform->bezt.vec[0], delta); add_v2_v2(point_deform->bezt.vec[1], delta); add_v2_v2(point_deform->bezt.vec[2], delta); diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 18617f0ef2e..00898b0fe10 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -253,9 +253,9 @@ void BKE_maskrasterize_handle_free(MaskRasterHandle *mr_handle) } -void maskrasterize_spline_differentiate_point_outset(float (*diff_feather_points)[2], float (*diff_points)[2], - const unsigned int tot_diff_point, const float ofs, - const short do_test) +static void maskrasterize_spline_differentiate_point_outset(float (*diff_feather_points)[2], float (*diff_points)[2], + const unsigned int tot_diff_point, const float ofs, + const short do_test) { unsigned int k_prev = tot_diff_point - 2; unsigned int k_curr = tot_diff_point - 1; diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index cd8b0e4e52c..97d4c150b84 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -391,7 +391,7 @@ static int moviecache_hashcmp(const void *av, const void *bv) return 0; } -void *moviecache_getprioritydata(void *key_v) +static void *moviecache_getprioritydata(void *key_v) { MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey *) key_v; MovieClipCachePriorityData *priority_data; @@ -402,7 +402,7 @@ void *moviecache_getprioritydata(void *key_v) return priority_data; } -int moviecache_getitempriority(void *last_userkey_v, void *priority_data_v) +static int moviecache_getitempriority(void *last_userkey_v, void *priority_data_v) { MovieClipImBufCacheKey *last_userkey = (MovieClipImBufCacheKey *) last_userkey_v; MovieClipCachePriorityData *priority_data = (MovieClipCachePriorityData *) priority_data_v; @@ -410,7 +410,7 @@ int moviecache_getitempriority(void *last_userkey_v, void *priority_data_v) return -abs(last_userkey->framenr - priority_data->framenr); } -void moviecache_prioritydeleter(void *priority_data_v) +static void moviecache_prioritydeleter(void *priority_data_v) { MovieClipCachePriorityData *priority_data = (MovieClipCachePriorityData *) priority_data_v; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 5dfecfcb717..4fb235ac9f7 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -305,17 +305,27 @@ void BKE_object_free(Object *ob) ID *id = ob->data; id->us--; if (id->us == 0) { - if (ob->type == OB_MESH) BKE_mesh_unlink(ob->data); - else if (ob->type == OB_CURVE) BKE_curve_unlink(ob->data); - else if (ob->type == OB_MBALL) BKE_mball_unlink(ob->data); + switch (ob->type) { + case OB_MESH: + BKE_mesh_unlink((Mesh *)id); + break; + case OB_CURVE: + BKE_curve_unlink((Curve *)id); + break; + case OB_MBALL: + BKE_mball_unlink((MetaBall *)id); + break; + } } ob->data = NULL; } - - for (a = 0; a < ob->totcol; a++) { - if (ob->mat[a]) ob->mat[a]->id.us--; + + if (ob->mat) { + for (a = 0; a < ob->totcol; a++) { + if (ob->mat[a]) ob->mat[a]->id.us--; + } + MEM_freeN(ob->mat); } - if (ob->mat) MEM_freeN(ob->mat); if (ob->matbits) MEM_freeN(ob->matbits); ob->mat = NULL; ob->matbits = NULL; @@ -1757,8 +1767,8 @@ static void give_parvert(Object *par, int nr, float vec[3]) { BMEditMesh *em; int a, count; - - vec[0] = vec[1] = vec[2] = 0.0f; + + zero_v3(vec); if (par->type == OB_MESH) { Mesh *me = par->data; @@ -1850,7 +1860,7 @@ static void give_parvert(Object *par, int nr, float vec[3]) while (a--) { if (count == nr) { found = 1; - memcpy(vec, bp->vec, sizeof(float) * 3); + copy_v3_v3(vec, bp->vec); break; } count++; @@ -1875,9 +1885,9 @@ static void give_parvert(Object *par, int nr, float vec[3]) while (a--) { if (count == nr) { if (co) - memcpy(vec, co, 3 * sizeof(float)); + copy_v3_v3(vec, co); else - memcpy(vec, bp->vec, 3 * sizeof(float)); + copy_v3_v3(vec, bp->vec); break; } count++; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index bae8efa758e..2c0452bc2d1 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -3776,7 +3776,7 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra)) * simulation. This should be called once per particle during a simulation * step, after the velocity has been updated. element_size defines the scale of * the simulation, and is typically the distance to neighbourning particles. */ -void update_courant_num(ParticleSimulationData *sim, ParticleData *pa, +static void update_courant_num(ParticleSimulationData *sim, ParticleData *pa, float dtime, SPHData *sphdata) { float relative_vel[3]; @@ -3788,8 +3788,7 @@ void update_courant_num(ParticleSimulationData *sim, ParticleData *pa, sim->courant_num = speed * dtime / sphdata->element_size; } /* Update time step size to suit current conditions. */ -float update_timestep(ParticleSystem *psys, ParticleSimulationData *sim, - float t_frac) +static float update_timestep(ParticleSystem *psys, ParticleSimulationData *sim, float t_frac) { if (sim->courant_num == 0.0f) psys->dt_frac = 1.0f; diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c index 1fa009d22a0..b0dcad64722 100644 --- a/source/blender/blenkernel/intern/seqmodifier.c +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -140,7 +140,7 @@ static void modifier_apply_threaded(ImBuf *ibuf, ImBuf *mask, modifier_apply_thr /* **** Color Balance Modifier **** */ -void colorBalance_init_data(SequenceModifierData *smd) +static void colorBalance_init_data(SequenceModifierData *smd) { ColorBalanceModifierData *cbmd = (ColorBalanceModifierData *) smd; int c; @@ -154,7 +154,7 @@ void colorBalance_init_data(SequenceModifierData *smd) } } -void colorBalance_apply(SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) +static void colorBalance_apply(SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) { ColorBalanceModifierData *cbmd = (ColorBalanceModifierData *) smd; @@ -173,21 +173,21 @@ static SequenceModifierTypeInfo seqModifier_ColorBalance = { /* **** Curves Modifier **** */ -void curves_init_data(SequenceModifierData *smd) +static void curves_init_data(SequenceModifierData *smd) { CurvesModifierData *cmd = (CurvesModifierData *) smd; curvemapping_set_defaults(&cmd->curve_mapping, 4, 0.0f, 0.0f, 1.0f, 1.0f); } -void curves_free_data(SequenceModifierData *smd) +static void curves_free_data(SequenceModifierData *smd) { CurvesModifierData *cmd = (CurvesModifierData *) smd; curvemapping_free_data(&cmd->curve_mapping); } -void curves_copy_data(SequenceModifierData *target, SequenceModifierData *smd) +static void curves_copy_data(SequenceModifierData *target, SequenceModifierData *smd) { CurvesModifierData *cmd = (CurvesModifierData *) smd; CurvesModifierData *cmd_target = (CurvesModifierData *) target; @@ -195,8 +195,8 @@ void curves_copy_data(SequenceModifierData *target, SequenceModifierData *smd) curvemapping_copy_data(&cmd_target->curve_mapping, &cmd->curve_mapping); } -void curves_apply_threaded(int width, int height, unsigned char *rect, float *rect_float, - unsigned char *mask_rect, float *mask_rect_float, void *data_v) +static void curves_apply_threaded(int width, int height, unsigned char *rect, float *rect_float, + unsigned char *mask_rect, float *mask_rect_float, void *data_v) { CurveMapping *curve_mapping = (CurveMapping *) data_v; int x, y; @@ -249,7 +249,7 @@ void curves_apply_threaded(int width, int height, unsigned char *rect, float *re } } -void curves_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) +static void curves_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) { CurvesModifierData *cmd = (CurvesModifierData *) smd; @@ -278,7 +278,7 @@ static SequenceModifierTypeInfo seqModifier_Curves = { /* **** Hue Correct Modifier **** */ -void hue_correct_init_data(SequenceModifierData *smd) +static void hue_correct_init_data(SequenceModifierData *smd) { HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd; int c; @@ -296,14 +296,14 @@ void hue_correct_init_data(SequenceModifierData *smd) hcmd->curve_mapping.cur = 1; } -void hue_correct_free_data(SequenceModifierData *smd) +static void hue_correct_free_data(SequenceModifierData *smd) { HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd; curvemapping_free_data(&hcmd->curve_mapping); } -void hue_correct_copy_data(SequenceModifierData *target, SequenceModifierData *smd) +static void hue_correct_copy_data(SequenceModifierData *target, SequenceModifierData *smd) { HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd; HueCorrectModifierData *hcmd_target = (HueCorrectModifierData *) target; @@ -311,7 +311,7 @@ void hue_correct_copy_data(SequenceModifierData *target, SequenceModifierData *s curvemapping_copy_data(&hcmd_target->curve_mapping, &hcmd->curve_mapping); } -void hue_correct_apply_threaded(int width, int height, unsigned char *rect, float *rect_float, +static void hue_correct_apply_threaded(int width, int height, unsigned char *rect, float *rect_float, unsigned char *mask_rect, float *mask_rect_float, void *data_v) { CurveMapping *curve_mapping = (CurveMapping *) data_v; @@ -365,7 +365,7 @@ void hue_correct_apply_threaded(int width, int height, unsigned char *rect, floa } } -void hue_correct_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) +static void hue_correct_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) { HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd; @@ -391,8 +391,8 @@ typedef struct BrightContrastThreadData { float contrast; } BrightContrastThreadData; -void brightcontrast_apply_threaded(int width, int height, unsigned char *rect, float *rect_float, - unsigned char *mask_rect, float *mask_rect_float, void *data_v) +static void brightcontrast_apply_threaded(int width, int height, unsigned char *rect, float *rect_float, + unsigned char *mask_rect, float *mask_rect_float, void *data_v) { BrightContrastThreadData *data = (BrightContrastThreadData *) data_v; int x, y; @@ -460,7 +460,7 @@ void brightcontrast_apply_threaded(int width, int height, unsigned char *rect, f } } -void brightcontrast_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) +static void brightcontrast_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask) { BrightContrastModifierData *bcmd = (BrightContrastModifierData *) smd; BrightContrastThreadData data; diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index ddcba509301..5e67e094e43 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -80,10 +80,10 @@ /* UNUSED so far, may be enabled later */ /* #define USE_SMOKE_COLLISION_DM */ -#ifdef WITH_SMOKE - #include "smoke_API.h" +#ifdef WITH_SMOKE + #ifdef _WIN32 #include #include @@ -148,7 +148,7 @@ static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs) /* Stubs to use when smoke is disabled */ struct WTURBULENCE *smoke_turbulence_init(int *UNUSED(res), int UNUSED(amplify), int UNUSED(noisetype)) { return NULL; } -struct FLUID_3D *smoke_init(int *UNUSED(res), float *UNUSED(p0)) { return NULL; } +// struct FLUID_3D *smoke_init(int *UNUSED(res), float *UNUSED(p0)) { return NULL; } void smoke_free(struct FLUID_3D *UNUSED(fluid)) {} float *smoke_get_density(struct FLUID_3D *UNUSED(fluid)) { return NULL; } void smoke_turbulence_free(struct WTURBULENCE *UNUSED(wt)) {} diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 787def5c20b..af5a8f5d59d 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -3031,30 +3031,6 @@ void txt_uncomment(Text *text) } } - -void txt_move_lines_up(struct Text *text) -{ - TextLine *prev_line; - - if (!text || !text->curl || !text->sell) return; - - txt_order_cursors(text); - - prev_line = text->curl->prev; - - if (!prev_line) return; - - BLI_remlink(&text->lines, prev_line); - BLI_insertlinkafter(&text->lines, text->sell, prev_line); - - txt_make_dirty(text); - txt_clean_text(text); - - if (!undoing) { - txt_undo_add_op(text, UNDO_MOVE_LINES_UP); - } -} - void txt_move_lines(struct Text *text, const int direction) { TextLine *line_other; diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index ee904de4af6..bdd9b424f3b 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -338,7 +338,7 @@ void colorband_table_RGBA(ColorBand *coba, float **array, int *size) do_colorband(coba, (float)a / (float)CM_TABLE, &(*array)[a * 4]); } -int vergcband(const void *a1, const void *a2) +static int vergcband(const void *a1, const void *a2) { const CBData *x1 = a1, *x2 = a2; diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index c0c5c579133..97ebc3a90ba 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -2223,8 +2223,8 @@ static ImBuf *tracking_context_get_frame_ibuf(MovieTrackingContext *context, int return ibuf; } -MovieTrackingMarker *tracking_context_get_keyframed_marker(MovieTrackingContext *context, MovieTrackingTrack *track, - MovieTrackingMarker *marker) +static MovieTrackingMarker *tracking_context_get_keyframed_marker(MovieTrackingContext *context, MovieTrackingTrack *track, + MovieTrackingMarker *marker) { int a = marker - track->markers; MovieTrackingMarker *marker_keyed = marker; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index bd25ff8c6e6..4019eba5177 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -847,7 +847,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report * parameter. *

    */ -void flush_ffmpeg(void) +static void flush_ffmpeg(void) { int outsize = 0; int ret = 0; diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 7520f09fe95..6fe5d48d06e 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -67,6 +67,8 @@ void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv); void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, int colorspace); void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv); void rgb_to_hsv_v(const float rgb[3], float r_hsv[3]); +void rgb_to_hsl(float r, float g, float b, float *lh, float *ls, float *ll); +void rgb_to_hsl_v(const float rgb[3], float r_hsl[3]); void rgb_to_hsv_compat(float r, float g, float b, float *lh, float *ls, float *lv); void rgb_to_hsv_compat_v(const float rgb[3], float r_hsv[3]); void rgb_to_lab(float r, float g, float b, float *ll, float *la, float *lb); diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index b93597bf107..64851dbf12c 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -293,6 +293,12 @@ void rgb_to_hsl(float r, float g, float b, float *lh, float *ls, float *ll) *ll = l; } +/* convenience function for now */ +void rgb_to_hsl_v(const float rgb[3], float r_hsl[3]) +{ + rgb_to_hsl(rgb[0], rgb[1], rgb[2], &r_hsl[0], &r_hsl[1], &r_hsl[2]); +} + void rgb_to_hsv_compat(float r, float g, float b, float *lh, float *ls, float *lv) { float orig_h = *lh; diff --git a/source/blender/blenlib/intern/md5.c b/source/blender/blenlib/intern/md5.c index a521d0e523b..4a09afe2e3d 100644 --- a/source/blender/blenlib/intern/md5.c +++ b/source/blender/blenlib/intern/md5.c @@ -2,6 +2,8 @@ * \ingroup imbuf */ +#include "BLI_md5.h" /* own include */ + /* md5.c - Functions to compute MD5 message digest of files or memory blocks according to the definition of MD5 in RFC 1321 from April 1992. Copyright (C) 1995 Software Foundation, Inc. diff --git a/source/blender/blenlib/intern/pbvh.c b/source/blender/blenlib/intern/pbvh.c index 22597c9f8e6..d3d8d371f60 100644 --- a/source/blender/blenlib/intern/pbvh.c +++ b/source/blender/blenlib/intern/pbvh.c @@ -487,7 +487,7 @@ static void build_leaf(PBVH *bvh, int node_index, BBC *prim_bbc, /* Return zero if all primitives in the node can be drawn with the * same material (including flat/smooth shading), non-zerootherwise */ -int leaf_needs_material_split(PBVH *bvh, int offset, int count) +static int leaf_needs_material_split(PBVH *bvh, int offset, int count) { int i, prim; diff --git a/source/blender/blenlib/intern/voronoi.c b/source/blender/blenlib/intern/voronoi.c index 80a4da5cace..3030e54eb78 100644 --- a/source/blender/blenlib/intern/voronoi.c +++ b/source/blender/blenlib/intern/voronoi.c @@ -480,7 +480,7 @@ static void voronoi_removeParabola(VoronoiProcess *process, VoronoiEvent *event) voronoi_checkCircle(process, p2); } -void voronoi_finishEdge(VoronoiProcess *process, VoronoiParabola *parabola) +static void voronoi_finishEdge(VoronoiProcess *process, VoronoiParabola *parabola) { float mx; @@ -503,12 +503,12 @@ void voronoi_finishEdge(VoronoiProcess *process, VoronoiParabola *parabola) MEM_freeN(parabola); } -void voronoi_clampEdgeVertex(int width, int height, float *coord, float *other_coord) +static void voronoi_clampEdgeVertex(int width, int height, float *coord, float *other_coord) { const float corners[4][2] = {{0.0f, 0.0f}, - {width - 1, 0.0f}, - {width - 1, height - 1}, - {0.0f, height - 1}}; + {width - 1, 0.0f}, + {width - 1, height - 1}, + {0.0f, height - 1}}; int i; if (IN_RANGE_INCL(coord[0], 0, width - 1) && IN_RANGE_INCL(coord[1], 0, height - 1)) { @@ -541,7 +541,7 @@ void voronoi_clampEdgeVertex(int width, int height, float *coord, float *other_c } } -void voronoi_clampEdges(ListBase *edges, int width, int height, ListBase *clamped_edges) +static void voronoi_clampEdges(ListBase *edges, int width, int height, ListBase *clamped_edges) { VoronoiEdge *edge; diff --git a/source/blender/blenlib/intern/winstuff.c b/source/blender/blenlib/intern/winstuff.c index 5b5f4cf8b80..a0b31f8d5b8 100644 --- a/source/blender/blenlib/intern/winstuff.c +++ b/source/blender/blenlib/intern/winstuff.c @@ -68,7 +68,7 @@ int BLI_getInstallationDir(char *str) return 1; } -void RegisterBlendExtension_Fail(HKEY root) +static void RegisterBlendExtension_Fail(HKEY root) { printf("failed\n"); if (root) diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index f0bf7e99758..16a4d8d46ec 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -244,6 +244,9 @@ void *BLO_library_read_struct(struct FileData *fd, struct BHead *bh, const char BlendFileData *blo_read_blendafterruntime(int file, const char *name, int actualsize, struct ReportList *reports); +/* internal function but we need to expose it */ +void blo_lib_link_screen_restore(struct Main *newmain, struct bScreen *curscreen, struct Scene *curscene); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index dd945dd4cc0..2932fb63f43 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -589,11 +589,7 @@ static void switch_endian_bh8(BHead8 *bhead) static void bh4_from_bh8(BHead *bhead, BHead8 *bhead8, int do_endian_swap) { BHead4 *bhead4 = (BHead4 *) bhead; -#if defined(WIN32) && !defined(FREE_WINDOWS) - __int64 old; -#else - long long old; -#endif + int64_t old; bhead4->code = bhead8->code; bhead4->len = bhead8->len; @@ -5455,7 +5451,7 @@ static void lib_link_clipboard_restore(Main *newmain) /* called from kernel/blender.c */ /* used to link a file (without UI) to the current UI */ /* note that it assumes the old pointers in UI are still valid, so old Main is not freed */ -void lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *curscene) +void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *curscene) { wmWindow *win; wmWindowManager *wm; @@ -6700,7 +6696,7 @@ static void do_versions_nodetree_convert_angle(bNodeTree *ntree) } } -void do_versions_image_settings_2_60(Scene *sce) +static void do_versions_image_settings_2_60(Scene *sce) { /* note: rd->subimtype is moved into individual settings now and no longer * exists */ diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index b10556af04e..84f6cb27b3b 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -484,7 +484,7 @@ void dummy_exec(BMesh *bm, BMOperator *op) /* multiply vertex edge angle by face angle * this means we are not left with sharp corners between _almost_ planer faces * convert angles [0-PI/2] -> [0-1], multiply together, then convert back to radians. */ -float bm_vert_edge_face_angle(BMVert *v) +static float bm_vert_edge_face_angle(BMVert *v) { const float angle = BM_vert_calc_edge_angle(v); /* note: could be either edge, it doesn't matter */ diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c index 87ba216d5cf..d97d901777c 100644 --- a/source/blender/bmesh/operators/bmo_hull.c +++ b/source/blender/bmesh/operators/bmo_hull.c @@ -44,6 +44,8 @@ #include "bmesh.h" +#include "intern/bmesh_operators_private.h" /* own include */ + #define HULL_EPSILON_FLT 0.0001f /* values above 0.0001 cause errors, see below for details, don't increase * without checking against bug [#32027] */ @@ -628,7 +630,7 @@ static void hull_tag_unused(BMesh *bm, BMOperator *op) } } -void hull_tag_holes(BMesh *bm, BMOperator *op) +static void hull_tag_holes(BMesh *bm, BMOperator *op) { BMIter iter; BMOIter oiter; diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index e1a5ef9f905..0caa766c0f0 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -487,7 +487,7 @@ void bmo_collapse_uvs_exec(BMesh *bm, BMOperator *op) } } -void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, BMOperator *optarget, const char *targetmapname) +static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, BMOperator *optarget, const char *targetmapname) { BMOIter oiter; BMVert *v, *v2; diff --git a/source/blender/bmesh/operators/bmo_wireframe.c b/source/blender/bmesh/operators/bmo_wireframe.c index e0dc5cf48c7..d572a1c5863 100644 --- a/source/blender/bmesh/operators/bmo_wireframe.c +++ b/source/blender/bmesh/operators/bmo_wireframe.c @@ -34,7 +34,7 @@ #include "intern/bmesh_operators_private.h" /* own include */ -BMLoop *bm_edge_tag_faceloop(BMEdge *e) +static BMLoop *bm_edge_tag_faceloop(BMEdge *e) { BMLoop *l, *l_first; diff --git a/source/blender/bmesh/tools/BME_bevel.c b/source/blender/bmesh/tools/BME_bevel.c index 91527313972..98f270abd16 100644 --- a/source/blender/bmesh/tools/BME_bevel.c +++ b/source/blender/bmesh/tools/BME_bevel.c @@ -66,7 +66,7 @@ /* ------- Bevel code starts here -------- */ -BME_TransData_Head *BME_init_transdata(int bufsize) +static BME_TransData_Head *BME_init_transdata(int bufsize) { BME_TransData_Head *td; @@ -85,9 +85,9 @@ void BME_free_transdata(BME_TransData_Head *td) MEM_freeN(td); } -BME_TransData *BME_assign_transdata(BME_TransData_Head *td, BMesh *bm, BMVert *v, - float *co, float *org, float *vec, float *loc, - float factor, float weight, float maxfactor, float *max) +static BME_TransData *BME_assign_transdata(BME_TransData_Head *td, BMesh *bm, BMVert *v, + float *co, float *org, float *vec, float *loc, + float factor, float weight, float maxfactor, float *max) { BME_TransData *vtd; int is_new = 0; @@ -140,7 +140,7 @@ BME_TransData *BME_get_transdata(BME_TransData_Head *td, BMVert *v) } /* a hack (?) to use the transdata memarena to allocate floats for use with the max limits */ -float *BME_new_transdata_float(BME_TransData_Head *td) +static float *BME_new_transdata_float(BME_TransData_Head *td) { return BLI_memarena_alloc(td->ma, sizeof(float)); } diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp index 41d3c790dd0..f1f1efdbd33 100644 --- a/source/blender/collada/ImageExporter.cpp +++ b/source/blender/collada/ImageExporter.cpp @@ -74,6 +74,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) short image_source = image->source; bool is_generated = image_source == IMA_SRC_GENERATED; + bool is_packed = image->packedfile != NULL; char export_path[FILE_MAX]; char source_path[FILE_MAX]; @@ -83,7 +84,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) // Destination folder for exported assets BLI_split_dir_part(this->export_settings->filepath, export_dir, sizeof(export_dir)); - if (is_generated || is_dirty || use_copies) { + if (is_generated || is_dirty || use_copies || is_packed) { // make absolute destination path @@ -96,7 +97,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) BLI_make_existing_file(export_path); } - if (is_generated || is_dirty) { + if (is_generated || is_dirty || is_packed) { // This image in its current state only exists in Blender memory. // So we have to export it. The export will keep the image state intact, diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 8cd8cfaea51..5e0459bea90 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -1086,7 +1086,7 @@ short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char grou * The flag argument is used for special settings that alter the behavior of * the keyframe deletion. These include the quick refresh options. */ -short clear_keyframe(ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, short UNUSED(flag)) +static short clear_keyframe(ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, short UNUSED(flag)) { AnimData *adt = BKE_animdata_from_id(id); PointerRNA id_ptr, ptr; diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index e9424a08b0c..b1a613bef5d 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -74,6 +74,7 @@ #include "ED_mesh.h" #include "ED_screen.h" #include "ED_object.h" +#include "ED_util.h" /* clipboard */ #include "UI_interface.h" #include "UI_resources.h" @@ -1049,7 +1050,7 @@ static void pose_copy_menu(Scene *scene) /* Global copy/paste buffer for pose - cleared on start/end session + before every copy operation */ static bPose *g_posebuf = NULL; -void free_posebuf(void) +void ED_clipboard_posebuf_free(void) { if (g_posebuf) { bPoseChannel *pchan; @@ -1225,7 +1226,7 @@ static int pose_copy_exec(bContext *C, wmOperator *op) } /* free existing pose buffer */ - free_posebuf(); + ED_clipboard_posebuf_free(); /* sets chan->flag to POSE_KEY if bone selected, then copy those bones to the buffer */ set_pose_keys(ob); diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index 8ebf932fd96..dc40b687dfd 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -53,14 +53,14 @@ void ED_keymap_mask(struct wmKeyConfig *keyconf); void ED_operatormacros_mask(void); /* mask_draw.c */ -void ED_mask_draw(const bContext *C, const char draw_flag, const char draw_type); +void ED_mask_draw(const struct bContext *C, const char draw_flag, const char draw_type); void ED_mask_draw_region(struct Mask *mask, struct ARegion *ar, const char draw_flag, const char draw_type, const int width_i, const int height_i, const float aspx, const float aspy, const short do_scale_applied, const short do_post_draw, float stabmat[4][4], - const bContext *C); + const struct bContext *C); void ED_mask_draw_frames(struct Mask *mask, struct ARegion *ar, const int cfra, const int sfra, const int efra); diff --git a/source/blender/editors/include/ED_sequencer.h b/source/blender/editors/include/ED_sequencer.h index 7807f06594e..84fd5332316 100644 --- a/source/blender/editors/include/ED_sequencer.h +++ b/source/blender/editors/include/ED_sequencer.h @@ -36,7 +36,7 @@ void ED_sequencer_deselect_all(struct Scene *scene); int ED_space_sequencer_maskedit_mask_poll(struct bContext *C); int ED_space_sequencer_check_show_maskedit(struct SpaceSeq *sseq, struct Scene *scene); -int ED_space_sequencer_maskedit_poll(bContext *C); +int ED_space_sequencer_maskedit_poll(struct bContext *C); void ED_operatormacros_sequencer(void); diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h index e10f049d0bc..d0ca079b8c9 100644 --- a/source/blender/editors/include/ED_util.h +++ b/source/blender/editors/include/ED_util.h @@ -84,6 +84,8 @@ void crazyspace_set_quats_mesh(struct Mesh *me, float *origcos, float *mappedcos int sculpt_get_first_deform_matrices(struct Scene *scene, struct Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]); void crazyspace_build_sculpt(struct Scene *scene, struct Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]); +/* cut-paste buffer free */ +void ED_clipboard_posebuf_free(void); /* ************** XXX OLD CRUFT WARNING ************* */ diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 72779234bae..ded5887f7f2 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -912,7 +912,7 @@ static void UI_OT_editsource(wmOperatorType *ot) * Note: this includes utility functions and button matching checks. * this only works in conjunction with a py operator! */ -void edittranslation_find_po_file(const char *root, const char *uilng, char *path, const size_t maxlen) +static void edittranslation_find_po_file(const char *root, const char *uilng, char *path, const size_t maxlen) { char tstr[32]; /* Should be more than enough! */ /* First, full lang code. */ diff --git a/source/blender/editors/io/io_ops.c b/source/blender/editors/io/io_ops.c index d2b0ddd4e7e..f2a0532932d 100644 --- a/source/blender/editors/io/io_ops.c +++ b/source/blender/editors/io/io_ops.c @@ -34,6 +34,8 @@ #include "WM_types.h" #include "WM_api.h" +#include "io_ops.h" /* own include */ + void ED_operatortypes_io(void) { #ifdef WITH_COLLADA diff --git a/source/blender/editors/mask/mask_editaction.c b/source/blender/editors/mask/mask_editaction.c index 6124947e3b9..561ad004a1d 100644 --- a/source/blender/editors/mask/mask_editaction.c +++ b/source/blender/editors/mask/mask_editaction.c @@ -48,6 +48,7 @@ #include "ED_anim_api.h" #include "ED_keyframes_edit.h" +#include "ED_mask.h" /* own include */ /* ***************************************** */ /* NOTE ABOUT THIS FILE: diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index d90735ca5ac..d73bbbabf84 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -198,7 +198,7 @@ float ED_object_new_primitive_matrix(bContext *C, Object *obedit, /********************* Add Object Operator ********************/ -void view_align_update(struct Main *UNUSED(main), struct Scene *UNUSED(scene), struct PointerRNA *ptr) +static void view_align_update(struct Main *UNUSED(main), struct Scene *UNUSED(scene), struct PointerRNA *ptr) { RNA_struct_idprops_unset(ptr, "rotation"); } diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index f95b07bd71e..099d868a0ad 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -782,7 +782,7 @@ static void fluidbake_endjob(void *customdata) } } -int runSimulationCallback(void *data, int status, int frame) +static int runSimulationCallback(void *data, int status, int frame) { FluidBakeJob *fb = (FluidBakeJob *)data; elbeemSimulationSettings *settings = fb->settings; @@ -1095,7 +1095,7 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor return 1; } -void fluidsimFreeBake(Object *UNUSED(ob)) +static void UNUSED_FUNCTION(fluidsimFreeBake)(Object *UNUSED(ob)) { /* not implemented yet */ } diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 6f51c5a98e6..64430a263f0 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -5258,7 +5258,7 @@ void PAINT_OT_image_paint(wmOperatorType *ot) RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); } -int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy) +static int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy) { RegionView3D *rv3d = CTX_wm_region_view3d(C); diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index cc71be4938e..39a95300d5d 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -602,7 +602,7 @@ static void ed_keymap_paint_brush_radial_control(wmKeyMap *keymap, const char *p } } -void paint_partial_visibility_keys(wmKeyMap *keymap) +static void paint_partial_visibility_keys(wmKeyMap *keymap) { wmKeyMapItem *kmi; diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index b53edeadb51..7657f78596a 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -254,7 +254,10 @@ static int paint_space_stroke(bContext *C, wmOperator *op, wmEvent *event, const pressure = event_tablet_data(event, NULL); if (pressure > FLT_EPSILON) { - scale = (BKE_brush_size_get(scene, stroke->brush) * pressure * stroke->brush->spacing / 50.0f) / length; + /* brushes can have a minimum size of 1.0 but with pressure it can be smaller then a pixel + * causing very high step sizes, hanging blender [#32381] */ + const float size_clamp = maxf(1.0f, BKE_brush_size_get(scene, stroke->brush) * pressure); + scale = (size_clamp * stroke->brush->spacing / 50.0f) / length; if (scale > FLT_EPSILON) { mul_v2_fl(vec, scale); diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index ba440e98290..fd5044afc44 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -257,7 +257,7 @@ static void do_shared_vertex_tesscol(Mesh *me) MEM_freeN(scolmain); } -void do_shared_vertexcol(Mesh *me, int do_tessface) +static void do_shared_vertexcol(Mesh *me, int do_tessface) { const int use_face_sel = (me->editflag & ME_EDIT_PAINT_MASK); MPoly *mp; diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c index fdce8ec04a4..0bcccd9479c 100644 --- a/source/blender/editors/sculpt_paint/sculpt_uv.c +++ b/source/blender/editors/sculpt_paint/sculpt_uv.c @@ -156,8 +156,8 @@ typedef struct Temp_UvData { -void HC_relaxation_iteration_uv(BMEditMesh *em, UvSculptData *sculptdata, float mouse_coord[2], - float alpha, float radius, float aspectRatio) +static void HC_relaxation_iteration_uv(BMEditMesh *em, UvSculptData *sculptdata, float mouse_coord[2], + float alpha, float radius, float aspectRatio) { Temp_UVData *tmp_uvdata; float diff[2]; diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c index 91501971d9d..7b070fde6ba 100644 --- a/source/blender/editors/space_clip/clip_graph_draw.c +++ b/source/blender/editors/space_clip/clip_graph_draw.c @@ -94,7 +94,7 @@ static void tracking_segment_point_cb(void *UNUSED(userdata), MovieTrackingTrack glVertex2f(scene_framenr, val); } -void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord) +static void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord) { static float colors[2][3] = {{1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}}; @@ -116,7 +116,7 @@ void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track, int co glBegin(GL_LINE_STRIP); } -void tracking_segment_end_cb(void *UNUSED(userdata)) +static void tracking_segment_end_cb(void *UNUSED(userdata)) { glEnd(); diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c index 71dcd326887..f48d4e8d946 100644 --- a/source/blender/editors/space_clip/clip_graph_ops.c +++ b/source/blender/editors/space_clip/clip_graph_ops.c @@ -130,7 +130,7 @@ static void find_nearest_tracking_segment_cb(void *userdata, MovieTrackingTrack copy_v2_v2(data->prev_co, co); } -void find_nearest_tracking_segment_end_cb(void *userdata) +static void find_nearest_tracking_segment_end_cb(void *userdata) { MouseSelectUserData *data = userdata; diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 616587b0b19..16804c5a1c6 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -192,7 +192,7 @@ int space_image_main_area_poll(bContext *C) } /* For IMAGE_OT_curves_point_set to avoid sampling when in uv smooth mode or editmode */ -int space_image_main_area_not_uv_brush_poll(bContext *C) +static int space_image_main_area_not_uv_brush_poll(bContext *C) { SpaceImage *sima = CTX_wm_space_image(C); Scene *scene = CTX_data_scene(C); diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 775dd5445c3..2861d17b350 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -1170,7 +1170,7 @@ static int nlaedit_bake_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -void NLA_OT_bake(wmOperatorType *ot) +static void NLA_OT_bake(wmOperatorType *ot) { /* identifiers */ ot->name = "Bake Strips"; diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 4fae060deb9..1f266c98020 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -893,7 +893,7 @@ static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bN } } -void node_uifunc_group(uiLayout *layout, bContext *C, PointerRNA *ptr) +static void node_uifunc_group(uiLayout *layout, bContext *C, PointerRNA *ptr) { uiTemplateIDBrowse(layout, C, ptr, "node_tree", NULL, NULL, NULL); } @@ -2388,7 +2388,7 @@ static void node_composit_buts_bokehblur(uiLayout *layout, bContext *UNUSED(C), uiItemR(layout, ptr, "blur_max", 0, NULL, ICON_NONE); } -void node_composit_backdrop_viewer(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y) +static void node_composit_backdrop_viewer(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y) { // node_composit_backdrop_canvas(snode, backdrop, node, x, y); if (node->custom1 == 0) { @@ -2408,7 +2408,7 @@ void node_composit_backdrop_viewer(SpaceNode *snode, ImBuf *backdrop, bNode *nod } } -void node_composit_backdrop_boxmask(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y) +static void node_composit_backdrop_boxmask(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y) { NodeBoxMask *boxmask = node->storage; const float backdropWidth = backdrop->x; @@ -2449,7 +2449,7 @@ void node_composit_backdrop_boxmask(SpaceNode *snode, ImBuf *backdrop, bNode *no glEnd(); } -void node_composit_backdrop_ellipsemask(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y) +static void node_composit_backdrop_ellipsemask(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y) { NodeEllipseMask *ellipsemask = node->storage; const float backdropWidth = backdrop->x; diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 1522528a8ac..0601d7c105f 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -44,6 +44,7 @@ #include "BKE_screen.h" #include "BKE_node.h" +#include "ED_space_api.h" #include "ED_render.h" #include "ED_screen.h" #include "ED_node.h" diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c index aa6bacf8836..dc5cf98f515 100644 --- a/source/blender/editors/space_sequencer/sequencer_ops.c +++ b/source/blender/editors/space_sequencer/sequencer_ops.c @@ -43,6 +43,7 @@ #include "WM_api.h" #include "WM_types.h" +#include "ED_sequencer.h" #include "ED_markers.h" #include "ED_transform.h" /* transform keymap */ diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index c357a05936a..3c3489115a4 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -211,7 +211,7 @@ static int sample_cancel(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -int sample_poll(bContext *C) +static int sample_poll(bContext *C) { return BKE_sequencer_editing_get(CTX_data_scene(C), FALSE) != NULL; } diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index 2e542737494..e7014bf41d5 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -179,7 +179,7 @@ static DMDrawOption draw_mesh_face_select__drawFaceOptsInv(void *userData, int i return DM_DRAW_OPTION_SKIP; } -void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm) +static void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm) { drawMeshFaceSelect_userData data; @@ -780,8 +780,8 @@ static int compareDrawOptionsEm(void *userData, int cur_index, int next_index) return 1; } -void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d, - Object *ob, DerivedMesh *dm, const int draw_flags) +static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d, + Object *ob, DerivedMesh *dm, const int draw_flags) { Mesh *me = ob->data; diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 5712144caf1..166a62562fd 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -646,7 +646,7 @@ static void do_lasso_select_meta(ViewContext *vc, int mcords[][2], short moves, } } -int do_paintvert_box_select(ViewContext *vc, rcti *rect, int select, int extend) +static int do_paintvert_box_select(ViewContext *vc, rcti *rect, int select, int extend) { Mesh *me; MVert *mvert; diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 5008c35e46a..06da1c8bfea 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -2836,7 +2836,7 @@ static int uv_lasso_select_exec(bContext *C, wmOperator *op) return OPERATOR_PASS_THROUGH; } -void UV_OT_select_lasso(wmOperatorType *ot) +static void UV_OT_select_lasso(wmOperatorType *ot) { ot->name = "Lasso Select UV"; ot->description = "Select UVs using lasso selection"; diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 5e38c31f4c7..9ce5d0e30da 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -109,7 +109,7 @@ typedef struct DitherContext { float f; } DitherContext; -DitherContext *create_dither_context(int w, float factor) +static DitherContext *create_dither_context(int w, float factor) { DitherContext *di; int i; diff --git a/source/blender/imbuf/intern/indexer_dv.c b/source/blender/imbuf/intern/indexer_dv.c index 6b960a18277..7a8f8fcc752 100644 --- a/source/blender/imbuf/intern/indexer_dv.c +++ b/source/blender/imbuf/intern/indexer_dv.c @@ -385,7 +385,7 @@ static void indexer_dv_delete(anim_index_builder *idx) MEM_freeN(This); } -void IMB_indexer_dv_new(anim_index_builder *idx) +static void UNUSED_FUNCTION(IMB_indexer_dv_new)(anim_index_builder *idx) { indexer_dv_context *rv = MEM_callocN( sizeof(indexer_dv_context), "index_dv builder context"); diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index 6d1e3c16631..833671e3f2f 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -225,7 +225,7 @@ static int isqtime(const char *name) static char ffmpeg_last_error[1024]; -void ffmpeg_log_callback(void *ptr, int level, const char *format, va_list arg) +static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_list arg) { if (ELEM(level, AV_LOG_FATAL, AV_LOG_ERROR)) { size_t n = BLI_vsnprintf(ffmpeg_last_error, sizeof(ffmpeg_last_error), format, arg); diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 22b1e33e2a6..25a2a61d8e3 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -185,7 +185,7 @@ static float get_ob2ob_distance(const Object *ob, const Object *obr) /** * Maps distances to weights, with an optional "smoothing" mapping. */ -void do_map(float *weights, const int nidx, const float min_d, const float max_d, short mode) +static void do_map(float *weights, const int nidx, const float min_d, const float max_d, short mode) { const float range_inv = 1.0f / (max_d - min_d); /* invert since multiplication is faster */ unsigned int i = nidx; diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c index fdbe82efeda..59a4d6818c8 100644 --- a/source/blender/nodes/intern/node_common.c +++ b/source/blender/nodes/intern/node_common.c @@ -349,7 +349,7 @@ void node_group_edit_clear(bNode *node) nodeGroupEditClear(inode); } -void node_group_link(bNodeTree *ntree, bNodeSocket *sock, int in_out) +static void UNUSED_FUNCTION(node_group_link)(bNodeTree *ntree, bNodeSocket *sock, int in_out) { node_group_expose_socket(ntree, sock, in_out); } diff --git a/source/blender/nodes/intern/node_util.h b/source/blender/nodes/intern/node_util.h index 9f9caef14e2..95104df5fed 100644 --- a/source/blender/nodes/intern/node_util.h +++ b/source/blender/nodes/intern/node_util.h @@ -67,7 +67,7 @@ ListBase node_internal_connect_default(struct bNodeTree *ntree, struct bNode *no #endif // this is needed for inlining behavior -#if defined _WIN32 +#if defined _MSC_VER # define DO_INLINE __inline #elif defined (__sun) || defined (__sun__) # define DO_INLINE diff --git a/source/blender/nodes/texture/node_texture_util.h b/source/blender/nodes/texture/node_texture_util.h index 7d8c4ce232c..e938e6fc419 100644 --- a/source/blender/nodes/texture/node_texture_util.h +++ b/source/blender/nodes/texture/node_texture_util.h @@ -61,6 +61,8 @@ #include "node_util.h" +#include "NOD_texture.h" + #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_rand.h" diff --git a/source/blender/python/bmesh/bmesh_py_ops.c b/source/blender/python/bmesh/bmesh_py_ops.c index c16b1fb901f..fb5b94249e6 100644 --- a/source/blender/python/bmesh/bmesh_py_ops.c +++ b/source/blender/python/bmesh/bmesh_py_ops.c @@ -42,6 +42,8 @@ #include "bmesh.h" +#include "bmesh_py_ops.h" /* own include */ + #include "bmesh_py_types.h" #include "bmesh_py_utils.h" /* own include */ @@ -69,7 +71,7 @@ typedef struct { const char *opname; } BPy_BMeshOpFunc; -PyObject *bpy_bmesh_op_CreatePyObject(const char *opname) +static PyObject *bpy_bmesh_op_CreatePyObject(const char *opname) { BPy_BMeshOpFunc *self = PyObject_New(BPy_BMeshOpFunc, &bmesh_op_Type); diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index 05583e133dc..604166eed3c 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -71,6 +71,7 @@ set(SRC bpy_app_handlers.h bpy_driver.h bpy_intern_string.h + bpy_library.h bpy_operator.h bpy_operator_wrap.h bpy_props.h diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index 0f0250fb8d5..f2222825c42 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -37,6 +37,7 @@ #include "bpy_rna.h" #include "bpy_app.h" #include "bpy_props.h" +#include "bpy_library.h" #include "bpy_operator.h" #include "BLI_path_util.h" @@ -238,7 +239,6 @@ static PyObject *bpy_import_test(const char *modname) void BPy_init_modules(void) { extern BPy_StructRNA *bpy_context_module; - extern int bpy_lib_init(PyObject *); PointerRNA ctx_ptr; PyObject *mod; @@ -273,7 +273,7 @@ void BPy_init_modules(void) PyModule_AddObject(mod, "StructMetaPropGroup", (PyObject *)&pyrna_struct_meta_idprop_Type); /* needs to be first so bpy_types can run */ - bpy_lib_init(mod); + BPY_library_module(mod); bpy_import_test("bpy_types"); PyModule_AddObject(mod, "data", BPY_rna_module()); /* imports bpy_types by running this */ diff --git a/source/blender/python/intern/bpy.h b/source/blender/python/intern/bpy.h index 2412d65aa21..fe877d161ff 100644 --- a/source/blender/python/intern/bpy.h +++ b/source/blender/python/intern/bpy.h @@ -23,10 +23,13 @@ * \ingroup pythonintern */ - +#ifndef __BPY_H__ + void BPy_init_modules(void); extern PyObject *bpy_package_py; /* bpy_interface_atexit.c */ void BPY_atexit_register(void); void BPY_atexit_unregister(void); + +#endif /* __BPY_H__ */ diff --git a/source/blender/python/intern/bpy_app_ffmpeg.c b/source/blender/python/intern/bpy_app_ffmpeg.c index 44bba4c098f..68fd9a99712 100644 --- a/source/blender/python/intern/bpy_app_ffmpeg.c +++ b/source/blender/python/intern/bpy_app_ffmpeg.c @@ -26,11 +26,8 @@ #include #include "BLI_utildefines.h" -#include "BLI_callbacks.h" -#include "RNA_types.h" -#include "RNA_access.h" -#include "bpy_rna.h" +#include "bpy_app_ffmpeg.h" #ifdef WITH_FFMPEG #include diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index bab5a83a6ed..4d7f2080bbc 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -37,6 +37,8 @@ #include "bpy_rna.h" #include "bpy_app_handlers.h" +#include "BPY_extern.h" + void bpy_app_generic_callback(struct Main *main, struct ID *id, void *arg); static PyTypeObject BlenderAppCbType; diff --git a/source/blender/python/intern/bpy_interface_atexit.c b/source/blender/python/intern/bpy_interface_atexit.c index db97d361c73..13d8cedf907 100644 --- a/source/blender/python/intern/bpy_interface_atexit.c +++ b/source/blender/python/intern/bpy_interface_atexit.c @@ -32,6 +32,7 @@ #include #include "bpy_util.h" +#include "bpy.h" /* own include */ #include "WM_api.h" diff --git a/source/blender/python/intern/bpy_library.c b/source/blender/python/intern/bpy_library.c index 40ec8136eb7..7571fe0f75e 100644 --- a/source/blender/python/intern/bpy_library.c +++ b/source/blender/python/intern/bpy_library.c @@ -55,6 +55,7 @@ #include "DNA_space_types.h" /* FILE_LINK, FILE_RELPATH */ #include "bpy_util.h" +#include "bpy_library.h" #ifdef USE_RNA_DATABLOCKS # include "bpy_rna.h" @@ -426,7 +427,7 @@ static PyObject *bpy_lib_dir(BPy_Library *self) } -int bpy_lib_init(PyObject *mod_par) +int BPY_library_module(PyObject *mod_par) { static PyMethodDef load_meth = {"load", (PyCFunction)bpy_lib_load, METH_STATIC | METH_VARARGS | METH_KEYWORDS, diff --git a/source/blender/python/intern/bpy_library.h b/source/blender/python/intern/bpy_library.h new file mode 100644 index 00000000000..1b68007b704 --- /dev/null +++ b/source/blender/python/intern/bpy_library.h @@ -0,0 +1,32 @@ +/* + * ***** 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. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/intern/bpy_library.h + * \ingroup pythonintern + */ + +#ifndef __BPY_LIBRARY_H__ +#define __BPY_LIBRARY_H__ + +int BPY_library_module(PyObject *); + +#endif /* __BPY_LIBRARY_H__ */ diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 4ae8e821298..8ec8c4c41ba 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -37,6 +37,8 @@ #include "RNA_types.h" +#include "BPY_extern.h" + #include "bpy_rna.h" #include "bpy_rna_anim.h" #include "bpy_props.h" @@ -45,7 +47,7 @@ #include "bpy_intern_string.h" #ifdef USE_PYRNA_INVALIDATE_WEAKREF -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif #include "BLI_dynstr.h" @@ -55,7 +57,7 @@ #include "BLI_utildefines.h" #ifdef USE_PYRNA_INVALIDATE_WEAKREF -#include "BLI_ghash.h" +# include "BLI_ghash.h" #endif #include "RNA_enum_types.h" @@ -78,7 +80,7 @@ #include "../generic/py_capi_utils.h" #ifdef WITH_INTERNATIONAL -#include "BLF_translation.h" +# include "BLF_translation.h" #endif #define USE_PEDANTIC_WRITE @@ -2150,10 +2152,10 @@ static PyObject *pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, cons * -1: exception set * 0: not found * 1: found */ -int pyrna_prop_collection_subscript_str_lib_pair_ptr(BPy_PropertyRNA *self, PyObject *key, - const char *err_prefix, const short err_not_found, - PointerRNA *r_ptr - ) +static int pyrna_prop_collection_subscript_str_lib_pair_ptr(BPy_PropertyRNA *self, PyObject *key, + const char *err_prefix, const short err_not_found, + PointerRNA *r_ptr + ) { char *keyname; @@ -5908,7 +5910,7 @@ PyTypeObject pyrna_prop_collection_iter_Type = { NULL }; -PyObject *pyrna_prop_collection_iter_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop) +static PyObject *pyrna_prop_collection_iter_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop) { BPy_PropertyCollectionIterRNA *self = PyObject_New(BPy_PropertyCollectionIterRNA, &pyrna_prop_collection_iter_Type); diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index 113367788b6..1fb4b116872 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -175,6 +175,10 @@ PyObject *BPY_rna_types(void); PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr); PyObject *pyrna_prop_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop); +/* extern'd by other modules which don't deal closely with RNA */ +PyObject *pyrna_id_CreatePyObject(struct ID *id); +int pyrna_id_FromPyObject(PyObject *obj, struct ID **id); + /* operators also need this to set args */ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const char *error_prefix); PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop); diff --git a/source/blender/python/intern/gpu.c b/source/blender/python/intern/gpu.c index 7e2da5b1818..69fe0c48a41 100644 --- a/source/blender/python/intern/gpu.c +++ b/source/blender/python/intern/gpu.c @@ -74,8 +74,7 @@ static struct PyModuleDef gpumodule = { NULL, NULL, NULL, NULL, NULL }; -PyMODINIT_FUNC -PyInit_gpu(void) +static PyObject *PyInit_gpu(void) { PyObject *m; diff --git a/source/blender/python/intern/stubs.c b/source/blender/python/intern/stubs.c index 50d2e88f210..e0508359e13 100644 --- a/source/blender/python/intern/stubs.c +++ b/source/blender/python/intern/stubs.c @@ -28,12 +28,15 @@ * \ingroup pythonintern */ +#include "BLI_utildefines.h" + +#include "BPY_extern.h" /* python, will come back */ //void BPY_script_exec(void) {} //void BPY_python_start(void) {} //void BPY_text_free_code(void) {} -void BPY_pyconstraint_exec(void) {} -void BPY_pyconstraint_target(void) {} -int BPY_is_pyconstraint(void) { return 0;} -void BPY_pyconstraint_update(void) {} +void BPY_pyconstraint_exec(struct bPythonConstraint *UNUSED(con), struct bConstraintOb *UNUSED(cob), struct ListBase *UNUSED(targets)) {} +void BPY_pyconstraint_target(struct bPythonConstraint *UNUSED(con), struct bConstraintTarget *UNUSED(ct)) {} +int BPY_is_pyconstraint(struct Text *UNUSED(text)) { return 0;} +void BPY_pyconstraint_update(struct Object *UNUSED(owner), struct bConstraint *UNUSED(con)) {} diff --git a/source/blender/render/intern/include/zbuf.h b/source/blender/render/intern/include/zbuf.h index e4ee19d8ed2..e873111e6bf 100644 --- a/source/blender/render/intern/include/zbuf.h +++ b/source/blender/render/intern/include/zbuf.h @@ -139,5 +139,10 @@ void zbufclipwire(struct ZSpan *zspan, int obi, int zvlnr, int ec, void zbuf_make_winmat(Render *re, float winmat[][4]); void zbuf_render_project(float winmat[][4], const float co[3], float ho[4]); +/* sould not really be exposed, bad! */ +void hoco_to_zco(ZSpan *zspan, float zco[3], const float hoco[4]); +void zspan_scanconvert_strand(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float, float) ); +void zbufsinglewire(ZSpan *zspan, int obi, int zvlnr, const float ho1[4], const float ho2[4]); + #endif diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 2d694a3e274..51e5b30a31c 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -117,6 +117,7 @@ #include "zbuf.h" #include "sunsky.h" +#include "RE_render_ext.h" /* 10 times larger than normal epsilon, test it on default nurbs sphere with ray_transp (for quad detection) */ /* or for checking vertex normal flips */ diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index f7e3a9ddc39..6d22d8991b4 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -83,6 +83,8 @@ #include "renderdatabase.h" /* needed for UV */ +#include "RE_render_ext.h" + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ /* only to be used here in this file, it's for speed */ @@ -1260,18 +1262,19 @@ int multitex_nodes(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, } /* this is called for surface shading */ -int multitex_mtex(ShadeInput *shi, MTex *mtex, float *texvec, float *dxt, float *dyt, TexResult *texres) +static int multitex_mtex(ShadeInput *shi, MTex *mtex, float *texvec, float *dxt, float *dyt, TexResult *texres) { - Tex *tex= mtex->tex; + Tex *tex = mtex->tex; if (tex->use_nodes && tex->nodetree) { /* stupid exception here .. but we have to pass shi and mtex to * textures nodes for 2d mapping and color management for images */ return ntreeTexExecTree(tex->nodetree, texres, texvec, dxt, dyt, shi->osatex, shi->thread, - tex, mtex->which_output, R.r.cfra, (R.r.scemode & R_TEXNODE_PREVIEW) != 0, shi, mtex); + tex, mtex->which_output, R.r.cfra, (R.r.scemode & R_TEXNODE_PREVIEW) != 0, shi, mtex); } - else + else { return multitex(mtex->tex, texvec, dxt, dyt, shi->osatex, texres, shi->thread, mtex->which_output); + } } /* Warning, if the texres's values are not declared zero, check the return value to be sure diff --git a/source/blender/render/intern/source/strand.c b/source/blender/render/intern/source/strand.c index 51be519d5b8..dc3225b7f09 100644 --- a/source/blender/render/intern/source/strand.c +++ b/source/blender/render/intern/source/strand.c @@ -61,11 +61,6 @@ #include "strand.h" #include "zbuf.h" -/* to be removed */ -void hoco_to_zco(ZSpan *zspan, float *zco, float *hoco); -void zspan_scanconvert_strand(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void (*func)(void *, int, int, float, float, float) ); -void zbufsinglewire(ZSpan *zspan, int obi, int zvlnr, float *ho1, float *ho2); - /* *************** */ static float strand_eval_width(Material *ma, float strandco) diff --git a/source/blender/render/intern/source/texture_ocean.c b/source/blender/render/intern/source/texture_ocean.c index 8c9df496dd6..b2bc635cba7 100644 --- a/source/blender/render/intern/source/texture_ocean.c +++ b/source/blender/render/intern/source/texture_ocean.c @@ -42,6 +42,8 @@ #include "texture.h" +#include "texture_ocean.h" /* own include */ + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index de9572bf57b..bf6962d0087 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -3476,7 +3476,7 @@ void zbuffer_abuf_shadow(Render *re, LampRen *lar, float winmat[][4], APixstr *A /* speed pointer NULL = sky, we clear */ /* else if either alpha is full or no solid was filled in: copy speed */ /* else fill in minimum speed */ -void add_transp_speed(RenderLayer *rl, int offset, float *speed, float alpha, intptr_t *rdrect) +static void add_transp_speed(RenderLayer *rl, int offset, float speed[4], float alpha, intptr_t *rdrect) { RenderPass *rpass; @@ -3525,7 +3525,7 @@ static void add_transp_obindex(RenderLayer *rl, int offset, Object *ob) /* ONLY OSA! merge all shaderesult samples to one */ /* target should have been cleared */ -void merge_transp_passes(RenderLayer *rl, ShadeResult *shr) +static void merge_transp_passes(RenderLayer *rl, ShadeResult *shr) { RenderPass *rpass; float weight= 1.0f/((float)R.osa); @@ -3627,7 +3627,7 @@ void merge_transp_passes(RenderLayer *rl, ShadeResult *shr) } -void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alpha) +static void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, float alpha) { RenderPass *rpass; diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index ff7c8cd2ea7..1d509a87ffe 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -361,6 +361,8 @@ void WM_progress_clear(struct wmWindow *win); /* Draw (for screenshot) */ void WM_redraw_windows(struct bContext *C); +void WM_main_playanim(int argc, const char **argv); + /* debugging only, convenience function to write on crash */ int write_crash_blend(void); diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index a1c46e4e6a2..908f7e27f0b 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -339,7 +339,6 @@ static void free_openrecent(void) extern void free_anim_copybuf(void); extern void free_anim_drivers_copybuf(void); extern void free_fmodifiers_copybuf(void); -extern void free_posebuf(void); #if WIN32 /* Read console events until there is a key event. Also returns on any error. */ @@ -424,7 +423,7 @@ void WM_exit_ext(bContext *C, const short do_python) free_anim_copybuf(); free_anim_drivers_copybuf(); free_fmodifiers_copybuf(); - free_posebuf(); + ED_clipboard_posebuf_free(); BKE_node_clipboard_clear(); BLF_exit(); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 1b76e71503c..313fc0a819e 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1693,7 +1693,7 @@ static void WM_OT_open_mainfile(wmOperatorType *ot) /* **************** link/append *************** */ -int wm_link_append_poll(bContext *C) +static int wm_link_append_poll(bContext *C) { if (WM_operator_winactive(C)) { /* linking changes active object which is pretty useful in general, diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index bbe5ddc72f2..bff40faf1d1 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -72,6 +72,8 @@ #include "wm_event_types.h" +#include "WM_api.h" /* only for WM_main_playanim */ + typedef struct PlayState { /* playback state */ @@ -142,7 +144,7 @@ static struct WindowStateGlobal { eWS_Qual qual; } g_WS = {NULL}; -void playanim_window_get_size(int *width_r, int *height_r) +static void playanim_window_get_size(int *width_r, int *height_r) { GHOST_RectangleHandle bounds = GHOST_GetClientBounds(g_WS.ghost_window); *width_r = GHOST_GetWidthRectangle(bounds); @@ -691,7 +693,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) return 1; } -void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey, int start_maximized) +static void playanim_window_open(const char *title, int posx, int posy, int sizex, int sizey, int start_maximized) { GHOST_TWindowState inital_state; GHOST_TUns32 scr_w, scr_h; @@ -722,7 +724,7 @@ void playanim_window_open(const char *title, int posx, int posy, int sizex, int } -void playanim(int argc, const char **argv) +void WM_main_playanim(int argc, const char **argv) { struct ImBuf *ibuf = NULL; char filepath[FILE_MAX]; diff --git a/source/creator/creator.c b/source/creator/creator.c index b3c11198403..ab9541cf299 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -91,7 +91,6 @@ #include "RE_engine.h" #include "RE_pipeline.h" -//XXX #include "playanim_ext.h" #include "ED_datafiles.h" #include "WM_api.h" @@ -454,11 +453,9 @@ static int set_env(int argc, const char **argv, void *UNUSED(data)) static int playback_mode(int argc, const char **argv, void *UNUSED(data)) { - extern void playanim(int argc, const char **argv); - /* not if -b was given first */ if (G.background == 0) { - playanim(argc, argv); /* not the same argc and argv as before */ + WM_main_playanim(argc, argv); /* not the same argc and argv as before */ exit(0); /* 2.4x didn't do this */ } From cdb144ade986ef97cc60801610e6e83bcbba60b1 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 15 Sep 2012 07:53:34 +0000 Subject: [PATCH 152/160] Merging r50618 through r50624 from trunk into soc-2011-tomato --- source/blender/avi/intern/avi.c | 21 +++++++++---------- source/blender/blenfont/intern/blf_font.c | 4 ++-- source/blender/blenfont/intern/blf_internal.h | 4 ++-- source/blender/blenfont/intern/blf_lang.c | 4 ++-- .../blender/blenkernel/intern/DerivedMesh.c | 2 +- source/blender/blenkernel/intern/object.c | 2 +- source/blender/blenkernel/intern/text.c | 1 - source/blender/blenloader/intern/readfile.c | 2 +- .../intern/COM_ExecutionSystemHelper.cpp | 10 +++------ .../operations/COM_MovieDistortionOperation.h | 4 ++-- .../blender/editors/armature/editarmature.c | 4 +++- .../blender/editors/armature/meshlaplacian.c | 2 +- source/blender/editors/armature/poseobject.c | 2 +- .../editors/interface/interface_regions.c | 11 ++-------- source/blender/editors/interface/view2d.c | 2 +- source/blender/editors/object/object_hook.c | 6 ++---- .../blender/editors/space_node/node_header.c | 2 +- .../editors/space_outliner/outliner_select.c | 9 +++++--- .../blender/editors/space_view3d/drawmesh.c | 2 +- .../blender/editors/space_view3d/drawobject.c | 3 ++- source/blender/gpu/intern/gpu_draw.c | 2 +- source/blender/imbuf/intern/IMB_metadata.h | 2 +- source/blender/imbuf/intern/metadata.c | 2 +- source/blender/imbuf/intern/targa.c | 6 ++++-- source/blender/makesdna/DNA_meshdata_types.h | 3 ++- .../modifiers/intern/MOD_particlesystem.c | 8 +++---- .../composite/nodes/node_composite_image.c | 4 ++-- 27 files changed, 58 insertions(+), 66 deletions(-) diff --git a/source/blender/avi/intern/avi.c b/source/blender/avi/intern/avi.c index cda2cf303eb..2845b2f95c9 100644 --- a/source/blender/avi/intern/avi.c +++ b/source/blender/avi/intern/avi.c @@ -734,16 +734,15 @@ AviError AVI_close(AviMovie *movie) fclose(movie->fp); - for (i = 0; movie->header && (i < movie->header->Streams); i++) { - if (movie->streams && (movie->streams[i].sf != NULL)) { + for (i = 0; i < movie->header->Streams; i++) { + if (movie->streams[i].sf != NULL) { MEM_freeN(movie->streams[i].sf); } } - if (movie->header != NULL) - MEM_freeN(movie->header); - if (movie->streams != NULL) - MEM_freeN(movie->streams); + MEM_freeN(movie->header); + MEM_freeN(movie->streams); + if (movie->entries != NULL) MEM_freeN(movie->entries); if (movie->offset_table != NULL) @@ -1082,15 +1081,15 @@ AviError AVI_close_compress(AviMovie *movie) fclose(movie->fp); - for (i = 0; movie->header && (i < movie->header->Streams); i++) { + for (i = 0; i < movie->header->Streams; i++) { if (movie->streams && (movie->streams[i].sf != NULL)) { MEM_freeN(movie->streams[i].sf); } } - if (movie->header != NULL) - MEM_freeN(movie->header); - if (movie->entries != NULL) - MEM_freeN(movie->entries); + + MEM_freeN(movie->header); + MEM_freeN(movie->entries); + if (movie->streams != NULL) MEM_freeN(movie->streams); if (movie->offset_table != NULL) diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index f4bfb22573b..02b66993c0a 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -161,7 +161,7 @@ static void blf_font_ensure_ascii_table(FontBLF *font) } \ } (void)0 -void blf_font_draw(FontBLF *font, const char *str, unsigned int len) +void blf_font_draw(FontBLF *font, const char *str, size_t len) { unsigned int c; GlyphBLF *g, *g_prev = NULL; @@ -193,7 +193,7 @@ void blf_font_draw(FontBLF *font, const char *str, unsigned int len) } /* faster version of blf_font_draw, ascii only for view dimensions */ -void blf_font_draw_ascii(FontBLF *font, const char *str, unsigned int len) +void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len) { unsigned char c; GlyphBLF *g, *g_prev = NULL; diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h index ba66fce8374..65a54783978 100644 --- a/source/blender/blenfont/intern/blf_internal.h +++ b/source/blender/blenfont/intern/blf_internal.h @@ -51,8 +51,8 @@ struct FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem void blf_font_attach_from_mem(struct FontBLF *font, const unsigned char *mem, int mem_size); void blf_font_size(struct FontBLF *font, int size, int dpi); -void blf_font_draw(struct FontBLF *font, const char *str, unsigned int len); -void blf_font_draw_ascii(struct FontBLF *font, const char *str, unsigned int len); +void blf_font_draw(struct FontBLF *font, const char *str, size_t len); +void blf_font_draw_ascii(struct FontBLF *font, const char *str, size_t len); void blf_font_buffer(struct FontBLF *font, const char *str); void blf_font_boundbox(struct FontBLF *font, const char *str, struct rctf *box); void blf_font_width_and_height(struct FontBLF *font, const char *str, float *width, float *height); diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c index 2b7e225d709..d0b77222114 100644 --- a/source/blender/blenfont/intern/blf_lang.c +++ b/source/blender/blenfont/intern/blf_lang.c @@ -129,7 +129,7 @@ void BLF_lang_init(void) } /* get LANG/LANGUAGE environment variable */ -static void get_language_variable(const char *varname, char *var, int maxlen) +static void get_language_variable(const char *varname, char *var, const size_t maxlen) { char *env = getenv(varname); @@ -149,7 +149,7 @@ static void get_language_variable(const char *varname, char *var, int maxlen) /* get language to be used based on locale(which might be empty when using default language) and * LANG environment variable */ -static void get_language(const char *locale, const char *lang, char *language, int maxlen) +static void get_language(const char *locale, const char *lang, char *language, const size_t maxlen) { if (locale[0]) { BLI_strncpy(language, locale, maxlen); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 8c0aea5723f..07d14513bd0 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -384,7 +384,7 @@ void DM_ensure_tessface(DerivedMesh *dm) } } - else if (dm->dirty && DM_DIRTY_TESS_CDLAYERS) { + else if (dm->dirty & DM_DIRTY_TESS_CDLAYERS) { BLI_assert(CustomData_has_layer(&dm->faceData, CD_POLYINDEX)); DM_update_tessface_data(dm); } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 4fb235ac9f7..5ba56a85c72 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -3288,7 +3288,7 @@ void BKE_object_groups_clear(Scene *scene, Base *base, Object *object) { Group *group = NULL; - BLI_assert(base->object == object); + BLI_assert((base == NULL) || (base->object == object)); if (scene && base == NULL) { base = BKE_scene_base_find(scene, object); diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index af5a8f5d59d..3c89fdba13a 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -3070,7 +3070,6 @@ int setcurr_tab_spaces(Text *text, int space) const char *comm = "#"; const char indent = (text->flags & TXT_TABSTOSPACES) ? ' ' : '\t'; static const char *back_words[] = {"return", "break", "continue", "pass", "yield", NULL}; - if (!text) return 0; if (!text->curl) return 0; while (text->curl->line[i] == indent) { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 2932fb63f43..8656812f90f 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7821,7 +7821,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) MovieTrackingMarker *marker = &track->markers[i]; if (is_zero_v2(marker->pattern_corners[0]) && is_zero_v2(marker->pattern_corners[1]) && - is_zero_v2(marker->pattern_corners[3]) && is_zero_v2(marker->pattern_corners[3])) + is_zero_v2(marker->pattern_corners[2]) && is_zero_v2(marker->pattern_corners[3])) { marker->pattern_corners[0][0] = track->pat_min[0]; marker->pattern_corners[0][1] = track->pat_min[1]; diff --git a/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp b/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp index e41361fcb2e..bedbfc72722 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystemHelper.cpp @@ -79,14 +79,10 @@ void ExecutionSystemHelper::addNode(vector& nodes, Node *node) Node *ExecutionSystemHelper::addNode(vector& nodes, bNode *b_node, bool inActiveGroup, bool fast) { - Node *node; - node = Converter::convert(b_node, fast); + Node *node = Converter::convert(b_node, fast); node->setIsInActiveGroup(inActiveGroup); - if (node != NULL) { - addNode(nodes, node); - return node; - } - return NULL; + addNode(nodes, node); + return node; } void ExecutionSystemHelper::addOperation(vector& operations, NodeOperation *operation) { diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.h b/source/blender/compositor/operations/COM_MovieDistortionOperation.h index 7e62de7b9f1..f3eeb2f48ba 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.h +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.h @@ -99,8 +99,8 @@ public: this->m_inverted == inverted && this->m_width == width && this->m_height == height && - this->m_calibration_width == this->m_calibration_width && - this->m_calibration_height == this->m_calibration_height; + this->m_calibration_width == calibration_width && + this->m_calibration_height == claibration_height; } void getUV(MovieTracking *trackingData, int x, int y, float *u, float *v) diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 738fdc229fb..cb52d88f985 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -4589,7 +4589,9 @@ void ED_pose_deselectall(Object *ob, int test) int selectmode = 0; /* we call this from outliner too */ - if (ELEM(NULL, ob, ob->pose)) return; + if (ob->pose == NULL) { + return; + } /* Determine if we're selecting or deselecting */ if (test == 1) { diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 6b6d2a1505f..346ed0002bd 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -667,7 +667,7 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numsource, *err_str = NULL; /* count triangles and create mask */ - if ((use_face_sel = (me->editflag & ME_EDIT_PAINT_MASK) != 0) || + if ((use_face_sel = ((me->editflag & ME_EDIT_PAINT_MASK) != 0)) || (use_vert_sel = ((me->editflag & ME_EDIT_VERT_SEL) != 0))) { mask = MEM_callocN(sizeof(int) * me->totvert, "heat_bone_weighting mask"); diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index b1a613bef5d..ac1766aff69 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -728,7 +728,7 @@ static int pose_select_grouped_exec(bContext *C, wmOperator *op) short changed = 0; /* sanity check */ - if (ELEM(NULL, ob, ob->pose)) + if (ob->pose == NULL) return OPERATOR_CANCELLED; /* selection types diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 2e88e3083a4..dc9347b3852 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -1496,7 +1496,7 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, BLI_rctf_translate(&block->rect, xof, yof); /* safety calculus */ - if (but) { + { const float midx = BLI_RCT_CENTER_X(&butrct); const float midy = BLI_RCT_CENTER_Y(&butrct); @@ -1523,20 +1523,13 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, } block->direction = dir1; } - else { - block->safety.xmin = block->rect.xmin - 40; - block->safety.ymin = block->rect.ymin - 40; - block->safety.xmax = block->rect.xmax + 40; - block->safety.ymax = block->rect.ymax + 40; - } /* keep a list of these, needed for pulldown menus */ saferct = MEM_callocN(sizeof(uiSafetyRct), "uiSafetyRct"); saferct->parent = butrct; saferct->safety = block->safety; BLI_freelistN(&block->saferct); - if (but) - BLI_duplicatelist(&block->saferct, &but->block->saferct); + BLI_duplicatelist(&block->saferct, &but->block->saferct); BLI_addhead(&block->saferct, saferct); } diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index 0f1d1a24dcb..9c71746d045 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -851,7 +851,7 @@ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, int resize if (scroll & V2D_SCROLL_VERTICAL) height -= V2D_SCROLL_HEIGHT; - if (ELEM3(0, v2d, width, height)) { + if (ELEM(0, width, height)) { if (G.debug & G_DEBUG) printf("Error: View2D totRect set exiting: v2d=%p width=%d height=%d\n", (void *)v2d, width, height); // XXX temp debug info return; diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 7c8386d55dc..a6afe6b2d04 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -585,13 +585,11 @@ void OBJECT_OT_hook_add_newobj(wmOperatorType *ot) static int object_hook_remove_exec(bContext *C, wmOperator *op) { int num = RNA_enum_get(op->ptr, "modifier"); - Object *ob = NULL; + Object *ob = CTX_data_edit_object(C); HookModifierData *hmd = NULL; - ob = CTX_data_edit_object(C); hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num); - - if (!ob || !hmd) { + if (!hmd) { BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_node/node_header.c b/source/blender/editors/space_node/node_header.c index e17961b6c7c..5ab698cd415 100644 --- a/source/blender/editors/space_node/node_header.c +++ b/source/blender/editors/space_node/node_header.c @@ -100,7 +100,7 @@ static void do_node_add(bContext *C, bNodeTemplate *ntemp) /* once this is called from an operator, this should be removed */ if (node_new) { char undostr[BKE_UNDO_STR_MAX]; - BLI_snprintf(undostr, sizeof(BKE_UNDO_STR_MAX), "Add Node %s", nodeLabel(node_new)); + BLI_snprintf(undostr, sizeof(undostr), "Add Node %s", nodeLabel(node_new)); BKE_write_undo(C, undostr); } diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 8b7cf406642..823de61d044 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -433,8 +433,11 @@ static int tree_element_active_bone(bContext *C, Scene *scene, TreeElement *te, if (set) { if (!(bone->flag & BONE_HIDDEN_P)) { - if (set == 2) ED_pose_deselectall(OBACT, 2); // 2 is clear active tag - else ED_pose_deselectall(OBACT, 0); + Object *ob = OBACT; + if (ob) { + if (set == 2) ED_pose_deselectall(ob, 2); // 2 is clear active tag + else ED_pose_deselectall(ob, 0); + } if (set == 2 && (bone->flag & BONE_SELECTED)) { bone->flag &= ~BONE_SELECTED; @@ -444,7 +447,7 @@ static int tree_element_active_bone(bContext *C, Scene *scene, TreeElement *te, arm->act_bone = bone; } - WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, OBACT); + WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, ob); } } else { diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index e7014bf41d5..ca4f00be2d5 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -515,7 +515,7 @@ static void update_tface_color_layer(DerivedMesh *dm) finalCol[i * 4 + j].r = 255; } } - else if (tface && mface && set_draw_settings_cached(0, tface, ma, Gtexdraw)) { + else if (tface && set_draw_settings_cached(0, tface, ma, Gtexdraw)) { for (j = 0; j < 4; j++) { finalCol[i * 4 + j].b = 255; finalCol[i * 4 + j].g = 0; diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index d1f0d8fa25e..a51ec15bd86 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -3305,7 +3305,8 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act); } - if (em) { + + { draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act, rv3d); if (me->drawflag & ME_DRAWNORMALS) { diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index af52366c964..9b027f7906d 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -1226,7 +1226,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O * - object transparency off: for glsl we draw both in a single pass, and * for solid we don't use transparency at all. */ GMS.use_alpha_pass = (do_alpha_after != NULL); - GMS.is_alpha_pass = (v3d && v3d->transp); + GMS.is_alpha_pass = (v3d->transp != FALSE); if (GMS.use_alpha_pass) *do_alpha_after = FALSE; diff --git a/source/blender/imbuf/intern/IMB_metadata.h b/source/blender/imbuf/intern/IMB_metadata.h index 4f512e04ef8..a68d7a7813e 100644 --- a/source/blender/imbuf/intern/IMB_metadata.h +++ b/source/blender/imbuf/intern/IMB_metadata.h @@ -62,7 +62,7 @@ void IMB_metadata_free(struct ImBuf *img); * \param len - length of value buffer allocated by user. * \return - 1 (true) if ImageInfo present and value for the key found, 0 (false) otherwise */ -int IMB_metadata_get_field(struct ImBuf *img, const char *key, char *value, int len); +int IMB_metadata_get_field(struct ImBuf *img, const char *key, char *value, const size_t len); /** set user data in the ImMetaData struct, which has to be allocated with IMB_metadata_create * before calling this function. diff --git a/source/blender/imbuf/intern/metadata.c b/source/blender/imbuf/intern/metadata.c index 1ce2053fde5..fed55c05eea 100644 --- a/source/blender/imbuf/intern/metadata.c +++ b/source/blender/imbuf/intern/metadata.c @@ -63,7 +63,7 @@ void IMB_metadata_free(struct ImBuf *img) } } -int IMB_metadata_get_field(struct ImBuf *img, const char *key, char *field, int len) +int IMB_metadata_get_field(struct ImBuf *img, const char *key, char *field, const size_t len) { ImMetaData *info; int retval = 0; diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c index 7b6bca6d54f..253680e4bea 100644 --- a/source/blender/imbuf/intern/targa.c +++ b/source/blender/imbuf/intern/targa.c @@ -685,9 +685,11 @@ ImBuf *imb_loadtarga(unsigned char *mem, size_t mem_size, int flags, char colors } } - if (tga.imgdes & 0x20) IMB_flipy(ibuf); + if (tga.imgdes & 0x20) { + IMB_flipy(ibuf); + } - if (ibuf && ibuf->rect) + if (ibuf->rect) IMB_convert_rgba_to_abgr(ibuf); return(ibuf); diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 0b826070fe4..54e1e762f8b 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -119,7 +119,8 @@ typedef struct MLoopUV { #define MLOOPUV_PINNED 4 /* at the moment alpha is abused for vertex painting - * and not used for transparency, note that red and blue are swapped */ + * and not used for transparency, + * note that red and blue are _not_ swapped, as they are with #MCol */ typedef struct MLoopCol { char r, g, b, a; } MLoopCol; diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index 890e45f7e80..254c02b7672 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -188,11 +188,9 @@ static void deformVerts(ModifierData *md, Object *ob, psmd->totdmface = psmd->dm->getNumTessFaces(psmd->dm); } - if (psys) { - psmd->flag &= ~eParticleSystemFlag_psys_updated; - particle_system_update(md->scene, ob, psys); - psmd->flag |= eParticleSystemFlag_psys_updated; - } + psmd->flag &= ~eParticleSystemFlag_psys_updated; + particle_system_update(md->scene, ob, psys); + psmd->flag |= eParticleSystemFlag_psys_updated; } /* disabled particles in editmode for now, until support for proper derivedmesh diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index a50cfae550c..9f3874560ac 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -282,6 +282,8 @@ static void cmp_node_image_update(bNodeTree *ntree, bNode *node) cmp_node_image_verify_outputs(ntree, node); } +#ifdef WITH_COMPOSITOR_LEGACY + /* float buffer from the image with matching color management */ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc) { @@ -309,8 +311,6 @@ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc) return rect; } -#ifdef WITH_COMPOSITOR_LEGACY - /* note: this function is used for multilayer too, to ensure uniform * handling with BKE_image_get_ibuf() */ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser) From 0bf6007e3bda226ae83c373ffeba029b53c93b70 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 15 Sep 2012 08:35:26 +0000 Subject: [PATCH 153/160] Silence compiler's warnings. --- source/blender/blenkernel/intern/sequencer.c | 12 ++++++------ source/blender/imbuf/intern/colormanagement.c | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 20db9d5e056..8d7ca94ed48 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -311,7 +311,7 @@ void BKE_sequencer_editing_free(Scene *scene) /*********************** Sequencer color space functions *************************/ -void BKE_sequencer_imbuf_assign_spaces(Scene *scene, ImBuf *ibuf) +static void sequencer_imbuf_assign_spaces(Scene *scene, ImBuf *ibuf) { IMB_colormanagement_imbuf_assign_float_space(ibuf, &scene->sequencer_colorspace_settings); } @@ -1303,7 +1303,7 @@ static ImBuf *seq_proxy_fetch(SeqRenderData context, Sequence *seq, int cfra) ImBuf *ibuf = IMB_loadiffname(name, IB_rect, NULL); if (ibuf) - BKE_sequencer_imbuf_assign_spaces(context.scene, ibuf); + sequencer_imbuf_assign_spaces(context.scene, ibuf); return ibuf; } @@ -1981,7 +1981,7 @@ static void copy_to_ibuf_still(SeqRenderData context, Sequence *seq, float nr, I * changing the cached image... */ ibuf = IMB_dupImBuf(ibuf); - BKE_sequencer_imbuf_assign_spaces(context.scene, ibuf); + sequencer_imbuf_assign_spaces(context.scene, ibuf); if (nr == 0) { BKE_sequencer_cache_put(context, seq, seq->start, SEQ_STRIPELEM_IBUF_STARTSTILL, ibuf); @@ -2583,7 +2583,7 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo case SEQ_TYPE_MOVIECLIP: { ibuf = seq_render_movieclip_strip(context, seq, nr); - BKE_sequencer_imbuf_assign_spaces(context.scene, ibuf); + sequencer_imbuf_assign_spaces(context.scene, ibuf); if (ibuf && use_preprocess) { ImBuf *i = IMB_dupImBuf(ibuf); @@ -2608,7 +2608,7 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo } if (ibuf) - BKE_sequencer_imbuf_assign_spaces(context.scene, ibuf); + sequencer_imbuf_assign_spaces(context.scene, ibuf); return ibuf; } @@ -2653,7 +2653,7 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) if (ibuf == NULL) { ibuf = IMB_allocImBuf(context.rectx, context.recty, 32, IB_rect); - BKE_sequencer_imbuf_assign_spaces(context.scene, ibuf); + sequencer_imbuf_assign_spaces(context.scene, ibuf); } if (ibuf->x != context.rectx || ibuf->y != context.recty) diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 7fa14dd6bd1..6db45f0308a 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -497,7 +497,7 @@ static void colormanage_load_config(ConstConfigRcPtr *config) global_tot_display = tot_display; } -void colormanage_free_config(void) +static void colormanage_free_config(void) { ColorSpace *colorspace; ColorManagedDisplay *display; From 18326d852b5e82a1c5d1b9c0c45fad213a6d0d01 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 5 Nov 2012 19:42:27 +0000 Subject: [PATCH 154/160] Merging r50625 through r51896 from trunk into soc-2011-tomato Merging just in case we'll want to develop some experimental stuff --- CMakeLists.txt | 246 +- GNUmakefile | 95 +- SConstruct | 13 +- .../build_environment/prepare_release_env.sh | 1483 ++++++++ .../config/user-config-glibc211-i686.py | 145 + .../config/user-config-glibc211-x86_64.py | 144 + ...ig-i686.py => user-config-glibc27-i686.py} | 11 +- ...86_64.py => user-config-glibc27-x86_64.py} | 8 + .../user-config-player-glibc211-i686.py | 112 + .../user-config-player-glibc211-x86_64.py | 112 + ....py => user-config-player-glibc27-i686.py} | 8 + ...y => user-config-player-glibc27-x86_64.py} | 8 + build_files/buildbot/master.cfg | 61 +- build_files/buildbot/master_unpack.py | 2 +- build_files/buildbot/slave_compile.py | 18 +- build_files/buildbot/slave_pack.py | 20 +- build_files/cmake/clang_array_check.py | 353 ++ .../cmake/cmake_consistency_check_config.py | 2 - build_files/cmake/cmake_qtcreator_project.py | 8 +- .../cmake/cmake_static_check_clang_array.py | 77 + .../cmake/cmake_static_check_cppcheck.py | 3 +- .../cmake/cmake_static_check_smatch.py | 3 +- .../cmake/cmake_static_check_sparse.py | 3 +- .../cmake/cmake_static_check_splint.py | 3 +- build_files/cmake/config/blender_lite.cmake | 3 +- build_files/cmake/macros.cmake | 8 +- build_files/cmake/project_info.py | 12 +- build_files/cmake/project_source_info.py | 26 +- build_files/package_spec/rpm/blender.spec.in | 1 + build_files/scons/config/linux-config.py | 2 +- .../scons/config/win32-mingw-config.py | 6 +- .../scons/config/win64-mingw-config.py | 4 +- build_files/scons/tools/Blender.py | 24 +- build_files/scons/tools/btools.py | 36 +- doc/guides/interface_API.txt | 16 +- doc/manpage/blender.1 | 4 +- .../examples/bpy.types.Operator.4.py | 4 +- .../examples/bpy.types.Operator.5.py | 4 +- doc/python_api/rst/bge.constraints.rst | 8 + doc/python_api/rst/bge.logic.rst | 6 +- doc/python_api/rst/bge.texture.rst | 23 +- doc/python_api/rst/bge.types.rst | 121 +- doc/python_api/rst/change_log.rst | 1499 ++++++++ doc/python_api/rst/info_overview.rst | 2 +- doc/python_api/rst/info_quickstart.rst | 20 +- doc/python_api/sphinx_changelog_gen.py | 13 +- doc/python_api/sphinx_doc_gen.py | 147 +- extern/Eigen3/Eigen/Cholesky | 7 +- extern/Eigen3/Eigen/CholmodSupport | 45 + extern/Eigen3/Eigen/Core | 60 +- extern/Eigen3/Eigen/Eigen2Support | 46 +- extern/Eigen3/Eigen/Eigenvalues | 10 +- extern/Eigen3/Eigen/Geometry | 4 - extern/Eigen3/Eigen/Householder | 4 - extern/Eigen3/Eigen/IterativeLinearSolvers | 40 + extern/Eigen3/Eigen/Jacobi | 4 - extern/Eigen3/Eigen/LU | 7 +- extern/Eigen3/Eigen/LeastSquares | 4 - extern/Eigen3/Eigen/OrderingMethods | 23 + extern/Eigen3/Eigen/PaStiXSupport | 46 + extern/Eigen3/Eigen/PardisoSupport | 30 + extern/Eigen3/Eigen/QR | 8 +- extern/Eigen3/Eigen/SVD | 7 +- extern/Eigen3/Eigen/Sparse | 66 +- extern/Eigen3/Eigen/SparseCholesky | 30 + extern/Eigen3/Eigen/SparseCore | 66 + extern/Eigen3/Eigen/StdDeque | 21 +- extern/Eigen3/Eigen/StdList | 21 +- extern/Eigen3/Eigen/StdVector | 21 +- extern/Eigen3/Eigen/SuperLUSupport | 59 + extern/Eigen3/Eigen/UmfPackSupport | 36 + extern/Eigen3/Eigen/src/Cholesky/LDLT.h | 172 +- extern/Eigen3/Eigen/src/Cholesky/LLT.h | 172 +- extern/Eigen3/Eigen/src/Cholesky/LLT_MKL.h | 102 + .../Eigen/src/CholmodSupport/CholmodSupport.h | 579 +++ extern/Eigen3/Eigen/src/Core/Array.h | 24 +- extern/Eigen3/Eigen/src/Core/ArrayBase.h | 31 +- extern/Eigen3/Eigen/src/Core/ArrayWrapper.h | 53 +- extern/Eigen3/Eigen/src/Core/Assign.h | 132 +- extern/Eigen3/Eigen/src/Core/Assign_MKL.h | 224 ++ extern/Eigen3/Eigen/src/Core/BandMatrix.h | 26 +- extern/Eigen3/Eigen/src/Core/Block.h | 46 +- extern/Eigen3/Eigen/src/Core/BooleanRedux.h | 37 +- .../Eigen3/Eigen/src/Core/CommaInitializer.h | 25 +- extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h | 29 +- extern/Eigen3/Eigen/src/Core/CwiseNullaryOp.h | 49 +- extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h | 27 +- extern/Eigen3/Eigen/src/Core/CwiseUnaryView.h | 27 +- extern/Eigen3/Eigen/src/Core/DenseBase.h | 28 +- .../Eigen3/Eigen/src/Core/DenseCoeffsBase.h | 33 +- extern/Eigen3/Eigen/src/Core/DenseStorage.h | 47 +- extern/Eigen3/Eigen/src/Core/Diagonal.h | 59 +- extern/Eigen3/Eigen/src/Core/DiagonalMatrix.h | 31 +- .../Eigen3/Eigen/src/Core/DiagonalProduct.h | 28 +- extern/Eigen3/Eigen/src/Core/Dot.h | 33 +- extern/Eigen3/Eigen/src/Core/EigenBase.h | 24 +- extern/Eigen3/Eigen/src/Core/Flagged.h | 25 +- .../Eigen/src/Core/ForceAlignedAccess.h | 25 +- extern/Eigen3/Eigen/src/Core/Functors.h | 115 +- extern/Eigen3/Eigen/src/Core/Fuzzy.h | 29 +- extern/Eigen3/Eigen/src/Core/GeneralProduct.h | 613 ++++ .../Eigen3/Eigen/src/Core/GenericPacketMath.h | 27 +- .../Eigen3/Eigen/src/Core/GlobalFunctions.h | 48 +- extern/Eigen3/Eigen/src/Core/IO.h | 27 +- extern/Eigen3/Eigen/src/Core/Map.h | 25 +- extern/Eigen3/Eigen/src/Core/MapBase.h | 23 +- extern/Eigen3/Eigen/src/Core/MathFunctions.h | 41 +- extern/Eigen3/Eigen/src/Core/Matrix.h | 44 +- extern/Eigen3/Eigen/src/Core/MatrixBase.h | 36 +- extern/Eigen3/Eigen/src/Core/NestByValue.h | 25 +- extern/Eigen3/Eigen/src/Core/NoAlias.h | 25 +- extern/Eigen3/Eigen/src/Core/NumTraits.h | 41 +- .../Eigen3/Eigen/src/Core/PermutationMatrix.h | 31 +- .../Eigen3/Eigen/src/Core/PlainObjectBase.h | 103 +- extern/Eigen3/Eigen/src/Core/Product.h | 647 +--- extern/Eigen3/Eigen/src/Core/ProductBase.h | 32 +- extern/Eigen3/Eigen/src/Core/Random.h | 25 +- extern/Eigen3/Eigen/src/Core/Redux.h | 64 +- extern/Eigen3/Eigen/src/Core/Replicate.h | 33 +- extern/Eigen3/Eigen/src/Core/ReturnByValue.h | 25 +- extern/Eigen3/Eigen/src/Core/Reverse.h | 32 +- extern/Eigen3/Eigen/src/Core/Select.h | 46 +- .../Eigen3/Eigen/src/Core/SelfAdjointView.h | 41 +- .../Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h | 35 +- .../Eigen3/Eigen/src/Core/SolveTriangular.h | 47 +- extern/Eigen3/Eigen/src/Core/StableNorm.h | 31 +- extern/Eigen3/Eigen/src/Core/Stride.h | 25 +- extern/Eigen3/Eigen/src/Core/Swap.h | 36 +- extern/Eigen3/Eigen/src/Core/Transpose.h | 31 +- extern/Eigen3/Eigen/src/Core/Transpositions.h | 27 +- .../Eigen3/Eigen/src/Core/TriangularMatrix.h | 57 +- extern/Eigen3/Eigen/src/Core/VectorBlock.h | 24 +- extern/Eigen3/Eigen/src/Core/VectorwiseOp.h | 109 +- extern/Eigen3/Eigen/src/Core/Visitor.h | 31 +- .../Eigen/src/Core/arch/AltiVec/Complex.h | 27 +- .../Eigen/src/Core/arch/AltiVec/PacketMath.h | 29 +- .../Eigen/src/Core/arch/Default/Settings.h | 21 +- .../Eigen3/Eigen/src/Core/arch/NEON/Complex.h | 25 +- .../Eigen/src/Core/arch/NEON/PacketMath.h | 28 +- .../Eigen3/Eigen/src/Core/arch/SSE/Complex.h | 31 +- .../Eigen/src/Core/arch/SSE/MathFunctions.h | 29 +- .../Eigen/src/Core/arch/SSE/PacketMath.h | 52 +- .../src/Core/products/CoeffBasedProduct.h | 63 +- .../Core/products/GeneralBlockPanelKernel.h | 275 +- .../src/Core/products/GeneralMatrixMatrix.h | 43 +- .../products/GeneralMatrixMatrixTriangular.h | 41 +- .../GeneralMatrixMatrixTriangular_MKL.h | 146 + .../Core/products/GeneralMatrixMatrix_MKL.h | 118 + .../src/Core/products/GeneralMatrixVector.h | 41 +- .../Core/products/GeneralMatrixVector_MKL.h | 131 + .../Eigen/src/Core/products/Parallelizer.h | 47 +- .../Core/products/SelfadjointMatrixMatrix.h | 29 +- .../products/SelfadjointMatrixMatrix_MKL.h | 295 ++ .../Core/products/SelfadjointMatrixVector.h | 50 +- .../products/SelfadjointMatrixVector_MKL.h | 114 + .../src/Core/products/SelfadjointProduct.h | 31 +- .../Core/products/SelfadjointRank2Update.h | 29 +- .../Core/products/TriangularMatrixMatrix.h | 112 +- .../products/TriangularMatrixMatrix_MKL.h | 309 ++ .../Core/products/TriangularMatrixVector.h | 101 +- .../products/TriangularMatrixVector_MKL.h | 247 ++ .../Core/products/TriangularSolverMatrix.h | 114 +- .../products/TriangularSolverMatrix_MKL.h | 155 + .../Core/products/TriangularSolverVector.h | 25 +- extern/Eigen3/Eigen/src/Core/util/BlasUtil.h | 47 +- extern/Eigen3/Eigen/src/Core/util/Constants.h | 78 +- .../src/Core/util/DisableStupidWarnings.h | 4 +- .../Eigen/src/Core/util/ForwardDeclarations.h | 27 +- .../Eigen3/Eigen/src/Core/util/MKL_support.h | 109 + extern/Eigen3/Eigen/src/Core/util/Macros.h | 44 +- extern/Eigen3/Eigen/src/Core/util/Memory.h | 105 +- extern/Eigen3/Eigen/src/Core/util/Meta.h | 42 +- extern/Eigen3/Eigen/src/Core/util/NonMPL2.h | 3 + .../Eigen3/Eigen/src/Core/util/StaticAssert.h | 45 +- extern/Eigen3/Eigen/src/Core/util/XprHelper.h | 60 +- extern/Eigen3/Eigen/src/Eigen2Support/Block.h | 25 +- extern/Eigen3/Eigen/src/Eigen2Support/Cwise.h | 25 +- .../Eigen/src/Eigen2Support/CwiseOperators.h | 25 +- .../src/Eigen2Support/Geometry/AlignedBox.h | 33 +- .../Eigen/src/Eigen2Support/Geometry/All.h | 2 +- .../src/Eigen2Support/Geometry/AngleAxis.h | 24 +- .../src/Eigen2Support/Geometry/Hyperplane.h | 25 +- .../Eigen2Support/Geometry/ParametrizedLine.h | 24 +- .../src/Eigen2Support/Geometry/Quaternion.h | 43 +- .../src/Eigen2Support/Geometry/Rotation2D.h | 24 +- .../src/Eigen2Support/Geometry/RotationBase.h | 31 +- .../src/Eigen2Support/Geometry/Scaling.h | 24 +- .../src/Eigen2Support/Geometry/Transform.h | 24 +- .../src/Eigen2Support/Geometry/Translation.h | 24 +- extern/Eigen3/Eigen/src/Eigen2Support/LU.h | 25 +- extern/Eigen3/Eigen/src/Eigen2Support/Lazy.h | 25 +- .../Eigen/src/Eigen2Support/LeastSquares.h | 24 +- .../Eigen3/Eigen/src/Eigen2Support/Macros.h | 21 +- .../Eigen/src/Eigen2Support/MathFunctions.h | 25 +- .../Eigen3/Eigen/src/Eigen2Support/Memory.h | 25 +- extern/Eigen3/Eigen/src/Eigen2Support/Meta.h | 25 +- extern/Eigen3/Eigen/src/Eigen2Support/Minor.h | 25 +- extern/Eigen3/Eigen/src/Eigen2Support/QR.h | 24 +- extern/Eigen3/Eigen/src/Eigen2Support/SVD.h | 27 +- .../src/Eigen2Support/TriangularSolver.h | 25 +- .../Eigen/src/Eigen2Support/VectorBlock.h | 25 +- .../src/Eigenvalues/ComplexEigenSolver.h | 25 +- .../Eigen/src/Eigenvalues/ComplexSchur.h | 72 +- .../Eigen/src/Eigenvalues/ComplexSchur_MKL.h | 94 + .../Eigen/src/Eigenvalues/EigenSolver.h | 32 +- .../Eigen/src/Eigenvalues/EigenvaluesCommon.h | 31 - .../GeneralizedSelfAdjointEigenSolver.h | 26 +- .../src/Eigenvalues/HessenbergDecomposition.h | 27 +- .../src/Eigenvalues/MatrixBaseEigenvalues.h | 25 +- .../Eigen3/Eigen/src/Eigenvalues/RealSchur.h | 92 +- .../Eigen/src/Eigenvalues/RealSchur_MKL.h | 83 + .../src/Eigenvalues/SelfAdjointEigenSolver.h | 327 +- .../Eigenvalues/SelfAdjointEigenSolver_MKL.h | 92 + .../src/Eigenvalues/Tridiagonalization.h | 33 +- extern/Eigen3/Eigen/src/Geometry/AlignedBox.h | 67 +- extern/Eigen3/Eigen/src/Geometry/AngleAxis.h | 27 +- .../Eigen3/Eigen/src/Geometry/EulerAngles.h | 24 +- .../Eigen3/Eigen/src/Geometry/Homogeneous.h | 39 +- extern/Eigen3/Eigen/src/Geometry/Hyperplane.h | 25 +- .../Eigen3/Eigen/src/Geometry/OrthoMethods.h | 39 +- .../Eigen/src/Geometry/ParametrizedLine.h | 67 +- extern/Eigen3/Eigen/src/Geometry/Quaternion.h | 77 +- extern/Eigen3/Eigen/src/Geometry/Rotation2D.h | 27 +- .../Eigen3/Eigen/src/Geometry/RotationBase.h | 37 +- extern/Eigen3/Eigen/src/Geometry/Scaling.h | 40 +- extern/Eigen3/Eigen/src/Geometry/Transform.h | 115 +- .../Eigen3/Eigen/src/Geometry/Translation.h | 31 +- extern/Eigen3/Eigen/src/Geometry/Umeyama.h | 25 +- .../Eigen/src/Geometry/arch/Geometry_SSE.h | 31 +- .../Eigen/src/Householder/BlockHouseholder.h | 27 +- .../Eigen/src/Householder/Householder.h | 73 +- .../src/Householder/HouseholderSequence.h | 74 +- .../BasicPreconditioners.h | 149 + .../src/IterativeLinearSolvers/BiCGSTAB.h | 254 ++ .../ConjugateGradient.h | 251 ++ .../IterativeLinearSolvers/IncompleteLUT.h | 466 +++ .../IterativeSolverBase.h | 254 ++ extern/Eigen3/Eigen/src/Jacobi/Jacobi.h | 32 +- extern/Eigen3/Eigen/src/LU/Determinant.h | 25 +- extern/Eigen3/Eigen/src/LU/FullPivLU.h | 26 +- extern/Eigen3/Eigen/src/LU/Inverse.h | 27 +- extern/Eigen3/Eigen/src/LU/PartialPivLU.h | 25 +- extern/Eigen3/Eigen/src/LU/PartialPivLU_MKL.h | 85 + extern/Eigen3/Eigen/src/LU/arch/Inverse_SSE.h | 27 +- extern/Eigen3/Eigen/src/OrderingMethods/Amd.h | 439 +++ .../Eigen/src/PaStiXSupport/PaStiXSupport.h | 742 ++++ .../Eigen/src/PardisoSupport/PardisoSupport.h | 614 ++++ .../Eigen3/Eigen/src/QR/ColPivHouseholderQR.h | 24 +- .../Eigen/src/QR/ColPivHouseholderQR_MKL.h | 98 + .../Eigen/src/QR/FullPivHouseholderQR.h | 122 +- extern/Eigen3/Eigen/src/QR/HouseholderQR.h | 24 +- .../Eigen3/Eigen/src/QR/HouseholderQR_MKL.h | 69 + extern/Eigen3/Eigen/src/SVD/JacobiSVD.h | 294 +- extern/Eigen3/Eigen/src/SVD/JacobiSVD_MKL.h | 92 + .../Eigen/src/SVD/UpperBidiagonalization.h | 25 +- .../Eigen/src/Sparse/DynamicSparseMatrix.h | 346 -- .../Eigen/src/Sparse/SparseCwiseUnaryOp.h | 146 - extern/Eigen3/Eigen/src/Sparse/SparseFuzzy.h | 41 - extern/Eigen3/Eigen/src/Sparse/SparseMatrix.h | 651 ---- .../Eigen/src/Sparse/SparseSparseProduct.h | 401 --- .../Eigen/src/Sparse/SparseTriangularView.h | 100 - .../src/SparseCholesky/SimplicialCholesky.h | 873 +++++ .../src/{Sparse => SparseCore}/AmbiVector.h | 32 +- .../CompressedStorage.h | 36 +- .../ConservativeSparseSparseProduct.h | 245 ++ .../{Sparse => SparseCore}/CoreIterators.h | 28 +- .../MappedSparseMatrix.h | 88 +- .../src/{Sparse => SparseCore}/SparseAssign.h | 0 .../src/{Sparse => SparseCore}/SparseBlock.h | 212 +- .../SparseCwiseBinaryOp.h | 87 +- .../Eigen/src/SparseCore/SparseCwiseUnaryOp.h | 163 + .../SparseDenseProduct.h | 147 +- .../SparseDiagonalProduct.h | 25 +- .../src/{Sparse => SparseCore}/SparseDot.h | 41 +- .../Eigen3/Eigen/src/SparseCore/SparseFuzzy.h | 26 + .../Eigen/src/SparseCore/SparseMatrix.h | 1116 ++++++ .../{Sparse => SparseCore}/SparseMatrixBase.h | 440 +-- .../Eigen/src/SparseCore/SparsePermutation.h | 148 + .../{Sparse => SparseCore}/SparseProduct.h | 103 +- .../src/{Sparse => SparseCore}/SparseRedux.h | 27 +- .../SparseSelfAdjointView.h | 176 +- .../SparseSparseProductWithPruning.h | 149 + .../{Sparse => SparseCore}/SparseTranspose.h | 41 +- .../src/SparseCore/SparseTriangularView.h | 164 + .../src/{Sparse => SparseCore}/SparseUtil.h | 109 +- .../src/{Sparse => SparseCore}/SparseVector.h | 205 +- .../src/{Sparse => SparseCore}/SparseView.h | 37 +- .../{Sparse => SparseCore}/TriangularSolver.h | 69 +- extern/Eigen3/Eigen/src/StlSupport/StdDeque.h | 21 +- extern/Eigen3/Eigen/src/StlSupport/StdList.h | 21 +- .../Eigen3/Eigen/src/StlSupport/StdVector.h | 21 +- extern/Eigen3/Eigen/src/StlSupport/details.h | 21 +- .../Eigen/src/SuperLUSupport/SuperLUSupport.h | 1025 ++++++ .../Eigen/src/UmfPackSupport/UmfPackSupport.h | 431 +++ extern/Eigen3/Eigen/src/misc/Image.h | 25 +- extern/Eigen3/Eigen/src/misc/Kernel.h | 25 +- extern/Eigen3/Eigen/src/misc/Solve.h | 27 +- extern/Eigen3/Eigen/src/misc/SparseSolve.h | 111 + extern/Eigen3/Eigen/src/misc/blas.h | 658 ++++ .../Eigen/src/plugins/ArrayCwiseBinaryOps.h | 56 + .../Eigen3/Eigen/src/plugins/BlockMethods.h | 21 +- .../Eigen/src/plugins/CommonCwiseBinaryOps.h | 21 +- .../Eigen/src/plugins/CommonCwiseUnaryOps.h | 21 +- .../Eigen/src/plugins/MatrixCwiseBinaryOps.h | 42 +- .../Eigen/src/plugins/MatrixCwiseUnaryOps.h | 21 +- extern/bullet2/patches/convex_hull.patch | 127 + extern/bullet2/readme.txt | 4 +- extern/bullet2/src/Bullet-C-Api.h | 10 + .../BulletDynamics/Dynamics/Bullet-C-API.cpp | 59 +- .../src/LinearMath/btConvexHullComputer.cpp | 2 + .../src/LinearMath/btConvexHullComputer.h | 1 + extern/carve/CMakeLists.txt | 2 +- extern/libmv/CMakeLists.txt | 19 +- extern/libmv/bundle.sh | 6 +- extern/libmv/libmv-capi.cpp | 14 +- extern/libmv/libmv-capi.h | 17 +- .../libmv/multiview/euclidean_resection.cc | 46 +- .../libmv/multiview/euclidean_resection.h | 12 +- extern/libmv/libmv/multiview/fundamental.cc | 4 +- extern/libmv/libmv/multiview/homography.cc | 2 +- .../libmv/libmv/numeric/levenberg_marquardt.h | 10 +- extern/libmv/libmv/simple_pipeline/detect.cc | 2 +- .../initialize_reconstruction.cc | 1 + .../libmv/libmv/simple_pipeline/intersect.cc | 1 + .../libmv/libmv/simple_pipeline/pipeline.cc | 29 +- extern/libmv/libmv/simple_pipeline/pipeline.h | 12 +- .../libmv/simple_pipeline/reconstruction.h | 11 + extern/libmv/libmv/simple_pipeline/resect.cc | 21 +- extern/libmv/libmv/simple_pipeline/resect.h | 6 +- extern/libmv/libmv/tracking/track_region.cc | 213 +- extern/libmv/libmv/tracking/track_region.h | 6 + extern/libmv/third_party/ceres/CMakeLists.txt | 50 +- extern/libmv/third_party/ceres/ChangeLog | 780 +++-- extern/libmv/third_party/ceres/SConscript | 6 +- extern/libmv/third_party/ceres/bundle.sh | 57 +- extern/libmv/third_party/ceres/files.txt | 22 +- .../include/ceres/autodiff_cost_function.h | 4 +- .../ceres/include/ceres/cost_function.h | 2 +- .../ceres/include/ceres/crs_matrix.h | 65 + .../ceres/include/ceres/fpclassify.h | 88 + .../include/ceres/internal/fixed_array.h | 3 +- .../ceres/include/ceres/internal/macros.h | 31 +- .../ceres/internal/manual_constructor.h | 67 +- .../ceres/include/ceres/internal/port.h | 6 + .../ceres/include/ceres/iteration_callback.h | 36 +- .../third_party/ceres/include/ceres/jet.h | 163 +- .../ceres/include/ceres/loss_function.h | 79 +- .../ceres/numeric_diff_cost_function.h | 6 +- .../third_party/ceres/include/ceres/problem.h | 6 +- .../ceres/include/ceres/rotation.h | 62 +- .../third_party/ceres/include/ceres/solver.h | 229 +- .../third_party/ceres/include/ceres/types.h | 68 +- .../{levenberg_marquardt.h => array_utils.cc} | 54 +- .../ceres/internal/ceres/array_utils.h | 65 + .../internal/ceres/block_evaluate_preparer.cc | 16 +- .../internal/ceres/block_evaluate_preparer.h | 16 +- .../ceres/block_jacobi_preconditioner.cc | 9 +- .../internal/ceres/block_jacobian_writer.cc | 5 +- .../ceres/block_random_access_dense_matrix.cc | 2 +- .../ceres/block_random_access_dense_matrix.h | 2 +- .../ceres/block_random_access_matrix.h | 2 +- .../block_random_access_sparse_matrix.cc | 6 +- .../ceres/block_random_access_sparse_matrix.h | 8 +- .../internal/ceres/block_sparse_matrix.cc | 8 +- .../internal/ceres/block_sparse_matrix.h | 8 +- .../ceres/internal/ceres/block_structure.cc | 2 +- .../ceres/canonical_views_clustering.cc | 8 +- .../ceres/internal/ceres/cgnr_solver.h | 2 +- .../ceres/internal/ceres/collections_port.h | 50 +- .../ceres/compressed_row_jacobian_writer.cc | 18 +- .../ceres/compressed_row_sparse_matrix.cc | 28 +- .../ceres/compressed_row_sparse_matrix.h | 28 +- .../ceres/conditioned_cost_function.cc | 4 +- .../ceres/conjugate_gradients_solver.cc | 20 +- .../ceres/conjugate_gradients_solver.h | 2 +- .../ceres/internal/ceres/corrector.cc | 2 +- .../ceres/internal/ceres/cxsparse.cc | 130 + .../ceres/internal/ceres/cxsparse.h | 90 + .../ceres/dense_normal_cholesky_solver.cc | 86 + .../ceres/dense_normal_cholesky_solver.h | 95 + .../ceres/internal/ceres/dense_qr_solver.cc | 4 +- .../ceres/internal/ceres/dense_qr_solver.h | 4 +- .../internal/ceres/dense_sparse_matrix.cc | 6 +- .../internal/ceres/dense_sparse_matrix.h | 4 +- .../ceres/internal/ceres/detect_structure.cc | 14 +- .../ceres/internal/ceres/detect_structure.h | 2 +- .../ceres/internal/ceres/dogleg_strategy.cc | 691 ++++ .../ceres/internal/ceres/dogleg_strategy.h | 163 + .../ceres/internal/ceres/evaluator.cc | 82 +- .../ceres/internal/ceres/evaluator.h | 31 + .../third_party/ceres/internal/ceres/file.cc | 5 +- .../generate_eliminator_specialization.py | 186 + .../ceres/gradient_checking_cost_function.cc | 10 +- .../third_party/ceres/internal/ceres/graph.h | 2 +- .../ceres/implicit_schur_complement.cc | 23 +- .../ceres/implicit_schur_complement.h | 10 +- .../iterative_schur_complement_solver.cc | 11 +- .../internal/ceres/levenberg_marquardt.cc | 574 --- .../ceres/levenberg_marquardt_strategy.cc | 144 + .../ceres/levenberg_marquardt_strategy.h | 86 + .../ceres/linear_least_squares_problems.cc | 103 +- .../ceres/internal/ceres/linear_solver.cc | 30 +- .../ceres/internal/ceres/linear_solver.h | 26 +- .../internal/ceres/local_parameterization.cc | 5 +- .../ceres/internal/ceres/loss_function.cc | 64 + .../ceres/internal/ceres/matrix_proto.h | 2 +- .../ceres/internal/ceres/minimizer.h | 68 +- .../third_party/ceres/internal/ceres/mutex.h | 98 +- .../ceres/internal/ceres/normal_prior.cc | 3 +- .../ceres/internal/ceres/parameter_block.h | 19 +- .../internal/ceres/partitioned_matrix_view.cc | 2 +- .../ceres/internal/ceres/polynomial_solver.cc | 184 + .../ceres/internal/ceres/polynomial_solver.h | 65 + .../ceres/internal/ceres/problem_impl.cc | 9 +- .../ceres/internal/ceres/problem_impl.h | 2 +- .../ceres/internal/ceres/program.cc | 79 +- .../ceres/internal/ceres/program.h | 21 +- .../ceres/internal/ceres/program_evaluator.h | 84 +- .../third_party/ceres/internal/ceres/random.h | 29 +- .../ceres/internal/ceres/residual_block.cc | 7 +- .../internal/ceres/residual_block_utils.cc | 41 +- .../internal/ceres/residual_block_utils.h | 9 - .../runtime_numeric_diff_cost_function.cc | 3 +- .../internal/ceres/schur_complement_solver.cc | 159 +- .../internal/ceres/schur_complement_solver.h | 40 +- .../internal/ceres/schur_eliminator_impl.h | 38 +- .../ceres/internal/ceres/schur_ordering.cc | 18 +- .../ceres/internal/ceres/solver.cc | 52 +- .../ceres/internal/ceres/solver_impl.cc | 286 +- .../ceres/internal/ceres/solver_impl.h | 14 +- .../ceres/internal/ceres/sparse_matrix.h | 2 +- .../ceres/sparse_normal_cholesky_solver.cc | 166 +- .../ceres/sparse_normal_cholesky_solver.h | 38 +- .../third_party/ceres/internal/ceres/split.cc | 1 + .../third_party/ceres/internal/ceres/split.h | 21 + .../ceres/internal/ceres/stringprintf.cc | 1 + .../ceres/internal/ceres/stringprintf.h | 14 +- .../ceres/internal/ceres/suitesparse.cc | 157 +- .../ceres/internal/ceres/suitesparse.h | 82 +- .../internal/ceres/triplet_sparse_matrix.cc | 10 +- .../internal/ceres/triplet_sparse_matrix.h | 4 +- .../internal/ceres/trust_region_minimizer.cc | 550 +++ .../internal/ceres/trust_region_minimizer.h | 67 + .../internal/ceres/trust_region_strategy.cc | 27 + .../internal/ceres/trust_region_strategy.h | 148 + .../third_party/ceres/internal/ceres/types.cc | 35 +- .../ceres/internal/ceres/visibility.cc | 4 +- .../ceres/visibility_based_preconditioner.cc | 36 +- .../ceres/visibility_based_preconditioner.h | 14 +- .../patches/collections_port.h.mingw.patch | 12 +- .../ceres/patches/msvc_glog_fix.patch | 50 + .../ceres/patches/msvc_isfinite.patch | 15 - .../patches/no_previous_declaration_fix.patch | 199 ++ extern/libmv/third_party/ceres/patches/series | 4 +- .../Recast/Source/RecastMeshDetail.cpp | 2 +- intern/CMakeLists.txt | 5 - intern/SConscript | 5 +- intern/audaspace/CMakeLists.txt | 2 + .../audaspace/FX/AUD_ButterworthFactory.cpp | 10 +- intern/audaspace/FX/AUD_DelayReader.cpp | 4 +- intern/audaspace/FX/AUD_HighpassFactory.cpp | 4 +- intern/audaspace/FX/AUD_IIRFilterReader.cpp | 2 +- intern/audaspace/OpenAL/AUD_OpenALDevice.cpp | 323 +- intern/audaspace/Python/AUD_PyAPI.cpp | 132 +- intern/audaspace/Python/AUD_PyAPI.h | 8 +- intern/audaspace/fftw/AUD_BandPassFactory.h | 2 +- .../intern/AUD_AnimateableProperty.cpp | 14 +- .../intern/AUD_AnimateableProperty.h | 7 +- intern/audaspace/intern/AUD_C-API.cpp | 6 +- .../intern/AUD_ChannelMapperReader.cpp | 50 +- intern/audaspace/intern/AUD_IDevice.h | 3 +- intern/audaspace/intern/AUD_IFactory.h | 2 +- intern/audaspace/intern/AUD_ILockable.h | 21 + intern/audaspace/intern/AUD_IReader.h | 2 +- intern/audaspace/intern/AUD_IWriter.h | 2 +- intern/audaspace/intern/AUD_MutexLock.h | 24 + intern/audaspace/intern/AUD_PyInit.h | 4 +- .../audaspace/intern/AUD_SequencerEntry.cpp | 53 +- intern/audaspace/intern/AUD_SequencerEntry.h | 7 +- .../audaspace/intern/AUD_SequencerFactory.cpp | 33 +- .../audaspace/intern/AUD_SequencerFactory.h | 7 +- .../audaspace/intern/AUD_SequencerHandle.cpp | 8 +- .../audaspace/intern/AUD_SequencerReader.cpp | 5 +- .../audaspace/intern/AUD_SoftwareDevice.cpp | 97 +- intern/bsp/CMakeLists.txt | 5 +- intern/bsp/extern/CSG_BooleanOps.h | 8 +- intern/bsp/intern/BOP_CarveInterface.cpp | 12 +- intern/container/CMakeLists.txt | 5 +- intern/container/CTR_HashedPtr.h | 23 +- intern/container/CTR_List.h | 112 - intern/container/CTR_Map.h | 84 +- intern/container/CTR_TaggedIndex.h | 15 +- intern/container/CTR_TaggedSetOps.h | 61 +- intern/container/CTR_UHeap.h | 307 -- intern/container/intern/CTR_List.cpp | 127 - intern/cycles/CMakeLists.txt | 5 +- intern/cycles/SConscript | 2 +- intern/cycles/app/CMakeLists.txt | 3 + intern/cycles/app/cycles_xml.cpp | 1 + intern/cycles/blender/CMakeLists.txt | 2 + intern/cycles/blender/addon/__init__.py | 10 +- intern/cycles/blender/addon/engine.py | 1 + intern/cycles/blender/addon/enums.py | 1 + intern/cycles/blender/addon/osl.py | 127 + intern/cycles/blender/addon/properties.py | 39 +- intern/cycles/blender/addon/ui.py | 54 +- intern/cycles/blender/blender_camera.cpp | 55 +- intern/cycles/blender/blender_mesh.cpp | 189 +- intern/cycles/blender/blender_object.cpp | 67 +- intern/cycles/blender/blender_particles.cpp | 93 +- intern/cycles/blender/blender_python.cpp | 178 +- intern/cycles/blender/blender_session.cpp | 55 +- intern/cycles/blender/blender_shader.cpp | 126 +- intern/cycles/blender/blender_sync.cpp | 34 +- intern/cycles/blender/blender_sync.h | 5 +- intern/cycles/blender/blender_util.h | 53 +- intern/cycles/bvh/CMakeLists.txt | 4 + intern/cycles/bvh/bvh_node.h | 2 +- intern/cycles/device/CMakeLists.txt | 4 + intern/cycles/device/device.cpp | 26 +- intern/cycles/device/device.h | 9 +- intern/cycles/device/device_cpu.cpp | 43 +- intern/cycles/device/device_cuda.cpp | 31 +- intern/cycles/device/device_intern.h | 10 +- intern/cycles/device/device_multi.cpp | 18 +- intern/cycles/device/device_network.cpp | 8 +- intern/cycles/device/device_opencl.cpp | 22 +- intern/cycles/device/device_task.h | 1 + intern/cycles/kernel/CMakeLists.txt | 39 +- intern/cycles/kernel/{svm => closure}/bsdf.h | 6 +- .../{svm => closure}/bsdf_ashikhmin_velvet.h | 50 +- .../kernel/{svm => closure}/bsdf_diffuse.h | 68 +- .../kernel/{svm => closure}/bsdf_microfacet.h | 178 +- .../kernel/{svm => closure}/bsdf_oren_nayar.h | 37 +- .../kernel/{svm => closure}/bsdf_reflection.h | 31 +- .../kernel/{svm => closure}/bsdf_refraction.h | 27 +- .../{svm => closure}/bsdf_transparent.h | 21 +- .../kernel/{svm => closure}/bsdf_ward.h | 73 +- .../kernel/{svm => closure}/bsdf_westin.h | 87 +- .../cycles/kernel/{svm => closure}/emissive.h | 12 +- .../cycles/kernel/{svm => closure}/volume.h | 20 +- intern/cycles/kernel/kernel_attribute.h | 2 +- intern/cycles/kernel/kernel_bvh.h | 173 +- intern/cycles/kernel/kernel_camera.h | 34 +- intern/cycles/kernel/kernel_displace.h | 3 + intern/cycles/kernel/kernel_emission.h | 7 + intern/cycles/kernel/kernel_light.h | 9 +- intern/cycles/kernel/kernel_mbvh.h | 394 --- intern/cycles/kernel/kernel_montecarlo.h | 19 +- intern/cycles/kernel/kernel_object.h | 136 +- intern/cycles/kernel/kernel_passes.h | 14 +- intern/cycles/kernel/kernel_path.h | 16 +- intern/cycles/kernel/kernel_qbvh.h | 413 --- intern/cycles/kernel/kernel_shader.h | 76 +- intern/cycles/kernel/kernel_triangle.h | 15 +- intern/cycles/kernel/kernel_types.h | 44 +- intern/cycles/kernel/osl/CMakeLists.txt | 19 +- intern/cycles/kernel/osl/background.cpp | 40 +- .../kernel/osl/bsdf_ashikhmin_velvet.cpp | 179 - intern/cycles/kernel/osl/bsdf_diffuse.cpp | 187 - intern/cycles/kernel/osl/bsdf_microfacet.cpp | 542 --- intern/cycles/kernel/osl/bsdf_oren_nayar.cpp | 138 - intern/cycles/kernel/osl/bsdf_phong.cpp | 277 -- intern/cycles/kernel/osl/bsdf_reflection.cpp | 109 - intern/cycles/kernel/osl/bsdf_refraction.cpp | 121 - intern/cycles/kernel/osl/bsdf_transparent.cpp | 98 - intern/cycles/kernel/osl/bsdf_ward.cpp | 226 -- intern/cycles/kernel/osl/bsdf_westin.cpp | 243 -- intern/cycles/kernel/osl/bssrdf.cpp | 106 - intern/cycles/kernel/osl/debug.cpp | 81 - intern/cycles/kernel/osl/emissive.cpp | 50 +- .../kernel/osl/nodes/node_voronoi_texture.osl | 81 - intern/cycles/kernel/osl/osl_closures.cpp | 148 +- intern/cycles/kernel/osl/osl_closures.h | 173 +- intern/cycles/kernel/osl/osl_services.cpp | 299 +- intern/cycles/kernel/osl/osl_services.h | 3 + intern/cycles/kernel/osl/osl_shader.cpp | 82 +- intern/cycles/kernel/osl/osl_shader.h | 3 +- intern/cycles/kernel/osl/vol_subsurface.cpp | 137 - .../{osl/nodes => shaders}/CMakeLists.txt | 13 +- .../nodes => shaders}/node_add_closure.osl | 0 .../{osl/nodes => shaders}/node_attribute.osl | 4 +- .../nodes => shaders}/node_background.osl | 2 +- .../nodes => shaders}/node_brick_texture.osl | 21 +- .../nodes => shaders}/node_brightness.osl | 12 +- .../{osl/nodes => shaders}/node_bump.osl | 21 +- .../{osl/nodes => shaders}/node_camera.osl | 0 .../node_checker_texture.osl | 12 +- .../{osl/nodes => shaders}/node_color.h | 0 .../nodes => shaders}/node_combine_rgb.osl | 0 .../node_convert_from_color.osl | 4 +- .../node_convert_from_float.osl | 2 + .../node_convert_from_int.osl} | 22 +- .../node_convert_from_normal.osl | 4 +- .../node_convert_from_point.osl | 4 +- .../node_convert_from_vector.osl | 4 +- .../nodes => shaders}/node_diffuse_bsdf.osl | 2 +- .../{osl/nodes => shaders}/node_emission.osl | 6 +- .../node_environment_texture.osl | 2 +- .../{osl/nodes => shaders}/node_fresnel.h | 0 .../{osl/nodes => shaders}/node_fresnel.osl | 2 +- .../{osl/nodes => shaders}/node_gamma.osl | 0 .../{osl/nodes => shaders}/node_geometry.osl | 28 +- .../nodes => shaders}/node_glass_bsdf.osl | 16 +- .../nodes => shaders}/node_glossy_bsdf.osl | 12 +- .../node_gradient_texture.osl | 37 +- .../{osl/nodes => shaders}/node_holdout.osl | 0 .../{osl/nodes => shaders}/node_hsv.osl | 0 .../kernel/shaders/node_image_texture.osl | 120 + .../{osl/nodes => shaders}/node_invert.osl | 0 .../node_layer_weight.osl} | 22 +- .../kernel/shaders/node_light_falloff.osl | 46 + .../nodes => shaders}/node_light_path.osl | 5 +- .../nodes => shaders}/node_magic_texture.osl | 91 +- .../{osl/nodes => shaders}/node_mapping.osl | 6 +- .../{osl/nodes => shaders}/node_math.osl | 46 +- .../{osl/nodes => shaders}/node_mix.osl | 150 +- .../nodes => shaders}/node_mix_closure.osl | 2 +- .../node_musgrave_texture.osl | 72 +- .../nodes => shaders}/node_noise_texture.osl | 6 +- .../{osl/nodes => shaders}/node_normal.osl | 0 .../nodes => shaders}/node_object_info.osl | 17 +- .../node_output_displacement.osl | 2 +- .../nodes => shaders}/node_output_surface.osl | 0 .../nodes => shaders}/node_output_volume.osl | 0 .../nodes => shaders}/node_particle_info.osl | 17 +- .../cycles/kernel/shaders/node_rgb_ramp.osl | 43 + .../nodes => shaders}/node_separate_rgb.osl | 0 .../node_set_normal.osl} | 14 +- .../nodes => shaders}/node_sky_texture.osl | 64 +- .../{osl/nodes => shaders}/node_texture.h | 16 +- .../node_texture_coordinate.osl | 37 +- .../node_translucent_bsdf.osl | 2 +- .../node_transparent_bsdf.osl | 2 +- .../{osl/nodes => shaders}/node_value.osl | 0 .../nodes => shaders}/node_vector_math.osl | 16 +- .../nodes => shaders}/node_velvet_bsdf.osl | 2 +- .../kernel/shaders/node_voronoi_texture.osl | 48 + .../cycles/kernel/shaders/node_ward_bsdf.osl | 51 + .../nodes => shaders}/node_wave_texture.osl | 14 +- .../kernel/{osl/nodes => shaders}/oslutil.h | 3 + .../kernel/{osl/nodes => shaders}/stdosl.h | 71 +- intern/cycles/kernel/svm/svm.h | 34 +- intern/cycles/kernel/svm/svm_bsdf.h | 102 +- intern/cycles/kernel/svm/svm_closure.h | 113 +- intern/cycles/kernel/svm/svm_convert.h | 28 +- intern/cycles/kernel/svm/svm_displace.h | 26 +- intern/cycles/kernel/svm/svm_fresnel.h | 2 +- intern/cycles/kernel/svm/svm_geometry.h | 43 +- intern/cycles/kernel/svm/svm_hsv.h | 4 +- intern/cycles/kernel/svm/svm_image.h | 8 +- intern/cycles/kernel/svm/svm_noise.h | 2 +- intern/cycles/kernel/svm/svm_tex_coord.h | 24 + intern/cycles/kernel/svm/svm_types.h | 23 +- intern/cycles/render/CMakeLists.txt | 4 + intern/cycles/render/attribute.cpp | 2 + intern/cycles/render/buffers.cpp | 15 +- intern/cycles/render/camera.cpp | 24 +- intern/cycles/render/camera.h | 1 + intern/cycles/render/graph.cpp | 90 +- intern/cycles/render/graph.h | 3 + intern/cycles/render/image.cpp | 42 +- intern/cycles/render/image.h | 5 +- intern/cycles/render/integrator.cpp | 2 + intern/cycles/render/light.cpp | 5 +- intern/cycles/render/mesh.cpp | 18 +- intern/cycles/render/nodes.cpp | 223 +- intern/cycles/render/nodes.h | 23 +- intern/cycles/render/object.cpp | 38 +- intern/cycles/render/object.h | 5 +- intern/cycles/render/osl.cpp | 482 ++- intern/cycles/render/osl.h | 36 +- intern/cycles/render/scene.cpp | 4 +- intern/cycles/render/scene.h | 2 +- intern/cycles/render/session.cpp | 148 +- intern/cycles/render/session.h | 28 +- intern/cycles/render/shader.cpp | 33 + intern/cycles/render/shader.h | 17 + intern/cycles/render/svm.cpp | 70 +- intern/cycles/render/tile.cpp | 133 +- intern/cycles/render/tile.h | 45 +- intern/cycles/subd/CMakeLists.txt | 5 + intern/cycles/subd/subd_build.cpp | 2 +- intern/cycles/util/CMakeLists.txt | 4 + intern/cycles/util/util_attribute.cpp | 2 + intern/cycles/util/util_cuda.cpp | 15 +- intern/cycles/util/util_math.h | 27 +- intern/cycles/util/util_md5.h | 2 +- intern/cycles/util/util_path.cpp | 10 +- intern/cycles/util/util_path.h | 3 + intern/cycles/util/util_progress.h | 40 +- intern/cycles/util/util_stats.h | 53 + intern/cycles/util/util_task.cpp | 33 +- intern/cycles/util/util_task.h | 1 + intern/cycles/util/util_thread.h | 4 + intern/cycles/util/util_transform.cpp | 3 +- intern/cycles/util/util_transform.h | 45 +- intern/cycles/util/util_types.h | 1 + intern/decimation/CMakeLists.txt | 63 - intern/decimation/SConscript | 8 - intern/decimation/extern/LOD_decimation.h | 117 - .../decimation/intern/LOD_DecimationClass.h | 118 - .../decimation/intern/LOD_EdgeCollapser.cpp | 410 --- intern/decimation/intern/LOD_EdgeCollapser.h | 117 - .../intern/LOD_ExternBufferEditor.h | 164 - .../intern/LOD_ExternNormalEditor.cpp | 264 -- .../intern/LOD_ExternNormalEditor.h | 135 - .../intern/LOD_FaceNormalEditor.cpp | 291 -- .../decimation/intern/LOD_FaceNormalEditor.h | 144 - intern/decimation/intern/LOD_ManMesh2.cpp | 618 ---- intern/decimation/intern/LOD_ManMesh2.h | 265 -- intern/decimation/intern/LOD_MeshBounds.h | 133 - .../decimation/intern/LOD_MeshPrimitives.cpp | 404 --- intern/decimation/intern/LOD_MeshPrimitives.h | 221 -- intern/decimation/intern/LOD_QSDecimator.cpp | 327 -- intern/decimation/intern/LOD_QSDecimator.h | 129 - intern/decimation/intern/LOD_Quadric.h | 167 - .../decimation/intern/LOD_QuadricEditor.cpp | 279 -- intern/decimation/intern/LOD_QuadricEditor.h | 120 - intern/decimation/intern/LOD_decimation.cpp | 155 - intern/dualcon/CMakeLists.txt | 5 +- intern/dualcon/intern/Projections.cpp | 4 +- intern/dualcon/intern/dualcon_c_api.cpp | 2 +- intern/dualcon/intern/octree.cpp | 179 +- intern/dualcon/intern/octree.h | 299 +- intern/elbeem/intern/ntl_geometryshader.h | 2 +- intern/elbeem/intern/utilities.cpp | 2 +- intern/ffmpeg/ffmpeg_compat.h | 2 +- intern/ghost/GHOST_C-api.h | 3 +- intern/ghost/GHOST_IEventConsumer.h | 13 +- intern/ghost/GHOST_ISystem.h | 108 +- intern/ghost/GHOST_IWindow.h | 96 +- intern/ghost/GHOST_Rect.h | 69 +- intern/ghost/GHOST_Types.h | 4 +- intern/ghost/intern/GHOST_C-api.cpp | 14 +- intern/ghost/intern/GHOST_Debug.h | 4 +- .../ghost/intern/GHOST_DisplayManagerCocoa.mm | 2 +- .../ghost/intern/GHOST_DisplayManagerX11.cpp | 10 +- intern/ghost/intern/GHOST_EventDragnDrop.h | 14 +- intern/ghost/intern/GHOST_EventManager.cpp | 12 +- intern/ghost/intern/GHOST_NDOFManager.h | 2 +- intern/ghost/intern/GHOST_Rect.cpp | 2 +- intern/ghost/intern/GHOST_System.h | 2 +- intern/ghost/intern/GHOST_SystemCarbon.cpp | 2 +- intern/ghost/intern/GHOST_SystemCocoa.mm | 116 +- intern/ghost/intern/GHOST_SystemPaths.h | 4 +- intern/ghost/intern/GHOST_SystemWin32.cpp | 2 - intern/ghost/intern/GHOST_SystemX11.cpp | 33 +- intern/ghost/intern/GHOST_SystemX11.h | 8 +- intern/ghost/intern/GHOST_TimerManager.cpp | 6 +- intern/ghost/intern/GHOST_Window.cpp | 10 +- intern/ghost/intern/GHOST_Window.h | 8 +- intern/ghost/intern/GHOST_WindowCocoa.mm | 40 +- intern/ghost/intern/GHOST_WindowManager.cpp | 4 +- intern/ghost/intern/GHOST_WindowWin32.cpp | 2 +- intern/ghost/intern/GHOST_WindowX11.cpp | 4 +- intern/ghost/test/multitest/EventToBuf.c | 21 +- intern/ghost/test/multitest/MultiTest.c | 5 +- intern/guardedalloc/test/simpletest/memtest.c | 9 +- intern/iksolver/intern/IK_QJacobianSolver.h | 4 +- intern/iksolver/intern/IK_QSegment.h | 4 +- intern/iksolver/intern/IK_QTask.h | 4 +- intern/iksolver/intern/IK_Solver.cpp | 6 +- intern/iksolver/intern/MT_ExpMap.h | 4 +- intern/iksolver/intern/TNT/cmat.h | 2 +- intern/iksolver/intern/TNT/vec.h | 2 +- intern/itasc/CMakeLists.txt | 424 +-- intern/itasc/Scene.cpp | 2 +- intern/itasc/kdl/utilities/utility_io.cpp | 6 +- intern/memutil/MEM_CacheLimiter.h | 69 +- intern/memutil/MEM_CacheLimiterC-Api.h | 4 +- intern/memutil/MEM_SmartPtr.h | 6 +- .../memutil/intern/MEM_CacheLimiterC-Api.cpp | 12 +- intern/mikktspace/mikktspace.c | 3 + intern/opencolorio/CMakeLists.txt | 51 +- intern/opencolorio/SConscript | 10 +- intern/opencolorio/ocio_capi.h | 130 +- intern/opennl/CMakeLists.txt | 3 +- intern/opennl/SConscript | 5 +- intern/opennl/intern/opennl.c | 15 +- intern/opennl/superlu/get_perm_c.c | 52 +- intern/raskter/CMakeLists.txt | 3 - intern/raskter/raskter.c | 1840 ++-------- intern/raskter/raskter.h | 70 +- intern/raskter/raskter_kdtree.c | 836 ----- intern/raskter/raskter_kdtree.h | 129 - intern/raskter/raskter_mt.c | 290 -- intern/smoke/CMakeLists.txt | 4 +- intern/smoke/extern/smoke_API.h | 51 +- intern/smoke/intern/FLUID_3D.cpp | 513 ++- intern/smoke/intern/FLUID_3D.h | 46 +- intern/smoke/intern/FLUID_3D_SOLVERS.cpp | 1 - intern/smoke/intern/FLUID_3D_STATIC.cpp | 28 - intern/smoke/intern/WTURBULENCE.cpp | 151 +- intern/smoke/intern/WTURBULENCE.h | 19 +- intern/smoke/intern/smoke_API.cpp | 414 ++- intern/smoke/intern/spectrum.cpp | 426 +++ intern/smoke/intern/spectrum.h | 6 + intern/string/STR_String.h | 24 +- intern/string/intern/STR_String.cpp | 1 - intern/utfconv/utfconv.h | 2 +- release/datafiles/blender_icons.png | Bin 227018 -> 228428 bytes release/datafiles/colormanagement/config.ocio | 31 +- release/datafiles/prvicons.png | Bin 12311 -> 14130 bytes release/datafiles/splash.png | Bin 109883 -> 212426 bytes release/datafiles/startup.blend | Bin 400648 -> 408072 bytes release/scripts/modules/addon_utils.py | 11 +- .../modules/bl_i18n_utils/bl_process_msg.py | 74 +- .../scripts/modules/bl_i18n_utils/check_po.py | 6 +- .../bl_i18n_utils/import_po_from_branches.py | 4 +- .../modules/bl_i18n_utils/rtl_preprocess.py | 37 +- .../scripts/modules/bl_i18n_utils/settings.py | 151 +- .../bl_i18n_utils/spell_check_utils.py | 19 +- .../modules/bl_i18n_utils/update_branches.py | 17 +- .../bl_i18n_utils/update_languages_menu.py | 148 + .../modules/bl_i18n_utils/update_mo.py | 5 +- .../modules/bl_i18n_utils/update_pot.py | 59 +- .../modules/bl_i18n_utils/update_trunk.py | 66 +- .../scripts/modules/bl_i18n_utils/utils.py | 10 +- release/scripts/modules/bpy/path.py | 4 +- release/scripts/modules/bpy/utils.py | 5 +- .../scripts/modules/bpy_extras/mesh_utils.py | 2 +- .../modules/bpy_extras/object_utils.py | 13 + release/scripts/modules/bpy_types.py | 8 +- release/scripts/modules/bpyml.py | 2 +- release/scripts/modules/console_python.py | 10 +- release/scripts/modules/console_shell.py | 4 +- release/scripts/modules/rna_info.py | 4 +- release/scripts/modules/rna_xml.py | 7 +- .../presets/interface_theme/back_to_black.xml | 1 + .../presets/interface_theme/blender_24x.xml | 1 + .../presets/interface_theme/elsyiun.xml | 3 +- .../presets/interface_theme/hexagon.xml | 1 + .../interface_theme/ubuntu_ambiance.xml | 219 +- release/scripts/presets/keyconfig/maya.py | 16 +- .../tracking_settings/blurry_footage.py | 2 +- .../presets/tracking_settings/default.py | 2 +- .../presets/tracking_settings/fast_motion.py | 2 +- .../presets/tracking_settings/planar.py | 2 +- .../startup/bl_operators/add_mesh_torus.py | 14 +- release/scripts/startup/bl_operators/anim.py | 10 +- release/scripts/startup/bl_operators/clip.py | 14 +- .../scripts/startup/bl_operators/console.py | 2 +- release/scripts/startup/bl_operators/mesh.py | 2 +- release/scripts/startup/bl_operators/node.py | 42 +- .../scripts/startup/bl_operators/object.py | 12 +- .../bl_operators/object_quick_effects.py | 63 +- .../scripts/startup/bl_operators/presets.py | 32 +- .../bl_operators/screen_play_rendered_anim.py | 2 +- release/scripts/startup/bl_operators/wm.py | 35 +- release/scripts/startup/bl_ui/__init__.py | 13 +- .../startup/bl_ui/properties_animviz.py | 7 +- .../startup/bl_ui/properties_data_armature.py | 7 +- .../startup/bl_ui/properties_data_bone.py | 32 +- .../startup/bl_ui/properties_data_camera.py | 12 +- .../startup/bl_ui/properties_data_lamp.py | 2 +- .../startup/bl_ui/properties_data_mesh.py | 21 + .../startup/bl_ui/properties_data_modifier.py | 45 +- .../scripts/startup/bl_ui/properties_game.py | 8 + .../startup/bl_ui/properties_material.py | 2 + .../startup/bl_ui/properties_object.py | 8 +- .../bl_ui/properties_object_constraint.py | 5 +- .../startup/bl_ui/properties_particle.py | 33 +- .../startup/bl_ui/properties_physics_cloth.py | 10 +- .../bl_ui/properties_physics_common.py | 8 +- .../bl_ui/properties_physics_dynamicpaint.py | 9 +- .../startup/bl_ui/properties_physics_field.py | 15 +- .../startup/bl_ui/properties_physics_smoke.py | 183 +- .../bl_ui/properties_physics_softbody.py | 8 +- .../startup/bl_ui/properties_render.py | 27 +- .../scripts/startup/bl_ui/properties_scene.py | 2 + .../startup/bl_ui/properties_texture.py | 27 +- release/scripts/startup/bl_ui/space_clip.py | 52 +- .../scripts/startup/bl_ui/space_console.py | 2 +- .../scripts/startup/bl_ui/space_dopesheet.py | 8 +- .../startup/bl_ui/space_filebrowser.py | 1 + release/scripts/startup/bl_ui/space_graph.py | 4 +- release/scripts/startup/bl_ui/space_info.py | 57 +- release/scripts/startup/bl_ui/space_logic.py | 5 + release/scripts/startup/bl_ui/space_node.py | 8 + .../scripts/startup/bl_ui/space_sequencer.py | 50 +- release/scripts/startup/bl_ui/space_text.py | 27 +- release/scripts/startup/bl_ui/space_time.py | 5 + .../scripts/startup/bl_ui/space_userpref.py | 28 +- .../startup/bl_ui/space_userpref_keymap.py | 8 +- release/scripts/startup/bl_ui/space_view3d.py | 62 +- .../startup/bl_ui/space_view3d_toolbar.py | 21 +- .../scripts/startup/keyingsets_builtins.py | 4 +- release/scripts/templates/addon_add_object.py | 4 +- release/scripts/templates/script_stub.py | 11 + release/scripts/templates/ui_panel.py | 59 +- release/scripts/templates/ui_panel_simple.py | 3 + release/text/readme.html | 2 +- release/windows/contrib/vfapi/vfapi-plugin.c | 55 +- source/blender/CMakeLists.txt | 5 +- source/blender/avi/AVI_avi.h | 2 +- source/blender/avi/CMakeLists.txt | 20 +- source/blender/avi/intern/avi.c | 23 +- .../avi/intern/{codecs.c => avi_codecs.c} | 8 +- .../avi/intern/{endian.c => avi_endian.c} | 38 +- .../avi/intern/{endian.h => avi_endian.h} | 12 +- .../avi/intern/{mjpeg.c => avi_mjpeg.c} | 24 +- .../avi/intern/{mjpeg.h => avi_mjpeg.h} | 5 +- .../avi/intern/{options.c => avi_options.c} | 4 +- .../avi/intern/{avirgb.c => avi_rgb.c} | 10 +- .../avi/intern/{avirgb.h => avi_rgb.h} | 9 +- .../avi/intern/{rgb32.c => avi_rgb32.c} | 9 +- .../avi/intern/{rgb32.h => avi_rgb32.h} | 9 +- source/blender/blenfont/BLF_api.h | 1 + source/blender/blenfont/BLF_translation.h | 9 + source/blender/blenfont/CMakeLists.txt | 2 + source/blender/blenfont/SConscript | 3 +- source/blender/blenfont/intern/blf.c | 118 +- source/blender/blenfont/intern/blf_font.c | 10 +- source/blender/blenfont/intern/blf_glyph.c | 2 +- source/blender/blenfont/intern/blf_lang.c | 341 +- source/blender/blenkernel/BKE_DerivedMesh.h | 16 +- source/blender/blenkernel/BKE_action.h | 2 +- source/blender/blenkernel/BKE_anim.h | 4 +- source/blender/blenkernel/BKE_armature.h | 11 +- source/blender/blenkernel/BKE_blender.h | 11 +- source/blender/blenkernel/BKE_bmesh.h | 4 +- source/blender/blenkernel/BKE_cdderivedmesh.h | 4 +- source/blender/blenkernel/BKE_colortools.h | 7 +- source/blender/blenkernel/BKE_curve.h | 4 +- source/blender/blenkernel/BKE_customdata.h | 16 +- source/blender/blenkernel/BKE_deform.h | 1 + source/blender/blenkernel/BKE_global.h | 15 +- source/blender/blenkernel/BKE_gpencil.h | 4 +- source/blender/blenkernel/BKE_group.h | 4 - source/blender/blenkernel/BKE_idprop.h | 29 +- source/blender/blenkernel/BKE_image.h | 3 +- source/blender/blenkernel/BKE_key.h | 52 +- source/blender/blenkernel/BKE_lattice.h | 2 +- source/blender/blenkernel/BKE_library.h | 1 + source/blender/blenkernel/BKE_main.h | 2 +- source/blender/blenkernel/BKE_mball.h | 6 +- source/blender/blenkernel/BKE_mesh.h | 9 +- source/blender/blenkernel/BKE_modifier.h | 1 + source/blender/blenkernel/BKE_multires.h | 3 +- .../blenkernel/BKE_navmesh_conversion.h | 2 +- source/blender/blenkernel/BKE_node.h | 27 +- source/blender/blenkernel/BKE_object.h | 4 +- source/blender/blenkernel/BKE_paint.h | 1 + source/blender/blenkernel/BKE_particle.h | 21 +- source/blender/blenkernel/BKE_pointcache.h | 2 +- source/blender/blenkernel/BKE_property.h | 27 +- source/blender/blenkernel/BKE_sca.h | 2 + source/blender/blenkernel/BKE_scene.h | 8 +- source/blender/blenkernel/BKE_sequencer.h | 40 +- source/blender/blenkernel/BKE_smoke.h | 6 +- source/blender/blenkernel/BKE_subsurf.h | 8 +- source/blender/blenkernel/BKE_tracking.h | 4 +- source/blender/blenkernel/BKE_utildefines.h | 2 +- source/blender/blenkernel/CMakeLists.txt | 18 +- source/blender/blenkernel/SConscript | 2 +- source/blender/blenkernel/depsgraph_private.h | 2 +- source/blender/blenkernel/intern/CCGSubSurf.c | 6 +- .../blender/blenkernel/intern/DerivedMesh.c | 190 +- source/blender/blenkernel/intern/action.c | 489 +-- source/blender/blenkernel/intern/anim.c | 119 +- source/blender/blenkernel/intern/anim_sys.c | 16 +- source/blender/blenkernel/intern/armature.c | 27 +- source/blender/blenkernel/intern/blender.c | 22 +- source/blender/blenkernel/intern/bmfont.c | 4 +- source/blender/blenkernel/intern/boids.c | 30 +- .../blenkernel/intern/booleanops_mesh.c | 12 +- source/blender/blenkernel/intern/brush.c | 52 +- source/blender/blenkernel/intern/bullet.c | 2 +- source/blender/blenkernel/intern/bvhutils.c | 44 +- source/blender/blenkernel/intern/camera.c | 5 +- .../blender/blenkernel/intern/cdderivedmesh.c | 242 +- source/blender/blenkernel/intern/cloth.c | 41 +- source/blender/blenkernel/intern/collision.c | 31 +- source/blender/blenkernel/intern/colortools.c | 103 +- source/blender/blenkernel/intern/constraint.c | 169 +- source/blender/blenkernel/intern/context.c | 5 +- source/blender/blenkernel/intern/curve.c | 51 +- source/blender/blenkernel/intern/customdata.c | 281 +- source/blender/blenkernel/intern/deform.c | 24 +- source/blender/blenkernel/intern/depsgraph.c | 142 +- source/blender/blenkernel/intern/displist.c | 8 +- .../blender/blenkernel/intern/dynamicpaint.c | 97 +- .../blenkernel/intern/editderivedmesh.c | 2 +- source/blender/blenkernel/intern/effect.c | 50 +- source/blender/blenkernel/intern/fcurve.c | 34 +- source/blender/blenkernel/intern/fluidsim.c | 36 +- source/blender/blenkernel/intern/fmodifier.c | 17 +- source/blender/blenkernel/intern/font.c | 30 +- source/blender/blenkernel/intern/gpencil.c | 14 +- source/blender/blenkernel/intern/group.c | 66 +- source/blender/blenkernel/intern/icons.c | 4 +- source/blender/blenkernel/intern/idprop.c | 123 +- source/blender/blenkernel/intern/image.c | 95 +- source/blender/blenkernel/intern/image_gen.c | 2 +- source/blender/blenkernel/intern/implicit.c | 153 +- source/blender/blenkernel/intern/ipo.c | 28 +- source/blender/blenkernel/intern/key.c | 121 +- source/blender/blenkernel/intern/lattice.c | 45 +- source/blender/blenkernel/intern/library.c | 24 +- source/blender/blenkernel/intern/mask.c | 43 +- .../blender/blenkernel/intern/mask_evaluate.c | 6 +- .../blenkernel/intern/mask_rasterize.c | 36 +- source/blender/blenkernel/intern/material.c | 42 +- source/blender/blenkernel/intern/mball.c | 60 +- source/blender/blenkernel/intern/mesh.c | 112 +- .../blender/blenkernel/intern/mesh_validate.c | 11 +- source/blender/blenkernel/intern/modifier.c | 49 +- .../blenkernel/intern/modifiers_bmesh.c | 32 +- source/blender/blenkernel/intern/movieclip.c | 74 +- source/blender/blenkernel/intern/multires.c | 32 +- .../blenkernel/intern/navmesh_conversion.c | 336 +- source/blender/blenkernel/intern/nla.c | 14 +- source/blender/blenkernel/intern/node.c | 122 +- source/blender/blenkernel/intern/object.c | 262 +- source/blender/blenkernel/intern/ocean.c | 2 +- source/blender/blenkernel/intern/packedFile.c | 11 +- source/blender/blenkernel/intern/paint.c | 12 +- source/blender/blenkernel/intern/particle.c | 105 +- .../blenkernel/intern/particle_system.c | 146 +- source/blender/blenkernel/intern/pointcache.c | 286 +- source/blender/blenkernel/intern/property.c | 65 +- source/blender/blenkernel/intern/report.c | 48 +- source/blender/blenkernel/intern/sca.c | 29 +- source/blender/blenkernel/intern/scene.c | 57 +- source/blender/blenkernel/intern/seqeffects.c | 24 +- source/blender/blenkernel/intern/sequencer.c | 158 +- source/blender/blenkernel/intern/shrinkwrap.c | 197 +- source/blender/blenkernel/intern/smoke.c | 3120 ++++++++++------- source/blender/blenkernel/intern/softbody.c | 58 +- source/blender/blenkernel/intern/sound.c | 7 +- .../blender/blenkernel/intern/subsurf_ccg.c | 70 +- source/blender/blenkernel/intern/text.c | 71 +- source/blender/blenkernel/intern/texture.c | 25 +- source/blender/blenkernel/intern/tracking.c | 130 +- source/blender/blenkernel/intern/unit.c | 4 +- source/blender/blenkernel/intern/world.c | 2 +- source/blender/blenkernel/intern/writeavi.c | 28 +- .../blender/blenkernel/intern/writeffmpeg.c | 27 +- .../blenkernel/intern/writeframeserver.c | 8 +- source/blender/blenkernel/nla_private.h | 2 +- source/blender/blenlib/BLI_blenlib.h | 2 - source/blender/blenlib/BLI_bpath.h | 2 +- source/blender/blenlib/BLI_dlrbTree.h | 4 +- source/blender/blenlib/BLI_dynstr.h | 7 +- source/blender/blenlib/BLI_endian_switch.h | 38 +- .../blenlib/BLI_endian_switch_inline.h | 80 +- source/blender/blenlib/BLI_fileops.h | 2 + source/blender/blenlib/BLI_fileops_types.h | 2 +- source/blender/blenlib/BLI_heap.h | 8 +- source/blender/blenlib/BLI_kdopbvh.h | 25 +- source/blender/blenlib/BLI_kdtree.h | 2 +- source/blender/blenlib/BLI_lasso.h | 6 +- source/blender/blenlib/BLI_math_base.h | 11 +- source/blender/blenlib/BLI_math_color.h | 2 + source/blender/blenlib/BLI_math_geom.h | 39 +- source/blender/blenlib/BLI_math_matrix.h | 1 + source/blender/blenlib/BLI_math_rotation.h | 4 +- source/blender/blenlib/BLI_math_vector.h | 9 +- source/blender/blenlib/BLI_pbvh.h | 4 +- .../blender/blenlib/BLI_quadric.h | 49 +- source/blender/blenlib/BLI_rand.h | 23 +- source/blender/blenlib/BLI_rect.h | 32 +- source/blender/blenlib/BLI_scanfill.h | 2 +- source/blender/blenlib/BLI_string.h | 26 +- source/blender/blenlib/BLI_string_utf8.h | 13 +- source/blender/blenlib/BLI_utildefines.h | 127 +- source/blender/blenlib/BLI_voronoi.h | 2 +- source/blender/blenlib/CMakeLists.txt | 4 +- source/blender/blenlib/PIL_time.h | 15 +- source/blender/blenlib/intern/BLI_ghash.c | 4 +- source/blender/blenlib/intern/BLI_heap.c | 137 +- source/blender/blenlib/intern/BLI_kdopbvh.c | 214 +- source/blender/blenlib/intern/BLI_kdtree.c | 10 +- source/blender/blenlib/intern/DLRB_tree.c | 4 +- source/blender/blenlib/intern/boxpack2d.c | 16 +- source/blender/blenlib/intern/bpath.c | 20 +- source/blender/blenlib/intern/edgehash.c | 2 +- source/blender/blenlib/intern/fileops.c | 60 +- source/blender/blenlib/intern/freetypefont.c | 29 +- source/blender/blenlib/intern/graph.c | 16 +- source/blender/blenlib/intern/lasso.c | 8 +- source/blender/blenlib/intern/listbase.c | 12 +- .../blender/blenlib/intern/math_base_inline.c | 18 +- .../blenlib/intern/math_color_inline.c | 15 + source/blender/blenlib/intern/math_geom.c | 143 +- .../blender/blenlib/intern/math_geom_inline.c | 20 + source/blender/blenlib/intern/math_matrix.c | 126 +- source/blender/blenlib/intern/math_rotation.c | 61 +- source/blender/blenlib/intern/math_vector.c | 11 +- .../blenlib/intern/math_vector_inline.c | 60 +- source/blender/blenlib/intern/noise.c | 13 +- source/blender/blenlib/intern/path_util.c | 18 +- source/blender/blenlib/intern/pbvh.c | 46 +- source/blender/blenlib/intern/quadric.c | 131 + source/blender/blenlib/intern/rand.c | 72 +- source/blender/blenlib/intern/rct.c | 94 +- source/blender/blenlib/intern/scanfill.c | 12 +- source/blender/blenlib/intern/storage.c | 10 +- source/blender/blenlib/intern/string.c | 46 +- .../blenlib/intern/string_cursor_utf8.c | 2 +- source/blender/blenlib/intern/string_utf8.c | 128 +- source/blender/blenlib/intern/time.c | 2 +- source/blender/blenlib/intern/uvproject.c | 2 +- source/blender/blenlib/intern/voronoi.c | 10 +- source/blender/blenlib/intern/voxel.c | 52 +- source/blender/blenlib/intern/winstuff.c | 4 +- source/blender/blenloader/CMakeLists.txt | 5 + source/blender/blenloader/SConscript | 5 +- .../blender/blenloader/intern/readblenentry.c | 18 +- source/blender/blenloader/intern/readfile.c | 742 +++- source/blender/blenloader/intern/runtime.c | 12 +- .../blenloader/intern/versioning_250.c | 10 +- .../blenloader/intern/versioning_legacy.c | 8 +- source/blender/blenloader/intern/writefile.c | 160 +- source/blender/bmesh/CMakeLists.txt | 20 +- source/blender/bmesh/SConscript | 11 +- source/blender/bmesh/bmesh.h | 1 + source/blender/bmesh/bmesh_class.h | 5 +- source/blender/bmesh/intern/bmesh_construct.c | 13 +- source/blender/bmesh/intern/bmesh_core.c | 69 +- source/blender/bmesh/intern/bmesh_core.h | 4 +- source/blender/bmesh/intern/bmesh_decimate.h | 41 + .../bmesh/intern/bmesh_decimate_collapse.c | 949 +++++ .../bmesh/intern/bmesh_decimate_dissolve.c | 243 ++ .../bmesh/intern/bmesh_decimate_unsubdivide.c | 344 ++ source/blender/bmesh/intern/bmesh_inline.h | 6 + source/blender/bmesh/intern/bmesh_interp.c | 19 +- source/blender/bmesh/intern/bmesh_iterators.c | 148 +- source/blender/bmesh/intern/bmesh_iterators.h | 14 +- source/blender/bmesh/intern/bmesh_marking.c | 5 +- source/blender/bmesh/intern/bmesh_mesh.c | 35 +- source/blender/bmesh/intern/bmesh_mesh_conv.c | 8 +- source/blender/bmesh/intern/bmesh_mods.c | 20 +- source/blender/bmesh/intern/bmesh_opdefines.c | 87 +- .../blender/bmesh/intern/bmesh_operator_api.h | 10 + source/blender/bmesh/intern/bmesh_operators.c | 30 +- source/blender/bmesh/intern/bmesh_operators.h | 7 + .../bmesh/intern/bmesh_operators_private.h | 3 + source/blender/bmesh/intern/bmesh_polygon.c | 12 +- source/blender/bmesh/intern/bmesh_queries.c | 120 + source/blender/bmesh/intern/bmesh_queries.h | 4 + .../blender/bmesh/intern/bmesh_walkers_impl.c | 9 +- source/blender/bmesh/operators/bmo_bevel.c | 10 +- source/blender/bmesh/operators/bmo_connect.c | 16 +- source/blender/bmesh/operators/bmo_create.c | 9 +- source/blender/bmesh/operators/bmo_dissolve.c | 177 +- source/blender/bmesh/operators/bmo_dupe.c | 2 +- source/blender/bmesh/operators/bmo_extrude.c | 122 +- source/blender/bmesh/operators/bmo_hull.c | 533 ++- .../bmesh/operators/bmo_join_triangles.c | 161 +- .../blender/bmesh/operators/bmo_primitive.c | 12 +- .../bmesh/operators/bmo_removedoubles.c | 13 +- source/blender/bmesh/operators/bmo_similar.c | 614 ++++ source/blender/bmesh/operators/bmo_slide.c | 4 +- .../bmesh/operators/bmo_smooth_laplacian.c | 619 ++++ .../blender/bmesh/operators/bmo_subdivide.c | 11 +- .../blender/bmesh/operators/bmo_symmetrize.c | 663 ++++ .../blender/bmesh/operators/bmo_unsubdivide.c | 59 + source/blender/bmesh/operators/bmo_utils.c | 555 +-- source/blender/bmesh/tools/BME_bevel.c | 11 +- source/blender/collada/AnimationExporter.cpp | 22 +- source/blender/collada/AnimationExporter.h | 19 +- source/blender/collada/AnimationImporter.cpp | 25 +- source/blender/collada/AnimationImporter.h | 2 +- source/blender/collada/ArmatureExporter.cpp | 2 +- source/blender/collada/ArmatureImporter.h | 2 +- source/blender/collada/CMakeLists.txt | 2 +- source/blender/collada/DocumentExporter.cpp | 38 +- source/blender/collada/DocumentExporter.h | 2 +- source/blender/collada/DocumentImporter.cpp | 14 +- source/blender/collada/DocumentImporter.h | 5 +- source/blender/collada/EffectExporter.cpp | 6 +- source/blender/collada/GeometryExporter.cpp | 10 +- source/blender/collada/ImageExporter.cpp | 4 +- source/blender/collada/MeshImporter.cpp | 12 +- source/blender/collada/MeshImporter.h | 26 +- source/blender/collada/SceneExporter.cpp | 6 +- source/blender/collada/collada.cpp | 1 + source/blender/collada/collada_internal.h | 1 + source/blender/collada/collada_utils.cpp | 5 +- source/blender/collada/collada_utils.h | 11 +- source/blender/compositor/CMakeLists.txt | 8 +- .../compositor/intern/COM_Converter.cpp | 4 + .../compositor/intern/COM_ExecutionGroup.cpp | 10 +- .../compositor/intern/COM_ExecutionSystem.cpp | 33 +- .../compositor/intern/COM_ExecutionSystem.h | 5 + .../intern/COM_ExecutionSystemHelper.cpp | 7 +- .../compositor/intern/COM_InputSocket.cpp | 11 + .../compositor/intern/COM_InputSocket.h | 18 +- .../compositor/intern/COM_MemoryBuffer.cpp | 6 +- source/blender/compositor/intern/COM_Node.cpp | 10 +- source/blender/compositor/intern/COM_Node.h | 15 +- .../blender/compositor/intern/COM_NodeBase.h | 8 +- .../compositor/intern/COM_NodeOperation.cpp | 10 +- .../compositor/intern/COM_NodeOperation.h | 9 +- .../compositor/intern/COM_OpenCLDevice.cpp | 2 +- .../compositor/intern/COM_OutputSocket.cpp | 10 + .../compositor/intern/COM_OutputSocket.h | 5 +- .../compositor/intern/COM_WorkScheduler.cpp | 13 +- .../compositor/intern/COM_compositor.cpp | 6 +- .../compositor/nodes/COM_ChannelMatteNode.h | 2 +- .../compositor/nodes/COM_ChromaMatteNode.h | 2 +- .../compositor/nodes/COM_ColorBalanceNode.h | 2 +- .../compositor/nodes/COM_ColorMatteNode.h | 2 +- .../compositor/nodes/COM_ColorRampNode.h | 2 +- .../compositor/nodes/COM_ColorSpillNode.h | 2 +- .../compositor/nodes/COM_ConvertAlphaNode.cpp | 2 +- .../blender/compositor/nodes/COM_CropNode.cpp | 2 +- .../nodes/COM_DifferenceMatteNode.h | 2 +- .../compositor/nodes/COM_DilateErodeNode.cpp | 4 +- .../compositor/nodes/COM_DistanceMatteNode.h | 2 +- .../blender/compositor/nodes/COM_FilterNode.h | 6 +- .../nodes/COM_HueSaturationValueNode.cpp | 2 +- .../compositor/nodes/COM_KeyingNode.cpp | 2 +- .../compositor/nodes/COM_LuminanceMatteNode.h | 6 +- .../compositor/nodes/COM_MapValueNode.h | 6 +- .../blender/compositor/nodes/COM_MaskNode.h | 6 +- .../compositor/nodes/COM_MovieClipNode.h | 6 +- .../blender/compositor/nodes/COM_MuteNode.cpp | 10 +- .../blender/compositor/nodes/COM_NormalNode.h | 2 +- .../compositor/nodes/COM_PixelateNode.cpp | 48 + .../compositor/nodes/COM_PixelateNode.h | 38 + .../compositor/nodes/COM_SeparateRGBANode.cpp | 3 + .../compositor/nodes/COM_TransformNode.h | 6 +- .../compositor/nodes/COM_ViewLevelsNode.cpp | 14 + .../compositor/nodes/COM_ViewerNode.cpp | 3 +- .../operations/COM_BokehBlurOperation.h | 5 +- .../operations/COM_ColorSpillOperation.cpp | 2 +- .../COM_ConvertDepthToRadiusOperation.cpp | 4 +- .../operations/COM_CropOperation.cpp | 46 +- .../compositor/operations/COM_CropOperation.h | 2 +- .../operations/COM_DespeckleOperation.h | 4 +- .../operations/COM_DilateErodeOperation.cpp | 14 +- .../operations/COM_DisplaceOperation.cpp | 4 +- .../COM_DisplaceSimpleOperation.cpp | 2 +- .../COM_FastGaussianBlurOperation.cpp | 6 +- .../COM_GaussianAlphaXBlurOperation.cpp | 8 +- .../COM_GaussianAlphaYBlurOperation.cpp | 8 +- .../COM_GaussianBokehBlurOperation.cpp | 16 +- .../operations/COM_GaussianXBlurOperation.cpp | 14 +- .../operations/COM_GaussianYBlurOperation.cpp | 16 +- .../operations/COM_GlareFogGlowOperation.cpp | 8 +- .../operations/COM_GlareGhostOperation.cpp | 8 +- .../operations/COM_GlareStreaksOperation.cpp | 8 +- .../operations/COM_InpaintOperation.cpp | 8 +- .../operations/COM_KeyingDespillOperation.cpp | 27 +- .../operations/COM_KeyingOperation.cpp | 28 +- .../operations/COM_MapUVOperation.cpp | 2 +- .../operations/COM_MaskOperation.cpp | 2 +- .../operations/COM_MathBaseOperation.h | 2 +- .../operations/COM_MixBaseOperation.h | 2 +- .../operations/COM_MixColorOperation.cpp | 9 +- .../operations/COM_MixGlareOperation.cpp | 10 +- .../COM_MovieDistortionOperation.cpp | 17 +- .../operations/COM_MovieDistortionOperation.h | 8 +- .../operations/COM_OpenCLKernels.cl | 14 +- .../operations/COM_OutputFileOperation.cpp | 13 +- .../operations/COM_PixelateOperation.cpp | 49 + .../operations/COM_PixelateOperation.h | 68 + .../COM_ProjectorLensDistortionOperation.cpp | 4 +- .../COM_ScreenLensDistortionOperation.cpp | 14 +- .../operations/COM_TrackPositionOperation.h | 8 +- .../COM_VariableSizeBokehBlurOperation.cpp | 12 +- .../operations/COM_ViewerBaseOperation.cpp | 8 +- .../operations/COM_ViewerOperation.cpp | 2 +- .../operations/COM_WriteBufferOperation.cpp | 3 +- .../operations/COM_ZCombineOperation.cpp | 10 +- source/blender/datatoc/datatoc.c | 5 +- .../editors/animation/anim_channels_defines.c | 92 +- .../editors/animation/anim_channels_edit.c | 18 +- source/blender/editors/animation/anim_deps.c | 2 - source/blender/editors/animation/anim_draw.c | 4 +- .../blender/editors/animation/anim_filter.c | 99 +- .../blender/editors/animation/anim_intern.h | 4 +- .../editors/animation/anim_ipo_utils.c | 2 +- .../blender/editors/animation/anim_markers.c | 24 +- source/blender/editors/animation/anim_ops.c | 3 +- source/blender/editors/animation/drivers.c | 12 +- .../blender/editors/animation/fmodifier_ui.c | 50 +- .../editors/animation/keyframes_draw.c | 8 +- .../editors/animation/keyframes_edit.c | 8 +- .../editors/animation/keyframes_general.c | 4 +- source/blender/editors/animation/keyframing.c | 210 +- source/blender/editors/animation/keyingsets.c | 22 +- .../blender/editors/armature/armature_ops.c | 4 +- .../blender/editors/armature/editarmature.c | 128 +- .../editors/armature/editarmature_generate.c | 2 +- .../editors/armature/editarmature_retarget.c | 40 +- .../editors/armature/editarmature_sketch.c | 135 +- .../blender/editors/armature/meshlaplacian.c | 146 +- source/blender/editors/armature/poseSlide.c | 15 +- source/blender/editors/armature/poseUtils.c | 2 +- source/blender/editors/armature/poselib.c | 32 +- source/blender/editors/armature/poseobject.c | 150 +- source/blender/editors/armature/reeb.c | 50 +- source/blender/editors/armature/reeb.h | 2 +- source/blender/editors/curve/editcurve.c | 297 +- source/blender/editors/curve/editfont.c | 79 +- source/blender/editors/gpencil/drawgpencil.c | 65 +- .../editors/gpencil/editaction_gpencil.c | 2 +- .../blender/editors/gpencil/gpencil_buttons.c | 8 +- source/blender/editors/gpencil/gpencil_edit.c | 24 +- .../blender/editors/gpencil/gpencil_paint.c | 205 +- source/blender/editors/gpencil/gpencil_undo.c | 2 +- source/blender/editors/include/ED_anim_api.h | 36 +- source/blender/editors/include/ED_armature.h | 15 +- source/blender/editors/include/ED_curve.h | 2 +- .../editors/include/ED_keyframes_draw.h | 1 - source/blender/editors/include/ED_mask.h | 4 +- source/blender/editors/include/ED_mball.h | 2 +- source/blender/editors/include/ED_mesh.h | 17 +- source/blender/editors/include/ED_object.h | 26 +- source/blender/editors/include/ED_particle.h | 2 +- source/blender/editors/include/ED_screen.h | 2 + .../blender/editors/include/ED_screen_types.h | 2 +- source/blender/editors/include/ED_sculpt.h | 6 +- source/blender/editors/include/ED_view3d.h | 250 +- source/blender/editors/include/UI_icons.h | 9 +- source/blender/editors/include/UI_interface.h | 18 +- source/blender/editors/include/UI_view2d.h | 18 +- source/blender/editors/interface/interface.c | 238 +- .../editors/interface/interface_draw.c | 120 +- .../editors/interface/interface_handlers.c | 664 ++-- .../editors/interface/interface_icons.c | 14 +- .../editors/interface/interface_intern.h | 33 +- .../editors/interface/interface_layout.c | 51 +- .../blender/editors/interface/interface_ops.c | 74 +- .../editors/interface/interface_panel.c | 40 +- .../editors/interface/interface_regions.c | 175 +- .../editors/interface/interface_style.c | 14 +- .../editors/interface/interface_templates.c | 153 +- .../editors/interface/interface_widgets.c | 449 ++- source/blender/editors/interface/resources.c | 60 +- source/blender/editors/interface/view2d.c | 171 +- source/blender/editors/interface/view2d_ops.c | 128 +- source/blender/editors/io/io_collada.c | 52 +- source/blender/editors/mask/CMakeLists.txt | 2 +- source/blender/editors/mask/mask_add.c | 28 +- source/blender/editors/mask/mask_draw.c | 103 +- source/blender/editors/mask/mask_edit.c | 6 +- source/blender/editors/mask/mask_intern.h | 3 + source/blender/editors/mask/mask_ops.c | 22 +- source/blender/editors/mask/mask_select.c | 11 +- source/blender/editors/mesh/CMakeLists.txt | 9 + source/blender/editors/mesh/SConscript | 8 +- source/blender/editors/mesh/editface.c | 18 +- source/blender/editors/mesh/editmesh_add.c | 196 +- source/blender/editors/mesh/editmesh_bvh.c | 13 +- source/blender/editors/mesh/editmesh_knife.c | 93 +- .../blender/editors/mesh/editmesh_loopcut.c | 22 +- source/blender/editors/mesh/editmesh_rip.c | 373 +- source/blender/editors/mesh/editmesh_select.c | 239 +- source/blender/editors/mesh/editmesh_slide.c | 48 +- source/blender/editors/mesh/editmesh_tools.c | 638 ++-- source/blender/editors/mesh/editmesh_utils.c | 42 +- source/blender/editors/mesh/mesh_data.c | 262 +- source/blender/editors/mesh/mesh_intern.h | 15 +- source/blender/editors/mesh/mesh_navmesh.c | 2 +- source/blender/editors/mesh/mesh_ops.c | 27 +- source/blender/editors/mesh/meshtools.c | 135 +- source/blender/editors/metaball/mball_edit.c | 84 +- source/blender/editors/object/object_add.c | 731 ++-- source/blender/editors/object/object_bake.c | 72 +- .../editors/object/object_constraint.c | 203 +- source/blender/editors/object/object_edit.c | 72 +- source/blender/editors/object/object_group.c | 6 +- source/blender/editors/object/object_hook.c | 24 +- source/blender/editors/object/object_intern.h | 5 + .../blender/editors/object/object_lattice.c | 282 +- .../blender/editors/object/object_modifier.c | 42 +- source/blender/editors/object/object_ops.c | 9 +- .../blender/editors/object/object_relations.c | 196 +- source/blender/editors/object/object_select.c | 16 +- .../blender/editors/object/object_shapekey.c | 30 +- .../blender/editors/object/object_transform.c | 70 +- source/blender/editors/object/object_vgroup.c | 635 +++- source/blender/editors/physics/CMakeLists.txt | 5 + source/blender/editors/physics/SConscript | 12 +- .../editors/physics/dynamicpaint_ops.c | 65 +- .../blender/editors/physics/particle_boids.c | 2 +- .../blender/editors/physics/particle_edit.c | 204 +- .../blender/editors/physics/particle_object.c | 11 +- .../blender/editors/physics/physics_fluid.c | 49 +- source/blender/editors/physics/physics_ops.c | 2 +- .../editors/physics/physics_pointcache.c | 6 +- .../blender/editors/render/render_internal.c | 30 +- source/blender/editors/render/render_opengl.c | 26 +- .../blender/editors/render/render_preview.c | 44 +- .../blender/editors/render/render_shading.c | 6 +- source/blender/editors/render/render_update.c | 53 +- source/blender/editors/render/render_view.c | 3 +- source/blender/editors/screen/area.c | 147 +- source/blender/editors/screen/glutil.c | 28 +- .../blender/editors/screen/screen_context.c | 4 +- source/blender/editors/screen/screen_edit.c | 27 +- source/blender/editors/screen/screen_ops.c | 189 +- source/blender/editors/screen/screendump.c | 14 +- .../editors/sculpt_paint/CMakeLists.txt | 2 +- .../editors/sculpt_paint/paint_cursor.c | 21 +- .../blender/editors/sculpt_paint/paint_hide.c | 6 +- .../editors/sculpt_paint/paint_image.c | 142 +- .../editors/sculpt_paint/paint_intern.h | 2 +- .../blender/editors/sculpt_paint/paint_mask.c | 7 +- .../blender/editors/sculpt_paint/paint_ops.c | 2 +- .../editors/sculpt_paint/paint_stroke.c | 35 +- .../blender/editors/sculpt_paint/paint_undo.c | 12 +- .../editors/sculpt_paint/paint_utils.c | 16 +- .../editors/sculpt_paint/paint_vertex.c | 239 +- source/blender/editors/sculpt_paint/sculpt.c | 135 +- .../editors/sculpt_paint/sculpt_intern.h | 6 +- .../editors/sculpt_paint/sculpt_undo.c | 31 +- .../editors/space_action/action_draw.c | 8 +- .../editors/space_action/action_edit.c | 79 +- .../editors/space_action/action_intern.h | 4 +- .../blender/editors/space_action/action_ops.c | 5 +- .../editors/space_action/action_select.c | 17 +- .../editors/space_action/space_action.c | 11 +- source/blender/editors/space_api/spacetypes.c | 4 +- .../editors/space_buttons/buttons_context.c | 6 +- .../editors/space_buttons/buttons_header.c | 2 +- .../editors/space_buttons/buttons_ops.c | 4 +- .../editors/space_buttons/space_buttons.c | 2 +- .../blender/editors/space_clip/CMakeLists.txt | 2 +- .../blender/editors/space_clip/clip_buttons.c | 2 +- .../editors/space_clip/clip_dopesheet_draw.c | 2 +- source/blender/editors/space_clip/clip_draw.c | 27 +- .../blender/editors/space_clip/clip_editor.c | 15 +- .../editors/space_clip/clip_graph_ops.c | 6 +- source/blender/editors/space_clip/clip_ops.c | 42 +- .../blender/editors/space_clip/space_clip.c | 24 +- .../blender/editors/space_clip/tracking_ops.c | 42 +- .../editors/space_clip/tracking_select.c | 13 +- .../editors/space_console/console_draw.c | 15 +- .../editors/space_console/console_ops.c | 24 +- .../editors/space_console/space_console.c | 10 +- source/blender/editors/space_file/file_draw.c | 18 +- .../blender/editors/space_file/file_intern.h | 1 + source/blender/editors/space_file/file_ops.c | 102 +- .../blender/editors/space_file/file_panels.c | 37 +- source/blender/editors/space_file/filelist.c | 66 +- source/blender/editors/space_file/filesel.c | 23 +- source/blender/editors/space_file/fsmenu.c | 206 +- source/blender/editors/space_file/fsmenu.h | 9 +- .../blender/editors/space_file/space_file.c | 13 +- .../editors/space_graph/graph_buttons.c | 51 +- .../blender/editors/space_graph/graph_draw.c | 48 +- .../blender/editors/space_graph/graph_edit.c | 94 +- .../editors/space_graph/graph_intern.h | 2 +- .../blender/editors/space_graph/graph_ops.c | 7 +- .../editors/space_graph/graph_select.c | 10 +- .../blender/editors/space_graph/space_graph.c | 4 +- .../editors/space_image/image_buttons.c | 43 +- .../blender/editors/space_image/image_draw.c | 10 +- .../blender/editors/space_image/image_edit.c | 18 +- .../blender/editors/space_image/image_ops.c | 146 +- .../blender/editors/space_image/space_image.c | 27 +- source/blender/editors/space_info/info_draw.c | 2 +- source/blender/editors/space_info/info_ops.c | 8 +- .../blender/editors/space_info/info_report.c | 8 +- .../blender/editors/space_info/info_stats.c | 2 +- .../blender/editors/space_info/space_info.c | 10 +- source/blender/editors/space_info/textview.c | 8 +- .../editors/space_logic/CMakeLists.txt | 4 + source/blender/editors/space_logic/SConscript | 5 +- .../editors/space_logic/logic_buttons.c | 32 +- .../blender/editors/space_logic/logic_ops.c | 6 +- .../editors/space_logic/logic_window.c | 2811 +-------------- .../blender/editors/space_logic/space_logic.c | 60 +- .../blender/editors/space_nla/nla_buttons.c | 11 +- .../blender/editors/space_nla/nla_channels.c | 2 +- source/blender/editors/space_nla/nla_draw.c | 16 +- source/blender/editors/space_nla/nla_edit.c | 33 +- source/blender/editors/space_nla/nla_ops.c | 2 +- source/blender/editors/space_nla/nla_select.c | 8 +- source/blender/editors/space_node/drawnode.c | 198 +- source/blender/editors/space_node/node_add.c | 183 +- source/blender/editors/space_node/node_draw.c | 45 +- source/blender/editors/space_node/node_edit.c | 130 +- .../blender/editors/space_node/node_group.c | 54 +- .../blender/editors/space_node/node_header.c | 12 +- .../blender/editors/space_node/node_intern.h | 2 + source/blender/editors/space_node/node_ops.c | 4 +- .../editors/space_node/node_relationships.c | 4 +- .../blender/editors/space_node/node_select.c | 10 +- .../editors/space_node/node_templates.c | 16 +- source/blender/editors/space_node/node_view.c | 15 +- .../blender/editors/space_node/space_node.c | 17 +- .../editors/space_outliner/outliner_draw.c | 52 +- .../editors/space_outliner/outliner_edit.c | 36 +- .../editors/space_outliner/outliner_select.c | 14 +- .../editors/space_outliner/outliner_tools.c | 89 +- .../editors/space_outliner/outliner_tree.c | 42 +- .../editors/space_sequencer/CMakeLists.txt | 4 + .../editors/space_sequencer/SConscript | 7 +- .../editors/space_sequencer/sequencer_add.c | 12 +- .../editors/space_sequencer/sequencer_draw.c | 40 +- .../editors/space_sequencer/sequencer_edit.c | 92 +- .../editors/space_sequencer/sequencer_ops.c | 45 +- .../space_sequencer/sequencer_scopes.c | 24 +- .../space_sequencer/sequencer_select.c | 17 +- .../editors/space_sequencer/sequencer_view.c | 2 +- .../editors/space_sequencer/space_sequencer.c | 14 +- .../blender/editors/space_text/CMakeLists.txt | 4 + source/blender/editors/space_text/SConscript | 3 + .../blender/editors/space_text/space_text.c | 2 +- source/blender/editors/space_text/text_draw.c | 43 +- .../blender/editors/space_text/text_header.c | 5 - source/blender/editors/space_text/text_ops.c | 55 +- .../blender/editors/space_text/text_python.c | 4 - .../blender/editors/space_time/space_time.c | 1 + source/blender/editors/space_time/time_ops.c | 2 +- .../editors/space_userpref/space_userpref.c | 2 +- .../editors/space_view3d/CMakeLists.txt | 2 + .../editors/space_view3d/drawanimviz.c | 24 +- .../editors/space_view3d/drawarmature.c | 59 +- .../blender/editors/space_view3d/drawmesh.c | 27 +- .../blender/editors/space_view3d/drawobject.c | 646 +--- .../blender/editors/space_view3d/drawvolume.c | 298 +- .../editors/space_view3d/space_view3d.c | 19 +- .../editors/space_view3d/view3d_buttons.c | 366 +- .../editors/space_view3d/view3d_draw.c | 283 +- .../editors/space_view3d/view3d_edit.c | 494 ++- .../blender/editors/space_view3d/view3d_fly.c | 25 +- .../editors/space_view3d/view3d_header.c | 29 +- .../editors/space_view3d/view3d_intern.h | 21 +- .../editors/space_view3d/view3d_iterators.c | 416 +++ .../blender/editors/space_view3d/view3d_ops.c | 18 +- .../editors/space_view3d/view3d_project.c | 493 +++ .../editors/space_view3d/view3d_select.c | 942 ++--- .../editors/space_view3d/view3d_snap.c | 89 +- .../editors/space_view3d/view3d_toolbar.c | 4 +- .../editors/space_view3d/view3d_view.c | 482 +-- source/blender/editors/transform/transform.c | 319 +- source/blender/editors/transform/transform.h | 2 +- .../editors/transform/transform_constraints.c | 2 +- .../editors/transform/transform_conversions.c | 226 +- .../editors/transform/transform_generics.c | 51 +- .../editors/transform/transform_manipulator.c | 4 +- .../blender/editors/transform/transform_ops.c | 22 +- .../transform/transform_orientations.c | 17 +- .../editors/transform/transform_snap.c | 216 +- source/blender/editors/util/crazyspace.c | 2 +- source/blender/editors/util/editmode_undo.c | 4 +- source/blender/editors/util/numinput.c | 4 +- source/blender/editors/util/undo.c | 2 +- source/blender/editors/uvedit/uvedit_draw.c | 51 +- source/blender/editors/uvedit/uvedit_intern.h | 25 - source/blender/editors/uvedit/uvedit_ops.c | 74 +- .../editors/uvedit/uvedit_parametrizer.c | 12 +- .../editors/uvedit/uvedit_smart_stitch.c | 84 +- .../editors/uvedit/uvedit_unwrap_ops.c | 152 +- source/blender/gpu/GPU_buffers.h | 45 +- source/blender/gpu/GPU_draw.h | 6 +- source/blender/gpu/GPU_extensions.h | 4 +- source/blender/gpu/GPU_material.h | 2 +- source/blender/gpu/intern/gpu_buffers.c | 457 ++- source/blender/gpu/intern/gpu_codegen.c | 29 +- source/blender/gpu/intern/gpu_codegen.h | 6 +- source/blender/gpu/intern/gpu_draw.c | 120 +- source/blender/gpu/intern/gpu_extensions.c | 20 +- source/blender/gpu/intern/gpu_material.c | 20 +- .../gpu/shaders/gpu_shader_material.glsl | 16 +- source/blender/ikplugin/BIK_api.h | 5 +- source/blender/ikplugin/CMakeLists.txt | 4 +- source/blender/ikplugin/intern/ikplugin_api.h | 3 +- .../blender/ikplugin/intern/iksolver_plugin.h | 3 +- .../blender/ikplugin/intern/itasc_plugin.cpp | 10 +- source/blender/ikplugin/intern/itasc_plugin.h | 3 +- source/blender/imbuf/CMakeLists.txt | 28 +- source/blender/imbuf/IMB_colormanagement.h | 23 +- source/blender/imbuf/IMB_imbuf.h | 12 +- source/blender/imbuf/IMB_imbuf_types.h | 15 +- source/blender/imbuf/intern/IMB_anim.h | 4 +- .../imbuf/intern/IMB_colormanagement_intern.h | 19 +- source/blender/imbuf/intern/IMB_filetype.h | 6 +- source/blender/imbuf/intern/IMB_indexer.h | 2 +- source/blender/imbuf/intern/allocimbuf.c | 2 +- source/blender/imbuf/intern/anim_movie.c | 24 +- source/blender/imbuf/intern/bmp.c | 2 +- .../imbuf/intern/cineon/CMakeLists.txt | 14 +- source/blender/imbuf/intern/cineon/SConscript | 3 + .../imbuf/intern/cineon/cin_debug_stuff.h | 4 - .../blender/imbuf/intern/cineon/cineon_dpx.c | 236 +- .../blender/imbuf/intern/cineon/cineonfile.h | 134 - .../blender/imbuf/intern/cineon/cineonlib.c | 1037 ++---- .../blender/imbuf/intern/cineon/cineonlib.h | 158 +- source/blender/imbuf/intern/cineon/dpxfile.h | 128 - source/blender/imbuf/intern/cineon/dpxlib.c | 1010 ++---- source/blender/imbuf/intern/cineon/dpxlib.h | 162 +- .../imbuf/intern/cineon/logImageCore.c | 1554 +++++++- .../imbuf/intern/cineon/logImageCore.h | 318 +- .../blender/imbuf/intern/cineon/logImageLib.c | 183 - .../blender/imbuf/intern/cineon/logImageLib.h | 87 - .../blender/imbuf/intern/cineon/logmemfile.c | 144 +- .../blender/imbuf/intern/cineon/logmemfile.h | 50 +- source/blender/imbuf/intern/colormanagement.c | 625 ++-- source/blender/imbuf/intern/dds/BlockDXT.cpp | 4 +- source/blender/imbuf/intern/dds/BlockDXT.h | 2 +- .../blender/imbuf/intern/dds/CMakeLists.txt | 14 +- source/blender/imbuf/intern/dds/Color.h | 2 +- .../blender/imbuf/intern/dds/ColorBlock.cpp | 2 +- source/blender/imbuf/intern/dds/ColorBlock.h | 2 +- source/blender/imbuf/intern/dds/Common.h | 6 +- .../imbuf/intern/dds/DirectDrawSurface.cpp | 250 +- .../imbuf/intern/dds/DirectDrawSurface.h | 4 +- source/blender/imbuf/intern/dds/FlipDXT.cpp | 255 ++ source/blender/imbuf/intern/dds/FlipDXT.h | 32 + source/blender/imbuf/intern/dds/Image.h | 2 +- source/blender/imbuf/intern/dds/PixelFormat.h | 58 +- source/blender/imbuf/intern/dds/SConscript | 2 +- source/blender/imbuf/intern/dds/Stream.h | 3 +- source/blender/imbuf/intern/dds/dds_api.cpp | 8 +- source/blender/imbuf/intern/divers.c | 48 +- source/blender/imbuf/intern/filetype.c | 4 +- source/blender/imbuf/intern/imageprocess.c | 40 +- source/blender/imbuf/intern/indexer.c | 39 +- source/blender/imbuf/intern/iris.c | 18 +- source/blender/imbuf/intern/jp2.c | 55 +- source/blender/imbuf/intern/jpeg.c | 4 +- source/blender/imbuf/intern/module.c | 3 + source/blender/imbuf/intern/moviecache.c | 2 +- .../imbuf/intern/openexr/CMakeLists.txt | 5 +- .../imbuf/intern/openexr/openexr_api.cpp | 18 +- source/blender/imbuf/intern/png.c | 3 +- source/blender/imbuf/intern/radiance_hdr.c | 6 +- source/blender/imbuf/intern/readimage.c | 6 +- source/blender/imbuf/intern/rectop.c | 8 +- source/blender/imbuf/intern/scaling.c | 2 +- source/blender/imbuf/intern/targa.c | 4 +- source/blender/imbuf/intern/thumbs.c | 10 +- source/blender/imbuf/intern/thumbs_blend.c | 2 +- source/blender/imbuf/intern/tiff.c | 11 +- source/blender/imbuf/intern/util.c | 13 +- source/blender/makesdna/DNA_action_types.h | 7 +- source/blender/makesdna/DNA_actuator_types.h | 32 +- source/blender/makesdna/DNA_anim_types.h | 210 +- source/blender/makesdna/DNA_armature_types.h | 188 +- source/blender/makesdna/DNA_boid_types.h | 26 +- source/blender/makesdna/DNA_camera_types.h | 2 +- source/blender/makesdna/DNA_cloth_types.h | 2 +- .../blender/makesdna/DNA_constraint_types.h | 18 +- source/blender/makesdna/DNA_curve_types.h | 8 +- .../blender/makesdna/DNA_customdata_types.h | 10 +- source/blender/makesdna/DNA_defs.h | 3 - .../blender/makesdna/DNA_dynamicpaint_types.h | 2 +- source/blender/makesdna/DNA_genfile.h | 6 +- source/blender/makesdna/DNA_gpencil_types.h | 12 +- source/blender/makesdna/DNA_image_types.h | 1 + source/blender/makesdna/DNA_ipo_types.h | 4 +- source/blender/makesdna/DNA_key_types.h | 2 +- source/blender/makesdna/DNA_lamp_types.h | 2 +- source/blender/makesdna/DNA_mask_types.h | 2 +- source/blender/makesdna/DNA_material_types.h | 17 +- source/blender/makesdna/DNA_mesh_types.h | 5 +- source/blender/makesdna/DNA_meshdata_types.h | 8 +- source/blender/makesdna/DNA_meta_types.h | 2 +- source/blender/makesdna/DNA_modifier_types.h | 47 +- source/blender/makesdna/DNA_movieclip_types.h | 56 +- source/blender/makesdna/DNA_nla_types.h | 2 +- source/blender/makesdna/DNA_node_types.h | 22 + source/blender/makesdna/DNA_object_force.h | 15 +- source/blender/makesdna/DNA_object_types.h | 20 +- .../blender/makesdna/DNA_packedFile_types.h | 10 +- source/blender/makesdna/DNA_scene_types.h | 51 +- source/blender/makesdna/DNA_sdna_types.h | 2 +- source/blender/makesdna/DNA_smoke_types.h | 111 +- source/blender/makesdna/DNA_space_types.h | 12 +- source/blender/makesdna/DNA_texture_types.h | 13 +- source/blender/makesdna/DNA_tracking_types.h | 162 +- source/blender/makesdna/DNA_userdef_types.h | 419 ++- source/blender/makesdna/DNA_view2d_types.h | 2 +- source/blender/makesdna/DNA_view3d_types.h | 2 + .../makesdna/DNA_windowmanager_types.h | 2 +- source/blender/makesdna/DNA_world_types.h | 6 +- source/blender/makesdna/intern/dna_genfile.c | 4 +- source/blender/makesdna/intern/makesdna.c | 42 +- source/blender/makesrna/RNA_access.h | 11 + source/blender/makesrna/RNA_enum_types.h | 1 + source/blender/makesrna/RNA_types.h | 2 + source/blender/makesrna/intern/makesrna.c | 902 ++++- source/blender/makesrna/intern/rna_ID.c | 18 +- source/blender/makesrna/intern/rna_access.c | 61 +- source/blender/makesrna/intern/rna_action.c | 113 +- .../blender/makesrna/intern/rna_action_api.c | 6 +- source/blender/makesrna/intern/rna_actuator.c | 9 +- .../makesrna/intern/rna_actuator_api.c | 2 + .../blender/makesrna/intern/rna_animation.c | 51 +- .../makesrna/intern/rna_animation_api.c | 5 +- source/blender/makesrna/intern/rna_armature.c | 36 +- .../makesrna/intern/rna_armature_api.c | 6 +- source/blender/makesrna/intern/rna_boid.c | 2 +- source/blender/makesrna/intern/rna_camera.c | 2 +- .../blender/makesrna/intern/rna_camera_api.c | 6 +- source/blender/makesrna/intern/rna_cloth.c | 12 +- source/blender/makesrna/intern/rna_color.c | 52 +- .../blender/makesrna/intern/rna_constraint.c | 9 +- .../blender/makesrna/intern/rna_controller.c | 4 +- .../makesrna/intern/rna_controller_api.c | 2 + source/blender/makesrna/intern/rna_curve.c | 53 +- source/blender/makesrna/intern/rna_define.c | 71 +- source/blender/makesrna/intern/rna_fcurve.c | 26 +- .../blender/makesrna/intern/rna_fcurve_api.c | 6 +- source/blender/makesrna/intern/rna_fluidsim.c | 2 +- source/blender/makesrna/intern/rna_gpencil.c | 349 +- source/blender/makesrna/intern/rna_group.c | 4 +- source/blender/makesrna/intern/rna_image.c | 28 +- .../blender/makesrna/intern/rna_image_api.c | 40 +- source/blender/makesrna/intern/rna_internal.h | 14 +- source/blender/makesrna/intern/rna_key.c | 6 +- source/blender/makesrna/intern/rna_lattice.c | 8 +- source/blender/makesrna/intern/rna_main.c | 2 +- source/blender/makesrna/intern/rna_main_api.c | 524 +-- source/blender/makesrna/intern/rna_mask.c | 12 +- source/blender/makesrna/intern/rna_material.c | 46 +- .../makesrna/intern/rna_material_api.c | 6 +- source/blender/makesrna/intern/rna_mesh.c | 48 +- source/blender/makesrna/intern/rna_mesh_api.c | 6 +- source/blender/makesrna/intern/rna_meta.c | 16 +- source/blender/makesrna/intern/rna_modifier.c | 168 +- .../blender/makesrna/intern/rna_movieclip.c | 11 +- source/blender/makesrna/intern/rna_nla.c | 28 +- source/blender/makesrna/intern/rna_nodetree.c | 347 +- .../makesrna/intern/rna_nodetree_types.h | 7 +- source/blender/makesrna/intern/rna_object.c | 171 +- .../blender/makesrna/intern/rna_object_api.c | 60 +- .../makesrna/intern/rna_object_force.c | 24 +- source/blender/makesrna/intern/rna_particle.c | 8 +- source/blender/makesrna/intern/rna_pose.c | 49 +- source/blender/makesrna/intern/rna_pose_api.c | 6 +- source/blender/makesrna/intern/rna_property.c | 4 +- source/blender/makesrna/intern/rna_render.c | 42 +- source/blender/makesrna/intern/rna_rna.c | 2 +- source/blender/makesrna/intern/rna_scene.c | 103 +- .../blender/makesrna/intern/rna_scene_api.c | 40 +- source/blender/makesrna/intern/rna_screen.c | 4 +- .../makesrna/intern/rna_sculpt_paint.c | 23 + source/blender/makesrna/intern/rna_sensor.c | 2 +- .../blender/makesrna/intern/rna_sensor_api.c | 2 + .../blender/makesrna/intern/rna_sequencer.c | 35 +- .../makesrna/intern/rna_sequencer_api.c | 74 +- source/blender/makesrna/intern/rna_smoke.c | 251 +- source/blender/makesrna/intern/rna_space.c | 85 +- source/blender/makesrna/intern/rna_speaker.c | 5 +- source/blender/makesrna/intern/rna_text_api.c | 2 + source/blender/makesrna/intern/rna_texture.c | 6 +- .../blender/makesrna/intern/rna_texture_api.c | 14 +- source/blender/makesrna/intern/rna_tracking.c | 55 +- source/blender/makesrna/intern/rna_ui.c | 8 +- source/blender/makesrna/intern/rna_ui_api.c | 35 +- source/blender/makesrna/intern/rna_userdef.c | 100 +- source/blender/makesrna/intern/rna_wm.c | 63 +- source/blender/makesrna/intern/rna_wm_api.c | 57 +- .../makesrna/rna_cleanup/rna_cleaner.py | 12 +- source/blender/modifiers/CMakeLists.txt | 9 +- source/blender/modifiers/MOD_modifiertypes.h | 3 +- source/blender/modifiers/SConscript | 5 +- .../blender/modifiers/intern/MOD_armature.c | 8 +- source/blender/modifiers/intern/MOD_array.c | 62 +- source/blender/modifiers/intern/MOD_bevel.c | 80 +- source/blender/modifiers/intern/MOD_boolean.c | 46 +- .../modifiers/intern/MOD_boolean_util.c | 4 +- .../modifiers/intern/MOD_boolean_util.h | 2 +- source/blender/modifiers/intern/MOD_build.c | 44 +- source/blender/modifiers/intern/MOD_cloth.c | 4 +- source/blender/modifiers/intern/MOD_curve.c | 4 +- .../blender/modifiers/intern/MOD_decimate.c | 217 +- .../modifiers/intern/MOD_dynamicpaint.c | 8 +- .../blender/modifiers/intern/MOD_edgesplit.c | 14 +- source/blender/modifiers/intern/MOD_explode.c | 59 +- .../modifiers/intern/MOD_fluidsim_util.c | 2 +- .../modifiers/intern/MOD_laplaciansmooth.c | 703 ++++ source/blender/modifiers/intern/MOD_lattice.c | 4 +- source/blender/modifiers/intern/MOD_mask.c | 6 +- .../blender/modifiers/intern/MOD_meshdeform.c | 52 +- source/blender/modifiers/intern/MOD_mirror.c | 3 +- .../blender/modifiers/intern/MOD_multires.c | 5 +- source/blender/modifiers/intern/MOD_ocean.c | 22 +- .../modifiers/intern/MOD_particleinstance.c | 87 +- .../modifiers/intern/MOD_particlesystem.c | 10 +- source/blender/modifiers/intern/MOD_remesh.c | 2 +- source/blender/modifiers/intern/MOD_screw.c | 20 +- .../blender/modifiers/intern/MOD_shapekey.c | 13 +- .../blender/modifiers/intern/MOD_shrinkwrap.c | 48 +- .../modifiers/intern/MOD_simpledeform.c | 36 +- source/blender/modifiers/intern/MOD_skin.c | 58 +- source/blender/modifiers/intern/MOD_smoke.c | 59 +- source/blender/modifiers/intern/MOD_smooth.c | 2 +- .../blender/modifiers/intern/MOD_solidify.c | 27 +- source/blender/modifiers/intern/MOD_util.c | 5 +- source/blender/modifiers/intern/MOD_util.h | 12 +- .../blender/modifiers/intern/MOD_uvproject.c | 62 +- source/blender/modifiers/intern/MOD_warp.c | 50 +- source/blender/modifiers/intern/MOD_wave.c | 2 +- .../modifiers/intern/MOD_weightvgedit.c | 10 +- .../modifiers/intern/MOD_weightvgmix.c | 32 +- .../modifiers/intern/MOD_weightvgproximity.c | 16 +- source/blender/nodes/CMakeLists.txt | 17 +- source/blender/nodes/NOD_composite.h | 6 +- source/blender/nodes/NOD_shader.h | 3 + .../nodes/composite/node_composite_tree.c | 12 +- .../nodes/composite/node_composite_util.c | 142 +- .../nodes/node_composite_alphaOver.c | 32 +- .../nodes/node_composite_bilateralblur.c | 10 +- .../nodes/node_composite_bokehimage.c | 2 +- .../composite/nodes/node_composite_boxmask.c | 10 +- .../nodes/node_composite_brightness.c | 6 +- .../nodes/node_composite_channelMatte.c | 6 +- .../nodes/node_composite_chromaMatte.c | 4 +- .../nodes/node_composite_colorMatte.c | 4 +- .../nodes/node_composite_colorSpill.c | 4 +- .../nodes/node_composite_colorbalance.c | 8 +- .../nodes/node_composite_colorcorrection.c | 4 +- .../composite/nodes/node_composite_common.c | 150 - .../nodes/node_composite_composite.c | 4 +- .../composite/nodes/node_composite_crop.c | 6 +- .../composite/nodes/node_composite_curves.c | 22 +- .../composite/nodes/node_composite_defocus.c | 12 +- .../nodes/node_composite_despeckle.c | 4 +- .../nodes/node_composite_diffMatte.c | 6 +- .../composite/nodes/node_composite_dilate.c | 16 +- .../nodes/node_composite_directionalblur.c | 2 +- .../composite/nodes/node_composite_displace.c | 8 +- .../nodes/node_composite_distanceMatte.c | 10 +- .../nodes/node_composite_doubleEdgeMask.c | 4 +- .../nodes/node_composite_ellipsemask.c | 10 +- .../composite/nodes/node_composite_filter.c | 44 +- .../composite/nodes/node_composite_flip.c | 6 +- .../composite/nodes/node_composite_gamma.c | 4 +- .../composite/nodes/node_composite_glare.c | 4 +- .../nodes/node_composite_hueSatVal.c | 14 +- .../nodes/node_composite_huecorrect.c | 14 +- .../composite/nodes/node_composite_idMask.c | 10 +- .../composite/nodes/node_composite_image.c | 4 +- .../composite/nodes/node_composite_invert.c | 14 +- .../composite/nodes/node_composite_lensdist.c | 8 +- .../composite/nodes/node_composite_levels.c | 14 +- .../nodes/node_composite_lummaMatte.c | 4 +- .../composite/nodes/node_composite_mapUV.c | 6 +- .../composite/nodes/node_composite_mapValue.c | 10 +- .../composite/nodes/node_composite_math.c | 68 +- .../composite/nodes/node_composite_mixrgb.c | 6 +- .../composite/nodes/node_composite_normal.c | 8 +- .../nodes/node_composite_normalize.c | 4 +- .../composite/nodes/node_composite_pixelate.c | 57 + .../nodes/node_composite_premulkey.c | 4 +- .../composite/nodes/node_composite_rgb.c | 2 +- .../composite/nodes/node_composite_rotate.c | 4 +- .../nodes/node_composite_sepcombHSVA.c | 16 +- .../nodes/node_composite_sepcombRGBA.c | 10 +- .../nodes/node_composite_sepcombYCCA.c | 34 +- .../nodes/node_composite_sepcombYUVA.c | 16 +- .../composite/nodes/node_composite_setalpha.c | 4 +- .../nodes/node_composite_splitViewer.c | 4 +- .../nodes/node_composite_stabilize2d.c | 4 +- .../composite/nodes/node_composite_switch.c | 4 +- .../composite/nodes/node_composite_texture.c | 22 +- .../composite/nodes/node_composite_tonemap.c | 4 +- .../nodes/node_composite_translate.c | 4 +- .../composite/nodes/node_composite_valToRgb.c | 8 +- .../composite/nodes/node_composite_value.c | 4 +- .../composite/nodes/node_composite_viewer.c | 2 +- .../composite/nodes/node_composite_zcombine.c | 50 +- source/blender/nodes/intern/node_common.c | 195 +- source/blender/nodes/intern/node_common.h | 12 - source/blender/nodes/intern/node_exec.c | 41 +- source/blender/nodes/intern/node_exec.h | 2 - source/blender/nodes/intern/node_socket.c | 22 +- source/blender/nodes/intern/node_util.c | 17 +- source/blender/nodes/intern/node_util.h | 2 +- .../blender/nodes/shader/node_shader_tree.c | 5 +- .../blender/nodes/shader/node_shader_util.c | 16 +- .../shader/nodes/node_shader_add_shader.c | 4 +- .../shader/nodes/node_shader_attribute.c | 2 +- .../shader/nodes/node_shader_background.c | 4 +- .../shader/nodes/node_shader_brightness.c | 4 +- .../nodes/node_shader_bsdf_anisotropic.c | 18 +- .../shader/nodes/node_shader_bsdf_diffuse.c | 10 +- .../shader/nodes/node_shader_bsdf_glass.c | 10 +- .../shader/nodes/node_shader_bsdf_glossy.c | 11 +- .../nodes/node_shader_bsdf_translucent.c | 10 +- .../nodes/node_shader_bsdf_transparent.c | 4 +- .../shader/nodes/node_shader_bsdf_velvet.c | 10 +- .../nodes/shader/nodes/node_shader_bump.c | 68 + .../nodes/shader/nodes/node_shader_camera.c | 6 +- .../nodes/shader/nodes/node_shader_common.c | 125 - .../nodes/shader/nodes/node_shader_curves.c | 8 +- .../nodes/shader/nodes/node_shader_emission.c | 4 +- .../nodes/shader/nodes/node_shader_fresnel.c | 4 +- .../nodes/shader/nodes/node_shader_gamma.c | 4 +- .../nodes/shader/nodes/node_shader_geom.c | 10 +- .../nodes/shader/nodes/node_shader_geometry.c | 2 +- .../nodes/shader/nodes/node_shader_holdout.c | 4 +- .../shader/nodes/node_shader_hueSatVal.c | 10 +- .../nodes/shader/nodes/node_shader_invert.c | 14 +- .../shader/nodes/node_shader_layer_weight.c | 4 +- .../shader/nodes/node_shader_light_falloff.c | 4 +- .../shader/nodes/node_shader_light_path.c | 2 +- .../nodes/shader/nodes/node_shader_mapping.c | 16 +- .../nodes/shader/nodes/node_shader_material.c | 26 +- .../nodes/shader/nodes/node_shader_math.c | 92 +- .../nodes/shader/nodes/node_shader_mixRgb.c | 4 +- .../shader/nodes/node_shader_mix_shader.c | 4 +- .../nodes/shader/nodes/node_shader_normal.c | 6 +- .../shader/nodes/node_shader_object_info.c | 2 +- .../nodes/shader/nodes/node_shader_output.c | 6 +- .../shader/nodes/node_shader_output_lamp.c | 4 +- .../nodes/node_shader_output_material.c | 4 +- .../shader/nodes/node_shader_output_world.c | 4 +- .../shader/nodes/node_shader_particle_info.c | 24 +- .../nodes/shader/nodes/node_shader_rgb.c | 2 +- .../nodes/shader/nodes/node_shader_script.c | 85 + .../shader/nodes/node_shader_sepcombRGB.c | 8 +- .../nodes/shader/nodes/node_shader_squeeze.c | 21 +- .../shader/nodes/node_shader_tex_brick.c | 4 +- .../shader/nodes/node_shader_tex_checker.c | 4 +- .../shader/nodes/node_shader_tex_coord.c | 4 +- .../nodes/node_shader_tex_environment.c | 23 +- .../shader/nodes/node_shader_tex_gradient.c | 4 +- .../shader/nodes/node_shader_tex_image.c | 23 +- .../shader/nodes/node_shader_tex_magic.c | 4 +- .../shader/nodes/node_shader_tex_musgrave.c | 4 +- .../shader/nodes/node_shader_tex_noise.c | 4 +- .../nodes/shader/nodes/node_shader_tex_sky.c | 4 +- .../shader/nodes/node_shader_tex_voronoi.c | 4 +- .../nodes/shader/nodes/node_shader_tex_wave.c | 4 +- .../nodes/shader/nodes/node_shader_texture.c | 31 +- .../nodes/shader/nodes/node_shader_valToRgb.c | 10 +- .../nodes/shader/nodes/node_shader_value.c | 4 +- .../nodes/shader/nodes/node_shader_vectMath.c | 56 +- .../nodes/node_shader_volume_isotropic.c | 4 +- .../nodes/node_shader_volume_transparent.c | 4 +- .../blender/nodes/texture/node_texture_tree.c | 30 +- .../blender/nodes/texture/node_texture_util.c | 24 +- .../blender/nodes/texture/node_texture_util.h | 6 +- .../nodes/texture/nodes/node_texture_at.c | 4 +- .../nodes/texture/nodes/node_texture_bricks.c | 6 +- .../texture/nodes/node_texture_checker.c | 6 +- .../nodes/texture/nodes/node_texture_common.c | 125 - .../texture/nodes/node_texture_compose.c | 4 +- .../nodes/texture/nodes/node_texture_coord.c | 2 +- .../nodes/texture/nodes/node_texture_curves.c | 6 +- .../texture/nodes/node_texture_decompose.c | 4 +- .../texture/nodes/node_texture_distance.c | 6 +- .../texture/nodes/node_texture_hueSatVal.c | 14 +- .../nodes/texture/nodes/node_texture_image.c | 2 +- .../nodes/texture/nodes/node_texture_invert.c | 12 +- .../nodes/texture/nodes/node_texture_math.c | 18 +- .../nodes/texture/nodes/node_texture_mixRgb.c | 4 +- .../nodes/texture/nodes/node_texture_output.c | 6 +- .../nodes/texture/nodes/node_texture_proc.c | 30 +- .../nodes/texture/nodes/node_texture_rotate.c | 12 +- .../nodes/texture/nodes/node_texture_scale.c | 10 +- .../texture/nodes/node_texture_texture.c | 4 +- .../texture/nodes/node_texture_translate.c | 10 +- .../texture/nodes/node_texture_valToNor.c | 14 +- .../texture/nodes/node_texture_valToRgb.c | 8 +- .../nodes/texture/nodes/node_texture_viewer.c | 2 +- source/blender/opencl/CMakeLists.txt | 1 - source/blender/opencl/intern/OCL_opencl.c | 8 +- source/blender/python/BPY_extern.h | 1 + source/blender/python/bmesh/bmesh_py_types.c | 8 +- source/blender/python/bmesh/bmesh_py_types.h | 2 +- .../python/bmesh/bmesh_py_types_customdata.c | 4 +- .../python/bmesh/bmesh_py_types_meshdata.c | 2 +- .../python/bmesh/bmesh_py_types_select.c | 4 +- source/blender/python/generic/idprop_py_api.c | 151 +- source/blender/python/generic/idprop_py_api.h | 11 + source/blender/python/generic/py_capi_utils.c | 14 +- source/blender/python/generic/py_capi_utils.h | 2 +- source/blender/python/intern/CMakeLists.txt | 4 +- source/blender/python/intern/bpy.c | 4 +- source/blender/python/intern/bpy_app.c | 1 + source/blender/python/intern/bpy_app.h | 2 +- source/blender/python/intern/bpy_app_ffmpeg.c | 4 +- source/blender/python/intern/bpy_app_ffmpeg.h | 2 +- .../blender/python/intern/bpy_app_handlers.c | 2 +- .../blender/python/intern/bpy_app_handlers.h | 2 +- source/blender/python/intern/bpy_driver.c | 2 +- source/blender/python/intern/bpy_driver.h | 2 +- source/blender/python/intern/bpy_interface.c | 65 +- source/blender/python/intern/bpy_props.c | 29 +- source/blender/python/intern/bpy_rna.c | 150 +- source/blender/python/intern/bpy_rna.h | 1 + source/blender/python/intern/bpy_rna_anim.c | 3 - source/blender/python/intern/bpy_rna_array.c | 5 +- source/blender/python/intern/bpy_traceback.h | 2 +- source/blender/python/intern/bpy_util.c | 23 +- source/blender/python/intern/gpu.h | 2 +- source/blender/python/mathutils/mathutils.c | 4 +- .../python/mathutils/mathutils_Color.c | 144 +- .../python/mathutils/mathutils_Color.h | 4 +- .../python/mathutils/mathutils_Euler.c | 142 +- .../python/mathutils/mathutils_Euler.h | 2 +- .../python/mathutils/mathutils_Matrix.c | 177 +- .../python/mathutils/mathutils_Quaternion.c | 162 +- .../python/mathutils/mathutils_Quaternion.h | 2 +- .../python/mathutils/mathutils_Vector.c | 18 +- .../python/mathutils/mathutils_geometry.c | 10 +- .../python/mathutils/mathutils_noise.c | 1 + .../python/mathutils/mathutils_noise.h | 2 +- source/blender/python/rna_dump.py | 4 +- source/blender/quicktime/apple/qtkit_export.m | 56 +- source/blender/quicktime/apple/qtkit_import.m | 71 +- .../quicktime/apple/quicktime_export.c | 60 +- source/blender/quicktime/quicktime_export.h | 4 +- source/blender/quicktime/quicktime_import.h | 34 +- .../blender/render/extern/include/RE_engine.h | 7 + .../render/extern/include/RE_pipeline.h | 7 +- .../render/extern/include/RE_render_ext.h | 7 +- .../render/extern/include/RE_shader_ext.h | 11 +- source/blender/render/intern/include/envmap.h | 2 +- .../render/intern/include/pointdensity.h | 2 +- .../blender/render/intern/include/rayobject.h | 2 +- .../render/intern/include/render_result.h | 2 +- .../render/intern/include/render_types.h | 7 +- .../render/intern/include/rendercore.h | 5 +- .../render/intern/include/renderdatabase.h | 4 +- .../blender/render/intern/include/shadbuf.h | 18 +- .../blender/render/intern/include/shading.h | 2 +- source/blender/render/intern/include/sunsky.h | 5 +- .../blender/render/intern/include/texture.h | 2 +- .../render/intern/include/texture_ocean.h | 7 +- .../render/intern/include/volume_precache.h | 4 +- source/blender/render/intern/raytrace/bvh.h | 2 +- .../render/intern/raytrace/rayobject.cpp | 2 +- .../intern/raytrace/rayobject_blibvh.cpp | 4 +- .../intern/raytrace/rayobject_instance.cpp | 2 +- .../intern/raytrace/rayobject_internal.h | 9 +- .../intern/raytrace/rayobject_octree.cpp | 8 +- .../render/intern/raytrace/rayobject_qbvh.cpp | 2 +- .../intern/raytrace/rayobject_raycounter.cpp | 4 +- .../intern/raytrace/rayobject_rtbuild.cpp | 46 +- .../intern/raytrace/rayobject_rtbuild.h | 13 +- .../render/intern/raytrace/rayobject_vbvh.cpp | 8 +- .../render/intern/raytrace/reorganize.h | 20 +- source/blender/render/intern/raytrace/svbvh.h | 36 +- source/blender/render/intern/raytrace/vbvh.h | 2 +- .../render/intern/source/convertblender.c | 256 +- source/blender/render/intern/source/envmap.c | 40 +- .../render/intern/source/external_engine.c | 23 +- .../intern/source/gammaCorrectionTables.c | 10 +- .../render/intern/source/imagetexture.c | 149 +- .../blender/render/intern/source/initrender.c | 31 +- .../blender/render/intern/source/occlusion.c | 24 +- .../blender/render/intern/source/pipeline.c | 133 +- .../render/intern/source/pixelshading.c | 4 +- .../render/intern/source/pointdensity.c | 13 +- .../blender/render/intern/source/rayshade.c | 28 +- .../render/intern/source/render_result.c | 20 +- .../render/intern/source/render_texture.c | 399 ++- .../blender/render/intern/source/rendercore.c | 148 +- .../render/intern/source/renderdatabase.c | 77 +- source/blender/render/intern/source/shadbuf.c | 57 +- .../blender/render/intern/source/shadeinput.c | 219 +- .../render/intern/source/shadeoutput.c | 85 +- source/blender/render/intern/source/sss.c | 10 +- source/blender/render/intern/source/strand.c | 14 +- source/blender/render/intern/source/sunsky.c | 11 +- .../render/intern/source/texture_ocean.c | 2 +- .../render/intern/source/volume_precache.c | 10 +- .../blender/render/intern/source/volumetric.c | 6 +- .../blender/render/intern/source/voxeldata.c | 171 +- source/blender/render/intern/source/zbuf.c | 56 +- source/blender/windowmanager/CMakeLists.txt | 2 +- source/blender/windowmanager/WM_api.h | 27 +- source/blender/windowmanager/WM_keymap.h | 6 +- source/blender/windowmanager/WM_types.h | 40 +- source/blender/windowmanager/intern/wm.c | 2 +- .../blender/windowmanager/intern/wm_cursors.c | 23 +- .../windowmanager/intern/wm_dragdrop.c | 2 +- .../windowmanager/intern/wm_event_system.c | 494 +-- .../blender/windowmanager/intern/wm_files.c | 31 +- .../blender/windowmanager/intern/wm_gesture.c | 4 +- .../windowmanager/intern/wm_init_exit.c | 26 +- source/blender/windowmanager/intern/wm_jobs.c | 25 +- .../blender/windowmanager/intern/wm_keymap.c | 75 +- .../windowmanager/intern/wm_operators.c | 149 +- .../windowmanager/intern/wm_playanim.c | 71 +- .../windowmanager/intern/wm_subwindow.c | 20 +- .../blender/windowmanager/intern/wm_window.c | 30 +- .../blender/windowmanager/wm_event_system.h | 70 +- source/blender/windowmanager/wm_event_types.h | 3 +- source/blenderplayer/CMakeLists.txt | 5 +- .../bad_level_call_stubs/stubs.c | 12 +- source/creator/CMakeLists.txt | 14 +- source/creator/creator.c | 1 + .../BlenderRoutines/BL_KetsjiEmbedStart.cpp | 64 +- .../gameengine/BlenderRoutines/CMakeLists.txt | 4 +- .../BlenderRoutines/KX_BlenderCanvas.cpp | 36 +- .../BlenderRoutines/KX_BlenderCanvas.h | 10 +- .../BlenderRoutines/KX_BlenderGL.cpp | 4 +- .../gameengine/BlenderRoutines/KX_BlenderGL.h | 7 +- .../BlenderRoutines/KX_BlenderInputDevice.h | 11 +- .../KX_BlenderKeyboardDevice.cpp | 6 +- .../KX_BlenderKeyboardDevice.h | 3 +- .../BlenderRoutines/KX_BlenderMouseDevice.cpp | 7 +- .../BlenderRoutines/KX_BlenderMouseDevice.h | 3 +- .../BlenderRoutines/KX_BlenderRenderTools.cpp | 35 +- .../BlenderRoutines/KX_BlenderRenderTools.h | 47 +- .../BlenderRoutines/KX_BlenderSystem.cpp | 6 +- .../BlenderRoutines/KX_BlenderSystem.h | 3 +- source/gameengine/CMakeLists.txt | 2 +- .../Converter/BL_ActionActuator.cpp | 43 +- .../gameengine/Converter/BL_ActionActuator.h | 2 +- .../Converter/BL_ArmatureActuator.cpp | 12 +- .../Converter/BL_ArmatureActuator.h | 24 +- .../Converter/BL_ArmatureChannel.cpp | 24 +- .../gameengine/Converter/BL_ArmatureChannel.h | 12 +- .../Converter/BL_ArmatureConstraint.cpp | 16 +- .../Converter/BL_ArmatureConstraint.h | 9 +- .../Converter/BL_ArmatureObject.cpp | 21 +- .../gameengine/Converter/BL_ArmatureObject.h | 10 +- .../Converter/BL_BlenderDataConversion.cpp | 180 +- .../Converter/BL_BlenderDataConversion.h | 3 +- .../Converter/BL_DeformableGameObject.h | 11 +- .../gameengine/Converter/BL_MeshDeformer.cpp | 41 +- source/gameengine/Converter/BL_MeshDeformer.h | 8 +- .../Converter/BL_ModifierDeformer.cpp | 13 +- .../Converter/BL_ModifierDeformer.h | 52 +- .../Converter/BL_ShapeActionActuator.cpp | 8 +- .../Converter/BL_ShapeActionActuator.h | 5 +- .../gameengine/Converter/BL_ShapeDeformer.cpp | 11 +- .../gameengine/Converter/BL_ShapeDeformer.h | 8 +- .../gameengine/Converter/BL_SkinDeformer.cpp | 23 +- source/gameengine/Converter/BL_SkinDeformer.h | 27 +- .../gameengine/Converter/BlenderWorldInfo.cpp | 6 +- .../gameengine/Converter/BlenderWorldInfo.h | 13 +- source/gameengine/Converter/CMakeLists.txt | 8 +- .../KX_BlenderScalarInterpolator.cpp | 4 +- .../Converter/KX_BlenderScalarInterpolator.h | 5 +- .../Converter/KX_BlenderSceneConverter.cpp | 57 +- .../Converter/KX_BlenderSceneConverter.h | 13 +- .../Converter/KX_ConvertActuators.cpp | 379 +- .../Converter/KX_ConvertActuators.h | 22 +- .../Converter/KX_ConvertControllers.cpp | 5 +- .../Converter/KX_ConvertControllers.h | 4 +- .../Converter/KX_ConvertProperties.cpp | 13 +- .../Converter/KX_ConvertProperties.h | 3 +- .../Converter/KX_ConvertSensors.cpp | 37 +- .../gameengine/Converter/KX_ConvertSensors.h | 3 +- source/gameengine/Converter/KX_IpoConvert.cpp | 17 +- source/gameengine/Converter/KX_IpoConvert.h | 3 +- .../Converter/KX_SoftBodyDeformer.cpp | 4 +- .../Converter/KX_SoftBodyDeformer.h | 6 +- source/gameengine/Expressions/BoolValue.cpp | 37 +- source/gameengine/Expressions/BoolValue.h | 5 +- source/gameengine/Expressions/ConstExpr.h | 3 +- source/gameengine/Expressions/EXP_C-Api.cpp | 4 +- source/gameengine/Expressions/EXP_C-Api.h | 5 +- source/gameengine/Expressions/EmptyValue.h | 3 +- source/gameengine/Expressions/ErrorValue.h | 3 +- source/gameengine/Expressions/Expression.h | 3 +- source/gameengine/Expressions/FloatValue.cpp | 238 +- source/gameengine/Expressions/FloatValue.h | 3 +- .../gameengine/Expressions/IdentifierExpr.h | 3 +- source/gameengine/Expressions/IfExpr.h | 11 +- source/gameengine/Expressions/InputParser.cpp | 184 +- source/gameengine/Expressions/IntValue.cpp | 273 +- source/gameengine/Expressions/IntValue.h | 3 +- source/gameengine/Expressions/KX_HashedPtr.h | 5 +- source/gameengine/Expressions/KX_Python.h | 3 +- source/gameengine/Expressions/ListValue.cpp | 130 +- source/gameengine/Expressions/ListValue.h | 4 +- source/gameengine/Expressions/Operator1Expr.h | 7 +- .../gameengine/Expressions/Operator2Expr.cpp | 6 +- source/gameengine/Expressions/Operator2Expr.h | 2 +- .../gameengine/Expressions/PyObjectPlus.cpp | 23 +- source/gameengine/Expressions/PyObjectPlus.h | 52 +- source/gameengine/Expressions/StringValue.cpp | 51 +- source/gameengine/Expressions/StringValue.h | 7 +- source/gameengine/Expressions/Value.cpp | 12 +- source/gameengine/Expressions/Value.h | 47 +- source/gameengine/Expressions/VectorValue.cpp | 55 +- source/gameengine/Expressions/VectorValue.h | 3 +- source/gameengine/Expressions/VoidValue.h | 1 - .../GameLogic/Joystick/SCA_Joystick.cpp | 56 +- .../GameLogic/Joystick/SCA_Joystick.h | 2 +- .../GameLogic/Joystick/SCA_JoystickEvents.cpp | 46 +- .../gameengine/GameLogic/SCA_ANDController.h | 3 +- .../GameLogic/SCA_ActuatorEventManager.h | 3 +- .../gameengine/GameLogic/SCA_ActuatorSensor.h | 4 +- .../GameLogic/SCA_AlwaysEventManager.h | 3 +- .../gameengine/GameLogic/SCA_AlwaysSensor.cpp | 9 +- .../gameengine/GameLogic/SCA_AlwaysSensor.h | 3 +- .../GameLogic/SCA_BasicEventManager.h | 3 +- .../gameengine/GameLogic/SCA_DelaySensor.cpp | 9 +- source/gameengine/GameLogic/SCA_DelaySensor.h | 3 +- .../GameLogic/SCA_ExpressionController.h | 3 +- source/gameengine/GameLogic/SCA_IActuator.h | 3 +- .../gameengine/GameLogic/SCA_IController.cpp | 12 +- source/gameengine/GameLogic/SCA_IController.h | 5 +- .../gameengine/GameLogic/SCA_IInputDevice.cpp | 4 +- .../gameengine/GameLogic/SCA_IInputDevice.h | 32 +- .../gameengine/GameLogic/SCA_ILogicBrick.cpp | 8 +- source/gameengine/GameLogic/SCA_ILogicBrick.h | 7 +- source/gameengine/GameLogic/SCA_IObject.cpp | 2 +- source/gameengine/GameLogic/SCA_IObject.h | 7 +- source/gameengine/GameLogic/SCA_IScene.h | 3 +- source/gameengine/GameLogic/SCA_ISensor.cpp | 26 +- source/gameengine/GameLogic/SCA_ISensor.h | 5 +- .../GameLogic/SCA_JoystickSensor.cpp | 105 +- .../gameengine/GameLogic/SCA_JoystickSensor.h | 10 +- .../GameLogic/SCA_KeyboardManager.h | 5 +- .../GameLogic/SCA_KeyboardSensor.cpp | 77 +- .../gameengine/GameLogic/SCA_KeyboardSensor.h | 7 +- .../gameengine/GameLogic/SCA_LogicManager.h | 7 +- .../gameengine/GameLogic/SCA_MouseManager.cpp | 8 +- .../gameengine/GameLogic/SCA_MouseManager.h | 5 +- .../gameengine/GameLogic/SCA_MouseSensor.cpp | 10 +- source/gameengine/GameLogic/SCA_MouseSensor.h | 3 +- .../gameengine/GameLogic/SCA_NANDController.h | 3 +- .../gameengine/GameLogic/SCA_NORController.h | 3 +- .../gameengine/GameLogic/SCA_ORController.h | 3 +- .../GameLogic/SCA_PropertyActuator.cpp | 2 +- .../GameLogic/SCA_PropertyActuator.h | 3 +- .../GameLogic/SCA_PropertyEventManager.h | 3 +- .../GameLogic/SCA_PythonController.cpp | 123 +- .../GameLogic/SCA_PythonController.h | 15 +- .../GameLogic/SCA_PythonKeyboard.cpp | 8 +- .../gameengine/GameLogic/SCA_PythonKeyboard.h | 5 +- .../gameengine/GameLogic/SCA_PythonMouse.cpp | 12 +- source/gameengine/GameLogic/SCA_PythonMouse.h | 17 +- .../GameLogic/SCA_RandomActuator.cpp | 77 +- .../gameengine/GameLogic/SCA_RandomActuator.h | 8 +- .../GameLogic/SCA_RandomEventManager.h | 3 +- .../gameengine/GameLogic/SCA_RandomSensor.cpp | 6 +- .../gameengine/GameLogic/SCA_RandomSensor.h | 3 +- .../GameLogic/SCA_TimeEventManager.cpp | 11 +- .../GameLogic/SCA_TimeEventManager.h | 3 +- .../gameengine/GameLogic/SCA_XNORController.h | 3 +- .../gameengine/GameLogic/SCA_XORController.h | 3 +- source/gameengine/GamePlayer/CMakeLists.txt | 2 +- .../GamePlayer/common/GPC_Canvas.cpp | 24 +- .../gameengine/GamePlayer/common/GPC_Canvas.h | 12 +- .../gameengine/GamePlayer/common/GPC_Engine.h | 3 +- .../GamePlayer/common/GPC_KeyboardDevice.h | 7 +- .../GamePlayer/common/GPC_MouseDevice.cpp | 6 +- .../GamePlayer/common/GPC_MouseDevice.h | 7 +- .../GamePlayer/common/GPC_RawImage.cpp | 2 +- .../GamePlayer/common/GPC_RawImage.h | 3 +- .../common/GPC_RawLoadDotBlendArray.cpp | 3 +- .../common/GPC_RawLoadDotBlendArray.h | 3 +- .../GamePlayer/common/GPC_RawLogoArrays.cpp | 6 +- .../GamePlayer/common/GPC_RawLogoArrays.h | 3 +- .../GamePlayer/common/GPC_RenderTools.cpp | 35 +- .../GamePlayer/common/GPC_RenderTools.h | 7 +- .../gameengine/GamePlayer/common/GPC_System.h | 3 +- .../gameengine/GamePlayer/common/bmfont.cpp | 4 +- .../GamePlayer/ghost/GPG_Application.cpp | 10 +- .../gameengine/GamePlayer/ghost/GPG_Canvas.h | 7 +- .../GamePlayer/ghost/GPG_KeyboardDevice.cpp | 40 +- .../GamePlayer/ghost/GPG_KeyboardDevice.h | 7 +- .../gameengine/GamePlayer/ghost/GPG_System.h | 5 +- .../gameengine/GamePlayer/ghost/GPG_ghost.cpp | 25 +- source/gameengine/Ketsji/BL_Action.cpp | 40 +- source/gameengine/Ketsji/BL_Action.h | 3 +- source/gameengine/Ketsji/BL_ActionManager.h | 3 +- source/gameengine/Ketsji/BL_BlenderShader.cpp | 6 +- source/gameengine/Ketsji/BL_BlenderShader.h | 2 +- source/gameengine/Ketsji/BL_Shader.cpp | 110 +- source/gameengine/Ketsji/BL_Shader.h | 4 +- source/gameengine/Ketsji/BL_Texture.cpp | 16 +- source/gameengine/Ketsji/BL_Texture.h | 2 +- source/gameengine/Ketsji/CMakeLists.txt | 6 +- .../Ketsji/KXNetwork/KX_NetworkEventManager.h | 3 +- .../KXNetwork/KX_NetworkMessageActuator.h | 3 +- .../KXNetwork/KX_NetworkMessageSensor.cpp | 6 +- .../KXNetwork/KX_NetworkMessageSensor.h | 7 +- .../gameengine/Ketsji/KX_ArmatureSensor.cpp | 6 +- source/gameengine/Ketsji/KX_ArmatureSensor.h | 4 +- .../gameengine/Ketsji/KX_BlenderMaterial.cpp | 36 +- source/gameengine/Ketsji/KX_BlenderMaterial.h | 10 +- .../Ketsji/KX_BulletPhysicsController.cpp | 2 +- .../Ketsji/KX_BulletPhysicsController.h | 3 +- source/gameengine/Ketsji/KX_Camera.cpp | 106 +- source/gameengine/Ketsji/KX_Camera.h | 13 +- .../gameengine/Ketsji/KX_CameraActuator.cpp | 46 +- source/gameengine/Ketsji/KX_CameraActuator.h | 5 +- .../Ketsji/KX_CameraIpoSGController.h | 9 +- .../gameengine/Ketsji/KX_CharacterWrapper.cpp | 94 + .../gameengine/Ketsji/KX_CharacterWrapper.h | 35 + .../gameengine/Ketsji/KX_ClientObjectInfo.h | 3 +- .../Ketsji/KX_ConstraintActuator.cpp | 6 +- .../gameengine/Ketsji/KX_ConstraintActuator.h | 5 +- .../Ketsji/KX_ConstraintWrapper.cpp | 10 +- .../gameengine/Ketsji/KX_ConstraintWrapper.h | 5 +- .../Ketsji/KX_ConvertPhysicsObject.h | 2 +- .../Ketsji/KX_ConvertPhysicsObjects.cpp | 9 +- source/gameengine/Ketsji/KX_Dome.cpp | 67 +- source/gameengine/Ketsji/KX_Dome.h | 2 +- source/gameengine/Ketsji/KX_EmptyObject.h | 3 +- source/gameengine/Ketsji/KX_FontObject.cpp | 16 +- source/gameengine/Ketsji/KX_FontObject.h | 2 +- source/gameengine/Ketsji/KX_GameObject.cpp | 415 ++- source/gameengine/Ketsji/KX_GameObject.h | 137 +- source/gameengine/Ketsji/KX_IInterpolator.h | 2 +- source/gameengine/Ketsji/KX_IPOTransform.h | 4 +- .../gameengine/Ketsji/KX_IPO_SGController.cpp | 10 +- .../gameengine/Ketsji/KX_IPO_SGController.h | 4 +- .../gameengine/Ketsji/KX_IPhysicsController.h | 3 +- .../Ketsji/KX_IScalarInterpolator.h | 2 +- source/gameengine/Ketsji/KX_ISceneConverter.h | 3 +- source/gameengine/Ketsji/KX_IpoActuator.cpp | 18 +- source/gameengine/Ketsji/KX_IpoActuator.h | 3 +- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 163 +- source/gameengine/Ketsji/KX_KetsjiEngine.h | 12 +- source/gameengine/Ketsji/KX_Light.cpp | 54 +- source/gameengine/Ketsji/KX_Light.h | 7 +- .../Ketsji/KX_LightIpoSGController.h | 9 +- .../Ketsji/KX_MaterialIpoController.h | 5 +- source/gameengine/Ketsji/KX_MeshProxy.cpp | 28 +- source/gameengine/Ketsji/KX_MeshProxy.h | 11 +- source/gameengine/Ketsji/KX_MotionState.h | 3 +- .../gameengine/Ketsji/KX_MouseFocusSensor.cpp | 60 +- .../gameengine/Ketsji/KX_MouseFocusSensor.h | 17 +- source/gameengine/Ketsji/KX_NavMeshObject.cpp | 22 +- source/gameengine/Ketsji/KX_NavMeshObject.h | 5 +- source/gameengine/Ketsji/KX_NearSensor.h | 5 +- .../Ketsji/KX_ObColorIpoSGController.h | 3 +- .../gameengine/Ketsji/KX_ObjectActuator.cpp | 53 +- source/gameengine/Ketsji/KX_ObjectActuator.h | 5 +- .../Ketsji/KX_ObstacleSimulation.cpp | 14 +- .../gameengine/Ketsji/KX_ObstacleSimulation.h | 8 +- .../gameengine/Ketsji/KX_ParentActuator.cpp | 6 +- source/gameengine/Ketsji/KX_ParentActuator.h | 7 +- .../gameengine/Ketsji/KX_PhysicsEngineEnums.h | 3 +- .../Ketsji/KX_PhysicsObjectWrapper.cpp | 8 +- .../Ketsji/KX_PhysicsObjectWrapper.h | 5 +- .../Ketsji/KX_PhysicsPropertiesobsolete.h | 3 +- source/gameengine/Ketsji/KX_PolyProxy.cpp | 42 +- source/gameengine/Ketsji/KX_PolyProxy.h | 25 +- .../gameengine/Ketsji/KX_PolygonMaterial.cpp | 34 +- source/gameengine/Ketsji/KX_PolygonMaterial.h | 9 +- .../Ketsji/KX_PyConstraintBinding.cpp | 167 +- .../Ketsji/KX_PyConstraintBinding.h | 5 +- source/gameengine/Ketsji/KX_PyMath.cpp | 34 +- source/gameengine/Ketsji/KX_PyMath.h | 22 +- source/gameengine/Ketsji/KX_PythonInit.cpp | 401 ++- source/gameengine/Ketsji/KX_PythonInit.h | 17 +- .../gameengine/Ketsji/KX_PythonInitTypes.cpp | 14 +- source/gameengine/Ketsji/KX_PythonInitTypes.h | 6 +- source/gameengine/Ketsji/KX_PythonMain.cpp | 12 +- source/gameengine/Ketsji/KX_PythonMain.h | 11 +- source/gameengine/Ketsji/KX_PythonSeq.cpp | 56 +- source/gameengine/Ketsji/KX_PythonSeq.h | 8 +- source/gameengine/Ketsji/KX_RadarSensor.cpp | 4 +- source/gameengine/Ketsji/KX_RadarSensor.h | 3 +- source/gameengine/Ketsji/KX_RayCast.cpp | 6 +- source/gameengine/Ketsji/KX_RayEventManager.h | 3 +- source/gameengine/Ketsji/KX_RaySensor.cpp | 2 +- source/gameengine/Ketsji/KX_RaySensor.h | 7 +- .../Ketsji/KX_SCA_AddObjectActuator.cpp | 12 +- .../Ketsji/KX_SCA_AddObjectActuator.h | 13 +- .../Ketsji/KX_SCA_DynamicActuator.cpp | 6 +- .../Ketsji/KX_SCA_ReplaceMeshActuator.cpp | 2 +- .../Ketsji/KX_SCA_ReplaceMeshActuator.h | 7 +- .../KX_SG_BoneParentNodeRelationship.cpp | 6 +- .../Ketsji/KX_SG_BoneParentNodeRelationship.h | 2 +- .../Ketsji/KX_SG_NodeRelationships.cpp | 16 +- .../Ketsji/KX_SG_NodeRelationships.h | 12 +- source/gameengine/Ketsji/KX_Scene.cpp | 162 +- source/gameengine/Ketsji/KX_Scene.h | 43 +- source/gameengine/Ketsji/KX_SceneActuator.cpp | 4 +- source/gameengine/Ketsji/KX_SceneActuator.h | 5 +- source/gameengine/Ketsji/KX_SoundActuator.cpp | 37 +- source/gameengine/Ketsji/KX_SoundActuator.h | 17 +- .../gameengine/Ketsji/KX_SteeringActuator.cpp | 32 +- .../gameengine/Ketsji/KX_SteeringActuator.h | 17 +- .../gameengine/Ketsji/KX_TimeCategoryLogger.h | 7 +- source/gameengine/Ketsji/KX_TimeLogger.h | 9 +- .../gameengine/Ketsji/KX_TouchEventManager.h | 3 +- source/gameengine/Ketsji/KX_TouchSensor.cpp | 8 +- source/gameengine/Ketsji/KX_TouchSensor.h | 5 +- .../gameengine/Ketsji/KX_TrackToActuator.cpp | 20 +- source/gameengine/Ketsji/KX_TrackToActuator.h | 9 +- .../gameengine/Ketsji/KX_VehicleWrapper.cpp | 34 +- source/gameengine/Ketsji/KX_VehicleWrapper.h | 4 +- source/gameengine/Ketsji/KX_VertexProxy.cpp | 112 +- source/gameengine/Ketsji/KX_VertexProxy.h | 35 +- source/gameengine/Ketsji/KX_WorldInfo.h | 3 +- .../gameengine/Ketsji/KX_WorldIpoController.h | 9 +- .../NG_LoopBackNetworkDeviceInterface.h | 5 +- .../Network/NG_NetworkDeviceInterface.h | 3 +- source/gameengine/Network/NG_NetworkMessage.h | 3 +- source/gameengine/Network/NG_NetworkObject.h | 3 +- source/gameengine/Network/NG_NetworkScene.h | 7 +- .../gameengine/Physics/Bullet/CMakeLists.txt | 2 +- .../Physics/Bullet/CcdGraphicController.h | 4 +- .../Physics/Bullet/CcdPhysicsController.cpp | 162 +- .../Physics/Bullet/CcdPhysicsController.h | 6 +- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 202 +- .../Physics/Bullet/CcdPhysicsEnvironment.h | 13 +- .../Physics/Dummy/DummyPhysicsEnvironment.h | 11 +- .../gameengine/Physics/common/CMakeLists.txt | 1 + .../Physics/common/PHY_DynamicTypes.h | 14 +- .../Physics/common/PHY_ICharacter.h | 30 + .../Physics/common/PHY_IController.h | 5 +- .../Physics/common/PHY_IGraphicController.h | 3 +- .../Physics/common/PHY_IMotionState.h | 5 +- .../Physics/common/PHY_IPhysicsController.h | 3 +- .../Physics/common/PHY_IPhysicsEnvironment.h | 11 +- .../gameengine/Physics/common/PHY_IVehicle.h | 2 +- source/gameengine/Physics/common/PHY_Pro.h | 3 +- .../Rasterizer/RAS_2DFilterManager.cpp | 10 +- .../Rasterizer/RAS_BucketManager.cpp | 21 +- .../gameengine/Rasterizer/RAS_BucketManager.h | 4 +- source/gameengine/Rasterizer/RAS_CameraData.h | 3 +- source/gameengine/Rasterizer/RAS_Deformer.h | 8 +- .../Rasterizer/RAS_FramingManager.cpp | 14 +- .../Rasterizer/RAS_FramingManager.h | 8 +- source/gameengine/Rasterizer/RAS_ICanvas.h | 10 +- .../Rasterizer/RAS_IPolygonMaterial.cpp | 16 +- .../Rasterizer/RAS_IPolygonMaterial.h | 3 +- .../gameengine/Rasterizer/RAS_IRasterizer.h | 10 +- .../gameengine/Rasterizer/RAS_IRenderTools.h | 35 +- .../gameengine/Rasterizer/RAS_LightObject.h | 3 +- .../Rasterizer/RAS_MaterialBucket.cpp | 24 +- .../Rasterizer/RAS_MaterialBucket.h | 2 +- .../gameengine/Rasterizer/RAS_MeshObject.cpp | 6 +- source/gameengine/Rasterizer/RAS_MeshObject.h | 9 +- .../gameengine/Rasterizer/RAS_ObjectColor.h | 3 +- .../RAS_OpenGLFilters/RAS_Erosion2DFilter.h | 2 +- .../RAS_ListRasterizer.cpp | 4 +- .../RAS_OpenGLRasterizer.cpp | 110 +- .../RAS_OpenGLRasterizer.h | 10 +- .../RAS_VAOpenGLRasterizer.cpp | 10 +- .../RAS_VAOpenGLRasterizer.h | 3 +- source/gameengine/Rasterizer/RAS_Polygon.cpp | 7 +- source/gameengine/Rasterizer/RAS_Rect.h | 3 +- source/gameengine/Rasterizer/RAS_TexMatrix.h | 3 +- source/gameengine/Rasterizer/RAS_TexVert.cpp | 2 +- source/gameengine/Rasterizer/RAS_TexVert.h | 3 +- .../gameengine/Rasterizer/RAS_texmatrix.cpp | 4 +- source/gameengine/SceneGraph/SG_Controller.h | 11 +- source/gameengine/SceneGraph/SG_DList.h | 3 +- source/gameengine/SceneGraph/SG_IObject.cpp | 2 +- source/gameengine/SceneGraph/SG_IObject.h | 11 +- source/gameengine/SceneGraph/SG_Node.cpp | 2 +- source/gameengine/SceneGraph/SG_Node.h | 21 +- .../gameengine/SceneGraph/SG_ParentRelation.h | 2 +- source/gameengine/SceneGraph/SG_QList.h | 3 +- source/gameengine/SceneGraph/SG_Spatial.cpp | 6 +- source/gameengine/SceneGraph/SG_Spatial.h | 15 +- source/gameengine/SceneGraph/SG_Tree.cpp | 2 +- source/gameengine/VideoTexture/BlendType.h | 13 +- source/gameengine/VideoTexture/FilterBase.cpp | 10 +- source/gameengine/VideoTexture/FilterBase.h | 16 +- .../VideoTexture/FilterBlueScreen.cpp | 10 +- .../gameengine/VideoTexture/FilterColor.cpp | 12 +- .../gameengine/VideoTexture/FilterNormal.cpp | 10 +- source/gameengine/VideoTexture/FilterSource.h | 60 +- source/gameengine/VideoTexture/ImageBase.cpp | 108 +- source/gameengine/VideoTexture/ImageBase.h | 58 +- source/gameengine/VideoTexture/ImageBuff.cpp | 16 +- source/gameengine/VideoTexture/ImageMix.cpp | 6 +- .../gameengine/VideoTexture/ImageRender.cpp | 30 +- .../gameengine/VideoTexture/ImageViewport.cpp | 86 +- .../gameengine/VideoTexture/ImageViewport.h | 12 +- source/gameengine/VideoTexture/PyTypeList.cpp | 8 +- source/gameengine/VideoTexture/PyTypeList.h | 14 +- source/gameengine/VideoTexture/Texture.cpp | 36 +- source/gameengine/VideoTexture/Texture.h | 8 +- source/gameengine/VideoTexture/VideoBase.cpp | 29 +- source/gameengine/VideoTexture/VideoBase.h | 28 +- .../gameengine/VideoTexture/VideoFFmpeg.cpp | 30 +- source/gameengine/VideoTexture/VideoFFmpeg.h | 6 +- .../gameengine/VideoTexture/blendVideoTex.cpp | 20 +- source/tests/CMakeLists.txt | 8 +- source/tests/batch_import.py | 12 +- source/tests/bl_load_addons.py | 2 +- source/tests/bl_load_py_modules.py | 2 +- source/tests/bl_mesh_modifiers.py | 2 +- source/tests/bl_rna_wiki_reference.py | 52 +- source/tests/bl_run_operators.py | 106 +- source/tests/bl_test.py | 2 +- source/tests/rna_array.py | 12 +- 2477 files changed, 80826 insertions(+), 56797 deletions(-) create mode 100755 build_files/build_environment/prepare_release_env.sh create mode 100644 build_files/buildbot/config/user-config-glibc211-i686.py create mode 100644 build_files/buildbot/config/user-config-glibc211-x86_64.py rename build_files/buildbot/config/{user-config-i686.py => user-config-glibc27-i686.py} (90%) rename build_files/buildbot/config/{user-config-x86_64.py => user-config-glibc27-x86_64.py} (93%) create mode 100644 build_files/buildbot/config/user-config-player-glibc211-i686.py create mode 100644 build_files/buildbot/config/user-config-player-glibc211-x86_64.py rename build_files/buildbot/config/{user-config-player-i686.py => user-config-player-glibc27-i686.py} (90%) rename build_files/buildbot/config/{user-config-player-x86_64.py => user-config-player-glibc27-x86_64.py} (90%) create mode 100644 build_files/cmake/clang_array_check.py create mode 100644 build_files/cmake/cmake_static_check_clang_array.py create mode 100644 extern/Eigen3/Eigen/CholmodSupport create mode 100644 extern/Eigen3/Eigen/IterativeLinearSolvers create mode 100644 extern/Eigen3/Eigen/OrderingMethods create mode 100644 extern/Eigen3/Eigen/PaStiXSupport create mode 100644 extern/Eigen3/Eigen/PardisoSupport create mode 100644 extern/Eigen3/Eigen/SparseCholesky create mode 100644 extern/Eigen3/Eigen/SparseCore create mode 100644 extern/Eigen3/Eigen/SuperLUSupport create mode 100644 extern/Eigen3/Eigen/UmfPackSupport create mode 100644 extern/Eigen3/Eigen/src/Cholesky/LLT_MKL.h create mode 100644 extern/Eigen3/Eigen/src/CholmodSupport/CholmodSupport.h create mode 100644 extern/Eigen3/Eigen/src/Core/Assign_MKL.h create mode 100644 extern/Eigen3/Eigen/src/Core/GeneralProduct.h create mode 100644 extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_MKL.h create mode 100644 extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix_MKL.h create mode 100644 extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector_MKL.h create mode 100644 extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h create mode 100644 extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h create mode 100644 extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h create mode 100644 extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector_MKL.h create mode 100644 extern/Eigen3/Eigen/src/Core/products/TriangularSolverMatrix_MKL.h create mode 100644 extern/Eigen3/Eigen/src/Core/util/MKL_support.h create mode 100644 extern/Eigen3/Eigen/src/Core/util/NonMPL2.h create mode 100644 extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur_MKL.h delete mode 100644 extern/Eigen3/Eigen/src/Eigenvalues/EigenvaluesCommon.h create mode 100644 extern/Eigen3/Eigen/src/Eigenvalues/RealSchur_MKL.h create mode 100644 extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h create mode 100644 extern/Eigen3/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h create mode 100644 extern/Eigen3/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h create mode 100644 extern/Eigen3/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h create mode 100644 extern/Eigen3/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h create mode 100644 extern/Eigen3/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h create mode 100644 extern/Eigen3/Eigen/src/LU/PartialPivLU_MKL.h create mode 100644 extern/Eigen3/Eigen/src/OrderingMethods/Amd.h create mode 100644 extern/Eigen3/Eigen/src/PaStiXSupport/PaStiXSupport.h create mode 100644 extern/Eigen3/Eigen/src/PardisoSupport/PardisoSupport.h create mode 100644 extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR_MKL.h create mode 100644 extern/Eigen3/Eigen/src/QR/HouseholderQR_MKL.h create mode 100644 extern/Eigen3/Eigen/src/SVD/JacobiSVD_MKL.h delete mode 100644 extern/Eigen3/Eigen/src/Sparse/DynamicSparseMatrix.h delete mode 100644 extern/Eigen3/Eigen/src/Sparse/SparseCwiseUnaryOp.h delete mode 100644 extern/Eigen3/Eigen/src/Sparse/SparseFuzzy.h delete mode 100644 extern/Eigen3/Eigen/src/Sparse/SparseMatrix.h delete mode 100644 extern/Eigen3/Eigen/src/Sparse/SparseSparseProduct.h delete mode 100644 extern/Eigen3/Eigen/src/Sparse/SparseTriangularView.h create mode 100644 extern/Eigen3/Eigen/src/SparseCholesky/SimplicialCholesky.h rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/AmbiVector.h (89%) rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/CompressedStorage.h (84%) create mode 100644 extern/Eigen3/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/CoreIterators.h (62%) rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/MappedSparseMatrix.h (68%) rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/SparseAssign.h (100%) rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/SparseBlock.h (66%) rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/SparseCwiseBinaryOp.h (77%) create mode 100644 extern/Eigen3/Eigen/src/SparseCore/SparseCwiseUnaryOp.h rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/SparseDenseProduct.h (56%) rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/SparseDiagonalProduct.h (87%) rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/SparseDot.h (67%) create mode 100644 extern/Eigen3/Eigen/src/SparseCore/SparseFuzzy.h create mode 100644 extern/Eigen3/Eigen/src/SparseCore/SparseMatrix.h rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/SparseMatrixBase.h (52%) create mode 100644 extern/Eigen3/Eigen/src/SparseCore/SparsePermutation.h rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/SparseProduct.h (62%) rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/SparseRedux.h (56%) rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/SparseSelfAdjointView.h (75%) create mode 100644 extern/Eigen3/Eigen/src/SparseCore/SparseSparseProductWithPruning.h rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/SparseTranspose.h (53%) create mode 100644 extern/Eigen3/Eigen/src/SparseCore/SparseTriangularView.h rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/SparseUtil.h (60%) rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/SparseVector.h (63%) rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/SparseView.h (64%) rename extern/Eigen3/Eigen/src/{Sparse => SparseCore}/TriangularSolver.h (83%) create mode 100644 extern/Eigen3/Eigen/src/SuperLUSupport/SuperLUSupport.h create mode 100644 extern/Eigen3/Eigen/src/UmfPackSupport/UmfPackSupport.h create mode 100644 extern/Eigen3/Eigen/src/misc/SparseSolve.h create mode 100644 extern/Eigen3/Eigen/src/misc/blas.h create mode 100644 extern/bullet2/patches/convex_hull.patch create mode 100644 extern/libmv/third_party/ceres/include/ceres/crs_matrix.h create mode 100644 extern/libmv/third_party/ceres/include/ceres/fpclassify.h rename extern/libmv/third_party/ceres/internal/ceres/{levenberg_marquardt.h => array_utils.cc} (64%) create mode 100644 extern/libmv/third_party/ceres/internal/ceres/array_utils.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/cxsparse.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/cxsparse.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/generate_eliminator_specialization.py delete mode 100644 extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/split.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.h create mode 100644 extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.cc create mode 100644 extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.h create mode 100644 extern/libmv/third_party/ceres/patches/msvc_glog_fix.patch delete mode 100644 extern/libmv/third_party/ceres/patches/msvc_isfinite.patch create mode 100644 extern/libmv/third_party/ceres/patches/no_previous_declaration_fix.patch create mode 100644 intern/audaspace/intern/AUD_ILockable.h create mode 100644 intern/audaspace/intern/AUD_MutexLock.h delete mode 100644 intern/container/CTR_List.h delete mode 100644 intern/container/CTR_UHeap.h delete mode 100644 intern/container/intern/CTR_List.cpp create mode 100644 intern/cycles/blender/addon/osl.py rename intern/cycles/kernel/{svm => closure}/bsdf.h (99%) rename intern/cycles/kernel/{svm => closure}/bsdf_ashikhmin_velvet.h (75%) rename intern/cycles/kernel/{svm => closure}/bsdf_diffuse.h (57%) rename intern/cycles/kernel/{svm => closure}/bsdf_microfacet.h (81%) rename intern/cycles/kernel/{svm => closure}/bsdf_oren_nayar.h (61%) rename intern/cycles/kernel/{svm => closure}/bsdf_reflection.h (69%) rename intern/cycles/kernel/{svm => closure}/bsdf_refraction.h (72%) rename intern/cycles/kernel/{svm => closure}/bsdf_transparent.h (74%) rename intern/cycles/kernel/{svm => closure}/bsdf_ward.h (77%) rename intern/cycles/kernel/{svm => closure}/bsdf_westin.h (67%) rename intern/cycles/kernel/{svm => closure}/emissive.h (86%) rename intern/cycles/kernel/{svm => closure}/volume.h (65%) delete mode 100644 intern/cycles/kernel/kernel_mbvh.h delete mode 100644 intern/cycles/kernel/kernel_qbvh.h delete mode 100644 intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp delete mode 100644 intern/cycles/kernel/osl/bsdf_diffuse.cpp delete mode 100644 intern/cycles/kernel/osl/bsdf_microfacet.cpp delete mode 100644 intern/cycles/kernel/osl/bsdf_oren_nayar.cpp delete mode 100644 intern/cycles/kernel/osl/bsdf_phong.cpp delete mode 100644 intern/cycles/kernel/osl/bsdf_reflection.cpp delete mode 100644 intern/cycles/kernel/osl/bsdf_refraction.cpp delete mode 100644 intern/cycles/kernel/osl/bsdf_transparent.cpp delete mode 100644 intern/cycles/kernel/osl/bsdf_ward.cpp delete mode 100644 intern/cycles/kernel/osl/bsdf_westin.cpp delete mode 100644 intern/cycles/kernel/osl/bssrdf.cpp delete mode 100644 intern/cycles/kernel/osl/debug.cpp delete mode 100644 intern/cycles/kernel/osl/nodes/node_voronoi_texture.osl delete mode 100644 intern/cycles/kernel/osl/vol_subsurface.cpp rename intern/cycles/kernel/{osl/nodes => shaders}/CMakeLists.txt (81%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_add_closure.osl (100%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_attribute.osl (95%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_background.osl (95%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_brick_texture.osl (79%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_brightness.osl (85%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_bump.osl (67%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_camera.osl (100%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_checker_texture.osl (86%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_color.h (100%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_combine_rgb.osl (100%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_convert_from_color.osl (87%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_convert_from_float.osl (96%) rename intern/cycles/kernel/{osl/nodes/node_image_texture.osl => shaders/node_convert_from_int.osl} (70%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_convert_from_normal.osl (88%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_convert_from_point.osl (88%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_convert_from_vector.osl (88%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_diffuse_bsdf.osl (97%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_emission.osl (88%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_environment_texture.osl (97%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_fresnel.h (100%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_fresnel.osl (96%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_gamma.osl (100%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_geometry.osl (66%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_glass_bsdf.osl (68%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_glossy_bsdf.osl (80%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_gradient_texture.osl (68%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_holdout.osl (100%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_hsv.osl (100%) create mode 100644 intern/cycles/kernel/shaders/node_image_texture.osl rename intern/cycles/kernel/{osl/nodes => shaders}/node_invert.osl (100%) rename intern/cycles/kernel/{osl/nodes/node_blend_weight.osl => shaders/node_layer_weight.osl} (71%) create mode 100644 intern/cycles/kernel/shaders/node_light_falloff.osl rename intern/cycles/kernel/{osl/nodes => shaders}/node_light_path.osl (91%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_magic_texture.osl (50%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_mapping.osl (87%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_math.osl (75%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_mix.osl (64%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_mix_closure.osl (95%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_musgrave_texture.osl (69%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_noise_texture.osl (94%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_normal.osl (100%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_object_info.osl (68%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_output_displacement.osl (92%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_output_surface.osl (100%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_output_volume.osl (100%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_particle_info.osl (70%) create mode 100644 intern/cycles/kernel/shaders/node_rgb_ramp.osl rename intern/cycles/kernel/{osl/nodes => shaders}/node_separate_rgb.osl (100%) rename intern/cycles/kernel/{osl/nodes/node_ward_bsdf.osl => shaders/node_set_normal.osl} (72%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_sky_texture.osl (66%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_texture.h (94%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_texture_coordinate.osl (72%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_translucent_bsdf.osl (96%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_transparent_bsdf.osl (96%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_value.osl (100%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_vector_math.osl (81%) rename intern/cycles/kernel/{osl/nodes => shaders}/node_velvet_bsdf.osl (95%) create mode 100644 intern/cycles/kernel/shaders/node_voronoi_texture.osl create mode 100644 intern/cycles/kernel/shaders/node_ward_bsdf.osl rename intern/cycles/kernel/{osl/nodes => shaders}/node_wave_texture.osl (86%) rename intern/cycles/kernel/{osl/nodes => shaders}/oslutil.h (98%) rename intern/cycles/kernel/{osl/nodes => shaders}/stdosl.h (78%) create mode 100644 intern/cycles/util/util_stats.h delete mode 100644 intern/decimation/CMakeLists.txt delete mode 100644 intern/decimation/SConscript delete mode 100644 intern/decimation/extern/LOD_decimation.h delete mode 100644 intern/decimation/intern/LOD_DecimationClass.h delete mode 100644 intern/decimation/intern/LOD_EdgeCollapser.cpp delete mode 100644 intern/decimation/intern/LOD_EdgeCollapser.h delete mode 100644 intern/decimation/intern/LOD_ExternBufferEditor.h delete mode 100644 intern/decimation/intern/LOD_ExternNormalEditor.cpp delete mode 100644 intern/decimation/intern/LOD_ExternNormalEditor.h delete mode 100644 intern/decimation/intern/LOD_FaceNormalEditor.cpp delete mode 100644 intern/decimation/intern/LOD_FaceNormalEditor.h delete mode 100644 intern/decimation/intern/LOD_ManMesh2.cpp delete mode 100644 intern/decimation/intern/LOD_ManMesh2.h delete mode 100644 intern/decimation/intern/LOD_MeshBounds.h delete mode 100644 intern/decimation/intern/LOD_MeshPrimitives.cpp delete mode 100644 intern/decimation/intern/LOD_MeshPrimitives.h delete mode 100644 intern/decimation/intern/LOD_QSDecimator.cpp delete mode 100644 intern/decimation/intern/LOD_QSDecimator.h delete mode 100644 intern/decimation/intern/LOD_Quadric.h delete mode 100644 intern/decimation/intern/LOD_QuadricEditor.cpp delete mode 100644 intern/decimation/intern/LOD_QuadricEditor.h delete mode 100644 intern/decimation/intern/LOD_decimation.cpp delete mode 100644 intern/raskter/raskter_kdtree.c delete mode 100644 intern/raskter/raskter_kdtree.h delete mode 100644 intern/raskter/raskter_mt.c create mode 100644 intern/smoke/intern/spectrum.cpp create mode 100644 intern/smoke/intern/spectrum.h create mode 100755 release/scripts/modules/bl_i18n_utils/update_languages_menu.py create mode 100644 release/scripts/templates/script_stub.py rename source/blender/avi/intern/{codecs.c => avi_codecs.c} (96%) rename source/blender/avi/intern/{endian.c => avi_endian.c} (91%) rename source/blender/avi/intern/{endian.h => avi_endian.h} (90%) rename source/blender/avi/intern/{mjpeg.c => avi_mjpeg.c} (99%) rename source/blender/avi/intern/{mjpeg.h => avi_mjpeg.h} (91%) rename source/blender/avi/intern/{options.c => avi_options.c} (98%) rename source/blender/avi/intern/{avirgb.c => avi_rgb.c} (98%) rename source/blender/avi/intern/{avirgb.h => avi_rgb.h} (76%) rename source/blender/avi/intern/{rgb32.c => avi_rgb32.c} (97%) rename source/blender/avi/intern/{rgb32.h => avi_rgb32.h} (76%) rename intern/decimation/intern/LOD_MeshException.h => source/blender/blenlib/BLI_quadric.h (50%) create mode 100644 source/blender/blenlib/intern/quadric.c create mode 100644 source/blender/bmesh/intern/bmesh_decimate.h create mode 100644 source/blender/bmesh/intern/bmesh_decimate_collapse.c create mode 100644 source/blender/bmesh/intern/bmesh_decimate_dissolve.c create mode 100644 source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c create mode 100644 source/blender/bmesh/operators/bmo_similar.c create mode 100644 source/blender/bmesh/operators/bmo_smooth_laplacian.c create mode 100644 source/blender/bmesh/operators/bmo_symmetrize.c create mode 100644 source/blender/bmesh/operators/bmo_unsubdivide.c create mode 100644 source/blender/compositor/nodes/COM_PixelateNode.cpp create mode 100644 source/blender/compositor/nodes/COM_PixelateNode.h create mode 100644 source/blender/compositor/operations/COM_PixelateOperation.cpp create mode 100644 source/blender/compositor/operations/COM_PixelateOperation.h create mode 100644 source/blender/editors/space_view3d/view3d_iterators.c create mode 100644 source/blender/editors/space_view3d/view3d_project.c delete mode 100644 source/blender/imbuf/intern/cineon/logImageLib.c create mode 100644 source/blender/imbuf/intern/dds/FlipDXT.cpp create mode 100644 source/blender/imbuf/intern/dds/FlipDXT.h create mode 100644 source/blender/modifiers/intern/MOD_laplaciansmooth.c create mode 100644 source/blender/nodes/composite/nodes/node_composite_pixelate.c create mode 100644 source/blender/nodes/shader/nodes/node_shader_bump.c create mode 100644 source/blender/nodes/shader/nodes/node_shader_script.c create mode 100644 source/gameengine/Ketsji/KX_CharacterWrapper.cpp create mode 100644 source/gameengine/Ketsji/KX_CharacterWrapper.h create mode 100644 source/gameengine/Physics/common/PHY_ICharacter.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 83e094b4375..b53c6f6b71f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -120,7 +120,7 @@ option(WITH_INTERNATIONAL "Enable I18N (International fonts and text)" ON) option(WITH_PYTHON "Enable Embedded Python API (only disable for development)" ON) option(WITH_PYTHON_SECURITY "Disables execution of scripts within blend files by default (recommend to leave off)" OFF) mark_as_advanced(WITH_PYTHON) # dont want people disabling this unless they really know what they are doing. -mark_as_advanced(WITH_PYTHON_SECURITY) # some distrobutions see this as a security issue, rather than have them patch it, make a build option. +mark_as_advanced(WITH_PYTHON_SECURITY) # some distributions see this as a security issue, rather than have them patch it, make a build option. option(WITH_PYTHON_SAFETY "Enable internal API error checking to track invalid data to prevent crash on access (at the expense of some effeciency, only enable for development)." OFF) option(WITH_PYTHON_MODULE "Enable building as a python module which runs without a user interface, like running regular blender in background mode (experimental, only enable for development)" OFF) @@ -186,12 +186,11 @@ unset(PLATFORM_DEFAULT) # Modifiers -option(WITH_MOD_FLUID "Enable Elbeem Modifier (Fluid Simulation)" ON) -option(WITH_MOD_SMOKE "Enable Smoke Modifier (Smoke Simulation)" ON) -option(WITH_MOD_DECIMATE "Enable Decimate Modifier" ON) -option(WITH_MOD_BOOLEAN "Enable Boolean Modifier" ON) -option(WITH_MOD_REMESH "Enable Remesh Modifier" ON) -option(WITH_MOD_CLOTH_ELTOPO "Enable Experimental cloth solver" OFF) +option(WITH_MOD_FLUID "Enable Elbeem Modifier (Fluid Simulation)" ON) +option(WITH_MOD_SMOKE "Enable Smoke Modifier (Smoke Simulation)" ON) +option(WITH_MOD_BOOLEAN "Enable Boolean Modifier" ON) +option(WITH_MOD_REMESH "Enable Remesh Modifier" ON) +option(WITH_MOD_CLOTH_ELTOPO "Enable Experimental cloth solver" OFF) mark_as_advanced(WITH_MOD_CLOTH_ELTOPO) option(WITH_MOD_OCEANSIM "Enable Ocean Modifier" OFF) @@ -206,6 +205,7 @@ option(WITH_IMAGE_REDCODE "Enable RedCode Image Support" OFF) option(WITH_IMAGE_FRAMESERVER "Enable image FrameServer Support for rendering" ON) # Audio/Video format support +option(WITH_CODEC_AVI "Enable Blenders own AVI file support (raw/jpeg)" ON) option(WITH_CODEC_FFMPEG "Enable FFMPeg Support (http://ffmpeg.org)" OFF) option(WITH_CODEC_SNDFILE "Enable libsndfile Support (http://www.mega-nerd.com/libsndfile)" OFF) @@ -254,6 +254,9 @@ set(CYCLES_CUDA_BINARIES_ARCH sm_13 sm_20 sm_21 sm_30 CACHE STRING "CUDA archite mark_as_advanced(CYCLES_CUDA_BINARIES_ARCH) unset(PLATFORM_DEFAULT) +# LLVM +option(WITH_LLVM "Use LLVM" OFF) + # disable for now, but plan to support on all platforms eventually option(WITH_MEM_JEMALLOC "Enable malloc replacement (http://www.canonware.com/jemalloc)" OFF) mark_as_advanced(WITH_MEM_JEMALLOC) @@ -293,11 +296,11 @@ if(APPLE) if(${CMAKE_GENERATOR} MATCHES "Xcode") - ##### workaround for actual official cmake incompatibility with xcode 4.3 ##### + ##### workaround for actual official cmake incompatibility with xcode 4.3 ##### if(${XCODE_VERSION} MATCHES '') # cmake fails due looking for xcode in the wrong path, thus will be empty var message("Official cmake does not yet support Xcode 4.3, get a patched version here: http://www.jensverwiebe.de/Blender/CMake%202.8-7patched.zip") endif() - ### end workaround for actual official cmake incompatibility with xcode 4.3 ### + ### end workaround for actual official cmake incompatibility with xcode 4.3 ### if(${XCODE_VERSION} VERSION_EQUAL 4 OR ${XCODE_VERSION} VERSION_GREATER 4 AND ${XCODE_VERSION} VERSION_LESS 4.3) # Xcode 4 defaults to the Apple LLVM Compiler. @@ -316,6 +319,9 @@ if(APPLE) option(WITH_COCOA "Use Cocoa framework instead of deprecated Carbon" ON) option(USE_QTKIT "Use QtKit instead of Carbon quicktime (needed for having partial quicktime for 64bit)" OFF) option(WITH_LIBS10.5 "Use 10.5 libs (needed for 64bit builds)" OFF) + if(CMAKE_OSX_ARCHITECTURES MATCHES x86_64) + set(USE_QTKIT ON CACHE BOOL "ON" FORCE) # no Quicktime in 64bit + endif() endif() @@ -371,13 +377,20 @@ if(WITH_CYCLES OR WITH_MOD_BOOLEAN) set(WITH_BOOST ON) endif() -# don't store paths to libs for portable distrobution +# auto enable llvm for cycles_osl +if(WITH_CYCLES_OSL) + set(WITH_LLVM ON CACHE BOOL "ON" FORCE) +endif() + +# don't store paths to libs for portable distribution if(WITH_INSTALL_PORTABLE) set(CMAKE_SKIP_BUILD_RPATH TRUE) endif() if(WITH_GHOST_SDL OR WITH_HEADLESS) set(WITH_GHOST_XDND OFF) + set(WITH_X11_XF86VMODE OFF) + set(WITH_X11_XINPUT OFF) endif() if(MINGW) @@ -563,7 +576,14 @@ if(UNIX AND NOT APPLE) endif() mark_as_advanced(FFMPEG) - set(FFMPEG_INCLUDE_DIRS ${FFMPEG}/include ${FFMPEG}/include/ffmpeg) + + # lame, but until we have proper find module for ffmpeg + set(FFMPEG_INCLUDE_DIRS ${FFMPEG}/include) + if(EXISTS "${FFMPEG}/include/ffmpeg/") + list(APPEND FFMPEG_INCLUDE_DIRS "${FFMPEG}/include/ffmpeg") + endif() + # end lameness + mark_as_advanced(FFMPEG_LIBRARIES) set(FFMPEG_LIBPATH ${FFMPEG}/lib) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__STDC_CONSTANT_MACROS") @@ -691,6 +711,47 @@ if(UNIX AND NOT APPLE) endif() endif() + if(WITH_LLVM) + set(LLVM_DIRECTORY ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation") + set(LLVM_VERSION "3.0" CACHE STRING "Version of LLVM to use") + set(LLVM_STATIC YES) + if(LLVM_DIRECTORY) + set(LLVM_CONFIG "${LLVM_DIRECTORY}/bin/llvm-config") + else() + set(LLVM_CONFIG llvm-config) + endif() + execute_process(COMMAND ${LLVM_CONFIG} --version + OUTPUT_VARIABLE LLVM_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND ${LLVM_CONFIG} --prefix + OUTPUT_VARIABLE LLVM_DIRECTORY + OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND ${LLVM_CONFIG} --libdir + OUTPUT_VARIABLE LLVM_LIB_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE) + find_library(LLVM_LIBRARY + NAMES libLLVMAnalysis.a # first of a whole bunch of libs to get + PATHS ${LLVM_LIB_DIR}) + message(STATUS "LLVM version = ${LLVM_VERSION}") + message(STATUS "LLVM dir = ${LLVM_DIRECTORY}") + message(STATUS "LLVM lib dir = ${LLVM_LIB_DIR}") + + if(LLVM_LIBRARY AND LLVM_DIRECTORY AND LLVM_LIB_DIR) + if(LLVM_STATIC) + # if static LLVM libraries were requested, use llvm-config to generate + # the list of what libraries we need, and substitute that in the right + # way for LLVM_LIBRARY. + execute_process(COMMAND ${LLVM_CONFIG} --libfiles + OUTPUT_VARIABLE LLVM_LIBRARY + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE " " ";" LLVM_LIBRARY ${LLVM_LIBRARY}) + endif() + message(STATUS "LLVM library = ${LLVM_LIBRARY}") + else() + message(FATAL_ERROR "LLVM not found.") + endif() + endif() + if(WITH_CYCLES_OSL) set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation") @@ -699,8 +760,9 @@ if(UNIX AND NOT APPLE) find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib) - # WARNING! depends on correct order of OSL libs linking - list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} ${OSL_LIB_EXEC} ${OSL_LIB_QUERY}) + # Note: --whole-archive is needed to force loading of all symbols in liboslexec, + # otherwise LLVM is missing the osl_allocate_closure_component function + list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} -Wl,--whole-archive ${OSL_LIB_EXEC} -Wl,--no-whole-archive ${OSL_LIB_QUERY}) find_path(OSL_INCLUDES OSL/oslclosure.h PATHS ${CYCLES_OSL}/include) find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin) @@ -712,8 +774,6 @@ if(UNIX AND NOT APPLE) else() message(STATUS "OSL not found") endif() - - include_directories(${OSL_INCLUDES}) endif() # OpenSuse needs lutil, ArchLinux not, for now keep, can avoid by using --as-needed @@ -764,7 +824,7 @@ if(UNIX AND NOT APPLE) elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing") # Solaris CC - elseif(CMAKE_CXX_COMPILER_ID MATCHES "SunPro") + elseif(CMAKE_CXX_COMPILER_ID MATCHES "SunPro") set(PLATFORM_CFLAGS "-pipe -features=extensions -fPIC -D__FUNCTION__=__func__") # Intel C++ Compiler @@ -798,7 +858,7 @@ elseif(WIN32) if(CMAKE_COMPILER_IS_GNUCC) set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw32) - # Setup 64bit and 64bit windows systems + # Setup 64bit and 64bit windows systems if(WITH_MINGW64) message("Set 64 bit compiler for MinGW.") set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw64) @@ -881,8 +941,6 @@ elseif(WIN32) else() message(STATUS "OSL not found") endif() - - include_directories(${OSL_INCLUDES}) endif() if(MSVC) @@ -926,7 +984,7 @@ elseif(WIN32) if(WITH_MOD_CLOTH_ELTOPO) set(LAPACK ${LIBDIR}/lapack) # set(LAPACK_INCLUDE_DIR ${LAPACK}/include) - set(LAPACK_LIBPATH ${LAPACK}/lib) + set(LAPACK_LIBPATH ${LAPACK}/lib) set(LAPACK_LIBRARIES ${LIBDIR}/lapack/lib/libf2c.lib ${LIBDIR}/lapack/lib/clapack_nowrap.lib @@ -1066,13 +1124,15 @@ elseif(WIN32) else() set(BOOST_LIBPATH ${BOOST}/lib) set(BOOST_POSTFIX "vc90-mt-s-1_49.lib") - set(BOOST_DEBUG_POSTFIX "vc90-mt-sgd-1_49.lib") + set(BOOST_DEBUG_POSTFIX "vc90-mt-sgd-1_49.lib") endif() set(BOOST_LIBRARIES optimized libboost_date_time-${BOOST_POSTFIX} optimized libboost_filesystem-${BOOST_POSTFIX} - optimized libboost_regex-${BOOST_POSTFIX} optimized libboost_system-${BOOST_POSTFIX} optimized libboost_thread-${BOOST_POSTFIX} + optimized libboost_regex-${BOOST_POSTFIX} + optimized libboost_system-${BOOST_POSTFIX} optimized libboost_thread-${BOOST_POSTFIX} debug libboost_date_time-${BOOST_DEBUG_POSTFIX} debug libboost_filesystem-${BOOST_DEBUG_POSTFIX} - debug libboost_regex-${BOOST_DEBUG_POSTFIX} debug libboost_system-${BOOST_DEBUG_POSTFIX} debug libboost_thread-${BOOST_DEBUG_POSTFIX}) + debug libboost_regex-${BOOST_DEBUG_POSTFIX} + debug libboost_system-${BOOST_DEBUG_POSTFIX} debug libboost_thread-${BOOST_DEBUG_POSTFIX}) set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB") endif() @@ -1088,7 +1148,7 @@ elseif(WIN32) set(OPENCOLORIO ${LIBDIR}/opencolorio) set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include) set(OPENCOLORIO_LIBRARIES OpenColorIO) - set_lib_path(OPENCOLORIO_LIBPATH "opencolorio/lib") + set(OPENCOLORIO_LIBPATH ${LIBDIR}/opencolorio/lib) set(OPENCOLORIO_DEFINITIONS) endif() @@ -1104,10 +1164,10 @@ elseif(WIN32) set(PLATFORM_LINKFLAGS_DEBUG "/NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libc.lib") # used in many places so include globally, like OpenGL - blender_include_dirs("${PTHREADS_INCLUDE_DIRS}") + blender_include_dirs_sys("${PTHREADS_INCLUDE_DIRS}") elseif(CMAKE_COMPILER_IS_GNUCC) - # keep GCC specific stuff here + # keep GCC specific stuff here set(PLATFORM_LINKLIBS "-lshell32 -lshfolder -lgdi32 -lmsvcrt -lwinmm -lmingw32 -lm -lws2_32 -lz -lstdc++ -lole32 -luuid -lwsock32 -lpsapi") set(PLATFORM_CFLAGS "-pipe -funsigned-char -fno-strict-aliasing") @@ -1243,14 +1303,16 @@ elseif(WIN32) set(BOOST_POSTFIX "mgw47-mt-s-1_49") set(BOOST_DEBUG_POSTFIX "mgw47-mt-sd-1_49") else() - set(BOOST_POSTFIX "mgw46-mt-s-1_47") - set(BOOST_DEBUG_POSTFIX "mgw46-mt-sd-1_47") - endif() + set(BOOST_POSTFIX "mgw46-mt-s-1_49") + set(BOOST_DEBUG_POSTFIX "mgw46-mt-sd-1_49") + endif() set(BOOST_LIBRARIES optimized boost_date_time-${BOOST_POSTFIX} boost_filesystem-${BOOST_POSTFIX} - boost_regex-${BOOST_POSTFIX} boost_system-${BOOST_POSTFIX} boost_thread-${BOOST_POSTFIX} + boost_regex-${BOOST_POSTFIX} + boost_system-${BOOST_POSTFIX} boost_thread-${BOOST_POSTFIX} debug boost_date_time-${BOOST_DEBUG_POSTFIX} boost_filesystem-${BOOST_DEBUG_POSTFIX} - boost_regex-${BOOST_DEBUG_POSTFIX} boost_system-${BOOST_DEBUG_POSTFIX} boost_thread-${BOOST_DEBUG_POSTFIX}) + boost_regex-${BOOST_DEBUG_POSTFIX} + boost_system-${BOOST_DEBUG_POSTFIX} boost_thread-${BOOST_DEBUG_POSTFIX}) set(BOOST_LIBPATH ${BOOST}/lib) set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB -DBOOST_THREAD_USE_LIB ") endif() @@ -1274,7 +1336,7 @@ elseif(WIN32) set(PLATFORM_LINKFLAGS "-Xlinker --stack=2097152") ## DISABLE - causes linking errors - ## for re-distrobution, so users dont need mingw installed + ## for re-distribution, so users dont need mingw installed # set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -static-libgcc -static-libstdc++") endif() @@ -1293,7 +1355,7 @@ elseif(APPLE) set(OSX_SYSROOT_PREFIX /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform) set(OSX_DEVELOPER_PREFIX /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk) # use guaranteed existing sdk set(CMAKE_OSX_SYSROOT ${OSX_SYSROOT_PREFIX}/${OSX_DEVELOPER_PREFIX} CACHE PATH "" FORCE) - endif() + endif() if(WITH_LIBS10.5) set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin-9.x.universal) @@ -1386,6 +1448,7 @@ elseif(APPLE) if(WITH_IMAGE_OPENEXR) set(OPENEXR ${LIBDIR}/openexr) + set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include) set(OPENEXR_INCLUDE_DIRS ${OPENEXR}/include/OpenEXR) set(OPENEXR_LIBRARIES Iex Half IlmImf Imath IlmThread) set(OPENEXR_LIBPATH ${OPENEXR}/lib) @@ -1512,7 +1575,7 @@ elseif(APPLE) if(WITH_OPENIMAGEIO) set(OPENIMAGEIO ${LIBDIR}/openimageio) set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include) - set(OPENIMAGEIO_LIBRARIES OpenImageIO ${PNG_LIBRARIES} ${JPEG_LIBRARIES} ${TIFF_LIBRARY} ${OPENEXR_LIBRARIES} ${ZLIB_LIBRARIES}) + set(OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO}/lib/libOpenImageIO.a ${PNG_LIBRARIES} ${JPEG_LIBRARIES} ${TIFF_LIBRARY} ${OPENEXR_LIBRARIES} ${ZLIB_LIBRARIES}) set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib ${JPEG_LIBPATH} ${PNG_LIBPATH} ${TIFF_LIBPATH} ${OPENEXR_LIBPATH} ${ZLIB_LIBPATH}) set(OPENIMAGEIO_DEFINITIONS "-DOIIO_STATIC_BUILD") endif() @@ -1525,6 +1588,47 @@ elseif(APPLE) set(OPENCOLORIO_DEFINITIONS "-DOCIO_STATIC_BUILD") endif() + if(WITH_LLVM) + set(LLVM_DIRECTORY ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation") + set(LLVM_VERSION "3.1" CACHE STRING "Version of LLVM to use") + set(LLVM_STATIC YES) + if(LLVM_DIRECTORY) + set(LLVM_CONFIG "${LLVM_DIRECTORY}/bin/llvm-config") + else() + set(LLVM_CONFIG llvm-config) + endif() + execute_process(COMMAND ${LLVM_CONFIG} --version + OUTPUT_VARIABLE LLVM_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND ${LLVM_CONFIG} --prefix + OUTPUT_VARIABLE LLVM_DIRECTORY + OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND ${LLVM_CONFIG} --libdir + OUTPUT_VARIABLE LLVM_LIB_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE) + find_library(LLVM_LIBRARY + NAMES libLLVMAnalysis.a # first of a whole bunch of libs to get + PATHS ${LLVM_LIB_DIR}) + message(STATUS "LLVM version = ${LLVM_VERSION}") + message(STATUS "LLVM dir = ${LLVM_DIRECTORY}") + message(STATUS "LLVM lib dir = ${LLVM_LIB_DIR}") + + if(LLVM_LIBRARY AND LLVM_DIRECTORY AND LLVM_LIB_DIR) + if(LLVM_STATIC) + # if static LLVM libraries were requested, use llvm-config to generate + # the list of what libraries we need, and substitute that in the right + # way for LLVM_LIBRARY. + execute_process(COMMAND ${LLVM_CONFIG} --libfiles + OUTPUT_VARIABLE LLVM_LIBRARY + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE " " ";" LLVM_LIBRARY ${LLVM_LIBRARY}) + endif() + message(STATUS "LLVM library = ${LLVM_LIBRARY}") + else() + message(FATAL_ERROR "LLVM not found.") + endif() + endif() + if(WITH_CYCLES_OSL) set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation") @@ -1534,7 +1638,7 @@ elseif(APPLE) find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib) find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib) # WARNING! depends on correct order of OSL libs linking - list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} ${OSL_LIB_EXEC} ${OSL_LIB_QUERY}) + list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} -force_load ${OSL_LIB_EXEC} ${OSL_LIB_QUERY}) find_path(OSL_INCLUDES OSL/oslclosure.h PATHS ${CYCLES_OSL}/include) find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin) @@ -1546,20 +1650,19 @@ elseif(APPLE) else() message(STATUS "OSL not found") endif() - - include_directories(${OSL_INCLUDES}) endif() set(EXETYPE MACOSX_BUNDLE) set(CMAKE_C_FLAGS_DEBUG "-fno-strict-aliasing -g") set(CMAKE_CXX_FLAGS_DEBUG "-fno-strict-aliasing -g") - if(CMAKE_OSX_ARCHITECTURES MATCHES "i386") - set(CMAKE_CXX_FLAGS_RELEASE "-O2 -mdynamic-no-pic -ftree-vectorize -msse -msse2 -fvariable-expansion-in-unroller") - set(CMAKE_C_FLAGS_RELEASE "-O2 -mdynamic-no-pic -ftree-vectorize -msse -msse2 -fvariable-expansion-in-unroller") - elseif(CMAKE_OSX_ARCHITECTURES MATCHES "x86_64") - set(CMAKE_CXX_FLAGS_RELEASE "-O2 -mdynamic-no-pic -ftree-vectorize -msse -msse2 -msse3 -mssse3 -fvariable-expansion-in-unroller") - set(CMAKE_C_FLAGS_RELEASE "-O2 -mdynamic-no-pic -ftree-vectorize -msse -msse2 -msse3 -mssse3 -fvariable-expansion-in-unroller") + if(CMAKE_OSX_ARCHITECTURES MATCHES "x86_64" OR CMAKE_OSX_ARCHITECTURES MATCHES "i386") + set(CMAKE_CXX_FLAGS_RELEASE "-O2 -mdynamic-no-pic -msse -msse2 -msse3 -mssse3") + set(CMAKE_C_FLAGS_RELEASE "-O2 -mdynamic-no-pic -msse -msse2 -msse3 -mssse3") + if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -ftree-vectorize -fvariable-expansion-in-unroller") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ftree-vectorize -fvariable-expansion-in-unroller") + endif() else() set(CMAKE_C_FLAGS_RELEASE "-mdynamic-no-pic -fno-strict-aliasing") set(CMAKE_CXX_FLAGS_RELEASE "-mdynamic-no-pic -fno-strict-aliasing") @@ -1582,6 +1685,12 @@ if(WITH_CYCLES) if(NOT WITH_BOOST) message(FATAL_ERROR "Cycles reqires WITH_BOOST, the library may not have been found. Configure BOOST or disable WITH_CYCLES") endif() + + if(WITH_CYCLES_OSL) + if(NOT WITH_LLVM) + message(FATAL_ERROR "Cycles OSL reqires WITH_LLVM, the library may not have been found. Configure LLVM or disable WITH_CYCLES_OSL") + endif() + endif() endif() @@ -1725,9 +1834,17 @@ if(CMAKE_COMPILER_IS_GNUCC) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_POINTER_ARITH -Wpointer-arith) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNUSED_PARAMETER -Wunused-parameter) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_WRITE_STRINGS -Wwrite-strings) + ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_LOGICAL_OP -Wlogical-op) + ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNDEF -Wundef) + ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_INIT_SELF -Winit-self) # needs -Wuninitialized + ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_NULL -Wnonnull) # C only + ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_MISSING_INCLUDE_DIRS -Wmissing-include-dirs) + ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero) - # # this causes too many warnings, disable - # ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNDEFINED -Wundef) + # gcc 4.2 gives annoying warnings on every file with this + if ("${CMAKE_C_COMPILER_VERSION}" VERSION_GREATER "4.2") + ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNINITIALIZED -Wuninitialized) + endif() # disable because it gives warnings for printf() & friends. # ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_DOUBLE_PROMOTION -Wdouble-promotion -Wno-error=double-promotion) @@ -1739,9 +1856,21 @@ if(CMAKE_COMPILER_IS_GNUCC) ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ALL -Wall) ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_INVALID_OFFSETOF -Wno-invalid-offsetof) ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_SIGN_COMPARE -Wno-sign-compare) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_LOGICAL_OP -Wlogical-op) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_INIT_SELF -Winit-self) # needs -Wuninitialized + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_MISSING_INCLUDE_DIRS -Wmissing-include-dirs) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero) - # # this causes too many warnings, disable - # ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNDEFINED -Wundef) + # gcc 4.2 gives annoying warnings on every file with this + if ("${CMAKE_C_COMPILER_VERSION}" VERSION_GREATER "4.2") + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNINITIALIZED -Wuninitialized) + endif() + + # causes too many warnings + if(NOT APPLE) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNDEF -Wundef) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_MISSING_DECLARATIONS -Wmissing-declarations) + endif() # flags to undo strict flags ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_DEPRECATED_DECLARATIONS -Wno-deprecated-declarations) @@ -1760,13 +1889,15 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_STRICT_PROTOTYPES -Wstrict-prototypes) ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_MISSING_PROTOTYPES -Wmissing-prototypes) + ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNUSED_MACROS -Wunused-macros) - ADD_CHECK_C_COMPILER_FLAG(CXX_WARNINGS C_WARN_ALL -Wall) - ADD_CHECK_C_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_AUTOLOGICAL_COMPARE -Wno-tautological-compare) - ADD_CHECK_C_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas) - ADD_CHECK_C_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts) - ADD_CHECK_C_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_OVERLOADED_VIRTUAL -Wno-overloaded-virtual) # we get a lot of these, if its a problem a dev needs to look into it. - ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_INVALID_OFFSETOF -Wno-invalid-offsetof) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ALL -Wall) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_AUTOLOGICAL_COMPARE -Wno-tautological-compare) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_OVERLOADED_VIRTUAL -Wno-overloaded-virtual) # we get a lot of these, if its a problem a dev needs to look into it. + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_INVALID_OFFSETOF -Wno-invalid-offsetof) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNUSED_MACROS -Wunused-macros) elseif(CMAKE_C_COMPILER_ID MATCHES "Intel") @@ -1847,9 +1978,10 @@ if(WITH_PYTHON) endif() endif() - -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PLATFORM_CFLAGS} ${C_WARNINGS}") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PLATFORM_CFLAGS} ${CXX_WARNINGS}") +# Include warnings first, so its possible to disable them with user defined flags +# eg: -Wno-uninitialized +set(CMAKE_C_FLAGS "${C_WARNINGS} ${CMAKE_C_FLAGS} ${PLATFORM_CFLAGS}") +set(CMAKE_CXX_FLAGS "${CXX_WARNINGS} ${CMAKE_CXX_FLAGS} ${PLATFORM_CFLAGS}") #------------------------------------------------------------------------------- # Global Defines @@ -1956,6 +2088,7 @@ if(FIRST_RUN) info_cfg_option(WITH_OPENAL) info_cfg_option(WITH_SDL) info_cfg_option(WITH_JACK) + info_cfg_option(WITH_CODEC_AVI) info_cfg_option(WITH_CODEC_FFMPEG) info_cfg_option(WITH_CODEC_SNDFILE) @@ -1972,7 +2105,6 @@ if(FIRST_RUN) info_cfg_text("Modifiers:") info_cfg_option(WITH_MOD_BOOLEAN) info_cfg_option(WITH_MOD_REMESH) - info_cfg_option(WITH_MOD_DECIMATE) info_cfg_option(WITH_MOD_FLUID) info_cfg_option(WITH_MOD_OCEANSIM) diff --git a/GNUmakefile b/GNUmakefile index 1f1de3f6b99..f8207787cbe 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -163,18 +163,27 @@ help: @echo " * package_archive - build an archive package" @echo "" @echo "Testing Targets (not associated with building blender)" - @echo " * test - run ctest, currently tests import/export, operator execution and that python modules load" - @echo " * test_cmake - runs our own cmake file checker which detects errors in the cmake file list definitions" - @echo " * test_pep8 - checks all python script are pep8 which are tagged to use the stricter formatting" - @echo " * test_deprecated - checks for deprecation tags in our code which may need to be removed" - @echo " * test_style - checks C/C++ conforms with blenders style guide: http://wiki.blender.org/index.php/Dev:Doc/CodeStyle" + @echo " * test - run ctest, currently tests import/export, operator execution and that python modules load" + @echo " * test_cmake - runs our own cmake file checker which detects errors in the cmake file list definitions" + @echo " * test_pep8 - checks all python script are pep8 which are tagged to use the stricter formatting" + @echo " * test_deprecated - checks for deprecation tags in our code which may need to be removed" + @echo " * test_style_c - checks C/C++ conforms with blenders style guide: http://wiki.blender.org/index.php/Dev:Doc/CodeStyle" + @echo " * test_style_c_qtc - same as test_style but outputs QtCreator tasks format" + @echo " * test_style_osl - checks OpenShadingLanguage conforms with blenders style guide: http://wiki.blender.org/index.php/Dev:Doc/CodeStyle" + @echo " * test_style_osl_qtc - checks OpenShadingLanguage conforms with blenders style guide: http://wiki.blender.org/index.php/Dev:Doc/CodeStyle" @echo "" @echo "Static Source Code Checking (not associated with building blender)" - @echo " * check_cppcheck - run blender source through cppcheck (C & C++)" - @echo " * check_splint - run blenders source through splint (C only)" - @echo " * check_sparse - run blenders source through sparse (C only)" - @echo " * check_spelling_c - check for spelling errors (C/C++ only)" - @echo " * check_spelling_py - check for spelling errors (Python only)" + @echo " * check_cppcheck - run blender source through cppcheck (C & C++)" + @echo " * check_clang_array - run blender source through clang array checking script (C & C++)" + @echo " * check_splint - run blenders source through splint (C only)" + @echo " * check_sparse - run blenders source through sparse (C only)" + @echo " * check_smatch - run blenders source through smatch (C only)" + @echo " * check_spelling_c - check for spelling errors (OSL only)" + @echo " * check_spelling_osl - check for spelling errors (C/C++ only)" + @echo " * check_spelling_py - check for spelling errors (Python only)" + @echo "" + @echo "Utilities (not associated with building blender)" + @echo " * tbz - create a compressed svn export 'blender_archive.tar.bz2'" @echo "" @echo "Documentation Targets (not associated with building blender)" @echo " * doc_py - generate sphinx python api docs" @@ -205,31 +214,51 @@ test: # run pep8 check check on scripts we distribute. test_pep8: - python3.2 source/tests/pep8.py > test_pep8.log 2>&1 + python3 source/tests/pep8.py > test_pep8.log 2>&1 @echo "written: test_pep8.log" # run some checks on our cmakefiles. test_cmake: - python3.2 build_files/cmake/cmake_consistency_check.py > test_cmake_consistency.log 2>&1 + python3 build_files/cmake/cmake_consistency_check.py > test_cmake_consistency.log 2>&1 @echo "written: test_cmake_consistency.log" # run deprecation tests, see if we have anything to remove. test_deprecated: - python3.2 source/tests/check_deprecated.py + python3 source/tests/check_deprecated.py -test_style: +test_style_c: # run our own checks on C/C++ style - PYTHONIOENCODING=utf_8 python3.2 $(BLENDER_DIR)/source/tools/check_style_c.py $(BLENDER_DIR)/source/blender $(BLENDER_DIR)/source/creator --no-length-check + PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/check_style_c.py $(BLENDER_DIR)/source/blender $(BLENDER_DIR)/source/creator --no-length-check + +test_style_c_qtc: + # run our own checks on C/C++ style + USE_QTC_TASK=1 \ + PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/check_style_c.py $(BLENDER_DIR)/source/blender $(BLENDER_DIR)/source/creator --no-length-check > \ + test_style.tasks + @echo "written: test_style.tasks" + + +test_style_osl: + # run our own checks on C/C++ style + PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/check_style_c.py $(BLENDER_DIR)/intern/cycles/kernel/osl + + +test_style_osl_qtc: + # run our own checks on C/C++ style + USE_QTC_TASK=1 \ + PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/check_style_c.py $(BLENDER_DIR)/intern/cycles/kernel/osl > \ + test_style.tasks + @echo "written: test_style.tasks" # ----------------------------------------------------------------------------- # Project Files # project_qtcreator: - python3.2 build_files/cmake/cmake_qtcreator_project.py $(BUILD_DIR) + python3 build_files/cmake/cmake_qtcreator_project.py $(BUILD_DIR) project_netbeans: - python3.2 build_files/cmake/cmake_netbeans_project.py $(BUILD_DIR) + python3 build_files/cmake/cmake_netbeans_project.py $(BUILD_DIR) project_eclipse: cmake -G"Eclipse CDT4 - Unix Makefiles" -H$(BLENDER_DIR) -B$(BUILD_DIR) @@ -241,25 +270,43 @@ project_eclipse: check_cppcheck: $(CMAKE_CONFIG) - cd $(BUILD_DIR) ; python3.2 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_cppcheck.py + cd $(BUILD_DIR) ; python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_cppcheck.py + +check_clang_array: + $(CMAKE_CONFIG) + cd $(BUILD_DIR) ; python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_clang_array.py check_splint: $(CMAKE_CONFIG) - cd $(BUILD_DIR) ; python3.2 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_splint.py + cd $(BUILD_DIR) ; python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_splint.py check_sparse: $(CMAKE_CONFIG) - cd $(BUILD_DIR) ; python3.2 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_sparse.py + cd $(BUILD_DIR) ; python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_sparse.py check_smatch: $(CMAKE_CONFIG) - cd $(BUILD_DIR) ; python3.2 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_smatch.py + cd $(BUILD_DIR) ; python3 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_smatch.py check_spelling_py: - cd $(BUILD_DIR) ; PYTHONIOENCODING=utf_8 python3.2 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/release/scripts + cd $(BUILD_DIR) ; PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/release/scripts check_spelling_c: - cd $(BUILD_DIR) ; PYTHONIOENCODING=utf_8 python3.2 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/source + cd $(BUILD_DIR) ; PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/source + +check_spelling_osl: + cd $(BUILD_DIR) ; PYTHONIOENCODING=utf_8 python3 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/intern/cycles/kernel/osl + +# ----------------------------------------------------------------------------- +# Utilities +# + +tbz: + svn export . blender_archive + tar cjf blender_archive.tar.bz2 blender_archive/ + rm -rf blender_archive/ + @echo "blender_archive.tar.bz2 written" + # ----------------------------------------------------------------------------- # Documentation @@ -280,7 +327,7 @@ doc_dna: @echo "docs written into: '$(BLENDER_DIR)/doc/blender_file_format/dna.html'" doc_man: - python3.2 doc/manpage/blender.1.py $(BUILD_DIR)/bin/blender + python3 doc/manpage/blender.1.py $(BUILD_DIR)/bin/blender clean: diff --git a/SConstruct b/SConstruct index 517f507ec61..064ae0bc0b5 100644 --- a/SConstruct +++ b/SConstruct @@ -264,7 +264,6 @@ if 'blenderlite' in B.targets: target_env_defs['WITH_BF_FLUID'] = False target_env_defs['WITH_BF_OCEANSIM'] = False target_env_defs['WITH_BF_SMOKE'] = False - target_env_defs['WITH_BF_DECIMATE'] = False target_env_defs['WITH_BF_BOOLEAN'] = False target_env_defs['WITH_BF_REMESH'] = False target_env_defs['WITH_BF_PYTHON'] = False @@ -366,6 +365,7 @@ else: # TODO, make optional env['CPPFLAGS'].append('-DWITH_AUDASPACE') +env['CPPFLAGS'].append('-DWITH_AVI') # lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir B.root_build_dir = env['BF_BUILDDIR'] @@ -871,9 +871,13 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'): if env['WITH_BF_OIIO'] and env['OURPLATFORM'] != 'win32-mingw': dllsources.append('${LCGDIR}/openimageio/bin/OpenImageIO.dll') - if env['WITH_BF_OCIO'] and env['OURPLATFORM'] != 'win32-mingw': - dllsources.append('${LCGDIR}/opencolorio/bin/OpenColorIO.dll') + if env['WITH_BF_OCIO']: + if not env['OURPLATFORM'] in ('win32-mingw', 'linuxcross'): + dllsources.append('${LCGDIR}/opencolorio/bin/OpenColorIO.dll') + else: + dllsources.append('${LCGDIR}/opencolorio/bin/libOpenColorIO.dll') + dllsources.append('#source/icons/blender.exe.manifest') windlls = env.Install(dir=env['BF_INSTALLDIR'], source = dllsources) @@ -903,6 +907,9 @@ if env['OURPLATFORM'] == 'win64-mingw': if(env['WITH_BF_OPENMP']): dllsources.append('${LCGDIR}/binaries/libgomp-1.dll') + + if env['WITH_BF_OCIO']: + dllsources.append('${LCGDIR}/opencolorio/bin/libOpenColorIO.dll') dllsources.append('${LCGDIR}/thumbhandler/lib/BlendThumb64.dll') dllsources.append('${LCGDIR}/binaries/libgcc_s_sjlj-1.dll') diff --git a/build_files/build_environment/prepare_release_env.sh b/build_files/build_environment/prepare_release_env.sh new file mode 100755 index 00000000000..0bad1501540 --- /dev/null +++ b/build_files/build_environment/prepare_release_env.sh @@ -0,0 +1,1483 @@ +#!/bin/sh + +# +# This script will prepare build environment with the same settings as release environment +# +# It will install two chroot environments: +# - /home/buildbot_squeeze_i686 +# - /home/buildbot_squeeze_x86_64 +# which are used for 32bit and 64bit +# +# This sctipt will also create folder /home/sources where all dependent libraries sources are +# downloading and compiling. +# +# Release builder scripts are stored in /home/sources/release-builder +# See build_all.sh script for usage details +# +# This script was tested on debian squeeze and wheezy, should work on ubuntu as well +# It wouldn't work on other distros +# +# TODO: +# - It's still required manual copying of build configuration files to /home/sources/release-builder/config +# - OSL is not set up yet +# + +set -e + +NO_COLOR='\033[0m' +EWHITE='\033[1;37m' +ERED='\033[1;31m' + +CONFIRM="--i-really-do-know-what-im-doing" + +ERROR() { + echo ${ERED}${@}${NO_COLOR} +} + +INFO() { + echo ${EWHITE}${@}${NO_COLOR} +} + +if [ $# != 1 ]; then + ERROR "Usage: $0 $CONFIRM" + exit 1 +fi + +if [ "$1" != "$CONFIRM" ]; then + ERROR "Usage: $0 $CONFIRM" + exit 1 +fi + +DEBIAN_BRANCH="squeeze" +DEBIAN_MIRROR="http://ftp.de.debian.org/debian" +USER_ID=1000 + +# For now it's always /home, so we can setup schroot to map /sources to the same +# path at both host and chroot systems (which is currently needed for release building script) +ENV_PATH="/home" + +AMD64_PATH="$ENV_PATH/buildbot_${DEBIAN_BRANCH}_x86_64" +I686_PATH="$ENV_PATH/buildbot_${DEBIAN_BRANCH}_i686" +SOURCES_PATH="$ENV_PATH/sources" + +THREADS=`cat /proc/cpuinfo | grep cores | uniq | sed -e "s/.*: *\(.*\)/\\1/"` + +# Force vpx be installed from the backports +VPX_V="1.0.0-2~bpo60+1" + +BINUTILS_V="2.22" +BINUTILS_FV="2.22-7.1" + +GCC_V="4.7_4.7.1" +GCC_FV="4.7_4.7.1-7" + +OPENAL_V="1.14" + +DPKG_V="1.16.8" + +DEBHELPER_V="9" +DEBHELPER_FV="9.20120909" + +JEMALLOC_V="3.1.0" +SPNAV_V="0.2.2" +FFMPEG_V="1.0" +BOOST_V="1_51_0" +PYTHON_V="3.3.0" +PYTHIN_V_SHORT="3.3" +OIIO_V="1.0.9" +OCIO_V="1.0.7" +MESA_V="8.0.5" + +CUDA_V="4.2.9" +CUDA_DISTR="ubuntu10.04" +CUDA_32="cudatoolkit_${CUDA_V}_linux_32_${CUDA_DISTR}.run" +CUDA_64="cudatoolkit_${CUDA_V}_linux_64_${CUDA_DISTR}.run" + +INSTALL_RELEASE_BUILDER() { + SOURCES_PATH=$1 + + RB=$SOURCES_PATH/release-builder + if [ ! -d $RB ]; then + INFO "Installing release building scripts" + + mkdir -p $RB + + cat << EOF > $RB/Readme.txt +This directory contains scrips needed for automated release archive preparation + +config/: storage of scons configs for different platforms + +build_all.sh: script asks version to add to archive name and revision to compile, + when script finished, there'll be 32 and 64 bit archives in current directory + better to run this script from this directory + +do_build_all.sh: uses environment variables set by build_all.sh script (or other scripts) + and launches compilation inside chroot environments + +chroot_compile.py: runs compilation process with giver parameters in chroots +compile.py: script runs inside chroot environment and prepares archive + +blender-buildenv.tar.bz2: archive, received from Ken Hughes when i've been preparing + new environment to make it as close to old one as it's possible + +Hope all this would help you. + +-Sergey- +EOF + + cat << EOF > $RB/build_all.sh +#!/bin/sh + +echo -n "version: " +read version +echo -n "svn revision (blank to latest, 0 to keep unchanged): " +read revision + +export version +export revision + +d=\`dirname \${0}\` +\${d}/do_build_all.sh +EOF + chmod +x $RB/build_all.sh + + cat << EOF > $RB/build_all-test.sh +#!/bin/sh + +d=\`dirname \${0}\` +\${d}/do_build_all.sh +EOF + chmod +x $RB/build_all-test.sh + + cat << EOF > $RB/chroot-compile.py +#!/usr/bin/env python + +import sys +import os +import platform + +from optparse import OptionParser + +# This could be passed through options, but does we actually need this? +bl_source = '/home/sources/blender' +build_dir = '/home/sources/blender-build/' +install_dir = '/home/sources/blender-install/' +with_player = True + +# Default config +curr_arch = platform.architecture()[0] +def_arch = 'x86_64' if curr_arch == '64bit' else 'i686' +builder_dir = os.path.dirname(os.path.realpath(__file__)) + +# XXX: bad thing! +# builder_dir = builder_dir.replace("sources-new", "sources") + +def_cores = 1 +if hasattr(os, 'sysconf'): + if 'SC_NPROCESSORS_ONLN' in os.sysconf_names: + def_cores = os.sysconf('SC_NPROCESSORS_ONLN') + +# Per-architecture chroot name +chroots = { 'i686': 'buildbot_squeeze_i686', + 'x86_64': 'buildbot_squeeze_x86_64'} + +# Parse command line +op = OptionParser() +op.add_option('--tag', default = None) +op.add_option('--branch', default = None) +op.add_option('--arch', default = def_arch) +op.add_option('--cores', default = def_cores) +op.add_option('--bl-version', default = 'UNDEFINED') +op.add_option('--no-clean', default = False) +(opts, args) = op.parse_args() + +if opts.arch not in chroots: + print('Error: No configured machine gound to build ' + + '{0} version' . format(opts.arch)) + sys.exit(1) + +chroot = chroots[opts.arch] + +if opts.tag: + bl_source = '/home/sources/blender-tags/' + opts.tag +elif opts.branch: + bl_source = '/home/sources/blender-branches/' + opts.branch + +if not os.path.isdir(bl_source): + print('Uname to find directory with sources: ' + bl_source) + sys.exit(1) + +print('Building {0} version, machine is {1}' . format(opts.bl_version, opts.arch)) + +# Assume builder directory is binded to the same location in +# chroot environments +compiler = os.path.join(builder_dir, 'compile.py') + +cmd = 'schroot -c %s -d /home/sources/release-builder --' % (chroot) +cmd += ' python %s' % (compiler) +cmd += ' --bl-version=%s' % (opts.bl_version) +cmd += ' --bl-source=%s' % (bl_source) +cmd += ' --arch=%s' % (opts.arch) +cmd += ' --build-dir=%s' % (build_dir) +cmd += ' --install-dir=%s' % (install_dir) + +if opts.no_clean: + cmd += ' --no-clean=1' + +if with_player: + cmd += ' --with-player=1' + +#if opts.branch: +# cmd += ' --use-new-ffmpeg=1' + +result = os.system(cmd) +if result != 0: + print('compiler script exited with errcode: %s' % (result)) + sys.exit(1) +EOF + chmod +x $RB/chroot-compile.py + + cat << EOF > $RB/compile.py +#!/usr/bin/env python + +import platform +import sys +import os +import shutil + +from optparse import OptionParser + +# Default config +curr_arch = platform.architecture()[0] +def_arch = 'x86_64' if curr_arch == '64bit' else 'i686' +builder_dir = os.path.dirname(os.path.realpath(__file__)) + +def_cores = 1 +if hasattr(os, 'sysconf'): + if 'SC_NPROCESSORS_ONLN' in os.sysconf_names: + def_cores = os.sysconf('SC_NPROCESSORS_ONLN') + +# Parse command line +op = OptionParser() +op.add_option('--arch', default = def_arch) +op.add_option('--cores', default = def_cores) +op.add_option('--no-clean', default = False) +op.add_option('--bl-version', default = 'UNKNOWN') +op.add_option('--bl-source', default = '') +op.add_option('--config-dir', default = '') +op.add_option('--build-dir', default = '') +op.add_option('--install-dir', default = '') +op.add_option('--with-player', default = False) +#op.add_option('--use-new-ffmpeg', default = False) +(opts, args) = op.parse_args() + +if opts.config_dir == '': + opts.config_dir = os.path.join(builder_dir, 'config') + +# Initial directory checking (could be problems with permissions) +if not os.path.isdir(opts.bl_source): + print('Blender\'s source tree not found: %s' % (opts.bl_source)) + sys.exit(1) + +if not os.path.isdir(opts.config_dir): + print('Directory with configuration files not found: %s' % (opts.config_dir)) + sys.exit(1) + +if not os.path.isdir(os.path.dirname(opts.build_dir)): + print('Build directory can\'t be reached: %s' % (opts.build_dir)) + sys.exit(1) + +if not os.path.isdir(os.path.dirname(opts.install_dir)): + print('Install directory can\'t be reached: %s' % (opts.install_dir)) + sys.exit(1) + +# Detect glibc version +libc = [name for name in os.listdir('/lib') if 'libc.so.' in name] +if len(libc) == 0: + print('Could not find "/lib/libc.so.*": cannot determine glibc version') + sys.exit(-1) + +if len(libc) > 1: + print('warning: found more than one "/lib/libc.so.*": '+ + 'using %s' % (libc[0])) + +glibc = 'glibc' + os.readlink('/lib/' + libc[0])[5:][:-3].replace('.', '') +glibc = glibc[:8] + +# Full name for archive +full_name = 'blender-%s-linux-%s-%s' % (opts.bl_version, glibc, opts.arch) +build_dir = os.path.join(opts.build_dir, full_name) +install_dir = os.path.join(opts.install_dir, full_name) +scons = os.path.join(opts.bl_source, 'scons', 'scons.py') +scons_cmd = 'python %s -C %s' % (scons, opts.bl_source) +config = os.path.join(opts.config_dir, 'user-config-' + glibc + '-' + opts.arch + '.py') + +if not os.path.isfile(config): + print('Configuration file not found: %s' % (config)) + sys.exit(1) + +# Clean build directory +if not opts.no_clean: + print('Cleaning up build directory...') + os.system('%s BF_BUILDDIR=%s clean ' % (scons_cmd, build_dir)) + +# Clean install directory +if os.path.isdir(install_dir): + shutil.rmtree(install_dir) + +flags = "" + +# Switch to newer libraries if needed +#if opts.use_new_ffmpeg: +# print("Using new ffmpeg-0.8.1") +# flags += " BF_FFMPEG='/home/sources/staticlibs/ffmpeg-0.8'" + +# Build blenderplayer first +# (to be sure all stuff needed for blender would copied automatically) +if opts.with_player: + player_config = os.path.join(opts.config_dir, + 'user-config-player-' + glibc + '-' + opts.arch + '.py') + + if not os.path.isfile(player_config): + print('Player configuration file not found: %s' % (player_config)) + sys.exit(1) + + cmd = '%s -j %d blenderplayer ' % (scons_cmd, opts.cores + 1) + cmd += ' BF_BUILDDIR=%s' % (build_dir + '-player') + cmd += ' BF_INSTALLDIR=%s' % (install_dir) + cmd += ' BF_CONFIG=%s' % (player_config) + cmd += flags + + result = os.system(cmd) + if result != 0: + print('Compilation failed, exit code is %d' % (result)) + sys.exit(-1) + +# Build blender itself +cmd = '%s -j %d blender ' % (scons_cmd, opts.cores + 1) +cmd += ' BF_BUILDDIR=%s' % (build_dir) +cmd += ' BF_INSTALLDIR=%s' % (install_dir) +cmd += ' BF_CONFIG=%s' % (config) +cmd += flags + +result = os.system(cmd) +if result != 0: + print('Compilation failed, exit code is %d' % (result)) + sys.exit(-1) + +blender = os.path.join(install_dir, 'blender') +blenderplayer = blender + 'player' + +if not os.path.exists(blender): + print('scons completed successfully but blender executable missing') + sys.exit(1) + +if opts.with_player and not os.path.exists(blenderplayer): + print('scons completed successfully but blenderplayer executable missing') + sys.exit(1) + +# compile python modules +#result = os.system('%s --background --python %s/source/tools/compile_scripts.py' % (blender, opts.bl_source)) +#if result != 0: +# print('Python modules compilation failed, exit code is %d' % (result)) +# sys.exit(-1) + +print('build successful') + +os.system('strip -s %s %s' % (blender, blenderplayer)) + +# Copy all texts needed for release +release_texts = os.path.join(opts.bl_source, 'release', 'text', '*') +release_txt = os.path.join(install_dir, 'release_%s.txt' % (opts.bl_version)) + +os.system('cp -r %s %s' % (release_texts, install_dir)) + +if os.path.exists(release_txt): + print 'RELEASE TEXT FOUND' +else: + print 'WARNING! RELEASE TEXT NOT FOUND!' + +# TODO: copy plugins data when ready + +# Add software gl libraries and scripts +mesa_arch = None + +if opts.arch == 'x86_64': + mesa_arch = 'mesalibs64.tar.bz2' +elif opts.arch == 'i686': + mesa_arch = 'mesalibs32.tar.bz2' + +if mesa_arch is not None: + mesalibs = os.path.join(builder_dir, 'extra', mesa_arch) + software_gl = os.path.join(builder_dir, 'extra', 'blender-softwaregl') + + os.system('tar -xpf %s -C %s' % (mesalibs, install_dir)) + os.system('cp %s %s' % (software_gl, install_dir)) + os.system('chmod 755 %s' % (os.path.join(install_dir, 'blender-softwaregl'))) + +# Pack release archive +print("Building Dynamic Tarball") +os.system('tar -C %s -cjf %s.tar.bz2 %s ' % (opts.install_dir, + full_name, full_name)) + +print('Done.') +EOF + chmod +x $RB/compile.py + + cat << EOF > $RB/do_build_al.sh +#!/bin/sh + +SOURCES="/home/sources" + +#opts="--cores=1 " +opts="" + +if [ "x\${tag}" != "x" ]; then + echo "Getting tagged source tree..." + d="\${SOURCES}/blender-tags/\${tag}" + opts="\${opts} --tag=\${tag}" + if [ ! -d \${d} ]; then + svn co https://svn.blender.org/svnroot/bf-blender/tags/\${tag}/blender/@\${revision} \${d} + else + svn up -r \${revision} \${d} + fi +elif [ "x\${branch}" != "x" ]; then + echo "Getting branched source tree..." + d="\${SOURCES}/blender-branches/\${branch}" + opts="\${opts} --branch=\${branch}" + if [ ! -d \${d} ]; then + if [ "x\${revision}" != "x" ]; then + svn co https://svn.blender.org/svnroot/bf-blender/branches/\${branch}/@\${revision} \${d} + else + svn co https://svn.blender.org/svnroot/bf-blender/branches/\${branch}/ \${d} + fi + else + if [ "x\${revision}" != "x" ]; then + svn up -r \${revision} \${d} + else + svn up \${d} + fi + fi +else + if [ "x\${revision}" != "x" ]; then + if [ "x\${revision}" != "x0" ]; then + svn up -r \${revision} \${SOURCES}/blender + else + svn up \${SOURCES}/blender + fi + fi +fi + +if [ "x\${tag}" != "x" ]; then + b="\${SOURCES}/blender-tags/\${tag}" +elif [ "x\${branch}" != "x" ]; then + b="\${SOURCES}/blender-branches/\${branch}" +else + b="\${SOURCES}/blender" +fi + +if [ "x\${addons_revision}" != "x" ]; then + d="\${b}/release/scripts/addons" + + if [ "x\${addons_revision}" != "x0" ]; then + svn up -r \${addons_revision} \${d} + else + svn up \${d} + fi +fi + +if [ "x\${locale_revision}" != "x" ]; then + d="\${b}/release/datafiles/locale" + + if [ "x\${locale_revision}" != "x0" ]; then + svn up -r \${locale_revision} \${d} + else + svn up \${d} + fi +fi + +if [ -z "\$version" ]; then + version=r\`/usr/bin/svnversion \$SOURCES/blender\` +fi + +cd extra +./update-libs.sh +cd .. + +python chroot-compile.py \${opts} --arch=x86_64 --bl-version \${version} # --no-clean=1 +python chroot-compile.py \${opts} --arch=i686 --bl-version \${version} # --no-clean=1 +EOF + chmod +x $RB/do_build_al.sh + + mkdir -p $RB/extra + + cat << EOF > $RB/extra/blender-softwaregl +#!/bin/sh + +BF_DIST_BIN=\`dirname "\$0"\` +BF_PROGRAM="blender" # BF_PROGRAM=\`basename "\$0"\`-bin +exitcode=0 + +LD_LIBRARY_PATH=\${BF_DIST_BIN}/lib:\${LD_LIBRARY_PATH} + +if [ -n "\$LD_LIBRARYN32_PATH" ]; then + LD_LIBRARYN32_PATH=\${BF_DIST_BIN}/lib:\${LD_LIBRARYN32_PATH} +fi +if [ -n "\$LD_LIBRARYN64_PATH" ]; then + LD_LIBRARYN64_PATH=\${BF_DIST_BIN}/lib:\${LD_LIBRARYN64_PATH} +fi +if [ -n "\$LD_LIBRARY_PATH_64" ]; then + LD_LIBRARY_PATH_64=\${BF_DIST_BIN}/lib:\${LD_LIBRARY_PATH_64} +fi + +# Workaround for half-transparent windows when compiz is enabled +XLIB_SKIP_ARGB_VISUALS=1 + +export LD_LIBRARY_PATH LD_LIBRARYN32_PATH LD_LIBRARYN64_PATH LD_LIBRARY_PATH_64 LD_PRELOAD XLIB_SKIP_ARGB_VISUALS + +"\$BF_DIST_BIN/\$BF_PROGRAM" \${1+"\$@"} +exitcode=\$? +exit \$exitcode +EOF + chmod +x $RB/extra/blender-softwaregl + + cat << EOF > $RB/extra/do_update-libs.sh +#!/bin/sh + +BITS=\$1 +V="\`readlink /opt/lib/mesa | sed -r 's/mesa-//'\`" +TMP=\`mktemp -d\` +N="mesalibs\$1-\$V" + +if [ ! -f \$N.tar.bz2 ]; then + mkdir -p \$TMP/lib + cp -P /opt/lib/mesa/lib/libGL* \$TMP/lib + strip -s \$TMP/lib/* + tar -C \$TMP -cf \$N.tar lib + bzip2 \$N.tar + + rm -f mesalibs\$BITS.tar,bz2 + ln -s \$N.tar.bz2 mesalibs\$BITS.tar.bz2 +fi + +rm -rf \$TMP +EOF + chmod +x $RB/extra/do_update-libs.sh + + cat << EOF > $RB/extra/update-libs.sh +#!/bin/sh + +P="/home/sources/release-builder/extra" +CHROOT_PREFIX="buildbot_squeeze_" +CHROOT32="\${CHROOT_PREFIX}i686" +CHROOT64="\${CHROOT_PREFIX}x86_64" +RUN32="schroot -c \$CHROOT32 -d \$P" +RUN64="schroot -c \$CHROOT64 -d \$P" + +\$RUN64 ./do_update-libs.sh 64 +\$RUN32 ./do_update-libs.sh 32 +EOF + chmod +x $RB/extra/update-libs.sh + + mkdir -p $RB/config + cp $SOURCES_PATH/blender/build_files/buildbot/config/* $RB/config + + fi +} + +INSTALL_SOURCES() { + SOURCES_PATH=$1 + + if [ ! -d "$SOURCES_PATH" ]; then + INFO "Creating sources directory" + mkdir -p "$SOURCES_PATH" + fi + + if [ ! -d "$SOURCES_PATH/backport/binutils" ]; then + INFO "Downloading binutils" + mkdir -p "$SOURCES_PATH/backport/binutils" + wget -c $DEBIAN_MIRROR/pool/main/b/binutils/binutils_$BINUTILS_FV.diff.gz \ + $DEBIAN_MIRROR/pool/main/b/binutils/binutils_$BINUTILS_FV.dsc \ + $DEBIAN_MIRROR/pool/main/b/binutils/binutils_$BINUTILS_V.orig.tar.gz \ + -P "$SOURCES_PATH/backport/binutils" + fi + + if [ ! -d "$SOURCES_PATH/backport/gcc-4.7" ]; then + INFO "Downloading gcc-4.7" + mkdir -p "$SOURCES_PATH/backport/gcc-4.7" + wget -c $DEBIAN_MIRROR/pool/main/g/gcc-4.7/gcc-$GCC_FV.diff.gz \ + $DEBIAN_MIRROR/pool/main/g/gcc-4.7/gcc-$GCC_FV.dsc \ + $DEBIAN_MIRROR/pool/main/g/gcc-4.7/gcc-$GCC_V.orig.tar.gz \ + -P "$SOURCES_PATH/backport/gcc-4.7" + fi + + # JeMalloc + J="$SOURCES_PATH/packages/jemalloc-$JEMALLOC_V" + if [ ! -d "$J" ]; then + INFO "Downloading jemalloc-$JEMALLOC_V" + wget -c http://www.canonware.com/download/jemalloc/jemalloc-$JEMALLOC_V.tar.bz2 -P "$SOURCES_PATH/packages" + tar -C "$SOURCES_PATH/packages" -xf "$J.tar.bz2" + cat << EOF > "$J/0config.sh" +#!/bin/sh + +./configure CC="gcc-4.7 -Wl,--as-needed" CXX="g++-4.7 -Wl,--as-needed" LDFLAGS="-pthread -static-libgcc" --prefix=/opt/lib/jemalloc-$JEMALLOC_V +EOF + chmod +x "$J/0config.sh" + fi + + # Spnav + S="$SOURCES_PATH/packages/libspnav-$SPNAV_V" + if [ ! -d "$S" ]; then + wget -c http://downloads.sourceforge.net/project/spacenav/spacenav%20library%20%28SDK%29/libspnav%200.2.2/libspnav-$SPNAV_V.tar.gz \ + -P "$SOURCES_PATH/packages" + tar -C "$SOURCES_PATH/packages" -xf "$S.tar.gz" + cat << EOF > "$S/0config.sh" +#!/bin/sh + +./configure --prefix=/opt/lib/libspnav-$SPNAV_V +EOF + chmod +x "$S/0config.sh" + fi + + # FFmpeg + F="$SOURCES_PATH/packages/ffmpeg-$FFMPEG_V" + if [ ! -d "$F" ]; then + INFO "Downloading FFmpeg-$FFMPEG_V" + wget -c http://ffmpeg.org/releases/ffmpeg-$FFMPEG_V.tar.bz2 -P "$SOURCES_PATH/packages" + tar -C "$SOURCES_PATH/packages" -xf "$F.tar.bz2" + cat << EOF > "$F/0config.sh" +#!/bin/sh + +./configure \\ + --cc="/usr/bin/gcc-4.7 -Wl,--as-needed" \\ + --extra-ldflags="-pthread -static-libgcc" \\ + --prefix=/opt/lib/ffmpeg-$FFMPEG_V \\ + --enable-static \\ + --enable-avfilter \\ + --disable-vdpau \\ + --disable-bzlib \\ + --disable-libgsm \\ + --enable-libschroedinger \\ + --disable-libspeex \\ + --enable-libtheora \\ + --enable-libvorbis \\ + --enable-pthreads \\ + --enable-zlib \\ + --enable-libvpx \\ + --enable-stripping \\ + --enable-runtime-cpudetect \\ + --disable-vaapi \\ + --enable-libopenjpeg \\ + --disable-libfaac \\ + --disable-nonfree \\ + --enable-gpl \\ + --disable-postproc \\ + --disable-x11grab \\ + --enable-libmp3lame \\ + --disable-librtmp \\ + --enable-libx264 \\ + --enable-libxvid \\ + --disable-libopencore-amrnb \\ + --disable-libopencore-amrwb \\ + --disable-libdc1394 \\ + --disable-version3 \\ + --disable-outdev=sdl \\ + --disable-outdev=alsa \\ + --disable-indev=sdl \\ + --disable-indev=alsa \\ + --disable-indev=jack \\ + --disable-indev=lavfi + +# --enable-debug +# --disable-optimizations +# --disable-ffplay +EOF + chmod +x "$F/0config.sh" + fi + + # Boost + B="$SOURCES_PATH/packages/boost_$BOOST_V" + if [ ! -d "$B" ]; then + INFO "Downloading Boost-$BOOST_V" + b_d=`echo "$BOOST_V" | sed -r 's/_/./g'` + wget -c http://sourceforge.net/projects/boost/files/boost/$b_d/boost_$BOOST_V.tar.bz2/download -O "$B.tar.bz2" + tar -C "$SOURCES_PATH/packages" -xf "$B.tar.bz2" + fi + + # Python + P="$SOURCES_PATH/packages/Python-$PYTHON_V" + if [ ! -d "$P" ]; then + INFO "Downloading Python-$PYTHON_V" + wget -c http://python.org/ftp/python/$PYTHON_V/Python-$PYTHON_V.tar.bz2 -P "$SOURCES_PATH/packages" + tar -C "$SOURCES_PATH/packages" -xf "$P.tar.bz2" + cat << EOF > "$P/0config.sh" +#!/bin/sh + +# NOTE: this sounds strange, but make sure /dev/shm/ is writable by your user, +# otherwise syncronization primitives wouldn't be included into python +if [[ "`stat -c '%a' /dev/shm/`" != "777" ]]; then + echo "Error checking syncronization primitives" + exit 1 +fi + +./configure --prefix=/opt/lib/python-$PYTHON_V \\ + --enable-ipv6 \\ + --enable-loadable-sqlite-extensions \\ + --with-dbmliborder=bdb \\ + --with-wide-unicode \\ + --with-computed-gotos \\ + --with-pymalloc +EOF + chmod +x "$P/0config.sh" + fi + + + # OpenImageIO + O="$SOURCES_PATH/packages/OpenImageIO-$OIIO_V" + if [ ! -d "$O" ]; then + INFO "Downloading OpenImageIO-$OIIO_V" + wget -c https://github.com/OpenImageIO/oiio/tarball/Release-$OIIO_V -O "$O.tar.gz" + tar -C "$SOURCES_PATH/packages" -xf "$O.tar.gz" + mv $SOURCES_PATH/packages/OpenImageIO-oiio* $O + mkdir $O/build + cat << EOF > "$O/build/prepare.sh" +#!/bin/sh + +if file /bin/cp | grep -q '32-bit'; then + cflags="-fPIC -m32 -march=i686" +else + cflags="-fPIC" +fi + +cmake \\ + -D CMAKE_BUILD_TYPE=Release \\ + -D CMAKE_PREFIX_PATH=/opt/lib/oiio-$OIIO_V \\ + -D CMAKE_INSTALL_PREFIX=/opt/lib/oiio-$OIIO_V \\ + -D BUILDSTATIC=ON \\ + -D USE_JASPER=OFF \\ + -D CMAKE_CXX_FLAGS:STRING="\${cflags}" \\ + -D CMAKE_C_FLAGS:STRING="\${cflags}" \\ + -D CMAKE_EXE_LINKER_FLAGS='-lgcc_s -lgcc' \\ + -D BOOST_ROOT=/opt/lib/boost \\ + ../src +EOF + chmod +x "$O/build/prepare.sh" + fi + + # OpenColorIO + O="$SOURCES_PATH/packages/OpenColorIO-$OCIO_V" + if [ ! -d "$O" ]; then + INFO "Downloading OpenColorIO-$OCIO_V" + wget -c http://github.com/imageworks/OpenColorIO/tarball/v$OCIO_V -O "$O.tar.gz" + tar -C "$SOURCES_PATH/packages" -xf "$O.tar.gz" + mv $SOURCES_PATH/packages/imageworks-OpenColorIO* $O + mkdir $O/build + cat << EOF > "$O/build/prepare.sh" +#!/bin/sh + +if file /bin/cp | grep -q '32-bit'; then + cflags="-fPIC -m32 -march=i686" +else + cflags="-fPIC" +fi + +cmake \\ + -D CMAKE_BUILD_TYPE=Release \\ + -D CMAKE_PREFIX_PATH=/opt/lib/ocio-1.0.7 \\ + -D CMAKE_INSTALL_PREFIX=/opt/lib/ocio-1.0.7 \\ + -D BUILDSTATIC=ON \\ + -D CMAKE_CXX_FLAGS:STRING="\${cflags}" \\ + -D CMAKE_C_FLAGS:STRING="\${cflags}" \\ + -D CMAKE_EXE_LINKER_FLAGS='-lgcc_s -lgcc' \\ + .. +EOF + + chmod +x "$O/build/prepare.sh" + fi + + # Mesa + M="$SOURCES_PATH/packages/Mesa-$MESA_V" + if [ ! -d "$M" ]; then + INFO "Downloading Mesa-$MESA_V" + wget -c ftp://ftp.freedesktop.org/pub/mesa/$MESA_V/MesaLib-$MESA_V.tar.bz2 -P "$SOURCES_PATH/packages" + tar -C "$SOURCES_PATH/packages" -xf "$SOURCES_PATH/packages/MesaLib-$MESA_V.tar.bz2" + cat << EOF > "$M/0config.sh" +#!/bin/sh + +OPTS="--with-driver=xlib \\ + --disable-driglx-direct \\ + --disable-egl \\ + --enable-gallium-gbm=no \\ + --enable-gallium-egl=no \\ + --enable-gallium-llvm=no \\ + --with-gallium-drivers=swrast \\ + --with-dri-drivers=swrast \\ + --prefix=/opt/lib/mesa-$MESA_V" + +if file /bin/cp | grep -q '32-bit'; then + ./configure CC="gcc-4.7 -Wl,--as-needed" CXX="g++-4.7 -Wl,--as-needed" LDFLAGS="-pthread -static-libgcc" \${OPTS} --enable-32-bit #--build=i486-linux-gnu +else + ./configure CC="gcc-4.7 -Wl,--as-needed" CXX="g++-4.7 -Wl,--as-needed" LDFLAGS="-pthread -static-libgcc" \${OPTS} +fi + +EOF + chmod +x "$M/0config.sh" + fi + + # OpenAL + O="$SOURCES_PATH/packages/openal-soft-$OPENAL_V" + if [ ! -d "$O" ]; then + INFO "Downloading OpenAL-$OPENAL_V" + wget -c http://kcat.strangesoft.net/openal-releases/openal-soft-$OPENAL_V.tar.bz2 -P "$SOURCES_PATH/packages" + tar -C "$SOURCES_PATH/packages" -xf "$SOURCES_PATH/packages/openal-soft-$OPENAL_V.tar.bz2" + cat << EOF > "$O/build-openal.sh" +#!/bin/sh + +DEB_CMAKE_OPTIONS="-DCMAKE_VERBOSE_MAKEFILE=ON \\ + -DCMAKE_INSTALL_PREFIX=/opt/lib/openal-$OPENAL_V \\ + -DCMAKE_BUILD_TYPE:String=Release \\ + -DALSOFT_CONFIG=ON \\ + -DLIBTYPE=STATIC .. " + +BUILD_TREE=./build-tree + +rm -rf "\${BUILD_TREE}" +mkdir -p "\${BUILD_TREE}" +cd "\${BUILD_TREE}" + +sh -c "cmake \`echo \$DEB_CMAKE_OPTIONS\`" +make -j$THREADS +make install +EOF + chmod +x "$O/build-openal.sh" + fi + + # OpenCollada + O="$SOURCES_PATH/packages/opencollada" + if [ ! -d "$O" ]; then + INFO "Checking out OpenCollada sources" + svn co http://opencollada.googlecode.com/svn/trunk $O + + cat << EOF > "$O/build_all.sh" +#!/bin/sh + +scons RELEASE=0 NOVALIDATION=1 XMLPARSER=libxmlnative PCRENATIVE=1 SHAREDLIB=0 -j ${THREADS} --clean +scons RELEASE=1 NOVALIDATION=1 XMLPARSER=libxmlnative PCRENATIVE=1 SHAREDLIB=0 -j ${THREADS} --clean + +scons RELEASE=0 NOVALIDATION=1 XMLPARSER=libxmlnative PCRENATIVE=1 SHAREDLIB=0 -j ${THREADS} +scons RELEASE=1 NOVALIDATION=1 XMLPARSER=libxmlnative PCRENATIVE=1 SHAREDLIB=0 -j ${THREADS} +EOF + + cat << EOF > "$O/prepare_lib-libxml.sh" +#!/bin/bash + +src="./COLLADAStreamWriter/include +./COLLADABaseUtils/include +./COLLADABaseUtils/include/Math +./COLLADAFramework/include +./GeneratedSaxParser/include +./COLLADASaxFrameworkLoader/include +./COLLADASaxFrameworkLoader/include/generated14 +./COLLADASaxFrameworkLoader/include/generated15" + +if [ -z \$1 ]; then + arch="x86_64" +else + arch=\$1 +fi + +libs="./GeneratedSaxParser/lib/posix/\${arch}/releaselibxml/libGeneratedSaxParser.a +./Externals/MathMLSolver/lib/posix/\${arch}/release/libMathMLSolver.a +./COLLADABaseUtils/lib/posix/\${arch}/release/libOpenCOLLADABaseUtils.a +./COLLADAFramework/lib/posix/\${arch}/release/libOpenCOLLADAFramework.a +./COLLADASaxFrameworkLoader/lib/posix/\${arch}/releaselibxmlNovalidation/libOpenCOLLADASaxFrameworkLoader.a +./COLLADAStreamWriter/lib/posix/\${arch}/release/libOpenCOLLADAStreamWriter.a +./Externals/UTF/lib/posix/\${arch}/release/libUTF.a +./common/libBuffer/lib/posix/\${arch}/release/libbuffer.a +./common/libftoa/lib/posix/\${arch}/release/libftoa.a" + +#./Externals/pcre/lib/posix/\${arch}/release/libpcre.a +#./Externals/LibXML/lib/posix/\${arch}/release/libxml.a + +debug_libs="./GeneratedSaxParser/lib/posix/\${arch}/debuglibxml/libGeneratedSaxParser.a +./Externals/MathMLSolver/lib/posix/\${arch}/debug/libMathMLSolver.a +./COLLADABaseUtils/lib/posix/\${arch}/debug/libOpenCOLLADABaseUtils.a +./COLLADAFramework/lib/posix/\${arch}/debug/libOpenCOLLADAFramework.a +./COLLADASaxFrameworkLoader/lib/posix/\${arch}/debuglibxmlNovalidation/libOpenCOLLADASaxFrameworkLoader.a +./COLLADAStreamWriter/lib/posix/\${arch}/debug/libOpenCOLLADAStreamWriter.a +./Externals/UTF/lib/posix/\${arch}/debug/libUTF.a +./common/libBuffer/lib/posix/\${arch}/debug/libbuffer.a +./common/libftoa/lib/posix/\${arch}/debug/libftoa.a" + +#./Externals/pcre/lib/posix/\${arch}/debug/libpcre.a +#./Externals/LibXML/lib/posix/\${arch}/debug/libxml.a + +d="opencollada-libxml" +rm -rf \${d} +mkdir -p \${d}/include + +for i in \${src}; do + mkdir -p \${d}/include/\${i} + cp \${i}/*.h \${d}/include/\${i} +done + +mkdir \${d}/lib +for i in \${libs}; do + echo "" > /dev/null + cp \${i} \${d}/lib +done + +for i in \${debug_libs}; do + f=\`basename \${i}\` + o=\${f/\\.a/_d.a} + cp \${i} \${d}/lib/\${o} +done + +rm -rf /opt/lib/opencollada +mv \${d} /opt/lib/opencollada +chown -R root:staff /opt/lib/opencollada +EOF + + chmod +x "$O/build_all.sh" + chmod +x "$O/prepare_lib-libxml.sh" + fi + + # Blender + B="$SOURCES_PATH/blender" + if [ ! -d "$B" ]; then + INFO "Checking out Blender sources" + svn co https://svn.blender.org/svnroot/bf-blender/trunk/blender $B + fi + + # CUDA Toolkit + C=$SOURCES_PATH/cudatoolkit + if [ ! -f "$C/$CUDA_32" ]; then + INFO "Downloading CUDA 32bit toolkit" + mkdir -p $C + wget -c http://developer.download.nvidia.com/compute/cuda/4_2/rel/toolkit/$CUDA_32 -P $C + fi + + if [ ! -f "$C/$CUDA_64" ]; then + INFO "Downloading CUDA 64bit toolkit" + mkdir -p $C + wget -c http://developer.download.nvidia.com/compute/cuda/4_2/rel/toolkit/$CUDA_64 -P $C + fi + + if [ ! -f $SOURCES_PATH/Readme.txt ]; then + + cat << EOF > $SOURCES_PATH/Readme.txt +This directory contains different things needed for Blender builds + +blender/: directory with blender's svnsnapshot + +blender-build/, blender-install/: build and install directories for + automated release creation + +buildbot-i686-slave/, +buildbot-x86_64-slave/: buildbot slave environments for automated builds + (maybe it'll be better to move them to /home?) + +staticlibs/: set of static libs. Mostly needed to make static linking prioretized + under dynamic linking + +release-builder/: all stuff needed for release archives preparation + +Hope all this would help you. + +-Sergey- +EOF + fi + + INSTALL_RELEASE_BUILDER $SOURCES_PATH +} + +DO_BACKPORT() { + CHROOT_ARCH=$1 + CHROOT_PATH=$2 + + RUN="chroot $CHROOT_PATH" + P="/home/sources/backport" + + # Backport fresh binutils + if [ `$RUN dpkg-query -W -f='${Version}\n' binutils | grep -c $BINUTILS_V` -eq "0" ]; then + INFO "Backporting binutils" + B="$P/binutils/binutils-$BINUTILS_V" + pkg="$P/binutils/binutils_${BINUTILS_FV}_amd64.deb" + + if [ ! -d "$CHROOT_PATH/$B" ]; then + INFO "Unpacking binutils" + $RUN dpkg-source -x "$P/binutils/binutils_$BINUTILS_FV.dsc" "$B" + fi + + if [ "$CHROOT_ARCH" = "i386" ]; then + pkg=`echo "$pkg" | sed -r 's/amd64/i386/g'` + fi + + if [ ! -f "$CHROOT_PATH/$pkg" ]; then + INFO "Compiling binutils" + sed -ie 's/with_check := yes/with_check := no/' "$CHROOT_PATH/$B/debian/rules" + $RUN sh -c "cd '$B' && dpkg-buildpackage -rfakeroot -j$THREADS" + fi + + INFO "Installing binutils" + $RUN dpkg -i "$pkg" + + INFO "Cleaning binutils" + $RUN sh -c "cd '$B' && fakeroot debian/rules clean" + fi + + # Install fresh gcc + if [ `$RUN dpkg-query -W -f='${Status}\n' gcc-4.7 2> /dev/null | grep -c installed` -eq "0" ]; then + INFO "Backporting gcc-4.7" + G="$P/gcc-4.7/gcc-$GCC_V" + + pkg="cpp-4.7_4.7.1-7_amd64.deb gcc-4.7-base_4.7.1-7_amd64.deb \ + libstdc++6-4.7-dev_4.7.1-7_amd64.deb libstdc++6_4.7.1-7_amd64.deb libgcc1_4.7.1-7_amd64.deb \ + libgomp1_4.7.1-7_amd64.deb libitm1_4.7.1-7_amd64.deb libquadmath0_4.7.1-7_amd64.deb \ + gcc-4.7_4.7.1-7_amd64.deb g++-4.7_4.7.1-7_amd64.deb" + + if [ ! -d "$CHROOT_PATH/$G" ]; then + INFO "Unpacking gcc-4.7" + $RUN dpkg-source -x "$P/gcc-4.7/gcc-$GCC_FV.dsc" "$G" + fi + + if [ "$CHROOT_ARCH" = "i386" ]; then + pkg=`echo "$pkg" | sed -r 's/amd64/i386/g'` + fi + + ok=true + for x in `echo "$pkg"`; do + if [ ! -f "$CHROOT_PATH/$P/gcc-4.7/$x" ]; then + ok=false + break; + fi + done + + if ! $ok; then + INFO "Compiling gcc-4.7" + sed -ie 's/#with_check := disabled by hand/with_check := disabled by hand/' "$CHROOT_PATH/$G/debian/rules.defs" + sed -ie 's/dpkg-dev (>= 1.16.0~ubuntu4)/dpkg-dev (>= 1.15.8)/' "$CHROOT_PATH/$G/debian/control" + sed -ie 's/doxygen (>= 1.7.2)/doxygen (>= 1.7.1)/' "$CHROOT_PATH/$G/debian/control" + sed -ie 's/libmpfr-dev (>= 3.0.0-9~)/libmpfr-dev (>= 3.0.0)/' "$CHROOT_PATH/$G/debian/control" + sed -ie 's/libc6-dev (>= 2.13-5)/libc6-dev (>= 2.11.3)/' "$CHROOT_PATH/$G/debian/control" + sed -ie 's/libgmp-dev (>= 2:5.0.1~)/libgmp3-dev (>= 2:4.3.2)/' "$CHROOT_PATH/$G/debian/control" + $RUN sh -c "cd '$G' && dpkg-buildpackage -rfakeroot" + fi + + inst="" + for x in `echo "$pkg"`; do + inst="$inst $P/gcc-4.7/$x" + done + + INFO "Installing gcc-4.7" + $RUN dpkg -i $inst + + INFO "Cleaning gcc-4.7" + $RUN sh -c "cd '$G' && fakeroot debian/rules clean" + fi +} + +DO_COMPILE() { + CHROOT_ARCH=$1 + CHROOT_PATH=$2 + + RUN="chroot $CHROOT_PATH" + P="/home/sources/packages" + L="$CHROOT_PATH/opt/lib" + + # JeMalloc + if [ ! -d "$L/jemalloc-$JEMALLOC_V" ]; then + INFO "Copmiling jemalloc-$JEMALLOC_V" + $RUN sh -c "cd '$P/jemalloc-$JEMALLOC_V' && ./0config.sh && make clean && make -j$THREADS && make install && make clean" + + rm -f "$L/jemalloc" + ln -s "jemalloc-$JEMALLOC_V" "$L/jemalloc" + fi + + # libspnav + if [ ! -d "$L/libspnav-$SPNAV_V" ]; then + INFO "Copmiling libspnav-$SPNAV_V" + mkdir -p "$L/libspnav-$SPNAV_V/lib" + mkdir -p "$L/libspnav-$SPNAV_V/include" + $RUN sh -c "cd '$P/libspnav-$SPNAV_V' && ./0config.sh && make clean && make -j$THREADS && make install && make clean" + + rm -f "$L/libspnav" + ln -s "libspnav-$SPNAV_V" "$L/libspnav" + fi + + # FFmpeg + if [ ! -d "$L/ffmpeg-$FFMPEG_V" ]; then + INFO "Copmiling ffmpeg-$FFMPEG_V" + $RUN sh -c "cd '$P/ffmpeg-$FFMPEG_V' && ./0config.sh && make clean && make -j$THREADS && make install && make clean" + + rm -f "$L/ffmpeg" + ln -s "ffmpeg-$FFMPEG_V" "$L/ffmpeg" + fi + + # Boost + V=`echo $BOOST_V | sed -r 's/_/./g'` + if [ ! -d "$L/boost-$V" ]; then + INFO "Copmiling boost-$V" + $RUN sh -c "cd '$P/boost_$BOOST_V' && ./bootstrap.sh && ./b2 --clean && ./b2 install --prefix='/opt/lib/boost-$V' && ./b2 --clean" + + rm -f "$L/boost" + ln -s "boost-$V" "$L/boost" + fi + + # OCIO + if [ ! -d "$L/ocio-$OCIO_V" ]; then + INFO "Copmiling ocio-$OCIO_V" + $RUN sh -c "cd '$P/OpenColorIO-$OCIO_V/build' && ./prepare.sh && make clean && make -j$THREADS && make install && make clean" + + # Force linking against sttaic libs + rm -f $L/ocio-$OCIO_V/lib/*.so* + + # Additional depencencies + cp $CHROOT_PATH/$P/OpenColorIO-$OCIO_V/build/ext/dist/lib/libtinyxml.a $L/ocio-$OCIO_V/lib + cp $CHROOT_PATH/$P/OpenColorIO-$OCIO_V/build/ext/dist/lib/libyaml-cpp.a $L/ocio-$OCIO_V/lib + + rm -f "$L/ocio" + ln -s "ocio-$OCIO_V" "$L/ocio" + fi + + # OIIO + if [ ! -d "$L/oiio-$OIIO_V" ]; then + INFO "Copmiling oiio-$OIIO_V" + $RUN sh -c "cd '$P/OpenImageIO-$OIIO_V/build' && ./prepare.sh && make clean && make -j$THREADS && make install && make clean" + + rm -f "$L/oiio" + ln -s "oiio-$OIIO_V" "$L/oiio" + fi + + # Python + if [ ! -d "$L/python-$PYTHON_V" ]; then + INFO "Copmiling Python-$PYTHON_V" + + cat << EOF > $CHROOT_PATH/$P/Python-$PYTHON_V/Modules/Setup.local +_md5 md5module.c + +_sha1 sha1module.c +_sha256 sha256module.c +_sha512 sha512module.c +EOF + + $RUN sh -c "cd '$P/Python-$PYTHON_V' && ./0config.sh && make clean && make -j$THREADS && make install && make clean" + + rm -f "$L/python-$PYTHIN_V_SHORT" + ln -s "python-$PYTHON_V" "$L/python-$PYTHIN_V_SHORT" + fi + + # Mesa + if [ ! -d "$L/mesa-$MESA_V" ]; then + INFO "Copmiling Mesa-$MESA_V" + + $RUN sh -c "cd '$P/Mesa-$MESA_V' && ./0config.sh && make clean && make -j$THREADS && make install && make clean" + + rm -f "$L/mesa" + ln -s "mesa-$MESA_V" "$L/mesa" + fi + + # OpenAL + if [ ! -d "$L/openal-$OPENAL_V" ]; then + INFO "Copmiling openal-$OPENAL_V" + + $RUN sh -c "cd '$P/openal-soft-$OPENAL_V' && ./build-openal.sh" + + rm -f "$L/openal" + ln -s "openal-$OPENAL_V" "$L/openal" + fi + + # OpenCollada + if [ ! -d "$L/opencollada" ]; then + INFO "Copmiling opencollada" + + cat << EOF > "$CHROOT_PATH/$P/opencollada/collada.patch" +Index: common/libBuffer/include/CommonBuffer.h +=================================================================== +--- common/libBuffer/include/CommonBuffer.h (revision 876) ++++ common/libBuffer/include/CommonBuffer.h (working copy) +@@ -12,6 +12,7 @@ + #define __COMMON_BUFFER_H__ + + #include "CommonIBufferFlusher.h" ++#include "COLLADABUPlatform.h" + + namespace Common + { +Index: common/libBuffer/src/CommonLogFileBufferFlusher.cpp +=================================================================== +--- common/libBuffer/src/CommonLogFileBufferFlusher.cpp (revision 876) ++++ common/libBuffer/src/CommonLogFileBufferFlusher.cpp (working copy) +@@ -10,6 +10,34 @@ + + #include "CommonLogFileBufferFlusher.h" + ++#include ++#include ++ ++#ifndef _WIN32 ++FILE *_wfopen(const wchar_t *path, const char *mode) ++{ ++ const wchar_t *src = path; ++ char *path_mbs; ++ int n; ++ FILE *file; ++ ++ n = (int)wcsrtombs(NULL, &src, 0, NULL); ++ ++ if (n < 0) ++ return NULL; ++ ++ path_mbs = (char *)malloc(n + 1); ++ wcsrtombs(path_mbs, &path, n, NULL); ++ path_mbs[n] = 0; ++ ++ file = fopen(path_mbs, mode); ++ ++ free(path_mbs); ++ ++ return file; ++} ++#endif ++ + namespace Common + { + //-------------------------------------------------------------------- +@@ -35,7 +63,7 @@ + #ifdef _WIN32 + mError = (int)_wfopen_s( &stream, fileName, L"wb" ); + #else +- stream = _wfopen( fileName, L"wb" ); ++ stream = _wfopen( fileName, "wb" ); + mError = stream ? 0 : errno; + #endif + if ( !mError ) +@@ -65,7 +93,7 @@ + #else + if ( mUseWideFileName ) + { +- stream = _wfopen( mWideFileName.c_str(), L"a" ); ++ stream = _wfopen( mWideFileName.c_str(), "a" ); + } + else + { +Index: common/libBuffer/SConscript +=================================================================== +--- common/libBuffer/SConscript (revision 876) ++++ common/libBuffer/SConscript (working copy) +@@ -11,7 +11,7 @@ + targetPath = outputDir + libName + + +-incDirs = ['include/', '../libftoa/include'] ++incDirs = ['include/', '../libftoa/include', '../../COLLADABaseUtils/include/', '../../Externals/UTF/include'] + + + src = [] +EOF + + # We're building in a chroot, architecture of host system would be used by scons + collada_arch="x86_64" + + $RUN sh -c "cd '$P/opencollada' && svn revert . -R && cat collada.patch | patch -p0 && ./build_all.sh && ./prepare_lib-libxml.sh $collada_arch" + fi +} + +ADD_REPO() { + CHROOT_PATH=$1 + DESC=$2 + REPO=$3 + C="$CHROOT_PATH/etc/apt/sources.list" + RUN="chroot $CHROOT_PATH" + + if [ `cat "$C" | grep -c "$REPO"` -eq "0" ]; then + INFO "Adding repo $DESC" + echo "" >> $C + echo "deb $REPO" >> $C + echo "deb-src $REPO" >> $C + + INFO "Updating packages list" + $RUN apt-get update + fi +} + +INSTALL_CHROOT() { + CHROOT_ARCH=$1 + CHROOT_PATH=$2 + + RUN="chroot $CHROOT_PATH" + + # Install fresh debian to a chroot + if [ ! -d "$CHROOT_PATH" ]; then + + INFO "Installing Debian ${DEBIAN_BRANCH} to ${CHROOT_PATH}" + debootstrap --arch "${CHROOT_ARCH}" "${DEBIAN_BRANCH}" "${CHROOT_PATH}" "${DEBIAN_MIRROR}" + fi + + # Configure users and groups + + if [ `cat ${CHROOT_PATH}/etc/group | grep -c developers` -eq "0" ]; then + INFO "Creating gorup 'developers'" + $RUN groupadd -g 7001 developers + fi + + if [ `mount | grep -c "$CHROOT_PATH/dev"` -eq "0" ]; then + INFO "Mounting devices from host system to chroot" + + mount -t proc none $CHROOT_PATH/proc + mount -t auto -o bind /dev $CHROOT_PATH/dev + mount -t devpts -o mode=0620 none $CHROOT_PATH/dev/pts + fi + + # Configure apt and install packages + + if [ ! -f ${CHROOT_PATH}/etc/apt/apt.conf ]; then + INFO "Setting up apt to not use recommended packages (saves disk space)" + + cat << EOF > "${CHROOT_PATH}/etc/apt/apt.conf" +APT { + Default-Release "${DEBIAN_BRANCH}"; + Install-Recommends "0"; +}; +EOF + fi + + ADD_REPO $CHROOT_PATH "mirror.yandex.ru" "http://mirror.yandex.ru/debian-multimedia/ squeeze main non-free" + ADD_REPO $CHROOT_PATH "backports.debian.org" "http://backports.debian.org/debian-backports squeeze-backports main non-free" + + $RUN apt-get upgrade + + $RUN apt-get install -y --force-yes deb-multimedia-keyring libx264-dev libxvidcore4-dev libmp3lame-dev + + if [ `$RUN dpkg-query -W -f='${Status}\n' locales | grep -c not-installed` -eq "1" ]; then + INFO "Configuring locales" + $RUN apt-get install -y locales + $RUN localedef -i en_US -f UTF-8 en_US.UTF-8 + fi + + INFO "Installing packages from repository" + $RUN apt-get install -y mc gcc g++ cmake python dpkg-dev build-essential autoconf bison \ + flex gettext texinfo dejagnu quilt file lsb-release zlib1g-dev fakeroot debhelper \ + g++-multilib libtool autoconf2.64 automake gawk lzma patchutils gperf sharutils \ + libcloog-ppl-dev libmpc-dev libmpfr-dev libgmp3-dev autogen realpath chrpath doxygen \ + graphviz gsfonts-x11 texlive-latex-base libelfg0-dev libx11-dev yasm libopenjpeg-dev \ + libschroedinger-dev libtheora-dev libvorbis-dev libvpx-dev=$VPX_V \ + libopenexr-dev libpng-dev libjpeg-dev libtiff-dev python-dev libbz2-dev libreadline-dev \ + libsqlite3-dev liblzma-dev libncurses5-dev xutils-dev libxext-dev python-libxml2 \ + libglu1-mesa-dev libfftw3-dev libfreetype6-dev libsdl1.2-dev libopenal-dev libjack-dev \ + libxi-dev portaudio19-dev po4a subversion scons libpcre3-dev libexpat1-dev sudo \ + expect + + if [ $CHROOT_ARCH = "amd64" ]; then + $RUN apt-get install -y libc6-dev-i386 lib32gcc1 + fi + + # Configure sources directory + if [ ! -d "$CHROOT_PATH/home/sources" ]; then + INFO "Creating sources directory" + $RUN mkdir "/home/sources" + $RUN chmod 775 /home/sources + $RUN chown root:developers /home/sources + fi + + # Bind directory from host system + if [ ! -d "$CHROOT_PATH/home/sources/backport" ]; then + INFO "Binding sources directory from host system to chroot" + mount -o bind "$SOURCES_PATH" "$CHROOT_PATH/home/sources" + fi + + if [ "`$RUN getent passwd $USER_ID`" = "" ]; then + INFO "Adding default user to chroot" + login=`getent passwd $USER_ID | cut -d : -f 1` + $RUN useradd -d "/home/$login" -G developers,sudo -m -u $USER_ID "$login" + fi + + # Backport packages + DO_BACKPORT "$CHROOT_ARCH" "$CHROOT_PATH" + + # Set default compiler to gcc-4.7 + if [ `readlink "$CHROOT_PATH/usr/bin/gcc"` != "gcc-4.7" ]; then + INFO "Setting gcc-4.7 as default compiler" + rm -f $CHROOT_PATH/usr/bin/gcc + rm -f $CHROOT_PATH/usr/bin/g++ + ln -s gcc-4.7 $CHROOT_PATH/usr/bin/gcc + ln -s g++-4.7 $CHROOT_PATH/usr/bin/g++ + fi + + # Compile packages + DO_COMPILE "$CHROOT_ARCH" "$CHROOT_PATH" + + # Install CUDA toolkit + if [ ! -d "$CHROOT_PATH/usr/local/cuda-$CUDA_V" ]; then + INFO "Installing CUDA toolkit" + + if [ "$CHROOT_ARCH" = "amd64" ]; then + C="cudatoolkit_${CUDA_V}_linux_64_${CUDA_DISTR}.run" + else + C="cudatoolkit_${CUDA_V}_linux_32_${CUDA_DISTR}.run" + fi + + rm -f $CHROOT_PATH/usr/local/cuda + + chmod +x $CHROOT_PATH//home/sources/cudatoolkit/$C + + $RUN /usr/bin/expect < /dev/null 2>&1; then + ERROR "debootstrap command not found, can not create chroot environment" + ERROR "Use apt-get install debootstrap to install debootstrap" + exit 1 +fi + +if [ -z "$ENV_PATH" ]; then + ERROR "Incorrect environment directory is set" + exit 1 +fi + +INSTALL_SOURCES "$SOURCES_PATH" +INSTALL_CHROOT amd64 "$AMD64_PATH" +INSTALL_CHROOT i386 "$I686_PATH" + +INFO "Configurtion of build environment is completed!" +echo "Add this lines to your /etc/fstab:" +echo + +for x in $I686_PATH $AMD64_PATH; do + echo "none $x/proc proc auto 0 0" + echo "/dev $x/dev auto bind,auto 0 0" + echo "none $x/dev/pts devpts mode=0620,auto 0 0" + echo "/home/sources $x/home/sources auto bind,auto 0 0" + echo +done + +echo "Add this lines to your /etc/schroot/schroot.conf:" +echo +login=`getent passwd $USER_ID | cut -d : -f 1` + +for x in $I686_PATH $AMD64_PATH; do + echo [`basename $x`] + echo "description=Linux buildbot environment" + echo "directory=$x" + echo "users=$login" + echo "root-groups=root" + echo +done diff --git a/build_files/buildbot/config/user-config-glibc211-i686.py b/build_files/buildbot/config/user-config-glibc211-i686.py new file mode 100644 index 00000000000..23ab87a6ba3 --- /dev/null +++ b/build_files/buildbot/config/user-config-glibc211-i686.py @@ -0,0 +1,145 @@ +BF_BUILDDIR = '../blender-build/linux-glibc211-i686' +BF_INSTALLDIR = '../blender-install/linux-glibc211-i686' +BF_NUMJOBS = 2 + +# Python configuration +BF_PYTHON_VERSION = '3.3' +BF_PYTHON_ABI_FLAGS = 'm' +BF_PYTHON = '/opt/lib/python-3.3' + +WITH_BF_STATICPYTHON = True + +# OpenCollada configuration +WITH_BF_COLLADA = True +WITH_BF_STATICOPENCOLLADA=True +BF_OPENCOLLADA = '/opt/lib/opencollada' +BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include' +BF_OPENCOLLADA_LIB_STATIC = '${BF_OPENCOLLADA}/lib/libOpenCOLLADAStreamWriter.a ' + \ + '${BF_OPENCOLLADA}/lib/libOpenCOLLADASaxFrameworkLoader.a ' + \ + '${BF_OPENCOLLADA}/lib/libOpenCOLLADAFramework.a ' + \ + '${BF_OPENCOLLADA}/lib/libOpenCOLLADABaseUtils.a ' + \ + '${BF_OPENCOLLADA}/lib/libGeneratedSaxParser.a ' + \ + '${BF_OPENCOLLADA}/lib/libUTF.a ${BF_OPENCOLLADA}/lib/libMathMLSolver.a ' + \ + '${BF_OPENCOLLADA}/lib/libbuffer.a ${BF_OPENCOLLADA}/lib/libftoa.a ' + \ + '/usr/lib/libxml2.a /usr/lib/libexpat.a /usr/lib/libpcre.a' +BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib /home/sources/staticlibs/lib64' +BF_PCRE_LIB = '' +BF_EXPAT_LIB = '' + +# FFMPEG configuration +WITH_BF_FFMPEG = True +WITH_BF_STATICFFMPEG = True + +BF_FFMPEG = '/opt/lib/ffmpeg' +BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib' +BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ' + \ + '${BF_FFMPEG_LIBPATH}/libavfilter.a ${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \ + '${BF_FFMPEG_LIBPATH}/libswscale.a ${BF_FFMPEG_LIBPATH}/libswresample.a ' + \ + '/usr/lib/libxvidcore.a /usr/lib/libx264.a /usr/lib/libmp3lame.a /usr/lib/libvpx.a /usr/lib/libvorbis.a ' + \ + '/usr/lib/libogg.a /usr/lib/libvorbisenc.a /usr/lib/libtheora.a /usr/lib/libschroedinger-1.0.a ' + \ + '/usr/lib/liborc-0.4.a' + +# Don't depend on system's libstdc++ +WITH_BF_STATICCXX = True +BF_CXX_LIB_STATIC = '/usr/lib/gcc/i486-linux-gnu/4.7.1/libstdc++.a' + +WITH_BF_OPENAL = True +WITH_BF_STATICOPENAL = True +BF_OPENAL = '/opt/lib/openal' +BF_OPENAL_LIB_STATIC = '/opt/lib/openal/lib/libopenal.a' + +WITH_BF_GETTEXT_STATIC = True + +WITH_BF_FREETYPE_STATIC = False + +WITH_BF_OPENEXR = True +WITH_BF_STATICOPENEXR = True + +WITH_BF_TIFF = True +WITH_BF_STATICTIFF = True +BF_TIFF_LIB_STATIC = '${BF_TIFF}/lib/libtiff.a' + +WITH_BF_JPEG = True +WITH_BF_STATICJPEG = True +BF_JPEG_LIB_STATIC= '${BF_JPEG}/lib/libjpeg.a' + +WITH_BF_PNG = True +WITH_BF_STATICPNG = True +BF_PNG_LIB_STATIC = '${BF_PNG}/lib/libpng.a' + +WITH_BF_STATICLIBSAMPLERATE = True + +WITH_BF_ZLIB = True +WITH_BF_STATICZLIB = True +BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a' + +WITH_BF_SDL = True +WITH_BF_OGG = True + +WITH_BF_OPENMP = True +WITH_BF_STATICOPENMP = True +BF_OPENMP_LIB_STATIC = '/usr/lib/gcc/i486-linux-gnu/4.7/libgomp.a' + +WITH_BF_GAMEENGINE = True +WITH_BF_BULLET = True + +# Blender player (would be enabled in it's own config) +WITH_BF_PLAYER = False + +# Use jemalloc memory manager +WITH_BF_JEMALLOC = True +WITH_BF_STATICJEMALLOC = True +BF_JEMALLOC = '/opt/lib/jemalloc' +BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib' + +# Use 3d mouse library +WITH_BF_3DMOUSE = True +WITH_BF_STATIC3DMOUSE = True +BF_3DMOUSE = '/opt/lib/libspnav' +BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib' + +# FFT +WITH_BF_FFTW3 = True +WITH_BF_STATICFFTW3 = True + +# JACK +WITH_BF_JACK = True +WITH_BF_STATICJACK = True +BF_JACK_LIB_STATIC = '${BF_ZLIB}/lib/libjack.a' + +# Cycles +WITH_BF_CYCLES = True +WITH_BF_CYCLES_CUDA_BINARIES = True +#BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30'] +BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30'] + +WITH_BF_OIIO = True +WITH_BF_STATICOIIO = True +BF_OIIO = '/opt/lib/oiio' +BF_OIIO_INC = '${BF_OIIO}/include' +BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_JPEG}/lib/libjpeg.a' +BF_OIIO_LIBPATH = '${BF_OIIO}/lib' + +# Color management +WITH_BF_OCIO = True +WITH_BF_STATICOCIO = True +BF_OCIO = '/opt/lib/ocio' +BF_OCIO_INC = '${BF_OCIO}/include' +BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a' +BF_OCIO_LIBPATH = '${BF_OCIO}/lib' + +WITH_BF_BOOST = True +WITH_BF_STATICBOOST = True +BF_BOOST = '/opt/lib/boost' +BF_BOOST_INC = '${BF_BOOST}/include' +BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \ + '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' +BF_BOOST_LIBPATH = '${BF_BOOST}/lib' + +# Ocean Simulation +WITH_BF_OCEANSIM = True + +# Compilation and optimization +BF_DEBUG = False +REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++ +PLATFORM_LINKFLAGS = ['-lrt'] diff --git a/build_files/buildbot/config/user-config-glibc211-x86_64.py b/build_files/buildbot/config/user-config-glibc211-x86_64.py new file mode 100644 index 00000000000..84899cc3848 --- /dev/null +++ b/build_files/buildbot/config/user-config-glibc211-x86_64.py @@ -0,0 +1,144 @@ +BF_BUILDDIR = '../blender-build/linux-glibc211-x86_64' +BF_INSTALLDIR = '../blender-install/linux-glibc211-x86_64' +BF_NUMJOBS = 2 + +# Python configuration +BF_PYTHON_VERSION = '3.3' +BF_PYTHON_ABI_FLAGS = 'm' +BF_PYTHON = '/opt/lib/python-3.3' + +WITH_BF_STATICPYTHON = True + +# OpenCollada configuration +WITH_BF_COLLADA = True +WITH_BF_STATICOPENCOLLADA=True +BF_OPENCOLLADA = '/opt/lib/opencollada' +BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include' +BF_OPENCOLLADA_LIB_STATIC = '${BF_OPENCOLLADA}/lib/libOpenCOLLADAStreamWriter.a ' + \ + '${BF_OPENCOLLADA}/lib/libOpenCOLLADASaxFrameworkLoader.a ' + \ + '${BF_OPENCOLLADA}/lib/libOpenCOLLADAFramework.a ' + \ + '${BF_OPENCOLLADA}/lib/libOpenCOLLADABaseUtils.a ' + \ + '${BF_OPENCOLLADA}/lib/libGeneratedSaxParser.a ' + \ + '${BF_OPENCOLLADA}/lib/libUTF.a ${BF_OPENCOLLADA}/lib/libMathMLSolver.a ' + \ + '${BF_OPENCOLLADA}/lib/libbuffer.a ${BF_OPENCOLLADA}/lib/libftoa.a ' + \ + '/usr/lib/libxml2.a /usr/lib/libexpat.a /usr/lib/libpcre.a' +BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib /home/sources/staticlibs/lib64' +BF_PCRE_LIB = '' +BF_EXPAT_LIB = '' + +# FFMPEG configuration +WITH_BF_FFMPEG = True +WITH_BF_STATICFFMPEG = True + +BF_FFMPEG = '/opt/lib/ffmpeg' +BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib' +BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ' + \ + '${BF_FFMPEG_LIBPATH}/libavfilter.a ${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \ + '${BF_FFMPEG_LIBPATH}/libswscale.a ${BF_FFMPEG_LIBPATH}/libswresample.a ' + \ + '/usr/lib/libxvidcore.a /usr/lib/libx264.a /usr/lib/libmp3lame.a /usr/lib/libvpx.a /usr/lib/libvorbis.a ' + \ + '/usr/lib/libogg.a /usr/lib/libvorbisenc.a /usr/lib/libtheora.a /usr/lib/libschroedinger-1.0.a ' + \ + '/usr/lib/liborc-0.4.a' + +# Don't depend on system's libstdc++ +WITH_BF_STATICCXX = True +BF_CXX_LIB_STATIC = '/usr/lib/gcc/x86_64-linux-gnu/4.7.1/libstdc++.a' + +WITH_BF_OPENAL = True +WITH_BF_STATICOPENAL = True +BF_OPENAL = '/opt/lib/openal' +BF_OPENAL_LIB_STATIC = '/opt/lib/openal/lib/libopenal.a' + +WITH_BF_GETTEXT_STATIC = True + +WITH_BF_FREETYPE_STATIC = False + +WITH_BF_OPENEXR = True +WITH_BF_STATICOPENEXR = True + +WITH_BF_TIFF = True +WITH_BF_STATICTIFF = True +BF_TIFF_LIB_STATIC = '${BF_TIFF}/lib/libtiff.a' + +WITH_BF_JPEG = True +WITH_BF_STATICJPEG = True +BF_JPEG_LIB_STATIC= '${BF_JPEG}/lib/libjpeg.a' + +WITH_BF_PNG = True +WITH_BF_STATICPNG = True +BF_PNG_LIB_STATIC = '${BF_PNG}/lib/libpng.a' + +WITH_BF_STATICLIBSAMPLERATE = True + +WITH_BF_ZLIB = True +WITH_BF_STATICZLIB = True +BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a' + +WITH_BF_SDL = True +WITH_BF_OGG = True + +WITH_BF_OPENMP = True +WITH_BF_STATICOPENMP = True +BF_OPENMP_LIB_STATIC = '/usr/lib/gcc/x86_64-linux-gnu/4.7/libgomp.a' + +WITH_BF_GAMEENGINE = True +WITH_BF_BULLET = True + +# Blender player (would be enabled in it's own config) +WITH_BF_PLAYER = False + +# Use jemalloc memory manager +WITH_BF_JEMALLOC = True +WITH_BF_STATICJEMALLOC = True +BF_JEMALLOC = '/opt/lib/jemalloc' +BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib' + +# Use 3d mouse library +WITH_BF_3DMOUSE = True +WITH_BF_STATIC3DMOUSE = True +BF_3DMOUSE = '/opt/lib/libspnav' +BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib' + +# FFT +WITH_BF_FFTW3 = True +WITH_BF_STATICFFTW3 = True + +# JACK +WITH_BF_JACK = True +WITH_BF_STATICJACK = True +BF_JACK_LIB_STATIC = '${BF_ZLIB}/lib/libjack.a' + +# Cycles +WITH_BF_CYCLES = True +WITH_BF_CYCLES_CUDA_BINARIES = True +BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30'] + +WITH_BF_OIIO = True +WITH_BF_STATICOIIO = True +BF_OIIO = '/opt/lib/oiio' +BF_OIIO_INC = '${BF_OIIO}/include' +BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_JPEG}/lib/libjpeg.a' +BF_OIIO_LIBPATH = '${BF_OIIO}/lib' + +# Color management +WITH_BF_OCIO = True +WITH_BF_STATICOCIO = True +BF_OCIO = '/opt/lib/ocio' +BF_OCIO_INC = '${BF_OCIO}/include' +BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a' +BF_OCIO_LIBPATH = '${BF_OCIO}/lib' + +WITH_BF_BOOST = True +WITH_BF_STATICBOOST = True +BF_BOOST = '/opt/lib/boost' +BF_BOOST_INC = '${BF_BOOST}/include' +BF_BOOST_LIB_STATIC = '${BF_BOOST_LIBPATH}/libboost_filesystem.a ${BF_BOOST_LIBPATH}/libboost_date_time.a ' + \ + '${BF_BOOST_LIBPATH}/libboost_regex.a ${BF_BOOST_LIBPATH}/libboost_system.a ${BF_BOOST_LIBPATH}/libboost_thread.a' +BF_BOOST_LIBPATH = '${BF_BOOST}/lib' + +# Ocean Simulation +WITH_BF_OCEANSIM = True + +# Compilation and optimization +BF_DEBUG = False +REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++ +PLATFORM_LINKFLAGS = ['-lrt'] diff --git a/build_files/buildbot/config/user-config-i686.py b/build_files/buildbot/config/user-config-glibc27-i686.py similarity index 90% rename from build_files/buildbot/config/user-config-i686.py rename to build_files/buildbot/config/user-config-glibc27-i686.py index b07dd505369..04b83253678 100644 --- a/build_files/buildbot/config/user-config-i686.py +++ b/build_files/buildbot/config/user-config-glibc27-i686.py @@ -97,7 +97,8 @@ WITH_BF_JACK = True # Cycles WITH_BF_CYCLES = True WITH_BF_CYCLES_CUDA_BINARIES = True -BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30'] +#BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30'] +BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21', 'sm_30'] WITH_BF_OIIO = True WITH_BF_STATICOIIO = True @@ -106,6 +107,14 @@ BF_OIIO_INC = '${BF_OIIO}/include' BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a' BF_OIIO_LIBPATH = '${BF_OIIO}/lib' +# Color management +WITH_BF_OCIO = True +WITH_BF_STATICOCIO = True +BF_OCIO = '/opt/ocio' +BF_OCIO_INC = '${BF_OCIO}/include' +BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a' +BF_OCIO_LIBPATH = '${BF_OCIO}/lib' + WITH_BF_BOOST = True WITH_BF_STATICBOOST = True BF_BOOST = '/opt/boost' diff --git a/build_files/buildbot/config/user-config-x86_64.py b/build_files/buildbot/config/user-config-glibc27-x86_64.py similarity index 93% rename from build_files/buildbot/config/user-config-x86_64.py rename to build_files/buildbot/config/user-config-glibc27-x86_64.py index 5905a9c29dd..070e62b2f20 100644 --- a/build_files/buildbot/config/user-config-x86_64.py +++ b/build_files/buildbot/config/user-config-glibc27-x86_64.py @@ -106,6 +106,14 @@ BF_OIIO_INC = '${BF_OIIO}/include' BF_OIIO_LIB_STATIC = '${BF_OIIO_LIBPATH}/libOpenImageIO.a ${BF_OPENEXR}/lib/libIlmImf.a' BF_OIIO_LIBPATH = '${BF_OIIO}/lib' +# Color management +WITH_BF_OCIO = True +WITH_BF_STATICOCIO = True +BF_OCIO = '/opt/ocio' +BF_OCIO_INC = '${BF_OCIO}/include' +BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a' +BF_OCIO_LIBPATH = '${BF_OCIO}/lib' + WITH_BF_BOOST = True WITH_BF_STATICBOOST = True BF_BOOST = '/opt/boost' diff --git a/build_files/buildbot/config/user-config-player-glibc211-i686.py b/build_files/buildbot/config/user-config-player-glibc211-i686.py new file mode 100644 index 00000000000..3ac061d934f --- /dev/null +++ b/build_files/buildbot/config/user-config-player-glibc211-i686.py @@ -0,0 +1,112 @@ +BF_BUILDDIR = '../blender-build/linux-glibc211-i686' +BF_INSTALLDIR = '../blender-install/linux-glibc211-i686' +BF_NUMJOBS = 2 + +# Python configuration +BF_PYTHON_VERSION = '3.3' +BF_PYTHON_ABI_FLAGS = 'm' +BF_PYTHON = '/opt/lib/python-3.3' + +WITH_BF_STATICPYTHON = True + +# OpenCollada configuration +WITH_BF_COLLADA = False + +# FFMPEG configuration +WITH_BF_FFMPEG = True +WITH_BF_STATICFFMPEG = True + +BF_FFMPEG = '/opt/lib/ffmpeg' +BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib' +BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ' + \ + '${BF_FFMPEG_LIBPATH}/libavfilter.a ${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \ + '${BF_FFMPEG_LIBPATH}/libswscale.a ${BF_FFMPEG_LIBPATH}/libswresample.a ' + \ + '/usr/lib/libxvidcore.a /usr/lib/libx264.a /usr/lib/libmp3lame.a /usr/lib/libvpx.a /usr/lib/libvorbis.a ' + \ + '/usr/lib/libogg.a /usr/lib/libvorbisenc.a /usr/lib/libtheora.a /usr/lib/libschroedinger-1.0.a ' + \ + '/usr/lib/liborc-0.4.a' + +# Don't depend on system's libstdc++ +WITH_BF_STATICCXX = True +BF_CXX_LIB_STATIC = '/usr/lib/gcc/i486-linux-gnu/4.7.1/libstdc++.a' + +WITH_BF_OPENAL = True +WITH_BF_STATICOPENAL = True +BF_OPENAL = '/opt/lib/openal' +BF_OPENAL_LIB_STATIC = '/opt/lib/openal/lib/libopenal.a' + +WITH_BF_GETTEXT_STATIC = True + +WITH_BF_FREETYPE_STATIC = False + +WITH_BF_OPENEXR = True +WITH_BF_STATICOPENEXR = True + +WITH_BF_TIFF = True +WITH_BF_STATICTIFF = True +BF_TIFF_LIB_STATIC = '${BF_TIFF}/lib/libtiff.a' + +WITH_BF_JPEG = True +WITH_BF_STATICJPEG = True +BF_JPEG_LIB_STATIC= '${BF_JPEG}/lib/libjpeg.a' + +WITH_BF_STATICLIBSAMPLERATE = True + +WITH_BF_PNG = True +WITH_BF_STATICPNG = True +BF_PNG_LIB_STATIC = '${BF_PNG}/lib/libpng.a' + +WITH_BF_ZLIB = True +WITH_BF_STATICZLIB = True +BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a' + +WITH_BF_SDL = True +WITH_BF_OGG = False + +WITH_BF_OPENMP = True +WITH_BF_STATICOPENMP = True +BF_OPENMP_LIB_STATIC = '/usr/lib/gcc/i486-linux-gnu/4.7/libgomp.a' + +WITH_BF_GAMEENGINE = True +WITH_BF_BULLET = True + +# Do not build blender when building blenderplayer +WITH_BF_NOBLENDER = True +WITH_BF_PLAYER = True + +# Use jemalloc memory manager +WITH_BF_JEMALLOC = True +WITH_BF_STATICJEMALLOC = True +BF_JEMALLOC = '/opt/lib/jemalloc' +BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib' + +# Use 3d mouse library +WITH_BF_3DMOUSE = True +WITH_BF_STATIC3DMOUSE = True +BF_3DMOUSE = '/opt/lib/libspnav' +BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib' + +# Color management +WITH_BF_OCIO = True +WITH_BF_STATICOCIO = True +BF_OCIO = '/opt/lib/ocio' +BF_OCIO_INC = '${BF_OCIO}/include' +BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a' +BF_OCIO_LIBPATH = '${BF_OCIO}/lib' + +# JACK +WITH_BF_JACK = True +WITH_BF_STATICJACK = True +BF_JACK_LIB_STATIC = '${BF_ZLIB}/lib/libjack.a' + +# Motion Tracking +WITH_BF_LIBMV = False + +# Ocean Simulation +WITH_BF_FFTW3 = True +WITH_BF_STATICFFTW3 = True +WITH_BF_OCEANSIM = True + +# Compilation and optimization +BF_DEBUG = False +REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++ +PLATFORM_LINKFLAGS = ['-lrt'] diff --git a/build_files/buildbot/config/user-config-player-glibc211-x86_64.py b/build_files/buildbot/config/user-config-player-glibc211-x86_64.py new file mode 100644 index 00000000000..08d277edb7b --- /dev/null +++ b/build_files/buildbot/config/user-config-player-glibc211-x86_64.py @@ -0,0 +1,112 @@ +BF_BUILDDIR = '../blender-build/linux-glibc211-x86_64' +BF_INSTALLDIR = '../blender-install/linux-glibc211-x86_64' +BF_NUMJOBS = 2 + +# Python configuration +BF_PYTHON_VERSION = '3.3' +BF_PYTHON_ABI_FLAGS = 'm' +BF_PYTHON = '/opt/lib/python-3.3' + +WITH_BF_STATICPYTHON = True + +# OpenCollada configuration +WITH_BF_COLLADA = False + +# FFMPEG configuration +WITH_BF_FFMPEG = True +WITH_BF_STATICFFMPEG = True + +BF_FFMPEG = '/opt/lib/ffmpeg' +BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib' +BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ' + \ + '${BF_FFMPEG_LIBPATH}/libavfilter.a ${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \ + '${BF_FFMPEG_LIBPATH}/libswscale.a ${BF_FFMPEG_LIBPATH}/libswresample.a ' + \ + '/usr/lib/libxvidcore.a /usr/lib/libx264.a /usr/lib/libmp3lame.a /usr/lib/libvpx.a /usr/lib/libvorbis.a ' + \ + '/usr/lib/libogg.a /usr/lib/libvorbisenc.a /usr/lib/libtheora.a /usr/lib/libschroedinger-1.0.a ' + \ + '/usr/lib/liborc-0.4.a' + +# Don't depend on system's libstdc++ +WITH_BF_STATICCXX = True +BF_CXX_LIB_STATIC = '/usr/lib/gcc/x86_64-linux-gnu/4.7.1/libstdc++.a' + +WITH_BF_OPENAL = True +WITH_BF_STATICOPENAL = True +BF_OPENAL = '/opt/lib/openal' +BF_OPENAL_LIB_STATIC = '/opt/lib/openal/lib/libopenal.a' + +WITH_BF_GETTEXT_STATIC = True + +WITH_BF_FREETYPE_STATIC = False + +WITH_BF_OPENEXR = True +WITH_BF_STATICOPENEXR = True + +WITH_BF_TIFF = True +WITH_BF_STATICTIFF = True +BF_TIFF_LIB_STATIC = '${BF_TIFF}/lib/libtiff.a' + +WITH_BF_JPEG = True +WITH_BF_STATICJPEG = True +BF_JPEG_LIB_STATIC= '${BF_JPEG}/lib/libjpeg.a' + +WITH_BF_STATICLIBSAMPLERATE = True + +WITH_BF_PNG = True +WITH_BF_STATICPNG = True +BF_PNG_LIB_STATIC = '${BF_PNG}/lib/libpng.a' + +WITH_BF_ZLIB = True +WITH_BF_STATICZLIB = True +BF_ZLIB_LIB_STATIC = '${BF_ZLIB}/lib/libz.a' + +WITH_BF_SDL = True +WITH_BF_OGG = False + +WITH_BF_OPENMP = True +WITH_BF_STATICOPENMP = True +BF_OPENMP_LIB_STATIC = '/usr/lib/gcc/x86_64-linux-gnu/4.7/libgomp.a' + +WITH_BF_GAMEENGINE = True +WITH_BF_BULLET = True + +# Do not build blender when building blenderplayer +WITH_BF_NOBLENDER = True +WITH_BF_PLAYER = True + +# Use jemalloc memory manager +WITH_BF_JEMALLOC = True +WITH_BF_STATICJEMALLOC = True +BF_JEMALLOC = '/opt/lib/jemalloc' +BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib' + +# Use 3d mouse library +WITH_BF_3DMOUSE = True +WITH_BF_STATIC3DMOUSE = True +BF_3DMOUSE = '/opt/lib/libspnav' +BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib' + +# Color management +WITH_BF_OCIO = True +WITH_BF_STATICOCIO = True +BF_OCIO = '/opt/lib/ocio' +BF_OCIO_INC = '${BF_OCIO}/include' +BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a' +BF_OCIO_LIBPATH = '${BF_OCIO}/lib' + +# JACK +WITH_BF_JACK = True +WITH_BF_STATICJACK = True +BF_JACK_LIB_STATIC = '${BF_ZLIB}/lib/libjack.a' + +# Motion Tracking +WITH_BF_LIBMV = False + +# Ocean Simulation +WITH_BF_FFTW3 = True +WITH_BF_STATICFFTW3 = True +WITH_BF_OCEANSIM = True + +# Compilation and optimization +BF_DEBUG = False +REL_CCFLAGS = ['-O2', '-msse', '-msse2'] # C & C++ +PLATFORM_LINKFLAGS = ['-lrt'] diff --git a/build_files/buildbot/config/user-config-player-i686.py b/build_files/buildbot/config/user-config-player-glibc27-i686.py similarity index 90% rename from build_files/buildbot/config/user-config-player-i686.py rename to build_files/buildbot/config/user-config-player-glibc27-i686.py index 6c5c5f89ad4..e23fc70262f 100644 --- a/build_files/buildbot/config/user-config-player-i686.py +++ b/build_files/buildbot/config/user-config-player-glibc27-i686.py @@ -82,6 +82,14 @@ WITH_BF_STATIC3DMOUSE = True BF_3DMOUSE = '/home/sources/staticlibs/spnav' BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib32' +# Color management +WITH_BF_OCIO = True +WITH_BF_STATICOCIO = True +BF_OCIO = '/opt/ocio' +BF_OCIO_INC = '${BF_OCIO}/include' +BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a' +BF_OCIO_LIBPATH = '${BF_OCIO}/lib' + # JACK WITH_BF_JACK = True diff --git a/build_files/buildbot/config/user-config-player-x86_64.py b/build_files/buildbot/config/user-config-player-glibc27-x86_64.py similarity index 90% rename from build_files/buildbot/config/user-config-player-x86_64.py rename to build_files/buildbot/config/user-config-player-glibc27-x86_64.py index 60c8060e78e..3c09603473e 100644 --- a/build_files/buildbot/config/user-config-player-x86_64.py +++ b/build_files/buildbot/config/user-config-player-glibc27-x86_64.py @@ -82,6 +82,14 @@ WITH_BF_STATIC3DMOUSE = True BF_3DMOUSE = '/home/sources/staticlibs/spnav' BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib64' +# Color management +WITH_BF_OCIO = True +WITH_BF_STATICOCIO = True +BF_OCIO = '/opt/ocio' +BF_OCIO_INC = '${BF_OCIO}/include' +BF_OCIO_LIB_STATIC = '${BF_OCIO_LIBPATH}/libOpenColorIO.a ${BF_OCIO_LIBPATH}/libtinyxml.a ${BF_OCIO_LIBPATH}/libyaml-cpp.a' +BF_OCIO_LIBPATH = '${BF_OCIO}/lib' + # JACK WITH_BF_JACK = True diff --git a/build_files/buildbot/master.cfg b/build_files/buildbot/master.cfg index 066c133d335..e9deade6e99 100644 --- a/build_files/buildbot/master.cfg +++ b/build_files/buildbot/master.cfg @@ -53,7 +53,7 @@ c['builders'] = [] buildernames = [] -def add_builder(c, name, libdir, factory, branch=''): +def add_builder(c, name, libdir, factory, branch='', rsync=False): slavenames = [] for slave in master_private.slaves: @@ -61,7 +61,7 @@ def add_builder(c, name, libdir, factory, branch=''): slavenames.append(slave['name']) if len(slavenames) > 0: - f = factory(name, libdir, branch) + f = factory(name, libdir, branch, rsync) c['builders'].append(BuilderConfig(name=name, slavenames=slavenames, factory=f, category='blender')) buildernames.append(name) @@ -74,15 +74,17 @@ def svn_step(branch=''): else: return SVN(baseURL='https://svn.blender.org/svnroot/bf-blender/%%BRANCH%%/blender', mode='update', defaultBranch='trunk', workdir='blender') +def lib_svn_step(dir): + return SVN(name='lib svn', baseURL='https://svn.blender.org/svnroot/bf-blender/%%BRANCH%%/lib/' + dir, mode='update', defaultBranch='trunk', workdir='lib/' + dir) -def lib_svn_step(libdir): - return SVN(name='lib svn', baseURL='https://svn.blender.org/svnroot/bf-blender/%%BRANCH%%/lib/' + libdir, mode='update', defaultBranch='trunk', workdir='lib/' + libdir) +def rsync_step(file_from, file_to): + return ShellCommand(name='rsync', command=['rsync', '-v', '-P', file_from, 'brecht@builder.blender.org:/data/buildbot-master/' + file_to], haltOnFailure=True, description=['rsync']) # generic builder -def generic_builder(idname, libdir='', branch=''): - filename = 'buildbot_upload_' + idname + '.zip' +def generic_builder(id, libdir='', branch='', rsync=False): + filename = 'buildbot_upload_' + id + '.zip' compile_script = '../blender/build_files/buildbot/slave_compile.py' test_script = '../blender/build_files/buildbot/slave_test.py' pack_script = '../blender/build_files/buildbot/slave_pack.py' @@ -93,10 +95,12 @@ def generic_builder(idname, libdir='', branch=''): if libdir != '': f.addStep(lib_svn_step(libdir)) - f.addStep(Compile(command=['python', compile_script, idname])) - f.addStep(Test(command=['python', test_script, idname])) - f.addStep(ShellCommand(name='package', command=['python', pack_script, idname, branch], description='packaging', descriptionDone='packaged')) - if 'cmake' in idname: + f.addStep(Compile(command=['python', compile_script, id])) + f.addStep(Test(command=['python', test_script, id])) + f.addStep(ShellCommand(name='package', command=['python', pack_script, id, branch], description='packaging', descriptionDone='packaged')) + if rsync: + f.addStep(rsync_step('../install/buildbot_upload.zip', filename)) + elif id.find('cmake') != -1: f.addStep(FileUpload(name='upload', slavesrc='buildbot_upload.zip', masterdest=filename, maxsize=100 * 1024 * 1024)) else: f.addStep(FileUpload(name='upload', slavesrc='buildbot_upload.zip', masterdest=filename, maxsize=100 * 1024 * 1024, workdir='install')) @@ -105,20 +109,22 @@ def generic_builder(idname, libdir='', branch=''): # builders -add_builder(c, 'mac_x86_64_scons', 'darwin-9.x.universal', generic_builder) -add_builder(c, 'salad_mac_x86_64_scons', 'darwin-9.x.universal', generic_builder, 'soc-2011-salad') +add_builder(c, 'mac_x86_64_scons', '', generic_builder) +#add_builder(c, 'salad_mac_x86_64_scons', 'darwin-9.x.universal', generic_builder, 'soc-2011-salad') add_builder(c, 'mac_i386_scons', 'darwin-9.x.universal', generic_builder) add_builder(c, 'mac_ppc_scons', 'darwin-9.x.universal', generic_builder) #add_builder(c, 'linux_x86_64_cmake', '', generic_builder) -add_builder(c, 'linux_i386_scons', '', generic_builder) -add_builder(c, 'salad_linux_i386_scons', '', generic_builder, 'soc-2011-salad') -add_builder(c, 'linux_x86_64_scons', '', generic_builder) -add_builder(c, 'salad_linux_x86_64_scons', '', generic_builder, 'soc-2011-salad') +add_builder(c, 'linux_glibc27_i386_scons', '', generic_builder) +add_builder(c, 'linux_glibc211_i386_scons', '', generic_builder) +#add_builder(c, 'salad_linux_i386_scons', '', generic_builder, 'soc-2011-salad') +add_builder(c, 'linux_glibc27_x86_64_scons', '', generic_builder) +add_builder(c, 'linux_glibc211_x86_64_scons', '', generic_builder) +#add_builder(c, 'salad_linux_x86_64_scons', '', generic_builder, 'soc-2011-salad') add_builder(c, 'win32_scons', 'windows', generic_builder) -add_builder(c, 'salad_win32_scons', 'windows', generic_builder, 'soc-2011-salad') +#add_builder(c, 'salad_win32_scons', 'windows', generic_builder, 'soc-2011-salad') add_builder(c, 'win64_scons', 'win64', generic_builder) -add_builder(c, 'mingw_win64_scons', 'mingw64', generic_builder) add_builder(c, 'mingw_win32_scons', 'mingw32', generic_builder) +add_builder(c, 'mingw_win64_scons', 'mingw64', generic_builder) #add_builder(c, 'freebsd_i386_cmake', '', generic_builder) #add_builder(c, 'freebsd_x86_64_cmake', '', generic_builder) @@ -137,10 +143,19 @@ c['schedulers'] = [] # builderNames=buildernames, # periodicBuildTimer=24*60*60)) -c['schedulers'].append(timed.Nightly(name='nightly', - builderNames=buildernames, - hour=3, - minute=0)) +schedule_cycle = 4 + +for i in range(0, schedule_cycle): + names = [] + for j in range(0, len(buildernames)): + if j % schedule_cycle == i: + names += [buildernames[j]] + + print(names) + c['schedulers'].append(timed.Nightly(name='nightly' + str(i), + builderNames=names, + hour=3+i, + minute=0)) # STATUS TARGETS # @@ -160,7 +175,7 @@ authz_cfg = authz.Authz( forceBuild=True, # use this to test your slave once it is set up forceAllBuilds=False, pingBuilder=False, - stopBuild=False, + stopBuild=True, stopAllBuilds=False, cancelPendingBuild=True, ) diff --git a/build_files/buildbot/master_unpack.py b/build_files/buildbot/master_unpack.py index f67bd294496..ecacf3bff6f 100644 --- a/build_files/buildbot/master_unpack.py +++ b/build_files/buildbot/master_unpack.py @@ -112,7 +112,7 @@ branch = get_branch(packagename) if platform == '': sys.stderr.write('Failed to detect platform ' + - 'from package: %r\n' % packagename) + 'from package: %r\n' % packagename) sys.exit(1) # extract diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py index eafdf0868cd..bedada93a5a 100644 --- a/build_files/buildbot/slave_compile.py +++ b/build_files/buildbot/slave_compile.py @@ -75,12 +75,18 @@ else: config_dir = os.path.join(buildbot_dir, 'config') configs = [] - if builder.endswith('linux_x86_64_scons'): - configs = ['user-config-player-x86_64.py', - 'user-config-x86_64.py'] - elif builder.endswith('linux_i386_scons'): - configs = ['user-config-player-i686.py', - 'user-config-i686.py'] + if builder.endswith('linux_glibc27_x86_64_scons'): + configs = ['user-config-player-glibc27-x86_64.py', + 'user-config-glibc27-x86_64.py'] + elif builder.endswith('linux_glibc27_i386_scons'): + configs = ['user-config-player-glibc27-i686.py', + 'user-config-glibc27-i686.py'] + if builder.endswith('linux_glibc211_x86_64_scons'): + configs = ['user-config-player-glibc211-x86_64.py', + 'user-config-glibc211-x86_64.py'] + elif builder.endswith('linux_glibc211_i386_scons'): + configs = ['user-config-player-glibc211-i686.py', + 'user-config-glibc211-i686.py'] for config in configs: config_fpath = os.path.join(config_dir, config) diff --git a/build_files/buildbot/slave_pack.py b/build_files/buildbot/slave_pack.py index 654efd72876..b7775ef872f 100644 --- a/build_files/buildbot/slave_pack.py +++ b/build_files/buildbot/slave_pack.py @@ -50,18 +50,24 @@ if builder.find('scons') != -1: install_dir = os.path.join('..', 'install', builder) scons_options += ['WITH_BF_NOBLENDER=True', 'WITH_BF_PLAYER=False', - 'BF_BUILDDIR=' + build_dir, - 'BF_INSTALLDIR=' + install_dir, - 'WITHOUT_BF_INSTALL=True'] + 'BF_BUILDDIR=' + build_dir, + 'BF_INSTALLDIR=' + install_dir, + 'WITHOUT_BF_INSTALL=True'] config = None bits = None - if builder.endswith('linux_x86_64_scons'): - config = 'user-config-x86_64.py' + if builder.endswith('linux_glibc27_x86_64_scons'): + config = 'user-config-glibc27-x86_64.py' bits = 64 - elif builder.endswith('linux_i386_scons'): - config = 'user-config-i686.py' + elif builder.endswith('linux_glibc27_i386_scons'): + config = 'user-config-glibc27-i686.py' + bits = 32 + if builder.endswith('linux_glibc211_x86_64_scons'): + config = 'user-config-glibc211-x86_64.py' + bits = 64 + elif builder.endswith('linux_glibc211_i386_scons'): + config = 'user-config-glibc211-i686.py' bits = 32 if config is not None: diff --git a/build_files/cmake/clang_array_check.py b/build_files/cmake/clang_array_check.py new file mode 100644 index 00000000000..3070c27f769 --- /dev/null +++ b/build_files/cmake/clang_array_check.py @@ -0,0 +1,353 @@ +# --- +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# --- +# by Campbell Barton + +""" +Invocation: + + export CLANG_BIND_DIR="/dsk/src/llvm/tools/clang/bindings/python" + export CLANG_LIB_DIR="/opt/llvm/lib" + + python2 clang_array_check.py somefile.c -DSOME_DEFINE -I/some/include + +... defines and includes are optional + +""" + +# delay parsing functions until we need them +USE_LAZY_INIT = True + +# ----------------------------------------------------------------------------- +# predefined function/arg sizes, handy sometimes, but not complete... + +defs_precalc = { + "glColor3bv": {0: 3}, + "glColor4bv": {0: 4}, + + "glColor3ubv": {0: 3}, + "glColor4ubv": {0: 4}, + + "glColor4usv": {0: 3}, + "glColor4usv": {0: 4}, + + "glColor3fv": {0: 3}, + "glColor4fv": {0: 4}, + + "glColor3dv": {0: 3}, + "glColor4dv": {0: 4}, + + "glVertex2fv": {0: 2}, + "glVertex3fv": {0: 3}, + "glVertex4fv": {0: 4}, + + "glEvalCoord1fv": {0: 1}, + "glEvalCoord1dv": {0: 1}, + "glEvalCoord2fv": {0: 2}, + "glEvalCoord2dv": {0: 2}, + + "glRasterPos2dv": {0: 2}, + "glRasterPos3dv": {0: 3}, + "glRasterPos4dv": {0: 4}, + + "glRasterPos2fv": {0: 2}, + "glRasterPos3fv": {0: 3}, + "glRasterPos4fv": {0: 4}, + + "glRasterPos2sv": {0: 2}, + "glRasterPos3sv": {0: 3}, + "glRasterPos4sv": {0: 4}, + + "glTexCoord2fv": {0: 2}, + "glTexCoord3fv": {0: 3}, + "glTexCoord4fv": {0: 4}, + + "glTexCoord2dv": {0: 2}, + "glTexCoord3dv": {0: 3}, + "glTexCoord4dv": {0: 4}, + + "glNormal3fv": {0: 3}, + "glNormal3dv": {0: 3}, + "glNormal3bv": {0: 3}, + "glNormal3iv": {0: 3}, + "glNormal3sv": {0: 3}, +} + +# ----------------------------------------------------------------------------- + +import sys + +if 0: + # Examples with LLVM as the root dir: '/dsk/src/llvm' + + # path containing 'clang/__init__.py' + CLANG_BIND_DIR = "/dsk/src/llvm/tools/clang/bindings/python" + + # path containing libclang.so + CLANG_LIB_DIR = "/opt/llvm/lib" +else: + import os + CLANG_BIND_DIR = os.environ.get("CLANG_BIND_DIR") + CLANG_LIB_DIR = os.environ.get("CLANG_LIB_DIR") + + if CLANG_BIND_DIR is None: + print("$CLANG_BIND_DIR python binding dir not set") + if CLANG_LIB_DIR is None: + print("$CLANG_LIB_DIR clang lib dir not set") + +sys.path.append(CLANG_BIND_DIR) + +import clang +import clang.cindex +from clang.cindex import (CursorKind, + TypeKind, + TokenKind) + +clang.cindex.Config.set_library_path(CLANG_LIB_DIR) + +index = clang.cindex.Index.create() + +args = sys.argv[2:] +# print(args) + +tu = index.parse(sys.argv[1], args) +print('Translation unit: %s' % tu.spelling) + +# ----------------------------------------------------------------------------- + + +def function_parm_wash_tokens(parm): + # print(parm.kind) + assert parm.kind in (CursorKind.PARM_DECL, + CursorKind.VAR_DECL, # XXX, double check this + CursorKind.FIELD_DECL, + ) + + """ + Return tolens without trailing commads and 'const' + """ + + tokens = [t for t in parm.get_tokens()] + if not tokens: + return tokens + + #if tokens[-1].kind == To + # remove trailing char + if tokens[-1].kind == TokenKind.PUNCTUATION: + if tokens[-1].spelling in (",", ")", ";"): + tokens.pop() + #else: + # print(tokens[-1].spelling) + + t_new = [] + for t in tokens: + t_kind = t.kind + t_spelling = t.spelling + ok = True + if t_kind == TokenKind.KEYWORD: + if t_spelling in ("const", "restrict", "volatile"): + ok = False + elif t_spelling.startswith("__"): + ok = False # __restrict + elif t_kind in (TokenKind.COMMENT, ): + ok = False + + # Use these + elif t_kind in (TokenKind.LITERAL, + TokenKind.PUNCTUATION, + TokenKind.IDENTIFIER): + # use but ignore + pass + + else: + print("Unknown!", t_kind, t_spelling) + + # if its OK we will add + if ok: + t_new.append(t) + return t_new + + +def parm_size(node_child): + tokens = function_parm_wash_tokens(node_child) + + # print(" ".join([t.spelling for t in tokens])) + + # NOT PERFECT CODE, EXTRACT SIZE FROM TOKENS + if len(tokens) >= 3: # foo [ 1 ] + if ((tokens[-3].kind == TokenKind.PUNCTUATION and tokens[-3].spelling == "[") and + (tokens[-2].kind == TokenKind.LITERAL and tokens[-2].spelling.isdigit()) and + (tokens[-1].kind == TokenKind.PUNCTUATION and tokens[-1].spelling == "]")): + # --- + return int(tokens[-2].spelling) + return -1 + + +def function_get_arg_sizes(node): + # Return a dict if (index: size) items + # {arg_indx: arg_array_size, ... ] + arg_sizes = {} + + if 1: # node.spelling == "BM_vert_create", for debugging + node_parms = [node_child for node_child in node.get_children() + if node_child.kind == CursorKind.PARM_DECL] + + for i, node_child in enumerate(node_parms): + + # print(node_child.kind, node_child.spelling) + #print(node_child.type.kind, node_child.spelling) # TypeKind.POINTER + + if node_child.type.kind == TypeKind.POINTER: + pointee = node_child.type.get_pointee() + if pointee.is_pod(): + size = parm_size(node_child) + if size != -1: + arg_sizes[i] = size + + return arg_sizes + + +# ----------------------------------------------------------------------------- +_defs = {} + + +def lookup_function_size_def(func_id): + if USE_LAZY_INIT: + result = _defs.get(func_id, {}) + if type(result) != dict: + result = _defs[func_id] = function_get_arg_sizes(result) + return result + else: + return _defs.get(func_id, {}) + +# ----------------------------------------------------------------------------- + + +def file_check_arg_sizes(tu): + + # main checking function + def validate_arg_size(node): + """ + Loop over args and validate sizes for args we KNOW the size of. + """ + assert node.kind == CursorKind.CALL_EXPR + + if 0: + print("---", + " <~> ".join( + [" ".join([t.spelling for t in C.get_tokens()]) + for C in node.get_children()] + )) + # print(node.location) + + # first child is the function call, skip that. + children = list(node.get_children()) + + if not children: + return # XXX, look into this, happens on C++ + + func = children[0] + + # get the func declaration! + # works but we can better scan for functions ahead of time. + if 0: + func_dec = func.get_definition() + if func_dec: + print("FD", " ".join([t.spelling for t in func_dec.get_tokens()])) + else: + # HRMP'f - why does this fail? + print("AA", " ".join([t.spelling for t in node.get_tokens()])) + else: + args_size_definition = () # dummy + + # get the key + tok = list(func.get_tokens()) + if tok: + func_id = tok[0].spelling + args_size_definition = lookup_function_size_def(func_id) + + if not args_size_definition: + return + + children = children[1:] + for i, node_child in enumerate(children): + children = list(node_child.get_children()) + + # skip if we dont have an index... + size_def = args_size_definition.get(i, -1) + + if size_def == -1: + continue + + #print([c.kind for c in children]) + # print(" ".join([t.spelling for t in node_child.get_tokens()])) + + if len(children) == 1: + arg = children[0] + if arg.kind in (CursorKind.DECL_REF_EXPR, + CursorKind.UNEXPOSED_EXPR): + + if arg.type.kind == TypeKind.POINTER: + dec = arg.get_definition() + if dec: + size = parm_size(dec) + + # size == 0 is for 'float *a' + if size != -1 and size != 0: + + # nice print! + if 0: + print("".join([t.spelling for t in func.get_tokens()]), + i, + " ".join([t.spelling for t in dec.get_tokens()])) + + # testing + # size_def = 100 + if size < size_def and size != 1: + location = node.location + print("%s:%d:%d: argument %d is size %d, should be %d" % + (location.file, + location.line, + location.column, + i + 1, size, size_def + )) + + # we dont really care what we are looking at, just scan entire file for + # function calls. + + def recursive_func_call_check(node): + if node.kind == CursorKind.CALL_EXPR: + validate_arg_size(node) + + for c in node.get_children(): + recursive_func_call_check(c) + + recursive_func_call_check(tu.cursor) + + +# -- first pass, cache function definitions sizes + +# PRINT FUNC DEFINES +def recursive_arg_sizes(node, ): + # print(node.kind, node.spelling) + if node.kind == CursorKind.FUNCTION_DECL: + if USE_LAZY_INIT: + args_sizes = node + else: + args_sizes = function_get_arg_sizes(node) + #if args_sizes: + # print(node.spelling, args_sizes) + _defs[node.spelling] = args_sizes + # print("adding", node.spelling) + for c in node.get_children(): + recursive_arg_sizes(c) +# cache function sizes +recursive_arg_sizes(tu.cursor) +_defs.update(defs_precalc) + +# --- second pass, check against def's +file_check_arg_sizes(tu) diff --git a/build_files/cmake/cmake_consistency_check_config.py b/build_files/cmake/cmake_consistency_check_config.py index a6215b40ae8..6b82e224a32 100644 --- a/build_files/cmake/cmake_consistency_check_config.py +++ b/build_files/cmake/cmake_consistency_check_config.py @@ -2,11 +2,9 @@ import os IGNORE = ( "/test/", - "/decimate_glut_test/", "/BSP_GhostTest/", "/release/", "/xembed/", - "/decimation/intern/future/", "/TerraplayNetwork/", "/ik_glut_test/", diff --git a/build_files/cmake/cmake_qtcreator_project.py b/build_files/cmake/cmake_qtcreator_project.py index 32d20489e6a..83ea761e2d1 100755 --- a/build_files/cmake/cmake_qtcreator_project.py +++ b/build_files/cmake/cmake_qtcreator_project.py @@ -105,7 +105,13 @@ def create_qtc_project_main(): qtc_cfg = os.path.join(PROJECT_DIR, "%s.config" % FILE_NAME) f = open(qtc_cfg, 'w') - f.write("// ADD PREDEFINED MACROS HERE!\n") + f.write("// ADD PREDEFINED MACROS TO %s_custom.config!\n" % FILE_NAME) + qtc_custom_cfg = os.path.join(PROJECT_DIR, "%s_custom.config" % FILE_NAME) + if os.path.exists(qtc_custom_cfg): + fc = open(qtc_custom_cfg, 'r') + f.write(fc.read()) + fc.close() + f.write("\n") defines_final = [("#define %s %s" % (item[0], quote_define(item[1]))) for item in defines] if sys.platform != "win32": defines_final += cmake_compiler_defines() diff --git a/build_files/cmake/cmake_static_check_clang_array.py b/build_files/cmake/cmake_static_check_clang_array.py new file mode 100644 index 00000000000..941407170ff --- /dev/null +++ b/build_files/cmake/cmake_static_check_clang_array.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3.2 + +# ***** 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. +# +# Contributor(s): Campbell Barton +# +# ***** END GPL LICENSE BLOCK ***** + +# + +import project_source_info +import subprocess +import sys +import os + +CHECKER_IGNORE_PREFIX = [ + "extern", + "intern/moto", + "blender/intern/opennl", + ] + +CHECKER_BIN = "python2" + +CHECKER_ARGS = [ + os.path.join(os.path.dirname(__file__), "clang_array_check.py"), + # not sure why this is needed, but it is. + "-I" + os.path.join(project_source_info.SOURCE_DIR, "extern", "glew", "include"), + ] + + +def main(): + source_info = project_source_info.build_info(ignore_prefix_list=CHECKER_IGNORE_PREFIX) + + check_commands = [] + for c, inc_dirs, defs in source_info: + cmd = ([CHECKER_BIN] + + CHECKER_ARGS + + [c] + + [("-I%s" % i) for i in inc_dirs] + + [("-D%s" % d) for d in defs] + ) + + check_commands.append((c, cmd)) + + process_functions = [] + + def my_process(i, c, cmd): + percent = 100.0 * (i / (len(check_commands) - 1)) + percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:" + + sys.stdout.flush() + sys.stdout.write("%s " % percent_str) + + return subprocess.Popen(cmd) + + for i, (c, cmd) in enumerate(check_commands): + process_functions.append((my_process, (i, c, cmd))) + + project_source_info.queue_processes(process_functions) + + +if __name__ == "__main__": + main() diff --git a/build_files/cmake/cmake_static_check_cppcheck.py b/build_files/cmake/cmake_static_check_cppcheck.py index c340ca5c458..c458e8ede11 100644 --- a/build_files/cmake/cmake_static_check_cppcheck.py +++ b/build_files/cmake/cmake_static_check_cppcheck.py @@ -30,6 +30,7 @@ import os CHECKER_IGNORE_PREFIX = [ "extern", "intern/moto", + "blender/intern/opennl", ] CHECKER_BIN = "cppcheck" @@ -54,7 +55,7 @@ def main(): [c] + [("-I%s" % i) for i in inc_dirs] + [("-D%s" % d) for d in defs] - ) + ) check_commands.append((c, cmd)) diff --git a/build_files/cmake/cmake_static_check_smatch.py b/build_files/cmake/cmake_static_check_smatch.py index 779945b030a..5681d2ae5ed 100644 --- a/build_files/cmake/cmake_static_check_smatch.py +++ b/build_files/cmake/cmake_static_check_smatch.py @@ -25,6 +25,7 @@ CHECKER_IGNORE_PREFIX = [ "extern", "intern/moto", + "blender/intern/opennl", ] CHECKER_BIN = "smatch" @@ -49,7 +50,7 @@ def main(): [c] + [("-I%s" % i) for i in inc_dirs] + [("-D%s" % d) for d in defs] - ) + ) check_commands.append((c, cmd)) diff --git a/build_files/cmake/cmake_static_check_sparse.py b/build_files/cmake/cmake_static_check_sparse.py index db1b14e7acb..4f4eb838dd5 100644 --- a/build_files/cmake/cmake_static_check_sparse.py +++ b/build_files/cmake/cmake_static_check_sparse.py @@ -25,6 +25,7 @@ CHECKER_IGNORE_PREFIX = [ "extern", "intern/moto", + "blender/intern/opennl", ] CHECKER_BIN = "sparse" @@ -47,7 +48,7 @@ def main(): [c] + [("-I%s" % i) for i in inc_dirs] + [("-D%s" % d) for d in defs] - ) + ) check_commands.append((c, cmd)) diff --git a/build_files/cmake/cmake_static_check_splint.py b/build_files/cmake/cmake_static_check_splint.py index f538fa612d0..7be28c01af8 100644 --- a/build_files/cmake/cmake_static_check_splint.py +++ b/build_files/cmake/cmake_static_check_splint.py @@ -25,6 +25,7 @@ CHECKER_IGNORE_PREFIX = [ "extern", "intern/moto", + "blender/intern/opennl", ] CHECKER_BIN = "splint" @@ -79,7 +80,7 @@ def main(): [c] + [("-I%s" % i) for i in inc_dirs] + [("-D%s" % d) for d in defs] - ) + ) check_commands.append((c, cmd)) diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake index b834cd37a8a..e74d1adcb1b 100644 --- a/build_files/cmake/config/blender_lite.cmake +++ b/build_files/cmake/config/blender_lite.cmake @@ -10,6 +10,7 @@ set(WITH_SYSTEM_GLEW ON CACHE FORCE BOOL) set(WITH_BUILDINFO OFF CACHE FORCE BOOL) set(WITH_BULLET OFF CACHE FORCE BOOL) +set(WITH_CODEC_AVI OFF CACHE FORCE BOOL) set(WITH_CODEC_FFMPEG OFF CACHE FORCE BOOL) set(WITH_CODEC_SNDFILE OFF CACHE FORCE BOOL) set(WITH_CYCLES OFF CACHE FORCE BOOL) @@ -34,7 +35,6 @@ set(WITH_JACK OFF CACHE FORCE BOOL) set(WITH_LZMA OFF CACHE FORCE BOOL) set(WITH_LZO OFF CACHE FORCE BOOL) set(WITH_MOD_BOOLEAN OFF CACHE FORCE BOOL) -set(WITH_MOD_DECIMATE OFF CACHE FORCE BOOL) set(WITH_MOD_FLUID OFF CACHE FORCE BOOL) set(WITH_MOD_REMESH OFF CACHE FORCE BOOL) set(WITH_MOD_SMOKE OFF CACHE FORCE BOOL) @@ -42,6 +42,7 @@ set(WITH_MOD_OCEANSIM OFF CACHE FORCE BOOL) set(WITH_AUDASPACE OFF CACHE FORCE BOOL) set(WITH_OPENAL OFF CACHE FORCE BOOL) set(WITH_OPENCOLLADA OFF CACHE FORCE BOOL) +set(WITH_OPENCOLORIO OFF CACHE FORCE BOOL) set(WITH_OPENMP OFF CACHE FORCE BOOL) set(WITH_PYTHON_INSTALL OFF CACHE FORCE BOOL) set(WITH_RAYOPTIMIZATION OFF CACHE FORCE BOOL) diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 43cfb31c03c..3c321cc60be 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -244,6 +244,9 @@ macro(SETUP_LIBDIRS) link_directories(${PCRE_LIBPATH}) link_directories(${EXPAT_LIBPATH}) endif() + if(WITH_LLVM) + link_directories(${LLVM_LIB_DIR}) + endif() if(WITH_MEM_JEMALLOC) link_directories(${JEMALLOC_LIBPATH}) endif() @@ -382,6 +385,9 @@ macro(setup_liblinks if(WITH_CYCLES_OSL) target_link_libraries(${target} ${OSL_LIBRARIES}) endif() + if(WITH_LLVM) + target_link_libraries(${target} ${LLVM_LIBRARY}) + endif() if(WIN32 AND NOT UNIX) target_link_libraries(${target} ${PTHREADS_LIBRARIES}) endif() @@ -519,7 +525,7 @@ macro(remove_strict_flags_file # TODO endif() - endforeach() + endforeach() unset(_SOURCE) diff --git a/build_files/cmake/project_info.py b/build_files/cmake/project_info.py index a80ae623eb9..b154d578144 100755 --- a/build_files/cmake/project_info.py +++ b/build_files/cmake/project_info.py @@ -112,7 +112,7 @@ def is_glsl(filename): def is_c(filename): ext = splitext(filename)[1] - return (ext in (".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl")) + return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl", ".osl"}) def is_c_any(filename): @@ -133,12 +133,20 @@ def cmake_advanced_info(): """ Extracr includes and defines from cmake. """ + make_exe = cmake_cache_var("CMAKE_MAKE_PROGRAM") + make_exe_basename = os.path.basename(make_exe) + def create_eclipse_project(): print("CMAKE_DIR %r" % CMAKE_DIR) if sys.platform == "win32": cmd = 'cmake "%s" -G"Eclipse CDT4 - MinGW Makefiles"' % CMAKE_DIR else: - cmd = 'cmake "%s" -G"Eclipse CDT4 - Unix Makefiles"' % CMAKE_DIR + if make_exe_basename.startswith("make"): + cmd = 'cmake "%s" -G"Eclipse CDT4 - Unix Makefiles"' % CMAKE_DIR + elif make_exe_basename.startswith("ninja"): + cmd = 'cmake "%s" -G"Eclipse CDT4 - Ninja"' % CMAKE_DIR + else: + raise Exception("Unknown make program %r" % make_exe) os.system(cmd) diff --git a/build_files/cmake/project_source_info.py b/build_files/cmake/project_source_info.py index ed17ec5bac4..10bc36ba1a8 100644 --- a/build_files/cmake/project_source_info.py +++ b/build_files/cmake/project_source_info.py @@ -48,7 +48,7 @@ def is_c_header(filename): def is_c(filename): ext = os.path.splitext(filename)[1] - return (ext in (".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl")) + return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl", ".osl"}) def is_c_any(filename): @@ -82,10 +82,20 @@ def makefile_log(): import subprocess import time - print("running make with --dry-run ...") - process = subprocess.Popen(["make", "--always-make", "--dry-run", "--keep-going", "VERBOSE=1"], - stdout=subprocess.PIPE, - ) + # support both make and ninja + make_exe = cmake_cache_var("CMAKE_MAKE_PROGRAM") + make_exe_basename = os.path.basename(make_exe) + + if make_exe_basename.startswith("make"): + print("running 'make' with --dry-run ...") + process = subprocess.Popen([make_exe, "--always-make", "--dry-run", "--keep-going", "VERBOSE=1"], + stdout=subprocess.PIPE, + ) + elif make_exe_basename.startswith("ninja"): + print("running 'ninja' with -t commands ...") + process = subprocess.Popen([make_exe, "-t", "commands"], + stdout=subprocess.PIPE, + ) while process.poll(): time.sleep(1) @@ -145,6 +155,12 @@ def build_info(use_c=True, use_cxx=True, ignore_prefix_list=None): source.append((c, inc_dirs, defs)) + # make relative includes absolute + # not totally essential but useful + for i, f in enumerate(inc_dirs): + if not os.path.isabs(f): + inc_dirs[i] = os.path.abspath(os.path.join(CMAKE_DIR, f)) + # safety check that our includes are ok for f in inc_dirs: if not os.path.exists(f): diff --git a/build_files/package_spec/rpm/blender.spec.in b/build_files/package_spec/rpm/blender.spec.in index 85a689031a3..a95fce80103 100644 --- a/build_files/package_spec/rpm/blender.spec.in +++ b/build_files/package_spec/rpm/blender.spec.in @@ -76,6 +76,7 @@ fi || : %defattr(-,root,root,-) %{_bindir}/%{name} %{_datadir}/%{name}/%{blender_api}/datafiles/fonts +%{_datadir}/%{name}/%{blender_api}/datafiles/colormanagement %{_datadir}/%{name}/%{blender_api}/scripts %{_datadir}/icons/hicolor/*/apps/%{name}.* %{_datadir}/applications/%{name}.desktop diff --git a/build_files/scons/config/linux-config.py b/build_files/scons/config/linux-config.py index 5c16baa2ee8..45f6602e4dd 100644 --- a/build_files/scons/config/linux-config.py +++ b/build_files/scons/config/linux-config.py @@ -239,7 +239,7 @@ WITH_BF_CYCLES = WITH_BF_OIIO and WITH_BF_BOOST WITH_BF_CYCLES_CUDA_BINARIES = False BF_CYCLES_CUDA_NVCC = '/usr/local/cuda/bin/nvcc' -BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21'] +BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30'] WITH_BF_OPENMP = True diff --git a/build_files/scons/config/win32-mingw-config.py b/build_files/scons/config/win32-mingw-config.py index 95b2329f426..0a72d87bb2a 100644 --- a/build_files/scons/config/win32-mingw-config.py +++ b/build_files/scons/config/win32-mingw-config.py @@ -159,7 +159,7 @@ BF_OIIO_INC = BF_OIIO + '/include' BF_OIIO_LIB = 'OpenImageIO' BF_OIIO_LIBPATH = BF_OIIO + '/lib' -WITH_BF_OCIO = False +WITH_BF_OCIO = True BF_OCIO = LIBDIR + '/opencolorio' BF_OCIO_INC = BF_OCIO + '/include' BF_OCIO_LIB = 'OpenColorIO' @@ -168,7 +168,7 @@ BF_OCIO_LIBPATH = BF_OCIO + '/lib' WITH_BF_BOOST = True BF_BOOST = LIBDIR + '/boost' BF_BOOST_INC = BF_BOOST + '/include' -BF_BOOST_LIB = 'boost_date_time-mgw46-mt-s-1_47 boost_filesystem-mgw46-mt-s-1_47 boost_regex-mgw46-mt-s-1_47 boost_system-mgw46-mt-s-1_47 boost_thread-mgw46-mt-s-1_47' +BF_BOOST_LIB = 'boost_date_time-mgw46-mt-s-1_49 boost_filesystem-mgw46-mt-s-1_49 boost_regex-mgw46-mt-s-1_49 boost_system-mgw46-mt-s-1_49 boost_thread-mgw46-mt-s-1_49' BF_BOOST_LIBPATH = BF_BOOST + '/lib' #Ray trace optimization @@ -201,7 +201,7 @@ LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32 PLATFORM_LINKFLAGS = ['-Xlinker', '--stack=2097152'] ## DISABLED, causes linking errors! -## for re-distrobution, so users dont need mingw installed +## for re-distribution, so users dont need mingw installed # PLATFORM_LINKFLAGS += ["-static-libgcc", "-static-libstdc++"] BF_DEBUG = False diff --git a/build_files/scons/config/win64-mingw-config.py b/build_files/scons/config/win64-mingw-config.py index c2bf2df6d00..838822bbbcb 100644 --- a/build_files/scons/config/win64-mingw-config.py +++ b/build_files/scons/config/win64-mingw-config.py @@ -159,7 +159,7 @@ BF_OIIO_INC = '${BF_OIIO}/include' BF_OIIO_LIB = 'OpenImageIO' BF_OIIO_LIBPATH = '${BF_OIIO}/lib' -WITH_BF_OCIO = False +WITH_BF_OCIO = True BF_OCIO = LIBDIR + '/opencolorio' BF_OCIO_INC = '${BF_OCIO}/include' BF_OCIO_LIB = 'OpenColorIO' @@ -199,7 +199,7 @@ LLIBS = ['-lshell32', '-lshfolder', '-lgdi32', '-lmsvcrt', '-lwinmm', '-lmingw32 PLATFORM_LINKFLAGS = ['-Xlinker', '--stack=2097152'] ## DISABLED, causes linking errors! -## for re-distrobution, so users dont need mingw installed +## for re-distribution, so users dont need mingw installed # PLATFORM_LINKFLAGS += ["-static-libgcc", "-static-libstdc++"] BF_DEBUG = False diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py index 1e114a43ae0..eb646f27d53 100644 --- a/build_files/scons/tools/Blender.py +++ b/build_files/scons/tools/Blender.py @@ -136,6 +136,11 @@ def setup_staticlibs(lenv): lenv['BF_ICONV_LIBPATH'] ]) + if lenv['WITH_BF_STATICJPEG']: + statlibs += Split(lenv['BF_JPEG_LIB_STATIC']) + if lenv['WITH_BF_STATICPNG']: + statlibs += Split(lenv['BF_PNG_LIB_STATIC']) + libincs += Split(lenv['BF_FREETYPE_LIBPATH']) if lenv['WITH_BF_PYTHON']: libincs += Split(lenv['BF_PYTHON_LIBPATH']) @@ -143,6 +148,8 @@ def setup_staticlibs(lenv): libincs += Split(lenv['BF_SDL_LIBPATH']) if lenv['WITH_BF_JACK']: libincs += Split(lenv['BF_JACK_LIBPATH']) + if lenv['WITH_BF_STATICJACK']: + statlibs += Split(lenv['BF_JACK_LIB_STATIC']) if lenv['WITH_BF_SNDFILE']: libincs += Split(lenv['BF_SNDFILE_LIBPATH']) if lenv['WITH_BF_OPENEXR']: @@ -194,10 +201,14 @@ def setup_staticlibs(lenv): if lenv['OURPLATFORM'] not in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): libincs += Split(lenv['BF_PCRE_LIBPATH']) libincs += Split(lenv['BF_EXPAT_LIBPATH']) + if lenv['WITH_BF_STATICOPENCOLLADA']: + statlibs += Split(lenv['BF_OPENCOLLADA_LIB_STATIC']) if lenv['WITH_BF_OPENMP']: if lenv['OURPLATFORM'] == 'linuxcross': libincs += Split(lenv['BF_OPENMP_LIBPATH']) + if lenv['WITH_BF_STATICOPENMP']: + statlibs += Split(lenv['BF_OPENMP_LIB_STATIC']) if lenv['WITH_BF_OIIO']: libincs += Split(lenv['BF_OIIO_LIBPATH']) @@ -246,7 +257,7 @@ def setup_syslibs(lenv): if lenv['WITH_BF_OPENAL']: if not lenv['WITH_BF_STATICOPENAL']: syslibs += Split(lenv['BF_OPENAL_LIB']) - if lenv['WITH_BF_OPENMP'] and lenv['CC'] != 'icc': + if lenv['WITH_BF_OPENMP'] and lenv['CC'] != 'icc' and not lenv['WITH_BF_STATICOPENMP']: if lenv['CC'] == 'cl.exe': syslibs += ['vcomp'] else: @@ -271,7 +282,7 @@ def setup_syslibs(lenv): syslibs += Split(lenv['BF_FFMPEG_LIB']) if lenv['WITH_BF_OGG']: syslibs += Split(lenv['BF_OGG_LIB']) - if lenv['WITH_BF_JACK']: + if lenv['WITH_BF_JACK'] and not lenv['WITH_BF_STATICJACK']: syslibs += Split(lenv['BF_JACK_LIB']) if lenv['WITH_BF_SNDFILE'] and not lenv['WITH_BF_STATICSNDFILE']: syslibs += Split(lenv['BF_SNDFILE_LIB']) @@ -285,7 +296,7 @@ def setup_syslibs(lenv): syslibs += Split(lenv['BF_OPENGL_LIB']) if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw','linuxcross', 'win64-vc', 'win64-mingw'): syslibs += Split(lenv['BF_PTHREADS_LIB']) - if lenv['WITH_BF_COLLADA']: + if lenv['WITH_BF_COLLADA'] and not lenv['WITH_BF_STATICOPENCOLLADA']: syslibs.append(lenv['BF_PCRE_LIB']) if lenv['BF_DEBUG'] and (lenv['OURPLATFORM'] != 'linux'): syslibs += [colladalib+'_d' for colladalib in Split(lenv['BF_OPENCOLLADA_LIB'])] @@ -305,8 +316,11 @@ def setup_syslibs(lenv): if lenv['WITH_BF_BOOST'] and not lenv['WITH_BF_STATICBOOST']: syslibs += Split(lenv['BF_BOOST_LIB']) - syslibs += Split(lenv['BF_JPEG_LIB']) - syslibs += Split(lenv['BF_PNG_LIB']) + if not lenv['WITH_BF_STATICJPEG']: + syslibs += Split(lenv['BF_JPEG_LIB']) + + if not lenv['WITH_BF_STATICPNG']: + syslibs += Split(lenv['BF_PNG_LIB']) syslibs += lenv['LLIBS'] diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py index 633492ba0ee..19652bb7851 100644 --- a/build_files/scons/tools/btools.py +++ b/build_files/scons/tools/btools.py @@ -99,7 +99,7 @@ def validate_arguments(args, bc): 'WITH_BF_PYTHON', 'WITH_BF_PYTHON_SAFETY', 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'WITH_BF_STATICPYTHON', 'WITH_OSX_STATICPYTHON', 'BF_PYTHON_LIB_STATIC', 'BF_PYTHON_DLL', 'BF_PYTHON_ABI_FLAGS', 'WITH_BF_OPENAL', 'BF_OPENAL', 'BF_OPENAL_INC', 'BF_OPENAL_LIB', 'BF_OPENAL_LIBPATH', 'WITH_BF_STATICOPENAL', 'BF_OPENAL_LIB_STATIC', 'WITH_BF_SDL', 'BF_SDL', 'BF_SDL_INC', 'BF_SDL_LIB', 'BF_SDL_LIBPATH', - 'WITH_BF_JACK', 'BF_JACK', 'BF_JACK_INC', 'BF_JACK_LIB', 'BF_JACK_LIBPATH', + 'WITH_BF_JACK', 'BF_JACK', 'BF_JACK_INC', 'BF_JACK_LIB', 'BF_JACK_LIBPATH', 'WITH_BF_STATICJACK', 'BF_JACK_LIB_STATIC', 'WITH_BF_SNDFILE', 'BF_SNDFILE', 'BF_SNDFILE_INC', 'BF_SNDFILE_LIB', 'BF_SNDFILE_LIBPATH', 'WITH_BF_STATICSNDFILE', 'BF_SNDFILE_LIB_STATIC', 'BF_PTHREADS', 'BF_PTHREADS_INC', 'BF_PTHREADS_LIB', 'BF_PTHREADS_LIBPATH', 'WITH_BF_OPENEXR', 'BF_OPENEXR', 'BF_OPENEXR_INC', 'BF_OPENEXR_LIB', 'BF_OPENEXR_LIBPATH', 'WITH_BF_STATICOPENEXR', 'BF_OPENEXR_LIB_STATIC', @@ -109,10 +109,10 @@ def validate_arguments(args, bc): 'WITH_BF_OGG', 'BF_OGG', 'BF_OGG_LIB', 'WITH_BF_FRAMESERVER', 'WITH_BF_COMPOSITOR', 'WITH_BF_COMPOSITOR_LEGACY', - 'WITH_BF_JPEG', 'BF_JPEG', 'BF_JPEG_INC', 'BF_JPEG_LIB', 'BF_JPEG_LIBPATH', + 'WITH_BF_JPEG', 'BF_JPEG', 'BF_JPEG_INC', 'BF_JPEG_LIB', 'BF_JPEG_LIBPATH', 'WITH_BF_STATICJPEG', 'BF_JPEG_LIB_STATIC', 'WITH_BF_OPENJPEG', 'BF_OPENJPEG', 'BF_OPENJPEG_INC', 'BF_OPENJPEG_LIB', 'BF_OPENJPEG_LIBPATH', 'WITH_BF_REDCODE', 'BF_REDCODE', 'BF_REDCODE_INC', 'BF_REDCODE_LIB', 'BF_REDCODE_LIBPATH', - 'WITH_BF_PNG', 'BF_PNG', 'BF_PNG_INC', 'BF_PNG_LIB', 'BF_PNG_LIBPATH', + 'WITH_BF_PNG', 'BF_PNG', 'BF_PNG_INC', 'BF_PNG_LIB', 'BF_PNG_LIBPATH', 'WITH_BF_STATICPNG', 'BF_PNG_LIB_STATIC', 'WITH_BF_TIFF', 'BF_TIFF', 'BF_TIFF_INC', 'BF_TIFF_LIB', 'BF_TIFF_LIBPATH', 'WITH_BF_STATICTIFF', 'BF_TIFF_LIB_STATIC', 'WITH_BF_ZLIB', 'BF_ZLIB', 'BF_ZLIB_INC', 'BF_ZLIB_LIB', 'BF_ZLIB_LIBPATH', 'WITH_BF_STATICZLIB', 'BF_ZLIB_LIB_STATIC', 'WITH_BF_INTERNATIONAL', @@ -127,6 +127,7 @@ def validate_arguments(args, bc): 'WITH_BF_FFTW3', 'BF_FFTW3', 'BF_FFTW3_INC', 'BF_FFTW3_LIB', 'BF_FFTW3_LIBPATH', 'WITH_BF_STATICFFTW3', 'BF_FFTW3_LIB_STATIC', 'WITH_BF_STATICOPENGL', 'BF_OPENGL', 'BF_OPENGL_INC', 'BF_OPENGL_LIB', 'BF_OPENGL_LIBPATH', 'BF_OPENGL_LIB_STATIC', 'WITH_BF_COLLADA', 'BF_COLLADA', 'BF_COLLADA_INC', 'BF_COLLADA_LIB', 'BF_OPENCOLLADA', 'BF_OPENCOLLADA_INC', 'BF_OPENCOLLADA_LIB', 'BF_OPENCOLLADA_LIBPATH', 'BF_PCRE', 'BF_PCRE_LIB', 'BF_PCRE_LIBPATH', 'BF_EXPAT', 'BF_EXPAT_LIB', 'BF_EXPAT_LIBPATH', + 'WITH_BF_STATICOPENCOLLADA', 'BF_OPENCOLLADA_LIB_STATIC', 'WITH_BF_PLAYER', 'WITH_BF_NOBLENDER', 'WITH_BF_BINRELOC', @@ -137,7 +138,7 @@ def validate_arguments(args, bc): 'WITHOUT_BF_INSTALL', 'WITHOUT_BF_PYTHON_INSTALL', 'WITHOUT_BF_PYTHON_UNPACK', 'WITH_BF_PYTHON_INSTALL_NUMPY' 'WITHOUT_BF_OVERWRITE_INSTALL', - 'WITH_BF_OPENMP', 'BF_OPENMP', 'BF_OPENMP_LIBPATH', + 'WITH_BF_OPENMP', 'BF_OPENMP', 'BF_OPENMP_LIBPATH', 'WITH_BF_STATICOPENMP', 'BF_OPENMP_STATIC_STATIC', 'WITH_GHOST_COCOA', 'WITH_GHOST_SDL', 'WITH_GHOST_XDND', @@ -152,7 +153,6 @@ def validate_arguments(args, bc): 'WITH_BF_RAYOPTIMIZATION', 'BF_RAYOPTIMIZATION_SSE_FLAGS', 'WITH_BF_FLUID', - 'WITH_BF_DECIMATE', 'WITH_BF_BOOLEAN', 'WITH_BF_REMESH', 'WITH_BF_OCEANSIM', @@ -265,7 +265,6 @@ def read_opts(env, cfg, args): ('BF_PYTHON_ABI_FLAGS', 'Python ABI flags (suffix in library version: m, mu, etc)', ''), (BoolVariable('WITH_BF_FLUID', 'Build with Fluid simulation (Elbeem)', True)), - (BoolVariable('WITH_BF_DECIMATE', 'Build with decimate modifier', True)), (BoolVariable('WITH_BF_BOOLEAN', 'Build with boolean modifier', True)), (BoolVariable('WITH_BF_REMESH', 'Build with remesh modifier', True)), (BoolVariable('WITH_BF_OCEANSIM', 'Build with ocean simulation', False)), @@ -286,10 +285,12 @@ def read_opts(env, cfg, args): ('BF_SDL_LIBPATH', 'SDL library path', ''), (BoolVariable('WITH_BF_JACK', 'Enable jack support if true', True)), + (BoolVariable('WITH_BF_STATICJACK', 'Staticly link to jack', False)), ('BF_JACK', 'jack base path', ''), ('BF_JACK_INC', 'jack include path', ''), ('BF_JACK_LIB', 'jack library', ''), ('BF_JACK_LIBPATH', 'jack library path', ''), + ('BF_JACK_LIB_STATIC', 'jack static library', ''), (BoolVariable('WITH_BF_SNDFILE', 'Enable sndfile support if true', True)), ('BF_SNDFILE', 'sndfile base path', ''), @@ -337,10 +338,12 @@ def read_opts(env, cfg, args): ('BF_OGG_LIB', 'OGG library', ''), (BoolVariable('WITH_BF_JPEG', 'Use JPEG if true', True)), + (BoolVariable('WITH_BF_STATICJPEG', 'Staticly link to JPEG', False)), ('BF_JPEG', 'JPEG base path', ''), ('BF_JPEG_INC', 'JPEG include path', ''), ('BF_JPEG_LIB', 'JPEG library', ''), ('BF_JPEG_LIBPATH', 'JPEG library path', ''), + ('BF_JPEG_LIB_STATIC', 'JPEG static library', ''), (BoolVariable('WITH_BF_OPENJPEG', 'Use OPENJPEG if true', False)), ('BF_OPENJPEG', 'OPENJPEG base path', ''), @@ -355,10 +358,12 @@ def read_opts(env, cfg, args): ('BF_REDCODE_LIBPATH', 'REDCODE library path', ''), (BoolVariable('WITH_BF_PNG', 'Use PNG if true', True)), + (BoolVariable('WITH_BF_STATICPNG', 'Staticly link to PNG', False)), ('BF_PNG', 'PNG base path', ''), ('BF_PNG_INC', 'PNG include path', ''), ('BF_PNG_LIB', 'PNG library', ''), ('BF_PNG_LIBPATH', 'PNG library path', ''), + ('BF_PNG_LIB_STATIC', 'PNG static library', ''), (BoolVariable('WITH_BF_TIFF', 'Use TIFF if true', True)), (BoolVariable('WITH_BF_STATICTIFF', 'Staticly link to TIFF', False)), @@ -420,12 +425,14 @@ def read_opts(env, cfg, args): ('BF_FREETYPE_LIB_STATIC', 'Static Freetype library', ''), (BoolVariable('WITH_BF_OPENMP', 'Use OpenMP if true', False)), + (BoolVariable('WITH_BF_STATICOPENMP', 'Staticly link to OpenMP', False)), ('BF_OPENMP', 'Base path to OpenMP (used when cross-compiling with older versions of WinGW)', ''), ('BF_OPENMP_INC', 'Path to OpenMP includes (used when cross-compiling with older versions of WinGW)', ''), ('BF_OPENMP_LIBPATH', 'Path to OpenMP libraries (used when cross-compiling with older versions of WinGW)', ''), (BoolVariable('WITH_GHOST_COCOA', 'Use Cocoa-framework if true', False)), (BoolVariable('WITH_GHOST_SDL', 'Enable building blender against SDL for windowing rather then the native APIs', False)), (BoolVariable('USE_QTKIT', 'Use QTKIT if true', False)), + ('BF_OPENMP_LIB_STATIC', 'OpenMP static library', ''), (BoolVariable('WITH_BF_QUICKTIME', 'Use QuickTime if true', False)), ('BF_QUICKTIME', 'QuickTime base path', ''), @@ -450,6 +457,7 @@ def read_opts(env, cfg, args): ('BF_OPENGL_LINKFLAGS', 'OpenGL link flags', ''), (BoolVariable('WITH_BF_COLLADA', 'Build COLLADA import/export module if true', False)), + (BoolVariable('WITH_BF_STATICOPENCOLLADA', 'Staticly link to OpenCollada', False)), ('BF_COLLADA', 'COLLADA base path', ''), ('BF_COLLADA_INC', 'COLLADA include path', ''), ('BF_COLLADA_LIB', 'COLLADA library', ''), @@ -463,6 +471,7 @@ def read_opts(env, cfg, args): ('BF_EXPAT', 'Expat base path', ''), ('BF_EXPAT_LIB', 'Expat library', ''), ('BF_EXPAT_LIBPATH', 'Expat library path', ''), + ('BF_OPENCOLLADA_LIB_STATIC', 'OpenCollada static library', ''), (BoolVariable('WITH_BF_JEMALLOC', 'Use jemalloc if true', False)), (BoolVariable('WITH_BF_STATICJEMALLOC', 'Staticly link to jemalloc', False)), @@ -541,7 +550,9 @@ def read_opts(env, cfg, args): (BoolVariable('WITH_BF_LIBMV', 'Enable libmv structure from motion library', True)), (BoolVariable('WITH_BF_COMPOSITOR', 'Enable the tile based nodal compositor', True)), + ) # end of opts.AddOptions() + localopts.AddVariables( ('BF_X264_CONFIG', 'configuration flags for x264', ''), ('BF_XVIDCORE_CONFIG', 'configuration flags for xvidcore', ''), # (BoolVariable('WITH_BF_DOCS', 'Generate API documentation', False)), @@ -559,9 +570,7 @@ def read_opts(env, cfg, args): (BoolVariable('WITH_BF_CXX_GUARDEDALLOC', 'Enable GuardedAlloc for C++ memory allocation tracking.', False)), ('BUILDBOT_BRANCH', 'Buildbot branch name', ''), - ) # end of opts.AddOptions() - localopts.AddVariables( (BoolVariable('WITH_BF_CYCLES', 'Build with the Cycles engine', True)), (BoolVariable('WITH_BF_CYCLES_CUDA_BINARIES', 'Build with precompiled CUDA binaries', False)), (BoolVariable('WITH_BF_CYCLES_CUDA_THREADED_COMPILE', 'Build several render kernels at once (using BF_NUMJOBS)', False)), @@ -593,7 +602,7 @@ def read_opts(env, cfg, args): ('BF_BOOST_LIB_STATIC', 'Boost static library', ''), (BoolVariable('WITH_GHOST_XDND', 'Build with drag-n-drop support on Linux platforms using XDND protocol', True)), - (BoolVariable('WITH_BF_COMPOSITOR_LEGACY', 'Enable the legacy compositor', True)) + (BoolVariable('WITH_BF_COMPOSITOR_LEGACY', 'Enable the legacy compositor', False)) ) # end of opts.AddOptions() return localopts @@ -653,11 +662,16 @@ def buildslave(target=None, source=None, env=None): if platform == 'linux': import platform + if env['BF_INSTALLDIR'].find('glibc27') != -1: + glibc="glibc27" + elif env['BF_INSTALLDIR'].find('glibc211') != -1: + glibc="glibc211" + bitness = platform.architecture()[0] if bitness == '64bit': - platform = 'linux-glibc27-x86_64' + platform = 'linux-' + glibc + '-x86_64' elif bitness == '32bit': - platform = 'linux-glibc27-i686' + platform = 'linux-' + glibc + '-i686' if platform == 'darwin': platform = 'OSX-' + env['MACOSX_ARCHITECTURE'] diff --git a/doc/guides/interface_API.txt b/doc/guides/interface_API.txt index 5f601dd3ebc..5f0fbc85ff8 100644 --- a/doc/guides/interface_API.txt +++ b/doc/guides/interface_API.txt @@ -50,7 +50,7 @@ Contents - It works with only OpenGL calls, for the full 100%. This means that it has some quirks built-in to work with all OS's and OpenGL versions. Especially frontbuffer drawing is a continuous point of attention. Buttons can be drawn with any window matrix. However, - errors can still occor when buttons are created in windows with non-standard glViewports. + errors can still occur when buttons are created in windows with non-standard glViewports. - The code was written to replace the old 1.8 button system, but under high pressure. Quite some button methods from the old system were copied for that reason. @@ -95,7 +95,7 @@ blender/source/blender/src/toolbox.c (extra GUI elements built on top of this AP All GUI elements are collected in uiBlocks, which in turn are linked together in a list that's part of a Blender Area-window. - uiBlock *block= uiNewBlock(&curarea->uiblocks, "stuff", UI_EMBOSSX, UI_HELV, curarea->win); + uiBlock *block = uiNewBlock(&curarea->uiblocks, "stuff", UI_EMBOSSX, UI_HELV, curarea->win); The next code example makes a new block, and puts it in the list of blocks of the current active Area: @@ -221,7 +221,7 @@ void uiBlockSetButmFunc(uiBlock *block, void (*menufunc)(void *arg, int event), void uiAutoBlock(uiBlock *block, float minx, float miny, float sizex, float sizey, UI_BLOCK_ROWS) Sets the buttons in this block to automatically align, and fit within boundaries. - Internally it allows multiple collums or rows as well. Only 'row order' has been implemented. + Internally it allows multiple colums or rows as well. Only 'row order' has been implemented. The uiDefBut definitions don't need coordinates as input here, but instead: - first value (x1) to indicate row number - width and height values (if filled in) will be used to define a relative width/height. @@ -346,7 +346,7 @@ type: without returnvalues, the first item gets value 0 (incl. title!) Example: "Do something %t| turn left %2| turn right %1| nothing %0" -11. COL +11. COLOR A special button that only visualizes a RGB value In 'retval' you can put a code, which is used to identify for sliders if it needs redraws while using the sliders. Check button '5'. @@ -363,7 +363,7 @@ uiBut *uiDefIconBut(uiBlock *block, int type, int retval, int icon, float min, float max, float a1, float a2, char *tip) Same syntax and types available as previous uiDefBut, but now with an icon code - instead of a name. THe icons are numbered in resources.c + instead of a name. The icons are numbered in resources.c uiBut *uiDefIconTextButF(uiBlock *block, int type, int retval, int icon, char *str, short x1, short y1, short x2, short y2, float *poin, @@ -397,9 +397,9 @@ void uiDefBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, char *str, static uiBlock *info_file_importmenu(void *arg_unused) { uiBlock *block; - short yco= 0, xco = 20; + short yco = 0, xco = 20; - block= uiNewBlock(&curarea->uiblocks, "importmenu", UI_EMBOSSW, UI_HELV, G.curscreen->mainwin); + block = uiNewBlock(&curarea->uiblocks, "importmenu", UI_EMBOSSW, UI_HELV, G.curscreen->mainwin); uiBlockSetXOfs(block, -40); // offset to parent button /* flags are defines */ @@ -409,7 +409,7 @@ void uiDefBlockBut(uiBlock *block, uiBlockFuncFP func, void *arg, char *str, uiDefButS(block, TOG|BIT|2, 0, "Two Sided", xco, yco-=20, 75, 19, &U.vrmlflag, 0.0, 0.0, 0, 0, ""); uiBlockSetDirection(block, UI_RIGHT); - uiTextBoundsBlock(block, 50); // checks for fontsize + uiTextBoundsBlock(block, 50); /* checks for fontsize */ return block; } diff --git a/doc/manpage/blender.1 b/doc/manpage/blender.1 index c7a762f08c7..e7164fcb96b 100644 --- a/doc/manpage/blender.1 +++ b/doc/manpage/blender.1 @@ -1,4 +1,4 @@ -.TH "BLENDER" "1" "July 19, 2012" "Blender Blender 2\&.63 (sub 14)" +.TH "BLENDER" "1" "October 04, 2012" "Blender Blender 2\&.64 (sub 0)" .SH NAME blender \- a 3D modelling and rendering package @@ -15,7 +15,7 @@ Use Blender to create TV commercials, to make technical visualizations, business http://www.blender.org .SH OPTIONS -Blender 2.63 (sub 14) +Blender 2.64 (sub 0) Usage: blender [args ...] [file] [args ...] .br .SS "Render Options:" diff --git a/doc/python_api/examples/bpy.types.Operator.4.py b/doc/python_api/examples/bpy.types.Operator.4.py index 861496c6d18..885ed857842 100644 --- a/doc/python_api/examples/bpy.types.Operator.4.py +++ b/doc/python_api/examples/bpy.types.Operator.4.py @@ -26,8 +26,8 @@ class CustomDrawOperator(bpy.types.Operator): return {'FINISHED'} def invoke(self, context, event): - context.window_manager.fileselect_add(self) - return {'RUNNING_MODAL'} + wm = context.window_manager + return wm.invoke_props_dialog(self) def draw(self, context): layout = self.layout diff --git a/doc/python_api/examples/bpy.types.Operator.5.py b/doc/python_api/examples/bpy.types.Operator.5.py index e123768431b..4a0abcb62c3 100644 --- a/doc/python_api/examples/bpy.types.Operator.5.py +++ b/doc/python_api/examples/bpy.types.Operator.5.py @@ -40,15 +40,17 @@ class ModalOperator(bpy.types.Operator): elif event.type == 'LEFTMOUSE': # Confirm return {'FINISHED'} elif event.type in ('RIGHTMOUSE', 'ESC'): # Cancel + context.object.location.x = self.init_loc_x return {'CANCELLED'} return {'RUNNING_MODAL'} def invoke(self, context, event): + self.init_loc_x = context.object.location.x self.value = event.mouse_x self.execute(context) - print(context.window_manager.modal_handler_add(self)) + context.window_manager.modal_handler_add(self) return {'RUNNING_MODAL'} diff --git a/doc/python_api/rst/bge.constraints.rst b/doc/python_api/rst/bge.constraints.rst index 83f2a6b4950..7757e11d41f 100644 --- a/doc/python_api/rst/bge.constraints.rst +++ b/doc/python_api/rst/bge.constraints.rst @@ -78,6 +78,14 @@ Physics Constraints (bge.constraints) :return: a vehicle constraint object. :rtype: :class:`bge.types.KX_VehicleWrapper` + +.. function:: getCharacter(gameobj) + + :arg gameobj: The game object with the character physics. + :type gameobj: :class:`bge.types.KX_GameObject` + + :return: character wrapper + :rtype: :class:`bge.types.KX_CharacterWrapper` .. function:: removeConstraint(constraintId) diff --git a/doc/python_api/rst/bge.logic.rst b/doc/python_api/rst/bge.logic.rst index 0d1d0df88c3..260a86f7c59 100644 --- a/doc/python_api/rst/bge.logic.rst +++ b/doc/python_api/rst/bge.logic.rst @@ -2,9 +2,9 @@ Game Logic (bge.logic) ====================== -***** -Intro -***** +************ +Introduction +************ Module to access logic functions, imported automatically into the python controllers namespace. diff --git a/doc/python_api/rst/bge.texture.rst b/doc/python_api/rst/bge.texture.rst index 07d83f66bd4..0c9e9da0661 100644 --- a/doc/python_api/rst/bge.texture.rst +++ b/doc/python_api/rst/bge.texture.rst @@ -351,6 +351,15 @@ When the texture object is deleted, the new texture is deleted and the old textu use whole viewport to render + .. attribute:: depth + + use depth component of render as array of float - not suitable for texture source, + should only be used with bge.texture.imageToArray(mode='F') + + .. attribute:: zbuff + + use depth component of render as grey scale color - suitable for texture source + .. class:: ImageViewport() Image source from viewport @@ -399,6 +408,15 @@ When the texture object is deleted, the new texture is deleted and the old textu use whole viewport to capture + .. attribute:: depth + + use depth component of viewport as array of float - not suitable for texture source, + should only be used with bge.texture.imageToArray(mode='F') + + .. attribute:: zbuff + + use depth component of viewport as grey scale color - suitable for texture source + .. class:: Texture(gameObj) Texture objects @@ -518,13 +536,16 @@ When the texture object is deleted, the new texture is deleted and the old textu 0 to force a fixed 0 color channel and 1 to force a fixed 255 color channel. Example: "BGR" will return 3 bytes per pixel with the Blue, Green and Red channels in that order. "RGB1" will return 4 bytes per pixel with the Red, Green, Blue channels in that order and the alpha channel forced to 255. + A special mode "F" allows to return the image as an array of float. This mode should only be used to retrieve + the depth buffer of the ImageViewport and ImageRender object. The default mode is "RGBA". + :type mode: string :rtype: :class:`~bgl.buffer` :return: A object representing the image as one dimensional array of bytes of size (pixel_size*width*height), line by line starting from the bottom of the image. The pixel size and format is determined by the mode - parameter. + parameter. For mode 'F', the array is a one dimensional array of float of size (width*height). .. function:: materialID(object,name) diff --git a/doc/python_api/rst/bge.types.rst b/doc/python_api/rst/bge.types.rst index 31ae45b9bf0..fdaeb61173f 100644 --- a/doc/python_api/rst/bge.types.rst +++ b/doc/python_api/rst/bge.types.rst @@ -4,6 +4,33 @@ Game Types (bge.types) .. module:: bge.types +************ +Introduction +************ + +This module contains the classes that appear as instances in the Game Engine. A +script must interact with these classes if it is to affect the behaviour of +objects in a game. + +The following example would move an object (i.e. an instance of +:class:`KX_GameObject`) one unit up. + +.. code-block:: python + + # bge.types.SCA_PythonController + cont = bge.logic.getCurrentController() + + # bge.types.KX_GameObject + obj = cont.owner + obj.worldPosition.z += 1 + +To run the code, it could be placed in a Blender text block and executed with +a :class:`SCA_PythonController` logic brick. + +***** +Types +***** + .. class:: PyObjectPlus PyObjectPlus base class of most other types in the Game Engine. @@ -306,7 +333,8 @@ Game Types (bge.types) .. attribute:: useContinue - The actions continue option, True or False. When True, the action will always play from where last left off, otherwise negative events to this actuator will reset it to its start frame. + The actions continue option, True or False. When True, the action will always play from where last left off, + otherwise negative events to this actuator will reset it to its start frame. :type: boolean @@ -852,7 +880,54 @@ Game Types (bge.types) .. note:: - Calling ANY method or attribute on an object that has been removed from a scene will raise a SystemError, if an object may have been removed since last accessing it use the :data:`invalid` attribute to check. + Calling ANY method or attribute on an object that has been removed from a scene will raise a SystemError, + if an object may have been removed since last accessing it use the :data:`invalid` attribute to check. + + KX_GameObject can be subclassed to extend functionality. For example: + + .. code-block:: python + + import bge + + class CustomGameObject(bge.types.KX_GameObject): + RATE = 0.05 + + def __init__(self, old_owner): + # "old_owner" can just be ignored. At this point, "self" is + # already the object in the scene, and "old_owner" has been + # destroyed. + + # New attributes can be defined - but we could also use a game + # property, like "self['rate']". + self.rate = CustomGameObject.RATE + + def update(self): + self.worldPosition.z += self.rate + + # switch direction + if self.worldPosition.z > 1.0: + self.rate = -CustomGameObject.RATE + elif self.worldPosition.z < 0.0: + self.rate = CustomGameObject.RATE + + # Called first + def mutate(cont): + old_object = cont.owner + mutated_object = CustomGameObject(cont.owner) + + # After calling the constructor above, references to the old object + # should not be used. + assert(old_object is not mutated_object) + assert(old_object.invalid) + assert(mutated_object is cont.owner) + + # Called later - note we are now working with the mutated object. + def update(cont): + cont.owner.update() + + When subclassing objects other than empties and meshes, the specific type + should be used - e.g. inherit from :class:`BL_ArmatureObject` when the object + to mutate is an armature. .. attribute:: name @@ -913,6 +988,24 @@ Game Types (bge.types) The object's parent object. (read-only). :type: :class:`KX_GameObject` or None + + .. attribute:: group_children + + Returns the list of group members if the object is a group object, otherwise None is returned. + + :type: :class:`CListValue` of :class:`KX_GameObject` or None + + .. attribute:: group_parent + + Returns the group object that the object belongs to or None if the object is not part of a group. + + :type: :class:`KX_GameObject` or None + + .. attribute:: scene + + The object's scene. (read-only). + + :type: :class:`KX_Scene` or None .. attribute:: visible @@ -3371,6 +3464,26 @@ Game Types (bge.types) :arg wheelIndex: the wheel index :type wheelIndex: integer +.. class:: KX_CharacterWrapper(PyObjectPlus) + + A wrapper to expose character physics options. + + .. attribute:: onGround + + Whether or not the character is on the ground. (read-only) + + :type: boolean + + .. attribute:: gravity + + The gravity value used for the character. + + :type: float + + .. method:: jump() + + The character jumps based on it's jump speed. + .. class:: KX_VertexProxy(SCA_IObject) A vertex holds position, UV, color and normal information. @@ -4473,7 +4586,9 @@ Game Types (bge.types) .. data:: KX_ACT_ARMATURE_RUN - Just make sure the armature will be updated on the next graphic frame. This is the only persistent mode of the actuator: it executes automatically once per frame until stopped by a controller + Just make sure the armature will be updated on the next graphic frame. + This is the only persistent mode of the actuator: + it executes automatically once per frame until stopped by a controller :value: 0 diff --git a/doc/python_api/rst/change_log.rst b/doc/python_api/rst/change_log.rst index 4d8f9a5171e..c1f3c2e4267 100644 --- a/doc/python_api/rst/change_log.rst +++ b/doc/python_api/rst/change_log.rst @@ -2397,3 +2397,1502 @@ Removed * **ffmpeg_packetsize** * **ffmpeg_video_bitrate** +2.62 to 2.63 +============ + +bpy.types.ThemeView3D +--------------------- + +Added +^^^^^ + +* :class:`bpy.types.ThemeView3D.camera` +* :class:`bpy.types.ThemeView3D.empty` + +bpy.types.KeyingSet +------------------- + +Added +^^^^^ + +* :class:`bpy.types.KeyingSet.bl_description` +* :class:`bpy.types.KeyingSet.bl_idname` + +Renamed +^^^^^^^ + +* **name** -> :class:`bpy.types.KeyingSet.bl_label` + +bpy.types.BlendDataScenes +------------------------- + +Added +^^^^^ + +* :class:`bpy.types.BlendDataScenes.tag` + +bpy.types.RenderEngine +---------------------- + +Added +^^^^^ + +* :class:`bpy.types.RenderEngine.camera_override` + +bpy.types.BackgroundImage +------------------------- + +Added +^^^^^ + +* :class:`bpy.types.BackgroundImage.show_on_foreground` + +bpy.types.CyclesRenderSettings +------------------------------ + +Added +^^^^^ + +* :class:`bpy.types.CyclesRenderSettings.preview_active_layer` +* :class:`bpy.types.CyclesRenderSettings.sample_clamp` + +bpy.types.ToolSettings +---------------------- + +Added +^^^^^ + +* :class:`bpy.types.ToolSettings.double_threshold` + +bpy.types.Image +--------------- + +Added +^^^^^ + +* :class:`bpy.types.Image.render_slot` + +bpy.types.MovieTrackingStabilization +------------------------------------ + +Added +^^^^^ + +* :class:`bpy.types.MovieTrackingStabilization.filter_type` + +bpy.types.DomainFluidSettings +----------------------------- + +Removed +^^^^^^^ + +* **viscosity_preset** + +bpy.types.ParticleSettings +-------------------------- + +Added +^^^^^ + +* :class:`bpy.types.ParticleSettings.use_rotations` + +bpy.types.SceneGameData +----------------------- + +Renamed +^^^^^^^ + +* **dome_tesselation** -> :class:`bpy.types.SceneGameData.dome_tessellation` + +bpy.types.RegionView3D +---------------------- + +Added +^^^^^ + +* :class:`bpy.types.RegionView3D.update` + +bpy.types.Scene +--------------- + +Added +^^^^^ + +* :class:`bpy.types.Scene.active_layer` + +bpy.types.ShaderNodeTexEnvironment +---------------------------------- + +Added +^^^^^ + +* :class:`bpy.types.ShaderNodeTexEnvironment.projection` + +bpy.types.UserPreferencesEdit +----------------------------- + +Added +^^^^^ + +* :class:`bpy.types.UserPreferencesEdit.fcurve_unselected_alpha` + +bpy.types.MeshTextureFace +------------------------- + +Removed +^^^^^^^ + +* **pin_uv** +* **select_uv** + +bpy.types.Menu +-------------- + +Function Arguments +^^^^^^^^^^^^^^^^^^ + +* :class:`bpy.types.Menu.path_menu` (self, searchpaths, operator, props_default, filter_ext), *was (self, searchpaths, operator, props_default)* + +bpy.types.CompositorNodeDistanceMatte +------------------------------------- + +Added +^^^^^ + +* :class:`bpy.types.CompositorNodeDistanceMatte.channel` + +bpy.types.KeyingSetInfo +----------------------- + +Added +^^^^^ + +* :class:`bpy.types.KeyingSetInfo.bl_description` + +bpy.types.KeyingSets +-------------------- + +Function Arguments +^^^^^^^^^^^^^^^^^^ + +* :class:`bpy.types.KeyingSets.new` (idname, name), *was (name)* + +bpy.types.CompositorNodeOutputFile +---------------------------------- + +Added +^^^^^ + +* :class:`bpy.types.CompositorNodeOutputFile.active_input` +* :class:`bpy.types.CompositorNodeOutputFile.active_input_index` +* :class:`bpy.types.CompositorNodeOutputFile.base_path` + +Removed +^^^^^^^ + +* **filepath** +* **frame_end** +* **frame_start** + +Renamed +^^^^^^^ + +* **image_settings** -> :class:`bpy.types.CompositorNodeOutputFile.format` + +bpy.types.CyclesCameraSettings +------------------------------ + +Added +^^^^^ + +* :class:`bpy.types.CyclesCameraSettings.aperture_fstop` +* :class:`bpy.types.CyclesCameraSettings.aperture_type` + +bpy.types.Struct +---------------- + +Added +^^^^^ + +* :class:`bpy.types.Struct.translation_context` + +bpy.types.ThemeSequenceEditor +----------------------------- + +Added +^^^^^ + +* :class:`bpy.types.ThemeSequenceEditor.movieclip_strip` +* :class:`bpy.types.ThemeSequenceEditor.preview_back` + +bpy.types.TexMapping +-------------------- + +Renamed +^^^^^^^ + +* **location** -> :class:`bpy.types.TexMapping.translation` + +bpy.types.ArmatureActuator +-------------------------- + +Added +^^^^^ + +* :class:`bpy.types.ArmatureActuator.influence` + +bpy.types.ThemeTextEditor +------------------------- + +Removed +^^^^^^^ + +* **scroll_bar** + +bpy.types.ThemeUserInterface +---------------------------- + +Added +^^^^^ + +* :class:`bpy.types.ThemeUserInterface.wcol_tooltip` + +bpy.types.MeshEdge +------------------ + +Removed +^^^^^^^ + +* **is_fgon** + +bpy.types.Brush +--------------- + +Added +^^^^^ + +* :class:`bpy.types.Brush.sculpt_capabilities` + +Renamed +^^^^^^^ + +* **use_space_atten** -> :class:`bpy.types.Brush.use_space_attenuation` + +bpy.types.ShaderNodeMapping +--------------------------- + +Renamed +^^^^^^^ + +* **location** -> :class:`bpy.types.ShaderNodeMapping.translation` + +bpy.types.Mesh +-------------- + +Added +^^^^^ + +* :class:`bpy.types.Mesh.auto_texspace` +* :class:`bpy.types.Mesh.calc_tessface` +* :class:`bpy.types.Mesh.loops` +* :class:`bpy.types.Mesh.polygons` +* :class:`bpy.types.Mesh.tessface_uv_textures` +* :class:`bpy.types.Mesh.tessface_vertex_colors` +* :class:`bpy.types.Mesh.tessfaces` +* :class:`bpy.types.Mesh.unit_test_compare` +* :class:`bpy.types.Mesh.uv_layer_clone` +* :class:`bpy.types.Mesh.uv_layer_clone_index` +* :class:`bpy.types.Mesh.uv_layer_stencil` +* :class:`bpy.types.Mesh.uv_layer_stencil_index` +* :class:`bpy.types.Mesh.uv_layers` + +Removed +^^^^^^^ + +* **faces** +* **layers_float** +* **layers_string** + +Renamed +^^^^^^^ + +* **layers_int** -> :class:`bpy.types.Mesh.polygon_layers_float` +* **layers_int** -> :class:`bpy.types.Mesh.polygon_layers_int` +* **layers_int** -> :class:`bpy.types.Mesh.polygon_layers_string` + +Function Arguments +^^^^^^^^^^^^^^^^^^ + +* :class:`bpy.types.Mesh.update` (calc_edges, calc_tessface), *was (calc_edges)* + +bpy.types.Key +------------- + +Added +^^^^^ + +* :class:`bpy.types.Key.eval_time` + +bpy.types.LatticeModifier +------------------------- + +Added +^^^^^ + +* :class:`bpy.types.LatticeModifier.strength` + +bpy.types.UserPreferencesView +----------------------------- + +Added +^^^^^ + +* :class:`bpy.types.UserPreferencesView.quit_dialog` + + +2.63 to 2.64 +============ + +bpy.types.CyclesLampSettings +---------------------------- + +Added +^^^^^ + +* :class:`bpy.types.CyclesLampSettings.samples` + +bpy.types.Histogram +------------------- + +Added +^^^^^ + +* :class:`bpy.types.Histogram.show_line` + +bpy.types.ThemeView3D +--------------------- + +Added +^^^^^ + +* :class:`bpy.types.ThemeView3D.bone_pose_active` +* :class:`bpy.types.ThemeView3D.skin_root` + +bpy.types.GameObjectSettings +---------------------------- + +Added +^^^^^ + +* :class:`bpy.types.GameObjectSettings.fall_speed` +* :class:`bpy.types.GameObjectSettings.jump_speed` +* :class:`bpy.types.GameObjectSettings.step_height` + + +bpy.types.BlendData +------------------- + +Added +^^^^^ + +* :class:`bpy.types.BlendData.masks` + + +bpy.types.TextureNodeMixRGB +--------------------------- + +Added +^^^^^ + +* :class:`bpy.types.TextureNodeMixRGB.use_clamp` + +bpy.types.SmokeCollSettings +--------------------------- + +Added +^^^^^ + +* :class:`bpy.types.SmokeCollSettings.collision_type` + +bpy.types.CompositorNodes +------------------------- + +Added +^^^^^ + +* :class:`bpy.types.CompositorNodes.active` + +bpy.types.RenderEngine +---------------------- + +Added +^^^^^ + +* :class:`bpy.types.RenderEngine.resolution_x` +* :class:`bpy.types.RenderEngine.resolution_y` +* :class:`bpy.types.RenderEngine.tile_x` +* :class:`bpy.types.RenderEngine.tile_y` + +Function Arguments +^^^^^^^^^^^^^^^^^^ + +* :class:`bpy.types.RenderEngine.begin_result` (x, y, w, h, layer), *was (x, y, w, h)* +* :class:`bpy.types.RenderEngine.end_result` (result, cancel), *was (result)* + +bpy.types.BackgroundImage +------------------------- + +Added +^^^^^ + +* :class:`bpy.types.BackgroundImage.draw_depth` +* :class:`bpy.types.BackgroundImage.frame_method` + +bpy.types.SmokeDomainSettings +----------------------------- + +Added +^^^^^ + +* :class:`bpy.types.SmokeDomainSettings.cell_size` +* :class:`bpy.types.SmokeDomainSettings.density` +* :class:`bpy.types.SmokeDomainSettings.domain_resolution` +* :class:`bpy.types.SmokeDomainSettings.scale` +* :class:`bpy.types.SmokeDomainSettings.start_point` + +bpy.types.CyclesRenderSettings +------------------------------ + +Added +^^^^^ + +* :class:`bpy.types.CyclesRenderSettings.aa_samples` +* :class:`bpy.types.CyclesRenderSettings.ao_samples` +* :class:`bpy.types.CyclesRenderSettings.blur_glossy` +* :class:`bpy.types.CyclesRenderSettings.diffuse_samples` +* :class:`bpy.types.CyclesRenderSettings.glossy_samples` +* :class:`bpy.types.CyclesRenderSettings.mesh_light_samples` +* :class:`bpy.types.CyclesRenderSettings.preview_aa_samples` +* :class:`bpy.types.CyclesRenderSettings.preview_start_resolution` +* :class:`bpy.types.CyclesRenderSettings.progressive` +* :class:`bpy.types.CyclesRenderSettings.transmission_samples` + +Removed +^^^^^^^ + +* **blur_caustics** +* **debug_min_size** + +bpy.types.ActionGroup +--------------------- + +Added +^^^^^ + +* :class:`bpy.types.ActionGroup.color_set` +* :class:`bpy.types.ActionGroup.colors` + +Removed +^^^^^^^ + +* **custom_color** + +bpy.types.WipeSequence +---------------------- + +Added +^^^^^ + +* :class:`bpy.types.WipeSequence.input_1` +* :class:`bpy.types.WipeSequence.input_count` + +bpy.types.ToolSettings +---------------------- + +Added +^^^^^ + +* :class:`bpy.types.ToolSettings.snap_node_element` +* :class:`bpy.types.ToolSettings.use_proportional_edit_mask` + +bpy.types.ThemeClipEditor +------------------------- + +Added +^^^^^ + +* :class:`bpy.types.ThemeClipEditor.space_list` +* :class:`bpy.types.ThemeClipEditor.strips` +* :class:`bpy.types.ThemeClipEditor.strips_selected` + +bpy.types.Image +--------------- + +Added +^^^^^ + +* :class:`bpy.types.Image.colorspace_settings` +* :class:`bpy.types.Image.frame_duration` +* :class:`bpy.types.Image.gl_touch` +* :class:`bpy.types.Image.scale` +* :class:`bpy.types.Image.view_as_render` + + +bpy.types.ThemeDopeSheet +------------------------ + +Added +^^^^^ + +* :class:`bpy.types.ThemeDopeSheet.summary` + +bpy.types.MovieClipUser +----------------------- + +Renamed +^^^^^^^ + +* **current_frame** -> :class:`bpy.types.MovieClipUser.frame_current` + +bpy.types.TransformSequence +--------------------------- + +Added +^^^^^ + +* :class:`bpy.types.TransformSequence.input_1` +* :class:`bpy.types.TransformSequence.input_count` + +bpy.types.ImageSequence +----------------------- + +Removed +^^^^^^^ + +* **color_balance** +* **use_color_balance** + +bpy.types.DupliObject +--------------------- + +Added +^^^^^ + +* :class:`bpy.types.DupliObject.index` +* :class:`bpy.types.DupliObject.particle_index` + +bpy.types.RenderSettings +------------------------ + +Removed +^^^^^^^ + +* **use_color_management** +* **use_radiosity** + +bpy.types.Curve +--------------- + +Added +^^^^^ + +* :class:`bpy.types.Curve.bevel_factor_end` +* :class:`bpy.types.Curve.bevel_factor_start` + +bpy.types.MovieClip +------------------- + +Added +^^^^^ + +* :class:`bpy.types.MovieClip.colorspace_settings` +* :class:`bpy.types.MovieClip.frame_duration` +* :class:`bpy.types.MovieClip.frame_offset` +* :class:`bpy.types.MovieClip.frame_start` + +bpy.types.CompositorNodeTree +---------------------------- + +Added +^^^^^ + +* :class:`bpy.types.CompositorNodeTree.chunk_size` +* :class:`bpy.types.CompositorNodeTree.edit_quality` +* :class:`bpy.types.CompositorNodeTree.render_quality` +* :class:`bpy.types.CompositorNodeTree.two_pass` +* :class:`bpy.types.CompositorNodeTree.use_opencl` + +bpy.types.SpaceUVEditor +----------------------- + +Removed +^^^^^^^ + +* **cursor_location** +* **pivot_point** + +bpy.types.RemeshModifier +------------------------ + +Added +^^^^^ + +* :class:`bpy.types.RemeshModifier.use_smooth_shade` + +bpy.types.CurveMapping +---------------------- + +Added +^^^^^ + +* :class:`bpy.types.CurveMapping.update` + +bpy.types.CompositorNodeMixRGB +------------------------------ + +Added +^^^^^ + +* :class:`bpy.types.CompositorNodeMixRGB.use_clamp` + +bpy.types.ParticleSettings +-------------------------- + +Added +^^^^^ + +* :class:`bpy.types.ParticleSettings.use_scale_dupli` + +bpy.types.SceneGameData +----------------------- + +Added +^^^^^ + +* :class:`bpy.types.SceneGameData.deactivation_angular_threshold` +* :class:`bpy.types.SceneGameData.deactivation_linear_threshold` +* :class:`bpy.types.SceneGameData.deactivation_time` + +bpy.types.SoundSequence +----------------------- + +Added +^^^^^ + +* :class:`bpy.types.SoundSequence.show_waveform` + +bpy.types.Scene +--------------- + +Added +^^^^^ + +* :class:`bpy.types.Scene.display_settings` +* :class:`bpy.types.Scene.sequence_editor_clear` +* :class:`bpy.types.Scene.sequence_editor_create` +* :class:`bpy.types.Scene.sequencer_colorspace_settings` +* :class:`bpy.types.Scene.view_settings` + +Removed +^^^^^^^ + +* **collada_export** + +bpy.types.Armature +------------------ + +Removed +^^^^^^^ + +* **use_deform_envelopes** +* **use_deform_preserve_volume** +* **use_deform_vertex_groups** + +bpy.types.MeshUVLoopLayer +------------------------- + +Added +^^^^^ + +* :class:`bpy.types.MeshUVLoopLayer.name` + +bpy.types.CurveMap +------------------ + +Added +^^^^^ + +* :class:`bpy.types.CurveMap.evaluate` + +bpy.types.ShaderNodeTexEnvironment +---------------------------------- + +Added +^^^^^ + +* :class:`bpy.types.ShaderNodeTexEnvironment.image_user` + +bpy.types.SolidifyModifier +-------------------------- + +Added +^^^^^ + +* :class:`bpy.types.SolidifyModifier.use_flip_normals` + +bpy.types.TextureNodeMath +------------------------- + +Added +^^^^^ + +* :class:`bpy.types.TextureNodeMath.use_clamp` + +bpy.types.SceneRenderLayer +-------------------------- + +Added +^^^^^ + +* :class:`bpy.types.SceneRenderLayer.layers_exclude` +* :class:`bpy.types.SceneRenderLayer.samples` + +bpy.types.CompositorNodeViewer +------------------------------ + +Added +^^^^^ + +* :class:`bpy.types.CompositorNodeViewer.center_x` +* :class:`bpy.types.CompositorNodeViewer.center_y` +* :class:`bpy.types.CompositorNodeViewer.tile_order` + +bpy.types.ClothCollisionSettings +-------------------------------- + +Added +^^^^^ + +* :class:`bpy.types.ClothCollisionSettings.vertex_group_self_collisions` + +bpy.types.SpeedControlSequence +------------------------------ + +Added +^^^^^ + +* :class:`bpy.types.SpeedControlSequence.input_1` +* :class:`bpy.types.SpeedControlSequence.input_count` + +bpy.types.ActionConstraint +-------------------------- + +Added +^^^^^ + +* :class:`bpy.types.ActionConstraint.use_bone_object_action` + +bpy.types.CompositorNodeScale +----------------------------- + +Added +^^^^^ + +* :class:`bpy.types.CompositorNodeScale.frame_method` +* :class:`bpy.types.CompositorNodeScale.offset_x` +* :class:`bpy.types.CompositorNodeScale.offset_y` + +bpy.types.SpaceDopeSheetEditor +------------------------------ + +Added +^^^^^ + +* :class:`bpy.types.SpaceDopeSheetEditor.show_group_colors` + +bpy.types.MetaSequence +---------------------- + +Removed +^^^^^^^ + +* **color_balance** +* **use_color_balance** + +bpy.types.ShaderNodeMixRGB +-------------------------- + +Added +^^^^^ + +* :class:`bpy.types.ShaderNodeMixRGB.use_clamp` + +bpy.types.FollowTrackConstraint +------------------------------- + +Added +^^^^^ + +* :class:`bpy.types.FollowTrackConstraint.frame_method` + +bpy.types.EffectSequence +------------------------ + +Removed +^^^^^^^ + +* **color_balance** +* **use_color_balance** + +bpy.types.ThemeNLAEditor +------------------------ + +Added +^^^^^ + +* :class:`bpy.types.ThemeNLAEditor.active_action` +* :class:`bpy.types.ThemeNLAEditor.active_action_unset` +* :class:`bpy.types.ThemeNLAEditor.meta_strips` +* :class:`bpy.types.ThemeNLAEditor.meta_strips_selected` +* :class:`bpy.types.ThemeNLAEditor.sound_strips` +* :class:`bpy.types.ThemeNLAEditor.sound_strips_selected` +* :class:`bpy.types.ThemeNLAEditor.transition_strips` +* :class:`bpy.types.ThemeNLAEditor.transition_strips_selected` +* :class:`bpy.types.ThemeNLAEditor.tweak` +* :class:`bpy.types.ThemeNLAEditor.tweak_duplicate` + +Removed +^^^^^^^ + +* **bars** +* **bars_selected** + +bpy.types.SculptCapabilities +---------------------------- + +Added +^^^^^ + +* :class:`bpy.types.SculptCapabilities.has_overlay` +* :class:`bpy.types.SculptCapabilities.has_texture_angle` +* :class:`bpy.types.SculptCapabilities.has_texture_angle_source` + +bpy.types.ImageFormatSettings +----------------------------- + +Added +^^^^^ + +* :class:`bpy.types.ImageFormatSettings.display_settings` +* :class:`bpy.types.ImageFormatSettings.view_settings` + + +bpy.types.Property +------------------ + +Added +^^^^^ + +* :class:`bpy.types.Property.is_library_editable` + +bpy.types.MovieTrackingTrack +---------------------------- + +Added +^^^^^ + +* :class:`bpy.types.MovieTrackingTrack.grease_pencil` +* :class:`bpy.types.MovieTrackingTrack.motion_model` +* :class:`bpy.types.MovieTrackingTrack.use_alpha_preview` +* :class:`bpy.types.MovieTrackingTrack.use_brute` +* :class:`bpy.types.MovieTrackingTrack.use_mask` +* :class:`bpy.types.MovieTrackingTrack.use_normalization` + +Removed +^^^^^^^ + +* **pattern_max** +* **pattern_min** +* **pyramid_levels** +* **search_max** +* **search_min** +* **tracker** + +bpy.types.CompositorNodeBlur +---------------------------- + +Added +^^^^^ + +* :class:`bpy.types.CompositorNodeBlur.use_variable_size` + +bpy.types.Object +---------------- + +Added +^^^^^ + +* :class:`bpy.types.Object.dm_info` +* :class:`bpy.types.Object.is_deform_modified` +* :class:`bpy.types.Object.layers_local_view` + +Renamed +^^^^^^^ + +* **animation_visualisation** -> :class:`bpy.types.Object.animation_visualization` + +bpy.types.UserPreferencesSystem +------------------------------- + +Added +^^^^^ + +* :class:`bpy.types.UserPreferencesSystem.use_gpu_mipmap` + +Removed +^^^^^^^ + +* **compute_device** +* **compute_device_type** + +bpy.types.Sequence +------------------ + +Added +^^^^^ + +* :class:`bpy.types.Sequence.modifiers` +* :class:`bpy.types.Sequence.use_linear_modifiers` + +Removed +^^^^^^^ + +* **input_1** +* **input_2** +* **input_3** +* **input_count** +* **waveform** + +bpy.types.ConsoleLine +--------------------- + +Added +^^^^^ + +* :class:`bpy.types.ConsoleLine.type` + +bpy.types.Region +---------------- + +Added +^^^^^ + +* :class:`bpy.types.Region.view2d` +* :class:`bpy.types.Region.x` +* :class:`bpy.types.Region.y` + +bpy.types.SpaceClipEditor +------------------------- + +Added +^^^^^ + +* :class:`bpy.types.SpaceClipEditor.grease_pencil_source` +* :class:`bpy.types.SpaceClipEditor.mask` +* :class:`bpy.types.SpaceClipEditor.mask_draw_type` +* :class:`bpy.types.SpaceClipEditor.pivot_point` +* :class:`bpy.types.SpaceClipEditor.show_graph_hidden` +* :class:`bpy.types.SpaceClipEditor.show_graph_only_selected` +* :class:`bpy.types.SpaceClipEditor.show_mask_smooth` +* :class:`bpy.types.SpaceClipEditor.show_seconds` + +bpy.types.NodeSocket +-------------------- + +Added +^^^^^ + +* :class:`bpy.types.NodeSocket.hide` +* :class:`bpy.types.NodeSocket.is_linked` + +bpy.types.MovieClipSequence +--------------------------- + +Removed +^^^^^^^ + +* **color_balance** +* **use_color_balance** + +bpy.types.Node +-------------- + +Added +^^^^^ + +* :class:`bpy.types.Node.color` +* :class:`bpy.types.Node.hide` +* :class:`bpy.types.Node.mute` +* :class:`bpy.types.Node.select` +* :class:`bpy.types.Node.show_options` +* :class:`bpy.types.Node.show_preview` +* :class:`bpy.types.Node.use_custom_color` + +bpy.types.SceneSequence +----------------------- + +Removed +^^^^^^^ + +* **color_balance** +* **use_color_balance** + +bpy.types.CompositorNodeOutputFile +---------------------------------- + +Added +^^^^^ + +* :class:`bpy.types.CompositorNodeOutputFile.file_slots` +* :class:`bpy.types.CompositorNodeOutputFile.layer_slots` + +Removed +^^^^^^^ + +* **active_input** + +bpy.types.ObjectBase +-------------------- + +Added +^^^^^ + +* :class:`bpy.types.ObjectBase.layers_local_view` + +bpy.types.CyclesCameraSettings +------------------------------ + +Added +^^^^^ + +* :class:`bpy.types.CyclesCameraSettings.fisheye_fov` +* :class:`bpy.types.CyclesCameraSettings.fisheye_lens` +* :class:`bpy.types.CyclesCameraSettings.panorama_type` + +bpy.types.CompositorNodeDefocus +------------------------------- + +Removed +^^^^^^^ + +* **samples** + +bpy.types.KeyMapItems +--------------------- + +Function Arguments +^^^^^^^^^^^^^^^^^^ + +* :class:`bpy.types.KeyMapItems.new` (idname, type, value, any, shift, ctrl, alt, oskey, key_modifier, head), *was (idname, type, value, any, shift, ctrl, alt, oskey, key_modifier)* + +bpy.types.CollisionSettings +--------------------------- + +Added +^^^^^ + +* :class:`bpy.types.CollisionSettings.stickiness` + +Removed +^^^^^^^ + +* **stickness** + +bpy.types.GlowSequence +---------------------- + +Added +^^^^^ + +* :class:`bpy.types.GlowSequence.input_1` +* :class:`bpy.types.GlowSequence.input_count` + +bpy.types.MouseSensor +--------------------- + +Added +^^^^^ + +* :class:`bpy.types.MouseSensor.use_pulse` + +bpy.types.MovieSequence +----------------------- + +Removed +^^^^^^^ + +* **color_balance** +* **use_color_balance** + +bpy.types.Pose +-------------- + +Renamed +^^^^^^^ + +* **animation_visualisation** -> :class:`bpy.types.Pose.animation_visualization` + +bpy.types.ThemeSequenceEditor +----------------------------- + +Removed +^^^^^^^ + +* **plugin_strip** + +bpy.types.IMAGE_UV_sculpt +------------------------- + +Added +^^^^^ + +* :class:`bpy.types.IMAGE_UV_sculpt.prop_unified_weight` + +bpy.types.SpaceImageEditor +-------------------------- + +Added +^^^^^ + +* :class:`bpy.types.SpaceImageEditor.cursor_location` +* :class:`bpy.types.SpaceImageEditor.mask` +* :class:`bpy.types.SpaceImageEditor.mask_draw_type` +* :class:`bpy.types.SpaceImageEditor.mode` +* :class:`bpy.types.SpaceImageEditor.pivot_point` +* :class:`bpy.types.SpaceImageEditor.show_mask_smooth` +* :class:`bpy.types.SpaceImageEditor.show_maskedit` + +Removed +^^^^^^^ + +* **curve** +* **use_grease_pencil** +* **use_image_paint** + +bpy.types.UserPreferencesFilePaths +---------------------------------- + +Added +^^^^^ + +* :class:`bpy.types.UserPreferencesFilePaths.i18n_branches_directory` + +Removed +^^^^^^^ + +* **sequence_plugin_directory** +* **texture_plugin_directory** + +bpy.types.CompositorNodeDilateErode +----------------------------------- + +Added +^^^^^ + +* :class:`bpy.types.CompositorNodeDilateErode.edge` +* :class:`bpy.types.CompositorNodeDilateErode.falloff` +* :class:`bpy.types.CompositorNodeDilateErode.type` + +bpy.types.ScrewModifier +----------------------- + +Added +^^^^^ + +* :class:`bpy.types.ScrewModifier.use_smooth_shade` + +bpy.types.SpaceNodeEditor +------------------------- + +Added +^^^^^ + +* :class:`bpy.types.SpaceNodeEditor.cursor_location` +* :class:`bpy.types.SpaceNodeEditor.edit_tree` +* :class:`bpy.types.SpaceNodeEditor.show_highlight` +* :class:`bpy.types.SpaceNodeEditor.use_hidden_preview` + +bpy.types.SpaceView3D +--------------------- + +Added +^^^^^ + +* :class:`bpy.types.SpaceView3D.layers_local_view` +* :class:`bpy.types.SpaceView3D.show_backface_culling` + +bpy.types.Area +-------------- + +Added +^^^^^ + +* :class:`bpy.types.Area.x` +* :class:`bpy.types.Area.y` + +bpy.types.RenderLayer +--------------------- + +Added +^^^^^ + +* :class:`bpy.types.RenderLayer.layers_exclude` + +bpy.types.MovieTracking +----------------------- + +Added +^^^^^ + +* :class:`bpy.types.MovieTracking.dopesheet` + +bpy.types.MovieTrackingSettings +------------------------------- + +Added +^^^^^ + +* :class:`bpy.types.MovieTrackingSettings.default_motion_model` +* :class:`bpy.types.MovieTrackingSettings.use_default_brute` +* :class:`bpy.types.MovieTrackingSettings.use_default_mask` +* :class:`bpy.types.MovieTrackingSettings.use_default_normalization` +* :class:`bpy.types.MovieTrackingSettings.use_tripod_solver` + +Removed +^^^^^^^ + +* **default_pyramid_levels** +* **default_tracker** + +bpy.types.CompositorNodeIDMask +------------------------------ + +Renamed +^^^^^^^ + +* **use_smooth_mask** -> :class:`bpy.types.CompositorNodeIDMask.use_antialiasing` + +bpy.types.UserPreferencesInput +------------------------------ + +Added +^^^^^ + +* :class:`bpy.types.UserPreferencesInput.ndof_orbit_sensitivity` +* :class:`bpy.types.UserPreferencesInput.ndof_view_rotate_method` + +bpy.types.Brush +--------------- + +Added +^^^^^ + +* :class:`bpy.types.Brush.mask_tool` +* :class:`bpy.types.Brush.weight` + +bpy.types.SpaceSequenceEditor +----------------------------- + +Added +^^^^^ + +* :class:`bpy.types.SpaceSequenceEditor.overlay_type` + +Removed +^^^^^^^ + +* **use_grease_pencil** + +bpy.types.MovieTrackingMarkers +------------------------------ + +Function Arguments +^^^^^^^^^^^^^^^^^^ + +* :class:`bpy.types.MovieTrackingMarkers.find_frame` (frame, exact), *was (frame)* + +bpy.types.UILayout +------------------ + +Added +^^^^^ + +* :class:`bpy.types.UILayout.template_colormanaged_view_settings` +* :class:`bpy.types.UILayout.template_colorspace_settings` + +Function Arguments +^^^^^^^^^^^^^^^^^^ + +* :class:`bpy.types.UILayout.template_image_settings` (image_settings, color_management), *was (image_settings)* + +bpy.types.ID +------------ + +Added +^^^^^ + +* :class:`bpy.types.ID.is_library_indirect` + +bpy.types.SpaceGraphEditor +-------------------------- + +Added +^^^^^ + +* :class:`bpy.types.SpaceGraphEditor.show_group_colors` + +bpy.types.Mesh +-------------- + +Added +^^^^^ + +* :class:`bpy.types.Mesh.skin_vertices` + +Removed +^^^^^^^ + +* **sticky** + +bpy.types.ShaderNodes +--------------------- + +Added +^^^^^ + +* :class:`bpy.types.ShaderNodes.active` + +bpy.types.ColorSequence +----------------------- + +Added +^^^^^ + +* :class:`bpy.types.ColorSequence.input_count` + +bpy.types.ShaderNodeMath +------------------------ + +Added +^^^^^ + +* :class:`bpy.types.ShaderNodeMath.use_clamp` + +bpy.types.Paint +--------------- + +Added +^^^^^ + +* :class:`bpy.types.Paint.input_samples` + +bpy.types.ShaderNodeTexImage +---------------------------- + +Added +^^^^^ + +* :class:`bpy.types.ShaderNodeTexImage.image_user` +* :class:`bpy.types.ShaderNodeTexImage.projection` +* :class:`bpy.types.ShaderNodeTexImage.projection_blend` + +bpy.types.UserPreferencesView +----------------------------- + +Added +^^^^^ + +* :class:`bpy.types.UserPreferencesView.use_mouse_depth_cursor` + +Renamed +^^^^^^^ + +* **use_mouse_auto_depth** -> :class:`bpy.types.UserPreferencesView.use_mouse_depth_navigate` + +bpy.types.CompositorNodeMath +---------------------------- + +Added +^^^^^ + +* :class:`bpy.types.CompositorNodeMath.use_clamp` + +bpy.types.Material +------------------ + +Added +^^^^^ + +* :class:`bpy.types.Material.use_uv_project` + +bpy.types.ThemeNodeEditor +------------------------- + +Added +^^^^^ + +* :class:`bpy.types.ThemeNodeEditor.frame_node` +* :class:`bpy.types.ThemeNodeEditor.node_active` +* :class:`bpy.types.ThemeNodeEditor.node_selected` + +bpy.types.Camera +---------------- + +Removed +^^^^^^^ + +* **use_panorama** + +bpy.types.UnifiedPaintSettings +------------------------------ + +Added +^^^^^ + +* :class:`bpy.types.UnifiedPaintSettings.use_unified_weight` +* :class:`bpy.types.UnifiedPaintSettings.weight` + +bpy.types.TextureNodes +---------------------- + +Added +^^^^^ + +* :class:`bpy.types.TextureNodes.active` + +bpy.types.MovieTrackingMarker +----------------------------- + +Added +^^^^^ + +* :class:`bpy.types.MovieTrackingMarker.pattern_bound_box` +* :class:`bpy.types.MovieTrackingMarker.pattern_corners` +* :class:`bpy.types.MovieTrackingMarker.search_max` +* :class:`bpy.types.MovieTrackingMarker.search_min` + +bpy.types.CyclesWorldSettings +----------------------------- + +Added +^^^^^ + +* :class:`bpy.types.CyclesWorldSettings.samples` + +bpy.types.LatticePoint +---------------------- + +Added +^^^^^ + +* :class:`bpy.types.LatticePoint.select` diff --git a/doc/python_api/rst/info_overview.rst b/doc/python_api/rst/info_overview.rst index 30c45213570..818eb692be9 100644 --- a/doc/python_api/rst/info_overview.rst +++ b/doc/python_api/rst/info_overview.rst @@ -71,7 +71,7 @@ The only difference between addons and built-in python modules is that addons mu The user preferences addon listing uses **bl_info** to display information about each addon. -`See Addons `_ for details on the **bl_info** dictionary. +`See Addons `_ for details on the **bl_info** dictionary. Integration through Classes diff --git a/doc/python_api/rst/info_quickstart.rst b/doc/python_api/rst/info_quickstart.rst index 19ec8059aca..62ad4e9c4d8 100644 --- a/doc/python_api/rst/info_quickstart.rst +++ b/doc/python_api/rst/info_quickstart.rst @@ -2,8 +2,8 @@ Quickstart Introduction *********************** -Intro -===== +Preface +======= This API is generally stable but some areas are still being added and improved. @@ -58,6 +58,22 @@ A quick list of helpful things to know before starting: * To examine further scripts distributed with Blender, see ``~/.blender/scripts/startup/bl_ui`` for the user interface and ``~/.blender/scripts/startup/bl_op`` for operators. +Running Scripts +--------------- + +The two most common ways to execute python scripts are using the built-in text editor or entering commands in the python console. + +Both the **Text Editor** and **Python Console** are space types you can select from the view header. + +Rather then manually configuring your spaces for Python development, you may prefer to use the **Scripting** screen, included default with Blender, accessible from the top headers screen selector. + +From the text editor you can open ``.py`` files or paste then from the clipboard, then test using **Run Script**. + +The Python Console is typically used for typing in snippets and for testing to get immediate feedback, but can also have entire scripts pasted into it. + +Scripts can also run from the command line with Blender but to learn Blender/Python this isn't essential. + + Key Concepts ============ diff --git a/doc/python_api/sphinx_changelog_gen.py b/doc/python_api/sphinx_changelog_gen.py index 3ded1035123..afc253940d4 100644 --- a/doc/python_api/sphinx_changelog_gen.py +++ b/doc/python_api/sphinx_changelog_gen.py @@ -28,15 +28,15 @@ blender --background --python doc/python_api/sphinx_changelog_gen.py -- --dump # create changelog blender --background --python doc/python_api/sphinx_changelog_gen.py -- \ - --api_from blender_2_56_1.py \ - --api_to blender_2_57_0.py \ + --api_from blender_2_63_0.py \ + --api_to blender_2_64_0.py \ --api_out changes.rst # Api comparison can also run without blender -python doc/python_api/sphinx_changelog_gen.py \ - --api_from blender_api_2_56_6.py \ - --api_to blender_api_2_57.py \ +python doc/python_api/sphinx_changelog_gen.py -- \ + --api_from blender_api_2_63_0.py \ + --api_to blender_api_2_64_0.py \ --api_out changes.rst # Save the latest API dump in this folder, renaming it with its revision. @@ -307,6 +307,8 @@ def api_changelog(api_from, api_to, api_out): fout.close() + print("Written: %r" % api_out) + def main(): import sys @@ -347,6 +349,7 @@ def main(): args = parser.parse_args(argv) # In this example we wont use the args if not argv: + print("No args given!") parser.print_help() return diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 186f67b0df6..6f7d4f3582a 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -399,7 +399,7 @@ SPHINX_THEMES = {'bf': ['blender-org'], # , 'naiad', available_themes = SPHINX_THEMES['bf'] + SPHINX_THEMES['sphinx'] if ARGS.sphinx_theme not in available_themes: - print ("Please choose a theme among: %s" % ', '.join(available_themes)) + print("Please choose a theme among: %s" % ', '.join(available_themes)) sys.exit() if ARGS.sphinx_theme in SPHINX_THEMES['bf']: @@ -910,6 +910,72 @@ def pymodule2sphinx(basepath, module_name, module, title): file.close() +# Changes in blender will force errors here +context_type_map = { + "active_base": ("ObjectBase", False), + "active_bone": ("EditBone", False), + "active_object": ("Object", False), + "active_operator": ("Operator", False), + "active_pose_bone": ("PoseBone", False), + "active_node": ("Node", False), + "armature": ("Armature", False), + "bone": ("Bone", False), + "brush": ("Brush", False), + "camera": ("Camera", False), + "cloth": ("ClothModifier", False), + "collision": ("CollisionModifier", False), + "curve": ("Curve", False), + "dynamic_paint": ("DynamicPaintModifier", False), + "edit_bone": ("EditBone", False), + "edit_image": ("Image", False), + "edit_mask": ("Mask", False), + "edit_movieclip": ("MovieClip", False), + "edit_object": ("Object", False), + "edit_text": ("Text", False), + "editable_bones": ("EditBone", True), + "fluid": ("FluidSimulationModifier", False), + "image_paint_object": ("Object", False), + "lamp": ("Lamp", False), + "lattice": ("Lattice", False), + "material": ("Material", False), + "material_slot": ("MaterialSlot", False), + "mesh": ("Mesh", False), + "meta_ball": ("MetaBall", False), + "object": ("Object", False), + "particle_edit_object": ("Object", False), + "particle_settings": ("ParticleSettings", False), + "particle_system": ("ParticleSystem", False), + "particle_system_editable": ("ParticleSystem", False), + "pose_bone": ("PoseBone", False), + "scene": ("Scene", False), + "sculpt_object": ("Object", False), + "selectable_bases": ("ObjectBase", True), + "selectable_objects": ("Object", True), + "selected_bases": ("ObjectBase", True), + "selected_bones": ("EditBone", True), + "selected_editable_bases": ("ObjectBase", True), + "selected_editable_bones": ("EditBone", True), + "selected_editable_objects": ("Object", True), + "selected_editable_sequences": ("Sequence", True), + "selected_nodes": ("Node", True), + "selected_objects": ("Object", True), + "selected_pose_bones": ("PoseBone", True), + "selected_sequences": ("Sequence", True), + "sequences": ("Sequence", True), + "smoke": ("SmokeModifier", False), + "soft_body": ("SoftBodyModifier", False), + "speaker": ("Speaker", False), + "texture": ("Texture", False), + "texture_slot": ("MaterialTextureSlot", False), + "texture_user": ("ID", False), + "vertex_paint_object": ("Object", False), + "visible_bases": ("ObjectBase", True), + "visible_bones": ("EditBone", True), + "visible_objects": ("Object", True), + "visible_pose_bones": ("PoseBone", True), + "weight_paint_object": ("Object", False), + "world": ("World", False), +} def pycontext2sphinx(basepath): # Only use once. very irregular @@ -938,72 +1004,6 @@ def pycontext2sphinx(basepath): "sequencer_context_dir", ) - # Changes in blender will force errors here - type_map = { - "active_base": ("ObjectBase", False), - "active_bone": ("Bone", False), - "active_object": ("Object", False), - "active_operator": ("Operator", False), - "active_pose_bone": ("PoseBone", False), - "active_node": ("Node", False), - "armature": ("Armature", False), - "bone": ("Bone", False), - "brush": ("Brush", False), - "camera": ("Camera", False), - "cloth": ("ClothModifier", False), - "collision": ("CollisionModifier", False), - "curve": ("Curve", False), - "dynamic_paint": ("DynamicPaintModifier", False), - "edit_bone": ("EditBone", False), - "edit_image": ("Image", False), - "edit_mask": ("Mask", False), - "edit_movieclip": ("MovieClip", False), - "edit_object": ("Object", False), - "edit_text": ("Text", False), - "editable_bones": ("EditBone", True), - "fluid": ("FluidSimulationModifier", False), - "image_paint_object": ("Object", False), - "lamp": ("Lamp", False), - "lattice": ("Lattice", False), - "material": ("Material", False), - "material_slot": ("MaterialSlot", False), - "mesh": ("Mesh", False), - "meta_ball": ("MetaBall", False), - "object": ("Object", False), - "particle_edit_object": ("Object", False), - "particle_settings": ("ParticleSettings", False), - "particle_system": ("ParticleSystem", False), - "particle_system_editable": ("ParticleSystem", False), - "pose_bone": ("PoseBone", False), - "scene": ("Scene", False), - "sculpt_object": ("Object", False), - "selectable_bases": ("ObjectBase", True), - "selectable_objects": ("Object", True), - "selected_bases": ("ObjectBase", True), - "selected_bones": ("Bone", True), - "selected_editable_bases": ("ObjectBase", True), - "selected_editable_bones": ("Bone", True), - "selected_editable_objects": ("Object", True), - "selected_editable_sequences": ("Sequence", True), - "selected_nodes": ("Node", True), - "selected_objects": ("Object", True), - "selected_pose_bones": ("PoseBone", True), - "selected_sequences": ("Sequence", True), - "sequences": ("Sequence", True), - "smoke": ("SmokeModifier", False), - "soft_body": ("SoftBodyModifier", False), - "speaker": ("Speaker", False), - "texture": ("Texture", False), - "texture_slot": ("MaterialTextureSlot", False), - "texture_user": ("ID", False), - "vertex_paint_object": ("Object", False), - "visible_bases": ("ObjectBase", True), - "visible_bones": ("Object", True), - "visible_objects": ("Object", True), - "visible_pose_bones": ("PoseBone", True), - "weight_paint_object": ("Object", False), - "world": ("World", False), - } unique = set() blend_cdll = ctypes.CDLL("") @@ -1018,7 +1018,7 @@ def pycontext2sphinx(basepath): while char_array[i] is not None: member = ctypes.string_at(char_array[i]).decode(encoding="ascii") fw(".. data:: %s\n\n" % member) - member_type, is_seq = type_map[member] + member_type, is_seq = context_type_map[member] fw(" :type: %s :class:`bpy.types.%s`\n\n" % ("sequence of " if is_seq else "", member_type)) unique.add(member) i += 1 @@ -1026,8 +1026,8 @@ def pycontext2sphinx(basepath): # generate typemap... # for member in sorted(unique): # print(' "%s": ("", False),' % member) - if len(type_map) > len(unique): - raise Exception("Some types are not used: %s" % str([member for member in type_map if member not in unique])) + if len(context_type_map) > len(unique): + raise Exception("Some types are not used: %s" % str([member for member in context_type_map if member not in unique])) else: pass # will have raised an error above @@ -1314,6 +1314,13 @@ def pyrna2sphinx(basepath): fw(".. hlist::\n") fw(" :columns: 2\n\n") + # context does its own thing + # "active_base": ("ObjectBase", False), + for ref_attr, (ref_type, ref_is_seq) in sorted(context_type_map.items()): + if ref_type == struct_id: + fw(" * :mod:`bpy.context.%s`\n" % ref_attr) + del ref_attr, ref_type, ref_is_seq + for ref in struct.references: ref_split = ref.split(".") if len(ref_split) > 2: diff --git a/extern/Eigen3/Eigen/Cholesky b/extern/Eigen3/Eigen/Cholesky index 53f7bf911a4..f727f5d89c0 100644 --- a/extern/Eigen3/Eigen/Cholesky +++ b/extern/Eigen3/Eigen/Cholesky @@ -5,8 +5,6 @@ #include "src/Core/util/DisableStupidWarnings.h" -namespace Eigen { - /** \defgroup Cholesky_Module Cholesky module * * @@ -24,8 +22,9 @@ namespace Eigen { #include "src/misc/Solve.h" #include "src/Cholesky/LLT.h" #include "src/Cholesky/LDLT.h" - -} // namespace Eigen +#ifdef EIGEN_USE_LAPACKE +#include "src/Cholesky/LLT_MKL.h" +#endif #include "src/Core/util/ReenableStupidWarnings.h" diff --git a/extern/Eigen3/Eigen/CholmodSupport b/extern/Eigen3/Eigen/CholmodSupport new file mode 100644 index 00000000000..745b884e74d --- /dev/null +++ b/extern/Eigen3/Eigen/CholmodSupport @@ -0,0 +1,45 @@ +#ifndef EIGEN_CHOLMODSUPPORT_MODULE_H +#define EIGEN_CHOLMODSUPPORT_MODULE_H + +#include "SparseCore" + +#include "src/Core/util/DisableStupidWarnings.h" + +extern "C" { + #include +} + +/** \ingroup Support_modules + * \defgroup CholmodSupport_Module CholmodSupport module + * + * This module provides an interface to the Cholmod library which is part of the suitesparse package. + * It provides the two following main factorization classes: + * - class CholmodSupernodalLLT: a supernodal LLT Cholesky factorization. + * - class CholmodDecomposiiton: a general L(D)LT Cholesky factorization with automatic or explicit runtime selection of the underlying factorization method (supernodal or simplicial). + * + * For the sake of completeness, this module also propose the two following classes: + * - class CholmodSimplicialLLT + * - class CholmodSimplicialLDLT + * Note that these classes does not bring any particular advantage compared to the built-in + * SimplicialLLT and SimplicialLDLT factorization classes. + * + * \code + * #include + * \endcode + * + * In order to use this module, the cholmod headers must be accessible from the include paths, and your binary must be linked to the cholmod library and its dependencies. + * The dependencies depend on how cholmod has been compiled. + * For a cmake based project, you can use our FindCholmod.cmake module to help you in this task. + * + */ + +#include "src/misc/Solve.h" +#include "src/misc/SparseSolve.h" + +#include "src/CholmodSupport/CholmodSupport.h" + + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_CHOLMODSUPPORT_MODULE_H + diff --git a/extern/Eigen3/Eigen/Core b/extern/Eigen3/Eigen/Core index a5025e37ead..d4801702261 100644 --- a/extern/Eigen3/Eigen/Core +++ b/extern/Eigen3/Eigen/Core @@ -4,24 +4,9 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2007-2011 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_CORE_H #define EIGEN_CORE_H @@ -34,6 +19,12 @@ // defined e.g. EIGEN_DONT_ALIGN) so it needs to be done before we do anything with vectorization. #include "src/Core/util/Macros.h" +#include + +// this include file manages BLAS and MKL related macros +// and inclusion of their respective header files +#include "src/Core/util/MKL_support.h" + // if alignment is disabled, then disable vectorization. Note: EIGEN_ALIGN is the proper check, it takes into // account both the user's will (EIGEN_DONT_ALIGN) and our own platform checks #if !EIGEN_ALIGN @@ -136,7 +127,7 @@ #endif // MSVC for windows mobile does not have the errno.h file -#if !(defined(_MSC_VER) && defined(_WIN32_WCE)) +#if !(defined(_MSC_VER) && defined(_WIN32_WCE)) && !defined(__ARMCC_VERSION) #define EIGEN_HAS_ERRNO #endif @@ -146,7 +137,6 @@ #include #include #include -#include #include #include #include @@ -175,9 +165,6 @@ #include #endif -// defined in bits/termios.h -#undef B0 - /** \brief Namespace containing all symbols from the %Eigen library. */ namespace Eigen { @@ -201,6 +188,8 @@ inline static const char *SimdInstructionSetsInUse(void) { #endif } +} // end namespace Eigen + #define STAGE10_FULL_EIGEN2_API 10 #define STAGE20_RESOLVE_API_CONFLICTS 20 #define STAGE30_FULL_EIGEN3_API 30 @@ -247,6 +236,10 @@ using std::ptrdiff_t; * \endcode */ +/** \defgroup Support_modules Support modules [category] + * Category of modules which add support for external libraries. + */ + #include "src/Core/util/Constants.h" #include "src/Core/util/ForwardDeclarations.h" #include "src/Core/util/Meta.h" @@ -318,15 +311,15 @@ using std::ptrdiff_t; #include "src/Core/CommaInitializer.h" #include "src/Core/Flagged.h" #include "src/Core/ProductBase.h" -#include "src/Core/Product.h" +#include "src/Core/GeneralProduct.h" #include "src/Core/TriangularMatrix.h" #include "src/Core/SelfAdjointView.h" -#include "src/Core/SolveTriangular.h" +#include "src/Core/products/GeneralBlockPanelKernel.h" #include "src/Core/products/Parallelizer.h" #include "src/Core/products/CoeffBasedProduct.h" -#include "src/Core/products/GeneralBlockPanelKernel.h" #include "src/Core/products/GeneralMatrixVector.h" #include "src/Core/products/GeneralMatrixMatrix.h" +#include "src/Core/SolveTriangular.h" #include "src/Core/products/GeneralMatrixMatrixTriangular.h" #include "src/Core/products/SelfadjointMatrixVector.h" #include "src/Core/products/SelfadjointMatrixMatrix.h" @@ -347,7 +340,20 @@ using std::ptrdiff_t; #include "src/Core/ArrayBase.h" #include "src/Core/ArrayWrapper.h" -} // namespace Eigen +#ifdef EIGEN_USE_BLAS +#include "src/Core/products/GeneralMatrixMatrix_MKL.h" +#include "src/Core/products/GeneralMatrixVector_MKL.h" +#include "src/Core/products/GeneralMatrixMatrixTriangular_MKL.h" +#include "src/Core/products/SelfadjointMatrixMatrix_MKL.h" +#include "src/Core/products/SelfadjointMatrixVector_MKL.h" +#include "src/Core/products/TriangularMatrixMatrix_MKL.h" +#include "src/Core/products/TriangularMatrixVector_MKL.h" +#include "src/Core/products/TriangularSolverMatrix_MKL.h" +#endif // EIGEN_USE_BLAS + +#ifdef EIGEN_USE_MKL_VML +#include "src/Core/Assign_MKL.h" +#endif #include "src/Core/GlobalFunctions.h" diff --git a/extern/Eigen3/Eigen/Eigen2Support b/extern/Eigen3/Eigen/Eigen2Support index d96592a8de9..36156d29a92 100644 --- a/extern/Eigen3/Eigen/Eigen2Support +++ b/extern/Eigen3/Eigen/Eigen2Support @@ -3,24 +3,9 @@ // // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN2SUPPORT_H #define EIGEN2SUPPORT_H @@ -31,9 +16,8 @@ #include "src/Core/util/DisableStupidWarnings.h" -namespace Eigen { - -/** \defgroup Eigen2Support_Module Eigen2 support module +/** \ingroup Support_modules + * \defgroup Eigen2Support_Module Eigen2 support module * This module provides a couple of deprecated functions improving the compatibility with Eigen2. * * To use it, define EIGEN2_SUPPORT before including any Eigen header @@ -56,13 +40,29 @@ namespace Eigen { #include "src/Eigen2Support/MathFunctions.h" -} // namespace Eigen - #include "src/Core/util/ReenableStupidWarnings.h" // Eigen2 used to include iostream #include +#define EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, SizeSuffix) \ +using Eigen::Matrix##SizeSuffix##TypeSuffix; \ +using Eigen::Vector##SizeSuffix##TypeSuffix; \ +using Eigen::RowVector##SizeSuffix##TypeSuffix; + +#define EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(TypeSuffix) \ +EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 2) \ +EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 3) \ +EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 4) \ +EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, X) \ + +#define EIGEN_USING_MATRIX_TYPEDEFS \ +EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(i) \ +EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(f) \ +EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(d) \ +EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(cf) \ +EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(cd) + #define USING_PART_OF_NAMESPACE_EIGEN \ EIGEN_USING_MATRIX_TYPEDEFS \ using Eigen::Matrix; \ diff --git a/extern/Eigen3/Eigen/Eigenvalues b/extern/Eigen3/Eigen/Eigenvalues index 250c0f46652..af99ccd1fab 100644 --- a/extern/Eigen3/Eigen/Eigenvalues +++ b/extern/Eigen3/Eigen/Eigenvalues @@ -9,8 +9,7 @@ #include "Jacobi" #include "Householder" #include "LU" - -namespace Eigen { +#include "Geometry" /** \defgroup Eigenvalues_Module Eigenvalues module * @@ -35,8 +34,11 @@ namespace Eigen { #include "src/Eigenvalues/ComplexSchur.h" #include "src/Eigenvalues/ComplexEigenSolver.h" #include "src/Eigenvalues/MatrixBaseEigenvalues.h" - -} // namespace Eigen +#ifdef EIGEN_USE_LAPACKE +#include "src/Eigenvalues/RealSchur_MKL.h" +#include "src/Eigenvalues/ComplexSchur_MKL.h" +#include "src/Eigenvalues/SelfAdjointEigenSolver_MKL.h" +#endif #include "src/Core/util/ReenableStupidWarnings.h" diff --git a/extern/Eigen3/Eigen/Geometry b/extern/Eigen3/Eigen/Geometry index 78277c0c560..efd9d4504cb 100644 --- a/extern/Eigen3/Eigen/Geometry +++ b/extern/Eigen3/Eigen/Geometry @@ -13,8 +13,6 @@ #define M_PI 3.14159265358979323846 #endif -namespace Eigen { - /** \defgroup Geometry_Module Geometry module * * @@ -58,8 +56,6 @@ namespace Eigen { #include "src/Eigen2Support/Geometry/All.h" #endif -} // namespace Eigen - #include "src/Core/util/ReenableStupidWarnings.h" #endif // EIGEN_GEOMETRY_MODULE_H diff --git a/extern/Eigen3/Eigen/Householder b/extern/Eigen3/Eigen/Householder index 6b86cf65c55..6e348db5c43 100644 --- a/extern/Eigen3/Eigen/Householder +++ b/extern/Eigen3/Eigen/Householder @@ -5,8 +5,6 @@ #include "src/Core/util/DisableStupidWarnings.h" -namespace Eigen { - /** \defgroup Householder_Module Householder module * This module provides Householder transformations. * @@ -19,8 +17,6 @@ namespace Eigen { #include "src/Householder/HouseholderSequence.h" #include "src/Householder/BlockHouseholder.h" -} // namespace Eigen - #include "src/Core/util/ReenableStupidWarnings.h" #endif // EIGEN_HOUSEHOLDER_MODULE_H diff --git a/extern/Eigen3/Eigen/IterativeLinearSolvers b/extern/Eigen3/Eigen/IterativeLinearSolvers new file mode 100644 index 00000000000..315c2dd1ee7 --- /dev/null +++ b/extern/Eigen3/Eigen/IterativeLinearSolvers @@ -0,0 +1,40 @@ +#ifndef EIGEN_ITERATIVELINEARSOLVERS_MODULE_H +#define EIGEN_ITERATIVELINEARSOLVERS_MODULE_H + +#include "SparseCore" +#include "OrderingMethods" + +#include "src/Core/util/DisableStupidWarnings.h" + +/** \ingroup Sparse_modules + * \defgroup IterativeLinearSolvers_Module IterativeLinearSolvers module + * + * This module currently provides iterative methods to solve problems of the form \c A \c x = \c b, where \c A is a squared matrix, usually very large and sparse. + * Those solvers are accessible via the following classes: + * - ConjugateGradient for selfadjoint (hermitian) matrices, + * - BiCGSTAB for general square matrices. + * + * These iterative solvers are associated with some preconditioners: + * - IdentityPreconditioner - not really useful + * - DiagonalPreconditioner - also called JAcobi preconditioner, work very well on diagonal dominant matrices. + * - IncompleteILUT - incomplete LU factorization with dual thresholding + * + * Such problems can also be solved using the direct sparse decomposition modules: SparseCholesky, CholmodSupport, UmfPackSupport, SuperLUSupport. + * + * \code + * #include + * \endcode + */ + +#include "src/misc/Solve.h" +#include "src/misc/SparseSolve.h" + +#include "src/IterativeLinearSolvers/IterativeSolverBase.h" +#include "src/IterativeLinearSolvers/BasicPreconditioners.h" +#include "src/IterativeLinearSolvers/ConjugateGradient.h" +#include "src/IterativeLinearSolvers/BiCGSTAB.h" +#include "src/IterativeLinearSolvers/IncompleteLUT.h" + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_ITERATIVELINEARSOLVERS_MODULE_H diff --git a/extern/Eigen3/Eigen/Jacobi b/extern/Eigen3/Eigen/Jacobi index afa67681379..ba8a4dc36a5 100644 --- a/extern/Eigen3/Eigen/Jacobi +++ b/extern/Eigen3/Eigen/Jacobi @@ -5,8 +5,6 @@ #include "src/Core/util/DisableStupidWarnings.h" -namespace Eigen { - /** \defgroup Jacobi_Module Jacobi module * This module provides Jacobi and Givens rotations. * @@ -21,8 +19,6 @@ namespace Eigen { #include "src/Jacobi/Jacobi.h" -} // namespace Eigen - #include "src/Core/util/ReenableStupidWarnings.h" #endif // EIGEN_JACOBI_MODULE_H diff --git a/extern/Eigen3/Eigen/LU b/extern/Eigen3/Eigen/LU index 226f88ca38a..db579550448 100644 --- a/extern/Eigen3/Eigen/LU +++ b/extern/Eigen3/Eigen/LU @@ -5,8 +5,6 @@ #include "src/Core/util/DisableStupidWarnings.h" -namespace Eigen { - /** \defgroup LU_Module LU module * This module includes %LU decomposition and related notions such as matrix inversion and determinant. * This module defines the following MatrixBase methods: @@ -23,6 +21,9 @@ namespace Eigen { #include "src/misc/Image.h" #include "src/LU/FullPivLU.h" #include "src/LU/PartialPivLU.h" +#ifdef EIGEN_USE_LAPACKE +#include "src/LU/PartialPivLU_MKL.h" +#endif #include "src/LU/Determinant.h" #include "src/LU/Inverse.h" @@ -34,8 +35,6 @@ namespace Eigen { #include "src/Eigen2Support/LU.h" #endif -} // namespace Eigen - #include "src/Core/util/ReenableStupidWarnings.h" #endif // EIGEN_LU_MODULE_H diff --git a/extern/Eigen3/Eigen/LeastSquares b/extern/Eigen3/Eigen/LeastSquares index 93a6302dcd9..35137c25db0 100644 --- a/extern/Eigen3/Eigen/LeastSquares +++ b/extern/Eigen3/Eigen/LeastSquares @@ -15,8 +15,6 @@ #include "Eigenvalues" #include "Geometry" -namespace Eigen { - /** \defgroup LeastSquares_Module LeastSquares module * This module provides linear regression and related features. * @@ -27,8 +25,6 @@ namespace Eigen { #include "src/Eigen2Support/LeastSquares.h" -} // namespace Eigen - #include "src/Core/util/ReenableStupidWarnings.h" #endif // EIGEN2_SUPPORT diff --git a/extern/Eigen3/Eigen/OrderingMethods b/extern/Eigen3/Eigen/OrderingMethods new file mode 100644 index 00000000000..1e2d87452e5 --- /dev/null +++ b/extern/Eigen3/Eigen/OrderingMethods @@ -0,0 +1,23 @@ +#ifndef EIGEN_ORDERINGMETHODS_MODULE_H +#define EIGEN_ORDERINGMETHODS_MODULE_H + +#include "SparseCore" + +#include "src/Core/util/DisableStupidWarnings.h" + +/** \ingroup Sparse_modules + * \defgroup OrderingMethods_Module OrderingMethods module + * + * This module is currently for internal use only. + * + * + * \code + * #include + * \endcode + */ + +#include "src/OrderingMethods/Amd.h" + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_ORDERINGMETHODS_MODULE_H diff --git a/extern/Eigen3/Eigen/PaStiXSupport b/extern/Eigen3/Eigen/PaStiXSupport new file mode 100644 index 00000000000..7c616ee5eac --- /dev/null +++ b/extern/Eigen3/Eigen/PaStiXSupport @@ -0,0 +1,46 @@ +#ifndef EIGEN_PASTIXSUPPORT_MODULE_H +#define EIGEN_PASTIXSUPPORT_MODULE_H + +#include "SparseCore" + +#include "src/Core/util/DisableStupidWarnings.h" + +#include +extern "C" { +#include +#include +} + +#ifdef complex +#undef complex +#endif + +/** \ingroup Support_modules + * \defgroup PaStiXSupport_Module PaStiXSupport module + * + * This module provides an interface to the PaSTiX library. + * PaSTiX is a general \b supernodal, \b parallel and \b opensource sparse solver. + * It provides the two following main factorization classes: + * - class PastixLLT : a supernodal, parallel LLt Cholesky factorization. + * - class PastixLDLT: a supernodal, parallel LDLt Cholesky factorization. + * - class PastixLU : a supernodal, parallel LU factorization (optimized for a symmetric pattern). + * + * \code + * #include + * \endcode + * + * In order to use this module, the PaSTiX headers must be accessible from the include paths, and your binary must be linked to the PaSTiX library and its dependencies. + * The dependencies depend on how PaSTiX has been compiled. + * For a cmake based project, you can use our FindPaSTiX.cmake module to help you in this task. + * + */ + +#include "src/misc/Solve.h" +#include "src/misc/SparseSolve.h" + +#include "src/PaStiXSupport/PaStiXSupport.h" + + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_PASTIXSUPPORT_MODULE_H diff --git a/extern/Eigen3/Eigen/PardisoSupport b/extern/Eigen3/Eigen/PardisoSupport new file mode 100644 index 00000000000..99330ce7a7d --- /dev/null +++ b/extern/Eigen3/Eigen/PardisoSupport @@ -0,0 +1,30 @@ +#ifndef EIGEN_PARDISOSUPPORT_MODULE_H +#define EIGEN_PARDISOSUPPORT_MODULE_H + +#include "SparseCore" + +#include "src/Core/util/DisableStupidWarnings.h" + +#include + +#include + +/** \ingroup Support_modules + * \defgroup PardisoSupport_Module PardisoSupport module + * + * This module brings support for the Intel(R) MKL PARDISO direct sparse solvers. + * + * \code + * #include + * \endcode + * + * In order to use this module, the MKL headers must be accessible from the include paths, and your binary must be linked to the MKL library and its dependencies. + * See this \ref TopicUsingIntelMKL "page" for more information on MKL-Eigen integration. + * + */ + +#include "src/PardisoSupport/PardisoSupport.h" + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_PARDISOSUPPORT_MODULE_H diff --git a/extern/Eigen3/Eigen/QR b/extern/Eigen3/Eigen/QR index 97c1788ee30..ac5b0269354 100644 --- a/extern/Eigen3/Eigen/QR +++ b/extern/Eigen3/Eigen/QR @@ -9,8 +9,6 @@ #include "Jacobi" #include "Householder" -namespace Eigen { - /** \defgroup QR_Module QR module * * @@ -28,13 +26,15 @@ namespace Eigen { #include "src/QR/HouseholderQR.h" #include "src/QR/FullPivHouseholderQR.h" #include "src/QR/ColPivHouseholderQR.h" +#ifdef EIGEN_USE_LAPACKE +#include "src/QR/HouseholderQR_MKL.h" +#include "src/QR/ColPivHouseholderQR_MKL.h" +#endif #ifdef EIGEN2_SUPPORT #include "src/Eigen2Support/QR.h" #endif -} // namespace Eigen - #include "src/Core/util/ReenableStupidWarnings.h" #ifdef EIGEN2_SUPPORT diff --git a/extern/Eigen3/Eigen/SVD b/extern/Eigen3/Eigen/SVD index 7c987a9dd36..fd310017ad1 100644 --- a/extern/Eigen3/Eigen/SVD +++ b/extern/Eigen3/Eigen/SVD @@ -7,8 +7,6 @@ #include "src/Core/util/DisableStupidWarnings.h" -namespace Eigen { - /** \defgroup SVD_Module SVD module * * @@ -24,14 +22,15 @@ namespace Eigen { #include "src/misc/Solve.h" #include "src/SVD/JacobiSVD.h" +#if defined(EIGEN_USE_LAPACKE) && !defined(EIGEN_USE_LAPACKE_STRICT) +#include "src/SVD/JacobiSVD_MKL.h" +#endif #include "src/SVD/UpperBidiagonalization.h" #ifdef EIGEN2_SUPPORT #include "src/Eigen2Support/SVD.h" #endif -} // namespace Eigen - #include "src/Core/util/ReenableStupidWarnings.h" #endif // EIGEN_SVD_MODULE_H diff --git a/extern/Eigen3/Eigen/Sparse b/extern/Eigen3/Eigen/Sparse index 7425b3a412a..2d1757172eb 100644 --- a/extern/Eigen3/Eigen/Sparse +++ b/extern/Eigen3/Eigen/Sparse @@ -1,69 +1,23 @@ #ifndef EIGEN_SPARSE_MODULE_H #define EIGEN_SPARSE_MODULE_H -#include "Core" - -#include "src/Core/util/DisableStupidWarnings.h" - -#include -#include -#include -#include -#include - -#ifdef EIGEN2_SUPPORT -#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET -#endif - -#ifndef EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET -#error The sparse module API is not stable yet. To use it anyway, please define the EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET preprocessor token. -#endif - -namespace Eigen { - -/** \defgroup Sparse_Module Sparse module +/** \defgroup Sparse_modules Sparse modules * - * - * - * See the \ref TutorialSparse "Sparse tutorial" + * Meta-module including all related modules: + * - SparseCore + * - OrderingMethods + * - SparseCholesky + * - IterativeLinearSolvers * * \code * #include * \endcode */ -/** The type used to identify a general sparse storage. */ -struct Sparse {}; - -#include "src/Sparse/SparseUtil.h" -#include "src/Sparse/SparseMatrixBase.h" -#include "src/Sparse/CompressedStorage.h" -#include "src/Sparse/AmbiVector.h" -#include "src/Sparse/SparseMatrix.h" -#include "src/Sparse/DynamicSparseMatrix.h" -#include "src/Sparse/MappedSparseMatrix.h" -#include "src/Sparse/SparseVector.h" -#include "src/Sparse/CoreIterators.h" -#include "src/Sparse/SparseBlock.h" -#include "src/Sparse/SparseTranspose.h" -#include "src/Sparse/SparseCwiseUnaryOp.h" -#include "src/Sparse/SparseCwiseBinaryOp.h" -#include "src/Sparse/SparseDot.h" -#include "src/Sparse/SparseAssign.h" -#include "src/Sparse/SparseRedux.h" -#include "src/Sparse/SparseFuzzy.h" -#include "src/Sparse/SparseProduct.h" -#include "src/Sparse/SparseSparseProduct.h" -#include "src/Sparse/SparseDenseProduct.h" -#include "src/Sparse/SparseDiagonalProduct.h" -#include "src/Sparse/SparseTriangularView.h" -#include "src/Sparse/SparseSelfAdjointView.h" -#include "src/Sparse/TriangularSolver.h" -#include "src/Sparse/SparseView.h" - -} // namespace Eigen - -#include "src/Core/util/ReenableStupidWarnings.h" +#include "SparseCore" +#include "OrderingMethods" +#include "SparseCholesky" +#include "IterativeLinearSolvers" #endif // EIGEN_SPARSE_MODULE_H diff --git a/extern/Eigen3/Eigen/SparseCholesky b/extern/Eigen3/Eigen/SparseCholesky new file mode 100644 index 00000000000..5f82742f7d8 --- /dev/null +++ b/extern/Eigen3/Eigen/SparseCholesky @@ -0,0 +1,30 @@ +#ifndef EIGEN_SPARSECHOLESKY_MODULE_H +#define EIGEN_SPARSECHOLESKY_MODULE_H + +#include "SparseCore" + +#include "src/Core/util/DisableStupidWarnings.h" + +/** \ingroup Sparse_modules + * \defgroup SparseCholesky_Module SparseCholesky module + * + * This module currently provides two variants of the direct sparse Cholesky decomposition for selfadjoint (hermitian) matrices. + * Those decompositions are accessible via the following classes: + * - SimplicialLLt, + * - SimplicialLDLt + * + * Such problems can also be solved using the ConjugateGradient solver from the IterativeLinearSolvers module. + * + * \code + * #include + * \endcode + */ + +#include "src/misc/Solve.h" +#include "src/misc/SparseSolve.h" + +#include "src/SparseCholesky/SimplicialCholesky.h" + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_SPARSECHOLESKY_MODULE_H diff --git a/extern/Eigen3/Eigen/SparseCore b/extern/Eigen3/Eigen/SparseCore new file mode 100644 index 00000000000..41d28c92824 --- /dev/null +++ b/extern/Eigen3/Eigen/SparseCore @@ -0,0 +1,66 @@ +#ifndef EIGEN_SPARSECORE_MODULE_H +#define EIGEN_SPARSECORE_MODULE_H + +#include "Core" + +#include "src/Core/util/DisableStupidWarnings.h" + +#include +#include +#include +#include +#include + +/** \ingroup Sparse_modules + * \defgroup SparseCore_Module SparseCore module + * + * This module provides a sparse matrix representation, and basic associatd matrix manipulations + * and operations. + * + * See the \ref TutorialSparse "Sparse tutorial" + * + * \code + * #include + * \endcode + * + * This module depends on: Core. + */ + +namespace Eigen { + +/** The type used to identify a general sparse storage. */ +struct Sparse {}; + +} + +#include "src/SparseCore/SparseUtil.h" +#include "src/SparseCore/SparseMatrixBase.h" +#include "src/SparseCore/CompressedStorage.h" +#include "src/SparseCore/AmbiVector.h" +#include "src/SparseCore/SparseMatrix.h" +#include "src/SparseCore/MappedSparseMatrix.h" +#include "src/SparseCore/SparseVector.h" +#include "src/SparseCore/CoreIterators.h" +#include "src/SparseCore/SparseBlock.h" +#include "src/SparseCore/SparseTranspose.h" +#include "src/SparseCore/SparseCwiseUnaryOp.h" +#include "src/SparseCore/SparseCwiseBinaryOp.h" +#include "src/SparseCore/SparseDot.h" +#include "src/SparseCore/SparsePermutation.h" +#include "src/SparseCore/SparseAssign.h" +#include "src/SparseCore/SparseRedux.h" +#include "src/SparseCore/SparseFuzzy.h" +#include "src/SparseCore/ConservativeSparseSparseProduct.h" +#include "src/SparseCore/SparseSparseProductWithPruning.h" +#include "src/SparseCore/SparseProduct.h" +#include "src/SparseCore/SparseDenseProduct.h" +#include "src/SparseCore/SparseDiagonalProduct.h" +#include "src/SparseCore/SparseTriangularView.h" +#include "src/SparseCore/SparseSelfAdjointView.h" +#include "src/SparseCore/TriangularSolver.h" +#include "src/SparseCore/SparseView.h" + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_SPARSECORE_MODULE_H + diff --git a/extern/Eigen3/Eigen/StdDeque b/extern/Eigen3/Eigen/StdDeque index a4f96232d8c..f27234778f4 100644 --- a/extern/Eigen3/Eigen/StdDeque +++ b/extern/Eigen3/Eigen/StdDeque @@ -4,24 +4,9 @@ // Copyright (C) 2009 Gael Guennebaud // Copyright (C) 2009 Hauke Heibel // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_STDDEQUE_MODULE_H #define EIGEN_STDDEQUE_MODULE_H diff --git a/extern/Eigen3/Eigen/StdList b/extern/Eigen3/Eigen/StdList index d914ded4f93..225c1e18f8e 100644 --- a/extern/Eigen3/Eigen/StdList +++ b/extern/Eigen3/Eigen/StdList @@ -3,24 +3,9 @@ // // Copyright (C) 2009 Hauke Heibel // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_STDLIST_MODULE_H #define EIGEN_STDLIST_MODULE_H diff --git a/extern/Eigen3/Eigen/StdVector b/extern/Eigen3/Eigen/StdVector index 3d8995e5aae..6b22627f6f6 100644 --- a/extern/Eigen3/Eigen/StdVector +++ b/extern/Eigen3/Eigen/StdVector @@ -4,24 +4,9 @@ // Copyright (C) 2009 Gael Guennebaud // Copyright (C) 2009 Hauke Heibel // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_STDVECTOR_MODULE_H #define EIGEN_STDVECTOR_MODULE_H diff --git a/extern/Eigen3/Eigen/SuperLUSupport b/extern/Eigen3/Eigen/SuperLUSupport new file mode 100644 index 00000000000..575e14fbc29 --- /dev/null +++ b/extern/Eigen3/Eigen/SuperLUSupport @@ -0,0 +1,59 @@ +#ifndef EIGEN_SUPERLUSUPPORT_MODULE_H +#define EIGEN_SUPERLUSUPPORT_MODULE_H + +#include "SparseCore" + +#include "src/Core/util/DisableStupidWarnings.h" + +#ifdef EMPTY +#define EIGEN_EMPTY_WAS_ALREADY_DEFINED +#endif + +typedef int int_t; +#include +#include +#include + +// slu_util.h defines a preprocessor token named EMPTY which is really polluting, +// so we remove it in favor of a SUPERLU_EMPTY token. +// If EMPTY was already defined then we don't undef it. + +#if defined(EIGEN_EMPTY_WAS_ALREADY_DEFINED) +# undef EIGEN_EMPTY_WAS_ALREADY_DEFINED +#elif defined(EMPTY) +# undef EMPTY +#endif + +#define SUPERLU_EMPTY (-1) + +namespace Eigen { struct SluMatrix; } + +/** \ingroup Support_modules + * \defgroup SuperLUSupport_Module SuperLUSupport module + * + * This module provides an interface to the SuperLU library. + * It provides the following factorization class: + * - class SuperLU: a supernodal sequential LU factorization. + * - class SuperILU: a supernodal sequential incomplete LU factorization (to be used as a preconditioner for iterative methods). + * + * \warning When including this module, you have to use SUPERLU_EMPTY instead of EMPTY which is no longer defined because it is too polluting. + * + * \code + * #include + * \endcode + * + * In order to use this module, the superlu headers must be accessible from the include paths, and your binary must be linked to the superlu library and its dependencies. + * The dependencies depend on how superlu has been compiled. + * For a cmake based project, you can use our FindSuperLU.cmake module to help you in this task. + * + */ + +#include "src/misc/Solve.h" +#include "src/misc/SparseSolve.h" + +#include "src/SuperLUSupport/SuperLUSupport.h" + + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_SUPERLUSUPPORT_MODULE_H diff --git a/extern/Eigen3/Eigen/UmfPackSupport b/extern/Eigen3/Eigen/UmfPackSupport new file mode 100644 index 00000000000..984f64a8419 --- /dev/null +++ b/extern/Eigen3/Eigen/UmfPackSupport @@ -0,0 +1,36 @@ +#ifndef EIGEN_UMFPACKSUPPORT_MODULE_H +#define EIGEN_UMFPACKSUPPORT_MODULE_H + +#include "SparseCore" + +#include "src/Core/util/DisableStupidWarnings.h" + +extern "C" { +#include +} + +/** \ingroup Support_modules + * \defgroup UmfPackSupport_Module UmfPackSupport module + * + * This module provides an interface to the UmfPack library which is part of the suitesparse package. + * It provides the following factorization class: + * - class UmfPackLU: a multifrontal sequential LU factorization. + * + * \code + * #include + * \endcode + * + * In order to use this module, the umfpack headers must be accessible from the include paths, and your binary must be linked to the umfpack library and its dependencies. + * The dependencies depend on how umfpack has been compiled. + * For a cmake based project, you can use our FindUmfPack.cmake module to help you in this task. + * + */ + +#include "src/misc/Solve.h" +#include "src/misc/SparseSolve.h" + +#include "src/UmfPackSupport/UmfPackSupport.h" + +#include "src/Core/util/ReenableStupidWarnings.h" + +#endif // EIGEN_UMFPACKSUPPORT_MODULE_H diff --git a/extern/Eigen3/Eigen/src/Cholesky/LDLT.h b/extern/Eigen3/Eigen/src/Cholesky/LDLT.h index a19e947a4c6..68e54b1d4ad 100644 --- a/extern/Eigen3/Eigen/src/Cholesky/LDLT.h +++ b/extern/Eigen3/Eigen/src/Cholesky/LDLT.h @@ -1,43 +1,33 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2008-2010 Gael Guennebaud +// Copyright (C) 2008-2011 Gael Guennebaud // Copyright (C) 2009 Keir Mierle // Copyright (C) 2009 Benoit Jacob +// Copyright (C) 2011 Timothy E. Holy // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_LDLT_H #define EIGEN_LDLT_H +namespace Eigen { + namespace internal { template struct LDLT_Traits; } -/** \ingroup cholesky_Module +/** \ingroup Cholesky_Module * * \class LDLT * * \brief Robust Cholesky decomposition of a matrix with pivoting * * \param MatrixType the type of the matrix of which to compute the LDL^T Cholesky decomposition + * \param UpLo the triangular part that will be used for the decompositon: Lower (default) or Upper. + * The other triangular part won't be read. * * Perform a robust Cholesky decomposition of a positive semidefinite or negative semidefinite * matrix \f$ A \f$ such that \f$ A = P^TLDL^*P \f$, where P is a permutation matrix, L @@ -48,14 +38,10 @@ template struct LDLT_Traits; * on D also stabilizes the computation. * * Remember that Cholesky decompositions are not rank-revealing. Also, do not use a Cholesky - * decomposition to determine whether a system of equations has a solution. + * decomposition to determine whether a system of equations has a solution. * * \sa MatrixBase::ldlt(), class LLT */ - /* THIS PART OF THE DOX IS CURRENTLY DISABLED BECAUSE INACCURATE BECAUSE OF BUG IN THE DECOMPOSITION CODE - * Note that during the decomposition, only the upper triangular part of A is considered. Therefore, - * the strict lower part does not have to store correct values. - */ template class LDLT { public: @@ -98,6 +84,11 @@ template class LDLT m_isInitialized(false) {} + /** \brief Constructor with decomposition + * + * This calculates the decomposition for the input \a matrix. + * \sa LDLT(Index size) + */ LDLT(const MatrixType& matrix) : m_matrix(matrix.rows(), matrix.cols()), m_transpositions(matrix.rows()), @@ -107,6 +98,14 @@ template class LDLT compute(matrix); } + /** Clear any existing decomposition + * \sa rankUpdate(w,sigma) + */ + void setZero() + { + m_isInitialized = false; + } + /** \returns a view of the upper triangular matrix U */ inline typename Traits::MatrixU matrixU() const { @@ -130,14 +129,14 @@ template class LDLT } /** \returns the coefficients of the diagonal matrix D */ - inline Diagonal vectorD(void) const + inline Diagonal vectorD() const { eigen_assert(m_isInitialized && "LDLT is not initialized."); return m_matrix.diagonal(); } /** \returns true if the matrix is positive (semidefinite) */ - inline bool isPositive(void) const + inline bool isPositive() const { eigen_assert(m_isInitialized && "LDLT is not initialized."); return m_sign == 1; @@ -196,6 +195,9 @@ template class LDLT LDLT& compute(const MatrixType& matrix); + template + LDLT& rankUpdate(const MatrixBase& w,RealScalar alpha=1); + /** \returns the internal LDLT decomposition matrix * * TODO: document the storage layout @@ -211,6 +213,17 @@ template class LDLT inline Index rows() const { return m_matrix.rows(); } inline Index cols() const { return m_matrix.cols(); } + /** \brief Reports whether previous computation was successful. + * + * \returns \c Success if computation was succesful, + * \c NumericalIssue if the matrix.appears to be negative. + */ + ComputationInfo info() const + { + eigen_assert(m_isInitialized && "LDLT is not initialized."); + return Success; + } + protected: /** \internal @@ -249,7 +262,7 @@ template<> struct ldlt_inplace return true; } - RealScalar cutoff = 0, biggest_in_corner; + RealScalar cutoff(0), biggest_in_corner; for (Index k = 0; k < size; ++k) { @@ -317,6 +330,61 @@ template<> struct ldlt_inplace return true; } + + // Reference for the algorithm: Davis and Hager, "Multiple Rank + // Modifications of a Sparse Cholesky Factorization" (Algorithm 1) + // Trivial rearrangements of their computations (Timothy E. Holy) + // allow their algorithm to work for rank-1 updates even if the + // original matrix is not of full rank. + // Here only rank-1 updates are implemented, to reduce the + // requirement for intermediate storage and improve accuracy + template + static bool updateInPlace(MatrixType& mat, MatrixBase& w, typename MatrixType::RealScalar sigma=1) + { + using internal::isfinite; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef typename MatrixType::Index Index; + + const Index size = mat.rows(); + eigen_assert(mat.cols() == size && w.size()==size); + + RealScalar alpha = 1; + + // Apply the update + for (Index j = 0; j < size; j++) + { + // Check for termination due to an original decomposition of low-rank + if (!(isfinite)(alpha)) + break; + + // Update the diagonal terms + RealScalar dj = real(mat.coeff(j,j)); + Scalar wj = w.coeff(j); + RealScalar swj2 = sigma*abs2(wj); + RealScalar gamma = dj*alpha + swj2; + + mat.coeffRef(j,j) += swj2/alpha; + alpha += swj2/dj; + + + // Update the terms of L + Index rs = size-j-1; + w.tail(rs) -= wj * mat.col(j).tail(rs); + if(gamma != 0) + mat.col(j).tail(rs) += (sigma*conj(wj)/gamma)*w.tail(rs); + } + return true; + } + + template + static bool update(MatrixType& mat, const TranspositionType& transpositions, Workspace& tmp, const WType& w, typename MatrixType::RealScalar sigma=1) + { + // Apply the permutation to the input w + tmp = transpositions * w; + + return ldlt_inplace::updateInPlace(mat,tmp,sigma); + } }; template<> struct ldlt_inplace @@ -327,22 +395,29 @@ template<> struct ldlt_inplace Transpose matt(mat); return ldlt_inplace::unblocked(matt, transpositions, temp, sign); } + + template + static EIGEN_STRONG_INLINE bool update(MatrixType& mat, TranspositionType& transpositions, Workspace& tmp, WType& w, typename MatrixType::RealScalar sigma=1) + { + Transpose matt(mat); + return ldlt_inplace::update(matt, transpositions, tmp, w.conjugate(), sigma); + } }; template struct LDLT_Traits { typedef const TriangularView MatrixL; typedef const TriangularView MatrixU; - inline static MatrixL getL(const MatrixType& m) { return m; } - inline static MatrixU getU(const MatrixType& m) { return m.adjoint(); } + static inline MatrixL getL(const MatrixType& m) { return m; } + static inline MatrixU getU(const MatrixType& m) { return m.adjoint(); } }; template struct LDLT_Traits { typedef const TriangularView MatrixL; typedef const TriangularView MatrixU; - inline static MatrixL getL(const MatrixType& m) { return m.adjoint(); } - inline static MatrixU getU(const MatrixType& m) { return m; } + static inline MatrixL getL(const MatrixType& m) { return m.adjoint(); } + static inline MatrixU getU(const MatrixType& m) { return m; } }; } // end namespace internal @@ -367,6 +442,37 @@ LDLT& LDLT::compute(const MatrixType& a) return *this; } +/** Update the LDLT decomposition: given A = L D L^T, efficiently compute the decomposition of A + sigma w w^T. + * \param w a vector to be incorporated into the decomposition. + * \param sigma a scalar, +1 for updates and -1 for "downdates," which correspond to removing previously-added column vectors. Optional; default value is +1. + * \sa setZero() + */ +template +template +LDLT& LDLT::rankUpdate(const MatrixBase& w,typename NumTraits::Real sigma) +{ + const Index size = w.rows(); + if (m_isInitialized) + { + eigen_assert(m_matrix.rows()==size); + } + else + { + m_matrix.resize(size,size); + m_matrix.setZero(); + m_transpositions.resize(size); + for (Index i = 0; i < size; i++) + m_transpositions.coeffRef(i) = i; + m_temporary.resize(size); + m_sign = sigma>=0 ? 1 : -1; + m_isInitialized = true; + } + + internal::ldlt_inplace::update(m_matrix, m_transpositions, m_temporary, w, sigma); + + return *this; +} + namespace internal { template struct solve_retval, Rhs> @@ -481,4 +587,6 @@ MatrixBase::ldlt() const return LDLT(derived()); } +} // end namespace Eigen + #endif // EIGEN_LDLT_H diff --git a/extern/Eigen3/Eigen/src/Cholesky/LLT.h b/extern/Eigen3/Eigen/src/Cholesky/LLT.h index 3bb76b5787f..41d14e532f1 100644 --- a/extern/Eigen3/Eigen/src/Cholesky/LLT.h +++ b/extern/Eigen3/Eigen/src/Cholesky/LLT.h @@ -3,39 +3,28 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_LLT_H #define EIGEN_LLT_H +namespace Eigen { + namespace internal{ template struct LLT_Traits; } -/** \ingroup cholesky_Module +/** \ingroup Cholesky_Module * * \class LLT * * \brief Standard Cholesky decomposition (LL^T) of a matrix and associated features * * \param MatrixType the type of the matrix of which we are computing the LL^T Cholesky decomposition + * \param UpLo the triangular part that will be used for the decompositon: Lower (default) or Upper. + * The other triangular part won't be read. * * This class performs a LL^T Cholesky decomposition of a symmetric, positive definite * matrix A such that A = LL^* = U^*U, where L is lower triangular. @@ -49,6 +38,9 @@ template struct LLT_Traits; * use LDLT instead for the semidefinite case. Also, do not use a Cholesky decomposition to determine whether a system of equations * has a solution. * + * Example: \include LLT_example.cpp + * Output: \verbinclude LLT_example.out + * * \sa MatrixBase::llt(), class LDLT */ /* HEY THIS DOX IS DISABLED BECAUSE THERE's A BUG EITHER HERE OR IN LDLT ABOUT THAT (OR BOTH) @@ -178,6 +170,9 @@ template class LLT inline Index rows() const { return m_matrix.rows(); } inline Index cols() const { return m_matrix.cols(); } + template + LLT rankUpdate(const VectorType& vec, const RealScalar& sigma = 1); + protected: /** \internal * Used to compute and store L @@ -190,16 +185,85 @@ template class LLT namespace internal { -template struct llt_inplace; +template struct llt_inplace; -template<> struct llt_inplace +template +static typename MatrixType::Index llt_rank_update_lower(MatrixType& mat, const VectorType& vec, const typename MatrixType::RealScalar& sigma) { + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef typename MatrixType::Index Index; + typedef typename MatrixType::ColXpr ColXpr; + typedef typename internal::remove_all::type ColXprCleaned; + typedef typename ColXprCleaned::SegmentReturnType ColXprSegment; + typedef Matrix TempVectorType; + typedef typename TempVectorType::SegmentReturnType TempVecSegment; + + int n = mat.cols(); + eigen_assert(mat.rows()==n && vec.size()==n); + + TempVectorType temp; + + if(sigma>0) + { + // This version is based on Givens rotations. + // It is faster than the other one below, but only works for updates, + // i.e., for sigma > 0 + temp = sqrt(sigma) * vec; + + for(int i=0; i g; + g.makeGivens(mat(i,i), -temp(i), &mat(i,i)); + + int rs = n-i-1; + if(rs>0) + { + ColXprSegment x(mat.col(i).tail(rs)); + TempVecSegment y(temp.tail(rs)); + apply_rotation_in_the_plane(x, y, g); + } + } + } + else + { + temp = vec; + RealScalar beta = 1; + for(int j=0; j struct llt_inplace +{ + typedef typename NumTraits::Real RealScalar; template static typename MatrixType::Index unblocked(MatrixType& mat) { typedef typename MatrixType::Index Index; - typedef typename MatrixType::Scalar Scalar; - typedef typename MatrixType::RealScalar RealScalar; eigen_assert(mat.rows()==mat.cols()); const Index size = mat.rows(); @@ -254,21 +318,35 @@ template<> struct llt_inplace } return -1; } -}; -template<> struct llt_inplace + template + static typename MatrixType::Index rankUpdate(MatrixType& mat, const VectorType& vec, const RealScalar& sigma) + { + return Eigen::internal::llt_rank_update_lower(mat, vec, sigma); + } +}; + +template struct llt_inplace { + typedef typename NumTraits::Real RealScalar; + template static EIGEN_STRONG_INLINE typename MatrixType::Index unblocked(MatrixType& mat) { Transpose matt(mat); - return llt_inplace::unblocked(matt); + return llt_inplace::unblocked(matt); } template static EIGEN_STRONG_INLINE typename MatrixType::Index blocked(MatrixType& mat) { Transpose matt(mat); - return llt_inplace::blocked(matt); + return llt_inplace::blocked(matt); + } + template + static typename MatrixType::Index rankUpdate(MatrixType& mat, const VectorType& vec, const RealScalar& sigma) + { + Transpose matt(mat); + return llt_inplace::rankUpdate(matt, vec.conjugate(), sigma); } }; @@ -276,33 +354,35 @@ template struct LLT_Traits { typedef const TriangularView MatrixL; typedef const TriangularView MatrixU; - inline static MatrixL getL(const MatrixType& m) { return m; } - inline static MatrixU getU(const MatrixType& m) { return m.adjoint(); } + static inline MatrixL getL(const MatrixType& m) { return m; } + static inline MatrixU getU(const MatrixType& m) { return m.adjoint(); } static bool inplace_decomposition(MatrixType& m) - { return llt_inplace::blocked(m)==-1; } + { return llt_inplace::blocked(m)==-1; } }; template struct LLT_Traits { typedef const TriangularView MatrixL; typedef const TriangularView MatrixU; - inline static MatrixL getL(const MatrixType& m) { return m.adjoint(); } - inline static MatrixU getU(const MatrixType& m) { return m; } + static inline MatrixL getL(const MatrixType& m) { return m.adjoint(); } + static inline MatrixU getU(const MatrixType& m) { return m; } static bool inplace_decomposition(MatrixType& m) - { return llt_inplace::blocked(m)==-1; } + { return llt_inplace::blocked(m)==-1; } }; } // end namespace internal /** Computes / recomputes the Cholesky decomposition A = LL^* = U^*U of \a matrix - * * * \returns a reference to *this + * + * Example: \include TutorialLinAlgComputeTwice.cpp + * Output: \verbinclude TutorialLinAlgComputeTwice.out */ template LLT& LLT::compute(const MatrixType& a) { - assert(a.rows()==a.cols()); + eigen_assert(a.rows()==a.cols()); const Index size = a.rows(); m_matrix.resize(size, size); m_matrix = a; @@ -314,6 +394,26 @@ LLT& LLT::compute(const MatrixType& a) return *this; } +/** Performs a rank one update (or dowdate) of the current decomposition. + * If A = LL^* before the rank one update, + * then after it we have LL^* = A + sigma * v v^* where \a v must be a vector + * of same dimension. + */ +template +template +LLT<_MatrixType,_UpLo> LLT<_MatrixType,_UpLo>::rankUpdate(const VectorType& v, const RealScalar& sigma) +{ + EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorType); + eigen_assert(v.size()==m_matrix.cols()); + eigen_assert(m_isInitialized); + if(internal::llt_inplace::rankUpdate(m_matrix,v,sigma)>=0) + m_info = NumericalIssue; + else + m_info = Success; + + return *this; +} + namespace internal { template struct solve_retval, Rhs> @@ -383,4 +483,6 @@ SelfAdjointView::llt() const return LLT(m_matrix); } +} // end namespace Eigen + #endif // EIGEN_LLT_H diff --git a/extern/Eigen3/Eigen/src/Cholesky/LLT_MKL.h b/extern/Eigen3/Eigen/src/Cholesky/LLT_MKL.h new file mode 100644 index 00000000000..64daa445cf7 --- /dev/null +++ b/extern/Eigen3/Eigen/src/Cholesky/LLT_MKL.h @@ -0,0 +1,102 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + 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 Intel Corporation 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. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL + * LLt decomposition based on LAPACKE_?potrf function. + ******************************************************************************** +*/ + +#ifndef EIGEN_LLT_MKL_H +#define EIGEN_LLT_MKL_H + +#include "Eigen/src/Core/util/MKL_support.h" +#include + +namespace Eigen { + +namespace internal { + +template struct mkl_llt; + +#define EIGEN_MKL_LLT(EIGTYPE, MKLTYPE, MKLPREFIX) \ +template<> struct mkl_llt \ +{ \ + template \ + static inline typename MatrixType::Index potrf(MatrixType& m, char uplo) \ + { \ + lapack_int matrix_order; \ + lapack_int size, lda, info, StorageOrder; \ + EIGTYPE* a; \ + eigen_assert(m.rows()==m.cols()); \ + /* Set up parameters for ?potrf */ \ + size = m.rows(); \ + StorageOrder = MatrixType::Flags&RowMajorBit?RowMajor:ColMajor; \ + matrix_order = StorageOrder==RowMajor ? LAPACK_ROW_MAJOR : LAPACK_COL_MAJOR; \ + a = &(m.coeffRef(0,0)); \ + lda = m.outerStride(); \ +\ + info = LAPACKE_##MKLPREFIX##potrf( matrix_order, uplo, size, (MKLTYPE*)a, lda ); \ + info = (info==0) ? Success : NumericalIssue; \ + return info; \ + } \ +}; \ +template<> struct llt_inplace \ +{ \ + template \ + static typename MatrixType::Index blocked(MatrixType& m) \ + { \ + return mkl_llt::potrf(m, 'L'); \ + } \ + template \ + static typename MatrixType::Index rankUpdate(MatrixType& mat, const VectorType& vec, const typename MatrixType::RealScalar& sigma) \ + { return Eigen::internal::llt_rank_update_lower(mat, vec, sigma); } \ +}; \ +template<> struct llt_inplace \ +{ \ + template \ + static typename MatrixType::Index blocked(MatrixType& m) \ + { \ + return mkl_llt::potrf(m, 'U'); \ + } \ + template \ + static typename MatrixType::Index rankUpdate(MatrixType& mat, const VectorType& vec, const typename MatrixType::RealScalar& sigma) \ + { \ + Transpose matt(mat); \ + return llt_inplace::rankUpdate(matt, vec.conjugate(), sigma); \ + } \ +}; + +EIGEN_MKL_LLT(double, double, d) +EIGEN_MKL_LLT(float, float, s) +EIGEN_MKL_LLT(dcomplex, MKL_Complex16, z) +EIGEN_MKL_LLT(scomplex, MKL_Complex8, c) + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_LLT_MKL_H diff --git a/extern/Eigen3/Eigen/src/CholmodSupport/CholmodSupport.h b/extern/Eigen3/Eigen/src/CholmodSupport/CholmodSupport.h new file mode 100644 index 00000000000..37f142150ff --- /dev/null +++ b/extern/Eigen3/Eigen/src/CholmodSupport/CholmodSupport.h @@ -0,0 +1,579 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2010 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_CHOLMODSUPPORT_H +#define EIGEN_CHOLMODSUPPORT_H + +namespace Eigen { + +namespace internal { + +template +void cholmod_configure_matrix(CholmodType& mat) +{ + if (internal::is_same::value) + { + mat.xtype = CHOLMOD_REAL; + mat.dtype = CHOLMOD_SINGLE; + } + else if (internal::is_same::value) + { + mat.xtype = CHOLMOD_REAL; + mat.dtype = CHOLMOD_DOUBLE; + } + else if (internal::is_same >::value) + { + mat.xtype = CHOLMOD_COMPLEX; + mat.dtype = CHOLMOD_SINGLE; + } + else if (internal::is_same >::value) + { + mat.xtype = CHOLMOD_COMPLEX; + mat.dtype = CHOLMOD_DOUBLE; + } + else + { + eigen_assert(false && "Scalar type not supported by CHOLMOD"); + } +} + +} // namespace internal + +/** Wraps the Eigen sparse matrix \a mat into a Cholmod sparse matrix object. + * Note that the data are shared. + */ +template +cholmod_sparse viewAsCholmod(SparseMatrix<_Scalar,_Options,_Index>& mat) +{ + typedef SparseMatrix<_Scalar,_Options,_Index> MatrixType; + cholmod_sparse res; + res.nzmax = mat.nonZeros(); + res.nrow = mat.rows();; + res.ncol = mat.cols(); + res.p = mat.outerIndexPtr(); + res.i = mat.innerIndexPtr(); + res.x = mat.valuePtr(); + res.sorted = 1; + if(mat.isCompressed()) + { + res.packed = 1; + } + else + { + res.packed = 0; + res.nz = mat.innerNonZeroPtr(); + } + + res.dtype = 0; + res.stype = -1; + + if (internal::is_same<_Index,int>::value) + { + res.itype = CHOLMOD_INT; + } + else + { + eigen_assert(false && "Index type different than int is not supported yet"); + } + + // setup res.xtype + internal::cholmod_configure_matrix<_Scalar>(res); + + res.stype = 0; + + return res; +} + +template +const cholmod_sparse viewAsCholmod(const SparseMatrix<_Scalar,_Options,_Index>& mat) +{ + cholmod_sparse res = viewAsCholmod(mat.const_cast_derived()); + return res; +} + +/** Returns a view of the Eigen sparse matrix \a mat as Cholmod sparse matrix. + * The data are not copied but shared. */ +template +cholmod_sparse viewAsCholmod(const SparseSelfAdjointView, UpLo>& mat) +{ + cholmod_sparse res = viewAsCholmod(mat.matrix().const_cast_derived()); + + if(UpLo==Upper) res.stype = 1; + if(UpLo==Lower) res.stype = -1; + + return res; +} + +/** Returns a view of the Eigen \b dense matrix \a mat as Cholmod dense matrix. + * The data are not copied but shared. */ +template +cholmod_dense viewAsCholmod(MatrixBase& mat) +{ + EIGEN_STATIC_ASSERT((internal::traits::Flags&RowMajorBit)==0,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES); + typedef typename Derived::Scalar Scalar; + + cholmod_dense res; + res.nrow = mat.rows(); + res.ncol = mat.cols(); + res.nzmax = res.nrow * res.ncol; + res.d = Derived::IsVectorAtCompileTime ? mat.derived().size() : mat.derived().outerStride(); + res.x = mat.derived().data(); + res.z = 0; + + internal::cholmod_configure_matrix(res); + + return res; +} + +/** Returns a view of the Cholmod sparse matrix \a cm as an Eigen sparse matrix. + * The data are not copied but shared. */ +template +MappedSparseMatrix viewAsEigen(cholmod_sparse& cm) +{ + return MappedSparseMatrix + (cm.nrow, cm.ncol, reinterpret_cast(cm.p)[cm.ncol], + reinterpret_cast(cm.p), reinterpret_cast(cm.i),reinterpret_cast(cm.x) ); +} + +enum CholmodMode { + CholmodAuto, CholmodSimplicialLLt, CholmodSupernodalLLt, CholmodLDLt +}; + + +/** \ingroup CholmodSupport_Module + * \class CholmodBase + * \brief The base class for the direct Cholesky factorization of Cholmod + * \sa class CholmodSupernodalLLT, class CholmodSimplicialLDLT, class CholmodSimplicialLLT + */ +template +class CholmodBase : internal::noncopyable +{ + public: + typedef _MatrixType MatrixType; + enum { UpLo = _UpLo }; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef MatrixType CholMatrixType; + typedef typename MatrixType::Index Index; + + public: + + CholmodBase() + : m_cholmodFactor(0), m_info(Success), m_isInitialized(false) + { + cholmod_start(&m_cholmod); + } + + CholmodBase(const MatrixType& matrix) + : m_cholmodFactor(0), m_info(Success), m_isInitialized(false) + { + cholmod_start(&m_cholmod); + compute(matrix); + } + + ~CholmodBase() + { + if(m_cholmodFactor) + cholmod_free_factor(&m_cholmodFactor, &m_cholmod); + cholmod_finish(&m_cholmod); + } + + inline Index cols() const { return m_cholmodFactor->n; } + inline Index rows() const { return m_cholmodFactor->n; } + + Derived& derived() { return *static_cast(this); } + const Derived& derived() const { return *static_cast(this); } + + /** \brief Reports whether previous computation was successful. + * + * \returns \c Success if computation was succesful, + * \c NumericalIssue if the matrix.appears to be negative. + */ + ComputationInfo info() const + { + eigen_assert(m_isInitialized && "Decomposition is not initialized."); + return m_info; + } + + /** Computes the sparse Cholesky decomposition of \a matrix */ + Derived& compute(const MatrixType& matrix) + { + analyzePattern(matrix); + factorize(matrix); + return derived(); + } + + /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. + * + * \sa compute() + */ + template + inline const internal::solve_retval + solve(const MatrixBase& b) const + { + eigen_assert(m_isInitialized && "LLT is not initialized."); + eigen_assert(rows()==b.rows() + && "CholmodDecomposition::solve(): invalid number of rows of the right hand side matrix b"); + return internal::solve_retval(*this, b.derived()); + } + + /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. + * + * \sa compute() + */ + template + inline const internal::sparse_solve_retval + solve(const SparseMatrixBase& b) const + { + eigen_assert(m_isInitialized && "LLT is not initialized."); + eigen_assert(rows()==b.rows() + && "CholmodDecomposition::solve(): invalid number of rows of the right hand side matrix b"); + return internal::sparse_solve_retval(*this, b.derived()); + } + + /** Performs a symbolic decomposition on the sparcity of \a matrix. + * + * This function is particularly useful when solving for several problems having the same structure. + * + * \sa factorize() + */ + void analyzePattern(const MatrixType& matrix) + { + if(m_cholmodFactor) + { + cholmod_free_factor(&m_cholmodFactor, &m_cholmod); + m_cholmodFactor = 0; + } + cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView()); + m_cholmodFactor = cholmod_analyze(&A, &m_cholmod); + + this->m_isInitialized = true; + this->m_info = Success; + m_analysisIsOk = true; + m_factorizationIsOk = false; + } + + /** Performs a numeric decomposition of \a matrix + * + * The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed. + * + * \sa analyzePattern() + */ + void factorize(const MatrixType& matrix) + { + eigen_assert(m_analysisIsOk && "You must first call analyzePattern()"); + cholmod_sparse A = viewAsCholmod(matrix.template selfadjointView()); + cholmod_factorize(&A, m_cholmodFactor, &m_cholmod); + + this->m_info = Success; + m_factorizationIsOk = true; + } + + /** Returns a reference to the Cholmod's configuration structure to get a full control over the performed operations. + * See the Cholmod user guide for details. */ + cholmod_common& cholmod() { return m_cholmod; } + + #ifndef EIGEN_PARSED_BY_DOXYGEN + /** \internal */ + template + void _solve(const MatrixBase &b, MatrixBase &dest) const + { + eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()"); + const Index size = m_cholmodFactor->n; + eigen_assert(size==b.rows()); + + // note: cd stands for Cholmod Dense + cholmod_dense b_cd = viewAsCholmod(b.const_cast_derived()); + cholmod_dense* x_cd = cholmod_solve(CHOLMOD_A, m_cholmodFactor, &b_cd, &m_cholmod); + if(!x_cd) + { + this->m_info = NumericalIssue; + } + // TODO optimize this copy by swapping when possible (be carreful with alignment, etc.) + dest = Matrix::Map(reinterpret_cast(x_cd->x),b.rows(),b.cols()); + cholmod_free_dense(&x_cd, &m_cholmod); + } + + /** \internal */ + template + void _solve(const SparseMatrix &b, SparseMatrix &dest) const + { + eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()"); + const Index size = m_cholmodFactor->n; + eigen_assert(size==b.rows()); + + // note: cs stands for Cholmod Sparse + cholmod_sparse b_cs = viewAsCholmod(b); + cholmod_sparse* x_cs = cholmod_spsolve(CHOLMOD_A, m_cholmodFactor, &b_cs, &m_cholmod); + if(!x_cs) + { + this->m_info = NumericalIssue; + } + // TODO optimize this copy by swapping when possible (be carreful with alignment, etc.) + dest = viewAsEigen(*x_cs); + cholmod_free_sparse(&x_cs, &m_cholmod); + } + #endif // EIGEN_PARSED_BY_DOXYGEN + + template + void dumpMemory(Stream& s) + {} + + protected: + mutable cholmod_common m_cholmod; + cholmod_factor* m_cholmodFactor; + mutable ComputationInfo m_info; + bool m_isInitialized; + int m_factorizationIsOk; + int m_analysisIsOk; +}; + +/** \ingroup CholmodSupport_Module + * \class CholmodSimplicialLLT + * \brief A simplicial direct Cholesky (LLT) factorization and solver based on Cholmod + * + * This class allows to solve for A.X = B sparse linear problems via a simplicial LL^T Cholesky factorization + * using the Cholmod library. + * This simplicial variant is equivalent to Eigen's built-in SimplicialLLT class. Thefore, it has little practical interest. + * The sparse matrix A must be selfajoint and positive definite. The vectors or matrices + * X and B can be either dense or sparse. + * + * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower + * or Upper. Default is Lower. + * + * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed. + * + * \sa \ref TutorialSparseDirectSolvers, class CholmodSupernodalLLT, class SimplicialLLT + */ +template +class CholmodSimplicialLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLLT<_MatrixType, _UpLo> > +{ + typedef CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLLT> Base; + using Base::m_cholmod; + + public: + + typedef _MatrixType MatrixType; + + CholmodSimplicialLLT() : Base() { init(); } + + CholmodSimplicialLLT(const MatrixType& matrix) : Base() + { + init(); + compute(matrix); + } + + ~CholmodSimplicialLLT() {} + protected: + void init() + { + m_cholmod.final_asis = 0; + m_cholmod.supernodal = CHOLMOD_SIMPLICIAL; + m_cholmod.final_ll = 1; + } +}; + + +/** \ingroup CholmodSupport_Module + * \class CholmodSimplicialLDLT + * \brief A simplicial direct Cholesky (LDLT) factorization and solver based on Cholmod + * + * This class allows to solve for A.X = B sparse linear problems via a simplicial LDL^T Cholesky factorization + * using the Cholmod library. + * This simplicial variant is equivalent to Eigen's built-in SimplicialLDLT class. Thefore, it has little practical interest. + * The sparse matrix A must be selfajoint and positive definite. The vectors or matrices + * X and B can be either dense or sparse. + * + * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower + * or Upper. Default is Lower. + * + * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed. + * + * \sa \ref TutorialSparseDirectSolvers, class CholmodSupernodalLLT, class SimplicialLDLT + */ +template +class CholmodSimplicialLDLT : public CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT<_MatrixType, _UpLo> > +{ + typedef CholmodBase<_MatrixType, _UpLo, CholmodSimplicialLDLT> Base; + using Base::m_cholmod; + + public: + + typedef _MatrixType MatrixType; + + CholmodSimplicialLDLT() : Base() { init(); } + + CholmodSimplicialLDLT(const MatrixType& matrix) : Base() + { + init(); + compute(matrix); + } + + ~CholmodSimplicialLDLT() {} + protected: + void init() + { + m_cholmod.final_asis = 1; + m_cholmod.supernodal = CHOLMOD_SIMPLICIAL; + } +}; + +/** \ingroup CholmodSupport_Module + * \class CholmodSupernodalLLT + * \brief A supernodal Cholesky (LLT) factorization and solver based on Cholmod + * + * This class allows to solve for A.X = B sparse linear problems via a supernodal LL^T Cholesky factorization + * using the Cholmod library. + * This supernodal variant performs best on dense enough problems, e.g., 3D FEM, or very high order 2D FEM. + * The sparse matrix A must be selfajoint and positive definite. The vectors or matrices + * X and B can be either dense or sparse. + * + * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower + * or Upper. Default is Lower. + * + * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed. + * + * \sa \ref TutorialSparseDirectSolvers + */ +template +class CholmodSupernodalLLT : public CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT<_MatrixType, _UpLo> > +{ + typedef CholmodBase<_MatrixType, _UpLo, CholmodSupernodalLLT> Base; + using Base::m_cholmod; + + public: + + typedef _MatrixType MatrixType; + + CholmodSupernodalLLT() : Base() { init(); } + + CholmodSupernodalLLT(const MatrixType& matrix) : Base() + { + init(); + compute(matrix); + } + + ~CholmodSupernodalLLT() {} + protected: + void init() + { + m_cholmod.final_asis = 1; + m_cholmod.supernodal = CHOLMOD_SUPERNODAL; + } +}; + +/** \ingroup CholmodSupport_Module + * \class CholmodDecomposition + * \brief A general Cholesky factorization and solver based on Cholmod + * + * This class allows to solve for A.X = B sparse linear problems via a LL^T or LDL^T Cholesky factorization + * using the Cholmod library. The sparse matrix A must be selfajoint and positive definite. The vectors or matrices + * X and B can be either dense or sparse. + * + * This variant permits to change the underlying Cholesky method at runtime. + * On the other hand, it does not provide access to the result of the factorization. + * The default is to let Cholmod automatically choose between a simplicial and supernodal factorization. + * + * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower + * or Upper. Default is Lower. + * + * This class supports all kind of SparseMatrix<>: row or column major; upper, lower, or both; compressed or non compressed. + * + * \sa \ref TutorialSparseDirectSolvers + */ +template +class CholmodDecomposition : public CholmodBase<_MatrixType, _UpLo, CholmodDecomposition<_MatrixType, _UpLo> > +{ + typedef CholmodBase<_MatrixType, _UpLo, CholmodDecomposition> Base; + using Base::m_cholmod; + + public: + + typedef _MatrixType MatrixType; + + CholmodDecomposition() : Base() { init(); } + + CholmodDecomposition(const MatrixType& matrix) : Base() + { + init(); + compute(matrix); + } + + ~CholmodDecomposition() {} + + void setMode(CholmodMode mode) + { + switch(mode) + { + case CholmodAuto: + m_cholmod.final_asis = 1; + m_cholmod.supernodal = CHOLMOD_AUTO; + break; + case CholmodSimplicialLLt: + m_cholmod.final_asis = 0; + m_cholmod.supernodal = CHOLMOD_SIMPLICIAL; + m_cholmod.final_ll = 1; + break; + case CholmodSupernodalLLt: + m_cholmod.final_asis = 1; + m_cholmod.supernodal = CHOLMOD_SUPERNODAL; + break; + case CholmodLDLt: + m_cholmod.final_asis = 1; + m_cholmod.supernodal = CHOLMOD_SIMPLICIAL; + break; + default: + break; + } + } + protected: + void init() + { + m_cholmod.final_asis = 1; + m_cholmod.supernodal = CHOLMOD_AUTO; + } +}; + +namespace internal { + +template +struct solve_retval, Rhs> + : solve_retval_base, Rhs> +{ + typedef CholmodBase<_MatrixType,_UpLo,Derived> Dec; + EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs) + + template void evalTo(Dest& dst) const + { + dec()._solve(rhs(),dst); + } +}; + +template +struct sparse_solve_retval, Rhs> + : sparse_solve_retval_base, Rhs> +{ + typedef CholmodBase<_MatrixType,_UpLo,Derived> Dec; + EIGEN_MAKE_SPARSE_SOLVE_HELPERS(Dec,Rhs) + + template void evalTo(Dest& dst) const + { + dec()._solve(rhs(),dst); + } +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_CHOLMODSUPPORT_H diff --git a/extern/Eigen3/Eigen/src/Core/Array.h b/extern/Eigen3/Eigen/src/Core/Array.h index a11fb1b53d5..aaa38997838 100644 --- a/extern/Eigen3/Eigen/src/Core/Array.h +++ b/extern/Eigen3/Eigen/src/Core/Array.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_ARRAY_H #define EIGEN_ARRAY_H +namespace Eigen { + /** \class Array * \ingroup Core_Module * @@ -316,5 +303,6 @@ EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(d) \ EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(cf) \ EIGEN_USING_ARRAY_TYPEDEFS_FOR_TYPE(cd) +} // end namespace Eigen #endif // EIGEN_ARRAY_H diff --git a/extern/Eigen3/Eigen/src/Core/ArrayBase.h b/extern/Eigen3/Eigen/src/Core/ArrayBase.h index 9399ac3d15c..004b117c933 100644 --- a/extern/Eigen3/Eigen/src/Core/ArrayBase.h +++ b/extern/Eigen3/Eigen/src/Core/ArrayBase.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_ARRAYBASE_H #define EIGEN_ARRAYBASE_H +namespace Eigen { + template class MatrixWrapper; /** \class ArrayBase @@ -159,7 +146,7 @@ template class ArrayBase /** \returns an \link MatrixBase Matrix \endlink expression of this array * \sa MatrixBase::array() */ MatrixWrapper matrix() { return derived(); } - const MatrixWrapper matrix() const { return derived(); } + const MatrixWrapper matrix() const { return derived(); } // template // inline void evalTo(Dest& dst) const { dst = matrix(); } @@ -174,10 +161,10 @@ template class ArrayBase protected: // mixing arrays and matrices is not legal template Derived& operator+=(const MatrixBase& ) - {EIGEN_STATIC_ASSERT(sizeof(typename OtherDerived::Scalar)==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES);} + {EIGEN_STATIC_ASSERT(std::ptrdiff_t(sizeof(typename OtherDerived::Scalar))==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES); return *this;} // mixing arrays and matrices is not legal template Derived& operator-=(const MatrixBase& ) - {EIGEN_STATIC_ASSERT(sizeof(typename OtherDerived::Scalar)==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES);} + {EIGEN_STATIC_ASSERT(std::ptrdiff_t(sizeof(typename OtherDerived::Scalar))==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES); return *this;} }; /** replaces \c *this by \c *this - \a other. @@ -236,4 +223,6 @@ ArrayBase::operator/=(const ArrayBase& other) return derived(); } +} // end namespace Eigen + #endif // EIGEN_ARRAYBASE_H diff --git a/extern/Eigen3/Eigen/src/Core/ArrayWrapper.h b/extern/Eigen3/Eigen/src/Core/ArrayWrapper.h index 07f082e1edc..87af7fda937 100644 --- a/extern/Eigen3/Eigen/src/Core/ArrayWrapper.h +++ b/extern/Eigen3/Eigen/src/Core/ArrayWrapper.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_ARRAYWRAPPER_H #define EIGEN_ARRAYWRAPPER_H +namespace Eigen { + /** \class ArrayWrapper * \ingroup Core_Module * @@ -61,7 +48,7 @@ class ArrayWrapper : public ArrayBase > typedef typename internal::nested::type NestedExpressionType; - inline ArrayWrapper(const ExpressionType& matrix) : m_expression(matrix) {} + inline ArrayWrapper(ExpressionType& matrix) : m_expression(matrix) {} inline Index rows() const { return m_expression.rows(); } inline Index cols() const { return m_expression.cols(); } @@ -71,7 +58,7 @@ class ArrayWrapper : public ArrayBase > inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); } inline const Scalar* data() const { return m_expression.data(); } - inline const CoeffReturnType coeff(Index row, Index col) const + inline CoeffReturnType coeff(Index row, Index col) const { return m_expression.coeff(row, col); } @@ -86,7 +73,7 @@ class ArrayWrapper : public ArrayBase > return m_expression.const_cast_derived().coeffRef(row, col); } - inline const CoeffReturnType coeff(Index index) const + inline CoeffReturnType coeff(Index index) const { return m_expression.coeff(index); } @@ -128,8 +115,14 @@ class ArrayWrapper : public ArrayBase > template inline void evalTo(Dest& dst) const { dst = m_expression; } + const typename internal::remove_all::type& + nestedExpression() const + { + return m_expression; + } + protected: - const NestedExpressionType m_expression; + NestedExpressionType m_expression; }; /** \class MatrixWrapper @@ -168,7 +161,7 @@ class MatrixWrapper : public MatrixBase > typedef typename internal::nested::type NestedExpressionType; - inline MatrixWrapper(const ExpressionType& matrix) : m_expression(matrix) {} + inline MatrixWrapper(ExpressionType& matrix) : m_expression(matrix) {} inline Index rows() const { return m_expression.rows(); } inline Index cols() const { return m_expression.cols(); } @@ -178,7 +171,7 @@ class MatrixWrapper : public MatrixBase > inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); } inline const Scalar* data() const { return m_expression.data(); } - inline const CoeffReturnType coeff(Index row, Index col) const + inline CoeffReturnType coeff(Index row, Index col) const { return m_expression.coeff(row, col); } @@ -193,7 +186,7 @@ class MatrixWrapper : public MatrixBase > return m_expression.derived().coeffRef(row, col); } - inline const CoeffReturnType coeff(Index index) const + inline CoeffReturnType coeff(Index index) const { return m_expression.coeff(index); } @@ -232,8 +225,16 @@ class MatrixWrapper : public MatrixBase > m_expression.const_cast_derived().template writePacket(index, x); } + const typename internal::remove_all::type& + nestedExpression() const + { + return m_expression; + } + protected: - const NestedExpressionType m_expression; + NestedExpressionType m_expression; }; +} // end namespace Eigen + #endif // EIGEN_ARRAYWRAPPER_H diff --git a/extern/Eigen3/Eigen/src/Core/Assign.h b/extern/Eigen3/Eigen/src/Core/Assign.h index 3a17152f043..cd29a88f0da 100644 --- a/extern/Eigen3/Eigen/src/Core/Assign.h +++ b/extern/Eigen3/Eigen/src/Core/Assign.h @@ -5,28 +5,15 @@ // Copyright (C) 2006-2010 Benoit Jacob // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_ASSIGN_H #define EIGEN_ASSIGN_H +namespace Eigen { + namespace internal { /*************************************************************************** @@ -152,7 +139,7 @@ struct assign_DefaultTraversal_CompleteUnrolling inner = Index % Derived1::InnerSizeAtCompileTime }; - EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src) + static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) { dst.copyCoeffByOuterInner(outer, inner, src); assign_DefaultTraversal_CompleteUnrolling::run(dst, src); @@ -162,13 +149,13 @@ struct assign_DefaultTraversal_CompleteUnrolling template struct assign_DefaultTraversal_CompleteUnrolling { - EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &) {} + static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &) {} }; template struct assign_DefaultTraversal_InnerUnrolling { - EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src, int outer) + static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src, int outer) { dst.copyCoeffByOuterInner(outer, Index, src); assign_DefaultTraversal_InnerUnrolling::run(dst, src, outer); @@ -178,7 +165,7 @@ struct assign_DefaultTraversal_InnerUnrolling template struct assign_DefaultTraversal_InnerUnrolling { - EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &, int) {} + static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &, int) {} }; /*********************** @@ -188,7 +175,7 @@ struct assign_DefaultTraversal_InnerUnrolling template struct assign_LinearTraversal_CompleteUnrolling { - EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src) + static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) { dst.copyCoeff(Index, src); assign_LinearTraversal_CompleteUnrolling::run(dst, src); @@ -198,7 +185,7 @@ struct assign_LinearTraversal_CompleteUnrolling template struct assign_LinearTraversal_CompleteUnrolling { - EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &) {} + static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &) {} }; /************************** @@ -214,7 +201,7 @@ struct assign_innervec_CompleteUnrolling JointAlignment = assign_traits::JointAlignment }; - EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src) + static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) { dst.template copyPacketByOuterInner(outer, inner, src); assign_innervec_CompleteUnrolling struct assign_innervec_CompleteUnrolling { - EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &) {} + static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &) {} }; template struct assign_innervec_InnerUnrolling { - EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src, int outer) + static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src, int outer) { dst.template copyPacketByOuterInner(outer, Index, src); assign_innervec_InnerUnrolling struct assign_innervec_InnerUnrolling { - EIGEN_STRONG_INLINE static void run(Derived1 &, const Derived2 &, int) {} + static EIGEN_STRONG_INLINE void run(Derived1 &, const Derived2 &, int) {} }; /*************************************************************************** @@ -251,24 +238,25 @@ struct assign_innervec_InnerUnrolling template::Traversal, - int Unrolling = assign_traits::Unrolling> + int Unrolling = assign_traits::Unrolling, + int Version = Specialized> struct assign_impl; /************************ *** Default traversal *** ************************/ -template -struct assign_impl +template +struct assign_impl { - inline static void run(Derived1 &, const Derived2 &) { } + static inline void run(Derived1 &, const Derived2 &) { } }; -template -struct assign_impl +template +struct assign_impl { typedef typename Derived1::Index Index; - inline static void run(Derived1 &dst, const Derived2 &src) + static inline void run(Derived1 &dst, const Derived2 &src) { const Index innerSize = dst.innerSize(); const Index outerSize = dst.outerSize(); @@ -278,21 +266,21 @@ struct assign_impl } }; -template -struct assign_impl +template +struct assign_impl { - EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src) + static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) { assign_DefaultTraversal_CompleteUnrolling ::run(dst, src); } }; -template -struct assign_impl +template +struct assign_impl { typedef typename Derived1::Index Index; - EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src) + static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) { const Index outerSize = dst.outerSize(); for(Index outer = 0; outer < outerSize; ++outer) @@ -305,11 +293,11 @@ struct assign_impl *** Linear traversal *** ***********************/ -template -struct assign_impl +template +struct assign_impl { typedef typename Derived1::Index Index; - inline static void run(Derived1 &dst, const Derived2 &src) + static inline void run(Derived1 &dst, const Derived2 &src) { const Index size = dst.size(); for(Index i = 0; i < size; ++i) @@ -317,10 +305,10 @@ struct assign_impl } }; -template -struct assign_impl +template +struct assign_impl { - EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src) + static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) { assign_LinearTraversal_CompleteUnrolling ::run(dst, src); @@ -331,11 +319,11 @@ struct assign_impl *** Inner vectorization *** **************************/ -template -struct assign_impl +template +struct assign_impl { typedef typename Derived1::Index Index; - inline static void run(Derived1 &dst, const Derived2 &src) + static inline void run(Derived1 &dst, const Derived2 &src) { const Index innerSize = dst.innerSize(); const Index outerSize = dst.outerSize(); @@ -346,21 +334,21 @@ struct assign_impl } }; -template -struct assign_impl +template +struct assign_impl { - EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src) + static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) { assign_innervec_CompleteUnrolling ::run(dst, src); } }; -template -struct assign_impl +template +struct assign_impl { typedef typename Derived1::Index Index; - EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src) + static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) { const Index outerSize = dst.outerSize(); for(Index outer = 0; outer < outerSize; ++outer) @@ -398,11 +386,11 @@ struct unaligned_assign_impl } }; -template -struct assign_impl +template +struct assign_impl { typedef typename Derived1::Index Index; - EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src) + static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) { const Index size = dst.size(); typedef packet_traits PacketTraits; @@ -412,7 +400,7 @@ struct assign_impl srcAlignment = assign_traits::JointAlignment }; const Index alignedStart = assign_traits::DstIsAligned ? 0 - : first_aligned(&dst.coeffRef(0), size); + : internal::first_aligned(&dst.coeffRef(0), size); const Index alignedEnd = alignedStart + ((size-alignedStart)/packetSize)*packetSize; unaligned_assign_impl::DstIsAligned!=0>::run(src,dst,0,alignedStart); @@ -426,11 +414,11 @@ struct assign_impl } }; -template -struct assign_impl +template +struct assign_impl { typedef typename Derived1::Index Index; - EIGEN_STRONG_INLINE static void run(Derived1 &dst, const Derived2 &src) + static EIGEN_STRONG_INLINE void run(Derived1 &dst, const Derived2 &src) { enum { size = Derived1::SizeAtCompileTime, packetSize = packet_traits::size, @@ -445,11 +433,11 @@ struct assign_impl -struct assign_impl +template +struct assign_impl { typedef typename Derived1::Index Index; - inline static void run(Derived1 &dst, const Derived2 &src) + static inline void run(Derived1 &dst, const Derived2 &src) { typedef packet_traits PacketTraits; enum { @@ -463,7 +451,7 @@ struct assign_impl const Index outerSize = dst.outerSize(); const Index alignedStep = alignable ? (packetSize - dst.outerStride() % packetSize) & packetAlignedMask : 0; Index alignedStart = ((!alignable) || assign_traits::DstIsAligned) ? 0 - : first_aligned(&dst.coeffRef(0,0), innerSize); + : internal::first_aligned(&dst.coeffRef(0,0), innerSize); for(Index outer = 0; outer < outerSize; ++outer) { @@ -531,19 +519,19 @@ struct assign_selector; template struct assign_selector { - EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.derived()); } + static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.derived()); } }; template struct assign_selector { - EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.eval()); } + static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.eval()); } }; template struct assign_selector { - EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose()); } + static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose()); } }; template struct assign_selector { - EIGEN_STRONG_INLINE static Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose().eval()); } + static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose().eval()); } }; } // end namespace internal @@ -590,4 +578,6 @@ EIGEN_STRONG_INLINE Derived& MatrixBase::operator=(const ReturnByValue< return derived(); } +} // end namespace Eigen + #endif // EIGEN_ASSIGN_H diff --git a/extern/Eigen3/Eigen/src/Core/Assign_MKL.h b/extern/Eigen3/Eigen/src/Core/Assign_MKL.h new file mode 100644 index 00000000000..428c6367b92 --- /dev/null +++ b/extern/Eigen3/Eigen/src/Core/Assign_MKL.h @@ -0,0 +1,224 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + 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 Intel Corporation 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. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL + * MKL VML support for coefficient-wise unary Eigen expressions like a=b.sin() + ******************************************************************************** +*/ + +#ifndef EIGEN_ASSIGN_VML_H +#define EIGEN_ASSIGN_VML_H + +namespace Eigen { + +namespace internal { + +template struct vml_call +{ enum { IsSupported = 0 }; }; + +template +class vml_assign_traits +{ + private: + enum { + DstHasDirectAccess = Dst::Flags & DirectAccessBit, + SrcHasDirectAccess = Src::Flags & DirectAccessBit, + + StorageOrdersAgree = (int(Dst::IsRowMajor) == int(Src::IsRowMajor)), + InnerSize = int(Dst::IsVectorAtCompileTime) ? int(Dst::SizeAtCompileTime) + : int(Dst::Flags)&RowMajorBit ? int(Dst::ColsAtCompileTime) + : int(Dst::RowsAtCompileTime), + InnerMaxSize = int(Dst::IsVectorAtCompileTime) ? int(Dst::MaxSizeAtCompileTime) + : int(Dst::Flags)&RowMajorBit ? int(Dst::MaxColsAtCompileTime) + : int(Dst::MaxRowsAtCompileTime), + MaxSizeAtCompileTime = Dst::SizeAtCompileTime, + + MightEnableVml = vml_call::IsSupported && StorageOrdersAgree && DstHasDirectAccess && SrcHasDirectAccess + && Src::InnerStrideAtCompileTime==1 && Dst::InnerStrideAtCompileTime==1, + MightLinearize = MightEnableVml && (int(Dst::Flags) & int(Src::Flags) & LinearAccessBit), + VmlSize = MightLinearize ? MaxSizeAtCompileTime : InnerMaxSize, + LargeEnough = VmlSize==Dynamic || VmlSize>=EIGEN_MKL_VML_THRESHOLD, + MayEnableVml = MightEnableVml && LargeEnough, + MayLinearize = MayEnableVml && MightLinearize + }; + public: + enum { + Traversal = MayLinearize ? LinearVectorizedTraversal + : MayEnableVml ? InnerVectorizedTraversal + : DefaultTraversal + }; +}; + +template::Traversal > +struct vml_assign_impl + : assign_impl,Traversal,Unrolling,BuiltIn> +{ +}; + +template +struct vml_assign_impl +{ + typedef typename Derived1::Scalar Scalar; + typedef typename Derived1::Index Index; + static inline void run(Derived1& dst, const CwiseUnaryOp& src) + { + // in case we want to (or have to) skip VML at runtime we can call: + // assign_impl,Traversal,Unrolling,BuiltIn>::run(dst,src); + const Index innerSize = dst.innerSize(); + const Index outerSize = dst.outerSize(); + for(Index outer = 0; outer < outerSize; ++outer) { + const Scalar *src_ptr = src.IsRowMajor ? &(src.nestedExpression().coeffRef(outer,0)) : + &(src.nestedExpression().coeffRef(0, outer)); + Scalar *dst_ptr = dst.IsRowMajor ? &(dst.coeffRef(outer,0)) : &(dst.coeffRef(0, outer)); + vml_call::run(src.functor(), innerSize, src_ptr, dst_ptr ); + } + } +}; + +template +struct vml_assign_impl +{ + static inline void run(Derived1& dst, const CwiseUnaryOp& src) + { + // in case we want to (or have to) skip VML at runtime we can call: + // assign_impl,Traversal,Unrolling,BuiltIn>::run(dst,src); + vml_call::run(src.functor(), dst.size(), src.nestedExpression().data(), dst.data() ); + } +}; + +// Macroses + +#define EIGEN_MKL_VML_SPECIALIZE_ASSIGN(TRAVERSAL,UNROLLING) \ + template \ + struct assign_impl, TRAVERSAL, UNROLLING, Specialized> { \ + static inline void run(Derived1 &dst, const Eigen::CwiseUnaryOp &src) { \ + vml_assign_impl::run(dst, src); \ + } \ + }; + +EIGEN_MKL_VML_SPECIALIZE_ASSIGN(DefaultTraversal,NoUnrolling) +EIGEN_MKL_VML_SPECIALIZE_ASSIGN(DefaultTraversal,CompleteUnrolling) +EIGEN_MKL_VML_SPECIALIZE_ASSIGN(DefaultTraversal,InnerUnrolling) +EIGEN_MKL_VML_SPECIALIZE_ASSIGN(LinearTraversal,NoUnrolling) +EIGEN_MKL_VML_SPECIALIZE_ASSIGN(LinearTraversal,CompleteUnrolling) +EIGEN_MKL_VML_SPECIALIZE_ASSIGN(InnerVectorizedTraversal,NoUnrolling) +EIGEN_MKL_VML_SPECIALIZE_ASSIGN(InnerVectorizedTraversal,CompleteUnrolling) +EIGEN_MKL_VML_SPECIALIZE_ASSIGN(InnerVectorizedTraversal,InnerUnrolling) +EIGEN_MKL_VML_SPECIALIZE_ASSIGN(LinearVectorizedTraversal,CompleteUnrolling) +EIGEN_MKL_VML_SPECIALIZE_ASSIGN(LinearVectorizedTraversal,NoUnrolling) +EIGEN_MKL_VML_SPECIALIZE_ASSIGN(SliceVectorizedTraversal,NoUnrolling) + + +#if !defined (EIGEN_FAST_MATH) || (EIGEN_FAST_MATH != 1) +#define EIGEN_MKL_VML_MODE VML_HA +#else +#define EIGEN_MKL_VML_MODE VML_LA +#endif + +#define EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, VMLOP, EIGENTYPE, VMLTYPE) \ + template<> struct vml_call< scalar_##EIGENOP##_op > { \ + enum { IsSupported = 1 }; \ + static inline void run( const scalar_##EIGENOP##_op& /*func*/, \ + int size, const EIGENTYPE* src, EIGENTYPE* dst) { \ + VMLOP(size, (const VMLTYPE*)src, (VMLTYPE*)dst); \ + } \ + }; + +#define EIGEN_MKL_VML_DECLARE_UNARY_CALL_LA(EIGENOP, VMLOP, EIGENTYPE, VMLTYPE) \ + template<> struct vml_call< scalar_##EIGENOP##_op > { \ + enum { IsSupported = 1 }; \ + static inline void run( const scalar_##EIGENOP##_op& /*func*/, \ + int size, const EIGENTYPE* src, EIGENTYPE* dst) { \ + MKL_INT64 vmlMode = EIGEN_MKL_VML_MODE; \ + VMLOP(size, (const VMLTYPE*)src, (VMLTYPE*)dst, vmlMode); \ + } \ + }; + +#define EIGEN_MKL_VML_DECLARE_POW_CALL(EIGENOP, VMLOP, EIGENTYPE, VMLTYPE) \ + template<> struct vml_call< scalar_##EIGENOP##_op > { \ + enum { IsSupported = 1 }; \ + static inline void run( const scalar_##EIGENOP##_op& func, \ + int size, const EIGENTYPE* src, EIGENTYPE* dst) { \ + EIGENTYPE exponent = func.m_exponent; \ + MKL_INT64 vmlMode = EIGEN_MKL_VML_MODE; \ + VMLOP(&size, (const VMLTYPE*)src, (const VMLTYPE*)&exponent, \ + (VMLTYPE*)dst, &vmlMode); \ + } \ + }; + +#define EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(EIGENOP, VMLOP) \ + EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, vs##VMLOP, float, float) \ + EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, vd##VMLOP, double, double) + +#define EIGEN_MKL_VML_DECLARE_UNARY_CALLS_COMPLEX(EIGENOP, VMLOP) \ + EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, vc##VMLOP, scomplex, MKL_Complex8) \ + EIGEN_MKL_VML_DECLARE_UNARY_CALL(EIGENOP, vz##VMLOP, dcomplex, MKL_Complex16) + +#define EIGEN_MKL_VML_DECLARE_UNARY_CALLS(EIGENOP, VMLOP) \ + EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(EIGENOP, VMLOP) \ + EIGEN_MKL_VML_DECLARE_UNARY_CALLS_COMPLEX(EIGENOP, VMLOP) + + +#define EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL_LA(EIGENOP, VMLOP) \ + EIGEN_MKL_VML_DECLARE_UNARY_CALL_LA(EIGENOP, vms##VMLOP, float, float) \ + EIGEN_MKL_VML_DECLARE_UNARY_CALL_LA(EIGENOP, vmd##VMLOP, double, double) + +#define EIGEN_MKL_VML_DECLARE_UNARY_CALLS_COMPLEX_LA(EIGENOP, VMLOP) \ + EIGEN_MKL_VML_DECLARE_UNARY_CALL_LA(EIGENOP, vmc##VMLOP, scomplex, MKL_Complex8) \ + EIGEN_MKL_VML_DECLARE_UNARY_CALL_LA(EIGENOP, vmz##VMLOP, dcomplex, MKL_Complex16) + +#define EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(EIGENOP, VMLOP) \ + EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL_LA(EIGENOP, VMLOP) \ + EIGEN_MKL_VML_DECLARE_UNARY_CALLS_COMPLEX_LA(EIGENOP, VMLOP) + + +EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(sin, Sin) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(asin, Asin) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(cos, Cos) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(acos, Acos) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(tan, Tan) +//EIGEN_MKL_VML_DECLARE_UNARY_CALLS(abs, Abs) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(exp, Exp) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(log, Ln) +EIGEN_MKL_VML_DECLARE_UNARY_CALLS_LA(sqrt, Sqrt) + +EIGEN_MKL_VML_DECLARE_UNARY_CALLS_REAL(square, Sqr) + +// The vm*powx functions are not avaibale in the windows version of MKL. +#ifdef _WIN32 +EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmspowx_, float, float) +EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmdpowx_, double, double) +EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmcpowx_, scomplex, MKL_Complex8) +EIGEN_MKL_VML_DECLARE_POW_CALL(pow, vmzpowx_, dcomplex, MKL_Complex16) +#endif + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_ASSIGN_VML_H diff --git a/extern/Eigen3/Eigen/src/Core/BandMatrix.h b/extern/Eigen3/Eigen/src/Core/BandMatrix.h index 2570d7b559f..ffd7fe8b301 100644 --- a/extern/Eigen3/Eigen/src/Core/BandMatrix.h +++ b/extern/Eigen3/Eigen/src/Core/BandMatrix.h @@ -3,30 +3,16 @@ // // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_BANDMATRIX_H #define EIGEN_BANDMATRIX_H -namespace internal { +namespace Eigen { +namespace internal { template class BandMatrixBase : public EigenBase @@ -343,4 +329,6 @@ class TridiagonalMatrix : public BandMatrix // Copyright (C) 2006-2010 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_BLOCK_H #define EIGEN_BLOCK_H +namespace Eigen { + /** \class Block * \ingroup Core_Module * @@ -242,6 +229,21 @@ template::type& nestedExpression() const + { + return m_xpr; + } + + Index startRow() const + { + return m_startRow.value(); + } + + Index startCol() const + { + return m_startCol.value(); + } + protected: const typename XprType::Nested m_xpr; @@ -304,6 +306,11 @@ class Block init(); } + const typename internal::remove_all::type& nestedExpression() const + { + return m_xpr; + } + /** \sa MapBase::innerStride() */ inline Index innerStride() const { @@ -341,9 +348,10 @@ class Block : m_xpr.innerStride(); } - const typename XprType::Nested m_xpr; + typename XprType::Nested m_xpr; Index m_outerStride; }; +} // end namespace Eigen #endif // EIGEN_BLOCK_H diff --git a/extern/Eigen3/Eigen/src/Core/BooleanRedux.h b/extern/Eigen3/Eigen/src/Core/BooleanRedux.h index 5c3444a57c9..57efd8e6953 100644 --- a/extern/Eigen3/Eigen/src/Core/BooleanRedux.h +++ b/extern/Eigen3/Eigen/src/Core/BooleanRedux.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_ALLANDANY_H #define EIGEN_ALLANDANY_H +namespace Eigen { + namespace internal { template @@ -35,7 +22,7 @@ struct all_unroller row = (UnrollCount-1) % Derived::RowsAtCompileTime }; - inline static bool run(const Derived &mat) + static inline bool run(const Derived &mat) { return all_unroller::run(mat) && mat.coeff(row, col); } @@ -44,13 +31,13 @@ struct all_unroller template struct all_unroller { - inline static bool run(const Derived &mat) { return mat.coeff(0, 0); } + static inline bool run(const Derived &mat) { return mat.coeff(0, 0); } }; template struct all_unroller { - inline static bool run(const Derived &) { return false; } + static inline bool run(const Derived &) { return false; } }; template @@ -61,7 +48,7 @@ struct any_unroller row = (UnrollCount-1) % Derived::RowsAtCompileTime }; - inline static bool run(const Derived &mat) + static inline bool run(const Derived &mat) { return any_unroller::run(mat) || mat.coeff(row, col); } @@ -70,13 +57,13 @@ struct any_unroller template struct any_unroller { - inline static bool run(const Derived &mat) { return mat.coeff(0, 0); } + static inline bool run(const Derived &mat) { return mat.coeff(0, 0); } }; template struct any_unroller { - inline static bool run(const Derived &) { return false; } + static inline bool run(const Derived &) { return false; } }; } // end namespace internal @@ -146,4 +133,6 @@ inline typename DenseBase::Index DenseBase::count() const return derived().template cast().template cast().sum(); } +} // end namespace Eigen + #endif // EIGEN_ALLANDANY_H diff --git a/extern/Eigen3/Eigen/src/Core/CommaInitializer.h b/extern/Eigen3/Eigen/src/Core/CommaInitializer.h index 92422bf2fa0..4adce64143c 100644 --- a/extern/Eigen3/Eigen/src/Core/CommaInitializer.h +++ b/extern/Eigen3/Eigen/src/Core/CommaInitializer.h @@ -4,28 +4,15 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_COMMAINITIALIZER_H #define EIGEN_COMMAINITIALIZER_H +namespace Eigen { + /** \class CommaInitializer * \ingroup Core_Module * @@ -147,4 +134,6 @@ DenseBase::operator<<(const DenseBase& other) return CommaInitializer(*static_cast(this), other); } +} // end namespace Eigen + #endif // EIGEN_COMMAINITIALIZER_H diff --git a/extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h b/extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h index 7386b2e1843..1b93af31b60 100644 --- a/extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h +++ b/extern/Eigen3/Eigen/src/Core/CwiseBinaryOp.h @@ -4,28 +4,15 @@ // Copyright (C) 2008-2009 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_CWISE_BINARY_OP_H #define EIGEN_CWISE_BINARY_OP_H +namespace Eigen { + /** \class CwiseBinaryOp * \ingroup Core_Module * @@ -167,8 +154,8 @@ class CwiseBinaryOp : internal::no_assignment_operator, const BinaryOp& functor() const { return m_functor; } protected: - const LhsNested m_lhs; - const RhsNested m_rhs; + LhsNested m_lhs; + RhsNested m_rhs; const BinaryOp m_functor; }; @@ -237,4 +224,6 @@ MatrixBase::operator+=(const MatrixBase& other) return derived(); } +} // end namespace Eigen + #endif // EIGEN_CWISE_BINARY_OP_H diff --git a/extern/Eigen3/Eigen/src/Core/CwiseNullaryOp.h b/extern/Eigen3/Eigen/src/Core/CwiseNullaryOp.h index c616e7ae13d..2635a62b07b 100644 --- a/extern/Eigen3/Eigen/src/Core/CwiseNullaryOp.h +++ b/extern/Eigen3/Eigen/src/Core/CwiseNullaryOp.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_CWISE_NULLARY_OP_H #define EIGEN_CWISE_NULLARY_OP_H +namespace Eigen { + /** \class CwiseNullaryOp * \ingroup Core_Module * @@ -101,6 +88,9 @@ class CwiseNullaryOp : internal::no_assignment_operator, return m_functor.packetOp(index); } + /** \returns the functor representing the nullary operation */ + const NullaryOp& functor() const { return m_functor; } + protected: const internal::variable_if_dynamic m_rows; const internal::variable_if_dynamic m_cols; @@ -238,6 +228,8 @@ DenseBase::Constant(const Scalar& value) * assumed to be a(0), a(1), ..., a(size). This assumption allows for better vectorization * and yields faster code than the random access version. * + * When size is set to 1, a vector of length 1 containing 'high' is returned. + * * \only_for_vectors * * Example: \include DenseBase_LinSpaced_seq.cpp @@ -270,6 +262,7 @@ DenseBase::LinSpaced(Sequential_t, const Scalar& low, const Scalar& hig * \brief Sets a linearly space vector. * * The function generates 'size' equally spaced values in the closed interval [low,high]. + * When size is set to 1, a vector of length 1 containing 'high' is returned. * * \only_for_vectors * @@ -381,6 +374,7 @@ PlainObjectBase::setConstant(Index rows, Index cols, const Scalar& valu * \brief Sets a linearly space vector. * * The function generates 'size' equally spaced values in the closed interval [low,high]. + * When size is set to 1, a vector of length 1 containing 'high' is returned. * * \only_for_vectors * @@ -396,6 +390,23 @@ EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(Index size, const return derived() = Derived::NullaryExpr(size, internal::linspaced_op(low,high,size)); } +/** + * \brief Sets a linearly space vector. + * + * The function fill *this with equally spaced values in the closed interval [low,high]. + * When size is set to 1, a vector of length 1 containing 'high' is returned. + * + * \only_for_vectors + * + * \sa setLinSpaced(Index, const Scalar&, const Scalar&), CwiseNullaryOp + */ +template +EIGEN_STRONG_INLINE Derived& DenseBase::setLinSpaced(const Scalar& low, const Scalar& high) +{ + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return setLinSpaced(size(), low, high); +} + // zero: /** \returns an expression of a zero matrix. @@ -848,4 +859,6 @@ template EIGEN_STRONG_INLINE const typename MatrixBase::BasisReturnType MatrixBase::UnitW() { return Derived::Unit(3); } +} // end namespace Eigen + #endif // EIGEN_CWISE_NULLARY_OP_H diff --git a/extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h b/extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h index 958571d64bf..063355ae521 100644 --- a/extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h +++ b/extern/Eigen3/Eigen/src/Core/CwiseUnaryOp.h @@ -4,28 +4,15 @@ // Copyright (C) 2008-2010 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_CWISE_UNARY_OP_H #define EIGEN_CWISE_UNARY_OP_H +namespace Eigen { + /** \class CwiseUnaryOp * \ingroup Core_Module * @@ -95,7 +82,7 @@ class CwiseUnaryOp : internal::no_assignment_operator, nestedExpression() { return m_xpr.const_cast_derived(); } protected: - const typename XprType::Nested m_xpr; + typename XprType::Nested m_xpr; const UnaryOp m_functor; }; @@ -134,4 +121,6 @@ class CwiseUnaryOpImpl } }; +} // end namespace Eigen + #endif // EIGEN_CWISE_UNARY_OP_H diff --git a/extern/Eigen3/Eigen/src/Core/CwiseUnaryView.h b/extern/Eigen3/Eigen/src/Core/CwiseUnaryView.h index d24ef037314..66f73a9505b 100644 --- a/extern/Eigen3/Eigen/src/Core/CwiseUnaryView.h +++ b/extern/Eigen3/Eigen/src/Core/CwiseUnaryView.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_CWISE_UNARY_VIEW_H #define EIGEN_CWISE_UNARY_VIEW_H +namespace Eigen { + /** \class CwiseUnaryView * \ingroup Core_Module * @@ -97,7 +84,7 @@ class CwiseUnaryView : internal::no_assignment_operator, protected: // FIXME changed from MatrixType::Nested because of a weird compilation error with sun CC - const typename internal::nested::type m_matrix; + typename internal::nested::type m_matrix; ViewOp m_functor; }; @@ -143,6 +130,6 @@ class CwiseUnaryViewImpl } }; - +} // end namespace Eigen #endif // EIGEN_CWISE_UNARY_VIEW_H diff --git a/extern/Eigen3/Eigen/src/Core/DenseBase.h b/extern/Eigen3/Eigen/src/Core/DenseBase.h index 920904f243a..1cc0314ef0b 100644 --- a/extern/Eigen3/Eigen/src/Core/DenseBase.h +++ b/extern/Eigen3/Eigen/src/Core/DenseBase.h @@ -4,28 +4,15 @@ // Copyright (C) 2007-2010 Benoit Jacob // Copyright (C) 2008-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_DENSEBASE_H #define EIGEN_DENSEBASE_H +namespace Eigen { + /** \class DenseBase * \ingroup Core_Module * @@ -376,12 +363,13 @@ template class DenseBase inline Derived& operator*=(const Scalar& other); inline Derived& operator/=(const Scalar& other); + typedef typename internal::add_const_on_value_type::type>::type EvalReturnType; /** \returns the matrix or vector obtained by evaluating this expression. * * Notice that in the case of a plain matrix or vector (not an expression) this function just returns * a const reference, in order to avoid a useless copy. */ - EIGEN_STRONG_INLINE const typename internal::eval::type eval() const + EIGEN_STRONG_INLINE EvalReturnType eval() const { // Even though MSVC does not honor strong inlining when the return type // is a dynamic matrix, we desperately need strong inlining for fixed @@ -540,4 +528,6 @@ template class DenseBase template explicit DenseBase(const DenseBase&); }; +} // end namespace Eigen + #endif // EIGEN_DENSEBASE_H diff --git a/extern/Eigen3/Eigen/src/Core/DenseCoeffsBase.h b/extern/Eigen3/Eigen/src/Core/DenseCoeffsBase.h index e45238fb584..72704c2d79f 100644 --- a/extern/Eigen3/Eigen/src/Core/DenseCoeffsBase.h +++ b/extern/Eigen3/Eigen/src/Core/DenseCoeffsBase.h @@ -3,28 +3,15 @@ // // Copyright (C) 2006-2010 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_DENSECOEFFSBASE_H #define EIGEN_DENSECOEFFSBASE_H +namespace Eigen { + namespace internal { template struct add_const_on_value_type_if_arithmetic { @@ -710,16 +697,16 @@ namespace internal { template struct first_aligned_impl { - inline static typename Derived::Index run(const Derived&) + static inline typename Derived::Index run(const Derived&) { return 0; } }; template struct first_aligned_impl { - inline static typename Derived::Index run(const Derived& m) + static inline typename Derived::Index run(const Derived& m) { - return first_aligned(&m.const_cast_derived().coeffRef(0,0), m.size()); + return internal::first_aligned(&m.const_cast_derived().coeffRef(0,0), m.size()); } }; @@ -729,7 +716,7 @@ struct first_aligned_impl * documentation. */ template -inline static typename Derived::Index first_aligned(const Derived& m) +static inline typename Derived::Index first_aligned(const Derived& m) { return first_aligned_impl @@ -762,4 +749,6 @@ struct outer_stride_at_compile_time } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_DENSECOEFFSBASE_H diff --git a/extern/Eigen3/Eigen/src/Core/DenseStorage.h b/extern/Eigen3/Eigen/src/Core/DenseStorage.h index 813053b00dd..1fc2daf2c40 100644 --- a/extern/Eigen3/Eigen/src/Core/DenseStorage.h +++ b/extern/Eigen3/Eigen/src/Core/DenseStorage.h @@ -5,24 +5,9 @@ // Copyright (C) 2006-2009 Benoit Jacob // Copyright (C) 2010 Hauke Heibel // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_MATRIXSTORAGE_H #define EIGEN_MATRIXSTORAGE_H @@ -33,6 +18,8 @@ #define EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN #endif +namespace Eigen { + namespace internal { struct constructor_without_unaligned_array_assert {}; @@ -104,8 +91,8 @@ template class DenseSt : m_data(internal::constructor_without_unaligned_array_assert()) {} inline DenseStorage(DenseIndex,DenseIndex,DenseIndex) {} inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); } - inline static DenseIndex rows(void) {return _Rows;} - inline static DenseIndex cols(void) {return _Cols;} + static inline DenseIndex rows(void) {return _Rows;} + static inline DenseIndex cols(void) {return _Cols;} inline void conservativeResize(DenseIndex,DenseIndex,DenseIndex) {} inline void resize(DenseIndex,DenseIndex,DenseIndex) {} inline const T *data() const { return m_data.array; } @@ -120,14 +107,24 @@ template class DenseStorage class DenseStorage +: public DenseStorage { }; + +template class DenseStorage +: public DenseStorage { }; + +template class DenseStorage +: public DenseStorage { }; + // dynamic-size matrix with fixed-size storage template class DenseStorage { @@ -241,7 +238,7 @@ template class DenseStorage(m_data, _Rows*m_cols); } inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_cols,other.m_cols); } - inline static DenseIndex rows(void) {return _Rows;} + static inline DenseIndex rows(void) {return _Rows;} inline DenseIndex cols(void) const {return m_cols;} inline void conservativeResize(DenseIndex size, DenseIndex, DenseIndex cols) { @@ -278,7 +275,7 @@ template class DenseStorage(m_data, _Cols*m_rows); } inline void swap(DenseStorage& other) { std::swap(m_data,other.m_data); std::swap(m_rows,other.m_rows); } inline DenseIndex rows(void) const {return m_rows;} - inline static DenseIndex cols(void) {return _Cols;} + static inline DenseIndex cols(void) {return _Cols;} inline void conservativeResize(DenseIndex size, DenseIndex rows, DenseIndex) { m_data = internal::conditional_aligned_realloc_new_auto(m_data, size, m_rows*_Cols); @@ -301,4 +298,6 @@ template class DenseStorage +// Copyright (C) 2009-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_DIAGONAL_H #define EIGEN_DIAGONAL_H +namespace Eigen { + /** \class Diagonal * \ingroup Core_Module * @@ -53,16 +41,15 @@ struct traits > typedef typename remove_reference::type _MatrixTypeNested; typedef typename MatrixType::StorageKind StorageKind; enum { - AbsDiagIndex = DiagIndex<0 ? -DiagIndex : DiagIndex, // only used if DiagIndex != Dynamic - // FIXME these computations are broken in the case where the matrix is rectangular and DiagIndex!=0 RowsAtCompileTime = (int(DiagIndex) == Dynamic || int(MatrixType::SizeAtCompileTime) == Dynamic) ? Dynamic - : (EIGEN_SIZE_MIN_PREFER_DYNAMIC(MatrixType::RowsAtCompileTime, - MatrixType::ColsAtCompileTime) - AbsDiagIndex), + : (EIGEN_PLAIN_ENUM_MIN(MatrixType::RowsAtCompileTime - EIGEN_PLAIN_ENUM_MAX(-DiagIndex, 0), + MatrixType::ColsAtCompileTime - EIGEN_PLAIN_ENUM_MAX( DiagIndex, 0))), ColsAtCompileTime = 1, MaxRowsAtCompileTime = int(MatrixType::MaxSizeAtCompileTime) == Dynamic ? Dynamic : DiagIndex == Dynamic ? EIGEN_SIZE_MIN_PREFER_FIXED(MatrixType::MaxRowsAtCompileTime, - MatrixType::MaxColsAtCompileTime) - : (EIGEN_SIZE_MIN_PREFER_FIXED(MatrixType::MaxRowsAtCompileTime, MatrixType::MaxColsAtCompileTime) - AbsDiagIndex), + MatrixType::MaxColsAtCompileTime) + : (EIGEN_PLAIN_ENUM_MIN(MatrixType::MaxRowsAtCompileTime - EIGEN_PLAIN_ENUM_MAX(-DiagIndex, 0), + MatrixType::MaxColsAtCompileTime - EIGEN_PLAIN_ENUM_MAX( DiagIndex, 0))), MaxColsAtCompileTime = 1, MaskLvalueBit = is_lvalue::value ? LvalueBit : 0, Flags = (unsigned int)_MatrixTypeNested::Flags & (HereditaryBits | LinearAccessBit | MaskLvalueBit | DirectAccessBit) & ~RowMajorBit, @@ -101,6 +88,15 @@ template class Diagonal return 0; } + typedef typename internal::conditional< + internal::is_lvalue::value, + Scalar, + const Scalar + >::type ScalarWithConstIfNotLvalue; + + inline ScalarWithConstIfNotLvalue* data() { return &(m_matrix.const_cast_derived().coeffRef(rowOffset(), colOffset())); } + inline const Scalar* data() const { return &(m_matrix.const_cast_derived().coeffRef(rowOffset(), colOffset())); } + inline Scalar& coeffRef(Index row, Index) { EIGEN_STATIC_ASSERT_LVALUE(MatrixType) @@ -133,8 +129,19 @@ template class Diagonal return m_matrix.coeff(index+rowOffset(), index+colOffset()); } + const typename internal::remove_all::type& + nestedExpression() const + { + return m_matrix; + } + + int index() const + { + return m_index.value(); + } + protected: - const typename MatrixType::Nested m_matrix; + typename MatrixType::Nested m_matrix; const internal::variable_if_dynamic m_index; private: @@ -224,4 +231,6 @@ MatrixBase::diagonal() const return derived(); } +} // end namespace Eigen + #endif // EIGEN_DIAGONAL_H diff --git a/extern/Eigen3/Eigen/src/Core/DiagonalMatrix.h b/extern/Eigen3/Eigen/src/Core/DiagonalMatrix.h index f41a74bfae7..88190da684d 100644 --- a/extern/Eigen3/Eigen/src/Core/DiagonalMatrix.h +++ b/extern/Eigen3/Eigen/src/Core/DiagonalMatrix.h @@ -4,28 +4,15 @@ // Copyright (C) 2009 Gael Guennebaud // Copyright (C) 2007-2009 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_DIAGONALMATRIX_H #define EIGEN_DIAGONALMATRIX_H +namespace Eigen { + #ifndef EIGEN_PARSED_BY_DOXYGEN template class DiagonalBase : public EigenBase @@ -72,7 +59,7 @@ class DiagonalBase : public EigenBase const DiagonalProduct operator*(const MatrixBase &matrix) const; - inline const DiagonalWrapper, const DiagonalVectorType> > + inline const DiagonalWrapper, const DiagonalVectorType> > inverse() const { return diagonal().cwiseInverse(); @@ -251,13 +238,13 @@ class DiagonalWrapper #endif /** Constructor from expression of diagonal coefficients to wrap. */ - inline DiagonalWrapper(const DiagonalVectorType& diagonal) : m_diagonal(diagonal) {} + inline DiagonalWrapper(DiagonalVectorType& diagonal) : m_diagonal(diagonal) {} /** \returns a const reference to the wrapped expression of diagonal coefficients. */ const DiagonalVectorType& diagonal() const { return m_diagonal; } protected: - const typename DiagonalVectorType::Nested m_diagonal; + typename DiagonalVectorType::Nested m_diagonal; }; /** \returns a pseudo-expression of a diagonal matrix with *this as vector of diagonal coefficients @@ -303,4 +290,6 @@ bool MatrixBase::isDiagonal(RealScalar prec) const return true; } +} // end namespace Eigen + #endif // EIGEN_DIAGONALMATRIX_H diff --git a/extern/Eigen3/Eigen/src/Core/DiagonalProduct.h b/extern/Eigen3/Eigen/src/Core/DiagonalProduct.h index de0c6ed11b7..598c6b3e19a 100644 --- a/extern/Eigen3/Eigen/src/Core/DiagonalProduct.h +++ b/extern/Eigen3/Eigen/src/Core/DiagonalProduct.h @@ -4,28 +4,15 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2007-2009 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_DIAGONALPRODUCT_H #define EIGEN_DIAGONALPRODUCT_H +namespace Eigen { + namespace internal { template struct traits > @@ -107,8 +94,8 @@ class DiagonalProduct : internal::no_assignment_operator, m_diagonal.diagonal().template packet(id)); } - const typename MatrixType::Nested m_matrix; - const typename DiagonalType::Nested m_diagonal; + typename MatrixType::Nested m_matrix; + typename DiagonalType::Nested m_diagonal; }; /** \returns the diagonal matrix product of \c *this by the diagonal matrix \a diagonal. @@ -131,5 +118,6 @@ DiagonalBase::operator*(const MatrixBase &matrix return DiagonalProduct(matrix.derived(), derived()); } +} // end namespace Eigen #endif // EIGEN_DIAGONALPRODUCT_H diff --git a/extern/Eigen3/Eigen/src/Core/Dot.h b/extern/Eigen3/Eigen/src/Core/Dot.h index 42da7849896..ae9274e36dd 100644 --- a/extern/Eigen3/Eigen/src/Core/Dot.h +++ b/extern/Eigen3/Eigen/src/Core/Dot.h @@ -3,28 +3,15 @@ // // Copyright (C) 2006-2008, 2010 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_DOT_H #define EIGEN_DOT_H +namespace Eigen { + namespace internal { // helper function for dot(). The problem is that if we put that in the body of dot(), then upon calling dot @@ -176,7 +163,7 @@ template struct lpNorm_selector { typedef typename NumTraits::Scalar>::Real RealScalar; - inline static RealScalar run(const MatrixBase& m) + static inline RealScalar run(const MatrixBase& m) { return pow(m.cwiseAbs().array().pow(p).sum(), RealScalar(1)/p); } @@ -185,7 +172,7 @@ struct lpNorm_selector template struct lpNorm_selector { - inline static typename NumTraits::Scalar>::Real run(const MatrixBase& m) + static inline typename NumTraits::Scalar>::Real run(const MatrixBase& m) { return m.cwiseAbs().sum(); } @@ -194,7 +181,7 @@ struct lpNorm_selector template struct lpNorm_selector { - inline static typename NumTraits::Scalar>::Real run(const MatrixBase& m) + static inline typename NumTraits::Scalar>::Real run(const MatrixBase& m) { return m.norm(); } @@ -203,7 +190,7 @@ struct lpNorm_selector template struct lpNorm_selector { - inline static typename NumTraits::Scalar>::Real run(const MatrixBase& m) + static inline typename NumTraits::Scalar>::Real run(const MatrixBase& m) { return m.cwiseAbs().maxCoeff(); } @@ -269,4 +256,6 @@ bool MatrixBase::isUnitary(RealScalar prec) const return true; } +} // end namespace Eigen + #endif // EIGEN_DOT_H diff --git a/extern/Eigen3/Eigen/src/Core/EigenBase.h b/extern/Eigen3/Eigen/src/Core/EigenBase.h index 0472539af33..0bbd28bec21 100644 --- a/extern/Eigen3/Eigen/src/Core/EigenBase.h +++ b/extern/Eigen3/Eigen/src/Core/EigenBase.h @@ -4,28 +4,14 @@ // Copyright (C) 2009 Benoit Jacob // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_EIGENBASE_H #define EIGEN_EIGENBASE_H +namespace Eigen { /** Common base class for all classes T such that MatrixBase has an operator=(T) and a constructor MatrixBase(T). * @@ -169,4 +155,6 @@ inline void MatrixBase::applyOnTheLeft(const EigenBase &o other.derived().applyThisOnTheLeft(derived()); } +} // end namespace Eigen + #endif // EIGEN_EIGENBASE_H diff --git a/extern/Eigen3/Eigen/src/Core/Flagged.h b/extern/Eigen3/Eigen/src/Core/Flagged.h index 458213ab553..1f2955fc1de 100644 --- a/extern/Eigen3/Eigen/src/Core/Flagged.h +++ b/extern/Eigen3/Eigen/src/Core/Flagged.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_FLAGGED_H #define EIGEN_FLAGGED_H +namespace Eigen { + /** \class Flagged * \ingroup Core_Module * @@ -148,4 +135,6 @@ DenseBase::flagged() const return derived(); } +} // end namespace Eigen + #endif // EIGEN_FLAGGED_H diff --git a/extern/Eigen3/Eigen/src/Core/ForceAlignedAccess.h b/extern/Eigen3/Eigen/src/Core/ForceAlignedAccess.h index 11c1f8f709a..807c7a29346 100644 --- a/extern/Eigen3/Eigen/src/Core/ForceAlignedAccess.h +++ b/extern/Eigen3/Eigen/src/Core/ForceAlignedAccess.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_FORCEALIGNEDACCESS_H #define EIGEN_FORCEALIGNEDACCESS_H +namespace Eigen { + /** \class ForceAlignedAccess * \ingroup Core_Module * @@ -154,4 +141,6 @@ MatrixBase::forceAlignedAccessIf() return derived(); } +} // end namespace Eigen + #endif // EIGEN_FORCEALIGNEDACCESS_H diff --git a/extern/Eigen3/Eigen/src/Core/Functors.h b/extern/Eigen3/Eigen/src/Core/Functors.h index 54636e0d459..278c46c6b61 100644 --- a/extern/Eigen3/Eigen/src/Core/Functors.h +++ b/extern/Eigen3/Eigen/src/Core/Functors.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_FUNCTORS_H #define EIGEN_FUNCTORS_H +namespace Eigen { + namespace internal { // associative functors: @@ -178,6 +165,18 @@ struct functor_traits > { enum { Cost = 5 * NumTraits::MulCost, PacketAccess=0 }; }; +/** \internal + * \brief Template functor to compute the pow of two scalars + */ +template struct scalar_binary_pow_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_binary_pow_op) + inline Scalar operator() (const Scalar& a, const OtherScalar& b) const { return internal::pow(a, b); } +}; +template +struct functor_traits > { + enum { Cost = 5 * NumTraits::MulCost, PacketAccess = false }; +}; + // other binary functors: /** \internal @@ -220,6 +219,38 @@ struct functor_traits > { }; }; +/** \internal + * \brief Template functor to compute the and of two booleans + * + * \sa class CwiseBinaryOp, ArrayBase::operator&& + */ +struct scalar_boolean_and_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_and_op) + EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a && b; } +}; +template<> struct functor_traits { + enum { + Cost = NumTraits::AddCost, + PacketAccess = false + }; +}; + +/** \internal + * \brief Template functor to compute the or of two booleans + * + * \sa class CwiseBinaryOp, ArrayBase::operator|| + */ +struct scalar_boolean_or_op { + EIGEN_EMPTY_STRUCT_CTOR(scalar_boolean_or_op) + EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a || b; } +}; +template<> struct functor_traits { + enum { + Cost = NumTraits::AddCost, + PacketAccess = false + }; +}; + // unary functors: /** \internal @@ -249,7 +280,7 @@ struct functor_traits > template struct scalar_abs_op { EIGEN_EMPTY_STRUCT_CTOR(scalar_abs_op) typedef typename NumTraits::Real result_type; - EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return abs(a); } + EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return internal::abs(a); } template EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const { return internal::pabs(a); } @@ -271,7 +302,7 @@ struct functor_traits > template struct scalar_abs2_op { EIGEN_EMPTY_STRUCT_CTOR(scalar_abs2_op) typedef typename NumTraits::Real result_type; - EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return abs2(a); } + EIGEN_STRONG_INLINE const result_type operator() (const Scalar& a) const { return internal::abs2(a); } template EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const { return internal::pmul(a,a); } @@ -287,7 +318,7 @@ struct functor_traits > */ template struct scalar_conjugate_op { EIGEN_EMPTY_STRUCT_CTOR(scalar_conjugate_op) - EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return conj(a); } + EIGEN_STRONG_INLINE const Scalar operator() (const Scalar& a) const { return internal::conj(a); } template EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a) const { return internal::pconj(a); } }; @@ -324,7 +355,7 @@ template struct scalar_real_op { EIGEN_EMPTY_STRUCT_CTOR(scalar_real_op) typedef typename NumTraits::Real result_type; - EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return real(a); } + EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return internal::real(a); } }; template struct functor_traits > @@ -339,7 +370,7 @@ template struct scalar_imag_op { EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_op) typedef typename NumTraits::Real result_type; - EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return imag(a); } + EIGEN_STRONG_INLINE result_type operator() (const Scalar& a) const { return internal::imag(a); } }; template struct functor_traits > @@ -354,7 +385,7 @@ template struct scalar_real_ref_op { EIGEN_EMPTY_STRUCT_CTOR(scalar_real_ref_op) typedef typename NumTraits::Real result_type; - EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return real_ref(*const_cast(&a)); } + EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return internal::real_ref(*const_cast(&a)); } }; template struct functor_traits > @@ -369,7 +400,7 @@ template struct scalar_imag_ref_op { EIGEN_EMPTY_STRUCT_CTOR(scalar_imag_ref_op) typedef typename NumTraits::Real result_type; - EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return imag_ref(*const_cast(&a)); } + EIGEN_STRONG_INLINE result_type& operator() (const Scalar& a) const { return internal::imag_ref(*const_cast(&a)); } }; template struct functor_traits > @@ -383,7 +414,7 @@ struct functor_traits > */ template struct scalar_exp_op { EIGEN_EMPTY_STRUCT_CTOR(scalar_exp_op) - inline const Scalar operator() (const Scalar& a) const { return exp(a); } + inline const Scalar operator() (const Scalar& a) const { return internal::exp(a); } typedef typename packet_traits::type Packet; inline Packet packetOp(const Packet& a) const { return internal::pexp(a); } }; @@ -399,7 +430,7 @@ struct functor_traits > */ template struct scalar_log_op { EIGEN_EMPTY_STRUCT_CTOR(scalar_log_op) - inline const Scalar operator() (const Scalar& a) const { return log(a); } + inline const Scalar operator() (const Scalar& a) const { return internal::log(a); } typedef typename packet_traits::type Packet; inline Packet packetOp(const Packet& a) const { return internal::plog(a); } }; @@ -584,7 +615,7 @@ template struct functor_traits< linspaced_o template struct linspaced_op { typedef typename packet_traits::type Packet; - linspaced_op(Scalar low, Scalar high, int num_steps) : impl(low, (high-low)/(num_steps-1)) {} + linspaced_op(Scalar low, Scalar high, int num_steps) : impl((num_steps==1 ? high : low), (num_steps==1 ? Scalar() : (high-low)/(num_steps-1))) {} template EIGEN_STRONG_INLINE const Scalar operator() (Index i) const { return impl(i); } @@ -657,7 +688,7 @@ struct functor_traits > */ template struct scalar_sqrt_op { EIGEN_EMPTY_STRUCT_CTOR(scalar_sqrt_op) - inline const Scalar operator() (const Scalar& a) const { return sqrt(a); } + inline const Scalar operator() (const Scalar& a) const { return internal::sqrt(a); } typedef typename packet_traits::type Packet; inline Packet packetOp(const Packet& a) const { return internal::psqrt(a); } }; @@ -675,7 +706,7 @@ struct functor_traits > */ template struct scalar_cos_op { EIGEN_EMPTY_STRUCT_CTOR(scalar_cos_op) - inline Scalar operator() (const Scalar& a) const { return cos(a); } + inline Scalar operator() (const Scalar& a) const { return internal::cos(a); } typedef typename packet_traits::type Packet; inline Packet packetOp(const Packet& a) const { return internal::pcos(a); } }; @@ -694,7 +725,7 @@ struct functor_traits > */ template struct scalar_sin_op { EIGEN_EMPTY_STRUCT_CTOR(scalar_sin_op) - inline const Scalar operator() (const Scalar& a) const { return sin(a); } + inline const Scalar operator() (const Scalar& a) const { return internal::sin(a); } typedef typename packet_traits::type Packet; inline Packet packetOp(const Packet& a) const { return internal::psin(a); } }; @@ -714,7 +745,7 @@ struct functor_traits > */ template struct scalar_tan_op { EIGEN_EMPTY_STRUCT_CTOR(scalar_tan_op) - inline const Scalar operator() (const Scalar& a) const { return tan(a); } + inline const Scalar operator() (const Scalar& a) const { return internal::tan(a); } typedef typename packet_traits::type Packet; inline Packet packetOp(const Packet& a) const { return internal::ptan(a); } }; @@ -733,7 +764,7 @@ struct functor_traits > */ template struct scalar_acos_op { EIGEN_EMPTY_STRUCT_CTOR(scalar_acos_op) - inline const Scalar operator() (const Scalar& a) const { return acos(a); } + inline const Scalar operator() (const Scalar& a) const { return internal::acos(a); } typedef typename packet_traits::type Packet; inline Packet packetOp(const Packet& a) const { return internal::pacos(a); } }; @@ -752,7 +783,7 @@ struct functor_traits > */ template struct scalar_asin_op { EIGEN_EMPTY_STRUCT_CTOR(scalar_asin_op) - inline const Scalar operator() (const Scalar& a) const { return asin(a); } + inline const Scalar operator() (const Scalar& a) const { return internal::asin(a); } typedef typename packet_traits::type Packet; inline Packet packetOp(const Packet& a) const { return internal::pasin(a); } }; @@ -781,6 +812,20 @@ template struct functor_traits > { enum { Cost = 5 * NumTraits::MulCost, PacketAccess = false }; }; +/** \internal + * \brief Template functor to compute the quotient between a scalar and array entries. + * \sa class CwiseUnaryOp, Cwise::inverse() + */ +template +struct scalar_inverse_mult_op { + scalar_inverse_mult_op(const Scalar& other) : m_other(other) {} + inline Scalar operator() (const Scalar& a) const { return m_other / a; } + template + inline const Packet packetOp(const Packet& a) const + { return internal::pdiv(pset1(m_other),a); } + Scalar m_other; +}; + /** \internal * \brief Template functor to compute the inverse of a scalar * \sa class CwiseUnaryOp, Cwise::inverse() @@ -939,4 +984,6 @@ struct functor_traits > } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_FUNCTORS_H diff --git a/extern/Eigen3/Eigen/src/Core/Fuzzy.h b/extern/Eigen3/Eigen/src/Core/Fuzzy.h index d266eed0ac6..d74edcfdb9d 100644 --- a/extern/Eigen3/Eigen/src/Core/Fuzzy.h +++ b/extern/Eigen3/Eigen/src/Core/Fuzzy.h @@ -4,28 +4,15 @@ // Copyright (C) 2006-2008 Benoit Jacob // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_FUZZY_H #define EIGEN_FUZZY_H +namespace Eigen { + namespace internal { @@ -35,8 +22,8 @@ struct isApprox_selector static bool run(const Derived& x, const OtherDerived& y, typename Derived::RealScalar prec) { using std::min; - const typename internal::nested::type nested(x); - const typename internal::nested::type otherNested(y); + typename internal::nested::type nested(x); + typename internal::nested::type otherNested(y); return (nested - otherNested).cwiseAbs2().sum() <= prec * prec * (min)(nested.cwiseAbs2().sum(), otherNested.cwiseAbs2().sum()); } }; @@ -158,4 +145,6 @@ bool DenseBase::isMuchSmallerThan( return internal::isMuchSmallerThan_object_selector::run(derived(), other.derived(), prec); } +} // end namespace Eigen + #endif // EIGEN_FUZZY_H diff --git a/extern/Eigen3/Eigen/src/Core/GeneralProduct.h b/extern/Eigen3/Eigen/src/Core/GeneralProduct.h new file mode 100644 index 00000000000..bfc2a67b12f --- /dev/null +++ b/extern/Eigen3/Eigen/src/Core/GeneralProduct.h @@ -0,0 +1,613 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2006-2008 Benoit Jacob +// Copyright (C) 2008-2011 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_GENERAL_PRODUCT_H +#define EIGEN_GENERAL_PRODUCT_H + +namespace Eigen { + +/** \class GeneralProduct + * \ingroup Core_Module + * + * \brief Expression of the product of two general matrices or vectors + * + * \param LhsNested the type used to store the left-hand side + * \param RhsNested the type used to store the right-hand side + * \param ProductMode the type of the product + * + * This class represents an expression of the product of two general matrices. + * We call a general matrix, a dense matrix with full storage. For instance, + * This excludes triangular, selfadjoint, and sparse matrices. + * It is the return type of the operator* between general matrices. Its template + * arguments are determined automatically by ProductReturnType. Therefore, + * GeneralProduct should never be used direclty. To determine the result type of a + * function which involves a matrix product, use ProductReturnType::Type. + * + * \sa ProductReturnType, MatrixBase::operator*(const MatrixBase&) + */ +template::value> +class GeneralProduct; + +enum { + Large = 2, + Small = 3 +}; + +namespace internal { + +template struct product_type_selector; + +template struct product_size_category +{ + enum { is_large = MaxSize == Dynamic || + Size >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD, + value = is_large ? Large + : Size == 1 ? 1 + : Small + }; +}; + +template struct product_type +{ + typedef typename remove_all::type _Lhs; + typedef typename remove_all::type _Rhs; + enum { + MaxRows = _Lhs::MaxRowsAtCompileTime, + Rows = _Lhs::RowsAtCompileTime, + MaxCols = _Rhs::MaxColsAtCompileTime, + Cols = _Rhs::ColsAtCompileTime, + MaxDepth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::MaxColsAtCompileTime, + _Rhs::MaxRowsAtCompileTime), + Depth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::ColsAtCompileTime, + _Rhs::RowsAtCompileTime), + LargeThreshold = EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD + }; + + // the splitting into different lines of code here, introducing the _select enums and the typedef below, + // is to work around an internal compiler error with gcc 4.1 and 4.2. +private: + enum { + rows_select = product_size_category::value, + cols_select = product_size_category::value, + depth_select = product_size_category::value + }; + typedef product_type_selector selector; + +public: + enum { + value = selector::ret + }; +#ifdef EIGEN_DEBUG_PRODUCT + static void debug() + { + EIGEN_DEBUG_VAR(Rows); + EIGEN_DEBUG_VAR(Cols); + EIGEN_DEBUG_VAR(Depth); + EIGEN_DEBUG_VAR(rows_select); + EIGEN_DEBUG_VAR(cols_select); + EIGEN_DEBUG_VAR(depth_select); + EIGEN_DEBUG_VAR(value); + } +#endif +}; + + +/* The following allows to select the kind of product at compile time + * based on the three dimensions of the product. + * This is a compile time mapping from {1,Small,Large}^3 -> {product types} */ +// FIXME I'm not sure the current mapping is the ideal one. +template struct product_type_selector { enum { ret = OuterProduct }; }; +template struct product_type_selector<1, 1, Depth> { enum { ret = InnerProduct }; }; +template<> struct product_type_selector<1, 1, 1> { enum { ret = InnerProduct }; }; +template<> struct product_type_selector { enum { ret = CoeffBasedProductMode }; }; +template<> struct product_type_selector<1, Small,Small> { enum { ret = CoeffBasedProductMode }; }; +template<> struct product_type_selector { enum { ret = CoeffBasedProductMode }; }; +template<> struct product_type_selector { enum { ret = LazyCoeffBasedProductMode }; }; +template<> struct product_type_selector { enum { ret = LazyCoeffBasedProductMode }; }; +template<> struct product_type_selector { enum { ret = LazyCoeffBasedProductMode }; }; +template<> struct product_type_selector<1, Large,Small> { enum { ret = CoeffBasedProductMode }; }; +template<> struct product_type_selector<1, Large,Large> { enum { ret = GemvProduct }; }; +template<> struct product_type_selector<1, Small,Large> { enum { ret = CoeffBasedProductMode }; }; +template<> struct product_type_selector { enum { ret = CoeffBasedProductMode }; }; +template<> struct product_type_selector { enum { ret = GemvProduct }; }; +template<> struct product_type_selector { enum { ret = CoeffBasedProductMode }; }; +template<> struct product_type_selector { enum { ret = GemmProduct }; }; +template<> struct product_type_selector { enum { ret = GemmProduct }; }; +template<> struct product_type_selector { enum { ret = GemmProduct }; }; +template<> struct product_type_selector { enum { ret = GemmProduct }; }; +template<> struct product_type_selector { enum { ret = GemmProduct }; }; +template<> struct product_type_selector { enum { ret = GemmProduct }; }; +template<> struct product_type_selector { enum { ret = GemmProduct }; }; + +} // end namespace internal + +/** \class ProductReturnType + * \ingroup Core_Module + * + * \brief Helper class to get the correct and optimized returned type of operator* + * + * \param Lhs the type of the left-hand side + * \param Rhs the type of the right-hand side + * \param ProductMode the type of the product (determined automatically by internal::product_mode) + * + * This class defines the typename Type representing the optimized product expression + * between two matrix expressions. In practice, using ProductReturnType::Type + * is the recommended way to define the result type of a function returning an expression + * which involve a matrix product. The class Product should never be + * used directly. + * + * \sa class Product, MatrixBase::operator*(const MatrixBase&) + */ +template +struct ProductReturnType +{ + // TODO use the nested type to reduce instanciations ???? +// typedef typename internal::nested::type LhsNested; +// typedef typename internal::nested::type RhsNested; + + typedef GeneralProduct Type; +}; + +template +struct ProductReturnType +{ + typedef typename internal::nested::type >::type LhsNested; + typedef typename internal::nested::type >::type RhsNested; + typedef CoeffBasedProduct Type; +}; + +template +struct ProductReturnType +{ + typedef typename internal::nested::type >::type LhsNested; + typedef typename internal::nested::type >::type RhsNested; + typedef CoeffBasedProduct Type; +}; + +// this is a workaround for sun CC +template +struct LazyProductReturnType : public ProductReturnType +{}; + +/*********************************************************************** +* Implementation of Inner Vector Vector Product +***********************************************************************/ + +// FIXME : maybe the "inner product" could return a Scalar +// instead of a 1x1 matrix ?? +// Pro: more natural for the user +// Cons: this could be a problem if in a meta unrolled algorithm a matrix-matrix +// product ends up to a row-vector times col-vector product... To tackle this use +// case, we could have a specialization for Block with: operator=(Scalar x); + +namespace internal { + +template +struct traits > + : traits::ReturnType,1,1> > +{}; + +} + +template +class GeneralProduct + : internal::no_assignment_operator, + public Matrix::ReturnType,1,1> +{ + typedef Matrix::ReturnType,1,1> Base; + public: + GeneralProduct(const Lhs& lhs, const Rhs& rhs) + { + EIGEN_STATIC_ASSERT((internal::is_same::value), + YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) + + Base::coeffRef(0,0) = (lhs.transpose().cwiseProduct(rhs)).sum(); + } + + /** Convertion to scalar */ + operator const typename Base::Scalar() const { + return Base::coeff(0,0); + } +}; + +/*********************************************************************** +* Implementation of Outer Vector Vector Product +***********************************************************************/ + +namespace internal { +template struct outer_product_selector; + +template +struct traits > + : traits, Lhs, Rhs> > +{}; + +} + +template +class GeneralProduct + : public ProductBase, Lhs, Rhs> +{ + public: + EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct) + + GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) + { + EIGEN_STATIC_ASSERT((internal::is_same::value), + YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) + } + + template void scaleAndAddTo(Dest& dest, Scalar alpha) const + { + internal::outer_product_selector<(int(Dest::Flags)&RowMajorBit) ? RowMajor : ColMajor>::run(*this, dest, alpha); + } +}; + +namespace internal { + +template<> struct outer_product_selector { + template + static EIGEN_DONT_INLINE void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) { + typedef typename Dest::Index Index; + // FIXME make sure lhs is sequentially stored + // FIXME not very good if rhs is real and lhs complex while alpha is real too + const Index cols = dest.cols(); + for (Index j=0; j struct outer_product_selector { + template + static EIGEN_DONT_INLINE void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) { + typedef typename Dest::Index Index; + // FIXME make sure rhs is sequentially stored + // FIXME not very good if lhs is real and rhs complex while alpha is real too + const Index rows = dest.rows(); + for (Index i=0; i call fast BLAS-like colmajor routine + * 2 - the matrix is row-major, BLAS compatible and N is large => call fast BLAS-like rowmajor routine + * 3 - all other cases are handled using a simple loop along the outer-storage direction. + * Therefore we need a lower level meta selector. + * Furthermore, if the matrix is the rhs, then the product has to be transposed. + */ +namespace internal { + +template +struct traits > + : traits, Lhs, Rhs> > +{}; + +template +struct gemv_selector; + +} // end namespace internal + +template +class GeneralProduct + : public ProductBase, Lhs, Rhs> +{ + public: + EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct) + + typedef typename Lhs::Scalar LhsScalar; + typedef typename Rhs::Scalar RhsScalar; + + GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) + { +// EIGEN_STATIC_ASSERT((internal::is_same::value), +// YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) + } + + enum { Side = Lhs::IsVectorAtCompileTime ? OnTheLeft : OnTheRight }; + typedef typename internal::conditional::type MatrixType; + + template void scaleAndAddTo(Dest& dst, Scalar alpha) const + { + eigen_assert(m_lhs.rows() == dst.rows() && m_rhs.cols() == dst.cols()); + internal::gemv_selector::HasUsableDirectAccess)>::run(*this, dst, alpha); + } +}; + +namespace internal { + +// The vector is on the left => transposition +template +struct gemv_selector +{ + template + static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) + { + Transpose destT(dest); + enum { OtherStorageOrder = StorageOrder == RowMajor ? ColMajor : RowMajor }; + gemv_selector + ::run(GeneralProduct,Transpose, GemvProduct> + (prod.rhs().transpose(), prod.lhs().transpose()), destT, alpha); + } +}; + +template struct gemv_static_vector_if; + +template +struct gemv_static_vector_if +{ + EIGEN_STRONG_INLINE Scalar* data() { eigen_internal_assert(false && "should never be called"); return 0; } +}; + +template +struct gemv_static_vector_if +{ + EIGEN_STRONG_INLINE Scalar* data() { return 0; } +}; + +template +struct gemv_static_vector_if +{ + #if EIGEN_ALIGN_STATICALLY + internal::plain_array m_data; + EIGEN_STRONG_INLINE Scalar* data() { return m_data.array; } + #else + // Some architectures cannot align on the stack, + // => let's manually enforce alignment by allocating more data and return the address of the first aligned element. + enum { + ForceAlignment = internal::packet_traits::Vectorizable, + PacketSize = internal::packet_traits::size + }; + internal::plain_array m_data; + EIGEN_STRONG_INLINE Scalar* data() { + return ForceAlignment + ? reinterpret_cast((reinterpret_cast(m_data.array) & ~(size_t(15))) + 16) + : m_data.array; + } + #endif +}; + +template<> struct gemv_selector +{ + template + static inline void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) + { + typedef typename ProductType::Index Index; + typedef typename ProductType::LhsScalar LhsScalar; + typedef typename ProductType::RhsScalar RhsScalar; + typedef typename ProductType::Scalar ResScalar; + typedef typename ProductType::RealScalar RealScalar; + typedef typename ProductType::ActualLhsType ActualLhsType; + typedef typename ProductType::ActualRhsType ActualRhsType; + typedef typename ProductType::LhsBlasTraits LhsBlasTraits; + typedef typename ProductType::RhsBlasTraits RhsBlasTraits; + typedef Map, Aligned> MappedDest; + + ActualLhsType actualLhs = LhsBlasTraits::extract(prod.lhs()); + ActualRhsType actualRhs = RhsBlasTraits::extract(prod.rhs()); + + ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs()) + * RhsBlasTraits::extractScalarFactor(prod.rhs()); + + enum { + // FIXME find a way to allow an inner stride on the result if packet_traits::size==1 + // on, the other hand it is good for the cache to pack the vector anyways... + EvalToDestAtCompileTime = Dest::InnerStrideAtCompileTime==1, + ComplexByReal = (NumTraits::IsComplex) && (!NumTraits::IsComplex), + MightCannotUseDest = (Dest::InnerStrideAtCompileTime!=1) || ComplexByReal + }; + + gemv_static_vector_if static_dest; + + bool alphaIsCompatible = (!ComplexByReal) || (imag(actualAlpha)==RealScalar(0)); + bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible; + + RhsScalar compatibleAlpha = get_factor::run(actualAlpha); + + ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(), + evalToDest ? dest.data() : static_dest.data()); + + if(!evalToDest) + { + #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN + int size = dest.size(); + EIGEN_DENSE_STORAGE_CTOR_PLUGIN + #endif + if(!alphaIsCompatible) + { + MappedDest(actualDestPtr, dest.size()).setZero(); + compatibleAlpha = RhsScalar(1); + } + else + MappedDest(actualDestPtr, dest.size()) = dest; + } + + general_matrix_vector_product + ::run( + actualLhs.rows(), actualLhs.cols(), + actualLhs.data(), actualLhs.outerStride(), + actualRhs.data(), actualRhs.innerStride(), + actualDestPtr, 1, + compatibleAlpha); + + if (!evalToDest) + { + if(!alphaIsCompatible) + dest += actualAlpha * MappedDest(actualDestPtr, dest.size()); + else + dest = MappedDest(actualDestPtr, dest.size()); + } + } +}; + +template<> struct gemv_selector +{ + template + static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) + { + typedef typename ProductType::LhsScalar LhsScalar; + typedef typename ProductType::RhsScalar RhsScalar; + typedef typename ProductType::Scalar ResScalar; + typedef typename ProductType::Index Index; + typedef typename ProductType::ActualLhsType ActualLhsType; + typedef typename ProductType::ActualRhsType ActualRhsType; + typedef typename ProductType::_ActualRhsType _ActualRhsType; + typedef typename ProductType::LhsBlasTraits LhsBlasTraits; + typedef typename ProductType::RhsBlasTraits RhsBlasTraits; + + typename add_const::type actualLhs = LhsBlasTraits::extract(prod.lhs()); + typename add_const::type actualRhs = RhsBlasTraits::extract(prod.rhs()); + + ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs()) + * RhsBlasTraits::extractScalarFactor(prod.rhs()); + + enum { + // FIXME find a way to allow an inner stride on the result if packet_traits::size==1 + // on, the other hand it is good for the cache to pack the vector anyways... + DirectlyUseRhs = _ActualRhsType::InnerStrideAtCompileTime==1 + }; + + gemv_static_vector_if static_rhs; + + ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhsPtr,actualRhs.size(), + DirectlyUseRhs ? const_cast(actualRhs.data()) : static_rhs.data()); + + if(!DirectlyUseRhs) + { + #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN + int size = actualRhs.size(); + EIGEN_DENSE_STORAGE_CTOR_PLUGIN + #endif + Map(actualRhsPtr, actualRhs.size()) = actualRhs; + } + + general_matrix_vector_product + ::run( + actualLhs.rows(), actualLhs.cols(), + actualLhs.data(), actualLhs.outerStride(), + actualRhsPtr, 1, + dest.data(), dest.innerStride(), + actualAlpha); + } +}; + +template<> struct gemv_selector +{ + template + static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) + { + typedef typename Dest::Index Index; + // TODO makes sure dest is sequentially stored in memory, otherwise use a temp + const Index size = prod.rhs().rows(); + for(Index k=0; k struct gemv_selector +{ + template + static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) + { + typedef typename Dest::Index Index; + // TODO makes sure rhs is sequentially stored in memory, otherwise use a temp + const Index rows = prod.rows(); + for(Index i=0; i +template +inline const typename ProductReturnType::Type +MatrixBase::operator*(const MatrixBase &other) const +{ + // A note regarding the function declaration: In MSVC, this function will sometimes + // not be inlined since DenseStorage is an unwindable object for dynamic + // matrices and product types are holding a member to store the result. + // Thus it does not help tagging this function with EIGEN_STRONG_INLINE. + enum { + ProductIsValid = Derived::ColsAtCompileTime==Dynamic + || OtherDerived::RowsAtCompileTime==Dynamic + || int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime), + AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime, + SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived) + }; + // note to the lost user: + // * for a dot product use: v1.dot(v2) + // * for a coeff-wise product use: v1.cwiseProduct(v2) + EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes), + INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS) + EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors), + INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION) + EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT) +#ifdef EIGEN_DEBUG_PRODUCT + internal::product_type::debug(); +#endif + return typename ProductReturnType::Type(derived(), other.derived()); +} + +/** \returns an expression of the matrix product of \c *this and \a other without implicit evaluation. + * + * The returned product will behave like any other expressions: the coefficients of the product will be + * computed once at a time as requested. This might be useful in some extremely rare cases when only + * a small and no coherent fraction of the result's coefficients have to be computed. + * + * \warning This version of the matrix product can be much much slower. So use it only if you know + * what you are doing and that you measured a true speed improvement. + * + * \sa operator*(const MatrixBase&) + */ +template +template +const typename LazyProductReturnType::Type +MatrixBase::lazyProduct(const MatrixBase &other) const +{ + enum { + ProductIsValid = Derived::ColsAtCompileTime==Dynamic + || OtherDerived::RowsAtCompileTime==Dynamic + || int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime), + AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime, + SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived) + }; + // note to the lost user: + // * for a dot product use: v1.dot(v2) + // * for a coeff-wise product use: v1.cwiseProduct(v2) + EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes), + INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS) + EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors), + INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION) + EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT) + + return typename LazyProductReturnType::Type(derived(), other.derived()); +} + +} // end namespace Eigen + +#endif // EIGEN_PRODUCT_H diff --git a/extern/Eigen3/Eigen/src/Core/GenericPacketMath.h b/extern/Eigen3/Eigen/src/Core/GenericPacketMath.h index 8ed83532712..858fb243ec8 100644 --- a/extern/Eigen3/Eigen/src/Core/GenericPacketMath.h +++ b/extern/Eigen3/Eigen/src/Core/GenericPacketMath.h @@ -4,28 +4,15 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_GENERIC_PACKET_MATH_H #define EIGEN_GENERIC_PACKET_MATH_H +namespace Eigen { + namespace internal { /** \internal @@ -312,7 +299,7 @@ template struct palign_impl { // by default data are aligned, so there is nothing to be done :) - inline static void run(PacketType&, const PacketType&) {} + static inline void run(PacketType&, const PacketType&) {} }; /** \internal update \a first using the concatenation of the \a Offset last elements @@ -335,5 +322,7 @@ template<> inline std::complex pmul(const std::complex& a, const } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_GENERIC_PACKET_MATH_H diff --git a/extern/Eigen3/Eigen/src/Core/GlobalFunctions.h b/extern/Eigen3/Eigen/src/Core/GlobalFunctions.h index 144145a955c..e63726c4735 100644 --- a/extern/Eigen3/Eigen/src/Core/GlobalFunctions.h +++ b/extern/Eigen3/Eigen/src/Core/GlobalFunctions.h @@ -4,24 +4,9 @@ // Copyright (C) 2010 Gael Guennebaud // Copyright (C) 2010 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_GLOBAL_FUNCTIONS_H #define EIGEN_GLOBAL_FUNCTIONS_H @@ -66,13 +51,36 @@ namespace std template inline const Eigen::CwiseUnaryOp, const Derived> - pow(const Eigen::ArrayBase& x, const typename Derived::Scalar& exponent) { \ - return x.derived().pow(exponent); \ + pow(const Eigen::ArrayBase& x, const typename Derived::Scalar& exponent) { + return x.derived().pow(exponent); + } + + template + inline const Eigen::CwiseBinaryOp, const Derived, const Derived> + pow(const Eigen::ArrayBase& x, const Eigen::ArrayBase& exponents) + { + return Eigen::CwiseBinaryOp, const Derived, const Derived>( + x.derived(), + exponents.derived() + ); } } namespace Eigen { + /** + * \brief Component-wise division of a scalar by array elements. + **/ + template + inline const Eigen::CwiseUnaryOp, const Derived> + operator/(typename Derived::Scalar s, const Eigen::ArrayBase& a) + { + return Eigen::CwiseUnaryOp, const Derived>( + a.derived(), + Eigen::internal::scalar_inverse_mult_op(s) + ); + } + namespace internal { EIGEN_ARRAY_DECLARE_GLOBAL_EIGEN_UNARY(real,scalar_real_op) diff --git a/extern/Eigen3/Eigen/src/Core/IO.h b/extern/Eigen3/Eigen/src/Core/IO.h index f3cfcdbf4a3..cc8e18a0076 100644 --- a/extern/Eigen3/Eigen/src/Core/IO.h +++ b/extern/Eigen3/Eigen/src/Core/IO.h @@ -4,28 +4,15 @@ // Copyright (C) 2006-2008 Benoit Jacob // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_IO_H #define EIGEN_IO_H +namespace Eigen { + enum { DontAlignCols = 1 }; enum { StreamPrecision = -1, FullPrecision = -2 }; @@ -171,7 +158,7 @@ std::ostream & print_matrix(std::ostream & s, const Derived& _m, const IOFormat& return s; } - const typename Derived::Nested m = _m; + typename Derived::Nested m = _m; typedef typename Derived::Scalar Scalar; typedef typename Derived::Index Index; @@ -257,4 +244,6 @@ std::ostream & operator << return internal::print_matrix(s, m.eval(), EIGEN_DEFAULT_IO_FORMAT); } +} // end namespace Eigen + #endif // EIGEN_IO_H diff --git a/extern/Eigen3/Eigen/src/Core/Map.h b/extern/Eigen3/Eigen/src/Core/Map.h index 2bf80b3af3d..15a19226e29 100644 --- a/extern/Eigen3/Eigen/src/Core/Map.h +++ b/extern/Eigen3/Eigen/src/Core/Map.h @@ -4,28 +4,15 @@ // Copyright (C) 2007-2010 Benoit Jacob // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_MAP_H #define EIGEN_MAP_H +namespace Eigen { + /** \class Map * \ingroup Core_Module * @@ -200,4 +187,6 @@ inline Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> this->_set_noalias(Eigen::Map(data)); } +} // end namespace Eigen + #endif // EIGEN_MAP_H diff --git a/extern/Eigen3/Eigen/src/Core/MapBase.h b/extern/Eigen3/Eigen/src/Core/MapBase.h index 9426e2d24dd..a388d61ea92 100644 --- a/extern/Eigen3/Eigen/src/Core/MapBase.h +++ b/extern/Eigen3/Eigen/src/Core/MapBase.h @@ -4,24 +4,9 @@ // Copyright (C) 2007-2010 Benoit Jacob // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_MAPBASE_H #define EIGEN_MAPBASE_H @@ -30,6 +15,7 @@ EIGEN_STATIC_ASSERT((int(internal::traits::Flags) & LinearAccessBit) || Derived::IsVectorAtCompileTime, \ YOU_ARE_TRYING_TO_USE_AN_INDEX_BASED_ACCESSOR_ON_AN_EXPRESSION_THAT_DOES_NOT_SUPPORT_THAT) +namespace Eigen { /** \class MapBase * \ingroup Core_Module @@ -251,5 +237,6 @@ template class MapBase using Base::Base::operator=; }; +} // end namespace Eigen #endif // EIGEN_MAPBASE_H diff --git a/extern/Eigen3/Eigen/src/Core/MathFunctions.h b/extern/Eigen3/Eigen/src/Core/MathFunctions.h index 2b454db21e9..05e913f2fec 100644 --- a/extern/Eigen3/Eigen/src/Core/MathFunctions.h +++ b/extern/Eigen3/Eigen/src/Core/MathFunctions.h @@ -3,28 +3,15 @@ // // Copyright (C) 2006-2010 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_MATHFUNCTIONS_H #define EIGEN_MATHFUNCTIONS_H +namespace Eigen { + namespace internal { /** \internal \struct global_math_functions_filtering_base @@ -309,8 +296,7 @@ struct abs2_impl > { static inline RealScalar run(const std::complex& x) { - using std::norm; - return norm(x); + return real(x)*real(x) + imag(x)*imag(x); } }; @@ -553,7 +539,7 @@ struct pow_default_impl { static inline Scalar run(Scalar x, Scalar y) { - Scalar res = 1; + Scalar res(1); eigen_assert(!NumTraits::IsSigned || y >= 0); if(y & 1) res *= x; y >>= 1; @@ -838,6 +824,19 @@ template<> struct scalar_fuzzy_impl }; +/**************************************************************************** +* Special functions * +****************************************************************************/ + +// std::isfinite is non standard, so let's define our own version, +// even though it is not very efficient. +template bool (isfinite)(const T& x) +{ + return x::highest() && x>NumTraits::lowest(); +} + } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_MATHFUNCTIONS_H diff --git a/extern/Eigen3/Eigen/src/Core/Matrix.h b/extern/Eigen3/Eigen/src/Core/Matrix.h index 982c9256af0..99160b591b0 100644 --- a/extern/Eigen3/Eigen/src/Core/Matrix.h +++ b/extern/Eigen3/Eigen/src/Core/Matrix.h @@ -4,28 +4,15 @@ // Copyright (C) 2006-2010 Benoit Jacob // Copyright (C) 2008-2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_MATRIX_H #define EIGEN_MATRIX_H +namespace Eigen { + /** \class Matrix * \ingroup Core_Module * @@ -411,25 +398,8 @@ EIGEN_MAKE_TYPEDEFS_ALL_SIZES(std::complex, cd) #undef EIGEN_MAKE_TYPEDEFS_ALL_SIZES #undef EIGEN_MAKE_TYPEDEFS +#undef EIGEN_MAKE_FIXED_TYPEDEFS -#undef EIGEN_MAKE_TYPEDEFS_LARGE - -#define EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, SizeSuffix) \ -using Eigen::Matrix##SizeSuffix##TypeSuffix; \ -using Eigen::Vector##SizeSuffix##TypeSuffix; \ -using Eigen::RowVector##SizeSuffix##TypeSuffix; - -#define EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(TypeSuffix) \ -EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 2) \ -EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 3) \ -EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, 4) \ -EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE_AND_SIZE(TypeSuffix, X) \ - -#define EIGEN_USING_MATRIX_TYPEDEFS \ -EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(i) \ -EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(f) \ -EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(d) \ -EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(cf) \ -EIGEN_USING_MATRIX_TYPEDEFS_FOR_TYPE(cd) +} // end namespace Eigen #endif // EIGEN_MATRIX_H diff --git a/extern/Eigen3/Eigen/src/Core/MatrixBase.h b/extern/Eigen3/Eigen/src/Core/MatrixBase.h index 62877bce09e..c1e0ed132cc 100644 --- a/extern/Eigen3/Eigen/src/Core/MatrixBase.h +++ b/extern/Eigen3/Eigen/src/Core/MatrixBase.h @@ -4,28 +4,15 @@ // Copyright (C) 2006-2009 Benoit Jacob // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_MATRIXBASE_H #define EIGEN_MATRIXBASE_H +namespace Eigen { + /** \class MatrixBase * \ingroup Core_Module * @@ -250,8 +237,7 @@ template class MatrixBase // huuuge hack. make Eigen2's matrix.part() work in eigen3. Problem: Diagonal is now a class template instead // of an integer constant. Solution: overload the part() method template wrt template parameters list. - // Note: replacing next line by "template class U>" produces a mysterious error C2082 in MSVC. - template class U> + template class U> const DiagonalWrapper part() const { return diagonal().asDiagonal(); } #endif // EIGEN2_SUPPORT @@ -331,7 +317,7 @@ template class MatrixBase /** \returns an \link ArrayBase Array \endlink expression of this matrix * \sa ArrayBase::matrix() */ ArrayWrapper array() { return derived(); } - const ArrayWrapper array() const { return derived(); } + const ArrayWrapper array() const { return derived(); } /////////// LU module /////////// @@ -466,6 +452,8 @@ template class MatrixBase const MatrixFunctionReturnValue sinh() const; const MatrixFunctionReturnValue cos() const; const MatrixFunctionReturnValue sin() const; + const MatrixSquareRootReturnValue sqrt() const; + const MatrixLogarithmReturnValue log() const; #ifdef EIGEN2_SUPPORT template @@ -512,10 +500,12 @@ template class MatrixBase protected: // mixing arrays and matrices is not legal template Derived& operator+=(const ArrayBase& ) - {EIGEN_STATIC_ASSERT(sizeof(typename OtherDerived::Scalar)==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES);} + {EIGEN_STATIC_ASSERT(std::ptrdiff_t(sizeof(typename OtherDerived::Scalar))==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES); return *this;} // mixing arrays and matrices is not legal template Derived& operator-=(const ArrayBase& ) - {EIGEN_STATIC_ASSERT(sizeof(typename OtherDerived::Scalar)==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES);} + {EIGEN_STATIC_ASSERT(std::ptrdiff_t(sizeof(typename OtherDerived::Scalar))==-1,YOU_CANNOT_MIX_ARRAYS_AND_MATRICES); return *this;} }; +} // end namespace Eigen + #endif // EIGEN_MATRIXBASE_H diff --git a/extern/Eigen3/Eigen/src/Core/NestByValue.h b/extern/Eigen3/Eigen/src/Core/NestByValue.h index a6104d2a426..a893b1761b5 100644 --- a/extern/Eigen3/Eigen/src/Core/NestByValue.h +++ b/extern/Eigen3/Eigen/src/Core/NestByValue.h @@ -4,28 +4,15 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_NESTBYVALUE_H #define EIGEN_NESTBYVALUE_H +namespace Eigen { + /** \class NestByValue * \ingroup Core_Module * @@ -119,4 +106,6 @@ DenseBase::nestByValue() const return NestByValue(derived()); } +} // end namespace Eigen + #endif // EIGEN_NESTBYVALUE_H diff --git a/extern/Eigen3/Eigen/src/Core/NoAlias.h b/extern/Eigen3/Eigen/src/Core/NoAlias.h index da64affcf9a..ecb3fa2850e 100644 --- a/extern/Eigen3/Eigen/src/Core/NoAlias.h +++ b/extern/Eigen3/Eigen/src/Core/NoAlias.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_NOALIAS_H #define EIGEN_NOALIAS_H +namespace Eigen { + /** \class NoAlias * \ingroup Core_Module * @@ -133,4 +120,6 @@ NoAlias MatrixBase::noalias() return derived(); } +} // end namespace Eigen + #endif // EIGEN_NOALIAS_H diff --git a/extern/Eigen3/Eigen/src/Core/NumTraits.h b/extern/Eigen3/Eigen/src/Core/NumTraits.h index 73ef05dfe7a..c94ef026b42 100644 --- a/extern/Eigen3/Eigen/src/Core/NumTraits.h +++ b/extern/Eigen3/Eigen/src/Core/NumTraits.h @@ -3,28 +3,15 @@ // // Copyright (C) 2006-2010 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_NUMTRAITS_H #define EIGEN_NUMTRAITS_H +namespace Eigen { + /** \class NumTraits * \ingroup Core_Module * @@ -81,14 +68,14 @@ template struct GenericNumTraits >::type NonInteger; typedef T Nested; - inline static Real epsilon() { return std::numeric_limits::epsilon(); } - inline static Real dummy_precision() + static inline Real epsilon() { return std::numeric_limits::epsilon(); } + static inline Real dummy_precision() { // make sure to override this for floating-point types return Real(0); } - inline static T highest() { return (std::numeric_limits::max)(); } - inline static T lowest() { return IsInteger ? (std::numeric_limits::min)() : (-(std::numeric_limits::max)()); } + static inline T highest() { return (std::numeric_limits::max)(); } + static inline T lowest() { return IsInteger ? (std::numeric_limits::min)() : (-(std::numeric_limits::max)()); } #ifdef EIGEN2_SUPPORT enum { @@ -104,12 +91,12 @@ template struct NumTraits : GenericNumTraits template<> struct NumTraits : GenericNumTraits { - inline static float dummy_precision() { return 1e-5f; } + static inline float dummy_precision() { return 1e-5f; } }; template<> struct NumTraits : GenericNumTraits { - inline static double dummy_precision() { return 1e-12; } + static inline double dummy_precision() { return 1e-12; } }; template<> struct NumTraits @@ -130,8 +117,8 @@ template struct NumTraits > MulCost = 4 * NumTraits::MulCost + 2 * NumTraits::AddCost }; - inline static Real epsilon() { return NumTraits::epsilon(); } - inline static Real dummy_precision() { return NumTraits::dummy_precision(); } + static inline Real epsilon() { return NumTraits::epsilon(); } + static inline Real dummy_precision() { return NumTraits::dummy_precision(); } }; template @@ -155,6 +142,6 @@ struct NumTraits > }; }; - +} // end namespace Eigen #endif // EIGEN_NUMTRAITS_H diff --git a/extern/Eigen3/Eigen/src/Core/PermutationMatrix.h b/extern/Eigen3/Eigen/src/Core/PermutationMatrix.h index a064e053e51..bc29f814205 100644 --- a/extern/Eigen3/Eigen/src/Core/PermutationMatrix.h +++ b/extern/Eigen3/Eigen/src/Core/PermutationMatrix.h @@ -4,28 +4,15 @@ // Copyright (C) 2009 Benoit Jacob // Copyright (C) 2009-2011 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_PERMUTATIONMATRIX_H #define EIGEN_PERMUTATIONMATRIX_H +namespace Eigen { + template class PermutedImpl; /** \class PermutationBase @@ -56,6 +43,8 @@ namespace internal { template struct permut_matrix_product_retval; +template +struct permut_sparsematrix_product_retval; enum PermPermProduct_t {PermPermProduct}; } // end namespace internal @@ -511,7 +500,7 @@ class PermutationWrapper : public PermutationBase MatrixBase::asPermutation() con return derived(); } +} // end namespace Eigen + #endif // EIGEN_PERMUTATIONMATRIX_H diff --git a/extern/Eigen3/Eigen/src/Core/PlainObjectBase.h b/extern/Eigen3/Eigen/src/Core/PlainObjectBase.h index 612254e9da9..71c74309acc 100644 --- a/extern/Eigen3/Eigen/src/Core/PlainObjectBase.h +++ b/extern/Eigen3/Eigen/src/Core/PlainObjectBase.h @@ -4,24 +4,9 @@ // Copyright (C) 2008-2009 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_DENSESTORAGEBASE_H #define EIGEN_DENSESTORAGEBASE_H @@ -32,6 +17,8 @@ # define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED #endif +namespace Eigen { + namespace internal { template @@ -47,13 +34,13 @@ EIGEN_ALWAYS_INLINE void check_rows_cols_for_overflow(Index rows, Index cols) throw_std_bad_alloc(); } -template (Derived::IsVectorAtCompileTime)> struct conservative_resize_like_impl; +template struct conservative_resize_like_impl; template struct matrix_swap_impl; } // end namespace internal -/** +/** \class PlainObjectBase * \brief %Dense storage base class for matrices and arrays. * * This class can be extended with the help of the plugin mechanism described on the page @@ -61,8 +48,29 @@ template struct m * * \sa \ref TopicClassHierarchy */ +#ifdef EIGEN_PARSED_BY_DOXYGEN +namespace internal { + +// this is a warkaround to doxygen not being able to understand the inheritence logic +// when it is hidden by the dense_xpr_base helper struct. +template struct dense_xpr_base_dispatcher_for_doxygen;// : public MatrixBase {}; +/** This class is just a workaround for Doxygen and it does not not actually exist. */ +template +struct dense_xpr_base_dispatcher_for_doxygen > + : public MatrixBase > {}; +/** This class is just a workaround for Doxygen and it does not not actually exist. */ +template +struct dense_xpr_base_dispatcher_for_doxygen > + : public ArrayBase > {}; + +} // namespace internal + +template +class PlainObjectBase : public internal::dense_xpr_base_dispatcher_for_doxygen +#else template class PlainObjectBase : public internal::dense_xpr_base::type +#endif { public: enum { Options = internal::traits::Options }; @@ -443,68 +451,68 @@ class PlainObjectBase : public internal::dense_xpr_base::type * \see class Map */ //@{ - inline static ConstMapType Map(const Scalar* data) + static inline ConstMapType Map(const Scalar* data) { return ConstMapType(data); } - inline static MapType Map(Scalar* data) + static inline MapType Map(Scalar* data) { return MapType(data); } - inline static ConstMapType Map(const Scalar* data, Index size) + static inline ConstMapType Map(const Scalar* data, Index size) { return ConstMapType(data, size); } - inline static MapType Map(Scalar* data, Index size) + static inline MapType Map(Scalar* data, Index size) { return MapType(data, size); } - inline static ConstMapType Map(const Scalar* data, Index rows, Index cols) + static inline ConstMapType Map(const Scalar* data, Index rows, Index cols) { return ConstMapType(data, rows, cols); } - inline static MapType Map(Scalar* data, Index rows, Index cols) + static inline MapType Map(Scalar* data, Index rows, Index cols) { return MapType(data, rows, cols); } - inline static ConstAlignedMapType MapAligned(const Scalar* data) + static inline ConstAlignedMapType MapAligned(const Scalar* data) { return ConstAlignedMapType(data); } - inline static AlignedMapType MapAligned(Scalar* data) + static inline AlignedMapType MapAligned(Scalar* data) { return AlignedMapType(data); } - inline static ConstAlignedMapType MapAligned(const Scalar* data, Index size) + static inline ConstAlignedMapType MapAligned(const Scalar* data, Index size) { return ConstAlignedMapType(data, size); } - inline static AlignedMapType MapAligned(Scalar* data, Index size) + static inline AlignedMapType MapAligned(Scalar* data, Index size) { return AlignedMapType(data, size); } - inline static ConstAlignedMapType MapAligned(const Scalar* data, Index rows, Index cols) + static inline ConstAlignedMapType MapAligned(const Scalar* data, Index rows, Index cols) { return ConstAlignedMapType(data, rows, cols); } - inline static AlignedMapType MapAligned(Scalar* data, Index rows, Index cols) + static inline AlignedMapType MapAligned(Scalar* data, Index rows, Index cols) { return AlignedMapType(data, rows, cols); } template - inline static typename StridedConstMapType >::type Map(const Scalar* data, const Stride& stride) + static inline typename StridedConstMapType >::type Map(const Scalar* data, const Stride& stride) { return typename StridedConstMapType >::type(data, stride); } template - inline static typename StridedMapType >::type Map(Scalar* data, const Stride& stride) + static inline typename StridedMapType >::type Map(Scalar* data, const Stride& stride) { return typename StridedMapType >::type(data, stride); } template - inline static typename StridedConstMapType >::type Map(const Scalar* data, Index size, const Stride& stride) + static inline typename StridedConstMapType >::type Map(const Scalar* data, Index size, const Stride& stride) { return typename StridedConstMapType >::type(data, size, stride); } template - inline static typename StridedMapType >::type Map(Scalar* data, Index size, const Stride& stride) + static inline typename StridedMapType >::type Map(Scalar* data, Index size, const Stride& stride) { return typename StridedMapType >::type(data, size, stride); } template - inline static typename StridedConstMapType >::type Map(const Scalar* data, Index rows, Index cols, const Stride& stride) + static inline typename StridedConstMapType >::type Map(const Scalar* data, Index rows, Index cols, const Stride& stride) { return typename StridedConstMapType >::type(data, rows, cols, stride); } template - inline static typename StridedMapType >::type Map(Scalar* data, Index rows, Index cols, const Stride& stride) + static inline typename StridedMapType >::type Map(Scalar* data, Index rows, Index cols, const Stride& stride) { return typename StridedMapType >::type(data, rows, cols, stride); } template - inline static typename StridedConstAlignedMapType >::type MapAligned(const Scalar* data, const Stride& stride) + static inline typename StridedConstAlignedMapType >::type MapAligned(const Scalar* data, const Stride& stride) { return typename StridedConstAlignedMapType >::type(data, stride); } template - inline static typename StridedAlignedMapType >::type MapAligned(Scalar* data, const Stride& stride) + static inline typename StridedAlignedMapType >::type MapAligned(Scalar* data, const Stride& stride) { return typename StridedAlignedMapType >::type(data, stride); } template - inline static typename StridedConstAlignedMapType >::type MapAligned(const Scalar* data, Index size, const Stride& stride) + static inline typename StridedConstAlignedMapType >::type MapAligned(const Scalar* data, Index size, const Stride& stride) { return typename StridedConstAlignedMapType >::type(data, size, stride); } template - inline static typename StridedAlignedMapType >::type MapAligned(Scalar* data, Index size, const Stride& stride) + static inline typename StridedAlignedMapType >::type MapAligned(Scalar* data, Index size, const Stride& stride) { return typename StridedAlignedMapType >::type(data, size, stride); } template - inline static typename StridedConstAlignedMapType >::type MapAligned(const Scalar* data, Index rows, Index cols, const Stride& stride) + static inline typename StridedConstAlignedMapType >::type MapAligned(const Scalar* data, Index rows, Index cols, const Stride& stride) { return typename StridedConstAlignedMapType >::type(data, rows, cols, stride); } template - inline static typename StridedAlignedMapType >::type MapAligned(Scalar* data, Index rows, Index cols, const Stride& stride) + static inline typename StridedAlignedMapType >::type MapAligned(Scalar* data, Index rows, Index cols, const Stride& stride) { return typename StridedAlignedMapType >::type(data, rows, cols, stride); } //@} @@ -594,6 +602,9 @@ class PlainObjectBase : public internal::dense_xpr_base::type template EIGEN_STRONG_INLINE void _init2(Index rows, Index cols, typename internal::enable_if::type* = 0) { + EIGEN_STATIC_ASSERT(bool(NumTraits::IsInteger) && + bool(NumTraits::IsInteger), + FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED) eigen_assert(rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows) && cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols)); internal::check_rows_cols_for_overflow(rows, cols); @@ -623,7 +634,7 @@ class PlainObjectBase : public internal::dense_xpr_base::type public: #ifndef EIGEN_PARSED_BY_DOXYGEN - EIGEN_STRONG_INLINE static void _check_template_params() + static EIGEN_STRONG_INLINE void _check_template_params() { EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor) && EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, (Options&RowMajor)==0) @@ -751,4 +762,6 @@ struct matrix_swap_impl } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_DENSESTORAGEBASE_H diff --git a/extern/Eigen3/Eigen/src/Core/Product.h b/extern/Eigen3/Eigen/src/Core/Product.h index e2035b242b1..30aa8943b4c 100644 --- a/extern/Eigen3/Eigen/src/Core/Product.h +++ b/extern/Eigen3/Eigen/src/Core/Product.h @@ -1,625 +1,98 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2006-2008 Benoit Jacob -// Copyright (C) 2008 Gael Guennebaud +// Copyright (C) 2008-2011 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_PRODUCT_H #define EIGEN_PRODUCT_H -/** \class GeneralProduct +template class Product; +template class ProductImpl; + +/** \class Product * \ingroup Core_Module * - * \brief Expression of the product of two general matrices or vectors + * \brief Expression of the product of two arbitrary matrices or vectors * - * \param LhsNested the type used to store the left-hand side - * \param RhsNested the type used to store the right-hand side - * \param ProductMode the type of the product + * \param Lhs the type of the left-hand side expression + * \param Rhs the type of the right-hand side expression * - * This class represents an expression of the product of two general matrices. - * We call a general matrix, a dense matrix with full storage. For instance, - * This excludes triangular, selfadjoint, and sparse matrices. - * It is the return type of the operator* between general matrices. Its template - * arguments are determined automatically by ProductReturnType. Therefore, - * GeneralProduct should never be used direclty. To determine the result type of a - * function which involves a matrix product, use ProductReturnType::Type. + * This class represents an expression of the product of two arbitrary matrices. * - * \sa ProductReturnType, MatrixBase::operator*(const MatrixBase&) */ -template::value> -class GeneralProduct; - -enum { - Large = 2, - Small = 3 -}; namespace internal { - -template struct product_type_selector; - -template struct product_size_category +template +struct traits > { - enum { is_large = MaxSize == Dynamic || - Size >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD, - value = is_large ? Large - : Size == 1 ? 1 - : Small + typedef MatrixXpr XprKind; + typedef typename remove_all::type LhsCleaned; + typedef typename remove_all::type RhsCleaned; + typedef typename scalar_product_traits::Scalar, typename traits::Scalar>::ReturnType Scalar; + typedef typename promote_storage_type::StorageKind, + typename traits::StorageKind>::ret StorageKind; + typedef typename promote_index_type::Index, + typename traits::Index>::type Index; + enum { + RowsAtCompileTime = LhsCleaned::RowsAtCompileTime, + ColsAtCompileTime = RhsCleaned::ColsAtCompileTime, + MaxRowsAtCompileTime = LhsCleaned::MaxRowsAtCompileTime, + MaxColsAtCompileTime = RhsCleaned::MaxColsAtCompileTime, + Flags = (MaxRowsAtCompileTime==1 ? RowMajorBit : 0), // TODO should be no storage order + CoeffReadCost = 0 // TODO CoeffReadCost should not be part of the expression traits }; }; - -template struct product_type -{ - typedef typename remove_all::type _Lhs; - typedef typename remove_all::type _Rhs; - enum { - MaxRows = _Lhs::MaxRowsAtCompileTime, - Rows = _Lhs::RowsAtCompileTime, - MaxCols = _Rhs::MaxColsAtCompileTime, - Cols = _Rhs::ColsAtCompileTime, - MaxDepth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::MaxColsAtCompileTime, - _Rhs::MaxRowsAtCompileTime), - Depth = EIGEN_SIZE_MIN_PREFER_FIXED(_Lhs::ColsAtCompileTime, - _Rhs::RowsAtCompileTime), - LargeThreshold = EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD - }; - - // the splitting into different lines of code here, introducing the _select enums and the typedef below, - // is to work around an internal compiler error with gcc 4.1 and 4.2. -private: - enum { - rows_select = product_size_category::value, - cols_select = product_size_category::value, - depth_select = product_size_category::value - }; - typedef product_type_selector selector; - -public: - enum { - value = selector::ret - }; -#ifdef EIGEN_DEBUG_PRODUCT - static void debug() - { - EIGEN_DEBUG_VAR(Rows); - EIGEN_DEBUG_VAR(Cols); - EIGEN_DEBUG_VAR(Depth); - EIGEN_DEBUG_VAR(rows_select); - EIGEN_DEBUG_VAR(cols_select); - EIGEN_DEBUG_VAR(depth_select); - EIGEN_DEBUG_VAR(value); - } -#endif -}; - - -/* The following allows to select the kind of product at compile time - * based on the three dimensions of the product. - * This is a compile time mapping from {1,Small,Large}^3 -> {product types} */ -// FIXME I'm not sure the current mapping is the ideal one. -template struct product_type_selector { enum { ret = OuterProduct }; }; -template struct product_type_selector<1, 1, Depth> { enum { ret = InnerProduct }; }; -template<> struct product_type_selector<1, 1, 1> { enum { ret = InnerProduct }; }; -template<> struct product_type_selector { enum { ret = CoeffBasedProductMode }; }; -template<> struct product_type_selector<1, Small,Small> { enum { ret = CoeffBasedProductMode }; }; -template<> struct product_type_selector { enum { ret = CoeffBasedProductMode }; }; -template<> struct product_type_selector { enum { ret = LazyCoeffBasedProductMode }; }; -template<> struct product_type_selector { enum { ret = LazyCoeffBasedProductMode }; }; -template<> struct product_type_selector { enum { ret = LazyCoeffBasedProductMode }; }; -template<> struct product_type_selector<1, Large,Small> { enum { ret = CoeffBasedProductMode }; }; -template<> struct product_type_selector<1, Large,Large> { enum { ret = GemvProduct }; }; -template<> struct product_type_selector<1, Small,Large> { enum { ret = CoeffBasedProductMode }; }; -template<> struct product_type_selector { enum { ret = CoeffBasedProductMode }; }; -template<> struct product_type_selector { enum { ret = GemvProduct }; }; -template<> struct product_type_selector { enum { ret = CoeffBasedProductMode }; }; -template<> struct product_type_selector { enum { ret = GemmProduct }; }; -template<> struct product_type_selector { enum { ret = GemmProduct }; }; -template<> struct product_type_selector { enum { ret = GemmProduct }; }; -template<> struct product_type_selector { enum { ret = GemmProduct }; }; -template<> struct product_type_selector { enum { ret = GemmProduct }; }; -template<> struct product_type_selector { enum { ret = GemmProduct }; }; -template<> struct product_type_selector { enum { ret = GemmProduct }; }; - } // end namespace internal -/** \class ProductReturnType - * \ingroup Core_Module - * - * \brief Helper class to get the correct and optimized returned type of operator* - * - * \param Lhs the type of the left-hand side - * \param Rhs the type of the right-hand side - * \param ProductMode the type of the product (determined automatically by internal::product_mode) - * - * This class defines the typename Type representing the optimized product expression - * between two matrix expressions. In practice, using ProductReturnType::Type - * is the recommended way to define the result type of a function returning an expression - * which involve a matrix product. The class Product should never be - * used directly. - * - * \sa class Product, MatrixBase::operator*(const MatrixBase&) - */ -template -struct ProductReturnType -{ - // TODO use the nested type to reduce instanciations ???? -// typedef typename internal::nested::type LhsNested; -// typedef typename internal::nested::type RhsNested; - - typedef GeneralProduct Type; -}; template -struct ProductReturnType -{ - typedef typename internal::nested::type >::type LhsNested; - typedef typename internal::nested::type >::type RhsNested; - typedef CoeffBasedProduct Type; -}; - -template -struct ProductReturnType -{ - typedef typename internal::nested::type >::type LhsNested; - typedef typename internal::nested::type >::type RhsNested; - typedef CoeffBasedProduct Type; -}; - -// this is a workaround for sun CC -template -struct LazyProductReturnType : public ProductReturnType -{}; - -/*********************************************************************** -* Implementation of Inner Vector Vector Product -***********************************************************************/ - -// FIXME : maybe the "inner product" could return a Scalar -// instead of a 1x1 matrix ?? -// Pro: more natural for the user -// Cons: this could be a problem if in a meta unrolled algorithm a matrix-matrix -// product ends up to a row-vector times col-vector product... To tackle this use -// case, we could have a specialization for Block with: operator=(Scalar x); - -namespace internal { - -template -struct traits > - : traits::ReturnType,1,1> > -{}; - -} - -template -class GeneralProduct - : internal::no_assignment_operator, - public Matrix::ReturnType,1,1> -{ - typedef Matrix::ReturnType,1,1> Base; - public: - GeneralProduct(const Lhs& lhs, const Rhs& rhs) - { - EIGEN_STATIC_ASSERT((internal::is_same::value), - YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) - - Base::coeffRef(0,0) = (lhs.transpose().cwiseProduct(rhs)).sum(); - } - - /** Convertion to scalar */ - operator const typename Base::Scalar() const { - return Base::coeff(0,0); - } -}; - -/*********************************************************************** -* Implementation of Outer Vector Vector Product -***********************************************************************/ - -namespace internal { -template struct outer_product_selector; - -template -struct traits > - : traits, Lhs, Rhs> > -{}; - -} - -template -class GeneralProduct - : public ProductBase, Lhs, Rhs> +class Product : public ProductImpl::StorageKind, + typename internal::traits::StorageKind>::ret> { public: - EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct) - - GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) - { - EIGEN_STATIC_ASSERT((internal::is_same::value), - YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) - } - - template void scaleAndAddTo(Dest& dest, Scalar alpha) const - { - internal::outer_product_selector<(int(Dest::Flags)&RowMajorBit) ? RowMajor : ColMajor>::run(*this, dest, alpha); - } -}; - -namespace internal { - -template<> struct outer_product_selector { - template - static EIGEN_DONT_INLINE void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) { - typedef typename Dest::Index Index; - // FIXME make sure lhs is sequentially stored - // FIXME not very good if rhs is real and lhs complex while alpha is real too - const Index cols = dest.cols(); - for (Index j=0; j struct outer_product_selector { - template - static EIGEN_DONT_INLINE void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) { - typedef typename Dest::Index Index; - // FIXME make sure rhs is sequentially stored - // FIXME not very good if lhs is real and rhs complex while alpha is real too - const Index rows = dest.rows(); - for (Index i=0; i call fast BLAS-like colmajor routine - * 2 - the matrix is row-major, BLAS compatible and N is large => call fast BLAS-like rowmajor routine - * 3 - all other cases are handled using a simple loop along the outer-storage direction. - * Therefore we need a lower level meta selector. - * Furthermore, if the matrix is the rhs, then the product has to be transposed. - */ -namespace internal { - -template -struct traits > - : traits, Lhs, Rhs> > -{}; - -template -struct gemv_selector; - -} // end namespace internal - -template -class GeneralProduct - : public ProductBase, Lhs, Rhs> -{ - public: - EIGEN_PRODUCT_PUBLIC_INTERFACE(GeneralProduct) - - typedef typename Lhs::Scalar LhsScalar; - typedef typename Rhs::Scalar RhsScalar; - - GeneralProduct(const Lhs& lhs, const Rhs& rhs) : Base(lhs,rhs) - { -// EIGEN_STATIC_ASSERT((internal::is_same::value), -// YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) - } - - enum { Side = Lhs::IsVectorAtCompileTime ? OnTheLeft : OnTheRight }; - typedef typename internal::conditional::type MatrixType; - - template void scaleAndAddTo(Dest& dst, Scalar alpha) const - { - eigen_assert(m_lhs.rows() == dst.rows() && m_rhs.cols() == dst.cols()); - internal::gemv_selector::HasUsableDirectAccess)>::run(*this, dst, alpha); - } -}; - -namespace internal { - -// The vector is on the left => transposition -template -struct gemv_selector -{ - template - static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) - { - Transpose destT(dest); - enum { OtherStorageOrder = StorageOrder == RowMajor ? ColMajor : RowMajor }; - gemv_selector - ::run(GeneralProduct,Transpose, GemvProduct> - (prod.rhs().transpose(), prod.lhs().transpose()), destT, alpha); - } -}; - -template struct gemv_static_vector_if; - -template -struct gemv_static_vector_if -{ - EIGEN_STRONG_INLINE Scalar* data() { eigen_internal_assert(false && "should never be called"); return 0; } -}; - -template -struct gemv_static_vector_if -{ - EIGEN_STRONG_INLINE Scalar* data() { return 0; } -}; - -template -struct gemv_static_vector_if -{ - #if EIGEN_ALIGN_STATICALLY - internal::plain_array m_data; - EIGEN_STRONG_INLINE Scalar* data() { return m_data.array; } - #else - // Some architectures cannot align on the stack, - // => let's manually enforce alignment by allocating more data and return the address of the first aligned element. - enum { - ForceAlignment = internal::packet_traits::Vectorizable, - PacketSize = internal::packet_traits::size - }; - internal::plain_array m_data; - EIGEN_STRONG_INLINE Scalar* data() { - return ForceAlignment - ? reinterpret_cast((reinterpret_cast(m_data.array) & ~(size_t(15))) + 16) - : m_data.array; - } - #endif -}; - -template<> struct gemv_selector -{ - template - static inline void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) - { - typedef typename ProductType::Index Index; - typedef typename ProductType::LhsScalar LhsScalar; - typedef typename ProductType::RhsScalar RhsScalar; - typedef typename ProductType::Scalar ResScalar; - typedef typename ProductType::RealScalar RealScalar; - typedef typename ProductType::ActualLhsType ActualLhsType; - typedef typename ProductType::ActualRhsType ActualRhsType; - typedef typename ProductType::LhsBlasTraits LhsBlasTraits; - typedef typename ProductType::RhsBlasTraits RhsBlasTraits; - typedef Map, Aligned> MappedDest; - - const ActualLhsType actualLhs = LhsBlasTraits::extract(prod.lhs()); - const ActualRhsType actualRhs = RhsBlasTraits::extract(prod.rhs()); - - ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs()) - * RhsBlasTraits::extractScalarFactor(prod.rhs()); - - enum { - // FIXME find a way to allow an inner stride on the result if packet_traits::size==1 - // on, the other hand it is good for the cache to pack the vector anyways... - EvalToDestAtCompileTime = Dest::InnerStrideAtCompileTime==1, - ComplexByReal = (NumTraits::IsComplex) && (!NumTraits::IsComplex), - MightCannotUseDest = (Dest::InnerStrideAtCompileTime!=1) || ComplexByReal - }; - - gemv_static_vector_if static_dest; - - // this is written like this (i.e., with a ?:) to workaround an ICE with ICC 12 - bool alphaIsCompatible = (!ComplexByReal) ? true : (imag(actualAlpha)==RealScalar(0)); - bool evalToDest = EvalToDestAtCompileTime && alphaIsCompatible; - RhsScalar compatibleAlpha = get_factor::run(actualAlpha); + typedef typename ProductImpl< + Lhs, Rhs, + typename internal::promote_storage_type::ret>::Base Base; + EIGEN_GENERIC_PUBLIC_INTERFACE(Product) - ei_declare_aligned_stack_constructed_variable(ResScalar,actualDestPtr,dest.size(), - evalToDest ? dest.data() : static_dest.data()); - - if(!evalToDest) + typedef typename Lhs::Nested LhsNested; + typedef typename Rhs::Nested RhsNested; + typedef typename internal::remove_all::type LhsNestedCleaned; + typedef typename internal::remove_all::type RhsNestedCleaned; + + Product(const Lhs& lhs, const Rhs& rhs) : m_lhs(lhs), m_rhs(rhs) { - #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN - int size = dest.size(); - EIGEN_DENSE_STORAGE_CTOR_PLUGIN - #endif - if(!alphaIsCompatible) - { - MappedDest(actualDestPtr, dest.size()).setZero(); - compatibleAlpha = RhsScalar(1); - } - else - MappedDest(actualDestPtr, dest.size()) = dest; + eigen_assert(lhs.cols() == rhs.rows() + && "invalid matrix product" + && "if you wanted a coeff-wise or a dot product use the respective explicit functions"); } - general_matrix_vector_product - ::run( - actualLhs.rows(), actualLhs.cols(), - &actualLhs.coeffRef(0,0), actualLhs.outerStride(), - actualRhs.data(), actualRhs.innerStride(), - actualDestPtr, 1, - compatibleAlpha); + inline Index rows() const { return m_lhs.rows(); } + inline Index cols() const { return m_rhs.cols(); } - if (!evalToDest) - { - if(!alphaIsCompatible) - dest += actualAlpha * MappedDest(actualDestPtr, dest.size()); - else - dest = MappedDest(actualDestPtr, dest.size()); - } - } + const LhsNestedCleaned& lhs() const { return m_lhs; } + const RhsNestedCleaned& rhs() const { return m_rhs; } + + protected: + + const LhsNested m_lhs; + const RhsNested m_rhs; }; -template<> struct gemv_selector +template +class ProductImpl : public internal::dense_xpr_base >::type { - template - static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) - { - typedef typename ProductType::LhsScalar LhsScalar; - typedef typename ProductType::RhsScalar RhsScalar; - typedef typename ProductType::Scalar ResScalar; - typedef typename ProductType::Index Index; - typedef typename ProductType::ActualLhsType ActualLhsType; - typedef typename ProductType::ActualRhsType ActualRhsType; - typedef typename ProductType::_ActualRhsType _ActualRhsType; - typedef typename ProductType::LhsBlasTraits LhsBlasTraits; - typedef typename ProductType::RhsBlasTraits RhsBlasTraits; + typedef Product Derived; + public: - typename add_const::type actualLhs = LhsBlasTraits::extract(prod.lhs()); - typename add_const::type actualRhs = RhsBlasTraits::extract(prod.rhs()); - - ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs()) - * RhsBlasTraits::extractScalarFactor(prod.rhs()); - - enum { - // FIXME find a way to allow an inner stride on the result if packet_traits::size==1 - // on, the other hand it is good for the cache to pack the vector anyways... - DirectlyUseRhs = _ActualRhsType::InnerStrideAtCompileTime==1 - }; - - gemv_static_vector_if static_rhs; - - ei_declare_aligned_stack_constructed_variable(RhsScalar,actualRhsPtr,actualRhs.size(), - DirectlyUseRhs ? const_cast(actualRhs.data()) : static_rhs.data()); - - if(!DirectlyUseRhs) - { - #ifdef EIGEN_DENSE_STORAGE_CTOR_PLUGIN - int size = actualRhs.size(); - EIGEN_DENSE_STORAGE_CTOR_PLUGIN - #endif - Map(actualRhsPtr, actualRhs.size()) = actualRhs; - } - - general_matrix_vector_product - ::run( - actualLhs.rows(), actualLhs.cols(), - &actualLhs.coeffRef(0,0), actualLhs.outerStride(), - actualRhsPtr, 1, - &dest.coeffRef(0,0), dest.innerStride(), - actualAlpha); - } + typedef typename internal::dense_xpr_base >::type Base; + EIGEN_DENSE_PUBLIC_INTERFACE(Derived) }; -template<> struct gemv_selector -{ - template - static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) - { - typedef typename Dest::Index Index; - // TODO makes sure dest is sequentially stored in memory, otherwise use a temp - const Index size = prod.rhs().rows(); - for(Index k=0; k struct gemv_selector -{ - template - static void run(const ProductType& prod, Dest& dest, typename ProductType::Scalar alpha) - { - typedef typename Dest::Index Index; - // TODO makes sure rhs is sequentially stored in memory, otherwise use a temp - const Index rows = prod.rows(); - for(Index i=0; i -template -inline const typename ProductReturnType::Type -MatrixBase::operator*(const MatrixBase &other) const -{ - // A note regarding the function declaration: In MSVC, this function will sometimes - // not be inlined since DenseStorage is an unwindable object for dynamic - // matrices and product types are holding a member to store the result. - // Thus it does not help tagging this function with EIGEN_STRONG_INLINE. - enum { - ProductIsValid = Derived::ColsAtCompileTime==Dynamic - || OtherDerived::RowsAtCompileTime==Dynamic - || int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime), - AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime, - SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived) - }; - // note to the lost user: - // * for a dot product use: v1.dot(v2) - // * for a coeff-wise product use: v1.cwiseProduct(v2) - EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes), - INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS) - EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors), - INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION) - EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT) -#ifdef EIGEN_DEBUG_PRODUCT - internal::product_type::debug(); -#endif - return typename ProductReturnType::Type(derived(), other.derived()); -} - -/** \returns an expression of the matrix product of \c *this and \a other without implicit evaluation. - * - * The returned product will behave like any other expressions: the coefficients of the product will be - * computed once at a time as requested. This might be useful in some extremely rare cases when only - * a small and no coherent fraction of the result's coefficients have to be computed. - * - * \warning This version of the matrix product can be much much slower. So use it only if you know - * what you are doing and that you measured a true speed improvement. - * - * \sa operator*(const MatrixBase&) - */ -template -template -const typename LazyProductReturnType::Type -MatrixBase::lazyProduct(const MatrixBase &other) const -{ - enum { - ProductIsValid = Derived::ColsAtCompileTime==Dynamic - || OtherDerived::RowsAtCompileTime==Dynamic - || int(Derived::ColsAtCompileTime)==int(OtherDerived::RowsAtCompileTime), - AreVectors = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime, - SameSizes = EIGEN_PREDICATE_SAME_MATRIX_SIZE(Derived,OtherDerived) - }; - // note to the lost user: - // * for a dot product use: v1.dot(v2) - // * for a coeff-wise product use: v1.cwiseProduct(v2) - EIGEN_STATIC_ASSERT(ProductIsValid || !(AreVectors && SameSizes), - INVALID_VECTOR_VECTOR_PRODUCT__IF_YOU_WANTED_A_DOT_OR_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTIONS) - EIGEN_STATIC_ASSERT(ProductIsValid || !(SameSizes && !AreVectors), - INVALID_MATRIX_PRODUCT__IF_YOU_WANTED_A_COEFF_WISE_PRODUCT_YOU_MUST_USE_THE_EXPLICIT_FUNCTION) - EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT) - - return typename LazyProductReturnType::Type(derived(), other.derived()); -} - #endif // EIGEN_PRODUCT_H diff --git a/extern/Eigen3/Eigen/src/Core/ProductBase.h b/extern/Eigen3/Eigen/src/Core/ProductBase.h index 91975880fdc..ec12e5c9f6b 100644 --- a/extern/Eigen3/Eigen/src/Core/ProductBase.h +++ b/extern/Eigen3/Eigen/src/Core/ProductBase.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_PRODUCTBASE_H #define EIGEN_PRODUCTBASE_H +namespace Eigen { + /** \class ProductBase * \ingroup Core_Module * @@ -115,10 +102,10 @@ class ProductBase : public MatrixBase inline void evalTo(Dest& dst) const { dst.setZero(); scaleAndAddTo(dst,Scalar(1)); } template - inline void addTo(Dest& dst) const { scaleAndAddTo(dst,1); } + inline void addTo(Dest& dst) const { scaleAndAddTo(dst,Scalar(1)); } template - inline void subTo(Dest& dst) const { scaleAndAddTo(dst,-1); } + inline void subTo(Dest& dst) const { scaleAndAddTo(dst,Scalar(-1)); } template inline void scaleAndAddTo(Dest& dst,Scalar alpha) const { derived().scaleAndAddTo(dst,alpha); } @@ -181,8 +168,8 @@ class ProductBase : public MatrixBase protected: - const LhsNested m_lhs; - const RhsNested m_rhs; + LhsNested m_lhs; + RhsNested m_rhs; mutable PlainObject m_result; }; @@ -286,5 +273,6 @@ Derived& MatrixBase::lazyAssign(const ProductBase // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_RANDOM_H #define EIGEN_RANDOM_H +namespace Eigen { + namespace internal { template struct scalar_random_op { @@ -160,4 +147,6 @@ PlainObjectBase::setRandom(Index rows, Index cols) return setRandom(); } +} // end namespace Eigen + #endif // EIGEN_RANDOM_H diff --git a/extern/Eigen3/Eigen/src/Core/Redux.h b/extern/Eigen3/Eigen/src/Core/Redux.h index f9f5a95d546..b7ce7c658a2 100644 --- a/extern/Eigen3/Eigen/src/Core/Redux.h +++ b/extern/Eigen3/Eigen/src/Core/Redux.h @@ -4,28 +4,15 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_REDUX_H #define EIGEN_REDUX_H +namespace Eigen { + namespace internal { // TODO @@ -95,7 +82,7 @@ struct redux_novec_unroller typedef typename Derived::Scalar Scalar; - EIGEN_STRONG_INLINE static Scalar run(const Derived &mat, const Func& func) + static EIGEN_STRONG_INLINE Scalar run(const Derived &mat, const Func& func) { return func(redux_novec_unroller::run(mat,func), redux_novec_unroller::run(mat,func)); @@ -112,7 +99,7 @@ struct redux_novec_unroller typedef typename Derived::Scalar Scalar; - EIGEN_STRONG_INLINE static Scalar run(const Derived &mat, const Func&) + static EIGEN_STRONG_INLINE Scalar run(const Derived &mat, const Func&) { return mat.coeffByOuterInner(outer, inner); } @@ -125,7 +112,7 @@ template struct redux_novec_unroller { typedef typename Derived::Scalar Scalar; - EIGEN_STRONG_INLINE static Scalar run(const Derived&, const Func&) { return Scalar(); } + static EIGEN_STRONG_INLINE Scalar run(const Derived&, const Func&) { return Scalar(); } }; /*** vectorization ***/ @@ -141,7 +128,7 @@ struct redux_vec_unroller typedef typename Derived::Scalar Scalar; typedef typename packet_traits::type PacketScalar; - EIGEN_STRONG_INLINE static PacketScalar run(const Derived &mat, const Func& func) + static EIGEN_STRONG_INLINE PacketScalar run(const Derived &mat, const Func& func) { return func.packetOp( redux_vec_unroller::run(mat,func), @@ -162,7 +149,7 @@ struct redux_vec_unroller typedef typename Derived::Scalar Scalar; typedef typename packet_traits::type PacketScalar; - EIGEN_STRONG_INLINE static PacketScalar run(const Derived &mat, const Func&) + static EIGEN_STRONG_INLINE PacketScalar run(const Derived &mat, const Func&) { return mat.template packetByOuterInner(outer, inner); } @@ -214,20 +201,33 @@ struct redux_impl const Index size = mat.size(); eigen_assert(size && "you are using an empty matrix"); const Index packetSize = packet_traits::size; - const Index alignedStart = first_aligned(mat); + const Index alignedStart = internal::first_aligned(mat); enum { alignment = bool(Derived::Flags & DirectAccessBit) || bool(Derived::Flags & AlignedBit) ? Aligned : Unaligned }; - const Index alignedSize = ((size-alignedStart)/packetSize)*packetSize; - const Index alignedEnd = alignedStart + alignedSize; + const Index alignedSize2 = ((size-alignedStart)/(2*packetSize))*(2*packetSize); + const Index alignedSize = ((size-alignedStart)/(packetSize))*(packetSize); + const Index alignedEnd2 = alignedStart + alignedSize2; + const Index alignedEnd = alignedStart + alignedSize; Scalar res; if(alignedSize) { - PacketScalar packet_res = mat.template packet(alignedStart); - for(Index index = alignedStart + packetSize; index < alignedEnd; index += packetSize) - packet_res = func.packetOp(packet_res, mat.template packet(index)); - res = func.predux(packet_res); + PacketScalar packet_res0 = mat.template packet(alignedStart); + if(alignedSize>packetSize) // we have at least two packets to partly unroll the loop + { + PacketScalar packet_res1 = mat.template packet(alignedStart+packetSize); + for(Index index = alignedStart + 2*packetSize; index < alignedEnd2; index += 2*packetSize) + { + packet_res0 = func.packetOp(packet_res0, mat.template packet(index)); + packet_res1 = func.packetOp(packet_res1, mat.template packet(index+packetSize)); + } + + packet_res0 = func.packetOp(packet_res0,packet_res1); + if(alignedEnd>alignedEnd2) + packet_res0 = func.packetOp(packet_res0, mat.template packet(alignedEnd2)); + } + res = func.predux(packet_res0); for(Index index = 0; index < alignedStart; ++index) res = func(res,mat.coeff(index)); @@ -296,7 +296,7 @@ struct redux_impl Size = Derived::SizeAtCompileTime, VectorizedSize = (Size / PacketSize) * PacketSize }; - EIGEN_STRONG_INLINE static Scalar run(const Derived& mat, const Func& func) + static EIGEN_STRONG_INLINE Scalar run(const Derived& mat, const Func& func) { eigen_assert(mat.rows()>0 && mat.cols()>0 && "you are using an empty matrix"); Scalar res = func.predux(redux_vec_unroller::run(mat,func)); @@ -401,4 +401,6 @@ MatrixBase::trace() const return derived().diagonal().sum(); } +} // end namespace Eigen + #endif // EIGEN_REDUX_H diff --git a/extern/Eigen3/Eigen/src/Core/Replicate.h b/extern/Eigen3/Eigen/src/Core/Replicate.h index 4c171f8d580..b61fdc29e2f 100644 --- a/extern/Eigen3/Eigen/src/Core/Replicate.h +++ b/extern/Eigen3/Eigen/src/Core/Replicate.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_REPLICATE_H #define EIGEN_REPLICATE_H +namespace Eigen { + /** * \class Replicate * \ingroup Core_Module @@ -92,7 +79,7 @@ template class Replicate } template - inline Replicate(const OriginalMatrixType& matrix, int rowFactor, int colFactor) + inline Replicate(const OriginalMatrixType& matrix, Index rowFactor, Index colFactor) : m_matrix(matrix), m_rowFactor(rowFactor), m_colFactor(colFactor) { EIGEN_STATIC_ASSERT((internal::is_same::type,OriginalMatrixType>::value), @@ -127,9 +114,13 @@ template class Replicate return m_matrix.template packet(actual_row, actual_col); } + const _MatrixTypeNested& nestedExpression() const + { + return m_matrix; + } protected: - const MatrixTypeNested m_matrix; + MatrixTypeNested m_matrix; const internal::variable_if_dynamic m_rowFactor; const internal::variable_if_dynamic m_colFactor; }; @@ -181,4 +172,6 @@ VectorwiseOp::replicate(Index factor) const (_expression(),Direction==Vertical?factor:1,Direction==Horizontal?factor:1); } +} // end namespace Eigen + #endif // EIGEN_REPLICATE_H diff --git a/extern/Eigen3/Eigen/src/Core/ReturnByValue.h b/extern/Eigen3/Eigen/src/Core/ReturnByValue.h index 24c5a4e215d..613912ffa8c 100644 --- a/extern/Eigen3/Eigen/src/Core/ReturnByValue.h +++ b/extern/Eigen3/Eigen/src/Core/ReturnByValue.h @@ -4,28 +4,15 @@ // Copyright (C) 2009-2010 Gael Guennebaud // Copyright (C) 2009-2010 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_RETURNBYVALUE_H #define EIGEN_RETURNBYVALUE_H +namespace Eigen { + /** \class ReturnByValue * \ingroup Core_Module * @@ -96,4 +83,6 @@ Derived& DenseBase::operator=(const ReturnByValue& other) return derived(); } +} // end namespace Eigen + #endif // EIGEN_RETURNBYVALUE_H diff --git a/extern/Eigen3/Eigen/src/Core/Reverse.h b/extern/Eigen3/Eigen/src/Core/Reverse.h index 600744ae758..e30ae3d281b 100644 --- a/extern/Eigen3/Eigen/src/Core/Reverse.h +++ b/extern/Eigen3/Eigen/src/Core/Reverse.h @@ -5,28 +5,15 @@ // Copyright (C) 2009 Ricard Marxer // Copyright (C) 2009-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_REVERSE_H #define EIGEN_REVERSE_H +namespace Eigen { + /** \class Reverse * \ingroup Core_Module * @@ -183,8 +170,14 @@ template class Reverse m_matrix.const_cast_derived().template writePacket(m_matrix.size() - index - PacketSize, internal::preverse(x)); } + const typename internal::remove_all::type& + nestedExpression() const + { + return m_matrix; + } + protected: - const typename MatrixType::Nested m_matrix; + typename MatrixType::Nested m_matrix; }; /** \returns an expression of the reverse of *this. @@ -226,5 +219,6 @@ inline void DenseBase::reverseInPlace() derived() = derived().reverse().eval(); } +} // end namespace Eigen #endif // EIGEN_REVERSE_H diff --git a/extern/Eigen3/Eigen/src/Core/Select.h b/extern/Eigen3/Eigen/src/Core/Select.h index d0cd66a261a..2bf6e91d0aa 100644 --- a/extern/Eigen3/Eigen/src/Core/Select.h +++ b/extern/Eigen3/Eigen/src/Core/Select.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SELECT_H #define EIGEN_SELECT_H +namespace Eigen { + /** \class Select * \ingroup Core_Module * @@ -101,10 +88,25 @@ class Select : internal::no_assignment_operator, return m_else.coeff(i); } + const ConditionMatrixType& conditionMatrix() const + { + return m_condition; + } + + const ThenMatrixType& thenMatrix() const + { + return m_then; + } + + const ElseMatrixType& elseMatrix() const + { + return m_else; + } + protected: - const typename ConditionMatrixType::Nested m_condition; - const typename ThenMatrixType::Nested m_then; - const typename ElseMatrixType::Nested m_else; + typename ConditionMatrixType::Nested m_condition; + typename ThenMatrixType::Nested m_then; + typename ElseMatrixType::Nested m_else; }; @@ -155,4 +157,6 @@ DenseBase::select(typename ElseDerived::Scalar thenScalar, derived(), ElseDerived::Constant(rows(),cols(),thenScalar), elseMatrix.derived()); } +} // end namespace Eigen + #endif // EIGEN_SELECT_H diff --git a/extern/Eigen3/Eigen/src/Core/SelfAdjointView.h b/extern/Eigen3/Eigen/src/Core/SelfAdjointView.h index 4bb68755eee..82cc4da736a 100644 --- a/extern/Eigen3/Eigen/src/Core/SelfAdjointView.h +++ b/extern/Eigen3/Eigen/src/Core/SelfAdjointView.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SELFADJOINTMATRIX_H #define EIGEN_SELFADJOINTMATRIX_H +namespace Eigen { + /** \class SelfAdjointView * \ingroup Core_Module * @@ -82,7 +69,7 @@ template class SelfAdjointView }; typedef typename MatrixType::PlainObject PlainObject; - inline SelfAdjointView(const MatrixType& matrix) : m_matrix(matrix) + inline SelfAdjointView(MatrixType& matrix) : m_matrix(matrix) {} inline Index rows() const { return m_matrix.rows(); } @@ -199,7 +186,7 @@ template class SelfAdjointView #endif protected: - const MatrixTypeNested m_matrix; + MatrixTypeNested m_matrix; }; @@ -222,7 +209,7 @@ struct triangular_assignment_selector::run(dst, src); @@ -236,7 +223,7 @@ struct triangular_assignment_selector struct triangular_assignment_selector { - inline static void run(Derived1 &, const Derived2 &) {} + static inline void run(Derived1 &, const Derived2 &) {} }; template @@ -247,7 +234,7 @@ struct triangular_assignment_selector::run(dst, src); @@ -261,14 +248,14 @@ struct triangular_assignment_selector struct triangular_assignment_selector { - inline static void run(Derived1 &, const Derived2 &) {} + static inline void run(Derived1 &, const Derived2 &) {} }; template struct triangular_assignment_selector { typedef typename Derived1::Index Index; - inline static void run(Derived1 &dst, const Derived2 &src) + static inline void run(Derived1 &dst, const Derived2 &src) { for(Index j = 0; j < dst.cols(); ++j) { @@ -285,7 +272,7 @@ struct triangular_assignment_selector struct triangular_assignment_selector { - inline static void run(Derived1 &dst, const Derived2 &src) + static inline void run(Derived1 &dst, const Derived2 &src) { typedef typename Derived1::Index Index; for(Index i = 0; i < dst.rows(); ++i) @@ -322,4 +309,6 @@ MatrixBase::selfadjointView() return derived(); } +} // end namespace Eigen + #endif // EIGEN_SELFADJOINTMATRIX_H diff --git a/extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h b/extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h index 4e9ca88745d..0caf2bab1d8 100644 --- a/extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h +++ b/extern/Eigen3/Eigen/src/Core/SelfCwiseBinaryOp.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SELFCWISEBINARYOP_H #define EIGEN_SELFCWISEBINARYOP_H +namespace Eigen { + /** \class SelfCwiseBinaryOp * \ingroup Core_Module * @@ -163,6 +150,16 @@ template class SelfCwiseBinaryOp return Base::operator=(rhs); } + Lhs& expression() const + { + return m_matrix; + } + + const BinaryOp& functor() const + { + return m_functor; + } + protected: Lhs& m_matrix; const BinaryOp& m_functor; @@ -192,4 +189,6 @@ inline Derived& DenseBase::operator/=(const Scalar& other) return derived(); } +} // end namespace Eigen + #endif // EIGEN_SELFCWISEBINARYOP_H diff --git a/extern/Eigen3/Eigen/src/Core/SolveTriangular.h b/extern/Eigen3/Eigen/src/Core/SolveTriangular.h index a23014a343f..ef17f288e29 100644 --- a/extern/Eigen3/Eigen/src/Core/SolveTriangular.h +++ b/extern/Eigen3/Eigen/src/Core/SolveTriangular.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008-2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SOLVETRIANGULAR_H #define EIGEN_SOLVETRIANGULAR_H +namespace Eigen { + namespace internal { // Forward declarations: @@ -98,12 +85,22 @@ struct triangular_solver_selector typedef typename Rhs::Index Index; typedef blas_traits LhsProductTraits; typedef typename LhsProductTraits::DirectLinearAccessType ActualLhsType; + static void run(const Lhs& lhs, Rhs& rhs) { - const ActualLhsType actualLhs = LhsProductTraits::extract(lhs); + typename internal::add_const_on_value_type::type actualLhs = LhsProductTraits::extract(lhs); + + const Index size = lhs.rows(); + const Index othersize = Side==OnTheLeft? rhs.cols() : rhs.rows(); + + typedef internal::gemm_blocking_space<(Rhs::Flags&RowMajorBit) ? RowMajor : ColMajor,Scalar,Scalar, + Rhs::MaxRowsAtCompileTime, Rhs::MaxColsAtCompileTime, Lhs::MaxRowsAtCompileTime,4> BlockingType; + + BlockingType blocking(rhs.rows(), rhs.cols(), size); + triangular_solve_matrix - ::run(lhs.rows(), Side==OnTheLeft? rhs.cols() : rhs.rows(), &actualLhs.coeffRef(0,0), actualLhs.outerStride(), &rhs.coeffRef(0,0), rhs.outerStride()); + ::run(size, othersize, &actualLhs.coeffRef(0,0), actualLhs.outerStride(), &rhs.coeffRef(0,0), rhs.outerStride(), blocking); } }; @@ -177,10 +174,8 @@ template void TriangularView::solveInPlace(const MatrixBase& _other) const { OtherDerived& other = _other.const_cast_derived(); - eigen_assert(cols() == rows()); - eigen_assert( (Side==OnTheLeft && cols() == other.rows()) || (Side==OnTheRight && cols() == other.cols()) ); - eigen_assert(!(Mode & ZeroDiag)); - eigen_assert((Mode & (Upper|Lower)) != 0); + eigen_assert( cols() == rows() && ((Side==OnTheLeft && cols() == other.rows()) || (Side==OnTheRight && cols() == other.cols())) ); + eigen_assert((!(Mode & ZeroDiag)) && bool(Mode & (Upper|Lower))); enum { copy = internal::traits::Flags & RowMajorBit && OtherDerived::IsVectorAtCompileTime }; typedef typename internal::conditional struct triangular_solv protected: const TriangularType& m_triangularMatrix; - const typename Rhs::Nested m_rhs; + typename Rhs::Nested m_rhs; }; } // namespace internal +} // end namespace Eigen + #endif // EIGEN_SOLVETRIANGULAR_H diff --git a/extern/Eigen3/Eigen/src/Core/StableNorm.h b/extern/Eigen3/Eigen/src/Core/StableNorm.h index f667272e4a4..d8bf7db70e4 100644 --- a/extern/Eigen3/Eigen/src/Core/StableNorm.h +++ b/extern/Eigen3/Eigen/src/Core/StableNorm.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_STABLENORM_H #define EIGEN_STABLENORM_H +namespace Eigen { + namespace internal { template inline void stable_norm_kernel(const ExpressionType& bl, Scalar& ssq, Scalar& scale, Scalar& invScale) @@ -58,9 +45,9 @@ MatrixBase::stableNorm() const { using std::min; const Index blockSize = 4096; - RealScalar scale = 0; - RealScalar invScale = 1; - RealScalar ssq = 0; // sum of square + RealScalar scale(0); + RealScalar invScale(1); + RealScalar ssq(0); // sum of square enum { Alignment = (int(Flags)&DirectAccessBit) || (int(Flags)&AlignedBit) ? 1 : 0 }; @@ -187,4 +174,6 @@ MatrixBase::hypotNorm() const return this->cwiseAbs().redux(internal::scalar_hypot_op()); } +} // end namespace Eigen + #endif // EIGEN_STABLENORM_H diff --git a/extern/Eigen3/Eigen/src/Core/Stride.h b/extern/Eigen3/Eigen/src/Core/Stride.h index 0430f111627..1e3f5fe9fff 100644 --- a/extern/Eigen3/Eigen/src/Core/Stride.h +++ b/extern/Eigen3/Eigen/src/Core/Stride.h @@ -3,28 +3,15 @@ // // Copyright (C) 2010 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_STRIDE_H #define EIGEN_STRIDE_H +namespace Eigen { + /** \class Stride * \ingroup Core_Module * @@ -116,4 +103,6 @@ class OuterStride : public Stride OuterStride(Index v) : Base(v,0) {} }; +} // end namespace Eigen + #endif // EIGEN_STRIDE_H diff --git a/extern/Eigen3/Eigen/src/Core/Swap.h b/extern/Eigen3/Eigen/src/Core/Swap.h index 5fb03286675..fd73cf3ad7e 100644 --- a/extern/Eigen3/Eigen/src/Core/Swap.h +++ b/extern/Eigen3/Eigen/src/Core/Swap.h @@ -3,28 +3,15 @@ // // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SWAP_H #define EIGEN_SWAP_H +namespace Eigen { + /** \class SwapWrapper * \ingroup Core_Module * @@ -52,6 +39,15 @@ template class SwapWrapper inline Index cols() const { return m_expression.cols(); } inline Index outerStride() const { return m_expression.outerStride(); } inline Index innerStride() const { return m_expression.innerStride(); } + + typedef typename internal::conditional< + internal::is_lvalue::value, + Scalar, + const Scalar + >::type ScalarWithConstIfNotLvalue; + + inline ScalarWithConstIfNotLvalue* data() { return m_expression.data(); } + inline const Scalar* data() const { return m_expression.data(); } inline Scalar& coeffRef(Index row, Index col) { @@ -119,8 +115,12 @@ template class SwapWrapper _other.template writePacket(index, tmp); } + ExpressionType& expression() const { return m_expression; } + protected: ExpressionType& m_expression; }; +} // end namespace Eigen + #endif // EIGEN_SWAP_H diff --git a/extern/Eigen3/Eigen/src/Core/Transpose.h b/extern/Eigen3/Eigen/src/Core/Transpose.h index 3f7c7df6ee1..045a1cce671 100644 --- a/extern/Eigen3/Eigen/src/Core/Transpose.h +++ b/extern/Eigen3/Eigen/src/Core/Transpose.h @@ -4,28 +4,15 @@ // Copyright (C) 2006-2008 Benoit Jacob // Copyright (C) 2009-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_TRANSPOSE_H #define EIGEN_TRANSPOSE_H +namespace Eigen { + /** \class Transpose * \ingroup Core_Module * @@ -91,7 +78,7 @@ template class Transpose nestedExpression() { return m_matrix.const_cast_derived(); } protected: - const typename MatrixType::Nested m_matrix; + typename MatrixType::Nested m_matrix; }; namespace internal { @@ -152,12 +139,12 @@ template class TransposeImpl return derived().nestedExpression().coeffRef(index); } - inline const CoeffReturnType coeff(Index row, Index col) const + inline CoeffReturnType coeff(Index row, Index col) const { return derived().nestedExpression().coeff(col, row); } - inline const CoeffReturnType coeff(Index index) const + inline CoeffReturnType coeff(Index index) const { return derived().nestedExpression().coeff(index); } @@ -422,4 +409,6 @@ void DenseBase::checkTransposeAliasing(const OtherDerived& other) const } #endif +} // end namespace Eigen + #endif // EIGEN_TRANSPOSE_H diff --git a/extern/Eigen3/Eigen/src/Core/Transpositions.h b/extern/Eigen3/Eigen/src/Core/Transpositions.h index 88fdfb2226f..2cd268a5fa0 100644 --- a/extern/Eigen3/Eigen/src/Core/Transpositions.h +++ b/extern/Eigen3/Eigen/src/Core/Transpositions.h @@ -3,28 +3,15 @@ // // Copyright (C) 2010-2011 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_TRANSPOSITIONS_H #define EIGEN_TRANSPOSITIONS_H +namespace Eigen { + /** \class Transpositions * \ingroup Core_Module * @@ -404,7 +391,7 @@ struct transposition_matrix_product_retval protected: const TranspositionType& m_transpositions; - const typename MatrixType::Nested m_matrix; + typename MatrixType::Nested m_matrix; }; } // end namespace internal @@ -444,4 +431,6 @@ class Transpose > const TranspositionType& m_transpositions; }; +} // end namespace Eigen + #endif // EIGEN_TRANSPOSITIONS_H diff --git a/extern/Eigen3/Eigen/src/Core/TriangularMatrix.h b/extern/Eigen3/Eigen/src/Core/TriangularMatrix.h index 033e81036f3..de9540063c2 100644 --- a/extern/Eigen3/Eigen/src/Core/TriangularMatrix.h +++ b/extern/Eigen3/Eigen/src/Core/TriangularMatrix.h @@ -4,28 +4,15 @@ // Copyright (C) 2008 Benoit Jacob // Copyright (C) 2008-2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_TRIANGULARMATRIX_H #define EIGEN_TRIANGULARMATRIX_H +namespace Eigen { + namespace internal { template struct triangular_solve_retval; @@ -273,11 +260,8 @@ template class TriangularView inline const TriangularView conjugate() const { return m_matrix.conjugate(); } - /** \sa MatrixBase::adjoint() */ - inline TriangularView adjoint() - { return m_matrix.adjoint(); } /** \sa MatrixBase::adjoint() const */ - inline const TriangularView adjoint() const + inline const TriangularView adjoint() const { return m_matrix.adjoint(); } /** \sa MatrixBase::transpose() */ @@ -288,11 +272,13 @@ template class TriangularView } /** \sa MatrixBase::transpose() const */ inline const TriangularView,TransposeMode> transpose() const - { return m_matrix.transpose(); } + { + return m_matrix.transpose(); + } /** Efficient triangular matrix times vector/matrix product */ template - TriangularProduct + TriangularProduct operator*(const MatrixBase& rhs) const { return TriangularProduct @@ -375,7 +361,8 @@ template class TriangularView template void swap(MatrixBase const & other) { - TriangularView,Mode>(const_cast(m_matrix)).lazyAssign(other.derived()); + SwapWrapper swaper(const_cast(m_matrix)); + TriangularView,Mode>(swaper).lazyAssign(other.derived()); } Scalar determinant() const @@ -433,7 +420,7 @@ template class TriangularView template EIGEN_STRONG_INLINE TriangularView& assignProduct(const ProductBase& prod, const Scalar& alpha); - const MatrixTypeNested m_matrix; + MatrixTypeNested m_matrix; }; /*************************************************************************** @@ -452,7 +439,7 @@ struct triangular_assignment_selector typedef typename Derived1::Scalar Scalar; - inline static void run(Derived1 &dst, const Derived2 &src) + static inline void run(Derived1 &dst, const Derived2 &src) { triangular_assignment_selector::run(dst, src); @@ -480,7 +467,7 @@ struct triangular_assignment_selector template struct triangular_assignment_selector { - inline static void run(Derived1 &, const Derived2 &) {} + static inline void run(Derived1 &, const Derived2 &) {} }; template @@ -488,7 +475,7 @@ struct triangular_assignment_selector struct triangular_assignment_selector { typedef typename Derived1::Index Index; - inline static void run(Derived1 &dst, const Derived2 &src) + static inline void run(Derived1 &dst, const Derived2 &src) { for(Index j = 0; j < dst.cols(); ++j) { @@ -524,7 +511,7 @@ template struct triangular_assignment_selector { typedef typename Derived1::Index Index; - inline static void run(Derived1 &dst, const Derived2 &src) + static inline void run(Derived1 &dst, const Derived2 &src) { for(Index j = 0; j < dst.cols(); ++j) { @@ -542,7 +529,7 @@ template struct triangular_assignment_selector { typedef typename Derived1::Index Index; - inline static void run(Derived1 &dst, const Derived2 &src) + static inline void run(Derived1 &dst, const Derived2 &src) { for(Index j = 0; j < dst.cols(); ++j) { @@ -560,7 +547,7 @@ template struct triangular_assignment_selector { typedef typename Derived1::Index Index; - inline static void run(Derived1 &dst, const Derived2 &src) + static inline void run(Derived1 &dst, const Derived2 &src) { for(Index j = 0; j < dst.cols(); ++j) { @@ -580,7 +567,7 @@ template struct triangular_assignment_selector { typedef typename Derived1::Index Index; - inline static void run(Derived1 &dst, const Derived2 &src) + static inline void run(Derived1 &dst, const Derived2 &src) { for(Index j = 0; j < dst.cols(); ++j) { @@ -835,4 +822,6 @@ bool MatrixBase::isLowerTriangular(RealScalar prec) const return true; } +} // end namespace Eigen + #endif // EIGEN_TRIANGULARMATRIX_H diff --git a/extern/Eigen3/Eigen/src/Core/VectorBlock.h b/extern/Eigen3/Eigen/src/Core/VectorBlock.h index 858e4c7865a..6f4effca055 100644 --- a/extern/Eigen3/Eigen/src/Core/VectorBlock.h +++ b/extern/Eigen3/Eigen/src/Core/VectorBlock.h @@ -4,28 +4,15 @@ // Copyright (C) 2008-2010 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_VECTORBLOCK_H #define EIGEN_VECTORBLOCK_H +namespace Eigen { + /** \class VectorBlock * \ingroup Core_Module * @@ -292,5 +279,6 @@ DenseBase::tail() const return typename ConstFixedSegmentReturnType::Type(derived(), size() - Size); } +} // end namespace Eigen #endif // EIGEN_VECTORBLOCK_H diff --git a/extern/Eigen3/Eigen/src/Core/VectorwiseOp.h b/extern/Eigen3/Eigen/src/Core/VectorwiseOp.h index 20f6881575b..862c0f33608 100644 --- a/extern/Eigen3/Eigen/src/Core/VectorwiseOp.h +++ b/extern/Eigen3/Eigen/src/Core/VectorwiseOp.h @@ -4,28 +4,15 @@ // Copyright (C) 2008-2010 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_PARTIAL_REDUX_H #define EIGEN_PARTIAL_REDUX_H +namespace Eigen { + /** \class PartialReduxExpr * \ingroup Core_Module * @@ -110,7 +97,7 @@ class PartialReduxExpr : internal::no_assignment_operator, } protected: - const MatrixTypeNested m_matrix; + MatrixTypeNested m_matrix; const MemberOp m_functor; }; @@ -237,7 +224,10 @@ template class VectorwiseOp typename ExtendedType::Type extendedTo(const DenseBase& other) const { - EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived); + EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(Direction==Vertical, OtherDerived::MaxColsAtCompileTime==1), + YOU_PASSED_A_ROW_VECTOR_BUT_A_COLUMN_VECTOR_WAS_EXPECTED) + EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(Direction==Horizontal, OtherDerived::MaxRowsAtCompileTime==1), + YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED) return typename ExtendedType::Type (other.derived(), Direction==Vertical ? 1 : m_matrix.rows(), @@ -418,10 +408,9 @@ template class VectorwiseOp ExpressionType& operator=(const DenseBase& other) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) + EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived) //eigen_assert((m_matrix.isNull()) == (other.isNull())); FIXME - for(Index j=0; j(m_matrix); + return const_cast(m_matrix = extendedTo(other.derived())); } /** Adds the vector \a other to each subvector of \c *this */ @@ -429,9 +418,8 @@ template class VectorwiseOp ExpressionType& operator+=(const DenseBase& other) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) - for(Index j=0; j(m_matrix); + EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived) + return const_cast(m_matrix += extendedTo(other.derived())); } /** Substracts the vector \a other to each subvector of \c *this */ @@ -439,8 +427,29 @@ template class VectorwiseOp ExpressionType& operator-=(const DenseBase& other) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) - for(Index j=0; j(m_matrix -= extendedTo(other.derived())); + } + + /** Multiples each subvector of \c *this by the vector \a other */ + template + ExpressionType& operator*=(const DenseBase& other) + { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) + EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType) + EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived) + m_matrix *= extendedTo(other.derived()); + return const_cast(m_matrix); + } + + /** Divides each subvector of \c *this by the vector \a other */ + template + ExpressionType& operator/=(const DenseBase& other) + { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) + EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType) + EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived) + m_matrix /= extendedTo(other.derived()); return const_cast(m_matrix); } @@ -451,7 +460,8 @@ template class VectorwiseOp const typename ExtendedType::Type> operator+(const DenseBase& other) const { - EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived); + EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) + EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived) return m_matrix + extendedTo(other.derived()); } @@ -462,10 +472,39 @@ template class VectorwiseOp const typename ExtendedType::Type> operator-(const DenseBase& other) const { - EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived); + EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) + EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived) return m_matrix - extendedTo(other.derived()); } + /** Returns the expression where each subvector is the product of the vector \a other + * by the corresponding subvector of \c *this */ + template EIGEN_STRONG_INLINE + CwiseBinaryOp, + const ExpressionTypeNestedCleaned, + const typename ExtendedType::Type> + operator*(const DenseBase& other) const + { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) + EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType) + EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived) + return m_matrix * extendedTo(other.derived()); + } + + /** Returns the expression where each subvector is the quotient of the corresponding + * subvector of \c *this by the vector \a other */ + template + CwiseBinaryOp, + const ExpressionTypeNestedCleaned, + const typename ExtendedType::Type> + operator/(const DenseBase& other) const + { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) + EIGEN_STATIC_ASSERT_ARRAYXPR(ExpressionType) + EIGEN_STATIC_ASSERT_SAME_XPR_KIND(ExpressionType, OtherDerived) + return m_matrix / extendedTo(other.derived()); + } + /////////// Geometry module /////////// #if EIGEN2_SUPPORT_STAGE > STAGE20_RESOLVE_API_CONFLICTS @@ -509,7 +548,7 @@ template class VectorwiseOp * Example: \include MatrixBase_colwise.cpp * Output: \verbinclude MatrixBase_colwise.out * - * \sa rowwise(), class VectorwiseOp + * \sa rowwise(), class VectorwiseOp, \ref TutorialReductionsVisitorsBroadcasting */ template inline const typename DenseBase::ConstColwiseReturnType @@ -520,7 +559,7 @@ DenseBase::colwise() const /** \returns a writable VectorwiseOp wrapper of *this providing additional partial reduction operations * - * \sa rowwise(), class VectorwiseOp + * \sa rowwise(), class VectorwiseOp, \ref TutorialReductionsVisitorsBroadcasting */ template inline typename DenseBase::ColwiseReturnType @@ -534,7 +573,7 @@ DenseBase::colwise() * Example: \include MatrixBase_rowwise.cpp * Output: \verbinclude MatrixBase_rowwise.out * - * \sa colwise(), class VectorwiseOp + * \sa colwise(), class VectorwiseOp, \ref TutorialReductionsVisitorsBroadcasting */ template inline const typename DenseBase::ConstRowwiseReturnType @@ -545,7 +584,7 @@ DenseBase::rowwise() const /** \returns a writable VectorwiseOp wrapper of *this providing additional partial reduction operations * - * \sa colwise(), class VectorwiseOp + * \sa colwise(), class VectorwiseOp, \ref TutorialReductionsVisitorsBroadcasting */ template inline typename DenseBase::RowwiseReturnType @@ -554,4 +593,6 @@ DenseBase::rowwise() return derived(); } +} // end namespace Eigen + #endif // EIGEN_PARTIAL_REDUX_H diff --git a/extern/Eigen3/Eigen/src/Core/Visitor.h b/extern/Eigen3/Eigen/src/Core/Visitor.h index 378ebcba174..916bfd096a9 100644 --- a/extern/Eigen3/Eigen/src/Core/Visitor.h +++ b/extern/Eigen3/Eigen/src/Core/Visitor.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_VISITOR_H #define EIGEN_VISITOR_H +namespace Eigen { + namespace internal { template @@ -35,7 +22,7 @@ struct visitor_impl row = (UnrollCount-1) % Derived::RowsAtCompileTime }; - inline static void run(const Derived &mat, Visitor& visitor) + static inline void run(const Derived &mat, Visitor& visitor) { visitor_impl::run(mat, visitor); visitor(mat.coeff(row, col), row, col); @@ -45,7 +32,7 @@ struct visitor_impl template struct visitor_impl { - inline static void run(const Derived &mat, Visitor& visitor) + static inline void run(const Derived &mat, Visitor& visitor) { return visitor.init(mat.coeff(0, 0), 0, 0); } @@ -55,7 +42,7 @@ template struct visitor_impl { typedef typename Derived::Index Index; - inline static void run(const Derived& mat, Visitor& visitor) + static inline void run(const Derived& mat, Visitor& visitor) { visitor.init(mat.coeff(0,0), 0, 0); for(Index i = 1; i < mat.rows(); ++i) @@ -245,4 +232,6 @@ DenseBase::maxCoeff(IndexType* index) const return maxVisitor.res; } +} // end namespace Eigen + #endif // EIGEN_VISITOR_H diff --git a/extern/Eigen3/Eigen/src/Core/arch/AltiVec/Complex.h b/extern/Eigen3/Eigen/src/Core/arch/AltiVec/Complex.h index f8adf1b6385..68d9a2bff8d 100644 --- a/extern/Eigen3/Eigen/src/Core/arch/AltiVec/Complex.h +++ b/extern/Eigen3/Eigen/src/Core/arch/AltiVec/Complex.h @@ -3,28 +3,15 @@ // // Copyright (C) 2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_COMPLEX_ALTIVEC_H #define EIGEN_COMPLEX_ALTIVEC_H +namespace Eigen { + namespace internal { static Packet4ui p4ui_CONJ_XOR = vec_mergeh((Packet4ui)p4i_ZERO, (Packet4ui)p4f_ZERO_);//{ 0x00000000, 0x80000000, 0x00000000, 0x80000000 }; @@ -168,7 +155,7 @@ template<> EIGEN_STRONG_INLINE std::complex predux_mul(const P template struct palign_impl { - EIGEN_STRONG_INLINE static void run(Packet2cf& first, const Packet2cf& second) + static EIGEN_STRONG_INLINE void run(Packet2cf& first, const Packet2cf& second) { if (Offset==1) { @@ -225,4 +212,6 @@ template<> EIGEN_STRONG_INLINE Packet2cf pcplxflip(const Packet2cf& x } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_COMPLEX_ALTIVEC_H diff --git a/extern/Eigen3/Eigen/src/Core/arch/AltiVec/PacketMath.h b/extern/Eigen3/Eigen/src/Core/arch/AltiVec/PacketMath.h index dc34ebbd660..75de1931198 100644 --- a/extern/Eigen3/Eigen/src/Core/arch/AltiVec/PacketMath.h +++ b/extern/Eigen3/Eigen/src/Core/arch/AltiVec/PacketMath.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008 Konstantinos Margaritis // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_PACKET_MATH_ALTIVEC_H #define EIGEN_PACKET_MATH_ALTIVEC_H +namespace Eigen { + namespace internal { #ifndef EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD @@ -487,7 +474,7 @@ template<> EIGEN_STRONG_INLINE int predux_max(const Packet4i& a) template struct palign_impl { - EIGEN_STRONG_INLINE static void run(Packet4f& first, const Packet4f& second) + static EIGEN_STRONG_INLINE void run(Packet4f& first, const Packet4f& second) { if (Offset!=0) first = vec_sld(first, second, Offset*4); @@ -497,7 +484,7 @@ struct palign_impl template struct palign_impl { - EIGEN_STRONG_INLINE static void run(Packet4i& first, const Packet4i& second) + static EIGEN_STRONG_INLINE void run(Packet4i& first, const Packet4i& second) { if (Offset!=0) first = vec_sld(first, second, Offset*4); @@ -506,4 +493,6 @@ struct palign_impl } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_PACKET_MATH_ALTIVEC_H diff --git a/extern/Eigen3/Eigen/src/Core/arch/Default/Settings.h b/extern/Eigen3/Eigen/src/Core/arch/Default/Settings.h index 957adc8fe42..097373c84dc 100644 --- a/extern/Eigen3/Eigen/src/Core/arch/Default/Settings.h +++ b/extern/Eigen3/Eigen/src/Core/arch/Default/Settings.h @@ -4,24 +4,9 @@ // Copyright (C) 2008-2010 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. /* All the parameters defined in this file can be specialized in the diff --git a/extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h b/extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h index 212887184c2..795b4be7303 100644 --- a/extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h +++ b/extern/Eigen3/Eigen/src/Core/arch/NEON/Complex.h @@ -3,28 +3,15 @@ // // Copyright (C) 2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_COMPLEX_NEON_H #define EIGEN_COMPLEX_NEON_H +namespace Eigen { + namespace internal { static uint32x4_t p4ui_CONJ_XOR = EIGEN_INIT_NEON_PACKET4(0x00000000, 0x80000000, 0x00000000, 0x80000000); @@ -267,4 +254,6 @@ template<> EIGEN_STRONG_INLINE Packet2cf pdiv(const Packet2cf& a, con } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_COMPLEX_NEON_H diff --git a/extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h b/extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h index 6c7cd159097..a20250f7c65 100644 --- a/extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h +++ b/extern/Eigen3/Eigen/src/Core/arch/NEON/PacketMath.h @@ -5,28 +5,15 @@ // Copyright (C) 2010 Konstantinos Margaritis // Heavily based on Gael's SSE version. // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_PACKET_MATH_NEON_H #define EIGEN_PACKET_MATH_NEON_H +namespace Eigen { + namespace internal { #ifndef EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD @@ -158,7 +145,8 @@ template<> EIGEN_STRONG_INLINE Packet4i pdiv(const Packet4i& /*a*/, co } // for some weird raisons, it has to be overloaded for packet of integers -template<> EIGEN_STRONG_INLINE Packet4i pmadd(const Packet4i& a, const Packet4i& b, const Packet4i& c) { return padd(pmul(a,b), c); } +template<> EIGEN_STRONG_INLINE Packet4f pmadd(const Packet4f& a, const Packet4f& b, const Packet4f& c) { return vmlaq_f32(c,a,b); } +template<> EIGEN_STRONG_INLINE Packet4i pmadd(const Packet4i& a, const Packet4i& b, const Packet4i& c) { return vmlaq_s32(c,a,b); } template<> EIGEN_STRONG_INLINE Packet4f pmin(const Packet4f& a, const Packet4f& b) { return vminq_f32(a,b); } template<> EIGEN_STRONG_INLINE Packet4i pmin(const Packet4i& a, const Packet4i& b) { return vminq_s32(a,b); } @@ -431,4 +419,6 @@ PALIGN_NEON(3,Packet4i,vextq_s32) } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_PACKET_MATH_NEON_H diff --git a/extern/Eigen3/Eigen/src/Core/arch/SSE/Complex.h b/extern/Eigen3/Eigen/src/Core/arch/SSE/Complex.h index c352bb3e6cf..12df987754c 100644 --- a/extern/Eigen3/Eigen/src/Core/arch/SSE/Complex.h +++ b/extern/Eigen3/Eigen/src/Core/arch/SSE/Complex.h @@ -3,28 +3,15 @@ // // Copyright (C) 2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_COMPLEX_SSE_H #define EIGEN_COMPLEX_SSE_H +namespace Eigen { + namespace internal { //---------- float ---------- @@ -102,7 +89,7 @@ template<> EIGEN_STRONG_INLINE Packet2cf pset1(const std::complex(&from)); #else res.v = _mm_loadl_pi(res.v, (const __m64*)&from); #endif @@ -151,7 +138,7 @@ template<> EIGEN_STRONG_INLINE std::complex predux_mul(const P template struct palign_impl { - EIGEN_STRONG_INLINE static void run(Packet2cf& first, const Packet2cf& second) + static EIGEN_STRONG_INLINE void run(Packet2cf& first, const Packet2cf& second) { if (Offset==1) { @@ -350,7 +337,7 @@ template<> EIGEN_STRONG_INLINE std::complex predux_mul(const template struct palign_impl { - EIGEN_STRONG_INLINE static void run(Packet1cd& /*first*/, const Packet1cd& /*second*/) + static EIGEN_STRONG_INLINE void run(Packet1cd& /*first*/, const Packet1cd& /*second*/) { // FIXME is it sure we never have to align a Packet1cd? // Even though a std::complex has 16 bytes, it is not necessarily aligned on a 16 bytes boundary... @@ -444,4 +431,6 @@ EIGEN_STRONG_INLINE Packet1cd pcplxflip/**/(const Packet1cd& x) } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_COMPLEX_SSE_H diff --git a/extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h b/extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h index 9d56d82180b..3f41a4e2600 100644 --- a/extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h +++ b/extern/Eigen3/Eigen/src/Core/arch/SSE/MathFunctions.h @@ -4,24 +4,9 @@ // Copyright (C) 2007 Julien Pommier // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. /* The sin, cos, exp, and log functions of this file come from * Julien Pommier's sse math library: http://gruntthepeon.free.fr/ssemath/ @@ -30,6 +15,8 @@ #ifndef EIGEN_MATH_FUNCTIONS_SSE_H #define EIGEN_MATH_FUNCTIONS_SSE_H +namespace Eigen { + namespace internal { template<> EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS EIGEN_UNUSED @@ -121,7 +108,7 @@ Packet4f pexp(const Packet4f& _x) _EIGEN_DECLARE_CONST_Packet4i(0x7f, 0x7f); - _EIGEN_DECLARE_CONST_Packet4f(exp_hi, 88.3762626647949f); + _EIGEN_DECLARE_CONST_Packet4f(exp_hi, 88.3762626647950f); _EIGEN_DECLARE_CONST_Packet4f(exp_lo, -88.3762626647949f); _EIGEN_DECLARE_CONST_Packet4f(cephes_LOG2EF, 1.44269504088896341f); @@ -168,7 +155,7 @@ Packet4f pexp(const Packet4f& _x) y = pmadd(y, z, x); y = padd(y, p4f_1); - /* build 2^n */ + // build 2^n emm0 = _mm_cvttps_epi32(fx); emm0 = _mm_add_epi32(emm0, p4i_0x7f); emm0 = _mm_slli_epi32(emm0, 23); @@ -392,4 +379,6 @@ Packet4f psqrt(const Packet4f& _x) } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_MATH_FUNCTIONS_SSE_H diff --git a/extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h b/extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h index 908e27368e8..10d9182190f 100644 --- a/extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h +++ b/extern/Eigen3/Eigen/src/Core/arch/SSE/PacketMath.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008-2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_PACKET_MATH_SSE_H #define EIGEN_PACKET_MATH_SSE_H +namespace Eigen { + namespace internal { #ifndef EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD @@ -110,9 +97,18 @@ template<> struct unpacket_traits { typedef float type; enum {size=4} template<> struct unpacket_traits { typedef double type; enum {size=2}; }; template<> struct unpacket_traits { typedef int type; enum {size=4}; }; +#if defined(_MSC_VER) && (_MSC_VER==1500) +// Workaround MSVC 9 internal compiler error. +// TODO: It has been detected with win64 builds (amd64), so let's check whether it also happens in 32bits+SSE mode +// TODO: let's check whether there does not exist a better fix, like adding a pset0() function. (it crashed on pset1(0)). +template<> EIGEN_STRONG_INLINE Packet4f pset1(const float& from) { return _mm_set_ps(from,from,from,from); } +template<> EIGEN_STRONG_INLINE Packet2d pset1(const double& from) { return _mm_set_pd(from,from); } +template<> EIGEN_STRONG_INLINE Packet4i pset1(const int& from) { return _mm_set_epi32(from,from,from,from); } +#else template<> EIGEN_STRONG_INLINE Packet4f pset1(const float& from) { return _mm_set1_ps(from); } template<> EIGEN_STRONG_INLINE Packet2d pset1(const double& from) { return _mm_set1_pd(from); } template<> EIGEN_STRONG_INLINE Packet4i pset1(const int& from) { return _mm_set1_epi32(from); } +#endif template<> EIGEN_STRONG_INLINE Packet4f plset(const float& a) { return _mm_add_ps(pset1(a), _mm_set_ps(3,2,1,0)); } template<> EIGEN_STRONG_INLINE Packet2d plset(const double& a) { return _mm_add_pd(pset1(a),_mm_set_pd(1,0)); } @@ -282,7 +278,7 @@ template<> EIGEN_STRONG_INLINE Packet4i ploadu(const int* from) template<> EIGEN_STRONG_INLINE Packet4f ploaddup(const float* from) { - return vec4f_swizzle1(_mm_castpd_ps(_mm_load_sd((const double*)from)), 0, 0, 1, 1); + return vec4f_swizzle1(_mm_castpd_ps(_mm_load_sd(reinterpret_cast(from))), 0, 0, 1, 1); } template<> EIGEN_STRONG_INLINE Packet2d ploaddup(const double* from) { return pset1(from[0]); } @@ -302,8 +298,8 @@ template<> EIGEN_STRONG_INLINE void pstoreu(double* to, const Packet2d& _mm_storel_pd((to), from); _mm_storeh_pd((to+1), from); } -template<> EIGEN_STRONG_INLINE void pstoreu(float* to, const Packet4f& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu((double*)to, _mm_castps_pd(from)); } -template<> EIGEN_STRONG_INLINE void pstoreu(int* to, const Packet4i& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu((double*)to, _mm_castsi128_pd(from)); } +template<> EIGEN_STRONG_INLINE void pstoreu(float* to, const Packet4f& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu(reinterpret_cast(to), _mm_castps_pd(from)); } +template<> EIGEN_STRONG_INLINE void pstoreu(int* to, const Packet4i& from) { EIGEN_DEBUG_UNALIGNED_STORE pstoreu(reinterpret_cast(to), _mm_castsi128_pd(from)); } // some compilers might be tempted to perform multiple moves instead of using a vector path. template<> EIGEN_STRONG_INLINE void pstore1(float* to, const float& a) @@ -541,7 +537,7 @@ template<> EIGEN_STRONG_INLINE int predux_max(const Packet4i& a) template struct palign_impl { - EIGEN_STRONG_INLINE static void run(Packet4f& first, const Packet4f& second) + static EIGEN_STRONG_INLINE void run(Packet4f& first, const Packet4f& second) { if (Offset!=0) first = _mm_castsi128_ps(_mm_alignr_epi8(_mm_castps_si128(second), _mm_castps_si128(first), Offset*4)); @@ -551,7 +547,7 @@ struct palign_impl template struct palign_impl { - EIGEN_STRONG_INLINE static void run(Packet4i& first, const Packet4i& second) + static EIGEN_STRONG_INLINE void run(Packet4i& first, const Packet4i& second) { if (Offset!=0) first = _mm_alignr_epi8(second,first, Offset*4); @@ -561,7 +557,7 @@ struct palign_impl template struct palign_impl { - EIGEN_STRONG_INLINE static void run(Packet2d& first, const Packet2d& second) + static EIGEN_STRONG_INLINE void run(Packet2d& first, const Packet2d& second) { if (Offset==1) first = _mm_castsi128_pd(_mm_alignr_epi8(_mm_castpd_si128(second), _mm_castpd_si128(first), 8)); @@ -572,7 +568,7 @@ struct palign_impl template struct palign_impl { - EIGEN_STRONG_INLINE static void run(Packet4f& first, const Packet4f& second) + static EIGEN_STRONG_INLINE void run(Packet4f& first, const Packet4f& second) { if (Offset==1) { @@ -595,7 +591,7 @@ struct palign_impl template struct palign_impl { - EIGEN_STRONG_INLINE static void run(Packet4i& first, const Packet4i& second) + static EIGEN_STRONG_INLINE void run(Packet4i& first, const Packet4i& second) { if (Offset==1) { @@ -618,7 +614,7 @@ struct palign_impl template struct palign_impl { - EIGEN_STRONG_INLINE static void run(Packet2d& first, const Packet2d& second) + static EIGEN_STRONG_INLINE void run(Packet2d& first, const Packet2d& second) { if (Offset==1) { @@ -631,4 +627,6 @@ struct palign_impl } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_PACKET_MATH_SSE_H diff --git a/extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h b/extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h index dc20f7e1e29..403d25fa9eb 100644 --- a/extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h +++ b/extern/Eigen3/Eigen/src/Core/products/CoeffBasedProduct.h @@ -4,28 +4,15 @@ // Copyright (C) 2006-2008 Benoit Jacob // Copyright (C) 2008-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_COEFFBASED_PRODUCT_H #define EIGEN_COEFFBASED_PRODUCT_H +namespace Eigen { + namespace internal { /********************************************************************************* @@ -224,8 +211,8 @@ class CoeffBasedProduct { return reinterpret_cast(*this).diagonal(index); } protected: - const LhsNested m_lhs; - const RhsNested m_rhs; + typename internal::add_const_on_value_type::type m_lhs; + typename internal::add_const_on_value_type::type m_rhs; mutable PlainObject m_result; }; @@ -252,7 +239,7 @@ template struct product_coeff_impl { typedef typename Lhs::Index Index; - EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res) + static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res) { product_coeff_impl::run(row, col, lhs, rhs, res); res += lhs.coeff(row, UnrollingIndex) * rhs.coeff(UnrollingIndex, col); @@ -263,7 +250,7 @@ template struct product_coeff_impl { typedef typename Lhs::Index Index; - EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res) + static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res) { res = lhs.coeff(row, 0) * rhs.coeff(0, col); } @@ -273,7 +260,7 @@ template struct product_coeff_impl { typedef typename Lhs::Index Index; - EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar& res) + static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar& res) { eigen_assert(lhs.cols()>0 && "you are using a non initialized matrix"); res = lhs.coeff(row, 0) * rhs.coeff(0, col); @@ -291,7 +278,7 @@ struct product_coeff_vectorized_unroller { typedef typename Lhs::Index Index; enum { PacketSize = packet_traits::size }; - EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::PacketScalar &pres) + static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::PacketScalar &pres) { product_coeff_vectorized_unroller::run(row, col, lhs, rhs, pres); pres = padd(pres, pmul( lhs.template packet(row, UnrollingIndex) , rhs.template packet(UnrollingIndex, col) )); @@ -302,7 +289,7 @@ template struct product_coeff_vectorized_unroller<0, Lhs, Rhs, Packet> { typedef typename Lhs::Index Index; - EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::PacketScalar &pres) + static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::PacketScalar &pres) { pres = pmul(lhs.template packet(row, 0) , rhs.template packet(0, col)); } @@ -314,7 +301,7 @@ struct product_coeff_impl::size }; - EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res) + static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, RetScalar &res) { Packet pres; product_coeff_vectorized_unroller::run(row, col, lhs, rhs, pres); @@ -327,7 +314,7 @@ template struct product_coeff_vectorized_dyn_selector { typedef typename Lhs::Index Index; - EIGEN_STRONG_INLINE static void run(Index /*row*/, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res) + static EIGEN_STRONG_INLINE void run(Index /*row*/, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res) { res = lhs.transpose().cwiseProduct(rhs.col(col)).sum(); } @@ -349,7 +336,7 @@ template struct product_coeff_vectorized_dyn_selector { typedef typename Lhs::Index Index; - EIGEN_STRONG_INLINE static void run(Index row, Index /*col*/, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res) + static EIGEN_STRONG_INLINE void run(Index row, Index /*col*/, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res) { res = lhs.row(row).transpose().cwiseProduct(rhs).sum(); } @@ -359,7 +346,7 @@ template struct product_coeff_vectorized_dyn_selector { typedef typename Lhs::Index Index; - EIGEN_STRONG_INLINE static void run(Index /*row*/, Index /*col*/, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res) + static EIGEN_STRONG_INLINE void run(Index /*row*/, Index /*col*/, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res) { res = lhs.transpose().cwiseProduct(rhs).sum(); } @@ -369,7 +356,7 @@ template struct product_coeff_impl { typedef typename Lhs::Index Index; - EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res) + static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, typename Lhs::Scalar &res) { product_coeff_vectorized_dyn_selector::run(row, col, lhs, rhs, res); } @@ -383,7 +370,7 @@ template { typedef typename Lhs::Index Index; - EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res) + static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res) { product_packet_impl::run(row, col, lhs, rhs, res); res = pmadd(pset1(lhs.coeff(row, UnrollingIndex)), rhs.template packet(UnrollingIndex, col), res); @@ -394,7 +381,7 @@ template { typedef typename Lhs::Index Index; - EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res) + static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res) { product_packet_impl::run(row, col, lhs, rhs, res); res = pmadd(lhs.template packet(row, UnrollingIndex), pset1(rhs.coeff(UnrollingIndex, col)), res); @@ -405,7 +392,7 @@ template struct product_packet_impl { typedef typename Lhs::Index Index; - EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res) + static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res) { res = pmul(pset1(lhs.coeff(row, 0)),rhs.template packet(0, col)); } @@ -415,7 +402,7 @@ template struct product_packet_impl { typedef typename Lhs::Index Index; - EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res) + static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet &res) { res = pmul(lhs.template packet(row, 0), pset1(rhs.coeff(0, col))); } @@ -425,7 +412,7 @@ template struct product_packet_impl { typedef typename Lhs::Index Index; - EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet& res) + static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet& res) { eigen_assert(lhs.cols()>0 && "you are using a non initialized matrix"); res = pmul(pset1(lhs.coeff(row, 0)),rhs.template packet(0, col)); @@ -438,7 +425,7 @@ template struct product_packet_impl { typedef typename Lhs::Index Index; - EIGEN_STRONG_INLINE static void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet& res) + static EIGEN_STRONG_INLINE void run(Index row, Index col, const Lhs& lhs, const Rhs& rhs, Packet& res) { eigen_assert(lhs.cols()>0 && "you are using a non initialized matrix"); res = pmul(lhs.template packet(row, 0), pset1(rhs.coeff(0, col))); @@ -449,4 +436,6 @@ struct product_packet_impl } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_COEFFBASED_PRODUCT_H diff --git a/extern/Eigen3/Eigen/src/Core/products/GeneralBlockPanelKernel.h b/extern/Eigen3/Eigen/src/Core/products/GeneralBlockPanelKernel.h index cd1c37c780e..5eb03c98ccf 100644 --- a/extern/Eigen3/Eigen/src/Core/products/GeneralBlockPanelKernel.h +++ b/extern/Eigen3/Eigen/src/Core/products/GeneralBlockPanelKernel.h @@ -3,34 +3,23 @@ // // Copyright (C) 2008-2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_GENERAL_BLOCK_PANEL_H #define EIGEN_GENERAL_BLOCK_PANEL_H +namespace Eigen { + namespace internal { template class gebp_traits; -inline std::ptrdiff_t manage_caching_sizes_second_if_negative(std::ptrdiff_t a, std::ptrdiff_t b) + +/** \internal \returns b if a<=0, and returns a otherwise. */ +inline std::ptrdiff_t manage_caching_sizes_helper(std::ptrdiff_t a, std::ptrdiff_t b) { return a<=0 ? b : a; } @@ -38,9 +27,14 @@ inline std::ptrdiff_t manage_caching_sizes_second_if_negative(std::ptrdiff_t a, /** \internal */ inline void manage_caching_sizes(Action action, std::ptrdiff_t* l1=0, std::ptrdiff_t* l2=0) { - static std::ptrdiff_t m_l1CacheSize = manage_caching_sizes_second_if_negative(queryL1CacheSize(),8 * 1024); - static std::ptrdiff_t m_l2CacheSize = manage_caching_sizes_second_if_negative(queryTopLevelCacheSize(),1*1024*1024); - + static std::ptrdiff_t m_l1CacheSize = 0; + static std::ptrdiff_t m_l2CacheSize = 0; + if(m_l2CacheSize==0) + { + m_l1CacheSize = manage_caching_sizes_helper(queryL1CacheSize(),8 * 1024); + m_l2CacheSize = manage_caching_sizes_helper(queryTopLevelCacheSize(),1*1024*1024); + } + if(action==SetAction) { // set the cpu cache size and cache all block sizes from a global cache size in byte @@ -533,7 +527,7 @@ struct gebp_kernel ResPacketSize = Traits::ResPacketSize }; - EIGEN_FLATTEN_ATTRIB + EIGEN_DONT_INLINE EIGEN_FLATTEN_ATTRIB void operator()(ResScalar* res, Index resStride, const LhsScalar* blockA, const RhsScalar* blockB, Index rows, Index depth, Index cols, ResScalar alpha, Index strideA=-1, Index strideB=-1, Index offsetA=0, Index offsetB=0, RhsScalar* unpackedB = 0) { @@ -595,64 +589,64 @@ struct gebp_kernel if(nr==2) { LhsPacket A0, A1; - RhsPacket B0; + RhsPacket B_0; RhsPacket T0; EIGEN_ASM_COMMENT("mybegin2"); traits.loadLhs(&blA[0*LhsProgress], A0); traits.loadLhs(&blA[1*LhsProgress], A1); - traits.loadRhs(&blB[0*RhsProgress], B0); - traits.madd(A0,B0,C0,T0); - traits.madd(A1,B0,C4,B0); - traits.loadRhs(&blB[1*RhsProgress], B0); - traits.madd(A0,B0,C1,T0); - traits.madd(A1,B0,C5,B0); + traits.loadRhs(&blB[0*RhsProgress], B_0); + traits.madd(A0,B_0,C0,T0); + traits.madd(A1,B_0,C4,B_0); + traits.loadRhs(&blB[1*RhsProgress], B_0); + traits.madd(A0,B_0,C1,T0); + traits.madd(A1,B_0,C5,B_0); traits.loadLhs(&blA[2*LhsProgress], A0); traits.loadLhs(&blA[3*LhsProgress], A1); - traits.loadRhs(&blB[2*RhsProgress], B0); - traits.madd(A0,B0,C0,T0); - traits.madd(A1,B0,C4,B0); - traits.loadRhs(&blB[3*RhsProgress], B0); - traits.madd(A0,B0,C1,T0); - traits.madd(A1,B0,C5,B0); + traits.loadRhs(&blB[2*RhsProgress], B_0); + traits.madd(A0,B_0,C0,T0); + traits.madd(A1,B_0,C4,B_0); + traits.loadRhs(&blB[3*RhsProgress], B_0); + traits.madd(A0,B_0,C1,T0); + traits.madd(A1,B_0,C5,B_0); traits.loadLhs(&blA[4*LhsProgress], A0); traits.loadLhs(&blA[5*LhsProgress], A1); - traits.loadRhs(&blB[4*RhsProgress], B0); - traits.madd(A0,B0,C0,T0); - traits.madd(A1,B0,C4,B0); - traits.loadRhs(&blB[5*RhsProgress], B0); - traits.madd(A0,B0,C1,T0); - traits.madd(A1,B0,C5,B0); + traits.loadRhs(&blB[4*RhsProgress], B_0); + traits.madd(A0,B_0,C0,T0); + traits.madd(A1,B_0,C4,B_0); + traits.loadRhs(&blB[5*RhsProgress], B_0); + traits.madd(A0,B_0,C1,T0); + traits.madd(A1,B_0,C5,B_0); traits.loadLhs(&blA[6*LhsProgress], A0); traits.loadLhs(&blA[7*LhsProgress], A1); - traits.loadRhs(&blB[6*RhsProgress], B0); - traits.madd(A0,B0,C0,T0); - traits.madd(A1,B0,C4,B0); - traits.loadRhs(&blB[7*RhsProgress], B0); - traits.madd(A0,B0,C1,T0); - traits.madd(A1,B0,C5,B0); + traits.loadRhs(&blB[6*RhsProgress], B_0); + traits.madd(A0,B_0,C0,T0); + traits.madd(A1,B_0,C4,B_0); + traits.loadRhs(&blB[7*RhsProgress], B_0); + traits.madd(A0,B_0,C1,T0); + traits.madd(A1,B_0,C5,B_0); EIGEN_ASM_COMMENT("myend"); } else { EIGEN_ASM_COMMENT("mybegin4"); LhsPacket A0, A1; - RhsPacket B0, B1, B2, B3; + RhsPacket B_0, B1, B2, B3; RhsPacket T0; traits.loadLhs(&blA[0*LhsProgress], A0); traits.loadLhs(&blA[1*LhsProgress], A1); - traits.loadRhs(&blB[0*RhsProgress], B0); + traits.loadRhs(&blB[0*RhsProgress], B_0); traits.loadRhs(&blB[1*RhsProgress], B1); - traits.madd(A0,B0,C0,T0); + traits.madd(A0,B_0,C0,T0); traits.loadRhs(&blB[2*RhsProgress], B2); - traits.madd(A1,B0,C4,B0); + traits.madd(A1,B_0,C4,B_0); traits.loadRhs(&blB[3*RhsProgress], B3); - traits.loadRhs(&blB[4*RhsProgress], B0); + traits.loadRhs(&blB[4*RhsProgress], B_0); traits.madd(A0,B1,C1,T0); traits.madd(A1,B1,C5,B1); traits.loadRhs(&blB[5*RhsProgress], B1); @@ -664,9 +658,9 @@ EIGEN_ASM_COMMENT("mybegin4"); traits.madd(A1,B3,C7,B3); traits.loadLhs(&blA[3*LhsProgress], A1); traits.loadRhs(&blB[7*RhsProgress], B3); - traits.madd(A0,B0,C0,T0); - traits.madd(A1,B0,C4,B0); - traits.loadRhs(&blB[8*RhsProgress], B0); + traits.madd(A0,B_0,C0,T0); + traits.madd(A1,B_0,C4,B_0); + traits.loadRhs(&blB[8*RhsProgress], B_0); traits.madd(A0,B1,C1,T0); traits.madd(A1,B1,C5,B1); traits.loadRhs(&blB[9*RhsProgress], B1); @@ -679,9 +673,9 @@ EIGEN_ASM_COMMENT("mybegin4"); traits.loadLhs(&blA[5*LhsProgress], A1); traits.loadRhs(&blB[11*RhsProgress], B3); - traits.madd(A0,B0,C0,T0); - traits.madd(A1,B0,C4,B0); - traits.loadRhs(&blB[12*RhsProgress], B0); + traits.madd(A0,B_0,C0,T0); + traits.madd(A1,B_0,C4,B_0); + traits.loadRhs(&blB[12*RhsProgress], B_0); traits.madd(A0,B1,C1,T0); traits.madd(A1,B1,C5,B1); traits.loadRhs(&blB[13*RhsProgress], B1); @@ -693,8 +687,8 @@ EIGEN_ASM_COMMENT("mybegin4"); traits.madd(A1,B3,C7,B3); traits.loadLhs(&blA[7*LhsProgress], A1); traits.loadRhs(&blB[15*RhsProgress], B3); - traits.madd(A0,B0,C0,T0); - traits.madd(A1,B0,C4,B0); + traits.madd(A0,B_0,C0,T0); + traits.madd(A1,B_0,C4,B_0); traits.madd(A0,B1,C1,T0); traits.madd(A1,B1,C5,B1); traits.madd(A0,B2,C2,T0); @@ -712,32 +706,32 @@ EIGEN_ASM_COMMENT("mybegin4"); if(nr==2) { LhsPacket A0, A1; - RhsPacket B0; + RhsPacket B_0; RhsPacket T0; traits.loadLhs(&blA[0*LhsProgress], A0); traits.loadLhs(&blA[1*LhsProgress], A1); - traits.loadRhs(&blB[0*RhsProgress], B0); - traits.madd(A0,B0,C0,T0); - traits.madd(A1,B0,C4,B0); - traits.loadRhs(&blB[1*RhsProgress], B0); - traits.madd(A0,B0,C1,T0); - traits.madd(A1,B0,C5,B0); + traits.loadRhs(&blB[0*RhsProgress], B_0); + traits.madd(A0,B_0,C0,T0); + traits.madd(A1,B_0,C4,B_0); + traits.loadRhs(&blB[1*RhsProgress], B_0); + traits.madd(A0,B_0,C1,T0); + traits.madd(A1,B_0,C5,B_0); } else { LhsPacket A0, A1; - RhsPacket B0, B1, B2, B3; + RhsPacket B_0, B1, B2, B3; RhsPacket T0; traits.loadLhs(&blA[0*LhsProgress], A0); traits.loadLhs(&blA[1*LhsProgress], A1); - traits.loadRhs(&blB[0*RhsProgress], B0); + traits.loadRhs(&blB[0*RhsProgress], B_0); traits.loadRhs(&blB[1*RhsProgress], B1); - traits.madd(A0,B0,C0,T0); + traits.madd(A0,B_0,C0,T0); traits.loadRhs(&blB[2*RhsProgress], B2); - traits.madd(A1,B0,C4,B0); + traits.madd(A1,B_0,C4,B_0); traits.loadRhs(&blB[3*RhsProgress], B3); traits.madd(A0,B1,C1,T0); traits.madd(A1,B1,C5,B1); @@ -824,42 +818,42 @@ EIGEN_ASM_COMMENT("mybegin4"); if(nr==2) { LhsPacket A0; - RhsPacket B0, B1; + RhsPacket B_0, B1; traits.loadLhs(&blA[0*LhsProgress], A0); - traits.loadRhs(&blB[0*RhsProgress], B0); + traits.loadRhs(&blB[0*RhsProgress], B_0); traits.loadRhs(&blB[1*RhsProgress], B1); - traits.madd(A0,B0,C0,B0); - traits.loadRhs(&blB[2*RhsProgress], B0); + traits.madd(A0,B_0,C0,B_0); + traits.loadRhs(&blB[2*RhsProgress], B_0); traits.madd(A0,B1,C1,B1); traits.loadLhs(&blA[1*LhsProgress], A0); traits.loadRhs(&blB[3*RhsProgress], B1); - traits.madd(A0,B0,C0,B0); - traits.loadRhs(&blB[4*RhsProgress], B0); + traits.madd(A0,B_0,C0,B_0); + traits.loadRhs(&blB[4*RhsProgress], B_0); traits.madd(A0,B1,C1,B1); traits.loadLhs(&blA[2*LhsProgress], A0); traits.loadRhs(&blB[5*RhsProgress], B1); - traits.madd(A0,B0,C0,B0); - traits.loadRhs(&blB[6*RhsProgress], B0); + traits.madd(A0,B_0,C0,B_0); + traits.loadRhs(&blB[6*RhsProgress], B_0); traits.madd(A0,B1,C1,B1); traits.loadLhs(&blA[3*LhsProgress], A0); traits.loadRhs(&blB[7*RhsProgress], B1); - traits.madd(A0,B0,C0,B0); + traits.madd(A0,B_0,C0,B_0); traits.madd(A0,B1,C1,B1); } else { LhsPacket A0; - RhsPacket B0, B1, B2, B3; + RhsPacket B_0, B1, B2, B3; traits.loadLhs(&blA[0*LhsProgress], A0); - traits.loadRhs(&blB[0*RhsProgress], B0); + traits.loadRhs(&blB[0*RhsProgress], B_0); traits.loadRhs(&blB[1*RhsProgress], B1); - traits.madd(A0,B0,C0,B0); + traits.madd(A0,B_0,C0,B_0); traits.loadRhs(&blB[2*RhsProgress], B2); traits.loadRhs(&blB[3*RhsProgress], B3); - traits.loadRhs(&blB[4*RhsProgress], B0); + traits.loadRhs(&blB[4*RhsProgress], B_0); traits.madd(A0,B1,C1,B1); traits.loadRhs(&blB[5*RhsProgress], B1); traits.madd(A0,B2,C2,B2); @@ -867,8 +861,8 @@ EIGEN_ASM_COMMENT("mybegin4"); traits.madd(A0,B3,C3,B3); traits.loadLhs(&blA[1*LhsProgress], A0); traits.loadRhs(&blB[7*RhsProgress], B3); - traits.madd(A0,B0,C0,B0); - traits.loadRhs(&blB[8*RhsProgress], B0); + traits.madd(A0,B_0,C0,B_0); + traits.loadRhs(&blB[8*RhsProgress], B_0); traits.madd(A0,B1,C1,B1); traits.loadRhs(&blB[9*RhsProgress], B1); traits.madd(A0,B2,C2,B2); @@ -877,8 +871,8 @@ EIGEN_ASM_COMMENT("mybegin4"); traits.loadLhs(&blA[2*LhsProgress], A0); traits.loadRhs(&blB[11*RhsProgress], B3); - traits.madd(A0,B0,C0,B0); - traits.loadRhs(&blB[12*RhsProgress], B0); + traits.madd(A0,B_0,C0,B_0); + traits.loadRhs(&blB[12*RhsProgress], B_0); traits.madd(A0,B1,C1,B1); traits.loadRhs(&blB[13*RhsProgress], B1); traits.madd(A0,B2,C2,B2); @@ -887,7 +881,7 @@ EIGEN_ASM_COMMENT("mybegin4"); traits.loadLhs(&blA[3*LhsProgress], A0); traits.loadRhs(&blB[15*RhsProgress], B3); - traits.madd(A0,B0,C0,B0); + traits.madd(A0,B_0,C0,B_0); traits.madd(A0,B1,C1,B1); traits.madd(A0,B2,C2,B2); traits.madd(A0,B3,C3,B3); @@ -902,26 +896,26 @@ EIGEN_ASM_COMMENT("mybegin4"); if(nr==2) { LhsPacket A0; - RhsPacket B0, B1; + RhsPacket B_0, B1; traits.loadLhs(&blA[0*LhsProgress], A0); - traits.loadRhs(&blB[0*RhsProgress], B0); + traits.loadRhs(&blB[0*RhsProgress], B_0); traits.loadRhs(&blB[1*RhsProgress], B1); - traits.madd(A0,B0,C0,B0); + traits.madd(A0,B_0,C0,B_0); traits.madd(A0,B1,C1,B1); } else { LhsPacket A0; - RhsPacket B0, B1, B2, B3; + RhsPacket B_0, B1, B2, B3; traits.loadLhs(&blA[0*LhsProgress], A0); - traits.loadRhs(&blB[0*RhsProgress], B0); + traits.loadRhs(&blB[0*RhsProgress], B_0); traits.loadRhs(&blB[1*RhsProgress], B1); traits.loadRhs(&blB[2*RhsProgress], B2); traits.loadRhs(&blB[3*RhsProgress], B3); - traits.madd(A0,B0,C0,B0); + traits.madd(A0,B_0,C0,B_0); traits.madd(A0,B1,C1,B1); traits.madd(A0,B2,C2,B2); traits.madd(A0,B3,C3,B3); @@ -968,26 +962,26 @@ EIGEN_ASM_COMMENT("mybegin4"); if(nr==2) { LhsScalar A0; - RhsScalar B0, B1; + RhsScalar B_0, B1; A0 = blA[k]; - B0 = blB[0]; + B_0 = blB[0]; B1 = blB[1]; - MADD(cj,A0,B0,C0,B0); + MADD(cj,A0,B_0,C0,B_0); MADD(cj,A0,B1,C1,B1); } else { LhsScalar A0; - RhsScalar B0, B1, B2, B3; + RhsScalar B_0, B1, B2, B3; A0 = blA[k]; - B0 = blB[0]; + B_0 = blB[0]; B1 = blB[1]; B2 = blB[2]; B3 = blB[3]; - MADD(cj,A0,B0,C0,B0); + MADD(cj,A0,B_0,C0,B_0); MADD(cj,A0,B1,C1,B1); MADD(cj,A0,B2,C2,B2); MADD(cj,A0,B3,C3,B3); @@ -1024,14 +1018,14 @@ EIGEN_ASM_COMMENT("mybegin4"); for(Index k=0; k struct gemm_pack_lhs { - void operator()(Scalar* blockA, const Scalar* EIGEN_RESTRICT _lhs, Index lhsStride, Index depth, Index rows, + EIGEN_DONT_INLINE void operator()(Scalar* blockA, const Scalar* EIGEN_RESTRICT _lhs, Index lhsStride, Index depth, Index rows, Index stride=0, Index offset=0) { -// enum { PacketSize = packet_traits::size }; + typedef typename packet_traits::type Packet; + enum { PacketSize = packet_traits::size }; + + EIGEN_ASM_COMMENT("EIGEN PRODUCT PACK LHS"); eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride)); + eigen_assert( (StorageOrder==RowMajor) || ((Pack1%PacketSize)==0 && Pack1<=4*PacketSize) ); conj_if::IsComplex && Conjugate> cj; const_blas_data_mapper lhs(_lhs,lhsStride); Index count = 0; @@ -1128,9 +1126,44 @@ struct gemm_pack_lhs for(Index i=0; i=1*PacketSize) A = ploadu(&lhs(i+0*PacketSize, k)); + if(Pack1>=2*PacketSize) B = ploadu(&lhs(i+1*PacketSize, k)); + if(Pack1>=3*PacketSize) C = ploadu(&lhs(i+2*PacketSize, k)); + if(Pack1>=4*PacketSize) D = ploadu(&lhs(i+3*PacketSize, k)); + if(Pack1>=1*PacketSize) { pstore(blockA+count, cj.pconj(A)); count+=PacketSize; } + if(Pack1>=2*PacketSize) { pstore(blockA+count, cj.pconj(B)); count+=PacketSize; } + if(Pack1>=3*PacketSize) { pstore(blockA+count, cj.pconj(C)); count+=PacketSize; } + if(Pack1>=4*PacketSize) { pstore(blockA+count, cj.pconj(D)); count+=PacketSize; } + } + } + else + { + for(Index k=0; k=Pack2) @@ -1164,9 +1197,10 @@ struct gemm_pack_rhs { typedef typename packet_traits::type Packet; enum { PacketSize = packet_traits::size }; - void operator()(Scalar* blockB, const Scalar* rhs, Index rhsStride, Index depth, Index cols, + EIGEN_DONT_INLINE void operator()(Scalar* blockB, const Scalar* rhs, Index rhsStride, Index depth, Index cols, Index stride=0, Index offset=0) { + EIGEN_ASM_COMMENT("EIGEN PRODUCT PACK RHS COLMAJOR"); eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride)); conj_if::IsComplex && Conjugate> cj; Index packet_cols = (cols/nr) * nr; @@ -1211,9 +1245,10 @@ template { enum { PacketSize = packet_traits::size }; - void operator()(Scalar* blockB, const Scalar* rhs, Index rhsStride, Index depth, Index cols, + EIGEN_DONT_INLINE void operator()(Scalar* blockB, const Scalar* rhs, Index rhsStride, Index depth, Index cols, Index stride=0, Index offset=0) { + EIGEN_ASM_COMMENT("EIGEN PRODUCT PACK RHS ROWMAJOR"); eigen_assert(((!PanelMode) && stride==0 && offset==0) || (PanelMode && stride>=depth && offset<=stride)); conj_if::IsComplex && Conjugate> cj; Index packet_cols = (cols/nr) * nr; @@ -1279,4 +1314,6 @@ inline void setCpuCacheSizes(std::ptrdiff_t l1, std::ptrdiff_t l2) internal::manage_caching_sizes(SetAction, &l1, &l2); } +} // end namespace Eigen + #endif // EIGEN_GENERAL_BLOCK_PANEL_H diff --git a/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h b/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h index ae94a27953b..73a465ec5ee 100644 --- a/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h +++ b/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008-2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_GENERAL_MATRIX_MATRIX_H #define EIGEN_GENERAL_MATRIX_MATRIX_H +namespace Eigen { + namespace internal { template class level3_blocking; @@ -77,7 +64,7 @@ static void run(Index rows, Index cols, Index depth, typedef gebp_traits Traits; - Index kc = blocking.kc(); // cache block size along the K direction + Index kc = blocking.kc(); // cache block size along the K direction Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction //Index nc = blocking.nc(); // cache block size along the N direction @@ -247,7 +234,7 @@ struct gemm_functor BlockingType& m_blocking; }; -template class gemm_blocking_space; template @@ -280,8 +267,8 @@ class level3_blocking inline RhsScalar* blockW() { return m_blockW; } }; -template -class gemm_blocking_space +template +class gemm_blocking_space : public level3_blocking< typename conditional::type, typename conditional::type> @@ -322,8 +309,8 @@ class gemm_blocking_space -class gemm_blocking_space +template +class gemm_blocking_space : public level3_blocking< typename conditional::type, typename conditional::type> @@ -347,7 +334,7 @@ class gemm_blocking_spacem_nc = Transpose ? rows : cols; this->m_kc = depth; - computeProductBlockingSizes(this->m_kc, this->m_mc, this->m_nc); + computeProductBlockingSizes(this->m_kc, this->m_mc, this->m_nc); m_sizeA = this->m_mc * this->m_kc; m_sizeB = this->m_kc * this->m_nc; m_sizeW = this->m_kc*Traits::WorkSpaceFactor; @@ -412,8 +399,8 @@ class GeneralProduct { eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols()); - const ActualLhsType lhs = LhsBlasTraits::extract(m_lhs); - const ActualRhsType rhs = RhsBlasTraits::extract(m_rhs); + typename internal::add_const_on_value_type::type lhs = LhsBlasTraits::extract(m_lhs); + typename internal::add_const_on_value_type::type rhs = RhsBlasTraits::extract(m_rhs); Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(m_lhs) * RhsBlasTraits::extractScalarFactor(m_rhs); @@ -436,4 +423,6 @@ class GeneralProduct } }; +} // end namespace Eigen + #endif // EIGEN_GENERAL_MATRIX_MATRIX_H diff --git a/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h b/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h index 5043b64fe2e..432d3a9dc84 100644 --- a/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h +++ b/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_GENERAL_MATRIX_MATRIX_TRIANGULAR_H #define EIGEN_GENERAL_MATRIX_MATRIX_TRIANGULAR_H +namespace Eigen { + namespace internal { /********************************************************************** @@ -42,14 +29,14 @@ struct tribb_kernel; template + int ResStorageOrder, int UpLo, int Version = Specialized> struct general_matrix_matrix_triangular_product; // as usual if the result is row major => we transpose the product template -struct general_matrix_matrix_triangular_product -{ + typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs, int UpLo, int Version> +struct general_matrix_matrix_triangular_product +{ typedef typename scalar_product_traits::ReturnType ResScalar; static EIGEN_STRONG_INLINE void run(Index size, Index depth,const LhsScalar* lhs, Index lhsStride, const RhsScalar* rhs, Index rhsStride, ResScalar* res, Index resStride, ResScalar alpha) @@ -63,8 +50,8 @@ struct general_matrix_matrix_triangular_product -struct general_matrix_matrix_triangular_product + typename RhsScalar, int RhsStorageOrder, bool ConjugateRhs, int UpLo, int Version> +struct general_matrix_matrix_triangular_product { typedef typename scalar_product_traits::ReturnType ResScalar; static EIGEN_STRONG_INLINE void run(Index size, Index depth,const LhsScalar* _lhs, Index lhsStride, @@ -201,13 +188,13 @@ TriangularView& TriangularView::assignProduct( typedef internal::blas_traits LhsBlasTraits; typedef typename LhsBlasTraits::DirectLinearAccessType ActualLhs; typedef typename internal::remove_all::type _ActualLhs; - const ActualLhs actualLhs = LhsBlasTraits::extract(prod.lhs()); + typename internal::add_const_on_value_type::type actualLhs = LhsBlasTraits::extract(prod.lhs()); typedef typename internal::remove_all::type Rhs; typedef internal::blas_traits RhsBlasTraits; typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhs; typedef typename internal::remove_all::type _ActualRhs; - const ActualRhs actualRhs = RhsBlasTraits::extract(prod.rhs()); + typename internal::add_const_on_value_type::type actualRhs = RhsBlasTraits::extract(prod.rhs()); typename ProductDerived::Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs().derived()) * RhsBlasTraits::extractScalarFactor(prod.rhs().derived()); @@ -222,4 +209,6 @@ TriangularView& TriangularView::assignProduct( return *this; } +} // end namespace Eigen + #endif // EIGEN_GENERAL_MATRIX_MATRIX_TRIANGULAR_H diff --git a/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_MKL.h b/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_MKL.h new file mode 100644 index 00000000000..3deed068e39 --- /dev/null +++ b/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_MKL.h @@ -0,0 +1,146 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + 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 Intel Corporation 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. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL + * Level 3 BLAS SYRK/HERK implementation. + ******************************************************************************** +*/ + +#ifndef EIGEN_GENERAL_MATRIX_MATRIX_TRIANGULAR_MKL_H +#define EIGEN_GENERAL_MATRIX_MATRIX_TRIANGULAR_MKL_H + +namespace Eigen { + +namespace internal { + +template +struct general_matrix_matrix_rankupdate : + general_matrix_matrix_triangular_product< + Index,Scalar,AStorageOrder,ConjugateA,Scalar,AStorageOrder,ConjugateA,ResStorageOrder,UpLo,BuiltIn> {}; + + +// try to go to BLAS specialization +#define EIGEN_MKL_RANKUPDATE_SPECIALIZE(Scalar) \ +template \ +struct general_matrix_matrix_triangular_product { \ + static EIGEN_STRONG_INLINE void run(Index size, Index depth,const Scalar* lhs, Index lhsStride, \ + const Scalar* rhs, Index rhsStride, Scalar* res, Index resStride, Scalar alpha) \ + { \ + if (lhs==rhs) { \ + general_matrix_matrix_rankupdate \ + ::run(size,depth,lhs,lhsStride,rhs,rhsStride,res,resStride,alpha); \ + } else { \ + general_matrix_matrix_triangular_product \ + ::run(size,depth,lhs,lhsStride,rhs,rhsStride,res,resStride,alpha); \ + } \ + } \ +}; + +EIGEN_MKL_RANKUPDATE_SPECIALIZE(double) +//EIGEN_MKL_RANKUPDATE_SPECIALIZE(dcomplex) +EIGEN_MKL_RANKUPDATE_SPECIALIZE(float) +//EIGEN_MKL_RANKUPDATE_SPECIALIZE(scomplex) + +// SYRK for float/double +#define EIGEN_MKL_RANKUPDATE_R(EIGTYPE, MKLTYPE, MKLFUNC) \ +template \ +struct general_matrix_matrix_rankupdate { \ + enum { \ + IsLower = (UpLo&Lower) == Lower, \ + LowUp = IsLower ? Lower : Upper, \ + conjA = ((AStorageOrder==ColMajor) && ConjugateA) ? 1 : 0 \ + }; \ + static EIGEN_STRONG_INLINE void run(Index size, Index depth,const EIGTYPE* lhs, Index lhsStride, \ + const EIGTYPE* rhs, Index rhsStride, EIGTYPE* res, Index resStride, EIGTYPE alpha) \ + { \ + /* typedef Matrix MatrixRhs;*/ \ +\ + MKL_INT lda=lhsStride, ldc=resStride, n=size, k=depth; \ + char uplo=(IsLower) ? 'L' : 'U', trans=(AStorageOrder==RowMajor) ? 'T':'N'; \ + MKLTYPE alpha_, beta_; \ +\ +/* Set alpha_ & beta_ */ \ + assign_scalar_eig2mkl(alpha_, alpha); \ + assign_scalar_eig2mkl(beta_, EIGTYPE(1)); \ + MKLFUNC(&uplo, &trans, &n, &k, &alpha_, lhs, &lda, &beta_, res, &ldc); \ + } \ +}; + +// HERK for complex data +#define EIGEN_MKL_RANKUPDATE_C(EIGTYPE, MKLTYPE, RTYPE, MKLFUNC) \ +template \ +struct general_matrix_matrix_rankupdate { \ + enum { \ + IsLower = (UpLo&Lower) == Lower, \ + LowUp = IsLower ? Lower : Upper, \ + conjA = (((AStorageOrder==ColMajor) && ConjugateA) || ((AStorageOrder==RowMajor) && !ConjugateA)) ? 1 : 0 \ + }; \ + static EIGEN_STRONG_INLINE void run(Index size, Index depth,const EIGTYPE* lhs, Index lhsStride, \ + const EIGTYPE* rhs, Index rhsStride, EIGTYPE* res, Index resStride, EIGTYPE alpha) \ + { \ + typedef Matrix MatrixType; \ +\ + MKL_INT lda=lhsStride, ldc=resStride, n=size, k=depth; \ + char uplo=(IsLower) ? 'L' : 'U', trans=(AStorageOrder==RowMajor) ? 'C':'N'; \ + RTYPE alpha_, beta_; \ + const EIGTYPE* a_ptr; \ +\ +/* Set alpha_ & beta_ */ \ +/* assign_scalar_eig2mkl(alpha_, alpha); */\ +/* assign_scalar_eig2mkl(beta_, EIGTYPE(1));*/ \ + alpha_ = alpha.real(); \ + beta_ = 1.0; \ +/* Copy with conjugation in some cases*/ \ + MatrixType a; \ + if (conjA) { \ + Map > mapA(lhs,n,k,OuterStride<>(lhsStride)); \ + a = mapA.conjugate(); \ + lda = a.outerStride(); \ + a_ptr = a.data(); \ + } else a_ptr=lhs; \ + MKLFUNC(&uplo, &trans, &n, &k, &alpha_, (MKLTYPE*)a_ptr, &lda, &beta_, (MKLTYPE*)res, &ldc); \ + } \ +}; + + +EIGEN_MKL_RANKUPDATE_R(double, double, dsyrk) +EIGEN_MKL_RANKUPDATE_R(float, float, ssyrk) + +//EIGEN_MKL_RANKUPDATE_C(dcomplex, MKL_Complex16, double, zherk) +//EIGEN_MKL_RANKUPDATE_C(scomplex, MKL_Complex8, double, cherk) + + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_GENERAL_MATRIX_MATRIX_TRIANGULAR_MKL_H diff --git a/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix_MKL.h b/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix_MKL.h new file mode 100644 index 00000000000..060af328ebe --- /dev/null +++ b/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixMatrix_MKL.h @@ -0,0 +1,118 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + 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 Intel Corporation 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. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL + * General matrix-matrix product functionality based on ?GEMM. + ******************************************************************************** +*/ + +#ifndef EIGEN_GENERAL_MATRIX_MATRIX_MKL_H +#define EIGEN_GENERAL_MATRIX_MATRIX_MKL_H + +namespace Eigen { + +namespace internal { + +/********************************************************************** +* This file implements general matrix-matrix multiplication using BLAS +* gemm function via partial specialization of +* general_matrix_matrix_product::run(..) method for float, double, +* std::complex and std::complex types +**********************************************************************/ + +// gemm specialization + +#define GEMM_SPECIALIZATION(EIGTYPE, EIGPREFIX, MKLTYPE, MKLPREFIX) \ +template< \ + typename Index, \ + int LhsStorageOrder, bool ConjugateLhs, \ + int RhsStorageOrder, bool ConjugateRhs> \ +struct general_matrix_matrix_product \ +{ \ +static void run(Index rows, Index cols, Index depth, \ + const EIGTYPE* _lhs, Index lhsStride, \ + const EIGTYPE* _rhs, Index rhsStride, \ + EIGTYPE* res, Index resStride, \ + EIGTYPE alpha, \ + level3_blocking& /*blocking*/, \ + GemmParallelInfo* /*info = 0*/) \ +{ \ + using std::conj; \ +\ + char transa, transb; \ + MKL_INT m, n, k, lda, ldb, ldc; \ + const EIGTYPE *a, *b; \ + MKLTYPE alpha_, beta_; \ + MatrixX##EIGPREFIX a_tmp, b_tmp; \ + EIGTYPE myone(1);\ +\ +/* Set transpose options */ \ + transa = (LhsStorageOrder==RowMajor) ? ((ConjugateLhs) ? 'C' : 'T') : 'N'; \ + transb = (RhsStorageOrder==RowMajor) ? ((ConjugateRhs) ? 'C' : 'T') : 'N'; \ +\ +/* Set m, n, k */ \ + m = (MKL_INT)rows; \ + n = (MKL_INT)cols; \ + k = (MKL_INT)depth; \ +\ +/* Set alpha_ & beta_ */ \ + assign_scalar_eig2mkl(alpha_, alpha); \ + assign_scalar_eig2mkl(beta_, myone); \ +\ +/* Set lda, ldb, ldc */ \ + lda = (MKL_INT)lhsStride; \ + ldb = (MKL_INT)rhsStride; \ + ldc = (MKL_INT)resStride; \ +\ +/* Set a, b, c */ \ + if ((LhsStorageOrder==ColMajor) && (ConjugateLhs)) { \ + Map > lhs(_lhs,m,k,OuterStride<>(lhsStride)); \ + a_tmp = lhs.conjugate(); \ + a = a_tmp.data(); \ + lda = a_tmp.outerStride(); \ + } else a = _lhs; \ +\ + if ((RhsStorageOrder==ColMajor) && (ConjugateRhs)) { \ + Map > rhs(_rhs,k,n,OuterStride<>(rhsStride)); \ + b_tmp = rhs.conjugate(); \ + b = b_tmp.data(); \ + ldb = b_tmp.outerStride(); \ + } else b = _rhs; \ +\ + MKLPREFIX##gemm(&transa, &transb, &m, &n, &k, &alpha_, (const MKLTYPE*)a, &lda, (const MKLTYPE*)b, &ldb, &beta_, (MKLTYPE*)res, &ldc); \ +}}; + +GEMM_SPECIALIZATION(double, d, double, d) +GEMM_SPECIALIZATION(float, f, float, s) +GEMM_SPECIALIZATION(dcomplex, cd, MKL_Complex16, z) +GEMM_SPECIALIZATION(scomplex, cf, MKL_Complex8, c) + +} // end namespase internal + +} // end namespace Eigen + +#endif // EIGEN_GENERAL_MATRIX_MATRIX_MKL_H diff --git a/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector.h b/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector.h index e0e2cbf8f62..ba1f73957db 100644 --- a/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector.h +++ b/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008-2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_GENERAL_MATRIX_VECTOR_H #define EIGEN_GENERAL_MATRIX_VECTOR_H +namespace Eigen { + namespace internal { /* Optimized col-major matrix * vector product: @@ -40,8 +27,8 @@ namespace internal { * |cplx |real |cplx | invalid, the caller has to do tmp: = A * B; C += alpha*tmp * |cplx |real |real | optimal case, vectorization possible via real-cplx mul */ -template -struct general_matrix_vector_product +template +struct general_matrix_vector_product { typedef typename scalar_product_traits::ReturnType ResScalar; @@ -99,7 +86,7 @@ EIGEN_DONT_INLINE static void run( // How many coeffs of the result do we have to skip to be aligned. // Here we assume data are at least aligned on the base scalar type. - Index alignedStart = first_aligned(res,size); + Index alignedStart = internal::first_aligned(res,size); Index alignedSize = ResPacketSize>1 ? alignedStart + ((size-alignedStart) & ~ResPacketAlignedMask) : 0; const Index peeledSize = peels>1 ? alignedStart + ((alignedSize-alignedStart) & ~PeelAlignedMask) : alignedStart; @@ -109,7 +96,7 @@ EIGEN_DONT_INLINE static void run( : FirstAligned; // we cannot assume the first element is aligned because of sub-matrices - const Index lhsAlignmentOffset = first_aligned(lhs,size); + const Index lhsAlignmentOffset = internal::first_aligned(lhs,size); // find how many columns do we have to skip to be aligned with the result (if possible) Index skipColumns = 0; @@ -296,8 +283,8 @@ EIGEN_DONT_INLINE static void run( * - alpha is always a complex (or converted to a complex) * - no vectorization */ -template -struct general_matrix_vector_product +template +struct general_matrix_vector_product { typedef typename scalar_product_traits::ReturnType ResScalar; @@ -351,7 +338,7 @@ EIGEN_DONT_INLINE static void run( // How many coeffs of the result do we have to skip to be aligned. // Here we assume data are at least aligned on the base scalar type // if that's not the case then vectorization is discarded, see below. - Index alignedStart = first_aligned(rhs, depth); + Index alignedStart = internal::first_aligned(rhs, depth); Index alignedSize = RhsPacketSize>1 ? alignedStart + ((depth-alignedStart) & ~RhsPacketAlignedMask) : 0; const Index peeledSize = peels>1 ? alignedStart + ((alignedSize-alignedStart) & ~PeelAlignedMask) : alignedStart; @@ -361,7 +348,7 @@ EIGEN_DONT_INLINE static void run( : FirstAligned; // we cannot assume the first element is aligned because of sub-matrices - const Index lhsAlignmentOffset = first_aligned(lhs,depth); + const Index lhsAlignmentOffset = internal::first_aligned(lhs,depth); // find how many rows do we have to skip to be aligned with rhs (if possible) Index skipRows = 0; @@ -556,4 +543,6 @@ EIGEN_DONT_INLINE static void run( } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_GENERAL_MATRIX_VECTOR_H diff --git a/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector_MKL.h b/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector_MKL.h new file mode 100644 index 00000000000..e9de6af3ed1 --- /dev/null +++ b/extern/Eigen3/Eigen/src/Core/products/GeneralMatrixVector_MKL.h @@ -0,0 +1,131 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + 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 Intel Corporation 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. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL + * General matrix-vector product functionality based on ?GEMV. + ******************************************************************************** +*/ + +#ifndef EIGEN_GENERAL_MATRIX_VECTOR_MKL_H +#define EIGEN_GENERAL_MATRIX_VECTOR_MKL_H + +namespace Eigen { + +namespace internal { + +/********************************************************************** +* This file implements general matrix-vector multiplication using BLAS +* gemv function via partial specialization of +* general_matrix_vector_product::run(..) method for float, double, +* std::complex and std::complex types +**********************************************************************/ + +// gemv specialization + +template +struct general_matrix_vector_product_gemv : + general_matrix_vector_product {}; + +#define EIGEN_MKL_GEMV_SPECIALIZE(Scalar) \ +template \ +struct general_matrix_vector_product { \ +static EIGEN_DONT_INLINE void run( \ + Index rows, Index cols, \ + const Scalar* lhs, Index lhsStride, \ + const Scalar* rhs, Index rhsIncr, \ + Scalar* res, Index resIncr, Scalar alpha) \ +{ \ + if (ConjugateLhs) { \ + general_matrix_vector_product::run( \ + rows, cols, lhs, lhsStride, rhs, rhsIncr, res, resIncr, alpha); \ + } else { \ + general_matrix_vector_product_gemv::run( \ + rows, cols, lhs, lhsStride, rhs, rhsIncr, res, resIncr, alpha); \ + } \ +} \ +}; \ +template \ +struct general_matrix_vector_product { \ +static EIGEN_DONT_INLINE void run( \ + Index rows, Index cols, \ + const Scalar* lhs, Index lhsStride, \ + const Scalar* rhs, Index rhsIncr, \ + Scalar* res, Index resIncr, Scalar alpha) \ +{ \ + general_matrix_vector_product_gemv::run( \ + rows, cols, lhs, lhsStride, rhs, rhsIncr, res, resIncr, alpha); \ +} \ +}; \ + +EIGEN_MKL_GEMV_SPECIALIZE(double) +EIGEN_MKL_GEMV_SPECIALIZE(float) +EIGEN_MKL_GEMV_SPECIALIZE(dcomplex) +EIGEN_MKL_GEMV_SPECIALIZE(scomplex) + +#define EIGEN_MKL_GEMV_SPECIALIZATION(EIGTYPE,MKLTYPE,MKLPREFIX) \ +template \ +struct general_matrix_vector_product_gemv \ +{ \ +typedef Matrix GEMVVector;\ +\ +static EIGEN_DONT_INLINE void run( \ + Index rows, Index cols, \ + const EIGTYPE* lhs, Index lhsStride, \ + const EIGTYPE* rhs, Index rhsIncr, \ + EIGTYPE* res, Index resIncr, EIGTYPE alpha) \ +{ \ + MKL_INT m=rows, n=cols, lda=lhsStride, incx=rhsIncr, incy=resIncr; \ + MKLTYPE alpha_, beta_; \ + const EIGTYPE *x_ptr, myone(1); \ + char trans=(LhsStorageOrder==ColMajor) ? 'N' : (ConjugateLhs) ? 'C' : 'T'; \ + if (LhsStorageOrder==RowMajor) { \ + m=cols; \ + n=rows; \ + }\ + assign_scalar_eig2mkl(alpha_, alpha); \ + assign_scalar_eig2mkl(beta_, myone); \ + GEMVVector x_tmp; \ + if (ConjugateRhs) { \ + Map > map_x(rhs,cols,1,InnerStride<>(incx)); \ + x_tmp=map_x.conjugate(); \ + x_ptr=x_tmp.data(); \ + incx=1; \ + } else x_ptr=rhs; \ + MKLPREFIX##gemv(&trans, &m, &n, &alpha_, (const MKLTYPE*)lhs, &lda, (const MKLTYPE*)x_ptr, &incx, &beta_, (MKLTYPE*)res, &incy); \ +}\ +}; + +EIGEN_MKL_GEMV_SPECIALIZATION(double, double, d) +EIGEN_MKL_GEMV_SPECIALIZATION(float, float, s) +EIGEN_MKL_GEMV_SPECIALIZATION(dcomplex, MKL_Complex16, z) +EIGEN_MKL_GEMV_SPECIALIZATION(scomplex, MKL_Complex8, c) + +} // end namespase internal + +} // end namespace Eigen + +#endif // EIGEN_GENERAL_MATRIX_VECTOR_MKL_H diff --git a/extern/Eigen3/Eigen/src/Core/products/Parallelizer.h b/extern/Eigen3/Eigen/src/Core/products/Parallelizer.h index ecdedc363ce..5c3e9b7ac15 100644 --- a/extern/Eigen3/Eigen/src/Core/products/Parallelizer.h +++ b/extern/Eigen3/Eigen/src/Core/products/Parallelizer.h @@ -3,28 +3,15 @@ // // Copyright (C) 2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_PARALLELIZER_H #define EIGEN_PARALLELIZER_H +namespace Eigen { + namespace internal { /** \internal */ @@ -55,12 +42,23 @@ inline void manage_multi_threading(Action action, int* v) } } +} + +/** Must be call first when calling Eigen from multiple threads */ +inline void initParallel() +{ + int nbt; + internal::manage_multi_threading(GetAction, &nbt); + std::ptrdiff_t l1, l2; + internal::manage_caching_sizes(GetAction, &l1, &l2); +} + /** \returns the max number of threads reserved for Eigen * \sa setNbThreads */ inline int nbThreads() { int ret; - manage_multi_threading(GetAction, &ret); + internal::manage_multi_threading(GetAction, &ret); return ret; } @@ -68,9 +66,11 @@ inline int nbThreads() * \sa nbThreads */ inline void setNbThreads(int v) { - manage_multi_threading(SetAction, &v); + internal::manage_multi_threading(SetAction, &v); } +namespace internal { + template struct GemmParallelInfo { GemmParallelInfo() : sync(-1), users(0), rhs_start(0), rhs_length(0) {} @@ -85,7 +85,9 @@ template struct GemmParallelInfo template void parallelize_gemm(const Functor& func, Index rows, Index cols, bool transpose) { -#ifndef EIGEN_HAS_OPENMP + // TODO when EIGEN_USE_BLAS is defined, + // we should still enable OMP for other scalar types +#if !(defined (EIGEN_HAS_OPENMP)) || defined (EIGEN_USE_BLAS) // FIXME the transpose variable is only needed to properly split // the matrix product when multithreading is enabled. This is a temporary // fix to support row-major destination matrices. This whole @@ -117,6 +119,7 @@ void parallelize_gemm(const Functor& func, Index rows, Index cols, bool transpos if(threads==1) return func(0,rows, 0,cols); + Eigen::initParallel(); func.initParallelSession(); if(transpose) @@ -151,4 +154,6 @@ void parallelize_gemm(const Functor& func, Index rows, Index cols, bool transpos } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_PARALLELIZER_H diff --git a/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix.h b/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix.h index ccd757cfaf8..48209636eed 100644 --- a/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix.h +++ b/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SELFADJOINT_MATRIX_MATRIX_H #define EIGEN_SELFADJOINT_MATRIX_MATRIX_H +namespace Eigen { + namespace internal { // pack a selfadjoint block diagonal for use with the gebp_kernel @@ -400,8 +387,8 @@ struct SelfadjointProductMatrix { eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols()); - const ActualLhsType lhs = LhsBlasTraits::extract(m_lhs); - const ActualRhsType rhs = RhsBlasTraits::extract(m_rhs); + typename internal::add_const_on_value_type::type lhs = LhsBlasTraits::extract(m_lhs); + typename internal::add_const_on_value_type::type rhs = RhsBlasTraits::extract(m_rhs); Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(m_lhs) * RhsBlasTraits::extractScalarFactor(m_rhs); @@ -424,4 +411,6 @@ struct SelfadjointProductMatrix } }; +} // end namespace Eigen + #endif // EIGEN_SELFADJOINT_MATRIX_MATRIX_H diff --git a/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h b/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h new file mode 100644 index 00000000000..4e5c4125c01 --- /dev/null +++ b/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixMatrix_MKL.h @@ -0,0 +1,295 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + 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 Intel Corporation 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. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL + * Self adjoint matrix * matrix product functionality based on ?SYMM/?HEMM. + ******************************************************************************** +*/ + +#ifndef EIGEN_SELFADJOINT_MATRIX_MATRIX_MKL_H +#define EIGEN_SELFADJOINT_MATRIX_MATRIX_MKL_H + +namespace Eigen { + +namespace internal { + + +/* Optimized selfadjoint matrix * matrix (?SYMM/?HEMM) product */ + +#define EIGEN_MKL_SYMM_L(EIGTYPE, MKLTYPE, EIGPREFIX, MKLPREFIX) \ +template \ +struct product_selfadjoint_matrix \ +{\ +\ + static EIGEN_DONT_INLINE void run( \ + Index rows, Index cols, \ + const EIGTYPE* _lhs, Index lhsStride, \ + const EIGTYPE* _rhs, Index rhsStride, \ + EIGTYPE* res, Index resStride, \ + EIGTYPE alpha) \ + { \ + char side='L', uplo='L'; \ + MKL_INT m, n, lda, ldb, ldc; \ + const EIGTYPE *a, *b; \ + MKLTYPE alpha_, beta_; \ + MatrixX##EIGPREFIX b_tmp; \ + EIGTYPE myone(1);\ +\ +/* Set transpose options */ \ +/* Set m, n, k */ \ + m = (MKL_INT)rows; \ + n = (MKL_INT)cols; \ +\ +/* Set alpha_ & beta_ */ \ + assign_scalar_eig2mkl(alpha_, alpha); \ + assign_scalar_eig2mkl(beta_, myone); \ +\ +/* Set lda, ldb, ldc */ \ + lda = (MKL_INT)lhsStride; \ + ldb = (MKL_INT)rhsStride; \ + ldc = (MKL_INT)resStride; \ +\ +/* Set a, b, c */ \ + if (LhsStorageOrder==RowMajor) uplo='U'; \ + a = _lhs; \ +\ + if (RhsStorageOrder==RowMajor) { \ + Map > rhs(_rhs,n,m,OuterStride<>(rhsStride)); \ + b_tmp = rhs.adjoint(); \ + b = b_tmp.data(); \ + ldb = b_tmp.outerStride(); \ + } else b = _rhs; \ +\ + MKLPREFIX##symm(&side, &uplo, &m, &n, &alpha_, (const MKLTYPE*)a, &lda, (const MKLTYPE*)b, &ldb, &beta_, (MKLTYPE*)res, &ldc); \ +\ + } \ +}; + + +#define EIGEN_MKL_HEMM_L(EIGTYPE, MKLTYPE, EIGPREFIX, MKLPREFIX) \ +template \ +struct product_selfadjoint_matrix \ +{\ + static EIGEN_DONT_INLINE void run( \ + Index rows, Index cols, \ + const EIGTYPE* _lhs, Index lhsStride, \ + const EIGTYPE* _rhs, Index rhsStride, \ + EIGTYPE* res, Index resStride, \ + EIGTYPE alpha) \ + { \ + char side='L', uplo='L'; \ + MKL_INT m, n, lda, ldb, ldc; \ + const EIGTYPE *a, *b; \ + MKLTYPE alpha_, beta_; \ + MatrixX##EIGPREFIX b_tmp; \ + Matrix a_tmp; \ + EIGTYPE myone(1); \ +\ +/* Set transpose options */ \ +/* Set m, n, k */ \ + m = (MKL_INT)rows; \ + n = (MKL_INT)cols; \ +\ +/* Set alpha_ & beta_ */ \ + assign_scalar_eig2mkl(alpha_, alpha); \ + assign_scalar_eig2mkl(beta_, myone); \ +\ +/* Set lda, ldb, ldc */ \ + lda = (MKL_INT)lhsStride; \ + ldb = (MKL_INT)rhsStride; \ + ldc = (MKL_INT)resStride; \ +\ +/* Set a, b, c */ \ + if (((LhsStorageOrder==ColMajor) && ConjugateLhs) || ((LhsStorageOrder==RowMajor) && (!ConjugateLhs))) { \ + Map, 0, OuterStride<> > lhs(_lhs,m,m,OuterStride<>(lhsStride)); \ + a_tmp = lhs.conjugate(); \ + a = a_tmp.data(); \ + lda = a_tmp.outerStride(); \ + } else a = _lhs; \ + if (LhsStorageOrder==RowMajor) uplo='U'; \ +\ + if (RhsStorageOrder==ColMajor && (!ConjugateRhs)) { \ + b = _rhs; } \ + else { \ + if (RhsStorageOrder==ColMajor && ConjugateRhs) { \ + Map > rhs(_rhs,m,n,OuterStride<>(rhsStride)); \ + b_tmp = rhs.conjugate(); \ + } else \ + if (ConjugateRhs) { \ + Map > rhs(_rhs,n,m,OuterStride<>(rhsStride)); \ + b_tmp = rhs.adjoint(); \ + } else { \ + Map > rhs(_rhs,n,m,OuterStride<>(rhsStride)); \ + b_tmp = rhs.transpose(); \ + } \ + b = b_tmp.data(); \ + ldb = b_tmp.outerStride(); \ + } \ +\ + MKLPREFIX##hemm(&side, &uplo, &m, &n, &alpha_, (const MKLTYPE*)a, &lda, (const MKLTYPE*)b, &ldb, &beta_, (MKLTYPE*)res, &ldc); \ +\ + } \ +}; + +EIGEN_MKL_SYMM_L(double, double, d, d) +EIGEN_MKL_SYMM_L(float, float, f, s) +EIGEN_MKL_HEMM_L(dcomplex, MKL_Complex16, cd, z) +EIGEN_MKL_HEMM_L(scomplex, MKL_Complex8, cf, c) + + +/* Optimized matrix * selfadjoint matrix (?SYMM/?HEMM) product */ + +#define EIGEN_MKL_SYMM_R(EIGTYPE, MKLTYPE, EIGPREFIX, MKLPREFIX) \ +template \ +struct product_selfadjoint_matrix \ +{\ +\ + static EIGEN_DONT_INLINE void run( \ + Index rows, Index cols, \ + const EIGTYPE* _lhs, Index lhsStride, \ + const EIGTYPE* _rhs, Index rhsStride, \ + EIGTYPE* res, Index resStride, \ + EIGTYPE alpha) \ + { \ + char side='R', uplo='L'; \ + MKL_INT m, n, lda, ldb, ldc; \ + const EIGTYPE *a, *b; \ + MKLTYPE alpha_, beta_; \ + MatrixX##EIGPREFIX b_tmp; \ + EIGTYPE myone(1);\ +\ +/* Set m, n, k */ \ + m = (MKL_INT)rows; \ + n = (MKL_INT)cols; \ +\ +/* Set alpha_ & beta_ */ \ + assign_scalar_eig2mkl(alpha_, alpha); \ + assign_scalar_eig2mkl(beta_, myone); \ +\ +/* Set lda, ldb, ldc */ \ + lda = (MKL_INT)rhsStride; \ + ldb = (MKL_INT)lhsStride; \ + ldc = (MKL_INT)resStride; \ +\ +/* Set a, b, c */ \ + if (RhsStorageOrder==RowMajor) uplo='U'; \ + a = _rhs; \ +\ + if (LhsStorageOrder==RowMajor) { \ + Map > lhs(_lhs,n,m,OuterStride<>(rhsStride)); \ + b_tmp = lhs.adjoint(); \ + b = b_tmp.data(); \ + ldb = b_tmp.outerStride(); \ + } else b = _lhs; \ +\ + MKLPREFIX##symm(&side, &uplo, &m, &n, &alpha_, (const MKLTYPE*)a, &lda, (const MKLTYPE*)b, &ldb, &beta_, (MKLTYPE*)res, &ldc); \ +\ + } \ +}; + + +#define EIGEN_MKL_HEMM_R(EIGTYPE, MKLTYPE, EIGPREFIX, MKLPREFIX) \ +template \ +struct product_selfadjoint_matrix \ +{\ + static EIGEN_DONT_INLINE void run( \ + Index rows, Index cols, \ + const EIGTYPE* _lhs, Index lhsStride, \ + const EIGTYPE* _rhs, Index rhsStride, \ + EIGTYPE* res, Index resStride, \ + EIGTYPE alpha) \ + { \ + char side='R', uplo='L'; \ + MKL_INT m, n, lda, ldb, ldc; \ + const EIGTYPE *a, *b; \ + MKLTYPE alpha_, beta_; \ + MatrixX##EIGPREFIX b_tmp; \ + Matrix a_tmp; \ + EIGTYPE myone(1); \ +\ +/* Set m, n, k */ \ + m = (MKL_INT)rows; \ + n = (MKL_INT)cols; \ +\ +/* Set alpha_ & beta_ */ \ + assign_scalar_eig2mkl(alpha_, alpha); \ + assign_scalar_eig2mkl(beta_, myone); \ +\ +/* Set lda, ldb, ldc */ \ + lda = (MKL_INT)rhsStride; \ + ldb = (MKL_INT)lhsStride; \ + ldc = (MKL_INT)resStride; \ +\ +/* Set a, b, c */ \ + if (((RhsStorageOrder==ColMajor) && ConjugateRhs) || ((RhsStorageOrder==RowMajor) && (!ConjugateRhs))) { \ + Map, 0, OuterStride<> > rhs(_rhs,n,n,OuterStride<>(rhsStride)); \ + a_tmp = rhs.conjugate(); \ + a = a_tmp.data(); \ + lda = a_tmp.outerStride(); \ + } else a = _rhs; \ + if (RhsStorageOrder==RowMajor) uplo='U'; \ +\ + if (LhsStorageOrder==ColMajor && (!ConjugateLhs)) { \ + b = _lhs; } \ + else { \ + if (LhsStorageOrder==ColMajor && ConjugateLhs) { \ + Map > lhs(_lhs,m,n,OuterStride<>(lhsStride)); \ + b_tmp = lhs.conjugate(); \ + } else \ + if (ConjugateLhs) { \ + Map > lhs(_lhs,n,m,OuterStride<>(lhsStride)); \ + b_tmp = lhs.adjoint(); \ + } else { \ + Map > lhs(_lhs,n,m,OuterStride<>(lhsStride)); \ + b_tmp = lhs.transpose(); \ + } \ + b = b_tmp.data(); \ + ldb = b_tmp.outerStride(); \ + } \ +\ + MKLPREFIX##hemm(&side, &uplo, &m, &n, &alpha_, (const MKLTYPE*)a, &lda, (const MKLTYPE*)b, &ldb, &beta_, (MKLTYPE*)res, &ldc); \ + } \ +}; + +EIGEN_MKL_SYMM_R(double, double, d, d) +EIGEN_MKL_SYMM_R(float, float, f, s) +EIGEN_MKL_HEMM_R(dcomplex, MKL_Complex16, cd, z) +EIGEN_MKL_HEMM_R(scomplex, MKL_Complex8, cf, c) + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_SELFADJOINT_MATRIX_MATRIX_MKL_H diff --git a/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector.h b/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector.h index d6121fc07bd..c3145c69a5f 100644 --- a/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector.h +++ b/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008-2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SELFADJOINT_MATRIX_VECTOR_H #define EIGEN_SELFADJOINT_MATRIX_VECTOR_H +namespace Eigen { + namespace internal { /* Optimized selfadjoint matrix * vector product: @@ -32,8 +19,15 @@ namespace internal { * the number of load/stores of the result by a factor 2 and to reduce * the instruction dependency. */ -template -static EIGEN_DONT_INLINE void product_selfadjoint_vector( + +template +struct selfadjoint_matrix_vector_product; + +template +struct selfadjoint_matrix_vector_product + +{ +static EIGEN_DONT_INLINE void run( Index size, const Scalar* lhs, Index lhsStride, const Scalar* _rhs, Index rhsIncr, @@ -85,14 +79,14 @@ static EIGEN_DONT_INLINE void product_selfadjoint_vector( Scalar t1 = cjAlpha * rhs[j+1]; Packet ptmp1 = pset1(t1); - Scalar t2 = 0; + Scalar t2(0); Packet ptmp2 = pset1(t2); - Scalar t3 = 0; + Scalar t3(0); Packet ptmp3 = pset1(t3); size_t starti = FirstTriangular ? 0 : j+2; size_t endi = FirstTriangular ? j : size; - size_t alignedStart = (starti) + first_aligned(&res[starti], endi-starti); + size_t alignedStart = (starti) + internal::first_aligned(&res[starti], endi-starti); size_t alignedEnd = alignedStart + ((endi-alignedStart)/(PacketSize))*(PacketSize); // TODO make sure this product is a real * complex and that the rhs is properly conjugated if needed @@ -148,7 +142,7 @@ static EIGEN_DONT_INLINE void product_selfadjoint_vector( register const Scalar* EIGEN_RESTRICT A0 = lhs + j*lhsStride; Scalar t1 = cjAlpha * rhs[j]; - Scalar t2 = 0; + Scalar t2(0); // TODO make sure this product is a real * complex and that the rhs is properly conjugated if needed res[j] += cjd.pmul(internal::real(A0[j]), t1); for (Index i=FirstTriangular ? 0 : j+1; i<(FirstTriangular ? j : size); i++) @@ -159,6 +153,7 @@ static EIGEN_DONT_INLINE void product_selfadjoint_vector( res[j] += alpha * t2; } } +}; } // end namespace internal @@ -193,8 +188,8 @@ struct SelfadjointProductMatrix eigen_assert(dest.rows()==m_lhs.rows() && dest.cols()==m_rhs.cols()); - const ActualLhsType lhs = LhsBlasTraits::extract(m_lhs); - const ActualRhsType rhs = RhsBlasTraits::extract(m_rhs); + typename internal::add_const_on_value_type::type lhs = LhsBlasTraits::extract(m_lhs); + typename internal::add_const_on_value_type::type rhs = RhsBlasTraits::extract(m_rhs); Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(m_lhs) * RhsBlasTraits::extractScalarFactor(m_rhs); @@ -232,7 +227,7 @@ struct SelfadjointProductMatrix } - internal::product_selfadjoint_vector::Flags&RowMajorBit) ? RowMajor : ColMajor, int(LhsUpLo), bool(LhsBlasTraits::NeedToConjugate), bool(RhsBlasTraits::NeedToConjugate)> + internal::selfadjoint_matrix_vector_product::Flags&RowMajorBit) ? RowMajor : ColMajor, int(LhsUpLo), bool(LhsBlasTraits::NeedToConjugate), bool(RhsBlasTraits::NeedToConjugate)>::run ( lhs.rows(), // size &lhs.coeffRef(0,0), lhs.outerStride(), // lhs info @@ -274,5 +269,6 @@ struct SelfadjointProductMatrix } }; +} // end namespace Eigen #endif // EIGEN_SELFADJOINT_MATRIX_VECTOR_H diff --git a/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h b/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h new file mode 100644 index 00000000000..f88d483b653 --- /dev/null +++ b/extern/Eigen3/Eigen/src/Core/products/SelfadjointMatrixVector_MKL.h @@ -0,0 +1,114 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + 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 Intel Corporation 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. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL + * Selfadjoint matrix-vector product functionality based on ?SYMV/HEMV. + ******************************************************************************** +*/ + +#ifndef EIGEN_SELFADJOINT_MATRIX_VECTOR_MKL_H +#define EIGEN_SELFADJOINT_MATRIX_VECTOR_MKL_H + +namespace Eigen { + +namespace internal { + +/********************************************************************** +* This file implements selfadjoint matrix-vector multiplication using BLAS +**********************************************************************/ + +// symv/hemv specialization + +template +struct selfadjoint_matrix_vector_product_symv : + selfadjoint_matrix_vector_product {}; + +#define EIGEN_MKL_SYMV_SPECIALIZE(Scalar) \ +template \ +struct selfadjoint_matrix_vector_product { \ +static EIGEN_DONT_INLINE void run( \ + Index size, const Scalar* lhs, Index lhsStride, \ + const Scalar* _rhs, Index rhsIncr, Scalar* res, Scalar alpha) { \ + enum {\ + IsColMajor = StorageOrder==ColMajor \ + }; \ + if (IsColMajor == ConjugateLhs) {\ + selfadjoint_matrix_vector_product::run( \ + size, lhs, lhsStride, _rhs, rhsIncr, res, alpha); \ + } else {\ + selfadjoint_matrix_vector_product_symv::run( \ + size, lhs, lhsStride, _rhs, rhsIncr, res, alpha); \ + }\ + } \ +}; \ + +EIGEN_MKL_SYMV_SPECIALIZE(double) +EIGEN_MKL_SYMV_SPECIALIZE(float) +EIGEN_MKL_SYMV_SPECIALIZE(dcomplex) +EIGEN_MKL_SYMV_SPECIALIZE(scomplex) + +#define EIGEN_MKL_SYMV_SPECIALIZATION(EIGTYPE,MKLTYPE,MKLFUNC) \ +template \ +struct selfadjoint_matrix_vector_product_symv \ +{ \ +typedef Matrix SYMVVector;\ +\ +static EIGEN_DONT_INLINE void run( \ +Index size, const EIGTYPE* lhs, Index lhsStride, \ +const EIGTYPE* _rhs, Index rhsIncr, EIGTYPE* res, EIGTYPE alpha) \ +{ \ + enum {\ + IsRowMajor = StorageOrder==RowMajor ? 1 : 0, \ + IsLower = UpLo == Lower ? 1 : 0 \ + }; \ + MKL_INT n=size, lda=lhsStride, incx=rhsIncr, incy=1; \ + MKLTYPE alpha_, beta_; \ + const EIGTYPE *x_ptr, myone(1); \ + char uplo=(IsRowMajor) ? (IsLower ? 'U' : 'L') : (IsLower ? 'L' : 'U'); \ + assign_scalar_eig2mkl(alpha_, alpha); \ + assign_scalar_eig2mkl(beta_, myone); \ + SYMVVector x_tmp; \ + if (ConjugateRhs) { \ + Map > map_x(_rhs,size,1,InnerStride<>(incx)); \ + x_tmp=map_x.conjugate(); \ + x_ptr=x_tmp.data(); \ + incx=1; \ + } else x_ptr=_rhs; \ + MKLFUNC(&uplo, &n, &alpha_, (const MKLTYPE*)lhs, &lda, (const MKLTYPE*)x_ptr, &incx, &beta_, (MKLTYPE*)res, &incy); \ +}\ +}; + +EIGEN_MKL_SYMV_SPECIALIZATION(double, double, dsymv) +EIGEN_MKL_SYMV_SPECIALIZATION(float, float, ssymv) +EIGEN_MKL_SYMV_SPECIALIZATION(dcomplex, MKL_Complex16, zhemv) +EIGEN_MKL_SYMV_SPECIALIZATION(scomplex, MKL_Complex8, chemv) + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_SELFADJOINT_MATRIX_VECTOR_MKL_H diff --git a/extern/Eigen3/Eigen/src/Core/products/SelfadjointProduct.h b/extern/Eigen3/Eigen/src/Core/products/SelfadjointProduct.h index 3a4523fa4a9..6a55f3d7715 100644 --- a/extern/Eigen3/Eigen/src/Core/products/SelfadjointProduct.h +++ b/extern/Eigen3/Eigen/src/Core/products/SelfadjointProduct.h @@ -3,24 +3,9 @@ // // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SELFADJOINT_PRODUCT_H #define EIGEN_SELFADJOINT_PRODUCT_H @@ -31,6 +16,8 @@ * It corresponds to the level 3 SYRK and level 2 SYR Blas routines. **********************************************************************/ +namespace Eigen { + template struct selfadjoint_rank1_update; @@ -72,7 +59,7 @@ struct selfadjoint_product_selector typedef internal::blas_traits OtherBlasTraits; typedef typename OtherBlasTraits::DirectLinearAccessType ActualOtherType; typedef typename internal::remove_all::type _ActualOtherType; - const ActualOtherType actualOther = OtherBlasTraits::extract(other.derived()); + typename internal::add_const_on_value_type::type actualOther = OtherBlasTraits::extract(other.derived()); Scalar actualAlpha = alpha * OtherBlasTraits::extractScalarFactor(other.derived()); @@ -105,12 +92,12 @@ struct selfadjoint_product_selector typedef internal::blas_traits OtherBlasTraits; typedef typename OtherBlasTraits::DirectLinearAccessType ActualOtherType; typedef typename internal::remove_all::type _ActualOtherType; - const ActualOtherType actualOther = OtherBlasTraits::extract(other.derived()); + typename internal::add_const_on_value_type::type actualOther = OtherBlasTraits::extract(other.derived()); Scalar actualAlpha = alpha * OtherBlasTraits::extractScalarFactor(other.derived()); enum { IsRowMajor = (internal::traits::Flags&RowMajorBit) ? 1 : 0 }; - + internal::general_matrix_matrix_triangular_product::IsComplex, Scalar, _ActualOtherType::Flags&RowMajorBit ? ColMajor : RowMajor, (!OtherBlasTraits::NeedToConjugate) && NumTraits::IsComplex, @@ -133,4 +120,6 @@ SelfAdjointView& SelfAdjointView return *this; } +} // end namespace Eigen + #endif // EIGEN_SELFADJOINT_PRODUCT_H diff --git a/extern/Eigen3/Eigen/src/Core/products/SelfadjointRank2Update.h b/extern/Eigen3/Eigen/src/Core/products/SelfadjointRank2Update.h index 9f8b8438a5d..57a98cc2de9 100644 --- a/extern/Eigen3/Eigen/src/Core/products/SelfadjointRank2Update.h +++ b/extern/Eigen3/Eigen/src/Core/products/SelfadjointRank2Update.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SELFADJOINTRANK2UPTADE_H #define EIGEN_SELFADJOINTRANK2UPTADE_H +namespace Eigen { + namespace internal { /* Optimized selfadjoint matrix += alpha * uv' + conj(alpha)*vu' @@ -76,12 +63,12 @@ SelfAdjointView& SelfAdjointView typedef internal::blas_traits UBlasTraits; typedef typename UBlasTraits::DirectLinearAccessType ActualUType; typedef typename internal::remove_all::type _ActualUType; - const ActualUType actualU = UBlasTraits::extract(u.derived()); + typename internal::add_const_on_value_type::type actualU = UBlasTraits::extract(u.derived()); typedef internal::blas_traits VBlasTraits; typedef typename VBlasTraits::DirectLinearAccessType ActualVType; typedef typename internal::remove_all::type _ActualVType; - const ActualVType actualV = VBlasTraits::extract(v.derived()); + typename internal::add_const_on_value_type::type actualV = VBlasTraits::extract(v.derived()); // If MatrixType is row major, then we use the routine for lower triangular in the upper triangular case and // vice versa, and take the complex conjugate of all coefficients and vector entries. @@ -101,4 +88,6 @@ SelfAdjointView& SelfAdjointView return *this; } +} // end namespace Eigen + #endif // EIGEN_SELFADJOINTRANK2UPTADE_H diff --git a/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix.h b/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix.h index 0c48d2efb75..92cba66f615 100644 --- a/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix.h +++ b/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_TRIANGULAR_MATRIX_MATRIX_H #define EIGEN_TRIANGULAR_MATRIX_MATRIX_H +namespace Eigen { + namespace internal { // template @@ -58,23 +45,23 @@ template + int ResStorageOrder, int Version = Specialized> struct product_triangular_matrix_matrix; template + int RhsStorageOrder, bool ConjugateRhs, int Version> struct product_triangular_matrix_matrix + RhsStorageOrder,ConjugateRhs,RowMajor,Version> { static EIGEN_STRONG_INLINE void run( Index rows, Index cols, Index depth, const Scalar* lhs, Index lhsStride, const Scalar* rhs, Index rhsStride, Scalar* res, Index resStride, - Scalar alpha) + Scalar alpha, level3_blocking& blocking) { product_triangular_matrix_matrix - ::run(cols, rows, depth, rhs, rhsStride, lhs, lhsStride, res, resStride, alpha); + ::run(cols, rows, depth, rhs, rhsStride, lhs, lhsStride, res, resStride, alpha, blocking); } }; // implements col-major += alpha * op(triangular) * op(general) template + int RhsStorageOrder, bool ConjugateRhs, int Version> struct product_triangular_matrix_matrix + RhsStorageOrder,ConjugateRhs,ColMajor,Version> { typedef gebp_traits Traits; enum { - SmallPanelWidth = EIGEN_PLAIN_ENUM_MAX(Traits::mr,Traits::nr), + SmallPanelWidth = 2 * EIGEN_PLAIN_ENUM_MAX(Traits::mr,Traits::nr), IsLower = (Mode&Lower) == Lower, SetDiag = (Mode&(ZeroDiag|UnitDiag)) ? 0 : 1 }; @@ -109,7 +96,7 @@ struct product_triangular_matrix_matrix& blocking) { // strip zeros Index diagSize = (std::min)(_rows,_depth); @@ -120,15 +107,16 @@ struct product_triangular_matrix_matrix lhs(_lhs,lhsStride); const_blas_data_mapper rhs(_rhs,rhsStride); - Index kc = depth; // cache block size along the K direction - Index mc = rows; // cache block size along the M direction - Index nc = cols; // cache block size along the N direction - computeProductBlockingSizes(kc, mc, nc); + Index kc = blocking.kc(); // cache block size along the K direction + Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction + + std::size_t sizeA = kc*mc; + std::size_t sizeB = kc*cols; std::size_t sizeW = kc*Traits::WorkSpaceFactor; - std::size_t sizeB = sizeW + kc*cols; - ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0); - ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0); - Scalar* blockB = allocatedBlockB + sizeW; + + ei_declare_aligned_stack_constructed_variable(Scalar, blockA, sizeA, blocking.blockA()); + ei_declare_aligned_stack_constructed_variable(Scalar, blockB, sizeB, blocking.blockB()); + ei_declare_aligned_stack_constructed_variable(Scalar, blockW, sizeW, blocking.blockW()); Matrix triangularBuffer; triangularBuffer.setZero(); @@ -186,7 +174,7 @@ struct product_triangular_matrix_matrix0) @@ -196,7 +184,7 @@ struct product_triangular_matrix_matrix() (blockA, &lhs(i2, actual_k2), lhsStride, actual_kc, actual_mc); - gebp_kernel(res+i2, resStride, blockA, blockB, actual_mc, actual_kc, cols, alpha); + gebp_kernel(res+i2, resStride, blockA, blockB, actual_mc, actual_kc, cols, alpha, -1, -1, 0, 0, blockW); } } } @@ -220,10 +208,10 @@ struct product_triangular_matrix_matrix + int RhsStorageOrder, bool ConjugateRhs, int Version> struct product_triangular_matrix_matrix + RhsStorageOrder,ConjugateRhs,ColMajor,Version> { typedef gebp_traits Traits; enum { @@ -237,7 +225,7 @@ struct product_triangular_matrix_matrix& blocking) { // strip zeros Index diagSize = (std::min)(_cols,_depth); @@ -248,16 +236,16 @@ struct product_triangular_matrix_matrix lhs(_lhs,lhsStride); const_blas_data_mapper rhs(_rhs,rhsStride); - Index kc = depth; // cache block size along the K direction - Index mc = rows; // cache block size along the M direction - Index nc = cols; // cache block size along the N direction - computeProductBlockingSizes(kc, mc, nc); + Index kc = blocking.kc(); // cache block size along the K direction + Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction + std::size_t sizeA = kc*mc; + std::size_t sizeB = kc*cols; std::size_t sizeW = kc*Traits::WorkSpaceFactor; - std::size_t sizeB = sizeW + kc*cols; - ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0); - ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0); - Scalar* blockB = allocatedBlockB + sizeW; + + ei_declare_aligned_stack_constructed_variable(Scalar, blockA, sizeA, blocking.blockA()); + ei_declare_aligned_stack_constructed_variable(Scalar, blockB, sizeB, blocking.blockB()); + ei_declare_aligned_stack_constructed_variable(Scalar, blockW, sizeW, blocking.blockW()); Matrix triangularBuffer; triangularBuffer.setZero(); @@ -345,13 +333,13 @@ struct product_triangular_matrix_matrix template void scaleAndAddTo(Dest& dst, Scalar alpha) const { - const ActualLhsType lhs = LhsBlasTraits::extract(m_lhs); - const ActualRhsType rhs = RhsBlasTraits::extract(m_rhs); + typename internal::add_const_on_value_type::type lhs = LhsBlasTraits::extract(m_lhs); + typename internal::add_const_on_value_type::type rhs = RhsBlasTraits::extract(m_rhs); Scalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(m_lhs) * RhsBlasTraits::extractScalarFactor(m_rhs); + typedef internal::gemm_blocking_space<(Dest::Flags&RowMajorBit) ? RowMajor : ColMajor,Scalar,Scalar, + Lhs::MaxRowsAtCompileTime, Rhs::MaxColsAtCompileTime, Lhs::MaxColsAtCompileTime,4> BlockingType; + + enum { IsLower = (Mode&Lower) == Lower }; + Index stripedRows = ((!LhsIsTriangular) || (IsLower)) ? lhs.rows() : (std::min)(lhs.rows(),lhs.cols()); + Index stripedCols = ((LhsIsTriangular) || (!IsLower)) ? rhs.cols() : (std::min)(rhs.cols(),rhs.rows()); + Index stripedDepth = LhsIsTriangular ? ((!IsLower) ? lhs.cols() : (std::min)(lhs.cols(),lhs.rows())) + : ((IsLower) ? rhs.rows() : (std::min)(rhs.rows(),rhs.cols())); + + BlockingType blocking(stripedRows, stripedCols, stripedDepth); + internal::product_triangular_matrix_matrix::Flags&RowMajorBit) ? RowMajor : ColMajor, LhsBlasTraits::NeedToConjugate, (internal::traits<_ActualRhsType>::Flags&RowMajorBit) ? RowMajor : ColMajor, RhsBlasTraits::NeedToConjugate, (internal::traits::Flags&RowMajorBit) ? RowMajor : ColMajor> ::run( - lhs.rows(), rhs.cols(), lhs.cols(),// LhsIsTriangular ? rhs.cols() : lhs.rows(), // sizes + stripedRows, stripedCols, stripedDepth, // sizes &lhs.coeffRef(0,0), lhs.outerStride(), // lhs info &rhs.coeffRef(0,0), rhs.outerStride(), // rhs info - &dst.coeffRef(0,0), dst.outerStride(), // result info - actualAlpha // alpha + &dst.coeffRef(0,0), dst.outerStride(), // result info + actualAlpha, blocking ); } }; +} // end namespace Eigen #endif // EIGEN_TRIANGULAR_MATRIX_MATRIX_H diff --git a/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h b/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h new file mode 100644 index 00000000000..8173da5bb6d --- /dev/null +++ b/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixMatrix_MKL.h @@ -0,0 +1,309 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + 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 Intel Corporation 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. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL + * Triangular matrix * matrix product functionality based on ?TRMM. + ******************************************************************************** +*/ + +#ifndef EIGEN_TRIANGULAR_MATRIX_MATRIX_MKL_H +#define EIGEN_TRIANGULAR_MATRIX_MATRIX_MKL_H + +namespace Eigen { + +namespace internal { + + +template +struct product_triangular_matrix_matrix_trmm : + product_triangular_matrix_matrix {}; + + +// try to go to BLAS specialization +#define EIGEN_MKL_TRMM_SPECIALIZE(Scalar, LhsIsTriangular) \ +template \ +struct product_triangular_matrix_matrix { \ + static inline void run(Index _rows, Index _cols, Index _depth, const Scalar* _lhs, Index lhsStride,\ + const Scalar* _rhs, Index rhsStride, Scalar* res, Index resStride, Scalar alpha) { \ + product_triangular_matrix_matrix_trmm::run( \ + _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha); \ + } \ +}; + +EIGEN_MKL_TRMM_SPECIALIZE(double, true) +EIGEN_MKL_TRMM_SPECIALIZE(double, false) +EIGEN_MKL_TRMM_SPECIALIZE(dcomplex, true) +EIGEN_MKL_TRMM_SPECIALIZE(dcomplex, false) +EIGEN_MKL_TRMM_SPECIALIZE(float, true) +EIGEN_MKL_TRMM_SPECIALIZE(float, false) +EIGEN_MKL_TRMM_SPECIALIZE(scomplex, true) +EIGEN_MKL_TRMM_SPECIALIZE(scomplex, false) + +// implements col-major += alpha * op(triangular) * op(general) +#define EIGEN_MKL_TRMM_L(EIGTYPE, MKLTYPE, EIGPREFIX, MKLPREFIX) \ +template \ +struct product_triangular_matrix_matrix_trmm \ +{ \ + enum { \ + IsLower = (Mode&Lower) == Lower, \ + SetDiag = (Mode&(ZeroDiag|UnitDiag)) ? 0 : 1, \ + IsUnitDiag = (Mode&UnitDiag) ? 1 : 0, \ + IsZeroDiag = (Mode&ZeroDiag) ? 1 : 0, \ + LowUp = IsLower ? Lower : Upper, \ + conjA = ((LhsStorageOrder==ColMajor) && ConjugateLhs) ? 1 : 0 \ + }; \ +\ + static EIGEN_DONT_INLINE void run( \ + Index _rows, Index _cols, Index _depth, \ + const EIGTYPE* _lhs, Index lhsStride, \ + const EIGTYPE* _rhs, Index rhsStride, \ + EIGTYPE* res, Index resStride, \ + EIGTYPE alpha) \ + { \ + Index diagSize = (std::min)(_rows,_depth); \ + Index rows = IsLower ? _rows : diagSize; \ + Index depth = IsLower ? diagSize : _depth; \ + Index cols = _cols; \ +\ + typedef Matrix MatrixLhs; \ + typedef Matrix MatrixRhs; \ +\ +/* Non-square case - doesn't fit to MKL ?TRMM. Fall to default triangular product or call MKL ?GEMM*/ \ + if (rows != depth) { \ +\ + int nthr = mkl_domain_get_max_threads(MKL_BLAS); \ +\ + if (((nthr==1) && (((std::max)(rows,depth)-diagSize)/(double)diagSize < 0.5))) { \ + /* Most likely no benefit to call TRMM or GEMM from MKL*/ \ + product_triangular_matrix_matrix::run( \ + _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha); \ + /*std::cout << "TRMM_L: A is not square! Go to Eigen TRMM implementation!\n";*/ \ + } else { \ + /* Make sense to call GEMM */ \ + Map > lhsMap(_lhs,rows,depth,OuterStride<>(lhsStride)); \ + MatrixLhs aa_tmp=lhsMap.template triangularView(); \ + MKL_INT aStride = aa_tmp.outerStride(); \ + gemm_blocking_space blocking(_rows,_cols,_depth); \ + general_matrix_matrix_product::run( \ + rows, cols, depth, aa_tmp.data(), aStride, _rhs, rhsStride, res, resStride, alpha, blocking, 0); \ +\ + /*std::cout << "TRMM_L: A is not square! Go to MKL GEMM implementation! " << nthr<<" \n";*/ \ + } \ + return; \ + } \ + char side = 'L', transa, uplo, diag = 'N'; \ + EIGTYPE *b; \ + const EIGTYPE *a; \ + MKL_INT m, n, lda, ldb; \ + MKLTYPE alpha_; \ +\ +/* Set alpha_*/ \ + assign_scalar_eig2mkl(alpha_, alpha); \ +\ +/* Set m, n */ \ + m = (MKL_INT)diagSize; \ + n = (MKL_INT)cols; \ +\ +/* Set trans */ \ + transa = (LhsStorageOrder==RowMajor) ? ((ConjugateLhs) ? 'C' : 'T') : 'N'; \ +\ +/* Set b, ldb */ \ + Map > rhs(_rhs,depth,cols,OuterStride<>(rhsStride)); \ + MatrixX##EIGPREFIX b_tmp; \ +\ + if (ConjugateRhs) b_tmp = rhs.conjugate(); else b_tmp = rhs; \ + b = b_tmp.data(); \ + ldb = b_tmp.outerStride(); \ +\ +/* Set uplo */ \ + uplo = IsLower ? 'L' : 'U'; \ + if (LhsStorageOrder==RowMajor) uplo = (uplo == 'L') ? 'U' : 'L'; \ +/* Set a, lda */ \ + Map > lhs(_lhs,rows,depth,OuterStride<>(lhsStride)); \ + MatrixLhs a_tmp; \ +\ + if ((conjA!=0) || (SetDiag==0)) { \ + if (conjA) a_tmp = lhs.conjugate(); else a_tmp = lhs; \ + if (IsZeroDiag) \ + a_tmp.diagonal().setZero(); \ + else if (IsUnitDiag) \ + a_tmp.diagonal().setOnes();\ + a = a_tmp.data(); \ + lda = a_tmp.outerStride(); \ + } else { \ + a = _lhs; \ + lda = lhsStride; \ + } \ + /*std::cout << "TRMM_L: A is square! Go to MKL TRMM implementation! \n";*/ \ +/* call ?trmm*/ \ + MKLPREFIX##trmm(&side, &uplo, &transa, &diag, &m, &n, &alpha_, (const MKLTYPE*)a, &lda, (MKLTYPE*)b, &ldb); \ +\ +/* Add op(a_triangular)*b into res*/ \ + Map > res_tmp(res,rows,cols,OuterStride<>(resStride)); \ + res_tmp=res_tmp+b_tmp; \ + } \ +}; + +EIGEN_MKL_TRMM_L(double, double, d, d) +EIGEN_MKL_TRMM_L(dcomplex, MKL_Complex16, cd, z) +EIGEN_MKL_TRMM_L(float, float, f, s) +EIGEN_MKL_TRMM_L(scomplex, MKL_Complex8, cf, c) + +// implements col-major += alpha * op(general) * op(triangular) +#define EIGEN_MKL_TRMM_R(EIGTYPE, MKLTYPE, EIGPREFIX, MKLPREFIX) \ +template \ +struct product_triangular_matrix_matrix_trmm \ +{ \ + enum { \ + IsLower = (Mode&Lower) == Lower, \ + SetDiag = (Mode&(ZeroDiag|UnitDiag)) ? 0 : 1, \ + IsUnitDiag = (Mode&UnitDiag) ? 1 : 0, \ + IsZeroDiag = (Mode&ZeroDiag) ? 1 : 0, \ + LowUp = IsLower ? Lower : Upper, \ + conjA = ((RhsStorageOrder==ColMajor) && ConjugateRhs) ? 1 : 0 \ + }; \ +\ + static EIGEN_DONT_INLINE void run( \ + Index _rows, Index _cols, Index _depth, \ + const EIGTYPE* _lhs, Index lhsStride, \ + const EIGTYPE* _rhs, Index rhsStride, \ + EIGTYPE* res, Index resStride, \ + EIGTYPE alpha) \ + { \ + Index diagSize = (std::min)(_cols,_depth); \ + Index rows = _rows; \ + Index depth = IsLower ? _depth : diagSize; \ + Index cols = IsLower ? diagSize : _cols; \ +\ + typedef Matrix MatrixLhs; \ + typedef Matrix MatrixRhs; \ +\ +/* Non-square case - doesn't fit to MKL ?TRMM. Fall to default triangular product or call MKL ?GEMM*/ \ + if (cols != depth) { \ +\ + int nthr = mkl_domain_get_max_threads(MKL_BLAS); \ +\ + if ((nthr==1) && (((std::max)(cols,depth)-diagSize)/(double)diagSize < 0.5)) { \ + /* Most likely no benefit to call TRMM or GEMM from MKL*/ \ + product_triangular_matrix_matrix::run( \ + _rows, _cols, _depth, _lhs, lhsStride, _rhs, rhsStride, res, resStride, alpha); \ + /*std::cout << "TRMM_R: A is not square! Go to Eigen TRMM implementation!\n";*/ \ + } else { \ + /* Make sense to call GEMM */ \ + Map > rhsMap(_rhs,depth,cols, OuterStride<>(rhsStride)); \ + MatrixRhs aa_tmp=rhsMap.template triangularView(); \ + MKL_INT aStride = aa_tmp.outerStride(); \ + gemm_blocking_space blocking(_rows,_cols,_depth); \ + general_matrix_matrix_product::run( \ + rows, cols, depth, _lhs, lhsStride, aa_tmp.data(), aStride, res, resStride, alpha, blocking, 0); \ +\ + /*std::cout << "TRMM_R: A is not square! Go to MKL GEMM implementation! " << nthr<<" \n";*/ \ + } \ + return; \ + } \ + char side = 'R', transa, uplo, diag = 'N'; \ + EIGTYPE *b; \ + const EIGTYPE *a; \ + MKL_INT m, n, lda, ldb; \ + MKLTYPE alpha_; \ +\ +/* Set alpha_*/ \ + assign_scalar_eig2mkl(alpha_, alpha); \ +\ +/* Set m, n */ \ + m = (MKL_INT)rows; \ + n = (MKL_INT)diagSize; \ +\ +/* Set trans */ \ + transa = (RhsStorageOrder==RowMajor) ? ((ConjugateRhs) ? 'C' : 'T') : 'N'; \ +\ +/* Set b, ldb */ \ + Map > lhs(_lhs,rows,depth,OuterStride<>(lhsStride)); \ + MatrixX##EIGPREFIX b_tmp; \ +\ + if (ConjugateLhs) b_tmp = lhs.conjugate(); else b_tmp = lhs; \ + b = b_tmp.data(); \ + ldb = b_tmp.outerStride(); \ +\ +/* Set uplo */ \ + uplo = IsLower ? 'L' : 'U'; \ + if (RhsStorageOrder==RowMajor) uplo = (uplo == 'L') ? 'U' : 'L'; \ +/* Set a, lda */ \ + Map > rhs(_rhs,depth,cols, OuterStride<>(rhsStride)); \ + MatrixRhs a_tmp; \ +\ + if ((conjA!=0) || (SetDiag==0)) { \ + if (conjA) a_tmp = rhs.conjugate(); else a_tmp = rhs; \ + if (IsZeroDiag) \ + a_tmp.diagonal().setZero(); \ + else if (IsUnitDiag) \ + a_tmp.diagonal().setOnes();\ + a = a_tmp.data(); \ + lda = a_tmp.outerStride(); \ + } else { \ + a = _rhs; \ + lda = rhsStride; \ + } \ + /*std::cout << "TRMM_R: A is square! Go to MKL TRMM implementation! \n";*/ \ +/* call ?trmm*/ \ + MKLPREFIX##trmm(&side, &uplo, &transa, &diag, &m, &n, &alpha_, (const MKLTYPE*)a, &lda, (MKLTYPE*)b, &ldb); \ +\ +/* Add op(a_triangular)*b into res*/ \ + Map > res_tmp(res,rows,cols,OuterStride<>(resStride)); \ + res_tmp=res_tmp+b_tmp; \ + } \ +}; + +EIGEN_MKL_TRMM_R(double, double, d, d) +EIGEN_MKL_TRMM_R(dcomplex, MKL_Complex16, cd, z) +EIGEN_MKL_TRMM_R(float, float, f, s) +EIGEN_MKL_TRMM_R(scomplex, MKL_Complex8, cf, c) + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_TRIANGULAR_MATRIX_MATRIX_MKL_H diff --git a/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector.h b/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector.h index 71b4a52ab80..b1c10c201c5 100644 --- a/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector.h +++ b/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector.h @@ -3,45 +3,36 @@ // // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_TRIANGULARMATRIXVECTOR_H #define EIGEN_TRIANGULARMATRIXVECTOR_H +namespace Eigen { + namespace internal { -template -struct product_triangular_matrix_vector; +template +struct triangular_matrix_vector_product; -template -struct product_triangular_matrix_vector +template +struct triangular_matrix_vector_product { typedef typename scalar_product_traits::ReturnType ResScalar; enum { IsLower = ((Mode&Lower)==Lower), - HasUnitDiag = (Mode & UnitDiag)==UnitDiag + HasUnitDiag = (Mode & UnitDiag)==UnitDiag, + HasZeroDiag = (Mode & ZeroDiag)==ZeroDiag }; - static EIGEN_DONT_INLINE void run(Index rows, Index cols, const LhsScalar* _lhs, Index lhsStride, + static EIGEN_DONT_INLINE void run(Index _rows, Index _cols, const LhsScalar* _lhs, Index lhsStride, const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, ResScalar alpha) { static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH; + Index size = (std::min)(_rows,_cols); + Index rows = IsLower ? _rows : (std::min)(_rows,_cols); + Index cols = IsLower ? (std::min)(_rows,_cols) : _cols; typedef Map, 0, OuterStride<> > LhsMap; const LhsMap lhs(_lhs,rows,cols,OuterStride<>(lhsStride)); @@ -54,45 +45,57 @@ struct product_triangular_matrix_vector > ResMap; ResMap res(_res,rows); - for (Index pi=0; pi0) + if ((!(HasUnitDiag||HasZeroDiag)) || (--r)>0) res.segment(s,r) += (alpha * cjRhs.coeff(i)) * cjLhs.col(i).segment(s,r); if (HasUnitDiag) res.coeffRef(i) += alpha * cjRhs.coeff(i); } - Index r = IsLower ? cols - pi - actualPanelWidth : pi; + Index r = IsLower ? rows - pi - actualPanelWidth : pi; if (r>0) { Index s = IsLower ? pi+actualPanelWidth : 0; - general_matrix_vector_product::run( + general_matrix_vector_product::run( r, actualPanelWidth, &lhs.coeffRef(s,pi), lhsStride, &rhs.coeffRef(pi), rhsIncr, &res.coeffRef(s), resIncr, alpha); } } + if((!IsLower) && cols>size) + { + general_matrix_vector_product::run( + rows, cols-size, + &lhs.coeffRef(0,size), lhsStride, + &rhs.coeffRef(size), rhsIncr, + _res, resIncr, alpha); + } } }; -template -struct product_triangular_matrix_vector +template +struct triangular_matrix_vector_product { typedef typename scalar_product_traits::ReturnType ResScalar; enum { IsLower = ((Mode&Lower)==Lower), - HasUnitDiag = (Mode & UnitDiag)==UnitDiag + HasUnitDiag = (Mode & UnitDiag)==UnitDiag, + HasZeroDiag = (Mode & ZeroDiag)==ZeroDiag }; - static void run(Index rows, Index cols, const LhsScalar* _lhs, Index lhsStride, + static void run(Index _rows, Index _cols, const LhsScalar* _lhs, Index lhsStride, const RhsScalar* _rhs, Index rhsIncr, ResScalar* _res, Index resIncr, ResScalar alpha) { static const Index PanelWidth = EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH; + Index diagSize = (std::min)(_rows,_cols); + Index rows = IsLower ? _rows : diagSize; + Index cols = IsLower ? diagSize : _cols; typedef Map, 0, OuterStride<> > LhsMap; const LhsMap lhs(_lhs,rows,cols,OuterStride<>(lhsStride)); @@ -105,15 +108,15 @@ struct product_triangular_matrix_vector, 0, InnerStride<> > ResMap; ResMap res(_res,rows,InnerStride<>(resIncr)); - for (Index pi=0; pi0) + if ((!(HasUnitDiag||HasZeroDiag)) || (--r)>0) res.coeffRef(i) += alpha * (cjLhs.row(i).segment(s,r).cwiseProduct(cjRhs.segment(s,r).transpose())).sum(); if (HasUnitDiag) res.coeffRef(i) += alpha * cjRhs.coeff(i); @@ -122,13 +125,21 @@ struct product_triangular_matrix_vector0) { Index s = IsLower ? 0 : pi + actualPanelWidth; - general_matrix_vector_product::run( + general_matrix_vector_product::run( actualPanelWidth, r, &lhs.coeffRef(pi,s), lhsStride, &rhs.coeffRef(s), rhsIncr, &res.coeffRef(pi), resIncr, alpha); } } + if(IsLower && rows>diagSize) + { + general_matrix_vector_product::run( + rows-diagSize, cols, + &lhs.coeffRef(diagSize,0), lhsStride, + &rhs.coeffRef(0), rhsIncr, + &res.coeffRef(diagSize), resIncr, alpha); + } } }; @@ -180,7 +191,7 @@ struct TriangularProduct { eigen_assert(dst.rows()==m_lhs.rows() && dst.cols()==m_rhs.cols()); - typedef TriangularProduct<(Mode & UnitDiag) | ((Mode & Lower) ? Upper : Lower),true,Transpose,false,Transpose,true> TriangularProductTranspose; + typedef TriangularProduct<(Mode & (UnitDiag|ZeroDiag)) | ((Mode & Lower) ? Upper : Lower),true,Transpose,false,Transpose,true> TriangularProductTranspose; Transpose dstT(dst); internal::trmv_selector<(int(internal::traits::Flags)&RowMajorBit) ? ColMajor : RowMajor>::run( TriangularProductTranspose(m_rhs.transpose(),m_lhs.transpose()), dstT, alpha); @@ -208,8 +219,8 @@ template<> struct trmv_selector typedef typename ProductType::RhsBlasTraits RhsBlasTraits; typedef Map, Aligned> MappedDest; - const ActualLhsType actualLhs = LhsBlasTraits::extract(prod.lhs()); - const ActualRhsType actualRhs = RhsBlasTraits::extract(prod.rhs()); + typename internal::add_const_on_value_type::type actualLhs = LhsBlasTraits::extract(prod.lhs()); + typename internal::add_const_on_value_type::type actualRhs = RhsBlasTraits::extract(prod.rhs()); ResScalar actualAlpha = alpha * LhsBlasTraits::extractScalarFactor(prod.lhs()) * RhsBlasTraits::extractScalarFactor(prod.rhs()); @@ -247,7 +258,7 @@ template<> struct trmv_selector MappedDest(actualDestPtr, dest.size()) = dest; } - internal::product_triangular_matrix_vector + internal::triangular_matrix_vector_product struct trmv_selector Map(actualRhsPtr, actualRhs.size()) = actualRhs; } - internal::product_triangular_matrix_vector + internal::triangular_matrix_vector_product struct trmv_selector } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_TRIANGULARMATRIXVECTOR_H diff --git a/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector_MKL.h b/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector_MKL.h new file mode 100644 index 00000000000..3589b8c5ef6 --- /dev/null +++ b/extern/Eigen3/Eigen/src/Core/products/TriangularMatrixVector_MKL.h @@ -0,0 +1,247 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + 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 Intel Corporation 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. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL + * Triangular matrix-vector product functionality based on ?TRMV. + ******************************************************************************** +*/ + +#ifndef EIGEN_TRIANGULAR_MATRIX_VECTOR_MKL_H +#define EIGEN_TRIANGULAR_MATRIX_VECTOR_MKL_H + +namespace Eigen { + +namespace internal { + +/********************************************************************** +* This file implements triangular matrix-vector multiplication using BLAS +**********************************************************************/ + +// trmv/hemv specialization + +template +struct triangular_matrix_vector_product_trmv : + triangular_matrix_vector_product {}; + +#define EIGEN_MKL_TRMV_SPECIALIZE(Scalar) \ +template \ +struct triangular_matrix_vector_product { \ + static EIGEN_DONT_INLINE void run(Index _rows, Index _cols, const Scalar* _lhs, Index lhsStride, \ + const Scalar* _rhs, Index rhsIncr, Scalar* _res, Index resIncr, Scalar alpha) { \ + triangular_matrix_vector_product_trmv::run( \ + _rows, _cols, _lhs, lhsStride, _rhs, rhsIncr, _res, resIncr, alpha); \ + } \ +}; \ +template \ +struct triangular_matrix_vector_product { \ + static EIGEN_DONT_INLINE void run(Index _rows, Index _cols, const Scalar* _lhs, Index lhsStride, \ + const Scalar* _rhs, Index rhsIncr, Scalar* _res, Index resIncr, Scalar alpha) { \ + triangular_matrix_vector_product_trmv::run( \ + _rows, _cols, _lhs, lhsStride, _rhs, rhsIncr, _res, resIncr, alpha); \ + } \ +}; + +EIGEN_MKL_TRMV_SPECIALIZE(double) +EIGEN_MKL_TRMV_SPECIALIZE(float) +EIGEN_MKL_TRMV_SPECIALIZE(dcomplex) +EIGEN_MKL_TRMV_SPECIALIZE(scomplex) + +// implements col-major: res += alpha * op(triangular) * vector +#define EIGEN_MKL_TRMV_CM(EIGTYPE, MKLTYPE, EIGPREFIX, MKLPREFIX) \ +template \ +struct triangular_matrix_vector_product_trmv { \ + enum { \ + IsLower = (Mode&Lower) == Lower, \ + SetDiag = (Mode&(ZeroDiag|UnitDiag)) ? 0 : 1, \ + IsUnitDiag = (Mode&UnitDiag) ? 1 : 0, \ + IsZeroDiag = (Mode&ZeroDiag) ? 1 : 0, \ + LowUp = IsLower ? Lower : Upper \ + }; \ + static EIGEN_DONT_INLINE void run(Index _rows, Index _cols, const EIGTYPE* _lhs, Index lhsStride, \ + const EIGTYPE* _rhs, Index rhsIncr, EIGTYPE* _res, Index resIncr, EIGTYPE alpha, level3_blocking& blocking) \ + { \ + if (ConjLhs || IsZeroDiag) { \ + triangular_matrix_vector_product::run( \ + _rows, _cols, _lhs, lhsStride, _rhs, rhsIncr, _res, resIncr, alpha, blocking); \ + return; \ + }\ + Index size = (std::min)(_rows,_cols); \ + Index rows = IsLower ? _rows : size; \ + Index cols = IsLower ? size : _cols; \ +\ + typedef VectorX##EIGPREFIX VectorRhs; \ + EIGTYPE *x, *y;\ +\ +/* Set x*/ \ + Map > rhs(_rhs,cols,InnerStride<>(rhsIncr)); \ + VectorRhs x_tmp; \ + if (ConjRhs) x_tmp = rhs.conjugate(); else x_tmp = rhs; \ + x = x_tmp.data(); \ +\ +/* Square part handling */\ +\ + char trans, uplo, diag; \ + MKL_INT m, n, lda, incx, incy; \ + EIGTYPE const *a; \ + MKLTYPE alpha_, beta_; \ + assign_scalar_eig2mkl(alpha_, alpha); \ + assign_scalar_eig2mkl(beta_, EIGTYPE(1)); \ +\ +/* Set m, n */ \ + n = (MKL_INT)size; \ + lda = lhsStride; \ + incx = 1; \ + incy = resIncr; \ +\ +/* Set uplo, trans and diag*/ \ + trans = 'N'; \ + uplo = IsLower ? 'L' : 'U'; \ + diag = IsUnitDiag ? 'U' : 'N'; \ +\ +/* call ?TRMV*/ \ + MKLPREFIX##trmv(&uplo, &trans, &diag, &n, (const MKLTYPE*)_lhs, &lda, (MKLTYPE*)x, &incx); \ +\ +/* Add op(a_tr)rhs into res*/ \ + MKLPREFIX##axpy(&n, &alpha_,(const MKLTYPE*)x, &incx, (MKLTYPE*)_res, &incy); \ +/* Non-square case - doesn't fit to MKL ?TRMV. Fall to default triangular product*/ \ + if (size<(std::max)(rows,cols)) { \ + typedef Matrix MatrixLhs; \ + if (ConjRhs) x_tmp = rhs.conjugate(); else x_tmp = rhs; \ + x = x_tmp.data(); \ + if (size \ +struct triangular_matrix_vector_product_trmv { \ + enum { \ + IsLower = (Mode&Lower) == Lower, \ + SetDiag = (Mode&(ZeroDiag|UnitDiag)) ? 0 : 1, \ + IsUnitDiag = (Mode&UnitDiag) ? 1 : 0, \ + IsZeroDiag = (Mode&ZeroDiag) ? 1 : 0, \ + LowUp = IsLower ? Lower : Upper \ + }; \ + static EIGEN_DONT_INLINE void run(Index _rows, Index _cols, const EIGTYPE* _lhs, Index lhsStride, \ + const EIGTYPE* _rhs, Index rhsIncr, EIGTYPE* _res, Index resIncr, EIGTYPE alpha, level3_blocking& blocking) \ + { \ + if (IsZeroDiag) { \ + triangular_matrix_vector_product::run( \ + _rows, _cols, _lhs, lhsStride, _rhs, rhsIncr, _res, resIncr, alpha, blocking); \ + return; \ + }\ + Index size = (std::min)(_rows,_cols); \ + Index rows = IsLower ? _rows : size; \ + Index cols = IsLower ? size : _cols; \ +\ + typedef VectorX##EIGPREFIX VectorRhs; \ + EIGTYPE *x, *y;\ +\ +/* Set x*/ \ + Map > rhs(_rhs,cols,InnerStride<>(rhsIncr)); \ + VectorRhs x_tmp; \ + if (ConjRhs) x_tmp = rhs.conjugate(); else x_tmp = rhs; \ + x = x_tmp.data(); \ +\ +/* Square part handling */\ +\ + char trans, uplo, diag; \ + MKL_INT m, n, lda, incx, incy; \ + EIGTYPE const *a; \ + MKLTYPE alpha_, beta_; \ + assign_scalar_eig2mkl(alpha_, alpha); \ + assign_scalar_eig2mkl(beta_, EIGTYPE(1)); \ +\ +/* Set m, n */ \ + n = (MKL_INT)size; \ + lda = lhsStride; \ + incx = 1; \ + incy = resIncr; \ +\ +/* Set uplo, trans and diag*/ \ + trans = ConjLhs ? 'C' : 'T'; \ + uplo = IsLower ? 'U' : 'L'; \ + diag = IsUnitDiag ? 'U' : 'N'; \ +\ +/* call ?TRMV*/ \ + MKLPREFIX##trmv(&uplo, &trans, &diag, &n, (const MKLTYPE*)_lhs, &lda, (MKLTYPE*)x, &incx); \ +\ +/* Add op(a_tr)rhs into res*/ \ + MKLPREFIX##axpy(&n, &alpha_,(const MKLTYPE*)x, &incx, (MKLTYPE*)_res, &incy); \ +/* Non-square case - doesn't fit to MKL ?TRMV. Fall to default triangular product*/ \ + if (size<(std::max)(rows,cols)) { \ + typedef Matrix MatrixLhs; \ + if (ConjRhs) x_tmp = rhs.conjugate(); else x_tmp = rhs; \ + x = x_tmp.data(); \ + if (size // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_TRIANGULAR_SOLVER_MATRIX_H #define EIGEN_TRIANGULAR_SOLVER_MATRIX_H +namespace Eigen { + namespace internal { // if the rhs is row major, let's transpose the product @@ -34,14 +21,15 @@ struct triangular_solve_matrix& blocking) { triangular_solve_matrix< Scalar, Index, Side==OnTheLeft?OnTheRight:OnTheLeft, (Mode&UnitDiag) | ((Mode&Upper) ? Lower : Upper), NumTraits::IsComplex && Conjugate, TriStorageOrder==RowMajor ? ColMajor : RowMajor, ColMajor> - ::run(size, cols, tri, triStride, _other, otherStride); + ::run(size, cols, tri, triStride, _other, otherStride, blocking); } }; @@ -53,7 +41,8 @@ struct triangular_solve_matrix& blocking) { Index cols = otherSize; const_blas_data_mapper tri(_tri,triStride); @@ -65,22 +54,29 @@ struct triangular_solve_matrix(kc, mc, nc); + Index kc = blocking.kc(); // cache block size along the K direction + Index mc = (std::min)(size,blocking.mc()); // cache block size along the M direction + std::size_t sizeA = kc*mc; + std::size_t sizeB = kc*cols; std::size_t sizeW = kc*Traits::WorkSpaceFactor; - std::size_t sizeB = sizeW + kc*cols; - ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0); - ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0); - Scalar* blockB = allocatedBlockB + sizeW; + + ei_declare_aligned_stack_constructed_variable(Scalar, blockA, sizeA, blocking.blockA()); + ei_declare_aligned_stack_constructed_variable(Scalar, blockB, sizeB, blocking.blockB()); + ei_declare_aligned_stack_constructed_variable(Scalar, blockW, sizeW, blocking.blockW()); conj_if conj; gebp_kernel gebp_kernel; gemm_pack_lhs pack_lhs; gemm_pack_rhs pack_rhs; + // the goal here is to subdivise the Rhs panels such that we keep some cache + // coherence when accessing the rhs elements + std::ptrdiff_t l1, l2; + manage_caching_sizes(GetAction, &l1, &l2); + Index subcols = cols>0 ? l2/(4 * sizeof(Scalar) * otherStride) : 0; + subcols = std::max((subcols/Traits::nr)*Traits::nr, Traits::nr); + for(Index k2=IsLower ? 0 : size; IsLower ? k20; IsLower ? k2+=kc : k2-=kc) @@ -92,16 +88,18 @@ struct triangular_solve_matrix general block copy (done during the next step) - // - R1 = L1^-1 B => tricky part + // - R1 = A11^-1 B => tricky part // - update B from the new R1 => actually this has to be performed continuously during the above step - // - R2 = L2 * B => GEPP + // - R2 -= A21 * B => GEPP - // The tricky part: compute R1 = L1^-1 B while updating B from R1 - // The idea is to split L1 into multiple small vertical panels. - // Each panel can be split into a small triangular part A1 which is processed without optimization, - // and the remaining small part A2 which is processed using gebp with appropriate block strides + // The tricky part: compute R1 = A11^-1 B while updating B from R1 + // The idea is to split A11 into multiple small vertical panels. + // Each panel can be split into a small triangular part T1k which is processed without optimization, + // and the remaining small part T2k which is processed using gebp with appropriate block strides + for(Index j2=0; j2(actual_kc-k1, SmallPanelWidth); @@ -114,11 +112,11 @@ struct triangular_solve_matrix0) @@ -152,13 +150,13 @@ struct triangular_solve_matrix GEPP + + // R2 -= A21 * B => GEPP { Index start = IsLower ? k2+kc : 0; Index end = IsLower ? size : k2-kc; @@ -169,7 +167,7 @@ struct triangular_solve_matrix& blocking) { Index rows = otherSize; const_blas_data_mapper rhs(_tri,triStride); @@ -198,19 +197,16 @@ struct triangular_solve_matrix(Traits::Max_kc/4,size); // cache block size along the K direction -// Index mc = std::min(Traits::Max_mc,size); // cache block size along the M direction - // check that !!!! - Index kc = size; // cache block size along the K direction - Index mc = size; // cache block size along the M direction - Index nc = rows; // cache block size along the N direction - computeProductBlockingSizes(kc, mc, nc); + Index kc = blocking.kc(); // cache block size along the K direction + Index mc = (std::min)(rows,blocking.mc()); // cache block size along the M direction + std::size_t sizeA = kc*mc; + std::size_t sizeB = kc*size; std::size_t sizeW = kc*Traits::WorkSpaceFactor; - std::size_t sizeB = sizeW + kc*size; - ei_declare_aligned_stack_constructed_variable(Scalar, blockA, kc*mc, 0); - ei_declare_aligned_stack_constructed_variable(Scalar, allocatedBlockB, sizeB, 0); - Scalar* blockB = allocatedBlockB + sizeW; + + ei_declare_aligned_stack_constructed_variable(Scalar, blockA, sizeA, blocking.blockA()); + ei_declare_aligned_stack_constructed_variable(Scalar, blockB, sizeB, blocking.blockB()); + ei_declare_aligned_stack_constructed_variable(Scalar, blockW, sizeW, blocking.blockW()); conj_if conj; gebp_kernel gebp_kernel; @@ -277,7 +273,7 @@ struct triangular_solve_matrix0) gebp_kernel(_other+i2+startPanel*otherStride, otherStride, blockA, geb, actual_mc, actual_kc, rs, Scalar(-1), - -1, -1, 0, 0, allocatedBlockB); + -1, -1, 0, 0, blockW); } } } @@ -316,4 +312,6 @@ struct triangular_solve_matrix \ +struct triangular_solve_matrix \ +{ \ + enum { \ + IsLower = (Mode&Lower) == Lower, \ + IsUnitDiag = (Mode&UnitDiag) ? 1 : 0, \ + IsZeroDiag = (Mode&ZeroDiag) ? 1 : 0, \ + conjA = ((TriStorageOrder==ColMajor) && Conjugate) ? 1 : 0 \ + }; \ + static EIGEN_DONT_INLINE void run( \ + Index size, Index otherSize, \ + const EIGTYPE* _tri, Index triStride, \ + EIGTYPE* _other, Index otherStride, level3_blocking& /*blocking*/) \ + { \ + MKL_INT m = size, n = otherSize, lda, ldb; \ + char side = 'L', uplo, diag='N', transa; \ + /* Set alpha_ */ \ + MKLTYPE alpha; \ + EIGTYPE myone(1); \ + assign_scalar_eig2mkl(alpha, myone); \ + ldb = otherStride;\ +\ + const EIGTYPE *a; \ +/* Set trans */ \ + transa = (TriStorageOrder==RowMajor) ? ((Conjugate) ? 'C' : 'T') : 'N'; \ +/* Set uplo */ \ + uplo = IsLower ? 'L' : 'U'; \ + if (TriStorageOrder==RowMajor) uplo = (uplo == 'L') ? 'U' : 'L'; \ +/* Set a, lda */ \ + typedef Matrix MatrixTri; \ + Map > tri(_tri,size,size,OuterStride<>(triStride)); \ + MatrixTri a_tmp; \ +\ + if (conjA) { \ + a_tmp = tri.conjugate(); \ + a = a_tmp.data(); \ + lda = a_tmp.outerStride(); \ + } else { \ + a = _tri; \ + lda = triStride; \ + } \ + if (IsUnitDiag) diag='U'; \ +/* call ?trsm*/ \ + MKLPREFIX##trsm(&side, &uplo, &transa, &diag, &m, &n, &alpha, (const MKLTYPE*)a, &lda, (MKLTYPE*)_other, &ldb); \ + } \ +}; + +EIGEN_MKL_TRSM_L(double, double, d) +EIGEN_MKL_TRSM_L(dcomplex, MKL_Complex16, z) +EIGEN_MKL_TRSM_L(float, float, s) +EIGEN_MKL_TRSM_L(scomplex, MKL_Complex8, c) + + +// implements RightSide general * op(triangular)^-1 +#define EIGEN_MKL_TRSM_R(EIGTYPE, MKLTYPE, MKLPREFIX) \ +template \ +struct triangular_solve_matrix \ +{ \ + enum { \ + IsLower = (Mode&Lower) == Lower, \ + IsUnitDiag = (Mode&UnitDiag) ? 1 : 0, \ + IsZeroDiag = (Mode&ZeroDiag) ? 1 : 0, \ + conjA = ((TriStorageOrder==ColMajor) && Conjugate) ? 1 : 0 \ + }; \ + static EIGEN_DONT_INLINE void run( \ + Index size, Index otherSize, \ + const EIGTYPE* _tri, Index triStride, \ + EIGTYPE* _other, Index otherStride, level3_blocking& /*blocking*/) \ + { \ + MKL_INT m = otherSize, n = size, lda, ldb; \ + char side = 'R', uplo, diag='N', transa; \ + /* Set alpha_ */ \ + MKLTYPE alpha; \ + EIGTYPE myone(1); \ + assign_scalar_eig2mkl(alpha, myone); \ + ldb = otherStride;\ +\ + const EIGTYPE *a; \ +/* Set trans */ \ + transa = (TriStorageOrder==RowMajor) ? ((Conjugate) ? 'C' : 'T') : 'N'; \ +/* Set uplo */ \ + uplo = IsLower ? 'L' : 'U'; \ + if (TriStorageOrder==RowMajor) uplo = (uplo == 'L') ? 'U' : 'L'; \ +/* Set a, lda */ \ + typedef Matrix MatrixTri; \ + Map > tri(_tri,size,size,OuterStride<>(triStride)); \ + MatrixTri a_tmp; \ +\ + if (conjA) { \ + a_tmp = tri.conjugate(); \ + a = a_tmp.data(); \ + lda = a_tmp.outerStride(); \ + } else { \ + a = _tri; \ + lda = triStride; \ + } \ + if (IsUnitDiag) diag='U'; \ +/* call ?trsm*/ \ + MKLPREFIX##trsm(&side, &uplo, &transa, &diag, &m, &n, &alpha, (const MKLTYPE*)a, &lda, (MKLTYPE*)_other, &ldb); \ + /*std::cout << "TRMS_L specialization!\n";*/ \ + } \ +}; + +EIGEN_MKL_TRSM_R(double, double, d) +EIGEN_MKL_TRSM_R(dcomplex, MKL_Complex16, z) +EIGEN_MKL_TRSM_R(float, float, s) +EIGEN_MKL_TRSM_R(scomplex, MKL_Complex8, c) + + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_TRIANGULAR_SOLVER_MATRIX_MKL_H diff --git a/extern/Eigen3/Eigen/src/Core/products/TriangularSolverVector.h b/extern/Eigen3/Eigen/src/Core/products/TriangularSolverVector.h index 639d4a5b476..ce4d1008801 100644 --- a/extern/Eigen3/Eigen/src/Core/products/TriangularSolverVector.h +++ b/extern/Eigen3/Eigen/src/Core/products/TriangularSolverVector.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_TRIANGULAR_SOLVER_VECTOR_H #define EIGEN_TRIANGULAR_SOLVER_VECTOR_H +namespace Eigen { + namespace internal { template @@ -147,4 +134,6 @@ struct triangular_solve_vector // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_BLASUTIL_H #define EIGEN_BLASUTIL_H @@ -28,6 +13,8 @@ // This file contains many lightweight helper classes used to // implement and control fast level 2 and level 3 BLAS-like routines. +namespace Eigen { + namespace internal { // forward declarations @@ -47,7 +34,7 @@ template< int ResStorageOrder> struct general_matrix_matrix_product; -template +template struct general_matrix_vector_product; @@ -56,11 +43,15 @@ template struct conj_if; template<> struct conj_if { template inline T operator()(const T& x) { return conj(x); } + template + inline T pconj(const T& x) { return internal::pconj(x); } }; template<> struct conj_if { template inline const T& operator()(const T& x) { return x; } + template + inline const T& pconj(const T& x) { return x; } }; template struct conj_helper @@ -118,11 +109,11 @@ template struct conj_helper struct get_factor { - EIGEN_STRONG_INLINE static To run(const From& x) { return x; } + static EIGEN_STRONG_INLINE To run(const From& x) { return x; } }; template struct get_factor::Real> { - EIGEN_STRONG_INLINE static typename NumTraits::Real run(const Scalar& x) { return real(x); } + static EIGEN_STRONG_INLINE typename NumTraits::Real run(const Scalar& x) { return real(x); } }; // Lightweight helper class to access matrix coefficients. @@ -175,7 +166,7 @@ template struct blas_traits ExtractType, typename _ExtractType::PlainObject >::type DirectLinearAccessType; - static inline const ExtractType extract(const XprType& x) { return x; } + static inline ExtractType extract(const XprType& x) { return x; } static inline const Scalar extractScalarFactor(const XprType&) { return Scalar(1); } }; @@ -192,7 +183,7 @@ struct blas_traits, NestedXpr> > IsComplex = NumTraits::IsComplex, NeedToConjugate = Base::NeedToConjugate ? 0 : IsComplex }; - static inline const ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); } + static inline ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); } static inline Scalar extractScalarFactor(const XprType& x) { return conj(Base::extractScalarFactor(x.nestedExpression())); } }; @@ -204,7 +195,7 @@ struct blas_traits, NestedXpr> > typedef blas_traits Base; typedef CwiseUnaryOp, NestedXpr> XprType; typedef typename Base::ExtractType ExtractType; - static inline const ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); } + static inline ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); } static inline Scalar extractScalarFactor(const XprType& x) { return x.functor().m_other * Base::extractScalarFactor(x.nestedExpression()); } }; @@ -217,7 +208,7 @@ struct blas_traits, NestedXpr> > typedef blas_traits Base; typedef CwiseUnaryOp, NestedXpr> XprType; typedef typename Base::ExtractType ExtractType; - static inline const ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); } + static inline ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); } static inline Scalar extractScalarFactor(const XprType& x) { return - Base::extractScalarFactor(x.nestedExpression()); } }; @@ -239,7 +230,7 @@ struct blas_traits > enum { IsTransposed = Base::IsTransposed ? 0 : 1 }; - static inline const ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); } + static inline ExtractType extract(const XprType& x) { return Base::extract(x.nestedExpression()); } static inline Scalar extractScalarFactor(const XprType& x) { return Base::extractScalarFactor(x.nestedExpression()); } }; @@ -252,7 +243,7 @@ template::HasUsableDirectA struct extract_data_selector { static const typename T::Scalar* run(const T& m) { - return const_cast(&blas_traits::extract(m).coeffRef(0,0)); // FIXME this should be .data() + return blas_traits::extract(m).data(); } }; @@ -268,4 +259,6 @@ template const typename T::Scalar* extract_data(const T& m) } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_BLASUTIL_H diff --git a/extern/Eigen3/Eigen/src/Core/util/Constants.h b/extern/Eigen3/Eigen/src/Core/util/Constants.h index c3dd3a09d00..3fd45e84f8e 100644 --- a/extern/Eigen3/Eigen/src/Core/util/Constants.h +++ b/extern/Eigen3/Eigen/src/Core/util/Constants.h @@ -4,28 +4,15 @@ // Copyright (C) 2008-2009 Gael Guennebaud // Copyright (C) 2007-2009 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_CONSTANTS_H #define EIGEN_CONSTANTS_H +namespace Eigen { + /** This value means that a quantity is not known at compile-time, and that instead the value is * stored in some runtime variable. * @@ -188,7 +175,9 @@ enum { /** View matrix as an upper triangular matrix with zeros on the diagonal. */ StrictlyUpper=ZeroDiag|Upper, /** Used in BandMatrix and SelfAdjointView to indicate that the matrix is self-adjoint. */ - SelfAdjoint=0x10 + SelfAdjoint=0x10, + /** Used to support symmetric, non-selfadjoint, complex matrices. */ + Symmetric=0x20 }; /** \ingroup enums @@ -200,8 +189,6 @@ enum { Aligned=1 }; -enum { ConditionalJumpCost = 5 }; - /** \ingroup enums * Enum used by DenseBase::corner() in Eigen2 compatibility mode. */ // FIXME after the corner() API change, this was not needed anymore, except by AlignedBox @@ -223,8 +210,6 @@ enum DirectionType { BothDirections }; -enum ProductEvaluationMode { NormalProduct, CacheFriendlyProduct }; - /** \internal \ingroup enums * Enum to specify how to traverse the entries of a matrix. */ enum { @@ -257,6 +242,13 @@ enum { CompleteUnrolling }; +/** \internal \ingroup enums + * Enum to specify whether to use the default (built-in) implementation or the specialization. */ +enum { + Specialized, + BuiltIn +}; + /** \ingroup enums * Enum containing possible values for the \p _Options template parameter of * Matrix, Array and BandMatrix. */ @@ -280,26 +272,21 @@ enum { OnTheRight = 2 }; -/* the following could as well be written: - * enum NoChange_t { NoChange }; - * but it feels dangerous to disambiguate overloaded functions on enum/integer types. - * If on some platform it is really impossible to get rid of "unused variable" warnings, then - * we can always come back to that solution. +/* the following used to be written as: + * + * struct NoChange_t {}; + * namespace { + * EIGEN_UNUSED NoChange_t NoChange; + * } + * + * on the ground that it feels dangerous to disambiguate overloaded functions on enum/integer types. + * However, this leads to "variable declared but never referenced" warnings on Intel Composer XE, + * and we do not know how to get rid of them (bug 450). */ -struct NoChange_t {}; -namespace { - EIGEN_UNUSED NoChange_t NoChange; -} -struct Sequential_t {}; -namespace { - EIGEN_UNUSED Sequential_t Sequential; -} - -struct Default_t {}; -namespace { - EIGEN_UNUSED Default_t Default; -} +enum NoChange_t { NoChange }; +enum Sequential_t { Sequential }; +enum Default_t { Default }; /** \internal \ingroup enums * Used in AmbiVector. */ @@ -375,7 +362,7 @@ enum QRPreconditioners { #error The preprocessor symbol 'Success' is defined, possibly by the X11 header file X.h #endif -/** \ingroups enums +/** \ingroup enums * Enum for reporting the status of a computation. */ enum ComputationInfo { /** Computation was successful. */ @@ -383,7 +370,10 @@ enum ComputationInfo { /** The provided data did not satisfy the prerequisites. */ NumericalIssue = 1, /** Iterative procedure did not converge. */ - NoConvergence = 2 + NoConvergence = 2, + /** The inputs are invalid, or the algorithm has been improperly called. + * When assertions are enabled, such errors trigger an assert. */ + InvalidInput = 3 }; /** \ingroup enums @@ -436,4 +426,6 @@ struct MatrixXpr {}; /** The type used to identify an array expression */ struct ArrayXpr {}; +} // end namespace Eigen + #endif // EIGEN_CONSTANTS_H diff --git a/extern/Eigen3/Eigen/src/Core/util/DisableStupidWarnings.h b/extern/Eigen3/Eigen/src/Core/util/DisableStupidWarnings.h index 00730524b26..6a0bf0629c5 100644 --- a/extern/Eigen3/Eigen/src/Core/util/DisableStupidWarnings.h +++ b/extern/Eigen3/Eigen/src/Core/util/DisableStupidWarnings.h @@ -21,15 +21,13 @@ #elif defined __INTEL_COMPILER // 2196 - routine is both "inline" and "noinline" ("noinline" assumed) // ICC 12 generates this warning even without any inline keyword, when defining class methods 'inline' i.e. inside of class body - // 2536 - type qualifiers are meaningless here - // ICC 12 generates this warning when a function return type is const qualified, even if that type is a template-parameter-dependent // typedef that may be a reference type. // 279 - controlling expression is constant // ICC 12 generates this warning on assert(constant_expression_depending_on_template_params) and frankly this is a legitimate use case. #ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS #pragma warning push #endif - #pragma warning disable 2196 2536 279 + #pragma warning disable 2196 279 #elif defined __clang__ // -Wconstant-logical-operand - warning: use of logical && with constant operand; switch to bitwise & or remove constant // this is really a stupid warning as it warns on compile-time expressions involving enums diff --git a/extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h b/extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h index 7fbccf98c2b..bcdfe3914e3 100644 --- a/extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h +++ b/extern/Eigen3/Eigen/src/Core/util/ForwardDeclarations.h @@ -4,28 +4,14 @@ // Copyright (C) 2007-2010 Benoit Jacob // Copyright (C) 2008-2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_FORWARDDECLARATIONS_H #define EIGEN_FORWARDDECLARATIONS_H +namespace Eigen { namespace internal { template struct traits; @@ -133,6 +119,7 @@ template class WithFormat; template struct CommaInitializer; template class ReturnByValue; template class ArrayWrapper; +template class MatrixWrapper; namespace internal { template struct solve_retval_base; @@ -282,6 +269,8 @@ template class Homogeneous; // MatrixFunctions module template struct MatrixExponentialReturnValue; template class MatrixFunctionReturnValue; +template class MatrixSquareRootReturnValue; +template class MatrixLogarithmReturnValue; namespace internal { template @@ -304,4 +293,6 @@ template struct eigen2_part_return_type; } #endif +} // end namespace Eigen + #endif // EIGEN_FORWARDDECLARATIONS_H diff --git a/extern/Eigen3/Eigen/src/Core/util/MKL_support.h b/extern/Eigen3/Eigen/src/Core/util/MKL_support.h new file mode 100644 index 00000000000..1e6e355d626 --- /dev/null +++ b/extern/Eigen3/Eigen/src/Core/util/MKL_support.h @@ -0,0 +1,109 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + 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 Intel Corporation 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. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL + * Include file with common MKL declarations + ******************************************************************************** +*/ + +#ifndef EIGEN_MKL_SUPPORT_H +#define EIGEN_MKL_SUPPORT_H + +#ifdef EIGEN_USE_MKL_ALL + #ifndef EIGEN_USE_BLAS + #define EIGEN_USE_BLAS + #endif + #ifndef EIGEN_USE_LAPACKE + #define EIGEN_USE_LAPACKE + #endif + #ifndef EIGEN_USE_MKL_VML + #define EIGEN_USE_MKL_VML + #endif +#endif + +#ifdef EIGEN_USE_LAPACKE_STRICT + #define EIGEN_USE_LAPACKE +#endif + +#if defined(EIGEN_USE_BLAS) || defined(EIGEN_USE_LAPACKE) || defined(EIGEN_USE_MKL_VML) + #define EIGEN_USE_MKL +#endif + +#if defined EIGEN_USE_MKL + +#include +#include +#define EIGEN_MKL_VML_THRESHOLD 128 + +namespace Eigen { + +typedef std::complex dcomplex; +typedef std::complex scomplex; + +namespace internal { + +template +static inline void assign_scalar_eig2mkl(MKLType& mklScalar, const EigenType& eigenScalar) { + mklScalar=eigenScalar; +} + +template +static inline void assign_conj_scalar_eig2mkl(MKLType& mklScalar, const EigenType& eigenScalar) { + mklScalar=eigenScalar; +} + +template <> +inline void assign_scalar_eig2mkl(MKL_Complex16& mklScalar, const dcomplex& eigenScalar) { + mklScalar.real=eigenScalar.real(); + mklScalar.imag=eigenScalar.imag(); +} + +template <> +inline void assign_scalar_eig2mkl(MKL_Complex8& mklScalar, const scomplex& eigenScalar) { + mklScalar.real=eigenScalar.real(); + mklScalar.imag=eigenScalar.imag(); +} + +template <> +inline void assign_conj_scalar_eig2mkl(MKL_Complex16& mklScalar, const dcomplex& eigenScalar) { + mklScalar.real=eigenScalar.real(); + mklScalar.imag=-eigenScalar.imag(); +} + +template <> +inline void assign_conj_scalar_eig2mkl(MKL_Complex8& mklScalar, const scomplex& eigenScalar) { + mklScalar.real=eigenScalar.real(); + mklScalar.imag=-eigenScalar.imag(); +} + +} // end namespace internal + +} // end namespace Eigen + +#endif + +#endif // EIGEN_MKL_SUPPORT_H diff --git a/extern/Eigen3/Eigen/src/Core/util/Macros.h b/extern/Eigen3/Eigen/src/Core/util/Macros.h index b7c2b79af92..d973a68372f 100644 --- a/extern/Eigen3/Eigen/src/Core/util/Macros.h +++ b/extern/Eigen3/Eigen/src/Core/util/Macros.h @@ -1,35 +1,19 @@ - // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2008-2010 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_MACROS_H #define EIGEN_MACROS_H #define EIGEN_WORLD_VERSION 3 -#define EIGEN_MAJOR_VERSION 0 -#define EIGEN_MINOR_VERSION 5 +#define EIGEN_MAJOR_VERSION 1 +#define EIGEN_MINOR_VERSION 1 #define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \ (EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \ @@ -235,12 +219,16 @@ #define EIGEN_ONLY_USED_FOR_DEBUG(x) #endif -#if (defined __GNUC__) -#define EIGEN_DEPRECATED __attribute__((deprecated)) -#elif (defined _MSC_VER) -#define EIGEN_DEPRECATED __declspec(deprecated) +#ifndef EIGEN_NO_DEPRECATED_WARNING + #if (defined __GNUC__) + #define EIGEN_DEPRECATED __attribute__((deprecated)) + #elif (defined _MSC_VER) + #define EIGEN_DEPRECATED __declspec(deprecated) + #else + #define EIGEN_DEPRECATED + #endif #else -#define EIGEN_DEPRECATED + #define EIGEN_DEPRECATED #endif #if (defined __GNUC__) @@ -252,7 +240,7 @@ // Suppresses 'unused variable' warnings. #define EIGEN_UNUSED_VARIABLE(var) (void)var; -#if (defined __GNUC__) +#if !defined(EIGEN_ASM_COMMENT) && (defined __GNUC__) #define EIGEN_ASM_COMMENT(X) asm("#" X) #else #define EIGEN_ASM_COMMENT(X) @@ -265,7 +253,7 @@ * If we made alignment depend on whether or not EIGEN_VECTORIZE is defined, it would be impossible to link * vectorized and non-vectorized code. */ -#if (defined __GNUC__) || (defined __PGI) || (defined __IBMCPP__) +#if (defined __GNUC__) || (defined __PGI) || (defined __IBMCPP__) || (defined __ARMCC_VERSION) #define EIGEN_ALIGN_TO_BOUNDARY(n) __attribute__((aligned(n))) #elif (defined _MSC_VER) #define EIGEN_ALIGN_TO_BOUNDARY(n) __declspec(align(n)) diff --git a/extern/Eigen3/Eigen/src/Core/util/Memory.h b/extern/Eigen3/Eigen/src/Core/util/Memory.h index 023716dc9e0..6e06ace44a0 100644 --- a/extern/Eigen3/Eigen/src/Core/util/Memory.h +++ b/extern/Eigen3/Eigen/src/Core/util/Memory.h @@ -7,24 +7,9 @@ // Copyright (C) 2010 Hauke Heibel // Copyright (C) 2010 Thomas Capricelli // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. /***************************************************************************** @@ -80,6 +65,8 @@ #define EIGEN_HAS_MM_MALLOC 0 #endif +namespace Eigen { + namespace internal { inline void throw_std_bad_alloc() @@ -457,7 +444,7 @@ template inline void conditional_aligned_delete_auto(T * * There is also the variant first_aligned(const MatrixBase&) defined in DenseCoeffsBase.h. */ template -inline static Index first_aligned(const Scalar* array, Index size) +static inline Index first_aligned(const Scalar* array, Index size) { typedef typename packet_traits::type Packet; enum { PacketSize = packet_traits::size, @@ -483,7 +470,26 @@ inline static Index first_aligned(const Scalar* array, Index size) } } -} // end namespace internal + +// std::copy is much slower than memcpy, so let's introduce a smart_copy which +// use memcpy on trivial types, i.e., on types that does not require an initialization ctor. +template struct smart_copy_helper; + +template void smart_copy(const T* start, const T* end, T* target) +{ + smart_copy_helper::RequireInitialization>::run(start, end, target); +} + +template struct smart_copy_helper { + static inline void run(const T* start, const T* end, T* target) + { memcpy(target, start, std::ptrdiff_t(end)-std::ptrdiff_t(start)); } +}; + +template struct smart_copy_helper { + static inline void run(const T* start, const T* end, T* target) + { std::copy(start, end, target); } +}; + /***************************************************************************** *** Implementation of runtime stack allocation (falling back to malloc) *** @@ -499,8 +505,6 @@ inline static Index first_aligned(const Scalar* array, Index size) #endif #endif -namespace internal { - // This helper class construct the allocated memory, and takes care of destructing and freeing the handled data // at destruction time. In practice this helper class is mainly useful to avoid memory leak in case of exceptions. template class aligned_stack_memory_handler @@ -531,14 +535,14 @@ template class aligned_stack_memory_handler bool m_deallocate; }; -} +} // end namespace internal /** \internal * Declares, allocates and construct an aligned buffer named NAME of SIZE elements of type TYPE on the stack * if SIZE is smaller than EIGEN_STACK_ALLOCATION_LIMIT, and if stack allocation is supported by the platform * (currently, this is Linux and Visual Studio only). Otherwise the memory is allocated on the heap. * The allocated buffer is automatically deleted when exiting the scope of this declaration. - * If BUFFER is non nul, then the declared variable is simply an alias for BUFFER, and no allocation/deletion occurs. + * If BUFFER is non null, then the declared variable is simply an alias for BUFFER, and no allocation/deletion occurs. * Here is an example: * \code * { @@ -619,7 +623,7 @@ template class aligned_stack_memory_handler #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(true) #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar,Size) \ - EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(((Size)!=Eigen::Dynamic) && ((sizeof(Scalar)*(Size))%16==0)) + EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(bool(((Size)!=Eigen::Dynamic) && ((sizeof(Scalar)*(Size))%16==0))) /****************************************************************************/ @@ -667,24 +671,24 @@ public: return &value; } - aligned_allocator() throw() + aligned_allocator() { } - aligned_allocator( const aligned_allocator& ) throw() + aligned_allocator( const aligned_allocator& ) { } template - aligned_allocator( const aligned_allocator& ) throw() + aligned_allocator( const aligned_allocator& ) { } - ~aligned_allocator() throw() + ~aligned_allocator() { } - size_type max_size() const throw() + size_type max_size() const { return (std::numeric_limits::max)(); } @@ -701,6 +705,15 @@ public: ::new( p ) T( value ); } + // Support for c++11 +#if (__cplusplus >= 201103L) + template + void construct(pointer p, Args&&... args) + { + ::new(p) T(std::forward(args)...); + } +#endif + void destroy( pointer p ) { p->~T(); @@ -720,19 +733,21 @@ public: //---------- Cache sizes ---------- -#if defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) -# if defined(__PIC__) && defined(__i386__) - // Case for x86 with PIC -# define EIGEN_CPUID(abcd,func,id) \ - __asm__ __volatile__ ("xchgl %%ebx, %%esi;cpuid; xchgl %%ebx,%%esi": "=a" (abcd[0]), "=S" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func), "c" (id)); -# else - // Case for x86_64 or x86 w/o PIC -# define EIGEN_CPUID(abcd,func,id) \ - __asm__ __volatile__ ("cpuid": "=a" (abcd[0]), "=b" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func), "c" (id) ); -# endif -#elif defined(_MSC_VER) -# if (_MSC_VER > 1500) -# define EIGEN_CPUID(abcd,func,id) __cpuidex((int*)abcd,func,id) +#if !defined(EIGEN_NO_CPUID) +# if defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) +# if defined(__PIC__) && defined(__i386__) + // Case for x86 with PIC +# define EIGEN_CPUID(abcd,func,id) \ + __asm__ __volatile__ ("xchgl %%ebx, %%esi;cpuid; xchgl %%ebx,%%esi": "=a" (abcd[0]), "=S" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func), "c" (id)); +# else + // Case for x86_64 or x86 w/o PIC +# define EIGEN_CPUID(abcd,func,id) \ + __asm__ __volatile__ ("cpuid": "=a" (abcd[0]), "=b" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func), "c" (id) ); +# endif +# elif defined(_MSC_VER) +# if (_MSC_VER > 1500) +# define EIGEN_CPUID(abcd,func,id) __cpuidex((int*)abcd,func,id) +# endif # endif #endif @@ -742,7 +757,7 @@ namespace internal { inline bool cpuid_is_vendor(int abcd[4], const char* vendor) { - return abcd[1]==((int*)(vendor))[0] && abcd[3]==((int*)(vendor))[1] && abcd[2]==((int*)(vendor))[2]; + return abcd[1]==(reinterpret_cast(vendor))[0] && abcd[3]==(reinterpret_cast(vendor))[1] && abcd[2]==(reinterpret_cast(vendor))[2]; } inline void queryCacheSizes_intel_direct(int& l1, int& l2, int& l3) @@ -932,4 +947,6 @@ inline int queryTopLevelCacheSize() } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_MEMORY_H diff --git a/extern/Eigen3/Eigen/src/Core/util/Meta.h b/extern/Eigen3/Eigen/src/Core/util/Meta.h index 4518261efef..a5f31164d15 100644 --- a/extern/Eigen3/Eigen/src/Core/util/Meta.h +++ b/extern/Eigen3/Eigen/src/Core/util/Meta.h @@ -4,28 +4,15 @@ // Copyright (C) 2008-2009 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_META_H #define EIGEN_META_H +namespace Eigen { + namespace internal { /** \internal @@ -80,8 +67,6 @@ template<> struct is_arithmetic { enum { value = true }; }; template<> struct is_arithmetic { enum { value = true }; }; template<> struct is_arithmetic { enum { value = true }; }; template<> struct is_arithmetic { enum { value = true }; }; -template<> struct is_arithmetic { enum { value = true }; }; -template<> struct is_arithmetic { enum { value = true }; }; template struct add_const { typedef const T type; }; template struct add_const { typedef T& type; }; @@ -103,6 +88,21 @@ template struct enable_if; template struct enable_if { typedef T type; }; + + +/** \internal + * A base class do disable default copy ctor and copy assignement operator. + */ +class noncopyable +{ + noncopyable(const noncopyable&); + const noncopyable& operator=(const noncopyable&); +protected: + noncopyable() {} + ~noncopyable() {} +}; + + /** \internal * Convenient struct to get the result type of a unary or binary functor. * @@ -226,4 +226,6 @@ template struct is_diagonal > } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_META_H diff --git a/extern/Eigen3/Eigen/src/Core/util/NonMPL2.h b/extern/Eigen3/Eigen/src/Core/util/NonMPL2.h new file mode 100644 index 00000000000..1af67cf18c7 --- /dev/null +++ b/extern/Eigen3/Eigen/src/Core/util/NonMPL2.h @@ -0,0 +1,3 @@ +#ifdef EIGEN_MPL2_ONLY +#error Including non-MPL2 code in EIGEN_MPL2_ONLY mode +#endif diff --git a/extern/Eigen3/Eigen/src/Core/util/StaticAssert.h b/extern/Eigen3/Eigen/src/Core/util/StaticAssert.h index 99c7c9972f0..b46a75b3783 100644 --- a/extern/Eigen3/Eigen/src/Core/util/StaticAssert.h +++ b/extern/Eigen3/Eigen/src/Core/util/StaticAssert.h @@ -4,24 +4,9 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_STATIC_ASSERT_H #define EIGEN_STATIC_ASSERT_H @@ -48,6 +33,8 @@ #else // not CXX0X + namespace Eigen { + namespace internal { template @@ -70,6 +57,7 @@ YOU_CALLED_A_DYNAMIC_SIZE_METHOD_ON_A_FIXED_SIZE_MATRIX_OR_VECTOR, UNALIGNED_LOAD_AND_STORE_OPERATIONS_UNIMPLEMENTED_ON_ALTIVEC, THIS_FUNCTION_IS_NOT_FOR_INTEGER_NUMERIC_TYPES, + FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED, NUMERIC_TYPE_MUST_BE_REAL, COEFFICIENT_WRITE_ACCESS_TO_SELFADJOINT_NOT_SUPPORTED, WRITING_TO_TRIANGULAR_PART_WITH_UNIT_DIAGONAL_IS_NOT_SUPPORTED, @@ -95,12 +83,20 @@ YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION, THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY, YOU_ARE_TRYING_TO_USE_AN_INDEX_BASED_ACCESSOR_ON_AN_EXPRESSION_THAT_DOES_NOT_SUPPORT_THAT, - THIS_METHOD_IS_ONLY_FOR_1x1_EXPRESSIONS + THIS_METHOD_IS_ONLY_FOR_1x1_EXPRESSIONS, + THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL, + THIS_METHOD_IS_ONLY_FOR_ARRAYS_NOT_MATRICES, + YOU_PASSED_A_ROW_VECTOR_BUT_A_COLUMN_VECTOR_WAS_EXPECTED, + YOU_PASSED_A_COLUMN_VECTOR_BUT_A_ROW_VECTOR_WAS_EXPECTED, + THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE, + THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH }; }; } // end namespace internal + } // end namespace Eigen + // Specialized implementation for MSVC to avoid "conditional // expression is constant" warnings. This implementation doesn't // appear to work under GCC, hence the multiple implementations. @@ -195,4 +191,15 @@ EIGEN_STATIC_ASSERT(internal::is_lvalue::value, \ THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY) +#define EIGEN_STATIC_ASSERT_ARRAYXPR(Derived) \ + EIGEN_STATIC_ASSERT((internal::is_same::XprKind, ArrayXpr>::value), \ + THIS_METHOD_IS_ONLY_FOR_ARRAYS_NOT_MATRICES) + +#define EIGEN_STATIC_ASSERT_SAME_XPR_KIND(Derived1, Derived2) \ + EIGEN_STATIC_ASSERT((internal::is_same::XprKind, \ + typename internal::traits::XprKind \ + >::value), \ + YOU_CANNOT_MIX_ARRAYS_AND_MATRICES) + + #endif // EIGEN_STATIC_ASSERT_H diff --git a/extern/Eigen3/Eigen/src/Core/util/XprHelper.h b/extern/Eigen3/Eigen/src/Core/util/XprHelper.h index c2078f13786..2a65c7cbfa4 100644 --- a/extern/Eigen3/Eigen/src/Core/util/XprHelper.h +++ b/extern/Eigen3/Eigen/src/Core/util/XprHelper.h @@ -4,24 +4,9 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_XPRHELPER_H #define EIGEN_XPRHELPER_H @@ -37,6 +22,8 @@ #define EIGEN_EMPTY_STRUCT_CTOR(X) #endif +namespace Eigen { + typedef EIGEN_DEFAULT_DENSE_INDEX_TYPE DenseIndex; namespace internal { @@ -260,30 +247,27 @@ template struct plain_matrix_type_row_major // we should be able to get rid of this one too template struct must_nest_by_value { enum { ret = false }; }; -template -struct is_reference -{ - enum { ret = false }; -}; - -template -struct is_reference -{ - enum { ret = true }; -}; - -/** -* \internal The reference selector for template expressions. The idea is that we don't -* need to use references for expressions since they are light weight proxy -* objects which should generate no copying overhead. -**/ +/** \internal The reference selector for template expressions. The idea is that we don't + * need to use references for expressions since they are light weight proxy + * objects which should generate no copying overhead. */ template struct ref_selector { typedef typename conditional< bool(traits::Flags & NestByRefBit), T const&, - T + const T + >::type type; +}; + +/** \internal Adds the const qualifier on the value-type of T2 if and only if T1 is a const type */ +template +struct transfer_constness +{ + typedef typename conditional< + bool(internal::is_const::value), + typename internal::add_const_on_value_type::type, + T2 >::type type; }; @@ -297,6 +281,8 @@ struct ref_selector * \param T the type of the expression being nested * \param n the number of coefficient accesses in the nested expression for each coefficient access in the bigger expression. * + * Note that if no evaluation occur, then the constness of T is preserved. + * * Example. Suppose that a, b, and c are of type Matrix3d. The user forms the expression a*(b+c). * b+c is an expression "sum of matrices", which we will denote by S. In order to determine how to nest it, * the Product expression uses: nested::ret, which turns out to be Matrix3d because the internal logic of @@ -456,4 +442,6 @@ struct is_lvalue } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_XPRHELPER_H diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Block.h b/extern/Eigen3/Eigen/src/Eigen2Support/Block.h index bc28051e017..604456f40e7 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/Block.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/Block.h @@ -4,28 +4,15 @@ // Copyright (C) 2008-2009 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_BLOCK2_H #define EIGEN_BLOCK2_H +namespace Eigen { + /** \returns a dynamic-size expression of a corner of *this. * * \param type the type of corner. Can be \a Eigen::TopLeft, \a Eigen::TopRight, @@ -134,4 +121,6 @@ DenseBase::corner(CornerType type) const } } +} // end namespace Eigen + #endif // EIGEN_BLOCK2_H diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Cwise.h b/extern/Eigen3/Eigen/src/Eigen2Support/Cwise.h index 2dc83b6a7dd..d95009b6e29 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/Cwise.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/Cwise.h @@ -4,28 +4,15 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_CWISE_H #define EIGEN_CWISE_H +namespace Eigen { + /** \internal * convenient macro to defined the return type of a cwise binary operation */ #define EIGEN_CWISE_BINOP_RETURN_TYPE(OP) \ @@ -200,4 +187,6 @@ inline Cwise MatrixBase::cwise() return derived(); } +} // end namespace Eigen + #endif // EIGEN_CWISE_H diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/CwiseOperators.h b/extern/Eigen3/Eigen/src/Eigen2Support/CwiseOperators.h index 9c28559c329..482f3064856 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/CwiseOperators.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/CwiseOperators.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_ARRAY_CWISE_OPERATORS_H #define EIGEN_ARRAY_CWISE_OPERATORS_H +namespace Eigen { + /*************************************************************************** * The following functions were defined in Core ***************************************************************************/ @@ -306,4 +293,6 @@ inline ExpressionType& Cwise::operator-=(const Scalar& scalar) return m_matrix.const_cast_derived() = *this - scalar; } +} // end namespace Eigen + #endif // EIGEN_ARRAY_CWISE_OPERATORS_H diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AlignedBox.h b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AlignedBox.h index 78df29d408a..5c928e8fc2d 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AlignedBox.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/AlignedBox.h @@ -3,27 +3,14 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. // no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway +namespace Eigen { + /** \geometry_module \ingroup Geometry_Module * \nonstableyet * @@ -63,7 +50,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim== ~AlignedBox() {} /** \returns the dimension in which the box holds */ - inline int dim() const { return AmbientDimAtCompileTime==Dynamic ? m_min.size()-1 : int(AmbientDimAtCompileTime); } + inline int dim() const { return AmbientDimAtCompileTime==Dynamic ? m_min.size()-1 : AmbientDimAtCompileTime; } /** \returns true if the box is null, i.e, empty. */ inline bool isNull() const { return (m_min.cwise() > m_max).any(); } @@ -157,14 +144,16 @@ protected: template inline Scalar AlignedBox::squaredExteriorDistance(const VectorType& p) const { - Scalar dist2 = 0.; + Scalar dist2(0); Scalar aux; for (int k=0; k // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. // no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway +namespace Eigen { /** \geometry_module \ingroup Geometry_Module * @@ -224,3 +210,5 @@ AngleAxis::toRotationMatrix(void) const return res; } + +} // end namespace Eigen diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Hyperplane.h b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Hyperplane.h index 81c4f55b173..19cc1bfd883 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Hyperplane.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Hyperplane.h @@ -4,27 +4,14 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. // no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway +namespace Eigen { + /** \geometry_module \ingroup Geometry_Module * * \class Hyperplane @@ -263,3 +250,5 @@ protected: Coefficients m_coeffs; }; + +} // end namespace Eigen diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h index 411c4b57079..6e4a168a8cd 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/ParametrizedLine.h @@ -4,27 +4,13 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. // no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway +namespace Eigen { /** \geometry_module \ingroup Geometry_Module * @@ -151,3 +137,5 @@ inline _Scalar ParametrizedLine<_Scalar, _AmbientDim>::intersection(const Hyperp return -(hyperplane.offset()+origin().eigen2_dot(hyperplane.normal())) /(direction().eigen2_dot(hyperplane.normal())); } + +} // end namespace Eigen diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Quaternion.h b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Quaternion.h index a75fa42aeac..ec87da054d6 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Quaternion.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Quaternion.h @@ -3,27 +3,14 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. // no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway +namespace Eigen { + template @@ -143,7 +130,7 @@ public: /** \returns a quaternion representing an identity rotation * \sa MatrixBase::Identity() */ - inline static Quaternion Identity() { return Quaternion(1, 0, 0, 0); } + static inline Quaternion Identity() { return Quaternion(1, 0, 0, 0); } /** \sa Quaternion::Identity(), MatrixBase::setIdentity() */ @@ -314,9 +301,9 @@ Quaternion::toRotationMatrix(void) const // it has to be inlined, and so the return by value is not an issue Matrix3 res; - const Scalar tx = 2*this->x(); - const Scalar ty = 2*this->y(); - const Scalar tz = 2*this->z(); + const Scalar tx = Scalar(2)*this->x(); + const Scalar ty = Scalar(2)*this->y(); + const Scalar tz = Scalar(2)*this->z(); const Scalar twx = tx*this->w(); const Scalar twy = ty*this->w(); const Scalar twz = tz*this->w(); @@ -327,15 +314,15 @@ Quaternion::toRotationMatrix(void) const const Scalar tyz = tz*this->y(); const Scalar tzz = tz*this->z(); - res.coeffRef(0,0) = 1-(tyy+tzz); + res.coeffRef(0,0) = Scalar(1)-(tyy+tzz); res.coeffRef(0,1) = txy-twz; res.coeffRef(0,2) = txz+twy; res.coeffRef(1,0) = txy+twz; - res.coeffRef(1,1) = 1-(txx+tzz); + res.coeffRef(1,1) = Scalar(1)-(txx+tzz); res.coeffRef(1,2) = tyz-twx; res.coeffRef(2,0) = txz-twy; res.coeffRef(2,1) = tyz+twx; - res.coeffRef(2,2) = 1-(txx+tyy); + res.coeffRef(2,2) = Scalar(1)-(txx+tyy); return res; } @@ -460,7 +447,7 @@ template struct ei_quaternion_assign_impl { typedef typename Other::Scalar Scalar; - inline static void run(Quaternion& q, const Other& mat) + static inline void run(Quaternion& q, const Other& mat) { // This algorithm comes from "Quaternion Calculus and Fast Animation", // Ken Shoemake, 1987 SIGGRAPH course notes @@ -499,8 +486,10 @@ template struct ei_quaternion_assign_impl { typedef typename Other::Scalar Scalar; - inline static void run(Quaternion& q, const Other& vec) + static inline void run(Quaternion& q, const Other& vec) { q.coeffs() = vec; } }; + +} // end namespace Eigen diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Rotation2D.h b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Rotation2D.h index ee7c80e7eaa..3e02b7a4fd1 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Rotation2D.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Rotation2D.h @@ -3,27 +3,13 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. // no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway +namespace Eigen { /** \geometry_module \ingroup Geometry_Module * @@ -155,3 +141,5 @@ Rotation2D::toRotationMatrix(void) const Scalar cosA = ei_cos(m_angle); return (Matrix2() << cosA, -sinA, sinA, cosA).finished(); } + +} // end namespace Eigen diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/RotationBase.h b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/RotationBase.h index 2f494f198bd..78ad73b60ad 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/RotationBase.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/RotationBase.h @@ -3,27 +3,14 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. // no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway +namespace Eigen { + // this file aims to contains the various representations of rotation/orientation // in 2D and 3D space excepted Matrix and Quaternion. @@ -113,22 +100,24 @@ Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols> * \sa class Transform, class Rotation2D, class Quaternion, class AngleAxis */ template -inline static Matrix ei_toRotationMatrix(const Scalar& s) +static inline Matrix ei_toRotationMatrix(const Scalar& s) { EIGEN_STATIC_ASSERT(Dim==2,YOU_MADE_A_PROGRAMMING_MISTAKE) return Rotation2D(s).toRotationMatrix(); } template -inline static Matrix ei_toRotationMatrix(const RotationBase& r) +static inline Matrix ei_toRotationMatrix(const RotationBase& r) { return r.toRotationMatrix(); } template -inline static const MatrixBase& ei_toRotationMatrix(const MatrixBase& mat) +static inline const MatrixBase& ei_toRotationMatrix(const MatrixBase& mat) { EIGEN_STATIC_ASSERT(OtherDerived::RowsAtCompileTime==Dim && OtherDerived::ColsAtCompileTime==Dim, YOU_MADE_A_PROGRAMMING_MISTAKE) return mat; } + +} // end namespace Eigen diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Scaling.h b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Scaling.h index 108e6d7d58f..a07c1c7c762 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Scaling.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Scaling.h @@ -3,27 +3,13 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. // no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway +namespace Eigen { /** \geometry_module \ingroup Geometry_Module * @@ -177,3 +163,5 @@ Scaling::operator* (const TransformType& t) const res.prescale(m_coeffs); return res; } + +} // end namespace Eigen diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Transform.h b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Transform.h index 88956c86c73..dceb8020383 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Transform.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Transform.h @@ -4,27 +4,13 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2009 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. // no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway +namespace Eigen { // Note that we have to pass Dim and HDim because it is not allowed to use a template // parameter to define a template specialization. To be more precise, in the following @@ -796,3 +782,5 @@ struct ei_transform_product_impl { return ((tr.linear() * other) + tr.translation()) * (Scalar(1) / ( (tr.matrix().template block<1,Dim>(Dim,0) * other).coeff(0) + tr.matrix().coeff(Dim,Dim))); } }; + +} // end namespace Eigen diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Translation.h b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Translation.h index e651e310212..0fb9a9f9a5a 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Translation.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/Geometry/Translation.h @@ -3,27 +3,13 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. // no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway +namespace Eigen { /** \geometry_module \ingroup Geometry_Module * @@ -194,3 +180,5 @@ Translation::operator* (const TransformType& t) const res.pretranslate(m_coeffs); return res; } + +} // end namespace Eigen diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/LU.h b/extern/Eigen3/Eigen/src/Eigen2Support/LU.h index c23c11baa72..49f19ad76e3 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/LU.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/LU.h @@ -3,28 +3,15 @@ // // Copyright (C) 2011 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN2_LU_H #define EIGEN2_LU_H +namespace Eigen { + template class LU : public FullPivLU { @@ -57,7 +44,6 @@ class LU : public FullPivLU > ImageResultType; typedef FullPivLU Base; - LU() : Base() {} template explicit LU(const T& t) : Base(t), m_originalMatrix(t) {} @@ -129,5 +115,6 @@ MatrixBase::eigen2_lu() const } #endif +} // end namespace Eigen #endif // EIGEN2_LU_H diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Lazy.h b/extern/Eigen3/Eigen/src/Eigen2Support/Lazy.h index c4288ede2ef..593fc78e6de 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/Lazy.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/Lazy.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_LAZY_H #define EIGEN_LAZY_H +namespace Eigen { + /** \deprecated it is only used by lazy() which is deprecated * * \returns an expression of *this with added flags @@ -79,4 +66,6 @@ Derived& MatrixBase::operator-=(const Flagged // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN2_LEASTSQUARES_H #define EIGEN2_LEASTSQUARES_H +namespace Eigen { + /** \ingroup LeastSquares_Module * * \leastsquares_module @@ -178,5 +165,6 @@ void fitHyperplane(int numPoints, result->offset() = - (result->normal().cwise()* mean).sum(); } +} // end namespace Eigen #endif // EIGEN2_LEASTSQUARES_H diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Macros.h b/extern/Eigen3/Eigen/src/Eigen2Support/Macros.h index 77e85a41e3d..351c32afb60 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/Macros.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/Macros.h @@ -3,24 +3,9 @@ // // Copyright (C) 2011 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN2_MACROS_H #define EIGEN2_MACROS_H diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/MathFunctions.h b/extern/Eigen3/Eigen/src/Eigen2Support/MathFunctions.h index caa44e63f32..3a8a9ca8146 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/MathFunctions.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/MathFunctions.h @@ -3,28 +3,15 @@ // // Copyright (C) 2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN2_MATH_FUNCTIONS_H #define EIGEN2_MATH_FUNCTIONS_H +namespace Eigen { + template inline typename NumTraits::Real ei_real(const T& x) { return internal::real(x); } template inline typename NumTraits::Real ei_imag(const T& x) { return internal::imag(x); } template inline T ei_conj(const T& x) { return internal::conj(x); } @@ -65,4 +52,6 @@ inline bool ei_isApproxOrLessThan(const Scalar& x, const Scalar& y, return internal::isApproxOrLessThan(x, y, precision); } +} // end namespace Eigen + #endif // EIGEN2_MATH_FUNCTIONS_H diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Memory.h b/extern/Eigen3/Eigen/src/Eigen2Support/Memory.h index 0283475419e..f86372b6b56 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/Memory.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/Memory.h @@ -3,28 +3,15 @@ // // Copyright (C) 2011 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN2_MEMORY_H #define EIGEN2_MEMORY_H +namespace Eigen { + inline void* ei_aligned_malloc(size_t size) { return internal::aligned_malloc(size); } inline void ei_aligned_free(void *ptr) { internal::aligned_free(ptr); } inline void* ei_aligned_realloc(void *ptr, size_t new_size, size_t old_size) { return internal::aligned_realloc(ptr, new_size, old_size); } @@ -53,6 +40,6 @@ template inline void ei_aligned_delete(T *ptr, size_t size) return internal::aligned_delete(ptr, size); } - +} // end namespace Eigen #endif // EIGEN2_MACROS_H diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Meta.h b/extern/Eigen3/Eigen/src/Eigen2Support/Meta.h index 6e500b79a2e..fa37cfc961e 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/Meta.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/Meta.h @@ -3,28 +3,15 @@ // // Copyright (C) 2011 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN2_META_H #define EIGEN2_META_H +namespace Eigen { + template struct ei_traits : internal::traits {}; @@ -83,4 +70,6 @@ class ei_meta_sqrt template class ei_meta_sqrt { public: enum { ret = (SupX*SupX <= Y) ? SupX : InfX }; }; +} // end namespace Eigen + #endif // EIGEN2_META_H diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/Minor.h b/extern/Eigen3/Eigen/src/Eigen2Support/Minor.h index eda91cc32be..4cded5734fa 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/Minor.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/Minor.h @@ -3,28 +3,15 @@ // // Copyright (C) 2006-2009 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_MINOR_H #define EIGEN_MINOR_H +namespace Eigen { + /** * \class Minor * @@ -125,4 +112,6 @@ MatrixBase::minor(Index row, Index col) const return Minor(derived(), row, col); } +} // end namespace Eigen + #endif // EIGEN_MINOR_H diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/QR.h b/extern/Eigen3/Eigen/src/Eigen2Support/QR.h index 64f5d5ccb30..2042c98510a 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/QR.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/QR.h @@ -4,28 +4,15 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2011 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN2_QR_H #define EIGEN2_QR_H +namespace Eigen { + template class QR : public HouseholderQR { @@ -75,5 +62,6 @@ MatrixBase::qr() const return QR(eval()); } +} // end namespace Eigen #endif // EIGEN2_QR_H diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/SVD.h b/extern/Eigen3/Eigen/src/Eigen2Support/SVD.h index 16b4b488f0c..3d2eeb44586 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/SVD.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/SVD.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN2_SVD_H #define EIGEN2_SVD_H +namespace Eigen { + /** \ingroup SVD_Module * \nonstableyet * @@ -390,7 +377,7 @@ void SVD::compute(const MatrixType& matrix) Scalar ek = e[k]/scale; Scalar b = ((spm1 + sp)*(spm1 - sp) + epm1*epm1)/Scalar(2); Scalar c = (sp*epm1)*(sp*epm1); - Scalar shift = 0.0; + Scalar shift(0); if ((b != 0.0) || (c != 0.0)) { shift = ei_sqrt(b*b + c); @@ -646,4 +633,6 @@ MatrixBase::svd() const return SVD(derived()); } +} // end namespace Eigen + #endif // EIGEN2_SVD_H diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/TriangularSolver.h b/extern/Eigen3/Eigen/src/Eigen2Support/TriangularSolver.h index e94e47a5093..ebbeb3b4958 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/TriangularSolver.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/TriangularSolver.h @@ -3,28 +3,15 @@ // // Copyright (C) 2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_TRIANGULAR_SOLVER2_H #define EIGEN_TRIANGULAR_SOLVER2_H +namespace Eigen { + const unsigned int UnitDiagBit = UnitDiag; const unsigned int SelfAdjointBit = SelfAdjoint; const unsigned int UpperTriangularBit = Upper; @@ -49,5 +36,7 @@ void Flagged::solveTriangularInPlace(const MatrixB { m_matrix.template triangularView().solveInPlace(other.derived()); } + +} // end namespace Eigen #endif // EIGEN_TRIANGULAR_SOLVER2_H diff --git a/extern/Eigen3/Eigen/src/Eigen2Support/VectorBlock.h b/extern/Eigen3/Eigen/src/Eigen2Support/VectorBlock.h index 010031d1971..71a8080a9fc 100644 --- a/extern/Eigen3/Eigen/src/Eigen2Support/VectorBlock.h +++ b/extern/Eigen3/Eigen/src/Eigen2Support/VectorBlock.h @@ -4,28 +4,15 @@ // Copyright (C) 2008-2009 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN2_VECTORBLOCK_H #define EIGEN2_VECTORBLOCK_H +namespace Eigen { + /** \deprecated use DenseMase::head(Index) */ template inline VectorBlock @@ -102,4 +89,6 @@ MatrixBase::end() const return VectorBlock(derived(), size() - Size); } +} // end namespace Eigen + #endif // EIGEN2_VECTORBLOCK_H diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h b/extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h index 57e00227d72..c4b8a308cee 100644 --- a/extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h +++ b/extern/Eigen3/Eigen/src/Eigenvalues/ComplexEigenSolver.h @@ -5,31 +5,17 @@ // Copyright (C) 2009 Gael Guennebaud // Copyright (C) 2010 Jitse Niesen // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_COMPLEX_EIGEN_SOLVER_H #define EIGEN_COMPLEX_EIGEN_SOLVER_H -#include "./EigenvaluesCommon.h" #include "./ComplexSchur.h" +namespace Eigen { + /** \eigenvalues_module \ingroup Eigenvalues_Module * * @@ -328,5 +314,6 @@ void ComplexEigenSolver::sortEigenvalues(bool computeEigenvectors) } } +} // end namespace Eigen #endif // EIGEN_COMPLEX_EIGEN_SOLVER_H diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur.h b/extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur.h index ec93af2e58a..16a9a03d219 100644 --- a/extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur.h +++ b/extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur.h @@ -5,31 +5,17 @@ // Copyright (C) 2009 Gael Guennebaud // Copyright (C) 2010 Jitse Niesen // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_COMPLEX_SCHUR_H #define EIGEN_COMPLEX_SCHUR_H -#include "./EigenvaluesCommon.h" #include "./HessenbergDecomposition.h" +namespace Eigen { + namespace internal { template struct complex_schur_reduce_to_hessenberg; } @@ -227,46 +213,6 @@ template class ComplexSchur friend struct internal::complex_schur_reduce_to_hessenberg::IsComplex>; }; -namespace internal { - -/** Computes the principal value of the square root of the complex \a z. */ -template -std::complex sqrt(const std::complex &z) -{ - RealScalar t, tre, tim; - - t = abs(z); - - if (abs(real(z)) <= abs(imag(z))) - { - // No cancellation in these formulas - tre = sqrt(RealScalar(0.5)*(t + real(z))); - tim = sqrt(RealScalar(0.5)*(t - real(z))); - } - else - { - // Stable computation of the above formulas - if (z.real() > RealScalar(0)) - { - tre = t + z.real(); - tim = abs(imag(z))*sqrt(RealScalar(0.5)/tre); - tre = sqrt(RealScalar(0.5)*tre); - } - else - { - tim = t - z.real(); - tre = abs(imag(z))*sqrt(RealScalar(0.5)/tim); - tim = sqrt(RealScalar(0.5)*tim); - } - } - if(z.imag() < RealScalar(0)) - tim = -tim; - - return (std::complex(tre,tim)); -} -} // end namespace internal - - /** If m_matT(i+1,i) is neglegible in floating point arithmetic * compared to m_matT(i,i) and m_matT(j,j), then set it to zero and * return true, else return false. */ @@ -302,7 +248,7 @@ typename ComplexSchur::ComplexScalar ComplexSchur::compu ComplexScalar b = t.coeff(0,1) * t.coeff(1,0); ComplexScalar c = t.coeff(0,0) - t.coeff(1,1); - ComplexScalar disc = internal::sqrt(c*c + RealScalar(4)*b); + ComplexScalar disc = sqrt(c*c + RealScalar(4)*b); ComplexScalar det = t.coeff(0,0) * t.coeff(1,1) - b; ComplexScalar trace = t.coeff(0,0) + t.coeff(1,1); ComplexScalar eival1 = (trace + disc) / RealScalar(2); @@ -406,7 +352,7 @@ void ComplexSchur::reduceToTriangularForm(bool computeU) // if we spent too many iterations on the current element, we give up iter++; - if(iter > m_maxIterations) break; + if(iter > m_maxIterations * m_matT.cols()) break; // find il, the top row of the active submatrix il = iu-1; @@ -436,7 +382,7 @@ void ComplexSchur::reduceToTriangularForm(bool computeU) } } - if(iter <= m_maxIterations) + if(iter <= m_maxIterations * m_matT.cols()) m_info = Success; else m_info = NoConvergence; @@ -445,4 +391,6 @@ void ComplexSchur::reduceToTriangularForm(bool computeU) m_matUisUptodate = computeU; } +} // end namespace Eigen + #endif // EIGEN_COMPLEX_SCHUR_H diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur_MKL.h b/extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur_MKL.h new file mode 100644 index 00000000000..aa18e696352 --- /dev/null +++ b/extern/Eigen3/Eigen/src/Eigenvalues/ComplexSchur_MKL.h @@ -0,0 +1,94 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + 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 Intel Corporation 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. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL + * Complex Schur needed to complex unsymmetrical eigenvalues/eigenvectors. + ******************************************************************************** +*/ + +#ifndef EIGEN_COMPLEX_SCHUR_MKL_H +#define EIGEN_COMPLEX_SCHUR_MKL_H + +#include "Eigen/src/Core/util/MKL_support.h" + +namespace Eigen { + +/** \internal Specialization for the data types supported by MKL */ + +#define EIGEN_MKL_SCHUR_COMPLEX(EIGTYPE, MKLTYPE, MKLPREFIX, MKLPREFIX_U, EIGCOLROW, MKLCOLROW) \ +template<> inline\ +ComplexSchur >& \ +ComplexSchur >::compute(const Matrix& matrix, bool computeU) \ +{ \ + typedef Matrix MatrixType; \ + typedef MatrixType::Scalar Scalar; \ + typedef MatrixType::RealScalar RealScalar; \ + typedef std::complex ComplexScalar; \ +\ + assert(matrix.cols() == matrix.rows()); \ +\ + m_matUisUptodate = false; \ + if(matrix.cols() == 1) \ + { \ + m_matT = matrix.cast(); \ + if(computeU) m_matU = ComplexMatrixType::Identity(1,1); \ + m_info = Success; \ + m_isInitialized = true; \ + m_matUisUptodate = computeU; \ + return *this; \ + } \ + lapack_int n = matrix.cols(), sdim, info; \ + lapack_int lda = matrix.outerStride(); \ + lapack_int matrix_order = MKLCOLROW; \ + char jobvs, sort='N'; \ + LAPACK_##MKLPREFIX_U##_SELECT1 select = 0; \ + jobvs = (computeU) ? 'V' : 'N'; \ + m_matU.resize(n, n); \ + lapack_int ldvs = m_matU.outerStride(); \ + m_matT = matrix; \ + Matrix w; \ + w.resize(n, 1);\ + info = LAPACKE_##MKLPREFIX##gees( matrix_order, jobvs, sort, select, n, (MKLTYPE*)m_matT.data(), lda, &sdim, (MKLTYPE*)w.data(), (MKLTYPE*)m_matU.data(), ldvs ); \ + if(info == 0) \ + m_info = Success; \ + else \ + m_info = NoConvergence; \ +\ + m_isInitialized = true; \ + m_matUisUptodate = computeU; \ + return *this; \ +\ +} + +EIGEN_MKL_SCHUR_COMPLEX(dcomplex, MKL_Complex16, z, Z, ColMajor, LAPACK_COL_MAJOR) +EIGEN_MKL_SCHUR_COMPLEX(scomplex, MKL_Complex8, c, C, ColMajor, LAPACK_COL_MAJOR) +EIGEN_MKL_SCHUR_COMPLEX(dcomplex, MKL_Complex16, z, Z, RowMajor, LAPACK_ROW_MAJOR) +EIGEN_MKL_SCHUR_COMPLEX(scomplex, MKL_Complex8, c, C, RowMajor, LAPACK_ROW_MAJOR) + +} // end namespace Eigen + +#endif // EIGEN_COMPLEX_SCHUR_MKL_H diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h b/extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h index f57353c065f..c16ff2b74e2 100644 --- a/extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h +++ b/extern/Eigen3/Eigen/src/Eigenvalues/EigenSolver.h @@ -4,31 +4,17 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2010 Jitse Niesen // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_EIGENSOLVER_H #define EIGEN_EIGENSOLVER_H -#include "./EigenvaluesCommon.h" #include "./RealSchur.h" +namespace Eigen { + /** \eigenvalues_module \ingroup Eigenvalues_Module * * @@ -432,7 +418,7 @@ void EigenSolver::doComputeEigenvectors() const Scalar eps = NumTraits::epsilon(); // inefficient! this is already computed in RealSchur - Scalar norm = 0.0; + Scalar norm(0); for (Index j = 0; j < size; ++j) { norm += m_matT.row(j).segment((std::max)(j-1,Index(0)), size-(std::max)(j-1,Index(0))).cwiseAbs().sum(); @@ -452,7 +438,7 @@ void EigenSolver::doComputeEigenvectors() // Scalar vector if (q == Scalar(0)) { - Scalar lastr=0, lastw=0; + Scalar lastr(0), lastw(0); Index l = n; m_matT.coeffRef(n,n) = 1.0; @@ -498,7 +484,7 @@ void EigenSolver::doComputeEigenvectors() } else if (q < Scalar(0) && n > 0) // Complex vector { - Scalar lastra=0, lastsa=0, lastw=0; + Scalar lastra(0), lastsa(0), lastw(0); Index l = n-1; // Last vector component imaginary so matrix is triangular @@ -588,4 +574,6 @@ void EigenSolver::doComputeEigenvectors() } } +} // end namespace Eigen + #endif // EIGEN_EIGENSOLVER_H diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/EigenvaluesCommon.h b/extern/Eigen3/Eigen/src/Eigenvalues/EigenvaluesCommon.h deleted file mode 100644 index 749bea79500..00000000000 --- a/extern/Eigen3/Eigen/src/Eigenvalues/EigenvaluesCommon.h +++ /dev/null @@ -1,31 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2010 Jitse Niesen -// -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . - -#ifndef EIGEN_EIGENVALUES_COMMON_H -#define EIGEN_EIGENVALUES_COMMON_H - - - -#endif // EIGEN_EIGENVALUES_COMMON_H - diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h b/extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h index 980af14ce71..07bf1ea0956 100644 --- a/extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h +++ b/extern/Eigen3/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h @@ -4,31 +4,17 @@ // Copyright (C) 2008-2010 Gael Guennebaud // Copyright (C) 2010 Jitse Niesen // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_GENERALIZEDSELFADJOINTEIGENSOLVER_H #define EIGEN_GENERALIZEDSELFADJOINTEIGENSOLVER_H -#include "./EigenvaluesCommon.h" #include "./Tridiagonalization.h" +namespace Eigen { + /** \eigenvalues_module \ingroup Eigenvalues_Module * * @@ -236,4 +222,6 @@ compute(const MatrixType& matA, const MatrixType& matB, int options) return *this; } +} // end namespace Eigen + #endif // EIGEN_GENERALIZEDSELFADJOINTEIGENSOLVER_H diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h b/extern/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h index c17f155a59b..b8378b08a09 100644 --- a/extern/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h +++ b/extern/Eigen3/Eigen/src/Eigenvalues/HessenbergDecomposition.h @@ -4,28 +4,15 @@ // Copyright (C) 2008-2009 Gael Guennebaud // Copyright (C) 2010 Jitse Niesen // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_HESSENBERGDECOMPOSITION_H #define EIGEN_HESSENBERGDECOMPOSITION_H +namespace Eigen { + namespace internal { template struct HessenbergDecompositionMatrixHReturnType; @@ -379,6 +366,8 @@ template struct HessenbergDecompositionMatrixHReturnType const HessenbergDecomposition& m_hess; }; -} +} // end namespace internal + +} // end namespace Eigen #endif // EIGEN_HESSENBERGDECOMPOSITION_H diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h b/extern/Eigen3/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h index 5591519fb75..6af481c75f6 100644 --- a/extern/Eigen3/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h +++ b/extern/Eigen3/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h @@ -4,28 +4,15 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2010 Jitse Niesen // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_MATRIXBASEEIGENVALUES_H #define EIGEN_MATRIXBASEEIGENVALUES_H +namespace Eigen { + namespace internal { template @@ -167,4 +154,6 @@ SelfAdjointView::operatorNorm() const return eigenvalues().cwiseAbs().maxCoeff(); } +} // end namespace Eigen + #endif diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h b/extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h index cc9af11c117..781692eccd3 100644 --- a/extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h +++ b/extern/Eigen3/Eigen/src/Eigenvalues/RealSchur.h @@ -4,31 +4,17 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2010 Jitse Niesen // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_REAL_SCHUR_H #define EIGEN_REAL_SCHUR_H -#include "./EigenvaluesCommon.h" #include "./HessenbergDecomposition.h" +namespace Eigen { + /** \eigenvalues_module \ingroup Eigenvalues_Module * * @@ -235,42 +221,44 @@ RealSchur& RealSchur::compute(const MatrixType& matrix, // Rows iu+1,...,end are already brought in triangular form. Index iu = m_matT.cols() - 1; Index iter = 0; // iteration count - Scalar exshift = 0.0; // sum of exceptional shifts + Scalar exshift(0); // sum of exceptional shifts Scalar norm = computeNormOfT(); - while (iu >= 0) + if(norm!=0) { - Index il = findSmallSubdiagEntry(iu, norm); + while (iu >= 0) + { + Index il = findSmallSubdiagEntry(iu, norm); - // Check for convergence - if (il == iu) // One root found - { - m_matT.coeffRef(iu,iu) = m_matT.coeff(iu,iu) + exshift; - if (iu > 0) - m_matT.coeffRef(iu, iu-1) = Scalar(0); - iu--; - iter = 0; + // Check for convergence + if (il == iu) // One root found + { + m_matT.coeffRef(iu,iu) = m_matT.coeff(iu,iu) + exshift; + if (iu > 0) + m_matT.coeffRef(iu, iu-1) = Scalar(0); + iu--; + iter = 0; + } + else if (il == iu-1) // Two roots found + { + splitOffTwoRows(iu, computeU, exshift); + iu -= 2; + iter = 0; + } + else // No convergence yet + { + // The firstHouseholderVector vector has to be initialized to something to get rid of a silly GCC warning (-O1 -Wall -DNDEBUG ) + Vector3s firstHouseholderVector(0,0,0), shiftInfo; + computeShift(iu, iter, exshift, shiftInfo); + iter = iter + 1; + if (iter > m_maxIterations * m_matT.cols()) break; + Index im; + initFrancisQRStep(il, iu, shiftInfo, im, firstHouseholderVector); + performFrancisQRStep(il, im, iu, computeU, firstHouseholderVector, workspace); + } } - else if (il == iu-1) // Two roots found - { - splitOffTwoRows(iu, computeU, exshift); - iu -= 2; - iter = 0; - } - else // No convergence yet - { - // The firstHouseholderVector vector has to be initialized to something to get rid of a silly GCC warning (-O1 -Wall -DNDEBUG ) - Vector3s firstHouseholderVector(0,0,0), shiftInfo; - computeShift(iu, iter, exshift, shiftInfo); - iter = iter + 1; - if (iter > m_maxIterations) break; - Index im; - initFrancisQRStep(il, iu, shiftInfo, im, firstHouseholderVector); - performFrancisQRStep(il, im, iu, computeU, firstHouseholderVector, workspace); - } - } - - if(iter <= m_maxIterations) + } + if(iter <= m_maxIterations * m_matT.cols()) m_info = Success; else m_info = NoConvergence; @@ -288,7 +276,7 @@ inline typename MatrixType::Scalar RealSchur::computeNormOfT() // FIXME to be efficient the following would requires a triangular reduxion code // Scalar norm = m_matT.upper().cwiseAbs().sum() // + m_matT.bottomLeftCorner(size-1,size-1).diagonal().cwiseAbs().sum(); - Scalar norm = 0.0; + Scalar norm(0); for (Index j = 0; j < size; ++j) norm += m_matT.row(j).segment((std::max)(j-1,Index(0)), size-(std::max)(j-1,Index(0))).cwiseAbs().sum(); return norm; @@ -471,4 +459,6 @@ inline void RealSchur::performFrancisQRStep(Index il, Index im, Inde } } +} // end namespace Eigen + #endif // EIGEN_REAL_SCHUR_H diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/RealSchur_MKL.h b/extern/Eigen3/Eigen/src/Eigenvalues/RealSchur_MKL.h new file mode 100644 index 00000000000..960ec3c764a --- /dev/null +++ b/extern/Eigen3/Eigen/src/Eigenvalues/RealSchur_MKL.h @@ -0,0 +1,83 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + 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 Intel Corporation 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. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL + * Real Schur needed to real unsymmetrical eigenvalues/eigenvectors. + ******************************************************************************** +*/ + +#ifndef EIGEN_REAL_SCHUR_MKL_H +#define EIGEN_REAL_SCHUR_MKL_H + +#include "Eigen/src/Core/util/MKL_support.h" + +namespace Eigen { + +/** \internal Specialization for the data types supported by MKL */ + +#define EIGEN_MKL_SCHUR_REAL(EIGTYPE, MKLTYPE, MKLPREFIX, MKLPREFIX_U, EIGCOLROW, MKLCOLROW) \ +template<> inline \ +RealSchur >& \ +RealSchur >::compute(const Matrix& matrix, bool computeU) \ +{ \ + typedef Matrix MatrixType; \ + typedef MatrixType::Scalar Scalar; \ + typedef MatrixType::RealScalar RealScalar; \ +\ + assert(matrix.cols() == matrix.rows()); \ +\ + lapack_int n = matrix.cols(), sdim, info; \ + lapack_int lda = matrix.outerStride(); \ + lapack_int matrix_order = MKLCOLROW; \ + char jobvs, sort='N'; \ + LAPACK_##MKLPREFIX_U##_SELECT2 select = 0; \ + jobvs = (computeU) ? 'V' : 'N'; \ + m_matU.resize(n, n); \ + lapack_int ldvs = m_matU.outerStride(); \ + m_matT = matrix; \ + Matrix wr, wi; \ + wr.resize(n, 1); wi.resize(n, 1); \ + info = LAPACKE_##MKLPREFIX##gees( matrix_order, jobvs, sort, select, n, (MKLTYPE*)m_matT.data(), lda, &sdim, (MKLTYPE*)wr.data(), (MKLTYPE*)wi.data(), (MKLTYPE*)m_matU.data(), ldvs ); \ + if(info == 0) \ + m_info = Success; \ + else \ + m_info = NoConvergence; \ +\ + m_isInitialized = true; \ + m_matUisUptodate = computeU; \ + return *this; \ +\ +} + +EIGEN_MKL_SCHUR_REAL(double, double, d, D, ColMajor, LAPACK_COL_MAJOR) +EIGEN_MKL_SCHUR_REAL(float, float, s, S, ColMajor, LAPACK_COL_MAJOR) +EIGEN_MKL_SCHUR_REAL(double, double, d, D, RowMajor, LAPACK_ROW_MAJOR) +EIGEN_MKL_SCHUR_REAL(float, float, s, S, RowMajor, LAPACK_ROW_MAJOR) + +} // end namespace Eigen + +#endif // EIGEN_REAL_SCHUR_MKL_H diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h b/extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h index ad107c63282..acc5576feb1 100644 --- a/extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h +++ b/extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h @@ -4,34 +4,24 @@ // Copyright (C) 2008-2010 Gael Guennebaud // Copyright (C) 2010 Jitse Niesen // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SELFADJOINTEIGENSOLVER_H #define EIGEN_SELFADJOINTEIGENSOLVER_H -#include "./EigenvaluesCommon.h" #include "./Tridiagonalization.h" +namespace Eigen { + template class GeneralizedSelfAdjointEigenSolver; +namespace internal { +template struct direct_selfadjoint_eigenvalues; +} + /** \eigenvalues_module \ingroup Eigenvalues_Module * * @@ -86,7 +76,7 @@ template class SelfAdjointEigenSolver Options = MatrixType::Options, MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime }; - + /** \brief Scalar type for matrices of type \p _MatrixType. */ typedef typename MatrixType::Scalar Scalar; typedef typename MatrixType::Index Index; @@ -98,6 +88,8 @@ template class SelfAdjointEigenSolver * complex. */ typedef typename NumTraits::Real RealScalar; + + friend struct internal::direct_selfadjoint_eigenvalues::IsComplex>; /** \brief Type for vector of eigenvalues as returned by eigenvalues(). * @@ -198,6 +190,22 @@ template class SelfAdjointEigenSolver * \sa SelfAdjointEigenSolver(const MatrixType&, int) */ SelfAdjointEigenSolver& compute(const MatrixType& matrix, int options = ComputeEigenvectors); + + /** \brief Computes eigendecomposition of given matrix using a direct algorithm + * + * This is a variant of compute(const MatrixType&, int options) which + * directly solves the underlying polynomial equation. + * + * Currently only 3x3 matrices for which the sizes are known at compile time are supported (e.g., Matrix3d). + * + * This method is usually significantly faster than the QR algorithm + * but it might also be less accurate. It is also worth noting that + * for 3x3 matrices it involves trigonometric operations which are + * not necessarily available for all scalar types. + * + * \sa compute(const MatrixType&, int options) + */ + SelfAdjointEigenSolver& computeDirect(const MatrixType& matrix, int options = ComputeEigenvectors); /** \brief Returns the eigenvectors of given matrix. * @@ -401,7 +409,7 @@ SelfAdjointEigenSolver& SelfAdjointEigenSolver // map the matrix coefficients to [-1:1] to avoid over- and underflow. RealScalar scale = matrix.cwiseAbs().maxCoeff(); - if(scale==Scalar(0)) scale = 1; + if(scale==RealScalar(0)) scale = RealScalar(1); mat = matrix / scale; m_subdiag.resize(n-1); internal::tridiagonalization_inplace(mat, diag, m_subdiag, computeEigenvectors); @@ -466,19 +474,277 @@ SelfAdjointEigenSolver& SelfAdjointEigenSolver return *this; } + +namespace internal { + +template struct direct_selfadjoint_eigenvalues +{ + static inline void run(SolverType& eig, const typename SolverType::MatrixType& A, int options) + { eig.compute(A,options); } +}; + +template struct direct_selfadjoint_eigenvalues +{ + typedef typename SolverType::MatrixType MatrixType; + typedef typename SolverType::RealVectorType VectorType; + typedef typename SolverType::Scalar Scalar; + + static inline void computeRoots(const MatrixType& m, VectorType& roots) + { + using std::sqrt; + using std::atan2; + using std::cos; + using std::sin; + const Scalar s_inv3 = Scalar(1.0)/Scalar(3.0); + const Scalar s_sqrt3 = sqrt(Scalar(3.0)); + + // The characteristic equation is x^3 - c2*x^2 + c1*x - c0 = 0. The + // eigenvalues are the roots to this equation, all guaranteed to be + // real-valued, because the matrix is symmetric. + Scalar c0 = m(0,0)*m(1,1)*m(2,2) + Scalar(2)*m(1,0)*m(2,0)*m(2,1) - m(0,0)*m(2,1)*m(2,1) - m(1,1)*m(2,0)*m(2,0) - m(2,2)*m(1,0)*m(1,0); + Scalar c1 = m(0,0)*m(1,1) - m(1,0)*m(1,0) + m(0,0)*m(2,2) - m(2,0)*m(2,0) + m(1,1)*m(2,2) - m(2,1)*m(2,1); + Scalar c2 = m(0,0) + m(1,1) + m(2,2); + + // Construct the parameters used in classifying the roots of the equation + // and in solving the equation for the roots in closed form. + Scalar c2_over_3 = c2*s_inv3; + Scalar a_over_3 = (c1 - c2*c2_over_3)*s_inv3; + if (a_over_3 > Scalar(0)) + a_over_3 = Scalar(0); + + Scalar half_b = Scalar(0.5)*(c0 + c2_over_3*(Scalar(2)*c2_over_3*c2_over_3 - c1)); + + Scalar q = half_b*half_b + a_over_3*a_over_3*a_over_3; + if (q > Scalar(0)) + q = Scalar(0); + + // Compute the eigenvalues by solving for the roots of the polynomial. + Scalar rho = sqrt(-a_over_3); + Scalar theta = atan2(sqrt(-q),half_b)*s_inv3; + Scalar cos_theta = cos(theta); + Scalar sin_theta = sin(theta); + roots(0) = c2_over_3 + Scalar(2)*rho*cos_theta; + roots(1) = c2_over_3 - rho*(cos_theta + s_sqrt3*sin_theta); + roots(2) = c2_over_3 - rho*(cos_theta - s_sqrt3*sin_theta); + + // Sort in increasing order. + if (roots(0) >= roots(1)) + std::swap(roots(0),roots(1)); + if (roots(1) >= roots(2)) + { + std::swap(roots(1),roots(2)); + if (roots(0) >= roots(1)) + std::swap(roots(0),roots(1)); + } + } + + static inline void run(SolverType& solver, const MatrixType& mat, int options) + { + using std::sqrt; + eigen_assert(mat.cols() == 3 && mat.cols() == mat.rows()); + eigen_assert((options&~(EigVecMask|GenEigMask))==0 + && (options&EigVecMask)!=EigVecMask + && "invalid option parameter"); + bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors; + + MatrixType& eivecs = solver.m_eivec; + VectorType& eivals = solver.m_eivalues; + + // map the matrix coefficients to [-1:1] to avoid over- and underflow. + Scalar scale = mat.cwiseAbs().maxCoeff(); + MatrixType scaledMat = mat / scale; + + // compute the eigenvalues + computeRoots(scaledMat,eivals); + + // compute the eigen vectors + if(computeEigenvectors) + { + Scalar safeNorm2 = Eigen::NumTraits::epsilon(); + safeNorm2 *= safeNorm2; + if((eivals(2)-eivals(0))<=Eigen::NumTraits::epsilon()) + { + eivecs.setIdentity(); + } + else + { + scaledMat = scaledMat.template selfadjointView(); + MatrixType tmp; + tmp = scaledMat; + + Scalar d0 = eivals(2) - eivals(1); + Scalar d1 = eivals(1) - eivals(0); + int k = d0 > d1 ? 2 : 0; + d0 = d0 > d1 ? d1 : d0; + + tmp.diagonal().array () -= eivals(k); + VectorType cross; + Scalar n; + n = (cross = tmp.row(0).cross(tmp.row(1))).squaredNorm(); + + if(n>safeNorm2) + eivecs.col(k) = cross / sqrt(n); + else + { + n = (cross = tmp.row(0).cross(tmp.row(2))).squaredNorm(); + + if(n>safeNorm2) + eivecs.col(k) = cross / sqrt(n); + else + { + n = (cross = tmp.row(1).cross(tmp.row(2))).squaredNorm(); + + if(n>safeNorm2) + eivecs.col(k) = cross / sqrt(n); + else + { + // the input matrix and/or the eigenvaues probably contains some inf/NaN, + // => exit + // scale back to the original size. + eivals *= scale; + + solver.m_info = NumericalIssue; + solver.m_isInitialized = true; + solver.m_eigenvectorsOk = computeEigenvectors; + return; + } + } + } + + tmp = scaledMat; + tmp.diagonal().array() -= eivals(1); + + if(d0<=Eigen::NumTraits::epsilon()) + eivecs.col(1) = eivecs.col(k).unitOrthogonal(); + else + { + n = (cross = eivecs.col(k).cross(tmp.row(0).normalized())).squaredNorm(); + if(n>safeNorm2) + eivecs.col(1) = cross / sqrt(n); + else + { + n = (cross = eivecs.col(k).cross(tmp.row(1))).squaredNorm(); + if(n>safeNorm2) + eivecs.col(1) = cross / sqrt(n); + else + { + n = (cross = eivecs.col(k).cross(tmp.row(2))).squaredNorm(); + if(n>safeNorm2) + eivecs.col(1) = cross / sqrt(n); + else + { + // we should never reach this point, + // if so the last two eigenvalues are likely to ve very closed to each other + eivecs.col(1) = eivecs.col(k).unitOrthogonal(); + } + } + } + + // make sure that eivecs[1] is orthogonal to eivecs[2] + Scalar d = eivecs.col(1).dot(eivecs.col(k)); + eivecs.col(1) = (eivecs.col(1) - d * eivecs.col(k)).normalized(); + } + + eivecs.col(k==2 ? 0 : 2) = eivecs.col(k).cross(eivecs.col(1)).normalized(); + } + } + // Rescale back to the original size. + eivals *= scale; + + solver.m_info = Success; + solver.m_isInitialized = true; + solver.m_eigenvectorsOk = computeEigenvectors; + } +}; + +// 2x2 direct eigenvalues decomposition, code from Hauke Heibel +template struct direct_selfadjoint_eigenvalues +{ + typedef typename SolverType::MatrixType MatrixType; + typedef typename SolverType::RealVectorType VectorType; + typedef typename SolverType::Scalar Scalar; + + static inline void computeRoots(const MatrixType& m, VectorType& roots) + { + using std::sqrt; + const Scalar t0 = Scalar(0.5) * sqrt( abs2(m(0,0)-m(1,1)) + Scalar(4)*m(1,0)*m(1,0)); + const Scalar t1 = Scalar(0.5) * (m(0,0) + m(1,1)); + roots(0) = t1 - t0; + roots(1) = t1 + t0; + } + + static inline void run(SolverType& solver, const MatrixType& mat, int options) + { + eigen_assert(mat.cols() == 2 && mat.cols() == mat.rows()); + eigen_assert((options&~(EigVecMask|GenEigMask))==0 + && (options&EigVecMask)!=EigVecMask + && "invalid option parameter"); + bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors; + + MatrixType& eivecs = solver.m_eivec; + VectorType& eivals = solver.m_eivalues; + + // map the matrix coefficients to [-1:1] to avoid over- and underflow. + Scalar scale = mat.cwiseAbs().maxCoeff(); + scale = (std::max)(scale,Scalar(1)); + MatrixType scaledMat = mat / scale; + + // Compute the eigenvalues + computeRoots(scaledMat,eivals); + + // compute the eigen vectors + if(computeEigenvectors) + { + scaledMat.diagonal().array () -= eivals(1); + Scalar a2 = abs2(scaledMat(0,0)); + Scalar c2 = abs2(scaledMat(1,1)); + Scalar b2 = abs2(scaledMat(1,0)); + if(a2>c2) + { + eivecs.col(1) << -scaledMat(1,0), scaledMat(0,0); + eivecs.col(1) /= sqrt(a2+b2); + } + else + { + eivecs.col(1) << -scaledMat(1,1), scaledMat(1,0); + eivecs.col(1) /= sqrt(c2+b2); + } + + eivecs.col(0) << eivecs.col(1).unitOrthogonal(); + } + + // Rescale back to the original size. + eivals *= scale; + + solver.m_info = Success; + solver.m_isInitialized = true; + solver.m_eigenvectorsOk = computeEigenvectors; + } +}; + +} + +template +SelfAdjointEigenSolver& SelfAdjointEigenSolver +::computeDirect(const MatrixType& matrix, int options) +{ + internal::direct_selfadjoint_eigenvalues::IsComplex>::run(*this,matrix,options); + return *this; +} + namespace internal { template static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index start, Index end, Scalar* matrixQ, Index n) { - // NOTE this version avoids over & underflow, however since the matrix is prescaled, overflow cannot occur, - // and underflows should be meaningless anyway. So I don't any reason to enable this version, but I keep - // it here for reference: -// RealScalar td = (diag[end-1] - diag[end])*RealScalar(0.5); -// RealScalar e = subdiag[end-1]; -// RealScalar mu = diag[end] - (e / (td + (td>0 ? 1 : -1))) * (e / hypot(td,e)); RealScalar td = (diag[end-1] - diag[end])*RealScalar(0.5); - RealScalar e2 = abs2(subdiag[end-1]); - RealScalar mu = diag[end] - e2 / (td + (td>0 ? 1 : -1) * sqrt(td*td + e2)); + RealScalar e = subdiag[end-1]; + // Note that thanks to scaling, e^2 or td^2 cannot overflow, however they can still + // underflow thus leading to inf/NaN values when using the following commented code: +// RealScalar e2 = abs2(subdiag[end-1]); +// RealScalar mu = diag[end] - e2 / (td + (td>0 ? 1 : -1) * sqrt(td*td + e2)); + // This explain the following, somewhat more complicated, version: + RealScalar mu = diag[end] - (e / (td + (td>0 ? 1 : -1))) * (e / hypot(td,e)); + RealScalar x = diag[start] - mu; RealScalar z = subdiag[start]; for (Index k = start; k < end; ++k) @@ -515,6 +781,9 @@ static void tridiagonal_qr_step(RealScalar* diag, RealScalar* subdiag, Index sta } } } + } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_SELFADJOINTEIGENSOLVER_H diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h b/extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h new file mode 100644 index 00000000000..9380956b5f9 --- /dev/null +++ b/extern/Eigen3/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_MKL.h @@ -0,0 +1,92 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + 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 Intel Corporation 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. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL + * Self-adjoint eigenvalues/eigenvectors. + ******************************************************************************** +*/ + +#ifndef EIGEN_SAEIGENSOLVER_MKL_H +#define EIGEN_SAEIGENSOLVER_MKL_H + +#include "Eigen/src/Core/util/MKL_support.h" + +namespace Eigen { + +/** \internal Specialization for the data types supported by MKL */ + +#define EIGEN_MKL_EIG_SELFADJ(EIGTYPE, MKLTYPE, MKLRTYPE, MKLNAME, EIGCOLROW, MKLCOLROW ) \ +template<> inline\ +SelfAdjointEigenSolver >& \ +SelfAdjointEigenSolver >::compute(const Matrix& matrix, int options) \ +{ \ + eigen_assert(matrix.cols() == matrix.rows()); \ + eigen_assert((options&~(EigVecMask|GenEigMask))==0 \ + && (options&EigVecMask)!=EigVecMask \ + && "invalid option parameter"); \ + bool computeEigenvectors = (options&ComputeEigenvectors)==ComputeEigenvectors; \ + lapack_int n = matrix.cols(), lda, matrix_order, info; \ + m_eivalues.resize(n,1); \ + m_subdiag.resize(n-1); \ + m_eivec = matrix; \ +\ + if(n==1) \ + { \ + m_eivalues.coeffRef(0,0) = internal::real(matrix.coeff(0,0)); \ + if(computeEigenvectors) m_eivec.setOnes(n,n); \ + m_info = Success; \ + m_isInitialized = true; \ + m_eigenvectorsOk = computeEigenvectors; \ + return *this; \ + } \ +\ + lda = matrix.outerStride(); \ + matrix_order=MKLCOLROW; \ + char jobz, uplo='L'/*, range='A'*/; \ + jobz = computeEigenvectors ? 'V' : 'N'; \ +\ + info = LAPACKE_##MKLNAME( matrix_order, jobz, uplo, n, (MKLTYPE*)m_eivec.data(), lda, (MKLRTYPE*)m_eivalues.data() ); \ + m_info = (info==0) ? Success : NoConvergence; \ + m_isInitialized = true; \ + m_eigenvectorsOk = computeEigenvectors; \ + return *this; \ +} + + +EIGEN_MKL_EIG_SELFADJ(double, double, double, dsyev, ColMajor, LAPACK_COL_MAJOR) +EIGEN_MKL_EIG_SELFADJ(float, float, float, ssyev, ColMajor, LAPACK_COL_MAJOR) +EIGEN_MKL_EIG_SELFADJ(dcomplex, MKL_Complex16, double, zheev, ColMajor, LAPACK_COL_MAJOR) +EIGEN_MKL_EIG_SELFADJ(scomplex, MKL_Complex8, float, cheev, ColMajor, LAPACK_COL_MAJOR) + +EIGEN_MKL_EIG_SELFADJ(double, double, double, dsyev, RowMajor, LAPACK_ROW_MAJOR) +EIGEN_MKL_EIG_SELFADJ(float, float, float, ssyev, RowMajor, LAPACK_ROW_MAJOR) +EIGEN_MKL_EIG_SELFADJ(dcomplex, MKL_Complex16, double, zheev, RowMajor, LAPACK_ROW_MAJOR) +EIGEN_MKL_EIG_SELFADJ(scomplex, MKL_Complex8, float, cheev, RowMajor, LAPACK_ROW_MAJOR) + +} // end namespace Eigen + +#endif // EIGEN_SAEIGENSOLVER_H diff --git a/extern/Eigen3/Eigen/src/Eigenvalues/Tridiagonalization.h b/extern/Eigen3/Eigen/src/Eigenvalues/Tridiagonalization.h index ae4cdce7aeb..c34b7b3b801 100644 --- a/extern/Eigen3/Eigen/src/Eigenvalues/Tridiagonalization.h +++ b/extern/Eigen3/Eigen/src/Eigenvalues/Tridiagonalization.h @@ -4,28 +4,15 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2010 Jitse Niesen // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_TRIDIAGONALIZATION_H #define EIGEN_TRIDIAGONALIZATION_H +namespace Eigen { + namespace internal { template struct TridiagonalizationMatrixTReturnType; @@ -97,13 +84,13 @@ template class Tridiagonalization typedef internal::TridiagonalizationMatrixTReturnType MatrixTReturnType; typedef typename internal::conditional::IsComplex, - const typename Diagonal::RealReturnType, + typename internal::add_const_on_value_type::RealReturnType>::type, const Diagonal >::type DiagonalReturnType; typedef typename internal::conditional::IsComplex, - const typename Diagonal< - Block >::RealReturnType, + typename internal::add_const_on_value_type >::RealReturnType>::type, const Diagonal< Block > >::type SubDiagonalReturnType; @@ -560,9 +547,11 @@ template struct TridiagonalizationMatrixTReturnType Index cols() const { return m_matrix.cols(); } protected: - const typename MatrixType::Nested m_matrix; + typename MatrixType::Nested m_matrix; }; } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_TRIDIAGONALIZATION_H diff --git a/extern/Eigen3/Eigen/src/Geometry/AlignedBox.h b/extern/Eigen3/Eigen/src/Geometry/AlignedBox.h index b51deb3f3c3..5830fcd35fc 100644 --- a/extern/Eigen3/Eigen/src/Geometry/AlignedBox.h +++ b/extern/Eigen3/Eigen/src/Geometry/AlignedBox.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_ALIGNEDBOX_H #define EIGEN_ALIGNEDBOX_H +namespace Eigen { + /** \geometry_module \ingroup Geometry_Module * * @@ -190,7 +177,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim) template inline bool contains(const MatrixBase& a_p) const { - const typename internal::nested::type p(a_p.derived()); + typename internal::nested::type p(a_p.derived()); return (m_min.array()<=p.array()).all() && (p.array()<=m_max.array()).all(); } @@ -202,7 +189,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim) template inline AlignedBox& extend(const MatrixBase& a_p) { - const typename internal::nested::type p(a_p.derived()); + typename internal::nested::type p(a_p.derived()); m_min = m_min.cwiseMin(p); m_max = m_max.cwiseMax(p); return *this; @@ -310,7 +297,7 @@ template inline Scalar AlignedBox::squaredExteriorDistance(const MatrixBase& a_p) const { const typename internal::nested::type p(a_p.derived()); - Scalar dist2 = 0.; + Scalar dist2(0); Scalar aux; for (Index k=0; k::squaredExteriorDistance(const Matri template inline Scalar AlignedBox::squaredExteriorDistance(const AlignedBox& b) const { - Scalar dist2 = 0.; + Scalar dist2(0); Scalar aux; for (Index k=0; k::squaredExteriorDistance(const Align return dist2; } +/** \defgroup alignedboxtypedefs Global aligned box typedefs + * + * \ingroup Geometry_Module + * + * Eigen defines several typedef shortcuts for most common aligned box types. + * + * The general patterns are the following: + * + * \c AlignedBoxSizeType where \c Size can be \c 1, \c 2,\c 3,\c 4 for fixed size boxes or \c X for dynamic size, + * and where \c Type can be \c i for integer, \c f for float, \c d for double. + * + * For example, \c AlignedBox3d is a fixed-size 3x3 aligned box type of doubles, and \c AlignedBoxXf is a dynamic-size aligned box of floats. + * + * \sa class AlignedBox + */ + +#define EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, Size, SizeSuffix) \ +/** \ingroup alignedboxtypedefs */ \ +typedef AlignedBox AlignedBox##SizeSuffix##TypeSuffix; + +#define EIGEN_MAKE_TYPEDEFS_ALL_SIZES(Type, TypeSuffix) \ +EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 1, 1) \ +EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 2, 2) \ +EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 3, 3) \ +EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 4, 4) \ +EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, Dynamic, X) + +EIGEN_MAKE_TYPEDEFS_ALL_SIZES(int, i) +EIGEN_MAKE_TYPEDEFS_ALL_SIZES(float, f) +EIGEN_MAKE_TYPEDEFS_ALL_SIZES(double, d) + +#undef EIGEN_MAKE_TYPEDEFS_ALL_SIZES +#undef EIGEN_MAKE_TYPEDEFS + +} // end namespace Eigen + #endif // EIGEN_ALIGNEDBOX_H diff --git a/extern/Eigen3/Eigen/src/Geometry/AngleAxis.h b/extern/Eigen3/Eigen/src/Geometry/AngleAxis.h index 0ec4624cf98..67197ac78c3 100644 --- a/extern/Eigen3/Eigen/src/Geometry/AngleAxis.h +++ b/extern/Eigen3/Eigen/src/Geometry/AngleAxis.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_ANGLEAXIS_H #define EIGEN_ANGLEAXIS_H +namespace Eigen { + /** \geometry_module \ingroup Geometry_Module * * \class AngleAxis @@ -144,7 +131,7 @@ public: m_angle = Scalar(other.angle()); } - inline static const AngleAxis Identity() { return AngleAxis(0, Vector3::UnitX()); } + static inline const AngleAxis Identity() { return AngleAxis(0, Vector3::UnitX()); } /** \returns \c true if \c *this is approximately equal to \a other, within the precision * determined by \a prec. @@ -238,4 +225,6 @@ AngleAxis::toRotationMatrix(void) const return res; } +} // end namespace Eigen + #endif // EIGEN_ANGLEAXIS_H diff --git a/extern/Eigen3/Eigen/src/Geometry/EulerAngles.h b/extern/Eigen3/Eigen/src/Geometry/EulerAngles.h index d246a6ebf4a..e424d240604 100644 --- a/extern/Eigen3/Eigen/src/Geometry/EulerAngles.h +++ b/extern/Eigen3/Eigen/src/Geometry/EulerAngles.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_EULERANGLES_H #define EIGEN_EULERANGLES_H +namespace Eigen { + /** \geometry_module \ingroup Geometry_Module * * @@ -92,5 +79,6 @@ MatrixBase::eulerAngles(Index a0, Index a1, Index a2) const return res; } +} // end namespace Eigen #endif // EIGEN_EULERANGLES_H diff --git a/extern/Eigen3/Eigen/src/Geometry/Homogeneous.h b/extern/Eigen3/Eigen/src/Geometry/Homogeneous.h index 2bc4f7e87e3..df03feb55c6 100644 --- a/extern/Eigen3/Eigen/src/Geometry/Homogeneous.h +++ b/extern/Eigen3/Eigen/src/Geometry/Homogeneous.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_HOMOGENEOUS_H #define EIGEN_HOMOGENEOUS_H +namespace Eigen { + /** \geometry_module \ingroup Geometry_Module * * \class Homogeneous @@ -121,7 +108,7 @@ template class Homogeneous } protected: - const typename MatrixType::Nested m_matrix; + typename MatrixType::Nested m_matrix; }; /** \geometry_module @@ -216,8 +203,8 @@ template struct take_matrix_for_product > { typedef Transform TransformType; - typedef typename TransformType::ConstAffinePart type; - static const type run (const TransformType& x) { return x.affine(); } + typedef typename internal::add_const::type type; + static type run (const TransformType& x) { return x.affine(); } }; template @@ -270,8 +257,8 @@ struct homogeneous_left_product_impl,Lhs> .template replicate(m_rhs.cols()); } - const typename LhsMatrixTypeCleaned::Nested m_lhs; - const typename MatrixType::Nested m_rhs; + typename LhsMatrixTypeCleaned::Nested m_lhs; + typename MatrixType::Nested m_rhs; }; template @@ -309,10 +296,12 @@ struct homogeneous_right_product_impl,Rhs> .template replicate(m_lhs.rows()); } - const typename MatrixType::Nested m_lhs; - const typename Rhs::Nested m_rhs; + typename MatrixType::Nested m_lhs; + typename Rhs::Nested m_rhs; }; } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_HOMOGENEOUS_H diff --git a/extern/Eigen3/Eigen/src/Geometry/Hyperplane.h b/extern/Eigen3/Eigen/src/Geometry/Hyperplane.h index d85d3e553f8..1b7c7c78c80 100644 --- a/extern/Eigen3/Eigen/src/Geometry/Hyperplane.h +++ b/extern/Eigen3/Eigen/src/Geometry/Hyperplane.h @@ -4,28 +4,15 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_HYPERPLANE_H #define EIGEN_HYPERPLANE_H +namespace Eigen { + /** \geometry_module \ingroup Geometry_Module * * \class Hyperplane @@ -277,4 +264,6 @@ protected: Coefficients m_coeffs; }; +} // end namespace Eigen + #endif // EIGEN_HYPERPLANE_H diff --git a/extern/Eigen3/Eigen/src/Geometry/OrthoMethods.h b/extern/Eigen3/Eigen/src/Geometry/OrthoMethods.h index 52b46988196..11ad5829cda 100644 --- a/extern/Eigen3/Eigen/src/Geometry/OrthoMethods.h +++ b/extern/Eigen3/Eigen/src/Geometry/OrthoMethods.h @@ -4,28 +4,15 @@ // Copyright (C) 2008-2009 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_ORTHOMETHODS_H #define EIGEN_ORTHOMETHODS_H +namespace Eigen { + /** \geometry_module * * \returns the cross product of \c *this and \a other @@ -43,8 +30,8 @@ MatrixBase::cross(const MatrixBase& other) const // Note that there is no need for an expression here since the compiler // optimize such a small temporary very well (even within a complex expression) - const typename internal::nested::type lhs(derived()); - const typename internal::nested::type rhs(other.derived()); + typename internal::nested::type lhs(derived()); + typename internal::nested::type rhs(other.derived()); return typename cross_product_return_type::type( internal::conj(lhs.coeff(1) * rhs.coeff(2) - lhs.coeff(2) * rhs.coeff(1)), internal::conj(lhs.coeff(2) * rhs.coeff(0) - lhs.coeff(0) * rhs.coeff(2)), @@ -56,9 +43,9 @@ namespace internal { template< int Arch,typename VectorLhs,typename VectorRhs, typename Scalar = typename VectorLhs::Scalar, - bool Vectorizable = (VectorLhs::Flags&VectorRhs::Flags)&PacketAccessBit> + bool Vectorizable = bool((VectorLhs::Flags&VectorRhs::Flags)&PacketAccessBit)> struct cross3_impl { - inline static typename internal::plain_matrix_type::type + static inline typename internal::plain_matrix_type::type run(const VectorLhs& lhs, const VectorRhs& rhs) { return typename internal::plain_matrix_type::type( @@ -145,7 +132,7 @@ struct unitOrthogonal_selector typedef typename NumTraits::Real RealScalar; typedef typename Derived::Index Index; typedef Matrix Vector2; - inline static VectorType run(const Derived& src) + static inline VectorType run(const Derived& src) { VectorType perp = VectorType::Zero(src.size()); Index maxi = 0; @@ -167,7 +154,7 @@ struct unitOrthogonal_selector typedef typename plain_matrix_type::type VectorType; typedef typename traits::Scalar Scalar; typedef typename NumTraits::Real RealScalar; - inline static VectorType run(const Derived& src) + static inline VectorType run(const Derived& src) { VectorType perp; /* Let us compute the crossed product of *this with a vector @@ -205,7 +192,7 @@ template struct unitOrthogonal_selector { typedef typename plain_matrix_type::type VectorType; - inline static VectorType run(const Derived& src) + static inline VectorType run(const Derived& src) { return VectorType(-conj(src.y()), conj(src.x())).normalized(); } }; @@ -226,4 +213,6 @@ MatrixBase::unitOrthogonal() const return internal::unitOrthogonal_selector::run(derived()); } +} // end namespace Eigen + #endif // EIGEN_ORTHOMETHODS_H diff --git a/extern/Eigen3/Eigen/src/Geometry/ParametrizedLine.h b/extern/Eigen3/Eigen/src/Geometry/ParametrizedLine.h index b90f9c088a2..719a904413d 100644 --- a/extern/Eigen3/Eigen/src/Geometry/ParametrizedLine.h +++ b/extern/Eigen3/Eigen/src/Geometry/ParametrizedLine.h @@ -4,28 +4,15 @@ // Copyright (C) 2008 Gael Guennebaud // Copyright (C) 2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_PARAMETRIZEDLINE_H #define EIGEN_PARAMETRIZEDLINE_H +namespace Eigen { + /** \geometry_module \ingroup Geometry_Module * * \class ParametrizedLine @@ -106,8 +93,16 @@ public: VectorType projection(const VectorType& p) const { return origin() + direction().dot(p-origin()) * direction(); } + VectorType pointAt( Scalar t ) const; + + template + Scalar intersectionParameter(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const; + template Scalar intersection(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const; + + template + VectorType intersectionPoint(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const; /** \returns \c *this with scalar type casted to \a NewScalarType * @@ -155,14 +150,46 @@ inline ParametrizedLine<_Scalar, _AmbientDim,_Options>::ParametrizedLine(const H origin() = -hyperplane.normal()*hyperplane.offset(); } -/** \returns the parameter value of the intersection between \c *this and the given hyperplane +/** \returns the point at \a t along this line + */ +template +inline typename ParametrizedLine<_Scalar, _AmbientDim,_Options>::VectorType +ParametrizedLine<_Scalar, _AmbientDim,_Options>::pointAt( _Scalar t ) const +{ + return origin() + (direction()*t); +} + +/** \returns the parameter value of the intersection between \c *this and the given \a hyperplane */ template template -inline _Scalar ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersection(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const +inline _Scalar ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersectionParameter(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const { return -(hyperplane.offset()+hyperplane.normal().dot(origin())) / hyperplane.normal().dot(direction()); } + +/** \deprecated use intersectionParameter() + * \returns the parameter value of the intersection between \c *this and the given \a hyperplane + */ +template +template +inline _Scalar ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersection(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const +{ + return intersectionParameter(hyperplane); +} + +/** \returns the point of the intersection between \c *this and the given hyperplane + */ +template +template +inline typename ParametrizedLine<_Scalar, _AmbientDim,_Options>::VectorType +ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersectionPoint(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const +{ + return pointAt(intersectionParameter(hyperplane)); +} + +} // end namespace Eigen + #endif // EIGEN_PARAMETRIZEDLINE_H diff --git a/extern/Eigen3/Eigen/src/Geometry/Quaternion.h b/extern/Eigen3/Eigen/src/Geometry/Quaternion.h index 9180db67d84..8792e2da2ae 100644 --- a/extern/Eigen3/Eigen/src/Geometry/Quaternion.h +++ b/extern/Eigen3/Eigen/src/Geometry/Quaternion.h @@ -4,27 +4,14 @@ // Copyright (C) 2008-2010 Gael Guennebaud // Copyright (C) 2009 Mathieu Gautier // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_QUATERNION_H #define EIGEN_QUATERNION_H +namespace Eigen { + /*************************************************************************** * Definition of QuaternionBase @@ -38,6 +25,12 @@ template class QuaternionBase : public RotationBase { @@ -109,7 +102,7 @@ public: /** \returns a quaternion representing an identity rotation * \sa MatrixBase::Identity() */ - inline static Quaternion Identity() { return Quaternion(1, 0, 0, 0); } + static inline Quaternion Identity() { return Quaternion(1, 0, 0, 0); } /** \sa QuaternionBase::Identity(), MatrixBase::setIdentity() */ @@ -278,6 +271,9 @@ public: explicit inline Quaternion(const Quaternion& other) { m_coeffs = other.coeffs().template cast(); } + template + static Quaternion FromTwoVectors(const MatrixBase& a, const MatrixBase& b); + inline Coefficients& coeffs() { return m_coeffs;} inline const Coefficients& coeffs() const { return m_coeffs;} @@ -287,7 +283,7 @@ protected: Coefficients m_coeffs; #ifndef EIGEN_PARSED_BY_DOXYGEN - EIGEN_STRONG_INLINE static void _check_template_params() + static EIGEN_STRONG_INLINE void _check_template_params() { EIGEN_STATIC_ASSERT( (_Options & DontAlign) == _Options, INVALID_MATRIX_TEMPLATE_PARAMETERS) @@ -434,7 +430,7 @@ typedef Map, Aligned> QuaternionMapAlignedd; namespace internal { template struct quat_product { - EIGEN_STRONG_INLINE static Quaternion run(const QuaternionBase& a, const QuaternionBase& b){ + static EIGEN_STRONG_INLINE Quaternion run(const QuaternionBase& a, const QuaternionBase& b){ return Quaternion ( a.w() * b.w() - a.x() * b.x() - a.y() * b.y() - a.z() * b.z(), @@ -544,9 +540,9 @@ QuaternionBase::toRotationMatrix(void) const // it has to be inlined, and so the return by value is not an issue Matrix3 res; - const Scalar tx = 2*this->x(); - const Scalar ty = 2*this->y(); - const Scalar tz = 2*this->z(); + const Scalar tx = Scalar(2)*this->x(); + const Scalar ty = Scalar(2)*this->y(); + const Scalar tz = Scalar(2)*this->z(); const Scalar twx = tx*this->w(); const Scalar twy = ty*this->w(); const Scalar twz = tz*this->w(); @@ -557,15 +553,15 @@ QuaternionBase::toRotationMatrix(void) const const Scalar tyz = tz*this->y(); const Scalar tzz = tz*this->z(); - res.coeffRef(0,0) = 1-(tyy+tzz); + res.coeffRef(0,0) = Scalar(1)-(tyy+tzz); res.coeffRef(0,1) = txy-twz; res.coeffRef(0,2) = txz+twy; res.coeffRef(1,0) = txy+twz; - res.coeffRef(1,1) = 1-(txx+tzz); + res.coeffRef(1,1) = Scalar(1)-(txx+tzz); res.coeffRef(1,2) = tyz-twx; res.coeffRef(2,0) = txz-twy; res.coeffRef(2,1) = tyz+twx; - res.coeffRef(2,2) = 1-(txx+tyy); + res.coeffRef(2,2) = Scalar(1)-(txx+tyy); return res; } @@ -618,6 +614,27 @@ inline Derived& QuaternionBase::setFromTwoVectors(const MatrixBase +template +Quaternion Quaternion::FromTwoVectors(const MatrixBase& a, const MatrixBase& b) +{ + Quaternion quat; + quat.setFromTwoVectors(a, b); + return quat; +} + + /** \returns the multiplicative inverse of \c *this * Note that in most cases, i.e., if you simply want the opposite rotation, * and/or the quaternion is normalized, then it is enough to use the conjugate. @@ -709,7 +726,7 @@ struct quaternionbase_assign_impl { typedef typename Other::Scalar Scalar; typedef DenseIndex Index; - template inline static void run(QuaternionBase& q, const Other& mat) + template static inline void run(QuaternionBase& q, const Other& mat) { // This algorithm comes from "Quaternion Calculus and Fast Animation", // Ken Shoemake, 1987 SIGGRAPH course notes @@ -748,7 +765,7 @@ template struct quaternionbase_assign_impl { typedef typename Other::Scalar Scalar; - template inline static void run(QuaternionBase& q, const Other& vec) + template static inline void run(QuaternionBase& q, const Other& vec) { q.coeffs() = vec; } @@ -756,4 +773,6 @@ struct quaternionbase_assign_impl } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_QUATERNION_H diff --git a/extern/Eigen3/Eigen/src/Geometry/Rotation2D.h b/extern/Eigen3/Eigen/src/Geometry/Rotation2D.h index cf36da1c50c..868e2ef312f 100644 --- a/extern/Eigen3/Eigen/src/Geometry/Rotation2D.h +++ b/extern/Eigen3/Eigen/src/Geometry/Rotation2D.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_ROTATION2D_H #define EIGEN_ROTATION2D_H +namespace Eigen { + /** \geometry_module \ingroup Geometry_Module * * \class Rotation2D @@ -121,7 +108,7 @@ public: m_angle = Scalar(other.angle()); } - inline static Rotation2D Identity() { return Rotation2D(0); } + static inline Rotation2D Identity() { return Rotation2D(0); } /** \returns \c true if \c *this is approximately equal to \a other, within the precision * determined by \a prec. @@ -162,4 +149,6 @@ Rotation2D::toRotationMatrix(void) const return (Matrix2() << cosA, -sinA, sinA, cosA).finished(); } +} // end namespace Eigen + #endif // EIGEN_ROTATION2D_H diff --git a/extern/Eigen3/Eigen/src/Geometry/RotationBase.h b/extern/Eigen3/Eigen/src/Geometry/RotationBase.h index 1abf06bb640..b88661de6b1 100644 --- a/extern/Eigen3/Eigen/src/Geometry/RotationBase.h +++ b/extern/Eigen3/Eigen/src/Geometry/RotationBase.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_ROTATIONBASE_H #define EIGEN_ROTATIONBASE_H +namespace Eigen { + // forward declaration namespace internal { template @@ -115,7 +102,7 @@ struct rotation_base_generic_product_selector { enum { Dim = RotationDerived::Dim }; typedef Matrix ReturnType; - inline static ReturnType run(const RotationDerived& r, const MatrixType& m) + static inline ReturnType run(const RotationDerived& r, const MatrixType& m) { return r.toRotationMatrix() * m; } }; @@ -123,7 +110,7 @@ template struct rotation_base_generic_product_selector< RotationDerived, DiagonalMatrix, false > { typedef Transform ReturnType; - inline static ReturnType run(const RotationDerived& r, const DiagonalMatrix& m) + static inline ReturnType run(const RotationDerived& r, const DiagonalMatrix& m) { ReturnType res(r); res.linear() *= m; @@ -136,7 +123,7 @@ struct rotation_base_generic_product_selector ReturnType; - EIGEN_STRONG_INLINE static ReturnType run(const RotationDerived& r, const OtherVectorType& v) + static EIGEN_STRONG_INLINE ReturnType run(const RotationDerived& r, const OtherVectorType& v) { return r._transformVector(v); } @@ -192,20 +179,20 @@ namespace internal { * \sa class Transform, class Rotation2D, class Quaternion, class AngleAxis */ template -inline static Matrix toRotationMatrix(const Scalar& s) +static inline Matrix toRotationMatrix(const Scalar& s) { EIGEN_STATIC_ASSERT(Dim==2,YOU_MADE_A_PROGRAMMING_MISTAKE) return Rotation2D(s).toRotationMatrix(); } template -inline static Matrix toRotationMatrix(const RotationBase& r) +static inline Matrix toRotationMatrix(const RotationBase& r) { return r.toRotationMatrix(); } template -inline static const MatrixBase& toRotationMatrix(const MatrixBase& mat) +static inline const MatrixBase& toRotationMatrix(const MatrixBase& mat) { EIGEN_STATIC_ASSERT(OtherDerived::RowsAtCompileTime==Dim && OtherDerived::ColsAtCompileTime==Dim, YOU_MADE_A_PROGRAMMING_MISTAKE) @@ -214,4 +201,6 @@ inline static const MatrixBase& toRotationMatrix(const MatrixBase< } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_ROTATIONBASE_H diff --git a/extern/Eigen3/Eigen/src/Geometry/Scaling.h b/extern/Eigen3/Eigen/src/Geometry/Scaling.h index c911d13e1d3..8edcac31c74 100644 --- a/extern/Eigen3/Eigen/src/Geometry/Scaling.h +++ b/extern/Eigen3/Eigen/src/Geometry/Scaling.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SCALING_H #define EIGEN_SCALING_H +namespace Eigen { + /** \geometry_module \ingroup Geometry_Module * * \class Scaling @@ -73,7 +60,12 @@ public: /** Concatenates a uniform scaling and an affine transformation */ template - inline Transform operator* (const Transform& t) const; + inline Transform operator* (const Transform& t) const + { + Transform res = t; + res.prescale(factor()); + return res; +} /** Concatenates a uniform scaling and a linear transformation matrix */ // TODO returns an expression @@ -169,14 +161,6 @@ UniformScaling::operator* (const Translation& t) const return res; } -template -template -inline Transform -UniformScaling::operator* (const Transform& t) const -{ - Transform res = t; - res.prescale(factor()); - return res; -} +} // end namespace Eigen #endif // EIGEN_SCALING_H diff --git a/extern/Eigen3/Eigen/src/Geometry/Transform.h b/extern/Eigen3/Eigen/src/Geometry/Transform.h index a694673ebed..4c1ef8eaade 100644 --- a/extern/Eigen3/Eigen/src/Geometry/Transform.h +++ b/extern/Eigen3/Eigen/src/Geometry/Transform.h @@ -5,28 +5,15 @@ // Copyright (C) 2009 Benoit Jacob // Copyright (C) 2010 Hauke Heibel // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_TRANSFORM_H #define EIGEN_TRANSFORM_H +namespace Eigen { + namespace internal { template @@ -37,7 +24,7 @@ struct transform_traits Dim = Transform::Dim, HDim = Transform::HDim, Mode = Transform::Mode, - IsProjective = (Mode==Projective) + IsProjective = (int(Mode)==int(Projective)) }; }; @@ -207,9 +194,9 @@ public: /** type of the matrix used to represent the linear part of the transformation */ typedef Matrix LinearMatrixType; /** type of read/write reference to the linear part of the transformation */ - typedef Block LinearPart; + typedef Block LinearPart; /** type of read reference to the linear part of the transformation */ - typedef const Block ConstLinearPart; + typedef const Block ConstLinearPart; /** type of read/write reference to the affine part of the transformation */ typedef typename internal::conditional VectorType; /** type of a read/write reference to the translation part of the rotation */ - typedef Block TranslationPart; + typedef Block TranslationPart; /** type of a read reference to the translation part of the rotation */ - typedef const Block ConstTranslationPart; + typedef const Block ConstTranslationPart; /** corresponding translation type */ typedef Translation TranslationType; @@ -279,6 +266,9 @@ public: template inline explicit Transform(const EigenBase& other) { + EIGEN_STATIC_ASSERT((internal::is_same::value), + YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY); + check_template_params(); internal::transform_construct_from_matrix::run(this, other.derived()); } @@ -287,6 +277,9 @@ public: template inline Transform& operator=(const EigenBase& other) { + EIGEN_STATIC_ASSERT((internal::is_same::value), + YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY); + internal::transform_construct_from_matrix::run(this, other.derived()); return *this; } @@ -376,9 +369,9 @@ public: inline MatrixType& matrix() { return m_matrix; } /** \returns a read-only expression of the linear part of the transformation */ - inline ConstLinearPart linear() const { return m_matrix.template block(0,0); } + inline ConstLinearPart linear() const { return ConstLinearPart(m_matrix,0,0); } /** \returns a writable expression of the linear part of the transformation */ - inline LinearPart linear() { return m_matrix.template block(0,0); } + inline LinearPart linear() { return LinearPart(m_matrix,0,0); } /** \returns a read-only expression of the Dim x HDim affine part of the transformation */ inline ConstAffinePart affine() const { return take_affine_part::run(m_matrix); } @@ -386,9 +379,9 @@ public: inline AffinePart affine() { return take_affine_part::run(m_matrix); } /** \returns a read-only expression of the translation vector of the transformation */ - inline ConstTranslationPart translation() const { return m_matrix.template block(0,Dim); } + inline ConstTranslationPart translation() const { return ConstTranslationPart(m_matrix,0,Dim); } /** \returns a writable expression of the translation vector of the transformation */ - inline TranslationPart translation() { return m_matrix.template block(0,Dim); } + inline TranslationPart translation() { return TranslationPart(m_matrix,0,Dim); } /** \returns an expression of the product between the transform \c *this and a matrix expression \a other * @@ -460,15 +453,40 @@ public: { return internal::transform_transform_product_impl::run(*this,other); } - + + #ifdef __INTEL_COMPILER +private: + // this intermediate structure permits to workaround a bug in ICC 11: + // error: template instantiation resulted in unexpected function type of "Eigen::Transform + // (const Eigen::Transform &) const" + // (the meaning of a name may have changed since the template declaration -- the type of the template is: + // "Eigen::internal::transform_transform_product_impl, + // Eigen::Transform, >::ResultType (const Eigen::Transform &) const") + // + template struct icc_11_workaround + { + typedef internal::transform_transform_product_impl > ProductType; + typedef typename ProductType::ResultType ResultType; + }; + +public: /** Concatenates two different transformations */ template - inline const typename internal::transform_transform_product_impl< - Transform,Transform >::ResultType + inline typename icc_11_workaround::ResultType + operator * (const Transform& other) const + { + typedef typename icc_11_workaround::ProductType ProductType; + return ProductType::run(*this,other); + } + #else + /** Concatenates two different transformations */ + template + inline typename internal::transform_transform_product_impl >::ResultType operator * (const Transform& other) const { return internal::transform_transform_product_impl >::run(*this,other); } + #endif /** \sa MatrixBase::setIdentity() */ void setIdentity() { m_matrix.setIdentity(); } @@ -512,7 +530,12 @@ public: inline Transform& operator=(const UniformScaling& t); inline Transform& operator*=(const UniformScaling& s) { return scale(s.factor()); } - inline Transform operator*(const UniformScaling& s) const; + inline Transform operator*(const UniformScaling& s) const + { + Transform res = *this; + res.scale(s.factor()); + return res; + } inline Transform& operator*=(const DiagonalMatrix& s) { linear() *= s; return *this; } @@ -571,7 +594,7 @@ public: if(int(Mode)!=int(AffineCompact)) { matrix().template block<1,Dim>(Dim,0).setZero(); - matrix().coeffRef(Dim,Dim) = 1; + matrix().coeffRef(Dim,Dim) = Scalar(1); } } @@ -608,7 +631,7 @@ public: protected: #ifndef EIGEN_PARSED_BY_DOXYGEN - EIGEN_STRONG_INLINE static void check_template_params() + static EIGEN_STRONG_INLINE void check_template_params() { EIGEN_STATIC_ASSERT((Options & (DontAlign|RowMajor)) == Options, INVALID_MATRIX_TEMPLATE_PARAMETERS) } @@ -940,14 +963,6 @@ inline Transform& Transform::o return *this; } -template -inline Transform Transform::operator*(const UniformScaling& s) const -{ - Transform res = *this; - res.scale(s.factor()); - return res; -} - template template inline Transform& Transform::operator=(const RotationBase& r) @@ -1219,7 +1234,7 @@ struct transform_right_product_impl< TransformType, MatrixType, 0 > { typedef typename MatrixType::PlainObject ResultType; - EIGEN_STRONG_INLINE static ResultType run(const TransformType& T, const MatrixType& other) + static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other) { return T.matrix() * other; } @@ -1237,11 +1252,11 @@ struct transform_right_product_impl< TransformType, MatrixType, 1 > typedef typename MatrixType::PlainObject ResultType; - EIGEN_STRONG_INLINE static ResultType run(const TransformType& T, const MatrixType& other) + static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other) { EIGEN_STATIC_ASSERT(OtherRows==HDim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES); - typedef Block TopLeftLhs; + typedef Block TopLeftLhs; ResultType res(other.rows(),other.cols()); TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() = T.affine() * other; @@ -1263,15 +1278,13 @@ struct transform_right_product_impl< TransformType, MatrixType, 2 > typedef typename MatrixType::PlainObject ResultType; - EIGEN_STRONG_INLINE static ResultType run(const TransformType& T, const MatrixType& other) + static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other) { EIGEN_STATIC_ASSERT(OtherRows==Dim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES); - typedef Block TopLeftLhs; - - ResultType res(other.rows(),other.cols()); - TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() = T.linear() * other; - TopLeftLhs(res, 0, 0, Dim, other.cols()).colwise() += T.translation(); + typedef Block TopLeftLhs; + ResultType res(Replicate(T.translation(),1,other.cols())); + TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() += T.linear() * other; return res; } @@ -1422,4 +1435,6 @@ struct transform_transform_product_impl // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_TRANSLATION_H #define EIGEN_TRANSLATION_H +namespace Eigen { + /** \geometry_module \ingroup Geometry_Module * * \class Translation @@ -54,6 +41,8 @@ public: typedef Matrix LinearMatrixType; /** corresponding affine transformation type */ typedef Transform AffineTransformType; + /** corresponding isometric transformation type */ + typedef Transform IsometryTransformType; protected: @@ -114,8 +103,8 @@ public: /** Concatenates a translation and a rotation */ template - inline AffineTransformType operator*(const RotationBase& r) const - { return *this * r.toRotationMatrix(); } + inline IsometryTransformType operator*(const RotationBase& r) const + { return *this * IsometryTransformType(r); } /** \returns the concatenation of a linear transformation \a l with the translation \a t */ // its a nightmare to define a templated friend function outside its declaration @@ -212,4 +201,6 @@ Translation::operator* (const EigenBase& linear) const return res; } +} // end namespace Eigen + #endif // EIGEN_TRANSLATION_H diff --git a/extern/Eigen3/Eigen/src/Geometry/Umeyama.h b/extern/Eigen3/Eigen/src/Geometry/Umeyama.h index b50f461730e..ac0939cde52 100644 --- a/extern/Eigen3/Eigen/src/Geometry/Umeyama.h +++ b/extern/Eigen3/Eigen/src/Geometry/Umeyama.h @@ -3,24 +3,9 @@ // // Copyright (C) 2009 Hauke Heibel // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_UMEYAMA_H #define EIGEN_UMEYAMA_H @@ -31,6 +16,8 @@ // * Eigen/SVD // * Eigen/Array +namespace Eigen { + #ifndef EIGEN_PARSED_BY_DOXYGEN // These helpers are required since it allows to use mixed types as parameters @@ -180,4 +167,6 @@ umeyama(const MatrixBase& src, const MatrixBase& dst, boo return Rt; } +} // end namespace Eigen + #endif // EIGEN_UMEYAMA_H diff --git a/extern/Eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h b/extern/Eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h index 2af32678d1c..3d8284f2d0c 100644 --- a/extern/Eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h +++ b/extern/Eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h @@ -4,34 +4,21 @@ // Copyright (C) 2009 Rohit Garg // Copyright (C) 2009-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_GEOMETRY_SSE_H #define EIGEN_GEOMETRY_SSE_H +namespace Eigen { + namespace internal { template struct quat_product { - inline static Quaternion run(const QuaternionBase& _a, const QuaternionBase& _b) + static inline Quaternion run(const QuaternionBase& _a, const QuaternionBase& _b) { const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0,0,0,0x80000000)); Quaternion res; @@ -53,7 +40,7 @@ struct quat_product template struct cross3_impl { - inline static typename plain_matrix_type::type + static inline typename plain_matrix_type::type run(const VectorLhs& lhs, const VectorRhs& rhs) { __m128 a = lhs.template packet(0); @@ -72,7 +59,7 @@ struct cross3_impl template struct quat_product { - inline static Quaternion run(const QuaternionBase& _a, const QuaternionBase& _b) + static inline Quaternion run(const QuaternionBase& _a, const QuaternionBase& _b) { const Packet2d mask = _mm_castsi128_pd(_mm_set_epi32(0x0,0x0,0x80000000,0x0)); @@ -123,4 +110,6 @@ struct quat_product } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_GEOMETRY_SSE_H diff --git a/extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h b/extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h index 23ce1bfbd46..1991c652738 100644 --- a/extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h +++ b/extern/Eigen3/Eigen/src/Householder/BlockHouseholder.h @@ -4,30 +4,17 @@ // Copyright (C) 2010 Vincent Lejeune // Copyright (C) 2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_BLOCK_HOUSEHOLDER_H #define EIGEN_BLOCK_HOUSEHOLDER_H // This file contains some helper function to deal with block householder reflectors +namespace Eigen { + namespace internal { /** \internal */ @@ -64,7 +51,7 @@ void apply_block_householder_on_the_left(MatrixType& mat, const VectorsType& vec Matrix T(nbVecs,nbVecs); make_block_householder_triangular_factor(T, vectors, hCoeffs); - const TriangularView& V(vectors); + const TriangularView& V(vectors); // A -= V T V^* A Matrix // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_HOUSEHOLDER_H #define EIGEN_HOUSEHOLDER_H +namespace Eigen { + namespace internal { template struct decrement_size { @@ -35,6 +22,22 @@ template struct decrement_size }; } +/** Computes the elementary reflector H such that: + * \f$ H *this = [ beta 0 ... 0]^T \f$ + * where the transformation H is: + * \f$ H = I - tau v v^*\f$ + * and the vector v is: + * \f$ v^T = [1 essential^T] \f$ + * + * The essential part of the vector \c v is stored in *this. + * + * On output: + * \param tau the scaling factor of the Householder transformation + * \param beta the result of H * \c *this + * + * \sa MatrixBase::makeHouseholder(), MatrixBase::applyHouseholderOnTheLeft(), + * MatrixBase::applyHouseholderOnTheRight() + */ template void MatrixBase::makeHouseholderInPlace(Scalar& tau, RealScalar& beta) { @@ -51,7 +54,7 @@ void MatrixBase::makeHouseholderInPlace(Scalar& tau, RealScalar& beta) * * On output: * \param essential the essential part of the vector \c v - * \param tau the scaling factor of the householder transformation + * \param tau the scaling factor of the Householder transformation * \param beta the result of H * \c *this * * \sa MatrixBase::makeHouseholderInPlace(), MatrixBase::applyHouseholderOnTheLeft(), @@ -86,6 +89,21 @@ void MatrixBase::makeHouseholder( } } +/** Apply the elementary reflector H given by + * \f$ H = I - tau v v^*\f$ + * with + * \f$ v^T = [1 essential^T] \f$ + * from the left to a vector or matrix. + * + * On input: + * \param essential the essential part of the vector \c v + * \param tau the scaling factor of the Householder transformation + * \param workspace a pointer to working space with at least + * this->cols() * essential.size() entries + * + * \sa MatrixBase::makeHouseholder(), MatrixBase::makeHouseholderInPlace(), + * MatrixBase::applyHouseholderOnTheRight() + */ template template void MatrixBase::applyHouseholderOnTheLeft( @@ -108,6 +126,21 @@ void MatrixBase::applyHouseholderOnTheLeft( } } +/** Apply the elementary reflector H given by + * \f$ H = I - tau v v^*\f$ + * with + * \f$ v^T = [1 essential^T] \f$ + * from the right to a vector or matrix. + * + * On input: + * \param essential the essential part of the vector \c v + * \param tau the scaling factor of the Householder transformation + * \param workspace a pointer to working space with at least + * this->cols() * essential.size() entries + * + * \sa MatrixBase::makeHouseholder(), MatrixBase::makeHouseholderInPlace(), + * MatrixBase::applyHouseholderOnTheLeft() + */ template template void MatrixBase::applyHouseholderOnTheRight( @@ -130,4 +163,6 @@ void MatrixBase::applyHouseholderOnTheRight( } } +} // end namespace Eigen + #endif // EIGEN_HOUSEHOLDER_H diff --git a/extern/Eigen3/Eigen/src/Householder/HouseholderSequence.h b/extern/Eigen3/Eigen/src/Householder/HouseholderSequence.h index 717f29c99e9..1e71e16a785 100644 --- a/extern/Eigen3/Eigen/src/Householder/HouseholderSequence.h +++ b/extern/Eigen3/Eigen/src/Householder/HouseholderSequence.h @@ -4,28 +4,15 @@ // Copyright (C) 2009 Gael Guennebaud // Copyright (C) 2010 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_HOUSEHOLDER_SEQUENCE_H #define EIGEN_HOUSEHOLDER_SEQUENCE_H +namespace Eigen { + /** \ingroup Householder_Module * \householder_module * \class HouseholderSequence @@ -237,13 +224,20 @@ template class HouseholderS ConjugateReturnType inverse() const { return adjoint(); } /** \internal */ - template void evalTo(DestType& dst) const + template inline void evalTo(DestType& dst) const { - Index vecs = m_length; - // FIXME find a way to pass this temporary if the user wants to Matrix temp(rows()); - if( internal::is_same::type,DestType>::value + AutoAlign|ColMajor, DestType::MaxRowsAtCompileTime, 1> workspace(rows()); + evalTo(dst, workspace); + } + + /** \internal */ + template + void evalTo(Dest& dst, Workspace& workspace) const + { + workspace.resize(rows()); + Index vecs = m_length; + if( internal::is_same::type,Dest>::value && internal::extract_data(dst) == internal::extract_data(m_vectors)) { // in-place @@ -254,10 +248,10 @@ template class HouseholderS Index cornerSize = rows() - k - m_shift; if(m_trans) dst.bottomRightCorner(cornerSize, cornerSize) - .applyHouseholderOnTheRight(essentialVector(k), m_coeffs.coeff(k), &temp.coeffRef(0)); + .applyHouseholderOnTheRight(essentialVector(k), m_coeffs.coeff(k), workspace.data()); else dst.bottomRightCorner(cornerSize, cornerSize) - .applyHouseholderOnTheLeft(essentialVector(k), m_coeffs.coeff(k), &temp.coeffRef(0)); + .applyHouseholderOnTheLeft(essentialVector(k), m_coeffs.coeff(k), workspace.data()); // clear the off diagonal vector dst.col(k).tail(rows()-k-1).setZero(); @@ -274,10 +268,10 @@ template class HouseholderS Index cornerSize = rows() - k - m_shift; if(m_trans) dst.bottomRightCorner(cornerSize, cornerSize) - .applyHouseholderOnTheRight(essentialVector(k), m_coeffs.coeff(k), &temp.coeffRef(0)); + .applyHouseholderOnTheRight(essentialVector(k), m_coeffs.coeff(k), &workspace.coeffRef(0)); else dst.bottomRightCorner(cornerSize, cornerSize) - .applyHouseholderOnTheLeft(essentialVector(k), m_coeffs.coeff(k), &temp.coeffRef(0)); + .applyHouseholderOnTheLeft(essentialVector(k), m_coeffs.coeff(k), &workspace.coeffRef(0)); } } } @@ -285,24 +279,40 @@ template class HouseholderS /** \internal */ template inline void applyThisOnTheRight(Dest& dst) const { - Matrix temp(dst.rows()); + Matrix workspace(dst.rows()); + applyThisOnTheRight(dst, workspace); + } + + /** \internal */ + template + inline void applyThisOnTheRight(Dest& dst, Workspace& workspace) const + { + workspace.resize(dst.rows()); for(Index k = 0; k < m_length; ++k) { Index actual_k = m_trans ? m_length-k-1 : k; dst.rightCols(rows()-m_shift-actual_k) - .applyHouseholderOnTheRight(essentialVector(actual_k), m_coeffs.coeff(actual_k), &temp.coeffRef(0)); + .applyHouseholderOnTheRight(essentialVector(actual_k), m_coeffs.coeff(actual_k), workspace.data()); } } /** \internal */ template inline void applyThisOnTheLeft(Dest& dst) const { - Matrix temp(dst.cols()); + Matrix workspace(dst.cols()); + applyThisOnTheLeft(dst, workspace); + } + + /** \internal */ + template + inline void applyThisOnTheLeft(Dest& dst, Workspace& workspace) const + { + workspace.resize(dst.cols()); for(Index k = 0; k < m_length; ++k) { Index actual_k = m_trans ? k : m_length-k-1; dst.bottomRows(rows()-m_shift-actual_k) - .applyHouseholderOnTheLeft(essentialVector(actual_k), m_coeffs.coeff(actual_k), &temp.coeffRef(0)); + .applyHouseholderOnTheLeft(essentialVector(actual_k), m_coeffs.coeff(actual_k), workspace.data()); } } @@ -426,4 +436,6 @@ HouseholderSequence rightHouseholderSequence( return HouseholderSequence(v, h); } +} // end namespace Eigen + #endif // EIGEN_HOUSEHOLDER_SEQUENCE_H diff --git a/extern/Eigen3/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h new file mode 100644 index 00000000000..73ca9bfde6a --- /dev/null +++ b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h @@ -0,0 +1,149 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2011 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_BASIC_PRECONDITIONERS_H +#define EIGEN_BASIC_PRECONDITIONERS_H + +namespace Eigen { + +/** \ingroup IterativeLinearSolvers_Module + * \brief A preconditioner based on the digonal entries + * + * This class allows to approximately solve for A.x = b problems assuming A is a diagonal matrix. + * In other words, this preconditioner neglects all off diagonal entries and, in Eigen's language, solves for: + * \code + * A.diagonal().asDiagonal() . x = b + * \endcode + * + * \tparam _Scalar the type of the scalar. + * + * This preconditioner is suitable for both selfadjoint and general problems. + * The diagonal entries are pre-inverted and stored into a dense vector. + * + * \note A variant that has yet to be implemented would attempt to preserve the norm of each column. + * + */ +template +class DiagonalPreconditioner +{ + typedef _Scalar Scalar; + typedef Matrix Vector; + typedef typename Vector::Index Index; + + public: + // this typedef is only to export the scalar type and compile-time dimensions to solve_retval + typedef Matrix MatrixType; + + DiagonalPreconditioner() : m_isInitialized(false) {} + + template + DiagonalPreconditioner(const MatType& mat) : m_invdiag(mat.cols()) + { + compute(mat); + } + + Index rows() const { return m_invdiag.size(); } + Index cols() const { return m_invdiag.size(); } + + template + DiagonalPreconditioner& analyzePattern(const MatType& ) + { + return *this; + } + + template + DiagonalPreconditioner& factorize(const MatType& mat) + { + m_invdiag.resize(mat.cols()); + for(int j=0; j + DiagonalPreconditioner& compute(const MatType& mat) + { + return factorize(mat); + } + + template + void _solve(const Rhs& b, Dest& x) const + { + x = m_invdiag.array() * b.array() ; + } + + template inline const internal::solve_retval + solve(const MatrixBase& b) const + { + eigen_assert(m_isInitialized && "DiagonalPreconditioner is not initialized."); + eigen_assert(m_invdiag.size()==b.rows() + && "DiagonalPreconditioner::solve(): invalid number of rows of the right hand side matrix b"); + return internal::solve_retval(*this, b.derived()); + } + + protected: + Vector m_invdiag; + bool m_isInitialized; +}; + +namespace internal { + +template +struct solve_retval, Rhs> + : solve_retval_base, Rhs> +{ + typedef DiagonalPreconditioner<_MatrixType> Dec; + EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs) + + template void evalTo(Dest& dst) const + { + dec()._solve(rhs(),dst); + } +}; + +} + +/** \ingroup IterativeLinearSolvers_Module + * \brief A naive preconditioner which approximates any matrix as the identity matrix + * + * \sa class DiagonalPreconditioner + */ +class IdentityPreconditioner +{ + public: + + IdentityPreconditioner() {} + + template + IdentityPreconditioner(const MatrixType& ) {} + + template + IdentityPreconditioner& analyzePattern(const MatrixType& ) { return *this; } + + template + IdentityPreconditioner& factorize(const MatrixType& ) { return *this; } + + template + IdentityPreconditioner& compute(const MatrixType& ) { return *this; } + + template + inline const Rhs& solve(const Rhs& b) const { return b; } +}; + +} // end namespace Eigen + +#endif // EIGEN_BASIC_PRECONDITIONERS_H diff --git a/extern/Eigen3/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h new file mode 100644 index 00000000000..126341be8d8 --- /dev/null +++ b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h @@ -0,0 +1,254 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2011 Gael Guennebaud +// Copyright (C) 2012 Désiré Nuentsa-Wakam +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_BICGSTAB_H +#define EIGEN_BICGSTAB_H + +namespace Eigen { + +namespace internal { + +/** \internal Low-level bi conjugate gradient stabilized algorithm + * \param mat The matrix A + * \param rhs The right hand side vector b + * \param x On input and initial solution, on output the computed solution. + * \param precond A preconditioner being able to efficiently solve for an + * approximation of Ax=b (regardless of b) + * \param iters On input the max number of iteration, on output the number of performed iterations. + * \param tol_error On input the tolerance error, on output an estimation of the relative error. + * \return false in the case of numerical issue, for example a break down of BiCGSTAB. + */ +template +bool bicgstab(const MatrixType& mat, const Rhs& rhs, Dest& x, + const Preconditioner& precond, int& iters, + typename Dest::RealScalar& tol_error) +{ + using std::sqrt; + using std::abs; + typedef typename Dest::RealScalar RealScalar; + typedef typename Dest::Scalar Scalar; + typedef Matrix VectorType; + RealScalar tol = tol_error; + int maxIters = iters; + + int n = mat.cols(); + VectorType r = rhs - mat * x; + VectorType r0 = r; + + RealScalar r0_sqnorm = r0.squaredNorm(); + Scalar rho = 1; + Scalar alpha = 1; + Scalar w = 1; + + VectorType v = VectorType::Zero(n), p = VectorType::Zero(n); + VectorType y(n), z(n); + VectorType kt(n), ks(n); + + VectorType s(n), t(n); + + RealScalar tol2 = tol*tol; + int i = 0; + + while ( r.squaredNorm()/r0_sqnorm > tol2 && i > +class BiCGSTAB; + +namespace internal { + +template< typename _MatrixType, typename _Preconditioner> +struct traits > +{ + typedef _MatrixType MatrixType; + typedef _Preconditioner Preconditioner; +}; + +} + +/** \ingroup IterativeLinearSolvers_Module + * \brief A bi conjugate gradient stabilized solver for sparse square problems + * + * This class allows to solve for A.x = b sparse linear problems using a bi conjugate gradient + * stabilized algorithm. The vectors x and b can be either dense or sparse. + * + * \tparam _MatrixType the type of the sparse matrix A, can be a dense or a sparse matrix. + * \tparam _Preconditioner the type of the preconditioner. Default is DiagonalPreconditioner + * + * The maximal number of iterations and tolerance value can be controlled via the setMaxIterations() + * and setTolerance() methods. The defaults are the size of the problem for the maximal number of iterations + * and NumTraits::epsilon() for the tolerance. + * + * This class can be used as the direct solver classes. Here is a typical usage example: + * \code + * int n = 10000; + * VectorXd x(n), b(n); + * SparseMatrix A(n,n); + * // fill A and b + * BiCGSTAB > solver; + * solver(A); + * x = solver.solve(b); + * std::cout << "#iterations: " << solver.iterations() << std::endl; + * std::cout << "estimated error: " << solver.error() << std::endl; + * // update b, and solve again + * x = solver.solve(b); + * \endcode + * + * By default the iterations start with x=0 as an initial guess of the solution. + * One can control the start using the solveWithGuess() method. Here is a step by + * step execution example starting with a random guess and printing the evolution + * of the estimated error: + * * \code + * x = VectorXd::Random(n); + * solver.setMaxIterations(1); + * int i = 0; + * do { + * x = solver.solveWithGuess(b,x); + * std::cout << i << " : " << solver.error() << std::endl; + * ++i; + * } while (solver.info()!=Success && i<100); + * \endcode + * Note that such a step by step excution is slightly slower. + * + * \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner + */ +template< typename _MatrixType, typename _Preconditioner> +class BiCGSTAB : public IterativeSolverBase > +{ + typedef IterativeSolverBase Base; + using Base::mp_matrix; + using Base::m_error; + using Base::m_iterations; + using Base::m_info; + using Base::m_isInitialized; +public: + typedef _MatrixType MatrixType; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::Index Index; + typedef typename MatrixType::RealScalar RealScalar; + typedef _Preconditioner Preconditioner; + +public: + + /** Default constructor. */ + BiCGSTAB() : Base() {} + + /** Initialize the solver with matrix \a A for further \c Ax=b solving. + * + * This constructor is a shortcut for the default constructor followed + * by a call to compute(). + * + * \warning this class stores a reference to the matrix A as well as some + * precomputed values that depend on it. Therefore, if \a A is changed + * this class becomes invalid. Call compute() to update it with the new + * matrix A, or modify a copy of A. + */ + BiCGSTAB(const MatrixType& A) : Base(A) {} + + ~BiCGSTAB() {} + + /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A + * \a x0 as an initial solution. + * + * \sa compute() + */ + template + inline const internal::solve_retval_with_guess + solveWithGuess(const MatrixBase& b, const Guess& x0) const + { + eigen_assert(m_isInitialized && "BiCGSTAB is not initialized."); + eigen_assert(Base::rows()==b.rows() + && "BiCGSTAB::solve(): invalid number of rows of the right hand side matrix b"); + return internal::solve_retval_with_guess + (*this, b.derived(), x0); + } + + /** \internal */ + template + void _solveWithGuess(const Rhs& b, Dest& x) const + { + bool failed = false; + for(int j=0; j + void _solve(const Rhs& b, Dest& x) const + { + x.setZero(); + _solveWithGuess(b,x); + } + +protected: + +}; + + +namespace internal { + + template +struct solve_retval, Rhs> + : solve_retval_base, Rhs> +{ + typedef BiCGSTAB<_MatrixType, _Preconditioner> Dec; + EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs) + + template void evalTo(Dest& dst) const + { + dec()._solve(rhs(),dst); + } +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_BICGSTAB_H diff --git a/extern/Eigen3/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h new file mode 100644 index 00000000000..f64f2534d28 --- /dev/null +++ b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h @@ -0,0 +1,251 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2011 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_CONJUGATE_GRADIENT_H +#define EIGEN_CONJUGATE_GRADIENT_H + +namespace Eigen { + +namespace internal { + +/** \internal Low-level conjugate gradient algorithm + * \param mat The matrix A + * \param rhs The right hand side vector b + * \param x On input and initial solution, on output the computed solution. + * \param precond A preconditioner being able to efficiently solve for an + * approximation of Ax=b (regardless of b) + * \param iters On input the max number of iteration, on output the number of performed iterations. + * \param tol_error On input the tolerance error, on output an estimation of the relative error. + */ +template +EIGEN_DONT_INLINE +void conjugate_gradient(const MatrixType& mat, const Rhs& rhs, Dest& x, + const Preconditioner& precond, int& iters, + typename Dest::RealScalar& tol_error) +{ + using std::sqrt; + using std::abs; + typedef typename Dest::RealScalar RealScalar; + typedef typename Dest::Scalar Scalar; + typedef Matrix VectorType; + + RealScalar tol = tol_error; + int maxIters = iters; + + int n = mat.cols(); + + VectorType residual = rhs - mat * x; //initial residual + VectorType p(n); + + p = precond.solve(residual); //initial search direction + + VectorType z(n), tmp(n); + RealScalar absNew = internal::real(residual.dot(p)); // the square of the absolute value of r scaled by invM + RealScalar rhsNorm2 = rhs.squaredNorm(); + RealScalar residualNorm2 = 0; + RealScalar threshold = tol*tol*rhsNorm2; + int i = 0; + while(i < maxIters) + { + tmp.noalias() = mat * p; // the bottleneck of the algorithm + + Scalar alpha = absNew / p.dot(tmp); // the amount we travel on dir + x += alpha * p; // update solution + residual -= alpha * tmp; // update residue + + residualNorm2 = residual.squaredNorm(); + if(residualNorm2 < threshold) + break; + + z = precond.solve(residual); // approximately solve for "A z = residual" + + RealScalar absOld = absNew; + absNew = internal::real(residual.dot(z)); // update the absolute value of r + RealScalar beta = absNew / absOld; // calculate the Gram-Schmidt value used to create the new search direction + p = z + beta * p; // update search direction + i++; + } + tol_error = sqrt(residualNorm2 / rhsNorm2); + iters = i; +} + +} + +template< typename _MatrixType, int _UpLo=Lower, + typename _Preconditioner = DiagonalPreconditioner > +class ConjugateGradient; + +namespace internal { + +template< typename _MatrixType, int _UpLo, typename _Preconditioner> +struct traits > +{ + typedef _MatrixType MatrixType; + typedef _Preconditioner Preconditioner; +}; + +} + +/** \ingroup IterativeLinearSolvers_Module + * \brief A conjugate gradient solver for sparse self-adjoint problems + * + * This class allows to solve for A.x = b sparse linear problems using a conjugate gradient algorithm. + * The sparse matrix A must be selfadjoint. The vectors x and b can be either dense or sparse. + * + * \tparam _MatrixType the type of the sparse matrix A, can be a dense or a sparse matrix. + * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower + * or Upper. Default is Lower. + * \tparam _Preconditioner the type of the preconditioner. Default is DiagonalPreconditioner + * + * The maximal number of iterations and tolerance value can be controlled via the setMaxIterations() + * and setTolerance() methods. The defaults are the size of the problem for the maximal number of iterations + * and NumTraits::epsilon() for the tolerance. + * + * This class can be used as the direct solver classes. Here is a typical usage example: + * \code + * int n = 10000; + * VectorXd x(n), b(n); + * SparseMatrix A(n,n); + * // fill A and b + * ConjugateGradient > cg; + * cg.compute(A); + * x = cg.solve(b); + * std::cout << "#iterations: " << cg.iterations() << std::endl; + * std::cout << "estimated error: " << cg.error() << std::endl; + * // update b, and solve again + * x = cg.solve(b); + * \endcode + * + * By default the iterations start with x=0 as an initial guess of the solution. + * One can control the start using the solveWithGuess() method. Here is a step by + * step execution example starting with a random guess and printing the evolution + * of the estimated error: + * * \code + * x = VectorXd::Random(n); + * cg.setMaxIterations(1); + * int i = 0; + * do { + * x = cg.solveWithGuess(b,x); + * std::cout << i << " : " << cg.error() << std::endl; + * ++i; + * } while (cg.info()!=Success && i<100); + * \endcode + * Note that such a step by step excution is slightly slower. + * + * \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner + */ +template< typename _MatrixType, int _UpLo, typename _Preconditioner> +class ConjugateGradient : public IterativeSolverBase > +{ + typedef IterativeSolverBase Base; + using Base::mp_matrix; + using Base::m_error; + using Base::m_iterations; + using Base::m_info; + using Base::m_isInitialized; +public: + typedef _MatrixType MatrixType; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::Index Index; + typedef typename MatrixType::RealScalar RealScalar; + typedef _Preconditioner Preconditioner; + + enum { + UpLo = _UpLo + }; + +public: + + /** Default constructor. */ + ConjugateGradient() : Base() {} + + /** Initialize the solver with matrix \a A for further \c Ax=b solving. + * + * This constructor is a shortcut for the default constructor followed + * by a call to compute(). + * + * \warning this class stores a reference to the matrix A as well as some + * precomputed values that depend on it. Therefore, if \a A is changed + * this class becomes invalid. Call compute() to update it with the new + * matrix A, or modify a copy of A. + */ + ConjugateGradient(const MatrixType& A) : Base(A) {} + + ~ConjugateGradient() {} + + /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A + * \a x0 as an initial solution. + * + * \sa compute() + */ + template + inline const internal::solve_retval_with_guess + solveWithGuess(const MatrixBase& b, const Guess& x0) const + { + eigen_assert(m_isInitialized && "ConjugateGradient is not initialized."); + eigen_assert(Base::rows()==b.rows() + && "ConjugateGradient::solve(): invalid number of rows of the right hand side matrix b"); + return internal::solve_retval_with_guess + (*this, b.derived(), x0); + } + + /** \internal */ + template + void _solveWithGuess(const Rhs& b, Dest& x) const + { + m_iterations = Base::maxIterations(); + m_error = Base::m_tolerance; + + for(int j=0; jtemplate selfadjointView(), b.col(j), xj, + Base::m_preconditioner, m_iterations, m_error); + } + + m_isInitialized = true; + m_info = m_error <= Base::m_tolerance ? Success : NoConvergence; + } + + /** \internal */ + template + void _solve(const Rhs& b, Dest& x) const + { + x.setOnes(); + _solveWithGuess(b,x); + } + +protected: + +}; + + +namespace internal { + +template +struct solve_retval, Rhs> + : solve_retval_base, Rhs> +{ + typedef ConjugateGradient<_MatrixType,_UpLo,_Preconditioner> Dec; + EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs) + + template void evalTo(Dest& dst) const + { + dec()._solve(rhs(),dst); + } +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_CONJUGATE_GRADIENT_H diff --git a/extern/Eigen3/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h new file mode 100644 index 00000000000..224304f0eb8 --- /dev/null +++ b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h @@ -0,0 +1,466 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2012 Désiré Nuentsa-Wakam +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_INCOMPLETE_LUT_H +#define EIGEN_INCOMPLETE_LUT_H + +namespace Eigen { + +/** + * \brief Incomplete LU factorization with dual-threshold strategy + * During the numerical factorization, two dropping rules are used : + * 1) any element whose magnitude is less than some tolerance is dropped. + * This tolerance is obtained by multiplying the input tolerance @p droptol + * by the average magnitude of all the original elements in the current row. + * 2) After the elimination of the row, only the @p fill largest elements in + * the L part and the @p fill largest elements in the U part are kept + * (in addition to the diagonal element ). Note that @p fill is computed from + * the input parameter @p fillfactor which is used the ratio to control the fill_in + * relatively to the initial number of nonzero elements. + * + * The two extreme cases are when @p droptol=0 (to keep all the @p fill*2 largest elements) + * and when @p fill=n/2 with @p droptol being different to zero. + * + * References : Yousef Saad, ILUT: A dual threshold incomplete LU factorization, + * Numerical Linear Algebra with Applications, 1(4), pp 387-402, 1994. + * + * NOTE : The following implementation is derived from the ILUT implementation + * in the SPARSKIT package, Copyright (C) 2005, the Regents of the University of Minnesota + * released under the terms of the GNU LGPL: + * http://www-users.cs.umn.edu/~saad/software/SPARSKIT/README + * However, Yousef Saad gave us permission to relicense his ILUT code to MPL2. + * See the Eigen mailing list archive, thread: ILUT, date: July 8, 2012: + * http://listengine.tuxfamily.org/lists.tuxfamily.org/eigen/2012/07/msg00064.html + * alternatively, on GMANE: + * http://comments.gmane.org/gmane.comp.lib.eigen/3302 + */ +template +class IncompleteLUT : internal::noncopyable +{ + typedef _Scalar Scalar; + typedef typename NumTraits::Real RealScalar; + typedef Matrix Vector; + typedef SparseMatrix FactorType; + typedef SparseMatrix PermutType; + typedef typename FactorType::Index Index; + + public: + typedef Matrix MatrixType; + + IncompleteLUT() + : m_droptol(NumTraits::dummy_precision()), m_fillfactor(10), + m_analysisIsOk(false), m_factorizationIsOk(false), m_isInitialized(false) + {} + + template + IncompleteLUT(const MatrixType& mat, RealScalar droptol=NumTraits::dummy_precision(), int fillfactor = 10) + : m_droptol(droptol),m_fillfactor(fillfactor), + m_analysisIsOk(false),m_factorizationIsOk(false),m_isInitialized(false) + { + eigen_assert(fillfactor != 0); + compute(mat); + } + + Index rows() const { return m_lu.rows(); } + + Index cols() const { return m_lu.cols(); } + + /** \brief Reports whether previous computation was successful. + * + * \returns \c Success if computation was succesful, + * \c NumericalIssue if the matrix.appears to be negative. + */ + ComputationInfo info() const + { + eigen_assert(m_isInitialized && "IncompleteLUT is not initialized."); + return m_info; + } + + template + void analyzePattern(const MatrixType& amat); + + template + void factorize(const MatrixType& amat); + + /** + * Compute an incomplete LU factorization with dual threshold on the matrix mat + * No pivoting is done in this version + * + **/ + template + IncompleteLUT& compute(const MatrixType& amat) + { + analyzePattern(amat); + factorize(amat); + eigen_assert(m_factorizationIsOk == true); + m_isInitialized = true; + return *this; + } + + void setDroptol(RealScalar droptol); + void setFillfactor(int fillfactor); + + template + void _solve(const Rhs& b, Dest& x) const + { + x = m_Pinv * b; + x = m_lu.template triangularView().solve(x); + x = m_lu.template triangularView().solve(x); + x = m_P * x; + } + + template inline const internal::solve_retval + solve(const MatrixBase& b) const + { + eigen_assert(m_isInitialized && "IncompleteLUT is not initialized."); + eigen_assert(cols()==b.rows() + && "IncompleteLUT::solve(): invalid number of rows of the right hand side matrix b"); + return internal::solve_retval(*this, b.derived()); + } + +protected: + + template + int QuickSplit(VectorV &row, VectorI &ind, int ncut); + + + /** keeps off-diagonal entries; drops diagonal entries */ + struct keep_diag { + inline bool operator() (const Index& row, const Index& col, const Scalar&) const + { + return row!=col; + } + }; + +protected: + + FactorType m_lu; + RealScalar m_droptol; + int m_fillfactor; + bool m_analysisIsOk; + bool m_factorizationIsOk; + bool m_isInitialized; + ComputationInfo m_info; + PermutationMatrix m_P; // Fill-reducing permutation + PermutationMatrix m_Pinv; // Inverse permutation +}; + +/** + * Set control parameter droptol + * \param droptol Drop any element whose magnitude is less than this tolerance + **/ +template +void IncompleteLUT::setDroptol(RealScalar droptol) +{ + this->m_droptol = droptol; +} + +/** + * Set control parameter fillfactor + * \param fillfactor This is used to compute the number @p fill_in of largest elements to keep on each row. + **/ +template +void IncompleteLUT::setFillfactor(int fillfactor) +{ + this->m_fillfactor = fillfactor; +} + + +/** + * Compute a quick-sort split of a vector + * On output, the vector row is permuted such that its elements satisfy + * abs(row(i)) >= abs(row(ncut)) if incut + * \param row The vector of values + * \param ind The array of index for the elements in @p row + * \param ncut The number of largest elements to keep + **/ +template +template +int IncompleteLUT::QuickSplit(VectorV &row, VectorI &ind, int ncut) +{ + using std::swap; + int mid; + int n = row.size(); /* length of the vector */ + int first, last ; + + ncut--; /* to fit the zero-based indices */ + first = 0; + last = n-1; + if (ncut < first || ncut > last ) return 0; + + do { + mid = first; + RealScalar abskey = std::abs(row(mid)); + for (int j = first + 1; j <= last; j++) { + if ( std::abs(row(j)) > abskey) { + ++mid; + swap(row(mid), row(j)); + swap(ind(mid), ind(j)); + } + } + /* Interchange for the pivot element */ + swap(row(mid), row(first)); + swap(ind(mid), ind(first)); + + if (mid > ncut) last = mid - 1; + else if (mid < ncut ) first = mid + 1; + } while (mid != ncut ); + + return 0; /* mid is equal to ncut */ +} + +template +template +void IncompleteLUT::analyzePattern(const _MatrixType& amat) +{ + // Compute the Fill-reducing permutation + SparseMatrix mat1 = amat; + SparseMatrix mat2 = amat.transpose(); + // Symmetrize the pattern + // FIXME for a matrix with nearly symmetric pattern, mat2+mat1 is the appropriate choice. + // on the other hand for a really non-symmetric pattern, mat2*mat1 should be prefered... + SparseMatrix AtA = mat2 + mat1; + AtA.prune(keep_diag()); + internal::minimum_degree_ordering(AtA, m_P); // Then compute the AMD ordering... + + m_Pinv = m_P.inverse(); // ... and the inverse permutation + + m_analysisIsOk = true; +} + +template +template +void IncompleteLUT::factorize(const _MatrixType& amat) +{ + using std::sqrt; + using std::swap; + using std::abs; + + eigen_assert((amat.rows() == amat.cols()) && "The factorization should be done on a square matrix"); + int n = amat.cols(); // Size of the matrix + m_lu.resize(n,n); + // Declare Working vectors and variables + Vector u(n) ; // real values of the row -- maximum size is n -- + VectorXi ju(n); // column position of the values in u -- maximum size is n + VectorXi jr(n); // Indicate the position of the nonzero elements in the vector u -- A zero location is indicated by -1 + + // Apply the fill-reducing permutation + eigen_assert(m_analysisIsOk && "You must first call analyzePattern()"); + SparseMatrix mat; + mat = amat.twistedBy(m_Pinv); + + // Initialization + jr.fill(-1); + ju.fill(0); + u.fill(0); + + // number of largest elements to keep in each row: + int fill_in = static_cast (amat.nonZeros()*m_fillfactor)/n+1; + if (fill_in > n) fill_in = n; + + // number of largest nonzero elements to keep in the L and the U part of the current row: + int nnzL = fill_in/2; + int nnzU = nnzL; + m_lu.reserve(n * (nnzL + nnzU + 1)); + + // global loop over the rows of the sparse matrix + for (int ii = 0; ii < n; ii++) + { + // 1 - copy the lower and the upper part of the row i of mat in the working vector u + + int sizeu = 1; // number of nonzero elements in the upper part of the current row + int sizel = 0; // number of nonzero elements in the lower part of the current row + ju(ii) = ii; + u(ii) = 0; + jr(ii) = ii; + RealScalar rownorm = 0; + + typename FactorType::InnerIterator j_it(mat, ii); // Iterate through the current row ii + for (; j_it; ++j_it) + { + int k = j_it.index(); + if (k < ii) + { + // copy the lower part + ju(sizel) = k; + u(sizel) = j_it.value(); + jr(k) = sizel; + ++sizel; + } + else if (k == ii) + { + u(ii) = j_it.value(); + } + else + { + // copy the upper part + int jpos = ii + sizeu; + ju(jpos) = k; + u(jpos) = j_it.value(); + jr(k) = jpos; + ++sizeu; + } + rownorm += internal::abs2(j_it.value()); + } + + // 2 - detect possible zero row + if(rownorm==0) + { + m_info = NumericalIssue; + return; + } + // Take the 2-norm of the current row as a relative tolerance + rownorm = sqrt(rownorm); + + // 3 - eliminate the previous nonzero rows + int jj = 0; + int len = 0; + while (jj < sizel) + { + // In order to eliminate in the correct order, + // we must select first the smallest column index among ju(jj:sizel) + int k; + int minrow = ju.segment(jj,sizel-jj).minCoeff(&k); // k is relative to the segment + k += jj; + if (minrow != ju(jj)) + { + // swap the two locations + int j = ju(jj); + swap(ju(jj), ju(k)); + jr(minrow) = jj; jr(j) = k; + swap(u(jj), u(k)); + } + // Reset this location + jr(minrow) = -1; + + // Start elimination + typename FactorType::InnerIterator ki_it(m_lu, minrow); + while (ki_it && ki_it.index() < minrow) ++ki_it; + eigen_internal_assert(ki_it && ki_it.col()==minrow); + Scalar fact = u(jj) / ki_it.value(); + + // drop too small elements + if(abs(fact) <= m_droptol) + { + jj++; + continue; + } + + // linear combination of the current row ii and the row minrow + ++ki_it; + for (; ki_it; ++ki_it) + { + Scalar prod = fact * ki_it.value(); + int j = ki_it.index(); + int jpos = jr(j); + if (jpos == -1) // fill-in element + { + int newpos; + if (j >= ii) // dealing with the upper part + { + newpos = ii + sizeu; + sizeu++; + eigen_internal_assert(sizeu<=n); + } + else // dealing with the lower part + { + newpos = sizel; + sizel++; + eigen_internal_assert(sizel<=ii); + } + ju(newpos) = j; + u(newpos) = -prod; + jr(j) = newpos; + } + else + u(jpos) -= prod; + } + // store the pivot element + u(len) = fact; + ju(len) = minrow; + ++len; + + jj++; + } // end of the elimination on the row ii + + // reset the upper part of the pointer jr to zero + for(int k = 0; k m_droptol * rownorm ) + { + ++len; + u(ii + len) = u(ii + k); + ju(ii + len) = ju(ii + k); + } + } + sizeu = len + 1; // +1 to take into account the diagonal element + len = (std::min)(sizeu, nnzU); + typename Vector::SegmentReturnType uu(u.segment(ii+1, sizeu-1)); + typename VectorXi::SegmentReturnType juu(ju.segment(ii+1, sizeu-1)); + QuickSplit(uu, juu, len); + + // store the largest elements of the U part + for(int k = ii + 1; k < ii + len; k++) + m_lu.insertBackByOuterInnerUnordered(ii,ju(k)) = u(k); + } + + m_lu.finalize(); + m_lu.makeCompressed(); + + m_factorizationIsOk = true; + m_info = Success; +} + +namespace internal { + +template +struct solve_retval, Rhs> + : solve_retval_base, Rhs> +{ + typedef IncompleteLUT<_MatrixType> Dec; + EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs) + + template void evalTo(Dest& dst) const + { + dec()._solve(rhs(),dst); + } +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_INCOMPLETE_LUT_H + diff --git a/extern/Eigen3/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h new file mode 100644 index 00000000000..11706cebabd --- /dev/null +++ b/extern/Eigen3/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h @@ -0,0 +1,254 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2011 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_ITERATIVE_SOLVER_BASE_H +#define EIGEN_ITERATIVE_SOLVER_BASE_H + +namespace Eigen { + +/** \ingroup IterativeLinearSolvers_Module + * \brief Base class for linear iterative solvers + * + * \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner + */ +template< typename Derived> +class IterativeSolverBase : internal::noncopyable +{ +public: + typedef typename internal::traits::MatrixType MatrixType; + typedef typename internal::traits::Preconditioner Preconditioner; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::Index Index; + typedef typename MatrixType::RealScalar RealScalar; + +public: + + Derived& derived() { return *static_cast(this); } + const Derived& derived() const { return *static_cast(this); } + + /** Default constructor. */ + IterativeSolverBase() + : mp_matrix(0) + { + init(); + } + + /** Initialize the solver with matrix \a A for further \c Ax=b solving. + * + * This constructor is a shortcut for the default constructor followed + * by a call to compute(). + * + * \warning this class stores a reference to the matrix A as well as some + * precomputed values that depend on it. Therefore, if \a A is changed + * this class becomes invalid. Call compute() to update it with the new + * matrix A, or modify a copy of A. + */ + IterativeSolverBase(const MatrixType& A) + { + init(); + compute(A); + } + + ~IterativeSolverBase() {} + + /** Initializes the iterative solver for the sparcity pattern of the matrix \a A for further solving \c Ax=b problems. + * + * Currently, this function mostly call analyzePattern on the preconditioner. In the future + * we might, for instance, implement column reodering for faster matrix vector products. + */ + Derived& analyzePattern(const MatrixType& A) + { + m_preconditioner.analyzePattern(A); + m_isInitialized = true; + m_analysisIsOk = true; + m_info = Success; + return derived(); + } + + /** Initializes the iterative solver with the numerical values of the matrix \a A for further solving \c Ax=b problems. + * + * Currently, this function mostly call factorize on the preconditioner. + * + * \warning this class stores a reference to the matrix A as well as some + * precomputed values that depend on it. Therefore, if \a A is changed + * this class becomes invalid. Call compute() to update it with the new + * matrix A, or modify a copy of A. + */ + Derived& factorize(const MatrixType& A) + { + eigen_assert(m_analysisIsOk && "You must first call analyzePattern()"); + mp_matrix = &A; + m_preconditioner.factorize(A); + m_factorizationIsOk = true; + m_info = Success; + return derived(); + } + + /** Initializes the iterative solver with the matrix \a A for further solving \c Ax=b problems. + * + * Currently, this function mostly initialized/compute the preconditioner. In the future + * we might, for instance, implement column reodering for faster matrix vector products. + * + * \warning this class stores a reference to the matrix A as well as some + * precomputed values that depend on it. Therefore, if \a A is changed + * this class becomes invalid. Call compute() to update it with the new + * matrix A, or modify a copy of A. + */ + Derived& compute(const MatrixType& A) + { + mp_matrix = &A; + m_preconditioner.compute(A); + m_isInitialized = true; + m_analysisIsOk = true; + m_factorizationIsOk = true; + m_info = Success; + return derived(); + } + + /** \internal */ + Index rows() const { return mp_matrix ? mp_matrix->rows() : 0; } + /** \internal */ + Index cols() const { return mp_matrix ? mp_matrix->cols() : 0; } + + /** \returns the tolerance threshold used by the stopping criteria */ + RealScalar tolerance() const { return m_tolerance; } + + /** Sets the tolerance threshold used by the stopping criteria */ + Derived& setTolerance(RealScalar tolerance) + { + m_tolerance = tolerance; + return derived(); + } + + /** \returns a read-write reference to the preconditioner for custom configuration. */ + Preconditioner& preconditioner() { return m_preconditioner; } + + /** \returns a read-only reference to the preconditioner. */ + const Preconditioner& preconditioner() const { return m_preconditioner; } + + /** \returns the max number of iterations */ + int maxIterations() const + { + return (mp_matrix && m_maxIterations<0) ? mp_matrix->cols() : m_maxIterations; + } + + /** Sets the max number of iterations */ + Derived& setMaxIterations(int maxIters) + { + m_maxIterations = maxIters; + return derived(); + } + + /** \returns the number of iterations performed during the last solve */ + int iterations() const + { + eigen_assert(m_isInitialized && "ConjugateGradient is not initialized."); + return m_iterations; + } + + /** \returns the tolerance error reached during the last solve */ + RealScalar error() const + { + eigen_assert(m_isInitialized && "ConjugateGradient is not initialized."); + return m_error; + } + + /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. + * + * \sa compute() + */ + template inline const internal::solve_retval + solve(const MatrixBase& b) const + { + eigen_assert(m_isInitialized && "IterativeSolverBase is not initialized."); + eigen_assert(rows()==b.rows() + && "IterativeSolverBase::solve(): invalid number of rows of the right hand side matrix b"); + return internal::solve_retval(derived(), b.derived()); + } + + /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. + * + * \sa compute() + */ + template + inline const internal::sparse_solve_retval + solve(const SparseMatrixBase& b) const + { + eigen_assert(m_isInitialized && "IterativeSolverBase is not initialized."); + eigen_assert(rows()==b.rows() + && "IterativeSolverBase::solve(): invalid number of rows of the right hand side matrix b"); + return internal::sparse_solve_retval(*this, b.derived()); + } + + /** \returns Success if the iterations converged, and NoConvergence otherwise. */ + ComputationInfo info() const + { + eigen_assert(m_isInitialized && "IterativeSolverBase is not initialized."); + return m_info; + } + + /** \internal */ + template + void _solve_sparse(const Rhs& b, SparseMatrix &dest) const + { + eigen_assert(rows()==b.rows()); + + int rhsCols = b.cols(); + int size = b.rows(); + Eigen::Matrix tb(size); + Eigen::Matrix tx(size); + for(int k=0; k::epsilon(); + } + const MatrixType* mp_matrix; + Preconditioner m_preconditioner; + + int m_maxIterations; + RealScalar m_tolerance; + + mutable RealScalar m_error; + mutable int m_iterations; + mutable ComputationInfo m_info; + mutable bool m_isInitialized, m_analysisIsOk, m_factorizationIsOk; +}; + +namespace internal { + +template +struct sparse_solve_retval, Rhs> + : sparse_solve_retval_base, Rhs> +{ + typedef IterativeSolverBase Dec; + EIGEN_MAKE_SPARSE_SOLVE_HELPERS(Dec,Rhs) + + template void evalTo(Dest& dst) const + { + dec().derived()._solve_sparse(rhs(),dst); + } +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_ITERATIVE_SOLVER_BASE_H diff --git a/extern/Eigen3/Eigen/src/Jacobi/Jacobi.h b/extern/Eigen3/Eigen/src/Jacobi/Jacobi.h index 98dea6800bc..a9c17dcdf19 100644 --- a/extern/Eigen3/Eigen/src/Jacobi/Jacobi.h +++ b/extern/Eigen3/Eigen/src/Jacobi/Jacobi.h @@ -4,28 +4,15 @@ // Copyright (C) 2009 Benoit Jacob // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_JACOBI_H #define EIGEN_JACOBI_H +namespace Eigen { + /** \ingroup Jacobi_Module * \jacobi_module * \class JacobiRotation @@ -326,7 +313,7 @@ void /*EIGEN_DONT_INLINE*/ apply_rotation_in_the_plane(VectorX& _x, VectorY& _y, // both vectors are sequentially stored in memory => vectorization enum { Peeling = 2 }; - Index alignedStart = first_aligned(y, size); + Index alignedStart = internal::first_aligned(y, size); Index alignedEnd = alignedStart + ((size-alignedStart)/PacketSize)*PacketSize; const Packet pc = pset1(j.c()); @@ -344,7 +331,7 @@ void /*EIGEN_DONT_INLINE*/ apply_rotation_in_the_plane(VectorX& _x, VectorY& _y, Scalar* EIGEN_RESTRICT px = x + alignedStart; Scalar* EIGEN_RESTRICT py = y + alignedStart; - if(first_aligned(x, size)==alignedStart) + if(internal::first_aligned(x, size)==alignedStart) { for(Index i=alignedStart; i // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_DETERMINANT_H #define EIGEN_DETERMINANT_H +namespace Eigen { + namespace internal { template @@ -109,4 +96,6 @@ inline typename internal::traits::Scalar MatrixBase::determina return internal::determinant_impl::type>::run(derived()); } +} // end namespace Eigen + #endif // EIGEN_DETERMINANT_H diff --git a/extern/Eigen3/Eigen/src/LU/FullPivLU.h b/extern/Eigen3/Eigen/src/LU/FullPivLU.h index 46ae7d651c8..e23f96cdcf1 100644 --- a/extern/Eigen3/Eigen/src/LU/FullPivLU.h +++ b/extern/Eigen3/Eigen/src/LU/FullPivLU.h @@ -3,28 +3,15 @@ // // Copyright (C) 2006-2009 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_LU_H #define EIGEN_LU_H +namespace Eigen { + /** \ingroup LU_Module * * \class FullPivLU @@ -282,6 +269,7 @@ template class FullPivLU FullPivLU& setThreshold(Default_t) { m_usePrescribedThreshold = false; + return *this; } /** Returns the threshold that will be used by certain methods such as rank(). @@ -743,4 +731,6 @@ MatrixBase::fullPivLu() const return FullPivLU(eval()); } +} // end namespace Eigen + #endif // EIGEN_LU_H diff --git a/extern/Eigen3/Eigen/src/LU/Inverse.h b/extern/Eigen3/Eigen/src/LU/Inverse.h index 2d3e6d10529..39b8cdbc8dc 100644 --- a/extern/Eigen3/Eigen/src/LU/Inverse.h +++ b/extern/Eigen3/Eigen/src/LU/Inverse.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008-2010 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_INVERSE_H #define EIGEN_INVERSE_H +namespace Eigen { + namespace internal { /********************************** @@ -286,7 +273,7 @@ struct inverse_impl : public ReturnByValue > typedef typename MatrixType::Index Index; typedef typename internal::eval::type MatrixTypeNested; typedef typename remove_all::type MatrixTypeNestedCleaned; - const MatrixTypeNested m_matrix; + MatrixTypeNested m_matrix; inverse_impl(const MatrixType& matrix) : m_matrix(matrix) @@ -404,4 +391,6 @@ inline void MatrixBase::computeInverseWithCheck( computeInverseAndDetWithCheck(inverse,determinant,invertible,absDeterminantThreshold); } +} // end namespace Eigen + #endif // EIGEN_INVERSE_H diff --git a/extern/Eigen3/Eigen/src/LU/PartialPivLU.h b/extern/Eigen3/Eigen/src/LU/PartialPivLU.h index 09394b01f5b..c9ff9dd5a36 100644 --- a/extern/Eigen3/Eigen/src/LU/PartialPivLU.h +++ b/extern/Eigen3/Eigen/src/LU/PartialPivLU.h @@ -4,28 +4,15 @@ // Copyright (C) 2006-2009 Benoit Jacob // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_PARTIALLU_H #define EIGEN_PARTIALLU_H +namespace Eigen { + /** \ingroup LU_Module * * \class PartialPivLU @@ -506,4 +493,6 @@ MatrixBase::lu() const } #endif +} // end namespace Eigen + #endif // EIGEN_PARTIALLU_H diff --git a/extern/Eigen3/Eigen/src/LU/PartialPivLU_MKL.h b/extern/Eigen3/Eigen/src/LU/PartialPivLU_MKL.h new file mode 100644 index 00000000000..9035953c82f --- /dev/null +++ b/extern/Eigen3/Eigen/src/LU/PartialPivLU_MKL.h @@ -0,0 +1,85 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + 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 Intel Corporation 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. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL + * LU decomposition with partial pivoting based on LAPACKE_?getrf function. + ******************************************************************************** +*/ + +#ifndef EIGEN_PARTIALLU_LAPACK_H +#define EIGEN_PARTIALLU_LAPACK_H + +#include "Eigen/src/Core/util/MKL_support.h" + +namespace Eigen { + +namespace internal { + +/** \internal Specialization for the data types supported by MKL */ + +#define EIGEN_MKL_LU_PARTPIV(EIGTYPE, MKLTYPE, MKLPREFIX) \ +template \ +struct partial_lu_impl \ +{ \ + /* \internal performs the LU decomposition in-place of the matrix represented */ \ + static lapack_int blocked_lu(lapack_int rows, lapack_int cols, EIGTYPE* lu_data, lapack_int luStride, lapack_int* row_transpositions, lapack_int& nb_transpositions, lapack_int maxBlockSize=256) \ + { \ + EIGEN_UNUSED_VARIABLE(maxBlockSize);\ + lapack_int matrix_order, first_zero_pivot; \ + lapack_int m, n, lda, *ipiv, info; \ + EIGTYPE* a; \ +/* Set up parameters for ?getrf */ \ + matrix_order = StorageOrder==RowMajor ? LAPACK_ROW_MAJOR : LAPACK_COL_MAJOR; \ + lda = luStride; \ + a = lu_data; \ + ipiv = row_transpositions; \ + m = rows; \ + n = cols; \ + nb_transpositions = 0; \ +\ + info = LAPACKE_##MKLPREFIX##getrf( matrix_order, m, n, (MKLTYPE*)a, lda, ipiv ); \ +\ + for(int i=0;i= 0); \ +/* something should be done with nb_transpositions */ \ +\ + first_zero_pivot = info; \ + return first_zero_pivot; \ + } \ +}; + +EIGEN_MKL_LU_PARTPIV(double, double, d) +EIGEN_MKL_LU_PARTPIV(float, float, s) +EIGEN_MKL_LU_PARTPIV(dcomplex, MKL_Complex16, z) +EIGEN_MKL_LU_PARTPIV(scomplex, MKL_Complex8, c) + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_PARTIALLU_LAPACK_H diff --git a/extern/Eigen3/Eigen/src/LU/arch/Inverse_SSE.h b/extern/Eigen3/Eigen/src/LU/arch/Inverse_SSE.h index 4c6153f0aff..60b7a23763e 100644 --- a/extern/Eigen3/Eigen/src/LU/arch/Inverse_SSE.h +++ b/extern/Eigen3/Eigen/src/LU/arch/Inverse_SSE.h @@ -5,24 +5,9 @@ // Copyright (C) 2010 Gael Guennebaud // Copyright (C) 2009 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. // The SSE code for the 4x4 float and double matrix inverse in this file // comes from the following Intel's library: @@ -42,6 +27,8 @@ #ifndef EIGEN_INVERSE_SSE_H #define EIGEN_INVERSE_SSE_H +namespace Eigen { + namespace internal { template @@ -335,6 +322,8 @@ struct compute_inverse_size4 } }; -} +} // end namespace internal + +} // end namespace Eigen #endif // EIGEN_INVERSE_SSE_H diff --git a/extern/Eigen3/Eigen/src/OrderingMethods/Amd.h b/extern/Eigen3/Eigen/src/OrderingMethods/Amd.h new file mode 100644 index 00000000000..ce04852b872 --- /dev/null +++ b/extern/Eigen3/Eigen/src/OrderingMethods/Amd.h @@ -0,0 +1,439 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2010 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/* + +NOTE: this routine has been adapted from the CSparse library: + +Copyright (c) 2006, Timothy A. Davis. +http://www.cise.ufl.edu/research/sparse/CSparse + +CSparse is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +CSparse 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this Module; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "../Core/util/NonMPL2.h" + +#ifndef EIGEN_SPARSE_AMD_H +#define EIGEN_SPARSE_AMD_H + +namespace Eigen { + +namespace internal { + +template inline T amd_flip(const T& i) { return -i-2; } +template inline T amd_unflip(const T& i) { return i<0 ? amd_flip(i) : i; } +template inline bool amd_marked(const T0* w, const T1& j) { return w[j]<0; } +template inline void amd_mark(const T0* w, const T1& j) { return w[j] = amd_flip(w[j]); } + +/* clear w */ +template +static int cs_wclear (Index mark, Index lemax, Index *w, Index n) +{ + Index k; + if(mark < 2 || (mark + lemax < 0)) + { + for(k = 0; k < n; k++) + if(w[k] != 0) + w[k] = 1; + mark = 2; + } + return (mark); /* at this point, w[0..n-1] < mark holds */ +} + +/* depth-first search and postorder of a tree rooted at node j */ +template +Index cs_tdfs(Index j, Index k, Index *head, const Index *next, Index *post, Index *stack) +{ + int i, p, top = 0; + if(!head || !next || !post || !stack) return (-1); /* check inputs */ + stack[0] = j; /* place j on the stack */ + while (top >= 0) /* while (stack is not empty) */ + { + p = stack[top]; /* p = top of stack */ + i = head[p]; /* i = youngest child of p */ + if(i == -1) + { + top--; /* p has no unordered children left */ + post[k++] = p; /* node p is the kth postordered node */ + } + else + { + head[p] = next[i]; /* remove i from children of p */ + stack[++top] = i; /* start dfs on child node i */ + } + } + return k; +} + + +/** \internal + * Approximate minimum degree ordering algorithm. + * \returns the permutation P reducing the fill-in of the input matrix \a C + * The input matrix \a C must be a selfadjoint compressed column major SparseMatrix object. Both the upper and lower parts have to be stored, but the diagonal entries are optional. + * On exit the values of C are destroyed */ +template +void minimum_degree_ordering(SparseMatrix& C, PermutationMatrix& perm) +{ + using std::sqrt; + typedef SparseMatrix CCS; + + int d, dk, dext, lemax = 0, e, elenk, eln, i, j, k, k1, + k2, k3, jlast, ln, dense, nzmax, mindeg = 0, nvi, nvj, nvk, mark, wnvi, + ok, nel = 0, p, p1, p2, p3, p4, pj, pk, pk1, pk2, pn, q, t; + unsigned int h; + + Index n = C.cols(); + dense = std::max (16, Index(10 * sqrt(double(n)))); /* find dense threshold */ + dense = std::min (n-2, dense); + + Index cnz = C.nonZeros(); + perm.resize(n+1); + t = cnz + cnz/5 + 2*n; /* add elbow room to C */ + C.resizeNonZeros(t); + + Index* W = new Index[8*(n+1)]; /* get workspace */ + Index* len = W; + Index* nv = W + (n+1); + Index* next = W + 2*(n+1); + Index* head = W + 3*(n+1); + Index* elen = W + 4*(n+1); + Index* degree = W + 5*(n+1); + Index* w = W + 6*(n+1); + Index* hhead = W + 7*(n+1); + Index* last = perm.indices().data(); /* use P as workspace for last */ + + /* --- Initialize quotient graph ---------------------------------------- */ + Index* Cp = C.outerIndexPtr(); + Index* Ci = C.innerIndexPtr(); + for(k = 0; k < n; k++) + len[k] = Cp[k+1] - Cp[k]; + len[n] = 0; + nzmax = t; + + for(i = 0; i <= n; i++) + { + head[i] = -1; // degree list i is empty + last[i] = -1; + next[i] = -1; + hhead[i] = -1; // hash list i is empty + nv[i] = 1; // node i is just one node + w[i] = 1; // node i is alive + elen[i] = 0; // Ek of node i is empty + degree[i] = len[i]; // degree of node i + } + mark = internal::cs_wclear(0, 0, w, n); /* clear w */ + elen[n] = -2; /* n is a dead element */ + Cp[n] = -1; /* n is a root of assembly tree */ + w[n] = 0; /* n is a dead element */ + + /* --- Initialize degree lists ------------------------------------------ */ + for(i = 0; i < n; i++) + { + d = degree[i]; + if(d == 0) /* node i is empty */ + { + elen[i] = -2; /* element i is dead */ + nel++; + Cp[i] = -1; /* i is a root of assembly tree */ + w[i] = 0; + } + else if(d > dense) /* node i is dense */ + { + nv[i] = 0; /* absorb i into element n */ + elen[i] = -1; /* node i is dead */ + nel++; + Cp[i] = amd_flip (n); + nv[n]++; + } + else + { + if(head[d] != -1) last[head[d]] = i; + next[i] = head[d]; /* put node i in degree list d */ + head[d] = i; + } + } + + while (nel < n) /* while (selecting pivots) do */ + { + /* --- Select node of minimum approximate degree -------------------- */ + for(k = -1; mindeg < n && (k = head[mindeg]) == -1; mindeg++) {} + if(next[k] != -1) last[next[k]] = -1; + head[mindeg] = next[k]; /* remove k from degree list */ + elenk = elen[k]; /* elenk = |Ek| */ + nvk = nv[k]; /* # of nodes k represents */ + nel += nvk; /* nv[k] nodes of A eliminated */ + + /* --- Garbage collection ------------------------------------------- */ + if(elenk > 0 && cnz + mindeg >= nzmax) + { + for(j = 0; j < n; j++) + { + if((p = Cp[j]) >= 0) /* j is a live node or element */ + { + Cp[j] = Ci[p]; /* save first entry of object */ + Ci[p] = amd_flip (j); /* first entry is now amd_flip(j) */ + } + } + for(q = 0, p = 0; p < cnz; ) /* scan all of memory */ + { + if((j = amd_flip (Ci[p++])) >= 0) /* found object j */ + { + Ci[q] = Cp[j]; /* restore first entry of object */ + Cp[j] = q++; /* new pointer to object j */ + for(k3 = 0; k3 < len[j]-1; k3++) Ci[q++] = Ci[p++]; + } + } + cnz = q; /* Ci[cnz...nzmax-1] now free */ + } + + /* --- Construct new element ---------------------------------------- */ + dk = 0; + nv[k] = -nvk; /* flag k as in Lk */ + p = Cp[k]; + pk1 = (elenk == 0) ? p : cnz; /* do in place if elen[k] == 0 */ + pk2 = pk1; + for(k1 = 1; k1 <= elenk + 1; k1++) + { + if(k1 > elenk) + { + e = k; /* search the nodes in k */ + pj = p; /* list of nodes starts at Ci[pj]*/ + ln = len[k] - elenk; /* length of list of nodes in k */ + } + else + { + e = Ci[p++]; /* search the nodes in e */ + pj = Cp[e]; + ln = len[e]; /* length of list of nodes in e */ + } + for(k2 = 1; k2 <= ln; k2++) + { + i = Ci[pj++]; + if((nvi = nv[i]) <= 0) continue; /* node i dead, or seen */ + dk += nvi; /* degree[Lk] += size of node i */ + nv[i] = -nvi; /* negate nv[i] to denote i in Lk*/ + Ci[pk2++] = i; /* place i in Lk */ + if(next[i] != -1) last[next[i]] = last[i]; + if(last[i] != -1) /* remove i from degree list */ + { + next[last[i]] = next[i]; + } + else + { + head[degree[i]] = next[i]; + } + } + if(e != k) + { + Cp[e] = amd_flip (k); /* absorb e into k */ + w[e] = 0; /* e is now a dead element */ + } + } + if(elenk != 0) cnz = pk2; /* Ci[cnz...nzmax] is free */ + degree[k] = dk; /* external degree of k - |Lk\i| */ + Cp[k] = pk1; /* element k is in Ci[pk1..pk2-1] */ + len[k] = pk2 - pk1; + elen[k] = -2; /* k is now an element */ + + /* --- Find set differences ----------------------------------------- */ + mark = internal::cs_wclear(mark, lemax, w, n); /* clear w if necessary */ + for(pk = pk1; pk < pk2; pk++) /* scan 1: find |Le\Lk| */ + { + i = Ci[pk]; + if((eln = elen[i]) <= 0) continue;/* skip if elen[i] empty */ + nvi = -nv[i]; /* nv[i] was negated */ + wnvi = mark - nvi; + for(p = Cp[i]; p <= Cp[i] + eln - 1; p++) /* scan Ei */ + { + e = Ci[p]; + if(w[e] >= mark) + { + w[e] -= nvi; /* decrement |Le\Lk| */ + } + else if(w[e] != 0) /* ensure e is a live element */ + { + w[e] = degree[e] + wnvi; /* 1st time e seen in scan 1 */ + } + } + } + + /* --- Degree update ------------------------------------------------ */ + for(pk = pk1; pk < pk2; pk++) /* scan2: degree update */ + { + i = Ci[pk]; /* consider node i in Lk */ + p1 = Cp[i]; + p2 = p1 + elen[i] - 1; + pn = p1; + for(h = 0, d = 0, p = p1; p <= p2; p++) /* scan Ei */ + { + e = Ci[p]; + if(w[e] != 0) /* e is an unabsorbed element */ + { + dext = w[e] - mark; /* dext = |Le\Lk| */ + if(dext > 0) + { + d += dext; /* sum up the set differences */ + Ci[pn++] = e; /* keep e in Ei */ + h += e; /* compute the hash of node i */ + } + else + { + Cp[e] = amd_flip (k); /* aggressive absorb. e->k */ + w[e] = 0; /* e is a dead element */ + } + } + } + elen[i] = pn - p1 + 1; /* elen[i] = |Ei| */ + p3 = pn; + p4 = p1 + len[i]; + for(p = p2 + 1; p < p4; p++) /* prune edges in Ai */ + { + j = Ci[p]; + if((nvj = nv[j]) <= 0) continue; /* node j dead or in Lk */ + d += nvj; /* degree(i) += |j| */ + Ci[pn++] = j; /* place j in node list of i */ + h += j; /* compute hash for node i */ + } + if(d == 0) /* check for mass elimination */ + { + Cp[i] = amd_flip (k); /* absorb i into k */ + nvi = -nv[i]; + dk -= nvi; /* |Lk| -= |i| */ + nvk += nvi; /* |k| += nv[i] */ + nel += nvi; + nv[i] = 0; + elen[i] = -1; /* node i is dead */ + } + else + { + degree[i] = std::min (degree[i], d); /* update degree(i) */ + Ci[pn] = Ci[p3]; /* move first node to end */ + Ci[p3] = Ci[p1]; /* move 1st el. to end of Ei */ + Ci[p1] = k; /* add k as 1st element in of Ei */ + len[i] = pn - p1 + 1; /* new len of adj. list of node i */ + h %= n; /* finalize hash of i */ + next[i] = hhead[h]; /* place i in hash bucket */ + hhead[h] = i; + last[i] = h; /* save hash of i in last[i] */ + } + } /* scan2 is done */ + degree[k] = dk; /* finalize |Lk| */ + lemax = std::max(lemax, dk); + mark = internal::cs_wclear(mark+lemax, lemax, w, n); /* clear w */ + + /* --- Supernode detection ------------------------------------------ */ + for(pk = pk1; pk < pk2; pk++) + { + i = Ci[pk]; + if(nv[i] >= 0) continue; /* skip if i is dead */ + h = last[i]; /* scan hash bucket of node i */ + i = hhead[h]; + hhead[h] = -1; /* hash bucket will be empty */ + for(; i != -1 && next[i] != -1; i = next[i], mark++) + { + ln = len[i]; + eln = elen[i]; + for(p = Cp[i]+1; p <= Cp[i] + ln-1; p++) w[Ci[p]] = mark; + jlast = i; + for(j = next[i]; j != -1; ) /* compare i with all j */ + { + ok = (len[j] == ln) && (elen[j] == eln); + for(p = Cp[j] + 1; ok && p <= Cp[j] + ln - 1; p++) + { + if(w[Ci[p]] != mark) ok = 0; /* compare i and j*/ + } + if(ok) /* i and j are identical */ + { + Cp[j] = amd_flip (i); /* absorb j into i */ + nv[i] += nv[j]; + nv[j] = 0; + elen[j] = -1; /* node j is dead */ + j = next[j]; /* delete j from hash bucket */ + next[jlast] = j; + } + else + { + jlast = j; /* j and i are different */ + j = next[j]; + } + } + } + } + + /* --- Finalize new element------------------------------------------ */ + for(p = pk1, pk = pk1; pk < pk2; pk++) /* finalize Lk */ + { + i = Ci[pk]; + if((nvi = -nv[i]) <= 0) continue;/* skip if i is dead */ + nv[i] = nvi; /* restore nv[i] */ + d = degree[i] + dk - nvi; /* compute external degree(i) */ + d = std::min (d, n - nel - nvi); + if(head[d] != -1) last[head[d]] = i; + next[i] = head[d]; /* put i back in degree list */ + last[i] = -1; + head[d] = i; + mindeg = std::min (mindeg, d); /* find new minimum degree */ + degree[i] = d; + Ci[p++] = i; /* place i in Lk */ + } + nv[k] = nvk; /* # nodes absorbed into k */ + if((len[k] = p-pk1) == 0) /* length of adj list of element k*/ + { + Cp[k] = -1; /* k is a root of the tree */ + w[k] = 0; /* k is now a dead element */ + } + if(elenk != 0) cnz = p; /* free unused space in Lk */ + } + + /* --- Postordering ----------------------------------------------------- */ + for(i = 0; i < n; i++) Cp[i] = amd_flip (Cp[i]);/* fix assembly tree */ + for(j = 0; j <= n; j++) head[j] = -1; + for(j = n; j >= 0; j--) /* place unordered nodes in lists */ + { + if(nv[j] > 0) continue; /* skip if j is an element */ + next[j] = head[Cp[j]]; /* place j in list of its parent */ + head[Cp[j]] = j; + } + for(e = n; e >= 0; e--) /* place elements in lists */ + { + if(nv[e] <= 0) continue; /* skip unless e is an element */ + if(Cp[e] != -1) + { + next[e] = head[Cp[e]]; /* place e in list of its parent */ + head[Cp[e]] = e; + } + } + for(k = 0, i = 0; i <= n; i++) /* postorder the assembly tree */ + { + if(Cp[i] == -1) k = internal::cs_tdfs(i, k, head, next, perm.indices().data(), w); + } + + perm.indices().conservativeResize(n); + + delete[] W; +} + +} // namespace internal + +} // end namespace Eigen + +#endif // EIGEN_SPARSE_AMD_H diff --git a/extern/Eigen3/Eigen/src/PaStiXSupport/PaStiXSupport.h b/extern/Eigen3/Eigen/src/PaStiXSupport/PaStiXSupport.h new file mode 100644 index 00000000000..82e137c645a --- /dev/null +++ b/extern/Eigen3/Eigen/src/PaStiXSupport/PaStiXSupport.h @@ -0,0 +1,742 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2012 Désiré Nuentsa-Wakam +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_PASTIXSUPPORT_H +#define EIGEN_PASTIXSUPPORT_H + +namespace Eigen { + +/** \ingroup PaStiXSupport_Module + * \brief Interface to the PaStix solver + * + * This class is used to solve the linear systems A.X = B via the PaStix library. + * The matrix can be either real or complex, symmetric or not. + * + * \sa TutorialSparseDirectSolvers + */ +template class PastixLU; +template class PastixLLT; +template class PastixLDLT; + +namespace internal +{ + + template struct pastix_traits; + + template + struct pastix_traits< PastixLU<_MatrixType> > + { + typedef _MatrixType MatrixType; + typedef typename _MatrixType::Scalar Scalar; + typedef typename _MatrixType::RealScalar RealScalar; + typedef typename _MatrixType::Index Index; + }; + + template + struct pastix_traits< PastixLLT<_MatrixType,Options> > + { + typedef _MatrixType MatrixType; + typedef typename _MatrixType::Scalar Scalar; + typedef typename _MatrixType::RealScalar RealScalar; + typedef typename _MatrixType::Index Index; + }; + + template + struct pastix_traits< PastixLDLT<_MatrixType,Options> > + { + typedef _MatrixType MatrixType; + typedef typename _MatrixType::Scalar Scalar; + typedef typename _MatrixType::RealScalar RealScalar; + typedef typename _MatrixType::Index Index; + }; + + void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, float *vals, int *perm, int * invp, float *x, int nbrhs, int *iparm, double *dparm) + { + if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; } + if (nbrhs == 0) {x = NULL; nbrhs=1;} + s_pastix(pastix_data, pastix_comm, n, ptr, idx, vals, perm, invp, x, nbrhs, iparm, dparm); + } + + void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, double *vals, int *perm, int * invp, double *x, int nbrhs, int *iparm, double *dparm) + { + if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; } + if (nbrhs == 0) {x = NULL; nbrhs=1;} + d_pastix(pastix_data, pastix_comm, n, ptr, idx, vals, perm, invp, x, nbrhs, iparm, dparm); + } + + void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex *vals, int *perm, int * invp, std::complex *x, int nbrhs, int *iparm, double *dparm) + { + if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; } + if (nbrhs == 0) {x = NULL; nbrhs=1;} + c_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast(vals), perm, invp, reinterpret_cast(x), nbrhs, iparm, dparm); + } + + void eigen_pastix(pastix_data_t **pastix_data, int pastix_comm, int n, int *ptr, int *idx, std::complex *vals, int *perm, int * invp, std::complex *x, int nbrhs, int *iparm, double *dparm) + { + if (n == 0) { ptr = NULL; idx = NULL; vals = NULL; } + if (nbrhs == 0) {x = NULL; nbrhs=1;} + z_pastix(pastix_data, pastix_comm, n, ptr, idx, reinterpret_cast(vals), perm, invp, reinterpret_cast(x), nbrhs, iparm, dparm); + } + + // Convert the matrix to Fortran-style Numbering + template + void c_to_fortran_numbering (MatrixType& mat) + { + if ( !(mat.outerIndexPtr()[0]) ) + { + int i; + for(i = 0; i <= mat.rows(); ++i) + ++mat.outerIndexPtr()[i]; + for(i = 0; i < mat.nonZeros(); ++i) + ++mat.innerIndexPtr()[i]; + } + } + + // Convert to C-style Numbering + template + void fortran_to_c_numbering (MatrixType& mat) + { + // Check the Numbering + if ( mat.outerIndexPtr()[0] == 1 ) + { // Convert to C-style numbering + int i; + for(i = 0; i <= mat.rows(); ++i) + --mat.outerIndexPtr()[i]; + for(i = 0; i < mat.nonZeros(); ++i) + --mat.innerIndexPtr()[i]; + } + } +} + +// This is the base class to interface with PaStiX functions. +// Users should not used this class directly. +template +class PastixBase : internal::noncopyable +{ + public: + typedef typename internal::pastix_traits::MatrixType _MatrixType; + typedef _MatrixType MatrixType; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef typename MatrixType::Index Index; + typedef Matrix Vector; + typedef SparseMatrix ColSpMatrix; + + public: + + PastixBase() : m_initisOk(false), m_analysisIsOk(false), m_factorizationIsOk(false), m_isInitialized(false), m_pastixdata(0), m_size(0) + { + init(); + } + + ~PastixBase() + { + clean(); + } + + /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. + * + * \sa compute() + */ + template + inline const internal::solve_retval + solve(const MatrixBase& b) const + { + eigen_assert(m_isInitialized && "Pastix solver is not initialized."); + eigen_assert(rows()==b.rows() + && "PastixBase::solve(): invalid number of rows of the right hand side matrix b"); + return internal::solve_retval(*this, b.derived()); + } + + template + bool _solve (const MatrixBase &b, MatrixBase &x) const; + + /** \internal */ + template + void _solve_sparse(const Rhs& b, SparseMatrix &dest) const + { + eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()"); + eigen_assert(rows()==b.rows()); + + // we process the sparse rhs per block of NbColsAtOnce columns temporarily stored into a dense matrix. + static const int NbColsAtOnce = 1; + int rhsCols = b.cols(); + int size = b.rows(); + Eigen::Matrix tmp(size,rhsCols); + for(int k=0; k(rhsCols-k, NbColsAtOnce); + tmp.leftCols(actualCols) = b.middleCols(k,actualCols); + tmp.leftCols(actualCols) = derived().solve(tmp.leftCols(actualCols)); + dest.middleCols(k,actualCols) = tmp.leftCols(actualCols).sparseView(); + } + } + + Derived& derived() + { + return *static_cast(this); + } + const Derived& derived() const + { + return *static_cast(this); + } + + /** Returns a reference to the integer vector IPARM of PaStiX parameters + * to modify the default parameters. + * The statistics related to the different phases of factorization and solve are saved here as well + * \sa analyzePattern() factorize() + */ + Array& iparm() + { + return m_iparm; + } + + /** Return a reference to a particular index parameter of the IPARM vector + * \sa iparm() + */ + + int& iparm(int idxparam) + { + return m_iparm(idxparam); + } + + /** Returns a reference to the double vector DPARM of PaStiX parameters + * The statistics related to the different phases of factorization and solve are saved here as well + * \sa analyzePattern() factorize() + */ + Array& dparm() + { + return m_dparm; + } + + + /** Return a reference to a particular index parameter of the DPARM vector + * \sa dparm() + */ + double& dparm(int idxparam) + { + return m_dparm(idxparam); + } + + inline Index cols() const { return m_size; } + inline Index rows() const { return m_size; } + + /** \brief Reports whether previous computation was successful. + * + * \returns \c Success if computation was succesful, + * \c NumericalIssue if the PaStiX reports a problem + * \c InvalidInput if the input matrix is invalid + * + * \sa iparm() + */ + ComputationInfo info() const + { + eigen_assert(m_isInitialized && "Decomposition is not initialized."); + return m_info; + } + + /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. + * + * \sa compute() + */ + template + inline const internal::sparse_solve_retval + solve(const SparseMatrixBase& b) const + { + eigen_assert(m_isInitialized && "Pastix LU, LLT or LDLT is not initialized."); + eigen_assert(rows()==b.rows() + && "PastixBase::solve(): invalid number of rows of the right hand side matrix b"); + return internal::sparse_solve_retval(*this, b.derived()); + } + + protected: + + // Initialize the Pastix data structure, check the matrix + void init(); + + // Compute the ordering and the symbolic factorization + void analyzePattern(ColSpMatrix& mat); + + // Compute the numerical factorization + void factorize(ColSpMatrix& mat); + + // Free all the data allocated by Pastix + void clean() + { + eigen_assert(m_initisOk && "The Pastix structure should be allocated first"); + m_iparm(IPARM_START_TASK) = API_TASK_CLEAN; + m_iparm(IPARM_END_TASK) = API_TASK_CLEAN; + internal::eigen_pastix(&m_pastixdata, MPI_COMM_WORLD, 0, 0, 0, (Scalar*)0, + m_perm.data(), m_invp.data(), 0, 0, m_iparm.data(), m_dparm.data()); + } + + void compute(ColSpMatrix& mat); + + int m_initisOk; + int m_analysisIsOk; + int m_factorizationIsOk; + bool m_isInitialized; + mutable ComputationInfo m_info; + mutable pastix_data_t *m_pastixdata; // Data structure for pastix + mutable int m_comm; // The MPI communicator identifier + mutable Matrix m_iparm; // integer vector for the input parameters + mutable Matrix m_dparm; // Scalar vector for the input parameters + mutable Matrix m_perm; // Permutation vector + mutable Matrix m_invp; // Inverse permutation vector + mutable int m_size; // Size of the matrix +}; + + /** Initialize the PaStiX data structure. + *A first call to this function fills iparm and dparm with the default PaStiX parameters + * \sa iparm() dparm() + */ +template +void PastixBase::init() +{ + m_size = 0; + m_iparm.setZero(IPARM_SIZE); + m_dparm.setZero(DPARM_SIZE); + + m_iparm(IPARM_MODIFY_PARAMETER) = API_NO; + pastix(&m_pastixdata, MPI_COMM_WORLD, + 0, 0, 0, 0, + 0, 0, 0, 1, m_iparm.data(), m_dparm.data()); + + m_iparm[IPARM_MATRIX_VERIFICATION] = API_NO; + m_iparm[IPARM_VERBOSE] = 2; + m_iparm[IPARM_ORDERING] = API_ORDER_SCOTCH; + m_iparm[IPARM_INCOMPLETE] = API_NO; + m_iparm[IPARM_OOC_LIMIT] = 2000; + m_iparm[IPARM_RHS_MAKING] = API_RHS_B; + m_iparm(IPARM_MATRIX_VERIFICATION) = API_NO; + + m_iparm(IPARM_START_TASK) = API_TASK_INIT; + m_iparm(IPARM_END_TASK) = API_TASK_INIT; + internal::eigen_pastix(&m_pastixdata, MPI_COMM_WORLD, 0, 0, 0, (Scalar*)0, + 0, 0, 0, 0, m_iparm.data(), m_dparm.data()); + + // Check the returned error + if(m_iparm(IPARM_ERROR_NUMBER)) { + m_info = InvalidInput; + m_initisOk = false; + } + else { + m_info = Success; + m_initisOk = true; + } +} + +template +void PastixBase::compute(ColSpMatrix& mat) +{ + eigen_assert(mat.rows() == mat.cols() && "The input matrix should be squared"); + + analyzePattern(mat); + factorize(mat); + + m_iparm(IPARM_MATRIX_VERIFICATION) = API_NO; + m_isInitialized = m_factorizationIsOk; +} + + +template +void PastixBase::analyzePattern(ColSpMatrix& mat) +{ + eigen_assert(m_initisOk && "The initialization of PaSTiX failed"); + + // clean previous calls + if(m_size>0) + clean(); + + m_size = mat.rows(); + m_perm.resize(m_size); + m_invp.resize(m_size); + + m_iparm(IPARM_START_TASK) = API_TASK_ORDERING; + m_iparm(IPARM_END_TASK) = API_TASK_ANALYSE; + internal::eigen_pastix(&m_pastixdata, MPI_COMM_WORLD, m_size, mat.outerIndexPtr(), mat.innerIndexPtr(), + mat.valuePtr(), m_perm.data(), m_invp.data(), 0, 0, m_iparm.data(), m_dparm.data()); + + // Check the returned error + if(m_iparm(IPARM_ERROR_NUMBER)) + { + m_info = NumericalIssue; + m_analysisIsOk = false; + } + else + { + m_info = Success; + m_analysisIsOk = true; + } +} + +template +void PastixBase::factorize(ColSpMatrix& mat) +{ +// if(&m_cpyMat != &mat) m_cpyMat = mat; + eigen_assert(m_analysisIsOk && "The analysis phase should be called before the factorization phase"); + m_iparm(IPARM_START_TASK) = API_TASK_NUMFACT; + m_iparm(IPARM_END_TASK) = API_TASK_NUMFACT; + m_size = mat.rows(); + + internal::eigen_pastix(&m_pastixdata, MPI_COMM_WORLD, m_size, mat.outerIndexPtr(), mat.innerIndexPtr(), + mat.valuePtr(), m_perm.data(), m_invp.data(), 0, 0, m_iparm.data(), m_dparm.data()); + + // Check the returned error + if(m_iparm(IPARM_ERROR_NUMBER)) + { + m_info = NumericalIssue; + m_factorizationIsOk = false; + m_isInitialized = false; + } + else + { + m_info = Success; + m_factorizationIsOk = true; + m_isInitialized = true; + } +} + +/* Solve the system */ +template +template +bool PastixBase::_solve (const MatrixBase &b, MatrixBase &x) const +{ + eigen_assert(m_isInitialized && "The matrix should be factorized first"); + EIGEN_STATIC_ASSERT((Dest::Flags&RowMajorBit)==0, + THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES); + int rhs = 1; + + x = b; /* on return, x is overwritten by the computed solution */ + + for (int i = 0; i < b.cols(); i++){ + m_iparm[IPARM_START_TASK] = API_TASK_SOLVE; + m_iparm[IPARM_END_TASK] = API_TASK_REFINE; + + internal::eigen_pastix(&m_pastixdata, MPI_COMM_WORLD, x.rows(), 0, 0, 0, + m_perm.data(), m_invp.data(), &x(0, i), rhs, m_iparm.data(), m_dparm.data()); + } + + // Check the returned error + m_info = m_iparm(IPARM_ERROR_NUMBER)==0 ? Success : NumericalIssue; + + return m_iparm(IPARM_ERROR_NUMBER)==0; +} + +/** \ingroup PaStiXSupport_Module + * \class PastixLU + * \brief Sparse direct LU solver based on PaStiX library + * + * This class is used to solve the linear systems A.X = B with a supernodal LU + * factorization in the PaStiX library. The matrix A should be squared and nonsingular + * PaStiX requires that the matrix A has a symmetric structural pattern. + * This interface can symmetrize the input matrix otherwise. + * The vectors or matrices X and B can be either dense or sparse. + * + * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam IsStrSym Indicates if the input matrix has a symmetric pattern, default is false + * NOTE : Note that if the analysis and factorization phase are called separately, + * the input matrix will be symmetrized at each call, hence it is advised to + * symmetrize the matrix in a end-user program and set \p IsStrSym to true + * + * \sa \ref TutorialSparseDirectSolvers + * + */ +template +class PastixLU : public PastixBase< PastixLU<_MatrixType> > +{ + public: + typedef _MatrixType MatrixType; + typedef PastixBase > Base; + typedef typename Base::ColSpMatrix ColSpMatrix; + typedef typename MatrixType::Index Index; + + public: + PastixLU() : Base() + { + init(); + } + + PastixLU(const MatrixType& matrix):Base() + { + init(); + compute(matrix); + } + /** Compute the LU supernodal factorization of \p matrix. + * iparm and dparm can be used to tune the PaStiX parameters. + * see the PaStiX user's manual + * \sa analyzePattern() factorize() + */ + void compute (const MatrixType& matrix) + { + m_structureIsUptodate = false; + ColSpMatrix temp; + grabMatrix(matrix, temp); + Base::compute(temp); + } + /** Compute the LU symbolic factorization of \p matrix using its sparsity pattern. + * Several ordering methods can be used at this step. See the PaStiX user's manual. + * The result of this operation can be used with successive matrices having the same pattern as \p matrix + * \sa factorize() + */ + void analyzePattern(const MatrixType& matrix) + { + m_structureIsUptodate = false; + ColSpMatrix temp; + grabMatrix(matrix, temp); + Base::analyzePattern(temp); + } + + /** Compute the LU supernodal factorization of \p matrix + * WARNING The matrix \p matrix should have the same structural pattern + * as the same used in the analysis phase. + * \sa analyzePattern() + */ + void factorize(const MatrixType& matrix) + { + ColSpMatrix temp; + grabMatrix(matrix, temp); + Base::factorize(temp); + } + protected: + + void init() + { + m_structureIsUptodate = false; + m_iparm(IPARM_SYM) = API_SYM_NO; + m_iparm(IPARM_FACTORIZATION) = API_FACT_LU; + } + + void grabMatrix(const MatrixType& matrix, ColSpMatrix& out) + { + if(IsStrSym) + out = matrix; + else + { + if(!m_structureIsUptodate) + { + // update the transposed structure + m_transposedStructure = matrix.transpose(); + + // Set the elements of the matrix to zero + for (Index j=0; j + * \tparam UpLo The part of the matrix to use : Lower or Upper. The default is Lower as required by PaStiX + * + * \sa \ref TutorialSparseDirectSolvers + */ +template +class PastixLLT : public PastixBase< PastixLLT<_MatrixType, _UpLo> > +{ + public: + typedef _MatrixType MatrixType; + typedef PastixBase > Base; + typedef typename Base::ColSpMatrix ColSpMatrix; + + public: + enum { UpLo = _UpLo }; + PastixLLT() : Base() + { + init(); + } + + PastixLLT(const MatrixType& matrix):Base() + { + init(); + compute(matrix); + } + + /** Compute the L factor of the LL^T supernodal factorization of \p matrix + * \sa analyzePattern() factorize() + */ + void compute (const MatrixType& matrix) + { + ColSpMatrix temp; + grabMatrix(matrix, temp); + Base::compute(temp); + } + + /** Compute the LL^T symbolic factorization of \p matrix using its sparsity pattern + * The result of this operation can be used with successive matrices having the same pattern as \p matrix + * \sa factorize() + */ + void analyzePattern(const MatrixType& matrix) + { + ColSpMatrix temp; + grabMatrix(matrix, temp); + Base::analyzePattern(temp); + } + /** Compute the LL^T supernodal numerical factorization of \p matrix + * \sa analyzePattern() + */ + void factorize(const MatrixType& matrix) + { + ColSpMatrix temp; + grabMatrix(matrix, temp); + Base::factorize(temp); + } + protected: + using Base::m_iparm; + + void init() + { + m_iparm(IPARM_SYM) = API_SYM_YES; + m_iparm(IPARM_FACTORIZATION) = API_FACT_LLT; + } + + void grabMatrix(const MatrixType& matrix, ColSpMatrix& out) + { + // Pastix supports only lower, column-major matrices + out.template selfadjointView() = matrix.template selfadjointView(); + internal::c_to_fortran_numbering(out); + } +}; + +/** \ingroup PaStiXSupport_Module + * \class PastixLDLT + * \brief A sparse direct supernodal Cholesky (LLT) factorization and solver based on the PaStiX library + * + * This class is used to solve the linear systems A.X = B via a LDL^T supernodal Cholesky factorization + * available in the PaStiX library. The matrix A should be symmetric and positive definite + * WARNING Selfadjoint complex matrices are not supported in the current version of PaStiX + * The vectors or matrices X and B can be either dense or sparse + * + * \tparam MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam UpLo The part of the matrix to use : Lower or Upper. The default is Lower as required by PaStiX + * + * \sa \ref TutorialSparseDirectSolvers + */ +template +class PastixLDLT : public PastixBase< PastixLDLT<_MatrixType, _UpLo> > +{ + public: + typedef _MatrixType MatrixType; + typedef PastixBase > Base; + typedef typename Base::ColSpMatrix ColSpMatrix; + + public: + enum { UpLo = _UpLo }; + PastixLDLT():Base() + { + init(); + } + + PastixLDLT(const MatrixType& matrix):Base() + { + init(); + compute(matrix); + } + + /** Compute the L and D factors of the LDL^T factorization of \p matrix + * \sa analyzePattern() factorize() + */ + void compute (const MatrixType& matrix) + { + ColSpMatrix temp; + grabMatrix(matrix, temp); + Base::compute(temp); + } + + /** Compute the LDL^T symbolic factorization of \p matrix using its sparsity pattern + * The result of this operation can be used with successive matrices having the same pattern as \p matrix + * \sa factorize() + */ + void analyzePattern(const MatrixType& matrix) + { + ColSpMatrix temp; + grabMatrix(matrix, temp); + Base::analyzePattern(temp); + } + /** Compute the LDL^T supernodal numerical factorization of \p matrix + * + */ + void factorize(const MatrixType& matrix) + { + ColSpMatrix temp; + grabMatrix(matrix, temp); + Base::factorize(temp); + } + + protected: + using Base::m_iparm; + + void init() + { + m_iparm(IPARM_SYM) = API_SYM_YES; + m_iparm(IPARM_FACTORIZATION) = API_FACT_LDLT; + } + + void grabMatrix(const MatrixType& matrix, ColSpMatrix& out) + { + // Pastix supports only lower, column-major matrices + out.template selfadjointView() = matrix.template selfadjointView(); + internal::c_to_fortran_numbering(out); + } +}; + +namespace internal { + +template +struct solve_retval, Rhs> + : solve_retval_base, Rhs> +{ + typedef PastixBase<_MatrixType> Dec; + EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs) + + template void evalTo(Dest& dst) const + { + dec()._solve(rhs(),dst); + } +}; + +template +struct sparse_solve_retval, Rhs> + : sparse_solve_retval_base, Rhs> +{ + typedef PastixBase<_MatrixType> Dec; + EIGEN_MAKE_SPARSE_SOLVE_HELPERS(Dec,Rhs) + + template void evalTo(Dest& dst) const + { + dec()._solve_sparse(rhs(),dst); + } +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif diff --git a/extern/Eigen3/Eigen/src/PardisoSupport/PardisoSupport.h b/extern/Eigen3/Eigen/src/PardisoSupport/PardisoSupport.h new file mode 100644 index 00000000000..e6defc8c39e --- /dev/null +++ b/extern/Eigen3/Eigen/src/PardisoSupport/PardisoSupport.h @@ -0,0 +1,614 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + 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 Intel Corporation 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. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL PARDISO + ******************************************************************************** +*/ + +#ifndef EIGEN_PARDISOSUPPORT_H +#define EIGEN_PARDISOSUPPORT_H + +namespace Eigen { + +template class PardisoLU; +template class PardisoLLT; +template class PardisoLDLT; + +namespace internal +{ + template + struct pardiso_run_selector + { + static Index run( _MKL_DSS_HANDLE_t pt, Index maxfct, Index mnum, Index type, Index phase, Index n, void *a, + Index *ia, Index *ja, Index *perm, Index nrhs, Index *iparm, Index msglvl, void *b, void *x) + { + Index error = 0; + ::pardiso(pt, &maxfct, &mnum, &type, &phase, &n, a, ia, ja, perm, &nrhs, iparm, &msglvl, b, x, &error); + return error; + } + }; + template<> + struct pardiso_run_selector + { + typedef long long int Index; + static Index run( _MKL_DSS_HANDLE_t pt, Index maxfct, Index mnum, Index type, Index phase, Index n, void *a, + Index *ia, Index *ja, Index *perm, Index nrhs, Index *iparm, Index msglvl, void *b, void *x) + { + Index error = 0; + ::pardiso_64(pt, &maxfct, &mnum, &type, &phase, &n, a, ia, ja, perm, &nrhs, iparm, &msglvl, b, x, &error); + return error; + } + }; + + template struct pardiso_traits; + + template + struct pardiso_traits< PardisoLU<_MatrixType> > + { + typedef _MatrixType MatrixType; + typedef typename _MatrixType::Scalar Scalar; + typedef typename _MatrixType::RealScalar RealScalar; + typedef typename _MatrixType::Index Index; + }; + + template + struct pardiso_traits< PardisoLLT<_MatrixType, Options> > + { + typedef _MatrixType MatrixType; + typedef typename _MatrixType::Scalar Scalar; + typedef typename _MatrixType::RealScalar RealScalar; + typedef typename _MatrixType::Index Index; + }; + + template + struct pardiso_traits< PardisoLDLT<_MatrixType, Options> > + { + typedef _MatrixType MatrixType; + typedef typename _MatrixType::Scalar Scalar; + typedef typename _MatrixType::RealScalar RealScalar; + typedef typename _MatrixType::Index Index; + }; + +} + +template +class PardisoImpl +{ + typedef internal::pardiso_traits Traits; + public: + typedef typename Traits::MatrixType MatrixType; + typedef typename Traits::Scalar Scalar; + typedef typename Traits::RealScalar RealScalar; + typedef typename Traits::Index Index; + typedef SparseMatrix SparseMatrixType; + typedef Matrix VectorType; + typedef Matrix IntRowVectorType; + typedef Matrix IntColVectorType; + enum { + ScalarIsComplex = NumTraits::IsComplex + }; + + PardisoImpl() + { + eigen_assert((sizeof(Index) >= sizeof(_INTEGER_t) && sizeof(Index) <= 8) && "Non-supported index type"); + m_iparm.setZero(); + m_msglvl = 0; // No output + m_initialized = false; + } + + ~PardisoImpl() + { + pardisoRelease(); + } + + inline Index cols() const { return m_size; } + inline Index rows() const { return m_size; } + + /** \brief Reports whether previous computation was successful. + * + * \returns \c Success if computation was succesful, + * \c NumericalIssue if the matrix appears to be negative. + */ + ComputationInfo info() const + { + eigen_assert(m_initialized && "Decomposition is not initialized."); + return m_info; + } + + /** \warning for advanced usage only. + * \returns a reference to the parameter array controlling PARDISO. + * See the PARDISO manual to know how to use it. */ + Array& pardisoParameterArray() + { + return m_iparm; + } + + /** Performs a symbolic decomposition on the sparcity of \a matrix. + * + * This function is particularly useful when solving for several problems having the same structure. + * + * \sa factorize() + */ + Derived& analyzePattern(const MatrixType& matrix); + + /** Performs a numeric decomposition of \a matrix + * + * The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed. + * + * \sa analyzePattern() + */ + Derived& factorize(const MatrixType& matrix); + + Derived& compute(const MatrixType& matrix); + + /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. + * + * \sa compute() + */ + template + inline const internal::solve_retval + solve(const MatrixBase& b) const + { + eigen_assert(m_initialized && "Pardiso solver is not initialized."); + eigen_assert(rows()==b.rows() + && "PardisoImpl::solve(): invalid number of rows of the right hand side matrix b"); + return internal::solve_retval(*this, b.derived()); + } + + /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. + * + * \sa compute() + */ + template + inline const internal::sparse_solve_retval + solve(const SparseMatrixBase& b) const + { + eigen_assert(m_initialized && "Pardiso solver is not initialized."); + eigen_assert(rows()==b.rows() + && "PardisoImpl::solve(): invalid number of rows of the right hand side matrix b"); + return internal::sparse_solve_retval(*this, b.derived()); + } + + Derived& derived() + { + return *static_cast(this); + } + const Derived& derived() const + { + return *static_cast(this); + } + + template + bool _solve(const MatrixBase &b, MatrixBase& x) const; + + /** \internal */ + template + void _solve_sparse(const Rhs& b, SparseMatrix &dest) const + { + eigen_assert(m_size==b.rows()); + + // we process the sparse rhs per block of NbColsAtOnce columns temporarily stored into a dense matrix. + static const int NbColsAtOnce = 4; + int rhsCols = b.cols(); + int size = b.rows(); + // Pardiso cannot solve in-place, + // so we need two temporaries + Eigen::Matrix tmp_rhs(size,rhsCols); + Eigen::Matrix tmp_res(size,rhsCols); + for(int k=0; k(rhsCols-k, NbColsAtOnce); + tmp_rhs.leftCols(actualCols) = b.middleCols(k,actualCols); + tmp_res.leftCols(actualCols) = derived().solve(tmp_rhs.leftCols(actualCols)); + dest.middleCols(k,actualCols) = tmp_res.leftCols(actualCols).sparseView(); + } + } + + protected: + void pardisoRelease() + { + if(m_initialized) // Factorization ran at least once + { + internal::pardiso_run_selector::run(m_pt, 1, 1, m_type, -1, m_size, 0, 0, 0, m_perm.data(), 0, + m_iparm.data(), m_msglvl, 0, 0); + } + } + + void pardisoInit(int type) + { + m_type = type; + bool symmetric = abs(m_type) < 10; + m_iparm[0] = 1; // No solver default + m_iparm[1] = 3; // use Metis for the ordering + m_iparm[2] = 1; // Numbers of processors, value of OMP_NUM_THREADS + m_iparm[3] = 0; // No iterative-direct algorithm + m_iparm[4] = 0; // No user fill-in reducing permutation + m_iparm[5] = 0; // Write solution into x + m_iparm[6] = 0; // Not in use + m_iparm[7] = 2; // Max numbers of iterative refinement steps + m_iparm[8] = 0; // Not in use + m_iparm[9] = 13; // Perturb the pivot elements with 1E-13 + m_iparm[10] = symmetric ? 0 : 1; // Use nonsymmetric permutation and scaling MPS + m_iparm[11] = 0; // Not in use + m_iparm[12] = symmetric ? 0 : 1; // Maximum weighted matching algorithm is switched-off (default for symmetric). + // Try m_iparm[12] = 1 in case of inappropriate accuracy + m_iparm[13] = 0; // Output: Number of perturbed pivots + m_iparm[14] = 0; // Not in use + m_iparm[15] = 0; // Not in use + m_iparm[16] = 0; // Not in use + m_iparm[17] = -1; // Output: Number of nonzeros in the factor LU + m_iparm[18] = -1; // Output: Mflops for LU factorization + m_iparm[19] = 0; // Output: Numbers of CG Iterations + + m_iparm[20] = 0; // 1x1 pivoting + m_iparm[26] = 0; // No matrix checker + m_iparm[27] = (sizeof(RealScalar) == 4) ? 1 : 0; + m_iparm[34] = 1; // C indexing + m_iparm[59] = 1; // Automatic switch between In-Core and Out-of-Core modes + } + + protected: + // cached data to reduce reallocation, etc. + + void manageErrorCode(Index error) + { + switch(error) + { + case 0: + m_info = Success; + break; + case -4: + case -7: + m_info = NumericalIssue; + break; + default: + m_info = InvalidInput; + } + } + + mutable SparseMatrixType m_matrix; + ComputationInfo m_info; + bool m_initialized, m_analysisIsOk, m_factorizationIsOk; + Index m_type, m_msglvl; + mutable void *m_pt[64]; + mutable Array m_iparm; + mutable IntColVectorType m_perm; + Index m_size; + + private: + PardisoImpl(PardisoImpl &) {} +}; + +template +Derived& PardisoImpl::compute(const MatrixType& a) +{ + m_size = a.rows(); + eigen_assert(a.rows() == a.cols()); + + pardisoRelease(); + memset(m_pt, 0, sizeof(m_pt)); + m_perm.setZero(m_size); + derived().getMatrix(a); + + Index error; + error = internal::pardiso_run_selector::run(m_pt, 1, 1, m_type, 12, m_size, + m_matrix.valuePtr(), m_matrix.outerIndexPtr(), m_matrix.innerIndexPtr(), + m_perm.data(), 0, m_iparm.data(), m_msglvl, NULL, NULL); + + manageErrorCode(error); + m_analysisIsOk = true; + m_factorizationIsOk = true; + m_initialized = true; + return derived(); +} + +template +Derived& PardisoImpl::analyzePattern(const MatrixType& a) +{ + m_size = a.rows(); + eigen_assert(m_size == a.cols()); + + pardisoRelease(); + memset(m_pt, 0, sizeof(m_pt)); + m_perm.setZero(m_size); + derived().getMatrix(a); + + Index error; + error = internal::pardiso_run_selector::run(m_pt, 1, 1, m_type, 11, m_size, + m_matrix.valuePtr(), m_matrix.outerIndexPtr(), m_matrix.innerIndexPtr(), + m_perm.data(), 0, m_iparm.data(), m_msglvl, NULL, NULL); + + manageErrorCode(error); + m_analysisIsOk = true; + m_factorizationIsOk = false; + m_initialized = true; + return derived(); +} + +template +Derived& PardisoImpl::factorize(const MatrixType& a) +{ + eigen_assert(m_analysisIsOk && "You must first call analyzePattern()"); + eigen_assert(m_size == a.rows() && m_size == a.cols()); + + derived().getMatrix(a); + + Index error; + error = internal::pardiso_run_selector::run(m_pt, 1, 1, m_type, 22, m_size, + m_matrix.valuePtr(), m_matrix.outerIndexPtr(), m_matrix.innerIndexPtr(), + m_perm.data(), 0, m_iparm.data(), m_msglvl, NULL, NULL); + + manageErrorCode(error); + m_factorizationIsOk = true; + return derived(); +} + +template +template +bool PardisoImpl::_solve(const MatrixBase &b, MatrixBase& x) const +{ + if(m_iparm[0] == 0) // Factorization was not computed + return false; + + //Index n = m_matrix.rows(); + Index nrhs = Index(b.cols()); + eigen_assert(m_size==b.rows()); + eigen_assert(((MatrixBase::Flags & RowMajorBit) == 0 || nrhs == 1) && "Row-major right hand sides are not supported"); + eigen_assert(((MatrixBase::Flags & RowMajorBit) == 0 || nrhs == 1) && "Row-major matrices of unknowns are not supported"); + eigen_assert(((nrhs == 1) || b.outerStride() == b.rows())); + + +// switch (transposed) { +// case SvNoTrans : m_iparm[11] = 0 ; break; +// case SvTranspose : m_iparm[11] = 2 ; break; +// case SvAdjoint : m_iparm[11] = 1 ; break; +// default: +// //std::cerr << "Eigen: transposition option \"" << transposed << "\" not supported by the PARDISO backend\n"; +// m_iparm[11] = 0; +// } + + Scalar* rhs_ptr = const_cast(b.derived().data()); + Matrix tmp; + + // Pardiso cannot solve in-place + if(rhs_ptr == x.derived().data()) + { + tmp = b; + rhs_ptr = tmp.data(); + } + + Index error; + error = internal::pardiso_run_selector::run(m_pt, 1, 1, m_type, 33, m_size, + m_matrix.valuePtr(), m_matrix.outerIndexPtr(), m_matrix.innerIndexPtr(), + m_perm.data(), nrhs, m_iparm.data(), m_msglvl, + rhs_ptr, x.derived().data()); + + return error==0; +} + + +/** \ingroup PardisoSupport_Module + * \class PardisoLU + * \brief A sparse direct LU factorization and solver based on the PARDISO library + * + * This class allows to solve for A.X = B sparse linear problems via a direct LU factorization + * using the Intel MKL PARDISO library. The sparse matrix A must be squared and invertible. + * The vectors or matrices X and B can be either dense or sparse. + * + * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> + * + * \sa \ref TutorialSparseDirectSolvers + */ +template +class PardisoLU : public PardisoImpl< PardisoLU > +{ + protected: + typedef PardisoImpl< PardisoLU > Base; + typedef typename Base::Scalar Scalar; + typedef typename Base::RealScalar RealScalar; + using Base::pardisoInit; + using Base::m_matrix; + friend class PardisoImpl< PardisoLU >; + + public: + + using Base::compute; + using Base::solve; + + PardisoLU() + : Base() + { + pardisoInit(Base::ScalarIsComplex ? 13 : 11); + } + + PardisoLU(const MatrixType& matrix) + : Base() + { + pardisoInit(Base::ScalarIsComplex ? 13 : 11); + compute(matrix); + } + protected: + void getMatrix(const MatrixType& matrix) + { + m_matrix = matrix; + } + + private: + PardisoLU(PardisoLU& ) {} +}; + +/** \ingroup PardisoSupport_Module + * \class PardisoLLT + * \brief A sparse direct Cholesky (LLT) factorization and solver based on the PARDISO library + * + * This class allows to solve for A.X = B sparse linear problems via a LL^T Cholesky factorization + * using the Intel MKL PARDISO library. The sparse matrix A must be selfajoint and positive definite. + * The vectors or matrices X and B can be either dense or sparse. + * + * \tparam MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam UpLo can be any bitwise combination of Upper, Lower. The default is Upper, meaning only the upper triangular part has to be used. + * Upper|Lower can be used to tell both triangular parts can be used as input. + * + * \sa \ref TutorialSparseDirectSolvers + */ +template +class PardisoLLT : public PardisoImpl< PardisoLLT > +{ + protected: + typedef PardisoImpl< PardisoLLT > Base; + typedef typename Base::Scalar Scalar; + typedef typename Base::Index Index; + typedef typename Base::RealScalar RealScalar; + using Base::pardisoInit; + using Base::m_matrix; + friend class PardisoImpl< PardisoLLT >; + + public: + + enum { UpLo = _UpLo }; + using Base::compute; + using Base::solve; + + PardisoLLT() + : Base() + { + pardisoInit(Base::ScalarIsComplex ? 4 : 2); + } + + PardisoLLT(const MatrixType& matrix) + : Base() + { + pardisoInit(Base::ScalarIsComplex ? 4 : 2); + compute(matrix); + } + + protected: + + void getMatrix(const MatrixType& matrix) + { + // PARDISO supports only upper, row-major matrices + PermutationMatrix p_null; + m_matrix.resize(matrix.rows(), matrix.cols()); + m_matrix.template selfadjointView() = matrix.template selfadjointView().twistedBy(p_null); + } + + private: + PardisoLLT(PardisoLLT& ) {} +}; + +/** \ingroup PardisoSupport_Module + * \class PardisoLDLT + * \brief A sparse direct Cholesky (LDLT) factorization and solver based on the PARDISO library + * + * This class allows to solve for A.X = B sparse linear problems via a LDL^T Cholesky factorization + * using the Intel MKL PARDISO library. The sparse matrix A is assumed to be selfajoint and positive definite. + * For complex matrices, A can also be symmetric only, see the \a Options template parameter. + * The vectors or matrices X and B can be either dense or sparse. + * + * \tparam MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam Options can be any bitwise combination of Upper, Lower, and Symmetric. The default is Upper, meaning only the upper triangular part has to be used. + * Symmetric can be used for symmetric, non-selfadjoint complex matrices, the default being to assume a selfadjoint matrix. + * Upper|Lower can be used to tell both triangular parts can be used as input. + * + * \sa \ref TutorialSparseDirectSolvers + */ +template +class PardisoLDLT : public PardisoImpl< PardisoLDLT > +{ + protected: + typedef PardisoImpl< PardisoLDLT > Base; + typedef typename Base::Scalar Scalar; + typedef typename Base::Index Index; + typedef typename Base::RealScalar RealScalar; + using Base::pardisoInit; + using Base::m_matrix; + friend class PardisoImpl< PardisoLDLT >; + + public: + + using Base::compute; + using Base::solve; + enum { UpLo = Options&(Upper|Lower) }; + + PardisoLDLT() + : Base() + { + pardisoInit(Base::ScalarIsComplex ? ( bool(Options&Symmetric) ? 6 : -4 ) : -2); + } + + PardisoLDLT(const MatrixType& matrix) + : Base() + { + pardisoInit(Base::ScalarIsComplex ? ( bool(Options&Symmetric) ? 6 : -4 ) : -2); + compute(matrix); + } + + void getMatrix(const MatrixType& matrix) + { + // PARDISO supports only upper, row-major matrices + PermutationMatrix p_null; + m_matrix.resize(matrix.rows(), matrix.cols()); + m_matrix.template selfadjointView() = matrix.template selfadjointView().twistedBy(p_null); + } + + private: + PardisoLDLT(PardisoLDLT& ) {} +}; + +namespace internal { + +template +struct solve_retval, Rhs> + : solve_retval_base, Rhs> +{ + typedef PardisoImpl<_Derived> Dec; + EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs) + + template void evalTo(Dest& dst) const + { + dec()._solve(rhs(),dst); + } +}; + +template +struct sparse_solve_retval, Rhs> + : sparse_solve_retval_base, Rhs> +{ + typedef PardisoImpl Dec; + EIGEN_MAKE_SPARSE_SOLVE_HELPERS(Dec,Rhs) + + template void evalTo(Dest& dst) const + { + dec().derived()._solve_sparse(rhs(),dst); + } +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_PARDISOSUPPORT_H diff --git a/extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h b/extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h index f04c6038d6a..2daa23cc354 100644 --- a/extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h +++ b/extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR.h @@ -4,28 +4,15 @@ // Copyright (C) 2008-2009 Gael Guennebaud // Copyright (C) 2009 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_COLPIVOTINGHOUSEHOLDERQR_H #define EIGEN_COLPIVOTINGHOUSEHOLDERQR_H +namespace Eigen { + /** \ingroup QR_Module * * \class ColPivHouseholderQR @@ -528,5 +515,6 @@ MatrixBase::colPivHouseholderQr() const return ColPivHouseholderQR(eval()); } +} // end namespace Eigen #endif // EIGEN_COLPIVOTINGHOUSEHOLDERQR_H diff --git a/extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR_MKL.h b/extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR_MKL.h new file mode 100644 index 00000000000..745ecf8be98 --- /dev/null +++ b/extern/Eigen3/Eigen/src/QR/ColPivHouseholderQR_MKL.h @@ -0,0 +1,98 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + 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 Intel Corporation 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. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL + * Householder QR decomposition of a matrix with column pivoting based on + * LAPACKE_?geqp3 function. + ******************************************************************************** +*/ + +#ifndef EIGEN_COLPIVOTINGHOUSEHOLDERQR_MKL_H +#define EIGEN_COLPIVOTINGHOUSEHOLDERQR_MKL_H + +#include "Eigen/src/Core/util/MKL_support.h" + +namespace Eigen { + +/** \internal Specialization for the data types supported by MKL */ + +#define EIGEN_MKL_QR_COLPIV(EIGTYPE, MKLTYPE, MKLPREFIX, EIGCOLROW, MKLCOLROW) \ +template<> inline\ +ColPivHouseholderQR >& \ +ColPivHouseholderQR >::compute( \ + const Matrix& matrix) \ +\ +{ \ + typedef Matrix MatrixType; \ + typedef MatrixType::Scalar Scalar; \ + typedef MatrixType::RealScalar RealScalar; \ + Index rows = matrix.rows();\ + Index cols = matrix.cols();\ + Index size = matrix.diagonalSize();\ +\ + m_qr = matrix;\ + m_hCoeffs.resize(size);\ +\ + m_colsTranspositions.resize(cols);\ + /*Index number_of_transpositions = 0;*/ \ +\ + m_nonzero_pivots = 0; \ + m_maxpivot = RealScalar(0);\ + m_colsPermutation.resize(cols); \ + m_colsPermutation.indices().setZero(); \ +\ + lapack_int lda = m_qr.outerStride(), i; \ + lapack_int matrix_order = MKLCOLROW; \ + LAPACKE_##MKLPREFIX##geqp3( matrix_order, rows, cols, (MKLTYPE*)m_qr.data(), lda, (lapack_int*)m_colsPermutation.indices().data(), (MKLTYPE*)m_hCoeffs.data()); \ + m_isInitialized = true; \ + m_maxpivot=m_qr.diagonal().cwiseAbs().maxCoeff(); \ + m_hCoeffs.adjointInPlace(); \ + RealScalar premultiplied_threshold = internal::abs(m_maxpivot) * threshold(); \ + lapack_int *perm = m_colsPermutation.indices().data(); \ + for(i=0;i premultiplied_threshold);\ + } \ + for(i=0;i // Copyright (C) 2009 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_FULLPIVOTINGHOUSEHOLDERQR_H #define EIGEN_FULLPIVOTINGHOUSEHOLDERQR_H +namespace Eigen { + +namespace internal { + +template struct FullPivHouseholderQRMatrixQReturnType; + +template +struct traits > +{ + typedef typename MatrixType::PlainObject ReturnType; +}; + +} + /** \ingroup QR_Module * * \class FullPivHouseholderQR @@ -62,7 +61,7 @@ template class FullPivHouseholderQR typedef typename MatrixType::Scalar Scalar; typedef typename MatrixType::RealScalar RealScalar; typedef typename MatrixType::Index Index; - typedef Matrix MatrixQType; + typedef internal::FullPivHouseholderQRMatrixQReturnType MatrixQReturnType; typedef typename internal::plain_diag_type::type HCoeffsType; typedef Matrix IntRowVectorType; typedef PermutationMatrix PermutationType; @@ -139,7 +138,9 @@ template class FullPivHouseholderQR return internal::solve_retval(*this, b.derived()); } - MatrixQType matrixQ(void) const; + /** \returns Expression object representing the matrix Q + */ + MatrixQReturnType matrixQ(void) const; /** \returns a reference to the matrix where the Householder QR decomposition is stored */ @@ -508,28 +509,73 @@ struct solve_retval, Rhs> } }; +/** \ingroup QR_Module + * + * \brief Expression type for return value of FullPivHouseholderQR::matrixQ() + * + * \tparam MatrixType type of underlying dense matrix + */ +template struct FullPivHouseholderQRMatrixQReturnType + : public ReturnByValue > +{ +public: + typedef typename MatrixType::Index Index; + typedef typename internal::plain_col_type::type IntColVectorType; + typedef typename internal::plain_diag_type::type HCoeffsType; + typedef Matrix WorkVectorType; + + FullPivHouseholderQRMatrixQReturnType(const MatrixType& qr, + const HCoeffsType& hCoeffs, + const IntColVectorType& rowsTranspositions) + : m_qr(qr), + m_hCoeffs(hCoeffs), + m_rowsTranspositions(rowsTranspositions) + {} + + template + void evalTo(ResultType& result) const + { + const Index rows = m_qr.rows(); + WorkVectorType workspace(rows); + evalTo(result, workspace); + } + + template + void evalTo(ResultType& result, WorkVectorType& workspace) const + { + // compute the product H'_0 H'_1 ... H'_n-1, + // where H_k is the k-th Householder transformation I - h_k v_k v_k' + // and v_k is the k-th Householder vector [1,m_qr(k+1,k), m_qr(k+2,k), ...] + const Index rows = m_qr.rows(); + const Index cols = m_qr.cols(); + const Index size = (std::min)(rows, cols); + workspace.resize(rows); + result.setIdentity(rows, rows); + for (Index k = size-1; k >= 0; k--) + { + result.block(k, k, rows-k, rows-k) + .applyHouseholderOnTheLeft(m_qr.col(k).tail(rows-k-1), internal::conj(m_hCoeffs.coeff(k)), &workspace.coeffRef(k)); + result.row(k).swap(result.row(m_rowsTranspositions.coeff(k))); + } + } + + Index rows() const { return m_qr.rows(); } + Index cols() const { return m_qr.rows(); } + +protected: + typename MatrixType::Nested m_qr; + typename HCoeffsType::Nested m_hCoeffs; + typename IntColVectorType::Nested m_rowsTranspositions; +}; + } // end namespace internal -/** \returns the matrix Q */ template -typename FullPivHouseholderQR::MatrixQType FullPivHouseholderQR::matrixQ() const +inline typename FullPivHouseholderQR::MatrixQReturnType FullPivHouseholderQR::matrixQ() const { eigen_assert(m_isInitialized && "FullPivHouseholderQR is not initialized."); - // compute the product H'_0 H'_1 ... H'_n-1, - // where H_k is the k-th Householder transformation I - h_k v_k v_k' - // and v_k is the k-th Householder vector [1,m_qr(k+1,k), m_qr(k+2,k), ...] - Index rows = m_qr.rows(); - Index cols = m_qr.cols(); - Index size = (std::min)(rows,cols); - MatrixQType res = MatrixQType::Identity(rows, rows); - Matrix temp(rows); - for (Index k = size-1; k >= 0; k--) - { - res.block(k, k, rows-k, rows-k) - .applyHouseholderOnTheLeft(m_qr.col(k).tail(rows-k-1), internal::conj(m_hCoeffs.coeff(k)), &temp.coeffRef(k)); - res.row(k).swap(res.row(m_rows_transpositions.coeff(k))); - } - return res; + return MatrixQReturnType(m_qr, m_hCoeffs, m_rows_transpositions); } /** \return the full-pivoting Householder QR decomposition of \c *this. @@ -543,4 +589,6 @@ MatrixBase::fullPivHouseholderQr() const return FullPivHouseholderQR(eval()); } +} // end namespace Eigen + #endif // EIGEN_FULLPIVOTINGHOUSEHOLDERQR_H diff --git a/extern/Eigen3/Eigen/src/QR/HouseholderQR.h b/extern/Eigen3/Eigen/src/QR/HouseholderQR.h index 9ee96de2680..5bcb32c1e18 100644 --- a/extern/Eigen3/Eigen/src/QR/HouseholderQR.h +++ b/extern/Eigen3/Eigen/src/QR/HouseholderQR.h @@ -5,28 +5,15 @@ // Copyright (C) 2009 Benoit Jacob // Copyright (C) 2010 Vincent Lejeune // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_QR_H #define EIGEN_QR_H +namespace Eigen { + /** \ingroup QR_Module * * @@ -351,5 +338,6 @@ MatrixBase::householderQr() const return HouseholderQR(eval()); } +} // end namespace Eigen #endif // EIGEN_QR_H diff --git a/extern/Eigen3/Eigen/src/QR/HouseholderQR_MKL.h b/extern/Eigen3/Eigen/src/QR/HouseholderQR_MKL.h new file mode 100644 index 00000000000..5313de604d2 --- /dev/null +++ b/extern/Eigen3/Eigen/src/QR/HouseholderQR_MKL.h @@ -0,0 +1,69 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + 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 Intel Corporation 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. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL + * Householder QR decomposition of a matrix w/o pivoting based on + * LAPACKE_?geqrf function. + ******************************************************************************** +*/ + +#ifndef EIGEN_QR_MKL_H +#define EIGEN_QR_MKL_H + +#include "Eigen/src/Core/util/MKL_support.h" + +namespace Eigen { + +namespace internal { + +/** \internal Specialization for the data types supported by MKL */ + +#define EIGEN_MKL_QR_NOPIV(EIGTYPE, MKLTYPE, MKLPREFIX) \ +template \ +void householder_qr_inplace_blocked(MatrixQR& mat, HCoeffs& hCoeffs, \ + typename MatrixQR::Index maxBlockSize=32, \ + EIGTYPE* tempData = 0) \ +{ \ + lapack_int m = mat.rows(); \ + lapack_int n = mat.cols(); \ + lapack_int lda = mat.outerStride(); \ + lapack_int matrix_order = (MatrixQR::IsRowMajor) ? LAPACK_ROW_MAJOR : LAPACK_COL_MAJOR; \ + LAPACKE_##MKLPREFIX##geqrf( matrix_order, m, n, (MKLTYPE*)mat.data(), lda, (MKLTYPE*)hCoeffs.data()); \ + hCoeffs.adjointInPlace(); \ +\ +} + +EIGEN_MKL_QR_NOPIV(double, double, d) +EIGEN_MKL_QR_NOPIV(float, float, s) +EIGEN_MKL_QR_NOPIV(dcomplex, MKL_Complex16, z) +EIGEN_MKL_QR_NOPIV(scomplex, MKL_Complex8, c) + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_QR_MKL_H diff --git a/extern/Eigen3/Eigen/src/SVD/JacobiSVD.h b/extern/Eigen3/Eigen/src/SVD/JacobiSVD.h index 3c423095c31..a7dbf073766 100644 --- a/extern/Eigen3/Eigen/src/SVD/JacobiSVD.h +++ b/extern/Eigen3/Eigen/src/SVD/JacobiSVD.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009-2010 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_JACOBISVD_H #define EIGEN_JACOBISVD_H +namespace Eigen { + namespace internal { // forward declaration (needed by ICC) // the empty body is required by MSVC @@ -61,9 +48,12 @@ template struct qr_preconditioner_impl {}; template -struct qr_preconditioner_impl +class qr_preconditioner_impl { - static bool run(JacobiSVD&, const MatrixType&) +public: + typedef typename MatrixType::Index Index; + void allocate(const JacobiSVD&) {} + bool run(JacobiSVD&, const MatrixType&) { return false; } @@ -72,134 +62,279 @@ struct qr_preconditioner_impl /*** preconditioner using FullPivHouseholderQR ***/ template -struct qr_preconditioner_impl +class qr_preconditioner_impl { - static bool run(JacobiSVD& svd, const MatrixType& matrix) +public: + typedef typename MatrixType::Index Index; + typedef typename MatrixType::Scalar Scalar; + enum + { + RowsAtCompileTime = MatrixType::RowsAtCompileTime, + MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime + }; + typedef Matrix WorkspaceType; + + void allocate(const JacobiSVD& svd) + { + if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols()) + { + m_qr = FullPivHouseholderQR(svd.rows(), svd.cols()); + } + if (svd.m_computeFullU) m_workspace.resize(svd.rows()); + } + + bool run(JacobiSVD& svd, const MatrixType& matrix) { if(matrix.rows() > matrix.cols()) { - FullPivHouseholderQR qr(matrix); - svd.m_workMatrix = qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView(); - if(svd.m_computeFullU) svd.m_matrixU = qr.matrixQ(); - if(svd.computeV()) svd.m_matrixV = qr.colsPermutation(); + m_qr.compute(matrix); + svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView(); + if(svd.m_computeFullU) m_qr.matrixQ().evalTo(svd.m_matrixU, m_workspace); + if(svd.computeV()) svd.m_matrixV = m_qr.colsPermutation(); return true; } return false; } +private: + FullPivHouseholderQR m_qr; + WorkspaceType m_workspace; }; template -struct qr_preconditioner_impl +class qr_preconditioner_impl { - static bool run(JacobiSVD& svd, const MatrixType& matrix) +public: + typedef typename MatrixType::Index Index; + typedef typename MatrixType::Scalar Scalar; + enum + { + RowsAtCompileTime = MatrixType::RowsAtCompileTime, + ColsAtCompileTime = MatrixType::ColsAtCompileTime, + MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, + MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime, + Options = MatrixType::Options + }; + typedef Matrix + TransposeTypeWithSameStorageOrder; + + void allocate(const JacobiSVD& svd) + { + if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols()) + { + m_qr = FullPivHouseholderQR(svd.cols(), svd.rows()); + } + m_adjoint.resize(svd.cols(), svd.rows()); + if (svd.m_computeFullV) m_workspace.resize(svd.cols()); + } + + bool run(JacobiSVD& svd, const MatrixType& matrix) { if(matrix.cols() > matrix.rows()) { - typedef Matrix - TransposeTypeWithSameStorageOrder; - FullPivHouseholderQR qr(matrix.adjoint()); - svd.m_workMatrix = qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView().adjoint(); - if(svd.m_computeFullV) svd.m_matrixV = qr.matrixQ(); - if(svd.computeU()) svd.m_matrixU = qr.colsPermutation(); + m_adjoint = matrix.adjoint(); + m_qr.compute(m_adjoint); + svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView().adjoint(); + if(svd.m_computeFullV) m_qr.matrixQ().evalTo(svd.m_matrixV, m_workspace); + if(svd.computeU()) svd.m_matrixU = m_qr.colsPermutation(); return true; } else return false; } +private: + FullPivHouseholderQR m_qr; + TransposeTypeWithSameStorageOrder m_adjoint; + typename internal::plain_row_type::type m_workspace; }; /*** preconditioner using ColPivHouseholderQR ***/ template -struct qr_preconditioner_impl +class qr_preconditioner_impl { - static bool run(JacobiSVD& svd, const MatrixType& matrix) +public: + typedef typename MatrixType::Index Index; + + void allocate(const JacobiSVD& svd) + { + if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols()) + { + m_qr = ColPivHouseholderQR(svd.rows(), svd.cols()); + } + if (svd.m_computeFullU) m_workspace.resize(svd.rows()); + else if (svd.m_computeThinU) m_workspace.resize(svd.cols()); + } + + bool run(JacobiSVD& svd, const MatrixType& matrix) { if(matrix.rows() > matrix.cols()) { - ColPivHouseholderQR qr(matrix); - svd.m_workMatrix = qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView(); - if(svd.m_computeFullU) svd.m_matrixU = qr.householderQ(); - else if(svd.m_computeThinU) { + m_qr.compute(matrix); + svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView(); + if(svd.m_computeFullU) m_qr.householderQ().evalTo(svd.m_matrixU, m_workspace); + else if(svd.m_computeThinU) + { svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols()); - qr.householderQ().applyThisOnTheLeft(svd.m_matrixU); + m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixU, m_workspace); } - if(svd.computeV()) svd.m_matrixV = qr.colsPermutation(); + if(svd.computeV()) svd.m_matrixV = m_qr.colsPermutation(); return true; } return false; } + +private: + ColPivHouseholderQR m_qr; + typename internal::plain_col_type::type m_workspace; }; template -struct qr_preconditioner_impl +class qr_preconditioner_impl { - static bool run(JacobiSVD& svd, const MatrixType& matrix) +public: + typedef typename MatrixType::Index Index; + typedef typename MatrixType::Scalar Scalar; + enum + { + RowsAtCompileTime = MatrixType::RowsAtCompileTime, + ColsAtCompileTime = MatrixType::ColsAtCompileTime, + MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, + MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime, + Options = MatrixType::Options + }; + + typedef Matrix + TransposeTypeWithSameStorageOrder; + + void allocate(const JacobiSVD& svd) + { + if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols()) + { + m_qr = ColPivHouseholderQR(svd.cols(), svd.rows()); + } + if (svd.m_computeFullV) m_workspace.resize(svd.cols()); + else if (svd.m_computeThinV) m_workspace.resize(svd.rows()); + m_adjoint.resize(svd.cols(), svd.rows()); + } + + bool run(JacobiSVD& svd, const MatrixType& matrix) { if(matrix.cols() > matrix.rows()) { - typedef Matrix - TransposeTypeWithSameStorageOrder; - ColPivHouseholderQR qr(matrix.adjoint()); - svd.m_workMatrix = qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView().adjoint(); - if(svd.m_computeFullV) svd.m_matrixV = qr.householderQ(); - else if(svd.m_computeThinV) { + m_adjoint = matrix.adjoint(); + m_qr.compute(m_adjoint); + + svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView().adjoint(); + if(svd.m_computeFullV) m_qr.householderQ().evalTo(svd.m_matrixV, m_workspace); + else if(svd.m_computeThinV) + { svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows()); - qr.householderQ().applyThisOnTheLeft(svd.m_matrixV); + m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixV, m_workspace); } - if(svd.computeU()) svd.m_matrixU = qr.colsPermutation(); + if(svd.computeU()) svd.m_matrixU = m_qr.colsPermutation(); return true; } else return false; } + +private: + ColPivHouseholderQR m_qr; + TransposeTypeWithSameStorageOrder m_adjoint; + typename internal::plain_row_type::type m_workspace; }; /*** preconditioner using HouseholderQR ***/ template -struct qr_preconditioner_impl +class qr_preconditioner_impl { - static bool run(JacobiSVD& svd, const MatrixType& matrix) +public: + typedef typename MatrixType::Index Index; + + void allocate(const JacobiSVD& svd) + { + if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols()) + { + m_qr = HouseholderQR(svd.rows(), svd.cols()); + } + if (svd.m_computeFullU) m_workspace.resize(svd.rows()); + else if (svd.m_computeThinU) m_workspace.resize(svd.cols()); + } + + bool run(JacobiSVD& svd, const MatrixType& matrix) { if(matrix.rows() > matrix.cols()) { - HouseholderQR qr(matrix); - svd.m_workMatrix = qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView(); - if(svd.m_computeFullU) svd.m_matrixU = qr.householderQ(); - else if(svd.m_computeThinU) { + m_qr.compute(matrix); + svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.cols(),matrix.cols()).template triangularView(); + if(svd.m_computeFullU) m_qr.householderQ().evalTo(svd.m_matrixU, m_workspace); + else if(svd.m_computeThinU) + { svd.m_matrixU.setIdentity(matrix.rows(), matrix.cols()); - qr.householderQ().applyThisOnTheLeft(svd.m_matrixU); + m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixU, m_workspace); } if(svd.computeV()) svd.m_matrixV.setIdentity(matrix.cols(), matrix.cols()); return true; } return false; } +private: + HouseholderQR m_qr; + typename internal::plain_col_type::type m_workspace; }; template -struct qr_preconditioner_impl +class qr_preconditioner_impl { - static bool run(JacobiSVD& svd, const MatrixType& matrix) +public: + typedef typename MatrixType::Index Index; + typedef typename MatrixType::Scalar Scalar; + enum + { + RowsAtCompileTime = MatrixType::RowsAtCompileTime, + ColsAtCompileTime = MatrixType::ColsAtCompileTime, + MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, + MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime, + Options = MatrixType::Options + }; + + typedef Matrix + TransposeTypeWithSameStorageOrder; + + void allocate(const JacobiSVD& svd) + { + if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols()) + { + m_qr = HouseholderQR(svd.cols(), svd.rows()); + } + if (svd.m_computeFullV) m_workspace.resize(svd.cols()); + else if (svd.m_computeThinV) m_workspace.resize(svd.rows()); + m_adjoint.resize(svd.cols(), svd.rows()); + } + + bool run(JacobiSVD& svd, const MatrixType& matrix) { if(matrix.cols() > matrix.rows()) { - typedef Matrix - TransposeTypeWithSameStorageOrder; - HouseholderQR qr(matrix.adjoint()); - svd.m_workMatrix = qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView().adjoint(); - if(svd.m_computeFullV) svd.m_matrixV = qr.householderQ(); - else if(svd.m_computeThinV) { + m_adjoint = matrix.adjoint(); + m_qr.compute(m_adjoint); + + svd.m_workMatrix = m_qr.matrixQR().block(0,0,matrix.rows(),matrix.rows()).template triangularView().adjoint(); + if(svd.m_computeFullV) m_qr.householderQ().evalTo(svd.m_matrixV, m_workspace); + else if(svd.m_computeThinV) + { svd.m_matrixV.setIdentity(matrix.cols(), matrix.rows()); - qr.householderQ().applyThisOnTheLeft(svd.m_matrixV); + m_qr.householderQ().applyThisOnTheLeft(svd.m_matrixV, m_workspace); } if(svd.computeU()) svd.m_matrixU.setIdentity(matrix.rows(), matrix.rows()); return true; } else return false; } + +private: + HouseholderQR m_qr; + TransposeTypeWithSameStorageOrder m_adjoint; + typename internal::plain_row_type::type m_workspace; }; /*** 2x2 SVD implementation @@ -316,7 +451,7 @@ void real_2x2_jacobi_svd(const MatrixType& matrix, Index p, Index q, * Here's an example demonstrating basic usage: * \include JacobiSVD_basic.cpp * Output: \verbinclude JacobiSVD_basic.out - * + * * This JacobiSVD class is a two-sided Jacobi R-SVD decomposition, ensuring optimal reliability and accuracy. The downside is that it's slower than * bidiagonalizing SVD algorithms for large square matrices; however its complexity is still \f$ O(n^2p) \f$ where \a n is the smaller dimension and * \a p is the greater dimension, meaning that it is still of the same order of complexity as the faster bidiagonalizing R-SVD algorithms. @@ -324,7 +459,7 @@ void real_2x2_jacobi_svd(const MatrixType& matrix, Index p, Index q, * * If the input matrix has inf or nan coefficients, the result of the computation is undefined, but the computation is guaranteed to * terminate in finite (and reasonable) time. - * + * * The possible values for QRPreconditioner are: * \li ColPivHouseholderQRPreconditioner is the default. In practice it's very safe. It uses column-pivoting QR. * \li FullPivHouseholderQRPreconditioner, is the safest and slowest. It uses full-pivoting QR. @@ -494,7 +629,7 @@ template class JacobiSVD * \param b the right-hand-side of the equation to solve. * * \note Solving requires both U and V to be computed. Thin U and V are enough, there is no need for full U or V. - * + * * \note SVD solving is implicitly least-squares. Thus, this method serves both purposes of exact solving and least-squares solving. * In other words, the returned solution is guaranteed to minimize the Euclidean norm \f$ \Vert A x - b \Vert \f$. */ @@ -535,6 +670,9 @@ template class JacobiSVD friend struct internal::svd_precondition_2x2_block_to_be_real; template friend struct internal::qr_preconditioner_impl; + + internal::qr_preconditioner_impl m_qr_precond_morecols; + internal::qr_preconditioner_impl m_qr_precond_morerows; }; template @@ -578,6 +716,9 @@ void JacobiSVD::allocate(Index rows, Index cols, u : m_computeThinV ? m_diagSize : 0); m_workMatrix.resize(m_diagSize, m_diagSize); + + if(m_cols>m_rows) m_qr_precond_morecols.allocate(*this); + if(m_rows>m_cols) m_qr_precond_morerows.allocate(*this); } template @@ -595,8 +736,7 @@ JacobiSVD::compute(const MatrixType& matrix, unsig /*** step 1. The R-SVD step: we use a QR decomposition to reduce to the case of a square matrix */ - if(!internal::qr_preconditioner_impl::run(*this, matrix) - && !internal::qr_preconditioner_impl::run(*this, matrix)) + if(!m_qr_precond_morecols.run(*this, matrix) && !m_qr_precond_morerows.run(*this, matrix)) { m_workMatrix = matrix.block(0,0,m_diagSize,m_diagSize); if(m_computeFullU) m_matrixU.setIdentity(m_rows,m_rows); @@ -722,6 +862,6 @@ MatrixBase::jacobiSvd(unsigned int computationOptions) const return JacobiSVD(*this, computationOptions); } - +} // end namespace Eigen #endif // EIGEN_JACOBISVD_H diff --git a/extern/Eigen3/Eigen/src/SVD/JacobiSVD_MKL.h b/extern/Eigen3/Eigen/src/SVD/JacobiSVD_MKL.h new file mode 100644 index 00000000000..4d479f6b26e --- /dev/null +++ b/extern/Eigen3/Eigen/src/SVD/JacobiSVD_MKL.h @@ -0,0 +1,92 @@ +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + 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 Intel Corporation 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. + + ******************************************************************************** + * Content : Eigen bindings to Intel(R) MKL + * Singular Value Decomposition - SVD. + ******************************************************************************** +*/ + +#ifndef EIGEN_JACOBISVD_MKL_H +#define EIGEN_JACOBISVD_MKL_H + +#include "Eigen/src/Core/util/MKL_support.h" + +namespace Eigen { + +/** \internal Specialization for the data types supported by MKL */ + +#define EIGEN_MKL_SVD(EIGTYPE, MKLTYPE, MKLRTYPE, MKLPREFIX, EIGCOLROW, MKLCOLROW) \ +template<> inline\ +JacobiSVD, ColPivHouseholderQRPreconditioner>& \ +JacobiSVD, ColPivHouseholderQRPreconditioner>::compute(const Matrix& matrix, unsigned int computationOptions) \ +{ \ + typedef Matrix MatrixType; \ + typedef MatrixType::Scalar Scalar; \ + typedef MatrixType::RealScalar RealScalar; \ + allocate(matrix.rows(), matrix.cols(), computationOptions); \ +\ + /*const RealScalar precision = RealScalar(2) * NumTraits::epsilon();*/ \ + m_nonzeroSingularValues = m_diagSize; \ +\ + lapack_int lda = matrix.outerStride(), ldu, ldvt; \ + lapack_int matrix_order = MKLCOLROW; \ + char jobu, jobvt; \ + MKLTYPE *u, *vt, dummy; \ + jobu = (m_computeFullU) ? 'A' : (m_computeThinU) ? 'S' : 'N'; \ + jobvt = (m_computeFullV) ? 'A' : (m_computeThinV) ? 'S' : 'N'; \ + if (computeU()) { \ + ldu = m_matrixU.outerStride(); \ + u = (MKLTYPE*)m_matrixU.data(); \ + } else { ldu=1; u=&dummy; }\ + MatrixType localV; \ + ldvt = (m_computeFullV) ? m_cols : (m_computeThinV) ? m_diagSize : 1; \ + if (computeV()) { \ + localV.resize(ldvt, m_cols); \ + vt = (MKLTYPE*)localV.data(); \ + } else { ldvt=1; vt=&dummy; }\ + Matrix superb; superb.resize(m_diagSize, 1); \ + MatrixType m_temp; m_temp = matrix; \ + LAPACKE_##MKLPREFIX##gesvd( matrix_order, jobu, jobvt, m_rows, m_cols, (MKLTYPE*)m_temp.data(), lda, (MKLRTYPE*)m_singularValues.data(), u, ldu, vt, ldvt, superb.data()); \ + if (computeV()) m_matrixV = localV.adjoint(); \ + /* for(int i=0;i // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_BIDIAGONALIZATION_H #define EIGEN_BIDIAGONALIZATION_H +namespace Eigen { + namespace internal { // UpperBidiagonalization will probably be replaced by a Bidiagonalization class, don't want to make it stable API. // At the same time, it's useful to keep for now as it's about the only thing that is testing the BandMatrix class. @@ -156,4 +143,6 @@ MatrixBase::bidiagonalization() const } // end namespace internal +} // end namespace Eigen + #endif // EIGEN_BIDIAGONALIZATION_H diff --git a/extern/Eigen3/Eigen/src/Sparse/DynamicSparseMatrix.h b/extern/Eigen3/Eigen/src/Sparse/DynamicSparseMatrix.h deleted file mode 100644 index 93e75f4c601..00000000000 --- a/extern/Eigen3/Eigen/src/Sparse/DynamicSparseMatrix.h +++ /dev/null @@ -1,346 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2008-2009 Gael Guennebaud -// -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . - -#ifndef EIGEN_DYNAMIC_SPARSEMATRIX_H -#define EIGEN_DYNAMIC_SPARSEMATRIX_H - -/** \class DynamicSparseMatrix - * - * \brief A sparse matrix class designed for matrix assembly purpose - * - * \param _Scalar the scalar type, i.e. the type of the coefficients - * - * Unlike SparseMatrix, this class provides a much higher degree of flexibility. In particular, it allows - * random read/write accesses in log(rho*outer_size) where \c rho is the probability that a coefficient is - * nonzero and outer_size is the number of columns if the matrix is column-major and the number of rows - * otherwise. - * - * Internally, the data are stored as a std::vector of compressed vector. The performances of random writes might - * decrease as the number of nonzeros per inner-vector increase. In practice, we observed very good performance - * till about 100 nonzeros/vector, and the performance remains relatively good till 500 nonzeros/vectors. - * - * \see SparseMatrix - */ - -namespace internal { -template -struct traits > -{ - typedef _Scalar Scalar; - typedef _Index Index; - typedef Sparse StorageKind; - typedef MatrixXpr XprKind; - enum { - RowsAtCompileTime = Dynamic, - ColsAtCompileTime = Dynamic, - MaxRowsAtCompileTime = Dynamic, - MaxColsAtCompileTime = Dynamic, - Flags = _Options | NestByRefBit | LvalueBit, - CoeffReadCost = NumTraits::ReadCost, - SupportedAccessPatterns = OuterRandomAccessPattern - }; -}; -} - -template -class DynamicSparseMatrix - : public SparseMatrixBase > -{ - public: - EIGEN_SPARSE_PUBLIC_INTERFACE(DynamicSparseMatrix) - // FIXME: why are these operator already alvailable ??? - // EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(DynamicSparseMatrix, +=) - // EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(DynamicSparseMatrix, -=) - typedef MappedSparseMatrix Map; - using Base::IsRowMajor; - using Base::operator=; - enum { - Options = _Options - }; - - protected: - - typedef DynamicSparseMatrix TransposedSparseMatrix; - - Index m_innerSize; - std::vector > m_data; - - public: - - inline Index rows() const { return IsRowMajor ? outerSize() : m_innerSize; } - inline Index cols() const { return IsRowMajor ? m_innerSize : outerSize(); } - inline Index innerSize() const { return m_innerSize; } - inline Index outerSize() const { return static_cast(m_data.size()); } - inline Index innerNonZeros(Index j) const { return m_data[j].size(); } - - std::vector >& _data() { return m_data; } - const std::vector >& _data() const { return m_data; } - - /** \returns the coefficient value at given position \a row, \a col - * This operation involes a log(rho*outer_size) binary search. - */ - inline Scalar coeff(Index row, Index col) const - { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - return m_data[outer].at(inner); - } - - /** \returns a reference to the coefficient value at given position \a row, \a col - * This operation involes a log(rho*outer_size) binary search. If the coefficient does not - * exist yet, then a sorted insertion into a sequential buffer is performed. - */ - inline Scalar& coeffRef(Index row, Index col) - { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - return m_data[outer].atWithInsertion(inner); - } - - class InnerIterator; - - void setZero() - { - for (Index j=0; j(m_data[j].size()); - return res; - } - - - - void reserve(Index reserveSize = 1000) - { - if (outerSize()>0) - { - Index reserveSizePerVector = (std::max)(reserveSize/outerSize(),Index(4)); - for (Index j=0; j(m_data[outer].size()) - 1; - m_data[outer].resize(id+2,1); - - while ( (id >= startId) && (m_data[outer].index(id) > inner) ) - { - m_data[outer].index(id+1) = m_data[outer].index(id); - m_data[outer].value(id+1) = m_data[outer].value(id); - --id; - } - m_data[outer].index(id+1) = inner; - m_data[outer].value(id+1) = 0; - return m_data[outer].value(id+1); - } - - /** Does nothing: provided for compatibility with SparseMatrix */ - inline void finalize() {} - - /** Suppress all nonzeros which are smaller than \a reference under the tolerence \a epsilon */ - void prune(Scalar reference, RealScalar epsilon = NumTraits::dummy_precision()) - { - for (Index j=0; jinnerSize) - { - // remove all coefficients with innerCoord>=innerSize - // TODO - //std::cerr << "not implemented yet\n"; - exit(2); - } - if (m_data.size() != outerSize) - { - m_data.resize(outerSize); - } - } - - inline DynamicSparseMatrix() - : m_innerSize(0), m_data(0) - { - eigen_assert(innerSize()==0 && outerSize()==0); - } - - inline DynamicSparseMatrix(Index rows, Index cols) - : m_innerSize(0) - { - resize(rows, cols); - } - - template - explicit inline DynamicSparseMatrix(const SparseMatrixBase& other) - : m_innerSize(0) - { - Base::operator=(other.derived()); - } - - inline DynamicSparseMatrix(const DynamicSparseMatrix& other) - : Base(), m_innerSize(0) - { - *this = other.derived(); - } - - inline void swap(DynamicSparseMatrix& other) - { - //EIGEN_DBG_SPARSE(std::cout << "SparseMatrix:: swap\n"); - std::swap(m_innerSize, other.m_innerSize); - //std::swap(m_outerSize, other.m_outerSize); - m_data.swap(other.m_data); - } - - inline DynamicSparseMatrix& operator=(const DynamicSparseMatrix& other) - { - if (other.isRValue()) - { - swap(other.const_cast_derived()); - } - else - { - resize(other.rows(), other.cols()); - m_data = other.m_data; - } - return *this; - } - - /** Destructor */ - inline ~DynamicSparseMatrix() {} - - public: - - /** \deprecated - * Set the matrix to zero and reserve the memory for \a reserveSize nonzero coefficients. */ - EIGEN_DEPRECATED void startFill(Index reserveSize = 1000) - { - setZero(); - reserve(reserveSize); - } - - /** \deprecated use insert() - * inserts a nonzero coefficient at given coordinates \a row, \a col and returns its reference assuming that: - * 1 - the coefficient does not exist yet - * 2 - this the coefficient with greater inner coordinate for the given outer coordinate. - * In other words, assuming \c *this is column-major, then there must not exists any nonzero coefficient of coordinates - * \c i \c x \a col such that \c i >= \a row. Otherwise the matrix is invalid. - * - * \see fillrand(), coeffRef() - */ - EIGEN_DEPRECATED Scalar& fill(Index row, Index col) - { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - return insertBack(outer,inner); - } - - /** \deprecated use insert() - * Like fill() but with random inner coordinates. - * Compared to the generic coeffRef(), the unique limitation is that we assume - * the coefficient does not exist yet. - */ - EIGEN_DEPRECATED Scalar& fillrand(Index row, Index col) - { - return insert(row,col); - } - - /** \deprecated use finalize() - * Does nothing. Provided for compatibility with SparseMatrix. */ - EIGEN_DEPRECATED void endFill() {} - -# ifdef EIGEN_DYNAMICSPARSEMATRIX_PLUGIN -# include EIGEN_DYNAMICSPARSEMATRIX_PLUGIN -# endif -}; - -template -class DynamicSparseMatrix::InnerIterator : public SparseVector::InnerIterator -{ - typedef typename SparseVector::InnerIterator Base; - public: - InnerIterator(const DynamicSparseMatrix& mat, Index outer) - : Base(mat.m_data[outer]), m_outer(outer) - {} - - inline Index row() const { return IsRowMajor ? m_outer : Base::index(); } - inline Index col() const { return IsRowMajor ? Base::index() : m_outer; } - - protected: - const Index m_outer; -}; - -#endif // EIGEN_DYNAMIC_SPARSEMATRIX_H diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseCwiseUnaryOp.h b/extern/Eigen3/Eigen/src/Sparse/SparseCwiseUnaryOp.h deleted file mode 100644 index aa068835fbb..00000000000 --- a/extern/Eigen3/Eigen/src/Sparse/SparseCwiseUnaryOp.h +++ /dev/null @@ -1,146 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2008-2010 Gael Guennebaud -// -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . - -#ifndef EIGEN_SPARSE_CWISE_UNARY_OP_H -#define EIGEN_SPARSE_CWISE_UNARY_OP_H - -// template -// struct internal::traits > : internal::traits -// { -// typedef typename internal::result_of< -// UnaryOp(typename MatrixType::Scalar) -// >::type Scalar; -// typedef typename MatrixType::Nested MatrixTypeNested; -// typedef typename internal::remove_reference::type _MatrixTypeNested; -// enum { -// CoeffReadCost = _MatrixTypeNested::CoeffReadCost + internal::functor_traits::Cost -// }; -// }; - -template -class CwiseUnaryOpImpl - : public SparseMatrixBase > -{ - public: - - class InnerIterator; -// typedef typename internal::remove_reference::type _LhsNested; - - typedef CwiseUnaryOp Derived; - EIGEN_SPARSE_PUBLIC_INTERFACE(Derived) -}; - -template -class CwiseUnaryOpImpl::InnerIterator -{ - typedef typename CwiseUnaryOpImpl::Scalar Scalar; - typedef typename internal::traits::_XprTypeNested _MatrixTypeNested; - typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator; - typedef typename MatrixType::Index Index; - public: - - EIGEN_STRONG_INLINE InnerIterator(const CwiseUnaryOpImpl& unaryOp, Index outer) - : m_iter(unaryOp.derived().nestedExpression(),outer), m_functor(unaryOp.derived().functor()) - {} - - EIGEN_STRONG_INLINE InnerIterator& operator++() - { ++m_iter; return *this; } - - EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_iter.value()); } - - EIGEN_STRONG_INLINE Index index() const { return m_iter.index(); } - EIGEN_STRONG_INLINE Index row() const { return m_iter.row(); } - EIGEN_STRONG_INLINE Index col() const { return m_iter.col(); } - - EIGEN_STRONG_INLINE operator bool() const { return m_iter; } - - protected: - MatrixTypeIterator m_iter; - const UnaryOp m_functor; -}; - -template -class CwiseUnaryViewImpl - : public SparseMatrixBase > -{ - public: - - class InnerIterator; -// typedef typename internal::remove_reference::type _LhsNested; - - typedef CwiseUnaryView Derived; - EIGEN_SPARSE_PUBLIC_INTERFACE(Derived) -}; - -template -class CwiseUnaryViewImpl::InnerIterator -{ - typedef typename CwiseUnaryViewImpl::Scalar Scalar; - typedef typename internal::traits::_MatrixTypeNested _MatrixTypeNested; - typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator; - typedef typename MatrixType::Index Index; - public: - - EIGEN_STRONG_INLINE InnerIterator(const CwiseUnaryViewImpl& unaryView, Index outer) - : m_iter(unaryView.derived().nestedExpression(),outer), m_functor(unaryView.derived().functor()) - {} - - EIGEN_STRONG_INLINE InnerIterator& operator++() - { ++m_iter; return *this; } - - EIGEN_STRONG_INLINE Scalar value() const { return m_functor(m_iter.value()); } - EIGEN_STRONG_INLINE Scalar& valueRef() { return m_functor(m_iter.valueRef()); } - - EIGEN_STRONG_INLINE Index index() const { return m_iter.index(); } - EIGEN_STRONG_INLINE Index row() const { return m_iter.row(); } - EIGEN_STRONG_INLINE Index col() const { return m_iter.col(); } - - EIGEN_STRONG_INLINE operator bool() const { return m_iter; } - - protected: - MatrixTypeIterator m_iter; - const ViewOp m_functor; -}; - -template -EIGEN_STRONG_INLINE Derived& -SparseMatrixBase::operator*=(const Scalar& other) -{ - for (Index j=0; j -EIGEN_STRONG_INLINE Derived& -SparseMatrixBase::operator/=(const Scalar& other) -{ - for (Index j=0; j -// -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . - -#ifndef EIGEN_SPARSE_FUZZY_H -#define EIGEN_SPARSE_FUZZY_H - -// template -// template -// bool SparseMatrixBase::isApprox( -// const OtherDerived& other, -// typename NumTraits::Real prec -// ) const -// { -// const typename internal::nested::type nested(derived()); -// const typename internal::nested::type otherNested(other.derived()); -// return (nested - otherNested).cwise().abs2().sum() -// <= prec * prec * (std::min)(nested.cwise().abs2().sum(), otherNested.cwise().abs2().sum()); -// } - -#endif // EIGEN_SPARSE_FUZZY_H diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseMatrix.h b/extern/Eigen3/Eigen/src/Sparse/SparseMatrix.h deleted file mode 100644 index 0e175ec6e71..00000000000 --- a/extern/Eigen3/Eigen/src/Sparse/SparseMatrix.h +++ /dev/null @@ -1,651 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2008-2010 Gael Guennebaud -// -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . - -#ifndef EIGEN_SPARSEMATRIX_H -#define EIGEN_SPARSEMATRIX_H - -/** \ingroup Sparse_Module - * - * \class SparseMatrix - * - * \brief The main sparse matrix class - * - * This class implements a sparse matrix using the very common compressed row/column storage - * scheme. - * - * \tparam _Scalar the scalar type, i.e. the type of the coefficients - * \tparam _Options Union of bit flags controlling the storage scheme. Currently the only possibility - * is RowMajor. The default is 0 which means column-major. - * \tparam _Index the type of the indices. Default is \c int. - * - * See http://www.netlib.org/linalg/html_templates/node91.html for details on the storage scheme. - * - * This class can be extended with the help of the plugin mechanism described on the page - * \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_SPARSEMATRIX_PLUGIN. - */ - -namespace internal { -template -struct traits > -{ - typedef _Scalar Scalar; - typedef _Index Index; - typedef Sparse StorageKind; - typedef MatrixXpr XprKind; - enum { - RowsAtCompileTime = Dynamic, - ColsAtCompileTime = Dynamic, - MaxRowsAtCompileTime = Dynamic, - MaxColsAtCompileTime = Dynamic, - Flags = _Options | NestByRefBit | LvalueBit, - CoeffReadCost = NumTraits::ReadCost, - SupportedAccessPatterns = InnerRandomAccessPattern - }; -}; - -} // end namespace internal - -template -class SparseMatrix - : public SparseMatrixBase > -{ - public: - EIGEN_SPARSE_PUBLIC_INTERFACE(SparseMatrix) -// using Base::operator=; - EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseMatrix, +=) - EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseMatrix, -=) - // FIXME: why are these operator already alvailable ??? - // EIGEN_SPARSE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(SparseMatrix, *=) - // EIGEN_SPARSE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(SparseMatrix, /=) - - typedef MappedSparseMatrix Map; - using Base::IsRowMajor; - typedef CompressedStorage Storage; - enum { - Options = _Options - }; - - protected: - - typedef SparseMatrix TransposedSparseMatrix; - - Index m_outerSize; - Index m_innerSize; - Index* m_outerIndex; - CompressedStorage m_data; - - public: - - inline Index rows() const { return IsRowMajor ? m_outerSize : m_innerSize; } - inline Index cols() const { return IsRowMajor ? m_innerSize : m_outerSize; } - - inline Index innerSize() const { return m_innerSize; } - inline Index outerSize() const { return m_outerSize; } - inline Index innerNonZeros(Index j) const { return m_outerIndex[j+1]-m_outerIndex[j]; } - - inline const Scalar* _valuePtr() const { return &m_data.value(0); } - inline Scalar* _valuePtr() { return &m_data.value(0); } - - inline const Index* _innerIndexPtr() const { return &m_data.index(0); } - inline Index* _innerIndexPtr() { return &m_data.index(0); } - - inline const Index* _outerIndexPtr() const { return m_outerIndex; } - inline Index* _outerIndexPtr() { return m_outerIndex; } - - inline Storage& data() { return m_data; } - inline const Storage& data() const { return m_data; } - - inline Scalar coeff(Index row, Index col) const - { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - return m_data.atInRange(m_outerIndex[outer], m_outerIndex[outer+1], inner); - } - - inline Scalar& coeffRef(Index row, Index col) - { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - - Index start = m_outerIndex[outer]; - Index end = m_outerIndex[outer+1]; - eigen_assert(end>=start && "you probably called coeffRef on a non finalized matrix"); - eigen_assert(end>start && "coeffRef cannot be called on a zero coefficient"); - const Index p = m_data.searchLowerIndex(start,end-1,inner); - eigen_assert((p(m_data.size()); } - - /** Preallocates \a reserveSize non zeros */ - inline void reserve(Index reserveSize) - { - m_data.reserve(reserveSize); - } - - //--- low level purely coherent filling --- - - /** \returns a reference to the non zero coefficient at position \a row, \a col assuming that: - * - the nonzero does not already exist - * - the new coefficient is the last one according to the storage order - * - * Before filling a given inner vector you must call the statVec(Index) function. - * - * After an insertion session, you should call the finalize() function. - * - * \sa insert, insertBackByOuterInner, startVec */ - inline Scalar& insertBack(Index row, Index col) - { - return insertBackByOuterInner(IsRowMajor?row:col, IsRowMajor?col:row); - } - - /** \sa insertBack, startVec */ - inline Scalar& insertBackByOuterInner(Index outer, Index inner) - { - eigen_assert(size_t(m_outerIndex[outer+1]) == m_data.size() && "Invalid ordered insertion (invalid outer index)"); - eigen_assert( (m_outerIndex[outer+1]-m_outerIndex[outer]==0 || m_data.index(m_data.size()-1)=0 && m_outerIndex[previousOuter]==0) - { - m_outerIndex[previousOuter] = static_cast(m_data.size()); - --previousOuter; - } - m_outerIndex[outer+1] = m_outerIndex[outer]; - } - - // here we have to handle the tricky case where the outerIndex array - // starts with: [ 0 0 0 0 0 1 ...] and we are inserting in, e.g., - // the 2nd inner vector... - bool isLastVec = (!(previousOuter==-1 && m_data.size()!=0)) - && (size_t(m_outerIndex[outer+1]) == m_data.size()); - - size_t startId = m_outerIndex[outer]; - // FIXME let's make sure sizeof(long int) == sizeof(size_t) - size_t p = m_outerIndex[outer+1]; - ++m_outerIndex[outer+1]; - - float reallocRatio = 1; - if (m_data.allocatedSize()<=m_data.size()) - { - // if there is no preallocated memory, let's reserve a minimum of 32 elements - if (m_data.size()==0) - { - m_data.reserve(32); - } - else - { - // we need to reallocate the data, to reduce multiple reallocations - // we use a smart resize algorithm based on the current filling ratio - // in addition, we use float to avoid integers overflows - float nnzEstimate = float(m_outerIndex[outer])*float(m_outerSize)/float(outer+1); - reallocRatio = (nnzEstimate-float(m_data.size()))/float(m_data.size()); - // furthermore we bound the realloc ratio to: - // 1) reduce multiple minor realloc when the matrix is almost filled - // 2) avoid to allocate too much memory when the matrix is almost empty - reallocRatio = (std::min)((std::max)(reallocRatio,1.5f),8.f); - } - } - m_data.resize(m_data.size()+1,reallocRatio); - - if (!isLastVec) - { - if (previousOuter==-1) - { - // oops wrong guess. - // let's correct the outer offsets - for (Index k=0; k<=(outer+1); ++k) - m_outerIndex[k] = 0; - Index k=outer+1; - while(m_outerIndex[k]==0) - m_outerIndex[k++] = 1; - while (k<=m_outerSize && m_outerIndex[k]!=0) - m_outerIndex[k++]++; - p = 0; - --k; - k = m_outerIndex[k]-1; - while (k>0) - { - m_data.index(k) = m_data.index(k-1); - m_data.value(k) = m_data.value(k-1); - k--; - } - } - else - { - // we are not inserting into the last inner vec - // update outer indices: - Index j = outer+2; - while (j<=m_outerSize && m_outerIndex[j]!=0) - m_outerIndex[j++]++; - --j; - // shift data of last vecs: - Index k = m_outerIndex[j]-1; - while (k>=Index(p)) - { - m_data.index(k) = m_data.index(k-1); - m_data.value(k) = m_data.value(k-1); - k--; - } - } - } - - while ( (p > startId) && (m_data.index(p-1) > inner) ) - { - m_data.index(p) = m_data.index(p-1); - m_data.value(p) = m_data.value(p-1); - --p; - } - - m_data.index(p) = inner; - return (m_data.value(p) = 0); - } - - - - - /** Must be called after inserting a set of non zero entries. - */ - inline void finalize() - { - Index size = static_cast(m_data.size()); - Index i = m_outerSize; - // find the last filled column - while (i>=0 && m_outerIndex[i]==0) - --i; - ++i; - while (i<=m_outerSize) - { - m_outerIndex[i] = size; - ++i; - } - } - - /** Suppress all nonzeros which are smaller than \a reference under the tolerence \a epsilon */ - void prune(Scalar reference, RealScalar epsilon = NumTraits::dummy_precision()) - { - prune(default_prunning_func(reference,epsilon)); - } - - /** Suppress all nonzeros which do not satisfy the predicate \a keep. - * The functor type \a KeepFunc must implement the following function: - * \code - * bool operator() (const Index& row, const Index& col, const Scalar& value) const; - * \endcode - * \sa prune(Scalar,RealScalar) - */ - template - void prune(const KeepFunc& keep = KeepFunc()) - { - Index k = 0; - for(Index j=0; j - inline SparseMatrix(const SparseMatrixBase& other) - : m_outerSize(0), m_innerSize(0), m_outerIndex(0) - { - *this = other.derived(); - } - - /** Copy constructor */ - inline SparseMatrix(const SparseMatrix& other) - : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0) - { - *this = other.derived(); - } - - /** Swap the content of two sparse matrices of same type (optimization) */ - inline void swap(SparseMatrix& other) - { - //EIGEN_DBG_SPARSE(std::cout << "SparseMatrix:: swap\n"); - std::swap(m_outerIndex, other.m_outerIndex); - std::swap(m_innerSize, other.m_innerSize); - std::swap(m_outerSize, other.m_outerSize); - m_data.swap(other.m_data); - } - - inline SparseMatrix& operator=(const SparseMatrix& other) - { -// std::cout << "SparseMatrix& operator=(const SparseMatrix& other)\n"; - if (other.isRValue()) - { - swap(other.const_cast_derived()); - } - else - { - resize(other.rows(), other.cols()); - memcpy(m_outerIndex, other.m_outerIndex, (m_outerSize+1)*sizeof(Index)); - m_data = other.m_data; - } - return *this; - } - - #ifndef EIGEN_PARSED_BY_DOXYGEN - template - inline SparseMatrix& operator=(const SparseSparseProduct& product) - { return Base::operator=(product); } - - template - inline SparseMatrix& operator=(const ReturnByValue& other) - { return Base::operator=(other); } - - template - inline SparseMatrix& operator=(const EigenBase& other) - { return Base::operator=(other); } - #endif - - template - EIGEN_DONT_INLINE SparseMatrix& operator=(const SparseMatrixBase& other) - { - const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit); - if (needToTranspose) - { - // two passes algorithm: - // 1 - compute the number of coeffs per dest inner vector - // 2 - do the actual copy/eval - // Since each coeff of the rhs has to be evaluated twice, let's evaluate it if needed - typedef typename internal::nested::type OtherCopy; - typedef typename internal::remove_all::type _OtherCopy; - OtherCopy otherCopy(other.derived()); - - resize(other.rows(), other.cols()); - Eigen::Map > (m_outerIndex,outerSize()).setZero(); - // pass 1 - // FIXME the above copy could be merged with that pass - for (Index j=0; j::operator=(other.derived()); - } - } - - friend std::ostream & operator << (std::ostream & s, const SparseMatrix& m) - { - EIGEN_DBG_SPARSE( - s << "Nonzero entries:\n"; - for (Index i=0; i&>(m); - return s; - } - - /** Destructor */ - inline ~SparseMatrix() - { - delete[] m_outerIndex; - } - - /** Overloaded for performance */ - Scalar sum() const; - - public: - - /** \deprecated use setZero() and reserve() - * Initializes the filling process of \c *this. - * \param reserveSize approximate number of nonzeros - * Note that the matrix \c *this is zero-ed. - */ - EIGEN_DEPRECATED void startFill(Index reserveSize = 1000) - { - setZero(); - m_data.reserve(reserveSize); - } - - /** \deprecated use insert() - * Like fill() but with random inner coordinates. - */ - EIGEN_DEPRECATED Scalar& fillrand(Index row, Index col) - { - return insert(row,col); - } - - /** \deprecated use insert() - */ - EIGEN_DEPRECATED Scalar& fill(Index row, Index col) - { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - - if (m_outerIndex[outer+1]==0) - { - // we start a new inner vector - Index i = outer; - while (i>=0 && m_outerIndex[i]==0) - { - m_outerIndex[i] = m_data.size(); - --i; - } - m_outerIndex[outer+1] = m_outerIndex[outer]; - } - else - { - eigen_assert(m_data.index(m_data.size()-1) -class SparseMatrix::InnerIterator -{ - public: - InnerIterator(const SparseMatrix& mat, Index outer) - : m_values(mat._valuePtr()), m_indices(mat._innerIndexPtr()), m_outer(outer), m_id(mat.m_outerIndex[outer]), m_end(mat.m_outerIndex[outer+1]) - {} - - inline InnerIterator& operator++() { m_id++; return *this; } - - inline const Scalar& value() const { return m_values[m_id]; } - inline Scalar& valueRef() { return const_cast(m_values[m_id]); } - - inline Index index() const { return m_indices[m_id]; } - inline Index outer() const { return m_outer; } - inline Index row() const { return IsRowMajor ? m_outer : index(); } - inline Index col() const { return IsRowMajor ? index() : m_outer; } - - inline operator bool() const { return (m_id < m_end); } - - protected: - const Scalar* m_values; - const Index* m_indices; - const Index m_outer; - Index m_id; - const Index m_end; -}; - -#endif // EIGEN_SPARSEMATRIX_H diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseSparseProduct.h b/extern/Eigen3/Eigen/src/Sparse/SparseSparseProduct.h deleted file mode 100644 index 19abcd1f8e4..00000000000 --- a/extern/Eigen3/Eigen/src/Sparse/SparseSparseProduct.h +++ /dev/null @@ -1,401 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2008-2010 Gael Guennebaud -// -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . - -#ifndef EIGEN_SPARSESPARSEPRODUCT_H -#define EIGEN_SPARSESPARSEPRODUCT_H - -namespace internal { - -template -static void sparse_product_impl2(const Lhs& lhs, const Rhs& rhs, ResultType& res) -{ - typedef typename remove_all::type::Scalar Scalar; - typedef typename remove_all::type::Index Index; - - // make sure to call innerSize/outerSize since we fake the storage order. - Index rows = lhs.innerSize(); - Index cols = rhs.outerSize(); - eigen_assert(lhs.outerSize() == rhs.innerSize()); - - std::vector mask(rows,false); - Matrix values(rows); - Matrix indices(rows); - - // estimate the number of non zero entries - float ratioLhs = float(lhs.nonZeros())/(float(lhs.rows())*float(lhs.cols())); - float avgNnzPerRhsColumn = float(rhs.nonZeros())/float(cols); - float ratioRes = (std::min)(ratioLhs * avgNnzPerRhsColumn, 1.f); - -// int t200 = rows/(log2(200)*1.39); -// int t = (rows*100)/139; - - res.resize(rows, cols); - res.reserve(Index(ratioRes*rows*cols)); - // we compute each column of the result, one after the other - for (Index j=0; j use a quick sort - // otherwise => loop through the entire vector - // In order to avoid to perform an expensive log2 when the - // result is clearly very sparse we use a linear bound up to 200. -// if((nnz<200 && nnz1) std::sort(indices.data(),indices.data()+nnz); -// for(int k=0; k -static void sparse_product_impl(const Lhs& lhs, const Rhs& rhs, ResultType& res) -{ -// return sparse_product_impl2(lhs,rhs,res); - - typedef typename remove_all::type::Scalar Scalar; - typedef typename remove_all::type::Index Index; - - // make sure to call innerSize/outerSize since we fake the storage order. - Index rows = lhs.innerSize(); - Index cols = rhs.outerSize(); - //int size = lhs.outerSize(); - eigen_assert(lhs.outerSize() == rhs.innerSize()); - - // allocate a temporary buffer - AmbiVector tempVector(rows); - - // estimate the number of non zero entries - float ratioLhs = float(lhs.nonZeros())/(float(lhs.rows())*float(lhs.cols())); - float avgNnzPerRhsColumn = float(rhs.nonZeros())/float(cols); - float ratioRes = (std::min)(ratioLhs * avgNnzPerRhsColumn, 1.f); - - // mimics a resizeByInnerOuter: - if(ResultType::IsRowMajor) - res.resize(cols, rows); - else - res.resize(rows, cols); - - res.reserve(Index(ratioRes*rows*cols)); - for (Index j=0; j::Iterator it(tempVector); it; ++it) - res.insertBackByOuterInner(j,it.index()) = it.value(); - } - res.finalize(); -} - -template::Flags&RowMajorBit, - int RhsStorageOrder = traits::Flags&RowMajorBit, - int ResStorageOrder = traits::Flags&RowMajorBit> -struct sparse_product_selector; - -template -struct sparse_product_selector -{ - typedef typename traits::type>::Scalar Scalar; - - static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) - { -// std::cerr << __LINE__ << "\n"; - typename remove_all::type _res(res.rows(), res.cols()); - sparse_product_impl(lhs, rhs, _res); - res.swap(_res); - } -}; - -template -struct sparse_product_selector -{ - static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) - { -// std::cerr << __LINE__ << "\n"; - // we need a col-major matrix to hold the result - typedef SparseMatrix SparseTemporaryType; - SparseTemporaryType _res(res.rows(), res.cols()); - sparse_product_impl(lhs, rhs, _res); - res = _res; - } -}; - -template -struct sparse_product_selector -{ - static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) - { -// std::cerr << __LINE__ << "\n"; - // let's transpose the product to get a column x column product - typename remove_all::type _res(res.rows(), res.cols()); - sparse_product_impl(rhs, lhs, _res); - res.swap(_res); - } -}; - -template -struct sparse_product_selector -{ - static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) - { -// std::cerr << "here...\n"; - typedef SparseMatrix ColMajorMatrix; - ColMajorMatrix colLhs(lhs); - ColMajorMatrix colRhs(rhs); -// std::cerr << "more...\n"; - sparse_product_impl(colLhs, colRhs, res); -// std::cerr << "OK.\n"; - - // let's transpose the product to get a column x column product - -// typedef SparseMatrix SparseTemporaryType; -// SparseTemporaryType _res(res.cols(), res.rows()); -// sparse_product_impl(rhs, lhs, _res); -// res = _res.transpose(); - } -}; - -// NOTE the 2 others cases (col row *) must never occur since they are caught -// by ProductReturnType which transforms it to (col col *) by evaluating rhs. - -} // end namespace internal - -// sparse = sparse * sparse -template -template -inline Derived& SparseMatrixBase::operator=(const SparseSparseProduct& product) -{ -// std::cerr << "there..." << typeid(Lhs).name() << " " << typeid(Lhs).name() << " " << (Derived::Flags&&RowMajorBit) << "\n"; - internal::sparse_product_selector< - typename internal::remove_all::type, - typename internal::remove_all::type, - Derived>::run(product.lhs(),product.rhs(),derived()); - return derived(); -} - -namespace internal { - -template::Flags&RowMajorBit, - int RhsStorageOrder = traits::Flags&RowMajorBit, - int ResStorageOrder = traits::Flags&RowMajorBit> -struct sparse_product_selector2; - -template -struct sparse_product_selector2 -{ - typedef typename traits::type>::Scalar Scalar; - - static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) - { - sparse_product_impl2(lhs, rhs, res); - } -}; - -template -struct sparse_product_selector2 -{ - static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) - { - // prevent warnings until the code is fixed - EIGEN_UNUSED_VARIABLE(lhs); - EIGEN_UNUSED_VARIABLE(rhs); - EIGEN_UNUSED_VARIABLE(res); - -// typedef SparseMatrix RowMajorMatrix; -// RowMajorMatrix rhsRow = rhs; -// RowMajorMatrix resRow(res.rows(), res.cols()); -// sparse_product_impl2(rhsRow, lhs, resRow); -// res = resRow; - } -}; - -template -struct sparse_product_selector2 -{ - static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) - { - typedef SparseMatrix RowMajorMatrix; - RowMajorMatrix lhsRow = lhs; - RowMajorMatrix resRow(res.rows(), res.cols()); - sparse_product_impl2(rhs, lhsRow, resRow); - res = resRow; - } -}; - -template -struct sparse_product_selector2 -{ - static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) - { - typedef SparseMatrix RowMajorMatrix; - RowMajorMatrix resRow(res.rows(), res.cols()); - sparse_product_impl2(rhs, lhs, resRow); - res = resRow; - } -}; - - -template -struct sparse_product_selector2 -{ - typedef typename traits::type>::Scalar Scalar; - - static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) - { - typedef SparseMatrix ColMajorMatrix; - ColMajorMatrix resCol(res.rows(), res.cols()); - sparse_product_impl2(lhs, rhs, resCol); - res = resCol; - } -}; - -template -struct sparse_product_selector2 -{ - static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) - { - typedef SparseMatrix ColMajorMatrix; - ColMajorMatrix lhsCol = lhs; - ColMajorMatrix resCol(res.rows(), res.cols()); - sparse_product_impl2(lhsCol, rhs, resCol); - res = resCol; - } -}; - -template -struct sparse_product_selector2 -{ - static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) - { - typedef SparseMatrix ColMajorMatrix; - ColMajorMatrix rhsCol = rhs; - ColMajorMatrix resCol(res.rows(), res.cols()); - sparse_product_impl2(lhs, rhsCol, resCol); - res = resCol; - } -}; - -template -struct sparse_product_selector2 -{ - static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) - { - typedef SparseMatrix ColMajorMatrix; -// ColMajorMatrix lhsTr(lhs); -// ColMajorMatrix rhsTr(rhs); -// ColMajorMatrix aux(res.rows(), res.cols()); -// sparse_product_impl2(rhs, lhs, aux); -// // ColMajorMatrix aux2 = aux.transpose(); -// res = aux; - typedef SparseMatrix ColMajorMatrix; - ColMajorMatrix lhsCol(lhs); - ColMajorMatrix rhsCol(rhs); - ColMajorMatrix resCol(res.rows(), res.cols()); - sparse_product_impl2(lhsCol, rhsCol, resCol); - res = resCol; - } -}; - -} // end namespace internal - -template -template -inline void SparseMatrixBase::_experimentalNewProduct(const Lhs& lhs, const Rhs& rhs) -{ - //derived().resize(lhs.rows(), rhs.cols()); - internal::sparse_product_selector2< - typename internal::remove_all::type, - typename internal::remove_all::type, - Derived>::run(lhs,rhs,derived()); -} - -// sparse * sparse -template -template -inline const typename SparseSparseProductReturnType::Type -SparseMatrixBase::operator*(const SparseMatrixBase &other) const -{ - return typename SparseSparseProductReturnType::Type(derived(), other.derived()); -} - -#endif // EIGEN_SPARSESPARSEPRODUCT_H diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseTriangularView.h b/extern/Eigen3/Eigen/src/Sparse/SparseTriangularView.h deleted file mode 100644 index 319eaf06638..00000000000 --- a/extern/Eigen3/Eigen/src/Sparse/SparseTriangularView.h +++ /dev/null @@ -1,100 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. -// -// Copyright (C) 2009 Gael Guennebaud -// -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . - -#ifndef EIGEN_SPARSE_TRIANGULARVIEW_H -#define EIGEN_SPARSE_TRIANGULARVIEW_H - -namespace internal { - -template -struct traits > -: public traits -{}; - -} // namespace internal - -template class SparseTriangularView - : public SparseMatrixBase > -{ - enum { SkipFirst = (Mode==Lower && !(MatrixType::Flags&RowMajorBit)) - || (Mode==Upper && (MatrixType::Flags&RowMajorBit)) }; - public: - - EIGEN_SPARSE_PUBLIC_INTERFACE(SparseTriangularView) - - class InnerIterator; - - inline Index rows() const { return m_matrix.rows(); } - inline Index cols() const { return m_matrix.cols(); } - - typedef typename internal::conditional::ret, - MatrixType, const MatrixType&>::type MatrixTypeNested; - - inline SparseTriangularView(const MatrixType& matrix) : m_matrix(matrix) {} - - /** \internal */ - inline const MatrixType& nestedExpression() const { return m_matrix; } - - template - typename internal::plain_matrix_type_column_major::type - solve(const MatrixBase& other) const; - - template void solveInPlace(MatrixBase& other) const; - template void solveInPlace(SparseMatrixBase& other) const; - - protected: - MatrixTypeNested m_matrix; -}; - -template -class SparseTriangularView::InnerIterator : public MatrixType::InnerIterator -{ - typedef typename MatrixType::InnerIterator Base; - public: - - EIGEN_STRONG_INLINE InnerIterator(const SparseTriangularView& view, Index outer) - : Base(view.nestedExpression(), outer) - { - if(SkipFirst) - while((*this) && this->index()index() <= this->outer()); - } -}; - -template -template -inline const SparseTriangularView -SparseMatrixBase::triangularView() const -{ - return derived(); -} - -#endif // EIGEN_SPARSE_TRIANGULARVIEW_H diff --git a/extern/Eigen3/Eigen/src/SparseCholesky/SimplicialCholesky.h b/extern/Eigen3/Eigen/src/SparseCholesky/SimplicialCholesky.h new file mode 100644 index 00000000000..9bf38ab2d91 --- /dev/null +++ b/extern/Eigen3/Eigen/src/SparseCholesky/SimplicialCholesky.h @@ -0,0 +1,873 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2010 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/* + +NOTE: the _symbolic, and _numeric functions has been adapted from + the LDL library: + +LDL Copyright (c) 2005 by Timothy A. Davis. All Rights Reserved. + +LDL License: + + Your use or distribution of LDL or any modified version of + LDL implies that you agree to this License. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA + + Permission is hereby granted to use or copy this program under the + terms of the GNU LGPL, provided that the Copyright, this License, + and the Availability of the original version is retained on all copies. + User documentation of any code that uses this code or any modified + version of this code must cite the Copyright, this License, the + Availability note, and "Used by permission." Permission to modify + the code and to distribute modified code is granted, provided the + Copyright, this License, and the Availability note are retained, + and a notice that the code was modified is included. + */ + +#include "../Core/util/NonMPL2.h" + +#ifndef EIGEN_SIMPLICIAL_CHOLESKY_H +#define EIGEN_SIMPLICIAL_CHOLESKY_H + +namespace Eigen { + +enum SimplicialCholeskyMode { + SimplicialCholeskyLLT, + SimplicialCholeskyLDLT +}; + +/** \ingroup SparseCholesky_Module + * \brief A direct sparse Cholesky factorizations + * + * These classes provide LL^T and LDL^T Cholesky factorizations of sparse matrices that are + * selfadjoint and positive definite. The factorization allows for solving A.X = B where + * X and B can be either dense or sparse. + * + * In order to reduce the fill-in, a symmetric permutation P is applied prior to the factorization + * such that the factorized matrix is P A P^-1. + * + * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower + * or Upper. Default is Lower. + * + */ +template +class SimplicialCholeskyBase : internal::noncopyable +{ + public: + typedef typename internal::traits::MatrixType MatrixType; + enum { UpLo = internal::traits::UpLo }; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef typename MatrixType::Index Index; + typedef SparseMatrix CholMatrixType; + typedef Matrix VectorType; + + public: + + /** Default constructor */ + SimplicialCholeskyBase() + : m_info(Success), m_isInitialized(false), m_shiftOffset(0), m_shiftScale(1) + {} + + SimplicialCholeskyBase(const MatrixType& matrix) + : m_info(Success), m_isInitialized(false), m_shiftOffset(0), m_shiftScale(1) + { + derived().compute(matrix); + } + + ~SimplicialCholeskyBase() + { + } + + Derived& derived() { return *static_cast(this); } + const Derived& derived() const { return *static_cast(this); } + + inline Index cols() const { return m_matrix.cols(); } + inline Index rows() const { return m_matrix.rows(); } + + /** \brief Reports whether previous computation was successful. + * + * \returns \c Success if computation was succesful, + * \c NumericalIssue if the matrix.appears to be negative. + */ + ComputationInfo info() const + { + eigen_assert(m_isInitialized && "Decomposition is not initialized."); + return m_info; + } + + /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. + * + * \sa compute() + */ + template + inline const internal::solve_retval + solve(const MatrixBase& b) const + { + eigen_assert(m_isInitialized && "Simplicial LLT or LDLT is not initialized."); + eigen_assert(rows()==b.rows() + && "SimplicialCholeskyBase::solve(): invalid number of rows of the right hand side matrix b"); + return internal::solve_retval(*this, b.derived()); + } + + /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. + * + * \sa compute() + */ + template + inline const internal::sparse_solve_retval + solve(const SparseMatrixBase& b) const + { + eigen_assert(m_isInitialized && "Simplicial LLT or LDLT is not initialized."); + eigen_assert(rows()==b.rows() + && "SimplicialCholesky::solve(): invalid number of rows of the right hand side matrix b"); + return internal::sparse_solve_retval(*this, b.derived()); + } + + /** \returns the permutation P + * \sa permutationPinv() */ + const PermutationMatrix& permutationP() const + { return m_P; } + + /** \returns the inverse P^-1 of the permutation P + * \sa permutationP() */ + const PermutationMatrix& permutationPinv() const + { return m_Pinv; } + + /** Sets the shift parameters that will be used to adjust the diagonal coefficients during the numerical factorization. + * + * During the numerical factorization, the diagonal coefficients are transformed by the following linear model:\n + * \c d_ii = \a offset + \a scale * \c d_ii + * + * The default is the identity transformation with \a offset=0, and \a scale=1. + * + * \returns a reference to \c *this. + */ + Derived& setShift(const RealScalar& offset, const RealScalar& scale = 1) + { + m_shiftOffset = offset; + m_shiftScale = scale; + return derived(); + } + +#ifndef EIGEN_PARSED_BY_DOXYGEN + /** \internal */ + template + void dumpMemory(Stream& s) + { + int total = 0; + s << " L: " << ((total+=(m_matrix.cols()+1) * sizeof(int) + m_matrix.nonZeros()*(sizeof(int)+sizeof(Scalar))) >> 20) << "Mb" << "\n"; + s << " diag: " << ((total+=m_diag.size() * sizeof(Scalar)) >> 20) << "Mb" << "\n"; + s << " tree: " << ((total+=m_parent.size() * sizeof(int)) >> 20) << "Mb" << "\n"; + s << " nonzeros: " << ((total+=m_nonZerosPerCol.size() * sizeof(int)) >> 20) << "Mb" << "\n"; + s << " perm: " << ((total+=m_P.size() * sizeof(int)) >> 20) << "Mb" << "\n"; + s << " perm^-1: " << ((total+=m_Pinv.size() * sizeof(int)) >> 20) << "Mb" << "\n"; + s << " TOTAL: " << (total>> 20) << "Mb" << "\n"; + } + + /** \internal */ + template + void _solve(const MatrixBase &b, MatrixBase &dest) const + { + eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()"); + eigen_assert(m_matrix.rows()==b.rows()); + + if(m_info!=Success) + return; + + if(m_P.size()>0) + dest = m_P * b; + else + dest = b; + + if(m_matrix.nonZeros()>0) // otherwise L==I + derived().matrixL().solveInPlace(dest); + + if(m_diag.size()>0) + dest = m_diag.asDiagonal().inverse() * dest; + + if (m_matrix.nonZeros()>0) // otherwise U==I + derived().matrixU().solveInPlace(dest); + + if(m_P.size()>0) + dest = m_Pinv * dest; + } + + /** \internal */ + template + void _solve_sparse(const Rhs& b, SparseMatrix &dest) const + { + eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()"); + eigen_assert(m_matrix.rows()==b.rows()); + + // we process the sparse rhs per block of NbColsAtOnce columns temporarily stored into a dense matrix. + static const int NbColsAtOnce = 4; + int rhsCols = b.cols(); + int size = b.rows(); + Eigen::Matrix tmp(size,rhsCols); + for(int k=0; k(rhsCols-k, NbColsAtOnce); + tmp.leftCols(actualCols) = b.middleCols(k,actualCols); + tmp.leftCols(actualCols) = derived().solve(tmp.leftCols(actualCols)); + dest.middleCols(k,actualCols) = tmp.leftCols(actualCols).sparseView(); + } + } + +#endif // EIGEN_PARSED_BY_DOXYGEN + + protected: + + /** Computes the sparse Cholesky decomposition of \a matrix */ + template + void compute(const MatrixType& matrix) + { + eigen_assert(matrix.rows()==matrix.cols()); + Index size = matrix.cols(); + CholMatrixType ap(size,size); + ordering(matrix, ap); + analyzePattern_preordered(ap, DoLDLT); + factorize_preordered(ap); + } + + template + void factorize(const MatrixType& a) + { + eigen_assert(a.rows()==a.cols()); + int size = a.cols(); + CholMatrixType ap(size,size); + ap.template selfadjointView() = a.template selfadjointView().twistedBy(m_P); + factorize_preordered(ap); + } + + template + void factorize_preordered(const CholMatrixType& a); + + void analyzePattern(const MatrixType& a, bool doLDLT) + { + eigen_assert(a.rows()==a.cols()); + int size = a.cols(); + CholMatrixType ap(size,size); + ordering(a, ap); + analyzePattern_preordered(ap,doLDLT); + } + void analyzePattern_preordered(const CholMatrixType& a, bool doLDLT); + + void ordering(const MatrixType& a, CholMatrixType& ap); + + /** keeps off-diagonal entries; drops diagonal entries */ + struct keep_diag { + inline bool operator() (const Index& row, const Index& col, const Scalar&) const + { + return row!=col; + } + }; + + mutable ComputationInfo m_info; + bool m_isInitialized; + bool m_factorizationIsOk; + bool m_analysisIsOk; + + CholMatrixType m_matrix; + VectorType m_diag; // the diagonal coefficients (LDLT mode) + VectorXi m_parent; // elimination tree + VectorXi m_nonZerosPerCol; + PermutationMatrix m_P; // the permutation + PermutationMatrix m_Pinv; // the inverse permutation + + RealScalar m_shiftOffset; + RealScalar m_shiftScale; +}; + +template class SimplicialLLT; +template class SimplicialLDLT; +template class SimplicialCholesky; + +namespace internal { + +template struct traits > +{ + typedef _MatrixType MatrixType; + enum { UpLo = _UpLo }; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::Index Index; + typedef SparseMatrix CholMatrixType; + typedef SparseTriangularView MatrixL; + typedef SparseTriangularView MatrixU; + static inline MatrixL getL(const MatrixType& m) { return m; } + static inline MatrixU getU(const MatrixType& m) { return m.adjoint(); } +}; + +template struct traits > +{ + typedef _MatrixType MatrixType; + enum { UpLo = _UpLo }; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::Index Index; + typedef SparseMatrix CholMatrixType; + typedef SparseTriangularView MatrixL; + typedef SparseTriangularView MatrixU; + static inline MatrixL getL(const MatrixType& m) { return m; } + static inline MatrixU getU(const MatrixType& m) { return m.adjoint(); } +}; + +template struct traits > +{ + typedef _MatrixType MatrixType; + enum { UpLo = _UpLo }; +}; + +} + +/** \ingroup SparseCholesky_Module + * \class SimplicialLLT + * \brief A direct sparse LLT Cholesky factorizations + * + * This class provides a LL^T Cholesky factorizations of sparse matrices that are + * selfadjoint and positive definite. The factorization allows for solving A.X = B where + * X and B can be either dense or sparse. + * + * In order to reduce the fill-in, a symmetric permutation P is applied prior to the factorization + * such that the factorized matrix is P A P^-1. + * + * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower + * or Upper. Default is Lower. + * + * \sa class SimplicialLDLT + */ +template + class SimplicialLLT : public SimplicialCholeskyBase > +{ +public: + typedef _MatrixType MatrixType; + enum { UpLo = _UpLo }; + typedef SimplicialCholeskyBase Base; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef typename MatrixType::Index Index; + typedef SparseMatrix CholMatrixType; + typedef Matrix VectorType; + typedef internal::traits Traits; + typedef typename Traits::MatrixL MatrixL; + typedef typename Traits::MatrixU MatrixU; +public: + /** Default constructor */ + SimplicialLLT() : Base() {} + /** Constructs and performs the LLT factorization of \a matrix */ + SimplicialLLT(const MatrixType& matrix) + : Base(matrix) {} + + /** \returns an expression of the factor L */ + inline const MatrixL matrixL() const { + eigen_assert(Base::m_factorizationIsOk && "Simplicial LLT not factorized"); + return Traits::getL(Base::m_matrix); + } + + /** \returns an expression of the factor U (= L^*) */ + inline const MatrixU matrixU() const { + eigen_assert(Base::m_factorizationIsOk && "Simplicial LLT not factorized"); + return Traits::getU(Base::m_matrix); + } + + /** Computes the sparse Cholesky decomposition of \a matrix */ + SimplicialLLT& compute(const MatrixType& matrix) + { + Base::template compute(matrix); + return *this; + } + + /** Performs a symbolic decomposition on the sparcity of \a matrix. + * + * This function is particularly useful when solving for several problems having the same structure. + * + * \sa factorize() + */ + void analyzePattern(const MatrixType& a) + { + Base::analyzePattern(a, false); + } + + /** Performs a numeric decomposition of \a matrix + * + * The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed. + * + * \sa analyzePattern() + */ + void factorize(const MatrixType& a) + { + Base::template factorize(a); + } + + /** \returns the determinant of the underlying matrix from the current factorization */ + Scalar determinant() const + { + Scalar detL = Base::m_matrix.diagonal().prod(); + return internal::abs2(detL); + } +}; + +/** \ingroup SparseCholesky_Module + * \class SimplicialLDLT + * \brief A direct sparse LDLT Cholesky factorizations without square root. + * + * This class provides a LDL^T Cholesky factorizations without square root of sparse matrices that are + * selfadjoint and positive definite. The factorization allows for solving A.X = B where + * X and B can be either dense or sparse. + * + * In order to reduce the fill-in, a symmetric permutation P is applied prior to the factorization + * such that the factorized matrix is P A P^-1. + * + * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> + * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower + * or Upper. Default is Lower. + * + * \sa class SimplicialLLT + */ +template + class SimplicialLDLT : public SimplicialCholeskyBase > +{ +public: + typedef _MatrixType MatrixType; + enum { UpLo = _UpLo }; + typedef SimplicialCholeskyBase Base; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef typename MatrixType::Index Index; + typedef SparseMatrix CholMatrixType; + typedef Matrix VectorType; + typedef internal::traits Traits; + typedef typename Traits::MatrixL MatrixL; + typedef typename Traits::MatrixU MatrixU; +public: + /** Default constructor */ + SimplicialLDLT() : Base() {} + + /** Constructs and performs the LLT factorization of \a matrix */ + SimplicialLDLT(const MatrixType& matrix) + : Base(matrix) {} + + /** \returns a vector expression of the diagonal D */ + inline const VectorType vectorD() const { + eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized"); + return Base::m_diag; + } + /** \returns an expression of the factor L */ + inline const MatrixL matrixL() const { + eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized"); + return Traits::getL(Base::m_matrix); + } + + /** \returns an expression of the factor U (= L^*) */ + inline const MatrixU matrixU() const { + eigen_assert(Base::m_factorizationIsOk && "Simplicial LDLT not factorized"); + return Traits::getU(Base::m_matrix); + } + + /** Computes the sparse Cholesky decomposition of \a matrix */ + SimplicialLDLT& compute(const MatrixType& matrix) + { + Base::template compute(matrix); + return *this; + } + + /** Performs a symbolic decomposition on the sparcity of \a matrix. + * + * This function is particularly useful when solving for several problems having the same structure. + * + * \sa factorize() + */ + void analyzePattern(const MatrixType& a) + { + Base::analyzePattern(a, true); + } + + /** Performs a numeric decomposition of \a matrix + * + * The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed. + * + * \sa analyzePattern() + */ + void factorize(const MatrixType& a) + { + Base::template factorize(a); + } + + /** \returns the determinant of the underlying matrix from the current factorization */ + Scalar determinant() const + { + return Base::m_diag.prod(); + } +}; + +/** \deprecated use SimplicialLDLT or class SimplicialLLT + * \ingroup SparseCholesky_Module + * \class SimplicialCholesky + * + * \sa class SimplicialLDLT, class SimplicialLLT + */ +template + class SimplicialCholesky : public SimplicialCholeskyBase > +{ +public: + typedef _MatrixType MatrixType; + enum { UpLo = _UpLo }; + typedef SimplicialCholeskyBase Base; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef typename MatrixType::Index Index; + typedef SparseMatrix CholMatrixType; + typedef Matrix VectorType; + typedef internal::traits Traits; + typedef internal::traits > LDLTTraits; + typedef internal::traits > LLTTraits; + public: + SimplicialCholesky() : Base(), m_LDLT(true) {} + + SimplicialCholesky(const MatrixType& matrix) + : Base(), m_LDLT(true) + { + compute(matrix); + } + + SimplicialCholesky& setMode(SimplicialCholeskyMode mode) + { + switch(mode) + { + case SimplicialCholeskyLLT: + m_LDLT = false; + break; + case SimplicialCholeskyLDLT: + m_LDLT = true; + break; + default: + break; + } + + return *this; + } + + inline const VectorType vectorD() const { + eigen_assert(Base::m_factorizationIsOk && "Simplicial Cholesky not factorized"); + return Base::m_diag; + } + inline const CholMatrixType rawMatrix() const { + eigen_assert(Base::m_factorizationIsOk && "Simplicial Cholesky not factorized"); + return Base::m_matrix; + } + + /** Computes the sparse Cholesky decomposition of \a matrix */ + SimplicialCholesky& compute(const MatrixType& matrix) + { + if(m_LDLT) + Base::template compute(matrix); + else + Base::template compute(matrix); + return *this; + } + + /** Performs a symbolic decomposition on the sparcity of \a matrix. + * + * This function is particularly useful when solving for several problems having the same structure. + * + * \sa factorize() + */ + void analyzePattern(const MatrixType& a) + { + Base::analyzePattern(a, m_LDLT); + } + + /** Performs a numeric decomposition of \a matrix + * + * The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed. + * + * \sa analyzePattern() + */ + void factorize(const MatrixType& a) + { + if(m_LDLT) + Base::template factorize(a); + else + Base::template factorize(a); + } + + /** \internal */ + template + void _solve(const MatrixBase &b, MatrixBase &dest) const + { + eigen_assert(Base::m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or symbolic()/numeric()"); + eigen_assert(Base::m_matrix.rows()==b.rows()); + + if(Base::m_info!=Success) + return; + + if(Base::m_P.size()>0) + dest = Base::m_P * b; + else + dest = b; + + if(Base::m_matrix.nonZeros()>0) // otherwise L==I + { + if(m_LDLT) + LDLTTraits::getL(Base::m_matrix).solveInPlace(dest); + else + LLTTraits::getL(Base::m_matrix).solveInPlace(dest); + } + + if(Base::m_diag.size()>0) + dest = Base::m_diag.asDiagonal().inverse() * dest; + + if (Base::m_matrix.nonZeros()>0) // otherwise I==I + { + if(m_LDLT) + LDLTTraits::getU(Base::m_matrix).solveInPlace(dest); + else + LLTTraits::getU(Base::m_matrix).solveInPlace(dest); + } + + if(Base::m_P.size()>0) + dest = Base::m_Pinv * dest; + } + + Scalar determinant() const + { + if(m_LDLT) + { + return Base::m_diag.prod(); + } + else + { + Scalar detL = Diagonal(Base::m_matrix).prod(); + return internal::abs2(detL); + } + } + + protected: + bool m_LDLT; +}; + +template +void SimplicialCholeskyBase::ordering(const MatrixType& a, CholMatrixType& ap) +{ + eigen_assert(a.rows()==a.cols()); + const Index size = a.rows(); + // TODO allows to configure the permutation + // Note that amd compute the inverse permutation + { + CholMatrixType C; + C = a.template selfadjointView(); + // remove diagonal entries: + // seems not to be needed + // C.prune(keep_diag()); + internal::minimum_degree_ordering(C, m_Pinv); + } + + if(m_Pinv.size()>0) + m_P = m_Pinv.inverse(); + else + m_P.resize(0); + + ap.resize(size,size); + ap.template selfadjointView() = a.template selfadjointView().twistedBy(m_P); +} + +template +void SimplicialCholeskyBase::analyzePattern_preordered(const CholMatrixType& ap, bool doLDLT) +{ + const Index size = ap.rows(); + m_matrix.resize(size, size); + m_parent.resize(size); + m_nonZerosPerCol.resize(size); + + ei_declare_aligned_stack_constructed_variable(Index, tags, size, 0); + + for(Index k = 0; k < size; ++k) + { + /* L(k,:) pattern: all nodes reachable in etree from nz in A(0:k-1,k) */ + m_parent[k] = -1; /* parent of k is not yet known */ + tags[k] = k; /* mark node k as visited */ + m_nonZerosPerCol[k] = 0; /* count of nonzeros in column k of L */ + for(typename CholMatrixType::InnerIterator it(ap,k); it; ++it) + { + Index i = it.index(); + if(i < k) + { + /* follow path from i to root of etree, stop at flagged node */ + for(; tags[i] != k; i = m_parent[i]) + { + /* find parent of i if not yet determined */ + if (m_parent[i] == -1) + m_parent[i] = k; + m_nonZerosPerCol[i]++; /* L (k,i) is nonzero */ + tags[i] = k; /* mark i as visited */ + } + } + } + } + + /* construct Lp index array from m_nonZerosPerCol column counts */ + Index* Lp = m_matrix.outerIndexPtr(); + Lp[0] = 0; + for(Index k = 0; k < size; ++k) + Lp[k+1] = Lp[k] + m_nonZerosPerCol[k] + (doLDLT ? 0 : 1); + + m_matrix.resizeNonZeros(Lp[size]); + + m_isInitialized = true; + m_info = Success; + m_analysisIsOk = true; + m_factorizationIsOk = false; +} + + +template +template +void SimplicialCholeskyBase::factorize_preordered(const CholMatrixType& ap) +{ + eigen_assert(m_analysisIsOk && "You must first call analyzePattern()"); + eigen_assert(ap.rows()==ap.cols()); + const Index size = ap.rows(); + eigen_assert(m_parent.size()==size); + eigen_assert(m_nonZerosPerCol.size()==size); + + const Index* Lp = m_matrix.outerIndexPtr(); + Index* Li = m_matrix.innerIndexPtr(); + Scalar* Lx = m_matrix.valuePtr(); + + ei_declare_aligned_stack_constructed_variable(Scalar, y, size, 0); + ei_declare_aligned_stack_constructed_variable(Index, pattern, size, 0); + ei_declare_aligned_stack_constructed_variable(Index, tags, size, 0); + + bool ok = true; + m_diag.resize(DoLDLT ? size : 0); + + for(Index k = 0; k < size; ++k) + { + // compute nonzero pattern of kth row of L, in topological order + y[k] = 0.0; // Y(0:k) is now all zero + Index top = size; // stack for pattern is empty + tags[k] = k; // mark node k as visited + m_nonZerosPerCol[k] = 0; // count of nonzeros in column k of L + for(typename MatrixType::InnerIterator it(ap,k); it; ++it) + { + Index i = it.index(); + if(i <= k) + { + y[i] += internal::conj(it.value()); /* scatter A(i,k) into Y (sum duplicates) */ + Index len; + for(len = 0; tags[i] != k; i = m_parent[i]) + { + pattern[len++] = i; /* L(k,i) is nonzero */ + tags[i] = k; /* mark i as visited */ + } + while(len > 0) + pattern[--top] = pattern[--len]; + } + } + + /* compute numerical values kth row of L (a sparse triangular solve) */ + + RealScalar d = internal::real(y[k]) * m_shiftScale + m_shiftOffset; // get D(k,k), apply the shift function, and clear Y(k) + y[k] = 0.0; + for(; top < size; ++top) + { + Index i = pattern[top]; /* pattern[top:n-1] is pattern of L(:,k) */ + Scalar yi = y[i]; /* get and clear Y(i) */ + y[i] = 0.0; + + /* the nonzero entry L(k,i) */ + Scalar l_ki; + if(DoLDLT) + l_ki = yi / m_diag[i]; + else + yi = l_ki = yi / Lx[Lp[i]]; + + Index p2 = Lp[i] + m_nonZerosPerCol[i]; + Index p; + for(p = Lp[i] + (DoLDLT ? 0 : 1); p < p2; ++p) + y[Li[p]] -= internal::conj(Lx[p]) * yi; + d -= internal::real(l_ki * internal::conj(yi)); + Li[p] = k; /* store L(k,i) in column form of L */ + Lx[p] = l_ki; + ++m_nonZerosPerCol[i]; /* increment count of nonzeros in col i */ + } + if(DoLDLT) + { + m_diag[k] = d; + if(d == RealScalar(0)) + { + ok = false; /* failure, D(k,k) is zero */ + break; + } + } + else + { + Index p = Lp[k] + m_nonZerosPerCol[k]++; + Li[p] = k ; /* store L(k,k) = sqrt (d) in column k */ + if(d <= RealScalar(0)) { + ok = false; /* failure, matrix is not positive definite */ + break; + } + Lx[p] = internal::sqrt(d) ; + } + } + + m_info = ok ? Success : NumericalIssue; + m_factorizationIsOk = true; +} + +namespace internal { + +template +struct solve_retval, Rhs> + : solve_retval_base, Rhs> +{ + typedef SimplicialCholeskyBase Dec; + EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs) + + template void evalTo(Dest& dst) const + { + dec().derived()._solve(rhs(),dst); + } +}; + +template +struct sparse_solve_retval, Rhs> + : sparse_solve_retval_base, Rhs> +{ + typedef SimplicialCholeskyBase Dec; + EIGEN_MAKE_SPARSE_SOLVE_HELPERS(Dec,Rhs) + + template void evalTo(Dest& dst) const + { + dec().derived()._solve_sparse(rhs(),dst); + } +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_SIMPLICIAL_CHOLESKY_H diff --git a/extern/Eigen3/Eigen/src/Sparse/AmbiVector.h b/extern/Eigen3/Eigen/src/SparseCore/AmbiVector.h similarity index 89% rename from extern/Eigen3/Eigen/src/Sparse/AmbiVector.h rename to extern/Eigen3/Eigen/src/SparseCore/AmbiVector.h index 2ea8ba3096b..6cfaadbaa9a 100644 --- a/extern/Eigen3/Eigen/src/Sparse/AmbiVector.h +++ b/extern/Eigen3/Eigen/src/SparseCore/AmbiVector.h @@ -3,28 +3,17 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_AMBIVECTOR_H #define EIGEN_AMBIVECTOR_H +namespace Eigen { + +namespace internal { + /** \internal * Hybrid sparse/dense vector class designed for intensive read-write operations. * @@ -299,7 +288,7 @@ class AmbiVector<_Scalar,_Index>::Iterator * In practice, all coefficients having a magnitude smaller than \a epsilon * are skipped. */ - Iterator(const AmbiVector& vec, RealScalar epsilon = RealScalar(0.1)*NumTraits::dummy_precision()) + Iterator(const AmbiVector& vec, RealScalar epsilon = 0) : m_vector(vec) { m_epsilon = epsilon; @@ -315,7 +304,7 @@ class AmbiVector<_Scalar,_Index>::Iterator { ListEl* EIGEN_RESTRICT llElements = reinterpret_cast(m_vector.m_buffer); m_currentEl = m_vector.m_llStart; - while (m_currentEl>=0 && internal::abs(llElements[m_currentEl].value)=0 && internal::abs(llElements[m_currentEl].value)<=m_epsilon) m_currentEl = llElements[m_currentEl].next; if (m_currentEl<0) { @@ -375,5 +364,8 @@ class AmbiVector<_Scalar,_Index>::Iterator bool m_isDense; // mode of the vector }; +} // end namespace internal + +} // end namespace Eigen #endif // EIGEN_AMBIVECTOR_H diff --git a/extern/Eigen3/Eigen/src/Sparse/CompressedStorage.h b/extern/Eigen3/Eigen/src/SparseCore/CompressedStorage.h similarity index 84% rename from extern/Eigen3/Eigen/src/Sparse/CompressedStorage.h rename to extern/Eigen3/Eigen/src/SparseCore/CompressedStorage.h index b3bde272ec2..85a998aff10 100644 --- a/extern/Eigen3/Eigen/src/Sparse/CompressedStorage.h +++ b/extern/Eigen3/Eigen/src/SparseCore/CompressedStorage.h @@ -3,29 +3,19 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_COMPRESSED_STORAGE_H #define EIGEN_COMPRESSED_STORAGE_H -/** Stores a sparse set of values as a list of values and a list of indices. +namespace Eigen { + +namespace internal { + +/** \internal + * Stores a sparse set of values as a list of values and a list of indices. * */ template @@ -218,8 +208,8 @@ class CompressedStorage Index* newIndices = new Index[size]; size_t copySize = (std::min)(size, m_size); // copy - memcpy(newValues, m_values, copySize * sizeof(Scalar)); - memcpy(newIndices, m_indices, copySize * sizeof(Index)); + internal::smart_copy(m_values, m_values+copySize, newValues); + internal::smart_copy(m_indices, m_indices+copySize, newIndices); // delete old stuff delete[] m_values; delete[] m_indices; @@ -236,4 +226,8 @@ class CompressedStorage }; +} // end namespace internal + +} // end namespace Eigen + #endif // EIGEN_COMPRESSED_STORAGE_H diff --git a/extern/Eigen3/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h b/extern/Eigen3/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h new file mode 100644 index 00000000000..16b5e1dba6c --- /dev/null +++ b/extern/Eigen3/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h @@ -0,0 +1,245 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2011 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_CONSERVATIVESPARSESPARSEPRODUCT_H +#define EIGEN_CONSERVATIVESPARSESPARSEPRODUCT_H + +namespace Eigen { + +namespace internal { + +template +static void conservative_sparse_sparse_product_impl(const Lhs& lhs, const Rhs& rhs, ResultType& res) +{ + typedef typename remove_all::type::Scalar Scalar; + typedef typename remove_all::type::Index Index; + + // make sure to call innerSize/outerSize since we fake the storage order. + Index rows = lhs.innerSize(); + Index cols = rhs.outerSize(); + eigen_assert(lhs.outerSize() == rhs.innerSize()); + + std::vector mask(rows,false); + Matrix values(rows); + Matrix indices(rows); + + // estimate the number of non zero entries + // given a rhs column containing Y non zeros, we assume that the respective Y columns + // of the lhs differs in average of one non zeros, thus the number of non zeros for + // the product of a rhs column with the lhs is X+Y where X is the average number of non zero + // per column of the lhs. + // Therefore, we have nnz(lhs*rhs) = nnz(lhs) + nnz(rhs) + Index estimated_nnz_prod = lhs.nonZeros() + rhs.nonZeros(); + + res.setZero(); + res.reserve(Index(estimated_nnz_prod)); + // we compute each column of the result, one after the other + for (Index j=0; j use a quick sort + // otherwise => loop through the entire vector + // In order to avoid to perform an expensive log2 when the + // result is clearly very sparse we use a linear bound up to 200. + //if((nnz<200 && nnz1) std::sort(indices.data(),indices.data()+nnz); + for(int k=0; k::Flags&RowMajorBit, + int RhsStorageOrder = traits::Flags&RowMajorBit, + int ResStorageOrder = traits::Flags&RowMajorBit> +struct conservative_sparse_sparse_product_selector; + +template +struct conservative_sparse_sparse_product_selector +{ + typedef typename remove_all::type LhsCleaned; + typedef typename LhsCleaned::Scalar Scalar; + + static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) + { + typedef SparseMatrix RowMajorMatrix; + typedef SparseMatrix ColMajorMatrix; + ColMajorMatrix resCol(lhs.rows(),rhs.cols()); + internal::conservative_sparse_sparse_product_impl(lhs, rhs, resCol); + // sort the non zeros: + RowMajorMatrix resRow(resCol); + res = resRow; + } +}; + +template +struct conservative_sparse_sparse_product_selector +{ + static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) + { + typedef SparseMatrix RowMajorMatrix; + RowMajorMatrix rhsRow = rhs; + RowMajorMatrix resRow(lhs.rows(), rhs.cols()); + internal::conservative_sparse_sparse_product_impl(rhsRow, lhs, resRow); + res = resRow; + } +}; + +template +struct conservative_sparse_sparse_product_selector +{ + static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) + { + typedef SparseMatrix RowMajorMatrix; + RowMajorMatrix lhsRow = lhs; + RowMajorMatrix resRow(lhs.rows(), rhs.cols()); + internal::conservative_sparse_sparse_product_impl(rhs, lhsRow, resRow); + res = resRow; + } +}; + +template +struct conservative_sparse_sparse_product_selector +{ + static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) + { + typedef SparseMatrix RowMajorMatrix; + RowMajorMatrix resRow(lhs.rows(), rhs.cols()); + internal::conservative_sparse_sparse_product_impl(rhs, lhs, resRow); + res = resRow; + } +}; + + +template +struct conservative_sparse_sparse_product_selector +{ + typedef typename traits::type>::Scalar Scalar; + + static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) + { + typedef SparseMatrix ColMajorMatrix; + ColMajorMatrix resCol(lhs.rows(), rhs.cols()); + internal::conservative_sparse_sparse_product_impl(lhs, rhs, resCol); + res = resCol; + } +}; + +template +struct conservative_sparse_sparse_product_selector +{ + static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) + { + typedef SparseMatrix ColMajorMatrix; + ColMajorMatrix lhsCol = lhs; + ColMajorMatrix resCol(lhs.rows(), rhs.cols()); + internal::conservative_sparse_sparse_product_impl(lhsCol, rhs, resCol); + res = resCol; + } +}; + +template +struct conservative_sparse_sparse_product_selector +{ + static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) + { + typedef SparseMatrix ColMajorMatrix; + ColMajorMatrix rhsCol = rhs; + ColMajorMatrix resCol(lhs.rows(), rhs.cols()); + internal::conservative_sparse_sparse_product_impl(lhs, rhsCol, resCol); + res = resCol; + } +}; + +template +struct conservative_sparse_sparse_product_selector +{ + static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) + { + typedef SparseMatrix RowMajorMatrix; + typedef SparseMatrix ColMajorMatrix; + RowMajorMatrix resRow(lhs.rows(),rhs.cols()); + internal::conservative_sparse_sparse_product_impl(rhs, lhs, resRow); + // sort the non zeros: + ColMajorMatrix resCol(resRow); + res = resCol; + } +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_CONSERVATIVESPARSESPARSEPRODUCT_H diff --git a/extern/Eigen3/Eigen/src/Sparse/CoreIterators.h b/extern/Eigen3/Eigen/src/SparseCore/CoreIterators.h similarity index 62% rename from extern/Eigen3/Eigen/src/Sparse/CoreIterators.h rename to extern/Eigen3/Eigen/src/SparseCore/CoreIterators.h index b4beaeee69e..6da4683d2c2 100644 --- a/extern/Eigen3/Eigen/src/Sparse/CoreIterators.h +++ b/extern/Eigen3/Eigen/src/SparseCore/CoreIterators.h @@ -3,32 +3,20 @@ // // Copyright (C) 2008-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_COREITERATORS_H #define EIGEN_COREITERATORS_H +namespace Eigen { + /* This file contains the respective InnerIterator definition of the expressions defined in Eigen/Core */ -/** \class InnerIterator +/** \ingroup SparseCore_Module + * \class InnerIterator * \brief An InnerIterator allows to loop over the element of a sparse (or dense) matrix or expression * * todo @@ -68,4 +56,6 @@ template class DenseBase::InnerIterator const Index m_end; }; +} // end namespace Eigen + #endif // EIGEN_COREITERATORS_H diff --git a/extern/Eigen3/Eigen/src/Sparse/MappedSparseMatrix.h b/extern/Eigen3/Eigen/src/SparseCore/MappedSparseMatrix.h similarity index 68% rename from extern/Eigen3/Eigen/src/Sparse/MappedSparseMatrix.h rename to extern/Eigen3/Eigen/src/SparseCore/MappedSparseMatrix.h index 31a431fb224..93cd4832dea 100644 --- a/extern/Eigen3/Eigen/src/Sparse/MappedSparseMatrix.h +++ b/extern/Eigen3/Eigen/src/SparseCore/MappedSparseMatrix.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_MAPPED_SPARSEMATRIX_H #define EIGEN_MAPPED_SPARSEMATRIX_H +namespace Eigen { + /** \class MappedSparseMatrix * * \brief Sparse matrix @@ -46,9 +33,9 @@ class MappedSparseMatrix { public: EIGEN_SPARSE_PUBLIC_INTERFACE(MappedSparseMatrix) + enum { IsRowMajor = Base::IsRowMajor }; protected: - enum { IsRowMajor = Base::IsRowMajor }; Index m_outerSize; Index m_innerSize; @@ -63,18 +50,17 @@ class MappedSparseMatrix inline Index cols() const { return IsRowMajor ? m_innerSize : m_outerSize; } inline Index innerSize() const { return m_innerSize; } inline Index outerSize() const { return m_outerSize; } - inline Index innerNonZeros(Index j) const { return m_outerIndex[j+1]-m_outerIndex[j]; } //---------------------------------------- // direct access interface - inline const Scalar* _valuePtr() const { return m_values; } - inline Scalar* _valuePtr() { return m_values; } + inline const Scalar* valuePtr() const { return m_values; } + inline Scalar* valuePtr() { return m_values; } - inline const Index* _innerIndexPtr() const { return m_innerIndices; } - inline Index* _innerIndexPtr() { return m_innerIndices; } + inline const Index* innerIndexPtr() const { return m_innerIndices; } + inline Index* innerIndexPtr() { return m_innerIndices; } - inline const Index* _outerIndexPtr() const { return m_outerIndex; } - inline Index* _outerIndexPtr() { return m_outerIndex; } + inline const Index* outerIndexPtr() const { return m_outerIndex; } + inline Index* outerIndexPtr() { return m_outerIndex; } //---------------------------------------- inline Scalar coeff(Index row, Index col) const @@ -112,6 +98,7 @@ class MappedSparseMatrix } class InnerIterator; + class ReverseInnerIterator; /** \returns the number of non zero coefficients */ inline Index nonZeros() const { return m_nnz; } @@ -132,23 +119,17 @@ class MappedSparseMatrix::InnerIterator InnerIterator(const MappedSparseMatrix& mat, Index outer) : m_matrix(mat), m_outer(outer), - m_id(mat._outerIndexPtr()[outer]), + m_id(mat.outerIndexPtr()[outer]), m_start(m_id), - m_end(mat._outerIndexPtr()[outer+1]) - {} - - template - InnerIterator(const Flagged& mat, Index outer) - : m_matrix(mat._expression()), m_id(m_matrix._outerIndexPtr()[outer]), - m_start(m_id), m_end(m_matrix._outerIndexPtr()[outer+1]) + m_end(mat.outerIndexPtr()[outer+1]) {} inline InnerIterator& operator++() { m_id++; return *this; } - inline Scalar value() const { return m_matrix._valuePtr()[m_id]; } - inline Scalar& valueRef() { return const_cast(m_matrix._valuePtr()[m_id]); } + inline Scalar value() const { return m_matrix.valuePtr()[m_id]; } + inline Scalar& valueRef() { return const_cast(m_matrix.valuePtr()[m_id]); } - inline Index index() const { return m_matrix._innerIndexPtr()[m_id]; } + inline Index index() const { return m_matrix.innerIndexPtr()[m_id]; } inline Index row() const { return IsRowMajor ? m_outer : index(); } inline Index col() const { return IsRowMajor ? index() : m_outer; } @@ -162,4 +143,37 @@ class MappedSparseMatrix::InnerIterator const Index m_end; }; +template +class MappedSparseMatrix::ReverseInnerIterator +{ + public: + ReverseInnerIterator(const MappedSparseMatrix& mat, Index outer) + : m_matrix(mat), + m_outer(outer), + m_id(mat.outerIndexPtr()[outer+1]), + m_start(mat.outerIndexPtr()[outer]), + m_end(m_id) + {} + + inline ReverseInnerIterator& operator--() { m_id--; return *this; } + + inline Scalar value() const { return m_matrix.valuePtr()[m_id-1]; } + inline Scalar& valueRef() { return const_cast(m_matrix.valuePtr()[m_id-1]); } + + inline Index index() const { return m_matrix.innerIndexPtr()[m_id-1]; } + inline Index row() const { return IsRowMajor ? m_outer : index(); } + inline Index col() const { return IsRowMajor ? index() : m_outer; } + + inline operator bool() const { return (m_id <= m_end) && (m_id>m_start); } + + protected: + const MappedSparseMatrix& m_matrix; + const Index m_outer; + Index m_id; + const Index m_start; + const Index m_end; +}; + +} // end namespace Eigen + #endif // EIGEN_MAPPED_SPARSEMATRIX_H diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseAssign.h b/extern/Eigen3/Eigen/src/SparseCore/SparseAssign.h similarity index 100% rename from extern/Eigen3/Eigen/src/Sparse/SparseAssign.h rename to extern/Eigen3/Eigen/src/SparseCore/SparseAssign.h diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseBlock.h b/extern/Eigen3/Eigen/src/SparseCore/SparseBlock.h similarity index 66% rename from extern/Eigen3/Eigen/src/Sparse/SparseBlock.h rename to extern/Eigen3/Eigen/src/SparseCore/SparseBlock.h index 8079c999994..eefd8070251 100644 --- a/extern/Eigen3/Eigen/src/Sparse/SparseBlock.h +++ b/extern/Eigen3/Eigen/src/SparseCore/SparseBlock.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008-2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SPARSE_BLOCK_H #define EIGEN_SPARSE_BLOCK_H +namespace Eigen { + namespace internal { template struct traits > @@ -65,6 +52,17 @@ class SparseInnerVectorSet : internal::no_assignment_operator, protected: Index m_outer; }; + class ReverseInnerIterator: public MatrixType::ReverseInnerIterator + { + public: + inline ReverseInnerIterator(const SparseInnerVectorSet& xpr, Index outer) + : MatrixType::ReverseInnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer) + {} + inline Index row() const { return IsRowMajor ? m_outer : this->index(); } + inline Index col() const { return IsRowMajor ? this->index() : m_outer; } + protected: + Index m_outer; + }; inline SparseInnerVectorSet(const MatrixType& matrix, Index outerStart, Index outerSize) : m_matrix(matrix), m_outerStart(outerStart), m_outerSize(outerSize) @@ -101,15 +99,16 @@ class SparseInnerVectorSet : internal::no_assignment_operator, const internal::variable_if_dynamic m_outerSize; }; + /*************************************************************************** -* specialisation for DynamicSparseMatrix +* specialisation for SparseMatrix ***************************************************************************/ -template -class SparseInnerVectorSet, Size> - : public SparseMatrixBase, Size> > +template +class SparseInnerVectorSet, Size> + : public SparseMatrixBase, Size> > { - typedef DynamicSparseMatrix<_Scalar, _Options> MatrixType; + typedef SparseMatrix<_Scalar, _Options, _Index> MatrixType; public: enum { IsRowMajor = internal::traits::IsRowMajor }; @@ -126,98 +125,11 @@ class SparseInnerVectorSet, Size> protected: Index m_outer; }; - - inline SparseInnerVectorSet(const MatrixType& matrix, Index outerStart, Index outerSize) - : m_matrix(matrix), m_outerStart(outerStart), m_outerSize(outerSize) - { - eigen_assert( (outerStart>=0) && ((outerStart+outerSize)<=matrix.outerSize()) ); - } - - inline SparseInnerVectorSet(const MatrixType& matrix, Index outer) - : m_matrix(matrix), m_outerStart(outer), m_outerSize(Size) - { - eigen_assert(Size!=Dynamic); - eigen_assert( (outer>=0) && (outer - inline SparseInnerVectorSet& operator=(const SparseMatrixBase& other) - { - if (IsRowMajor != ((OtherDerived::Flags&RowMajorBit)==RowMajorBit)) - { - // need to transpose => perform a block evaluation followed by a big swap - DynamicSparseMatrix aux(other); - *this = aux.markAsRValue(); - } - else - { - // evaluate/copy vector per vector - for (Index j=0; j aux(other.innerVector(j)); - m_matrix.const_cast_derived()._data()[m_outerStart+j].swap(aux._data()); - } - } - return *this; - } - - inline SparseInnerVectorSet& operator=(const SparseInnerVectorSet& other) - { - return operator=(other); - } - - Index nonZeros() const - { - Index count = 0; - for (Index j=0; j0); - return m_matrix.data()[m_outerStart].vale(m_matrix.data()[m_outerStart].size()-1); - } - -// template -// inline SparseInnerVectorSet& operator=(const SparseMatrixBase& other) -// { -// return *this; -// } - - EIGEN_STRONG_INLINE Index rows() const { return IsRowMajor ? m_outerSize.value() : m_matrix.rows(); } - EIGEN_STRONG_INLINE Index cols() const { return IsRowMajor ? m_matrix.cols() : m_outerSize.value(); } - - protected: - - const typename MatrixType::Nested m_matrix; - Index m_outerStart; - const internal::variable_if_dynamic m_outerSize; - -}; - - -/*************************************************************************** -* specialisation for SparseMatrix -***************************************************************************/ - -template -class SparseInnerVectorSet, Size> - : public SparseMatrixBase, Size> > -{ - typedef SparseMatrix<_Scalar, _Options> MatrixType; - public: - - enum { IsRowMajor = internal::traits::IsRowMajor }; - - EIGEN_SPARSE_PUBLIC_INTERFACE(SparseInnerVectorSet) - class InnerIterator: public MatrixType::InnerIterator + class ReverseInnerIterator: public MatrixType::ReverseInnerIterator { public: - inline InnerIterator(const SparseInnerVectorSet& xpr, Index outer) - : MatrixType::InnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer) + inline ReverseInnerIterator(const SparseInnerVectorSet& xpr, Index outer) + : MatrixType::ReverseInnerIterator(xpr.m_matrix, xpr.m_outerStart + outer), m_outer(outer) {} inline Index row() const { return IsRowMajor ? m_outer : this->index(); } inline Index col() const { return IsRowMajor ? this->index() : m_outer; } @@ -243,19 +155,19 @@ class SparseInnerVectorSet, Size> { typedef typename internal::remove_all::type _NestedMatrixType; _NestedMatrixType& matrix = const_cast<_NestedMatrixType&>(m_matrix);; - // This assignement is slow if this vector set not empty + // This assignement is slow if this vector set is not empty // and/or it is not at the end of the nonzeros of the underlying matrix. // 1 - eval to a temporary to avoid transposition and/or aliasing issues SparseMatrix tmp(other); // 2 - let's check whether there is enough allocated memory - Index nnz = tmp.nonZeros(); - Index nnz_previous = nonZeros(); - Index free_size = matrix.data().allocatedSize() - nnz_previous; - std::size_t nnz_head = m_outerStart==0 ? 0 : matrix._outerIndexPtr()[m_outerStart]; - std::size_t tail = m_matrix._outerIndexPtr()[m_outerStart+m_outerSize.value()]; - std::size_t nnz_tail = matrix.nonZeros() - tail; + Index nnz = tmp.nonZeros(); + Index nnz_previous = nonZeros(); + Index free_size = Index(matrix.data().allocatedSize()) + nnz_previous; + Index nnz_head = m_outerStart==0 ? 0 : matrix.outerIndexPtr()[m_outerStart]; + Index tail = m_matrix.outerIndexPtr()[m_outerStart+m_outerSize.value()]; + Index nnz_tail = matrix.nonZeros() - tail; if(nnz>free_size) { @@ -298,15 +210,15 @@ class SparseInnerVectorSet, Size> // update outer index pointers Index p = nnz_head; - for(Index k=1; k, Size> return operator=(other); } - inline const Scalar* _valuePtr() const - { return m_matrix._valuePtr() + m_matrix._outerIndexPtr()[m_outerStart]; } - inline Scalar* _valuePtr() - { return m_matrix.const_cast_derived()._valuePtr() + m_matrix._outerIndexPtr()[m_outerStart]; } + inline const Scalar* valuePtr() const + { return m_matrix.valuePtr() + m_matrix.outerIndexPtr()[m_outerStart]; } + inline Scalar* valuePtr() + { return m_matrix.const_cast_derived().valuePtr() + m_matrix.outerIndexPtr()[m_outerStart]; } - inline const Index* _innerIndexPtr() const - { return m_matrix._innerIndexPtr() + m_matrix._outerIndexPtr()[m_outerStart]; } - inline Index* _innerIndexPtr() - { return m_matrix.const_cast_derived()._innerIndexPtr() + m_matrix._outerIndexPtr()[m_outerStart]; } + inline const Index* innerIndexPtr() const + { return m_matrix.innerIndexPtr() + m_matrix.outerIndexPtr()[m_outerStart]; } + inline Index* innerIndexPtr() + { return m_matrix.const_cast_derived().innerIndexPtr() + m_matrix.outerIndexPtr()[m_outerStart]; } - inline const Index* _outerIndexPtr() const - { return m_matrix._outerIndexPtr() + m_outerStart; } - inline Index* _outerIndexPtr() - { return m_matrix.const_cast_derived()._outerIndexPtr() + m_outerStart; } + inline const Index* outerIndexPtr() const + { return m_matrix.outerIndexPtr() + m_outerStart; } + inline Index* outerIndexPtr() + { return m_matrix.const_cast_derived().outerIndexPtr() + m_outerStart; } Index nonZeros() const { - return std::size_t(m_matrix._outerIndexPtr()[m_outerStart+m_outerSize.value()]) - - std::size_t(m_matrix._outerIndexPtr()[m_outerStart]); + if(m_matrix.isCompressed()) + return std::size_t(m_matrix.outerIndexPtr()[m_outerStart+m_outerSize.value()]) + - std::size_t(m_matrix.outerIndexPtr()[m_outerStart]); + else if(m_outerSize.value()==0) + return 0; + else + return Map >(m_matrix.innerNonZeroPtr()+m_outerStart, m_outerSize.value()).sum(); } const Scalar& lastCoeff() const { EIGEN_STATIC_ASSERT_VECTOR_ONLY(SparseInnerVectorSet); eigen_assert(nonZeros()>0); - return m_matrix._valuePtr()[m_matrix._outerIndexPtr()[m_outerStart+1]-1]; + if(m_matrix.isCompressed()) + return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart+1]-1]; + else + return m_matrix.valuePtr()[m_matrix.outerIndexPtr()[m_outerStart]+m_matrix.innerNonZeroPtr()[m_outerStart]-1]; } // template @@ -356,7 +276,7 @@ class SparseInnerVectorSet, Size> protected: - const typename MatrixType::Nested m_matrix; + typename MatrixType::Nested m_matrix; Index m_outerStart; const internal::variable_if_dynamic m_outerSize; @@ -412,11 +332,9 @@ template const SparseInnerVectorSet SparseMatrixBase::innerVector(Index outer) const { return SparseInnerVectorSet(derived(), outer); } -//---------- - /** \returns the i-th row of the matrix \c *this. For row-major matrix only. */ template -SparseInnerVectorSet SparseMatrixBase::subrows(Index start, Index size) +SparseInnerVectorSet SparseMatrixBase::middleRows(Index start, Index size) { EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES); return innerVectors(start, size); @@ -425,7 +343,7 @@ SparseInnerVectorSet SparseMatrixBase::subrows(Index s /** \returns the i-th row of the matrix \c *this. For row-major matrix only. * (read-only version) */ template -const SparseInnerVectorSet SparseMatrixBase::subrows(Index start, Index size) const +const SparseInnerVectorSet SparseMatrixBase::middleRows(Index start, Index size) const { EIGEN_STATIC_ASSERT(IsRowMajor,THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES); return innerVectors(start, size); @@ -433,7 +351,7 @@ const SparseInnerVectorSet SparseMatrixBase::subrows(I /** \returns the i-th column of the matrix \c *this. For column-major matrix only. */ template -SparseInnerVectorSet SparseMatrixBase::subcols(Index start, Index size) +SparseInnerVectorSet SparseMatrixBase::middleCols(Index start, Index size) { EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES); return innerVectors(start, size); @@ -442,12 +360,14 @@ SparseInnerVectorSet SparseMatrixBase::subcols(Index s /** \returns the i-th column of the matrix \c *this. For column-major matrix only. * (read-only version) */ template -const SparseInnerVectorSet SparseMatrixBase::subcols(Index start, Index size) const +const SparseInnerVectorSet SparseMatrixBase::middleCols(Index start, Index size) const { EIGEN_STATIC_ASSERT(!IsRowMajor,THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES); return innerVectors(start, size); } + + /** \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this * is col-major (resp. row-major). */ @@ -462,4 +382,6 @@ template const SparseInnerVectorSet SparseMatrixBase::innerVectors(Index outerStart, Index outerSize) const { return SparseInnerVectorSet(derived(), outerStart, outerSize); } +} // end namespace Eigen + #endif // EIGEN_SPARSE_BLOCK_H diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseCwiseBinaryOp.h b/extern/Eigen3/Eigen/src/SparseCore/SparseCwiseBinaryOp.h similarity index 77% rename from extern/Eigen3/Eigen/src/Sparse/SparseCwiseBinaryOp.h rename to extern/Eigen3/Eigen/src/SparseCore/SparseCwiseBinaryOp.h index cde5bbc0300..d5f97f78fc9 100644 --- a/extern/Eigen3/Eigen/src/Sparse/SparseCwiseBinaryOp.h +++ b/extern/Eigen3/Eigen/src/SparseCore/SparseCwiseBinaryOp.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SPARSE_CWISE_BINARY_OP_H #define EIGEN_SPARSE_CWISE_BINARY_OP_H +namespace Eigen { + // Here we have to handle 3 cases: // 1 - sparse op dense // 2 - dense op sparse @@ -63,8 +50,18 @@ class CwiseBinaryOpImpl { public: class InnerIterator; + class ReverseInnerIterator; typedef CwiseBinaryOp Derived; EIGEN_SPARSE_PUBLIC_INTERFACE(Derived) + CwiseBinaryOpImpl() + { + typedef typename internal::traits::StorageKind LhsStorageKind; + typedef typename internal::traits::StorageKind RhsStorageKind; + EIGEN_STATIC_ASSERT(( + (!internal::is_same::value) + || ((Lhs::Flags&RowMajorBit) == (Rhs::Flags&RowMajorBit))), + THE_STORAGE_ORDER_OF_BOTH_SIDES_MUST_MATCH); + } }; template @@ -76,7 +73,7 @@ class CwiseBinaryOpImpl::InnerIterator typedef internal::sparse_cwise_binary_op_inner_iterator_selector< BinaryOp,Lhs,Rhs, InnerIterator> Base; - EIGEN_STRONG_INLINE InnerIterator(const CwiseBinaryOpImpl& binOp, Index outer) + EIGEN_STRONG_INLINE InnerIterator(const CwiseBinaryOpImpl& binOp, typename CwiseBinaryOpImpl::Index outer) : Base(binOp.derived(),outer) {} }; @@ -246,7 +243,7 @@ class sparse_cwise_binary_op_inner_iterator_selector, Lhs, EIGEN_STRONG_INLINE operator bool() const { return m_lhsIter; } protected: - const RhsNested m_rhs; + RhsNested m_rhs; LhsIterator m_lhsIter; const BinaryFunc m_functor; const Index m_outer; @@ -298,16 +295,6 @@ class sparse_cwise_binary_op_inner_iterator_selector, Lhs, * Implementation of SparseMatrixBase and SparseCwise functions/operators ***************************************************************************/ -// template -// template -// EIGEN_STRONG_INLINE const CwiseBinaryOp::Scalar>, -// Derived, OtherDerived> -// SparseMatrixBase::operator-(const SparseMatrixBase &other) const -// { -// return CwiseBinaryOp, -// Derived, OtherDerived>(derived(), other.derived()); -// } - template template EIGEN_STRONG_INLINE Derived & @@ -316,14 +303,6 @@ SparseMatrixBase::operator-=(const SparseMatrixBase &othe return *this = derived() - other.derived(); } -// template -// template -// EIGEN_STRONG_INLINE const CwiseBinaryOp::Scalar>, Derived, OtherDerived> -// SparseMatrixBase::operator+(const SparseMatrixBase &other) const -// { -// return CwiseBinaryOp, Derived, OtherDerived>(derived(), other.derived()); -// } - template template EIGEN_STRONG_INLINE Derived & @@ -332,14 +311,6 @@ SparseMatrixBase::operator+=(const SparseMatrixBase& othe return *this = derived() + other.derived(); } -// template -// template -// EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE -// SparseCwise::operator*(const SparseMatrixBase &other) const -// { -// return EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE(_expression(), other.derived()); -// } - template template EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE @@ -348,28 +319,6 @@ SparseMatrixBase::cwiseProduct(const MatrixBase &other) c return EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE(derived(), other.derived()); } -// template -// template -// EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op) -// SparseCwise::operator/(const SparseMatrixBase &other) const -// { -// return EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op)(_expression(), other.derived()); -// } -// -// template -// template -// EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op) -// SparseCwise::operator/(const MatrixBase &other) const -// { -// return EIGEN_SPARSE_CWISE_BINOP_RETURN_TYPE(internal::scalar_quotient_op)(_expression(), other.derived()); -// } - -// template -// template -// inline ExpressionType& SparseCwise::operator*=(const SparseMatrixBase &other) -// { -// return m_matrix.const_cast_derived() = _expression() * other.derived(); -// } - +} // end namespace Eigen #endif // EIGEN_SPARSE_CWISE_BINARY_OP_H diff --git a/extern/Eigen3/Eigen/src/SparseCore/SparseCwiseUnaryOp.h b/extern/Eigen3/Eigen/src/SparseCore/SparseCwiseUnaryOp.h new file mode 100644 index 00000000000..5a50c780303 --- /dev/null +++ b/extern/Eigen3/Eigen/src/SparseCore/SparseCwiseUnaryOp.h @@ -0,0 +1,163 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2010 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SPARSE_CWISE_UNARY_OP_H +#define EIGEN_SPARSE_CWISE_UNARY_OP_H + +namespace Eigen { + +template +class CwiseUnaryOpImpl + : public SparseMatrixBase > +{ + public: + + class InnerIterator; + class ReverseInnerIterator; + + typedef CwiseUnaryOp Derived; + EIGEN_SPARSE_PUBLIC_INTERFACE(Derived) + + protected: + typedef typename internal::traits::_XprTypeNested _MatrixTypeNested; + typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator; + typedef typename _MatrixTypeNested::ReverseInnerIterator MatrixTypeReverseIterator; +}; + +template +class CwiseUnaryOpImpl::InnerIterator + : public CwiseUnaryOpImpl::MatrixTypeIterator +{ + typedef typename CwiseUnaryOpImpl::Scalar Scalar; + typedef typename CwiseUnaryOpImpl::MatrixTypeIterator Base; + public: + + EIGEN_STRONG_INLINE InnerIterator(const CwiseUnaryOpImpl& unaryOp, typename CwiseUnaryOpImpl::Index outer) + : Base(unaryOp.derived().nestedExpression(),outer), m_functor(unaryOp.derived().functor()) + {} + + EIGEN_STRONG_INLINE InnerIterator& operator++() + { Base::operator++(); return *this; } + + EIGEN_STRONG_INLINE typename CwiseUnaryOpImpl::Scalar value() const { return m_functor(Base::value()); } + + protected: + const UnaryOp m_functor; + private: + typename CwiseUnaryOpImpl::Scalar& valueRef(); +}; + +template +class CwiseUnaryOpImpl::ReverseInnerIterator + : public CwiseUnaryOpImpl::MatrixTypeReverseIterator +{ + typedef typename CwiseUnaryOpImpl::Scalar Scalar; + typedef typename CwiseUnaryOpImpl::MatrixTypeReverseIterator Base; + public: + + EIGEN_STRONG_INLINE ReverseInnerIterator(const CwiseUnaryOpImpl& unaryOp, typename CwiseUnaryOpImpl::Index outer) + : Base(unaryOp.derived().nestedExpression(),outer), m_functor(unaryOp.derived().functor()) + {} + + EIGEN_STRONG_INLINE ReverseInnerIterator& operator--() + { Base::operator--(); return *this; } + + EIGEN_STRONG_INLINE typename CwiseUnaryOpImpl::Scalar value() const { return m_functor(Base::value()); } + + protected: + const UnaryOp m_functor; + private: + typename CwiseUnaryOpImpl::Scalar& valueRef(); +}; + +template +class CwiseUnaryViewImpl + : public SparseMatrixBase > +{ + public: + + class InnerIterator; + class ReverseInnerIterator; + + typedef CwiseUnaryView Derived; + EIGEN_SPARSE_PUBLIC_INTERFACE(Derived) + + protected: + typedef typename internal::traits::_MatrixTypeNested _MatrixTypeNested; + typedef typename _MatrixTypeNested::InnerIterator MatrixTypeIterator; + typedef typename _MatrixTypeNested::ReverseInnerIterator MatrixTypeReverseIterator; +}; + +template +class CwiseUnaryViewImpl::InnerIterator + : public CwiseUnaryViewImpl::MatrixTypeIterator +{ + typedef typename CwiseUnaryViewImpl::Scalar Scalar; + typedef typename CwiseUnaryViewImpl::MatrixTypeIterator Base; + public: + + EIGEN_STRONG_INLINE InnerIterator(const CwiseUnaryViewImpl& unaryOp, typename CwiseUnaryViewImpl::Index outer) + : Base(unaryOp.derived().nestedExpression(),outer), m_functor(unaryOp.derived().functor()) + {} + + EIGEN_STRONG_INLINE InnerIterator& operator++() + { Base::operator++(); return *this; } + + EIGEN_STRONG_INLINE typename CwiseUnaryViewImpl::Scalar value() const { return m_functor(Base::value()); } + EIGEN_STRONG_INLINE typename CwiseUnaryViewImpl::Scalar& valueRef() { return m_functor(Base::valueRef()); } + + protected: + const ViewOp m_functor; +}; + +template +class CwiseUnaryViewImpl::ReverseInnerIterator + : public CwiseUnaryViewImpl::MatrixTypeReverseIterator +{ + typedef typename CwiseUnaryViewImpl::Scalar Scalar; + typedef typename CwiseUnaryViewImpl::MatrixTypeReverseIterator Base; + public: + + EIGEN_STRONG_INLINE ReverseInnerIterator(const CwiseUnaryViewImpl& unaryOp, typename CwiseUnaryViewImpl::Index outer) + : Base(unaryOp.derived().nestedExpression(),outer), m_functor(unaryOp.derived().functor()) + {} + + EIGEN_STRONG_INLINE ReverseInnerIterator& operator--() + { Base::operator--(); return *this; } + + EIGEN_STRONG_INLINE typename CwiseUnaryViewImpl::Scalar value() const { return m_functor(Base::value()); } + EIGEN_STRONG_INLINE typename CwiseUnaryViewImpl::Scalar& valueRef() { return m_functor(Base::valueRef()); } + + protected: + const ViewOp m_functor; +}; + +template +EIGEN_STRONG_INLINE Derived& +SparseMatrixBase::operator*=(const Scalar& other) +{ + for (Index j=0; j +EIGEN_STRONG_INLINE Derived& +SparseMatrixBase::operator/=(const Scalar& other) +{ + for (Index j=0; j // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SPARSEDENSEPRODUCT_H #define EIGEN_SPARSEDENSEPRODUCT_H +namespace Eigen { + template struct SparseDenseProductReturnType { typedef SparseTimeDenseProduct Type; @@ -149,6 +136,102 @@ struct traits > typedef Dense StorageKind; typedef MatrixXpr XprKind; }; + +template +struct sparse_time_dense_product_impl; + +template +struct sparse_time_dense_product_impl +{ + typedef typename internal::remove_all::type Lhs; + typedef typename internal::remove_all::type Rhs; + typedef typename internal::remove_all::type Res; + typedef typename Lhs::Index Index; + typedef typename Lhs::InnerIterator LhsInnerIterator; + static void run(const SparseLhsType& lhs, const DenseRhsType& rhs, DenseResType& res, typename Res::Scalar alpha) + { + for(Index c=0; c +struct sparse_time_dense_product_impl +{ + typedef typename internal::remove_all::type Lhs; + typedef typename internal::remove_all::type Rhs; + typedef typename internal::remove_all::type Res; + typedef typename Lhs::InnerIterator LhsInnerIterator; + typedef typename Lhs::Index Index; + static void run(const SparseLhsType& lhs, const DenseRhsType& rhs, DenseResType& res, typename Res::Scalar alpha) + { + for(Index c=0; c +struct sparse_time_dense_product_impl +{ + typedef typename internal::remove_all::type Lhs; + typedef typename internal::remove_all::type Rhs; + typedef typename internal::remove_all::type Res; + typedef typename Lhs::InnerIterator LhsInnerIterator; + typedef typename Lhs::Index Index; + static void run(const SparseLhsType& lhs, const DenseRhsType& rhs, DenseResType& res, typename Res::Scalar alpha) + { + for(Index j=0; j +struct sparse_time_dense_product_impl +{ + typedef typename internal::remove_all::type Lhs; + typedef typename internal::remove_all::type Rhs; + typedef typename internal::remove_all::type Res; + typedef typename Lhs::InnerIterator LhsInnerIterator; + typedef typename Lhs::Index Index; + static void run(const SparseLhsType& lhs, const DenseRhsType& rhs, DenseResType& res, typename Res::Scalar alpha) + { + for(Index j=0; j +inline void sparse_time_dense_product(const SparseLhsType& lhs, const DenseRhsType& rhs, DenseResType& res, const AlphaType& alpha) +{ + sparse_time_dense_product_impl::run(lhs, rhs, res, alpha); +} + } // end namespace internal template @@ -163,21 +246,7 @@ class SparseTimeDenseProduct template void scaleAndAddTo(Dest& dest, Scalar alpha) const { - typedef typename internal::remove_all::type _Lhs; - typedef typename internal::remove_all::type _Rhs; - typedef typename _Lhs::InnerIterator LhsInnerIterator; - enum { LhsIsRowMajor = (_Lhs::Flags&RowMajorBit)==RowMajorBit }; - for(Index j=0; j void scaleAndAddTo(Dest& dest, Scalar alpha) const { - typedef typename internal::remove_all::type _Rhs; - typedef typename _Rhs::InnerIterator RhsInnerIterator; - enum { RhsIsRowMajor = (_Rhs::Flags&RowMajorBit)==RowMajorBit }; - for(Index j=0; j lhs_t(m_lhs); + Transpose rhs_t(m_rhs); + Transpose dest_t(dest); + internal::sparse_time_dense_product(rhs_t, lhs_t, dest_t, alpha); } private: @@ -228,4 +295,6 @@ SparseMatrixBase::operator*(const MatrixBase &other) cons return typename SparseDenseProductReturnType::Type(derived(), other.derived()); } +} // end namespace Eigen + #endif // EIGEN_SPARSEDENSEPRODUCT_H diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseDiagonalProduct.h b/extern/Eigen3/Eigen/src/SparseCore/SparseDiagonalProduct.h similarity index 87% rename from extern/Eigen3/Eigen/src/Sparse/SparseDiagonalProduct.h rename to extern/Eigen3/Eigen/src/SparseCore/SparseDiagonalProduct.h index fb9a29c051b..095bf6863fc 100644 --- a/extern/Eigen3/Eigen/src/Sparse/SparseDiagonalProduct.h +++ b/extern/Eigen3/Eigen/src/SparseCore/SparseDiagonalProduct.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SPARSE_DIAGONAL_PRODUCT_H #define EIGEN_SPARSE_DIAGONAL_PRODUCT_H +namespace Eigen { + // The product of a diagonal matrix with a sparse matrix can be easily // implemented using expression template. // We have two consider very different cases: @@ -192,4 +179,6 @@ SparseMatrixBase::operator*(const DiagonalBase &other) co return SparseDiagonalProduct(this->derived(), other.derived()); } +} // end namespace Eigen + #endif // EIGEN_SPARSE_DIAGONAL_PRODUCT_H diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseDot.h b/extern/Eigen3/Eigen/src/SparseCore/SparseDot.h similarity index 67% rename from extern/Eigen3/Eigen/src/Sparse/SparseDot.h rename to extern/Eigen3/Eigen/src/SparseCore/SparseDot.h index 1f10f71a402..5c4a593dc01 100644 --- a/extern/Eigen3/Eigen/src/Sparse/SparseDot.h +++ b/extern/Eigen3/Eigen/src/SparseCore/SparseDot.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SPARSE_DOT_H #define EIGEN_SPARSE_DOT_H +namespace Eigen { + template template typename internal::traits::Scalar @@ -40,7 +27,7 @@ SparseMatrixBase::dot(const MatrixBase& other) const eigen_assert(other.size()>0 && "you are using a non initialized vector"); typename Derived::InnerIterator i(derived(),0); - Scalar res = 0; + Scalar res(0); while (i) { res += internal::conj(i.value()) * other.coeff(i.index()); @@ -62,9 +49,17 @@ SparseMatrixBase::dot(const SparseMatrixBase& other) cons eigen_assert(size() == other.size()); - typename Derived::InnerIterator i(derived(),0); - typename OtherDerived::InnerIterator j(other.derived(),0); - Scalar res = 0; + typedef typename Derived::Nested Nested; + typedef typename OtherDerived::Nested OtherNested; + typedef typename internal::remove_all::type NestedCleaned; + typedef typename internal::remove_all::type OtherNestedCleaned; + + const Nested nthis(derived()); + const OtherNested nother(other.derived()); + + typename NestedCleaned::InnerIterator i(nthis,0); + typename OtherNestedCleaned::InnerIterator j(nother,0); + Scalar res(0); while (i && j) { if (i.index()==j.index()) @@ -94,4 +89,6 @@ SparseMatrixBase::norm() const return internal::sqrt(squaredNorm()); } +} // end namespace Eigen + #endif // EIGEN_SPARSE_DOT_H diff --git a/extern/Eigen3/Eigen/src/SparseCore/SparseFuzzy.h b/extern/Eigen3/Eigen/src/SparseCore/SparseFuzzy.h new file mode 100644 index 00000000000..45f36e9eb90 --- /dev/null +++ b/extern/Eigen3/Eigen/src/SparseCore/SparseFuzzy.h @@ -0,0 +1,26 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SPARSE_FUZZY_H +#define EIGEN_SPARSE_FUZZY_H + +// template +// template +// bool SparseMatrixBase::isApprox( +// const OtherDerived& other, +// typename NumTraits::Real prec +// ) const +// { +// const typename internal::nested::type nested(derived()); +// const typename internal::nested::type otherNested(other.derived()); +// return (nested - otherNested).cwise().abs2().sum() +// <= prec * prec * (std::min)(nested.cwise().abs2().sum(), otherNested.cwise().abs2().sum()); +// } + +#endif // EIGEN_SPARSE_FUZZY_H diff --git a/extern/Eigen3/Eigen/src/SparseCore/SparseMatrix.h b/extern/Eigen3/Eigen/src/SparseCore/SparseMatrix.h new file mode 100644 index 00000000000..efb774f031b --- /dev/null +++ b/extern/Eigen3/Eigen/src/SparseCore/SparseMatrix.h @@ -0,0 +1,1116 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2010 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SPARSEMATRIX_H +#define EIGEN_SPARSEMATRIX_H + +namespace Eigen { + +/** \ingroup SparseCore_Module + * + * \class SparseMatrix + * + * \brief A versatible sparse matrix representation + * + * This class implements a more versatile variants of the common \em compressed row/column storage format. + * Each colmun's (resp. row) non zeros are stored as a pair of value with associated row (resp. colmiun) index. + * All the non zeros are stored in a single large buffer. Unlike the \em compressed format, there might be extra + * space inbetween the nonzeros of two successive colmuns (resp. rows) such that insertion of new non-zero + * can be done with limited memory reallocation and copies. + * + * A call to the function makeCompressed() turns the matrix into the standard \em compressed format + * compatible with many library. + * + * More details on this storage sceheme are given in the \ref TutorialSparse "manual pages". + * + * \tparam _Scalar the scalar type, i.e. the type of the coefficients + * \tparam _Options Union of bit flags controlling the storage scheme. Currently the only possibility + * is RowMajor. The default is 0 which means column-major. + * \tparam _Index the type of the indices. It has to be a \b signed type (e.g., short, int, std::ptrdiff_t). Default is \c int. + * + * This class can be extended with the help of the plugin mechanism described on the page + * \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_SPARSEMATRIX_PLUGIN. + */ + +namespace internal { +template +struct traits > +{ + typedef _Scalar Scalar; + typedef _Index Index; + typedef Sparse StorageKind; + typedef MatrixXpr XprKind; + enum { + RowsAtCompileTime = Dynamic, + ColsAtCompileTime = Dynamic, + MaxRowsAtCompileTime = Dynamic, + MaxColsAtCompileTime = Dynamic, + Flags = _Options | NestByRefBit | LvalueBit, + CoeffReadCost = NumTraits::ReadCost, + SupportedAccessPatterns = InnerRandomAccessPattern + }; +}; + +template +struct traits, DiagIndex> > +{ + typedef SparseMatrix<_Scalar, _Options, _Index> MatrixType; + typedef typename nested::type MatrixTypeNested; + typedef typename remove_reference::type _MatrixTypeNested; + + typedef _Scalar Scalar; + typedef Dense StorageKind; + typedef _Index Index; + typedef MatrixXpr XprKind; + + enum { + RowsAtCompileTime = Dynamic, + ColsAtCompileTime = 1, + MaxRowsAtCompileTime = Dynamic, + MaxColsAtCompileTime = 1, + Flags = 0, + CoeffReadCost = _MatrixTypeNested::CoeffReadCost*10 + }; +}; + +} // end namespace internal + +template +class SparseMatrix + : public SparseMatrixBase > +{ + public: + EIGEN_SPARSE_PUBLIC_INTERFACE(SparseMatrix) + EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseMatrix, +=) + EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseMatrix, -=) + + typedef MappedSparseMatrix Map; + using Base::IsRowMajor; + typedef internal::CompressedStorage Storage; + enum { + Options = _Options + }; + + protected: + + typedef SparseMatrix TransposedSparseMatrix; + + Index m_outerSize; + Index m_innerSize; + Index* m_outerIndex; + Index* m_innerNonZeros; // optional, if null then the data is compressed + Storage m_data; + + Eigen::Map > innerNonZeros() { return Eigen::Map >(m_innerNonZeros, m_innerNonZeros?m_outerSize:0); } + const Eigen::Map > innerNonZeros() const { return Eigen::Map >(m_innerNonZeros, m_innerNonZeros?m_outerSize:0); } + + public: + + /** \returns whether \c *this is in compressed form. */ + inline bool isCompressed() const { return m_innerNonZeros==0; } + + /** \returns the number of rows of the matrix */ + inline Index rows() const { return IsRowMajor ? m_outerSize : m_innerSize; } + /** \returns the number of columns of the matrix */ + inline Index cols() const { return IsRowMajor ? m_innerSize : m_outerSize; } + + /** \returns the number of rows (resp. columns) of the matrix if the storage order column major (resp. row major) */ + inline Index innerSize() const { return m_innerSize; } + /** \returns the number of columns (resp. rows) of the matrix if the storage order column major (resp. row major) */ + inline Index outerSize() const { return m_outerSize; } + + /** \returns a const pointer to the array of values. + * This function is aimed at interoperability with other libraries. + * \sa innerIndexPtr(), outerIndexPtr() */ + inline const Scalar* valuePtr() const { return &m_data.value(0); } + /** \returns a non-const pointer to the array of values. + * This function is aimed at interoperability with other libraries. + * \sa innerIndexPtr(), outerIndexPtr() */ + inline Scalar* valuePtr() { return &m_data.value(0); } + + /** \returns a const pointer to the array of inner indices. + * This function is aimed at interoperability with other libraries. + * \sa valuePtr(), outerIndexPtr() */ + inline const Index* innerIndexPtr() const { return &m_data.index(0); } + /** \returns a non-const pointer to the array of inner indices. + * This function is aimed at interoperability with other libraries. + * \sa valuePtr(), outerIndexPtr() */ + inline Index* innerIndexPtr() { return &m_data.index(0); } + + /** \returns a const pointer to the array of the starting positions of the inner vectors. + * This function is aimed at interoperability with other libraries. + * \sa valuePtr(), innerIndexPtr() */ + inline const Index* outerIndexPtr() const { return m_outerIndex; } + /** \returns a non-const pointer to the array of the starting positions of the inner vectors. + * This function is aimed at interoperability with other libraries. + * \sa valuePtr(), innerIndexPtr() */ + inline Index* outerIndexPtr() { return m_outerIndex; } + + /** \returns a const pointer to the array of the number of non zeros of the inner vectors. + * This function is aimed at interoperability with other libraries. + * \warning it returns the null pointer 0 in compressed mode */ + inline const Index* innerNonZeroPtr() const { return m_innerNonZeros; } + /** \returns a non-const pointer to the array of the number of non zeros of the inner vectors. + * This function is aimed at interoperability with other libraries. + * \warning it returns the null pointer 0 in compressed mode */ + inline Index* innerNonZeroPtr() { return m_innerNonZeros; } + + /** \internal */ + inline Storage& data() { return m_data; } + /** \internal */ + inline const Storage& data() const { return m_data; } + + /** \returns the value of the matrix at position \a i, \a j + * This function returns Scalar(0) if the element is an explicit \em zero */ + inline Scalar coeff(Index row, Index col) const + { + const Index outer = IsRowMajor ? row : col; + const Index inner = IsRowMajor ? col : row; + Index end = m_innerNonZeros ? m_outerIndex[outer] + m_innerNonZeros[outer] : m_outerIndex[outer+1]; + return m_data.atInRange(m_outerIndex[outer], end, inner); + } + + /** \returns a non-const reference to the value of the matrix at position \a i, \a j + * + * If the element does not exist then it is inserted via the insert(Index,Index) function + * which itself turns the matrix into a non compressed form if that was not the case. + * + * This is a O(log(nnz_j)) operation (binary search) plus the cost of insert(Index,Index) + * function if the element does not already exist. + */ + inline Scalar& coeffRef(Index row, Index col) + { + const Index outer = IsRowMajor ? row : col; + const Index inner = IsRowMajor ? col : row; + + Index start = m_outerIndex[outer]; + Index end = m_innerNonZeros ? m_outerIndex[outer] + m_innerNonZeros[outer] : m_outerIndex[outer+1]; + eigen_assert(end>=start && "you probably called coeffRef on a non finalized matrix"); + if(end<=start) + return insert(row,col); + const Index p = m_data.searchLowerIndex(start,end-1,inner); + if((p(m_data.size()); + } + + /** Preallocates \a reserveSize non zeros. + * + * Precondition: the matrix must be in compressed mode. */ + inline void reserve(Index reserveSize) + { + eigen_assert(isCompressed() && "This function does not make sense in non compressed mode."); + m_data.reserve(reserveSize); + } + + #ifdef EIGEN_PARSED_BY_DOXYGEN + /** Preallocates \a reserveSize[\c j] non zeros for each column (resp. row) \c j. + * + * This function turns the matrix in non-compressed mode */ + template + inline void reserve(const SizesType& reserveSizes); + #else + template + inline void reserve(const SizesType& reserveSizes, const typename SizesType::value_type& enableif = typename SizesType::value_type()) + { + EIGEN_UNUSED_VARIABLE(enableif); + reserveInnerVectors(reserveSizes); + } + template + inline void reserve(const SizesType& reserveSizes, const typename SizesType::Scalar& enableif = + #if (!defined(_MSC_VER)) || (_MSC_VER>=1500) // MSVC 2005 fails to compile with this typename + typename + #endif + SizesType::Scalar()) + { + EIGEN_UNUSED_VARIABLE(enableif); + reserveInnerVectors(reserveSizes); + } + #endif // EIGEN_PARSED_BY_DOXYGEN + protected: + template + inline void reserveInnerVectors(const SizesType& reserveSizes) + { + + if(isCompressed()) + { + std::size_t totalReserveSize = 0; + // turn the matrix into non-compressed mode + m_innerNonZeros = new Index[m_outerSize]; + + // temporarily use m_innerSizes to hold the new starting points. + Index* newOuterIndex = m_innerNonZeros; + + Index count = 0; + for(Index j=0; j=0; --j) + { + ptrdiff_t innerNNZ = previousOuterIndex - m_outerIndex[j]; + for(std::ptrdiff_t i=innerNNZ-1; i>=0; --i) + { + m_data.index(newOuterIndex[j]+i) = m_data.index(m_outerIndex[j]+i); + m_data.value(newOuterIndex[j]+i) = m_data.value(m_outerIndex[j]+i); + } + previousOuterIndex = m_outerIndex[j]; + m_outerIndex[j] = newOuterIndex[j]; + m_innerNonZeros[j] = innerNNZ; + } + m_outerIndex[m_outerSize] = m_outerIndex[m_outerSize-1] + m_innerNonZeros[m_outerSize-1] + reserveSizes[m_outerSize-1]; + + m_data.resize(m_outerIndex[m_outerSize]); + } + else + { + Index* newOuterIndex = new Index[m_outerSize+1]; + Index count = 0; + for(Index j=0; j(reserveSizes[j], alreadyReserved); + count += toReserve + m_innerNonZeros[j]; + } + newOuterIndex[m_outerSize] = count; + + m_data.resize(count); + for(ptrdiff_t j=m_outerSize-1; j>=0; --j) + { + std::ptrdiff_t offset = newOuterIndex[j] - m_outerIndex[j]; + if(offset>0) + { + std::ptrdiff_t innerNNZ = m_innerNonZeros[j]; + for(std::ptrdiff_t i=innerNNZ-1; i>=0; --i) + { + m_data.index(newOuterIndex[j]+i) = m_data.index(m_outerIndex[j]+i); + m_data.value(newOuterIndex[j]+i) = m_data.value(m_outerIndex[j]+i); + } + } + } + + std::swap(m_outerIndex, newOuterIndex); + delete[] newOuterIndex; + } + + } + public: + + //--- low level purely coherent filling --- + + /** \internal + * \returns a reference to the non zero coefficient at position \a row, \a col assuming that: + * - the nonzero does not already exist + * - the new coefficient is the last one according to the storage order + * + * Before filling a given inner vector you must call the statVec(Index) function. + * + * After an insertion session, you should call the finalize() function. + * + * \sa insert, insertBackByOuterInner, startVec */ + inline Scalar& insertBack(Index row, Index col) + { + return insertBackByOuterInner(IsRowMajor?row:col, IsRowMajor?col:row); + } + + /** \internal + * \sa insertBack, startVec */ + inline Scalar& insertBackByOuterInner(Index outer, Index inner) + { + eigen_assert(size_t(m_outerIndex[outer+1]) == m_data.size() && "Invalid ordered insertion (invalid outer index)"); + eigen_assert( (m_outerIndex[outer+1]-m_outerIndex[outer]==0 || m_data.index(m_data.size()-1)(m_data.size()); + Index i = m_outerSize; + // find the last filled column + while (i>=0 && m_outerIndex[i]==0) + --i; + ++i; + while (i<=m_outerSize) + { + m_outerIndex[i] = size; + ++i; + } + } + } + + //--- + + template + void setFromTriplets(const InputIterators& begin, const InputIterators& end); + + void sumupDuplicates(); + + //--- + + /** \internal + * same as insert(Index,Index) except that the indices are given relative to the storage order */ + EIGEN_DONT_INLINE Scalar& insertByOuterInner(Index j, Index i) + { + return insert(IsRowMajor ? j : i, IsRowMajor ? i : j); + } + + /** Turns the matrix into the \em compressed format. + */ + void makeCompressed() + { + if(isCompressed()) + return; + + Index oldStart = m_outerIndex[1]; + m_outerIndex[1] = m_innerNonZeros[0]; + for(Index j=1; j0) + { + for(Index k=0; k::dummy_precision()) + { + prune(default_prunning_func(reference,epsilon)); + } + + /** Turns the matrix into compressed format, and suppresses all nonzeros which do not satisfy the predicate \a keep. + * The functor type \a KeepFunc must implement the following function: + * \code + * bool operator() (const Index& row, const Index& col, const Scalar& value) const; + * \endcode + * \sa prune(Scalar,RealScalar) + */ + template + void prune(const KeepFunc& keep = KeepFunc()) + { + // TODO optimize the uncompressed mode to avoid moving and allocating the data twice + // TODO also implement a unit test + makeCompressed(); + + Index k = 0; + for(Index j=0; j diagonal() const { return *this; } + + /** Default constructor yielding an empty \c 0 \c x \c 0 matrix */ + inline SparseMatrix() + : m_outerSize(-1), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0) + { + check_template_parameters(); + resize(0, 0); + } + + /** Constructs a \a rows \c x \a cols empty matrix */ + inline SparseMatrix(Index rows, Index cols) + : m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0) + { + check_template_parameters(); + resize(rows, cols); + } + + /** Constructs a sparse matrix from the sparse expression \a other */ + template + inline SparseMatrix(const SparseMatrixBase& other) + : m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0) + { + check_template_parameters(); + *this = other.derived(); + } + + /** Copy constructor (it performs a deep copy) */ + inline SparseMatrix(const SparseMatrix& other) + : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0) + { + check_template_parameters(); + *this = other.derived(); + } + + /** Swaps the content of two sparse matrices of the same type. + * This is a fast operation that simply swaps the underlying pointers and parameters. */ + inline void swap(SparseMatrix& other) + { + //EIGEN_DBG_SPARSE(std::cout << "SparseMatrix:: swap\n"); + std::swap(m_outerIndex, other.m_outerIndex); + std::swap(m_innerSize, other.m_innerSize); + std::swap(m_outerSize, other.m_outerSize); + std::swap(m_innerNonZeros, other.m_innerNonZeros); + m_data.swap(other.m_data); + } + + inline SparseMatrix& operator=(const SparseMatrix& other) + { + if (other.isRValue()) + { + swap(other.const_cast_derived()); + } + else + { + initAssignment(other); + if(other.isCompressed()) + { + memcpy(m_outerIndex, other.m_outerIndex, (m_outerSize+1)*sizeof(Index)); + m_data = other.m_data; + } + else + { + Base::operator=(other); + } + } + return *this; + } + + #ifndef EIGEN_PARSED_BY_DOXYGEN + template + inline SparseMatrix& operator=(const SparseSparseProduct& product) + { return Base::operator=(product); } + + template + inline SparseMatrix& operator=(const ReturnByValue& other) + { return Base::operator=(other.derived()); } + + template + inline SparseMatrix& operator=(const EigenBase& other) + { return Base::operator=(other.derived()); } + #endif + + template + EIGEN_DONT_INLINE SparseMatrix& operator=(const SparseMatrixBase& other) + { + initAssignment(other.derived()); + const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit); + if (needToTranspose) + { + // two passes algorithm: + // 1 - compute the number of coeffs per dest inner vector + // 2 - do the actual copy/eval + // Since each coeff of the rhs has to be evaluated twice, let's evaluate it if needed + typedef typename internal::nested::type OtherCopy; + typedef typename internal::remove_all::type _OtherCopy; + OtherCopy otherCopy(other.derived()); + + Eigen::Map > (m_outerIndex,outerSize()).setZero(); + // pass 1 + // FIXME the above copy could be merged with that pass + for (Index j=0; j&>(m); + return s; + } + + /** Destructor */ + inline ~SparseMatrix() + { + delete[] m_outerIndex; + delete[] m_innerNonZeros; + } + +#ifndef EIGEN_PARSED_BY_DOXYGEN + /** Overloaded for performance */ + Scalar sum() const; +#endif + +# ifdef EIGEN_SPARSEMATRIX_PLUGIN +# include EIGEN_SPARSEMATRIX_PLUGIN +# endif + +protected: + + template + void initAssignment(const Other& other) + { + resize(other.rows(), other.cols()); + if(m_innerNonZeros) + { + delete[] m_innerNonZeros; + m_innerNonZeros = 0; + } + } + + /** \internal + * \sa insert(Index,Index) */ + EIGEN_DONT_INLINE Scalar& insertCompressed(Index row, Index col) + { + eigen_assert(isCompressed()); + + const Index outer = IsRowMajor ? row : col; + const Index inner = IsRowMajor ? col : row; + + Index previousOuter = outer; + if (m_outerIndex[outer+1]==0) + { + // we start a new inner vector + while (previousOuter>=0 && m_outerIndex[previousOuter]==0) + { + m_outerIndex[previousOuter] = static_cast(m_data.size()); + --previousOuter; + } + m_outerIndex[outer+1] = m_outerIndex[outer]; + } + + // here we have to handle the tricky case where the outerIndex array + // starts with: [ 0 0 0 0 0 1 ...] and we are inserted in, e.g., + // the 2nd inner vector... + bool isLastVec = (!(previousOuter==-1 && m_data.size()!=0)) + && (size_t(m_outerIndex[outer+1]) == m_data.size()); + + size_t startId = m_outerIndex[outer]; + // FIXME let's make sure sizeof(long int) == sizeof(size_t) + size_t p = m_outerIndex[outer+1]; + ++m_outerIndex[outer+1]; + + float reallocRatio = 1; + if (m_data.allocatedSize()<=m_data.size()) + { + // if there is no preallocated memory, let's reserve a minimum of 32 elements + if (m_data.size()==0) + { + m_data.reserve(32); + } + else + { + // we need to reallocate the data, to reduce multiple reallocations + // we use a smart resize algorithm based on the current filling ratio + // in addition, we use float to avoid integers overflows + float nnzEstimate = float(m_outerIndex[outer])*float(m_outerSize)/float(outer+1); + reallocRatio = (nnzEstimate-float(m_data.size()))/float(m_data.size()); + // furthermore we bound the realloc ratio to: + // 1) reduce multiple minor realloc when the matrix is almost filled + // 2) avoid to allocate too much memory when the matrix is almost empty + reallocRatio = (std::min)((std::max)(reallocRatio,1.5f),8.f); + } + } + m_data.resize(m_data.size()+1,reallocRatio); + + if (!isLastVec) + { + if (previousOuter==-1) + { + // oops wrong guess. + // let's correct the outer offsets + for (Index k=0; k<=(outer+1); ++k) + m_outerIndex[k] = 0; + Index k=outer+1; + while(m_outerIndex[k]==0) + m_outerIndex[k++] = 1; + while (k<=m_outerSize && m_outerIndex[k]!=0) + m_outerIndex[k++]++; + p = 0; + --k; + k = m_outerIndex[k]-1; + while (k>0) + { + m_data.index(k) = m_data.index(k-1); + m_data.value(k) = m_data.value(k-1); + k--; + } + } + else + { + // we are not inserting into the last inner vec + // update outer indices: + Index j = outer+2; + while (j<=m_outerSize && m_outerIndex[j]!=0) + m_outerIndex[j++]++; + --j; + // shift data of last vecs: + Index k = m_outerIndex[j]-1; + while (k>=Index(p)) + { + m_data.index(k) = m_data.index(k-1); + m_data.value(k) = m_data.value(k-1); + k--; + } + } + } + + while ( (p > startId) && (m_data.index(p-1) > inner) ) + { + m_data.index(p) = m_data.index(p-1); + m_data.value(p) = m_data.value(p-1); + --p; + } + + m_data.index(p) = inner; + return (m_data.value(p) = 0); + } + + /** \internal + * A vector object that is equal to 0 everywhere but v at the position i */ + class SingletonVector + { + Index m_index; + Index m_value; + public: + typedef Index value_type; + SingletonVector(Index i, Index v) + : m_index(i), m_value(v) + {} + + Index operator[](Index i) const { return i==m_index ? m_value : 0; } + }; + + /** \internal + * \sa insert(Index,Index) */ + EIGEN_DONT_INLINE Scalar& insertUncompressed(Index row, Index col) + { + eigen_assert(!isCompressed()); + + const Index outer = IsRowMajor ? row : col; + const Index inner = IsRowMajor ? col : row; + + std::ptrdiff_t room = m_outerIndex[outer+1] - m_outerIndex[outer]; + std::ptrdiff_t innerNNZ = m_innerNonZeros[outer]; + if(innerNNZ>=room) + { + // this inner vector is full, we need to reallocate the whole buffer :( + reserve(SingletonVector(outer,std::max(2,innerNNZ))); + } + + Index startId = m_outerIndex[outer]; + Index p = startId + m_innerNonZeros[outer]; + while ( (p > startId) && (m_data.index(p-1) > inner) ) + { + m_data.index(p) = m_data.index(p-1); + m_data.value(p) = m_data.value(p-1); + --p; + } + + m_innerNonZeros[outer]++; + + m_data.index(p) = inner; + return (m_data.value(p) = 0); + } + +public: + /** \internal + * \sa insert(Index,Index) */ + inline Scalar& insertBackUncompressed(Index row, Index col) + { + const Index outer = IsRowMajor ? row : col; + const Index inner = IsRowMajor ? col : row; + + eigen_assert(!isCompressed()); + eigen_assert(m_innerNonZeros[outer]<=(m_outerIndex[outer+1] - m_outerIndex[outer])); + + Index p = m_outerIndex[outer] + m_innerNonZeros[outer]; + m_innerNonZeros[outer]++; + m_data.index(p) = inner; + return (m_data.value(p) = 0); + } + +private: + static void check_template_parameters() + { + EIGEN_STATIC_ASSERT(NumTraits::IsSigned,THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE); + } + + struct default_prunning_func { + default_prunning_func(Scalar ref, RealScalar eps) : reference(ref), epsilon(eps) {} + inline bool operator() (const Index&, const Index&, const Scalar& value) const + { + return !internal::isMuchSmallerThan(value, reference, epsilon); + } + Scalar reference; + RealScalar epsilon; + }; +}; + +template +class SparseMatrix::InnerIterator +{ + public: + InnerIterator(const SparseMatrix& mat, Index outer) + : m_values(mat.valuePtr()), m_indices(mat.innerIndexPtr()), m_outer(outer), m_id(mat.m_outerIndex[outer]) + { + if(mat.isCompressed()) + m_end = mat.m_outerIndex[outer+1]; + else + m_end = m_id + mat.m_innerNonZeros[outer]; + } + + inline InnerIterator& operator++() { m_id++; return *this; } + + inline const Scalar& value() const { return m_values[m_id]; } + inline Scalar& valueRef() { return const_cast(m_values[m_id]); } + + inline Index index() const { return m_indices[m_id]; } + inline Index outer() const { return m_outer; } + inline Index row() const { return IsRowMajor ? m_outer : index(); } + inline Index col() const { return IsRowMajor ? index() : m_outer; } + + inline operator bool() const { return (m_id < m_end); } + + protected: + const Scalar* m_values; + const Index* m_indices; + const Index m_outer; + Index m_id; + Index m_end; +}; + +template +class SparseMatrix::ReverseInnerIterator +{ + public: + ReverseInnerIterator(const SparseMatrix& mat, Index outer) + : m_values(mat.valuePtr()), m_indices(mat.innerIndexPtr()), m_outer(outer), m_start(mat.m_outerIndex[outer]) + { + if(mat.isCompressed()) + m_id = mat.m_outerIndex[outer+1]; + else + m_id = m_start + mat.m_innerNonZeros[outer]; + } + + inline ReverseInnerIterator& operator--() { --m_id; return *this; } + + inline const Scalar& value() const { return m_values[m_id-1]; } + inline Scalar& valueRef() { return const_cast(m_values[m_id-1]); } + + inline Index index() const { return m_indices[m_id-1]; } + inline Index outer() const { return m_outer; } + inline Index row() const { return IsRowMajor ? m_outer : index(); } + inline Index col() const { return IsRowMajor ? index() : m_outer; } + + inline operator bool() const { return (m_id > m_start); } + + protected: + const Scalar* m_values; + const Index* m_indices; + const Index m_outer; + Index m_id; + const Index m_start; +}; + +namespace internal { + +template +void set_from_triplets(const InputIterator& begin, const InputIterator& end, SparseMatrixType& mat, int Options = 0) +{ + EIGEN_UNUSED_VARIABLE(Options); + enum { IsRowMajor = SparseMatrixType::IsRowMajor }; + typedef typename SparseMatrixType::Scalar Scalar; + typedef typename SparseMatrixType::Index Index; + SparseMatrix trMat(mat.rows(),mat.cols()); + + // pass 1: count the nnz per inner-vector + VectorXi wi(trMat.outerSize()); + wi.setZero(); + for(InputIterator it(begin); it!=end; ++it) + wi(IsRowMajor ? it->col() : it->row())++; + + // pass 2: insert all the elements into trMat + trMat.reserve(wi); + for(InputIterator it(begin); it!=end; ++it) + trMat.insertBackUncompressed(it->row(),it->col()) = it->value(); + + // pass 3: + trMat.sumupDuplicates(); + + // pass 4: transposed copy -> implicit sorting + mat = trMat; +} + +} + + +/** Fill the matrix \c *this with the list of \em triplets defined by the iterator range \a begin - \b. + * + * A \em triplet is a tuple (i,j,value) defining a non-zero element. + * The input list of triplets does not have to be sorted, and can contains duplicated elements. + * In any case, the result is a \b sorted and \b compressed sparse matrix where the duplicates have been summed up. + * This is a \em O(n) operation, with \em n the number of triplet elements. + * The initial contents of \c *this is destroyed. + * The matrix \c *this must be properly resized beforehand using the SparseMatrix(Index,Index) constructor, + * or the resize(Index,Index) method. The sizes are not extracted from the triplet list. + * + * The \a InputIterators value_type must provide the following interface: + * \code + * Scalar value() const; // the value + * Scalar row() const; // the row index i + * Scalar col() const; // the column index j + * \endcode + * See for instance the Eigen::Triplet template class. + * + * Here is a typical usage example: + * \code + typedef Triplet T; + std::vector tripletList; + triplets.reserve(estimation_of_entries); + for(...) + { + // ... + tripletList.push_back(T(i,j,v_ij)); + } + SparseMatrixType m(rows,cols); + m.setFromTriplets(tripletList.begin(), tripletList.end()); + // m is ready to go! + * \endcode + * + * \warning The list of triplets is read multiple times (at least twice). Therefore, it is not recommended to define + * an abstract iterator over a complex data-structure that would be expensive to evaluate. The triplets should rather + * be explicitely stored into a std::vector for instance. + */ +template +template +void SparseMatrix::setFromTriplets(const InputIterators& begin, const InputIterators& end) +{ + internal::set_from_triplets(begin, end, *this); +} + +/** \internal */ +template +void SparseMatrix::sumupDuplicates() +{ + eigen_assert(!isCompressed()); + // TODO, in practice we should be able to use m_innerNonZeros for that task + VectorXi wi(innerSize()); + wi.fill(-1); + Index count = 0; + // for each inner-vector, wi[inner_index] will hold the position of first element into the index/value buffers + for(int j=0; j=start) + { + // we already meet this entry => accumulate it + m_data.value(wi(i)) += m_data.value(k); + } + else + { + m_data.value(count) = m_data.value(k); + m_data.index(count) = m_data.index(k); + wi(i) = count; + ++count; + } + } + m_outerIndex[j] = start; + } + m_outerIndex[m_outerSize] = count; + + // turn the matrix into compressed form + delete[] m_innerNonZeros; + m_innerNonZeros = 0; + m_data.resize(m_outerIndex[m_outerSize]); +} + +} // end namespace Eigen + +#endif // EIGEN_SPARSEMATRIX_H diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseMatrixBase.h b/extern/Eigen3/Eigen/src/SparseCore/SparseMatrixBase.h similarity index 52% rename from extern/Eigen3/Eigen/src/Sparse/SparseMatrixBase.h rename to extern/Eigen3/Eigen/src/SparseCore/SparseMatrixBase.h index c01981bc935..9a1258097fe 100644 --- a/extern/Eigen3/Eigen/src/Sparse/SparseMatrixBase.h +++ b/extern/Eigen3/Eigen/src/SparseCore/SparseMatrixBase.h @@ -1,31 +1,18 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2008-2009 Gael Guennebaud +// Copyright (C) 2008-2011 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SPARSEMATRIXBASE_H #define EIGEN_SPARSEMATRIXBASE_H -/** \ingroup Sparse_Module +namespace Eigen { + +/** \ingroup SparseCore_Module * * \class SparseMatrixBase * @@ -44,6 +31,9 @@ template class SparseMatrixBase : public EigenBase typedef typename internal::packet_traits::type PacketScalar; typedef typename internal::traits::StorageKind StorageKind; typedef typename internal::traits::Index Index; + typedef typename internal::add_const_on_value_type_if_arithmetic< + typename internal::packet_traits::type + >::type PacketReturnType; typedef SparseMatrixBase StorageBaseType; typedef EigenBase Base; @@ -54,8 +44,6 @@ template class SparseMatrixBase : public EigenBase other.derived().evalTo(derived()); return derived(); } - -// using Base::operator=; enum { @@ -107,15 +95,6 @@ template class SparseMatrixBase : public EigenBase #endif }; - /* \internal the return type of MatrixBase::conjugate() */ -// typedef typename internal::conditional::IsComplex, -// const SparseCwiseUnaryOp, Derived>, -// const Derived& -// >::type ConjugateReturnType; - /* \internal the return type of MatrixBase::real() */ -// typedef SparseCwiseUnaryOp, Derived> RealReturnType; - /* \internal the return type of MatrixBase::imag() */ -// typedef SparseCwiseUnaryOp, Derived> ImagReturnType; /** \internal the return type of MatrixBase::adjoint() */ typedef typename internal::conditional::IsComplex, CwiseUnaryOp, Eigen::Transpose >, @@ -125,16 +104,6 @@ template class SparseMatrixBase : public EigenBase typedef SparseMatrix PlainObject; -#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::SparseMatrixBase -# include "../plugins/CommonCwiseUnaryOps.h" -# include "../plugins/CommonCwiseBinaryOps.h" -# include "../plugins/MatrixCwiseUnaryOps.h" -# include "../plugins/MatrixCwiseBinaryOps.h" -# ifdef EIGEN_SPARSEMATRIXBASE_PLUGIN -# include EIGEN_SPARSEMATRIXBASE_PLUGIN -# endif -# undef EIGEN_CURRENT_STORAGE_BASE_CLASS -#undef EIGEN_CURRENT_STORAGE_BASE_CLASS #ifndef EIGEN_PARSED_BY_DOXYGEN /** This is the "real scalar" type; if the \a Scalar type is already real numbers @@ -162,12 +131,24 @@ template class SparseMatrixBase : public EigenBase { return *static_cast(const_cast(this)); } #endif // not EIGEN_PARSED_BY_DOXYGEN - /** \returns the number of rows. \sa cols(), RowsAtCompileTime */ +#define EIGEN_CURRENT_STORAGE_BASE_CLASS Eigen::SparseMatrixBase +# include "../plugins/CommonCwiseUnaryOps.h" +# include "../plugins/CommonCwiseBinaryOps.h" +# include "../plugins/MatrixCwiseUnaryOps.h" +# include "../plugins/MatrixCwiseBinaryOps.h" +# ifdef EIGEN_SPARSEMATRIXBASE_PLUGIN +# include EIGEN_SPARSEMATRIXBASE_PLUGIN +# endif +# undef EIGEN_CURRENT_STORAGE_BASE_CLASS +#undef EIGEN_CURRENT_STORAGE_BASE_CLASS + + + /** \returns the number of rows. \sa cols() */ inline Index rows() const { return derived().rows(); } - /** \returns the number of columns. \sa rows(), ColsAtCompileTime*/ + /** \returns the number of columns. \sa rows() */ inline Index cols() const { return derived().cols(); } /** \returns the number of coefficients, which is \a rows()*cols(). - * \sa rows(), cols(), SizeAtCompileTime. */ + * \sa rows(), cols(). */ inline Index size() const { return rows() * cols(); } /** \returns the number of nonzero coefficients which is in practice the number * of stored coefficients. */ @@ -188,16 +169,7 @@ template class SparseMatrixBase : public EigenBase Derived& markAsRValue() { m_isRValue = true; return derived(); } SparseMatrixBase() : m_isRValue(false) { /* TODO check flags */ } - - inline Derived& operator=(const Derived& other) - { -// std::cout << "Derived& operator=(const Derived& other)\n"; -// if (other.isRValue()) -// derived().swap(other.const_cast_derived()); -// else - this->operator=(other); - return derived(); - } + template Derived& operator=(const ReturnByValue& other) @@ -207,10 +179,54 @@ template class SparseMatrixBase : public EigenBase } + template + inline Derived& operator=(const SparseMatrixBase& other) + { + return assign(other.derived()); + } + + inline Derived& operator=(const Derived& other) + { +// if (other.isRValue()) +// derived().swap(other.const_cast_derived()); +// else + return assign(other.derived()); + } + + protected: + + template + inline Derived& assign(const OtherDerived& other) + { + const bool transpose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit); + const Index outerSize = (int(OtherDerived::Flags) & RowMajorBit) ? other.rows() : other.cols(); + if ((!transpose) && other.isRValue()) + { + // eval without temporary + derived().resize(other.rows(), other.cols()); + derived().setZero(); + derived().reserve((std::max)(this->rows(),this->cols())*2); + for (Index j=0; j inline void assignGeneric(const OtherDerived& other) { -// std::cout << "Derived& operator=(const MatrixBase& other)\n"; //const bool transpose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit); eigen_assert(( ((internal::traits::SupportedAccessPatterns&OuterRandomAccessPattern)==OuterRandomAccessPattern) || (!((Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit)))) && @@ -230,8 +246,7 @@ template class SparseMatrixBase : public EigenBase for (typename OtherDerived::InnerIterator it(other.derived(), j); it; ++it) { Scalar v = it.value(); - if (v!=Scalar(0)) - temp.insertBackByOuterInner(Flip?it.index():j,Flip?j:it.index()) = v; + temp.insertBackByOuterInner(Flip?it.index():j,Flip?j:it.index()) = v; } } temp.finalize(); @@ -239,54 +254,23 @@ template class SparseMatrixBase : public EigenBase derived() = temp.markAsRValue(); } - - template - inline Derived& operator=(const SparseMatrixBase& other) - { -// std::cout << typeid(OtherDerived).name() << "\n"; -// std::cout << Flags << " " << OtherDerived::Flags << "\n"; - const bool transpose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit); -// std::cout << "eval transpose = " << transpose << "\n"; - const Index outerSize = (int(OtherDerived::Flags) & RowMajorBit) ? other.rows() : other.cols(); - if ((!transpose) && other.isRValue()) - { - // eval without temporary - derived().resize(other.rows(), other.cols()); - derived().setZero(); - derived().reserve((std::max)(this->rows(),this->cols())*2); - for (Index j=0; j inline Derived& operator=(const SparseSparseProduct& product); - template - inline void _experimentalNewProduct(const Lhs& lhs, const Rhs& rhs); - friend std::ostream & operator << (std::ostream & s, const SparseMatrixBase& m) { + typedef typename Derived::Nested Nested; + typedef typename internal::remove_all::type NestedCleaned; + if (Flags&RowMajorBit) { - for (Index row=0; row class SparseMatrixBase : public EigenBase } else { + const Nested nm(m.derived()); if (m.cols() == 1) { Index row = 0; - for (typename Derived::InnerIterator it(m.derived(), 0); it; ++it) + for (typename NestedCleaned::InnerIterator it(nm.derived(), 0); it; ++it) { for ( ; row class SparseMatrixBase : public EigenBase } else { - SparseMatrix trans = m.derived(); - s << trans; + SparseMatrix trans = m; + s << static_cast >&>(trans); } } return s; } -// const SparseCwiseUnaryOp::Scalar>,Derived> operator-() const; - -// template -// const CwiseBinaryOp::Scalar>, Derived, OtherDerived> -// operator+(const SparseMatrixBase &other) const; - -// template -// const CwiseBinaryOp::Scalar>, Derived, OtherDerived> -// operator-(const SparseMatrixBase &other) const; - template Derived& operator+=(const SparseMatrixBase& other); template Derived& operator-=(const SparseMatrixBase& other); -// template -// Derived& operator+=(const Flagged, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit>& other); - Derived& operator*=(const Scalar& other); Derived& operator/=(const Scalar& other); @@ -358,16 +330,6 @@ template class SparseMatrixBase : public EigenBase EIGEN_STRONG_INLINE const EIGEN_SPARSE_CWISE_PRODUCT_RETURN_TYPE cwiseProduct(const MatrixBase &other) const; -// const SparseCwiseUnaryOp::Scalar>, Derived> -// operator*(const Scalar& scalar) const; -// const SparseCwiseUnaryOp::Scalar>, Derived> -// operator/(const Scalar& scalar) const; - -// inline friend const SparseCwiseUnaryOp::Scalar>, Derived> -// operator*(const Scalar& scalar, const SparseMatrixBase& matrix) -// { return matrix*scalar; } - - // sparse * sparse template const typename SparseSparseProductReturnType::Type @@ -394,6 +356,12 @@ template class SparseMatrixBase : public EigenBase template const typename SparseDenseProductReturnType::Type operator*(const MatrixBase &other) const; + + /** \returns an expression of P H P^-1 where H is the matrix represented by \c *this */ + SparseSymmetricPermutationProduct twistedBy(const PermutationMatrix& perm) const + { + return SparseSymmetricPermutationProduct(derived(), perm); + } template Derived& operator*=(const SparseMatrixBase& other); @@ -407,8 +375,6 @@ template class SparseMatrixBase : public EigenBase // deprecated template void solveTriangularInPlace(MatrixBase& other) const; -// template -// void solveTriangularInPlace(SparseMatrixBase& other) const; #endif // EIGEN2_SUPPORT template @@ -421,12 +387,9 @@ template class SparseMatrixBase : public EigenBase template Scalar dot(const SparseMatrixBase& other) const; RealScalar squaredNorm() const; RealScalar norm() const; -// const PlainObject normalized() const; -// void normalize(); Transpose transpose() { return derived(); } const Transpose transpose() const { return derived(); } - // void transposeInPlace(); const AdjointReturnType adjoint() const { return transpose(); } // sub-vector @@ -442,77 +405,14 @@ template class SparseMatrixBase : public EigenBase const SparseInnerVectorSet subrows(Index start, Index size) const; SparseInnerVectorSet subcols(Index start, Index size); const SparseInnerVectorSet subcols(Index start, Index size) const; + + SparseInnerVectorSet middleRows(Index start, Index size); + const SparseInnerVectorSet middleRows(Index start, Index size) const; + SparseInnerVectorSet middleCols(Index start, Index size); + const SparseInnerVectorSet middleCols(Index start, Index size) const; SparseInnerVectorSet innerVectors(Index outerStart, Index outerSize); const SparseInnerVectorSet innerVectors(Index outerStart, Index outerSize) const; -// typename BlockReturnType::Type block(int startRow, int startCol, int blockRows, int blockCols); -// const typename BlockReturnType::Type -// block(int startRow, int startCol, int blockRows, int blockCols) const; -// -// typename BlockReturnType::SubVectorType segment(int start, int size); -// const typename BlockReturnType::SubVectorType segment(int start, int size) const; -// -// typename BlockReturnType::SubVectorType start(int size); -// const typename BlockReturnType::SubVectorType start(int size) const; -// -// typename BlockReturnType::SubVectorType end(int size); -// const typename BlockReturnType::SubVectorType end(int size) const; -// -// template -// typename BlockReturnType::Type block(int startRow, int startCol); -// template -// const typename BlockReturnType::Type block(int startRow, int startCol) const; - -// template typename BlockReturnType::SubVectorType start(void); -// template const typename BlockReturnType::SubVectorType start() const; - -// template typename BlockReturnType::SubVectorType end(); -// template const typename BlockReturnType::SubVectorType end() const; - -// template typename BlockReturnType::SubVectorType segment(int start); -// template const typename BlockReturnType::SubVectorType segment(int start) const; - -// Diagonal diagonal(); -// const Diagonal diagonal() const; - -// template Part part(); -// template const Part part() const; - - -// static const ConstantReturnType Constant(int rows, int cols, const Scalar& value); -// static const ConstantReturnType Constant(int size, const Scalar& value); -// static const ConstantReturnType Constant(const Scalar& value); - -// template -// static const CwiseNullaryOp NullaryExpr(int rows, int cols, const CustomNullaryOp& func); -// template -// static const CwiseNullaryOp NullaryExpr(int size, const CustomNullaryOp& func); -// template -// static const CwiseNullaryOp NullaryExpr(const CustomNullaryOp& func); - -// static const ConstantReturnType Zero(int rows, int cols); -// static const ConstantReturnType Zero(int size); -// static const ConstantReturnType Zero(); -// static const ConstantReturnType Ones(int rows, int cols); -// static const ConstantReturnType Ones(int size); -// static const ConstantReturnType Ones(); -// static const IdentityReturnType Identity(); -// static const IdentityReturnType Identity(int rows, int cols); -// static const BasisReturnType Unit(int size, int i); -// static const BasisReturnType Unit(int i); -// static const BasisReturnType UnitX(); -// static const BasisReturnType UnitY(); -// static const BasisReturnType UnitZ(); -// static const BasisReturnType UnitW(); - -// const DiagonalMatrix asDiagonal() const; - -// Derived& setConstant(const Scalar& value); -// Derived& setZero(); -// Derived& setOnes(); -// Derived& setRandom(); -// Derived& setIdentity(); - /** \internal use operator= */ template void evalTo(MatrixBase& dst) const @@ -537,37 +437,6 @@ template class SparseMatrixBase : public EigenBase bool isApprox(const MatrixBase& other, RealScalar prec = NumTraits::dummy_precision()) const { return toDense().isApprox(other,prec); } -// bool isMuchSmallerThan(const RealScalar& other, -// RealScalar prec = NumTraits::dummy_precision()) const; -// template -// bool isMuchSmallerThan(const MatrixBase& other, -// RealScalar prec = NumTraits::dummy_precision()) const; - -// bool isApproxToConstant(const Scalar& value, RealScalar prec = NumTraits::dummy_precision()) const; -// bool isZero(RealScalar prec = NumTraits::dummy_precision()) const; -// bool isOnes(RealScalar prec = NumTraits::dummy_precision()) const; -// bool isIdentity(RealScalar prec = NumTraits::dummy_precision()) const; -// bool isDiagonal(RealScalar prec = NumTraits::dummy_precision()) const; - -// bool isUpper(RealScalar prec = NumTraits::dummy_precision()) const; -// bool isLower(RealScalar prec = NumTraits::dummy_precision()) const; - -// template -// bool isOrthogonal(const MatrixBase& other, -// RealScalar prec = NumTraits::dummy_precision()) const; -// bool isUnitary(RealScalar prec = NumTraits::dummy_precision()) const; - -// template -// inline bool operator==(const MatrixBase& other) const -// { return (cwise() == other).all(); } - -// template -// inline bool operator!=(const MatrixBase& other) const -// { return (cwise() != other).any(); } - - -// template -// const SparseCwiseUnaryOp::Scalar, NewType>, Derived> cast() const; /** \returns the matrix or vector obtained by evaluating this expression. * @@ -577,130 +446,13 @@ template class SparseMatrixBase : public EigenBase inline const typename internal::eval::type eval() const { return typename internal::eval::type(derived()); } -// template -// void swap(MatrixBase const & other); - -// template -// const SparseFlagged marked() const; -// const Flagged lazy() const; - - /** \returns number of elements to skip to pass from one row (resp. column) to another - * for a row-major (resp. column-major) matrix. - * Combined with coeffRef() and the \ref flags flags, it allows a direct access to the data - * of the underlying matrix. - */ -// inline int stride(void) const { return derived().stride(); } - -// FIXME -// ConjugateReturnType conjugate() const; -// const RealReturnType real() const; -// const ImagReturnType imag() const; - -// template -// const SparseCwiseUnaryOp unaryExpr(const CustomUnaryOp& func = CustomUnaryOp()) const; - -// template -// const CwiseBinaryOp -// binaryExpr(const MatrixBase &other, const CustomBinaryOp& func = CustomBinaryOp()) const; - - Scalar sum() const; -// Scalar trace() const; - -// typename internal::traits::Scalar minCoeff() const; -// typename internal::traits::Scalar maxCoeff() const; - -// typename internal::traits::Scalar minCoeff(int* row, int* col = 0) const; -// typename internal::traits::Scalar maxCoeff(int* row, int* col = 0) const; - -// template -// typename internal::result_of::Scalar)>::type -// redux(const BinaryOp& func) const; - -// template -// void visit(Visitor& func) const; - - -// const SparseCwise cwise() const; -// SparseCwise cwise(); - -// inline const WithFormat format(const IOFormat& fmt) const; - -/////////// Array module /////////// - /* - bool all(void) const; - bool any(void) const; - - const VectorwiseOp rowwise() const; - const VectorwiseOp colwise() const; - - static const CwiseNullaryOp,Derived> Random(int rows, int cols); - static const CwiseNullaryOp,Derived> Random(int size); - static const CwiseNullaryOp,Derived> Random(); - - template - const Select - select(const MatrixBase& thenMatrix, - const MatrixBase& elseMatrix) const; - - template - inline const Select - select(const MatrixBase& thenMatrix, typename ThenDerived::Scalar elseScalar) const; - - template - inline const Select - select(typename ElseDerived::Scalar thenScalar, const MatrixBase& elseMatrix) const; - - template RealScalar lpNorm() const; - */ - - -// template -// Scalar dot(const MatrixBase& other) const -// { -// EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) -// EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherDerived) -// EIGEN_STATIC_ASSERT((internal::is_same::value), -// YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY) -// -// eigen_assert(derived().size() == other.size()); -// // short version, but the assembly looks more complicated because -// // of the CwiseBinaryOp iterator complexity -// // return res = (derived().cwise() * other.derived().conjugate()).sum(); -// -// // optimized, generic version -// typename Derived::InnerIterator i(derived(),0); -// typename OtherDerived::InnerIterator j(other.derived(),0); -// Scalar res = 0; -// while (i && j) -// { -// if (i.index()==j.index()) -// { -// // std::cerr << i.value() << " * " << j.value() << "\n"; -// res += i.value() * internal::conj(j.value()); -// ++i; ++j; -// } -// else if (i.index() +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SPARSE_PERMUTATION_H +#define EIGEN_SPARSE_PERMUTATION_H + +// This file implements sparse * permutation products + +namespace Eigen { + +namespace internal { + +template +struct traits > +{ + typedef typename remove_all::type MatrixTypeNestedCleaned; + typedef typename MatrixTypeNestedCleaned::Scalar Scalar; + typedef typename MatrixTypeNestedCleaned::Index Index; + enum { + SrcStorageOrder = MatrixTypeNestedCleaned::Flags&RowMajorBit ? RowMajor : ColMajor, + MoveOuter = SrcStorageOrder==RowMajor ? Side==OnTheLeft : Side==OnTheRight + }; + + typedef typename internal::conditional, + SparseMatrix >::type ReturnType; +}; + +template +struct permut_sparsematrix_product_retval + : public ReturnByValue > +{ + typedef typename remove_all::type MatrixTypeNestedCleaned; + typedef typename MatrixTypeNestedCleaned::Scalar Scalar; + typedef typename MatrixTypeNestedCleaned::Index Index; + + enum { + SrcStorageOrder = MatrixTypeNestedCleaned::Flags&RowMajorBit ? RowMajor : ColMajor, + MoveOuter = SrcStorageOrder==RowMajor ? Side==OnTheLeft : Side==OnTheRight + }; + + permut_sparsematrix_product_retval(const PermutationType& perm, const MatrixType& matrix) + : m_permutation(perm), m_matrix(matrix) + {} + + inline int rows() const { return m_matrix.rows(); } + inline int cols() const { return m_matrix.cols(); } + + template inline void evalTo(Dest& dst) const + { + if(MoveOuter) + { + SparseMatrix tmp(m_matrix.rows(), m_matrix.cols()); + VectorXi sizes(m_matrix.outerSize()); + for(Index j=0; j tmp(m_matrix.rows(), m_matrix.cols()); + VectorXi sizes(tmp.outerSize()); + sizes.setZero(); + PermutationMatrix perm; + if((Side==OnTheLeft) ^ Transposed) + perm = m_permutation; + else + perm = m_permutation.transpose(); + + for(Index j=0; j +inline const internal::permut_sparsematrix_product_retval, SparseDerived, OnTheRight, false> +operator*(const SparseMatrixBase& matrix, const PermutationBase& perm) +{ + return internal::permut_sparsematrix_product_retval, SparseDerived, OnTheRight, false>(perm, matrix.derived()); +} + +/** \returns the matrix with the permutation applied to the rows + */ +template +inline const internal::permut_sparsematrix_product_retval, SparseDerived, OnTheLeft, false> +operator*( const PermutationBase& perm, const SparseMatrixBase& matrix) +{ + return internal::permut_sparsematrix_product_retval, SparseDerived, OnTheLeft, false>(perm, matrix.derived()); +} + + + +/** \returns the matrix with the inverse permutation applied to the columns. + */ +template +inline const internal::permut_sparsematrix_product_retval, SparseDerived, OnTheRight, true> +operator*(const SparseMatrixBase& matrix, const Transpose >& tperm) +{ + return internal::permut_sparsematrix_product_retval, SparseDerived, OnTheRight, true>(tperm.nestedPermutation(), matrix.derived()); +} + +/** \returns the matrix with the inverse permutation applied to the rows. + */ +template +inline const internal::permut_sparsematrix_product_retval, SparseDerived, OnTheLeft, true> +operator*(const Transpose >& tperm, const SparseMatrixBase& matrix) +{ + return internal::permut_sparsematrix_product_retval, SparseDerived, OnTheLeft, true>(tperm.nestedPermutation(), matrix.derived()); +} + +} // end namespace Eigen + +#endif // EIGEN_SPARSE_SELFADJOINTVIEW_H diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseProduct.h b/extern/Eigen3/Eigen/src/SparseCore/SparseProduct.h similarity index 62% rename from extern/Eigen3/Eigen/src/Sparse/SparseProduct.h rename to extern/Eigen3/Eigen/src/SparseCore/SparseProduct.h index 1c1f54706ac..6a555b83434 100644 --- a/extern/Eigen3/Eigen/src/Sparse/SparseProduct.h +++ b/extern/Eigen3/Eigen/src/SparseCore/SparseProduct.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008-2010 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SPARSEPRODUCT_H #define EIGEN_SPARSEPRODUCT_H +namespace Eigen { + template struct SparseSparseProductReturnType { @@ -38,11 +25,11 @@ struct SparseSparseProductReturnType typedef typename internal::conditional, - const typename internal::nested::type>::type LhsNested; + typename internal::nested::type>::type LhsNested; typedef typename internal::conditional, - const typename internal::nested::type>::type RhsNested; + typename internal::nested::type>::type RhsNested; typedef SparseSparseProduct Type; }; @@ -106,9 +93,42 @@ class SparseSparseProduct : internal::no_assignment_operator, template EIGEN_STRONG_INLINE SparseSparseProduct(const Lhs& lhs, const Rhs& rhs) - : m_lhs(lhs), m_rhs(rhs) + : m_lhs(lhs), m_rhs(rhs), m_tolerance(0), m_conservative(true) { - eigen_assert(lhs.cols() == rhs.rows()); + init(); + } + + template + EIGEN_STRONG_INLINE SparseSparseProduct(const Lhs& lhs, const Rhs& rhs, RealScalar tolerance) + : m_lhs(lhs), m_rhs(rhs), m_tolerance(tolerance), m_conservative(false) + { + init(); + } + + SparseSparseProduct pruned(Scalar reference = 0, RealScalar epsilon = NumTraits::dummy_precision()) const + { + return SparseSparseProduct(m_lhs,m_rhs,internal::abs(reference)*epsilon); + } + + template + void evalTo(Dest& result) const + { + if(m_conservative) + internal::conservative_sparse_sparse_product_selector<_LhsNested, _RhsNested, Dest>::run(lhs(),rhs(),result); + else + internal::sparse_sparse_product_with_pruning_selector<_LhsNested, _RhsNested, Dest>::run(lhs(),rhs(),result,m_tolerance); + } + + EIGEN_STRONG_INLINE Index rows() const { return m_lhs.rows(); } + EIGEN_STRONG_INLINE Index cols() const { return m_rhs.cols(); } + + EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; } + EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; } + + protected: + void init() + { + eigen_assert(m_lhs.cols() == m_rhs.rows()); enum { ProductIsValid = _LhsNested::ColsAtCompileTime==Dynamic @@ -127,15 +147,40 @@ class SparseSparseProduct : internal::no_assignment_operator, EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT) } - EIGEN_STRONG_INLINE Index rows() const { return m_lhs.rows(); } - EIGEN_STRONG_INLINE Index cols() const { return m_rhs.cols(); } - - EIGEN_STRONG_INLINE const _LhsNested& lhs() const { return m_lhs; } - EIGEN_STRONG_INLINE const _RhsNested& rhs() const { return m_rhs; } - - protected: LhsNested m_lhs; RhsNested m_rhs; + RealScalar m_tolerance; + bool m_conservative; }; +// sparse = sparse * sparse +template +template +inline Derived& SparseMatrixBase::operator=(const SparseSparseProduct& product) +{ + product.evalTo(derived()); + return derived(); +} + +/** \returns an expression of the product of two sparse matrices. + * By default a conservative product preserving the symbolic non zeros is performed. + * The automatic pruning of the small values can be achieved by calling the pruned() function + * in which case a totally different product algorithm is employed: + * \code + * C = (A*B).pruned(); // supress numerical zeros (exact) + * C = (A*B).pruned(ref); + * C = (A*B).pruned(ref,epsilon); + * \endcode + * where \c ref is a meaningful non zero reference value. + * */ +template +template +inline const typename SparseSparseProductReturnType::Type +SparseMatrixBase::operator*(const SparseMatrixBase &other) const +{ + return typename SparseSparseProductReturnType::Type(derived(), other.derived()); +} + +} // end namespace Eigen + #endif // EIGEN_SPARSEPRODUCT_H diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseRedux.h b/extern/Eigen3/Eigen/src/SparseCore/SparseRedux.h similarity index 56% rename from extern/Eigen3/Eigen/src/Sparse/SparseRedux.h rename to extern/Eigen3/Eigen/src/SparseCore/SparseRedux.h index afc49de7aad..f3da93a71d4 100644 --- a/extern/Eigen3/Eigen/src/Sparse/SparseRedux.h +++ b/extern/Eigen3/Eigen/src/SparseCore/SparseRedux.h @@ -3,34 +3,21 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SPARSEREDUX_H #define EIGEN_SPARSEREDUX_H +namespace Eigen { + template typename internal::traits::Scalar SparseMatrixBase::sum() const { eigen_assert(rows()>0 && cols()>0 && "you are using a non initialized matrix"); - Scalar res = 0; + Scalar res(0); for (Index j=0; j::sum() const return Matrix::Map(&m_data.value(0), m_data.size()).sum(); } +} // end namespace Eigen + #endif // EIGEN_SPARSEREDUX_H diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseSelfAdjointView.h b/extern/Eigen3/Eigen/src/SparseCore/SparseSelfAdjointView.h similarity index 75% rename from extern/Eigen3/Eigen/src/Sparse/SparseSelfAdjointView.h rename to extern/Eigen3/Eigen/src/SparseCore/SparseSelfAdjointView.h index d82044c789c..86ec0a6c5e2 100644 --- a/extern/Eigen3/Eigen/src/Sparse/SparseSelfAdjointView.h +++ b/extern/Eigen3/Eigen/src/SparseCore/SparseSelfAdjointView.h @@ -3,30 +3,17 @@ // // Copyright (C) 2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SPARSE_SELFADJOINTVIEW_H #define EIGEN_SPARSE_SELFADJOINTVIEW_H -/** \class SparseSelfAdjointView - * +namespace Eigen { + +/** \ingroup SparseCore_Module + * \class SparseSelfAdjointView * * \brief Pseudo expression to manipulate a triangular sparse matrix as a selfadjoint matrix. * @@ -45,9 +32,6 @@ class SparseSelfAdjointTimeDenseProduct; template class DenseTimeSparseSelfAdjointProduct; -template -class SparseSymmetricPermutationProduct; - namespace internal { template @@ -106,9 +90,6 @@ template class SparseSelfAdjointView * * \returns a reference to \c *this * - * Note that it is faster to set alpha=0 than initializing the matrix to zero - * and then keep the default value alpha=1. - * * To perform \f$ this = this + \alpha ( u^* u ) \f$ you can simply * call this function with u.adjoint(). */ @@ -116,21 +97,21 @@ template class SparseSelfAdjointView SparseSelfAdjointView& rankUpdate(const SparseMatrixBase& u, Scalar alpha = Scalar(1)); /** \internal triggered by sparse_matrix = SparseSelfadjointView; */ - template void evalTo(SparseMatrix& _dest) const + template void evalTo(SparseMatrix& _dest) const { internal::permute_symm_to_fullsymm(m_matrix, _dest); } - template void evalTo(DynamicSparseMatrix& _dest) const + template void evalTo(DynamicSparseMatrix& _dest) const { // TODO directly evaluate into _dest; - SparseMatrix tmp(_dest.rows(),_dest.cols()); + SparseMatrix tmp(_dest.rows(),_dest.cols()); internal::permute_symm_to_fullsymm(m_matrix, tmp); _dest = tmp; } - /** \returns an expression of P^-1 H P */ - SparseSymmetricPermutationProduct<_MatrixTypeNested,UpLo> twistedBy(const PermutationMatrix& perm) const + /** \returns an expression of P H P^-1 */ + SparseSymmetricPermutationProduct<_MatrixTypeNested,UpLo> twistedBy(const PermutationMatrix& perm) const { return SparseSymmetricPermutationProduct<_MatrixTypeNested,UpLo>(m_matrix, perm); } @@ -141,6 +122,20 @@ template class SparseSelfAdjointView permutedMatrix.evalTo(*this); return *this; } + + + SparseSelfAdjointView& operator=(const SparseSelfAdjointView& src) + { + PermutationMatrix pnull; + return *this = src.twistedBy(pnull); + } + + template + SparseSelfAdjointView& operator=(const SparseSelfAdjointView& src) + { + PermutationMatrix pnull; + return *this = src.twistedBy(pnull); + } // const SparseLLT llt() const; @@ -148,7 +143,7 @@ template class SparseSelfAdjointView protected: - const typename MatrixType::Nested m_matrix; + typename MatrixType::Nested m_matrix; mutable VectorI m_countPerRow; mutable VectorI m_countPerCol; }; @@ -230,12 +225,15 @@ class SparseSelfAdjointTimeDenseProduct for (Index j=0; j dest_j(dest.row(LhsIsRowMajor ? j : 0)); for(; (ProcessFirstHalf ? i && i.index() < j : i) ; ++i) { Index a = LhsIsRowMajor ? j : i.index(); @@ -300,7 +298,7 @@ void permute_symm_to_fullsymm(const MatrixType& mat, SparseMatrixj) || (UpLo==Upper && ic) || ( UpLo==Upper && rj) || (UpLo==Upper && ic) || ( (UpLo&Upper)==Upper && r -void permute_symm_to_symm(const MatrixType& mat, SparseMatrix& _dest, const typename MatrixType::Index* perm) +template +void permute_symm_to_symm(const MatrixType& mat, SparseMatrix& _dest, const typename MatrixType::Index* perm) { typedef typename MatrixType::Index Index; typedef typename MatrixType::Scalar Scalar; - typedef SparseMatrix Dest; - Dest& dest(_dest.derived()); + SparseMatrix& dest(_dest.derived()); typedef Matrix VectorI; - //internal::conj_if cj; + enum { + SrcOrder = MatrixType::IsRowMajor ? RowMajor : ColMajor, + StorageOrderMatch = int(SrcOrder) == int(DstOrder), + DstUpLo = DstOrder==RowMajor ? (_DstUpLo==Upper ? Lower : Upper) : _DstUpLo, + SrcUpLo = SrcOrder==RowMajor ? (_SrcUpLo==Upper ? Lower : Upper) : _SrcUpLo + }; Index size = mat.rows(); VectorI count(size); @@ -379,37 +397,40 @@ void permute_symm_to_symm(const MatrixType& mat, SparseMatrixj)) + if((int(SrcUpLo)==int(Lower) && ij)) continue; Index ip = perm ? perm[i] : i; - count[DstUpLo==Lower ? (std::min)(ip,jp) : (std::max)(ip,jp)]++; + count[int(DstUpLo)==int(Lower) ? (std::min)(ip,jp) : (std::max)(ip,jp)]++; } } - dest._outerIndexPtr()[0] = 0; + dest.outerIndexPtr()[0] = 0; for(Index j=0; jj)) + if((int(SrcUpLo)==int(Lower) && ij)) continue; + Index jp = perm ? perm[j] : j; Index ip = perm? perm[i] : i; - Index k = count[DstUpLo==Lower ? (std::min)(ip,jp) : (std::max)(ip,jp)]++; - dest._innerIndexPtr()[k] = DstUpLo==Lower ? (std::max)(ip,jp) : (std::min)(ip,jp); - if((DstUpLo==Lower && ipjp)) - dest._valuePtr()[k] = conj(it.value()); + Index k = count[int(DstUpLo)==int(Lower) ? (std::min)(ip,jp) : (std::max)(ip,jp)]++; + dest.innerIndexPtr()[k] = int(DstUpLo)==int(Lower) ? (std::max)(ip,jp) : (std::min)(ip,jp); + + if(!StorageOrderMatch) std::swap(ip,jp); + if( ((int(DstUpLo)==int(Lower) && ipjp))) + dest.valuePtr()[k] = conj(it.value()); else - dest._valuePtr()[k] = it.value(); + dest.valuePtr()[k] = it.value(); } } } @@ -420,10 +441,12 @@ template class SparseSymmetricPermutationProduct : public EigenBase > { - typedef PermutationMatrix Perm; public: typedef typename MatrixType::Scalar Scalar; typedef typename MatrixType::Index Index; + protected: + typedef PermutationMatrix Perm; + public: typedef Matrix VectorI; typedef typename MatrixType::Nested MatrixTypeNested; typedef typename internal::remove_all::type _MatrixTypeNested; @@ -435,7 +458,8 @@ class SparseSymmetricPermutationProduct inline Index rows() const { return m_matrix.rows(); } inline Index cols() const { return m_matrix.cols(); } - template void evalTo(SparseMatrix& _dest) const + template + void evalTo(SparseMatrix& _dest) const { internal::permute_symm_to_fullsymm(m_matrix,_dest,m_perm.indices().data()); } @@ -446,9 +470,11 @@ class SparseSymmetricPermutationProduct } protected: - const MatrixTypeNested m_matrix; + MatrixTypeNested m_matrix; const Perm& m_perm; }; +} // end namespace Eigen + #endif // EIGEN_SPARSE_SELFADJOINTVIEW_H diff --git a/extern/Eigen3/Eigen/src/SparseCore/SparseSparseProductWithPruning.h b/extern/Eigen3/Eigen/src/SparseCore/SparseSparseProductWithPruning.h new file mode 100644 index 00000000000..2438ac573d0 --- /dev/null +++ b/extern/Eigen3/Eigen/src/SparseCore/SparseSparseProductWithPruning.h @@ -0,0 +1,149 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2011 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SPARSESPARSEPRODUCTWITHPRUNING_H +#define EIGEN_SPARSESPARSEPRODUCTWITHPRUNING_H + +namespace Eigen { + +namespace internal { + + +// perform a pseudo in-place sparse * sparse product assuming all matrices are col major +template +static void sparse_sparse_product_with_pruning_impl(const Lhs& lhs, const Rhs& rhs, ResultType& res, typename ResultType::RealScalar tolerance) +{ + // return sparse_sparse_product_with_pruning_impl2(lhs,rhs,res); + + typedef typename remove_all::type::Scalar Scalar; + typedef typename remove_all::type::Index Index; + + // make sure to call innerSize/outerSize since we fake the storage order. + Index rows = lhs.innerSize(); + Index cols = rhs.outerSize(); + //int size = lhs.outerSize(); + eigen_assert(lhs.outerSize() == rhs.innerSize()); + + // allocate a temporary buffer + AmbiVector tempVector(rows); + + // estimate the number of non zero entries + // given a rhs column containing Y non zeros, we assume that the respective Y columns + // of the lhs differs in average of one non zeros, thus the number of non zeros for + // the product of a rhs column with the lhs is X+Y where X is the average number of non zero + // per column of the lhs. + // Therefore, we have nnz(lhs*rhs) = nnz(lhs) + nnz(rhs) + Index estimated_nnz_prod = lhs.nonZeros() + rhs.nonZeros(); + + // mimics a resizeByInnerOuter: + if(ResultType::IsRowMajor) + res.resize(cols, rows); + else + res.resize(rows, cols); + + res.reserve(estimated_nnz_prod); + double ratioColRes = double(estimated_nnz_prod)/double(lhs.rows()*rhs.cols()); + for (Index j=0; j::Iterator it(tempVector,tolerance); it; ++it) + res.insertBackByOuterInner(j,it.index()) = it.value(); + } + res.finalize(); +} + +template::Flags&RowMajorBit, + int RhsStorageOrder = traits::Flags&RowMajorBit, + int ResStorageOrder = traits::Flags&RowMajorBit> +struct sparse_sparse_product_with_pruning_selector; + +template +struct sparse_sparse_product_with_pruning_selector +{ + typedef typename traits::type>::Scalar Scalar; + typedef typename ResultType::RealScalar RealScalar; + + static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, RealScalar tolerance) + { + typename remove_all::type _res(res.rows(), res.cols()); + internal::sparse_sparse_product_with_pruning_impl(lhs, rhs, _res, tolerance); + res.swap(_res); + } +}; + +template +struct sparse_sparse_product_with_pruning_selector +{ + typedef typename ResultType::RealScalar RealScalar; + static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, RealScalar tolerance) + { + // we need a col-major matrix to hold the result + typedef SparseMatrix SparseTemporaryType; + SparseTemporaryType _res(res.rows(), res.cols()); + internal::sparse_sparse_product_with_pruning_impl(lhs, rhs, _res, tolerance); + res = _res; + } +}; + +template +struct sparse_sparse_product_with_pruning_selector +{ + typedef typename ResultType::RealScalar RealScalar; + static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, RealScalar tolerance) + { + // let's transpose the product to get a column x column product + typename remove_all::type _res(res.rows(), res.cols()); + internal::sparse_sparse_product_with_pruning_impl(rhs, lhs, _res, tolerance); + res.swap(_res); + } +}; + +template +struct sparse_sparse_product_with_pruning_selector +{ + typedef typename ResultType::RealScalar RealScalar; + static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res, RealScalar tolerance) + { + typedef SparseMatrix ColMajorMatrix; + ColMajorMatrix colLhs(lhs); + ColMajorMatrix colRhs(rhs); + internal::sparse_sparse_product_with_pruning_impl(colLhs, colRhs, res, tolerance); + + // let's transpose the product to get a column x column product +// typedef SparseMatrix SparseTemporaryType; +// SparseTemporaryType _res(res.cols(), res.rows()); +// sparse_sparse_product_with_pruning_impl(rhs, lhs, _res); +// res = _res.transpose(); + } +}; + +// NOTE the 2 others cases (col row *) must never occur since they are caught +// by ProductReturnType which transforms it to (col col *) by evaluating rhs. + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_SPARSESPARSEPRODUCTWITHPRUNING_H diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseTranspose.h b/extern/Eigen3/Eigen/src/SparseCore/SparseTranspose.h similarity index 53% rename from extern/Eigen3/Eigen/src/Sparse/SparseTranspose.h rename to extern/Eigen3/Eigen/src/SparseCore/SparseTranspose.h index 2aea2fa32c7..273f9de688f 100644 --- a/extern/Eigen3/Eigen/src/Sparse/SparseTranspose.h +++ b/extern/Eigen3/Eigen/src/SparseCore/SparseTranspose.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008-2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SPARSETRANSPOSE_H #define EIGEN_SPARSETRANSPOSE_H +namespace Eigen { + template class TransposeImpl : public SparseMatrixBase > { @@ -39,17 +26,21 @@ template class TransposeImpl inline Index nonZeros() const { return derived().nestedExpression().nonZeros(); } }; +// NOTE: VC10 trigger an ICE if don't put typename TransposeImpl:: in front of Index, +// a typedef typename TransposeImpl::Index Index; +// does not fix the issue. +// An alternative is to define the nested class in the parent class itself. template class TransposeImpl::InnerIterator : public _MatrixTypeNested::InnerIterator { typedef typename _MatrixTypeNested::InnerIterator Base; public: - EIGEN_STRONG_INLINE InnerIterator(const TransposeImpl& trans, Index outer) + EIGEN_STRONG_INLINE InnerIterator(const TransposeImpl& trans, typename TransposeImpl::Index outer) : Base(trans.derived().nestedExpression(), outer) {} - inline Index row() const { return Base::col(); } - inline Index col() const { return Base::row(); } + inline typename TransposeImpl::Index row() const { return Base::col(); } + inline typename TransposeImpl::Index col() const { return Base::row(); } }; template class TransposeImpl::ReverseInnerIterator @@ -58,11 +49,13 @@ template class TransposeImpl::ReverseInn typedef typename _MatrixTypeNested::ReverseInnerIterator Base; public: - EIGEN_STRONG_INLINE ReverseInnerIterator(const TransposeImpl& xpr, Index outer) + EIGEN_STRONG_INLINE ReverseInnerIterator(const TransposeImpl& xpr, typename TransposeImpl::Index outer) : Base(xpr.derived().nestedExpression(), outer) {} - inline Index row() const { return Base::col(); } - inline Index col() const { return Base::row(); } + inline typename TransposeImpl::Index row() const { return Base::col(); } + inline typename TransposeImpl::Index col() const { return Base::row(); } }; +} // end namespace Eigen + #endif // EIGEN_SPARSETRANSPOSE_H diff --git a/extern/Eigen3/Eigen/src/SparseCore/SparseTriangularView.h b/extern/Eigen3/Eigen/src/SparseCore/SparseTriangularView.h new file mode 100644 index 00000000000..477e4bd94b0 --- /dev/null +++ b/extern/Eigen3/Eigen/src/SparseCore/SparseTriangularView.h @@ -0,0 +1,164 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SPARSE_TRIANGULARVIEW_H +#define EIGEN_SPARSE_TRIANGULARVIEW_H + +namespace Eigen { + +namespace internal { + +template +struct traits > +: public traits +{}; + +} // namespace internal + +template class SparseTriangularView + : public SparseMatrixBase > +{ + enum { SkipFirst = ((Mode&Lower) && !(MatrixType::Flags&RowMajorBit)) + || ((Mode&Upper) && (MatrixType::Flags&RowMajorBit)), + SkipLast = !SkipFirst, + HasUnitDiag = (Mode&UnitDiag) ? 1 : 0 + }; + + public: + + EIGEN_SPARSE_PUBLIC_INTERFACE(SparseTriangularView) + + class InnerIterator; + class ReverseInnerIterator; + + inline Index rows() const { return m_matrix.rows(); } + inline Index cols() const { return m_matrix.cols(); } + + typedef typename MatrixType::Nested MatrixTypeNested; + typedef typename internal::remove_reference::type MatrixTypeNestedNonRef; + typedef typename internal::remove_all::type MatrixTypeNestedCleaned; + + inline SparseTriangularView(const MatrixType& matrix) : m_matrix(matrix) {} + + /** \internal */ + inline const MatrixTypeNestedCleaned& nestedExpression() const { return m_matrix; } + + template + typename internal::plain_matrix_type_column_major::type + solve(const MatrixBase& other) const; + + template void solveInPlace(MatrixBase& other) const; + template void solveInPlace(SparseMatrixBase& other) const; + + protected: + MatrixTypeNested m_matrix; +}; + +template +class SparseTriangularView::InnerIterator : public MatrixTypeNestedCleaned::InnerIterator +{ + typedef typename MatrixTypeNestedCleaned::InnerIterator Base; + public: + + EIGEN_STRONG_INLINE InnerIterator(const SparseTriangularView& view, Index outer) + : Base(view.nestedExpression(), outer), m_returnOne(false) + { + if(SkipFirst) + { + while((*this) && (HasUnitDiag ? this->index()<=outer : this->index()=Base::outer())) + { + if((!SkipFirst) && Base::operator bool()) + Base::operator++(); + m_returnOne = true; + } + } + + EIGEN_STRONG_INLINE InnerIterator& operator++() + { + if(HasUnitDiag && m_returnOne) + m_returnOne = false; + else + { + Base::operator++(); + if(HasUnitDiag && (!SkipFirst) && ((!Base::operator bool()) || Base::index()>=Base::outer())) + { + if((!SkipFirst) && Base::operator bool()) + Base::operator++(); + m_returnOne = true; + } + } + return *this; + } + + inline Index row() const { return Base::row(); } + inline Index col() const { return Base::col(); } + inline Index index() const + { + if(HasUnitDiag && m_returnOne) return Base::outer(); + else return Base::index(); + } + inline Scalar value() const + { + if(HasUnitDiag && m_returnOne) return Scalar(1); + else return Base::value(); + } + + EIGEN_STRONG_INLINE operator bool() const + { + if(HasUnitDiag && m_returnOne) + return true; + return (SkipFirst ? Base::operator bool() : (Base::operator bool() && this->index() <= this->outer())); + } + protected: + bool m_returnOne; +}; + +template +class SparseTriangularView::ReverseInnerIterator : public MatrixTypeNestedCleaned::ReverseInnerIterator +{ + typedef typename MatrixTypeNestedCleaned::ReverseInnerIterator Base; + public: + + EIGEN_STRONG_INLINE ReverseInnerIterator(const SparseTriangularView& view, Index outer) + : Base(view.nestedExpression(), outer) + { + eigen_assert((!HasUnitDiag) && "ReverseInnerIterator does not support yet triangular views with a unit diagonal"); + if(SkipLast) + while((*this) && this->index()>outer) + --(*this); + } + + EIGEN_STRONG_INLINE InnerIterator& operator--() + { Base::operator--(); return *this; } + + inline Index row() const { return Base::row(); } + inline Index col() const { return Base::col(); } + + EIGEN_STRONG_INLINE operator bool() const + { + return SkipLast ? Base::operator bool() : (Base::operator bool() && this->index() >= this->outer()); + } +}; + +template +template +inline const SparseTriangularView +SparseMatrixBase::triangularView() const +{ + return derived(); +} + +} // end namespace Eigen + +#endif // EIGEN_SPARSE_TRIANGULARVIEW_H diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseUtil.h b/extern/Eigen3/Eigen/src/SparseCore/SparseUtil.h similarity index 60% rename from extern/Eigen3/Eigen/src/Sparse/SparseUtil.h rename to extern/Eigen3/Eigen/src/SparseCore/SparseUtil.h index db9ae98e7a0..6062a086ff7 100644 --- a/extern/Eigen3/Eigen/src/Sparse/SparseUtil.h +++ b/extern/Eigen3/Eigen/src/SparseCore/SparseUtil.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SPARSEUTIL_H #define EIGEN_SPARSEUTIL_H +namespace Eigen { + #ifdef NDEBUG #define EIGEN_DBG_SPARSE(X) #else @@ -58,22 +45,22 @@ EIGEN_SPARSE_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Derived, /=) #define _EIGEN_SPARSE_PUBLIC_INTERFACE(Derived, BaseClass) \ typedef BaseClass Base; \ - typedef typename Eigen::internal::traits::Scalar Scalar; \ + typedef typename Eigen::internal::traits::Scalar Scalar; \ typedef typename Eigen::NumTraits::Real RealScalar; \ - typedef typename Eigen::internal::nested::type Nested; \ - typedef typename Eigen::internal::traits::StorageKind StorageKind; \ - typedef typename Eigen::internal::traits::Index Index; \ - enum { RowsAtCompileTime = Eigen::internal::traits::RowsAtCompileTime, \ - ColsAtCompileTime = Eigen::internal::traits::ColsAtCompileTime, \ - Flags = Eigen::internal::traits::Flags, \ - CoeffReadCost = Eigen::internal::traits::CoeffReadCost, \ + typedef typename Eigen::internal::nested::type Nested; \ + typedef typename Eigen::internal::traits::StorageKind StorageKind; \ + typedef typename Eigen::internal::traits::Index Index; \ + enum { RowsAtCompileTime = Eigen::internal::traits::RowsAtCompileTime, \ + ColsAtCompileTime = Eigen::internal::traits::ColsAtCompileTime, \ + Flags = Eigen::internal::traits::Flags, \ + CoeffReadCost = Eigen::internal::traits::CoeffReadCost, \ SizeAtCompileTime = Base::SizeAtCompileTime, \ IsVectorAtCompileTime = Base::IsVectorAtCompileTime }; \ using Base::derived; \ using Base::const_cast_derived; #define EIGEN_SPARSE_PUBLIC_INTERFACE(Derived) \ - _EIGEN_SPARSE_PUBLIC_INTERFACE(Derived, Eigen::SparseMatrixBase) + _EIGEN_SPARSE_PUBLIC_INTERFACE(Derived, Eigen::SparseMatrixBase) const int CoherentAccessPattern = 0x1; const int InnerRandomAccessPattern = 0x2 | CoherentAccessPattern; @@ -100,20 +87,43 @@ template class SparseDenseOuterProdu template struct SparseSparseProductReturnType; template::ColsAtCompileTime> struct DenseSparseProductReturnType; template::ColsAtCompileTime> struct SparseDenseProductReturnType; +template class SparseSymmetricPermutationProduct; namespace internal { -template struct eval -{ - typedef typename traits::Scalar _Scalar; - enum { - _Flags = traits::Flags - }; +template struct sparse_eval; +template struct eval + : public sparse_eval::RowsAtCompileTime,traits::ColsAtCompileTime> +{}; + +template struct sparse_eval { + typedef typename traits::Scalar _Scalar; + enum { _Flags = traits::Flags| RowMajorBit }; + public: + typedef SparseVector<_Scalar, _Flags> type; +}; + +template struct sparse_eval { + typedef typename traits::Scalar _Scalar; + enum { _Flags = traits::Flags & (~RowMajorBit) }; + public: + typedef SparseVector<_Scalar, _Flags> type; +}; + +template struct sparse_eval { + typedef typename traits::Scalar _Scalar; + enum { _Flags = traits::Flags }; public: typedef SparseMatrix<_Scalar, _Flags> type; }; +template struct sparse_eval { + typedef typename traits::Scalar _Scalar; + public: + typedef Matrix<_Scalar, 1, 1> type; +}; + template struct plain_matrix_type { typedef typename traits::Scalar _Scalar; @@ -127,4 +137,37 @@ template struct plain_matrix_type } // end namespace internal +/** \ingroup SparseCore_Module + * + * \class Triplet + * + * \brief A small structure to hold a non zero as a triplet (i,j,value). + * + * \sa SparseMatrix::setFromTriplets() + */ +template +class Triplet +{ +public: + Triplet() : m_row(0), m_col(0), m_value(0) {} + + Triplet(const Index& i, const Index& j, const Scalar& v = Scalar(0)) + : m_row(i), m_col(j), m_value(v) + {} + + /** \returns the row index of the element */ + const Index& row() const { return m_row; } + + /** \returns the column index of the element */ + const Index& col() const { return m_col; } + + /** \returns the value of the element */ + const Scalar& value() const { return m_value; } +protected: + Index m_row, m_col; + Scalar m_value; +}; + +} // end namespace Eigen + #endif // EIGEN_SPARSEUTIL_H diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseVector.h b/extern/Eigen3/Eigen/src/SparseCore/SparseVector.h similarity index 63% rename from extern/Eigen3/Eigen/src/Sparse/SparseVector.h rename to extern/Eigen3/Eigen/src/SparseCore/SparseVector.h index ce4bb51a27e..c952f654038 100644 --- a/extern/Eigen3/Eigen/src/Sparse/SparseVector.h +++ b/extern/Eigen3/Eigen/src/SparseCore/SparseVector.h @@ -3,29 +3,17 @@ // // Copyright (C) 2008-2009 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SPARSEVECTOR_H #define EIGEN_SPARSEVECTOR_H -/** \class SparseVector +namespace Eigen { + +/** \ingroup SparseCore_Module + * \class SparseVector * * \brief a sparse vector class * @@ -46,13 +34,13 @@ struct traits > typedef Sparse StorageKind; typedef MatrixXpr XprKind; enum { - IsColVector = _Options & RowMajorBit ? 0 : 1, + IsColVector = (_Options & RowMajorBit) ? 0 : 1, RowsAtCompileTime = IsColVector ? Dynamic : 1, ColsAtCompileTime = IsColVector ? 1 : Dynamic, MaxRowsAtCompileTime = RowsAtCompileTime, MaxColsAtCompileTime = ColsAtCompileTime, - Flags = _Options | NestByRefBit | LvalueBit, + Flags = _Options | NestByRefBit | LvalueBit | (IsColVector ? 0 : RowMajorBit), CoeffReadCost = NumTraits::ReadCost, SupportedAccessPatterns = InnerRandomAccessPattern }; @@ -67,7 +55,6 @@ class SparseVector EIGEN_SPARSE_PUBLIC_INTERFACE(SparseVector) EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, +=) EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, -=) -// EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, =) protected: public: @@ -79,11 +66,11 @@ class SparseVector Options = _Options }; - CompressedStorage m_data; + internal::CompressedStorage m_data; Index m_size; - CompressedStorage& _data() { return m_data; } - CompressedStorage& _data() const { return m_data; } + internal::CompressedStorage& _data() { return m_data; } + internal::CompressedStorage& _data() const { return m_data; } public: @@ -91,13 +78,12 @@ class SparseVector EIGEN_STRONG_INLINE Index cols() const { return IsColVector ? 1 : m_size; } EIGEN_STRONG_INLINE Index innerSize() const { return m_size; } EIGEN_STRONG_INLINE Index outerSize() const { return 1; } - EIGEN_STRONG_INLINE Index innerNonZeros(Index j) const { eigen_assert(j==0); return m_size; } - EIGEN_STRONG_INLINE const Scalar* _valuePtr() const { return &m_data.value(0); } - EIGEN_STRONG_INLINE Scalar* _valuePtr() { return &m_data.value(0); } + EIGEN_STRONG_INLINE const Scalar* valuePtr() const { return &m_data.value(0); } + EIGEN_STRONG_INLINE Scalar* valuePtr() { return &m_data.value(0); } - EIGEN_STRONG_INLINE const Index* _innerIndexPtr() const { return &m_data.index(0); } - EIGEN_STRONG_INLINE Index* _innerIndexPtr() { return &m_data.index(0); } + EIGEN_STRONG_INLINE const Index* innerIndexPtr() const { return &m_data.index(0); } + EIGEN_STRONG_INLINE Index* innerIndexPtr() { return &m_data.index(0); } inline Scalar coeff(Index row, Index col) const { @@ -126,6 +112,7 @@ class SparseVector public: class InnerIterator; + class ReverseInnerIterator; inline void setZero() { m_data.clear(); } @@ -134,11 +121,13 @@ class SparseVector inline void startVec(Index outer) { + EIGEN_UNUSED_VARIABLE(outer); eigen_assert(outer==0); } inline Scalar& insertBackByOuterInner(Index outer, Index inner) { + EIGEN_UNUSED_VARIABLE(outer); eigen_assert(outer==0); return insertBack(inner); } @@ -158,7 +147,7 @@ class SparseVector Scalar& insert(Index i) { Index startId = 0; - Index p = m_data.size() - 1; + Index p = Index(m_data.size()) - 1; // TODO smart realloc m_data.resize(p+2,1); @@ -205,13 +194,6 @@ class SparseVector inline SparseVector(Index rows, Index cols) : m_size(0) { resize(rows,cols); } - template - inline SparseVector(const MatrixBase& other) - : m_size(0) - { - *this = other.derived(); - } - template inline SparseVector(const SparseMatrixBase& other) : m_size(0) @@ -249,9 +231,9 @@ class SparseVector inline SparseVector& operator=(const SparseMatrixBase& other) { if (int(RowsAtCompileTime)!=int(OtherDerived::RowsAtCompileTime)) - return Base::operator=(other.transpose()); + return assign(other.transpose()); else - return Base::operator=(other); + return assign(other); } #ifndef EIGEN_PARSED_BY_DOXYGEN @@ -262,56 +244,6 @@ class SparseVector } #endif -// const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit); -// if (needToTranspose) -// { -// // two passes algorithm: -// // 1 - compute the number of coeffs per dest inner vector -// // 2 - do the actual copy/eval -// // Since each coeff of the rhs has to be evaluated twice, let's evauluate it if needed -// typedef typename internal::nested::type OtherCopy; -// OtherCopy otherCopy(other.derived()); -// typedef typename internal::remove_all::type _OtherCopy; -// -// resize(other.rows(), other.cols()); -// Eigen::Map(m_outerIndex,outerSize()).setZero(); -// // pass 1 -// // FIXME the above copy could be merged with that pass -// for (int j=0; j::operator=(other.derived()); -// } -// } - friend std::ostream & operator << (std::ostream & s, const SparseVector& m) { for (Index i=0; i + EIGEN_DONT_INLINE SparseVector& assign(const SparseMatrixBase& _other) + { + const OtherDerived& other(_other.derived()); + const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit); + if(needToTranspose) + { + Index size = other.size(); + Index nnz = other.nonZeros(); + resize(size); + reserve(nnz); + for(Index i=0; i @@ -399,18 +336,14 @@ class SparseVector::InnerIterator InnerIterator(const SparseVector& vec, Index outer=0) : m_data(vec.m_data), m_id(0), m_end(static_cast(m_data.size())) { + EIGEN_UNUSED_VARIABLE(outer); eigen_assert(outer==0); } - InnerIterator(const CompressedStorage& data) + InnerIterator(const internal::CompressedStorage& data) : m_data(data), m_id(0), m_end(static_cast(m_data.size())) {} - template - InnerIterator(const Flagged& vec, Index ) - : m_data(vec._expression().m_data), m_id(0), m_end(m_data.size()) - {} - inline InnerIterator& operator++() { m_id++; return *this; } inline Scalar value() const { return m_data.value(m_id); } @@ -423,9 +356,43 @@ class SparseVector::InnerIterator inline operator bool() const { return (m_id < m_end); } protected: - const CompressedStorage& m_data; + const internal::CompressedStorage& m_data; Index m_id; const Index m_end; }; +template +class SparseVector::ReverseInnerIterator +{ + public: + ReverseInnerIterator(const SparseVector& vec, Index outer=0) + : m_data(vec.m_data), m_id(static_cast(m_data.size())), m_start(0) + { + EIGEN_UNUSED_VARIABLE(outer); + eigen_assert(outer==0); + } + + ReverseInnerIterator(const internal::CompressedStorage& data) + : m_data(data), m_id(static_cast(m_data.size())), m_start(0) + {} + + inline ReverseInnerIterator& operator--() { m_id--; return *this; } + + inline Scalar value() const { return m_data.value(m_id-1); } + inline Scalar& valueRef() { return const_cast(m_data.value(m_id-1)); } + + inline Index index() const { return m_data.index(m_id-1); } + inline Index row() const { return IsColVector ? index() : 0; } + inline Index col() const { return IsColVector ? 0 : index(); } + + inline operator bool() const { return (m_id > m_start); } + + protected: + const internal::CompressedStorage& m_data; + Index m_id; + const Index m_start; +}; + +} // end namespace Eigen + #endif // EIGEN_SPARSEVECTOR_H diff --git a/extern/Eigen3/Eigen/src/Sparse/SparseView.h b/extern/Eigen3/Eigen/src/SparseCore/SparseView.h similarity index 64% rename from extern/Eigen3/Eigen/src/Sparse/SparseView.h rename to extern/Eigen3/Eigen/src/SparseCore/SparseView.h index 24306561098..8b0b9ea0304 100644 --- a/extern/Eigen3/Eigen/src/Sparse/SparseView.h +++ b/extern/Eigen3/Eigen/src/SparseCore/SparseView.h @@ -1,31 +1,18 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2010 Gael Guennebaud +// Copyright (C) 2011 Gael Guennebaud // Copyright (C) 2010 Daniel Lowengrub // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SPARSEVIEW_H #define EIGEN_SPARSEVIEW_H +namespace Eigen { + namespace internal { template @@ -61,7 +48,7 @@ public: inline Index outerSize() const { return m_matrix.outerSize(); } protected: - const MatrixTypeNested m_matrix; + MatrixTypeNested m_matrix; Scalar m_reference; typename NumTraits::Real m_epsilon; }; @@ -92,10 +79,10 @@ protected: private: void incrementToNonZero() { - while(internal::isMuchSmallerThan(value(), m_view.m_reference, m_view.m_epsilon) && (bool(*this))) - { - IterBase::operator++(); - } + while((bool(*this)) && internal::isMuchSmallerThan(value(), m_view.m_reference, m_view.m_epsilon)) + { + IterBase::operator++(); + } } }; @@ -106,4 +93,6 @@ const SparseView MatrixBase::sparseView(const Scalar& m_refere return SparseView(derived(), m_reference, m_epsilon); } +} // end namespace Eigen + #endif diff --git a/extern/Eigen3/Eigen/src/Sparse/TriangularSolver.h b/extern/Eigen3/Eigen/src/SparseCore/TriangularSolver.h similarity index 83% rename from extern/Eigen3/Eigen/src/Sparse/TriangularSolver.h rename to extern/Eigen3/Eigen/src/SparseCore/TriangularSolver.h index 62bb8bb44c9..cb8ad82b4f6 100644 --- a/extern/Eigen3/Eigen/src/Sparse/TriangularSolver.h +++ b/extern/Eigen3/Eigen/src/SparseCore/TriangularSolver.h @@ -3,28 +3,15 @@ // // Copyright (C) 2008 Gael Guennebaud // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SPARSETRIANGULARSOLVER_H #define EIGEN_SPARSETRIANGULARSOLVER_H +namespace Eigen { + namespace internal { template for(int i=0; i for(int i=lhs.rows()-1 ; i>=0 ; --i) { Scalar tmp = other.coeff(i,col); + Scalar l_ii = 0; typename Lhs::InnerIterator it(lhs, i); - if (it && it.index() == i) + while(it && it.index() if (Mode & UnitDiag) other.coeffRef(i,col) = tmp; else - { - typename Lhs::InnerIterator it(lhs, i); - eigen_assert(it && it.index() == i); - other.coeffRef(i,col) = tmp/it.value(); - } + other.coeffRef(i,col) = tmp/l_ii; } } } @@ -118,9 +110,11 @@ struct sparse_solve_triangular_selector if (tmp!=Scalar(0)) // optimization when other is actually sparse { typename Lhs::InnerIterator it(lhs, i); + while(it && it.index() { if(!(Mode & UnitDiag)) { - // FIXME lhs.coeff(i,i) might not be always efficient while it must simply be the - // last element of the column ! - other.coeffRef(i,col) /= lhs.innerVector(i).lastCoeff(); + // TODO replace this by a binary search. make sure the binary search is safe for partially sorted elements + typename Lhs::ReverseInnerIterator it(lhs, i); + while(it && it.index()!=i) + --it; + eigen_assert(it && it.index()==i); + other.coeffRef(i,col) /= it.value(); } typename Lhs::InnerIterator it(lhs, i); for(; it && it.index() template void SparseTriangularView::solveInPlace(MatrixBase& other) const { - eigen_assert(m_matrix.cols() == m_matrix.rows()); - eigen_assert(m_matrix.cols() == other.rows()); - eigen_assert(!(Mode & ZeroDiag)); - eigen_assert((Mode & (Upper|Lower)) != 0); + eigen_assert(m_matrix.cols() == m_matrix.rows() && m_matrix.cols() == other.rows()); + eigen_assert((!(Mode & ZeroDiag)) && bool(Mode & (Upper|Lower))); enum { copy = internal::traits::Flags & RowMajorBit }; @@ -295,10 +290,8 @@ template template void SparseTriangularView::solveInPlace(SparseMatrixBase& other) const { - eigen_assert(m_matrix.cols() == m_matrix.rows()); - eigen_assert(m_matrix.cols() == other.rows()); - eigen_assert(!(Mode & ZeroDiag)); - eigen_assert((Mode & (Upper|Lower)) != 0); + eigen_assert(m_matrix.cols() == m_matrix.rows() && m_matrix.cols() == other.rows()); + eigen_assert( (!(Mode & ZeroDiag)) && bool(Mode & (Upper|Lower))); // enum { copy = internal::traits::Flags & RowMajorBit }; @@ -336,4 +329,6 @@ SparseMatrixBase::solveTriangular(const MatrixBase& other } #endif // EIGEN2_SUPPORT +} // end namespace Eigen + #endif // EIGEN_SPARSETRIANGULARSOLVER_H diff --git a/extern/Eigen3/Eigen/src/StlSupport/StdDeque.h b/extern/Eigen3/Eigen/src/StlSupport/StdDeque.h index 6f12c106dbc..4ee8e5c10a5 100644 --- a/extern/Eigen3/Eigen/src/StlSupport/StdDeque.h +++ b/extern/Eigen3/Eigen/src/StlSupport/StdDeque.h @@ -4,24 +4,9 @@ // Copyright (C) 2009 Gael Guennebaud // Copyright (C) 2009 Hauke Heibel // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_STDDEQUE_H #define EIGEN_STDDEQUE_H diff --git a/extern/Eigen3/Eigen/src/StlSupport/StdList.h b/extern/Eigen3/Eigen/src/StlSupport/StdList.h index d329a0b2dc5..627381ecec0 100644 --- a/extern/Eigen3/Eigen/src/StlSupport/StdList.h +++ b/extern/Eigen3/Eigen/src/StlSupport/StdList.h @@ -3,24 +3,9 @@ // // Copyright (C) 2009 Hauke Heibel // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_STDLIST_H #define EIGEN_STDLIST_H diff --git a/extern/Eigen3/Eigen/src/StlSupport/StdVector.h b/extern/Eigen3/Eigen/src/StlSupport/StdVector.h index 27d6ab539f9..40a9abefa82 100644 --- a/extern/Eigen3/Eigen/src/StlSupport/StdVector.h +++ b/extern/Eigen3/Eigen/src/StlSupport/StdVector.h @@ -4,24 +4,9 @@ // Copyright (C) 2009 Gael Guennebaud // Copyright (C) 2009 Hauke Heibel // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_STDVECTOR_H #define EIGEN_STDVECTOR_H diff --git a/extern/Eigen3/Eigen/src/StlSupport/details.h b/extern/Eigen3/Eigen/src/StlSupport/details.h index 397c8ef8581..d8debc7c4f8 100644 --- a/extern/Eigen3/Eigen/src/StlSupport/details.h +++ b/extern/Eigen3/Eigen/src/StlSupport/details.h @@ -4,24 +4,9 @@ // Copyright (C) 2009 Gael Guennebaud // Copyright (C) 2009 Hauke Heibel // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_STL_DETAILS_H #define EIGEN_STL_DETAILS_H diff --git a/extern/Eigen3/Eigen/src/SuperLUSupport/SuperLUSupport.h b/extern/Eigen3/Eigen/src/SuperLUSupport/SuperLUSupport.h new file mode 100644 index 00000000000..11fb014dd93 --- /dev/null +++ b/extern/Eigen3/Eigen/src/SuperLUSupport/SuperLUSupport.h @@ -0,0 +1,1025 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2011 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SUPERLUSUPPORT_H +#define EIGEN_SUPERLUSUPPORT_H + +namespace Eigen { + +#define DECL_GSSVX(PREFIX,FLOATTYPE,KEYTYPE) \ + extern "C" { \ + typedef struct { FLOATTYPE for_lu; FLOATTYPE total_needed; int expansions; } PREFIX##mem_usage_t; \ + extern void PREFIX##gssvx(superlu_options_t *, SuperMatrix *, int *, int *, int *, \ + char *, FLOATTYPE *, FLOATTYPE *, SuperMatrix *, SuperMatrix *, \ + void *, int, SuperMatrix *, SuperMatrix *, \ + FLOATTYPE *, FLOATTYPE *, FLOATTYPE *, FLOATTYPE *, \ + PREFIX##mem_usage_t *, SuperLUStat_t *, int *); \ + } \ + inline float SuperLU_gssvx(superlu_options_t *options, SuperMatrix *A, \ + int *perm_c, int *perm_r, int *etree, char *equed, \ + FLOATTYPE *R, FLOATTYPE *C, SuperMatrix *L, \ + SuperMatrix *U, void *work, int lwork, \ + SuperMatrix *B, SuperMatrix *X, \ + FLOATTYPE *recip_pivot_growth, \ + FLOATTYPE *rcond, FLOATTYPE *ferr, FLOATTYPE *berr, \ + SuperLUStat_t *stats, int *info, KEYTYPE) { \ + PREFIX##mem_usage_t mem_usage; \ + PREFIX##gssvx(options, A, perm_c, perm_r, etree, equed, R, C, L, \ + U, work, lwork, B, X, recip_pivot_growth, rcond, \ + ferr, berr, &mem_usage, stats, info); \ + return mem_usage.for_lu; /* bytes used by the factor storage */ \ + } + +DECL_GSSVX(s,float,float) +DECL_GSSVX(c,float,std::complex) +DECL_GSSVX(d,double,double) +DECL_GSSVX(z,double,std::complex) + +#ifdef MILU_ALPHA +#define EIGEN_SUPERLU_HAS_ILU +#endif + +#ifdef EIGEN_SUPERLU_HAS_ILU + +// similarly for the incomplete factorization using gsisx +#define DECL_GSISX(PREFIX,FLOATTYPE,KEYTYPE) \ + extern "C" { \ + extern void PREFIX##gsisx(superlu_options_t *, SuperMatrix *, int *, int *, int *, \ + char *, FLOATTYPE *, FLOATTYPE *, SuperMatrix *, SuperMatrix *, \ + void *, int, SuperMatrix *, SuperMatrix *, FLOATTYPE *, FLOATTYPE *, \ + PREFIX##mem_usage_t *, SuperLUStat_t *, int *); \ + } \ + inline float SuperLU_gsisx(superlu_options_t *options, SuperMatrix *A, \ + int *perm_c, int *perm_r, int *etree, char *equed, \ + FLOATTYPE *R, FLOATTYPE *C, SuperMatrix *L, \ + SuperMatrix *U, void *work, int lwork, \ + SuperMatrix *B, SuperMatrix *X, \ + FLOATTYPE *recip_pivot_growth, \ + FLOATTYPE *rcond, \ + SuperLUStat_t *stats, int *info, KEYTYPE) { \ + PREFIX##mem_usage_t mem_usage; \ + PREFIX##gsisx(options, A, perm_c, perm_r, etree, equed, R, C, L, \ + U, work, lwork, B, X, recip_pivot_growth, rcond, \ + &mem_usage, stats, info); \ + return mem_usage.for_lu; /* bytes used by the factor storage */ \ + } + +DECL_GSISX(s,float,float) +DECL_GSISX(c,float,std::complex) +DECL_GSISX(d,double,double) +DECL_GSISX(z,double,std::complex) + +#endif + +template +struct SluMatrixMapHelper; + +/** \internal + * + * A wrapper class for SuperLU matrices. It supports only compressed sparse matrices + * and dense matrices. Supernodal and other fancy format are not supported by this wrapper. + * + * This wrapper class mainly aims to avoids the need of dynamic allocation of the storage structure. + */ +struct SluMatrix : SuperMatrix +{ + SluMatrix() + { + Store = &storage; + } + + SluMatrix(const SluMatrix& other) + : SuperMatrix(other) + { + Store = &storage; + storage = other.storage; + } + + SluMatrix& operator=(const SluMatrix& other) + { + SuperMatrix::operator=(static_cast(other)); + Store = &storage; + storage = other.storage; + return *this; + } + + struct + { + union {int nnz;int lda;}; + void *values; + int *innerInd; + int *outerInd; + } storage; + + void setStorageType(Stype_t t) + { + Stype = t; + if (t==SLU_NC || t==SLU_NR || t==SLU_DN) + Store = &storage; + else + { + eigen_assert(false && "storage type not supported"); + Store = 0; + } + } + + template + void setScalarType() + { + if (internal::is_same::value) + Dtype = SLU_S; + else if (internal::is_same::value) + Dtype = SLU_D; + else if (internal::is_same >::value) + Dtype = SLU_C; + else if (internal::is_same >::value) + Dtype = SLU_Z; + else + { + eigen_assert(false && "Scalar type not supported by SuperLU"); + } + } + + template + static SluMatrix Map(MatrixBase& _mat) + { + MatrixType& mat(_mat.derived()); + eigen_assert( ((MatrixType::Flags&RowMajorBit)!=RowMajorBit) && "row-major dense matrices are not supported by SuperLU"); + SluMatrix res; + res.setStorageType(SLU_DN); + res.setScalarType(); + res.Mtype = SLU_GE; + + res.nrow = mat.rows(); + res.ncol = mat.cols(); + + res.storage.lda = MatrixType::IsVectorAtCompileTime ? mat.size() : mat.outerStride(); + res.storage.values = mat.data(); + return res; + } + + template + static SluMatrix Map(SparseMatrixBase& mat) + { + SluMatrix res; + if ((MatrixType::Flags&RowMajorBit)==RowMajorBit) + { + res.setStorageType(SLU_NR); + res.nrow = mat.cols(); + res.ncol = mat.rows(); + } + else + { + res.setStorageType(SLU_NC); + res.nrow = mat.rows(); + res.ncol = mat.cols(); + } + + res.Mtype = SLU_GE; + + res.storage.nnz = mat.nonZeros(); + res.storage.values = mat.derived().valuePtr(); + res.storage.innerInd = mat.derived().innerIndexPtr(); + res.storage.outerInd = mat.derived().outerIndexPtr(); + + res.setScalarType(); + + // FIXME the following is not very accurate + if (MatrixType::Flags & Upper) + res.Mtype = SLU_TRU; + if (MatrixType::Flags & Lower) + res.Mtype = SLU_TRL; + + eigen_assert(((MatrixType::Flags & SelfAdjoint)==0) && "SelfAdjoint matrix shape not supported by SuperLU"); + + return res; + } +}; + +template +struct SluMatrixMapHelper > +{ + typedef Matrix MatrixType; + static void run(MatrixType& mat, SluMatrix& res) + { + eigen_assert( ((Options&RowMajor)!=RowMajor) && "row-major dense matrices is not supported by SuperLU"); + res.setStorageType(SLU_DN); + res.setScalarType(); + res.Mtype = SLU_GE; + + res.nrow = mat.rows(); + res.ncol = mat.cols(); + + res.storage.lda = mat.outerStride(); + res.storage.values = mat.data(); + } +}; + +template +struct SluMatrixMapHelper > +{ + typedef Derived MatrixType; + static void run(MatrixType& mat, SluMatrix& res) + { + if ((MatrixType::Flags&RowMajorBit)==RowMajorBit) + { + res.setStorageType(SLU_NR); + res.nrow = mat.cols(); + res.ncol = mat.rows(); + } + else + { + res.setStorageType(SLU_NC); + res.nrow = mat.rows(); + res.ncol = mat.cols(); + } + + res.Mtype = SLU_GE; + + res.storage.nnz = mat.nonZeros(); + res.storage.values = mat.valuePtr(); + res.storage.innerInd = mat.innerIndexPtr(); + res.storage.outerInd = mat.outerIndexPtr(); + + res.setScalarType(); + + // FIXME the following is not very accurate + if (MatrixType::Flags & Upper) + res.Mtype = SLU_TRU; + if (MatrixType::Flags & Lower) + res.Mtype = SLU_TRL; + + eigen_assert(((MatrixType::Flags & SelfAdjoint)==0) && "SelfAdjoint matrix shape not supported by SuperLU"); + } +}; + +namespace internal { + +template +SluMatrix asSluMatrix(MatrixType& mat) +{ + return SluMatrix::Map(mat); +} + +/** View a Super LU matrix as an Eigen expression */ +template +MappedSparseMatrix map_superlu(SluMatrix& sluMat) +{ + eigen_assert((Flags&RowMajor)==RowMajor && sluMat.Stype == SLU_NR + || (Flags&ColMajor)==ColMajor && sluMat.Stype == SLU_NC); + + Index outerSize = (Flags&RowMajor)==RowMajor ? sluMat.ncol : sluMat.nrow; + + return MappedSparseMatrix( + sluMat.nrow, sluMat.ncol, sluMat.storage.outerInd[outerSize], + sluMat.storage.outerInd, sluMat.storage.innerInd, reinterpret_cast(sluMat.storage.values) ); +} + +} // end namespace internal + +/** \ingroup SuperLUSupport_Module + * \class SuperLUBase + * \brief The base class for the direct and incomplete LU factorization of SuperLU + */ +template +class SuperLUBase : internal::noncopyable +{ + public: + typedef _MatrixType MatrixType; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef typename MatrixType::Index Index; + typedef Matrix Vector; + typedef Matrix IntRowVectorType; + typedef Matrix IntColVectorType; + typedef SparseMatrix LUMatrixType; + + public: + + SuperLUBase() {} + + ~SuperLUBase() + { + clearFactors(); + } + + Derived& derived() { return *static_cast(this); } + const Derived& derived() const { return *static_cast(this); } + + inline Index rows() const { return m_matrix.rows(); } + inline Index cols() const { return m_matrix.cols(); } + + /** \returns a reference to the Super LU option object to configure the Super LU algorithms. */ + inline superlu_options_t& options() { return m_sluOptions; } + + /** \brief Reports whether previous computation was successful. + * + * \returns \c Success if computation was succesful, + * \c NumericalIssue if the matrix.appears to be negative. + */ + ComputationInfo info() const + { + eigen_assert(m_isInitialized && "Decomposition is not initialized."); + return m_info; + } + + /** Computes the sparse Cholesky decomposition of \a matrix */ + void compute(const MatrixType& matrix) + { + derived().analyzePattern(matrix); + derived().factorize(matrix); + } + + /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. + * + * \sa compute() + */ + template + inline const internal::solve_retval solve(const MatrixBase& b) const + { + eigen_assert(m_isInitialized && "SuperLU is not initialized."); + eigen_assert(rows()==b.rows() + && "SuperLU::solve(): invalid number of rows of the right hand side matrix b"); + return internal::solve_retval(*this, b.derived()); + } + + /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. + * + * \sa compute() + */ +// template +// inline const internal::sparse_solve_retval solve(const SparseMatrixBase& b) const +// { +// eigen_assert(m_isInitialized && "SuperLU is not initialized."); +// eigen_assert(rows()==b.rows() +// && "SuperLU::solve(): invalid number of rows of the right hand side matrix b"); +// return internal::sparse_solve_retval(*this, b.derived()); +// } + + /** Performs a symbolic decomposition on the sparcity of \a matrix. + * + * This function is particularly useful when solving for several problems having the same structure. + * + * \sa factorize() + */ + void analyzePattern(const MatrixType& /*matrix*/) + { + m_isInitialized = true; + m_info = Success; + m_analysisIsOk = true; + m_factorizationIsOk = false; + } + + template + void dumpMemory(Stream& s) + {} + + protected: + + void initFactorization(const MatrixType& a) + { + set_default_options(&this->m_sluOptions); + + const int size = a.rows(); + m_matrix = a; + + m_sluA = internal::asSluMatrix(m_matrix); + clearFactors(); + + m_p.resize(size); + m_q.resize(size); + m_sluRscale.resize(size); + m_sluCscale.resize(size); + m_sluEtree.resize(size); + + // set empty B and X + m_sluB.setStorageType(SLU_DN); + m_sluB.setScalarType(); + m_sluB.Mtype = SLU_GE; + m_sluB.storage.values = 0; + m_sluB.nrow = 0; + m_sluB.ncol = 0; + m_sluB.storage.lda = size; + m_sluX = m_sluB; + + m_extractedDataAreDirty = true; + } + + void init() + { + m_info = InvalidInput; + m_isInitialized = false; + m_sluL.Store = 0; + m_sluU.Store = 0; + } + + void extractData() const; + + void clearFactors() + { + if(m_sluL.Store) + Destroy_SuperNode_Matrix(&m_sluL); + if(m_sluU.Store) + Destroy_CompCol_Matrix(&m_sluU); + + m_sluL.Store = 0; + m_sluU.Store = 0; + + memset(&m_sluL,0,sizeof m_sluL); + memset(&m_sluU,0,sizeof m_sluU); + } + + // cached data to reduce reallocation, etc. + mutable LUMatrixType m_l; + mutable LUMatrixType m_u; + mutable IntColVectorType m_p; + mutable IntRowVectorType m_q; + + mutable LUMatrixType m_matrix; // copy of the factorized matrix + mutable SluMatrix m_sluA; + mutable SuperMatrix m_sluL, m_sluU; + mutable SluMatrix m_sluB, m_sluX; + mutable SuperLUStat_t m_sluStat; + mutable superlu_options_t m_sluOptions; + mutable std::vector m_sluEtree; + mutable Matrix m_sluRscale, m_sluCscale; + mutable Matrix m_sluFerr, m_sluBerr; + mutable char m_sluEqued; + + mutable ComputationInfo m_info; + bool m_isInitialized; + int m_factorizationIsOk; + int m_analysisIsOk; + mutable bool m_extractedDataAreDirty; + + private: + SuperLUBase(SuperLUBase& ) { } +}; + + +/** \ingroup SuperLUSupport_Module + * \class SuperLU + * \brief A sparse direct LU factorization and solver based on the SuperLU library + * + * This class allows to solve for A.X = B sparse linear problems via a direct LU factorization + * using the SuperLU library. The sparse matrix A must be squared and invertible. The vectors or matrices + * X and B can be either dense or sparse. + * + * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> + * + * \sa \ref TutorialSparseDirectSolvers + */ +template +class SuperLU : public SuperLUBase<_MatrixType,SuperLU<_MatrixType> > +{ + public: + typedef SuperLUBase<_MatrixType,SuperLU> Base; + typedef _MatrixType MatrixType; + typedef typename Base::Scalar Scalar; + typedef typename Base::RealScalar RealScalar; + typedef typename Base::Index Index; + typedef typename Base::IntRowVectorType IntRowVectorType; + typedef typename Base::IntColVectorType IntColVectorType; + typedef typename Base::LUMatrixType LUMatrixType; + typedef TriangularView LMatrixType; + typedef TriangularView UMatrixType; + + public: + + SuperLU() : Base() { init(); } + + SuperLU(const MatrixType& matrix) : Base() + { + Base::init(); + compute(matrix); + } + + ~SuperLU() + { + } + + /** Performs a symbolic decomposition on the sparcity of \a matrix. + * + * This function is particularly useful when solving for several problems having the same structure. + * + * \sa factorize() + */ + void analyzePattern(const MatrixType& matrix) + { + m_info = InvalidInput; + m_isInitialized = false; + Base::analyzePattern(matrix); + } + + /** Performs a numeric decomposition of \a matrix + * + * The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed. + * + * \sa analyzePattern() + */ + void factorize(const MatrixType& matrix); + + #ifndef EIGEN_PARSED_BY_DOXYGEN + /** \internal */ + template + void _solve(const MatrixBase &b, MatrixBase &dest) const; + #endif // EIGEN_PARSED_BY_DOXYGEN + + inline const LMatrixType& matrixL() const + { + if (m_extractedDataAreDirty) this->extractData(); + return m_l; + } + + inline const UMatrixType& matrixU() const + { + if (m_extractedDataAreDirty) this->extractData(); + return m_u; + } + + inline const IntColVectorType& permutationP() const + { + if (m_extractedDataAreDirty) this->extractData(); + return m_p; + } + + inline const IntRowVectorType& permutationQ() const + { + if (m_extractedDataAreDirty) this->extractData(); + return m_q; + } + + Scalar determinant() const; + + protected: + + using Base::m_matrix; + using Base::m_sluOptions; + using Base::m_sluA; + using Base::m_sluB; + using Base::m_sluX; + using Base::m_p; + using Base::m_q; + using Base::m_sluEtree; + using Base::m_sluEqued; + using Base::m_sluRscale; + using Base::m_sluCscale; + using Base::m_sluL; + using Base::m_sluU; + using Base::m_sluStat; + using Base::m_sluFerr; + using Base::m_sluBerr; + using Base::m_l; + using Base::m_u; + + using Base::m_analysisIsOk; + using Base::m_factorizationIsOk; + using Base::m_extractedDataAreDirty; + using Base::m_isInitialized; + using Base::m_info; + + void init() + { + Base::init(); + + set_default_options(&this->m_sluOptions); + m_sluOptions.PrintStat = NO; + m_sluOptions.ConditionNumber = NO; + m_sluOptions.Trans = NOTRANS; + m_sluOptions.ColPerm = COLAMD; + } + + + private: + SuperLU(SuperLU& ) { } +}; + +template +void SuperLU::factorize(const MatrixType& a) +{ + eigen_assert(m_analysisIsOk && "You must first call analyzePattern()"); + if(!m_analysisIsOk) + { + m_info = InvalidInput; + return; + } + + this->initFactorization(a); + + int info = 0; + RealScalar recip_pivot_growth, rcond; + RealScalar ferr, berr; + + StatInit(&m_sluStat); + SuperLU_gssvx(&m_sluOptions, &m_sluA, m_q.data(), m_p.data(), &m_sluEtree[0], + &m_sluEqued, &m_sluRscale[0], &m_sluCscale[0], + &m_sluL, &m_sluU, + NULL, 0, + &m_sluB, &m_sluX, + &recip_pivot_growth, &rcond, + &ferr, &berr, + &m_sluStat, &info, Scalar()); + StatFree(&m_sluStat); + + m_extractedDataAreDirty = true; + + // FIXME how to better check for errors ??? + m_info = info == 0 ? Success : NumericalIssue; + m_factorizationIsOk = true; +} + +template +template +void SuperLU::_solve(const MatrixBase &b, MatrixBase& x) const +{ + eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or analyzePattern()/factorize()"); + + const int size = m_matrix.rows(); + const int rhsCols = b.cols(); + eigen_assert(size==b.rows()); + + m_sluOptions.Trans = NOTRANS; + m_sluOptions.Fact = FACTORED; + m_sluOptions.IterRefine = NOREFINE; + + + m_sluFerr.resize(rhsCols); + m_sluBerr.resize(rhsCols); + m_sluB = SluMatrix::Map(b.const_cast_derived()); + m_sluX = SluMatrix::Map(x.derived()); + + typename Rhs::PlainObject b_cpy; + if(m_sluEqued!='N') + { + b_cpy = b; + m_sluB = SluMatrix::Map(b_cpy.const_cast_derived()); + } + + StatInit(&m_sluStat); + int info = 0; + RealScalar recip_pivot_growth, rcond; + SuperLU_gssvx(&m_sluOptions, &m_sluA, + m_q.data(), m_p.data(), + &m_sluEtree[0], &m_sluEqued, + &m_sluRscale[0], &m_sluCscale[0], + &m_sluL, &m_sluU, + NULL, 0, + &m_sluB, &m_sluX, + &recip_pivot_growth, &rcond, + &m_sluFerr[0], &m_sluBerr[0], + &m_sluStat, &info, Scalar()); + StatFree(&m_sluStat); + m_info = info==0 ? Success : NumericalIssue; +} + +// the code of this extractData() function has been adapted from the SuperLU's Matlab support code, +// +// Copyright (c) 1994 by Xerox Corporation. All rights reserved. +// +// THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY +// EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK. +// +template +void SuperLUBase::extractData() const +{ + eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for extracting factors, you must first call either compute() or analyzePattern()/factorize()"); + if (m_extractedDataAreDirty) + { + int upper; + int fsupc, istart, nsupr; + int lastl = 0, lastu = 0; + SCformat *Lstore = static_cast(m_sluL.Store); + NCformat *Ustore = static_cast(m_sluU.Store); + Scalar *SNptr; + + const int size = m_matrix.rows(); + m_l.resize(size,size); + m_l.resizeNonZeros(Lstore->nnz); + m_u.resize(size,size); + m_u.resizeNonZeros(Ustore->nnz); + + int* Lcol = m_l.outerIndexPtr(); + int* Lrow = m_l.innerIndexPtr(); + Scalar* Lval = m_l.valuePtr(); + + int* Ucol = m_u.outerIndexPtr(); + int* Urow = m_u.innerIndexPtr(); + Scalar* Uval = m_u.valuePtr(); + + Ucol[0] = 0; + Ucol[0] = 0; + + /* for each supernode */ + for (int k = 0; k <= Lstore->nsuper; ++k) + { + fsupc = L_FST_SUPC(k); + istart = L_SUB_START(fsupc); + nsupr = L_SUB_START(fsupc+1) - istart; + upper = 1; + + /* for each column in the supernode */ + for (int j = fsupc; j < L_FST_SUPC(k+1); ++j) + { + SNptr = &((Scalar*)Lstore->nzval)[L_NZ_START(j)]; + + /* Extract U */ + for (int i = U_NZ_START(j); i < U_NZ_START(j+1); ++i) + { + Uval[lastu] = ((Scalar*)Ustore->nzval)[i]; + /* Matlab doesn't like explicit zero. */ + if (Uval[lastu] != 0.0) + Urow[lastu++] = U_SUB(i); + } + for (int i = 0; i < upper; ++i) + { + /* upper triangle in the supernode */ + Uval[lastu] = SNptr[i]; + /* Matlab doesn't like explicit zero. */ + if (Uval[lastu] != 0.0) + Urow[lastu++] = L_SUB(istart+i); + } + Ucol[j+1] = lastu; + + /* Extract L */ + Lval[lastl] = 1.0; /* unit diagonal */ + Lrow[lastl++] = L_SUB(istart + upper - 1); + for (int i = upper; i < nsupr; ++i) + { + Lval[lastl] = SNptr[i]; + /* Matlab doesn't like explicit zero. */ + if (Lval[lastl] != 0.0) + Lrow[lastl++] = L_SUB(istart+i); + } + Lcol[j+1] = lastl; + + ++upper; + } /* for j ... */ + + } /* for k ... */ + + // squeeze the matrices : + m_l.resizeNonZeros(lastl); + m_u.resizeNonZeros(lastu); + + m_extractedDataAreDirty = false; + } +} + +template +typename SuperLU::Scalar SuperLU::determinant() const +{ + eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for computing the determinant, you must first call either compute() or analyzePattern()/factorize()"); + + if (m_extractedDataAreDirty) + this->extractData(); + + Scalar det = Scalar(1); + for (int j=0; j 0) + { + int lastId = m_u.outerIndexPtr()[j+1]-1; + eigen_assert(m_u.innerIndexPtr()[lastId]<=j); + if (m_u.innerIndexPtr()[lastId]==j) + det *= m_u.valuePtr()[lastId]; + } + } + if(m_sluEqued!='N') + return det/m_sluRscale.prod()/m_sluCscale.prod(); + else + return det; +} + +#ifdef EIGEN_PARSED_BY_DOXYGEN +#define EIGEN_SUPERLU_HAS_ILU +#endif + +#ifdef EIGEN_SUPERLU_HAS_ILU + +/** \ingroup SuperLUSupport_Module + * \class SuperILU + * \brief A sparse direct \b incomplete LU factorization and solver based on the SuperLU library + * + * This class allows to solve for an approximate solution of A.X = B sparse linear problems via an incomplete LU factorization + * using the SuperLU library. This class is aimed to be used as a preconditioner of the iterative linear solvers. + * + * \warning This class requires SuperLU 4 or later. + * + * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> + * + * \sa \ref TutorialSparseDirectSolvers, class ConjugateGradient, class BiCGSTAB + */ + +template +class SuperILU : public SuperLUBase<_MatrixType,SuperILU<_MatrixType> > +{ + public: + typedef SuperLUBase<_MatrixType,SuperILU> Base; + typedef _MatrixType MatrixType; + typedef typename Base::Scalar Scalar; + typedef typename Base::RealScalar RealScalar; + typedef typename Base::Index Index; + + public: + + SuperILU() : Base() { init(); } + + SuperILU(const MatrixType& matrix) : Base() + { + init(); + compute(matrix); + } + + ~SuperILU() + { + } + + /** Performs a symbolic decomposition on the sparcity of \a matrix. + * + * This function is particularly useful when solving for several problems having the same structure. + * + * \sa factorize() + */ + void analyzePattern(const MatrixType& matrix) + { + Base::analyzePattern(matrix); + } + + /** Performs a numeric decomposition of \a matrix + * + * The given matrix must has the same sparcity than the matrix on which the symbolic decomposition has been performed. + * + * \sa analyzePattern() + */ + void factorize(const MatrixType& matrix); + + #ifndef EIGEN_PARSED_BY_DOXYGEN + /** \internal */ + template + void _solve(const MatrixBase &b, MatrixBase &dest) const; + #endif // EIGEN_PARSED_BY_DOXYGEN + + protected: + + using Base::m_matrix; + using Base::m_sluOptions; + using Base::m_sluA; + using Base::m_sluB; + using Base::m_sluX; + using Base::m_p; + using Base::m_q; + using Base::m_sluEtree; + using Base::m_sluEqued; + using Base::m_sluRscale; + using Base::m_sluCscale; + using Base::m_sluL; + using Base::m_sluU; + using Base::m_sluStat; + using Base::m_sluFerr; + using Base::m_sluBerr; + using Base::m_l; + using Base::m_u; + + using Base::m_analysisIsOk; + using Base::m_factorizationIsOk; + using Base::m_extractedDataAreDirty; + using Base::m_isInitialized; + using Base::m_info; + + void init() + { + Base::init(); + + ilu_set_default_options(&m_sluOptions); + m_sluOptions.PrintStat = NO; + m_sluOptions.ConditionNumber = NO; + m_sluOptions.Trans = NOTRANS; + m_sluOptions.ColPerm = MMD_AT_PLUS_A; + + // no attempt to preserve column sum + m_sluOptions.ILU_MILU = SILU; + // only basic ILU(k) support -- no direct control over memory consumption + // better to use ILU_DropRule = DROP_BASIC | DROP_AREA + // and set ILU_FillFactor to max memory growth + m_sluOptions.ILU_DropRule = DROP_BASIC; + m_sluOptions.ILU_DropTol = NumTraits::dummy_precision()*10; + } + + private: + SuperILU(SuperILU& ) { } +}; + +template +void SuperILU::factorize(const MatrixType& a) +{ + eigen_assert(m_analysisIsOk && "You must first call analyzePattern()"); + if(!m_analysisIsOk) + { + m_info = InvalidInput; + return; + } + + this->initFactorization(a); + + int info = 0; + RealScalar recip_pivot_growth, rcond; + + StatInit(&m_sluStat); + SuperLU_gsisx(&m_sluOptions, &m_sluA, m_q.data(), m_p.data(), &m_sluEtree[0], + &m_sluEqued, &m_sluRscale[0], &m_sluCscale[0], + &m_sluL, &m_sluU, + NULL, 0, + &m_sluB, &m_sluX, + &recip_pivot_growth, &rcond, + &m_sluStat, &info, Scalar()); + StatFree(&m_sluStat); + + // FIXME how to better check for errors ??? + m_info = info == 0 ? Success : NumericalIssue; + m_factorizationIsOk = true; +} + +template +template +void SuperILU::_solve(const MatrixBase &b, MatrixBase& x) const +{ + eigen_assert(m_factorizationIsOk && "The decomposition is not in a valid state for solving, you must first call either compute() or analyzePattern()/factorize()"); + + const int size = m_matrix.rows(); + const int rhsCols = b.cols(); + eigen_assert(size==b.rows()); + + m_sluOptions.Trans = NOTRANS; + m_sluOptions.Fact = FACTORED; + m_sluOptions.IterRefine = NOREFINE; + + m_sluFerr.resize(rhsCols); + m_sluBerr.resize(rhsCols); + m_sluB = SluMatrix::Map(b.const_cast_derived()); + m_sluX = SluMatrix::Map(x.derived()); + + typename Rhs::PlainObject b_cpy; + if(m_sluEqued!='N') + { + b_cpy = b; + m_sluB = SluMatrix::Map(b_cpy.const_cast_derived()); + } + + int info = 0; + RealScalar recip_pivot_growth, rcond; + + StatInit(&m_sluStat); + SuperLU_gsisx(&m_sluOptions, &m_sluA, + m_q.data(), m_p.data(), + &m_sluEtree[0], &m_sluEqued, + &m_sluRscale[0], &m_sluCscale[0], + &m_sluL, &m_sluU, + NULL, 0, + &m_sluB, &m_sluX, + &recip_pivot_growth, &rcond, + &m_sluStat, &info, Scalar()); + StatFree(&m_sluStat); + + m_info = info==0 ? Success : NumericalIssue; +} +#endif + +namespace internal { + +template +struct solve_retval, Rhs> + : solve_retval_base, Rhs> +{ + typedef SuperLUBase<_MatrixType,Derived> Dec; + EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs) + + template void evalTo(Dest& dst) const + { + dec().derived()._solve(rhs(),dst); + } +}; + +template +struct sparse_solve_retval, Rhs> + : sparse_solve_retval_base, Rhs> +{ + typedef SuperLUBase<_MatrixType,Derived> Dec; + EIGEN_MAKE_SPARSE_SOLVE_HELPERS(Dec,Rhs) + + template void evalTo(Dest& dst) const + { + dec().derived()._solve(rhs(),dst); + } +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_SUPERLUSUPPORT_H diff --git a/extern/Eigen3/Eigen/src/UmfPackSupport/UmfPackSupport.h b/extern/Eigen3/Eigen/src/UmfPackSupport/UmfPackSupport.h new file mode 100644 index 00000000000..f01720362de --- /dev/null +++ b/extern/Eigen3/Eigen/src/UmfPackSupport/UmfPackSupport.h @@ -0,0 +1,431 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2011 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_UMFPACKSUPPORT_H +#define EIGEN_UMFPACKSUPPORT_H + +namespace Eigen { + +/* TODO extract L, extract U, compute det, etc... */ + +// generic double/complex wrapper functions: + +inline void umfpack_free_numeric(void **Numeric, double) +{ umfpack_di_free_numeric(Numeric); *Numeric = 0; } + +inline void umfpack_free_numeric(void **Numeric, std::complex) +{ umfpack_zi_free_numeric(Numeric); *Numeric = 0; } + +inline void umfpack_free_symbolic(void **Symbolic, double) +{ umfpack_di_free_symbolic(Symbolic); *Symbolic = 0; } + +inline void umfpack_free_symbolic(void **Symbolic, std::complex) +{ umfpack_zi_free_symbolic(Symbolic); *Symbolic = 0; } + +inline int umfpack_symbolic(int n_row,int n_col, + const int Ap[], const int Ai[], const double Ax[], void **Symbolic, + const double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + return umfpack_di_symbolic(n_row,n_col,Ap,Ai,Ax,Symbolic,Control,Info); +} + +inline int umfpack_symbolic(int n_row,int n_col, + const int Ap[], const int Ai[], const std::complex Ax[], void **Symbolic, + const double Control [UMFPACK_CONTROL], double Info [UMFPACK_INFO]) +{ + return umfpack_zi_symbolic(n_row,n_col,Ap,Ai,&internal::real_ref(Ax[0]),0,Symbolic,Control,Info); +} + +inline int umfpack_numeric( const int Ap[], const int Ai[], const double Ax[], + void *Symbolic, void **Numeric, + const double Control[UMFPACK_CONTROL],double Info [UMFPACK_INFO]) +{ + return umfpack_di_numeric(Ap,Ai,Ax,Symbolic,Numeric,Control,Info); +} + +inline int umfpack_numeric( const int Ap[], const int Ai[], const std::complex Ax[], + void *Symbolic, void **Numeric, + const double Control[UMFPACK_CONTROL],double Info [UMFPACK_INFO]) +{ + return umfpack_zi_numeric(Ap,Ai,&internal::real_ref(Ax[0]),0,Symbolic,Numeric,Control,Info); +} + +inline int umfpack_solve( int sys, const int Ap[], const int Ai[], const double Ax[], + double X[], const double B[], void *Numeric, + const double Control[UMFPACK_CONTROL], double Info[UMFPACK_INFO]) +{ + return umfpack_di_solve(sys,Ap,Ai,Ax,X,B,Numeric,Control,Info); +} + +inline int umfpack_solve( int sys, const int Ap[], const int Ai[], const std::complex Ax[], + std::complex X[], const std::complex B[], void *Numeric, + const double Control[UMFPACK_CONTROL], double Info[UMFPACK_INFO]) +{ + return umfpack_zi_solve(sys,Ap,Ai,&internal::real_ref(Ax[0]),0,&internal::real_ref(X[0]),0,&internal::real_ref(B[0]),0,Numeric,Control,Info); +} + +inline int umfpack_get_lunz(int *lnz, int *unz, int *n_row, int *n_col, int *nz_udiag, void *Numeric, double) +{ + return umfpack_di_get_lunz(lnz,unz,n_row,n_col,nz_udiag,Numeric); +} + +inline int umfpack_get_lunz(int *lnz, int *unz, int *n_row, int *n_col, int *nz_udiag, void *Numeric, std::complex) +{ + return umfpack_zi_get_lunz(lnz,unz,n_row,n_col,nz_udiag,Numeric); +} + +inline int umfpack_get_numeric(int Lp[], int Lj[], double Lx[], int Up[], int Ui[], double Ux[], + int P[], int Q[], double Dx[], int *do_recip, double Rs[], void *Numeric) +{ + return umfpack_di_get_numeric(Lp,Lj,Lx,Up,Ui,Ux,P,Q,Dx,do_recip,Rs,Numeric); +} + +inline int umfpack_get_numeric(int Lp[], int Lj[], std::complex Lx[], int Up[], int Ui[], std::complex Ux[], + int P[], int Q[], std::complex Dx[], int *do_recip, double Rs[], void *Numeric) +{ + double& lx0_real = internal::real_ref(Lx[0]); + double& ux0_real = internal::real_ref(Ux[0]); + double& dx0_real = internal::real_ref(Dx[0]); + return umfpack_zi_get_numeric(Lp,Lj,Lx?&lx0_real:0,0,Up,Ui,Ux?&ux0_real:0,0,P,Q, + Dx?&dx0_real:0,0,do_recip,Rs,Numeric); +} + +inline int umfpack_get_determinant(double *Mx, double *Ex, void *NumericHandle, double User_Info [UMFPACK_INFO]) +{ + return umfpack_di_get_determinant(Mx,Ex,NumericHandle,User_Info); +} + +inline int umfpack_get_determinant(std::complex *Mx, double *Ex, void *NumericHandle, double User_Info [UMFPACK_INFO]) +{ + double& mx_real = internal::real_ref(*Mx); + return umfpack_zi_get_determinant(&mx_real,0,Ex,NumericHandle,User_Info); +} + +/** \ingroup UmfPackSupport_Module + * \brief A sparse LU factorization and solver based on UmfPack + * + * This class allows to solve for A.X = B sparse linear problems via a LU factorization + * using the UmfPack library. The sparse matrix A must be squared and full rank. + * The vectors or matrices X and B can be either dense or sparse. + * + * \WARNING The input matrix A should be in a \b compressed and \b column-major form. + * Otherwise an expensive copy will be made. You can call the inexpensive makeCompressed() to get a compressed matrix. + * \tparam _MatrixType the type of the sparse matrix A, it must be a SparseMatrix<> + * + * \sa \ref TutorialSparseDirectSolvers + */ +template +class UmfPackLU : internal::noncopyable +{ + public: + typedef _MatrixType MatrixType; + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef typename MatrixType::Index Index; + typedef Matrix Vector; + typedef Matrix IntRowVectorType; + typedef Matrix IntColVectorType; + typedef SparseMatrix LUMatrixType; + typedef SparseMatrix UmfpackMatrixType; + + public: + + UmfPackLU() { init(); } + + UmfPackLU(const MatrixType& matrix) + { + init(); + compute(matrix); + } + + ~UmfPackLU() + { + if(m_symbolic) umfpack_free_symbolic(&m_symbolic,Scalar()); + if(m_numeric) umfpack_free_numeric(&m_numeric,Scalar()); + } + + inline Index rows() const { return m_copyMatrix.rows(); } + inline Index cols() const { return m_copyMatrix.cols(); } + + /** \brief Reports whether previous computation was successful. + * + * \returns \c Success if computation was succesful, + * \c NumericalIssue if the matrix.appears to be negative. + */ + ComputationInfo info() const + { + eigen_assert(m_isInitialized && "Decomposition is not initialized."); + return m_info; + } + + inline const LUMatrixType& matrixL() const + { + if (m_extractedDataAreDirty) extractData(); + return m_l; + } + + inline const LUMatrixType& matrixU() const + { + if (m_extractedDataAreDirty) extractData(); + return m_u; + } + + inline const IntColVectorType& permutationP() const + { + if (m_extractedDataAreDirty) extractData(); + return m_p; + } + + inline const IntRowVectorType& permutationQ() const + { + if (m_extractedDataAreDirty) extractData(); + return m_q; + } + + /** Computes the sparse Cholesky decomposition of \a matrix + * Note that the matrix should be column-major, and in compressed format for best performance. + * \sa SparseMatrix::makeCompressed(). + */ + void compute(const MatrixType& matrix) + { + analyzePattern(matrix); + factorize(matrix); + } + + /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. + * + * \sa compute() + */ + template + inline const internal::solve_retval solve(const MatrixBase& b) const + { + eigen_assert(m_isInitialized && "UmfPackLU is not initialized."); + eigen_assert(rows()==b.rows() + && "UmfPackLU::solve(): invalid number of rows of the right hand side matrix b"); + return internal::solve_retval(*this, b.derived()); + } + + /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A. + * + * \sa compute() + */ +// template +// inline const internal::sparse_solve_retval solve(const SparseMatrixBase& b) const +// { +// eigen_assert(m_isInitialized && "UmfPAckLU is not initialized."); +// eigen_assert(rows()==b.rows() +// && "UmfPAckLU::solve(): invalid number of rows of the right hand side matrix b"); +// return internal::sparse_solve_retval(*this, b.derived()); +// } + + /** Performs a symbolic decomposition on the sparcity of \a matrix. + * + * This function is particularly useful when solving for several problems having the same structure. + * + * \sa factorize(), compute() + */ + void analyzePattern(const MatrixType& matrix) + { + if(m_symbolic) + umfpack_free_symbolic(&m_symbolic,Scalar()); + if(m_numeric) + umfpack_free_numeric(&m_numeric,Scalar()); + + grapInput(matrix); + + int errorCode = 0; + errorCode = umfpack_symbolic(matrix.rows(), matrix.cols(), m_outerIndexPtr, m_innerIndexPtr, m_valuePtr, + &m_symbolic, 0, 0); + + m_isInitialized = true; + m_info = errorCode ? InvalidInput : Success; + m_analysisIsOk = true; + m_factorizationIsOk = false; + } + + /** Performs a numeric decomposition of \a matrix + * + * The given matrix must has the same sparcity than the matrix on which the pattern anylysis has been performed. + * + * \sa analyzePattern(), compute() + */ + void factorize(const MatrixType& matrix) + { + eigen_assert(m_analysisIsOk && "UmfPackLU: you must first call analyzePattern()"); + if(m_numeric) + umfpack_free_numeric(&m_numeric,Scalar()); + + grapInput(matrix); + + int errorCode; + errorCode = umfpack_numeric(m_outerIndexPtr, m_innerIndexPtr, m_valuePtr, + m_symbolic, &m_numeric, 0, 0); + + m_info = errorCode ? NumericalIssue : Success; + m_factorizationIsOk = true; + } + + #ifndef EIGEN_PARSED_BY_DOXYGEN + /** \internal */ + template + bool _solve(const MatrixBase &b, MatrixBase &x) const; + #endif + + Scalar determinant() const; + + void extractData() const; + + protected: + + + void init() + { + m_info = InvalidInput; + m_isInitialized = false; + m_numeric = 0; + m_symbolic = 0; + m_outerIndexPtr = 0; + m_innerIndexPtr = 0; + m_valuePtr = 0; + } + + void grapInput(const MatrixType& mat) + { + m_copyMatrix.resize(mat.rows(), mat.cols()); + if( ((MatrixType::Flags&RowMajorBit)==RowMajorBit) || sizeof(typename MatrixType::Index)!=sizeof(int) || !mat.isCompressed() ) + { + // non supported input -> copy + m_copyMatrix = mat; + m_outerIndexPtr = m_copyMatrix.outerIndexPtr(); + m_innerIndexPtr = m_copyMatrix.innerIndexPtr(); + m_valuePtr = m_copyMatrix.valuePtr(); + } + else + { + m_outerIndexPtr = mat.outerIndexPtr(); + m_innerIndexPtr = mat.innerIndexPtr(); + m_valuePtr = mat.valuePtr(); + } + } + + // cached data to reduce reallocation, etc. + mutable LUMatrixType m_l; + mutable LUMatrixType m_u; + mutable IntColVectorType m_p; + mutable IntRowVectorType m_q; + + UmfpackMatrixType m_copyMatrix; + const Scalar* m_valuePtr; + const int* m_outerIndexPtr; + const int* m_innerIndexPtr; + void* m_numeric; + void* m_symbolic; + + mutable ComputationInfo m_info; + bool m_isInitialized; + int m_factorizationIsOk; + int m_analysisIsOk; + mutable bool m_extractedDataAreDirty; + + private: + UmfPackLU(UmfPackLU& ) { } +}; + + +template +void UmfPackLU::extractData() const +{ + if (m_extractedDataAreDirty) + { + // get size of the data + int lnz, unz, rows, cols, nz_udiag; + umfpack_get_lunz(&lnz, &unz, &rows, &cols, &nz_udiag, m_numeric, Scalar()); + + // allocate data + m_l.resize(rows,(std::min)(rows,cols)); + m_l.resizeNonZeros(lnz); + + m_u.resize((std::min)(rows,cols),cols); + m_u.resizeNonZeros(unz); + + m_p.resize(rows); + m_q.resize(cols); + + // extract + umfpack_get_numeric(m_l.outerIndexPtr(), m_l.innerIndexPtr(), m_l.valuePtr(), + m_u.outerIndexPtr(), m_u.innerIndexPtr(), m_u.valuePtr(), + m_p.data(), m_q.data(), 0, 0, 0, m_numeric); + + m_extractedDataAreDirty = false; + } +} + +template +typename UmfPackLU::Scalar UmfPackLU::determinant() const +{ + Scalar det; + umfpack_get_determinant(&det, 0, m_numeric, 0); + return det; +} + +template +template +bool UmfPackLU::_solve(const MatrixBase &b, MatrixBase &x) const +{ + const int rhsCols = b.cols(); + eigen_assert((BDerived::Flags&RowMajorBit)==0 && "UmfPackLU backend does not support non col-major rhs yet"); + eigen_assert((XDerived::Flags&RowMajorBit)==0 && "UmfPackLU backend does not support non col-major result yet"); + + int errorCode; + for (int j=0; j +struct solve_retval, Rhs> + : solve_retval_base, Rhs> +{ + typedef UmfPackLU<_MatrixType> Dec; + EIGEN_MAKE_SOLVE_HELPERS(Dec,Rhs) + + template void evalTo(Dest& dst) const + { + dec()._solve(rhs(),dst); + } +}; + +template +struct sparse_solve_retval, Rhs> + : sparse_solve_retval_base, Rhs> +{ + typedef UmfPackLU<_MatrixType> Dec; + EIGEN_MAKE_SPARSE_SOLVE_HELPERS(Dec,Rhs) + + template void evalTo(Dest& dst) const + { + dec()._solve(rhs(),dst); + } +}; + +} // end namespace internal + +} // end namespace Eigen + +#endif // EIGEN_UMFPACKSUPPORT_H diff --git a/extern/Eigen3/Eigen/src/misc/Image.h b/extern/Eigen3/Eigen/src/misc/Image.h index 19b3e08cbfd..75c5f433a8a 100644 --- a/extern/Eigen3/Eigen/src/misc/Image.h +++ b/extern/Eigen3/Eigen/src/misc/Image.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_MISC_IMAGE_H #define EIGEN_MISC_IMAGE_H +namespace Eigen { + namespace internal { /** \class image_retval_base @@ -92,4 +79,6 @@ template struct image_retval_base image_retval(const DecompositionType& dec, const MatrixType& originalMatrix) \ : Base(dec, originalMatrix) {} +} // end namespace Eigen + #endif // EIGEN_MISC_IMAGE_H diff --git a/extern/Eigen3/Eigen/src/misc/Kernel.h b/extern/Eigen3/Eigen/src/misc/Kernel.h index 0115970e8eb..b9e1518fd49 100644 --- a/extern/Eigen3/Eigen/src/misc/Kernel.h +++ b/extern/Eigen3/Eigen/src/misc/Kernel.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_MISC_KERNEL_H #define EIGEN_MISC_KERNEL_H +namespace Eigen { + namespace internal { /** \class kernel_retval_base @@ -89,4 +76,6 @@ template struct kernel_retval_base using Base::cols; \ kernel_retval(const DecompositionType& dec) : Base(dec) {} +} // end namespace Eigen + #endif // EIGEN_MISC_KERNEL_H diff --git a/extern/Eigen3/Eigen/src/misc/Solve.h b/extern/Eigen3/Eigen/src/misc/Solve.h index b7cbcadb392..7f70d60afbd 100644 --- a/extern/Eigen3/Eigen/src/misc/Solve.h +++ b/extern/Eigen3/Eigen/src/misc/Solve.h @@ -3,28 +3,15 @@ // // Copyright (C) 2009 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_MISC_SOLVE_H #define EIGEN_MISC_SOLVE_H +namespace Eigen { + namespace internal { /** \class solve_retval_base @@ -66,7 +53,7 @@ template struct solve_retval_base protected: const DecompositionType& m_dec; - const typename Rhs::Nested m_rhs; + typename Rhs::Nested m_rhs; }; } // end namespace internal @@ -84,4 +71,6 @@ template struct solve_retval_base solve_retval(const DecompositionType& dec, const Rhs& rhs) \ : Base(dec, rhs) {} +} // end namespace Eigen + #endif // EIGEN_MISC_SOLVE_H diff --git a/extern/Eigen3/Eigen/src/misc/SparseSolve.h b/extern/Eigen3/Eigen/src/misc/SparseSolve.h new file mode 100644 index 00000000000..272c4a479d7 --- /dev/null +++ b/extern/Eigen3/Eigen/src/misc/SparseSolve.h @@ -0,0 +1,111 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2010 Gael Guennebaud +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_SPARSE_SOLVE_H +#define EIGEN_SPARSE_SOLVE_H + +namespace Eigen { + +namespace internal { + +template struct sparse_solve_retval_base; +template struct sparse_solve_retval; + +template +struct traits > +{ + typedef typename DecompositionType::MatrixType MatrixType; + typedef SparseMatrix ReturnType; +}; + +template struct sparse_solve_retval_base + : public ReturnByValue > +{ + typedef typename remove_all::type RhsNestedCleaned; + typedef _DecompositionType DecompositionType; + typedef ReturnByValue Base; + typedef typename Base::Index Index; + + sparse_solve_retval_base(const DecompositionType& dec, const Rhs& rhs) + : m_dec(dec), m_rhs(rhs) + {} + + inline Index rows() const { return m_dec.cols(); } + inline Index cols() const { return m_rhs.cols(); } + inline const DecompositionType& dec() const { return m_dec; } + inline const RhsNestedCleaned& rhs() const { return m_rhs; } + + template inline void evalTo(Dest& dst) const + { + static_cast*>(this)->evalTo(dst); + } + + protected: + const DecompositionType& m_dec; + typename Rhs::Nested m_rhs; +}; + +#define EIGEN_MAKE_SPARSE_SOLVE_HELPERS(DecompositionType,Rhs) \ + typedef typename DecompositionType::MatrixType MatrixType; \ + typedef typename MatrixType::Scalar Scalar; \ + typedef typename MatrixType::RealScalar RealScalar; \ + typedef typename MatrixType::Index Index; \ + typedef Eigen::internal::sparse_solve_retval_base Base; \ + using Base::dec; \ + using Base::rhs; \ + using Base::rows; \ + using Base::cols; \ + sparse_solve_retval(const DecompositionType& dec, const Rhs& rhs) \ + : Base(dec, rhs) {} + + + +template struct solve_retval_with_guess; + +template +struct traits > +{ + typedef typename DecompositionType::MatrixType MatrixType; + typedef Matrix ReturnType; +}; + +template struct solve_retval_with_guess + : public ReturnByValue > +{ + typedef typename DecompositionType::Index Index; + + solve_retval_with_guess(const DecompositionType& dec, const Rhs& rhs, const Guess& guess) + : m_dec(dec), m_rhs(rhs), m_guess(guess) + {} + + inline Index rows() const { return m_dec.cols(); } + inline Index cols() const { return m_rhs.cols(); } + + template inline void evalTo(Dest& dst) const + { + dst = m_guess; + m_dec._solveWithGuess(m_rhs,dst); + } + + protected: + const DecompositionType& m_dec; + const typename Rhs::Nested m_rhs; + const typename Guess::Nested m_guess; +}; + +} // namepsace internal + +} // end namespace Eigen + +#endif // EIGEN_SPARSE_SOLVE_H diff --git a/extern/Eigen3/Eigen/src/misc/blas.h b/extern/Eigen3/Eigen/src/misc/blas.h new file mode 100644 index 00000000000..6fce99ed5c4 --- /dev/null +++ b/extern/Eigen3/Eigen/src/misc/blas.h @@ -0,0 +1,658 @@ +#ifndef BLAS_H +#define BLAS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define BLASFUNC(FUNC) FUNC##_ + +#ifdef __WIN64__ +typedef long long BLASLONG; +typedef unsigned long long BLASULONG; +#else +typedef long BLASLONG; +typedef unsigned long BLASULONG; +#endif + +int BLASFUNC(xerbla)(const char *, int *info, int); + +float BLASFUNC(sdot) (int *, float *, int *, float *, int *); +float BLASFUNC(sdsdot)(int *, float *, float *, int *, float *, int *); + +double BLASFUNC(dsdot) (int *, float *, int *, float *, int *); +double BLASFUNC(ddot) (int *, double *, int *, double *, int *); +double BLASFUNC(qdot) (int *, double *, int *, double *, int *); + +int BLASFUNC(cdotuw) (int *, float *, int *, float *, int *, float*); +int BLASFUNC(cdotcw) (int *, float *, int *, float *, int *, float*); +int BLASFUNC(zdotuw) (int *, double *, int *, double *, int *, double*); +int BLASFUNC(zdotcw) (int *, double *, int *, double *, int *, double*); + +int BLASFUNC(saxpy) (int *, float *, float *, int *, float *, int *); +int BLASFUNC(daxpy) (int *, double *, double *, int *, double *, int *); +int BLASFUNC(qaxpy) (int *, double *, double *, int *, double *, int *); +int BLASFUNC(caxpy) (int *, float *, float *, int *, float *, int *); +int BLASFUNC(zaxpy) (int *, double *, double *, int *, double *, int *); +int BLASFUNC(xaxpy) (int *, double *, double *, int *, double *, int *); +int BLASFUNC(caxpyc)(int *, float *, float *, int *, float *, int *); +int BLASFUNC(zaxpyc)(int *, double *, double *, int *, double *, int *); +int BLASFUNC(xaxpyc)(int *, double *, double *, int *, double *, int *); + +int BLASFUNC(scopy) (int *, float *, int *, float *, int *); +int BLASFUNC(dcopy) (int *, double *, int *, double *, int *); +int BLASFUNC(qcopy) (int *, double *, int *, double *, int *); +int BLASFUNC(ccopy) (int *, float *, int *, float *, int *); +int BLASFUNC(zcopy) (int *, double *, int *, double *, int *); +int BLASFUNC(xcopy) (int *, double *, int *, double *, int *); + +int BLASFUNC(sswap) (int *, float *, int *, float *, int *); +int BLASFUNC(dswap) (int *, double *, int *, double *, int *); +int BLASFUNC(qswap) (int *, double *, int *, double *, int *); +int BLASFUNC(cswap) (int *, float *, int *, float *, int *); +int BLASFUNC(zswap) (int *, double *, int *, double *, int *); +int BLASFUNC(xswap) (int *, double *, int *, double *, int *); + +float BLASFUNC(sasum) (int *, float *, int *); +float BLASFUNC(scasum)(int *, float *, int *); +double BLASFUNC(dasum) (int *, double *, int *); +double BLASFUNC(qasum) (int *, double *, int *); +double BLASFUNC(dzasum)(int *, double *, int *); +double BLASFUNC(qxasum)(int *, double *, int *); + +int BLASFUNC(isamax)(int *, float *, int *); +int BLASFUNC(idamax)(int *, double *, int *); +int BLASFUNC(iqamax)(int *, double *, int *); +int BLASFUNC(icamax)(int *, float *, int *); +int BLASFUNC(izamax)(int *, double *, int *); +int BLASFUNC(ixamax)(int *, double *, int *); + +int BLASFUNC(ismax) (int *, float *, int *); +int BLASFUNC(idmax) (int *, double *, int *); +int BLASFUNC(iqmax) (int *, double *, int *); +int BLASFUNC(icmax) (int *, float *, int *); +int BLASFUNC(izmax) (int *, double *, int *); +int BLASFUNC(ixmax) (int *, double *, int *); + +int BLASFUNC(isamin)(int *, float *, int *); +int BLASFUNC(idamin)(int *, double *, int *); +int BLASFUNC(iqamin)(int *, double *, int *); +int BLASFUNC(icamin)(int *, float *, int *); +int BLASFUNC(izamin)(int *, double *, int *); +int BLASFUNC(ixamin)(int *, double *, int *); + +int BLASFUNC(ismin)(int *, float *, int *); +int BLASFUNC(idmin)(int *, double *, int *); +int BLASFUNC(iqmin)(int *, double *, int *); +int BLASFUNC(icmin)(int *, float *, int *); +int BLASFUNC(izmin)(int *, double *, int *); +int BLASFUNC(ixmin)(int *, double *, int *); + +float BLASFUNC(samax) (int *, float *, int *); +double BLASFUNC(damax) (int *, double *, int *); +double BLASFUNC(qamax) (int *, double *, int *); +float BLASFUNC(scamax)(int *, float *, int *); +double BLASFUNC(dzamax)(int *, double *, int *); +double BLASFUNC(qxamax)(int *, double *, int *); + +float BLASFUNC(samin) (int *, float *, int *); +double BLASFUNC(damin) (int *, double *, int *); +double BLASFUNC(qamin) (int *, double *, int *); +float BLASFUNC(scamin)(int *, float *, int *); +double BLASFUNC(dzamin)(int *, double *, int *); +double BLASFUNC(qxamin)(int *, double *, int *); + +float BLASFUNC(smax) (int *, float *, int *); +double BLASFUNC(dmax) (int *, double *, int *); +double BLASFUNC(qmax) (int *, double *, int *); +float BLASFUNC(scmax) (int *, float *, int *); +double BLASFUNC(dzmax) (int *, double *, int *); +double BLASFUNC(qxmax) (int *, double *, int *); + +float BLASFUNC(smin) (int *, float *, int *); +double BLASFUNC(dmin) (int *, double *, int *); +double BLASFUNC(qmin) (int *, double *, int *); +float BLASFUNC(scmin) (int *, float *, int *); +double BLASFUNC(dzmin) (int *, double *, int *); +double BLASFUNC(qxmin) (int *, double *, int *); + +int BLASFUNC(sscal) (int *, float *, float *, int *); +int BLASFUNC(dscal) (int *, double *, double *, int *); +int BLASFUNC(qscal) (int *, double *, double *, int *); +int BLASFUNC(cscal) (int *, float *, float *, int *); +int BLASFUNC(zscal) (int *, double *, double *, int *); +int BLASFUNC(xscal) (int *, double *, double *, int *); +int BLASFUNC(csscal)(int *, float *, float *, int *); +int BLASFUNC(zdscal)(int *, double *, double *, int *); +int BLASFUNC(xqscal)(int *, double *, double *, int *); + +float BLASFUNC(snrm2) (int *, float *, int *); +float BLASFUNC(scnrm2)(int *, float *, int *); + +double BLASFUNC(dnrm2) (int *, double *, int *); +double BLASFUNC(qnrm2) (int *, double *, int *); +double BLASFUNC(dznrm2)(int *, double *, int *); +double BLASFUNC(qxnrm2)(int *, double *, int *); + +int BLASFUNC(srot) (int *, float *, int *, float *, int *, float *, float *); +int BLASFUNC(drot) (int *, double *, int *, double *, int *, double *, double *); +int BLASFUNC(qrot) (int *, double *, int *, double *, int *, double *, double *); +int BLASFUNC(csrot) (int *, float *, int *, float *, int *, float *, float *); +int BLASFUNC(zdrot) (int *, double *, int *, double *, int *, double *, double *); +int BLASFUNC(xqrot) (int *, double *, int *, double *, int *, double *, double *); + +int BLASFUNC(srotg) (float *, float *, float *, float *); +int BLASFUNC(drotg) (double *, double *, double *, double *); +int BLASFUNC(qrotg) (double *, double *, double *, double *); +int BLASFUNC(crotg) (float *, float *, float *, float *); +int BLASFUNC(zrotg) (double *, double *, double *, double *); +int BLASFUNC(xrotg) (double *, double *, double *, double *); + +int BLASFUNC(srotmg)(float *, float *, float *, float *, float *); +int BLASFUNC(drotmg)(double *, double *, double *, double *, double *); + +int BLASFUNC(srotm) (int *, float *, int *, float *, int *, float *); +int BLASFUNC(drotm) (int *, double *, int *, double *, int *, double *); +int BLASFUNC(qrotm) (int *, double *, int *, double *, int *, double *); + +/* Level 2 routines */ + +int BLASFUNC(sger)(int *, int *, float *, float *, int *, + float *, int *, float *, int *); +int BLASFUNC(dger)(int *, int *, double *, double *, int *, + double *, int *, double *, int *); +int BLASFUNC(qger)(int *, int *, double *, double *, int *, + double *, int *, double *, int *); +int BLASFUNC(cgeru)(int *, int *, float *, float *, int *, + float *, int *, float *, int *); +int BLASFUNC(cgerc)(int *, int *, float *, float *, int *, + float *, int *, float *, int *); +int BLASFUNC(zgeru)(int *, int *, double *, double *, int *, + double *, int *, double *, int *); +int BLASFUNC(zgerc)(int *, int *, double *, double *, int *, + double *, int *, double *, int *); +int BLASFUNC(xgeru)(int *, int *, double *, double *, int *, + double *, int *, double *, int *); +int BLASFUNC(xgerc)(int *, int *, double *, double *, int *, + double *, int *, double *, int *); + +int BLASFUNC(sgemv)(char *, int *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(dgemv)(char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(qgemv)(char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(cgemv)(char *, int *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(zgemv)(char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(xgemv)(char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); + +int BLASFUNC(strsv) (char *, char *, char *, int *, float *, int *, + float *, int *); +int BLASFUNC(dtrsv) (char *, char *, char *, int *, double *, int *, + double *, int *); +int BLASFUNC(qtrsv) (char *, char *, char *, int *, double *, int *, + double *, int *); +int BLASFUNC(ctrsv) (char *, char *, char *, int *, float *, int *, + float *, int *); +int BLASFUNC(ztrsv) (char *, char *, char *, int *, double *, int *, + double *, int *); +int BLASFUNC(xtrsv) (char *, char *, char *, int *, double *, int *, + double *, int *); + +int BLASFUNC(stpsv) (char *, char *, char *, int *, float *, float *, int *); +int BLASFUNC(dtpsv) (char *, char *, char *, int *, double *, double *, int *); +int BLASFUNC(qtpsv) (char *, char *, char *, int *, double *, double *, int *); +int BLASFUNC(ctpsv) (char *, char *, char *, int *, float *, float *, int *); +int BLASFUNC(ztpsv) (char *, char *, char *, int *, double *, double *, int *); +int BLASFUNC(xtpsv) (char *, char *, char *, int *, double *, double *, int *); + +int BLASFUNC(strmv) (char *, char *, char *, int *, float *, int *, + float *, int *); +int BLASFUNC(dtrmv) (char *, char *, char *, int *, double *, int *, + double *, int *); +int BLASFUNC(qtrmv) (char *, char *, char *, int *, double *, int *, + double *, int *); +int BLASFUNC(ctrmv) (char *, char *, char *, int *, float *, int *, + float *, int *); +int BLASFUNC(ztrmv) (char *, char *, char *, int *, double *, int *, + double *, int *); +int BLASFUNC(xtrmv) (char *, char *, char *, int *, double *, int *, + double *, int *); + +int BLASFUNC(stpmv) (char *, char *, char *, int *, float *, float *, int *); +int BLASFUNC(dtpmv) (char *, char *, char *, int *, double *, double *, int *); +int BLASFUNC(qtpmv) (char *, char *, char *, int *, double *, double *, int *); +int BLASFUNC(ctpmv) (char *, char *, char *, int *, float *, float *, int *); +int BLASFUNC(ztpmv) (char *, char *, char *, int *, double *, double *, int *); +int BLASFUNC(xtpmv) (char *, char *, char *, int *, double *, double *, int *); + +int BLASFUNC(stbmv) (char *, char *, char *, int *, int *, float *, int *, float *, int *); +int BLASFUNC(dtbmv) (char *, char *, char *, int *, int *, double *, int *, double *, int *); +int BLASFUNC(qtbmv) (char *, char *, char *, int *, int *, double *, int *, double *, int *); +int BLASFUNC(ctbmv) (char *, char *, char *, int *, int *, float *, int *, float *, int *); +int BLASFUNC(ztbmv) (char *, char *, char *, int *, int *, double *, int *, double *, int *); +int BLASFUNC(xtbmv) (char *, char *, char *, int *, int *, double *, int *, double *, int *); + +int BLASFUNC(stbsv) (char *, char *, char *, int *, int *, float *, int *, float *, int *); +int BLASFUNC(dtbsv) (char *, char *, char *, int *, int *, double *, int *, double *, int *); +int BLASFUNC(qtbsv) (char *, char *, char *, int *, int *, double *, int *, double *, int *); +int BLASFUNC(ctbsv) (char *, char *, char *, int *, int *, float *, int *, float *, int *); +int BLASFUNC(ztbsv) (char *, char *, char *, int *, int *, double *, int *, double *, int *); +int BLASFUNC(xtbsv) (char *, char *, char *, int *, int *, double *, int *, double *, int *); + +int BLASFUNC(ssymv) (char *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(dsymv) (char *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(qsymv) (char *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(csymv) (char *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(zsymv) (char *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(xsymv) (char *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); + +int BLASFUNC(sspmv) (char *, int *, float *, float *, + float *, int *, float *, float *, int *); +int BLASFUNC(dspmv) (char *, int *, double *, double *, + double *, int *, double *, double *, int *); +int BLASFUNC(qspmv) (char *, int *, double *, double *, + double *, int *, double *, double *, int *); +int BLASFUNC(cspmv) (char *, int *, float *, float *, + float *, int *, float *, float *, int *); +int BLASFUNC(zspmv) (char *, int *, double *, double *, + double *, int *, double *, double *, int *); +int BLASFUNC(xspmv) (char *, int *, double *, double *, + double *, int *, double *, double *, int *); + +int BLASFUNC(ssyr) (char *, int *, float *, float *, int *, + float *, int *); +int BLASFUNC(dsyr) (char *, int *, double *, double *, int *, + double *, int *); +int BLASFUNC(qsyr) (char *, int *, double *, double *, int *, + double *, int *); +int BLASFUNC(csyr) (char *, int *, float *, float *, int *, + float *, int *); +int BLASFUNC(zsyr) (char *, int *, double *, double *, int *, + double *, int *); +int BLASFUNC(xsyr) (char *, int *, double *, double *, int *, + double *, int *); + +int BLASFUNC(ssyr2) (char *, int *, float *, + float *, int *, float *, int *, float *, int *); +int BLASFUNC(dsyr2) (char *, int *, double *, + double *, int *, double *, int *, double *, int *); +int BLASFUNC(qsyr2) (char *, int *, double *, + double *, int *, double *, int *, double *, int *); +int BLASFUNC(csyr2) (char *, int *, float *, + float *, int *, float *, int *, float *, int *); +int BLASFUNC(zsyr2) (char *, int *, double *, + double *, int *, double *, int *, double *, int *); +int BLASFUNC(xsyr2) (char *, int *, double *, + double *, int *, double *, int *, double *, int *); + +int BLASFUNC(sspr) (char *, int *, float *, float *, int *, + float *); +int BLASFUNC(dspr) (char *, int *, double *, double *, int *, + double *); +int BLASFUNC(qspr) (char *, int *, double *, double *, int *, + double *); +int BLASFUNC(cspr) (char *, int *, float *, float *, int *, + float *); +int BLASFUNC(zspr) (char *, int *, double *, double *, int *, + double *); +int BLASFUNC(xspr) (char *, int *, double *, double *, int *, + double *); + +int BLASFUNC(sspr2) (char *, int *, float *, + float *, int *, float *, int *, float *); +int BLASFUNC(dspr2) (char *, int *, double *, + double *, int *, double *, int *, double *); +int BLASFUNC(qspr2) (char *, int *, double *, + double *, int *, double *, int *, double *); +int BLASFUNC(cspr2) (char *, int *, float *, + float *, int *, float *, int *, float *); +int BLASFUNC(zspr2) (char *, int *, double *, + double *, int *, double *, int *, double *); +int BLASFUNC(xspr2) (char *, int *, double *, + double *, int *, double *, int *, double *); + +int BLASFUNC(cher) (char *, int *, float *, float *, int *, + float *, int *); +int BLASFUNC(zher) (char *, int *, double *, double *, int *, + double *, int *); +int BLASFUNC(xher) (char *, int *, double *, double *, int *, + double *, int *); + +int BLASFUNC(chpr) (char *, int *, float *, float *, int *, float *); +int BLASFUNC(zhpr) (char *, int *, double *, double *, int *, double *); +int BLASFUNC(xhpr) (char *, int *, double *, double *, int *, double *); + +int BLASFUNC(cher2) (char *, int *, float *, + float *, int *, float *, int *, float *, int *); +int BLASFUNC(zher2) (char *, int *, double *, + double *, int *, double *, int *, double *, int *); +int BLASFUNC(xher2) (char *, int *, double *, + double *, int *, double *, int *, double *, int *); + +int BLASFUNC(chpr2) (char *, int *, float *, + float *, int *, float *, int *, float *); +int BLASFUNC(zhpr2) (char *, int *, double *, + double *, int *, double *, int *, double *); +int BLASFUNC(xhpr2) (char *, int *, double *, + double *, int *, double *, int *, double *); + +int BLASFUNC(chemv) (char *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(zhemv) (char *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(xhemv) (char *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); + +int BLASFUNC(chpmv) (char *, int *, float *, float *, + float *, int *, float *, float *, int *); +int BLASFUNC(zhpmv) (char *, int *, double *, double *, + double *, int *, double *, double *, int *); +int BLASFUNC(xhpmv) (char *, int *, double *, double *, + double *, int *, double *, double *, int *); + +int BLASFUNC(snorm)(char *, int *, int *, float *, int *); +int BLASFUNC(dnorm)(char *, int *, int *, double *, int *); +int BLASFUNC(cnorm)(char *, int *, int *, float *, int *); +int BLASFUNC(znorm)(char *, int *, int *, double *, int *); + +int BLASFUNC(sgbmv)(char *, int *, int *, int *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(dgbmv)(char *, int *, int *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(qgbmv)(char *, int *, int *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(cgbmv)(char *, int *, int *, int *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(zgbmv)(char *, int *, int *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(xgbmv)(char *, int *, int *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); + +int BLASFUNC(ssbmv)(char *, int *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(dsbmv)(char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(qsbmv)(char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(csbmv)(char *, int *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(zsbmv)(char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(xsbmv)(char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); + +int BLASFUNC(chbmv)(char *, int *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(zhbmv)(char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(xhbmv)(char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); + +/* Level 3 routines */ + +int BLASFUNC(sgemm)(char *, char *, int *, int *, int *, float *, + float *, int *, float *, int *, float *, float *, int *); +int BLASFUNC(dgemm)(char *, char *, int *, int *, int *, double *, + double *, int *, double *, int *, double *, double *, int *); +int BLASFUNC(qgemm)(char *, char *, int *, int *, int *, double *, + double *, int *, double *, int *, double *, double *, int *); +int BLASFUNC(cgemm)(char *, char *, int *, int *, int *, float *, + float *, int *, float *, int *, float *, float *, int *); +int BLASFUNC(zgemm)(char *, char *, int *, int *, int *, double *, + double *, int *, double *, int *, double *, double *, int *); +int BLASFUNC(xgemm)(char *, char *, int *, int *, int *, double *, + double *, int *, double *, int *, double *, double *, int *); + +int BLASFUNC(cgemm3m)(char *, char *, int *, int *, int *, float *, + float *, int *, float *, int *, float *, float *, int *); +int BLASFUNC(zgemm3m)(char *, char *, int *, int *, int *, double *, + double *, int *, double *, int *, double *, double *, int *); +int BLASFUNC(xgemm3m)(char *, char *, int *, int *, int *, double *, + double *, int *, double *, int *, double *, double *, int *); + +int BLASFUNC(sge2mm)(char *, char *, char *, int *, int *, + float *, float *, int *, float *, int *, + float *, float *, int *); +int BLASFUNC(dge2mm)(char *, char *, char *, int *, int *, + double *, double *, int *, double *, int *, + double *, double *, int *); +int BLASFUNC(cge2mm)(char *, char *, char *, int *, int *, + float *, float *, int *, float *, int *, + float *, float *, int *); +int BLASFUNC(zge2mm)(char *, char *, char *, int *, int *, + double *, double *, int *, double *, int *, + double *, double *, int *); + +int BLASFUNC(strsm)(char *, char *, char *, char *, int *, int *, + float *, float *, int *, float *, int *); +int BLASFUNC(dtrsm)(char *, char *, char *, char *, int *, int *, + double *, double *, int *, double *, int *); +int BLASFUNC(qtrsm)(char *, char *, char *, char *, int *, int *, + double *, double *, int *, double *, int *); +int BLASFUNC(ctrsm)(char *, char *, char *, char *, int *, int *, + float *, float *, int *, float *, int *); +int BLASFUNC(ztrsm)(char *, char *, char *, char *, int *, int *, + double *, double *, int *, double *, int *); +int BLASFUNC(xtrsm)(char *, char *, char *, char *, int *, int *, + double *, double *, int *, double *, int *); + +int BLASFUNC(strmm)(char *, char *, char *, char *, int *, int *, + float *, float *, int *, float *, int *); +int BLASFUNC(dtrmm)(char *, char *, char *, char *, int *, int *, + double *, double *, int *, double *, int *); +int BLASFUNC(qtrmm)(char *, char *, char *, char *, int *, int *, + double *, double *, int *, double *, int *); +int BLASFUNC(ctrmm)(char *, char *, char *, char *, int *, int *, + float *, float *, int *, float *, int *); +int BLASFUNC(ztrmm)(char *, char *, char *, char *, int *, int *, + double *, double *, int *, double *, int *); +int BLASFUNC(xtrmm)(char *, char *, char *, char *, int *, int *, + double *, double *, int *, double *, int *); + +int BLASFUNC(ssymm)(char *, char *, int *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(dsymm)(char *, char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(qsymm)(char *, char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(csymm)(char *, char *, int *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(zsymm)(char *, char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(xsymm)(char *, char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); + +int BLASFUNC(csymm3m)(char *, char *, int *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(zsymm3m)(char *, char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(xsymm3m)(char *, char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); + +int BLASFUNC(ssyrk)(char *, char *, int *, int *, float *, float *, int *, + float *, float *, int *); +int BLASFUNC(dsyrk)(char *, char *, int *, int *, double *, double *, int *, + double *, double *, int *); +int BLASFUNC(qsyrk)(char *, char *, int *, int *, double *, double *, int *, + double *, double *, int *); +int BLASFUNC(csyrk)(char *, char *, int *, int *, float *, float *, int *, + float *, float *, int *); +int BLASFUNC(zsyrk)(char *, char *, int *, int *, double *, double *, int *, + double *, double *, int *); +int BLASFUNC(xsyrk)(char *, char *, int *, int *, double *, double *, int *, + double *, double *, int *); + +int BLASFUNC(ssyr2k)(char *, char *, int *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(dsyr2k)(char *, char *, int *, int *, double *, double *, int *, + double*, int *, double *, double *, int *); +int BLASFUNC(qsyr2k)(char *, char *, int *, int *, double *, double *, int *, + double*, int *, double *, double *, int *); +int BLASFUNC(csyr2k)(char *, char *, int *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(zsyr2k)(char *, char *, int *, int *, double *, double *, int *, + double*, int *, double *, double *, int *); +int BLASFUNC(xsyr2k)(char *, char *, int *, int *, double *, double *, int *, + double*, int *, double *, double *, int *); + +int BLASFUNC(chemm)(char *, char *, int *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(zhemm)(char *, char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(xhemm)(char *, char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); + +int BLASFUNC(chemm3m)(char *, char *, int *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(zhemm3m)(char *, char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); +int BLASFUNC(xhemm3m)(char *, char *, int *, int *, double *, double *, int *, + double *, int *, double *, double *, int *); + +int BLASFUNC(cherk)(char *, char *, int *, int *, float *, float *, int *, + float *, float *, int *); +int BLASFUNC(zherk)(char *, char *, int *, int *, double *, double *, int *, + double *, double *, int *); +int BLASFUNC(xherk)(char *, char *, int *, int *, double *, double *, int *, + double *, double *, int *); + +int BLASFUNC(cher2k)(char *, char *, int *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(zher2k)(char *, char *, int *, int *, double *, double *, int *, + double*, int *, double *, double *, int *); +int BLASFUNC(xher2k)(char *, char *, int *, int *, double *, double *, int *, + double*, int *, double *, double *, int *); +int BLASFUNC(cher2m)(char *, char *, char *, int *, int *, float *, float *, int *, + float *, int *, float *, float *, int *); +int BLASFUNC(zher2m)(char *, char *, char *, int *, int *, double *, double *, int *, + double*, int *, double *, double *, int *); +int BLASFUNC(xher2m)(char *, char *, char *, int *, int *, double *, double *, int *, + double*, int *, double *, double *, int *); + +int BLASFUNC(sgemt)(char *, int *, int *, float *, float *, int *, + float *, int *); +int BLASFUNC(dgemt)(char *, int *, int *, double *, double *, int *, + double *, int *); +int BLASFUNC(cgemt)(char *, int *, int *, float *, float *, int *, + float *, int *); +int BLASFUNC(zgemt)(char *, int *, int *, double *, double *, int *, + double *, int *); + +int BLASFUNC(sgema)(char *, char *, int *, int *, float *, + float *, int *, float *, float *, int *, float *, int *); +int BLASFUNC(dgema)(char *, char *, int *, int *, double *, + double *, int *, double*, double *, int *, double*, int *); +int BLASFUNC(cgema)(char *, char *, int *, int *, float *, + float *, int *, float *, float *, int *, float *, int *); +int BLASFUNC(zgema)(char *, char *, int *, int *, double *, + double *, int *, double*, double *, int *, double*, int *); + +int BLASFUNC(sgems)(char *, char *, int *, int *, float *, + float *, int *, float *, float *, int *, float *, int *); +int BLASFUNC(dgems)(char *, char *, int *, int *, double *, + double *, int *, double*, double *, int *, double*, int *); +int BLASFUNC(cgems)(char *, char *, int *, int *, float *, + float *, int *, float *, float *, int *, float *, int *); +int BLASFUNC(zgems)(char *, char *, int *, int *, double *, + double *, int *, double*, double *, int *, double*, int *); + +int BLASFUNC(sgetf2)(int *, int *, float *, int *, int *, int *); +int BLASFUNC(dgetf2)(int *, int *, double *, int *, int *, int *); +int BLASFUNC(qgetf2)(int *, int *, double *, int *, int *, int *); +int BLASFUNC(cgetf2)(int *, int *, float *, int *, int *, int *); +int BLASFUNC(zgetf2)(int *, int *, double *, int *, int *, int *); +int BLASFUNC(xgetf2)(int *, int *, double *, int *, int *, int *); + +int BLASFUNC(sgetrf)(int *, int *, float *, int *, int *, int *); +int BLASFUNC(dgetrf)(int *, int *, double *, int *, int *, int *); +int BLASFUNC(qgetrf)(int *, int *, double *, int *, int *, int *); +int BLASFUNC(cgetrf)(int *, int *, float *, int *, int *, int *); +int BLASFUNC(zgetrf)(int *, int *, double *, int *, int *, int *); +int BLASFUNC(xgetrf)(int *, int *, double *, int *, int *, int *); + +int BLASFUNC(slaswp)(int *, float *, int *, int *, int *, int *, int *); +int BLASFUNC(dlaswp)(int *, double *, int *, int *, int *, int *, int *); +int BLASFUNC(qlaswp)(int *, double *, int *, int *, int *, int *, int *); +int BLASFUNC(claswp)(int *, float *, int *, int *, int *, int *, int *); +int BLASFUNC(zlaswp)(int *, double *, int *, int *, int *, int *, int *); +int BLASFUNC(xlaswp)(int *, double *, int *, int *, int *, int *, int *); + +int BLASFUNC(sgetrs)(char *, int *, int *, float *, int *, int *, float *, int *, int *); +int BLASFUNC(dgetrs)(char *, int *, int *, double *, int *, int *, double *, int *, int *); +int BLASFUNC(qgetrs)(char *, int *, int *, double *, int *, int *, double *, int *, int *); +int BLASFUNC(cgetrs)(char *, int *, int *, float *, int *, int *, float *, int *, int *); +int BLASFUNC(zgetrs)(char *, int *, int *, double *, int *, int *, double *, int *, int *); +int BLASFUNC(xgetrs)(char *, int *, int *, double *, int *, int *, double *, int *, int *); + +int BLASFUNC(sgesv)(int *, int *, float *, int *, int *, float *, int *, int *); +int BLASFUNC(dgesv)(int *, int *, double *, int *, int *, double*, int *, int *); +int BLASFUNC(qgesv)(int *, int *, double *, int *, int *, double*, int *, int *); +int BLASFUNC(cgesv)(int *, int *, float *, int *, int *, float *, int *, int *); +int BLASFUNC(zgesv)(int *, int *, double *, int *, int *, double*, int *, int *); +int BLASFUNC(xgesv)(int *, int *, double *, int *, int *, double*, int *, int *); + +int BLASFUNC(spotf2)(char *, int *, float *, int *, int *); +int BLASFUNC(dpotf2)(char *, int *, double *, int *, int *); +int BLASFUNC(qpotf2)(char *, int *, double *, int *, int *); +int BLASFUNC(cpotf2)(char *, int *, float *, int *, int *); +int BLASFUNC(zpotf2)(char *, int *, double *, int *, int *); +int BLASFUNC(xpotf2)(char *, int *, double *, int *, int *); + +int BLASFUNC(spotrf)(char *, int *, float *, int *, int *); +int BLASFUNC(dpotrf)(char *, int *, double *, int *, int *); +int BLASFUNC(qpotrf)(char *, int *, double *, int *, int *); +int BLASFUNC(cpotrf)(char *, int *, float *, int *, int *); +int BLASFUNC(zpotrf)(char *, int *, double *, int *, int *); +int BLASFUNC(xpotrf)(char *, int *, double *, int *, int *); + +int BLASFUNC(slauu2)(char *, int *, float *, int *, int *); +int BLASFUNC(dlauu2)(char *, int *, double *, int *, int *); +int BLASFUNC(qlauu2)(char *, int *, double *, int *, int *); +int BLASFUNC(clauu2)(char *, int *, float *, int *, int *); +int BLASFUNC(zlauu2)(char *, int *, double *, int *, int *); +int BLASFUNC(xlauu2)(char *, int *, double *, int *, int *); + +int BLASFUNC(slauum)(char *, int *, float *, int *, int *); +int BLASFUNC(dlauum)(char *, int *, double *, int *, int *); +int BLASFUNC(qlauum)(char *, int *, double *, int *, int *); +int BLASFUNC(clauum)(char *, int *, float *, int *, int *); +int BLASFUNC(zlauum)(char *, int *, double *, int *, int *); +int BLASFUNC(xlauum)(char *, int *, double *, int *, int *); + +int BLASFUNC(strti2)(char *, char *, int *, float *, int *, int *); +int BLASFUNC(dtrti2)(char *, char *, int *, double *, int *, int *); +int BLASFUNC(qtrti2)(char *, char *, int *, double *, int *, int *); +int BLASFUNC(ctrti2)(char *, char *, int *, float *, int *, int *); +int BLASFUNC(ztrti2)(char *, char *, int *, double *, int *, int *); +int BLASFUNC(xtrti2)(char *, char *, int *, double *, int *, int *); + +int BLASFUNC(strtri)(char *, char *, int *, float *, int *, int *); +int BLASFUNC(dtrtri)(char *, char *, int *, double *, int *, int *); +int BLASFUNC(qtrtri)(char *, char *, int *, double *, int *, int *); +int BLASFUNC(ctrtri)(char *, char *, int *, float *, int *, int *); +int BLASFUNC(ztrtri)(char *, char *, int *, double *, int *, int *); +int BLASFUNC(xtrtri)(char *, char *, int *, double *, int *, int *); + +int BLASFUNC(spotri)(char *, int *, float *, int *, int *); +int BLASFUNC(dpotri)(char *, int *, double *, int *, int *); +int BLASFUNC(qpotri)(char *, int *, double *, int *, int *); +int BLASFUNC(cpotri)(char *, int *, float *, int *, int *); +int BLASFUNC(zpotri)(char *, int *, double *, int *, int *); +int BLASFUNC(xpotri)(char *, int *, double *, int *, int *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h b/extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h index 7d509e78f3a..5b979ebf89d 100644 --- a/extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h +++ b/extern/Eigen3/Eigen/src/plugins/ArrayCwiseBinaryOps.h @@ -29,6 +29,16 @@ operator/(const EIGEN_CURRENT_STORAGE_BASE_CLASS &other) const */ EIGEN_MAKE_CWISE_BINARY_OP(min,internal::scalar_min_op) +/** \returns an expression of the coefficient-wise min of \c *this and scalar \a other + * + * \sa max() + */ +EIGEN_STRONG_INLINE const CwiseBinaryOp, const Derived, const ConstantReturnType> +(min)(const Scalar &other) const +{ + return (min)(Derived::PlainObject::Constant(rows(), cols(), other)); +} + /** \returns an expression of the coefficient-wise max of \c *this and \a other * * Example: \include Cwise_max.cpp @@ -38,6 +48,16 @@ EIGEN_MAKE_CWISE_BINARY_OP(min,internal::scalar_min_op) */ EIGEN_MAKE_CWISE_BINARY_OP(max,internal::scalar_max_op) +/** \returns an expression of the coefficient-wise max of \c *this and scalar \a other + * + * \sa min() + */ +EIGEN_STRONG_INLINE const CwiseBinaryOp, const Derived, const ConstantReturnType> +(max)(const Scalar &other) const +{ + return (max)(Derived::PlainObject::Constant(rows(), cols(), other)); +} + /** \returns an expression of the coefficient-wise \< operator of *this and \a other * * Example: \include Cwise_less.cpp @@ -141,3 +161,39 @@ operator-(const Scalar& scalar,const EIGEN_CURRENT_STORAGE_BASE_CLASS& { return (-other) + scalar; } + +/** \returns an expression of the coefficient-wise && operator of *this and \a other + * + * \warning this operator is for expression of bool only. + * + * Example: \include Cwise_boolean_and.cpp + * Output: \verbinclude Cwise_boolean_and.out + * + * \sa operator||(), select() + */ +template +inline const CwiseBinaryOp +operator&&(const EIGEN_CURRENT_STORAGE_BASE_CLASS &other) const +{ + EIGEN_STATIC_ASSERT((internal::is_same::value && internal::is_same::value), + THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL); + return CwiseBinaryOp(derived(),other.derived()); +} + +/** \returns an expression of the coefficient-wise || operator of *this and \a other + * + * \warning this operator is for expression of bool only. + * + * Example: \include Cwise_boolean_or.cpp + * Output: \verbinclude Cwise_boolean_or.out + * + * \sa operator&&(), select() + */ +template +inline const CwiseBinaryOp +operator||(const EIGEN_CURRENT_STORAGE_BASE_CLASS &other) const +{ + EIGEN_STATIC_ASSERT((internal::is_same::value && internal::is_same::value), + THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL); + return CwiseBinaryOp(derived(),other.derived()); +} diff --git a/extern/Eigen3/Eigen/src/plugins/BlockMethods.h b/extern/Eigen3/Eigen/src/plugins/BlockMethods.h index 4eba933388a..ef224001a54 100644 --- a/extern/Eigen3/Eigen/src/plugins/BlockMethods.h +++ b/extern/Eigen3/Eigen/src/plugins/BlockMethods.h @@ -4,24 +4,9 @@ // Copyright (C) 2008-2010 Gael Guennebaud // Copyright (C) 2006-2010 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_BLOCKMETHODS_H #define EIGEN_BLOCKMETHODS_H diff --git a/extern/Eigen3/Eigen/src/plugins/CommonCwiseBinaryOps.h b/extern/Eigen3/Eigen/src/plugins/CommonCwiseBinaryOps.h index 8f7765e72bd..688d2244088 100644 --- a/extern/Eigen3/Eigen/src/plugins/CommonCwiseBinaryOps.h +++ b/extern/Eigen3/Eigen/src/plugins/CommonCwiseBinaryOps.h @@ -4,24 +4,9 @@ // Copyright (C) 2008-2009 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. // This file is a base class plugin containing common coefficient wise functions. diff --git a/extern/Eigen3/Eigen/src/plugins/CommonCwiseUnaryOps.h b/extern/Eigen3/Eigen/src/plugins/CommonCwiseUnaryOps.h index 941d5153c59..08e931aaddd 100644 --- a/extern/Eigen3/Eigen/src/plugins/CommonCwiseUnaryOps.h +++ b/extern/Eigen3/Eigen/src/plugins/CommonCwiseUnaryOps.h @@ -4,24 +4,9 @@ // Copyright (C) 2008-2009 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. // This file is a base class plugin containing common coefficient wise functions. diff --git a/extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h b/extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h index 35183f91f80..3a737df7b86 100644 --- a/extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h +++ b/extern/Eigen3/Eigen/src/plugins/MatrixCwiseBinaryOps.h @@ -4,24 +4,9 @@ // Copyright (C) 2008-2009 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. // This file is a base class plugin containing matrix specifics coefficient wise functions. @@ -91,6 +76,16 @@ cwiseMin(const EIGEN_CURRENT_STORAGE_BASE_CLASS &other) const return CwiseBinaryOp, const Derived, const OtherDerived>(derived(), other.derived()); } +/** \returns an expression of the coefficient-wise min of *this and scalar \a other + * + * \sa class CwiseBinaryOp, min() + */ +EIGEN_STRONG_INLINE const CwiseBinaryOp, const Derived, const ConstantReturnType> +cwiseMin(const Scalar &other) const +{ + return cwiseMin(Derived::PlainObject::Constant(rows(), cols(), other)); +} + /** \returns an expression of the coefficient-wise max of *this and \a other * * Example: \include MatrixBase_cwiseMax.cpp @@ -105,6 +100,17 @@ cwiseMax(const EIGEN_CURRENT_STORAGE_BASE_CLASS &other) const return CwiseBinaryOp, const Derived, const OtherDerived>(derived(), other.derived()); } +/** \returns an expression of the coefficient-wise max of *this and scalar \a other + * + * \sa class CwiseBinaryOp, min() + */ +EIGEN_STRONG_INLINE const CwiseBinaryOp, const Derived, const ConstantReturnType> +cwiseMax(const Scalar &other) const +{ + return cwiseMax(Derived::PlainObject::Constant(rows(), cols(), other)); +} + + /** \returns an expression of the coefficient-wise quotient of *this and \a other * * Example: \include MatrixBase_cwiseQuotient.cpp diff --git a/extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h b/extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h index a3d9a0e1465..0cf0640bae6 100644 --- a/extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h +++ b/extern/Eigen3/Eigen/src/plugins/MatrixCwiseUnaryOps.h @@ -4,24 +4,9 @@ // Copyright (C) 2008-2009 Gael Guennebaud // Copyright (C) 2006-2008 Benoit Jacob // -// Eigen is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 3 of the License, or (at your option) any later version. -// -// Alternatively, 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. -// -// Eigen 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 Lesser General Public License or the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License and a copy of the GNU General Public License along with -// Eigen. If not, see . +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. // This file is a base class plugin containing matrix specifics coefficient wise functions. diff --git a/extern/bullet2/patches/convex_hull.patch b/extern/bullet2/patches/convex_hull.patch new file mode 100644 index 00000000000..1b2978221fb --- /dev/null +++ b/extern/bullet2/patches/convex_hull.patch @@ -0,0 +1,127 @@ +Index: extern/bullet2/src/Bullet-C-Api.h +=================================================================== +--- extern/bullet2/src/Bullet-C-Api.h (revision 51556) ++++ extern/bullet2/src/Bullet-C-Api.h (working copy) +@@ -167,6 +167,16 @@ extern "C" { + // needed for source/blender/blenkernel/intern/collision.c + double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]); + ++ ++ /* Convex Hull */ ++ PL_DECLARE_HANDLE(plConvexHull); ++ plConvexHull plConvexHullCompute(float (*coords)[3], int count); ++ int plConvexHullNumVertices(plConvexHull hull); ++ int plConvexHullNumFaces(plConvexHull hull); ++ void plConvexHullGetVertex(plConvexHull hull, int n, float coords[3], int *original_index); ++ int plConvexHullGetFaceSize(plConvexHull hull, int n); ++ void plConvexHullGetFaceVertices(plConvexHull hull, int n, int *vertices); ++ + #ifdef __cplusplus + } + #endif +Index: extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp +=================================================================== +--- extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp (revision 51556) ++++ extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp (working copy) +@@ -23,7 +23,7 @@ subject to the following restrictions: + #include "Bullet-C-Api.h" + #include "btBulletDynamicsCommon.h" + #include "LinearMath/btAlignedAllocator.h" +- ++#include "LinearMath/btConvexHullComputer.h" + + + #include "LinearMath/btVector3.h" +@@ -403,3 +403,60 @@ double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float + return -1.0f; + } + ++// Convex hull ++plConvexHull plConvexHullCompute(float (*coords)[3], int count) ++{ ++ btConvexHullComputer *computer = new btConvexHullComputer; ++ computer->compute(reinterpret_cast< float* >(coords), ++ sizeof(*coords), count, 0, 0); ++ return reinterpret_cast(computer); ++} ++ ++int plConvexHullNumVertices(plConvexHull hull) ++{ ++ btConvexHullComputer *computer(reinterpret_cast< btConvexHullComputer* >(hull)); ++ return computer->vertices.size(); ++} ++ ++int plConvexHullNumFaces(plConvexHull hull) ++{ ++ btConvexHullComputer *computer(reinterpret_cast< btConvexHullComputer* >(hull)); ++ return computer->faces.size(); ++} ++ ++void plConvexHullGetVertex(plConvexHull hull, int n, float coords[3], ++ int *original_index) ++{ ++ btConvexHullComputer *computer(reinterpret_cast< btConvexHullComputer* >(hull)); ++ const btVector3 &v(computer->vertices[n]); ++ coords[0] = v[0]; ++ coords[1] = v[1]; ++ coords[2] = v[2]; ++ (*original_index) = computer->original_vertex_index[n]; ++} ++ ++int plConvexHullGetFaceSize(plConvexHull hull, int n) ++{ ++ btConvexHullComputer *computer(reinterpret_cast< btConvexHullComputer* >(hull)); ++ const btConvexHullComputer::Edge *e_orig, *e; ++ int count; ++ ++ for (e_orig = &computer->edges[computer->faces[n]], e = e_orig, count = 0; ++ count == 0 || e != e_orig; ++ e = e->getNextEdgeOfFace(), count++); ++ return count; ++} ++ ++void plConvexHullGetFaceVertices(plConvexHull hull, int n, int *vertices) ++{ ++ btConvexHullComputer *computer(reinterpret_cast< btConvexHullComputer* >(hull)); ++ const btConvexHullComputer::Edge *e_orig, *e; ++ int count; ++ ++ for (e_orig = &computer->edges[computer->faces[n]], e = e_orig, count = 0; ++ count == 0 || e != e_orig; ++ e = e->getNextEdgeOfFace(), count++) ++ { ++ vertices[count] = e->getTargetVertex(); ++ } ++} +Index: extern/bullet2/src/LinearMath/btConvexHullComputer.cpp +=================================================================== +--- extern/bullet2/src/LinearMath/btConvexHullComputer.cpp (revision 51556) ++++ extern/bullet2/src/LinearMath/btConvexHullComputer.cpp (working copy) +@@ -2661,6 +2661,7 @@ btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, in + } + + vertices.resize(0); ++ original_vertex_index.resize(0); + edges.resize(0); + faces.resize(0); + +@@ -2671,6 +2672,7 @@ btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, in + { + btConvexHullInternal::Vertex* v = oldVertices[copied]; + vertices.push_back(hull.getCoordinates(v)); ++ original_vertex_index.push_back(v->point.index); + btConvexHullInternal::Edge* firstEdge = v->edges; + if (firstEdge) + { +Index: extern/bullet2/src/LinearMath/btConvexHullComputer.h +=================================================================== +--- extern/bullet2/src/LinearMath/btConvexHullComputer.h (revision 51556) ++++ extern/bullet2/src/LinearMath/btConvexHullComputer.h (working copy) +@@ -67,6 +67,7 @@ class btConvexHullComputer + + // Vertices of the output hull + btAlignedObjectArray vertices; ++ btAlignedObjectArray original_vertex_index; + + // Edges of the output hull + btAlignedObjectArray edges; diff --git a/extern/bullet2/readme.txt b/extern/bullet2/readme.txt index 343cb104c4d..7f5a7f1e163 100644 --- a/extern/bullet2/readme.txt +++ b/extern/bullet2/readme.txt @@ -14,6 +14,8 @@ Apply patches/make_id.patch to prevent duplicated define of MAKE_ID macro in ble side and bullet side. Sergey -Apply patches/ghost_character.path to prevent characters from colliding with ghost objects. +Apply patches/ghost_character.patch to prevent characters from colliding with ghost objects. Mitchell +Apply patches/convex_hull.patch to add access to the convex hull +operation, used in the BMesh convex hull operator. diff --git a/extern/bullet2/src/Bullet-C-Api.h b/extern/bullet2/src/Bullet-C-Api.h index f27a17d51f7..2eabf3840e1 100644 --- a/extern/bullet2/src/Bullet-C-Api.h +++ b/extern/bullet2/src/Bullet-C-Api.h @@ -167,6 +167,16 @@ extern "C" { // needed for source/blender/blenkernel/intern/collision.c double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]); + + /* Convex Hull */ + PL_DECLARE_HANDLE(plConvexHull); + plConvexHull plConvexHullCompute(float (*coords)[3], int count); + int plConvexHullNumVertices(plConvexHull hull); + int plConvexHullNumFaces(plConvexHull hull); + void plConvexHullGetVertex(plConvexHull hull, int n, float coords[3], int *original_index); + int plConvexHullGetFaceSize(plConvexHull hull, int n); + void plConvexHullGetFaceVertices(plConvexHull hull, int n, int *vertices); + #ifdef __cplusplus } #endif diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp index bd8e2748383..cf735569a9d 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp @@ -23,7 +23,7 @@ subject to the following restrictions: #include "Bullet-C-Api.h" #include "btBulletDynamicsCommon.h" #include "LinearMath/btAlignedAllocator.h" - +#include "LinearMath/btConvexHullComputer.h" #include "LinearMath/btVector3.h" @@ -403,3 +403,60 @@ double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float return -1.0f; } +// Convex hull +plConvexHull plConvexHullCompute(float (*coords)[3], int count) +{ + btConvexHullComputer *computer = new btConvexHullComputer; + computer->compute(reinterpret_cast< float* >(coords), + sizeof(*coords), count, 0, 0); + return reinterpret_cast(computer); +} + +int plConvexHullNumVertices(plConvexHull hull) +{ + btConvexHullComputer *computer(reinterpret_cast< btConvexHullComputer* >(hull)); + return computer->vertices.size(); +} + +int plConvexHullNumFaces(plConvexHull hull) +{ + btConvexHullComputer *computer(reinterpret_cast< btConvexHullComputer* >(hull)); + return computer->faces.size(); +} + +void plConvexHullGetVertex(plConvexHull hull, int n, float coords[3], + int *original_index) +{ + btConvexHullComputer *computer(reinterpret_cast< btConvexHullComputer* >(hull)); + const btVector3 &v(computer->vertices[n]); + coords[0] = v[0]; + coords[1] = v[1]; + coords[2] = v[2]; + (*original_index) = computer->original_vertex_index[n]; +} + +int plConvexHullGetFaceSize(plConvexHull hull, int n) +{ + btConvexHullComputer *computer(reinterpret_cast< btConvexHullComputer* >(hull)); + const btConvexHullComputer::Edge *e_orig, *e; + int count; + + for (e_orig = &computer->edges[computer->faces[n]], e = e_orig, count = 0; + count == 0 || e != e_orig; + e = e->getNextEdgeOfFace(), count++); + return count; +} + +void plConvexHullGetFaceVertices(plConvexHull hull, int n, int *vertices) +{ + btConvexHullComputer *computer(reinterpret_cast< btConvexHullComputer* >(hull)); + const btConvexHullComputer::Edge *e_orig, *e; + int count; + + for (e_orig = &computer->edges[computer->faces[n]], e = e_orig, count = 0; + count == 0 || e != e_orig; + e = e->getNextEdgeOfFace(), count++) + { + vertices[count] = e->getTargetVertex(); + } +} diff --git a/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp b/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp index c03c901c051..4fd81dac107 100644 --- a/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp +++ b/extern/bullet2/src/LinearMath/btConvexHullComputer.cpp @@ -2661,6 +2661,7 @@ btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, in } vertices.resize(0); + original_vertex_index.resize(0); edges.resize(0); faces.resize(0); @@ -2671,6 +2672,7 @@ btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, in { btConvexHullInternal::Vertex* v = oldVertices[copied]; vertices.push_back(hull.getCoordinates(v)); + original_vertex_index.push_back(v->point.index); btConvexHullInternal::Edge* firstEdge = v->edges; if (firstEdge) { diff --git a/extern/bullet2/src/LinearMath/btConvexHullComputer.h b/extern/bullet2/src/LinearMath/btConvexHullComputer.h index 7240ac4fb52..6871ce80e00 100644 --- a/extern/bullet2/src/LinearMath/btConvexHullComputer.h +++ b/extern/bullet2/src/LinearMath/btConvexHullComputer.h @@ -67,6 +67,7 @@ class btConvexHullComputer // Vertices of the output hull btAlignedObjectArray vertices; + btAlignedObjectArray original_vertex_index; // Edges of the output hull btAlignedObjectArray edges; diff --git a/extern/carve/CMakeLists.txt b/extern/carve/CMakeLists.txt index 3916047ff32..5e917ac1e44 100644 --- a/extern/carve/CMakeLists.txt +++ b/extern/carve/CMakeLists.txt @@ -158,7 +158,7 @@ if(WITH_BOOST) -DCARVE_SYSTEM_BOOST ) - list(APPEND INC + list(APPEND INC_SYS ${BOOST_INCLUDE_DIR} ) endif() diff --git a/extern/libmv/CMakeLists.txt b/extern/libmv/CMakeLists.txt index 60cd84d89d4..38be34add75 100644 --- a/extern/libmv/CMakeLists.txt +++ b/extern/libmv/CMakeLists.txt @@ -28,31 +28,18 @@ set(INC . - ../Eigen3 - third_party/ssba - third_party/ldl/Include ../colamd/Include third_party/ceres/include ) set(INC_SYS + ../Eigen3 + third_party/ssba + third_party/ldl/Include ${PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIRS} ) - -# XXX - FIXME -# this is a momentary hack to find unwind.h in 10.6.sdk -if(APPLE) - if(${CMAKE_OSX_DEPLOYMENT_TARGET} STREQUAL "10.6") - list(APPEND INC_SYS - ${CMAKE_OSX_SYSROOT}/Developer/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin10/4.2.1/include - ) - endif() -endif() -# XXX - END - - set(SRC libmv-capi.cpp libmv/image/array_nd.cc diff --git a/extern/libmv/bundle.sh b/extern/libmv/bundle.sh index 3f877508c46..1e386ec8096 100755 --- a/extern/libmv/bundle.sh +++ b/extern/libmv/bundle.sh @@ -124,14 +124,14 @@ cat > CMakeLists.txt << EOF set(INC . - ../Eigen3 - third_party/ssba - third_party/ldl/Include ../colamd/Include third_party/ceres/include ) set(INC_SYS + ../Eigen3 + third_party/ssba + third_party/ldl/Include \${PNG_INCLUDE_DIR} \${ZLIB_INCLUDE_DIRS} ) diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index 3d3b7398c9b..a15927f881d 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -523,7 +523,7 @@ int libmv_refineParametersAreValid(int parameters) { LIBMV_REFINE_RADIAL_DISTORTION_K1)); } -void libmv_solveRefineIntrinsics(libmv::Tracks *tracks, libmv::CameraIntrinsics *intrinsics, +static void libmv_solveRefineIntrinsics(libmv::Tracks *tracks, libmv::CameraIntrinsics *intrinsics, libmv::EuclideanReconstruction *reconstruction, int refine_intrinsics, reconstruct_progress_update_cb progress_update_callback, void *callback_customdata) { @@ -550,7 +550,8 @@ void libmv_solveRefineIntrinsics(libmv::Tracks *tracks, libmv::CameraIntrinsics } libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyframe1, int keyframe2, - int refine_intrinsics, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, + int refine_intrinsics, double focal_length, double principal_x, double principal_y, + double k1, double k2, double k3, struct libmv_reconstructionOptions *options, reconstruct_progress_update_cb progress_update_callback, void *callback_customdata) { /* Invert the camera intrinsics. */ @@ -558,6 +559,7 @@ libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyfra libmv_Reconstruction *libmv_reconstruction = new libmv_Reconstruction(); libmv::EuclideanReconstruction *reconstruction = &libmv_reconstruction->reconstruction; libmv::CameraIntrinsics *intrinsics = &libmv_reconstruction->intrinsics; + libmv::ReconstructionOptions reconstruction_options; ReconstructUpdateCallback update_callback = ReconstructUpdateCallback(progress_update_callback, callback_customdata); @@ -566,6 +568,9 @@ libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyfra intrinsics->SetPrincipalPoint(principal_x, principal_y); intrinsics->SetRadialDistortion(k1, k2, k3); + reconstruction_options.success_threshold = options->success_threshold; + reconstruction_options.use_fallback_reconstruction = options->use_fallback_reconstruction; + for (int i = 0; i < markers.size(); ++i) { intrinsics->InvertIntrinsics(markers[i].x, markers[i].y, @@ -584,7 +589,8 @@ libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyfra libmv::EuclideanReconstructTwoFrames(keyframe_markers, reconstruction); libmv::EuclideanBundle(normalized_tracks, reconstruction); - libmv::EuclideanCompleteReconstruction(normalized_tracks, reconstruction, &update_callback); + libmv::EuclideanCompleteReconstruction(reconstruction_options, normalized_tracks, + reconstruction, &update_callback); if (refine_intrinsics) { libmv_solveRefineIntrinsics((libmv::Tracks *)tracks, intrinsics, reconstruction, @@ -1027,7 +1033,7 @@ void libmv_InvertIntrinsics(double focal_length, double principal_x, double prin /* ************ point clouds ************ */ -void libmvTransformToMat4(libmv::Mat3 &R, libmv::Vec3 &S, libmv::Vec3 &t, double M[4][4]) +static void libmvTransformToMat4(libmv::Mat3 &R, libmv::Vec3 &S, libmv::Vec3 &t, double M[4][4]) { for (int j = 0; j < 3; ++j) for (int k = 0; k < 3; ++k) diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h index fc3b6f94f62..e5885e7addf 100644 --- a/extern/libmv/libmv-capi.h +++ b/extern/libmv/libmv-capi.h @@ -91,13 +91,20 @@ void libmv_tracksDestroy(struct libmv_Tracks *libmv_tracks); #define LIBMV_REFINE_RADIAL_DISTORTION_K1 (1<<2) #define LIBMV_REFINE_RADIAL_DISTORTION_K2 (1<<4) +/* TODO: make keyframes/distortion model a part of options? */ +struct libmv_reconstructionOptions { + double success_threshold; + int use_fallback_reconstruction; +}; + typedef void (*reconstruct_progress_update_cb) (void *customdata, double progress, const char *message); int libmv_refineParametersAreValid(int parameters); struct libmv_Reconstruction *libmv_solveReconstruction(struct libmv_Tracks *tracks, int keyframe1, int keyframe2, int refine_intrinsics, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, - reconstruct_progress_update_cb progress_update_callback, void *callback_customdata); + struct libmv_reconstructionOptions *options, reconstruct_progress_update_cb progress_update_callback, + void *callback_customdata); struct libmv_Reconstruction *libmv_solveModal(struct libmv_Tracks *tracks, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, reconstruct_progress_update_cb progress_update_callback, void *callback_customdata); @@ -147,14 +154,14 @@ void libmv_CameraIntrinsicsDistortFloat(struct libmv_CameraIntrinsics *libmvIntr /* dsitortion */ void libmv_undistortByte(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, - unsigned char *src, unsigned char *dst, int width, int height, int channels); + unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels); void libmv_undistortFloat(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, - float *src, float *dst, int width, int height, int channels); + float *src, float *dst, int width, int height, float overscan, int channels); void libmv_distortByte(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, - unsigned char *src, unsigned char *dst, int width, int height, int channels); + unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels); void libmv_distortFloat(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, - float *src, float *dst, int width, int height, int channels); + float *src, float *dst, int width, int height, float overscan, int channels); /* utils */ void libmv_applyCameraIntrinsics(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3, diff --git a/extern/libmv/libmv/multiview/euclidean_resection.cc b/extern/libmv/libmv/multiview/euclidean_resection.cc index 92862515d7e..2605bf04622 100644 --- a/extern/libmv/libmv/multiview/euclidean_resection.cc +++ b/extern/libmv/libmv/multiview/euclidean_resection.cc @@ -37,13 +37,14 @@ typedef unsigned int uint; bool EuclideanResection(const Mat2X &x_camera, const Mat3X &X_world, Mat3 *R, Vec3 *t, - ResectionMethod method) { + ResectionMethod method, + double success_threshold) { switch (method) { case RESECTION_ANSAR_DANIILIDIS: EuclideanResectionAnsarDaniilidis(x_camera, X_world, R, t); break; case RESECTION_EPNP: - return EuclideanResectionEPnP(x_camera, X_world, R, t); + return EuclideanResectionEPnP(x_camera, X_world, R, t, success_threshold); break; default: LOG(FATAL) << "Unknown resection method."; @@ -351,9 +352,9 @@ void EuclideanResectionAnsarDaniilidis(const Mat2X &x_camera, } // Selects 4 virtual control points using mean and PCA. -void SelectControlPoints(const Mat3X &X_world, - Mat *X_centered, - Mat34 *X_control_points) { +static void SelectControlPoints(const Mat3X &X_world, + Mat *X_centered, + Mat34 *X_control_points) { size_t num_points = X_world.cols(); // The first virtual control point, C0, is the centroid. @@ -377,9 +378,9 @@ void SelectControlPoints(const Mat3X &X_world, } // Computes the barycentric coordinates for all real points -void ComputeBarycentricCoordinates(const Mat3X &X_world_centered, - const Mat34 &X_control_points, - Mat4X *alphas) { +static void ComputeBarycentricCoordinates(const Mat3X &X_world_centered, + const Mat34 &X_control_points, + Mat4X *alphas) { size_t num_points = X_world_centered.cols(); Mat3 C2 ; for (size_t c = 1; c < 4; c++) { @@ -398,7 +399,7 @@ void ComputeBarycentricCoordinates(const Mat3X &X_world_centered, } // Estimates the coordinates of all real points in the camera coordinate frame -void ComputePointsCoordinatesInCameraFrame( +static void ComputePointsCoordinatesInCameraFrame( const Mat4X &alphas, const Vec4 &betas, const Eigen::Matrix &U, @@ -435,8 +436,9 @@ void ComputePointsCoordinatesInCameraFrame( } bool EuclideanResectionEPnP(const Mat2X &x_camera, - const Mat3X &X_world, - Mat3 *R, Vec3 *t) { + const Mat3X &X_world, + Mat3 *R, Vec3 *t, + double success_threshold) { CHECK(x_camera.cols() == X_world.cols()); CHECK(x_camera.cols() > 3); size_t num_points = X_world.cols(); @@ -535,7 +537,21 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera, vector ts(3); Vec rmse(3); - // TODO(julien): Document where the "1e-3" magical constant comes from below. + // At one point this threshold was 1e-3, and caused no end of problems in + // Blender by causing frames to not resect when they would have worked fine. + // When the resect failed, the projective followup is run leading to worse + // results, and often the dreaded "flipping" where objects get flipped + // between frames. Instead, disable the check for now, always succeeding. The + // ultimate check is always reprojection error anyway. + // + // TODO(keir): Decide if setting this to infinity, effectively disabling the + // check, is the right approach. So far this seems the case. + // + // TODO(sergey): Made it an option for now, in some cases it makes sense to + // still fallback to reprojection solution (see bug [#32765] from Blender bug tracker) + + // double kSuccessThreshold = std::numeric_limits::max(); + double kSuccessThreshold = success_threshold; // Find the first possible solution for R, t corresponding to: // Betas = [b00 b01 b11 b02 b12 b22 b03 b13 b23 b33] @@ -548,7 +564,7 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera, Eigen::JacobiSVD svd_of_l4(l_6x4, Eigen::ComputeFullU | Eigen::ComputeFullV); Vec4 b4 = svd_of_l4.solve(rho); - if ((l_6x4 * b4).isApprox(rho, 1e-3)) { + if ((l_6x4 * b4).isApprox(rho, kSuccessThreshold)) { if (b4(0) < 0) { b4 = -b4; } @@ -574,7 +590,7 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera, Vec3 b3 = svdOfL3.solve(rho); VLOG(2) << " rho = " << rho; VLOG(2) << " l_6x3 * b3 = " << l_6x3 * b3; - if ((l_6x3 * b3).isApprox(rho, 1e-3)) { + if ((l_6x3 * b3).isApprox(rho, kSuccessThreshold)) { if (b3(0) < 0) { betas(0) = std::sqrt(-b3(0)); betas(1) = (b3(2) < 0) ? std::sqrt(-b3(2)) : 0; @@ -605,7 +621,7 @@ bool EuclideanResectionEPnP(const Mat2X &x_camera, Eigen::JacobiSVD svdOfL5(l_6x5, Eigen::ComputeFullU | Eigen::ComputeFullV); Vec5 b5 = svdOfL5.solve(rho); - if ((l_6x5 * b5).isApprox(rho, 1e-3)) { + if ((l_6x5 * b5).isApprox(rho, kSuccessThreshold)) { if (b5(0) < 0) { betas(0) = std::sqrt(-b5(0)); if (b5(2) < 0) { diff --git a/extern/libmv/libmv/multiview/euclidean_resection.h b/extern/libmv/libmv/multiview/euclidean_resection.h index 08fa3d90bd3..b0428ec61fd 100644 --- a/extern/libmv/libmv/multiview/euclidean_resection.h +++ b/extern/libmv/libmv/multiview/euclidean_resection.h @@ -29,6 +29,9 @@ namespace euclidean_resection { enum ResectionMethod { RESECTION_ANSAR_DANIILIDIS, + + // The "EPnP" algorithm by Lepetit et al. + // http://cvlab.epfl.ch/~lepetit/papers/lepetit_ijcv08.pdf RESECTION_EPNP, }; @@ -42,11 +45,14 @@ enum ResectionMethod { * \param R Solution for the camera rotation matrix * \param t Solution for the camera translation vector * \param method The resection method to use. + * \param success_threshold Threshold of an error which is still considered a success + * (currently used by EPnP algorithm only) */ bool EuclideanResection(const Mat2X &x_camera, const Mat3X &X_world, Mat3 *R, Vec3 *t, - ResectionMethod method = RESECTION_EPNP); + ResectionMethod method = RESECTION_EPNP, + double success_threshold = 1e-3); /** * Computes the extrinsic parameters, R and t for a calibrated camera @@ -107,6 +113,7 @@ void EuclideanResectionAnsarDaniilidis(const Mat2X &x_camera, * \param X_world 3D points in the world coordinate system * \param R Solution for the camera rotation matrix * \param t Solution for the camera translation vector + * \param success_threshold Threshold of an error which is still considered a success * * This is the algorithm described in: * "{EP$n$P: An Accurate $O(n)$ Solution to the P$n$P Problem", by V. Lepetit @@ -115,7 +122,8 @@ void EuclideanResectionAnsarDaniilidis(const Mat2X &x_camera, */ bool EuclideanResectionEPnP(const Mat2X &x_camera, const Mat3X &X_world, - Mat3 *R, Vec3 *t); + Mat3 *R, Vec3 *t, + double success_threshold = 1e-3); } // namespace euclidean_resection } // namespace libmv diff --git a/extern/libmv/libmv/multiview/fundamental.cc b/extern/libmv/libmv/multiview/fundamental.cc index 7a6b4a08439..80f155e804d 100644 --- a/extern/libmv/libmv/multiview/fundamental.cc +++ b/extern/libmv/libmv/multiview/fundamental.cc @@ -28,7 +28,7 @@ namespace libmv { -void EliminateRow(const Mat34 &P, int row, Mat *X) { +static void EliminateRow(const Mat34 &P, int row, Mat *X) { X->resize(2, 4); int first_row = (row + 1) % 3; @@ -69,7 +69,7 @@ void FundamentalFromProjections(const Mat34 &P1, const Mat34 &P2, Mat3 *F) { // HZ 11.1 pag.279 (x1 = x, x2 = x') // http://www.cs.unc.edu/~marc/tutorial/node54.html -double EightPointSolver(const Mat &x1, const Mat &x2, Mat3 *F) { +static double EightPointSolver(const Mat &x1, const Mat &x2, Mat3 *F) { DCHECK_EQ(x1.rows(), 2); DCHECK_GE(x1.cols(), 8); DCHECK_EQ(x1.rows(), x2.rows()); diff --git a/extern/libmv/libmv/multiview/homography.cc b/extern/libmv/libmv/multiview/homography.cc index 366392f3923..b5c483998d8 100644 --- a/extern/libmv/libmv/multiview/homography.cc +++ b/extern/libmv/libmv/multiview/homography.cc @@ -40,7 +40,7 @@ namespace libmv { * (a-x1*g)*y1 + (b-x1*h)*y2 + c-x1 = |0| * (-x2*a+x1*d)*y1 + (-x2*b+x1*e)*y2 + -x2*c+x1*f |0| */ -bool Homography2DFromCorrespondencesLinearEuc( +static bool Homography2DFromCorrespondencesLinearEuc( const Mat &x1, const Mat &x2, Mat3 *H, diff --git a/extern/libmv/libmv/numeric/levenberg_marquardt.h b/extern/libmv/libmv/numeric/levenberg_marquardt.h index 4473b72f156..a7877e0270b 100644 --- a/extern/libmv/libmv/numeric/levenberg_marquardt.h +++ b/extern/libmv/libmv/numeric/levenberg_marquardt.h @@ -124,11 +124,11 @@ class LevenbergMarquardt { Parameters dx, x_new; int i; for (i = 0; results.status == RUNNING && i < params.max_iterations; ++i) { - VLOG(1) << "iteration: " << i; - VLOG(1) << "||f(x)||: " << f_(x).norm(); - VLOG(1) << "max(g): " << g.array().abs().maxCoeff(); - VLOG(1) << "u: " << u; - VLOG(1) << "v: " << v; + VLOG(3) << "iteration: " << i; + VLOG(3) << "||f(x)||: " << f_(x).norm(); + VLOG(3) << "max(g): " << g.array().abs().maxCoeff(); + VLOG(3) << "u: " << u; + VLOG(3) << "v: " << v; AMatrixType A_augmented = A + u*AMatrixType::Identity(J.cols(), J.cols()); Solver solver(A_augmented); diff --git a/extern/libmv/libmv/simple_pipeline/detect.cc b/extern/libmv/libmv/simple_pipeline/detect.cc index 8a093dadeca..9e3edf32d71 100644 --- a/extern/libmv/libmv/simple_pipeline/detect.cc +++ b/extern/libmv/libmv/simple_pipeline/detect.cc @@ -35,7 +35,7 @@ namespace libmv { typedef unsigned int uint; -int featurecmp(const void *a_v, const void *b_v) +static int featurecmp(const void *a_v, const void *b_v) { Feature *a = (Feature*)a_v; Feature *b = (Feature*)b_v; diff --git a/extern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc b/extern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc index 77fe2a530c4..9c06d1ef4e6 100644 --- a/extern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc +++ b/extern/libmv/libmv/simple_pipeline/initialize_reconstruction.cc @@ -24,6 +24,7 @@ #include "libmv/multiview/projection.h" #include "libmv/numeric/levenberg_marquardt.h" #include "libmv/numeric/numeric.h" +#include "libmv/simple_pipeline/initialize_reconstruction.h" #include "libmv/simple_pipeline/reconstruction.h" #include "libmv/simple_pipeline/tracks.h" diff --git a/extern/libmv/libmv/simple_pipeline/intersect.cc b/extern/libmv/libmv/simple_pipeline/intersect.cc index b1518e04651..0c2f744dc1c 100644 --- a/extern/libmv/libmv/simple_pipeline/intersect.cc +++ b/extern/libmv/libmv/simple_pipeline/intersect.cc @@ -26,6 +26,7 @@ #include "libmv/multiview/projection.h" #include "libmv/numeric/numeric.h" #include "libmv/numeric/levenberg_marquardt.h" +#include "libmv/simple_pipeline/intersect.h" #include "libmv/simple_pipeline/reconstruction.h" #include "libmv/simple_pipeline/tracks.h" diff --git a/extern/libmv/libmv/simple_pipeline/pipeline.cc b/extern/libmv/libmv/simple_pipeline/pipeline.cc index 2459d059114..efceda5c455 100644 --- a/extern/libmv/libmv/simple_pipeline/pipeline.cc +++ b/extern/libmv/libmv/simple_pipeline/pipeline.cc @@ -50,9 +50,10 @@ struct EuclideanPipelineRoutines { EuclideanBundle(tracks, reconstruction); } - static bool Resect(const vector &markers, + static bool Resect(const ReconstructionOptions &options, + const vector &markers, EuclideanReconstruction *reconstruction, bool final_pass) { - return EuclideanResect(markers, reconstruction, final_pass); + return EuclideanResect(options, markers, reconstruction, final_pass); } static bool Intersect(const vector &markers, @@ -88,7 +89,8 @@ struct ProjectivePipelineRoutines { ProjectiveBundle(tracks, reconstruction); } - static bool Resect(const vector &markers, + static bool Resect(const ReconstructionOptions &options, + const vector &markers, ProjectiveReconstruction *reconstruction, bool final_pass) { return ProjectiveResect(markers, reconstruction); } @@ -136,6 +138,7 @@ static void CompleteReconstructionLogProress(ProgressUpdateCallback *update_call template void InternalCompleteReconstruction( + const ReconstructionOptions &options, const Tracks &tracks, typename PipelineRoutines::Reconstruction *reconstruction, ProgressUpdateCallback *update_callback = NULL) { @@ -204,7 +207,7 @@ void InternalCompleteReconstruction( if (reconstructed_markers.size() >= 5) { CompleteReconstructionLogProress(update_callback, (double)tot_resects/(max_image)); - if (PipelineRoutines::Resect(reconstructed_markers, reconstruction, false)) { + if (PipelineRoutines::Resect(options, reconstructed_markers, reconstruction, false)) { num_resects++; tot_resects++; LG << "Ran Resect() for image " << image; @@ -240,11 +243,11 @@ void InternalCompleteReconstruction( if (reconstructed_markers.size() >= 5) { CompleteReconstructionLogProress(update_callback, (double)tot_resects/(max_image)); - if (PipelineRoutines::Resect(reconstructed_markers, reconstruction, true)) { + if (PipelineRoutines::Resect(options, reconstructed_markers, reconstruction, true)) { num_resects++; - LG << "Ran Resect() for image " << image; + LG << "Ran final Resect() for image " << image; } else { - LG << "Failed Resect() for image " << image; + LG << "Failed final Resect() for image " << image; } } } @@ -325,17 +328,21 @@ double ProjectiveReprojectionError( intrinsics); } -void EuclideanCompleteReconstruction(const Tracks &tracks, +void EuclideanCompleteReconstruction(const ReconstructionOptions &options, + const Tracks &tracks, EuclideanReconstruction *reconstruction, ProgressUpdateCallback *update_callback) { - InternalCompleteReconstruction(tracks, + InternalCompleteReconstruction(options, + tracks, reconstruction, update_callback); } -void ProjectiveCompleteReconstruction(const Tracks &tracks, +void ProjectiveCompleteReconstruction(const ReconstructionOptions &options, + const Tracks &tracks, ProjectiveReconstruction *reconstruction) { - InternalCompleteReconstruction(tracks, + InternalCompleteReconstruction(options, + tracks, reconstruction); } diff --git a/extern/libmv/libmv/simple_pipeline/pipeline.h b/extern/libmv/libmv/simple_pipeline/pipeline.h index e940b57bc0d..11c11297d78 100644 --- a/extern/libmv/libmv/simple_pipeline/pipeline.h +++ b/extern/libmv/libmv/simple_pipeline/pipeline.h @@ -39,6 +39,9 @@ namespace libmv { repeated until all points and cameras are estimated. Periodically, bundle adjustment is run to ensure a quality reconstruction. + \a options are used to define some specific befaviours based on settings + see documentation for ReconstructionOptions + \a tracks should contain markers used in the reconstruction. \a reconstruction should contain at least some 3D points or some estimated cameras. The minimum number of cameras is two (with no 3D points) and the @@ -46,7 +49,8 @@ namespace libmv { \sa EuclideanResect, EuclideanIntersect, EuclideanBundle */ -void EuclideanCompleteReconstruction(const Tracks &tracks, +void EuclideanCompleteReconstruction(const ReconstructionOptions &options, + const Tracks &tracks, EuclideanReconstruction *reconstruction, ProgressUpdateCallback *update_callback = NULL); @@ -63,6 +67,9 @@ void EuclideanCompleteReconstruction(const Tracks &tracks, repeated until all points and cameras are estimated. Periodically, bundle adjustment is run to ensure a quality reconstruction. + \a options are used to define some specific befaviours based on settings + see documentation for ReconstructionOptions + \a tracks should contain markers used in the reconstruction. \a reconstruction should contain at least some 3D points or some estimated cameras. The minimum number of cameras is two (with no 3D points) and the @@ -70,7 +77,8 @@ void EuclideanCompleteReconstruction(const Tracks &tracks, \sa ProjectiveResect, ProjectiveIntersect, ProjectiveBundle */ -void ProjectiveCompleteReconstruction(const Tracks &tracks, +void ProjectiveCompleteReconstruction(const ReconstructionOptions &options, + const Tracks &tracks, ProjectiveReconstruction *reconstruction); diff --git a/extern/libmv/libmv/simple_pipeline/reconstruction.h b/extern/libmv/libmv/simple_pipeline/reconstruction.h index 947a0636476..71789e3a245 100644 --- a/extern/libmv/libmv/simple_pipeline/reconstruction.h +++ b/extern/libmv/libmv/simple_pipeline/reconstruction.h @@ -26,6 +26,17 @@ namespace libmv { +struct ReconstructionOptions { + // threshold value of reconstruction error which is still considered successful + // if reconstruction error bigger than this value, fallback reconstruction + // algorithm would be used (if enabled) + double success_threshold; + + // use fallback reconstruction algorithm in cases main reconstruction algorithm + // failed to reconstruct + bool use_fallback_reconstruction; +}; + /*! A EuclideanCamera is the location and rotation of the camera viewing \a image. diff --git a/extern/libmv/libmv/simple_pipeline/resect.cc b/extern/libmv/libmv/simple_pipeline/resect.cc index b30d959b512..4c9ca6d8677 100644 --- a/extern/libmv/libmv/simple_pipeline/resect.cc +++ b/extern/libmv/libmv/simple_pipeline/resect.cc @@ -27,6 +27,7 @@ #include "libmv/multiview/projection.h" #include "libmv/numeric/numeric.h" #include "libmv/numeric/levenberg_marquardt.h" +#include "libmv/simple_pipeline/resect.h" #include "libmv/simple_pipeline/reconstruction.h" #include "libmv/simple_pipeline/tracks.h" @@ -89,7 +90,8 @@ struct EuclideanResectCostFunction { } // namespace -bool EuclideanResect(const vector &markers, +bool EuclideanResect(const ReconstructionOptions &options, + const vector &markers, EuclideanReconstruction *reconstruction, bool final_pass) { if (markers.size() < 5) { return false; @@ -103,10 +105,25 @@ bool EuclideanResect(const vector &markers, Mat3 R; Vec3 t; - if (0 || !euclidean_resection::EuclideanResection(points_2d, points_3d, &R, &t)) { + + double success_threshold = std::numeric_limits::max(); + + if(options.use_fallback_reconstruction) + success_threshold = options.success_threshold; + + if (0 || !euclidean_resection::EuclideanResection(points_2d, points_3d, &R, &t, + euclidean_resection::RESECTION_EPNP, + success_threshold)) + { // printf("Resection for image %d failed\n", markers[0].image); LG << "Resection for image " << markers[0].image << " failed;" << " trying fallback projective resection."; + + if (!options.use_fallback_reconstruction) { + LG << "No fallback; failing resection for " << markers[0].image; + return false; + } + if (!final_pass) return false; // Euclidean resection failed. Fall back to projective resection, which is // less reliable but better conditioned when there are many points. diff --git a/extern/libmv/libmv/simple_pipeline/resect.h b/extern/libmv/libmv/simple_pipeline/resect.h index f8b5b9f68ee..1691e7ee245 100644 --- a/extern/libmv/libmv/simple_pipeline/resect.h +++ b/extern/libmv/libmv/simple_pipeline/resect.h @@ -35,6 +35,9 @@ namespace libmv { reconstruction object, and solves for the pose and orientation of the camera for that frame. + \a options are used to define some specific befaviours based on settings + see documentation for ReconstructionOptions + \a markers should contain \l Marker markers \endlink belonging to tracks visible in the one frame to be resectioned. Each of the tracks associated with the markers must have a corresponding reconstructed 3D position in the @@ -51,7 +54,8 @@ namespace libmv { \sa EuclideanIntersect, EuclideanReconstructTwoFrames */ -bool EuclideanResect(const vector &markers, +bool EuclideanResect(const ReconstructionOptions &options, + const vector &markers, EuclideanReconstruction *reconstruction, bool final_pass); /*! diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc index f52919b2a61..472d58a1547 100644 --- a/extern/libmv/libmv/tracking/track_region.cc +++ b/extern/libmv/libmv/tracking/track_region.cc @@ -18,7 +18,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // -// Author: mierle@google.com (Keir Mierle) +// Author: mierle@gmail.com (Keir Mierle) // // TODO(keir): While this tracking code works rather well, it has some // outragous inefficiencies. There is probably a 5-10x speedup to be had if a @@ -41,6 +41,85 @@ #include "libmv/multiview/homography.h" #include "libmv/numeric/numeric.h" +// Expand the Jet functionality of Ceres to allow mixed numeric/autodiff. +// +// TODO(keir): Push this (or something similar) into upstream Ceres. +namespace ceres { + +// A jet traits class to make it easier to work with mixed auto / numeric diff. +template +struct JetOps { + static bool IsScalar() { + return true; + } + static T GetScalar(const T& t) { + return t; + } + static void SetScalar(const T& scalar, T* t) { + *t = scalar; + } + static void ScaleDerivative(double scale_by, T *value) { + // For double, there is no derivative to scale. + } +}; + +template +struct JetOps > { + static bool IsScalar() { + return false; + } + static T GetScalar(const Jet& t) { + return t.a; + } + static void SetScalar(const T& scalar, Jet* t) { + t->a = scalar; + } + static void ScaleDerivative(double scale_by, Jet *value) { + value->v *= scale_by; + } +}; + +template +struct Chain { + static ArgumentType Rule(const FunctionType &f, + const FunctionType dfdx[kNumArgs], + const ArgumentType x[kNumArgs]) { + // In the default case of scalars, there's nothing to do since there are no + // derivatives to propagate. + return f; + } +}; + +// XXX Add documentation here! +template +struct Chain > { + static Jet Rule(const FunctionType &f, + const FunctionType dfdx[kNumArgs], + const Jet x[kNumArgs]) { + // x is itself a function of another variable ("z"); what this function + // needs to return is "f", but with the derivative with respect to z + // attached to the jet. So combine the derivative part of x's jets to form + // a Jacobian matrix between x and z (i.e. dx/dz). + Eigen::Matrix dxdz; + for (int i = 0; i < kNumArgs; ++i) { + dxdz.row(i) = x[i].v.transpose(); + } + + // Map the input gradient dfdx into an Eigen row vector. + Eigen::Map > + vector_dfdx(dfdx, 1, kNumArgs); + + // Now apply the chain rule to obtain df/dz. Combine the derivative with + // the scalar part to obtain f with full derivative information. + Jet jet_f; + jet_f.a = f; + jet_f.v = vector_dfdx.template cast() * dxdz; // Also known as dfdz. + return jet_f; + } +}; + +} // namespace ceres + namespace libmv { using ceres::Jet; @@ -57,6 +136,7 @@ TrackRegionOptions::TrackRegionOptions() sigma(0.9), num_extra_points(0), regularization_coefficient(0.0), + minimum_corner_shift_tolerance_pixels(0.005), image1_mask(NULL) { } @@ -108,45 +188,93 @@ static T SampleWithDerivative(const FloatImage &image_and_gradient, } template -class BoundaryCheckingCallback : public ceres::IterationCallback { +class TerminationCheckingCallback : public ceres::IterationCallback { public: - BoundaryCheckingCallback(const FloatImage& image2, - const Warp &warp, - const double *x1, const double *y1) - : image2_(image2), warp_(warp), x1_(x1), y1_(y1) {} + TerminationCheckingCallback(const TrackRegionOptions &options, + const FloatImage& image2, + const Warp &warp, + const double *x1, const double *y1) + : options_(options), image2_(image2), warp_(warp), x1_(x1), y1_(y1), + have_last_successful_step_(false) {} virtual ceres::CallbackReturnType operator()( const ceres::IterationSummary& summary) { + // If the step wasn't successful, there's nothing to do. + if (!summary.step_is_successful) { + return ceres::SOLVER_CONTINUE; + } // Warp the original 4 points with the current warp into image2. double x2[4]; double y2[4]; for (int i = 0; i < 4; ++i) { warp_.Forward(warp_.parameters, x1_[i], y1_[i], x2 + i, y2 + i); } - // Enusre they are all in bounds. + // Ensure the corners are all in bounds. if (!AllInBounds(image2_, x2, y2)) { + LG << "Successful step fell outside of the pattern bounds; aborting."; return ceres::SOLVER_ABORT; } + + // Ensure the minimizer is making large enough shifts to bother continuing. + // Ideally, this check would happen on the parameters themselves which + // Ceres supports directly; however, the mapping from parameter change + // magnitude to corner movement in pixels is not a simple norm. Hence, the + // need for a stateful callback which tracks the last successful set of + // parameters (and the position of the projected patch corners). + if (have_last_successful_step_) { + // Compute the maximum shift of any corner in pixels since the last + // successful iteration. + double max_change_pixels = 0; + for (int i = 0; i < 4; ++i) { + double dx = x2[i] - x2_last_successful_[i]; + double dy = y2[i] - y2_last_successful_[i]; + double change_pixels = dx*dx + dy*dy; + if (change_pixels > max_change_pixels) { + max_change_pixels = change_pixels; + } + } + max_change_pixels = sqrt(max_change_pixels); + LG << "Max patch corner shift is " << max_change_pixels; + + // Bail if the shift is too small. + if (max_change_pixels < options_.minimum_corner_shift_tolerance_pixels) { + LG << "Max patch corner shift is " << max_change_pixels + << " from the last iteration; returning success."; + return ceres::SOLVER_TERMINATE_SUCCESSFULLY; + } + } + + // Save the projected corners for checking on the next successful iteration. + for (int i = 0; i < 4; ++i) { + x2_last_successful_[i] = x2[i]; + y2_last_successful_[i] = y2[i]; + } + have_last_successful_step_ = true; return ceres::SOLVER_CONTINUE; } private: + const TrackRegionOptions &options_; const FloatImage &image2_; const Warp &warp_; const double *x1_; const double *y1_; + + bool have_last_successful_step_; + double x2_last_successful_[4]; + double y2_last_successful_[4]; }; template class PixelDifferenceCostFunctor { public: PixelDifferenceCostFunctor(const TrackRegionOptions &options, - const FloatImage &image_and_gradient1, - const FloatImage &image_and_gradient2, - const Mat3 &canonical_to_image1, - int num_samples_x, - int num_samples_y, - const Warp &warp) + const FloatImage &image_and_gradient1, + const FloatImage &image_and_gradient2, + const Mat3 &canonical_to_image1, + int num_samples_x, + int num_samples_y, + const Warp &warp) : options_(options), image_and_gradient1_(image_and_gradient1), image_and_gradient2_(image_and_gradient2), @@ -1044,6 +1172,9 @@ void CreateBrutePattern(const double *x1, const double *y1, // correlation. Instead, this is a dumb implementation. Surprisingly, it is // fast enough in practice. // +// Returns true if any alignment was found, and false if the projected pattern +// is zero sized. +// // TODO(keir): The normalization is less effective for the brute force search // than it is with the Ceres solver. It's unclear if this is a bug or due to // the original frame being too different from the reprojected reference in the @@ -1054,7 +1185,7 @@ void CreateBrutePattern(const double *x1, const double *y1, // totally different warping interface, since access to more than a the source // and current destination frame is necessary. template -void BruteTranslationOnlyInitialize(const FloatImage &image1, +bool BruteTranslationOnlyInitialize(const FloatImage &image1, const FloatImage *image1_mask, const FloatImage &image2, const int num_extra_points, @@ -1100,6 +1231,7 @@ void BruteTranslationOnlyInitialize(const FloatImage &image1, int best_c = -1; int w = pattern.cols(); int h = pattern.rows(); + for (int r = 0; r < (image2.Height() - h); ++r) { for (int c = 0; c < (image2.Width() - w); ++c) { // Compute the weighted sum of absolute differences, Eigen style. Note @@ -1124,8 +1256,12 @@ void BruteTranslationOnlyInitialize(const FloatImage &image1, } } } - CHECK_NE(best_r, -1); - CHECK_NE(best_c, -1); + + // This mean the effective pattern area is zero. This check could go earlier, + // but this is less code. + if (best_r == -1 || best_c == -1) { + return false; + } LG << "Brute force translation found a shift. " << "best_c: " << best_c << ", best_r: " << best_r << ", " @@ -1140,6 +1276,7 @@ void BruteTranslationOnlyInitialize(const FloatImage &image1, x2[i] += best_c - origin_x; y2[i] += best_r - origin_y; } + return true; } } // namespace @@ -1191,12 +1328,19 @@ void TemplatedTrackRegion(const FloatImage &image1, if (SearchAreaTooBigForDescent(image2, x2, y2) && options.use_brute_initialization) { LG << "Running brute initialization..."; - BruteTranslationOnlyInitialize(image_and_gradient1, - options.image1_mask, - image2, - options.num_extra_points, - options.use_normalized_intensities, - x1, y1, x2, y2); + bool found_any_alignment = BruteTranslationOnlyInitialize( + image_and_gradient1, + options.image1_mask, + image2, + options.num_extra_points, + options.use_normalized_intensities, + x1, y1, x2, y2); + if (!found_any_alignment) { + LG << "Brute failed to find an alignment; pattern too small. " + << "Failing entire track operation."; + result->termination = TrackRegionResult::INSUFFICIENT_PATTERN_AREA; + return; + } for (int i = 0; i < 4; ++i) { LG << "P" << i << ": (" << x1[i] << ", " << y1[i] << "); brute (" << x2[i] << ", " << y2[i] << "); (dx, dy): (" << (x2[i] - x1[i]) @@ -1260,14 +1404,15 @@ void TemplatedTrackRegion(const FloatImage &image1, // Configure the solve. ceres::Solver::Options solver_options; - solver_options.linear_solver_type = ceres::DENSE_QR; + solver_options.linear_solver_type = ceres::DENSE_NORMAL_CHOLESKY; solver_options.max_num_iterations = options.max_iterations; solver_options.update_state_every_iteration = true; solver_options.parameter_tolerance = 1e-16; solver_options.function_tolerance = 1e-16; - // Prevent the corners from going outside the destination image. - BoundaryCheckingCallback callback(image2, warp, x1, y1); + // Prevent the corners from going outside the destination image and + // terminate if the optimizer is making tiny moves (converged). + TerminationCheckingCallback callback(options, image2, warp, x1, y1); solver_options.callbacks.push_back(&callback); // Run the solve. @@ -1290,11 +1435,21 @@ void TemplatedTrackRegion(const FloatImage &image1, // TODO(keir): Update the result statistics. // TODO(keir): Add a normalize-cross-correlation variant. - CHECK_NE(summary.termination_type, ceres::USER_ABORT) << "Libmv bug."; if (summary.termination_type == ceres::USER_ABORT) { result->termination = TrackRegionResult::FELL_OUT_OF_BOUNDS; return; } + + // This happens when the minimum corner shift tolerance is reached. Due to + // how the tolerance is computed this can't be done by Ceres. So return the + // same termination enum as Ceres, even though this is slightly different + // than Ceres's parameter tolerance, which operates on the raw parameter + // values rather than the pixel shifts of the patch corners. + if (summary.termination_type == ceres::USER_SUCCESS) { + result->termination = TrackRegionResult::PARAMETER_TOLERANCE; + return; + } + #define HANDLE_TERMINATION(termination_enum) \ if (summary.termination_type == ceres::termination_enum) { \ result->termination = TrackRegionResult::termination_enum; \ @@ -1377,11 +1532,11 @@ bool SamplePlanarPatch(const FloatImage &image, image_position(0), &(*patch)(r, c, 0)); if (mask) { - float maskValue = SampleLinear(*mask, image_position(1), - image_position(0), 0); + float mask_value = SampleLinear(*mask, image_position(1), + image_position(0), 0); for (int d = 0; d < image.Depth(); d++) - (*patch)(r, c, d) *= maskValue; + (*patch)(r, c, d) *= mask_value; } } } diff --git a/extern/libmv/libmv/tracking/track_region.h b/extern/libmv/libmv/tracking/track_region.h index 22ecfc54a15..cd7ee0aa2ba 100644 --- a/extern/libmv/libmv/tracking/track_region.h +++ b/extern/libmv/libmv/tracking/track_region.h @@ -90,6 +90,11 @@ struct TrackRegionOptions { // If zero, no regularization is used. double regularization_coefficient; + // If the maximum shift of any patch corner between successful iterations of + // the solver is less than this amount, then the tracking is declared + // successful. The solver termination becomes PARAMETER_TOLERANCE. + double minimum_corner_shift_tolerance_pixels; + // If non-null, this is used as the pattern mask. It should match the size of // image1, even though only values inside the image1 quad are examined. The // values must be in the range 0.0 to 0.1. @@ -111,6 +116,7 @@ struct TrackRegionResult { DESTINATION_OUT_OF_BOUNDS, FELL_OUT_OF_BOUNDS, INSUFFICIENT_CORRELATION, + INSUFFICIENT_PATTERN_AREA, CONFIGURATION_ERROR, }; Termination termination; diff --git a/extern/libmv/third_party/ceres/CMakeLists.txt b/extern/libmv/third_party/ceres/CMakeLists.txt index e6a9e430c47..e2f06d74646 100644 --- a/extern/libmv/third_party/ceres/CMakeLists.txt +++ b/extern/libmv/third_party/ceres/CMakeLists.txt @@ -28,16 +28,17 @@ set(INC . - ../../../Eigen3 include internal ../gflags ) set(INC_SYS + ../../../Eigen3 ) set(SRC + internal/ceres/array_utils.cc internal/ceres/block_evaluate_preparer.cc internal/ceres/block_jacobian_writer.cc internal/ceres/block_jacobi_preconditioner.cc @@ -53,16 +54,19 @@ set(SRC internal/ceres/conditioned_cost_function.cc internal/ceres/conjugate_gradients_solver.cc internal/ceres/corrector.cc + internal/ceres/cxsparse.cc + internal/ceres/dense_normal_cholesky_solver.cc internal/ceres/dense_qr_solver.cc internal/ceres/dense_sparse_matrix.cc internal/ceres/detect_structure.cc + internal/ceres/dogleg_strategy.cc internal/ceres/evaluator.cc internal/ceres/file.cc internal/ceres/generated/schur_eliminator_d_d_d.cc internal/ceres/gradient_checking_cost_function.cc internal/ceres/implicit_schur_complement.cc internal/ceres/iterative_schur_complement_solver.cc - internal/ceres/levenberg_marquardt.cc + internal/ceres/levenberg_marquardt_strategy.cc internal/ceres/linear_least_squares_problems.cc internal/ceres/linear_operator.cc internal/ceres/linear_solver.cc @@ -70,6 +74,7 @@ set(SRC internal/ceres/loss_function.cc internal/ceres/normal_prior.cc internal/ceres/partitioned_matrix_view.cc + internal/ceres/polynomial_solver.cc internal/ceres/problem.cc internal/ceres/problem_impl.cc internal/ceres/program.cc @@ -88,6 +93,8 @@ set(SRC internal/ceres/stringprintf.cc internal/ceres/suitesparse.cc internal/ceres/triplet_sparse_matrix.cc + internal/ceres/trust_region_minimizer.cc + internal/ceres/trust_region_strategy.cc internal/ceres/types.cc internal/ceres/visibility_based_preconditioner.cc internal/ceres/visibility.cc @@ -96,6 +103,8 @@ set(SRC include/ceres/ceres.h include/ceres/conditioned_cost_function.h include/ceres/cost_function.h + include/ceres/crs_matrix.h + include/ceres/fpclassify.h include/ceres/internal/autodiff.h include/ceres/internal/eigen.h include/ceres/internal/fixed_array.h @@ -114,6 +123,7 @@ set(SRC include/ceres/sized_cost_function.h include/ceres/solver.h include/ceres/types.h + internal/ceres/array_utils.h internal/ceres/block_evaluate_preparer.h internal/ceres/block_jacobian_writer.h internal/ceres/block_jacobi_preconditioner.h @@ -131,10 +141,13 @@ set(SRC internal/ceres/compressed_row_sparse_matrix.h internal/ceres/conjugate_gradients_solver.h internal/ceres/corrector.h + internal/ceres/cxsparse.h internal/ceres/dense_jacobian_writer.h + internal/ceres/dense_normal_cholesky_solver.h internal/ceres/dense_qr_solver.h internal/ceres/dense_sparse_matrix.h internal/ceres/detect_structure.h + internal/ceres/dogleg_strategy.h internal/ceres/evaluator.h internal/ceres/file.h internal/ceres/gradient_checking_cost_function.h @@ -143,7 +156,7 @@ set(SRC internal/ceres/implicit_schur_complement.h internal/ceres/integral_types.h internal/ceres/iterative_schur_complement_solver.h - internal/ceres/levenberg_marquardt.h + internal/ceres/levenberg_marquardt_strategy.h internal/ceres/linear_least_squares_problems.h internal/ceres/linear_operator.h internal/ceres/linear_solver.h @@ -153,6 +166,7 @@ set(SRC internal/ceres/mutex.h internal/ceres/parameter_block.h internal/ceres/partitioned_matrix_view.h + internal/ceres/polynomial_solver.h internal/ceres/problem_impl.h internal/ceres/program_evaluator.h internal/ceres/program.h @@ -168,10 +182,13 @@ set(SRC internal/ceres/solver_impl.h internal/ceres/sparse_matrix.h internal/ceres/sparse_normal_cholesky_solver.h + internal/ceres/split.h internal/ceres/stl_util.h internal/ceres/stringprintf.h internal/ceres/suitesparse.h internal/ceres/triplet_sparse_matrix.h + internal/ceres/trust_region_minimizer.h + internal/ceres/trust_region_strategy.h internal/ceres/visibility_based_preconditioner.h internal/ceres/visibility.h ) @@ -203,7 +220,7 @@ if(WIN32) if(NOT MINGW) list(APPEND INC - third_party/msinttypes + ../msinttypes ) endif() else() @@ -214,11 +231,30 @@ endif() add_definitions( -DCERES_HAVE_PTHREAD - -D"CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {" - -D"CERES_HASH_NAMESPACE_END=}}" -DCERES_NO_SUITESPARSE - -DCERES_DONT_HAVE_PROTOCOL_BUFFERS + -DCERES_NO_CXSPARSE + -DCERES_NO_PROTOCOL_BUFFERS -DCERES_RESTRICT_SCHUR_SPECIALIZATION ) +if(MSVC10) + add_definitions( + -D"CERES_HASH_NAMESPACE_START=namespace std {" + -D"CERES_HASH_NAMESPACE_END=}" + ) +else() + add_definitions( + -D"CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {" + -D"CERES_HASH_NAMESPACE_END=}}" + ) +endif() + +if(APPLE) + if(CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL "10.5") + add_definitions( + -DCERES_NO_TR1 + ) + endif() +endif() + blender_add_lib(extern_ceres "${SRC}" "${INC}" "${INC_SYS}") diff --git a/extern/libmv/third_party/ceres/ChangeLog b/extern/libmv/third_party/ceres/ChangeLog index 6e919658f13..8b84328cf98 100644 --- a/extern/libmv/third_party/ceres/ChangeLog +++ b/extern/libmv/third_party/ceres/ChangeLog @@ -1,324 +1,524 @@ -commit ca72152362ae1f4b9928c012e74b4d49d094a4ca -Merge: d297f8d 0a04199 -Author: Keir Mierle -Date: Wed May 9 13:10:59 2012 -0700 +commit 552f9f85bba89f00ca307bc18fbda1dff23bd0e4 +Author: Sameer Agarwal +Date: Fri Aug 31 07:27:22 2012 -0700 - Merge branch 'master' into windows - -commit 0a04199ef279cc9ea97f665fed8e7fae717813c3 -Merge: fdeb577 f2571f1 -Author: Keir Mierle -Date: Wed May 9 12:54:56 2012 -0700 - - Merge branch 'master' of https://code.google.com/p/ceres-solver - -commit fdeb5772cc5eeebca4d776d220d80cc91b6d0f74 -Author: Keir Mierle -Date: Wed May 9 07:38:07 2012 -0700 - - Support varying numbers of residuals in autodiff. + Various minor bug fixes to the solver logic. - This commit modifies the only function in autodiff that takes a - templated number of outputs (i.e. residuals) and makes that - template parameter a normal parameter. With that change, it - is a trivial matter to support a dynamic number of residuals. + 1. CostFunction returning false is handled better. + If only the cost is being evaluated, it is possible to + use the false value as an infinite value signal/outside + a region of validity. This allows a weak form of constraint + handling. Useful for example in handling infinities. - The API for dynamic residuals is to pass a fake number of - residuals as the second template argument to - AutoDiffCostFunction, and to pass the real number of - parameters as a second constructor argument. - -commit da3e0563cc12e08e7b3e0fbf11d9cc8cfe9658aa -Author: Sameer Agarwal -Date: Wed May 9 11:57:47 2012 -0700 - - Typo corrections in the documentation from Bing - -commit aa9526d8e8fb34c23d63e3af5bf9239b0c4ea603 -Author: Sameer Agarwal -Date: Tue May 8 21:22:09 2012 -0700 - - Share search paths across various library searches. - Fix typos in glog search. - Split the error messages for include and lib. - Enable building of tests by default. - Made building on homebrew installations a bit better. - Remove temporary variables for glog and gflags. - -commit f2571f186850ed3dd316236ac4be488979df7d30 -Author: Sameer Agarwal -Date: Wed May 9 11:57:47 2012 -0700 - - Typo corrections in the documentation from Bing - -commit 8f7f11ff7d07737435428a2620c52419cf99f98e -Merge: e6c17c4 eaccbb3 -Author: Sameer Agarwal -Date: Wed May 9 11:34:15 2012 -0700 - - Merge branch 'master' of https://code.google.com/p/ceres-solver - -commit e6c17c4c9d9307218f6f739cea39bc2d87733d4d -Author: Sameer Agarwal -Date: Tue May 8 21:22:09 2012 -0700 - - Share search paths across various library searches. - Fix typos in glog search. - Split the error messages for include and lib. - Enable building of tests by default. - Made building on homebrew installations a bit better. - Remove temporary variables for glog and gflags. - -commit eaccbb345614c0d24c5e21fa931f470cfda874df -Author: Keir Mierle -Date: Wed May 9 05:31:29 2012 -0700 - - Remove unused template parameter from VariadicEvaluate. - -commit 82f4b88c34b0b2cf85064e5fc20e374e978b2e3b -Author: Sameer Agarwal -Date: Sun May 6 21:05:28 2012 -0700 - - Extend support writing linear least squares problems to disk. + 2. Changed the way how the slop around zero when model_cost + is larger than the current cost. Relative instead of absolute + tolerances are used. The same logic is propagated how the + corresponding clamping of the model_cost is done. - 1. Make the mechanism for writing problems to disk, generic and - controllable using an enum DumpType visible in the API. + 3. Fixed a minor indexing bug in nist.cc. - 2. Instead of single file containing protocol buffers, now matrices can - be written in a matlab/octave friendly format. This is now the default. + 4. Some minor logging fixes to nist.cc to make it more + compatible with the rest of ceres. - 3. The support for writing problems to disk is moved into - linear_least_squares_problem.cc/h + Together these changes, take the successful solve count from + 41/54 to 46/54 and eliminate all NUMERICAL_FAILURE problems. - 4. SparseMatrix now has a ToTextFile virtual method which is - implemented by each of its subclasses to write a (i,j,s) triplets. - - 5. Minor changes to simple_bundle_adjuster to enable logging at startup. + Change-Id: If94170ea4731af5b243805c0200963dd31aa94a7 -commit d297f8d3d3f5025c24752f0f4c1ec2469a769f99 -Merge: 7e74d81 f8bd7fa -Author: Keir Mierle -Date: Tue May 8 05:39:56 2012 -0700 - - Merge branch 'master' into windows - -commit f8bd7fa9aa9dbf64b6165606630287cf8cf21194 -Author: Keir Mierle -Date: Tue May 8 05:39:32 2012 -0700 - - Small tweaks to the block jacobi preconditioner. - -commit 7e74d81ad57a159f14110eb5348b3bc7990b8bd4 -Merge: ecd7c8d e2a6cdc -Author: Keir Mierle -Date: Mon May 7 07:02:49 2012 -0700 - - Merge branch 'master' into windows - -commit e2a6cdc0816af9d0c77933f5017f137da3d52a35 -Author: Keir Mierle -Date: Mon May 7 06:39:56 2012 -0700 - - Address some of the comments on CGNR patch - - - Rename BlockDiagonalPreconditioner to BlockJacobiPreconditioner - - Include the diagonal in the block jacobi preconditioner. - - Better flag help for eta. - - Enable test for CGNR - - Rename CONJUGATE_GRADIENTS to CGNR. - - etc. - -commit 1b95dc580aa5d89be021c0915e26df83f18013bb -Merge: 211812a 7646039 -Author: Keir Mierle -Date: Mon May 7 04:34:10 2012 -0700 - - Merge branch 'master' of https://code.google.com/p/ceres-solver - -commit 211812a57360d2011cbcfd115cd55e0eb73600db -Author: Keir Mierle -Date: Mon May 7 04:33:50 2012 -0700 - - Better error handling in bundle_adjuster.cc - -commit 7646039ad9672b267495f5b31925473ad3022ac8 +commit 0b776b5cc9634d3b88d623905b96006f7647ce3e Author: Sameer Agarwal -Date: Sun May 6 22:02:19 2012 -0700 +Date: Thu Aug 30 15:26:17 2012 -0700 - Kashif's corrections to the docs - -commit 0d2d34148d10c5c7e924b3ca82ad2b237573ef64 -Author: Sameer Agarwal -Date: Sun May 6 21:16:03 2012 -0700 - - glog minimum version requirements + Update docs. - Building Ceres requires version 0.3.1 or better of glog. - Fedora 16 ships with a busted version 0.3. + Change-Id: I69d50bcd37aed3bea2190ca614f023e83172901b + +commit 2d7176ad7c8fb7238ca8abd6de73415d95877494 +Author: Petter Strandmark +Date: Thu Aug 30 19:51:24 2012 -0700 + + max_consecutive_nonmonotonic_steps should be int - issue 15 contains the gory details. + Found via Visual Studio warning. - Added a note to the build documentation to this effect. + Change-Id: Id2cd7de562dfc8cd35df5d5f5220dd2d7350eb2c -commit 39efc5ec4b64b8f5a2c5a3dbacdbc45421221547 -Author: Keir Mierle -Date: Sun May 6 16:09:52 2012 -0700 - - Fix tests broken by the CGNR change. - -commit 3faa08b7f7c4ac73661c6a15a6824c12080dfcb1 +commit 1a89bcc94e88933f89b20427a45bc40cdd23c056 Author: Sameer Agarwal -Date: Sun May 6 16:08:22 2012 -0700 +Date: Thu Aug 30 15:26:17 2012 -0700 - Formatting fixed based on Keir's comments and extended the tests - -commit 4f21c68409bc478c431a9b6aedf9e5cfdf11d2f3 -Author: Sameer Agarwal -Date: Sun May 6 15:33:47 2012 -0700 - - Fix the struct weak ordering used by independent set ordering, tests for it - -commit 887b156b917ccd4c172484452b059d33ea45f4f0 -Author: Sameer Agarwal -Date: Sun May 6 15:14:47 2012 -0700 - - fix he degree ordering routine - -commit ecd7c8df2af19404dc394b36bbe96e9db3bce840 -Author: Keir Mierle -Date: Sun May 6 00:09:41 2012 -0700 - - First step towards windows compatibilty + Better reporting on the NIST problems. - This adds some small changes to Ceres to make it mostly - compile on Windows. There are still issues with the - hash map use in schur_ordering.cc but I will fix those - shortly. + Change-Id: I7cf774ec3242c0612dbe52fc233c3fc6cff3f031 -commit f7898fba1b92f0e996571b5bfa22a37f5e3644de -Author: Keir Mierle -Date: Sat May 5 20:55:08 2012 -0700 +commit ea11704857a1e4a735e096896e4d775d83981499 +Author: Sameer Agarwal +Date: Wed Aug 29 18:18:48 2012 -0700 - Add a general sparse iterative solver: CGNR + Basic harness for testing NIST problems. - This adds a new LinearOperator which implements symmetric - products of a matrix, and a new CGNR solver to leverage - CG to directly solve the normal equations. This also - includes a block diagonal preconditioner. In experiments - on problem-16, the non-preconditioned version is about - 1/5 the speed of SPARSE_SCHUR, and the preconditioned - version using block cholesky is about 20% slower than - SPARSE_SCHUR. + Change-Id: I5baaa24dbf0506ceedf4a9be4ed17c84974d71a1 -commit 0a359d6198d257776a8831c3eb98f64ee91cf836 -Author: Keir Mierle -Date: Sat May 5 20:33:46 2012 -0700 +commit 98bf14d2b95386c2c4a6c29154637943dae4c36c +Author: Sameer Agarwal +Date: Thu Aug 30 10:26:44 2012 -0700 - Comment formatting. - -commit db4ec9312bb2f1ca7b2337812f6bad6cdd75b227 -Author: Keir Mierle -Date: Sat May 5 20:33:16 2012 -0700 - - Comment formatting - -commit f10163aaf3e57f52551bcd60bbdae873890a49dd -Author: Keir Mierle -Date: Fri May 4 21:33:53 2012 -0700 - - Warn about disabled schur specializations. + Miscellaneous fixes. - This commit brought to you from 30,000ft. + Change-Id: I521e11f2d20bf24960bbc6b5dab4ec8bb1503d23 -commit ad7b2b4aaf3ccc51f2b854febd53a9df54686cfe -Author: Keir Mierle -Date: Fri May 4 20:15:28 2012 -0700 +commit 1e3cbd9a4442cdd8fda43a7fb452f19dac8c74af +Author: Petter Strandmark +Date: Wed Aug 29 09:39:56 2012 -0700 - Add vim swapfiles to .gitignore - -commit 6447219826bf6e47b0c99d9ff0eaf5e2ba573d79 -Author: Sameer Agarwal -Date: Thu May 3 21:53:07 2012 -0700 - - 1. Changes the tutorial to refer to BriefReport. - 2. Some of the enums have commas at the end. - 3. Fix a bug in the default value of circle_fit.cc in the examples. - -commit 30c5f93c7f88dec49f76168663372772e06f17f5 -Author: Sameer Agarwal -Date: Thu May 3 10:44:43 2012 -0700 - - Rework the glog and gtest path checking to be consistent with the rest of the file and disable the dashboard support enabled by the earlier ctesting related patch. - -commit f10b033eb4aca77919987bc551d16d8a88b10110 -Merge: cc38774 e0a52a9 -Author: Sameer Agarwal -Date: Thu May 3 08:45:20 2012 -0700 - - Merge branch 'ctest' - -commit e0a52a993394e73bc7f7db8d520728926feab83e -Author: Sameer Agarwal -Date: Thu May 3 08:43:34 2012 -0700 - - Arnaus Gelas' patch to add better path searching for gflags and glog - -commit a9b8e815e1c026599734510399b10f4cf014c9cd -Author: Sameer Agarwal -Date: Thu May 3 08:41:52 2012 -0700 - - Arnaus Gelas' patch to add .gitignore - -commit a0cefc3347c32b2065053bbaff4f34d11529d931 -Author: Sameer Agarwal -Date: Thu May 3 08:38:33 2012 -0700 - - Arnaus Gelas' patch to move to Ctest - -commit cc38774d74e287704915282425fbd16818a72ec3 -Author: Keir Mierle -Date: Thu May 3 01:27:50 2012 -0700 - - Clarify ProgramEvaluator comments. - -commit 017c9530df557863f78212fb5ccd02814baa9fa8 -Author: Sameer Agarwal -Date: Wed May 2 08:21:59 2012 -0700 - - Mac OS X build instructions are much simpler, as homebrew takes care of gflags when glog is brought in. Also CMAKE does not need any flags to do the default thing - -commit 92d5ab5f8ae6fe355c30b606a5f230415ee0494b -Author: Keir Mierle -Date: Tue May 1 18:33:08 2012 -0700 - - Link BLAS explicitly on non-Mac platforms + Caching the symbolic Cholesky factorization when using CXSparse - Fixes issue #3. - -commit df3e54eb4a6b001b7f0560a2da73a5bd7f18615e -Author: Keir Mierle -Date: Tue May 1 18:22:51 2012 -0700 - - Fix link order of CHOLMOD + Average factorization times for bundle adjustment test problem: + SuiteSparse: 0.2794 s. + CXSparse: 0.4039 s. + CXSparse cached: 0.2399 s. - This was working by accident due to dynamic linking. Fixes issue #2. - -commit f477a3835329e2b48eb20c34c631a480b0f0d5bf -Author: Keir Mierle -Date: Tue May 1 18:10:48 2012 -0700 - - Fix Eigen search paths + CXSparse will still be slower, though, because it has to compute + the transpose and J^T * J. - Fixes issue #1 on http://code.google.com/p/ceres-solver. + Change-Id: If9cdaa3dd520bee84b56e5fd4953b56a93db6bde -commit 17fbc8ebb894c1d22bb3b0b02ea1394b580120f8 +commit 8b64140878ccd1e183d3715c38942a81fdecefde Author: Sameer Agarwal -Date: Tue May 1 00:21:19 2012 -0700 +Date: Wed Aug 29 05:41:22 2012 -0700 - Minor changes to the documentation. Formatting, and typos. + Documentation update + + Change-Id: I271a0422e7f6f42bcfd1dc6b5dc10c7a18f6a179 -commit 8ebb0730388045570f22b89fe8672c860cd2ad1b +commit a5353acd85a9fd19370b3d74035d87b0f0bac230 +Author: Petter Strandmark +Date: Tue Aug 28 18:16:41 2012 -0700 + + Adding gflags include to test_util.cc + + test_util seems to need gflags. + + Change-Id: I0c4757960f8ac69ad599c138aea58e3c88a4ea28 + +commit 87ca1b2ba28ec512752bbcf5fc994ce1434eb765 +Author: Petter Strandmark +Date: Tue Aug 28 18:05:20 2012 -0700 + + Changing random.h to use cstdlib for Windows compability. + + As discussed with Sameer today. + + Change-Id: If3d0284830c6591c71cc77b8400cafb45c0da61f + +commit aeb00a07323808a0a1816e733ad18a87d5109ea3 +Author: Petter Strandmark +Date: Mon Aug 27 22:22:57 2012 -0700 + + Removing gomp for Visual Studio + + Linking currently fails in Visual Studio due to a missing library + "gomp.lib". This is not needed in Visual Studio. OpenMP works + without it. + + Change-Id: I39e204a8dd4f1b7425df7d4b222d86a8bb961432 + +commit 6f362464ba99b800494d2f15c27768a342ddaa68 +Author: Markus Moll +Date: Tue Aug 28 01:03:38 2012 +0200 + + Add some tests for DoglegStrategy. + + Not necessarily a complete set. + + Change-Id: I14eb3a38c6fe976c8212f3934655411b6d1e0aa4 + +commit 122cf836a6dc9726489ce2fbecc6143bddc1caaf +Author: Sameer Agarwal +Date: Fri Aug 24 16:28:27 2012 -0700 + + Documentation update. + + Change-Id: I0a3c5ae4bc981a8f5bdd5a8905f923dc5f09a024 + +commit 69081719f73da8de2935774a42d237837a91952a Author: Keir Mierle -Date: Mon Apr 30 23:09:08 2012 -0700 +Date: Mon Aug 27 13:28:56 2012 -0700 - Initial commit of Ceres Solver. + Remove unnecessary overload for hash<> + + The overload for pointers in hash tables was applied in normal + usage of schur_ordering.cc. However, the tests did not include the + overload since they only included collections_port.h. As a result, + the routines in schur_ordering.cc were using a different hash + function than that inside the tests. + + The fix is to remove the specialization. If this breaks one of the + compiler configurations, we will find a workaround at that time. + + Change-Id: Idbf60415d5e2aec0c865b514ad0c577d21b91405 + +commit 1762420b6ed76b1c4d30b913b2cac1927b666534 +Author: Sameer Agarwal +Date: Wed Aug 22 10:01:31 2012 -0700 + + Update changelog. + + Change-Id: Idf5af69d5a9dbe35f58e30a8afcbfcd29bb7ebfe + +commit 976ab7aca908309b8282cb40bc080ca859136854 +Author: Keir Mierle +Date: Thu Aug 23 18:21:36 2012 -0700 + + Remove Google-era vestigial unit test. + + Change-Id: Ia7a295a5c759a17c1675a3055d287d3e40e9e0fe + +commit 6ad6257de0e2152ac5e77dc003758de45187d6ea +Author: Keir Mierle +Date: Wed Aug 22 11:10:31 2012 -0700 + + Add a workaround for an Android NDK compiler bug. + + On certain NDK build configurations, one of the innermost + parts of the Schur eliminator would get compiled + incorrectly. The compiler changed a -= to a +=. + + The normal Ceres unit tests caught the problem; however, + since it is not possible to build the tests with the NDK + (only with the standalone toolchain) this was difficult to + track down. Finding the issue involved pasting the schur + eliminator unit test inside of solver_impl.cc and other such + hacks. + + Change-Id: Ie91bb545d74fe39f0c8cbd1a6eb69ee4d8b25fb2 + +commit aecb2dc92b4aa7f3bf77a1ac918e62953602392b +Author: Sameer Agarwal +Date: Wed Aug 22 10:08:17 2012 -0700 + + Fix relative path bug in bibtex call. + + Change-Id: I0d31786564320a6831259bcdf4c75a6b665c43ad + +commit 1e2892009e591804df6286caebd5c960e7e3b099 +Author: Sameer Agarwal +Date: Tue Aug 21 18:00:54 2012 -0700 + + Update Summary::FullReport to report dogleg type. + + Change-Id: I0b4be8d7486c1c4b36b299693b3fe8b0d3426537 + +commit 295ade1122a86b83e1ea605d5ca394f315874717 +Author: Sameer Agarwal +Date: Wed Aug 22 06:51:22 2012 -0700 + + Fix Eigen3 Row/Column Major storage issue. + + Eigen3 does not allow column vectors to be stored in row-major + format. NumericDiffCostFunction by default stores its Jacobian + matrices in row-major format. This works fine if the residual + contains more than one variable. But if the residual block + depends on one variable and has more than one residuals, the + resulting Jacobian matrix is a column matrix in row-major format + resulting in a compile time error. + + The fix is to check the template parameters and switch to column-major + storage as needed. + + Thanks to Lena Gieseke for reporting this. + + Change-Id: Icc51c5b38e1f3609e0e1ecb3c4e4a02aecd72c3b + +commit 9ad27e8e9fb1bbd2054e2f6ae37623e01428f1c0 +Author: Arnaud Gelas +Date: Tue Aug 21 09:56:30 2012 +0200 + + Add one uninstall target to remove all installed files + + Change-Id: Ifcf89a6c27b25f28403d95a50e29c093a525298f + +commit 0c3a748ee49e04fe334f8f5a433649d18003d550 +Author: Markus Moll +Date: Tue Aug 21 14:44:59 2012 +0200 + + Allow equal lower and upper bound for diagonal scaling. + + This way, setting the lower and upper bound both to 1.0, one can disable + the automatic trust region scaling. + + Change-Id: Ifa317a6911b813a89c1cf7fdfde25af603705319 + +commit 3d644b76adefac6475b91dc53c3ae5e01c4f4d66 +Author: Arnaud Gelas +Date: Thu Aug 16 17:33:21 2012 +0200 + + Install headers, libraries and pdf + + Headers are installed in ${CMAKE_INSTALL_PREFIX}/include/ceres + Libraries are installed in ${CMAKE_INSTALL_PREFIX}/lib + pdf is installed in ${CMAKE_INSTALL_PREFIX}/share/ceres/docs + + Change-Id: Ic175f2c2f5fa86820a1e8c64c2ed171f4a302a68 + +commit d2fb5adea4d8c2aeb43c4289c6976798a54d3cf1 +Author: Arnaud Gelas +Date: Fri Aug 17 10:11:02 2012 +0200 + + Configure gerrit hook at CMake time + + If the source directory is a clone, at CMake time the commit-msg hook gets + downloaded and installed in the right location. + + Change-Id: I5fee17d050ca22d8b92a49fdcc2a1cd6659f209b + +commit 73166098fc4b1072adc30321c666188a3909c43c +Author: Arnaud Gelas +Date: Mon Aug 20 15:40:41 2012 +0200 + + Add one CMake option to build the examples. + + Currently the examples are always built. For external projects, it is useful + not to compile the examples. + + Change-Id: I41d3bde19c7e742818e60f78222d39c43992ca8b + +commit 86d4f1ba41ef14eb1b6b61a7936af83387b35eb2 +Author: Keir Mierle +Date: Mon Aug 20 11:52:04 2012 -0700 + + Add missing return statement. + + Change-Id: I5eaf718318e27040e3c97e32ee46cf0a11176a37 + +commit 51eb229da34187a4e8ce73ed9cc0e731998bb2be +Author: Keir Mierle +Date: Mon Aug 20 11:46:12 2012 -0700 + + Add Program::ToString() to aid debugging. + + Change-Id: I0ab37ed2fe0947ca87a152919d4e7dc9b56dedc6 + +commit bcc7100635e2047dc2b77df19a4ded8a6ab4d4b9 +Author: Keir Mierle +Date: Mon Aug 20 11:45:04 2012 -0700 + + Ignore minted.sty. + + Change-Id: I2467a6f801812b9007b51bf14b00757f026e4322 + +commit 9705a736dd3d6fbead0d8a6ff77102c69bbcdc08 +Author: Keir Mierle +Date: Mon Aug 20 11:24:05 2012 -0700 + + Add ParameterBlock::ToString() to aid debugging. + + Change-Id: Id3f5cb27b855c536dd65a986f345bd8eb2799dfa + +commit 0c714a70e6123ceb68e5cfcd3cfbee0d09deb1db +Author: Sameer Agarwal +Date: Mon Aug 20 11:18:16 2012 -0700 + + Fix blanks before private in loss_function.h + + Change-Id: I068bed6431bc7c9b7958af391655df61499000b2 + +commit 51cf7cbe3bac45c6807c2703a2fc3175d76a1b47 +Author: Markus Moll +Date: Mon Aug 20 20:10:20 2012 +0200 + + Add the two-dimensional subspace search to DoglegStrategy + + Change-Id: I5163744c100cdf07dd93343d0734ffe0e80364f3 + +commit ad1f7b772e559a911ac3a3b078b0aee1836fe785 +Author: Sameer Agarwal +Date: Mon Aug 20 11:10:34 2012 -0700 + + Add ArcTanLoss, TolerantLoss and ComposedLossFunction. + + Based on work by James Roseborough. + + Change-Id: Idc4e0b099028f67702bfc7fe3e43dbd96b6f9256 + +commit 05292bf8fc5208b86b4a13544615b584f6efa936 +Author: Sameer Agarwal +Date: Mon Aug 20 07:40:45 2012 -0700 + + Add a TrustRegionStrategy::Summary object. + + Change-Id: I7caee35a3408ee4a0ec16ba407410d822929340d + +commit b12b906c4d21c3949f0dce62c4c0d083c8edecf1 +Author: Arnaud Gelas +Date: Wed Aug 15 16:27:38 2012 +0200 + + Add one option to generate the PDF from CMake at build time + + Make sure pygmentize is installed + + Change-Id: I068ba45c33a8e96acc906a464b12d10d58b3e231 + +commit b9f15a59361c609ffc4a328aea9be3d265b5da81 +Author: Sameer Agarwal +Date: Sat Aug 18 13:06:19 2012 -0700 + + Add a dense Cholesky factorization based linear solver. + + For problems with a small number of variables, but a large + number of residuals, it is sometimes beneficial to use the + Cholesky factorization on the normal equations, instead of + the dense QR factorization of the Jacobian, even though it + is numerically the better thing to do. + + Change-Id: I3506b006195754018deec964e6e190b7e8c9ac8f + +commit b3fa009435acf476cd373052e62988f6437970b1 +Author: Arnaud Gelas +Date: Fri Aug 17 10:31:41 2012 +0200 + + Set CMAKE_*_OUTPUT_DIRECTORY + + Gather + * all executables in ${CMAKE_BINARY_DIR}/bin + * all libraries (static and dynamic) in ${CMAKE_BINARY_DIR}/lib + + Change-Id: Ibc2fa1adfb6f0aea65d66d570259b79546bf3b07 + +commit 1b8a4d5d11671ed83cf6077e363dd95333f08ef8 +Author: Sameer Agarwal +Date: Fri Aug 17 16:49:11 2012 -0700 + + Fix a minor bug in detect_structure logging. + + Change-Id: I117f7745e4c67595b3ff9244cde82b5b5b34ee4b + +commit 31c1e784ab2cb9294c6e05414cf06aae2b3766de +Author: Keir Mierle +Date: Fri Aug 17 16:16:32 2012 -0700 + + Minor cleanups. + + Change-Id: Ida4866997deeaa1bc2cebd6b69313a05ac82e457 + +commit e83f7879a8b21c6976e116958caf35bcdcf41cb0 +Author: Sameer Agarwal +Date: Fri Aug 17 15:34:42 2012 -0700 + + Fix SuiteSparse3 UFConfig.h detection really. + + Change-Id: Id187102e755b7d778dff4363f22f9a4697ed12dd + +commit 96f25dc57658d296ee6b6633818b4f1e51d7d587 +Author: Sameer Agarwal +Date: Fri Aug 17 15:34:42 2012 -0700 + + Fix SuiteSparse3 UFConfig.h detection. + + Change-Id: Ia59aefdb0ad7f713f76ed79692f2db4fa2821e5b + +commit c497bd6cd9aa944f518aa491d3bc645851ff9594 +Author: Markus Moll +Date: Fri Aug 17 14:40:13 2012 +0200 + + Add UFconfig and/or SuiteSparse_config test to CMakeLists.txt + + SuiteSparse 4 requires linking to libsuitesparseconfig.a. + Both SuiteSparse 3 and SuiteSparse 4 require an additional header + (either UFconfig.h or SuiteSparse_config.h) that is not found if it is + in a separate path. Therefore, add explicit checks. + + Change-Id: I699902b5db4f1b7f17134b5a54f9aa681445e294 + +commit 383c04f4236d92801c7c674892814362dedf7ad6 +Author: Sameer Agarwal +Date: Fri Aug 17 10:14:04 2012 -0700 + + Fix QuaternionToAngleAxis to ensure rotations are between -pi and pi. + + Thanks to Guoxuan Zhang for reporting this. + + Change-Id: I2831ca3a04d5dc6467849c290461adbe23faaea3 + +commit dd2b17d7dd9750801ba4720bdece2062e59b7ae3 +Author: Sameer Agarwal +Date: Thu Aug 16 19:34:57 2012 -0700 + + CERES_DONT_HAVE_PROTOCOL_BUFFERS -> CERES_NO_PROTOCOL_BUFFERS. + + Change-Id: I6c9f50e4c006faf4e75a8f417455db18357f3187 + +commit 8b4cb7aa2c74a0da62c638b2023566aa242af995 +Author: Sameer Agarwal +Date: Thu Aug 16 19:26:55 2012 -0700 + + Fix sparse linear algebra library logging in Summary::FullReport. + + Change-Id: Id2c902dc86c00954fde7749c7b4a67dd94215a31 + +commit 47d26bcd3b38b5ff53b34768c33b499d47b26bd0 +Author: Markus Moll +Date: Thu Aug 16 00:23:38 2012 +0200 + + Do not implicitly negate the step in the TrustRegionMinimizer. + + In the TrustRegionMinimizer, the step is currently implicitly negated. + This is done so that the linearized residual is |r - J*step|^2, which + corresponds to J*step = r, so neither J nor r have to be modified. + However, it leads to the rather unintuitive situation that the strategy + returns a step in positive gradient direction, which you would expect to + increase the function value. One way is to rename the "step" parameter in + the strategy to "negative_step" and document it. + This patch instead moves the negation inside the strategy, just around + the linear solver call, so that it is done in a local context and easier + to document. + + Change-Id: Idb258149a01f61c64e22128ea221c5a30cd89c89 + +commit 51da590c8457e6664f76fe9813425a0c71351497 +Author: Markus Moll +Date: Fri Aug 17 12:56:09 2012 +0200 + + Remove tmp file + + Change-Id: I07496fafae7b0c5c12cc26ae336e0db3b5592735 + +commit 7006a1f2b1701b8d89b8d1525fc0101943802221 +Author: Sameer Agarwal +Date: Thu Aug 16 18:04:22 2012 -0700 + + Correct example code in Powell's function example. + + Thanks to Petter Strandmark for pointing this out. + + Change-Id: I967632235dccdb481396e94904bb911c9a1efe1e + +commit 57a44b27bc6fc95b4e70fdc25c25c9925a2072a0 +Author: Keir Mierle +Date: Thu Aug 16 17:04:50 2012 -0700 + + Remove unnecessary flags in NDK build. + + Change-Id: Ib5b4d0b7f2d898671252734978c789b8171d96a8 + +commit f21bee247251a8b2e836c215a84c4668c31d75cd +Author: Keir Mierle +Date: Thu Aug 16 16:27:10 2012 -0700 + + Fix for fpclassify.h NDK porting work. + + Change-Id: I69df1b4caf2941ed96a53e35e43ec54073f84f59 + +commit 8ceb02cb75b66602de44a35e413225386cb21c27 +Author: Keir Mierle +Date: Thu Aug 16 14:23:47 2012 -0700 + + Add Android NDK build files. + + This adds a Android.mk build that builds a Ceres static library + suitable for embetting in larger Android applications. This is + useful when needing to build Ceres without GPL'd components, since + the standalone toolchain (needed for the CMake Android build) does + not work with STLPort. + + Change-Id: I8d857237f6f82658741017d161b2e31d9a20e5a7 diff --git a/extern/libmv/third_party/ceres/SConscript b/extern/libmv/third_party/ceres/SConscript index c629fa00176..6d0d2cd5c40 100644 --- a/extern/libmv/third_party/ceres/SConscript +++ b/extern/libmv/third_party/ceres/SConscript @@ -20,9 +20,13 @@ defs.append('CERES_HAVE_PTHREAD') defs.append('CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {') defs.append('CERES_HASH_NAMESPACE_END=}}') defs.append('CERES_NO_SUITESPARSE') -defs.append('CERES_DONT_HAVE_PROTOCOL_BUFFERS') +defs.append('CERES_NO_CXSPARSE') +defs.append('CERES_NO_PROTOCOL_BUFFERS') defs.append('CERES_RESTRICT_SCHUR_SPECIALIZATION') +if 'Mac OS X 10.5' in env['MACOSX_SDK_CHECK']: + defs.append('CERES_NO_TR1') + incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags' # work around broken hashtable in 10.5 SDK diff --git a/extern/libmv/third_party/ceres/bundle.sh b/extern/libmv/third_party/ceres/bundle.sh index 99aaadd8d87..ccf6d0aca16 100755 --- a/extern/libmv/third_party/ceres/bundle.sh +++ b/extern/libmv/third_party/ceres/bundle.sh @@ -1,6 +1,5 @@ #!/bin/sh -if false; then if [ "x$1" = "x--i-really-know-what-im-doing" ] ; then echo Proceeding as requested by command line ... else @@ -8,16 +7,22 @@ else exit 1 fi -repo="https://code.google.com/p/ceres-solver/" -branch="windows" +repo="https://ceres-solver.googlesource.com/ceres-solver" +branch="master" +tag="1.3.0" tmp=`mktemp -d` +checkout="$tmp/ceres" -GIT="git --git-dir $tmp/ceres/.git --work-tree $tmp/ceres" +GIT="git --git-dir $tmp/ceres/.git --work-tree $checkout" -git clone $repo $tmp/ceres +git clone $repo $checkout if [ $branch != "master" ]; then $GIT checkout -t remotes/origin/$branch +else + if [ "x$tag" != "x" ]; then + $GIT checkout $tag + fi fi $GIT log -n 50 > ChangeLog @@ -37,8 +42,6 @@ done rm -rf $tmp -fi - sources=`find ./include ./internal -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//\t/' | grep -v -E 'schur_eliminator_[0-9]_[0-9]_[0-9d].cc' | sort -d` generated_sources=`find ./include ./internal -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//#\t\t/' | grep -E 'schur_eliminator_[0-9]_[0-9]_[0-9d].cc' | sort -d` headers=`find ./include ./internal -type f -iname '*.h' | sed -r 's/^\.\//\t/' | sort -d` @@ -114,13 +117,13 @@ cat > CMakeLists.txt << EOF set(INC . - ../../../Eigen3 include internal ../gflags ) set(INC_SYS + ../../../Eigen3 ) set(SRC @@ -142,7 +145,7 @@ if(WIN32) if(NOT MINGW) list(APPEND INC - third_party/msinttypes + ../msinttypes ) endif() else() @@ -153,13 +156,32 @@ endif() add_definitions( -DCERES_HAVE_PTHREAD - -D"CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {" - -D"CERES_HASH_NAMESPACE_END=}}" -DCERES_NO_SUITESPARSE - -DCERES_DONT_HAVE_PROTOCOL_BUFFERS + -DCERES_NO_CXSPARSE + -DCERES_NO_PROTOCOL_BUFFERS -DCERES_RESTRICT_SCHUR_SPECIALIZATION ) +if(MSVC10) + add_definitions( + -D"CERES_HASH_NAMESPACE_START=namespace std {" + -D"CERES_HASH_NAMESPACE_END=}" + ) +else() + add_definitions( + -D"CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {" + -D"CERES_HASH_NAMESPACE_END=}}" + ) +endif() + +if(APPLE) + if(CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL "10.5") + add_definitions( + -DCERES_NO_TR1 + ) + endif() +endif() + blender_add_lib(extern_ceres "\${SRC}" "\${INC}" "\${INC_SYS}") EOF @@ -186,11 +208,20 @@ defs.append('CERES_HAVE_PTHREAD') defs.append('CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {') defs.append('CERES_HASH_NAMESPACE_END=}}') defs.append('CERES_NO_SUITESPARSE') -defs.append('CERES_DONT_HAVE_PROTOCOL_BUFFERS') +defs.append('CERES_NO_CXSPARSE') +defs.append('CERES_NO_PROTOCOL_BUFFERS') defs.append('CERES_RESTRICT_SCHUR_SPECIALIZATION') +if 'Mac OS X 10.5' in env['MACOSX_SDK_CHECK']: + defs.append('CERES_NO_TR1') + incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags' +# work around broken hashtable in 10.5 SDK +if env['OURPLATFORM'] == 'darwin' and env['WITH_BF_BOOST']: + incs += ' ' + env['BF_BOOST_INC'] + defs.append('CERES_HASH_BOOST') + if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): incs += ' ../msinttypes' diff --git a/extern/libmv/third_party/ceres/files.txt b/extern/libmv/third_party/ceres/files.txt index e9d7f585260..55083572977 100644 --- a/extern/libmv/third_party/ceres/files.txt +++ b/extern/libmv/third_party/ceres/files.txt @@ -2,6 +2,8 @@ include/ceres/autodiff_cost_function.h include/ceres/ceres.h include/ceres/conditioned_cost_function.h include/ceres/cost_function.h +include/ceres/crs_matrix.h +include/ceres/fpclassify.h include/ceres/internal/autodiff.h include/ceres/internal/eigen.h include/ceres/internal/fixed_array.h @@ -20,6 +22,8 @@ include/ceres/rotation.h include/ceres/sized_cost_function.h include/ceres/solver.h include/ceres/types.h +internal/ceres/array_utils.cc +internal/ceres/array_utils.h internal/ceres/block_evaluate_preparer.cc internal/ceres/block_evaluate_preparer.h internal/ceres/block_jacobian_writer.cc @@ -52,13 +56,19 @@ internal/ceres/conjugate_gradients_solver.cc internal/ceres/conjugate_gradients_solver.h internal/ceres/corrector.cc internal/ceres/corrector.h +internal/ceres/cxsparse.cc +internal/ceres/cxsparse.h internal/ceres/dense_jacobian_writer.h +internal/ceres/dense_normal_cholesky_solver.cc +internal/ceres/dense_normal_cholesky_solver.h internal/ceres/dense_qr_solver.cc internal/ceres/dense_qr_solver.h internal/ceres/dense_sparse_matrix.cc internal/ceres/dense_sparse_matrix.h internal/ceres/detect_structure.cc internal/ceres/detect_structure.h +internal/ceres/dogleg_strategy.cc +internal/ceres/dogleg_strategy.h internal/ceres/evaluator.cc internal/ceres/evaluator.h internal/ceres/file.cc @@ -79,6 +89,7 @@ internal/ceres/generated/schur_eliminator_4_4_3.cc internal/ceres/generated/schur_eliminator_4_4_4.cc internal/ceres/generated/schur_eliminator_4_4_d.cc internal/ceres/generated/schur_eliminator_d_d_d.cc +internal/ceres/generate_eliminator_specialization.py internal/ceres/gradient_checking_cost_function.cc internal/ceres/gradient_checking_cost_function.h internal/ceres/graph_algorithms.h @@ -88,8 +99,8 @@ internal/ceres/implicit_schur_complement.h internal/ceres/integral_types.h internal/ceres/iterative_schur_complement_solver.cc internal/ceres/iterative_schur_complement_solver.h -internal/ceres/levenberg_marquardt.cc -internal/ceres/levenberg_marquardt.h +internal/ceres/levenberg_marquardt_strategy.cc +internal/ceres/levenberg_marquardt_strategy.h internal/ceres/linear_least_squares_problems.cc internal/ceres/linear_least_squares_problems.h internal/ceres/linear_operator.cc @@ -106,6 +117,8 @@ internal/ceres/normal_prior.cc internal/ceres/parameter_block.h internal/ceres/partitioned_matrix_view.cc internal/ceres/partitioned_matrix_view.h +internal/ceres/polynomial_solver.cc +internal/ceres/polynomial_solver.h internal/ceres/problem.cc internal/ceres/problem_impl.cc internal/ceres/problem_impl.h @@ -136,6 +149,7 @@ internal/ceres/sparse_matrix.h internal/ceres/sparse_normal_cholesky_solver.cc internal/ceres/sparse_normal_cholesky_solver.h internal/ceres/split.cc +internal/ceres/split.h internal/ceres/stl_util.h internal/ceres/stringprintf.cc internal/ceres/stringprintf.h @@ -143,6 +157,10 @@ internal/ceres/suitesparse.cc internal/ceres/suitesparse.h internal/ceres/triplet_sparse_matrix.cc internal/ceres/triplet_sparse_matrix.h +internal/ceres/trust_region_minimizer.cc +internal/ceres/trust_region_minimizer.h +internal/ceres/trust_region_strategy.cc +internal/ceres/trust_region_strategy.h internal/ceres/types.cc internal/ceres/visibility_based_preconditioner.cc internal/ceres/visibility_based_preconditioner.h diff --git a/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h index e86d6993864..da9ee2c7993 100644 --- a/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h +++ b/extern/libmv/third_party/ceres/include/ceres/autodiff_cost_function.h @@ -163,7 +163,7 @@ class AutoDiffCostFunction : explicit AutoDiffCostFunction(CostFunctor* functor) : functor_(functor) { CHECK_NE(M, DYNAMIC) << "Can't run the fixed-size constructor if the " - << "number of residuals is set to ceres::DYNAMIC."; + << "number of residuals is set to ceres::DYNAMIC."; } // Takes ownership of functor. Ignores the template-provided number of @@ -174,7 +174,7 @@ class AutoDiffCostFunction : AutoDiffCostFunction(CostFunctor* functor, int num_residuals) : functor_(functor) { CHECK_EQ(M, DYNAMIC) << "Can't run the dynamic-size constructor if the " - << "number of residuals is not ceres::DYNAMIC."; + << "number of residuals is not ceres::DYNAMIC."; SizedCostFunction::set_num_residuals(num_residuals); } diff --git a/extern/libmv/third_party/ceres/include/ceres/cost_function.h b/extern/libmv/third_party/ceres/include/ceres/cost_function.h index 84403d90636..9b010f78f9d 100644 --- a/extern/libmv/third_party/ceres/include/ceres/cost_function.h +++ b/extern/libmv/third_party/ceres/include/ceres/cost_function.h @@ -119,7 +119,7 @@ class CostFunction { // number of outputs (residuals). vector parameter_block_sizes_; int num_residuals_; - DISALLOW_COPY_AND_ASSIGN(CostFunction); + CERES_DISALLOW_COPY_AND_ASSIGN(CostFunction); }; } // namespace ceres diff --git a/extern/libmv/third_party/ceres/include/ceres/crs_matrix.h b/extern/libmv/third_party/ceres/include/ceres/crs_matrix.h new file mode 100644 index 00000000000..c9fe8f78b7c --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/crs_matrix.h @@ -0,0 +1,65 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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 Google Inc. 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. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_PUBLIC_CRS_MATRIX_H_ +#define CERES_PUBLIC_CRS_MATRIX_H_ + +#include +#include "ceres/internal/port.h" + +namespace ceres { + +// A compressed row sparse matrix used primarily for communicating the +// Jacobian matrix to the user. +struct CRSMatrix { + CRSMatrix() : num_rows(0), num_cols(0) {} + + int num_rows; + int num_cols; + + // A compressed row matrix stores its contents in three arrays. + // The non-zero pattern of the i^th row is given by + // + // rows[cols[i] ... cols[i + 1]] + // + // and the corresponding values by + // + // values[cols[i] ... cols[i + 1]] + // + // Thus, cols is a vector of size num_cols + 1, and rows and values + // have as many entries as number of non-zeros in the matrix. + vector cols; + vector rows; + vector values; +}; + +} // namespace ceres + +#endif // CERES_PUBLIC_CRS_MATRIX_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/fpclassify.h b/extern/libmv/third_party/ceres/include/ceres/fpclassify.h new file mode 100644 index 00000000000..5a9ea1599d2 --- /dev/null +++ b/extern/libmv/third_party/ceres/include/ceres/fpclassify.h @@ -0,0 +1,88 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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 Google Inc. 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. +// +// Author: keir@google.com (Keir Mierle) +// +// Portable floating point classification. The names are picked such that they +// do not collide with macros. For example, "isnan" in C99 is a macro and hence +// does not respect namespaces. +// +// TODO(keir): Finish porting! + +#ifndef CERES_PUBLIC_FPCLASSIFY_H_ +#define CERES_PUBLIC_FPCLASSIFY_H_ + +#if defined(_MSC_VER) +#include +#endif + +namespace ceres { + +#if defined(_MSC_VER) +inline bool IsFinite (double x) { return _finite(x); } +inline bool IsInfinite(double x) { return !_finite(x) && !_isnan(x); } +inline bool IsNaN (double x) { return _isnan(x); } +inline bool IsNormal (double x) { + int classification = _fpclass(x); + return classification == _FPCLASS_NN || + classification == _FPCLASS_PN; +} +#elif defined(ANDROID) + +// On Android when using the GNU STL, the C++ fpclassify functions are not +// available. Strictly speaking, the std functions are are not standard until +// C++11. Instead use the C99 macros on Android. +inline bool IsNaN (double x) { return isnan(x); } +inline bool IsNormal (double x) { return isnormal(x); } + +// On Android NDK r6, when using STLPort, the isinf and isfinite functions are +// not available, so reimplement them. +# if defined(_STLPORT_VERSION) +inline bool IsInfinite(double x) { + return x == std::numeric_limits::infinity() || + x == -std::numeric_limits::infinity(); +} +inline bool IsFinite(double x) { + return !isnan(x) && !IsInfinite(x); +} +# else +inline bool IsFinite (double x) { return isfinite(x); } +inline bool IsInfinite(double x) { return isinf(x); } +# endif // defined(_STLPORT_VERSION) +#else +// These definitions are for the normal Unix suspects. +// TODO(keir): Test the "else" with more platforms. +inline bool IsFinite (double x) { return std::isfinite(x); } +inline bool IsInfinite(double x) { return std::isinf(x); } +inline bool IsNaN (double x) { return std::isnan(x); } +inline bool IsNormal (double x) { return std::isnormal(x); } +#endif + +} // namespace ceres + +#endif // CERES_PUBLIC_FPCLASSIFY_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h b/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h index 84617c4fa06..ce777d22dc7 100644 --- a/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h +++ b/extern/libmv/third_party/ceres/include/ceres/internal/fixed_array.h @@ -34,6 +34,8 @@ #include #include +#include "Eigen/Core" +#include "ceres/internal/macros.h" #include "ceres/internal/manual_constructor.h" namespace ceres { @@ -136,7 +138,6 @@ class FixedArray { // and T must be the same, otherwise callers' assumptions about use // of this code will be broken. struct InnerContainer { - EIGEN_MAKE_ALIGNED_OPERATOR_NEW T element; }; diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/macros.h b/extern/libmv/third_party/ceres/include/ceres/internal/macros.h index 0cfd773bcca..83ec31193e7 100644 --- a/extern/libmv/third_party/ceres/include/ceres/internal/macros.h +++ b/extern/libmv/third_party/ceres/include/ceres/internal/macros.h @@ -43,11 +43,13 @@ // // For disallowing only assign or copy, write the code directly, but declare // the intend in a comment, for example: -// void operator=(const TypeName&); // DISALLOW_ASSIGN -// Note, that most uses of DISALLOW_ASSIGN and DISALLOW_COPY are broken -// semantically, one should either use disallow both or neither. Try to -// avoid these in new code. -#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ +// +// void operator=(const TypeName&); // _DISALLOW_ASSIGN + +// Note, that most uses of CERES_DISALLOW_ASSIGN and CERES_DISALLOW_COPY +// are broken semantically, one should either use disallow both or +// neither. Try to avoid these in new code. +#define CERES_DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&); \ void operator=(const TypeName&) @@ -57,9 +59,9 @@ // This should be used in the private: declarations for a class // that wants to prevent anyone from instantiating it. This is // especially useful for classes containing only static methods. -#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ +#define CERES_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ TypeName(); \ - DISALLOW_COPY_AND_ASSIGN(TypeName) + CERES_DISALLOW_COPY_AND_ASSIGN(TypeName) // The arraysize(arr) macro returns the # of elements in an array arr. // The expression is a compile-time constant, and therefore can be @@ -151,4 +153,19 @@ char (&ArraySizeHelper(const T (&array)[N]))[N]; #define MUST_USE_RESULT #endif +// Platform independent macros to get aligned memory allocations. +// For example +// +// MyFoo my_foo CERES_ALIGN_ATTRIBUTE(16); +// +// Gives us an instance of MyFoo which is aligned at a 16 byte +// boundary. +#if defined(_MSC_VER) +#define CERES_ALIGN_ATTRIBUTE(n) __declspec(align(n)) +#define CERES_ALIGN_OF(T) __alignof(T) +#elif defined(__GNUC__) +#define CERES_ALIGN_ATTRIBUTE(n) __attribute__((aligned(n))) +#define CERES_ALIGN_OF(T) __alignof(T) +#endif + #endif // CERES_PUBLIC_INTERNAL_MACROS_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h b/extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h index a1d1f444e36..174d35ee2bd 100644 --- a/extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h +++ b/extern/libmv/third_party/ceres/include/ceres/internal/manual_constructor.h @@ -45,60 +45,49 @@ namespace ceres { namespace internal { -// ------- Define ALIGNED_CHAR_ARRAY -------------------------------- +// ------- Define CERES_ALIGNED_CHAR_ARRAY -------------------------------- -#ifndef ALIGNED_CHAR_ARRAY +#ifndef CERES_ALIGNED_CHAR_ARRAY // Because MSVC and older GCCs require that the argument to their alignment // construct to be a literal constant integer, we use a template instantiated // at all the possible powers of two. template struct AlignType { }; template struct AlignType<0, size> { typedef char result[size]; }; -#if defined(_MSC_VER) -#define BASE_PORT_H_ALIGN_ATTRIBUTE(X) __declspec(align(X)) -#define BASE_PORT_H_ALIGN_OF(T) __alignof(T) -#elif defined(__GNUC__) -#define BASE_PORT_H_ALIGN_ATTRIBUTE(X) __attribute__((aligned(X))) -#define BASE_PORT_H_ALIGN_OF(T) __alignof__(T) -#endif -#if defined(BASE_PORT_H_ALIGN_ATTRIBUTE) +#if !defined(CERES_ALIGN_ATTRIBUTE) +#define CERES_ALIGNED_CHAR_ARRAY you_must_define_CERES_ALIGNED_CHAR_ARRAY_for_your_compiler +#else // !defined(CERES_ALIGN_ATTRIBUTE) -#define BASE_PORT_H_ALIGNTYPE_TEMPLATE(X) \ +#define CERES_ALIGN_TYPE_TEMPLATE(X) \ template struct AlignType { \ - typedef BASE_PORT_H_ALIGN_ATTRIBUTE(X) char result[size]; \ + typedef CERES_ALIGN_ATTRIBUTE(X) char result[size]; \ } -BASE_PORT_H_ALIGNTYPE_TEMPLATE(1); -BASE_PORT_H_ALIGNTYPE_TEMPLATE(2); -BASE_PORT_H_ALIGNTYPE_TEMPLATE(4); -BASE_PORT_H_ALIGNTYPE_TEMPLATE(8); -BASE_PORT_H_ALIGNTYPE_TEMPLATE(16); -BASE_PORT_H_ALIGNTYPE_TEMPLATE(32); -BASE_PORT_H_ALIGNTYPE_TEMPLATE(64); -BASE_PORT_H_ALIGNTYPE_TEMPLATE(128); -BASE_PORT_H_ALIGNTYPE_TEMPLATE(256); -BASE_PORT_H_ALIGNTYPE_TEMPLATE(512); -BASE_PORT_H_ALIGNTYPE_TEMPLATE(1024); -BASE_PORT_H_ALIGNTYPE_TEMPLATE(2048); -BASE_PORT_H_ALIGNTYPE_TEMPLATE(4096); -BASE_PORT_H_ALIGNTYPE_TEMPLATE(8192); +CERES_ALIGN_TYPE_TEMPLATE(1); +CERES_ALIGN_TYPE_TEMPLATE(2); +CERES_ALIGN_TYPE_TEMPLATE(4); +CERES_ALIGN_TYPE_TEMPLATE(8); +CERES_ALIGN_TYPE_TEMPLATE(16); +CERES_ALIGN_TYPE_TEMPLATE(32); +CERES_ALIGN_TYPE_TEMPLATE(64); +CERES_ALIGN_TYPE_TEMPLATE(128); +CERES_ALIGN_TYPE_TEMPLATE(256); +CERES_ALIGN_TYPE_TEMPLATE(512); +CERES_ALIGN_TYPE_TEMPLATE(1024); +CERES_ALIGN_TYPE_TEMPLATE(2048); +CERES_ALIGN_TYPE_TEMPLATE(4096); +CERES_ALIGN_TYPE_TEMPLATE(8192); // Any larger and MSVC++ will complain. -#define ALIGNED_CHAR_ARRAY(T, Size) \ - typename AlignType::result +#undef CERES_ALIGN_TYPE_TEMPLATE -#undef BASE_PORT_H_ALIGNTYPE_TEMPLATE -#undef BASE_PORT_H_ALIGN_ATTRIBUTE +#define CERES_ALIGNED_CHAR_ARRAY(T, Size) \ + typename AlignType::result -#else // defined(BASE_PORT_H_ALIGN_ATTRIBUTE) -#define ALIGNED_CHAR_ARRAY you_must_define_ALIGNED_CHAR_ARRAY_for_your_compiler -#endif // defined(BASE_PORT_H_ALIGN_ATTRIBUTE) +#endif // !defined(CERES_ALIGN_ATTRIBUTE) -#undef BASE_PORT_H_ALIGNTYPE_TEMPLATE -#undef BASE_PORT_H_ALIGN_ATTRIBUTE - -#endif // ALIGNED_CHAR_ARRAY +#endif // CERES_ALIGNED_CHAR_ARRAY template class ManualConstructor { @@ -203,10 +192,10 @@ class ManualConstructor { } private: - ALIGNED_CHAR_ARRAY(Type, 1) space_; + CERES_ALIGNED_CHAR_ARRAY(Type, 1) space_; }; -#undef ALIGNED_CHAR_ARRAY +#undef CERES_ALIGNED_CHAR_ARRAY } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/include/ceres/internal/port.h b/extern/libmv/third_party/ceres/include/ceres/internal/port.h index 9a3e5cced58..a9fe247cef5 100644 --- a/extern/libmv/third_party/ceres/include/ceres/internal/port.h +++ b/extern/libmv/third_party/ceres/include/ceres/internal/port.h @@ -31,6 +31,8 @@ #ifndef CERES_PUBLIC_INTERNAL_PORT_H_ #define CERES_PUBLIC_INTERNAL_PORT_H_ +#include + namespace ceres { // It is unfortunate that this import of the entire standard namespace is @@ -39,6 +41,10 @@ namespace ceres { // things outside of the Ceres optimization package. using namespace std; +// This is necessary to properly handle the case that there is a different +// "string" implementation in the global namespace. +using std::string; + } // namespace ceres #endif // CERES_PUBLIC_INTERNAL_PORT_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h b/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h index 88da992d0c5..29157d380f2 100644 --- a/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h +++ b/extern/libmv/third_party/ceres/include/ceres/iteration_callback.h @@ -28,8 +28,9 @@ // // Author: sameeragarwal@google.com (Sameer Agarwal) // -// When an iteration callback is specified, Ceres calls the callback after each -// optimizer step and pass it an IterationSummary object, defined below. +// When an iteration callback is specified, Ceres calls the callback +// after each minimizer step (if the minimizer has not converged) and +// passes it an IterationSummary object, defined below. #ifndef CERES_PUBLIC_ITERATION_CALLBACK_H_ #define CERES_PUBLIC_ITERATION_CALLBACK_H_ @@ -44,7 +45,15 @@ struct IterationSummary { // Current iteration number. int32 iteration; + // Step was numerically valid, i.e., all values are finite and the + // step reduces the value of the linearized model. + // + // Note: step_is_valid is false when iteration = 0. + bool step_is_valid; + // Whether or not the algorithm made progress in this iteration. + // + // Note: step_is_successful is false when iteration = 0. bool step_is_successful; // Value of the objective function. @@ -66,9 +75,10 @@ struct IterationSummary { // cost and the change in the cost of the linearized approximation. double relative_decrease; - // Value of the regularization parameter for Levenberg-Marquardt - // algorithm at the end of the current iteration. - double mu; + // Size of the trust region at the end of the current iteration. For + // the Levenberg-Marquardt algorithm, the regularization parameter + // mu = 1.0 / trust_region_radius. + double trust_region_radius; // For the inexact step Levenberg-Marquardt algorithm, this is the // relative accuracy with which the Newton(LM) step is solved. This @@ -81,13 +91,15 @@ struct IterationSummary { // Newton step. int linear_solver_iterations; - // TODO(sameeragarwal): Change to use a higher precision timer using - // clock_gettime. - // Time (in seconds) spent inside the linear least squares solver. - int iteration_time_sec; + // Time (in seconds) spent inside the minimizer loop in the current + // iteration. + double iteration_time_in_seconds; - // Time (in seconds) spent inside the linear least squares solver. - int linear_solver_time_sec; + // Time (in seconds) spent inside the trust region step solver. + double step_solver_time_in_seconds; + + // Time (in seconds) since the user called Solve(). + double cumulative_time_in_seconds; }; // Interface for specifying callbacks that are executed at the end of @@ -133,7 +145,7 @@ struct IterationSummary { // summary.gradient_max_norm, // summary.step_norm, // summary.relative_decrease, -// summary.mu, +// summary.trust_region_radius, // summary.eta, // summary.linear_solver_iterations); // if (log_to_stdout_) { diff --git a/extern/libmv/third_party/ceres/include/ceres/jet.h b/extern/libmv/third_party/ceres/include/ceres/jet.h index a37870210f1..96e2256fd02 100644 --- a/extern/libmv/third_party/ceres/include/ceres/jet.h +++ b/extern/libmv/third_party/ceres/include/ceres/jet.h @@ -162,16 +162,7 @@ #include #include "Eigen/Core" - -// Visual Studio 2012 or older version -#if defined(_MSC_VER) && _MSC_VER <= 1700 -namespace std { -inline bool isfinite(double x) { return _finite(x); } -inline bool isinf (double x) { return !_finite(x) && !_isnan(x); } -inline bool isnan (double x) { return _isnan(x); } -inline bool isnormal(double x) { return _finite(x) && x != 0.0; } -} // namespace std -#endif +#include "ceres/fpclassify.h" namespace ceres { @@ -184,7 +175,9 @@ struct Jet { // (where T is a Jet). This usually only happens in opt mode. Note that // the C++ standard mandates that e.g. default constructed doubles are // initialized to 0.0; see sections 8.5 of the C++03 standard. - Jet() : a() {} + Jet() : a() { + v.setZero(); + } // Constructor from scalar: a + 0. explicit Jet(const T& value) { @@ -199,18 +192,6 @@ struct Jet { v[k] = T(1.0); } - /* - - // Construct from an array where the first element is the scalar. - // This is templated to support converting from other data types. - template - Jet(const D* scalar_and_derivatives) { - a = T(scalar_and_derivatives[0]); - v = Eigen::Map >( - scalar_and_derivatives + 1, N).cast(); - } - */ - // Compound operators Jet& operator+=(const Jet &y) { *this = *this + y; @@ -232,8 +213,25 @@ struct Jet { return *this; } - T a; // The scalar part. - Eigen::Matrix v; // The infinitesimal part. + // The scalar part. + T a; + + // The infinitesimal part. + // + // Note the Eigen::DontAlign bit is needed here because this object + // gets allocated on the stack and as part of other arrays and + // structs. Forcing the right alignment there is the source of much + // pain and suffering. Even if that works, passing Jets around to + // functions by value has problems because the C++ ABI does not + // guarantee alignment for function arguments. + // + // Setting the DontAlign bit prevents Eigen from using SSE for the + // various operations on Jets. This is a small performance penalty + // since the AutoDiff code will still expose much of the code as + // statically sized loops to the compiler. But given the subtle + // issues that arise due to alignment, especially when dealing with + // multiple platforms, it seems to be a trade off worth making. + Eigen::Matrix v; }; // Unary + @@ -411,10 +409,6 @@ inline double cos (double x) { return std::cos(x); } inline double acos (double x) { return std::acos(x); } inline double sin (double x) { return std::sin(x); } inline double asin (double x) { return std::asin(x); } -inline bool isfinite(double x) { return std::isfinite(x); } -inline bool isinf (double x) { return std::isinf(x); } -inline bool isnan (double x) { return std::isnan(x); } -inline bool isnormal(double x) { return std::isnormal(x); } inline double pow (double x, double y) { return std::pow(x, y); } inline double atan2(double y, double x) { return std::atan2(y, x); } @@ -492,22 +486,23 @@ Jet asin(const Jet& f) { } // Jet Classification. It is not clear what the appropriate semantics are for -// these classifications. This picks that isfinite and isnormal are "all" -// operations, i.e. all elements of the jet must be finite for the jet itself to -// be finite (or normal). For isnan and isinf, the answer is less clear. This -// takes a "any" approach for isnan and isinf such that if any part of a jet is -// nan or inf, then the entire jet is nan or inf. This leads to strange -// situations like a jet can be both isinf and isnan, but in practice the "any" -// semantics are the most useful for e.g. checking that derivatives are sane. +// these classifications. This picks that IsFinite and isnormal are "all" +// operations, i.e. all elements of the jet must be finite for the jet itself +// to be finite (or normal). For IsNaN and IsInfinite, the answer is less +// clear. This takes a "any" approach for IsNaN and IsInfinite such that if any +// part of a jet is nan or inf, then the entire jet is nan or inf. This leads +// to strange situations like a jet can be both IsInfinite and IsNaN, but in +// practice the "any" semantics are the most useful for e.g. checking that +// derivatives are sane. // The jet is finite if all parts of the jet are finite. template inline -bool isfinite(const Jet& f) { - if (!isfinite(f.a)) { +bool IsFinite(const Jet& f) { + if (!IsFinite(f.a)) { return false; } for (int i = 0; i < N; ++i) { - if (!isfinite(f.v[i])) { + if (!IsFinite(f.v[i])) { return false; } } @@ -516,12 +511,12 @@ bool isfinite(const Jet& f) { // The jet is infinite if any part of the jet is infinite. template inline -bool isinf(const Jet& f) { - if (isinf(f.a)) { +bool IsInfinite(const Jet& f) { + if (IsInfinite(f.a)) { return true; } for (int i = 0; i < N; i++) { - if (isinf(f.v[i])) { + if (IsInfinite(f.v[i])) { return true; } } @@ -530,12 +525,12 @@ bool isinf(const Jet& f) { // The jet is NaN if any part of the jet is NaN. template inline -bool isnan(const Jet& f) { - if (isnan(f.a)) { +bool IsNaN(const Jet& f) { + if (IsNaN(f.a)) { return true; } for (int i = 0; i < N; ++i) { - if (isnan(f.v[i])) { + if (IsNaN(f.v[i])) { return true; } } @@ -544,12 +539,12 @@ bool isnan(const Jet& f) { // The jet is normal if all parts of the jet are normal. template inline -bool isnormal(const Jet& f) { - if (!isnormal(f.a)) { +bool IsNormal(const Jet& f) { + if (!IsNormal(f.a)) { return false; } for (int i = 0; i < N; ++i) { - if (!isnormal(f.v[i])) { + if (!IsNormal(f.v[i])) { return false; } } @@ -650,78 +645,6 @@ inline std::ostream &operator<<(std::ostream &s, const Jet& z) { return s << "[" << z.a << " ; " << z.v.transpose() << "]"; } -// A jet traits class to make it easier to work with mixed auto / numeric diff. -template -struct JetOps { - static bool IsScalar() { - return true; - } - static T GetScalar(const T& t) { - return t; - } - static void SetScalar(const T& scalar, T* t) { - *t = scalar; - } - static void ScaleDerivative(double scale_by, T *value) { - // For double, there is no derivative to scale. - } -}; - -template -struct JetOps > { - static bool IsScalar() { - return false; - } - static T GetScalar(const Jet& t) { - return t.a; - } - static void SetScalar(const T& scalar, Jet* t) { - t->a = scalar; - } - static void ScaleDerivative(double scale_by, Jet *value) { - value->v *= scale_by; - } -}; - -template -struct Chain { - static ArgumentType Rule(const FunctionType &f, - const FunctionType dfdx[kNumArgs], - const ArgumentType x[kNumArgs]) { - // In the default case of scalars, there's nothing to do since there are no - // derivatives to propagate. - return f; - } -}; - -// XXX Add documentation here! -template -struct Chain > { - static Jet Rule(const FunctionType &f, - const FunctionType dfdx[kNumArgs], - const Jet x[kNumArgs]) { - // x is itself a function of another variable ("z"); what this function - // needs to return is "f", but with the derivative with respect to z - // attached to the jet. So combine the derivative part of x's jets to form - // a Jacobian matrix between x and z (i.e. dx/dz). - Eigen::Matrix dxdz; - for (int i = 0; i < kNumArgs; ++i) { - dxdz.row(i) = x[i].v.transpose(); - } - - // Map the input gradient dfdx into an Eigen row vector. - Eigen::Map > - vector_dfdx(dfdx, 1, kNumArgs); - - // Now apply the chain rule to obtain df/dz. Combine the derivative with - // the scalar part to obtain f with full derivative information. - Jet jet_f; - jet_f.a = f; - jet_f.v = vector_dfdx.template cast() * dxdz; // Also known as dfdz. - return jet_f; - } -}; - } // namespace ceres namespace Eigen { diff --git a/extern/libmv/third_party/ceres/include/ceres/loss_function.h b/extern/libmv/third_party/ceres/include/ceres/loss_function.h index 81add02cdee..0c0ceaaecd0 100644 --- a/extern/libmv/third_party/ceres/include/ceres/loss_function.h +++ b/extern/libmv/third_party/ceres/include/ceres/loss_function.h @@ -175,6 +175,7 @@ class HuberLoss : public LossFunction { public: explicit HuberLoss(double a) : a_(a), b_(a * a) { } virtual void Evaluate(double, double*) const; + private: const double a_; // b = a^2. @@ -190,6 +191,7 @@ class SoftLOneLoss : public LossFunction { public: explicit SoftLOneLoss(double a) : b_(a * a), c_(1 / b_) { } virtual void Evaluate(double, double*) const; + private: // b = a^2. const double b_; @@ -206,6 +208,7 @@ class CauchyLoss : public LossFunction { public: explicit CauchyLoss(double a) : b_(a * a), c_(1 / b_) { } virtual void Evaluate(double, double*) const; + private: // b = a^2. const double b_; @@ -213,6 +216,78 @@ class CauchyLoss : public LossFunction { const double c_; }; +// Loss that is capped beyond a certain level using the arc-tangent function. +// The scaling parameter 'a' determines the level where falloff occurs. +// For costs much smaller than 'a', the loss function is linear and behaves like +// TrivialLoss, and for values much larger than 'a' the value asymptotically +// approaches the constant value of a * PI / 2. +// +// rho(s) = a atan(s / a). +// +// At s = 0: rho = [0, 1, 0]. +class ArctanLoss : public LossFunction { + public: + explicit ArctanLoss(double a) : a_(a), b_(1 / (a * a)) { } + virtual void Evaluate(double, double*) const; + + private: + const double a_; + // b = 1 / a^2. + const double b_; +}; + +// Loss function that maps to approximately zero cost in a range around the +// origin, and reverts to linear in error (quadratic in cost) beyond this range. +// The tolerance parameter 'a' sets the nominal point at which the +// transition occurs, and the transition size parameter 'b' sets the nominal +// distance over which most of the transition occurs. Both a and b must be +// greater than zero, and typically b will be set to a fraction of a. +// The slope rho'[s] varies smoothly from about 0 at s <= a - b to +// about 1 at s >= a + b. +// +// The term is computed as: +// +// rho(s) = b log(1 + exp((s - a) / b)) - c0. +// +// where c0 is chosen so that rho(0) == 0 +// +// c0 = b log(1 + exp(-a / b) +// +// This has the following useful properties: +// +// rho(s) == 0 for s = 0 +// rho'(s) ~= 0 for s << a - b +// rho'(s) ~= 1 for s >> a + b +// rho''(s) > 0 for all s +// +// In addition, all derivatives are continuous, and the curvature is +// concentrated in the range a - b to a + b. +// +// At s = 0: rho = [0, ~0, ~0]. +class TolerantLoss : public LossFunction { + public: + explicit TolerantLoss(double a, double b); + virtual void Evaluate(double, double*) const; + + private: + const double a_, b_, c_; +}; + +// Composition of two loss functions. The error is the result of first +// evaluating g followed by f to yield the composition f(g(s)). +// The loss functions must not be NULL. +class ComposedLoss : public LossFunction { + public: + explicit ComposedLoss(const LossFunction* f, Ownership ownership_f, + const LossFunction* g, Ownership ownership_g); + virtual ~ComposedLoss(); + virtual void Evaluate(double, double*) const; + + private: + internal::scoped_ptr f_, g_; + const Ownership ownership_f_, ownership_g_; +}; + // The discussion above has to do with length scaling: it affects the space // in which s is measured. Sometimes you want to simply scale the output // value of the robustifier. For example, you might want to weight @@ -249,7 +324,7 @@ class ScaledLoss : public LossFunction { internal::scoped_ptr rho_; const double a_; const Ownership ownership_; - DISALLOW_COPY_AND_ASSIGN(ScaledLoss); + CERES_DISALLOW_COPY_AND_ASSIGN(ScaledLoss); }; // Sometimes after the optimization problem has been constructed, we @@ -314,7 +389,7 @@ class LossFunctionWrapper : public LossFunction { private: internal::scoped_ptr rho_; Ownership ownership_; - DISALLOW_COPY_AND_ASSIGN(LossFunctionWrapper); + CERES_DISALLOW_COPY_AND_ASSIGN(LossFunctionWrapper); }; } // namespace ceres diff --git a/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h b/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h index bbaefca5b6c..8544e44d0bc 100644 --- a/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h +++ b/extern/libmv/third_party/ceres/include/ceres/numeric_diff_cost_function.h @@ -93,11 +93,13 @@ struct Differencer { using Eigen::Map; using Eigen::Matrix; using Eigen::RowMajor; + using Eigen::ColMajor; typedef Matrix ResidualVector; typedef Matrix ParameterVector; - typedef Matrix - JacobianMatrix; + typedef Matrix 1) ? ColMajor : RowMajor> JacobianMatrix; Map parameter_jacobian(jacobians[parameter_block], num_residuals, diff --git a/extern/libmv/third_party/ceres/include/ceres/problem.h b/extern/libmv/third_party/ceres/include/ceres/problem.h index 0ca61006bdb..2b08c6723e8 100644 --- a/extern/libmv/third_party/ceres/include/ceres/problem.h +++ b/extern/libmv/third_party/ceres/include/ceres/problem.h @@ -50,13 +50,13 @@ namespace ceres { class CostFunction; class LossFunction; class LocalParameterization; +class Solver; namespace internal { class Preprocessor; class ProblemImpl; class ParameterBlock; class ResidualBlock; -class SolverImpl; } // namespace internal // A ResidualBlockId is a handle clients can use to delete residual @@ -255,9 +255,9 @@ class Problem { int NumResiduals() const; private: - friend class internal::SolverImpl; + friend class Solver; internal::scoped_ptr problem_impl_; - DISALLOW_COPY_AND_ASSIGN(Problem); + CERES_DISALLOW_COPY_AND_ASSIGN(Problem); }; } // namespace ceres diff --git a/extern/libmv/third_party/ceres/include/ceres/rotation.h b/extern/libmv/third_party/ceres/include/ceres/rotation.h index e4227e78b9a..0d8a390d5d1 100644 --- a/extern/libmv/third_party/ceres/include/ceres/rotation.h +++ b/extern/libmv/third_party/ceres/include/ceres/rotation.h @@ -47,6 +47,7 @@ #include #include +#include "glog/logging.h" namespace ceres { @@ -145,18 +146,11 @@ void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]); // --- IMPLEMENTATION -// Duplicate rather than decorate every use of cmath with _USE_MATH_CONSTANTS. -// Necessitated by Windows. -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#define CERES_NEED_M_PI_UNDEF -#endif - template inline void AngleAxisToQuaternion(const T* angle_axis, T* quaternion) { - const T &a0 = angle_axis[0]; - const T &a1 = angle_axis[1]; - const T &a2 = angle_axis[2]; + const T& a0 = angle_axis[0]; + const T& a1 = angle_axis[1]; + const T& a2 = angle_axis[2]; const T theta_squared = a0 * a0 + a1 * a1 + a2 * a2; // For points not at the origin, the full conversion is numerically stable. @@ -183,16 +177,35 @@ inline void AngleAxisToQuaternion(const T* angle_axis, T* quaternion) { template inline void QuaternionToAngleAxis(const T* quaternion, T* angle_axis) { - const T &q1 = quaternion[1]; - const T &q2 = quaternion[2]; - const T &q3 = quaternion[3]; - const T sin_squared = q1 * q1 + q2 * q2 + q3 * q3; + const T& q1 = quaternion[1]; + const T& q2 = quaternion[2]; + const T& q3 = quaternion[3]; + const T sin_squared_theta = q1 * q1 + q2 * q2 + q3 * q3; // For quaternions representing non-zero rotation, the conversion // is numerically stable. - if (sin_squared > T(0.0)) { - const T sin_theta = sqrt(sin_squared); - const T k = T(2.0) * atan2(sin_theta, quaternion[0]) / sin_theta; + if (sin_squared_theta > T(0.0)) { + const T sin_theta = sqrt(sin_squared_theta); + const T& cos_theta = quaternion[0]; + + // If cos_theta is negative, theta is greater than pi/2, which + // means that angle for the angle_axis vector which is 2 * theta + // would be greater than pi. + // + // While this will result in the correct rotation, it does not + // result in a normalized angle-axis vector. + // + // In that case we observe that 2 * theta ~ 2 * theta - 2 * pi, + // which is equivalent saying + // + // theta - pi = atan(sin(theta - pi), cos(theta - pi)) + // = atan(-sin(theta), -cos(theta)) + // + const T two_theta = + T(2.0) * ((cos_theta < 0.0) + ? atan2(-sin_theta, -cos_theta) + : atan2(sin_theta, cos_theta)); + const T k = two_theta / sin_theta; angle_axis[0] = q1 * k; angle_axis[1] = q2 * k; angle_axis[2] = q3 * k; @@ -259,7 +272,7 @@ inline void RotationMatrixToAngleAxis(const T * R, T * angle_axis) { // Case 2: theta ~ 0, means sin(theta) ~ theta to a good // approximation. - if (costheta > 0) { + if (costheta > 0.0) { const T kHalf = T(0.5); for (int i = 0; i < 3; ++i) { angle_axis[i] *= kHalf; @@ -284,8 +297,8 @@ inline void RotationMatrixToAngleAxis(const T * R, T * angle_axis) { // angle_axis[i] should be positive, otherwise negative. for (int i = 0; i < 3; ++i) { angle_axis[i] = theta * sqrt((R[i*4] - costheta) * inv_one_minus_costheta); - if (((sintheta < 0) && (angle_axis[i] > 0)) || - ((sintheta > 0) && (angle_axis[i] < 0))) { + if (((sintheta < 0.0) && (angle_axis[i] > 0.0)) || + ((sintheta > 0.0) && (angle_axis[i] < 0.0))) { angle_axis[i] = -angle_axis[i]; } } @@ -334,7 +347,8 @@ template inline void EulerAnglesToRotationMatrix(const T* euler, const int row_stride, T* R) { - const T degrees_to_radians(M_PI / 180.0); + const double kPi = 3.14159265358979323846; + const T degrees_to_radians(kPi / 180.0); const T pitch(euler[0] * degrees_to_radians); const T roll(euler[1] * degrees_to_radians); @@ -517,10 +531,4 @@ void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]) { } // namespace ceres -// Clean define pollution. -#ifdef CERES_NEED_M_PI_UNDEF -#undef CERES_NEED_M_PI_UNDEF -#undef M_PI -#endif - #endif // CERES_PUBLIC_ROTATION_H_ diff --git a/extern/libmv/third_party/ceres/include/ceres/solver.h b/extern/libmv/third_party/ceres/include/ceres/solver.h index bd669272023..31d5e8d7987 100644 --- a/extern/libmv/third_party/ceres/include/ceres/solver.h +++ b/extern/libmv/third_party/ceres/include/ceres/solver.h @@ -34,10 +34,10 @@ #include #include #include - -#include "ceres/iteration_callback.h" +#include "ceres/crs_matrix.h" #include "ceres/internal/macros.h" #include "ceres/internal/port.h" +#include "ceres/iteration_callback.h" #include "ceres/types.h" namespace ceres { @@ -57,24 +57,47 @@ class Solver { struct Options { // Default constructor that sets up a generic sparse problem. Options() { - minimizer_type = LEVENBERG_MARQUARDT; + trust_region_strategy_type = LEVENBERG_MARQUARDT; + dogleg_type = TRADITIONAL_DOGLEG; + use_nonmonotonic_steps = false; + max_consecutive_nonmonotonic_steps = 5; max_num_iterations = 50; - max_solver_time_sec = 1.0e9; + max_solver_time_in_seconds = 1e9; num_threads = 1; - tau = 1e-4; + initial_trust_region_radius = 1e4; + max_trust_region_radius = 1e16; + min_trust_region_radius = 1e-32; min_relative_decrease = 1e-3; + lm_min_diagonal = 1e-6; + lm_max_diagonal = 1e32; + max_num_consecutive_invalid_steps = 5; function_tolerance = 1e-6; gradient_tolerance = 1e-10; parameter_tolerance = 1e-8; -#ifndef CERES_NO_SUITESPARSE - linear_solver_type = SPARSE_NORMAL_CHOLESKY; -#else + +#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE) linear_solver_type = DENSE_QR; -#endif // CERES_NO_SUITESPARSE +#else + linear_solver_type = SPARSE_NORMAL_CHOLESKY; +#endif + preconditioner_type = JACOBI; + + sparse_linear_algebra_library = SUITE_SPARSE; +#if defined(CERES_NO_SUITESPARSE) && !defined(CERES_NO_CXSPARSE) + sparse_linear_algebra_library = CX_SPARSE; +#endif + num_linear_solver_threads = 1; num_eliminate_blocks = 0; ordering_type = NATURAL; + +#if defined(CERES_NO_SUITESPARSE) + use_block_amd = false; +#else + use_block_amd = true; +#endif + linear_solver_min_num_iterations = 1; linear_solver_max_num_iterations = 500; eta = 1e-1; @@ -82,10 +105,13 @@ class Solver { logging_type = PER_MINIMIZER_ITERATION; minimizer_progress_to_stdout = false; return_initial_residuals = false; + return_initial_gradient = false; + return_initial_jacobian = false; return_final_residuals = false; + return_final_gradient = false; + return_final_jacobian = false; lsqp_dump_directory = "/tmp"; lsqp_dump_format_type = TEXTFILE; - crash_and_dump_lsqp_on_failure = false; check_gradients = false; gradient_check_relative_precision = 1e-8; numeric_derivative_relative_step_size = 1e-6; @@ -94,27 +120,78 @@ class Solver { // Minimizer options ---------------------------------------- - MinimizerType minimizer_type; + TrustRegionStrategyType trust_region_strategy_type; + + // Type of dogleg strategy to use. + DoglegType dogleg_type; + + // The classical trust region methods are descent methods, in that + // they only accept a point if it strictly reduces the value of + // the objective function. + // + // Relaxing this requirement allows the algorithm to be more + // efficient in the long term at the cost of some local increase + // in the value of the objective function. + // + // This is because allowing for non-decreasing objective function + // values in a princpled manner allows the algorithm to "jump over + // boulders" as the method is not restricted to move into narrow + // valleys while preserving its convergence properties. + // + // Setting use_nonmonotonic_steps to true enables the + // non-monotonic trust region algorithm as described by Conn, + // Gould & Toint in "Trust Region Methods", Section 10.1. + // + // The parameter max_consecutive_nonmonotonic_steps controls the + // window size used by the step selection algorithm to accept + // non-monotonic steps. + // + // Even though the value of the objective function may be larger + // than the minimum value encountered over the course of the + // optimization, the final parameters returned to the user are the + // ones corresponding to the minimum cost over all iterations. + bool use_nonmonotonic_steps; + int max_consecutive_nonmonotonic_steps; // Maximum number of iterations for the minimizer to run for. int max_num_iterations; // Maximum time for which the minimizer should run for. - double max_solver_time_sec; + double max_solver_time_in_seconds; // Number of threads used by Ceres for evaluating the cost and // jacobians. int num_threads; - // For Levenberg-Marquardt, the initial value for the - // regularizer. This is the inversely related to the size of the - // initial trust region. - double tau; + // Trust region minimizer settings. + double initial_trust_region_radius; + double max_trust_region_radius; - // For trust region methods, this is lower threshold for the - // relative decrease before a step is accepted. + // Minimizer terminates when the trust region radius becomes + // smaller than this value. + double min_trust_region_radius; + + // Lower bound for the relative decrease before a step is + // accepted. double min_relative_decrease; + // For the Levenberg-Marquadt algorithm, the scaled diagonal of + // the normal equations J'J is used to control the size of the + // trust region. Extremely small and large values along the + // diagonal can make this regularization scheme + // fail. lm_max_diagonal and lm_min_diagonal, clamp the values of + // diag(J'J) from above and below. In the normal course of + // operation, the user should not have to modify these parameters. + double lm_min_diagonal; + double lm_max_diagonal; + + // Sometimes due to numerical conditioning problems or linear + // solver flakiness, the trust region strategy may return a + // numerically invalid step that can be fixed by reducing the + // trust region size. So the TrustRegionMinimizer allows for a few + // successive invalid steps before it declares NUMERICAL_FAILURE. + int max_num_consecutive_invalid_steps; + // Minimizer terminates when // // (new_cost - old_cost) < function_tolerance * old_cost; @@ -141,6 +218,12 @@ class Solver { // Type of preconditioner to use with the iterative linear solvers. PreconditionerType preconditioner_type; + // Ceres supports using multiple sparse linear algebra libraries + // for sparse matrix ordering and factorizations. Currently, + // SUITE_SPARSE and CX_SPARSE are the valid choices, depending on + // whether they are linked into Ceres at build time. + SparseLinearAlgebraLibraryType sparse_linear_algebra_library; + // Number of threads used by Ceres to solve the Newton // step. Currently only the SPARSE_SCHUR solver is capable of // using this setting. @@ -170,6 +253,19 @@ class Solver { // non-empty. vector ordering; + // By virtue of the modeling layer in Ceres being block oriented, + // all the matrices used by Ceres are also block oriented. When + // doing sparse direct factorization of these matrices (for + // SPARSE_NORMAL_CHOLESKY, SPARSE_SCHUR and ITERATIVE in + // conjunction with CLUSTER_TRIDIAGONAL AND CLUSTER_JACOBI + // preconditioners), the fill-reducing ordering algorithms can + // either be run on the block or the scalar form of these matrices. + // Running it on the block form exposes more of the super-nodal + // structure of the matrix to the factorization routines. Setting + // this parameter to true runs the ordering algorithms in block + // form. Currently this option only makes sense with + // sparse_linear_algebra_library = SUITE_SPARSE. + bool use_block_amd; // Minimum number of iterations for which the linear solver should // run, even if the convergence criterion is satisfied. @@ -206,7 +302,12 @@ class Solver { bool minimizer_progress_to_stdout; bool return_initial_residuals; + bool return_initial_gradient; + bool return_initial_jacobian; + bool return_final_residuals; + bool return_final_gradient; + bool return_final_jacobian; // List of iterations at which the optimizer should dump the // linear least squares problem to disk. Useful for testing and @@ -217,15 +318,6 @@ class Solver { string lsqp_dump_directory; DumpFormatType lsqp_dump_format_type; - // Dump the linear least squares problem to disk if the minimizer - // fails due to NUMERICAL_FAILURE and crash the process. This flag - // is useful for generating debugging information. The problem is - // dumped in a file whose name is determined by - // Solver::Options::lsqp_dump_format. - // - // Note: This requires a version of Ceres built with protocol buffers. - bool crash_and_dump_lsqp_on_failure; - // Finite differences options ---------------------------------------------- // Check all jacobians computed by each residual block with finite @@ -273,16 +365,25 @@ class Solver { bool update_state_every_iteration; // Callbacks that are executed at the end of each iteration of the - // Minimizer. They are executed in the order that they are - // specified in this vector. By default, parameter blocks are - // updated only at the end of the optimization, i.e when the - // Minimizer terminates. This behaviour is controlled by + // Minimizer. An iteration may terminate midway, either due to + // numerical failures or because one of the convergence tests has + // been satisfied. In this case none of the callbacks are + // executed. + + // Callbacks are executed in the order that they are specified in + // this vector. By default, parameter blocks are updated only at + // the end of the optimization, i.e when the Minimizer + // terminates. This behaviour is controlled by // update_state_every_variable. If the user wishes to have access // to the update parameter blocks when his/her callbacks are // executed, then set update_state_every_iteration to true. // // The solver does NOT take ownership of these pointers. vector callbacks; + + // If non-empty, a summary of the execution of the solver is + // recorded to this file. + string solver_log; }; struct Summary { @@ -313,20 +414,74 @@ class Solver { // blocks that they depend on were fixed. double fixed_cost; - // Residuals before and after the optimization. Each vector - // contains problem.NumResiduals() elements. Residuals are in the - // same order in which they were added to the problem object when - // constructing this problem. + // Vectors of residuals before and after the optimization. The + // entries of these vectors are in the order in which + // ResidualBlocks were added to the Problem object. + // + // Whether the residual vectors are populated with values is + // controlled by Solver::Options::return_initial_residuals and + // Solver::Options::return_final_residuals respectively. vector initial_residuals; vector final_residuals; + // Gradient vectors, before and after the optimization. The rows + // are in the same order in which the ParameterBlocks were added + // to the Problem object. + // + // NOTE: Since AddResidualBlock adds ParameterBlocks to the + // Problem automatically if they do not already exist, if you wish + // to have explicit control over the ordering of the vectors, then + // use Problem::AddParameterBlock to explicitly add the + // ParameterBlocks in the order desired. + // + // Whether the vectors are populated with values is controlled by + // Solver::Options::return_initial_gradient and + // Solver::Options::return_final_gradient respectively. + vector initial_gradient; + vector final_gradient; + + // Jacobian matrices before and after the optimization. The rows + // of these matrices are in the same order in which the + // ResidualBlocks were added to the Problem object. The columns + // are in the same order in which the ParameterBlocks were added + // to the Problem object. + // + // NOTE: Since AddResidualBlock adds ParameterBlocks to the + // Problem automatically if they do not already exist, if you wish + // to have explicit control over the column ordering of the + // matrix, then use Problem::AddParameterBlock to explicitly add + // the ParameterBlocks in the order desired. + // + // The Jacobian matrices are stored as compressed row sparse + // matrices. Please see ceres/crs_matrix.h for more details of the + // format. + // + // Whether the Jacboan matrices are populated with values is + // controlled by Solver::Options::return_initial_jacobian and + // Solver::Options::return_final_jacobian respectively. + CRSMatrix initial_jacobian; + CRSMatrix final_jacobian; + vector iterations; int num_successful_steps; int num_unsuccessful_steps; + // When the user calls Solve, before the actual optimization + // occurs, Ceres performs a number of preprocessing steps. These + // include error checks, memory allocations, and reorderings. This + // time is accounted for as preprocessing time. double preprocessor_time_in_seconds; + + // Time spent in the TrustRegionMinimizer. double minimizer_time_in_seconds; + + // After the Minimizer is finished, some time is spent in + // re-evaluating residuals etc. This time is accounted for in the + // postprocessor time. + double postprocessor_time_in_seconds; + + // Some total of all time spent inside Ceres when Solve is called. double total_time_in_seconds; // Preprocessor summary. @@ -354,6 +509,10 @@ class Solver { PreconditionerType preconditioner_type; OrderingType ordering_type; + + TrustRegionStrategyType trust_region_strategy_type; + DoglegType dogleg_type; + SparseLinearAlgebraLibraryType sparse_linear_algebra_library; }; // Once a least squares problem has been built, this function takes diff --git a/extern/libmv/third_party/ceres/include/ceres/types.h b/extern/libmv/third_party/ceres/include/ceres/types.h index a30c79029ac..3980885b53c 100644 --- a/extern/libmv/third_party/ceres/include/ceres/types.h +++ b/extern/libmv/third_party/ceres/include/ceres/types.h @@ -59,14 +59,18 @@ enum LinearSolverType { // normal equations A'A x = A'b. They are direct solvers and do not // assume any special problem structure. - // Solve the normal equations using a sparse cholesky solver; based - // on CHOLMOD. - SPARSE_NORMAL_CHOLESKY, + // Solve the normal equations using a dense Cholesky solver; based + // on Eigen. + DENSE_NORMAL_CHOLESKY, // Solve the normal equations using a dense QR solver; based on // Eigen. DENSE_QR, + // Solve the normal equations using a sparse cholesky solver; requires + // SuiteSparse or CXSparse. + SPARSE_NORMAL_CHOLESKY, + // Specialized solvers, specific to problems with a generalized // bi-partitite structure. @@ -110,6 +114,15 @@ enum PreconditionerType { CLUSTER_TRIDIAGONAL }; +enum SparseLinearAlgebraLibraryType { + // High performance sparse Cholesky factorization and approximate + // minimum degree ordering. + SUITE_SPARSE, + + // A lightweight replacment for SuiteSparse. + CX_SPARSE +}; + enum LinearSolverTerminationType { // Termination criterion was met. For factorization based solvers // the tolerance is assumed to be zero. Any user provided values are @@ -149,8 +162,47 @@ enum LoggingType { PER_MINIMIZER_ITERATION }; -enum MinimizerType { - LEVENBERG_MARQUARDT +// Ceres supports different strategies for computing the trust region +// step. +enum TrustRegionStrategyType { + // The default trust region strategy is to use the step computation + // used in the Levenberg-Marquardt algorithm. For more details see + // levenberg_marquardt_strategy.h + LEVENBERG_MARQUARDT, + + // Powell's dogleg algorithm interpolates between the Cauchy point + // and the Gauss-Newton step. It is particularly useful if the + // LEVENBERG_MARQUARDT algorithm is making a large number of + // unsuccessful steps. For more details see dogleg_strategy.h. + // + // NOTES: + // + // 1. This strategy has not been experimented with or tested as + // extensively as LEVENBERG_MARQUARDT, and therefore it should be + // considered EXPERIMENTAL for now. + // + // 2. For now this strategy should only be used with exact + // factorization based linear solvers, i.e., SPARSE_SCHUR, + // DENSE_SCHUR, DENSE_QR and SPARSE_NORMAL_CHOLESKY. + DOGLEG +}; + +// Ceres supports two different dogleg strategies. +// The "traditional" dogleg method by Powell and the +// "subspace" method described in +// R. H. Byrd, R. B. Schnabel, and G. A. Shultz, +// "Approximate solution of the trust region problem by minimization +// over two-dimensional subspaces", Mathematical Programming, +// 40 (1988), pp. 247--263 +enum DoglegType { + // The traditional approach constructs a dogleg path + // consisting of two line segments and finds the furthest + // point on that path that is still inside the trust region. + TRADITIONAL_DOGLEG, + + // The subspace approach finds the exact minimum of the model + // constrained to the subspace spanned by the dogleg path. + SUBSPACE_DOGLEG }; enum SolverTerminationType { @@ -246,11 +298,15 @@ enum DimensionType { const char* LinearSolverTypeToString(LinearSolverType type); const char* PreconditionerTypeToString(PreconditionerType type); +const char* SparseLinearAlgebraLibraryTypeToString( + SparseLinearAlgebraLibraryType type); const char* LinearSolverTerminationTypeToString( LinearSolverTerminationType type); const char* OrderingTypeToString(OrderingType type); const char* SolverTerminationTypeToString(SolverTerminationType type); - +const char* SparseLinearAlgebraLibraryTypeToString( + SparseLinearAlgebraLibraryType type); +const char* TrustRegionStrategyTypeToString( TrustRegionStrategyType type); bool IsSchurType(LinearSolverType type); } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.h b/extern/libmv/third_party/ceres/internal/ceres/array_utils.cc similarity index 64% rename from extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.h rename to extern/libmv/third_party/ceres/internal/ceres/array_utils.cc index d00bb9095be..673baa4f70f 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.h +++ b/extern/libmv/third_party/ceres/internal/ceres/array_utils.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// Copyright 2012 Google Inc. All rights reserved. // http://code.google.com/p/ceres-solver/ // // Redistribution and use in source and binary forms, with or without @@ -27,39 +27,41 @@ // POSSIBILITY OF SUCH DAMAGE. // // Author: sameeragarwal@google.com (Sameer Agarwal) -// -// Implmentation of Levenberg Marquardt algorithm based on "Methods for -// Nonlinear Least Squares" by K. Madsen, H.B. Nielsen and -// O. Tingleff. Available to download from -// -// http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf -// -#ifndef CERES_INTERNAL_LEVENBERG_MARQUARDT_H_ -#define CERES_INTERNAL_LEVENBERG_MARQUARDT_H_ +#include "ceres/array_utils.h" -#include "ceres/minimizer.h" -#include "ceres/solver.h" +#include +#include +#include "ceres/fpclassify.h" namespace ceres { namespace internal { -class Evaluator; -class LinearSolver; +// It is a near impossibility that user code generates this exact +// value in normal operation, thus we will use it to fill arrays +// before passing them to user code. If on return an element of the +// array still contains this value, we will assume that the user code +// did not write to that memory location. +const double kImpossibleValue = 1e302; -class LevenbergMarquardt : public Minimizer { - public: - virtual ~LevenbergMarquardt(); +bool IsArrayValid(const int size, const double* x) { + if (x != NULL) { + for (int i = 0; i < size; ++i) { + if (!IsFinite(x[i]) || (x[i] == kImpossibleValue)) { + return false; + } + } + } + return true; +} - virtual void Minimize(const Minimizer::Options& options, - Evaluator* evaluator, - LinearSolver* linear_solver, - const double* initial_parameters, - double* final_parameters, - Solver::Summary* summary); -}; +void InvalidateArray(const int size, double* x) { + if (x != NULL) { + for (int i = 0; i < size; ++i) { + x[i] = kImpossibleValue; + } + } +} } // namespace internal } // namespace ceres - -#endif // CERES_INTERNAL_LEVENBERG_MARQUARDT_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/array_utils.h b/extern/libmv/third_party/ceres/internal/ceres/array_utils.h new file mode 100644 index 00000000000..99cc8d8ebbf --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/array_utils.h @@ -0,0 +1,65 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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 Google Inc. 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. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Utility routines for validating arrays. +// +// These are useful for detecting two common class of errors. +// +// 1. Uninitialized memory - where the user for some reason did not +// compute part of an array, but the code expects it. +// +// 2. Numerical failure while computing the cost/residual/jacobian, +// e.g. NaN, infinities etc. This is particularly useful since the +// automatic differentiation code does computations that are not +// evident to the user and can silently generate hard to debug errors. + +#ifndef CERES_INTERNAL_ARRAY_UTILS_H_ +#define CERES_INTERNAL_ARRAY_UTILS_H_ + +#include "ceres/internal/port.h" + +namespace ceres { +namespace internal { + +// Fill the array x with an impossible value that the user code is +// never expected to compute. +void InvalidateArray(int size, double* x); + +// Check if all the entries of the array x are valid, i.e. all the +// values in the array should be finite and none of them should be +// equal to the "impossible" value used by InvalidateArray. +bool IsArrayValid(int size, const double* x); + +extern const double kImpossibleValue; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_ARRAY_UTILS_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.cc b/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.cc index 05e63eb560b..9edc4fa23bd 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.cc @@ -40,16 +40,26 @@ namespace ceres { namespace internal { -void BlockEvaluatePreparer::Init(int** jacobian_layout) { +void BlockEvaluatePreparer::Init(int const* const* jacobian_layout, + int max_derivatives_per_residual_block) { jacobian_layout_ = jacobian_layout; + scratch_evaluate_preparer_.Init(max_derivatives_per_residual_block); } // Point the jacobian blocks directly into the block sparse matrix. void BlockEvaluatePreparer::Prepare(const ResidualBlock* residual_block, int residual_block_index, SparseMatrix* jacobian, - double** jacobians) const { - CHECK(jacobian != NULL); + double** jacobians) { + // If the overall jacobian is not available, use the scratch space. + if (jacobian == NULL) { + scratch_evaluate_preparer_.Prepare(residual_block, + residual_block_index, + jacobian, + jacobians); + return; + } + double* jacobian_values = down_cast(jacobian)->mutable_values(); diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.h b/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.h index a7869311e6e..354acc031f4 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.h +++ b/extern/libmv/third_party/ceres/internal/ceres/block_evaluate_preparer.h @@ -36,6 +36,8 @@ #ifndef CERES_INTERNAL_BLOCK_EVALUATE_PREPARER_H_ #define CERES_INTERNAL_BLOCK_EVALUATE_PREPARER_H_ +#include "ceres/scratch_evaluate_preparer.h" + namespace ceres { namespace internal { @@ -47,18 +49,26 @@ class BlockEvaluatePreparer { // Using Init() instead of a constructor allows for allocating this structure // with new[]. This is because C++ doesn't allow passing arguments to objects // constructed with new[] (as opposed to plain 'new'). - void Init(int** jacobian_layout); + void Init(int const* const* jacobian_layout, + int max_derivatives_per_residual_block); // EvaluatePreparer interface - // Point the jacobian blocks directly into the block sparse matrix. + // Point the jacobian blocks directly into the block sparse matrix, if + // jacobian is non-null. Otherwise, uses an internal per-thread buffer to + // store the jacobians temporarily. void Prepare(const ResidualBlock* residual_block, int residual_block_index, SparseMatrix* jacobian, - double** jacobians) const; + double** jacobians); private: int const* const* jacobian_layout_; + + // For the case that the overall jacobian is not available, but the + // individual jacobians are requested, use a pass-through scratch evaluate + // preparer. + ScratchEvaluatePreparer scratch_evaluate_preparer_; }; } // namespace internal diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc index 1a5001f9c71..474c37f7ca4 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/block_jacobi_preconditioner.cc @@ -40,11 +40,10 @@ namespace ceres { namespace internal { -BlockJacobiPreconditioner::BlockJacobiPreconditioner( - const LinearOperator& A) - : block_structure_( - *(down_cast(&A)->block_structure())), - num_rows_(A.num_rows()) { +BlockJacobiPreconditioner::BlockJacobiPreconditioner(const LinearOperator& A) + : num_rows_(A.num_rows()), + block_structure_( + *(down_cast(&A)->block_structure())) { // Calculate the amount of storage needed. int storage_needed = 0; for (int c = 0; c < block_structure_.cols.size(); ++c) { diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.cc b/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.cc index 52a58bb43a6..f90c350cc80 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/block_jacobian_writer.cc @@ -136,9 +136,12 @@ BlockJacobianWriter::BlockJacobianWriter(const Evaluator::Options& options, // makes the final Write() a nop. BlockEvaluatePreparer* BlockJacobianWriter::CreateEvaluatePreparers( int num_threads) { + int max_derivatives_per_residual_block = + program_->MaxDerivativesPerResidualBlock(); + BlockEvaluatePreparer* preparers = new BlockEvaluatePreparer[num_threads]; for (int i = 0; i < num_threads; i++) { - preparers[i].Init(&jacobian_layout_[0]); + preparers[i].Init(&jacobian_layout_[0], max_derivatives_per_residual_block); } return preparers; } diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc index 2afaf5e2ea2..0f95e8932b8 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.cc @@ -28,10 +28,10 @@ // // Author: sameeragarwal@google.com (Sameer Agarwal) +#include "glog/logging.h" #include "ceres/block_random_access_dense_matrix.h" #include -#include #include "ceres/internal/eigen.h" #include "ceres/internal/scoped_ptr.h" diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h index 3a0096209f7..9f27a4c30f3 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_dense_matrix.h @@ -89,7 +89,7 @@ class BlockRandomAccessDenseMatrix : public BlockRandomAccessMatrix { vector block_layout_; scoped_array values_; - DISALLOW_COPY_AND_ASSIGN(BlockRandomAccessDenseMatrix); + CERES_DISALLOW_COPY_AND_ASSIGN(BlockRandomAccessDenseMatrix); }; } // namespace internal diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.h index f398af3be87..b76cb78b160 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.h +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_matrix.h @@ -77,7 +77,7 @@ namespace internal { // // if (cell != NULL) { // MatrixRef m(cell->values, row_stride, col_stride); -// MutexLock l(&cell->m); +// CeresMutexLock l(&cell->m); // m.block(row, col, row_block_size, col_block_size) = ... // } diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc index c496fcd13de..9ed62ce948b 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.cc @@ -28,17 +28,17 @@ // // Author: sameeragarwal@google.com (Sameer Agarwal) +#include "glog/logging.h" #include "ceres/block_random_access_sparse_matrix.h" #include #include #include #include -#include -#include "ceres/mutex.h" -#include "ceres/triplet_sparse_matrix.h" #include "ceres/internal/port.h" #include "ceres/internal/scoped_ptr.h" +#include "ceres/mutex.h" +#include "ceres/triplet_sparse_matrix.h" #include "ceres/types.h" namespace ceres { diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h index 12613c3daa0..48a00437cf6 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h +++ b/extern/libmv/third_party/ceres/internal/ceres/block_random_access_sparse_matrix.h @@ -38,6 +38,7 @@ #include "ceres/block_random_access_matrix.h" #include "ceres/collections_port.h" #include "ceres/triplet_sparse_matrix.h" +#include "ceres/integral_types.h" #include "ceres/internal/macros.h" #include "ceres/internal/port.h" #include "ceres/internal/scoped_ptr.h" @@ -84,11 +85,11 @@ class BlockRandomAccessSparseMatrix : public BlockRandomAccessMatrix { TripletSparseMatrix* mutable_matrix() { return tsm_.get(); } private: - long int IntPairToLong(int a, int b) { + int64 IntPairToLong(int a, int b) { return a * kMaxRowBlocks + b; } - const int kMaxRowBlocks; + const int64 kMaxRowBlocks; // row/column block sizes. const vector blocks_; @@ -100,7 +101,8 @@ class BlockRandomAccessSparseMatrix : public BlockRandomAccessMatrix { // The underlying matrix object which actually stores the cells. scoped_ptr tsm_; - DISALLOW_COPY_AND_ASSIGN(BlockRandomAccessSparseMatrix); + friend class BlockRandomAccessSparseMatrixTest; + CERES_DISALLOW_COPY_AND_ASSIGN(BlockRandomAccessSparseMatrix); }; } // namespace internal diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc index 7dd395e2975..dbe5ec93ef0 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.cc @@ -33,11 +33,11 @@ #include #include #include -#include #include "ceres/block_structure.h" +#include "ceres/internal/eigen.h" #include "ceres/matrix_proto.h" #include "ceres/triplet_sparse_matrix.h" -#include "ceres/internal/eigen.h" +#include "glog/logging.h" namespace ceres { namespace internal { @@ -81,7 +81,7 @@ BlockSparseMatrix::BlockSparseMatrix( CHECK_NOTNULL(values_.get()); } -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS BlockSparseMatrix::BlockSparseMatrix(const SparseMatrixProto& outer_proto) { CHECK(outer_proto.has_block_matrix()); @@ -244,7 +244,7 @@ const CompressedRowBlockStructure* BlockSparseMatrix::block_structure() return block_structure_.get(); } -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS void BlockSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const { outer_proto->Clear(); diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h index f71446e8f58..513d398c54d 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h +++ b/extern/libmv/third_party/ceres/internal/ceres/block_sparse_matrix.h @@ -74,7 +74,7 @@ class BlockSparseMatrixBase : public SparseMatrix { virtual const double* RowBlockValues(int row_block_index) const = 0; private: - DISALLOW_COPY_AND_ASSIGN(BlockSparseMatrixBase); + CERES_DISALLOW_COPY_AND_ASSIGN(BlockSparseMatrixBase); }; // This class implements the SparseMatrix interface for storing and @@ -96,7 +96,7 @@ class BlockSparseMatrix : public BlockSparseMatrixBase { explicit BlockSparseMatrix(CompressedRowBlockStructure* block_structure); // Construct a block sparse matrix from a protocol buffer. -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS explicit BlockSparseMatrix(const SparseMatrixProto& proto); #endif @@ -110,7 +110,7 @@ class BlockSparseMatrix : public BlockSparseMatrixBase { virtual void SquaredColumnNorm(double* x) const; virtual void ScaleColumns(const double* scale); virtual void ToDenseMatrix(Matrix* dense_matrix) const; -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS virtual void ToProto(SparseMatrixProto* proto) const; #endif virtual void ToTextFile(FILE* file) const; @@ -135,7 +135,7 @@ class BlockSparseMatrix : public BlockSparseMatrixBase { int num_nonzeros_; scoped_array values_; scoped_ptr block_structure_; - DISALLOW_COPY_AND_ASSIGN(BlockSparseMatrix); + CERES_DISALLOW_COPY_AND_ASSIGN(BlockSparseMatrix); }; } // namespace internal diff --git a/extern/libmv/third_party/ceres/internal/ceres/block_structure.cc b/extern/libmv/third_party/ceres/internal/ceres/block_structure.cc index 5add4f3b94d..e61131192af 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/block_structure.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/block_structure.cc @@ -38,7 +38,7 @@ bool CellLessThan(const Cell& lhs, const Cell& rhs) { return (lhs.block_id < rhs.block_id); } -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS void ProtoToBlockStructure(const BlockStructureProto &proto, CompressedRowBlockStructure *block_structure) { // Decode the column blocks. diff --git a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc index 53190ada6fc..d0dc1e670c2 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/canonical_views_clustering.cc @@ -31,11 +31,11 @@ #include "ceres/canonical_views_clustering.h" -#include -#include "ceres/graph.h" #include "ceres/collections_port.h" -#include "ceres/map_util.h" +#include "ceres/graph.h" #include "ceres/internal/macros.h" +#include "ceres/map_util.h" +#include "glog/logging.h" namespace ceres { namespace internal { @@ -75,7 +75,7 @@ class CanonicalViewsClustering { IntMap view_to_canonical_view_; // Maps a view to its similarity to its current cluster center. HashMap view_to_canonical_view_similarity_; - DISALLOW_COPY_AND_ASSIGN(CanonicalViewsClustering); + CERES_DISALLOW_COPY_AND_ASSIGN(CanonicalViewsClustering); }; void ComputeCanonicalViewsClustering( diff --git a/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h b/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h index dd36f99006b..877b4c4ceea 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h +++ b/extern/libmv/third_party/ceres/internal/ceres/cgnr_solver.h @@ -57,7 +57,7 @@ class CgnrSolver : public LinearSolver { private: const LinearSolver::Options options_; scoped_ptr jacobi_preconditioner_; - DISALLOW_COPY_AND_ASSIGN(CgnrSolver); + CERES_DISALLOW_COPY_AND_ASSIGN(CgnrSolver); }; } // namespace internal diff --git a/extern/libmv/third_party/ceres/internal/ceres/collections_port.h b/extern/libmv/third_party/ceres/internal/ceres/collections_port.h index 9dff0efe245..c2fce9033cd 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/collections_port.h +++ b/extern/libmv/third_party/ceres/internal/ceres/collections_port.h @@ -33,31 +33,49 @@ #ifndef CERES_INTERNAL_COLLECTIONS_PORT_H_ #define CERES_INTERNAL_COLLECTIONS_PORT_H_ -#ifdef CERES_HASH_BOOST -#include -#include +#if defined(CERES_NO_TR1) +# include +# include #else -#if defined(_MSC_VER) && _MSC_VER <= 1700 -#include -#include -#else -#include -#include +# if defined(_MSC_VER) && _MSC_VER <= 1600 +# include +# include +# else +# include +# include +# endif #endif -#endif - #include #include "ceres/integral_types.h" #include "ceres/internal/port.h" +// Some systems don't have access to TR1. In that case, substitute the hash +// map/set with normal map/set. The price to pay is slightly slower speed for +// some operations. +#if defined(CERES_NO_TR1) + namespace ceres { namespace internal { template -struct HashMap : tr1::unordered_map {}; +struct HashMap : map {}; template -struct HashSet : tr1::unordered_set {}; +struct HashSet : set {}; + +} // namespace internal +} // namespace ceres + +#else + +namespace ceres { +namespace internal { + +template +struct HashMap : std::tr1::unordered_map {}; + +template +struct HashSet : std::tr1::unordered_set {}; #if defined(_WIN32) && !defined(__MINGW64__) && !defined(__MINGW32__) #define GG_LONGLONG(x) x##I64 @@ -124,11 +142,7 @@ CERES_HASH_NAMESPACE_START // Hasher for STL pairs. Requires hashers for both members to be defined. template -#ifdef CERES_HASH_BOOST -struct hash { -#else struct hash > { -#endif size_t operator()(const pair& p) const { size_t h1 = hash()(p.first); size_t h2 = hash()(p.second); @@ -148,4 +162,6 @@ struct hash > { CERES_HASH_NAMESPACE_END +#endif // CERES_NO_TR1 + #endif // CERES_INTERNAL_COLLECTIONS_PORT_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc index aa883b7d353..912c4845441 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_jacobian_writer.cc @@ -130,8 +130,24 @@ SparseMatrix* CompressedRowJacobianWriter::CreateJacobian() const { } row_pos += num_residuals; } - CHECK_EQ(num_jacobian_nonzeros, rows[total_num_residuals]); + + // Populate the row and column block vectors for use by block + // oriented ordering algorithms. This is useful when + // Solver::Options::use_block_amd = true. + const vector& parameter_blocks = program_->parameter_blocks(); + vector& col_blocks = *(jacobian->mutable_col_blocks()); + col_blocks.resize(parameter_blocks.size()); + for (int i = 0; i < parameter_blocks.size(); ++i) { + col_blocks[i] = parameter_blocks[i]->LocalSize(); + } + + vector& row_blocks = *(jacobian->mutable_row_blocks()); + row_blocks.resize(residual_blocks.size()); + for (int i = 0; i < residual_blocks.size(); ++i) { + row_blocks[i] = residual_blocks[i]->NumResiduals(); + } + return jacobian; } diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc index 95edf5396af..1b61468aaae 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc @@ -32,15 +32,22 @@ #include #include -#include "ceres/matrix_proto.h" +#include "ceres/crs_matrix.h" #include "ceres/internal/port.h" +#include "ceres/matrix_proto.h" namespace ceres { namespace internal { namespace { // Helper functor used by the constructor for reordering the contents -// of a TripletSparseMatrix. +// of a TripletSparseMatrix. This comparator assumes thay there are no +// duplicates in the pair of arrays rows and cols, i.e., there is no +// indices i and j (not equal to each other) s.t. +// +// rows[i] == rows[j] && cols[i] == cols[j] +// +// If this is the case, this functor will not be a StrictWeakOrdering. struct RowColLessThan { RowColLessThan(const int* rows, const int* cols) : rows(rows), cols(cols) { @@ -128,7 +135,7 @@ CompressedRowSparseMatrix::CompressedRowSparseMatrix( CHECK_EQ(num_nonzeros(), m.num_nonzeros()); } -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS CompressedRowSparseMatrix::CompressedRowSparseMatrix( const SparseMatrixProto& outer_proto) { CHECK(outer_proto.has_compressed_row_matrix()); @@ -241,7 +248,7 @@ void CompressedRowSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const { } } -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS void CompressedRowSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const { CHECK_NOTNULL(outer_proto); @@ -330,5 +337,18 @@ void CompressedRowSparseMatrix::ToTextFile(FILE* file) const { } } +void CompressedRowSparseMatrix::ToCRSMatrix(CRSMatrix* matrix) const { + matrix->num_rows = num_rows(); + matrix->num_cols = num_cols(); + + matrix->rows.resize(matrix->num_rows + 1); + matrix->cols.resize(num_nonzeros()); + matrix->values.resize(num_nonzeros()); + + copy(rows_.get(), rows_.get() + matrix->num_rows + 1, matrix->rows.begin()); + copy(cols_.get(), cols_.get() + num_nonzeros(), matrix->cols.begin()); + copy(values_.get(), values_.get() + num_nonzeros(), matrix->values.begin()); +} + } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h index 9a39d28e111..6a9d82842e5 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h +++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.h @@ -31,14 +31,19 @@ #ifndef CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_ #define CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_ +#include #include #include "ceres/sparse_matrix.h" #include "ceres/triplet_sparse_matrix.h" #include "ceres/internal/eigen.h" #include "ceres/internal/macros.h" +#include "ceres/internal/port.h" #include "ceres/types.h" namespace ceres { + +class CRSMatrix; + namespace internal { class SparseMatrixProto; @@ -52,7 +57,7 @@ class CompressedRowSparseMatrix : public SparseMatrix { // // We assume that m does not have any repeated entries. explicit CompressedRowSparseMatrix(const TripletSparseMatrix& m); -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS explicit CompressedRowSparseMatrix(const SparseMatrixProto& proto); #endif @@ -85,7 +90,7 @@ class CompressedRowSparseMatrix : public SparseMatrix { virtual void ScaleColumns(const double* scale); virtual void ToDenseMatrix(Matrix* dense_matrix) const; -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS virtual void ToProto(SparseMatrixProto* proto) const; #endif virtual void ToTextFile(FILE* file) const; @@ -103,6 +108,8 @@ class CompressedRowSparseMatrix : public SparseMatrix { // have the same number of columns as this matrix. void AppendRows(const CompressedRowSparseMatrix& m); + void ToCRSMatrix(CRSMatrix* matrix) const; + // Low level access methods that expose the structure of the matrix. const int* cols() const { return cols_.get(); } int* mutable_cols() { return cols_.get(); } @@ -110,6 +117,12 @@ class CompressedRowSparseMatrix : public SparseMatrix { const int* rows() const { return rows_.get(); } int* mutable_rows() { return rows_.get(); } + const vector& row_blocks() const { return row_blocks_; } + vector* mutable_row_blocks() { return &row_blocks_; } + + const vector& col_blocks() const { return col_blocks_; } + vector* mutable_col_blocks() { return &col_blocks_; } + private: scoped_array cols_; scoped_array rows_; @@ -117,10 +130,17 @@ class CompressedRowSparseMatrix : public SparseMatrix { int num_rows_; int num_cols_; - int max_num_nonzeros_; - DISALLOW_COPY_AND_ASSIGN(CompressedRowSparseMatrix); + // If the matrix has an underlying block structure, then it can also + // carry with it row and column block sizes. This is auxilliary and + // optional information for use by algorithms operating on the + // matrix. The class itself does not make use of this information in + // any way. + vector row_blocks_; + vector col_blocks_; + + CERES_DISALLOW_COPY_AND_ASSIGN(CompressedRowSparseMatrix); }; } // namespace internal diff --git a/extern/libmv/third_party/ceres/internal/ceres/conditioned_cost_function.cc b/extern/libmv/third_party/ceres/internal/ceres/conditioned_cost_function.cc index ca80bfb9c9d..7322790f717 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/conditioned_cost_function.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/conditioned_cost_function.cc @@ -34,10 +34,10 @@ #include -#include -#include "ceres/stl_util.h" #include "ceres/internal/eigen.h" +#include "ceres/stl_util.h" #include "ceres/types.h" +#include "glog/logging.h" namespace ceres { diff --git a/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc index 75f9e043fa5..ae8e8774709 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.cc @@ -41,18 +41,18 @@ #include #include -#include -#include "ceres/linear_operator.h" +#include "ceres/fpclassify.h" #include "ceres/internal/eigen.h" +#include "ceres/linear_operator.h" #include "ceres/types.h" -#include "ceres/jet.h" +#include "glog/logging.h" namespace ceres { namespace internal { namespace { bool IsZeroOrInfinity(double x) { - return ((x == 0.0) || (isinf(x))); + return ((x == 0.0) || (IsInfinite(x))); } // Constant used in the MATLAB implementation ~ 2 * eps. @@ -115,7 +115,7 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve( for (summary.num_iterations = 1; summary.num_iterations < options_.max_num_iterations; ++summary.num_iterations) { - VLOG(2) << "cg iteration " << summary.num_iterations; + VLOG(3) << "cg iteration " << summary.num_iterations; // Apply preconditioner if (per_solve_options.preconditioner != NULL) { @@ -151,14 +151,14 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve( A->RightMultiply(p.data(), q.data()); double pq = p.dot(q); - if ((pq <= 0) || isinf(pq)) { + if ((pq <= 0) || IsInfinite(pq)) { LOG(ERROR) << "Numerical failure. pq = " << pq; summary.termination_type = FAILURE; break; } double alpha = rho / pq; - if (isinf(alpha)) { + if (IsInfinite(alpha)) { LOG(ERROR) << "Numerical failure. alpha " << alpha; summary.termination_type = FAILURE; break; @@ -202,13 +202,13 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve( // 1. Stephen G. Nash & Ariela Sofer, Assessing A Search // Direction Within A Truncated Newton Method, Operation // Research Letters 9(1990) 219-221. - // + // // 2. Stephen G. Nash, A Survey of Truncated Newton Methods, // Journal of Computational and Applied Mathematics, // 124(1-2), 45-59, 2000. // double zeta = summary.num_iterations * (Q1 - Q0) / Q1; - VLOG(2) << "Q termination: zeta " << zeta + VLOG(3) << "Q termination: zeta " << zeta << " " << per_solve_options.q_tolerance; if (zeta < per_solve_options.q_tolerance) { summary.termination_type = TOLERANCE; @@ -218,7 +218,7 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve( // Residual based termination. norm_r = r. norm(); - VLOG(2) << "R termination: norm_r " << norm_r + VLOG(3) << "R termination: norm_r " << norm_r << " " << tol_r; if (norm_r <= tol_r) { summary.termination_type = TOLERANCE; diff --git a/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.h b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.h index 57f99e31db7..b8dfa56b526 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.h +++ b/extern/libmv/third_party/ceres/internal/ceres/conjugate_gradients_solver.h @@ -65,7 +65,7 @@ class ConjugateGradientsSolver : public LinearSolver { private: const LinearSolver::Options options_; - DISALLOW_COPY_AND_ASSIGN(ConjugateGradientsSolver); + CERES_DISALLOW_COPY_AND_ASSIGN(ConjugateGradientsSolver); }; } // namespace internal diff --git a/extern/libmv/third_party/ceres/internal/ceres/corrector.cc b/extern/libmv/third_party/ceres/internal/ceres/corrector.cc index 4ca2c6f6c86..eff4dff8566 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/corrector.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/corrector.cc @@ -32,8 +32,8 @@ #include #include -#include #include "ceres/internal/eigen.h" +#include "glog/logging.h" namespace ceres { namespace internal { diff --git a/extern/libmv/third_party/ceres/internal/ceres/cxsparse.cc b/extern/libmv/third_party/ceres/internal/ceres/cxsparse.cc new file mode 100644 index 00000000000..ca36ce07614 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/cxsparse.cc @@ -0,0 +1,130 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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 Google Inc. 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. +// +// Author: strandmark@google.com (Petter Strandmark) + +#ifndef CERES_NO_CXSPARSE + +#include "ceres/cxsparse.h" + +#include "ceres/compressed_row_sparse_matrix.h" +#include "ceres/triplet_sparse_matrix.h" +#include "glog/logging.h" + +namespace ceres { +namespace internal { + +CXSparse::CXSparse() : scratch_size_(0), scratch_(NULL) { +} + +CXSparse::~CXSparse() { + if (scratch_size_ > 0) { + cs_free(scratch_); + } +} + +bool CXSparse::SolveCholesky(cs_di* A, + cs_dis* symbolic_factorization, + double* b) { + // Make sure we have enough scratch space available. + if (scratch_size_ < A->n) { + if (scratch_size_ > 0) { + cs_free(scratch_); + } + scratch_ = reinterpret_cast(cs_malloc(A->n, sizeof(CS_ENTRY))); + } + + // Solve using Cholesky factorization + csn* numeric_factorization = cs_chol(A, symbolic_factorization); + if (numeric_factorization == NULL) { + LOG(WARNING) << "Cholesky factorization failed."; + return false; + } + + // When the Cholesky factorization succeeded, these methods are guaranteed to + // succeeded as well. In the comments below, "x" refers to the scratch space. + // + // Set x = P * b. + cs_ipvec(symbolic_factorization->pinv, b, scratch_, A->n); + + // Set x = L \ x. + cs_lsolve(numeric_factorization->L, scratch_); + + // Set x = L' \ x. + cs_ltsolve(numeric_factorization->L, scratch_); + + // Set b = P' * x. + cs_pvec(symbolic_factorization->pinv, scratch_, b, A->n); + + // Free Cholesky factorization. + cs_nfree(numeric_factorization); + return true; +} + +cs_dis* CXSparse::AnalyzeCholesky(cs_di* A) { + // order = 1 for Cholesky factorization. + return cs_schol(1, A); +} + +cs_di CXSparse::CreateSparseMatrixTransposeView(CompressedRowSparseMatrix* A) { + cs_di At; + At.m = A->num_cols(); + At.n = A->num_rows(); + At.nz = -1; + At.nzmax = A->num_nonzeros(); + At.p = A->mutable_rows(); + At.i = A->mutable_cols(); + At.x = A->mutable_values(); + return At; +} + +cs_di* CXSparse::CreateSparseMatrix(TripletSparseMatrix* tsm) { + cs_di_sparse tsm_wrapper; + tsm_wrapper.nzmax = tsm->num_nonzeros();; + tsm_wrapper.nz = tsm->num_nonzeros();; + tsm_wrapper.m = tsm->num_rows(); + tsm_wrapper.n = tsm->num_cols(); + tsm_wrapper.p = tsm->mutable_cols(); + tsm_wrapper.i = tsm->mutable_rows(); + tsm_wrapper.x = tsm->mutable_values(); + + return cs_compress(&tsm_wrapper); +} + +void CXSparse::Free(cs_di* factor) { + cs_free(factor); +} + +void CXSparse::Free(cs_dis* factor) { + cs_sfree(factor); +} + +} // namespace internal +} // namespace ceres + +#endif // CERES_NO_CXSPARSE diff --git a/extern/libmv/third_party/ceres/internal/ceres/cxsparse.h b/extern/libmv/third_party/ceres/internal/ceres/cxsparse.h new file mode 100644 index 00000000000..d3b64fcd1a5 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/cxsparse.h @@ -0,0 +1,90 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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 Google Inc. 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. +// +// Author: strandmark@google.com (Petter Strandmark) + +#ifndef CERES_INTERNAL_CXSPARSE_H_ +#define CERES_INTERNAL_CXSPARSE_H_ + +#ifndef CERES_NO_CXSPARSE + +#include "cs.h" + +namespace ceres { +namespace internal { + +class CompressedRowSparseMatrix; +class TripletSparseMatrix; + +// This object provides access to solving linear systems using Cholesky +// factorization with a known symbolic factorization. This features does not +// explicity exist in CXSparse. The methods in the class are nonstatic because +// the class manages internal scratch space. +class CXSparse { + public: + CXSparse(); + ~CXSparse(); + + // Solves a symmetric linear system A * x = b using Cholesky factorization. + // A - The system matrix. + // symbolic_factorization - The symbolic factorization of A. This is obtained + // from AnalyzeCholesky. + // b - The right hand size of the linear equation. This + // array will also recieve the solution. + // Returns false if Cholesky factorization of A fails. + bool SolveCholesky(cs_di* A, cs_dis* symbolic_factorization, double* b); + + // Creates a sparse matrix from a compressed-column form. No memory is + // allocated or copied; the structure A is filled out with info from the + // argument. + cs_di CreateSparseMatrixTransposeView(CompressedRowSparseMatrix* A); + + // Creates a new matrix from a triplet form. Deallocate the returned matrix + // with Free. May return NULL if the compression or allocation fails. + cs_di* CreateSparseMatrix(TripletSparseMatrix* A); + + // Computes a symbolic factorization of A that can be used in SolveCholesky. + // The returned matrix should be deallocated with Free when not used anymore. + cs_dis* AnalyzeCholesky(cs_di* A); + + // Deallocates the memory of a matrix obtained from AnalyzeCholesky. + void Free(cs_di* factor); + void Free(cs_dis* factor); + + private: + // Cached scratch space + CS_ENTRY* scratch_; + int scratch_size_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_NO_CXSPARSE + +#endif // CERES_INTERNAL_CXSPARSE_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.cc new file mode 100644 index 00000000000..f6bb99abf63 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.cc @@ -0,0 +1,86 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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 Google Inc. 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. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/dense_normal_cholesky_solver.h" + +#include + +#include "Eigen/Dense" +#include "ceres/dense_sparse_matrix.h" +#include "ceres/linear_solver.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +DenseNormalCholeskySolver::DenseNormalCholeskySolver( + const LinearSolver::Options& options) + : options_(options) {} + +LinearSolver::Summary DenseNormalCholeskySolver::SolveImpl( + DenseSparseMatrix* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x) { + const int num_rows = A->num_rows(); + const int num_cols = A->num_cols(); + + ConstAlignedMatrixRef Aref = A->matrix(); + Matrix lhs(num_cols, num_cols); + lhs.setZero(); + + // lhs += A'A + // + // Using rankUpdate instead of GEMM, exposes the fact that its the + // same matrix being multiplied with itself and that the product is + // symmetric. + lhs.selfadjointView().rankUpdate(Aref.transpose()); + + // rhs = A'b + Vector rhs = Aref.transpose() * ConstVectorRef(b, num_rows); + + if (per_solve_options.D != NULL) { + ConstVectorRef D(per_solve_options.D, num_cols); + lhs += D.array().square().matrix().asDiagonal(); + } + + VectorRef(x, num_cols) = + lhs.selfadjointView().ldlt().solve(rhs); + + LinearSolver::Summary summary; + summary.num_iterations = 1; + summary.termination_type = TOLERANCE; + return summary; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.h b/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.h new file mode 100644 index 00000000000..de47740583d --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/dense_normal_cholesky_solver.h @@ -0,0 +1,95 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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 Google Inc. 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. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Solve dense rectangular systems Ax = b by forming the normal +// equations and solving them using the Cholesky factorization. + +#ifndef CERES_INTERNAL_DENSE_NORMAL_CHOLESKY_SOLVER_H_ +#define CERES_INTERNAL_DENSE_NORMAL_CHOLESKY_SOLVER_H_ + +#include "ceres/linear_solver.h" +#include "ceres/internal/macros.h" + +namespace ceres { +namespace internal { + +class DenseSparseMatrix; + +// This class implements the LinearSolver interface for solving +// rectangular/unsymmetric (well constrained) linear systems of the +// form +// +// Ax = b +// +// Since there does not usually exist a solution that satisfies these +// equations, the solver instead solves the linear least squares +// problem +// +// min_x |Ax - b|^2 +// +// Setting the gradient of the above optimization problem to zero +// gives us the normal equations +// +// A'Ax = A'b +// +// A'A is a positive definite matrix (hopefully), and the resulting +// linear system can be solved using Cholesky factorization. +// +// If the PerSolveOptions struct has a non-null array D, then the +// augmented/regularized linear system +// +// [ A ]x = [b] +// [ diag(D) ] [0] +// +// is solved. +// +// This class uses the LDLT factorization routines from the Eigen +// library. This solver always returns a solution, it is the user's +// responsibility to judge if the solution is good enough for their +// purposes. +class DenseNormalCholeskySolver: public DenseSparseMatrixSolver { + public: + explicit DenseNormalCholeskySolver(const LinearSolver::Options& options); + + private: + virtual LinearSolver::Summary SolveImpl( + DenseSparseMatrix* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double* x); + + const LinearSolver::Options options_; + CERES_DISALLOW_COPY_AND_ASSIGN(DenseNormalCholeskySolver); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_DENSE_NORMAL_CHOLESKY_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc index 328505404d7..2b329ee0e9c 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.cc @@ -33,8 +33,8 @@ #include #include "Eigen/Dense" +#include "ceres/dense_sparse_matrix.h" #include "ceres/linear_solver.h" -#include "ceres/triplet_sparse_matrix.h" #include "ceres/internal/eigen.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/types.h" @@ -62,7 +62,7 @@ LinearSolver::Summary DenseQRSolver::SolveImpl( } // rhs = [b;0] to account for the additional rows in the lhs. - Vector rhs(num_rows + ((per_solve_options.D !=NULL) ? num_cols : 0)); + Vector rhs(num_rows + ((per_solve_options.D != NULL) ? num_cols : 0)); rhs.setZero(); rhs.head(num_rows) = ConstVectorRef(b, num_rows); diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h index 990c8d445eb..dd683a8c4ea 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h +++ b/extern/libmv/third_party/ceres/internal/ceres/dense_qr_solver.h @@ -28,7 +28,7 @@ // // Author: sameeragarwal@google.com (Sameer Agarwal) // -// Solve dense rectangular systems Ax = b using the QR factoriztion. +// Solve dense rectangular systems Ax = b using the QR factorization. #ifndef CERES_INTERNAL_DENSE_QR_SOLVER_H_ #define CERES_INTERNAL_DENSE_QR_SOLVER_H_ @@ -90,7 +90,7 @@ class DenseQRSolver: public DenseSparseMatrixSolver { double* x); const LinearSolver::Options options_; - DISALLOW_COPY_AND_ASSIGN(DenseQRSolver); + CERES_DISALLOW_COPY_AND_ASSIGN(DenseQRSolver); }; } // namespace internal diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc index 5d392ba6c3b..86730cc101b 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.cc @@ -67,7 +67,7 @@ DenseSparseMatrix::DenseSparseMatrix(const Matrix& m) has_diagonal_reserved_(false) { } -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS DenseSparseMatrix::DenseSparseMatrix(const SparseMatrixProto& outer_proto) : m_(Eigen::MatrixXd::Zero( outer_proto.dense_matrix().num_rows(), @@ -108,7 +108,7 @@ void DenseSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const { *dense_matrix = m_; } -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS void DenseSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const { CHECK(!has_diagonal_appended_) << "Not supported."; outer_proto->Clear(); @@ -183,7 +183,7 @@ void DenseSparseMatrix::ToTextFile(FILE* file) const { CHECK_NOTNULL(file); const int active_rows = (has_diagonal_reserved_ && !has_diagonal_appended_) - ? (m_.rows() - m_.cols()) + ? (m_.rows() - m_.cols()) : m_.rows(); for (int r = 0; r < active_rows; ++r) { diff --git a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h index 416c2143c2c..e7ad14d0ee6 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h +++ b/extern/libmv/third_party/ceres/internal/ceres/dense_sparse_matrix.h @@ -52,7 +52,7 @@ class DenseSparseMatrix : public SparseMatrix { // m. This assumes that m does not have any repeated entries. explicit DenseSparseMatrix(const TripletSparseMatrix& m); explicit DenseSparseMatrix(const Matrix& m); -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS explicit DenseSparseMatrix(const SparseMatrixProto& proto); #endif @@ -67,7 +67,7 @@ class DenseSparseMatrix : public SparseMatrix { virtual void SquaredColumnNorm(double* x) const; virtual void ScaleColumns(const double* scale); virtual void ToDenseMatrix(Matrix* dense_matrix) const; -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS virtual void ToProto(SparseMatrixProto* proto) const; #endif virtual void ToTextFile(FILE* file) const; diff --git a/extern/libmv/third_party/ceres/internal/ceres/detect_structure.cc b/extern/libmv/third_party/ceres/internal/ceres/detect_structure.cc index e9755043bab..ea5bf2e9690 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/detect_structure.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/detect_structure.cc @@ -28,9 +28,9 @@ // // Author: sameeragarwal@google.com (Sameer Agarwal) -#include #include "ceres/detect_structure.h" #include "ceres/internal/eigen.h" +#include "glog/logging.h" namespace ceres { namespace internal { @@ -60,10 +60,10 @@ void DetectStructure(const CompressedRowBlockStructure& bs, *row_block_size = row.block.size; } else if (*row_block_size != Eigen::Dynamic && *row_block_size != row.block.size) { - *row_block_size = Eigen::Dynamic; VLOG(2) << "Dynamic row block size because the block size changed from " << *row_block_size << " to " << row.block.size; + *row_block_size = Eigen::Dynamic; } @@ -71,10 +71,10 @@ void DetectStructure(const CompressedRowBlockStructure& bs, *e_block_size = bs.cols[e_block_id].size; } else if (*e_block_size != Eigen::Dynamic && *e_block_size != bs.cols[e_block_id].size) { - *e_block_size = Eigen::Dynamic; VLOG(2) << "Dynamic e block size because the block size changed from " << *e_block_size << " to " << bs.cols[e_block_id].size; + *e_block_size = Eigen::Dynamic; } if (*f_block_size == 0) { @@ -85,11 +85,11 @@ void DetectStructure(const CompressedRowBlockStructure& bs, } else if (*f_block_size != Eigen::Dynamic) { for (int c = 1; c < row.cells.size(); ++c) { if (*f_block_size != bs.cols[row.cells[c].block_id].size) { - *f_block_size = Eigen::Dynamic; VLOG(2) << "Dynamic f block size because the block size " - << "changed from " << *f_block_size << " to " - << bs.cols[row.cells[c].block_id].size; - break; + << "changed from " << *f_block_size << " to " + << bs.cols[row.cells[c].block_id].size; + *f_block_size = Eigen::Dynamic; + break; } } } diff --git a/extern/libmv/third_party/ceres/internal/ceres/detect_structure.h b/extern/libmv/third_party/ceres/internal/ceres/detect_structure.h index 8af4f236690..5f8e1b4ff46 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/detect_structure.h +++ b/extern/libmv/third_party/ceres/internal/ceres/detect_structure.h @@ -49,7 +49,7 @@ namespace internal { // is known as compile time. // // For more details about e_blocks and f_blocks, see -// schur_complement.h. This information is used to initialized an +// schur_eliminator.h. This information is used to initialized an // appropriate template specialization of SchurEliminator. void DetectStructure(const CompressedRowBlockStructure& bs, const int num_eliminate_blocks, diff --git a/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.cc b/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.cc new file mode 100644 index 00000000000..668fa54b8b8 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.cc @@ -0,0 +1,691 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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 Google Inc. 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. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/dogleg_strategy.h" + +#include +#include "Eigen/Dense" +#include "ceres/array_utils.h" +#include "ceres/internal/eigen.h" +#include "ceres/linear_solver.h" +#include "ceres/polynomial_solver.h" +#include "ceres/sparse_matrix.h" +#include "ceres/trust_region_strategy.h" +#include "ceres/types.h" +#include "glog/logging.h" + +namespace ceres { +namespace internal { +namespace { +const double kMaxMu = 1.0; +const double kMinMu = 1e-8; +} + +DoglegStrategy::DoglegStrategy(const TrustRegionStrategy::Options& options) + : linear_solver_(options.linear_solver), + radius_(options.initial_radius), + max_radius_(options.max_radius), + min_diagonal_(options.lm_min_diagonal), + max_diagonal_(options.lm_max_diagonal), + mu_(kMinMu), + min_mu_(kMinMu), + max_mu_(kMaxMu), + mu_increase_factor_(10.0), + increase_threshold_(0.75), + decrease_threshold_(0.25), + dogleg_step_norm_(0.0), + reuse_(false), + dogleg_type_(options.dogleg_type) { + CHECK_NOTNULL(linear_solver_); + CHECK_GT(min_diagonal_, 0.0); + CHECK_LE(min_diagonal_, max_diagonal_); + CHECK_GT(max_radius_, 0.0); +} + +// If the reuse_ flag is not set, then the Cauchy point (scaled +// gradient) and the new Gauss-Newton step are computed from +// scratch. The Dogleg step is then computed as interpolation of these +// two vectors. +TrustRegionStrategy::Summary DoglegStrategy::ComputeStep( + const TrustRegionStrategy::PerSolveOptions& per_solve_options, + SparseMatrix* jacobian, + const double* residuals, + double* step) { + CHECK_NOTNULL(jacobian); + CHECK_NOTNULL(residuals); + CHECK_NOTNULL(step); + + const int n = jacobian->num_cols(); + if (reuse_) { + // Gauss-Newton and gradient vectors are always available, only a + // new interpolant need to be computed. For the subspace case, + // the subspace and the two-dimensional model are also still valid. + switch(dogleg_type_) { + case TRADITIONAL_DOGLEG: + ComputeTraditionalDoglegStep(step); + break; + + case SUBSPACE_DOGLEG: + ComputeSubspaceDoglegStep(step); + break; + } + TrustRegionStrategy::Summary summary; + summary.num_iterations = 0; + summary.termination_type = TOLERANCE; + return summary; + } + + reuse_ = true; + // Check that we have the storage needed to hold the various + // temporary vectors. + if (diagonal_.rows() != n) { + diagonal_.resize(n, 1); + gradient_.resize(n, 1); + gauss_newton_step_.resize(n, 1); + } + + // Vector used to form the diagonal matrix that is used to + // regularize the Gauss-Newton solve and that defines the + // elliptical trust region + // + // || D * step || <= radius_ . + // + jacobian->SquaredColumnNorm(diagonal_.data()); + for (int i = 0; i < n; ++i) { + diagonal_[i] = min(max(diagonal_[i], min_diagonal_), max_diagonal_); + } + diagonal_ = diagonal_.array().sqrt(); + + ComputeGradient(jacobian, residuals); + ComputeCauchyPoint(jacobian); + + LinearSolver::Summary linear_solver_summary = + ComputeGaussNewtonStep(jacobian, residuals); + + TrustRegionStrategy::Summary summary; + summary.residual_norm = linear_solver_summary.residual_norm; + summary.num_iterations = linear_solver_summary.num_iterations; + summary.termination_type = linear_solver_summary.termination_type; + + if (linear_solver_summary.termination_type != FAILURE) { + switch(dogleg_type_) { + // Interpolate the Cauchy point and the Gauss-Newton step. + case TRADITIONAL_DOGLEG: + ComputeTraditionalDoglegStep(step); + break; + + // Find the minimum in the subspace defined by the + // Cauchy point and the (Gauss-)Newton step. + case SUBSPACE_DOGLEG: + if (!ComputeSubspaceModel(jacobian)) { + summary.termination_type = FAILURE; + break; + } + ComputeSubspaceDoglegStep(step); + break; + } + } + + return summary; +} + +// The trust region is assumed to be elliptical with the +// diagonal scaling matrix D defined by sqrt(diagonal_). +// It is implemented by substituting step' = D * step. +// The trust region for step' is spherical. +// The gradient, the Gauss-Newton step, the Cauchy point, +// and all calculations involving the Jacobian have to +// be adjusted accordingly. +void DoglegStrategy::ComputeGradient( + SparseMatrix* jacobian, + const double* residuals) { + gradient_.setZero(); + jacobian->LeftMultiply(residuals, gradient_.data()); + gradient_.array() /= diagonal_.array(); +} + +// The Cauchy point is the global minimizer of the quadratic model +// along the one-dimensional subspace spanned by the gradient. +void DoglegStrategy::ComputeCauchyPoint(SparseMatrix* jacobian) { + // alpha * -gradient is the Cauchy point. + Vector Jg(jacobian->num_rows()); + Jg.setZero(); + // The Jacobian is scaled implicitly by computing J * (D^-1 * (D^-1 * g)) + // instead of (J * D^-1) * (D^-1 * g). + Vector scaled_gradient = + (gradient_.array() / diagonal_.array()).matrix(); + jacobian->RightMultiply(scaled_gradient.data(), Jg.data()); + alpha_ = gradient_.squaredNorm() / Jg.squaredNorm(); +} + +// The dogleg step is defined as the intersection of the trust region +// boundary with the piecewise linear path from the origin to the Cauchy +// point and then from there to the Gauss-Newton point (global minimizer +// of the model function). The Gauss-Newton point is taken if it lies +// within the trust region. +void DoglegStrategy::ComputeTraditionalDoglegStep(double* dogleg) { + VectorRef dogleg_step(dogleg, gradient_.rows()); + + // Case 1. The Gauss-Newton step lies inside the trust region, and + // is therefore the optimal solution to the trust-region problem. + const double gradient_norm = gradient_.norm(); + const double gauss_newton_norm = gauss_newton_step_.norm(); + if (gauss_newton_norm <= radius_) { + dogleg_step = gauss_newton_step_; + dogleg_step_norm_ = gauss_newton_norm; + dogleg_step.array() /= diagonal_.array(); + VLOG(3) << "GaussNewton step size: " << dogleg_step_norm_ + << " radius: " << radius_; + return; + } + + // Case 2. The Cauchy point and the Gauss-Newton steps lie outside + // the trust region. Rescale the Cauchy point to the trust region + // and return. + if (gradient_norm * alpha_ >= radius_) { + dogleg_step = -(radius_ / gradient_norm) * gradient_; + dogleg_step_norm_ = radius_; + dogleg_step.array() /= diagonal_.array(); + VLOG(3) << "Cauchy step size: " << dogleg_step_norm_ + << " radius: " << radius_; + return; + } + + // Case 3. The Cauchy point is inside the trust region and the + // Gauss-Newton step is outside. Compute the line joining the two + // points and the point on it which intersects the trust region + // boundary. + + // a = alpha * -gradient + // b = gauss_newton_step + const double b_dot_a = -alpha_ * gradient_.dot(gauss_newton_step_); + const double a_squared_norm = pow(alpha_ * gradient_norm, 2.0); + const double b_minus_a_squared_norm = + a_squared_norm - 2 * b_dot_a + pow(gauss_newton_norm, 2); + + // c = a' (b - a) + // = alpha * -gradient' gauss_newton_step - alpha^2 |gradient|^2 + const double c = b_dot_a - a_squared_norm; + const double d = sqrt(c * c + b_minus_a_squared_norm * + (pow(radius_, 2.0) - a_squared_norm)); + + double beta = + (c <= 0) + ? (d - c) / b_minus_a_squared_norm + : (radius_ * radius_ - a_squared_norm) / (d + c); + dogleg_step = (-alpha_ * (1.0 - beta)) * gradient_ + + beta * gauss_newton_step_; + dogleg_step_norm_ = dogleg_step.norm(); + dogleg_step.array() /= diagonal_.array(); + VLOG(3) << "Dogleg step size: " << dogleg_step_norm_ + << " radius: " << radius_; +} + +// The subspace method finds the minimum of the two-dimensional problem +// +// min. 1/2 x' B' H B x + g' B x +// s.t. || B x ||^2 <= r^2 +// +// where r is the trust region radius and B is the matrix with unit columns +// spanning the subspace defined by the steepest descent and Newton direction. +// This subspace by definition includes the Gauss-Newton point, which is +// therefore taken if it lies within the trust region. +void DoglegStrategy::ComputeSubspaceDoglegStep(double* dogleg) { + VectorRef dogleg_step(dogleg, gradient_.rows()); + + // The Gauss-Newton point is inside the trust region if |GN| <= radius_. + // This test is valid even though radius_ is a length in the two-dimensional + // subspace while gauss_newton_step_ is expressed in the (scaled) + // higher dimensional original space. This is because + // + // 1. gauss_newton_step_ by definition lies in the subspace, and + // 2. the subspace basis is orthonormal. + // + // As a consequence, the norm of the gauss_newton_step_ in the subspace is + // the same as its norm in the original space. + const double gauss_newton_norm = gauss_newton_step_.norm(); + if (gauss_newton_norm <= radius_) { + dogleg_step = gauss_newton_step_; + dogleg_step_norm_ = gauss_newton_norm; + dogleg_step.array() /= diagonal_.array(); + VLOG(3) << "GaussNewton step size: " << dogleg_step_norm_ + << " radius: " << radius_; + return; + } + + // The optimum lies on the boundary of the trust region. The above problem + // therefore becomes + // + // min. 1/2 x^T B^T H B x + g^T B x + // s.t. || B x ||^2 = r^2 + // + // Notice the equality in the constraint. + // + // This can be solved by forming the Lagrangian, solving for x(y), where + // y is the Lagrange multiplier, using the gradient of the objective, and + // putting x(y) back into the constraint. This results in a fourth order + // polynomial in y, which can be solved using e.g. the companion matrix. + // See the description of MakePolynomialForBoundaryConstrainedProblem for + // details. The result is up to four real roots y*, not all of which + // correspond to feasible points. The feasible points x(y*) have to be + // tested for optimality. + + if (subspace_is_one_dimensional_) { + // The subspace is one-dimensional, so both the gradient and + // the Gauss-Newton step point towards the same direction. + // In this case, we move along the gradient until we reach the trust + // region boundary. + dogleg_step = -(radius_ / gradient_.norm()) * gradient_; + dogleg_step_norm_ = radius_; + dogleg_step.array() /= diagonal_.array(); + VLOG(3) << "Dogleg subspace step size (1D): " << dogleg_step_norm_ + << " radius: " << radius_; + return; + } + + Vector2d minimum(0.0, 0.0); + if (!FindMinimumOnTrustRegionBoundary(&minimum)) { + // For the positive semi-definite case, a traditional dogleg step + // is taken in this case. + LOG(WARNING) << "Failed to compute polynomial roots. " + << "Taking traditional dogleg step instead."; + ComputeTraditionalDoglegStep(dogleg); + return; + } + + // Test first order optimality at the minimum. + // The first order KKT conditions state that the minimum x* + // has to satisfy either || x* ||^2 < r^2 (i.e. has to lie within + // the trust region), or + // + // (B x* + g) + y x* = 0 + // + // for some positive scalar y. + // Here, as it is already known that the minimum lies on the boundary, the + // latter condition is tested. To allow for small imprecisions, we test if + // the angle between (B x* + g) and -x* is smaller than acos(0.99). + // The exact value of the cosine is arbitrary but should be close to 1. + // + // This condition should not be violated. If it is, the minimum was not + // correctly determined. + const double kCosineThreshold = 0.99; + const Vector2d grad_minimum = subspace_B_ * minimum + subspace_g_; + const double cosine_angle = -minimum.dot(grad_minimum) / + (minimum.norm() * grad_minimum.norm()); + if (cosine_angle < kCosineThreshold) { + LOG(WARNING) << "First order optimality seems to be violated " + << "in the subspace method!\n" + << "Cosine of angle between x and B x + g is " + << cosine_angle << ".\n" + << "Taking a regular dogleg step instead.\n" + << "Please consider filing a bug report if this " + << "happens frequently or consistently.\n"; + ComputeTraditionalDoglegStep(dogleg); + return; + } + + // Create the full step from the optimal 2d solution. + dogleg_step = subspace_basis_ * minimum; + dogleg_step_norm_ = radius_; + dogleg_step.array() /= diagonal_.array(); + VLOG(3) << "Dogleg subspace step size: " << dogleg_step_norm_ + << " radius: " << radius_; +} + +// Build the polynomial that defines the optimal Lagrange multipliers. +// Let the Lagrangian be +// +// L(x, y) = 0.5 x^T B x + x^T g + y (0.5 x^T x - 0.5 r^2). (1) +// +// Stationary points of the Lagrangian are given by +// +// 0 = d L(x, y) / dx = Bx + g + y x (2) +// 0 = d L(x, y) / dy = 0.5 x^T x - 0.5 r^2 (3) +// +// For any given y, we can solve (2) for x as +// +// x(y) = -(B + y I)^-1 g . (4) +// +// As B + y I is 2x2, we form the inverse explicitly: +// +// (B + y I)^-1 = (1 / det(B + y I)) adj(B + y I) (5) +// +// where adj() denotes adjugation. This should be safe, as B is positive +// semi-definite and y is necessarily positive, so (B + y I) is indeed +// invertible. +// Plugging (5) into (4) and the result into (3), then dividing by 0.5 we +// obtain +// +// 0 = (1 / det(B + y I))^2 g^T adj(B + y I)^T adj(B + y I) g - r^2 +// (6) +// +// or +// +// det(B + y I)^2 r^2 = g^T adj(B + y I)^T adj(B + y I) g (7a) +// = g^T adj(B)^T adj(B) g +// + 2 y g^T adj(B)^T g + y^2 g^T g (7b) +// +// as +// +// adj(B + y I) = adj(B) + y I = adj(B)^T + y I . (8) +// +// The left hand side can be expressed explicitly using +// +// det(B + y I) = det(B) + y tr(B) + y^2 . (9) +// +// So (7) is a polynomial in y of degree four. +// Bringing everything back to the left hand side, the coefficients can +// be read off as +// +// y^4 r^2 +// + y^3 2 r^2 tr(B) +// + y^2 (r^2 tr(B)^2 + 2 r^2 det(B) - g^T g) +// + y^1 (2 r^2 det(B) tr(B) - 2 g^T adj(B)^T g) +// + y^0 (r^2 det(B)^2 - g^T adj(B)^T adj(B) g) +// +Vector DoglegStrategy::MakePolynomialForBoundaryConstrainedProblem() const { + const double detB = subspace_B_.determinant(); + const double trB = subspace_B_.trace(); + const double r2 = radius_ * radius_; + Matrix2d B_adj; + B_adj << subspace_B_(1,1) , -subspace_B_(0,1), + -subspace_B_(1,0) , subspace_B_(0,0); + + Vector polynomial(5); + polynomial(0) = r2; + polynomial(1) = 2.0 * r2 * trB; + polynomial(2) = r2 * ( trB * trB + 2.0 * detB ) - subspace_g_.squaredNorm(); + polynomial(3) = -2.0 * ( subspace_g_.transpose() * B_adj * subspace_g_ + - r2 * detB * trB ); + polynomial(4) = r2 * detB * detB - (B_adj * subspace_g_).squaredNorm(); + + return polynomial; +} + +// Given a Lagrange multiplier y that corresponds to a stationary point +// of the Lagrangian L(x, y), compute the corresponding x from the +// equation +// +// 0 = d L(x, y) / dx +// = B * x + g + y * x +// = (B + y * I) * x + g +// +DoglegStrategy::Vector2d DoglegStrategy::ComputeSubspaceStepFromRoot( + double y) const { + const Matrix2d B_i = subspace_B_ + y * Matrix2d::Identity(); + return -B_i.partialPivLu().solve(subspace_g_); +} + +// This function evaluates the quadratic model at a point x in the +// subspace spanned by subspace_basis_. +double DoglegStrategy::EvaluateSubspaceModel(const Vector2d& x) const { + return 0.5 * x.dot(subspace_B_ * x) + subspace_g_.dot(x); +} + +// This function attempts to solve the boundary-constrained subspace problem +// +// min. 1/2 x^T B^T H B x + g^T B x +// s.t. || B x ||^2 = r^2 +// +// where B is an orthonormal subspace basis and r is the trust-region radius. +// +// This is done by finding the roots of a fourth degree polynomial. If the +// root finding fails, the function returns false and minimum will be set +// to (0, 0). If it succeeds, true is returned. +// +// In the failure case, another step should be taken, such as the traditional +// dogleg step. +bool DoglegStrategy::FindMinimumOnTrustRegionBoundary(Vector2d* minimum) const { + CHECK_NOTNULL(minimum); + + // Return (0, 0) in all error cases. + minimum->setZero(); + + // Create the fourth-degree polynomial that is a necessary condition for + // optimality. + const Vector polynomial = MakePolynomialForBoundaryConstrainedProblem(); + + // Find the real parts y_i of its roots (not only the real roots). + Vector roots_real; + if (!FindPolynomialRoots(polynomial, &roots_real, NULL)) { + // Failed to find the roots of the polynomial, i.e. the candidate + // solutions of the constrained problem. Report this back to the caller. + return false; + } + + // For each root y, compute B x(y) and check for feasibility. + // Notice that there should always be four roots, as the leading term of + // the polynomial is r^2 and therefore non-zero. However, as some roots + // may be complex, the real parts are not necessarily unique. + double minimum_value = std::numeric_limits::max(); + bool valid_root_found = false; + for (int i = 0; i < roots_real.size(); ++i) { + const Vector2d x_i = ComputeSubspaceStepFromRoot(roots_real(i)); + + // Not all roots correspond to points on the trust region boundary. + // There are at most four candidate solutions. As we are interested + // in the minimum, it is safe to consider all of them after projecting + // them onto the trust region boundary. + if (x_i.norm() > 0) { + const double f_i = EvaluateSubspaceModel((radius_ / x_i.norm()) * x_i); + valid_root_found = true; + if (f_i < minimum_value) { + minimum_value = f_i; + *minimum = x_i; + } + } + } + + return valid_root_found; +} + +LinearSolver::Summary DoglegStrategy::ComputeGaussNewtonStep( + SparseMatrix* jacobian, + const double* residuals) { + const int n = jacobian->num_cols(); + LinearSolver::Summary linear_solver_summary; + linear_solver_summary.termination_type = FAILURE; + + // The Jacobian matrix is often quite poorly conditioned. Thus it is + // necessary to add a diagonal matrix at the bottom to prevent the + // linear solver from failing. + // + // We do this by computing the same diagonal matrix as the one used + // by Levenberg-Marquardt (other choices are possible), and scaling + // it by a small constant (independent of the trust region radius). + // + // If the solve fails, the multiplier to the diagonal is increased + // up to max_mu_ by a factor of mu_increase_factor_ every time. If + // the linear solver is still not successful, the strategy returns + // with FAILURE. + // + // Next time when a new Gauss-Newton step is requested, the + // multiplier starts out from the last successful solve. + // + // When a step is declared successful, the multiplier is decreased + // by half of mu_increase_factor_. + + while (mu_ < max_mu_) { + // Dogleg, as far as I (sameeragarwal) understand it, requires a + // reasonably good estimate of the Gauss-Newton step. This means + // that we need to solve the normal equations more or less + // exactly. This is reflected in the values of the tolerances set + // below. + // + // For now, this strategy should only be used with exact + // factorization based solvers, for which these tolerances are + // automatically satisfied. + // + // The right way to combine inexact solves with trust region + // methods is to use Stiehaug's method. + LinearSolver::PerSolveOptions solve_options; + solve_options.q_tolerance = 0.0; + solve_options.r_tolerance = 0.0; + + lm_diagonal_ = diagonal_ * std::sqrt(mu_); + solve_options.D = lm_diagonal_.data(); + + // As in the LevenbergMarquardtStrategy, solve Jy = r instead + // of Jx = -r and later set x = -y to avoid having to modify + // either jacobian or residuals. + InvalidateArray(n, gauss_newton_step_.data()); + linear_solver_summary = linear_solver_->Solve(jacobian, + residuals, + solve_options, + gauss_newton_step_.data()); + + if (linear_solver_summary.termination_type == FAILURE || + !IsArrayValid(n, gauss_newton_step_.data())) { + mu_ *= mu_increase_factor_; + VLOG(2) << "Increasing mu " << mu_; + linear_solver_summary.termination_type = FAILURE; + continue; + } + break; + } + + if (linear_solver_summary.termination_type != FAILURE) { + // The scaled Gauss-Newton step is D * GN: + // + // - (D^-1 J^T J D^-1)^-1 (D^-1 g) + // = - D (J^T J)^-1 D D^-1 g + // = D -(J^T J)^-1 g + // + gauss_newton_step_.array() *= -diagonal_.array(); + } + + return linear_solver_summary; +} + +void DoglegStrategy::StepAccepted(double step_quality) { + CHECK_GT(step_quality, 0.0); + + if (step_quality < decrease_threshold_) { + radius_ *= 0.5; + } + + if (step_quality > increase_threshold_) { + radius_ = max(radius_, 3.0 * dogleg_step_norm_); + } + + // Reduce the regularization multiplier, in the hope that whatever + // was causing the rank deficiency has gone away and we can return + // to doing a pure Gauss-Newton solve. + mu_ = max(min_mu_, 2.0 * mu_ / mu_increase_factor_ ); + reuse_ = false; +} + +void DoglegStrategy::StepRejected(double step_quality) { + radius_ *= 0.5; + reuse_ = true; +} + +void DoglegStrategy::StepIsInvalid() { + mu_ *= mu_increase_factor_; + reuse_ = false; +} + +double DoglegStrategy::Radius() const { + return radius_; +} + +bool DoglegStrategy::ComputeSubspaceModel(SparseMatrix* jacobian) { + // Compute an orthogonal basis for the subspace using QR decomposition. + Matrix basis_vectors(jacobian->num_cols(), 2); + basis_vectors.col(0) = gradient_; + basis_vectors.col(1) = gauss_newton_step_; + Eigen::ColPivHouseholderQR basis_qr(basis_vectors); + + switch (basis_qr.rank()) { + case 0: + // This should never happen, as it implies that both the gradient + // and the Gauss-Newton step are zero. In this case, the minimizer should + // have stopped due to the gradient being too small. + LOG(ERROR) << "Rank of subspace basis is 0. " + << "This means that the gradient at the current iterate is " + << "zero but the optimization has not been terminated. " + << "You may have found a bug in Ceres."; + return false; + + case 1: + // Gradient and Gauss-Newton step coincide, so we lie on one of the + // major axes of the quadratic problem. In this case, we simply move + // along the gradient until we reach the trust region boundary. + subspace_is_one_dimensional_ = true; + return true; + + case 2: + subspace_is_one_dimensional_ = false; + break; + + default: + LOG(ERROR) << "Rank of the subspace basis matrix is reported to be " + << "greater than 2. As the matrix contains only two " + << "columns this cannot be true and is indicative of " + << "a bug."; + return false; + } + + // The subspace is two-dimensional, so compute the subspace model. + // Given the basis U, this is + // + // subspace_g_ = g_scaled^T U + // + // and + // + // subspace_B_ = U^T (J_scaled^T J_scaled) U + // + // As J_scaled = J * D^-1, the latter becomes + // + // subspace_B_ = ((U^T D^-1) J^T) (J (D^-1 U)) + // = (J (D^-1 U))^T (J (D^-1 U)) + + subspace_basis_ = + basis_qr.householderQ() * Matrix::Identity(jacobian->num_cols(), 2); + + subspace_g_ = subspace_basis_.transpose() * gradient_; + + Eigen::Matrix + Jb(2, jacobian->num_rows()); + Jb.setZero(); + + Vector tmp; + tmp = (subspace_basis_.col(0).array() / diagonal_.array()).matrix(); + jacobian->RightMultiply(tmp.data(), Jb.row(0).data()); + tmp = (subspace_basis_.col(1).array() / diagonal_.array()).matrix(); + jacobian->RightMultiply(tmp.data(), Jb.row(1).data()); + + subspace_B_ = Jb * Jb.transpose(); + + return true; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.h b/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.h new file mode 100644 index 00000000000..bff1689aa4a --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/dogleg_strategy.h @@ -0,0 +1,163 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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 Google Inc. 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. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_DOGLEG_STRATEGY_H_ +#define CERES_INTERNAL_DOGLEG_STRATEGY_H_ + +#include "ceres/linear_solver.h" +#include "ceres/trust_region_strategy.h" + +namespace ceres { +namespace internal { + +// Dogleg step computation and trust region sizing strategy based on +// on "Methods for Nonlinear Least Squares" by K. Madsen, H.B. Nielsen +// and O. Tingleff. Available to download from +// +// http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf +// +// One minor modification is that instead of computing the pure +// Gauss-Newton step, we compute a regularized version of it. This is +// because the Jacobian is often rank-deficient and in such cases +// using a direct solver leads to numerical failure. +// +// If SUBSPACE is passed as the type argument to the constructor, the +// DoglegStrategy follows the approach by Shultz, Schnabel, Byrd. +// This finds the exact optimum over the two-dimensional subspace +// spanned by the two Dogleg vectors. +class DoglegStrategy : public TrustRegionStrategy { +public: + DoglegStrategy(const TrustRegionStrategy::Options& options); + virtual ~DoglegStrategy() {} + + // TrustRegionStrategy interface + virtual Summary ComputeStep(const PerSolveOptions& per_solve_options, + SparseMatrix* jacobian, + const double* residuals, + double* step); + virtual void StepAccepted(double step_quality); + virtual void StepRejected(double step_quality); + virtual void StepIsInvalid(); + + virtual double Radius() const; + + // These functions are predominantly for testing. + Vector gradient() const { return gradient_; } + Vector gauss_newton_step() const { return gauss_newton_step_; } + Matrix subspace_basis() const { return subspace_basis_; } + Vector subspace_g() const { return subspace_g_; } + Matrix subspace_B() const { return subspace_B_; } + + private: + typedef Eigen::Matrix Vector2d; + typedef Eigen::Matrix Matrix2d; + + LinearSolver::Summary ComputeGaussNewtonStep(SparseMatrix* jacobian, + const double* residuals); + void ComputeCauchyPoint(SparseMatrix* jacobian); + void ComputeGradient(SparseMatrix* jacobian, const double* residuals); + void ComputeTraditionalDoglegStep(double* step); + bool ComputeSubspaceModel(SparseMatrix* jacobian); + void ComputeSubspaceDoglegStep(double* step); + + bool FindMinimumOnTrustRegionBoundary(Vector2d* minimum) const; + Vector MakePolynomialForBoundaryConstrainedProblem() const; + Vector2d ComputeSubspaceStepFromRoot(double lambda) const; + double EvaluateSubspaceModel(const Vector2d& x) const; + + LinearSolver* linear_solver_; + double radius_; + const double max_radius_; + + const double min_diagonal_; + const double max_diagonal_; + + // mu is used to scale the diagonal matrix used to make the + // Gauss-Newton solve full rank. In each solve, the strategy starts + // out with mu = min_mu, and tries values upto max_mu. If the user + // reports an invalid step, the value of mu_ is increased so that + // the next solve starts with a stronger regularization. + // + // If a successful step is reported, then the value of mu_ is + // decreased with a lower bound of min_mu_. + double mu_; + const double min_mu_; + const double max_mu_; + const double mu_increase_factor_; + const double increase_threshold_; + const double decrease_threshold_; + + Vector diagonal_; // sqrt(diag(J^T J)) + Vector lm_diagonal_; + + Vector gradient_; + Vector gauss_newton_step_; + + // cauchy_step = alpha * gradient + double alpha_; + double dogleg_step_norm_; + + // When, ComputeStep is called, reuse_ indicates whether the + // Gauss-Newton and Cauchy steps from the last call to ComputeStep + // can be reused or not. + // + // If the user called StepAccepted, then it is expected that the + // user has recomputed the Jacobian matrix and new Gauss-Newton + // solve is needed and reuse is set to false. + // + // If the user called StepRejected, then it is expected that the + // user wants to solve the trust region problem with the same matrix + // but a different trust region radius and the Gauss-Newton and + // Cauchy steps can be reused to compute the Dogleg, thus reuse is + // set to true. + // + // If the user called StepIsInvalid, then there was a numerical + // problem with the step computed in the last call to ComputeStep, + // and the regularization used to do the Gauss-Newton solve is + // increased and a new solve should be done when ComputeStep is + // called again, thus reuse is set to false. + bool reuse_; + + // The dogleg type determines how the minimum of the local + // quadratic model is found. + DoglegType dogleg_type_; + + // If the type is SUBSPACE_DOGLEG, the two-dimensional + // model 1/2 x^T B x + g^T x has to be computed and stored. + bool subspace_is_one_dimensional_; + Matrix subspace_basis_; + Vector2d subspace_g_; + Matrix2d subspace_B_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_DOGLEG_STRATEGY_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/evaluator.cc b/extern/libmv/third_party/ceres/internal/ceres/evaluator.cc index ea05aefec8c..a3ce6f04bd4 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/evaluator.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/evaluator.cc @@ -28,14 +28,18 @@ // // Author: keir@google.com (Keir Mierle) -#include -#include "ceres/evaluator.h" +#include #include "ceres/block_evaluate_preparer.h" #include "ceres/block_jacobian_writer.h" #include "ceres/compressed_row_jacobian_writer.h" -#include "ceres/scratch_evaluate_preparer.h" +#include "ceres/compressed_row_sparse_matrix.h" +#include "ceres/crs_matrix.h" #include "ceres/dense_jacobian_writer.h" +#include "ceres/evaluator.h" +#include "ceres/internal/port.h" #include "ceres/program_evaluator.h" +#include "ceres/scratch_evaluate_preparer.h" +#include "glog/logging.h" namespace ceres { namespace internal { @@ -47,6 +51,7 @@ Evaluator* Evaluator::Create(const Evaluator::Options& options, string* error) { switch (options.linear_solver_type) { case DENSE_QR: + case DENSE_NORMAL_CHOLESKY: return new ProgramEvaluator(options, program); @@ -67,5 +72,76 @@ Evaluator* Evaluator::Create(const Evaluator::Options& options, } } +bool Evaluator::Evaluate(Program* program, + int num_threads, + double* cost, + vector* residuals, + vector* gradient, + CRSMatrix* output_jacobian) { + CHECK_GE(num_threads, 1) + << "This is a Ceres bug; please contact the developers!"; + CHECK_NOTNULL(cost); + + // Setup the Parameter indices and offsets before an evaluator can + // be constructed and used. + program->SetParameterOffsetsAndIndex(); + + Evaluator::Options evaluator_options; + evaluator_options.linear_solver_type = SPARSE_NORMAL_CHOLESKY; + evaluator_options.num_threads = num_threads; + + string error; + scoped_ptr evaluator( + Evaluator::Create(evaluator_options, program, &error)); + if (evaluator.get() == NULL) { + LOG(ERROR) << "Unable to create an Evaluator object. " + << "Error: " << error + << "This is a Ceres bug; please contact the developers!"; + return false; + } + + if (residuals !=NULL) { + residuals->resize(evaluator->NumResiduals()); + } + + if (gradient != NULL) { + gradient->resize(evaluator->NumEffectiveParameters()); + } + + scoped_ptr jacobian; + if (output_jacobian != NULL) { + jacobian.reset( + down_cast(evaluator->CreateJacobian())); + } + + // Point the state pointers to the user state pointers. This is + // needed so that we can extract a parameter vector which is then + // passed to Evaluator::Evaluate. + program->SetParameterBlockStatePtrsToUserStatePtrs(); + + // Copy the value of the parameter blocks into a vector, since the + // Evaluate::Evaluate method needs its input as such. The previous + // call to SetParameterBlockStatePtrsToUserStatePtrs ensures that + // these values are the ones corresponding to the actual state of + // the parameter blocks, rather than the temporary state pointer + // used for evaluation. + Vector parameters(program->NumParameters()); + program->ParameterBlocksToStateVector(parameters.data()); + + if (!evaluator->Evaluate(parameters.data(), + cost, + residuals != NULL ? &(*residuals)[0] : NULL, + gradient != NULL ? &(*gradient)[0] : NULL, + jacobian.get())) { + return false; + } + + if (output_jacobian != NULL) { + jacobian->ToCRSMatrix(output_jacobian); + } + + return true; +} + } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/evaluator.h b/extern/libmv/third_party/ceres/internal/ceres/evaluator.h index adefdd26660..6aa30d7b739 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/evaluator.h +++ b/extern/libmv/third_party/ceres/internal/ceres/evaluator.h @@ -33,10 +33,14 @@ #define CERES_INTERNAL_EVALUATOR_H_ #include +#include #include "ceres/internal/port.h" #include "ceres/types.h" namespace ceres { + +class CRSMatrix; + namespace internal { class Program; @@ -65,6 +69,32 @@ class Evaluator { Program* program, string* error); + + // This is used for computing the cost, residual and Jacobian for + // returning to the user. For actually solving the optimization + // problem, the optimization algorithm uses the ProgramEvaluator + // objects directly. + // + // The residual, gradients and jacobian pointers can be NULL, in + // which case they will not be evaluated. cost cannot be NULL. + // + // The parallelism of the evaluator is controlled by num_threads; it + // should be at least 1. + // + // Note: That this function does not take a parameter vector as + // input. The parameter blocks are evaluated on the values contained + // in the arrays pointed to by their user_state pointers. + // + // Also worth noting is that this function mutates program by + // calling Program::SetParameterOffsetsAndIndex() on it so that an + // evaluator object can be constructed. + static bool Evaluate(Program* program, + int num_threads, + double* cost, + vector* residuals, + vector* gradient, + CRSMatrix* jacobian); + // Build and return a sparse matrix for storing and working with the Jacobian // of the objective function. The jacobian has dimensions // NumEffectiveParameters() by NumParameters(), and is typically extremely @@ -95,6 +125,7 @@ class Evaluator { virtual bool Evaluate(const double* state, double* cost, double* residuals, + double* gradient, SparseMatrix* jacobian) = 0; // Make a change delta (of size NumEffectiveParameters()) to state (of size diff --git a/extern/libmv/third_party/ceres/internal/ceres/file.cc b/extern/libmv/third_party/ceres/internal/ceres/file.cc index 5fc9d220861..6fe7557246d 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/file.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/file.cc @@ -31,7 +31,8 @@ // Really simple file IO. #include -#include +#include "file.h" +#include "glog/logging.h" namespace ceres { namespace internal { @@ -48,7 +49,7 @@ void WriteStringToFileOrDie(const string &data, const string &filename) { } void ReadFileToStringOrDie(const string &filename, string *data) { - FILE* file_descriptor = file_descriptor = fopen(filename.c_str(), "r"); + FILE* file_descriptor = fopen(filename.c_str(), "r"); if (!file_descriptor) { LOG(FATAL) << "Couldn't read file: " << filename; diff --git a/extern/libmv/third_party/ceres/internal/ceres/generate_eliminator_specialization.py b/extern/libmv/third_party/ceres/internal/ceres/generate_eliminator_specialization.py new file mode 100644 index 00000000000..af9873f94c0 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/generate_eliminator_specialization.py @@ -0,0 +1,186 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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 Google Inc. 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. +// +# +# Copyright 2011 Google Inc. All Rights Reserved. +# Author: sameeragarwal@google.com (Sameer Agarwal) +# +# Script for explicitly generating template specialization of the +# SchurEliminator class. It is a rather large class +# and the number of explicit instantiations is also large. Explicitly +# generating these instantiations in separate .cc files breaks the +# compilation into separate compilation unit rather than one large cc +# file which takes 2+GB of RAM to compile. +# +# This script creates two sets of files. +# +# 1. schur_eliminator_x_x_x.cc +# where, the x indicates the template parameters and +# +# 2. schur_eliminator.cc +# +# that contains a factory function for instantiating these classes +# based on runtime parameters. +# +# The list of tuples, specializations indicates the set of +# specializations that is generated. + +# Set of template specializations to generate +SPECIALIZATIONS = [(2, 2, 2), + (2, 2, 3), + (2, 2, 4), + (2, 2, "Dynamic"), + (2, 3, 3), + (2, 3, 4), + (2, 3, 9), + (2, 3, "Dynamic"), + (2, 4, 3), + (2, 4, 4), + (2, 4, "Dynamic"), + (4, 4, 2), + (4, 4, 3), + (4, 4, 4), + (4, 4, "Dynamic"), + ("Dynamic", "Dynamic", "Dynamic")] + +SPECIALIZATION_FILE = """// Copyright 2011 Google Inc. All Rights Reserved. +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// Template specialization of SchurEliminator. +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_eliminator_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/schur_eliminator_impl.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +template class SchurEliminator<%s, %s, %s>; + +} // namespace internal +} // namespace ceres + +""" + +FACTORY_FILE_HEADER = """// Copyright 2011 Google Inc. All Rights Reserved. +// Author: sameeragarwal@google.com (Sameer Agarwal) +// +// ======================================== +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +// THIS FILE IS AUTOGENERATED. DO NOT EDIT. +//========================================= +// +// This file is generated using generate_template_specializations.py. +// Editing it manually is not recommended. + +#include "ceres/linear_solver.h" +#include "ceres/schur_eliminator.h" +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +SchurEliminatorBase* +SchurEliminatorBase::Create(const LinearSolver::Options& options) { +#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION +""" + +FACTORY_CONDITIONAL = """ if ((options.row_block_size == %s) && + (options.e_block_size == %s) && + (options.f_block_size == %s)) { + return new SchurEliminator<%s, %s, %s>(options); + } +""" + +FACTORY_FOOTER = """ +#endif + VLOG(1) << "Template specializations not found for <" + << options.row_block_size << "," + << options.e_block_size << "," + << options.f_block_size << ">"; + return new SchurEliminator(options); +} + +} // namespace internal +} // namespace ceres +""" + + +def SuffixForSize(size): + if size == "Dynamic": + return "d" + return str(size) + + +def SpecializationFilename(prefix, row_block_size, e_block_size, f_block_size): + return "_".join([prefix] + map(SuffixForSize, (row_block_size, + e_block_size, + f_block_size))) + + +def Specialize(): + """ + Generate specialization code and the conditionals to instantiate it. + """ + f = open("schur_eliminator.cc", "w") + f.write(FACTORY_FILE_HEADER) + + for row_block_size, e_block_size, f_block_size in SPECIALIZATIONS: + output = SpecializationFilename("generated/schur_eliminator", + row_block_size, + e_block_size, + f_block_size) + ".cc" + fptr = open(output, "w") + fptr.write(SPECIALIZATION_FILE % (row_block_size, + e_block_size, + f_block_size)) + fptr.close() + + f.write(FACTORY_CONDITIONAL % (row_block_size, + e_block_size, + f_block_size, + row_block_size, + e_block_size, + f_block_size)) + f.write(FACTORY_FOOTER) + f.close() + + +if __name__ == "__main__": + Specialize() diff --git a/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc b/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc index abba40824ef..7fb3ed7b3a8 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/gradient_checking_cost_function.cc @@ -36,18 +36,18 @@ #include #include -#include +#include "ceres/cost_function.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" #include "ceres/parameter_block.h" +#include "ceres/problem.h" #include "ceres/problem_impl.h" #include "ceres/program.h" #include "ceres/residual_block.h" #include "ceres/runtime_numeric_diff_cost_function.h" #include "ceres/stringprintf.h" -#include "ceres/cost_function.h" -#include "ceres/internal/eigen.h" -#include "ceres/internal/scoped_ptr.h" -#include "ceres/problem.h" #include "ceres/types.h" +#include "glog/logging.h" namespace ceres { namespace internal { diff --git a/extern/libmv/third_party/ceres/internal/ceres/graph.h b/extern/libmv/third_party/ceres/internal/ceres/graph.h index fd7a224f0aa..2c0f6d28e54 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/graph.h +++ b/extern/libmv/third_party/ceres/internal/ceres/graph.h @@ -129,7 +129,7 @@ class Graph { HashMap > edges_; HashMap, double> edge_weights_; - DISALLOW_COPY_AND_ASSIGN(Graph); + CERES_DISALLOW_COPY_AND_ASSIGN(Graph); }; } // namespace internal diff --git a/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc index bd908846362..4af030a8535 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.cc @@ -30,22 +30,20 @@ #include "ceres/implicit_schur_complement.h" -#include #include "Eigen/Dense" #include "ceres/block_sparse_matrix.h" #include "ceres/block_structure.h" #include "ceres/internal/eigen.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/types.h" +#include "glog/logging.h" namespace ceres { namespace internal { ImplicitSchurComplement::ImplicitSchurComplement(int num_eliminate_blocks, - bool constant_sparsity, bool preconditioner) : num_eliminate_blocks_(num_eliminate_blocks), - constant_sparsity_(constant_sparsity), preconditioner_(preconditioner), A_(NULL), D_(NULL), @@ -62,7 +60,7 @@ void ImplicitSchurComplement::Init(const BlockSparseMatrixBase& A, const double* b) { // Since initialization is reasonably heavy, perhaps we can save on // constructing a new object everytime. - if ((A_ == NULL) || !constant_sparsity_) { + if (A_ == NULL) { A_.reset(new PartitionedMatrixView(A, num_eliminate_blocks_)); } @@ -71,7 +69,7 @@ void ImplicitSchurComplement::Init(const BlockSparseMatrixBase& A, // Initialize temporary storage and compute the block diagonals of // E'E and F'E. - if ((!constant_sparsity_) || (block_diagonal_EtE_inverse_ == NULL)) { + if (block_diagonal_EtE_inverse_ == NULL) { block_diagonal_EtE_inverse_.reset(A_->CreateBlockDiagonalEtE()); if (preconditioner_) { block_diagonal_FtF_inverse_.reset(A_->CreateBlockDiagonalFtF()); @@ -92,17 +90,10 @@ void ImplicitSchurComplement::Init(const BlockSparseMatrixBase& A, // The block diagonals of the augmented linear system contain // contributions from the diagonal D if it is non-null. Add that to // the block diagonals and invert them. - if (D_ != NULL) { - AddDiagonalAndInvert(D_, block_diagonal_EtE_inverse_.get()); - if (preconditioner_) { - AddDiagonalAndInvert(D_ + A_->num_cols_e(), - block_diagonal_FtF_inverse_.get()); - } - } else { - AddDiagonalAndInvert(NULL, block_diagonal_EtE_inverse_.get()); - if (preconditioner_) { - AddDiagonalAndInvert(NULL, block_diagonal_FtF_inverse_.get()); - } + AddDiagonalAndInvert(D_, block_diagonal_EtE_inverse_.get()); + if (preconditioner_) { + AddDiagonalAndInvert((D_ == NULL) ? NULL : D_ + A_->num_cols_e(), + block_diagonal_FtF_inverse_.get()); } // Compute the RHS of the Schur complement system. diff --git a/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h index 37a319f9c57..b9ebaa4628e 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h +++ b/extern/libmv/third_party/ceres/internal/ceres/implicit_schur_complement.h @@ -91,20 +91,13 @@ class ImplicitSchurComplement : public LinearOperator { // num_eliminate_blocks is the number of E blocks in the matrix // A. // - // constant_sparsity indicates if across calls to Init, the sparsity - // structure of the matrix A remains constant or not. This makes for - // significant savings across multiple matrices A, e.g. when used in - // conjunction with an optimization algorithm. - // // preconditioner indicates whether the inverse of the matrix F'F // should be computed or not as a preconditioner for the Schur // Complement. // // TODO(sameeragarwal): Get rid of the two bools below and replace // them with enums. - ImplicitSchurComplement(int num_eliminate_blocks, - bool constant_sparsity, - bool preconditioner); + ImplicitSchurComplement(int num_eliminate_blocks, bool preconditioner); virtual ~ImplicitSchurComplement(); // Initialize the Schur complement for a linear least squares @@ -151,7 +144,6 @@ class ImplicitSchurComplement : public LinearOperator { void UpdateRhs(); int num_eliminate_blocks_; - bool constant_sparsity_; bool preconditioner_; scoped_ptr A_; diff --git a/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc index 51303195317..679c41f2431 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/iterative_schur_complement_solver.cc @@ -33,22 +33,18 @@ #include #include #include - -#include #include "Eigen/Dense" #include "ceres/block_sparse_matrix.h" #include "ceres/block_structure.h" #include "ceres/conjugate_gradients_solver.h" #include "ceres/implicit_schur_complement.h" -#include "ceres/linear_solver.h" -#include "ceres/triplet_sparse_matrix.h" -#include "ceres/visibility_based_preconditioner.h" #include "ceres/internal/eigen.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/linear_solver.h" #include "ceres/triplet_sparse_matrix.h" #include "ceres/types.h" #include "ceres/visibility_based_preconditioner.h" +#include "glog/logging.h" namespace ceres { namespace internal { @@ -69,10 +65,9 @@ LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl( CHECK_NOTNULL(A->block_structure()); // Initialize a ImplicitSchurComplement object. - if ((schur_complement_ == NULL) || (!options_.constant_sparsity)) { + if (schur_complement_ == NULL) { schur_complement_.reset( new ImplicitSchurComplement(options_.num_eliminate_blocks, - options_.constant_sparsity, options_.preconditioner_type == JACOBI)); } schur_complement_->Init(*A, per_solve_options.D, b); @@ -119,7 +114,7 @@ LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl( new VisibilityBasedPreconditioner(*A->block_structure(), options_)); } is_preconditioner_good = - visibility_based_preconditioner_->Compute(*A, per_solve_options.D); + visibility_based_preconditioner_->Update(*A, per_solve_options.D); cg_per_solve_options.preconditioner = visibility_based_preconditioner_.get(); break; diff --git a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc deleted file mode 100644 index b40a5162adc..00000000000 --- a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt.cc +++ /dev/null @@ -1,574 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. -// http://code.google.com/p/ceres-solver/ -// -// 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 Google Inc. 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. -// -// Author: sameeragarwal@google.com (Sameer Agarwal) -// -// Implementation of a simple LM algorithm which uses the step sizing -// rule of "Methods for Nonlinear Least Squares" by K. Madsen, -// H.B. Nielsen and O. Tingleff. Available to download from -// -// http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf -// -// The basic algorithm described in this note is an exact step -// algorithm that depends on the Newton(LM) step being solved exactly -// in each iteration. When a suitable iterative solver is available to -// solve the Newton(LM) step, the algorithm will automatically switch -// to an inexact step solution method. This trades some slowdown in -// convergence for significant savings in solve time and memory -// usage. Our implementation of the Truncated Newton algorithm follows -// the discussion and recommendataions in "Stephen G. Nash, A Survey -// of Truncated Newton Methods, Journal of Computational and Applied -// Mathematics, 124(1-2), 45-59, 2000. - -#include "ceres/levenberg_marquardt.h" - -#include -#include -#include -#include -#include -#include - -#include -#include "Eigen/Core" -#include "ceres/evaluator.h" -#include "ceres/file.h" -#include "ceres/linear_least_squares_problems.h" -#include "ceres/linear_solver.h" -#include "ceres/matrix_proto.h" -#include "ceres/sparse_matrix.h" -#include "ceres/stringprintf.h" -#include "ceres/internal/eigen.h" -#include "ceres/internal/scoped_ptr.h" -#include "ceres/types.h" - -namespace ceres { -namespace internal { -namespace { - -// Numbers for clamping the size of the LM diagonal. The size of these -// numbers is heuristic. We will probably be adjusting them in the -// future based on more numerical experience. With jacobi scaling -// enabled, these numbers should be all but redundant. -const double kMinLevenbergMarquardtDiagonal = 1e-6; -const double kMaxLevenbergMarquardtDiagonal = 1e32; - -// Small constant for various floating point issues. -const double kEpsilon = 1e-12; - -// Number of times the linear solver should be retried in case of -// numerical failure. The retries are done by exponentially scaling up -// mu at each retry. This leads to stronger and stronger -// regularization making the linear least squares problem better -// conditioned at each retry. -const int kMaxLinearSolverRetries = 5; - -// D = 1/sqrt(diag(J^T * J)) -void EstimateScale(const SparseMatrix& jacobian, double* D) { - CHECK_NOTNULL(D); - jacobian.SquaredColumnNorm(D); - for (int i = 0; i < jacobian.num_cols(); ++i) { - D[i] = 1.0 / (kEpsilon + sqrt(D[i])); - } -} - -// D = diag(J^T * J) -void LevenbergMarquardtDiagonal(const SparseMatrix& jacobian, - double* D) { - CHECK_NOTNULL(D); - jacobian.SquaredColumnNorm(D); - for (int i = 0; i < jacobian.num_cols(); ++i) { - D[i] = min(max(D[i], kMinLevenbergMarquardtDiagonal), - kMaxLevenbergMarquardtDiagonal); - } -} - -bool RunCallback(IterationCallback* callback, - const IterationSummary& iteration_summary, - Solver::Summary* summary) { - const CallbackReturnType status = (*callback)(iteration_summary); - switch (status) { - case SOLVER_TERMINATE_SUCCESSFULLY: - summary->termination_type = USER_SUCCESS; - VLOG(1) << "Terminating on USER_SUCCESS."; - return false; - case SOLVER_ABORT: - summary->termination_type = USER_ABORT; - VLOG(1) << "Terminating on USER_ABORT."; - return false; - case SOLVER_CONTINUE: - return true; - default: - LOG(FATAL) << "Unknown status returned by callback: " - << status; - return NULL; - } -} - -} // namespace - -LevenbergMarquardt::~LevenbergMarquardt() {} - -void LevenbergMarquardt::Minimize(const Minimizer::Options& options, - Evaluator* evaluator, - LinearSolver* linear_solver, - const double* initial_parameters, - double* final_parameters, - Solver::Summary* summary) { - time_t start_time = time(NULL); - const int num_parameters = evaluator->NumParameters(); - const int num_effective_parameters = evaluator->NumEffectiveParameters(); - const int num_residuals = evaluator->NumResiduals(); - - summary->termination_type = NO_CONVERGENCE; - summary->num_successful_steps = 0; - summary->num_unsuccessful_steps = 0; - - // Allocate the various vectors needed by the algorithm. - memcpy(final_parameters, initial_parameters, - num_parameters * sizeof(*initial_parameters)); - - VectorRef x(final_parameters, num_parameters); - Vector x_new(num_parameters); - - Vector lm_step(num_effective_parameters); - Vector gradient(num_effective_parameters); - Vector scaled_gradient(num_effective_parameters); - // Jacobi scaling vector - Vector scale(num_effective_parameters); - - Vector f_model(num_residuals); - Vector f(num_residuals); - Vector f_new(num_residuals); - Vector D(num_parameters); - Vector muD(num_parameters); - - // Ask the Evaluator to create the jacobian matrix. The sparsity - // pattern of this matrix is going to remain constant, so we only do - // this once and then re-use this matrix for all subsequent Jacobian - // computations. - scoped_ptr jacobian(evaluator->CreateJacobian()); - - double x_norm = x.norm(); - - double cost = 0.0; - D.setOnes(); - f.setZero(); - - // Do initial cost and Jacobian evaluation. - if (!evaluator->Evaluate(x.data(), &cost, f.data(), jacobian.get())) { - LOG(WARNING) << "Failed to compute residuals and Jacobian. " - << "Terminating."; - summary->termination_type = NUMERICAL_FAILURE; - return; - } - - if (options.jacobi_scaling) { - EstimateScale(*jacobian, scale.data()); - jacobian->ScaleColumns(scale.data()); - } else { - scale.setOnes(); - } - - // This is a poor way to do this computation. Even if fixed_cost is - // zero, because we are subtracting two possibly large numbers, we - // are depending on exact cancellation to give us a zero here. But - // initial_cost and cost have been computed by two different - // evaluators. One which runs on the whole problem (in - // solver_impl.cc) in single threaded mode and another which runs - // here on the reduced problem, so fixed_cost can (and does) contain - // some numerical garbage with a relative magnitude of 1e-14. - // - // The right way to do this, would be to compute the fixed cost on - // just the set of residual blocks which are held constant and were - // removed from the original problem when the reduced problem was - // constructed. - summary->fixed_cost = summary->initial_cost - cost; - - double model_cost = f.squaredNorm() / 2.0; - double total_cost = summary->fixed_cost + cost; - - scaled_gradient.setZero(); - jacobian->LeftMultiply(f.data(), scaled_gradient.data()); - gradient = scaled_gradient.array() / scale.array(); - - double gradient_max_norm = gradient.lpNorm(); - // We need the max here to guard againt the gradient being zero. - const double gradient_max_norm_0 = max(gradient_max_norm, kEpsilon); - double gradient_tolerance = options.gradient_tolerance * gradient_max_norm_0; - - double mu = options.tau; - double nu = 2.0; - int iteration = 0; - double actual_cost_change = 0.0; - double step_norm = 0.0; - double relative_decrease = 0.0; - - // Insane steps are steps which are not sane, i.e. there is some - // numerical kookiness going on with them. There are various reasons - // for this kookiness, some easier to diagnose then others. From the - // point of view of the non-linear solver, they are steps which - // cannot be used. We return with NUMERICAL_FAILURE after - // kMaxLinearSolverRetries consecutive insane steps. - bool step_is_sane = false; - int num_consecutive_insane_steps = 0; - - // Whether the step resulted in a sufficient decrease in the - // objective function when compared to the decrease in the value of - // the lineariztion. - bool step_is_successful = false; - - // Parse the iterations for which to dump the linear problem. - vector iterations_to_dump = options.lsqp_iterations_to_dump; - sort(iterations_to_dump.begin(), iterations_to_dump.end()); - - IterationSummary iteration_summary; - iteration_summary.iteration = iteration; - iteration_summary.step_is_successful = false; - iteration_summary.cost = total_cost; - iteration_summary.cost_change = actual_cost_change; - iteration_summary.gradient_max_norm = gradient_max_norm; - iteration_summary.step_norm = step_norm; - iteration_summary.relative_decrease = relative_decrease; - iteration_summary.mu = mu; - iteration_summary.eta = options.eta; - iteration_summary.linear_solver_iterations = 0; - iteration_summary.linear_solver_time_sec = 0.0; - iteration_summary.iteration_time_sec = (time(NULL) - start_time); - if (options.logging_type >= PER_MINIMIZER_ITERATION) { - summary->iterations.push_back(iteration_summary); - } - - // Check if the starting point is an optimum. - VLOG(2) << "Gradient max norm: " << gradient_max_norm - << " tolerance: " << gradient_tolerance - << " ratio: " << gradient_max_norm / gradient_max_norm_0 - << " tolerance: " << options.gradient_tolerance; - if (gradient_max_norm <= gradient_tolerance) { - summary->termination_type = GRADIENT_TOLERANCE; - VLOG(1) << "Terminating on GRADIENT_TOLERANCE. " - << "Relative gradient max norm: " - << gradient_max_norm / gradient_max_norm_0 - << " <= " << options.gradient_tolerance; - return; - } - - // Call the various callbacks. - for (int i = 0; i < options.callbacks.size(); ++i) { - if (!RunCallback(options.callbacks[i], iteration_summary, summary)) { - return; - } - } - - // We only need the LM diagonal if we are actually going to do at - // least one iteration of the optimization. So we wait to do it - // until now. - LevenbergMarquardtDiagonal(*jacobian, D.data()); - - while ((iteration < options.max_num_iterations) && - (time(NULL) - start_time) <= options.max_solver_time_sec) { - time_t iteration_start_time = time(NULL); - step_is_sane = false; - step_is_successful = false; - - IterationSummary iteration_summary; - // The while loop here is just to provide an easily breakable - // control structure. We are guaranteed to always exit this loop - // at the end of one iteration or before. - while (1) { - muD = (mu * D).array().sqrt(); - LinearSolver::PerSolveOptions solve_options; - solve_options.D = muD.data(); - solve_options.q_tolerance = options.eta; - // Disable r_tolerance checking. Since we only care about - // termination via the q_tolerance. As Nash and Sofer show, - // r_tolerance based termination is essentially useless in - // Truncated Newton methods. - solve_options.r_tolerance = -1.0; - - const time_t linear_solver_start_time = time(NULL); - LinearSolver::Summary linear_solver_summary = - linear_solver->Solve(jacobian.get(), - f.data(), - solve_options, - lm_step.data()); - iteration_summary.linear_solver_time_sec = - (time(NULL) - linear_solver_start_time); - iteration_summary.linear_solver_iterations = - linear_solver_summary.num_iterations; - - if (binary_search(iterations_to_dump.begin(), - iterations_to_dump.end(), - iteration)) { - CHECK(DumpLinearLeastSquaresProblem(options.lsqp_dump_directory, - iteration, - options.lsqp_dump_format_type, - jacobian.get(), - muD.data(), - f.data(), - lm_step.data(), - options.num_eliminate_blocks)) - << "Tried writing linear least squares problem: " - << options.lsqp_dump_directory - << " but failed."; - } - - // We ignore the case where the linear solver did not converge, - // since the partial solution computed by it still maybe of use, - // and there is no reason to ignore it, especially since we - // spent so much time computing it. - if ((linear_solver_summary.termination_type != TOLERANCE) && - (linear_solver_summary.termination_type != MAX_ITERATIONS)) { - VLOG(1) << "Linear solver failure: retrying with a higher mu"; - break; - } - - step_norm = (lm_step.array() * scale.array()).matrix().norm(); - - // Check step length based convergence. If the step length is - // too small, then we are done. - const double step_size_tolerance = options.parameter_tolerance * - (x_norm + options.parameter_tolerance); - - VLOG(2) << "Step size: " << step_norm - << " tolerance: " << step_size_tolerance - << " ratio: " << step_norm / step_size_tolerance - << " tolerance: " << options.parameter_tolerance; - if (step_norm <= options.parameter_tolerance * - (x_norm + options.parameter_tolerance)) { - summary->termination_type = PARAMETER_TOLERANCE; - VLOG(1) << "Terminating on PARAMETER_TOLERANCE." - << "Relative step size: " << step_norm / step_size_tolerance - << " <= " << options.parameter_tolerance; - return; - } - - Vector delta = -(lm_step.array() * scale.array()).matrix(); - if (!evaluator->Plus(x.data(), delta.data(), x_new.data())) { - LOG(WARNING) << "Failed to compute Plus(x, delta, x_plus_delta). " - << "Terminating."; - summary->termination_type = NUMERICAL_FAILURE; - return; - } - - double cost_new = 0.0; - if (!evaluator->Evaluate(x_new.data(), &cost_new, NULL, NULL)) { - LOG(WARNING) << "Failed to compute the value of the objective " - << "function. Terminating."; - summary->termination_type = NUMERICAL_FAILURE; - return; - } - - f_model.setZero(); - jacobian->RightMultiply(lm_step.data(), f_model.data()); - const double model_cost_new = - (f.segment(0, num_residuals) - f_model).squaredNorm() / 2; - - actual_cost_change = cost - cost_new; - double model_cost_change = model_cost - model_cost_new; - - VLOG(2) << "[Model cost] current: " << model_cost - << " new : " << model_cost_new - << " change: " << model_cost_change; - - VLOG(2) << "[Nonlinear cost] current: " << cost - << " new : " << cost_new - << " change: " << actual_cost_change - << " relative change: " << fabs(actual_cost_change) / cost - << " tolerance: " << options.function_tolerance; - - // In exact arithmetic model_cost_change should never be - // negative. But due to numerical precision issues, we may end up - // with a small negative number. model_cost_change which are - // negative and large in absolute value are indicative of a - // numerical failure in the solver. - if (model_cost_change < -kEpsilon) { - VLOG(1) << "Model cost change is negative.\n" - << "Current : " << model_cost - << " new : " << model_cost_new - << " change: " << model_cost_change << "\n"; - break; - } - - // If we have reached this far, then we are willing to trust the - // numerical quality of the step. - step_is_sane = true; - num_consecutive_insane_steps = 0; - - // Check function value based convergence. - if (fabs(actual_cost_change) < options.function_tolerance * cost) { - VLOG(1) << "Termination on FUNCTION_TOLERANCE." - << " Relative cost change: " << fabs(actual_cost_change) / cost - << " tolerance: " << options.function_tolerance; - summary->termination_type = FUNCTION_TOLERANCE; - return; - } - - // Clamp model_cost_change at kEpsilon from below. - if (model_cost_change < kEpsilon) { - VLOG(1) << "Clamping model cost change " << model_cost_change - << " to " << kEpsilon; - model_cost_change = kEpsilon; - } - - relative_decrease = actual_cost_change / model_cost_change; - VLOG(2) << "actual_cost_change / model_cost_change = " - << relative_decrease; - - if (relative_decrease < options.min_relative_decrease) { - VLOG(2) << "Unsuccessful step."; - break; - } - - VLOG(2) << "Successful step."; - - ++summary->num_successful_steps; - x = x_new; - x_norm = x.norm(); - - if (!evaluator->Evaluate(x.data(), &cost, f.data(), jacobian.get())) { - LOG(WARNING) << "Failed to compute residuals and jacobian. " - << "Terminating."; - summary->termination_type = NUMERICAL_FAILURE; - return; - } - - if (options.jacobi_scaling) { - jacobian->ScaleColumns(scale.data()); - } - - model_cost = f.squaredNorm() / 2.0; - LevenbergMarquardtDiagonal(*jacobian, D.data()); - scaled_gradient.setZero(); - jacobian->LeftMultiply(f.data(), scaled_gradient.data()); - gradient = scaled_gradient.array() / scale.array(); - gradient_max_norm = gradient.lpNorm(); - - // Check gradient based convergence. - VLOG(2) << "Gradient max norm: " << gradient_max_norm - << " tolerance: " << gradient_tolerance - << " ratio: " << gradient_max_norm / gradient_max_norm_0 - << " tolerance: " << options.gradient_tolerance; - if (gradient_max_norm <= gradient_tolerance) { - summary->termination_type = GRADIENT_TOLERANCE; - VLOG(1) << "Terminating on GRADIENT_TOLERANCE. " - << "Relative gradient max norm: " - << gradient_max_norm / gradient_max_norm_0 - << " <= " << options.gradient_tolerance - << " (tolerance)."; - return; - } - - mu = mu * max(1.0 / 3.0, 1 - pow(2 * relative_decrease - 1, 3)); - nu = 2.0; - step_is_successful = true; - break; - } - - if (!step_is_sane) { - ++num_consecutive_insane_steps; - } - - if (num_consecutive_insane_steps == kMaxLinearSolverRetries) { - summary->termination_type = NUMERICAL_FAILURE; - VLOG(1) << "Too many consecutive retries; ending with numerical fail."; - - if (!options.crash_and_dump_lsqp_on_failure) { - return; - } - - // Dump debugging information to disk. - CHECK(options.lsqp_dump_format_type == TEXTFILE || - options.lsqp_dump_format_type == PROTOBUF) - << "Dumping the linear least squares problem on crash " - << "requires Solver::Options::lsqp_dump_format_type to be " - << "PROTOBUF or TEXTFILE."; - - if (DumpLinearLeastSquaresProblem(options.lsqp_dump_directory, - iteration, - options.lsqp_dump_format_type, - jacobian.get(), - muD.data(), - f.data(), - lm_step.data(), - options.num_eliminate_blocks)) { - LOG(FATAL) << "Linear least squares problem saved to: " - << options.lsqp_dump_directory - << ". Please provide this to the Ceres developers for " - << " debugging along with the v=2 log."; - } else { - LOG(FATAL) << "Tried writing linear least squares problem: " - << options.lsqp_dump_directory - << " but failed."; - } - } - - if (!step_is_successful) { - // Either the step did not lead to a decrease in cost or there - // was numerical failure. In either case we will scale mu up and - // retry. If it was a numerical failure, we hope that the - // stronger regularization will make the linear system better - // conditioned. If it was numerically sane, but there was no - // decrease in cost, then increasing mu reduces the size of the - // trust region and we look for a decrease closer to the - // linearization point. - ++summary->num_unsuccessful_steps; - mu = mu * nu; - nu = 2 * nu; - } - - ++iteration; - - total_cost = summary->fixed_cost + cost; - - iteration_summary.iteration = iteration; - iteration_summary.step_is_successful = step_is_successful; - iteration_summary.cost = total_cost; - iteration_summary.cost_change = actual_cost_change; - iteration_summary.gradient_max_norm = gradient_max_norm; - iteration_summary.step_norm = step_norm; - iteration_summary.relative_decrease = relative_decrease; - iteration_summary.mu = mu; - iteration_summary.eta = options.eta; - iteration_summary.iteration_time_sec = (time(NULL) - iteration_start_time); - - if (options.logging_type >= PER_MINIMIZER_ITERATION) { - summary->iterations.push_back(iteration_summary); - } - - // Call the various callbacks. - for (int i = 0; i < options.callbacks.size(); ++i) { - if (!RunCallback(options.callbacks[i], iteration_summary, summary)) { - return; - } - } - } -} - -} // namespace internal -} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.cc b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.cc new file mode 100644 index 00000000000..9e6a59e3813 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.cc @@ -0,0 +1,144 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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 Google Inc. 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. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/levenberg_marquardt_strategy.h" + +#include +#include "Eigen/Core" +#include "ceres/array_utils.h" +#include "ceres/internal/eigen.h" +#include "ceres/linear_solver.h" +#include "ceres/sparse_matrix.h" +#include "ceres/trust_region_strategy.h" +#include "ceres/types.h" +#include "glog/logging.h" + +namespace ceres { +namespace internal { + +LevenbergMarquardtStrategy::LevenbergMarquardtStrategy( + const TrustRegionStrategy::Options& options) + : linear_solver_(options.linear_solver), + radius_(options.initial_radius), + max_radius_(options.max_radius), + min_diagonal_(options.lm_min_diagonal), + max_diagonal_(options.lm_max_diagonal), + decrease_factor_(2.0), + reuse_diagonal_(false) { + CHECK_NOTNULL(linear_solver_); + CHECK_GT(min_diagonal_, 0.0); + CHECK_LE(min_diagonal_, max_diagonal_); + CHECK_GT(max_radius_, 0.0); +} + +LevenbergMarquardtStrategy::~LevenbergMarquardtStrategy() { +} + +TrustRegionStrategy::Summary LevenbergMarquardtStrategy::ComputeStep( + const TrustRegionStrategy::PerSolveOptions& per_solve_options, + SparseMatrix* jacobian, + const double* residuals, + double* step) { + CHECK_NOTNULL(jacobian); + CHECK_NOTNULL(residuals); + CHECK_NOTNULL(step); + + const int num_parameters = jacobian->num_cols(); + if (!reuse_diagonal_) { + if (diagonal_.rows() != num_parameters) { + diagonal_.resize(num_parameters, 1); + } + + jacobian->SquaredColumnNorm(diagonal_.data()); + for (int i = 0; i < num_parameters; ++i) { + diagonal_[i] = min(max(diagonal_[i], min_diagonal_), max_diagonal_); + } + } + + lm_diagonal_ = (diagonal_ / radius_).array().sqrt(); + + LinearSolver::PerSolveOptions solve_options; + solve_options.D = lm_diagonal_.data(); + solve_options.q_tolerance = per_solve_options.eta; + // Disable r_tolerance checking. Since we only care about + // termination via the q_tolerance. As Nash and Sofer show, + // r_tolerance based termination is essentially useless in + // Truncated Newton methods. + solve_options.r_tolerance = -1.0; + + // Invalidate the output array lm_step, so that we can detect if + // the linear solver generated numerical garbage. This is known + // to happen for the DENSE_QR and then DENSE_SCHUR solver when + // the Jacobin is severly rank deficient and mu is too small. + InvalidateArray(num_parameters, step); + + // Instead of solving Jx = -r, solve Jy = r. + // Then x can be found as x = -y, but the inputs jacobian and residuals + // do not need to be modified. + LinearSolver::Summary linear_solver_summary = + linear_solver_->Solve(jacobian, residuals, solve_options, step); + if (linear_solver_summary.termination_type == FAILURE || + !IsArrayValid(num_parameters, step)) { + LOG(WARNING) << "Linear solver failure. Failed to compute a finite step."; + linear_solver_summary.termination_type = FAILURE; + } else { + VectorRef(step, num_parameters) *= -1.0; + } + + reuse_diagonal_ = true; + + TrustRegionStrategy::Summary summary; + summary.residual_norm = linear_solver_summary.residual_norm; + summary.num_iterations = linear_solver_summary.num_iterations; + summary.termination_type = linear_solver_summary.termination_type; + return summary; +} + +void LevenbergMarquardtStrategy::StepAccepted(double step_quality) { + CHECK_GT(step_quality, 0.0); + radius_ = radius_ / std::max(1.0 / 3.0, + 1.0 - pow(2.0 * step_quality - 1.0, 3)); + radius_ = std::min(max_radius_, radius_); + decrease_factor_ = 2.0; + reuse_diagonal_ = false; +} + +void LevenbergMarquardtStrategy::StepRejected(double step_quality) { + radius_ = radius_ / decrease_factor_; + decrease_factor_ *= 2.0; + reuse_diagonal_ = true; +} + +double LevenbergMarquardtStrategy::Radius() const { + return radius_; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.h b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.h new file mode 100644 index 00000000000..90c21789797 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/levenberg_marquardt_strategy.h @@ -0,0 +1,86 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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 Google Inc. 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. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_LEVENBERG_MARQUARDT_STRATEGY_H_ +#define CERES_INTERNAL_LEVENBERG_MARQUARDT_STRATEGY_H_ + +#include "ceres/internal/eigen.h" +#include "ceres/trust_region_strategy.h" + +namespace ceres { +namespace internal { + +// Levenberg-Marquardt step computation and trust region sizing +// strategy based on on "Methods for Nonlinear Least Squares" by +// K. Madsen, H.B. Nielsen and O. Tingleff. Available to download from +// +// http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf +class LevenbergMarquardtStrategy : public TrustRegionStrategy { +public: + LevenbergMarquardtStrategy(const TrustRegionStrategy::Options& options); + virtual ~LevenbergMarquardtStrategy(); + + // TrustRegionStrategy interface + virtual TrustRegionStrategy::Summary ComputeStep( + const TrustRegionStrategy::PerSolveOptions& per_solve_options, + SparseMatrix* jacobian, + const double* residuals, + double* step); + virtual void StepAccepted(double step_quality); + virtual void StepRejected(double step_quality); + virtual void StepIsInvalid() { + // Treat the current step as a rejected step with no increase in + // solution quality. Since rejected steps lead to decrease in the + // size of the trust region, the next time ComputeStep is called, + // this will lead to a better conditioned system. + StepRejected(0.0); + } + + virtual double Radius() const; + + private: + LinearSolver* linear_solver_; + double radius_; + double max_radius_; + const double min_diagonal_; + const double max_diagonal_; + double decrease_factor_; + bool reuse_diagonal_; + Vector diagonal_; // diagonal_ = diag(J'J) + // Scaled copy of diagonal_. Stored here as optimization to prevent + // allocations in every iteration and reuse when a step fails and + // ComputeStep is called again. + Vector lm_diagonal_; // lm_diagonal_ = diagonal_ / radius_; +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_LEVENBERG_MARQUARDT_STRATEGY_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc index cca9f442fe7..a91e254a663 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_least_squares_problems.cc @@ -33,17 +33,17 @@ #include #include #include -#include #include "ceres/block_sparse_matrix.h" #include "ceres/block_structure.h" #include "ceres/casts.h" #include "ceres/compressed_row_sparse_matrix.h" #include "ceres/file.h" -#include "ceres/matrix_proto.h" -#include "ceres/triplet_sparse_matrix.h" -#include "ceres/stringprintf.h" #include "ceres/internal/scoped_ptr.h" +#include "ceres/matrix_proto.h" +#include "ceres/stringprintf.h" +#include "ceres/triplet_sparse_matrix.h" #include "ceres/types.h" +#include "glog/logging.h" namespace ceres { namespace internal { @@ -64,7 +64,7 @@ LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromId(int id) { return NULL; } -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromFile( const string& filename) { LinearLeastSquaresProblemProto problem_proto; @@ -130,7 +130,7 @@ LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromFile( << "Ceres to be built with Protocol Buffers support."; return NULL; } -#endif // CERES_DONT_HAVE_PROTOCOL_BUFFERS +#endif // CERES_NO_PROTOCOL_BUFFERS /* A = [1 2] @@ -573,13 +573,13 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem3() { return problem; } -bool DumpLinearLeastSquaresProblemToConsole(const string& directory, - int iteration, - const SparseMatrix* A, - const double* D, - const double* b, - const double* x, - int num_eliminate_blocks) { +static bool DumpLinearLeastSquaresProblemToConsole(const string& directory, + int iteration, + const SparseMatrix* A, + const double* D, + const double* b, + const double* x, + int num_eliminate_blocks) { CHECK_NOTNULL(A); Matrix AA; A->ToDenseMatrix(&AA); @@ -600,14 +600,14 @@ bool DumpLinearLeastSquaresProblemToConsole(const string& directory, return true; }; -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS -bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory, - int iteration, - const SparseMatrix* A, - const double* D, - const double* b, - const double* x, - int num_eliminate_blocks) { +#ifndef CERES_NO_PROTOCOL_BUFFERS +static bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory, + int iteration, + const SparseMatrix* A, + const double* D, + const double* b, + const double* x, + int num_eliminate_blocks) { CHECK_NOTNULL(A); LinearLeastSquaresProblemProto lsqp; A->ToProto(lsqp.mutable_a()); @@ -641,13 +641,13 @@ bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory, return true; } #else -bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory, - int iteration, - const SparseMatrix* A, - const double* D, - const double* b, - const double* x, - int num_eliminate_blocks) { +static bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory, + int iteration, + const SparseMatrix* A, + const double* D, + const double* b, + const double* x, + int num_eliminate_blocks) { LOG(ERROR) << "Dumping least squares problems is only " << "supported when Ceres is compiled with " << "protocol buffer support."; @@ -655,9 +655,9 @@ bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory, } #endif -void WriteArrayToFileOrDie(const string& filename, - const double* x, - const int size) { +static void WriteArrayToFileOrDie(const string& filename, + const double* x, + const int size) { CHECK_NOTNULL(x); VLOG(2) << "Writing array to: " << filename; FILE* fptr = fopen(filename.c_str(), "w"); @@ -668,43 +668,68 @@ void WriteArrayToFileOrDie(const string& filename, fclose(fptr); } -bool DumpLinearLeastSquaresProblemToTextFile(const string& directory, - int iteration, - const SparseMatrix* A, - const double* D, - const double* b, - const double* x, - int num_eliminate_blocks) { +static bool DumpLinearLeastSquaresProblemToTextFile(const string& directory, + int iteration, + const SparseMatrix* A, + const double* D, + const double* b, + const double* x, + int num_eliminate_blocks) { CHECK_NOTNULL(A); string format_string = JoinPath(directory, "lm_iteration_%03d"); string filename_prefix = StringPrintf(format_string.c_str(), iteration); + LOG(INFO) << "writing to: " << filename_prefix << "*"; + + string matlab_script; + StringAppendF(&matlab_script, + "function lsqp = lm_iteration_%03d()\n", iteration); + StringAppendF(&matlab_script, + "lsqp.num_rows = %d;\n", A->num_rows()); + StringAppendF(&matlab_script, + "lsqp.num_cols = %d;\n", A->num_cols()); + { string filename = filename_prefix + "_A.txt"; - LOG(INFO) << "writing to: " << filename; FILE* fptr = fopen(filename.c_str(), "w"); CHECK_NOTNULL(fptr); A->ToTextFile(fptr); fclose(fptr); + StringAppendF(&matlab_script, + "tmp = load('%s', '-ascii');\n", filename.c_str()); + StringAppendF( + &matlab_script, + "lsqp.A = sparse(tmp(:, 1) + 1, tmp(:, 2) + 1, tmp(:, 3), %d, %d);\n", + A->num_rows(), + A->num_cols()); } + if (D != NULL) { string filename = filename_prefix + "_D.txt"; WriteArrayToFileOrDie(filename, D, A->num_cols()); + StringAppendF(&matlab_script, + "lsqp.D = load('%s', '-ascii');\n", filename.c_str()); } if (b != NULL) { string filename = filename_prefix + "_b.txt"; WriteArrayToFileOrDie(filename, b, A->num_rows()); + StringAppendF(&matlab_script, + "lsqp.b = load('%s', '-ascii');\n", filename.c_str()); } if (x != NULL) { string filename = filename_prefix + "_x.txt"; WriteArrayToFileOrDie(filename, x, A->num_cols()); + StringAppendF(&matlab_script, + "lsqp.x = load('%s', '-ascii');\n", filename.c_str()); } + string matlab_filename = filename_prefix + ".m"; + WriteStringToFileOrDie(matlab_script, matlab_filename); return true; } diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc index b2e3941eea1..08c3ba110d0 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.cc @@ -30,13 +30,14 @@ #include "ceres/linear_solver.h" -#include #include "ceres/cgnr_solver.h" +#include "ceres/dense_normal_cholesky_solver.h" #include "ceres/dense_qr_solver.h" #include "ceres/iterative_schur_complement_solver.h" #include "ceres/schur_complement_solver.h" #include "ceres/sparse_normal_cholesky_solver.h" #include "ceres/types.h" +#include "glog/logging.h" namespace ceres { namespace internal { @@ -50,22 +51,24 @@ LinearSolver* LinearSolver::Create(const LinearSolver::Options& options) { return new CgnrSolver(options); case SPARSE_NORMAL_CHOLESKY: -#ifndef CERES_NO_SUITESPARSE - return new SparseNormalCholeskySolver(options); -#else +#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE) LOG(WARNING) << "SPARSE_NORMAL_CHOLESKY is not available. Please " - << "build Ceres with SuiteSparse. Returning NULL."; + << "build Ceres with SuiteSparse or CXSparse. " + << "Returning NULL."; return NULL; -#endif // CERES_NO_SUITESPARSE +#else + return new SparseNormalCholeskySolver(options); +#endif case SPARSE_SCHUR: -#ifndef CERES_NO_SUITESPARSE - return new SparseSchurComplementSolver(options); -#else +#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE) LOG(WARNING) << "SPARSE_SCHUR is not available. Please " - << "build Ceres with SuiteSparse. Returning NULL."; + << "build Ceres with SuiteSparse or CXSparse. " + << "Returning NULL."; return NULL; -#endif // CERES_NO_SUITESPARSE +#else + return new SparseSchurComplementSolver(options); +#endif case DENSE_SCHUR: return new DenseSchurComplementSolver(options); @@ -76,10 +79,13 @@ LinearSolver* LinearSolver::Create(const LinearSolver::Options& options) { case DENSE_QR: return new DenseQRSolver(options); + case DENSE_NORMAL_CHOLESKY: + return new DenseNormalCholeskySolver(options); + default: LOG(FATAL) << "Unknown linear solver type :" << options.type; - return NULL; // MSVC doesn't understand that LOG(FATAL) never returns. + return NULL; // MSVC doesn't understand that LOG(FATAL) never returns. } } diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h index 5860ecc8a77..31f88740b9f 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h +++ b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h @@ -55,10 +55,11 @@ class LinearOperator; // Ax = b // // It is expected that a single instance of a LinearSolver object -// maybe used multiple times for solving different linear -// systems. This allows them to cache and reuse information across -// solves if for example the sparsity of the linear system remains -// constant. +// maybe used multiple times for solving multiple linear systems with +// the same sparsity structure. This allows them to cache and reuse +// information across solves. This means that calling Solve on the +// same LinearSolver instance with two different linear systems will +// result in undefined behaviour. // // Subclasses of LinearSolver use two structs to configure themselves. // The Options struct configures the LinearSolver object for its @@ -70,10 +71,11 @@ class LinearSolver { Options() : type(SPARSE_NORMAL_CHOLESKY), preconditioner_type(JACOBI), + sparse_linear_algebra_library(SUITE_SPARSE), + use_block_amd(true), min_num_iterations(1), max_num_iterations(1), num_threads(1), - constant_sparsity(false), num_eliminate_blocks(0), residual_reset_period(10), row_block_size(Dynamic), @@ -85,6 +87,11 @@ class LinearSolver { PreconditionerType preconditioner_type; + SparseLinearAlgebraLibraryType sparse_linear_algebra_library; + + // See solver.h for explanation of this option. + bool use_block_amd; + // Number of internal iterations that the solver uses. This // parameter only makes sense for iterative solvers like CG. int min_num_iterations; @@ -93,10 +100,6 @@ class LinearSolver { // If possible, how many threads can the solver use. int num_threads; - // If possible cache and reuse the symbolic factorization across - // multiple calls. - bool constant_sparsity; - // Eliminate 0 to num_eliminate_blocks - 1 from the Normal // equations to form a schur complement. Only used by the Schur // complement based solver. The most common use for this parameter @@ -121,8 +124,8 @@ class LinearSolver { // It is expected that these parameters are set programmatically // rather than manually. // - // Please see explicit_schur_complement_solver_impl.h for more - // details. + // Please see schur_complement_solver.h and schur_eliminator.h for + // more details. int row_block_size; int e_block_size; int f_block_size; @@ -244,6 +247,7 @@ class LinearSolver { const PerSolveOptions& per_solve_options, double* x) = 0; + // Factory static LinearSolver* Create(const Options& options); }; diff --git a/extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc b/extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc index eeae74e3f95..26e7f4908a4 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/local_parameterization.cc @@ -28,10 +28,11 @@ // // Author: sameeragarwal@google.com (Sameer Agarwal) -#include -#include "ceres/internal/eigen.h" #include "ceres/local_parameterization.h" + +#include "ceres/internal/eigen.h" #include "ceres/rotation.h" +#include "glog/logging.h" namespace ceres { diff --git a/extern/libmv/third_party/ceres/internal/ceres/loss_function.cc b/extern/libmv/third_party/ceres/internal/ceres/loss_function.cc index 00b2b184729..b948f289f21 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/loss_function.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/loss_function.cc @@ -77,6 +77,70 @@ void CauchyLoss::Evaluate(double s, double rho[3]) const { rho[2] = - c_ * (inv * inv); } +void ArctanLoss::Evaluate(double s, double rho[3]) const { + const double sum = 1 + s * s * b_; + const double inv = 1 / sum; + // 'sum' and 'inv' are always positive. + rho[0] = a_ * atan2(s, a_); + rho[1] = inv; + rho[2] = -2 * s * b_ * (inv * inv); +} + +TolerantLoss::TolerantLoss(double a, double b) + : a_(a), + b_(b), + c_(b * log(1.0 + exp(-a / b))) { + CHECK_GE(a, 0.0); + CHECK_GT(b, 0.0); +} + +void TolerantLoss::Evaluate(double s, double rho[3]) const { + const double x = (s - a_) / b_; + // The basic equation is rho[0] = b ln(1 + e^x). However, if e^x is too + // large, it will overflow. Since numerically 1 + e^x == e^x when the + // x is greater than about ln(2^53) for doubles, beyond this threshold + // we substitute x for ln(1 + e^x) as a numerically equivalent approximation. + static const double kLog2Pow53 = 36.7; // ln(MathLimits::kEpsilon). + if (x > kLog2Pow53) { + rho[0] = s - a_ - c_; + rho[1] = 1.0; + rho[2] = 0.0; + } else { + const double e_x = exp(x); + rho[0] = b_ * log(1.0 + e_x) - c_; + rho[1] = e_x / (1.0 + e_x); + rho[2] = 0.5 / (b_ * (1.0 + cosh(x))); + } +} + +ComposedLoss::ComposedLoss(const LossFunction* f, Ownership ownership_f, + const LossFunction* g, Ownership ownership_g) + : f_(CHECK_NOTNULL(f)), + g_(CHECK_NOTNULL(g)), + ownership_f_(ownership_f), + ownership_g_(ownership_g) { +} + +ComposedLoss::~ComposedLoss() { + if (ownership_f_ == DO_NOT_TAKE_OWNERSHIP) { + f_.release(); + } + if (ownership_g_ == DO_NOT_TAKE_OWNERSHIP) { + g_.release(); + } +} + +void ComposedLoss::Evaluate(double s, double rho[3]) const { + double rho_f[3], rho_g[3]; + g_->Evaluate(s, rho_g); + f_->Evaluate(rho_g[0], rho_f); + rho[0] = rho_f[0]; + // f'(g(s)) * g'(s). + rho[1] = rho_f[1] * rho_g[1]; + // f''(g(s)) * g'(s) * g'(s) + f'(g(s)) * g''(s). + rho[2] = rho_f[2] * rho_g[1] * rho_g[1] + rho_f[1] * rho_g[2]; +} + void ScaledLoss::Evaluate(double s, double rho[3]) const { if (rho_.get() == NULL) { rho[0] = a_ * s; diff --git a/extern/libmv/third_party/ceres/internal/ceres/matrix_proto.h b/extern/libmv/third_party/ceres/internal/ceres/matrix_proto.h index b8a3a1a6de6..94b3076e3d7 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/matrix_proto.h +++ b/extern/libmv/third_party/ceres/internal/ceres/matrix_proto.h @@ -33,7 +33,7 @@ #ifndef CERES_INTERNAL_MATRIX_PROTO_H_ #define CERES_INTERNAL_MATRIX_PROTO_H_ -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS #include "ceres/matrix.pb.h" #endif diff --git a/extern/libmv/third_party/ceres/internal/ceres/minimizer.h b/extern/libmv/third_party/ceres/internal/ceres/minimizer.h index 77cb00cb6b4..cfc98a3ebd0 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/minimizer.h +++ b/extern/libmv/third_party/ceres/internal/ceres/minimizer.h @@ -40,6 +40,8 @@ namespace internal { class Evaluator; class LinearSolver; +class SparseMatrix; +class TrustRegionStrategy; // Interface for non-linear least squares solvers. class Minimizer { @@ -48,53 +50,93 @@ class Minimizer { // see solver.h for detailed information about the meaning and // default values of each of these parameters. struct Options { + Options() { + Init(Solver::Options()); + } + explicit Options(const Solver::Options& options) { + Init(options); + } + + void Init(const Solver::Options& options) { max_num_iterations = options.max_num_iterations; - max_solver_time_sec = options.max_solver_time_sec; + max_solver_time_in_seconds = options.max_solver_time_in_seconds; + max_step_solver_retries = 5; gradient_tolerance = options.gradient_tolerance; parameter_tolerance = options.parameter_tolerance; function_tolerance = options.function_tolerance; min_relative_decrease = options.min_relative_decrease; eta = options.eta; - tau = options.tau; jacobi_scaling = options.jacobi_scaling; - crash_and_dump_lsqp_on_failure = options.crash_and_dump_lsqp_on_failure; + use_nonmonotonic_steps = options.use_nonmonotonic_steps; + max_consecutive_nonmonotonic_steps = + options.max_consecutive_nonmonotonic_steps; lsqp_dump_directory = options.lsqp_dump_directory; lsqp_iterations_to_dump = options.lsqp_iterations_to_dump; lsqp_dump_format_type = options.lsqp_dump_format_type; num_eliminate_blocks = options.num_eliminate_blocks; - logging_type = options.logging_type; + max_num_consecutive_invalid_steps = + options.max_num_consecutive_invalid_steps; + min_trust_region_radius = options.min_trust_region_radius; + evaluator = NULL; + trust_region_strategy = NULL; + jacobian = NULL; + callbacks = options.callbacks; } int max_num_iterations; - int max_solver_time_sec; + double max_solver_time_in_seconds; + + // Number of times the linear solver should be retried in case of + // numerical failure. The retries are done by exponentially scaling up + // mu at each retry. This leads to stronger and stronger + // regularization making the linear least squares problem better + // conditioned at each retry. + int max_step_solver_retries; double gradient_tolerance; double parameter_tolerance; double function_tolerance; double min_relative_decrease; double eta; - double tau; bool jacobi_scaling; - bool crash_and_dump_lsqp_on_failure; + bool use_nonmonotonic_steps; + int max_consecutive_nonmonotonic_steps; vector lsqp_iterations_to_dump; DumpFormatType lsqp_dump_format_type; string lsqp_dump_directory; int num_eliminate_blocks; - LoggingType logging_type; + int max_num_consecutive_invalid_steps; + int min_trust_region_radius; // List of callbacks that are executed by the Minimizer at the end // of each iteration. // - // Client owns these pointers. + // The Options struct does not own these pointers. vector callbacks; + + // Object responsible for evaluating the cost, residuals and + // Jacobian matrix. The Options struct does not own this pointer. + Evaluator* evaluator; + + // Object responsible for actually computing the trust region + // step, and sizing the trust region radius. The Options struct + // does not own this pointer. + TrustRegionStrategy* trust_region_strategy; + + // Object holding the Jacobian matrix. It is assumed that the + // sparsity structure of the matrix has already been initialized + // and will remain constant for the life time of the + // optimization. The Options struct does not own this pointer. + SparseMatrix* jacobian; }; virtual ~Minimizer() {} + + // Note: The minimizer is expected to update the state of the + // parameters array every iteration. This is required for the + // StateUpdatingCallback to work. virtual void Minimize(const Options& options, - Evaluator* evaluator, - LinearSolver* linear_solver, - const double* initial_parameters, - double* final_parameters, + double* parameters, Solver::Summary* summary) = 0; }; diff --git a/extern/libmv/third_party/ceres/internal/ceres/mutex.h b/extern/libmv/third_party/ceres/internal/ceres/mutex.h index 6514b107041..5090a71b78d 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/mutex.h +++ b/extern/libmv/third_party/ceres/internal/ceres/mutex.h @@ -95,11 +95,11 @@ #ifndef CERES_INTERNAL_MUTEX_H_ #define CERES_INTERNAL_MUTEX_H_ -#if defined(NO_THREADS) +#if defined(CERES_NO_THREADS) typedef int MutexType; // to keep a lock-count #elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__) -# define WIN32_LEAN_AND_MEAN // We only need minimal includes -# ifdef GMUTEX_TRYLOCK +# define CERES_WIN32_LEAN_AND_MEAN // We only need minimal includes +# ifdef CERES_GMUTEX_TRYLOCK // We need Windows NT or later for TryEnterCriticalSection(). If you // don't need that functionality, you can remove these _WIN32_WINNT // lines, and change TryLock() to assert(0) or something. @@ -108,9 +108,9 @@ # endif # endif // To avoid macro definition of ERROR. -# define NOGDI +# define CERES_NOGDI // To avoid macro definition of min/max. -# define NOMINMAX +# define CERES_NOMINMAX # include typedef CRITICAL_SECTION MutexType; #elif defined(CERES_HAVE_PTHREAD) && defined(CERES_HAVE_RWLOCK) @@ -151,7 +151,7 @@ class Mutex { inline void Lock(); // Block if needed until free then acquire exclusively inline void Unlock(); // Release a lock acquired via Lock() -#ifdef GMUTEX_TRYLOCK +#ifdef CERES_GMUTEX_TRYLOCK inline bool TryLock(); // If free, Lock() and return true, else return false #endif // Note that on systems that don't support read-write locks, these may @@ -183,7 +183,7 @@ class Mutex { }; // Now the implementation of Mutex for various systems -#if defined(NO_THREADS) +#if defined(CERES_NO_THREADS) // When we don't have threads, we can be either reading or writing, // but not both. We can have lots of readers at once (in no-threads @@ -199,7 +199,7 @@ Mutex::Mutex() : mutex_(0) { } Mutex::~Mutex() { assert(mutex_ == 0); } void Mutex::Lock() { assert(--mutex_ == -1); } void Mutex::Unlock() { assert(mutex_++ == -1); } -#ifdef GMUTEX_TRYLOCK +#ifdef CERES_GMUTEX_TRYLOCK bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; } #endif void Mutex::ReaderLock() { assert(++mutex_ > 0); } @@ -220,91 +220,101 @@ void Mutex::ReaderUnlock() { Unlock(); } #elif defined(CERES_HAVE_PTHREAD) && defined(CERES_HAVE_RWLOCK) -#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ - if (is_safe_ && fncall(&mutex_) != 0) abort(); \ +#define CERES_SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ + if (is_safe_ && fncall(&mutex_) != 0) abort(); \ } while (0) Mutex::Mutex() { SetIsSafe(); if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort(); } -Mutex::~Mutex() { SAFE_PTHREAD(pthread_rwlock_destroy); } -void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); } -void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } -#ifdef GMUTEX_TRYLOCK +Mutex::~Mutex() { CERES_SAFE_PTHREAD(pthread_rwlock_destroy); } +void Mutex::Lock() { CERES_SAFE_PTHREAD(pthread_rwlock_wrlock); } +void Mutex::Unlock() { CERES_SAFE_PTHREAD(pthread_rwlock_unlock); } +#ifdef CERES_GMUTEX_TRYLOCK bool Mutex::TryLock() { return is_safe_ ? pthread_rwlock_trywrlock(&mutex_) == 0 : true; } #endif -void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); } -void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); } -#undef SAFE_PTHREAD +void Mutex::ReaderLock() { CERES_SAFE_PTHREAD(pthread_rwlock_rdlock); } +void Mutex::ReaderUnlock() { CERES_SAFE_PTHREAD(pthread_rwlock_unlock); } +#undef CERES_SAFE_PTHREAD #elif defined(CERES_HAVE_PTHREAD) -#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ - if (is_safe_ && fncall(&mutex_) != 0) abort(); \ +#define CERES_SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ + if (is_safe_ && fncall(&mutex_) != 0) abort(); \ } while (0) Mutex::Mutex() { SetIsSafe(); if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort(); } -Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy); } -void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); } -void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); } -#ifdef GMUTEX_TRYLOCK +Mutex::~Mutex() { CERES_SAFE_PTHREAD(pthread_mutex_destroy); } +void Mutex::Lock() { CERES_SAFE_PTHREAD(pthread_mutex_lock); } +void Mutex::Unlock() { CERES_SAFE_PTHREAD(pthread_mutex_unlock); } +#ifdef CERES_GMUTEX_TRYLOCK bool Mutex::TryLock() { return is_safe_ ? pthread_mutex_trylock(&mutex_) == 0 : true; } #endif void Mutex::ReaderLock() { Lock(); } void Mutex::ReaderUnlock() { Unlock(); } -#undef SAFE_PTHREAD +#undef CERES_SAFE_PTHREAD #endif // -------------------------------------------------------------------------- // Some helper classes -// MutexLock(mu) acquires mu when constructed and releases it when destroyed. -class MutexLock { +// Note: The weird "Ceres" prefix for the class is a workaround for having two +// similar mutex.h files included in the same translation unit. This is a +// problem because macros do not respect C++ namespaces, and as a result, this +// does not work well (e.g. inside Chrome). The offending macros are +// "MutexLock(x) COMPILE_ASSERT(false)". To work around this, "Ceres" is +// prefixed to the class names; this permits defining the classes. + +// CeresMutexLock(mu) acquires mu when constructed and releases it when destroyed. +class CeresMutexLock { public: - explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); } - ~MutexLock() { mu_->Unlock(); } + explicit CeresMutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); } + ~CeresMutexLock() { mu_->Unlock(); } private: Mutex * const mu_; // Disallow "evil" constructors - MutexLock(const MutexLock&); - void operator=(const MutexLock&); + CeresMutexLock(const CeresMutexLock&); + void operator=(const CeresMutexLock&); }; -// ReaderMutexLock and WriterMutexLock do the same, for rwlocks -class ReaderMutexLock { +// CeresReaderMutexLock and CeresWriterMutexLock do the same, for rwlocks +class CeresReaderMutexLock { public: - explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); } - ~ReaderMutexLock() { mu_->ReaderUnlock(); } + explicit CeresReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); } + ~CeresReaderMutexLock() { mu_->ReaderUnlock(); } private: Mutex * const mu_; // Disallow "evil" constructors - ReaderMutexLock(const ReaderMutexLock&); - void operator=(const ReaderMutexLock&); + CeresReaderMutexLock(const CeresReaderMutexLock&); + void operator=(const CeresReaderMutexLock&); }; -class WriterMutexLock { +class CeresWriterMutexLock { public: - explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); } - ~WriterMutexLock() { mu_->WriterUnlock(); } + explicit CeresWriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); } + ~CeresWriterMutexLock() { mu_->WriterUnlock(); } private: Mutex * const mu_; // Disallow "evil" constructors - WriterMutexLock(const WriterMutexLock&); - void operator=(const WriterMutexLock&); + CeresWriterMutexLock(const CeresWriterMutexLock&); + void operator=(const CeresWriterMutexLock&); }; // Catch bug where variable name is omitted, e.g. MutexLock (&mu); -#define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name) -#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name) -#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name) +#define CeresMutexLock(x) \ + COMPILE_ASSERT(0, ceres_mutex_lock_decl_missing_var_name) +#define CeresReaderMutexLock(x) \ + COMPILE_ASSERT(0, ceres_rmutex_lock_decl_missing_var_name) +#define CeresWriterMutexLock(x) \ + COMPILE_ASSERT(0, ceres_wmutex_lock_decl_missing_var_name) } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/normal_prior.cc b/extern/libmv/third_party/ceres/internal/ceres/normal_prior.cc index f30bbc8b46b..392d728fb32 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/normal_prior.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/normal_prior.cc @@ -32,11 +32,10 @@ #include #include - -#include #include "ceres/internal/eigen.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/types.h" +#include "glog/logging.h" namespace ceres { diff --git a/extern/libmv/third_party/ceres/internal/ceres/parameter_block.h b/extern/libmv/third_party/ceres/internal/ceres/parameter_block.h index 4bac1a85828..f20805ca873 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/parameter_block.h +++ b/extern/libmv/third_party/ceres/internal/ceres/parameter_block.h @@ -32,13 +32,15 @@ #define CERES_INTERNAL_PARAMETER_BLOCK_H_ #include +#include +#include "ceres/array_utils.h" #include "ceres/integral_types.h" -#include #include "ceres/internal/eigen.h" #include "ceres/internal/port.h" #include "ceres/internal/scoped_ptr.h" #include "ceres/local_parameterization.h" -#include "ceres/residual_block_utils.h" +#include "ceres/stringprintf.h" +#include "glog/logging.h" namespace ceres { namespace internal { @@ -172,6 +174,19 @@ class ParameterBlock { return local_parameterization_->Plus(x, delta, x_plus_delta); } + string ToString() const { + return StringPrintf("{ user_state=%p, state=%p, size=%d, " + "constant=%d, index=%d, state_offset=%d, " + "delta_offset=%d }", + user_state_, + state_, + size_, + is_constant_, + index_, + state_offset_, + delta_offset_); + } + private: void Init(double* user_state, int size, diff --git a/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc b/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc index fcf8fd53aed..0722fc82c02 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/partitioned_matrix_view.cc @@ -35,10 +35,10 @@ #include #include #include -#include #include "ceres/block_sparse_matrix.h" #include "ceres/block_structure.h" #include "ceres/internal/eigen.h" +#include "glog/logging.h" namespace ceres { namespace internal { diff --git a/extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.cc new file mode 100644 index 00000000000..20c01566a89 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.cc @@ -0,0 +1,184 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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 Google Inc. 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. +// +// Author: moll.markus@arcor.de (Markus Moll) + +#include "ceres/polynomial_solver.h" + +#include +#include +#include "Eigen/Dense" +#include "ceres/internal/port.h" +#include "glog/logging.h" + +namespace ceres { +namespace internal { +namespace { + +// Balancing function as described by B. N. Parlett and C. Reinsch, +// "Balancing a Matrix for Calculation of Eigenvalues and Eigenvectors". +// In: Numerische Mathematik, Volume 13, Number 4 (1969), 293-304, +// Springer Berlin / Heidelberg. DOI: 10.1007/BF02165404 +void BalanceCompanionMatrix(Matrix* companion_matrix_ptr) { + CHECK_NOTNULL(companion_matrix_ptr); + Matrix& companion_matrix = *companion_matrix_ptr; + Matrix companion_matrix_offdiagonal = companion_matrix; + companion_matrix_offdiagonal.diagonal().setZero(); + + const int degree = companion_matrix.rows(); + + // gamma <= 1 controls how much a change in the scaling has to + // lower the 1-norm of the companion matrix to be accepted. + // + // gamma = 1 seems to lead to cycles (numerical issues?), so + // we set it slightly lower. + const double gamma = 0.9; + + // Greedily scale row/column pairs until there is no change. + bool scaling_has_changed; + do { + scaling_has_changed = false; + + for (int i = 0; i < degree; ++i) { + const double row_norm = companion_matrix_offdiagonal.row(i).lpNorm<1>(); + const double col_norm = companion_matrix_offdiagonal.col(i).lpNorm<1>(); + + // Decompose row_norm/col_norm into mantissa * 2^exponent, + // where 0.5 <= mantissa < 1. Discard mantissa (return value + // of frexp), as only the exponent is needed. + int exponent = 0; + std::frexp(row_norm / col_norm, &exponent); + exponent /= 2; + + if (exponent != 0) { + const double scaled_col_norm = std::ldexp(col_norm, exponent); + const double scaled_row_norm = std::ldexp(row_norm, -exponent); + if (scaled_col_norm + scaled_row_norm < gamma * (col_norm + row_norm)) { + // Accept the new scaling. (Multiplication by powers of 2 should not + // introduce rounding errors (ignoring non-normalized numbers and + // over- or underflow)) + scaling_has_changed = true; + companion_matrix_offdiagonal.row(i) *= std::ldexp(1.0, -exponent); + companion_matrix_offdiagonal.col(i) *= std::ldexp(1.0, exponent); + } + } + } + } while (scaling_has_changed); + + companion_matrix_offdiagonal.diagonal() = companion_matrix.diagonal(); + companion_matrix = companion_matrix_offdiagonal; + VLOG(3) << "Balanced companion matrix is\n" << companion_matrix; +} + +void BuildCompanionMatrix(const Vector& polynomial, + Matrix* companion_matrix_ptr) { + CHECK_NOTNULL(companion_matrix_ptr); + Matrix& companion_matrix = *companion_matrix_ptr; + + const int degree = polynomial.size() - 1; + + companion_matrix.resize(degree, degree); + companion_matrix.setZero(); + companion_matrix.diagonal(-1).setOnes(); + companion_matrix.col(degree - 1) = -polynomial.reverse().head(degree); +} + +// Remove leading terms with zero coefficients. +Vector RemoveLeadingZeros(const Vector& polynomial_in) { + int i = 0; + while (i < (polynomial_in.size() - 1) && polynomial_in(i) == 0.0) { + ++i; + } + return polynomial_in.tail(polynomial_in.size() - i); +} +} // namespace + +bool FindPolynomialRoots(const Vector& polynomial_in, + Vector* real, + Vector* imaginary) { + if (polynomial_in.size() == 0) { + LOG(ERROR) << "Invalid polynomial of size 0 passed to FindPolynomialRoots"; + return false; + } + + Vector polynomial = RemoveLeadingZeros(polynomial_in); + const int degree = polynomial.size() - 1; + + // Is the polynomial constant? + if (degree == 0) { + LOG(WARNING) << "Trying to extract roots from a constant " + << "polynomial in FindPolynomialRoots"; + return true; + } + + // Divide by leading term + const double leading_term = polynomial(0); + polynomial /= leading_term; + + // Separately handle linear polynomials. + if (degree == 1) { + if (real != NULL) { + real->resize(1); + (*real)(0) = -polynomial(1); + } + if (imaginary != NULL) { + imaginary->resize(1); + imaginary->setZero(); + } + } + + // The degree is now known to be at least 2. + // Build and balance the companion matrix to the polynomial. + Matrix companion_matrix(degree, degree); + BuildCompanionMatrix(polynomial, &companion_matrix); + BalanceCompanionMatrix(&companion_matrix); + + // Find its (complex) eigenvalues. + Eigen::EigenSolver solver(companion_matrix, + Eigen::EigenvaluesOnly); + if (solver.info() != Eigen::Success) { + LOG(ERROR) << "Failed to extract eigenvalues from companion matrix."; + return false; + } + + // Output roots + if (real != NULL) { + *real = solver.eigenvalues().real(); + } else { + LOG(WARNING) << "NULL pointer passed as real argument to " + << "FindPolynomialRoots. Real parts of the roots will not " + << "be returned."; + } + if (imaginary != NULL) { + *imaginary = solver.eigenvalues().imag(); + } + return true; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.h b/extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.h new file mode 100644 index 00000000000..1cf07ddb549 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/polynomial_solver.h @@ -0,0 +1,65 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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 Google Inc. 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. +// +// Author: moll.markus@arcor.de (Markus Moll) + +#ifndef CERES_INTERNAL_POLYNOMIAL_SOLVER_H_ +#define CERES_INTERNAL_POLYNOMIAL_SOLVER_H_ + +#include "ceres/internal/eigen.h" + +namespace ceres { +namespace internal { + +// Use the companion matrix eigenvalues to determine the roots of the polynomial +// +// sum_{i=0}^N polynomial(i) x^{N-i}. +// +// This function returns true on success, false otherwise. +// Failure indicates that the polynomial is invalid (of size 0) or +// that the eigenvalues of the companion matrix could not be computed. +// On failure, a more detailed message will be written to LOG(ERROR). +// If real is not NULL, the real parts of the roots will be returned in it. +// Likewise, if imaginary is not NULL, imaginary parts will be returned in it. +bool FindPolynomialRoots(const Vector& polynomial, + Vector* real, + Vector* imaginary); + +// Evaluate the polynomial at x using the Horner scheme. +inline double EvaluatePolynomial(const Vector& polynomial, double x) { + double v = 0.0; + for (int i = 0; i < polynomial.size(); ++i) { + v = v * x + polynomial(i); + } + return v; +} + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_POLYNOMIAL_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc index 68242477d6f..c186f527be8 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc @@ -37,16 +37,15 @@ #include #include #include - -#include +#include "ceres/cost_function.h" +#include "ceres/loss_function.h" +#include "ceres/map_util.h" #include "ceres/parameter_block.h" #include "ceres/program.h" #include "ceres/residual_block.h" #include "ceres/stl_util.h" -#include "ceres/map_util.h" #include "ceres/stringprintf.h" -#include "ceres/cost_function.h" -#include "ceres/loss_function.h" +#include "glog/logging.h" namespace ceres { namespace internal { diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h index 523860e652a..2ca055448c3 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h +++ b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.h @@ -118,7 +118,7 @@ class ProblemImpl { map parameter_block_map_; internal::scoped_ptr program_; - DISALLOW_COPY_AND_ASSIGN(ProblemImpl); + CERES_DISALLOW_COPY_AND_ASSIGN(ProblemImpl); }; } // namespace internal diff --git a/extern/libmv/third_party/ceres/internal/ceres/program.cc b/extern/libmv/third_party/ceres/internal/ceres/program.cc index 444b1020253..82d76d39233 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/program.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/program.cc @@ -32,14 +32,18 @@ #include #include +#include "ceres/casts.h" +#include "ceres/compressed_row_sparse_matrix.h" +#include "ceres/cost_function.h" +#include "ceres/evaluator.h" +#include "ceres/internal/port.h" +#include "ceres/local_parameterization.h" +#include "ceres/loss_function.h" +#include "ceres/map_util.h" #include "ceres/parameter_block.h" +#include "ceres/problem.h" #include "ceres/residual_block.h" #include "ceres/stl_util.h" -#include "ceres/map_util.h" -#include "ceres/problem.h" -#include "ceres/cost_function.h" -#include "ceres/loss_function.h" -#include "ceres/local_parameterization.h" namespace ceres { namespace internal { @@ -69,7 +73,8 @@ vector* Program::mutable_residual_blocks() { bool Program::StateVectorToParameterBlocks(const double *state) { for (int i = 0; i < parameter_blocks_.size(); ++i) { - if (!parameter_blocks_[i]->SetState(state)) { + if (!parameter_blocks_[i]->IsConstant() && + !parameter_blocks_[i]->SetState(state)) { return false; } state += parameter_blocks_[i]->Size(); @@ -86,11 +91,20 @@ void Program::ParameterBlocksToStateVector(double *state) const { void Program::CopyParameterBlockStateToUserState() { for (int i = 0; i < parameter_blocks_.size(); ++i) { - parameter_blocks_[i]->GetState( - parameter_blocks_[i]->mutable_user_state()); + parameter_blocks_[i]->GetState(parameter_blocks_[i]->mutable_user_state()); } } +bool Program::SetParameterBlockStatePtrsToUserStatePtrs() { + for (int i = 0; i < parameter_blocks_.size(); ++i) { + if (!parameter_blocks_[i]->IsConstant() && + !parameter_blocks_[i]->SetState(parameter_blocks_[i]->user_state())) { + return false; + } + } + return true; +} + bool Program::Plus(const double* state, const double* delta, double* state_plus_delta) const { @@ -193,40 +207,25 @@ int Program::MaxParametersPerResidualBlock() const { return max_parameters; } -bool Program::Evaluate(double* cost, double* residuals) { - *cost = 0.0; - - // Scratch space is only needed if residuals is NULL. - scoped_array scratch; - if (residuals == NULL) { - scratch.reset(new double[MaxScratchDoublesNeededForEvaluate()]); - } else { - // TODO(keir): Is this needed? Check by removing the equivalent statement in - // dense_evaluator.cc and running the tests. - VectorRef(residuals, NumResiduals()).setZero(); - } - +int Program::MaxResidualsPerResidualBlock() const { + int max_residuals = 0; for (int i = 0; i < residual_blocks_.size(); ++i) { - ResidualBlock* residual_block = residual_blocks_[i]; - - // Evaluate the cost function for this residual. - double residual_cost; - if (!residual_block->Evaluate(&residual_cost, - residuals, - NULL, // No jacobian. - scratch.get())) { - return false; - } - - // Accumulate residual cost into the total cost. - *cost += residual_cost; - - // Update the residuals cursor. - if (residuals != NULL) { - residuals += residual_block->NumResiduals(); - } + max_residuals = max(max_residuals, + residual_blocks_[i]->NumResiduals()); } - return true; + return max_residuals; +} + +string Program::ToString() const { + string ret = "Program dump\n"; + ret += StringPrintf("Number of parameter blocks: %d\n", NumParameterBlocks()); + ret += StringPrintf("Number of parameters: %d\n", NumParameters()); + ret += "Parameters:\n"; + for (int i = 0; i < parameter_blocks_.size(); ++i) { + ret += StringPrintf("%d: %s\n", + i, parameter_blocks_[i]->ToString().c_str()); + } + return ret; } } // namespace internal diff --git a/extern/libmv/third_party/ceres/internal/ceres/program.h b/extern/libmv/third_party/ceres/internal/ceres/program.h index 113d352d562..5002b7e752e 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/program.h +++ b/extern/libmv/third_party/ceres/internal/ceres/program.h @@ -31,6 +31,7 @@ #ifndef CERES_INTERNAL_PROGRAM_H_ #define CERES_INTERNAL_PROGRAM_H_ +#include #include #include "ceres/internal/port.h" @@ -71,9 +72,14 @@ class Program { bool StateVectorToParameterBlocks(const double *state); void ParameterBlocksToStateVector(double *state) const; - // Copy internal state out to the user's parameters. + // Copy internal state to the user's parameters. void CopyParameterBlockStateToUserState(); + // Set the parameter block pointers to the user pointers. Since this + // runs parameter block set state internally, which may call local + // parameterizations, this can fail. False is returned on failure. + bool SetParameterBlockStatePtrsToUserStatePtrs(); + // Update a state vector for the program given a delta. bool Plus(const double* state, const double* delta, @@ -103,16 +109,11 @@ class Program { int MaxScratchDoublesNeededForEvaluate() const; int MaxDerivativesPerResidualBlock() const; int MaxParametersPerResidualBlock() const; + int MaxResidualsPerResidualBlock() const; - // Evaluate the cost and maybe the residuals for the program. If residuals is - // NULL, then residuals are not calculated. If the jacobian is needed, instead - // use the various evaluators (e.g. dense_evaluator.h). - // - // This is a trivial implementation of evaluate not intended for use in the - // core solving loop. The other evaluators, which support constructing the - // jacobian in addition to the cost and residuals, are considerably - // complicated by the need to construct the jacobian. - bool Evaluate(double* cost, double* residuals); + // A human-readable dump of the parameter blocks for debugging. + // TODO(keir): If necessary, also dump the residual blocks. + string ToString() const; private: // The Program does not own the ParameterBlock or ResidualBlock objects. diff --git a/extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h b/extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h index 7ec74b1b269..6c48e7d7643 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h +++ b/extern/libmv/third_party/ceres/internal/ceres/program_evaluator.h @@ -120,13 +120,18 @@ class ProgramEvaluator : public Evaluator { bool Evaluate(const double* state, double* cost, double* residuals, + double* gradient, SparseMatrix* jacobian) { // The parameters are stateful, so set the state before evaluating. if (!program_->StateVectorToParameterBlocks(state)) { return false; } - if (jacobian) { + if (residuals != NULL) { + VectorRef(residuals, program_->NumResiduals()).setZero(); + } + + if (jacobian != NULL) { jacobian->SetZero(); } @@ -158,13 +163,16 @@ class ProgramEvaluator : public Evaluator { // Prepare block residuals if requested. const ResidualBlock* residual_block = program_->residual_blocks()[i]; - double* block_residuals = (residuals != NULL) - ? (residuals + residual_layout_[i]) - : NULL; + double* block_residuals = NULL; + if (residuals != NULL) { + block_residuals = residuals + residual_layout_[i]; + } else if (gradient != NULL) { + block_residuals = scratch->residual_block_residuals.get(); + } // Prepare block jacobians if requested. double** block_jacobians = NULL; - if (jacobian != NULL) { + if (jacobian != NULL || gradient != NULL) { preparer->Prepare(residual_block, i, jacobian, @@ -174,10 +182,11 @@ class ProgramEvaluator : public Evaluator { // Evaluate the cost, residuals, and jacobians. double block_cost; - if (!residual_block->Evaluate(&block_cost, - block_residuals, - block_jacobians, - scratch->scratch.get())) { + if (!residual_block->Evaluate( + &block_cost, + block_residuals, + block_jacobians, + scratch->residual_block_evaluate_scratch.get())) { abort = true; // This ensures that the OpenMP threads have a consistent view of 'abort'. Do // the flush inside the failure case so that there is usually only one @@ -188,19 +197,49 @@ class ProgramEvaluator : public Evaluator { scratch->cost += block_cost; + // Store the jacobians, if they were requested. if (jacobian != NULL) { jacobian_writer_.Write(i, residual_layout_[i], block_jacobians, jacobian); } + + // Compute and store the gradient, if it was requested. + if (gradient != NULL) { + int num_residuals = residual_block->NumResiduals(); + int num_parameter_blocks = residual_block->NumParameterBlocks(); + for (int j = 0; j < num_parameter_blocks; ++j) { + const ParameterBlock* parameter_block = + residual_block->parameter_blocks()[j]; + if (parameter_block->IsConstant()) { + continue; + } + MatrixRef block_jacobian(block_jacobians[j], + num_residuals, + parameter_block->LocalSize()); + VectorRef block_gradient(scratch->gradient.get() + + parameter_block->delta_offset(), + parameter_block->LocalSize()); + VectorRef block_residual(block_residuals, num_residuals); + block_gradient += block_residual.transpose() * block_jacobian; + } + } } if (!abort) { - // Sum the cost from each thread. + // Sum the cost and gradient (if requested) from each thread. (*cost) = 0.0; + int num_parameters = program_->NumEffectiveParameters(); + if (gradient != NULL) { + VectorRef(gradient, num_parameters).setZero(); + } for (int i = 0; i < options_.num_threads; ++i) { (*cost) += evaluate_scratch_[i].cost; + if (gradient != NULL) { + VectorRef(gradient, num_parameters) += + VectorRef(evaluate_scratch_[i].gradient.get(), num_parameters); + } } } return !abort; @@ -224,16 +263,28 @@ class ProgramEvaluator : public Evaluator { } private: + // Per-thread scratch space needed to evaluate and store each residual block. struct EvaluateScratch { void Init(int max_parameters_per_residual_block, - int max_scratch_doubles_needed_for_evaluate) { + int max_scratch_doubles_needed_for_evaluate, + int max_residuals_per_residual_block, + int num_parameters) { + residual_block_evaluate_scratch.reset( + new double[max_scratch_doubles_needed_for_evaluate]); + gradient.reset(new double[num_parameters]); + VectorRef(gradient.get(), num_parameters).setZero(); + residual_block_residuals.reset( + new double[max_residuals_per_residual_block]); jacobian_block_ptrs.reset( new double*[max_parameters_per_residual_block]); - scratch.reset(new double[max_scratch_doubles_needed_for_evaluate]); } double cost; - scoped_array scratch; + scoped_array residual_block_evaluate_scratch; + // The gradient in the local parameterization. + scoped_array gradient; + // Enough space to store the residual for the largest residual block. + scoped_array residual_block_residuals; scoped_array jacobian_block_ptrs; }; @@ -256,11 +307,16 @@ class ProgramEvaluator : public Evaluator { program.MaxParametersPerResidualBlock(); int max_scratch_doubles_needed_for_evaluate = program.MaxScratchDoublesNeededForEvaluate(); + int max_residuals_per_residual_block = + program.MaxResidualsPerResidualBlock(); + int num_parameters = program.NumEffectiveParameters(); EvaluateScratch* evaluate_scratch = new EvaluateScratch[num_threads]; for (int i = 0; i < num_threads; i++) { evaluate_scratch[i].Init(max_parameters_per_residual_block, - max_scratch_doubles_needed_for_evaluate); + max_scratch_doubles_needed_for_evaluate, + max_residuals_per_residual_block, + num_parameters); } return evaluate_scratch; } diff --git a/extern/libmv/third_party/ceres/internal/ceres/random.h b/extern/libmv/third_party/ceres/internal/ceres/random.h index 769e0b4dd27..352c0032b5a 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/random.h +++ b/extern/libmv/third_party/ceres/internal/ceres/random.h @@ -27,21 +27,44 @@ // POSSIBILITY OF SUCH DAMAGE. // // Author: keir@google.com (Keir Mierle) +// sameeragarwal@google.com (Sameer Agarwal) #ifndef CERES_INTERNAL_RANDOM_H_ #define CERES_INTERNAL_RANDOM_H_ +#include +#include +#include "ceres/internal/port.h" + namespace ceres { -inline double RandDouble() { - double r = rand(); - return r / RAND_MAX; +inline void SetRandomState(int state) { + srand(state); } inline int Uniform(int n) { return rand() % n; } +inline double RandDouble() { + double r = static_cast(rand()); + return r / RAND_MAX; +} + +// Box-Muller algorithm for normal random number generation. +// http://en.wikipedia.org/wiki/Box-Muller_transform +inline double RandNormal() { + double x1, x2, w; + do { + x1 = 2.0 * RandDouble() - 1.0; + x2 = 2.0 * RandDouble() - 1.0; + w = x1 * x1 + x2 * x2; + } while ( w >= 1.0 || w == 0.0 ); + + w = sqrt((-2.0 * log(w)) / w); + return x1 * w; +} + } // namespace ceres #endif // CERES_INTERNAL_RANDOM_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/residual_block.cc b/extern/libmv/third_party/ceres/internal/ceres/residual_block.cc index 03867891dba..bdb88b1dd97 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/residual_block.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/residual_block.cc @@ -102,8 +102,11 @@ bool ResidualBlock::Evaluate(double* cost, InvalidateEvaluation(*this, cost, residuals, eval_jacobians); - if (!cost_function_->Evaluate(parameters.get(), residuals, eval_jacobians) || - !IsEvaluationValid(*this, + if (!cost_function_->Evaluate(parameters.get(), residuals, eval_jacobians)) { + return false; + } + + if (!IsEvaluationValid(*this, parameters.get(), cost, residuals, diff --git a/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc b/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc index 28e03130844..9442bb2a1c1 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.cc @@ -33,46 +33,17 @@ #include #include #include -#include -#include "ceres/residual_block.h" -#include "ceres/parameter_block.h" -#include "ceres/stringprintf.h" +#include "ceres/array_utils.h" #include "ceres/internal/eigen.h" #include "ceres/internal/port.h" - -#ifdef _MSC_VER -# define isfinite _finite -#endif +#include "ceres/parameter_block.h" +#include "ceres/residual_block.h" +#include "ceres/stringprintf.h" +#include "glog/logging.h" namespace ceres { namespace internal { -// It is a near impossibility that user code generates this exact -// value in normal operation, thus we will use it to fill arrays -// before passing them to user code. If on return an element of the -// array still contains this value, we will assume that the user code -// did not write to that memory location. -static const double kImpossibleValue = 1e302; - -bool IsArrayValid(const int size, const double* x) { - if (x != NULL) { - for (int i = 0; i < size; ++i) { - if (!isfinite(x[i]) || (x[i] == kImpossibleValue)) { - return false; - } - } - } - return true; -} - -void InvalidateArray(const int size, double* x) { - if (x != NULL) { - for (int i = 0; i < size; ++i) { - x[i] = kImpossibleValue; - } - } -} - void InvalidateEvaluation(const ResidualBlock& block, double* cost, double* residuals, @@ -92,7 +63,7 @@ void InvalidateEvaluation(const ResidualBlock& block, // Utility routine to print an array of doubles to a string. If the // array pointer is NULL, it is treated as an array of zeros. -void AppendArrayToString(const int size, const double* x, string* result) { +static void AppendArrayToString(const int size, const double* x, string* result) { for (int i = 0; i < size; ++i) { if (x == NULL) { StringAppendF(result, "Not Computed "); diff --git a/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.h b/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.h index 228867cc60c..7051c2112fd 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.h +++ b/extern/libmv/third_party/ceres/internal/ceres/residual_block_utils.h @@ -51,15 +51,6 @@ namespace internal { class ResidualBlock; -// Fill the array x with an impossible value that the user code is -// never expected to compute. -void InvalidateArray(int size, double* x); - -// Check if all the entries of the array x are valid, i.e. all the -// values in the array should be finite and none of them should be -// equal to the "impossible" value used by InvalidateArray. -bool IsArrayValid(int size, const double* x); - // Invalidate cost, resdual and jacobian arrays (if not NULL). void InvalidateEvaluation(const ResidualBlock& block, double* cost, diff --git a/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc b/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc index ac6d8aa279a..7af275c1dd8 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/runtime_numeric_diff_cost_function.cc @@ -35,11 +35,10 @@ #include #include #include - -#include #include "Eigen/Dense" #include "ceres/cost_function.h" #include "ceres/internal/scoped_ptr.h" +#include "glog/logging.h" namespace ceres { namespace internal { diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc index 2bc8cdd6bec..2cbe78d133a 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.cc @@ -32,7 +32,13 @@ #include #include #include + +#ifndef CERES_NO_CXSPARSE +#include "cs.h" +#endif // CERES_NO_CXSPARSE + #include "Eigen/Dense" +#include "glog/logging.h" #include "ceres/block_random_access_dense_matrix.h" #include "ceres/block_random_access_matrix.h" #include "ceres/block_random_access_sparse_matrix.h" @@ -48,6 +54,7 @@ #include "ceres/internal/scoped_ptr.h" #include "ceres/types.h" + namespace ceres { namespace internal { @@ -57,7 +64,7 @@ LinearSolver::Summary SchurComplementSolver::SolveImpl( const LinearSolver::PerSolveOptions& per_solve_options, double* x) { const time_t start_time = time(NULL); - if (!options_.constant_sparsity || (eliminator_.get() == NULL)) { + if (eliminator_.get() == NULL) { InitStorage(A->block_structure()); DetectStructure(*A->block_structure(), options_.num_eliminate_blocks, @@ -88,11 +95,11 @@ LinearSolver::Summary SchurComplementSolver::SolveImpl( const time_t backsubstitute_time = time(NULL); summary.termination_type = TOLERANCE; - VLOG(2) << "time (sec) total: " << backsubstitute_time - start_time - << " init: " << init_time - start_time - << " eliminate: " << eliminate_time - init_time - << " solve: " << solve_time - eliminate_time - << " backsubstitute: " << backsubstitute_time - solve_time; + VLOG(2) << "time (sec) total: " << (backsubstitute_time - start_time) + << " init: " << (init_time - start_time) + << " eliminate: " << (eliminate_time - init_time) + << " solve: " << (solve_time - eliminate_time) + << " backsubstitute: " << (backsubstitute_time - solve_time); return summary; } @@ -139,18 +146,33 @@ bool DenseSchurComplementSolver::SolveReducedLinearSystem(double* solution) { return true; } -#ifndef CERES_NO_SUITESPARSE + SparseSchurComplementSolver::SparseSchurComplementSolver( const LinearSolver::Options& options) - : SchurComplementSolver(options), - symbolic_factor_(NULL) { + : SchurComplementSolver(options) { +#ifndef CERES_NO_SUITESPARSE + factor_ = NULL; +#endif // CERES_NO_SUITESPARSE + +#ifndef CERES_NO_CXSPARSE + cxsparse_factor_ = NULL; +#endif // CERES_NO_CXSPARSE } SparseSchurComplementSolver::~SparseSchurComplementSolver() { - if (symbolic_factor_ != NULL) { - ss_.Free(symbolic_factor_); - symbolic_factor_ = NULL; +#ifndef CERES_NO_SUITESPARSE + if (factor_ != NULL) { + ss_.Free(factor_); + factor_ = NULL; } +#endif // CERES_NO_SUITESPARSE + +#ifndef CERES_NO_CXSPARSE + if (cxsparse_factor_ != NULL) { + cxsparse_.Free(cxsparse_factor_); + cxsparse_factor_ = NULL; + } +#endif // CERES_NO_CXSPARSE } // Determine the non-zero blocks in the Schur Complement matrix, and @@ -161,13 +183,13 @@ void SparseSchurComplementSolver::InitStorage( const int num_col_blocks = bs->cols.size(); const int num_row_blocks = bs->rows.size(); - vector blocks(num_col_blocks - num_eliminate_blocks, 0); + blocks_.resize(num_col_blocks - num_eliminate_blocks, 0); for (int i = num_eliminate_blocks; i < num_col_blocks; ++i) { - blocks[i - num_eliminate_blocks] = bs->cols[i].size; + blocks_[i - num_eliminate_blocks] = bs->cols[i].size; } set > block_pairs; - for (int i = 0; i < blocks.size(); ++i) { + for (int i = 0; i < blocks_.size(); ++i) { block_pairs.insert(make_pair(i, i)); } @@ -220,15 +242,34 @@ void SparseSchurComplementSolver::InitStorage( } } - set_lhs(new BlockRandomAccessSparseMatrix(blocks, block_pairs)); + set_lhs(new BlockRandomAccessSparseMatrix(blocks_, block_pairs)); set_rhs(new double[lhs()->num_rows()]); } +bool SparseSchurComplementSolver::SolveReducedLinearSystem(double* solution) { + switch (options().sparse_linear_algebra_library) { + case SUITE_SPARSE: + return SolveReducedLinearSystemUsingSuiteSparse(solution); + case CX_SPARSE: + return SolveReducedLinearSystemUsingCXSparse(solution); + default: + LOG(FATAL) << "Unknown sparse linear algebra library : " + << options().sparse_linear_algebra_library; + } + + LOG(FATAL) << "Unknown sparse linear algebra library : " + << options().sparse_linear_algebra_library; + return false; +} + +#ifndef CERES_NO_SUITESPARSE // Solve the system Sx = r, assuming that the matrix S is stored in a // BlockRandomAccessSparseMatrix. The linear system is solved using // CHOLMOD's sparse cholesky factorization routines. -bool SparseSchurComplementSolver::SolveReducedLinearSystem(double* solution) { - // Extract the TripletSparseMatrix that is used for actually storing S. +bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse( + double* solution) { + const time_t start_time = time(NULL); + TripletSparseMatrix* tsm = const_cast( down_cast(lhs())->matrix()); @@ -245,30 +286,38 @@ bool SparseSchurComplementSolver::SolveReducedLinearSystem(double* solution) { // The matrix is symmetric, and the upper triangular part of the // matrix contains the values. cholmod_lhs->stype = 1; + const time_t lhs_time = time(NULL); cholmod_dense* cholmod_rhs = ss_.CreateDenseVector(const_cast(rhs()), num_rows, num_rows); + const time_t rhs_time = time(NULL); // Symbolic factorization is computed if we don't already have one handy. - if (symbolic_factor_ == NULL) { - symbolic_factor_ = ss_.AnalyzeCholesky(cholmod_lhs); + if (factor_ == NULL) { + if (options().use_block_amd) { + factor_ = ss_.BlockAnalyzeCholesky(cholmod_lhs, blocks_, blocks_); + } else { + factor_ = ss_.AnalyzeCholesky(cholmod_lhs); + } + + if (VLOG_IS_ON(2)) { + cholmod_print_common("Symbolic Analysis", ss_.mutable_cc()); + } } + CHECK_NOTNULL(factor_); + + const time_t symbolic_time = time(NULL); cholmod_dense* cholmod_solution = - ss_.SolveCholesky(cholmod_lhs, symbolic_factor_, cholmod_rhs); + ss_.SolveCholesky(cholmod_lhs, factor_, cholmod_rhs); + + const time_t solve_time = time(NULL); ss_.Free(cholmod_lhs); cholmod_lhs = NULL; ss_.Free(cholmod_rhs); cholmod_rhs = NULL; - // If sparsity is not constant across calls, then reset the symbolic - // factorization. - if (!options().constant_sparsity) { - ss_.Free(symbolic_factor_); - symbolic_factor_ = NULL; - } - if (cholmod_solution == NULL) { LOG(ERROR) << "CHOLMOD solve failed."; return false; @@ -277,9 +326,63 @@ bool SparseSchurComplementSolver::SolveReducedLinearSystem(double* solution) { VectorRef(solution, num_rows) = VectorRef(static_cast(cholmod_solution->x), num_rows); ss_.Free(cholmod_solution); + const time_t final_time = time(NULL); + VLOG(2) << "time: " << (final_time - start_time) + << " lhs : " << (lhs_time - start_time) + << " rhs: " << (rhs_time - lhs_time) + << " analyze: " << (symbolic_time - rhs_time) + << " factor_and_solve: " << (solve_time - symbolic_time) + << " cleanup: " << (final_time - solve_time); return true; } +#else +bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingSuiteSparse( + double* solution) { + LOG(FATAL) << "No SuiteSparse support in Ceres."; + return false; +} #endif // CERES_NO_SUITESPARSE +#ifndef CERES_NO_CXSPARSE +// Solve the system Sx = r, assuming that the matrix S is stored in a +// BlockRandomAccessSparseMatrix. The linear system is solved using +// CXSparse's sparse cholesky factorization routines. +bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingCXSparse( + double* solution) { + // Extract the TripletSparseMatrix that is used for actually storing S. + TripletSparseMatrix* tsm = + const_cast( + down_cast(lhs())->matrix()); + + const int num_rows = tsm->num_rows(); + + // The case where there are no f blocks, and the system is block + // diagonal. + if (num_rows == 0) { + return true; + } + + cs_di* lhs = CHECK_NOTNULL(cxsparse_.CreateSparseMatrix(tsm)); + VectorRef(solution, num_rows) = ConstVectorRef(rhs(), num_rows); + + // Compute symbolic factorization if not available. + if (cxsparse_factor_ == NULL) { + cxsparse_factor_ = CHECK_NOTNULL(cxsparse_.AnalyzeCholesky(lhs)); + } + + // Solve the linear system. + bool ok = cxsparse_.SolveCholesky(lhs, cxsparse_factor_, solution); + + cxsparse_.Free(lhs); + return ok; +} +#else +bool SparseSchurComplementSolver::SolveReducedLinearSystemUsingCXSparse( + double* solution) { + LOG(FATAL) << "No CXSparse support in Ceres."; + return false; +} +#endif // CERES_NO_CXPARSE + } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h index 039bc09e3ce..ea1b3184c33 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_complement_solver.h @@ -31,9 +31,13 @@ #ifndef CERES_INTERNAL_SCHUR_COMPLEMENT_SOLVER_H_ #define CERES_INTERNAL_SCHUR_COMPLEMENT_SOLVER_H_ +#include +#include + #include "ceres/block_random_access_matrix.h" #include "ceres/block_sparse_matrix.h" #include "ceres/block_structure.h" +#include "ceres/cxsparse.h" #include "ceres/linear_solver.h" #include "ceres/schur_eliminator.h" #include "ceres/suitesparse.h" @@ -128,7 +132,7 @@ class SchurComplementSolver : public BlockSparseMatrixBaseSolver { scoped_ptr lhs_; scoped_array rhs_; - DISALLOW_COPY_AND_ASSIGN(SchurComplementSolver); + CERES_DISALLOW_COPY_AND_ASSIGN(SchurComplementSolver); }; // Dense Cholesky factorization based solver. @@ -142,10 +146,10 @@ class DenseSchurComplementSolver : public SchurComplementSolver { virtual void InitStorage(const CompressedRowBlockStructure* bs); virtual bool SolveReducedLinearSystem(double* solution); - DISALLOW_COPY_AND_ASSIGN(DenseSchurComplementSolver); + CERES_DISALLOW_COPY_AND_ASSIGN(DenseSchurComplementSolver); }; -#ifndef CERES_NO_SUITESPARSE + // Sparse Cholesky factorization based solver. class SparseSchurComplementSolver : public SchurComplementSolver { public: @@ -155,27 +159,27 @@ class SparseSchurComplementSolver : public SchurComplementSolver { private: virtual void InitStorage(const CompressedRowBlockStructure* bs); virtual bool SolveReducedLinearSystem(double* solution); + bool SolveReducedLinearSystemUsingSuiteSparse(double* solution); + bool SolveReducedLinearSystemUsingCXSparse(double* solution); + // Size of the blocks in the Schur complement. + vector blocks_; +#ifndef CERES_NO_SUITESPARSE SuiteSparse ss_; // Symbolic factorization of the reduced linear system. Precomputed - // once and reused if constant_sparsity_ is true. - cholmod_factor* symbolic_factor_; - DISALLOW_COPY_AND_ASSIGN(SparseSchurComplementSolver); -}; -#else // CERES_NO_SUITESPARSE -class SparseSchurComplementSolver : public SchurComplementSolver { - public: - explicit SparseSchurComplementSolver(const LinearSolver::Options& options) - : SchurComplementSolver(options) { - LOG(FATAL) << "SPARSE_SCHUR is not available. Please " - "build Ceres with SuiteSparse."; - } - - virtual ~SparseSchurComplementSolver() {} -}; + // once and reused in subsequent calls. + cholmod_factor* factor_; #endif // CERES_NO_SUITESPARSE +#ifndef CERES_NO_CXSPARSE + CXSparse cxsparse_; + // Cached factorization + cs_dis* cxsparse_factor_; +#endif // CERES_NO_CXSPARSE + CERES_DISALLOW_COPY_AND_ASSIGN(SparseSchurComplementSolver); +}; + } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h index a388d005424..6120db9b009 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_eliminator_impl.h @@ -188,7 +188,7 @@ Eliminate(const BlockSparseMatrixBase* A, typename EigenTypes::ConstVectorRef diag(D + bs->cols[i].position, block_size); - MutexLock l(&cell_info->m); + CeresMutexLock l(&cell_info->m); MatrixRef m(cell_info->values, row_stride, col_stride); m.block(r, c, block_size, block_size).diagonal() += diag.array().square().matrix(); @@ -387,7 +387,7 @@ UpdateRhs(const Chunk& chunk, row.block.size, block_size); const int block = block_id - num_eliminate_blocks_; - MutexLock l(rhs_locks_[block]); + CeresMutexLock l(rhs_locks_[block]); typename EigenTypes::VectorRef (rhs + lhs_row_layout_[block], block_size).noalias() += b.transpose() * sj; @@ -523,7 +523,7 @@ ChunkOuterProduct(const CompressedRowBlockStructure* bs, const typename EigenTypes::ConstMatrixRef b2(buffer + it2->second, e_block_size, block2_size); - MutexLock l(&cell_info->m); + CeresMutexLock l(&cell_info->m); MatrixRef m(cell_info->values, row_stride, col_stride); // We explicitly construct a block object here instead of using @@ -532,7 +532,29 @@ ChunkOuterProduct(const CompressedRowBlockStructure* bs, // like the Matrix class does. Eigen::Block block(m, r, c, block1_size, block2_size); - block.noalias() -= b1_transpose_inverse_ete * b2; +#ifdef CERES_WORK_AROUND_ANDROID_NDK_COMPILER_BUG + // Removing the ".noalias()" annotation on the following statement is + // necessary to produce a correct build with the Android NDK, including + // versions 6, 7, 8, and 8b, when built with STLPort and the + // non-standalone toolchain (i.e. ndk-build). This appears to be a + // compiler bug; if the workaround is not in place, the line + // + // block.noalias() -= b1_transpose_inverse_ete * b2; + // + // gets compiled to + // + // block.noalias() += b1_transpose_inverse_ete * b2; + // + // which breaks schur elimination. Introducing a temporary by removing the + // .noalias() annotation causes the issue to disappear. Tracking this + // issue down was tricky, since the test suite doesn't run when built with + // the non-standalone toolchain. + // + // TODO(keir): Make a reproduction case for this and send it upstream. + block -= b1_transpose_inverse_ete * b2; +#else + block.noalias() -= b1_transpose_inverse_ete * b2; +#endif // CERES_WORK_AROUND_ANDROID_NDK_COMPILER_BUG } } } @@ -601,7 +623,7 @@ NoEBlockRowOuterProduct(const BlockSparseMatrixBase* A, &r, &c, &row_stride, &col_stride); if (cell_info != NULL) { - MutexLock l(&cell_info->m); + CeresMutexLock l(&cell_info->m); MatrixRef m(cell_info->values, row_stride, col_stride); m.block(r, c, block1_size, block1_size) .selfadjointView() @@ -621,7 +643,7 @@ NoEBlockRowOuterProduct(const BlockSparseMatrixBase* A, } const int block2_size = bs->cols[row.cells[j].block_id].size; - MutexLock l(&cell_info->m); + CeresMutexLock l(&cell_info->m); MatrixRef m(cell_info->values, row_stride, col_stride); m.block(r, c, block1_size, block2_size).noalias() += b1.transpose() * ConstMatrixRef(row_values + row.cells[j].position, @@ -660,7 +682,7 @@ EBlockRowOuterProduct(const BlockSparseMatrixBase* A, continue; } - MutexLock l(&cell_info->m); + CeresMutexLock l(&cell_info->m); MatrixRef m(cell_info->values, row_stride, col_stride); Eigen::Block @@ -687,7 +709,7 @@ EBlockRowOuterProduct(const BlockSparseMatrixBase* A, row.block.size, block2_size); - MutexLock l(&cell_info->m); + CeresMutexLock l(&cell_info->m); MatrixRef m(cell_info->values, row_stride, col_stride); Eigen::Block block(m, r, c, block1_size, block2_size); diff --git a/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc b/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc index c4fc1da3c2f..1cdff4e6dec 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/schur_ordering.cc @@ -30,25 +30,14 @@ #include "ceres/schur_ordering.h" -#include #include "ceres/graph.h" #include "ceres/graph_algorithms.h" +#include "ceres/internal/scoped_ptr.h" #include "ceres/map_util.h" #include "ceres/parameter_block.h" #include "ceres/program.h" #include "ceres/residual_block.h" -#include "ceres/internal/scoped_ptr.h" - -CERES_HASH_NAMESPACE_START - -// Allow us to hash pointers as if they were int's -template<> struct hash< ::ceres::internal::ParameterBlock*> { - size_t operator()(::ceres::internal::ParameterBlock* x) const { - return reinterpret_cast(x); - } -}; - -CERES_HASH_NAMESPACE_END +#include "glog/logging.h" namespace ceres { namespace internal { @@ -59,8 +48,7 @@ int ComputeSchurOrdering(const Program& program, scoped_ptr > graph( CHECK_NOTNULL(CreateHessianGraph(program))); - int independent_set_size = - IndependentSetOrdering(*graph, ordering); + int independent_set_size = IndependentSetOrdering(*graph, ordering); const vector& parameter_blocks = program.parameter_blocks(); // Add the excluded blocks to back of the ordering vector. diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver.cc b/extern/libmv/third_party/ceres/internal/ceres/solver.cc index 77f04d1d918..66ca93283a1 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/solver.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/solver.cc @@ -32,36 +32,32 @@ #include "ceres/solver.h" #include -#include "ceres/levenberg_marquardt.h" +#include "ceres/problem.h" +#include "ceres/problem_impl.h" #include "ceres/program.h" #include "ceres/solver_impl.h" #include "ceres/stringprintf.h" -#include "ceres/problem.h" namespace ceres { Solver::~Solver() {} -// TODO(sameeragarwal): The timing code here should use a sub-second -// timer. +// TODO(sameeragarwal): Use subsecond timers. void Solver::Solve(const Solver::Options& options, Problem* problem, Solver::Summary* summary) { time_t start_time_seconds = time(NULL); - internal::SolverImpl::Solve(options, problem, summary); + internal::ProblemImpl* problem_impl = + CHECK_NOTNULL(problem)->problem_impl_.get(); + internal::SolverImpl::Solve(options, problem_impl, summary); summary->total_time_in_seconds = time(NULL) - start_time_seconds; - summary->preprocessor_time_in_seconds = - summary->total_time_in_seconds - summary->minimizer_time_in_seconds; } void Solve(const Solver::Options& options, Problem* problem, Solver::Summary* summary) { - time_t start_time_seconds = time(NULL); - internal::SolverImpl::Solve(options, problem, summary); - summary->total_time_in_seconds = time(NULL) - start_time_seconds; - summary->preprocessor_time_in_seconds = - summary->total_time_in_seconds - summary->minimizer_time_in_seconds; + Solver solver; + solver.Solve(options, problem, summary); } Solver::Summary::Summary() @@ -75,6 +71,7 @@ Solver::Summary::Summary() num_unsuccessful_steps(-1), preprocessor_time_in_seconds(-1.0), minimizer_time_in_seconds(-1.0), + postprocessor_time_in_seconds(-1.0), total_time_in_seconds(-1.0), num_parameter_blocks(-1), num_parameters(-1), @@ -93,7 +90,9 @@ Solver::Summary::Summary() linear_solver_type_given(SPARSE_NORMAL_CHOLESKY), linear_solver_type_used(SPARSE_NORMAL_CHOLESKY), preconditioner_type(IDENTITY), - ordering_type(NATURAL) { + ordering_type(NATURAL), + trust_region_strategy_type(LEVENBERG_MARQUARDT), + sparse_linear_algebra_library(SUITE_SPARSE) { } string Solver::Summary::BriefReport() const { @@ -136,7 +135,7 @@ string Solver::Summary::FullReport() const { num_parameters); internal::StringAppendF(&report, "Residual blocks % 10d\n", num_residual_blocks); - internal::StringAppendF(&report, "Residual % 10d\n\n", + internal::StringAppendF(&report, "Residuals % 10d\n\n", num_residuals); } else { internal::StringAppendF(&report, "%45s %21s\n", "Original", "Reduced"); @@ -183,10 +182,33 @@ string Solver::Summary::FullReport() const { internal::StringAppendF(&report, "Threads: % 25d% 25d\n", num_threads_given, num_threads_used); - internal::StringAppendF(&report, "Linear Solver Threads:% 23d% 25d\n", + internal::StringAppendF(&report, "Linear solver threads % 23d% 25d\n", num_linear_solver_threads_given, num_linear_solver_threads_used); + if (linear_solver_type_used == SPARSE_NORMAL_CHOLESKY || + linear_solver_type_used == SPARSE_SCHUR || + (linear_solver_type_used == ITERATIVE_SCHUR && + (preconditioner_type == SCHUR_JACOBI || + preconditioner_type == CLUSTER_JACOBI || + preconditioner_type == CLUSTER_TRIDIAGONAL))) { + internal::StringAppendF(&report, "\nSparse Linear Algebra Library %15s\n", + SparseLinearAlgebraLibraryTypeToString( + sparse_linear_algebra_library)); + } + + internal::StringAppendF(&report, "Trust Region Strategy %19s", + TrustRegionStrategyTypeToString( + trust_region_strategy_type)); + if (trust_region_strategy_type == DOGLEG) { + if (dogleg_type == TRADITIONAL_DOGLEG) { + internal::StringAppendF(&report, " (TRADITIONAL)"); + } else { + internal::StringAppendF(&report, " (SUBSPACE)"); + } + } + internal::StringAppendF(&report, "\n"); + if (termination_type == DID_NOT_RUN) { CHECK(!error.empty()) diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc index ed07d9dc6d7..8ef5b98e35f 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc @@ -30,40 +30,29 @@ #include "ceres/solver_impl.h" +#include #include // NOLINT #include #include "ceres/evaluator.h" #include "ceres/gradient_checking_cost_function.h" -#include "ceres/levenberg_marquardt.h" +#include "ceres/iteration_callback.h" +#include "ceres/levenberg_marquardt_strategy.h" #include "ceres/linear_solver.h" #include "ceres/map_util.h" #include "ceres/minimizer.h" #include "ceres/parameter_block.h" +#include "ceres/problem.h" #include "ceres/problem_impl.h" #include "ceres/program.h" #include "ceres/residual_block.h" #include "ceres/schur_ordering.h" #include "ceres/stringprintf.h" -#include "ceres/iteration_callback.h" -#include "ceres/problem.h" +#include "ceres/trust_region_minimizer.h" namespace ceres { namespace internal { namespace { -void EvaluateCostAndResiduals(ProblemImpl* problem_impl, - double* cost, - vector* residuals) { - CHECK_NOTNULL(cost); - Program* program = CHECK_NOTNULL(problem_impl)->mutable_program(); - if (residuals != NULL) { - residuals->resize(program->NumResiduals()); - program->Evaluate(cost, &(*residuals)[0]); - } else { - program->Evaluate(cost, NULL); - } -} - // Callback for updating the user's parameter blocks. Updates are only // done if the step is successful. class StateUpdatingCallback : public IterationCallback { @@ -96,7 +85,7 @@ class LoggingCallback : public IterationCallback { CallbackReturnType operator()(const IterationSummary& summary) { const char* kReportRowFormat = "% 4d: f:% 8e d:% 3.2e g:% 3.2e h:% 3.2e " - "rho:% 3.2e mu:% 3.2e li:% 3d"; + "rho:% 3.2e mu:% 3.2e li:% 3d it:% 3.2e tt:% 3.2e"; string output = StringPrintf(kReportRowFormat, summary.iteration, summary.cost, @@ -104,8 +93,10 @@ class LoggingCallback : public IterationCallback { summary.gradient_max_norm, summary.step_norm, summary.relative_decrease, - summary.mu, - summary.linear_solver_iterations); + summary.trust_region_radius, + summary.linear_solver_iterations, + summary.iteration_time_in_seconds, + summary.cumulative_time_in_seconds); if (log_to_stdout_) { cout << output << endl; } else { @@ -118,44 +109,101 @@ class LoggingCallback : public IterationCallback { const bool log_to_stdout_; }; +// Basic callback to record the execution of the solver to a file for +// offline analysis. +class FileLoggingCallback : public IterationCallback { + public: + explicit FileLoggingCallback(const string& filename) + : fptr_(NULL) { + fptr_ = fopen(filename.c_str(), "w"); + CHECK_NOTNULL(fptr_); + } + + virtual ~FileLoggingCallback() { + if (fptr_ != NULL) { + fclose(fptr_); + } + } + + virtual CallbackReturnType operator()(const IterationSummary& summary) { + fprintf(fptr_, + "%4d %e %e\n", + summary.iteration, + summary.cost, + summary.cumulative_time_in_seconds); + return SOLVER_CONTINUE; + } + private: + FILE* fptr_; +}; + } // namespace void SolverImpl::Minimize(const Solver::Options& options, Program* program, Evaluator* evaluator, LinearSolver* linear_solver, - double* initial_parameters, - double* final_parameters, + double* parameters, Solver::Summary* summary) { Minimizer::Options minimizer_options(options); + // TODO(sameeragarwal): Add support for logging the configuration + // and more detailed stats. + scoped_ptr file_logging_callback; + if (!options.solver_log.empty()) { + file_logging_callback.reset(new FileLoggingCallback(options.solver_log)); + minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(), + file_logging_callback.get()); + } + LoggingCallback logging_callback(options.minimizer_progress_to_stdout); if (options.logging_type != SILENT) { - minimizer_options.callbacks.push_back(&logging_callback); + minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(), + &logging_callback); } - StateUpdatingCallback updating_callback(program, initial_parameters); + StateUpdatingCallback updating_callback(program, parameters); if (options.update_state_every_iteration) { - minimizer_options.callbacks.push_back(&updating_callback); + // This must get pushed to the front of the callbacks so that it is run + // before any of the user callbacks. + minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(), + &updating_callback); } - LevenbergMarquardt levenberg_marquardt; + minimizer_options.evaluator = evaluator; + scoped_ptr jacobian(evaluator->CreateJacobian()); + minimizer_options.jacobian = jacobian.get(); - time_t start_minimizer_time_seconds = time(NULL); - levenberg_marquardt.Minimize(minimizer_options, - evaluator, - linear_solver, - initial_parameters, - final_parameters, - summary); - summary->minimizer_time_in_seconds = - time(NULL) - start_minimizer_time_seconds; + TrustRegionStrategy::Options trust_region_strategy_options; + trust_region_strategy_options.linear_solver = linear_solver; + trust_region_strategy_options.initial_radius = + options.initial_trust_region_radius; + trust_region_strategy_options.max_radius = options.max_trust_region_radius; + trust_region_strategy_options.lm_min_diagonal = options.lm_min_diagonal; + trust_region_strategy_options.lm_max_diagonal = options.lm_max_diagonal; + trust_region_strategy_options.trust_region_strategy_type = + options.trust_region_strategy_type; + trust_region_strategy_options.dogleg_type = options.dogleg_type; + scoped_ptr strategy( + TrustRegionStrategy::Create(trust_region_strategy_options)); + minimizer_options.trust_region_strategy = strategy.get(); + + TrustRegionMinimizer minimizer; + time_t minimizer_start_time = time(NULL); + minimizer.Minimize(minimizer_options, parameters, summary); + summary->minimizer_time_in_seconds = time(NULL) - minimizer_start_time; } void SolverImpl::Solve(const Solver::Options& original_options, - Problem* problem, + ProblemImpl* original_problem_impl, Solver::Summary* summary) { + time_t solver_start_time = time(NULL); Solver::Options options(original_options); + Program* original_program = original_problem_impl->mutable_program(); + ProblemImpl* problem_impl = original_problem_impl; + // Reset the summary object to its default values. + *CHECK_NOTNULL(summary) = Solver::Summary(); + #ifndef CERES_USE_OPENMP if (options.num_threads > 1) { @@ -174,8 +222,6 @@ void SolverImpl::Solve(const Solver::Options& original_options, } #endif - // Reset the summary object to its default values; - *CHECK_NOTNULL(summary) = Solver::Summary(); summary->linear_solver_type_given = options.linear_solver_type; summary->num_eliminate_blocks_given = original_options.num_eliminate_blocks; summary->num_threads_given = original_options.num_threads; @@ -183,32 +229,38 @@ void SolverImpl::Solve(const Solver::Options& original_options, original_options.num_linear_solver_threads; summary->ordering_type = original_options.ordering_type; - ProblemImpl* problem_impl = CHECK_NOTNULL(problem)->problem_impl_.get(); - summary->num_parameter_blocks = problem_impl->NumParameterBlocks(); summary->num_parameters = problem_impl->NumParameters(); summary->num_residual_blocks = problem_impl->NumResidualBlocks(); summary->num_residuals = problem_impl->NumResiduals(); summary->num_threads_used = options.num_threads; + summary->sparse_linear_algebra_library = + options.sparse_linear_algebra_library; + summary->trust_region_strategy_type = options.trust_region_strategy_type; + summary->dogleg_type = options.dogleg_type; - // Evaluate the initial cost and residual vector (if needed). The - // initial cost needs to be computed on the original unpreprocessed - // problem, as it is used to determine the value of the "fixed" part - // of the objective function after the problem has undergone - // reduction. Also the initial residuals are in the order in which - // the user added the ResidualBlocks to the optimization problem. - EvaluateCostAndResiduals(problem_impl, - &summary->initial_cost, - options.return_initial_residuals - ? &summary->initial_residuals - : NULL); + // Evaluate the initial cost, residual vector and the jacobian + // matrix if requested by the user. The initial cost needs to be + // computed on the original unpreprocessed problem, as it is used to + // determine the value of the "fixed" part of the objective function + // after the problem has undergone reduction. + Evaluator::Evaluate( + original_program, + options.num_threads, + &(summary->initial_cost), + options.return_initial_residuals ? &summary->initial_residuals : NULL, + options.return_initial_gradient ? &summary->initial_gradient : NULL, + options.return_initial_jacobian ? &summary->initial_jacobian : NULL); + original_program->SetParameterBlockStatePtrsToUserStatePtrs(); // If the user requests gradient checking, construct a new // ProblemImpl by wrapping the CostFunctions of problem_impl inside // GradientCheckingCostFunction and replacing problem_impl with // gradient_checking_problem_impl. scoped_ptr gradient_checking_problem_impl; + // Save the original problem impl so we don't use the gradient + // checking one when computing the residuals. if (options.check_gradients) { VLOG(1) << "Checking Gradients"; gradient_checking_problem_impl.reset( @@ -224,8 +276,10 @@ void SolverImpl::Solve(const Solver::Options& original_options, // Create the three objects needed to minimize: the transformed program, the // evaluator, and the linear solver. - scoped_ptr reduced_program( - CreateReducedProgram(&options, problem_impl, &summary->error)); + scoped_ptr reduced_program(CreateReducedProgram(&options, + problem_impl, + &summary->fixed_cost, + &summary->error)); if (reduced_program == NULL) { return; } @@ -259,19 +313,21 @@ void SolverImpl::Solve(const Solver::Options& original_options, } // The optimizer works on contiguous parameter vectors; allocate some. - Vector initial_parameters(reduced_program->NumParameters()); - Vector optimized_parameters(reduced_program->NumParameters()); + Vector parameters(reduced_program->NumParameters()); // Collect the discontiguous parameters into a contiguous state vector. - reduced_program->ParameterBlocksToStateVector(&initial_parameters[0]); + reduced_program->ParameterBlocksToStateVector(parameters.data()); + + time_t minimizer_start_time = time(NULL); + summary->preprocessor_time_in_seconds = + minimizer_start_time - solver_start_time; // Run the optimization. Minimize(options, reduced_program.get(), evaluator.get(), linear_solver.get(), - initial_parameters.data(), - optimized_parameters.data(), + parameters.data(), summary); // If the user aborted mid-optimization or the optimization @@ -282,30 +338,45 @@ void SolverImpl::Solve(const Solver::Options& original_options, return; } + time_t post_process_start_time = time(NULL); + // Push the contiguous optimized parameters back to the user's parameters. - reduced_program->StateVectorToParameterBlocks(&optimized_parameters[0]); + reduced_program->StateVectorToParameterBlocks(parameters.data()); reduced_program->CopyParameterBlockStateToUserState(); - // Return the final cost and residuals for the original problem. - EvaluateCostAndResiduals(problem->problem_impl_.get(), - &summary->final_cost, - options.return_final_residuals - ? &summary->final_residuals - : NULL); + // Evaluate the final cost, residual vector and the jacobian + // matrix if requested by the user. + Evaluator::Evaluate( + original_program, + options.num_threads, + &summary->final_cost, + options.return_final_residuals ? &summary->final_residuals : NULL, + options.return_final_gradient ? &summary->final_gradient : NULL, + options.return_final_jacobian ? &summary->final_jacobian : NULL); + // Ensure the program state is set to the user parameters on the way out. + original_program->SetParameterBlockStatePtrsToUserStatePtrs(); // Stick a fork in it, we're done. - return; + summary->postprocessor_time_in_seconds = time(NULL) - post_process_start_time; } // Strips varying parameters and residuals, maintaining order, and updating // num_eliminate_blocks. bool SolverImpl::RemoveFixedBlocksFromProgram(Program* program, int* num_eliminate_blocks, + double* fixed_cost, string* error) { int original_num_eliminate_blocks = *num_eliminate_blocks; vector* parameter_blocks = program->mutable_parameter_blocks(); + scoped_array residual_block_evaluate_scratch; + if (fixed_cost != NULL) { + residual_block_evaluate_scratch.reset( + new double[program->MaxScratchDoublesNeededForEvaluate()]); + *fixed_cost = 0.0; + } + // Mark all the parameters as unused. Abuse the index member of the parameter // blocks for the marking. for (int i = 0; i < parameter_blocks->size(); ++i) { @@ -335,6 +406,17 @@ bool SolverImpl::RemoveFixedBlocksFromProgram(Program* program, if (!all_constant) { (*residual_blocks)[j++] = (*residual_blocks)[i]; + } else if (fixed_cost != NULL) { + // The residual is constant and will be removed, so its cost is + // added to the variable fixed_cost. + double cost = 0.0; + if (!residual_block->Evaluate( + &cost, NULL, NULL, residual_block_evaluate_scratch.get())) { + *error = StringPrintf("Evaluation of the residual %d failed during " + "removal of fixed residual blocks.", i); + return false; + } + *fixed_cost += cost; } } residual_blocks->resize(j); @@ -367,6 +449,7 @@ bool SolverImpl::RemoveFixedBlocksFromProgram(Program* program, Program* SolverImpl::CreateReducedProgram(Solver::Options* options, ProblemImpl* problem_impl, + double* fixed_cost, string* error) { Program* original_program = problem_impl->mutable_program(); scoped_ptr transformed_program(new Program(*original_program)); @@ -397,6 +480,7 @@ Program* SolverImpl::CreateReducedProgram(Solver::Options* options, if (!RemoveFixedBlocksFromProgram(transformed_program.get(), &num_eliminate_blocks, + fixed_cost, error)) { return NULL; } @@ -431,13 +515,34 @@ Program* SolverImpl::CreateReducedProgram(Solver::Options* options, LinearSolver* SolverImpl::CreateLinearSolver(Solver::Options* options, string* error) { + if (options->trust_region_strategy_type == DOGLEG) { + if (options->linear_solver_type == ITERATIVE_SCHUR || + options->linear_solver_type == CGNR) { + *error = "DOGLEG only supports exact factorization based linear " + "solvers. If you want to use an iterative solver please " + "use LEVENBERG_MARQUARDT as the trust_region_strategy_type"; + return NULL; + } + } + #ifdef CERES_NO_SUITESPARSE - if (options->linear_solver_type == SPARSE_NORMAL_CHOLESKY) { - *error = "Can't use SPARSE_NORMAL_CHOLESKY because SuiteSparse was not " - "enabled when Ceres was built."; + if (options->linear_solver_type == SPARSE_NORMAL_CHOLESKY && + options->sparse_linear_algebra_library == SUITE_SPARSE) { + *error = "Can't use SPARSE_NORMAL_CHOLESKY with SUITESPARSE because " + "SuiteSparse was not enabled when Ceres was built."; return NULL; } -#endif // CERES_NO_SUITESPARSE +#endif + +#ifdef CERES_NO_CXSPARSE + if (options->linear_solver_type == SPARSE_NORMAL_CHOLESKY && + options->sparse_linear_algebra_library == CX_SPARSE) { + *error = "Can't use SPARSE_NORMAL_CHOLESKY with CXSPARSE because " + "CXSparse was not enabled when Ceres was built."; + return NULL; + } +#endif + if (options->linear_solver_max_num_iterations <= 0) { *error = "Solver::Options::linear_solver_max_num_iterations is 0."; @@ -455,30 +560,32 @@ LinearSolver* SolverImpl::CreateLinearSolver(Solver::Options* options, } LinearSolver::Options linear_solver_options; - linear_solver_options.constant_sparsity = true; linear_solver_options.min_num_iterations = options->linear_solver_min_num_iterations; linear_solver_options.max_num_iterations = options->linear_solver_max_num_iterations; linear_solver_options.type = options->linear_solver_type; linear_solver_options.preconditioner_type = options->preconditioner_type; + linear_solver_options.sparse_linear_algebra_library = + options->sparse_linear_algebra_library; + linear_solver_options.use_block_amd = options->use_block_amd; #ifdef CERES_NO_SUITESPARSE if (linear_solver_options.preconditioner_type == SCHUR_JACOBI) { *error = "SCHUR_JACOBI preconditioner not suppored. Please build Ceres " - "with SuiteSparse support"; + "with SuiteSparse support."; return NULL; } if (linear_solver_options.preconditioner_type == CLUSTER_JACOBI) { *error = "CLUSTER_JACOBI preconditioner not suppored. Please build Ceres " - "with SuiteSparse support"; + "with SuiteSparse support."; return NULL; } if (linear_solver_options.preconditioner_type == CLUSTER_TRIDIAGONAL) { *error = "CLUSTER_TRIDIAGONAL preconditioner not suppored. Please build " - "Ceres with SuiteSparse support"; + "Ceres with SuiteSparse support."; return NULL; } #endif @@ -489,23 +596,23 @@ LinearSolver* SolverImpl::CreateLinearSolver(Solver::Options* options, if ((linear_solver_options.num_eliminate_blocks == 0) && IsSchurType(linear_solver_options.type)) { -#ifndef CERES_NO_SUITESPARSE +#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE) + LOG(INFO) << "No elimination block remaining switching to DENSE_QR."; + linear_solver_options.type = DENSE_QR; +#else LOG(INFO) << "No elimination block remaining " << "switching to SPARSE_NORMAL_CHOLESKY."; linear_solver_options.type = SPARSE_NORMAL_CHOLESKY; -#else - LOG(INFO) << "No elimination block remaining switching to DENSE_QR."; - linear_solver_options.type = DENSE_QR; -#endif // CERES_NO_SUITESPARSE +#endif } -#ifdef CERES_NO_SUITESPARSE +#if defined(CERES_NO_SUITESPARSE) && defined(CERES_NO_CXSPARSE) if (linear_solver_options.type == SPARSE_SCHUR) { - *error = "Can't use SPARSE_SCHUR because SuiteSparse was not " - "enabled when Ceres was built."; + *error = "Can't use SPARSE_SCHUR because neither SuiteSparse nor" + "CXSparse was enabled when Ceres was compiled."; return NULL; } -#endif // CERES_NO_SUITESPARSE +#endif // The matrix used for storing the dense Schur complement has a // single lock guarding the whole matrix. Running the @@ -578,15 +685,18 @@ bool SolverImpl::ApplyUserOrdering(const ProblemImpl& problem_impl, // Find the minimum index of any parameter block to the given residual. // Parameter blocks that have indices greater than num_eliminate_blocks are // considered to have an index equal to num_eliminate_blocks. -int MinParameterBlock(const ResidualBlock* residual_block, - int num_eliminate_blocks) { +static int MinParameterBlock(const ResidualBlock* residual_block, + int num_eliminate_blocks) { int min_parameter_block_position = num_eliminate_blocks; for (int i = 0; i < residual_block->NumParameterBlocks(); ++i) { ParameterBlock* parameter_block = residual_block->parameter_blocks()[i]; - DCHECK_NE(parameter_block->index(), -1) - << "Did you forget to call Program::SetParameterOffsetsAndIndex()?"; - min_parameter_block_position = std::min(parameter_block->index(), - min_parameter_block_position); + if (!parameter_block->IsConstant()) { + CHECK_NE(parameter_block->index(), -1) + << "Did you forget to call Program::SetParameterOffsetsAndIndex()? " + << "This is a Ceres bug; please contact the developers!"; + min_parameter_block_position = std::min(parameter_block->index(), + min_parameter_block_position); + } } return min_parameter_block_position; } diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h index 957ebcc65df..11b44de6f42 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h +++ b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h @@ -31,6 +31,9 @@ #ifndef CERES_INTERNAL_SOLVER_IMPL_H_ #define CERES_INTERNAL_SOLVER_IMPL_H_ +#include +#include +#include "ceres/internal/port.h" #include "ceres/solver.h" namespace ceres { @@ -46,15 +49,18 @@ class SolverImpl { // Mirrors the interface in solver.h, but exposes implementation // details for testing internally. static void Solve(const Solver::Options& options, - Problem* problem, + ProblemImpl* problem_impl, Solver::Summary* summary); // Create the transformed Program, which has all the fixed blocks // and residuals eliminated, and in the case of automatic schur // ordering, has the E blocks first in the resulting program, with // options.num_eliminate_blocks set appropriately. + // If fixed_cost is not NULL, the residual blocks that are removed + // are evaluated and the sum of their cost is returned in fixed_cost. static Program* CreateReducedProgram(Solver::Options* options, ProblemImpl* problem_impl, + double* fixed_cost, string* error); // Create the appropriate linear solver, taking into account any @@ -92,16 +98,18 @@ class SolverImpl { Program* program, Evaluator* evaluator, LinearSolver* linear_solver, - double* initial_parameters, - double* final_parameters, + double* parameters, Solver::Summary* summary); // Remove the fixed or unused parameter blocks and residuals // depending only on fixed parameters from the problem. Also updates // num_eliminate_blocks, since removed parameters changes the point // at which the eliminated blocks is valid. + // If fixed_cost is not NULL, the residual blocks that are removed + // are evaluated and the sum of their cost is returned in fixed_cost. static bool RemoveFixedBlocksFromProgram(Program* program, int* num_eliminate_blocks, + double* fixed_cost, string* error); }; diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h index 562210dfec8..1b19f887946 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h +++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_matrix.h @@ -86,7 +86,7 @@ class SparseMatrix : public LinearOperator { // sparse matrix. virtual void ToDenseMatrix(Matrix* dense_matrix) const = 0; -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS // Dump the sparse matrix to a proto. Destroys the contents of proto. virtual void ToProto(SparseMatrixProto* proto) const = 0; #endif diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc index 59222dc374d..9e00b4402dc 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc @@ -28,13 +28,16 @@ // // Author: sameeragarwal@google.com (Sameer Agarwal) -#ifndef CERES_NO_SUITESPARSE - #include "ceres/sparse_normal_cholesky_solver.h" #include #include #include + +#ifndef CERES_NO_CXSPARSE +#include "cs.h" +#endif + #include "ceres/compressed_row_sparse_matrix.h" #include "ceres/linear_solver.h" #include "ceres/suitesparse.h" @@ -48,13 +51,30 @@ namespace internal { SparseNormalCholeskySolver::SparseNormalCholeskySolver( const LinearSolver::Options& options) - : options_(options), symbolic_factor_(NULL) {} + : options_(options) { +#ifndef CERES_NO_SUITESPARSE + factor_ = NULL; +#endif + +#ifndef CERES_NO_CXSPARSE + cxsparse_factor_ = NULL; +#endif // CERES_NO_CXSPARSE +} SparseNormalCholeskySolver::~SparseNormalCholeskySolver() { - if (symbolic_factor_ != NULL) { - ss_.Free(symbolic_factor_); - symbolic_factor_ = NULL; +#ifndef CERES_NO_SUITESPARSE + if (factor_ != NULL) { + ss_.Free(factor_); + factor_ = NULL; } +#endif + +#ifndef CERES_NO_CXSPARSE + if (cxsparse_factor_ != NULL) { + cxsparse_.Free(cxsparse_factor_); + cxsparse_factor_ = NULL; + } +#endif // CERES_NO_CXSPARSE } LinearSolver::Summary SparseNormalCholeskySolver::SolveImpl( @@ -62,6 +82,93 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImpl( const double* b, const LinearSolver::PerSolveOptions& per_solve_options, double * x) { + switch (options_.sparse_linear_algebra_library) { + case SUITE_SPARSE: + return SolveImplUsingSuiteSparse(A, b, per_solve_options, x); + case CX_SPARSE: + return SolveImplUsingCXSparse(A, b, per_solve_options, x); + default: + LOG(FATAL) << "Unknown sparse linear algebra library : " + << options_.sparse_linear_algebra_library; + } + + LOG(FATAL) << "Unknown sparse linear algebra library : " + << options_.sparse_linear_algebra_library; + return LinearSolver::Summary(); +} + +#ifndef CERES_NO_CXSPARSE +LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingCXSparse( + CompressedRowSparseMatrix* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double * x) { + LinearSolver::Summary summary; + summary.num_iterations = 1; + const int num_cols = A->num_cols(); + Vector Atb = Vector::Zero(num_cols); + A->LeftMultiply(b, Atb.data()); + + if (per_solve_options.D != NULL) { + // Temporarily append a diagonal block to the A matrix, but undo + // it before returning the matrix to the user. + CompressedRowSparseMatrix D(per_solve_options.D, num_cols); + A->AppendRows(D); + } + + VectorRef(x, num_cols).setZero(); + + // Wrap the augmented Jacobian in a compressed sparse column matrix. + cs_di At = cxsparse_.CreateSparseMatrixTransposeView(A); + + // Compute the normal equations. J'J delta = J'f and solve them + // using a sparse Cholesky factorization. Notice that when compared + // to SuiteSparse we have to explicitly compute the transpose of Jt, + // and then the normal equations before they can be + // factorized. CHOLMOD/SuiteSparse on the other hand can just work + // off of Jt to compute the Cholesky factorization of the normal + // equations. + cs_di* A2 = cs_transpose(&At, 1); + cs_di* AtA = cs_multiply(&At,A2); + + cxsparse_.Free(A2); + if (per_solve_options.D != NULL) { + A->DeleteRows(num_cols); + } + + // Compute symbolic factorization if not available. + if (cxsparse_factor_ == NULL) { + cxsparse_factor_ = CHECK_NOTNULL(cxsparse_.AnalyzeCholesky(AtA)); + } + + // Solve the linear system. + if (cxsparse_.SolveCholesky(AtA, cxsparse_factor_, Atb.data())) { + VectorRef(x, Atb.rows()) = Atb; + summary.termination_type = TOLERANCE; + } + + cxsparse_.Free(AtA); + return summary; +} +#else +LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingCXSparse( + CompressedRowSparseMatrix* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double * x) { + LOG(FATAL) << "No CXSparse support in Ceres."; + + // Unreachable but MSVC does not know this. + return LinearSolver::Summary(); +} +#endif + +#ifndef CERES_NO_SUITESPARSE +LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse( + CompressedRowSparseMatrix* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double * x) { const time_t start_time = time(NULL); const int num_cols = A->num_cols(); @@ -84,13 +191,25 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImpl( cholmod_dense* rhs = ss_.CreateDenseVector(Atb.data(), num_cols, num_cols); const time_t init_time = time(NULL); - if (symbolic_factor_ == NULL) { - symbolic_factor_ = CHECK_NOTNULL(ss_.AnalyzeCholesky(lhs.get())); + if (factor_ == NULL) { + if (options_.use_block_amd) { + factor_ = ss_.BlockAnalyzeCholesky(lhs.get(), + A->col_blocks(), + A->row_blocks()); + } else { + factor_ = ss_.AnalyzeCholesky(lhs.get()); + } + + if (VLOG_IS_ON(2)) { + cholmod_print_common("Symbolic Analysis", ss_.mutable_cc()); + } } + CHECK_NOTNULL(factor_); + const time_t symbolic_time = time(NULL); - cholmod_dense* sol = ss_.SolveCholesky(lhs.get(), symbolic_factor_, rhs); + cholmod_dense* sol = ss_.SolveCholesky(lhs.get(), factor_, rhs); const time_t solve_time = time(NULL); ss_.Free(rhs); @@ -100,11 +219,6 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImpl( A->DeleteRows(num_cols); } - if (!options_.constant_sparsity) { - ss_.Free(symbolic_factor_); - symbolic_factor_ = NULL; - } - summary.num_iterations = 1; if (sol != NULL) { memcpy(x, sol->x, num_cols * sizeof(*x)); @@ -115,15 +229,25 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImpl( } const time_t cleanup_time = time(NULL); - VLOG(2) << "time (sec) total: " << cleanup_time - start_time - << " init: " << init_time - start_time - << " symbolic: " << symbolic_time - init_time - << " solve: " << solve_time - symbolic_time - << " cleanup: " << cleanup_time - solve_time; + VLOG(2) << "time (sec) total: " << (cleanup_time - start_time) + << " init: " << (init_time - start_time) + << " symbolic: " << (symbolic_time - init_time) + << " solve: " << (solve_time - symbolic_time) + << " cleanup: " << (cleanup_time - solve_time); return summary; } +#else +LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse( + CompressedRowSparseMatrix* A, + const double* b, + const LinearSolver::PerSolveOptions& per_solve_options, + double * x) { + LOG(FATAL) << "No SuiteSparse support in Ceres."; + + // Unreachable but MSVC does not know this. + return LinearSolver::Summary(); +} +#endif } // namespace internal } // namespace ceres - -#endif // CERES_NO_SUITESPARSE diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h index ce1d6d285be..40d9e0a0327 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h +++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.h @@ -34,13 +34,10 @@ #ifndef CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_ #define CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_ -#ifndef CERES_NO_SUITESPARSE - -#include "cholmod.h" -#include "cholmod_core.h" +#include "ceres/cxsparse.h" #include "ceres/linear_solver.h" -#include "ceres/suitesparse.h" #include "ceres/internal/macros.h" +#include "ceres/suitesparse.h" namespace ceres { namespace internal { @@ -61,17 +58,36 @@ class SparseNormalCholeskySolver : public CompressedRowSparseMatrixSolver { const LinearSolver::PerSolveOptions& options, double* x); - const LinearSolver::Options options_; - SuiteSparse ss_; + LinearSolver::Summary SolveImplUsingSuiteSparse( + CompressedRowSparseMatrix* A, + const double* b, + const LinearSolver::PerSolveOptions& options, + double* x); + // Crashes if CSparse is not installed. + LinearSolver::Summary SolveImplUsingCXSparse( + CompressedRowSparseMatrix* A, + const double* b, + const LinearSolver::PerSolveOptions& options, + double* x); + +#ifndef CERES_NO_SUITESPARSE + SuiteSparse ss_; // Cached factorization - cholmod_factor* symbolic_factor_; - DISALLOW_COPY_AND_ASSIGN(SparseNormalCholeskySolver); + cholmod_factor* factor_; +#endif // CERES_NO_SUITESPARSE + +#ifndef CERES_NO_CXSPARSE + CXSparse cxsparse_; + // Cached factorization + cs_dis* cxsparse_factor_; +#endif // CERES_NO_CXSPARSE + + const LinearSolver::Options options_; + CERES_DISALLOW_COPY_AND_ASSIGN(SparseNormalCholeskySolver); }; } // namespace internal } // namespace ceres -#endif // CERES_NO_SUITESPARSE - #endif // CERES_INTERNAL_SPARSE_NORMAL_CHOLESKY_SOLVER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/split.cc b/extern/libmv/third_party/ceres/internal/ceres/split.cc index 4fa1bd468b9..c65c8a5bb5d 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/split.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/split.cc @@ -31,6 +31,7 @@ #include #include #include +#include "ceres/split.h" #include "ceres/internal/port.h" namespace ceres { diff --git a/extern/libmv/third_party/ceres/internal/ceres/split.h b/extern/libmv/third_party/ceres/internal/ceres/split.h new file mode 100644 index 00000000000..ec579e974da --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/split.h @@ -0,0 +1,21 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// Author: keir@google.com (Keir Mierle) + +#ifndef CERES_INTERNAL_SPLIT_H_ +#define VISION_OPTIMIZATION_LEAST_SQUARES_INTERNAL_SPLIT_H_ + +#include +#include +#include "ceres/internal/port.h" + +namespace ceres { + +// Split a string using one or more character delimiters, presented as a +// nul-terminated c string. Append the components to 'result'. If there are +// consecutive delimiters, this function skips over all of them. +void SplitStringUsing(const string& full, const char* delim, + vector* res); + +} // namespace ceres + +#endif // CERES_INTERNAL_SPLIT_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc index c0f35225bc3..396a48b7d97 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.cc @@ -34,6 +34,7 @@ #include #include +#include "ceres/stringprintf.h" #include "ceres/internal/port.h" namespace ceres { diff --git a/extern/libmv/third_party/ceres/internal/ceres/stringprintf.h b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.h index 30b974e7ae5..f2f907ab32d 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/stringprintf.h +++ b/extern/libmv/third_party/ceres/internal/ceres/stringprintf.h @@ -54,34 +54,34 @@ namespace internal { // N.B.: As the GCC manual states, "[s]ince non-static C++ methods // have an implicit 'this' argument, the arguments of such methods // should be counted from two, not one." -#define PRINTF_ATTRIBUTE(string_index, first_to_check) \ +#define CERES_PRINTF_ATTRIBUTE(string_index, first_to_check) \ __attribute__((__format__ (__printf__, string_index, first_to_check))) -#define SCANF_ATTRIBUTE(string_index, first_to_check) \ +#define CERES_SCANF_ATTRIBUTE(string_index, first_to_check) \ __attribute__((__format__ (__scanf__, string_index, first_to_check))) #else -#define PRINTF_ATTRIBUTE(string_index, first_to_check) +#define CERES_PRINTF_ATTRIBUTE(string_index, first_to_check) #endif // Return a C++ string. extern string StringPrintf(const char* format, ...) // Tell the compiler to do printf format string checking. - PRINTF_ATTRIBUTE(1,2); + CERES_PRINTF_ATTRIBUTE(1,2); // Store result into a supplied string and return it. extern const string& SStringPrintf(string* dst, const char* format, ...) // Tell the compiler to do printf format string checking. - PRINTF_ATTRIBUTE(2,3); + CERES_PRINTF_ATTRIBUTE(2,3); // Append result to a supplied string. extern void StringAppendF(string* dst, const char* format, ...) // Tell the compiler to do printf format string checking. - PRINTF_ATTRIBUTE(2,3); + CERES_PRINTF_ATTRIBUTE(2,3); // Lower-level routine that takes a va_list and appends to a specified string. // All other routines are just convenience wrappers around it. extern void StringAppendV(string* dst, const char* format, va_list ap); -#undef PRINTF_ATTRIBUTE +#undef CERES_PRINTF_ATTRIBUTE } // namespace internal } // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc index 1cf6a7496a7..cf3c48f84e6 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc @@ -29,15 +29,14 @@ // Author: sameeragarwal@google.com (Sameer Agarwal) #ifndef CERES_NO_SUITESPARSE - #include "ceres/suitesparse.h" +#include #include "cholmod.h" #include "ceres/compressed_row_sparse_matrix.h" #include "ceres/triplet_sparse_matrix.h" namespace ceres { namespace internal { - cholmod_sparse* SuiteSparse::CreateSparseMatrix(TripletSparseMatrix* A) { cholmod_triplet triplet; @@ -111,6 +110,13 @@ cholmod_dense* SuiteSparse::CreateDenseVector(const double* x, } cholmod_factor* SuiteSparse::AnalyzeCholesky(cholmod_sparse* A) { + // Cholmod can try multiple re-ordering strategies to find a fill + // reducing ordering. Here we just tell it use AMD with automatic + // matrix dependence choice of supernodal versus simplicial + // factorization. + cc_.nmethods = 1; + cc_.method[0].ordering = CHOLMOD_AMD; + cc_.supernodal = CHOLMOD_AUTO; cholmod_factor* factor = cholmod_analyze(A, &cc_); CHECK_EQ(cc_.status, CHOLMOD_OK) << "Cholmod symbolic analysis failed " << cc_.status; @@ -118,6 +124,153 @@ cholmod_factor* SuiteSparse::AnalyzeCholesky(cholmod_sparse* A) { return factor; } +cholmod_factor* SuiteSparse::BlockAnalyzeCholesky( + cholmod_sparse* A, + const vector& row_blocks, + const vector& col_blocks) { + vector ordering; + if (!BlockAMDOrdering(A, row_blocks, col_blocks, &ordering)) { + return NULL; + } + return AnalyzeCholeskyWithUserOrdering(A, ordering); +} + +cholmod_factor* SuiteSparse::AnalyzeCholeskyWithUserOrdering(cholmod_sparse* A, + const vector& ordering) { + CHECK_EQ(ordering.size(), A->nrow); + cc_.nmethods = 1 ; + cc_.method[0].ordering = CHOLMOD_GIVEN; + cholmod_factor* factor = + cholmod_analyze_p(A, const_cast(&ordering[0]), NULL, 0, &cc_); + CHECK_EQ(cc_.status, CHOLMOD_OK) + << "Cholmod symbolic analysis failed " << cc_.status; + CHECK_NOTNULL(factor); + return factor; +} + +bool SuiteSparse::BlockAMDOrdering(const cholmod_sparse* A, + const vector& row_blocks, + const vector& col_blocks, + vector* ordering) { + const int num_row_blocks = row_blocks.size(); + const int num_col_blocks = col_blocks.size(); + + // Arrays storing the compressed column structure of the matrix + // incoding the block sparsity of A. + vector block_cols; + vector block_rows; + + ScalarMatrixToBlockMatrix(A, + row_blocks, + col_blocks, + &block_rows, + &block_cols); + + cholmod_sparse_struct block_matrix; + block_matrix.nrow = num_row_blocks; + block_matrix.ncol = num_col_blocks; + block_matrix.nzmax = block_rows.size(); + block_matrix.p = reinterpret_cast(&block_cols[0]); + block_matrix.i = reinterpret_cast(&block_rows[0]); + block_matrix.x = NULL; + block_matrix.stype = A->stype; + block_matrix.itype = CHOLMOD_INT; + block_matrix.xtype = CHOLMOD_PATTERN; + block_matrix.dtype = CHOLMOD_DOUBLE; + block_matrix.sorted = 1; + block_matrix.packed = 1; + + vector block_ordering(num_row_blocks); + if (!cholmod_amd(&block_matrix, NULL, 0, &block_ordering[0], &cc_)) { + return false; + } + + BlockOrderingToScalarOrdering(row_blocks, block_ordering, ordering); + return true; +} + +void SuiteSparse::ScalarMatrixToBlockMatrix(const cholmod_sparse* A, + const vector& row_blocks, + const vector& col_blocks, + vector* block_rows, + vector* block_cols) { + CHECK_NOTNULL(block_rows)->clear(); + CHECK_NOTNULL(block_cols)->clear(); + const int num_row_blocks = row_blocks.size(); + const int num_col_blocks = col_blocks.size(); + + vector row_block_starts(num_row_blocks); + for (int i = 0, cursor = 0; i < num_row_blocks; ++i) { + row_block_starts[i] = cursor; + cursor += row_blocks[i]; + } + + // The reinterpret_cast is needed here because CHOLMOD stores arrays + // as void*. + const int* scalar_cols = reinterpret_cast(A->p); + const int* scalar_rows = reinterpret_cast(A->i); + + // This loop extracts the block sparsity of the scalar sparse matrix + // A. It does so by iterating over the columns, but only considering + // the columns corresponding to the first element of each column + // block. Within each column, the inner loop iterates over the rows, + // and detects the presence of a row block by checking for the + // presence of a non-zero entry corresponding to its first element. + block_cols->push_back(0); + int c = 0; + for (int col_block = 0; col_block < num_col_blocks; ++col_block) { + int column_size = 0; + for (int idx = scalar_cols[c]; idx < scalar_cols[c + 1]; ++idx) { + vector::const_iterator it = lower_bound(row_block_starts.begin(), + row_block_starts.end(), + scalar_rows[idx]); + // Since we are using lower_bound, it will return the row id + // where the row block starts. For everything but the first row + // of the block, where these values will be the same, we can + // skip, as we only need the first row to detect the presence of + // the block. + // + // For rows all but the first row in the last row block, + // lower_bound will return row_block_starts.end(), but those can + // be skipped like the rows in other row blocks too. + if (it == row_block_starts.end() || *it != scalar_rows[idx]) { + continue; + } + + block_rows->push_back(it - row_block_starts.begin()); + ++column_size; + } + block_cols->push_back(block_cols->back() + column_size); + c += col_blocks[col_block]; + } +} + +void SuiteSparse::BlockOrderingToScalarOrdering( + const vector& blocks, + const vector& block_ordering, + vector* scalar_ordering) { + CHECK_EQ(blocks.size(), block_ordering.size()); + const int num_blocks = blocks.size(); + + // block_starts = [0, block1, block1 + block2 ..] + vector block_starts(num_blocks); + for (int i = 0, cursor = 0; i < num_blocks ; ++i) { + block_starts[i] = cursor; + cursor += blocks[i]; + } + + scalar_ordering->resize(block_starts.back() + blocks.back()); + int cursor = 0; + for (int i = 0; i < num_blocks; ++i) { + const int block_id = block_ordering[i]; + const int block_size = blocks[block_id]; + int block_position = block_starts[block_id]; + for (int j = 0; j < block_size; ++j) { + (*scalar_ordering)[cursor++] = block_position++; + } + } +} + bool SuiteSparse::Cholesky(cholmod_sparse* A, cholmod_factor* L) { CHECK_NOTNULL(A); CHECK_NOTNULL(L); diff --git a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h index 091e67a69a9..eb691c0c0ed 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h +++ b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h @@ -37,6 +37,7 @@ #include #include +#include #include #include "cholmod.h" @@ -105,12 +106,35 @@ class SuiteSparse { cholmod_sdmult(A, 0, alpha_, beta_, x, y, &cc_); } - // Analyze the sparsity structure of the matrix A compute the - // symbolic factorization of A. A is not modified, only the pattern - // of non-zeros of A is used, the actual numerical values in A are - // of no consequence. Caller owns the result. + // Find an ordering of A or AA' (if A is unsymmetric) that minimizes + // the fill-in in the Cholesky factorization of the corresponding + // matrix. This is done by using the AMD algorithm. + // + // Using this ordering, the symbolic Cholesky factorization of A (or + // AA') is computed and returned. + // + // A is not modified, only the pattern of non-zeros of A is used, + // the actual numerical values in A are of no consequence. + // + // Caller owns the result. cholmod_factor* AnalyzeCholesky(cholmod_sparse* A); + cholmod_factor* BlockAnalyzeCholesky(cholmod_sparse* A, + const vector& row_blocks, + const vector& col_blocks); + + // If A is symmetric, then compute the symbolic Cholesky + // factorization of A(ordering, ordering). If A is unsymmetric, then + // compute the symbolic factorization of + // A(ordering,:) A(ordering,:)'. + // + // A is not modified, only the pattern of non-zeros of A is used, + // the actual numerical values in A are of no consequence. + // + // Caller owns the result. + cholmod_factor* AnalyzeCholeskyWithUserOrdering(cholmod_sparse* A, + const vector& ordering); + // Use the symbolic factorization in L, to find the numerical // factorization for the matrix A or AA^T. Return true if // successful, false otherwise. L contains the numeric factorization @@ -129,6 +153,56 @@ class SuiteSparse { cholmod_factor* L, cholmod_dense* b); + // By virtue of the modeling layer in Ceres being block oriented, + // all the matrices used by Ceres are also block oriented. When + // doing sparse direct factorization of these matrices the + // fill-reducing ordering algorithms (in particular AMD) can either + // be run on the block or the scalar form of these matrices. The two + // SuiteSparse::AnalyzeCholesky methods allows the the client to + // compute the symbolic factorization of a matrix by either using + // AMD on the matrix or a user provided ordering of the rows. + // + // But since the underlying matrices are block oriented, it is worth + // running AMD on just the block structre of these matrices and then + // lifting these block orderings to a full scalar ordering. This + // preserves the block structure of the permuted matrix, and exposes + // more of the super-nodal structure of the matrix to the numerical + // factorization routines. + // + // Find the block oriented AMD ordering of a matrix A, whose row and + // column blocks are given by row_blocks, and col_blocks + // respectively. The matrix may or may not be symmetric. The entries + // of col_blocks do not need to sum to the number of columns in + // A. If this is the case, only the first sum(col_blocks) are used + // to compute the ordering. + bool BlockAMDOrdering(const cholmod_sparse* A, + const vector& row_blocks, + const vector& col_blocks, + vector* ordering); + + // Given a set of blocks and a permutation of these blocks, compute + // the corresponding "scalar" ordering, where the scalar ordering of + // size sum(blocks). + static void BlockOrderingToScalarOrdering(const vector& blocks, + const vector& block_ordering, + vector* scalar_ordering); + + // Extract the block sparsity pattern of the scalar sparse matrix + // A and return it in compressed column form. The compressed column + // form is stored in two vectors block_rows, and block_cols, which + // correspond to the row and column arrays in a compressed column sparse + // matrix. + // + // If c_ij is the block in the matrix A corresponding to row block i + // and column block j, then it is expected that A contains at least + // one non-zero entry corresponding to the top left entry of c_ij, + // as that entry is used to detect the presence of a non-zero c_ij. + static void ScalarMatrixToBlockMatrix(const cholmod_sparse* A, + const vector& row_blocks, + const vector& col_blocks, + vector* block_rows, + vector* block_cols); + void Free(cholmod_sparse* m) { cholmod_free_sparse(&m, &cc_); } void Free(cholmod_dense* m) { cholmod_free_dense(&m, &cc_); } void Free(cholmod_factor* m) { cholmod_free_factor(&m, &cc_); } diff --git a/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc index 247ab2e697b..ed8677ea18a 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.cc @@ -32,12 +32,12 @@ #include #include -#include -#include "ceres/matrix_proto.h" #include "ceres/internal/eigen.h" #include "ceres/internal/port.h" #include "ceres/internal/scoped_ptr.h" +#include "ceres/matrix_proto.h" #include "ceres/types.h" +#include "glog/logging.h" namespace ceres { namespace internal { @@ -82,7 +82,7 @@ TripletSparseMatrix::TripletSparseMatrix(const TripletSparseMatrix& orig) CopyData(orig); } -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS TripletSparseMatrix::TripletSparseMatrix(const SparseMatrixProto& outer_proto) { CHECK(outer_proto.has_triplet_matrix()); @@ -130,7 +130,7 @@ bool TripletSparseMatrix::AllTripletsWithinBounds() const { void TripletSparseMatrix::Reserve(int new_max_num_nonzeros) { CHECK_LE(num_nonzeros_, new_max_num_nonzeros) - << "Reallocation will cause data loss"; + << "Reallocation will cause data loss"; // Nothing to do if we have enough space already. if (new_max_num_nonzeros <= max_num_nonzeros_) @@ -214,7 +214,7 @@ void TripletSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const { } } -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS void TripletSparseMatrix::ToProto(SparseMatrixProto *proto) const { proto->Clear(); diff --git a/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h index 300e74d0bbc..89a645bd879 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h +++ b/extern/libmv/third_party/ceres/internal/ceres/triplet_sparse_matrix.h @@ -50,7 +50,7 @@ class TripletSparseMatrix : public SparseMatrix { TripletSparseMatrix(); TripletSparseMatrix(int num_rows, int num_cols, int max_num_nonzeros); explicit TripletSparseMatrix(const TripletSparseMatrix& orig); -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS explicit TripletSparseMatrix(const SparseMatrixProto& proto); #endif @@ -65,7 +65,7 @@ class TripletSparseMatrix : public SparseMatrix { virtual void SquaredColumnNorm(double* x) const; virtual void ScaleColumns(const double* scale); virtual void ToDenseMatrix(Matrix* dense_matrix) const; -#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS +#ifndef CERES_NO_PROTOCOL_BUFFERS virtual void ToProto(SparseMatrixProto *proto) const; #endif virtual void ToTextFile(FILE* file) const; diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc b/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc new file mode 100644 index 00000000000..76c4f8a7580 --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc @@ -0,0 +1,550 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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 Google Inc. 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. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#include "ceres/trust_region_minimizer.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "Eigen/Core" +#include "ceres/array_utils.h" +#include "ceres/evaluator.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/scoped_ptr.h" +#include "ceres/linear_least_squares_problems.h" +#include "ceres/sparse_matrix.h" +#include "ceres/trust_region_strategy.h" +#include "ceres/types.h" +#include "glog/logging.h" + +namespace ceres { +namespace internal { +namespace { +// Small constant for various floating point issues. +const double kEpsilon = 1e-12; +} // namespace + +// Execute the list of IterationCallbacks sequentially. If any one of +// the callbacks does not return SOLVER_CONTINUE, then stop and return +// its status. +CallbackReturnType TrustRegionMinimizer::RunCallbacks( + const IterationSummary& iteration_summary) { + for (int i = 0; i < options_.callbacks.size(); ++i) { + const CallbackReturnType status = + (*options_.callbacks[i])(iteration_summary); + if (status != SOLVER_CONTINUE) { + return status; + } + } + return SOLVER_CONTINUE; +} + +// Compute a scaling vector that is used to improve the conditioning +// of the Jacobian. +void TrustRegionMinimizer::EstimateScale(const SparseMatrix& jacobian, + double* scale) const { + jacobian.SquaredColumnNorm(scale); + for (int i = 0; i < jacobian.num_cols(); ++i) { + scale[i] = 1.0 / (kEpsilon + sqrt(scale[i])); + } +} + +void TrustRegionMinimizer::Init(const Minimizer::Options& options) { + options_ = options; + sort(options_.lsqp_iterations_to_dump.begin(), + options_.lsqp_iterations_to_dump.end()); +} + +bool TrustRegionMinimizer::MaybeDumpLinearLeastSquaresProblem( + const int iteration, + const SparseMatrix* jacobian, + const double* residuals, + const double* step) const { + // TODO(sameeragarwal): Since the use of trust_region_radius has + // moved inside TrustRegionStrategy, its not clear how we dump the + // regularization vector/matrix anymore. + // + // Doing this right requires either an API change to the + // TrustRegionStrategy and/or how LinearLeastSquares problems are + // stored on disk. + // + // For now, we will just not dump the regularizer. + return (!binary_search(options_.lsqp_iterations_to_dump.begin(), + options_.lsqp_iterations_to_dump.end(), + iteration) || + DumpLinearLeastSquaresProblem(options_.lsqp_dump_directory, + iteration, + options_.lsqp_dump_format_type, + jacobian, + NULL, + residuals, + step, + options_.num_eliminate_blocks)); +} + +void TrustRegionMinimizer::Minimize(const Minimizer::Options& options, + double* parameters, + Solver::Summary* summary) { + time_t start_time = time(NULL); + time_t iteration_start_time = start_time; + Init(options); + + summary->termination_type = NO_CONVERGENCE; + summary->num_successful_steps = 0; + summary->num_unsuccessful_steps = 0; + + Evaluator* evaluator = CHECK_NOTNULL(options_.evaluator); + SparseMatrix* jacobian = CHECK_NOTNULL(options_.jacobian); + TrustRegionStrategy* strategy = CHECK_NOTNULL(options_.trust_region_strategy); + + const int num_parameters = evaluator->NumParameters(); + const int num_effective_parameters = evaluator->NumEffectiveParameters(); + const int num_residuals = evaluator->NumResiduals(); + + VectorRef x_min(parameters, num_parameters); + Vector x = x_min; + double x_norm = x.norm(); + + Vector residuals(num_residuals); + Vector trust_region_step(num_effective_parameters); + Vector delta(num_effective_parameters); + Vector x_plus_delta(num_parameters); + Vector gradient(num_effective_parameters); + Vector model_residuals(num_residuals); + Vector scale(num_effective_parameters); + + IterationSummary iteration_summary; + iteration_summary.iteration = 0; + iteration_summary.step_is_valid = false; + iteration_summary.step_is_successful = false; + iteration_summary.cost = summary->initial_cost; + iteration_summary.cost_change = 0.0; + iteration_summary.gradient_max_norm = 0.0; + iteration_summary.step_norm = 0.0; + iteration_summary.relative_decrease = 0.0; + iteration_summary.trust_region_radius = strategy->Radius(); + // TODO(sameeragarwal): Rename eta to linear_solver_accuracy or + // something similar across the board. + iteration_summary.eta = options_.eta; + iteration_summary.linear_solver_iterations = 0; + iteration_summary.step_solver_time_in_seconds = 0; + + // Do initial cost and Jacobian evaluation. + double cost = 0.0; + if (!evaluator->Evaluate(x.data(), &cost, residuals.data(), NULL, jacobian)) { + LOG(WARNING) << "Terminating: Residual and Jacobian evaluation failed."; + summary->termination_type = NUMERICAL_FAILURE; + return; + } + + int num_consecutive_nonmonotonic_steps = 0; + double minimum_cost = cost; + double reference_cost = cost; + double accumulated_reference_model_cost_change = 0.0; + double candidate_cost = cost; + double accumulated_candidate_model_cost_change = 0.0; + + gradient.setZero(); + jacobian->LeftMultiply(residuals.data(), gradient.data()); + iteration_summary.gradient_max_norm = gradient.lpNorm(); + + if (options_.jacobi_scaling) { + EstimateScale(*jacobian, scale.data()); + jacobian->ScaleColumns(scale.data()); + } else { + scale.setOnes(); + } + + // The initial gradient max_norm is bounded from below so that we do + // not divide by zero. + const double gradient_max_norm_0 = + max(iteration_summary.gradient_max_norm, kEpsilon); + const double absolute_gradient_tolerance = + options_.gradient_tolerance * gradient_max_norm_0; + + if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) { + summary->termination_type = GRADIENT_TOLERANCE; + VLOG(1) << "Terminating: Gradient tolerance reached." + << "Relative gradient max norm: " + << iteration_summary.gradient_max_norm / gradient_max_norm_0 + << " <= " << options_.gradient_tolerance; + return; + } + + iteration_summary.iteration_time_in_seconds = + time(NULL) - iteration_start_time; + iteration_summary.cumulative_time_in_seconds = time(NULL) - start_time + + summary->preprocessor_time_in_seconds; + summary->iterations.push_back(iteration_summary); + + // Call the various callbacks. + switch (RunCallbacks(iteration_summary)) { + case SOLVER_TERMINATE_SUCCESSFULLY: + summary->termination_type = USER_SUCCESS; + VLOG(1) << "Terminating: User callback returned USER_SUCCESS."; + return; + case SOLVER_ABORT: + summary->termination_type = USER_ABORT; + VLOG(1) << "Terminating: User callback returned USER_ABORT."; + return; + case SOLVER_CONTINUE: + break; + default: + LOG(FATAL) << "Unknown type of user callback status"; + } + + int num_consecutive_invalid_steps = 0; + while (true) { + iteration_start_time = time(NULL); + if (iteration_summary.iteration >= options_.max_num_iterations) { + summary->termination_type = NO_CONVERGENCE; + VLOG(1) << "Terminating: Maximum number of iterations reached."; + break; + } + + const double total_solver_time = iteration_start_time - start_time + + summary->preprocessor_time_in_seconds; + if (total_solver_time >= options_.max_solver_time_in_seconds) { + summary->termination_type = NO_CONVERGENCE; + VLOG(1) << "Terminating: Maximum solver time reached."; + break; + } + + iteration_summary = IterationSummary(); + iteration_summary = summary->iterations.back(); + iteration_summary.iteration = summary->iterations.back().iteration + 1; + iteration_summary.step_is_valid = false; + iteration_summary.step_is_successful = false; + + const time_t strategy_start_time = time(NULL); + TrustRegionStrategy::PerSolveOptions per_solve_options; + per_solve_options.eta = options_.eta; + TrustRegionStrategy::Summary strategy_summary = + strategy->ComputeStep(per_solve_options, + jacobian, + residuals.data(), + trust_region_step.data()); + + iteration_summary.step_solver_time_in_seconds = + time(NULL) - strategy_start_time; + iteration_summary.linear_solver_iterations = + strategy_summary.num_iterations; + + if (!MaybeDumpLinearLeastSquaresProblem(iteration_summary.iteration, + jacobian, + residuals.data(), + trust_region_step.data())) { + LOG(FATAL) << "Tried writing linear least squares problem: " + << options.lsqp_dump_directory << "but failed."; + } + + double new_model_cost = 0.0; + if (strategy_summary.termination_type != FAILURE) { + // new_model_cost = 1/2 |f + J * step|^2 + model_residuals = residuals; + jacobian->RightMultiply(trust_region_step.data(), model_residuals.data()); + new_model_cost = model_residuals.squaredNorm() / 2.0; + + // In exact arithmetic, this would never be the case. But poorly + // conditioned matrices can give rise to situations where the + // new_model_cost can actually be larger than half the squared + // norm of the residual vector. We allow for small tolerance + // around cost and beyond that declare the step to be invalid. + if ((1.0 - new_model_cost / cost) < -kEpsilon) { + VLOG(1) << "Invalid step: current_cost: " << cost + << " new_model_cost " << new_model_cost + << " absolute difference " << (cost - new_model_cost) + << " relative difference " << (1.0 - new_model_cost/cost); + } else { + iteration_summary.step_is_valid = true; + } + } + + if (!iteration_summary.step_is_valid) { + // Invalid steps can happen due to a number of reasons, and we + // allow a limited number of successive failures, and return with + // NUMERICAL_FAILURE if this limit is exceeded. + if (++num_consecutive_invalid_steps >= + options_.max_num_consecutive_invalid_steps) { + summary->termination_type = NUMERICAL_FAILURE; + LOG(WARNING) << "Terminating. Number of successive invalid steps more " + << "than " + << "Solver::Options::max_num_consecutive_invalid_steps: " + << options_.max_num_consecutive_invalid_steps; + return; + } + + // We are going to try and reduce the trust region radius and + // solve again. To do this, we are going to treat this iteration + // as an unsuccessful iteration. Since the various callbacks are + // still executed, we are going to fill the iteration summary + // with data that assumes a step of length zero and no progress. + iteration_summary.cost = cost; + iteration_summary.cost_change = 0.0; + iteration_summary.gradient_max_norm = + summary->iterations.back().gradient_max_norm; + iteration_summary.step_norm = 0.0; + iteration_summary.relative_decrease = 0.0; + iteration_summary.eta = options_.eta; + } else { + // The step is numerically valid, so now we can judge its quality. + num_consecutive_invalid_steps = 0; + + // We allow some slop around 0, and clamp the model_cost_change + // at kEpsilon * min(1.0, cost) from below. + // + // In exact arithmetic this should never be needed, as we are + // guaranteed to new_model_cost <= cost. However, due to various + // numerical issues, it is possible that new_model_cost is + // nearly equal to cost, and the difference is a small negative + // number. To make sure that the relative_decrease computation + // remains sane, as clamp the difference (cost - new_model_cost) + // from below at a small positive number. + // + // This number is the minimum of kEpsilon * (cost, 1.0), which + // ensures that it will never get too large in absolute value, + // while scaling down proportionally with the magnitude of the + // cost. This is important for problems where the minimum of the + // objective function is near zero. + const double model_cost_change = + max(kEpsilon * min(1.0, cost), cost - new_model_cost); + + // Undo the Jacobian column scaling. + delta = (trust_region_step.array() * scale.array()).matrix(); + iteration_summary.step_norm = delta.norm(); + + // Convergence based on parameter_tolerance. + const double step_size_tolerance = options_.parameter_tolerance * + (x_norm + options_.parameter_tolerance); + if (iteration_summary.step_norm <= step_size_tolerance) { + VLOG(1) << "Terminating. Parameter tolerance reached. " + << "relative step_norm: " + << iteration_summary.step_norm / + (x_norm + options_.parameter_tolerance) + << " <= " << options_.parameter_tolerance; + summary->termination_type = PARAMETER_TOLERANCE; + return; + } + + if (!evaluator->Plus(x.data(), delta.data(), x_plus_delta.data())) { + summary->termination_type = NUMERICAL_FAILURE; + LOG(WARNING) << "Terminating. Failed to compute " + << "Plus(x, delta, x_plus_delta)."; + return; + } + + // Try this step. + double new_cost; + if (!evaluator->Evaluate(x_plus_delta.data(), + &new_cost, + NULL, NULL, NULL)) { + // If the evaluation of the new cost fails, treat it as a step + // with high cost. + LOG(WARNING) << "Step failed to evaluate. " + << "Treating it as step with infinite cost"; + new_cost = numeric_limits::max(); + } + + VLOG(2) << "old cost: " << cost << " new cost: " << new_cost; + iteration_summary.cost_change = cost - new_cost; + const double absolute_function_tolerance = + options_.function_tolerance * cost; + if (fabs(iteration_summary.cost_change) < absolute_function_tolerance) { + VLOG(1) << "Terminating. Function tolerance reached. " + << "|cost_change|/cost: " + << fabs(iteration_summary.cost_change) / cost + << " <= " << options_.function_tolerance; + summary->termination_type = FUNCTION_TOLERANCE; + return; + } + + const double relative_decrease = + iteration_summary.cost_change / model_cost_change; + + const double historical_relative_decrease = + (reference_cost - new_cost) / + (accumulated_reference_model_cost_change + model_cost_change); + + // If monotonic steps are being used, then the relative_decrease + // is the usual ratio of the change in objective function value + // divided by the change in model cost. + // + // If non-monotonic steps are allowed, then we take the maximum + // of the relative_decrease and the + // historical_relative_decrease, which measures the increase + // from a reference iteration. The model cost change is + // estimated by accumulating the model cost changes since the + // reference iteration. The historical relative_decrease offers + // a boost to a step which is not too bad compared to the + // reference iteration, allowing for non-monotonic steps. + iteration_summary.relative_decrease = + options.use_nonmonotonic_steps + ? max(relative_decrease, historical_relative_decrease) + : relative_decrease; + + iteration_summary.step_is_successful = + iteration_summary.relative_decrease > options_.min_relative_decrease; + + if (iteration_summary.step_is_successful) { + accumulated_candidate_model_cost_change += model_cost_change; + accumulated_reference_model_cost_change += model_cost_change; + if (relative_decrease <= options_.min_relative_decrease) { + VLOG(2) << "Non-monotonic step! " + << " relative_decrease: " << relative_decrease + << " historical_relative_decrease: " + << historical_relative_decrease; + } + } + } + + if (iteration_summary.step_is_successful) { + ++summary->num_successful_steps; + strategy->StepAccepted(iteration_summary.relative_decrease); + x = x_plus_delta; + x_norm = x.norm(); + + // Step looks good, evaluate the residuals and Jacobian at this + // point. + if (!evaluator->Evaluate(x.data(), + &cost, + residuals.data(), + NULL, + jacobian)) { + summary->termination_type = NUMERICAL_FAILURE; + LOG(WARNING) << "Terminating: Residual and Jacobian evaluation failed."; + return; + } + + gradient.setZero(); + jacobian->LeftMultiply(residuals.data(), gradient.data()); + iteration_summary.gradient_max_norm = gradient.lpNorm(); + + if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) { + summary->termination_type = GRADIENT_TOLERANCE; + VLOG(1) << "Terminating: Gradient tolerance reached." + << "Relative gradient max norm: " + << iteration_summary.gradient_max_norm / gradient_max_norm_0 + << " <= " << options_.gradient_tolerance; + return; + } + + if (options_.jacobi_scaling) { + jacobian->ScaleColumns(scale.data()); + } + + // Update the best, reference and candidate iterates. + // + // Based on algorithm 10.1.2 (page 357) of "Trust Region + // Methods" by Conn Gould & Toint, or equations 33-40 of + // "Non-monotone trust-region algorithms for nonlinear + // optimization subject to convex constraints" by Phil Toint, + // Mathematical Programming, 77, 1997. + if (cost < minimum_cost) { + // A step that improves solution quality was found. + x_min = x; + minimum_cost = cost; + // Set the candidate iterate to the current point. + candidate_cost = cost; + num_consecutive_nonmonotonic_steps = 0; + accumulated_candidate_model_cost_change = 0.0; + } else { + ++num_consecutive_nonmonotonic_steps; + if (cost > candidate_cost) { + // The current iterate is has a higher cost than the + // candidate iterate. Set the candidate to this point. + VLOG(2) << "Updating the candidate iterate to the current point."; + candidate_cost = cost; + accumulated_candidate_model_cost_change = 0.0; + } + + // At this point we have made too many non-monotonic steps and + // we are going to reset the value of the reference iterate so + // as to force the algorithm to descend. + // + // This is the case because the candidate iterate has a value + // greater than minimum_cost but smaller than the reference + // iterate. + if (num_consecutive_nonmonotonic_steps == + options.max_consecutive_nonmonotonic_steps) { + VLOG(2) << "Resetting the reference point to the candidate point"; + reference_cost = candidate_cost; + accumulated_reference_model_cost_change = + accumulated_candidate_model_cost_change; + } + } + } else { + ++summary->num_unsuccessful_steps; + if (iteration_summary.step_is_valid) { + strategy->StepRejected(iteration_summary.relative_decrease); + } else { + strategy->StepIsInvalid(); + } + } + + iteration_summary.cost = cost + summary->fixed_cost; + iteration_summary.trust_region_radius = strategy->Radius(); + if (iteration_summary.trust_region_radius < + options_.min_trust_region_radius) { + summary->termination_type = PARAMETER_TOLERANCE; + VLOG(1) << "Termination. Minimum trust region radius reached."; + return; + } + + iteration_summary.iteration_time_in_seconds = + time(NULL) - iteration_start_time; + iteration_summary.cumulative_time_in_seconds = time(NULL) - start_time + + summary->preprocessor_time_in_seconds; + summary->iterations.push_back(iteration_summary); + + switch (RunCallbacks(iteration_summary)) { + case SOLVER_TERMINATE_SUCCESSFULLY: + summary->termination_type = USER_SUCCESS; + VLOG(1) << "Terminating: User callback returned USER_SUCCESS."; + return; + case SOLVER_ABORT: + summary->termination_type = USER_ABORT; + VLOG(1) << "Terminating: User callback returned USER_ABORT."; + return; + case SOLVER_CONTINUE: + break; + default: + LOG(FATAL) << "Unknown type of user callback status"; + } + } +} + + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.h b/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.h new file mode 100644 index 00000000000..a4f5ba3674d --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.h @@ -0,0 +1,67 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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 Google Inc. 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. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_TRUST_REGION_MINIMIZER_H_ +#define CERES_INTERNAL_TRUST_REGION_MINIMIZER_H_ + +#include "ceres/minimizer.h" +#include "ceres/solver.h" +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +// Generic trust region minimization algorithm. The heavy lifting is +// done by a TrustRegionStrategy object passed in as one of the +// arguments to the Minimize method. +// +// For example usage, see SolverImpl::Minimize. +class TrustRegionMinimizer : public Minimizer { + public: + ~TrustRegionMinimizer() {} + virtual void Minimize(const Minimizer::Options& options, + double* parameters, + Solver::Summary* summary); + + private: + void Init(const Minimizer::Options& options); + void EstimateScale(const SparseMatrix& jacobian, double* scale) const; + CallbackReturnType RunCallbacks(const IterationSummary& iteration_summary); + bool MaybeDumpLinearLeastSquaresProblem( const int iteration, + const SparseMatrix* jacobian, + const double* residuals, + const double* step) const; + + Minimizer::Options options_; +}; + +} // namespace internal +} // namespace ceres +#endif // CERES_INTERNAL_TRUST_REGION_MINIMIZER_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.cc b/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.cc new file mode 100644 index 00000000000..89bc19d084b --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.cc @@ -0,0 +1,27 @@ +#include "ceres/trust_region_strategy.h" +#include "ceres/dogleg_strategy.h" +#include "ceres/levenberg_marquardt_strategy.h" + +namespace ceres { +namespace internal { + +TrustRegionStrategy::~TrustRegionStrategy() {} + +TrustRegionStrategy* TrustRegionStrategy::Create(const Options& options) { + switch (options.trust_region_strategy_type) { + case LEVENBERG_MARQUARDT: + return new LevenbergMarquardtStrategy(options); + case DOGLEG: + return new DoglegStrategy(options); + default: + LOG(FATAL) << "Unknown trust region strategy: " + << options.trust_region_strategy_type; + } + + LOG(FATAL) << "Unknown trust region strategy: " + << options.trust_region_strategy_type; + return NULL; +} + +} // namespace internal +} // namespace ceres diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.h b/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.h new file mode 100644 index 00000000000..391da97d5eb --- /dev/null +++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_strategy.h @@ -0,0 +1,148 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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 Google Inc. 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. +// +// Author: sameeragarwal@google.com (Sameer Agarwal) + +#ifndef CERES_INTERNAL_TRUST_REGION_STRATEGY_H_ +#define CERES_INTERNAL_TRUST_REGION_STRATEGY_H_ + +#include "ceres/types.h" + +namespace ceres { +namespace internal { + +class LinearSolver; +class SparseMatrix; + +// Interface for classes implementing various trust region strategies +// for nonlinear least squares problems. +// +// The object is expected to maintain and update a trust region +// radius, which it then uses to solve for the trust region step using +// the jacobian matrix and residual vector. +// +// Here the term trust region radius is used loosely, as the strategy +// is free to treat it as guidance and violate it as need be. e.g., +// the LevenbergMarquardtStrategy uses the inverse of the trust region +// radius to scale the damping term, which controls the step size, but +// does not set a hard limit on its size. +class TrustRegionStrategy { +public: + struct Options { + Options() + : trust_region_strategy_type(LEVENBERG_MARQUARDT), + initial_radius(1e4), + max_radius(1e32), + lm_min_diagonal(1e-6), + lm_max_diagonal(1e32), + dogleg_type(TRADITIONAL_DOGLEG) { + } + + TrustRegionStrategyType trust_region_strategy_type; + // Linear solver used for actually solving the trust region step. + LinearSolver* linear_solver; + double initial_radius; + double max_radius; + + // Minimum and maximum values of the diagonal damping matrix used + // by LevenbergMarquardtStrategy. The DoglegStrategy also uses + // these bounds to construct a regularizing diagonal to ensure + // that the Gauss-Newton step computation is of full rank. + double lm_min_diagonal; + double lm_max_diagonal; + + // Further specify which dogleg method to use + DoglegType dogleg_type; + }; + + // Per solve options. + struct PerSolveOptions { + // Forcing sequence for inexact solves. + double eta; + }; + + struct Summary { + Summary() + : residual_norm(0.0), + num_iterations(-1), + termination_type(FAILURE) { + } + + // If the trust region problem is, + // + // 1/2 x'Ax + b'x + c, + // + // then + // + // residual_norm = |Ax -b| + double residual_norm; + + // Number of iterations used by the linear solver. If a linear + // solver was not called (e.g., DogLegStrategy after an + // unsuccessful step), then this would be zero. + int num_iterations; + + // Status of the linear solver used to solve the Newton system. + LinearSolverTerminationType termination_type; + }; + + virtual ~TrustRegionStrategy(); + + // Use the current radius to solve for the trust region step. + virtual Summary ComputeStep(const PerSolveOptions& per_solve_options, + SparseMatrix* jacobian, + const double* residuals, + double* step) = 0; + + // Inform the strategy that the current step has been accepted, and + // that the ratio of the decrease in the non-linear objective to the + // decrease in the trust region model is step_quality. + virtual void StepAccepted(double step_quality) = 0; + + // Inform the strategy that the current step has been rejected, and + // that the ratio of the decrease in the non-linear objective to the + // decrease in the trust region model is step_quality. + virtual void StepRejected(double step_quality) = 0; + + // Inform the strategy that the current step has been rejected + // because it was found to be numerically invalid. + // StepRejected/StepAccepted will not be called for this step, and + // the strategy is free to do what it wants with this information. + virtual void StepIsInvalid() = 0; + + // Current trust region radius. + virtual double Radius() const = 0; + + // Factory. + static TrustRegionStrategy* Create(const Options& options); +}; + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_TRUST_REGION_STRATEGY_H_ diff --git a/extern/libmv/third_party/ceres/internal/ceres/types.cc b/extern/libmv/third_party/ceres/internal/ceres/types.cc index 860f8a43f37..05e573ff6d5 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/types.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/types.cc @@ -37,8 +37,9 @@ namespace ceres { const char* LinearSolverTypeToString(LinearSolverType solver_type) { switch (solver_type) { - CASESTR(SPARSE_NORMAL_CHOLESKY); + CASESTR(DENSE_NORMAL_CHOLESKY); CASESTR(DENSE_QR); + CASESTR(SPARSE_NORMAL_CHOLESKY); CASESTR(DENSE_SCHUR); CASESTR(SPARSE_SCHUR); CASESTR(ITERATIVE_SCHUR); @@ -61,6 +62,16 @@ const char* PreconditionerTypeToString( } } +const char* SparseLinearAlgebraLibraryTypeToString( + SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type) { + switch (sparse_linear_algebra_library_type) { + CASESTR(SUITE_SPARSE); + CASESTR(CX_SPARSE); + default: + return "UNKNOWN"; + } +} + const char* OrderingTypeToString(OrderingType ordering_type) { switch (ordering_type) { CASESTR(NATURAL); @@ -87,6 +98,28 @@ const char* SolverTerminationTypeToString( } } +#if 0 /* UNUSED */ +static const char* SparseLinearAlgebraTypeToString( + SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type) { + switch (sparse_linear_algebra_library_type) { + CASESTR(CX_SPARSE); + CASESTR(SUITE_SPARSE); + default: + return "UNKNOWN"; + } +} +#endif + +const char* TrustRegionStrategyTypeToString( + TrustRegionStrategyType trust_region_strategy_type) { + switch (trust_region_strategy_type) { + CASESTR(LEVENBERG_MARQUARDT); + CASESTR(DOGLEG); + default: + return "UNKNOWN"; + } +} + #undef CASESTR bool IsSchurType(LinearSolverType type) { diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility.cc b/extern/libmv/third_party/ceres/internal/ceres/visibility.cc index fd41648a7af..564cc54493e 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/visibility.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/visibility.cc @@ -34,11 +34,11 @@ #include #include #include - -#include #include "ceres/block_structure.h" #include "ceres/collections_port.h" +#include "ceres/visibility.h" #include "ceres/graph.h" +#include "glog/logging.h" namespace ceres { namespace internal { diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc index aca77528215..4caad03d7a1 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc +++ b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.cc @@ -33,11 +33,9 @@ #include #include #include -#include #include #include #include -#include #include "Eigen/Dense" #include "ceres/block_random_access_sparse_matrix.h" #include "ceres/block_sparse_matrix.h" @@ -46,10 +44,11 @@ #include "ceres/detect_structure.h" #include "ceres/graph.h" #include "ceres/graph_algorithms.h" +#include "ceres/internal/scoped_ptr.h" #include "ceres/linear_solver.h" #include "ceres/schur_eliminator.h" #include "ceres/visibility.h" -#include "ceres/internal/scoped_ptr.h" +#include "glog/logging.h" namespace ceres { namespace internal { @@ -253,7 +252,6 @@ void VisibilityBasedPreconditioner::ComputeBlockPairsInPreconditioner( } int r = 0; - set > skipped_pairs; const int num_row_blocks = bs.rows.size(); const int num_eliminate_blocks = options_.num_eliminate_blocks; @@ -304,8 +302,6 @@ void VisibilityBasedPreconditioner::ComputeBlockPairsInPreconditioner( for (; block2 != f_blocks.end(); ++block2) { if (IsBlockPairInPreconditioner(*block1, *block2)) { block_pairs_.insert(make_pair(*block1, *block2)); - } else { - skipped_pairs.insert(make_pair(*block1, *block2)); } } } @@ -322,17 +318,13 @@ void VisibilityBasedPreconditioner::ComputeBlockPairsInPreconditioner( if (block1 <= block2) { if (IsBlockPairInPreconditioner(block1, block2)) { block_pairs_.insert(make_pair(block1, block2)); - } else { - skipped_pairs.insert(make_pair(block1, block2)); } } } } } - VLOG(1) << "Block pair stats: " - << block_pairs_.size() << " included " - << skipped_pairs.size() << " excluded"; + VLOG(1) << "Block pair stats: " << block_pairs_.size(); } // Initialize the SchurEliminator. @@ -341,7 +333,6 @@ void VisibilityBasedPreconditioner::InitEliminator( LinearSolver::Options eliminator_options; eliminator_options.num_eliminate_blocks = options_.num_eliminate_blocks; eliminator_options.num_threads = options_.num_threads; - eliminator_options.constant_sparsity = true; DetectStructure(bs, options_.num_eliminate_blocks, &eliminator_options.row_block_size, @@ -352,9 +343,9 @@ void VisibilityBasedPreconditioner::InitEliminator( eliminator_->Init(options_.num_eliminate_blocks, &bs); } -// Compute the values of the preconditioner matrix and factorize it. -bool VisibilityBasedPreconditioner::Compute(const BlockSparseMatrixBase& A, - const double* D) { +// Update the values of the preconditioner matrix and factorize it. +bool VisibilityBasedPreconditioner::Update(const BlockSparseMatrixBase& A, + const double* D) { const time_t start_time = time(NULL); const int num_rows = m_->num_rows(); CHECK_GT(num_rows, 0); @@ -448,12 +439,21 @@ bool VisibilityBasedPreconditioner::Factorize() { // matrix contains the values. lhs->stype = 1; - // Symbolic factorization is computed if we don't already have one - // handy. + // Symbolic factorization is computed if we don't already have one handy. if (factor_ == NULL) { - factor_ = ss_.AnalyzeCholesky(lhs); + if (options_.use_block_amd) { + factor_ = ss_.BlockAnalyzeCholesky(lhs, block_size_, block_size_); + } else { + factor_ = ss_.AnalyzeCholesky(lhs); + } + + if (VLOG_IS_ON(2)) { + cholmod_print_common("Symbolic Analysis", ss_.mutable_cc()); + } } + CHECK_NOTNULL(factor_); + bool status = ss_.Cholesky(lhs, factor_); ss_.Free(lhs); return status; diff --git a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h index fa095ca1dd8..888c65eba3a 100644 --- a/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h +++ b/extern/libmv/third_party/ceres/internal/ceres/visibility_based_preconditioner.h @@ -133,7 +133,7 @@ class SchurEliminatorBase; // options.num_eliminate_blocks = num_points; // VisibilityBasedPreconditioner preconditioner( // *A.block_structure(), options); -// preconditioner.Compute(A, NULL); +// preconditioner.Update(A, NULL); // preconditioner.RightMultiply(x, y); // @@ -160,7 +160,7 @@ class VisibilityBasedPreconditioner : public LinearOperator { const LinearSolver::Options& options); virtual ~VisibilityBasedPreconditioner(); - // Compute the numerical value of the preconditioner for the linear + // Update the numerical value of the preconditioner for the linear // system: // // | A | x = |b| @@ -171,12 +171,12 @@ class VisibilityBasedPreconditioner : public LinearOperator { // // D can be NULL, in which case its interpreted as a diagonal matrix // of size zero. - bool Compute(const BlockSparseMatrixBase& A, - const double* D); + bool Update(const BlockSparseMatrixBase& A, const double* D); + // LinearOperator interface. Since the operator is symmetric, // LeftMultiply and num_cols are just calls to RightMultiply and - // num_rows respectively. Compute() must be called before + // num_rows respectively. Update() must be called before // RightMultiply can be called. virtual void RightMultiply(const double* x, double* y) const; virtual void LeftMultiply(const double* x, double* y) const { @@ -244,7 +244,7 @@ class VisibilityBasedPreconditioner : public LinearOperator { // Temporary vector used by RightMultiply. cholmod_dense* tmp_rhs_; - DISALLOW_COPY_AND_ASSIGN(VisibilityBasedPreconditioner); + CERES_DISALLOW_COPY_AND_ASSIGN(VisibilityBasedPreconditioner); }; #else // SuiteSparse // If SuiteSparse is not compiled in, the preconditioner is not @@ -261,7 +261,7 @@ class VisibilityBasedPreconditioner : public LinearOperator { virtual void LeftMultiply(const double* x, double* y) const {} virtual int num_rows() const { return -1; } virtual int num_cols() const { return -1; } - bool Compute(const BlockSparseMatrixBase& A, const double* D) { + bool Update(const BlockSparseMatrixBase& A, const double* D) { return false; } }; diff --git a/extern/libmv/third_party/ceres/patches/collections_port.h.mingw.patch b/extern/libmv/third_party/ceres/patches/collections_port.h.mingw.patch index bbb366e22bc..c01a17c7992 100644 --- a/extern/libmv/third_party/ceres/patches/collections_port.h.mingw.patch +++ b/extern/libmv/third_party/ceres/patches/collections_port.h.mingw.patch @@ -1,10 +1,10 @@ -Index: internal/ceres/collections_port.h -=================================================================== ---- internal/ceres/collections_port.h (revision 47730) -+++ internal/ceres/collections_port.h (working copy) -@@ -53,7 +53,7 @@ +diff --git a/internal/ceres/collections_port.h b/internal/ceres/collections_port.h +index a356cc0..c2fce90 100644 +--- a/internal/ceres/collections_port.h ++++ b/internal/ceres/collections_port.h +@@ -77,7 +77,7 @@ struct HashMap : std::tr1::unordered_map {}; template - struct HashSet : tr1::unordered_set {}; + struct HashSet : std::tr1::unordered_set {}; -#ifdef _WIN32 +#if defined(_WIN32) && !defined(__MINGW64__) && !defined(__MINGW32__) diff --git a/extern/libmv/third_party/ceres/patches/msvc_glog_fix.patch b/extern/libmv/third_party/ceres/patches/msvc_glog_fix.patch new file mode 100644 index 00000000000..f3200fb8e0a --- /dev/null +++ b/extern/libmv/third_party/ceres/patches/msvc_glog_fix.patch @@ -0,0 +1,50 @@ +diff --git a/internal/ceres/block_random_access_dense_matrix.cc b/internal/ceres/block_random_access_dense_matrix.cc +index aedfc74..0f95e89 100644 +--- a/internal/ceres/block_random_access_dense_matrix.cc ++++ b/internal/ceres/block_random_access_dense_matrix.cc +@@ -28,12 +28,12 @@ + // + // Author: sameeragarwal@google.com (Sameer Agarwal) + ++#include "glog/logging.h" + #include "ceres/block_random_access_dense_matrix.h" + + #include + #include "ceres/internal/eigen.h" + #include "ceres/internal/scoped_ptr.h" +-#include "glog/logging.h" + + namespace ceres { + namespace internal { +diff --git a/internal/ceres/block_random_access_sparse_matrix.cc b/internal/ceres/block_random_access_sparse_matrix.cc +index f789436..9ed62ce 100644 +--- a/internal/ceres/block_random_access_sparse_matrix.cc ++++ b/internal/ceres/block_random_access_sparse_matrix.cc +@@ -28,6 +28,7 @@ + // + // Author: sameeragarwal@google.com (Sameer Agarwal) + ++#include "glog/logging.h" + #include "ceres/block_random_access_sparse_matrix.h" + + #include +@@ -39,7 +40,6 @@ + #include "ceres/mutex.h" + #include "ceres/triplet_sparse_matrix.h" + #include "ceres/types.h" +-#include "glog/logging.h" + + namespace ceres { + namespace internal { +diff --git a/internal/ceres/schur_complement_solver.cc b/internal/ceres/schur_complement_solver.cc +index b9224d8..2cbe78d 100644 +--- a/internal/ceres/schur_complement_solver.cc ++++ b/internal/ceres/schur_complement_solver.cc +@@ -38,6 +38,7 @@ + #endif // CERES_NO_CXSPARSE + + #include "Eigen/Dense" ++#include "glog/logging.h" + #include "ceres/block_random_access_dense_matrix.h" + #include "ceres/block_random_access_matrix.h" + #include "ceres/block_random_access_sparse_matrix.h" diff --git a/extern/libmv/third_party/ceres/patches/msvc_isfinite.patch b/extern/libmv/third_party/ceres/patches/msvc_isfinite.patch deleted file mode 100644 index c3129d8e02b..00000000000 --- a/extern/libmv/third_party/ceres/patches/msvc_isfinite.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/internal/ceres/residual_block_utils.cc b/internal/ceres/residual_block_utils.cc -index ed3499b..28e0313 100644 ---- a/internal/ceres/residual_block_utils.cc -+++ b/internal/ceres/residual_block_utils.cc -@@ -40,6 +40,10 @@ - #include "ceres/internal/eigen.h" - #include "ceres/internal/port.h" - -+#ifdef _MSC_VER -+# define isfinite _finite -+#endif -+ - namespace ceres { - namespace internal { - diff --git a/extern/libmv/third_party/ceres/patches/no_previous_declaration_fix.patch b/extern/libmv/third_party/ceres/patches/no_previous_declaration_fix.patch new file mode 100644 index 00000000000..03f1c500d9a --- /dev/null +++ b/extern/libmv/third_party/ceres/patches/no_previous_declaration_fix.patch @@ -0,0 +1,199 @@ +diff --git a/internal/ceres/file.cc b/internal/ceres/file.cc +index 387f359..6fe7557 100644 +--- a/internal/ceres/file.cc ++++ b/internal/ceres/file.cc +@@ -31,6 +31,7 @@ + // Really simple file IO. + + #include ++#include "file.h" + #include "glog/logging.h" + + namespace ceres { +diff --git a/internal/ceres/linear_least_squares_problems.cc b/internal/ceres/linear_least_squares_problems.cc +index 3e3bcd0..a91e254 100644 +--- a/internal/ceres/linear_least_squares_problems.cc ++++ b/internal/ceres/linear_least_squares_problems.cc +@@ -573,13 +573,13 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem3() { + return problem; + } + +-bool DumpLinearLeastSquaresProblemToConsole(const string& directory, +- int iteration, +- const SparseMatrix* A, +- const double* D, +- const double* b, +- const double* x, +- int num_eliminate_blocks) { ++static bool DumpLinearLeastSquaresProblemToConsole(const string& directory, ++ int iteration, ++ const SparseMatrix* A, ++ const double* D, ++ const double* b, ++ const double* x, ++ int num_eliminate_blocks) { + CHECK_NOTNULL(A); + Matrix AA; + A->ToDenseMatrix(&AA); +@@ -601,13 +601,13 @@ bool DumpLinearLeastSquaresProblemToConsole(const string& directory, + }; + + #ifndef CERES_NO_PROTOCOL_BUFFERS +-bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory, +- int iteration, +- const SparseMatrix* A, +- const double* D, +- const double* b, +- const double* x, +- int num_eliminate_blocks) { ++static bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory, ++ int iteration, ++ const SparseMatrix* A, ++ const double* D, ++ const double* b, ++ const double* x, ++ int num_eliminate_blocks) { + CHECK_NOTNULL(A); + LinearLeastSquaresProblemProto lsqp; + A->ToProto(lsqp.mutable_a()); +@@ -641,13 +641,13 @@ bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory, + return true; + } + #else +-bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory, +- int iteration, +- const SparseMatrix* A, +- const double* D, +- const double* b, +- const double* x, +- int num_eliminate_blocks) { ++static bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory, ++ int iteration, ++ const SparseMatrix* A, ++ const double* D, ++ const double* b, ++ const double* x, ++ int num_eliminate_blocks) { + LOG(ERROR) << "Dumping least squares problems is only " + << "supported when Ceres is compiled with " + << "protocol buffer support."; +@@ -655,9 +655,9 @@ bool DumpLinearLeastSquaresProblemToProtocolBuffer(const string& directory, + } + #endif + +-void WriteArrayToFileOrDie(const string& filename, +- const double* x, +- const int size) { ++static void WriteArrayToFileOrDie(const string& filename, ++ const double* x, ++ const int size) { + CHECK_NOTNULL(x); + VLOG(2) << "Writing array to: " << filename; + FILE* fptr = fopen(filename.c_str(), "w"); +@@ -668,13 +668,13 @@ void WriteArrayToFileOrDie(const string& filename, + fclose(fptr); + } + +-bool DumpLinearLeastSquaresProblemToTextFile(const string& directory, +- int iteration, +- const SparseMatrix* A, +- const double* D, +- const double* b, +- const double* x, +- int num_eliminate_blocks) { ++static bool DumpLinearLeastSquaresProblemToTextFile(const string& directory, ++ int iteration, ++ const SparseMatrix* A, ++ const double* D, ++ const double* b, ++ const double* x, ++ int num_eliminate_blocks) { + CHECK_NOTNULL(A); + string format_string = JoinPath(directory, + "lm_iteration_%03d"); +diff --git a/internal/ceres/residual_block_utils.cc b/internal/ceres/residual_block_utils.cc +index ff18e21..9442bb2 100644 +--- a/internal/ceres/residual_block_utils.cc ++++ b/internal/ceres/residual_block_utils.cc +@@ -63,7 +63,7 @@ void InvalidateEvaluation(const ResidualBlock& block, + + // Utility routine to print an array of doubles to a string. If the + // array pointer is NULL, it is treated as an array of zeros. +-void AppendArrayToString(const int size, const double* x, string* result) { ++static void AppendArrayToString(const int size, const double* x, string* result) { + for (int i = 0; i < size; ++i) { + if (x == NULL) { + StringAppendF(result, "Not Computed "); +diff --git a/internal/ceres/solver_impl.cc b/internal/ceres/solver_impl.cc +index 2802a75..8ef5b98 100644 +--- a/internal/ceres/solver_impl.cc ++++ b/internal/ceres/solver_impl.cc +@@ -685,8 +685,8 @@ bool SolverImpl::ApplyUserOrdering(const ProblemImpl& problem_impl, + // Find the minimum index of any parameter block to the given residual. + // Parameter blocks that have indices greater than num_eliminate_blocks are + // considered to have an index equal to num_eliminate_blocks. +-int MinParameterBlock(const ResidualBlock* residual_block, +- int num_eliminate_blocks) { ++static int MinParameterBlock(const ResidualBlock* residual_block, ++ int num_eliminate_blocks) { + int min_parameter_block_position = num_eliminate_blocks; + for (int i = 0; i < residual_block->NumParameterBlocks(); ++i) { + ParameterBlock* parameter_block = residual_block->parameter_blocks()[i]; +diff --git a/internal/ceres/split.cc b/internal/ceres/split.cc +index 4fa1bd4..c65c8a5 100644 +--- a/internal/ceres/split.cc ++++ b/internal/ceres/split.cc +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include "ceres/split.h" + #include "ceres/internal/port.h" + + namespace ceres { +diff --git a/internal/ceres/stringprintf.cc b/internal/ceres/stringprintf.cc +index c0f3522..396a48b 100644 +--- a/internal/ceres/stringprintf.cc ++++ b/internal/ceres/stringprintf.cc +@@ -34,6 +34,7 @@ + #include + #include + ++#include "ceres/stringprintf.h" + #include "ceres/internal/port.h" + + namespace ceres { +diff --git a/internal/ceres/types.cc b/internal/ceres/types.cc +index 2e950c5..05e573f 100644 +--- a/internal/ceres/types.cc ++++ b/internal/ceres/types.cc +@@ -98,7 +98,8 @@ const char* SolverTerminationTypeToString( + } + } + +-const char* SparseLinearAlgebraTypeToString( ++#if 0 /* UNUSED */ ++static const char* SparseLinearAlgebraTypeToString( + SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type) { + switch (sparse_linear_algebra_library_type) { + CASESTR(CX_SPARSE); +@@ -107,6 +108,7 @@ const char* SparseLinearAlgebraTypeToString( + return "UNKNOWN"; + } + } ++#endif + + const char* TrustRegionStrategyTypeToString( + TrustRegionStrategyType trust_region_strategy_type) { +diff --git a/internal/ceres/visibility.cc b/internal/ceres/visibility.cc +index 9d80654..564cc54 100644 +--- a/internal/ceres/visibility.cc ++++ b/internal/ceres/visibility.cc +@@ -36,6 +36,7 @@ + #include + #include "ceres/block_structure.h" + #include "ceres/collections_port.h" ++#include "ceres/visibility.h" + #include "ceres/graph.h" + #include "glog/logging.h" + diff --git a/extern/libmv/third_party/ceres/patches/series b/extern/libmv/third_party/ceres/patches/series index dbe955ae61e..a6874318923 100644 --- a/extern/libmv/third_party/ceres/patches/series +++ b/extern/libmv/third_party/ceres/patches/series @@ -1 +1,3 @@ -msvc_isfinite.patch +collections_port.h.mingw.patch +msvc_glog_fix.patch +no_previous_declaration_fix.patch \ No newline at end of file diff --git a/extern/recastnavigation/Recast/Source/RecastMeshDetail.cpp b/extern/recastnavigation/Recast/Source/RecastMeshDetail.cpp index 130c08ec369..b52da597675 100644 --- a/extern/recastnavigation/Recast/Source/RecastMeshDetail.cpp +++ b/extern/recastnavigation/Recast/Source/RecastMeshDetail.cpp @@ -1015,7 +1015,7 @@ bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompa maxhh = rcMax(maxhh, ymax-ymin); } - hp.data = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxhw*maxhh, RC_ALLOC_TEMP); + hp.data = (unsigned short *)rcAlloc(sizeof(unsigned short)*maxhw*maxhh, RC_ALLOC_TEMP); if (!hp.data) { ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'hp.data' (%d).", maxhw*maxhh); diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt index 2551df6ba76..cb2fc239859 100644 --- a/intern/CMakeLists.txt +++ b/intern/CMakeLists.txt @@ -49,11 +49,6 @@ if(WITH_MOD_SMOKE) add_subdirectory(smoke) endif() -if(WITH_MOD_DECIMATE) - add_subdirectory(container) - add_subdirectory(decimation) -endif() - if(WITH_MOD_BOOLEAN) add_subdirectory(bsp) endif() diff --git a/intern/SConscript b/intern/SConscript index 3e40ef38705..59e412333b0 100644 --- a/intern/SConscript +++ b/intern/SConscript @@ -6,9 +6,7 @@ SConscript(['audaspace/SConscript', 'ghost/SConscript', 'guardedalloc/SConscript', 'moto/SConscript', - 'container/SConscript', 'memutil/SConscript/', - 'decimation/SConscript', 'iksolver/SConscript', 'itasc/SConscript', 'opencolorio/SConscript', @@ -17,6 +15,9 @@ SConscript(['audaspace/SConscript', 'smoke/SConscript', 'raskter/SConscript']) +# currently only contains headers +# SConscript('container/SConscript') + if env ['WITH_BF_REMESH']: SConscript(['dualcon/SConscript']) diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt index dc4ca7903cd..1671194653a 100644 --- a/intern/audaspace/CMakeLists.txt +++ b/intern/audaspace/CMakeLists.txt @@ -94,6 +94,7 @@ set(SRC intern/AUD_IDevice.h intern/AUD_IFactory.h intern/AUD_IHandle.h + intern/AUD_ILockable.h intern/AUD_IReader.h intern/AUD_IWriter.h intern/AUD_JOSResampleFactory.cpp @@ -108,6 +109,7 @@ set(SRC intern/AUD_Mixer.h intern/AUD_MixerFactory.cpp intern/AUD_MixerFactory.h + intern/AUD_MutexLock.h intern/AUD_NULLDevice.cpp intern/AUD_NULLDevice.h intern/AUD_PyInit.h diff --git a/intern/audaspace/FX/AUD_ButterworthFactory.cpp b/intern/audaspace/FX/AUD_ButterworthFactory.cpp index 5edca302ece..af1a5af97df 100644 --- a/intern/audaspace/FX/AUD_ButterworthFactory.cpp +++ b/intern/audaspace/FX/AUD_ButterworthFactory.cpp @@ -53,11 +53,11 @@ void AUD_ButterworthFactory::recalculateCoefficients(AUD_SampleRate rate, float omega = 2 * tan(m_frequency * M_PI / rate); float o2 = omega * omega; float o4 = o2 * o2; - float x1 = o2 + 2 * BWPB41 * omega + 4; - float x2 = o2 + 2 * BWPB42 * omega + 4; - float y1 = o2 - 2 * BWPB41 * omega + 4; - float y2 = o2 - 2 * BWPB42 * omega + 4; - float o228 = 2 * o2 - 8; + float x1 = o2 + 2.0f * (float)BWPB41 * omega + 4.0f; + float x2 = o2 + 2.0f * (float)BWPB42 * omega + 4.0f; + float y1 = o2 - 2.0f * (float)BWPB41 * omega + 4.0f; + float y2 = o2 - 2.0f * (float)BWPB42 * omega + 4.0f; + float o228 = 2.0f * o2 - 8.0f; float norm = x1 * x2; a.push_back(1); a.push_back((x1 + x2) * o228 / norm); diff --git a/intern/audaspace/FX/AUD_DelayReader.cpp b/intern/audaspace/FX/AUD_DelayReader.cpp index 903e043af01..0e9833cd07f 100644 --- a/intern/audaspace/FX/AUD_DelayReader.cpp +++ b/intern/audaspace/FX/AUD_DelayReader.cpp @@ -33,8 +33,8 @@ AUD_DelayReader::AUD_DelayReader(AUD_Reference reader, float delay) : AUD_EffectReader(reader), - m_delay(int(delay * reader->getSpecs().rate)), - m_remdelay(int(delay * reader->getSpecs().rate)) + m_delay(int((AUD_SampleRate)delay * reader->getSpecs().rate)), + m_remdelay(int((AUD_SampleRate)delay * reader->getSpecs().rate)) { } diff --git a/intern/audaspace/FX/AUD_HighpassFactory.cpp b/intern/audaspace/FX/AUD_HighpassFactory.cpp index 41070842596..b56be8942ff 100644 --- a/intern/audaspace/FX/AUD_HighpassFactory.cpp +++ b/intern/audaspace/FX/AUD_HighpassFactory.cpp @@ -48,8 +48,8 @@ void AUD_HighpassFactory::recalculateCoefficients(AUD_SampleRate rate, std::vector &b, std::vector &a) { - float w0 = 2 * M_PI * m_frequency / rate; - float alpha = sin(w0) / (2 * m_Q); + float w0 = 2.0 * M_PI * (AUD_SampleRate)m_frequency / rate; + float alpha = (float)(sin(w0) / (2.0 * (double)m_Q)); float norm = 1 + alpha; float c = cos(w0); a.push_back(1); diff --git a/intern/audaspace/FX/AUD_IIRFilterReader.cpp b/intern/audaspace/FX/AUD_IIRFilterReader.cpp index 06880818692..8f78c110d1f 100644 --- a/intern/audaspace/FX/AUD_IIRFilterReader.cpp +++ b/intern/audaspace/FX/AUD_IIRFilterReader.cpp @@ -34,7 +34,7 @@ AUD_IIRFilterReader::AUD_IIRFilterReader(AUD_Reference reader, const std::vector& a) : AUD_BaseIIRFilterReader(reader, b.size(), a.size()), m_a(a), m_b(b) { - if(m_a.size()) + if(m_a.empty() == false) { for(int i = 1; i < m_a.size(); i++) m_a[i] /= m_a[0]; diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp index c3f3f46d188..a114d8b8a87 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp @@ -31,6 +31,7 @@ #include "AUD_IFactory.h" #include "AUD_IReader.h" #include "AUD_ConverterReader.h" +#include "AUD_MutexLock.h" #include #include @@ -125,7 +126,7 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::pause() { if(m_status) { - m_device->lock(); + AUD_MutexLock lock(*m_device); if(m_status == AUD_STATUS_PLAYING) { @@ -135,12 +136,9 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::pause() alSourcePause(m_source); m_status = AUD_STATUS_PAUSED; - m_device->unlock(); return true; } - - m_device->unlock(); } return false; @@ -150,7 +148,7 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::resume() { if(m_status) { - m_device->lock(); + AUD_MutexLock lock(*m_device); if(m_status == AUD_STATUS_PAUSED) { @@ -159,11 +157,8 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::resume() m_device->start(); m_status = AUD_STATUS_PLAYING; - m_device->unlock(); return true; } - - m_device->unlock(); } return false; @@ -174,25 +169,39 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::stop() if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - // AUD_XXX Create a reference of our own object so that it doesn't get - // deleted before the end of this function - AUD_Reference This = this; + if(!m_status) + return false; - if(m_status == AUD_STATUS_PLAYING) - m_device->m_playingSounds.remove(This); - else - m_device->m_pausedSounds.remove(This); - - m_device->unlock(); + m_status = AUD_STATUS_INVALID; alDeleteSources(1, &m_source); if(!m_isBuffered) alDeleteBuffers(CYCLE_BUFFERS, m_buffers); - m_status = AUD_STATUS_INVALID; - return true; + for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++) + { + if(it->get() == this) + { + AUD_Reference This = *it; + + m_device->m_playingSounds.erase(it); + + return true; + } + } + + for(AUD_HandleIterator it = m_device->m_pausedSounds.begin(); it != m_device->m_pausedSounds.end(); it++) + { + if(it->get() == this) + { + m_device->m_pausedSounds.erase(it); + return true; + } + } + + return false; } bool AUD_OpenALDevice::AUD_OpenALHandle::getKeep() @@ -208,12 +217,13 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setKeep(bool keep) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; m_keep = keep; - m_device->unlock(); - return true; } @@ -222,7 +232,10 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::seek(float position) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; if(m_isBuffered) alSourcef(m_source, AL_SEC_OFFSET, position); @@ -272,17 +285,18 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::seek(float position) } } - m_device->unlock(); - return true; } float AUD_OpenALDevice::AUD_OpenALHandle::getPosition() { if(!m_status) - return 0.0f; + return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return 0.0f; float position = 0.0f; @@ -295,8 +309,6 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getPosition() CYCLE_BUFFERS) / (float)specs.rate; } - m_device->unlock(); - return position; } @@ -309,15 +321,16 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getVolume() { float result = std::numeric_limits::quiet_NaN(); + if(!m_status) + return false; + + AUD_MutexLock lock(*m_device); + if(!m_status) return result; - m_device->lock(); - alGetSourcef(m_source, AL_GAIN, &result); - m_device->unlock(); - return result; } @@ -326,12 +339,13 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setVolume(float volume) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; alSourcef(m_source, AL_GAIN, volume); - m_device->unlock(); - return true; } @@ -339,15 +353,16 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getPitch() { float result = std::numeric_limits::quiet_NaN(); + if(!m_status) + return false; + + AUD_MutexLock lock(*m_device); + if(!m_status) return result; - m_device->lock(); - alGetSourcef(m_source, AL_PITCH, &result); - m_device->unlock(); - return result; } @@ -356,12 +371,13 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setPitch(float pitch) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; alSourcef(m_source, AL_PITCH, pitch); - m_device->unlock(); - return true; } @@ -385,13 +401,14 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setStopCallback(stopCallback callback, if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; m_stop = callback; m_stop_data = data; - m_device->unlock(); - return true; } @@ -404,15 +421,16 @@ AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceLocation() AUD_Vector3 result = AUD_Vector3(0, 0, 0); if(!m_status) - return result; + return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return result; ALfloat p[3]; alGetSourcefv(m_source, AL_POSITION, p); - m_device->unlock(); - result = AUD_Vector3(p[0], p[1], p[2]); return result; @@ -423,12 +441,13 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceLocation(const AUD_Vector3& lo if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; alSourcefv(m_source, AL_POSITION, (ALfloat*)location.get()); - m_device->unlock(); - return true; } @@ -437,15 +456,16 @@ AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceVelocity() AUD_Vector3 result = AUD_Vector3(0, 0, 0); if(!m_status) - return result; + return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return result; ALfloat v[3]; alGetSourcefv(m_source, AL_VELOCITY, v); - m_device->unlock(); - result = AUD_Vector3(v[0], v[1], v[2]); return result; @@ -456,12 +476,13 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceVelocity(const AUD_Vector3& ve if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; alSourcefv(m_source, AL_VELOCITY, (ALfloat*)velocity.get()); - m_device->unlock(); - return true; } @@ -472,9 +493,6 @@ AUD_Quaternion AUD_OpenALDevice::AUD_OpenALHandle::getSourceOrientation() bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceOrientation(const AUD_Quaternion& orientation) { - if(!m_status) - return false; - ALfloat direction[3]; direction[0] = -2 * (orientation.w() * orientation.y() + orientation.x() * orientation.z()); @@ -482,12 +500,17 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceOrientation(const AUD_Quaterni orientation.z() * orientation.y()); direction[2] = 2 * (orientation.x() * orientation.x() + orientation.y() * orientation.y()) - 1; - m_device->lock(); + + if(!m_status) + return false; + + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; alSourcefv(m_source, AL_DIRECTION, direction); - m_device->unlock(); - m_orientation = orientation; return true; @@ -500,12 +523,13 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::isRelative() if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; alGetSourcei(m_source, AL_SOURCE_RELATIVE, &result); - m_device->unlock(); - return result; } @@ -514,12 +538,13 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setRelative(bool relative) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; alSourcei(m_source, AL_SOURCE_RELATIVE, relative); - m_device->unlock(); - return true; } @@ -527,15 +552,16 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMaximum() { float result = std::numeric_limits::quiet_NaN(); + if(!m_status) + return false; + + AUD_MutexLock lock(*m_device); + if(!m_status) return result; - m_device->lock(); - alGetSourcef(m_source, AL_MAX_GAIN, &result); - m_device->unlock(); - return result; } @@ -544,12 +570,13 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMaximum(float volume) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; alSourcef(m_source, AL_MAX_GAIN, volume); - m_device->unlock(); - return true; } @@ -557,15 +584,16 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMinimum() { float result = std::numeric_limits::quiet_NaN(); + if(!m_status) + return false; + + AUD_MutexLock lock(*m_device); + if(!m_status) return result; - m_device->lock(); - alGetSourcef(m_source, AL_MIN_GAIN, &result); - m_device->unlock(); - return result; } @@ -574,12 +602,13 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMinimum(float volume) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; alSourcef(m_source, AL_MIN_GAIN, volume); - m_device->unlock(); - return true; } @@ -587,15 +616,16 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceMaximum() { float result = std::numeric_limits::quiet_NaN(); + if(!m_status) + return false; + + AUD_MutexLock lock(*m_device); + if(!m_status) return result; - m_device->lock(); - alGetSourcef(m_source, AL_MAX_DISTANCE, &result); - m_device->unlock(); - return result; } @@ -604,12 +634,13 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceMaximum(float distance) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; alSourcef(m_source, AL_MAX_DISTANCE, distance); - m_device->unlock(); - return true; } @@ -617,15 +648,16 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceReference() { float result = std::numeric_limits::quiet_NaN(); + if(!m_status) + return false; + + AUD_MutexLock lock(*m_device); + if(!m_status) return result; - m_device->lock(); - alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &result); - m_device->unlock(); - return result; } @@ -634,12 +666,13 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceReference(float distance) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; alSourcef(m_source, AL_REFERENCE_DISTANCE, distance); - m_device->unlock(); - return true; } @@ -647,15 +680,16 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getAttenuation() { float result = std::numeric_limits::quiet_NaN(); + if(!m_status) + return false; + + AUD_MutexLock lock(*m_device); + if(!m_status) return result; - m_device->lock(); - alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &result); - m_device->unlock(); - return result; } @@ -664,12 +698,13 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setAttenuation(float factor) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; alSourcef(m_source, AL_ROLLOFF_FACTOR, factor); - m_device->unlock(); - return true; } @@ -677,15 +712,16 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleOuter() { float result = std::numeric_limits::quiet_NaN(); + if(!m_status) + return false; + + AUD_MutexLock lock(*m_device); + if(!m_status) return result; - m_device->lock(); - alGetSourcef(m_source, AL_CONE_OUTER_ANGLE, &result); - m_device->unlock(); - return result; } @@ -694,12 +730,13 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleOuter(float angle) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; alSourcef(m_source, AL_CONE_OUTER_ANGLE, angle); - m_device->unlock(); - return true; } @@ -707,15 +744,16 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleInner() { float result = std::numeric_limits::quiet_NaN(); + if(!m_status) + return false; + + AUD_MutexLock lock(*m_device); + if(!m_status) return result; - m_device->lock(); - alGetSourcef(m_source, AL_CONE_INNER_ANGLE, &result); - m_device->unlock(); - return result; } @@ -724,12 +762,13 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleInner(float angle) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; alSourcef(m_source, AL_CONE_INNER_ANGLE, angle); - m_device->unlock(); - return true; } @@ -737,15 +776,16 @@ float AUD_OpenALDevice::AUD_OpenALHandle::getConeVolumeOuter() { float result = std::numeric_limits::quiet_NaN(); + if(!m_status) + return false; + + AUD_MutexLock lock(*m_device); + if(!m_status) return result; - m_device->lock(); - alGetSourcef(m_source, AL_CONE_OUTER_GAIN, &result); - m_device->unlock(); - return result; } @@ -754,12 +794,13 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setConeVolumeOuter(float volume) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; alSourcef(m_source, AL_CONE_OUTER_GAIN, volume); - m_device->unlock(); - return true; } @@ -767,7 +808,7 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::setConeVolumeOuter(float volume) /**************************** Threading Code **********************************/ /******************************************************************************/ -void* AUD_openalRunThread(void* device) +static void *AUD_openalRunThread(void *device) { AUD_OpenALDevice* dev = (AUD_OpenALDevice*)device; dev->updateStreams(); @@ -776,7 +817,7 @@ void* AUD_openalRunThread(void* device) void AUD_OpenALDevice::start(bool join) { - lock(); + AUD_MutexLock lock(*this); if(!m_playing) { @@ -793,8 +834,6 @@ void AUD_OpenALDevice::start(bool join) m_playing = true; } - - unlock(); } void AUD_OpenALDevice::updateStreams() @@ -970,7 +1009,6 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) { // cannot determine how many channels or which format OpenAL uses, but // it at least is able to play 16 bit stereo audio - specs.channels = AUD_CHANNELS_STEREO; specs.format = AUD_FORMAT_S16; #if 0 @@ -993,7 +1031,7 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) AUD_THROW(AUD_ERROR_OPENAL, open_error); // at least try to set the frequency - ALCint attribs[] = { ALC_FREQUENCY, specs.rate, 0 }; + ALCint attribs[] = { ALC_FREQUENCY, (ALCint)specs.rate, 0 }; ALCint* attributes = attribs; if(specs.rate == AUD_RATE_INVALID) attributes = NULL; @@ -1009,6 +1047,11 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE; + if((!m_useMC && specs.channels > AUD_CHANNELS_STEREO) || + specs.channels == AUD_CHANNELS_STEREO_LFE || + specs.channels == AUD_CHANNELS_SURROUND5) + specs.channels = AUD_CHANNELS_STEREO; + alGetError(); alcGetError(m_device); @@ -1177,7 +1220,8 @@ AUD_Reference AUD_OpenALDevice::play(AUD_Reference rea if(!getFormat(format, specs)) return AUD_Reference(); - lock(); + AUD_MutexLock lock(*this); + alcSuspendContext(m_context); AUD_Reference sound; @@ -1190,7 +1234,6 @@ AUD_Reference AUD_OpenALDevice::play(AUD_Reference rea catch(AUD_Exception&) { alcProcessContext(m_context); - unlock(); throw; } @@ -1201,8 +1244,6 @@ AUD_Reference AUD_OpenALDevice::play(AUD_Reference rea start(); - unlock(); - return AUD_Reference(sound); } @@ -1285,7 +1326,8 @@ AUD_Reference AUD_OpenALDevice::play(AUD_Reference fa void AUD_OpenALDevice::stopAll() { - lock(); + AUD_MutexLock lock(*this); + alcSuspendContext(m_context); while(!m_playingSounds.empty()) @@ -1295,7 +1337,6 @@ void AUD_OpenALDevice::stopAll() m_pausedSounds.front()->stop(); alcProcessContext(m_context); - unlock(); } void AUD_OpenALDevice::lock() diff --git a/intern/audaspace/Python/AUD_PyAPI.cpp b/intern/audaspace/Python/AUD_PyAPI.cpp index 238249bc7c8..dd58e5a7398 100644 --- a/intern/audaspace/Python/AUD_PyAPI.cpp +++ b/intern/audaspace/Python/AUD_PyAPI.cpp @@ -80,7 +80,7 @@ typedef enum // ==================================================================== -static PyObject* AUDError; +static PyObject *AUDError; static const char* device_not_3d_error = "Device is not a 3D device!"; @@ -92,7 +92,7 @@ Factory_dealloc(Factory* self) if(self->factory) delete reinterpret_cast*>(self->factory); Py_XDECREF(self->child_list); - Py_TYPE(self)->tp_free((PyObject*)self); + Py_TYPE(self)->tp_free((PyObject *)self); } static PyObject * @@ -139,7 +139,7 @@ PyDoc_STRVAR(M_aud_Factory_sine_doc, ":rtype: :class:`Factory`"); static PyObject * -Factory_sine(PyTypeObject* type, PyObject* args) +Factory_sine(PyTypeObject* type, PyObject *args) { float frequency; double rate = 44100; @@ -179,7 +179,7 @@ PyDoc_STRVAR(M_aud_Factory_file_doc, "playback of that factory."); static PyObject * -Factory_file(PyTypeObject* type, PyObject* args) +Factory_file(PyTypeObject* type, PyObject *args) { const char* filename = NULL; @@ -218,7 +218,7 @@ PyDoc_STRVAR(M_aud_Factory_lowpass_doc, ":rtype: :class:`Factory`"); static PyObject * -Factory_lowpass(Factory* self, PyObject* args) +Factory_lowpass(Factory* self, PyObject *args) { float frequency; float Q = 0.5; @@ -232,7 +232,7 @@ Factory_lowpass(Factory* self, PyObject* args) if(parent != NULL) { Py_INCREF(self); - parent->child_list = (PyObject*)self; + parent->child_list = (PyObject *)self; try { @@ -260,7 +260,7 @@ PyDoc_STRVAR(M_aud_Factory_delay_doc, ":rtype: :class:`Factory`"); static PyObject * -Factory_delay(Factory* self, PyObject* args) +Factory_delay(Factory* self, PyObject *args) { float delay; @@ -273,7 +273,7 @@ Factory_delay(Factory* self, PyObject* args) if(parent != NULL) { Py_INCREF(self); - parent->child_list = (PyObject*)self; + parent->child_list = (PyObject *)self; try { @@ -301,7 +301,7 @@ PyDoc_STRVAR(M_aud_Factory_join_doc, "(channels and samplerate)."); static PyObject * -Factory_join(Factory* self, PyObject* object) +Factory_join(Factory* self, PyObject *object) { PyTypeObject* type = Py_TYPE(self); @@ -346,7 +346,7 @@ PyDoc_STRVAR(M_aud_Factory_highpass_doc, ":rtype: :class:`Factory`"); static PyObject * -Factory_highpass(Factory* self, PyObject* args) +Factory_highpass(Factory* self, PyObject *args) { float frequency; float Q = 0.5; @@ -360,7 +360,7 @@ Factory_highpass(Factory* self, PyObject* args) if(parent != NULL) { Py_INCREF(self); - parent->child_list = (PyObject*)self; + parent->child_list = (PyObject *)self; try { @@ -388,7 +388,7 @@ PyDoc_STRVAR(M_aud_Factory_limit_doc, ":rtype: :class:`Factory`"); static PyObject * -Factory_limit(Factory* self, PyObject* args) +Factory_limit(Factory* self, PyObject *args) { float start, end; @@ -401,7 +401,7 @@ Factory_limit(Factory* self, PyObject* args) if(parent != NULL) { Py_INCREF(self); - parent->child_list = (PyObject*)self; + parent->child_list = (PyObject *)self; try { @@ -432,7 +432,7 @@ PyDoc_STRVAR(M_aud_Factory_pitch_doc, ":attr:`Handle.pitch` instead."); static PyObject * -Factory_pitch(Factory* self, PyObject* args) +Factory_pitch(Factory* self, PyObject *args) { float factor; @@ -445,7 +445,7 @@ Factory_pitch(Factory* self, PyObject* args) if(parent != NULL) { Py_INCREF(self); - parent->child_list = (PyObject*)self; + parent->child_list = (PyObject *)self; try { @@ -474,7 +474,7 @@ PyDoc_STRVAR(M_aud_Factory_volume_doc, ":attr:`Handle.volume` instead."); static PyObject * -Factory_volume(Factory* self, PyObject* args) +Factory_volume(Factory* self, PyObject *args) { float volume; @@ -487,7 +487,7 @@ Factory_volume(Factory* self, PyObject* args) if(parent != NULL) { Py_INCREF(self); - parent->child_list = (PyObject*)self; + parent->child_list = (PyObject *)self; try { @@ -517,7 +517,7 @@ PyDoc_STRVAR(M_aud_Factory_fadein_doc, ".. note:: Before the fade starts it plays silence."); static PyObject * -Factory_fadein(Factory* self, PyObject* args) +Factory_fadein(Factory* self, PyObject *args) { float start, length; @@ -530,7 +530,7 @@ Factory_fadein(Factory* self, PyObject* args) if(parent != NULL) { Py_INCREF(self); - parent->child_list = (PyObject*)self; + parent->child_list = (PyObject *)self; try { @@ -561,7 +561,7 @@ PyDoc_STRVAR(M_aud_Factory_fadeout_doc, "the length of the factory is not altered."); static PyObject * -Factory_fadeout(Factory* self, PyObject* args) +Factory_fadeout(Factory* self, PyObject *args) { float start, length; @@ -574,7 +574,7 @@ Factory_fadeout(Factory* self, PyObject* args) if(parent != NULL) { Py_INCREF(self); - parent->child_list = (PyObject*)self; + parent->child_list = (PyObject *)self; try { @@ -603,7 +603,7 @@ PyDoc_STRVAR(M_aud_Factory_loop_doc, ":attr:`Handle.loop_count` instead."); static PyObject * -Factory_loop(Factory* self, PyObject* args) +Factory_loop(Factory* self, PyObject *args) { int loop; @@ -616,7 +616,7 @@ Factory_loop(Factory* self, PyObject* args) if(parent != NULL) { Py_INCREF(self); - parent->child_list = (PyObject*)self; + parent->child_list = (PyObject *)self; try { @@ -644,7 +644,7 @@ PyDoc_STRVAR(M_aud_Factory_mix_doc, "(channels and samplerate)."); static PyObject * -Factory_mix(Factory* self, PyObject* object) +Factory_mix(Factory* self, PyObject *object) { PyTypeObject* type = Py_TYPE(self); @@ -692,7 +692,7 @@ Factory_pingpong(Factory* self) if(parent != NULL) { Py_INCREF(self); - parent->child_list = (PyObject*)self; + parent->child_list = (PyObject *)self; try { @@ -731,7 +731,7 @@ Factory_reverse(Factory* self) if(parent != NULL) { Py_INCREF(self); - parent->child_list = (PyObject*)self; + parent->child_list = (PyObject *)self; try { @@ -795,7 +795,7 @@ PyDoc_STRVAR(M_aud_Factory_square_doc, ":rtype: :class:`Factory`"); static PyObject * -Factory_square(Factory* self, PyObject* args) +Factory_square(Factory* self, PyObject *args) { float threshold = 0; @@ -808,7 +808,7 @@ Factory_square(Factory* self, PyObject* args) if(parent != NULL) { Py_INCREF(self); - parent->child_list = (PyObject*)self; + parent->child_list = (PyObject *)self; try { @@ -842,10 +842,10 @@ PyDoc_STRVAR(M_aud_Factory_filter_doc, ":rtype: :class:`Factory`"); static PyObject * -Factory_filter(Factory* self, PyObject* args) +Factory_filter(Factory* self, PyObject *args) { - PyObject* py_b; - PyObject* py_a = NULL; + PyObject *py_b; + PyObject *py_a = NULL; Py_ssize_t py_a_len; Py_ssize_t py_b_len; @@ -868,7 +868,7 @@ Factory_filter(Factory* self, PyObject* args) } std::vector a, b; - PyObject* py_value; + PyObject *py_value; float value; for(Py_ssize_t i = 0; i < py_b_len; i++) @@ -911,7 +911,7 @@ Factory_filter(Factory* self, PyObject* args) if(parent != NULL) { Py_INCREF(self); - parent->child_list = (PyObject*)self; + parent->child_list = (PyObject *)self; try { @@ -1040,7 +1040,7 @@ Handle_dealloc(Handle* self) { if(self->handle) delete reinterpret_cast*>(self->handle); - Py_TYPE(self)->tp_free((PyObject*)self); + Py_TYPE(self)->tp_free((PyObject *)self); } PyDoc_STRVAR(M_aud_Handle_pause_doc, @@ -1135,7 +1135,7 @@ Handle_get_position(Handle *self, void* nothing) } static int -Handle_set_position(Handle *self, PyObject* args, void* nothing) +Handle_set_position(Handle *self, PyObject *args, void* nothing) { float position; @@ -1180,7 +1180,7 @@ Handle_get_keep(Handle *self, void* nothing) } static int -Handle_set_keep(Handle *self, PyObject* args, void* nothing) +Handle_set_keep(Handle *self, PyObject *args, void* nothing) { if(!PyBool_Check(args)) { @@ -1239,7 +1239,7 @@ Handle_get_volume(Handle *self, void* nothing) } static int -Handle_set_volume(Handle *self, PyObject* args, void* nothing) +Handle_set_volume(Handle *self, PyObject *args, void* nothing) { float volume; @@ -1278,7 +1278,7 @@ Handle_get_pitch(Handle *self, void* nothing) } static int -Handle_set_pitch(Handle *self, PyObject* args, void* nothing) +Handle_set_pitch(Handle *self, PyObject *args, void* nothing) { float pitch; @@ -1317,7 +1317,7 @@ Handle_get_loop_count(Handle *self, void* nothing) } static int -Handle_set_loop_count(Handle *self, PyObject* args, void* nothing) +Handle_set_loop_count(Handle *self, PyObject *args, void* nothing) { int loops; @@ -1366,7 +1366,7 @@ Handle_get_location(Handle *self, void* nothing) } static int -Handle_set_location(Handle *self, PyObject* args, void* nothing) +Handle_set_location(Handle *self, PyObject *args, void* nothing) { float x, y, z; @@ -1422,7 +1422,7 @@ Handle_get_velocity(Handle *self, void* nothing) } static int -Handle_set_velocity(Handle *self, PyObject* args, void* nothing) +Handle_set_velocity(Handle *self, PyObject *args, void* nothing) { float x, y, z; @@ -1478,7 +1478,7 @@ Handle_get_orientation(Handle *self, void* nothing) } static int -Handle_set_orientation(Handle *self, PyObject* args, void* nothing) +Handle_set_orientation(Handle *self, PyObject *args, void* nothing) { float w, x, y, z; @@ -1533,7 +1533,7 @@ Handle_get_relative(Handle *self, void* nothing) } static int -Handle_set_relative(Handle *self, PyObject* args, void* nothing) +Handle_set_relative(Handle *self, PyObject *args, void* nothing) { if(!PyBool_Check(args)) { @@ -1591,7 +1591,7 @@ Handle_get_volume_minimum(Handle *self, void* nothing) } static int -Handle_set_volume_minimum(Handle *self, PyObject* args, void* nothing) +Handle_set_volume_minimum(Handle *self, PyObject *args, void* nothing) { float volume; @@ -1646,7 +1646,7 @@ Handle_get_volume_maximum(Handle *self, void* nothing) } static int -Handle_set_volume_maximum(Handle *self, PyObject* args, void* nothing) +Handle_set_volume_maximum(Handle *self, PyObject *args, void* nothing) { float volume; @@ -1702,7 +1702,7 @@ Handle_get_distance_reference(Handle *self, void* nothing) } static int -Handle_set_distance_reference(Handle *self, PyObject* args, void* nothing) +Handle_set_distance_reference(Handle *self, PyObject *args, void* nothing) { float distance; @@ -1758,7 +1758,7 @@ Handle_get_distance_maximum(Handle *self, void* nothing) } static int -Handle_set_distance_maximum(Handle *self, PyObject* args, void* nothing) +Handle_set_distance_maximum(Handle *self, PyObject *args, void* nothing) { float distance; @@ -1814,7 +1814,7 @@ Handle_get_attenuation(Handle *self, void* nothing) } static int -Handle_set_attenuation(Handle *self, PyObject* args, void* nothing) +Handle_set_attenuation(Handle *self, PyObject *args, void* nothing) { float factor; @@ -1875,7 +1875,7 @@ Handle_get_cone_angle_inner(Handle *self, void* nothing) } static int -Handle_set_cone_angle_inner(Handle *self, PyObject* args, void* nothing) +Handle_set_cone_angle_inner(Handle *self, PyObject *args, void* nothing) { float angle; @@ -1930,7 +1930,7 @@ Handle_get_cone_angle_outer(Handle *self, void* nothing) } static int -Handle_set_cone_angle_outer(Handle *self, PyObject* args, void* nothing) +Handle_set_cone_angle_outer(Handle *self, PyObject *args, void* nothing) { float angle; @@ -1985,7 +1985,7 @@ Handle_get_cone_volume_outer(Handle *self, void* nothing) } static int -Handle_set_cone_volume_outer(Handle *self, PyObject* args, void* nothing) +Handle_set_cone_volume_outer(Handle *self, PyObject *args, void* nothing) { float volume; @@ -2105,7 +2105,7 @@ Device_dealloc(Device* self) { if(self->device) delete reinterpret_cast*>(self->device); - Py_TYPE(self)->tp_free((PyObject*)self); + Py_TYPE(self)->tp_free((PyObject *)self); } static PyObject * @@ -2201,8 +2201,8 @@ PyDoc_STRVAR(M_aud_Device_play_doc, static PyObject * Device_play(Device *self, PyObject *args, PyObject *kwds) { - PyObject* object; - PyObject* keepo = NULL; + PyObject *object; + PyObject *keepo = NULL; bool keep = false; @@ -2402,7 +2402,7 @@ Device_get_volume(Device *self, void* nothing) } static int -Device_set_volume(Device *self, PyObject* args, void* nothing) +Device_set_volume(Device *self, PyObject *args, void* nothing) { float volume; @@ -2449,7 +2449,7 @@ Device_get_listener_location(Device *self, void* nothing) } static int -Device_set_listener_location(Device *self, PyObject* args, void* nothing) +Device_set_listener_location(Device *self, PyObject *args, void* nothing) { float x, y, z; @@ -2504,7 +2504,7 @@ Device_get_listener_velocity(Device *self, void* nothing) } static int -Device_set_listener_velocity(Device *self, PyObject* args, void* nothing) +Device_set_listener_velocity(Device *self, PyObject *args, void* nothing) { float x, y, z; @@ -2559,7 +2559,7 @@ Device_get_listener_orientation(Device *self, void* nothing) } static int -Device_set_listener_orientation(Device *self, PyObject* args, void* nothing) +Device_set_listener_orientation(Device *self, PyObject *args, void* nothing) { float w, x, y, z; @@ -2614,7 +2614,7 @@ Device_get_speed_of_sound(Device *self, void* nothing) } static int -Device_set_speed_of_sound(Device *self, PyObject* args, void* nothing) +Device_set_speed_of_sound(Device *self, PyObject *args, void* nothing) { float speed; @@ -2670,7 +2670,7 @@ Device_get_doppler_factor(Device *self, void* nothing) } static int -Device_set_doppler_factor(Device *self, PyObject* args, void* nothing) +Device_set_doppler_factor(Device *self, PyObject *args, void* nothing) { float factor; @@ -2724,7 +2724,7 @@ Device_get_distance_model(Device *self, void* nothing) } static int -Device_set_distance_model(Device *self, PyObject* args, void* nothing) +Device_set_distance_model(Device *self, PyObject *args, void* nothing) { int model; @@ -2833,7 +2833,7 @@ Factory_empty() } Factory* -checkFactory(PyObject* factory) +checkFactory(PyObject *factory) { if(!PyObject_TypeCheck(factory, &FactoryType)) { @@ -2862,7 +2862,7 @@ static struct PyModuleDef audmodule = { PyMODINIT_FUNC PyInit_aud(void) { - PyObject* m; + PyObject *m; if(PyType_Ready(&FactoryType) < 0) return NULL; @@ -2878,13 +2878,13 @@ PyInit_aud(void) return NULL; Py_INCREF(&FactoryType); - PyModule_AddObject(m, "Factory", (PyObject*)&FactoryType); + PyModule_AddObject(m, "Factory", (PyObject *)&FactoryType); Py_INCREF(&DeviceType); - PyModule_AddObject(m, "Device", (PyObject*)&DeviceType); + PyModule_AddObject(m, "Device", (PyObject *)&DeviceType); Py_INCREF(&HandleType); - PyModule_AddObject(m, "Handle", (PyObject*)&HandleType); + PyModule_AddObject(m, "Handle", (PyObject *)&HandleType); AUDError = PyErr_NewException("aud.error", NULL, NULL); Py_INCREF(AUDError); diff --git a/intern/audaspace/Python/AUD_PyAPI.h b/intern/audaspace/Python/AUD_PyAPI.h index 7a7e87ec67d..0183a2df6b2 100644 --- a/intern/audaspace/Python/AUD_PyAPI.h +++ b/intern/audaspace/Python/AUD_PyAPI.h @@ -46,7 +46,7 @@ typedef void AUD_Reference_AUD_IHandle; typedef struct { PyObject_HEAD - PyObject* child_list; + PyObject *child_list; AUD_Reference_AUD_IFactory* factory; } Factory; @@ -63,9 +63,9 @@ typedef struct { PyMODINIT_FUNC PyInit_aud(void); -extern PyObject* Device_empty(); -extern PyObject* Factory_empty(); -extern Factory* checkFactory(PyObject* factory); +extern PyObject *Device_empty(); +extern PyObject *Factory_empty(); +extern Factory *checkFactory(PyObject *factory); #ifdef __cplusplus } diff --git a/intern/audaspace/fftw/AUD_BandPassFactory.h b/intern/audaspace/fftw/AUD_BandPassFactory.h index 75de071403f..90b090dce16 100644 --- a/intern/audaspace/fftw/AUD_BandPassFactory.h +++ b/intern/audaspace/fftw/AUD_BandPassFactory.h @@ -84,7 +84,7 @@ public: * Sets the highest passed frequency. * \param high The highest passed frequency. */ - void setHigh(float hight); + void setHigh(float high); virtual AUD_IReader* createReader(); }; diff --git a/intern/audaspace/intern/AUD_AnimateableProperty.cpp b/intern/audaspace/intern/AUD_AnimateableProperty.cpp index 8a5c538c094..0b333e687ff 100644 --- a/intern/audaspace/intern/AUD_AnimateableProperty.cpp +++ b/intern/audaspace/intern/AUD_AnimateableProperty.cpp @@ -28,6 +28,7 @@ #include "AUD_AnimateableProperty.h" +#include "AUD_MutexLock.h" #include #include @@ -63,17 +64,15 @@ void AUD_AnimateableProperty::unlock() void AUD_AnimateableProperty::write(const float* data) { - lock(); + AUD_MutexLock lock(*this); m_isAnimated = false; memcpy(getBuffer(), data, m_count * sizeof(float)); - - unlock(); } void AUD_AnimateableProperty::write(const float* data, int position, int count) { - lock(); + AUD_MutexLock lock(*this); m_isAnimated = true; @@ -87,18 +86,15 @@ void AUD_AnimateableProperty::write(const float* data, int position, int count) for(int i = pos; i < position; i++) memcpy(buf + i * m_count, buf + (pos - 1) * m_count, m_count * sizeof(float)); - - unlock(); } void AUD_AnimateableProperty::read(float position, float* out) { - lock(); + AUD_MutexLock lock(*this); if(!m_isAnimated) { memcpy(out, getBuffer(), m_count * sizeof(float)); - unlock(); return; } @@ -147,8 +143,6 @@ void AUD_AnimateableProperty::read(float position, float* out) (t3 - 2 * t2 + t) * m0 + (t3 - t2) * m1; } } - - unlock(); } bool AUD_AnimateableProperty::isAnimated() const diff --git a/intern/audaspace/intern/AUD_AnimateableProperty.h b/intern/audaspace/intern/AUD_AnimateableProperty.h index 2f25e330ebd..322748ad571 100644 --- a/intern/audaspace/intern/AUD_AnimateableProperty.h +++ b/intern/audaspace/intern/AUD_AnimateableProperty.h @@ -31,13 +31,14 @@ #define __AUD_ANIMATEABLEPROPERTY_H__ #include "AUD_Buffer.h" +#include "AUD_ILockable.h" #include /** * This class saves animation data for float properties. */ -class AUD_AnimateableProperty : private AUD_Buffer +class AUD_AnimateableProperty : private AUD_Buffer, public AUD_ILockable { private: /// The count of floats for a single property. @@ -68,12 +69,12 @@ public: /** * Locks the property. */ - void lock(); + virtual void lock(); /** * Unlocks the previously locked property. */ - void unlock(); + virtual void unlock(); /** * Writes the properties value and marks it non-animated. diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp index 46bba237cff..a1da90b073e 100644 --- a/intern/audaspace/intern/AUD_C-API.cpp +++ b/intern/audaspace/intern/AUD_C-API.cpp @@ -68,6 +68,7 @@ #include "AUD_SequencerFactory.h" #include "AUD_SequencerEntry.h" #include "AUD_SilenceFactory.h" +#include "AUD_MutexLock.h" #ifdef WITH_SDL #include "AUD_SDLDevice.h" @@ -858,13 +859,12 @@ AUD_Handle *AUD_pauseAfter(AUD_Handle *handle, float seconds) AUD_Reference silence = new AUD_SilenceFactory; AUD_Reference limiter = new AUD_LimiterFactory(silence, 0, seconds); - AUD_device->lock(); + AUD_MutexLock lock(*AUD_device); try { AUD_Handle handle2 = AUD_device->play(limiter); if (!handle2.isNull()) { handle2->setStopCallback((stopCallback)pauseSound, handle); - AUD_device->unlock(); return new AUD_Handle(handle2); } } @@ -872,8 +872,6 @@ AUD_Handle *AUD_pauseAfter(AUD_Handle *handle, float seconds) { } - AUD_device->unlock(); - return NULL; } diff --git a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp index 61796098bf7..7a179c6f94a 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp +++ b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp @@ -67,10 +67,12 @@ void AUD_ChannelMapperReader::setMonoAngle(float angle) float AUD_ChannelMapperReader::angleDistance(float alpha, float beta) { - alpha = fabs(alpha - beta); + alpha = beta - alpha; if(alpha > M_PI) - alpha = fabs(alpha - 2 * M_PI); + alpha -= 2 * M_PI; + if(alpha < -M_PI) + alpha += 2 * M_PI; return alpha; } @@ -107,8 +109,8 @@ void AUD_ChannelMapperReader::calculateMapping() if(m_source_channels == AUD_CHANNELS_MONO) source_angles = &m_mono_angle; - int channel_min1, channel_min2; - float angle_min1, angle_min2, angle; + int channel_left, channel_right; + float angle_left, angle_right, angle; for(int i = 0; i < m_source_channels; i++) { @@ -120,38 +122,46 @@ void AUD_ChannelMapperReader::calculateMapping() continue; } - channel_min1 = channel_min2 = -1; - angle_min1 = angle_min2 = 2 * M_PI; + channel_left = channel_right = -1; + angle_left = -2 * M_PI; + angle_right = 2 * M_PI; for(int j = 0; j < m_target_channels; j++) { if(j == lfe) continue; angle = angleDistance(source_angles[i], target_angles[j]); - if(angle < angle_min1) + if(angle < 0) { - channel_min2 = channel_min1; - angle_min2 = angle_min1; - - channel_min1 = j; - angle_min1 = angle; + if(angle > angle_left) + { + angle_left = angle; + channel_left = j; + } } - else if(angle < angle_min2) + else { - channel_min2 = j; - angle_min2 = angle; + if(angle < angle_right) + { + angle_right = angle; + channel_right = j; + } } } - angle = angle_min1 + angle_min2; - if(channel_min2 == -1 || angle == 0) + angle = angle_right - angle_left; + if(channel_right == -1 || angle == 0) { - m_mapping[channel_min1 * m_source_channels + i] = 1; + m_mapping[channel_left * m_source_channels + i] = 1; + } + else if(channel_left == -1) + { + m_mapping[channel_right * m_source_channels + i] = 1; } else { - m_mapping[channel_min1 * m_source_channels + i] = cos(M_PI_2 * angle_min1 / angle); - m_mapping[channel_min2 * m_source_channels + i] = cos(M_PI_2 * angle_min2 / angle); + m_mapping[channel_left * m_source_channels + i] = cos(M_PI_2 * angle_left / angle); + m_mapping[channel_right * m_source_channels + i] = cos(M_PI_2 * angle_right / angle); } } diff --git a/intern/audaspace/intern/AUD_IDevice.h b/intern/audaspace/intern/AUD_IDevice.h index 1d6f8ca6efb..f4d6635e79a 100644 --- a/intern/audaspace/intern/AUD_IDevice.h +++ b/intern/audaspace/intern/AUD_IDevice.h @@ -35,6 +35,7 @@ #include "AUD_IFactory.h" #include "AUD_IReader.h" #include "AUD_IHandle.h" +#include "AUD_ILockable.h" /** * This class represents an output device for sound sources. @@ -44,7 +45,7 @@ * \warning Thread safety must be insured so that no reader is beeing called * twice at the same time. */ -class AUD_IDevice +class AUD_IDevice : public AUD_ILockable { public: /** diff --git a/intern/audaspace/intern/AUD_IFactory.h b/intern/audaspace/intern/AUD_IFactory.h index a7c214bb5a1..95b4643072e 100644 --- a/intern/audaspace/intern/AUD_IFactory.h +++ b/intern/audaspace/intern/AUD_IFactory.h @@ -45,7 +45,7 @@ public: /** * Destroys the factory. */ - virtual ~AUD_IFactory(){} + virtual ~AUD_IFactory() {} /** * Creates a reader for playback of the sound source. diff --git a/intern/audaspace/intern/AUD_ILockable.h b/intern/audaspace/intern/AUD_ILockable.h new file mode 100644 index 00000000000..9bc417504fe --- /dev/null +++ b/intern/audaspace/intern/AUD_ILockable.h @@ -0,0 +1,21 @@ +#ifndef AUD_ILOCKABLE_H +#define AUD_ILOCKABLE_H + +/** + * This class provides an interface for lockable objects. + * The main reason for this interface is to be used with AUD_MutexLock. + */ +class AUD_ILockable +{ +public: + /** + * Locks the object. + */ + virtual void lock()=0; + /** + * Unlocks the previously locked object. + */ + virtual void unlock()=0; +}; + +#endif // AUD_ILOCKABLE_H diff --git a/intern/audaspace/intern/AUD_IReader.h b/intern/audaspace/intern/AUD_IReader.h index 8e0e03dd95d..c2c9e607b55 100644 --- a/intern/audaspace/intern/AUD_IReader.h +++ b/intern/audaspace/intern/AUD_IReader.h @@ -42,7 +42,7 @@ public: /** * Destroys the reader. */ - virtual ~AUD_IReader(){} + virtual ~AUD_IReader() {} /** * Tells whether the source provides seeking functionality or not. diff --git a/intern/audaspace/intern/AUD_IWriter.h b/intern/audaspace/intern/AUD_IWriter.h index 3c92661c75d..5406577dd50 100644 --- a/intern/audaspace/intern/AUD_IWriter.h +++ b/intern/audaspace/intern/AUD_IWriter.h @@ -41,7 +41,7 @@ public: /** * Destroys the writer. */ - virtual ~AUD_IWriter(){} + virtual ~AUD_IWriter() {} /** * Returns how many samples have been written so far. diff --git a/intern/audaspace/intern/AUD_MutexLock.h b/intern/audaspace/intern/AUD_MutexLock.h new file mode 100644 index 00000000000..b6f6d2b4334 --- /dev/null +++ b/intern/audaspace/intern/AUD_MutexLock.h @@ -0,0 +1,24 @@ +#ifndef AUD_MUTEXLOCK_H +#define AUD_MUTEXLOCK_H + +#include "AUD_ILockable.h" + +class AUD_MutexLock +{ +public: + inline AUD_MutexLock(AUD_ILockable& lockable) : + lockable(lockable) + { + lockable.lock(); + } + + inline ~AUD_MutexLock() + { + lockable.unlock(); + } + +private: + AUD_ILockable& lockable; +}; + +#endif // AUD_MUTEXLOCK_H diff --git a/intern/audaspace/intern/AUD_PyInit.h b/intern/audaspace/intern/AUD_PyInit.h index 8c045e60f37..d8b6e2f3519 100644 --- a/intern/audaspace/intern/AUD_PyInit.h +++ b/intern/audaspace/intern/AUD_PyInit.h @@ -38,9 +38,9 @@ extern "C" { #endif /** - * Initalizes the Python module. + * Initializes the Python module. */ -extern PyObject* AUD_initPython(void); +extern PyObject *AUD_initPython(void); #ifdef __cplusplus } diff --git a/intern/audaspace/intern/AUD_SequencerEntry.cpp b/intern/audaspace/intern/AUD_SequencerEntry.cpp index 6e6e2397626..96fd15a0bf8 100644 --- a/intern/audaspace/intern/AUD_SequencerEntry.cpp +++ b/intern/audaspace/intern/AUD_SequencerEntry.cpp @@ -29,6 +29,7 @@ #include "AUD_SequencerEntry.h" #include "AUD_SequencerReader.h" +#include "AUD_MutexLock.h" #include #include @@ -87,20 +88,18 @@ void AUD_SequencerEntry::unlock() void AUD_SequencerEntry::setSound(AUD_Reference sound) { - lock(); + AUD_MutexLock lock(*this); if(m_sound.get() != sound.get()) { m_sound = sound; m_sound_status++; } - - unlock(); } void AUD_SequencerEntry::move(float begin, float end, float skip) { - lock(); + AUD_MutexLock lock(*this); if(m_begin != begin || m_skip != skip || m_end != end) { @@ -109,17 +108,13 @@ void AUD_SequencerEntry::move(float begin, float end, float skip) m_end = end; m_pos_status++; } - - unlock(); } void AUD_SequencerEntry::mute(bool mute) { - lock(); + AUD_MutexLock lock(*this); m_muted = mute; - - unlock(); } int AUD_SequencerEntry::getID() const @@ -150,7 +145,7 @@ void AUD_SequencerEntry::updateAll(float volume_max, float volume_min, float dis float distance_reference, float attenuation, float cone_angle_outer, float cone_angle_inner, float cone_volume_outer) { - lock(); + AUD_MutexLock lock(*this); if(volume_max != m_volume_max) { @@ -199,8 +194,6 @@ void AUD_SequencerEntry::updateAll(float volume_max, float volume_min, float dis m_cone_volume_outer = cone_volume_outer; m_status++; } - - unlock(); } bool AUD_SequencerEntry::isRelative() @@ -210,15 +203,13 @@ bool AUD_SequencerEntry::isRelative() void AUD_SequencerEntry::setRelative(bool relative) { - lock(); + AUD_MutexLock lock(*this); if(m_relative != relative) { m_relative = relative; m_status++; } - - unlock(); } float AUD_SequencerEntry::getVolumeMaximum() @@ -228,12 +219,10 @@ float AUD_SequencerEntry::getVolumeMaximum() void AUD_SequencerEntry::setVolumeMaximum(float volume) { - lock(); + AUD_MutexLock lock(*this); m_volume_max = volume; m_status++; - - unlock(); } float AUD_SequencerEntry::getVolumeMinimum() @@ -243,12 +232,10 @@ float AUD_SequencerEntry::getVolumeMinimum() void AUD_SequencerEntry::setVolumeMinimum(float volume) { - lock(); + AUD_MutexLock lock(*this); m_volume_min = volume; m_status++; - - unlock(); } float AUD_SequencerEntry::getDistanceMaximum() @@ -258,12 +245,10 @@ float AUD_SequencerEntry::getDistanceMaximum() void AUD_SequencerEntry::setDistanceMaximum(float distance) { - lock(); + AUD_MutexLock lock(*this); m_distance_max = distance; m_status++; - - unlock(); } float AUD_SequencerEntry::getDistanceReference() @@ -273,12 +258,10 @@ float AUD_SequencerEntry::getDistanceReference() void AUD_SequencerEntry::setDistanceReference(float distance) { - lock(); + AUD_MutexLock lock(*this); m_distance_reference = distance; m_status++; - - unlock(); } float AUD_SequencerEntry::getAttenuation() @@ -288,12 +271,10 @@ float AUD_SequencerEntry::getAttenuation() void AUD_SequencerEntry::setAttenuation(float factor) { - lock(); + AUD_MutexLock lock(*this); m_attenuation = factor; m_status++; - - unlock(); } float AUD_SequencerEntry::getConeAngleOuter() @@ -303,12 +284,10 @@ float AUD_SequencerEntry::getConeAngleOuter() void AUD_SequencerEntry::setConeAngleOuter(float angle) { - lock(); + AUD_MutexLock lock(*this); m_cone_angle_outer = angle; m_status++; - - unlock(); } float AUD_SequencerEntry::getConeAngleInner() @@ -318,12 +297,10 @@ float AUD_SequencerEntry::getConeAngleInner() void AUD_SequencerEntry::setConeAngleInner(float angle) { - lock(); + AUD_MutexLock lock(*this); m_cone_angle_inner = angle; m_status++; - - unlock(); } float AUD_SequencerEntry::getConeVolumeOuter() @@ -333,10 +310,8 @@ float AUD_SequencerEntry::getConeVolumeOuter() void AUD_SequencerEntry::setConeVolumeOuter(float volume) { - lock(); + AUD_MutexLock lock(*this); m_cone_volume_outer = volume; m_status++; - - unlock(); } diff --git a/intern/audaspace/intern/AUD_SequencerEntry.h b/intern/audaspace/intern/AUD_SequencerEntry.h index 7ff6fffea11..46efc52d66b 100644 --- a/intern/audaspace/intern/AUD_SequencerEntry.h +++ b/intern/audaspace/intern/AUD_SequencerEntry.h @@ -33,13 +33,14 @@ #include "AUD_Reference.h" #include "AUD_AnimateableProperty.h" #include "AUD_IFactory.h" +#include "AUD_ILockable.h" #include /** * This class represents a sequenced entry in a sequencer factory. */ -class AUD_SequencerEntry +class AUD_SequencerEntry : public AUD_ILockable { friend class AUD_SequencerHandle; private: @@ -130,12 +131,12 @@ public: /** * Locks the entry. */ - void lock(); + virtual void lock(); /** * Unlocks the previously locked entry. */ - void unlock(); + virtual void unlock(); /** * Sets the sound of the entry. diff --git a/intern/audaspace/intern/AUD_SequencerFactory.cpp b/intern/audaspace/intern/AUD_SequencerFactory.cpp index fd495f467cf..2cc0a656cf1 100644 --- a/intern/audaspace/intern/AUD_SequencerFactory.cpp +++ b/intern/audaspace/intern/AUD_SequencerFactory.cpp @@ -30,6 +30,7 @@ #include "AUD_SequencerFactory.h" #include "AUD_SequencerReader.h" #include "AUD_3DMath.h" +#include "AUD_MutexLock.h" AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, float fps, bool muted) : m_specs(specs), @@ -75,30 +76,24 @@ void AUD_SequencerFactory::unlock() void AUD_SequencerFactory::setSpecs(AUD_Specs specs) { - lock(); + AUD_MutexLock lock(*this); m_specs = specs; m_status++; - - unlock(); } void AUD_SequencerFactory::setFPS(float fps) { - lock(); + AUD_MutexLock lock(*this); m_fps = fps; - - unlock(); } void AUD_SequencerFactory::mute(bool muted) { - lock(); + AUD_MutexLock lock(*this); m_muted = muted; - - unlock(); } bool AUD_SequencerFactory::getMute() const @@ -113,12 +108,10 @@ float AUD_SequencerFactory::getSpeedOfSound() const void AUD_SequencerFactory::setSpeedOfSound(float speed) { - lock(); + AUD_MutexLock lock(*this); m_speed_of_sound = speed; m_status++; - - unlock(); } float AUD_SequencerFactory::getDopplerFactor() const @@ -128,12 +121,10 @@ float AUD_SequencerFactory::getDopplerFactor() const void AUD_SequencerFactory::setDopplerFactor(float factor) { - lock(); + AUD_MutexLock lock(*this); m_doppler_factor = factor; m_status++; - - unlock(); } AUD_DistanceModel AUD_SequencerFactory::getDistanceModel() const @@ -143,12 +134,10 @@ AUD_DistanceModel AUD_SequencerFactory::getDistanceModel() const void AUD_SequencerFactory::setDistanceModel(AUD_DistanceModel model) { - lock(); + AUD_MutexLock lock(*this); m_distance_model = model; m_status++; - - unlock(); } AUD_AnimateableProperty* AUD_SequencerFactory::getAnimProperty(AUD_AnimateablePropertyType type) @@ -168,26 +157,22 @@ AUD_AnimateableProperty* AUD_SequencerFactory::getAnimProperty(AUD_AnimateablePr AUD_Reference AUD_SequencerFactory::add(AUD_Reference sound, float begin, float end, float skip) { - lock(); + AUD_MutexLock lock(*this); AUD_Reference entry = new AUD_SequencerEntry(sound, begin, end, skip, m_id++); m_entries.push_front(entry); m_entry_status++; - unlock(); - return entry; } void AUD_SequencerFactory::remove(AUD_Reference entry) { - lock(); + AUD_MutexLock lock(*this); m_entries.remove(entry); m_entry_status++; - - unlock(); } AUD_Reference AUD_SequencerFactory::createQualityReader() diff --git a/intern/audaspace/intern/AUD_SequencerFactory.h b/intern/audaspace/intern/AUD_SequencerFactory.h index 38241112020..38cbc2d1867 100644 --- a/intern/audaspace/intern/AUD_SequencerFactory.h +++ b/intern/audaspace/intern/AUD_SequencerFactory.h @@ -32,6 +32,7 @@ #include "AUD_IFactory.h" #include "AUD_AnimateableProperty.h" +#include "AUD_ILockable.h" #include #include @@ -41,7 +42,7 @@ class AUD_SequencerEntry; /** * This factory represents sequenced entries to play a sound scene. */ -class AUD_SequencerFactory : public AUD_IFactory +class AUD_SequencerFactory : public AUD_IFactory, public AUD_ILockable { friend class AUD_SequencerReader; private: @@ -104,12 +105,12 @@ public: /** * Locks the factory. */ - void lock(); + virtual void lock(); /** * Unlocks the previously locked factory. */ - void unlock(); + virtual void unlock(); /** * Sets the audio output specification. diff --git a/intern/audaspace/intern/AUD_SequencerHandle.cpp b/intern/audaspace/intern/AUD_SequencerHandle.cpp index f4bfae6cee7..38d2ed38a7e 100644 --- a/intern/audaspace/intern/AUD_SequencerHandle.cpp +++ b/intern/audaspace/intern/AUD_SequencerHandle.cpp @@ -29,6 +29,7 @@ #include "AUD_SequencerHandle.h" #include "AUD_ReadDevice.h" +#include "AUD_MutexLock.h" AUD_SequencerHandle::AUD_SequencerHandle(AUD_Reference entry, AUD_ReadDevice& device) : m_entry(entry), @@ -68,7 +69,7 @@ void AUD_SequencerHandle::update(float position, float frame, float fps) { if(!m_handle.isNull()) { - m_entry->lock(); + AUD_MutexLock lock(*m_entry); if(position >= m_entry->m_end && m_entry->m_end >= 0) m_handle->pause(); else if(position >= m_entry->m_begin) @@ -134,7 +135,6 @@ void AUD_SequencerHandle::update(float position, float frame, float fps) if(m_entry->m_muted) m_handle->setVolume(0); - m_entry->unlock(); } } @@ -142,11 +142,10 @@ void AUD_SequencerHandle::seek(float position) { if(!m_handle.isNull()) { - m_entry->lock(); + AUD_MutexLock lock(*m_entry); if(position >= m_entry->m_end && m_entry->m_end >= 0) { m_handle->pause(); - m_entry->unlock(); return; } @@ -160,6 +159,5 @@ void AUD_SequencerHandle::seek(float position) m_handle->pause(); else m_handle->resume(); - m_entry->unlock(); } } diff --git a/intern/audaspace/intern/AUD_SequencerReader.cpp b/intern/audaspace/intern/AUD_SequencerReader.cpp index 2e41a99d3db..39a4d29e6e4 100644 --- a/intern/audaspace/intern/AUD_SequencerReader.cpp +++ b/intern/audaspace/intern/AUD_SequencerReader.cpp @@ -28,6 +28,7 @@ #include "AUD_SequencerReader.h" +#include "AUD_MutexLock.h" typedef std::list >::iterator AUD_HandleIterator; typedef std::list >::iterator AUD_EntryIterator; @@ -77,7 +78,7 @@ AUD_Specs AUD_SequencerReader::getSpecs() const void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer) { - m_factory->lock(); + AUD_MutexLock lock(*m_factory); if(m_factory->m_status != m_status) { @@ -197,8 +198,6 @@ void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer) time += float(len) / float(specs.rate); } - m_factory->unlock(); - m_position += length; eos = false; diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp index 1d993abab73..1fbd0ad82d2 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp +++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp @@ -33,6 +33,7 @@ #include "AUD_IFactory.h" #include "AUD_JOSResampleReader.h" #include "AUD_LinearResampleReader.h" +#include "AUD_MutexLock.h" #include #include @@ -226,7 +227,7 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::pause() { if(m_status) { - m_device->lock(); + AUD_MutexLock lock(*m_device); if(m_status == AUD_STATUS_PLAYING) { @@ -236,12 +237,9 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::pause() if(m_device->m_playingSounds.empty()) m_device->playing(m_device->m_playback = false); m_status = AUD_STATUS_PAUSED; - m_device->unlock(); return true; } - - m_device->unlock(); } return false; @@ -251,7 +249,7 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::resume() { if(m_status) { - m_device->lock(); + AUD_MutexLock lock(*m_device); if(m_status == AUD_STATUS_PAUSED) { @@ -261,11 +259,9 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::resume() if(!m_device->m_playback) m_device->playing(m_device->m_playback = true); m_status = AUD_STATUS_PLAYING; - m_device->unlock(); return true; } - m_device->unlock(); } return false; @@ -276,25 +272,38 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::stop() if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); - // AUD_XXX Create a reference of our own object so that it doesn't get - // deleted before the end of this function - AUD_Reference This = this; + if(!m_status) + return false; - if(m_status == AUD_STATUS_PLAYING) - { - m_device->m_playingSounds.remove(This); - - if(m_device->m_playingSounds.empty()) - m_device->playing(m_device->m_playback = false); - } - else - m_device->m_pausedSounds.remove(This); - - m_device->unlock(); m_status = AUD_STATUS_INVALID; - return true; + + for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++) + { + if(it->get() == this) + { + AUD_Reference This = *it; + + m_device->m_playingSounds.erase(it); + + if(m_device->m_playingSounds.empty()) + m_device->playing(m_device->m_playback = false); + + return true; + } + } + + for(AUD_HandleIterator it = m_device->m_pausedSounds.begin(); it != m_device->m_pausedSounds.end(); it++) + { + if(it->get() == this) + { + m_device->m_pausedSounds.erase(it); + return true; + } + } + + return false; } bool AUD_SoftwareDevice::AUD_SoftwareHandle::getKeep() @@ -310,12 +319,13 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::setKeep(bool keep) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; m_keep = keep; - m_device->unlock(); - return true; } @@ -324,26 +334,28 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::seek(float position) if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; m_reader->seek((int)(position * m_reader->getSpecs().rate)); - m_device->unlock(); - return true; } float AUD_SoftwareDevice::AUD_SoftwareHandle::getPosition() { + if(!m_status) + return false; + + AUD_MutexLock lock(*m_device); + if(!m_status) return 0.0f; - m_device->lock(); - float position = m_reader->getPosition() / (float)m_device->m_specs.rate; - m_device->unlock(); - return position; } @@ -407,13 +419,14 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::setStopCallback(stopCallback callba if(!m_status) return false; - m_device->lock(); + AUD_MutexLock lock(*m_device); + + if(!m_status) + return false; m_stop = callback; m_stop_data = data; - m_device->unlock(); - return true; } @@ -691,7 +704,7 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length) { m_buffer.assureSize(length * AUD_SAMPLE_SIZE(m_specs)); - lock(); + AUD_MutexLock lock(*this); { AUD_Reference sound; @@ -775,8 +788,6 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length) sound->pause(); } } - - unlock(); } void AUD_SoftwareDevice::setPanning(AUD_IHandle* handle, float pan) @@ -833,12 +844,12 @@ AUD_Reference AUD_SoftwareDevice::play(AUD_Reference r // play sound AUD_Reference sound = new AUD_SoftwareDevice::AUD_SoftwareHandle(this, reader, pitch, resampler, mapper, keep); - lock(); + AUD_MutexLock lock(*this); + m_playingSounds.push_back(sound); if(!m_playback) playing(m_playback = true); - unlock(); return AUD_Reference(sound); } @@ -850,15 +861,13 @@ AUD_Reference AUD_SoftwareDevice::play(AUD_Reference void AUD_SoftwareDevice::stopAll() { - lock(); + AUD_MutexLock lock(*this); while(!m_playingSounds.empty()) m_playingSounds.front()->stop(); while(!m_pausedSounds.empty()) m_pausedSounds.front()->stop(); - - unlock(); } void AUD_SoftwareDevice::lock() diff --git a/intern/bsp/CMakeLists.txt b/intern/bsp/CMakeLists.txt index e492c04423e..e3907c5273d 100644 --- a/intern/bsp/CMakeLists.txt +++ b/intern/bsp/CMakeLists.txt @@ -29,11 +29,10 @@ set(INC ../guardedalloc ../memutil ../moto/include - ../../extern/carve/include ) set(INC_SYS - + ../../extern/carve/include ) set(SRC @@ -62,7 +61,7 @@ if(WITH_BOOST) -DCARVE_SYSTEM_BOOST ) - list(APPEND INC + list(APPEND INC_SYS ${BOOST_INCLUDE_DIR} ) endif() diff --git a/intern/bsp/extern/CSG_BooleanOps.h b/intern/bsp/extern/CSG_BooleanOps.h index 94a74c30536..5ba6e0d76a1 100644 --- a/intern/bsp/extern/CSG_BooleanOps.h +++ b/intern/bsp/extern/CSG_BooleanOps.h @@ -61,9 +61,9 @@ extern "C" { #endif typedef struct { - int vertex_index[4]; - int vertex_number; - int orig_face; + int vertex_index[4]; + int vertex_number; + int orig_face; } CSG_IFace; /** @@ -72,7 +72,7 @@ typedef struct { */ typedef struct { - float position[3]; + float position[3]; } CSG_IVertex; /** diff --git a/intern/bsp/intern/BOP_CarveInterface.cpp b/intern/bsp/intern/BOP_CarveInterface.cpp index 255d885007c..49c999a1dd4 100644 --- a/intern/bsp/intern/BOP_CarveInterface.cpp +++ b/intern/bsp/intern/BOP_CarveInterface.cpp @@ -58,9 +58,9 @@ static bool isQuadPlanar(carve::geom3d::Vector &v1, carve::geom3d::Vector &v2, cross = carve::geom::cross(vec1, vec2); float production = carve::geom::dot(cross, vec3); - float magnitude = 1e-6 * cross.length(); + float magnitude = 1e-5 * cross.length(); - return fabs(production) < magnitude; + return fabsf(production) < magnitude; } static bool isFacePlanar(CSG_IFace &face, std::vector &vertices) @@ -135,10 +135,10 @@ static bool Carve_checkEdgeFaceIntersections(carve::csg::Intersections &intersec static inline bool Carve_facesAreCoplanar(const MeshSet<3>::face_t *a, const MeshSet<3>::face_t *b) { - carve::geom3d::Ray temp; - // XXX: Find a better definition. This may be a source of problems - // if floating point inaccuracies cause an incorrect answer. - return !carve::geom3d::planeIntersection(a->plane, b->plane, temp); + carve::geom3d::Ray temp; + // XXX: Find a better definition. This may be a source of problems + // if floating point inaccuracies cause an incorrect answer. + return !carve::geom3d::planeIntersection(a->plane, b->plane, temp); } static bool Carve_checkMeshSetInterseciton_do(carve::csg::Intersections &intersections, diff --git a/intern/container/CMakeLists.txt b/intern/container/CMakeLists.txt index b29eea37bc7..8adc46a59de 100644 --- a/intern/container/CMakeLists.txt +++ b/intern/container/CMakeLists.txt @@ -33,14 +33,11 @@ set(INC_SYS ) set(SRC - intern/CTR_List.cpp - CTR_HashedPtr.h - CTR_List.h CTR_Map.h CTR_TaggedIndex.h CTR_TaggedSetOps.h - CTR_UHeap.h ) +# infact nothing to compile! blender_add_lib(bf_intern_ctr "${SRC}" "${INC}" "${INC_SYS}") diff --git a/intern/container/CTR_HashedPtr.h b/intern/container/CTR_HashedPtr.h index 11dc37b3625..b7ac460f270 100644 --- a/intern/container/CTR_HashedPtr.h +++ b/intern/container/CTR_HashedPtr.h @@ -30,8 +30,8 @@ * \ingroup ctr */ -#ifndef CTR_HASHEDPTR_H -#define CTR_HASHEDPTR_H +#ifndef __CTR_HASHEDPTR_H__ +#define __CTR_HASHEDPTR_H__ #include @@ -43,13 +43,20 @@ inline unsigned int CTR_Hash(void *inDWord) class CTR_HashedPtr { - void* m_valptr; + void *m_valptr; public: - CTR_HashedPtr(void* val) : m_valptr(val) {}; - unsigned int hash() const { return CTR_Hash(m_valptr);}; - inline friend bool operator ==(const CTR_HashedPtr & rhs, const CTR_HashedPtr & lhs) { return rhs.m_valptr == lhs.m_valptr;}; - void *getValue() const { return m_valptr; } + CTR_HashedPtr(void *val) : m_valptr(val) { + }; + unsigned int hash() const { + return CTR_Hash(m_valptr); + }; + inline friend bool operator ==(const CTR_HashedPtr & rhs, const CTR_HashedPtr & lhs) { + return rhs.m_valptr == lhs.m_valptr; + }; + void *getValue() const { + return m_valptr; + } }; -#endif //CTR_HASHEDPTR_H +#endif /* __CTR_HASHEDPTR_H__ */ diff --git a/intern/container/CTR_List.h b/intern/container/CTR_List.h deleted file mode 100644 index 404a08fddf2..00000000000 --- a/intern/container/CTR_List.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file container/CTR_List.h - * \ingroup ctr - */ - - - -#ifndef CTR_LIST_H -#define CTR_LIST_H - -class CTR_Link { -public: - CTR_Link( - ); - - CTR_Link( - CTR_Link *next, - CTR_Link *prev - ); - - CTR_Link * - getNext( - ) const; - - CTR_Link * - getPrev( - ) const; - - bool - isHead( - ) const; - - bool - isTail( - ) const; - - void - insertBefore( - CTR_Link *link - ); - - void - insertAfter( - CTR_Link *link - ); - - void - remove( - ); - -private: - CTR_Link *m_next; - CTR_Link *m_prev; -}; - -class CTR_List { -public: - - CTR_List( - ); - - CTR_Link * - getHead( - ) const; - - CTR_Link * - getTail( - ) const; - - void - addHead( - CTR_Link *link - ); - - void - addTail( - CTR_Link *link - ); - -private: - CTR_Link m_head; - CTR_Link m_tail; -}; - -#endif - diff --git a/intern/container/CTR_Map.h b/intern/container/CTR_Map.h index 9557821d642..c278fe5330c 100644 --- a/intern/container/CTR_Map.h +++ b/intern/container/CTR_Map.h @@ -29,22 +29,22 @@ * \ingroup ctr */ - -#ifndef CTR_MAP_H -#define CTR_MAP_H +#ifndef __CTR_MAP_H__ +#define __CTR_MAP_H__ template class CTR_Map { private: struct Entry { Entry (Entry *next, Key key, Value value) : - m_next(next), - m_key(key), - m_value(value) {} + m_next(next), + m_key(key), + m_value(value) { + } Entry *m_next; - Key m_key; - Value m_value; + Key m_key; + Value m_value; }; public: @@ -63,18 +63,18 @@ public: for (int i = 0; i < m_num_buckets; ++i) { m_buckets[i] = 0; - for (Entry *entry = map.m_buckets[i]; entry; entry=entry->m_next) + for (Entry *entry = map.m_buckets[i]; entry; entry = entry->m_next) { insert(entry->m_key, entry->m_value); + } } } - int size() { - int count=0; - for (int i=0;im_next; count++; } @@ -82,15 +82,13 @@ public: return count; } - Value* at(int index) { - int count=0; - for (int i=0;im_value; } bucket = bucket->m_next; @@ -100,15 +98,13 @@ public: return 0; } - Key* getKey(int index) { - int count=0; - for (int i=0;im_key; } bucket = bucket->m_next; @@ -118,7 +114,8 @@ public: return 0; } - void clear() { + void clear() + { for (int i = 0; i < m_num_buckets; ++i) { Entry *entry_ptr = m_buckets[i]; @@ -131,12 +128,14 @@ public: } } - ~CTR_Map() { + ~CTR_Map() + { clear(); - delete [] m_buckets; + delete[] m_buckets; } - void insert(const Key& key, const Value& value) { + void insert(const Key& key, const Value& value) + { Entry *entry_ptr = m_buckets[key.hash() % m_num_buckets]; while ((entry_ptr != 0) && !(key == entry_ptr->m_key)) { entry_ptr = entry_ptr->m_next; @@ -151,7 +150,8 @@ public: } } - void remove(const Key& key) { + void remove(const Key& key) + { Entry **entry_ptr = &m_buckets[key.hash() % m_num_buckets]; while ((*entry_ptr != 0) && !(key == (*entry_ptr)->m_key)) { entry_ptr = &(*entry_ptr)->m_next; @@ -164,7 +164,8 @@ public: } } - Value *operator[](Key key) { + Value *operator[](Key key) + { Entry *bucket = m_buckets[key.hash() % m_num_buckets]; while ((bucket != 0) && !(key == bucket->m_key)) { bucket = bucket->m_next; @@ -177,5 +178,4 @@ private: Entry **m_buckets; }; -#endif - +#endif /* __CTR_MAP_H__ */ diff --git a/intern/container/CTR_TaggedIndex.h b/intern/container/CTR_TaggedIndex.h index 8420414d6c7..0eb4e02e84f 100644 --- a/intern/container/CTR_TaggedIndex.h +++ b/intern/container/CTR_TaggedIndex.h @@ -29,13 +29,6 @@ * \ingroup ctr */ - -/** - - * Copyright (C) 2001 NaN Technologies B.V. - * Simple tagged index class. - */ - #ifndef __CTR_TAGGEDINDEX_H__ #define __CTR_TAGGEDINDEX_H__ @@ -53,7 +46,6 @@ #include "MEM_sys_types.h" enum { - empty_tag = 0x0, empty_index = 0xffffffff }; @@ -191,7 +183,7 @@ public: return (Tag() == Empty().Tag()); } - // functionals + /* functionals */ struct greater : std::binary_function { @@ -213,7 +205,6 @@ private : unsigned int m_val; -}; - -#endif +}; +#endif /* __CTR_TAGGEDINDEX_H__ */ diff --git a/intern/container/CTR_TaggedSetOps.h b/intern/container/CTR_TaggedSetOps.h index d30081d2d60..6ebf20b77bf 100644 --- a/intern/container/CTR_TaggedSetOps.h +++ b/intern/container/CTR_TaggedSetOps.h @@ -50,16 +50,16 @@ * type ObjectType must have the following public methods to be used by * this template class: * - * int + * int * OpenTag(void) --- return a persistent tag value for the primitive * - * void + * void * SetOpenTag(int bla) --- set the persistent tag value for this primitive to bla. * - * bool + * bool * SelectTag() --- return a persistent boolean tag for this primitive * - * void + * void * SetSelectTag(bool bla) --- set the persistent boolean tag for this primitive to bla. * * Here persistent means that the tag should be associated with the object for the @@ -86,16 +86,16 @@ public : unsigned int shift ) { - // iterate through vectors in index_list - // iterate through individual members of each vector - // mark each obejct that the index points to + /* iterate through vectors in index_list + * iterate through individual members of each vector + * mark each obejct that the index points to */ typename std::vector< std::vector >::const_iterator last_vector = index_list.end(); typename std::vector< std::vector >::const_iterator start_vector = index_list.begin(); - // FIXME some temporary space + /* FIXME some temporary space */ std::vector temp_union; temp_union.reserve(64); @@ -114,7 +114,7 @@ public : ObjectType & prim = primitives[*start_index]; if (!prim.OpenTag()) { - // compute the union + /* compute the union */ temp_union.push_back(*start_index); } int tag = prim.OpenTag(); @@ -126,7 +126,7 @@ public : ++tag_num; } - // now iterate through the union and pull out all those with the right tag + /* now iterate through the union and pull out all those with the right tag */ typename std::vector::const_iterator last_index = temp_union.end(); @@ -138,20 +138,20 @@ public : ObjectType & prim = primitives[*start_index]; if (prim.OpenTag() == tag_num) { - //it's part of the intersection! + /* it's part of the intersection! */ output.push_back(*start_index); - // because we're iterating through the union - // it's safe to remove the tag at this point + /* because we're iterating through the union + * it's safe to remove the tag at this point */ prim.SetOpenTag(prim.OpenTag() & ~mask); } } }; - // note not a strict set intersection! - // if x appears twice in b and is part of the intersection - // it will appear twice in the intersection + /* note not a strict set intersection! + * if x appears twice in b and is part of the intersection + * it will appear twice in the intersection */ static void @@ -180,7 +180,7 @@ public : output.push_back(*start_index); } } - // deselect + /* deselect */ last_index = a.end(); start_index = a.begin(); @@ -199,9 +199,9 @@ public : std::vector &output ) { - // iterate through vectors in index_list - // iterate through individual members of each vector - // mark each obejct that the index points to + /* iterate through vectors in index_list + * iterate through individual members of each vector + * mark each obejct that the index points to */ typename std::vector< std::vector >::const_iterator last_vector = index_list.end(); @@ -220,15 +220,15 @@ public : ObjectType & prim = primitives[*start_index]; if (!prim.SelectTag()) { - // compute the union + /* compute the union */ output.push_back(*start_index); prim.SetSelectTag(true); } } } - // now iterate through the union and reset the tags - + /* now iterate through the union and reset the tags */ + typename std::vector::const_iterator last_index = output.end(); typename std::vector::iterator start_index = @@ -238,7 +238,7 @@ public : ObjectType & prim = primitives[*start_index]; prim.SetSelectTag(false); - } + } } @@ -251,8 +251,8 @@ public : std::vector< IndexType> &output ) { - // iterate through b mark all - // iterate through a and add to output all unmarked + /* iterate through b mark all + * iterate through a and add to output all unmarked */ typename std::vector::const_iterator last_index = b.end(); @@ -276,7 +276,7 @@ public : } } - // clean up the tags + /* clean up the tags */ last_index = b.end(); start_index = b.begin(); @@ -290,12 +290,11 @@ public : private : - // private constructor - this class is not meant for - // instantiation + /* private constructor - this class is not meant for + * instantiation */ CTR_TaggedSetOps(); }; -#endif - +#endif /* __CTR_TAGGEDSETOPS_H__ */ diff --git a/intern/container/CTR_UHeap.h b/intern/container/CTR_UHeap.h deleted file mode 100644 index 8330faa2f54..00000000000 --- a/intern/container/CTR_UHeap.h +++ /dev/null @@ -1,307 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file container/CTR_UHeap.h - * \ingroup ctr - */ - - -/** - - * Copyright (C) 2001 NaN Technologies B.V. - * - * @author Laurence - * @mainpage CTR_UHeap an updatable heap template class (also - * known as an updatable priority queue) - * - * Todo: Make CTR_UHeapable a template class with m_key the - * template parameter, so that arbitrary value types with - * operators (=,>) defined can be used. - * - */ - -#ifndef __CTR_UHEAP_H__ -#define __CTR_UHEAP_H__ - -#include - -#include "MEM_NonCopyable.h" - -class CTR_UHeapable { - -public: - int & - HeapPos( - ) { - return m_ind; - }; - float & - HeapKey( - ) { - return m_key; - }; - - const - float & - HeapKey( - ) const { - return m_key; - }; - - const - int & - HeapPos( - ) const { - return m_ind; - }; - -private: - - float m_key; - int m_ind; - -protected: - - CTR_UHeapable( - ) : m_key(0), - m_ind(0) - { - }; - - ~CTR_UHeapable( - ) { - }; -}; - -template -class CTR_UHeap : public MEM_NonCopyable -{ - -public: - - static - CTR_UHeap * - New( - ) { - return new CTR_UHeap(); - } - - void - MakeHeap( - HeapType *base - ) { - int i; - int start = Parent(m_vector.size() - 1); - for (i = start; i >= 0; --i) { - DownHeap(base, i); - } - }; - - void - Insert( - HeapType *base, - int elem - ) { - // add element to vector - m_vector.push_back(elem); - base[elem].HeapPos() = m_vector.size() - 1; - - // push the element up the heap - UpHeap(base, m_vector.size() - 1); - } - - // access to the vector for initial loading of elements - - std::vector & - HeapVector( - ) { - return m_vector; - }; - - - void - Remove( - HeapType *base, - int i - ) { - - // exchange with last element - pop last - // element and move up or down the heap as appropriate - if (m_vector.empty()) { - assert(false); - } - - if (i != int(m_vector.size()) - 1) { - - Swap(base, i, m_vector.size() - 1); - m_vector.pop_back(); - - if (!m_vector.empty()) { - UpHeap(base, i); - DownHeap(base, i); - } - } - else { - m_vector.pop_back(); - } - } - - int - Top( - ) const { - if (m_vector.empty()) return -1; - return m_vector[0]; - } - - - void - SC_Heap( - HeapType *base - ) { - int i; - for (i = 1; i < int(m_vector.size()); i++) { - - CTR_UHeapable *elem = base + m_vector[i]; - CTR_UHeapable *p_elem = base + m_vector[Parent(i)]; - - assert(p_elem->HeapKey() >= elem->HeapKey()); - assert(elem->HeapPos() == i); - } - - }; - - - ~CTR_UHeap( - ) { - }; - - -private: - - CTR_UHeap( - ) { - }; - - - std::vector m_vector; - -private: - void - Swap( - HeapType *base, - int i, - int j - ) { - std::swap(m_vector[i], m_vector[j]); - - CTR_UHeapable *heap_i = base + m_vector[i]; - CTR_UHeapable *heap_j = base + m_vector[j]; - - // Exchange heap positions - heap_i->HeapPos() = i; - heap_j->HeapPos() = j; - } - - int - Parent( - unsigned int i - ) { - return (i - 1) >> 1; - } - int - Left( - int i - ) { - return (i << 1) + 1; - } - - int - Right( - int i - ) { - return (i << 1) + 2; - } - - float - HeapVal( - HeapType *base, - int i - ) { - return base[m_vector[i]].HeapKey(); - } - - void - DownHeap( - HeapType *base, - int i - ) { - int heap_size = m_vector.size(); - - int l = Left(i); - int r = Right(i); - - int largest; - if (l < heap_size && HeapVal(base, l) > HeapVal(base, i)) { - largest = l; - } - else { - largest = i; - } - - if (r < heap_size && HeapVal(base, r) > HeapVal(base, largest)) { - largest = r; - } - - if (largest != i) { - // exchange i and largest - Swap(base, i, largest); - DownHeap(base, largest); - } - } - - void - UpHeap( - HeapType *base, - int i - ) { - - // swap parents untill it's found a place in the heap < it's parent or - // top of heap - - while (i > 0) { - int p = Parent(i); - if (HeapVal(base, i) < HeapVal(base, p)) { - break; - } - Swap(base, p, i); - i = p; - } - } -}; - -#endif - diff --git a/intern/container/intern/CTR_List.cpp b/intern/container/intern/CTR_List.cpp deleted file mode 100644 index c72d3ccf0d8..00000000000 --- a/intern/container/intern/CTR_List.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file container/intern/CTR_List.cpp - * \ingroup ctr - */ - - -#include "CTR_List.h" - - -CTR_Link::CTR_Link() : - m_next(0), - m_prev(0) -{ -} - -CTR_Link::CTR_Link(CTR_Link *next, CTR_Link *prev) : - m_next(next), - m_prev(prev) -{ -} - -CTR_Link * -CTR_Link::getNext() const -{ - return m_next; -} - -CTR_Link * -CTR_Link::getPrev() const -{ - return m_prev; -} - -bool -CTR_Link::isHead() const -{ - return m_prev == 0; -} - -bool -CTR_Link::isTail() const -{ - return m_next == 0; -} - -void -CTR_Link::insertBefore(CTR_Link *link) -{ - m_next = link; - m_prev = link->m_prev; - m_next->m_prev = this; - m_prev->m_next = this; -} - -void -CTR_Link::insertAfter(CTR_Link *link) -{ - m_next = link->m_next; - m_prev = link; - m_next->m_prev = this; - m_prev->m_next = this; -} - -void -CTR_Link::remove() -{ - m_next->m_prev = m_prev; - m_prev->m_next = m_next; -} - - -CTR_List::CTR_List() : - m_head(&m_tail, 0), - m_tail(0, &m_head) -{ -} - -CTR_Link * -CTR_List:: getHead() const -{ - return m_head.getNext(); -} - -CTR_Link * -CTR_List::getTail() const -{ - return m_tail.getPrev(); -} - -void -CTR_List::addHead(CTR_Link *link) -{ - link->insertAfter(&m_head); -} - -void -CTR_List::addTail(CTR_Link *link) -{ - link->insertBefore(&m_tail); -} - diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 337eebe4be0..7562ee0a0a5 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -41,6 +41,7 @@ endif() if(WITH_CYCLES_OSL) add_definitions(-DWITH_OSL) + include_directories(${OSL_INCLUDES}) endif() if(WITH_CYCLES_PARTIO) @@ -56,9 +57,11 @@ add_definitions(-DWITH_CUDA) add_definitions(-DWITH_MULTI) include_directories( + SYSTEM ${BOOST_INCLUDE_DIR} ${OPENIMAGEIO_INCLUDE_DIRS} - ${OPENIMAGEIO_INCLUDE_DIRS}/OpenImageIO) + ${OPENIMAGEIO_INCLUDE_DIRS}/OpenImageIO + ${OPENEXR_INCLUDE_DIR}) # Subdirectories diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript index a7b8637e3ad..c0e0353d37d 100644 --- a/intern/cycles/SConscript +++ b/intern/cycles/SConscript @@ -29,7 +29,7 @@ if env['WITH_BF_CYCLES_CUDA_BINARIES']: incs.extend('. bvh render device kernel kernel/osl kernel/svm util subd'.split()) incs.extend('#intern/guardedalloc #source/blender/makesrna #source/blender/makesdna'.split()) incs.extend('#source/blender/blenloader ../../source/blender/makesrna/intern'.split()) -incs.extend('#extern/glew/include'.split()) +incs.extend('#extern/glew/include #intern/mikktspace'.split()) incs.append(cycles['BF_OIIO_INC']) incs.append(cycles['BF_BOOST_INC']) incs.append(cycles['BF_PYTHON_INC']) diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt index 2e2897d0443..83b3f731ffe 100644 --- a/intern/cycles/app/CMakeLists.txt +++ b/intern/cycles/app/CMakeLists.txt @@ -9,6 +9,8 @@ set(INC ../render ../subd ) +set(INC_SYS +) set(LIBRARIES cycles_device @@ -38,6 +40,7 @@ if(WITH_CYCLES_PARTIO) endif() include_directories(${INC}) +include_directories(SYSTEM ${INC_SYS}) if(WITH_CYCLES_TEST) set(SRC diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 87a238e508c..5de9d71b8cc 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -591,6 +591,7 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug if(string_iequals(in->name, attr.name())) { switch(in->type) { case SHADER_SOCKET_FLOAT: + case SHADER_SOCKET_INT: xml_read_float(&in->value.x, node, attr.name()); break; case SHADER_SOCKET_COLOR: diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt index a8c7eef89fa..292c37d6b61 100644 --- a/intern/cycles/blender/CMakeLists.txt +++ b/intern/cycles/blender/CMakeLists.txt @@ -7,6 +7,7 @@ set(INC ../util ../subd ../../guardedalloc + ../../mikktspace ../../../source/blender/makesdna ../../../source/blender/makesrna ../../../source/blender/blenloader @@ -38,6 +39,7 @@ set(ADDON_FILES addon/__init__.py addon/engine.py addon/enums.py + addon/osl.py addon/presets.py addon/properties.py addon/ui.py diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index 4a60a329e2b..16697c08b2b 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -25,7 +25,7 @@ bl_info = { "location": "Info header, render engine menu", "description": "Cycles Render Engine integration", "warning": "", - "wiki_url": "http://wiki.blender.org/index.php/Dev:2.6/Source/Render/Cycles", + "wiki_url": "http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles", "tracker_url": "", "support": 'OFFICIAL', "category": "Render"} @@ -71,6 +71,13 @@ class CyclesRender(bpy.types.RenderEngine): def view_draw(self, context): engine.draw(self, context.region, context.space_data, context.region_data) + def update_script_node(self, node): + if engine.with_osl(): + from . import osl + osl.update_script_node(node, self.report) + else: + self.report({'ERROR'}, "OSL support disabled in this build.") + def register(): properties.register() @@ -84,3 +91,4 @@ def unregister(): properties.unregister() presets.unregister() bpy.utils.unregister_module(__name__) + diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index 05b1f883594..e4f80cb4d5d 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -83,3 +83,4 @@ def available_devices(): def with_osl(): import _cycles return _cycles.with_osl + diff --git a/intern/cycles/blender/addon/enums.py b/intern/cycles/blender/addon/enums.py index 6cc3010eb0e..e63e1e84245 100644 --- a/intern/cycles/blender/addon/enums.py +++ b/intern/cycles/blender/addon/enums.py @@ -60,3 +60,4 @@ panorama_types = ( ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ideal for fulldomes, ignore the sensor dimensions"), ('FISHEYE_EQUISOLID', "Fisheye Equisolid", "Similar to most fisheye modern lens, take sensor dimensions into consideration"), ) + diff --git a/intern/cycles/blender/addon/osl.py b/intern/cycles/blender/addon/osl.py new file mode 100644 index 00000000000..aac1e2422b9 --- /dev/null +++ b/intern/cycles/blender/addon/osl.py @@ -0,0 +1,127 @@ +# +# 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. +# + +# + +import bpy, _cycles, os, tempfile + +# compile .osl file with given filepath to temporary .oso file +def osl_compile(input_path, report): + output_file = tempfile.NamedTemporaryFile(mode='w', suffix=".oso", delete=False) + output_path = output_file.name + output_file.close() + + ok = _cycles.osl_compile(input_path, output_path) + + if ok: + report({'INFO'}, "OSL shader compilation succeeded") + + return ok, output_path + +# compile and update shader script node +def update_script_node(node, report): + import os, shutil + + if node.mode == 'EXTERNAL': + # compile external script file + script_path = bpy.path.abspath(node.filepath, library=node.id_data.library) + script_path_noext, script_ext = os.path.splitext(script_path) + + if script_ext == ".oso": + # it's a .oso file, no need to compile + ok, oso_path = True, script_path + oso_file_remove = False + elif script_ext == ".osl": + # compile .osl file + ok, oso_path = osl_compile(script_path, report) + oso_file_remove = True + + if ok: + # copy .oso from temporary path to .osl directory + dst_path = script_path_noext + ".oso" + try: + shutil.copy2(oso_path, dst_path) + except: + report({'ERROR'}, "Failed to write .oso file next to external .osl file at " + dst_path) + elif os.path.dirname(node.filepath) == "": + # module in search path + oso_path = node.filepath + oso_file_remove = False + ok = True + else: + # unknown + report({'ERROR'}, "External shader script must have .osl or .oso extension, or be a module name") + ok = False + + if ok: + node.bytecode = "" + node.bytecode_hash = "" + + elif node.mode == 'INTERNAL' and node.script: + # internal script, we will store bytecode in the node + script = node.script + osl_path = bpy.path.abspath(script.filepath, library=script.library) + + if script.is_in_memory or script.is_dirty or script.is_modified or not os.path.exists(osl_path): + # write text datablock contents to temporary file + osl_file = tempfile.NamedTemporaryFile(mode='w', suffix=".osl", delete=True) + osl_file.write(script.as_string()) + osl_file.flush() + ok, oso_path = osl_compile(osl_file.name, report) + oso_file_remove = False + osl_file.close() + else: + # compile text datablock from disk directly + ok, oso_path = osl_compile(osl_path, report) + oso_file_remove = False + + if ok: + # read bytecode + try: + oso = open(oso_path, 'r') + node.bytecode = oso.read() + oso.close() + except: + import traceback + traceback.print_exc() + + report({'ERROR'}, "Can't read OSO bytecode to store in node at %r" % oso_path) + ok = False + + else: + report({'WARNING'}, "No text or file specified in node, nothing to compile") + return + + if ok: + # now update node with new sockets + ok = _cycles.osl_update_node(node.id_data.as_pointer(), node.as_pointer(), oso_path) + + if not ok: + report({'ERROR'}, "OSL query failed to open " + oso_path) + else: + report({'ERROR'}, "OSL script compilation failed, see console for errors") + + # remove temporary oso file + if oso_file_remove: + try: + os.remove(oso_path) + except: + pass + + return ok + diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 7f3eca471e6..0b8ca6e0fbe 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -136,7 +136,8 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): ) cls.blur_glossy = FloatProperty( name="Filter Glossy", - description="Adaptively blur glossy shaders after blurry bounces, to reduce noise at the cost of accuracy", + description="Adaptively blur glossy shaders after blurry bounces, " + "to reduce noise at the cost of accuracy", min=0.0, max=10.0, default=0.0, ) @@ -230,7 +231,9 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): cls.sample_clamp = FloatProperty( name="Clamp", - description="If non-zero, the maximum value for a sample, higher values will be scaled down to avoid too much noise and slow convergence at the cost of accuracy", + description="If non-zero, the maximum value for a sample, " + "higher values will be scaled down to avoid too " + "much noise and slow convergence at the cost of accuracy", min=0.0, max=1e8, default=0.0, ) @@ -242,11 +245,12 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): default=1024, ) - cls.resolution_divider = IntProperty( - name="Resolution Divider", - description="For viewport render, the number of lower resolutions to render before the full resolution", - min=1, max=512, - default=4, + cls.preview_start_resolution = IntProperty( + name="Start Resolution", + description="Resolution to start rendering preview at, " + "progressively increasing it to the full viewport size", + min=8, max=16384, + default=64, ) cls.debug_reset_timeout = FloatProperty( @@ -284,6 +288,14 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): description="Cache last built BVH to disk for faster re-render if no geometry changed", default=False, ) + cls.use_progressive_refine = BoolProperty( + name="Progressive Refine", + description="Instead of rendering each tile until it is finished, " + "refine the whole image progressively " + "(this renders somewhat slower, " + "but time can be saved by manually stopping the render when the noise is low enough)", + default=False, + ) @classmethod def unregister(cls): @@ -369,12 +381,15 @@ class CyclesMaterialSettings(bpy.types.PropertyGroup): ) cls.sample_as_light = BoolProperty( name="Sample as Lamp", - description="Use direct light sampling for this material, disabling may reduce overall noise for large objects that emit little light compared to other light sources", + description="Use direct light sampling for this material, " + "disabling may reduce overall noise for large " + "objects that emit little light compared to other light sources", default=True, ) cls.homogeneous_volume = BoolProperty( name="Homogeneous Volume", - description="When using volume rendering, assume volume has the same density everywhere, for faster rendering", + description="When using volume rendering, assume volume has the same density everywhere, " + "for faster rendering", default=False, ) @@ -418,12 +433,14 @@ class CyclesWorldSettings(bpy.types.PropertyGroup): ) cls.sample_as_light = BoolProperty( name="Sample as Lamp", - description="Use direct light sampling for the environment, enabling for non-solid colors is recommended", + description="Use direct light sampling for the environment, " + "enabling for non-solid colors is recommended", default=False, ) cls.sample_map_resolution = IntProperty( name="Map Resolution", - description="Importance map size is resolution x resolution; higher values potentially produce less noise, at the cost of memory and speed", + description="Importance map size is resolution x resolution; " + "higher values potentially produce less noise, at the cost of memory and speed", min=4, max=8096, default=256, ) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 7486edf2319..9cc58e65bef 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -59,7 +59,7 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel): col = split.column() sub = col.column() - sub.enabled = (device_type == 'NONE' or cscene.device == 'CPU') + sub.active = (device_type == 'NONE' or cscene.device == 'CPU') sub.prop(cscene, "progressive") sub = col.column(align=True) @@ -134,10 +134,6 @@ class CyclesRender_PT_motion_blur(CyclesButtonsPanel, Panel): bl_label = "Motion Blur" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - return False - def draw_header(self, context): rd = context.scene.render @@ -197,10 +193,12 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel): sub.prop(rd, "threads") sub = col.column(align=True) - sub.label(text="Tiles:") + sub.label(text="Tile Size:") - sub.prop(rd, "parts_x", text="X") - sub.prop(rd, "parts_y", text="Y") + sub.prop(rd, "tile_x", text="X") + sub.prop(rd, "tile_y", text="Y") + + sub.prop(cscene, "use_progressive_refine") subsub = sub.column() subsub.enabled = not rd.use_border @@ -216,7 +214,7 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel): sub = col.column(align=True) sub.label(text="Viewport:") - sub.prop(cscene, "resolution_divider") + sub.prop(cscene, "preview_start_resolution") class CyclesRender_PT_layers(CyclesButtonsPanel, Panel): @@ -438,6 +436,28 @@ class Cycles_PT_mesh_displacement(CyclesButtonsPanel, Panel): layout.prop(cdata, "dicing_rate") +class Cycles_PT_mesh_normals(CyclesButtonsPanel, Panel): + bl_label = "Normals" + bl_context = "data" + + @classmethod + def poll(cls, context): + return CyclesButtonsPanel.poll(context) and context.mesh + + def draw(self, context): + layout = self.layout + + mesh = context.mesh + + split = layout.split() + + col = split.column() + col.prop(mesh, "show_double_sided") + + col = split.column() + col.label() + + class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel): bl_label = "Ray Visibility" bl_context = "object" @@ -513,6 +533,7 @@ class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel): lamp = context.lamp clamp = lamp.cycles cscene = context.scene.cycles + device_type = context.user_preferences.system.compute_device_type layout.prop(lamp, "type", expand=True) @@ -531,7 +552,7 @@ class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel): sub.prop(lamp, "size", text="Size X") sub.prop(lamp, "size_y", text="Size Y") - if not cscene.progressive and cscene.device == 'CPU': + if not cscene.progressive and (device_type == 'NONE' or cscene.device == 'CPU'): col.prop(clamp, "samples") col = split.column() @@ -656,6 +677,7 @@ class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel): world = context.world cworld = world.cycles cscene = context.scene.cycles + device_type = context.user_preferences.system.compute_device_type col = layout.column() @@ -663,7 +685,7 @@ class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel): sub = col.row(align=True) sub.active = cworld.sample_as_light sub.prop(cworld, "sample_map_resolution") - if not cscene.progressive and cscene.device == 'CPU': + if not cscene.progressive and (device_type == 'NONE' or cscene.device == 'CPU'): sub.prop(cworld, "samples") @@ -930,8 +952,8 @@ def draw_device(self, context): layout.prop(cscene, "device") elif device_type == 'OPENCL' and cscene.feature_set == 'EXPERIMENTAL': layout.prop(cscene, "device") - - if cscene.feature_set == 'EXPERIMENTAL' and cscene.device == 'CPU' and engine.with_osl(): + + if engine.with_osl() and (cscene.device == 'CPU' or device_type == 'None'): layout.prop(cscene, "shading_system") @@ -966,6 +988,7 @@ def get_panels(): bpy.types.DATA_PT_context_mesh, bpy.types.DATA_PT_context_camera, bpy.types.DATA_PT_context_lamp, + bpy.types.DATA_PT_context_speaker, bpy.types.DATA_PT_texture_space, bpy.types.DATA_PT_curve_texture_space, bpy.types.DATA_PT_mball_texture_space, @@ -976,9 +999,14 @@ def get_panels(): bpy.types.DATA_PT_camera, bpy.types.DATA_PT_camera_display, bpy.types.DATA_PT_lens, + bpy.types.DATA_PT_speaker, + bpy.types.DATA_PT_distance, + bpy.types.DATA_PT_cone, + bpy.types.DATA_PT_customdata, bpy.types.DATA_PT_custom_props_mesh, bpy.types.DATA_PT_custom_props_camera, bpy.types.DATA_PT_custom_props_lamp, + bpy.types.DATA_PT_custom_props_speaker, bpy.types.TEXTURE_PT_clouds, bpy.types.TEXTURE_PT_wood, bpy.types.TEXTURE_PT_marble, diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index 46d5fefd4dc..af16e210301 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -94,7 +94,7 @@ static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera) return fabsf(transform_get_column(&mat, 3).z); } -static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob) +static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob, bool skip_panorama = false) { BL::ID b_ob_data = b_ob.data(); @@ -111,7 +111,10 @@ static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob) bcam->type = CAMERA_ORTHOGRAPHIC; break; case BL::Camera::type_PANO: - bcam->type = CAMERA_PANORAMA; + if(!skip_panorama) + bcam->type = CAMERA_PANORAMA; + else + bcam->type = CAMERA_PERSPECTIVE; break; case BL::Camera::type_PERSP: default: @@ -378,7 +381,7 @@ void BlenderSync::sync_camera_motion(BL::Object b_ob, int motion) /* Sync 3D View Camera */ -static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height) +static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height, bool skip_panorama = false) { /* 3d view parameters */ bcam->nearclip = b_v3d.clip_start(); @@ -391,7 +394,7 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL: BL::Object b_ob = (b_v3d.lock_camera_and_layers())? b_scene.camera(): b_v3d.camera(); if(b_ob) { - blender_camera_from_object(bcam, b_ob); + blender_camera_from_object(bcam, b_ob, skip_panorama); /* magic zoom formula */ bcam->zoom = (float)b_rv3d.view_camera_zoom(); @@ -408,8 +411,14 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL: bcam->farclip *= 0.5f; bcam->nearclip = -bcam->farclip; + float sensor_size; + if(bcam->sensor_fit == BlenderCamera::VERTICAL) + sensor_size = bcam->sensor_height; + else + sensor_size = bcam->sensor_width; + bcam->type = CAMERA_ORTHOGRAPHIC; - bcam->ortho_scale = b_rv3d.view_distance(); + bcam->ortho_scale = b_rv3d.view_distance() * sensor_size / b_v3d.lens(); } bcam->zoom *= 2.0f; @@ -422,12 +431,26 @@ static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::Sp BL::RegionView3D b_rv3d, int width, int height) { BL::RenderSettings r = b_scene.render(); - - if(!r.use_border()) - return; + bool is_camera_view; /* camera view? */ - if(!(b_rv3d && b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA)) + is_camera_view = b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA; + + if(!is_camera_view) { + /* for non-camera view check whether render border is enabled for viewport + * and if so use border from 3d viewport + * assume viewport has got correctly clamped border already + */ + if(b_v3d.use_render_border()) { + bcam->border_left = b_v3d.render_border_min_x(); + bcam->border_right = b_v3d.render_border_max_x(); + bcam->border_bottom = b_v3d.render_border_min_y(); + bcam->border_top = b_v3d.render_border_max_y(); + + return; + } + } + else if(!r.use_border()) return; BL::Object b_ob = (b_v3d.lock_camera_and_layers())? b_scene.camera(): b_v3d.camera(); @@ -447,7 +470,7 @@ static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::Sp /* get viewport viewplane */ BlenderCamera view_bcam; blender_camera_init(&view_bcam); - blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height); + blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height, true); blender_camera_viewplane(&view_bcam, width, height, &view_left, &view_right, &view_bottom, &view_top, &view_aspect, &sensor_size); @@ -460,7 +483,7 @@ static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::Sp /* get camera viewplane */ BlenderCamera cam_bcam; blender_camera_init(&cam_bcam); - blender_camera_from_object(&cam_bcam, b_ob); + blender_camera_from_object(&cam_bcam, b_ob, true); width = (int)(r.resolution_x()*r.resolution_percentage()/100); height = (int)(r.resolution_y()*r.resolution_percentage()/100); @@ -501,14 +524,20 @@ void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int blender_camera_sync(scene->camera, &bcam, width, height); } -BufferParams BlenderSync::get_buffer_params(BL::Scene b_scene, Camera *cam, int width, int height) +BufferParams BlenderSync::get_buffer_params(BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, Camera *cam, int width, int height) { BufferParams params; + bool use_border = false; params.full_width = width; params.full_height = height; - if(b_scene.render().use_border()) { + if(b_v3d && b_rv3d && b_rv3d.view_perspective() != BL::RegionView3D::view_perspective_CAMERA) + use_border = b_v3d.use_render_border(); + else + use_border = b_scene.render().use_border(); + + if(use_border) { /* border render */ params.full_x = cam->border_left*width; params.full_y = cam->border_bottom*height; diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 9764f24a893..0e13479a761 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -16,6 +16,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + #include "mesh.h" #include "object.h" #include "scene.h" @@ -29,9 +30,137 @@ #include "util_foreach.h" +#include "mikktspace.h" + CCL_NAMESPACE_BEGIN -/* Find/Add */ +/* Tangent Space */ + +struct MikkUserData { + MikkUserData(const BL::Mesh mesh_, const BL::MeshTextureFaceLayer layer_, int num_faces_) + : mesh(mesh_), layer(layer_), num_faces(num_faces_) + { + tangent.resize(num_faces*4); + } + + BL::Mesh mesh; + BL::MeshTextureFaceLayer layer; + int num_faces; + vector tangent; +}; + +static int mikk_get_num_faces(const SMikkTSpaceContext *context) +{ + MikkUserData *userdata = (MikkUserData*)context->m_pUserData; + return userdata->num_faces; +} + +static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context, const int face_num) +{ + MikkUserData *userdata = (MikkUserData*)context->m_pUserData; + BL::MeshTessFace f = userdata->mesh.tessfaces[face_num]; + int4 vi = get_int4(f.vertices_raw()); + + return (vi[3] == 0)? 3: 4; +} + +static void mikk_get_position(const SMikkTSpaceContext *context, float P[3], const int face_num, const int vert_num) +{ + MikkUserData *userdata = (MikkUserData*)context->m_pUserData; + BL::MeshTessFace f = userdata->mesh.tessfaces[face_num]; + int4 vi = get_int4(f.vertices_raw()); + BL::MeshVertex v = userdata->mesh.vertices[vi[vert_num]]; + float3 vP = get_float3(v.co()); + + P[0] = vP.x; + P[1] = vP.y; + P[2] = vP.z; +} + +static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, float uv[2], const int face_num, const int vert_num) +{ + MikkUserData *userdata = (MikkUserData*)context->m_pUserData; + BL::MeshTextureFace tf = userdata->layer.data[face_num]; + float3 tfuv; + + if(vert_num == 0) + tfuv = get_float3(tf.uv1()); + else if(vert_num == 1) + tfuv = get_float3(tf.uv2()); + else if(vert_num == 2) + tfuv = get_float3(tf.uv3()); + else + tfuv = get_float3(tf.uv4()); + + uv[0] = tfuv.x; + uv[1] = tfuv.y; +} + +static void mikk_get_normal(const SMikkTSpaceContext *context, float N[3], const int face_num, const int vert_num) +{ + MikkUserData *userdata = (MikkUserData*)context->m_pUserData; + BL::MeshTessFace f = userdata->mesh.tessfaces[face_num]; + int4 vi = get_int4(f.vertices_raw()); + BL::MeshVertex v = userdata->mesh.vertices[vi[vert_num]]; + float3 vN = get_float3(v.normal()); + + N[0] = vN.x; + N[1] = vN.y; + N[2] = vN.z; +} + +static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const float T[], const float sign, const int face, const int vert) +{ + MikkUserData *userdata = (MikkUserData*)context->m_pUserData; + + userdata->tangent[face*4 + vert] = make_float4(T[0], T[1], T[2], sign); +} + +static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_layer, Mesh *mesh, vector& nverts) +{ + /* setup userdata */ + MikkUserData userdata(b_mesh, b_layer, nverts.size()); + + /* setup interface */ + SMikkTSpaceInterface sm_interface; + memset(&sm_interface, 0, sizeof(sm_interface)); + sm_interface.m_getNumFaces = mikk_get_num_faces; + sm_interface.m_getNumVerticesOfFace = mikk_get_num_verts_of_face; + sm_interface.m_getPosition = mikk_get_position; + sm_interface.m_getTexCoord = mikk_get_texture_coordinate; + sm_interface.m_getNormal = mikk_get_normal; + sm_interface.m_setTSpaceBasic = mikk_set_tangent_space; + + /* setup context */ + SMikkTSpaceContext context; + memset(&context, 0, sizeof(context)); + context.m_pUserData = &userdata; + context.m_pInterface = &sm_interface; + + /* compute tangents */ + genTangSpaceDefault(&context); + + /* create attribute */ + /* todo: create float4 attribute for sign */ + Attribute *attr = mesh->attributes.add(ATTR_STD_TANGENT, ustring("tangent")); + float3 *tangent = attr->data_float3(); + + for (int i = 0; i < nverts.size(); i++) { + tangent[0] = float4_to_float3(userdata.tangent[i*4 + 0]); + tangent[1] = float4_to_float3(userdata.tangent[i*4 + 1]); + tangent[2] = float4_to_float3(userdata.tangent[i*4 + 2]); + tangent += 3; + + if(nverts[i] == 4) { + tangent[0] = float4_to_float3(userdata.tangent[i*4 + 0]); + tangent[1] = float4_to_float3(userdata.tangent[i*4 + 2]); + tangent[2] = float4_to_float3(userdata.tangent[i*4 + 3]); + tangent += 3; + } + } +} + +/* Create Mesh */ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector& used_shaders) { @@ -67,27 +196,6 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< nverts.push_back(n); } - /* create generated coordinates. todo: we should actually get the orco - * coordinates from modifiers, for now we use texspace loc/size which - * is available in the api. */ - if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) { - Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED); - float3 loc = get_float3(b_mesh.texspace_location()); - float3 size = get_float3(b_mesh.texspace_size()); - - if(size.x != 0.0f) size.x = 0.5f/size.x; - if(size.y != 0.0f) size.y = 0.5f/size.y; - if(size.z != 0.0f) size.z = 0.5f/size.z; - - loc = loc*size - make_float3(0.5f, 0.5f, 0.5f); - - float3 *fdata = attr->data_float3(); - size_t i = 0; - - for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) - fdata[i++] = get_float3(v->co())*size - loc; - } - /* create vertex color attributes */ { BL::Mesh::tessface_vertex_colors_iterator l; @@ -157,6 +265,39 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< } } } + + /* create texcoord-based tangent attributes */ + if(mesh->need_attribute(scene, ATTR_STD_TANGENT)) { + BL::Mesh::tessface_uv_textures_iterator l; + + for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) { + if(!l->active_render()) + continue; + + mikk_compute_tangents(b_mesh, *l, mesh, nverts); + } + } + + /* create generated coordinates. todo: we should actually get the orco + * coordinates from modifiers, for now we use texspace loc/size which + * is available in the api. */ + if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) { + Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED); + float3 loc = get_float3(b_mesh.texspace_location()); + float3 size = get_float3(b_mesh.texspace_size()); + + if(size.x != 0.0f) size.x = 0.5f/size.x; + if(size.y != 0.0f) size.y = 0.5f/size.y; + if(size.z != 0.0f) size.z = 0.5f/size.z; + + loc = loc*size - make_float3(0.5f, 0.5f, 0.5f); + + float3 *generated = attr->data_float3(); + size_t i = 0; + + for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) + generated[i++] = get_float3(v->co())*size - loc; + } } static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector& used_shaders) @@ -270,7 +411,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated) create_mesh(scene, mesh, b_mesh, used_shaders); /* free derived mesh */ - object_remove_mesh(b_data, b_mesh); + b_data.meshes.remove(b_mesh); } /* displacement method */ @@ -328,7 +469,7 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion) mesh->attributes.remove(std); /* free derived mesh */ - object_remove_mesh(b_data, b_mesh); + b_data.meshes.remove(b_mesh); } } diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index eb9deb0de2d..1b920249733 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -17,12 +17,14 @@ */ #include "camera.h" +#include "integrator.h" #include "graph.h" #include "light.h" #include "mesh.h" #include "object.h" #include "scene.h" #include "nodes.h" +#include "particles.h" #include "shader.h" #include "blender_sync.h" @@ -194,8 +196,10 @@ void BlenderSync::sync_background_light() /* Object */ -void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm, uint layer_flag, int motion, int particle_id) +void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject b_dupli_ob, Transform& tfm, uint layer_flag, int motion, int particle_id) { + BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent); + /* light is handled separately */ if(object_is_light(b_ob)) { if(!motion) @@ -225,7 +229,9 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, object->use_motion = true; } - sync_mesh_motion(b_ob, object->mesh, motion); + /* mesh deformation blur not supported yet */ + if(!scene->integrator->motion_blur) + sync_mesh_motion(b_ob, object->mesh, motion); } return; @@ -274,6 +280,15 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, object->visibility &= ~PATH_RAY_CAMERA; } + if (b_dupli_ob) { + object->dupli_generated = get_float3(b_dupli_ob.orco()); + object->dupli_uv = get_float2(b_dupli_ob.uv()); + } + else { + object->dupli_generated = make_float3(0.0f, 0.0f, 0.0f); + object->dupli_uv = make_float2(0.0f, 0.0f); + } + object->particle_id = particle_id; object->tag_update(scene); @@ -293,6 +308,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) mesh_map.pre_sync(); object_map.pre_sync(); mesh_synced.clear(); + particle_system_map.pre_sync(); } /* object loop */ @@ -309,15 +325,15 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) hide = hide || !(ob_layer & scene_layer); if(!hide) { - progress.set_status("Synchronizing object", (*b_ob).name()); + progress.set_sync_status("Synchronizing object", (*b_ob).name()); int num_particles = object_count_particles(*b_ob); if(b_ob->is_duplicator()) { - hide = true; /* duplicators hidden by default */ + hide = true; /* duplicators hidden by default */ /* dupli objects */ - object_create_duplilist(*b_ob, b_scene); + b_ob->dupli_list_create(b_scene, 2); BL::Object::dupli_list_iterator b_dup; int b_index = 0; @@ -326,27 +342,42 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) Transform tfm = get_transform(b_dup->matrix()); BL::Object b_dup_ob = b_dup->object(); bool dup_hide = (b_v3d)? b_dup_ob.hide(): b_dup_ob.hide_render(); + bool emitter_hide = false; - if(!(b_dup->hide() || dup_hide)) { - sync_object(*b_ob, b_index, b_dup_ob, tfm, ob_layer, motion, b_dup->particle_index() + particle_offset); + if(b_dup_ob.is_duplicator()) { + emitter_hide = true; /* duplicators hidden by default */ + + /* check if we should render or hide particle emitter */ + BL::Object::particle_systems_iterator b_psys; + for(b_dup_ob.particle_systems.begin(b_psys); b_psys != b_dup_ob.particle_systems.end(); ++b_psys) + if(b_psys->settings().use_render_emitter()) + emitter_hide = false; + } + + if(!(b_dup->hide() || dup_hide || emitter_hide)) { + sync_object(*b_ob, b_index, *b_dup, tfm, ob_layer, motion, b_dup->particle_index() + particle_offset); } ++b_index; } - object_free_duplilist(*b_ob); + b_ob->dupli_list_clear(); } - /* check if we should render or hide particle emitter */ + /* sync particles and check if we should render or hide particle emitter */ BL::Object::particle_systems_iterator b_psys; - for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) + for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) { + if(!motion) + sync_particles(*b_ob, *b_psys); + if(b_psys->settings().use_render_emitter()) hide = false; + } if(!hide) { /* object itself */ Transform tfm = get_transform(b_ob->matrix_world()); - sync_object(*b_ob, 0, *b_ob, tfm, ob_layer, motion, 0); + sync_object(*b_ob, 0, PointerRNA_NULL, tfm, ob_layer, motion, 0); } particle_offset += num_particles; @@ -356,6 +387,8 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) } } + progress.set_sync_status(""); + if(!cancel && !motion) { sync_background_light(); @@ -366,6 +399,8 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) scene->mesh_manager->tag_update(scene); if(object_map.post_sync()) scene->object_manager->tag_update(scene); + if(particle_system_map.post_sync()) + scene->particle_system_manager->tag_update(scene); mesh_synced.clear(); } } @@ -380,11 +415,13 @@ void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override) if(b_override) b_cam = b_override; + Camera prevcam = *(scene->camera); + /* go back and forth one frame */ int frame = b_scene.frame_current(); for(int motion = -1; motion <= 1; motion += 2) { - scene_frame_set(b_scene, frame + motion); + b_scene.frame_set(frame + motion, 0.0f); /* camera object */ if(b_cam) @@ -394,7 +431,11 @@ void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override) sync_objects(b_v3d, motion); } - scene_frame_set(b_scene, frame); + b_scene.frame_set(frame, 0.0f); + + /* tag camera for motion update */ + if(scene->camera->motion_modified(prevcam)) + scene->camera->tag_update(); } CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp index f309960fc55..c4c6d2f79a3 100644 --- a/intern/cycles/blender/blender_particles.cpp +++ b/intern/cycles/blender/blender_particles.cpp @@ -51,7 +51,7 @@ bool BlenderSync::psys_need_update(BL::ParticleSystem b_psys) case BL::ParticleSettings::render_type_PATH: { /* for strand rendering */ BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob.data(); Mesh *mesh = mesh_map.find(key); - if (mesh) { + if(mesh) { need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update; } break; @@ -60,10 +60,10 @@ bool BlenderSync::psys_need_update(BL::ParticleSystem b_psys) case BL::ParticleSettings::render_type_OBJECT: { BL::Object b_dupli_ob = b_psys.settings().dupli_object(); - if (b_dupli_ob) { + if(b_dupli_ob) { BL::ID key = (BKE_object_is_modified(b_dupli_ob))? b_dupli_ob: b_dupli_ob.data(); Mesh *mesh = mesh_map.find(key); - if (mesh) { + if(mesh) { need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update; } } @@ -72,12 +72,12 @@ bool BlenderSync::psys_need_update(BL::ParticleSystem b_psys) case BL::ParticleSettings::render_type_GROUP: { BL::Group b_dupli_group = b_psys.settings().dupli_group(); - if (b_dupli_group) { + if(b_dupli_group) { BL::Group::objects_iterator b_gob; for (b_dupli_group.objects.begin(b_gob); b_gob != b_dupli_group.objects.end(); ++b_gob) { BL::ID key = (BKE_object_is_modified(*b_gob))? *b_gob: b_gob->data(); Mesh *mesh = mesh_map.find(key); - if (mesh) { + if(mesh) { need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update; } } @@ -109,38 +109,43 @@ static bool use_particle_system(BL::ParticleSystem b_psys) return true; } -static bool use_particle(BL::Particle b_pa) +static bool use_particle(BL::Particle b_pa, bool preview, bool show_unborn, bool use_dead) { - return b_pa.is_exist() && b_pa.is_visible() && - (b_pa.alive_state()==BL::Particle::alive_state_ALIVE || b_pa.alive_state()==BL::Particle::alive_state_DYING); + return b_pa.is_exist() && (!preview || b_pa.is_visible()) && + (b_pa.alive_state() != BL::Particle::alive_state_UNBORN || show_unborn) && + (b_pa.alive_state() != BL::Particle::alive_state_DEAD || use_dead); } -static int psys_count_particles(BL::ParticleSystem b_psys) +static int psys_count_particles(BL::ParticleSystem b_psys, bool preview) { - int tot = 0; BL::ParticleSystem::particles_iterator b_pa; - for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) { - if(use_particle(*b_pa)) - ++tot; - } - return tot; + bool show_unborn = b_psys.settings().show_unborn(); + bool use_dead = b_psys.settings().use_dead(); + int num = 0; + + for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) + if(use_particle(*b_pa, preview, show_unborn, use_dead)) + ++num; + + return num; } int BlenderSync::object_count_particles(BL::Object b_ob) { - int tot = 0; BL::Object::particle_systems_iterator b_psys; - for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) { - if (use_particle_system(*b_psys)) - tot += psys_count_particles(*b_psys); - } - return tot; + int num = 0; + + for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) + if(use_particle_system(*b_psys)) + num += psys_count_particles(*b_psys, preview); + + return num; } void BlenderSync::sync_particles(BL::Object b_ob, BL::ParticleSystem b_psys) { /* depending on settings the psys may not even be rendered */ - if (!use_particle_system(b_psys)) + if(!use_particle_system(b_psys)) return; /* key to lookup particle system */ @@ -155,15 +160,19 @@ void BlenderSync::sync_particles(BL::Object b_ob, BL::ParticleSystem b_psys) bool need_update = psys_need_update(b_psys); - if (object_updated || need_update) { - int tot = psys_count_particles(b_psys); + if(object_updated || need_update) { + bool show_unborn = b_psys.settings().show_unborn(); + bool use_dead = b_psys.settings().use_dead(); + + int num = psys_count_particles(b_psys, preview); psys->particles.clear(); - psys->particles.reserve(tot); + psys->particles.reserve(num); - int index = 0; BL::ParticleSystem::particles_iterator b_pa; + int index = 0; + for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) { - if(use_particle(*b_pa)) { + if(use_particle(*b_pa, preview, show_unborn, use_dead)) { Particle pa; pa.index = index; @@ -185,34 +194,4 @@ void BlenderSync::sync_particles(BL::Object b_ob, BL::ParticleSystem b_psys) } } -void BlenderSync::sync_particle_systems() -{ - /* layer data */ - uint scene_layer = render_layer.scene_layer; - - particle_system_map.pre_sync(); - - /* object loop */ - BL::Scene::objects_iterator b_ob; - BL::Scene b_sce = b_scene; - - for(; b_sce; b_sce = b_sce.background_set()) { - for(b_sce.objects.begin(b_ob); b_ob != b_sce.objects.end(); ++b_ob) { - bool hide = (render_layer.use_viewport_visibility)? b_ob->hide(): b_ob->hide_render(); - uint ob_layer = get_layer(b_ob->layers(), b_ob->layers_local_view(), render_layer.use_localview, object_is_light(*b_ob)); - hide = hide || !(ob_layer & scene_layer); - - if(!hide) { - BL::Object::particle_systems_iterator b_psys; - for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) - sync_particles(*b_ob, *b_psys); - } - } - } - - /* handle removed data and modified pointers */ - if(particle_system_map.post_sync()) - scene->particle_system_manager->tag_update(scene); -} - CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index 96d5bb61ff8..c047805c6ae 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -24,9 +24,17 @@ #include "blender_session.h" #include "util_foreach.h" +#include "util_md5.h" #include "util_opengl.h" #include "util_path.h" +#ifdef WITH_OSL +#include "osl.h" + +#include +#include +#endif + CCL_NAMESPACE_BEGIN static PyObject *init_func(PyObject *self, PyObject *args) @@ -163,6 +171,170 @@ static PyObject *available_devices_func(PyObject *self, PyObject *args) return ret; } +#ifdef WITH_OSL +static PyObject *osl_update_node_func(PyObject *self, PyObject *args) +{ + PyObject *pynodegroup, *pynode; + const char *filepath = NULL; + + if(!PyArg_ParseTuple(args, "OOs", &pynodegroup, &pynode, &filepath)) + return NULL; + + /* RNA */ + PointerRNA nodeptr; + RNA_pointer_create((ID*)PyLong_AsVoidPtr(pynodegroup), &RNA_ShaderNodeScript, (void*)PyLong_AsVoidPtr(pynode), &nodeptr); + BL::ShaderNodeScript b_node(nodeptr); + + /* update bytecode hash */ + string bytecode = b_node.bytecode(); + + if(!bytecode.empty()) { + MD5Hash md5; + md5.append((const uint8_t*)bytecode.c_str(), bytecode.size()); + b_node.bytecode_hash(md5.get_hex().c_str()); + } + else + b_node.bytecode_hash(""); + + /* query from file path */ + OSL::OSLQuery query; + + if(!OSLShaderManager::osl_query(query, filepath)) + Py_RETURN_FALSE; + + /* add new sockets from parameters */ + set used_sockets; + + for(int i = 0; i < query.nparams(); i++) { + const OSL::OSLQuery::Parameter *param = query.getparam(i); + + /* skip unsupported types */ + if(param->varlenarray || param->isstruct || param->type.arraylen > 1) + continue; + + /* determine socket type */ + BL::NodeSocket::type_enum socket_type; + float default_float4[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + float default_float = 0.0f; + int default_int = 0; + + if(param->isclosure) { + socket_type = BL::NodeSocket::type_SHADER; + } + else if(param->type.vecsemantics == TypeDesc::COLOR) { + socket_type = BL::NodeSocket::type_RGBA; + + if(param->validdefault) { + default_float4[0] = param->fdefault[0]; + default_float4[1] = param->fdefault[1]; + default_float4[2] = param->fdefault[2]; + } + } + else if(param->type.vecsemantics == TypeDesc::POINT || + param->type.vecsemantics == TypeDesc::VECTOR || + param->type.vecsemantics == TypeDesc::NORMAL) { + socket_type = BL::NodeSocket::type_VECTOR; + + if(param->validdefault) { + default_float4[0] = param->fdefault[0]; + default_float4[1] = param->fdefault[1]; + default_float4[2] = param->fdefault[2]; + } + } + else if(param->type.aggregate == TypeDesc::SCALAR) { + if(param->type.basetype == TypeDesc::INT) { + socket_type = BL::NodeSocket::type_INT; + if(param->validdefault) + default_int = param->idefault[0]; + } + else if(param->type.basetype == TypeDesc::FLOAT) { + socket_type = BL::NodeSocket::type_VALUE; + if(param->validdefault) + default_float = param->fdefault[0]; + } + } + else + continue; + + /* find socket socket */ + BL::NodeSocket b_sock = b_node.find_socket(param->name.c_str(), param->isoutput); + + /* remove if type no longer matches */ + if(b_sock && b_sock.type() != socket_type) { + b_node.remove_socket(b_sock); + b_sock = BL::NodeSocket(PointerRNA_NULL); + } + + /* create new socket */ + if(!b_sock) { + b_sock = b_node.add_socket(param->name.c_str(), socket_type, param->isoutput); + + /* set default value */ + if(socket_type == BL::NodeSocket::type_VALUE) { + BL::NodeSocketFloatNone b_float_sock(b_sock.ptr); + b_float_sock.default_value(default_float); + } + else if(socket_type == BL::NodeSocket::type_INT) { + BL::NodeSocketIntNone b_int_sock(b_sock.ptr); + b_int_sock.default_value(default_int); + } + else if(socket_type == BL::NodeSocket::type_RGBA) { + BL::NodeSocketRGBA b_rgba_sock(b_sock.ptr); + b_rgba_sock.default_value(default_float4); + } + else if(socket_type == BL::NodeSocket::type_VECTOR) { + BL::NodeSocketVectorNone b_vector_sock(b_sock.ptr); + b_vector_sock.default_value(default_float4); + } + } + + used_sockets.insert(b_sock.ptr.data); + } + + /* remove unused parameters */ + bool removed; + + do { + BL::Node::inputs_iterator b_input; + BL::Node::outputs_iterator b_output; + + removed = false; + + for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) { + if(used_sockets.find(b_input->ptr.data) == used_sockets.end()) { + b_node.remove_socket(*b_input); + removed = true; + break; + } + } + + for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) { + if(used_sockets.find(b_output->ptr.data) == used_sockets.end()) { + b_node.remove_socket(*b_output); + removed = true; + break; + } + } + } while(removed); + + Py_RETURN_TRUE; +} + +static PyObject *osl_compile_func(PyObject *self, PyObject *args) +{ + const char *inputfile = NULL, *outputfile = NULL; + + if(!PyArg_ParseTuple(args, "ss", &inputfile, &outputfile)) + return NULL; + + /* return */ + if(!OSLShaderManager::osl_compile(inputfile, outputfile)) + Py_RETURN_FALSE; + + Py_RETURN_TRUE; +} +#endif + static PyMethodDef methods[] = { {"init", init_func, METH_VARARGS, ""}, {"create", create_func, METH_VARARGS, ""}, @@ -170,6 +342,10 @@ static PyMethodDef methods[] = { {"render", render_func, METH_O, ""}, {"draw", draw_func, METH_VARARGS, ""}, {"sync", sync_func, METH_O, ""}, +#ifdef WITH_OSL + {"osl_update_node", osl_update_node_func, METH_VARARGS, ""}, + {"osl_compile", osl_compile_func, METH_VARARGS, ""}, +#endif {"available_devices", available_devices_func, METH_NOARGS, ""}, {NULL, NULL, 0, NULL}, }; @@ -183,7 +359,7 @@ static struct PyModuleDef module = { NULL, NULL, NULL, NULL }; -CCLDeviceInfo *compute_device_list(DeviceType type) +static CCLDeviceInfo *compute_device_list(DeviceType type) { /* device list stored static */ static ccl::vector device_list; diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 5930a2800bf..01bd5f013e3 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -105,7 +105,7 @@ void BlenderSession::create_session() sync->sync_camera(b_engine.camera_override(), width, height); /* set buffer parameters */ - BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_v3d, b_rv3d, scene->camera, width, height); session->reset(buffer_params, session_params.samples); } @@ -178,15 +178,12 @@ static PassType get_pass_type(BL::RenderPass b_pass) static BL::RenderResult begin_render_result(BL::RenderEngine b_engine, int x, int y, int w, int h, const char *layername) { - RenderResult *rrp = RE_engine_begin_result((RenderEngine*)b_engine.ptr.data, x, y, w, h, layername); - PointerRNA rrptr; - RNA_pointer_create(NULL, &RNA_RenderResult, rrp, &rrptr); - return BL::RenderResult(rrptr); + return b_engine.begin_result(x, y, w, h, layername); } static void end_render_result(BL::RenderEngine b_engine, BL::RenderResult b_rr, bool cancel = false) { - RE_engine_end_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data, (int)cancel); + b_engine.end_result(b_rr, (int)cancel); } void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_update_only) @@ -239,7 +236,7 @@ void BlenderSession::render() /* get buffer parameters */ SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); - BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_v3d, b_rv3d, scene->camera, width, height); /* render each layer */ BL::RenderSettings r = b_scene.render(); @@ -335,16 +332,16 @@ void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::Re /* copy pixels */ if(buffers->get_pass_rect(pass_type, exposure, rtile.sample, components, &pixels[0])) - rna_RenderPass_rect_set(&b_pass.ptr, &pixels[0]); + b_pass.rect(&pixels[0]); } } /* copy combined pass */ if(buffers->get_pass_rect(PASS_COMBINED, exposure, rtile.sample, 4, &pixels[0])) - rna_RenderLayer_rect_set(&b_rlay.ptr, &pixels[0]); + b_rlay.rect(&pixels[0]); /* tag result as updated */ - RE_engine_update_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data); + b_engine.update_result(b_rr); } void BlenderSession::write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile) @@ -372,12 +369,6 @@ void BlenderSession::synchronize() return; } - /* if the session is still resetting the device come back later */ - if(session->resetting()) { - tag_update(); - return; - } - /* increase samples, but never decrease */ session->set_samples(session_params.samples); session->set_pause(BlenderSync::get_session_pause(b_scene, background)); @@ -405,7 +396,7 @@ void BlenderSession::synchronize() /* reset if needed */ if(scene->need_reset()) { - BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_v3d, b_rv3d, scene->camera, width, height); session->reset(buffer_params, session_params.samples); } } @@ -443,7 +434,7 @@ bool BlenderSession::draw(int w, int h) /* reset if requested */ if(reset) { SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); - BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, w, h); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_v3d, b_rv3d, scene->camera, w, h); session->reset(buffer_params, session_params.samples); } @@ -453,7 +444,7 @@ bool BlenderSession::draw(int w, int h) update_status_progress(); /* draw */ - BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height); + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_v3d, b_rv3d, scene->camera, width, height); return !session->draw(buffer_params); } @@ -472,9 +463,12 @@ void BlenderSession::get_progress(float& progress, double& total_time) session->progress.get_tile(tile, total_time, tile_time); sample = session->progress.get_sample(); - samples_per_tile = session->tile_manager.state.num_samples; + samples_per_tile = session->params.samples; - progress = ((float)sample/(float)(tile_total * samples_per_tile)); + if(samples_per_tile) + progress = ((float)sample/(float)(tile_total * samples_per_tile)); + else + progress = 0.0; } void BlenderSession::update_status_progress() @@ -483,11 +477,15 @@ void BlenderSession::update_status_progress() float progress; double total_time; char time_str[128]; + float mem_used = (float)session->stats.mem_used / 1024.0f / 1024.0f; + float mem_peak = (float)session->stats.mem_peak / 1024.0f / 1024.0f; get_status(status, substatus); get_progress(progress, total_time); - timestatus = b_scene.name(); + timestatus = string_printf("Mem: %.2fM, Peak: %.2fM | ", mem_used, mem_peak); + + timestatus += b_scene.name(); if(b_rlay_name != "") timestatus += ", " + b_rlay_name; timestatus += " | "; @@ -499,11 +497,12 @@ void BlenderSession::update_status_progress() status += " | " + substatus; if(status != last_status) { - RE_engine_update_stats((RenderEngine*)b_engine.ptr.data, "", (timestatus + status).c_str()); + b_engine.update_stats("", (timestatus + status).c_str()); + b_engine.update_memory_stats(mem_used, mem_peak); last_status = status; } if(progress != last_progress) { - RE_engine_update_progress((RenderEngine*)b_engine.ptr.data, progress); + b_engine.update_progress(progress); last_progress = progress; } } @@ -511,7 +510,7 @@ void BlenderSession::update_status_progress() void BlenderSession::tag_update() { /* tell blender that we want to get another update callback */ - engine_tag_update((RenderEngine*)b_engine.ptr.data); + b_engine.tag_update(); } void BlenderSession::tag_redraw() @@ -523,13 +522,13 @@ void BlenderSession::tag_redraw() /* offline render, redraw if timeout passed */ if(time_dt() - last_redraw_time > 1.0) { - engine_tag_redraw((RenderEngine*)b_engine.ptr.data); + b_engine.tag_redraw(); last_redraw_time = time_dt(); } } else { /* tell blender that we want to redraw */ - engine_tag_redraw((RenderEngine*)b_engine.ptr.data); + b_engine.tag_redraw(); } } @@ -537,7 +536,7 @@ void BlenderSession::test_cancel() { /* test if we need to cancel rendering */ if(background) - if(RE_engine_test_break((RenderEngine*)b_engine.ptr.data)) + if(b_engine.test_break()) session->progress.set_cancel("Cancelled"); } diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 9758d9bf92a..9e3380c6f8e 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -20,6 +20,7 @@ #include "graph.h" #include "light.h" #include "nodes.h" +#include "osl.h" #include "scene.h" #include "shader.h" @@ -43,6 +44,7 @@ void BlenderSync::find_shader(BL::ID id, vector& used_shaders, int default for(size_t i = 0; i < scene->shaders.size(); i++) { if(scene->shaders[i] == shader) { used_shaders.push_back(i); + scene->shaders[i]->tag_used(scene); break; } } @@ -80,6 +82,8 @@ static ShaderSocketType convert_socket_type(BL::NodeSocket::type_enum b_type) switch (b_type) { case BL::NodeSocket::type_VALUE: return SHADER_SOCKET_FLOAT; + case BL::NodeSocket::type_INT: + return SHADER_SOCKET_INT; case BL::NodeSocket::type_VECTOR: return SHADER_SOCKET_VECTOR; case BL::NodeSocket::type_RGBA: @@ -89,7 +93,6 @@ static ShaderSocketType convert_socket_type(BL::NodeSocket::type_enum b_type) case BL::NodeSocket::type_BOOLEAN: case BL::NodeSocket::type_MESH: - case BL::NodeSocket::type_INT: default: return SHADER_SOCKET_FLOAT; } @@ -104,6 +107,11 @@ static void set_default_value(ShaderInput *input, BL::NodeSocket sock) input->set(value_sock.default_value()); break; } + case SHADER_SOCKET_INT: { + BL::NodeSocketIntNone value_sock(sock); + input->set((float)value_sock.default_value()); + break; + } case SHADER_SOCKET_COLOR: { BL::NodeSocketRGBA rgba_sock(sock); input->set(get_float3(rgba_sock.default_value())); @@ -152,7 +160,7 @@ static void get_tex_mapping(TextureMapping *mapping, BL::ShaderNodeMapping b_map mapping->max = get_float3(b_mapping.max()); } -static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNode b_node) +static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, BL::ShaderNode b_node) { ShaderNode *node = NULL; @@ -315,6 +323,10 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph node = new HoldoutNode(); break; } + case BL::ShaderNode::type_BSDF_ANISOTROPIC: { + node = new WardBsdfNode(); + break; + } case BL::ShaderNode::type_BSDF_DIFFUSE: { node = new DiffuseBsdfNode(); break; @@ -398,12 +410,68 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph node = new ParticleInfoNode(); break; } + case BL::ShaderNode::type_BUMP: { + node = new BumpNode(); + break; + } + case BL::ShaderNode::type_SCRIPT: { +#ifdef WITH_OSL + if(scene->params.shadingsystem != SceneParams::OSL) + break; + + /* create script node */ + BL::ShaderNodeScript b_script_node(b_node); + OSLScriptNode *script_node = new OSLScriptNode(); + + /* Generate inputs/outputs from node sockets + * + * Note: the node sockets are generated from OSL parameters, + * so the names match those of the corresponding parameters exactly. + * + * Note 2: ShaderInput/ShaderOutput store shallow string copies only! + * Socket names must be stored in the extra lists instead. */ + BL::Node::inputs_iterator b_input; + + for (b_script_node.inputs.begin(b_input); b_input != b_script_node.inputs.end(); ++b_input) { + script_node->input_names.push_back(ustring(b_input->name())); + ShaderInput *input = script_node->add_input(script_node->input_names.back().c_str(), convert_socket_type(b_input->type())); + set_default_value(input, *b_input); + } + + BL::Node::outputs_iterator b_output; + + for (b_script_node.outputs.begin(b_output); b_output != b_script_node.outputs.end(); ++b_output) { + script_node->output_names.push_back(ustring(b_output->name())); + script_node->add_output(script_node->output_names.back().c_str(), convert_socket_type(b_output->type())); + } + + /* load bytecode or filepath */ + OSLShaderManager *manager = (OSLShaderManager*)scene->shader_manager; + string bytecode_hash = b_script_node.bytecode_hash(); + + if(!bytecode_hash.empty()) { + /* loaded bytecode if not already done */ + if(!manager->shader_test_loaded(bytecode_hash)) + manager->shader_load_bytecode(bytecode_hash, b_script_node.bytecode()); + + script_node->bytecode_hash = bytecode_hash; + } + else { + /* set filepath */ + script_node->filepath = blender_absolute_path(b_data, b_ntree, b_script_node.filepath()); + } + + node = script_node; +#endif + + break; + } case BL::ShaderNode::type_TEX_IMAGE: { BL::ShaderNodeTexImage b_image_node(b_node); BL::Image b_image(b_image_node.image()); ImageTextureNode *image = new ImageTextureNode(); /* todo: handle generated/builtin images */ - if(b_image) + if(b_image && b_image.source() != BL::Image::source_MOVIE) image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current()); image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()]; image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()]; @@ -416,7 +484,7 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph BL::ShaderNodeTexEnvironment b_env_node(b_node); BL::Image b_image(b_env_node.image()); EnvironmentTextureNode *env = new EnvironmentTextureNode(); - if(b_image) + if(b_image && b_image.source() != BL::Image::source_MOVIE) env->filename = image_user_file_path(b_env_node.image_user(), b_image, b_scene.frame_current()); env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()]; env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()]; @@ -490,7 +558,10 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph break; } case BL::ShaderNode::type_TEX_COORD: { - node = new TextureCoordinateNode(); + BL::ShaderNodeTexCoord b_tex_coord_node(b_node); + TextureCoordinateNode *tex_coord = new TextureCoordinateNode(); + tex_coord->from_dupli = b_tex_coord_node.from_dupli(); + node = tex_coord; break; } case BL::ShaderNode::type_TEX_SKY: { @@ -558,7 +629,7 @@ static SocketPair node_socket_map_pair(PtrNodeMap& node_map, BL::Node b_node, BL return SocketPair(node_map[b_node.ptr.data], name); } -static void add_nodes(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, PtrSockMap& sockets_map) +static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, PtrSockMap& sockets_map) { /* add nodes */ BL::ShaderNodeTree::nodes_iterator b_node; @@ -566,7 +637,34 @@ static void add_nodes(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *grap PtrSockMap proxy_map; for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) { - if(b_node->is_a(&RNA_NodeGroup)) { + if(b_node->mute()) { + BL::Node::inputs_iterator b_input; + BL::Node::outputs_iterator b_output; + bool found_match = false; + + /* this is slightly different than blender logic, we just connect a + * single pair for of input/output, but works ok for the node we have */ + for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { + if(b_input->is_linked()) { + for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { + if(b_output->is_linked() && b_input->type() == b_output->type()) { + ProxyNode *proxy = new ProxyNode(convert_socket_type(b_input->type()), convert_socket_type(b_output->type())); + graph->add(proxy); + + proxy_map[b_input->ptr.data] = SocketPair(proxy, proxy->inputs[0]->name); + proxy_map[b_output->ptr.data] = SocketPair(proxy, proxy->outputs[0]->name); + found_match = true; + + break; + } + } + } + + if(found_match) + break; + } + } + else if(b_node->is_a(&RNA_NodeGroup)) { /* add proxy converter nodes for inputs and outputs */ BL::NodeGroup b_gnode(*b_node); BL::ShaderNodeTree b_group_ntree(b_gnode.node_tree()); @@ -606,10 +704,10 @@ static void add_nodes(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *grap set_default_value(proxy->inputs[0], b_output->group_socket()); } - add_nodes(b_data, b_scene, graph, b_group_ntree, group_sockmap); + add_nodes(scene, b_data, b_scene, graph, b_group_ntree, group_sockmap); } else { - ShaderNode *node = add_node(b_data, b_scene, graph, BL::ShaderNode(*b_node)); + ShaderNode *node = add_node(scene, b_data, b_scene, graph, b_ntree, BL::ShaderNode(*b_node)); if(node) { BL::Node::inputs_iterator b_input; @@ -646,7 +744,7 @@ static void add_nodes(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *grap /* from sock */ if(b_from_node) { - if (b_from_node.is_a(&RNA_NodeGroup)) + if (b_from_node.mute() || b_from_node.is_a(&RNA_NodeGroup)) from_pair = proxy_map[b_from_sock.ptr.data]; else from_pair = node_socket_map_pair(node_map, b_from_node, b_from_sock); @@ -656,7 +754,7 @@ static void add_nodes(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *grap /* to sock */ if(b_to_node) { - if (b_to_node.is_a(&RNA_NodeGroup)) + if (b_to_node.mute() || b_to_node.is_a(&RNA_NodeGroup)) to_pair = proxy_map[b_to_sock.ptr.data]; else to_pair = node_socket_map_pair(node_map, b_to_node, b_to_sock); @@ -699,7 +797,7 @@ void BlenderSync::sync_materials() PtrSockMap sock_to_node; BL::ShaderNodeTree b_ntree(b_mat->node_tree()); - add_nodes(b_data, b_scene, graph, b_ntree, sock_to_node); + add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node); } else { ShaderNode *closure, *out; @@ -740,7 +838,7 @@ void BlenderSync::sync_world() PtrSockMap sock_to_node; BL::ShaderNodeTree b_ntree(b_world.node_tree()); - add_nodes(b_data, b_scene, graph, b_ntree, sock_to_node); + add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node); } else if(b_world) { ShaderNode *closure, *out; @@ -799,7 +897,7 @@ void BlenderSync::sync_lamps() PtrSockMap sock_to_node; BL::ShaderNodeTree b_ntree(b_lamp->node_tree()); - add_nodes(b_data, b_scene, graph, b_ntree, sock_to_node); + add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node); } else { ShaderNode *closure, *out; diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 907573cf072..c63f72c68c6 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -17,6 +17,7 @@ */ #include "background.h" +#include "camera.h" #include "film.h" #include "../render/filter.h" #include "graph.h" @@ -141,7 +142,6 @@ void BlenderSync::sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, const sync_film(); sync_shaders(); sync_objects(b_v3d); - sync_particle_systems(); sync_motion(b_v3d, b_override); } @@ -149,6 +149,9 @@ void BlenderSync::sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, const void BlenderSync::sync_integrator() { +#ifdef __CAMERA_MOTION__ + BL::RenderSettings r = b_scene.render(); +#endif PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); experimental = (RNA_enum_get(&cscene, "feature_set") != 0); @@ -175,7 +178,12 @@ void BlenderSync::sync_integrator() integrator->layer_flag = render_layer.layer; integrator->sample_clamp = get_float(cscene, "sample_clamp"); -#ifdef __MOTION__ +#ifdef __CAMERA_MOTION__ + if(integrator->motion_blur != r.use_motion_blur()) { + scene->object_manager->tag_update(scene); + scene->camera->tag_update(); + } + integrator->motion_blur = (!preview && r.use_motion_blur()); #endif @@ -368,7 +376,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use params.tile_size = make_int2(tile_x, tile_y); } - params.resolution = 1 << get_int(cscene, "resolution_divider"); + params.start_resolution = get_int(cscene, "preview_start_resolution"); /* other parameters */ params.threads = b_scene.render().threads(); @@ -377,13 +385,27 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use params.reset_timeout = get_float(cscene, "debug_reset_timeout"); params.text_timeout = get_float(cscene, "debug_text_timeout"); + params.progressive_refine = get_boolean(cscene, "use_progressive_refine"); + if(background) { - params.progressive = false; - params.resolution = 1; + if(params.progressive_refine) + params.progressive = true; + else + params.progressive = false; + + params.start_resolution = INT_MAX; } else params.progressive = true; - + + /* shading system - scene level needs full refresh */ + int shadingsystem = RNA_enum_get(&cscene, "shading_system"); + + if(shadingsystem == 0) + params.shadingsystem = SessionParams::SVM; + else if(shadingsystem == 1) + params.shadingsystem = SessionParams::OSL; + return params; } diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 27f6b6ee4ee..36cd5e684a7 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -63,7 +63,7 @@ public: static SceneParams get_scene_params(BL::Scene b_scene, bool background); static SessionParams get_session_params(BL::RenderEngine b_engine, BL::UserPreferences b_userpref, BL::Scene b_scene, bool background); static bool get_session_pause(BL::Scene b_scene, bool background); - static BufferParams get_buffer_params(BL::Scene b_scene, Camera *cam, int width, int height); + static BufferParams get_buffer_params(BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, Camera *cam, int width, int height); private: /* sync */ @@ -77,11 +77,10 @@ private: void sync_world(); void sync_render_layers(BL::SpaceView3D b_v3d, const char *layer); void sync_shaders(); - void sync_particle_systems(); void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree); Mesh *sync_mesh(BL::Object b_ob, bool object_updated); - void sync_object(BL::Object b_parent, int b_index, BL::Object b_object, Transform& tfm, uint layer_flag, int motion, int particle_id); + void sync_object(BL::Object b_parent, int b_index, BL::DupliObject b_dupli_object, Transform& tfm, uint layer_flag, int motion, int particle_id); void sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm); void sync_background_light(); void sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion); diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index d0fca9a9fb9..df1e99882b8 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -30,29 +30,7 @@ * todo: clean this up ... */ extern "C" { - -struct RenderEngine; -struct RenderResult; - -ID *rna_Object_to_mesh(void *_self, void *reports, void *scene, int apply_modifiers, int settings); -void rna_Main_meshes_remove(void *bmain, void *reports, void *mesh); -void rna_Object_create_duplilist(void *ob, void *reports, void *sce); -void rna_Object_free_duplilist(void *ob, void *reports); -void rna_RenderLayer_rect_set(PointerRNA *ptr, const float *values); -void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values); -struct RenderResult *RE_engine_begin_result(struct RenderEngine *engine, int x, int y, int w, int h, const char *layername); -void RE_engine_update_result(struct RenderEngine *engine, struct RenderResult *result); -void RE_engine_end_result(struct RenderEngine *engine, struct RenderResult *result, int cancel); -int RE_engine_test_break(struct RenderEngine *engine); -void RE_engine_update_stats(struct RenderEngine *engine, const char *stats, const char *info); -void RE_engine_update_progress(struct RenderEngine *engine, float progress); -void engine_tag_redraw(void *engine); -void engine_tag_update(void *engine); -int rna_Object_is_modified(void *ob, void *scene, int settings); -int rna_Object_is_deform_modified(void *ob, void *scene, int settings); void BLI_timestr(double _time, char *str); -void rna_ColorRamp_eval(void *coba, float position, float color[4]); -void rna_Scene_frame_set(void *scene, int frame, float subframe); void BKE_image_user_frame_calc(void *iuser, int cfra, int fieldnr); void BKE_image_user_file_path(void *iuser, void *ima, char *path); } @@ -61,10 +39,7 @@ CCL_NAMESPACE_BEGIN static inline BL::Mesh object_to_mesh(BL::Object self, BL::Scene scene, bool apply_modifiers, bool render) { - ID *data = rna_Object_to_mesh(self.ptr.data, NULL, scene.ptr.data, apply_modifiers, (render)? 2: 1); - PointerRNA ptr; - RNA_id_pointer_create(data, &ptr); - return BL::Mesh(ptr); + return self.to_mesh(scene, apply_modifiers, (render)? 2: 1); } static inline void colorramp_to_array(BL::ColorRamp ramp, float4 *data, int size) @@ -72,34 +47,19 @@ static inline void colorramp_to_array(BL::ColorRamp ramp, float4 *data, int size for(int i = 0; i < size; i++) { float color[4]; - rna_ColorRamp_eval(ramp.ptr.data, i/(float)(size-1), color); + ramp.evaluate(i/(float)(size-1), color); data[i] = make_float4(color[0], color[1], color[2], color[3]); } } -static inline void object_remove_mesh(BL::BlendData data, BL::Mesh mesh) -{ - rna_Main_meshes_remove(data.ptr.data, NULL, mesh.ptr.data); -} - -static inline void object_create_duplilist(BL::Object self, BL::Scene scene) -{ - rna_Object_create_duplilist(self.ptr.data, NULL, scene.ptr.data); -} - -static inline void object_free_duplilist(BL::Object self) -{ - rna_Object_free_duplilist(self.ptr.data, NULL); -} - static inline bool BKE_object_is_modified(BL::Object self, BL::Scene scene, bool preview) { - return rna_Object_is_modified(self.ptr.data, scene.ptr.data, (preview)? (1<<0): (1<<1))? true: false; + return self.is_modified(scene, (preview)? (1<<0): (1<<1))? true: false; } static inline bool BKE_object_is_deform_modified(BL::Object self, BL::Scene scene, bool preview) { - return rna_Object_is_deform_modified(self.ptr.data, scene.ptr.data, (preview)? (1<<0): (1<<1))? true: false; + return self.is_deform_modified(scene, (preview)? (1<<0): (1<<1))? true: false; } static inline string image_user_file_path(BL::ImageUser iuser, BL::Image ima, int cfra) @@ -110,11 +70,6 @@ static inline string image_user_file_path(BL::ImageUser iuser, BL::Image ima, in return string(filepath); } -static inline void scene_frame_set(BL::Scene scene, int frame) -{ - rna_Scene_frame_set(scene.ptr.data, frame, 0.0f); -} - /* Utilities */ static inline Transform get_transform(BL::Array array) diff --git a/intern/cycles/bvh/CMakeLists.txt b/intern/cycles/bvh/CMakeLists.txt index 131a7a1f750..cbbd23fcff8 100644 --- a/intern/cycles/bvh/CMakeLists.txt +++ b/intern/cycles/bvh/CMakeLists.txt @@ -8,6 +8,9 @@ set(INC ../device ) +set(INC_SYS +) + set(SRC bvh.cpp bvh_binning.cpp @@ -28,5 +31,6 @@ set(SRC_HEADERS ) include_directories(${INC}) +include_directories(SYSTEM ${INC_SYS}) add_library(cycles_bvh ${SRC} ${SRC_HEADERS}) diff --git a/intern/cycles/bvh/bvh_node.h b/intern/cycles/bvh/bvh_node.h index 5c00f7b7a38..a0d10a46bfc 100644 --- a/intern/cycles/bvh/bvh_node.h +++ b/intern/cycles/bvh/bvh_node.h @@ -54,7 +54,7 @@ public: // Subtree functions int getSubtreeSize(BVH_STAT stat=BVH_STAT_NODE_COUNT) const; - float computeSubtreeSAHCost(const BVHParams& p, float probability = 1.0f) const; + float computeSubtreeSAHCost(const BVHParams& p, float probability = 1.0f) const; void deleteSubtree(); uint update_visibility(); diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt index 6038abd815e..0071bbe5cdc 100644 --- a/intern/cycles/device/CMakeLists.txt +++ b/intern/cycles/device/CMakeLists.txt @@ -6,6 +6,9 @@ set(INC ../kernel/osl ../util ../render +) + +set(INC_SYS ${OPENGL_INCLUDE_DIR} ${GLEW_INCLUDE_PATH} ) @@ -31,5 +34,6 @@ set(SRC_HEADERS add_definitions(-DGLEW_STATIC) include_directories(${INC}) +include_directories(SYSTEM ${INC_SYS}) add_library(cycles_device ${SRC} ${SRC_HEADERS}) diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index 9a4d364a9b8..550da2982a3 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -28,6 +28,7 @@ #include "util_math.h" #include "util_opencl.h" #include "util_opengl.h" +#include "util_time.h" #include "util_types.h" #include "util_vector.h" @@ -77,36 +78,36 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int w glDisable(GL_BLEND); } -Device *Device::create(DeviceInfo& info, bool background, int threads) +Device *Device::create(DeviceInfo& info, Stats &stats, bool background, int threads) { Device *device; switch(info.type) { case DEVICE_CPU: - device = device_cpu_create(info, threads); + device = device_cpu_create(info, stats, threads); break; #ifdef WITH_CUDA case DEVICE_CUDA: if(cuLibraryInit()) - device = device_cuda_create(info, background); + device = device_cuda_create(info, stats, background); else device = NULL; break; #endif #ifdef WITH_MULTI case DEVICE_MULTI: - device = device_multi_create(info, background); + device = device_multi_create(info, stats, background); break; #endif #ifdef WITH_NETWORK case DEVICE_NETWORK: - device = device_network_create(info, "127.0.0.1"); + device = device_network_create(info, stats, "127.0.0.1"); break; #endif #ifdef WITH_OPENCL case DEVICE_OPENCL: if(clLibraryInit()) - device = device_opencl_create(info, background); + device = device_opencl_create(info, stats, background); else device = NULL; break; @@ -188,6 +189,18 @@ vector& Device::available_devices() { static vector devices; static bool devices_init = false; + static double device_update_time = 0.0; + + /* only update device list if we're not actively rendering already, things + * could go very wrong if a device suddenly becomes (un)available. also do + * it only every 5 seconds. it not super cpu intensive but don't want to do + * it on every redraw. */ + if(devices_init) { + if(!TaskScheduler::active() && (time_dt() > device_update_time + 5.0)) { + devices.clear(); + devices_init = false; + } + } if(!devices_init) { #ifdef WITH_CUDA @@ -211,6 +224,7 @@ vector& Device::available_devices() #endif devices_init = true; + device_update_time = time_dt(); } return devices; diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index 8e3bc408399..95da0a89833 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -25,6 +25,7 @@ #include "device_task.h" #include "util_list.h" +#include "util_stats.h" #include "util_string.h" #include "util_thread.h" #include "util_types.h" @@ -72,7 +73,7 @@ public: class Device { protected: - Device() {} + Device(Stats &stats_) : stats(stats_) {} bool background; string error_msg; @@ -84,6 +85,9 @@ public: DeviceInfo info; virtual const string& error_message() { return error_msg; } + /* statistics */ + Stats &stats; + /* regular memory */ virtual void mem_alloc(device_memory& mem, MemoryType type) = 0; virtual void mem_copy_to(device_memory& mem) = 0; @@ -115,7 +119,6 @@ public: virtual void task_add(DeviceTask& task) = 0; virtual void task_wait() = 0; virtual void task_cancel() = 0; - virtual bool task_cancelled() = 0; /* opengl drawing */ virtual void draw_pixels(device_memory& mem, int y, int w, int h, @@ -131,7 +134,7 @@ public: virtual int device_number(Device *sub_device) { return 0; } /* static */ - static Device *create(DeviceInfo& info, bool background = true, int threads = 0); + static Device *create(DeviceInfo& info, Stats &stats, bool background = true, int threads = 0); static DeviceType type_from_string(const char *name); static string string_from_type(DeviceType type); diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index e2f612ee233..519c458ffdf 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -45,7 +45,7 @@ public: TaskPool task_pool; KernelGlobals *kg; - CPUDevice(int threads_num) + CPUDevice(Stats &stats, int threads_num) : Device(stats) { kg = kernel_globals_create(); @@ -67,6 +67,8 @@ public: void mem_alloc(device_memory& mem, MemoryType type) { mem.device_pointer = mem.data_pointer; + + stats.mem_alloc(mem.memory_size()); } void mem_copy_to(device_memory& mem) @@ -87,6 +89,8 @@ public: void mem_free(device_memory& mem) { mem.device_pointer = 0; + + stats.mem_free(mem.memory_size()); } void const_copy_to(const char *name, void *host, size_t size) @@ -98,11 +102,15 @@ public: { kernel_tex_copy(kg, name, mem.data_pointer, mem.data_width, mem.data_height); mem.device_pointer = mem.data_pointer; + + stats.mem_alloc(mem.memory_size()); } void tex_free(device_memory& mem) { mem.device_pointer = 0; + + stats.mem_free(mem.memory_size()); } void *osl_memory() @@ -135,8 +143,10 @@ public: void thread_path_trace(DeviceTask& task) { - if(task_pool.cancelled()) - return; + if(task_pool.cancelled()) { + if(task.need_finish_queue == false) + return; + } #ifdef WITH_OSL if(kernel_osl_use(kg)) @@ -154,8 +164,10 @@ public: #ifdef WITH_OPTIMIZED_KERNEL if(system_cpu_support_optimized()) { for(int sample = start_sample; sample < end_sample; sample++) { - if (task.get_cancel() || task_pool.cancelled()) - break; + if (task.get_cancel() || task_pool.cancelled()) { + if(task.need_finish_queue == false) + break; + } for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) { @@ -173,8 +185,10 @@ public: #endif { for(int sample = start_sample; sample < end_sample; sample++) { - if (task.get_cancel() || task_pool.cancelled()) - break; + if (task.get_cancel() || task_pool.cancelled()) { + if(task.need_finish_queue == false) + break; + } for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) { @@ -191,8 +205,10 @@ public: task.release_tile(tile); - if(task_pool.cancelled()) - break; + if(task_pool.cancelled()) { + if(task.need_finish_queue == false) + break; + } } #ifdef WITH_OSL @@ -273,16 +289,11 @@ public: { task_pool.cancel(); } - - bool task_cancelled() - { - return task_pool.cancelled(); - } }; -Device *device_cpu_create(DeviceInfo& info, int threads) +Device *device_cpu_create(DeviceInfo& info, Stats &stats, int threads) { - return new CPUDevice(threads); + return new CPUDevice(stats, threads); } void device_cpu_info(vector& devices) diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index acc1086cc35..d797c0f09ca 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -157,7 +157,7 @@ public: cuda_assert(cuCtxSetCurrent(NULL)); } - CUDADevice(DeviceInfo& info, bool background_) + CUDADevice(DeviceInfo& info, Stats &stats, bool background_) : Device(stats) { background = background_; @@ -316,8 +316,10 @@ public: { cuda_push_context(); CUdeviceptr device_pointer; - cuda_assert(cuMemAlloc(&device_pointer, mem.memory_size())) + size_t size = mem.memory_size(); + cuda_assert(cuMemAlloc(&device_pointer, size)) mem.device_pointer = (device_ptr)device_pointer; + stats.mem_alloc(size); cuda_pop_context(); } @@ -356,6 +358,8 @@ public: cuda_pop_context(); mem.device_pointer = 0; + + stats.mem_free(mem.memory_size()); } } @@ -424,6 +428,8 @@ public: cuda_assert(cuTexRefSetFlags(texref, CU_TRSF_NORMALIZED_COORDINATES)) mem.device_pointer = (device_ptr)handle; + + stats.mem_alloc(size); } else { cuda_pop_context(); @@ -463,6 +469,8 @@ public: tex_interp_map.erase(tex_interp_map.find(mem.device_pointer)); mem.device_pointer = 0; + + stats.mem_free(mem.memory_size()); } else { tex_interp_map.erase(tex_interp_map.find(mem.device_pointer)); @@ -707,6 +715,8 @@ public: mem.device_pointer = pmem.cuTexId; pixel_mem_map[mem.device_pointer] = pmem; + stats.mem_alloc(mem.memory_size()); + return; } else { @@ -762,6 +772,8 @@ public: pixel_mem_map.erase(pixel_mem_map.find(mem.device_pointer)); mem.device_pointer = 0; + stats.mem_free(mem.memory_size()); + return; } @@ -837,8 +849,10 @@ public: int end_sample = tile.start_sample + tile.num_samples; for(int sample = start_sample; sample < end_sample; sample++) { - if (task->get_cancel()) - break; + if (task->get_cancel()) { + if(task->need_finish_queue == false) + break; + } path_trace(tile, sample); @@ -892,16 +906,11 @@ public: { task_pool.cancel(); } - - bool task_cancelled() - { - return task_pool.cancelled(); - } }; -Device *device_cuda_create(DeviceInfo& info, bool background) +Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background) { - return new CUDADevice(info, background); + return new CUDADevice(info, stats, background); } void device_cuda_info(vector& devices) diff --git a/intern/cycles/device/device_intern.h b/intern/cycles/device/device_intern.h index e3601aa8ad4..02fbac6860e 100644 --- a/intern/cycles/device/device_intern.h +++ b/intern/cycles/device/device_intern.h @@ -23,11 +23,11 @@ CCL_NAMESPACE_BEGIN class Device; -Device *device_cpu_create(DeviceInfo& info, int threads); -Device *device_opencl_create(DeviceInfo& info, bool background); -Device *device_cuda_create(DeviceInfo& info, bool background); -Device *device_network_create(DeviceInfo& info, const char *address); -Device *device_multi_create(DeviceInfo& info, bool background); +Device *device_cpu_create(DeviceInfo& info, Stats &stats, int threads); +Device *device_opencl_create(DeviceInfo& info, Stats &stats, bool background); +Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background); +Device *device_network_create(DeviceInfo& info, Stats &stats, const char *address); +Device *device_multi_create(DeviceInfo& info, Stats &stats, bool background); void device_cpu_info(vector& devices); void device_opencl_info(vector& devices); diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp index 4923e5c9e66..807bfe578f3 100644 --- a/intern/cycles/device/device_multi.cpp +++ b/intern/cycles/device/device_multi.cpp @@ -46,14 +46,14 @@ public: list devices; device_ptr unique_ptr; - MultiDevice(DeviceInfo& info, bool background_) - : unique_ptr(1) + MultiDevice(DeviceInfo& info, Stats &stats, bool background_) + : Device(stats), unique_ptr(1) { Device *device; background = background_; foreach(DeviceInfo& subinfo, info.multi_devices) { - device = Device::create(subinfo, background); + device = Device::create(subinfo, stats, background); devices.push_back(SubDevice(device)); } @@ -312,19 +312,11 @@ public: foreach(SubDevice& sub, devices) sub.device->task_cancel(); } - - bool task_cancelled() - { - foreach(SubDevice& sub, devices) - if (sub.device->task_cancelled()) - return true; - return false; - } }; -Device *device_multi_create(DeviceInfo& info, bool background) +Device *device_multi_create(DeviceInfo& info, Stats &stats, bool background) { - return new MultiDevice(info, background); + return new MultiDevice(info, stats, background); } static bool device_multi_add(vector& devices, DeviceType type, bool with_display, bool with_advanced_shading, const char *id_fmt, int num) diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp index 931890b5859..a5e0d39df73 100644 --- a/intern/cycles/device/device_network.cpp +++ b/intern/cycles/device/device_network.cpp @@ -32,8 +32,8 @@ public: boost::asio::io_service io_service; tcp::socket socket; - NetworkDevice(const char *address) - : socket(io_service) + NetworkDevice(Stats &stats, const char *address) + : Device(stats), socket(io_service) { stringstream portstr; portstr << SERVER_PORT; @@ -202,9 +202,9 @@ public: } }; -Device *device_network_create(DeviceInfo& info, const char *address) +Device *device_network_create(DeviceInfo& info, Stats &stats, const char *address) { - return new NetworkDevice(address); + return new NetworkDevice(stats, address); } void device_network_info(vector& devices) diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index ed7229d49da..69287f1a8bd 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -144,7 +144,8 @@ public: } } - OpenCLDevice(DeviceInfo& info, bool background_) + OpenCLDevice(DeviceInfo& info, Stats &stats, bool background_) + : Device(stats) { background = background_; cpPlatform = NULL; @@ -473,6 +474,8 @@ public: mem.device_pointer = (device_ptr)clCreateBuffer(cxContext, CL_MEM_READ_WRITE, size, NULL, &ciErr); opencl_assert(ciErr); + + stats.mem_alloc(size); } void mem_copy_to(device_memory& mem) @@ -506,6 +509,8 @@ public: ciErr = clReleaseMemObject(CL_MEM_PTR(mem.device_pointer)); mem.device_pointer = 0; opencl_assert(ciErr); + + stats.mem_free(mem.memory_size()); } } @@ -686,8 +691,10 @@ public: int end_sample = tile.start_sample + tile.num_samples; for(int sample = start_sample; sample < end_sample; sample++) { - if (task->get_cancel()) - break; + if (task->get_cancel()) { + if(task->need_finish_queue == false) + break; + } path_trace(tile, sample); @@ -724,16 +731,11 @@ public: { task_pool.cancel(); } - - bool task_cancelled() - { - return task_pool.cancelled(); - } }; -Device *device_opencl_create(DeviceInfo& info, bool background) +Device *device_opencl_create(DeviceInfo& info, Stats &stats, bool background) { - return new OpenCLDevice(info, background); + return new OpenCLDevice(info, stats, background); } void device_opencl_info(vector& devices) diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h index cfb3d8d988e..8ca8b88ea49 100644 --- a/intern/cycles/device/device_task.h +++ b/intern/cycles/device/device_task.h @@ -65,6 +65,7 @@ public: boost::function release_tile; boost::function get_cancel; + bool need_finish_queue; protected: double last_update_time; }; diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index b43aca24496..82b0605ab6b 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -6,6 +6,10 @@ set(INC svm ) +set(INC_SYS + +) + set(SRC kernel.cpp kernel_optimized.cpp @@ -29,13 +33,11 @@ set(SRC_HEADERS kernel_globals.h kernel_light.h kernel_math.h - kernel_mbvh.h kernel_montecarlo.h kernel_object.h kernel_passes.h kernel_path.h kernel_projection.h - kernel_qbvh.h kernel_random.h kernel_shader.h kernel_textures.h @@ -43,18 +45,21 @@ set(SRC_HEADERS kernel_types.h ) +set(SRC_CLOSURE_HEADERS + closure/bsdf.h + closure/bsdf_ashikhmin_velvet.h + closure/bsdf_diffuse.h + closure/bsdf_microfacet.h + closure/bsdf_oren_nayar.h + closure/bsdf_reflection.h + closure/bsdf_refraction.h + closure/bsdf_transparent.h + closure/bsdf_ward.h + closure/bsdf_westin.h + closure/emissive.h + closure/volume.h +) set(SRC_SVM_HEADERS - svm/bsdf.h - svm/bsdf_ashikhmin_velvet.h - svm/bsdf_diffuse.h - svm/bsdf_oren_nayar.h - svm/bsdf_microfacet.h - svm/bsdf_reflection.h - svm/bsdf_refraction.h - svm/bsdf_transparent.h - svm/bsdf_ward.h - svm/bsdf_westin.h - svm/emissive.h svm/svm.h svm/svm_attribute.h svm/svm_bsdf.h @@ -90,7 +95,6 @@ set(SRC_SVM_HEADERS svm/svm_value.h svm/svm_voronoi.h svm/svm_wave.h - svm/volume.h ) set(SRC_UTIL_HEADERS @@ -108,7 +112,7 @@ if(WITH_CYCLES_CUDA_BINARIES) set(CUDA_BITS 32) endif() - set(cuda_sources kernel.cu ${SRC_HEADERS} ${SRC_SVM_HEADERS} ${SRC_UTIL_HEADERS}) + set(cuda_sources kernel.cu ${SRC_HEADERS} ${SRC_SVM_HEADERS} ${SRC_CLOSURE_HEADERS} ${SRC_UTIL_HEADERS}) set(cuda_cubins) foreach(arch ${CYCLES_CUDA_BINARIES_ARCH}) @@ -130,13 +134,15 @@ endif() if(WITH_CYCLES_OSL) add_subdirectory(osl) + add_subdirectory(shaders) endif() # CPU module include_directories(${INC}) +include_directories(SYSTEM ${INC_SYS}) -add_library(cycles_kernel ${SRC} ${SRC_HEADERS} ${SRC_SVM_HEADERS}) +add_library(cycles_kernel ${SRC} ${SRC_HEADERS} ${SRC_CLOSURE_HEADERS} ${SRC_SVM_HEADERS}) if(WITH_CYCLES_OPTIMIZED_KERNEL) set_source_files_properties(kernel_optimized.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_OPTIMIZED_KERNEL_FLAGS}") @@ -159,6 +165,7 @@ endif() delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel.cl" ${CYCLES_INSTALL_PATH}/kernel) delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernel.cu" ${CYCLES_INSTALL_PATH}/kernel) delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel) +delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_CLOSURE_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/closure) delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_SVM_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/svm) delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_UTIL_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel) diff --git a/intern/cycles/kernel/svm/bsdf.h b/intern/cycles/kernel/closure/bsdf.h similarity index 99% rename from intern/cycles/kernel/svm/bsdf.h rename to intern/cycles/kernel/closure/bsdf.h index 1a90eab0cd1..cfb6321a918 100644 --- a/intern/cycles/kernel/svm/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -58,7 +58,8 @@ __device float fresnel_dielectric(float eta, const float3 N, neta = 1 / eta; Nn = N; *is_inside = false; - } else { + } + else { // we are inside the surface, cos = -cos; neta = eta; @@ -74,7 +75,8 @@ __device float fresnel_dielectric(float eta, const float3 N, *dTdy = make_float3(0.0f, 0.0f, 0.0f); #endif return 1; // total internal reflection - } else { + } + else { float dnp = sqrtf(arg); float nK = (neta * cos)- dnp; *T = -(neta * I)+(nK * Nn); diff --git a/intern/cycles/kernel/svm/bsdf_ashikhmin_velvet.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h similarity index 75% rename from intern/cycles/kernel/svm/bsdf_ashikhmin_velvet.h rename to intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h index 40249dbe9c6..016fd73204e 100644 --- a/intern/cycles/kernel/svm/bsdf_ashikhmin_velvet.h +++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h @@ -35,37 +35,34 @@ CCL_NAMESPACE_BEGIN -typedef struct BsdfAshikhminVelvetClosure { - //float3 m_N; - float m_invsigma2; -} BsdfAshikhminVelvetClosure; - -__device void bsdf_ashikhmin_velvet_setup(ShaderData *sd, ShaderClosure *sc, float sigma) +__device int bsdf_ashikhmin_velvet_setup(ShaderClosure *sc) { + float sigma = sc->data0; sigma = fmaxf(sigma, 0.01f); float m_invsigma2 = 1.0f/(sigma * sigma); sc->type = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID; - sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL; sc->data0 = m_invsigma2; + + return SD_BSDF|SD_BSDF_HAS_EVAL; } __device void bsdf_ashikhmin_velvet_blur(ShaderClosure *sc, float roughness) { } -__device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { float m_invsigma2 = sc->data0; - float3 m_N = sd->N; + float3 N = sc->N; - float cosNO = dot(m_N, I); - float cosNI = dot(m_N, omega_in); + float cosNO = dot(N, I); + float cosNI = dot(N, omega_in); if(cosNO > 0 && cosNI > 0) { float3 H = normalize(omega_in + I); - float cosNH = dot(m_N, H); + float cosNH = dot(N, H); float cosHO = fabsf(dot(I, H)); if(!(fabsf(cosNH) < 1.0f-1e-5f && cosHO > 1e-5f)) @@ -93,32 +90,27 @@ __device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderData *sd, const S return make_float3(0, 0, 0); } -__device float3 bsdf_ashikhmin_velvet_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_ashikhmin_velvet_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float bsdf_ashikhmin_velvet_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_ashikhmin_velvet_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_ashikhmin_velvet_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { float m_invsigma2 = sc->data0; - float3 m_N = sd->N; + float3 N = sc->N; // we are viewing the surface from above - send a ray out with uniform // distribution over the hemisphere - sample_uniform_hemisphere(m_N, randu, randv, omega_in, pdf); + sample_uniform_hemisphere(N, randu, randv, omega_in, pdf); - if(dot(sd->Ng, *omega_in) > 0) { - float3 H = normalize(*omega_in + sd->I); + if(dot(Ng, *omega_in) > 0) { + float3 H = normalize(*omega_in + I); - float cosNI = dot(m_N, *omega_in); - float cosNO = dot(m_N, sd->I); - float cosNH = dot(m_N, H); - float cosHO = fabsf(dot(sd->I, H)); + float cosNI = dot(N, *omega_in); + float cosNO = dot(N, I); + float cosNH = dot(N, H); + float cosHO = fabsf(dot(I, H)); if(fabsf(cosNO) > 1e-5f && fabsf(cosNH) < 1.0f-1e-5f && cosHO > 1e-5f) { float cosNHdivHO = cosNH / cosHO; @@ -140,8 +132,8 @@ __device int bsdf_ashikhmin_velvet_sample(const ShaderData *sd, const ShaderClos #ifdef __RAY_DIFFERENTIALS__ // TODO: find a better approximation for the retroreflective bounce - *domega_in_dx = (2 * dot(m_N, sd->dI.dx)) * m_N - sd->dI.dx; - *domega_in_dy = (2 * dot(m_N, sd->dI.dy)) * m_N - sd->dI.dy; + *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx; + *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy; *domega_in_dx *= 125.0f; *domega_in_dy *= 125.0f; #endif diff --git a/intern/cycles/kernel/svm/bsdf_diffuse.h b/intern/cycles/kernel/closure/bsdf_diffuse.h similarity index 57% rename from intern/cycles/kernel/svm/bsdf_diffuse.h rename to intern/cycles/kernel/closure/bsdf_diffuse.h index 45e82a566c0..88b40e3d479 100644 --- a/intern/cycles/kernel/svm/bsdf_diffuse.h +++ b/intern/cycles/kernel/closure/bsdf_diffuse.h @@ -37,52 +37,43 @@ CCL_NAMESPACE_BEGIN /* DIFFUSE */ -typedef struct BsdfDiffuseClosure { - //float3 m_N; -} BsdfDiffuseClosure; - -__device void bsdf_diffuse_setup(ShaderData *sd, ShaderClosure *sc) +__device int bsdf_diffuse_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_DIFFUSE_ID; - sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL; + return SD_BSDF|SD_BSDF_HAS_EVAL; } __device void bsdf_diffuse_blur(ShaderClosure *sc, float roughness) { } -__device float3 bsdf_diffuse_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_diffuse_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { - float3 m_N = sd->N; + float3 N = sc->N; - float cos_pi = fmaxf(dot(m_N, omega_in), 0.0f) * M_1_PI_F; + float cos_pi = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F; *pdf = cos_pi; return make_float3(cos_pi, cos_pi, cos_pi); } -__device float3 bsdf_diffuse_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_diffuse_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float bsdf_diffuse_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) +__device int bsdf_diffuse_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { - return 1.0f; -} - -__device int bsdf_diffuse_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) -{ - float3 m_N = sd->N; + float3 N = sc->N; // distribution over the hemisphere - sample_cos_hemisphere(m_N, randu, randv, omega_in, pdf); + sample_cos_hemisphere(N, randu, randv, omega_in, pdf); - if(dot(sd->Ng, *omega_in) > 0.0f) { + if(dot(Ng, *omega_in) > 0.0f) { *eval = make_float3(*pdf, *pdf, *pdf); #ifdef __RAY_DIFFERENTIALS__ // TODO: find a better approximation for the diffuse bounce - *domega_in_dx = (2 * dot(m_N, sd->dI.dx)) * m_N - sd->dI.dx; - *domega_in_dy = (2 * dot(m_N, sd->dI.dy)) * m_N - sd->dI.dy; + *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx; + *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy; *domega_in_dx *= 125.0f; *domega_in_dy *= 125.0f; #endif @@ -95,58 +86,55 @@ __device int bsdf_diffuse_sample(const ShaderData *sd, const ShaderClosure *sc, /* TRANSLUCENT */ -typedef struct BsdfTranslucentClosure { - //float3 m_N; -} BsdfTranslucentClosure; - -__device void bsdf_translucent_setup(ShaderData *sd, ShaderClosure *sc) +__device int bsdf_translucent_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_TRANSLUCENT_ID; - sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL; + return SD_BSDF|SD_BSDF_HAS_EVAL; } __device void bsdf_translucent_blur(ShaderClosure *sc, float roughness) { } -__device float3 bsdf_translucent_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_translucent_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float3 bsdf_translucent_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_translucent_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { - float3 m_N = sd->N; + float3 N = sc->N; - float cos_pi = fmaxf(-dot(m_N, omega_in), 0.0f) * M_1_PI_F; + float cos_pi = fmaxf(-dot(N, omega_in), 0.0f) * M_1_PI_F; *pdf = cos_pi; return make_float3 (cos_pi, cos_pi, cos_pi); } -__device float bsdf_translucent_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) +__device float bsdf_translucent_albedo(const ShaderClosure *sc, const float3 I) { return 1.0f; } -__device int bsdf_translucent_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_translucent_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { - float3 m_N = sd->N; + float3 N = sc->N; // we are viewing the surface from the right side - send a ray out with cosine // distribution over the hemisphere - sample_cos_hemisphere (-m_N, randu, randv, omega_in, pdf); - if(dot(sd->Ng, *omega_in) < 0) { + sample_cos_hemisphere (-N, randu, randv, omega_in, pdf); + if(dot(Ng, *omega_in) < 0) { *eval = make_float3(*pdf, *pdf, *pdf); #ifdef __RAY_DIFFERENTIALS__ // TODO: find a better approximation for the diffuse bounce - *domega_in_dx = (2 * dot(m_N, sd->dI.dx)) * m_N - sd->dI.dx; - *domega_in_dy = (2 * dot(m_N, sd->dI.dy)) * m_N - sd->dI.dy; + *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx; + *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy; *domega_in_dx *= -125.0f; *domega_in_dy *= -125.0f; #endif - } else + } + else { *pdf = 0; - + } return LABEL_TRANSMIT|LABEL_DIFFUSE; } diff --git a/intern/cycles/kernel/svm/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h similarity index 81% rename from intern/cycles/kernel/svm/bsdf_microfacet.h rename to intern/cycles/kernel/closure/bsdf_microfacet.h index 01e3acb76e8..a564b99e759 100644 --- a/intern/cycles/kernel/svm/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -37,31 +37,36 @@ CCL_NAMESPACE_BEGIN /* GGX */ -typedef struct BsdfMicrofacetGGXClosure { - //float3 m_N; - float m_ag; - float m_eta; -} BsdfMicrofacetGGXClosure; - __device_inline float safe_sqrtf(float f) { return sqrtf(max(f, 0.0f)); } -__device void bsdf_microfacet_ggx_setup(ShaderData *sd, ShaderClosure *sc, float ag, float eta, bool refractive) +__device int bsdf_microfacet_ggx_setup(ShaderClosure *sc) { + float ag = sc->data0; + + float m_ag = clamp(ag, 1e-4f, 1.0f); + + sc->data0 = m_ag; + sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID; + + return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; +} + +__device int bsdf_microfacet_ggx_refraction_setup(ShaderClosure *sc) +{ + float ag = sc->data0; + float eta = sc->data1; + float m_ag = clamp(ag, 1e-4f, 1.0f); float m_eta = eta; sc->data0 = m_ag; sc->data1 = m_eta; + sc->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; - if(refractive) - sc->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; - else - sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID; - - sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; + return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; } __device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness) @@ -71,23 +76,22 @@ __device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness) sc->data0 = m_ag; } -__device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { float m_ag = sc->data0; - //float m_eta = sc->data1; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; - float3 m_N = sd->N; + float3 N = sc->N; if(m_refractive) return make_float3 (0, 0, 0); - float cosNO = dot(m_N, I); - float cosNI = dot(m_N, omega_in); + float cosNO = dot(N, I); + float cosNI = dot(N, omega_in); if(cosNI > 0 && cosNO > 0) { // get half vector float3 Hr = normalize(omega_in + I); // eq. 20: (F*G*D)/(4*in*on) // eq. 33: first we calculate D(m) with m=Hr: float alpha2 = m_ag * m_ag; - float cosThetaM = dot(m_N, Hr); + float cosThetaM = dot(N, Hr); float cosThetaM2 = cosThetaM * cosThetaM; float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; float cosThetaM4 = cosThetaM2 * cosThetaM2; @@ -108,16 +112,16 @@ __device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderData *sd, const Sha return make_float3 (0, 0, 0); } -__device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { float m_ag = sc->data0; float m_eta = sc->data1; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; - float3 m_N = sd->N; + float3 N = sc->N; if(!m_refractive) return make_float3 (0, 0, 0); - float cosNO = dot(m_N, I); - float cosNI = dot(m_N, omega_in); + float cosNO = dot(N, I); + float cosNI = dot(N, omega_in); if(cosNO <= 0 || cosNI >= 0) return make_float3 (0, 0, 0); // vectors on same side -- not possible // compute half-vector of the refraction (eq. 16) @@ -128,7 +132,7 @@ __device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderData *sd, const Sh float cosHI = dot(Ht, omega_in); // eq. 33: first we calculate D(m) with m=Ht: float alpha2 = m_ag * m_ag; - float cosThetaM = dot(m_N, Ht); + float cosThetaM = dot(N, Ht); float cosThetaM2 = cosThetaM * cosThetaM; float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; float cosThetaM4 = cosThetaM2 * cosThetaM2; @@ -144,21 +148,15 @@ __device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderData *sd, const Sh return make_float3 (out, out, out); } -__device float bsdf_microfacet_ggx_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_microfacet_ggx_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { float m_ag = sc->data0; - float m_eta = sc->data1; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; - float3 m_N = sd->N; + float3 N = sc->N; - float cosNO = dot(m_N, sd->I); + float cosNO = dot(N, I); if(cosNO > 0) { - float3 X, Y, Z = m_N; + float3 X, Y, Z = N; make_orthonormals(Z, &X, &Y); // generate a random microfacet normal m // eq. 35,36: @@ -173,11 +171,11 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur (sinf(phiM) * sinThetaM) * Y + cosThetaM * Z; if(!m_refractive) { - float cosMO = dot(m, sd->I); + float cosMO = dot(m, I); if(cosMO > 0) { // eq. 39 - compute actual reflected direction - *omega_in = 2 * cosMO * m - sd->I; - if(dot(sd->Ng, *omega_in) > 0) { + *omega_in = 2 * cosMO * m - I; + if(dot(Ng, *omega_in) > 0) { // microfacet normal is visible to this ray // eq. 33 float cosThetaM2 = cosThetaM * cosThetaM; @@ -190,7 +188,7 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf *pdf = pm * 0.25f / cosMO; // eval BRDF*cosNI - float cosNI = dot(m_N, *omega_in); + float cosNI = dot(N, *omega_in); // eq. 34: now calculate G1(i,m) and G1(o,m) float G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); @@ -199,8 +197,8 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur float out = (G * D) * 0.25f / cosNO; *eval = make_float3(out, out, out); #ifdef __RAY_DIFFERENTIALS__ - *domega_in_dx = (2 * dot(m, sd->dI.dx)) * m - sd->dI.dx; - *domega_in_dy = (2 * dot(m, sd->dI.dy)) * m - sd->dI.dy; + *domega_in_dx = (2 * dot(m, dIdx)) * m - dIdx; + *domega_in_dy = (2 * dot(m, dIdy)) * m - dIdy; // Since there is some blur to this reflection, make the // derivatives a bit bigger. In theory this varies with the // roughness but the exact relationship is complex and @@ -210,17 +208,19 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur #endif } } - } else { + } + else { // CAUTION: the i and o variables are inverted relative to the paper // eq. 39 - compute actual refractive direction float3 R, T; #ifdef __RAY_DIFFERENTIALS__ float3 dRdx, dRdy, dTdx, dTdy; #endif + float m_eta = sc->data1; bool inside; - fresnel_dielectric(m_eta, m, sd->I, &R, &T, + fresnel_dielectric(m_eta, m, I, &R, &T, #ifdef __RAY_DIFFERENTIALS__ - sd->dI.dx, sd->dI.dy, &dRdx, &dRdy, &dTdx, &dTdy, + dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy, #endif &inside); @@ -237,14 +237,14 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur // eq. 24 float pm = D * cosThetaM; // eval BRDF*cosNI - float cosNI = dot(m_N, *omega_in); + float cosNI = dot(N, *omega_in); // eq. 34: now calculate G1(i,m) and G1(o,m) float G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); float G = G1o * G1i; // eq. 21 float cosHI = dot(m, *omega_in); - float cosHO = dot(m, sd->I); + float cosHO = dot(m, I); float Ht2 = m_eta * cosHI + cosHO; Ht2 *= Ht2; float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2); @@ -267,26 +267,29 @@ __device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosur /* BECKMANN */ -typedef struct BsdfMicrofacetBeckmannClosure { - //float3 m_N; - float m_ab; - float m_eta; -} BsdfMicrofacetBeckmannClosure; - -__device void bsdf_microfacet_beckmann_setup(ShaderData *sd, ShaderClosure *sc, float ab, float eta, bool refractive) +__device int bsdf_microfacet_beckmann_setup(ShaderClosure *sc) { + float ab = sc->data0; + float m_ab = clamp(ab, 1e-4f, 1.0f); + + sc->data0 = m_ab; + + sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID; + return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; +} + +__device int bsdf_microfacet_beckmann_refraction_setup(ShaderClosure *sc) +{ + float ab = sc->data0; + float eta = sc->data1; float m_ab = clamp(ab, 1e-4f, 1.0f); float m_eta = eta; sc->data0 = m_ab; sc->data1 = m_eta; - if(refractive) - sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; - else - sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID; - - sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; + sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; + return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; } __device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness) @@ -296,23 +299,22 @@ __device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness) sc->data0 = m_ab; } -__device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { float m_ab = sc->data0; - //float m_eta = sc->data1; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; - float3 m_N = sd->N; + float3 N = sc->N; if(m_refractive) return make_float3 (0, 0, 0); - float cosNO = dot(m_N, I); - float cosNI = dot(m_N, omega_in); + float cosNO = dot(N, I); + float cosNI = dot(N, omega_in); if(cosNO > 0 && cosNI > 0) { // get half vector float3 Hr = normalize(omega_in + I); // eq. 20: (F*G*D)/(4*in*on) // eq. 25: first we calculate D(m) with m=Hr: float alpha2 = m_ab * m_ab; - float cosThetaM = dot(m_N, Hr); + float cosThetaM = dot(N, Hr); float cosThetaM2 = cosThetaM * cosThetaM; float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; float cosThetaM4 = cosThetaM2 * cosThetaM2; @@ -335,16 +337,16 @@ __device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderData *sd, cons return make_float3 (0, 0, 0); } -__device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { float m_ab = sc->data0; float m_eta = sc->data1; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; - float3 m_N = sd->N; + float3 N = sc->N; if(!m_refractive) return make_float3 (0, 0, 0); - float cosNO = dot(m_N, I); - float cosNI = dot(m_N, omega_in); + float cosNO = dot(N, I); + float cosNI = dot(N, omega_in); if(cosNO <= 0 || cosNI >= 0) return make_float3 (0, 0, 0); // compute half-vector of the refraction (eq. 16) @@ -355,7 +357,7 @@ __device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderData *sd, con float cosHI = dot(Ht, omega_in); // eq. 33: first we calculate D(m) with m=Ht: float alpha2 = m_ab * m_ab; - float cosThetaM = dot(m_N, Ht); + float cosThetaM = dot(N, Ht); float cosThetaM2 = cosThetaM * cosThetaM; float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; float cosThetaM4 = cosThetaM2 * cosThetaM2; @@ -373,21 +375,15 @@ __device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderData *sd, con return make_float3 (out, out, out); } -__device float bsdf_microfacet_beckmann_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_microfacet_beckmann_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { float m_ab = sc->data0; - float m_eta = sc->data1; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; - float3 m_N = sd->N; + float3 N = sc->N; - float cosNO = dot(m_N, sd->I); + float cosNO = dot(N, I); if(cosNO > 0) { - float3 X, Y, Z = m_N; + float3 X, Y, Z = N; make_orthonormals(Z, &X, &Y); // generate a random microfacet normal m // eq. 35,36: @@ -403,11 +399,11 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC cosThetaM * Z; if(!m_refractive) { - float cosMO = dot(m, sd->I); + float cosMO = dot(m, I); if(cosMO > 0) { // eq. 39 - compute actual reflected direction - *omega_in = 2 * cosMO * m - sd->I; - if(dot(sd->Ng, *omega_in) > 0) { + *omega_in = 2 * cosMO * m - I; + if(dot(Ng, *omega_in) > 0) { // microfacet normal is visible to this ray // eq. 25 float cosThetaM2 = cosThetaM * cosThetaM; @@ -421,7 +417,7 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf *pdf = pm * 0.25f / cosMO; // Eval BRDF*cosNI - float cosNI = dot(m_N, *omega_in); + float cosNI = dot(N, *omega_in); // eq. 26, 27: now calculate G1(i,m) and G1(o,m) float ao = 1 / (m_ab * safe_sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); float ai = 1 / (m_ab * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); @@ -432,8 +428,8 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC float out = (G * D) * 0.25f / cosNO; *eval = make_float3(out, out, out); #ifdef __RAY_DIFFERENTIALS__ - *domega_in_dx = (2 * dot(m, sd->dI.dx)) * m - sd->dI.dx; - *domega_in_dy = (2 * dot(m, sd->dI.dy)) * m - sd->dI.dy; + *domega_in_dx = (2 * dot(m, dIdx)) * m - dIdx; + *domega_in_dy = (2 * dot(m, dIdy)) * m - dIdy; // Since there is some blur to this reflection, make the // derivatives a bit bigger. In theory this varies with the // roughness but the exact relationship is complex and @@ -443,17 +439,19 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC #endif } } - } else { + } + else { // CAUTION: the i and o variables are inverted relative to the paper // eq. 39 - compute actual refractive direction float3 R, T; #ifdef __RAY_DIFFERENTIALS__ float3 dRdx, dRdy, dTdx, dTdy; #endif + float m_eta = sc->data1; bool inside; - fresnel_dielectric(m_eta, m, sd->I, &R, &T, + fresnel_dielectric(m_eta, m, I, &R, &T, #ifdef __RAY_DIFFERENTIALS__ - sd->dI.dx, sd->dI.dy, &dRdx, &dRdy, &dTdx, &dTdy, + dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy, #endif &inside); @@ -472,7 +470,7 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC // eq. 24 float pm = D * cosThetaM; // eval BRDF*cosNI - float cosNI = dot(m_N, *omega_in); + float cosNI = dot(N, *omega_in); // eq. 26, 27: now calculate G1(i,m) and G1(o,m) float ao = 1 / (m_ab * safe_sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); float ai = 1 / (m_ab * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); @@ -481,7 +479,7 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderC float G = G1o * G1i; // eq. 21 float cosHI = dot(m, *omega_in); - float cosHO = dot(m, sd->I); + float cosHO = dot(m, I); float Ht2 = m_eta * cosHI + cosHO; Ht2 *= Ht2; float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2); diff --git a/intern/cycles/kernel/svm/bsdf_oren_nayar.h b/intern/cycles/kernel/closure/bsdf_oren_nayar.h similarity index 61% rename from intern/cycles/kernel/svm/bsdf_oren_nayar.h rename to intern/cycles/kernel/closure/bsdf_oren_nayar.h index a7edccdc423..066937da6eb 100644 --- a/intern/cycles/kernel/svm/bsdf_oren_nayar.h +++ b/intern/cycles/kernel/closure/bsdf_oren_nayar.h @@ -21,11 +21,6 @@ CCL_NAMESPACE_BEGIN -typedef struct BsdfOrenNayarClosure { - float m_a; - float m_b; -} BsdfOrenNayarClosure; - __device float3 bsdf_oren_nayar_get_intensity(const ShaderClosure *sc, float3 n, float3 v, float3 l) { float nl = max(dot(n, l), 0.0f); @@ -38,10 +33,11 @@ __device float3 bsdf_oren_nayar_get_intensity(const ShaderClosure *sc, float3 n, return make_float3(is, is, is); } -__device void bsdf_oren_nayar_setup(ShaderData *sd, ShaderClosure *sc, float sigma) +__device int bsdf_oren_nayar_setup(ShaderClosure *sc) { + float sigma = sc->data0; + sc->type = CLOSURE_BSDF_OREN_NAYAR_ID; - sd->flag |= SD_BSDF | SD_BSDF_HAS_EVAL; sigma = clamp(sigma, 0.0f, 1.0f); @@ -49,17 +45,19 @@ __device void bsdf_oren_nayar_setup(ShaderData *sd, ShaderClosure *sc, float sig sc->data0 = 1.0f * div; sc->data1 = sigma * div; + + return SD_BSDF | SD_BSDF_HAS_EVAL; } __device void bsdf_oren_nayar_blur(ShaderClosure *sc, float roughness) { } -__device float3 bsdf_oren_nayar_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_oren_nayar_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { - if (dot(sd->N, omega_in) > 0.0f) { + if (dot(sc->N, omega_in) > 0.0f) { *pdf = 0.5f * M_1_PI_F; - return bsdf_oren_nayar_get_intensity(sc, sd->N, I, omega_in); + return bsdf_oren_nayar_get_intensity(sc, sc->N, I, omega_in); } else { *pdf = 0.0f; @@ -67,27 +65,22 @@ __device float3 bsdf_oren_nayar_eval_reflect(const ShaderData *sd, const ShaderC } } -__device float3 bsdf_oren_nayar_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_oren_nayar_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float bsdf_oren_nayar_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) +__device int bsdf_oren_nayar_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { - return 1.0f; -} + sample_uniform_hemisphere(sc->N, randu, randv, omega_in, pdf); -__device int bsdf_oren_nayar_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) -{ - sample_uniform_hemisphere(sd->N, randu, randv, omega_in, pdf); - - if (dot(sd->Ng, *omega_in) > 0.0f) { - *eval = bsdf_oren_nayar_get_intensity(sc, sd->N, sd->I, *omega_in); + if (dot(Ng, *omega_in) > 0.0f) { + *eval = bsdf_oren_nayar_get_intensity(sc, sc->N, I, *omega_in); #ifdef __RAY_DIFFERENTIALS__ // TODO: find a better approximation for the bounce - *domega_in_dx = (2.0f * dot(sd->N, sd->dI.dx)) * sd->N - sd->dI.dx; - *domega_in_dy = (2.0f * dot(sd->N, sd->dI.dy)) * sd->N - sd->dI.dy; + *domega_in_dx = (2.0f * dot(sc->N, dIdx)) * sc->N - dIdx; + *domega_in_dy = (2.0f * dot(sc->N, dIdy)) * sc->N - dIdy; *domega_in_dx *= 125.0f; *domega_in_dy *= 125.0f; #endif diff --git a/intern/cycles/kernel/svm/bsdf_reflection.h b/intern/cycles/kernel/closure/bsdf_reflection.h similarity index 69% rename from intern/cycles/kernel/svm/bsdf_reflection.h rename to intern/cycles/kernel/closure/bsdf_reflection.h index 09b4e0e48f0..9356f950d98 100644 --- a/intern/cycles/kernel/svm/bsdf_reflection.h +++ b/intern/cycles/kernel/closure/bsdf_reflection.h @@ -37,48 +37,39 @@ CCL_NAMESPACE_BEGIN /* REFLECTION */ -typedef struct BsdfReflectionClosure { - //float3 m_N; -} BsdfReflectionClosure; - -__device void bsdf_reflection_setup(ShaderData *sd, ShaderClosure *sc) +__device int bsdf_reflection_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_REFLECTION_ID; - sd->flag |= SD_BSDF; + return SD_BSDF; } __device void bsdf_reflection_blur(ShaderClosure *sc, float roughness) { } -__device float3 bsdf_reflection_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_reflection_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float3 bsdf_reflection_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_reflection_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float bsdf_reflection_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_reflection_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_reflection_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { //const BsdfReflectionClosure *self = (const BsdfReflectionClosure*)sc->data; - float3 m_N = sd->N; + float3 N = sc->N; // only one direction is possible - float cosNO = dot(m_N, sd->I); + float cosNO = dot(N, I); if(cosNO > 0) { - *omega_in = (2 * cosNO) * m_N - sd->I; - if(dot(sd->Ng, *omega_in) > 0) { + *omega_in = (2 * cosNO) * N - I; + if(dot(Ng, *omega_in) > 0) { #ifdef __RAY_DIFFERENTIALS__ - *domega_in_dx = 2 * dot(m_N, sd->dI.dx) * m_N - sd->dI.dx; - *domega_in_dy = 2 * dot(m_N, sd->dI.dy) * m_N - sd->dI.dy; + *domega_in_dx = 2 * dot(N, dIdx) * N - dIdx; + *domega_in_dy = 2 * dot(N, dIdy) * N - dIdy; #endif *pdf = 1; *eval = make_float3(1, 1, 1); diff --git a/intern/cycles/kernel/svm/bsdf_refraction.h b/intern/cycles/kernel/closure/bsdf_refraction.h similarity index 72% rename from intern/cycles/kernel/svm/bsdf_refraction.h rename to intern/cycles/kernel/closure/bsdf_refraction.h index c9c268999c0..ef79d6cc259 100644 --- a/intern/cycles/kernel/svm/bsdf_refraction.h +++ b/intern/cycles/kernel/closure/bsdf_refraction.h @@ -37,50 +37,39 @@ CCL_NAMESPACE_BEGIN /* REFRACTION */ -typedef struct BsdfRefractionClosure { - float m_eta; -} BsdfRefractionClosure; - -__device void bsdf_refraction_setup(ShaderData *sd, ShaderClosure *sc, float eta) +__device int bsdf_refraction_setup(ShaderClosure *sc) { - sc->data0 = eta; - sc->type = CLOSURE_BSDF_REFRACTION_ID; - sd->flag |= SD_BSDF; + return SD_BSDF; } __device void bsdf_refraction_blur(ShaderClosure *sc, float roughness) { } -__device float3 bsdf_refraction_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_refraction_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float3 bsdf_refraction_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_refraction_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float bsdf_refraction_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_refraction_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_refraction_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { float m_eta = sc->data0; - float3 m_N = sd->N; + float3 N = sc->N; float3 R, T; #ifdef __RAY_DIFFERENTIALS__ float3 dRdx, dRdy, dTdx, dTdy; #endif bool inside; - fresnel_dielectric(m_eta, m_N, sd->I, &R, &T, + fresnel_dielectric(m_eta, N, I, &R, &T, #ifdef __RAY_DIFFERENTIALS__ - sd->dI.dx, sd->dI.dy, &dRdx, &dRdy, &dTdx, &dTdy, + dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy, #endif &inside); diff --git a/intern/cycles/kernel/svm/bsdf_transparent.h b/intern/cycles/kernel/closure/bsdf_transparent.h similarity index 74% rename from intern/cycles/kernel/svm/bsdf_transparent.h rename to intern/cycles/kernel/closure/bsdf_transparent.h index 511836cdfa2..81bc7690b50 100644 --- a/intern/cycles/kernel/svm/bsdf_transparent.h +++ b/intern/cycles/kernel/closure/bsdf_transparent.h @@ -35,38 +35,33 @@ CCL_NAMESPACE_BEGIN -__device void bsdf_transparent_setup(ShaderData *sd, ShaderClosure *sc) +__device int bsdf_transparent_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_TRANSPARENT_ID; - sd->flag |= SD_BSDF; + return SD_BSDF; } __device void bsdf_transparent_blur(ShaderClosure *sc, float roughness) { } -__device float3 bsdf_transparent_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_transparent_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float3 bsdf_transparent_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_transparent_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float bsdf_transparent_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_transparent_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_transparent_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { // only one direction is possible - *omega_in = -sd->I; + *omega_in = -I; #ifdef __RAY_DIFFERENTIALS__ - *domega_in_dx = -sd->dI.dx; - *domega_in_dy = -sd->dI.dy; + *domega_in_dx = -dIdx; + *domega_in_dy = -dIdy; #endif *pdf = 1; *eval = make_float3(1, 1, 1); diff --git a/intern/cycles/kernel/svm/bsdf_ward.h b/intern/cycles/kernel/closure/bsdf_ward.h similarity index 77% rename from intern/cycles/kernel/svm/bsdf_ward.h rename to intern/cycles/kernel/closure/bsdf_ward.h index 86bca69425d..9c81548a2c3 100644 --- a/intern/cycles/kernel/svm/bsdf_ward.h +++ b/intern/cycles/kernel/closure/bsdf_ward.h @@ -37,23 +37,19 @@ CCL_NAMESPACE_BEGIN /* WARD */ -typedef struct BsdfWardClosure { - //float3 m_N; - //float3 m_T; - float m_ax; - float m_ay; -} BsdfWardClosure; - -__device void bsdf_ward_setup(ShaderData *sd, ShaderClosure *sc, float3 T, float ax, float ay) +__device int bsdf_ward_setup(ShaderClosure *sc) { - float m_ax = clamp(ax, 1e-5f, 1.0f); - float m_ay = clamp(ay, 1e-5f, 1.0f); + float ax = sc->data0; + float ay = sc->data1; + + float m_ax = clamp(ax, 1e-4f, 1.0f); + float m_ay = clamp(ay, 1e-4f, 1.0f); sc->data0 = m_ax; sc->data1 = m_ay; sc->type = CLOSURE_BSDF_WARD_ID; - sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; + return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; } __device void bsdf_ward_blur(ShaderClosure *sc, float roughness) @@ -62,25 +58,25 @@ __device void bsdf_ward_blur(ShaderClosure *sc, float roughness) sc->data1 = fmaxf(roughness, sc->data1); } -__device float3 bsdf_ward_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_ward_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { float m_ax = sc->data0; float m_ay = sc->data1; - float3 m_N = sd->N; - float3 m_T = normalize(sd->dPdu); + float3 N = sc->N; + float3 T = sc->T; - float cosNO = dot(m_N, I); - float cosNI = dot(m_N, omega_in); + float cosNO = dot(N, I); + float cosNI = dot(N, omega_in); if(cosNI > 0 && cosNO > 0) { // get half vector and get x,y basis on the surface for anisotropy float3 H = normalize(omega_in + I); // normalize needed for pdf float3 X, Y; - make_orthonormals_tangent(m_N, m_T, &X, &Y); + make_orthonormals_tangent(N, T, &X, &Y); // eq. 4 float dotx = dot(H, X) / m_ax; float doty = dot(H, Y) / m_ay; - float dotn = dot(H, m_N); + float dotn = dot(H, N); float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn); float denom = (4 * M_PI_F * m_ax * m_ay * sqrtf(cosNO * cosNI)); float exp_val = expf(-exp_arg); @@ -90,31 +86,27 @@ __device float3 bsdf_ward_eval_reflect(const ShaderData *sd, const ShaderClosure *pdf = exp_val / denom; return make_float3 (out, out, out); } + return make_float3 (0, 0, 0); } -__device float3 bsdf_ward_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_ward_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float bsdf_ward_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_ward_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_ward_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { float m_ax = sc->data0; float m_ay = sc->data1; - float3 m_N = sd->N; - float3 m_T = normalize(sd->dPdu); + float3 N = sc->N; + float3 T = sc->T; - float cosNO = dot(m_N, sd->I); + float cosNO = dot(N, I); if(cosNO > 0) { // get x,y basis on the surface for anisotropy float3 X, Y; - make_orthonormals_tangent(m_N, m_T, &X, &Y); + make_orthonormals_tangent(N, T, &X, &Y); // generate random angles for the half vector // eq. 7 (taking care around discontinuities to keep //ttoutput angle in the right quadrant) @@ -127,19 +119,22 @@ __device int bsdf_ward_sample(const ShaderData *sd, const ShaderClosure *sc, flo float tanPhi = alphaRatio * tanf(M_PI_2_F * val); cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi); sinPhi = tanPhi * cosPhi; - } else if(randu < 0.5f) { + } + else if(randu < 0.5f) { float val = 1 - 4 * (0.5f - randu); float tanPhi = alphaRatio * tanf(M_PI_2_F * val); // phi = M_PI_F - phi; cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi); sinPhi = -tanPhi * cosPhi; - } else if(randu < 0.75f) { + } + else if(randu < 0.75f) { float val = 4 * (randu - 0.5f); float tanPhi = alphaRatio * tanf(M_PI_2_F * val); //phi = M_PI_F + phi; cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi); sinPhi = tanPhi * cosPhi; - } else { + } + else { float val = 1 - 4 * (1 - randu); float tanPhi = alphaRatio * tanf(M_PI_2_F * val); // phi = 2 * M_PI_F - phi; @@ -163,12 +158,12 @@ __device int bsdf_ward_sample(const ShaderData *sd, const ShaderClosure *sc, flo float doty = h.y / m_ay; float dotn = h.z; // transform to world space - h = h.x * X + h.y * Y + h.z * m_N; + h = h.x * X + h.y * Y + h.z * N; // generate the final sample - float oh = dot(h, sd->I); - *omega_in = 2.0f * oh * h - sd->I; - if(dot(sd->Ng, *omega_in) > 0) { - float cosNI = dot(m_N, *omega_in); + float oh = dot(h, I); + *omega_in = 2.0f * oh * h - I; + if(dot(Ng, *omega_in) > 0) { + float cosNI = dot(N, *omega_in); if(cosNI > 0) { // eq. 9 float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn); @@ -179,8 +174,8 @@ __device int bsdf_ward_sample(const ShaderData *sd, const ShaderClosure *sc, flo float power = cosNI * expf(-exp_arg) / denom; *eval = make_float3(power, power, power); #ifdef __RAY_DIFFERENTIALS__ - *domega_in_dx = (2 * dot(m_N, sd->dI.dx)) * m_N - sd->dI.dx; - *domega_in_dy = (2 * dot(m_N, sd->dI.dy)) * m_N - sd->dI.dy; + *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx; + *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy; // Since there is some blur to this reflection, make the // derivatives a bit bigger. In theory this varies with the // roughness but the exact relationship is complex and diff --git a/intern/cycles/kernel/svm/bsdf_westin.h b/intern/cycles/kernel/closure/bsdf_westin.h similarity index 67% rename from intern/cycles/kernel/svm/bsdf_westin.h rename to intern/cycles/kernel/closure/bsdf_westin.h index 6193d81c244..968173208b4 100644 --- a/intern/cycles/kernel/svm/bsdf_westin.h +++ b/intern/cycles/kernel/closure/bsdf_westin.h @@ -37,19 +37,16 @@ CCL_NAMESPACE_BEGIN /* WESTIN BACKSCATTER */ -typedef struct BsdfWestinBackscatterClosure { - //float3 m_N; - float m_invroughness; -} BsdfWestinBackscatterClosure; - -__device void bsdf_westin_backscatter_setup(ShaderData *sd, ShaderClosure *sc, float roughness) +__device int bsdf_westin_backscatter_setup(ShaderClosure *sc) { + float roughness = sc->data0; roughness = clamp(roughness, 1e-5f, 1.0f); float m_invroughness = 1.0f/roughness; sc->type = CLOSURE_BSDF_WESTIN_BACKSCATTER_ID; - sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; sc->data0 = m_invroughness; + + return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; } __device void bsdf_westin_backscatter_blur(ShaderClosure *sc, float roughness) @@ -59,14 +56,14 @@ __device void bsdf_westin_backscatter_blur(ShaderClosure *sc, float roughness) sc->data0 = m_invroughness; } -__device float3 bsdf_westin_backscatter_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_westin_backscatter_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { float m_invroughness = sc->data0; - float3 m_N = sd->N; + float3 N = sc->N; // pdf is implicitly 0 (no indirect sampling) - float cosNO = dot(m_N, I); - float cosNI = dot(m_N, omega_in); + float cosNO = dot(N, I); + float cosNI = dot(N, omega_in); if(cosNO > 0 && cosNI > 0) { float cosine = dot(I, omega_in); *pdf = cosine > 0 ? (m_invroughness + 1) * powf(cosine, m_invroughness) : 0; @@ -76,40 +73,35 @@ __device float3 bsdf_westin_backscatter_eval_reflect(const ShaderData *sd, const return make_float3 (0, 0, 0); } -__device float3 bsdf_westin_backscatter_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_westin_backscatter_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float bsdf_westin_backscatter_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_westin_backscatter_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_westin_backscatter_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { float m_invroughness = sc->data0; - float3 m_N = sd->N; + float3 N = sc->N; - float cosNO = dot(m_N, sd->I); + float cosNO = dot(N, I); if(cosNO > 0) { #ifdef __RAY_DIFFERENTIALS__ - *domega_in_dx = sd->dI.dx; - *domega_in_dy = sd->dI.dy; + *domega_in_dx = dIdx; + *domega_in_dy = dIdy; #endif float3 T, B; - make_orthonormals (sd->I, &T, &B); + make_orthonormals (I, &T, &B); float phi = 2 * M_PI_F * randu; float cosTheta = powf(randv, 1 / (m_invroughness + 1)); float sinTheta2 = 1 - cosTheta * cosTheta; float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; *omega_in = (cosf(phi) * sinTheta) * T + (sinf(phi) * sinTheta) * B + - (cosTheta) * sd->I; - if(dot(sd->Ng, *omega_in) > 0) + (cosTheta) * I; + if(dot(Ng, *omega_in) > 0) { // common terms for pdf and eval - float cosNI = dot(m_N, *omega_in); + float cosNI = dot(N, *omega_in); // make sure the direction we chose is still in the right hemisphere if(cosNI > 0) { @@ -132,30 +124,26 @@ __device int bsdf_westin_backscatter_sample(const ShaderData *sd, const ShaderCl /* WESTIN SHEEN */ -typedef struct BsdfWestinSheenClosure { - //float3 m_N; - float m_edginess; -} BsdfWestinSheenClosure; - -__device void bsdf_westin_sheen_setup(ShaderData *sd, ShaderClosure *sc, float edginess) +__device int bsdf_westin_sheen_setup(ShaderClosure *sc) { + float edginess = sc->data0; sc->type = CLOSURE_BSDF_WESTIN_SHEEN_ID; - sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; sc->data0 = edginess; + return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; } __device void bsdf_westin_sheen_blur(ShaderClosure *sc, float roughness) { } -__device float3 bsdf_westin_sheen_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_westin_sheen_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { float m_edginess = sc->data0; - float3 m_N = sd->N; + float3 N = sc->N; // pdf is implicitly 0 (no indirect sampling) - float cosNO = dot(m_N, I); - float cosNI = dot(m_N, omega_in); + float cosNO = dot(N, I); + float cosNI = dot(N, omega_in); if(cosNO > 0 && cosNI > 0) { float sinNO2 = 1 - cosNO * cosNO; *pdf = cosNI * M_1_PI_F; @@ -165,39 +153,36 @@ __device float3 bsdf_westin_sheen_eval_reflect(const ShaderData *sd, const Shade return make_float3 (0, 0, 0); } -__device float3 bsdf_westin_sheen_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) +__device float3 bsdf_westin_sheen_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { return make_float3(0.0f, 0.0f, 0.0f); } -__device float bsdf_westin_sheen_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - -__device int bsdf_westin_sheen_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) +__device int bsdf_westin_sheen_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { float m_edginess = sc->data0; - float3 m_N = sd->N; + float3 N = sc->N; // we are viewing the surface from the right side - send a ray out with cosine // distribution over the hemisphere - sample_cos_hemisphere(m_N, randu, randv, omega_in, pdf); - if(dot(sd->Ng, *omega_in) > 0) { + sample_cos_hemisphere(N, randu, randv, omega_in, pdf); + if(dot(Ng, *omega_in) > 0) { // TODO: account for sheen when sampling - float cosNO = dot(m_N, sd->I); + float cosNO = dot(N, I); float sinNO2 = 1 - cosNO * cosNO; float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * (*pdf) : 0; *eval = make_float3(westin, westin, westin); #ifdef __RAY_DIFFERENTIALS__ // TODO: find a better approximation for the diffuse bounce - *domega_in_dx = (2 * dot(m_N, sd->dI.dx)) * m_N - sd->dI.dx; - *domega_in_dy = (2 * dot(m_N, sd->dI.dy)) * m_N - sd->dI.dy; + *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx; + *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy; *domega_in_dx *= 125.0f; *domega_in_dy *= 125.0f; #endif - } else + } + else { pdf = 0; + } return LABEL_REFLECT|LABEL_DIFFUSE; } diff --git a/intern/cycles/kernel/svm/emissive.h b/intern/cycles/kernel/closure/emissive.h similarity index 86% rename from intern/cycles/kernel/svm/emissive.h rename to intern/cycles/kernel/closure/emissive.h index 9a906f82963..cbf9d9a4efb 100644 --- a/intern/cycles/kernel/svm/emissive.h +++ b/intern/cycles/kernel/closure/emissive.h @@ -34,15 +34,21 @@ CCL_NAMESPACE_BEGIN /* EMISSION CLOSURE */ -/// Return the probability distribution function in the direction I, -/// given the parameters and the light's surface normal. This MUST match -/// the PDF computed by sample(). +/* return the probability distribution function in the direction I, + * given the parameters and the light's surface normal. This MUST match + * the PDF computed by sample(). */ __device float emissive_pdf(const float3 Ng, const float3 I) { float cosNO = fabsf(dot(Ng, I)); return (cosNO > 0.0f)? 1.0f: 0.0f; } +__device void emissive_sample(const float3 Ng, float randu, float randv, + float3 *omega_out, float *pdf) +{ + /* todo: not implemented and used yet */ +} + __device float3 emissive_eval(const float3 Ng, const float3 I) { float res = emissive_pdf(Ng, I); diff --git a/intern/cycles/kernel/svm/volume.h b/intern/cycles/kernel/closure/volume.h similarity index 65% rename from intern/cycles/kernel/svm/volume.h rename to intern/cycles/kernel/closure/volume.h index 10e9c5de352..734f9111ab6 100644 --- a/intern/cycles/kernel/svm/volume.h +++ b/intern/cycles/kernel/closure/volume.h @@ -23,44 +23,46 @@ CCL_NAMESPACE_BEGIN /* ISOTROPIC VOLUME CLOSURE */ -__device void volume_isotropic_setup(ShaderData *sd, ShaderClosure *sc, float density) +__device int volume_isotropic_setup(ShaderClosure *sc, float density) { sc->type = CLOSURE_VOLUME_ISOTROPIC_ID; - sd->flag |= SD_VOLUME; sc->data0 = density; + + return SD_VOLUME; } -__device float3 volume_isotropic_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) +__device float3 volume_isotropic_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) { return make_float3(1.0f, 1.0f, 1.0f); } /* TRANSPARENT VOLUME CLOSURE */ -__device void volume_transparent_setup(ShaderData *sd, ShaderClosure *sc, float density) +__device int volume_transparent_setup(ShaderClosure *sc, float density) { sc->type = CLOSURE_VOLUME_TRANSPARENT_ID; - sd->flag |= SD_VOLUME; sc->data0 = density; + + return SD_VOLUME; } -__device float3 volume_transparent_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) +__device float3 volume_transparent_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) { return make_float3(1.0f, 1.0f, 1.0f); } /* VOLUME CLOSURE */ -__device float3 volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) +__device float3 volume_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) { float3 eval; switch(sc->type) { case CLOSURE_VOLUME_ISOTROPIC_ID: - eval = volume_isotropic_eval_phase(sd, sc, omega_in, omega_out); + eval = volume_isotropic_eval_phase(sc, omega_in, omega_out); break; case CLOSURE_VOLUME_TRANSPARENT_ID: - eval = volume_transparent_eval_phase(sd, sc, omega_in, omega_out); + eval = volume_transparent_eval_phase(sc, omega_in, omega_out); break; default: eval = make_float3(0.0f, 0.0f, 0.0f); diff --git a/intern/cycles/kernel/kernel_attribute.h b/intern/cycles/kernel/kernel_attribute.h index 115de2fdbdb..2774f5e924b 100644 --- a/intern/cycles/kernel/kernel_attribute.h +++ b/intern/cycles/kernel/kernel_attribute.h @@ -59,7 +59,7 @@ __device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id) attr_map = kernel_tex_fetch(__attributes_map, ++attr_offset); /* return result */ - return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : attr_map.z; + return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z; } } diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h index 34a44af8b8d..d70485fd6cf 100644 --- a/intern/cycles/kernel/kernel_bvh.h +++ b/intern/cycles/kernel/kernel_bvh.h @@ -57,7 +57,7 @@ __device_inline float3 bvh_inverse_direction(float3 dir) __device_inline void bvh_instance_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *idir, float *t, const float tmax) { - Transform tfm = object_fetch_transform(kg, object, ray->time, OBJECT_INVERSE_TRANSFORM); + Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); *P = transform_point(&tfm, ray->P); @@ -75,7 +75,7 @@ __device_inline void bvh_instance_push(KernelGlobals *kg, int object, const Ray __device_inline void bvh_instance_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *idir, float *t, const float tmax) { if(*t != FLT_MAX) { - Transform tfm = object_fetch_transform(kg, object, ray->time, OBJECT_TRANSFORM); + Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); *t *= len(transform_direction(&tfm, 1.0f/(*idir))); } @@ -83,6 +83,35 @@ __device_inline void bvh_instance_pop(KernelGlobals *kg, int object, const Ray * *idir = bvh_inverse_direction(ray->D); } +#ifdef __OBJECT_MOTION__ +__device_inline void bvh_instance_motion_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *idir, float *t, Transform *tfm, const float tmax) +{ + Transform itfm; + *tfm = object_fetch_transform_motion_test(kg, object, ray->time, &itfm); + + *P = transform_point(&itfm, ray->P); + + float3 dir = transform_direction(&itfm, ray->D); + + float len; + dir = normalize_len(dir, &len); + + *idir = bvh_inverse_direction(dir); + + if(*t != FLT_MAX) + *t *= len; +} + +__device_inline void bvh_instance_motion_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *idir, float *t, Transform *tfm, const float tmax) +{ + if(*t != FLT_MAX) + *t *= len(transform_direction(tfm, 1.0f/(*idir))); + + *P = ray->P; + *idir = bvh_inverse_direction(ray->D); +} +#endif + /* intersect two bounding boxes */ __device_inline void bvh_node_intersect(KernelGlobals *kg, bool *traverseChild0, bool *traverseChild1, @@ -176,7 +205,7 @@ __device_inline void bvh_triangle_intersect(KernelGlobals *kg, Intersection *ise } } -__device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect) +__device_inline bool bvh_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect) { /* traversal stack in CUDA thread-local memory */ int traversalStack[BVH_STACK_SIZE]; @@ -268,7 +297,6 @@ __device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const ui else { /* instance push */ object = kernel_tex_fetch(__prim_object, -primAddr-1); - bvh_instance_push(kg, object, ray, &P, &idir, &isect->t, tmax); ++stackPtr; @@ -296,6 +324,135 @@ __device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const ui return (isect->prim != ~0); } +#ifdef __OBJECT_MOTION__ +__device_inline bool bvh_intersect_motion(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect) +{ + /* 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; + + 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, visibility, 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; + + /* triangle intersection */ + while(primAddr < primAddr2) { + /* intersect ray against triangle */ + bvh_triangle_intersect(kg, isect, P, idir, visibility, object, primAddr); + + /* shadow ray early termination */ + if(visibility == PATH_RAY_SHADOW_OPAQUE && isect->prim != ~0) + return true; + + primAddr++; + } + } + else { + /* instance push */ + 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); + } + } + } 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 (isect->prim != ~0); +} +#endif + +__device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const uint visibility, Intersection *isect) +{ +#ifdef __OBJECT_MOTION__ + if(kernel_data.bvh.have_motion) + return bvh_intersect_motion(kg, ray, visibility, isect); + else + return bvh_intersect(kg, ray, visibility, isect); +#else + return bvh_intersect(kg, ray, visibility, isect); +#endif +} + __device_inline float3 ray_offset(float3 P, float3 Ng) { #ifdef __INTERSECTION_REFINE__ @@ -349,10 +506,10 @@ __device_inline float3 bvh_triangle_refine(KernelGlobals *kg, ShaderData *sd, co #ifdef __INTERSECTION_REFINE__ if(isect->object != ~0) { -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ Transform tfm = sd->ob_itfm; #else - Transform tfm = object_fetch_transform(kg, isect->object, ray->time, OBJECT_INVERSE_TRANSFORM); + Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM); #endif P = transform_point(&tfm, P); @@ -370,10 +527,10 @@ __device_inline float3 bvh_triangle_refine(KernelGlobals *kg, ShaderData *sd, co P = P + D*rt; if(isect->object != ~0) { -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ Transform tfm = sd->ob_tfm; #else - Transform tfm = object_fetch_transform(kg, isect->object, ray->time, OBJECT_TRANSFORM); + Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM); #endif P = transform_point(&tfm, P); diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index e1b474d8537..1b2fe8c56ee 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -63,7 +63,7 @@ __device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float /* transform ray from camera to world */ Transform cameratoworld = kernel_data.cam.cameratoworld; -#ifdef __MOTION__ +#ifdef __CAMERA_MOTION__ if(kernel_data.cam.have_motion) transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time); #endif @@ -106,7 +106,7 @@ __device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, floa /* transform ray from camera to world */ Transform cameratoworld = kernel_data.cam.cameratoworld; -#ifdef __MOTION__ +#ifdef __CAMERA_MOTION__ if(kernel_data.cam.have_motion) transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time); #endif @@ -134,7 +134,7 @@ __device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, floa /* Panorama Camera */ -__device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float raster_y, Ray *ray) +__device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, Ray *ray) { Transform rastertocamera = kernel_data.cam.rastertocamera; float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f)); @@ -151,6 +151,26 @@ __device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float ra ray->D = panorama_to_direction(kg, Pcamera.x, Pcamera.y); + /* modify ray for depth of field */ + float aperturesize = kernel_data.cam.aperturesize; + + if(aperturesize > 0.0f) { + /* sample point on aperture */ + float2 lensuv = camera_sample_aperture(kg, lens_u, lens_v)*aperturesize; + + /* compute point on plane of focus */ + float3 D = normalize(ray->D); + float3 Pfocus = D * kernel_data.cam.focaldistance; + + /* calculate orthonormal coordinates perpendicular to D */ + float3 U, V; + make_orthonormals(D, &U, &V); + + /* update ray for effect of lens */ + ray->P = U * lensuv.x + V * lensuv.y; + ray->D = normalize(Pfocus - ray->P); + } + /* indicates ray should not receive any light, outside of the lens */ if(len_squared(ray->D) == 0.0f) { ray->t = 0.0f; @@ -160,7 +180,7 @@ __device void camera_sample_panorama(KernelGlobals *kg, float raster_x, float ra /* transform ray from camera to world */ Transform cameratoworld = kernel_data.cam.cameratoworld; -#ifdef __MOTION__ +#ifdef __CAMERA_MOTION__ if(kernel_data.cam.have_motion) transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time); #endif @@ -192,12 +212,12 @@ __device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, flo 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); -#ifdef __MOTION__ +#ifdef __CAMERA_MOTION__ /* motion blur */ if(kernel_data.cam.shuttertime == 0.0f) ray->time = TIME_INVALID; else - ray->time = 0.5f + (time - 0.5f)*kernel_data.cam.shuttertime; + ray->time = 0.5f + 0.5f*(time - 0.5f)*kernel_data.cam.shuttertime; #endif /* sample */ @@ -206,7 +226,7 @@ __device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, flo else if(kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) camera_sample_orthographic(kg, raster_x, raster_y, ray); else - camera_sample_panorama(kg, raster_x, raster_y, ray); + camera_sample_panorama(kg, raster_x, raster_y, lens_u, lens_v, ray); } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_displace.h b/intern/cycles/kernel/kernel_displace.h index 6461a1eea38..a55f7a7fd75 100644 --- a/intern/cycles/kernel/kernel_displace.h +++ b/intern/cycles/kernel/kernel_displace.h @@ -47,6 +47,9 @@ __device void kernel_shader_evaluate(KernelGlobals *kg, uint4 *input, float4 *ou ray.P = make_float3(0.0f, 0.0f, 0.0f); ray.D = equirectangular_to_direction(u, v); ray.t = 0.0f; +#ifdef __CAMERA_MOTION__ + ray.time = 0.5f; +#endif #ifdef __RAY_DIFFERENTIALS__ ray.dD.dx = make_float3(0.0f, 0.0f, 0.0f); diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 53d53b4bedd..6d650a0158d 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -32,8 +32,15 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando, Ray ray; ray.D = ls->D; ray.P = ls->P; + ray.t = 1.0f; +#ifdef __OBJECT_MOTION__ + ray.time = time; +#endif ray.dP.dx = make_float3(0.0f, 0.0f, 0.0f); ray.dP.dy = make_float3(0.0f, 0.0f, 0.0f); +#ifdef __CAMERA_MOTION__ + ray.time = time; +#endif shader_setup_from_background(kg, &sd, &ray); eval = shader_eval_background(kg, &sd, 0); } diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 1084415d0cf..2791b3abbb6 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -301,8 +301,13 @@ __device void triangle_light_sample(KernelGlobals *kg, int prim, int object, #ifdef __INSTANCING__ /* instance transform */ if(ls->object >= 0) { - Transform tfm = object_fetch_transform(kg, ls->object, time, OBJECT_TRANSFORM); - Transform itfm = object_fetch_transform(kg, ls->object, time, OBJECT_INVERSE_TRANSFORM); +#ifdef __OBJECT_MOTION__ + Transform itfm; + Transform tfm = object_fetch_transform_motion_test(kg, object, time, &itfm); +#else + Transform tfm = object_fetch_transform(kg, ls->object, OBJECT_TRANSFORM); + Transform itfm = object_fetch_transform(kg, ls->object, OBJECT_INVERSE_TRANSFORM); +#endif ls->P = transform_point(&tfm, ls->P); ls->Ng = normalize(transform_direction_transposed(&itfm, ls->Ng)); diff --git a/intern/cycles/kernel/kernel_mbvh.h b/intern/cycles/kernel/kernel_mbvh.h deleted file mode 100644 index ccbd3d069b4..00000000000 --- a/intern/cycles/kernel/kernel_mbvh.h +++ /dev/null @@ -1,394 +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. - */ - -CCL_NAMESPACE_BEGIN - -#define MBVH_OBJECT_SENTINEL 0x76543210 -#define MBVH_NODE_SIZE 8 -#define MBVH_STACK_SIZE 1024 -#define MBVH_RAY_STACK_SIZE 10000 - -typedef struct MBVHTask { - int node; - int index; - int num; - int object; -} MBVHTask; - -typedef struct MVBHRay { - float3 P; - float u; - float3 idir; - float v; - float t; - int index; - int object; - - float3 origP; - float3 origD; - float tmax; -} MBVHRay; - -__device float3 mbvh_inverse_direction(float3 dir) -{ - // Avoid divide by zero (ooeps = exp2f(-80.0f)) - float ooeps = 0.00000000000000000000000082718061255302767487140869206996285356581211090087890625f; - float3 idir; - - idir.x = 1.0f / (fabsf(dir.x) > ooeps ? dir.x : copysignf(ooeps, dir.x)); - idir.y = 1.0f / (fabsf(dir.y) > ooeps ? dir.y : copysignf(ooeps, dir.y)); - idir.z = 1.0f / (fabsf(dir.z) > ooeps ? dir.z : copysignf(ooeps, dir.z)); - - return idir; -} - -__device void mbvh_instance_push(KernelGlobals *kg, int object, MBVHRay *ray) -{ - Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); - - ray->P = transform_point(&tfm, ray->origP); - - float3 dir = ray->origD; - - if(ray->t != ray->tmax) dir *= ray->t; - - dir = transform_direction(&tfm, dir); - ray->idir = mbvh_inverse_direction(normalize(dir)); - - if(ray->t != ray->tmax) ray->t = len(dir); -} - -__device void mbvh_instance_pop(KernelGlobals *kg, int object, MBVHRay *ray) -{ - Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); - - if(ray->t != ray->tmax) - ray->t = len(transform_direction(&tfm, (1.0f/(ray->idir)) * (ray->t))); - - ray->P = ray->origP; - ray->idir = mbvh_inverse_direction(ray->origD); -} - -/* Sven Woop's algorithm */ -__device void mbvh_triangle_intersect(KernelGlobals *kg, MBVHRay *ray, int object, int triAddr) -{ - float3 P = ray->P; - float3 idir = ray->idir; - - /* compute and check intersection t-value */ - float4 v00 = kernel_tex_fetch(__tri_woop, triAddr*MBVH_NODE_SIZE+0); - float4 v11 = kernel_tex_fetch(__tri_woop, triAddr*MBVH_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 < ray->t) { - /* 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*MBVH_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) { - /* record intersection */ - ray->index = triAddr; - ray->object = object; - ray->u = u; - ray->v = v; - ray->t = t; - } - } - } -} - -__device void mbvh_node_intersect(KernelGlobals *kg, __m128 *traverseChild, - __m128 *tHit, float3 P, float3 idir, float t, int nodeAddr) -{ - /* X axis */ - const __m128 bminx = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*MBVH_NODE_SIZE+0); - const __m128 t0x = _mm_mul_ps(_mm_sub_ps(bminx, _mm_set_ps1(P.x)), _mm_set_ps1(idir.x)); - const __m128 bmaxx = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*MBVH_NODE_SIZE+1); - const __m128 t1x = _mm_mul_ps(_mm_sub_ps(bmaxx, _mm_set_ps1(P.x)), _mm_set_ps1(idir.x)); - - __m128 tmin = _mm_max_ps(_mm_min_ps(t0x, t1x), _mm_setzero_ps()); - __m128 tmax = _mm_min_ps(_mm_max_ps(t0x, t1x), _mm_set_ps1(t)); - - /* Y axis */ - const __m128 bminy = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*MBVH_NODE_SIZE+2); - const __m128 t0y = _mm_mul_ps(_mm_sub_ps(bminy, _mm_set_ps1(P.y)), _mm_set_ps1(idir.y)); - const __m128 bmaxy = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*MBVH_NODE_SIZE+3); - const __m128 t1y = _mm_mul_ps(_mm_sub_ps(bmaxy, _mm_set_ps1(P.y)), _mm_set_ps1(idir.y)); - - tmin = _mm_max_ps(_mm_min_ps(t0y, t1y), tmin); - tmax = _mm_min_ps(_mm_max_ps(t0y, t1y), tmax); - - /* Z axis */ - const __m128 bminz = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*MBVH_NODE_SIZE+4); - const __m128 t0z = _mm_mul_ps(_mm_sub_ps(bminz, _mm_set_ps1(P.z)), _mm_set_ps1(idir.z)); - const __m128 bmaxz = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*MBVH_NODE_SIZE+5); - const __m128 t1z = _mm_mul_ps(_mm_sub_ps(bmaxz, _mm_set_ps1(P.z)), _mm_set_ps1(idir.z)); - - tmin = _mm_max_ps(_mm_min_ps(t0z, t1z), tmin); - tmax = _mm_min_ps(_mm_max_ps(t0z, t1z), tmax); - - /* compare and get mask */ - *traverseChild = _mm_cmple_ps(tmin, tmax); - - /* get distance XXX probably wrong */ - *tHit = tmin; -} - -static void mbvh_sort_by_length(int id[4], float len[4]) -{ - for(int i = 1; i < 4; i++) { - int j = i - 1; - - while(j >= 0 && len[j] > len[j+1]) { - swap(len[j], len[j+1]); - swap(id[j], id[j+1]); - j--; - } - } -} - -__device void scene_intersect(KernelGlobals *kg, MBVHRay *rays, int numrays) -{ - /* traversal stacks */ - MBVHTask task_stack[MBVH_STACK_SIZE]; - int active_ray_stacks[4][MBVH_RAY_STACK_SIZE]; - int num_task, num_active[4] = {0, 0, 0, 0}; - __m128i one_mm = _mm_set1_epi32(1); - - /* push root node task on stack */ - task_stack[0].node = kernel_data.bvh.root; - task_stack[0].index = 0; - task_stack[0].num = numrays; - task_stack[0].object = ~0; - num_task = 1; - - /* push all rays in first SIMD lane */ - for(int i = 0; i < numrays; i++) - active_ray_stacks[0][i] = i; - num_active[0] = numrays; - - while(num_task >= 1) { - /* pop task */ - MBVHTask task = task_stack[--num_task]; - - if(task.node == MBVH_OBJECT_SENTINEL) { - /* instance pop */ - - /* pop rays from stack */ - num_active[task.index] -= task.num; - int ray_offset = num_active[task.index]; - - /* transform rays */ - for(int i = 0; i < task.num; i++) { - MBVHRay *ray = &rays[active_ray_stacks[task.index][ray_offset + i]]; - mbvh_instance_pop(kg, task.object, ray); - } - } - else if(task.node >= 0) { - /* inner node? */ - - /* pop rays from stack*/ - num_active[task.index] -= task.num; - int ray_offset = num_active[task.index]; - - /* initialze simd values */ - __m128i num_active_mm = _mm_load_si128((__m128i*)num_active); - __m128 len_mm = _mm_set_ps1(0.0f); - - for(int i = 0; i < task.num; i++) { - int rayid = active_ray_stacks[task.index][ray_offset + i]; - MVBHRay *ray = rays + rayid; - - /* intersect 4 QBVH node children */ - __m128 result; - __m128 thit; - - mbvh_node_intersect(kg, &result, &thit, ray->P, ray->idir, ray->t, task.node); - - /* update length for sorting */ - len_mm = _mm_add_ps(len_mm, _mm_and_ps(thit, result)); - - /* push rays on stack */ - for(int j = 0; j < 4; j++) - active_ray_stacks[j][num_active[j]] = rayid; - - /* update num active */ - __m128i resulti = _mm_and_si128(*((__m128i*)&result), one_mm); - num_active_mm = _mm_add_epi32(resulti, num_active_mm); - _mm_store_si128((__m128i*)num_active, num_active_mm); - } - - if(num_active[0] || num_active[1] || num_active[2] || num_active[3]) { - /* load child node addresses */ - float4 cnodes = kernel_tex_fetch(__bvh_nodes, task.node); - int child[4] = { - __float_as_int(cnodes.x), - __float_as_int(cnodes.y), - __float_as_int(cnodes.z), - __float_as_int(cnodes.w)}; - - /* sort nodes by average intersection distance */ - int ids[4] = {0, 1, 2, 3}; - float len[4]; - - _mm_store_ps(len, len_mm); - mbvh_sort_by_length(ids, len); - - /* push new tasks on stack */ - for(int j = 0; j < 4; j++) { - if(num_active[j]) { - int id = ids[j]; - - task_stack[num_task].node = child[id]; - task_stack[num_task].index = id; - task_stack[num_task].num = num_active[id]; - task_stack[num_task].object = task.object; - num_task++; - } - } - } - } - else { - /* fetch leaf node data */ - float4 leaf = kernel_tex_fetch(__bvh_nodes, (-task.node-1)*MBVH_NODE_SIZE+(MBVH_NODE_SIZE-2)); - int triAddr = __float_as_int(leaf.x); - int triAddr2 = __float_as_int(leaf.y); - - /* pop rays from stack*/ - num_active[task.index] -= task.num; - int ray_offset = num_active[task.index]; - - /* triangles */ - if(triAddr >= 0) { - int i, numq = (task.num >> 2) << 2; - - /* SIMD ray leaf intersection */ - for(i = 0; i < numq; i += 4) { - MBVHRay *ray4[4] = { - &rays[active_ray_stacks[task.index][ray_offset + i + 0]], - &rays[active_ray_stacks[task.index][ray_offset + i + 1]], - &rays[active_ray_stacks[task.index][ray_offset + i + 2]], - &rays[active_ray_stacks[task.index][ray_offset + i + 3]]}; - - /* load SoA */ - - while(triAddr < triAddr2) { - mbvh_triangle_intersect(ray4[0], task.object, task.node); - mbvh_triangle_intersect(ray4[1], task.object, task.node); - mbvh_triangle_intersect(ray4[2], task.object, task.node); - mbvh_triangle_intersect(ray4[3], task.object, task.node); - triAddr++; - - /* some shadow ray optim could be done by setting t=0 */ - } - - /* store AoS */ - } - - /* mono ray leaf intersection */ - for(; i < task.num; i++) { - MBVHRay *ray = &rays[active_ray_stacks[task.index][ray_offset + i]]; - - while(triAddr < triAddr2) { - mbvh_triangle_intersect(kg, ray, task.object, task.node); - triAddr++; - } - } - } - else { - /* instance push */ - int object = -triAddr-1; - int node = triAddr; - - /* push instance pop task */ - task_stack[num_task].node = MBVH_OBJECT_SENTINEL; - task_stack[num_task].index = task.index; - task_stack[num_task].num = task.num; - task_stack[num_task].object = object; - num_task++; - - num_active[task.index] += task.num; - - /* push node task */ - task_stack[num_task].node = node; - task_stack[num_task].index = task.index; - task_stack[num_task].num = task.num; - task_stack[num_task].object = object; - num_task++; - - for(int i = 0; i < task.num; i++) { - int rayid = active_ray_stacks[task.index][ray_offset + i]; - - /* push on stack for last task */ - active_ray_stacks[task.index][num_active[task.index]] = rayid; - num_active[task.index]++; - - /* transform ray */ - MBVHRay *ray = &rays[rayid]; - mbvh_instance_push(kg, object, ray); - } - } - } - } -} - -__device void mbvh_set_ray(MBVHRay *rays, int i, Ray *ray, float tmax) -{ - MBVHRay *mray = &rays[i]; - - /* ray parameters in registers */ - mray->P = ray->P; - mray->idir = mbvh_inverse_direction(ray->D); - mray->t = tmax; -} - -__device bool mbvh_get_intersection(MVBHRay *rays, int i, Intersection *isect, float tmax) -{ - MBVHRay *mray = &rays[i]; - - if(mray->t == tmax) - return false; - - isect->t = mray->t; - isect->u = mray->u; - isect->v = mray->v; - isect->index = mray->index; - isect->object = mray->object; - - return true; -} - -__device bool mbvh_get_shadow(MBVHRay *rays, int i, float tmax) -{ - return (rays[i].t == tmax); -} - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/kernel_montecarlo.h b/intern/cycles/kernel/kernel_montecarlo.h index afc53b1117a..48d1aa64c9f 100644 --- a/intern/cycles/kernel/kernel_montecarlo.h +++ b/intern/cycles/kernel/kernel_montecarlo.h @@ -46,16 +46,19 @@ __device void to_unit_disk(float *x, float *y) if(a > -b) { if(a > b) { r = a; - phi = M_PI_4_F *(b/a); - } else { - r = b; - phi = M_PI_4_F *(2.0f - a/b); - } - } else { + phi = M_PI_4_F *(b/a); + } + else { + r = b; + phi = M_PI_4_F *(2.0f - a/b); + } + } + else { if(a < b) { r = -a; phi = M_PI_4_F *(4.0f + b/a); - } else { + } + else { r = -b; if(b != 0.0f) phi = M_PI_4_F *(6.0f - a/b); @@ -69,7 +72,7 @@ __device void to_unit_disk(float *x, float *y) __device void make_orthonormals_tangent(const float3 N, const float3 T, float3 *a, float3 *b) { - *b = cross(N, T); + *b = normalize(cross(N, T)); *a = cross(*b, N); } diff --git a/intern/cycles/kernel/kernel_object.h b/intern/cycles/kernel/kernel_object.h index 222ade504cc..112bfbb86b5 100644 --- a/intern/cycles/kernel/kernel_object.h +++ b/intern/cycles/kernel/kernel_object.h @@ -23,42 +23,16 @@ enum ObjectTransform { OBJECT_INVERSE_TRANSFORM = 3, OBJECT_PROPERTIES = 6, OBJECT_TRANSFORM_MOTION_PRE = 8, - OBJECT_TRANSFORM_MOTION_POST = 12 + OBJECT_TRANSFORM_MOTION_MID = 12, + OBJECT_TRANSFORM_MOTION_POST = 16, + OBJECT_DUPLI = 20 }; -__device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, float time, enum ObjectTransform type) +__device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, enum ObjectTransform type) { - Transform tfm; - -#ifdef __MOTION__ - /* if we do motion blur */ - if(sd->flag & SD_OBJECT_MOTION) { - /* fetch motion transforms */ - MotionTransform motion; - - motion.pre.x = have_motion; - motion.pre.y = kernel_tex_fetch(__objects, offset + 1); - motion.pre.z = kernel_tex_fetch(__objects, offset + 2); - motion.pre.w = kernel_tex_fetch(__objects, offset + 3); - - motion.post.x = kernel_tex_fetch(__objects, offset + 4); - motion.post.y = kernel_tex_fetch(__objects, offset + 5); - motion.post.z = kernel_tex_fetch(__objects, offset + 6); - motion.post.w = kernel_tex_fetch(__objects, offset + 7); - - /* interpolate (todo: do only once per object) */ - transform_motion_interpolate(&tfm, &motion, time); - - /* invert */ - if(type == OBJECT_INVERSE_TRANSFORM) - tfm = transform_quick_inverse(tfm); - - return tfm; - } -#endif - int offset = object*OBJECT_SIZE + (int)type; + Transform tfm; tfm.x = kernel_tex_fetch(__objects, offset + 0); tfm.y = kernel_tex_fetch(__objects, offset + 1); tfm.z = kernel_tex_fetch(__objects, offset + 2); @@ -67,62 +41,116 @@ __device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, return tfm; } +#ifdef __OBJECT_MOTION__ +__device_inline Transform object_fetch_transform_motion(KernelGlobals *kg, int object, float time) +{ + MotionTransform motion; + + int offset = object*OBJECT_SIZE + (int)OBJECT_TRANSFORM_MOTION_PRE; + + motion.pre.x = kernel_tex_fetch(__objects, offset + 0); + motion.pre.y = kernel_tex_fetch(__objects, offset + 1); + motion.pre.z = kernel_tex_fetch(__objects, offset + 2); + motion.pre.w = kernel_tex_fetch(__objects, offset + 3); + + motion.mid.x = kernel_tex_fetch(__objects, offset + 4); + motion.mid.y = kernel_tex_fetch(__objects, offset + 5); + motion.mid.z = kernel_tex_fetch(__objects, offset + 6); + motion.mid.w = kernel_tex_fetch(__objects, offset + 7); + + motion.post.x = kernel_tex_fetch(__objects, offset + 8); + motion.post.y = kernel_tex_fetch(__objects, offset + 9); + motion.post.z = kernel_tex_fetch(__objects, offset + 10); + motion.post.w = kernel_tex_fetch(__objects, offset + 11); + + Transform tfm; + transform_motion_interpolate(&tfm, &motion, time); + + return tfm; +} + +__device_inline Transform object_fetch_transform_motion_test(KernelGlobals *kg, int object, float time, Transform *itfm) +{ + int object_flag = kernel_tex_fetch(__object_flag, object); + + if(object_flag & SD_OBJECT_MOTION) { + /* if we do motion blur */ + Transform tfm = object_fetch_transform_motion(kg, object, time); + + if(itfm) + *itfm = transform_quick_inverse(tfm); + + return tfm; + } + else { + Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); + if(itfm) + *itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); + + return tfm; + } +} +#endif + __device_inline void object_position_transform(KernelGlobals *kg, ShaderData *sd, float3 *P) { -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ *P = transform_point(&sd->ob_tfm, *P); #else - Transform tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_TRANSFORM); + Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM); *P = transform_point(&tfm, *P); #endif } __device_inline void object_inverse_position_transform(KernelGlobals *kg, ShaderData *sd, float3 *P) { -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ *P = transform_point(&sd->ob_itfm, *P); #else - Transform tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_INVERSE_TRANSFORM); + Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM); *P = transform_point(&tfm, *P); #endif } __device_inline void object_inverse_normal_transform(KernelGlobals *kg, ShaderData *sd, float3 *N) { -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ *N = normalize(transform_direction_transposed(&sd->ob_tfm, *N)); #else - Transform tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_TRANSFORM); + Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM); *N = normalize(transform_direction_transposed(&tfm, *N)); #endif } __device_inline void object_normal_transform(KernelGlobals *kg, ShaderData *sd, float3 *N) { -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ *N = normalize(transform_direction_transposed(&sd->ob_itfm, *N)); #else - Transform tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_INVERSE_TRANSFORM); + Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM); *N = normalize(transform_direction_transposed(&tfm, *N)); #endif } __device_inline void object_dir_transform(KernelGlobals *kg, ShaderData *sd, float3 *D) { -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ *D = transform_direction(&sd->ob_tfm, *D); #else - Transform tfm = object_fetch_transform(kg, sd->object, 0.0f, OBJECT_TRANSFORM); + Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM); *D = transform_direction(&tfm, *D); #endif } __device_inline float3 object_location(KernelGlobals *kg, ShaderData *sd) { -#ifdef __MOTION__ + if(sd->object == ~0) + return make_float3(0.0f, 0.0f, 0.0f); + +#ifdef __OBJECT_MOTION__ return make_float3(sd->ob_tfm.x.w, sd->ob_tfm.y.w, sd->ob_tfm.z.w); #else - Transform tfm = object_fetch_transform(kg, sd->object, 0.0f, OBJECT_TRANSFORM); + Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM); return make_float3(tfm.x.w, tfm.y.w, tfm.z.w); #endif } @@ -164,6 +192,27 @@ __device_inline uint object_particle_id(KernelGlobals *kg, int object) return __float_as_int(f.w); } +__device_inline float3 object_dupli_generated(KernelGlobals *kg, int object) +{ + if(object == ~0) + return make_float3(0.0f, 0.0f, 0.0f); + + int offset = object*OBJECT_SIZE + OBJECT_DUPLI; + float4 f = kernel_tex_fetch(__objects, offset); + return make_float3(f.x, f.y, f.z); +} + +__device_inline float3 object_dupli_uv(KernelGlobals *kg, int object) +{ + if(object == ~0) + return make_float3(0.0f, 0.0f, 0.0f); + + int offset = object*OBJECT_SIZE + OBJECT_DUPLI; + float4 f = kernel_tex_fetch(__objects, offset + 1); + return make_float3(f.x, f.y, 0.0f); +} + + __device int shader_pass_id(KernelGlobals *kg, ShaderData *sd) { return kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2 + 1); @@ -227,6 +276,5 @@ __device float3 particle_angular_velocity(KernelGlobals *kg, int particle) return make_float3(f3.z, f3.w, f4.x); } - CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index f3ddda4a392..42733d691e0 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -125,8 +125,18 @@ __device_inline void kernel_write_light_passes(KernelGlobals *kg, __global float kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_color, sample, L->color_glossy); if(flag & PASS_TRANSMISSION_COLOR) kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_color, sample, L->color_transmission); - if(flag & PASS_SHADOW) - kernel_write_pass_float4(buffer + kernel_data.film.pass_shadow, sample, L->shadow); + if(flag & PASS_SHADOW) { + float4 shadow = L->shadow; + + /* bit of an ugly hack to compensate for emitting triangles influencing + * amount of samples we get for this pass */ + if(kernel_data.integrator.progressive && kernel_data.integrator.pdf_triangles != 0.0f) + shadow.w = 0.5f; + else + shadow.w = 1.0f; + + kernel_write_pass_float4(buffer + kernel_data.film.pass_shadow, sample, shadow); + } #endif } diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index d606c3d634a..817f254a5e5 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -343,7 +343,7 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, light_ray.P = ray_offset(sd.P, sd.Ng); light_ray.D = ao_D; light_ray.t = kernel_data.background.ao_distance; -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ light_ray.time = sd.time; #endif @@ -368,7 +368,7 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, BsdfEval L_light; bool is_lamp; -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ light_ray.time = sd.time; #endif @@ -520,7 +520,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray light_ray.P = ray_offset(sd.P, sd.Ng); light_ray.D = ao_D; light_ray.t = kernel_data.background.ao_distance; -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ light_ray.time = sd.time; #endif @@ -545,7 +545,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray BsdfEval L_light; bool is_lamp; -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ light_ray.time = sd.time; #endif @@ -728,7 +728,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam light_ray.P = ray_offset(sd.P, sd.Ng); light_ray.D = ao_D; light_ray.t = kernel_data.background.ao_distance; -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ light_ray.time = sd.time; #endif @@ -748,7 +748,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam BsdfEval L_light; bool is_lamp; -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ light_ray.time = sd.time; #endif @@ -867,7 +867,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam bsdf_ray.dP = sd.dP; bsdf_ray.dD = bsdf_domega_in; #endif -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ bsdf_ray.time = sd.time; #endif @@ -925,7 +925,7 @@ __device void kernel_path_trace(KernelGlobals *kg, float lens_u = path_rng(kg, &rng, sample, PRNG_LENS_U); float lens_v = path_rng(kg, &rng, sample, PRNG_LENS_V); -#ifdef __MOTION__ +#ifdef __CAMERA_MOTION__ float time = path_rng(kg, &rng, sample, PRNG_TIME); #else float time = 0.0f; diff --git a/intern/cycles/kernel/kernel_qbvh.h b/intern/cycles/kernel/kernel_qbvh.h deleted file mode 100644 index 525b616921d..00000000000 --- a/intern/cycles/kernel/kernel_qbvh.h +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Adapted from code Copyright 2009-2010 NVIDIA Corporation - * Modifications Copyright 2011, Blender Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -CCL_NAMESPACE_BEGIN - -/* - * "Persistent while-while kernel" used in: - * - * "Understanding the Efficiency of Ray Traversal on GPUs", - * Timo Aila and Samuli Laine, - * Proc. High-Performance Graphics 2009 - */ - -/* bottom-most stack entry, indicating the end of traversal */ - -#define ENTRYPOINT_SENTINEL 0x76543210 -/* 64 object BVH + 64 mesh BVH + 64 object node splitting */ -#define QBVH_STACK_SIZE 192 -#define QBVH_NODE_SIZE 8 -#define TRI_NODE_SIZE 3 - -__device_inline float3 qbvh_inverse_direction(float3 dir) -{ - // Avoid divide by zero (ooeps = exp2f(-80.0f)) - float ooeps = 0.00000000000000000000000082718061255302767487140869206996285356581211090087890625f; - float3 idir; - - idir.x = 1.0f/((fabsf(dir.x) > ooeps)? dir.x: copysignf(ooeps, dir.x)); - idir.y = 1.0f/((fabsf(dir.y) > ooeps)? dir.y: copysignf(ooeps, dir.y)); - idir.z = 1.0f/((fabsf(dir.z) > ooeps)? dir.z: copysignf(ooeps, dir.z)); - - return idir; -} - -__device_inline void qbvh_instance_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *idir, float *t, const float tmax) -{ - Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); - - *P = transform_point(&tfm, ray->P); - - float3 dir = transform_direction(&tfm, ray->D); - - float len; - dir = normalize_len(dir, &len); - - *idir = qbvh_inverse_direction(dir); - - if(*t != FLT_MAX) - *t *= len; -} - -__device_inline void qbvh_instance_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *idir, float *t, const float tmax) -{ - Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); - - if(*t != FLT_MAX) - *t *= len(transform_direction(&tfm, 1.0f/(*idir))); - - *P = ray->P; - *idir = qbvh_inverse_direction(ray->D); -} - -#ifdef __KERNEL_CPU__ - -__device_inline void qbvh_node_intersect(KernelGlobals *kg, int *traverseChild, - int nodeAddrChild[4], float3 P, float3 idir, float t, int nodeAddr) -{ - /* X axis */ - const __m128 bminx = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+0); - const __m128 t0x = _mm_mul_ps(_mm_sub_ps(bminx, _mm_set_ps1(P.x)), _mm_set_ps1(idir.x)); - const __m128 bmaxx = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+1); - const __m128 t1x = _mm_mul_ps(_mm_sub_ps(bmaxx, _mm_set_ps1(P.x)), _mm_set_ps1(idir.x)); - - __m128 tmin = _mm_max_ps(_mm_min_ps(t0x, t1x), _mm_setzero_ps()); - __m128 tmax = _mm_min_ps(_mm_max_ps(t0x, t1x), _mm_set_ps1(t)); - - /* Y axis */ - const __m128 bminy = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+2); - const __m128 t0y = _mm_mul_ps(_mm_sub_ps(bminy, _mm_set_ps1(P.y)), _mm_set_ps1(idir.y)); - const __m128 bmaxy = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+3); - const __m128 t1y = _mm_mul_ps(_mm_sub_ps(bmaxy, _mm_set_ps1(P.y)), _mm_set_ps1(idir.y)); - - tmin = _mm_max_ps(_mm_min_ps(t0y, t1y), tmin); - tmax = _mm_min_ps(_mm_max_ps(t0y, t1y), tmax); - - /* Z axis */ - const __m128 bminz = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+4); - const __m128 t0z = _mm_mul_ps(_mm_sub_ps(bminz, _mm_set_ps1(P.z)), _mm_set_ps1(idir.z)); - const __m128 bmaxz = kernel_tex_fetch_m128(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+5); - const __m128 t1z = _mm_mul_ps(_mm_sub_ps(bmaxz, _mm_set_ps1(P.z)), _mm_set_ps1(idir.z)); - - tmin = _mm_max_ps(_mm_min_ps(t0z, t1z), tmin); - tmax = _mm_min_ps(_mm_max_ps(t0z, t1z), tmax); - - /* compare and get mask */ - *traverseChild = _mm_movemask_ps(_mm_cmple_ps(tmin, tmax)); - - /* get node addresses */ - float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+6); - - nodeAddrChild[0] = __float_as_int(cnodes.x); - nodeAddrChild[1] = __float_as_int(cnodes.y); - nodeAddrChild[2] = __float_as_int(cnodes.z); - nodeAddrChild[3] = __float_as_int(cnodes.w); -} - -#else - -__device_inline bool qbvh_bb_intersect(float3 bmin, float3 bmax, float3 P, float3 idir, float t) -{ - float t0x = (bmin.x - P.x)*idir.x; - float t1x = (bmax.x - P.x)*idir.x; - float t0y = (bmin.y - P.y)*idir.y; - float t1y = (bmax.y - P.y)*idir.y; - float t0z = (bmin.z - P.z)*idir.z; - float t1z = (bmax.z - P.z)*idir.z; - - float minx = min(t0x, t1x); - float maxx = max(t0x, t1x); - float miny = min(t0y, t1y); - float maxy = max(t0y, t1y); - float minz = min(t0z, t1z); - float maxz = max(t0z, t1z); - - float tmin = max4(0.0f, minx, miny, minz); - float tmax = min4(t, maxx, maxy, maxz); - - return (tmin <= tmax); -} - -/* intersect four bounding boxes */ -__device_inline void qbvh_node_intersect(KernelGlobals *kg, int *traverseChild, - int nodeAddrChild[4], float3 P, float3 idir, float t, int nodeAddr) -{ - /* fetch node data */ - float4 minx = kernel_tex_fetch(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+0); - float4 miny = kernel_tex_fetch(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+2); - float4 minz = kernel_tex_fetch(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+4); - float4 maxx = kernel_tex_fetch(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+1); - float4 maxy = kernel_tex_fetch(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+3); - float4 maxz = kernel_tex_fetch(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+5); - - /* intersect bounding boxes */ - bool traverseChild0 = qbvh_bb_intersect(make_float3(minx.x, miny.x, minz.x), make_float3(maxx.x, maxy.x, maxz.x), P, idir, t); - bool traverseChild1 = qbvh_bb_intersect(make_float3(minx.y, miny.y, minz.y), make_float3(maxx.y, maxy.y, maxz.y), P, idir, t); - bool traverseChild2 = qbvh_bb_intersect(make_float3(minx.z, miny.z, minz.z), make_float3(maxx.z, maxy.z, maxz.z), P, idir, t); - bool traverseChild3 = qbvh_bb_intersect(make_float3(minx.w, miny.w, minz.w), make_float3(maxx.w, maxy.w, maxz.w), P, idir, t); - - *traverseChild = 0; - if(traverseChild0) *traverseChild |= 1; - if(traverseChild1) *traverseChild |= 2; - if(traverseChild2) *traverseChild |= 4; - if(traverseChild3) *traverseChild |= 8; - - /* get node addresses */ - float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*QBVH_NODE_SIZE+6); - - nodeAddrChild[0] = __float_as_int(cnodes.x); - nodeAddrChild[1] = __float_as_int(cnodes.y); - nodeAddrChild[2] = __float_as_int(cnodes.z); - nodeAddrChild[3] = __float_as_int(cnodes.w); -} - -#endif - -/* Sven Woop's algorithm */ -__device_inline void qbvh_triangle_intersect(KernelGlobals *kg, Intersection *isect, float3 P, float3 idir, int object, int triAddr) -{ - /* 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 < isect->t) { - /* 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) { - /* record intersection */ - isect->prim = triAddr; - isect->object = object; - isect->u = u; - isect->v = v; - isect->t = t; - } - } - } -} - -__device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const bool isshadowray, Intersection *isect) -{ - /* traversal stack in CUDA thread-local memory */ - int traversalStack[QBVH_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 = qbvh_inverse_direction(ray->D); - int object = ~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) - { - int traverseChild, nodeAddrChild[4]; - - qbvh_node_intersect(kg, &traverseChild, nodeAddrChild, - P, idir, isect->t, nodeAddr); - - if(traverseChild & 1) { - ++stackPtr; - traversalStack[stackPtr] = nodeAddrChild[0]; - } - - if(traverseChild & 2) { - ++stackPtr; - traversalStack[stackPtr] = nodeAddrChild[1]; - } - if(traverseChild & 4) { - ++stackPtr; - traversalStack[stackPtr] = nodeAddrChild[2]; - } - - if(traverseChild & 8) { - ++stackPtr; - traversalStack[stackPtr] = nodeAddrChild[3]; - } - - nodeAddr = traversalStack[stackPtr]; - --stackPtr; - } - - /* if node is leaf, fetch triangle list */ - if(nodeAddr < 0) { - float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*QBVH_NODE_SIZE+(QBVH_NODE_SIZE-2)); - 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; - - /* triangle intersection */ - while(primAddr < primAddr2) { - /* intersect ray against triangle */ - qbvh_triangle_intersect(kg, isect, P, idir, object, primAddr); - - /* shadow ray early termination */ - if(isshadowray && isect->prim != ~0) - return true; - - primAddr++; - } -#ifdef __INSTANCING__ - } - else { - /* instance push */ - object = kernel_tex_fetch(__prim_object, -primAddr-1); - - qbvh_instance_push(kg, object, ray, &P, &idir, &isect->t, tmax); - - ++stackPtr; - traversalStack[stackPtr] = ENTRYPOINT_SENTINEL; - - nodeAddr = kernel_tex_fetch(__object_node, object); - } -#endif - } - } while(nodeAddr != ENTRYPOINT_SENTINEL); - -#ifdef __INSTANCING__ - if(stackPtr >= 0) { - kernel_assert(object != ~0); - - /* instance pop */ - qbvh_instance_pop(kg, object, ray, &P, &idir, &isect->t, tmax); - object = ~0; - nodeAddr = traversalStack[stackPtr]; - --stackPtr; - } -#endif - } while(nodeAddr != ENTRYPOINT_SENTINEL); - - return (isect->prim != ~0); -} - -__device_inline float3 ray_offset(float3 P, float3 Ng) -{ -#ifdef __INTERSECTION_REFINE__ - const float epsilon_f = 1e-5f; - const int epsilon_i = 32; - - float3 res; - - /* x component */ - if(fabsf(P.x) < epsilon_f) { - res.x = P.x + Ng.x*epsilon_f; - } - else { - uint ix = __float_as_uint(P.x); - ix += ((ix ^ __float_as_uint(Ng.x)) >> 31)? -epsilon_i: epsilon_i; - res.x = __uint_as_float(ix); - } - - /* y component */ - if(fabsf(P.y) < epsilon_f) { - res.y = P.y + Ng.y*epsilon_f; - } - else { - uint iy = __float_as_uint(P.y); - iy += ((iy ^ __float_as_uint(Ng.y)) >> 31)? -epsilon_i: epsilon_i; - res.y = __uint_as_float(iy); - } - - /* z component */ - if(fabsf(P.z) < epsilon_f) { - res.z = P.z + Ng.z*epsilon_f; - } - else { - uint iz = __float_as_uint(P.z); - iz += ((iz ^ __float_as_uint(Ng.z)) >> 31)? -epsilon_i: epsilon_i; - res.z = __uint_as_float(iz); - } - - return res; -#else - const float epsilon_f = 1e-4f; - return P + epsilon_f*Ng; -#endif -} - -__device_inline float3 bvh_triangle_refine(KernelGlobals *kg, const Intersection *isect, const Ray *ray) -{ - float3 P = ray->P; - float3 D = ray->D; - float t = isect->t; - -#ifdef __INTERSECTION_REFINE__ - if(isect->object != ~0) { - Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM); - - P = transform_point(&tfm, P); - D = transform_direction(&tfm, D*t); - D = normalize_len(D, &t); - } - - P = P + D*t; - - float4 v00 = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0); - float Oz = v00.w - P.x*v00.x - P.y*v00.y - P.z*v00.z; - float invDz = 1.0f/(D.x*v00.x + D.y*v00.y + D.z*v00.z); - float rt = Oz * invDz; - - P = P + D*rt; - - if(isect->object != ~0) { - Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM); - P = transform_point(&tfm, P); - } - - return P; -#else - return P + D*t; -#endif -} - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index b57e27bc8ed..86886a6a231 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -27,22 +27,36 @@ */ #ifdef __OSL__ - #include "osl_shader.h" - #endif -#include "svm/bsdf.h" -#include "svm/emissive.h" -#include "svm/volume.h" +#include "closure/bsdf.h" +#include "closure/emissive.h" +#include "closure/volume.h" + #include "svm/svm_bsdf.h" #include "svm/svm.h" - CCL_NAMESPACE_BEGIN /* ShaderData setup from incoming ray */ +#ifdef __OBJECT_MOTION__ +__device_noinline void shader_setup_object_transforms(KernelGlobals *kg, ShaderData *sd, float time) +{ + /* note that this is a separate non-inlined function to work around crash + * on CUDA sm 2.0, otherwise kernel execution crashes (compiler bug?) */ + if(sd->flag & SD_OBJECT_MOTION) { + sd->ob_tfm = object_fetch_transform_motion(kg, sd->object, time); + sd->ob_itfm= transform_quick_inverse(sd->ob_tfm); + } + else { + sd->ob_tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM); + sd->ob_itfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM); + } +} +#endif + __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray) { @@ -67,11 +81,12 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, sd->v = isect->v; #endif - /* matrices and time */ -#ifdef __MOTION__ - sd->ob_tfm = object_fetch_transform(kg, sd->object, ray->time, OBJECT_TRANSFORM); - sd->ob_itfm = object_fetch_transform(kg, sd->object, ray->time, OBJECT_INVERSE_TRANSFORM); + sd->flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*2); + sd->flag |= kernel_tex_fetch(__object_flag, sd->object); + /* matrices and time */ +#ifdef __OBJECT_MOTION__ + shader_setup_object_transforms(kg, sd, ray->time); sd->time = ray->time; #endif @@ -87,9 +102,6 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, if(sd->shader & SHADER_SMOOTH_NORMAL) sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v); - sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2); - sd->flag |= kernel_tex_fetch(__object_flag, sd->object); - #ifdef __DPDU__ /* dPdu/dPdv */ triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim); @@ -171,11 +183,17 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, } #endif -#ifdef __MOTION__ - sd->time = time; + sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2); + if(sd->object != -1) { + sd->flag |= kernel_tex_fetch(__object_flag, sd->object); - sd->ob_tfm = object_fetch_transform(kg, sd->object, time, OBJECT_TRANSFORM); - sd->ob_itfm = object_fetch_transform(kg, sd->object, time, OBJECT_INVERSE_TRANSFORM); +#ifdef __OBJECT_MOTION__ + shader_setup_object_transforms(kg, sd, time); + } + + sd->time = time; +#else + } #endif /* smooth normal */ @@ -188,10 +206,6 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, #endif } - sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2); - if(sd->object != -1) - sd->flag |= kernel_tex_fetch(__object_flag, sd->object); - #ifdef __DPDU__ /* dPdu/dPdv */ if(sd->prim == ~0) { @@ -275,7 +289,7 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData sd->I = -sd->P; sd->shader = kernel_data.background.shader; sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2); -#ifdef __MOTION__ +#ifdef __OBJECT_MOTION__ sd->time = ray->time; #endif sd->ray_length = 0.0f; @@ -483,18 +497,22 @@ __device int shader_bsdf_sample_closure(KernelGlobals *kg, const ShaderData *sd, __device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughness) { -#ifndef __OSL__ #ifdef __MULTI_CLOSURE__ for(int i = 0; i< sd->num_closure; i++) { ShaderClosure *sc = &sd->closure[i]; - if(CLOSURE_IS_BSDF(sc->type)) - svm_bsdf_blur(sc, roughness); + if(CLOSURE_IS_BSDF(sc->type)) { +#ifdef __OSL__ + if (kernel_osl_use(kg)) + OSLShader::bsdf_blur(sc, roughness); + else +#endif + svm_bsdf_blur(sc, roughness); + } } #else svm_bsdf_blur(&sd->closure, roughness); #endif -#endif } __device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd) @@ -704,16 +722,16 @@ __device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd, if(CLOSURE_IS_VOLUME(sc->type)) { #ifdef __OSL__ if (kernel_osl_use(kg)) - eval += OSLShader::volume_eval_phase(sd, sc, omega_in, omega_out); + eval += OSLShader::volume_eval_phase(sc, omega_in, omega_out); else #endif - eval += volume_eval_phase(sd, sc, omega_in, omega_out); + eval += volume_eval_phase(sc, omega_in, omega_out); } } return eval; #else - return volume_eval_phase(sd, &sd->closure, omega_in, omega_out); + return volume_eval_phase(&sd->closure, omega_in, omega_out); #endif } diff --git a/intern/cycles/kernel/kernel_triangle.h b/intern/cycles/kernel/kernel_triangle.h index f57c59a45eb..e39ae1d4fbc 100644 --- a/intern/cycles/kernel/kernel_triangle.h +++ b/intern/cycles/kernel/kernel_triangle.h @@ -68,6 +68,17 @@ __device_inline float3 triangle_normal_MT(KernelGlobals *kg, int tri_index, int #endif } +/* Return 3 triangle vertex locations */ +__device_inline void triangle_vertices(KernelGlobals *kg, int tri_index, float3 P[3]) +{ + /* load triangle vertices */ + float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, tri_index)); + + P[0] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x))); + P[1] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y))); + P[2] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z))); +} + __device_inline float3 triangle_smooth_normal(KernelGlobals *kg, int tri_index, float u, float v) { /* load triangle vertices */ @@ -201,10 +212,10 @@ __device float4 triangle_motion_vector(KernelGlobals *kg, ShaderData *sd) * transformation was set match the world/object space of motion_pre/post */ Transform tfm; - tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_TRANSFORM_MOTION_PRE); + tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM_MOTION_PRE); motion_pre = transform_point(&tfm, motion_pre); - tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_TRANSFORM_MOTION_POST); + tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM_MOTION_POST); motion_post = transform_point(&tfm, motion_post); float3 P; diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index ce21ab994f0..98d998351a7 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -29,13 +29,15 @@ CCL_NAMESPACE_BEGIN /* constants */ -#define OBJECT_SIZE 16 +#define OBJECT_SIZE 22 #define LIGHT_SIZE 4 #define FILTER_TABLE_SIZE 256 #define RAMP_TABLE_SIZE 256 #define PARTICLE_SIZE 5 #define TIME_INVALID FLT_MAX +#define TEX_NUM_FLOAT_IMAGES 5 + /* device capabilities */ #ifdef __KERNEL_CPU__ #define __KERNEL_SHADING__ @@ -108,11 +110,15 @@ CCL_NAMESPACE_BEGIN #define __PASSES__ #define __BACKGROUND_MIS__ #define __AO__ -//#define __MOTION__ +#define __CAMERA_MOTION__ + +#ifndef __KERNEL_CUDA__ +#define __OBJECT_MOTION__ +#endif + #endif //#define __SOBOL_FULL_SCREEN__ -//#define __QBVH__ /* Shader Evaluation */ @@ -129,7 +135,7 @@ enum PathTraceDimension { PRNG_FILTER_V = 1, PRNG_LENS_U = 2, PRNG_LENS_V = 3, -#ifdef __MOTION__ +#ifdef __CAMERA_MOTION__ PRNG_TIME = 4, PRNG_UNUSED = 5, PRNG_BASE_NUM = 6, @@ -148,9 +154,7 @@ enum PathTraceDimension { PRNG_BOUNCE_NUM = 8 }; -/* these flag values correspond exactly to OSL defaults, so be careful not to - * change this, or if you do, set the "raytypes" shading system attribute with - * your own new ray types and bitflag values. +/* these flags values correspond to raytypes in osl.cpp, so keep them in sync! * * for ray visibility tests in BVH traversal, the upper 20 bits are used for * layer visibility tests. */ @@ -370,6 +374,9 @@ typedef struct ShaderClosure { float data0; float data1; + float3 N; + float3 T; + } ShaderClosure; /* Shader Data @@ -408,7 +415,7 @@ typedef struct ShaderData { /* view/incoming direction */ float3 I; /* shader id */ - int shader; + int shader; /* booleans describing shader, see ShaderDataFlag */ int flag; @@ -426,13 +433,6 @@ typedef struct ShaderData { /* length of the ray being shaded */ float ray_length; -#ifdef __MOTION__ - /* object <-> world space transformations, cached to avoid - * re-interpolating them constantly for shading */ - Transform ob_tfm; - Transform ob_itfm; -#endif - #ifdef __RAY_DIFFERENTIALS__ /* differential of P. these are orthogonal to Ng, not N */ differential3 dP; @@ -448,6 +448,13 @@ typedef struct ShaderData { float3 dPdu, dPdv; #endif +#ifdef __OBJECT_MOTION__ + /* object <-> world space transformations, cached to avoid + * re-interpolating them constantly for shading */ + Transform ob_tfm; + Transform ob_itfm; +#endif + #ifdef __MULTI_CLOSURE__ /* Closure data, we store a fixed array of closures */ ShaderClosure closure[MAX_CLOSURE]; @@ -511,7 +518,9 @@ typedef struct KernelCamera { /* more matrices */ Transform screentoworld; Transform rastertoworld; - Transform ndctoworld; + /* work around cuda sm 2.0 crash, this seems to + * cross some limit in combination with motion + * Transform ndctoworld; */ Transform worldtoscreen; Transform worldtoraster; Transform worldtondc; @@ -627,7 +636,8 @@ typedef struct KernelBVH { /* root node */ int root; int attributes_map_stride; - int pad1, pad2; + int have_motion; + int pad2; } KernelBVH; typedef struct KernelData { diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt index d4ea8b12f5a..8938b16a48f 100644 --- a/intern/cycles/kernel/osl/CMakeLists.txt +++ b/intern/cycles/kernel/osl/CMakeLists.txt @@ -8,25 +8,16 @@ set(INC ../../device ) +set(INC_SYS + +) + set(SRC background.cpp - bsdf_ashikhmin_velvet.cpp - bsdf_diffuse.cpp - bsdf_oren_nayar.cpp - bsdf_phong.cpp - bsdf_microfacet.cpp - bsdf_reflection.cpp - bsdf_refraction.cpp - bsdf_transparent.cpp - bsdf_ward.cpp - bsdf_westin.cpp - bssrdf.cpp - debug.cpp emissive.cpp osl_closures.cpp osl_services.cpp osl_shader.cpp - vol_subsurface.cpp ) set(HEADER_SRC @@ -39,7 +30,7 @@ set(HEADER_SRC set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${RTTI_DISABLE_FLAGS}") include_directories(${INC}) +include_directories(SYSTEM ${INC_SYS}) add_library(cycles_kernel_osl ${SRC} ${HEADER_SRC}) -add_subdirectory(nodes) diff --git a/intern/cycles/kernel/osl/background.cpp b/intern/cycles/kernel/osl/background.cpp index 81812a46b6c..b6e9473b7bf 100644 --- a/intern/cycles/kernel/osl/background.cpp +++ b/intern/cycles/kernel/osl/background.cpp @@ -46,23 +46,16 @@ using namespace OSL; /// to return a color in background shaders. No methods, /// only the weight is taking into account /// -class GenericBackgroundClosure : public BackgroundClosure { +class GenericBackgroundClosure : public OSL::BackgroundClosure { public: GenericBackgroundClosure() {} void setup() {}; - size_t memsize() const { return sizeof(*this); } - const char *name() const { return "background"; } - - void print_on(std::ostream &out) const { - out << name() << " ()"; - } - + void print_on(std::ostream &out) const { out << name() << " ()"; } }; - /// Holdout closure /// /// This will be used by the shader to mark the @@ -75,26 +68,29 @@ public: HoldoutClosure () : ClosurePrimitive(Holdout) {} void setup() {}; - size_t memsize() const { return sizeof(*this); } - const char *name() const { return "holdout"; } - - void print_on(std::ostream &out) const { - out << name() << " ()"; - } + void print_on(std::ostream &out) const { out << name() << " ()"; } }; -ClosureParam closure_background_params[] = { - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(GenericBackgroundClosure) -}; +ClosureParam *closure_background_params() +{ + static ClosureParam params[] = { + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(GenericBackgroundClosure) + }; + return params; +} CLOSURE_PREPARE(closure_background_prepare, GenericBackgroundClosure) -ClosureParam closure_holdout_params[] = { - CLOSURE_FINISH_PARAM(HoldoutClosure) -}; +ClosureParam *closure_holdout_params() +{ + static ClosureParam params[] = { + CLOSURE_FINISH_PARAM(HoldoutClosure) + }; + return params; +} CLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure) diff --git a/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp b/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp deleted file mode 100644 index cb6be6959f5..00000000000 --- a/intern/cycles/kernel/osl/bsdf_ashikhmin_velvet.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* - * 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 - -#include - -#include "osl_closures.h" - -#include "util_math.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -class AshikhminVelvetClosure : public BSDFClosure { -public: - Vec3 m_N; - float m_sigma; - float m_invsigma2; - - AshikhminVelvetClosure() : BSDFClosure(Labels::DIFFUSE) {} - - void setup() - { - m_sigma = max(m_sigma, 0.01f); - m_invsigma2 = 1.0f / (m_sigma * m_sigma); - } - - bool mergeable(const ClosurePrimitive *other) const { - const AshikhminVelvetClosure *comp = (const AshikhminVelvetClosure *)other; - return m_N == comp->m_N && m_sigma == comp->m_sigma && - BSDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "ashikhmin_velvet"; } - - void print_on(std::ostream &out) const - { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_sigma; - out << ")"; - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO > 0 && cosNI > 0) { - Vec3 H = omega_in + omega_out; - H.normalize(); - - float cosNH = m_N.dot(H); - float cosHO = fabsf(omega_out.dot(H)); - - float cosNHdivHO = cosNH / cosHO; - cosNHdivHO = max(cosNHdivHO, 0.00001f); - - float fac1 = 2 * fabsf(cosNHdivHO * cosNO); - float fac2 = 2 * fabsf(cosNHdivHO * cosNI); - - float sinNH2 = 1 - cosNH * cosNH; - float sinNH4 = sinNH2 * sinNH2; - float cotangent2 = (cosNH * cosNH) / sinNH2; - - float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4; - float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically - - float out = 0.25f * (D * G) / cosNO; - - pdf = 0.5f * (float) M_1_PI; - return Color3(out, out, out); - } - return Color3(0, 0, 0); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // we are viewing the surface from above - send a ray out with uniform - // distribution over the hemisphere - sample_uniform_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf); - if (Ng.dot(omega_in) > 0) { - Vec3 H = omega_in + omega_out; - H.normalize(); - - float cosNI = m_N.dot(omega_in); - float cosNO = m_N.dot(omega_out); - float cosNH = m_N.dot(H); - float cosHO = fabsf(omega_out.dot(H)); - - float cosNHdivHO = cosNH / cosHO; - cosNHdivHO = max(cosNHdivHO, 0.00001f); - - float fac1 = 2 * fabsf(cosNHdivHO * cosNO); - float fac2 = 2 * fabsf(cosNHdivHO * cosNI); - - float sinNH2 = 1 - cosNH * cosNH; - float sinNH4 = sinNH2 * sinNH2; - float cotangent2 = (cosNH * cosNH) / sinNH2; - - float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * float(M_1_PI) / sinNH4; - float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically - - float power = 0.25f * (D * G) / cosNO; - - eval.setValue(power, power, power); - - // TODO: find a better approximation for the retroreflective bounce - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - domega_in_dx *= 125; - domega_in_dy *= 125; - } - else - pdf = 0; - return Labels::REFLECT; - } - -}; - - - -ClosureParam bsdf_ashikhmin_velvet_params[] = { - CLOSURE_VECTOR_PARAM(AshikhminVelvetClosure, m_N), - CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, m_sigma), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(AshikhminVelvetClosure) -}; - -CLOSURE_PREPARE(bsdf_ashikhmin_velvet_prepare, AshikhminVelvetClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/bsdf_diffuse.cpp b/intern/cycles/kernel/osl/bsdf_diffuse.cpp deleted file mode 100644 index 582ac01d959..00000000000 --- a/intern/cycles/kernel/osl/bsdf_diffuse.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* - * 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 - -#include - -#include "osl_closures.h" - -#include "util_math.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -class DiffuseClosure : public BSDFClosure { -public: - Vec3 m_N; - - DiffuseClosure() : BSDFClosure(Labels::DIFFUSE) {} - - void setup() {}; - - bool mergeable(const ClosurePrimitive *other) const { - const DiffuseClosure *comp = (const DiffuseClosure *)other; - return m_N == comp->m_N && BSDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "diffuse"; } - - void print_on(std::ostream &out) const - { - out << name() << " ((" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))"; - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - float cos_pi = max(m_N.dot(omega_in), 0.0f) * (float) M_1_PI; - pdf = cos_pi; - return Color3(cos_pi, cos_pi, cos_pi); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // we are viewing the surface from the right side - send a ray out with cosine - // distribution over the hemisphere - sample_cos_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf); - if (Ng.dot(omega_in) > 0) { - eval.setValue(pdf, pdf, pdf); - // TODO: find a better approximation for the diffuse bounce - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - domega_in_dx *= 125; - domega_in_dy *= 125; - } - else - pdf = 0; - return Labels::REFLECT; - } -}; - - - -class TranslucentClosure : public BSDFClosure { -public: - Vec3 m_N; - - TranslucentClosure() : BSDFClosure(Labels::DIFFUSE, Back) {} - - void setup() {}; - - bool mergeable(const ClosurePrimitive *other) const { - const TranslucentClosure *comp = (const TranslucentClosure *)other; - return m_N == comp->m_N && BSDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "translucent"; } - - void print_on(std::ostream &out) const - { - out << name() << " ((" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))"; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - float cos_pi = max(-m_N.dot(omega_in), 0.0f) * (float) M_1_PI; - pdf = cos_pi; - return Color3(cos_pi, cos_pi, cos_pi); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // we are viewing the surface from the right side - send a ray out with cosine - // distribution over the hemisphere - sample_cos_hemisphere(-m_N, omega_out, randu, randv, omega_in, pdf); - if (Ng.dot(omega_in) < 0) { - eval.setValue(pdf, pdf, pdf); - // TODO: find a better approximation for the diffuse bounce - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - domega_in_dx *= -125; - domega_in_dy *= -125; - } - else - pdf = 0; - return Labels::TRANSMIT; - } -}; - -ClosureParam bsdf_diffuse_params[] = { - CLOSURE_VECTOR_PARAM(DiffuseClosure, m_N), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(DiffuseClosure) -}; - -ClosureParam bsdf_translucent_params[] = { - CLOSURE_VECTOR_PARAM(TranslucentClosure, m_N), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(TranslucentClosure) -}; - -CLOSURE_PREPARE(bsdf_diffuse_prepare, DiffuseClosure) -CLOSURE_PREPARE(bsdf_translucent_prepare, TranslucentClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/bsdf_microfacet.cpp b/intern/cycles/kernel/osl/bsdf_microfacet.cpp deleted file mode 100644 index 09730d8c3e1..00000000000 --- a/intern/cycles/kernel/osl/bsdf_microfacet.cpp +++ /dev/null @@ -1,542 +0,0 @@ -/* - * 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 - -#include - -#include "osl_closures.h" - -#include "util_math.h" - -using namespace OSL; - -CCL_NAMESPACE_BEGIN - -// TODO: fresnel_dielectric is only used for derivatives, could be optimized - -// TODO: refactor these two classes so they share everything by the microfacet -// distribution terms - -// microfacet model with GGX facet distribution -// see http://www.graphics.cornell.edu/~bjw/microfacetbsdf.pdf -template -class MicrofacetGGXClosure : public BSDFClosure { -public: - Vec3 m_N; - float m_ag; // width parameter (roughness) - float m_eta; // index of refraction (for fresnel term) - MicrofacetGGXClosure() : BSDFClosure(Labels::GLOSSY, Refractive ? Back : Front) { m_eta = 1.0f; } - - void setup() - { - m_ag = clamp(m_ag, 1e-5f, 1.0f); - } - - bool mergeable(const ClosurePrimitive *other) const { - const MicrofacetGGXClosure *comp = (const MicrofacetGGXClosure *)other; - return m_N == comp->m_N && m_ag == comp->m_ag && - m_eta == comp->m_eta && BSDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { - return Refractive ? "microfacet_ggx_refraction" : "microfacet_ggx"; - } - - void print_on(std::ostream &out) const { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_ag << ", "; - out << m_eta; - out << ")"; - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - if (Refractive == 1) return Color3(0, 0, 0); - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNI > 0 && cosNO > 0) { - // get half vector - Vec3 Hr = omega_in + omega_out; - Hr.normalize(); - // eq. 20: (F*G*D)/(4*in*on) - // eq. 33: first we calculate D(m) with m=Hr: - float alpha2 = m_ag * m_ag; - float cosThetaM = m_N.dot(Hr); - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = alpha2 / ((float) M_PI * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); - // eq. 34: now calculate G1(i,m) and G1(o,m) - float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); - float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); - float G = G1o * G1i; - float out = (G * D) * 0.25f / cosNO; - // eq. 24 - float pm = D * cosThetaM; - // convert into pdf of the sampled direction - // eq. 38 - but see also: - // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf - pdf = pm * 0.25f / Hr.dot(omega_out); - return Color3(out, out, out); - } - return Color3(0, 0, 0); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - if (Refractive == 0) return Color3(0, 0, 0); - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO <= 0 || cosNI >= 0) - return Color3(0, 0, 0); // vectors on same side -- not possible - // compute half-vector of the refraction (eq. 16) - Vec3 ht = -(m_eta * omega_in + omega_out); - Vec3 Ht = ht; Ht.normalize(); - float cosHO = Ht.dot(omega_out); - - float cosHI = Ht.dot(omega_in); - // eq. 33: first we calculate D(m) with m=Ht: - float alpha2 = m_ag * m_ag; - float cosThetaM = m_N.dot(Ht); - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = alpha2 / ((float) M_PI * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); - // eq. 34: now calculate G1(i,m) and G1(o,m) - float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); - float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); - float G = G1o * G1i; - // probability - float invHt2 = 1 / ht.dot(ht); - pdf = D * fabsf(cosThetaM) * (fabsf(cosHI) * (m_eta * m_eta)) * invHt2; - float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D) * invHt2) / cosNO; - return Color3(out, out, out); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - Vec3 X, Y, Z = m_N; - make_orthonormals(Z, X, Y); - // generate a random microfacet normal m - // eq. 35,36: - // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2) - // and sin(atan(x)) == x/sqrt(1+x^2) - float alpha2 = m_ag * m_ag; - float tanThetaM2 = alpha2 * randu / (1 - randu); - float cosThetaM = 1 / sqrtf(1 + tanThetaM2); - float sinThetaM = cosThetaM * sqrtf(tanThetaM2); - float phiM = 2 * float(M_PI) * randv; - Vec3 m = (cosf(phiM) * sinThetaM) * X + - (sinf(phiM) * sinThetaM) * Y + - cosThetaM * Z; - if (Refractive == 0) { - float cosMO = m.dot(omega_out); - if (cosMO > 0) { - // eq. 39 - compute actual reflected direction - omega_in = 2 * cosMO * m - omega_out; - if (Ng.dot(omega_in) > 0) { - // microfacet normal is visible to this ray - // eq. 33 - float cosThetaM2 = cosThetaM * cosThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = alpha2 / (float(M_PI) * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); - // eq. 24 - float pm = D * cosThetaM; - // convert into pdf of the sampled direction - // eq. 38 - but see also: - // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf - pdf = pm * 0.25f / cosMO; - // eval BRDF*cosNI - float cosNI = m_N.dot(omega_in); - // eq. 34: now calculate G1(i,m) and G1(o,m) - float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); - float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); - float G = G1o * G1i; - // eq. 20: (F*G*D)/(4*in*on) - float out = (G * D) * 0.25f / cosNO; - eval.setValue(out, out, out); - domega_in_dx = (2 * m.dot(domega_out_dx)) * m - domega_out_dx; - domega_in_dy = (2 * m.dot(domega_out_dy)) * m - domega_out_dy; - - /* disabled for now - gives texture filtering problems */ -#if 0 - // Since there is some blur to this reflection, make the - // derivatives a bit bigger. In theory this varies with the - // roughness but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; -#endif - } - } - } - else { - // CAUTION: the i and o variables are inverted relative to the paper - // eq. 39 - compute actual refractive direction - Vec3 R, dRdx, dRdy; - Vec3 T, dTdx, dTdy; - bool inside; - fresnel_dielectric(m_eta, m, omega_out, domega_out_dx, domega_out_dy, - R, dRdx, dRdy, - T, dTdx, dTdy, - inside); - - if (!inside) { - omega_in = T; - domega_in_dx = dTdx; - domega_in_dy = dTdy; - // eq. 33 - float cosThetaM2 = cosThetaM * cosThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = alpha2 / (float(M_PI) * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2)); - // eq. 24 - float pm = D * cosThetaM; - // eval BRDF*cosNI - float cosNI = m_N.dot(omega_in); - // eq. 34: now calculate G1(i,m) and G1(o,m) - float G1o = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO))); - float G1i = 2 / (1 + sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); - float G = G1o * G1i; - // eq. 21 - float cosHI = m.dot(omega_in); - float cosHO = m.dot(omega_out); - float Ht2 = m_eta * cosHI + cosHO; - Ht2 *= Ht2; - float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2); - // eq. 38 and eq. 17 - pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2; - eval.setValue(out, out, out); - - /* disabled for now - gives texture filtering problems */ -#if 0 - // Since there is some blur to this refraction, make the - // derivatives a bit bigger. In theory this varies with the - // roughness but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; -#endif - } - } - } - return Refractive ? Labels::TRANSMIT : Labels::REFLECT; - } -}; - -// microfacet model with Beckmann facet distribution -// see http://www.graphics.cornell.edu/~bjw/microfacetbsdf.pdf -template -class MicrofacetBeckmannClosure : public BSDFClosure { -public: - Vec3 m_N; - float m_ab; // width parameter (roughness) - float m_eta; // index of refraction (for fresnel term) - MicrofacetBeckmannClosure() : BSDFClosure(Labels::GLOSSY, Refractive ? Back : Front) { - } - - void setup() - { - m_ab = clamp(m_ab, 1e-5f, 1.0f); - } - - bool mergeable(const ClosurePrimitive *other) const { - const MicrofacetBeckmannClosure *comp = (const MicrofacetBeckmannClosure *)other; - return m_N == comp->m_N && m_ab == comp->m_ab && - m_eta == comp->m_eta && BSDFClosure::mergeable(other); - } - - size_t memsize() const { - return sizeof(*this); - } - - const char *name() const { - return Refractive ? "microfacet_beckmann_refraction" - : "microfacet_beckmann"; - } - - void print_on(std::ostream &out) const - { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_ab << ", "; - out << m_eta; - out << ")"; - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - if (Refractive == 1) return Color3(0, 0, 0); - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO > 0 && cosNI > 0) { - // get half vector - Vec3 Hr = omega_in + omega_out; - Hr.normalize(); - // eq. 20: (F*G*D)/(4*in*on) - // eq. 25: first we calculate D(m) with m=Hr: - float alpha2 = m_ab * m_ab; - float cosThetaM = m_N.dot(Hr); - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4); - // eq. 26, 27: now calculate G1(i,m) and G1(o,m) - float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); - float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); - float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; - float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; - float G = G1o * G1i; - float out = (G * D) * 0.25f / cosNO; - // eq. 24 - float pm = D * cosThetaM; - // convert into pdf of the sampled direction - // eq. 38 - but see also: - // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf - pdf = pm * 0.25f / Hr.dot(omega_out); - return Color3(out, out, out); - } - return Color3(0, 0, 0); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - if (Refractive == 0) return Color3(0, 0, 0); - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO <= 0 || cosNI >= 0) - return Color3(0, 0, 0); - // compute half-vector of the refraction (eq. 16) - Vec3 ht = -(m_eta * omega_in + omega_out); - Vec3 Ht = ht; Ht.normalize(); - float cosHO = Ht.dot(omega_out); - - float cosHI = Ht.dot(omega_in); - // eq. 33: first we calculate D(m) with m=Ht: - float alpha2 = m_ab * m_ab; - float cosThetaM = m_N.dot(Ht); - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4); - // eq. 26, 27: now calculate G1(i,m) and G1(o,m) - float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); - float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); - float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; - float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; - float G = G1o * G1i; - // probability - float invHt2 = 1 / ht.dot(ht); - pdf = D * fabsf(cosThetaM) * (fabsf(cosHI) * (m_eta * m_eta)) * invHt2; - float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D) * invHt2) / cosNO; - return Color3(out, out, out); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - Vec3 X, Y, Z = m_N; - make_orthonormals(Z, X, Y); - // generate a random microfacet normal m - // eq. 35,36: - // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2) - // and sin(atan(x)) == x/sqrt(1+x^2) - float alpha2 = m_ab * m_ab; - float tanThetaM = sqrtf(-alpha2 * logf(1 - randu)); - float cosThetaM = 1 / sqrtf(1 + tanThetaM * tanThetaM); - float sinThetaM = cosThetaM * tanThetaM; - float phiM = 2 * float(M_PI) * randv; - Vec3 m = (cosf(phiM) * sinThetaM) * X + - (sinf(phiM) * sinThetaM) * Y + - cosThetaM * Z; - if (Refractive == 0) { - float cosMO = m.dot(omega_out); - if (cosMO > 0) { - // eq. 39 - compute actual reflected direction - omega_in = 2 * cosMO * m - omega_out; - if (Ng.dot(omega_in) > 0) { - // microfacet normal is visible to this ray - // eq. 25 - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = tanThetaM * tanThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4); - // eq. 24 - float pm = D * cosThetaM; - // convert into pdf of the sampled direction - // eq. 38 - but see also: - // eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf - pdf = pm * 0.25f / cosMO; - // Eval BRDF*cosNI - float cosNI = m_N.dot(omega_in); - // eq. 26, 27: now calculate G1(i,m) and G1(o,m) - float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); - float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); - float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; - float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; - float G = G1o * G1i; - // eq. 20: (F*G*D)/(4*in*on) - float out = (G * D) * 0.25f / cosNO; - eval.setValue(out, out, out); - domega_in_dx = (2 * m.dot(domega_out_dx)) * m - domega_out_dx; - domega_in_dy = (2 * m.dot(domega_out_dy)) * m - domega_out_dy; - - /* disabled for now - gives texture filtering problems */ -#if 0 - // Since there is some blur to this reflection, make the - // derivatives a bit bigger. In theory this varies with the - // roughness but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; -#endif - } - } - } - else { - // CAUTION: the i and o variables are inverted relative to the paper - // eq. 39 - compute actual refractive direction - Vec3 R, dRdx, dRdy; - Vec3 T, dTdx, dTdy; - bool inside; - fresnel_dielectric(m_eta, m, omega_out, domega_out_dx, domega_out_dy, - R, dRdx, dRdy, - T, dTdx, dTdy, - inside); - if (!inside) { - omega_in = T; - domega_in_dx = dTdx; - domega_in_dy = dTdy; - // eq. 33 - float cosThetaM2 = cosThetaM * cosThetaM; - float tanThetaM2 = tanThetaM * tanThetaM; - float cosThetaM4 = cosThetaM2 * cosThetaM2; - float D = expf(-tanThetaM2 / alpha2) / (float(M_PI) * alpha2 * cosThetaM4); - // eq. 24 - float pm = D * cosThetaM; - // eval BRDF*cosNI - float cosNI = m_N.dot(omega_in); - // eq. 26, 27: now calculate G1(i,m) and G1(o,m) - float ao = 1 / (m_ab * sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); - float ai = 1 / (m_ab * sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); - float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; - float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; - float G = G1o * G1i; - // eq. 21 - float cosHI = m.dot(omega_in); - float cosHO = m.dot(omega_out); - float Ht2 = m_eta * cosHI + cosHO; - Ht2 *= Ht2; - float out = (fabsf(cosHI * cosHO) * (m_eta * m_eta) * (G * D)) / (cosNO * Ht2); - // eq. 38 and eq. 17 - pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2; - eval.setValue(out, out, out); - - /* disabled for now - gives texture filtering problems */ -#if 0 - // Since there is some blur to this refraction, make the - // derivatives a bit bigger. In theory this varies with the - // roughness but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; -#endif - } - } - } - return Refractive ? Labels::TRANSMIT : Labels::REFLECT; - } -}; - - - -ClosureParam bsdf_microfacet_ggx_params[] = { - CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure<0>, m_N), - CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure<0>, m_ag), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(MicrofacetGGXClosure<0>) -}; - -ClosureParam bsdf_microfacet_ggx_refraction_params[] = { - CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure<1>, m_N), - CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure<1>, m_ag), - CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure<1>, m_eta), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(MicrofacetGGXClosure<1>) -}; - -ClosureParam bsdf_microfacet_beckmann_params[] = { - CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure<0>, m_N), - CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure<0>, m_ab), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(MicrofacetBeckmannClosure<0>) -}; - -ClosureParam bsdf_microfacet_beckmann_refraction_params[] = { - CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure<1>, m_N), - CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure<1>, m_ab), - CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure<1>, m_eta), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(MicrofacetBeckmannClosure<1>) -}; - -CLOSURE_PREPARE(bsdf_microfacet_ggx_prepare, MicrofacetGGXClosure<0>) -CLOSURE_PREPARE(bsdf_microfacet_ggx_refraction_prepare, MicrofacetGGXClosure<1>) -CLOSURE_PREPARE(bsdf_microfacet_beckmann_prepare, MicrofacetBeckmannClosure<0>) -CLOSURE_PREPARE(bsdf_microfacet_beckmann_refraction_prepare, MicrofacetBeckmannClosure<1>) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/bsdf_oren_nayar.cpp b/intern/cycles/kernel/osl/bsdf_oren_nayar.cpp deleted file mode 100644 index 83d0e583695..00000000000 --- a/intern/cycles/kernel/osl/bsdf_oren_nayar.cpp +++ /dev/null @@ -1,138 +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 -#include -#include "osl_closures.h" -#include "util_math.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - - -class OrenNayarClosure : public BSDFClosure { -public: - Vec3 m_N; - float m_sigma; - float m_a, m_b; - - OrenNayarClosure() : BSDFClosure(Labels::DIFFUSE) {} - - void setup() { - m_sigma = clamp(m_sigma, 0.0f, 1.0f); - - float div = 1.0f / (M_PI + ((3.0f * M_PI - 4.0f) / 6.0f) * m_sigma); - - m_a = 1.0f * div; - m_b = m_sigma * div; - } - - bool mergeable(const ClosurePrimitive *other) const { - const OrenNayarClosure *comp = static_cast(other); - return - m_N == comp->m_N && - m_sigma == comp->m_sigma && - BSDFClosure::mergeable(other); - } - - size_t memsize() const { - return sizeof(*this); - } - - const char *name() const { - return "oren_nayar"; - } - - void print_on(std::ostream& out) const { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_sigma; - out << ")"; - } - - float albedo(const Vec3& omega_out) const { - return 1.0f; - } - - Color3 eval_reflect(const Vec3& omega_out, const Vec3& omega_in, float& pdf) const { - if (m_N.dot(omega_in) > 0.0f) { - pdf = float(0.5 * M_1_PI); - float is = get_intensity(m_N, omega_out, omega_in); - return Color3(is, is, is); - } - else { - pdf = 0.0f; - return Color3(0.0f, 0.0f, 0.0f); - } - } - - Color3 eval_transmit(const Vec3& omega_out, const Vec3& omega_in, float& pdf) const { - return Color3(0.0f, 0.0f, 0.0f); - } - - ustring sample( - const Vec3& Ng, - const Vec3& omega_out, const Vec3& domega_out_dx, const Vec3& domega_out_dy, - float randu, float randv, - Vec3& omega_in, Vec3& domega_in_dx, Vec3& domega_in_dy, - float& pdf, Color3& eval - ) const { - sample_uniform_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf); - - if (Ng.dot(omega_in) > 0.0f) { - float is = get_intensity(m_N, omega_out, omega_in); - eval.setValue(is, is, is); - - // TODO: find a better approximation for the bounce - domega_in_dx = (2.0f * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2.0f * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - domega_in_dx *= 125.0f; - domega_in_dy *= 125.0f; - } - else { - pdf = 0.0f; - } - - return Labels::REFLECT; - } - -private: - float get_intensity(Vec3 const& n, Vec3 const& v, Vec3 const& l) const { - float nl = max(n.dot(l), 0.0f); - float nv = max(n.dot(v), 0.0f); - float t = l.dot(v) - nl * nv; - - if (t > 0.0f) { - t /= max(nl, nv) + 1e-8f; - } - return nl * (m_a + m_b * t); - } -}; - -ClosureParam bsdf_oren_nayar_params[] = { - CLOSURE_VECTOR_PARAM(OrenNayarClosure, m_N), - CLOSURE_FLOAT_PARAM(OrenNayarClosure, m_sigma), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(OrenNayarClosure) -}; - -CLOSURE_PREPARE(bsdf_oren_nayar_prepare, OrenNayarClosure) - - -CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/bsdf_phong.cpp b/intern/cycles/kernel/osl/bsdf_phong.cpp deleted file mode 100644 index 57745079d33..00000000000 --- a/intern/cycles/kernel/osl/bsdf_phong.cpp +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Adapted from Open Shading Language with this license: - * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2012, 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 - -#include -#include "osl_closures.h" -#include "util_math.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -// vanilla phong - leaks energy at grazing angles -// see Global Illumination Compendium entry (66) -class PhongClosure : public BSDFClosure { -public: - Vec3 m_N; - float m_exponent; - PhongClosure() : BSDFClosure(Labels::GLOSSY) { } - - void setup() {}; - - bool mergeable (const ClosurePrimitive *other) const { - const PhongClosure *comp = (const PhongClosure *)other; - return m_N == comp->m_N && m_exponent == comp->m_exponent && - BSDFClosure::mergeable(other); - } - - size_t memsize () const { return sizeof(*this); } - - const char *name () const { return "phong"; } - - void print_on (std::ostream &out) const { - out << name() << " (("; - out << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_exponent << ")"; - } - - float albedo (const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - float cosNI = m_N.dot(omega_in); - float cosNO = m_N.dot(omega_out); - if (cosNI > 0 && cosNO > 0) { - // reflect the view vector - Vec3 R = (2 * cosNO) * m_N - omega_out; - float cosRI = R.dot(omega_in); - if (cosRI > 0) { - float common = 0.5f * (float) M_1_PI * powf(cosRI, m_exponent); - float out = cosNI * (m_exponent + 2) * common; - pdf = (m_exponent + 1) * common; - return Color3 (out, out, out); - } - } - return Color3 (0, 0, 0); - } - - Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3 (0, 0, 0); - } - - ustring sample (const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - // reflect the view vector - Vec3 R = (2 * cosNO) * m_N - omega_out; - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - Vec3 T, B; - make_orthonormals (R, T, B); - float phi = 2 * (float) M_PI * randu; - float cosTheta = powf(randv, 1 / (m_exponent + 1)); - float sinTheta2 = 1 - cosTheta * cosTheta; - float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; - omega_in = (cosf(phi) * sinTheta) * T + - (sinf(phi) * sinTheta) * B + - ( cosTheta) * R; - if (Ng.dot(omega_in) > 0) - { - // common terms for pdf and eval - float cosNI = m_N.dot(omega_in); - // make sure the direction we chose is still in the right hemisphere - if (cosNI > 0) - { - float common = 0.5f * (float) M_1_PI * powf(cosTheta, m_exponent); - pdf = (m_exponent + 1) * common; - float out = cosNI * (m_exponent + 2) * common; - eval.setValue(out, out, out); - // Since there is some blur to this reflection, make the - // derivatives a bit bigger. In theory this varies with the - // exponent but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; - } - } - } - return Labels::REFLECT; - } -}; - - -class PhongRampClosure : public BSDFClosure { -public: - static const int MAXCOLORS = 8; - Vec3 m_N; - float m_exponent; - Color3 m_colors[MAXCOLORS]; - PhongRampClosure() : BSDFClosure(Labels::GLOSSY) { } - - void setup() {}; - - bool mergeable (const ClosurePrimitive *other) const { - const PhongRampClosure *comp = (const PhongRampClosure *)other; - if (! (m_N == comp->m_N && m_exponent == comp->m_exponent && - BSDFClosure::mergeable(other))) - return false; - for (int i = 0; i < MAXCOLORS; ++i) - if (m_colors[i] != comp->m_colors[i]) - return false; - return true; - } - - size_t memsize () const { return sizeof(*this); } - - const char *name () const { return "phong_ramp"; } - - void print_on (std::ostream &out) const { - out << name() << " (("; - out << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_exponent << ")"; - } - - Color3 get_color (float pos) const - { - float npos = pos * (float)(MAXCOLORS - 1); - int ipos = (int)npos; - if (ipos >= (MAXCOLORS - 1)) - return m_colors[MAXCOLORS - 1]; - float offset = npos - (float)ipos; - return m_colors[ipos] * (1.0f - offset) + m_colors[ipos+1] * offset; - } - - float albedo (const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - float cosNI = m_N.dot(omega_in); - float cosNO = m_N.dot(omega_out); - if (cosNI > 0 && cosNO > 0) { - // reflect the view vector - Vec3 R = (2 * cosNO) * m_N - omega_out; - float cosRI = R.dot(omega_in); - if (cosRI > 0) { - float cosp = powf(cosRI, m_exponent); - float common = 0.5f * (float) M_1_PI * cosp; - float out = cosNI * (m_exponent + 2) * common; - pdf = (m_exponent + 1) * common; - return get_color(cosp) * out; - } - } - return Color3 (0, 0, 0); - } - - Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3 (0, 0, 0); - } - - ustring sample (const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - // reflect the view vector - Vec3 R = (2 * cosNO) * m_N - omega_out; - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - Vec3 T, B; - make_orthonormals (R, T, B); - float phi = 2 * (float) M_PI * randu; - float cosTheta = powf(randv, 1 / (m_exponent + 1)); - float sinTheta2 = 1 - cosTheta * cosTheta; - float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; - omega_in = (cosf(phi) * sinTheta) * T + - (sinf(phi) * sinTheta) * B + - ( cosTheta) * R; - if (Ng.dot(omega_in) > 0) - { - // common terms for pdf and eval - float cosNI = m_N.dot(omega_in); - // make sure the direction we chose is still in the right hemisphere - if (cosNI > 0) - { - float cosp = powf(cosTheta, m_exponent); - float common = 0.5f * (float) M_1_PI * cosp; - pdf = (m_exponent + 1) * common; - float out = cosNI * (m_exponent + 2) * common; - eval = get_color(cosp) * out; - // Since there is some blur to this reflection, make the - // derivatives a bit bigger. In theory this varies with the - // exponent but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; - } - } - } - return Labels::REFLECT; - } -}; - - - -ClosureParam bsdf_phong_params[] = { - CLOSURE_VECTOR_PARAM(PhongClosure, m_N), - CLOSURE_FLOAT_PARAM (PhongClosure, m_exponent), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(PhongClosure) }; - -ClosureParam bsdf_phong_ramp_params[] = { - CLOSURE_VECTOR_PARAM (PhongRampClosure, m_N), - CLOSURE_FLOAT_PARAM (PhongRampClosure, m_exponent), - CLOSURE_COLOR_ARRAY_PARAM(PhongRampClosure, m_colors, PhongRampClosure::MAXCOLORS), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM (PhongRampClosure) }; - -CLOSURE_PREPARE(bsdf_phong_prepare, PhongClosure) -CLOSURE_PREPARE(bsdf_phong_ramp_prepare, PhongRampClosure) - -CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/bsdf_reflection.cpp b/intern/cycles/kernel/osl/bsdf_reflection.cpp deleted file mode 100644 index 7041b4ced6f..00000000000 --- a/intern/cycles/kernel/osl/bsdf_reflection.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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 - -#include - -#include "osl_closures.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -class ReflectionClosure : public BSDFClosure { -public: - Vec3 m_N; // shading normal - ReflectionClosure() : BSDFClosure(Labels::SINGULAR) {} - - void setup() {}; - - bool mergeable(const ClosurePrimitive *other) const { - const ReflectionClosure *comp = (const ReflectionClosure *)other; - return m_N == comp->m_N && BSDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "reflection"; } - - void print_on(std::ostream &out) const { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "))"; - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // only one direction is possible - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - omega_in = (2 * cosNO) * m_N - omega_out; - if (Ng.dot(omega_in) > 0) { - domega_in_dx = 2 * m_N.dot(domega_out_dx) * m_N - domega_out_dx; - domega_in_dy = 2 * m_N.dot(domega_out_dy) * m_N - domega_out_dy; - pdf = 1; - eval.setValue(1, 1, 1); - } - } - return Labels::REFLECT; - } -}; - -ClosureParam bsdf_reflection_params[] = { - CLOSURE_VECTOR_PARAM(ReflectionClosure, m_N), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(ReflectionClosure) -}; - -CLOSURE_PREPARE(bsdf_reflection_prepare, ReflectionClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/bsdf_refraction.cpp b/intern/cycles/kernel/osl/bsdf_refraction.cpp deleted file mode 100644 index f56ad7b127c..00000000000 --- a/intern/cycles/kernel/osl/bsdf_refraction.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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 - -#include - -#include "osl_closures.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -class RefractionClosure : public BSDFClosure { -public: - Vec3 m_N; // shading normal - float m_eta; // ratio of indices of refraction (inside / outside) - RefractionClosure() : BSDFClosure(Labels::SINGULAR, Back) {} - - void setup() {} - - bool mergeable(const ClosurePrimitive *other) const { - const RefractionClosure *comp = (const RefractionClosure *)other; - return m_N == comp->m_N && m_eta == comp->m_eta && - BSDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "refraction"; } - - void print_on(std::ostream &out) const { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_eta; - out << ")"; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - Vec3 R, dRdx, dRdy; - Vec3 T, dTdx, dTdy; - bool inside; - - fresnel_dielectric(m_eta, m_N, - omega_out, domega_out_dx, domega_out_dy, - R, dRdx, dRdy, - T, dTdx, dTdy, - inside); - - if (!inside) { - pdf = 1; - eval.setValue(1.0f, 1.0f, 1.0f); - omega_in = T; - domega_in_dx = dTdx; - domega_in_dy = dTdy; - } - - return Labels::TRANSMIT; - } -}; - -ClosureParam bsdf_refraction_params[] = { - CLOSURE_VECTOR_PARAM(RefractionClosure, m_N), - CLOSURE_FLOAT_PARAM(RefractionClosure, m_eta), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(RefractionClosure) -}; - -CLOSURE_PREPARE(bsdf_refraction_prepare, RefractionClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/bsdf_transparent.cpp b/intern/cycles/kernel/osl/bsdf_transparent.cpp deleted file mode 100644 index acde92530a2..00000000000 --- a/intern/cycles/kernel/osl/bsdf_transparent.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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 - -#include - -#include "osl_closures.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -class TransparentClosure : public BSDFClosure { -public: - TransparentClosure() : BSDFClosure(Labels::STRAIGHT, Back) {} - - void setup() {} - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "transparent"; } - - void print_on(std::ostream &out) const { - out << name() << " ()"; - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // only one direction is possible - omega_in = -omega_out; - domega_in_dx = -domega_out_dx; - domega_in_dy = -domega_out_dy; - pdf = 1; - eval.setValue(1, 1, 1); - return Labels::TRANSMIT; - } -}; - - - -ClosureParam bsdf_transparent_params[] = { - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(TransparentClosure) -}; - -CLOSURE_PREPARE(bsdf_transparent_prepare, TransparentClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/bsdf_ward.cpp b/intern/cycles/kernel/osl/bsdf_ward.cpp deleted file mode 100644 index 4aacbc4ffc3..00000000000 --- a/intern/cycles/kernel/osl/bsdf_ward.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/* - * 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 - -#include - -#include "osl_closures.h" - -#include "util_math.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -// anisotropic ward - leaks energy at grazing angles -// see http://www.graphics.cornell.edu/~bjw/wardnotes.pdf -class WardClosure : public BSDFClosure { -public: - Vec3 m_N; - Vec3 m_T; - float m_ax, m_ay; - WardClosure() : BSDFClosure(Labels::GLOSSY) {} - - void setup() - { - m_ax = clamp(m_ax, 1e-5f, 1.0f); - m_ay = clamp(m_ay, 1e-5f, 1.0f); - } - - bool mergeable(const ClosurePrimitive *other) const { - const WardClosure *comp = (const WardClosure *)other; - return m_N == comp->m_N && m_T == comp->m_T && - m_ax == comp->m_ax && m_ay == comp->m_ay && - BSDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "ward"; } - - void print_on(std::ostream &out) const { - out << name() << " (("; - out << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ("; - out << m_T[0] << ", " << m_T[1] << ", " << m_T[2] << "), "; - out << m_ax << ", " << m_ay << ")"; - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNI > 0 && cosNO > 0) { - // get half vector and get x,y basis on the surface for anisotropy - Vec3 H = omega_in + omega_out; - H.normalize(); // normalize needed for pdf - Vec3 X, Y; - make_orthonormals(m_N, m_T, X, Y); - // eq. 4 - float dotx = H.dot(X) / m_ax; - float doty = H.dot(Y) / m_ay; - float dotn = H.dot(m_N); - float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn); - float denom = (4 * (float) M_PI * m_ax * m_ay * sqrtf(cosNO * cosNI)); - float exp_val = expf(-exp_arg); - float out = cosNI * exp_val / denom; - float oh = H.dot(omega_out); - denom = 4 * (float) M_PI * m_ax * m_ay * oh * dotn * dotn * dotn; - pdf = exp_val / denom; - return Color3(out, out, out); - } - return Color3(0, 0, 0); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const - { - return Color3(0, 0, 0); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - // get x,y basis on the surface for anisotropy - Vec3 X, Y; - make_orthonormals(m_N, m_T, X, Y); - // generate random angles for the half vector - // eq. 7 (taking care around discontinuities to keep - // output angle in the right quadrant) - // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2) - // and sin(atan(x)) == x/sqrt(1+x^2) - float alphaRatio = m_ay / m_ax; - float cosPhi, sinPhi; - if (randu < 0.25f) { - float val = 4 * randu; - float tanPhi = alphaRatio * tanf((float) M_PI_2 * val); - cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi); - sinPhi = tanPhi * cosPhi; - } - else if (randu < 0.5) { - float val = 1 - 4 * (0.5f - randu); - float tanPhi = alphaRatio * tanf((float) M_PI_2 * val); - // phi = (float) M_PI - phi; - cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi); - sinPhi = -tanPhi * cosPhi; - } - else if (randu < 0.75f) { - float val = 4 * (randu - 0.5f); - float tanPhi = alphaRatio * tanf((float) M_PI_2 * val); - //phi = (float) M_PI + phi; - cosPhi = -1 / sqrtf(1 + tanPhi * tanPhi); - sinPhi = tanPhi * cosPhi; - } - else { - float val = 1 - 4 * (1 - randu); - float tanPhi = alphaRatio * tanf((float) M_PI_2 * val); - // phi = 2 * (float) M_PI - phi; - cosPhi = 1 / sqrtf(1 + tanPhi * tanPhi); - sinPhi = -tanPhi * cosPhi; - } - // eq. 6 - // we take advantage of cos(atan(x)) == 1/sqrt(1+x^2) - // and sin(atan(x)) == x/sqrt(1+x^2) - float thetaDenom = (cosPhi * cosPhi) / (m_ax * m_ax) + (sinPhi * sinPhi) / (m_ay * m_ay); - float tanTheta2 = -logf(1 - randv) / thetaDenom; - float cosTheta = 1 / sqrtf(1 + tanTheta2); - float sinTheta = cosTheta * sqrtf(tanTheta2); - - Vec3 h; // already normalized becaused expressed from spherical coordinates - h.x = sinTheta * cosPhi; - h.y = sinTheta * sinPhi; - h.z = cosTheta; - // compute terms that are easier in local space - float dotx = h.x / m_ax; - float doty = h.y / m_ay; - float dotn = h.z; - // transform to world space - h = h.x * X + h.y * Y + h.z * m_N; - // generate the final sample - float oh = h.dot(omega_out); - omega_in.x = 2 * oh * h.x - omega_out.x; - omega_in.y = 2 * oh * h.y - omega_out.y; - omega_in.z = 2 * oh * h.z - omega_out.z; - if (Ng.dot(omega_in) > 0) { - float cosNI = m_N.dot(omega_in); - if (cosNI > 0) { - // eq. 9 - float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn); - float denom = 4 * (float) M_PI * m_ax * m_ay * oh * dotn * dotn * dotn; - pdf = expf(-exp_arg) / denom; - // compiler will reuse expressions already computed - denom = (4 * (float) M_PI * m_ax * m_ay * sqrtf(cosNO * cosNI)); - float power = cosNI * expf(-exp_arg) / denom; - eval.setValue(power, power, power); - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - - /* disabled for now - gives texture filtering problems */ -#if 0 - // Since there is some blur to this reflection, make the - // derivatives a bit bigger. In theory this varies with the - // roughness but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; -#endif - } - } - } - return Labels::REFLECT; - } -}; - - - -ClosureParam bsdf_ward_params[] = { - CLOSURE_VECTOR_PARAM(WardClosure, m_N), - CLOSURE_VECTOR_PARAM(WardClosure, m_T), - CLOSURE_FLOAT_PARAM(WardClosure, m_ax), - CLOSURE_FLOAT_PARAM(WardClosure, m_ay), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(WardClosure) -}; - -CLOSURE_PREPARE(bsdf_ward_prepare, WardClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/bsdf_westin.cpp b/intern/cycles/kernel/osl/bsdf_westin.cpp deleted file mode 100644 index a476e8045f7..00000000000 --- a/intern/cycles/kernel/osl/bsdf_westin.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * 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 - -#include - -#include "osl_closures.h" - -#include "util_math.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -class WestinBackscatterClosure : public BSDFClosure { -public: - Vec3 m_N; - float m_roughness; - float m_invroughness; - WestinBackscatterClosure() : BSDFClosure(Labels::GLOSSY) {} - - void setup() - { - m_roughness = clamp(m_roughness, 1e-5f, 1.0f); - m_invroughness = m_roughness > 0 ? 1 / m_roughness : 0; - } - - bool mergeable(const ClosurePrimitive *other) const { - const WestinBackscatterClosure *comp = (const WestinBackscatterClosure *)other; - return m_N == comp->m_N && m_roughness == comp->m_roughness && - BSDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "westin_backscatter"; } - - void print_on(std::ostream &out) const - { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_roughness; - out << ")"; - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const - { - // pdf is implicitly 0 (no indirect sampling) - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO > 0 && cosNI > 0) { - float cosine = omega_out.dot(omega_in); - pdf = cosine > 0 ? (m_invroughness + 1) * powf(cosine, m_invroughness) : 0; - pdf *= 0.5f * float(M_1_PI); - return Color3(pdf, pdf, pdf); - } - return Color3(0, 0, 0); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const - { - return Color3(0, 0, 0); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - float cosNO = m_N.dot(omega_out); - if (cosNO > 0) { - domega_in_dx = domega_out_dx; - domega_in_dy = domega_out_dy; - Vec3 T, B; - make_orthonormals(omega_out, T, B); - float phi = 2 * (float) M_PI * randu; - float cosTheta = powf(randv, 1 / (m_invroughness + 1)); - float sinTheta2 = 1 - cosTheta * cosTheta; - float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0; - omega_in = (cosf(phi) * sinTheta) * T + - (sinf(phi) * sinTheta) * B + - (cosTheta) * omega_out; - if (Ng.dot(omega_in) > 0) - { - // common terms for pdf and eval - float cosNI = m_N.dot(omega_in); - // make sure the direction we chose is still in the right hemisphere - if (cosNI > 0) - { - pdf = 0.5f * (float) M_1_PI * powf(cosTheta, m_invroughness); - pdf = (m_invroughness + 1) * pdf; - eval.setValue(pdf, pdf, pdf); - // Since there is some blur to this reflection, make the - // derivatives a bit bigger. In theory this varies with the - // exponent but the exact relationship is complex and - // requires more ops than are practical. - domega_in_dx *= 10; - domega_in_dy *= 10; - } - } - } - return Labels::REFLECT; - } - -}; - - -class WestinSheenClosure : public BSDFClosure { -public: - Vec3 m_N; - float m_edginess; -// float m_normalization; - WestinSheenClosure() : BSDFClosure(Labels::DIFFUSE) {} - - void setup() {}; - - bool mergeable(const ClosurePrimitive *other) const { - const WestinSheenClosure *comp = (const WestinSheenClosure *)other; - return m_N == comp->m_N && m_edginess == comp->m_edginess && - BSDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "westin_sheen"; } - - void print_on(std::ostream &out) const - { - out << name() << " ("; - out << "(" << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), "; - out << m_edginess; - out << ")"; - } - - float albedo(const Vec3 &omega_out) const - { - return 1.0f; - } - - Color3 eval_reflect(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const - { - // pdf is implicitly 0 (no indirect sampling) - float cosNO = m_N.dot(omega_out); - float cosNI = m_N.dot(omega_in); - if (cosNO > 0 && cosNI > 0) { - float sinNO2 = 1 - cosNO * cosNO; - pdf = cosNI * float(M_1_PI); - float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0; - return Color3(westin, westin, westin); - } - return Color3(0, 0, 0); - } - - Color3 eval_transmit(const Vec3 &omega_out, const Vec3 &omega_in, float &pdf) const - { - return Color3(0, 0, 0); - } - - ustring sample(const Vec3 &Ng, - const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy, - float randu, float randv, - Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy, - float &pdf, Color3 &eval) const - { - // we are viewing the surface from the right side - send a ray out with cosine - // distribution over the hemisphere - sample_cos_hemisphere(m_N, omega_out, randu, randv, omega_in, pdf); - if (Ng.dot(omega_in) > 0) { - // TODO: account for sheen when sampling - float cosNO = m_N.dot(omega_out); - float sinNO2 = 1 - cosNO * cosNO; - float westin = sinNO2 > 0 ? powf(sinNO2, 0.5f * m_edginess) * pdf : 0; - eval.setValue(westin, westin, westin); - // TODO: find a better approximation for the diffuse bounce - domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx; - domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy; - domega_in_dx *= 125; - domega_in_dy *= 125; - } - else { - pdf = 0; - } - return Labels::REFLECT; - } -}; - - - -ClosureParam bsdf_westin_backscatter_params[] = { - CLOSURE_VECTOR_PARAM(WestinBackscatterClosure, m_N), - CLOSURE_FLOAT_PARAM(WestinBackscatterClosure, m_roughness), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(WestinBackscatterClosure) -}; - -ClosureParam bsdf_westin_sheen_params[] = { - CLOSURE_VECTOR_PARAM(WestinSheenClosure, m_N), - CLOSURE_FLOAT_PARAM(WestinSheenClosure, m_edginess), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(WestinSheenClosure) -}; - -CLOSURE_PREPARE(bsdf_westin_backscatter_prepare, WestinBackscatterClosure) -CLOSURE_PREPARE(bsdf_westin_sheen_prepare, WestinSheenClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/bssrdf.cpp b/intern/cycles/kernel/osl/bssrdf.cpp deleted file mode 100644 index b195cf513cd..00000000000 --- a/intern/cycles/kernel/osl/bssrdf.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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 - -#include - -#include "osl_closures.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -class BSSRDFCubicClosure : public BSSRDFClosure { -public: - Color3 m_radius; - Color3 m_scale; - float m_max_radius; - - template - static inline T pow3(const T &x) { return x * x * x; } - - template - static inline T pow5(const T &x) { T x2 = x * x; return x2 * x2 * x; } - - BSSRDFCubicClosure() {} - - void setup() - { - // pre-compute some terms - m_max_radius = 0; - for (int i = 0; i < 3; i++) { - m_scale[i] = m_radius[i] > 0 ? 4 / pow5(m_radius[i]) : 0; - m_max_radius = std::max(m_max_radius, m_radius[i]); - } - } - - bool mergeable(const ClosurePrimitive *other) const { - const BSSRDFCubicClosure *comp = (const BSSRDFCubicClosure *)other; - return m_radius == comp->m_radius && BSSRDFClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "bssrdf_cubic"; } - - void print_on(std::ostream &out) const - { - out << name() << " ((" << m_radius[0] << ", " << m_radius[1] << ", " << m_radius[2] << "), (" - << m_scale[0] << ", " << m_scale[1] << ", " << m_scale[2] << "))"; - } - - Color3 eval(float r) const - { - return Color3((r < m_radius.x) ? pow3(m_radius.x - r) * m_scale.x : 0, - (r < m_radius.y) ? pow3(m_radius.y - r) * m_scale.y : 0, - (r < m_radius.z) ? pow3(m_radius.z - r) * m_scale.z : 0); - } - - float max_radius() const - { - return m_max_radius; - } -}; - - - -ClosureParam closure_bssrdf_cubic_params[] = { - CLOSURE_COLOR_PARAM(BSSRDFCubicClosure, m_radius), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(BSSRDFCubicClosure) -}; - -CLOSURE_PREPARE(closure_bssrdf_cubic_prepare, BSSRDFCubicClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/debug.cpp b/intern/cycles/kernel/osl/debug.cpp deleted file mode 100644 index 768a9100e8a..00000000000 --- a/intern/cycles/kernel/osl/debug.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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 - -#include - -#include "osl_closures.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -/// Debug closure -/// -/// This is going to be used for mask AOV's and similar -/// purposes. A tag (string) is always associated with -/// this closure, that "selects: the channel where the -/// weight should be sent. - -class DebugClosure : public ClosurePrimitive { -public: - ustring m_tag; - - DebugClosure () : ClosurePrimitive(Debug) {} - - bool mergeable(const ClosurePrimitive *other) const { - const DebugClosure *comp = (const DebugClosure *)other; - return m_tag == comp->m_tag && - ClosurePrimitive::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "debug"; } - - void print_on(std::ostream &out) const { - out << name() << " (\"" << m_tag.c_str() << "\")"; - } - -}; - -ClosureParam closure_debug_params[] = { - CLOSURE_STRING_PARAM(DebugClosure, m_tag), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(DebugClosure) -}; - -CLOSURE_PREPARE(closure_debug_prepare, DebugClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/emissive.cpp b/intern/cycles/kernel/osl/emissive.cpp index 0a582c3f558..37e3e37c00a 100644 --- a/intern/cycles/kernel/osl/emissive.cpp +++ b/intern/cycles/kernel/osl/emissive.cpp @@ -36,6 +36,9 @@ #include "osl_closures.h" +#include "kernel_types.h" +#include "closure/emissive.h" + CCL_NAMESPACE_BEGIN using namespace OSL; @@ -52,55 +55,42 @@ public: GenericEmissiveClosure() { } void setup() {} - size_t memsize() const { return sizeof(*this); } - const char *name() const { return "emission"; } - void print_on(std::ostream &out) const { + void print_on(std::ostream &out) const + { out << name() << "()"; } Color3 eval(const Vec3 &Ng, const Vec3 &omega_out) const { - float cosNO = fabsf(Ng.dot(omega_out)); - float res = cosNO > 0 ? 1.0f : 0.0f; - return Color3(res, res, res); + float3 result = emissive_eval(TO_FLOAT3(Ng), TO_FLOAT3(omega_out)); + return TO_COLOR3(result); } void sample(const Vec3 &Ng, float randu, float randv, Vec3 &omega_out, float &pdf) const { - // We don't do anything sophisticated here for the step - // We just sample the whole cone uniformly to the cosine - Vec3 T, B; - make_orthonormals(Ng, T, B); - float phi = 2 * (float) M_PI * randu; - float cosTheta = sqrtf(1.0f - 1.0f * randv); - float sinTheta = sqrtf(1.0f - cosTheta * cosTheta); - omega_out = (cosf(phi) * sinTheta) * T + - (sinf(phi) * sinTheta) * B + - cosTheta * Ng; - pdf = 1.0f / float(M_PI); + float3 omega_out_; + emissive_sample(TO_FLOAT3(Ng), randu, randv, &omega_out_, &pdf); + omega_out = TO_VEC3(omega_out_); } - /// Return the probability distribution function in the direction omega_out, - /// given the parameters and the light's surface normal. This MUST match - /// the PDF computed by sample(). - float pdf(const Vec3 &Ng, - const Vec3 &omega_out) const + float pdf(const Vec3 &Ng, const Vec3 &omega_out) const { - float cosNO = Ng.dot(omega_out); - return cosNO > 0 ? 1.0f : 0.0f; + return emissive_pdf(TO_FLOAT3(Ng), TO_FLOAT3(omega_out)); } }; - - -ClosureParam closure_emission_params[] = { - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(GenericEmissiveClosure) -}; +ClosureParam *closure_emission_params() +{ + static ClosureParam params[] = { + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(GenericEmissiveClosure) + }; + return params; +} CLOSURE_PREPARE(closure_emission_prepare, GenericEmissiveClosure) diff --git a/intern/cycles/kernel/osl/nodes/node_voronoi_texture.osl b/intern/cycles/kernel/osl/nodes/node_voronoi_texture.osl deleted file mode 100644 index f24f154be84..00000000000 --- a/intern/cycles/kernel/osl/nodes/node_voronoi_texture.osl +++ /dev/null @@ -1,81 +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 "stdosl.h" -#include "node_texture.h" - -/* Voronoi */ - -shader node_voronoi_texture( - string DistanceMetric = "Actual Distance", - string Coloring = "Intensity", - float Weight1 = 1.0, - float Weight2 = 0.0, - float Weight3 = 0.0, - float Weight4 = 0.0, - float Exponent = 2.5, - float Intensity = 1.0, - float Scale = 5.0, - point Vector = P, - output float Fac = 0.0, - output color Color = color(0.0, 0.0, 0.0)) -{ - float exponent = max(Exponent, 1e-5); - - float aw1 = fabs(Weight1); - float aw2 = fabs(Weight2); - float aw3 = fabs(Weight3); - float aw4 = fabs(Weight4); - float sc = (aw1 + aw2 + aw3 + aw4); - - if(sc != 0.0) - sc = Intensity/sc; - - /* compute distance and point coordinate of 4 nearest neighbours */ - float da[4]; - point pa[4]; - - voronoi(Vector*Scale, DistanceMetric, exponent, da, pa); - - /* Scalar output */ - Fac = sc * fabs(Weight1*da[0] + Weight2*da[1] + Weight3*da[2] + Weight4*da[3]); - - /* Colored output */ - if(Coloring == "Intensity") { - Color = color(Fac, Fac, Fac); - } - else { - Color = aw1*cellnoise_color(pa[0]); - Color += aw2*cellnoise_color(pa[1]); - Color += aw3*cellnoise_color(pa[2]); - Color += aw4*cellnoise_color(pa[3]); - - if(Coloring != "Position") { - float t1 = min((da[1] - da[0])*10.0, 1.0); - - if(Coloring == "Position, Outline, and Intensity") - Color *= t1*Fac; - else if(Coloring == "Position and Outline") - Color *= t1*sc; - } - else { - Color *= sc; - } - } -} - diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index a1a108a1b1d..73e96643df7 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -37,10 +37,100 @@ #include "osl_shader.h" #include "util_debug.h" +#include "util_math.h" #include "util_param.h" +#include "kernel_types.h" +#include "kernel_montecarlo.h" + +#include "closure/bsdf.h" +#include "closure/bsdf_ashikhmin_velvet.h" +#include "closure/bsdf_diffuse.h" +#include "closure/bsdf_microfacet.h" +#include "closure/bsdf_oren_nayar.h" +#include "closure/bsdf_reflection.h" +#include "closure/bsdf_refraction.h" +#include "closure/bsdf_transparent.h" +#include "closure/bsdf_ward.h" +#include "closure/bsdf_westin.h" + CCL_NAMESPACE_BEGIN +using namespace OSL; + +/* BSDF class definitions */ + +BSDF_CLOSURE_CLASS_BEGIN(Diffuse, diffuse, diffuse, LABEL_DIFFUSE) + CLOSURE_VECTOR_PARAM(DiffuseClosure, N), +BSDF_CLOSURE_CLASS_END(Diffuse, diffuse) + +BSDF_CLOSURE_CLASS_BEGIN(Translucent, translucent, translucent, LABEL_DIFFUSE) + CLOSURE_VECTOR_PARAM(TranslucentClosure, N), +BSDF_CLOSURE_CLASS_END(Translucent, translucent) + +BSDF_CLOSURE_CLASS_BEGIN(OrenNayar, oren_nayar, oren_nayar, LABEL_DIFFUSE) + CLOSURE_VECTOR_PARAM(OrenNayarClosure, N), + CLOSURE_FLOAT_PARAM(OrenNayarClosure, sc.data0), +BSDF_CLOSURE_CLASS_END(OrenNayar, oren_nayar) + +BSDF_CLOSURE_CLASS_BEGIN(Reflection, reflection, reflection, LABEL_SINGULAR) + CLOSURE_VECTOR_PARAM(ReflectionClosure, N), +BSDF_CLOSURE_CLASS_END(Reflection, reflection) + +BSDF_CLOSURE_CLASS_BEGIN(Refraction, refraction, refraction, LABEL_SINGULAR) + CLOSURE_VECTOR_PARAM(RefractionClosure, N), + CLOSURE_FLOAT_PARAM(RefractionClosure, sc.data0), +BSDF_CLOSURE_CLASS_END(Refraction, refraction) + +BSDF_CLOSURE_CLASS_BEGIN(WestinBackscatter, westin_backscatter, westin_backscatter, LABEL_GLOSSY) + CLOSURE_VECTOR_PARAM(WestinBackscatterClosure, N), + CLOSURE_FLOAT_PARAM(WestinBackscatterClosure, sc.data0), +BSDF_CLOSURE_CLASS_END(WestinBackscatter, westin_backscatter) + +BSDF_CLOSURE_CLASS_BEGIN(WestinSheen, westin_sheen, westin_sheen, LABEL_DIFFUSE) + CLOSURE_VECTOR_PARAM(WestinSheenClosure, N), + CLOSURE_FLOAT_PARAM(WestinSheenClosure, sc.data0), +BSDF_CLOSURE_CLASS_END(WestinSheen, westin_sheen) + +BSDF_CLOSURE_CLASS_BEGIN(Transparent, transparent, transparent, LABEL_SINGULAR) +BSDF_CLOSURE_CLASS_END(Transparent, transparent) + +BSDF_CLOSURE_CLASS_BEGIN(AshikhminVelvet, ashikhmin_velvet, ashikhmin_velvet, LABEL_DIFFUSE) + CLOSURE_VECTOR_PARAM(AshikhminVelvetClosure, N), + CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, sc.data0), +BSDF_CLOSURE_CLASS_END(AshikhminVelvet, ashikhmin_velvet) + +BSDF_CLOSURE_CLASS_BEGIN(Ward, ward, ward, LABEL_GLOSSY) + CLOSURE_VECTOR_PARAM(WardClosure, N), + CLOSURE_VECTOR_PARAM(WardClosure, T), + CLOSURE_FLOAT_PARAM(WardClosure, sc.data0), + CLOSURE_FLOAT_PARAM(WardClosure, sc.data1), +BSDF_CLOSURE_CLASS_END(Ward, ward) + +BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGX, microfacet_ggx, microfacet_ggx, LABEL_GLOSSY) + CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure, N), + CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, sc.data0), +BSDF_CLOSURE_CLASS_END(MicrofacetGGX, microfacet_ggx) + +BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmann, microfacet_beckmann, microfacet_beckmann, LABEL_GLOSSY) + CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure, N), + CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, sc.data0), +BSDF_CLOSURE_CLASS_END(MicrofacetBeckmann, microfacet_beckmann) + +BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXRefraction, microfacet_ggx_refraction, microfacet_ggx, LABEL_GLOSSY) + CLOSURE_VECTOR_PARAM(MicrofacetGGXRefractionClosure, N), + CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, sc.data0), + CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, sc.data1), +BSDF_CLOSURE_CLASS_END(MicrofacetGGXRefraction, microfacet_ggx_refraction) + +BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction, microfacet_beckmann, LABEL_GLOSSY) + CLOSURE_VECTOR_PARAM(MicrofacetBeckmannRefractionClosure, N), + CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, sc.data0), + CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, sc.data1), +BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction) + +/* Registration */ + static void generic_closure_setup(OSL::RendererServices *, int id, void *data) { assert(data); @@ -64,28 +154,42 @@ static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, O void OSLShader::register_closures(OSL::ShadingSystem *ss) { - register_closure(ss, "diffuse", OSL_CLOSURE_BSDF_DIFFUSE_ID, bsdf_diffuse_params, bsdf_diffuse_prepare); - register_closure(ss, "oren_nayar", OSL_CLOSURE_BSDF_OREN_NAYAR_ID, bsdf_oren_nayar_params, bsdf_oren_nayar_prepare); - register_closure(ss, "translucent", OSL_CLOSURE_BSDF_TRANSLUCENT_ID, bsdf_translucent_params, bsdf_translucent_prepare); - register_closure(ss, "reflection", OSL_CLOSURE_BSDF_REFLECTION_ID, bsdf_reflection_params, bsdf_reflection_prepare); - register_closure(ss, "refraction", OSL_CLOSURE_BSDF_REFRACTION_ID, bsdf_refraction_params, bsdf_refraction_prepare); - register_closure(ss, "transparent", OSL_CLOSURE_BSDF_TRANSPARENT_ID, bsdf_transparent_params, bsdf_transparent_prepare); - register_closure(ss, "microfacet_ggx", OSL_CLOSURE_BSDF_MICROFACET_GGX_ID, bsdf_microfacet_ggx_params, bsdf_microfacet_ggx_prepare); - register_closure(ss, "microfacet_ggx_refraction", OSL_CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID, bsdf_microfacet_ggx_refraction_params, bsdf_microfacet_ggx_refraction_prepare); - register_closure(ss, "microfacet_beckmann", OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_ID, bsdf_microfacet_beckmann_params, bsdf_microfacet_beckmann_prepare); - register_closure(ss, "microfacet_beckmann_refraction", OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID, bsdf_microfacet_beckmann_refraction_params, bsdf_microfacet_beckmann_refraction_prepare); - register_closure(ss, "ward", OSL_CLOSURE_BSDF_WARD_ID, bsdf_ward_params, bsdf_ward_prepare); - register_closure(ss, "phong", OSL_CLOSURE_BSDF_PHONG_ID, bsdf_phong_params, bsdf_phong_prepare); - register_closure(ss, "phong_ramp", OSL_CLOSURE_BSDF_PHONG_RAMP_ID, bsdf_phong_ramp_params, bsdf_phong_ramp_prepare); - register_closure(ss, "ashikhmin_velvet", OSL_CLOSURE_BSDF_ASHIKHMIN_VELVET_ID, bsdf_ashikhmin_velvet_params, bsdf_ashikhmin_velvet_prepare); - register_closure(ss, "westin_backscatter", OSL_CLOSURE_BSDF_WESTIN_BACKSCATTER_ID, bsdf_westin_backscatter_params, bsdf_westin_backscatter_prepare); - register_closure(ss, "westin_sheen", OSL_CLOSURE_BSDF_WESTIN_SHEEN_ID, bsdf_westin_sheen_params, bsdf_westin_sheen_prepare); - register_closure(ss, "bssrdf_cubic", OSL_CLOSURE_BSSRDF_CUBIC_ID, closure_bssrdf_cubic_params, closure_bssrdf_cubic_prepare); - register_closure(ss, "emission", OSL_CLOSURE_EMISSION_ID, closure_emission_params, closure_emission_prepare); - register_closure(ss, "debug", OSL_CLOSURE_DEBUG_ID, closure_debug_params, closure_debug_prepare); - register_closure(ss, "background", OSL_CLOSURE_BACKGROUND_ID, closure_background_params, closure_background_prepare); - register_closure(ss, "holdout", OSL_CLOSURE_HOLDOUT_ID, closure_holdout_params, closure_holdout_prepare); - register_closure(ss, "subsurface", OSL_CLOSURE_SUBSURFACE_ID, closure_subsurface_params, closure_subsurface_prepare); + int id = 0; + + register_closure(ss, "diffuse", id++, + bsdf_diffuse_params(), bsdf_diffuse_prepare); + register_closure(ss, "oren_nayar", id++, + bsdf_oren_nayar_params(), bsdf_oren_nayar_prepare); + register_closure(ss, "translucent", id++, + bsdf_translucent_params(), bsdf_translucent_prepare); + register_closure(ss, "reflection", id++, + bsdf_reflection_params(), bsdf_reflection_prepare); + register_closure(ss, "refraction", id++, + bsdf_refraction_params(), bsdf_refraction_prepare); + register_closure(ss, "transparent", id++, + bsdf_transparent_params(), bsdf_transparent_prepare); + register_closure(ss, "microfacet_ggx", id++, + bsdf_microfacet_ggx_params(), bsdf_microfacet_ggx_prepare); + register_closure(ss, "microfacet_ggx_refraction", id++, + bsdf_microfacet_ggx_refraction_params(), bsdf_microfacet_ggx_refraction_prepare); + register_closure(ss, "microfacet_beckmann", id++, + bsdf_microfacet_beckmann_params(), bsdf_microfacet_beckmann_prepare); + register_closure(ss, "microfacet_beckmann_refraction", id++, + bsdf_microfacet_beckmann_refraction_params(), bsdf_microfacet_beckmann_refraction_prepare); + register_closure(ss, "ward", id++, + bsdf_ward_params(), bsdf_ward_prepare); + register_closure(ss, "ashikhmin_velvet", id++, + bsdf_ashikhmin_velvet_params(), bsdf_ashikhmin_velvet_prepare); + register_closure(ss, "westin_backscatter", id++, + bsdf_westin_backscatter_params(), bsdf_westin_backscatter_prepare); + register_closure(ss, "westin_sheen", id++, + bsdf_westin_sheen_params(), bsdf_westin_sheen_prepare); + register_closure(ss, "emission", id++, + closure_emission_params(), closure_emission_prepare); + register_closure(ss, "background", id++, + closure_background_params(), closure_background_prepare); + register_closure(ss, "holdout", id++, + closure_holdout_params(), closure_holdout_prepare); } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h index 00794183ca5..574cb685db5 100644 --- a/intern/cycles/kernel/osl/osl_closures.h +++ b/intern/cycles/kernel/osl/osl_closures.h @@ -37,78 +37,19 @@ #include #include +#include "kernel_types.h" + +#include "util_types.h" + CCL_NAMESPACE_BEGIN -enum { - OSL_CLOSURE_BSDF_DIFFUSE_ID, - OSL_CLOSURE_BSDF_OREN_NAYAR_ID, - OSL_CLOSURE_BSDF_TRANSLUCENT_ID, - OSL_CLOSURE_BSDF_REFLECTION_ID, - OSL_CLOSURE_BSDF_REFRACTION_ID, - OSL_CLOSURE_BSDF_TRANSPARENT_ID, - OSL_CLOSURE_BSDF_MICROFACET_GGX_ID, - OSL_CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID, - OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_ID, - OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID, - OSL_CLOSURE_BSDF_WARD_ID, - OSL_CLOSURE_BSDF_PHONG_ID, - OSL_CLOSURE_BSDF_PHONG_RAMP_ID, - OSL_CLOSURE_BSDF_ASHIKHMIN_VELVET_ID, - OSL_CLOSURE_BSDF_WESTIN_BACKSCATTER_ID, - OSL_CLOSURE_BSDF_WESTIN_SHEEN_ID, - OSL_CLOSURE_BSSRDF_CUBIC_ID, - OSL_CLOSURE_EMISSION_ID, - OSL_CLOSURE_DEBUG_ID, - OSL_CLOSURE_BACKGROUND_ID, - OSL_CLOSURE_HOLDOUT_ID, - OSL_CLOSURE_SUBSURFACE_ID -}; +OSL::ClosureParam *closure_emission_params(); +OSL::ClosureParam *closure_background_params(); +OSL::ClosureParam *closure_holdout_params(); -extern OSL::ClosureParam bsdf_diffuse_params[]; -extern OSL::ClosureParam bsdf_oren_nayar_params[]; -extern OSL::ClosureParam bsdf_translucent_params[]; -extern OSL::ClosureParam bsdf_reflection_params[]; -extern OSL::ClosureParam bsdf_refraction_params[]; -extern OSL::ClosureParam bsdf_transparent_params[]; -extern OSL::ClosureParam bsdf_microfacet_ggx_params[]; -extern OSL::ClosureParam bsdf_microfacet_ggx_refraction_params[]; -extern OSL::ClosureParam bsdf_microfacet_beckmann_params[]; -extern OSL::ClosureParam bsdf_microfacet_beckmann_refraction_params[]; -extern OSL::ClosureParam bsdf_ward_params[]; -extern OSL::ClosureParam bsdf_phong_params[]; -extern OSL::ClosureParam bsdf_phong_ramp_params[]; -extern OSL::ClosureParam bsdf_ashikhmin_velvet_params[]; -extern OSL::ClosureParam bsdf_westin_backscatter_params[]; -extern OSL::ClosureParam bsdf_westin_sheen_params[]; -extern OSL::ClosureParam closure_bssrdf_cubic_params[]; -extern OSL::ClosureParam closure_emission_params[]; -extern OSL::ClosureParam closure_debug_params[]; -extern OSL::ClosureParam closure_background_params[]; -extern OSL::ClosureParam closure_holdout_params[]; -extern OSL::ClosureParam closure_subsurface_params[]; - -void bsdf_diffuse_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_oren_nayar_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_translucent_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_reflection_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_refraction_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_transparent_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_microfacet_ggx_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_microfacet_ggx_refraction_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_microfacet_beckmann_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_microfacet_beckmann_refraction_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_ward_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_phong_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_ashikhmin_velvet_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_westin_backscatter_prepare(OSL::RendererServices *, int id, void *data); -void bsdf_westin_sheen_prepare(OSL::RendererServices *, int id, void *data); -void closure_bssrdf_cubic_prepare(OSL::RendererServices *, int id, void *data); void closure_emission_prepare(OSL::RendererServices *, int id, void *data); -void closure_debug_prepare(OSL::RendererServices *, int id, void *data); void closure_background_prepare(OSL::RendererServices *, int id, void *data); void closure_holdout_prepare(OSL::RendererServices *, int id, void *data); -void closure_subsurface_prepare(OSL::RendererServices *, int id, void *data); #define CLOSURE_PREPARE(name, classname) \ void name(RendererServices *, int id, void *data) \ @@ -117,6 +58,106 @@ void name(RendererServices *, int id, void *data) \ new (data) classname(); \ } +#define TO_VEC3(v) (*(OSL::Vec3 *)&(v)) +#define TO_COLOR3(v) (*(OSL::Color3 *)&(v)) +#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2]) + +/* BSDF */ + +class CBSDFClosure : public OSL::ClosurePrimitive { +public: + ShaderClosure sc; + OSL::Vec3 N, T; + + CBSDFClosure(int scattering) : OSL::ClosurePrimitive(BSDF), + m_scattering_label(scattering), m_shaderdata_flag(0) { } + ~CBSDFClosure() { } + + int scattering() const { return m_scattering_label; } + int shaderdata_flag() const { return m_shaderdata_flag; } + ClosureType shaderclosure_type() const { return sc.type; } + + virtual void blur(float roughness) = 0; + virtual float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0; + virtual float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0; + + virtual int sample(const float3 &Ng, + const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy, + float randu, float randv, + float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy, + float &pdf, float3 &eval) const = 0; + +protected: + int m_scattering_label; + int m_shaderdata_flag; +}; + +#define BSDF_CLOSURE_CLASS_BEGIN(Upper, lower, svmlower, TYPE) \ +\ +class Upper##Closure : public CBSDFClosure { \ +public: \ + Upper##Closure() : CBSDFClosure(TYPE) {} \ + size_t memsize() const { return sizeof(*this); } \ + const char *name() const { return #lower; } \ +\ + void setup() \ + { \ + sc.N = TO_FLOAT3(N); \ + sc.T = TO_FLOAT3(T); \ + m_shaderdata_flag = bsdf_##lower##_setup(&sc); \ + } \ +\ + bool mergeable(const ClosurePrimitive *other) const \ + { \ + return false; \ + } \ + \ + void blur(float roughness) \ + { \ + bsdf_##svmlower##_blur(&sc, roughness); \ + } \ +\ + void print_on(std::ostream &out) const \ + { \ + out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))"; \ + } \ +\ + float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const \ + { \ + return bsdf_##svmlower##_eval_reflect(&sc, omega_out, omega_in, &pdf); \ + } \ +\ + float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const \ + { \ + return bsdf_##svmlower##_eval_transmit(&sc, omega_out, omega_in, &pdf); \ + } \ +\ + int sample(const float3 &Ng, \ + const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy, \ + float randu, float randv, \ + float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy, \ + float &pdf, float3 &eval) const \ + { \ + return bsdf_##svmlower##_sample(&sc, Ng, omega_out, domega_out_dx, domega_out_dy, \ + randu, randv, &eval, &omega_in, &domega_in_dx, &domega_in_dy, &pdf); \ + } \ +}; \ +\ +ClosureParam *bsdf_##lower##_params() \ +{ \ + static ClosureParam params[] = { + +/* parameters */ + +#define BSDF_CLOSURE_CLASS_END(Upper, lower) \ + CLOSURE_STRING_KEYPARAM("label"), \ + CLOSURE_FINISH_PARAM(Upper##Closure) \ + }; \ + return params; \ +} \ +\ +CLOSURE_PREPARE(bsdf_##lower##_prepare, Upper##Closure) + CCL_NAMESPACE_END #endif /* __OSL_CLOSURES_H__ */ diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index f1deaa9db9d..ac26fc1c18d 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -72,7 +72,11 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr int object = sd->object; if (object != ~0) { - Transform tfm = object_fetch_transform(kg, object, time, OBJECT_TRANSFORM); +#ifdef __OBJECT_MOTION__ + Transform tfm = object_fetch_transform_motion_test(kg, object, time, NULL); +#else + Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); +#endif tfm = transform_transpose(tfm); result = TO_MATRIX44(tfm); @@ -93,9 +97,14 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::Transform int object = sd->object; if (object != ~0) { - Transform tfm = object_fetch_transform(kg, object, time, OBJECT_INVERSE_TRANSFORM); - tfm = transform_transpose(tfm); - result = TO_MATRIX44(tfm); +#ifdef __OBJECT_MOTION__ + Transform itfm; + object_fetch_transform_motion_test(kg, object, time, &itfm); +#else + Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); +#endif + itfm = transform_transpose(itfm); + result = TO_MATRIX44(itfm); return true; } @@ -109,7 +118,7 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from, float ti KernelGlobals *kg = kernel_globals; if (from == u_ndc) { - Transform tfm = transform_transpose(kernel_data.cam.ndctoworld); + Transform tfm = transform_transpose(transform_quick_inverse(kernel_data.cam.worldtondc)); result = TO_MATRIX44(tfm); return true; } @@ -162,14 +171,108 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to, fl bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform) { - // XXX implementation - return true; + /* this is only used for shader and object space, we don't really have + * a concept of shader space, so we just use object space for both. */ + if (xform) { + const ShaderData *sd = (const ShaderData *)xform; + int object = sd->object; + + if (object != ~0) { +#ifdef __OBJECT_MOTION__ + Transform tfm = sd->ob_tfm; +#else + KernelGlobals *kg = kernel_globals; + Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); +#endif + tfm = transform_transpose(tfm); + result = TO_MATRIX44(tfm); + + return true; + } + } + + return false; +} + +bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform) +{ + /* this is only used for shader and object space, we don't really have + * a concept of shader space, so we just use object space for both. */ + if (xform) { + const ShaderData *sd = (const ShaderData *)xform; + int object = sd->object; + + if (object != ~0) { +#ifdef __OBJECT_MOTION__ + Transform tfm = sd->ob_itfm; +#else + KernelGlobals *kg = kernel_globals; + Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); +#endif + tfm = transform_transpose(tfm); + result = TO_MATRIX44(tfm); + + return true; + } + } + + return false; } bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from) { - // XXX implementation - return true; + KernelGlobals *kg = kernel_globals; + + if (from == u_ndc) { + Transform tfm = transform_transpose(transform_quick_inverse(kernel_data.cam.worldtondc)); + result = TO_MATRIX44(tfm); + return true; + } + else if (from == u_raster) { + Transform tfm = transform_transpose(kernel_data.cam.rastertoworld); + result = TO_MATRIX44(tfm); + return true; + } + else if (from == u_screen) { + Transform tfm = transform_transpose(kernel_data.cam.screentoworld); + result = TO_MATRIX44(tfm); + return true; + } + else if (from == u_camera) { + Transform tfm = transform_transpose(kernel_data.cam.cameratoworld); + result = TO_MATRIX44(tfm); + return true; + } + + return false; +} + +bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to) +{ + KernelGlobals *kg = kernel_globals; + + if (to == u_ndc) { + Transform tfm = transform_transpose(kernel_data.cam.worldtondc); + result = TO_MATRIX44(tfm); + return true; + } + else if (to == u_raster) { + Transform tfm = transform_transpose(kernel_data.cam.worldtoraster); + result = TO_MATRIX44(tfm); + return true; + } + else if (to == u_screen) { + Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen); + result = TO_MATRIX44(tfm); + return true; + } + else if (to == u_camera) { + Transform tfm = transform_transpose(kernel_data.cam.worldtocamera); + result = TO_MATRIX44(tfm); + return true; + } + + return false; } bool OSLRenderServices::get_array_attribute(void *renderstate, bool derivatives, @@ -184,16 +287,26 @@ static void set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, v if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { - float3 *fval = (float3 *)val; - fval[0] = f[0]; + float *fval = (float *)val; + + fval[0] = f[0].x; + fval[1] = f[0].y; + fval[2] = f[0].z; + if (derivatives) { - fval[1] = f[1]; - fval[2] = f[2]; + fval[3] = f[1].x; + fval[4] = f[1].y; + fval[5] = f[1].z; + + fval[6] = f[2].x; + fval[7] = f[2].y; + fval[8] = f[2].z; } } else { float *fval = (float *)val; fval[0] = average(f[0]); + if (derivatives) { fval[1] = average(f[1]); fval[2] = average(f[2]); @@ -206,16 +319,25 @@ static void set_attribute_float(float f[3], TypeDesc type, bool derivatives, voi if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) { - float3 *fval = (float3 *)val; - fval[0] = make_float3(f[0], f[0], f[0]); + float *fval = (float *)val; + fval[0] = f[0]; + fval[1] = f[1]; + fval[2] = f[2]; + if (derivatives) { - fval[1] = make_float3(f[1], f[2], f[1]); - fval[2] = make_float3(f[2], f[2], f[2]); + fval[3] = f[1]; + fval[4] = f[1]; + fval[5] = f[1]; + + fval[6] = f[2]; + fval[7] = f[2]; + fval[8] = f[2]; } } else { float *fval = (float *)val; fval[0] = f[0]; + if (derivatives) { fval[1] = f[1]; fval[2] = f[2]; @@ -223,28 +345,73 @@ static void set_attribute_float(float f[3], TypeDesc type, bool derivatives, voi } } +static bool set_attribute_int(int i, TypeDesc type, bool derivatives, void *val) +{ + if(type.basetype == TypeDesc::INT && type.aggregate == TypeDesc::SCALAR && type.arraylen == 0) { + int *ival = (int *)val; + ival[0] = i; + + if (derivatives) { + ival[1] = 0; + ival[2] = 0; + } + + return true; + } + + return false; +} + +static bool set_attribute_float3_3(float3 P[3], TypeDesc type, bool derivatives, void *val) +{ + if(type.vecsemantics == TypeDesc::POINT && type.arraylen >= 3) { + float *fval = (float *)val; + + fval[0] = P[0].x; + fval[1] = P[0].y; + fval[2] = P[0].z; + + fval[3] = P[1].x; + fval[4] = P[1].y; + fval[5] = P[1].z; + + fval[6] = P[2].x; + fval[7] = P[2].y; + fval[8] = P[2].z; + + if(type.arraylen > 3) + memset(fval + 3*3, 0, sizeof(float)*3*(type.arraylen - 3)); + if (derivatives) + memset(fval + type.arraylen*3, 0, sizeof(float)*2*3*type.arraylen); + + return true; + } + + return false; +} + static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OSLGlobals::Attribute& attr, const TypeDesc& type, bool derivatives, void *val) { - if (attr.type == TypeDesc::TypeFloat) { - float fval[3]; - fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset, - (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); - set_attribute_float(fval, type, derivatives, val); - return true; - } - else if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector || + if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector || attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) { - /* todo: this won't work when float3 has w component */ float3 fval[3]; fval[0] = triangle_attribute_float3(kg, sd, attr.elem, attr.offset, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); set_attribute_float3(fval, type, derivatives, val); return true; } - else + else if (attr.type == TypeDesc::TypeFloat) { + float fval[3]; + fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset, + (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + set_attribute_float(fval, type, derivatives, val); + return true; + } + else { return false; + } } static void get_object_attribute(const OSLGlobals::Attribute& attr, bool derivatives, void *val) @@ -259,29 +426,45 @@ static void get_object_attribute(const OSLGlobals::Attribute& attr, bool derivat static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, TypeDesc type, bool derivatives, void *val) { + /* todo: turn this into hash table + callback once */ + /* Object Attributes */ - if (name == "std::object_location") { + if (name == "object:location") { float3 fval[3]; fval[0] = object_location(kg, sd); fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ set_attribute_float3(fval, type, derivatives, val); return true; } - else if (name == "std::object_index") { + else if (name == "object:index") { float fval[3]; fval[0] = object_pass_id(kg, sd->object); fval[1] = fval[2] = 0.0; /* derivates set to 0 */ set_attribute_float(fval, type, derivatives, val); return true; } - else if (name == "std::material_index") { + else if (name == "geom:dupli_generated") { + float3 fval[3]; + fval[0] = object_dupli_generated(kg, sd->object); + fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ + set_attribute_float3(fval, type, derivatives, val); + return true; + } + else if (name == "geom:dupli_uv") { + float3 fval[3]; + fval[0] = object_dupli_uv(kg, sd->object); + fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */ + set_attribute_float3(fval, type, derivatives, val); + return true; + } + else if (name == "material:index") { float fval[3]; fval[0] = shader_pass_id(kg, sd); fval[1] = fval[2] = 0.0; /* derivates set to 0 */ set_attribute_float(fval, type, derivatives, val); return true; } - else if (name == "std::object_random") { + else if (name == "object:random") { float fval[3]; fval[0] = object_random_number(kg, sd->object); fval[1] = fval[2] = 0.0; /* derivates set to 0 */ @@ -290,7 +473,7 @@ static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ust } /* Particle Attributes */ - else if (name == "std::particle_index") { + else if (name == "particle:index") { float fval[3]; uint particle_id = object_particle_id(kg, sd->object); fval[0] = particle_index(kg, particle_id); @@ -298,7 +481,7 @@ static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ust set_attribute_float(fval, type, derivatives, val); return true; } - else if (name == "std::particle_age") { + else if (name == "particle:age") { float fval[3]; uint particle_id = object_particle_id(kg, sd->object); fval[0] = particle_age(kg, particle_id); @@ -306,7 +489,7 @@ static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ust set_attribute_float(fval, type, derivatives, val); return true; } - else if (name == "std::particle_lifetime") { + else if (name == "particle:lifetime") { float fval[3]; uint particle_id = object_particle_id(kg, sd->object); fval[0] = particle_lifetime(kg, particle_id); @@ -314,7 +497,7 @@ static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ust set_attribute_float(fval, type, derivatives, val); return true; } - else if (name == "std::particle_location") { + else if (name == "particle:location") { float3 fval[3]; uint particle_id = object_particle_id(kg, sd->object); fval[0] = particle_location(kg, particle_id); @@ -323,7 +506,7 @@ static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ust return true; } #if 0 /* unsupported */ - else if (name == "std::particle_rotation") { + else if (name == "particle:rotation") { float4 fval[3]; uint particle_id = object_particle_id(kg, sd->object); fval[0] = particle_rotation(kg, particle_id); @@ -332,7 +515,7 @@ static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ust return true; } #endif - else if (name == "std::particle_size") { + else if (name == "particle:size") { float fval[3]; uint particle_id = object_particle_id(kg, sd->object); fval[0] = particle_size(kg, particle_id); @@ -340,7 +523,7 @@ static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ust set_attribute_float(fval, type, derivatives, val); return true; } - else if (name == "std::particle_velocity") { + else if (name == "particle:velocity") { float3 fval[3]; uint particle_id = object_particle_id(kg, sd->object); fval[0] = particle_velocity(kg, particle_id); @@ -348,7 +531,7 @@ static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ust set_attribute_float3(fval, type, derivatives, val); return true; } - else if (name == "std::particle_angular_velocity") { + else if (name == "particle:angular_velocity") { float3 fval[3]; uint particle_id = object_particle_id(kg, sd->object); fval[0] = particle_angular_velocity(kg, particle_id); @@ -356,6 +539,32 @@ static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ust set_attribute_float3(fval, type, derivatives, val); return true; } + else if (name == "geom:numpolyvertices") { + return set_attribute_int(3, type, derivatives, val); + } + else if (name == "geom:trianglevertices" || name == "geom:polyvertices") { + float3 P[3]; + triangle_vertices(kg, sd->prim, P); + object_position_transform(kg, sd, &P[0]); + object_position_transform(kg, sd, &P[1]); + object_position_transform(kg, sd, &P[2]); + return set_attribute_float3_3(P, type, derivatives, val); + } + else + return false; +} + +static bool get_background_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, + TypeDesc type, bool derivatives, void *val) +{ + /* Ray Length */ + if (name == "path:ray_length") { + float fval[3]; + fval[0] = sd->ray_length; + fval[1] = fval[2] = 0.0; /* derivates set to 0 */ + set_attribute_float(fval, type, derivatives, val); + return true; + } else return false; @@ -380,8 +589,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri tri = ~0; } else if (object == ~0) { - /* no background attributes supported */ - return false; + return get_background_attribute(kg, sd, name, type, derivatives, val); } /* find attribute on object */ @@ -390,7 +598,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri if (it != attribute_map.end()) { const OSLGlobals::Attribute& attr = it->second; - + if (attr.elem != ATTR_ELEMENT_VALUE) { /* triangle and vertex attributes */ if (tri != ~0) @@ -404,7 +612,12 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri } else { /* not found in attribute, check standard object info */ - return get_object_standard_attribute(kg, sd, name, type, derivatives, val); + bool is_std_object_attribute = get_object_standard_attribute(kg, sd, name, type, derivatives, val); + + if (is_std_object_attribute) + return true; + + return get_background_attribute(kg, sd, name, type, derivatives, val); } return false; diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h index 790b02a8abc..fa32d47a89f 100644 --- a/intern/cycles/kernel/osl/osl_services.h +++ b/intern/cycles/kernel/osl/osl_services.h @@ -54,7 +54,10 @@ public: bool get_inverse_matrix(OSL::Matrix44 &result, ustring to, float time); bool get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform); + bool get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform); + bool get_matrix(OSL::Matrix44 &result, ustring from); + bool get_inverse_matrix(OSL::Matrix44 &result, ustring from); bool get_array_attribute(void *renderstate, bool derivatives, ustring object, TypeDesc type, ustring name, diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index 98ede0e4f60..8b71ac30ab6 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_closures.h" #include "osl_services.h" #include "osl_shader.h" @@ -61,10 +62,6 @@ void OSLShader::thread_free(KernelGlobals *kg) /* Globals */ -#define TO_VEC3(v) (*(OSL::Vec3 *)&(v)) -#define TO_COLOR3(v) (*(OSL::Color3 *)&(v)) -#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2]) - static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, int path_flag, OSL::ShaderGlobals *globals) { @@ -127,27 +124,20 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, if (sd->num_closure == MAX_CLOSURE) return; - OSL::BSDFClosure *bsdf = (OSL::BSDFClosure *)prim; - ustring scattering = bsdf->scattering(); + CBSDFClosure *bsdf = (CBSDFClosure *)prim; + int scattering = bsdf->scattering(); /* no caustics option */ - if (no_glossy && scattering == OSL::Labels::GLOSSY) + if (no_glossy && scattering == LABEL_GLOSSY) return; /* sample weight */ - float albedo = bsdf->albedo(TO_VEC3(sd->I)); - float sample_weight = fabsf(average(weight)) * albedo; + float sample_weight = fabsf(average(weight)); + + sd->flag |= bsdf->shaderdata_flag(); sc.sample_weight = sample_weight; - sc.type = CLOSURE_BSDF_ID; - - /* scattering flags */ - if (scattering == OSL::Labels::DIFFUSE) - sd->flag |= SD_BSDF | SD_BSDF_HAS_EVAL; - else if (scattering == OSL::Labels::GLOSSY) - sd->flag |= SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_GLOSSY; - else - sd->flag |= SD_BSDF; + sc.type = bsdf->shaderclosure_type(); /* add */ sd->closure[sd->num_closure++] = sc; @@ -394,54 +384,34 @@ void OSLShader::release(KernelGlobals *kg, ShaderData *sd) int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3& eval, float3& omega_in, differential3& domega_in, float& pdf) { - OSL::BSDFClosure *sample_bsdf = (OSL::BSDFClosure *)sc->prim; - int label = LABEL_NONE; + CBSDFClosure *sample_bsdf = (CBSDFClosure *)sc->prim; pdf = 0.0f; - /* sample BSDF closure */ - ustring ulabel; - - ulabel = sample_bsdf->sample(TO_VEC3(sd->Ng), - TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy), - randu, randv, - TO_VEC3(omega_in), TO_VEC3(domega_in.dx), TO_VEC3(domega_in.dy), - pdf, TO_COLOR3(eval)); - - /* convert OSL label */ - if (ulabel == OSL::Labels::REFLECT) - label = LABEL_REFLECT; - else if (ulabel == OSL::Labels::TRANSMIT) - label = LABEL_TRANSMIT; - else - return LABEL_NONE; /* sampling failed */ - - /* convert scattering to our bitflag label */ - ustring uscattering = sample_bsdf->scattering(); - - if (uscattering == OSL::Labels::DIFFUSE) - label |= LABEL_DIFFUSE; - else if (uscattering == OSL::Labels::GLOSSY) - label |= LABEL_GLOSSY; - else if (uscattering == OSL::Labels::SINGULAR) - label |= LABEL_SINGULAR; - else - label |= LABEL_TRANSPARENT; - - return label; + return sample_bsdf->sample(sd->Ng, + sd->I, sd->dI.dx, sd->dI.dy, + randu, randv, + omega_in, domega_in.dx, domega_in.dy, + pdf, eval); } float3 OSLShader::bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3& omega_in, float& pdf) { - OSL::BSDFClosure *bsdf = (OSL::BSDFClosure *)sc->prim; - OSL::Color3 bsdf_eval; + CBSDFClosure *bsdf = (CBSDFClosure *)sc->prim; + float3 bsdf_eval; if (dot(sd->Ng, omega_in) >= 0.0f) - bsdf_eval = bsdf->eval_reflect(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf); + bsdf_eval = bsdf->eval_reflect(sd->I, omega_in, pdf); else - bsdf_eval = bsdf->eval_transmit(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf); + bsdf_eval = bsdf->eval_transmit(sd->I, omega_in, pdf); - return TO_FLOAT3(bsdf_eval); + return bsdf_eval; +} + +void OSLShader::bsdf_blur(ShaderClosure *sc, float roughness) +{ + CBSDFClosure *bsdf = (CBSDFClosure *)sc->prim; + bsdf->blur(roughness); } /* Emissive Closure */ @@ -456,7 +426,7 @@ float3 OSLShader::emissive_eval(const ShaderData *sd, const ShaderClosure *sc) /* Volume Closure */ -float3 OSLShader::volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) +float3 OSLShader::volume_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) { OSL::VolumeClosure *volume = (OSL::VolumeClosure *)sc->prim; OSL::Color3 volume_eval = volume->eval_phase(TO_VEC3(omega_in), TO_VEC3(omega_out)); diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h index e2f4d1e94b8..9ff31e9160b 100644 --- a/intern/cycles/kernel/osl/osl_shader.h +++ b/intern/cycles/kernel/osl/osl_shader.h @@ -72,10 +72,11 @@ public: float3& eval, float3& omega_in, differential3& domega_in, float& pdf); static float3 bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3& omega_in, float& pdf); + static void bsdf_blur(ShaderClosure *sc, float roughness); static float3 emissive_eval(const ShaderData *sd, const ShaderClosure *sc); - static float3 volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc, + static float3 volume_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out); /* release */ diff --git a/intern/cycles/kernel/osl/vol_subsurface.cpp b/intern/cycles/kernel/osl/vol_subsurface.cpp deleted file mode 100644 index 818a057b6cc..00000000000 --- a/intern/cycles/kernel/osl/vol_subsurface.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * 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 - -#include - -#include "osl_closures.h" - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -// Computes scattering properties based on Jensen's reparameterization -// described in: -// http://graphics.ucsd.edu/~henrik/papers/fast_bssrdf/ - -class SubsurfaceClosure : public VolumeClosure { -public: - float m_g; - float m_eta; - Color3 m_mfp, m_albedo; - static float root_find_Rd(const float Rd0, const float A) { - // quick exit for trivial cases - if (Rd0 <= 0) return 0; - const float A43 = A * 4.0f / 3.0f; - // Find alpha such that f(alpha) = Rd (see eq.15). A simple bisection - // method can be used because this function is monotonicaly increasing. - float lo = 0, hi = 1; - for (int i = 0; i < 20; i++) { // 2^20 divisions should be sufficient - // eval function at midpoint - float alpha = 0.5f * (lo + hi); - float a1 = sqrtf(3 * (1 - alpha)); - float e1 = expf(-a1); - float e2 = expf(-A43 * a1); - float Rd = 0.5f * alpha * (1 + e2) * e1 - Rd0; - if (fabsf(Rd) < 1e-6f) - return alpha; // close enough - else if (Rd > 0) - hi = alpha; // root is on left side - else - lo = alpha; // root is on right side - } - // didn't quite converge, pick result in the middle of remaining interval - return 0.5f * (lo + hi); - } - SubsurfaceClosure() { - } - - void setup() - { - ior(m_eta); - - if (m_g >= 0.99f) m_g = 0.99f; - if (m_g <= -0.99f) m_g = -0.99f; - - // eq.10 - float inv_eta = 1 / m_eta; - float Fdr = -1.440f * inv_eta * inv_eta + 0.710 * inv_eta + 0.668f + 0.0636 * m_eta; - float A = (1 + Fdr) / (1 - Fdr); - // compute sigma_s, sigma_a (eq.16) - Color3 alpha_prime = Color3(root_find_Rd(m_albedo[0], A), - root_find_Rd(m_albedo[1], A), - root_find_Rd(m_albedo[2], A)); - Color3 sigma_t_prime = Color3(m_mfp.x > 0 ? 1.0f / (m_mfp[0] * sqrtf(3 * (1 - alpha_prime[0]))) : 0.0f, - m_mfp.y > 0 ? 1.0f / (m_mfp[1] * sqrtf(3 * (1 - alpha_prime[1]))) : 0.0f, - m_mfp.z > 0 ? 1.0f / (m_mfp[2] * sqrtf(3 * (1 - alpha_prime[2]))) : 0.0f); - Color3 sigma_s_prime = alpha_prime * sigma_t_prime; - - sigma_s((1.0f / (1 - m_g)) * sigma_s_prime); - sigma_a(sigma_t_prime - sigma_s_prime); - } - - bool mergeable(const ClosurePrimitive *other) const { - const SubsurfaceClosure *comp = (const SubsurfaceClosure *)other; - return m_g == comp->m_g && VolumeClosure::mergeable(other); - } - - size_t memsize() const { return sizeof(*this); } - - const char *name() const { return "subsurface"; } - - void print_on(std::ostream &out) const { - out << name() << " ()"; - } - - virtual Color3 eval_phase(const Vec3 &omega_in, const Vec3 &omega_out) const { - float costheta = omega_in.dot(omega_out); - float ph = 0.25f * float(M_1_PI) * ((1 - m_g * m_g) / powf(1 + m_g * m_g - 2.0f * m_g * costheta, 1.5f)); - return Color3(ph, ph, ph); - } -}; - - - -ClosureParam closure_subsurface_params[] = { - CLOSURE_FLOAT_PARAM(SubsurfaceClosure, m_eta), - CLOSURE_FLOAT_PARAM(SubsurfaceClosure, m_g), - CLOSURE_COLOR_PARAM(SubsurfaceClosure, m_mfp), - CLOSURE_COLOR_PARAM(SubsurfaceClosure, m_albedo), - CLOSURE_STRING_KEYPARAM("label"), - CLOSURE_FINISH_PARAM(SubsurfaceClosure) -}; - -CLOSURE_PREPARE(closure_subsurface_prepare, SubsurfaceClosure) - -CCL_NAMESPACE_END - diff --git a/intern/cycles/kernel/osl/nodes/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt similarity index 81% rename from intern/cycles/kernel/osl/nodes/CMakeLists.txt rename to intern/cycles/kernel/shaders/CMakeLists.txt index 729d4dae1c9..00ab52a1d13 100644 --- a/intern/cycles/kernel/osl/nodes/CMakeLists.txt +++ b/intern/cycles/kernel/shaders/CMakeLists.txt @@ -12,6 +12,7 @@ set(SRC_OSL node_combine_rgb.osl node_convert_from_color.osl node_convert_from_float.osl + node_convert_from_int.osl node_convert_from_normal.osl node_convert_from_point.osl node_convert_from_vector.osl @@ -29,7 +30,9 @@ set(SRC_OSL node_hsv.osl node_image_texture.osl node_invert.osl + node_layer_weight.osl node_light_path.osl + node_light_falloff.osl node_magic_texture.osl node_mapping.osl node_math.osl @@ -43,7 +46,9 @@ set(SRC_OSL node_output_surface.osl node_output_volume.osl node_particle_info.osl + node_rgb_ramp.osl node_separate_rgb.osl + node_set_normal.osl node_sky_texture.osl node_texture_coordinate.osl node_translucent_bsdf.osl @@ -71,11 +76,11 @@ set(SRC_OSO # TODO, add a module to compile OSL foreach(_file ${SRC_OSL}) set(_OSL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${_file}) - string(REPLACE ".osl" ".oso" _OSO_FILE ${_OSL_FILE}) # TODO, replace extension only + string(REPLACE ".osl" ".oso" _OSO_FILE ${_OSL_FILE}) string(REPLACE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} _OSO_FILE ${_OSO_FILE}) add_custom_command( OUTPUT ${_OSO_FILE} - COMMAND ${OSL_COMPILER} -O2 ${_OSL_FILE} + COMMAND ${OSL_COMPILER} -O2 -I"${CMAKE_CURRENT_SOURCE_DIR}" ${_OSL_FILE} DEPENDS ${_OSL_FILE} ${SRC_OSL_HEADERS}) list(APPEND SRC_OSO ${_OSO_FILE} @@ -85,7 +90,9 @@ foreach(_file ${SRC_OSL}) unset(_OSO_FILE) endforeach() -add_custom_target(shader ALL DEPENDS ${SRC_OSO} ${SRC_OSL_HEADERS}) +add_custom_target(cycles_osl_shaders ALL DEPENDS ${SRC_OSO} ${SRC_OSL_HEADERS}) # CMAKE_CURRENT_SOURCE_DIR is already included in OSO paths delayed_install("" "${SRC_OSO}" ${CYCLES_INSTALL_PATH}/shader) +delayed_install("${CMAKE_CURRENT_SOURCE_DIR}" "${SRC_OSL_HEADERS}" ${CYCLES_INSTALL_PATH}/shader) + diff --git a/intern/cycles/kernel/osl/nodes/node_add_closure.osl b/intern/cycles/kernel/shaders/node_add_closure.osl similarity index 100% rename from intern/cycles/kernel/osl/nodes/node_add_closure.osl rename to intern/cycles/kernel/shaders/node_add_closure.osl diff --git a/intern/cycles/kernel/osl/nodes/node_attribute.osl b/intern/cycles/kernel/shaders/node_attribute.osl similarity index 95% rename from intern/cycles/kernel/osl/nodes/node_attribute.osl rename to intern/cycles/kernel/shaders/node_attribute.osl index d273d0c68d7..8e7c846d1a3 100644 --- a/intern/cycles/kernel/osl/nodes/node_attribute.osl +++ b/intern/cycles/kernel/shaders/node_attribute.osl @@ -29,12 +29,12 @@ shader node_attribute( Vector = point(Color); getattribute(name, Fac); - if(bump_offset == "dx") { + if (bump_offset == "dx") { Color += Dx(Color); Vector += Dx(Vector); Fac += Dx(Fac); } - else if(bump_offset == "dy") { + else if (bump_offset == "dy") { Color += Dy(Color); Vector += Dy(Vector); Fac += Dy(Fac); diff --git a/intern/cycles/kernel/osl/nodes/node_background.osl b/intern/cycles/kernel/shaders/node_background.osl similarity index 95% rename from intern/cycles/kernel/osl/nodes/node_background.osl rename to intern/cycles/kernel/shaders/node_background.osl index 69f8d85a82e..b51a1685294 100644 --- a/intern/cycles/kernel/osl/nodes/node_background.osl +++ b/intern/cycles/kernel/shaders/node_background.osl @@ -23,6 +23,6 @@ shader node_background( float Strength = 1.0, output closure color Background = background()) { - Background = Color*Strength*background(); + Background = Color * Strength * background(); } diff --git a/intern/cycles/kernel/osl/nodes/node_brick_texture.osl b/intern/cycles/kernel/shaders/node_brick_texture.osl similarity index 79% rename from intern/cycles/kernel/osl/nodes/node_brick_texture.osl rename to intern/cycles/kernel/shaders/node_brick_texture.osl index 4daceb4018e..478d9457001 100644 --- a/intern/cycles/kernel/osl/nodes/node_brick_texture.osl +++ b/intern/cycles/kernel/shaders/node_brick_texture.osl @@ -40,21 +40,21 @@ float brick(point p, float mortar_size, float bias, rownum = (int)floor(p[1] / row_height); - if(offset_frequency && squash_frequency) { - brick_width *= ((int)(rownum) % squash_frequency ) ? 1.0 : squash_amount; /* squash */ - offset = ((int)(rownum) % offset_frequency ) ? 0 : (brick_width*offset_amount); /* offset */ + if (offset_frequency && squash_frequency) { + brick_width *= ((int)(rownum) % squash_frequency) ? 1.0 : squash_amount; /* squash */ + offset = ((int)(rownum) % offset_frequency) ? 0 : (brick_width * offset_amount); /* offset */ } - bricknum = (int)floor((p[0]+offset) / brick_width); + bricknum = (int)floor((p[0] + offset) / brick_width); - x = (p[0]+offset) - brick_width*bricknum; - y = p[1] - row_height*rownum; + x = (p[0] + offset) - brick_width * bricknum; + y = p[1] - row_height * rownum; tint = clamp((brick_noise((rownum << 16) + (bricknum & 65535)) + bias), 0.0, 1.0); return (x < mortar_size || y < mortar_size || - x > (brick_width - mortar_size) || - y > (row_height - mortar_size)) ? 1.0 : 0.0; + x > (brick_width - mortar_size) || + y > (row_height - mortar_size)) ? 1.0 : 0.0; } shader node_brick_texture( @@ -77,10 +77,10 @@ shader node_brick_texture( float tint = 0.0; color Col = Color1; - Fac = brick(Vector*Scale, MortarSize, Bias, BrickWidth, RowHeight, + Fac = brick(Vector * Scale, MortarSize, Bias, BrickWidth, RowHeight, Offset, OffsetFrequency, Squash, SquashFrequency, tint); - if(Fac != 1.0) { + if (Fac != 1.0) { float facm = 1.0 - tint; Col[0] = facm * (Color1[0]) + tint * Color2[0]; @@ -89,6 +89,5 @@ shader node_brick_texture( } Color = (Fac == 1.0) ? Mortar: Col; - } diff --git a/intern/cycles/kernel/osl/nodes/node_brightness.osl b/intern/cycles/kernel/shaders/node_brightness.osl similarity index 85% rename from intern/cycles/kernel/osl/nodes/node_brightness.osl rename to intern/cycles/kernel/shaders/node_brightness.osl index 4f19a20f736..8e9f5c9c796 100644 --- a/intern/cycles/kernel/osl/nodes/node_brightness.osl +++ b/intern/cycles/kernel/shaders/node_brightness.osl @@ -24,7 +24,7 @@ shader node_brightness( float Contrast = 0.0, output color ColorOut = color(0.8, 0.8, 0.8)) { - float delta = Contrast * (1.0/200.0); + float delta = Contrast * (1.0 / 200.0); float a = 1.0 - delta * 2.0; float b; @@ -32,13 +32,13 @@ shader node_brightness( float bright_factor = Brightness / 100.0; /* - * The algorithm is by Werner D. Streidt - * (http://visca.com/ffactory/archives/5-99/msg00021.html) - * Extracted of OpenCV demhist.c - */ + * The algorithm is by Werner D. Streidt + * (http://visca.com/ffactory/archives/5-99/msg00021.html) + * Extracted of OpenCV demhist.c + */ if (Contrast > 0.0) { - a = (a < 0.0 ? 1.0/a : 0.0); + a = (a < 0.0 ? 1.0 / a : 0.0); b = a * (bright_factor - delta); } else { diff --git a/intern/cycles/kernel/osl/nodes/node_bump.osl b/intern/cycles/kernel/shaders/node_bump.osl similarity index 67% rename from intern/cycles/kernel/osl/nodes/node_bump.osl rename to intern/cycles/kernel/shaders/node_bump.osl index a3849e70f98..24db1b24458 100644 --- a/intern/cycles/kernel/osl/nodes/node_bump.osl +++ b/intern/cycles/kernel/shaders/node_bump.osl @@ -18,29 +18,32 @@ #include "stdosl.h" -/* "Bump Mapping Unparametrized Surfaces on the GPU" +/* "Bump Mapping Unparameterized Surfaces on the GPU" * Morten S. Mikkelsen, 2010 */ surface node_bump( + normal NormalIn = N, + float Strength = 0.0, float SampleCenter = 0.0, float SampleX = 0.0, float SampleY = 0.0, output normal Normal = N) { - float dx = SampleX - SampleCenter; - float dy = SampleY - SampleCenter; - + /* get surface tangents from normal */ vector dPdx = Dx(P); vector dPdy = Dy(P); - vector Rx = cross(dPdy, N); - vector Ry = cross(N, dPdx); + vector Rx = cross(dPdy, NormalIn); + vector Ry = cross(NormalIn, dPdx); + /* compute surface gradient and determinant */ float det = dot(dPdx, Rx); - vector surfgrad = dx*Rx + dy*Ry; + vector surfgrad = (SampleX - SampleCenter) * Rx + (SampleY - SampleCenter) * Ry; - surfgrad *= 0.1; /* todo: remove this factor */ + surfgrad *= Strength; + float absdet = fabs(det); - Normal = normalize(abs(det)*N - sign(det)*surfgrad); + /* compute and output perturbed normal */ + Normal = normalize(absdet * NormalIn - sign(det) * surfgrad); } diff --git a/intern/cycles/kernel/osl/nodes/node_camera.osl b/intern/cycles/kernel/shaders/node_camera.osl similarity index 100% rename from intern/cycles/kernel/osl/nodes/node_camera.osl rename to intern/cycles/kernel/shaders/node_camera.osl diff --git a/intern/cycles/kernel/osl/nodes/node_checker_texture.osl b/intern/cycles/kernel/shaders/node_checker_texture.osl similarity index 86% rename from intern/cycles/kernel/osl/nodes/node_checker_texture.osl rename to intern/cycles/kernel/shaders/node_checker_texture.osl index e92d7be34fc..577caf308ff 100644 --- a/intern/cycles/kernel/osl/nodes/node_checker_texture.osl +++ b/intern/cycles/kernel/shaders/node_checker_texture.osl @@ -23,15 +23,15 @@ float checker(point p) { - p[0] = (p[0] + 0.00001)*0.9999; - p[1] = (p[1] + 0.00001)*0.9999; - p[2] = (p[2] + 0.00001)*0.9999; + p[0] = (p[0] + 0.00001) * 0.9999; + p[1] = (p[1] + 0.00001) * 0.9999; + p[2] = (p[2] + 0.00001) * 0.9999; int xi = (int)fabs(floor(p[0])); int yi = (int)fabs(floor(p[1])); int zi = (int)fabs(floor(p[2])); - if((xi % 2 == yi % 2) == (zi % 2)) { + if ((xi % 2 == yi % 2) == (zi % 2)) { return 1.0; } else { @@ -47,8 +47,8 @@ shader node_checker_texture( output float Fac = 0.0, output color Color = color(0.0, 0.0, 0.0)) { - Fac = checker(Vector*Scale); - if(Fac == 1.0) { + Fac = checker(Vector * Scale); + if (Fac == 1.0) { Color = Color1; } else { diff --git a/intern/cycles/kernel/osl/nodes/node_color.h b/intern/cycles/kernel/shaders/node_color.h similarity index 100% rename from intern/cycles/kernel/osl/nodes/node_color.h rename to intern/cycles/kernel/shaders/node_color.h diff --git a/intern/cycles/kernel/osl/nodes/node_combine_rgb.osl b/intern/cycles/kernel/shaders/node_combine_rgb.osl similarity index 100% rename from intern/cycles/kernel/osl/nodes/node_combine_rgb.osl rename to intern/cycles/kernel/shaders/node_combine_rgb.osl diff --git a/intern/cycles/kernel/osl/nodes/node_convert_from_color.osl b/intern/cycles/kernel/shaders/node_convert_from_color.osl similarity index 87% rename from intern/cycles/kernel/osl/nodes/node_convert_from_color.osl rename to intern/cycles/kernel/shaders/node_convert_from_color.osl index 97356139c48..2884c772414 100644 --- a/intern/cycles/kernel/osl/nodes/node_convert_from_color.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_color.osl @@ -21,11 +21,13 @@ shader node_convert_from_color( color Color = color(0.0, 0.0, 0.0), output float Val = 0.0, + output int ValInt = 0, output vector Vector = vector(0.0, 0.0, 0.0), output point Point = point(0.0, 0.0, 0.0), output normal Normal = normal(0.0, 0.0, 0.0)) { - Val = Color[0]*0.2126 + Color[1]*0.7152 + Color[2]*0.0722; + Val = Color[0] * 0.2126 + Color[1] * 0.7152 + Color[2] * 0.0722; + ValInt = (int)(Color[0]*0.2126 + Color[1]*0.7152 + Color[2]*0.0722); Vector = vector(Color[0], Color[1], Color[2]); Point = point(Color[0], Color[1], Color[2]); Normal = normal(Color[0], Color[1], Color[2]); diff --git a/intern/cycles/kernel/osl/nodes/node_convert_from_float.osl b/intern/cycles/kernel/shaders/node_convert_from_float.osl similarity index 96% rename from intern/cycles/kernel/osl/nodes/node_convert_from_float.osl rename to intern/cycles/kernel/shaders/node_convert_from_float.osl index 00e78f3bab4..4466fbae3a6 100644 --- a/intern/cycles/kernel/osl/nodes/node_convert_from_float.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_float.osl @@ -20,11 +20,13 @@ shader node_convert_from_float( float Val = 0.0, + output int ValInt = 0, output color Color = color(0.0, 0.0, 0.0), output vector Vector = vector(0.0, 0.0, 0.0), output point Point = point(0.0, 0.0, 0.0), output normal Normal = normal(0.0, 0.0, 0.0)) { + ValInt = (int)Val; Color = color(Val, Val, Val); Vector = vector(Val, Val, Val); Point = point(Val, Val, Val); diff --git a/intern/cycles/kernel/osl/nodes/node_image_texture.osl b/intern/cycles/kernel/shaders/node_convert_from_int.osl similarity index 70% rename from intern/cycles/kernel/osl/nodes/node_image_texture.osl rename to intern/cycles/kernel/shaders/node_convert_from_int.osl index 38126401d76..060d4184fa6 100644 --- a/intern/cycles/kernel/osl/nodes/node_image_texture.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_int.osl @@ -17,18 +17,20 @@ */ #include "stdosl.h" -#include "node_color.h" -shader node_image_texture( - point Vector = P, - string filename = "", - string color_space = "sRGB", +shader node_convert_from_int( + int ValInt = 0, + output float Val = 0.0, output color Color = color(0.0, 0.0, 0.0), - output float Alpha = 1.0) + output vector Vector = vector(0.0, 0.0, 0.0), + output point Point = point(0.0, 0.0, 0.0), + output normal Normal = normal(0.0, 0.0, 0.0)) { - Color = (color)texture(filename, Vector[0], 1.0-Vector[1], "wrap", "periodic", "alpha", Alpha); - - if(color_space == "sRGB") - Color = color_srgb_to_scene_linear(Color); + float f = (float)ValInt; + Val = f; + Color = color(f, f, f); + Vector = vector(f, f, f); + Point = point(f, f, f); + Normal = normal(f, f, f); } diff --git a/intern/cycles/kernel/osl/nodes/node_convert_from_normal.osl b/intern/cycles/kernel/shaders/node_convert_from_normal.osl similarity index 88% rename from intern/cycles/kernel/osl/nodes/node_convert_from_normal.osl rename to intern/cycles/kernel/shaders/node_convert_from_normal.osl index 0bb9092591d..32ef430d93b 100644 --- a/intern/cycles/kernel/osl/nodes/node_convert_from_normal.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_normal.osl @@ -21,11 +21,13 @@ shader node_convert_from_normal( normal Normal = normal(0.0, 0.0, 0.0), output float Val = 0.0, + output int ValInt = 0, output vector Vector = vector(0.0, 0.0, 0.0), output color Color = color(0.0, 0.0, 0.0), output point Point = point(0.0, 0.0, 0.0)) { - Val = (Normal[0] + Normal[1] + Normal[2])*(1.0/3.0); + Val = (Normal[0] + Normal[1] + Normal[2]) * (1.0 / 3.0); + ValInt = (int)((Normal[0] + Normal[1] + Normal[2]) * (1.0 / 3.0)); Vector = vector(Normal[0], Normal[1], Normal[2]); Color = color(Normal[0], Normal[1], Normal[2]); Point = point(Normal[0], Normal[1], Normal[2]); diff --git a/intern/cycles/kernel/osl/nodes/node_convert_from_point.osl b/intern/cycles/kernel/shaders/node_convert_from_point.osl similarity index 88% rename from intern/cycles/kernel/osl/nodes/node_convert_from_point.osl rename to intern/cycles/kernel/shaders/node_convert_from_point.osl index e66d6a864d6..a9435c8abf4 100644 --- a/intern/cycles/kernel/osl/nodes/node_convert_from_point.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_point.osl @@ -21,11 +21,13 @@ shader node_convert_from_point( point Point = point(0.0, 0.0, 0.0), output float Val = 0.0, + output int ValInt = 0, output vector Vector = vector(0.0, 0.0, 0.0), output color Color = color(0.0, 0.0, 0.0), output normal Normal = normal(0.0, 0.0, 0.0)) { - Val = (Point[0] + Point[1] + Point[2])*(1.0/3.0); + Val = (Point[0] + Point[1] + Point[2]) * (1.0 / 3.0); + ValInt = (int)((Normal[0] + Normal[1] + Normal[2]) * (1.0 / 3.0)); Vector = vector(Point[0], Point[1], Point[2]); Color = color(Point[0], Point[1], Point[2]); Normal = normal(Point[0], Point[1], Point[2]); diff --git a/intern/cycles/kernel/osl/nodes/node_convert_from_vector.osl b/intern/cycles/kernel/shaders/node_convert_from_vector.osl similarity index 88% rename from intern/cycles/kernel/osl/nodes/node_convert_from_vector.osl rename to intern/cycles/kernel/shaders/node_convert_from_vector.osl index 37ba9582cad..4516f92c753 100644 --- a/intern/cycles/kernel/osl/nodes/node_convert_from_vector.osl +++ b/intern/cycles/kernel/shaders/node_convert_from_vector.osl @@ -21,11 +21,13 @@ shader node_convert_from_vector( vector Vector = vector(0.0, 0.0, 0.0), output float Val = 0.0, + output int ValInt = 0, output color Color = color(0.0, 0.0, 0.0), output point Point = point(0.0, 0.0, 0.0), output normal Normal = normal(0.0, 0.0, 0.0)) { - Val = (Vector[0] + Vector[1] + Vector[2])*(1.0/3.0); + Val = (Vector[0] + Vector[1] + Vector[2]) * (1.0 / 3.0); + ValInt = (int)((Normal[0] + Normal[1] + Normal[2]) * (1.0 / 3.0)); Color = color(Vector[0], Vector[1], Vector[2]); Point = point(Vector[0], Vector[1], Vector[2]); Normal = normal(Vector[0], Vector[1], Vector[2]); diff --git a/intern/cycles/kernel/osl/nodes/node_diffuse_bsdf.osl b/intern/cycles/kernel/shaders/node_diffuse_bsdf.osl similarity index 97% rename from intern/cycles/kernel/osl/nodes/node_diffuse_bsdf.osl rename to intern/cycles/kernel/shaders/node_diffuse_bsdf.osl index 6075b7c93f3..d6dc17316e8 100644 --- a/intern/cycles/kernel/osl/nodes/node_diffuse_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_diffuse_bsdf.osl @@ -24,7 +24,7 @@ shader node_diffuse_bsdf( normal Normal = N, output closure color BSDF = diffuse(Normal)) { - if(Roughness == 0.0) + if (Roughness == 0.0) BSDF = Color * diffuse(Normal); else BSDF = Color * oren_nayar(Normal, Roughness); diff --git a/intern/cycles/kernel/osl/nodes/node_emission.osl b/intern/cycles/kernel/shaders/node_emission.osl similarity index 88% rename from intern/cycles/kernel/osl/nodes/node_emission.osl rename to intern/cycles/kernel/shaders/node_emission.osl index 8bfd1af173a..7ad0f9f7760 100644 --- a/intern/cycles/kernel/osl/nodes/node_emission.osl +++ b/intern/cycles/kernel/shaders/node_emission.osl @@ -24,9 +24,9 @@ shader node_emission( float Strength = 1.0, output closure color Emission = emission()) { - if(TotalPower) - Emission = ((Strength/surfacearea())*Color)*emission(); + if (TotalPower) + Emission = ((Strength / surfacearea()) * Color) * emission(); else - Emission = (Strength*Color)*emission(); + Emission = (Strength * Color) * emission(); } diff --git a/intern/cycles/kernel/osl/nodes/node_environment_texture.osl b/intern/cycles/kernel/shaders/node_environment_texture.osl similarity index 97% rename from intern/cycles/kernel/osl/nodes/node_environment_texture.osl rename to intern/cycles/kernel/shaders/node_environment_texture.osl index 3ad806781eb..bad62e56ab4 100644 --- a/intern/cycles/kernel/osl/nodes/node_environment_texture.osl +++ b/intern/cycles/kernel/shaders/node_environment_texture.osl @@ -28,7 +28,7 @@ shader node_environment_texture( { Color = (color)environment(filename, Vector, "alpha", Alpha); - if(color_space == "sRGB") + if (color_space == "sRGB") Color = color_srgb_to_scene_linear(Color); } diff --git a/intern/cycles/kernel/osl/nodes/node_fresnel.h b/intern/cycles/kernel/shaders/node_fresnel.h similarity index 100% rename from intern/cycles/kernel/osl/nodes/node_fresnel.h rename to intern/cycles/kernel/shaders/node_fresnel.h diff --git a/intern/cycles/kernel/osl/nodes/node_fresnel.osl b/intern/cycles/kernel/shaders/node_fresnel.osl similarity index 96% rename from intern/cycles/kernel/osl/nodes/node_fresnel.osl rename to intern/cycles/kernel/shaders/node_fresnel.osl index 3af4448b43f..e8d8e945f98 100644 --- a/intern/cycles/kernel/osl/nodes/node_fresnel.osl +++ b/intern/cycles/kernel/shaders/node_fresnel.osl @@ -25,7 +25,7 @@ shader node_fresnel( output float Fac = 0.0) { float f = max(IOR, 1.0 + 1e-5); - float eta = backfacing()? 1.0/f: f; + float eta = backfacing() ? 1.0 / f: f; Fac = fresnel_dielectric(I, Normal, eta); } diff --git a/intern/cycles/kernel/osl/nodes/node_gamma.osl b/intern/cycles/kernel/shaders/node_gamma.osl similarity index 100% rename from intern/cycles/kernel/osl/nodes/node_gamma.osl rename to intern/cycles/kernel/shaders/node_gamma.osl diff --git a/intern/cycles/kernel/osl/nodes/node_geometry.osl b/intern/cycles/kernel/shaders/node_geometry.osl similarity index 66% rename from intern/cycles/kernel/osl/nodes/node_geometry.osl rename to intern/cycles/kernel/shaders/node_geometry.osl index 9efc2a75c64..953c5d1fa2b 100644 --- a/intern/cycles/kernel/osl/nodes/node_geometry.osl +++ b/intern/cycles/kernel/shaders/node_geometry.osl @@ -32,19 +32,41 @@ shader node_geometry( { Position = P; Normal = NormalIn; - Tangent = normalize(dPdu); TrueNormal = Ng; Incoming = I; Parametric = point(u, v, 0.0); Backfacing = backfacing(); - if(bump_offset == "dx") { + if (bump_offset == "dx") { Position += Dx(Position); Parametric += Dx(Parametric); } - else if(bump_offset == "dy") { + else if (bump_offset == "dy") { Position += Dy(Position); Parametric += Dy(Parametric); } + + /* first try to get tangent attribute */ + vector T; + + if (getattribute("geom:tangent", T)) { + /* ensure orthogonal and normalized (interpolation breaks it) */ + T = transform("object", "world", T); + Tangent = cross(Normal, normalize(cross(T, Normal))); + } + else { + point generated; + + /* try to create spherical tangent from generated coordinates */ + if (getattribute("geom:generated", generated)) { + T = vector(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0); + T = transform("object", "world", T); + Tangent = cross(Normal, normalize(cross(T, Normal))); + } + else { + /* otherwise use surface derivatives */ + Tangent = normalize(dPdu); + } + } } diff --git a/intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl b/intern/cycles/kernel/shaders/node_glass_bsdf.osl similarity index 68% rename from intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl rename to intern/cycles/kernel/shaders/node_glass_bsdf.osl index 52743669c99..30b9d301f32 100644 --- a/intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_glass_bsdf.osl @@ -28,14 +28,16 @@ shader node_glass_bsdf( output closure color BSDF = diffuse(Normal)) { float f = max(IOR, 1.0 + 1e-5); - float eta = backfacing()? 1.0/f: f; + float eta = backfacing() ? 1.0 / f: f; float Fr = fresnel_dielectric(I, Normal, eta); - if(distribution == "Sharp") - BSDF = Color*(Fr*reflection(Normal) + (1.0-Fr)*refraction(Normal, eta)); - else if(distribution == "Beckmann") - BSDF = Color*(Fr*microfacet_beckmann(Normal, Roughness, eta) + (1.0-Fr)*microfacet_beckmann_refraction(Normal, Roughness, eta)); - else if(distribution == "GGX") - BSDF = Color*(Fr*microfacet_ggx(Normal, Roughness, eta) + (1.0-Fr)*microfacet_ggx_refraction(Normal, Roughness, eta)); + if (distribution == "Sharp") + BSDF = Color * (Fr * reflection(Normal) + (1.0 - Fr) * refraction(Normal, eta)); + else if (distribution == "Beckmann") + BSDF = Color * (Fr * microfacet_beckmann(Normal, Roughness) + + (1.0 - Fr) * microfacet_beckmann_refraction(Normal, Roughness, eta)); + else if (distribution == "GGX") + BSDF = Color * (Fr * microfacet_ggx(Normal, Roughness) + + (1.0 - Fr) * microfacet_ggx_refraction(Normal, Roughness, eta)); } diff --git a/intern/cycles/kernel/osl/nodes/node_glossy_bsdf.osl b/intern/cycles/kernel/shaders/node_glossy_bsdf.osl similarity index 80% rename from intern/cycles/kernel/osl/nodes/node_glossy_bsdf.osl rename to intern/cycles/kernel/shaders/node_glossy_bsdf.osl index 3890630e8a2..03340c74af5 100644 --- a/intern/cycles/kernel/osl/nodes/node_glossy_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_glossy_bsdf.osl @@ -26,12 +26,12 @@ shader node_glossy_bsdf( normal Normal = N, output closure color BSDF = diffuse(Normal)) { - if(distribution == "Sharp") - BSDF = Color*reflection(Normal); - else if(distribution == "Beckmann") - BSDF = Color*microfacet_beckmann(Normal, Roughness, 1.0); - else if(distribution == "GGX") - BSDF = Color*microfacet_ggx(Normal, Roughness, 1.0); + if (distribution == "Sharp") + BSDF = Color * reflection(Normal); + else if (distribution == "Beckmann") + BSDF = Color * microfacet_beckmann(Normal, Roughness); + else if (distribution == "GGX") + BSDF = Color * microfacet_ggx(Normal, Roughness); } diff --git a/intern/cycles/kernel/osl/nodes/node_gradient_texture.osl b/intern/cycles/kernel/shaders/node_gradient_texture.osl similarity index 68% rename from intern/cycles/kernel/osl/nodes/node_gradient_texture.osl rename to intern/cycles/kernel/shaders/node_gradient_texture.osl index a8dd65ae23b..ae7cfa51f59 100644 --- a/intern/cycles/kernel/osl/nodes/node_gradient_texture.osl +++ b/intern/cycles/kernel/shaders/node_gradient_texture.osl @@ -23,38 +23,39 @@ float gradient(point p, string type) { - float x, y; + float x, y, z; x = p[0]; y = p[1]; + z = p[2]; float result = 0.0; - if(type == "Linear") { - result = (1.0 + x)/2.0; + if (type == "Linear") { + result = x; } - else if(type == "Quadratic") { - float r = max((1.0 + x)/2.0, 0.0); - result = r*r; + else if (type == "Quadratic") { + float r = max(x, 0.0); + result = r * r; } - else if(type == "Easing") { - float r = min(max((1.0 + x)/2.0, 0.0), 1.0); - float t = r*r; + else if (type == "Easing") { + float r = min(max(x, 0.0), 1.0); + float t = r * r; - result = (3.0*t - 2.0*t*r); + result = (3.0 * t - 2.0 * t * r); } - else if(type == "Diagonal") { - result = (2.0 + x + y)/4.0; + else if (type == "Diagonal") { + result = (x + y) / 2.0; } - else if(type == "Radial") { - result = atan2(y, x)/(2*M_PI) + 0.5; + else if (type == "Radial") { + result = atan2(y, x) / (2.0 * M_PI) + 0.5; } else { - float r = max(1.0 - sqrt(x*x + y*y + p[2]*p[2]), 0.0); + float r = max(1.0 - sqrt(x * x + y * y + z * z), 0.0); - if(type == "Quadratic Sphere") - result = r*r; - else if(type == "Spherical") + if (type == "Quadratic Sphere") + result = r * r; + else if (type == "Spherical") result = r; } diff --git a/intern/cycles/kernel/osl/nodes/node_holdout.osl b/intern/cycles/kernel/shaders/node_holdout.osl similarity index 100% rename from intern/cycles/kernel/osl/nodes/node_holdout.osl rename to intern/cycles/kernel/shaders/node_holdout.osl diff --git a/intern/cycles/kernel/osl/nodes/node_hsv.osl b/intern/cycles/kernel/shaders/node_hsv.osl similarity index 100% rename from intern/cycles/kernel/osl/nodes/node_hsv.osl rename to intern/cycles/kernel/shaders/node_hsv.osl diff --git a/intern/cycles/kernel/shaders/node_image_texture.osl b/intern/cycles/kernel/shaders/node_image_texture.osl new file mode 100644 index 00000000000..6393605e6b5 --- /dev/null +++ b/intern/cycles/kernel/shaders/node_image_texture.osl @@ -0,0 +1,120 @@ +/* + * 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" +#include "node_color.h" + +color image_texture_lookup(string filename, string color_space, float u, float v, output float Alpha) +{ + color rgb = (color)texture(filename, u, 1.0 - v, "wrap", "periodic", "alpha", Alpha); + + if (color_space == "sRGB") + rgb = color_srgb_to_scene_linear(rgb); + + return rgb; +} + +shader node_image_texture( + point Vector = P, + string filename = "", + string color_space = "sRGB", + string projection = "Flat", + float projection_blend = 0.0, + output color Color = color(0.0, 0.0, 0.0), + output float Alpha = 1.0) +{ + if (projection == "Flat") { + Color = image_texture_lookup(filename, color_space, Vector[0], Vector[1], Alpha); + } + else if (projection == "Box") { + /* object space normal */ + vector Nob = transform("world", "object", N); + + /* project from direction vector to barycentric coordinates in triangles */ + Nob = vector(fabs(Nob[0]), fabs(Nob[1]), fabs(Nob[2])); + Nob /= (Nob[0] + Nob[1] + Nob[2]); + + /* basic idea is to think of this as a triangle, each corner representing + * one of the 3 faces of the cube. in the corners we have single textures, + * in between we blend between two textures, and in the middle we a blend + * between three textures. + * + * the Nxyz values are the barycentric coordinates in an equilateral + * triangle, which in case of blending, in the middle has a smaller + * equilateral triangle where 3 textures blend. this divides things into + * 7 zones, with an if () test for each zone */ + + vector weight = vector(0.0, 0.0, 0.0); + float blend = projection_blend; + float limit = 0.5*(1.0 + blend); + + /* first test for corners with single texture */ + if (Nob[0] > limit*(Nob[0] + Nob[1]) && Nob[0] > limit*(Nob[0] + Nob[2])) { + weight[0] = 1.0; + } + else if (Nob[1] > limit*(Nob[0] + Nob[1]) && Nob[1] > limit*(Nob[1] + Nob[2])) { + weight[1] = 1.0; + } + else if (Nob[2] > limit*(Nob[0] + Nob[2]) && Nob[2] > limit*(Nob[1] + Nob[2])) { + weight[2] = 1.0; + } + else if (blend > 0.0) { + /* in case of blending, test for mixes between two textures */ + if (Nob[2] < (1.0 - limit)*(Nob[1] + Nob[0])) { + weight[0] = Nob[0] / (Nob[0] + Nob[1]); + weight[0] = clamp((weight[0] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); + weight[1] = 1.0 - weight[0]; + } + else if (Nob[0] < (1.0 - limit)*(Nob[1] + Nob[2])) { + weight[1] = Nob[1] / (Nob[1] + Nob[2]); + weight[1] = clamp((weight[1] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); + weight[2] = 1.0 - weight[1]; + } + else if (Nob[1] < (1.0 - limit) * (Nob[0] + Nob[2])) { + weight[0] = Nob[0] / (Nob[0] + Nob[2]); + weight[0] = clamp((weight[0] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); + weight[2] = 1.0 - weight[0]; + } + else { + /* last case, we have a mix between three */ + weight[0] = ((2.0 - limit) * Nob[0] + (limit - 1.0)) / (2.0 * limit - 1.0); + weight[1] = ((2.0 - limit) * Nob[1] + (limit - 1.0)) / (2.0 * limit - 1.0); + weight[2] = ((2.0 - limit) * Nob[2] + (limit - 1.0)) / (2.0 * limit - 1.0); + } + } + + Color = color(0.0, 0.0, 0.0); + Alpha = 0.0; + + float tmp_alpha; + + if (weight[0] > 0.0) { + Color += weight[0]*image_texture_lookup(filename, color_space, Vector[1], Vector[2], tmp_alpha); + Alpha += weight[0]*tmp_alpha; + } + if (weight[1] > 0.0) { + Color += weight[1]*image_texture_lookup(filename, color_space, Vector[0], Vector[2], tmp_alpha); + Alpha += weight[1]*tmp_alpha; + } + if (weight[2] > 0.0) { + Color += weight[2]*image_texture_lookup(filename, color_space, Vector[1], Vector[0], tmp_alpha); + Alpha += weight[2]*tmp_alpha; + } + } +} + diff --git a/intern/cycles/kernel/osl/nodes/node_invert.osl b/intern/cycles/kernel/shaders/node_invert.osl similarity index 100% rename from intern/cycles/kernel/osl/nodes/node_invert.osl rename to intern/cycles/kernel/shaders/node_invert.osl diff --git a/intern/cycles/kernel/osl/nodes/node_blend_weight.osl b/intern/cycles/kernel/shaders/node_layer_weight.osl similarity index 71% rename from intern/cycles/kernel/osl/nodes/node_blend_weight.osl rename to intern/cycles/kernel/shaders/node_layer_weight.osl index d834819ef3a..3ea57f71786 100644 --- a/intern/cycles/kernel/osl/nodes/node_blend_weight.osl +++ b/intern/cycles/kernel/shaders/node_layer_weight.osl @@ -19,24 +19,28 @@ #include "stdosl.h" #include "node_fresnel.h" -shader node_blend_weight( - float Blend = 0.3, +shader node_layer_weight( + float Blend = 0.5, normal Normal = N, output float Fresnel = 0.0, output float Facing = 0.0) { - float f = max(1.0 - Blend, 1e-5); - Fresnel = fresnel_dielectric(I, Normal, backfacing()? f: 1.0/f); + float blend = Blend; + /* Fresnel */ + float eta = max(1.0 - Blend, 1e-5); + eta = backfacing() ? eta : 1.0 / eta; + Fresnel = fresnel_dielectric(I, Normal, eta); + + /* Facing */ Facing = abs(dot(I, Normal)); - if(Blend != 0.5) { - Blend = clamp(Blend, 0.0, 1.0); - Blend = (Blend < 0.5)? 2.0*Blend: 0.5/(1.0 - Blend); + if (blend != 0.5) { + blend = clamp(blend, 0.0, 1.0 - 1e-5); + blend = (blend < 0.5) ? 2.0 * blend : 0.5 / (1.0 - blend); - Facing = powf(Facing, Blend); + Facing = pow(Facing, blend); } Facing = 1.0 - Facing; } - diff --git a/intern/cycles/kernel/shaders/node_light_falloff.osl b/intern/cycles/kernel/shaders/node_light_falloff.osl new file mode 100644 index 00000000000..7ffa6fe0ffb --- /dev/null +++ b/intern/cycles/kernel/shaders/node_light_falloff.osl @@ -0,0 +1,46 @@ +/* + * Copyright 2012, 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_light_falloff( + float Strength = 0.0, + float Smooth = 0.0, + output float Quadratic = 0.0, + output float Linear = 0.0, + output float Constant = 0.0) +{ + float ray_length = 0.0; + float strength = Strength; + getattribute("path:ray_length", ray_length); + + if (Smooth > 0.0) { + float squared = ray_length*ray_length; + strength *= squared / (Smooth + squared); + } + + /* Quadratic */ + Quadratic = strength; + + /* Linear */ + Linear = (strength*ray_length); + + /* Constant */ + Constant = (strength*ray_length*ray_length); +} + diff --git a/intern/cycles/kernel/osl/nodes/node_light_path.osl b/intern/cycles/kernel/shaders/node_light_path.osl similarity index 91% rename from intern/cycles/kernel/osl/nodes/node_light_path.osl rename to intern/cycles/kernel/shaders/node_light_path.osl index 0ead20bf2bb..9e3f6c7b4a9 100644 --- a/intern/cycles/kernel/osl/nodes/node_light_path.osl +++ b/intern/cycles/kernel/shaders/node_light_path.osl @@ -25,7 +25,8 @@ shader node_light_path( output float IsGlossyRay = 0.0, output float IsSingularRay = 0.0, output float IsReflectionRay = 0.0, - output float IsTransmissionRay = 0.0) + output float IsTransmissionRay = 0.0, + output float RayLength = 0.0) { IsCameraRay = raytype("camera"); IsShadowRay = raytype("shadow"); @@ -34,5 +35,7 @@ shader node_light_path( IsSingularRay = raytype("singular"); IsReflectionRay = raytype("reflection"); IsTransmissionRay = raytype("refraction"); + + getattribute("path:ray_length", RayLength); } diff --git a/intern/cycles/kernel/osl/nodes/node_magic_texture.osl b/intern/cycles/kernel/shaders/node_magic_texture.osl similarity index 50% rename from intern/cycles/kernel/osl/nodes/node_magic_texture.osl rename to intern/cycles/kernel/shaders/node_magic_texture.osl index 0b6e980debc..e464b83bc9e 100644 --- a/intern/cycles/kernel/osl/nodes/node_magic_texture.osl +++ b/intern/cycles/kernel/shaders/node_magic_texture.osl @@ -21,56 +21,56 @@ /* Magic */ -color magic(point p, int n, float turbulence) +color magic(point p, int n, float distortion) { - float turb = turbulence/5.0; + float dist = distortion; - float x = sin((p[0] + p[1] + p[2])*5.0); - float y = cos((-p[0] + p[1] - p[2])*5.0); - float z = -cos((-p[0] - p[1] + p[2])*5.0); + float x = sin(( p[0] + p[1] + p[2]) * 5.0); + float y = cos((-p[0] + p[1] - p[2]) * 5.0); + float z = -cos((-p[0] - p[1] + p[2]) * 5.0); - if(n > 0) { - x *= turb; - y *= turb; - z *= turb; - y = -cos(x-y+z); - y *= turb; + if (n > 0) { + x *= dist; + y *= dist; + z *= dist; + y = -cos(x - y + z); + y *= dist; - if(n > 1) { - x= cos(x-y-z); - x *= turb; + if (n > 1) { + x = cos(x - y - z); + x *= dist; - if(n > 2) { - z= sin(-x-y-z); - z *= turb; + if (n > 2) { + z = sin(-x - y - z); + z *= dist; - if(n > 3) { - x= -cos(-x+y-z); - x *= turb; + if (n > 3) { + x = -cos(-x + y - z); + x *= dist; - if(n > 4) { - y= -sin(-x+y+z); - y *= turb; + if (n > 4) { + y = -sin(-x + y + z); + y *= dist; - if(n > 5) { - y= -cos(-x+y+z); - y *= turb; + if (n > 5) { + y = -cos(-x + y + z); + y *= dist; - if(n > 6) { - x= cos(x+y+z); - x *= turb; + if (n > 6) { + x = cos(x + y + z); + x *= dist; - if(n > 7) { - z= sin(x+y-z); - z *= turb; + if (n > 7) { + z = sin(x + y - z); + z *= dist; - if(n > 8) { - x= -cos(-x-y+z); - x *= turb; + if (n > 8) { + x = -cos(-x - y + z); + x *= dist; - if(n > 9) { - y= -sin(x-y+z); - y *= turb; + if (n > 9) { + y = -sin(x - y + z); + y *= dist; } } } @@ -82,11 +82,11 @@ color magic(point p, int n, float turbulence) } } - if(turb != 0.0) { - turb *= 2.0; - x /= turb; - y /= turb; - z /= turb; + if (dist != 0.0) { + dist *= 2.0; + x /= dist; + y /= dist; + z /= dist; } return color(0.5 - x, 0.5 - y, 0.5 - z); @@ -94,10 +94,11 @@ color magic(point p, int n, float turbulence) shader node_magic_texture( int Depth = 2, - float Turbulence = 5.0, + float Distortion = 5.0, + float Scale = 5.0, point Vector = P, output color Color = color(0.0, 0.0, 0.0)) { - Color = magic(Vector, Depth, Turbulence); + Color = magic(Vector * Scale, Depth, Distortion); } diff --git a/intern/cycles/kernel/osl/nodes/node_mapping.osl b/intern/cycles/kernel/shaders/node_mapping.osl similarity index 87% rename from intern/cycles/kernel/osl/nodes/node_mapping.osl rename to intern/cycles/kernel/shaders/node_mapping.osl index f342837d3c9..2e720edfc7e 100644 --- a/intern/cycles/kernel/osl/nodes/node_mapping.osl +++ b/intern/cycles/kernel/shaders/node_mapping.osl @@ -20,9 +20,9 @@ shader node_mapping( matrix Matrix = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - point Vector = point(0.0, 0.0, 0.0), - output point Vector_ = point(0.0, 0.0, 0.0)) + point VectorIn = point(0.0, 0.0, 0.0), + output point VectorOut = point(0.0, 0.0, 0.0)) { - Vector_ = transform(Matrix, Vector); + VectorOut = transform(Matrix, VectorIn); } diff --git a/intern/cycles/kernel/osl/nodes/node_math.osl b/intern/cycles/kernel/shaders/node_math.osl similarity index 75% rename from intern/cycles/kernel/osl/nodes/node_math.osl rename to intern/cycles/kernel/shaders/node_math.osl index 3327795286a..24dce898fd2 100644 --- a/intern/cycles/kernel/osl/nodes/node_math.osl +++ b/intern/cycles/kernel/shaders/node_math.osl @@ -22,20 +22,20 @@ float safe_divide(float a, float b) { float result; - if(b == 0.0) + if (b == 0.0) result = 0.0; else - result = a/b; + result = a / b; return result; } float safe_log(float a, float b) { - if(a < 0.0 || b < 0.0) + if (a < 0.0 || b < 0.0) return 0.0; - return log(a)/log(b); + return log(a) / log(b); } shader node_math( @@ -47,42 +47,42 @@ shader node_math( { /* OSL asin, acos, pow check for values that could give rise to nan */ - if(type == "Add") + if (type == "Add") Value = Value1 + Value2; - if(type == "Subtract") + if (type == "Subtract") Value = Value1 - Value2; - if(type == "Multiply") - Value = Value1*Value2; - if(type == "Divide") + if (type == "Multiply") + Value = Value1 * Value2; + if (type == "Divide") Value = safe_divide(Value1, Value2); - if(type == "Sine") + if (type == "Sine") Value = sin(Value1); - if(type == "Cosine") + if (type == "Cosine") Value = cos(Value1); - if(type == "Tangent") + if (type == "Tangent") Value = tan(Value1); - if(type == "Arcsine") + if (type == "Arcsine") Value = asin(Value1); - if(type == "Arccosine") + if (type == "Arccosine") Value = acos(Value1); - if(type == "Arctangent") + if (type == "Arctangent") Value = atan(Value1); - if(type == "Power") + if (type == "Power") Value = pow(Value1, Value2); - if(type == "Logarithm") + if (type == "Logarithm") Value = safe_log(Value1, Value2); - if(type == "Minimum") + if (type == "Minimum") Value = min(Value1, Value2); - if(type == "Maximum") + if (type == "Maximum") Value = max(Value1, Value2); - if(type == "Round") + if (type == "Round") Value = floor(Value1 + 0.5); - if(type == "Less Than") + if (type == "Less Than") Value = Value1 < Value2; - if(type == "Greater Than") + if (type == "Greater Than") Value = Value1 > Value2; - if(Clamp) + if (Clamp) Value = clamp(Value1, 0.0, 1.0); } diff --git a/intern/cycles/kernel/osl/nodes/node_mix.osl b/intern/cycles/kernel/shaders/node_mix.osl similarity index 64% rename from intern/cycles/kernel/osl/nodes/node_mix.osl rename to intern/cycles/kernel/shaders/node_mix.osl index 661e543fdd8..69e68e5ed15 100644 --- a/intern/cycles/kernel/osl/nodes/node_mix.osl +++ b/intern/cycles/kernel/shaders/node_mix.osl @@ -38,7 +38,7 @@ color node_mix_screen(float t, color col1, color col2) { float tm = 1.0 - t; - return color(1.0) - (color(tm) + t*(color(1.0) - col2))*(color(1.0) - col1); + return color(1.0) - (color(tm) + t * (color(1.0) - col2)) * (color(1.0) - col1); } color node_mix_overlay(float t, color col1, color col2) @@ -47,20 +47,20 @@ color node_mix_overlay(float t, color col1, color col2) color outcol = col1; - if(outcol[0] < 0.5) - outcol[0] *= tm + 2.0*t*col2[0]; + if (outcol[0] < 0.5) + outcol[0] *= tm + 2.0 * t * col2[0]; else - outcol[0] = 1.0 - (tm + 2.0*t*(1.0 - col2[0]))*(1.0 - outcol[0]); + outcol[0] = 1.0 - (tm + 2.0 * t * (1.0 - col2[0])) * (1.0 - outcol[0]); - if(outcol[1] < 0.5) - outcol[1] *= tm + 2.0*t*col2[1]; + if (outcol[1] < 0.5) + outcol[1] *= tm + 2.0 * t * col2[1]; else - outcol[1] = 1.0 - (tm + 2.0*t*(1.0 - col2[1]))*(1.0 - outcol[1]); + outcol[1] = 1.0 - (tm + 2.0 * t * (1.0 - col2[1])) * (1.0 - outcol[1]); - if(outcol[2] < 0.5) - outcol[2] *= tm + 2.0*t*col2[2]; + if (outcol[2] < 0.5) + outcol[2] *= tm + 2.0 * t * col2[2]; else - outcol[2] = 1.0 - (tm + 2.0*t*(1.0 - col2[2]))*(1.0 - outcol[2]); + outcol[2] = 1.0 - (tm + 2.0 * t * (1.0 - col2[2])) * (1.0 - outcol[2]); return outcol; } @@ -76,9 +76,9 @@ color node_mix_div(float t, color col1, color col2) color outcol = col1; - if(col2[0] != 0.0) outcol[0] = tm*outcol[0] + t*outcol[0]/col2[0]; - if(col2[1] != 0.0) outcol[1] = tm*outcol[1] + t*outcol[1]/col2[1]; - if(col2[2] != 0.0) outcol[2] = tm*outcol[2] + t*outcol[2]/col2[2]; + if (col2[0] != 0.0) outcol[0] = tm * outcol[0] + t * outcol[0] / col2[0]; + if (col2[1] != 0.0) outcol[1] = tm * outcol[1] + t * outcol[1] / col2[1]; + if (col2[2] != 0.0) outcol[2] = tm * outcol[2] + t * outcol[2] / col2[2]; return outcol; } @@ -90,41 +90,41 @@ color node_mix_diff(float t, color col1, color col2) color node_mix_dark(float t, color col1, color col2) { - return min(col1, col2*t); + return min(col1, col2 * t); } color node_mix_light(float t, color col1, color col2) { - return max(col1, col2*t); + return max(col1, col2 * t); } color node_mix_dodge(float t, color col1, color col2) { color outcol = col1; - if(outcol[0] != 0.0) { - float tmp = 1.0 - t*col2[0]; - if(tmp <= 0.0) + if (outcol[0] != 0.0) { + float tmp = 1.0 - t * col2[0]; + if (tmp <= 0.0) outcol[0] = 1.0; - else if((tmp = outcol[0]/tmp) > 1.0) + else if ((tmp = outcol[0] / tmp) > 1.0) outcol[0] = 1.0; else outcol[0] = tmp; } - if(outcol[1] != 0.0) { - float tmp = 1.0 - t*col2[1]; - if(tmp <= 0.0) + if (outcol[1] != 0.0) { + float tmp = 1.0 - t * col2[1]; + if (tmp <= 0.0) outcol[1] = 1.0; - else if((tmp = outcol[1]/tmp) > 1.0) + else if ((tmp = outcol[1] / tmp) > 1.0) outcol[1] = 1.0; else outcol[1] = tmp; } - if(outcol[2] != 0.0) { - float tmp = 1.0 - t*col2[2]; - if(tmp <= 0.0) + if (outcol[2] != 0.0) { + float tmp = 1.0 - t * col2[2]; + if (tmp <= 0.0) outcol[2] = 1.0; - else if((tmp = outcol[2]/tmp) > 1.0) + else if ((tmp = outcol[2] / tmp) > 1.0) outcol[2] = 1.0; else outcol[2] = tmp; @@ -139,32 +139,32 @@ color node_mix_burn(float t, color col1, color col2) color outcol = col1; - tmp = tm + t*col2[0]; - if(tmp <= 0.0) + tmp = tm + t * col2[0]; + if (tmp <= 0.0) outcol[0] = 0.0; - else if((tmp = (1.0 - (1.0 - outcol[0])/tmp)) < 0.0) + else if ((tmp = (1.0 - (1.0 - outcol[0]) / tmp)) < 0.0) outcol[0] = 0.0; - else if(tmp > 1.0) + else if (tmp > 1.0) outcol[0] = 1.0; else outcol[0] = tmp; - tmp = tm + t*col2[1]; - if(tmp <= 0.0) + tmp = tm + t * col2[1]; + if (tmp <= 0.0) outcol[1] = 0.0; - else if((tmp = (1.0 - (1.0 - outcol[1])/tmp)) < 0.0) + else if ((tmp = (1.0 - (1.0 - outcol[1]) / tmp)) < 0.0) outcol[1] = 0.0; - else if(tmp > 1.0) + else if (tmp > 1.0) outcol[1] = 1.0; else outcol[1] = tmp; - tmp = tm + t*col2[2]; - if(tmp <= 0.0) + tmp = tm + t * col2[2]; + if (tmp <= 0.0) outcol[2] = 0.0; - else if((tmp = (1.0 - (1.0 - outcol[2])/tmp)) < 0.0) + else if ((tmp = (1.0 - (1.0 - outcol[2]) / tmp)) < 0.0) outcol[2] = 0.0; - else if(tmp > 1.0) + else if (tmp > 1.0) outcol[2] = 1.0; else outcol[2] = tmp; @@ -177,7 +177,7 @@ color node_mix_hue(float t, color col1, color col2) color outcol = col1; color hsv2 = rgb_to_hsv(col2); - if(hsv2[1] != 0.0) { + if (hsv2[1] != 0.0) { color hsv = rgb_to_hsv(outcol); hsv[0] = hsv2[0]; color tmp = hsv_to_rgb(hsv); @@ -196,10 +196,10 @@ color node_mix_sat(float t, color col1, color col2) color hsv = rgb_to_hsv(outcol); - if(hsv[1] != 0.0) { + if (hsv[1] != 0.0) { color hsv2 = rgb_to_hsv(col2); - hsv[1] = tm*hsv[1] + t*hsv2[1]; + hsv[1] = tm * hsv[1] + t * hsv2[1]; outcol = hsv_to_rgb(hsv); } @@ -213,7 +213,7 @@ color node_mix_val(float t, color col1, color col2) color hsv = rgb_to_hsv(col1); color hsv2 = rgb_to_hsv(col2); - hsv[2] = tm*hsv[2] + t*hsv2[2]; + hsv[2] = tm * hsv[2] + t * hsv2[2]; return hsv_to_rgb(hsv); } @@ -223,7 +223,7 @@ color node_mix_color(float t, color col1, color col2) color outcol = col1; color hsv2 = rgb_to_hsv(col2); - if(hsv2[1] != 0.0) { + if (hsv2[1] != 0.0) { color hsv = rgb_to_hsv(outcol); hsv[0] = hsv2[0]; hsv[1] = hsv2[1]; @@ -239,30 +239,30 @@ color node_mix_soft(float t, color col1, color col2) { float tm = 1.0 - t; - color one= color(1.0); - color scr= one - (one - col2)*(one - col1); + color one = color(1.0); + color scr = one - (one - col2) * (one - col1); - return tm*col1 + t*((one - col1)*col2*col1 + col1*scr); + return tm * col1 + t * ((one - col1) * col2 * col1 + col1 * scr); } color node_mix_linear(float t, color col1, color col2) { color outcol = col1; - if(col2[0] > 0.5) - outcol[0]= col1[0] + t*(2.0*(col2[0] - 0.5)); + if (col2[0] > 0.5) + outcol[0] = col1[0] + t * (2.0 * (col2[0] - 0.5)); else - outcol[0]= col1[0] + t*(2.0*(col2[0]) - 1.0); + outcol[0] = col1[0] + t * (2.0 * (col2[0]) - 1.0); - if(col2[1] > 0.5) - outcol[1]= col1[1] + t*(2.0*(col2[1] - 0.5)); + if (col2[1] > 0.5) + outcol[1] = col1[1] + t * (2.0 * (col2[1] - 0.5)); else - outcol[1]= col1[1] + t*(2.0*(col2[1]) - 1.0); + outcol[1] = col1[1] + t * (2.0 * (col2[1]) - 1.0); - if(col2[2] > 0.5) - outcol[2]= col1[2] + t*(2.0*(col2[2] - 0.5)); + if (col2[2] > 0.5) + outcol[2] = col1[2] + t * (2.0 * (col2[2] - 0.5)); else - outcol[2]= col1[2] + t*(2.0*(col2[2]) - 1.0); + outcol[2] = col1[2] + t * (2.0 * (col2[2]) - 1.0); return outcol; } @@ -288,44 +288,44 @@ shader node_mix( { float t = clamp(Fac, 0.0, 1.0); - if(type == "Mix") + if (type == "Mix") Color = node_mix_blend(t, Color1, Color2); - if(type == "Add") + if (type == "Add") Color = node_mix_add(t, Color1, Color2); - if(type == "Multiply") + if (type == "Multiply") Color = node_mix_mul(t, Color1, Color2); - if(type == "Screen") + if (type == "Screen") Color = node_mix_screen(t, Color1, Color2); - if(type == "Overlay") + if (type == "Overlay") Color = node_mix_overlay(t, Color1, Color2); - if(type == "Subtract") + if (type == "Subtract") Color = node_mix_sub(t, Color1, Color2); - if(type == "Divide") + if (type == "Divide") Color = node_mix_div(t, Color1, Color2); - if(type == "Difference") + if (type == "Difference") Color = node_mix_diff(t, Color1, Color2); - if(type == "Darken") + if (type == "Darken") Color = node_mix_dark(t, Color1, Color2); - if(type == "Lighten") + if (type == "Lighten") Color = node_mix_light(t, Color1, Color2); - if(type == "Dodge") + if (type == "Dodge") Color = node_mix_dodge(t, Color1, Color2); - if(type == "Burn") + if (type == "Burn") Color = node_mix_burn(t, Color1, Color2); - if(type == "Hue") + if (type == "Hue") Color = node_mix_hue(t, Color1, Color2); - if(type == "Saturation") + if (type == "Saturation") Color = node_mix_sat(t, Color1, Color2); - if(type == "Value") + if (type == "Value") Color = node_mix_val (t, Color1, Color2); - if(type == "Color") + if (type == "Color") Color = node_mix_color(t, Color1, Color2); - if(type == "Soft Light") + if (type == "Soft Light") Color = node_mix_soft(t, Color1, Color2); - if(type == "Linear Light") + if (type == "Linear Light") Color = node_mix_linear(t, Color1, Color2); - if(Clamp) + if (Clamp) Color = node_mix_clamp(Color); } diff --git a/intern/cycles/kernel/osl/nodes/node_mix_closure.osl b/intern/cycles/kernel/shaders/node_mix_closure.osl similarity index 95% rename from intern/cycles/kernel/osl/nodes/node_mix_closure.osl rename to intern/cycles/kernel/shaders/node_mix_closure.osl index 1a377abd381..e28dd1fc436 100644 --- a/intern/cycles/kernel/osl/nodes/node_mix_closure.osl +++ b/intern/cycles/kernel/shaders/node_mix_closure.osl @@ -25,6 +25,6 @@ shader node_mix_closure( output closure color Closure = background()) { float t = clamp(Fac, 0.0, 1.0); - Closure = (1.0 - t)*Closure1 + t*Closure2; + Closure = (1.0 - t) * Closure1 + t * Closure2; } diff --git a/intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl b/intern/cycles/kernel/shaders/node_musgrave_texture.osl similarity index 69% rename from intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl rename to intern/cycles/kernel/shaders/node_musgrave_texture.osl index 3e1a6862660..71461b8fd79 100644 --- a/intern/cycles/kernel/osl/nodes/node_musgrave_texture.osl +++ b/intern/cycles/kernel/shaders/node_musgrave_texture.osl @@ -36,15 +36,15 @@ float noise_musgrave_fBm(point p, string basis, float H, float lacunarity, float float pwHL = pow(lacunarity, -H); int i; - for(i = 0; i < (int)octaves; i++) { - value += noise_basis(p, basis) * pwr; + for (i = 0; i < (int)octaves; i++) { + value += noise("perlin", p) * pwr; pwr *= pwHL; p *= lacunarity; } rmd = octaves - floor(octaves); - if(rmd != 0.0) - value += rmd * noise_basis(p, basis) * pwr; + if (rmd != 0.0) + value += rmd * noise("perlin", p) * pwr; return value; } @@ -64,15 +64,15 @@ float noise_musgrave_multi_fractal(point p, string basis, float H, float lacunar float pwHL = pow(lacunarity, -H); int i; - for(i = 0; i < (int)octaves; i++) { - value *= (pwr * noise_basis(p, basis) + 1.0); + for (i = 0; i < (int)octaves; i++) { + value *= (pwr * noise("perlin", p) + 1.0); pwr *= pwHL; p *= lacunarity; } rmd = octaves - floor(octaves); - if(rmd != 0.0) - value *= (rmd * pwr * noise_basis(p, basis) + 1.0); /* correct? */ + if (rmd != 0.0) + value *= (rmd * pwr * noise("perlin", p) + 1.0); /* correct? */ return value; } @@ -93,19 +93,19 @@ float noise_musgrave_hetero_terrain(point p, string basis, float H, float lacuna int i; /* first unscaled octave of function; later octaves are scaled */ - value = offset + noise_basis(p, basis); + value = offset + noise("perlin", p); p *= lacunarity; - for(i = 1; i < (int)octaves; i++) { - increment = (noise_basis(p, basis) + offset) * pwr * value; + for (i = 1; i < (int)octaves; i++) { + increment = (noise("perlin", p) + offset) * pwr * value; value += increment; pwr *= pwHL; p *= lacunarity; } rmd = octaves - floor(octaves); - if(rmd != 0.0) { - increment = (noise_basis(p, basis) + offset) * pwr * value; + if (rmd != 0.0) { + increment = (noise("perlin", p) + offset) * pwr * value; value += rmd * increment; } @@ -120,22 +120,23 @@ float noise_musgrave_hetero_terrain(point p, string basis, float H, float lacuna * offset: raises the terrain from `sea level' */ -float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, float lacunarity, float octaves, float offset, float gain) +float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, + float lacunarity, float octaves, float offset, float gain) { float result, signal, weight, rmd; float pwHL = pow(lacunarity, -H); float pwr = pwHL; int i; - result = noise_basis(p, basis) + offset; + result = noise("perlin", p) + offset; weight = gain * result; p *= lacunarity; - for(i = 1; (weight > 0.001) && (i < (int)octaves); i++) { - if(weight > 1.0) + for (i = 1; (weight > 0.001) && (i < (int)octaves); i++) { + if (weight > 1.0) weight = 1.0; - signal = (noise_basis(p, basis) + offset) * pwr; + signal = (noise("perlin", p) + offset) * pwr; pwr *= pwHL; result += weight * signal; weight *= gain * signal; @@ -143,8 +144,8 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, float } rmd = octaves - floor(octaves); - if(rmd != 0.0) - result += rmd * ((noise_basis(p, basis) + offset) * pwr); + if (rmd != 0.0) + result += rmd * ((noise("perlin", p) + offset) * pwr); return result; } @@ -157,22 +158,23 @@ float noise_musgrave_hybrid_multi_fractal(point p, string basis, float H, float * offset: raises the terrain from `sea level' */ -float noise_musgrave_ridged_multi_fractal(point p, string basis, float H, float lacunarity, float octaves, float offset, float gain) +float noise_musgrave_ridged_multi_fractal(point p, string basis, float H, + float lacunarity, float octaves, float offset, float gain) { float result, signal, weight; float pwHL = pow(lacunarity, -H); float pwr = pwHL; int i; - signal = offset - fabs(noise_basis(p, basis)); + signal = offset - fabs(noise("perlin", p)); signal *= signal; result = signal; weight = 1.0; - for(i = 1; i < (int)octaves; i++) { + for (i = 1; i < (int)octaves; i++) { p *= lacunarity; weight = clamp(signal * gain, 0.0, 1.0); - signal = offset - fabs(noise_basis(p, basis)); + signal = offset - fabs(noise("perlin", p)); signal *= signal; signal *= weight; result += signal * pwr; @@ -202,18 +204,18 @@ shader node_musgrave_texture( string Basis = "Perlin"; float intensity = 1.0; - point p = Vector*Scale; + point p = Vector * Scale; - if(Type == "Multifractal") - Fac = intensity*noise_musgrave_multi_fractal(p, Basis, dimension, lacunarity, octaves); - else if(Type == "fBM") - Fac = intensity*noise_musgrave_fBm(p, Basis, dimension, lacunarity, octaves); - else if(Type == "Hybrid Multifractal") - Fac = intensity*noise_musgrave_hybrid_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain); - else if(Type == "Ridged Multifractal") - Fac = intensity*noise_musgrave_ridged_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain); - else if(Type == "Hetero Terrain") - Fac = intensity*noise_musgrave_hetero_terrain(p, Basis, dimension, lacunarity, octaves, Offset); + if (Type == "Multifractal") + Fac = intensity * noise_musgrave_multi_fractal(p, Basis, dimension, lacunarity, octaves); + else if (Type == "fBM") + Fac = intensity * noise_musgrave_fBm(p, Basis, dimension, lacunarity, octaves); + else if (Type == "Hybrid Multifractal") + Fac = intensity * noise_musgrave_hybrid_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain); + else if (Type == "Ridged Multifractal") + Fac = intensity * noise_musgrave_ridged_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain); + else if (Type == "Hetero Terrain") + Fac = intensity * noise_musgrave_hetero_terrain(p, Basis, dimension, lacunarity, octaves, Offset); Color = color(Fac, Fac, Fac); } diff --git a/intern/cycles/kernel/osl/nodes/node_noise_texture.osl b/intern/cycles/kernel/shaders/node_noise_texture.osl similarity index 94% rename from intern/cycles/kernel/osl/nodes/node_noise_texture.osl rename to intern/cycles/kernel/shaders/node_noise_texture.osl index 1ddb4d8a08b..227b2bf8cea 100644 --- a/intern/cycles/kernel/osl/nodes/node_noise_texture.osl +++ b/intern/cycles/kernel/shaders/node_noise_texture.osl @@ -25,8 +25,8 @@ float noise(point p, string basis, float distortion, float detail, float fac, co { point r; int hard = 0; - - if(distortion != 0.0) { + + if (distortion != 0.0) { r[0] = noise_basis(p + point(13.5), basis) * distortion; r[1] = noise_basis(p, basis) * distortion; r[2] = noise_basis(p - point(13.5), basis) * distortion; @@ -51,6 +51,6 @@ shader node_noise_texture( output color Color = color(0.2, 0.2, 0.2)) { string Basis = "Perlin"; - Fac = noise(Vector*Scale, Basis, Distortion, Detail, Fac, Color); + Fac = noise(Vector * Scale, Basis, Distortion, Detail, Fac, Color); } diff --git a/intern/cycles/kernel/osl/nodes/node_normal.osl b/intern/cycles/kernel/shaders/node_normal.osl similarity index 100% rename from intern/cycles/kernel/osl/nodes/node_normal.osl rename to intern/cycles/kernel/shaders/node_normal.osl diff --git a/intern/cycles/kernel/osl/nodes/node_object_info.osl b/intern/cycles/kernel/shaders/node_object_info.osl similarity index 68% rename from intern/cycles/kernel/osl/nodes/node_object_info.osl rename to intern/cycles/kernel/shaders/node_object_info.osl index 21e50d8a43e..c3b1ff29f09 100644 --- a/intern/cycles/kernel/osl/nodes/node_object_info.osl +++ b/intern/cycles/kernel/shaders/node_object_info.osl @@ -19,15 +19,14 @@ #include "stdosl.h" shader node_object_info( - output point Location = point(0.0, 0.0, 0.0), - output float ObjectIndex = 0.0, - output float MaterialIndex = 0.0, - output float Random = 0.0 - ) + output point Location = point(0.0, 0.0, 0.0), + output float ObjectIndex = 0.0, + output float MaterialIndex = 0.0, + output float Random = 0.0) { - getattribute("std::object_location", Location); - getattribute("std::object_index", ObjectIndex); - getattribute("std::material_index", MaterialIndex); - getattribute("std::object_random", Random); + getattribute("object:location", Location); + getattribute("object:index", ObjectIndex); + getattribute("material:index", MaterialIndex); + getattribute("object:random", Random); } diff --git a/intern/cycles/kernel/osl/nodes/node_output_displacement.osl b/intern/cycles/kernel/shaders/node_output_displacement.osl similarity index 92% rename from intern/cycles/kernel/osl/nodes/node_output_displacement.osl rename to intern/cycles/kernel/shaders/node_output_displacement.osl index a6b452c532a..5649b879c5b 100644 --- a/intern/cycles/kernel/osl/nodes/node_output_displacement.osl +++ b/intern/cycles/kernel/shaders/node_output_displacement.osl @@ -20,6 +20,6 @@ displacement node_output_displacement(float Displacement = 0.0) { - P += N*Displacement*0.1; /* todo: get rid of this factor */ + P += N * Displacement * 0.1; /* todo: get rid of this factor */ } diff --git a/intern/cycles/kernel/osl/nodes/node_output_surface.osl b/intern/cycles/kernel/shaders/node_output_surface.osl similarity index 100% rename from intern/cycles/kernel/osl/nodes/node_output_surface.osl rename to intern/cycles/kernel/shaders/node_output_surface.osl diff --git a/intern/cycles/kernel/osl/nodes/node_output_volume.osl b/intern/cycles/kernel/shaders/node_output_volume.osl similarity index 100% rename from intern/cycles/kernel/osl/nodes/node_output_volume.osl rename to intern/cycles/kernel/shaders/node_output_volume.osl diff --git a/intern/cycles/kernel/osl/nodes/node_particle_info.osl b/intern/cycles/kernel/shaders/node_particle_info.osl similarity index 70% rename from intern/cycles/kernel/osl/nodes/node_particle_info.osl rename to intern/cycles/kernel/shaders/node_particle_info.osl index aadc2812865..5e59ad1a990 100644 --- a/intern/cycles/kernel/osl/nodes/node_particle_info.osl +++ b/intern/cycles/kernel/shaders/node_particle_info.osl @@ -25,15 +25,14 @@ shader node_particle_info( output point Location = point(0.0, 0.0, 0.0), output float Size = 0.0, output vector Velocity = point(0.0, 0.0, 0.0), - output vector AngularVelocity = point(0.0, 0.0, 0.0) - ) + output vector AngularVelocity = point(0.0, 0.0, 0.0)) { - getattribute("std::particle_index", Index); - getattribute("std::particle_age", Age); - getattribute("std::particle_lifetime", Lifetime); - getattribute("std::particle_location", Location); - getattribute("std::particle_size", Size); - getattribute("std::particle_velocity", Velocity); - getattribute("std::particle_angular_velocity", AngularVelocity); + getattribute("particle:index", Index); + getattribute("particle:age", Age); + getattribute("particle:lifetime", Lifetime); + getattribute("particle:location", Location); + getattribute("particle:size", Size); + getattribute("particle:velocity", Velocity); + getattribute("particle:angular_velocity", AngularVelocity); } diff --git a/intern/cycles/kernel/shaders/node_rgb_ramp.osl b/intern/cycles/kernel/shaders/node_rgb_ramp.osl new file mode 100644 index 00000000000..a128ebbd1cf --- /dev/null +++ b/intern/cycles/kernel/shaders/node_rgb_ramp.osl @@ -0,0 +1,43 @@ +/* + * 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" +#include "oslutil.h" + +shader node_rgb_ramp( + color ramp_color[RAMP_TABLE_SIZE] = {0.0}, + float ramp_alpha[RAMP_TABLE_SIZE] = {0.0}, + + float Fac = 0.0, + output color Color = color(0.0, 0.0, 0.0), + output float Alpha = 1.0) +{ + float f = clamp(Fac, 0.0, 1.0) * (RAMP_TABLE_SIZE - 1); + + int i = (int)f; + float t = f - (float)i; + + Color = ramp_color[i]; + Alpha = ramp_alpha[i]; + + if (t > 0.0) { + Color = (1.0 - t) * Color + t * ramp_color[i + 1]; + Alpha = (1.0 - t) * Alpha + t * ramp_alpha[i + 1]; + } +} + diff --git a/intern/cycles/kernel/osl/nodes/node_separate_rgb.osl b/intern/cycles/kernel/shaders/node_separate_rgb.osl similarity index 100% rename from intern/cycles/kernel/osl/nodes/node_separate_rgb.osl rename to intern/cycles/kernel/shaders/node_separate_rgb.osl diff --git a/intern/cycles/kernel/osl/nodes/node_ward_bsdf.osl b/intern/cycles/kernel/shaders/node_set_normal.osl similarity index 72% rename from intern/cycles/kernel/osl/nodes/node_ward_bsdf.osl rename to intern/cycles/kernel/shaders/node_set_normal.osl index 68db07109ed..27a4b2f5b8b 100644 --- a/intern/cycles/kernel/osl/nodes/node_ward_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_set_normal.osl @@ -1,5 +1,5 @@ /* - * Copyright 2011, Blender Foundation. + * Copyright 2012, Blender Foundation. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,13 +18,11 @@ #include "stdosl.h" -shader node_ward_bsdf( - color Color = color(0.8, 0.8, 0.8), - float RoughnessU = 0.0, - float RoughnessV = 0.0, - normal Normal = N, - output closure color BSDF = diffuse(Normal)) +surface node_set_normal( + normal Direction = N, + output normal Normal = N) { - BSDF = Color*ward(Normal, normalize(dPdu), RoughnessU, RoughnessV); + N = Direction; + Normal = Direction; } diff --git a/intern/cycles/kernel/osl/nodes/node_sky_texture.osl b/intern/cycles/kernel/shaders/node_sky_texture.osl similarity index 66% rename from intern/cycles/kernel/osl/nodes/node_sky_texture.osl rename to intern/cycles/kernel/shaders/node_sky_texture.osl index fdb9b1d9708..932fb1e2f17 100644 --- a/intern/cycles/kernel/osl/nodes/node_sky_texture.osl +++ b/intern/cycles/kernel/shaders/node_sky_texture.osl @@ -32,10 +32,10 @@ color xyY_to_xyz(float x, float y, float Y) { float X, Z; - if(y != 0.0) X = (x / y) * Y; + if (y != 0.0) X = (x / y) * Y; else X = 0.0; - if(y != 0.0 && Y != 0.0) Z = ((1.0 - x - y) / y) * Y; + if (y != 0.0 && Y != 0.0) Z = ((1.0 - x - y) / y) * Y; else Z = 0.0; return color(X, Y, Z); @@ -50,11 +50,11 @@ color xyz_to_rgb(float x, float y, float z) float sky_angle_between(float thetav, float phiv, float theta, float phi) { - float cospsi = sin(thetav)*sin(theta)*cos(phi - phiv) + cos(thetav)*cos(theta); + float cospsi = sin(thetav) * sin(theta) * cos(phi - phiv) + cos(thetav) * cos(theta); - if(cospsi > 1.0) + if (cospsi > 1.0) return 0.0; - if(cospsi < -1.0) + if (cospsi < -1.0) return M_PI; return acos(cospsi); @@ -70,7 +70,7 @@ float sky_perez_function(float lam[5], float theta, float gamma) float ctheta = cos(theta); float cgamma = cos(gamma); - return (1.0 + lam[0]*exp(lam[1] / ctheta)) * (1.0 + lam[2]*exp(lam[3]*gamma) + lam[4]*cgamma*cgamma); + return (1.0 + lam[0] * exp(lam[1] / ctheta)) * (1.0 + lam[2] * exp(lam[3] * gamma) + lam[4] * cgamma * cgamma); } color sky_xyz_radiance(KernelSunSky sunsky, vector dir) @@ -106,42 +106,42 @@ void precompute_sunsky(vector dir, float turbidity, output KernelSunSky sunsky) sunsky.phi = phi; sunsky.dir = dir; - float theta2 = theta*theta; - float theta3 = theta*theta*theta; + float theta2 = theta * theta; + float theta3 = theta * theta * theta; float T = turbidity; - float T2 = T*T; + float T2 = T * T; - float chi = (4.0/ 9.0- T / 120.0) * (M_PI - 2.0* theta); - sunsky.zenith_Y = (4.0453*T - 4.9710) * tan(chi) - 0.2155*T + 2.4192; + float chi = (4.0 / 9.0 - T / 120.0) * (M_PI - 2.0 * theta); + sunsky.zenith_Y = (4.0453 * T - 4.9710) * tan(chi) - 0.2155 * T + 2.4192; sunsky.zenith_Y *= 0.06; sunsky.zenith_x = - (0.00166* theta3 - 0.00375* theta2 + 0.00209* theta)*T2 + - (-0.02903* theta3 + 0.06377* theta2 - 0.03202* theta + 0.00394)*T + - (0.11693* theta3 - 0.21196* theta2 + 0.06052* theta + 0.25886); + ( 0.00166 * theta3 - 0.00375 * theta2 + 0.00209 * theta) * T2 + + (-0.02903 * theta3 + 0.06377 * theta2 - 0.03202 * theta + 0.00394) * T + + ( 0.11693 * theta3 - 0.21196 * theta2 + 0.06052 * theta + 0.25886); sunsky.zenith_y = - (0.00275* theta3 - 0.00610* theta2 + 0.00317* theta)*T2 + - (-0.04214* theta3 + 0.08970* theta2 - 0.04153* theta + 0.00516)*T + - (0.15346* theta3 - 0.26756* theta2 + 0.06670* theta + 0.26688); + ( 0.00275 * theta3 - 0.00610 * theta2 + 0.00317 * theta) * T2 + + (-0.04214 * theta3 + 0.08970 * theta2 - 0.04153 * theta + 0.00516) * T + + ( 0.15346 * theta3 - 0.26756 * theta2 + 0.06670 * theta + 0.26688); - sunsky.perez_Y[0] = (0.1787*T - 1.4630); - sunsky.perez_Y[1] = (-0.3554*T + 0.4275); - sunsky.perez_Y[2] = (-0.0227*T + 5.3251); - sunsky.perez_Y[3] = (0.1206*T - 2.5771); - sunsky.perez_Y[4] = (-0.0670*T + 0.3703); + sunsky.perez_Y[0] = ( 0.1787 * T - 1.4630); + sunsky.perez_Y[1] = (-0.3554 * T + 0.4275); + sunsky.perez_Y[2] = (-0.0227 * T + 5.3251); + sunsky.perez_Y[3] = ( 0.1206 * T - 2.5771); + sunsky.perez_Y[4] = (-0.0670 * T + 0.3703); - sunsky.perez_x[0] = (-0.0193*T - 0.2592); - sunsky.perez_x[1] = (-0.0665*T + 0.0008); - sunsky.perez_x[2] = (-0.0004*T + 0.2125); - sunsky.perez_x[3] = (-0.0641*T - 0.8989); - sunsky.perez_x[4] = (-0.0033*T + 0.0452); + sunsky.perez_x[0] = (-0.0193 * T - 0.2592); + sunsky.perez_x[1] = (-0.0665 * T + 0.0008); + sunsky.perez_x[2] = (-0.0004 * T + 0.2125); + sunsky.perez_x[3] = (-0.0641 * T - 0.8989); + sunsky.perez_x[4] = (-0.0033 * T + 0.0452); - sunsky.perez_y[0] = (-0.0167*T - 0.2608); - sunsky.perez_y[1] = (-0.0950*T + 0.0092); - sunsky.perez_y[2] = (-0.0079*T + 0.2102); - sunsky.perez_y[3] = (-0.0441*T - 1.6537); - sunsky.perez_y[4] = (-0.0109*T + 0.0529); + sunsky.perez_y[0] = (-0.0167 * T - 0.2608); + sunsky.perez_y[1] = (-0.0950 * T + 0.0092); + sunsky.perez_y[2] = (-0.0079 * T + 0.2102); + sunsky.perez_y[3] = (-0.0441 * T - 1.6537); + sunsky.perez_y[4] = (-0.0109 * T + 0.0529); sunsky.zenith_Y /= sky_perez_function(sunsky.perez_Y, 0, theta); sunsky.zenith_x /= sky_perez_function(sunsky.perez_x, 0, theta); diff --git a/intern/cycles/kernel/osl/nodes/node_texture.h b/intern/cycles/kernel/shaders/node_texture.h similarity index 94% rename from intern/cycles/kernel/osl/nodes/node_texture.h rename to intern/cycles/kernel/shaders/node_texture.h index b00bf6ab31f..1b3ba8207ab 100644 --- a/intern/cycles/kernel/osl/nodes/node_texture.h +++ b/intern/cycles/kernel/shaders/node_texture.h @@ -156,7 +156,7 @@ float noise_basis(point p, string basis) float result = 0.0; if (basis == "Perlin") - result = noise(p); + result = noise(p); /* returns perlin noise in range 0..1 */ if (basis == "Voronoi F1") result = voronoi_F1S(p); if (basis == "Voronoi F2") @@ -235,21 +235,21 @@ float noise_turbulence(point p, string basis, float details, int hard) float rmd = octaves - floor(octaves); - if(rmd != 0.0) { - float t = noise_basis(fscale*p, basis); + if (rmd != 0.0) { + float t = noise_basis(fscale * p, basis); - if(hard) - t = fabs(2.0*t - 1.0); + if (hard) + t = fabs(2.0 * t - 1.0); float sum2 = sum + t*amp; - sum *= ((float)(1 << n)/(float)((1 << (n+1)) - 1)); - sum2 *= ((float)(1 << (n+1))/(float)((1 << (n+2)) - 1)); + sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1)); + sum2 *= ((float)(1 << (n + 1)) / (float)((1 << (n + 2)) - 1)); return (1.0 - rmd)*sum + rmd*sum2; } else { - sum *= ((float)(1 << n)/(float)((1 << (n+1)) - 1)); + sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1)); return sum; } } diff --git a/intern/cycles/kernel/osl/nodes/node_texture_coordinate.osl b/intern/cycles/kernel/shaders/node_texture_coordinate.osl similarity index 72% rename from intern/cycles/kernel/osl/nodes/node_texture_coordinate.osl rename to intern/cycles/kernel/shaders/node_texture_coordinate.osl index 2acf72aef54..791838dfffe 100644 --- a/intern/cycles/kernel/osl/nodes/node_texture_coordinate.osl +++ b/intern/cycles/kernel/shaders/node_texture_coordinate.osl @@ -19,8 +19,9 @@ #include "stdosl.h" shader node_texture_coordinate( - normal Normal = N, + normal NormalIn = N, int is_background = 0, + int from_dupli = 0, string bump_offset = "center", output point Generated = point(0.0, 0.0, 0.0), @@ -28,36 +29,50 @@ shader node_texture_coordinate( output point Object = point(0.0, 0.0, 0.0), output point Camera = point(0.0, 0.0, 0.0), output point Window = point(0.0, 0.0, 0.0), + output normal Normal = normal(0.0, 0.0, 0.0), output point Reflection = point(0.0, 0.0, 0.0)) { - if(is_background) { + if (is_background) { Generated = P; UV = point(0.0, 0.0, 0.0); Object = P; point Pcam = transform("camera", "world", point(0, 0, 0)); Camera = transform("camera", P + Pcam); Window = transform("NDC", P + Pcam); + Normal = NormalIn; Reflection = I; } else { - getattribute("std::generated", Generated); - getattribute("std::uv", UV); + if (from_dupli) { + getattribute("geom:dupli_generated", Generated); + getattribute("geom:dupli_uv", UV); + } + else { + getattribute("geom:generated", Generated); + getattribute("geom:uv", UV); + } + Object = transform("object", P); Camera = transform("camera", P); Window = transform("NDC", P); - Reflection = reflect(I, Normal); + Normal = transform("world", "object", NormalIn); + Reflection = reflect(I, NormalIn); } - if(bump_offset == "dx") { - Generated += Dx(Generated); - UV += Dx(UV); + if (bump_offset == "dx") { + if (!from_dupli) { + Generated += Dx(Generated); + UV += Dx(UV); + } Object += Dx(Object); Camera += Dx(Camera); Window += Dx(Window); } - else if(bump_offset == "dy") { - Generated += Dy(Generated); - UV += Dy(UV); + else if (bump_offset == "dy") { + if (!from_dupli) { + Generated += Dy(Generated); + UV += Dy(UV); + } Object += Dy(Object); Camera += Dy(Camera); Window += Dy(Window); diff --git a/intern/cycles/kernel/osl/nodes/node_translucent_bsdf.osl b/intern/cycles/kernel/shaders/node_translucent_bsdf.osl similarity index 96% rename from intern/cycles/kernel/osl/nodes/node_translucent_bsdf.osl rename to intern/cycles/kernel/shaders/node_translucent_bsdf.osl index 9acd46756d2..e7efe73700c 100644 --- a/intern/cycles/kernel/osl/nodes/node_translucent_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_translucent_bsdf.osl @@ -23,6 +23,6 @@ shader node_translucent_bsdf( normal Normal = N, output closure color BSDF = diffuse(Normal)) { - BSDF = Color*translucent(Normal); + BSDF = Color * translucent(Normal); } diff --git a/intern/cycles/kernel/osl/nodes/node_transparent_bsdf.osl b/intern/cycles/kernel/shaders/node_transparent_bsdf.osl similarity index 96% rename from intern/cycles/kernel/osl/nodes/node_transparent_bsdf.osl rename to intern/cycles/kernel/shaders/node_transparent_bsdf.osl index b347bfb116b..875bce3f16c 100644 --- a/intern/cycles/kernel/osl/nodes/node_transparent_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_transparent_bsdf.osl @@ -23,6 +23,6 @@ shader node_transparent_bsdf( normal Normal = N, output closure color BSDF = diffuse(Normal)) { - BSDF = Color*transparent(); + BSDF = Color * transparent(); } diff --git a/intern/cycles/kernel/osl/nodes/node_value.osl b/intern/cycles/kernel/shaders/node_value.osl similarity index 100% rename from intern/cycles/kernel/osl/nodes/node_value.osl rename to intern/cycles/kernel/shaders/node_value.osl diff --git a/intern/cycles/kernel/osl/nodes/node_vector_math.osl b/intern/cycles/kernel/shaders/node_vector_math.osl similarity index 81% rename from intern/cycles/kernel/osl/nodes/node_vector_math.osl rename to intern/cycles/kernel/shaders/node_vector_math.osl index 9e0f0b60522..f22a6e8441a 100644 --- a/intern/cycles/kernel/osl/nodes/node_vector_math.osl +++ b/intern/cycles/kernel/shaders/node_vector_math.osl @@ -25,27 +25,27 @@ shader node_vector_math( output float Value = 0.0, output vector Vector = vector(0.0, 0.0, 0.0)) { - if(type == "Add") { + if (type == "Add") { Vector = Vector1 + Vector2; - Value = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2]))/3.0; + Value = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2])) / 3.0; } - if(type == "Subtract") { + if (type == "Subtract") { Vector = Vector1 - Vector2; - Value = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2]))/3.0; + Value = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2])) / 3.0; } - if(type == "Average") { + if (type == "Average") { Value = length(Vector1 + Vector2); Vector = normalize(Vector1 + Vector2); } - if(type == "Dot Product") { + if (type == "Dot Product") { Value = dot(Vector1, Vector2); } - if(type == "Cross Product") { + if (type == "Cross Product") { vector c = cross(Vector1, Vector2); Value = length(c); Vector = normalize(c); } - if(type == "Normalize") { + if (type == "Normalize") { Value = length(Vector1); Vector = normalize(Vector1); } diff --git a/intern/cycles/kernel/osl/nodes/node_velvet_bsdf.osl b/intern/cycles/kernel/shaders/node_velvet_bsdf.osl similarity index 95% rename from intern/cycles/kernel/osl/nodes/node_velvet_bsdf.osl rename to intern/cycles/kernel/shaders/node_velvet_bsdf.osl index 5e0cae8cbd1..3aa662bdd08 100644 --- a/intern/cycles/kernel/osl/nodes/node_velvet_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_velvet_bsdf.osl @@ -27,6 +27,6 @@ shader node_velvet_bsdf( { float sigma = clamp(Sigma, 0.0, 1.0); - BSDF = Color*ashikhmin_velvet(Normal, sigma, 1.0); + BSDF = Color * ashikhmin_velvet(Normal, sigma); } diff --git a/intern/cycles/kernel/shaders/node_voronoi_texture.osl b/intern/cycles/kernel/shaders/node_voronoi_texture.osl new file mode 100644 index 00000000000..a44df00a267 --- /dev/null +++ b/intern/cycles/kernel/shaders/node_voronoi_texture.osl @@ -0,0 +1,48 @@ +/* + * 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" +#include "node_texture.h" + +/* Voronoi */ + +shader node_voronoi_texture( + string Coloring = "Intensity", + float Scale = 5.0, + point Vector = P, + output float Fac = 0.0, + output color Color = color(0.0, 0.0, 0.0)) +{ + /* compute distance and point coordinate of 4 nearest neighbours */ + float da[4]; + point pa[4]; + + voronoi(Vector * Scale, "Distance Squared", 1.0, da, pa); + + /* Colored output */ + if (Coloring == "Intensity") { + Fac = fabs(da[0]); + Color = color(Fac); + } + else { + Color = cellnoise_color(pa[0]); + Fac = (Color[0] + Color[1] + Color[2]) * (1.0 / 3.0); + + } +} + diff --git a/intern/cycles/kernel/shaders/node_ward_bsdf.osl b/intern/cycles/kernel/shaders/node_ward_bsdf.osl new file mode 100644 index 00000000000..03a0477038e --- /dev/null +++ b/intern/cycles/kernel/shaders/node_ward_bsdf.osl @@ -0,0 +1,51 @@ +/* + * 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_ward_bsdf( + color Color = color(0.8, 0.8, 0.8), + float Roughness = 0.0, + float Anisotropy = 0.0, + float Rotation = 0.0, + normal Normal = N, + normal Tangent = normalize(dPdu), + output closure color BSDF = diffuse(Normal)) +{ + /* rotate tangent around normal */ + vector T = Tangent; + + if(Rotation != 0.0) + T = rotate(T, Rotation*2.0*M_PI, point(0.0, 0.0, 0.0), Normal); + + /* compute roughness */ + float RoughnessU, RoughnessV; + float aniso = clamp(Anisotropy, -0.99, 0.99); + + if(aniso < 0.0) { + RoughnessU = Roughness*(1.0 + aniso); + RoughnessV = Roughness/(1.0 + aniso); + } + else { + RoughnessU = Roughness/(1.0 - aniso); + RoughnessV = Roughness*(1.0 - aniso); + } + + BSDF = Color * ward(Normal, T, RoughnessU, RoughnessV); +} + diff --git a/intern/cycles/kernel/osl/nodes/node_wave_texture.osl b/intern/cycles/kernel/shaders/node_wave_texture.osl similarity index 86% rename from intern/cycles/kernel/osl/nodes/node_wave_texture.osl rename to intern/cycles/kernel/shaders/node_wave_texture.osl index db53faaf94b..79b8a8885d1 100644 --- a/intern/cycles/kernel/osl/nodes/node_wave_texture.osl +++ b/intern/cycles/kernel/shaders/node_wave_texture.osl @@ -30,15 +30,15 @@ float wave(point p, float scale, string type, float detail, float distortion, fl float result = 0.0; float n = 0.0; - if(type == "Bands") { - n = (x + y + z)*10.0; + if (type == "Bands") { + n = (x + y + z) * 10.0; } - else if(type == "Rings") { - n = (sqrt(x*x + y*y + z*z)*20.0); + else if (type == "Rings") { + n = (sqrt(x * x + y * y + z * z) * 20.0); } - - if(distortion != 0.0) { - n = n +(distortion * noise_turbulence(p*dscale, "Perlin", detail, 0)); + + if (distortion != 0.0) { + n = n + (distortion * noise_turbulence(p * dscale, "Perlin", detail, 0)); } result = noise_wave("Sine", n); diff --git a/intern/cycles/kernel/osl/nodes/oslutil.h b/intern/cycles/kernel/shaders/oslutil.h similarity index 98% rename from intern/cycles/kernel/osl/nodes/oslutil.h rename to intern/cycles/kernel/shaders/oslutil.h index 08611187a3c..6c91684d9a6 100644 --- a/intern/cycles/kernel/osl/nodes/oslutil.h +++ b/intern/cycles/kernel/shaders/oslutil.h @@ -29,6 +29,9 @@ #ifndef CCL_OSLUTIL_H #define CCL_OSLUTIL_H +/* NB: must match the value in kernel_types.h */ +#define RAMP_TABLE_SIZE 256 + // Return wireframe opacity factor [0, 1] given a geometry type in // ("triangles", "polygons" or "patches"), and a line_width in raster // or world space depending on the last (raster) boolean argument. diff --git a/intern/cycles/kernel/osl/nodes/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h similarity index 78% rename from intern/cycles/kernel/osl/nodes/stdosl.h rename to intern/cycles/kernel/shaders/stdosl.h index e5accf4eb54..4237291c7a4 100644 --- a/intern/cycles/kernel/osl/nodes/stdosl.h +++ b/intern/cycles/kernel/shaders/stdosl.h @@ -434,81 +434,18 @@ string concat (string a, string b, string c, string d, string e, string f) { closure color diffuse(normal N) BUILTIN; closure color oren_nayar(normal N, float sigma) BUILTIN; closure color translucent(normal N) BUILTIN; -closure color reflection(normal N, float eta) BUILTIN; -closure color reflection(normal N) { return reflection (N, 0.0); } +closure color reflection(normal N) BUILTIN; closure color refraction(normal N, float eta) BUILTIN; -closure color dielectric(normal N, float eta) BUILTIN; closure color transparent() BUILTIN; -closure color microfacet_ggx(normal N, float ag, float eta) BUILTIN; +closure color microfacet_ggx(normal N, float ag) BUILTIN; closure color microfacet_ggx_refraction(normal N, float ag, float eta) BUILTIN; -closure color microfacet_beckmann(normal N, float ab, float eta) BUILTIN; +closure color microfacet_beckmann(normal N, float ab) BUILTIN; closure color microfacet_beckmann_refraction(normal N, float ab, float eta) BUILTIN; closure color ward(normal N, vector T,float ax, float ay) BUILTIN; -closure color phong(normal N, float exponent) BUILTIN; -closure color phong_ramp(normal N, float exponent, color colors[8]) BUILTIN; -closure color hair_diffuse(vector T) BUILTIN; -closure color hair_specular(vector T, float offset, float exponent) BUILTIN; -closure color ashikhmin_velvet(normal N, float sigma, float eta) BUILTIN; -closure color westin_backscatter(normal N, float roughness) BUILTIN; -closure color westin_sheen(normal N, float edginess) BUILTIN; -closure color bssrdf_cubic(color radius) BUILTIN; -closure color emission(float inner_angle, float outer_angle) BUILTIN; -closure color emission(float outer_angle) BUILTIN; +closure color ashikhmin_velvet(normal N, float sigma) BUILTIN; closure color emission() BUILTIN; -closure color debug(string tag) BUILTIN; closure color background() BUILTIN; closure color holdout() BUILTIN; -closure color subsurface(float eta, float g, color mfp, color albedo) BUILTIN; - -closure color cloth(normal N, float s, float t, float dsdx, float dtdx, float dsdy, float dtdy, - float area_scaled, vector dPdu, color diff_warp_col, color diff_weft_col, - color spec_warp_col, color spec_weft_col, float fresnel_warp, float fresnel_weft, - float spread_x_mult, float spread_y_mult, int pattern, float pattern_angle, - float warp_width_scale, float weft_width_scale, float thread_count_mult_u, - float thread_count_mult_v) BUILTIN; -closure color cloth_specular(normal N, color spec_col[4], float eta[4], int thread_pattern[4], - float pattern_weight[4], int current_thread, float brdf_interp, - float btf_interp, float uux, float vvx, float area_scaled, vector dPdu, - float eccentricity[4], float angle[4], float Kx[4], float Ky[4], - float Sx[4], float Sy[4]) BUILTIN; -closure color fakefur_diffuse(normal N, vector T, float fur_reflectivity, float fur_transmission, - float shadow_start, float shadow_end, float fur_attenuation, float fur_density, - float fur_avg_radius, float fur_length, float fur_shadow_fraction) BUILTIN; -closure color fakefur_specular(normal N, vector T, float offset, float exp, float fur_reflectivity, - float fur_transmission, float shadow_start, float shadow_end, - float fur_attenuation, float fur_density, float fur_avg_radius, - float fur_length, float fur_shadow_fraction) BUILTIN; - -closure color fakefur_skin(vector N, vector T, float fur_reflectivity, float fur_transmission, - float shadow_start, float shadow_end, float fur_attenuation, float fur_density, - float fur_avg_radius, float fur_length) BUILTIN; - - -closure color cloth(normal N, float s, float t, color diff_warp, color diff_weft, - color spec_warp, color spec_weft, float fresnel_warp, float fresnel_weft, - float spread_x_mult, float spread_y_mult, int pattern, float pattern_angle, - float warp_width_scale, float weft_width_scale, float thread_count_mult_u, - float thread_count_mult_v) -{ - - return cloth(N, s, t, Dx(s), Dx(t), Dy(s), Dy(t), area(P), dPdu, diff_warp, diff_weft, spec_warp, spec_weft, - fresnel_warp, fresnel_weft, spread_x_mult, spread_y_mult, pattern, pattern_angle, - warp_width_scale, weft_width_scale, thread_count_mult_u, thread_count_mult_v); -} - -closure color cloth(normal N, float s, float t, color diff_warp, color diff_weft, - color spec_warp, color spec_weft, float fresnel_warp, float fresnel_weft, - float spread_x_mult, float spread_y_mult, int pattern, float pattern_angle, - float warp_width_scale, float weft_width_scale, float thread_count_mult_u, - float thread_count_mult_v, string tok, string val) -{ - - return cloth(N, s, t, Dx(s), Dx(t), Dy(s), Dy(t), area(P), dPdu, diff_warp, diff_weft, spec_warp, spec_weft, - fresnel_warp, fresnel_weft, spread_x_mult, spread_y_mult, pattern, pattern_angle, - warp_width_scale, weft_width_scale, thread_count_mult_u, thread_count_mult_v, tok, val); -} - - // Renderer state int raytype (string typename) BUILTIN; diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 5b0f192ea47..698ef5016f0 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -82,6 +82,25 @@ __device_inline void stack_store_float(float *stack, uint a, float f) stack[a] = f; } +__device_inline int stack_load_int(float *stack, uint a) +{ + kernel_assert(a < SVM_STACK_SIZE); + + return __float_as_int(stack[a]); +} + +__device_inline float stack_load_int_default(float *stack, uint a, uint value) +{ + return (a == (uint)SVM_STACK_INVALID)? (int)value: stack_load_int(stack, a); +} + +__device_inline void stack_store_int(float *stack, uint a, int i) +{ + kernel_assert(a < SVM_STACK_SIZE); + + stack[a] = __int_as_float(i); +} + __device_inline bool stack_valid(uint a) { return a != (uint)SVM_STACK_INVALID; @@ -185,7 +204,7 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT break; } case NODE_CLOSURE_BSDF: - svm_node_closure_bsdf(kg, sd, stack, node, randb, path_flag); + svm_node_closure_bsdf(kg, sd, stack, node, randb, path_flag, &offset); break; case NODE_CLOSURE_EMISSION: svm_node_closure_emission(sd, stack, node); @@ -261,14 +280,14 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT svm_node_camera(kg, sd, stack, node.y, node.z, node.w); break; case NODE_GEOMETRY: - svm_node_geometry(sd, stack, node.y, node.z); + svm_node_geometry(kg, sd, stack, node.y, node.z); break; #ifdef __EXTRA_NODES__ case NODE_GEOMETRY_BUMP_DX: - svm_node_geometry_bump_dx(sd, stack, node.y, node.z); + svm_node_geometry_bump_dx(kg, sd, stack, node.y, node.z); break; case NODE_GEOMETRY_BUMP_DY: - svm_node_geometry_bump_dy(sd, stack, node.y, node.z); + svm_node_geometry_bump_dy(kg, sd, stack, node.y, node.z); break; case NODE_LIGHT_PATH: svm_node_light_path(sd, stack, node.y, node.z, path_flag); @@ -334,7 +353,7 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT svm_node_set_displacement(sd, stack, node.y); break; case NODE_SET_BUMP: - svm_node_set_bump(sd, stack, node.y, node.z, node.w); + svm_node_set_bump(kg, sd, stack, node); break; case NODE_MATH: svm_node_math(kg, sd, stack, node.y, node.z, node.w, &offset); @@ -362,6 +381,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT case NODE_TEX_COORD_BUMP_DY: svm_node_tex_coord_bump_dy(kg, sd, stack, node.y, node.z); break; + case NODE_CLOSURE_SET_NORMAL: + svm_node_set_normal(kg, sd, stack, node.y, node.z ); + break; #endif case NODE_EMISSION_SET_WEIGHT_TOTAL: svm_node_emission_set_weight_total(kg, sd, node.y, node.z, node.w); @@ -376,7 +398,7 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT case NODE_LIGHT_FALLOFF: svm_node_light_falloff(sd, stack, node); break; -#endif +#endif case NODE_END: default: #ifndef __MULTI_CLOSURE__ diff --git a/intern/cycles/kernel/svm/svm_bsdf.h b/intern/cycles/kernel/svm/svm_bsdf.h index 411916f8aa0..07c20231d54 100644 --- a/intern/cycles/kernel/svm/svm_bsdf.h +++ b/intern/cycles/kernel/svm/svm_bsdf.h @@ -16,17 +16,17 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "bsdf_ashikhmin_velvet.h" -#include "bsdf_diffuse.h" -#include "bsdf_oren_nayar.h" -#include "bsdf_microfacet.h" -#include "bsdf_reflection.h" -#include "bsdf_refraction.h" -#include "bsdf_transparent.h" +#include "../closure/bsdf_ashikhmin_velvet.h" +#include "../closure/bsdf_diffuse.h" +#include "../closure/bsdf_oren_nayar.h" +#include "../closure/bsdf_microfacet.h" +#include "../closure/bsdf_reflection.h" +#include "../closure/bsdf_refraction.h" +#include "../closure/bsdf_transparent.h" #ifdef __DPDU__ -#include "bsdf_ward.h" +#include "../closure/bsdf_ward.h" #endif -#include "bsdf_westin.h" +#include "../closure/bsdf_westin.h" CCL_NAMESPACE_BEGIN @@ -36,45 +36,57 @@ __device int svm_bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, floa switch(sc->type) { case CLOSURE_BSDF_DIFFUSE_ID: - label = bsdf_diffuse_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_diffuse_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; #ifdef __SVM__ case CLOSURE_BSDF_OREN_NAYAR_ID: - label = bsdf_oren_nayar_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_oren_nayar_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_TRANSLUCENT_ID: - label = bsdf_translucent_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_translucent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_REFLECTION_ID: - label = bsdf_reflection_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_REFRACTION_ID: - label = bsdf_refraction_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_refraction_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_TRANSPARENT_ID: - label = bsdf_transparent_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_transparent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_MICROFACET_GGX_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: - label = bsdf_microfacet_ggx_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_microfacet_ggx_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: - label = bsdf_microfacet_beckmann_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_microfacet_beckmann_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; #ifdef __DPDU__ case CLOSURE_BSDF_WARD_ID: - label = bsdf_ward_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_ward_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; #endif case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: - label = bsdf_ashikhmin_velvet_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_ashikhmin_velvet_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: - label = bsdf_westin_backscatter_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_westin_backscatter_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; case CLOSURE_BSDF_WESTIN_SHEEN_ID: - label = bsdf_westin_sheen_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + label = bsdf_westin_sheen_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); break; #endif default: @@ -92,45 +104,45 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con if(dot(sd->Ng, omega_in) >= 0.0f) { switch(sc->type) { case CLOSURE_BSDF_DIFFUSE_ID: - eval = bsdf_diffuse_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_diffuse_eval_reflect(sc, sd->I, omega_in, pdf); break; #ifdef __SVM__ case CLOSURE_BSDF_OREN_NAYAR_ID: - eval = bsdf_oren_nayar_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_TRANSLUCENT_ID: - eval = bsdf_translucent_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_REFLECTION_ID: - eval = bsdf_reflection_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_REFRACTION_ID: - eval = bsdf_refraction_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_TRANSPARENT_ID: - eval = bsdf_transparent_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_MICROFACET_GGX_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: - eval = bsdf_microfacet_ggx_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: - eval = bsdf_microfacet_beckmann_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf); break; #ifdef __DPDU__ case CLOSURE_BSDF_WARD_ID: - eval = bsdf_ward_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_ward_eval_reflect(sc, sd->I, omega_in, pdf); break; #endif case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: - eval = bsdf_ashikhmin_velvet_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: - eval = bsdf_westin_backscatter_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_westin_backscatter_eval_reflect(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_WESTIN_SHEEN_ID: - eval = bsdf_westin_sheen_eval_reflect(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_westin_sheen_eval_reflect(sc, sd->I, omega_in, pdf); break; #endif default: @@ -141,45 +153,45 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con else { switch(sc->type) { case CLOSURE_BSDF_DIFFUSE_ID: - eval = bsdf_diffuse_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_diffuse_eval_transmit(sc, sd->I, omega_in, pdf); break; #ifdef __SVM__ case CLOSURE_BSDF_OREN_NAYAR_ID: - eval = bsdf_oren_nayar_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_TRANSLUCENT_ID: - eval = bsdf_translucent_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_REFLECTION_ID: - eval = bsdf_reflection_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_REFRACTION_ID: - eval = bsdf_refraction_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_TRANSPARENT_ID: - eval = bsdf_transparent_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_MICROFACET_GGX_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: - eval = bsdf_microfacet_ggx_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: - eval = bsdf_microfacet_beckmann_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf); break; #ifdef __DPDU__ case CLOSURE_BSDF_WARD_ID: - eval = bsdf_ward_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_ward_eval_transmit(sc, sd->I, omega_in, pdf); break; #endif case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: - eval = bsdf_ashikhmin_velvet_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: - eval = bsdf_westin_backscatter_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_westin_backscatter_eval_transmit(sc, sd->I, omega_in, pdf); break; case CLOSURE_BSDF_WESTIN_SHEEN_ID: - eval = bsdf_westin_sheen_eval_transmit(sd, sc, sd->I, omega_in, pdf); + eval = bsdf_westin_sheen_eval_transmit(sc, sd->I, omega_in, pdf); break; #endif default: diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index 935504026ef..11ce3b7c5d1 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -23,16 +23,31 @@ CCL_NAMESPACE_BEGIN __device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract) { if(type == CLOSURE_BSDF_REFRACTION_ID) { - if(refract) - bsdf_refraction_setup(sd, sc, eta); + if(refract) { + sc->data0 = eta; + sd->flag |= bsdf_refraction_setup(sc); + } else - bsdf_reflection_setup(sd, sc); + sd->flag |= bsdf_reflection_setup(sc); } else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) { - bsdf_microfacet_beckmann_setup(sd, sc, roughness, eta, refract); + sc->data0 = roughness; + sc->data1 = eta; + + if(refract) + sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc); + else + sd->flag |= bsdf_microfacet_beckmann_setup(sc); + } + else { + sc->data0 = roughness; + sc->data1 = eta; + + if(refract) + sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc); + else + sd->flag |= bsdf_microfacet_ggx_setup(sc); } - else - bsdf_microfacet_ggx_setup(sd, sc, roughness, eta, refract); } __device_inline ShaderClosure *svm_node_closure_get(ShaderData *sd) @@ -57,7 +72,7 @@ __device_inline void svm_node_closure_set_mix_weight(ShaderClosure *sc, float mi #endif } -__device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, float randb, int path_flag) +__device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, float randb, int path_flag, int *offset) { uint type, param1_offset, param2_offset; @@ -66,11 +81,19 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st decode_node_uchar4(node.y, &type, ¶m1_offset, ¶m2_offset, &mix_weight_offset); float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f); + /* note we read this extra node before weight check, so offset is added */ + uint4 data_node = read_node(kg, offset); + if(mix_weight == 0.0f) return; + + float3 N = stack_valid(data_node.y)? stack_load_float3(stack, data_node.y): sd->N; #else decode_node_uchar4(node.y, &type, ¶m1_offset, ¶m2_offset, NULL); float mix_weight = 1.0f; + + uint4 data_node = read_node(kg, offset); + float3 N = stack_valid(data_node.y)? stack_load_float3(stack, data_node.y): sd->N; #endif float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __int_as_float(node.z); @@ -79,25 +102,32 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st switch(type) { case CLOSURE_BSDF_DIFFUSE_ID: { ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; svm_node_closure_set_mix_weight(sc, mix_weight); float roughness = param1; - if(roughness == 0.0f) - bsdf_diffuse_setup(sd, sc); - else - bsdf_oren_nayar_setup(sd, sc, roughness); + + if(roughness == 0.0f) { + sd->flag |= bsdf_diffuse_setup(sc); + } + else { + sc->data0 = roughness; + sd->flag |= bsdf_oren_nayar_setup(sc); + } break; } case CLOSURE_BSDF_TRANSLUCENT_ID: { ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; svm_node_closure_set_mix_weight(sc, mix_weight); - bsdf_translucent_setup(sd, sc); + sd->flag |= bsdf_translucent_setup(sc); break; } case CLOSURE_BSDF_TRANSPARENT_ID: { ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; svm_node_closure_set_mix_weight(sc, mix_weight); - bsdf_transparent_setup(sd, sc); + sd->flag |= bsdf_transparent_setup(sc); break; } case CLOSURE_BSDF_REFLECTION_ID: @@ -108,17 +138,17 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st break; #endif ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; + sc->data0 = param1; svm_node_closure_set_mix_weight(sc, mix_weight); - float roughness = param1; - /* setup bsdf */ if(type == CLOSURE_BSDF_REFLECTION_ID) - bsdf_reflection_setup(sd, sc); + sd->flag |= bsdf_reflection_setup(sc); else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID) - bsdf_microfacet_beckmann_setup(sd, sc, roughness, 1.0f, false); + sd->flag |= bsdf_microfacet_beckmann_setup(sc); else - bsdf_microfacet_ggx_setup(sd, sc, roughness, 1.0f, false); + sd->flag |= bsdf_microfacet_ggx_setup(sc); break; } @@ -134,13 +164,14 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta; /* fresnel */ - float cosNO = dot(sd->N, sd->I); + float cosNO = dot(N, sd->I); float fresnel = fresnel_dielectric_cos(cosNO, eta); float roughness = param1; #ifdef __MULTI_CLOSURE__ /* reflection */ ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; float3 weight = sc->weight; float sample_weight = sc->sample_weight; @@ -150,6 +181,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st /* refraction */ sc = svm_node_closure_get(sd); + sc->N = N; sc->weight = weight; sc->sample_weight = sample_weight; @@ -158,6 +190,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st svm_node_glossy_setup(sd, sc, type, eta, roughness, true); #else ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; bool refract = (randb > fresnel); @@ -174,22 +207,41 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st break; #endif ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; + sc->T = stack_load_float3(stack, data_node.z); svm_node_closure_set_mix_weight(sc, mix_weight); - float roughness_u = param1; - float roughness_v = param2; + /* rotate tangent */ + float rotation = stack_load_float(stack, data_node.w); - bsdf_ward_setup(sd, sc, normalize(sd->dPdu), roughness_u, roughness_v); + if(rotation != 0.0f) + sc->T = rotate_around_axis(sc->T, sc->N, rotation * 2.0f * M_PI_F); + + /* compute roughness */ + float roughness = param1; + float anisotropy = clamp(param2, -0.99f, 0.99f); + + if(anisotropy < 0.0f) { + sc->data0 = roughness*(1.0f + anisotropy); + sc->data1 = roughness/(1.0f + anisotropy); + } + else { + sc->data0 = roughness/(1.0f - anisotropy); + sc->data1 = roughness*(1.0f - anisotropy); + } + + sd->flag |= bsdf_ward_setup(sc); break; } #endif case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: { ShaderClosure *sc = svm_node_closure_get(sd); + sc->N = N; svm_node_closure_set_mix_weight(sc, mix_weight); /* sigma */ - float sigma = clamp(param1, 0.0f, 1.0f); - bsdf_ashikhmin_velvet_setup(sd, sc, sigma); + sc->data0 = clamp(param1, 0.0f, 1.0f); + sd->flag |= bsdf_ashikhmin_velvet_setup(sc); break; } default: @@ -222,7 +274,7 @@ __device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float * svm_node_closure_set_mix_weight(sc, mix_weight); float density = param1; - volume_transparent_setup(sd, sc, density); + sd->flag |= volume_transparent_setup(sc, density); break; } case CLOSURE_VOLUME_ISOTROPIC_ID: { @@ -230,7 +282,7 @@ __device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float * svm_node_closure_set_mix_weight(sc, mix_weight); float density = param1; - volume_isotropic_setup(sd, sc, density); + sd->flag |= volume_isotropic_setup(sc, density); break; } default: @@ -425,5 +477,14 @@ __device void svm_node_add_closure(ShaderData *sd, float *stack, uint unused, #endif } +/* (Bump) normal */ + +__device void svm_node_set_normal(KernelGlobals *kg, ShaderData *sd, float *stack, uint in_direction, uint out_normal) +{ + float3 normal = stack_load_float3(stack, in_direction); + sd->N = normal; + stack_store_float3(stack, out_normal, normal); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_convert.h b/intern/cycles/kernel/svm/svm_convert.h index 188b0489d9e..f74915a4bc9 100644 --- a/intern/cycles/kernel/svm/svm_convert.h +++ b/intern/cycles/kernel/svm/svm_convert.h @@ -23,6 +23,11 @@ CCL_NAMESPACE_BEGIN __device void svm_node_convert(ShaderData *sd, float *stack, uint type, uint from, uint to) { switch(type) { + case NODE_CONVERT_FI: { + float f = stack_load_float(stack, from); + stack_store_int(stack, to, (int)f); + break; + } case NODE_CONVERT_FV: { float f = stack_load_float(stack, from); stack_store_float3(stack, to, make_float3(f, f, f)); @@ -34,13 +39,34 @@ __device void svm_node_convert(ShaderData *sd, float *stack, uint type, uint fro stack_store_float(stack, to, g); break; } + case NODE_CONVERT_CI: { + float3 f = stack_load_float3(stack, from); + int i = (int)linear_rgb_to_gray(f); + stack_store_int(stack, to, i); + break; + } case NODE_CONVERT_VF: { float3 f = stack_load_float3(stack, from); float g = (f.x + f.y + f.z)*(1.0f/3.0f); stack_store_float(stack, to, g); break; } - + case NODE_CONVERT_VI: { + float3 f = stack_load_float3(stack, from); + int i = (f.x + f.y + f.z)*(1.0f/3.0f); + stack_store_int(stack, to, i); + break; + } + case NODE_CONVERT_IF: { + float f = (float)stack_load_int(stack, from); + stack_store_float(stack, to, f); + break; + } + case NODE_CONVERT_IV: { + float f = (float)stack_load_int(stack, from); + stack_store_float3(stack, to, make_float3(f, f, f)); + break; + } } } diff --git a/intern/cycles/kernel/svm/svm_displace.h b/intern/cycles/kernel/svm/svm_displace.h index b1677f67eca..92f23990ad1 100644 --- a/intern/cycles/kernel/svm/svm_displace.h +++ b/intern/cycles/kernel/svm/svm_displace.h @@ -20,23 +20,35 @@ CCL_NAMESPACE_BEGIN /* Bump Node */ -__device void svm_node_set_bump(ShaderData *sd, float *stack, uint c_offset, uint x_offset, uint y_offset) +__device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) { #ifdef __RAY_DIFFERENTIALS__ + /* get normal input */ + float3 normal_in = stack_valid(node.y)? stack_load_float3(stack, node.y): sd->N; + + /* get surface tangents from normal */ + float3 Rx = cross(sd->dP.dy, normal_in); + float3 Ry = cross(normal_in, sd->dP.dx); + + /* get bump values */ + uint c_offset, x_offset, y_offset, intensity_offset; + decode_node_uchar4(node.z, &c_offset, &x_offset, &y_offset, &intensity_offset); + float h_c = stack_load_float(stack, c_offset); float h_x = stack_load_float(stack, x_offset); float h_y = stack_load_float(stack, y_offset); - float3 Rx = cross(sd->dP.dy, sd->N); - float3 Ry = cross(sd->N, sd->dP.dx); - + /* compute surface gradient and determinant */ float det = dot(sd->dP.dx, Rx); float3 surfgrad = (h_x - h_c)*Rx + (h_y - h_c)*Ry; + float intensity = stack_load_float(stack, intensity_offset); - surfgrad *= 0.1f; /* todo: remove this factor */ - + surfgrad *= intensity; float absdet = fabsf(det); - sd->N = normalize(absdet*sd->N - signf(det)*surfgrad); + + /* compute and output perturbed normal */ + float3 outN = normalize(absdet*normal_in - signf(det)*surfgrad); + stack_store_float3(stack, node.w, outN); #endif } diff --git a/intern/cycles/kernel/svm/svm_fresnel.h b/intern/cycles/kernel/svm/svm_fresnel.h index 7684eabeecb..d5b415a87ce 100644 --- a/intern/cycles/kernel/svm/svm_fresnel.h +++ b/intern/cycles/kernel/svm/svm_fresnel.h @@ -54,7 +54,7 @@ __device void svm_node_layer_weight(ShaderData *sd, float *stack, uint4 node) f = fabsf(dot(sd->I, sd->N)); if(blend != 0.5f) { - blend = clamp(blend, 0.0f, 1.0f); + blend = clamp(blend, 0.0f, 1.0f-1e-5f); blend = (blend < 0.5f)? 2.0f*blend: 0.5f/(1.0f - blend); f = powf(f, blend); diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h index 22741bdb067..8e772f849c7 100644 --- a/intern/cycles/kernel/svm/svm_geometry.h +++ b/intern/cycles/kernel/svm/svm_geometry.h @@ -20,7 +20,7 @@ CCL_NAMESPACE_BEGIN /* Geometry Node */ -__device void svm_node_geometry(ShaderData *sd, float *stack, uint type, uint out_offset) +__device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset) { float3 data; @@ -28,7 +28,34 @@ __device void svm_node_geometry(ShaderData *sd, float *stack, uint type, uint ou case NODE_GEOM_P: data = sd->P; break; case NODE_GEOM_N: data = sd->N; break; #ifdef __DPDU__ - case NODE_GEOM_T: data = normalize(sd->dPdu); break; + case NODE_GEOM_T: { + /* first try to get tangent attribute */ + int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_TANGENT): ATTR_STD_NOT_FOUND; + + if(attr_offset != ATTR_STD_NOT_FOUND) { + /* ensure orthogonal and normalized (interpolation breaks it) */ + data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL); + object_normal_transform(kg, sd, &data); + data = cross(sd->N, normalize(cross(data, sd->N)));; + } + else { + /* try to create spherical tangent from generated coordinates */ + int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_GENERATED): ATTR_STD_NOT_FOUND; + + if(attr_offset != ATTR_STD_NOT_FOUND) { + data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL); + data = make_float3(-(data.y - 0.5), (data.x - 0.5), 0.0f); + object_normal_transform(kg, sd, &data); + data = cross(sd->N, normalize(cross(data, sd->N)));; + } + else { + /* otherwise use surface derivatives */ + data = normalize(sd->dPdu); + } + } + + break; + } #endif case NODE_GEOM_I: data = sd->I; break; case NODE_GEOM_Ng: data = sd->Ng; break; @@ -40,7 +67,7 @@ __device void svm_node_geometry(ShaderData *sd, float *stack, uint type, uint ou stack_store_float3(stack, out_offset, data); } -__device void svm_node_geometry_bump_dx(ShaderData *sd, float *stack, uint type, uint out_offset) +__device void svm_node_geometry_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset) { #ifdef __RAY_DIFFERENTIALS__ float3 data; @@ -48,16 +75,16 @@ __device void svm_node_geometry_bump_dx(ShaderData *sd, float *stack, uint type, switch(type) { case NODE_GEOM_P: data = sd->P + sd->dP.dx; break; case NODE_GEOM_uv: data = make_float3(sd->u + sd->du.dx, sd->v + sd->dv.dx, 0.0f); break; - default: svm_node_geometry(sd, stack, type, out_offset); return; + default: svm_node_geometry(kg, sd, stack, type, out_offset); return; } stack_store_float3(stack, out_offset, data); #else - svm_node_geometry(sd, stack, type, out_offset); + svm_node_geometry(kg, sd, stack, type, out_offset); #endif } -__device void svm_node_geometry_bump_dy(ShaderData *sd, float *stack, uint type, uint out_offset) +__device void svm_node_geometry_bump_dy(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset) { #ifdef __RAY_DIFFERENTIALS__ float3 data; @@ -65,12 +92,12 @@ __device void svm_node_geometry_bump_dy(ShaderData *sd, float *stack, uint type, switch(type) { case NODE_GEOM_P: data = sd->P + sd->dP.dy; break; case NODE_GEOM_uv: data = make_float3(sd->u + sd->du.dy, sd->v + sd->dv.dy, 0.0f); break; - default: svm_node_geometry(sd, stack, type, out_offset); return; + default: svm_node_geometry(kg, sd, stack, type, out_offset); return; } stack_store_float3(stack, out_offset, data); #else - svm_node_geometry(sd, stack, type, out_offset); + svm_node_geometry(kg, sd, stack, type, out_offset); #endif } diff --git a/intern/cycles/kernel/svm/svm_hsv.h b/intern/cycles/kernel/svm/svm_hsv.h index ed17d3fc985..bce11d62923 100644 --- a/intern/cycles/kernel/svm/svm_hsv.h +++ b/intern/cycles/kernel/svm/svm_hsv.h @@ -69,11 +69,11 @@ __device float3 hsv_to_rgb(float3 hsv) s = hsv.y; v = hsv.z; - if(s==0.0f) { + if(s == 0.0f) { rgb = make_float3(v, v, v); } else { - if(h==1.0f) + if(h == 1.0f) h = 0.0f; h *= 6.0f; diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index 662419418e3..0894c9c8290 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -52,6 +52,12 @@ __device_inline float svm_image_texture_frac(float x, int *ix) __device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, uint srgb) { + /* first slots are used by float textures, which are not supported here */ + if(id < TEX_NUM_FLOAT_IMAGES) + return make_float4(1.0f, 0.0f, 1.0f, 1.0f); + + id -= TEX_NUM_FLOAT_IMAGES; + uint4 info = kernel_tex_fetch(__tex_image_packed_info, id); uint width = info.x; uint height = info.y; @@ -265,7 +271,7 @@ __device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float *s * between three textures. * * the Nxyz values are the barycentric coordinates in an equilateral - * triangle, which in case of blending in the middle has a smaller + * triangle, which in case of blending, in the middle has a smaller * equilateral triangle where 3 textures blend. this divides things into * 7 zones, with an if() test for each zone */ diff --git a/intern/cycles/kernel/svm/svm_noise.h b/intern/cycles/kernel/svm/svm_noise.h index dfaf43acbd4..224a1d96543 100644 --- a/intern/cycles/kernel/svm/svm_noise.h +++ b/intern/cycles/kernel/svm/svm_noise.h @@ -104,7 +104,7 @@ __device float grad(int hash, float x, float y, float z) // use vectors pointing to the edges of the cube int h = hash & 15; float u = h<8 ? x : y; - float v = h<4 ? y : h==12||h==14 ? x : z; + float v = h<4 ? y : h == 12 || h == 14 ? x : z; return ((h&1) ? -u : u) + ((h&2) ? -v : v); } diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index fbaf253177d..6bd8f2ac69c 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -92,6 +92,14 @@ __device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, float *stack data = sd->I; break; } + case NODE_TEXCO_DUPLI_GENERATED: { + data = object_dupli_generated(kg, sd->object); + break; + } + case NODE_TEXCO_DUPLI_UV: { + data = object_dupli_uv(kg, sd->object); + break; + } } stack_store_float3(stack, out_offset, data); @@ -141,6 +149,14 @@ __device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, floa data = sd->I; break; } + case NODE_TEXCO_DUPLI_GENERATED: { + data = object_dupli_generated(kg, sd->object); + break; + } + case NODE_TEXCO_DUPLI_UV: { + data = object_dupli_uv(kg, sd->object); + break; + } } stack_store_float3(stack, out_offset, data); @@ -193,6 +209,14 @@ __device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, floa data = sd->I; break; } + case NODE_TEXCO_DUPLI_GENERATED: { + data = object_dupli_generated(kg, sd->object); + break; + } + case NODE_TEXCO_DUPLI_UV: { + data = object_dupli_uv(kg, sd->object); + break; + } } stack_store_float3(stack, out_offset, data); diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index c82eafc790a..77df373a159 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -43,6 +43,7 @@ typedef enum NodeType { NODE_TEX_IMAGE_BOX, NODE_TEX_SKY, NODE_GEOMETRY, + NODE_GEOMETRY_DUPLI, NODE_LIGHT_PATH, NODE_VALUE_F, NODE_VALUE_V, @@ -91,7 +92,8 @@ typedef enum NodeType { NODE_LIGHT_FALLOFF, NODE_OBJECT_INFO, NODE_PARTICLE_INFO, - NODE_TEX_BRICK + NODE_TEX_BRICK, + NODE_CLOSURE_SET_NORMAL, } NodeType; typedef enum NodeAttributeType { @@ -149,7 +151,9 @@ typedef enum NodeTexCoord { NODE_TEXCO_OBJECT, NODE_TEXCO_CAMERA, NODE_TEXCO_WINDOW, - NODE_TEXCO_REFLECTION + NODE_TEXCO_REFLECTION, + NODE_TEXCO_DUPLI_GENERATED, + NODE_TEXCO_DUPLI_UV } NodeTexCoord; typedef enum NodeMix { @@ -206,8 +210,13 @@ typedef enum NodeVectorMath { typedef enum NodeConvert { NODE_CONVERT_FV, + NODE_CONVERT_FI, NODE_CONVERT_CF, - NODE_CONVERT_VF + NODE_CONVERT_CI, + NODE_CONVERT_VF, + NODE_CONVERT_VI, + NODE_CONVERT_IF, + NODE_CONVERT_IV } NodeConvert; typedef enum NodeDistanceMetric { @@ -284,16 +293,18 @@ typedef enum ClosureType { CLOSURE_BSDF_DIFFUSE_ID, CLOSURE_BSDF_OREN_NAYAR_ID, + CLOSURE_BSDF_GLOSSY_ID, CLOSURE_BSDF_REFLECTION_ID, CLOSURE_BSDF_MICROFACET_GGX_ID, CLOSURE_BSDF_MICROFACET_BECKMANN_ID, CLOSURE_BSDF_WARD_ID, + CLOSURE_BSDF_ASHIKHMIN_VELVET_ID, CLOSURE_BSDF_WESTIN_SHEEN_ID, + CLOSURE_BSDF_TRANSMISSION_ID, CLOSURE_BSDF_TRANSLUCENT_ID, CLOSURE_BSDF_REFRACTION_ID, CLOSURE_BSDF_WESTIN_BACKSCATTER_ID, - CLOSURE_BSDF_ASHIKHMIN_VELVET_ID, CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID, CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID, CLOSURE_BSDF_GLASS_ID, @@ -317,8 +328,8 @@ typedef enum ClosureType { /* watch this, being lazy with memory usage */ #define CLOSURE_IS_BSDF(type) (type <= CLOSURE_BSDF_TRANSPARENT_ID) #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_REFLECTION_ID && type <= CLOSURE_BSDF_WESTIN_SHEEN_ID) -#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSLUCENT_ID && type <= CLOSURE_BSDF_GLASS_ID) +#define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_GLOSSY_ID && type <= CLOSURE_BSDF_WESTIN_SHEEN_ID) +#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_GLASS_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 85b476e60d9..7907061c19c 100644 --- a/intern/cycles/render/CMakeLists.txt +++ b/intern/cycles/render/CMakeLists.txt @@ -7,6 +7,9 @@ set(INC ../kernel/osl ../bvh ../util +) + +set(INC_SYS ${GLEW_INCLUDE_PATH} ) @@ -64,6 +67,7 @@ set(SRC_HEADERS set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${RTTI_DISABLE_FLAGS}") include_directories(${INC}) +include_directories(SYSTEM ${INC_SYS}) add_library(cycles_render ${SRC} ${SRC_HEADERS}) diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index 5122c1af410..c7a9ab3e51a 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -162,6 +162,8 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) attr = add(name, TypeDesc::TypeNormal, Attribute::FACE); else if(std == ATTR_STD_UV) attr = add(name, TypeDesc::TypePoint, Attribute::CORNER); + else if(std == ATTR_STD_TANGENT) + attr = add(name, TypeDesc::TypeVector, Attribute::CORNER); else if(std == ATTR_STD_GENERATED) attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX); else if(std == ATTR_STD_POSITION_UNDEFORMED) diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index 51568f65323..3b61ccd176d 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -101,7 +101,7 @@ RenderTile::RenderTile() RenderBuffers::RenderBuffers(Device *device_) { - device = device_; + device = device_; } RenderBuffers::~RenderBuffers() @@ -196,7 +196,18 @@ bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int else if(components == 3) { assert(pass.components == 4); - if(pass.divide_type != PASS_NONE) { + /* RGBA */ + if(type == PASS_SHADOW) { + for(int i = 0; i < size; i++, in += pass_stride, pixels += 3) { + float4 f = make_float4(in[0], in[1], in[2], in[3]); + float invw = (f.w > 0.0f)? 1.0f/f.w: 1.0f; + + pixels[0] = f.x*invw; + pixels[1] = f.y*invw; + pixels[2] = f.z*invw; + } + } + else if(pass.divide_type != PASS_NONE) { /* RGB lighting passes that need to divide out color */ pass_offset = 0; foreach(Pass& color_pass, params.passes) { diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index e44caa90f12..649936bec04 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -19,6 +19,8 @@ #include "camera.h" #include "scene.h" +#include "device.h" + #include "util_vector.h" CCL_NAMESPACE_BEGIN @@ -141,7 +143,7 @@ void Camera::update() void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) { - Scene::MotionType need_motion = scene->need_motion(); + Scene::MotionType need_motion = scene->need_motion(device->info.advanced_shading); update(); @@ -160,7 +162,6 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) /* store matrices */ kcam->screentoworld = screentoworld; kcam->rastertoworld = rastertoworld; - kcam->ndctoworld = ndctoworld; kcam->rastertocamera = rastertocamera; kcam->cameratoworld = cameratoworld; kcam->worldtoscreen = transform_inverse(screentoworld); @@ -193,13 +194,14 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) } } } +#ifdef __CAMERA_MOTION__ else if(need_motion == Scene::MOTION_BLUR) { - /* todo: exact camera position will not be hit this way */ if(use_motion) { - transform_motion_decompose(&kcam->motion, &motion); + transform_motion_decompose(&kcam->motion, &motion, &matrix); kcam->have_motion = 1; } } +#endif /* depth of field */ kcam->aperturesize = aperturesize; @@ -208,7 +210,11 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) kcam->bladesrotation = bladesrotation; /* motion blur */ +#ifdef __CAMERA_MOTION__ kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime: 0.0f; +#else + kcam->shuttertime = 0.0f; +#endif /* type */ kcam->type = type; @@ -245,7 +251,7 @@ void Camera::device_free(Device *device, DeviceScene *dscene) bool Camera::modified(const Camera& cam) { - return !((shuttertime== cam.shuttertime) && + return !((shuttertime == cam.shuttertime) && (aperturesize == cam.aperturesize) && (blades == cam.blades) && (bladesrotation == cam.bladesrotation) && @@ -268,13 +274,17 @@ bool Camera::modified(const Camera& cam) (border_bottom == cam.border_bottom) && (border_top == cam.border_top) && (matrix == cam.matrix) && - (motion == cam.motion) && - (use_motion == cam.use_motion) && (panorama_type == cam.panorama_type) && (fisheye_fov == cam.fisheye_fov) && (fisheye_lens == cam.fisheye_lens)); } +bool Camera::motion_modified(const Camera& cam) +{ + return !((motion == cam.motion) && + (use_motion == cam.use_motion)); +} + void Camera::tag_update() { need_update = true; diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 82852bde5e0..1407c86e7c2 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -103,6 +103,7 @@ public: void device_free(Device *device, DeviceScene *dscene); bool modified(const Camera& cam); + bool motion_modified(const Camera& cam); void tag_update(); }; diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index 20fbfa0cf27..c1c976dc193 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -181,14 +181,14 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to) assert(from && to); if(to->link) { - fprintf(stderr, "ShaderGraph connect: input already connected.\n"); + fprintf(stderr, "Cycles shader graph connect: input already connected.\n"); return; } if(from->type != to->type) { /* for closures we can't do automatic conversion */ if(from->type == SHADER_SOCKET_CLOSURE || to->type == SHADER_SOCKET_CLOSURE) { - fprintf(stderr, "ShaderGraph connect: can only connect closure to closure " + fprintf(stderr, "Cycles shader graph connect: can only connect closure to closure " "(ShaderNode:%s, ShaderOutput:%s , type:%d -> to ShaderNode:%s, ShaderInput:%s, type:%d).\n", from->parent->name.c_str(), from->name, (int)from->type, to->parent->name.c_str(), to->name, (int)to->type); @@ -229,6 +229,8 @@ void ShaderGraph::finalize(bool do_bump, bool do_osl) if(!finalized) { clean(); default_inputs(do_osl); + refine_bump_nodes(); + if(do_bump) bump_from_displacement(); @@ -363,7 +365,7 @@ void ShaderGraph::break_cycles(ShaderNode *node, vector& visited, vectorid]) { /* break cycle */ disconnect(input); - fprintf(stderr, "ShaderGraph: detected cycle in graph, connection removed.\n"); + fprintf(stderr, "Cycles shader graph: detected cycle in graph, connection removed.\n"); } else if(!visited[depnode->id]) { /* visit dependencies */ @@ -468,6 +470,12 @@ void ShaderGraph::default_inputs(bool do_osl) connect(geom->output("Position"), input); } + else if(input->default_value == ShaderInput::TANGENT) { + if(!geom) + geom = new GeometryNode(); + + connect(geom->output("Tangent"), input); + } } } } @@ -478,6 +486,61 @@ void ShaderGraph::default_inputs(bool do_osl) add(texco); } +void ShaderGraph::refine_bump_nodes() +{ + /* we transverse the node graph looking for bump nodes, when we find them, + * like in bump_from_displacement(), we copy the sub-graph defined from "bump" + * input to the inputs "center","dx" and "dy" What is in "bump" input is moved + * to "center" input. */ + + foreach(ShaderNode *node, nodes) { + if(node->name == ustring("bump") && node->input("Height")->link) { + ShaderInput *bump_input = node->input("Height"); + set nodes_bump; + + /* make 2 extra copies of the subgraph defined in Bump input */ + map nodes_dx; + map nodes_dy; + + /* find dependencies for the given input */ + find_dependencies(nodes_bump, bump_input ); + + copy_nodes(nodes_bump, nodes_dx); + copy_nodes(nodes_bump, nodes_dy); + + /* mark nodes to indicate they are use for bump computation, so + that any texture coordinates are shifted by dx/dy when sampling */ + foreach(ShaderNode *node, nodes_bump) + node->bump = SHADER_BUMP_CENTER; + foreach(NodePair& pair, nodes_dx) + pair.second->bump = SHADER_BUMP_DX; + foreach(NodePair& pair, nodes_dy) + pair.second->bump = SHADER_BUMP_DY; + + ShaderOutput *out = bump_input->link; + ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name); + ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name); + + connect(out_dx, node->input("SampleX")); + connect(out_dy, node->input("SampleY")); + + /* add generated nodes */ + foreach(NodePair& pair, nodes_dx) + add(pair.second); + foreach(NodePair& pair, nodes_dy) + add(pair.second); + + /* connect what is conected is bump to samplecenter input*/ + connect(out , node->input("SampleCenter")); + + /* bump input is just for connectivity purpose for the graph input, + * we reconected this input to samplecenter, so lets disconnect it + * from bump input */ + disconnect(bump_input); + } + } +} + void ShaderGraph::bump_from_displacement() { /* generate bump mapping automatically from displacement. bump mapping is @@ -491,7 +554,7 @@ void ShaderGraph::bump_from_displacement() * different shifted coordinates. * * these 3 displacement values are then fed into the bump node, which will - * modify the normal. */ + * output the the perturbed normal. */ ShaderInput *displacement_in = output()->input("Displacement"); @@ -520,6 +583,12 @@ void ShaderGraph::bump_from_displacement() foreach(NodePair& pair, nodes_dy) pair.second->bump = SHADER_BUMP_DY; + /* add set normal node and connect the bump normal ouput to the set normal + * output, so it can finally set the shader normal, note we are only doing + * this for bump from displacement, this will be the only bump allowed to + * overwrite the shader normal */ + ShaderNode *set_normal = add(new SetNormalNode()); + /* add bump node and connect copied graphs to it */ ShaderNode *bump = add(new BumpNode()); @@ -531,6 +600,9 @@ void ShaderGraph::bump_from_displacement() connect(out_center, bump->input("SampleCenter")); connect(out_dx, bump->input("SampleX")); connect(out_dy, bump->input("SampleY")); + + /* connect the bump out to the set normal in: */ + connect(bump->output("Normal"), set_normal->input("Direction")); /* connect bump output to normal input nodes that aren't set yet. actually * this will only set the normal input to the geometry node that we created @@ -538,8 +610,14 @@ void ShaderGraph::bump_from_displacement() foreach(ShaderNode *node, nodes) foreach(ShaderInput *input, node->inputs) if(!input->link && input->default_value == ShaderInput::NORMAL) - connect(bump->output("Normal"), input); - + connect(set_normal->output("Normal"), input); + + /* for displacement bump, clear the normal input in case the above loop + * connected the setnormal out to the bump normalin */ + ShaderInput *bump_normal_in = bump->input("NormalIn"); + if(bump_normal_in) + bump_normal_in->link = NULL; + /* finally, add the copied nodes to the graph. we can't do this earlier * because we would create dependency cycles in the above loop */ foreach(NodePair& pair, nodes_center) diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index c3b674d0f23..b339c3c3847 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -44,6 +44,7 @@ class OSLCompiler; enum ShaderSocketType { SHADER_SOCKET_FLOAT, + SHADER_SOCKET_INT, SHADER_SOCKET_COLOR, SHADER_SOCKET_VECTOR, SHADER_SOCKET_POINT, @@ -112,6 +113,7 @@ public: INCOMING, NORMAL, POSITION, + TANGENT, NONE }; @@ -234,6 +236,7 @@ protected: void break_cycles(ShaderNode *node, vector& visited, vector& on_stack); void clean(); void bump_from_displacement(); + void refine_bump_nodes(); void default_inputs(bool do_osl); }; diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 4ee024dd52a..f136f08dc2c 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -366,8 +366,10 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl device_vector& tex_img = dscene->tex_float_image[slot]; - if(tex_img.device_pointer) + if(tex_img.device_pointer) { + thread_scoped_lock device_lock(device_mutex); device->tex_free(tex_img); + } if(!file_load_float_image(img, tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ @@ -384,8 +386,10 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl if(slot >= 10) name = string_printf("__tex_image_float_0%d", slot); else name = string_printf("__tex_image_float_00%d", slot); - if(!pack_images) + if(!pack_images) { + thread_scoped_lock device_lock(device_mutex); device->tex_alloc(name.c_str(), tex_img, true, true); + } } else { string filename = path_filename(images[slot - tex_image_byte_start]->filename); @@ -393,8 +397,10 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl device_vector& tex_img = dscene->tex_image[slot - tex_image_byte_start]; - if(tex_img.device_pointer) + if(tex_img.device_pointer) { + thread_scoped_lock device_lock(device_mutex); device->tex_free(tex_img); + } if(!file_load_image(img, tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ @@ -411,8 +417,10 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl if(slot >= 10) name = string_printf("__tex_image_0%d", slot); else name = string_printf("__tex_image_00%d", slot); - if(!pack_images) + if(!pack_images) { + thread_scoped_lock device_lock(device_mutex); device->tex_alloc(name.c_str(), tex_img, true, true); + } } img->need_load = false; @@ -440,15 +448,27 @@ void ImageManager::device_free_image(Device *device, DeviceScene *dscene, int sl #endif } else if(is_float) { - device->tex_free(dscene->tex_float_image[slot]); - dscene->tex_float_image[slot].clear(); + device_vector& tex_img = dscene->tex_float_image[slot]; + + if(tex_img.device_pointer) { + thread_scoped_lock device_lock(device_mutex); + device->tex_free(tex_img); + } + + tex_img.clear(); delete float_images[slot]; float_images[slot] = NULL; } else { - device->tex_free(dscene->tex_image[slot - tex_image_byte_start]); - dscene->tex_image[slot - tex_image_byte_start].clear(); + device_vector& tex_img = dscene->tex_image[slot - tex_image_byte_start]; + + if(tex_img.device_pointer) { + thread_scoped_lock device_lock(device_mutex); + device->tex_free(tex_img); + } + + tex_img.clear(); delete images[slot - tex_image_byte_start]; images[slot - tex_image_byte_start] = NULL; @@ -460,7 +480,7 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress& { if(!need_update) return; - + TaskPool pool; for(size_t slot = 0; slot < images.size(); slot++) { @@ -542,9 +562,9 @@ void ImageManager::device_free(Device *device, DeviceScene *dscene) device_free_image(device, dscene, slot); device->tex_free(dscene->tex_image_packed); - dscene->tex_image_packed.clear(); - device->tex_free(dscene->tex_image_packed_info); + + dscene->tex_image_packed.clear(); dscene->tex_image_packed_info.clear(); images.clear(); diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 04a705c27bf..485bfc5cbf5 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -22,11 +22,13 @@ #include "device_memory.h" #include "util_string.h" +#include "util_thread.h" #include "util_vector.h" +#include "kernel_types.h" /* for TEX_NUM_FLOAT_IMAGES */ + CCL_NAMESPACE_BEGIN -#define TEX_NUM_FLOAT_IMAGES 5 #define TEX_NUM_IMAGES 95 #define TEX_IMAGE_BYTE_START TEX_NUM_FLOAT_IMAGES @@ -66,6 +68,7 @@ private: int tex_num_images; int tex_num_float_images; int tex_image_byte_start; + thread_mutex device_mutex; struct Image { string filename; diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp index da563c9c4ec..699e6979990 100644 --- a/intern/cycles/render/integrator.cpp +++ b/intern/cycles/render/integrator.cpp @@ -123,6 +123,8 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene max_samples *= (max_bounce + transparent_max_bounce + 2); int dimensions = PRNG_BASE_NUM + max_samples*PRNG_BOUNCE_NUM; + dimensions = min(dimensions, SOBOL_MAX_DIMENSIONS); + uint *directions = dscene->sobol_directions.resize(SOBOL_BITS*dimensions); sobol_generate_direction_vectors((uint(*)[SOBOL_BITS])directions, dimensions); diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 6445c04257f..d77516a1b18 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -67,15 +67,16 @@ static void dump_background_pixels(Device *device, DeviceScene *dscene, int res, main_task.shader_x = 0; main_task.shader_w = width*height; + /* disabled splitting for now, there's an issue with multi-GPU mem_copy_from */ list split_tasks; - main_task.split_max_size(split_tasks, 128*128); + main_task.split_max_size(split_tasks, 128*128); foreach(DeviceTask& task, split_tasks) { device->task_add(task); device->task_wait(); + device->mem_copy_from(d_output, task.shader_x, 1, task.shader_w, sizeof(float4)); } - device->mem_copy_from(d_output, 0, 1, d_output.size(), sizeof(float4)); device->mem_free(d_input); device->mem_free(d_output); diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 7037e36f313..14f23992664 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -19,6 +19,7 @@ #include "bvh.h" #include "bvh_build.h" +#include "camera.h" #include "device.h" #include "shader.h" #include "light.h" @@ -354,6 +355,9 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vectorattribute_map[i][stdname] = osl_attr; } else if(req.name != ustring()) { @@ -722,10 +726,16 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen foreach(Shader *shader, scene->shaders) shader->need_update_attributes = false; - bool motion_blur = scene->need_motion() == Scene::MOTION_BLUR; + float shuttertime = scene->camera->shuttertime; +#ifdef __OBJECT_MOTION__ + Scene::MotionType need_motion = scene->need_motion(device->info.advanced_shading); + bool motion_blur = need_motion == Scene::MOTION_BLUR; +#else + bool motion_blur = false; +#endif foreach(Object *object, scene->objects) - object->compute_bounds(motion_blur); + object->compute_bounds(motion_blur, shuttertime); if(progress.get_cancel()) return; diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 1f03ab4e347..d7bf71337f6 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -225,6 +225,8 @@ void ImageTextureNode::compile(OSLCompiler& compiler) compiler.parameter("color_space", "Linear"); else compiler.parameter("color_space", "sRGB"); + compiler.parameter("projection", projection); + compiler.parameter("projection_blend", projection_blend); compiler.add(this, "node_image_texture"); } @@ -1021,7 +1023,7 @@ void NormalNode::compile(SVMCompiler& compiler) void NormalNode::compile(OSLCompiler& compiler) { - compiler.parameter_vector("Direction", direction); + compiler.parameter_normal("Direction", direction); compiler.add(this, "node_normal"); } @@ -1065,6 +1067,8 @@ ConvertNode::ConvertNode(ShaderSocketType from_, ShaderSocketType to_) if(from == SHADER_SOCKET_FLOAT) add_input("Val", SHADER_SOCKET_FLOAT); + else if(from == SHADER_SOCKET_INT) + add_input("ValInt", SHADER_SOCKET_INT); else if(from == SHADER_SOCKET_COLOR) add_input("Color", SHADER_SOCKET_COLOR); else if(from == SHADER_SOCKET_VECTOR) @@ -1078,6 +1082,8 @@ ConvertNode::ConvertNode(ShaderSocketType from_, ShaderSocketType to_) if(to == SHADER_SOCKET_FLOAT) add_output("Val", SHADER_SOCKET_FLOAT); + else if(to == SHADER_SOCKET_INT) + add_output("ValInt", SHADER_SOCKET_INT); else if(to == SHADER_SOCKET_COLOR) add_output("Color", SHADER_SOCKET_COLOR); else if(to == SHADER_SOCKET_VECTOR) @@ -1095,7 +1101,29 @@ void ConvertNode::compile(SVMCompiler& compiler) ShaderInput *in = inputs[0]; ShaderOutput *out = outputs[0]; - if(to == SHADER_SOCKET_FLOAT) { + if(from == SHADER_SOCKET_FLOAT) { + compiler.stack_assign(in); + compiler.stack_assign(out); + + if(to == SHADER_SOCKET_INT) + /* float to int */ + compiler.add_node(NODE_CONVERT, NODE_CONVERT_FI, in->stack_offset, out->stack_offset); + else + /* float to float3 */ + compiler.add_node(NODE_CONVERT, NODE_CONVERT_FV, in->stack_offset, out->stack_offset); + } + else if(from == SHADER_SOCKET_INT) { + compiler.stack_assign(in); + compiler.stack_assign(out); + + if(to == SHADER_SOCKET_FLOAT) + /* int to float */ + compiler.add_node(NODE_CONVERT, NODE_CONVERT_IF, in->stack_offset, out->stack_offset); + else + /* int to vector/point/normal */ + compiler.add_node(NODE_CONVERT, NODE_CONVERT_IV, in->stack_offset, out->stack_offset); + } + else if(to == SHADER_SOCKET_FLOAT) { compiler.stack_assign(in); compiler.stack_assign(out); @@ -1106,12 +1134,16 @@ void ConvertNode::compile(SVMCompiler& compiler) /* vector/point/normal to float */ compiler.add_node(NODE_CONVERT, NODE_CONVERT_VF, in->stack_offset, out->stack_offset); } - else if(from == SHADER_SOCKET_FLOAT) { + else if(to == SHADER_SOCKET_INT) { compiler.stack_assign(in); compiler.stack_assign(out); - /* float to float3 */ - compiler.add_node(NODE_CONVERT, NODE_CONVERT_FV, in->stack_offset, out->stack_offset); + if(from == SHADER_SOCKET_COLOR) + /* color to int */ + compiler.add_node(NODE_CONVERT, NODE_CONVERT_CI, in->stack_offset, out->stack_offset); + else + /* vector/point/normal to int */ + compiler.add_node(NODE_CONVERT, NODE_CONVERT_VI, in->stack_offset, out->stack_offset); } else { /* float3 to float3 */ @@ -1134,6 +1166,8 @@ void ConvertNode::compile(OSLCompiler& compiler) { if(from == SHADER_SOCKET_FLOAT) compiler.add(this, "node_convert_from_float"); + else if(from == SHADER_SOCKET_INT) + compiler.add(this, "node_convert_from_int"); else if(from == SHADER_SOCKET_COLOR) compiler.add(this, "node_convert_from_color"); else if(from == SHADER_SOCKET_VECTOR) @@ -1175,14 +1209,16 @@ BsdfNode::BsdfNode() closure = ccl::CLOSURE_BSDF_DIFFUSE_ID; add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); - add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL); add_output("BSDF", SHADER_SOCKET_CLOSURE); } -void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2) +void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3) { ShaderInput *color_in = input("Color"); + ShaderInput *normal_in = input("Normal"); + ShaderInput *tangent_in = input("Tangent"); if(color_in->link) { compiler.stack_assign(color_in); @@ -1195,6 +1231,14 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput * compiler.stack_assign(param1); if(param2) compiler.stack_assign(param2); + if(param3) + compiler.stack_assign(param3); + + if(normal_in->link) + compiler.stack_assign(normal_in); + + if(tangent_in && tangent_in->link) + compiler.stack_assign(tangent_in); compiler.add_node(NODE_CLOSURE_BSDF, compiler.encode_uchar4(closure, @@ -1203,6 +1247,14 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput * compiler.closure_mix_weight_offset()), __float_as_int((param1)? param1->value.x: 0.0f), __float_as_int((param2)? param2->value.x: 0.0f)); + + if(tangent_in) { + compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset, tangent_in->stack_offset, + (param3)? param3->stack_offset: SVM_STACK_INVALID); + } + else { + compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset); + } } void BsdfNode::compile(SVMCompiler& compiler) @@ -1221,13 +1273,28 @@ WardBsdfNode::WardBsdfNode() { closure = CLOSURE_BSDF_WARD_ID; - add_input("Roughness U", SHADER_SOCKET_FLOAT, 0.2f); - add_input("Roughness V", SHADER_SOCKET_FLOAT, 0.2f); + add_input("Tangent", SHADER_SOCKET_VECTOR, ShaderInput::TANGENT); + + add_input("Roughness", SHADER_SOCKET_FLOAT, 0.2f); + add_input("Anisotropy", SHADER_SOCKET_FLOAT, 0.5f); + add_input("Rotation", SHADER_SOCKET_FLOAT, 0.0f); +} + +void WardBsdfNode::attributes(AttributeRequestSet *attributes) +{ + ShaderInput *tangent_in = input("Tangent"); + + if(!tangent_in->link) { + attributes->add(ATTR_STD_TANGENT); + attributes->add(ATTR_STD_GENERATED); + } + + ShaderNode::attributes(attributes); } void WardBsdfNode::compile(SVMCompiler& compiler) { - BsdfNode::compile(compiler, input("Roughness U"), input("Roughness V")); + BsdfNode::compile(compiler, input("Roughness"), input("Anisotropy"), input("Rotation")); } void WardBsdfNode::compile(OSLCompiler& compiler) @@ -1566,6 +1633,16 @@ GeometryNode::GeometryNode() add_output("Backfacing", SHADER_SOCKET_FLOAT); } +void GeometryNode::attributes(AttributeRequestSet *attributes) +{ + if(!output("Tangent")->links.empty()) { + attributes->add(ATTR_STD_TANGENT); + attributes->add(ATTR_STD_GENERATED); + } + + ShaderNode::attributes(attributes); +} + void GeometryNode::compile(SVMCompiler& compiler) { ShaderOutput *out; @@ -1636,7 +1713,7 @@ void GeometryNode::compile(OSLCompiler& compiler) TextureCoordinateNode::TextureCoordinateNode() : ShaderNode("texture_coordinate") { - add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); add_output("Generated", SHADER_SOCKET_POINT); add_output("Normal", SHADER_SOCKET_NORMAL); add_output("UV", SHADER_SOCKET_POINT); @@ -1644,14 +1721,18 @@ TextureCoordinateNode::TextureCoordinateNode() add_output("Camera", SHADER_SOCKET_POINT); add_output("Window", SHADER_SOCKET_POINT); add_output("Reflection", SHADER_SOCKET_NORMAL); + + from_dupli = false; } void TextureCoordinateNode::attributes(AttributeRequestSet *attributes) { - if(!output("Generated")->links.empty()) - attributes->add(ATTR_STD_GENERATED); - if(!output("UV")->links.empty()) - attributes->add(ATTR_STD_UV); + if(!from_dupli) { + if(!output("Generated")->links.empty()) + attributes->add(ATTR_STD_GENERATED); + if(!output("UV")->links.empty()) + attributes->add(ATTR_STD_UV); + } ShaderNode::attributes(attributes); } @@ -1681,9 +1762,15 @@ void TextureCoordinateNode::compile(SVMCompiler& compiler) compiler.add_node(geom_node, NODE_GEOM_P, out->stack_offset); } else { - int attr = compiler.attribute(ATTR_STD_GENERATED); - compiler.stack_assign(out); - compiler.add_node(attr_node, attr, out->stack_offset, NODE_ATTR_FLOAT3); + if(from_dupli) { + compiler.stack_assign(out); + compiler.add_node(texco_node, NODE_TEXCO_DUPLI_GENERATED, out->stack_offset); + } + else { + int attr = compiler.attribute(ATTR_STD_GENERATED); + compiler.stack_assign(out); + compiler.add_node(attr_node, attr, out->stack_offset, NODE_ATTR_FLOAT3); + } } } @@ -1695,9 +1782,15 @@ void TextureCoordinateNode::compile(SVMCompiler& compiler) out = output("UV"); if(!out->links.empty()) { - int attr = compiler.attribute(ATTR_STD_UV); - compiler.stack_assign(out); - compiler.add_node(attr_node, attr, out->stack_offset, NODE_ATTR_FLOAT3); + if(from_dupli) { + compiler.stack_assign(out); + compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, out->stack_offset); + } + else { + int attr = compiler.attribute(ATTR_STD_UV); + compiler.stack_assign(out); + compiler.add_node(attr_node, attr, out->stack_offset, NODE_ATTR_FLOAT3); + } } out = output("Object"); @@ -1742,6 +1835,8 @@ void TextureCoordinateNode::compile(OSLCompiler& compiler) if(compiler.background) compiler.parameter("is_background", true); + + compiler.parameter("from_dupli", from_dupli); compiler.add(this, "node_texture_coordinate"); } @@ -2168,7 +2263,7 @@ static ShaderEnum mix_type_init() enm.insert("Burn", NODE_MIX_BURN); enm.insert("Hue", NODE_MIX_HUE); enm.insert("Saturation", NODE_MIX_SAT); - enm.insert("Value", NODE_MIX_VAL ); + enm.insert("Value", NODE_MIX_VAL); enm.insert("Color", NODE_MIX_COLOR); enm.insert("Soft Light", NODE_MIX_SOFT); enm.insert("Linear Light", NODE_MIX_LINEAR); @@ -2528,7 +2623,7 @@ void LayerWeightNode::compile(SVMCompiler& compiler) void LayerWeightNode::compile(OSLCompiler& compiler) { - compiler.add(this, "node_blend_weight"); + compiler.add(this, "node_layer_weight"); } /* Output */ @@ -2539,6 +2634,7 @@ OutputNode::OutputNode() add_input("Surface", SHADER_SOCKET_CLOSURE); add_input("Volume", SHADER_SOCKET_CLOSURE); add_input("Displacement", SHADER_SOCKET_FLOAT); + add_input("Normal", SHADER_SOCKET_NORMAL); } void OutputNode::compile(SVMCompiler& compiler) @@ -2686,9 +2782,15 @@ void VectorMathNode::compile(OSLCompiler& compiler) BumpNode::BumpNode() : ShaderNode("bump") { + /* this input is used by the user, but after graph transform it is no longer + * used and moved to sampler center/x/y instead */ + add_input("Height", SHADER_SOCKET_FLOAT); + add_input("SampleCenter", SHADER_SOCKET_FLOAT); add_input("SampleX", SHADER_SOCKET_FLOAT); add_input("SampleY", SHADER_SOCKET_FLOAT); + add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL); + add_input("Strength", SHADER_SOCKET_FLOAT, 0.1f); add_output("Normal", SHADER_SOCKET_NORMAL); } @@ -2698,12 +2800,25 @@ void BumpNode::compile(SVMCompiler& compiler) ShaderInput *center_in = input("SampleCenter"); ShaderInput *dx_in = input("SampleX"); ShaderInput *dy_in = input("SampleY"); + ShaderInput *normal_in = input("NormalIn"); + ShaderInput *intensity_in = input("Strength"); + ShaderOutput *normal_out = output("Normal"); compiler.stack_assign(center_in); compiler.stack_assign(dx_in); compiler.stack_assign(dy_in); + compiler.stack_assign(intensity_in); + compiler.stack_assign(normal_out); - compiler.add_node(NODE_SET_BUMP, center_in->stack_offset, dx_in->stack_offset, dy_in->stack_offset); + if(normal_in->link) + compiler.stack_assign(normal_in); + + /* pack all parameters in the node */ + compiler.add_node(NODE_SET_BUMP, + normal_in->stack_offset, + compiler.encode_uchar4(center_in->stack_offset, dx_in->stack_offset, + dy_in->stack_offset, intensity_in->stack_offset), + normal_out->stack_offset); } void BumpNode::compile(OSLCompiler& compiler) @@ -2768,8 +2883,68 @@ void RGBRampNode::compile(SVMCompiler& compiler) void RGBRampNode::compile(OSLCompiler& compiler) { + /* OSL shader only takes separate RGB and A array, split the RGBA base array */ + /* NB: cycles float3 type is actually 4 floats! need to use an explicit array */ + float ramp_color[RAMP_TABLE_SIZE][3]; + float ramp_alpha[RAMP_TABLE_SIZE]; + + for (int i = 0; i < RAMP_TABLE_SIZE; ++i) { + ramp_color[i][0] = ramp[i].x; + ramp_color[i][1] = ramp[i].y; + ramp_color[i][2] = ramp[i].z; + ramp_alpha[i] = ramp[i].w; + } + + compiler.parameter_color_array("ramp_color", ramp_color, RAMP_TABLE_SIZE); + compiler.parameter_array("ramp_alpha", ramp_alpha, RAMP_TABLE_SIZE); + compiler.add(this, "node_rgb_ramp"); } +/* Set Normal Node */ + +SetNormalNode::SetNormalNode() +: ShaderNode("set_normal") +{ + add_input("Direction", SHADER_SOCKET_VECTOR); + add_output("Normal", SHADER_SOCKET_NORMAL); +} + +void SetNormalNode::compile(SVMCompiler& compiler) +{ + ShaderInput *direction_in = input("Direction"); + ShaderOutput *normal_out = output("Normal"); + + compiler.stack_assign(direction_in); + compiler.stack_assign(normal_out); + + compiler.add_node(NODE_CLOSURE_SET_NORMAL, direction_in->stack_offset, normal_out->stack_offset); +} + +void SetNormalNode::compile(OSLCompiler& compiler) +{ + compiler.add(this, "node_set_normal"); +} + +/* OSLScriptNode */ + +OSLScriptNode::OSLScriptNode() +: ShaderNode("osl_script") +{ +} + +void OSLScriptNode::compile(SVMCompiler& compiler) +{ + /* doesn't work for SVM, obviously ... */ +} + +void OSLScriptNode::compile(OSLCompiler& compiler) +{ + if(!filepath.empty()) + compiler.add(this, filepath.c_str(), true); + else + compiler.add(this, bytecode_hash.c_str(), false); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 82bead7e41a..d90cae5f668 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -193,7 +193,7 @@ class BsdfNode : public ShaderNode { public: SHADER_NODE_CLASS(BsdfNode) - void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2); + void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3 = NULL); ClosureType closure; }; @@ -201,6 +201,7 @@ public: class WardBsdfNode : public BsdfNode { public: SHADER_NODE_CLASS(WardBsdfNode) + void attributes(AttributeRequestSet *attributes); }; class DiffuseBsdfNode : public BsdfNode { @@ -278,12 +279,15 @@ public: class GeometryNode : public ShaderNode { public: SHADER_NODE_CLASS(GeometryNode) + void attributes(AttributeRequestSet *attributes); }; class TextureCoordinateNode : public ShaderNode { public: SHADER_NODE_CLASS(TextureCoordinateNode) void attributes(AttributeRequestSet *attributes); + + bool from_dupli; }; class LightPathNode : public ShaderNode { @@ -436,6 +440,23 @@ public: float4 ramp[RAMP_TABLE_SIZE]; }; +class SetNormalNode : public ShaderNode { +public: + SHADER_NODE_CLASS(SetNormalNode) +}; + +class OSLScriptNode : public ShaderNode { +public: + SHADER_NODE_CLASS(OSLScriptNode) + string filepath; + string bytecode_hash; + + /* ShaderInput/ShaderOutput only stores a shallow string copy (const char *)! + * The actual socket names have to be stored externally to avoid memory errors. */ + vector input_names; + vector output_names; +}; + CCL_NAMESPACE_END #endif /* __NODES_H__ */ diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 7389b239627..25b4d1f08cc 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -51,20 +51,23 @@ Object::~Object() { } -void Object::compute_bounds(bool motion_blur) +void Object::compute_bounds(bool motion_blur, float shuttertime) { BoundBox mbounds = mesh->bounds; if(motion_blur && use_motion) { MotionTransform decomp; - transform_motion_decompose(&decomp, &motion); + transform_motion_decompose(&decomp, &motion, &tfm); bounds = BoundBox::empty; /* todo: this is really terrible. according to pbrt there is a better * way to find this iteratively, but did not find implementation yet * or try to implement myself */ - for(float t = 0.0f; t < 1.0f; t += 1.0f/128.0f) { + float start_t = 0.5f - shuttertime*0.25f; + float end_t = 0.5f + shuttertime*0.25f; + + for(float t = start_t; t < end_t; t += (1.0f/128.0f)*shuttertime) { Transform ttfm; transform_motion_interpolate(&ttfm, &decomp, t); @@ -109,7 +112,7 @@ void Object::apply_transform() if(bounds.valid()) { mesh->compute_bounds(); - compute_bounds(false); + compute_bounds(false, 0.0f); } /* tfm is not reset to identity, all code that uses it needs to check the @@ -151,7 +154,8 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene uint *object_flag = dscene->object_flag.resize(scene->objects.size()); int i = 0; map surface_area_map; - Scene::MotionType need_motion = scene->need_motion(); + Scene::MotionType need_motion = scene->need_motion(device->info.advanced_shading); + bool have_motion = false; foreach(Object *ob, scene->objects) { Mesh *mesh = ob->mesh; @@ -218,22 +222,29 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene mtfm_post = mtfm_post * itfm; memcpy(&objects[offset+8], &mtfm_pre, sizeof(float4)*4); - memcpy(&objects[offset+12], &mtfm_post, sizeof(float4)*4); + memcpy(&objects[offset+16], &mtfm_post, sizeof(float4)*4); } +#ifdef __OBJECT_MOTION__ else if(need_motion == Scene::MOTION_BLUR) { if(ob->use_motion) { /* decompose transformations for interpolation */ MotionTransform decomp; - transform_motion_decompose(&decomp, &ob->motion); - memcpy(&objects[offset+8], &decomp, sizeof(float4)*8); + transform_motion_decompose(&decomp, &ob->motion, &ob->tfm); + memcpy(&objects[offset+8], &decomp, sizeof(float4)*12); flag |= SD_OBJECT_MOTION; + have_motion = true; } else { float4 no_motion = make_float4(FLT_MAX); - memcpy(&objects[offset+8], &no_motion, sizeof(float4)); + memcpy(&objects[offset+8], &no_motion, sizeof(float4)*12); } } +#endif + + /* dupli object coords */ + objects[offset+20] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f); + objects[offset+21] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f); /* object flag */ if(ob->use_holdout) @@ -247,6 +258,8 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene device->tex_alloc("__objects", dscene->objects); device->tex_alloc("__object_flag", dscene->object_flag); + + dscene->data.bvh.have_motion = have_motion; } void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) @@ -293,7 +306,12 @@ void ObjectManager::apply_static_transforms(Scene *scene, Progress& progress) /* counter mesh users */ map mesh_users; - bool motion_blur = scene->need_motion() == Scene::MOTION_BLUR; +#ifdef __OBJECT_MOTION__ + Scene::MotionType need_motion = scene->need_motion(); + bool motion_blur = need_motion == Scene::MOTION_BLUR; +#else + bool motion_blur = false; +#endif foreach(Object *object, scene->objects) { map::iterator it = mesh_users.find(object->mesh); diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index 88677d79dff..922c886d961 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -49,6 +49,9 @@ public: bool use_motion; bool use_holdout; + float3 dupli_generated; + float2 dupli_uv; + int particle_id; Object(); @@ -56,7 +59,7 @@ public: void tag_update(Scene *scene); - void compute_bounds(bool motion_blur); + void compute_bounds(bool motion_blur, float shuttertime); void apply_transform(); }; diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index dbd6b0ac9d9..a8a40a4e596 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -31,6 +31,7 @@ #include "osl_shader.h" #include "util_foreach.h" +#include "util_md5.h" #include "util_path.h" #include "util_progress.h" @@ -46,20 +47,8 @@ OSLShaderManager::OSLShaderManager() { services = new OSLRenderServices(); - /* if we let OSL create it, it leaks */ - ts = TextureSystem::create(true); - ts->attribute("automip", 1); - ts->attribute("autotile", 64); - - ss = OSL::ShadingSystem::create(services, ts, &errhandler); - ss->attribute("lockgeom", 1); - ss->attribute("commonspace", "world"); - ss->attribute("optimize", 2); - //ss->attribute("debug", 1); - //ss->attribute("statistics:level", 1); - ss->attribute("searchpath:shader", path_get("shader").c_str()); - - OSLShader::register_closures(ss); + shading_system_init(); + texture_system_init(); } OSLShaderManager::~OSLShaderManager() @@ -71,18 +60,14 @@ OSLShaderManager::~OSLShaderManager() void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) { - /* test if we need to update */ - bool need_update = false; - - foreach(Shader *shader, scene->shaders) - if(shader->need_update) - need_update = true; - if(!need_update) return; device_free(device, dscene); + /* determine which shaders are in use */ + device_update_shaders_used(scene); + /* create shaders */ OSLGlobals *og = (OSLGlobals*)device->osl_memory(); @@ -94,7 +79,7 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene if(shader->sample_as_light && shader->has_surface_emission) scene->light_manager->need_update = true; - OSLCompiler compiler((void*)ss); + OSLCompiler compiler((void*)this, (void*)ss); compiler.background = (shader == scene->shaders[scene->default_background]); compiler.compile(og, shader); } @@ -110,6 +95,8 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene foreach(Shader *shader, scene->shaders) shader->need_update = false; + + need_update = false; /* set texture system */ scene->image_manager->set_osl_texture_system((void*)ts); @@ -135,10 +122,165 @@ void OSLShaderManager::device_free(Device *device, DeviceScene *dscene) og->background_state.reset(); } +void OSLShaderManager::texture_system_init() +{ + /* if we let OSL create it, it leaks */ + ts = TextureSystem::create(true); + ts->attribute("automip", 1); + ts->attribute("autotile", 64); + + /* effectively unlimited for now, until we support proper mipmap lookups */ + ts->attribute("max_memory_MB", 16384); +} + +void OSLShaderManager::shading_system_init() +{ + ss = OSL::ShadingSystem::create(services, ts, &errhandler); + ss->attribute("lockgeom", 1); + ss->attribute("commonspace", "world"); + ss->attribute("optimize", 2); + //ss->attribute("debug", 1); + //ss->attribute("statistics:level", 1); + ss->attribute("searchpath:shader", path_get("shader")); + + /* our own ray types */ + static const char *raytypes[] = { + "camera", /* PATH_RAY_CAMERA */ + "reflection", /* PATH_RAY_REFLECT */ + "refraction", /* PATH_RAY_TRANSMIT */ + "diffuse", /* PATH_RAY_DIFFUSE */ + "glossy", /* PATH_RAY_GLOSSY */ + "singular", /* PATH_RAY_SINGULAR */ + "transparent", /* PATH_RAY_TRANSPARENT */ + "shadow", /* PATH_RAY_SHADOW_OPAQUE */ + "shadow", /* PATH_RAY_SHADOW_TRANSPARENT */ + }; + + const int nraytypes = sizeof(raytypes)/sizeof(raytypes[0]); + ss->attribute("raytypes", TypeDesc(TypeDesc::STRING, nraytypes), raytypes); + + OSLShader::register_closures(ss); + + loaded_shaders.clear(); +} + +bool OSLShaderManager::osl_compile(const string& inputfile, const string& outputfile) +{ + vector options; + string stdosl_path; + + /* specify output file name */ + options.push_back("-o"); + options.push_back(outputfile); + + /* specify standard include path */ + options.push_back("-I" + path_get("shader")); + stdosl_path = path_get("shader/stdosl.h"); + + /* compile */ + OSL::OSLCompiler *compiler = OSL::OSLCompiler::create(); + bool ok = compiler->compile(inputfile, options, stdosl_path); + delete compiler; + + return ok; +} + +bool OSLShaderManager::osl_query(OSL::OSLQuery& query, const string& filepath) +{ + string searchpath = path_user_get("shaders"); + return query.open(filepath, searchpath); +} + +static string shader_filepath_hash(const string& filepath, uint64_t modified_time) +{ + /* compute a hash from filepath and modified time to detect changes */ + MD5Hash md5; + md5.append((const uint8_t*)filepath.c_str(), filepath.size()); + md5.append((const uint8_t*)&modified_time, sizeof(modified_time)); + + return md5.get_hex(); +} + +const char *OSLShaderManager::shader_test_loaded(const string& hash) +{ + set::iterator it = loaded_shaders.find(hash); + return (it == loaded_shaders.end())? NULL: it->c_str(); +} + +const char *OSLShaderManager::shader_load_filepath(string filepath) +{ + size_t len = filepath.size(); + string extension = filepath.substr(len - 4); + uint64_t modified_time = path_modified_time(filepath); + + if(extension == ".osl") { + /* .OSL File */ + string osopath = filepath.substr(0, len - 4) + ".oso"; + uint64_t oso_modified_time = path_modified_time(osopath); + + /* test if we have loaded the corresponding .OSO already */ + if(oso_modified_time != 0) { + const char *hash = shader_test_loaded(shader_filepath_hash(osopath, oso_modified_time)); + + if(hash) + return hash; + } + + /* autocompile .OSL to .OSO if needed */ + if(oso_modified_time == 0 || (oso_modified_time < modified_time)) { + OSLShaderManager::osl_compile(filepath, osopath); + modified_time = path_modified_time(osopath); + } + else + modified_time = oso_modified_time; + + filepath = osopath; + } + else { + if(extension == ".oso") { + /* .OSO File, nothing to do */ + } + else if(path_dirname(filepath) == "") { + /* .OSO File in search path */ + filepath = path_join(path_user_get("shaders"), filepath + ".oso"); + } + else { + /* unknown file */ + return NULL; + } + + /* test if we have loaded this .OSO already */ + const char *hash = shader_test_loaded(shader_filepath_hash(filepath, modified_time)); + + if(hash) + return hash; + } + + /* read oso bytecode from file */ + string bytecode_hash = shader_filepath_hash(filepath, modified_time); + string bytecode; + + if(!path_read_text(filepath, bytecode)) { + fprintf(stderr, "Cycles shader graph: failed to read file %s\n", filepath.c_str()); + loaded_shaders.insert(bytecode_hash); /* to avoid repeat tries */ + return NULL; + } + + return shader_load_bytecode(bytecode_hash, bytecode); +} + +const char *OSLShaderManager::shader_load_bytecode(const string& hash, const string& bytecode) +{ + ss->LoadMemoryShader(hash.c_str(), bytecode.c_str()); + + return loaded_shaders.insert(hash).first->c_str(); +} + /* Graph Compiler */ -OSLCompiler::OSLCompiler(void *shadingsys_) +OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_) { + manager = manager_; shadingsys = shadingsys_; current_type = SHADER_TYPE_SURFACE; current_shader = NULL; @@ -154,14 +296,43 @@ string OSLCompiler::id(ShaderNode *node) return stream.str(); } -string OSLCompiler::compatible_name(const char *name) +string OSLCompiler::compatible_name(ShaderNode *node, ShaderInput *input) { - string sname = name; + string sname(input->name); size_t i; + /* strip whitespace */ while((i = sname.find(" ")) != string::npos) sname.replace(i, 1, ""); + /* if output exists with the same name, add "In" suffix */ + foreach(ShaderOutput *output, node->outputs) { + if (strcmp(input->name, output->name)==0) { + sname += "In"; + break; + } + } + + return sname; +} + +string OSLCompiler::compatible_name(ShaderNode *node, ShaderOutput *output) +{ + string sname(output->name); + size_t i; + + /* strip whitespace */ + while((i = sname.find(" ")) != string::npos) + sname.replace(i, 1, ""); + + /* if output exists with the same name, add "In" suffix */ + foreach(ShaderInput *input, node->inputs) { + if (strcmp(input->name, output->name)==0) { + sname += "Out"; + break; + } + } + return sname; } @@ -177,6 +348,12 @@ bool OSLCompiler::node_skip_input(ShaderNode *node, ShaderInput *input) return true; if(strcmp(input->name, "Displacement") == 0 && current_type != SHADER_TYPE_DISPLACEMENT) return true; + if(strcmp(input->name, "Normal") == 0) + return true; + } + else if(node->name == ustring("bump")) { + if(strcmp(input->name, "Height") == 0) + return true; } else if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->name == ustring("bump")) return true; @@ -184,10 +361,18 @@ bool OSLCompiler::node_skip_input(ShaderNode *node, ShaderInput *input) return false; } -void OSLCompiler::add(ShaderNode *node, const char *name) +void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath) { OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; + /* load filepath */ + if(isfilepath) { + name = ((OSLShaderManager*)manager)->shader_load_filepath(name); + + if(name == NULL) + return; + } + /* pass in fixed parameter values */ foreach(ShaderInput *input, node->inputs) { if(!input->link) { @@ -198,21 +383,25 @@ void OSLCompiler::add(ShaderNode *node, const char *name) else if(input->default_value != ShaderInput::NONE) continue; + string param_name = compatible_name(node, input); switch(input->type) { case SHADER_SOCKET_COLOR: - parameter_color(compatible_name(input->name).c_str(), input->value); + parameter_color(param_name.c_str(), input->value); break; case SHADER_SOCKET_POINT: - parameter_point(compatible_name(input->name).c_str(), input->value); + parameter_point(param_name.c_str(), input->value); break; case SHADER_SOCKET_VECTOR: - parameter_vector(compatible_name(input->name).c_str(), input->value); + parameter_vector(param_name.c_str(), input->value); break; case SHADER_SOCKET_NORMAL: - parameter_normal(compatible_name(input->name).c_str(), input->value); + parameter_normal(param_name.c_str(), input->value); break; case SHADER_SOCKET_FLOAT: - parameter(compatible_name(input->name).c_str(), input->value.x); + parameter(param_name.c_str(), input->value.x); + break; + case SHADER_SOCKET_INT: + parameter(param_name.c_str(), (int)input->value.x); break; case SHADER_SOCKET_CLOSURE: break; @@ -242,12 +431,8 @@ void OSLCompiler::add(ShaderNode *node, const char *name) /* connect shaders */ string id_from = id(input->link->parent); string id_to = id(node); - string param_from = compatible_name(input->link->name); - string param_to = compatible_name(input->name); - - /* avoid name conflict with same input/output socket name */ - if(input->link->parent->input(input->link->name)) - param_from += "_"; + string param_from = compatible_name(input->link->parent, input->link); + string param_to = compatible_name(node, input); ss->ConnectShaders(id_from.c_str(), param_from.c_str(), id_to.c_str(), param_to.c_str()); } @@ -309,6 +494,70 @@ void OSLCompiler::parameter(const char *name, const Transform& tfm) ss->Parameter(name, TypeDesc::TypeMatrix, (float*)&tfm); } +void OSLCompiler::parameter_array(const char *name, const float f[], int arraylen) +{ + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; + TypeDesc type = TypeDesc::TypeFloat; + type.arraylen = arraylen; + ss->Parameter(name, type, f); +} + +void OSLCompiler::parameter_color_array(const char *name, const float f[][3], int arraylen) +{ + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; + TypeDesc type = TypeDesc::TypeColor; + type.arraylen = arraylen; + ss->Parameter(name, type, f); +} + +void OSLCompiler::parameter_vector_array(const char *name, const float f[][3], int arraylen) +{ + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; + TypeDesc type = TypeDesc::TypeVector; + type.arraylen = arraylen; + ss->Parameter(name, type, f); +} + +void OSLCompiler::parameter_normal_array(const char *name, const float f[][3], int arraylen) +{ + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; + TypeDesc type = TypeDesc::TypeNormal; + type.arraylen = arraylen; + ss->Parameter(name, type, f); +} + +void OSLCompiler::parameter_point_array(const char *name, const float f[][3], int arraylen) +{ + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; + TypeDesc type = TypeDesc::TypePoint; + type.arraylen = arraylen; + ss->Parameter(name, type, f); +} + +void OSLCompiler::parameter_array(const char *name, const int f[], int arraylen) +{ + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; + TypeDesc type = TypeDesc::TypeInt; + type.arraylen = arraylen; + ss->Parameter(name, type, f); +} + +void OSLCompiler::parameter_array(const char *name, const char * const s[], int arraylen) +{ + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; + TypeDesc type = TypeDesc::TypeString; + type.arraylen = arraylen; + ss->Parameter(name, type, s); +} + +void OSLCompiler::parameter_array(const char *name, const Transform tfm[], int arraylen) +{ + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; + TypeDesc type = TypeDesc::TypeMatrix; + type.arraylen = arraylen; + ss->Parameter(name, type, (const float *)tfm); +} + void OSLCompiler::find_dependencies(set& dependencies, ShaderInput *input) { ShaderNode *node = (input->link)? input->link->parent: NULL; @@ -392,82 +641,85 @@ void OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty void OSLCompiler::compile(OSLGlobals *og, Shader *shader) { - OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; - ShaderGraph *graph = shader->graph; - ShaderNode *output = (graph)? graph->output(): NULL; + if(shader->need_update) { + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; + ShaderGraph *graph = shader->graph; + ShaderNode *output = (graph)? graph->output(): NULL; - /* copy graph for shader with bump mapping */ - if(output->input("Surface")->link && output->input("Displacement")->link) - if(!shader->graph_bump) - shader->graph_bump = shader->graph->copy(); + /* copy graph for shader with bump mapping */ + if(output->input("Surface")->link && output->input("Displacement")->link) + if(!shader->graph_bump) + shader->graph_bump = shader->graph->copy(); - /* finalize */ - shader->graph->finalize(false, true); - if(shader->graph_bump) - shader->graph_bump->finalize(true, true); + /* finalize */ + shader->graph->finalize(false, true); + if(shader->graph_bump) + shader->graph_bump->finalize(true, true); - current_shader = shader; + current_shader = shader; - shader->has_surface = false; - shader->has_surface_emission = false; - shader->has_surface_transparent = false; - shader->has_volume = false; - shader->has_displacement = false; + shader->has_surface = false; + shader->has_surface_emission = false; + shader->has_surface_transparent = false; + shader->has_volume = false; + shader->has_displacement = false; - /* generate surface shader */ - if(graph && output->input("Surface")->link) { - compile_type(shader, shader->graph, SHADER_TYPE_SURFACE); - og->surface_state.push_back(ss->state()); + /* generate surface shader */ + if(shader->used && graph && output->input("Surface")->link) { + compile_type(shader, shader->graph, SHADER_TYPE_SURFACE); + shader->osl_surface_ref = ss->state(); - if(shader->graph_bump) { + if(shader->graph_bump) { + ss->clear_state(); + compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE); + } + + shader->osl_surface_bump_ref = ss->state(); + ss->clear_state(); + + shader->has_surface = true; + } + else { + shader->osl_surface_ref = OSL::ShadingAttribStateRef(); + shader->osl_surface_bump_ref = OSL::ShadingAttribStateRef(); + } + + /* generate volume shader */ + if(shader->used && graph && output->input("Volume")->link) { + compile_type(shader, shader->graph, SHADER_TYPE_VOLUME); + shader->has_volume = true; + + shader->osl_volume_ref = ss->state(); ss->clear_state(); - compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE); - og->surface_state.push_back(ss->state()); } else - og->surface_state.push_back(ss->state()); + shader->osl_volume_ref = OSL::ShadingAttribStateRef(); - ss->clear_state(); - - shader->has_surface = true; - } - else { - og->surface_state.push_back(OSL::ShadingAttribStateRef()); - og->surface_state.push_back(OSL::ShadingAttribStateRef()); + /* generate displacement shader */ + if(shader->used && graph && output->input("Displacement")->link) { + compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT); + shader->has_displacement = true; + shader->osl_displacement_ref = ss->state(); + ss->clear_state(); + } + else + shader->osl_displacement_ref = OSL::ShadingAttribStateRef(); } - /* generate volume shader */ - if(graph && output->input("Volume")->link) { - compile_type(shader, shader->graph, SHADER_TYPE_VOLUME); - shader->has_volume = true; + /* push state to array for lookup */ + og->surface_state.push_back(shader->osl_surface_ref); + og->surface_state.push_back(shader->osl_surface_bump_ref); - og->volume_state.push_back(ss->state()); - og->volume_state.push_back(ss->state()); - ss->clear_state(); - } - else { - og->volume_state.push_back(OSL::ShadingAttribStateRef()); - og->volume_state.push_back(OSL::ShadingAttribStateRef()); - } + og->volume_state.push_back(shader->osl_volume_ref); + og->volume_state.push_back(shader->osl_volume_ref); - /* generate displacement shader */ - if(graph && output->input("Displacement")->link) { - compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT); - shader->has_displacement = true; - - og->displacement_state.push_back(ss->state()); - og->displacement_state.push_back(ss->state()); - ss->clear_state(); - } - else { - og->displacement_state.push_back(OSL::ShadingAttribStateRef()); - og->displacement_state.push_back(OSL::ShadingAttribStateRef()); - } + og->displacement_state.push_back(shader->osl_displacement_ref); + og->displacement_state.push_back(shader->osl_displacement_ref); } #else -void OSLCompiler::add(ShaderNode *node, const char *name) +void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath) { } @@ -483,6 +735,14 @@ void OSLCompiler::parameter_vector(const char *name, float3 f) { } +void OSLCompiler::parameter_point(const char *name, float3 f) +{ +} + +void OSLCompiler::parameter_normal(const char *name, float3 f) +{ +} + void OSLCompiler::parameter(const char *name, int f) { } @@ -499,6 +759,38 @@ void OSLCompiler::parameter(const char *name, const Transform& tfm) { } +void OSLCompiler::parameter_array(const char *name, const float f[], int arraylen) +{ +} + +void OSLCompiler::parameter_color_array(const char *name, const float f[][3], int arraylen) +{ +} + +void OSLCompiler::parameter_vector_array(const char *name, const float f[][3], int arraylen) +{ +} + +void OSLCompiler::parameter_normal_array(const char *name, const float f[][3], int arraylen) +{ +} + +void OSLCompiler::parameter_point_array(const char *name, const float f[][3], int arraylen) +{ +} + +void OSLCompiler::parameter_array(const char *name, const int f[], int arraylen) +{ +} + +void OSLCompiler::parameter_array(const char *name, const char * const s[], int arraylen) +{ +} + +void OSLCompiler::parameter_array(const char *name, const Transform tfm[], int arraylen) +{ +} + #endif /* WITH_OSL */ CCL_NAMESPACE_END diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h index 329cf9a4828..cee37c58d74 100644 --- a/intern/cycles/render/osl.h +++ b/intern/cycles/render/osl.h @@ -20,11 +20,14 @@ #define __OSL_H__ #include "util_set.h" +#include "util_string.h" #include "shader.h" #ifdef WITH_OSL +#include #include +#include #endif CCL_NAMESPACE_BEGIN @@ -37,6 +40,7 @@ class OSLGlobals; class Scene; class ShaderGraph; class ShaderNode; +class ShaderInput; class ShaderOutput; #ifdef WITH_OSL @@ -51,11 +55,24 @@ public: void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_free(Device *device, DeviceScene *dscene); -private: + /* osl compile and query */ + static bool osl_compile(const string& inputfile, const string& outputfile); + static bool osl_query(OSL::OSLQuery& query, const string& filepath); + + /* shader file loading, all functions return pointer to hash string if found */ + const char *shader_test_loaded(const string& hash); + const char *shader_load_bytecode(const string& hash, const string& bytecode); + const char *shader_load_filepath(string filepath); + +protected: + void texture_system_init(); + void shading_system_init(); + OSL::ShadingSystem *ss; OSL::TextureSystem *ts; OSLRenderServices *services; OSL::ErrorHandler errhandler; + set loaded_shaders; }; #endif @@ -64,10 +81,10 @@ private: class OSLCompiler { public: - OSLCompiler(void *shadingsys); + OSLCompiler(void *manager, void *shadingsys); void compile(OSLGlobals *og, Shader *shader); - void add(ShaderNode *node, const char *name); + void add(ShaderNode *node, const char *name, bool isfilepath = false); void parameter(const char *name, float f); void parameter_color(const char *name, float3 f); @@ -79,6 +96,15 @@ public: void parameter(const char *name, ustring str); void parameter(const char *name, const Transform& tfm); + void parameter_array(const char *name, const float f[], int arraylen); + void parameter_color_array(const char *name, const float f[][3], int arraylen); + void parameter_vector_array(const char *name, const float f[][3], int arraylen); + void parameter_normal_array(const char *name, const float f[][3], int arraylen); + void parameter_point_array(const char *name, const float f[][3], int arraylen); + void parameter_array(const char *name, const int f[], int arraylen); + void parameter_array(const char *name, const char * const s[], int arraylen); + void parameter_array(const char *name, const Transform tfm[], int arraylen); + ShaderType output_type() { return current_type; } bool background; @@ -87,12 +113,14 @@ private: string id(ShaderNode *node); void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type); bool node_skip_input(ShaderNode *node, ShaderInput *input); - string compatible_name(const char *name); + string compatible_name(ShaderNode *node, ShaderInput *input); + string compatible_name(ShaderNode *node, ShaderOutput *output); void find_dependencies(set& dependencies, ShaderInput *input); void generate_nodes(const set& nodes); void *shadingsys; + void *manager; ShaderType current_type; Shader *current_shader; }; diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 071338d49c2..15031b9500c 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -183,10 +183,10 @@ void Scene::device_update(Device *device_, Progress& progress) device->const_copy_to("__data", &dscene.data, sizeof(dscene.data)); } -Scene::MotionType Scene::need_motion() +Scene::MotionType Scene::need_motion(bool advanced_shading) { if(integrator->motion_blur) - return MOTION_BLUR; + return (advanced_shading)? MOTION_BLUR: MOTION_NONE; else if(Pass::contains(film->passes, PASS_MOTION)) return MOTION_PASS; else diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 09087fb2970..bd45c1c04e6 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -194,7 +194,7 @@ public: void need_global_attributes(AttributeRequestSet& attributes); enum MotionType { MOTION_NONE = 0, MOTION_PASS, MOTION_BLUR }; - MotionType need_motion(); + MotionType need_motion(bool advanced_shading = true); bool need_update(); bool need_reset(); diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 05c57ba48ec..7303cb52ad8 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -34,16 +34,22 @@ CCL_NAMESPACE_BEGIN +/* Note about preserve_tile_device option for tile manager: + * progressive refine and viewport rendering does requires tiles to + * always be allocated for the same device + */ Session::Session(const SessionParams& params_) : params(params_), - tile_manager(params.progressive, params.samples, params.tile_size, params.resolution, - (params.background)? 1: max(params.device.multi_devices.size(), 1)) + tile_manager(params.progressive, params.samples, params.tile_size, params.start_resolution, + params.background == false || params.progressive_refine, params.background, + max(params.device.multi_devices.size(), 1)), + stats() { device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background); TaskScheduler::init(params.threads); - device = Device::create(params.device, params.background, params.threads); + device = Device::create(params.device, stats, params.background, params.threads); if(params.background) { buffers = NULL; @@ -96,6 +102,9 @@ Session::~Session() display->write(device, params.output_path); } + foreach(RenderBuffers *buffers, tile_buffers) + delete buffers; + delete buffers; delete display; delete scene; @@ -140,12 +149,6 @@ void Session::reset_gpu(BufferParams& buffer_params, int samples) pause_cond.notify_all(); } -bool Session::resetting_gpu() const -{ - /* no need to wait for gpu device */ - return false; -} - bool Session::draw_gpu(BufferParams& buffer_params) { /* block for buffer access */ @@ -179,9 +182,12 @@ bool Session::draw_gpu(BufferParams& buffer_params) void Session::run_gpu() { + bool tiles_written = false; + start_time = time_dt(); reset_time = time_dt(); paused_time = 0.0; + last_update_time = time_dt(); if(!params.background) progress.set_start_time(start_time + paused_time); @@ -273,10 +279,15 @@ void Session::run_gpu() if(device->error_message() != "") progress.set_cancel(device->error_message()); + tiles_written = update_progressive_refine(progress.get_cancel()); + if(progress.get_cancel()) break; } } + + if(!tiles_written) + update_progressive_refine(true); } /* CPU Session */ @@ -296,11 +307,6 @@ void Session::reset_cpu(BufferParams& buffer_params, int samples) pause_cond.notify_all(); } -bool Session::resetting_cpu() const -{ - return device->task_cancelled(); -} - bool Session::draw_cpu(BufferParams& buffer_params) { thread_scoped_lock display_lock(display_mutex); @@ -324,14 +330,18 @@ bool Session::draw_cpu(BufferParams& buffer_params) bool Session::acquire_tile(Device *tile_device, RenderTile& rtile) { - if(progress.get_cancel()) - return false; + if(progress.get_cancel()) { + if(params.progressive_refine == false) { + /* for progressive refine current sample should be finished for all tiles */ + return false; + } + } thread_scoped_lock tile_lock(tile_mutex); /* get next tile from manager */ Tile tile; - int device_num = (params.background)? 0: device->device_number(tile_device); + int device_num = device->device_number(tile_device); if(!tile_manager.next_tile(tile, device_num)) return false; @@ -343,13 +353,13 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile) rtile.h = tile.h; rtile.start_sample = tile_manager.state.sample; rtile.num_samples = tile_manager.state.num_samples; - rtile.resolution = tile_manager.state.resolution; + rtile.resolution = tile_manager.state.resolution_divider; tile_lock.unlock(); /* in case of a permant buffer, return it, otherwise we will allocate * a new temporary buffer */ - if(!write_render_tile_cb) { + if(!params.background) { tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride); rtile.buffer = buffers->buffer.device_pointer; @@ -371,9 +381,30 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile) buffer_params.get_offset_stride(rtile.offset, rtile.stride); - /* allocate buffers */ RenderBuffers *tilebuffers = new RenderBuffers(tile_device); - tilebuffers->reset(tile_device, buffer_params); + + /* allocate buffers */ + if(params.progressive_refine) { + tile_lock.lock(); + + if(tile_buffers.size() == 0) + tile_buffers.resize(tile_manager.state.num_tiles, NULL); + + tilebuffers = tile_buffers[tile.index]; + if(tilebuffers == NULL) { + tilebuffers = new RenderBuffers(tile_device); + tile_buffers[tile.index] = tilebuffers; + + tilebuffers->reset(tile_device, buffer_params); + } + + tile_lock.unlock(); + } + else { + tilebuffers = new RenderBuffers(tile_device); + + tilebuffers->reset(tile_device, buffer_params); + } rtile.buffer = tilebuffers->buffer.device_pointer; rtile.rng_state = tilebuffers->rng_state.device_pointer; @@ -388,9 +419,11 @@ void Session::update_tile_sample(RenderTile& rtile) thread_scoped_lock tile_lock(tile_mutex); if(update_render_tile_cb) { - /* todo: optimize this by making it thread safe and removing lock */ + if(params.progressive_refine == false) { + /* todo: optimize this by making it thread safe and removing lock */ - update_render_tile_cb(rtile); + update_render_tile_cb(rtile); + } } update_status_time(); @@ -401,10 +434,12 @@ void Session::release_tile(RenderTile& rtile) thread_scoped_lock tile_lock(tile_mutex); if(write_render_tile_cb) { - /* todo: optimize this by making it thread safe and removing lock */ - write_render_tile_cb(rtile); + if(params.progressive_refine == false) { + /* todo: optimize this by making it thread safe and removing lock */ + write_render_tile_cb(rtile); - delete rtile.buffers; + delete rtile.buffers; + } } update_status_time(); @@ -412,6 +447,10 @@ void Session::release_tile(RenderTile& rtile) void Session::run_cpu() { + bool tiles_written = false; + + last_update_time = time_dt(); + { /* reset once to start */ thread_scoped_lock reset_lock(delayed_reset.mutex); @@ -513,10 +552,15 @@ void Session::run_cpu() if(device->error_message() != "") progress.set_cancel(device->error_message()); + + tiles_written = update_progressive_refine(progress.get_cancel()); } progress.set_update(); } + + if(!tiles_written) + update_progressive_refine(true); } void Session::run() @@ -595,14 +639,6 @@ void Session::reset(BufferParams& buffer_params, int samples) reset_cpu(buffer_params, samples); } -bool Session::resetting() const -{ - if(device_use_gl) - return resetting_gpu(); - else - return resetting_cpu(); -} - void Session::set_samples(int samples) { if(samples != params.samples) { @@ -668,7 +704,7 @@ void Session::update_scene() void Session::update_status_time(bool show_pause, bool show_done) { int sample = tile_manager.state.sample; - int resolution = tile_manager.state.resolution; + int resolution = tile_manager.state.resolution_divider; int num_tiles = tile_manager.state.num_tiles; int tile = tile_manager.state.num_rendered_tiles; @@ -676,10 +712,13 @@ void Session::update_status_time(bool show_pause, bool show_done) string status, substatus; if(!params.progressive) { + bool is_gpu = params.device.type == DEVICE_CUDA || params.device.type == DEVICE_OPENCL; + bool is_multidevice = params.device.multi_devices.size() > 1; + bool is_cpu = params.device.type == DEVICE_CPU; + substatus = string_printf("Path Tracing Tile %d/%d", tile, num_tiles); - if(params.device.type == DEVICE_CUDA || params.device.type == DEVICE_OPENCL || - (params.device.type == DEVICE_CPU && num_tiles == 1)) { + if((is_gpu && !is_multidevice) || (is_cpu && num_tiles == 1)) { /* when rendering on GPU multithreading happens within single tile, as in * tiles are handling sequentially and in this case we could display * currently rendering sample number @@ -741,6 +780,7 @@ void Session::path_trace() task.get_cancel = function_bind(&Progress::get_cancel, &this->progress); task.update_tile_sample = function_bind(&Session::update_tile_sample, this, _1); task.update_progress_sample = function_bind(&Session::update_progress_sample, this); + task.need_finish_queue = params.progressive_refine; device->task_add(task); } @@ -757,7 +797,7 @@ void Session::tonemap() task.rgba = display->rgba.device_pointer; task.buffer = buffers->buffer.device_pointer; task.sample = tile_manager.state.sample; - task.resolution = tile_manager.state.resolution; + task.resolution = tile_manager.state.resolution_divider; tile_manager.state.buffer.get_offset_stride(task.offset, task.stride); if(task.w > 0 && task.h > 0) { @@ -771,5 +811,35 @@ void Session::tonemap() display_outdated = false; } -CCL_NAMESPACE_END +bool Session::update_progressive_refine(bool cancel) +{ + int sample = tile_manager.state.sample + 1; + bool write = sample == params.samples || cancel; + double current_time = time_dt(); + + if (current_time - last_update_time < 1.0f) { + /* if last sample was processed, we need to write buffers anyway */ + if (!write) + return false; + } + + if(params.progressive_refine) { + foreach(RenderBuffers *buffers, tile_buffers) { + RenderTile rtile; + rtile.buffers = buffers; + rtile.sample = sample; + + if(write) + write_render_tile_cb(rtile); + else + update_render_tile_cb(rtile); + } + } + + last_update_time = current_time; + + return write; +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index e45753d22a0..7bb0cd1ae01 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -24,7 +24,9 @@ #include "tile.h" #include "util_progress.h" +#include "util_stats.h" #include "util_thread.h" +#include "util_vector.h" CCL_NAMESPACE_BEGIN @@ -42,50 +44,58 @@ class SessionParams { public: DeviceInfo device; bool background; + bool progressive_refine; string output_path; bool progressive; bool experimental; int samples; int2 tile_size; - int resolution; + int start_resolution; int threads; double cancel_timeout; double reset_timeout; double text_timeout; + enum { OSL, SVM } shadingsystem; + SessionParams() { background = false; + progressive_refine = false; output_path = ""; progressive = false; experimental = false; samples = INT_MAX; tile_size = make_int2(64, 64); - resolution = 4; + start_resolution = INT_MAX; threads = 0; cancel_timeout = 0.1; reset_timeout = 0.1; text_timeout = 1.0; + + shadingsystem = SVM; } bool modified(const SessionParams& params) { return !(device.type == params.device.type && device.id == params.device.id && background == params.background + && progressive_refine == params.progressive_refine && output_path == params.output_path /* && samples == params.samples */ && progressive == params.progressive && experimental == params.experimental && tile_size == params.tile_size - && resolution == params.resolution + && start_resolution == params.start_resolution && threads == params.threads && cancel_timeout == params.cancel_timeout && reset_timeout == params.reset_timeout - && text_timeout == params.text_timeout); } + && text_timeout == params.text_timeout + && shadingsystem == params.shadingsystem); } }; @@ -103,6 +113,7 @@ public: Progress progress; SessionParams params; TileManager tile_manager; + Stats stats; boost::function write_render_tile_cb; boost::function update_render_tile_cb; @@ -116,7 +127,6 @@ public: bool ready_to_reset(); void reset(BufferParams& params, int samples); - bool resetting() const; void set_samples(int samples); void set_pause(bool pause); @@ -140,12 +150,10 @@ protected: void run_cpu(); bool draw_cpu(BufferParams& params); void reset_cpu(BufferParams& params, int samples); - bool resetting_cpu() const; void run_gpu(); bool draw_gpu(BufferParams& params); void reset_gpu(BufferParams& params, int samples); - bool resetting_gpu() const; bool acquire_tile(Device *tile_device, RenderTile& tile); void update_tile_sample(RenderTile& tile); @@ -176,6 +184,12 @@ protected: double reset_time; double preview_time; double paused_time; + + /* progressive refine */ + double last_update_time; + bool update_progressive_refine(bool cancel); + + vector tile_buffers; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index fae1d6bd81c..17f7fbd43d6 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -49,6 +49,8 @@ Shader::Shader() has_volume = false; has_displacement = false; + used = false; + need_update = true; need_update_attributes = true; } @@ -98,6 +100,16 @@ void Shader::tag_update(Scene *scene) } } +void Shader::tag_used(Scene *scene) +{ + /* if an unused shader suddenly gets used somewhere, it needs to be + * recompiled because it was skipped for compilation before */ + if(!used) { + need_update = true; + scene->shader_manager->need_update = true; + } +} + /* Shader Manager */ ShaderManager::ShaderManager() @@ -161,6 +173,27 @@ int ShaderManager::get_shader_id(uint shader, Mesh *mesh, bool smooth) return id; } +void ShaderManager::device_update_shaders_used(Scene *scene) +{ + /* figure out which shaders are in use, so SVM/OSL can skip compiling them + * for speed and avoid loading image textures into memory */ + foreach(Shader *shader, scene->shaders) + shader->used = false; + + scene->shaders[scene->default_surface]->used = true; + scene->shaders[scene->default_light]->used = true; + scene->shaders[scene->default_background]->used = true; + scene->shaders[scene->default_holdout]->used = true; + scene->shaders[scene->default_empty]->used = true; + + foreach(Mesh *mesh, scene->meshes) + foreach(uint shader, mesh->used_shaders) + scene->shaders[shader]->used = true; + + foreach(Light *light, scene->lights) + scene->shaders[light->shader]->used = true; +} + void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) { device_free_common(device, dscene); diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index 02788008060..373b3356f51 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -27,6 +27,10 @@ #include "util_string.h" #include "util_types.h" +#ifdef WITH_OSL +#include +#endif + CCL_NAMESPACE_BEGIN class Device; @@ -75,11 +79,23 @@ public: /* requested mesh attributes */ AttributeRequestSet attributes; + /* determined before compiling */ + bool used; + +#ifdef WITH_OSL + /* osl shading state references */ + OSL::ShadingAttribStateRef osl_surface_ref; + OSL::ShadingAttribStateRef osl_surface_bump_ref; + OSL::ShadingAttribStateRef osl_volume_ref; + OSL::ShadingAttribStateRef osl_displacement_ref; +#endif + Shader(); ~Shader(); void set_graph(ShaderGraph *graph); void tag_update(Scene *scene); + void tag_used(Scene *scene); }; /* Shader Manager virtual base class @@ -98,6 +114,7 @@ public: virtual void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) = 0; virtual void device_free(Device *device, DeviceScene *dscene) = 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); diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 844ce01569f..dc249984499 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -48,6 +48,9 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene /* test if we need to update */ device_free(device, dscene); + /* determine which shaders are in use */ + device_update_shaders_used(scene); + /* svm_nodes */ vector svm_nodes; size_t i; @@ -119,6 +122,8 @@ int SVMCompiler::stack_size(ShaderSocketType type) { if(type == SHADER_SOCKET_FLOAT) return 1; + else if(type == SHADER_SOCKET_INT) + return 1; else if(type == SHADER_SOCKET_COLOR) return 3; else if(type == SHADER_SOCKET_VECTOR) @@ -212,10 +217,13 @@ void SVMCompiler::stack_assign(ShaderInput *input) if(input->type == SHADER_SOCKET_FLOAT) { add_node(NODE_VALUE_F, __float_as_int(input->value.x), input->stack_offset); } + else if(input->type == SHADER_SOCKET_INT) { + add_node(NODE_VALUE_F, (int)input->value.x, input->stack_offset); + } else if(input->type == SHADER_SOCKET_VECTOR || - input->type == SHADER_SOCKET_NORMAL || - input->type == SHADER_SOCKET_POINT || - input->type == SHADER_SOCKET_COLOR) { + input->type == SHADER_SOCKET_NORMAL || + input->type == SHADER_SOCKET_POINT || + input->type == SHADER_SOCKET_COLOR) { add_node(NODE_VALUE_V, input->stack_offset); add_node(NODE_VALUE_V, input->value); @@ -604,37 +612,39 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty output->stack_offset = SVM_STACK_INVALID; } - if(clin->link) { - bool generate = false; - if(type == SHADER_TYPE_SURFACE) { - /* generate surface shader */ - generate = true; - shader->has_surface = true; - } - else if(type == SHADER_TYPE_VOLUME) { - /* generate volume shader */ - generate = true; - shader->has_volume = true; - } - else if(type == SHADER_TYPE_DISPLACEMENT) { - /* generate displacement shader */ - generate = true; - shader->has_displacement = true; + if(shader->used) { + if(clin->link) { + bool generate = false; + if(type == SHADER_TYPE_SURFACE) { + /* generate surface shader */ + generate = true; + shader->has_surface = true; + } + else if(type == SHADER_TYPE_VOLUME) { + /* generate volume shader */ + generate = true; + shader->has_volume = true; + } + else if(type == SHADER_TYPE_DISPLACEMENT) { + /* generate displacement shader */ + generate = true; + shader->has_displacement = true; + } + + if(generate) { + set done; + + if(use_multi_closure) + generate_multi_closure(clin->link->parent, done, SVM_STACK_INVALID); + else + generate_closure(clin->link->parent, done); + } } - if(generate) { - set done; - - if(use_multi_closure) - generate_multi_closure(clin->link->parent, done, SVM_STACK_INVALID); - else - generate_closure(clin->link->parent, done); - } + /* compile output node */ + node->compile(*this); } - /* compile output node */ - node->compile(*this); - add_node(NODE_END, 0, 0, 0); } diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index b4156fd9471..74585dd5058 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -23,12 +23,15 @@ CCL_NAMESPACE_BEGIN -TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int resolution_, int num_devices_) +TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int start_resolution_, + bool preserve_tile_device_, bool background_, int num_devices_) { progressive = progressive_; tile_size = tile_size_; - resolution = resolution_; + start_resolution = start_resolution_; num_devices = num_devices_; + preserve_tile_device = preserve_tile_device_; + background = background_; BufferParams buffer_params; reset(buffer_params, 0); @@ -42,6 +45,18 @@ void TileManager::reset(BufferParams& params_, int num_samples_) { params = params_; + int divider = 1; + int w = params.width, h = params.height; + + if(start_resolution != INT_MAX) { + while(w*h > start_resolution*start_resolution) { + w = max(1, w/2); + h = max(1, h/2); + + divider *= 2; + } + } + num_samples = num_samples_; state.buffer = BufferParams(); @@ -49,7 +64,7 @@ void TileManager::reset(BufferParams& params_, int num_samples_) state.num_tiles = 0; state.num_rendered_tiles = 0; state.num_samples = 0; - state.resolution = resolution; + state.resolution_divider = divider; state.tiles.clear(); } @@ -58,15 +73,55 @@ void TileManager::set_samples(int num_samples_) num_samples = num_samples_; } -void TileManager::set_tiles() +/* splits image into tiles and assigns equal amount of tiles to every render device */ +void TileManager::gen_tiles_global() { - int resolution = state.resolution; + int resolution = state.resolution_divider; int image_w = max(1, params.width/resolution); int image_h = max(1, params.height/resolution); state.tiles.clear(); - int num = min(image_h, num_devices); + int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 1)/tile_size.x; + int tile_h = (tile_size.y >= image_h)? 1: (image_h + tile_size.y - 1)/tile_size.y; + + int num_logical_devices = preserve_tile_device? num_devices: 1; + int num = min(image_h, num_logical_devices); + int tile_index = 0; + + int tiles_per_device = (tile_w * tile_h + num - 1) / num; + int cur_device = 0, cur_tiles = 0; + + for(int tile_y = 0; tile_y < tile_h; tile_y++) { + for(int tile_x = 0; tile_x < tile_w; tile_x++, tile_index++) { + int x = tile_x * tile_size.x; + int y = tile_y * tile_size.y; + int w = (tile_x == tile_w-1)? image_w - x: tile_size.x; + int h = (tile_y == tile_h-1)? image_h - y: tile_size.y; + + state.tiles.push_back(Tile(tile_index, x, y, w, h, cur_device)); + cur_tiles++; + + if(cur_tiles == tiles_per_device) { + cur_tiles = 0; + cur_device++; + } + } + } +} + +/* slices image into as much pieces as how many devices are rendering this image */ +void TileManager::gen_tiles_sliced() +{ + int resolution = state.resolution_divider; + int image_w = max(1, params.width/resolution); + int image_h = max(1, params.height/resolution); + + state.tiles.clear(); + + int num_logical_devices = preserve_tile_device? num_devices: 1; + int num = min(image_h, num_logical_devices); + int tile_index = 0; for(int device = 0; device < num; device++) { int device_y = (image_h/num)*device; @@ -74,20 +129,30 @@ void TileManager::set_tiles() int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 1)/tile_size.x; int tile_h = (tile_size.y >= device_h)? 1: (device_h + tile_size.y - 1)/tile_size.y; - int sub_w = (image_w + tile_w - 1)/tile_w; - int sub_h = (device_h + tile_h - 1)/tile_h; for(int tile_y = 0; tile_y < tile_h; tile_y++) { - for(int tile_x = 0; tile_x < tile_w; tile_x++) { - int x = tile_x * sub_w; - int y = tile_y * sub_h; - int w = (tile_x == tile_w-1)? image_w - x: sub_w; - int h = (tile_y == tile_h-1)? device_h - y: sub_h; + for(int tile_x = 0; tile_x < tile_w; tile_x++, tile_index++) { + int x = tile_x * tile_size.x; + int y = tile_y * tile_size.y; + int w = (tile_x == tile_w-1)? image_w - x: tile_size.x; + int h = (tile_y == tile_h-1)? device_h - y: tile_size.x; - state.tiles.push_back(Tile(x, y + device_y, w, h, device)); + state.tiles.push_back(Tile(tile_index, x, y + device_y, w, h, device)); } } } +} + +void TileManager::set_tiles() +{ + int resolution = state.resolution_divider; + int image_w = max(1, params.width/resolution); + int image_h = max(1, params.height/resolution); + + if(background) + gen_tiles_global(); + else + gen_tiles_sliced(); state.num_tiles = state.tiles.size(); @@ -104,17 +169,14 @@ list::iterator TileManager::next_center_tile(int device) { list::iterator iter, best = state.tiles.end(); - int resolution = state.resolution; + int resolution = state.resolution_divider; int image_w = max(1, params.width/resolution); int image_h = max(1, params.height/resolution); - int num = min(image_h, num_devices); + int logical_device = preserve_tile_device? device: 0; - int device_y = (image_h / num) * device; - int device_h = (device == num - 1) ? image_h - device * (image_h / num) : image_h / num; - - int64_t centx = image_w / 2, centy = device_y + device_h / 2, tot = 1; - int64_t mindist = (int64_t) image_w * (int64_t) device_h; + int64_t centx = image_w / 2, centy = image_h / 2, tot = 1; + int64_t mindist = (int64_t) image_w * (int64_t) image_h; /* find center of rendering tiles, image center counts for 1 too */ for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) { @@ -131,7 +193,7 @@ list::iterator TileManager::next_center_tile(int device) /* closest of the non-rendering tiles */ for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) { - if(iter->device == device && iter->rendering == false) { + if(iter->device == logical_device && iter->rendering == false) { Tile &cur_tile = *iter; int64_t distx = centx - (cur_tile.x + cur_tile.w / 2); @@ -148,11 +210,28 @@ list::iterator TileManager::next_center_tile(int device) return best; } +list::iterator TileManager::next_simple_tile(int device) +{ + list::iterator iter; + + int logical_device = preserve_tile_device? device: 0; + + for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) { + if(iter->device == logical_device && iter->rendering == false) + return iter; + } + + return state.tiles.end(); +} + bool TileManager::next_tile(Tile& tile, int device) { list::iterator tile_it; - tile_it = next_center_tile(device); + if(background) + tile_it = next_center_tile(device); + else + tile_it = next_simple_tile(device); if(tile_it != state.tiles.end()) { tile_it->rendering = true; @@ -167,7 +246,7 @@ bool TileManager::next_tile(Tile& tile, int device) bool TileManager::done() { - return (state.sample+state.num_samples >= num_samples && state.resolution == 1); + return (state.sample+state.num_samples >= num_samples && state.resolution_divider == 1); } bool TileManager::next() @@ -175,9 +254,9 @@ bool TileManager::next() if(done()) return false; - if(progressive && state.resolution > 1) { + if(progressive && state.resolution_divider > 1) { state.sample = 0; - state.resolution /= 2; + state.resolution_divider /= 2; state.num_samples = 1; set_tiles(); } @@ -189,7 +268,7 @@ bool TileManager::next() else state.num_samples = num_samples; - state.resolution = 1; + state.resolution_divider = 1; set_tiles(); } diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h index 29f2b1ef9f9..6f7a8f20734 100644 --- a/intern/cycles/render/tile.h +++ b/intern/cycles/render/tile.h @@ -30,6 +30,7 @@ CCL_NAMESPACE_BEGIN class Tile { public: + int index; int x, y, w, h; int device; bool rendering; @@ -37,8 +38,8 @@ public: Tile() {} - Tile(int x_, int y_, int w_, int h_, int device_) - : x(x_), y(y_), w(w_), h(h_), device(device_), rendering(false) {} + Tile(int index_, int x_, int y_, int w_, int h_, int device_) + : index(index_), x(x_), y(y_), w(w_), h(h_), device(device_), rendering(false) {} }; /* Tile Manager */ @@ -51,13 +52,14 @@ public: BufferParams buffer; int sample; int num_samples; - int resolution; + int resolution_divider; int num_tiles; int num_rendered_tiles; list tiles; } state; - TileManager(bool progressive, int num_samples, int2 tile_size, int resolution, int num_devices = 1); + TileManager(bool progressive, int num_samples, int2 tile_size, int start_resolution, + bool preserve_tile_device, bool background, int num_devices = 1); ~TileManager(); void reset(BufferParams& params, int num_samples); @@ -72,12 +74,41 @@ protected: bool progressive; int num_samples; int2 tile_size; - int resolution; + int start_resolution; int num_devices; - int start_resolution; + /* in some cases it is important that the same tile will be returned for the same + * device it was originally generated for (i.e. viewport rendering when buffer is + * allocating once for tile and then always used by it) + * + * in other cases any tile could be handled by any device (i.e. final rendering + * without progressive refine) + */ + bool preserve_tile_device; - list::iterator next_center_tile(int device = 0); + /* for background render tiles should exactly match render parts generated from + * blender side, which means image first gets split into tiles and then tiles are + * assigning to render devices + * + * however viewport rendering expects tiles to be allocated in a special way, + * meaning image is being sliced horizontally first and every device handles + * it's own slice + */ + bool background; + + /* splits image into tiles and assigns equal amount of tiles to every render device */ + void gen_tiles_global(); + + /* slices image into as much pieces as how many devices are rendering this image */ + void gen_tiles_sliced(); + + /* returns closest tile to center of rendered tiles + * mimics behavior of blender internal's tile order + */ + list::iterator next_center_tile(int device); + + /* returns first unhandled tile starting from left bottom corner of the image */ + list::iterator next_simple_tile(int device); }; CCL_NAMESPACE_END diff --git a/intern/cycles/subd/CMakeLists.txt b/intern/cycles/subd/CMakeLists.txt index 75f70753ddf..838776d60bf 100644 --- a/intern/cycles/subd/CMakeLists.txt +++ b/intern/cycles/subd/CMakeLists.txt @@ -7,6 +7,10 @@ set(INC ../render ) +set(INC_SYS + +) + set(SRC subd_build.cpp subd_dice.cpp @@ -31,5 +35,6 @@ set(SRC_HEADERS ) include_directories(${INC}) +include_directories(SYSTEM ${INC_SYS}) add_library(cycles_subd ${SRC} ${SRC_HEADERS}) diff --git a/intern/cycles/subd/subd_build.cpp b/intern/cycles/subd/subd_build.cpp index 312980f1fa2..8e84da7f019 100644 --- a/intern/cycles/subd/subd_build.cpp +++ b/intern/cycles/subd/subd_build.cpp @@ -333,7 +333,7 @@ void SubdAccBuilder::computeEdgeStencil(SubdFaceRing *ring, GregoryAccStencil *s /* @@ this probably does not provide watertight results!! (1/3 + 1/3 + 1/3 != 1) */ /* distribute weight to all verts */ - stencil->get(eid1, vert) += beta * costerm1_b / 3.0f; + stencil->get(eid1, vert) += beta * costerm1_b / 3.0f; stencil->get(eid1, edge->to()) += beta * costerm1_b / 3.0f; stencil->get(eid1, edge->next->to()) += beta * costerm1_b / 3.0f; diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt index ae8403a14a8..bf5f791a245 100644 --- a/intern/cycles/util/CMakeLists.txt +++ b/intern/cycles/util/CMakeLists.txt @@ -1,6 +1,9 @@ set(INC . +) + +set(INC_SYS ${GLEW_INCLUDE_PATH} ${OPENGL_INCLUDE_DIR} ) @@ -64,5 +67,6 @@ set(SRC_HEADERS ) include_directories(${INC}) +include_directories(SYSTEM ${INC_SYS}) add_library(cycles_util ${SRC} ${SRC_HEADERS}) diff --git a/intern/cycles/util/util_attribute.cpp b/intern/cycles/util/util_attribute.cpp index 3a1c2b6f332..163a92902f3 100644 --- a/intern/cycles/util/util_attribute.cpp +++ b/intern/cycles/util/util_attribute.cpp @@ -30,6 +30,8 @@ const char *attribute_standard_name(AttributeStandard std) return "uv"; else if(std == ATTR_STD_GENERATED) return "generated"; + else if(std == ATTR_STD_TANGENT) + return "tangent"; else if(std == ATTR_STD_POSITION_UNDEFORMED) return "undeformed"; else if(std == ATTR_STD_POSITION_UNDISPLACED) diff --git a/intern/cycles/util/util_cuda.cpp b/intern/cycles/util/util_cuda.cpp index 2960022fd8d..2716f00e173 100644 --- a/intern/cycles/util/util_cuda.cpp +++ b/intern/cycles/util/util_cuda.cpp @@ -17,6 +17,7 @@ */ #include +#include #include "util_cuda.h" #include "util_debug.h" @@ -413,8 +414,18 @@ string cuCompilerPath() return nvcc; #ifndef _WIN32 - if(system("which nvcc") == 0) - return "nvcc"; + { + FILE *handle = popen("which nvcc", "r"); + if(handle) { + char buffer[4096] = {0}; + int len = fread(buffer, 1, sizeof(buffer) - 1, handle); + buffer[len] = '\0'; + pclose(handle); + + if(buffer[0]) + return "nvcc"; + } + } #endif return ""; diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index 71a5dedeaa4..70adee4385b 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -26,7 +26,9 @@ #ifndef __KERNEL_OPENCL__ -#define _USE_MATH_DEFINES +#ifdef _MSC_VER +# define _USE_MATH_DEFINES +#endif #include #include @@ -1067,6 +1069,29 @@ __device_inline float3 safe_divide_color(float3 a, float3 b) return make_float3(x, y, z); } +/* Rotation of point around axis and angle */ + +__device_inline float3 rotate_around_axis(float3 p, float3 axis, float angle) +{ + float costheta = cosf(angle); + float sintheta = sinf(angle); + float3 r; + + r.x = ((costheta + (1 - costheta) * axis.x * axis.x) * p.x) + + (((1 - costheta) * axis.x * axis.y - axis.z * sintheta) * p.y) + + (((1 - costheta) * axis.x * axis.z + axis.y * sintheta) * p.z); + + r.y = (((1 - costheta) * axis.x * axis.y + axis.z * sintheta) * p.x) + + ((costheta + (1 - costheta) * axis.y * axis.y) * p.y) + + (((1 - costheta) * axis.y * axis.z - axis.x * sintheta) * p.z); + + r.z = (((1 - costheta) * axis.x * axis.z - axis.y * sintheta) * p.x) + + (((1 - costheta) * axis.y * axis.z + axis.x * sintheta) * p.y) + + ((costheta + (1 - costheta) * axis.z * axis.z) * p.z); + + return r; +} + CCL_NAMESPACE_END #endif /* __UTIL_MATH_H__ */ diff --git a/intern/cycles/util/util_md5.h b/intern/cycles/util/util_md5.h index 43e08e64f39..aab177d9fe6 100644 --- a/intern/cycles/util/util_md5.h +++ b/intern/cycles/util/util_md5.h @@ -44,7 +44,7 @@ public: bool append_file(const string& filepath); string get_hex(); - protected: +protected: void process(const uint8_t *data); void finish(uint8_t digest[16]); diff --git a/intern/cycles/util/util_path.cpp b/intern/cycles/util/util_path.cpp index a571fe81118..8cf23bc6a76 100644 --- a/intern/cycles/util/util_path.cpp +++ b/intern/cycles/util/util_path.cpp @@ -170,7 +170,7 @@ bool path_read_binary(const string& path, vector& binary) return true; } -static bool path_read_text(const string& path, string& text) +bool path_read_text(const string& path, string& text) { vector binary; @@ -184,6 +184,14 @@ static bool path_read_text(const string& path, string& text) return true; } +uint64_t path_modified_time(const string& path) +{ + if(boost::filesystem::exists(path)) + return (uint64_t)boost::filesystem::last_write_time(path); + + return 0; +} + string path_source_replace_includes(const string& source_, const string& path) { /* our own little c preprocessor that replaces #includes with the file diff --git a/intern/cycles/util/util_path.h b/intern/cycles/util/util_path.h index 6cba6a3158f..89e4452ecd9 100644 --- a/intern/cycles/util/util_path.h +++ b/intern/cycles/util/util_path.h @@ -45,6 +45,9 @@ string path_files_md5_hash(const string& dir); void path_create_directories(const string& path); bool path_write_binary(const string& path, const vector& binary); bool path_read_binary(const string& path, vector& binary); +bool path_read_text(const string& path, string& text); + +uint64_t path_modified_time(const string& path); string path_source_replace_includes(const string& source, const string& path); diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h index ab9ab7243e9..c97379d8776 100644 --- a/intern/cycles/util/util_progress.h +++ b/intern/cycles/util/util_progress.h @@ -43,6 +43,8 @@ public: tile_time = 0.0f; status = "Initializing"; substatus = ""; + sync_status = ""; + sync_substatus = ""; update_cb = NULL; cancel = false; cancel_message = ""; @@ -164,11 +166,42 @@ public: set_update(); } + void set_sync_status(const string& status_, const string& substatus_ = "") + { + { + thread_scoped_lock lock(progress_mutex); + sync_status = status_; + sync_substatus = substatus_; + total_time = time_dt() - start_time; + } + + set_update(); + + } + + void set_sync_substatus(const string& substatus_) + { + { + thread_scoped_lock lock(progress_mutex); + sync_substatus = substatus_; + total_time = time_dt() - start_time; + } + + set_update(); + } + void get_status(string& status_, string& substatus_) { thread_scoped_lock lock(progress_mutex); - status_ = status; - substatus_ = substatus; + + if(sync_status != "") { + status_ = sync_status; + substatus_ = sync_substatus; + } + else { + status_ = status; + substatus_ = substatus; + } } /* callback */ @@ -202,6 +235,9 @@ protected: string status; string substatus; + string sync_status; + string sync_substatus; + volatile bool cancel; string cancel_message; }; diff --git a/intern/cycles/util/util_stats.h b/intern/cycles/util/util_stats.h new file mode 100644 index 00000000000..405c81a1e1f --- /dev/null +++ b/intern/cycles/util/util_stats.h @@ -0,0 +1,53 @@ +/* + * Copyright 2012, 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 __UTIL_STATS_H__ +#define __UTIL_STATS_H__ + +#include "util_thread.h" + +CCL_NAMESPACE_BEGIN + +class Stats { +public: + Stats() : lock(), mem_used(0), mem_peak(0) {} + + void mem_alloc(size_t size) { + lock.lock(); + + mem_used += size; + if(mem_used > mem_peak) + mem_peak = mem_used; + + lock.unlock(); + } + + void mem_free(size_t size) { + lock.lock(); + mem_used -= size; + lock.unlock(); + } + + spin_lock lock; + size_t mem_used; + size_t mem_peak; +}; + +CCL_NAMESPACE_END + +#endif /* __UTIL_STATS_H__ */ diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp index 2b209c135f4..ea0abd6f54f 100644 --- a/intern/cycles/util/util_task.cpp +++ b/intern/cycles/util/util_task.cpp @@ -38,8 +38,6 @@ TaskPool::~TaskPool() void TaskPool::push(Task *task, bool front) { - thread_scoped_lock num_lock(num_mutex); - TaskScheduler::Entry entry; entry.task = task; @@ -104,17 +102,22 @@ void TaskPool::wait_work() void TaskPool::cancel() { - thread_scoped_lock num_lock(num_mutex); - do_cancel = true; TaskScheduler::clear(this); + + { + thread_scoped_lock num_lock(num_mutex); + + while(num) + num_cond.wait(num_lock); + } + + do_cancel = false; } void TaskPool::stop() { - thread_scoped_lock num_lock(num_mutex); - TaskScheduler::clear(this); assert(num == 0); @@ -127,20 +130,20 @@ bool TaskPool::cancelled() void TaskPool::num_decrease(int done) { + num_mutex.lock(); num -= done; + assert(num >= 0); - - if(num == 0) { - do_cancel = false; - + if(num == 0) num_cond.notify_all(); - } + + num_mutex.unlock(); } void TaskPool::num_increase() { + thread_scoped_lock num_lock(num_mutex); num++; - num_cond.notify_all(); } @@ -236,11 +239,7 @@ void TaskScheduler::thread_run(int thread_id) delete entry.task; /* notify pool task was done */ - { - /* not called from TaskPool, have to explicitly lock the mutex here */ - thread_scoped_lock num_lock(entry.pool->num_mutex); - entry.pool->num_decrease(1); - } + entry.pool->num_decrease(1); } } diff --git a/intern/cycles/util/util_task.h b/intern/cycles/util/util_task.h index 401a503f540..a2f284479c7 100644 --- a/intern/cycles/util/util_task.h +++ b/intern/cycles/util/util_task.h @@ -95,6 +95,7 @@ public: static void exit(); static int num_threads() { return threads.size(); } + static bool active() { return users != 0; } protected: friend class TaskPool; diff --git a/intern/cycles/util/util_thread.h b/intern/cycles/util/util_thread.h index 9bea4e7808a..6d1bd0023a7 100644 --- a/intern/cycles/util/util_thread.h +++ b/intern/cycles/util/util_thread.h @@ -33,6 +33,9 @@ typedef boost::mutex thread_mutex; typedef boost::mutex::scoped_lock thread_scoped_lock; typedef boost::condition_variable thread_condition_variable; +/* use boost for spinlocks as well */ +typedef boost::detail::spinlock spin_lock; + /* own pthread based implementation, to avoid boost version conflicts with * dynamically loaded blender plugins */ @@ -60,6 +63,7 @@ public: bool join() { + joined = true; return pthread_join(pthread_id, NULL) == 0; } diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp index b3c6506dfa0..70ee13d96d7 100644 --- a/intern/cycles/util/util_transform.cpp +++ b/intern/cycles/util/util_transform.cpp @@ -246,9 +246,10 @@ static void transform_decompose(Transform *decomp, const Transform *tfm) decomp->w = make_float4(scale.y.z, scale.z.x, scale.z.y, scale.z.z); } -void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion) +void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid) { transform_decompose(&decomp->pre, &motion->pre); + transform_decompose(&decomp->mid, mid); transform_decompose(&decomp->post, &motion->post); } diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h index d93bbff5415..df525542207 100644 --- a/intern/cycles/util/util_transform.h +++ b/intern/cycles/util/util_transform.h @@ -41,6 +41,7 @@ typedef struct Transform { typedef struct MotionTransform { Transform pre; + Transform mid; Transform post; } MotionTransform; @@ -304,10 +305,18 @@ __device_inline float4 quat_interpolate(float4 q1, float4 q2, float t) { float costheta = dot(q1, q2); + /* rotate around shortest angle */ + if(costheta < 0.0f) { + costheta = -costheta; + q1 = -q1; + } + if(costheta > 0.9995f) { + /* linear interpolation in degenerate case */ return normalize((1.0f - t)*q1 + t*q2); } else { + /* slerp */ float theta = acosf(clamp(costheta, -1.0f, 1.0f)); float thetap = theta * t; float4 qperp = normalize(q2 - q1 * costheta); @@ -375,11 +384,37 @@ __device void transform_motion_interpolate(Transform *tfm, const MotionTransform { Transform decomp; - decomp.x = quat_interpolate(motion->pre.x, motion->post.x, t); - decomp.y = (1.0f - t)*motion->pre.y + t*motion->post.y; - decomp.z = (1.0f - t)*motion->pre.z + t*motion->post.z; - decomp.w = (1.0f - t)*motion->pre.w + t*motion->post.w; + /* 3 point bezier curve interpolation for position */ + float3 Ppre = float4_to_float3(motion->pre.y); + float3 Pmid = float4_to_float3(motion->mid.y); + float3 Ppost = float4_to_float3(motion->post.y); + float3 Pcontrol = 2.0f*Pmid - 0.5f*(Ppre + Ppost); + float3 P = Ppre*t*t + Pcontrol*2.0f*t*(1.0f - t) + Ppost*(1.0f - t)*(1.0f - t); + + decomp.y.x = P.x; + decomp.y.y = P.y; + decomp.y.z = P.z; + + /* linear interpolation for rotation and scale */ + if(t < 0.5f) { + t *= 2.0f; + + decomp.x = quat_interpolate(motion->pre.x, motion->mid.x, t); + decomp.y.w = (1.0f - t)*motion->pre.y.w + t*motion->mid.y.w; + decomp.z = (1.0f - t)*motion->pre.z + t*motion->mid.z; + decomp.w = (1.0f - t)*motion->pre.w + t*motion->mid.w; + } + else { + t = (t - 0.5f)*2.0f; + + decomp.x = quat_interpolate(motion->mid.x, motion->post.x, t); + decomp.y.w = (1.0f - t)*motion->mid.y.w + t*motion->post.y.w; + decomp.z = (1.0f - t)*motion->mid.z + t*motion->post.z; + decomp.w = (1.0f - t)*motion->mid.w + t*motion->post.w; + } + + /* compose rotation, translation, scale into matrix */ transform_compose(tfm, &decomp); } @@ -390,7 +425,7 @@ __device_inline bool operator==(const MotionTransform& A, const MotionTransform& return (A.pre == B.pre && A.post == B.post); } -void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion); +void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid); #endif diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h index 5c6b9d5bb78..f2c02cadcbf 100644 --- a/intern/cycles/util/util_types.h +++ b/intern/cycles/util/util_types.h @@ -449,6 +449,7 @@ typedef enum AttributeStandard { ATTR_STD_VERTEX_NORMAL, ATTR_STD_FACE_NORMAL, ATTR_STD_UV, + ATTR_STD_TANGENT, ATTR_STD_GENERATED, ATTR_STD_POSITION_UNDEFORMED, ATTR_STD_POSITION_UNDISPLACED, diff --git a/intern/decimation/CMakeLists.txt b/intern/decimation/CMakeLists.txt deleted file mode 100644 index 73b67d7f3b1..00000000000 --- a/intern/decimation/CMakeLists.txt +++ /dev/null @@ -1,63 +0,0 @@ -# ***** 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) 2006, Blender Foundation -# All rights reserved. -# -# The Original Code is: all of this file. -# -# Contributor(s): Jacques Beaurain. -# -# ***** END GPL LICENSE BLOCK ***** - -set(INC - . - ../container - ../guardedalloc - ../memutil - ../moto/include -) - -set(INC_SYS - -) - -set(SRC - intern/LOD_EdgeCollapser.cpp - intern/LOD_ExternNormalEditor.cpp - intern/LOD_FaceNormalEditor.cpp - intern/LOD_ManMesh2.cpp - intern/LOD_MeshPrimitives.cpp - intern/LOD_QSDecimator.cpp - intern/LOD_QuadricEditor.cpp - intern/LOD_decimation.cpp - - extern/LOD_decimation.h - intern/LOD_DecimationClass.h - intern/LOD_EdgeCollapser.h - intern/LOD_ExternBufferEditor.h - intern/LOD_ExternNormalEditor.h - intern/LOD_FaceNormalEditor.h - intern/LOD_ManMesh2.h - intern/LOD_MeshBounds.h - intern/LOD_MeshException.h - intern/LOD_MeshPrimitives.h - intern/LOD_QSDecimator.h - intern/LOD_Quadric.h - intern/LOD_QuadricEditor.h -) - -blender_add_lib(bf_intern_decimate "${SRC}" "${INC}" "${INC_SYS}") diff --git a/intern/decimation/SConscript b/intern/decimation/SConscript deleted file mode 100644 index 6f4befb3ffa..00000000000 --- a/intern/decimation/SConscript +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/python -Import ('env') - -sources = env.Glob('intern/*.cpp') - -incs = '. ../moto/include ../container ../memutil ../guardedalloc' - -env.BlenderLib ('bf_intern_decimate', sources, Split(incs) , [], libtype=['core', 'player'], priority = [200, 100] ) diff --git a/intern/decimation/extern/LOD_decimation.h b/intern/decimation/extern/LOD_decimation.h deleted file mode 100644 index 4c52cb18577..00000000000 --- a/intern/decimation/extern/LOD_decimation.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/extern/LOD_decimation.h - * \ingroup decimation - */ - - -/** - - * @author Laurence Bourn - * @date 6/7/2001 - * - * This is the external interface for the decimation module. - */ - -#ifndef __LOD_DECIMATION_H__ -#define __LOD_DECIMATION_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * External decimation structure - */ - -typedef struct LOD_Decimation_Info { - float * vertex_buffer; - float * vertex_normal_buffer; - int * triangle_index_buffer; - int vertex_num; - int face_num; - void * intern; -} LOD_Decimation_Info; - -typedef LOD_Decimation_Info* LOD_Decimation_InfoPtr; - -/** - * Create internal mesh representation from - * LOD_Decimation_Info structure. - * @return 1 on successful loading - * @return 0 on failure - * @warning This should be changed to return an enumeration - * detailing the error encountered - */ - -extern int LOD_LoadMesh(LOD_Decimation_InfoPtr info); - -/** - * Allocate and Compute internal data strucures required for - * decimation. - * @return 1 on successful computation of data - * @return 0 on failure - * @warning This should be changed to return an enumeration - * detailing the error encountered - */ - -extern int LOD_PreprocessMesh(LOD_Decimation_InfoPtr info); - -/** - * Once both the stages above have been completed - * this function collapses a single edge in the mesh. - * The LOD_Decimation_Info structure is updated - * to represent the new mesh. - * @return 1 if an edge was collapsed. - * @return 0 if no suitable edge was found to be collapsable - * You should stop calling this method in this case - * @warning Do not expect that the order of polygons, vertices or - * vertex normals will be preserved by this operation. This function - * returns a packed array of polygons and vertices and so necessarily - * the order will be different. This means you should not expect to - * find the same polygon in the same place in the polygon array after - * this function has been called. - */ - -extern int LOD_CollapseEdge(LOD_Decimation_InfoPtr info); - -/** - * Free any memory the decimation process used - * during the decimation process - * @return 1 if internal data successfully freed - * @return 0 if no data was freed - */ - -extern int LOD_FreeDecimationData(LOD_Decimation_InfoPtr); - -#ifdef __cplusplus -} -#endif - -#endif // __LOD_DECIMATION_H__ - diff --git a/intern/decimation/intern/LOD_DecimationClass.h b/intern/decimation/intern/LOD_DecimationClass.h deleted file mode 100644 index ecf2e4e6790..00000000000 --- a/intern/decimation/intern/LOD_DecimationClass.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_DecimationClass.h - * \ingroup decimation - */ - - -#ifndef __LOD_DECIMATIONCLASS_H__ -#define __LOD_DECIMATIONCLASS_H__ - -#include "MEM_SmartPtr.h" -#include "MEM_NonCopyable.h" - -#include "LOD_ManMesh2.h" -#include "LOD_QSDecimator.h" -#include "LOD_ExternNormalEditor.h" -#include "../extern/LOD_decimation.h" -#include "LOD_ExternBufferEditor.h" - - -class LOD_DecimationClass : public MEM_NonCopyable -{ -public : - - enum { - e_not_loaded, - e_loaded, - e_preprocessed - } m_e_decimation_state; - - - static - LOD_DecimationClass * - New( - LOD_Decimation_InfoPtr extern_info - ) { - // create everything - - MEM_SmartPtr output(new LOD_DecimationClass()); - MEM_SmartPtr mesh(LOD_ManMesh2::New()); - MEM_SmartPtr extern_editor(LOD_ExternBufferEditor::New(extern_info)); - - if (mesh == NULL || extern_editor == NULL) return NULL; - MEM_SmartPtr normals(LOD_ExternNormalEditor::New(extern_info,mesh.Ref())); - - if (normals == NULL) return NULL; - MEM_SmartPtr decimator(LOD_QSDecimator::New( - mesh.Ref(), - normals.Ref(), - extern_editor.Ref() - )); - if (decimator == NULL || output == NULL) return NULL; - - output->m_mesh = mesh.Release(); - output->m_decimator = decimator.Release(); - output->m_normals = normals.Release(); - output->m_extern_editor = extern_editor.Release(); - - return output.Release(); - } - - LOD_ManMesh2 & - Mesh( - ){ - return m_mesh.Ref(); - } - - LOD_QSDecimator & - Decimator( - ) { - return m_decimator.Ref(); - } - - LOD_ExternNormalEditor & - FaceEditor( - ){ - return m_normals.Ref(); - } - -private : - - LOD_DecimationClass( - ) : m_e_decimation_state(e_not_loaded) { - }; - - MEM_SmartPtr m_mesh; - MEM_SmartPtr m_decimator; - MEM_SmartPtr m_normals; - MEM_SmartPtr m_extern_editor; -}; - -#endif - diff --git a/intern/decimation/intern/LOD_EdgeCollapser.cpp b/intern/decimation/intern/LOD_EdgeCollapser.cpp deleted file mode 100644 index 1405d6f53fa..00000000000 --- a/intern/decimation/intern/LOD_EdgeCollapser.cpp +++ /dev/null @@ -1,410 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_EdgeCollapser.cpp - * \ingroup decimation - */ - - -#include "LOD_EdgeCollapser.h" - -#include "LOD_ManMesh2.h" -#include "CTR_TaggedSetOps.h" -#include -#include - - -using namespace std; - - - LOD_EdgeCollapser * -LOD_EdgeCollapser:: -New( -){ - return new LOD_EdgeCollapser(); -} - - - bool -LOD_EdgeCollapser:: -TJunctionTest( - LOD_ManMesh2 &mesh, - vector &e_v0v1, - LOD_EdgeInd collapse_edge -){ - - // we need to copy the edges in e_v0v1 from the mesh - // into a new buffer -> we are going to modify them - - int original_size = e_v0v1.size(); - if (original_size == 0) return true; - - vector &edge_set = mesh.EdgeSet(); - - LOD_VertexInd c_v0 = edge_set[collapse_edge].m_verts[0]; - LOD_VertexInd c_v1 = edge_set[collapse_edge].m_verts[1]; - - vector temp_edges; - temp_edges.reserve(e_v0v1.size()); - - vector::iterator edge_it = e_v0v1.begin(); - vector::const_iterator edge_end = e_v0v1.end(); - - for (;edge_it != edge_end; ++edge_it) { - temp_edges.push_back(edge_set[*edge_it]); - } - - // in the copied edges replace all instances of c_v0 with c_v1 - - vector::iterator e_it = temp_edges.begin(); - vector::const_iterator e_it_end = temp_edges.end(); - - for (; e_it != e_it_end; ++e_it) { - - if (e_it->m_verts[0] == c_v0) { - e_it->m_verts[0] = c_v1; - } - if (e_it->m_verts[1] == c_v0) { - e_it->m_verts[1] = c_v1; - } - - // normalize the edge - if (int(e_it->m_verts[0]) > int(e_it->m_verts[1])) { - LOD_EdgeInd temp = e_it->m_verts[0]; - e_it->m_verts[0] = e_it->m_verts[1]; - e_it->m_verts[1] = temp; - } - } - - // sort the edges using the edge less functional - - sort(temp_edges.begin(),temp_edges.end(),LOD_EdgeCollapser::less()); - // count the unique edges. - - e_it = temp_edges.begin(); - e_it_end = temp_edges.end(); - - int coincedent_edges = 0; - - vector::const_iterator last_edge = e_it; - ++e_it; - - for (; e_it != e_it_end; ++e_it) { - - if ((e_it->m_verts[0] == last_edge->m_verts[0]) && - (e_it->m_verts[1] == last_edge->m_verts[1]) - ) { - ++coincedent_edges; - } - last_edge = e_it; - } - - // now if the collapse edge is a boundary edges - // then we are alloved at most one coincedent edge - - // otherwise at most 2 coincedent edges - - if (edge_set[collapse_edge].BoundaryEdge()) { - return (coincedent_edges > 1); - } else { - return (coincedent_edges > 2); - } - - -} - - - - bool -LOD_EdgeCollapser:: -CollapseEdge( - LOD_EdgeInd ei, - LOD_ManMesh2 &mesh, - vector & degenerate_edges, - vector & degenerate_faces, - vector & degenerate_vertices, - vector & new_edges, - vector & update_faces, - vector & update_vertices -){ - - vector &verts = mesh.VertexSet(); - vector &edges = mesh.EdgeSet(); - vector &faces = mesh.FaceSet(); - - // shouldn't do this (use mesh interface instead!) - LOD_VertexInd v0_ind = edges[ei].m_verts[0]; - LOD_VertexInd v1_ind = edges[ei].m_verts[1]; -#if 0 - LOD_Vertex &v0 = verts[v0_ind]; - LOD_Vertex &v1 = verts[v1_ind]; -#endif - vector > e_v01(2); - e_v01[0].reserve(32); - e_v01[1].reserve(32); - - mesh.VertexEdges(v0_ind,e_v01[0]); - mesh.VertexEdges(v1_ind,e_v01[1]); - - - // compute the union of e_v0 and e_v1 -> this is the degenerate edges of the collapse - // we remove old edges and replace edges inside the collapse zone with new ones - - CTR_TaggedSetOps::Union(e_v01,edges,degenerate_edges); - - vector< vector > p_v01(2); - p_v01[0].reserve(32); - p_v01[1].reserve(32); - - mesh.VertexFaces(v0_ind,p_v01[0]); - mesh.VertexFaces(v1_ind,p_v01[1]); - - // compute the union of p_v0 anf p_v1 - vector p_v0v1; - p_v0v1.reserve(32); - - CTR_TaggedSetOps::Union(p_v01,faces,p_v0v1); - - // compute the union of all the edges in p_v0v1 this is the collapse zone - - vector > e_input_vectors(p_v0v1.size()); - - vector::iterator p_v0v1_end = p_v0v1.end(); - vector::iterator p_v0v1_start = p_v0v1.begin(); - - vector >::iterator vector_insert_it = e_input_vectors.begin(); - - for (;p_v0v1_start != p_v0v1_end; ++p_v0v1_start , ++vector_insert_it) { - mesh.FaceEdges(*p_v0v1_start,*vector_insert_it); - } - - vector collapse_zone; - collapse_zone.reserve(32); - - CTR_TaggedSetOps::Union(e_input_vectors,edges,collapse_zone); - - // compute the ring edges = collpase_zone - e_v0v1 - - vector edge_ring; - edge_ring.reserve(32); - - CTR_TaggedSetOps::Difference(collapse_zone,degenerate_edges,edges,edge_ring); - - // T Junction test - ////////////////// - // At this point we check to see if any of the polygons - // in p_v0v1 are coninceddent - this leads - // to errors later on if we try and insert a polygon - // into the mesh to an edge which already has 2 polygons. - - // not that t junctions occur naturally from edge collapses - // and are not just the result of coincedent polygons - // for example consider collapsing an edge that forms part - // of a triangular bottle neck. - - // Really we need to make sure that we don't create t-junctions. - - // I think that a sufficient test is to check the number of - // coincedent edge pairs after a collapse. If it is more than 2 - // then collapsing the edge may result in an undeleted edge - // sharing more than 2 polygons. This test probably is too - // restictive though. - - // To perform this test we need to make a copy of the edges - // in e_v0v1. We then apply the contraction to these edge - // copies. Sort them using a function that places coincedent - // edges next to each other. And then count the number - // of coincedent pairs. - - // Of course we have to do this test before we change any of the - // mesh -> so we can back out safely. - - if (TJunctionTest(mesh,degenerate_edges,ei)) return false; - - // Compute the set of possibly degenerate vertices - // this is the union of all the vertices of polygons - // of v0 and v1 - - vector::iterator face_it = p_v0v1.begin(); - vector::const_iterator face_end = p_v0v1.end(); - - - vector > p_v0v1_vertices(p_v0v1.size()); - - for (int i = 0; face_it != face_end; ++face_it, ++i) { - mesh.FaceVertices(*face_it,p_v0v1_vertices[i]); - } - - vector vertex_ring; - vertex_ring.reserve(32); - - CTR_TaggedSetOps::Union(p_v0v1_vertices,verts,vertex_ring); - - // remove all the internal edges e_v0v1 from the mesh. - // for each edge remove the egde from it's vertices edge lists. - - vector::iterator edge_it = degenerate_edges.begin(); - vector::const_iterator edge_end = degenerate_edges.end(); - - for (; !(edge_it == edge_end); ++edge_it) { - - LOD_EdgeInd ed = (*edge_it); - LOD_Edge & edge = edges[ed];//*edge_it]; - - verts[edge.m_verts[0]].RemoveEdge(ed); - verts[edge.m_verts[1]].RemoveEdge(ed); - } - - // we postpone deletion of the internal edges untill the end - // this is because deleting edges invalidates all of the - // EdgeInd vectors above. - - - // now untie all the polygons in p_v0v1 from the edge ring - - // select all polygons in p_v0v1 - - face_it = p_v0v1.begin(); - face_end = p_v0v1.end(); - - for (;face_it != face_end; ++face_it) { - faces[*face_it].SetSelectTag(true); - } - - edge_it = edge_ring.begin(); - edge_end = edge_ring.end(); - - for (;edge_it != edge_end; ++edge_it) { - LOD_Edge & edge = edges[*edge_it]; - - // presumably all edges in edge_ring point to at least - // one polygon from p_v0v1 - - if (!edge.m_faces[0].IsEmpty() && faces[edge.m_faces[0]].SelectTag()) { - edge.m_faces[0].Invalidate(); - } - - if (!edge.m_faces[1].IsEmpty() && faces[edge.m_faces[1]].SelectTag()) { - edge.m_faces[1].Invalidate(); - } - } - - // deselect the faces - - face_it = p_v0v1.begin(); - face_end = p_v0v1.end(); - - for (;face_it != face_end; ++face_it) { - faces[*face_it].SetSelectTag(false); - } - - // perform the edge collapse - //////////////////////////// - - // iterate through the polygons of p_v0 and replace the vertex - // index v0 with v1 - - face_it = p_v01[0].begin(); - face_end = p_v01[0].end(); - - for (;face_it != face_end; ++face_it) { - faces[*face_it].SwapVertex(v0_ind,v1_ind); - } - - face_it = p_v0v1.begin(); - face_end = p_v0v1.end(); - - for (;face_it != face_end; ++face_it) { - if (faces[*face_it].Degenerate()) { - degenerate_faces.push_back(*face_it); - } else { - update_faces.push_back(*face_it); - } - } - - // Add all the non-degenerate faces back into the - // mesh. Get a record of the new edges created in - // this process. - - face_it = update_faces.begin(); - face_end = update_faces.end(); - - for (;face_it != face_end; ++face_it) { - mesh.ConnectTriangle(*face_it,new_edges); - } - - // degenerate ring primitives - ///////////////////////////// - - // we now need to examine each of the edges on the ring - // and work out if they are degenerate - if so we attempt - // to delete them -> add them to the other edges to delete - // in e_v0v1 - - edge_it = edge_ring.begin(); - edge_end = edge_ring.end(); - - for (;edge_it != edge_end; ++edge_it) { - if (edges[*edge_it].Degenerate()) { - degenerate_edges.push_back(*edge_it); - } - } - - // do the same for the ring vertices. - - vector::iterator vertex_it = vertex_ring.begin(); - vector::const_iterator vertex_end = vertex_ring.end(); - - for (;vertex_it != vertex_end; ++vertex_it) { - if (verts[*vertex_it].Degenerate()) { - degenerate_vertices.push_back(*vertex_it); - } else { - update_vertices.push_back(*vertex_it); - } - } - - // we now know all the degenerate primitives - // and the new primitives we have inserted into the mesh - - // We now delete the mesh primitives, mesh.DeleteXXXXXX() methods - // assume that the index vectors are sorted into descending order. - // we do that now. - - sort(degenerate_edges.begin(),degenerate_edges.end(),LOD_EdgeInd::greater()); - sort(degenerate_faces.begin(),degenerate_faces.end(),LOD_FaceInd::greater()); - sort(degenerate_vertices.begin(),degenerate_vertices.end(),LOD_VertexInd::greater()); - - - return true; - -} - -LOD_EdgeCollapser:: -LOD_EdgeCollapser( -){ - // nothing to do -} diff --git a/intern/decimation/intern/LOD_EdgeCollapser.h b/intern/decimation/intern/LOD_EdgeCollapser.h deleted file mode 100644 index 75a8b70f672..00000000000 --- a/intern/decimation/intern/LOD_EdgeCollapser.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_EdgeCollapser.h - * \ingroup decimation - */ - - -#ifndef __LOD_EDGECOLLAPSER_H__ -#define __LOD_EDGECOLLAPSER_H__ - -// This is a helper class that collapses edges of a 2 - manifold mesh. - -#include "LOD_MeshPrimitives.h" -#include "MEM_NonCopyable.h" -#include -#include - -class LOD_ManMesh2; - -class LOD_EdgeCollapser -: public MEM_NonCopyable -{ - -public : - - static - LOD_EdgeCollapser * - New( - ); - - // returns via arguments the set of modified - // verts,edges and faces. - - bool - CollapseEdge( - LOD_EdgeInd ei, - LOD_ManMesh2 &mesh, - std::vector & degenerate_edges, - std::vector & degenerate_faces, - std::vector & degenerate_vertices, - std::vector & new_edges, - std::vector & update_faces, - std::vector & update_vertices - ); - -private : - - LOD_EdgeCollapser( - ); - - // Test to see if the result of collapsing the - // edge produces 2 junctions in the mesh i.e. where - // an edge is shared by more than 2 polygons - - // We count the number of coincedent edge pairs that - // result from the collapse of collapse_edge. - - // If collapse edge is a boundary edge then the number of - // coincedent pairs should be 1 - // else it should be 2. - - bool - TJunctionTest( - LOD_ManMesh2 &mesh, - std::vector &e_v0v1, - LOD_EdgeInd collapse_edge - ); - - // here's the definition of the sort function - // we use to determine coincedent edges - - // assumes the edges are normalized i.e. m_verts[0] <= m_verts[1] - - struct less : std::binary_function { - bool - operator()( - const LOD_Edge& a, - const LOD_Edge& b - ) const { - - if (int(a.m_verts[0]) == int(b.m_verts[0])) { - return (int(a.m_verts[1]) < int(b.m_verts[1])); - } else { - return (int(a.m_verts[0]) < int(b.m_verts[0])); - } - } - }; - -}; - -#endif - diff --git a/intern/decimation/intern/LOD_ExternBufferEditor.h b/intern/decimation/intern/LOD_ExternBufferEditor.h deleted file mode 100644 index c903b255812..00000000000 --- a/intern/decimation/intern/LOD_ExternBufferEditor.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_ExternBufferEditor.h - * \ingroup decimation - */ - - -/** - - * Copyright (C) 2001 NaN Technologies B.V. - */ - -#ifndef __LOD_EXTERNBUFFEREDITOR_H__ -#define __LOD_EXTERNBUFFEREDITOR_H__ - -#include "LOD_MeshPrimitives.h" -#include -#include "LOD_ManMesh2.h" -#include "../extern/LOD_decimation.h" - - -// This class syncs external vertex/face buffers -// with the internal mesh representation during -// decimation. - -class LOD_ExternBufferEditor -{ - -public : - - static - LOD_ExternBufferEditor * - New( - LOD_Decimation_InfoPtr extern_info - ){ - if (extern_info == NULL) return NULL; - return new LOD_ExternBufferEditor(extern_info); - } - - // update the external vertex buffer with vertices - // from the mesh - - void - CopyModifiedVerts( - LOD_ManMesh2 & mesh, - const std::vector & mod_vertices - ){ - - std::vector::const_iterator v_start = mod_vertices.begin(); - std::vector::const_iterator v_end = mod_vertices.end(); - - std::vector & mesh_verts = mesh.VertexSet(); - - float * const extern_vertex_ptr = m_extern_info->vertex_buffer; - - for (; v_start != v_end; ++v_start) { - float * mod_vert = extern_vertex_ptr + int(*v_start)*3; - mesh_verts[*v_start].CopyPosition(mod_vert); - } - } - - // update the external face buffer with faces from the mesh - - void - CopyModifiedFaces( - LOD_ManMesh2 & mesh, - const std::vector & mod_faces - ){ - - std::vector::const_iterator f_start = mod_faces.begin(); - std::vector::const_iterator f_end = mod_faces.end(); - - std::vector &mesh_faces = mesh.FaceSet(); - - int * const extern_face_ptr = m_extern_info->triangle_index_buffer; - - for (; f_start != f_end; ++f_start) { - int *mod_face = extern_face_ptr + 3*int(*f_start); - mesh_faces[*f_start].CopyVerts(mod_face); - } - } - - - // Copy the last vertex over the vertex specified by - // vi. Decrement the size of the vertex array - - void - CopyBackVertex( - LOD_VertexInd vi - ){ - - float * const extern_vertex_ptr = m_extern_info->vertex_buffer; - int * extern_vertex_num = &(m_extern_info->vertex_num); - - float * last_external_vert = extern_vertex_ptr + 3*((*extern_vertex_num) - 1); - float * external_vert = extern_vertex_ptr + 3*int(vi); - - external_vert[0] = last_external_vert[0]; - external_vert[1] = last_external_vert[1]; - external_vert[2] = last_external_vert[2]; - - *extern_vertex_num -=1; - } - - // Copy the last face over the face specified by fi - // Decrement the size of the face array - - void - CopyBackFace( - LOD_FaceInd fi - ) { - int * const extern_face_ptr = m_extern_info->triangle_index_buffer; - int * extern_face_num = &(m_extern_info->face_num); - - int * last_external_face = extern_face_ptr + 3*((*extern_face_num) -1); - int * external_face = extern_face_ptr + 3*int(fi); - external_face[0] = last_external_face[0]; - external_face[1] = last_external_face[1]; - external_face[2] = last_external_face[2]; - - *extern_face_num -=1; - } - - -private : - - LOD_ExternBufferEditor( - LOD_Decimation_InfoPtr extern_info - ) : - m_extern_info (extern_info) - { - } - - LOD_Decimation_InfoPtr const m_extern_info; - -}; - -#endif - diff --git a/intern/decimation/intern/LOD_ExternNormalEditor.cpp b/intern/decimation/intern/LOD_ExternNormalEditor.cpp deleted file mode 100644 index 90033fe672b..00000000000 --- a/intern/decimation/intern/LOD_ExternNormalEditor.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_ExternNormalEditor.cpp - * \ingroup decimation - */ - - -#include "LOD_ExternNormalEditor.h" -#include - -using namespace std; - - -LOD_ExternNormalEditor:: -LOD_ExternNormalEditor( - LOD_Decimation_InfoPtr extern_info, - LOD_ManMesh2 &mesh -) : - m_mesh(mesh), - m_extern_info (extern_info) -{ -} - - LOD_ExternNormalEditor * -LOD_ExternNormalEditor:: -New( - LOD_Decimation_InfoPtr extern_info, - LOD_ManMesh2 &mesh -){ - if (extern_info == NULL) return NULL; - - MEM_SmartPtr output(new LOD_ExternNormalEditor(extern_info,mesh)); - - int face_num = mesh.FaceSet().size(); - - MEM_SmartPtr > normals(new vector); - - if (output == NULL || - normals == NULL - ) { - return NULL; - } - - normals->reserve(face_num); - output->m_normals = normals.Release(); - - return output.Release(); -}; - - - void -LOD_ExternNormalEditor:: -Remove( - std::vector &sorted_faces -){ - // assumes a collection of faces sorted in descending order . - - vector & normals = m_normals.Ref(); - - vector::const_iterator it_start = sorted_faces.begin(); - vector::const_iterator it_end = sorted_faces.end(); - - for (; it_start != it_end; ++it_start) { - - if (normals.size() > 0) { - MT_Vector3 temp = normals[*it_start]; - - normals[*it_start] = normals.back(); - normals.back() = temp; - - normals.pop_back(); - } - - // FIXME - throw exception - } -} - - - void -LOD_ExternNormalEditor:: -Add( -){ - MT_Vector3 zero(0.0f,0.0f,0.0f); - m_normals->push_back(zero); -}; - - void -LOD_ExternNormalEditor:: -Update( - std::vector &sorted_faces -){ - vector & normals = m_normals.Ref(); - - vector::const_iterator it_start = sorted_faces.begin(); - vector::const_iterator it_end = sorted_faces.end(); - - const vector &faces = m_mesh.FaceSet(); - - for (; it_start != it_end; ++it_start) { - normals[*it_start] = ComputeNormal(faces[*it_start]); - } -}; - - - - -// vertex normals -///////////////// - - void -LOD_ExternNormalEditor:: -RemoveVertexNormals( - std::vector &sorted_verts -){ - - float * vertex_normals = m_extern_info->vertex_normal_buffer; - - // assumption here that the vertexs normal number corresponds with - // the number of vertices ! - - int vertex_normal_num = m_extern_info->vertex_num; - - vector::const_iterator it_start = sorted_verts.begin(); - vector::const_iterator it_end = sorted_verts.end(); - - for (; it_start != it_end; ++it_start) { - - if (vertex_normal_num > 0) { - float * vertex_normal = vertex_normals + int(*it_start)*3; - float * last_vertex = vertex_normals + ((vertex_normal_num-1)*3); - - MT_Vector3 last_v(last_vertex); - last_v.getValue(vertex_normal); - vertex_normal_num--; - } - - // FIXME - through exception - } -}; - - - - void -LOD_ExternNormalEditor:: -UpdateVertexNormals( - std::vector &sorted_verts -){ - float * vertex_normals = m_extern_info->vertex_normal_buffer; - - vector::const_iterator it_start = sorted_verts.begin(); - vector::const_iterator it_end = sorted_verts.end(); - - for (; it_start != it_end; ++it_start) { - MT_Vector3 temp = ComputeVertexNormal(*it_start); - float * vertex_normal = vertex_normals + int(*it_start)*3; - temp.getValue(vertex_normal); - } -} - -// Editor specific methods -////////////////////////// - - void -LOD_ExternNormalEditor:: -BuildNormals( -) { - const vector &faces = m_mesh.FaceSet(); - vector & normals = m_normals.Ref(); - - int face_num = faces.size(); - int cur_face = 0; - - for (; cur_face < face_num; ++cur_face) { - - MT_Vector3 new_normal = ComputeNormal(faces[cur_face]); - normals.push_back(new_normal); - } -} - -const - MT_Vector3 -LOD_ExternNormalEditor:: -ComputeNormal( - const LOD_TriFace &face -) const { - - const vector &verts = m_mesh.VertexSet(); - - MT_Vector3 vec1 = - verts[face.m_verts[1]].pos - - verts[face.m_verts[0]].pos; - - MT_Vector3 vec2 = - verts[face.m_verts[2]].pos - - verts[face.m_verts[1]].pos; - - vec1 = vec1.cross(vec2); - - if (!vec1.fuzzyZero()) { - vec1.normalize(); - return (vec1); - } else { - return (MT_Vector3(1.0,0,0)); - } -} - -const - MT_Vector3 -LOD_ExternNormalEditor:: -ComputeVertexNormal( - const LOD_VertexInd v -) const { - - // average the face normals surrounding this - // vertex and normalize - // vector &verts = m_mesh.VertexSet(); /*unused*/ - const vector & face_normals = m_normals.Ref(); - - vector vertex_faces; - vertex_faces.reserve(32); - - m_mesh.VertexFaces(v,vertex_faces); - - MT_Vector3 normal(0,0,0); - - vector::const_iterator face_it = vertex_faces.begin(); - vector::const_iterator face_end = vertex_faces.end(); - - for (; face_it != face_end; ++face_it) { - normal += face_normals[*face_it]; - } - - if (!normal.fuzzyZero()) { - normal.normalize(); - return (normal); - } else { - return (MT_Vector3(1.0,0,0)); - } -} diff --git a/intern/decimation/intern/LOD_ExternNormalEditor.h b/intern/decimation/intern/LOD_ExternNormalEditor.h deleted file mode 100644 index 52135196dc5..00000000000 --- a/intern/decimation/intern/LOD_ExternNormalEditor.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_ExternNormalEditor.h - * \ingroup decimation - */ - - -#ifndef __LOD_EXTERNNORMALEDITOR_H__ -#define __LOD_EXTERNNORMALEDITOR_H__ - -#include "MEM_NonCopyable.h" -#include "LOD_ManMesh2.h" -#include "MT_Vector3.h" -#include "../extern/LOD_decimation.h" - -class LOD_ExternNormalEditor : public MEM_NonCopyable -{ - -public : - - // Creation - /////////// - - static - LOD_ExternNormalEditor * - New( - LOD_Decimation_InfoPtr, - LOD_ManMesh2 &mesh - ); - - // Property editor interface - //////////////////////////// - - - // Faces - //////// - void - Remove( - std::vector &sorted_faces - ); - - void - Add( - ); - - void - Update( - std::vector &sorted_faces - ); - - const - std::vector & - Normals( - ) const { - return m_normals.Ref(); - }; - - - // vertex normals - ///////////////// - - void - RemoveVertexNormals( - std::vector &sorted_verts - ); - - - void - UpdateVertexNormals( - std::vector &sorted_verts - ); - - // Editor specific methods - ////////////////////////// - - void - BuildNormals( - ); - - -private : - - MEM_SmartPtr > m_normals; - - LOD_ManMesh2 &m_mesh; - LOD_Decimation_InfoPtr m_extern_info; - -private : - - - LOD_ExternNormalEditor( - LOD_Decimation_InfoPtr extern_info, - LOD_ManMesh2 &mesh - ); - - const - MT_Vector3 - ComputeNormal( - const LOD_TriFace &face - ) const; - - const - MT_Vector3 - ComputeVertexNormal ( - const LOD_VertexInd vi - ) const; -}; - -#endif - diff --git a/intern/decimation/intern/LOD_FaceNormalEditor.cpp b/intern/decimation/intern/LOD_FaceNormalEditor.cpp deleted file mode 100644 index 430406a6d63..00000000000 --- a/intern/decimation/intern/LOD_FaceNormalEditor.cpp +++ /dev/null @@ -1,291 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_FaceNormalEditor.cpp - * \ingroup decimation - */ - - -// implementation of LOD_FaceNormalEditor.h - -/////////////////////////////////////// -#include "LOD_FaceNormalEditor.h" - -using namespace std; - -LOD_FaceNormalEditor:: -LOD_FaceNormalEditor( - LOD_ManMesh2 & mesh -) : m_mesh(mesh) { -}; - - LOD_FaceNormalEditor * -LOD_FaceNormalEditor:: -New( - LOD_ManMesh2 &mesh -){ - // build a set of normals of the same size - // as the number of polys in the mesh - - MEM_SmartPtr output(new LOD_FaceNormalEditor(mesh)); - - int face_num = mesh.FaceSet().size(); - - MEM_SmartPtr > normals(new vector); - MEM_SmartPtr > vertex_normals(new vector); - - if (output == NULL || - normals == NULL - ) { - return NULL; - } - - normals->reserve(face_num); - vertex_normals->reserve(mesh.VertexSet().size()); - output->m_normals = normals.Release(); - output->m_vertex_normals = vertex_normals.Release(); - - return output.Release(); -}; - - -// Property editor interface -//////////////////////////// - - void -LOD_FaceNormalEditor:: -Remove( - std::vector &sorted_faces -){ - - // assumes a collection of faces sorted in descending order . - - vector & normals = m_normals.Ref(); - - vector::const_iterator it_start = sorted_faces.begin(); - vector::const_iterator it_end = sorted_faces.end(); - - for (; it_start != it_end; ++it_start) { - - if (normals.size() > 0) { - MT_Vector3 temp = normals[*it_start]; - - normals[*it_start] = normals.back(); - normals.back() = temp; - - normals.pop_back(); - } - - // FIXME - through exception - } -} - - - void -LOD_FaceNormalEditor:: -Add( -){ - MT_Vector3 zero(0.0f,0.0f,0.0f); - m_normals->push_back(zero); -} - - void -LOD_FaceNormalEditor:: -Update( - std::vector &sorted_faces -){ - - vector & normals = m_normals.Ref(); - - vector::const_iterator it_start = sorted_faces.begin(); - vector::const_iterator it_end = sorted_faces.end(); - - const vector &faces = m_mesh.FaceSet(); - - for (; it_start != it_end; ++it_start) { - normals[*it_start] = ComputeNormal(faces[*it_start]); - } -}; - -// vertex normals -///////////////// - - - void -LOD_FaceNormalEditor:: -RemoveVertexNormals( - vector &sorted_verts -){ - vector & vertex_normals = m_vertex_normals.Ref(); - - vector::const_iterator it_start = sorted_verts.begin(); - vector::const_iterator it_end = sorted_verts.end(); - - for (; it_start != it_end; ++it_start) { - - if (vertex_normals.size() > 0) { - MT_Vector3 temp = vertex_normals[*it_start]; - - vertex_normals[*it_start] = vertex_normals.back(); - vertex_normals.back() = temp; - - vertex_normals.pop_back(); - } - - // FIXME - through exception - } -}; - - void -LOD_FaceNormalEditor:: -UpdateVertexNormals( - vector &sorted_verts -){ - vector & vertex_normals = m_vertex_normals.Ref(); - - vector::const_iterator it_start = sorted_verts.begin(); - vector::const_iterator it_end = sorted_verts.end(); - - for (; it_start != it_end; ++it_start) { - vertex_normals[*it_start] = ComputeVertexNormal(*it_start); - } -} - - - -// Editor specific methods -////////////////////////// - - void -LOD_FaceNormalEditor:: -BuildNormals( -){ - - const vector &faces = m_mesh.FaceSet(); - vector & normals = m_normals.Ref(); - - int face_num = faces.size(); - int cur_face = 0; - - for (; cur_face < face_num; ++cur_face) { - - MT_Vector3 new_normal = ComputeNormal(faces[cur_face]); - normals.push_back(new_normal); - } - // now build the vertex normals - - vector & vertex_normals = m_vertex_normals.Ref(); - const vector &verts = m_mesh.VertexSet(); - - int vertex_num = verts.size(); - int cur_vertex = 0; - - for (; cur_vertex < vertex_num; ++cur_vertex) { - MT_Vector3 new_normal = ComputeVertexNormal(cur_vertex); - vertex_normals.push_back(new_normal); - } -} - -const - MT_Vector3 -LOD_FaceNormalEditor:: -ComputeNormal( - const LOD_TriFace &face -) const { - - const vector &verts = m_mesh.VertexSet(); - - MT_Vector3 vec1 = - verts[face.m_verts[1]].pos - - verts[face.m_verts[0]].pos; - - MT_Vector3 vec2 = - verts[face.m_verts[2]].pos - - verts[face.m_verts[1]].pos; - - vec1 = vec1.cross(vec2); - - if (!vec1.fuzzyZero()) { - vec1.normalize(); - return (vec1); - } else { - return (MT_Vector3(1.0,0,0)); - } -} - -const - MT_Vector3 -LOD_FaceNormalEditor:: -ComputeVertexNormal( - const LOD_VertexInd v -) const { - - // average the face normals surrounding this - // vertex and normalize - const vector & face_normals = m_normals.Ref(); - - vector vertex_faces; - vertex_faces.reserve(32); - - m_mesh.VertexFaces(v,vertex_faces); - - MT_Vector3 normal(0,0,0); - - vector::const_iterator face_it = vertex_faces.begin(); - vector::const_iterator face_end = vertex_faces.end(); - - for (; face_it != face_end; ++face_it) { - normal += face_normals[*face_it]; - } - - if (!normal.fuzzyZero()) { - normal.normalize(); - return (normal); - } else { - return (MT_Vector3(1.0,0,0)); - } -} - - - - - - - - - - - - - - - - - - - - diff --git a/intern/decimation/intern/LOD_FaceNormalEditor.h b/intern/decimation/intern/LOD_FaceNormalEditor.h deleted file mode 100644 index a221ab0bd7a..00000000000 --- a/intern/decimation/intern/LOD_FaceNormalEditor.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_FaceNormalEditor.h - * \ingroup decimation - */ - - -#ifndef __LOD_FACENORMALEDITOR_H__ -#define __LOD_FACENORMALEDITOR_H__ - -#include "MEM_NonCopyable.h" -#include "LOD_ManMesh2.h" -#include "MT_Vector3.h" - - -class LOD_FaceNormalEditor : public MEM_NonCopyable -{ - -public : - - // Creation - /////////// - - static - LOD_FaceNormalEditor * - New( - LOD_ManMesh2 &mesh - ); - - // Property editor interface - //////////////////////////// - - - // Faces - //////// - void - Remove( - std::vector &sorted_faces - ); - - void - Add( - ); - - void - Update( - std::vector &sorted_faces - ); - - - // vertex normals - ///////////////// - - void - RemoveVertexNormals( - std::vector &sorted_verts - ); - - - void - UpdateVertexNormals( - std::vector &sorted_verts - ); - - - - const - std::vector & - Normals( - ) const { - return m_normals.Ref(); - }; - - - const - std::vector & - VertexNormals( - ) const { - return m_vertex_normals.Ref(); - }; - - // Editor specific methods - ////////////////////////// - - void - BuildNormals( - ); - - -private : - - MEM_SmartPtr > m_normals; - MEM_SmartPtr > m_vertex_normals; - - LOD_ManMesh2 &m_mesh; - -private : - - - LOD_FaceNormalEditor(LOD_ManMesh2 &mesh); - - const - MT_Vector3 - ComputeNormal( - const LOD_TriFace &face - ) const; - - const - MT_Vector3 - ComputeVertexNormal ( - const LOD_VertexInd vi - ) const; - - - -}; - -#endif - diff --git a/intern/decimation/intern/LOD_ManMesh2.cpp b/intern/decimation/intern/LOD_ManMesh2.cpp deleted file mode 100644 index c618944162f..00000000000 --- a/intern/decimation/intern/LOD_ManMesh2.cpp +++ /dev/null @@ -1,618 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_ManMesh2.cpp - * \ingroup decimation - */ - - -#include "LOD_ManMesh2.h" - -#include "MT_assert.h" -#include -#include "LOD_MeshException.h" -#include "CTR_TaggedSetOps.h" -#include "CTR_UHeap.h" -#include "LOD_ExternBufferEditor.h" - - -using namespace std; - -LOD_ManMesh2:: -LOD_ManMesh2( -) : - m_bbox_min(0,0,0), - m_bbox_max(0,0,0) -{ -} - - - LOD_ManMesh2 * -LOD_ManMesh2:: -New( -){ - MEM_SmartPtr output(new LOD_ManMesh2()); - if (output == NULL) return NULL; - - // build the vertex, edge and face sets. - - MEM_SmartPtr > verts(new vector); - MEM_SmartPtr > faces(new vector); - MEM_SmartPtr > edges(new vector); - - if ((faces == NULL) || (edges == NULL) || (verts == NULL)) { - return NULL; - } - - output->m_verts = verts.Release(); - output->m_faces = faces.Release(); - output->m_edges = edges.Release(); - - return output.Release(); -} - -// take ownership of the vertices. - - bool -LOD_ManMesh2:: -SetVertices( - MEM_SmartPtr > verts -){ - - - // take ownership of vertices - m_verts = verts; - - // create a polygon and edge buffer of half the size - // and just use the automatic resizing feature of vector<> - // to worry about the dynamic array resizing - - m_faces->clear(); - m_edges->clear(); - - m_faces->reserve(m_verts->size()/2); - m_edges->reserve(m_verts->size()/2); - - return true; - -} - - -// add a triangle to the mesh - - void -LOD_ManMesh2:: -AddTriangle( - int verts[3] -) { - - MT_assert(verts[0] < int(m_verts->size())); - MT_assert(verts[1] < int(m_verts->size())); - MT_assert(verts[2] < int(m_verts->size())); - - LOD_TriFace face; - face.m_verts[0] = verts[0]; - face.m_verts[1] = verts[1]; - face.m_verts[2] = verts[2]; - - LOD_FaceInd face_index = m_faces->size(); - - m_faces->push_back(face); - - // now work out if any of the directed edges or their - // companion edges exist already. - // We go through the edges associated with each of the given vertices - - // the safest thing to do is iterate through each of the edge sets - // check against each of the 2 other triangle edges to see if they are there - - vector new_edges; - new_edges.reserve(3); - - InsertEdge(verts[0],verts[1],face_index,new_edges); - InsertEdge(verts[1],verts[2],face_index,new_edges); - InsertEdge(verts[2],verts[0],face_index,new_edges); - -} - -// Adds the index of any created edges to new_edges - - bool -LOD_ManMesh2:: -InsertEdge( - const LOD_VertexInd v1, - const LOD_VertexInd v2, - const LOD_FaceInd f, - vector &new_edges -){ - - MT_assert(!v1.IsEmpty()); - MT_assert(!v2.IsEmpty()); - MT_assert(!f.IsEmpty()); - - vector &verts = VertexSet(); - vector &edges = EdgeSet(); - - LOD_EdgeInd e; - - e = FindEdge(v1,v2); - - if (e.IsEmpty()) { - // This edge does not exist -- make a new one - - LOD_Edge temp_e; - temp_e.m_verts[0] = v1; - temp_e.m_verts[1] = v2; - - e = m_edges->size(); - - // set the face ptr for this half-edge - temp_e.m_faces[0] = f; - - m_edges->push_back(temp_e); - - // add the edge index to it's vertices - - verts[v1].AddEdge(e); - verts[v2].AddEdge(e); - - new_edges.push_back(e); - - } else { - - // edge already exists - // insure that there is no polygon already - // attached to the other side of this edge - - // swap the empty face pointer in edge with f - - LOD_Edge &edge = edges[e]; - - edge.SwapFace(LOD_FaceInd::Empty(),f); - } - - - return true; - -} - - void -LOD_ManMesh2:: -ConnectTriangle( - LOD_FaceInd fi, - std::vector & new_edges -){ - - vector &faces = FaceSet(); - - MT_assert(!faces[fi].Degenerate()); - - LOD_TriFace & face = faces[fi]; - - InsertEdge(face.m_verts[0],face.m_verts[1],fi,new_edges); - InsertEdge(face.m_verts[1],face.m_verts[2],fi,new_edges); - InsertEdge(face.m_verts[2],face.m_verts[0],fi,new_edges); -}; - - - - -// geometry access -////////////////// - - vector & -LOD_ManMesh2:: -VertexSet( -) const { - return m_verts.Ref(); -} - - vector & -LOD_ManMesh2:: -FaceSet( -) const { - return m_faces.Ref(); -} - - vector & -LOD_ManMesh2:: -EdgeSet( -) const { - return m_edges.Ref(); -}; - -LOD_ManMesh2:: -~LOD_ManMesh2( -){ - //auto ptr takes care of vertex arrays etc. -} - - LOD_EdgeInd -LOD_ManMesh2:: -FindEdge( - const LOD_VertexInd v1, - const LOD_VertexInd v2 -) { - - vector &verts = VertexSet(); - vector &edges = EdgeSet(); - - LOD_Edge e; - e.m_verts[0] = v1; - e.m_verts[1] = v2; - - vector &v1_edges = verts[v1].m_edges; - vector::const_iterator v1_end = v1_edges.end(); - vector::iterator v1_begin = v1_edges.begin(); - - for (; v1_begin != v1_end; ++v1_begin) { - if (edges[*v1_begin] == e) return *v1_begin; - } - - return LOD_EdgeInd::Empty(); -} - -// face queries -/////////////// - - void -LOD_ManMesh2:: -FaceVertices( - LOD_FaceInd fi, - vector &output -){ - const vector &faces = FaceSet(); - const LOD_TriFace & f = faces[fi]; - - output.push_back(f.m_verts[0]); - output.push_back(f.m_verts[1]); - output.push_back(f.m_verts[2]); -} - - void -LOD_ManMesh2:: -FaceEdges( - LOD_FaceInd fi, - vector &output -){ - const vector &faces = FaceSet(); - vector &edges = EdgeSet(); - vector &verts = VertexSet(); - - const LOD_TriFace & f = faces[fi]; - // intersect vertex edges - - vector & v0_edges = verts[f.m_verts[0]].m_edges; - vector & v1_edges = verts[f.m_verts[1]].m_edges; - vector & v2_edges = verts[f.m_verts[2]].m_edges; - - CTR_TaggedSetOps::IntersectPair(v0_edges,v1_edges,edges,output); - CTR_TaggedSetOps::IntersectPair(v1_edges,v2_edges,edges,output); - CTR_TaggedSetOps::IntersectPair(v2_edges,v0_edges,edges,output); - - MT_assert(output.size() == 3); - if (output.size() != 3) { - LOD_MeshException e(LOD_MeshException::e_non_manifold); - throw(e); - } -} - - -// edge queries -/////////////// - - void -LOD_ManMesh2:: -EdgeVertices( - LOD_EdgeInd ei, - vector &output -){ - const vector &edges = EdgeSet(); - const LOD_Edge & e = edges[ei]; - - output.push_back(e.m_verts[0]); - output.push_back(e.m_verts[1]); -} - - void -LOD_ManMesh2:: -EdgeFaces( - LOD_EdgeInd ei, - vector &output -){ - const vector &edges = EdgeSet(); - const LOD_Edge & e = edges[ei]; - - if (!e.m_faces[0].IsEmpty()) { - output.push_back(e.m_faces[0]); - } - if (!e.m_faces[1].IsEmpty()) { - output.push_back(e.m_faces[1]); - } -} - -// vertex queries -///////////////// - - void -LOD_ManMesh2:: -VertexEdges( - LOD_VertexInd vi, - vector &output -){ - // iterate through the edges of v and push them onto the - // output - - vector &verts = VertexSet(); - - vector & v_edges = verts[vi].m_edges; - vector::iterator v_it = v_edges.begin(); - - for (; v_it != v_edges.end(); ++v_it) { - output.push_back(*v_it); - } -} - - void -LOD_ManMesh2:: -VertexFaces( - LOD_VertexInd vi, - vector &output -){ - const vector &verts = VertexSet(); - vector &edges = EdgeSet(); - vector &faces = FaceSet(); - - const vector &v_edges = verts[vi].m_edges; - vector::const_iterator e_it = v_edges.begin(); - - for (; e_it != v_edges.end(); ++e_it) { - - LOD_Edge &e = edges[*e_it]; - - if ((!e.m_faces[0].IsEmpty()) && (!faces[e.m_faces[0]].SelectTag())) { - output.push_back(e.m_faces[0]); - faces[e.m_faces[0]].SetSelectTag(true); - } - - if ((!e.m_faces[1].IsEmpty()) && (!faces[e.m_faces[1]].SelectTag())) { - output.push_back(e.m_faces[1]); - faces[e.m_faces[1]].SetSelectTag(true); - } - } - - vector::iterator f_it = output.begin(); - - for (; f_it != output.end(); ++f_it) { - faces[*f_it].SetSelectTag(false); - } -}; - - void -LOD_ManMesh2:: -SetBBox( - MT_Vector3 bbox_min, - MT_Vector3 bbox_max -){ - m_bbox_min = bbox_min; - m_bbox_max = bbox_max; -}; - - void -LOD_ManMesh2:: -SC_TriFace( - LOD_FaceInd f -){ - LOD_TriFace face = (*m_faces)[f]; - - // check for unique vertices - - if ( - (face.m_verts[0] == face.m_verts[1]) || - (face.m_verts[1] == face.m_verts[2]) || - (face.m_verts[2] == face.m_verts[0]) - ) { - MT_assert(false); - } - -} - - - void -LOD_ManMesh2:: -SC_EdgeList( - LOD_VertexInd v -){ - vector &edges = EdgeSet(); - vector &verts = VertexSet(); - - vector::iterator e_it = verts[v].m_edges.begin(); - - for (;e_it != verts[v].m_edges.end(); ++e_it) { - MT_assert( (edges[*e_it].m_verts[0] == v) || (edges[*e_it].m_verts[1] == v)); - } - -}; - - void -LOD_ManMesh2:: -DeleteVertex( - LOD_ExternBufferEditor & extern_editor, - LOD_VertexInd v -){ - - vector &edges = EdgeSet(); - vector &verts = VertexSet(); - vector &faces = FaceSet(); - - // need to update all the edge and polygons pointing to - // the last vertex in m_verts - - if (verts.size() == 1) { - verts.clear(); - return; - } - - LOD_VertexInd last = LOD_VertexInd(size_t(verts.end() - verts.begin() - 1)); - - if (!(last == v)) { - - // we asume that v is already disconnected - - vector v_faces; - vector v_edges; - - v_faces.reserve(64); - v_edges.reserve(64); - - VertexFaces(last,v_faces); - VertexEdges(last,v_edges); - - // map the faces and edges to look at v - - vector::iterator face_it = v_faces.begin(); - - for(; face_it != v_faces.end(); ++face_it) { - faces[*face_it].SwapVertex(last,v); - } - vector::iterator edge_it = v_edges.begin(); - - for (; edge_it != v_edges.end(); ++edge_it) { - edges[*edge_it].SwapVertex(last,v); - } - - // copy the last vertex onto v and pop off the back. - - verts[v] = verts[last]; - - // tidy external buffer - extern_editor.CopyModifiedFaces(*this,v_faces); - } - - verts.pop_back(); - extern_editor.CopyBackVertex(v); - - -}; - - void -LOD_ManMesh2:: -DeleteEdge( - LOD_EdgeInd e, - CTR_UHeap * heap -){ - vector &edges = EdgeSet(); - vector &verts = VertexSet(); - - if (edges.size() == 1) { - edges.clear(); - return; - } - - LOD_EdgeInd last = LOD_EdgeInd(size_t(edges.end() - edges.begin() - 1)); - - if (!(last == e)) { - vector e_verts; - e_verts.reserve(2); - EdgeVertices(last,e_verts); - // something is wrong if there arent two! - - verts[e_verts[0]].SwapEdge(last,e); - verts[e_verts[1]].SwapEdge(last,e); - - // edges[e] should already have been removed from the heap - - MT_assert(edges[e].HeapPos() == -1); - - edges[e] = edges[last]; - // also have to swap there heap positions.!!!!! - - heap->HeapVector()[edges[e].HeapPos()] = e; - - - } - edges.pop_back(); -}; - - void -LOD_ManMesh2:: -DeleteFace( - LOD_ExternBufferEditor & extern_editor, - LOD_FaceInd f -){ - - vector &edges = EdgeSet(); - vector &faces = FaceSet(); - - if (faces.size() == 1) { - faces.clear(); - return; - } - - LOD_FaceInd last = LOD_FaceInd(size_t (faces.end() - faces.begin() - 1)); - - if (!(last == f)) { - - // we have to update the edges which point to the last - // face - - vector f_edges; - f_edges.reserve(3); - - FaceEdges(last,f_edges); - - vector::iterator edge_it = f_edges.begin(); - vector::const_iterator edge_end = f_edges.end(); - - for (; edge_it != edge_end; ++edge_it) { - edges[*edge_it].SwapFace(last,f); - } - - faces[f] = faces[last]; - - } - faces.pop_back(); - - // tidy external buffers - extern_editor.CopyBackFace(f); -}; - - - - - - - - - - - - - - - - diff --git a/intern/decimation/intern/LOD_ManMesh2.h b/intern/decimation/intern/LOD_ManMesh2.h deleted file mode 100644 index 5d4e1aff4e6..00000000000 --- a/intern/decimation/intern/LOD_ManMesh2.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_ManMesh2.h - * \ingroup decimation - */ - - -#ifndef __LOD_MANMESH2_H__ -#define __LOD_MANMESH2_H__ - -#include "LOD_MeshPrimitives.h" -#include "MEM_SmartPtr.h" -#include - -template class CTR_UHeap; - -class LOD_ExternBufferEditor; - -class LOD_ManMesh2 // Manifold 2 dimensional mesh -{ - -public: - - static - LOD_ManMesh2 * - New( - ); - - // take ownership of the vertices. - - bool - SetVertices( - MEM_SmartPtr > verts - ); - - // Add a triangle to the mesh - - void - AddTriangle( - int verts[3] - ); - - void - ConnectTriangle( - LOD_FaceInd fi, - std::vector & new_edges - ); - - // geometry access - ////////////////// - - std::vector & - VertexSet( - ) const; - - std::vector & - FaceSet( - ) const; - - std::vector & - EdgeSet( - ) const; - - ~LOD_ManMesh2( - ); - - // local geometry queries - ///////////////////////// - - // face queries - /////////////// - - void - FaceVertices( - LOD_FaceInd f, - std::vector &output - ); - - void - FaceEdges( - LOD_FaceInd f, - std::vector &output - ); - - // edge queries - /////////////// - - void - EdgeVertices( - LOD_EdgeInd e, - std::vector &output - ); - - void - EdgeFaces( - LOD_EdgeInd e, - std::vector &output - ); - - // vertex queries - ///////////////// - - void - VertexEdges( - LOD_VertexInd v, - std::vector &output - ); - - void - VertexFaces( - LOD_VertexInd v, - std::vector &output - ); - - void - SetBBox( - MT_Vector3 bbox_min, - MT_Vector3 bbox_max - ); - - MT_Vector3 - BBoxMin( - ) const { - return m_bbox_min; - }; - - MT_Vector3 - BBoxMax( - ) const { - return m_bbox_max; - }; - - // Remove a primitive from the mesh - /////////////////////////////////// - - // These methods assume you have correctly - // tidied up the index pointers in other primitives, - // so that nothing refers to this object any more - - // These methods exchange the primitive with the - // last primitive in the vector. It modifies everything - // pointing to the last primitive correctly. - - // FIXME refactor extern editor out of primitive deletion - // insead return a vector of primitives that need to be - // modified and do this externally - - void - DeleteVertex( - LOD_ExternBufferEditor & extern_editor, - LOD_VertexInd v - ); - - void - DeleteEdge( - LOD_EdgeInd e, - CTR_UHeap *heap - ); - - void - DeleteFace( - LOD_ExternBufferEditor & extern_editor, - LOD_FaceInd f - ); - - // Sanity Check routines - //////////////////////// - - // Make sure the edge sets and the vertex sets are - // consistent - - void - SC_TriFace( - LOD_FaceInd f - ); - - // basic sanity checking of an edge list bails out if there are more than 1024 - // edges - - void - SC_EdgeList( - LOD_EdgeInd e - ); - - - // Check to see that the edges of v1 and v2 are unique. - - bool - SC_UniqueEdge( - LOD_EdgeInd e - ); - - -private : - - - // Returns the edge index of the edge from v1 to v2. - // Does this by searching the edge sets of v1 - but not v2. - // If you are paranoid you should check both and make sure the - // indices are the same. If the edge doe not exist edgeInd is empty. - - LOD_EdgeInd - FindEdge( - const LOD_VertexInd v1, - const LOD_VertexInd v2 - ); - - // Insert an edge into the mesh - // Tie up the ptrs and create space for the edge - // returns manifold errors - need to sort out memory edges - - bool - InsertEdge( - const LOD_VertexInd v1, - const LOD_VertexInd v2, - const LOD_FaceInd f, - std::vector &new_edges - ); - - -private : - - LOD_ManMesh2( - ); - - MEM_SmartPtr< std::vector > m_verts; - MEM_SmartPtr< std::vector > m_faces; - MEM_SmartPtr< std::vector > m_edges; - - // not sure of these descrtiptions of the mesh should - // reside in this class coz may lead to very bloated interface. - - MT_Vector3 m_bbox_min; - MT_Vector3 m_bbox_max; - - -}; - -#endif - diff --git a/intern/decimation/intern/LOD_MeshBounds.h b/intern/decimation/intern/LOD_MeshBounds.h deleted file mode 100644 index c95e6c7b61f..00000000000 --- a/intern/decimation/intern/LOD_MeshBounds.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_MeshBounds.h - * \ingroup decimation - */ - - -#ifndef __LOD_MESHBOUNDS_H__ -#define __LOD_MESHBOUNDS_H__ - -#include "MEM_SmartPtr.h" -#include "LOD_MeshPrimitives.h" -#include "LOD_ManMesh2.h" -#include "MT_assert.h" - -// simple class to compute the mesh bounds of a manifold mesh, - -class LOD_MeshBounds { - -public : - static - LOD_MeshBounds * - New( - ){ - - MEM_SmartPtr output(new LOD_MeshBounds()); - return output.Release(); - } - - void - ComputeBounds( - const LOD_ManMesh2 * mesh - ){ - MT_assert(mesh!=NULL); - MT_assert(mesh->VertexSet().size() > 0); - - const std::vector &verts = mesh->VertexSet(); - - m_min = verts[0].pos; - m_max = verts[0].pos; - - // iterate through the verts - - int t; - const int size = verts.size(); - - for (t=1; t< size ; ++t) { - - UpdateBounds(verts[t].pos,m_min,m_max); - } - } - - MT_Vector3 - Min( - ) const { - return m_min; - } - - MT_Vector3 - Max( - ) const { - return m_max; - } - -private : - - void - UpdateBounds( - MT_Vector3 vertex, - MT_Vector3& min, - MT_Vector3& max - ) { - if (vertex.x() < min.x()) { - min.x() = vertex.x(); - } else - if (vertex.x() > max.x()) { - max.x()= vertex.x(); - } - - if (vertex.y() < min.y()) { - min.y() = vertex.y(); - } else - if (vertex.y() > max.y()) { - max.y()= vertex.y(); - } - - if (vertex.z() < min.z()) { - min.z() = vertex.z(); - } else - if (vertex.z() > max.z()) { - max.z()= vertex.z(); - } - } - - LOD_MeshBounds( - ) : - m_min(0,0,0), - m_max(0,0,0) - { - }; - - MT_Vector3 m_min; - MT_Vector3 m_max; - -}; - -#endif - diff --git a/intern/decimation/intern/LOD_MeshPrimitives.cpp b/intern/decimation/intern/LOD_MeshPrimitives.cpp deleted file mode 100644 index ee4e4c120fc..00000000000 --- a/intern/decimation/intern/LOD_MeshPrimitives.cpp +++ /dev/null @@ -1,404 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_MeshPrimitives.cpp - * \ingroup decimation - */ - - -#include "LOD_MeshPrimitives.h" - -#include "MT_assert.h" -#include "LOD_MeshException.h" -#include - -using namespace std; - -// Vertex Methods -///////////////// - -LOD_Vertex:: -LOD_Vertex( -) : - pos (MT_Vector3()), - m_select_tag(false) -{ -}; - - bool -LOD_Vertex:: -RemoveEdge( - LOD_EdgeInd e -){ - - vector::iterator result = find(m_edges.begin(),m_edges.end(),e); - if (result == m_edges.end()) { - return false; - } - - std::swap(*result, m_edges.back()); - m_edges.pop_back(); - return true; -}; - - void -LOD_Vertex:: -AddEdge( - LOD_EdgeInd e -){ - m_edges.push_back(e); -}; - - void -LOD_Vertex:: -SwapEdge( - LOD_EdgeInd e_old, - LOD_EdgeInd e_new -){ - - vector::iterator result = - find(m_edges.begin(),m_edges.end(),e_old); - if (result == m_edges.end()) { - MT_assert(false); - LOD_MeshException e(LOD_MeshException::e_search_error); - throw(e); - } - - *result = e_new; -}; - - bool -LOD_Vertex:: -SelectTag( -) const { - return m_select_tag; -}; - - void -LOD_Vertex:: -SetSelectTag( - bool tag -){ - m_select_tag = tag; -}; - - bool -LOD_Vertex:: -Degenerate( -){ - return m_edges.empty(); -} - - void -LOD_Vertex:: -CopyPosition( - float *float_ptr -){ - pos.getValue(float_ptr); -} - - - -// Edge Methods -/////////////// - -LOD_Edge:: -LOD_Edge ( -) { - m_verts[0] = m_verts[1] = LOD_VertexInd::Empty(); - m_faces[0] = m_faces[1] = LOD_FaceInd::Empty(); -} - - bool -LOD_Edge:: -operator == ( - LOD_Edge & rhs -) { - // edges are the same if their vertex indices are the - // same!!! Other properties are not checked - - int matches = 0; - - if (this->m_verts[0] == rhs.m_verts[0]) { - ++matches; - } - if (this->m_verts[1] == rhs.m_verts[0]) { - ++matches; - } - if (this->m_verts[0] == rhs.m_verts[1]) { - ++matches; - } - if (this->m_verts[1] == rhs.m_verts[1]) { - ++matches; - } - - if (matches >= 2) { - return true; - } - return false; -} - -// Elementary helper methods -//////////////////////////// - - LOD_FaceInd -LOD_Edge:: -OpFace( - LOD_FaceInd f -) const { - if (f == m_faces[0]) { - return m_faces[1]; - } else - if (f == m_faces[1]) { - return m_faces[0]; - } else { - MT_assert(false); - LOD_MeshException e(LOD_MeshException::e_search_error); - throw(e); - - return LOD_FaceInd::Empty(); - } -} - - void -LOD_Edge:: -SwapFace( - LOD_FaceInd old_f, - LOD_FaceInd new_f -) { - if (old_f == m_faces[0]) { - m_faces[0] = new_f; - } else - if (old_f == m_faces[1]) { - m_faces[1] = new_f; - } else { - LOD_MeshException e(LOD_MeshException::e_search_error); - throw(e); - } -} - - -// return the half edge face - the half edge is defined -// by the {vertex,edge} tuple. - - LOD_FaceInd -LOD_Edge:: -HalfEdgeFace( - LOD_VertexInd vi -){ - if (vi == m_verts[0]) return m_faces[0]; - if (vi == m_verts[1]) return m_faces[1]; - MT_assert(false); - - LOD_MeshException e(LOD_MeshException::e_search_error); - throw(e); - - return LOD_FaceInd::Empty(); -} - - - LOD_VertexInd -LOD_Edge:: -OpVertex( - LOD_VertexInd vi -) { - if (vi == m_verts[0]) return m_verts[1]; - if (vi == m_verts[1]) return m_verts[0]; - MT_assert(false); - - LOD_MeshException e(LOD_MeshException::e_search_error); - throw(e); - - return LOD_VertexInd::Empty(); -} - -// replace the vertex v_old with vertex v_new -// error if v_old is not one of the original vertices - - void -LOD_Edge:: -SwapVertex( - LOD_VertexInd v_old, - LOD_VertexInd v_new -) { - if (v_old == m_verts[0]) { - m_verts[0] = v_new; - } else - if (v_old == m_verts[1]) { - m_verts[1] = v_new; - } else { - - MT_assert(false); - - LOD_MeshException e(LOD_MeshException::e_search_error); - throw(e); - } - if(m_verts[0] == m_verts[1]) { - MT_assert(false); - - LOD_MeshException e(LOD_MeshException::e_non_manifold); - throw(e); - } - -} - - bool -LOD_Edge:: -SelectTag( -) const { - return bool(m_verts[1].Tag() & 0x1); -}; - - void -LOD_Edge:: -SetSelectTag( - bool tag -) { - m_verts[1].SetTag(int(tag)); -}; - - int -LOD_Edge:: -OpenTag( -) const { - return m_faces[0].Tag(); -} - - void -LOD_Edge:: -SetOpenTag( - int tag -) { - m_faces[0].SetTag(tag); -} - - bool -LOD_Edge:: -Degenerate( -) const { - return ( - (m_faces[0].IsEmpty() && m_faces[1].IsEmpty()) || - (m_verts[0] == m_verts[1]) - ); -}; - -// TriFace Methods -////////////////// - -LOD_TriFace:: -LOD_TriFace( -) { - m_verts[0] = m_verts[1] = m_verts[2] = LOD_VertexInd::Empty(); -} - -// Elementary helper methods -//////////////////////////// - - void -LOD_TriFace:: -SwapVertex( - LOD_VertexInd old_v, - LOD_VertexInd new_v -) { - // could save branching here... - - if (m_verts[0] == old_v) { - m_verts[0] = new_v; - } else - if (m_verts[1] == old_v) { - m_verts[1] = new_v; - } else - if (m_verts[2] == old_v) { - m_verts[2] = new_v; - } else { - MT_assert(false); - - LOD_MeshException excep(LOD_MeshException::e_search_error); - throw(excep); - } -} - - bool -LOD_TriFace:: -SelectTag( -) const { - return bool(m_verts[1].Tag() & 0x1); -}; - - void -LOD_TriFace:: -SetSelectTag( - bool tag -) { - m_verts[1].SetTag(int(tag)); -}; - - int -LOD_TriFace:: -OpenTag( -) { - return m_verts[2].Tag(); -} - - void -LOD_TriFace:: -SetOpenTag( - int tag -) { - m_verts[2].SetTag(tag); -} - - bool -LOD_TriFace:: -Degenerate( -) { - - return ( - (m_verts[0] == m_verts[1]) || - (m_verts[1] == m_verts[2]) || - (m_verts[2] == m_verts[0]) - ); -} - - void -LOD_TriFace:: -CopyVerts( - int * index_ptr -){ - index_ptr[0] = m_verts[0]; - index_ptr[1] = m_verts[1]; - index_ptr[2] = m_verts[2]; -}; - - - - - - - - - diff --git a/intern/decimation/intern/LOD_MeshPrimitives.h b/intern/decimation/intern/LOD_MeshPrimitives.h deleted file mode 100644 index ea2d157308b..00000000000 --- a/intern/decimation/intern/LOD_MeshPrimitives.h +++ /dev/null @@ -1,221 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_MeshPrimitives.h - * \ingroup decimation - */ - - -#ifndef __LOD_MESHPRIMITIVES_H__ -#define __LOD_MESHPRIMITIVES_H__ - -#include "MT_Vector3.h" -#include "CTR_TaggedIndex.h" -#include "CTR_UHeap.h" -#include - -typedef CTR_TaggedIndex<24,0x00ffffff> LOD_VertexInd; -typedef CTR_TaggedIndex<24,0x00ffffff> LOD_EdgeInd; -typedef CTR_TaggedIndex<24,0x00ffffff> LOD_FaceInd; -typedef CTR_TaggedIndex<24,0x00ffffff> LOD_HeapInd; - -class LOD_Vertex { -public : - MT_Vector3 pos; - std::vector m_edges; - bool m_select_tag; - - LOD_Vertex( - ); - - bool - RemoveEdge( - LOD_EdgeInd e - ); - - void - AddEdge( - LOD_EdgeInd e - ); - - void - SwapEdge( - LOD_EdgeInd e_old, - LOD_EdgeInd e_new - ); - - bool - SelectTag( - ) const; - - void - SetSelectTag( - bool tag - ); - - bool - Degenerate( - ); - - void - CopyPosition( - float *float_ptr - ); - -private : - - -}; - -class LOD_Edge : public CTR_UHeapable { -public : - LOD_VertexInd m_verts[2]; - LOD_FaceInd m_faces[2]; - - LOD_Edge ( - ); - - bool operator == ( - LOD_Edge & rhs - ); - - // Elementary helper methods - //////////////////////////// - - LOD_FaceInd - OpFace( - LOD_FaceInd f - ) const; - - void - SwapFace( - LOD_FaceInd old_f, - LOD_FaceInd new_f - ); - - - // return the half edge face - the half edge is defined - // by the {vertex,edge} tuple. - - LOD_FaceInd - HalfEdgeFace( - LOD_VertexInd vi - ); - - - LOD_VertexInd - OpVertex( - LOD_VertexInd vi - ); - - // replace the vertex v_old with vertex v_new - // error if v_old is not one of the original vertices - - void - SwapVertex( - LOD_VertexInd v_old, - LOD_VertexInd v_new - ); - - bool - SelectTag( - ) const; - - void - SetSelectTag( - bool tag - ); - - int - OpenTag( - ) const; - - void - SetOpenTag( - int tag - ); - - bool - Degenerate( - ) const; - - bool - BoundaryEdge( - ) const { - return (m_faces[0].IsEmpty() || m_faces[1].IsEmpty()); - }; - - -}; - -class LOD_TriFace { -public: - - LOD_VertexInd m_verts[3]; - - LOD_TriFace( - ); - - // Elementary helper methods - //////////////////////////// - - void - SwapVertex( - LOD_VertexInd old_v, - LOD_VertexInd new_v - ); - - bool - SelectTag( - ) const; - - void - SetSelectTag( - bool tag - ); - - int - OpenTag( - ); - void - SetOpenTag( - int tag - ); - - bool - Degenerate( - ); - - void - CopyVerts( - int * index_ptr - ); - -}; - -#endif - diff --git a/intern/decimation/intern/LOD_QSDecimator.cpp b/intern/decimation/intern/LOD_QSDecimator.cpp deleted file mode 100644 index bdcf7950447..00000000000 --- a/intern/decimation/intern/LOD_QSDecimator.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_QSDecimator.cpp - * \ingroup decimation - */ - - -#include "LOD_QSDecimator.h" - -#include "LOD_ExternBufferEditor.h" - -using namespace std; - - LOD_QSDecimator * -LOD_QSDecimator:: -New( - LOD_ManMesh2 &mesh, - LOD_ExternNormalEditor &face_editor, - LOD_ExternBufferEditor &extern_editor -){ - - MEM_SmartPtr output - = new LOD_QSDecimator(mesh,face_editor,extern_editor); - - MEM_SmartPtr collapser(LOD_EdgeCollapser::New()); - MEM_SmartPtr q_editor(LOD_QuadricEditor::New(mesh)); - - if ( - output == NULL || - collapser == NULL || - q_editor == NULL - ) { - return NULL; - } - output->m_collapser = collapser.Release(); - output->m_quadric_editor = q_editor.Release(); - return output.Release(); -} - - - - bool -LOD_QSDecimator:: -Arm( -){ - MT_assert(!m_is_armed); - bool heap_result = BuildHeap(); - if (!heap_result) { - return false; - } - m_is_armed = true; - return true; -} - - bool -LOD_QSDecimator:: -Step( -){ - return CollapseEdge(); -} - - -LOD_QSDecimator:: -LOD_QSDecimator( - LOD_ManMesh2 &mesh, - LOD_ExternNormalEditor &face_editor, - LOD_ExternBufferEditor &extern_editor -) : - m_is_armed (false), - m_mesh(mesh), - m_face_editor(face_editor), - m_extern_editor(extern_editor) -{ - m_deg_edges.reserve(32); - m_deg_faces.reserve(32); - m_deg_vertices.reserve(32); - m_update_faces.reserve(32); - m_new_edges.reserve(32); - m_update_vertices.reserve(32); -}; - - bool -LOD_QSDecimator:: -CollapseEdge( -){ - - // find an edge to collapse - - // FIXME force an edge collapse - // or return false - - std::vector & edges = m_mesh.EdgeSet(); - std::vector & verts = m_mesh.VertexSet(); - std::vector & quadrics = m_quadric_editor->Quadrics(); - int size = edges.size(); - - if (size == 0) return false; - - const int heap_top = m_heap->Top(); - - if (heap_top == -1 || edges[heap_top].HeapKey() <= -MT_INFINITY) { - return false; - } - - // compute the target position - MT_Vector3 new_vertex = m_quadric_editor->TargetVertex(edges[heap_top]); - LOD_Quadric & q0 = quadrics[edges[heap_top].m_verts[0]]; - LOD_Quadric & q1 = quadrics[edges[heap_top].m_verts[1]]; - - LOD_Vertex &v0 = verts[edges[heap_top].m_verts[0]]; - LOD_Vertex &v1 = verts[edges[heap_top].m_verts[1]]; - - LOD_Quadric sum = q0; - sum += q1; - - - if (m_collapser->CollapseEdge( - heap_top, - m_mesh, - m_deg_edges, - m_deg_faces, - m_deg_vertices, - m_new_edges, - m_update_faces, - m_update_vertices - )) { - - // assign new vertex position - - v0.pos = new_vertex; - v1.pos = new_vertex; - - // sum the quadrics of v0 and v1 - q0 = sum; - q1 = sum; - - // ok update the primitive properties - - m_face_editor.Update(m_update_faces); - m_face_editor.UpdateVertexNormals(m_update_vertices); - - // update the external vertex buffer - m_extern_editor.CopyModifiedVerts(m_mesh,m_update_vertices); - - // update the external face buffer - m_extern_editor.CopyModifiedFaces(m_mesh,m_update_faces); - - // update the edge heap - UpdateHeap(m_deg_edges,m_new_edges); - - m_quadric_editor->Remove(m_deg_vertices); - m_face_editor.Remove(m_deg_faces); - m_face_editor.RemoveVertexNormals(m_deg_vertices); - - // delete the primitives - - DeletePrimitives(m_deg_edges,m_deg_faces,m_deg_vertices); - - } else { - // the edge could not be collapsed at the moment - so - // we adjust it's priority and add it back to the heap. - m_heap->Remove(&edges[0],0); - edges[heap_top].HeapKey() = - MT_INFINITY; - m_heap->Insert(&edges[0],heap_top); - } - - //clear all the temporary buffers - - m_deg_faces.clear(); - m_deg_edges.clear(); - m_deg_vertices.clear(); - - m_update_faces.clear(); - m_update_vertices.clear(); - m_new_edges.clear(); - - return true; - -} - - void -LOD_QSDecimator:: -DeletePrimitives( - const vector & degenerate_edges, - const vector & degenerate_faces, - const vector & degenerate_vertices -) { - - // assumes that the 3 vectors are sorted in descending order. - - // Delete Degnerate primitives - ////////////////////////////// - - - // delete the old edges - we have to be very careful here - // mesh.delete() swaps edges to be deleted with the last edge in - // the edge buffer. However the next edge to be deleted may have - // been the last edge in the buffer! - - // One way to solve this is to sort degenerate_edges in descending order. - // And then delete them in that order. - - // it is also vital that degenerate_edges contains no duplicates - - vector::const_iterator edge_it = degenerate_edges.begin(); - vector::const_iterator edge_end = degenerate_edges.end(); - - for (; edge_it != edge_end; ++edge_it) { - m_mesh.DeleteEdge(*edge_it,m_heap); - } - - - - vector::const_iterator face_it = degenerate_faces.begin(); - vector::const_iterator face_end = degenerate_faces.end(); - - for (;face_it != face_end; ++face_it) { - m_mesh.DeleteFace(m_extern_editor,*face_it); - } - - vector::const_iterator vertex_it = degenerate_vertices.begin(); - vector::const_iterator vertex_end = degenerate_vertices.end(); - - for (;vertex_it != vertex_end; ++vertex_it) { - m_mesh.DeleteVertex(m_extern_editor,*vertex_it); - } -} - - - bool -LOD_QSDecimator:: -BuildHeap( -){ - // build the quadrics - - if (m_quadric_editor->BuildQuadrics(m_face_editor,true) == false) return false; - - - m_heap = CTR_UHeap::New(); - // load in edge pointers to the heap - - std::vector & edge_set= m_mesh.EdgeSet(); - - // UNUSED - // std::vector::const_iterator edge_end = edge_set.end(); - // std::vector::iterator edge_start = edge_set.begin(); - - std::vector & heap_vector = m_heap->HeapVector(); - - for (unsigned int i = 0; i < edge_set.size(); ++i) { - edge_set[i].HeapPos() = i; - heap_vector.push_back(i); - } - - m_heap->MakeHeap(&edge_set[0]); - - return true; -} - - void -LOD_QSDecimator:: -UpdateHeap( - std::vector °_edges, - std::vector &new_edges -){ - // first of all compute values for the new edges - // and bung them on the heap. - - std::vector & edge_set= m_mesh.EdgeSet(); - - std::vector::const_iterator edge_it = new_edges.begin(); - std::vector::const_iterator end_it = new_edges.end(); - - - // insert all the new edges - /////////////////////////// - - // compute edge costs ffor the new edges - - m_quadric_editor->ComputeEdgeCosts(new_edges); - - // inser the new elements into the heap - - for (; edge_it != end_it; ++edge_it) { - m_heap->Insert(&edge_set[0],*edge_it); - } - - - // remove all the old values from the heap - - edge_it = deg_edges.begin(); - end_it = deg_edges.end(); - - for (; edge_it != end_it; ++edge_it) { - LOD_Edge &e = edge_set[*edge_it]; - m_heap->Remove(&edge_set[0],e.HeapPos()); - - e.HeapPos() = -1; - - } -} - diff --git a/intern/decimation/intern/LOD_QSDecimator.h b/intern/decimation/intern/LOD_QSDecimator.h deleted file mode 100644 index 2ac223996f2..00000000000 --- a/intern/decimation/intern/LOD_QSDecimator.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_QSDecimator.h - * \ingroup decimation - */ - - -#ifndef __LOD_QSDECIMATOR_H__ -#define __LOD_QSDECIMATOR_H__ - -#include "MEM_NonCopyable.h" -#include "LOD_ManMesh2.h" -#include "LOD_ExternNormalEditor.h" -#include "LOD_EdgeCollapser.h" -#include "LOD_QuadricEditor.h" - -class LOD_ExternBufferEditor; - -class LOD_QSDecimator : public MEM_NonCopyable { - -public : - - static - LOD_QSDecimator * - New( - LOD_ManMesh2 &mesh, - LOD_ExternNormalEditor &face_editor, - LOD_ExternBufferEditor &extern_editor - ); - - - bool - Arm( - ); - - - bool - Step( - ); - -private : - - LOD_QSDecimator( - LOD_ManMesh2 &mesh, - LOD_ExternNormalEditor &face_editor, - LOD_ExternBufferEditor &extern_editor - ); - - bool - CollapseEdge( - ); - - bool - BuildHeap( - ); - - void - UpdateHeap( - std::vector °_edges, - std::vector &new_edges - ); - - void - DeletePrimitives( - const std::vector & degenerate_edges, - const std::vector & degenerate_faces, - const std::vector & degenerate_vertices - ); - - -private : - - // owned by this class - ////////////////////// - - MEM_SmartPtr m_collapser; - MEM_SmartPtr > m_heap; - MEM_SmartPtr m_quadric_editor; - - bool m_is_armed; - - // arguments to New(...) - //////////////////////// - - LOD_ManMesh2 & m_mesh; - LOD_ExternNormalEditor &m_face_editor; - LOD_ExternBufferEditor & m_extern_editor; - - // temporary buffers - //////////////////// - - std::vector m_deg_faces; - std::vector m_deg_edges; - std::vector m_deg_vertices; - - std::vector m_update_faces; - std::vector m_new_edges; - std::vector m_update_vertices; - - -}; - -#endif - diff --git a/intern/decimation/intern/LOD_Quadric.h b/intern/decimation/intern/LOD_Quadric.h deleted file mode 100644 index 9dde0502aa3..00000000000 --- a/intern/decimation/intern/LOD_Quadric.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_Quadric.h - * \ingroup decimation - */ - - -#ifndef __LOD_QUADRIC_H__ -#define __LOD_QUADRIC_H__ - -#include "MT_Vector3.h" -#include "MT_Matrix3x3.h" - - -class LOD_Quadric { - -private: - MT_Scalar a2, ab, ac, ad; - MT_Scalar b2, bc, bd; - MT_Scalar c2, cd; - MT_Scalar d2; - - void init(MT_Scalar a, MT_Scalar b, MT_Scalar c, MT_Scalar d); - -public: - - LOD_Quadric( - ) { - Clear(); - }; - - LOD_Quadric( - const MT_Vector3 & vec, - const MT_Scalar & offset - ) { - a2 = vec[0] *vec[0]; - b2 = vec[1] *vec[1]; - c2 = vec[2] *vec[2]; - - ab = vec[0]*vec[1]; - ac = vec[0]*vec[2]; - bc = vec[1]*vec[2]; - - MT_Vector3 temp = vec*offset; - ad = temp[0]; - bd = temp[1]; - cd = temp[2]; - - d2 = offset*offset; - }; - - MT_Matrix3x3 - Tensor( - ) const { - // return a symmetric matrix - - return MT_Matrix3x3( - a2,ab,ac, - ab,b2,bc, - ac,bc,c2 - ); - }; - - - MT_Vector3 - Vector( - ) const { - return MT_Vector3(ad, bd, cd); - }; - - void - Clear( - MT_Scalar val=0.0 - ) { - a2=ab=ac=ad=b2=bc=bd=c2=cd=d2=val; - }; - - LOD_Quadric & - operator=( - const LOD_Quadric& Q - ) { - - a2 = Q.a2; ab = Q.ab; ac = Q.ac; ad = Q.ad; - b2 = Q.b2; bc = Q.bc; bd = Q.bd; - c2 = Q.c2; cd = Q.cd; - d2 = Q.d2; - return *this; - }; - - LOD_Quadric& - operator+=( - const LOD_Quadric& Q - ) { - a2 += Q.a2; ab += Q.ab; ac += Q.ac; ad += Q.ad; - b2 += Q.b2; bc += Q.bc; bd += Q.bd; - c2 += Q.c2; cd += Q.cd; - d2 += Q.d2; - return *this; - }; - - LOD_Quadric& - operator*=( - const MT_Scalar & s - ) { - a2 *= s; ab *= s; ac *= s; ad *= s; - b2 *= s; bc *= s; bd *= s; - c2 *= s; cd *= s; - d2 *= s; - return *this; - }; - - - MT_Scalar - Evaluate( - const MT_Vector3 &v - ) const { - // compute the LOD_Quadric error - - return v[0]*v[0]*a2 + 2*v[0]*v[1]*ab + 2*v[0]*v[2]*ac + 2*v[0]*ad - +v[1]*v[1]*b2 + 2*v[1]*v[2]*bc + 2*v[1]*bd - +v[2]*v[2]*c2 + 2*v[2]*cd - + d2; - }; - - bool - Optimize( - MT_Vector3& v - ) const { - - MT_Scalar det = Tensor().determinant(); - if (MT_fuzzyZero(det)) { - return false; - } - - v = -((Tensor().inverse()) * Vector()); - return true; - }; - -}; - -#endif - diff --git a/intern/decimation/intern/LOD_QuadricEditor.cpp b/intern/decimation/intern/LOD_QuadricEditor.cpp deleted file mode 100644 index fbaf0c1180f..00000000000 --- a/intern/decimation/intern/LOD_QuadricEditor.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_QuadricEditor.cpp - * \ingroup decimation - */ - - -#include "LOD_QuadricEditor.h" -#include "LOD_ExternNormalEditor.h" - -// Creation -/////////// - -using namespace std; - - -LOD_QuadricEditor:: -LOD_QuadricEditor( - LOD_ManMesh2 &mesh -) : - m_quadrics(NULL), - m_mesh(mesh) -{ -}; - - LOD_QuadricEditor * -LOD_QuadricEditor:: -New( - LOD_ManMesh2 &mesh -){ - //same number of quadrics as vertices in the mesh - - MEM_SmartPtr output(new LOD_QuadricEditor(mesh)); - - if (output == NULL) { - return NULL; - } - return output.Release(); -} - - -// Property editor interface -//////////////////////////// - - void -LOD_QuadricEditor:: -Remove( - std::vector &sorted_vertices -){ - vector & quadrics = *m_quadrics; - - vector::const_iterator it_start = sorted_vertices.begin(); - vector::const_iterator it_end = sorted_vertices.end(); - - for (; it_start != it_end; ++it_start) { - - if (quadrics.size() > 0) { - LOD_Quadric temp = quadrics[*it_start]; - - quadrics[*it_start] = quadrics.back(); - quadrics.back() = temp; - - quadrics.pop_back(); - } - } -}; - - -// Editor specific methods -////////////////////////// - - bool -LOD_QuadricEditor:: -BuildQuadrics( - LOD_ExternNormalEditor& normal_editor, - bool preserve_boundaries -){ - if (m_quadrics != NULL) delete(m_quadrics); - - m_quadrics =new vector (m_mesh.VertexSet().size()); - if (m_quadrics == NULL) return false; - - // iterate through the face set of the mesh - // compute a quadric based upon that face and - // add it to each of it's vertices quadrics. - - const vector &faces = m_mesh.FaceSet(); - const vector &verts = m_mesh.VertexSet(); - vector &edges = m_mesh.EdgeSet(); - - const vector &normals = normal_editor.Normals(); - vector::const_iterator normal_it = normals.begin(); - - vector::const_iterator face_it = faces.begin(); - vector::const_iterator face_end = faces.end(); - - vector & quadrics = *m_quadrics; - - - for (; face_it != face_end; ++face_it, ++normal_it) { - - MT_Vector3 normal = *normal_it; - MT_Scalar offset = -normal.dot(verts[face_it->m_verts[0]].pos); - - LOD_Quadric q(normal,offset); - - quadrics[face_it->m_verts[0]] += q; - quadrics[face_it->m_verts[1]] += q; - quadrics[face_it->m_verts[2]] += q; - } - - if (preserve_boundaries) { - - // iterate through the edge set and add a boundary quadric to - // each of the boundary edges vertices. - - vector::const_iterator edge_it = edges.begin(); - vector::const_iterator edge_end = edges.end(); - - for (; edge_it != edge_end; ++edge_it) { - if (edge_it->BoundaryEdge()) { - - // compute a plane perpendicular to the edge and the normal - // of the edges single polygon. - const MT_Vector3 & v0 = verts[edge_it->m_verts[0]].pos; - const MT_Vector3 & v1 = verts[edge_it->m_verts[1]].pos; - - MT_Vector3 edge_vector = v1 - v0; - - LOD_FaceInd edge_face = edge_it->OpFace(LOD_EdgeInd::Empty()); - edge_vector = edge_vector.cross(normals[edge_face]); - - if (!edge_vector.fuzzyZero()) { - edge_vector.normalize(); - - LOD_Quadric boundary_q(edge_vector, - edge_vector.dot(v0)); - boundary_q *= 100; - - quadrics[edge_it->m_verts[0]] += boundary_q; - quadrics[edge_it->m_verts[1]] += boundary_q; - } - } - } - } - - - // initiate the heap keys of the edges by computing the edge costs. - - vector::iterator edge_it = edges.begin(); - vector::const_iterator edge_end = edges.end(); - - for (; edge_it != edge_end; ++edge_it) { - - MT_Vector3 target = TargetVertex(*edge_it); - - LOD_Edge &e = *edge_it; - LOD_Quadric q0 = quadrics[e.m_verts[0]]; - const LOD_Quadric &q1 = quadrics[e.m_verts[1]]; - - e.HeapKey() = -float(q0.Evaluate(target) + q1.Evaluate(target)); - } - - return true; - -}; - - MT_Vector3 -LOD_QuadricEditor:: -TargetVertex( - LOD_Edge & e -){ - - // compute an edge contration target for edge ei - // this is computed by summing it's vertices quadrics and - // optimizing the result. - vector &verts = m_mesh.VertexSet(); - - vector &quadrics = *m_quadrics; - - LOD_VertexInd v0 = e.m_verts[0]; - LOD_VertexInd v1 = e.m_verts[1]; - - LOD_Quadric q0 = quadrics[v0]; - q0 += quadrics[v1]; - - MT_Vector3 result; - - if (q0.Optimize(result)) { - return result; - } else { - // the quadric was degenerate -> just take the average of - // v0 and v1 - - return ((verts[v0].pos + verts[v1].pos) * 0.5); - } -}; - - void -LOD_QuadricEditor:: -ComputeEdgeCosts( - vector &edges -){ - - // for each we compute the target vertex and then compute - // the quadric error e = Q1(v') + Q2(v') - vector &edge_set = m_mesh.EdgeSet(); - - vector &quadrics = *m_quadrics; - - vector::const_iterator edge_it = edges.begin(); - vector::const_iterator edge_end = edges.end(); - - for (; edge_it != edge_end; ++edge_it) { - - MT_Vector3 target = TargetVertex(edge_set[*edge_it]); - - LOD_Edge &e = edge_set[*edge_it]; - LOD_Quadric q0 = quadrics[e.m_verts[0]]; - const LOD_Quadric &q1 = quadrics[e.m_verts[1]]; - - e.HeapKey() = -float(q0.Evaluate(target) + q1.Evaluate(target)); - } -}; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/intern/decimation/intern/LOD_QuadricEditor.h b/intern/decimation/intern/LOD_QuadricEditor.h deleted file mode 100644 index 0a66d299e15..00000000000 --- a/intern/decimation/intern/LOD_QuadricEditor.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_QuadricEditor.h - * \ingroup decimation - */ - - -#ifndef __LOD_QUADRICEDITOR_H__ -#define __LOD_QUADRICEDITOR_H__ - -#include "MEM_NonCopyable.h" -#include "LOD_ManMesh2.h" -#include "MT_Vector3.h" -#include "LOD_Quadric.h" - -class LOD_ExternNormalEditor; - - -class LOD_QuadricEditor : public MEM_NonCopyable -{ - -public : - - // Creation - /////////// - - static - LOD_QuadricEditor * - New( - LOD_ManMesh2 &mesh - ); - - // Property editor interface - //////////////////////////// - - void - Remove( - std::vector &sorted_vertices - ); - - void - Update( - std::vector &sorted_vertices - ); - - - std::vector & - Quadrics( - ) const { - return *m_quadrics; - }; - - - // Editor specific methods - ////////////////////////// - - bool - BuildQuadrics( - LOD_ExternNormalEditor& normal_editor, - bool preserve_boundaries - ); - - - void - ComputeEdgeCosts( - std::vector &edges - ); - - MT_Vector3 - TargetVertex( - LOD_Edge &e - ); - - ~LOD_QuadricEditor( - ){ - delete(m_quadrics); - }; - - -private : - - std::vector * m_quadrics; - - LOD_ManMesh2 &m_mesh; - -private : - - LOD_QuadricEditor(LOD_ManMesh2 &mesh); - - - -}; - -#endif - diff --git a/intern/decimation/intern/LOD_decimation.cpp b/intern/decimation/intern/LOD_decimation.cpp deleted file mode 100644 index 49033933cd6..00000000000 --- a/intern/decimation/intern/LOD_decimation.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - * ***** 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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file decimation/intern/LOD_decimation.cpp - * \ingroup decimation - */ - - -// implementation of external c api -#include "../extern/LOD_decimation.h" -#include "LOD_DecimationClass.h" - -using namespace std; - - int -LOD_LoadMesh( - LOD_Decimation_InfoPtr info -) { - if (info == NULL) return 0; - if ( - info->vertex_buffer == NULL || - info->vertex_normal_buffer == NULL || - info->triangle_index_buffer == NULL - ) { - return 0; - } - - - // create the intern object to hold all - // the decimation classes - - MEM_SmartPtr intern(LOD_DecimationClass::New(info)); - - if (intern == NULL) return 0; - - MEM_SmartPtr > intern_vertex_buffer(new vector(info->vertex_num)); - if (intern_vertex_buffer == NULL) return 0; - - vector::iterator intern_vertex_it(intern_vertex_buffer->begin()); - - // now load in the vertices to the mesh - - const int vertex_stride = 3; - - float * vertex_ptr = info->vertex_buffer; - const float * vertex_end = vertex_ptr + info->vertex_num*vertex_stride; - - LOD_ManMesh2 &mesh = intern->Mesh(); - - for (;vertex_ptr < vertex_end; vertex_ptr += vertex_stride,++intern_vertex_it) { - intern_vertex_it->pos = MT_Vector3(vertex_ptr); - } - - mesh.SetVertices(intern_vertex_buffer); - - // load in the triangles - - const int triangle_stride = 3; - - int * triangle_ptr = info->triangle_index_buffer; - const int * triangle_end = triangle_ptr + info->face_num*triangle_stride; - - try { - - for (;triangle_ptr < triangle_end; triangle_ptr += triangle_stride) { - mesh.AddTriangle(triangle_ptr); - } - } - - catch (...) { - return 0; - } - - // ok we have built the mesh - - intern->m_e_decimation_state = LOD_DecimationClass::e_loaded; - - info->intern = (void *) (intern.Release()); - - return 1; -} - - int -LOD_PreprocessMesh( - LOD_Decimation_InfoPtr info -) { - if (info == NULL) return 0; - if (info->intern == NULL) return 0; - - LOD_DecimationClass *intern = (LOD_DecimationClass *) info->intern; - if (intern->m_e_decimation_state != LOD_DecimationClass::e_loaded) return 0; - - // arm the various internal classes so that we are ready to step - // through decimation - - intern->FaceEditor().BuildNormals(); - if (intern->Decimator().Arm() == false) return 0; - - // ok preprocessing done - intern->m_e_decimation_state = LOD_DecimationClass::e_preprocessed; - - return 1; -} - - int -LOD_CollapseEdge( - LOD_Decimation_InfoPtr info -){ - if (info == NULL) return 0; - if (info->intern == NULL) return 0; - LOD_DecimationClass *intern = (LOD_DecimationClass *) info->intern; - if (intern->m_e_decimation_state != LOD_DecimationClass::e_preprocessed) return 0; - - bool step_result = intern->Decimator().Step(); - - return step_result == true ? 1 : 0; -} - - - int -LOD_FreeDecimationData( - LOD_Decimation_InfoPtr info -){ - if (info == NULL) return 0; - if (info->intern == NULL) return 0; - LOD_DecimationClass *intern = (LOD_DecimationClass *) info->intern; - delete(intern); - info->intern = NULL; - return 1; -} - diff --git a/intern/dualcon/CMakeLists.txt b/intern/dualcon/CMakeLists.txt index caa1ea09b04..da5e10fe6a7 100644 --- a/intern/dualcon/CMakeLists.txt +++ b/intern/dualcon/CMakeLists.txt @@ -19,6 +19,9 @@ set(INC . intern +) + +set(INC_SYS ../../extern/Eigen3 ) @@ -42,5 +45,5 @@ set(SRC dualcon.h ) -blender_add_lib(bf_intern_dualcon "${SRC}" "${INC}" "") +blender_add_lib(bf_intern_dualcon "${SRC}" "${INC}" "${INC_SYS}") diff --git a/intern/dualcon/intern/Projections.cpp b/intern/dualcon/intern/Projections.cpp index 2a52cc9972a..f00d998591f 100644 --- a/intern/dualcon/intern/Projections.cpp +++ b/intern/dualcon/intern/Projections.cpp @@ -92,12 +92,12 @@ static void crossProduct(double res[3], const double a[3], const double b[3]) /** * Method to perform dot product */ -int64_t dotProduct(const int64_t a[3], const int64_t b[3]) +static int64_t dotProduct(const int64_t a[3], const int64_t b[3]) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; } -void normalize(double a[3]) +static void normalize(double a[3]) { double mag = a[0] * a[0] + a[1] * a[1] + a[2] * a[2]; if (mag > 0) { diff --git a/intern/dualcon/intern/dualcon_c_api.cpp b/intern/dualcon/intern/dualcon_c_api.cpp index 894ab6b0873..c96415bfb54 100644 --- a/intern/dualcon/intern/dualcon_c_api.cpp +++ b/intern/dualcon/intern/dualcon_c_api.cpp @@ -32,7 +32,7 @@ #define isnan(n) _isnan(n) #endif -void veccopy(float dst[3], const float src[3]) +static void veccopy(float dst[3], const float src[3]) { dst[0] = src[0]; dst[1] = src[1]; diff --git a/intern/dualcon/intern/octree.cpp b/intern/dualcon/intern/octree.cpp index 9f44e7bbfdf..49c50c8240d 100644 --- a/intern/dualcon/intern/octree.cpp +++ b/intern/dualcon/intern/octree.cpp @@ -345,11 +345,13 @@ void Octree::addTriangle(Triangle *trian, int triind) delete proj; } -void print_depth(int height, int maxDepth) +#if 0 +static void print_depth(int height, int maxDepth) { for (int i = 0; i < maxDepth - height; i++) printf(" "); } +#endif InternalNode *Octree::addTriangle(InternalNode *node, CubeTriangleIsect *p, int height) { @@ -382,22 +384,22 @@ InternalNode *Octree::addTriangle(InternalNode *node, CubeTriangleIsect *p, int /* Pruning using intersection test */ if (subp->isIntersecting()) { - if (!hasChild(node, i)) { + if (!node->has_child(i)) { if (height == 1) node = addLeafChild(node, i, count, createLeaf(0)); else node = addInternalChild(node, i, count, createInternal(0)); } - Node *chd = getChild(node, count); + Node *chd = node->get_child(count); if (node->is_child_leaf(i)) - setChild(node, count, (Node *)updateCell(&chd->leaf, subp)); + node->set_child(count, (Node *)updateCell(&chd->leaf, subp)); else - setChild(node, count, (Node *)addTriangle(&chd->internal, subp, height - 1)); + node->set_child(count, (Node *)addTriangle(&chd->internal, subp, height - 1)); } } - if (hasChild(node, i)) + if (node->has_child(i)) count++; } @@ -448,11 +450,11 @@ void Octree::preparePrimalEdgesMask(InternalNode *node) { int count = 0; for (int i = 0; i < 8; i++) { - if (hasChild(node, i)) { + if (node->has_child(i)) { if (node->is_child_leaf(i)) - createPrimalEdgesMask(&getChild(node, count)->leaf); + createPrimalEdgesMask(&node->get_child(count)->leaf); else - preparePrimalEdgesMask(&getChild(node, count)->internal); + preparePrimalEdgesMask(&node->get_child(count)->internal); count++; } @@ -485,7 +487,7 @@ Node *Octree::trace(Node *newnode, int *st, int len, int depth, PathList *& path // Get children paths int chdleaf[8]; - fillChildren(&newnode->internal, chd, chdleaf); + newnode->internal.fill_children(chd, chdleaf); // int count = 0; for (i = 0; i < 8; i++) { @@ -508,7 +510,7 @@ Node *Octree::trace(Node *newnode, int *st, int len, int depth, PathList *& path int df[2] = {depth - 1, depth - 1}; int *nstf[2]; - fillChildren(&newnode->internal, chd, chdleaf); + newnode->internal.fill_children(chd, chdleaf); for (i = 0; i < 12; i++) { int c[2] = {cellProcFaceMask[i][0], cellProcFaceMask[i][1]}; @@ -588,7 +590,7 @@ void Octree::findPaths(Node *node[2], int leaf[2], int depth[2], int *st[2], int for (j = 0; j < 2; j++) { if (!leaf[j]) { - fillChildren(&node[j]->internal, chd[j], chdleaf[j]); + node[j]->internal.fill_children(chd[j], chdleaf[j]); int len = (dimen >> (maxDepth - depth[j] + 1)); for (i = 0; i < 8; i++) { @@ -964,10 +966,10 @@ Node *Octree::patch(Node *newnode, int st[3], int len, PathList *rings) st[1] + len * vertmap[i][1], st[2] + len * vertmap[i][2] }; - patch(getChild(&newnode->internal, count), nori, len, zlists[i]); + patch(newnode->internal.get_child(count), nori, len, zlists[i]); } - if (hasChild(&newnode->internal, i)) { + if (newnode->internal.has_child(i)) { count++; } } @@ -1406,16 +1408,16 @@ Node *Octree::locateCell(InternalNode *node, int st[3], int len, int ori[3], int rst[1] = st[1] + vertmap[ind][1] * len; rst[2] = st[2] + vertmap[ind][2] * len; - if (hasChild(node, ind)) { - int count = getChildCount(node, ind); - Node *chd = getChild(node, count); + if (node->has_child(ind)) { + int count = node->get_child_count(ind); + Node *chd = node->get_child(count); if (node->is_child_leaf(ind)) { rleaf = chd; rlen = len; } else { // Recur - setChild(node, count, locateCell(&chd->internal, rst, len, ori, dir, side, rleaf, rst, rlen)); + node->set_child(count, locateCell(&chd->internal, rst, len, ori, dir, side, rleaf, rst, rlen)); } } else { @@ -1722,7 +1724,7 @@ void Octree::buildSigns(unsigned char table[], Node *node, int isLeaf, int sg, i // Internal node Node *chd[8]; int leaf[8]; - fillChildren(&node->internal, chd, leaf); + node->internal.fill_children(chd, leaf); // Get the signs at the corners of the first cube rvalue[0] = sg; @@ -1782,8 +1784,8 @@ void Octree::clearProcessBits(Node *node, int height) // Internal cell, recur int count = 0; for (i = 0; i < 8; i++) { - if (hasChild(&node->internal, i)) { - clearProcessBits(getChild(&node->internal, count), height - 1); + if (node->internal.has_child(i)) { + clearProcessBits(node->internal.get_child(count), height - 1); count++; } } @@ -2014,13 +2016,13 @@ int Octree::floodFill(Node *node, int st[3], int len, int height, int threshold) int count = 0; len >>= 1; for (i = 0; i < 8; i++) { - if (hasChild((InternalNode *)node, i)) { + if (node->internal.has_child(i)) { int nst[3]; nst[0] = st[0] + vertmap[i][0] * len; nst[1] = st[1] + vertmap[i][1] * len; nst[2] = st[2] + vertmap[i][2] * len; - int d = floodFill(getChild((InternalNode *)node, count), nst, len, height - 1, threshold); + int d = floodFill(node->internal.get_child(count), nst, len, height - 1, threshold); if (d > maxtotal) { maxtotal = d; } @@ -2060,9 +2062,9 @@ void Octree::writeOut() void Octree::countIntersection(Node *node, int height, int& nedge, int& ncell, int& nface) { if (height > 0) { - int total = getNumChildren(&node->internal); + int total = node->internal.get_num_children(); for (int i = 0; i < total; i++) { - countIntersection(getChild(&node->internal, i), height - 1, nedge, ncell, nface); + countIntersection(node->internal.get_child(i), height - 1, nedge, ncell, nface); } } else { @@ -2108,8 +2110,8 @@ void pseudoInverse(const _Matrix_Type_ &a, svd.matrixU().adjoint(); } -void solve_least_squares(const float halfA[], const float b[], - const float midpoint[], float rvalue[]) +static void solve_least_squares(const float halfA[], const float b[], + const float midpoint[], float rvalue[]) { /* calculate pseudo-inverse */ Eigen::MatrixXf A(3, 3), pinv(3, 3); @@ -2126,8 +2128,32 @@ void solve_least_squares(const float halfA[], const float b[], rvalue[i] = result(i); } -void minimize(float rvalue[3], float mp[3], const float pts[12][3], - const float norms[12][3], const int parity[12]) +static void mass_point(float mp[3], const float pts[12][3], const int parity[12]) +{ + int ec = 0; + + for (int i = 0; i < 12; i++) { + if (parity[i]) { + const float *p = pts[i]; + + mp[0] += p[0]; + mp[1] += p[1]; + mp[2] += p[2]; + + ec++; + } + } + + if (ec == 0) { + return; + } + mp[0] /= ec; + mp[1] /= ec; + mp[2] /= ec; +} + +static void minimize(float rvalue[3], float mp[3], const float pts[12][3], + const float norms[12][3], const int parity[12]) { float ata[6] = {0, 0, 0, 0, 0, 0}; float atb[3] = {0, 0, 0}; @@ -2173,34 +2199,51 @@ void minimize(float rvalue[3], float mp[3], const float pts[12][3], solve_least_squares(ata, atb, mp, rvalue); } -void Octree::computeMinimizer(LeafNode *leaf, int st[3], int len, float rvalue[3]) +void Octree::computeMinimizer(const LeafNode *leaf, int st[3], int len, + float rvalue[3]) const { // First, gather all edge intersections float pts[12][3], norms[12][3]; int parity[12]; fillEdgeIntersections(leaf, st, len, pts, norms, parity); - // Next, construct QEF and minimizer - float mp[3] = {0, 0, 0}; - minimize(rvalue, mp, pts, norms, parity); - - /* Restraining the location of the minimizer */ - float nh1 = hermite_num * len; - float nh2 = (1 + hermite_num) * len; - if ((mode == DUALCON_MASS_POINT || mode == DUALCON_CENTROID) || - (rvalue[0] < st[0] - nh1 || rvalue[1] < st[1] - nh1 || rvalue[2] < st[2] - nh1 || - rvalue[0] > st[0] + nh2 || rvalue[1] > st[1] + nh2 || rvalue[2] > st[2] + nh2)) { - if (mode == DUALCON_CENTROID) { - // Use centroids + switch (mode) { + case DUALCON_CENTROID: rvalue[0] = (float) st[0] + len / 2; rvalue[1] = (float) st[1] + len / 2; rvalue[2] = (float) st[2] + len / 2; - } - else { - // Use mass point instead - rvalue[0] = mp[0]; - rvalue[1] = mp[1]; - rvalue[2] = mp[2]; + break; + + case DUALCON_MASS_POINT: + rvalue[0] = rvalue[1] = rvalue[2] = 0; + mass_point(rvalue, pts, parity); + break; + + default: { + // Sharp features */ + + // construct QEF and minimizer + float mp[3] = {0, 0, 0}; + minimize(rvalue, mp, pts, norms, parity); + + /* Restraining the location of the minimizer */ + float nh1 = hermite_num * len; + float nh2 = (1 + hermite_num) * len; + + if (rvalue[0] < st[0] - nh1 || + rvalue[1] < st[1] - nh1 || + rvalue[2] < st[2] - nh1 || + + rvalue[0] > st[0] + nh2 || + rvalue[1] > st[1] + nh2 || + rvalue[2] > st[2] + nh2) + { + // Use mass point instead + rvalue[0] = mp[0]; + rvalue[1] = mp[1]; + rvalue[2] = mp[2]; + } + break; } } } @@ -2251,13 +2294,13 @@ void Octree::generateMinimizer(Node *node, int st[3], int len, int height, int& int count = 0; len >>= 1; for (i = 0; i < 8; i++) { - if (hasChild(&node->internal, i)) { + if (node->internal.has_child(i)) { int nst[3]; nst[0] = st[0] + vertmap[i][0] * len; nst[1] = st[1] + vertmap[i][1] * len; nst[2] = st[2] + vertmap[i][2] * len; - generateMinimizer(getChild(&node->internal, count), + generateMinimizer(node->internal.get_child(count), nst, len, height - 1, offset); count++; } @@ -2342,9 +2385,9 @@ void Octree::edgeProcContour(Node *node[4], int leaf[4], int depth[4], int maxde Node *chd[4][8]; for (j = 0; j < 4; j++) { for (i = 0; i < 8; i++) { - chd[j][i] = ((!leaf[j]) && hasChild(&node[j]->internal, i)) ? - getChild(&node[j]->internal, - getChildCount(&node[j]->internal, i)) : NULL; + chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ? + node[j]->internal.get_child( + node[j]->internal.get_child_count(i)) : NULL; } } @@ -2389,9 +2432,9 @@ void Octree::faceProcContour(Node *node[2], int leaf[2], int depth[2], int maxde Node *chd[2][8]; for (j = 0; j < 2; j++) { for (i = 0; i < 8; i++) { - chd[j][i] = ((!leaf[j]) && hasChild(&node[j]->internal, i)) ? - getChild(&node[j]->internal, - getChildCount(&node[j]->internal, i)) : NULL; + chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ? + node[j]->internal.get_child( + node[j]->internal.get_child_count(i)) : NULL; } } @@ -2458,9 +2501,8 @@ void Octree::cellProcContour(Node *node, int leaf, int depth) // Fill children nodes Node *chd[8]; for (i = 0; i < 8; i++) { - chd[i] = ((!leaf) && hasChild(&node->internal, i)) ? - getChild(&node->internal, - getChildCount(&node->internal, i)) : NULL; + chd[i] = ((!leaf) && node->internal.has_child(i)) ? + node->internal.get_child(node->internal.get_child_count(i)) : NULL; } // 8 Cell calls @@ -2537,8 +2579,8 @@ void Octree::edgeProcParity(Node *node[4], int leaf[4], int depth[4], int maxdep Node *chd[4][8]; for (j = 0; j < 4; j++) { for (i = 0; i < 8; i++) { - chd[j][i] = ((!leaf[j]) && hasChild(&node[j]->internal, i)) ? - getChild(&node[j]->internal, getChildCount(&node[j]->internal, i)) : NULL; + chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ? + node[j]->internal.get_child( node[j]->internal.get_child_count(i)) : NULL; } } @@ -2587,9 +2629,9 @@ void Octree::faceProcParity(Node *node[2], int leaf[2], int depth[2], int maxdep Node *chd[2][8]; for (j = 0; j < 2; j++) { for (i = 0; i < 8; i++) { - chd[j][i] = ((!leaf[j]) && hasChild(&node[j]->internal, i)) ? - getChild(&node[j]->internal, - getChildCount(&node[j]->internal, i)) : NULL; + chd[j][i] = ((!leaf[j]) && node[j]->internal.has_child(i)) ? + node[j]->internal.get_child( + node[j]->internal.get_child_count(i)) : NULL; } } @@ -2656,9 +2698,8 @@ void Octree::cellProcParity(Node *node, int leaf, int depth) // Fill children nodes Node *chd[8]; for (i = 0; i < 8; i++) { - chd[i] = ((!leaf) && hasChild((InternalNode *)node, i)) ? - getChild((InternalNode *)node, - getChildCount((InternalNode *)node, i)) : NULL; + chd[i] = ((!leaf) && node->internal.has_child(i)) ? + node->internal.get_child(node->internal.get_child_count(i)) : NULL; } // 8 Cell calls @@ -2801,3 +2842,7 @@ const int dirEdge[3][4] = { {7, 6, 5, 4}, {11, 10, 9, 8} }; + +int InternalNode::numChildrenTable[256]; +int InternalNode::childrenCountTable[256][8]; +int InternalNode::childrenIndexTable[256][8]; diff --git a/intern/dualcon/intern/octree.h b/intern/dualcon/intern/octree.h index 550d584baa7..6cbdc9fb3d8 100644 --- a/intern/dualcon/intern/octree.h +++ b/intern/dualcon/intern/octree.h @@ -56,12 +56,18 @@ #define EDGE_FLOATS 4 union Node; +struct LeafNode; struct InternalNode { - /* Treat as bitfield, bit N indicates whether child N exists or not */ - unsigned char has_child; - /* Treat as bitfield, bit N indicates whether child N is a leaf or not */ - unsigned char child_is_leaf; + /* Initialized in Octree::BuildTable */ + static int numChildrenTable[256]; + static int childrenCountTable[256][8]; + static int childrenIndexTable[256][8]; + + /* Bit N indicates whether child N exists or not */ + unsigned char has_child_bitfield; + /* Bit N indicates whether child N is a leaf or not */ + unsigned char child_is_leaf_bitfield; /* Can have up to eight children */ Node *children[0]; @@ -69,7 +75,78 @@ struct InternalNode { /// Test if child is leaf int is_child_leaf(int index) const { - return (child_is_leaf >> index) & 1; + return (child_is_leaf_bitfield >> index) & 1; + } + + /// If child index exists + int has_child(int index) const + { + return (has_child_bitfield >> index) & 1; + } + + /// Get the pointer to child index + Node *get_child(int count) + { + return children[count]; + } + + const Node *get_child(int count) const + { + return children[count]; + } + + /// Get total number of children + int get_num_children() const + { + return numChildrenTable[has_child_bitfield]; + } + + /// Get the count of children + int get_child_count(int index) const + { + return childrenCountTable[has_child_bitfield][index]; + } + int get_child_index(int count) + { + return childrenIndexTable[has_child_bitfield][count]; + } + const int *get_child_counts() const + { + return childrenCountTable[has_child_bitfield]; + } + + /// Get all children + void fill_children(Node *children[8], int leaf[8]) + { + int count = 0; + for (int i = 0; i < 8; i++) { + leaf[i] = is_child_leaf(i); + if (has_child(i)) { + children[i] = get_child(count); + count++; + } + else { + children[i] = NULL; + leaf[i] = 0; + } + } + } + + /// Sets the child pointer + void set_child(int count, Node *chd) + { + children[count] = chd; + } + void set_internal_child(int index, int count, InternalNode *chd) + { + set_child(count, (Node *)chd); + has_child_bitfield |= (1 << index); + } + void set_leaf_child(int index, int count, LeafNode *chd) + { + set_child(count, (Node *)chd); + has_child_bitfield |= (1 << index); + child_is_leaf_bitfield |= (1 << index); } }; @@ -345,7 +422,8 @@ class Octree void countIntersection(Node *node, int height, int& nedge, int& ncell, int& nface); void generateMinimizer(Node * node, int st[3], int len, int height, int& offset); - void computeMinimizer(LeafNode * leaf, int st[3], int len, float rvalue[3]); + void computeMinimizer(const LeafNode * leaf, int st[3], int len, + float rvalue[3]) const; /** * Traversal functions to generate polygon model * op: 0 for counting, 1 for writing OBJ, 2 for writing OFF, 3 for writing PLY @@ -365,9 +443,6 @@ class Octree /************ Operators for all nodes ************/ /// Lookup table - int numChildrenTable[256]; - int childrenCountTable[256][8]; - int childrenIndexTable[256][8]; int numEdgeTable[8]; int edgeCountTable[8][3]; @@ -375,12 +450,12 @@ class Octree void buildTable() { for (int i = 0; i < 256; i++) { - numChildrenTable[i] = 0; + InternalNode::numChildrenTable[i] = 0; int count = 0; for (int j = 0; j < 8; j++) { - numChildrenTable[i] += ((i >> j) & 1); - childrenCountTable[i][j] = count; - childrenIndexTable[i][count] = j; + InternalNode::numChildrenTable[i] += ((i >> j) & 1); + InternalNode::childrenCountTable[i][j] = count; + InternalNode::childrenIndexTable[i][count] = j; count += ((i >> j) & 1); } } @@ -402,15 +477,15 @@ class Octree return getSign(&node->leaf, index); } else { - if (hasChild(&node->internal, index)) { - return getSign(getChild(&node->internal, getChildCount(&node->internal, index)), + if (node->internal.has_child(index)) { + return getSign(node->internal.get_child(node->internal.get_child_count(index)), height - 1, index); } else { - return getSign(getChild(&node->internal, 0), + return getSign(node->internal.get_child(0), height - 1, - 7 - getChildIndex(&node->internal, 0)); + 7 - node->internal.get_child_index(0)); } } } @@ -469,7 +544,7 @@ class Octree leaf->signs |= ((sign & 1) << index); } - int getSignMask(const LeafNode *leaf) + int getSignMask(const LeafNode *leaf) const { return leaf->signs; } @@ -536,7 +611,7 @@ class Octree } /// Get edge parity - int getEdgeParity(LeafNode *leaf, int index) + int getEdgeParity(const LeafNode *leaf, int index) const { assert(index >= 0 && index <= 11); @@ -597,7 +672,8 @@ class Octree leaf->primary_edge_intersections |= (1 << pindex); } - int getStoredEdgesParity(LeafNode *leaf, int pindex) + + int getStoredEdgesParity(const LeafNode *leaf, int pindex) const { assert(pindex <= 2 && pindex >= 0); @@ -652,7 +728,7 @@ class Octree InternalNode *parent = locateParent(node, len, st, count); // Update - setChild(parent, count, (Node *)leaf); + parent->set_child(count, (Node *)leaf); } void updateParent(InternalNode *node, int len, int st[3]) @@ -667,14 +743,14 @@ class Octree InternalNode *parent = locateParent(len, st, count); // UPdate - setChild(parent, count, (Node *)node); + parent->set_child(count, (Node *)node); } /// Find edge intersection on a given edge - int getEdgeIntersectionByIndex(int st[3], int index, float pt[3], int check) + int getEdgeIntersectionByIndex(int st[3], int index, float pt[3], int check) const { // First, locat the leaf - LeafNode *leaf; + const LeafNode *leaf; if (check) { leaf = locateLeafCheck(st); } @@ -697,7 +773,7 @@ class Octree } /// Retrieve number of edges intersected - int getPrimalEdgesMask(LeafNode *leaf) + int getPrimalEdgesMask(const LeafNode *leaf) const { return leaf->primary_edge_intersections; } @@ -710,7 +786,7 @@ class Octree } /// Get the count for a primary edge - int getEdgeCount(LeafNode *leaf, int index) + int getEdgeCount(const LeafNode *leaf, int index) const { return edgeCountTable[getPrimalEdgesMask(leaf)][index]; } @@ -744,7 +820,7 @@ class Octree } /// Retrieve edge intersection - float getEdgeOffset(LeafNode *leaf, int count) + float getEdgeOffset(const LeafNode *leaf, int count) const { return leaf->edge_intersections[4 * count]; } @@ -834,10 +910,11 @@ class Octree } /// Retrieve complete edge intersection - void getEdgeIntersectionByIndex(LeafNode *leaf, int index, int st[3], int len, float pt[3], float nm[3]) + void getEdgeIntersectionByIndex(const LeafNode *leaf, int index, int st[3], + int len, float pt[3], float nm[3]) const { int count = getEdgeCount(leaf, index); - float *pts = leaf->edge_intersections; + const float *pts = leaf->edge_intersections; float off = pts[4 * count]; @@ -865,7 +942,8 @@ class Octree return off; } - void fillEdgeIntersections(LeafNode *leaf, int st[3], int len, float pts[12][3], float norms[12][3]) + void fillEdgeIntersections(const LeafNode *leaf, int st[3], int len, + float pts[12][3], float norms[12][3]) const { int i; // int stt[3] = {0, 0, 0}; @@ -890,7 +968,7 @@ class Octree nst[i] += len; // int nstt[3] = {0, 0, 0}; // nstt[i] += 1; - LeafNode *node = locateLeaf(nst); + const LeafNode *node = locateLeaf(nst); if (e1) { // getEdgeIntersectionByIndex(node, femask[i][0], nstt, 1, pts[fmask[i][0]], norms[fmask[i][0]]); @@ -912,7 +990,7 @@ class Octree nst[i] -= len; // int nstt[3] = {1, 1, 1}; // nstt[i] -= 1; - LeafNode *node = locateLeaf(nst); + const LeafNode *node = locateLeaf(nst); // getEdgeIntersectionByIndex(node, eemask[i], nstt, 1, pts[emask[i]], norms[emask[i]]); getEdgeIntersectionByIndex(node, eemask[i], nst, len, pts[emask[i]], norms[emask[i]]); @@ -921,7 +999,9 @@ class Octree } - void fillEdgeIntersections(LeafNode *leaf, int st[3], int len, float pts[12][3], float norms[12][3], int parity[12]) + void fillEdgeIntersections(const LeafNode *leaf, int st[3], int len, + float pts[12][3], float norms[12][3], + int parity[12]) const { int i; for (i = 0; i < 12; i++) { @@ -948,7 +1028,7 @@ class Octree nst[i] += len; // int nstt[3] = {0, 0, 0}; // nstt[i] += 1; - LeafNode *node = locateLeafCheck(nst); + const LeafNode *node = locateLeafCheck(nst); if (node == NULL) { continue; } @@ -979,7 +1059,7 @@ class Octree nst[i] -= len; // int nstt[3] = {1, 1, 1}; // nstt[i] -= 1; - LeafNode *node = locateLeafCheck(nst); + const LeafNode *node = locateLeafCheck(nst); if (node == NULL) { continue; } @@ -1088,7 +1168,20 @@ class Octree int index = (((st[0] >> i) & 1) << 2) | (((st[1] >> i) & 1) << 1) | (((st[2] >> i) & 1)); - node = getChild(&node->internal, getChildCount(&node->internal, index)); + node = node->internal.get_child(node->internal.get_child_count(index)); + } + + return &node->leaf; + } + + const LeafNode *locateLeaf(int st[3]) const + { + const Node *node = root; + for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) { + int index = (((st[0] >> i) & 1) << 2) | + (((st[1] >> i) & 1) << 1) | + (((st[2] >> i) & 1)); + node = node->internal.get_child(node->internal.get_child_count(index)); } return &node->leaf; @@ -1102,8 +1195,7 @@ class Octree index = (((st[0] & i) ? 4 : 0) | ((st[1] & i) ? 2 : 0) | ((st[2] & i) ? 1 : 0)); - node = getChild(&node->internal, - getChildCount(&node->internal, index)); + node = node->internal.get_child(node->internal.get_child_count(index)); } return &node->leaf; @@ -1116,10 +1208,26 @@ class Octree int index = (((st[0] >> i) & 1) << 2) | (((st[1] >> i) & 1) << 1) | (((st[2] >> i) & 1)); - if (!hasChild(&node->internal, index)) { + if (!node->internal.has_child(index)) { return NULL; } - node = getChild(&node->internal, getChildCount(&node->internal, index)); + node = node->internal.get_child(node->internal.get_child_count(index)); + } + + return &node->leaf; + } + + const LeafNode *locateLeafCheck(int st[3]) const + { + const Node *node = root; + for (int i = GRID_DIMENSION - 1; i > GRID_DIMENSION - maxDepth - 1; i--) { + int index = (((st[0] >> i) & 1) << 2) | + (((st[1] >> i) & 1) << 1) | + (((st[2] >> i) & 1)); + if (!node->internal.has_child(index)) { + return NULL; + } + node = node->internal.get_child(node->internal.get_child_count(index)); } return &node->leaf; @@ -1135,10 +1243,10 @@ class Octree ((st[1] & i) ? 2 : 0) | ((st[2] & i) ? 1 : 0)); pre = node; - node = &getChild(node, getChildCount(node, index))->internal; + node = &node->get_child(node->get_child_count(index))->internal; } - count = getChildCount(pre, index); + count = pre->get_child_count(index); return pre; } @@ -1152,88 +1260,21 @@ class Octree ((st[1] & i) ? 2 : 0) | ((st[2] & i) ? 1 : 0)); pre = node; - node = (InternalNode *)getChild(node, getChildCount(node, index)); + node = &node->get_child(node->get_child_count(index))->internal; } - count = getChildCount(pre, index); + count = pre->get_child_count(index); return pre; } /************ Operators for internal nodes ************/ - /// If child index exists - int hasChild(InternalNode *node, int index) - { - return (node->has_child >> index) & 1; - } - - /// Get the pointer to child index - Node *getChild(InternalNode *node, int count) - { - return node->children[count]; - }; - - /// Get total number of children - int getNumChildren(InternalNode *node) - { - return numChildrenTable[node->has_child]; - } - - /// Get the count of children - int getChildCount(InternalNode *node, int index) - { - return childrenCountTable[node->has_child][index]; - } - int getChildIndex(InternalNode *node, int count) - { - return childrenIndexTable[node->has_child][count]; - } - int *getChildCounts(InternalNode *node) - { - return childrenCountTable[node->has_child]; - } - - /// Get all children - void fillChildren(InternalNode *node, Node *children[8], int leaf[8]) - { - int count = 0; - for (int i = 0; i < 8; i++) { - leaf[i] = node->is_child_leaf(i); - if (hasChild(node, i)) { - children[i] = getChild(node, count); - count++; - } - else { - children[i] = NULL; - leaf[i] = 0; - } - } - } - - /// Sets the child pointer - void setChild(InternalNode *node, int count, Node *chd) - { - node->children[count] = chd; - } - void setInternalChild(InternalNode *node, int index, int count, InternalNode *chd) - { - setChild(node, count, (Node *)chd); - node->has_child |= (1 << index); - } - void setLeafChild(InternalNode *node, int index, int count, LeafNode *chd) - { - setChild(node, count, (Node *)chd); - node->has_child |= (1 << index); - node->child_is_leaf |= (1 << index); - } /// Add a kid to an existing internal node - /// Fix me: can we do this without wasting memory ? - /// Fixed: using variable memory InternalNode *addChild(InternalNode *node, int index, Node *child, int aLeaf) { // Create new internal node - int num = getNumChildren(node); + int num = node->get_num_children(); InternalNode *rnode = createInternal(num + 1); // Establish children @@ -1242,19 +1283,19 @@ class Octree for (i = 0; i < 8; i++) { if (i == index) { if (aLeaf) { - setLeafChild(rnode, i, count2, &child->leaf); + rnode->set_leaf_child(i, count2, &child->leaf); } else { - setInternalChild(rnode, i, count2, &child->internal); + rnode->set_internal_child(i, count2, &child->internal); } count2++; } - else if (hasChild(node, i)) { + else if (node->has_child(i)) { if (node->is_child_leaf(i)) { - setLeafChild(rnode, i, count2, &getChild(node, count1)->leaf); + rnode->set_leaf_child(i, count2, &node->get_child(count1)->leaf); } else { - setInternalChild(rnode, i, count2, &getChild(node, count1)->internal); + rnode->set_internal_child(i, count2, &node->get_child(count1)->internal); } count1++; count2++; @@ -1269,8 +1310,8 @@ class Octree InternalNode *createInternal(int length) { InternalNode *inode = (InternalNode *)alloc[length]->allocate(); - inode->has_child = 0; - inode->child_is_leaf = 0; + inode->has_child_bitfield = 0; + inode->child_is_leaf_bitfield = 0; return inode; } @@ -1301,21 +1342,21 @@ class Octree InternalNode *addLeafChild(InternalNode *par, int index, int count, LeafNode *leaf) { - int num = getNumChildren(par) + 1; + int num = par->get_num_children() + 1; InternalNode *npar = createInternal(num); *npar = *par; if (num == 1) { - setLeafChild(npar, index, 0, leaf); + npar->set_leaf_child(index, 0, leaf); } else { int i; for (i = 0; i < count; i++) { - setChild(npar, i, getChild(par, i)); + npar->set_child(i, par->get_child(i)); } - setLeafChild(npar, index, count, leaf); + npar->set_leaf_child(index, count, leaf); for (i = count + 1; i < num; i++) { - setChild(npar, i, getChild(par, i - 1)); + npar->set_child(i, par->get_child(i - 1)); } } @@ -1326,21 +1367,21 @@ class Octree InternalNode *addInternalChild(InternalNode *par, int index, int count, InternalNode *node) { - int num = getNumChildren(par) + 1; + int num = par->get_num_children() + 1; InternalNode *npar = createInternal(num); *npar = *par; if (num == 1) { - setInternalChild(npar, index, 0, node); + npar->set_internal_child(index, 0, node); } else { int i; for (i = 0; i < count; i++) { - setChild(npar, i, getChild(par, i)); + npar->set_child(i, par->get_child(i)); } - setInternalChild(npar, index, count, node); + npar->set_internal_child(index, count, node); for (i = count + 1; i < num; i++) { - setChild(npar, i, getChild(par, i - 1)); + npar->set_child(i, par->get_child(i - 1)); } } diff --git a/intern/elbeem/intern/ntl_geometryshader.h b/intern/elbeem/intern/ntl_geometryshader.h index 61598556b7e..f43df6539e6 100644 --- a/intern/elbeem/intern/ntl_geometryshader.h +++ b/intern/elbeem/intern/ntl_geometryshader.h @@ -46,7 +46,7 @@ class ntlGeometryShader : /*! notify object that dump is in progress (e.g. for field dump) */ virtual void notifyShaderOfDump(int dumptype, int frameNr,char *frameNrStr,string outfilename) = 0; - /*! get ouput filename, returns global render outfile if empty */ + /*! get output filename, returns global render outfile if empty */ string getOutFilename( void ) { return mOutFilename; } protected: diff --git a/intern/elbeem/intern/utilities.cpp b/intern/elbeem/intern/utilities.cpp index c912e70b281..2b9b8d5b8a5 100644 --- a/intern/elbeem/intern/utilities.cpp +++ b/intern/elbeem/intern/utilities.cpp @@ -51,7 +51,7 @@ int getElbeemState(void) { return gElbeemState; } int isSimworldOk(void) { - return (getElbeemState>=0); + return (getElbeemState() >=0); } // last error as string, acces with get/setElbeemErrorString diff --git a/intern/ffmpeg/ffmpeg_compat.h b/intern/ffmpeg/ffmpeg_compat.h index 2fd61570011..37cde2c2837 100644 --- a/intern/ffmpeg/ffmpeg_compat.h +++ b/intern/ffmpeg/ffmpeg_compat.h @@ -110,7 +110,7 @@ void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp) #endif /* there are some version inbetween, which have avio_... functions but no - AVIO_FLAG_... */ + * AVIO_FLAG_... */ #ifndef AVIO_FLAG_WRITE #define AVIO_FLAG_WRITE URL_WRONLY #endif diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index ae30458a5e5..87ab3c013c6 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -387,11 +387,12 @@ extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle, * \param windowhandle The handle to the window * \param mode The new grab state of the cursor. * \param bounds The grab ragion (optional) - left,top,right,bottom + * \param mouse_ungrab_xy XY for new mouse location (optional) - x,y * \return Indication of success. */ extern GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle, GHOST_TGrabCursorMode mode, - int *bounds); + int bounds[4], int mouse_ungrab_xy[2]); /*************************************************************************************** * Access to mouse button and keyboard states. diff --git a/intern/ghost/GHOST_IEventConsumer.h b/intern/ghost/GHOST_IEventConsumer.h index 5682d04d434..5b6fa7ba046 100644 --- a/intern/ghost/GHOST_IEventConsumer.h +++ b/intern/ghost/GHOST_IEventConsumer.h @@ -42,8 +42,8 @@ * they want to receive events. The system will call the processEvent() method * for every installed event consumer to pass events. * \see GHOST_ISystem#addEventConsumer - * \author Maarten Gribnau - * \date May 14, 2001 + * \author Maarten Gribnau + * \date May 14, 2001 */ class GHOST_IEventConsumer { @@ -58,15 +58,14 @@ public: /** * This method is called by the system when it has events to dispatch. * \see GHOST_ISystem#dispatchEvents - * \param event The event that can be handled or ignored. - * \return Indication as to whether the event was handled. + * \param event The event that can be handled or ignored. + * \return Indication as to whether the event was handled. */ virtual bool processEvent(GHOST_IEvent *event) = 0; - + #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IEventConsumer") #endif }; -#endif // _GHOST_EVENT_CONSUMER_H_ - +#endif /* __GHOST_IEVENTCONSUMER_H__ */ diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 8aef81bb762..ad5d2379787 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -47,14 +47,14 @@ class GHOST_IEventConsumer; * \section intro Introduction * * GHOST is yet another acronym. It stands for "Generic Handy Operating System - * Toolkit". It has been created to replace the OpenGL utility tool kit + * Toolkit". It has been created to replace the OpenGL utility tool kit * GLUT. * GLUT was used in Blender until the * point that Blender needed to be ported to Apple's Mac OSX. Blender needed a * number of modifications in GLUT to work but the GLUT sources for OSX were * unavailable at the time. The decision was made to build our own replacement - * for GLUT. In those days, NaN Technologies BV was the company that developed - * Blender. + * for GLUT. In those days, NaN Technologies BV was the company that developed + * Blender. *

    * Enough history. What does GHOST have to offer?
    * In short: everything that Blender needed from GLUT to run on all it's supported @@ -96,7 +96,7 @@ class GHOST_IEventConsumer; *

+ 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